sane-backends-1.0.27/0000775000175000017500000000000013110600540011270 500000000000000sane-backends-1.0.27/README.solaris0000664000175000017500000001636112112021330013545 00000000000000This is a report on how to build SANE on Solaris/x86 using a USB scanner. See below for SCSI. Another report for SANE on OpenSolaris can be found here: http://ginfo.egim-mrs.fr/article.php3?id_article=44 From: Tomasz Orlinski To: sane-devel@lists.alioth.debian.org Subject: [sane-devel] USB scanners DO work on Solaris 10 x86 Date: Thu, 7 Oct 2004 20:26:50 +0200 I would like to inform you, that I have compiled SANE on Sun Solaris 10 x86 with built-in USB scanner support. It was possible, because Sun had prepared libusb library wrapper for Solaris 10. I know, that Solaris 10 Software Express Release 08/04 is required. I have done it in that way: LD_LIBRARY_PATH=/usr/sfw/lib:$LD_LIBRARY_PATH CFLAGS="-I/usr/sfw/include" CPPFLAGS="-I/usr/sfw/include" LDFLAGS="-L/usr/sfw/lib -R/usr/sfw/lib -lusb" export LD_LIBRARY_PATH CFLAGS CPPFLAGS LDFLAGS ./configure --prefix=/opt/sane --disable-fork-process make make install It was also required to add a generic USB kernel driver. I had to look for my scanner device name in output of prtconf -D -v command. My scanner is Plustek UT24 and the apropriate part of output looked like this: name='compatible' type=string items=8 value='usb7b3,17.100' + ... I had to remove the not used kernel driver rem_drv ugen And add it again: add_drv -i 'usb7b3,17.100' ugen Then, /opt/sane/bin/sane-find-scanner detected my scanner and everything worked fine. I to add " " signs around usb7b3,17.100 name in /etc/driver_aliases to have the scanner working after reboot. To compile this packages SUNWlibusb and SUNWlibusbugen were needed. I used Solaris Software Companion CD gcc 2.95.3 compiler and Sun's /usr/ccs/bin/ld linker. USB support DOES NOT work in Solaris 9 and earlier versions. I hope, that this information would be useful for other USB scanner users. From: Tomasz Orlinski To: sane-devel@lists.alioth.debian.org Subject: Re: [sane-devel] USB scanners DO work on Solaris 10 x86 Date: Fri, 8 Oct 2004 16:06:14 +0200 [...] Sun in Driver Development Kit v. 0.9 writes how to compile SANE, but it does not really work :) They write about compiling with gcc and give options for Sun Forte compiler (cc) and forget about attaching a kernel driver. But they write, that versions earlier than 1.0.14 cannot be used. They want also to build SANE with Posix threads enabled. So I think that can be true. Sun writes also, that Solaris Software Express release at least S10_62 is needed to use libusb. Release number can be checked in /etc/release. The newest version can be downloaded from www.sun.com/solaris for free. In my opinion it is important to be cautious when using scanner or just libusb on important Solaris machines (especially multi-processor ones), because unlike in other systems, Solaris kernel is fully preemtible, what means, that many instances of the same driver can ran simultanously - it's dangerous, when drivers are not perfect. And Solaris USB framework is absolutely new, so it can contain bugs. I tried to crash my Solaris using USB subsystem and SANE, I didn't manage to, but it doesn't mean, it's impossible. SANE frontends work without any problems with Xsun and GIMP included in Solaris Software Companion CD. --------------------------------------------------------------------------- The following text describes, how to use a SCSI scanner (2002-06-11). You need a generic SCSI driver to run SANE on Solaris. There are at least three such drivers: the scg driver by Joerg Schillig, the sg driver by Kevin Sheehan, and starting with Solaris 8 Sun's own sgen(7D) driver. NOTE: You should install the SCSI generic driver BEFORE you run `configure' in the sane directory---otherwise configure won't set up SANE to work with the generic scsi driver. *** scg driver The SCSI general driver scg is Copyright 1986-1995 Joerg Schilling, It is supplied binary in pkgadd(1m) format and is tested from Solaris 2.3 to Solaris 2.6 (sparc) and Solaris 2.3 to Solaris 2.5.1 (x86). It can be found in ftp://ftp.fokus.gmd.de/pub/unix/kernel/scg/ To install it on a SPARC do: cd /tmp get SCHILYscg.sparc.tar.Z uncompress SCHILYscg.sparc.tar.Z tar -xvf SCHILYscg.sparc.tar as root: pkgadd -d . NOTE: Be very careful with pkgadd as it does not check for the correct target architecture. Do not install drivers for x86 on sparc and vice versa. You will get a corrupt system otherwise. For Solaris on an x86 do: cd /tmp get SCHILYscg.i386.tar.Z uncompress SCHILYscg.i386.tar.Z tar -xvf SCHILYscg.i386.tar as root: pkgadd -d . Then do a reboot --r Once the system has rebooted, there should be a device node /dev/scgXX for each of your SCSI adapters (/dev/scg0 for the first adapter, /dev/scg1 for the second, and so on...) Because the device name specifies a SCSI adapter, you need to use a special device naming syntax so SANE can tell which device you want to talk to. If the device is at SCSI id 0, the character 'a' should be appended, character 'b' should be used for SCSI id 1, and so on (see also the Solaris section in sane-scsi(5)). E.g., to configure an HP scanner, configuration file /opt/local/etc/sane.d/hp.conf might contain: /dev/scg0c if the scanner has the SCSI target id 2 WARNING! Everybody who can read/write a generic SCSI device can do with all your disks whatever he/she wants. It takes only a few lines of code to send a FORMAT control block... Rather than giving users access to the SCSI adapter special device, it may be a better idea to install scanimage/xscanimage setgid to a special "scanner" group and then turn on write permission for the scanner group. *** sg driver Another solution to the permission problem is to use the generic SCSI driver sg by Kevin Sheehan. This driver is not free but uses separate device node for each SCSI target: /dev/sg/0, /dev/sg/1, ... This allows to control device access on a per-device basis. *** sgen driver The solaris 8 sgen driver must be configured before it can be used. See /kernel/drv/sgen.conf and the manual page sgen(7D). The minimal config includes defining the correct "device-type-config-list" property in /kernel/drv/sgen.conf. The typical SCSI device type for a scanner is either "scanner" or "processor". You can optionally restrict the devices sgen attaches to, by defining the "inquiry-config-list" property. You also have to uncomment the scanner's "target/lun" entry, so that the sgen driver is allowed to attach to the SCSI scanner hardware. After the configuration file /kernel/drv/sgen.conf is set up for the scanner, run the command "devfsadm -v -i sgen" to create sgen device nodes for the scanner. In case you need to rerun devfsadm to incorporate changes to the sgen.conf file, make sure the sgen driver is unloaded from the kernel before you re-run devfsadm. The driver is unloaded using the "modunload -i {id}" command; the {id} of the sgen driver can be determined with the modinfo command. The device nodes use names of the following form: /dev/scsi/device-type/cXtXdX Example: A HP Scanjet 4c (SCSI device type: "processor") on controller #1, target #6, lun #0 uses the device name /dev/scsi/processor/c1t6d0 /kernel/drv/sgen.conf contains: device-type-config-list="processor"; name="sgen" class="scsi" target=6 lun=0; If you have questions or problems with the Solaris support in SANE, send mail to: hu@garfield.m.isar.de sane-backends-1.0.27/config.sub0000775000175000017500000010724313110434403013205 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2017 Free Software Foundation, Inc. timestamp='2017-04-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | wasm32 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; nsx-tandem) basic_machine=nsx-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; wasm32) basic_machine=wasm32-unknown ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -ios) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; pru-*) os=-elf ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: sane-backends-1.0.27/doc/0000775000175000017500000000000013110600532012036 500000000000000sane-backends-1.0.27/doc/sane-coolscan.man0000664000175000017500000000572712775312262015233 00000000000000.TH sane\-coolscan 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-coolscan .SH NAME sane\-coolscan \- SANE backend for Nikon film-scanners .SH ABOUT THIS FILE This file is a short description of the coolscan-backend for sane! .SH DESCRIPTION The .B sane\-coolscan library implements a SANE backend that provides the interface to the following Nikon Coolscan Film scanners: Nikon LS20, LS30, LS1000, LS2000. .B Even though the backend has worked for a number of people, there are still some problems, especially in combination with some SCSI card/drivers (AHA-1505/aha152x.o) and the autofocus command. You should consider this backend 'alpha' and be careful when using it the first time. .SH CONFIGURATION The configuration file for this backend resides in .IR @CONFIGDIR@/coolscan.conf . Its contents is a list of device names that correspond to Nikon Coolscan scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .nf #scsi Vendor Model Type scsi Nikon * Scanner /dev/scanner .fi The special device name must be a generic SCSI device or a symlink to such a device. To find out to which device your scanner is assigned and how you have to set the permissions of that device, have a look at sane\-scsi. .SH SCSI ADAPTER TIPS Some SCSI-adapters and low-level SCSI drivers do not work correctly with this backend and the Coolscan scanners. These systems hang when the autofocus command is send to the Scanner. To see a list of which card/driver combinations work or don't work have a look at: http://andreas.rick.free.fr/sane/autofocus.html. .SH FILES .TP The backend configuration file: .I @CONFIGDIR@/coolscan.conf .TP The static library implementing this backend: .I @LIBDIR@/libsane\-coolscan.a .TP The shared library implementing this backend: .I @LIBDIR@/libsane\-coolscan.so (present on systems that support dynamic loading) .SH ENVIRONMENT .TP .B SANE_DEBUG_COOLSCAN If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity: SANE_DEBUG_COOLSCAN values Examples: on bash: .br export SANE_DEBUG_COOLSCAN=8 on csh: .br setenv SANE_DEBUG_COOLSCAN 8 .SH BUGS The autofocus command does not work with some SCSI card/driver combinations .PP The gamma table is not implemented for the LS1000 yet. .PP The dust-removal is not working yet .SH SEE ALSO .TP .I http://andreas.rick.free.fr/sane/ The homepage of this backend .TP .I http://www.sema.be/coolscan/ The original version of the coolscan backend by Didier .PP sane(7), sane\-scsi(5) .SH THANKS TO .PP Didier Carlier \- For writing the original Coolscan backend (without it I would not have started this) .PP Oliver Rauch \- For adapting xsane so quickly to the infrared stuff. .PP All the other people working on SANE. .SH AUTHOR Andreas Rick .SH EMAIL-CONTACT andreas.rick@free.fr sane-backends-1.0.27/doc/sane-sharp.man0000664000175000017500000003317512775277260014555 00000000000000.TH sane\-sharp 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-sharp .SH NAME sane\-sharp \- SANE backend for SHARP scanners .SH DESCRIPTION The .B sane\-sharp library implements a SANE (Scanner Access Now Easy) backend that provides access to Sharp SCSI scanners. This backend should be considered .B beta-quality software! In the current state it is known to work with JX-610 and JX-250 scanners. It is prepared for usage with the JX-330 series scanners, but we are not able to test it with these devices. .PP For other Sharp scanners, it may or may not work. .PP At present, the following scanners are known to work with this backend. .RS .PP .ft CR .nf Vendor Product id: ----- ----------- Sharp JX-610 Sharp JX-250 Sharp JX-320 Sharp JX-330 Sharp JX-350 .fi .ft R .RE .PP The following scanners are detected by the backend, but not tested: .PP .RS .ft CR .nf Vendor Product id: ----- ----------- Sharp JX-325 .fi .ft R .RE .SH DEVICE NAMES This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is either the path-name for the special device that corresponds to a SCSI scanner. The special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. See sane\-scsi(5) for details. .SH SCAN OPTIONS .B Scan Mode (parameter .B \-\-mode for scanimage). Possible settings: .RS .B Lineart (1 bit black & white scans), .br .B Gray (8 bit gray scale scans), .br .B Lineart Color (bi-level color scans), .br .B Color (8 bit RGB scans). .RE The default value is .B Color. .B Halftone Pattern (parameter .B \-\-halftone\-pattern for scanimage). Available only for the JX-330 series scanners. Possible settings: .RS .B none .br .B Dither Bayer .br .B Dither Spiral .br .B Dither Dispersed .br .B Error Diffusion .RE The default value is .B none. .B Paper Source (parameter .B \-\-source for scanimage). This option is only available, if an automatic document feeder or a transparency adapter is installed. Possible settings: .RS .B Flatbed .br .B Automatic Document Feeder .br .B Transparency Adapter .RE If an ADF or a transparency adapter is installed, using it is the default selection. .B Custom Gamma (parameter .B \-\-custom\-gamma for scanimage). This option determines whether a builtin or a custom gamma-table is used. Possible settings: .RS .B yes enables custom gamma tables .br .B no enables a built gamma table .RE .B Gamma (parameter .B \-\-Gamma for scanimage). This option is only available, if .B Custom Gamma is set to .B no. Possible values: .RS .B 1.0 .br .B 2.2 .RE The default value is 2.2. (The JX-250 and JX-350 have no built in gamma correction; for these scanner, a gamma table is downloaded to the scanner by the backend.) .B Gamma Table (parameter .B \-\-gamma\-table for scanimage). Allowed values: 0..255; 256 numbers must be defined. The default values are 0, 1, 2, .. 255 (i.e., gamma == 1). This table is only used for gray scale scans. .B Red Gamma Table (parameter .B \-\-red\-gamma\-table for scanimage). Allowed values: 0..255; 256 numbers must be defined. The default values are 0, 1, 2, .. 255 (i.e., gamma == 1). .B Green Gamma Table (parameter .B \-\-green\-gamma\-table for scanimage). Allowed values: 0..255; 256 numbers must be defined. The default values are 0, 1, 2, .. 255 (i.e., gamma == 1). .B Blue Gamma Table (parameter .B \-\-blue\-gamma\-table for scanimage). Allowed values: 0..255; 256 numbers must be defined. The default values are 0, 1, 2, .. 255 (i.e., gamma == 1). .B Resolution in pixel per inch (parameter .B \-\-resolution for scanimage). Selects the resolution of the scanned image. Allowed values: .RS .B 30..600 (JX-330, JX-350 and JX-610) resp. .B 30..400 (JX-250) .RE The default value is 150. .B Scan Window The possible settings depend on the scanner model and, for the JX-250 and the JX-350, also on the usage of the automatic document feeder resp. the transparency adapter. Please refer to the values allowed by xscanimage, or xsane. With scanimage, enter one of the following commands: .RS .I scanimage \-d sharp \-\-source """Automatic Document Feeder""" \-\-help .I scanimage \-d sharp \-\-source Flatbed \-\-help .I scanimage \-d sharp \-\-source """Transparency Adapter""" \-\-help .RE in order to see the allowed parameter values for the scan window. The scan window parameters are: .RS Top-left x position of scan area (parameter .B \-l for scanimage); .br Top-left y position of scan area (parameter .B \-t for scanimage); .br bottom right x position of scan area (parameter .B \-x for scanimage); .br bottom right y position of scan area (parameter .B \-y for scanimage); .RE .B Edge emphasis (parameter .B \-\-Edge emphasis for scanimage). This option is not available for the JX-250 and the JX-350. Possible settings: .RS .B None .br .B Middle .br .B Strong .br .B Blur .RE The default value is .B None. .B Threshold (parameter .B \-\-threshold for scanimage). Sets the threshold for black and white pixels in lineart mode. Possible values: .RS .B 1..255 .RE The default value is .B 128. This option is only available in scan mode lineart. .B Threshold Red (parameter .B \-\-threshold-red for scanimage). Sets the threshold for the red component of a pixel in in lineart color scan mode. Possible values: .RS .B 1..255 .RE The default value is .B 128. This option is only available in scan mode color lineart. .B Threshold Green (parameter .B \-\-threshold-green for scanimage). Sets the threshold for the green component of a pixel in in lineart color scan mode. Possible values: .RS .B 1..255 .RE The default value is .B 128. This option is only available in scan mode color lineart. .B Threshold Blue (parameter .B \-\-threshold-blue for scanimage). Sets the threshold for the blue component of a pixel in in lineart color scan mode. Possible values: .RS .B 1..255 .RE The default value is .B 128. This option is only available in scan mode color lineart. .B Light Color (parameter .B \-\-LightColor for scanimage). Sets the color of the light source. Possible values: .RS .B white .br .B red .br .B green .br .B blue .RE The default value is .B white. This option is only available in scan modes lineart color and color. .SH ADF USAGE If a paper jam occurred, the maintenance cover .I must be opened and closed, even if the jammed paper can be removed without opening the maintenance cover. Otherwise, the error condition cannot be cleared. .SH CONFIGURATION The contents of the .I sharp.conf file is a list of options and device names that correspond to Sharp scanners. Empty lines and lines beginning with a hash mark (#) are ignored. See sane\-scsi(5) for details about device names. .PP Lines setting an option start with the key word .B option, followed by the option's name and the option's value. At present, three options are defined: .B buffers, buffersize, and .B readqueue. .PP Options defined at the start of .I sharp.conf apply to all devices; options defined after a device name apply to this device. .PP The options .B buffers and .B readqueue are only significant if the backend has been compiled so that for each scan a second process is forked (switch .B USE_FORK in .I sharp.c ). This process reads the scan data from the scanner and writes this data into a block of shared memory. The parent process reads the data from this memory block and delivers it to the frontend. The options control the size and usage of this shared memory block. .PP .B option buffers defines the number of buffers used. The smallest number allowed is 2. .PP .B option buffersize defines the size of one buffer. Since each buffer is filled with a single read command sent to the scanner, its size is limited automatically to the size allowed by the operating system or by the Sane SCSI library for SCSI read commands. A buffer size of 128 kB or 256 kB is recommended for scan resolutions of 300 dpi and above. .PP .B option readqueue defines how many read commands to be sent to the scanner are queued. At present, the Sane SCSI library supports queued read commands only for for Linux. For other operating systems, .B option readqueue should be set to 0. For Linux, .B option readqueue should be set to 2. Larger values than 2 for .B option readqueue are not reasonable in most cases. .B option buffers should be greater than .B option readqueue. .SH Performance Considerations This section focuses on the problem of stops of the scanner's carriage during a scan. Carriage stops happen mainly with the JX-250. This scanner has obviously only a small internal buffer compared to its speed. That means that the backend must read the data as fast as possible from the scanner in order to avoid carriage stops. .PP Even the JX-250 needs only less than 10 seconds for a 400 dpi A4 gray scale scan, which results in a data transfer rate of more than 1.6 MB per second. This means that the data produced by the scanner must be processed fairly fast. Due to the small internal buffer of the JX-250, the backend must issue a read request for the next data block as soon as possible after reading a block of data in order to avoid carriage stops. .PP Stops of the carriage can be caused by the following reasons: .PP .RS \- too much "traffic" on the SCSI bus .br \- slow responses by the backend to the scanner, .br \- a program which processes the data acquired by the backend too slow. .PP .RE Too much "traffic" on the SCSI bus: This happens for example, if hard disks are connected to the same SCSI bus as the scanner, and when data transfer from/to these hard disks requires a considerable part of the SCSI bandwidth during a scan. If this is the case, you should consider to connect the scanner to a separate SCSI adapter. .PP Slow responses by the backend to the scanner: Unfortunately, Unix-like operating systems generally have no real time capabilities. Thus there is no guarantee that the backend is under any circumstances able to communicate with the scanner as fast as required. To minimize this problem, the backend should be compiled so that a separate reader process is forked: Make sure that .B USE_FORK is defined when you compile .I sharp.c. If slow responses of the backend remain to be problem, you could try to reduce the load of the system. Even while the backend and the reader process need only a minor amount of processor time, other running processes can cause an increase in the time delay between two time slices given to the reader process. On slower systems, such an increased delay can be enough to cause a carriage stop with the JX-250. For Linux, the usage of the SG driver version 2.1.36 or above is recommended, because it supports, in combination with the SCSI library of Sane version 1.0.2, command queueing within the kernel. This queueing implementation, combined with a buffer size of at least 128 kB, should avoid most carriage stops. .PP Slow processing of the scan data: An example for this situation is the access to the scanner via a 10 MBit Ethernet, which is definitely too slow to transfer the scan data as fast as they are produced by the scanner. If you have enough memory available, you can increase .B option buffers, so that an entire image can be stored in these buffers. .PP In order to see, if the backend is too slow or if the further processing of the data is too slow, set the environment variable .B SANE_DEBUG_SHARP to 1. When a scan is finished, the backend writes the line "buffer full conditions: .I nn" to stderr. If .I nn is zero, carriage stops are caused by too slow responses of the backend or too much "traffic" on the SCSI bus. If .I nn is greater than zero, the backend had to wait .I nn times until a buffer has been processed by the frontend. (Please note that .B option buffers must be greater than .B option readqueue in order to get useful output for "buffer full conditions".) .SH FILES .TP .I @CONFIGDIR@/sharp.conf The backend configuration file. .TP .I @LIBDIR@/libsane\-sharp.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-sharp.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_SHARP If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH KNOWN PROBLEMS 1. ADF Mode .RS After several ADF scans, the scanner moves the carriage back to the idle position and back to ADF scan position, before a scan starts. We do not know, if this is a problem of the scanner, or if this is a bug of the backend. At present, the scanner must power off and on to stop this annoying behaviour. .RE 2. Threshold level does not work (only JX-610) .PP 3. The maximum resolution is limited to 600 dpi(JX-610 supported to 1200 dpi) resp. 400 dpi (JX-250) .PP 4. If the JX250 is used with an ADF, the following situation can occur: After several scans, the scanner moves, after loading a new sheet of paper, the carriage to the idle position, and then back to the position used for ADF scans. This happens for .I every scan, in contrast to the calibration, which is done after 10 scans. (For the calibration, the carriage is also moved to the idle position.) We do not know, if this behavior is caused by the backend, or if it is a bug in the firmware of the scanner. .PP 5. Usage of a transparency adapter (film scan unit) is supported, but not tested. .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHORS Kazuya Fukuda, Abel Deuring .SH CREDITS The Sharp backend is based on the Canon backend written by Helmut Koeberle .PP Parts of this man page are a plain copy of sane\-mustek(5) by David Mosberger-Tang, Andreas Czechanowski and Andreas Bolsch sane-backends-1.0.27/doc/sane-ibm.man0000664000175000017500000000532412112021330014144 00000000000000.TH sane\-ibm 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-ibm .SH NAME sane\-ibm \- SANE backend for IBM and Ricoh SCSI flatbed scanners .SH DESCRIPTION The .B sane\-ibm library implements a SANE (Scanner Access Now Easy) backend that provides access to the IBM 2456 and the Ricoh IS-410, IS-420, and IS-430 flatbed scanners. Support for the IS-410 and IS-430 is untested. Please contact the maintainer or the sane\-devel mailing list if you own such a scanner. .PP This backend is alpha-quality. It may have bugs and some scanners haven't been tested at all. Be careful and pull the plug if the scanner causes unusual noise. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is either the path-name for the special device that corresponds to a SCSI scanner. The program .I sane\-find\-scanner helps to find out the correct device. Under Linux, such a device name could be .I /dev/sg0 or .IR /dev/sga , for example. See .BR sane\-scsi (5) for details. .SH CONFIGURATION The contents of the .I ibm.conf file is a list of device names that correspond to SCSI scanners. Empty lines and lines starting with a hash mark (#) are ignored. See .BR sane\-scsi (5) on details of what constitutes a valid device name. .SH FILES .TP .I @CONFIGDIR@/ibm.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-ibm.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-ibm.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_IBM If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. .SH "SEE ALSO" .BR sane (7), .BR sane\-find\-scanner (1), .BR sane\-scsi (5), .SH AUTHOR mf .br Maintained by Henning Meier-Geinitz sane-backends-1.0.27/doc/sane-p5.man0000664000175000017500000001052212617742237013747 00000000000000.TH "sane\-p5" "5" "15 Feb 2010" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-p5 .SH "NAME" sane\-p5 \- SANE backend for the Primax PagePartner .SH "DESCRIPTION" The .B sane\-p5 library implements a SANE (Scanner Access Now Easy) backend that provides access to the Primax PagePartner parallel port sheet fed scanner. .PP This backend handles 100, 150, 200, 300 and 600 dpi scan resolutions, in color and gray modes. The 600 dpi is actually 300x600 with lines enlarged to match the vertical resolution. .PP .B EPP/ECP MODES ONLY The current version of the backend uses only EPP or ECP mode to communicate with the scanner. It is recommended that you set your parallel port to EPP in BIOS with the current version of this backend. ECPEPP will only work if you use a 2.4 or 2.6 kernel with ppdev character device support. .PP .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I port value .RE .PP Where \fBvalue\fR is : .RS .TP auto autodetect all parallel ports and probe them for scanner .TP /dev/parport0 uses linux ppdev device, depending on the number of available parallel port, you have to use /dev/parport1, /dev/parport2, ... .PP .RE You can rename any device using the .PP .RS .br .I option name my_name .RE .PP option. This option apply to the last port option. .SH "CONFIGURATION" Please make sure to edit dll.conf .B before you use the backend, since this backend isn't enabled by default. .PP .PP .SH "FILES" .TP .I @CONFIGDIR@/p5.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-p5.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-p5.so The shared library implementing this backend (present on systems that support dynamic loading). .SH "ENVIRONMENT" .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_P5 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 255 requests all debug output to be printed. Smaller levels reduce verbosity. .PP .RS .ft CR .nf level debug output \-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- 0 critical errors 1 errors 2 warnings & minor errors 4 information messages 8 start/stop of functions 16 tracing messages 32 I/O functions 64 I/O functions with traces 128 scanned/calibration data .fi .ft R .RE .PP .TP .PP .RS .ft CR .nf .PP .PP .SH "SEE ALSO" sane(7), sane\-net(5), saned(8) .SH "AUTHOR" St\['e]phane Voltz .SH "CREDITS" Support for the Prima PagePartner has been made possible thank to an hardware donation by S\['e]bastien Lange. .SH "BUG REPORTS" If something doesn't work mail sane-devel@lists.alioth.debian.org or use the bug tracker at https://alioth.debian.org/tracker/?atid=410366&group_id=30186 . Please give as much information as you can. .TP .I SANE version run "scanimage \-V" to determine this .TP .I the backend version and your scanner hardware run "SANE_DEBUG_P5=255 scanimage \-L 2>log" as root. If you don't get any output from the p5 backend, make sure a line "p5" is included into your @CONFIGDIR@/dll.conf. If your scanner isn't detected, make sure you've defined the right port address, or the correct device in your p5.conf. .TP .I the name of your scanner/vendor also a worthy information. Please also include the optical resolution and lamp type of your scanner, both can be found in the manual of your scanner. .TP .I any further comments if you have comments about the documentation (what could be done better), or you think I should know something, please include it. sane-backends-1.0.27/doc/sane-hp5590.man0000664000175000017500000000324412112021330014326 00000000000000.TH sane\-hp5590 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hp5590 .SH NAME sane\-hp5590 \- SANE backend for Hewlett-Packard 4500C/4570C/5500C/5550C/5590/7650 Workgroup/Document scanners .SH DESCRIPTION The .B sane\-hp5590 library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Hewlett-Packard Workgroup/Document scanners: .PP .RS ScanJet 4500C .br ScanJet 4570C .br ScanJet 5500C .br ScanJet 5550C .br ScanJet 5590 .br ScanJet 7650 .RE .PP If you own a scanner other than the ones listed above that works with this backend, please let us know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .IR /proc/bus/usb/devices , .I sane\-find\-scanner or syslog) to us. Even if the scanner's name is only slightly different from the models mentioned above, please let us know. .SH CONFIGURATION None required. .SH FILES .TP .I @LIBDIR@/libsane\-hp5590.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hp5590.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_HP5590 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. See used levels below. .P .RS Level 10 - generic processing .br Level 20 - verbose backend messages .br Level 40 - HP5590 high-level commands .br Level 50 - HP5590 low-level (USB-in-USB) commands .P Example: export SANE_DEBUG_HP5590=50 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .SH AUTHOR Ilia Sotnikov sane-backends-1.0.27/doc/leo/0000775000175000017500000000000013110600532012615 500000000000000sane-backends-1.0.27/doc/leo/leo.txt0000664000175000017500000000630612112021330014054 00000000000000 BACKEND LEO Across Technologies FS-1130 (A rebadged LEO Technologies) 000: 06 31 14 01 1f 00 00 00 41 43 52 4f 53 53 20 20 .1......ACROSS 016: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 032: 31 2e 31 36 09 f6 0d b6 01 2c 01 2c 39 36 30 30 1.16.....,.,9600 LEO LEOScan S3: 000: 06 31 14 01 1F 00 00 00 4C 45 4F 20 20 20 20 20 .1......LEO 016: 4C 45 4F 53 63 61 6E 2D 53 33 20 20 20 20 20 20 LEOScan-S3 032: 33 2E 30 31 09 F6 0D B6 01 2C 01 2C 39 36 30 30 3.01.....,.,9600 or 000: 06 00 02 02 1f 00 00 00 4c 45 4f 00 00 00 00 00 ........LEO..... 016: 4c 45 4f 53 63 61 6e 2d 53 33 00 00 00 00 00 00 LEOScan-S3...... 032: 31 2e 31 30 1.10 Genius FS1130 000: 06 31 14 01 1f 00 00 00 4b 59 45 20 43 4f 52 50 .1......KYE CORP 016: 43 6f 6c 6f 72 50 61 67 65 2d 43 53 20 20 20 20 ColorPage-CS 032: 31 2e 31 34 1.14 /*--------------------------------------------------------------------------*/ SCSI commands supported by the FS-1130 TEST UNIT READY 00 00 00 00 00 00 INQUIRY 12 00 00 00 30 00 8-15: vendor name 16-31: product name 32-35: firmware level 36-37: scan area width in 1/300th of inches 38-39: scan area length in 1/300th of inches 40-41: max X resolution in dpi 42-43: max Y resolution in dpi 44-47: ? SCAN 1B 00 00 00 00 00 Start a scan SET WINDOW 24 00 00 00 00 00 30 00 00 00 Total length is 48 bytes 01 = 0x2E (may be 0x30 - 2, ie total length -2) 07 = length (48-8 = 40 = 0x28) 10-11 = X Resolution 12-13 = Y resolution 14-17 = X top left corner 18-21 = Y top left corner 22-25 = width (size in inches * 300) 26-29 = length (size in inches * 300) 31 = 0x80 ? 33 = scan mode 0x00 = black & white 0x01 = halftone 0x02 = grayscale 0x05 = color 34 = bit depth 1 or 8 37 = ? RIF + other 43 = ? 0x01 READ 28 00 00 00 00 00 00 0B 28 00 SEND 2A 00 03 00 00 01 00 03 00 00 2A 00 02 00 00 0F 00 01 00 00 2 = data type code 0x02 = halftone pattern 0x03 = gamma - 3 colors with 256 bytes each GET DATA BUFFER STATUS 34 00 00 00 00 00 00 00 10 00 7-8 allocation length returned buffer is 0x10 bytes long. 00 00 0D 00 00 00 03 D3 60 00 00 00 01 48 00 EE 0-2 = additional length (0x10-3 = 0x0D) 6-8 = (?) total scan length 9-11 = filled data buffer 12-13 = number of lines left (decrease during a scan) 14-15 = bytes per line (constant during a scan) /*--------------------------------------------------------------------------*/ Command sequence for the FS-1130 Setup the scan: TUR SET WINDOWS SEND gamma SEND haltone pattern (if halftone scan) SCAN TUR until scanner ready GET DATA BUFFER STATUS loop until all data read: GET DATA BUFFER STATUS READ park the CCD: SET WINDOWS TUR SCAN /*--------------------------------------------------------------------------*/ Command sequence for the S3 It seems similar to the FS-1130 except that no gamma nor halftone pattern is sent. Setup the scan: TUR SET WINDOWS SCAN TUR until scanner ready loop until all data read: GET DATA BUFFER STATUS READ park the CCD: SET WINDOWS SCAN sane-backends-1.0.27/doc/sane-find-scanner.man0000664000175000017500000001000212112021330015731 00000000000000.TH sane\-find\-scanner 1 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-find\-scanner .SH NAME sane\-find\-scanner \- find SCSI and USB scanners and their device files .SH SYNOPSIS .B sane\-find\-scanner .RB [ \-h | \-? ] .RB [ \-v ] .RB [ \-q ] .RB [ \-p ] .RB [ \-f ] .RB [ \-F .IR filename ] .RI [ devname ] .SH DESCRIPTION .B sane\-find\-scanner is a command-line tool to find SCSI and USB scanners and determine their Unix device files. Its primary aim is to make sure that scanners can be detected by SANE backends. .PP For .B SCSI scanners, it checks the default generic SCSI device files (e.g., .IR /dev/sg0 ) and .IR /dev/scanner . The test is done by sending a SCSI inquiry command and looking for a device type of "scanner" or "processor" (some old HP scanners seem to send "processor"). So .B sane\-find\-scanner will find any SCSI scanner connected to those default device files even if it isn't supported by any SANE backend. .PP For .B USB scanners, first the USB kernel scanner device files (e.g. .IR /dev/usb/scanner0 ), .IR /dev/usb/scanner , and .IR /dev/usbscanner ) are tested. The files are opened and the vendor and device ids are determined, if the operating system supports this feature. Currently USB scanners are only found this way if they are supported by the Linux scanner module or the FreeBSD or OpenBSD uscanner driver. After that test, .B sane\-find\-scanner tries to scan for USB devices found by the USB library libusb (if available). There is no special USB class for scanners, so the heuristics used to distinguish scanners from other USB devices is not perfect. .B sane\-find\-scanner also tries to find out the type of USB chip used in the scanner. If detected, it will be printed after the vendor and product ids. .B sane\-find\-scanner will even find USB scanners, that are not supported by any SANE backend. .PP .B sane\-find\-scanner won't find most parallel port scanners, or scanners connected to proprietary ports. Some .B parallel port scanners may be detected by .B sane\-find\-scanner -p. At the time of writing this will only detect Mustek parallel port scanners. .SH OPTIONS .TP 8 .B \-h, \-? Prints a short usage message. .TP 8 .B \-v Verbose output. If used once, .B sane\-find\-scanner shows every device name and the test result. If used twice, SCSI inquiry information and the USB device descriptors are also printed. .TP 8 .B \-q Be quiet. Print only the devices, no comments. .TP 8 .B \-p Probe parallel port scanners. .TP 8 .B \-f Force opening all explicitly given devices as SCSI and USB devices. That's useful if .B sane\-find\-scanner is wrong in determining the device type. .TP 8 .B \-F filename filename is a file that contains USB descriptors in the format of /proc/bus/usb/devices as used by Linux. .B sane\-find\-scanner tries to identify the chipset(s) of all USB scanners found in such a file. This option is useful for developers when the output of "cat /proc/bus/usb/devices" is available but the scanner itself isn't. .TP 8 .B devname Test device file "devname". No other devices are checked if devname is given. .SH EXAMPLE .B sane\-find\-scanner \-v .br Check all SCSI and USB devices for available scanners and print a line for every device file. .PP .B sane\-find\-scanner /dev/scanner .br Look for a (SCSI) scanner only at /dev/scanner and print the result. .PP .B sane\-find\-scanner \-p .br Probe for parallel port scanners. .SH "SEE ALSO" .BR sane (7), .BR sane\-scsi (5), .BR sane\-usb (5), .BR scanimage (1), .BR xscanimage (1), .BR xsane (1), .BR sane\-"backendname" (5) .SH AUTHOR Oliver Rauch, Henning Meier-Geinitz and others .SH SUPPORTED PLATFORMS USB support is limited to Linux (kernel, libusb), FreeBSD (kernel, libusb), NetBSD (libusb), OpenBSD (kernel, libusb). Detecting the vendor and device ids only works with Linux or libusb. .PP SCSI support is available on Irix, EMX, Linux, Next, AIX, Solaris, FreeBSD, NetBSD, OpenBSD, and HP-UX. .SH BUGS No support for most parallel port scanners yet. .br Detection of USB chipsets is limited to a few chipsets. sane-backends-1.0.27/doc/sane-sp15c.man0000664000175000017500000000433412112021330014330 00000000000000.TH sane\-sp15c 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .SH NAME sane\-sp15c \- SANE backend for Fujitsu ScanPartner 15C flatbed scanner .SH DESCRIPTION The .B sane\-sp15c library implements a SANE (Scanner Access Now Easy) backend which provides access to the Fujitsu flatbed scanners. At present, the following scanner is known to work with these backend: .PP .RS .ft CR .nf Vendor: Model: Rev: -------- ---------------- ----- FCPA ScanPartner 15C 1.01 .fi .ft R .RE .P The ScanPartner 15C driver supports lineart (1-bit), halftone (1-bit), grayscale (4-bit and 8-bit), and color (3 x 8-bit) scanning. Other scanners in these families may work. The ScanPartner 15C seems to be a repackaging of the ScanPartner 600C. People are encouraged to try these driver with the other scanners and to contact the author with test results. .SH CONFIGURATION A modest effort has been made to expose the standard options to the API. This allows frontends such as xscanimage to set scanning region, resolution, bit-depth (and color), and enable the automatic document feeder. .SH "SEE ALSO" sane(7), sane\-scsi(5), sane\-fujitsu(5) .br Fujitsu ScanPartner 15C OEM Manual, Doc. No. 250-0081-0 .br Fujitsu M3096G OEM Manual, part number 50FH5028E-05 .br Fujitsu M3096GX/M3093GX/M3093DG OEM Manual, part number C150-E015...03 .SH AUTHOR Randolph Bentson , with credit to the unnamed author of the coolscan driver .SH LIMITATIONS Testing limited to a Linux 2.2.5 kernel .br Can't quite get the scan page/minute performance in ADF modes. This may be due to limited system buffer size. .SH BUGS I'm sure there are plenty, and not too well hidden, but I haven't seen them yet. .br Both scanners claim to have separate control of resolution in X and Y directions. I confess I haven't tested this yet. I have found that xsane doesn't even display this capability. .br Threshold settings on the SP15C don't seem to affect the results of lineart mode scans. .br It might be possible to merge these two drivers without much effort since the SP15C driver was derived from the M3096G driver. They were split so as to keep the second driver development from breaking the working first driver. Watch this space for changes. sane-backends-1.0.27/doc/sane-hp4200.man0000664000175000017500000000661612112021330014317 00000000000000.TH sane\-hp4200 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hp4200 .SH NAME sane\-hp4200 \- SANE backend for Hewlett-Packard 4200 scanners .SH DESCRIPTION The .B sane\-hp4200 library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Hewlett-Packard USB flatbed scanners: .PP .RS ScanJet 4200 C .br ScanJet 4200 Cxi .br ScanJet 4200 Cse .RE .PP More details can be found on the hp4200 backend homepage .IR http://hp4200\-backend.sourceforge.net/ . .PP This is BETA software. Keep your hand at the scanner's plug and unplug it, if the head bumps at the end of the scan area. .PP If you own a scanner other than the ones listed above that works with this backend, please let us know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .IR /proc/bus/usb/devices , .I sane\-find\-scanner or syslog) to us. Even if the scanner's name is only slightly different from the models mentioned above, please let us know. .PP .SH CONFIGURATION The contents of the .I hp4200.conf file is a list of usb lines containing vendor and product ids that correspond to USB scanners. The file can also contain the names of device files that correspond to an HP 4200 scanner. Empty lines and lines starting with a hash mark (#) are ignored. The scanners are autodetected by .B usb vendor_id product_id statements which are already included into .IR hp4200.conf . "vendor_id" and "product_id" are hexadecimal numbers that identify the scanner. If autodetection does not work, add the device name of your scanner to the configuration file, e.g. .IR /dev/usb/scanner0 . .PP .SH FILES .TP .I @CONFIGDIR@/hp4200.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-hp4200.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hp4200.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_HP4200 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_HP4200=4 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .br .I http://hp4200\-backend.sourceforge.net/ .SH AUTHOR Adrian Perez Jorge, Andrew John Lewis, Arnar Mar Hrafnkelsson, Frank Zago, Henning Meier-Geinitz. Current maintainer: Henning Meier-Geinitz . .SH BUGS Tested only with Linux. .PP Only 8 bit color mode works. .PP Scanning is slow due to backtracking. .PP Send bug reports to the sane\-devel mailing list: sane\-devel@lists.alioth.debian.org. sane-backends-1.0.27/doc/mustek/0000775000175000017500000000000013110600532013346 500000000000000sane-backends-1.0.27/doc/mustek/mustek.CHANGES0000664000175000017500000007466012617742237015631 00000000000000CHANGES for the SANE Mustek backend 2005-05-05: * Released Mustek backend 1.0-138 * Added options to set the time after which the lamp of the A3 Pro is shut off and to shut it off immediately. 2004-06-08 * Released Mustek backend 1.0-137 * Reduced scan area of Mustek Paragon 1200 A3 Pro. Removed warning message. Increased support level to complete. 2004-03-21 * Released Mustek backend 1.0-136 * Added detection of Mustek ScanExpress 1200 FS. 2003-12-25 * Released Mustek backend 1.0-135 * Added support for Mustek Paragon 600 II EP (SCSI-over-parallel port). This is based on a patch from James Perry. Support for libiee1284 is missing until now. 2003-10-29 * Added support for sanei_thread. * Removed OS/2 specific code. 2003-10-29 * Released Mustek backend 1.0-134 2003-10-29 * Added support for sanei_thread. * Removed OS/2 specific code. 2003-10-15 * Added more debug messages. 2003-09-21 * Released Mustek backend 1.0-133 2003-09-21 * Fixed check for single quotation marks. 2003-03-07 * Released Mustek backend 1.0-132 2003-03-07 * Minor debug message updates. 2003-02-27 * Fixed a little bug in sane_control_option (gamma control). * Removed the signal blocking again. That only hides the segfault in sanei_scsi. * Check if there are documents in ADF for Paragon 2. Otherwise return error. 2003-02-25 * Fix some minor issues in reading the config file. 2003-02-22 * Initialize global variables in sane_init. 2003-02-17 * Released Mustek backend 1.0-131 2003-02-17 * Make sure that the result of the reader_process is interpreted correctly. * Block signals when waiting for a SCSI request to finish. Otherwise we may get a segfault if the reader_process is terminated while waiting. 2002-11-29 * Released Mustek backend 1.0-130 2002-11-29 * PACKAGE_VERSION fix. 2002-11-18 * Fixed debug message in do_stop: really print exit status of reader process. 2002-11-17 * Fixed minor issues in mapage. Added links to plustek and gt68xx backends. 2002-11-09 * Added link to SCSI documentation to manpage. 2002-11-07 * Released Mustek backend 1.0-129 2002-11-05 * Upload linear gamma table for Pro models if custom gamma is off instead of uploading the composed gamma table. That avoids applying gamm twice. * Minor man page update. 2002-10-11 * Released Mustek backend 1.0-128 2002-10-10 * Fixed lamp off time (60 minutes) for the 1200 A3 Pro. 2002-07-30 * Released Mustek backend 1.0-127. 2002-07-30 * Fixed some warnings. 2002-07-07 * Released Mustek backend 1.0-126. 2002-07-07 * Increased width and height of Paragon 800 and 600. 2002-06-07 * Released Mustek backend 1.0-125. 2002-06-07 * Fixed some comments. * Use FORCE_GAMMA for Paragon 6000SP as 2.x versions otherwise produce solid black images. * Used my own address instead of sane-devel for bug reports. 2002-05-31 * Explicitely set some arrays to 0. 2002-05-28 * Released Mustek backend 1.0-124. 2002-05-28 * Set X minimum value to 0 for Paragon 6000SP. 2002-04-24: * Released Mustek backend 1.0-122. 2002-04-24: * Undef MIN and MAX if they are defined in mustek.h to avoid warnings. 2002-04-22: * Fixed debug output in sane_control_option and sane_get_device_descriptor. 2002-04-10: * Released Mustek backend 1.0-121. 2002-04-10: * Set freed variables to 0 at sane_exit. * Coding-style fixed. 2002-04-06: * Released Mustek backend 1.0-120. 2002-04-05: * For 3-pass scanners use area_wait_ready and inquiry_wait_ready. The first wait doesn't seem to be enough for some scanners. 2002-03-20: * Released Mustek backend 1.0-119. 2002-03-20: * Fix halftone pattern handling. The buffer was way too small. 2002-03-19: * Option 0 has an empty name. 2002-03-18: * Better debug output for dev_cmd. * Set size for group options to 0. * Set size of halftone pattern to non 0. 2002-02-14: * Fixed some problems with wrong formats in DBG statements. 2002-01-23: * Fixed undefined operation warnings. 2002-01-20: * Released Mustek backend 1.0-118. 2002-01-20 * Changes for 1200 Pro: Removed debug code. Calibration is done in every mode. Calibration is on by default. Added some scsi_sense_wait_ready commands to be sure. 2002-01-16 * Changed option names to use only "-" not "_". 2002-01-10 * OPT_CONTRAST_R is red, not blue. 2002-01-07 * Released Mustek backend 1.0-117. 2001-12-29 * Send start_stop_scan for Pro even if scan wasn't cancelled but less data than expected was send (e.g. scanimage -T). 2001-12-22 * Added Trust Imagery 1200 to man page and .desc. 2001-12-15 * Released Mustek backend 1.0-116. 2001-12-11 * Fixed possible segfault in sane_control_option. * Added debug output of SCSI commands in dev_cmd and dev_read_req_enter. 2001-11-29 * Released Mustek backend 1.0-115. 2001-11-29 * Removed empty test for pro models. * Added check for TL_X > BR_X or TL_Y > BR_Y. 2001-11-22 * Released Mustek backend 1.0-114. 2001-11-22 * Added OS/2 compatibility fixes from "Franz Bakan" . 2001-11-18 * The Primax Compact 4800 seems to bes also supported. Added .desc and manpage entries. 2001-09-10 * Released Mustek backend 1.0-113. 2001-09-10 * Fixed bug in gamma correction code that broke at least custom gamma for the Paragon 12000SP. 2001-08-26 * Released Mustek backend 1.0-112. 2001-08-10 * Don't close fds[1] in case of OS/2. 2001-08-01 * Send stop_scan only for ScanExpress scanners when the scan wasn't cancelled. 2001-07-18 * Released Mustek backend 1.0-111. 2001-07-18 * Added warning about Aashima (Trust) scanners. * Only call stop_scan if Scan was cancelled for Paragon scanners. 2001-07-15 * Added message in reader_process that's printed when the kernel SCSI buffer is too small for the selected buffer size. 2001-07-11 * Released Mustek backend 1.0-110. 2001-07-10 * Added debug output for the total amount of data transfered to the frontend. * Fixed bug in fix_line_distance_block which lead to too much data transferred to sane_read. 2001-07-09 * Released Mustek backend 1.0-109. 2001-07-09 * Fixed (hopefully) problem with black images (Paragon 6000 SP). 2001-07-08 * Fixed problem with double buffering/SCSI command queuing and Linux 2.4.x. Thaks to Abel Deuring for his help. * Added option to disable backtracking 2001-07-07 * Released Mustek backend 1.0-108. 2001-07-07 * added option to disable double-buffering * don't set any options by default in mustek.conf * updated manpage * fixed debug statement in scsi_inquiry_wait_ready 2001-05-06 * Fixed memory leak in sane_get_devices () 2001-04-29 * Fixed several memory leaks. 2001-04-27 * Released Mustek backend 1.0-107 (in CVS). 2001-04-23 * Add internationalization support (mark all strings that can be translated with SANE_I18N()). 2001-04-19 * Don't check for macro VERSION any longer in sane_init. Print out PACKAGE_VERSION instead. * Update email address and homepage. 2001-08-08 * Released Mustek backend 1.0-106 2001-04-08 * Backend status is "stable" now. Hopefully this doesn't mean that new bugs show up now :-) 2001-04-01 * Added detection of the Pro models TA (at least the 1200SP Pro). * Added warning about real (not relabeled) Trust scanners. 2001-03-31 * Removed comment about brightness and contrast in the description strings because you can't read them anyway in color mode (at least with xsane). 2001-03-31 * Released Mustek backend 1.0-105 2001-03-31 * Removed compilation warning in gamma_correction. * Fixed handling of tlx and brx when scanning with ADF (bug found by Andreas Rathgeber ). * Fixed bug in linedistance correction (ld_block) concerning ADF. With ADF the linedistance values are ordered in the other direction. * Fixed bug concerning ld correction for the 1200SP 1.00 (frontend hangs). Moved the do-nothing ld correction to its own function. With ADF this scanner doesn't really work in color mode but that's probably a firmware problem. 2001-03-18 * 600 II N: Gamma correction in gray mode now works. Length must be 768 bytes in gray mode also, cdb size is 6 bytes. Thanks to Jakub Bogusz who found out about that and wrote a patch. 2001-01-17 * Released Mustek backend 1.0-104 2001-01-17 * Pro: Do calibration only in Lineart, Gray and Color 24 modes. 2001-01-03 * Added 36 bit color mode for the Paragon Pro scanners. 2000-12-31 * Added function little_endian (from coolscan.c) to check the endianess of the current architecture (needed for 16 bit frames). * Added option for Gray fast * Added option for bit depth (8 and 12 bits for the Pro models) * Removed "special" modes from mode option * Removed 48 bit options for the SE Plus. This mode seems to use only interpolated information (but I may be wrong). 2000-12-31 * Released Mustek backend 1.0-103 2000-12-30 * Implemented calibration (color and gray mode) for the Paragon 1200 Pro. It's not perfect and needs lots of tests. It may work for the Paragon A3 also but is not tested. * SE 12000 SP Plus calibration is now better but not yet perfect. 2000-12-27 * Enabled fast_preview for the Pro scanners (30 dpi). * Increased scan width to 8.6" for 1200 Pro. 2000-12-26 * Added calibration for the SE 12000 SP Plus. Doesn't fully work until now (images are too dark and colored). 2000-12-23 * Added option for Legal format (because the ScanExpress 12000 SP A4 size scanner can't be distinguished from the Paragon 1200 LS Legal size scanner by software). 2000-12-21 * Added a few checks for Null-Pointers. * Removed old code for SE calibration. * Added option "quality calibration" for SE Plus scanners 2000-12-21 * sane-backends 1.0.4 was released (including Mustek backend 1.0.102). 2000-12-10 * Released Mustek backend 1.0-102 2000-12-09 * Fixed wrong comment in encode_resolution * Added missing test for return status in sane_start * Fixed wrong calculation of tlx and tly for Pro series scanners 2000-12-05 * Released Mustek backend 1.0-101 2000-12-05 * Fixed lamp setting (avoid problems with some SE scanners). 2000-12-01 * Reduced scan area for Paragon 1200 SP PRO (to avoid bumping the scan slider at the end). * Removed warning for 1200 SP PRO. 2000-11-26 * Released Mustek backend 1.0-100 2000-11-26 * Default for "fast preview" is "false" now because this option doesn't work for all SE scanners correctly. * Added more debug output for area_and_windows. * Added more debug output for set_window. * Set minimum tly for 8000SP to 0. * Don't use block mode for Paragon 8000 SP scanners because this breaks color mode with firmware 2.x. 2000-11-19 * Paragon 6000 SP doesn't use block mode any more. It's a bit faster now. * Updated sane-mustek.man concerning buffersize and blocksite. 2000-11-17 * Updated manpage concerning force-wait. Some minor corrections and additions * Added option force-wait to mustek.conf and did some minor changes. 2000-11-16 * With option force_wait set, the backend waits also before sending the inquiry command. This seems to be necessary for the 600 II N. 2000-11-12 * Use SANE_Int, SANE_Bool, SANE_Word for int wherever this seems to be appropriate. * Move macros to mustek.h. * Code cleanup. 2000-11-11 * OPT_GRAY_PREVIEW is now called OPT_FAST_PREVIEW. * For SE scanners use 36/38 dpi color for fast preview. * use include "../include/sane/" instead of "sane/" * go back to old scheme for SE scanners in color mode (faster scans couldn't be reproduced) 2000-11-10 * added more debug output in constrain_value 2000-11-05 * Released backend version 1.0-99. 2000-11-05 * Added support for TAIV for SE 12000 SP. Lamp is turned off while scanning (seems to work for firmware >= 2.00) * Adjusted transparency adapter support for all ScanExpress scanners. The 12000 A3 SP can only do A4 beacuse I don't have the right TA. * don't use u_int* types in mustek.h because the definitions for these types are not included 2000-11-04 * SE scanners can now scan 75, 100, 150, 200, 250, 300, 400, 500, 600, 900 and 1200 dpi in color mode (the 1200 dpi models). These are fixed resolutions, a resolution >= the wanted resolution is selected. This makes preview and some resolutions faster than before (at least for some scanners), because lower resolutions can be used. * Minimum scan resolution is 60 dpi in gray and lineart and 75 dpi in color mode for the SE scanners now. 2000-10-29 * Fixed a bug concerning block LD. Paragon 1 and 2 were exchanged. * Paragon 12000SP color mode works now without garbage at the end * Fixed Paragon 1200 SP Pro color mode > 600 dpi (rounding problem) * Temporarily disabled 48 bit color mode for release 2000-10-25 * Detect support for TA IV (transparency adapter for ScanExpress scanners) * TA IV supported now; lamp is turned off at least for SE 1200 SP Plus scanners * Adjusted scan area for TA: SE 12000SP Plus * Simplify enlarge x * Set tl-y to 0 for all ScanExpress scanners * First attempt to support 48 bits color mode (SE 12000 SP Plus) 2000-10-22 * Detect SE 12000 SP Plus properly * Cover sensor only checked for SE models that support this feature 2000-10-21 * Removed MAX_BLOCKSIZE macro (not used anymore). 2000-10-03 * Released backend version 1.0-98. 2000-10-03 * Fixed segmentation fault in sane_init (else statement was missing). Thanks to Oliver Rauch who spotted this problem. * Re-enabled double buffering. 2000-10-02 * Zero out inquiry memory block before reading inquiry. 2000-10-01 * Fixed fix_line_distance_block. * Adjusted Paragon 12000 SP to use block LD correction if necessary. * removed LD MFS (wasn't used anyway) 2000-09-30 * Set blockbuffer size to 2 MB for Paragon series II scanners. * Fix sane_cancel for Paragon series II scanners * Fix speed and grain for Paragon series II scanners * Backtracking is used for all scanners (removed option) * included stop_scan into do_stop * better integration of the wait_ready functions * check that size of buffer <= size of block buffer 2000-09-24 * Added more debug output in sane_get_option_descriptor. * Added more debug output in sane_control_option. * Added check for devicename and handle != 0 in sane_open * Added check for handle != 0 in sane_get_option_descriptor * Added check for handle != 0 in sane_get_parameters * Added check for handle and val != 0 in sane_control_option * Added check for handle != 0 in sane_start * Added check for handle, buf and len != 0 in sane_read * Added check for handle != 0 in sane_cancel * Added check for handle != 0 in sane_set_io_mode * Added check for handle != 0 in sane_get_select_fd * Output option title in sane_get_option_descriptor if name is null 2000-09-24 * Released backend version 1.0-97. 2000-09-24 * Added RGB brightness and contrast for 3pass scanners * Brightness and contrast is +-100% for 3pass scanners now 2000-09-23 * Paragon 12000CX uses pixel unit now. * Paragon 6000CX uses pixel unit now (MSF-06000CZ). * Option "force backtracking" is enabled by default now * Option "scan speed" is set to "fastest" by default now * Add option "force-wait" (for mustek.conf). If enabled, wait for scan head to return to start position after scan. * Make DBG output in sane_control_option() more readable * Better error handling and debug output in sane_get_option_descriptor() * Changed Halftone handling, removed grain size 2000-09-22 * Paragon 12000SP 1.06 uses LD_NORMAL now. 2000-09-19 * Return sane_status_cancelled in sane_read if last scan was cancelled. 2000-09-18 * Changed speed_code to use values between 1...5 for 3pass scanners. I don't know yet if these are correct for the other scanners, too. * Don't do a stop scan for 3pass scanners (only when cancelling). * Set bit 0 of first byte of area_and_windows for gray + color. * Paragon 6000CX uses pixel unit now (MFS-06000CX). * Pixel unit for 3pass scanners is now supported 2000-09-17 * changed maximum y range of MFS-800 II SP to 288 mm because of a report of scanner touching the end. 2000-09-10 * added some testing (result != null and arg !=0) in sense_handler (found by Martin Blasczyk) 2000-08-20 * Paragon series II is also using blockmode now. * Removed warning from mustek.c. * Fixed (maybe) problem in scsi_sense_wait_ready and added more debug output. 2000-08-18 * added new option blocksize to mustek.conf * 800 II SP works now in new block mode (get_image_status is needed before each block) 2000-08-17 * Removed some warnings from sanei_ab306.c. 2000-08-16 * Fixed some bugs in fix_linedistance_block. Paragon 600 models seem to work now. 800 II SP freezes, however. * Fixed segmentation fault for the 600 II N in ld correction code. 2000-08-15 * Changed handling of three pass scanners (MUSTEK_FLAG_THREE_PASS instead of !MUSTEK_FLAG_SINGLE_PASS). * Added flags for Paragon series I and II (MUSTEK_PLAG_PARAGON_1 and MUSTEK_PLAG_PARAGON_2). * Distinguish between three-pass, Paragon series 1, Paragon series 2, ScanExpress, Pro and N type scanners. * Added support for scanning the whole image in one block without backtracking for the Paragon series II scanners. * Added fix_linedistance_block: like linedistance_normal but broken up into several SCSI buffers. 2000-08-14 * Changed again linedistance correction for the Paragon 12000 SP 1.11. This seems to be a never ending story. * Set the minimum dpi value to 30. Some scanners (e.g. the MFS 8000SP v 2.04) block the SCSI bus with lower resolutions. 2000-08-12 * Added support for Paragon 1200 SP Pro. * Added support for ScanExpress A3 SP. * Removed detection for " C12" and " C04" (don't seem to exist). * Changed SCSI read request scheme. Now two requests with half of the maximum SCSI buffer size are entered. Standard buffer size is 128 kB, so the buffer sent to the scanner is 64 kB for all types of scanners. * sane_read now reads more than 4096 bytes from pipe (if available). 2000-08-12 * SANE 1.0.3 released (including Mustek backend 1.0.96). 2000-07-31 * Released backend version 1.0-96. 2000-07-30 * Fixed bug concerning inquiry of 3-pass scanners. ASCII values > 127 weren't interpreted correctly (char instead of unsigned char). 2000-07-30 * Released backend version 1.0-95 2000-07-30 * Removed while {wait ()} loop. Used waitpid() instead. Maybe this cures some reported freezes. It's cleaner anyway. * Removed dead code. 2000-07-28 * Released backend version 1.0-94 2000-07-29 * Use #include "sane/..." instead of #include . 2000-07-27 * Released backend version 1.0-93 2000-07-27 * removed warnings 2000-07-26 * fixed possible segfault pointer info was not checked for 0 (found by Petter Reinholdtsen) * Updated comment about Paragon 600 II N linedistance correction in man page 2000-07-25 * Fixed color scanning for Paragon 600 II N firmware < 2.00. 2000-07-25 * Released backend version 1.0-92 2000-07-24 * Fixed ADF handling (output was mirrored in x direction). Gray and lineart seems to work now. Color and halftone modes look somewhat crazy. * Removed comment about lack of testing of ADFs in manpage. They are tested to work now with most scanner at least basically. * removed braindead test for Pro series concerning gamma table length (discovered by Jan-Erik Karlsson). 2000-07-22 * Fixed margin positions of MFS 6000CX and removed warning. * Warning is printed with DBG level 0 again. 2000-07-18 * Released backend version 1.0-91 2000-07-18 * Removed again MUSTEK_FLAG_LD_NONE for MFS-08000SP. Maybe the automatical detection works now. 2000-07-15 * Released backend version 1.0-90 2000-07-15 * Added MUSTEK_FLAG_LD_NONE for MFS-08000SP and removed warning for this scanner. Added TA support. First report for this device from Roland Koebler. * Changed LD correction system. Some scanners (e.g. the 800 II SP) seem to need different LD correction depending on resolution. Now with LD_NORMAL max_value is checked and correction is only done if it is != 0. Hope this works for all scanners. * Moved the comment after the example port entry in mustek.conf to the next line. Now this line should work. * Updated manpage concerning PP scanners and 600 II N. 2000-06-30 * Released backend version 1.0-89 2000-06-30 * Fixed bug in do_stop. The scan slider didn't return after the scan in some situations. 2000-06-28 * Released backend version 1.0-88 2000-06-28 * Changed again linedistance handling for the Paragon 1200SP. This time version 1.07 seems to need a special treetment. Even with normal linedistance correction the image is corrupted at buffer boundaries in color mode. Maybe a firmware bug? Thanks to Michael Prechtl for all his tests. 2000-06-25 * added missing newline to mustek.conf 2000-06-25 * Released backend version 1.0-87 2000-06-25 * updated manpage concerning parport and USB scanners * added example for 600 II N to mustek.conf 2000-06-22 * fixed debug output bug in fix_linedistance_se (found by Jan-Erik Karlsson) 2000-06-21 * fixed dependancy of mustek.h on sane-backends.h 2000-06-19 * Fixed gamma correction in lineart mode for Paragon 1200 A3 2000-06-18 * Released backend version 1.0-86 2000-06-18 * added enlarging x resolution for Paragon 1200 A3 Pro * Paragon 1200 A3 PRO is fully functional now. Thanks to Heinrich Falk, who borrowed me this device. 2000-06-17 * added calibration for Paragon 1200 A3 Pro (only dummy, doesn't work yet) * adjusted options for Paragon 1200 A3 Pro * added lineart support for Paragon 1200 A4 Pro * removed support for color lineart and color halftone modes * added color support for Paragon 1200 A3 Pro * added scsi_wait_sense, this fixed 1200 A3 Pro hangs * fixed gamma correction for 1200 A3 Pro. At the moment only 8 bit and 24 bit per pixel are supported (12/36 are possible in hardware) 2000-06-16 * addded debugging output in sane_control_option * added gamma correction for Paragon 1200 A3 Pro (doesn't work correctly yet) 2000-06-15 * removed old config file reading system. 2000-06-14 * Preliminary support for the Mustek Paragon 1200 A3 Pro. Only grayscale mode works so far. Missing: Gamma correction and calibration. The scanner is locked after each scan. 2000-06-12 * Fixed bug in sane_control_option. option was not checked for negative values. Thanks to Jochen Eisinger. * Code cleanup and reorganization for inclusion of the Paragon 1200 A3 Pro. 2000-06-07 * Fixed bug in sane_close where the chain of handles got destroyed by closing the first device. This bug is in the backend since 3 1/2 years. Thanks to Jochen Eisinger for spotting this. 2000-06-05 * Fixed some debug messages in fix_linedistance_se 2000-06-04 * released backend version 1.0-85 2000-06-04 * changed (again) Paragon 12000 SP linedistance handling, now 1.02 uses normal LD corrections, all other use none. We'll see, if this works. Thanks to Reinhard Günzel who helped to debug this. * fixed some long lines (>80 chars) 2000-06-03 * released backend version 1.0-84 2000-06-03 * changed line-distance handling, removed ld.max_value magic (didn't work) * fixed (maybe) Paragon 12000 SP color stripes problems (v 1.11 and others) * simpler linedistance debug output, only for 1-pass Paragon scanners 2000-06-02 * removed code in dev_read_start which was never called (suggestion from Jan-Erik Karlsson) 2000-05-21 * added double buffering (trying to copy the scsi buffer to the frontend while getting a new one). This probably won't work on all platforms and with all SCSI host adapters but in this case performance shouldn't be worse than before. 2000-05-21 * released backend version 1.0-83 2000-05-21 * The Mustek Paragon 1200 A3 PRO is now detected. This is only a test release. Be carefull and read the PROBLEMS file if you want to try this scanner. 2000-05-19 * released backend version 1.0-82 2000-05-18 * set debug level for output of unknown Mustek scanner to 0 (suggestion from Thorben Kundinger) 2000-05-12 * fixed bug in distinguishing firmware formats * added shrinked image fix to ScanExpress 12000SP models <= v2.0 2000-05-08 * fixed remaining sane_cancel problems (in non_blocking mode) * fixed color stripes and segmentation fault for Paragon MFS-12000SP 1.00 (at least for me) * added more debug output to inquiry * added possibility to distinguish old and new firmware formats * added one more debug level (5) * added output of SANE version 2000-05-07 * released backend version 1.0-81 2000-05-06 * added transparency adapter support for the Paragon 600 II CD, 600S, 800 II SP, 600 II N, ScannExpress 6000SP and 12000SP * removed "color lineart" and "color halftone" for all scanners. These modes didn't work for any of my scanners. * added more debug output for ADF and TA * fixed bug when ADF is out of documents * Scan source option is only available if TA or ADF is present. For SE and N models TA is always available because it can't be detected by hardware * removed "backtrack", "speed" and "grain" from 600 II N options, the scanner doesn't support them * updated mustek.desc and mustek.man 2000-05-02 * Reduced scan area for the Paragon MFC-600S because of ugly noises at the end of the scan area 2000-04-29 * Adjusted scan area to the Windows driver defaults for ScanExpress 6000SP; added MUSTEK_FLAG_ENLARGE_X for this scanner * Added Warning for scanners that are not (fully) tested 2000-04-26 * changed sane_init to use sanei_config_read () and sanei_config_get_string () 2000-04-24 * released backend version 1.0-80 2000-04-23 * fixed lineart and color scanning >600 dpi for the SE 12000SP * added variable debug_level to be faster without debugging in attach () * fixed bug in mustek.conf handling; positional options were applied to the first device only * added an option to mustek.conf: "buffersize". This overwrites the default scan buffer sizes. The unit is kilobytes. * adjusted mustek.conf to more reasonable defaults * update manpage and mustek.desc to reflect the changes 2000-04-22 * fixed greyscale scanning >600 dpi for the SE 12000SP 2000-04-21 * added more debug output to sane_get_parameters 2000-04-20 * Output of scanning time now works with scanimage, too. * Adjusted scan area to the Windows driver defaults for Paragon MFS-6000CX * Added transparency adapter support for the Paragon MFS-6000CX and MFS-12000SP 2000-04-19 * Adjusted scan area to the Windows driver defaults for Paragon MFS-12000SP 2000-04-17 * added support for the sanei_scsi_open_extended method with variable buffersizes * removed support for SCSI queue. Couldn't find improvements for any scanner 2000-04-16 * removed "color lineart" and "color halftone" for single pass scanners. These modes didn't work for any of my scanners. * fixed problems in color mode for the MFS-8000SP (gamma table is now uploaded even if not selected) * Output "cover open" only for ScanExpress scanners (Paragon scanners don't have a cover sensor) * Added transparency adapter support for the Paragon MFS-6000SP and MFS-12000CX * Added output of transfer speed (kb/s) * maximum allocated memory for read request can be set by a #define * buffer size can be set on a per scanner basis * Adjusted scan area to the Windows driver defaults for Paragon 800 II SP * Added quotation marks to inquiry output 2000-04-15 * Adjusted scan area to the Windows driver defaults for Paragon 8000SP, ScanExpress 12000SP * Fixed scan area settings (TL-X and TL-Y) for transparency adapter (TA) * Added TA support for Paragon 8000SP 2000-04-13 * Added more debug output in sane_read and some other functions * removed warnings 2000-04-12 * Added more debug output concerning buffer handling 2000-04-10 * Adjusted scan area to the Windows driver defaults for Paragon 12000CX, 6000SP, 600 II CD, 600 II N 2000-04-09 * released backend version 1.0-79 2000-04-08 * added output of scanning time (debuglevel 2 and higher) * removed old code from sane_cancel 2000-04-07 * fixed line-distance correction for the 600 II N * rewrite of the 600 II N code * documentation update for the 600 II N 2000-04-06 * Rewrite of resolution encoding for 3-pass scanners * added more comments * some spelling errors corrected 2000-04-03 * output backend and version information * fixed resolution encoding for MFS12000cx * Changed version system to be compatible to the SANE standard (major, minor, build); 0.78 --> 1.0-78 2000-04-02 * released backend version 0.78 * added MUSTEK_FLAG_DOUBLE_RES for the MFS-12000CX 3-pass scanner, resolutions > 600 dpi should work now 2000-04-01 * reduced scan area for Paragon 800 S / II SP 2000-03-29 * released backend version 0.77 * inquiry is printed in full text at debug level 4 * more debug level tweaking * man page update * model name update 2000-03-25 * corrected some spelling errors 2000-03-24 * reduced scanarea for the MSF-6000SP * restructured scanner recognition 2000-03-18 * released backend version 0.76 2000-03-17 * removed some compiler warnings * changed the sane.model names (e.g. ScanExpress 12000SP instead of C06IDW...) * added SCSI information output to inquiry * adjusted debug levels and debug output 2000-03-15 * fixed typo in man page 2000-03-12 * released backend version 0.75 * man page update * mustek.desc update * test for option < 0 in sane_get_option_descriptor (thanks to Oliver Rauch) * added do_stop in sane_cancel (don't wait for next read that will possibly never happen) * fixed firmware version identification for newer ScanExpress models (patch from Marco G. Salvagno) * probably fixed linedistance correction at high resolutions for MFS-1200SP firmware 1.00 and possibly others (patch from Andreas Beck) * added check for ADF ready in sane_start (patch from Joerg Anders) * Bug fix in the STORE makros (patch from Norbert Mueller) 2000-03-06 * created mustek.CHANGES file * released backend version 0.74 * added linedistance correction for the 600 II N + documentation updates * added detection of newer ScanExpress models ("XC06" instead og " C06") * bugfix for 600 II N waiting 60 s before cancelling Henning Meier-Geinitz sane-backends-1.0.27/doc/sane-epson.man0000664000175000017500000002701213106201017014525 00000000000000.TH sane\-epson 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-epson .SH NAME sane\-epson \- SANE backend for EPSON scanners .SH DESCRIPTION The .B sane\-epson library implements a SANE (Scanner Access Now Easy) backend that provides access to Epson flatbed scanners. Some functions of this backend should be considered .B beta-quality software! Most functions have been stable for a long time, but of course new development can not and often times will not function properly from the very first day. Please report any strange behavior to the maintainer of the backend. .PP At present, the following scanners are known to work with this backend: .PP .RS .ft CR .nf Model: Connection Type --------------------------- ------------------- GT-5000 SCSI, parallel GT-6000 parallel GT-6500 SCSI (use only the line "scsi" in epson.conf) ActionScanner II SCSI, parallel GT-7000 SCSI Perfection 636 SCSI Perfection 636U USB Perfection 610 USB Perfection 640 USB Perfection 1200S SCSI Perfection 1200U USB Perfection 1240 USB, SCSI Perfection 1640 USB, SCSI Perfection 1650 USB Perfection 1660 USB Perfection 2400 USB Perfection 2450 USB, IEEE-1394 Expression 636 / GT-9500 SCSI Expression 1600 USB, SCSI, IEEE-1394 Expression 1680 USB, SCSI, IEEE-1394 CX-3200 USB CX-5200 USB .fi .ft R and many more. The official list is on the Sane web site. .RE For other scanners the software may or may not work. Please send mail to the backend author (khk@khk.net) to report success with scanners not on the list or problems with scanners that are listed. .SH OPTIONS The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in programs like xscanimage or xsane. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d epson .RE Not all devices support all options. .TP .I Scan Mode The .I \-\-mode switch selects the basic mode of operation of the scanner. Valid choices are Binary, Gray and Color. The Binary mode is black and white only, Gray will produce 256 levels of gray or more depending on the scanner and Color means 24 bit color mode or more depending on the scanner. Some scanners will internally use 36 bit color, their external interface however may only support 24 bits. The .I \-\-depth option selects the bit depth the scanner is using. This option is only available for scanners that support more than one bit depth. Older scanners will always transfer the image in 8bit mode. Newer scanners allow one to select either 8 bits, 12 or 14 bits per color channel. For a color scan this means an effective color depth of 36 or 42 bits over all three channels. The valid choices depend on the scanner model. The .I \-\-halftoning switch selects the mode that is used in Binary mode. Valid options are "None", "Halftone A (Hard Tone)", "Halftone B (Soft Tone)", "Halftone C (Net Screen)", "Dither A (4x4 Bayer)", "Dither B (4x4 Spiral)", "Dither C (4x4 Net Screen)", "Dither D (8x4 Net Screen)", "Text Enhanced Technology", "Download pattern A", and "Download pattern B". The .I \-\-dropout switch selects the so called dropout color. Valid options are None, Red, Green and Blue. The default is None. The dropout color is used for monochrome scanning and selects the color that is not scanned. This can be used to e.g. scan an original with a colored background. The .I \-\-brightness switch controls the brightness of the scan. Valid options are integer values from \-3 to 3. The default is 0. The larger the brightness value, the brighter the image gets. If a user defined table for the gamma correction is selected, the brightness parameter is not available. The .I \-\-sharpness switch sets the sharpness of the image data. Valid options are integer values from \-2 to 2, with \-2 meaning "Defocus", \-1 "Defocus slightly", 0 "Normal", 1 "Sharpen slightly" and 2 "Sharpen". The .I \-\-gamma\-correction switch controls the scanner's internal gamma correction. Valid options are "Default", "User defined", "High density printing" "Low density printing" and "High contrast printing". The .I \-\-color\-correction switch controls the scanner's internal color correction function. Valid options are "No Correction", "Impact\-dot printers", "Thermal printers", "Ink\-jet printers" and "CRT monitors". The default is "CRT monitors". The .I \-\-resolution switch selects the resolution for a scan. Some EPSON scanners will scan in any resolution between the lowest and highest possible value. The list reported by the scanner can be displayed using the "\-\-help \-d epson" parameters to scanimage. The .I \-\-mirror option controls the way the image is scanned. By reading the image data from right to left the image is mirrored. Valid options are "yes" and "no". The default is "no". The .I \-\-speed option can improve the scan speed in monochrome mode. Valid options are "yes" or "no", the "yes" option will speed up the scan if this option is supported. The .I \-\-auto\-area\-segmentation switch activates the automatic area segmentation for monochrome scans. The scanner will try to determine which areas are text and which contain images. The image areas will be halftoned, and the text will be improved. Valid options are "yes" and "no". The default is "yes". The .I \-\-gamma\-table parameter can be used to download a user defined gamma table. The option takes 256 values from the range 0-255. In color mode this option equally affects the red, green, and blue channel. The .I \-\-red\-gamma\-table parameter can be used to download a user defined gamma table for the red channel. The valid options are the same as for \-\-gamma\-table. The .I \-\-green\-gamma\-table parameter can be used to download a user defined gamma table for the green channel. The valid options are the same as for \-\-gamma\-table. The .I \-\-blue\-gamma\-table parameter can be used to download a user defined gamma table for the blue channel. The valid options are the same as for \-\-gamma\-table. The color correction coefficients .I \-\-cct\-1 \-\-cct\-2 \-\-cct\-3 ... \-\-cct\-9 will install color correction coefficients for the user defined color correction. Values are specified as integers in the range \-127..127. The .I \-\-preview option requests a preview scan. The frontend software automatically selects a low resolution. Valid options are "yes" and "no". The default is "no". The .I \-\-preview\-speed options will increase the scan speed if this is supported by the scanner. Valid options are "yes" and "no", the default is "no". The geometry options .I \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters. The .I \-\-quick\-format option lets the user select a scan area with predefined sizes. Valid parameters are "CD", "A5 portrait", "A5 landscape", "Letter", "A4" and "max". The default is "max", which selects the largest possible area. The .I \-\-source option selects the scan source. Valid options depend on the installed options. The default is "Flatbed". The .I \-\-auto\-eject option will eject a page after scanning from the document feeder. The .I \-\-film\-type option will select the film type for scans with the transparency unit. This option is only activated if the TPU is selected as scan source. Valid options are "Negative Film" and "Positive Film". The .I \-\-focus\-position option selects the focus position for all scans. Valid options are "Focus 2.5mm above glass" and "Focus on glass". The focus on the 2.5mm point above the glass is necessary for scans with the transparency unit, so that the scanner can focus on the film if one of the film holders is used. This option is only functional for selected scanners, all other scanners will ignore this option. .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/epson.conf specifies the device(s) that the backend will use. Possible connection types are: .TP .I SCSI This is the default, and if nothing else is specified the backend software will open a given path as SCSI device. More information about valid syntax for SCSI devices can be found in sane\-scsi(5). .br Usually SCSI scanners are configured with a line "scsi EPSON" in this file. In some cases it may be necessary to only use the string "scsi" (e.g. for the GT-6500). .TP .I PIO \- Parallel Interface The parallel interface can be configured in two ways: An integer value starting at the beginning of a line will be interpreted as the IO address of the parallel port. To make it clearer that a configured IO address is a parallel port the port address can be preceded by the string "PIO". The PIO connection does not use a special device file in the /dev directory. The IO address can be specified in hex mode (prefixed with "0x"). .TP .I USB A device file that is preceded by the string "USB" is treated as a scanner connected via the Universal Serial Bus. The correct special device file has to be created prior to using it with Sane. See the USB documentation for more information about how to set up the USB subsystem and the required device files. .SH FILES .TP .I @LIBDIR@/libsane\-epson.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-epson.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_EPSON If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .TP .B SANE_DEBUG_EPSON_SCSI If the library was compiled with debug support enabled, this environment variable controls the SCSI related debug level for this backend. Only a value of 2 is supported. .TP .B SANE_EPSON_CMD_LVL This allows one to override the function or command level that the backend uses to communicate with the scanner. The function level a scanner supports is determined during the initialization of the device. If the backend does not recognize the function level reported by the scanner it will default to function level B3. Valid function levels are A1, A2, B1, B2, B3, B4, B5, B6, B7, B8, D1 and F5. Use this feature only if you know what you are doing! .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1) .SH BUGS None :-) At least none are currently known. .SH UNSUPPORTED DEVICES The backend may be used with Epson scanners that are not yet listed under the list of supported devices. A scanner that is not recognized may default to the function level B3, which means that not all functions that the scanner may be capable of are accessible. If the scanner is not even recognized as an Epson scanner this is probably because the device name reported by the scanner is not in the correct format. Please send this information to the backend maintainer (email address is in the AUTHOR section of this man page or in the AUTHORS file of the SANE distribution). The Perfection 600, Perfection 650, Perfection 660, Perfection 1250 and Perfection 1260 are not supported by this backend. .SH AUTHOR The package is actively maintained by Karl Heinz Kremer (khk@khk.net). The software is based on work by Christian Bucher and Kazuhiro Sasayama sane-backends-1.0.27/doc/matsushita/0000775000175000017500000000000013110600532014220 500000000000000sane-backends-1.0.27/doc/matsushita/matsushita.txt0000664000175000017500000001203312112021330017054 00000000000000Made by Kyushu Matsushita Electric, a.k.a. Panasonic http://www.kme.panasonic.co.jp/ http://panasonic.com/ The same twain driver handle these scanners: Same family as KV-SS25, KV-SS50, KV-SS55, KV-SS50EX, KV-SS55EX, KV-SS850, KV-SS855. Another driver handle the KV-S2055L, KV-S2055W. However all these scanner show similarities. /*--------------------------------------------------------------------------*/ SCSI commands supported by the KV-SS25: TEST UNIT READY: 00 00 00 00 00 00 REQUEST SENSE: 03 00 00 00 0E 00 a return after a short read is: f0 00 60 00 00 00 02 0a 00 00 00 00 00 00 00 00 a return after a jam (sure?) f0 00 03 00 00 00 00 0a 00 00 00 00 80 01 00 00 no paper f0 00 03 00 00 00 00 0a 00 00 00 00 3a 00 00 00 jam door open: f0 00 02 00 00 00 00 0a 00 00 00 00 04 81 00 00 paper jam f0 00 03 00 00 00 00 0a 00 00 00 00 80 04 00 00 after a power cycle f0 00 06 00 00 00 00 0a 00 00 00 00 29 00 00 00 after ???? f0 00 05 00 00 00 00 0a 00 00 00 00 2c 02 00 00 out of memory (scan data too big for scanner) f0 00 05 00 00 00 00 0a 00 00 00 00 2c 80 00 00 INQUIRY: 12 00 00 00 60 00 result: 06 00 02 02 5B 00 00 10 4B 2E 4D 2E 45 2E 20 20 4B 56 2D 53 53 32 35 41 20 20 20 20 20 20 20 20 31 2E 30 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 SET WINDOWS: 24 00 00 00 00 00 00 00 00 00 reset (?) 24 00 00 00 00 00 00 00 48 00 72 bytes. 6-7 = 0x40 = window descriptor length Window Descriptor Block: 0 = page side 0x00 = front 0x80 = back 2-3 = X resolution 4-5 = Y Resolution 14-17 = width (size in inches * 1200) 18-21 = length (size in inches * 1200) 22 = 255 - brightness 23 = same as 22 24 = contrast 25 = image composition 0x00 = black&white (1 bit) 0x01 = black&white with halftone pattern 0x02 = grayscale 26 = bits/pixel 0x01, if image comp == 0 0x04, if image comp == (0x01 || 0x02) -> grayscale 4 bits 0x08, if image comp == 0x02 -> grayscale 8 bits 28 = haltone pattern 0x00 = Bayer 64 0x01 = Bayer 16 0x02 = Dot 32 0x03 = Dot 64 0x04 = Error diffusion 0x80 = User downloaded pattern 29 = reverse image 0x00 = no reverse 0x80 = reverse 43 = image emphasis 0x80 smooth 0x00 none 0x01 low 0x30 medium (twain default) 0x50 high 44 = gamma (Gray 4/8 only) 0x00 normal 0x01 from CRT 0x80 gamma table 0 (previously downloaded) 0x81 gamma table 1 (previously downloaded) 0x82 gamma table 2 (previously downloaded) 0x83 gamma table 3 (previously downloaded) 47 = ? (only used by the ISIS driver) bit 7 = ? set by the ISIS driver bit 6 = length control bit 2 = ? set by the ISIS driver bit 1 = ? set by the ISIS driver 48-51 = width (again?, maybe paper size) 52-55 = length (again?, maybe paper size) 57 = feeder mode 0x00 = one page other = number of pages to read (TWAIN driver defaults to 0xff) 58 = auto threshold 0x00 = none (twain default) 0x80 = mode 1 0x81 = mode 2 0x82 = mode 3 59 = automatic separation 0x00 = no (twain default) 0x80 = yes 60 = white level 0x00 = from white stick (twain default) 0x80 = from paper 0x81 = automatic 61 = noise reduction 0x00 = none (twain default) 0x01 = 1x1 0x02 = 2x2 0x03 = 3x3 0x04 = 4x4 0x05 = 5x5 READ: 28 00 80 00 00 00 00 00 10 00 28 00 00 00 00 00 00 80 00 00 2 = data type code 0x00 image data The TWAIN driver always reads 0x8000 bytes at the time, except for the last packet where it read the size left plus 2 more bytes (and thus generating a check condition). 5: page side 0x00 = front 0x80 = back 0x80 image size in dots 3(?)-4: number of the page to read. Multipage mode. returns 16 bytes: 0-3: length in pixels 4-7: width in lines SEND(10): 2A 00 03 00 00 01 00 01 0A 00 2 = data type code 0x02 = halftone pattern data is 10 bytes of header + 64 bytes for the matrix 0x03 = gamma table data is 10 bytes of header + 256 bytes for the table 5 = gamma table number (data type code is 2) the scanner can store 4 gamma tables (from 0 to 3) 7-8 = length SET AREA (?) C0 00 00 00 00 00 00 00 58 00 Total message length = 88 bytes 7 = length -> 0x40 = 64 bytes 14-17 = area 1 X 18-21 = area 1 Y 22-25 = area 1 width 26-29 = area 1 length 33 = image composition 1 = halftone 36 = haltone pattern (if image composition == 1) 0x00 = Bayer 64 0x01 = Bayer 16 0x02 = Dot 32 0x03 = Dot 64 0x04 = Error diffusion 50-53 = area 2 X 54-57 = area 2 Y 58-61 = area 2 width 62-65 = area 2 length 68-71 = area 3 X 72-75 = area 3 Y 76-79 = area 3 width 80-83 = area 3 length Other supported commands: 16 RESERVE UNIT 17 RELEASE UNIT 1D SEND DIAGNOSTIC 31 OBJECT POSITION 3B WRITE BUFFER sane-backends-1.0.27/doc/figs/0000775000175000017500000000000013110600532012766 500000000000000sane-backends-1.0.27/doc/figs/image-data.fig0000664000175000017500000000451312112021330015363 00000000000000#FIG 3.1 Portrait Center Inches 1200 2 6 1725 450 5925 1650 6 1800 975 3150 1350 2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 1800 1200 3150 1200 3150 1350 1800 1350 1800 1200 4 0 -1 0 0 16 12 0.0000 4 135 1260 1875 1125 7 6 5 4 3 2 1 0\001 -6 6 3150 975 4500 1350 2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 3150 1200 4500 1200 4500 1350 3150 1350 3150 1200 4 0 -1 0 0 16 12 0.0000 4 135 1260 3225 1125 7 6 5 4 3 2 1 0\001 -6 6 4500 975 5850 1350 2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 4500 1200 5850 1200 5850 1350 4500 1350 4500 1200 4 0 -1 0 0 16 12 0.0000 4 135 1260 4575 1125 7 6 5 4 3 2 1 0\001 -6 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 1800 1200 5850 1200 5850 1350 1800 1350 1800 1200 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 7 1800 900 1950 825 3750 825 3825 750 3900 825 5700 825 5850 900 4 0 -1 0 0 16 12 0.0000 4 105 60 2475 1575 r\001 4 1 -1 0 0 16 12 0.0000 4 150 105 3825 1575 g\001 4 1 -1 0 0 16 12 0.0000 4 135 105 5175 1575 b\001 4 1 -1 0 0 16 12 0.0000 4 180 555 3825 600 pixel 0\001 -6 6 5850 975 7200 1350 2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 5850 1200 7200 1200 7200 1350 5850 1350 5850 1200 4 0 -1 0 0 16 12 0.0000 4 135 1260 5925 1125 7 6 5 4 3 2 1 0\001 -6 6 7200 975 8550 1350 2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 7200 1200 8550 1200 8550 1350 7200 1350 7200 1200 4 0 -1 0 0 16 12 0.0000 4 135 1260 7275 1125 7 6 5 4 3 2 1 0\001 -6 6 8550 975 9900 1350 2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 8550 1200 9900 1200 9900 1350 8550 1350 8550 1200 4 0 -1 0 0 16 12 0.0000 4 135 1260 8625 1125 7 6 5 4 3 2 1 0\001 -6 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 5850 1200 9900 1200 9900 1350 5850 1350 5850 1200 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 7 5850 900 6000 825 7800 825 7875 750 7950 825 9750 825 9900 900 4 0 -1 0 0 16 12 0.0000 4 105 60 6525 1575 r\001 4 1 -1 0 0 16 12 0.0000 4 150 105 7875 1575 g\001 4 1 -1 0 0 16 12 0.0000 4 135 105 9225 1575 b\001 4 1 -1 0 0 16 12 0.0000 4 180 555 7875 600 pixel 1\001 4 1 -1 0 0 16 12 0.0000 4 180 525 9225 1950 byte 5\001 4 1 -1 0 0 16 12 0.0000 4 180 525 7875 1950 byte 4\001 4 1 -1 0 0 16 12 0.0000 4 180 525 6525 1950 byte 3\001 4 1 -1 0 0 16 12 0.0000 4 180 525 5175 1950 byte 2\001 4 1 -1 0 0 16 12 0.0000 4 180 465 3825 1950 byte1\001 4 1 -1 0 0 16 12 0.0000 4 180 465 2475 1950 byte0\001 4 1 -1 0 0 16 12 0.0000 4 15 180 10050 1275 ....\001 4 2 -1 0 0 16 12 0.0000 4 135 240 1725 1125 bit:\001 sane-backends-1.0.27/doc/figs/xfer.fig0000664000175000017500000000140712112021330014335 00000000000000#FIG 3.1 Portrait Center Inches 1200 2 6 2325 3150 8175 3750 2 1 0 2 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 2 1 2.00 120.00 240.00 2400 3300 8100 3300 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 2 1 2.00 120.00 240.00 8100 3375 2400 3675 -6 6 2325 3600 8175 4200 2 1 0 2 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 2 1 2.00 120.00 240.00 2400 3750 8100 3750 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 2 1 2.00 120.00 240.00 8100 3825 2400 4125 -6 2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 2250 3150 8250 3150 8250 6150 2250 6150 2250 3150 2 1 0 2 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 2 1 2.00 120.00 240.00 2400 4200 8100 4200 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 2 1 2.00 120.00 240.00 8100 4275 2400 4575 2 1 0 2 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 2 1 2.00 120.00 240.00 2400 4650 8100 4650 sane-backends-1.0.27/doc/figs/area.fig0000664000175000017500000000211112112021330014272 00000000000000#FIG 3.1 Portrait Center Inches 1200 2 6 1650 1650 1800 1800 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 1725 1650 1725 1800 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 1650 1725 1800 1725 -6 6 3300 2700 3450 2850 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 3375 2700 3375 2850 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 3300 2775 3450 2775 -6 6 1725 1725 3375 2775 2 2 0 0 7 7 10 0 18 0.000 0 0 -1 0 0 5 1725 1725 3375 1725 3375 2775 1725 2775 1725 1725 4 1 -1 10 0 16 12 0.0000 4 105 840 2550 2302 scan area\001 -6 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 1200 675 4275 675 4275 3375 1200 3375 1200 675 2 1 0 1 -1 7 10 0 16 0.000 0 0 -1 1 0 2 2 1 1.00 60.00 120.00 1200 525 1200 3825 2 1 0 1 -1 7 10 0 16 0.000 0 0 -1 1 0 2 2 1 1.00 60.00 120.00 1050 675 4650 675 4 1 -1 10 0 16 12 0.0000 4 180 1020 3375 3150 bottom-right\001 4 1 -1 10 0 16 12 0.0000 4 180 615 1725 1500 top-left\001 4 1 -1 10 0 16 12 0.0000 4 135 1080 2700 1050 scan surface\001 4 1 -1 10 0 16 12 0.0000 4 150 105 1050 3600 y\001 4 1 -1 10 0 16 12 0.0000 4 105 90 4425 525 x\001 4 1 -1 10 0 16 12 0.0000 4 135 105 1080 585 0\001 sane-backends-1.0.27/doc/figs/flow.fig0000664000175000017500000000376412112021330014350 00000000000000#FIG 3.1 Portrait Center Inches 1200 2 6 4200 7305 9945 7575 4 0 -1 0 0 17 18 0.0000 4 270 1500 4200 7515 - go back to\001 4 0 -1 0 0 16 18 0.0000 4 270 1440 5775 7515 sane_start()\001 4 0 -1 0 0 17 18 0.0000 4 210 2670 7275 7515 if more frames desired\001 -6 2 2 0 1 -1 7 10 0 19 0.000 0 0 -1 0 0 5 2700 600 10200 600 10200 9600 2700 9600 2700 600 2 2 0 1 -1 7 8 0 18 0.000 0 0 -1 0 0 5 3300 2400 10200 2400 10200 8925 3300 8925 3300 2400 2 2 0 1 -1 7 8 0 17 0.000 0 0 -1 0 0 5 3900 2925 10200 2925 10200 4650 3900 4650 3900 2925 2 2 0 1 -1 7 8 0 17 0.000 0 0 -1 0 0 5 3900 4800 10200 4800 10200 8250 3900 8250 3900 4800 2 1 0 1 -1 7 8 0 -1 0.000 0 0 -1 0 0 4 10350 3000 10425 3075 10425 4500 10350 4575 2 1 0 1 -1 7 8 0 -1 0.000 0 0 -1 0 0 4 10350 4875 10425 4950 10425 8100 10350 8175 4 0 -1 0 0 17 18 0.0000 4 150 735 4200 3300 - use:\001 4 0 -1 0 0 16 18 0.0000 4 270 1680 4200 5100 - sane_start()\001 4 0 -1 0 0 17 18 0.0000 4 270 4950 4500 4500 repeatedly to configure device as desired\001 4 0 -1 0 0 16 18 0.0000 4 270 2715 5400 4080 sane_control_option()\001 4 0 -1 0 0 16 18 0.0000 4 270 3660 5400 3600 sane_get_option_descriptor()\001 4 0 -1 0 0 17 18 0.0000 4 150 735 4200 5700 - use:\001 4 0 -1 0 0 17 18 0.0000 4 270 4080 4500 6900 repeatedly until read returns EOF\001 4 0 -1 0 0 16 18 0.0000 4 270 2805 5400 6000 sane_get_parameters()\001 4 0 -1 0 0 16 18 0.0000 4 270 1440 5400 6450 sane_read()\001 4 0 -1 0 0 16 18 0.0000 4 270 1935 4200 8100 - sane_cancel()\001 4 0 -1 0 0 16 18 0.0000 4 270 1500 3000 1200 - sane_init()\001 4 0 -1 0 0 16 18 0.0000 4 270 1590 3000 9300 - sane_exit()\001 4 0 -1 0 0 17 18 0.0000 4 270 4845 3600 1800 - pick desired device, possibly by using\001 4 0 -1 0 0 16 18 0.0000 4 270 1770 3600 2700 - sane_open()\001 4 0 -1 0 0 16 18 0.0000 4 270 1800 3600 8700 - sane_close()\001 4 0 -1 0 0 16 18 0.0000 4 270 2415 4800 2175 sane_get_devices()\001 4 0 -1 8 0 17 18 0.0000 4 270 2070 10575 6600 image acquisition\001 4 0 -1 8 0 17 18 0.0000 4 270 1500 10575 3825 device setup\001 sane-backends-1.0.27/doc/figs/hierarchy.fig0000664000175000017500000000605412112021330015352 00000000000000#FIG 3.1 Landscape Center Inches 1200 2 6 10500 4500 12300 5400 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 10650 4785 12150 4785 12150 5385 10650 5385 10650 4785 4 1 -1 0 0 16 18 0.0000 4 210 660 11399 5182 qcam\001 -6 6 7200 4500 9000 5400 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 7350 4785 8850 4785 8850 5385 7350 5385 7350 4785 4 1 -1 0 0 16 18 0.0000 4 270 315 8099 5182 hp\001 -6 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 2250 1185 3750 1185 3750 1785 2250 1785 2250 1185 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 450 2985 1950 2985 1950 3585 450 3585 450 2985 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 2250 2985 3750 2985 3750 3585 2250 3585 2250 2985 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 4050 2985 5550 2985 5550 3585 4050 3585 4050 2985 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 8850 1185 10350 1185 10350 1785 8850 1785 8850 1185 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 2700 1800 1200 3000 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 3000 1800 3000 3000 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 3300 1800 4800 3000 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 9600 1800 9600 2100 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 9450 2700 8100 4800 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 11400 4200 11400 4800 2 2 0 0 0 0 10 0 2 0.000 0 0 -1 0 0 5 5700 3825 300 3825 300 300 5700 300 5700 3825 2 2 0 0 0 0 10 0 2 0.000 0 0 -1 0 0 5 12300 5550 7200 5550 7200 300 12300 300 12300 5550 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 1200 3600 1200 4200 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 3000 3600 3000 4125 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 7875 5400 7350 5850 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 8250 5400 8775 5850 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 11475 5400 11475 5850 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 8850 2100 10350 2100 10350 2700 8850 2700 8850 2100 2 2 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 10650 3600 12150 3600 12150 4200 10650 4200 10650 3600 2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 9750 2700 11400 3600 3 2 0 1 -1 7 0 0 -1 0.000 0 0 0 7 4800 3600 4275 4500 5025 5475 6150 4575 6525 1350 9450 900 9600 1200 0.00 0.00 4390.23 4024.37 4258.98 4249.38 4300.21 4894.51 4554.60 5418.20 5575.94 5541.53 5962.09 4914.18 6573.46 3810.63 5758.15 2145.68 7223.99 624.74 8573.68 446.85 9524.49 938.52 9561.99 1013.52 0.00 0.00 4 1 -1 0 0 16 18 0.0000 4 210 525 1199 3382 pnm\001 4 1 -1 0 0 16 18 0.0000 4 210 870 2999 3382 mustek\001 4 1 -1 0 0 17 14 0.0000 4 210 855 1200 4425 pnm files\001 4 1 -1 0 0 17 14 0.0000 4 120 765 3000 4380 scanner\001 4 1 -1 0 0 17 14 0.0000 4 150 945 7350 6165 scanner 1\001 4 1 -1 0 0 17 14 0.0000 4 150 945 8925 6165 scanner 2\001 4 1 -1 0 0 17 14 0.0000 4 165 1290 11475 6135 video camera\001 4 1 -1 0 0 17 14 0.0000 4 165 1035 3000 600 machine A\001 4 1 -1 0 0 17 14 0.0000 4 165 1020 9600 630 machine B\001 4 1 -1 0 0 17 14 0.0000 4 165 1860 4725 5850 network connection\001 4 1 -1 0 0 16 18 0.0000 4 210 285 2999 1582 dll\001 4 1 -1 0 0 16 18 0.0000 4 195 390 4799 3382 net\001 4 1 -1 0 0 16 18 0.0000 4 210 735 9599 1582 saned\001 4 1 -1 0 0 16 18 0.0000 4 210 285 9599 2482 dll\001 4 1 -1 0 0 16 18 0.0000 4 210 960 11399 3982 autolum\001 sane-backends-1.0.27/doc/sane-mustek_usb2.man0000664000175000017500000000510412112021330015634 00000000000000.TH sane\-mustek_usb2 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-mustek_usb2 .SH NAME sane\-mustek_usb2 \- SANE backend for SQ113 based USB flatbed scanners .SH DESCRIPTION The .B sane\-mustek_usb2 library implements a SANE (Scanner Access Now Easy) backend that provides access to USB flatbed scanners based on the Service & Quality SQ113 chipset. At the moment, only the Mustek BearPaw 2448 TA Pro is supported. It's planned to add support for other scanners that are based on the SQ113 and maybe SQ11 chip. For more details, see the mustek_usb2 backend homepage: .IR http://www.meier\-geinitz.de/sane/mustek_usb2\-backend/ . .PP This is BETA software. Especially if you test new or untested scanners, keep your hand at the scanner's plug and unplug it, if the head bumps at the end of the scan area. .PP If you own a scanner other than the ones listed on the mustek_usb2 homepage that works with this backend, please let me know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .I sane\-find\-scanner or syslog) to me. Even if the scanner's name is only slightly different from the models already listed as supported, please let me know. .PP .SH LIBUSB ISSUES Please use libusb-0.1.8 or later. Without libusb or with older libusb versions all kinds of trouble can be expected. The scanner should be found by sane\-find\-scanner without further actions. For setting permissions and general USB information looks at .BR sane\-usb (5). .PP .SH FILES .TP .I @LIBDIR@/libsane\-mustek_usb2.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-mustek_usb2.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_MUSTEK_USB2 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_MUSTEK_USB2=4 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .BR sane\-plustek (5), .BR sane\-ma1509 (5), .BR sane\-mustek_usb (5), .BR sane\-mustek (5), .BR sane\-mustek_pp (5) .br .I @DOCDIR@/mustek_usb2/mustek_usb2.CHANGES .br .I http://www.meier\-geinitz.de/sane/mustek_usb2\-backend/ .SH AUTHOR The driver has been written Roy Zhou, Jack Xu, and Vinci Cen from Mustek. Adjustments to SANE by Henning Meier-Geinitz. .SH BUGS Please contact me if you find a bug or missing feature: . Please send a debug log if your scanner isn't detected correctly (see SANE_DEBUG_MUSTEK_USB2 above). sane-backends-1.0.27/doc/icons/0000775000175000017500000000000013110600532013151 500000000000000sane-backends-1.0.27/doc/icons/up.gif0000664000175000017500000000022112112021330014171 00000000000000GIF89añ¿¿¿çççooo[!ù,bŒ©Ë­b€œ´Z `¸üæØ…Ò·‰!9 –zjé*¢KÑœ Øó>ô®ËÍX6 Lø¹vbmbl2§Ñ'’ºœ^}WLvÈå…½ QPYÉ%óík²àârMæŽÏëñ½ÿ/P;sane-backends-1.0.27/doc/icons/index.gif0000664000175000017500000000026412112021330014663 00000000000000GIF89a+ñ¿¿¿çççooo[!ù,+…Œ©Ëí—0 Ú‹³ÞVÌÀ…"çQãy– Ê’ß5°q ¨°Lׯ5Ÿ=kãUbƒ"ÌØ+¿^p8L ™³&”yyb·W+w[ÍoU¹¤b´á©÷w\Áå·¦]a_÷ç)ý«gƃt„Ç¥•Cƒ˜4ÇØhòز()¢â™©¹ÉÙ¹à*:Z;sane-backends-1.0.27/doc/icons/references_gr.gif0000664000175000017500000000036712112021330016371 00000000000000GIF87aQñ¿¿¿çççooo‚‚‚,QÐŒ©Ëí£œ´2a€Þ¼û†â8 X@¦êÊ~fÖÆò¬½(碽 þOò醞fÀ†ÄfíÔë0ASçШf{À¬ò7E~»[²Wy4ƒ9Øj˜ùM˽ÜùØÏ“›ö: Ç·¸Gh¨eˆÒ6xÖ•÷ç&øAù†Ð8˜HèévÙ)*‚ÆiéQ)åȪúÔ¥ˆ¨÷Y;i×y{ëxªøw¬%ìü˜d†eµ¼¢Ìü¼# =Í(M} ƒ½mcâý .>N^n~þ‚®¾ÎÞ^;sane-backends-1.0.27/doc/icons/up_gr.gif0000664000175000017500000000022112112021330014661 00000000000000GIF89añ¿¿¿çççooo‚‚‚!ù,bŒ©Ë­b€œ´Z `¸üæØ…Ò·‰!9 –zjé*¢KÑœ Øó>ô®ËÍX6 Lø¹vbmbl2§Ñ'’ºœ^}WLvÈå…½ QPYÉ%óík²àârMæŽÏëñ½ÿ/P;sane-backends-1.0.27/doc/icons/previous_gr.gif0000664000175000017500000000033412112021330016116 00000000000000GIF89a?ñ¿¿¿çççooo‚‚‚!ù,?­Œ©Ëí£œI€³Þ¼ûj‚„æ‰~ã•¶.¸–ïLq6äz ¼HÂir¿"æÖÛøŒ?$`)|J{»©ªÃ©ÄŒú\v­S­UM‚¡ß¬95£ã[0EÞâÜðrß5æô§WxE—øWeC˜—ö¨¦xÈæhyf¨ÉFf‰‡Y)ø¹'¸#ÆØˆÇÔ:ÈêÚê+ëHË4{[3Òëû ,N^n~þ‚®¾ÎÞ^;sane-backends-1.0.27/doc/icons/next_gr.gif0000664000175000017500000000025412112021330015221 00000000000000GIF89a%ñ¿¿¿çççooo‚‚‚!ù,%}Œ©Ëí¿„´Ú‹ó2èbÜ–ßè™êÖUö®bK ±+7€âûnÚõj:ËÍf#ú’”añùü)gŒy5Nq+÷Šdê¤]´˜ÍˆÏ^Ÿò’f›bj”ÛœÃXí¸L’£â$XBXrˆ¨¡¸8cÀ)9IYi`™©™Y;sane-backends-1.0.27/doc/sane-umax_pp.man0000664000175000017500000002100312775312262015064 00000000000000.TH "sane\-umax_pp" "5" "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-umax_pp .SH "NAME" sane\-umax_pp \- SANE backend for Umax Astra parallel port flatbed scanners .SH "DESCRIPTION" The .B sane\-umax_pp library implements a SANE (Scanner Access Now Easy) backend that provides access to Umax parallel port flatbed scanners. The following scanners work with this backend: .PP .RS Model: .br \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- .br Astra 610P .br Astra 1220P .br HP3200C .br Astra 1600P .br Astra 2000P .br Genius ColorPage-Life Pro .br .RE .PP This backend handles 75x75, 150x150, 300x300, 600x600 and 600x1200 for 1220P/1600P/2000P dpi scan resolutions, and 75x75, 150x150, 300x300 and 300x600 for 610P. In color and gray levels, there is a software lineart mode. .PP The new generation models share a newer version of the 610P ASIC embedded in an EPAT chip. Only parts such as CCD and ADC change from one to another. They even all reports being UMAX Astra 1220P via IEEE1284. There isn't software way to recognize them properly. Under windows, model is set by the driver installed, regardless of the hardware. .PP .TP .B EPP/ECP MODES ONLY The current version of the backend uses only EPP or ECP mode to communicate with the scanner. PS/2 mode isn't implemented. The 610P only use SPP. It is recommended that you set your parallel port to EPP in BIOS with the current version of this backend. You can leave it to ECP or ECP+EPP, but in this case you may not use ppdev but only direct hardware access if you have to use ECP. ECPEPP will only work if you use a 2.4 or 2.6 kernel with ppdev character device support. .PP This backend does support parport sharing only .I if you have a kernel with ppdev support. .I .PP Note that if you don't use the ppdev character device, the backend needs to run as root. To allow user access to the scanner run the backend through the network interface (See saned(8) and sane\-net(5)). A more relaxed solution (security wise) is to add suid bit to the frontend (See chmod(1)). The backend drop root privileges as soon as it can, right after gaining direct access to IO ports, which lessen risks when being root. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I port value .RE .PP Where \fBvalue\fR is : .RS .TP auto autodetect all parallel ports and probe them for scanner .TP safe\-auto autodetect all parallel ports and probe them for scanner, but does not try direct hardware access .TP /dev/ppi0 uses *BSD ppi device, depending on the number of available parallel port, you have to use /dev/ppi1, /dev/ppi2, ... .TP /dev/parport0 uses linux ppdev device, depending on the number of available parallel port, you have to use /dev/parport1, /dev/parport2, ... .TP 0x378 does direct hardware access on the given address. Usual values are 0x378, 0x278, 0x3BC In this case, you have to run the scanner as root (*BSD and linux), or with 'IOPL=yes' on OS/2 .PP .RE \fBNOTE:\fR in all cases, you must have sufficient privileges to get access to the chosen device or address. Depending on the security settings, devices may not be available for all users. You have to change permissions on the dev/ppi* or /dev/parport* devices. .PP .RE You can rename any device using the .PP .RS .I name devname .br .I model model .br .I vendor vendor .RE .PP options. These options apply to the last port option. .SH "CONFIGURATION" Please make sure to edit umax_pp.conf .B before you use the backend. .PP The contents of the .B umax_pp.conf file is a list of options and device names that correspond to Umax scanners. Empty lines and lines starting with a hash mark (#) are ignored. .PP The eight options supported are .BR red\-gain , .BR green\-gain , .BR blue\-gain , .BR red\-offset , .BR green\-offset , .BR blue\-offset , .BR astra , and .BR buffer . Options .B red\-gain , .B green\-gain and .B blue\-gain allow you to adjust the sensitivity of your scanner for the given color. Values range from 0 (lowest gain) to 15 (highest). If the advanced option "Gain" isn't checked in the frontend, the backend does automatic gain calibration, and do not use user provided values. .PP Options .B red\-offset , .B green\-offset and .B blue\-offset allow you to adjust the offset of your scanner for the given color. Values range from 0 (lowest offset) to 15 (highest). .PP Option .B astra allows you to change the model of your scanner. Current auto detection is based on side effects on scanning when using 1220P command set on other models, so it may fail on unknown hardware combination. Valid values are 610, 1220, 1600 and 2000. It is useful only when autodetection fails to detect properly your scanner model. If your scanner work properly but is reported wrongly, let it be that way. The only valid case to change the model is when your scanner produces "black" or "inverted" scans. In this case you can put the model. Be aware that it will prevent scanner model autodetection. .PP Option .B buffer allows you to change the size of the scan buffer. The size must be specified in bytes. The default value is 2 megabytes. Decreasing this value will improve the smoothness of progress bar in the frontend, but will stall the scan more often. .PP .SH "FILES" .TP .I @CONFIGDIR@/umax_pp.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-umax_pp.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-umax_pp.so The shared library implementing this backend (present on systems that support dynamic loading). .SH "ENVIRONMENT" .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_UMAX_PP If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .PP .RS .ft CR .nf level debug output \-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- 0 nothing 1 errors 2 warnings & minor errors 3 additional information 4 debug information 5 code flow (not supported yet) 6 special debug information .fi .ft R .RE .PP .TP .B SANE_DEBUG_UMAX_PP_LOW This variable sets the debug level for the SANE interface for the Umax ASIC. Note that enabling this will spam your terminal with some million lines of debug output. .PP .RS .ft CR .nf level debug output \-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- 0 nothing 1 errors 8 command blocks 16 detailed code flow 32 dump datafiles 255 everything .fi .ft R .RE .PP .PP .SH "SEE ALSO" sane(7), sane\-net(5), saned(8) .TP For latest bug fixes and information see .I http://umax1220p.sourceforge.net/ .SH "AUTHOR" St\['e]phane Voltz .SH "CREDITS" Support for the 610P has been made possible thank to an hardware donation by William Stuart. .SH "BUG REPORTS" If something doesn't work, please contact me. But I need some information about your scanner to be able to help you... .TP .I SANE version run "scanimage \-V" to determine this .TP .I the backend version and your scanner hardware run "SANE_DEBUG_UMAX_PP=255 scanimage \-L 2>log" as root. If you don't get any output from the umax_pp backend, make sure a line "umax_pp" is included into your @CONFIGDIR@/dll.conf. If your scanner isn't detected, make sure you've defined the right port address, or the correct device in your umax_pp.conf. .TP .I the name of your scanner/vendor also a worthy information. Please also include the optical resolution and lamp type of your scanner, both can be found in the manual of your scanner. .TP .I any further comments if you have comments about the documentation (what could be done better), or you think I should know something, please include it. sane-backends-1.0.27/doc/sane-sm3600.man0000664000175000017500000000436412112021330014330 00000000000000.TH sane\-sm3600 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-sm3600 .SH NAME sane\-sm3600 \- SANE backend for Microtek scanners with M011 USB chip .SH DESCRIPTION The .B sane\-sm3600 library implements a SANE (Scanner Access Now Easy) backend that provides access to some Microtek scanners with the Toshiba M011 custom USB chip. This backend should be considered alpha. .PP There are also backends for Microtek scanners with SCSI command set. Refer to sane\-microtek(5) and sane\-microtek2(5) for details. .PP At present, the following scanners are known positively to work with this backend: .PP .RS .ft CR .nf Vendor Product id: Remark: -------- -------------- ----------- Microtek ScanMaker 3600 all modes ok Microtek ScanMaker 3700 reported to work Microtek ScanMaker 3750 reported to work .fi .ft R .RE .PP If you own a Microtek scanner with the M011 chip other than the ones listed above, it may or may not work with SANE! .SH "FRONTEND OPTIONS" This backend dynamically enables the options for the frontend, that are supported by the scanner in dependence of the scanning-mode and other options. Not supported options are disabled. .PP The following options are supported by the Microtek2-driver: .PP Color, grayscale, halftone and lineart scans. .PP contrast, brightness, control, gamma correction. .SH "DEVICE NAMES" This backend does not support device names in a standardized form. .SH CONFIGURATION This backend does not support a configuration file right now. .SH FILES .TP .I @LIBDIR@/libsane\-sm3600.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-sm3600.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_SM3600 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. To see error messages on stderr set SANE_DEBUG_SM3600 to 1. .br E.g. just say: .br export SANE_DEBUG_SM3600=5 .SH "SEE ALSO" sane\-microtek2(5), http://sm3600.sourceforge.net .SH AUTHOR .br Marian Eichholz (eichholz@computer.org) .br Glenn Ramsey (glenn@componic.com) .br sane-backends-1.0.27/doc/sane-artec.man0000664000175000017500000001173012775277260014527 00000000000000.TH sane\-artec 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-artec .SH NAME sane\-artec \- SANE backend for Artec flatbed scanners .SH DESCRIPTION The .B sane\-artec library implements a SANE (Scanner Access Now Easy) backend that provides access to Artec/Ultima SCSI flatbed scanners. At present, the following scanners are known to work at least partially with this backend: .PP .RS * Artec A6000C .br * Artec A6000C PLUS .br * Artec ViewStation AT3 .br * BlackWidow BW4800SP (rebadged Artec AT3) .br * Artec ViewStation AT6 .br * Artec ViewStation AT12 .br * Artec AM12S .br * Plustek 19200S (rebadged Artec AM12S) .RE .PP Although this manual page is generally updated with each release, up-to-date information on new releases and extraneous helpful hints are available from the backend homepage: .br .br .RS .B http://www4.infi.net/~cpinkham/sane/ .RE .SH DOCUMENTATION .SH CONFIGURATION The contents of the .I artec.conf file are a list of device names that correspond to Artec scanners. Empty lines and lines starting with a hash mark (#) are ignored. See .I sane\-scsi(5) on details of what constitutes a valid device name. Sample file: .br .br .nf # artec.conf # # this is a comment. # # this line says search for any SCSI devices which are scanners and have # a vendor string of 'ULTIMA' scsi ULTIMA # # the next line forces the backend to assume the next scanner found has # the specified vendor string (useful for testing rebadged models). vendor ULTIMA # # the next line forces the backend to assume the next scanner found has # the specified model string (useful for testing rebadged models). model AT3 # # now a line that actually specifies a device. The backend is going to # assume this is an Artec/Ultima AT3 because we forced the vendor and # model above. /dev/scanner # # once we hit a scanner device line, the forced vendor and model # string are # 'forgotten', so the vendor and model for this next device will be # determined from the result of a SCSI inquiry. /dev/sge # .fi .SH SCSI ADAPTER TIPS Some Artec scanners come with an included SCSI adapter. If your scanner came with a DTC ISA scsi cards, you can probably use it with recent (>= 2.2.0) kernels using the generic NCR5380 support. You must pass the following boot argument to the kernel: "dtc3181e=0x2c0,0" .br I do not have any information on the PCI SCSI adapter included with some newer Artec scanners. .SH FILES .TP .I @CONFIGDIR@/artec.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-artec.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-artec.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi- colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working direc- tory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_ARTEC If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity: SANE_DEBUG_ARTEC values .ft CR .nf Number Remark \ 0 print important errors 1 print errors 2 print sense 3 print warnings 4 print scanner-inquiry 5 print information 6 print less important information 7 print major called procedures 8 print all called procedures 9 print procedure info/data messages 10 print called sane\-init-routines 11 print called sane\-procedures 12 print sane infos 13 print sane option-control messages \ 50 print verbose data/debug messages \ == 100 print software RGB calibration data == 101 print raw data from scanner to artec.data.raw file \ == 128 print out all messages .fi .ft R .PP Example: export SANE_DEBUG_ARTEC=13 .SH BUGS Known bugs in this release: A6000C+ users with firmware v1.92 or earlier have problems with the backend, the cause has not been determined. Sometimes the backend is not particularly robust, you can possibly lock up the SCSI bus (and/or machine) by not having patience enough when scanning. 3-channel gamma correction is not implemented and single-channel gamma correction is not totally working on models other than the AT3. .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHOR Chris Pinkham (cpinkham@corp.infi.net) sane-backends-1.0.27/doc/mustek_usb2/0000775000175000017500000000000013110600532014301 500000000000000sane-backends-1.0.27/doc/mustek_usb2/mustek_usb2.CHANGES0000664000175000017500000001231212112021330017447 00000000000000mustek_usb2.CHANGES -*-text-*- V 1.0-10 (2005-10-16) - Removed typedefs for DWORD, WORD and so on. Used int, unsigned short, ... directly in the code. V 1.0-9 (2005-10-02) - Removed global variables in mustek_usb2.c: Deleted the following variables (not necessary): m_bIsOpen Moved the following varaiables to Mustek_Scanner structure: m_bIsScanning m_bIsReading setpara getpara read_rows Scan_data_buf Scan_data_buf_start scan_buffer_len Used local variables instead: dpi_list; - Minor cleanups. - Fixed check for Scan_data_buf != NULL. - Moved check for Scan_data_buf to sane_close (). - Avoid typedef'ing to long int in mustek_usb2_asic.h. Used int instead. Fixed DBG messages accordingly. - Fixed some compilation warnings on 64 bit platforms. V 1.0-8 (2005-10-01) - Added/modified checks for libpthread in acinclude.m4/configure.in. Disable backend if it's not there. V 1.0-7 (2005-09-30) - Added usleep in Asic_ScanStop() to avoid freezes after cancellation of a scan. - Added sane_constrain_value call in sane_control_option(). - Test with tstbackend succeeded this. - Changed usage of perror to DBG. - Removed _Open and _Close. These functions didn't do much at all. - Removed (commented out) code that tries to read values from config file. V 1.0-6 (2005-09-29) - Commented out unused code. - Made all symbols that don't belong to the SANE API static. - Changed all fprintfs to DBG messages. - Used real device name. Used real model name. - Added manual page (sane-mustek_usb2). - Fixed backend name in AUTHORS. V 1.0-5 (2005-09-28) - Merged all asic-related code into mustek_usb2_asic.c and .h. - Merged function definitions from mustek_usb2_tarnsparent.h and mustek_usb2_refelective.h to their respective .c files. Filename changes are finished now. - Moved defines used in mustek_usb2_high.c to moustek_usb_high.h. - All license/comment headers name the right scanner now. - Fixed "already included check" of header files - Used indent -gnu on all files. - Fixed compilation warnings and several bugs ("=" instead of "==" and similar stuff) in mustek_usb2_asic.c, mustek_usb2_transparent.c, mustek_usb2_reflective.c, mustek_usb2_high.c, mustek_usb2.c. V 1.0-4 (2005-09-27) - Changed filenames (preliminary, may be changed again): mustek_a2nu2.c --> mustek_usb2.c mustek_a2nu2.h --> mustek_usb2.h a2nu2/spicall/MustScanner.c --> mustek_usb2_high.c a2nu2/spicall/MustScanner.h --> mustek_usb2_high.h a2nu2/spicall/ScannerDefine.h --> included in mustek_usb2_high.h a2nu2/spicall/ScannerReflective.c --> mustek_usb2_reflective.c a2nu2/spicall/ScannerReflective.h --> mustek_usb2_reflective.h a2nu2/spicall/ScannerTransparent.c --> mustek_usb2_transparent.c a2nu2/spicall/ScannerTransparent.h --> mustek_usb2_transparent.h a2nu2/spicall/spicall.c --> included in mustek_usb2.c a2nu2/spicall/spicall_ex.h a2nu2/spicall/spicall_g.h --> included in mustek_usb2_high.c a2nu2/include/asic.h --> included in mustek_usb2_asic_low.h a2nu2/include/debug.h --> removed a2nu2/include/ini.h a2nu2/include/msam.ini --> removed a2nu2/include/public.h --> included in mustek_usb2_typedef.h a2nu2/include/spicall.h --> included in mustek_usb2.h a2nu2/include/typedef.h --> mustek_usb2_asic_low.h a2nu2/conf/ini.c --> removed a2nu2/asic/asic.c --> mustek_usb2_asic.c a2nu2/asic/asic_libusb.c --> removed (used sanei_usb) a2nu2/asic/asic_libusb.h --> removed a2nu2/asic/asic_mid.c --> mustek_usb2_asic_mid.c a2nu2/asic/asic_mid.h --> included in mustek_usb2_asic_mid.c a2nu2/asic/asic_motor.c --> mustek_usb2_asic_motor.c a2nu2/asic/asic_motor.h --> mustek_usb2_asic_motor.h a2nu2/asic/asic_usb.c --> mustek_usb2_asic_low.c a2nu2/asic/asic_usb.h --> included in mustek_usb2_asic_low.h a2nu2/asic/DefineScanner.h --> mustek_usb2_asic_low.h a2nu2/asic/ScanRegDef.h --> included in mustek_usb2_asic_low.h - Changed backend name to mustek_usb2. - Used dos2unix to change dos line endings to unix. - Added mustek_usb2.TODO. - Changed several occurences of "//" to "/* */". - Used DBG instead of XDBG. - Defined DBG levels in mustek_usb2_asic_low.h. - Changed code to use sanei_usb instead of home-grown usb functions. V 1.0-3 (2005-08-31) - Updated code from Mustek, mostly changed // to /* */ - Enabled compilation warnings again. - Scanner is confirmed to work at least on Linux. V 1.0-2 (2005-08-30) - Initial version based on the code from Roy Zhou, Jack Xu, Vinci Cen. - This version is just to make it compile at all and to trim down the package size by removing all the unneeded backends. Before inclusion into SANE can be done, the sub directories, several libraries and the amount of files has to be fixed (and lots of other stuff). - Based everything on current CVS. - Fixed AUTHORS. - Added mustek_pro.CHANGES. - Fixed dll.conf. - Fixed .desc file. - Adjusted configure.in to build only test, net and mustek_a2nu2 backends. - Adjusted backend/Makefile.in. - Disabled compilation warnings, otherwise the "//" comments will cause errors. - Fixed several upper/lower case problems. - Removed definition of Option_Value. - Started renaming doc files to new backend name: msutek_usb2. - Added GPL+SANE exception to all remaining files. sane-backends-1.0.27/doc/mustek_usb2/mustek_usb2.TODO0000664000175000017500000000056612112021330017154 00000000000000.mustek_usb2.TODO -*-text-*- - Check if there is an easy way to avoid pthread - prepare for different scanners (and more than one scanner) - adjust debug levels (currently only DBG_FUNC is used in _high.c). - unify debug messages ("start"/"exit" functions etc.) - check all "HOLD"s in the code - check if 1200 x 2400 dpi modes can be added - try to add additional scanners sane-backends-1.0.27/doc/sane-epjitsu.man0000664000175000017500000000754013073301665015105 00000000000000.TH sane\-epjitsu 5 "11 Apr 2017" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-epjitsu .SH NAME sane\-epjitsu \- SANE backend for Epson-based Fujitsu USB scanners. .SH DESCRIPTION The .B sane\-epjitsu library implements a SANE (Scanner Access Now Easy) backend which provides basic access the Fujitsu fi\-60F/fi\-65F and ScanSnap S300/S1300(i)/S1100(i) scanners. .SH HARDWARE SUPPORT These scanners are fairly limited, only supporting a couple of modes and resolutions, and always scanning full width. The backend supports missing modes (binary, grayscale) and intermediate resolutions in software, but provides only minimal scan area controls. See .B KNOWN ISSUES. This backend may support other scanners. If physical inspection reveals an Epson chipset, please contact the author for instructions on collecting a USB trace under Windows to verify. .SH OPTIONS A limited effort has been made to expose the standard options to the API. This allows a frontend to set resolution, color mode, and choose the ADF setting. The epjitsu backend supports the following basic options for most scanners: .PP source s .RS Selects the source for the scan. Options may include "Flatbed", "ADF Front", "ADF Back", "ADF Duplex". .RE .PP mode m .RS Selects the mode for the scan. Options may include "Lineart", "Gray", "Color". .RE .PP resolution, y\-resolution .RS Controls scan resolution. Setting \-\-resolution also sets \-\-y\-resolution, though this behavior is overridden by some frontends. .RE .PP Other options will be available based on the capabilities of the scanner. Use 'scanimage \-\-help' to get a list. Be aware that some options may appear only when another option has been set, and that advanced options may be hidden by the frontend. .PP .SH CONFIGURATION FILE The configuration file "@CONFIGDIR@/epjitsu.conf" is used to tell the backend how to look for scanners, and provide options controlling the operation of the backend. This file is read each time the frontend asks the backend for a list of scanners, generally only when the frontend starts. If the configuration file is missing, the backend will not work. .PP Scanners can be specified in the configuration file in two ways: .PP "usb 0x04c5 0x10c7" (or other vendor/product ids) .RS Requests backend to search all usb busses in the system for a device which uses that vendor and product id. The device will then be queried to determine if it is a supported scanner. .RE .PP "usb /dev/usb/scanner0" (or other device file) .RS Some systems use a kernel driver to access usb scanners. This method is untested. .RE .PP The only configuration option supported is "firmware /PATH/TO/FILE", allowing you to set the location of the firmware file you have extracted from the Windows driver. .PP .B Note: This firmware is a copyrighted work of Fujitsu, so cannot be provided by the backend or the author. Please do not ask. .PP .B Note: These scanners REQUIRE a firmware file to function. See the supplied configuration file for more detail. .PP .B Note: This option may appear multiple times in the configuration file. It only applies to scanners discovered by 'usb' lines that follow this option. .PP .SH ENVIRONMENT The backend uses a single environment variable, SANE_DEBUG_EPJITSU, which enables debugging output to stderr. Valid values are: .PP .RS 5 Errors .br 10 Function trace .br 15 Function detail .br 20 Option commands .br 25 USB trace .br 30 USB detail .br 35 Useless noise .RE .SH KNOWN ISSUES .PP .RS Only limited scan area options are exposed. .br .br fi\-60F and fi\-65F hardware grayscale mode is not used, because the calibration code is not finished. .RE .SH CREDITS S300 support funded by Microdea, Inc. and Archivista, GmbH. .br fi\-60F support funded by TrueCheck, Inc. .br Improved calibration code provided by Richard Goedeken. .SH "SEE ALSO" sane(7), sane\-usb(5) .SH AUTHOR m. allan noah: sane-backends-1.0.27/doc/sane-gphoto2.man0000664000175000017500000000747312112021330014766 00000000000000.TH sane\-gphoto2 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-gphoto2 .SH NAME sane\-gphoto2 \- SANE backend for gphoto2 supported cameras .SH DESCRIPTION The .B sane\-gphoto2 library implements a SANE (Scanner Access Now Easy) backend that provides access to the digital cameras supported by gphoto2. This backend has only been tested with a handful of cameras so far. Patches to support other models are welcome. .PP Because of the limited testing of this backend, it is commented out in @CONFIGDIR@/dll.conf by default. Either the comment character must be removed or the backend must be called explicitly. E.g. `scanimage \-d gphoto2' or `xscanimage gphoto2'. .SH "DEVICE NAMES" The current version of the backend only allows one camera to be connected. The device name is always "0". .SH CONFIGURATION The contents of the .I gphoto2.conf specify the characteristics of the camera to be used. Resolutions (high resolution, low resolution, and thumbnail size) are required since they are needed by the sane frontends, but can't be obtained through the gphoto2 interface. Valid ports and cameras can be obtained by "gphoto2 \-\-list\-cameras" and "gphoto2 \-\-list\-ports". .PP The dumpinquiry line causes some information about the camera to be printed. .PP Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP The "topfolder" line specifies the "fixed" part of the file path. For example, on the Kodak DC-240, files are stored in the directory /DCIM/100DC240. The /DCIM portion is constant, but 100DC240 will change and must be read from the camera. In this case, the line would read "topfolder=/DCIM" .PP Some cameras don't implement a file structure and store all pictures in the "/" directory. This is indicated by setting "subdirs=0" with "topfolder=/" .PP .RS port=usb: .br camera=Kodak DC240 .br # this is a comment .br high_resolution=1280x960 .br low_resolution=640x480 .br thumb_resolution=160x120 .br dumpinquiry .RE .PP .SH FILES .TP .I @CONFIGDIR@/gphoto2.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-gphoto2.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-gphoto2.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_GPHOTO2 If the library was compiled with debugging support enabled, this environment variable controls the debug level for this backend. A value of 128 requests maximally copious debug output; smaller levels reduce verbosity. .TP .B GP_DEBUG Set to 1, 2, or 3, to enable various levels of debugging within the gphoto2 libraries. .SH "SEE ALSO" sane(7) .SH AUTHOR Peter S. Fales .PP The manpage was largely copied from the dc210 manpage. .SH BUGS Many, no doubt. .PP More general comments, suggestions, and inquiries about frontends or SANE should go to the SANE Developers mailing list (see http://www.sane\-project.org/mailing\-lists.html for details). You must be subscribed to the list, otherwise your mail won't be sent to the subscribers. sane-backends-1.0.27/doc/sane-hp3500.man0000664000175000017500000000266212112021330014316 00000000000000.TH sane\-hp3500 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hp3500 .SH NAME sane\-hp3500 \- SANE backend for Hewlett-Packard ScanJet 3500 series scanners .SH DESCRIPTION The .B sane\-hp3500 library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Hewlett-Packard USB flatbed scanners: .PP .RS ScanJet 3500C .br ScanJet 3530C .br ScanJet 3570C .RE .PP If you own a scanner other than the ones listed above that works with this backend, please let us know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .IR /proc/bus/usb/devices , .I sane\-find\-scanner or syslog) to us. Even if the scanner's name is only slightly different from the models mentioned above, please let us know. .SH CONFIGURATION None required. .SH FILES .TP .I @LIBDIR@/libsane\-hp3500.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hp3500.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .B SANE_DEBUG_HP3500 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_HP3500=4 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .br .I http://projects.troy.rollo.name/rt-scanners/ .SH AUTHOR Troy Rollo sane-backends-1.0.27/doc/sane-usb.man0000664000175000017500000001323212775312262014211 00000000000000.TH sane\-usb 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-usb .SH NAME sane\-usb \- USB configuration tips for SANE .SH DESCRIPTION This manual page contains information on how to access scanners with a USB interface. It focusses on two main topics: getting the scanner detected by the operating system kernel and using it with SANE. .PP This page applies to USB most backends and scanners, as they use the generic sanei_usb interface. However, there is one exceptions: USB Scanners supported by the microtek2 backend need a special USB kernel driver, see .BR sane\-microtek2 (5) for details. .SH "QUICK START" This is a short HOWTO-like section. For the full details, read the following sections. The goal of this section is to get the scanner detected by .BR sane\-find\-scanner (1). .PP Run sane\-find\-scanner. If it lists your scanner with the correct vendor and product ids, you are done. See section .B "SANE ISSUES" for details on how to go on. .PP sane\-find\-scanner doesn't list your scanner? Does it work as root? If yes, there is a permission issue. See the .B LIBUSB section for details. .PP Nothing is found even as root? Check that your kernel supports USB and that libusb is installed (see section .BR LIBUSB ). .SH "USB ACCESS METHODS" For accessing USB devices, the USB library libusb is used. There used to exist another method to access USB devices: the kernel scanner driver. The kernel scanner driver method is deprecated and shouldn't be used anymore. It may be removed from SANE at any time. In Linux, the kernel scanner driver has been removed in the 2.6.* kernel series. Only libusb access is documented in this manual page. .SH LIBUSB SANE can only use libusb 0.1.6 or newer. It needs to be installed at build-time. Modern Linux distributions and other operating systems come with libusb. .PP Libusb can only access your scanner if it's not claimed by the kernel scanner driver. If you want to use libusb, unload the kernel driver (e.g. rmmod scanner under Linux) or disable the driver when compiling a new kernel. For Linux, your kernel needs support for the USB filesystem (usbfs). For kernels older than 2.4.19, replace "usbfs" with "usbdevfs" because the name has changed. This filesystem must be mounted. That's done automatically at boot time, if /etc/fstab contains a line like this: .PP .RS none /proc/bus/usb usbfs defaults 0 0 .RE .PP The permissions for the device files used by libusb must be adjusted for user access. Otherwise only root can use SANE devices. For .IR Linux , the devices are located in /proc/bus/usb/ or in /dev/bus/usb, if you use udev. There are directories named e.g. "001" (the bus name) containing files "001", "002" etc. (the device files). The right device files can be found out by running scanimage \-L as root. Setting permissions with "chmod" is not permanent, however. They will be reset after reboot or replugging the scanner. .PP Usually udev or for older distributions the hotplug utilities are used, which support dynamic setting of access permissions. SANE comes with udev and hotplug scripts in the directory tools/udev and tools/hotplug. They can be used for setting permissions, see @DOCDIR@/README.linux, tools/README and the README in the tools/hotplug directory for more details. .PP For the .BR BSDs , the device files used by libusb are named .IR /dev/ugen* . Use chmod to apply appropriate permissions. .SH "SANE ISSUES" .PP This section assumes that your scanner is detected by sane\-find\-scanner. It doesn't make sense to go on, if this is not the case. While sane\-find\-scanner is able to detect any USB scanner, actual scanning will only work if the scanner is supported by a SANE backend. Information on the level of support can be found on the SANE webpage .RI ( http://www.sane\-project.org/ ), and the individual backend manpages. .PP Most backends can detect USB scanners automatically using "usb" configuration file lines. This method allows one to identify scanners by the USB vendor and product numbers. The syntax for specifying a scanner this way is: .PP .RS usb .I VENDOR PRODUCT .RE .PP where .I VENDOR is the USB vendor id, and .I PRODUCT is the USB product id of the scanner. Both ids are non-negative integer numbers in decimal or hexadecimal format. The correct values for these fields can be found by running sane\-find\-scanner, looking into the syslog (e.g., /var/log/messages) or under Linux by issuing the command "cat /proc/bus/usb/devices". This is an example of a config file line: .PP .RS usb 0x055f 0x0006 .RE .PP would have the effect that all USB devices in the system with a vendor id of 0x55f and a product id of 0x0006 would be probed and recognized by the backend. .PP If your scanner is not detected automatically, it may be necessary to edit the appropriate backend configuration file before using SANE for the first time. For a detailed description of each backend's configuration file, please refer to the relevant backend manual page (e.g. .BR sane\-mustek_usb (5) for Mustek USB scanners). .PP Do .B not create a symlink from .I /dev/scanner to the USB device because this link is used by the SCSI backends. The scanner may be confused if it receives SCSI commands. .SH ENVIRONMENT .TP .B SANE_DEBUG_SANEI_USB If the library was compiled with debug support enabled, this environment variable controls the debug level for the USB I/O subsystem. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. Values greater than 4 enable libusb debugging (if available). Example: export SANE_DEBUG_SANEI_USB=4. .SH "SEE ALSO" .BR sane (7), .BR sane\-find\-scanner (1), .BR sane\-"backendname" (5), .BR sane\-scsi (5) .SH AUTHOR Henning Meier-Geinitz sane-backends-1.0.27/doc/sane-xerox_mfp.man0000664000175000017500000000407213063340150015415 00000000000000.TH sane\-xerox_mfp 5 "15 Dec 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-xerox_mfp .SH NAME sane\-xerox_mfp \- SANE backend for Xerox Phaser 3200MFP device et al. .SH DESCRIPTION The .B sane\-xerox_mfp library implements a SANE (Scanner Access Now Easy) backend that provides access to several Samsung-based Samsung, Xerox, and Dell scanners. Please see full list of supported devices at http://www.sane\-project.org/sane\-supported\-devices.html .SH CONFIGURATION .I @CONFIGDIR@/xerox_mfp.conf USB scanners do not need any configuration. For SCX\-4500W in network mode you need to specify .PP .RS .B tcp host_address [port] .RE .PP The .B host_address is passed through resolver, thus can be a dotted quad or a name from /etc/hosts or resolvable through DNS. .SH FILES .TP .I @CONFIGDIR@/xerox_mfp.conf The backend configuration file. By default all scanner types/models are enabled, you may want to comment out unwanted. .TP .I @LIBDIR@/libsane\-xerox_mfp.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-xerox_mfp.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .B SANE_DEBUG_XEROX_MFP If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_XEROX_MFP=4 .SH LIMITATIONS Multicast autoconfiguration for LAN scanners is not implemented yet. IPv6 addressing never been tested. .SH BUGS AND SUPPORT If you have found a bug or need support please follow open\-source way of acquiring support via mail\-lists http://www.sane\-project.org/mailing\-lists.html or SANE bug tracker http://www.sane\-project.org/bugs.html .SH AUTHORS Alex Belkin .br Samsung SCX\-4500W scan over network support by Alexander Kuznetsov .br Color scanning on Samsung M2870 model and Xerox Cognac 3215 & 3225 models by Laxmeesh Onkar Markod .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5) .br sane-backends-1.0.27/doc/sane-coolscan2.man0000664000175000017500000001505112112021330015256 00000000000000.TH sane\-coolscan2 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-coolscan2 .SH NAME sane\-coolscan2 \- SANE backend for Nikon Coolscan film scanners .SH DESCRIPTION The .B sane\-coolscan2 library implements a SANE (Scanner Access Now Easy) backend that provides access to Nikon Coolscan film scanners. Some functions of this backend should be considered .B beta-quality software. Most functions have been stable for a long time, but of course new development can not and will not function properly from the very first day. Please report any strange behaviour to the maintainer of the backend. .PP At present, the following scanners are known to work with this backend: .PP .RS .ft CR .nf Model: Connection Type --------------------------- ------------------- LS-30 (Coolscan III) SCSI LS-2000 SCSI LS-40 ED (Coolscan IV) USB LS-4000 ED IEEE 1394 LS-8000 ED IEEE 1394 .fi .ft R .RE Please send mail to the backend author (andras@users.sourceforge.net) to report successes or failures. .SH OPTIONS The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage or xsane. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d coolscan2:: .RE where and specify the device in question, as in the configuration file (see next section). The \-d parameter and its argument can be omitted to obtain information on the first scanner identified. Use the command .RS scanimage \-L .RE to list all devices recognized by your SANE installation. The options should be fully described by the description or tooltips given by frontend. Here is a description of some of the most important options, in the syntax with which they must be supplied to scanimage: .TP .I \-\-frame This option specifies which frame to operate on, if a motorized film strip feeder or APS adapter are used. The frame number .I ranges from 1 to the number of frames available, which is sensed each time the backend is initialized (usually each time you start the frontend). .TP .I \-\-subframe This option shifts the scan window by the specified amount (default unit is mm). .TP .I \-\-infrared=yes/no If set to "yes", the scanner will read the infrared channel, thus allowing defect removal in software. The infrared image is read during a second scan, with no options altered. The backend must not be restarted between the scans. If you use scanimage, perform a batch scan with batch\-count=2 to obtain the IR information. .TP .I \-\-depth Here can either be 8 or the maximum number of bits supported by the scanner (10, 12, or 14). It specifies whether or not the scanner reduces the scanned data to 8 bits before sending it to the backend. If 8 bits are used, some information and thus image quality is lost, but the amount of data is smaller compared to higher depths. Also, many imaging programs and image formats cannot handle depths greater than 8 bits. .TP .I \-\-autofocus Perform autofocus operation. Unless otherwise specified by the other options ( .I \-\-focus\-on\-centre and friends), focusing is performed on the centre of the selected scan area. .TP .I \-\-ae\-wb .TP .I \-\-ae Perform a pre-scan to calculate exposure values automatically. .I \-\-ae\-wb will maintain the white balance, while .I \-\-ae will adjust each channel separately. .TP .I \-\-exposure Multiply all exposure times with this value. This allows exposure correction without modifying white balance. .TP .I \-\-load Load the next slide when using the slide loader. .TP .I \-\-eject Eject the film strip or mounted slide when using the slide loader. .TP .I \-\-reset Reset scanner. The scanner will perform the same action as when power is turned on: it will eject the film strip and calibrate itself. Use this whenever the scanner refuses to load a film strip properly, as a result of which .I \-\-eject does not work. .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/coolscan2.conf specifies the device(s) that the backend will use. Owing to the nature of the supported connection types SCSI, USB, and IEEE 1394, the default configuration file supplied with the SANE distribution should work without being edited. Each line in the configuration file is either of the following, where all entries are case-sensitive: .TP .I blank or starting with a '#' character These lines are ignored, thus '#' can be used to include comments. .TP .I containing only the word """auto""" This instructs the backend to probe for a scanner by scanning the buses for devices with know identifiers. This is the action taken when no configuration file is present. .TP .I a line of the form : Here can be one of "scsi" or "usb", and is the device file of the scanner. Note that IEEE 1394 devices are handled by the SBP-2 module in the kernel and appear to SANE as SCSI devices. .SH FILES .TP .I @LIBDIR@/libsane\-coolscan2.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-coolscan2.so The shared library implementing this backend (present on systems that support dynamic loading). .TP .I @CONFIGDIR@/coolscan2.conf Configuration file for this backend, read each time the backend is initialized. .SH ENVIRONMENT .TP .B SANE_DEBUG_COOLSCAN2 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH "SEE ALSO" sane\-scsi(5), sane\-usb(5), scanimage(1), xscanimage(1), xsane(1) .SH BUGS Currently, the SANE protocol does not allow automatically updating options whenever the hardware changes. Thus the number of choices for the .B \-\-frame option will be fixed when the backend is initialized (usually when the user runs the frontend). In particular, if there is no film strip in the automatic film strip feeder when the backend is initialized, the frame option will not appear at all. Also, restarting the frontend after swapping film adapters is strongly recommended. Linux kernels prior to 2.4.19 had a patch that truncated INQUIRY data from IEEE 1394 scanners to 36 bytes, discarding vital information about the scanner. The IEEE 1394 models therefore only work with 2.4.19 or later. No real bugs currently known, please report any to the backend maintainer or the SANE developers' email list. .SH AUTHORS The backend is written and maintained by Andr\['a]s Major (andras@users.sourceforge.net). sane-backends-1.0.27/doc/sane-pnm.man0000664000175000017500000000330512775277260014222 00000000000000.TH sane\-pnm 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-pnm .SH NAME sane\-pnm \- SANE PNM image reader pseudo-backend .SH DESCRIPTION The .B sane\-pnm library implements a SANE (Scanner Access Now Easy) backend that provides access to PNM (Portable aNyMap files, which covers PBM bitmap files, PGM grayscale files, and PPM pixmap files). The purpose of this backend is primarily to aid in debugging of SANE frontends. It also serves as an illustrative example of a minimal SANE backend. .SH "DEVICE NAMES" This backend provides two devices called .B 0 and .BR 1. .SH CONFIGURATION No configuration required. .SH FILES .TP .I @LIBDIR@/libsane\-pnm.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-pnm.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_PNM If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH BUGS If the pnm backend is installed and saned is used to allow users on remote computers to scan on the local machine, pnm files can be read by the remote user. This is limited to the files saned can access (usually it's running as user "sane"). All pnm files can be read if saned runs as root which isn't recommended anyway. The pnm backend is disabled by default. If you want to use it, enable it with configure (see configure \-\-help for details). Be sure that only trusted users can access the pnm backend over saned. .SH AUTHOR Andreas Beck, Gordon Matzigkeit, and David Mosberger .SH SEE ALSO sane(7) sane-backends-1.0.27/doc/sane-dll.man0000664000175000017500000001151712775277260014207 00000000000000.TH sane\-dll 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-dll .SH NAME sane\-dll \- SANE dynamic backend loader .SH DESCRIPTION The .B sane\-dll library implements a SANE (Scanner Access Now Easy) backend that provides access to an arbitrary number of other SANE backends. These backends may either be pre-loaded at the time the .B sane\-dll library is built or, on systems that support dynamic loading of shared libraries, the backends may be loaded at runtime. In the latter case, adding support for a new backend simply involves installing the relevant library in .I @LIBDIR@ and adding an entry to the .I dll.conf configuration file. In other words, no applications need to be modified or recompiled to add support for new devices. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .IR backend : device .RE .PP Where .I backend is the name of the backend and .I device is the name of the device in this backend that should be addressed. If the device name does not contain a colon (:), then the entire string is treated as the .I device string for the default backend. The default backend is the backend listed last in the configuration file (see below) or the first pre-loaded backend (if any). .SH CONFIGURATION The contents of the .I dll.conf file is a list of backend names that may be loaded dynamically upon demand. Empty lines are ignored, also everything after a hash mark (#). A sample configuration file is shown below: .PP .RS net .br # this is a comment .br pnm .br mustek .RE .PP It is also possible to add a file in .I @CONFIGDIR@/dll.d that contains the list of backends to be added. Backends mentioned in a file included in this directory will be added before any backends listed in .I dll.conf. Files in .I @CONFIGDIR@/dll.d can be freely named. They shall follow the format conventions as apply for .I dll.conf. .PP Note that backends that were pre-loaded when building this library do not have to be listed in this configuration file. That is, if a backend was preloaded, then that backend will always be present, regardless of whether it's listed in the configuration file or not. .PP The list of preloaded backends is determined by macro .B PRELOADABLE_BACKENDS in file backend/Makefile.in of the SANE source code distribution. After changing the value of this macro, it is necessary to reconfigure, rebuild, and reinstall SANE for the change to take effect. Aliases are defined in the config file .IR dll.aliases . It can contain entries of the form .PP .RS .br alias SomeName SaneDeviceName .br alias "Some Name" SaneDeviceName .br hide SaneDeviceName .RE .PP For example: .PP .RS .br alias Epson net:somehost:epson:/dev/sgX .br alias "Siemens ST400" st400:/dev/sgY .br hide net:somehost:pnm:0 .br hide net:somehost:pnm:1 .br alias "Read from file" pnm:0 .br hide pnm:1 .RE .PP Aliased device names are automatically hidden. The idea is that users don't have to deal with complicated device names (especially for networked devices), and to hide other exported devices which might confuse them. Note that a hidden device can still be accessed if the device name is known, it just doesn't appear on the list. .SH FILES .TP .I @CONFIGDIR@/dll.aliases The list of aliased or hidden backends. .TP .I @CONFIGDIR@/dll.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-dll.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-dll.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_DLL If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .ft CR .nf Value Description 0 print severe errors only 1 print normal errors and important messages 2 print normal messages 3 print debugging messages 4 print everything .fi .ft R Example: export SANE_DEBUG_DLL=3 .SH "SEE ALSO" .BR sane (7), .BR scanimage (1), .BR sane\-"backendname" (5) .SH AUTHOR David Mosberger sane-backends-1.0.27/doc/sane-leo.man0000664000175000017500000000723712112021330014161 00000000000000.TH sane\-leo 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-leo .SH NAME sane\-leo \- SANE backend for LEO Technologies scanners .SH DESCRIPTION The .B sane\-leo library implements a SANE (Scanner Access Now Easy) backend that provides access to some LEO SCSI flatbed scanners. This backend should be considered .B beta-quality software! LEO scanners were also sold under the Across Technologies brand. .PP The scanners that should work with this backend are: .PP .RS .ft CR .nf Vendor Model status ---------------------- ----------- Across FS-1130 tested Leo S3 tested .fi .ft R .RE The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage or xsane. .br If you have any strange behavior, please report to the backend maintainer or to the SANE mailing list. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d leo .RE .TP .B Scan Mode .TP .B \-\-mode selects the basic mode of operation of the scanner valid choices are .I Black & White , .I Grayscale and .I Color The Black & White mode is black and white only (1 bit). Grayscale will produce 256 levels of gray (8 bits). Color will produce a 24 bits color image. .TP .B \-\-resolution selects the resolution for a scan. The scanner can do all resolutions between 1 and 300, in increments of 1. .TP .B Geometry options .TP .B \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters by default. .TP .B Enhancement options .TP .B \-\-custom\-gamma (grayscale and color mode only) allows the user to specify a gamma table (see the next 3 parameters). .TP .B \-\-red\-gamma\-table (color mode only) can be used to download a user defined gamma table for the red channel. The table must be 256 bytes long. .TP .B \-\-green\-gamma\-table (color mode only) can be used to download a user defined gamma table for the green channel. The table must be 256 bytes long. .TP .B \-\-blue\-gamma\-table (color mode only) can be used to download a user defined gamma table for the blue channel. The table must be 256 bytes long. .TP .B \-\-halftone (Black & White only) select the halftone mask to use. Possible values are .I Diamond , .I 8x8 Coarse Fatting , .I 8x8 Fine Fatting , .I 8x8 Bayer and .I 8x8 Vertical Line .TP .B \-\-preview requests a preview scan. The resolution used for that scan is 28 dpi and the scan area is the maximum allowed. The scan mode is user selected. The default is "no". .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/leo.conf supports only one information: the device name to use (eg /dev/scanner). .SH FILES .TP .I @LIBDIR@/libsane\-leo.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-leo.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_LEO If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH LIMITATIONS The windows TWAIN driver has many more options than this SANE backend. However they are only software adjustments. This backend only implements what the scanner can support. .SH BUGS None known. .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1), sane(7) .SH AUTHOR .TP The package is actively maintained by Frank Zago. .I http://www.zago.net/sane/#leo sane-backends-1.0.27/doc/sane-gt68xx.man0000664000175000017500000001675012775312262014600 00000000000000.TH sane\-gt68xx 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-gt68xx .SH NAME sane\-gt68xx \- SANE backend for GT-68XX based USB flatbed scanners .SH DESCRIPTION The .B sane\-gt68xx library implements a SANE (Scanner Access Now Easy) backend that provides access to USB flatbed scanners based on the Grandtech GT-6801 and GT-6816 chips. A list of supported scanners can be found on the gt68xx backend homepage: .IR http://www.meier\-geinitz.de/sane/gt68xx\-backend/ . .PP This is BETA software. Especially if you test new or untested scanners, keep your hand at the scanner's plug and unplug it, if the head bumps at the end of the scan area. .PP If you own a scanner other than the ones listed on the gt68xx homepage that works with this backend, please let me know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .I sane\-find\-scanner or syslog) to me. Even if the scanner's name is only slightly different from the models already listed as supported, please let me know. .PP If you own a scanner that isn't detected by the gt68xx backend but has a GT-6801 or GT-6816 chipset, you can try to add it to the backend. Have a look at the following web page: .I http://www.meier\-geinitz.de/sane/gt68xx\-backend/adding.html .PP .SH LIBUSB ISSUES Please use libusb-0.1.8 or later. Without libusb or with older libusb versions all kinds of trouble can be expected. The scanner should be found by sane\-find\-scanner without further actions. For setting permissions and general USB information looks at .BR sane\-usb (5). .PP .SH FIRMWARE FILE You need a firmware file for your scanner. That's a small file containing software that will be uploaded to the scanner's memory. It's usually named *.usb, e.g. .IR PS1fw.usb . It comes on the installation CD that was provided by the manufacturer, but it may be packaged together with the installation program in an .exe file. For Mustek scanners, the file can be downloaded from the gt68xx backend homepage. For other scanners, check the CD for .usb files. If you only find *.cab files, try cabextract to unpack. If everything else fails, you must install the Windows driver and get the firmware from there (usually in the .I windows/system or .I system32 directories). Put that firmware file into .IR @DATADIR@/sane/gt68xx/ . Make sure that it's readable by everyone. .SH CONFIGURATION The contents of the .I gt68xx.conf file is a list of usb lines containing vendor and product ids that correspond to USB scanners. The file can also contain option lines. Empty lines and lines starting with a hash mark (#) are ignored. The scanners are autodetected by .B usb vendor_id product_id statements which are already included into .IR gt68xx.conf . "vendor_id" and "product_id" are hexadecimal numbers that identify the scanner. .PP The .BR override , .BR firmware , .BR vendor , .BR model , and .B afe options must be placed after the .B usb line they refer to. .PP Option .B override is used to override the default model parameters. That's necessary for some scanners that use the same vendor/product ids but are different. For these scanners there are already commented out override lines in the configuration file. .B override "mustek\-scanexpress\-1200\-ub\-plus" is necessary for the Mustek Scanexpress 1200 UB Plus, the Medion/Lifetec/Tevion LT 9452, and the Trust Compact Scan USB 19200. .B override "artec\-ultima\-2000" is used for the Artec Ultima 2000, the Boeder SmartScan Slim Edition, the Medion/ Lifetec/ Tevion/ Cytron MD/LT 9385, the Medion/ Lifetec/ Tevion MD 9458, and the Trust Flat Scan USB 19200. .B override "mustek\-bearpaw\-2400\-cu" is necessary for the Mustek BearPaw 2400 CU and the Fujitsu 1200CUS. The .B override option must be the first one after the .B usb line. .PP Option .B firmware selects the name and path of the firmware file. It's only necessary if the default (or override) doesn't work. The default firmware directory is .IR @DATADIR@/sane/gt68xx/ . You may need to create this directory. If you want to place the firmware files at a different path, use a .B firmware line. .PP The .B vendor and .B model options are not absolutely necessary but for convenience. Quite a lot of scanners from different manufacturers share the same vendor/product ids so you can set the "correct" name here. .PP The .B afe option allows one to set custom offset and gain values for the Analog FrontEnd of the scanner. This option can be either used to select the AFE values if automatic coarse calibration is disabled, or to make automatic coarse calibration faster. For the latter usage, enable debug level 3 (see below), scan an image and look for debug line string with "afe". Copy this line to .IR gt68xx.conf . The option has six parameters: red offset, red gain, green offset, green gain, blue offset, and blue gain. .PP A sample configuration file is shown below: .PP .RS usb 0x05d8 0x4002 .br override "mustek\-scanexpress\-1200\-ub\-plus" .br firmware "/opt/gt68xx/SBfw.usb" .br vendor "Trust" .br model "Compact Scan USB 19200" .br afe 0x20 0x02 0x22 0x03 0x1f 0x04 .RE .SH FILES .TP .I @CONFIGDIR@/gt68xx.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-gt68xx.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-gt68xx.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_GT68XX If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. If the debug level is set to 1 or higher, some debug options become available that are normally hidden. Handle them with care. Example: export SANE_DEBUG_GT68XX=4 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .BR sane\-artec_eplus48u (5) .BR sane\-plustek (5), .BR sane\-ma1509 (5), .BR sane\-mustek_usb (5), .BR sane\-mustek (5), .BR sane\-mustek_pp (5) .br .I @DOCDIR@/gt68xx/gt68xx.CHANGES .br .I http://www.meier\-geinitz.de/sane/gt68xx .SH AUTHOR Henning Meier-Geinitz .br The original gt68xx driver was written by Sergey Vlasov, Andreas Nowack, and David Stevenson. Thanks for sending patches and answering questions to them and all the other contributors. .SH BUGS The first few lines of the image are garbage for the 2400 TA Plus. .PP Interpolation should be used instead of just copying data, when the X- and Y-resolution differ. .PP Support for buttons is missing. .PP More detailed bug information is available at the gt68xx backend homepage .IR http://www.meier\-geinitz.de/sane/gt68xx\-backend/ . Please contact us if you find a bug or missing feature: . Please send a debug log if your scanner isn't detected correctly (see SANE_DEBUG_GT68XX above). sane-backends-1.0.27/doc/sane-genesys.man0000664000175000017500000002606713106201017015067 00000000000000.TH "sane\-genesys" "5" "4 Jul 2012" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-genesys .SH "NAME" sane\-genesys \- SANE backend for GL646, GL841, GL843, GL847 and GL124 based USB flatbed scanners .SH "DESCRIPTION" The .B sane\-genesys library implements a SANE (Scanner Access Now Easy) backend that provides access to USB flatbed scanners based on the Genesys GL646, GL841, GL843, GL847 and GL124 chips. At present, the following scanners are known to work with this backend: .PP .RS Canon LiDE 35/40/50/60/100/110/120/200/210/220/700 .br Hewlett-Packard HP2300C/HP2400/HP3670/HP3690/G4010/G4050 .br Medion MD5345/MD6228/MD6274 .br Panasonic KV-SS080 .br Plustek OpticBook 3600 .br Pentax DSmobile 600 .br Syscan/Ambir DocketPORT 467/485/487/665/685 .br Visioneer OneTouch 7100/Strobe XP100 (rev3)/XP200/XP300/Roadwarrior .br Xerox Travel Scanner 100, OneTouch 2400 .RE .PP This is stable software for supported models. But if you test new or untested scanners, keep your hand at the scanner's plug and unplug it, if the head bumps at the end of the scan area. .PP If you own a scanner other than the ones listed above that works with this backend, please let me know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .IR /proc/bus/usb/devices , .I sane\-find\-scanner or syslog) to the sane\-devel mailing list. Even if the scanner's name is only slightly different from the models mentioned above, please let me know. .PP If you own a scanner that isn't detected by the genesys backend but has a GL646, GL841, GL843, GL847 or GL124 chipset, you can try to add it to the backend. .PP .SH "CALIBRATION" To give correct image quality, sheet fed scanners need to be calibrated using the calibration sheet sold with the scanner. To do calibration, you must insert this target in the feeder then start calibration either by passing the \-\-calibrate option to scanimage or by clicking on the available 'calibrate' button in the 'advanced options' in a graphical frontend. The result of the calibration is stored in a file in the home directory of the user doing it. If you plug the scanner in another machine or use it with another account, calibration will have to be redone, unless you use the \-\-calibration\-file option. If no home directory is defined, USERAPPPROFILE will be used, then TMPDIR or TMP. If none of these directories exist, the backend will try to write in the current working directory. Flatbed scanners also make use of the calibration file as a cache to avoid calibration before each scan. Calibration file name is the name of the scanner model if only one scanner is detected. In the case of several identical model, the file name will be the name of the logical USB device name. The expiration time manages the time a calibration is valid in cache. A value of -1 means forever, 0 means no cache. .SH EXTRAS SCAN OPTIONS .B \-\-lamp\-off\-time number .RS The lamp will be turned off after the given time (in minutes). A value of 0 means that the lamp won't be turned off. .RE .B \-\-threshold percent .RS 0..100% (in steps of 1). Select minimum brightness to get a white point. Pixels with brightness below that value will be scanned as black. .RE .B \-\-brightness value .RS \-100..100 (in steps of 1). Set the brightness enhancement. 0 for no enhancement, negative values to decrease brigthness, and positive values to increase it. .RE .B \-\-contrast value .RS \-100..100 (in steps of 1). Set the contrast enhancement. 0 for no enhancement, negative values to decrease contrast, and positive values to increase it. .RE .B \-\-disable-interpolation yes|no .RS When using high resolutions where the horizontal resolution is smaller than vertical resolution, data is expanded by software to preserve picture geometry. This can be disabled by this option to get real scanned data. .RE .B \-\-disable-dynamic-lineart yes|no .RS Disable use of a software adaptive algorithm to generate lineart and rely on hardware lineart. .RE .B \-\-color-filter None|Red|Green|Blue .RS When using gray or lineart this option selects the used color. Using a color filter will give a monochrome scan. CIS based scanners can to true gray when no filter (None value) is selected. .RE .B \-\-lamp\-off\-scan .RS The lamp will be turned off during the scan. Calibration is still done with lamp on. .RE .B \-\-clear\-calibration .RS Clear calibration cache data, triggering a new calibration for the device when the next scan will happen. .RE .B \-\-calibration\-file .RS Specify the calibration file name to use. At least the directory containing the file must exist, since it won't be created. This option is disabled if the backend is ran as root. It maybe used in case of sheet-fed scanners to share a calibration file for several users. .RE .B \-\-expiration\-time .RS Specify the time (in minutes) a cached calibration is considered valid. If older than the given value, a new calibration is done. A value of -1 means no expiration and cached value are kept forever unless cleared by userwith the calibration clear option. A value of 0 means cache is disabled. .RE .PP Additionally, several 'software' options are exposed by the backend. These are reimplementations of features provided natively by larger scanners, but running on the host computer. This enables smaller machines to have similar capabilities. Please note that these features are somewhat simplistic, and may not perform as well as the native implementations. Note also that these features all require that the driver cache the entire image in memory. This will almost certainly result in a reduction of scanning speed. .PP .B \-\-swcrop .RS Requests the driver to detect the extremities of the paper within the larger image, and crop the empty edges. .RE .PP .B \-\-swdeskew .RS Requests the driver to detect the rotation of the paper within the larger image, and counter the rotation. .RE .PP .B \-\-swdespeck \-\-despeck X .RS Requests the driver to find and remove dots of X diameter or smaller from the image, and fill the space with the average surrounding color. .RE .PP .B \-\-swskip 0..100% (in steps of 1) [0] .RS Request driver to discard pages with low numbers of dark pixels. .RE .PP .B \-\-swderotate[=(yes|no)] [no] .RS Request driver to detect and correct 90 degree image rotation. .PP .SH "SYSTEM ISSUES" This backend needs libusb-0.1.6 or later installed, and hasn't tested in other configuration than a linux kernel 2.6.9 or higher. However, it should work any system with libusb where the SANE package can be compiled. For setting permissions and general USB information look at .BR sane\-usb (5). .SH "CONFIGURATION" The contents of the .I genesys.conf file is a list of usb lines containing vendor and product ids that correspond to USB scanners. The file can also contain option lines. Empty lines and lines starting with a hash mark (#) are ignored. The scanners are autodetected by .B usb vendor_id product_id statements which are already included into .IR genesys.conf . "vendor_id" and "product_id" are hexadecimal numbers that identify the scanner. .PP .SH "FILES" .TP .I @CONFIGDIR@/genesys.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-genesys.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-genesys.so The shared library implementing this backend (present on systems that support dynamic loading). .SH "ENVIRONMENT" .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_GENESYS If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. If the debug level is set to 1 or higher, some debug options become available that are normally hidden. Handle them with care. This will print messages related to core genesys functions. .TP .B SANE_DEBUG_GENESYS_LOW This environment variable controls the debug level for low level functions common to all genesys ASICs. .TP .B SANE_DEBUG_GENESYS_GL646 This environment variable controls the debug level for the specific GL646 code part. .TP .B SANE_DEBUG_GENESYS_GL841 This environment variable controls the debug level for the specific GL841 code part. .TP .B SANE_DEBUG_GENESYS_GL843 This environment variable controls the debug level for the specific GL843 code part. .TP .B SANE_DEBUG_GENESYS_GL847 This environment variable controls the debug level for the specific GL847 code part. .TP .B SANE_DEBUG_GENESYS_GL124 This environment variable controls the debug level for the specific GL124 code part. Example (full and highly verbose output for gl646): .br export SANE_DEBUG_GENESYS=255 .br export SANE_DEBUG_GENESYS_LOW=255 .br export SANE_DEBUG_GENESYS_GL646=255 .SH CREDITS Jack McGill for donating several sheetfed and flatbed scanners, which made possible to add support for them in the genesys backend: .RS Hewlett-Packard HP3670 .br Visioneer Strobe XP100 (rev3)/XP200/XP300/Roadwarrior .br Canon LiDE 200 .br Pentax DSmobile 600 .br Syscan/Ambir DocketPORT 467/485/487/665/685 .br Xerox Travel Scanner 100, Onetouch 2400 .RE .TP cncsolutions (http://www.cncsolutions.com.br) sponsored and supported the work on the Panasonic KV-SS080. .br .TP Brian Paavo from Benthic Science Limited for donating a Canoscan LiDE 700F. .br .TP Dany Qumsiyeh for donating a Canoscan LiDE 210 and a LiDE 220. .br .TP Luc Verhaegen for donating a Canoscan LiDE 120. .br .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5) .br .SH "AUTHOR" Oliver Rauch .br Henning Meier-Geinitz .br Gerhard Jaeger .br St\['e]phane Voltz .br Philipp Schmid .br Pierre Willenbrock .br Alexey Osipov for HP2400 final support .SH "LIMITATIONS" Powersaving isn't implemented for gl646 based scanner. Dynamic (emulated from gray data and with dithering) isn't enabled for gl646 scanners. Hardware lineart is limited up to 600 dpi for gl847 based scanners, due to the way image sensors are built. .br .TP This backend will be much slower if not using libusb\-1.0. So be sure that sane\-backends is built with the \-\-enable-libusb_1_0 option. .br .SH "BUGS" For the LiDE 200, the scanned data at 4800 dpi is obtained "as is" from sensor. It seems the windows driver does some digital processing to improve it, which is not implemented in the backend. .PP sane-backends-1.0.27/doc/sane-pie.man0000664000175000017500000000267712112021330014162 00000000000000.TH sane\-pie 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-pie .SH NAME sane\-pie \- SANE backend for PIE, Devcom and AdLib SCSI flatbed scanners .SH DESCRIPTION The .B sane\-pie library implements a SANE (Scanner Access Now Easy) backend that provides access to PIE, Devcom and AdLib SCSI flatbed scanners. .br At present, the following scanners should work with this backend: .PP .ft CR .nf Model: Status ---------------------- ------ Devcom 9636PRO OK Devcom 9636S Untested Devcom 9630S Untested ScanAce 1236S Untested ScanAce 1230S Untested ScanAce II Untested ScanAce III OK ScanAce Plus Untested ScanAce II Plus Untested ScanAce III Plus Untested ScanAce V Untested ScanAce ScanMedia Untested ScanAce ScanMedia II Untested ScanAce 630S Untested ScanAce 636S Untested JetScan 630 OK JetScan 636PRO Untested .fi .ft R .PP .SH FILES .TP .I @CONFIGDIR@/pie.conf The backend configuration file .TP .I @LIBDIR@/libsane\-pie.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-pie.so The shared library implementing this backend (present on systems that support dynamic loading). .PP .SH SEE ALSO sane(7) .SH "CONTACT AND BUG-REPORTS" Please send any information and bug-reports to: .br .B Simon Munton sane-backends-1.0.27/doc/sane-apple.man0000664000175000017500000002250512775312262014524 00000000000000.TH sane\-apple 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-apple .SH NAME sane\-apple \- SANE backend for Apple flatbed scanners .SH DESCRIPTION The .B sane\-apple library implements a SANE (Scanner Access Now Easy) backend that provides access to Apple flatbed scanners. At present, the following scanners are supported from this backend: .PP .br .ft CR .nf --------------- ----- ------------------ ------ AppleScanner 4bit 16 Shades of Gray OneScanner 8bit 256 Shades of Gray ColorOneScanner 24bit RGB color 3-pass .fi .ft R .PP If you own a Apple scanner other than the ones listed above that works with this backend, please let us know by sending the scanner's model name, SCSI id, and firmware revision to .IR sane\-devel@lists.alioth.debian.org . See http://www.sane\-project.org/mailing\-lists.html for details on how to subscribe to sane\-devel. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is either the path-name for the special device that corresponds to a SCSI scanner. For SCSI scanners, the special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. See sane\-scsi(5) for details. .SH CONFIGURATION The .I apple.conf file is a list of options and device names that correspond to Apple scanners. Empty lines and lines starting with a hash mark (#) are ignored. See sane\-scsi(5) on details of what constitutes a valid device name. .PP Options come in two flavors: global and positional ones. Global options apply to all devices managed by the backend, whereas positional options apply just to the most recently mentioned device. Note that this means that the order in which the options appear matters! .SH SCSI ADAPTER TIPS SCSI scanners are typically delivered with an ISA SCSI adapter. Unfortunately, that adapter is not worth much since it is not interrupt driven. It is sometimes possible to get the supplied card to work, but without an interrupt line, scanning will put so much load on the system that it becomes almost unusable for other tasks. .SH FILES .TP .I @CONFIGDIR@/apple.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-apple.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-apple.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable is list of directories where SANE looks for the configuration file. Under UNIX directory names are separated by a colon (`:'), under OS/2 by a semi-colon (`;'). If SANE_CONFIG_DIR is not set, SANE defaults to searching the current working directory (".") and then /etc/sane.d. If the value of $SANE_CONFIG_DIR ends with the separator character, the default directories are searched after the directory list. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in that order). .TP .B SANE_DEBUG_APPLE Controls the debug level. A value of 255 prints all debug output. Smaller values reduce verbosity. Requires a library compiled with debug support. .SH CURRENT STATUS The apple backend is now in version 0.3 (Tue Jul 21 1998). Since I only have the AppleScanner and not the other models (OneScanner, ColorOneScanner) I can only develop/test for the AppleScanner effectively. However with this release I almost completed the gui part of all scanners. Most of the functionality is there. At least OneScanner should scan at the AppleScanner's compatible modes (LineArt, HalfTone, Gray16). My personal belief is that with a slight touch of debugging the OneScanner could be actually usable. The ColorOneScanner needs more work. AppleScanner is of course almost fully supported. .SH MISSING FUNCTIONALITY Currently all three models lack upload/download support. .TP .B AppleScanner Cannot up/download a halftone pattern. .TP .B OneScanner Cannot up/download halftone patterns or calibration vectors. .TP .B ColorOneScanner Cannot up/download halftone patterns, calibration vectors, custom Color Correction Tables (CCT) and of course custom gamma tables. .TP .B Park/UnPark (OneScanner, ColorOneScanner) Some capabilities are missing. .PP The above functionalities are missing because I don't have the hardware to experiment on. Another reason is my lack of understanding as to how or if the SANE API provide means to describe any array type besides gamma. .SH UNSUPPORTED FEATURES The following "features" will never be supported, at least while I maintain the sane\-apple backend. .TP .B NoHome (AppleScanner) The scanner lamp stays on and the carriage assembly remains where it stops at the end of the scan. After two minutes, if the scanner does not receive another SCAN command, the lamp goes off and the carriage returns to the home position. .TP .B Compression (AppleScanner) The Scanner can compress data with CCITT Group III one dimensional algorithm (fax) and the Skip White Line algorithm. .TP .B Multiple Windows (AppleScanner) AppleScanner may support multiple windows. It would be a cool feature and a challenge for me to code if it could intermix different options for different windows (scan areas). This way it could scan a document in LineArt mode but the figures in it in Gray and at a different resolution. Unfortunately this is impossible. .TP .B Scan Direction (OneScanner) It controls the scan direction. (?) .TP .B Status/Reset Button (OneScanner) This option controls the status of the button on the OneScanner model. You can also reset the button status by software. .SH BUGS SANE backend bugs are divided in two classes. We have .B GUI bugs and .B scanner specific bugs. .PP We know we have a GUI bug when a parameter is not showing up when it should (active) or vice versa. Finding out which parameters are active across various Apple modes and models from the documentation .B ftp://ftpdev.info.apple.com/devworld/Technical_Documentation/Peripherals_Documentation/ is an interesting exercise. I may have missed some dependencies. For example of the threshold parameter the Apple Scanners Programming Guide says nothing. I had to assume it is valid only in LineArt mode. .PP Scanner specific bugs are mostly due to mandatory round-offs in order to scan. In the documentation in one place states that the width of the scan area should be a byte multiple. In another place it says that the width of the scan area should be an even byte multiple. Go figure... .PP Other sources of bugs are due to scsi communication, scsi connects and disconnects. However the classical bugs are still there. So you may encounter buffer overruns, null pointers, memory corruption and .B SANE API violations. .TP .B SIGSEGV on SliceBars When you try to modify the scan area from the slice bar you have a nice little cute core dump. I don't know why. If you select the scan area from the preview window or by hand typing the numbers everything is fine. The SIGSEGV happens deep in gtk library (gdk). I really cannot debug it. .TP .B Options too much It is possible, especially for the ColorOneScanner, for the backend's options panel to extend beyond your screen. It happens with mine and I am running my X Server at 1024x768. What can I say? Try smaller fonts in the X server, or virtual screens. .TP .B Weird SCSI behaviour I am quoting David Myers Here... >> OS: FreeBSD 2.2.6 .br >> CC: egcs-1.02 .br Just wanted to follow up on this... I recently changed my SCSI card from the Adaptec 2940UW to a dual-channel Symbios 786 chipset. When I started up SANE with your driver, I managed to scan line art drawings okay, but Gray16 scans led to a stream of SCSI error messages on the console, ultimately hanging with a message saying the scanner wasn't releasing the SCSI bus. This may be that the Symbios is simply less tolerant of ancient hardware, or may be bugs in your driver or in SANE itself... .SH DEBUG If you encounter a GUI bug please set the environmental variable SANE_DEBUG_APPLE to 255 and rerun the exact sequence of keystrokes and menu selections to reproduce it. Then send me a report with the log attached. .PP If you have an Apple Macintosh with the AppleScanners driver installed, reporting to me which options are grayed out (inactive) in what modes would be very helpful. .PP If you want to offer some help but you don't have a scanner, or you don't have the model you would like to help with, or you are a SANE developer and you just want to take a look at how the apple backend looks like, goto to apple.h and #define the NEUTRALIZE_BACKEND macro. You can select the scanner model through the APPLE_MODEL_SELECT macro. Available options are APPLESCANNER, ONESCANNER, COLORONESCANNER. .PP If you encounter a SCSI bus error or trimmed and/or displaced images please set the environment variable SANE_DEBUG_SANEI_SCSI to 255 before sending me the report. .SH TODO .TP .B Non Blocking Support Make sane\-apple a non blocking backend. Properly support .B sane_set_io_mode and .B sane_get_select_fd .TP .B Scan Make scanning possible for all models in all supported modes. .PP Add other missing functionality .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHOR The sane\-apple backend was written not entirely from scratch by Milon Firikis. It is mostly based on the mustek backend from David Mosberger and Andreas Czechanowski sane-backends-1.0.27/doc/sane-kodakaio.man0000664000175000017500000000271212775312262015203 00000000000000.TH sane\-kodakaio 5 "17 Jun 2012" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-kodakaio .SH NAME sane\-kodakaio \- SANE backend for Kodak aio printer / scanners .SH DESCRIPTION The .B sane\-kodakaio library implements a SANE (Scanner Access Now Easy) backend which provides access to Kodak aio printer / scanners, like the ESP and Hero series. This document describes backend version 2.4, which is the first candidate for incorporation in sane-backends. .SH SUPPORTED HARDWARE This version should support models of the Kodak ESP and Hero series, and possibly some Advent AiO scanners. The ESP 5250 and Hero 9.1 were used to develop the backend, but other models may work. Please see the desc file. If you have a model not on that list, or reported as 'untested': the best way to determine level of support is to test the scanner directly. .SH CONFIGURATION FILE The configuration file "kodakaio.conf" is used to tell the backend how to look for scanners, and provide options controlling the operation of the backend. This file is read each time the frontend asks the backend for a list of scanners, generally only when the frontend starts. .SH ENVIRONMENT The backend uses a single environment variable, SANE_DEBUG_KODAKAIO, which enables debugging output to stderr. .SH KNOWN ISSUES Most hardware options are either not supported or not exposed for control by the user, including: multifeed detection, image compression etc. .PP .SH AUTHOR P. Newall sane-backends-1.0.27/doc/teco/0000775000175000017500000000000013110600532012770 500000000000000sane-backends-1.0.27/doc/teco/teco1.txt0000664000175000017500000001270312112021330014461 00000000000000 BACKEND TECO1 Relisys RELI 2412 (no ADF, no transparency adapter) single pass scanner - 300*1200 dpi - 8.5*14 Inquiry: 000: 06 00 02 02 30 00 00 10 52 45 4c 49 53 59 53 20 ....0...RELISYS 016: 56 4d 33 35 33 30 2b 20 20 20 20 20 20 20 20 20 VM3530+ 032: 31 2e 30 38 31 2e 30 38 02 00 54 45 43 4f 20 56 1.081.08..TECO V 048: 4d 33 35 33 41 M353A Inquiry page 0x82 000: 06 82 00 12 11 54 45 43 4f 20 56 4d 33 35 33 41 .....TECO VM353A 016: 20 56 31 2e 30 36 V1.06 AVEC Colour 2412 three pass scanner - 300*600 dpi - 8.5*14 000: 06 00 02 02 30 00 00 10 20 20 20 20 20 20 20 20 ....0... 016: 49 6d 61 67 65 20 53 63 61 6e 6e 65 72 20 20 20 Image Scanner 032: 31 2e 30 38 31 2e 30 38 02 00 54 45 43 4f 20 56 1.081.08..TECO V 048: 4d 33 35 32 41 M352A Avec Color Office 2400 (no ADF, no transparency adapter) three pass scanner - 300*600 dpi - 8.5*14 Inquiry: 000: 06 00 02 02 30 00 00 10 20 20 20 20 20 20 20 20 ....0... 016: 49 6d 61 67 65 20 53 63 61 6e 6e 65 72 20 20 20 Image Scanner 032: 32 2e 30 34 32 2e 30 34 02 00 54 45 43 4f 20 56 2.042.04..TECO V 048: 4d 33 35 32 30 M3520 Inquiry page 0x82 000: 06 82 00 12 11 54 45 43 4f 20 56 4d 33 35 32 30 .....TECO VM3520 016: 20 56 32 2e 30 34 V2.04 RELI 4830 (no ADF, with transparency adapter) 000: 06 00 02 02 30 00 00 10 52 45 4c 49 53 59 53 20 ....0...RELISYS 016: 52 45 4c 49 20 34 38 33 30 20 20 20 20 20 20 20 RELI 4830 032: 31 2e 30 33 31 2e 30 33 02 00 54 45 43 4f 20 56 1.031.03..TECO V 048: 4d 34 35 34 32 M4542 Inquiry page 0x82 000: 06 82 00 12 11 54 45 43 4f 20 56 4d 34 35 34 32 .....TECO VM4542 016: 20 56 31 2e 30 33 V1.03 Dextra DF-600P - VM3510 000: 06 00 02 02 24 00 00 10 44 46 2D 36 30 30 4D 20 ....$...DF-600M 016: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 032: 31 2E 31 37 31 2E 31 37 02 1.171.17. /*--------------------------------------------------------------------------*/ SCSI commands supported by the RELISYS VM3530+: TEST UNIT READY 00 00 00 00 00 00 REQ SENSE 03 00 00 00 12 00 VENDOR-09 09 00 00 78 00 00 3-4 = length of data to receive. Always 30720 bytes. Probably 12 lines of calibration at 300dpi. 8.5*300*12=30600 VENDOR-0E (?) 0E 00 00 00 00 00 Always follows VENDOR-09 command INQUIRY: 12 00 00 00 35 00 12 01 82 00 21 00 standard inquiry 52 bytes - appears to never change 32-39: firmware version 42-52: real scanner name page 0x82 (vendor specific) - real scanner name with version 0-3 = page header 4 = string length 5-21 = real scanner name with version MODE SELECT 15 10 00 00 18 00 always sends: 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 01 03 06 02 00 00 01 00 00 SCAN 1B 00 00 00 00 00 SET WINDOW 24 00 00 00 00 00 00 00 63 00 Total length is 99 07 = length (99-8 = 91) 10-11 = X Resolution 12-13 = Y resolution 14-17 = X top left corner 18-21 = Y top left corner 22-25 = width (size in inches * 300) 26-29 = length (size in inches * 300) 31 = 0x80 ? 33 = scan mode 0x00 = black & white 0x02 = grayscale 0x05 = color 34 = bit depth? - invariants, always 8 36 = dither pattern - only for B&W 0x00 = line art 0x01 = 2 X 2 0x02 = 3 X 3 0x03 = 4 X 4 Bayer 0x04 = 4 X 4 Smooth 0x05 = 8 X 8 Bayer 0x06 = 8 X 8 Smooth 0x07 = 8 X 8 Horizontal 0x08 = 8 X 8 Vertical 37 = 0x80 = RIF (VM353A only?) 63 = calibration? 0x00 yes 0x02 no 81 = ??? transparency adapter 0x00 no 0x01 yes 93 = 0x80 = ? (seems to activate a contrast value on VM353A) 37, 55, 57, 59, 61, 65, 67, 69, 71, 73, 75, 77, 79 = 0x80 85, 89, 93, 97 = 0xff READ 28 00 00 00 00 00 00 00 3E 00 6-8 = length SEND 2A 00 03 00 00 02 00 04 00 00 2 = data type code 0x03 = gamma - 4*256 bytes GET DATA BUFFER STATUS 34 01 00 00 00 00 00 00 12 00 1 = bit 1 is wait 7-8 allocation length returned buffer is 0x10 bytes long. 0-2 = additional length (0x10-3 = 0x0D) 3 = reserved(?) 8 = ? 9-11 = filled data buffer 12-13 = number of lines (constant during a scan) 14-15 = bytes per line (constant during a scan) /*--------------------------------------------------------------------------*/ Command sequence (simplified, since the TWAIN driver seems to be quite stupid) Get some info: INQUIRY INQUIRY page 0x82 Setup the scan: TUR MODE SELECT SET WINDOWS GET BUFFER STATUS VENDOR-09 VENDOR-0E SEND(10) SET WINDOWS (same as the first one) SCAN loop until all data read: GET BUFFER STATUS READ(10) if any data available park the CCD: SET WINDOWS SCAN /*--------------------------------------------------------------------------*/ The vendor specific command 0x09 and 0x0e are issued by the windows driver to the AVEC 2400, but the scanner rejects them. /*--------------------------------------------------------------------------*/ The Dextra DF600-P is a VM3510. It's older than the other scanner and is a little more primitive. The driver recognizes its scsi id and fake a more evolved one. The scan sequence is also simplified. The rest is identical. sane-backends-1.0.27/doc/teco/teco2.txt0000664000175000017500000001741112112021330014463 00000000000000 BACKEND TECO2 INQUIRY TECO VM3564 (1) 000: 06 00 02 02 43 00 00 10 52 45 4c 49 53 59 53 20 ....C...RELISYS 016: 41 56 45 43 20 49 49 20 53 33 20 20 20 20 20 20 AVEC II S3 032: 31 2e 30 37 31 2e 30 37 00 01 54 45 43 4f 20 56 1.071.07..TECO V 048: 4d 33 35 36 34 20 00 01 01 2c 00 01 02 58 09 f6 M3564 ...,...X.. 064: 0d af 01 2c 00 08 01 00 ...,.... TECO VM3564 (2) 000: 06 00 02 02 43 00 00 10 52 45 4c 49 53 59 53 20 ....C...RELISYS 016: 41 56 45 43 20 49 49 20 53 33 20 20 20 20 20 20 AVEC II S3 032: 31 2e 30 39 31 2e 30 39 00 01 54 45 43 4f 20 56 1.091.09..TECO V 048: 4d 33 35 36 34 20 00 01 01 2c 00 01 02 58 09 f6 M3564 ...,...X.. 064: 0d af 01 2c 00 08 01 00 ...,.... TECO VM356A (1) 000: 06 00 02 02 43 00 00 00 52 45 4c 49 53 59 53 20 ....C...RELISYS 016: 41 50 4f 4c 4c 4f 20 45 78 70 72 65 73 73 20 33 APOLLO Express 3 032: 31 2e 30 33 31 2e 30 33 00 01 54 45 43 4f 20 56 1.031.03..TECO V 048: 4d 33 35 36 41 20 00 01 01 2c 00 01 02 58 09 f6 M356A ...,...X.. 064: 0d af 01 2c 00 08 01 00 ...,.... TECO VM356A (2) 000: 06 00 02 02 43 00 00 10 50 72 69 6d 61 78 20 20 ....C...Primax 016: 4a 65 77 65 6c 20 20 20 20 20 20 20 20 20 20 20 Jewel 032: 31 2e 30 31 31 2e 30 31 00 01 54 45 43 4f 20 56 1.011.01..TECO V 048: 4d 33 35 36 41 20 00 01 01 2c 00 01 02 58 09 f6 M356A ...,...X.. 064: 0d af 01 2c 00 08 01 00 ...,.... TECO VM3575 000: 06 00 02 02 43 00 00 00 20 20 20 20 20 20 20 20 ....C... 016: 46 6c 61 74 62 65 64 20 53 63 61 6e 6e 65 72 20 Flatbed Scanner 032: 31 2e 30 33 31 2e 30 33 00 01 54 45 43 4f 20 56 1.031.03..TECO V 048: 4d 33 35 37 35 20 00 01 01 2c 00 01 02 58 09 f6 M3575 ...,...X.. 064: 0d af 01 2c 00 08 01 00 ...,.... TECO VM656A 000: 06 00 02 02 43 00 00 00 52 45 4c 49 53 59 53 20 ....C...RELISYS 016: 41 50 4f 4c 4c 4f 20 45 78 70 72 65 73 73 20 36 APOLLO Express 6 032: 31 2e 30 33 31 2e 30 33 00 01 54 45 43 4f 20 56 1.031.03..TECO V 048: 4d 36 35 36 41 00 01 01 2c 00 01 02 58 09 f6 0d M656A...,...X... 064: af 01 2c 00 08 01 00 00 ..,..... TECO VM6575 000: 06 00 02 02 43 00 00 10 52 45 4c 49 53 59 53 20 ....C...RELISYS 016: 53 43 4f 52 50 49 4f 20 50 72 6f 20 20 20 20 20 SCORPIO Pro 032: 31 2e 30 31 31 2e 30 31 00 01 54 45 43 4f 20 56 1.011.01..TECO V 048: 4d 36 35 37 35 20 00 01 01 2c 00 01 02 58 09 f6 M6575 ...,...X.. 064: 0d af 01 2c 00 08 01 00 ...,.... TECO VM6586 000: 06 00 02 02 43 00 00 00 20 20 20 20 20 20 20 20 ....C... 016: 46 6c 61 74 62 65 64 20 53 63 61 6e 6e 65 72 20 Flatbed Scanner 032: 33 2e 30 31 33 2e 30 31 00 01 54 45 43 4f 20 56 3.013.01..TECO V 048: 4d 36 35 38 36 20 00 01 01 2c 00 01 02 58 09 f6 M6586 ...,...X.. 064: 0d af 01 2c 00 08 01 00 ...,.... /*--------------------------------------------------------------------------*/ SCSI Commands supported by the TECO VM3575: REQUEST SENSE 03 00 00 00 12 00 VENDOR-06 ??? Receives 4 bytes of data VENDOR-9 Get calibration lines - 12 lines 2 = ? 0x00 color scan 0x01 grayscal scan 0x02 b&w scan Returns 6 bytes per pixel, probably 2 bytes per color in little endian order. (2550 * 6 = 15300) VENDOR-0C ??? Unsupported? VENDOR-0E Set calibration. Apparently the line is computed from the calibration lines. It is not an average though. INQUIRY 12 00 00 00 48 00 standard inquiry 72 bytes 32-39: firmware version 42-52: real scanner name 54-55: min X resolution 56-57: max X resolution 58-59: min Y resolution 60-61: max Y resolution 62-63: scan area length 64-65: scan area width 66-67: unit for scan area (eg 300th of inch) eg if 62-63 = 2550 and 66-67 = 300, the length is 2550/300=8.5 inches. SCAN 1B 00 00 00 00 00 VENDOR-1C 1c 00 00 00 00 00 (Same opcode as RECEIVE DIAGNOSTIC RESULTS) sends 4 bytes of data. SET WINDOW 24 00 00 00 00 00 00 00 35 00 (VM3575) 24 00 00 00 00 00 00 00 38 00 (VM6586) Total length is 07 = length VM3575 53-8 = 45 VM6586 56-8 = 48 VM3552 69-8 = 61 10-11 = X Resolution 12-13 = Y resolution 14-17 = X top left corner 18-21 = Y top left corner 22-25 = width (size in inches * 300) 26-29 = length (size in inches * 300) 31 = 0x80 ? 33 = scan mode 0x00 = black & white 0x02 = grayscale 0x05 = color 34 = bit depth? - invariant, always 8 36 = (vm6586 only ?) halftone pattern ? 1 = type 1 dithering 37 = 0x80 = RIF? 48 = color channel to use if scan mode is 0 or 2: 0x00 = red 0x01 = green 0x02 = blue if scan mode is 05 -> ignored TWAIN leaves 0x02 50 = ? VM6585 only: 52-53 = size of a line expected? 54-55 = number of lines expected? READ 28 00 00 00 00 19 00 1f 0e 00 5 = number of lines to read 7-8 = buffer size. Always number of lines to read * size of a line. 0x2000 appears to be the upper limit SEND 2A 00 03 00 00 04 00 0C 00 00 2 = data type code 0x03 = gamma 4-5 = data type qualifier (?) 6-8 = length (0xc00 = 3276 = 3*2^10) or: 5-6: length of each gamma 7-8: length of all gamma OBJECT POSITION 31 00 00 00 00 00 00 00 00 00 Park the CCD. GET DATA BUFFER STATUS 34 01 00 00 00 00 00 00 12 00 1 = bit 1 is wait 7-8 = allocation length returned buffer is 0x12 bytes long. 00 00 0f 00 00 00 00 14 00 00 00 80 1b 6c 09 f6 05 05 0-2 = additional length (0x12-3 = 0x0F) 7 = ? always 0x14 11 = bit 7 - (maybe) scanner is ready to send data 12-13 = number of lines (constant during a scan) 14-15 = bytes per line (constant during a scan) 16-17 = garbage (the command only returns 0x10 bytes) /*--------------------------------------------------------------------------*/ Scan sequence Get some info: INQUIRY Setup the scan: REQUEST SENSE TUR SET WINDOWS GET BUFFER STATUS VENDOR-0C VENDOR-09 (read calibration) VENDOR-0E (send new calibration) REQUEST SENSE SEND(10) SET WINDOWS (same as the first one) COMMAND 06 RECEIVE DIAGNOSTIC RESULTS SCAN GET BUFFER STATUS loop until all data read: READ(10) park the CCD: OBJECT POSITION /*--------------------------------------------------------------------------*/ calibration TECO VM3575 reads 12 lines of calibration TECO VM656A reads 8 lines of calibration TECO VM6586 ?? Algorithms used (text from Alex Wulms): The old algorithm was based on the assumption that the calibration value needs to be an offset, to go from the value obtained during input to the average value (0x800). E.g., if the input value is 0x800, the calibration value must be 0x800 (0x1000 - 0x800). Likewise, if the input value is 0x700, the calibration value must be 0x900 (0x1000 - 0x700) And if the input value is 0x600, the calibration value must be 0xA00 The new algorithm is based on the assumption that the calibration needs to be a multiplication factor, to compensate for the too strong or too weak pixel in the sensor. Again, we want to obtain the average value (approximately 0x800) for every pixel read during calibration. E.g., if the input value is 0x800, the calibration value must be 0x800 (0x800*0x800 / 0x800). Likewise, if the input value is 0x700, the calibration value must be 0x924 (0x800*0x800 / 0x700). And if the input value is 0x600, the calibration value must 0xAAA (0x800*0x800 / 0x600) Though, carefull comparison with scans done under windows has shown that the factor is slightly different from 0x800*0x800(=0x400000) but in stead it seems to be approximately 0x40302f (which would mean that the average value is approximately 0x803 in stead of 0x800). Hope this is clarifies the new algorithm. sane-backends-1.0.27/doc/teco/teco3.txt0000664000175000017500000001100512112021330014455 00000000000000 BACKEND TECO3 This scanner capabilities are in the middle of the 3520 and 3575, sharing features of both. Hence a third backend. PIOTECH 3024 (TECO Scorpio/Taurus Infinity VM3552): 000: 06 00 02 02 43 00 00 10 20 20 20 20 20 20 20 20 ....C... 016: 46 6c 61 74 2d 62 65 64 20 73 63 61 6e 6e 65 72 Flat-bed scanner 032: 35 2e 30 38 35 2e 30 38 03 02 54 45 43 4f 20 56 5.085.08..TECO V 048: 4d 33 35 35 32 20 00 01 01 2c 00 01 04 b0 09 f6 M3552 ...,...... 064: 10 68 01 2c 00 00 00 01 .h.,.... RELISYS INFINiTY SCORPIO: 000: 06 00 02 02 43 00 00 10 52 45 4c 49 53 59 53 20 ....C...RELISYS 016: 53 63 6f 72 70 69 6f 20 20 20 20 20 20 20 20 20 Scorpio 032: 31 2e 30 34 31 2e 30 34 03 02 54 45 43 4f 20 56 1.041.04..TECO V 048: 4d 33 35 35 32 20 00 01 01 2c 00 01 04 b0 09 f6 M3552 ...,...... 064: 10 68 01 2c 00 00 00 00 .h.,.... Trust Imagery 2400SP: 000: 06 00 02 02 43 00 00 10 41 61 73 68 69 6d 61 20 ....C...Aashima 016: 49 4d 41 47 45 52 59 20 32 34 30 30 53 50 20 20 IMAGERY 2400SP 032: 31 2e 30 30 31 2e 30 30 03 02 54 45 43 4f 20 56 1.001.00..TECO V 048: 4d 33 35 35 32 20 00 01 01 2c 00 01 04 b0 09 f6 M3552 ...,...... 064: 10 68 01 2c 00 00 00 01 .h.,.... Trust Imagery 4800 SP +: 000: 06 00 02 02 43 00 00 10 41 61 73 68 69 6d 61 20 ....C...Aashima 016: 49 4d 41 47 45 52 59 20 34 38 30 30 53 50 20 2b IMAGERY 4800SP + 032: 35 2e 30 38 35 2e 30 38 03 02 54 45 43 4f 20 56 5.085.08..TECO V 048: 4d 33 35 35 32 20 00 01 01 2c 00 01 04 b0 09 f6 M3552 ...,...... 064: 10 68 01 2c 00 00 00 00 .h.,.... /*--------------------------------------------------------------------------*/ SCSI commands supported by the RELISYS VM3530+: TEST UNIT READY 00 00 00 00 00 00 REQ SENSE 03 00 00 00 12 00 VENDOR-09 09 00 00 78 00 00 3-4 = length of data to receive. Always 30720 bytes. Probably 12 lines of calibration at 300dpi. 8.5*300*12=30600 VENDOR-0E (?) 0E 00 00 00 00 00 Always follows VENDOR-09 command INQUIRY: 12 00 00 00 35 00 standard inquiry 52 bytes - appears to never change 32-39: firmware version 42-52: real scanner name SCAN 1B 00 00 00 00 00 SET WINDOW 24 00 00 00 00 00 00 00 45 00 (3552) Total length is 99 07 = length (99-8 = 91) 10-11 = X Resolution 12-13 = Y resolution 14-17 = X top left corner 18-21 = Y top left corner 22-25 = width (size in inches * 300) 26-29 = length (size in inches * 300) 31 = 0x80 ? 33 = scan mode 0x00 = black & white 0x02 = grayscale 0x05 = color 34 = bit depth? - invariants, always 8 36 = dither pattern - only for B&W 0x00 = line art 0x01 = 2 X 2 0x02 = 3 X 3 0x03 = 4 X 4 Bayer 0x04 = 4 X 4 Smooth 0x05 = 8 X 8 Bayer 0x06 = 8 X 8 Smooth 0x07 = 8 X 8 Horizontal 0x08 = 8 X 8 Vertical 37 = 0x80 = RIF ? 48 = color channel to use if scan mode is 0 or 2: 0x00 = red 0x01 = green 0x02 = blue if scan mode is 05 -> ignored TWAIN leaves 0x02 50: calibration 00 = yes 02 = no 53, 57, 61, 65: 0xff READ 28 00 00 00 00 00 00 00 3E 00 6-8 = length SEND 2A 00 03 00 00 02 00 04 00 00 2 = data type code 0x03 = gamma - 4*256 bytes OBJECT POSITION 31 00 00 00 00 00 00 00 00 00 Park the CCD. GET DATA BUFFER STATUS 34 01 00 00 00 00 00 00 12 00 1 = bit 1 is wait 7-8 allocation length returned buffer is 0x10 bytes long. 0-2 = additional length (0x10-3 = 0x0D) 3 = reserved(?) 6-8 = scanner memory (with no RAM, it is 32KB on the VM3552) 9-11 = filled data buffer 12-13 = number of lines (constant during a scan) 14-15 = bytes per line (constant during a scan) 16 = ? 17 = in color mode, 0x07 seems to means to the colors are shifted and given by rasters. 0x00 seems to mean that there is no color shifting and that each pixel is coded by 3 consecutive bytes. /*--------------------------------------------------------------------------*/ Command sequence (simplified, since the TWAIN driver seems to be quite stupid) Get some info: INQUIRY Setup the scan: TUR SET WINDOWS GET BUFFER STATUS VENDOR-09 VENDOR-0E SEND(10) SET WINDOWS (same as the first one) SCAN loop until all data read: GET BUFFER STATUS READ(10) if any data available park the CCD: OBJECT POSITION /*--------------------------------------------------------------------------*/ sane-backends-1.0.27/doc/net.tex0000664000175000017500000004734512112021330013275 00000000000000\chapter{Network Protocol}\label{chap:net} The SANE interface has been designed to facilitate network access to image acquisition devices. In particular, most SANE implementations are expected to support a network backend (net client) and a corresponding network daemon (net server) that allows accessing image acquisition devices through a network connection. Network access is useful in several situations: \begin{itemize} \item To provide controlled access to resources that are inaccessible to a regular user. For example, a user may want to access a device on a host where she has no account on. With the network protocol, it is possible to allow certain users to access scanners without giving them full access to the system. Controlling access through the network daemon can be useful even in the local case: for example, certain backends may require root privileges to access a device. Rather than installing each frontend as setuid-root, a system administrator could instead install the SANE network daemon as setuid-root. This enables regular users to access the privileged device through the SANE daemon (which, presumably, supports a more fine-grained access control mechanism than the simple setuid approach). This has the added benefit that the system administrator only needs to trust the SANE daemon, not each and every frontend that may need access to the privileged device. \item Network access provides a sense of ubiquity of the available image acquisition devices. For example, in a local area network environment, this allows a user to log onto any machine and have convenient access to any resource available to any machine on the network (subject to permission constraints). \item For devices that do not require physical access when used (e.g., video cameras), network access allows a user to control and use these devices without being in physical proximity. Indeed, if such devices are connected to the Internet, access from any place in the world is possible. \end{itemize} The network protocol described in this chapter has been design with the following goals in mind: \begin{enumerate} \item Image transmission should be efficient (have low encoding overhead). \item Accessing option descriptors on the client side must be efficient (since this is a very common operation). \item Other operations, such as setting or inquiring the value of an option are less performance critical since they typically require explicit user action. \item The network protocol should be simple and easy to implement on any host architecture and any programming language. \end{enumerate} The SANE protocol can be run across any transport protocol that provides reliable data delivery. While SANE does not specify a specific transport protocol, it is expected that TCP/IP will be among the most commonly used protocols. \section{Data Type Encoding} \subsection{Primitive Data Types} The four primitive types of the SANE standard are encoded as follows: \begin{description} \item[\code{\defn{SANE\_Byte}}:] A byte is encoded as an 8 bit value. Since the transport protocol is assumed to be byte-orientd, the bit order is irrelevant. \item[\code{\defn{SANE\_Word}}:] A word is encoded as 4 bytes (32 bits). The bytes are ordered from most-significant to least-significant byte (big-endian byte-order). \item[\code{\defn{SANE\_Char}}:] A character is currently encoded as an 8-bit ISO LATIN-1 value. An extension to support wider character sets (16 or 32 bits) is planned for the future, but not supported at this point. \item[\code{\defn{SANE\_String}}:] A string pointer is encoded as a \code{SANE\_Char} array. The trailing NUL byte is considered part of the array and a \code{NULL} pointer is encoded as a zero-length array. \item[\code{\defn{SANE\_Handle}}:] A handle is encoded like a word. The network backend needs to take care of converting these integer values to the opaque pointer values that are presented to the user of the network backend. Similarly, the SANE daemon needs to take care of converting the opaque pointer values it receives from its backends into 32-bit integers suitable for use for network encoding. \item[{\em\defn{enumeration types}}:] Enumeration types are encoded like words. \end{description} \subsection{Type Constructors} Closely following the type constructors of the C language, the SANE network protocol supports the following four constructors: \begin{description} \item[{\em\defn{pointer}}:] A pointer is encoded by a word that indicates whether the pointer is a NULL-pointer which is then followed by the value that the pointer points to (in the case of a non-NULL pointer; in the case of a NULL pointer, no bytes are encoded for the pointer value). \item[{\em\defn{array}}:] An array is encoded by a word that indicates the length of the array followed by the values of the elements in the array. The length may be zero in which case no bytes are encoded for the element values. \item[{\em\defn{structure}}:] A structure is encoded by simply encoding the structure members in the order in which they appear in the corresponding C type declaration. \item[{\em\defn{union}}:] A union must always be accompanied by a tag value that indicates which of the union members is the currently the active one. For this reason, the union itself is encoded simply by encoding the value of the currently active member. \end{description} Note that for type constructors, the pointer, element, or member values themselves may have a constructed type. Thus, the above rules should be applied recursively until a sequence of primitive types has been found. Also SANE had no need for encoding of circular structures. This greatly simplifies the network protocol. \section{Remote Procedure Call Requests} The SANE network protocol is a client/server-style remote procedure call (RPC) protocol. This means that all activity is initiated by the client side (the network backend)---a server is restricted to answering requests sent by the client. The data transferred from the client to the server is comprised of the RPC code (as a \code{SANE\_WORD}), followed by arguments defined in the {\bf request} column below. The format of the server's answer is given in the {\bf reply} column. \subsection{\code{\defn{SANE\_NET\_INIT}}} RPC Code: 0 This RPC establishes a connection to a particular SANE network daemon. It must be the first call in a SANE network session. The parameter and reply arguments for this call are shown in the table below: \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_Word version\_code} & \code{SANE\_Word status} \\ \code{SANE\_String user\_name} & \code{SANE\_Word version\_code} \\ \end{tabular} \end{center} The \code{version\_code} argument in the request is the SANE version-code of the network backend that is contacting the network daemon (see Section~\ref{sec:saneversioncode}). The ``build-revision'' in the version code is used to hold the network protocol version. The SANE network daemon receiving such a request must make sure that the network protocol version corresponds to a supported version since otherwise the encoding of the network stream may be incompatible (even though the SANE interface itself may be compatible). The \code{user\_name} argument is the name of the user on whose behalf this call is being performed. If the network backend cannot determine a user-name, it passes a \code{NULL} pointer for this argument. No trust should be placed in the authenticity of this user-name. The intent of this string is to provide more convenience to the user. E.g., it could be used as the default-user name in subsequent authentication calls. In the reply, \code{status} indicates the completion status. If the value is anything other than \code{SANE\_STA\-TUS\_GOOD}, the remainder of the reply has undefined values.\footnote{The sane network daemon should be careful not to leak information in the undefined portion of the reply.} The \code{version\_code} argument returns the SANE version-code that the network daemon supports. See the comments in the previous paragraph on the meaning of the build-revision in this version code. \subsection{\code{\defn{SANE\_NET\_GET\_DEVICES}}} RPC Code: 1 This RPC is used to obtain the list of devices accessible by the SANE daemon. \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{void} & \code{SANE\_Word status} \\ & \code{SANE\_Device ***device\_list} \\ \end{tabular} \end{center} There are no arguments in the request for this call. In the reply, \code{status} indicates the completion status. If the value is anything other than \code{SANE\_STA\-TUS\_GOOD}, the remainder of the reply has undefined values. The \code{device\_list} argument is a pointer to a \code{NULL}-terminated array of \code{SANE\_Device} pointers. \subsection{\code{\defn{SANE\_NET\_OPEN}}} RPC Code: 2 This RPC is used to open a connection to a remote SANE device. \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_String device\_name} & \code{SANE\_Word status} \\ & \code{SANE\_Word handle} \\ & \code{SANE\_String resource} \\ \end{tabular} \end{center} The \code{device\_name} argument specifies the name of the device to open. In the reply, \code{status} indicates the completion status. If the value is anything other than \code{SANE\_STA\-TUS\_GOOD}, the remainder of the reply has undefined values. The \code{handle} argument specifies the device handle that uniquely identifies the connection. The \code{resource} argument is used to request authentication. If it has a non-\code{NULL} value, the network backend should authenticate the specified resource and then retry this operation (see Section~\ref{sec:authorization} for details on how to authorize a resource). \subsection{\code{\defn{SANE\_NET\_CLOSE}}} RPC Code: 3 This RPC is used to close a connection to a remote SANE device. \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_Word handle} & \code{SANE\_Word dummy} \\ \end{tabular} \end{center} The \code{handle} argument identifies the connection that should be closed. In the reply, the \code{dummy} argument is unused. Its purpose is to ensure proper synchronization (without it, a net client would not be able to determine when the RPC has completed). \subsection{\code{\defn{SANE\_NET\_GET\_OPTION\_DESCRIPTORS}}} RPC Code: 4 This RPC is used to obtain {\em all\/} the option descriptors for a remote SANE device. \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_Word handle} & \code{Option\_Descriptor\_Array odesc} \\ \end{tabular} \end{center} The \code{handle} argument identifies the remote device whose option descriptors should be obtained. In the reply, the \code{odesc} argument is used to return the array of option descriptors. The option descriptor array has the following structure: \begin{quote}\index{Option\_Descriptor\_Array} \begin{verbatim} struct Option_Descriptor_Array { SANE_Word num_options; SANE_Option_Descriptor **desc; }; \end{verbatim} \end{quote} \subsection{\code{\defn{SANE\_NET\_CONTROL\_OPTION}}} RPC Code: 5 This RPC is used to control (inquire, set, or set to automatic) a specific option of a remote SANE device. \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_Word handle} & \code{SANE\_Status status} \\ \code{SANE\_Word option} & \code{SANE\_Word info} \\ \code{SANE\_Word action} & \code{SANE\_Word value\_type} \\ \code{SANE\_Word value\_type} & \code{SANE\_Word value\_size} \\ \code{SANE\_Word value\_size} & \code{void *value} \\ \code{void *value} & \code{SANE\_String *resource} \\ \end{tabular} \end{center} The \code{handle} argument identifies the remote device whose option should be controlled. Argument \code{option} is the number (index) of the option that should be controlled. Argument \code{action} specifies what action should be taken (get, set, or set automatic). Argument \code{value\_type} specifies the type of the option value (must be one of \code{SANE\_TYPE\_BOOL}, \code{SANE\_TYPE\_INT}, \code{SANE\_TYPE\_FIXED}, \code{SANE\_TYPE\_STR\-ING}, \code{SANE\_TYPE\_BUTTON}). Argument \code{value\_size} specifies the size of the option value in number of bytes (see Section~\ref{sec:valuesize} for the precise meaning of this value). Finally, argument \code{value} is a pointer to the option value. It must be a writeable area that is at least \code{value\_size} bytes large. (Note that this area must be writable even if the action is to set the option value. This is because the backend may not be able to set the exact option value, in which case the option value is used to return the next best value that the backend has chosen.) In the reply, argument \code{resource} is set to the name of the resource that must be authorized before this call can be retried. If this value is non-\code{NULL}, all other arguments have undefined values (see Section~\ref{sec:authorization} for details on how to authorize a resource). Argument \code{status} indicates the completion status. If the value is anything other than \code{SANE\_STA\-TUS\_GOOD}, the remainder of the reply has undefined values. The \code{info} argument returns the information on how well the backend was able to satisfy the request. For details, see the description of the corresponding argument in Section~\ref{sec:control}. Arguments \code{value\_type} and \code{value\_size} have the same values as the arguments by the same name in corresponding request. The values are repeated here to ensure that both the request and the reply are self-contained (i.e., they can be encoded and decoded independently). Argument \code{value} is holds the value of the option that has become effective as a result of this RPC. \subsection{\code{\defn{SANE\_NET\_GET\_PARAMETERS}}} RPC Code: 6 This RPC is used to obtain the scan parameters of a remote SANE device. \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_Word handle} & \code{SANE\_Status status} \\ & \code{SANE\_Parameters params} \\ \end{tabular} \end{center} The \code{handle} argument identifies the connection to the remote device whose scan parameters should be returned. In the reply, \code{status} indicates the completion status. If the value is anything other than \code{SANE\_STA\-TUS\_GOOD}, the remainder of the reply has undefined values. The argument \code{params} is used to return the scan parameters. \subsection{\code{\defn{SANE\_NET\_START}}} RPC Code: 7 This RPC is used to start image acquisition (scanning). \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_Word handle} & \code{SANE\_Status status} \\ & \code{SANE\_Word port} \\ & \code{SANE\_Word byte\_order} \\ & \code{SANE\_String resource} \\ \end{tabular} \end{center} The \code{handle} argument identifies the connection to the remote device from which the image should be acquired. In the reply, argument \code{resource} is set to the name of the resource that must be authorized before this call can be retried. If this value is non-\code{NULL}, all other arguments have undefined values (see Section~\ref{sec:authorization} for details on how to authorize a resource). Argument, \code{status} indicates the completion status. If the value is anything other than \code{SANE\_STA\-TUS\_GOOD}, the remainder of the reply has undefined values. The argument \code{port} returns the port number from which the image data will be available. To read the image data, a network client must connect to the remote host at the indicated port number. Through this port, the image data is transmitted as a sequence of data records. Each record starts with the data length in bytes. The data length is transmitted as a sequence of four bytes. These bytes should be interpreted as an unsigned integer in big-endian format. The four length bytes are followed by the number of data bytes indicated by the length. Except for byte-order, the data is in the same format as defined for \code{sane\_read()}. Since some records may contain no data at all, a length value of zero is perfectly valid. The special length value of \code{0xffffffff} is used to indicate the end of the data stream. That is, after receiving a record length of \code{0xffffffff}, the network client should close the data connection and stop reading data. Argument \code{byte\_order} specifies the byte-order of the image data. A value of 0x1234 indicates little-endian format, a value of 0x4321 indicates big-endian format. All other values are presently undefined and reserved for future enhancements of this protocol. The intent is that a network server sends data in its own byte-order and the client is responsible for adjusting the byte-order, if necessary. This approach causes no unnecessary overheads in the case where the server and client byte-order match and puts the extra burden on the client side when there is a byte-order mismatch. Putting the burden on the client-side improves the scalability properties of this protocol. \subsection{\code{\defn{SANE\_NET\_CANCEL}}} RPC Code: 8 This RPC is used to cancel the current operation of a remote SANE device. \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_Word handle} & \code{SANE\_Word dummy} \\ \end{tabular} \end{center} The \code{handle} argument identifies the connection whose operation should be cancelled. In the reply, the \code{dummy} argument is unused. Its purpose is to ensure proper synchronization (without it, a net client would not be able to determine when the RPC has completed). \subsection{\code{\defn{SANE\_NET\_AUTHORIZE}}}\label{sec:authorization} \index{network authorization} RPC Code: 9 This RPC is used to pass authorization data from the net client to the net server. \begin{center} \begin{tabular}{ll} {\bf request:} & {\bf reply:} \\ \code{SANE\_String resource} & \code{SANE\_Word dummy} \\ \code{SANE\_String username} & \\ \code{SANE\_String password} & \\ \end{tabular} \end{center} The \code{resource} argument specifies the name of the resource to be authorized. This argument should be set to the string returned in the \code{resource} argument of the RPC reply that required this authorization call. The \code{username} and \code{password} are the name of the user that is accessing the resource and the password for the specified resource/user pair. Since the password is not encrypted during network transmission, it is recommended to use the following extension: If the server adds the string `\code{\$MD5\$}' to the resource-name followed by a random string not longer then 128 bytes, the client may answer with the MD5 digest of the concatenation of the password and the random string. To differentiate between the MD5 digest and a strange password the client prepends the MD5 digest with the string `\code{\$MD5\$}'. In the reply, \code{dummy} is completely unused. Note that there is no direct failure indication. This is unnecessary since a net client will retry the RPC that resulted in the authorization request until that call succeeds (or until the request is cancelled). The RPC that resulted in the authorization request continues after the reply from the client and may fail with \code{SANE\_STATUS\_ACCESS\_DENIED}. \subsection{\code{\defn{SANE\_NET\_EXIT}}} RPC Code: 10 This RPC is used to disconnect a net client from a net server. There are no request or reply arguments in this call. As a result of this call, the connection between the client and the server that was established by the \code{SANE\_NET\_INIT} call will be closed. % Local Variables: % mode: latex % TeX-master: "sane.tex" % End: sane-backends-1.0.27/doc/sane-magicolor.man0000664000175000017500000000536112775277260015410 00000000000000.\" .IX sane-magicolor .TH "sane-magicolor" "5" "10 Jan 2011" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .SH "NAME" sane\-magicolor \- SANE backend for KONICA MINOLTA magicolor scanners .SH "DESCRIPTION" The .B sane\-magicolor backend supports KONICA MINOLTA magicolor scanners connected via USB or LAN. Currently, only the magicolor 1690MF device is supported, no other devices with the same scanning protocol are known. .SH "SUPPORTED DEVICES" The following scanner should work with this backend: Device Details .br \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- .br Vendor: KONICA MINOLTA .br Model: magicolor 1690MF .SH "CONFIGURATION" .PP This section describes the backend's configuration file entries. The file is located at: .IP .I @CONFIGDIR@/magicolor.conf .PP For a proper setup, at least one of the following entries are needed: .IP .I net autodiscovery .br .I net [IP ADDRESS] [DEVICE-ID] .br .I usb .br .I usb [VENDOR-ID] [DEVICE-ID] .SH "FILES" .TP .I @CONFIGDIR@/magicolor.conf The backend configuration file .TP .I @LIBDIR@/libsane\-magicolor.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-magicolor.so The shared library implementing this backend (present on systems that support dynamic loading). .SH "ENVIRONMENT" .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi\-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "/tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_MAGICOLOR If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_MAGICOLOR=127 To obtain debug messages from the backend, set this environment variable before calling your favorite frontend (e.g. xscanimage). Example: SANE_DEBUG_MAGICOLOR=65 xscanimage .SH "KNOWN BUGS AND RESTRICTIONS" .PP Large color scans may sometimes timeout due to unknown reasons (the scanner simply stops returning data) .PP Cancelling large scans may lock up the scanner. .SH "SEE ALSO" .BR sane (7), .br .I http://wiki.kainhofer.com/hardware/magicolor_scan .SH "AUTHOR" .PP Reinhold Kainhofer sane-backends-1.0.27/doc/sane-dc240.man0000664000175000017500000000743512112021330014216 00000000000000.TH sane\-dc240 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-dc240 .SH NAME sane\-dc240 \- SANE backend for Kodak DC240 Digital Camera .SH DESCRIPTION The .B sane\-dc240 library implements a SANE (Scanner Access Now Easy) backend that provides access to the Kodak DC240 camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! .SH "DEVICE NAMES" The current version of the backend only allows one camera to be connected. The device name is always "0". .SH CONFIGURATION The contents of the .I dc240.conf specify the serial port and baud rate to use. The baud rate specifies the maximum rate to use while downloading pictures. (The camera is always initialized using 9600 baud, then switches to the higher rate). On a 450MHz Pentium, I usually have no problems downloading at 115200 baud, though the camera sometimes has to resend packets due to lost characters. Results are better when the "interrupt-unmask flag" is set in the IDE driver (hdparm \-u1). Supported baud rates are: 9600, 19200, 38400, 57600, and 115200. .PP The dumpinquiry line causes some information about the camera to be printed. .PP cmdrespause specifies how many usec (1,000,000ths of a) between writing the command and reading the result should be used. 125000 seems to be the lowest I could go reliably. .PP breakpause is the time in 1,000,000ths of a usec between sending the "back to default" break sending commands. .PP Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS port=/dev/ttyS0 .br # this is a comment .br baud=115200 .br dumpinquiry .br cmdrespause=125000 .br breakpause=1000000 .RE .PP .SH FILES .TP .I @CONFIGDIR@/dc240.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-dc240.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-dc240.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_DC240 If the library was compiled with debugging support enabled, this environment variable controls the debug level for this backend. A value of 128 requests maximally copious debug output; smaller levels reduce verbosity. .SH "SEE ALSO" sane(7) .SH AUTHOR Peter S. Fales .PP This backend borrows heavily from the dc210 backend by Brian J. Murrell which is based somewhat on the dc25 backend by Peter Fales. .PP The manpage was largely copied from the dc210 manpage. .SH BUGS The major limitation that I know of is that the backend assumes the directory in the camera is 100dc240. Once the camera has taken more than 9999 pictures, the directory will increment to 101dc240. Not only should we check for the additional directory, but pictures may actually be found in multiple directories. .PP More general comments, suggestions, and inquiries about frontends or SANE should go to the SANE Developers mailing list (see http://www.sane\-project.org/mailing\-lists.html for details). You must be subscribed to the list, otherwise your mail won't be sent to the subscribers. sane-backends-1.0.27/doc/sane-artec_eplus48u.man0000664000175000017500000001250512112021330016243 00000000000000.TH sane\-artec_eplus48u 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE" .SH NAME sane\-artec_eplus48u \- SANE backend for the scanner Artec E+ 48U and re-badged models .SH DESCRIPTION The .B sane\-artec_eplus48u library implements a SANE (Scanner Access Now Easy) backend that provides access to several USB flatbed scanners using the GT6816 chipset like the Artec E+ 48U. These scanners have a contact image sensor (CIS) and an USB interface. .PP A complete list of supported devices can be found on .IR http://www.sane\-project.org/sane\-supported\-devices.html . .PP This is ALPHA software. Especially if you test new or untested scanners, keep your hand at the scanner's plug and unplug it, if the head bumps at the end of the scan area. .PP If you own a scanner other than the ones mentioned on the list that works with this backend, please let us know this by sending the scanner's exact model name and the USB vendor and product ids (e.g. from /proc/bus/usb/devices, sane\-find\-scanner or syslog) to me. Even if the scanner's name is only slightly different from the models mentioned above, please let me know. .PP .SH KERNEL ISSUES If libusb-0.1.6 or later is installed, this section can be skipped. The scanner should be found by sane\-find\-scanner without further actions. For setting permissions and general USB information look at sane\-usb(5). .PP When you are using the scanner module, a Linux kernel 2.4.12 or newer is required. .SH FIRMWARE FILE You need a firmware file for your scanner. That's a small file containing software that will be uploaded to the scanner's memory. For the scanners mentioned above, it's usually named Artec48.usb or 1200.usb. You can find it on the installation CD that was provided by the manufacturer, normally in the directory Win98, WinMe or similar. If the Windows-driver is installed on your computer, then you can also find the firmware file under c:\\windows\\system32\\drivers. .SH CONFIGURATION The contents of the .I artec_eplus48u.conf file is a list of usb lines containing vendor and product ids that correspond to USB scanners. The file can also contain option lines. Empty lines and lines starting with a hash mark (#) are ignored. The scanners are autodetected by .I usb vendor_id product_id statements which are already included into .I artec_eplus48u.conf . "vendor_id" and "product_id" are hexadecimal numbers that identify the .B scanner. .PP Every usb section can have additional options .TP .B artecFirmwareFile @DATADIR@/sane/artec_eplus48u/Artec48.usb The path to the firmware file. This option is required. .TP .B redGamma 1.0 .TP .B greenGamma 1.0 .TP .B blueGamma 1.0 .TP .B masterGamma 1.9 These are the default gamma values. If you set the "Defaults" option with a frontend, then the gamma options are reset to the values specified here. .TP .B redOffset 0x28 .TP .B greenOffset 0x2f .TP .B blueOffset 0x2f .TP .B redExposure 0xa7 .TP .B greenExposure 0x116 .TP .B blueExposure 0xdc These are the default values for offset and exposure time. You can e.g. change them to speed up calibration, if you don't want to save the calibration data to disk. .TP .B vendorString "Artec" .TP .B modelString "E+ 48U" By default, the scanner is reported as "Artec E+ 48U". If you don't like this, e.g. because you have an Tevion MD 9693, then change the options accordingly. .SH FILES .TP .I /usr/local/etc/sane.d/artec_eplus48u.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I /usr/local/lib/sane/libsane\-artec_eplus48u.a The static library implementing this backend. .TP .I /usr/local/lib/sane/libsane\-artec_eplus48u.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in /usr/local/etc/sane.d. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "/usr/local/etc/sane.d" being searched (in this order). .TP .B SANE_DEBUG_ARTEC_EPLUS48U If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_ARTEC_EPLUS48U=3 .SH "SEE ALSO" sane(7), sane\-usb(5) .SH AUTHOR Michael Herder .br This backend is based on the gt68xx test-program written by Sergey Vlasov, Andreas Nowack, and David Stevenson. Thanks to everyone who tested the backend or reported bugs. .br This man page is based on man sane\-gt68xx, written by Henning Meier-Geinitz. .SH BUGS This backend has been tested on Linux only. If you are using it on a different platform, please contact us. .PP Interpolation with 1200 dpi is weak. .PP Support for buttons is missing due to missing support in SANE. .PP Please contact us if you find a bug: .IR http://www.sane\-project.org/bugs.html . sane-backends-1.0.27/doc/sane-dmc.man0000664000175000017500000001132012112021330014131 00000000000000.TH sane\-dmc 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-dmc .SH NAME sane\-dmc \- SANE backend for the Polaroid Digital Microscope Camera .SH DESCRIPTION The .B sane\-dmc library implements a SANE (Scanner Access Now Easy) backend that provides access to the Polaroid Digital Microscope Camera. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the UNIX path-name for the special device that corresponds to the scanner. The special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. .SH IMAGING MODES The Polaroid DMC supports a number of imaging modes. This driver supports five of the imaging modes: .PP .TP .B Full Frame This mode corresponds to the 801-by-600 pixel full-color full-frame image. .TP .B Viewfinder This mode corresponds to the 270-by-201 pixel grey-scale viewfinder image. This image is acquired very quickly. .TP .B Raw This mode corresponds to the 1599-by-600 pixel "raw" image from the CCD. It is grey-scale, with pixels alternating horizontally between red, green and blue stripes. The pixels are twice as high as they are wide, so the image is distorted. .TP .B Thumbnail This mode corresponds to the 80-by-60 pixel full-color thumbnail image. .TP .B Super Resolution This image is a 1599-by-1200 pixel full-color image constructed by filtering and interpolating the "raw" image. The filtering and interpolation is done in software, so this mode is very slow. Also, this mode places restrictions on how the image is read which means that the "preview" mode of xscanimage does not work in Super Resolution mode. (xcam and the non-preview modes of scanimage and xscanimage work fine, however.) .PP .SH OTHER SETTINGS .TP .B ASA Setting This setting adjusts the camera's sensitivity. You can choose one of 25, 50, or 100 "equivalent" ASA. .TP .B Shutter Speed You can select a shutter speed from 8 to 1000 milliseconds. The shutter speed is quantized in units of 32 microseconds. .TP .B White Balance You can choose one of "Daylight", "Incandescent" or "Fluorescent" white balances. This setting more-or-less corresponds to the "Color Temperature" settings on Polaroid's Windows and Mac software. .SH CONFIGURATION The contents of the .I dmc.conf file is a list of device names that correspond to DMC scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS /dev/scanner .br # this is a comment .br /dev/sge .RE .SH FILES .TP .I @CONFIGDIR@/dmc.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-dmc.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-dmc.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_DMC If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH BUGS In the "Full Frame" and "Raw" modes, images must be read in units of entire lines. The driver performs no buffering in these modes; if you ask sane_read to read a non-integral number of lines, it may read less than you ask for. If you ask sane_read to read less than a single line, it returns SANE_STATUS_INVAL. .PP In the "Super Resolution" mode, images must be read in units of \fItwo\fR lines (3198 pixels or 9594 bytes.) If you try to read less than two lines, you get SANE_STATUS_INVAL. The Super Resolution mode is very slow. .PP In the "Viewfinder" and "Thumbnail" modes, the entire image must be read in one SCSI transfer. In this case, the driver performs buffering and you can read the image in as small an increment as you like. .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHOR David F. Skoll .PP The backend is derived from .BR sane\-hp by David Mosberger sane-backends-1.0.27/doc/sane-nec.man0000664000175000017500000000274212112021330014143 00000000000000.TH sane\-nec 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-nec .SH NAME sane\-nec \- SANE backend for NEC scanners .SH DESCRIPTION The .B sane\-nec library implements a SANE (Scanner Access Now Easy) backend that provides access to NEC SCSI scanners. This backend should be considered .B alpha-quality software! In the current state it is known to work with PC-IN500/4C scanners. Another MultiReader scanner series is not supported. PC-IN 500/4C and MultiReader scanner are only sold in Japan.(except Multi Reader PetiScan.) For other scanners, it may or may not work. .PP The backend has the following known problems: .RS \- ColorLineart mode is not supported. .br \- device name is fixed to /dev/scanner .RE .PP At present, the following scanners are known to work with this backend. .RS .ft CR .nf Vendor Product id ------ ----------- NEC PC-IN500/4C .fi .ft R .RE .SH FILES .TP .I @CONFIGDIR@/nec.conf The backend configuration file. .TP .I @LIBDIR@/libsane\-nec.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-nec.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_NEC If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHORS Kazuya Fukuda sane-backends-1.0.27/doc/sane-ma1509.man0000664000175000017500000001020512112021330014303 00000000000000.TH sane\-ma1509 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-ma1509 .SH NAME sane\-ma1509 \- SANE backend for Mustek BearPaw 1200F USB scanner .SH DESCRIPTION The .B sane\-ma1509 library implements a SANE (Scanner Access Now Easy) backend that provides access to the Mustek BearPaw 1200F USB flatbed scanner. This scanner is based on the MA-1509 chipset. Other scanners that use this chip (if they exist) may also work. .PP This backend is ALPHA software. Be careful and remove the power plug immediately if your hear unusual noises. .PP More details can be found on the ma1509 backend homepage .IR http://www.meier\-geinitz.de/sane/ma1509\-backend/ . .PP Other Mustek USB scanners are supported by the gt68xx, mustek_usb and the plustek backends. See .BR sane\-mustek_usb (5), .BR sane\-gt68xx (5) and .BR sane\-plustek (5) for details. .PP This backend can only work with scanners that are already detected by the operating system. See .BR sane\-usb (5) for details. .PP If you own a scanner other than the Mustek BearPaw 1200F that works with this backend, please let me know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .I /proc/bus/usb/devices or syslog) to me. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is a path-name for the special device that corresponds to a USB scanner. With Linux, such a device name could be .I /dev/usb/scanner0 or .IR libusb:001:002 , for example. .PP .SH CONFIGURATION The contents of the .I ma1509.conf file is a list of options and device names that correspond to Mustek BearPaw 1200F scanners. Empty lines and lines starting with a hash mark (#) are ignored. .PP Instead of using the device name, the scanner can be autodetected by .B "usb vendor_id product_id" statements which are already included into .IR ma1509.conf . This is only supported with Linux 2.4.8 and higher and all systems that support libsub. "vendor_id" and "product_id" are hexadecimal numbers that identify the scanner. If this doesn't work, a device name must be placed in .I ma1509.conf as described above. .PP To set the time the lamp needs for warm-up, use .B option .B warmup-time in .IR ma1509.conf . The time is given in seconds after the option. The default is 30 seconds. .SH FILES .TP .I @CONFIGDIR@/ma1509.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-ma1509.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-ma1509.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_MA1509 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .BR sane\-gt68xx (5), .BR sane\-plustek (5), .BR sane\-mustek_usb (5), .BR sane\-mustek (5), .BR sane\-mustek_pp (5), .br .I http://www.meier\-geinitz.de/sane/ma1509\-backend/ .SH AUTHOR Henning Meier-Geinitz .SH BUGS Resolutions higher than 600 dpi don't work .br Transparency adapter and automatic document feeder is not supported yet .br No support for "high-speed" mode (jpeg) .PP More detailed bug information is available at the MA-1509 backend homepage .IR http://www.meier\-geinitz.de/sane/ma1509-backend/ . sane-backends-1.0.27/doc/sane-umax1220u.man0000664000175000017500000000613012112021330015035 00000000000000.TH sane\-umax1220u 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-umax .SH NAME sane\-umax1220u \- SANE backend for the UMAX Astra 1220U and similar scanners .SH DESCRIPTION The .B sane\-umax1220 library implements a SANE (Scanner Access Now Easy) backend for the the UMAX Astra 1220U and similar scanners. For more information on this backend, please visit .IR http://umax1220u\-sane.sourceforge.net/ . .SH UMAX ASTRA 1600U/2000U/2100U SUPPORT This backend is also able to drive the UMAX Astra 1600U/2000U/2100U. The 2100U is confirmed to work. For the other scanners no reports have been received yet. Please contact us and tell us if your scanner works (sane\-devel@lists.alioth.debian.org). .SH CONFIGURATION Usually, no manual configuration is necessary. The configuration file for this backend resides in .IR @CONFIGDIR@/umax1220u.conf . Its contents is a list of device names that correspond to UMAX Astra scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .nf #usb vendor product usb 0x1606 0x0010 # Device list for non-linux systems /dev/scanner /dev/usb/scanner0 .fi See sane\-usb(5) for information on how to set the access permissions on the usb device files. .SH FILES .TP The backend configuration file: .I @CONFIGDIR@/umax1220u.conf .TP The static library implementing this backend: .I @LIBDIR@/libsane\-umax1220u.a .TP The shared library implementing this backend: .I @LIBDIR@/libsane\-umax1220u.so (present on systems that support dynamic loading) .SH ENVIRONMENT .TP .B SANE_DEBUG_UMAX1220U If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity: SANE_DEBUG_UMAX1220U values .ft CR .nf Number Remark \ 1 print failures 2 print information 3 print high-level function calls 4 print high-level function checkpoints 9 print mid-level function calls 10 print mid-level function checkpoints 80 print protocol-level function entry 90 print protocol-level function exit .fi .ft R .TP Example: export SANE_DEBUG_UMAX1220U=10 .SH KNOWN BUGS 600 dpi scanning may fail for large image sizes. If you keep getting I/O errors, try cycling the power on your scanner to reset it. There is no way to cancel a scan, since the driver ignores sane_cancel(). If you try scanning an image which is too small, you will get I/O errors. Be sure to adjust the scan area before doing a scan, since by default, the scan area is zero. .SH SEE ALSO sane(7), sane\-usb(5) .TP (Old) homepage: .I http://umax1220u\-sane.sourceforge.net/ .SH AUTHOR Marcio Luis Teixeira .SH EMAIL-CONTACT sane\-devel@lists.alioth.debian.org .SH REPORTING BUGS This backend isn't actively maintained. Nevertheless, bug reports and comments should be sent to the sane\-devel mailing list. When reporting bugs, please run the backend with SANE_DEBUG_UMAX1220U set to 10 and attach a copy of the log messages. sane-backends-1.0.27/doc/descriptions/0000775000175000017500000000000013110600532014544 500000000000000sane-backends-1.0.27/doc/descriptions/kvs1025.desc0000664000175000017500000000167612775277260016501 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "kvs1025" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-kvs1025" ; name of manpage (if it exists) :comment "New backend for SANE release 1.0.21, see sane-kvs1025 manpage" :devicetype :scanner ; start of a list of devices.... :mfg "Panasonic" ; name a manufacturer :url "http://www.panasonic.com/" :model "KV-S1020C" :interface "USB" :usbid "0x04da" "0x1007" :status :good :model "KV-S1025C" :interface "USB" :usbid "0x04da" "0x1006" :status :good :model "KV-S1045C" :interface "USB" :usbid "0x04da" "0x1010" :status :good sane-backends-1.0.27/doc/descriptions/unsupported.desc0000664000175000017500000022653212775312262017746 00000000000000 ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "unsupported" ; name of backend :version "2010-06-09" ; version of backend :url "/contrib.html" ;:manpage "sane-mustek" ; name of manpage (if it exists) :comment "The devices mentioned here are not supported by any SANE backend. However, there may be links to information about them or stand-alone programs." :devicetype :scanner ;******************************************************************************************** :mfg "Agfa" :model "DuoScan f40" :url "/unsupported/agfa-duoscan-f40.html" :interface "USB IEEE-1394" :usbid "0x06bd" "0x02bf" :status :unsupported :comment "Unsupported. See link for details." :model "DuoScan T2000XL" :url "/unsupported/agfa-duoscan-t2000xl.html" :interface "SCSI" :status :unsupported :comment "Unsupported. Same as Microtek ArtixScan 2020?" :model "DuoScan T2500" :interface "SCSI IEEE-1384" :status :unsupported :comment "Unsupported. Same as Microtek Artixscan 2500f" :model "SnapScan 310P" :url "/unsupported/acer-parport.html" :interface "Parport" :status :unsupported :comment "Unsupported, see link for details." :model "SnapScan EZ" :url "/unsupported/acer-parport.html" :interface "Parport" :status :unsupported :comment "Unsupported, see link for details." :model "SnapScan 1200P" :url "/unsupported/acer-parport.html" :interface "Parport" :status :unsupported :comment "Unsupported, see link for details." :model "SnapScan 1212P" :url "/unsupported/acer-parport.html" :interface "Parport" :status :unsupported :comment "Unsupported, see link for details." ;******************************************************************************************** :mfg "Artec/Ultima" :url "http://www.artecusa.com/" :model "1236 USB" :url "/unsupported/artec_1236usb.html" :interface "USB" :usbid "0x05d8" "0x4001" :status :unsupported :comment "Unsupported. See link for details." :model "AM12e+" :status :unsupported :interface "Parport" :comment "Unsupported. Chips found inside: AT015, AD9816JS. Maybe similar to SCSI version or as6e?" :model "Ultima 2000 (0x4001)" :url "/unsupported/artec-ultima-2000-2.html" :interface "USB" :usbid "0x05d8" "0x4001" :status :unsupported :comment "Same name, but different ids: This scanner is not supported. The scanner with product id 0x4002 is supported by the gt68xx backend, however." ;******************************************************************************************** :mfg "Avigramm" :model "Minidoc" :url "/unsupported/trust-combiscan-19200.html" :interface "USB Parport" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** :mfg "Avision" :url "http://www.avision.com/" :model "DS310F" :interface "Parport" :status :unsupported :comment "Probably not supported. Scanner/printer/copier combination." :model "iVina FB2400" :interface "USB" :status :unsupported :comment "Not supported. No chipset information available. Same as UMAX Astra 6700." :model "iVina 1600" :url "/unsupported/umax-astra-4500.html" :interface "USB" :usbid "0x0638" "0x0a10" :status :unsupported :comment "GL646 based, to be added to genesys backend. Same as UMAX Astra 4500." :model "iVina FB1800" :url "/unsupported/umax-astra-4700.html" :interface "USB" :usbid "0x0638" "0x0a20" :status :unsupported :comment "GL646/GL660 based. Same as UMAX Astra 4700." ;******************************************************************************************** :mfg "Benq (Acer)" :url "http://www.benq.com" :comment "Formerly Acer Peripherals" :model "310P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "320P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "340P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "610P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "610PT" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "620P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "620PT" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "640P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "5450" :interface "USB" :usbid "0x04a5" "0x211e" :status :unsupported :comment "Unsupported." :model "5550" :url "/unsupported/benq-5550.html" :interface "USB" :usbid "0x04a5" "0x2211" :status :unsupported :comment "Unsupported, see link for details." :model "5560" :interface "USB" :usbid "0x04a5" "0x2311" :status :unsupported :url "http://lists.alioth.debian.org/pipermail/sane-devel/2009-January/023447.html" :model "7400UT" :url "/unsupported/benq-7400ut.html" :interface "USB" :usbid "0x04a5" "0x2202" :status :unsupported ;******************************************************************************************** :mfg "Boeder" :model "Sm@rtScan Office" :url "/unsupported/trust-combiscan-19200.html" :interface "Parport USB" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Brother" :url "http://www.brother.com/" :model "MFC 2500" :url "/unsupported/brother-mfc-2500.html" :interface "USB" :usbid "0x04f9" "0x000a" :status :unsupported :comment "Not supported. See link for details." :model "MFC 4600" :status :unsupported :url "http://sourceforge.net/projects/brother-mfc" :interface "Parport" :comment "The parport 200x400dpi grayscale version of this scanner is unsupported. Dmitri Katchalov did some investigations on this scanner. If you want to write a backend, contact him (see link)." :model "MFC 7300c" :url "/unsupported/brother-mfc-7300.html" :interface "Parport USB" :usbid "0x04f9" "0x0106" :status :unsupported :model "MFC 9600" :url "/unsupported/brother-mfc-9600.html" :interface "USB" :usbid "0x04f9" "0x0101" :status :unsupported ;******************************************************************************************** :mfg "C-Channel" :url "http://www.c-channel.ch/" :model "MyPen Pro" :url "/unsupported/c-channel-mypen-pro.html" :interface "USB" ;:usbid "" "" :status :unsupported :comment "Probably unsupported. See link for details." :model "MyPen Light" :interface "USB" :usbid "0x0a93" "0x0005" :status :unsupported :comment "See bug #306792 for details." :model "MoneyPen II" ;:url "/unsupported/c-channel-mypen-pro.html" :interface "USB" ;:usbid "" "" :status :unsupported :comment "Probably unsupported." ;******************************************************************************************** :mfg "Canon" :url "http://www.canon.com/" :model "CanoScan 3000" :url "/unsupported/canon-3000.html" :interface "USB" :usbid "0x04a9" "0x2215" :status :unsupported :comment "GL660+GL646 based." :model "CanoScan 3000ex" :url "/unsupported/canon-3000.html" :interface "USB" :usbid "0x04a9" "0x2215" :status :unsupported :comment "GL660+GL646 based." :model "CanoScan 3000F" :url "/unsupported/canon-3000.html" :interface "USB" :usbid "0x04a9" "0x2215" :status :unsupported :comment "GL660+GL646 based, to be added to genesys backend" :model "CanoScan 4200F" :url "/unsupported/canon-4200f.html" :interface "USB" :usbid "0x04a9" "0x221b" :status :unsupported :comment "Probably unsupported. See link." :model "CanoScan 4400F" :url "/unsupported/canon-4400.html" :interface "USB" :usbid "0x04a9" "0x2228" :status :unsupported :comment "GL843 based, to be added to genesys backend" :model "CanoScan 5000F" :url "/unsupported/canon-5000f.html" :interface "USB" :usbid "0x04a9" "0x2212" :status :unsupported :comment "Unsupported. See link for details." :model "CanoScan 5200F" :url "/unsupported/canon-5200f.html" :interface "USB" :usbid "0x04a9" "0x2217" :status :unsupported :comment "Probably unsupported. See link for details." :model "CanoScan 8000F" :url "/unsupported/canon-8000f.html" :interface "USB" :usbid "0x04a9" "0x220f" :status :unsupported :comment "Not supported. See link for more information. With transparency adapter." :model "CanoScan 8400F" :url "/unsupported/canon-8400f.html" :interface "USB" :usbid "0x04a9" "0x221e" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "CanoScan 8600F" :url "/unsupported/canon-8600.html" :interface "USB" :usbid "0x04a9" "0x2229" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "CanoScan 9900F" :url "/unsupported/canon-9900f.html" :interface "USB" :usbid "0x04a9" "0x2210" :status :unsupported :comment "Probably unsupported, similar to 8000F. 3200x6400 dpi USB2. With transparency adapter." :model "CanoScan 9950F" :url "/unsupported/canon-9950f.html" :interface "USB" :usbid "0x04a9" "0x2219" :status :unsupported :comment "Probably unsupported." :model "CanoScan D646U" :url "/unsupported/canon-d646u.html" :interface "USB" :usbid "0x04a9" "0x220b" :status :unsupported :comment "Probably not supported. See link for more information and test program." :model "CanoScan D646U ex" :url "/unsupported/canon-d646u.html" :interface "USB" :usbid "0x04a9" "0x220b" :status :unsupported :comment "Probably not supported. See D646." :model "CanoScan D1230U" :url "/unsupported/canon-d1230u.html" :interface "USB" :usbid "0x04a9" "0x2209" :status :unsupported :comment "Probably not supported. " :model "CanoScan D1250U2" :url "/unsupported/canon-d1250u2.html" :interface "USB" :usbid "0x04a9" "0x220c" :status :unsupported :comment "Not supported. However, someone started working on this scanner and some information is available (see link)." :model "CanoScan D2400UF" :url "/unsupported/canon-d2400uf.html" :interface "USB" :usbid "0x04a9" "0x220a" :status :unsupported :comment "Not supported. See link." :model "CanoScan FB320U" :interface "USB" :usbid "0x04a9" "0x2201" :status :unsupported :comment "Probably not supported. No details known." :model "CanoScan FB620U" :url "/unsupported/canon-fb620u.html" :interface "USB" :usbid "0x04a9" "0x2202" :status :unsupported :comment "Probably not supported. Some information is available." :model "CanoScan FB1210U" :url "http://sourceforge.net/projects/canonscanner/" :interface "USB" :usbid "0x04a9" "0x2205" :status :unsupported :comment "Not supported. However, a stand-alone program for FreeBSD is available." :model "CanoScan LiDE 70" :url "http://www.juergen-ernst.de/info_sane.html" :interface "USB" :usbid "0x04a9" "0x2225" :status :unsupported :comment "Philips chip. Backend started, see link" :model "CanoScan LiDE 90" :url "/unsupported/canon-lide-90.html" :interface "USB" :usbid "0x04a9" "0x1900" :status :unsupported :comment "Unsupported. See link for details." :model "CanoScan LiDE 500F" :url "/unsupported/canon-canoscan-lide-500f.html" :interface "USB" :usbid "0x04a9" "0x221f" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "CanoScan LiDE 600" :interface "USB" :url "http://www.juergen-ernst.de/info_sane.html" :usbid "0x04a9" "0x2224" :status :unsupported :comment "Philips chip. Backend started, see link" :model "CanoScan LiDE 600F" :interface "USB" :url "http://www.juergen-ernst.de/info_sane.html" :usbid "0x04a9" "0x2224" :status :unsupported :comment "Philips chip. Backend started, see link" :model "FS4000" :url "/unsupported/canon-fs4000.html" :interface "USB SCSI" :usbid "0x04a9" "0x3042" :status :unsupported :comment "Not supported. See link for more details." :model "IS 12" :url "/unsupported/canon-is-12.html" :interface "USB" :status :unsupported :comment "Probably not supported. Scanner cardridge for Canon inkjet printers." :model "IS 22" :url "/unsupported/canon-is-22.html" :interface "Parport" :status :unsupported :comment "Probably not supported. Scanner cardridge for Canon inkjet printers." :model "IS 32" :url "/unsupported/canon-is-32.html" :interface "USB" :usbid "0x04a9" "0x105d" :status :unsupported :comment "Probably not supported. Scanner cardridge for Canon inkjet printers." :model "IS 52" :url "/unsupported/canon-is-52.html" :interface "USB" :status :unsupported :comment "Probably not supported. Scanner cardridge for Canon inkjet printers." :model "ImageRunner iR1018" :url "/unsupported/canon-imagerunner.html" :interface "USB" :usbid "0x04a9" "0x269d" :status :unsupported :comment "Probably not supported. See link for details." :model "ImageRunner iR1022" :url "/unsupported/canon-imagerunner.html" :interface "USB" :usbid "0x04a9" "0x269d" :status :unsupported :comment "Probably not supported. See link for details." :model "ImageRunner iR1023" :url "/unsupported/canon-imagerunner.html" :interface "USB" :usbid "0x04a9" "0x269d" :status :unsupported :comment "Probably not supported. See link for details." :model "PIXMA MP110" :url "/unsupported/canon-pixma-mp110.html" :interface "USB" :usbid "0x04a9" "0x1700" :status :unsupported :comment "Probably not supported. See link for details." :model "PIXMA MP130" :url "/unsupported/canon-pixma-mp130.html" :interface "USB" :usbid "0x04a9" "0x1701" :status :unsupported :comment "Probably not supported. See link for details." :model "DR-2020U" :interface "USB" :status :unsupported :comment "GL84x?" ;******************************************************************************************** :mfg "Chinon" :model "DS-3000" :url "/unsupported/chinon-ds3000.html" :interface "Parport Serial Port" :status :unsupported :comment "Unsupported at the moment, but a backend is in preparation. See link." ;******************************************************************************************** :mfg "Compaq" :url "http://www.compaq.com/" :model "S200" :interface "USB" :usbid "0x049f" "0x0021" :status :unsupported :comment "Not supported. 2400x1200 dpi. One bulk-in, one bulk-out and one interrupt endpoint. Type-number: U0001-HB21, another type nr on the inside: 75100512-00" ;******************************************************************************************** :mfg "Compeye" :model "Simplex 1236C" :url "/unsupported/trust-combiscan-19200.html" :interface "Parport USB" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Corex" :url "http://www.cardscan.com/" :model "Cardscan 500" :url "/unsupported/corex-cardscan-500.html" :interface "USB" :usbid "0x08f0" "0x0001" :status :unsupported :comment "Probably not supported. Businesscard reader." :model "Cardscan 700 C" :url "/unsupported/corex-cardscan-700.html" :interface "USB" :usbid "0x08f0" "0x0004" :status :unsupported :comment "Probably not supported." ;******************************************************************************************** :mfg "Dell" :url "http://www.dell.com/" :model "A940" :interface "USB" :usbid "0x413c" "0x5106" :status :unsupported :comment "Probably rebadged Lexmark X5150. May work with sane-lexmark? See bug #312130" :model "A960" :url "/unsupported/dell-a960.html" :interface "USB" :usbid "0x413c" "0x5107" :status :unsupported :comment "Probably not supported. See link for details." :model "922" :url "/unsupported/dell-922.html" :interface "USB" :usbid "0x413c" "0x5109" :status :unsupported :comment "Probably not supported. See link for details." ;******************************************************************************************** :mfg "Epson" :url "http://www.epson.com/" :model "GT-2200" :interface "USB" :usbid "0x04b8" "0x0102" :status :unsupported :comment "Probably unsupported. No details known." :model "StylusScan 2000" :interface "USB" :usbid "0x04b8" "0x0105" :status :unsupported :comment "Probably unsupported. No details known." :model "Stylus DX4450" :url "/unsupported/epson-stylus-dx4450.html" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "Probably unsupported. See link for details." :model "Stylus CX-5800" :interface "USB" :status :unsupported :comment "Probably unsupported at the moment. Not compatible to snapscan backend. It's not known if it may work with epson or epkowa backend." ;******************************************************************************************** :mfg "EDT (Electronic Document Technology)" :url "http://www.bizcardreader.com/" :model "BizCardReader 900C" :url "/unsupported/edt-900c.html" :interface "USB" :usbid "0x0a53" "0x5001" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "E-Lux" :comment "E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX" :model "j-6121" :interface "Parport" :status :unsupported :comment "Probably unsupported. Sold 1998. Same as E-Lux j-6121." ;******************************************************************************************** :mfg "Enhans" :comment "E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX" :model "j-6121" :interface "Parport" :status :unsupported :comment "Probably unsupported. Sold 1998. Same as E-Lux j-6121." :model "M-3630 A" :interface "Parport" :status :unsupported :comment "Probably unsupported. " ;******************************************************************************************** :mfg "Fujitsu" :url "http://www.fujitsu.com/" :model "SP1120" :interface "USB" :usbid "0x04c5" "0x1473" :status :unsupported :comment "Genesys GL310 chipset, not supported by sane-genesys backend." :model "SP1125" :interface "USB" :usbid "0x04c5" "0x1475" :status :unsupported :comment "Genesys GL310 chipset, not supported by sane-genesys backend." :model "SP1130" :interface "USB" :usbid "0x04c5" "0x1476" :status :unsupported :comment "Genesys GL310 chipset, not supported by sane-genesys backend." ;******************************************************************************************** :mfg "Genius" :url "http://www.geniusnet.com.tw/" :url "http://www.genius-kye.com/" :model "ColorPage CS" :url "/unsupported/genius-colorpage-cs.html" :interface "SCSI" :status :unsupported :comment "Probably unsupported, see link for details." :model "ColorPage-Slim 1200 USB2" :url "/unsupported/genius-colorpage-slim-1200-usb2.html" :interface "USB" :usbid "0x0458" "0x2020" :status :unsupported :comment "GL841 based, to be added to genesys backend." :model "ColorPage HR6X Slim" :url "/unsupported/genius-colorpage-hr6x.html" :interface "USB" :usbid "0x0458" "0x2019" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "ColorPage HR7X" :url "/unsupported/genius-colorpage-hr7x.html" :interface "USB" :usbid "0x0458" "0x2018" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "ColorPage HR7XE" :url "/unsupported/genius-colorpage-hr7xe.html" :interface "USB" :usbid "0x06dc" "0x0012" :status :unsupported :comment "Unsuported. See link for details." :model "ColorPage HR8" :url "/unsupported/genius-colorpage-hr8.html" :interface "USB" :usbid "0x0458" "0x201c" :status :unsupported :comment "GL841 based, to be added to genesys backend" ;******************************************************************************************** :mfg "Guillemot" ; name a manufacturer :model "SCAN@HOME 48 USB" :url "/unsupported/teco-vm6509.html" :interface "USB" :usbid "0x080d" "0x0102" :status :unsupported :comment "Probably unsupported. See link for details." :model "Maxi Scan A4 Parallel 36 bit" :interface "Parport" :status :unsupported :comment "Probably unsupported. Identical to the Benq Prisa 620P." ;******************************************************************************************** :mfg "Hercules" ; name a manufacturer :model "SCAN@HOME 48 USB" :url "/unsupported/teco-vm6509.html" :interface "USB" :usbid "0x080d" "0x0102" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "Photo Scanner 1000" :url "/unsupported/hp-photo-1000.html" :interface "USB" :usbid "0x03f0" "0x1001" :status :unsupported :comment "Not supported by SANE. However, it's detected as mass storage device so just mounting it is reported to work. See link for device data." :model "Photosmart 1200 Photo" :interface "USB" :status :unsupported :comment "Probably not supported by SANE. No details known. 10x15 cm. Maybe similar to Photo Scanner 1000?" :model "Photosmart S20 (C5101A)" :url "/unsupported/hp-photosmart-s20xi.html" :interface "USB" :usbid "0x03f0" "0x0102" :status :unsupported :comment "Not supported yet by SANE. See link for details." :model "Photosmart S20xi (C7150A)" :url "/unsupported/hp-photosmart-s20xi.html" :interface "USB" :usbid "0x03f0" "0x0102" :status :unsupported :comment "Not supported yet by SANE. See link for details." :model "Photosmart C5100 series" :url "/unsupported/hp-photosmart-5100.html" :interface "USB" :usbid "0x03f0" "0x5811" :status :unsupported :comment "Not supported yet by SANE. See link for details." :model "Photosmart C3180" :url "/unsupported/hp-photosmart-3180.html" :interface "USB" :usbid "0x03f0" "0x5611" :status :unsupported :comment "Not supported yet by SANE. See link for details." :model "ScanJet 3770" :status :unsupported :interface "USB" :usbid "0x03f0" "0x2505" :comment "While an external binary-only backend exists, it works only on Linux i386. Therefore the scanner is unsupported on other platforms." :model "ScanJet 4600" :url "/unsupported/hp-scanjet-4600.html" :interface "USB" :usbid "0x03f0" "0x3005" :comment "Not supported. See link for details, or http://www.chmil.org/hp4600linux/ for code" :status :unsupported :model "ScanJet 4670" :interface "USB" :usbid "0x03f0" "0x3005" :comment "Not supported. See ScanJet 4600 entry." :status :unsupported :model "ScanJet 4890C" :url "/unsupported/hp-scanjet-4850.html" :interface "USB" :usbid "0x03f0" "0x1b05" :comment "GL843, maybe can be added to genesys backend " :status :unsupported :model "ScanJet 5530C Photosmart" :url "/unsupported/hp-scanjet-5530.html" :interface "USB" :usbid "0x03f0" "0x1605" :comment "Maybe GL841_HP, but not confirmed, maybe can be added to genesys backend" :status :unsupported :model "ScanJet 8390" :url "/unsupported/hp-scanjet-8390.html" :interface "USB" :usbid "0x03f0" "0x3805" :comment "Probably not supported. See link for details." :status :unsupported :model "ScanJet G4000" :url "/unsupported/hp-g4000.html" :interface "USB" :usbid "0x03f0" "0x4505" :comment "Probably not supported. See link for details." :status :unsupported ;******************************************************************************************** :mfg "IBM" :url "http://www.ibm.com" :model "ADF Color Scanner" :interface "Proprietary" :status :unsupported :comment "Unsupported. Uses proprietary ISA card. Maybe the same as the Plustek Spectra ADF?" ;******************************************************************************************** :mfg "IOMagic" :url "http://www.iomagic.com/" :model "MobileScan USB" :url "/unsupported/trust-combiscan-19200.html" :interface "USB Parport" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Iris" :url "http://irislink.com/" :model "IriScan" :url "/unsupported/iris-iriscan.html" :interface "USB" :usbid "0x0a53" "0x1000" :status :unsupported :comment "Unsupported. LM9832/3. See link for details." :model "IRISPen Translator Executive" :url "/unsupported/iris-irispen-translator.html" :interface "USB" :usbid "0x0f43" "0x015a" :status :unsupported :comment "Unsupported. See link for details." :model "IRISCard Pro (IBCR II)" :url "/unsupported/iris-business.html" :interface "USB" :usbid "0x0a38" "0x0301" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Kodak" :url "http://www.kodak.com" :model "Snapshot Photo Scanner 1" :interface "Parport" :status :unsupported :comment "Unsupported. FCC ID HWF96PHS" ;******************************************************************************************** :mfg "Lexmark" :url "http://www.lexmark.com/" :model "P6250" :url "/unsupported/lexmark-p6250.html" :interface "USB" :usbid "0x043d" "0x0097" :status :unsupported :comment "Unsupported. See link for details." :model "Photo 3150" :url "/unsupported/lexmark-3150.html" :interface "USB" :usbid "0x043d" "0x007d" :status :unsupported :comment "Unsupported. See link for details." :model "X74" :url "/unsupported/lexmark-x75.html" :interface "USB" :usbid "0x043d" "0x0060" :status :unsupported :comment "Unsupported. See link for details." :model "X75" :url "/unsupported/lexmark-x75.html" :interface "USB" :usbid "0x043d" "0x0060" :status :unsupported :comment "Unsupported. See link for details." :model "X75 PrinTrio" :url "/unsupported/lexmark-x75.html" :interface "USB" :usbid "0x043d" "0x0060" :status :unsupported :comment "Unsupported. See link for details." :model "X83" :url "/unsupported/lexmark-x83.html" :interface "USB" :usbid "0x043d" "0x003d" :status :unsupported :comment "Unsupported. GL640." :model "X2330" :url "/unsupported/lexmark-x2330.html" :interface "USB" :usbid "0x043d" "0x00bb" :status :unsupported :comment "Unsupported. See link for details." :model "X3450" :url "/unsupported/lexmark-x3450.html" :interface "USB" :usbid "0x043d" "0x00f6" :status :unsupported :comment "Unsupported. See link for details." :model "X5130" :url "/unsupported/lexmark-x5130.html" :interface "USB" :usbid "0x043d" "0x0065" :status :unsupported :comment "Unsupported." :model "X5150" :url "/unsupported/lexmark-x5130.html" :interface "USB" :usbid "0x043d" "0x0065" :status :unsupported :comment "Probably unsupported. See link for details." :model "X5250" :url "/unsupported/lexmark-x5250.html" :interface "USB" :usbid "0x043d" "0x0093" :status :unsupported :comment "Unsupported." :model "X6170" :url "/unsupported/lexmark-x6170.html" :interface "USB" :usbid "0x043d" "0x0072" :status :unsupported :comment "Unsupported. See link for details." :model "X7170" :interface "USB" :usbid "0x043d" "0x0098" :status :unsupported :comment "Unsupported. See bug #310889 for details." :model "X7350" :url "/unsupported/lexmark-x7350.html" :interface "USB" :usbid "0x043d" "0x00b8" :status :unsupported :comment "Unsupported. See link for details." :model "X8350" :url "/unsupported/lexmark-x8350.html" :interface "USB" :usbid "0x043d" "0x00b9" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Logitech" :model "PageScan Color" :interface "Parport" :status :unsupported :comment "Most probably unsupported." :model "PageScan USB" :url "/unsupported/logitech-pagescan-usb.html" :interface "USB" :usbid "0x046d" "0x040f" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.com/" :url "http://www.medion.de/" :model "MD 6190" :url "/unsupported/medion-md6190.html" :interface "USB" :usbid "0x0461" "0x0392" :status :unsupported :comment "Probably unsupported. There seem to exist two different scanners with that name. See link for details." :model "MD 6190" :url "/unsupported/medion-md6190.html" :interface "USB" :usbid "0x0461" "0x037b" :status :unsupported :comment "Probably unsupported. There seem to exist two different scanners with that name. See link for details." :model "MD 40420" :url "/unsupported/tevion-md40420.html" :interface "USB" :usbid "0x05da" "0x3008" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 41260" :url "/unsupported/medion-md6190.html" :interface "USB" :usbid "0x0461" "0x037b" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 41985" :url "/unsupported/medion-md6190.html" :interface "USB" :usbid "0x0461" "0x037b" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 42666" :url "/unsupported/tevion-md40420.html" :interface "USB" :usbid "0x05da" "0x3008" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 85264" :url "http://gkall.hobby.nl/authentec.html" :interface "USB" :usbid "0x08ff" "0x2580" :status :unsupported :comment "Fingerprint sensor. See link for details." :model "MD 90009" :url "/unsupported/tevion-md90009.html" :interface "USB" :usbid "0x05da" "0x30e5" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 90070" :url "/unsupported/tevion-md90070.html" :interface "USB" :usbid "0x05da" "0x3022" :status :unsupported :comment "Unsupported. See link for details." :model "MD 90090" :url "/unsupported/tevion-md90070.html" :interface "USB" :usbid "0x05da" "0x3022" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Memorex" :url "http://www.memorex.com/" :model "6136u" :url "/unsupported/memorex-maxx-6136u.html" :interface "USB" :usbid "0x0461" "0x0346" :status :unsupported :comment "Probably unsupported." :model "6142u" :url "/unsupported/visioneer-onetouch4400.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Probably unsupported. Same as Visioneer Onetouch 4400. See link for details." :model "MaxxScan 6122" :url "/unsupported/trust-combiscan-19200.html" :interface "USB Parport" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." :model "SCF 9612P" :url "/unsupported/memorex-scf-9612p.html" :interface "Parport" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Microtek" :url "http://www.microtek.com/" :model "ArtixScan 2020" :interface "SCSI" :status :unsupported :comment "Unsupported. Same as Agfa DuoScan T2000XL?" :model "ArtixScanDI 2020" :url "/unsupported/microtek-artixscan-2020.html" :interface "USB" :usbid "0x05da" "0x202e" :status :unsupported :comment "Unsupported. See link for details." :model "Artixscan 2500f" :interface "SCSI IEEE-1384" :status :unsupported :comment "Unsupported. Same as Agfa DuoScan T2500?" :model "ArtixScan 4000tf" :interface "USB" :status :unsupported :comment "Unsupported. Uses ALI M5611B." :model "FilmScan 35" :url "/unsupported/microtek-filmscan-35.html" :interface "USB" :usbid "0x05e3" "0x0120" :status :unsupported :comment "Probably unsupported. See link for details." :model "ScanMaker 336 CX" :interface "SCSI" :status :unsupported :comment "Probably unsupported. Seems to be similar to the Microtek 330 CX and is detected by the microtek2 backend. Scanning doesn't seem to work however." :model "Scanmaker 1850S" :url "/unsupported/microtek-scanmaker-1850s.html" :interface "SCSI" :status :unsupported :comment "Unsupported. See link for details." :model "ScanMaker 3630" :url "/unsupported/microtek-scanmaker-3630.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Unsupported. Doesn't seem to be compatible to 3600 series, see link." :model "ScanMaker 3800" :url "/unsupported/microtek-scanmaker-3800.html" :interface "USB" :usbid "0x05da" "0x30ce" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 3830" :url "/unsupported/microtek-scanmaker-3830.html" :interface "USB" :usbid "0x05da" "0x30ce" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 3860" :url "/unsupported/microtek-scanmaker-3880.html" :interface "USB" :usbid "0x05da" "0x3023" :status :unsupported :comment "Unsupported. See link for more details. Appears to be similar to ScanMaker 3880." :model "ScanMaker 3880" :url "/unsupported/microtek-scanmaker-3880.html" :interface "USB" :usbid "0x05da" "0x3021" :status :unsupported :comment "Unsupported. SQ113 chip. See link for more details." :model "ScanMaker 4600" :url "/unsupported/microtek-scanmaker-4600.html" :interface "USB" :usbid "0x05da" "0x40c7" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 4700" :url "/unsupported/microtek-scanmaker-4700.html" :interface "USB" :usbid "0x05da" "0x20b4" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 4850" :url "/unsupported/microtek-scanmaker-4900.html" :interface "USB" :usbid "0x05da" "0x30d9" :status :unsupported :comment "Probably unsupported. See link for details." :model "ScanMaker 4850 II" :url "/unsupported/microtek-scanmaker-4850-2.html" :interface "USB" :usbid "0x05da" "0x3008" :status :unsupported :comment "Probably unsupported. See link for details." :model "ScanMaker 4900" :url "/unsupported/microtek-scanmaker-4900.html" :interface "USB" :usbid "0x05da" "0x30b9" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 5" :url "/unsupported/microtek-scanmaker-5600.html" :interface "SCSI" :status :unsupported :comment "Probably unsupported. See link for more details." :model "ScanMaker 5600" :url "/unsupported/microtek-scanmaker-5600.html" :interface "USB" :usbid "0x05da" "0x20a7" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 5700" :interface "USB" :usbid "0x05da" "0x20bd" :status :unsupported :comment "Unsupported. Uses ALI M5615 like the ScanMaker 4700." :model "ScanMaker 5800" :url "/unsupported/microtek-scanmaker-5800.html" :interface "USB" :usbid "0x05da" "0x3008" :status :unsupported :comment "Unsupported. See link for details." :model "ScanMaker 5800" :url "/unsupported/microtek-scanmaker-5800.html" :interface "USB" :usbid "0x05da" "0x30d8" :status :unsupported :comment "Unsupported. See link for details." :model "ScanMaker 5900" :url "/unsupported/microtek-scanmaker-5900.html" :interface "USB" :usbid "0x05da" "0x30d8" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 5950" :url "/unsupported/microtek-scanmaker-5950.html" :interface "USB" :usbid "0x05da" "0x30d8" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 6000" :url "/unsupported/microtek-scanmaker-6000.html" :interface "USB" :usbid "0x05da" "0x30e5" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 6100" :url "/unsupported/microtek-scanmaker-6100.html" :interface "USB" :usbid "0x05da" "0x30e5" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 6700" :url "/unsupported/microtek-scanmaker-6700.html" :interface "USB IEEE-1394" :usbid "0x05da" "0x20c9" :status :unsupported :comment "Unsupported. See link." :model "ScanMaker 8700" :status :unsupported :url "/unsupported/microtek-scanmaker-8700.html" :interface "USB IEEE-1394" :usbid "0x05da" "0x20b1" :comment "Unsupported. See link for details. USB vendor and product ids to be checked." :model "ScanMaker 9600XL" :interface "USB IEEE-1394" :usbid "0x05da" "0x20de" :status :unsupported :comment "Probably unsupported. SCSI seems to work with microtek2 backend." :model "ScanMaker 9800XL" :url "/unsupported/microtek-scanmaker-9800.html" :interface "USB SCSI" :usbid "0x05da" "0x20de" :status :unsupported :comment "Partly unsupported. IEEE-1394 works with microtek2 backend. See link." :model "ScanMaker i320" :url "/unsupported/microtek-scanmaker-i320.html" :interface "USB" :usbid "0x05da" "0x30e6" :status :unsupported :comment "Unsupported. See link." :model "ScanMaker s400" :url "/unsupported/microtek-scanmaker-s400.html" :interface "USB" :usbid "0x05da" "0x201c" :status :unsupported :comment "Unsupported. See link." :model "ScanMaker S400" :url "/unsupported/microtek-scanmaker-s400.html" :interface "USB" :usbid "0x05da" "0x300b" :status :unsupported :comment "Unsupported. See link." :model "ScanPort 3000" :url "/unsupported/microtek-scanport-3000.html" :interface "USB" :usbid "0x04a7" "0x0224" :status :unsupported :comment "Unsupported. Vendor/Product ids: 0x04a7/0x0224. Realtek RTS8801B?. See link for details." ;******************************************************************************************** :mfg "Konica Minolta" :url "http://www.konicaminolta.com/" :model "Dual Scan III" :url "/unsupported/minolta-dual-scan-III.html" :interface "USB" :usbid "0x0686" "0x400d" :status :unsupported :comment "Unsupported. May work with vuescan. See link for details." :model "Dual Scan IV" :url "/unsupported/minolta-dual-scan-IV.html" :interface "USB" :usbid "0x132b" "0x000a" :status :unsupported :comment "Unsupported. Works with vuescan. See link for details." :model "DiMAGE Scan Elite 5400" :url "/unsupported/minolta-dse-5400.html" :interface "USB IEEE-1394" :usbid "0x0686" "0x400e" :status :unsupported :comment "Probably unsupported. May work with vuescan. See link for details." :model "DiMAGE Scan Elite 5400 2" :url "/unsupported/minolta-dse-5400-2.html" :interface "USB" :usbid "0x132b" "0x0012" :status :unsupported :comment "Probably unsupported. See link for details." :model "DiMAGE Scan Multi Pro" :url "/unsupported/minolta-dimage-scan-multi-pro.html" :interface "IEEE-1394" :status :unsupported :comment "Probably unsupported. See link for details." :model "magicolor 2480MF" :interface "USB Network" :status :unsupported :comment "Uses a different scanning protocol than the magicolor 1690MF" ;******************************************************************************************** :mfg "Mustek" ; name a manufacturer :url "http://www.mustek.com/" :url "http://www.mustek.de/" :url "http://www.mustek.com.tw/" :model "1200 III EP" :interface "Parport" :status :unsupported :comment "Probably not supported. quarlewm at jmu dot edu offers to temporarily loan such a scanner to anyone who is interested in writing a driver." :model "2400 M" :interface "USB" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :status :unsupported :comment "Probably unsupported. No details known." :model "BearPaw 2400 TA Pro" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x0400" :comment "Not supported. May be supported by mustek_usb2 backend later. See link for some information." :status :unsupported :model "BearPaw 2448 CU Pro" :url "/unsupported/mustek-bearpaw-2448-cu-pro.html" :usbid "0x055f" "0x0408" :interface "USB" :comment "Not supported. May be supported by mustek_usb2 backend later. See link for some information." :status :unsupported :model "BearPaw 4800 TA Pro" :url "/unsupported/mustek-bearpaw-4800ta-pro.html" :interface "USB" :usbid "0x055f" "0x1000" :comment "Not supported. See link for some information." :status :unsupported :model "BearPaw 4800 TA Pro II" :url "/unsupported/mustek-bearpaw-4800ta-pro-ii.html" :interface "USB" :usbid "0x055f" "0x040a" :comment "Not supported. May be supported by mustek_usb2 backend later. See link for some information." :status :unsupported :model "BearPaw 6400 TA Pro" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x040b" :comment "Not supported. May be supported by mustek_usb2 backend later. See link for some information." :status :unsupported :model "Paragon 800 II EP" :interface "Parport" :status :unsupported :comment "Not supported. Maybe similar to 600 II EP (SCSI_over-parport)? In this case it could be supported by the mustek SCSI backend." :model "ScanExpress 600 USB" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x0873" :status :unsupported :comment "Unsupported. Programming information is available." :model "ScanExpress 1200 USB" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x0003" :status :unsupported :comment "Unsupported. Programming information is available." :model "ScanExpress 1200 USB Plus" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x0007" :status :unsupported :comment "Unsupported." :model "ScanExpress 12000 P" :url "http://penguin-breeder.org/?page=mustek_pp" :interface "Parport" :status :unsupported :comment "Not supported. Asic 1505/05." :model "ScanExpress A3 EP" :interface "Parport" :status :unsupported :comment "Not supported. Maybe it will be supported by the mustek_pp backend in future." :model "ScanExpress CardSmart" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :status :unsupported :comment "Probably unsupported. USB business card scanner. Maybe works as USB storage device?" :model "ScanMagic 9636P" :url "http://lists.alioth.debian.org/pipermail/sane-devel/2003-May/007682.html" :interface "Parport" :status :unsupported :comment "Probably not supported. Same as Mustek 12000 P?. ASIC 1505." ;******************************************************************************************** :mfg "NEC" :url "http://www.nevt.co.jp/" :model "Petiscan" :url "/unsupported/nec-petiscan.html" :interface "USB" :usbid "0x0475" "0x0100" :status :unsupported :comment "Most probably unsupported. See link for details. Vendor ID is Relisys/Teco. Not known if it is similar to other Relisys/Teco USB scanners." ;******************************************************************************************** :mfg "Nikon" :url "http://www.nikon.com/" :model "LS-9000 ED" :url "/unsupported/nikon-ls9000-ed.html" :interface "IEEE-1394" :status :unsupported :comment "Probably not supported. See link for details. Possibly similar to LS-8000 ED." ;******************************************************************************************** :mfg "Olivetti" :url "http://www.olivetti.com" :model "Job-Jet M400" :url "/unsupported/olivetti-job-jet-m400.html" :interface "USB" :usbid "0x0b3c" "0xa880" :status :unsupported :comment "Probably not supported. See link for details." ;******************************************************************************************** :mfg "Olympus" :url "http://www.olympus.com" :model "ES-10P" :url "http://lists.alioth.debian.org/pipermail/sane-devel/2008-December/023326.html" :interface "Parport" :status :unsupported :model "ES-10S" :url "/unsupported/olympus-es10s.html" :interface "SCSI" :status :unsupported :comment "Probably not supported. See link for details." ;******************************************************************************************** :mfg "Optoelectronics" :model "Barcode scanner" :interface "USB" :usbid "0x065a" "0x0001" :status :unsupported :comment "Probably not supported." ;******************************************************************************************** :mfg "Optrox" :model "PhotoMaker 3C" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Parport" :status :unsupported :model "PhotoMaker 3E" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Parport" :status :unsupported :model "PhotoMaker 3F" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Proprietary" :status :unsupported :comment "Special ISA card" :model "PhotoMaker 3S" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Parport" :status :unsupported :model "PhotoMaker 6E" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Parport" :status :unsupported :model "PhotoMaker 6F" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Proprietary" :status :unsupported :comment "Special ISA card" ;******************************************************************************************** :mfg "Panasonic" :model "KV-SS905C" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool." :model "KV-S2055W" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S2055L" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S2065W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S3065CW" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S3065CL" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S3085" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S3105C" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool." :model "KV-S6040W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S6045W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S6050W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S6055W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S7065C" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." ;******************************************************************************************** :mfg "Pentax" :model "DSmobile USB" :url "/unsupported/syscan-travelscan-pro.html" :interface "USB" :usbid "0x0a82" "0x2000" :status :unsupported :comment "Probably not supported. Some information is available." ;******************************************************************************************** :mfg "PIE" :url "http://www.scanace.com/" :comment "Pacific Image Electronics" :model "Primefilm 1800u" :url "/unsupported/pie-1800u.html" :interface "USB" :usbid "0x05e3" "0x0120" :status :unsupported :comment "Not supported. See link for details." :model "Primefilm 2700" :interface "USB" :status :unsupported :url "http://lists.alioth.debian.org/pipermail/sane-devel/2009-January/023442.html" :model "Primefilm 3600PRO" :interface "USB IEEE-1394" :status :unsupported :comment "Probably not supported. " :model "Powerslide 3600" :url "/unsupported/reflecta-digitdia-3600.html" :interface "USB IEEE-1394" :usbid "0x05e3" "0x0142" :status :unsupported :comment "Probably unsupported. Film scanner that can scan directly from the magazine." :model "PF3650 Pro3 Film Scanner" :url "/unsupported/pie-pf3650.html" :interface "USB IEEE-1394" :usbid "0x05e3" "0x0143" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** ;:mfg "Packard Bell" ;******************************************************************************************** :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticFilm 7200" :url "/unsupported/plustek-opticfilm-7200.html" :interface "USB" :usbid "0x07b3" "0x0807" :status :unsupported :comment "GL842 based, maybe to be added to genesys backend" :model "OpticFilm 7200i" :interface "USB" :usbid "0x07b3" "0x0c04" :status :unsupported :comment "GL843 based, maybe to be added to genesys backend" :model "OpticPro A3U" :interface "USB" :status :unsupported :comment "Uses Plustek ASIC P99002" :model "OpticPro S6" :interface "USB" :status :unsupported :comment "Uses RealTek chipset (RTL8801D)" :model "OpticPro S12" :url "/unsupported/plustek-opticpro-st12.html" :interface "USB" :usbid "0x07b3" "0x0600" :status :unsupported :comment "Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend." :model "OpticPro ST12" :url "/unsupported/plustek-opticpro-st12.html" :interface "USB" :usbid "0x07b3" "0x0600" :status :unsupported :comment "Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend." :model "OpticPro ST16" :url "/unsupported/plustek-opticpro-st16.html" :interface "USB" :usbid "0x07b3" "0x0600" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "OpticPro UA18" :interface "USB" :status :unsupported :comment "Probably LM983x based." :model "OpticPro S24" :url "/unsupported/plustek-opticpro-st24.html" :interface "USB" :usbid "0x07b3" "0x0601" :status :unsupported :comment "Product id 0x0601 is unsupported but may be supported by the genesys backend in future /GL646). Product id 0x040e is supported by the gt68xx backend." :model "OpticPro ST24" :url "/unsupported/plustek-opticpro-st24.html" :interface "USB" :usbid "0x07b3" "0x0601" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "OpticPro S28" :interface "USB" :url "/unsupported/plustek-opticpro-s28.html" :usbid "0x07b3" "0x0801" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticPro ST28" :url "/unsupported/plustek-opticpro-s28.html" :interface "USB" :usbid "0x07b3" "0x0801" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticPro ST28" :url "/unsupported/plustek-opticpro-st28.html" :interface "USB" :usbid "0x07b3" "0x0802" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "Umax AstraScan 4750" :url "/unsupported/umax-astrscan-4750.html" :interface "USB" :usbid "0x07b3" "0x0802" :status :unsupported :comment "GL841 based, to be added to genesys backend, rebadged Plustek ST28" :model "OpticPro ST48" :url "/unsupported/plustek-opticpro-st48.html" :interface "USB" :usbid "0x07b3" "0x0800" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticPro ST64" :url "/unsupported/plustek-opticpro-st64.html" :interface "USB" :usbid "0x07b3" "0x0c00" :status :unsupported :comment "GL843 based, maybe to be added to genesys backend" :model "OpticPro ST64+" :url "/unsupported/plustek-opticpro-st64plus.html" :interface "USB" :usbid "0x07b3" "0x0c03" :status :unsupported :comment "GL843 based. See link for more details." :model "PL 806" :url "/unsupported/plustek-pl806.html" :interface "USB" :usbid "0x07b3" "0x0c0c" :status :unsupported :comment "Unsupported. See link for more details." :model "SmartOffice PL 812" :url "/unsupported/plustek-pl812.html" :interface "USB" :usbid "0x07b3" "0x0c0d" :status :unsupported :comment "Unsupported. See link for more details." :model "OpticSlim 500" :url "/unsupported/plustek-opticslim-500.html" :interface "USB" :usbid "0x07b3" "0x0458" :status :unsupported :comment "Unsupported. See link for more details." :model "OpticSlim 2420" :url "/unsupported/plustek-opticslim-2420.html" :interface "USB" :usbid "0x07b3" "0x0806" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticSlim 2420+" :url "/unsupported/plustek-opticslim-2420plus.html" :interface "USB" :usbid "0x07b3" "0x0914" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticWorks 2000" :interface "Parport" :status :unsupported :comment "Multifunction device. No further information available." :model "OptiCard 600+" :interface "USB" :status :unsupported :comment "Business card reader. No further information available." :model "ScanCopy 115" :url "/unsupported/plustek-scancopy-115.html" :interface "USB" :usbid "0x07b3" "0x081c" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "Spectra ADF" :interface "Proprietary" :status :unsupported :comment "Unsupported. Uses proprietary ISA card that also provides power and is labelled GPS-1 PAGE-A from Taiwan. Other labels on the scanner include ADF Color Scanner and SF600AS. Maybe the same as the IBM ADF Color Scanner?" :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0005" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0007" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x000f" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0012" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0014" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0016" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." ;******************************************************************************************** :mfg "PLANon" :url "http://www.planon.com/" :model "DocuPen RC800" :interface "USB" :usbid "0x18dd" "0x1000" :status :unsupported :comment "Probably not supported. No details known." :model "DocuPen R700" :url "/unsupported/planon-docupen-r700.html" :interface "USB" :usbid "0x10c4" "0xea60" :status :unsupported :comment "Probably not supported. See link for details." :model "DocuPen (DPEN-BW)" :interface "USB" :status :unsupported :comment "Probably not supported. No details known." ;******************************************************************************************** :mfg "Primax" :url "http://www.primax.nl/" :model "Colorado 600U" :url "/unsupported/primax-colorado-600u.html" :interface "USB" :usbid "0x0461" "0x0341" :status :unsupported :comment "Not supported. Some information is available." :model "Colorado 1200p" :interface "Parport" :url "http://home2.swipnet.se/~w-25069/pxscan.html" :status :unsupported :comment "Unsupported by SANE. But is reported to partly work with pxscan. See link." :model "Colorado 1200u" :interface "USB" :usbid "0x0461" "0x0361" :status :unsupported :comment "Probably unsupported. No details known." :model "Primascan Colorado 2600u" :url "/unsupported/visioneer-onetouch4400.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Unsupported. Same as Visioneer Onetouch 4400. See link for details." :model "Colorado Direct 600" :url "http://home2.swipnet.se/~w-25069/pxscan.html" :interface "Parport" :status :unsupported :comment "Not supported. However, a stand-alone program is available." :model "Colorado Direct 9600" :url "http://home2.swipnet.se/~w-25069/pxscan.html" :interface "Parport" :status :unsupported :comment "Not supported. However, a stand-alone program is available." :model "Colorado USB 9600" :url "/unsupported/primax-colorado-usb-9600.html" :interface "USB" :usbid "0x0461" "0x0340" :status :unsupported :comment "Not supported. See link for details." :model "G2-300" :interface "USB" :usbid "0x0461" "0x0300" :status :unsupported :comment "Probably unsupported. No details known." :model "G2-300 #2" :interface "USB" :usbid "0x0461" "0x0302" :status :unsupported :comment "Probably unsupported. No details known." :model "G2E-300" :interface "USB" :usbid "0x0461" "0x0301" :status :unsupported :comment "Probably unsupported. No details known." :model "G2E-300 #2" :usbid "0x0461" "0x0303" :interface "USB" :status :unsupported :comment "Probably unsupported. No details known." :model "G2-600" :usbid "0x0461" "0x0380" :interface "USB" :status :unsupported :comment "Probably unsupported. No details known." :model "G2-600 #2" :interface "USB" :usbid "0x0461" "0x0382" :status :unsupported :comment "Probably unsupported. No details known." :model "G2E-600" :usbid "0x0461" "0x0383" :interface "USB" :status :unsupported :comment "Probably unsupported. No details known." :model "OneTouch 5300" :interface "Parport" :status :unsupported :comment "Not supported." :model "ReadyScan 636i" :usbid "0x0461" "0x0381" :interface "USB" :status :unsupported :comment "Probably unsupported. No details known." :model "Slim-Line 1200" :interface "USB" :status :unsupported :comment "Maybe GL646. Maybe similar to Medion MD 6228?" :model "Onetouch 8920" :url "/unsupported/visioneer-onetouch8920.html" :interface "USB" :usbid "0x0461" "0x0371" :status :unsupported :comment "Not supported. Look similar to Visioneer Onetouch 8920 (same USB product id)." ;******************************************************************************************** :mfg "Prolink" :url "http://www.fida.com/" :model "Winscan Pro 2448U" :url "/unsupported/prolink-2448u.html" :interface "USB" :usbid "0x06dc" "0x0014" :status :unsupported :comment "Not supported. Some information is available. RealTek RTS8801." :model "Winscan Pro 2000" :interface "USB Parport" :status :unsupported :comment "Not supported. No further information available." ;******************************************************************************************** :mfg "Quato" :url "http://www.quato.de/" :model "X-Finity" :interface "SCSI" :status :unsupported :comment "Probably not supported. No details yet. Originally manufactured by PFU?" :model "X-Finity Ultra" :interface "USB IEEE-1394" :status :unsupported :comment "Probably not supported. No details yet." ;******************************************************************************************** :mfg "Reflecta" :model "DigitDia 3600" :url "/unsupported/reflecta-digitdia-3600.html" :interface "USB IEEE-1394" :usbid "0x05e3" "0x0142" :status :unsupported :comment "Film scanner that can scan directly from the magazine." :model "iScan 1800" :url "/unsupported/reflecta-iscan-1800.html" :interface "USB" :usbid "0x05e3" "0x0120" :status :unsupported :comment "Probably unsupported. See link for details." :model "ProScan 4000" :url "/unsupported/reflecta-proscan-4000.html" :interface "USB IEEE-1394" :usbid "0x05e3" "0x0143" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Relisys" :model "Eclipse 1200U" :url "/unsupported/relisys-eclipse-1200u.html" :interface "USB" :usbid "0x0475" "0x0103" :status :unsupported :comment "Probably unsupported. See link for details." :model "Scorpio Ultra 3" :url "/unsupported/relisys-scorpio-ultra3.html" :interface "USB" :usbid "0x0475" "0x0210" :status :unsupported :comment "Probably unsupported. See link for details." :model "Episode" :url "/unsupported/relisys-episode.html" :interface "USB" :usbid "0x0475" "0x0103" :status :unsupported :comment "Probably unsupported. See link for details." :model "AVEC II E3" :interface "Parport" :status :unsupported :comment "Parport version of AVEC II S3?. See bug #304992 for details" ;******************************************************************************************** :mfg "Samsung" :model "SCX-4725FN" :url "/unsupported/samsung-scx-4725.html" :interface "USB" :usbid "0x04e8" "0x341f" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** :mfg "Scanshell" :model "800N" :url "/unsupported/scanshell-800n.html" :interface "USB" :usbid "0x0a82" "0x6605" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** :mfg "Sicos" :model "DMS 2000" :url "mailto:ehaase@inf.fu-berlin.de" :interface "proprietary" :status :unsupported :comment "Not supported until now. Work on a backend has started, contact the author for details (see link)" ;******************************************************************************************** :mfg "Siemens" ; name a manufacturer :url "http://www.siemens.com/" :model "ID Mouse Professional" :interface "USB" :usbid "0x0681" "0x0005" :status :unsupported :comment "Not supported." :model "Cherry FingerTIP ID Board - Sensor" :interface "USB" :usbid "0x0681" "0x0010" :status :unsupported :comment "Not supported." ;******************************************************************************************** :mfg "SmartDisk" :model "SmartScan 3600" :interface "USB IEEE-1394" :status :unsupported :comment "Probably not supported. Same as PIE Primefilm 2600 PRO." ;******************************************************************************************** :mfg "Spot Technology" :comment "Spot seems have gone out of business." :model "Maxiscan A4" :url "http://www.el-profesor.net/spoonset/" :interface "proprietary" :status :unsupported :comment "Not supported until now. Work on a backend has started, see link for more information." :model "ScanTak 2c" :url "http://www.el-profesor.net/spoonset" :interface "proprietary" :status :unsupported :comment "Not supported. Work on a backend has started, see link for more information." :model "ScanTak 3c" :url "http://www.el-profesor.net/spoonset" :interface "proprietary" :status :unsupported :comment "Not supported. Work on a backend has started, see link for more information." ;******************************************************************************************** :mfg "Syscan" :model "TravelScan FS-531" :url "/unsupported/syscan-travelscan-fs531.html" :interface "USB" :usbid "0x0a82" "0x0530" :status :unsupported :comment "Not supported. May work with the Plustek backend in future. See link for details." :model "TravelScan Pro" :url "/unsupported/syscan-travelscan-pro.html" :interface "USB" :usbid "0x0a82" "0x2000" :status :unsupported :comment "Probably not supported. Some information is available." ;******************************************************************************************** :mfg "Tamarack" :model "Artiscan 9600" ; name models for above-specified mfg. :interface "Parport" :status :unsupported :url "http://www.autistici.org/tamarhack/" :comment "Unsupported at the moment. See link for a project for that scanner taht may support it in future." :model "Artiscan 9600 pro 36" ; name models for above-specified mfg. :interface "Parport" :status :unsupported :url "http://www.autistici.org/tamarhack/" :comment "Unsupported at the moment. See link for a project for that scanner." :model "Artiscan 2400FS" :url "/unsupported/tamarack-artiscan-2400.html" :interface "USB" :usbid "0x05e3" "0x0100" :status :unsupported :comment "Unsupported. See link for more information." ;******************************************************************************************** :mfg "TCE" :comment "Brasilian vendor." :url "http://www.tce.com.br/" :model "MK600U" :url "/unsupported/memorex-maxx-6136u.html" :interface "USB" :usbid "0x0461" "0x0346" :status :unsupported :comment "Not supported. Some information is available." :model "S450" :url "http://home2.swipnet.se/~w-25069/pxscan.html" :interface "Parport" :status :unsupported :comment "Not supported by SANE but is reported to work with pxscan (see link)." ;******************************************************************************************** :mfg "Teco" :url "http://www.tecoimage.com.tw/" :model "VM6509F" :url "/unsupported/teco-vm6509.html" :interface "USB" :usbid "0x080d" "0x0102" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Tiny" :model "FU661E" :url "/unsupported/visioneer-onetouch4400.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Trust" :url "http://www.trust-site.com" :model "CombiScan 19200" :url "/unsupported/trust-combiscan-19200.html" :interface "Parport USB" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." :model "EasyScan 19200" :url "http://lists.alioth.debian.org/pipermail/sane-devel/2008-October/022955.html" :interface "Parport" :status :unsupported :model "SCSI Scan 19200 -Excellence Series-" :url "/unsupported/trust-scsi-scan-19200.html" :interface "SCSI" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "UMAX" :url "http://www.umax.com/" :model "Astra 2500" :url "/unsupported/umax-astra-2500.html" :interface "USB" :usbid "0x0461" "0x0374" :status :unsupported :comment "Probably not supported. See link for details." :model "Astra 2850" :url "/unsupported/plustek-opticpro-st24.html" :interface "USB" :usbid "0x07b3" "0x0601" :status :unsupported :comment "Probably not supported. Same IDs as Plustek OpticPro ST24. See link for details." :model "Astra 3000" :url "/unsupported/umax-astra-3000.html" :interface "USB" :usbid "0x0461" "0x038a" :status :unsupported :comment "Probably not supported. See link for details." :model "Astra 3600" :url "/unsupported/umax-astra-3600.html" :interface "USB" :usbid "0x0461" "0x038a" :status :unsupported :comment "Probably not supported. See link for details." :model "Astra 4000" :url "/unsupported/umax-astra-4000.html" :interface "USB" :usbid "0x1606" "0x1030" :status :unsupported :comment "Not supported. See link for details." :model "Astra 4100" :url "/unsupported/umax-astra-4100.html" :interface "USB" :usbid "0x0461" "0x038c" :status :unsupported :comment "Not supported, to be added to genesys backend." :model "Astra 4500" :url "/unsupported/umax-astra-4500.html" :interface "USB" :usbid "0x0638" "0x0a10" :status :unsupported :comment "GL646 based, to be added to genesys backend. Avision iVina FB1600 clone" :model "Astra 4600" :interface "USB" :status :unsupported :comment "Probably not supported, no details known." :model "Astra 4700" :url "/unsupported/umax-astra-4700.html" :interface "USB" :usbid "0x0638" "0x0a20" :status :unsupported :comment "GL646/GL660 based. Avision iVina FB1800 clone." :model "Astra 6700" :interface "USB" :usbid "0x0638" "0x0a30" :status :unsupported :comment "Not supported. No chipset information available. Same as Avision iVina FB2400." :model "AstraSlim" :url "/unsupported/umax-astraslim.html" :usbid "0x080d" "0x0104" :interface "USB" :status :unsupported :comment "Probably not supported currently. See link for more details." :model "AstraSlim 1200" :url "/unsupported/umax-astraslim-1200.html" :interface "USB" :usbid "0x080d" "0x0110" :status :unsupported :comment "See link for more details." :model "AstraSlim 6000" :url "/unsupported/umax-astraslim-6000.html" :interface "USB" :usbid "0x080d" "0x0104" :status :unsupported :comment "Probably not supported currently. See link for more details." :model "Nete3470'" :interface "Parport" :status :unsupported :comment "Probably not supported. No details known.." :model "Powerlook 180" :url "/unsupported/umax-powerlook-180.html" :interface "USB" ;:usbid "0x3902" "0xc470" #correct? :status :unsupported :comment "Probably not supported. See link for details." :model "Powerlook 1000 USB" :interface "USB" :status :unsupported :comment "Probably not supported. No further information available." ;******************************************************************************************** :mfg "Vantas" :model "3000" :url "/unsupported/visioneer-onetouch4800.html" :interface "USB" :usbid "0x04a7" "0x0224" :status :unsupported :comment "Not supported. See link for more details." ;******************************************************************************************** :mfg "Visioneer" :url "http://www.visioneer.com/" :model "6200" :interface "USB" :usbid "0x0461" "0x0345" :status :unsupported :comment "Not supported. Is reported to use the E5 chipset. Uses a Primax ID. Looks similar to Primascan Colorado 2600u." :model "6200 EPP/USB" :interface "USB" :usbid "0x04a7" "0x0311" :status :unsupported :comment "Not supported. Id is from Primax? Yet another scanner with the same name?" :model "9420" :url "/unsupported/visioneer-9420.html" :interface "USB" :usbid "0x0461" "0x03a8" :status :unsupported :comment "Unsupported. See link for details." :model "9450 USB" :url "/unsupported/visioneer-9450-usb.html" :interface "USB" :usbid "0x04a7" "0x0421" :status :unsupported :comment "Unsupported. See link for details." :model "Onetouch 4400" :url "/unsupported/visioneer-onetouch4400.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Not supported. E5 chipset? See link for more details." :model "OneTouch 4800 USB" :url "/unsupported/visioneer-onetouch4800.html" :interface "USB" :usbid "0x04a7" "0x0224" :status :unsupported :comment "Unsupported. Seems to use Realtek RTS8801B. Same as Microtek Scanport 3000. See link for details." :model "OneTouch 5300 USB" :url "/unsupported/visioneer-onetouch5300.html" :interface "USB" :usbid "0x04a7" "0x0226" :status :unsupported :comment "Not supported. Chipset is RTS8801B(?). See link for output of /proc/bus/usb/devices." :model "OneTouch 5300" :interface "USB" :usbid "0x04a7" "0x0221" :status :unsupported :comment "Not supported. Yet another scanner with this name?" :model "OneTouch 5800 USB" :url "/unsupported/visioneer-onetouch5800.html" :interface "USB" :usbid "0x04a7" "0x0226" :status :unsupported :comment "Unsupported. 48 bit scanner, doesn't work with viceo backend. RTS8801C." :model "OneTouch 6600" :url "/unsupported/visioneer-onetouch6600.html" :interface "USB" :usbid "0x04a7" "0x022a" :status :unsupported :comment "Unsupported. See link for details." :model "Onetouch 7100" :url "/unsupported/visioneer-onetouch7100.html" :interface "USB" :usbid "0x04a7" "0x0229" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "Onetouch 7700" :url "/unsupported/visioneer-onetouch7700.html" :interface "USB" :usbid "0x04a7" "0x0380" :status :unsupported :comment "LM9832/3 based, to be added to plustek backend" :model "OneTouch 8100" :url "/unsupported/visioneer-onetouch8100.html" :interface "USB" :usbid "0x04a7" "0x0321" :status :unsupported :comment "Unsupported. See link for details." :model "Onetouch 8700" :url "/unsupported/visioneer-onetouch8920.html" :interface "USB" :usbid "0x04a7" "0x0371" :status :unsupported :comment "Not supported. See link for details." :model "Onetouch 8900" :url "/unsupported/visioneer-onetouch8920.html" :interface "USB" :usbid "0x04a7" "0x0371" :status :unsupported :comment "Not supported. Same as 8920 but without TA?" :model "Onetouch 8920" :url "/unsupported/visioneer-onetouch8920.html" :interface "USB" :usbid "0x04a7" "0x0371" :status :unsupported :comment "Not supported. Same as 8700 and 8900 but includes a TA. Uses a Primax ID. Chipset is RTS8801C. See link for output of /proc/bus/usb/devices." :model "Onetouch 9000" :url "/unsupported/visioneer-onetouch9020.html" :interface "USB" :usbid "0x04a7" "0x022c" :status :unsupported :comment "Not supported. See link for details." :model "Onetouch 9020" :url "/unsupported/visioneer-onetouch9020.html" :interface "USB" :usbid "0x04a7" "0x022c" :status :unsupported :comment "Not supported. See link for details." :model "Onetouch 9320" :url "/unsupported/visioneer-onetouch9320.html" :interface "USB" :usbid "0x04a7" "0x0362" :status :unsupported :comment "Probably not supported. See link for details." :model "Onetouch Pro 8800" :url "/unsupported/visioneer-onetouch8820.html" :interface "USB" :usbid "0x04a7" "0x0410" :status :unsupported :comment "Probably not supported. See link for details." :model "Onetouch Pro 8820" :url "/unsupported/visioneer-onetouch8820.html" :interface "USB" :usbid "0x04a7" "0x0410" :status :unsupported :comment "Probably not supported. See link for details." :model "PaperPort 3100b" :url "/unsupported/visioneer-paperport-3100b.html" :interface "Parport" :status :unsupported :comment "Most probably not supported. See link for details." :model "PaperPort 6100" :interface "Parport" :status :unsupported :comment "Most probably not supported. More details would be appreciated." :model "PaperPort OneTouch" :url "/unsupported/visioneer-paperport-onetouch.html" :interface "Parport" :status :unsupported :comment "Most probably not supported. See link for details." :model "Strobe Pro USB" :url "/unsupported/visioneer-strobe-pro-usb.html" :interface "USB" :usbid "0x04a7" "0x0102" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** :model "4800 One Touch" :url "/unsupported/xerox-4800-onetouch.html" :interface "USB" :usbid "0x04a7" "0x03a0" :status :unsupported :comment "Unsupported. See link for details. Different id compared to One Touch 4800?" :model "DocuImage 620S" :url "/unsupported/xerox-docuimage-620s.html" :interface "SCSI" :status :unsupported :comment "Not supported. See link for more details." :model "DocuMate 510" :url "/unsupported/xerox-documate-510.html" :interface "USB" :status :unsupported :usbid "0x04a7" "0x0446" :comment "Not supported. See link for more details." :model "DocuMate 510" :url "/unsupported/xerox-documate-510.html" :interface "USB" :status :unsupported :usbid "0x04a7" "0x047c" :comment "Not supported. See link for more details. Yet another USB id." :model "One Touch 4800" :url "/unsupported/visioneer-onetouch4800.html" :interface "USB" :usbid "0x04a7" "0x0224" :status :unsupported :comment "Unsupported. See link for details. Different id compared to 4800 One Touch?" :model "WorkCentre 470cx" :url "/unsupported/xerox-workcentre-470cx.html" :interface "Parport" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre M15i" :url "/unsupported/xerox-workcentre-m15i.html" :interface "USB" :usbid "0x0924" "0xffef" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre XK35c" :url "/unsupported/xerox-workcentre-xk35c.html" :interface "USB Parport" :usbid "0x043d" "0x0020" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre XK50cx" :url "/unsupported/xerox-workcentre-xk50cx.html" :interface "USB" :usbid "0x04e8" "0x3903" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre Pro 412" :url "/unsupported/xerox-workcentre-pro412.html" :interface "USB Parport" :usbid "0x043d" "0x4303" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre PE16" :url "/unsupported/xerox-workcentre-pe16.html" :interface "USB Parport" :usbid "0x0924" "0x4220" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre PE120i" :url "/unsupported/xerox-workcentre-pe120i.html" :interface "USB" :usbid "0x0924" "0x4237" :status :unsupported :comment "Not supported. See link for more details." ;******************************************************************************************** ;******************************************************************************************** ;******************************************************************************************** :devicetype :vidcam :mfg "Biolux" :model "654 (micrOcular)" :url "/unsupported/biolux-654.html" :interface "USB" :usbid "0x0923" "0x010f" :status :unsupported :comment "Not supported yet. See link for more details." ;******************************************************************************************** :mfg "Grandtek Scopecam" :model "8x30 Binocular & Digital Camera" :url "/unsupported/grandtech-scopecam.html" :interface "USB" :usbid "0x0797" "0x801c" :status :unsupported :comment "Not Supported yet. See link for more details." ;******************************************************************************************** ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/dc240.desc0000664000175000017500000000106013063340150016141 00000000000000;Kodak DC240 backend .desc file by Peter S. Fales :backend "dc240" ; name of backend :version "0.0 (unmaintained)" ; version of backend :manpage "sane-dc240" ; name of manpage (if it exists) :url "mailto:peter@fales-lorenz.net" ; backend's web page :devicetype :stillcam ; start of a list of devices.... :mfg "Kodak" :url "http://www.kodak.com/global/en/service/products/ekn006568.jhtml" :model "DC240" :status :good ; minimal, basic, good, complete :interface "Serial port" :comment "Use gphoto2 backend to get USB support" sane-backends-1.0.27/doc/descriptions/coolscan3.desc0000664000175000017500000000317013063340150017215 00000000000000; ; SANE Backend specification file for coolscan2 ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "coolscan3" :version "1.0.0 (unmaintained)" :manpage "sane-coolscan3" :devicetype :scanner :mfg "Nikon" :url "http://www.nikon.com/" :model "LS 30" :interface "SCSI" :status :complete :model "Coolscan III" :interface "SCSI" :status :complete :comment "Rebadged LS 30?" :model "LS 40 ED" :interface "USB" :usbid "0x04b0" "0x4000" :status :complete :model "Coolspan IV" :interface "USB" :usbid "0x04b0" "0x4000" :status :complete :comment "Rebadged LS 40?" :model "LS 50 ED" :url "/unsupported/nikon-ls50-ed.html" :interface "USB" :usbid "0x04b0" "0x4001" :status :minimal :model "Coolscan V ED" :url "/unsupported/nikon-ls50-ed.html" :interface "USB" :usbid "0x04b0" "0x4001" :status :minimal :comment "Rebadged LS 50?" :model "LS 2000" :interface "SCSI" :status :good :model "LS 4000 ED" :interface "IEEE-1394" :status :good :comment "needs linux kernel 2.4.19 or later" :model "Super Coolscan LS-5000 ED" :url "/unsupported/nikon-ls5000-ed.html" :interface "USB" :usbid "0x04b0" "0x4002" :status :untested :comment "May work, similar to LS 50 ED, but untested. Please tell us if it works." :model "LS 8000 ED" :interface "IEEE-1394" :status :good :comment "needs linux kernel 2.4.19 or later" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/sm3840.desc0000664000175000017500000000511713063340150016272 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "sm3840" ; name of backend :version "1.1 (unmaintained)" ; version of backend (or "unmaintained") :manpage "sane-sm3840" ; name of manpage (if it exists) :url "http://www.ziplabel.com/sm3840/" ; backend's web page :comment "This reverse-engineered backend supports the USB ScanMaker 3840 model" ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Microtek" ; name a manufacturer :url "http://www.microtek.com/" ; manufacturer's URL :comment "Microtek makes a wide variety of devices." ; comment about the manufacturer :model "ScanMaker 3840" ; name models for above-specified mfg. :status :good ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :usbid "0x05da" "0x30d4" :comment "8 and 16 bit, color and grayscale" ; comment about the model :model "ScanMaker 4800" ; name models for above-specified mfg. :status :good ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :usbid "0x05da" "0x30cf" :comment "Same hardware as SM3840, different color box" ; comment ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; :status specifier is optional after :model and at the top-level sane-backends-1.0.27/doc/descriptions/ma1509.desc0000664000175000017500000000230113063340150016240 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "ma1509" ; name of backend :version "1.0-3 (unmaintained)" ; version of backend :manpage "sane-ma1509" ; name of manpage (if it exists) :url "http://www.meier-geinitz.de/sane/ma1509-backend/" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Mustek" ; name a manufacturer :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "BearPaw 1200 F" :interface "USB" :usbid "0x055f" "0x0010" :status :good :comment "Works upto 600 dpi. No support for TA and ADF yet." :mfg "Fujitsu" ; name a manufacturer :url "http://www.fujitsu.com/" :model "fi-4110EOX/2/3" :interface "USB" :usbid "0x04c5" "0x1040" :status :unsupported :comment "Uses ma1509 chip, but very different from other scanners supported by the ma1509 backend" sane-backends-1.0.27/doc/descriptions/mustek_usb.desc0000664000175000017500000000173313063340150017515 00000000000000:backend "mustek_usb" :version "1.0-18 (unmaintained)" :manpage "sane-mustek_usb" :url "http://www.meier-geinitz.de/sane/mustek_usb-backend/" :comment "Only the USB scanners mentioned below are supported. For BearPaws, look at the Plustek, MA-1509, and gt68xx backends." :devicetype :scanner :mfg "Mustek" :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "ScanExpress 600 CU" :interface "USB" :usbid "0x055f" "0x0002" :status :complete :model "ScanExpress 1200 CU" :interface "USB" :usbid "0x055f" "0x0001" :status :complete :model "ScanExpress 1200 CU Plus" :interface "USB" :usbid "0x055f" "0x0008" :status :complete :model "ScanExpress 1200 UB" :interface "USB" :usbid "0x055f" "0x0006" :status :complete :comment "For the UB Plus, see gt68xx backend" :mfg "Trust" :url "http://www.trust-site.com" :model "Compact Scan USB 19200" :interface "USB" :usbid "0x055f" "0x0006" :status :complete :comment "Mustek 1200 UB compatible" sane-backends-1.0.27/doc/descriptions/umax1220u.desc0000664000175000017500000000256212112021330016767 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "umax1220u" ; name of backend :version "unmaintained" ; version of backend ;:status :stable ; :alpha, :beta, :stable, :new :manpage "sane-umax1220u" ; name of manpage (if it exists) :url "http://sourceforge.net/projects/umax1220u-sane" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com/" :model "Astra 1220U" ; name models for above-specified mfg. :interface "USB" :usbid "0x1606" "0x0010" :status :good :model "Astra 1600U" :interface "USB" :usbid "0x1606" "0x0030" :status :good :model "Astra 2000U" :interface "USB" :usbid "0x1606" "0x0030" :status :good :model "Astra 2100U" :interface "USB" :usbid "0x1606" "0x0130" :status :good ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/umax.desc0000664000175000017500000001632713063340150016313 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "umax" ; name of backend :version "1.0-41 (unmaintained)" ; version of backend :manpage "sane-umax" ; name of manpage (if it exists) :url "http://www.rauch-domain.de/sane-umax/index.html" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com/" :url "http://www.umax.com.tw/" :url "http://www.umax.de/en" :url "http://www.umax-europe.com" :url "http://www.umaxjapan.co.jp" :url "http://www.umax.com.cn" :model "Vista S6" :interface "SCSI" :status :good :comment "OK" :model "Vista S6E" :interface "SCSI" :status :good :comment "OK" :model "UMAX S-6E" :interface "SCSI" :status :good :comment "OK" :model "UMAX S-6EG" :interface "SCSI" :status :good :comment "OK" :model "Vista-S8" :interface "SCSI" :status :good :comment "OK" :model "Supervista S-12" :interface "SCSI" :status :good :comment "OK" :model "UMAX S-12" :interface "SCSI" :status :good :comment "OK" :model "UMAX S-12G" :interface "SCSI" :status :good :comment "OK" :model "Astra 600S" :interface "SCSI" :status :good :comment "OK" :model "Astra 610S" :interface "SCSI" :status :good :comment "OK" :model "Astra 1200S" :interface "SCSI" :status :good :comment "OK" :model "Astra 1220S" :interface "SCSI" :status :good :comment "OK" :model "Astra 2100S" :interface "SCSI" :status :good :comment "OK" :model "Astra 2200 (SU)" :interface "SCSI" :status :good :comment "OK" :model "Astra 2200 (SU)" :interface "USB" :usbid "0x1606" "0x0230" :status :good :comment "OK, needs USB control messages" :model "Astra 2400S" :interface "SCSI" :status :good :comment "OK" :model "Astra 6400" :interface "IEEE-1394" :status :unsupported :comment "will probably work one day" :model "Astra 6450" :interface "IEEE-1394" :status :unsupported :comment "will probably work one day" :model "Astra MX3" :interface "SCSI" :status :good :comment "OK" :model "Astra MX3" :interface "USB" :status :good :comment "OK, needs USB control messages" :model "Mirage D-16L" :interface "SCSI" :status :good :comment "OK" :model "Mirage II" :interface "SCSI" :status :good :comment "OK" :model "Mirage IIse" :interface "SCSI" :status :good :comment "OK" :model "PSD" :interface "SCSI" :status :good :comment "OK" :model "PowerLook" :interface "SCSI" :status :good :comment "OK, SCSI-ID=PS-2400X" :model "PL-II" :interface "SCSI" :status :good :comment "OK" :model "PowerLook III" :interface "SCSI" :status :good :comment "OK" :model "PowerLook 270" :interface "SCSI" :status :unsupported :comment "incompatible" :model "PowerLook 270plus" :interface "SCSI" :status :unsupported :comment "incompatible" :model "PowerLook 1100" :interface "IEEE-1394" :status :unsupported :comment "will probably work one day" :model "PowerLook 2000" :interface "SCSI" :status :good :comment "OK" :model "PowerLook 2100XL" :interface "SCSI" :status :good :comment "OK" :model "PowerLook 3000" :interface "SCSI" :status :good :comment "OK" :model "Gemini D-16" :interface "SCSI" :status :good :comment "OK" :model "UMAX VT600" :interface "SCSI" :status :untested :comment "may work, please test and give feedback" :model "Vista-T630" :interface "SCSI" :status :good :comment "OK for some firmwareversions, on others only lineart OK" :model "UC 630" :interface "SCSI" :status :good :comment "Version 2.8 OK, others only lineart OK" :model "UG 630" :interface "SCSI" :status :good :comment "OK" :model "UG 80" :interface "SCSI" :status :good :comment "OK" :model "UC 840" :interface "SCSI" :status :good :comment "Version 1.6 OK, others only lineart OK" :model "UC 1200S" :interface "SCSI" :status :untested :comment "may work, please test and give feedback" :model "UC 1200SE" :interface "SCSI" :status :good :comment "Version 3.0 OK, others unknown" :model "UC 1260" :interface "SCSI" :status :good :comment "Version 1.6 OK, others unknown" :mfg "Linotype Hell" ; another manufacturer... :url "http://www.heidelberg.com/" :model "Jade" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell Office" :model "Jade" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell JADE" :model "Jade2" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell Office2" :model "Saphir" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Saphir2" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell SAPHIR2" :model "Saphir3" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell SAPHIR3" :model "Saphir Ultra" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Saphir Ultra II" :interface "SCSI" :status :good :comment "OK, SCSI-ID=Linotype SAPHIR4" :model "Saphir HiRes" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Opal" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Opal2" :interface "SCSI" :status :good :comment "OK; SCSI-ID=LinoHell OPAL2" :model "Opal Ultra" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Linoscan 1400" :interface "SCSI" :status :good :comment "OK, SCSI-ID=HDM LS4H1S" :mfg "Vobis" :url "http://www.vobis.de/" :model "Highscreen Scanboostar Premium" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell Office2" :mfg "EDGE" ; another manufacturer... ; :url "http://???/" :model "KTX-9600US" :interface "SCSI" :status :untested :comment "no feedback" :mfg "Epson" ; another manufacturer... :url "http://www.epson.com/" :model "Perfection 600" :interface "SCSI" :status :good :comment "OK, SCSI-ID=EPSON Perfection600" :mfg "Escom" ; another manufacturer... :model "Image Scanner 256" :interface "SCSI" :status :good :comment "OK, SCSI-ID=UMAX UG 80" :mfg "Escort" ; another manufacturer... :model "Galleria 600" :interface "SCSI" :status :untested :comment "untested, SCSI-ID=ESCORT Galleria 600S" :mfg "Genius" ; another manufacturer... ;:url "http://www.genius.kye.de/" :model "ColorPage-HR5 (Pro)" :interface "SCSI" :status :good :comment "OK, SCSI-ID=KYE ColorPage-HR5" :mfg "Nikon" ; another manufacturer... :url "http://www.nikon.com/" :model "AX-110 / Scantouch 110" :interface "SCSI" :status :untested :comment "may work, please test and give feedback" :model "AX-210" :interface "SCSI" :status :good :comment "OK" :mfg "TriGem" ; another manufacturer... :url "http://www.nikon.com/" :model "PowerScanII" :interface "SCSI" :status :good :comment "OK" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/plustek_pp.desc0000664000175000017500000000676612112021330017523 00000000000000; ; SANE Backend description file for Plustek_pp backend ; :backend "plustek_pp" :version "0.43" :manpage "sane-plustek_pp" ; backend's web page :url "http://www.gjaeger.de/scanner/plustek_pp/" :devicetype :scanner ;* Plustek ********************************************************************************** :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" ;name models for above-specified mfg. :model "OpticPro 4800P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 4830P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 600P/6000P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 4831P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 9630P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 9630PL" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=1" :model "OpticPro 9600P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 1236P" :interface "Parport (SPP, EPP)" :status :complete :comment "reported as OpticPro 12000P/96000P" :model "OpticPro 12000P/96000P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 9636P" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=4" :model "OpticPro 9636P+/Turbo" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=3" :model "OpticPro 9636T" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 12000T" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro AI3" :interface "Parport (SPP, EPP)" :status :basic :comment "use driver-switch mov=5, poor picture quality" :model "OpticPro P8" :interface "Parport" :status :untested :model "OpticPro P12" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro PT12" :interface "Parport (SPP, EPP)" :status :complete ;* Primax *********************************************************************************** :mfg "Primax" ; name of manufacturer :url "http://www.primax.nl/" ;name models for above-specified mfg. :model "Colorado 4800" :interface "Parport (SPP, EPP)" :status :untested :comment "same as OpticPro 4800P" :model "Compact 4800 Direct" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=2" :model "Compact 4800 Direct-30" :interface "Parport (SPP, EPP)" :status :complete :comment "same as OpticPro 4830P, use driver-switch mov=7" :model "Compact 9600 Direct-30" :interface "Parport (SPP, EPP)" :status :complete :comment "same as OpticPro 9630P" ;* Genius/KYE ******************************************************************************************* :mfg "Genius" :url "http://www.geniusnet.com.tw/" :model "Colorpage Vivid III V2" :interface "Parport (SPP, EPP)" :status :complete :comment "Reported as PT12" :model "Colorpage Vivid Pro II Film" :interface "Parport (SPP, EPP)" :status :complete :comment "Reported as OP9636T/12000T" :model "Colorpage HR6X EPP" :interface "Parport (SPP, EPP)" :status :good :comment "Negative scanning does not work correctly" ;******************************************************************************************** :mfg "Aries" :model "Scan-It Pro 4800" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=2" ;******************************************************************************************** :mfg "BrightScan" :model "BrighScan OpticPro" :interface "Parport (SPP, EPP)" :status :complete :comment "Reported as P12" sane-backends-1.0.27/doc/descriptions/canon_pp.desc0000664000175000017500000000336413063340150017133 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "canon_pp" ; name of backend :manpage "sane-canon_pp" :version "0.33 (unmaintained)" ; version of backend :url "http://canon-fb330p.sourceforge.net" ; backend home page :devicetype :scanner :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" :model "CanoScan FB310P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :unsupported :comment "Rebadged Avision, different command set" :model "CanoScan FB610P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :unsupported :comment "Rebadged Avision, different command set" :model "CanoScan FB320P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :basic :comment "Newly added support" :model "CanoScan FB620P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :basic :comment "Newly added support" :model "CanoScan FB330P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :model "CanoScan FB630P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :model "CanoScan N340P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :model "CanoScan N640P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :model "CanoScan N640P ex" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :comment "Just an N640P in a different box?" sane-backends-1.0.27/doc/descriptions/template.desc.0000664000175000017500000000567112112021330017220 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "template" ; name of backend :version "0.42" ; version of backend (or "unmaintained") :new :yes ; Is the backend new to this SANE release? ; :yes or :no :manpage "sane-template" ; name of manpage (if it exists) :url "http://www.luser.com/temp/" ; backend's web page :url "http://www.luser.com/b/" ; another backend webpage :comment "This backend supports only the USB and SCSI models" ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "TemPlate" ; name a manufacturer :url "http://www.template.com/" ; manufacturer's URL :url "http://www.template.de/" ; another manufacturer URL :comment "TemPlate scanners are sometimes labeled \"TMP\"" ; comment about the manufacturer :model "Templ Z" ; name models for above-specified mfg. :status :untested ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "SCSI" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :usbid "0x1234" "0x4321" ; Vendor and product ids of an USB device :url "http://www.tmp.com/z.html" ; model's URL :comment "With Z-Axis scrolling" ; comment about the model :model "Templ ZS" :interface "USB" :usbid "0x1234" "0x4322" :status :unsupported :comment "No support yet, but we have docs." :model "Templ ZQ" :interface "USB" :usbid "0x1234" "0x4323" :status :minimal :model "Templ ZY" :interface "SCSI" :status :basic :model "Templ ZZ" :interface "SCSI" :status :good :mfg "ArmorPlate" ; another manufacturer... :url "http://www.armorplate.com/" :model "AmplScan II" :interface "SCSI" :status :complete :comment "AmplScan *II*, not AmplScan!" :devicetype :api ; specify a different type :desc "Interface to FrObYz API" ; describe a non-hardware device :comment "Only FrObYz version 2.0 is supported!" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; :status specifier is optional after :model and at the top-level sane-backends-1.0.27/doc/descriptions/u12.desc0000664000175000017500000000255712775312262015764 00000000000000; ; SANE Backend description file for U12 backend ; :backend "u12" :version "0.02" :manpage "sane-u12" ; backend's web page :url "http://www.gjaeger.de/scanner/u12/" :devicetype :scanner ;* Plustek ********************************************************************************** :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticPro U12" :interface "USB" :usbid "0x07b3" "0x0001" :status :basic :comment "Note: Only devices with product ID 0x0001 are supported!" :model "OpticPro UT12" :interface "USB" :usbid "0x07b3" "0x0001" :status :basic :comment "Note: Only devices with product ID 0x0001 are supported!" :model "OpticPro 1212U" :interface "USB" :usbid "0x07b3" "0x0001" :status :basic ;* RevScan ********************************************************************************** :mfg "RevScan" :model "RevScan Orange R48Ti" :interface "USB" :usbid "0x07b3" "0x0001" :status :basic :comment "Rebadged Plustek OpticPro UT12" ;* Genius/KYE ******************************************************************************************* :mfg "Genius" :url "http://www.geniusnet.com.tw/" :model "ColorPage HR6 V1" :interface "USB" :usbid "0x0458" "0x2004" :status :basic :model "ColorPage Vivid III USB" :interface "USB" :usbid "0x07b3" "0x0001" :status :untested :comment "Note: Device has Plustek vendor and product ID (0x07b3/0x0001)" sane-backends-1.0.27/doc/descriptions/kvs20xx.desc0000664000175000017500000000222512775277260016702 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "kvs20xx" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-kvs20xx" ; name of manpage (if it exists) :comment "New backend for SANE release 1.0.22, see sane-kvs20xx manpage" :devicetype :scanner ; start of a list of devices.... :mfg "Panasonic" ; name a manufacturer :url "http://www.panasonic.com/" :model "KV-S2025C" :interface "SCSI" :status :untested :model "KV-S2026C" :interface "USB SCSI" :usbid "0x04da" "0x1000" :status :untested :model "KV-S2028C" :interface "USB" :usbid "0x04da" "0x100a" :status :untested :model "KV-S2045C" :interface "SCSI" :status :untested :model "KV-S2046C" :interface "USB SCSI" :usbid "0x04da" "0x1001" :status :untested :model "KV-S2048C" :interface "USB" :usbid "0x04da" "0x1009" :status :untested sane-backends-1.0.27/doc/descriptions/pieusb.desc0000664000175000017500000000522613106201017016620 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "pieusb" ; name of backend :version "1.0 (unmaintained)" ; version of backend :new :no :manpage "sane-pieusb" ; name of manpage (if it exists) :url "https://github.com/kkaempf/sane-backends" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "PIE" :url "http://www.scanace.com" :model "PowerSlide 3600" :interface "USB" :usbid "0x05e3" "0x0142" :status :untested :comment "Identical to Reflecta DigitDia 3600" :model "PowerSlide 3650" :interface "USB" :usbid "0x05e3" "0x0142" :status :basic :comment "Identical to Reflecta DigitDia 4000" :model "PowerSlide 4000" :interface "USB" :usbid "0x05e3" "0x0142" :status :basic :comment "Identical to Reflecta DigitDia 5000" :model "PowerSlide 5000" :interface "USB" :usbid "0x05e3" "0x0142" :status :basic :comment "Identical to Reflecta DigitDia 6000" :mfg "Reflecta" :url "https://reflecta.de" :model "Reflecta ProScan 10T" :interface "USB" :usbid "0x05e3" "0x0145" :status :basic :model "Reflecta ProScan 7200" :interface "USB" :usbid "0x05e3" "0x0145" :status :good :comment "Similar to PrimeFilm 7250 scanner from Pacific Image Electronics" :model "CrystalScan 3600" :interface "USB" :usbid 0x05e3 0x0145 :status :basic :model "CrystalScan 7200" :interface "USB" :status :untested :model "Reflecta CrystalScan 7250" :interface "USB" :usbid "0x05e3" "0x0145" :status :basic :comment "Similar to PrimeFilm 7250 scanner from Pacific Image Electronics" :model "DigitDia 3600" :interface "USB" :usbid "0x05e3" "0x0142" :status :untested :comment "Identical to Pacific Image Electronics PowerSlide 3600 scanner" :model "DigitDia 4000" :interface "USB" :usbid "0x05e3" "0x0142" :status :basic :comment "Identical to Pacific Image Electronics PowerSlide 3650 scanner" :model "DigitDia 5000" :interface "USB" :usbid "0x05e3" "0x0142" :status :untested :comment "Identical to Pacific Image Electronics PowerSlide 4000 scanner" :model "Reflecta DigitDia 6000 Multiple Slide Scanner" :interface "USB" :usbid "0x05e3" "0x0142" :status :good :comment "Identical to Pacific Image Electronics PowerSlide 5000 scanner" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/cardscan.desc0000664000175000017500000000260012775312261017117 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "cardscan" ; name of backend :url "http://www.thebility.com/cardscan/" :version "3" ; version of backend :manpage "sane-cardscan" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.21, see sane-cardscan manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Corex/Dymo" ; name a manufacturer :url "http://www.cardscan.com/" :model "800c" :interface "USB" :usbid "0x08f0" "0x0005" :status :good :comment "4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner" :model "600c" :interface "USB" :usbid "0x08f0" "0x0002" :status :basic :comment "4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner" :mfg "Sanford" ; name a manufacturer :model "800c" :interface "USB" :usbid "0x0451" "0x6250" :status :good :comment "4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner" sane-backends-1.0.27/doc/descriptions/hp.desc0000664000175000017500000000615112775312262015756 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hp" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-hp" ; name of manpage (if it exists) :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "ScanJet Plus" ; name models for above-specified mfg. :interface "Propietary" :status :complete :comment "Driver for HP parallel interface card required" :model "ScanJet IIc" :interface "SCSI" :status :complete :scsi "HP" "C1750A" "processor" :model "ScanJet IIp" :interface "SCSI" :status :complete :scsi "HP" "C1790A" "processor" :model "ScanJet IIcx" :interface "SCSI" :status :complete :scsi "HP" "C2500A" "processor" :model "ScanJet 3c" :interface "SCSI" :status :complete :model "ScanJet 3p" :interface "SCSI" :status :complete :model "ScanJet 4c" :interface "SCSI" :status :complete :scsi "HP" "C2520A" "processor" :model "ScanJet 4p" :interface "SCSI" :status :complete :scsi "HP" "C1130A" "processor" :comment "Buttons may not work on some scanners" :model "ScanJet 4100C" :interface "USB" :usbid "0x03f0" "0x0101" :status :complete :comment "Buttons may not work on some scanners" :model "ScanJet 5p" :interface "SCSI" :status :complete :scsi "HP" "C5110A" "processor" :comment "Buttons may not work on some scanners" :model "ScanJet 5100C" :interface "Parport" :status :complete :comment "Requires ppscsi driver and epst module. Buttons may not work on some scanners" :model "ScanJet 5200C" :interface "Parport USB" :usbid "0x03f0" "0x0401" :status :complete :comment "Parallel interface requires ppscsi driver and epst module. Buttons may not work on some scanners" :model "ScanJet 6100C" :interface "SCSI" :status :complete :model "ScanJet 6200C" :interface "SCSI USB" :scsi "HP" "C6270A" "processor" :usbid "0x03f0" "0x0201" :status :complete :comment "Buttons may not work on some scanners" :model "ScanJet 6250C" :interface "SCSI USB" :usbid "0x03f0" "0x0201" :status :complete :comment "Buttons may not work on some scanners" :model "ScanJet 6300C" :interface "SCSI USB" :scsi "HP" "C7670A" "processor" :usbid "0x03f0" "0x0601" :status :complete :comment "Buttons may not work on some scanners" :model "ScanJet 6350C" :interface "SCSI USB" :usbid "0x03f0" "0x0601" :status :complete :comment "Buttons may not work on some scanners" :model "ScanJet 6390C" :interface "SCSI USB" :usbid "0x03f0" "0x0601" :status :complete :comment "Buttons may not work on some scanners" :model "PhotoSmart PhotoScanner" :interface "SCSI" :status :complete ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/microtek2.desc0000664000175000017500000000631212112021330017217 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "microtek2" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-microtek2" ; name of manpage (if it exists) :url "http://karstenfestag.gmxhome.de/linux.html" :devicetype :scanner ; start of a list of devices.... :mfg "Microtek" ; name a manufacturer :url "http://www.microtek.com/" :model "ScanMaker E3plus" :interface "Parport" :status :complete :model "ScanMaker E3plus" ; name models for above-specified mfg. :interface "SCSI" :status :complete :model "ScanMaker X6" :interface "SCSI" :status :complete :model "ScanMaker X6EL" :interface "SCSI" :status :basic :model "ScanMaker X6USB" :interface "USB" :usbid "0x05da" "0x0099" :status :good :model "ScanMaker V300" :interface "SCSI" :status :good :model "ScanMaker V300" :interface "Parport" :status :good :model "ScanMaker V310" :interface "SCSI" :status :basic :model "ScanMaker V310" :interface "Parport" :status :basic :model "ScanMaker V600" :interface "SCSI" :status :basic :model "ScanMaker V600" :interface "Parport" :status :basic :model "ScanMaker 330" :interface "SCSI" :status :basic :model "ScanMaker 630" :interface "SCSI" :status :basic :model "ScanMaker 636" :interface "SCSI" :status :complete :model "ScanMaker 6400XL" :interface "SCSI" :status :complete :model "ScanMaker 9600XL" :interface "SCSI" :comment "only flatbed mode ?" :status :good :model "ScanMaker 9800XL" :url "/unsupported/microtek-scanmaker-9800.html" :interface "IEEE-1394" :status :minimal :comment "IEEE-1394 seems to work. See link. More reports welcome." :model "Phantom 330CX" :interface "Parport" :status :complete :model "SlimScan C3" :interface "Parport" :status :complete :model "Phantom 636" :interface "SCSI" :status :complete :model "Phantom 636CX" :interface "Parport" :status :complete :model "SlimScan C6" :interface "USB" :usbid "0x05da" "0x009a" :status :complete :model "ScanMaker V6UPL" :interface "USB" :usbid "0x05da" "0x00b6" :status :basic :comment "Sometimes scan speed goes to fast and results look badly smudged." :model "ScanMaker V6USL" :interface "SCSI" :status :complete :model "ScanMaker V6USL" :interface "USB" :usbid "0x05da" "0x00a3" :status :complete :model "ScanMaker V6USL" :interface "USB" :usbid "0x05da" "0x80a3" :status :complete :model "ScanMaker X12USL" :interface "SCSI" :comment "only Flatbed mode ?" :status :good :mfg "Vobis" :url "http://www.vobis.de/" :model "HighScan" ; name models for above-specified mfg. :interface "SCSI" :comment "only E3plus based models" :status :complete :mfg "Scanport" :url "http://www.scanport.com/" :model "SQ300" :interface "Parport?" :status :basic :model "SQ2030" :interface "Parport" :status :basic :model "SQ4836" :interface "SCSI" :status :basic :mfg "Genius" :url "http://www.geniusmouse.co.uk/" :model "ColorPage-EP" :interface "Parport" :status :good sane-backends-1.0.27/doc/descriptions/gphoto2.desc0000664000175000017500000000135413063340150016715 00000000000000;gphoto2 backend .desc file by Peter S. Fales :backend "gphoto2" ; name of backend :version "0.0 (unmaintained)" ; version of backend :manpage "sane-gphoto2" ; name of manpage (if it exists) :url "mailto:peter@fales-lorenz.net" ; backend's web page :devicetype :api ; start of a list of devices.... :desc "Multiple cameras supported by the gphoto2 libraries" :url "http://www.gphoto.org" ;:interface "USB, serial port" :comment "The long-term plan is to support all the cameras supported by the gphoto2 libraries (currently over 140 models). However, at this stage, only a handful of cameras are definitely known to work with SANE. Other cameras will probably work if the native file format is EXIF or JPEG. Testers welcome!" sane-backends-1.0.27/doc/descriptions/st400.desc0000664000175000017500000000076113063340150016206 00000000000000; ST400 backend .desc by Ingo Wilken :backend "st400" ; name of backend :version "1.6 (unmaintained)" ; version number :manpage "sane-st400" ; name of manpage (if it exists) :url "http://www.informatik.uni-oldenburg.de/~ingo/sane/" ; backend's web page :devicetype :scanner ; start of a list of devices :mfg "Siemens" :url "http://www.siemens.de/" :model "ST400" :interface "SCSI" :comment "6 bit gray" :status :basic :model "ST800" :interface "SCSI" :comment "6 bit gray" :status :basic sane-backends-1.0.27/doc/descriptions/artec.desc0000664000175000017500000000347512112021330016425 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "artec" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-artec" ; name of manpage (if it exists) :url "http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Artec/Ultima" ; name a manufacturer :url "http://www.artecusa.com/" ;; name models for above-specified mfg. :model "AT3" :interface "SCSI" :status :complete :comment "all modes working" :model "A6000C" :interface "SCSI" :status :complete :comment "all modes working" :model "A6000C PLUS" :interface "SCSI" :status :complete :comment "f/w <= v1.92 basic, f/w >= v1.93 OK" :model "AT6" :status :good :interface "SCSI" :comment "Scan head needs to return home before another scan can be started." :model "AT12" :interface "SCSI" :status :complete :comment "all modes working" :model "AM12S" :interface "SCSI" :status :complete :comment "all modes working" :mfg "BlackWidow" :url "http://www.blackwidow.co.uk/" :model "BW4800SP" :interface "SCSI" :status :complete :comment "rebadged Artec AT3" :mfg "Plustek" :url "http://www.plustek.com/" :model "OpticPro 19200S" :interface "SCSI" :status :complete :comment "rebadged Artec AM12S" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/epsonds.desc0000664000175000017500000000337713063340150017015 00000000000000; ; SANE Backend specification file for the epsonds backend ; ; Copyright (C) 2015 Alessandro Zummo ; Released under GPLv2 ; :backend "epsonds" :version "1.0.18 (unmaintained)" :new :no :manpage "sane-epsonds" :devicetype :scanner :mfg "Epson" :url "http://www.epson.com/" :model "DS-5500" :interface "USB" :usbid "0x04b8" "0x0145" :status :untested :model "DS-6500" :interface "USB" :usbid "0x04b8" "0x0145" :status :untested :model "DS-7500" :interface "USB" :usbid "0x04b8" "0x0145" :status :untested :model "DS-50000" :interface "USB" :usbid "0x04b8" "0x0146" :status :untested :model "DS-60000" :interface "USB" :usbid "0x04b8" "0x0146" :status :good :model "DS-70000" :interface "USB" :usbid "0x04b8" "0x0146" :status :untested :model "DS-510" :interface "USB" :usbid "0x04b8" "0x014c" :status :good :model "DS-560" :interface "USB" :usbid "0x04b8" "0x014d" :status :untested :model "DS-40" :interface "USB" :usbid "0x04b8" "0x0150" :status :untested :model "DS-760" :interface "USB" :usbid "0x04b8" "0x0152" :status :untested :model "DS-860" :interface "USB" :usbid "0x04b8" "0x0152" :status :untested :model "DS-520" :interface "USB" :usbid "0x04b8" "0x0154" :status :untested :model "PX-M7050 Series" :interface "USB" :usbid "0x04b8" "0x08bc" :status :untested :model "WF-8510/8590 Series" :interface "USB" :usbid "0x04b8" "0x08bc" :status :untested :model "PX-M7050FX Series" :interface "USB" :usbid "0x04b8" "0x08cc" :status :untested :model "WF-R8590 Series" :interface "USB" :usbid "0x04b8" "0x08cc" :status :untested sane-backends-1.0.27/doc/descriptions/apple.desc0000664000175000017500000000161312112021330016420 00000000000000;Apple backend .desc file by Milon Firikis. :backend "apple" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-apple" ; name of manpage (if it exists) ;:url "http://no.www.page.yet/" ; backend's web page :devicetype :scanner ; start of a list of devices.... :mfg "Apple" :url "http://developer.apple.com/" :model "Apple Scanner" :interface "SCSI" :status :good ; :alpha, :beta, :stable, :new :comment "4bit, 16 shades of gray" :model "OneScanner" :interface "SCSI" :comment "8bit, 256 shades of gray. The backend needs work especially in the quantization code but it may work." :status :basic ; :alpha, :beta, :stable, :new :model "Color OneScanner" :interface "SCSI" :status :minimal ; :alpha, :beta, :stable, :new :comment "truecolor (needs much work) but it scans in non color modes." sane-backends-1.0.27/doc/descriptions/mustek.desc0000664000175000017500000000765113063340150016651 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "mustek" ; name of backend :version "1.0-138 (unmaintained)" ; version of backend :manpage "sane-mustek" ; name of manpage (if it exists) :url "http://www.meier-geinitz.de/sane/mustek-backend/" :comment "Most Mustek SCSI scanners are supported by this backend. For USB scanners, look at the mustek_usb backend." :devicetype :scanner :mfg "Mustek" ; name a manufacturer :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "Paragon MFS-6000CX" :interface "SCSI" :comment "3-pass" :status :good :model "Paragon MFS-12000CX" :interface "SCSI" :comment "3-pass" :status :good :model "Paragon MFC-600S" :interface "SCSI" :status :complete :model "Paragon 600 II CD" :interface "SCSI" :status :complete :model "Paragon 600 II ED" :interface "Parport" :status :untested :comment "Completely untested. If it's the same as the 600 II EP, it may work. Please contact me if you own such a device." :model "Paragon 600 II EP" :interface "Parport" :status :minimal :comment "Works, however only low resolutions and quality in color mode is bad." :model "ScanMagic 600 II SP" :interface "SCSI" :status :complete :model "TwainScan II SP" :interface "SCSI" :status :complete :model "Paragon MFC-800S" :interface "SCSI" :status :complete :model "Paragon 800 II SP" :interface "SCSI" :status :complete :model "Paragon MFS-6000SP" :interface "SCSI" :status :complete :model "Paragon MFS-8000SP" :interface "SCSI" :status :complete :model "Paragon MFS-1200SP" :interface "SCSI" :status :complete :model "Paragon MFS-12000SP" :interface "SCSI" :status :complete :model "ScanExpress 6000SP" :interface "SCSI" :status :complete :model "ScanExpress 12000SP" :interface "SCSI" :status :complete :model "ScanExpress 1200 FS" :interface "SCSI" :status :untested :comment "One report that it crashes the computer. SCSI driver issue? Please contact me if you own such a device." :model "ScanExpress 12000SP Plus" :interface "SCSI" :status :complete :model "Paragon 1200 III SP" :interface "SCSI" :status :complete :model "Paragon 1200 LS" :interface "SCSI" :status :complete :model "ScanMagic 9636S" :interface "SCSI" :status :complete :model "ScanMagic 9636S Plus" :interface "SCSI" :status :complete :model "ScanExpress A3 SP" :interface "SCSI" :comment "Please test!" :status :basic :model "Paragon 1200 SP Pro" :interface "SCSI" :status :good :model "Paragon 1200 A3 Pro" :interface "SCSI" :status :complete :comment "ADF and TA untested. Please contact me if you own such equipment." :model "Paragon 600 II N" :interface "Proprietary" :status :basic :comment "Resolutions above 300 dpi may cause trouble." :mfg "Trust" ; name a manufacturer :url "http://www.trust-site.com" :comment "Carefully check the model names. Trust uses similar names for completely different hardware." :model "Imagery 1200" :interface "SCSI" :status :good :comment "3-pass, Mustek Paragon MFS-6000CX compatible" :model "Imagery 1200 SP" :interface "SCSI" :status :complete :comment "Mustek Paragon MFS-6000SP compatible" :model "Imagery 4800 SP" :interface "SCSI" :status :complete :comment "Mustek Paragon 600 II CD compatible" :model "SCSI Connect 19200" :interface "SCSI" :status :complete :comment "Mustek ScanExpress 12000SP compatible" :model "SCSI excellence series 19200" :interface "SCSI" :status :complete :comment "Mustek ScanExpress 12000SP compatible" :mfg "Primax" ; name a manufacturer :url "http://www.primax.nl/" :model "Compact 4800 SCSI" :interface "SCSI" :status :complete :comment "Mustek 600 II CD compatible" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/pnm.desc0000664000175000017500000000034113063340150016120 00000000000000:backend "pnm" :version "1.0.8 (unmaintained)" :manpage "sane-pnm" :url "mailto:henning@meier-geinitz.de" :devicetype :api :desc "Reads PNM files" :comment "Used for debugging frontends. Obsolete, use test backend instead." sane-backends-1.0.27/doc/descriptions/agfafocus.desc0000664000175000017500000000117512112021330017260 00000000000000:backend "agfafocus" :version "unmaintained" :manpage "sane-agfafocus" :devicetype :scanner :mfg "AGFA" :url "http://www.agfa.com/" :model "Focus GS Scanner" :interface "SCSI" :status :untested :comment "6 bit gray" :model "Focus Lineart Scanner" :interface "SCSI" :status :untested :comment "Lineart only? Untested." :model "Focus II" :interface "SCSI" :status :untested :comment "gray only" :model "Focus Color" :interface "SCSI" :status :good :comment "3-pass" :model "Focus Color Plus" :interface "SCSI" :status :good :comment "3-pass" :mfg "Siemens" :model "S9036" :interface "SCSI" :status :untested :comment "gray only" sane-backends-1.0.27/doc/descriptions/canon.desc0000664000175000017500000000331612775277260016455 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "canon" ; name of backend :manpage "sane-canon" :version "1.12" ; version of backend ;:status :good ; :alpha, :beta, :stable, :new :url "http://www.rzg.mpg.de/~mpd/sane/" ; backend home page :devicetype :scanner :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" :model "CanoScan 300" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :model "CanoScan 600" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :model "CanoScan 620S" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :model "CanoScan 1200S" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :model "CanoScan 2700F" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; film scanner" :status :good :model "CanoScan 2710S" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; 36bit film scanner" :status :good :model "IX-4015" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :mfg "Apple" ; name a manufacturer :url "http://www.apple.com/" :model "Color OneScanner 600/27" ; name models for above-specified mfg. :interface "SCSI" :comment "Rebadged CanoScan 300" :status :good sane-backends-1.0.27/doc/descriptions/sm3600.desc0000664000175000017500000000233413063340150016262 00000000000000; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "sm3600" ; name of backend :version "0.1 (unmaintained)" ; version of backend :manpage "sane-sm3600" ; name of manpage (if it exists) :url "http://sm3600.sourceforge.net/" ; backend's web page :devicetype :scanner ; start of a list of devices.... :mfg "Microtek" :url "http://www.microtek.com/" :model "ScanMaker 3600" :interface "USB" :usbid "0x05da" "0x40b3" :comment "works" :status :basic :model "ScanMaker 3600" :interface "USB" :usbid "0x05da" "0x40ca" :comment "works" :status :basic :model "ScanMaker 3600" :interface "USB" :usbid "0x05da" "0x40ff" :comment "works" :status :basic :model "ScanMaker 3700" :interface "USB" :usbid "0x05da" "0x40b8" :comment "works" :status :basic :model "ScanMaker 3700" :interface "USB" :usbid "0x05da" "0x40cb" :comment "works" :status :basic :model "ScanMaker 3750" :interface "USB" :usbid "0x05da" "0x40dd" :comment "works (told)" :status :basic sane-backends-1.0.27/doc/descriptions/coolscan2.desc0000664000175000017500000000276713063340150017227 00000000000000; ; SANE Backend specification file for coolscan2 ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "coolscan2" :version "0.1.8 (unmaintained)" :manpage "sane-coolscan2" :url "http://coolscan2.sourceforge.net/" :devicetype :scanner :mfg "Nikon" :url "http://www.nikon.com/" :model "LS 30" :interface "SCSI" :comment "working -- model available to developer" :status :complete :model "LS 2000" :interface "SCSI" :status :good :model "LS 40 ED" :interface "USB" :usbid "0x04b0" "0x4000" :status :complete :model "LS 4000 ED" :interface "IEEE-1394" :status :good :comment "needs linux kernel 2.4.19 or later" :model "LS 50 ED" ;:url "/unsupported/nikon-ls50-ed.html" :interface "USB" :usbid "0x04b0" "0x4001" :status :minimal :model "Coolscan V ED" :url "/unsupported/nikon-ls50-ed.html" :interface "USB" :usbid "0x04b0" "0x4001" :status :minimal :model "Super Coolscan LS-5000 ED" :url "/unsupported/nikon-ls5000-ed.html" :interface "USB" :usbid "0x04b0" "0x4002" :status :untested :comment "May work, similar to LS 50 ED, but untested. Please tell us if it works." :model "LS 8000 ED" :interface "IEEE-1394" :status :good :comment "needs linux kernel 2.4.19 or later" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/hp3900.desc0000664000175000017500000000346413063340150016262 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "hp3900" :version "0.12 (unmaintained)" :manpage "sane-hp3900" :url "http://sourceforge.net/projects/hp3900-series/" :comment "Still Beta" :devicetype :scanner ; ----------------------------------------------------- :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "ScanJet 3800" :interface "USB" :status :basic :usbid "0x03f0" "0x2605" :comment "Works with resolutions equal and less than 600dpi" :model "ScanJet 3970c" :interface "USB" :status :good :usbid "0x03f0" "0x2305" :model "ScanJet 4070 Photosmart" :interface "USB" :status :good :usbid "0x03f0" "0x2405" :model "ScanJet 4370" :interface "USB" :usbid "0x03f0" "0x4105" :status :basic :comment "Works with resolutions lower than 1200dpi" :model "ScanJet G2710" :interface "USB" :usbid "0x03f0" "0x2805" :status :basic :comment "Similar to hp scanjet 3800" :model "ScanJet G3010" :interface "USB" :usbid "0x03f0" "0x4205" :status :basic :comment "Similar to hp scanjet 4370" :model "ScanJet G3110" :interface "USB" :usbid "0x03f0" "0x4305" :status :basic :comment "Similar to hp scanjet 4370" ; ----------------------------------------------------- :mfg "UMAX" :url "http://www.umax.com" :model "Astra 4900" :interface "USB" :usbid "0x06dc" "0x0020" :status :minimal :comment "developing yet" ; ----------------------------------------------------- :mfg "BenQ" :url "http://www.benq.com/" :model "5550" :interface "USB" :usbid "0x04a5" "0x2211" :status :minimal :comment "developing yet" sane-backends-1.0.27/doc/descriptions/sharp.desc0000664000175000017500000000207313063340150016447 00000000000000:backend "sharp" ; name of backend :version "0.32 (unmaintained)" ; version of backend ;:status :beta ; :alpha, :beta, :stable, :new :url "http://www.satzbau-gmbh.de/staff/abel/sane-sharp.html" ; backend's homepage :manpage "sane-sharp" :devicetype :scanner :mfg "Sharp" ; name a manufacturer :url "http://sharp-world.com/" :model "JX-610" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" :model "JX-250" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" :model "JX-320" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" :model "JX-325" ; name models for above-specified mfg. :interface "SCSI" :status :untested :comment "" :model "JX-330" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" :model "JX-350" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" sane-backends-1.0.27/doc/descriptions/avision.desc0000664000175000017500000003471412775312261017024 00000000000000; SANE Backend specification file ; ; THIS FILE IS GENERATED FROM THE "avision.c" FILE AUTOMATICALLY - DO NOT EDIT ; THIS FILE MANUALLY !!! ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; name of backend :backend "avision" ; version of backend :version "Build: 296" ;status: alpha, beta, stable, new ;:status :stable ; backend's web page :url "http://exactcode.com/site/open_source/saneavision/" ; name of manpage (if it exists) :manpage "sane-avision" :devicetype :scanner :mfg "Avision" :url "http://www.avision.com" :model "AV100CS" :interface "SCSI" :status :untested :model "AV100IIICS" :interface "SCSI" :status :untested :model "AV100S" :interface "SCSI" :status :untested :model "AV120" :interface "USB" :usbid "0x0638" "0x0a27" :comment "sheetfed scanner" :status :complete :model "AV121" :interface "USB" :usbid "0x0638" "0x0a3c" :comment "sheetfed scanner" :status :good :model "AV122" :interface "USB" :usbid "0x0638" "0x0a33" :comment "sheetfed duplex scanner" :status :good :model "AV122 C2" :interface "USB" :usbid "0x0638" "0x0a93" :comment "sheetfed duplex scanner" :status :good :model "AV210" :interface "USB" :usbid "0x0638" "0x0a24" :comment "sheetfed scanner" :status :complete :model "AV210" :interface "USB" :usbid "0x0638" "0x0a25" :comment "sheetfed scanner" :status :complete :model "AV210C2" :interface "USB" :usbid "0x0638" "0x0a3a" :comment "sheetfed scanner" :status :complete :model "AV210C2-G" :interface "USB" :usbid "0x0638" "0x0a2f" :comment "sheetfed scanner" :status :complete :model "AV210D2+" :interface "USB" :usbid "0x0638" "0x1a35" :comment "sheetfed scanner" :status :complete :model "AV220" :interface "USB" :usbid "0x0638" "0x0a23" :comment "duplex! sheetfed scanner" :status :complete :model "AV220C2" :interface "USB" :usbid "0x0638" "0x0a2a" :comment "duplex! sheetfed scanner" :status :complete :model "AV220D2" :interface "USB" :usbid "0x0638" "0x0a2b" :comment "duplex! sheetfed scanner" :status :basic :model "AV220D2" :interface "USB" :usbid "0x0638" "0x1a31" :comment "duplex! sheetfed scanner" :status :untested :model "AV220+" :interface "USB" :usbid "0x0638" "0x0a2c" :comment "duplex! sheetfed scanner" :status :complete :model "AV220C2-G" :interface "USB" :usbid "0x0638" "0x0a2d" :comment "duplex! sheetfed scanner" :status :complete :model "AV220C2-B" :interface "USB" :usbid "0x0638" "0x0a2e" :comment "duplex! sheetfed scanner" :status :complete :model "AV220-G" :interface "USB" :usbid "0x0638" "0x0a94" :comment "duplex! sheetfed scanner" :status :complete :model "AV240SC" :interface "SCSI" :status :untested :model "AV260CS" :interface "SCSI" :status :untested :model "AV360CS" :interface "SCSI" :status :untested :model "AV363CS" :interface "SCSI" :status :untested :model "AV420CS" :interface "SCSI" :status :untested :model "AV6120" :interface "SCSI" :status :untested :model "AV610" :interface "USB" :usbid "0x0638" "0x0a18" :status :good :model "AV600U Plus" :interface "USB" :usbid "0x0638" "0x0a18" :status :good :model "AV610C2" :interface "USB" :usbid "0x0638" "0x0a5e" :status :good :model "AM3000 Series" :interface "USB" :usbid "0x0638" "0x0a41" :comment "MFD" :status :basic :model "DS610CU Scancopier" :interface "USB" :usbid "0x0638" "0x0a16" :comment "1 pass, 600 dpi, A4" :status :good :model "AV620CS" :interface "SCSI" :comment "1 pass, 600 dpi" :status :complete :model "AV620CS Plus" :interface "SCSI" :comment "1 pass, 1200 dpi" :status :complete :model "AV630CS" :interface "SCSI" :comment "1 pass, 1200 dpi" :status :complete :model "AV630CSL" :interface "SCSI" :comment "1 pass, 1200 dpi" :status :untested :model "AV6240" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV600U" :interface "USB" :usbid "0x0638" "0x0a13" :comment "1 pass, 600 dpi" :status :good :model "AV660S" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV680S" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV690U" :interface "SCSI" :comment "1 pass, 2400 dpi" :status :untested :model "AV800S" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV810C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV820" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV820C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV820C Plus" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV830C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV830C Plus" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV880" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV880C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV3200C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV3200SU" :interface "USB" :usbid "0x0638" "0x0a4e" :comment "1 pass, ??? dpi" :status :complete :model "AV3730SU" :interface "USB" :usbid "0x0638" "0x0a4f" :comment "1 pass, ??? dpi" :status :complete :model "AV3750SU" :interface "USB" :usbid "0x0638" "0x0a65" :comment "1 pass, ??? dpi" :status :complete :model "AV3800C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV3850SU" :interface "USB" :usbid "0x0638" "0x0a66" :comment "1 pass, ??? dpi" :status :complete :model "FB6000E" :interface "SCSI" :comment "1 pass, 1200 dpi, A3 - duplex! - zero edge!" :status :complete :model "FB6080E" :interface "USB" :usbid "0x0638" "0x0a82" :comment "1 pass, 1200 dpi, A3 - duplex! - zero edge!" :status :complete :model "FB2080E" :interface "USB" :usbid "0x0638" "0x0a84" :comment "1 pass, 600 dpi, zero-edge" ASIC 7 :status :basic :model "AV8000S" :interface "SCSI" :comment "1 pass, 1200 dpi, A3" :status :complete :model "AV8050U" :interface "USB" :usbid "0x0638" "0x0a4d" :comment "1 pass, 1200 dpi, A3 - duplex!" :status :complete :model "AV8300" :interface "USB" :usbid "0x0638" "0x0a40" :comment "1 pass, 1200 dpi, A3 - duplex!" :status :complete :model "AV8350" :interface "USB" :usbid "0x0638" "0x0a68" :comment "1 pass, 1200 dpi, A3 - duplex!" :status :complete :model "IT8300" :interface "USB" :usbid "0x0638" "0x0a61" :comment "1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" :status :good :model "@V2500" :interface "USB" :usbid "0x0638" "0x0aa1" :status :untested :model "@V5100" :interface "USB" :usbid "0x0638" "0x0a45" :comment "1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" :status :good :model "AVA3" :interface "SCSI" :comment "1 pass, 600 dpi, A3" :status :basic :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "ScanJet 5300C" :interface "USB" :usbid "0x03f0" "0x0701" :comment "1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" :status :complete :model "ScanJet 5370C" :interface "USB" :usbid "0x03f0" "0x0701" :comment "1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" :status :good :model "ScanJet 7400c" :interface "USB" :usbid "0x03f0" "0x0801" :comment "1 pass, 2400 dpi - dual USB/SCSI interface" :status :good :model "ScanJet 7450c" :interface "USB" :usbid "0x03f0" "0x0801" :comment "1 pass, 2400 dpi - dual USB/SCSI interface" :status :good :model "ScanJet 7490c" :interface "USB" :usbid "0x03f0" "0x0801" :comment "1 pass, 1200 dpi - dual USB/SCSI interface" :status :good :model "ScanJet 8200" :interface "USB" :usbid "0x03f0" "0x0b01" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8250" :interface "USB" :usbid "0x03f0" "0x0b01" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8270" :interface "USB" :usbid "0x03f0" "0x3905" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8290" :interface "USB" :usbid "0x03f0" "0x0b01" :comment "1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far" :status :good :model "ScanJet 8300" :interface "USB" :usbid "0x03f0" "0x3805" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8350" :interface "USB" :usbid "0x03f0" "0x3805" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8390" :interface "USB" :usbid "0x03f0" "0x3805" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :mfg "Minolta" :url "http://www.minolta.com" :model "Dimage Scan Dual I" :interface "SCSI" :status :basic :model "Scan Multi Pro" :interface "SCSI" :status :untested :model "Dimage Scan Dual II" :interface "USB" :usbid "0x0638" "0x026a" :comment "1 pass, film-scanner" :status :good :model "Elite II" :interface "USB" :usbid "0x0686" "0x4004" :comment "1 pass, film-scanner" :status :untested :model "Dimage Scan Dual III" :interface "USB" :usbid "0x0686" "0x400d" :comment "1 pass, film-scanner" :status :good :model "Dimage Scan Elite 5400" :interface "USB" :usbid "0x0686" "0x400e" :comment "1 pass, film-scanner" :status :good :mfg "Minolta-QMS" :model "SC-110" :interface "USB" :usbid "0x0638" "0x0a15" :status :untested :model "SC-215" :interface "USB" :usbid "0x0638" "0x0a16" :status :good :mfg "Mitsubishi" :model "MCA-ADFC" :interface "SCSI" :status :untested :model "S1200C" :interface "SCSI" :status :untested :model "S600C" :interface "SCSI" :status :untested :model "SS600" :interface "SCSI" :status :good :mfg "Fujitsu" :url "http://www.fujitsu.com" :model "ScanPartner" :interface "SCSI" :status :untested :model "ScanPartner 10" :interface "SCSI" :status :untested :model "ScanPartner 10C" :interface "SCSI" :status :untested :model "ScanPartner 15C" :interface "SCSI" :status :untested :model "ScanPartner 300C" :interface "SCSI" :status :untested :model "ScanPartner 600C" :interface "SCSI" :status :untested :model "ScanPartner 620C" :interface "SCSI" :status :good :model "ScanPartner Jr" :interface "SCSI" :status :untested :model "ScanStation" :interface "SCSI" :status :untested :model "fi-4010CU" :interface "USB" :usbid "0x04c5" "0x1029" :status :untested :model "fi-5015C" :interface "USB" :usbid "0x04c5" "0x10ef" :status :good :mfg "Kodak" :url "http://www.kodak.com" :model "i30" :interface "USB" :usbid "0x040a" "0x6001" :status :untested :model "i40" :interface "USB" :usbid "0x040a" "0x6002" :status :basic :model "i50" :interface "USB" :usbid "0x040a" "0x6003" :status :untested :model "i55" :interface "USB" :usbid "0x040a" "0x6003" :status :untested :model "i60" :interface "USB" :usbid "0x040a" "0x6004" :status :untested :model "i65" :interface "USB" :usbid "0x040a" "0x6004" :status :untested :model "i80" :interface "USB" :usbid "0x040a" "0x6005" :status :good :mfg "iVina" :model "1200U" :interface "USB" :usbid "0x0638" "0x0268" :status :untested :mfg "Visioneer" :model "Strobe XP 450" :interface "USB" :usbid "0x04a7" "0x0424" :comment "sheetfed scanner" :status :complete :model "Strobe XP 450-G" :interface "USB" :usbid "0x04a7" "0x0491" :comment "sheetfed scanner" :status :complete :model "Strobe XP 470" :interface "USB" :usbid "0x04a7" "0x0479" :comment "sheetfed scanner" :status :complete :model "Strobe XP 470-G" :interface "USB" :usbid "0x04a7" "0x048f" :comment "sheetfed scanner" :status :complete :model "9320" :interface "USB" :usbid "0x04a7" "0x0420" :comment "sheetfed scanner" :status :complete :model "9450" :interface "USB" :usbid "0x04a7" "0x0421" :comment "sheetfed scanner" :status :complete :model "9450-G" :interface "USB" :usbid "0x04a7" "0x047a" :comment "sheetfed scanner" :status :complete :model "9550" :interface "USB" :usbid "0x04a7" "0x0422" :comment "sheetfed scanner" :status :complete :model "9650" :interface "USB" :usbid "0x04a7" "0x0390" :comment "sheetfed scanner" :status :complete :model "9650-G" :interface "USB" :usbid "0x04a7" "0x047b" :comment "sheetfed scanner" :status :complete :model "9750" :interface "USB" :usbid "0x04a7" "0x0423" :comment "sheetfed scanner" :status :complete :model "9750-G" :interface "USB" :usbid "0x04a7" "0x0493" :comment "sheetfed scanner" :status :complete :model "Patriot 430" :interface "USB" :usbid "0x04a7" "0x0497" :comment "sheetfed scanner" :status :complete :model "Patriot 470" :interface "USB" :usbid "0x04a7" "0x048f" :comment "sheetfed scanner" :status :complete :model "Patriot 680" :interface "USB" :usbid "0x04a7" "0x0498" :comment "sheetfed scanner" :status :complete :model "Patriot 780" :interface "USB" :usbid "0x04a7" "0x0499" :comment "sheetfed scanner" :status :complete :mfg "Xerox" :model "DocuMate150" :interface "USB" :usbid "0x04a7" "0x049c" :status :good :model "DocuMate152" :interface "USB" :usbid "0x04a7" "0x0477" :status :good :model "DocuMate162" :interface "USB" :usbid "0x04a7" "0x049d" :status :good :model "DocuMate250" :interface "USB" :usbid "0x04a7" "0x0448" :status :good :model "DocuMate250-G" :interface "USB" :usbid "0x04a7" "0x0490" :status :good :model "DocuMate252" :interface "USB" :usbid "0x04a7" "0x0449" :status :good :model "DocuMate252-G" :interface "USB" :usbid "0x04a7" "0x048c" :status :good :model "DocuMate232" :interface "USB" :usbid "0x04a7" "0x0476" :status :good :model "DocuMate262" :interface "USB" :usbid "0x04a7" "0x044c" :status :good :model "DocuMate262-G" :interface "USB" :usbid "0x04a7" "0x048d" :status :good :model "DocuMate262i" :interface "USB" :usbid "0x04a7" "0x04a7" :status :good :model "DocuMate272" :interface "USB" :usbid "0x04a7" "0x0475" :status :untested :model "DocuMate272-G" :interface "USB" :usbid "0x04a7" "0x048e" :status :untested :model "DocuMate510" :interface "USB" :usbid "0x04a7" "0x0446" :status :untested :model "DocuMate512" :interface "USB" :usbid "0x04a7" "0x0495" :status :untested :model "DocuMate510-G" :interface "USB" :usbid "0x04a7" "0x047c" :status :untested :model "DocuMate520" :interface "USB" :usbid "0x04a7" "0x0447" :status :untested :model "DocuMate520-G" :interface "USB" :usbid "0x04a7" "0x0492" :status :untested :model "DocuMate632" :interface "USB" :usbid "0x04a7" "0x0498" :status :untested :model "DocuMate752" :interface "USB" :usbid "0x04a7" "0x0478" :status :untested :model "DocuMate752" :interface "USB" :usbid "0x04a7" "0x049a" :status :untested :mfg "OKI" :model "S700 Scancopier" :interface "USB" :usbid "0x0638" "0x0a16" :comment "1 pass, 600 dpi, A4" :status :good :mfg "Bell+Howell" :model "2000F" :interface "SCSI" :comment "1 pass, ??? dpi, A4" :status :basic :mfg "Kyocera" :model "FS-1016MFP" :interface "USB" :usbid "0x0482" "0x0335" :comment "1 pass, ??? dpi, A4" :status :untested sane-backends-1.0.27/doc/descriptions/xerox_mfp.desc0000664000175000017500000001520112775312262017352 00000000000000:backend "xerox_mfp" :version "1.0-13" :manpage "sane-xerox_mfp" :devicetype :scanner :mfg "Xerox" :url "http://www.office.xerox.com/" :model "Phaser 6110MFP" :interface "USB" :usbid "0x0924" "0x3d5d" :status :good :model "Phaser 3200MFP" :interface "USB" :usbid "0x0924" "0x3da4" :status :complete :url "http://www.office.xerox.com/multifunction-printer/multifunction-under-30ppm/phaser-3200mfp/spec-enus.html" :model "WorkCentre 3119 Series" :interface "USB" :usbid "0x0924" "0x4265" :status :good :model "WorkCentre 4118 Series" :interface "USB" :usbid "0x0924" "0x420c" :status :good :model "WorkCentre 3210" :interface "USB" :usbid "0x0924" "0x4293" :status :good :model "WorkCentre 3220" :interface "USB" :usbid "0x0924" "0x4294" :status :good :mfg "Dell" :url "http://www.dell.com/" :model "Dell MFP Laser Printer 1815dn" :interface "USB" :usbid "0x413c" "0x5124" :status :good :model "Dell 1235cn" :interface "USB" :usbid "0x413c" "0x5310" :status :good :mfg "Samsung" :url "http://www.samsung.com" :model "X4300 Series" :interface "USB" :usbid "0x04e8" "0x3324" :status :untested :model "K4350 Series" :interface "USB" :usbid "0x04e8" "0x3325" :status :untested :model "X7600 Series" :interface "USB" :usbid "0x04e8" "0x3326" :status :untested :model "K7600 Series" :interface "USB" :usbid "0x04e8" "0x3327" :status :untested :model "K703 Series" :interface "USB" :usbid "0x04e8" "0x3331" :status :untested :model "X703 Series" :interface "USB" :usbid "0x04e8" "0x3332" :status :untested :model "SCX-4x16" :interface "USB" :usbid "0x04e8" "0x3409" :status :untested :model "SCX-6x20" :interface "USB" :usbid "0x04e8" "0x340d" :status :untested :model "MFP-560" :interface "USB" :usbid "0x04e8" "0x340e" :status :untested :model "MFP-750" :interface "USB" :usbid "0x04e8" "0x340f" :status :untested :model "SCX-4x20" :interface "USB" :usbid "0x04e8" "0x3412" :status :untested :model "SCX-4100" :interface "USB" :usbid "0x04e8" "0x3413" :status :good :model "SCX-4x21" :interface "USB" :usbid "0x04e8" "0x3419" :status :untested :model "SCX-5x30" :interface "USB" :usbid "0x04e8" "0x341a" :status :untested :model "SCX-4200" :interface "USB" :usbid "0x04e8" "0x341b" :status :good :model "CLX-3160" :interface "USB" :usbid "0x04e8" "0x341c" :status :untested :model "SCX-6x22" :interface "USB" :usbid "0x04e8" "0x341d" :status :untested :model "SCX4725" :interface "USB" :usbid "0x04e8" "0x341f" :status :untested :model "SCX4725-FN" :interface "USB" :usbid "0x04e8" "0x341f" :status :good :model "SCX-6x45" :interface "USB" :usbid "0x04e8" "0x3420" :status :untested :model "CLX-8380" :interface "USB" :usbid "0x04e8" "0x3421" :status :untested :model "CLX-2160" :interface "USB" :usbid "0x04e8" "0x3425" :status :good :model "SCX-4500" :interface "USB" :usbid "0x04e8" "0x3426" :status :good :model "CLX-6200" :interface "USB" :usbid "0x04e8" "0x3427" :status :untested :model "CLX-6240" :interface "USB" :usbid "0x04e8" "0x3428" :status :untested :model "SCX-6x55" :interface "USB" :usbid "0x04e8" "0x3429" :status :good :model "CLX-3170fn (CLX-3170 Series)" :interface "USB" :usbid "0x04e8" "0x342a" :status :good :model "CLX-3175FW" :interface "USB" :usbid "0x04e8" "0x342a" :status :good :model "SCX-4500W" :interface "USB Ethernet" :usbid "0x04e8" "0x342b" :status :basic :model "SCX-4824 (SCX-4x24 Series)" :interface "USB" :usbid "0x04e8" "0x342c" :status :good :model "SCX-4828FN (SCX-4x28 Series)" :interface "USB" :usbid "0x04e8" "0x342d" :status :good :model "SCX-4300" :interface "USB" :usbid "0x04e8" "0x342e" :status :good :model "SCX-5835_5935" :interface "USB" :usbid "0x04e8" "0x342f" :status :good :model "SCX-5635" :interface "USB" :usbid "0x04e8" "0x3430" :status :untested :model "SCX-4x26" :interface "USB" :usbid "0x04e8" "0x3432" :status :untested :model "SCX-4600" :interface "USB" :usbid "0x04e8" "0x3433" :status :good :model "SCX-4623" :interface "USB" :usbid "0x04e8" "0x3434" :status :good :model "MFP-65x" :interface "USB" :usbid "0x04e8" "0x3435" :status :untested :model "SCX-6545" :interface "USB" :usbid "0x04e8" "0x3437" :status :good :model "CLX-8385" :interface "USB" :usbid "0x04e8" "0x3439" :status :untested :model "CLX-6220" :interface "USB" :usbid "0x04e8" "0x343a" :status :good :model "CLX-6250" :interface "USB" :usbid "0x04e8" "0x343b" :status :untested :model "SCX-4825FN (SCX-4x25 Series)" :interface "USB" :usbid "0x04e8" "0x343c" :status :good :model "CLX-3185" :interface "USB" :usbid "0x04e8" "0x343d" :status :good :model "CLX-8540" :interface "USB" :usbid "0x04e8" "0x343f" :status :untested :model "SCX-4623FW" :interface "USB" :usbid "0x04e8" "0x3440" :status :good :model "SCX-3205W (SCX-3200 Series)" :interface "USB Ethernet" :usbid "0x04e8" "0x3441" :status :good :model "SCX-6545X" :interface "USB" :usbid "0x04e8" "0x3442" :status :good :model "SCX-6x55X" :interface "USB" :usbid "0x04e8" "0x3443" :status :good :model "CLX-8385X" :interface "USB" :usbid "0x04e8" "0x3444" :status :good :model "SCX-5835_5935X" :interface "USB" :usbid "0x04e8" "0x3446" :status :good :model "SCX-4833FD" :interface "USB" :usbid "0x04e8" "0x344b" :status :good :model "SCX-4835FD" :interface "Ethernet" :usbid "0x04e8" "0x344b" :status :good :model "SCX-3405W" :interface "Ethernet" :status :good :model "SCX-3400" :interface "USB" :usbid "0x04e8" "0x344f" :status :good :model "SF-760" :interface "USB" :usbid "0x04e8" "0x3450" :status :untested :model "SCX-4729FD" :interface "USB" :usbid "0x04e8" "0x3453" :status :good :model "CLX-6260" :interface "USB" :usbid "0x04e8" "0x3455" :status :good :model "CLX-3300 Series" :interface "USB" :usbid "0x04e8" "0x3456" :status :good :model "SCX-470x" :interface "USB" :usbid "0x04e8" "0x3457" :status :untested :model "CLX-4190" :interface "USB" :usbid "0x04e8" "0x345a" :status :good :model "SCX-4650 4x21S Series" :interface "USB" :usbid "0x04e8" "0x345b" :status :untested :model "M337x 387x 407x Series" :interface "USB" :usbid "0x04e8" "0x3460" :status :good :model "M267x 287x Series" :interface "USB" :usbid "0x04e8" "0x3461" :status :unsupported :model "SCX-681x" :interface "USB" :usbid "0x04e8" "0x3466" :status :untested :model "C460" :interface "USB" :usbid "0x04e8" "0x3468" :status :untested :model "M458x Series" :interface "USB" :usbid "0x04e8" "0x346f" :status :untested :model "M4370 5370 Series" :interface "USB" :usbid "0x04e8" "0x3471" :status :untested :model "X401 Series" :interface "USB" :usbid "0x04e8" "0x3477" :status :untested :model "K401 Series" :interface "USB" :usbid "0x04e8" "0x3478" :status :untested :model "K3250 Series" :interface "USB" :usbid "0x04e8" "0x3481" :status :untested :model "X3220 Series" :interface "USB" :usbid "0x04e8" "0x3482" :status :untested sane-backends-1.0.27/doc/descriptions/test.desc0000664000175000017500000000157113063340150016313 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "test" ; name of backend :version "1.0-28 (unmaintained)" ; version of backend :manpage "sane-test" ; name of manpage (if it exists) :url "http://www.meier-geinitz.de/sane/test-backend/" ; backend's web page :devicetype :api ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :desc "Frontend-tester" :comment "Backend for testing frontends. Also serves as example for SANE backend options." sane-backends-1.0.27/doc/descriptions/mustek_pp.desc0000664000175000017500000000714613063340150017347 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "mustek_pp" ; name of backend :version "13 (unmaintained)" ; version of backend :manpage "sane-mustek_pp" ; name of manpage (if it exists) ; backend's web page :url "http://penguin-breeder.org/sane/mustek_pp/" :comment "Supports CIS and CCD type parallel port scanners from Mustek." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Mustek" ; name a manufacturer :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "ScanExpress 6000 P" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "ScanExpress 600 SEP" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "ScanMagic 4800 P" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "600 III EP Plus" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "96 CP" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :model "ScanExpress 600 CP" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :model "ScanMagic 600 CP" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :model "ScanExpress 1200 CP" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :model "ScanExpress 1200 CP+" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.de/" :comment "Those scanners are also known as \"Aldi Scanner\" or \"Tchibo Scanners\"" :model "MD 9848" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "MD 9806" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "MD/LT 935x" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :model "MD/LT 985x" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :model "MD/LT 9890" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :mfg "Targa" :model "Funline TS12 EP" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :model "Funline TS6 EP" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :mfg "Trust" :url "http://www.trust-site.com/home/" :model "Easy Connect 9600+" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :model "Easy Connect 19200+" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :mfg "Viviscan" :model "Compact II" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :mfg "Cybercom" :model "9352" :interface "Parport (EPP)" :status :good :comment "CIS scanner" :mfg "Gallery" :model "4800" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :mfg "Network" :model "Easy Plus 30 Bit" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :mfg "Micromaxx" :model "MM-9851" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/dc210.desc0000664000175000017500000000071713063340150016146 00000000000000;Kodak DC210 backend .desc file by Brian J. Murrell :backend "dc210" ; name of backend :version "0.0 (unmaintained)" ; version of backend :manpage "sane-dc210" ; name of manpage (if it exists) :url "mailto:peter@fales-lorenz.net" ; backend's web page :devicetype :stillcam ; start of a list of devices.... :mfg "Kodak" :url "http://www.kodak.com/global/en/service/digCam/dc210/dc210.shtml" :model "DC210" :interface "Serial port" :status :basic sane-backends-1.0.27/doc/descriptions/leo.desc0000664000175000017500000000162113063340150016107 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "leo" ; name of backend :version "1.0-10 (unmaintained)" ; version of backend :manpage "sane-leo" ; name of manpage (if it exists) :url "http://www.zago.net/sane/#leo" ; backend's web page :devicetype :scanner ; start of a list of devices.... :mfg "LEO" :model "LEOScan S3" :interface "SCSI" :comment "FCC ID LUZFS1130" :status :good :mfg "Across Technologies" :model "FS-1130" :interface "SCSI" :comment "FCC ID LUZFS1130" :status :good :mfg "Genius" :model "FS-1130 Colorpage Scanner" :interface "SCSI" :status :good sane-backends-1.0.27/doc/descriptions/teco2.desc0000664000175000017500000000314413063340150016346 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "teco2" ; name of backend :version "1.0-9 (unmaintained)" ; version of backend :manpage "sane-teco2" :url "http://gkall.hobby.nl/teco2.html" ; backend's web page :devicetype :scanner :mfg "Relisys" :url "http://www.relisys.com/" :model "AVEC Super 3" :interface "SCSI" :comment "sub model VM3575" :status :untested :model "AVEC II S3" :interface "SCSI" :comment "sub model VM3564" :status :good :model "SCORPIO Super 3" :comment "sub model VM3575" :interface "SCSI" :status :good :model "APOLLO Express 3" :comment "sub model VM356A" :interface "SCSI" :status :basic :model "APOLLO Express 6" :comment "sub model VM6565" ; aka VM656A :interface "SCSI" :status :good :model "SCORPIO Pro" :comment "sub model VM6575" :interface "SCSI" :status :good :model "SCORPIO Pro-S" :comment "sub model VM6586" :interface "SCSI" :status :untested :mfg "Primax" :url "http://www.primax.nl/" :model "Jewel 4800" :comment "sub model VM356A" :interface "SCSI" :status :good :model "Profi 9600" :comment "sub model VM6575" :interface "SCSI" :status :basic :model "Profi 19200" :comment "sub model VM6586" :interface "SCSI" :status :good :mfg "Mustek" :url "http://www.mustek.com/" :model "ScanMagic 4830S" :comment "sub model VM3575" :interface "SCSI" :status :untested sane-backends-1.0.27/doc/descriptions/dell1600n_net.desc0000664000175000017500000000054113063340150017603 00000000000000; ; dell1600n_net backend ; Jon Chambers , 2006-05-29 ; :backend "dell1600n_net" :version "unmaintained" :devicetype :scanner :mfg "Dell" :url "http://www.dell.com/" :model "1600n" :interface "Ethernet USB" :usbid "0x413c" "0x5250" :status :basic :comment "Supports colour and monochrome scans over ethernet (USB not supported)" sane-backends-1.0.27/doc/descriptions/teco1.desc0000664000175000017500000000501513063340150016344 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "teco1" ; name of backend :version "1.0-10 (unmaintained)" ; version of backend :manpage "sane-teco1" ; name of manpage (if it exists) :url "http://www.zago.net/sane/#teco" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Relisys" :url "http://www.relisys.com/" :url "http://www.tecoimage.com.tw/" :model "RELI 2412" :interface "SCSI" :comment "sub model VM3530+" :status :complete :model "AVEC 2400" :interface "SCSI" :comment "sub model VM3520" :status :complete :model "RELI 4830" :interface "SCSI" :comment "sub model VM4542" :status :good :model "AVEC 2412" :comment "sub model VM3520+" :interface "SCSI" :status :complete :model "AVEC 4800" :comment "sub model VM4530" :interface "SCSI" :status :untested :model "AVEC 4816" :comment "sub model VM4530+" :interface "SCSI" :status :untested :model "RELI DS6" :comment "sub model VM3420" :interface "SCSI" :status :untested :model "RELI DS15" :comment "sub model VM3440" :interface "SCSI" :status :untested :model "RELI 2400" :comment "sub model VM3530" :interface "SCSI" :status :untested :model "RELI 4816" :comment "sub model VM4540" :interface "SCSI" :status :complete :model "RELI 9600" :comment "sub model VM6530" :interface "SCSI" :status :untested :model "RELI 9612" :comment "sub model VM6530*" :interface "SCSI" :status :untested :model "RELI 9624" :comment "sub model VM6530+" :interface "SCSI" :status :untested :model "RELI 9630" :comment "sub model VM6540" :interface "SCSI" :status :untested :mfg "Actown" :model "ACT Scan I 30" :comment "sub model VM3520A" :interface "SCSI" :status :untested :mfg "Dextra" :model "DF-600P" :comment "sub model VM3510" :interface "SCSI" :status :good :model "DF-1200T+" :comment "sub model VM3530+" :interface "SCSI" :status :untested :model "DF-4830T" :comment "sub model VM4542" :interface "SCSI" :status :untested :model "DF-9624" :comment "sub model VM6530+" :interface "SCSI" :status :untested ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/epson.desc0000664000175000017500000001436213063340150016462 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "epson" ; name of backend :version "0.2.42 (unmaintained)" ; version of backend :new :no :manpage "sane-epson" ; name of manpage (if it exists) :url "http://www.khk.net/sane" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Epson" ; name a manufacturer :url "http://www.epson.com/" :model "GT-5000" ; name models for above-specified mfg. :interface "SCSI Parport" :status :good :model "Actionscanner II" :comment "US version of GT-5000" :interface "SCSI Parport" :status :good :model "GT-6000" :interface "SCSI Parport" :status :good :model "ES-300C" :comment "US version of GT-6000" :interface "SCSI Parport" :status :good :model "ES-300GS" :interface "SCSI" :status :good :model "GT-5500" :interface "SCSI" :status :good :model "GT-6500" :interface "Parport" :status :good :model "ES-600C" :comment "US version of GT-6500" :interface "Parport" :status :good :model "ES-1200C" :comment "US version of GT-9000" :interface "Parport" :status :good :model "GT-7000" :interface "SCSI" :scsi "EPSON" "SCANNER GT-7000" "processor" :status :good :model "GT-8000" :interface "SCSI" :status :good :model "ES-8500" :interface "SCSI" :status :good :model "Perfection 636S" :comment "US version of GT-7000" :interface "SCSI" :scsi "EPSON" "Perfection1200" "processor" :status :complete :model "Perfection 636" :interface "SCSI" :scsi "EPSON" "Perfection636" "processor" :status :complete :model "Perfection 636U" :interface "USB" :usbid "0x04b8" "0x0101" :status :complete :model "Perfection 610" :interface "USB" :usbid "0x04b8" "0x0103" :status :complete :model "Perfection 640" :interface "USB" :usbid "0x04b8" "0x010c" :status :complete :model "Perfection 1200S" :interface "SCSI" :scsi "EPSON" "Perfection1200" "processor" :status :complete :model "Perfection 1200U" :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :model "Perfection 1200Photo" :comment "with TPU" :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :model "Perfection 1240" :interface "SCSI USB" :usbid "0x04b8" "0x010b" :status :complete :model "Perfection 1640" :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :complete :model "Perfection 1650" :interface "USB" :usbid "0x04b8" "0x0110" :status :complete :model "Perfection 1660" :interface "USB" :usbid "0x04b8" "0x011e" :status :complete :model "Perfection 2400" :interface "USB" :usbid "0x04b8" "0x011b" :status :complete :model "Perfection 2450" :interface "USB IEEE-1394" :usbid "0x04b8" "0x0112" :scsi "EPSON" "GT-9700" "processor" :status :complete :model "Perfection 3200" :comment "US version of the GT-9800" :interface "USB IEEE-1394" :usbid "0x04b8" "0x011c" :scsi "EPSON" "GT-9800" "processor" :status :complete :model "Perfection 4870" :comment "US version of the GT-X700" :interface "USB" :usbid "0x04b8" "0x0128" :status :complete :model "Perfection 4990" :comment "US version of the GT-X800" :interface "USB" :usbid "0x04b8" "0x012a" :status :complete :model "Expression 636" :comment "US version of GT-9500" :interface "SCSI" :status :complete :model "Expression 800" :interface "SCSI" :status :complete :scsi "EPSON" "Expression800" "processor" :model "Expression 1600" :interface "SCSI USB IEEE-1394" :usbid "0x04b8" "0x0107" :status :complete :model "Expression 1680" :interface "SCSI USB IEEE-1394" :usbid "0x04b8" "0x010e" :status :complete :model "FilmScan 200" :interface "SCSI" :status :unsupported :model "CX-3200" :interface "USB" :usbid "0x04b8" "0x0802" :status :good :model "CX-3600" :interface "USB" :usbid "0x04b8" "0x080e" :status :good :model "CX-3650" :interface "USB" :usbid "0x04b8" "0x080e" :status :good :model "CX-4600" :interface "USB" :usbid "0x04b8" "0x080d" :status :good :model "CX-4800" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :model "CX-5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :model "CX-5200" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :model "CX-5400" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :model "CX-5400" :interface "USB" :usbid "0x04b8" "0x0808" :status :good :model "CX-6300" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :model "CX-6400" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :model "CX-6500" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :model "CX-6600" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :model "RX-500" :interface "USB" :usbid "0x04b8" "0x0807" :status :good :model "RX-600" :interface "USB" :usbid "0x04b8" "0x0806" :status :good :model "RX-425" :interface "USB" :usbid "0x04b8" "0x080f" :status :good :model "RX-700" :interface "USB" :usbid "0x04b8" "0x0810" :status :good :model "RX-620" :interface "USB" :usbid "0x04b8" "0x0811" :status :good :model "DX-3850" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :model "CX-3700" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :model "CX-3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :model "CX-4200" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :model "DX-3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :model "DX-5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :model "DX-5050" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :model "DX-6000" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :model "DX-7400" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :model "DX-4050" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :model "AcuLaser CX11" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :model "AcuLaser CX11NF" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :model "V700" :interface "USB IEEE-1394" :usbid "0x04b8" "0x012c" :status :good :model "V750" :interface "USB IEEE-1394" :usbid "0x04b8" "0x012c" :status :good sane-backends-1.0.27/doc/descriptions/microtek.desc0000664000175000017500000000416313063340150017151 00000000000000:backend "microtek" :version "0.13.1 (unmaintained)" :manpage "sane-microtek" :url "http://www.mir.com/mtek/" :devicetype :scanner :mfg "Microtek" :url "http://www.microtek.com/" :model "Scanmaker E6" :interface "SCSI" :status :good :model "Scanmaker E3" :interface "SCSI" :status :good :model "Scanmaker E2" :interface "SCSI" :comment "3-pass" :status :good :model "Scanmaker 35t+" :interface "SCSI" :comment "slide-scanner" :status :good :model "Scanmaker 45t" :interface "SCSI" :comment "slide-scanner" :status :good :model "Scanmaker 35" :interface "SCSI" :comment "slide-scanner" :status :good :model "Scanmaker III" :interface "SCSI" :status :good :model "Scanmaker IISP" :interface "SCSI" :status :good :model "Scanmaker IIHR" :interface "SCSI" :comment "3-pass" :status :good :model "Scanmaker IIG" :interface "SCSI" :comment "gray only" :status :good :model "Scanmaker II" :interface "SCSI" :comment "3-pass" :status :good :model "Scanmaker 600Z(S)" :interface "SCSI" :status :untested :model "Scanmaker 600G(S)" :interface "SCSI" :comment "gray only (see manpage)" :status :basic :model "Color PageWiz" :interface "SCSI (Parport)" :comment "sheet-fed (preliminary, see mapage)" :status :basic :mfg "Agfa" :url "http://www.agfa.com/" :model "Arcus II" :interface "SCSI" :comment "Arcus *II*, not Arcus!" :status :good :model "StudioScan" :interface "SCSI" :status :good :model "StudioScan II" :interface "SCSI" :status :good :model "StudioScan IIsi" :interface "SCSI" :status :good :model "Studiostar" :interface "SCSI" :status :minimal :comment "Is detected but scans are very dark" :model "DuoScan" :interface "SCSI" :status :basic :mfg "Vobis" :url "http://www.vobis.de/" :model "Highscreen Realscan" :interface "SCSI" :status :good :mfg "Genius" :url "http://www.genius-kye.com/" :model "Colorpage-SP2" :interface "SCSI" :comment "Same as Microtek Scanmaker E3" :status :good sane-backends-1.0.27/doc/descriptions/fujitsu.desc0000664000175000017500000003467313072310726017044 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "fujitsu" ; name of backend :url "http://www.thebility.com/fujitsu/" :version "133" ; version of backend :manpage "sane-fujitsu" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.26, see sane-fujitsu manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Fujitsu" ; name a manufacturer :url "http://www.fujitsu.com/" ;================================================== ; DISCONTINUED OLDER MODELS, SMALL :model "M3091DC" :interface "SCSI" :url "http://www.remote.org/frederik/projects/software/sane/" :status :complete :comment "small, old, discontinued" :model "M3092DC" :interface "SCSI" :status :complete :comment "small, old, discontinued" ;================================================== ; DISCONTINUED NEWER MODELS, SMALL :model "fi-4120C" :interface "SCSI USB" :usbid "0x04c5" "0x1041" :status :complete :comment "small, recent, discontinued, usb 1.1" :model "fi-4120C2" :interface "SCSI USB" :usbid "0x04c5" "0x10ae" :status :complete :comment "small, recent, discontinued, usb 2.0" :model "fi-4220C" :interface "SCSI USB" :usbid "0x04c5" "0x1042" :status :complete :comment "small, recent, discontinued, usb 1.1" :model "fi-4220C2" :interface "SCSI USB" :usbid "0x04c5" "0x10af" :status :complete :comment "small, recent, discontinued, usb 2.0" :model "fi-5110C" :interface "USB" :status :complete :usbid "0x04c5" "0x1097" :comment "small, recent, discontinued" :model "fi-5110EOX/2" :interface "USB" :status :complete :usbid "0x04c5" "0x1096" :comment "small, recent, discontinued" :model "fi-5110EOX3" :interface "USB" :status :complete :usbid "0x04c5" "0x10e6" :comment "small, recent, discontinued" :model "fi-5110EOXM" :interface "USB" :usbid "0x04c5" "0x10f2" :status :complete :comment "small, recent, discontinued" :model "fi-5120C" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x10e0" :comment "small, recent, discontinued" :model "fi-5220C" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x10e1" :comment "small, recent, discontinued" :model "fi-5000N" :interface "Ethernet" :status :untested :comment "Not a scanner, rather a scanner to ethernet interface" :model "fi-6000NS" :interface "Ethernet" :status :untested :comment "small, recent, discontinued, integrated touchscreen and keyboard" :model "ScanSnap S500" :interface "USB" :status :complete :usbid "0x04c5" "0x10fe" :comment "small, recent, discontinued" :model "ScanSnap S500M" :interface "USB" :status :complete :usbid "0x04c5" "0x1135" :comment "small, recent, discontinued" :model "ScanSnap S510" :interface "USB" :status :complete :usbid "0x04c5" "0x1155" :comment "small, recent, discontinued" :model "ScanSnap S510M" :interface "USB" :status :complete :usbid "0x04c5" "0x116f" :comment "small, recent, discontinued" :model "fi-6125" :interface "USB" :status :complete :usbid "0x04c5" "0x11ee" :comment "small, recent, discontinued" :model "fi-6130" :interface "USB" :status :complete :usbid "0x04c5" "0x114f" :comment "small, recent, discontinued" :model "fi-6230" :interface "USB" :status :complete :usbid "0x04c5" "0x1150" :comment "small, recent, discontinued" :model "fi-6130Z" :interface "USB" :status :complete :usbid "0x04c5" "0x11f3" :comment "small, recent, discontinued" :model "fi-6230Z" :interface "USB" :status :complete :usbid "0x04c5" "0x11f4" :comment "small, recent, discontinued" :model "fi-6120ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x146d" :comment "small, recent, discontinued, expected to work" :model "fi-6220ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x146e" :comment "small, recent, discontinued, expected to work" :model "fi-6125ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x1463" :comment "small, recent, discontinued, expected to work" :model "fi-6225ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x1464" :comment "small, recent, discontinued, expected to work" :model "fi-6130ZLA" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x1461" :comment "small, recent, discontinued" :model "fi-6230ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x1462" :comment "small, recent, discontinued, expected to work" :model "ScanSnap S1500" :interface "USB" :status :complete :usbid "0x04c5" "0x11a2" :comment "small, discontinued" :model "ScanSnap S1500M" :interface "USB" :status :complete :usbid "0x04c5" "0x11a2" :comment "small, discontinued, same as S1500" :model "ScanSnap N1800" :interface "Ethernet" :status :untested :comment "small, discontinued, integrated touchscreen and keyboard" ;================================================== ; CURRENT MODELS, SMALL :model "ScanSnap N7100" :interface "Ethernet" :status :untested :comment "small, current, integrated touchscreen and keyboard" :model "ScanSnap fi-6010N" :interface "Ethernet" :status :untested :comment "small, current, integrated touchscreen and keyboard" :model "fi-6110" :interface "USB" :status :complete :usbid "0x04c5" "0x11fc" :comment "small, current" :model "fi-7160" :interface "USB" :status :complete :usbid "0x04c5" "0x132e" :comment "small, current" :model "fi-7260" :interface "USB" :status :complete :usbid "0x04c5" "0x132f" :comment "small, current" :model "ScanSnap iX500" :interface "USB WiFi" :status :good :usbid "0x04c5" "0x132b" :comment "small, current, WiFi not supported. Hardware only scans in color. Backend generates binary and grayscale modes." :model "ScanSnap iX100" :interface "USB WiFi" :status :good :usbid "0x04c5" "0x13f4" :comment "small, current, WiFi not supported." :model "ScanSnap SV600" :interface "USB" :status :untested :usbid "0x04c5" "0x128e" :comment "Also has a second USB VID 0x13ba. Will require some gymnastics to support." ;================================================== ; DISCONTINUED OLDER MODELS, MEDIUM :model "M3093E" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3093DE" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3093DG" :interface "SCSI" :status :complete :comment "medium, old, discontinued" :model "M3093EX" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3093GX" :interface "SCSI" :status :complete :comment "medium, old, discontinued" :model "M3096EX" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3096GX" :interface "SCSI" :status :complete :comment "medium, old, discontinued" :model "M3097E+" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3097G+" :interface "SCSI" :status :complete :comment "medium, old, discontinued" :model "M3097DE" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3097DG" :interface "SCSI" :status :complete :comment "medium, old, discontinued" ;================================================== ; DISCONTINUED NEWER MODELS, MEDIUM :model "fi-4340C" :interface "SCSI USB" :usbid "0x04c5" "0x10cf" :status :complete :comment "medium, current" :model "fi-4530C" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x1078" :comment "medium, recent, discontinued" :model "fi-4640S" :interface "SCSI" :status :complete :comment "medium, recent, discontinued" :model "fi-4750C" :interface "SCSI" :status :complete :comment "medium, recent, discontinued" :model "fi-5530C" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x10e2" :comment "medium, recent, discontinued" :model "fi-6140" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x114d" :comment "medium, recent, discontinued" :model "fi-6240" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x114e" :comment "medium, recent, discontinued" :model "fi-6140Z/fi-6140ZLA" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x11f1" :comment "medium, recent, discontinued" :model "fi-6240Z" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x11f2" :comment "medium, recent, discontinued" :model "fi-6135ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x146b" :comment "medium, recent, discontinued, expected to work" :model "fi-6235ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x146c" :comment "medium, recent, discontinued, expected to work" :model "fi-6140ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x145f" :comment "medium, recent, discontinued, expected to work" :model "fi-6240ZLA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x1460" :comment "medium, recent, discontinued, expected to work" ;================================================== ; CURRENT MODELS, MEDIUM :model "fi-5530C2" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x114a" :comment "medium, current" :model "fi-7180" :interface "USB" :status :complete :usbid "0x04c5" "0x132c" :comment "medium, current" :model "fi-7280" :interface "USB" :status :complete :usbid "0x04c5" "0x132d" :comment "medium, current" ;================================================== ; DISCONTINUED OLDER MODELS, BIG :model "M3099A" :interface "RS232C/Video" :status :unsupported :comment "big, old, discontinued" :model "M3099G" :interface "SCSI" :status :complete :comment "big, old, discontinued" :model "M3099EH" :interface "RS232C/Video" :status :unsupported :comment "big, old, discontinued" :model "M3099GH" :interface "SCSI" :status :complete :comment "big, old, discontinued" :model "M3099EX" :interface "RS232C/Video" :status :unsupported :comment "big, old, discontinued" :model "M3099GX" :interface "SCSI" :status :complete :comment "big, old, discontinued" :model "M4097D" :interface "SCSI" :status :complete :comment "big, old, discontinued" :model "M4099D" :interface "SCSI" :status :complete :comment "big, old, discontinued" ;================================================== ; DISCONTINUED NEWER MODELS, BIG :model "fi-4750L" :interface "SCSI" :status :complete :comment "big, recent, discontinued" :model "fi-4860C" :interface "SCSI" :status :complete :comment "big, recent, discontinued" :model "fi-4860C2" :interface "SCSI" :status :complete :comment "big, recent, discontinued" :model "fi-4990C" :interface "SCSI" :status :complete :comment "big, recent, discontinued" :model "fi-5650C" :interface "SCSI USB" :usbid "0x04c5" "0x10ad" :status :complete :comment "big, recent, discontinued" :model "fi-5750C" :interface "SCSI USB" :usbid "0x04c5" "0x1095" :status :complete :comment "big, recent, discontinued" :model "fi-5900C" :interface "SCSI USB" :usbid "0x04c5" "0x10e7" :status :good :comment "big, recent, discontinued. Independent ultrasonic control and multistream unsupported" :model "fi-6750S" :interface "USB" :status :untested :usbid "0x04c5" "0x1178" :comment "Simplex, USB only version of fi-6770, won't wakeup via software, discontinued" ;================================================== ; CURRENT MODELS, BIG :model "fi-5950" :interface "SCSI USB" :usbid "0x04c5" "0x1213" :status :untested :comment "big, current. Faster version of fi-5900?" :model "fi-6670" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x1176" :comment "big, current, won't wakeup via software" :model "fi-6670A" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x1177" :comment "big, current, VRS CGA board unsupported, won't wakeup via software" :model "fi-6770" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x1174" :comment "big, current, won't wakeup via software" :model "fi-6770A" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x1175" :comment "big, current, VRS CGA board unsupported, won't wakeup via software" :model "fi-6800" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x119d" :comment "big, current. Independent ultrasonic control and multistream unsupported" :model "fi-6800-CGA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x119e" :comment "big, current. VRS CGA board unsupported, Independent ultrasonic control and multistream unsupported" :model "fi-6400" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x14ac" ;================================================== ; 2015/2016/2017 NEW MODELS, UNORDERED :model "fi-6420" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x14bd" :model "fi-6225" :interface "USB" :status :untested :usbid "0x04c5" "0x11ef" :model "ScanSnap iX500EE" :interface "USB" :status :untested :usbid "0x04c5" "0x13f3" :model "ScanPartner SP25" :interface "USB" :status :unsupported :usbid "0x04c5" "0x1409" :comment "Possibly Genesys protocol?" :model "ScanPartner SP30" :interface "USB" :status :unsupported :usbid "0x04c5" "0x140a" :comment "Possibly Genesys protocol?" :model "ScanPartner SP30F" :interface "USB" :status :unsupported :usbid "0x04c5" "0x140c" :comment "Possibly Genesys protocol?" :model "N7100" :interface "USB Ethernet" :status :untested :usbid "0x04c5" "0x146f" :model "fi-7480" :interface "USB" :status :good :usbid "0x04c5" "0x14b8" :model "fi-7460" :interface "USB" :status :good :usbid "0x04c5" "0x14be" :model "fi-7140" :interface "USB" :status :untested :usbid "0x04c5" "0x14df" :model "fi-7240" :interface "USB" :status :untested :usbid "0x04c5" "0x14e0" :model "fi-7135" :interface "USB" :status :untested :usbid "0x04c5" "0x14e1" :model "fi-7235" :interface "USB" :status :untested :usbid "0x04c5" "0x14e2" :model "fi-7130" :interface "USB" :status :untested :usbid "0x04c5" "0x14e3" :model "fi-7230" :interface "USB" :status :untested :usbid "0x04c5" "0x14e4" :model "fi-7125" :interface "USB" :status :untested :usbid "0x04c5" "0x14e5" :model "fi-7225" :interface "USB" :status :untested :usbid "0x04c5" "0x14e6" :model "fi-7120" :interface "USB" :status :untested :usbid "0x04c5" "0x14e7" :model "fi-7220" :interface "USB" :status :untested :usbid "0x04c5" "0x14e8" :model "fi-400F" :interface "USB" :status :untested :usbid "0x04c5" "0x151e" :model "fi-7030" :interface "USB" :status :good :usbid "0x04c5" "0x151f" :model "fi-7700" :interface "USB" :status :good :usbid "0x04c5" "0x1520" :model "fi-7600" :interface "USB" :status :good :usbid "0x04c5" "0x1521" :model "fi-7700S" :interface "USB" :status :untested :usbid "0x04c5" "0x1522" sane-backends-1.0.27/doc/descriptions/pixma.desc0000664000175000017500000007056013110416067016462 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "pixma" ; name of backend :version "0.17.37" ; version of backend (or "unmaintained") :manpage "sane-pixma" ; name of manpage (if it exists) ;:comment "Devices marked as experimantal are disabled by default. See the manual page for how to enable them." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" :model "PIXMA E400" :interface "USB" :usbid "0x04a9" "0x177a" :status :untested :comment "Testers needed!" :model "PIXMA E460 Series" :interface "USB" :usbid "0x04a9" "0x1788" :status :untested :comment "Testers needed!" :model "PIXMA E470 Series" :interface "USB" :usbid "0x04a9" "0x180c" :status :untested :comment "Testers needed!" :model "PIXMA E480 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1789" :status :untested :comment "Testers needed!" :model "PIXMA E500" :interface "USB" :usbid "0x04a9" "0x1758" :status :untested :comment "Testers needed!" :model "PIXMA E510" :interface "USB" :usbid "0x04a9" "0x1761" :status :untested :comment "Testers needed!" :model "PIXMA E560" :interface "USB" :usbid "0x04a9" "0x177b" :status :untested :comment "Testers needed!" :model "PIXMA E600" :interface "USB" :usbid "0x04a9" "0x175a" :status :untested :comment "Testers needed!" :model "PIXMA E610" :interface "USB" :usbid "0x04a9" "0x1767" :status :untested :comment "Testers needed!" :model "PIXMA G3000" :interface "USB WIFI" :usbid "0x04a9" "0x181d" :status :untested :comment "Testers needed!" :model "PIXMA MG2100 Series" :interface "USB" :usbid "0x04a9" "0x1751" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG2200 Series" :interface "USB" :usbid "0x04a9" "0x1760" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG2400 Series" :interface "USB" :usbid "0x04a9" "0x176c" :status :complete :comment "All resolutions supported (up to 600DPI)." :model "PIXMA MG2500 Series" :interface "USB" :usbid "0x04a9" "0x176d" :status :complete :comment "All resolutions supported (up to 600DPI)." :model "PIXMA MG2900 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1780" :status :complete :comment "All resolutions supported (up to 600DPI)." :model "PIXMA MG3000 Series" :interface "USB WiFi" :usbid "0x04a9" "0x180b" :status :untested :comment "Testers needed!" :model "PIXMA MG3100 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1752" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG3200 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1762" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG3500 Series" :interface "USB WiFi" :usbid "0x04a9" "0x176e" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG3600 Series" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x178a" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG4100 Series" :interface "USB" :usbid "0x04a9" "0x1753" :status :untested :comment "Testers needed!" :model "PIXMA MG4200 Series" :interface "USB" :usbid "0x04a9" "0x1763" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG5100 Series" :interface "USB" :usbid "0x04a9" "0x1748" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG5200 Series" :interface "USB" :usbid "0x04a9" "0x1749" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG5300 Series" :interface "USB" :usbid "0x04a9" "0x1754" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG5400 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1764" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG5500 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1771" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG5600 Series" :interface "USB WiFi" :usbid "0x04a9" "0x177f" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG5700 Series" :interface "USB WiFi" :usbid "0x04a9" "0x178e" :status :complete :comment "All resolutions supported (up to 1200 DPI)." :model "PIXMA MG6100 Series" :interface "USB" :usbid "0x04a9" "0x174a" :status :complete :comment "All resolutions supported (up to 2400 DPI)" :model "PIXMA MG6200 Series" :interface "USB" :usbid "0x04a9" "0x1755" :status :complete :comment "All resolutions supported (up to 4800 DPI)" :model "PIXMA MG6300 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1765" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG6400 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1770" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG6500 Series" :interface "USB" :usbid "0x04a9" "0x176f" :status :untested :comment "Testers needed!" :model "PIXMA MG6600 Series" :interface "USB" :usbid "0x04a9" "0x177e" :status :untested :comment "Testers needed!" :model "PIXMA MG6800 Series" :interface "USB WiFi" :usbid "0x04a9" "0x178d" :status :untested :comment "Testers needed!" :model "PIXMA MG6900 Series" :interface "USB WiFi" :usbid "0x04a9" "0x178c" :status :untested :comment "Testers needed!" :model "PIXMA MG7100 Series" :interface "USB" :usbid "0x04a9" "0x1772" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG7500 Series" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x177c" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG7700 Series" :interface "USB WiFi" :usbid "0x04a9" "0x178b" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG8100 Series" :interface "USB" :usbid "0x04a9" "0x174b" :status :untested :comment "Testers needed!" :model "PIXMA MG8200 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1756" :status :complete :comment "All resolutions supported (up to 4800DPI)." :model "PIXUS MP5" :interface "USB" :usbid "0x04a9" "0x2635" :status :untested :comment "Testers needed! Identical with imageCLASS MPC190." :model "PIXUS MP10" :interface "USB" :usbid "0x04a9" "0x261f" :status :complete :comment "All resolutions supported (up to 600DPI). Identical with imageCLASS MPC200." :model "PIXMA MP140" :interface "USB" :usbid "0x04a9" "0x172b" :status :complete :comment "All resolutions supported (up to 600 DPI)" :model "PIXMA MP150" :interface "USB" :usbid "0x04a9" "0x1709" :status :good :model "PIXMA MP160" :interface "USB" :usbid "0x04a9" "0x1714" :status :basic :model "PIXMA MP170" :interface "USB" :usbid "0x04a9" "0x170a" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP180" :interface "USB" :usbid "0x04a9" "0x1715" :status :basic :model "PIXMA MP190" :interface "USB" :usbid "0x04a9" "0x1734" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "PIXMA MP210" :interface "USB" :usbid "0x04a9" "0x1721" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "PIXMA MP220" :interface "USB" :usbid "0x04a9" "0x1722" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP230" :interface "USB" :usbid "0x04a9" "0x175f" :status :complete :comment "All resolutions supported (up to 600DPI)." :model "PIXMA MP240" :interface "USB" :usbid "0x04a9" "0x1732" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP250" :interface "USB" :usbid "0x04a9" "0x173a" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "PIXMA MP260" :interface "USB" :usbid "0x04a9" "0x1733" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP270" :interface "USB" :usbid "0x04a9" "0x173b" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP280" :interface "USB" :usbid "0x04a9" "0x1746" :status :good :comment "All resolutions supported (up to 600DPI)." :model "PIXMA MP360" :interface "USB" :usbid "0x04a9" "0x263c" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP370" :interface "USB" :usbid "0x04a9" "0x263d" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP375R" :interface "USB" :usbid "0x04a9" "0x263f" :status :untested :comment "Same protocol as Pixma MP360/370/390? Testers needed!" :model "PIXMA MP390" :interface "USB" :usbid "0x04a9" "0x263e" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP450" :interface "USB" :usbid "0x04a9" "0x170b" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP460" :interface "USB" :usbid "0x04a9" "0x1716" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP470" :interface "USB" :usbid "0x04a9" "0x1723" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MP480" :interface "USB" :usbid "0x04a9" "0x1731" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP490" :interface "USB" :usbid "0x04a9" "0x173c" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP493" :interface "USB" :usbid "0x04a9" "0x1757" :status :untested :comment "Testers needed!" :model "PIXMA MP495" :interface "USB" :usbid "0x04a9" "0x1747" :status :untested :comment "Same protocol as Pixma MP280? Testers needed!" :model "PIXMA MP500" :interface "USB" :usbid "0x04a9" "0x170c" :status :good :model "PIXMA MP510" :interface "USB" :usbid "0x04a9" "0x1717" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP520" :interface "USB" :usbid "0x04a9" "0x1724" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP530" :interface "USB" :usbid "0x04a9" "0x1712" :status :good :model "PIXMA MP540" :interface "USB" :usbid "0x04a9" "0x1730" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP550" :interface "USB" :usbid "0x04a9" "0x173d" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP560" :interface "USB" :usbid "0x04a9" "0x173e" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP600" :interface "USB" :usbid "0x04a9" "0x1718" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP600R" :interface "USB Ethernet" :usbid "0x04a9" "0x1719" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP610" :interface "USB" :usbid "0x04a9" "0x1725" :status :complete :comment "All resolutions supported (up to 4800DPI)" :model "PIXMA MP620" :interface "USB Ethernet" :usbid "0x04a9" "0x172f" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP630" :interface "USB" :usbid "0x04a9" "0x172e" :status :complete :comment "All resolutions supported (up to 4800DPI)" :model "PIXMA MP640" :interface "USB Ethernet" :usbid "0x04a9" "0x173f" :status :complete :comment "All resolutions supported (up to 4800DPI)" :model "PIXMA MP700" :interface "USB" :usbid "0x04a9" "0x2630" :status :complete :comment "All resolutions supported (flatbed color up to 1200DPI, grayscale up to 600DPI)." :model "PIXMA MP710" :interface "USB" :usbid "0x04a9" "0x264d" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP730" :interface "USB" :usbid "0x04a9" "0x262f" :status :good :comment "Flatbed color up to 1200DPI, grayscale up to 600DPI. ADF scan to be confirmed." :model "PIXMA MP740" :interface "USB" :usbid "0x04a9" "0x264c" :status :untested :comment "Same protocol as Pixma MP710? Testers needed!" :model "PIXMA MP750" :interface "USB" :usbid "0x04a9" "0x1706" :status :minimal :comment "No grayscale. Canceling scan in ADF mode doesn't eject the paper!" :model "PIXMA MP760" :interface "USB" :usbid "0x04a9" "0x1708" :status :minimal :comment "No grayscale. The scanner sometimes hangs!" :model "PIXMA MP770" :interface "USB" :usbid "0x04a9" "0x1708" :status :minimal :comment "No grayscale. The scanner sometimes hangs!" :model "PIXMA MP780" :interface "USB" :usbid "0x04a9" "0x1707" :status :minimal :comment "No grayscale. The scanner sometimes hangs!" :model "PIXMA MP790" :interface "USB" :usbid "0x04a9" "0x1707" :status :minimal :comment "No grayscale. The scanner sometimes hangs!" :model "PIXMA MP800" :interface "USB" :usbid "0x04a9" "0x170d" :status :complete :comment "All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI." :model "PIXMA MP800R" :interface "USB" :usbid "0x04a9" "0x170e" :status :complete :comment "All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI." :model "PIXMA MP810" :interface "USB" :usbid "0x04a9" "0x171a" :status :complete :comment "All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI." :model "PIXMA MP830" :interface "USB" :usbid "0x04a9" "0x1713" :status :complete :comment "All resolutions supported up to 2400DPI. Flatbed, ADF simplex and Duplex supported." :model "PIXMA MP960" :interface "USB" :usbid "0x04a9" "0x171b" :status :complete :comment "All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI." :model "PIXMA MP970" :interface "USB Ethernet" :usbid "0x04a9" "0x1726" :status :complete :comment "All resolutions supported (up to 4800DPI). Full TPU support (negative and slides) at 24 or 48 bits." :model "PIXMA MP980" :interface "USB Ethernet" :usbid "0x04a9" "0x172d" :status :complete :comment "Working fine at all resolutions." :model "PIXMA MP990" :interface "USB Ethernet" :usbid "0x04a9" "0x1740" :status :complete :comment "Working fine at all resolutions." :model "PIXMA MX300" :interface "USB" :usbid "0x04a9" "0x1727" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "PIXMA MX310" :interface "USB" :usbid "0x04a9" "0x1728" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)" :model "PIXMA MX320" :interface "USB" :usbid "0x04a9" "0x1736" :status :untested :comment "Same protocol as Pixma Generation 3? Testers needed!" :model "PIXMA MX330" :interface "USB" :usbid "0x04a9" "0x1737" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)" :model "PIXMA MX340" :interface "USB" :usbid "0x04a9" "0x1741" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)" :model "PIXMA MX350" :interface "USB Ethernet" :usbid "0x04a9" "0x1742" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)" :model "PIXMA MX360" :interface "USB" :usbid "0x04a9" "0x174d" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX370 Series" :interface "USB" :usbid "0x04a9" "0x1759" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX390 Series" :interface "USB" :usbid "0x04a9" "0x1766" :status :untested :comment "Testers needed!" :model "PIXMA MX410" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x174e" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX420" :interface "USB Ethernet" :usbid "0x04a9" "0x174f" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX430 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175b" :status :untested :comment "Testers needed!" :model "PIXMA MX450 Series" :interface "USB" :usbid "0x04a9" "0x1768" :status :untested :comment "Testers needed!" :model "PIXMA MX470 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1774" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX490 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1787" :status :untested :comment "Testers needed!" :model "PIXMA MX510 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175c" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX520 Series" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x1769" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX530 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1775" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX700" :interface "USB Ethernet" :usbid "0x04a9" "0x1729" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 2400DPI)" :model "PIXMA MX710 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175d" :status :untested :comment "Testers needed!" :model "PIXMA MX720 Series" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x176a" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX850" :interface "USB Ethernet" :usbid "0x04a9" "0x172c" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX860" :interface "USB Ethernet" :usbid "0x04a9" "0x1735" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX870" :interface "USB Ethernet" :usbid "0x04a9" "0x1743" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX880 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX882" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX885" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX890 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175e" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX920 Series" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x176b" :status :good :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX7600" :interface "USB Ethernet" :usbid "0x04a9" "0x171c" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 4800DPI)" :model "PIXMA TS9000 Series" :interface "USB WiFi" :usbid "0x04a9" "0x179f" :status :untested :comment "Testers needed!" :model "PIXMA TS8000 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1800" :status :untested :comment "Testers needed!" :model "PIXMA TS6000 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1801" :status :untested :comment "Testers needed!" :model "PIXMA TS5000 Series" :interface "USB WiFi" :usbid "0x04a9" "0x1802" :status :untested :comment "Testers needed!" :model "imageCLASS D420" :interface "USB" :usbid "0x04a9" "0x26ef" :status :complete :comment "All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported." :model "imageCLASS D480" :interface "USB" :usbid "0x04a9" "0x26ed" :status :complete :comment "All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported." :model "imageCLASS D530" :interface "USB" :usbid "0x04a9" "0x2775" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "i-SENSYS MF210 Series" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x27a9" :status :untested :comment "Testers needed!" :model "i-SENSYS MF220 Series" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x27a8" :status :untested :comment "Testers needed!" :model "i-SENSYS MF230 Series" :interface "USB WiFi" :usbid "0x04a9" "0x27d1" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). WiFi only for w Types." :model "i-SENSYS MF240 Series" :interface "USB Ethernet WiFi" :usbid "0x04a9" "0x27d2" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). ADF only 300DPI." :model "i-SENSYS MF810/820" :interface "USB Ethernet" :usbid "0x04a9" "0x27a6" :status :untested :comment "Testers needed!" :model "i-SENSYS MF3010" :interface "USB Ethernet" :usbid "0x04a9" "0x2759" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF3110" :interface "USB" :usbid "0x04a9" "0x2660" :status :complete :comment "All resolutions supported (up to 600DPI)." :model "imageCLASS MF3240" :interface "USB" :usbid "0x04a9" "0x2684" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4010" :interface "USB" :usbid "0x04a9" "0x26b4" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4018" :interface "USB" :usbid "0x04a9" "0x26b4" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4120" :interface "USB" :usbid "0x04a9" "0x26a3" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4122" :interface "USB" :usbid "0x04a9" "0x26a3" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4140" :interface "USB" :usbid "0x04a9" "0x26a3" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4150" :interface "USB" :usbid "0x04a9" "0x26a3" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF4270" :interface "USB" :usbid "0x04a9" "0x26b5" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "I-SENSYS MF4320d" :interface "USB" :usbid "0x04a9" "0x26ee" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "I-SENSYS MF4330d" :interface "USB" :usbid "0x04a9" "0x26ee" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF4350d" :interface "USB" :usbid "0x04a9" "0x26ee" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF4370dn" :interface "USB" :usbid "0x04a9" "0x26ec" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported" :model "imageCLASS MF4380dn" :interface "USB" :usbid "0x04a9" "0x26ec" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported" :model "imageCLASS MF4410" :interface "USB" :usbid "0x04a9" "0x2737" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4430" :interface "USB" :usbid "0x04a9" "0x2737" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). ADF empty buggy." :model "i-SENSYS MF4500 Series" :interface "USB" :usbid "0x04a9" "0x2736" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)." :model "imageCLASS MF4570dw" :interface "USB" :usbid "0x04a9" "0x275a" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4660" :interface "USB" :usbid "0x04a9" "0x26b0" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF4690" :interface "USB" :usbid "0x04a9" "0x26b0" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "i-SENSYS MF4700 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x2774" :status :good :comment "Flatbed scan. All resolutions supported (up to 600DPI). ADF buggy." :model "i-SENSYS MF4800 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x2773" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Ethernet buggy." :model "imageCLASS MF5630" :interface "USB" :usbid "0x04a9" "0x264e" :status :untested :comment "Testers needed!" :model "laserBase MF5650" :interface "USB" :usbid "0x04a9" "0x264f" :status :untested :comment "Testers needed!" :model "imageCLASS MF5730" :interface "USB" :usbid "0x04a9" "0x265d" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "imageCLASS MF5750" :interface "USB" :usbid "0x04a9" "0x265e" :status :untested :comment "Testers needed!" :model "imageCLASS MF5770" :interface "USB" :usbid "0x04a9" "0x265f" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)." :model "i-SENSYS MF5880dn" :interface "USB" :usbid "0x04a9" "0x26f9" :status :untested :comment "Testers needed!" :model "i-SENSYS MF5900 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x2743" :status :untested :comment "Testers needed!" :model "i-SENSYS MF6100 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x278e" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Note: document feeder does not have 600DPI capability." :model "imageCLASS MF6500 Series" :interface "USB" :usbid "0x04a9" "0x2686" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF6550" :interface "USB" :usbid "0x04a9" "0x2686" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "i-SENSYS MF6680dn" :interface "USB" :usbid "0x04a9" "0x26fa" :status :untested :comment "Testers needed!" :model "imageCLASS MF8030" :interface "USB" :usbid "0x04a9" "0x2707" :status :untested :comment "Testers needed!" :model "imageCLASS MF8170c" :interface "USB" :usbid "0x04a9" "0x2659" :status :untested :comment "Testers needed!" :model "i-SENSYS MF8200C Series" :interface "USB Ethernet" :usbid "0x04a9" "0x2779" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Note: document feeder does not have 600DPI capability." :model "i-SENSYS MF8300 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x2708" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)." :model "i-SENSYS MF8500C Series" :interface "USB Ethernet" :usbid "0x04a9" "0x277a" :status :untested :comment "Same protocol as MF8200C Series? Testers needed!" :model "imageCLASS MPC190" :interface "USB" :usbid "0x04a9" "0x2635" :status :untested :comment "Testers needed! Identical with SmartBase MPC190 and PIXUS MP5." :model "imageCLASS MPC200" :interface "USB" :usbid "0x04a9" "0x261f" :status :complete :comment "All resolutions supported (up to 600DPI). Identical with SmartBase MPC200 and PIXUS MP10." :model "imageRUNNER 1020/1024/1025" :interface "USB" :usbid "0x04a9" "0x26e6" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageRUNNER 1133" :interface "USB" :usbid "0x04a9" "0x2742" :status :untested :comment "Testers needed!" :model "MAXIFY MB2000 Series" :interface "USB" :usbid "0x04a9" "0x1778" :status :untested :comment "Testers needed!" :model "MAXIFY MB2300 Series" :interface "USB" :usbid "0x04a9" "0x1779" :status :untested :comment "Testers needed!" :model "MAXIFY MB5000 Series" :interface "USB" :usbid "0x04a9" "0x1776" :status :complete :comment "Flatbed works, All resolutions supported (up to 1200DPI), ADF does not work" :model "MAXIFY MB5300 Series" :interface "USB" :usbid "0x04a9" "0x1777" :status :untested :comment "Testers needed!" :model "CanoScan 8800F" :interface "USB" :usbid "0x04a9" "0x1901" :status :complete :comment "Flatbed scan. TPU for negatives and slides. All resolutions supported (up to 4800DPI)." :model "CanoScan 9000F" :interface "USB" :usbid "0x04a9" "0x1908" :status :complete :comment "Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI." :model "CanoScan 9000F Mark II" :interface "USB" :usbid "0x04a9" "0x190d" :status :complete :comment "Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI." sane-backends-1.0.27/doc/descriptions/epson2.desc0000664000175000017500000030565113063340150016550 00000000000000; ; SANE Backend specification file for the epson2 backend ; ; Copyright (C) 2009-10 Alessandro Zummo ; Released under GPLv2 ; ; This file is derived from epkowa.desc, Copyright (C) Olaf Meeuwissen, ; distributed with "Image Scan!" and released under GPL. ; ; DO NOT EDIT - It's automatically generated. :backend "epson2" :version "1.0.124 (unmaintained)" :new :no :manpage "sane-epson2" :devicetype :scanner :mfg "Epson" :url "http://www.epson.com/" :model "AL-MX300DN Series" :interface "USB" :usbid "0x04b8" "0x08ac" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :url "http://www.epson.com/" :model "AL-MX300DNF Series" :interface "USB" :usbid "0x04b8" "0x08ac" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Actionscanner II" :interface "parallel SCSI" :status :good :comment "overseas version of the GT-5000" :model "AcuLaser CX11" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :comment "overseas version of the LP-A500" :model "AcuLaser CX11NF" :interface "USB Network" :usbid "0x04b8" "0x0815" :status :good :comment "network interface supported
AcuLaser CX11 with network interface and fax" :model "AcuLaser CX21" :interface "USB Network" :usbid "0x04b8" "0x0835" :status :good :comment "network interface supported" :model "AcuLaser MX20DN" :interface "USB" :usbid "0x04b8" "0x0866" :status :complete :comment "network interface probably supported
business all-in-one" :model "AcuLaser MX20DNF" :interface "USB" :usbid "0x04b8" "0x0866" :status :complete :comment "network interface probably supported
business all-in-one" :model "AcuLaser MX21DNF" :interface "USB" :usbid "0x04b8" "0x0866" :status :complete :comment "network interface probably supported
business all-in-one" :model "Artisan 635" :interface "USB" :usbid "0x04b8" "0x0878" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-704A" :model "Artisan 700" :interface "USB Network" :usbid "0x04b8" "0x0846" :status :good :comment "network interface supported
all-in-one
overseas version of the EP-801A" :model "Artisan 710 Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" :model "Artisan 725" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" :model "Artisan 730 Series" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Artisan 800" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-901A" :model "Artisan 810 Series" :interface "USB" :usbid "0x04b8" "0x0853" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-902A" :model "Artisan 835" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" :model "Artisan 837" :interface "USB" :usbid "0x04b8" "0x0879" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-904F" :model "CC-500L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010d" :status :unsupported :comment "all-in-one" :model "CC-550L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011a" :status :unsupported :comment "all-in-one" :model "CC-570L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one" :model "CC-600PX" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one" :model "CC-700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0108" :status :unsupported :comment "all-in-one" :model "DS-30" :interface "USB" :usbid "0x04b8" "0x0147" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "EP-702A" :interface "USB" :usbid "0x04b8" "0x0850" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-703A" :interface "USB" :usbid "0x04b8" "0x0862" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-704A" :interface "USB" :usbid "0x04b8" "0x0878" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-705A" :interface "USB" :usbid "0x04b8" "0x089f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-706A" :interface "USB" :usbid "0x04b8" "0x08b7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-707A" :interface "USB" :usbid "0x04b8" "0x08c9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-774A" :interface "USB" :usbid "0x04b8" "0x0893" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-775A" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-775AW" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-776AB" :interface "USB" :usbid "0x04b8" "0x08b6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-776AW" :interface "USB" :usbid "0x04b8" "0x08b6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-777A" :interface "USB" :usbid "0x04b8" "0x08c8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-801A" :interface "USB Network" :usbid "0x04b8" "0x0846" :status :good :comment "network interface supported
all-in-one" :model "EP-802A" :interface "USB" :usbid "0x04b8" "0x0852" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-803A" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-803AW" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-804A" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-804AR" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-804AW" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-805A" :interface "USB" :usbid "0x04b8" "0x089c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-805AR" :interface "USB" :usbid "0x04b8" "0x089c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-805AW" :interface "USB" :usbid "0x04b8" "0x089c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-806AB" :interface "USB" :usbid "0x04b8" "0x08b5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-806AR" :interface "USB" :usbid "0x04b8" "0x08b5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-806AW" :interface "USB" :usbid "0x04b8" "0x08b5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-807AB" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-807AR" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-807AW" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-901A" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one" :model "EP-901F" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one" :model "EP-902A" :interface "USB" :usbid "0x04b8" "0x0853" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-903A" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-903F" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-904A" :interface "USB" :usbid "0x04b8" "0x0879" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-904F" :interface "USB" :usbid "0x04b8" "0x0879" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-905A" :interface "USB" :usbid "0x04b8" "0x089b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-905F" :interface "USB" :usbid "0x04b8" "0x089a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-906F" :interface "USB" :usbid "0x04b8" "0x08b4" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-907F" :interface "USB" :usbid "0x04b8" "0x08c6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-976A3" :interface "USB" :usbid "0x04b8" "0x08b3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-977A3" :interface "USB" :usbid "0x04b8" "0x08c5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ES-300C" :interface "SCSI parallel" :status :good :comment "overseas version of the GT-6000" :model "ES-300GS" :interface "SCSI" :status :good :model "ES-600C" :interface "parallel" :status :good :comment "overseas version of the GT-5400" :model "ES-800C" :interface "SCSI" :status :good :comment "overseas version of the GT-8000" :model "ES-1000C" :status :unsupported :comment "overseas version of the GT-8500" :model "ES-1200C" :interface "parallel" :status :good :comment "overseas version of the GT-9000" :model "ES-2000" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0107" :status :complete :comment "IEEE1394 untested" :model "ES-2200" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010e" :status :complete :comment "IEEE1394 untested" :model "ES-6000" ; product spec (JP) :interface "SCSI" :status :good :model "ES-6000H" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-6000HS" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-7000H" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0126" :status :good :comment "network interface probably supported
IEEE1394 untested" :model "ES-8000" :interface "SCSI" :status :untested :model "ES-8500" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0109" :status :good :comment "IEEE1394 untested" :model "ES-9000H" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-10000G" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0129" :status :good :comment "network interface probably supported
IEEE1394 untested" :model "ES-D200" :interface "USB" :usbid "0x04b8" "0x0137" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "ES-D350" :interface "USB" :usbid "0x04b8" "0x0144" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "ES-D400" :interface "USB" :usbid "0x04b8" "0x0136" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "ES-G11000" :interface "USB" :usbid "0x04b8" "0x014b" :status :good :model "ES-H300" :interface "USB" :usbid "0x04b8" "0x012b" :status :good :comment "network interface probably supported" :model "ES-H7200" :interface "USB Ethernet" :usbid "0x04b8" "0x0138" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package" :model "Expression 636" :interface "SCSI" :status :complete :comment "overseas version of the GT-9500" :model "Expression 800" ; command spec :interface "SCSI" :scsi "EPSON" "Expression800" "processor" :status :complete :comment "overseas version of the GT-9600" :model "Expression 836XL" ; command spec :interface "SCSI" :status :untested :comment "overseas version of the ES-8000" :model "Expression 1600" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0107" :status :complete :comment "IEEE1394 untested
overseas version of the ES-2000" :model "Expression 1640XL" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0109" :status :good :comment "IEEE1394 untested
overseas version of the ES-8500" :model "Expression 1680" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x010e" :status :complete :comment "IEEE1394 untested
overseas version of the ES-2200" :model "Expression 1680 Pro" :interface "SCSI USB" :status :untested :comment "IEEE1394 option" :model "Expression 1680XL Pro" :interface "SCSI USB" :status :untested :model "Expression 10000XL" ; command spec :interface "USB" :usbid "0x04b8" "0x0129" :status :good :comment "network interface probably supported
IEEE1394 untested
overseas version of the ES-10000G" :model "Expression 10000XL Graphic Arts" :interface "USB IEEE1394" :status :untested :comment "network interface probably supported" :model "Expression 10000XL Photo" :interface "USB IEEE1394" :status :untested :comment "network interface probably supported" :model "Expression 11000XL" :interface "USB" :usbid "0x04b8" "0x014b" :status :good :comment "overseas version of the ES-G11000" :model "F-3200" ; product spec (JP) :interface "USB IEEE1394" :usbid "0x04b8" "0x080a" :status :unsupported :comment "Film scanner" :model "F-3200 Photo" :interface "USB IEEE1394" :status :unsupported :model "FilmScan 200" :interface "SCSI" :status :minimal :comment "missing documentation" :model "GT-1500" :interface "USB" :usbid "0x04b8" "0x0133" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-2200" :interface "USB" :usbid "0x04b8" "0x0102" :status :unsupported :model "GT-2500" :interface "USB" :usbid "0x04b8" "0x012b" :status :good :comment "network interface probably supported
overseas version of the ES-H300" :model "GT-4000" :status :untested :model "GT-5000" :interface "parallel SCSI" :status :good :model "GT-5400" :interface "parallel" :status :good :model "GT-5500" :interface "SCSI" :scsi "EPSON" "SCANNER GT-5500" "processor" :status :good :model "GT-6000" :interface "SCSI Parport" :status :good :model "GT-6500" :interface "parallel" :status :good :comment "overseas version of the GT-5400" :model "GT-6600U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0103" :status :complete :model "GT-6700U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010c" :status :complete :model "GT-7000S" :interface "SCSI" :scsi "EPSON" "SCANNER GT-7000" "processor" :status :complete :model "GT-7000U" :interface "USB" :usbid "0x04b8" "0x0101" :status :complete :model "GT-7200U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-7300U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-7400U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0120" :status :unsupported :comment "supported by the snapscan backend" :model "GT-7600S" ; product spec (JP) :interface "SCSI" :status :complete :comment "SCSI version of the GT-7600U" :model "GT-7600U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "USB version of the GT-7600S" :model "GT-7600UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "GT-7600U with TPU option bundled" :model "GT-7700U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010b" :status :complete :model "GT-8000" :interface "SCSI" :status :good :model "GT-8200U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0110" :status :complete :model "GT-8200UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0110" :status :good :model "GT-8300UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011e" :status :complete :model "GT-8400UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :model "GT-8500" :status :untested :model "GT-8700" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :complete :model "GT-8700F" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :good :comment "GT-8700U with TPU option bundled" :model "GT-9000" :interface "parallel" :status :good :model "GT-9300UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011b" :status :complete :model "GT-9400UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0116" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-9500" :interface "SCSI" :status :complete :model "GT-9600" :interface "SCSI" :status :complete :model "GT-9700F" ; product spec (JP) :interface "USB IEEE1394" :scsi "EPSON" "GT-9700" "processor" :usbid "0x04b8" "0x0112" :status :complete :model "GT-9800F" ; product spec (JP) :interface "USB IEEE1394" :scsi "EPSON" "GT-9800" "processor" :usbid "0x04b8" "0x011c" :status :complete :model "GT-10000" :interface "SCSI" :status :good :comment "overseas version of the ES-6000" :model "GT-10000+" ; command spec :interface "SCSI" :status :good :comment "IEEE1394 untested
overseas version of the ES-6000H" :model "GT-12000" :interface "SCSI" :status :untested :comment "overseas version of the ES-8000" :model "GT-15000" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0126" :status :good :comment "IEEE1394 untested
overseas version of the ES-7000H" :model "GT-20000" :interface "USB Ethernet" :usbid "0x04b8" "0x0138" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the ES-H7200" :model "GT-30000" ; command spec :interface "SCSI" :status :good :comment "IEEE1394 untested
overseas version of the ES-9000H" :model "GT-D1000" :interface "USB" :usbid "0x04b8" "0x0133" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F500" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F520" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F550" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F570" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F600" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0118" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F650" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F670" :interface "USB" :usbid "0x04b8" "0x012e" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F700" :interface "USB" :usbid "0x04b8" "0x012f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F720" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F730" :interface "USB" :usbid "0x04b8" "0x0142" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-F740" :interface "USB" :usbid "0x04b8" "0x014a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S50" :interface "USB" :usbid "0x04b8" "0x0137" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S55" :interface "USB" :usbid "0x04b8" "0x0143" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S80" :interface "USB" :usbid "0x04b8" "0x0136" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S85" :interface "USB" :usbid "0x04b8" "0x0144" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S600" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S620" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S630" :interface "USB" :usbid "0x04b8" "0x0142" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S640" :interface "USB" :usbid "0x04b8" "0x014a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-S650" :interface "USB" :usbid "0x04b8" "0x013d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-X700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0128" :status :complete :comment "IEEE1394 untested" :model "GT-X750" :interface "USB" :usbid "0x04b8" "0x0119" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-X770" :interface "USB" :usbid "0x04b8" "0x0130" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-X800" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x012a" :status :complete :comment "film area guide mode not supported
IEEE1394 untested" :model "GT-X820" :interface "USB" :usbid "0x04b8" "0x013a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-X830" :interface "USB" :usbid "0x04b8" "0x0153" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-X900" :interface "USB" :scsi "EPSON" "GT-X900" "processor" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested" :model "GT-X970" :interface "USB" :usbid "0x04b8" "0x0135" :status :good :comment "IEEE1394 untested" :model "GT-X980" :interface "USB" :usbid "0x04b8" "0x0151" :status :good :model "K200 Series" :interface "USB" :usbid "0x04b8" "0x0871" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "K300 Series" :interface "USB" :usbid "0x04b8" "0x0872" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "L200 Series" :interface "USB" :usbid "0x04b8" "0x0873" :status :complete :comment "all-in-one" :model "L210 Series" :interface "USB" :usbid "0x04b8" "0x08a1" :status :complete :comment "all-in-one" :model "L350" :interface "USB" :usbid "0x04b8" "0x08a1" :status :complete :comment "all-in-one" :model "L351" :interface "USB" :usbid "0x04b8" "0x08a1" :status :complete :comment "all-in-one" :model "L355" :interface "USB" :usbid "0x04b8" "0x08a8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "L358" :interface "USB" :usbid "0x04b8" "0x08a8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "L550 Series" :interface "USB" :usbid "0x04b8" "0x08a9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "L850 Series" :interface "USB" :usbid "0x04b8" "0x08ca" :status :complete :comment "all-in-one" :model "LP-7900CS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9000CCH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9000CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9000CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9500CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9500CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9500CH2" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9800CCH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9800CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9800CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-A500" :interface "USB Network" :usbid "0x04b8" "0x0815" :status :good :comment "network interface supported
business all-in-one" :model "LP-M5000" :interface "USB" :usbid "0x04b8" "0x0843" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M5300 Series" :interface "USB" :usbid "0x04b8" "0x0894" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M5500" :interface "USB" :usbid "0x04b8" "0x0817" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M5500F" :interface "USB" :usbid "0x04b8" "0x0817" :status :good :comment "network interface probably supported
business all-in-one
LP-M5500 with the fax option bundled" :model "LP-M5600" :interface "USB" :usbid "0x04b8" "0x0833" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M6000" :interface "USB" :usbid "0x04b8" "0x0834" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M8040" :interface "USB" :usbid "0x04b8" "0x08ad" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M8040A" :interface "USB" :usbid "0x04b8" "0x08ad" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M8040F" :interface "USB" :usbid "0x04b8" "0x08ad" :status :good :comment "network interface probably supported
business all-in-one" :model "M200 Series" :interface "USB" :usbid "0x04b8" "0x08aa" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME 200" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "ME 300" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "ME 320 Series" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "ME 330 Series" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "ME 340 Series" :interface "USB" :usbid "0x04b8" "0x0883" :status :complete :comment "all-in-one" :model "ME OFFICE 510" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "ME OFFICE 520 Series" :interface "USB" :usbid "0x04b8" "0x0865" :status :complete :comment "all-in-one" :model "ME OFFICE 535" :interface "USB" :usbid "0x04b8" "0x0881" :status :complete :comment "all-in-one
overseas version of the PX-404A" :model "ME OFFICE 560W Series" :interface "USB" :usbid "0x04b8" "0x0864" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 570W Series" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-434A" :model "ME Office 600F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 620F Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 650FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "ME Office 700FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "ME OFFICE 900WD Series" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "ME OFFICE 940FW Series" :interface "USB" :usbid "0x04b8" "0x0890" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 960FWD Series" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME-101" :interface "USB" :usbid "0x04b8" "0x08a0" :status :complete :comment "all-in-one" :model "ME-301" :interface "USB" :usbid "0x04b8" "0x0896" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME-303" :interface "USB" :usbid "0x04b8" "0x0897" :status :complete :comment "all-in-one
overseas version of the PX-405A" :model "ME-401" :interface "USB" :usbid "0x04b8" "0x0898" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" :model "PM-A700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0814" :status :good :comment "all-in-one" :model "PM-A750" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one" :model "PM-A820" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one" :model "PM-A840" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one" :model "PM-A840S" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "network interface probably supported
all-in-one" :model "PM-A850" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0806" :status :good :comment "all-in-one" :model "PM-A870" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one" :model "PM-A890" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one" :model "PM-A900" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0810" :status :good :comment "all-in-one" :model "PM-A920" :interface "USB" :usbid "0x04b8" "0x082a" :status :good :comment "all-in-one" :model "PM-A940" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one" :model "PM-A950" :interface "USB" :usbid "0x04b8" "0x081d" :status :good :comment "all-in-one" :model "PM-A970" :interface "USB" :usbid "0x04b8" "0x0828" :status :good :comment "all-in-one" :model "PM-T960" :interface "USB" :usbid "0x04b8" "0x0836" :status :good :comment "all-in-one" :model "PM-T990" :interface "USB" :usbid "0x04b8" "0x0829" :status :good :comment "all-in-one
PM-A970 with network interface" :model "PX-045A" :interface "USB" :usbid "0x04b8" "0x0895" :status :complete :comment "all-in-one" :model "PX-046A" :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-047A" :interface "USB" :usbid "0x04b8" "0x08c0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-1600F" :interface "USB" :usbid "0x04b8" "0x0869" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-1700F" :interface "USB" :usbid "0x04b8" "0x087c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-401A" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one" :model "PX-402A" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one" :model "PX-403A" :interface "USB" :usbid "0x04b8" "0x087f" :status :complete :comment "all-in-one" :model "PX-404A" :interface "USB" :usbid "0x04b8" "0x0881" :status :complete :comment "all-in-one" :model "PX-405A" :interface "USB" :usbid "0x04b8" "0x0897" :status :complete :comment "all-in-one" :model "PX-434A" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-435A" :interface "USB" :usbid "0x04b8" "0x0898" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-436A" :interface "USB" :usbid "0x04b8" "0x08af" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-437A" :interface "USB" :usbid "0x04b8" "0x08bf" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-501A" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface probably supported
all-in-one" :model "PX-502A" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one" :model "PX-503A" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-504A" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-505F" :interface "USB" :usbid "0x04b8" "0x08a5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-535F" :interface "USB" :usbid "0x04b8" "0x08a6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-601F" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported" :model "PX-602F" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-603F" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-605F" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-673F" :interface "USB" :usbid "0x04b8" "0x086a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-675F" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-A550" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one" :model "PX-A620" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one" :model "PX-A640" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one" :model "PX-A650" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one" :model "PX-A720" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one" :model "PX-A740" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one" :model "PX-B750F" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-FA700" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one" :model "PX-M350F" :interface "USB" :usbid "0x04b8" "0x08d0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M5040F" :interface "USB" :usbid "0x04b8" "0x08b9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M5041F" :interface "USB" :usbid "0x04b8" "0x08b9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M650A" :interface "USB" :usbid "0x04b8" "0x08c3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M650F" :interface "USB" :usbid "0x04b8" "0x08c3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M740F" :interface "USB" :usbid "0x04b8" "0x08b8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M741F" :interface "USB" :usbid "0x04b8" "0x08b8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M840F" :interface "USB" :usbid "0x04b8" "0x08bd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Perfection 600" :interface "SCSI" :status :unsupported :comment "supported by the umax backend
rebadged UMAX Astra 1200S" :model "Perfection 610" ; command spec :interface "USB" :usbid "0x04b8" "0x0103" :status :basic :comment "overseas version of the GT-6600U" :model "Perfection 636S" :interface "SCSI" :scsi "EPSON" "Perfection636" "processor" :status :complete :comment "overseas version of the GT-7000S" :model "Perfection 636U" ; command spec :interface "USB" :usbid "0x04b8" "0x0101" :status :complete :comment "overseas version of the GT-7000U" :model "Perfection 640U" ; command spec :interface "USB" :usbid "0x04b8" "0x010c" :status :complete :comment "overseas version of the GT-6700U" :model "Perfection 660" :interface "USB" :usbid "0x04b8" "0x0114" :status :unsupported :comment "supported by the snapscan backend" :model "Perfection 1200S" ; command spec :interface "SCSI" :scsi "EPSON" "Perfection1200" "processor" :status :complete :comment "overseas version of the GT-7600S" :model "Perfection 1200U" ; command spec :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "overseas version of the GT-7600U" :model "Perfection 1200U PHOTO" :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "Perfection 1200U with TPU option bundled
overseas version of the GT-7600UF" :model "Perfection 1240U" ; command spec :interface "USB" :usbid "0x04b8" "0x010b" :status :complete :comment "overseas version of the GT-7700U" :model "Perfection 1250" :interface "USB" :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 1250 PHOTO" :interface "USB" :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 1260" :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 1260 PHOTO" :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 1270" :interface "USB" :usbid "0x04b8" "0x0120" :status :unsupported :comment "supported by the snapscan backend
overseas version of the GT-7400" :model "Perfection 1600" :interface "SCSI" :status :unsupported :model "Perfection 1640SU" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :complete :comment "overseas version of the GT-8700" :model "Perfection 1640SU PHOTO" :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :good :comment "overseas version of the GT-8700F" :model "Perfection 1650" ; command spec :interface "USB" :usbid "0x04b8" "0x0110" :status :complete :comment "overseas version of the GT-8200U" :model "Perfection 1650 PHOTO" :interface "USB" :usbid "0x04b8" "0x0110" :status :good :comment "overseas version of the GT-8200UF" :model "Perfection 1660 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x011e" :status :complete :comment "overseas version of the GT-8300UF" :model "Perfection 1670" :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :comment "supported by the snapscan backend" :model "Perfection 1670 PHOTO" :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :comment "supported by the snapscan backend
overseas version of the GT-8400UF" :model "Perfection 2400 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x011b" :status :complete :comment "overseas version of the GT-9300UF" :model "Perfection 2450 PHOTO" ; command spec :interface "USB IEEE1394" :scsi "EPSON" "GT-9700" "processor" :usbid "0x04b8" "0x0112" :status :complete :comment "overseas version of the GT-9700F" :model "Perfection 2480 PHOTO" :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 2580 PHOTO" :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 3170 PHOTO" :interface "USB" :usbid "0x04b8" "0x0116" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 3200 PHOTO" ; command spec :interface "USB IEEE1394" :scsi "EPSON" "GT-9800" "processor" :usbid "0x04b8" "0x011c" :status :complete :comment "overseas version of the GT-9800F" :model "Perfection 3490 PHOTO" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 3590 PHOTO" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 4180 PHOTO" :interface "USB" :usbid "0x04b8" "0x0118" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 4490 PHOTO" :interface "USB" :usbid "0x04b8" "0x0119" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection 4870 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x0128" :status :complete :comment "IEEE1394 untested
overseas version of the GT-X700" :model "Perfection 4990 PHOTO" :interface "USB" :usbid "0x04b8" "0x012a" :status :good :comment "film area guide mode not supported
IEEE1394 untested
overseas version of the GT-X800" :model "Perfection 4990 Pro" :interface "USB IEEE1394" :status :untested :comment "seems to be a 4990 PHOTO with additional software" :model "Perfection V10" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V19" :interface "USB" :usbid "0x04b8" "0x013c" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V30" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V33" :interface "USB" :usbid "0x04b8" "0x0142" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V37" :interface "USB" :usbid "0x04b8" "0x014a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V39" :interface "USB" :usbid "0x04b8" "0x013d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V100 Photo" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V200 Photo" :interface "USB" :usbid "0x04b8" "0x012e" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V300 Photo" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V330 Photo" :interface "USB" :usbid "0x04b8" "0x0142" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V370 Photo" :interface "USB" :usbid "0x04b8" "0x014a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V350 Photo" :interface "USB" :usbid "0x04b8" "0x012f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V500 Photo" :interface "USB" :usbid "0x04b8" "0x0130" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V550 Photo" :interface "USB" :usbid "0x04b8" "0x013b" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V600 Photo" :interface "USB" :usbid "0x04b8" "0x013a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Perfection V700 Photo" :interface "USB" :scsi "EPSON" "GT-X900" "processor" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested
overseas version of the GT-X900" :model "Perfection V750 Photo" :interface "USB" :scsi "EPSON" "GT-X900" "processor" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested
overseas version of the GT-X900" :model "Perfection V800 Photo" :interface "USB" :usbid "0x04b8" "0x0151" :status :good :model "Perfection V850 Pro" :interface "USB" :usbid "0x04b8" "0x0151" :status :good :comment "overseas version of the GT-X980" :model "Stylus CX1500" ; Australia :interface "USB" :usbid "0x04b8" "0x080c" :status :unsupported :comment "supported by the snapscan backend
all-in-one" :model "Stylus CX2800" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "Stylus CX2900" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "Stylus CX3100" :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one
overseas version of the CC-570L" :model "Stylus CX3200" :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one
overseas version of the CC-570L" :model "Stylus CX3500" ; Australia :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one
overseas version of the PX-A550" :model "Stylus CX3600" ; UK :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one
overseas version of the PX-A550" :model "Stylus CX3650" ; France :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one" :model "Stylus CX3700" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus CX3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus CX3810" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus CX3900" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one
overseas version of the PX-A620" :model "Stylus CX4100" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus CX4200" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus CX4300" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus CX4400" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus CX4500" :interface "USB" :usbid "0x04b8" "0x080d" :status :good :comment "all-in-one" :model "Stylus CX4600" :interface "USB" :usbid "0x04b8" "0x080d" :status :good :comment "all-in-one" :model "Stylus CX4700" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus CX4800" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus CX4900" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus CX5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus CX5100" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one
overseas version of the CC-600PX" :model "Stylus CX5200" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one
overseas version of the CC-600PX" :model "Stylus CX5300" :interface "USB" :usbid "0x04b8" "0x0808" :status :good :comment "all-in-one" :model "Stylus CX5400" :interface "USB" :usbid "0x04b8" "0x0808" :status :good :comment "all-in-one" :model "Stylus CX5500" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus CX5600" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus CX5700F" :interface "USB" :usbid "0x04b8" "0x0821" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX5800F" :interface "USB" :usbid "0x04b8" "0x0821" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX5900" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus CX6000" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus CX6300" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :comment "all-in-one
mistakenly thinks its a PX-A650" :model "Stylus CX6400" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :comment "all-in-one
mistakenly thinks its a PX-A650" :model "Stylus CX6500" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :comment "all-in-one" :model "Stylus CX6600" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :comment "all-in-one" :model "Stylus CX6900F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX7000F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX7300" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus CX7400" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus CX7700" :interface "USB" :usbid "0x04b8" "0x081f" :status :good :comment "all-in-one" :model "Stylus CX7800" :interface "USB" :usbid "0x04b8" "0x081f" :status :good :comment "all-in-one" :model "Stylus CX8300" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus CX8400" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus CX9300F" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus CX9400Fax" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus DX3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus DX3850" :interface "USB" :status :good :comment "all-in-one" :model "Stylus DX4000" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one
overseas version of the PX-A620" :model "Stylus DX4200" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus DX4400" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus DX4800" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus DX4850" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
DX4800 + card reader" :model "Stylus DX5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus DX6000" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus DX7000F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus DX7400" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus DX8400" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus DX9400F" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus Office BX300F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX305F" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX305FW" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX305FW Plus" :interface "USB" :usbid "0x04b8" "0x0870" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX310FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "Stylus Office BX320FW Series" :interface "USB" :usbid "0x04b8" "0x085f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX535WD" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" :model "Stylus Office BX630FW Series" :interface "USB" :usbid "0x04b8" "0x0890" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX525WD" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "Stylus Office BX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "Stylus Office BX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" :model "Stylus Office BX625FWD" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX635FWD" :interface "USB" :usbid "0x04b8" "0x088f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX925FWD" :interface "USB" :usbid "0x04b8" "0x086a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-673F" :model "Stylus Office BX935FWD" :interface "USB" :usbid "0x04b8" "0x0892" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX300F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX320F Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX510FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "Stylus Office TX525FW" :interface "USB" :usbid "0x04b8" "0x085f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "Stylus Office TX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" :model "Stylus Office TX620FWD Series" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Photo PX650 Series" :interface "USB" :usbid "0x04b8" "0x0850" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-702A" :model "Stylus Photo PX660 Series" :interface "USB" :usbid "0x04b8" "0x0862" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-703A" :model "Stylus Photo PX700W" :interface "USB Network" :usbid "0x04b8" "0x0846" :status :good :comment "network interface supported
all-in-one
overseas version of the EP-801A" :model "Stylus Photo PX710W Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" :model "Stylus Photo PX720WD Series" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" :model "Stylus Photo PX730WD Series" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Stylus Photo PX800FW" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-901A" :model "Stylus Photo PX810FW Series" :interface "USB" :usbid "0x04b8" "0x0853" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-902A" :model "Stylus Photo PX820FWD Series" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" :model "Stylus Photo PX830FWD Series" :interface "USB" :usbid "0x04b8" "0x0879" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-904F" :model "Stylus Photo RX420" :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX425" ; France :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX430" ; Australia :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX500" :interface "USB" :usbid "0x04b8" "0x0807" :status :good :comment "all-in-one" :model "Stylus Photo RX510" :interface "USB" :usbid "0x04b8" "0x0807" :status :good :comment "all-in-one" :model "Stylus Photo RX520" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one
overseas version of the PM-A750" :model "Stylus Photo RX530" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one
overseas version of the PM-A750" :model "Stylus Photo RX560" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX585" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX580" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX595" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX590" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX600" :interface "USB" :usbid "0x04b8" "0x0806" :status :good :comment "all-in-one
overseas version of the PM-A850" :model "Stylus Photo RX610" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX620" :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one
overseas version of the PM-A870" :model "Stylus Photo RX630" :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one
overseas version of the PM-A870" :model "Stylus Photo RX640" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one
overseas version of the PM-A890" :model "Stylus Photo RX650" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one
overseas version of the PM-A890" :model "Stylus Photo RX680" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX685" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX690" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX700" :interface "USB" :usbid "0x04b8" "0x0810" :status :good :comment "all-in-one
overseas version of the PM-A900" :model "Stylus Photo TX650 Series" :interface "USB" :usbid "0x04b8" "0x0850" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-702A" :model "Stylus Photo TX700W" :interface "USB" :usbid "0x04b8" "0x0846" :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-801A" :model "Stylus Photo TX710W Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" :model "Stylus Photo TX720WD Series" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" :model "Stylus Photo TX730WD Series" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Stylus Photo TX800FW" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-901A" :model "Stylus Photo TX820FWD Series" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" :model "Stylus NX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus NX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus NX125" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "Stylus NX127" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "Stylus NX130 Series" :interface "USB" :usbid "0x04b8" "0x0883" :status :complete :comment "all-in-one" :model "Stylus NX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus NX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus NX220 Series" :interface "USB" :usbid "0x04b8" "0x0865" :status :complete :comment "all-in-one" :model "Stylus NX230 Series" :interface "USB" :usbid "0x04b8" "0x0885" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX300 Series" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX330 Series" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-501A" :model "Stylus NX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface probably supported
all-in-one" :model "Stylus NX420 Series" :interface "USB" :usbid "0x04b8" "0x0864" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX430W Series" :interface "USB" :usbid "0x04b8" "0x0884" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX510 Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "Stylus NX530 Series" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-504A" :model "Stylus NX625" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "Stylus NX635" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" :model "Stylus SX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus SX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus SX125" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "Stylus SX130 Series" :interface "USB" :usbid "0x04b8" "0x0883" :status :complete :comment "all-in-one" :model "Stylus SX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus SX205" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus SX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus SX218" :interface "USB" :usbid "0x04b8" "0x0865" :status :complete :comment "all-in-one" :model "Stylus SX230 Series" :interface "USB" :usbid "0x04b8" "0x0881" :status :complete :comment "all-in-one
overseas version of the PX-404A" :model "Stylus SX235W" :interface "USB" :usbid "0x04b8" "0x0885" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus SX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-501A" :model "Stylus SX405" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "all-in-one" :model "Stylus SX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface probably supported
all-in-one" :model "Stylus SX420W Series" :interface "USB" :usbid "0x04b8" "0x0864" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus SX430W Series" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus SX440W Series" :interface "USB" :usbid "0x04b8" "0x0884" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus SX510W Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "Stylus SX525WD" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "Stylus SX535WD" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" :model "Stylus SX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "Stylus SX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" :model "Stylus SX620FW Series" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Scan 2000" :interface "USB" :usbid "0x04b8" "0x0105" :status :untested :comment "apparently mostly the same as the Stylus Scan 2500" :model "Stylus Scan 2500" :interface "USB" :usbid "0x04b8" "0x0106" :status :untested :comment "scanner is apparently a GT-7000" :model "Stylus TX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus TX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus TX120 Series" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "Stylus TX130 Series" :interface "USB" :usbid "0x04b8" "0x0883" :status :complete :comment "all-in-one" :model "Stylus TX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX203" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX209" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus TX220 Series" :interface "USB" :usbid "0x04b8" "0x0865" :status :complete :comment "all-in-one" :model "Stylus TX230W Series" :interface "USB" :usbid "0x04b8" "0x0885" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus TX235" :interface "USB" :usbid "0x04b8" "0x0881" :status :complete :comment "all-in-one
overseas version of the PX-404A" :model "Stylus TX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-501A" :model "Stylus TX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface probably supported
all-in-one" :model "Stylus TX420W Series" :interface "USB" :usbid "0x04b8" "0x0864" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus TX430W Series" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus TX435W" :interface "USB" :usbid "0x04b8" "0x0884" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus TX550W Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "Stylus TX560WD Series" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "WF-2510 Series" :interface "USB" :usbid "0x04b8" "0x08a5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-505F" :model "WF-2520 Series" :interface "USB" :usbid "0x04b8" "0x08a6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" :model "WF-2530 Series" :interface "USB" :usbid "0x04b8" "0x08a6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" :model "WF-2540 Series" :interface "USB" :usbid "0x04b8" "0x08a6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" :model "WF-2630 Series" :interface "USB" :usbid "0x04b8" "0x08c4" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-2650 Series" :interface "USB" :usbid "0x04b8" "0x08c3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-2660 Series" :interface "USB" :usbid "0x04b8" "0x08c3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-3520 Series" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-605F" :model "WF-3530 Series" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-675F" :model "WF-3540 Series" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-3620 Series" :interface "USB" :usbid "0x04b8" "0x08b8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M740F" :model "WF-3640 Series" :interface "USB" :usbid "0x04b8" "0x08b8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M741F" :model "WF-4630 Series" :interface "USB" :usbid "0x04b8" "0x08be" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-4640 Series" :interface "USB" :usbid "0x04b8" "0x08be" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-5620 Series" :interface "USB" :usbid "0x04b8" "0x08bd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M840F" :model "WF-5690 Series" :interface "USB" :usbid "0x04b8" "0x08bd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-7510 Series" :interface "USB" :usbid "0x04b8" "0x0869" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-1600F" :model "WF-7520 Series" :interface "USB" :usbid "0x04b8" "0x087c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-1700F" :model "WF-7610 Series" :interface "USB" :usbid "0x04b8" "0x08b9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M5040F" :model "WF-7620 Series" :interface "USB" :usbid "0x04b8" "0x08b9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M5041F" :model "WF-M1560 Series" :interface "USB" :usbid "0x04b8" "0x08ab" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-M5690 Series" :interface "USB" :usbid "0x04b8" "0x08d0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M350F" :model "WF-R4640 Series" :interface "USB" :usbid "0x04b8" "0x08cd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-R5690 Series" :interface "USB" :usbid "0x04b8" "0x08cd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WP-4511" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4515" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WP-4521" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4525" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4530 Series" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4540 Series" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4590 Series" :interface "USB" :usbid "0x04b8" "0x087e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 310 Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "WorkForce 320 Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
some models in the series have a built-in network interface
all-in-one" :model "WorkForce 435" :interface "USB" :usbid "0x04b8" "0x0870" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 500" :interface "USB" :usbid "0x04b8" "0x084c" :status :good :comment "all-in-one" :model "WorkForce 520 Series" :interface "USB" :usbid "0x04b8" "0x085f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 545" :interface "USB" :usbid "0x04b8" "0x0890" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 600" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "WorkForce 610 Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" :model "WorkForce 625" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "WorkForce 630 Series" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 645" :interface "USB" :usbid "0x04b8" "0x088f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 840 Series" :interface "USB" :usbid "0x04b8" "0x086a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-673F" :model "WorkForce 845" :interface "USB" :usbid "0x04b8" "0x0892" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce K301" :interface "USB" :usbid "0x04b8" "0x0872" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-100 Series" :interface "USB" :usbid "0x04b8" "0x0895" :status :complete :comment "all-in-one
overseas version of the PX-045A" :model "XP-200 Series" :interface "USB" :usbid "0x04b8" "0x0896" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-211" :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-046A" :model "XP-212" :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-046A" :model "XP-215" :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-046A" :model "XP-225" :interface "USB" :usbid "0x04b8" "0x08c0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-047A" :model "XP-300 Series" :interface "USB" :usbid "0x04b8" "0x0898" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" :model "XP-310 Series" :interface "USB" :usbid "0x04b8" "0x08af" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-436A" :model "XP-320 Series" :interface "USB" :usbid "0x04b8" "0x08bf" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-437A" :model "XP-400 Series" :interface "USB" :usbid "0x04b8" "0x0898" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" :model "XP-410 Series" :interface "USB" :usbid "0x04b8" "0x08b0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-420 Series" :interface "USB" :usbid "0x04b8" "0x08c1" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-600 Series" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-775A" :model "XP-510 Series" :interface "USB" :usbid "0x04b8" "0x08b7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-706A" :model "XP-520 Series" :interface "USB" :usbid "0x04b8" "0x08c8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-777A" :model "XP-610 Series" :interface "USB" :usbid "0x04b8" "0x08b6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-776AB/EP-776AW" :model "XP-620 Series" :interface "USB" :usbid "0x04b8" "0x08c8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-777A" :model "XP-700 Series" :interface "USB" :usbid "0x04b8" "0x089d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-710 Series" :interface "USB" :usbid "0x04b8" "0x08b5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-806AB/EP-806AR/EP-806AW" :model "XP-720 Series" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-807AB/EP-807AR/EP-807AW" :model "XP-750 Series" :interface "USB" :usbid "0x04b8" "0x089c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-805A/EP-805AR/EP-805AW" :model "XP-760 Series" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-807AB/EP-807AR/EP-807AW" :model "XP-800 Series" :interface "USB" :usbid "0x04b8" "0x089b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-905A" :model "XP-810 Series" :interface "USB" :usbid "0x04b8" "0x08b4" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-906F" :model "XP-820 Series" :interface "USB" :usbid "0x04b8" "0x08c6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-907F" :model "XP-850 Series" :interface "USB" :usbid "0x04b8" "0x089a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-905F" :model "XP-860 Series" :interface "USB" :usbid "0x04b8" "0x08c6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-907F" :model "XP-950 Series" :interface "USB" :usbid "0x04b8" "0x08b3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-976A3" :model "Epson ME 350" :interface "USB" :usbid "0x04b8" "0x088d" :status :good :model "WP-M4525, WP-M4521, PX-K751F, WP-M4595" :interface "USB" :usbid "0x04b8" "0x08a7" :status :good sane-backends-1.0.27/doc/descriptions/qcam.desc0000664000175000017500000000121212112021330016233 00000000000000:backend "qcam" ; name of backend :version "unmaintained" ; version of backend ; :url "" ; backend's homepage :manpage "sane-qcam" :devicetype :vidcam :mfg "Connectix" ; name a manufacturer ;:url "http://www.connectix.com/" ; doesn't exist any longer? :model "Color QuickCam" ; name models for above-specified mfg. :interface "Parport" :status :good :comment "Requires root privileges." :model "Greyscale QuickCam" ; name models for above-specified mfg. :interface "Parport" :status :minimal :comment "Requires root privileges. Partly working." sane-backends-1.0.27/doc/descriptions/nec.desc0000664000175000017500000000070013063340150016072 00000000000000:backend "nec" ; name of backend :version "0.12 (unmaintained)" ; version of backend :url "http://www5a.biglobe.ne.jp/~saetaka/" ; backend's homepage :manpage "sane-nec" :devicetype :scanner :mfg "NEC" ; name a manufacturer :url "http://www.nevt.co.jp/" :model "PC-IN500/4C" ; name models for above-specified mfg. :interface "SCSI" :comment "PC-IN500/4C was sold only in JAPAN" :status :good sane-backends-1.0.27/doc/descriptions/as6e.desc0000664000175000017500000000243713063340150016174 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "as6e" ; name of backend :version "0.5 (unmaintained)" ; version of backend :manpage "sane-as6e" ; name of manpage (if it exists) :url "http://as6edriver.sourceforge.net/" :devicetype :scanner :mfg "Artec/Ultima" ; name a manufacturer :url "http://www.artecusa.com/" :model "AS6E" :interface "Parport" :status :basic :comment "Requires the program 'as6edriver' to run." :mfg "Trust" ; name a manufacturer :url "http://www.trust-site.com" :comment "Carefully check the model names. Trust uses similar names for completely different hardware." :model "Easy Scan 9600 Plus" :interface "Parport" :status :basic :comment "Requires the program 'as6edriver' to run." :mfg "Dexxa" ; name a manufacturer :url "http://www.dexxa.com" :model "4800" :interface "Parport" :status :basic :comment "Requires the program 'as6edriver' to run." ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/lexmark.desc0000664000175000017500000000442113072310420016771 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "lexmark" ; name of backend :version "1.0-0 (unmaintained)" ; version of backend (or "unmaintained") :manpage "sane-lexmark" ; name of manpage (if it exists) :url "http://stef.dev.free.fr/sane/lexmark" ; backend's web page :comment "This backend supports lexmark x1100 series scanners." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Lexmark" ; name a manufacturer :url "http://www.lexmark.com/" ; manufacturer's URL :model "X1110" :interface "USB" :usbid "0x043d" "0x007c" :status :untested :model "X1130" :interface "USB" :usbid "0x043d" "0x007c" :status :good :comment "Supports 75, 150, 300, 600 dpi" :model "X1140" :interface "USB" :usbid "0x043d" "0x007c" :status :untested :model "X1150" :interface "USB" :usbid "0x043d" "0x007c" :status :good :comment "Supports 75, 150, 300, 600 dpi" :model "X1170" :interface "USB" :usbid "0x043d" "0x007c" :status :good :comment "Supports 75, 150, 300, 600 dpi" :model "X1180" :interface "USB" :usbid "0x043d" "0x007c" :status :good :model "X1185" :interface "USB" :usbid "0x043d" "0x007c" :status :good :comment "Tested with xscanimage. Supports 75, 150, 300, 600, 1200(600x1200) dpi resolutions. Does grayscale or colour scans in the following sizes: wallet, 3x5, 4x6, 5x7, 8x10, letter." :model "X1195" :interface "USB" :usbid "0x043d" "0x007c" :status :untested :model "X74" :interface "USB" :usbid "0x043d" "0x0060" :status :good :comment "Supports 75, 150, 300, 600 dpi" :model "X12xx" :interface "USB" :usbid "0x043d" "0x007d" :status :good :comment "USB1.1 is OK, USB2.0 needs testing" :mfg "Dell" ; name a manufacturer :model "A920" :interface "USB" :usbid "0x413c" "0x5105" :status :good :comment "Relabelled X11xx model" sane-backends-1.0.27/doc/descriptions/hpljm1005.desc0000664000175000017500000000165213063340150016754 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "hpljm1005" :version "0 (unmaintained)" :manpage "sane-hpljm1005" :devicetype :scanner :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "LaserJet M1005 MFP" :interface "USB" :usbid "0x03f0" "0x3b17" :status :good :comment "grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI" :model "LaserJet M1120 MFP" :interface "USB" :usbid "0x03f0" "0x5617" :status :good :comment "grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI" :model "LaserJet M1120n MFP" :interface "USB" :usbid "0x03f0" "0x5717" :status :good :comment "grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI" sane-backends-1.0.27/doc/descriptions/bh.desc0000664000175000017500000000320413063340150015720 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "bh" ; name of backend :version "1.0-4 (unmaintained)" ; version of backend :manpage "sane-bh" ; name of manpage (if it exists) :url "http://www.martoneconsulting.com/sane-bh.html" ; backend's web page :comment "Supports Copiscan II scanners with Remote SCSI Controller (RSC) interface" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Bell and Howell" ; name a manufacturer :url "http://www.bhscanners.com/" :model "COPISCAN II 6338" :interface "SCSI" :status :good :comment "Duplex Scanner with ACE - development model" :model "COPISCAN II 2135" :status :untested :interface "SCSI" :comment "Simplex Scanner" :model "COPISCAN II 2137(A)" :interface "SCSI" :status :good :comment "Simplex Scanner (with ACE) - limited testing" :model "COPISCAN II 2138A" :status :untested :interface "SCSI" :comment "Simplex Scanner with ACE" :model "COPISCAN II 3238" :status :untested :interface "SCSI" :comment "Simplex Scanner" :model "COPISCAN II 3338(A)" :status :untested :interface "SCSI" :comment "Simplex Scanner (with ACE)" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/hp5590.desc0000664000175000017500000000321312112021330016247 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "hp5590" :version "1.0.5" :manpage "sane-hp5590" :devicetype :scanner :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "ScanJet 4500C" :interface "USB" :usbid "0x03f0" "0x1205" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives" :model "ScanJet 4570C" :interface "USB" :usbid "0x03f0" "0x1305" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives" :model "ScanJet 5500C" :interface "USB" :usbid "0x03f0" "0x1305" :status :untested :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives" :model "ScanJet 5550C" :interface "USB" :usbid "0x03f0" "0x1205" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives" :model "ScanJet 5590" :interface "USB" :usbid "0x03f0" "0x1705" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives" :model "ScanJet 7650" :interface "USB" :usbid "0x03f0" "0x1805" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives" sane-backends-1.0.27/doc/descriptions/rts8891.desc0000664000175000017500000000306213072310420016470 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "rts8891" ; name of backend :version "1.0-0 (unmaintained)" ; version of backend (or "unmaintained") :manpage "sane-rts8891" ; name of manpage (if it exists) :url "http://stef.dev.free.fr/sane/rts8891/index.html" ; backend's web page :comment "This backend supports Realtek RTS8891 ASIC bases scanners." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com.tw/" ; manufacturer's URL :model "Astra 4400" :interface "USB" :usbid "0x1606" "0x0070" :status :good :comment "Supports 75, 150, 300, 600 and 1200 dpi" :model "Astra 4450" :interface "USB" :usbid "0x1606" "0x0070" :status :untested :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "scanjet 4470c" :interface "USB" :usbid "0x03f0" "0x0805" :status :good :comment "re-branded Astra 4400" :model "scanjet 4400c" :interface "USB" :usbid "0x03f0" "0x0705" :status :good :comment "exists with 2 different sensors of which only one works" sane-backends-1.0.27/doc/descriptions/ricoh.desc0000664000175000017500000000153412112021330016425 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "ricoh" ; name of backend :version "unmaintained" ; version of backend ; :manpage "sane-ricoh" ; name of manpage (if it exists) :devicetype :scanner :mfg "Ricoh" ; name a manufacturer :url "http://www.ricoh.com/" :model "Ricoh IS50" ; name models for above-specified mfg. :interface "SCSI" :status :basic ;:comment "?" :model "Ricoh IS60" ; name models for above-specified mfg. :interface "SCSI" :status :basic ;:comment "?" sane-backends-1.0.27/doc/descriptions/stv680.desc0000664000175000017500000000361613063340150016410 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "stv680" ; name of backend :version "1.0-1 (unmaintained)" ; version of backend :manpage "sane-stv680" :url "http://gkall.hobby.nl/stv680-aiptek.html" ; backend's web page :comment "This vidcam backend is for the stv0680 chipset, See the website for more info." :devicetype :vidcam ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Aiptek" ; name a manufacturer :url "http://www.aiptek.com.tw" ; name models for above-specified mfg. :model "Aiptek Pencam" :interface "USB" :usbid "0x0553" "0x0202" :status :minimal :comment "image is OK for CIF and QCIF, VGA and QVGA untested, streaming video is a problem" :mfg "Konica" ; name a manufacturer :url "http://www.konicaminolta.com" ; name models for above-specified mfg. :model "e-mini" :interface "USB" :usbid "0x04c8" "0x0722" :status :untested :comment " " :mfg "Digital Dream" ; name a manufacturer :url "http://www.digitaldreamco.com/en/index.shtml" ; name models for above-specified mfg. :model "l' espion XS" :interface "USB" :usbid "0x1183" "0x0001" :status :untested :comment " " :mfg "Creative" ; name a manufacturer :url "http://www.creative.com/" ; name models for above-specified mfg. :model "WebCam Go Mini" :interface "USB" :usbid "0x041e" "0x4007" :status :untested :comment " " ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/gt68xx.desc0000664000175000017500000002547613063340150016516 00000000000000:backend "gt68xx" :version "1.0-84 (unmaintained)" :manpage "sane-gt68xx" :url "http://www.meier-geinitz.de/sane/gt68xx-backend/" :comment "Only the USB scanners mentioned below are supported. For other Mustek BearPaws, look at the Plustek and the MA-1509 backend." :devicetype :scanner ; ----------------------------------------------------------------------------- :mfg "Artec/Ultima" :url "http://www.artecusa.com/" :model "Ultima 2000" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Works, only product id 0x4002 is supported" :model "Ultima 2000 e+" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Works, however 12 bit mode doesn't seem to be supported" ; ----------------------------------------------------------------------------- :mfg "Boeder" :model "Sm@rtScan Slim Edition" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Artec Ultima 2000" ; ----------------------------------------------------------------------------- :mfg "Fujitsu" :url "http://www.fujitsu.com/" :model "1200CUS" :interface "USB" :usbid "0x05d8" "0x4002" :status :basic :comment "Works, but is slow. Probably a Mustek BearPaw 2400 CU clone." ; ----------------------------------------------------------------------------- :mfg "Genius" :url "http://www.genius-kye.com/" :model "ColorPage Slim 1200" ;:url "/unsupported/genius-colorpage-slim-1200.html" :interface "USB" :usbid "0x0458" "0x201e" :status :untested :comment "Untested but should work." :model "Colorpage SF600" :interface "USB" :usbid "0x0458" "0x2021" :status :basic :model "Colorpage Vivid3x" :interface "USB" :usbid "0x0458" "0x2011" :status :good :model "Colorpage Vivid3 V2" :interface "USB" :usbid "0x0458" "0x2011" :status :good :comment "Same as Colorpage Vivid3x" :model "Colorpage Vivid3xe" :interface "USB" :usbid "0x0458" "0x2017" :status :good :model "Colorpage Vivid4" :usbid "0x0458" "0x2014" :interface "USB" :status :good :model "Colorpage Vivid4x" :usbid "0x0458" "0x201b" :interface "USB" :status :good :model "Colorpage Vivid4xe" :usbid "0x0458" "0x201a" :interface "USB" :status :good :model "Colorpage Vivid 1200 X" :interface "USB" :usbid "0x0458" "0x201d" :status :good :model "Colorpage Vivid 1200 XE" :interface "USB" :usbid "0x0458" "0x201f" :status :good ; ----------------------------------------------------------------------------- :mfg "Googlegear" :model "2000" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Same as Artec Ultima 2000." ; ----------------------------------------------------------------------------- :mfg "Lexmark" :url "http://www.lexmark.com/" :model "X70" :interface "USB" :usbid "0x043d" "0x002d" :status :good :comment "Works, some resolutions fail at 16 bit" :model "X73" :interface "USB" :usbid "0x043d" "0x002d" :status :good :comment "Works, some resolutions fail at 16 bit, same as X70" ; ----------------------------------------------------------------------------- :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.com" :comment "Sold by Aldi and Tchibo." :model "MD 4394" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Product id 0x4002. If you have 0x4003, use artec_eplus48u backend." :model "MD/LT 9375" :interface "USB" :usbid "0x05d8" "0x4002" :status :untested :comment "Untested, but is reported to have the same ids as the Artec Ultima 2000. Please test." :model "MD/LT 9385" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Artec Ultima 2000" :model "LT 9452" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Mustek ScanExpress 1200 UB Plus" :model "MD 9458" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Artec Ultima 2000 (e+?)" ; ----------------------------------------------------------------------------- :mfg "Mustek" :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "BearPaw 1200 CS" :interface "USB" :usbid "0x055f" "0x021e" :status :good :model "BearPaw 1200 CU" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :model "BearPaw 1200 CU Plus" :interface "USB" :usbid "0x055f" "0x021b" :status :good :model "BearPaw 1200 CU Plus" :interface "USB" :usbid "0x055f" "0x021c" :status :good :model "BearPaw 1200 TA" :interface "USB" :usbid "0x055f" "0x021e" :status :good :comment "Transparency adapter supported" :model "BearPaw 1248 CU" :interface "USB" :usbid "0x055f" "0x021c" :status :good :comment "Seems to use the same ids as BearPaw 1200 CU Plus." :model "BearPaw 2400 CS" :interface "USB" :usbid "0x055f" "0x0218" :status :untested :comment "Probably works, reports are welcome" :model "BearPaw 2400 CS Plus" :interface "USB" :usbid "0x055f" "0x0219" :status :good :comment "Works, problems with 12/16 bit modes?" :model "BearPaw 2400 CU" :interface "USB" :usbid "0x05d8" "0x4002" :status :basic :comment "Works, but is slow" :model "BearPaw 2400 CU Plus" :interface "USB" :usbid "0x055f" "0x021d" :status :good :model "BearPaw 2400 TA" :interface "USB" :usbid "0x055f" "0x0218" :status :good :comment "Transparency adapter supported" :model "BearPaw 2400 TA Plus" :interface "USB" :usbid "0x055f" "0x0219" :status :good :comment "Transparency adapter supported" :model "BearPaw 2448 CS Plus" :interface "USB" :usbid "0x055f" "0x021a" :status :basic :comment "Slow. Same as 2448 TA Plus, but without TA." :model "BearPaw 2448 TA Plus" :interface "USB" :usbid "0x055f" "0x021a" :status :basic :comment "Slow. Transparency adapter supported. Slow. Brightness depends on resolution?" :model "Plug-n-Scan 2400 MT" :interface "USB" :usbid "0x055f" "0x0219" :status :good :comment "Works but is slow in high resolutions. Same as BearPaw 2400 TA Plus." :model "Plug-n-Scan 2400 M" :interface "USB" :usbid "0x055f" "0x0219" :status :good :comment "Works but is slow in high resolutions. Same as BearPaw 2400 CS Plus." :model "ScanExpress 1200 UB Plus" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :model "ScanExpress 1248 UB" :interface "USB" :usbid "0x055f" "0x021f" :status :complete :model "ScanExpress 2400 USB" :interface "USB" :usbid "0x05d8" "0x4002" :status :minimal :comment "Should be detected but may need some more work in the code. Testers welcome. Please contact me if you own this scanner." :model "ScanExpress A3 USB" :interface "USB" :usbid "0x055f" "0x0210" :status :basic :comment "Still some vertical stripes." :model "ScanMagic 1200 UB Plus" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Same as ScanExpress 1200 UB Plus" ; ----------------------------------------------------------------------------- :mfg "NeatReceipts" :model "Scanalizer Professional 2.5" :interface "USB" :usbid "0x07b3" "0x0412" :status :untested :comment "Similar to Plustek OpticSlim M12. Please tell us if this scanner works." :model "Mobile Scanner" :interface "USB" :usbid "0x07b3" "0x0462" :status :basic :comment "Similar to Plustek OpticSlim M12." ; ----------------------------------------------------------------------------- :mfg "Nortek" :model "MyScan 1200" :interface "USB" :usbid "0x07b3" "0x040b" :status :untested :comment "Untested. Please test. Similar to Plustek OpticPro S12?" ; ----------------------------------------------------------------------------- :mfg "Packard Bell" :model "Diamond 1200" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Mustek BearPaw 1200 (Plus)" :model "Diamond 1200 Plus" :interface "USB" :usbid "0x055f" "0x021c" :status :good :comment "Similar to Mustek BearPaw 1200 Plus" :model "Diamond 1200 Plus" :interface "USB" :usbid "0x055f" "0x021b" :status :good :comment "Similar to Mustek BearPaw 1200 Plus" :model "Diamond 2450" :interface "USB" :usbid "0x055f" "0x0219" :status :good ; ----------------------------------------------------------------------------- :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticPro 1248U" :interface "USB" :usbid "0x07b3" "0x0400" :status :good :model "OpticPro 1248U" :interface "USB" :usbid "0x07b3" "0x0401" :status :good :model "OpticPro U16B" :interface "USB" :usbid "0x07b3" "0x0402" :status :good :model "OpticPro U16B+" :interface "USB" :usbid "0x07b3" "0x0403" :status :good :model "OpticPro UT16B" :interface "USB" :usbid "0x07b3" "0x0403" :status :untested :comment "Probably works. Transparency adapter not supported yet. Please contact me if you own such a device. " :model "OpticPro S12" :interface "USB" :usbid "0x07b3" "0x040b" :status :good :comment "Product ID 0x040b only." :model "OpticPro S24" :interface "USB" :usbid "0x07b3" "0x040e" :status :good :comment "Product ID 0x040e only. Is reported to work." :model "OpticPro ST12" :interface "USB" :usbid "0x07b3" "0x040b" :status :untested :comment "Product ID 0x040b only. Needs testing. Transparency adapter completely untested. Please contact me if you own such a scanner." :model "OpticSlim 1200" :interface "USB" :usbid "0x07b3" "0x0413" :status :good :model "OpticSlim 2400" :interface "USB" :usbid "0x07b3" "0x0422" :status :good :comment "Works up to 1200 dpi." :model "OpticSlim 2400 plus" :interface "USB" :usbid "0x07b3" "0x0454" :status :good :comment "Same as OpticSlim 2400." :model "Iriscan Express 2" :interface "USB" :usbid "0x07b3" "0x045f" :status :complete :comment "Works up to 1200 dpi. Calibration with external calibration sheet supported" ; ----------------------------------------------------------------------------- :model "OpticSlim M12" :interface "USB" :usbid "0x07b3" "0x0412" :status :complete :comment "Works up to 1200 dpi. Calibration with external calibration sheet supported" ; ----------------------------------------------------------------------------- :mfg "RevScan" ;:url "" :model "19200i" :interface "USB" :usbid "0x07b3" "0x0400" :status :good :comment "Similar to Plustek OpticPro 1248U" ; ----------------------------------------------------------------------------- :mfg "Trust" :url "http://www.trust-site.com" :model "240TH Easy Webscan Gold" :interface "USB" :usbid "0x055f" "0x0218" :status :good :comment "Same as Mustek Bearpaw 2400 TA plus." :model "Compact Scan USB 19200" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Works, if you have vendor id 0x055f and product id 0x0006, use the mustek_usb backend instead, similar to Mustek ScanExpress 1200 UB (Plus)" :model "Direct WebScan 19200" :interface "USB" :usbid "0x055f" "0x021c" :status :good :comment "Same as Mustek BearPaw 1200 CU Plus (0x021c)." :model "Flat Scan USB 19200" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Artec Ultima 2000" ; ----------------------------------------------------------------------------- :mfg "Visioneer" :url "http://www.visioneer.com/" :model "OneTouch 7300" :interface "USB" :usbid "0x04a7" "0x0444" :status :good :comment "Works upto 1200 dpi and 12 bits/color." ; ----------------------------------------------------------------------------- sane-backends-1.0.27/doc/descriptions/teco3.desc0000664000175000017500000000276213063340150016354 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "teco3" ; name of backend :version "1.0-1 (unmaintained)" ; version of backend :manpage "sane-teco3" ; name of manpage (if it exists) :url "http://www.zago.net/sane/#teco3" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Relisys" :url "http://www.tecoimage.com.tw/" :model "Infinity Scorpio" :comment "sub model VM3552" :interface "SCSI" :status :good :mfg "Plustek" :model "OpticPro 2400SP" :comment "sub model VM3552" :interface "SCSI" :status :untested :mfg "PIOTECH" :url "http://www.image-land.com/" :model "Splendeur 3024" :comment "sub model VM3552" :interface "SCSI" :status :good :mfg "Trust" :model "Imagery 2400 SP" :comment "sub model VM3552" :interface "SCSI" :status :good :model "Imagery 4800 SP+" :comment "sub model VM3552" :interface "SCSI" :status :good :model "Imagery 9600 SP" :comment "sub model VM3552" :interface "SCSI" :status :untested ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/dc25.desc0000664000175000017500000000121713063340150016066 00000000000000;Kodak DC25 backend .desc file by Peter Fales :backend "dc25" ; name of backend :version "1.2 (unmaintained)" ; version of backend :manpage "sane-dc25" ; name of manpage (if it exists) :url "mailto:peter@fales-lorenz.net"; :devicetype :stillcam ; start of a list of devices.... :mfg "Kodak" ; Manufacturer :url "http://www.kodak.com/global/en/service/digCam/dc25/dc25.shtml"; :model "DC25" ; :status :complete ; untested, minimal, basic, complete :interface "Serial port" :model "DC20" ; :status :basic ; untested, minimal, basic, complete :interface "Serial port" :comment "DC-20 untested by author but reported to work" sane-backends-1.0.27/doc/descriptions/snapscan.desc0000664000175000017500000001577012775312262017164 00000000000000; $Id$ ; ; SANE Backend specification file (Matto Marjanovic's format) ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "SnapScan" ; name of backend :version "1.4" ; version of backend :manpage "sane-snapscan" ; name of manpage (if it exists) :url "http://snapscan.sourceforge.net/" ; backend's web page :comment "Supported bit depths: 24 bit (color), 48 bit (color, Epson) 8 bit (gray)" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api ;----------------------------------------------------------------------------- :mfg "AGFA" ; name a manufacturer :url "http://www.agfa.com/" :model "SnapScan" ; name models for above-specified mfg. :interface "SCSI" :status :good :model "SnapScan 300" :interface "SCSI" :status :good :model "SnapScan 310" :interface "SCSI" :status :good :model "SnapScan 600" :interface "SCSI" :status :good :comment "Optional ADF supported." :model "Arcus 1200" :interface "SCSI" :status :good :comment "Optional transparency unit supported." :model "SnapScan 1236s" :interface "SCSI" :status :good :comment "Optional ADF and transparency unit supported." :model "SnapScan 1236u" :interface "USB" :status :good :usbid "0x06bd" "0x0002" :comment "Optional ADF and transparency unit supported." :model "SnapScan 1212U" :interface "USB" :usbid "0x06bd" "0x0001" :status :good :model "SnapScan 1212U_2" :interface "USB" :usbid "0x06bd" "0x2061" :status :good :model "SnapScan e10" :interface "USB" :usbid "0x06bd" "0x2093" :status :good :model "SnapScan e20" :interface "USB" :usbid "0x06bd" "0x2091" :status :good :model "SnapScan e25" :interface "USB" :usbid "0x06bd" "0x2095" :status :good :model "SnapScan e26" :interface "USB" :usbid "0x06bd" "0x2097" :status :good :model "SnapScan e40" :interface "USB" :usbid "0x06bd" "0x208d" :status :good :model "SnapScan e42" :interface "USB" :usbid "0x06bd" "0x20ff" :status :good :model "SnapScan e50" :interface "USB" :status :good :usbid "0x06bd" "0x208f" :comment "Optional tranparency unit supported" :model "SnapScan e52" :interface "USB" :status :good :usbid "0x06bd" "0x20fd" :comment "Optional tranparency unit supported" :model "SnapScan e60" :interface "USB" :status :untested ;------------------------------------------------------------------------------ :mfg "Acer Peripherals" :comment "Company was renamed to Benq." :mfg "Vuego" :comment "Company was renamed to Benq." :mfg "Benq (Acer)" :url "http://www.benq.com" :comment "Formerly Acer Peripherals" :model "300f" :interface "SCSI" :status :good :model "310s" :interface "SCSI" :status :good :model "610s" :interface "SCSI" :status :good :model "610plus" :interface "SCSI" :status :good :model "620s" :interface "SCSI" :status :good :model "ScanWit 2720s" :interface "SCSI" :status :good :model "310U" :interface "USB" :usbid "0x04a5" "0x1a20" :status :good :model "320U" :interface "USB" :usbid "0x04a5" "0x2022" :status :good :model "340U" :interface "USB" :usbid "0x04a5" "0x2022" :status :good :model "620U" :interface "USB" :usbid "0x04a5" "0x1a2a" :status :good :comment "Optional tranparency unit supported" :model "620UT" :interface "USB" :usbid "0x04a5" "0x2040" :status :good :comment "Optional tranparency unit supported" :model "640U" :interface "USB" :usbid "0x04a5" "0x2060" :status :good :comment "Optional tranparency unit supported" :model "640bu" :interface "USB" :usbid "0x04a5" "0x207e" :status :good :model "640BT" :interface "USB" :usbid "0x04a5" "0x20be" :status :good :comment "Optional tranparency unit supported" :model "1240" :interface "USB" :usbid "0x04a5" "0x20c0" :status :good :comment "Optional tranparency unit supported" :model "3300" :interface "USB" :usbid "0x04a5" "0x20b0" :status :good :model "3300" :interface "USB" :usbid "0x04a5" "0x20de" :status :good :model "4300" :interface "USB" :usbid "0x04a5" "0x20b0" :status :good :model "4300" :interface "USB" :usbid "0x04a5" "0x20de" :status :good :model "5000E" :interface "USB" :usbid "0x04a5" "0x20fc" :status :basic :comment "Same as 5000U, working up to 600 DPI" :model "5000U" :interface "USB" :usbid "0x04a5" "0x20fc" :status :basic :comment "Same as 5000E, working up to 600 DPI" :model "5000" :interface "USB" :usbid "0x04a5" "0x20f8" :status :good :comment "USB ID 0x04a5,0x20f8: Color / grayscale scans working up to 1200 DPI" :model "5150" :interface "USB" :usbid "0x04a5" "0x2137" :status :basic :comment "Calibration algorithm unknown" :model "5250" :interface "USB" :usbid "0x04a5" "0x2137" :status :basic :comment "Same hardware as 5150 (?), Calibration algorithm unknown" :model "5300" :interface "USB" :usbid "0x04a5" "0x20fe" :status :basic :comment "Problems with firmware upload reported" ;------------------------------------------------------------------------------ :mfg "Guillemot / Hercules" :url "http://www.guillemot.com" :model "Maxi Scan A4 Deluxe (SCSI)" :interface "SCSI" :status :good :comment "Rebadged SnapScan 310s." :model "Scan@home Touch 1248 (USB)" :interface "USB" :usbid "0x04a5" "0x20de" :status :good :comment "Rebadged Benq 3300." :model "Maxi Scan A4 USB 640U" :interface "USB" :usbid "0x04a5" "0x2060" :status :good :comment "Rebadged Benq 640U." :model "Maxi A4 36 bit" :interface "USB" :usbid "0x04a5" "0x2060" :status :good :comment "Rebadged Benq 620U, needs Benq firmware file u96v???.bin" ;------------------------------------------------------------------------------ :mfg "Mitsubishi" :url "http://www.mitsubishi.com" :model "Diamondview 648UT" :interface "USB" :usbid "0x04a5" "0x2022" :status :good :comment "Rebadged Benq 320u." :model "Diamondview 650U" :interface "USB" :usbid "0x04a5" "0x20b0" :status :good :comment "Rebadged Benq 4300." ;------------------------------------------------------------------------------ :mfg "Epson" :url "http://www.epson.com" :model "Perfection 660" :interface "USB" :usbid "0x04b8" "0x0114" :status :good :model "Perfection 1270" :interface "USB" :usbid "0x04b8" "0x0120" :status :good :model "Perfection 1670" :interface "USB" :usbid "0x04b8" "0x011f" :status :good :model "Perfection 2480" :interface "USB" :usbid "0x04b8" "0x0121" :status :good :model "Perfection 2580" :interface "USB" :status :basic :usbid "0x04b8" "0x0121" :comment "Film scanning unit unsupported" :model "Perfection 3490" :interface "USB" :usbid "0x04b8" "0x0122" :status :good :model "Perfection 3590" :interface "USB" :usbid "0x04b8" "0x0122" :status :basic :comment "Film scanning unit unsupported" :model "Stylus CX-1500" :interface "USB" :usbid "0x04b8" "0x080c" :status :good ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/sp15c.desc0000664000175000017500000000214712112021330016255 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "sp15c" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-sp15c" ; name of manpage (if it exists) ;:url "http://www.aa.net/~bentson/sane.html" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Fujitsu" ; name a manufacturer :url "http://www.fcpa.fujitsu.com/products/scanners/" :url "http://www.fujitsu.com/" :model "ScanPartner 15C" ; name models for above-specified mfg. :interface "SCSI" :status :good :model "ScanPartner 600C" ; name models for above-specified mfg. :interface "SCSI" :status :good sane-backends-1.0.27/doc/descriptions/v4l.desc0000664000175000017500000000206013063340150016033 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "v4l" ; name of backend :version "1.0-3 (unmaintained)" ; version of backend :manpage "sane-v4l" ; name of manpage (if it exists) :url "mailto:henning@meier-geinitz.de" ; backend's web page :devicetype :api ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :desc "Interface to Video For Linux API" ; describe a non-hardware device :comment "Supports video cameras and other devices accessed by the v4l kernel API, e.g. bttv devices. Quite a lot of known bugs." ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/dll.desc0000664000175000017500000000032213063340150016100 00000000000000:backend "dll" ; name of backend :version "1.0.13 (unmaintained)" :manpage "sane-dll" :url "mailto:henning@meier-geinitz.de" :devicetype :meta :desc "Dynamic loading of shared-library backends." sane-backends-1.0.27/doc/descriptions/hp3500.desc0000664000175000017500000000264412112021330016243 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hp3500" ; name of backend :version "1.1" ; version of backend :manpage "sane-hp3500" ; name of manpage (if it exists) :url "http://projects.troy.rollo.name/rt-scanners/" ; backend's web page :comment "HP3500 series scanners." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com" :model "ScanJet 3500C" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port" or "Propretiary". :usbid "0x03f0" "0x2205" :status :good :model "ScanJet 3530C" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: :usbid "0x03f0" "0x2005" :status :good :model "ScanJet 3570C" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: :usbid "0x03f0" "0x2005" :status :good ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/kodak.desc0000664000175000017500000000656412617742237016454 00000000000000:backend "kodak" :url "http://www.thebility.com/kodak/" :version "7" :manpage "sane-kodak" :comment "New backend for SANE release 1.0.21, see sane-kodak manpage" :devicetype :scanner :mfg "Kodak" :url "http://www.kodak.com/" ;====================================== ; workgroup machines, old :model "Scanner 1500" :interface "SCSI" :status :untested :comment "Please test!" ;====================================== ; departmental machines, old :model "Scanner 2500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 3500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 3510" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 3520" :interface "SCSI" :status :untested :comment "Please test!" :model "Color Scanner 3590C" :interface "SCSI" :status :untested :comment "Please test!" :model "Color Scanner 4500" :interface "SCSI" :status :untested :comment "Please test!" ;====================================== ; departmental machines, recent :model "i150 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i160 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i250 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i260 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i280 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" ;====================================== ; production machines, old :model "Scanner 900" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 923" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 5500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 7500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 7520" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 9500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 9520" :interface "SCSI" :status :untested :comment "Please test!" ;====================================== ; production machines, recent :model "i610 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i620 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i640 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i660 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i730 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i750 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i780 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i810 Scanner" :interface "SCSI" :status :untested :comment "Please test!" :model "i820 Scanner" :interface "SCSI" :status :untested :comment "Please test!" :model "i830 Scanner" :interface "SCSI" :status :untested :comment "Please test!" :model "i840 Scanner" :interface "SCSI" :status :untested :comment "Please test!" :model "i1840 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i1860 Scanner" :interface "IEEE-1394" :status :basic :comment "Uncompressed B&W, Gray and Color, some automatic features supported" :model "s1740" :interface "SCSI" :status :untested :comment "Please test!" sane-backends-1.0.27/doc/descriptions/hpsj5s.desc0000664000175000017500000000226013063340150016544 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hpsj5s" ; name of backend :version "0.03 (unmaintained)" ; version of backend ;:status :alpha ; :alpha, :beta, :stable, :new :manpage "sane-hpsj5s" ; name of manpage (if it exists) :url "http://hpsj5s.sourceforge.net/" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "ScanJet 5s" ; name models for above-specified mfg. :interface "Parport (EPP)" :comment "Requires libieee1284 library. Only gray mode." :status :minimal ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/magicolor.desc0000664000175000017500000000235013063340150017304 00000000000000; ; SANE Backend specification file for the magicolor backend ; ; Copyright (C) 2010-11 Reinhold Kainhofer ; Released under GPLv2 ; :backend "magicolor" :version "1.0.0 (unmaintained)" :manpage "sane-magicolor" :url "http://wiki.kainhofer.com/hardware/magicolor_scan" :devicetype :scanner :mfg "KONICA MINOLTA" :url "http://www.konicaminolta.com/" :model "magicolor 1690MF" :interface "USB Network" :usbid "0x132b" "0x2089" :status :good :comment "Multi-function color laser printer with fax, scanner and network interface" :url "http://www.konicaminolta.eu/business-solutions/products/laser-printers/all-in-one/magicolor-1690mf/key-features.html" :model "magicolor 4690MF" :interface "USB Network" :usbid "0x132b" "0x2079" :status :good :comment "Multi-function color laser printer with fax, scanner and network interface" :model "BizHub 162/132" :interface "USB Network" :usbid "ignore" :status :unsupported :comment "Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov." :model "DiMage 1611" :interface "USB Network" :usbid "ignore" :status :unsupported :comment "Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov." sane-backends-1.0.27/doc/descriptions/umax_pp.desc0000664000175000017500000000331613072310420017001 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "umax_pp" ; name of backend :version "1 (unmaintained)" ; version of backend :manpage "sane-umax_pp" ; name of manpage (if it exists) ; backend's web page :url "http://umax1220p.sourceforge.net/" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com.tw/" ; These scanners are known to have the same ASIC family. :model "Astra 1220P" :interface "Parport (EPP/ECP)" :status :good :model "Astra 2000P" :interface "Parport (EPP/ECP)" :status :good :model "Astra 1600P" :interface "Parport (EPP/ECP)" :status :good :model "Astra 600P" :interface "Parport (SPP/ECP)" :status :unsupported :comment "untested, but should be close to 610P" :model "Astra 610P" :interface "Parport (SPP/ECP)" :status :good :mfg "Hewlett-Packard" :model "Scanjet 3200C" :interface "Parport (EPP/ECP)" :status :good :comment "works (relabelled 1220P and 2000P)" :mfg "Genius" :model "ColorPage-Life Pro" :interface "Parport (EPP/ECP)" :status :good :comment "works (relabelled 1220P and 2000P)" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/tamarack.desc0000664000175000017500000000205612112021330017104 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "tamarack" ; name of backend :version "unmaintained" ; version of backend ; :manpage "sane-tamarack" ; name of manpage (if it exists) :devicetype :scanner :mfg "Tamarack" ; name a manufacturer ;:url "http://www.tamarack.net/" ; doesn't exist anymore? :model "Artiscan 6000C" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "3 pass, 300 DPI" :model "Artiscan 8000C" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "3 pass, 400 DPI" :model "Artiscan 12000C" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "3 pass, 600 DPI" sane-backends-1.0.27/doc/descriptions/pie.desc0000664000175000017500000000371613063340150016114 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "pie" ; name of backend :version "1.0 (unmaintained)" ; version of backend :manpage "sane-pie" ; name of manpage (if it exists) :url "http://www.munton.demon.co.uk/sane" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Devcom" :url "http://www.blackwidow.co.uk/" :model "9636PRO" :interface "SCSI" :status :good :model "9636S" :interface "SCSI" :status :untested :model "9630S" :interface "SCSI" :status :untested :mfg "PIE" ; name a manufacturer :url "http://www.scanace.com/" :model "ScanAce 1236S" :interface "SCSI" :status :good :model "ScanAce 1230S" :interface "SCSI" :status :good :model "ScanAce II" :interface "SCSI" :status :untested :model "ScanAce III" :interface "SCSI" :status :good :model "ScanAce Plus" :interface "SCSI" :status :untested :model "ScanAce II Plus" :interface "SCSI" :status :untested :model "ScanAce III Plus" :interface "SCSI" :status :untested :model "ScanAce V" :interface "SCSI" :status :untested :model "ScanAce ScanMedia" :interface "SCSI" :status :untested :model "ScanAce ScanMedia II" :interface "SCSI" :status :untested :model "ScanAce 630S" :interface "SCSI" :status :untested :model "ScanAce 636S" :interface "SCSI" :status :untested :mfg "Adlib" :model "JetScan630" :interface "SCSI" :status :good :model "JetScan636PRO" :interface "SCSI" :status :untested ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/canon_dr.desc0000664000175000017500000002235312775312261017133 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "canon_dr" ; name of backend :url "http://www.thebility.com/canon/" :version "51" ; version of backend :manpage "sane-canon_dr" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.25, see sane-canon_dr manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" ;================================================== :model "CR-25" :interface "USB" :usbid "0x1083" "0x161a" :status :untested :comment "Please test!" :model "CR-50" :interface "USB" ;:usbid "0x1083" "0x" :status :untested :comment "Please test!" :model "CR-55" :interface "USB" :usbid "0x1083" "0x160c" :status :untested :comment "Please test!" :model "CR-80" :interface "USB" ;:usbid "0x1083" "0x" :status :untested :comment "Please test!" :model "CR-135i" :interface "USB SCSI" :usbid "0x1083" "0x1639" :status :untested :comment "Please test!" :model "CR-180" :interface "USB SCSI" :usbid "0x04a9" "0x1602" :status :untested :comment "Please test!" :model "CR-180II" :interface "USB SCSI" :usbid "0x04a9" "0x1602" :status :untested :comment "Same as CR-180? Please test!" :model "CR-190i" :interface "USB SCSI" :usbid "0x1083" "0x162b" :status :untested :comment "Please test!" :model "DR-1210C" :interface "USB" :usbid "0x04a9" "0x2222" :status :untested :comment "Older version? Please test!" :model "DR-1210C" :interface "USB" :usbid "0x1083" "0x160f" :status :untested :comment "Later version? Please test!" :model "DR-2010C" :interface "USB" :usbid "0x1083" "0x161b" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions." :model "DR-2010M" :interface "USB" :status :complete :comment "DR-2010C with a different label, same USB IDs" :model "DR-2050C" :interface "USB" :usbid "0x04a9" "0x160a" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration." :model "DR-2050SP" :interface "USB" :usbid "0x04a9" "0x160a" :status :untested :comment "Same as DR-2050C? Please test!" :model "DR-2080C" :interface "USB SCSI" :usbid "0x04a9" "0x1601" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration" :model "DR-2510C" :interface "USB" :usbid "0x1083" "0x1617" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions" :model "DR-2510M" :interface "USB" :status :untested :comment "Mac version of DR-2510C? Please test!" :model "DR-2580C" :interface "USB SCSI" :usbid "0x04a9" "0x1608" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration" :model "DR-3010C" :interface "USB" :usbid "0x1083" "0x161d" :status :good :comment "Minimal testing, settings copied from DR-2510C" :model "DR3020" :interface "SCSI" :status :untested :comment "Please test!" :model "DR-3020C" :interface "SCSI" :status :untested :comment "Please test!" :model "DR-3060" :interface "SCSI" :status :untested :comment "Please test!" :model "DR-3080C" :interface "SCSI" :status :untested :comment "Almost works, need to investigate traces from windows driver" :model "DR-3080CII" :interface "USB SCSI" :usbid "0x04a9" "0x1609" :status :untested :comment "Almost works, need to investigate traces from windows driver" :model "DR-4010C" :interface "USB" :usbid "0x1083" "0x1614" :status :good :comment "Binary/HT/Gray/Color, Simplex/Duplex working. Multistream unsupported." :model "DR4080U" :interface "USB" ;:usbid "0x1083" "0x1614" :status :untested :comment "Please test!" :model "DR-4580U" :interface "USB" ;:usbid "0x1083" "0x1614" :status :untested :comment "Please test!" :model "DR-5010C" :interface "USB" :usbid "0x04a9" "0x1606" :status :basic :comment "ADF and Duplex work, needs more testing" :model "DR-5020" :interface "SCSI" :status :good :comment "LineArt, Duplex working, cannot read buttons or screen?" :model "DR-5060F" :interface "SCSI" :status :basic :comment "Grayscale works, LineArt might" :model "DR-5080C" :interface "SCSI" :status :untested :comment "Please test!" :model "DR-6010C" :interface "USB SCSI" :usbid "0x1083" "0x1626" :status :untested :comment "Please test!" :model "DR-6030C" :interface "USB SCSI" :usbid "0x1083" "0x1638" :status :untested :comment "Please test!" :model "DR-6050C" :interface "USB SCSI" :usbid "0x1083" "0x1624" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode" :model "DR-6080" :interface "USB SCSI" :usbid "0x04a9" "0x1607" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported" :model "DR-7080C" :interface "USB SCSI" :usbid "0x04a9" "0x1604" :status :good :comment "ADF and flatbed work" :model "DR-7090C" :interface "USB SCSI" :usbid "0x1083" "0x1620" :status :good :comment "ADF and flatbed work" :model "DR-7550C" :interface "USB SCSI" :usbid "0x1083" "0x1623" :status :untested :comment "Assumed compatible with DR-6050C" :model "DR-7580" :interface "USB SCSI" :usbid "0x04a9" "0x160b" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported" :model "DR-9050C" :interface "USB SCSI" :usbid "0x1083" "0x1622" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode" :model "DR-9080C" :interface "USB SCSI" :usbid "0x04a9" "0x1603" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray/color, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported" :model "DR-X10C" :interface "USB SCSI" :usbid "0x1083" "0x1618" :status :untested :comment "Please test!" :model "DR-C120" :interface "USB" :usbid "0x1083" "0x1651" :status :untested :model "DR-C125" :interface "USB" :usbid "0x1083" "0x1640" :status :good :model "DR-C130" :interface "USB" :usbid "0x1083" "0x164a" :status :untested :model "DR-C225" :interface "USB" :usbid "0x1083" "0x1658" :status :untested :comment "" :model "DR-F120" :interface "USB" :usbid "0x1083" "0x1654" :status :basic :comment "Flatbed not working. ADF working. Simplex+duplex, all resolutions <= 600, gray/color, calibration poor." :model "DR-G1100" :interface "USB" :usbid "0x1083" "0x1650" :status :good :model "DR-G1130" :interface "USB" :usbid "0x1083" "0x164f" :status :untested :model "DR-M140" :interface "USB" :usbid "0x1083" "0x163f" :status :good :model "DR-M160" :interface "USB" :usbid "0x1083" "0x163e" :status :good :model "DR-M160II" :interface "USB" ;:usbid "0x1083" "0x" :status :untested :model "DR-M1060" :interface "USB" :usbid "0x1083" "0x1657" :status :untested :model "P-150" :interface "USB" ;:usbid "0x1083" "0x162c" :status :untested :comment "Same as P-150M?" :model "P-150M" :interface "USB" :usbid "0x1083" "0x162c" :status :good :model "P-201" :interface "USB" :usbid "0x1083" "0x1652" :status :untested :model "DR-P208" :interface "USB" :usbid "0x1083" "0x164b" :status :untested :comment "Same as P-208?" :model "P-208" :interface "USB" :usbid "0x1083" "0x164c" :status :basic :comment "All modes and resolutions working, but calibration is poor." :model "P-208" :interface "USB" :usbid "0x1083" "0x164e" :status :basic :comment "This is the same device as the 0x164c P-208, but the mode switch on the scanner is in the wrong position, you must move the switch." :model "DR-P208II" :interface "USB" :usbid "0x1083" "0x165d" :status :untested :model "P-208II" :interface "USB" :usbid "0x1083" "0x165f" :status :untested :model "DR-P215" :interface "USB" :usbid "0x1083" "0x1641" :status :untested :comment "Same as P-215?" :model "P-215" :interface "USB" :usbid "0x1083" "0x1646" :status :basic :comment "All modes and resolutions working, but calibration is poor. Card reader slot not working." :model "P-215" :interface "USB" :usbid "0x1083" "0x1647" :status :basic :comment "This is the same device as the 0x1646 P-215, but the mode switch on the scanner is in the wrong position, you must move the switch." :model "DR-P215II" :interface "USB" :usbid "0x1083" "0x1659" :status :untested :model "P-215II" :interface "USB" :usbid "0x1083" "0x165b" :status :untested :model "FSU-201" :interface "USB" :usbid "0x1083" "0x1648" :status :untested sane-backends-1.0.27/doc/descriptions/plustek.desc0000664000175000017500000001401212775277260017041 00000000000000; ; SANE Backend description file for Plustek backend (USB only) ; :backend "plustek" :version "0.52" :manpage "sane-plustek" ; backend's web page :url "http://www.gjaeger.de/scanner/plustek/" :devicetype :scanner ;* Plustek ********************************************************************************** :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticPro U12" :interface "USB" :usbid "0x07b3" "0x0010" :status :complete :comment "NOTE: Devices with product ID 0x0001 are not supported!" :model "OpticPro UT12" :interface "USB" :usbid "0x07b3" "0x0013" :status :complete :model "OpticPro UT12" :interface "USB" :usbid "0x07b3" "0x0017" :status :complete :comment "Note: Devices with product ID 0x0001 are not supported!" :model "OpticPro UT16" :interface "USB" :usbid "0x07b3" "0x0017" :status :complete :model "OpticPro U24" :interface "USB" :usbid "0x07b3" "0x0011" :status :complete :model "OpticPro U24" :interface "USB" :usbid "0x07b3" "0x0015" :status :complete :model "OpticPro UT24" :interface "USB" :usbid "0x07b3" "0x0017" :status :complete ;* Genius/KYE ******************************************************************************************* :mfg "Genius" :url "http://www.geniusnet.com.tw/" :model "Colorpage HR6 V2" :interface "USB" :usbid "0x0458" "0x2007" :status :complete :model "Colorpage HR6 V2" :interface "USB" :usbid "0x0458" "0x2008" :status :complete :model "Colorpage HR7" :interface "USB" :usbid "0x0458" "0x2013" :status :complete :model "Colorpage HR6A" :interface "USB" :usbid "0x0458" "0x2009" :status :untested :model "Colorpage HR7LE" :interface "USB" :usbid "0x0458" "0x2015" :status :untested :model "Colorpage HR6X" :interface "USB" :usbid "0x0458" "0x2016" :status :untested ;* MUSTEK *********************************************************************************** :mfg "Mustek" :url "http://www.mustek.com/" :model "BearPaw 1200" :interface "USB" :usbid "0x0400" "0x1000" :status :complete :comment "both product versions are supported, see backends' man-page" :model "BearPaw 1200" :interface "USB" :usbid "0x0400" "0x1001" :status :complete :comment "both product versions are supported, see backends' man-page" :model "BearPaw 2400" :interface "USB" :usbid "0x0400" "0x1001" :status :complete ;* Hewlett-Packard ************************************************************************** :mfg "Hewlett-Packard" :url "http://www.hp.com/" :model "ScanJet 2100C" :interface "USB" :usbid "0x03f0" "0x0505" :status :complete :model "ScanJet 2200C" :interface "USB" :usbid "0x03f0" "0x0605" :status :complete ;* EPSON ******************************************************************************************* :mfg "Epson" :url "http://www.epson.com/" :model "Perfection 1250" :interface "USB" :usbid "0x04b8" "0x010f" :status :complete :model "Perfection 1250Photo" :interface "USB" :usbid "0x04b8" "0x010f" :status :good :comment "TPA scans not perfect" :model "Perfection 1260" :interface "USB" :usbid "0x04b8" "0x011d" :status :complete :model "Perfection 1260Photo" :interface "USB" :usbid "0x04b8" "0x011d" :status :good :comment "TPA scans not perfect" ;* UMAX ************************************************************************************* :mfg "Umax" :url "http://www.umax.com/" :model "UMAX 3400" :interface "USB" :usbid "0x1606" "0x0050" :status :complete :comment "there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x" :model "UMAX 3400" :interface "USB" :usbid "0x1606" "0x0060" :status :complete :comment "there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x" :model "UMAX Astranet ia101" :interface "USB" :usbid "0x1606" "0x0060" :status :complete :comment "seems to be a renamed UMAX 3400" :model "UMAX 3450" :interface "USB" :usbid "0x1606" "0x0060" :status :complete :model "UMAX 5400" :interface "USB" :usbid "0x1606" "0x0160" :status :complete ;* COMPAQ ****************************************************************************************** :mfg "Compaq" :url "http://www.compaq.com/" :model "S4-100" :interface "USB" :usbid "0x049f" "0x001a" :status :complete :comment "Identical to UMAX 3400" ;* CANON ******************************************************************************************* :mfg "Canon" :url "http://www.canon.com/" :model "CanoScan N650U/N656U" :interface "USB" :usbid "0x04a9" "0x2206" :status :complete :model "CanoScan N1220U" :interface "USB" :usbid "0x04a9" "0x2207" :status :complete :model "CanoScan N670U/N676U/LiDE20" :interface "USB" :usbid "0x04a9" "0x220d" :status :complete :model "CanoScan N1240U/LiDE30" :interface "USB" :usbid "0x04a9" "0x220e" :status :complete :model "CanoScan LiDE25" :interface "USB" :usbid "0x04a9" "0x2220" :status :good :model "CanoScan D660U" :interface "USB" :usbid "0x04a9" "0x2208" :status :good :comment "TPA scans not perfect" ;* SYSCAN ******************************************************************************************* :mfg "Syscan" :url "http://www.syscaninc.com/" :model "TravelScan 460/464" :interface "USB" :usbid "0x0a82" "0x4600" :status :complete :model "TravelScan 662" :interface "USB" :usbid "0x0a82" "0x6620" :status :complete ;* SYSCAN ******************************************************************************************* :mfg "Ambir" :model "Visigo A4" :interface "USB" :usbid "0x0a82" "0x4600" :status :complete :comment "Rebaged Travelscan 464" ;* Portable Peripheral Co., Ltd. ******************************************************************** :mfg "Portable Peripheral Co., Ltd." :url "http://www.pandp.com.tw/" :model "Q-Scan USB001 (A4 portable scanner)" :interface "USB" :usbid "0x0a53" "0x1000" :status :complete :model "Q-Scan USB201 (A6 portable scanner)" :interface "USB" :usbid "0x0a53" "0x2000" :status :good ;* Visioneer **************************************************************************************** :mfg "Visioneer" :url "http://www.visioneer.com/" :model "Strobe XP 100" :interface "USB" :usbid "0x04a7" "0x0427" :status :basic sane-backends-1.0.27/doc/descriptions/hp5400.desc0000664000175000017500000000303413063340150016250 00000000000000; Copied from hp3300 testtools - Martijn van Oosterhout 22/02/2003 ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hp5400" ; name of backend :version "1.0-2 (unmaintained)" ; version of backend :manpage "sane-hp5400" ; name of manpage (if it exists) :url "http://sourceforge.net/projects/hp5400backend" ; backend's web page :comment "HP5400 and HP5470 scanners. Prototype backend available" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com" :model "ScanJet 5400c" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port" or "Propretiary". :usbid "0x03f0" "0x1005"" :status :basic :model "ScanJet 5470c" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: :usbid "0x03f0" "0x1105" :status :basic :model "ScanJet 5490c" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: :usbid "0x03f0" "0x1105" :status :basic ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/mustek_usb2.desc0000664000175000017500000000064413063340150017577 00000000000000:backend "mustek_usb2" :version "1.0-10 (unmaintained)" :manpage "sane-mustek_usb2" :url "http://www.meier-geinitz.de/sane/mustek_usb2-backend/" :comment "Only BearPaw 2448TA Pro is supported at the moment" :devicetype :scanner :mfg "Mustek" :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "BearPaw 2448TA Pro" :interface "USB" :usbid "0x055f" "0x0409" :status :good sane-backends-1.0.27/doc/descriptions/niash.desc0000664000175000017500000000250213063340150016431 00000000000000; $Id$ ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "niash" :version "0.3 (unmaintained)" :manpage "sane-niash" :url "http://sourceforge.net/projects/hp3300backend" :devicetype :scanner :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "ScanJet 3300c" :interface "USB" :usbid "0x03f0" "0x0205" :status :complete :model "ScanJet 3400c" :interface "USB" :usbid "0x03f0" "0x0405" :comment "If you use Linux 2.6, version 2.6.8 or newer is necessary." :status :complete :model "ScanJet 4300c" :interface "USB" :usbid "0x03f0" "0x0305" :comment "If you use Linux 2.6, version 2.6.8 or newer is necessary." :status :complete :model "ScanJet 4300c/Silitek" :interface "USB" :usbid "0x047b" "0x1002" :comment "If you use Linux 2.6, version 2.6.8 or newer is necessary." :status :complete :mfg "Agfa" :url "http://www.agfa.com" :model "Snapscan Touch" :interface "USB" :usbid "0x06bd" "0x0100" :status :complete :mfg "Trust" :url "http://www.trust.com" :model "Office Scan USB 19200" :interface "USB" :usbid "0x047b" "0x1000" :status :complete sane-backends-1.0.27/doc/descriptions/matsushita.desc0000664000175000017500000000317313063340150017516 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "matsushita" ; name of backend :version "1.0-7 (unmaintained)" ; version of backend :manpage "sane-matsushita" ; name of manpage :url "http://www.zago.net/sane" ; backend's web page :devicetype :scanner ; start of a list of devices.... :mfg "Panasonic" ; name a manufacturer :url "http://www.panasonic.com/" :model "KV-SS25" :interface "SCSI" :status :complete :model "KV-SS25D" :interface "SCSI" :status :complete :model "KV-SS50" :interface "SCSI" :status :untested :model "KV-SS55" :interface "SCSI" :status :untested :model "KV-SS50EX" :interface "SCSI" :status :untested :model "KV-SS55EX" :interface "SCSI" :status :minimal :comment "no color, no high resolution, no automatic cropping" :model "KV-SS850" :interface "SCSI" :status :untested :model "KV-SS855" :interface "SCSI" :status :untested :model "KV-S2025C" :interface "SCSI" :status :minimal :comment "no color, no high resolution, no automatic cropping" :model "KV-S2045C" :interface "SCSI" :status :minimal :comment "no color, no high resolution, no automatic cropping" :model "KV-S2065L" :interface "SCSI" :status :minimal :comment "no color, no high resolution, no automatic cropping" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/hp4200.desc0000664000175000017500000000304413063340150016246 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "hp4200" ; name of backend :version "1.0-2 (unmaintained)" ; version of backend :manpage "sane-hp4200" ; name of manpage (if it exists) :url "http://hp4200-backend.sourceforge.net" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "ScanJet 4200C" ; name models for above-specified mfg. :interface "USB" :usbid "0x03f0" "0x0105" :status :basic :comment "8bpp color, 75/150/300/600 dpi only" :model "ScanJet 4200Cxi" ; name models for above-specified mfg. :interface "USB" :usbid "0x03f0" "0x0105" :status :basic :comment "8bpp color, 75/150/300/600 dpi only" :model "ScanJet 4200Cse" ; name models for above-specified mfg. :interface "USB" :usbid "0x03f0" "0x0105" :status :basic :comment "8bpp color, 75/150/300/600 dpi only" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/coolscan.desc0000664000175000017500000000270013063340150017130 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "coolscan" ; name of backend :version "0.4.3 (unmaintained)" ; version of backend :url "http://andreas.rick.free.fr/sane/" ; backend's web page :manpage "sane-coolscan" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Nikon" ; name a manufacturer :url "http://www.nikon.com/" :model "LS-20" ; name models for above-specified mfg. :interface "SCSI" :comment "The LS-20 has been replaced by the LS-30" :status :basic :model "LS-30" ; name models for above-specified mfg. :interface "SCSI" :comment "alpha: only 24/30 bit RGB + 32/40 bit RGBI" :status :basic :model "LS-2000" ; name models for above-specified mfg. :interface "SCSI" :comment "alpha: only 24/36 bit + RGB 32/48 bit RGBI" :status :basic :model "LS-1000" :interface "SCSI" :comment "Doesn't support gamma correction" :status :basic ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/net.desc0000664000175000017500000000047113063340150016120 00000000000000:backend "net" ; name of backend :version "1.0.14 (unmaintained)" :manpage "sane-net" :url "http://www.penguin-breeder.org/?page=sane-net" :devicetype :meta :desc "Network access to saned servers" :comment "Can be used to access any scanner supported by SANE over the net. Supports IPv4 and IPv6." sane-backends-1.0.27/doc/descriptions/hs2p.desc0000664000175000017500000000346112112021330016176 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hs2p" ; name of backend :url "http://www.acjlaw.net:8080/~jeremy/Ricoh/" :version "1.00" ; version of backend ; :manpage "sane-hs2p" ; name of manpage (if it exists) :comment "This backend has been tested with the IS450DE (Duplex/Endorser). All major functions necessary for scanning are supported. This backend should work with all Ricoh scanners in the IS450 family as well as the IS420 series, but the IS420 has not yet been tested. Features provided by the optional Image Processing Unit (IPU) are not yet integrated into the backend, as my scanner lacks the IPU." :devicetype :scanner :mfg "Ricoh" ; name a manufacturer :url "http://www.ricoh.com/" :model "IS450" ; name models for above-specified mfg. :interface "SCSI" :status :complete :comment "All major scanning-related features are supported (except for IPU). Certain non-scanning features, such as those related to scanner maintenance, are not supported. Such features would be better implemented in a separate stand-alone tool. For instance, if you replace the ADF Unit, you must recalibrate the scanner optics using a Ricoh Test Sheet and reset the E^2PROM registers. Reports are welcome." :model "IS-410" :interface "SCSI" :status :untested :comment "Untested, please report!" :model "IS-420" :interface "SCSI" :status :untested :comment "Untested, please report!" :model "IS-430" :interface "SCSI" :status :untested :comment "Untested, please report!" sane-backends-1.0.27/doc/descriptions/canon630u.desc0000664000175000017500000000230113063340150017040 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "canon630u" ; name of backend :manpage "sane-canon630u" :version "0.1 (unmaintained)" ; version of backend ;:status :beta :url "http://canon-fb630u.sourceforge.net/" ; backend home page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" :model "CanoScan fb630u" ; name models for above-specified mfg. :interface "USB" :usbid "0x04a9" "0x2204" :comment "OK" :status :good :model "CanoScan fb636u" ; name models for above-specified mfg. :interface "USB" :usbid "0x04a9" "0x2204" :status :good :comment "OK" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/pint.desc0000664000175000017500000000056712112021330016300 00000000000000:backend "pint" ; name of backend :version "unmaintained" ; version of backend ; :url "" ; backend's homepage :manpage "sane-pint" :devicetype :api ; name models for above-specified mfg. :desc "Scanners with the machine-independent PINT interface" :comment "Haven't been tested for a long time. Handle with care." sane-backends-1.0.27/doc/descriptions/ibm.desc0000664000175000017500000000241013063340150016074 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "ibm" ; name of backend :url "http://www.meier-geinitz.de/sane/ibm-backend/" :version "1.0-4 (unmaintained)" ; version of backend ; :manpage "sane-ibm" ; name of manpage (if it exists) :comment "This backend has had only limited testing. It needs more work especially for the Ricoh scanners. Patches are welcome." :devicetype :scanner :mfg "IBM" ; name a manufacturer :url "http://www.ibm.com/" :model "2456" ; name models for above-specified mfg. :interface "SCSI" :status :basic :comment "Was reported to work long time ago. Reports are welcome." :mfg "Ricoh" ; name a manufacturer :model "IS-410" :interface "SCSI" :status :untested :comment "Untested, please report!" :model "IS-420" :interface "SCSI" :status :basic :comment "Works at least in flatbed mode." :model "IS-430" :interface "SCSI" :status :untested :comment "Untested, please report!" sane-backends-1.0.27/doc/descriptions/artec_eplus48u.desc0000664000175000017500000000373712112021330020177 00000000000000; ; SANE Backend specification file ; :backend "artec_eplus48u" :version "unmaintained" :manpage "sane-artec_eplus48u" ;:url "http://www.angelfire.com/linux/crapsite/" :devicetype :scanner :mfg "Artec/Ultima" :url "http://www.artecusa.com/" :model "E+ 48U" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :comment "CIS scanner based on the GT6816 chip. Apparently all other devices are re-badged Artec scanners." :model "E+ Pro" :status :minimal :interface "USB" :usbid "0x05d8" "0x4004" :comment "Works up to 600dpi, but not 1200. Needs better calibration. See bug #310490" :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.com" :comment "Sold by Aldi and Tchibo." :model "MD9693" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :model "MD9705" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :model "MD4394" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :comment "Only scanners with product id 0x4003 will work; try the gt68xx backend, if your scanner has product id 0x4002 " :mfg "Trust" :url "http://www.trust-site.com" :model "Easy Webscan 19200" :status :good :interface "USB" :usbid "0x05d8" "0x4006" :model "240H Easy Webscan Gold" :status :basic :interface "USB" :usbid "0x05d8" "0x4007" :comment "Works up to 600 dpi" :mfg "Memorex" :url "http://www.artecusa.com/" :model "MEM 48U" :status :good :interface "USB" :usbid "0x05d8" "0x4005" :mfg "Microstar" :url "http://www.microstar.de/" :model "MR 9791" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :mfg "UMAX" :url "http://www.umax.com/" :url "http://www.umax.com.tw/" :url "http://www.umax.de/en" :url "http://www.umax-europe.com" :url "http://www.umaxjapan.co.jp" :url "http://www.umax.com.cn" :model "AstraSlim SE" :status :good :interface "USB" :usbid "0x05d8" "0x4009" :model "AstraSlim 1200 SE" :status :good :interface "USB" :usbid "0x05d8" "0x4010" :mfg "Yakumo" :url "http://www.yakumo.com/" :model "Scan50" :status :good :interface "USB" :usbid "0x05d8" "0x4011" sane-backends-1.0.27/doc/descriptions/p5.desc0000664000175000017500000000217113072310420015652 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "p5" ; name of backend :version "1 (unmaintained)"; version of backend :manpage "sane-p5" ; name of manpage (if it exists) :comment "New backend for SANE release 1.0.21, see sane-p5 manpage" :url "http://www.sane-project.org/" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "PRIMAX" ; name a manufacturer :url "http://www.primax.com.tw" :model "PagePartner" :interface "Parport (EPP/ECP)" :status :basic :comment "Sheetfed scanner, work in gray and color, but uncalibrated scans" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions/abaton.desc0000664000175000017500000000060712112021330016565 00000000000000:backend "abaton" :version "unmaintained" :manpage "sane-abaton" ;:url "http://aix2.uottawa.ca/~s1204672/sane/" :devicetype :scanner :mfg "Abaton" ;:url "http://www.everex.com/" ;dead? :model "Scan 300/GS" :interface "SCSI" :status :complete :comment "All known modes and functions supported" :model "Scan 300/S" :interface "SCSI" :status :untested :comment "Untested, use with caution" sane-backends-1.0.27/doc/descriptions/kvs40xx.desc0000664000175000017500000000171312775312262016675 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "kvs40xx" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-kvs40xx" ; name of manpage (if it exists) :comment "New backend for SANE release 1.0.23, see sane-kvs40xx manpage" :devicetype :scanner ; start of a list of devices.... :mfg "Panasonic" ; name a manufacturer :url "http://www.panasonic.com/" :model "KV-S4065C" :interface "USB" :usbid "0x04da" "0x100d" :status :untested :model "KV-S4085C" :interface "USB" :usbid "0x04da" "0x100c" :status :untested :model "KV-S7075C" :interface "USB" :usbid "0x04da" "0x100e" :status :untested sane-backends-1.0.27/doc/descriptions/sceptre.desc0000664000175000017500000000140513063340150016775 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "sceptre" :version "1.0-10 (unmaintained)" ; version of backend :manpage "sane-sceptre" ; name of manpage :url "http://www.zago.net/sane/" ; backend's web page :devicetype :scanner :mfg "Sceptre" :url "http://www.sceptre.com/" :model "Vividscan S1200" :interface "SCSI" :status :basic :mfg "Komodo" :url "http://www.komodo.com/" :model "S1200" :interface "SCSI" :status :untested :comment "rebadged Sceptre S1200" sane-backends-1.0.27/doc/descriptions/kodakaio.desc0000664000175000017500000000633312775312262017133 00000000000000:backend "kodakaio" :url "http://sourceforge.net/projects/cupsdriverkodak/" :version "2.7.2" :manpage "sane-kodakaio" :comment "Backend for Kodak AiO ESP and Hero printers. Also possibly Advent AWL10" :devicetype :scanner :mfg "Kodak" :url "http://www.kodak.com/" ;====================================== ; ESP series :model "ESP 2150" :interface "USB" :usbid "0x040a" "0x4059" :status :untested :comment "Please test!" :model "ESP 2170" :interface "USB" :usbid "0x040a" "0x4066" :status :basic :comment "Tested with network" :model "ESP 3200" :interface "USB" :usbid "0x040a" "0x4043" :status :untested :comment "Please test!" :model "ESP 3300" :interface "USB" :usbid "0x040a" "0x4031" :status :untested :comment "Please test!" :model "ESP 4100" :interface "USB" :usbid "0x040a" "0x4053" :status :untested :comment "Please test!" :model "ESP 5000" :interface "USB" :usbid "0x040a" "0x4028" :status :untested :comment "Please test!" :model "ESP 5100" :interface "USB" :usbid "0x040a" "0x4025" :status :untested :comment "Please test!" :model "ESP 5200" :interface "USB Ethernet" :usbid "0x040a" "0x4041" :status :complete :comment "USB good, Network good" :model "ESP 5300" :interface "USB" :usbid "0x040a" "0x4026" :status :untested :comment "Please test!" :model "ESP 5500" :interface "USB" :usbid "0x040a" "0x4027" :status :untested :comment "Please test!" :model "ESP 6100" :interface "USB" :usbid "0x040a" "0x4054" :status :untested :comment "Please test!" :model "ESP 7200" :interface "USB" :usbid "0x040a" "0x4056" :status :untested :comment "Please test!" :model "ESP 9200" :interface "USB" :usbid "0x040a" "0x4065" :status :untested :comment "Please test!" :model "ESP 5" :interface "USB" :usbid "0x040a" "0x4032" :status :untested :comment "Please test!" :model "ESP 7" :interface "USB" :usbid "0x040a" "0x403e" :status :untested :comment "Please test!" :model "ESP 9" :interface "USB" :usbid "0x040a" "0x403f" :status :untested :comment "Please test!" :model "ESP C110" :interface "USB" :usbid "0x040a" "0x4057" :status :untested :comment "Please test!" :model "ESP C115" :interface "USB" :usbid "0x040a" "0x4058" :status :untested :comment "Please test!" :model "ESP C310" :interface "USB" :usbid "0x040a" "0x405d" :status :untested :comment "Please test!" :model "ESP C315" :interface "USB" :usbid "0x040a" "0x405e" :status :untested :comment "Please test!" ;====================================== ; Hero series :model "Hero 3.1" :interface "USB" :usbid "0x040a" "0x406d" :status :untested :comment "Please test!" :model "Hero 4.1" :interface "USB" :usbid "0x040a" "0x4069" :status :untested :comment "Please test!" :model "Hero 5.1" :interface "USB" :usbid "0x040a" "0x4064" :status :untested :comment "Please test!" :model "Hero Office 6.1" :interface "USB" :usbid "0x040a" "0x4062" :status :basic :comment "Does the adf work?" :model "Hero 7.1" :interface "USB" :usbid "0x040a" "0x4063" :status :untested :comment "Please test!" :model "Hero 9.1" :interface "USB Ethernet" :usbid "0x040a" "0x4067" :status :complete :comment "USB good, Network good" ;=================================== :mfg "Advent" :url "http://www.adventcomputers.co.uk" :model "AW10" :interface "USB" :usbid "0x040a" "0x4060" :status :untested :comment "Please test!" sane-backends-1.0.27/doc/descriptions/genesys.desc0000664000175000017500000001707412775312261017031 00000000000000:backend "genesys" :version "1.0-63" :manpage "sane-genesys" :comment "Only the USB scanners mentioned below are currently supported." :url "http://www.meier-geinitz.de/sane/genesys-backend/" :devicetype :scanner ; ----------------------------------------------------------------------------- :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticBook 3600" :interface "USB" :usbid "0x07b3" "0x0900" :status :basic :comment "Has a Primax USB ID" ; ----------------------------------------------------------------------------- :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.com/" :url "http://www.medion.de/" :model "MD5345" :interface "USB" :usbid "0x0461" "0x0377" :status :good :comment "Has a Primax USB ID" :model "MD6228" :interface "USB" :usbid "0x0461" "0x0377" :status :good :comment "Has a Primax USB ID. Same as MD5345" :model "MD6471" :interface "USB" :usbid "0x0461" "0x0377" :status :complete :comment "Has a Primax USB ID. Same as MD5345" ; ----------------------------------------------------------------------------- :mfg "Hewlett-Packard" :url "http://www.hp.com/" :model "ScanJet 2300C" :interface "USB" :usbid "0x03f0" "0x0901" :status :complete :comment "600x1200 dpi max" :model "ScanJet 2400C" :interface "USB" :usbid "0x03f0" "0x0a01" :status :complete :comment "1200x1200 dpi max" :model "ScanJet G2410" :interface "USB" :usbid "0x03f0" "0x0a01" :status :basic :comment "clone of the HP 2400C" :model "ScanJet 3670C" :interface "USB" :usbid "0x03f0" "0x1405" :status :complete :comment "1200x1200 dpi max, complete transparency adaptor support" :model "ScanJet 3690C" :interface "USB" :usbid "0x03f0" "0x1405" :status :complete :comment "1200x1200 dpi max, same as HP 3670C" :model "ScanJet 4850C" :interface "USB" :usbid "0x03f0" "0x1b05" :status :good :comment "resolution from 100 to 2400 supported, UTA not supported yet" :model "ScanJet G4010" :interface "USB" :usbid "0x03f0" "0x4505" :status :good :comment "resolution from 100 to 2400 supported, UTA not supported yet" :model "ScanJet G4050" :interface "USB" :usbid "0x03f0" "0x4605" :status :good :comment "resolution from 100 to 2400 supported, UTA not supported yet" :model "ScanJet N6310" :interface "USB" :usbid "0x03f0" "0x4705" :status :untested :comment "Not supported yet" ; ----------------------------------------------------------------------------- :mfg "Canon" :url "http://www.canon.com/" :model "CanoScan LiDE 35" :interface "USB" :usbid "0x04a9" "0x2213" :status :good :comment "Same ids as LiDE 50." :model "CanoScan LiDE 40" :interface "USB" :usbid "0x04a9" "0x2213" :status :good :comment "Same ids as LiDE 50." :model "CanoScan LiDE 50" :interface "USB" :usbid "0x04a9" "0x2213" :status :good :model "CanoScan LiDE 60" :interface "USB" :usbid "0x04a9" "0x221c" :status :good :model "CanoScan LiDE 80" :interface "USB" :usbid "0x04a9" "0x2214" :status :basic :comment "No 2400 dpi support, slow speed at lower resolution" :model "CanoScan LiDE 100" :interface "USB" :usbid "0x04a9" "0x1904" :status :complete :comment "GL847 based, resolution from 75 to 2400 dpi" :model "CanoScan LiDE 110" :interface "USB" :usbid "0x04a9" "0x1909" :status :complete :comment "GL124 based, resolution from 75 to 2400 dpi" :model "CanoScan LiDE 120" :interface "USB" :usbid "0x04a9" "0x190e" :status :complete :comment "GL124+ based, resolution from 75 to 2400 dpi" :model "CanoScan LiDE 200" :interface "USB" :usbid "0x04a9" "0x1905" :status :complete :comment "GL847 based, resolution from 75 to 4800 dpi" :model "CanoScan LiDE 210" :interface "USB" :usbid "0x04a9" "0x190a" :status :complete :comment "GL124 based, resolution from 75 to 4800 dpi" :model "CanoScan LiDE 220" :interface "USB" :usbid "0x04a9" "0x190f" :status :complete :comment "GL124+ based, resolution from 75 to 4800 dpi" :model "CanoScan 4400f" :interface "USB" :usbid "0x04a9" "0x2228" :status :unsupported :comment "GL843 based, to be added to the genesys backend" :model "CanoScan 5600F" :interface "USB" :usbid "0x04a9" "0x1906" :status :unsupported :comment "GL847 based, to be added to the genesys backend" :model "CanoScan 700F" :interface "USB" :usbid "0x04a9" "0x1907" :status :good :comment "GL847 based, resolution from 75 to 4800 dpi" :model "Canon Image Formula 101" :interface "USB" :usbid "0x1083" "0x162e" :status :unsupported :comment "GL846 based, work in progress" ; ----------------------------------------------------------------------------- :mfg "Visioneer" :url "http://www.visioneer.com/" :model "Strobe XP 100,r3" :interface "USB" :usbid "0x04a7" "0x049b" :status :good :comment "All resolution and mode supported, calibration is available" :model "Strobe XP 200" :interface "USB" :usbid "0x04a7" "0x0426" :status :good :comment "All resolution and mode supported, calibration is available" :model "Strobe XP 300" :interface "USB" :usbid "0x04a7" "0x0474" :status :good :comment "All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally." :model "Roadwarrior" :interface "USB" :usbid "0x04a7" "0x0494" :status :basic :comment "All resolution and mode supported, calibration is available" :model "Visioneer OneTouch 7100" :interface "USB" :usbid "0x04a7" "0x0229" :status :complete :comment "Same as MD5345" ; ----------------------------------------------------------------------------- :mfg "Pentax" :url "http://www.pentaxtech.com/" :url "http://mobilesolutions.brother-usa.com/" :model "DSmobile 600" :interface "USB" :usbid "0x0a17" "0x3210" :status :good :comment "All resolution and mode supported, calibration is available" :model "DSmobile 600" :interface "USB" :usbid "0x04f9" "0x2038" :status :good :comment "All resolution and mode supported, calibration is available" ; ----------------------------------------------------------------------------- :mfg "DCT" :url "http://www.docucap.com/" :comment "Successor of Syscan in the USA" :model "DocketPort 487" :interface "USB" :usbid "0x1dcc" "0x4810" :status :basic :comment "All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally." ; ----------------------------------------------------------------------------- :mfg "Syscan" :model "DocketPort 485" :interface "USB" :usbid "0x0a82" "0x4810" :status :basic :comment "All resolution and mode supported, front- and backside side-by-side, with backside mirrored horizontally." :model "DocketPort 465" :interface "USB" :usbid "0x0a82" "0x4802" :status :untested :comment "All resolution and mode should be supported, but uncorrected scans" :model "DocketPort 665" :interface "USB" :usbid "0x0a82" "0x4803" :status :basic :comment "All resolution and mode supported, calibration is available" :model "DocketPort 685/ Ambir DS685" :interface "USB" :usbid "0x0a82" "0x480c" :status :good :comment "All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally." :mfg "Xerox" :url "http://www.xerox.com/" :model "Travel Scanner 100" :interface "USB" :usbid "0x04a7" "0x04ac" :status :good :comment "All resolution and mode supported, calibration is available" :model "2400 Onetouch" :interface "USB" :usbid "0x0461" "0x038b" :status :complete :comment "GL646 based, resolution from 75 to 2400 dpi" ; ----------------------------------------------------------------------------- :mfg "Panasonic" :model "KV-SS080" :interface "USB" :usbid "0x04da" "0x100f" :status :complete :comment "All resolution and mode supported, calibration is available. Support sponsored by cncsolutions (http://www.cncsolutions.com.br)" sane-backends-1.0.27/doc/descriptions/s9036.desc0000664000175000017500000000062512112021330016105 00000000000000:backend "s9036" ; name of backend :version "unmaintained" ; version of backend ; :url "" ; backend's homepage :manpage "sane-s9036" :devicetype :scanner :mfg "Siemens" ; name a manufacturer :url "http://www.siemens.com/" :model "9036 Flatbed scanner" ; name models for above-specified mfg. :interface "SCSI" :status :basic ; :comment "" sane-backends-1.0.27/doc/descriptions/epjitsu.desc0000664000175000017500000000476213073301665017035 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "epjitsu" ; name of backend :version "31" ; version of backend :manpage "sane-epjitsu" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.26, see sane-epjitsu manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Fujitsu" ; name a manufacturer :url "http://www.fujitsu.com/" ;================================================== :model "fi-60F" :interface "USB" :status :good :usbid "0x04c5" "0x10c7" :comment "A6-size flatbed. Hardware provides 150/200/300/400/600 dpi in color. Software creates other resolutions, plus grayscale and binary modes. Hardware grayscale mode is not used due to poor calibration." :model "ScanSnap S300" :interface "USB" :status :good :usbid "0x04c5" "0x1156" :comment "Letter-size ADF. Hardware provides duplex, 150/225/300/600 dpi in color on AC or USB power. Software creates other resolutions, plus grayscale and binary modes. All buttons and sensors are exposed. Scanner always scans in _triplex_ color, fast USB required." :model "ScanSnap S300M" :interface "USB" :status :good :usbid "0x04c5" "0x117f" :comment "Same as S300, with different usb id" :model "fi-65F" :interface "USB" :status :good :usbid "0x04c5" "0x11bd" :comment "Same as fi-60f, with different usb id. Button support untested." :model "ScanSnap S1300" :interface "USB" :status :good :usbid "0x04c5" "0x11ed" :comment "Same as S300, with different usb id" :model "ScanSnap S1100" :interface "USB" :status :good :usbid "0x04c5" "0x1200" :comment "Letter-size ADF. Hardware provides simplex, 300/600 dpi in color on USB power. Software creates other resolutions, plus grayscale and binary modes. All buttons and sensors are exposed. Scanner always scans in _triplex_ color, fast USB required." :model "ScanSnap S1300i" :interface "USB" :status :good :usbid "0x04c5" "0x128d" :comment "Same as S300, with different usb id" :model "ScanSnap S1100i" :interface "USB" :status :good :usbid "0x04c5" "0x1447" :comment "Same as S1100, with different usb id" sane-backends-1.0.27/doc/descriptions/dmc.desc0000664000175000017500000000214212112021330016060 00000000000000; $Id$ ; ; SANE Backend specification file (Matto Marjanovic's format) ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "dmc" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-dmc" ; name of manpage (if it exists) :devicetype :stillcam ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Polaroid" ; name a manufacturer :url "http://www.polaroid.com/" :model "DMC" ; name models for above-specified mfg. :interface "SCSI" ;:url "http://digitalimage.polaroid.com/products/digital_imaging/digital_cameras/dmcsuite/dmc/" :status :good ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/sane.tex0000664000175000017500000023067012775312262013456 00000000000000\documentclass[11pt]{report} \usepackage{times,graphicx,url} % Not Currently using changebar package so comment out to reduce % external dependencies. %\usepackage{changebar} \setlength{\parindent}{0pt} \setlength{\parskip}{1.5ex plus 0.5ex minus 0.5ex} \setlength{\textwidth}{6.5in} \setlength{\textheight}{8.5in} \setlength{\marginparwidth}{0pt} \setlength{\oddsidemargin}{0pt} \setlength{\evensidemargin}{0pt} \setlength{\marginparsep}{0pt} \addtolength{\topmargin}{-0.75in} \title{\huge SANE Standard Version 1.06} \author{} \date{2008-05-03} \makeindex \begin{document} \newcommand{\filename}[1]{{\tt #1}} \newcommand{\code}[1]{{\tt #1}} \newcommand{\var}[1]{{\it #1}} \newcommand{\defn}[1]{#1\index{#1}} % Uncomment if adding changebars to text %\begin{latexonly} % \setcounter{changebargrey}{0} % black change bars %\end{latexonly} \maketitle \tableofcontents \listoffigures \listoftables \chapter{Preface} The SANE standard is being developed by a group of free-software developers. The process is open to the public and comments as well as suggestions for improvements are welcome. Information on how to join the SANE development process can be found in Chapter \ref{chap:contact}. The SANE standard is intended to streamline software development by providing a standard application programming interface to access raster scanner hardware. This should reduce the number of different driver implementations, thereby reducing the need for reimplementing similar code. \section{About This Document} This document is intended for developers who are creating either an application that requires access to raster scanner hardware and for developers who are implementing a SANE driver. It does not cover specific implementations of SANE components. Its sole purpose is to describe and define the SANE application interface that will enable any application on any platform to interoperate with any SANE backend for that platform. The remainder of this document is organized as follows. Chapter~\ref{chap:intro} provides introductional material. Chapter~\ref{chap:environ} presents the environment SANE is designed for. Chapter~\ref{chap:api} details the SANE Application Programmer Interface. Chapter~\ref{chap:net} specifies the network protocol that can be used to implement the SANE API in a network transparent fashion. Finally, Chapter~\ref{chap:contact} gives information on how to join the SANE development process. \subsection{Typographic Conventions} Changes since the last revision of this document are highlighted like this: % \begin{changebar} % Paragraphs that changed since the last revision of the documention % are marked like this paragraph. % \end{changebar} \chapter{Introduction}\label{chap:intro} SANE is an application programming interface (API) that provides standardized access to any raster image scanner hardware. The standardized interface allows to write just one driver for each scanner device instead of one driver for each scanner and application. The reduction in the number of required drivers provides significant savings in development time. More importantly, SANE raises the level at which applications can work. As such, it will enable applications that were previously unheard of in the UNIX world. While SANE is primarily targeted at a UNIX environment, the standard has been carefully designed to make it possible to implement the API on virtually any hardware or operating system. SANE is an acronym for ``Scanner Access Now Easy.'' Also, the hope is that SANE is sane in the sense that it will allow easy implementation of the API while accommodating all features required by today's scanner hardware and applications. Specifically, SANE should be broad enough to accommodate devices such as scanners, digital still and video cameras, as well as virtual devices like image file filters. \section{Terminology} An application that uses the SANE interface is called a SANE {\em frontend}. A driver that implements the SANE interface is called a SANE {\em backend}. A {\em meta backend\/} provides some means to manage one or more other backends. \chapter{The SANE Environment}\label{chap:environ} SANE is defined as a C-callable library interface. Accessing a raster scanner device typically consists of two phases: first, various controls of the scanner need to be setup or queried. In the second phase, one or more images are acquired. Since the device controls are widely different from device to device, SANE provides a generic interface that makes it easy for a frontend to give a user access to all controls without having to understand each and every device control. The design principle used here is to abstract each device control into a SANE {\em option\/}. An option is a self-describing name/value pair. For example, the brightness control of a camera might be represented by an option called \code{brightness} whose value is an integer in the range from 0 to 255. With self-describing options, a backend need not be concerned with {\em presentation\/} issues: the backend simply provides a list of options that describe all the controls available in the device. Similarly, there are benefits to the frontend: it need not be concerned with the {\em meaning\/} of each option. It simply provides means to present and alter the options defined by the backend. \section{Attaching to a SANE backend} The process through which a SANE frontend connects to a backend is platform dependent. Several possibilities exist: \begin{itemize} \item {\bf Static linking:} A SANE backend may be linked directly into a frontend. While the simplest method of attaching to a backend, it is somewhat limited in functionality since the available devices is limited to the ones for which support has been linked in when the frontend was built. But even so static linking can be quite useful, particularly when combined with a backend that can access scanners via a network. Also, it is possible to support multiple backends simultaneously by implementing a meta backend that manages several backends that have been compiled in such a manner that they export unique function names. For example, a backend called \code{be} would normally export a function called \code{sane\_read()}. If each backend would provide such a function, static linking would fail due to multiple conflicting definitions of the same symbol. This can be resolved by having backend \code{be} include a header file that has lines of the form: \begin{quote} \begin{verbatim} #define sane_read be_sane_read \end{verbatim} \end{quote} With definitions of this kind, backend \code{be} will export function name \code{be\_sane\_read()}. Thus, all backends will export unique names. As long as a meta backend knows about these names, it is possible to combine several backends at link time and select and use them dynamically at runtime. \item {\bf Dynamic linking:} A simpler yet more powerful way to support multiple backends is to exploit dynamic linking on platforms that support it. In this case, a frontend is linked against a shared library that implements any SANE backend. Since each dynamically linked backend exports the same set of global symbols (all starting with the prefix \code{sane\_}), the dynamic library that gets loaded at runtime does not necessarily have to be the same one as one the frontend got linked against. In other words, it is possible to switch the backend by installing the appropriate backend dynamic library. More importantly, dynamic linking makes it easy to implement a meta backend that loads other backends {\em on demand}. This is a powerful mechanism since it allows adding new backends merely by installing a shared library and updating a configuration file. \item {\bf Network connection:} Arguably the ultimate way to attach to a scanner is by using the network to connect to a backend on a remote machine. This makes it possible to scan images from any host in the universe, as long as there is a network connection to that host and provided the user is permitted to access that scanner. \end{itemize} \begin{figure}[htbp] \begin{center} \leavevmode \includegraphics[width=\textwidth]{figs/hierarchy} \caption{Example SANE Hiearchy} \label{fig:hierarchy} \end{center} \end{figure} The above discussion lists just a few ways for frontends to attach to a backend. It is of course possible to combine these solutions to provide an entire hierarchy of SANE backends. Such a hierarchy is depicted in Figure~\ref{fig:hierarchy}. The figure shows that machine A uses a dynamic-linking based meta backend called \code{dll} to access the backends called \code{pnm}, \code{mustek}, and \code{net}. The first two are real backends, whereas the last one is a meta backend that provides network transparent access to remote scanners. In the figure, machine B provides non-local access to its scanners through the SANE frontend called \code{saned}. The \code{saned} in turn has access to the \code{hp} and \code{autolum} backends through another instance of the \code{dll} backend. The \code{autolum} meta backend is used to automatically adjust the luminance (brightness) of the image data acquired by the camera backend called \code{qcam}. Note that a meta backend really is both a frontend and a backend at the same time. It is a frontend from the viewpoint of the backends that it manages and a backend from the viewpoint of the frontends that access it. The name ``meta backend'' was chosen primarily because the SANE standard describes the interface from the viewpoint of a (real) frontend. \section{Image Data Format}\label{sec:imageformat}\index{image data format} Arguably the most important aspect of an image acquisition system is how images are represented. The SANE approach is to define a simple yet powerful representation that is sufficient for vast majority of applications and devices. While the representation is simple, the interface has been defined carefully to allow extending it in the future without breaking backwards compatibility. Thus, it will be possible to accommodate future applications or devices that were not anticipated at the time this standard was created. A SANE image is a rectangular area. The rectangular area is subdivided into a number of rows and columns. At the intersection of each row and column is a quadratic pixel. A pixel consists of one or more sample values. Each sample value represents one channel (e.g., the red channel). Each sample value has a certain bit depth. The bit depth is fixed for the entire image and can be as small as one bit. Valid bit depths are 1, 8, or 16 bits per sample. If a device's natural bit depth is something else, it is up to the driver to scale the sample values appropriately (e.g., a 4 bit sample could be scaled by a factor of four to represent a sample value of depth 8). \subsection{Image Transmission} The SANE API transmits an image as a sequence of frames. Each frame covers the same rectangular area as the entire image, but may contain only a subset of the channels in the final image. For example, a red/green/blue image could either be transmitted as a single frame that contains the sample values for all three channels or it could be transmitted as a sequence of three frames: the first frame containing the red channel, the second the green channel, and the third the blue channel. Conceptually, each frame is transmitted a byte at a time. Each byte may contain 8 sample values (for an image bit depth of 1), one full sample value (for an image bit depth of 8), or a partial sample value (for an image bit depth of 16 or bigger). In the latter case, the bytes of each sample value are transmitted in the machine's native byte order. For depth 1, the leftmost pixel is stored in the most significant bit, and the rightmost pixel in the least significant bit. \begin{quote} \begin{center} {\bf Backend Implementation Note} \end{center} A network-based meta backend will have to ensure that the byte order in image data is adjusted appropriately if necessary. For example, when the meta backend attaches to the server proxy, the proxy may inform the backend of the server's byte order. The backend can then apply the adjustment if necessary. In essence, this implements a ``receiver-makes-right'' approach. \end{quote} \begin{figure}[htbp] \begin{center} \leavevmode \includegraphics[width=0.5\textwidth]{figs/xfer} \caption{Transfer order of image data bytes} \label{fig:xfer} \end{center} \end{figure} The order in which the sample values in a frame are transmitted is illustrated in Figure~\ref{fig:xfer}. As can be seen, the values are transmitted row by row and each row is transmitted from left-most to right-most column. The left-to-right, top-to-bottom transmission order applies when the image is viewed in its normal orientation (as it would be displayed on a screen, for example). If a frame contains multiple channels, then the channels are transmitted in an interleaved fashion. Figure~\ref{fig:pixels} illustrates this for the case where a frame contains a complete red/green/blue image with a bit-depth of 8. For a bit depth of 1, each byte contains 8 sample values of a {\em single\/} channel. In other words, a bit depth 1 frame is transmitted in a byte interleaved fashion. \begin{figure}[htbp] \begin{center} \leavevmode \includegraphics[width=0.8\textwidth]{figs/image-data} \caption{Bit and byte order or image data} \label{fig:pixels} \end{center} \end{figure} When transmitting an image frame by frame, the frontend needs to know what part of the image a frame represents (and how many frames it should expect). For that purpose, the SANE API tags every frame with a type. This version of the SANE standard supports the following frame types: \begin{quote} \begin{description} \item[\code{\defn{SANE\_FRAME\_GRAY}}:] The frame contains a single channel of data that represents sample values from a spectral band that covers the human visual range. The image consists of this frame only. \item[\code{\defn{SANE\_FRAME\_RGB}}:] The frame contains three channels of data that represent sample values from the red, green, and blue spectral bands. The sample values are interleaved in the order red, green, and blue. The image consists of this frame only. \item[\code{\defn{SANE\_FRAME\_RED}}:] The frame contains one channel of data that represents sample values from the red spectral band. The complete image consists of three frames: \code{SANE\_\-FRA\-ME\_RED}, \code{SANE\_FRAME\_GREEN}, and \code{SANE\_FRAME\_BLUE}. The order in which the frames are transmitted chosen by the backend. \item[\code{\defn{SANE\_FRAME\_GREEN}}:] The frame contains one channel of data that represents sample values from the green spectral band. The complete image consists of three frames: \code{SANE\_\-FRA\-ME\_RED}, \code{SANE\_FRAME\_GREEN}, and \code{SANE\_FRAME\_BLUE}. The order in which the frames are transmitted chosen by the backend. \item[\code{\defn{SANE\_FRAME\_BLUE}}:] The frame contains one channel of data that represents sample values from the blue spectral band. The complete image consists of three frames: \code{SANE\_\-FRA\-ME\_RED}, \code{SANE\_FRAME\_GREEN}, and \code{SANE\_FRAME\_BLUE}. The order in which the frames are transmitted chosen by the backend. \end{description} \end{quote} In frames of type \code{SANE\_FRAME\_GRAY}, when the bit depth is 1 there are only two sample values possible, 1 represents minimum intensity (black) and 0 represents maximum intensity (white). For all other bit depth and frame type combinations, a sample value of 0 represents minimum intensity and larger values represent increasing intensity. The combination of bit depth 1 and \code{SANE\_FRAME\_RGB} (or \code{SANE\_FRAME\_RED}, \code{SANE\_FRAME\_GREEN}, \code{SANE\_FRAME\_BLUE}) is rarely used and may not be supported by every frontend. \chapter{The SANE Application Programmer Interface (API)}\label{chap:api} This Section defines version 1 of the SANE application programmer interface (API). Any SANE frontend must depend on the interface defined in this section only. Converseley, any SANE backend must implement its functionality in accordance with this specification. The interface as documented here is declared as a C callable interface in a file called \filename{sane/sane.h}. This file should normally be included via a C pre-processor directive of the form: \begin{verbatim} #include \end{verbatim} \section{Version Control} The SANE standard is expected to evolve over time. Whenever a change to the SANE standard is made that may render an existing frontend or backend incompatible with the new standard, the major version number must be increased. Thus, any frontend/backend pair is compatible provided the major version number of the SANE standard they implement is the same. A frontend may implement backwards compatiblity by allowing major numbers that are smaller than the expected major number (provided the frontend really can cope with the older version). In contrast, a backend always provides support for one and only one version of the standard. If a specific application does require that two different versions of the same backend are accessible at the same time, it is possible to do so by installing the two versions under different names. SANE version control also includes a minor version number and a build revision. While control of these numbers remains with the implementor of a backend, the recommended use is as follows. The minor version is incremented with each official release of a backend. The build revision is increased with each build of a backend. The SANE API provides the following five macros to manage version numbers. \begin{quote} \begin{description} \item[\code{\defn{SANE\_CURRENT\_MAJOR}}:] The value of this macro is the number of the SANE standard that the interface implements. \item[\code{\defn{SANE\_VERSION\_CODE}(\var{maj},\var{min},\var{bld})}:] \label{sec:saneversioncode} This macro can be used to build a monotonically increasing version code. A SANE version code consists of the SANE standard major version number (\var{maj}), the minor version number \var{min}, and the build revision of a backend (\var{bld}). The major and minor version numbers must be in the range 0\ldots255 and the build revision must be in the range 0\ldots65535. Version codes are monotonic in the sense that it is possible to apply relational operators (e.g., equality or less-than test) directly on the version code rather than individually on the three components of the version code. Note that the major version number alone determines whether a frontend/backend pair is compatible. The minor version and the build revision are used for informational and bug-fixing purposes only. \item[\code{\defn{SANE\_VERSION\_MAJOR}(\var{vc})}:] This macro returns the major version number component of the version code passed in argument \var{vc}. \item[\code{SANE\_VERSION\_MINOR(\var{vc})}:] This macro returns the minor version number component of the version code passed in argument \var{vc}. \item[\code{SANE\_VERSION\_BUILD(\var{vc})}:] This macro returns the build revision component of the version code passed in argument \var{vc}. \end{description} \end{quote} \section{Data Types} \subsection{Base Types} The SANE standard is based on just two SANE-specific base types: the SANE byte and word. \begin{quote} \code{typedef \var{some-scalar-type\/} \defn{SANE\_Byte};} \\ \code{typedef \var{some-scalar-type\/} \defn{SANE\_Word};} \end{quote} \verb|SANE_Byte| must correspond to some scalar C type that is capable of holding values in the range 0 to 255. \verb|SANE_Word| must be capable of holding any of the following: \begin{itemize} \item the truth values \verb|SANE_FALSE| and \verb|SANE_TRUE| \item signed integers in the range $-2^{31}\ldots2^{31}-1$ \item fixed point values in the range $-32768\ldots32767.9999$ with a resolution of $1/65536$ \item 32 bits (for bit sets) \end{itemize} Note that the SANE standard does not define what C type \verb|SANE_Byte| and \verb|SANE_Word| map to. For example, on some platforms, the latter may map to \verb|long int| whereas on others it may map to \verb|int|. A portable SANE frontend or backend must therefore not depend on a particular mapping. \subsection{Boolean Type} \code{\defn{SANE\_Bool}} is used for variables that can take one of the two truth values \code{\defn{SANE\_FALSE}} and \code{\defn{SANE\_TRUE}}. The former value is defined to be 0, whereas the latter is 1.\footnote{This is different from ANSI C where any non-zero integer value represents logical TRUE.} The C declarations for this type are given below. \begin{quote} \begin{verbatim} #define SANE_FALSE 0 #define SANE_TRUE 1 typedef SANE_Word SANE_Bool; \end{verbatim} \end{quote} Note that \verb|SANE_Bool| is simply an alias of \verb|SANE_Word|. It is therefore always legal to use the latter type in place of the former. However, for clarity, it is recommended to use \verb|SANE_Bool| whenever a given variable or formal argument has a fixed interpretation as a boolean object. \subsection{Integer Type} \code{\defn{SANE\_Int}} is used for variables that can take integer values in the range $-2^{32}$ to $2^{31}-1$. Its C declaration is given below. \begin{quote} \begin{verbatim} typedef SANE_Word SANE_Int; \end{verbatim} \end{quote} Note that \verb|SANE_Int| is simply an alias of \verb|SANE_Word|. It is therefore always legal to use the latter type in place of the former. However, for clarity, it is recommended to use \verb|SANE_Int| whenever a given variable or formal argument has a fixed interpretation as an integer object. \subsection{Fixed-point Type} \code{\defn{SANE\_Fixed}} is used for variables that can take fixed point values in the range $-32768$ to $32767.9999$ with a resolution of $1/65535$. The C declarations relating to this type are given below. \begin{quote} \begin{verbatim} #define SANE_FIXED_SCALE_SHIFT 16 typedef SANE_Word SANE_Fixed; \end{verbatim} \end{quote} The macro \code{\defn{SANE\_FIXED\_SCALE\_SHIFT}} gives the location of the fixed binary point. This standard defines that value to be 16, which yields a resolution of $1/65536$. Note that \verb|SANE_Fixed| is simply an alias of \verb|SANE_Word|. It is therefore always legal to use the latter type in place of the former. However, for clarity, it is recommended to use \verb|SANE_Fixed| whenever a given variable or formal argument has a fixed interpretation as a fixed-point object. For convenience, SANE also defines two macros that convert fixed-point values to and from C double floating point values. \begin{quote} \begin{description} \item[\code{\defn{SANE\_FIX}(\var{d})}:] Returns the largest SANE fixed-point value that is smaller than the double value \var{d}. No range checking is performed. If the value of \var{d} is out of range, the result is undefined. \item[\code{\defn{SANE\_UNFIX}(\var{w})}:] Returns the nearest double machine number that corresponds to fixed-point value \var{w}. \end{description} \end{quote} SANE does {\em not\/} require that the following two expressions hold true (even if the values of \var{w} and \var{d} are in range): \begin{quote} \begin{verbatim} SANE_UNFIX(SANE_FIX(d)) == d SANE_FIX(SANE_UNFIX(w)) == w \end{verbatim} \end{quote} In other words, conversion between fixed and double values may be lossy. It is therefore recommended to avoid repeated conversions between the two representations. \subsection{Text} \subsubsection{Character Type} Type \code{\defn{SANE\_Char}} represents a single text character or symbol. At present, this type maps directly to the underlying C \verb|char| type (typically one byte). The encoding for such characters is currently fixed as ISO LATIN-1. Future versions of this standard may map this type to a wider type and allow multi-byte encodings to support internationalization. As a result of this, care should be taken to avoid the assumption that \verb|sizeof(SANE_Char)==sizeof(char)|. \begin{quote} \begin{verbatim} typedef char SANE_Char; \end{verbatim} \end{quote} \subsubsection{String Type} Type \code{\defn{SANE\_String}} represents a text string as a sequence of C \verb|char| values. The end of the sequence is indicated by a \verb|'\0'| (\defn{NUL}) character. \begin{quote} \begin{verbatim} typedef SANE_Char *SANE_String; typedef const SANE_Char *SANE_String_Const; \end{verbatim} \end{quote} The type \code{\defn{SANE\_String\_Const}} is provided by SANE to enable declaring strings whose contents is unchangable. Note that in ANSI C, the declaration \begin{quote} \begin{verbatim} const SANE_String str; \end{verbatim} \end{quote} declares a string pointer that is constant (not a string pointer that points to a constant value). \subsection{Scanner Handle Type} Access to a scanner is provided through an opaque type called \code{\defn{SANE\_Handle}}. The C declaration of this type is given below. \begin{quote} \begin{verbatim} typedef void *SANE_Handle; \end{verbatim} \end{quote} While this type is declared to be a void pointer, an application must not attempt to interpret the value of a \verb|SANE_Handle|. In particular, SANE does not require that a value of this type is a legal pointer value. \subsection{Status Type} Most SANE operations return a value of type \code{\defn{SANE\_Status}} to indicate whether the completion status of the operation. If an operation completes successfully, \verb|SANE_STATUS_GOOD| is returned. In case of an error, a value is returned that indicates the nature of the problem. The complete list of available status codes is listed in Table \ref{tab:status}. It is recommended to use function \code{sane\_strstatus()} to convert status codes into a legible string. \begin{table}[htbp] \begin{center} \begin{tabular}{|l|r|l|} \hline \multicolumn{1}{|c|}{\bf Symbol} & \multicolumn{1}{c|}{\bf Code} & \multicolumn{1}{c|}{\bf Description} \\ \hline\hline \code{\defn{SANE\_STATUS\_GOOD}} & 0 & Operation completed succesfully. \\ \code{\defn{SANE\_STATUS\_UNSUPPORTED}} & 1 & Operation is not supported. \\ \code{\defn{SANE\_STATUS\_CANCELLED}} & 2 & Operation was cancelled. \\ \code{\defn{SANE\_STATUS\_DEVICE\_BUSY}} & 3 & Device is busy---retry later. \\ \code{\defn{SANE\_STATUS\_INVAL}} & 4 & Data or argument is invalid. \\ \code{\defn{SANE\_STATUS\_EOF}} & 5 & No more data available (end-of-file). \\ \code{\defn{SANE\_STATUS\_JAMMED}} & 6 & Document feeder jammed. \\ \code{\defn{SANE\_STATUS\_NO\_DOCS}} & 7 & Document feeder out of documents. \\ \code{\defn{SANE\_STATUS\_COVER\_OPEN}} & 8 & Scanner cover is open. \\ \code{\defn{SANE\_STATUS\_IO\_ERROR}} & 9 & Error during device I/O. \\ \code{\defn{SANE\_STATUS\_NO\_MEM}} & 10 & Out of memory. \\ \code{\defn{SANE\_STATUS\_ACCESS\_DENIED}} & 11 & Access to resource has been denied. \\ \hline \end{tabular} \caption{Status Codes}\label{tab:status} \end{center} \end{table} \subsection{Device Descriptor Type} Each SANE device is represented by a structure of type \code{\defn{SANE\_Device}}. The C declaration of this type is given below. \begin{quote} \begin{verbatim} typedef struct { SANE_String_Const name; SANE_String_Const vendor; SANE_String_Const model; SANE_String_Const type; } SANE_Device; \end{verbatim} \end{quote} \index{device-name} The structure provides the unique name of the scanner in member \code{name}. It is this unique name that should be passed in a call to \code{sane\_open()}. The format of this name is completely up to the backend. The only constraints are that the name is unique among all devices supported by the backend and that the name is a legal SANE text string. To simplify presentation of unique names, their length should not be excessive. It is {\em recommended\/} that backends keep unique names below 32 characters in length. However, applications {\em must\/} be able to cope with arbitrary length unique names. The remaining members in the device structure provide additional information on the device corresponding to the unique name. Specifically, members \code{vendor}, \code{model}, and \code{type} are single-line strings that give information on the vendor (manufacturer), model, and the type of the device. For consistency's sake, the following strings should be used when appropriate (the lists will be expanded as need arises): \begin{table}[htbp] \begin{center} \leavevmode \hspace{\fill} \begin{tabular}[t]{|ll|} \hline \multicolumn{2}{|c|}{\bf \defn{Vendor Strings}} \\ \hline\hline \code{AGFA} & \code{Microtek} \\ \code{Abaton} & \code{Minolta} \\ \code{Acer} & \code{Mitsubishi} \\ \code{Apple} & \code{Mustek} \\ \code{Artec} & \code{NEC} \\ \code{Avision} & \code{Nikon} \\ \code{CANON} & \code{Plustek} \\ \code{Connectix} & \code{Polaroid} \\ \code{Epson} & \code{Relisys} \\ \code{Fujitsu} & \code{Ricoh} \\ \code{Hewlett-Packard} & \code{Sharp} \\ \code{IBM} & \code{Siemens} \\ \code{Kodak} & \code{Tamarack} \\ \code{Lexmark} & \code{UMAX} \\ \code{Logitech} & \code{Noname} \\ \hline \end{tabular} \hspace{\fill} \begin{tabular}[t]{|l|} \hline \multicolumn{1}{|c|}{\bf \defn{Type Strings}} \\ \hline\hline \code{film scanner} \\ \code{flatbed scanner} \\ \code{frame grabber} \\ \code{handheld scanner} \\ \code{multi-function peripheral} \\ \code{sheetfed scanner} \\ \code{still camera} \\ \code{video camera} \\ \code{virtual device} \\ \hline \end{tabular} \hspace{\fill} \caption{Predefined Device Information Strings} \label{tab:devinfo} \end{center} \end{table} Note that vendor string \code{Noname} can be used for virtual devices that have no physical vendor associated. Also, there are no predefined model name strings since those are vendor specific and therefore completely under control of the respective backends. \subsection{Option Descriptor Type}\label{sec:odesc} Option descriptors are at the same time the most intricate and powerful type in the SANE standard. Options are used to control virtually all aspects of device operation. Much of the power of the SANE API stems from the fact that most device controls are completely described by their respective option descriptor. Thus, a frontend can control a scanner abstractly, without requiring knowledge as to what the purpose of any given option is. Conversely, a scanner can describe its controls without requiring knowledge of how the frontend operates. The C declaration of the \code{\defn{SANE\_Option\_Descriptor}} type is given below. \begin{quote} \begin{verbatim} typedef struct { SANE_String_Const name; SANE_String_Const title; SANE_String_Const desc; SANE_Value_Type type; SANE_Unit unit; SANE_Int size; SANE_Int cap; SANE_Constraint_Type constraint_type; union { const SANE_String_Const *string_list; const SANE_Word *word_list; const SANE_Range *range; } constraint; } SANE_Option_Descriptor; \end{verbatim} \end{quote} \subsubsection{Option Name} Member \code{name} is a string that uniquely identifies the option. The name must be unique for a given device (i.e., the option names across different backends or devices need not be unique). The option name must consist of lower-case ASCII letters (\code{a}--\code{z}), digits (\code{0}--\code{9}), or the dash character (\code{-}) only. The first character must be a lower-case ASCII character (i.e., not a digit or a dash). \subsubsection{Option Title} Member \code{title} is a single-line string that can be used by the frontend as a title string. This should typically be a short (one or two-word) string that is chosen based on the function of the option. \subsubsection{Option Description} Member \code{desc} is a (potentially very) long string that can be used as a help text to describe the option. It is the responsibility of the frontend to break the string into managable-length lines. Newline characters in this string should be interpreted as paragraph breaks. \subsubsection{Option Value Type} Member \code{type} specifies the type of the option value. The possible values for type \code{\defn{SANE\_Value\_Type}} are described in Table \ref{tab:valuetype}. \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{|l|l|p{0.6\textwidth}|} \hline \multicolumn{1}{|c|}{\bf Symbol} & \multicolumn{1}{c|}{\bf Code} & \multicolumn{1}{c|}{\bf Description} \\ \hline\hline \code{\defn{SANE\_TYPE\_BOOL}} & 0 & Option value is of type \verb|SANE_Bool|. \\ \code{\defn{SANE\_TYPE\_INT}} & 1 & Option value is of type \verb|SANE_Int|. \\ \code{\defn{SANE\_TYPE\_FIXED}}&2 & Option value is of type \verb|SANE_Fixed|. \\ \code{\defn{SANE\_TYPE\_STRING}}&3 & Option value is of type \verb|SANE_String|. \\ \code{\defn{SANE\_TYPE\_BUTTON}} & 4 & An option of this type has no value. Instead, setting an option of this type has an option-specific side-effect. For example, a button-typed option could be used by a backend to provide a means to select default values or to the tell an automatic document feeder to advance to the next sheet of paper. \\ \code{\defn{SANE\_TYPE\_GROUP}} & 5 & An option of this type has no value. This type is used to group logically related options. A group option is in effect up to the point where another group option is encountered (or up to the end of the option list, if there are no other group options). For group options, only members \code{title} and \code{type} are valid in the option descriptor. \\ \hline \end{tabular} \caption{Option Value Types (\code{SANE\_Value\_Type})} \label{tab:valuetype} \end{center} \end{table} \subsubsection{Option Value Unit} Member \code{unit} specifies what the physical unit of the option value is. The possible values for type \code{\defn{SANE\_U\-nit}} are described in Table \ref{tab:units}. Note that the specified unit is what the SANE backend expects. It is entirely up to a frontend as to how these units a presented to the user. For example, SANE expresses all lengths in millimeters. A frontend is generally expected to provide appropriate conversion routines so that a user can express quantities in a customary unit (e.g., inches or centimeters). \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{|l|l|l|} \hline \multicolumn{1}{|c|}{\bf Symbol} & \multicolumn{1}{|c|}{\bf Code} & \multicolumn{1}{|c|}{\bf Description} \\ \hline\hline \code{\defn{SANE\_UNIT\_NONE}} & 0 & Value is unit-less (e.g., page count).\\ \code{\defn{SANE\_UNIT\_PIXEL}} & 1 & Value is in number of pixels. \\ \code{\defn{SANE\_UNIT\_BIT}} & 2 & Value is in number of bits. \\ \code{\defn{SANE\_UNIT\_MM}} & 3 & Value is in millimeters. \\ \code{\defn{SANE\_UNIT\_DPI}} & 4 & Value is a resolution in dots/inch. \\ \code{\defn{SANE\_UNIT\_PERCENT}}& 5 & Value is a percentage. \\ \code{\defn{SANE\_UNIT\_MICROSECOND}}& 6 & Value is time in $\mu$-seconds. \\ \hline \end{tabular} \caption{Physical Units (\code{SANE\_Unit})} \label{tab:units} \end{center} \end{table} \subsubsection{Option Value Size}\label{sec:valuesize} Member \code{size} specifies the size of the option value (in bytes). This member has a slightly different interpretation depending on the type of the option value: \begin{quote} \begin{description} \item[\code{SANE\_TYPE\_STRING}:] The size is the maximum size of the string. For the purpose of string size calcuations, the terminating \code{NUL} character is considered to be part of the string. Note that the terminating \code{NUL} character must always be present in string option values. \item[\code{SANE\_TYPE\_INT}, \code{SANE\_TYPE\_FIXED}:] The size must be a positive integer multiple of the size of a \verb|SANE_Word|. The option value is a vector of length \[ \code{size}/\code{sizeof(SANE\_Word)}. \] \item[\code{SANE\_TYPE\_BOOL}:] The size must be set to \code{sizeof(SANE\_Word)}. \item[\code{SANE\_TYPE\_BUTTON}, \code{SANE\_TYPE\_GROUP}:] The option size is ignored. \end{description} \end{quote} \subsubsection{Option Capabilities} Member \code{cap} describes what capabilities the option posseses. This is a bitset that is formed as the inclusive logical OR of the capabilities described in Table \ref{tab:capabilities}. The SANE API provides the following to macros to test certain features of a given capability bitset: \begin{quote} \begin{description} \item[\code{\defn{SANE\_OPTION\_IS\_ACTIVE}(\var{cap})}:] This macro returns \code{SANE\_TRUE} if and only if the option with the capability set \var{cap} is currently active. \item[\code{\defn{SANE\_OPTION\_IS\_SETTABLE}(\var{cap})}:] This macro returns \code{SANE\_TRUE} if and only if the option with the capability set \var{cap} is software settable. \end{description} \end{quote} \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{|l|r|p{0.59\textwidth}|} \hline \multicolumn{1}{|c|}{\bf Symbol} & \multicolumn{1}{c|}{\bf Code} & \multicolumn{1}{c|}{\bf Description} \\ \hline\hline \code{\defn{SANE\_CAP\_SOFT\_SELECT}} & 1 & The option value can be set by a call to \code{sane\_con\-trol\_opt\-ion()}.\\ \code{\defn{SANE\_CAP\_HARD\_SELECT}} & 2 & The option value can be set by user-intervention (e.g., by flipping a switch). The user-interface should prompt the user to execute the appropriate action to set such an option. This capability is mutually exclusive with SANE\_CAP\_SOFT\_SELECT (either one of them can be set, but not both simultaneously). \\ \code{\defn{SANE\_CAP\_SOFT\_DETECT}} & 4 & The option value can be detected by software. If \code{SANE\_\-CAP\_\-SO\-FT\_SEL\-ECT} is set, this capability {\em must\/} be set. If \code{SANE\_CAP\_HARD\_SELECT} is set, this capability may or may not be set. If this capability is set but neither \code{SANE\_CAP\_SO\-FT\_SEL\-ECT} nor \code{SANE\_CAP\_HA\-RD\_SEL\-ECT} are, then there is no way to control the option. That is, the option provides read-out of the current value only. \\ \code{\defn{SANE\_CAP\_EMULATED}} & 8 & If set, this capability indicates that an option is not directly supported by the device and is instead emulated in the backend. A sophisticated frontend may elect to use its own (presumably better) emulation in lieu of an emulated option. \\ \code{\defn{SANE\_CAP\_AUTOMATIC}} & 16 & If set, this capability indicates that the backend (or the device) is capable to picking a reasonable option value automatically. For such options, it is possible to select automatic operation by calling \code{sane\_control\_option()} with an action value of \code{SANE\_ACTION\_SET\_AUTO}. \\ \code{\defn{SANE\_CAP\_INACTIVE}} & 32 & If set, this capability indicates that the option is not currently active (e.g., because it's meaningful only if another option is set to some other value). \\ \code{\defn{SANE\_CAP\_ADVANCED}} & 64 & If set, this capability indicates that the option should be considered an ``advanced user option.'' A frontend typically displays such options in a less conspicuous way than regular options (e.g., a command line interface may list such options last or a graphical interface may make them available in a seperate ``advanced settings'' dialog). \\ \hline \end{tabular} \caption{Option Capabilities} \label{tab:capabilities} \end{center} \end{table} \subsubsection{Option Value Constraints} It is often useful to constrain the values that an option can take. For example, constraints can be used by a frontend to determine how to represent a given option. Member \code{constraint\_type} indicates what constraint is in effect for the option. The constrained values that are allowed for the option are described by one of the union members of member \code{constraint}. The possible values of type \code{\defn{SANE\_Constraint\_Type}} and the interpretation of the \code{constraint} union is described in Table~\ref{tab:constraints}. \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{|l|r|p{0.5\textwidth}|} \hline \multicolumn{1}{|c|}{\bf Symbol} & \multicolumn{1}{|c|}{\bf Code} & \multicolumn{1}{|c|}{\bf Description} \\ \hline\hline \code{\defn{SANE\_CONSTRAINT\_NONE}} & 0 & The value is unconstrained. The option can take any of the values possible for the option's type. \\ \code{\defn{SANE\_CONSTRAINT\_RANGE}} & 1 & This constraint is applicable to integer and fixed-point valued options only. It constrains the option value to a possibly quantized range of numbers. Option descriptor member \code{constraint.range} points to a range of the type \code{\defn{SANE\_Range}}. This type is illustrated below: \begin{quote} \begin{verbatim} typedef struct { SANE_Word min; SANE_Word max; SANE_Word quant; } SANE_Range; \end{verbatim} \end{quote} All three members in this structure are interpreted according to the option value type (\verb|SANE_TYPE_INT| or \verb|SANE_TYPE_FIXED|). Members \code{min} and \code{max} specify the minimum and maximum values, respectively. If member \code{quant} is non-zero, it specifies the quantization value. If $l$ is the minimum value, $u$ the maximum value and $q$ the (non-zero) quantization of a range, then the legal values are $v=k\cdot q+l$ for all non-negative integer values of $k$ such that $v<=u$. \\ \code{\defn{SANE\_CONSTRAINT\_WORD\_LIST}} & 2 & This constraint is applicable to integer and fixed-point valued options only. It constrains the option value to a list of numeric values. Option descriptor member \code{constraint.word\_list} points to a list of words that enumerates the legal values. The first element in that list is an integer (\verb|SANE_Int|) that specifies the length of the list (not counting the length itself). The remaining elements in the list are interpreted according to the type of the option value (\verb|SANE_TYPE_INT| or \verb|SANE_TYPE_FIXED|). \\ \code{\defn{SANE\_CONSTRAINT\_STRING\_LIST}} & 3 & This constraint is applicable to string-valued options only. It constrains the option value to a list of strings. The option descriptor member \code{con\-strai\-nt.str\-ing\_list} points to a \code{NULL} terminated list of strings that enumerate the legal values for the option value. \\\hline \end{tabular} \caption{Option Value Constraints} \label{tab:constraints} \end{center} \end{table} \section{Operations} \subsection{\code{sane\_init}} This function must be called before any other SANE function can be called. The behavior of a SANE backend is undefined if this function is not called first or if the status code returned by \code{sane\_init} is different from \code{\defn{SANE\_STATUS\_GOOD}}. The version code of the backend is returned in the value pointed to by \code{version\_code}. If that pointer is \code{NULL}, no version code is returned. Argument \code{authorize} is either a pointer to a function that is invoked when the backend requires authentication for a specific resource or \code{NULL} if the frontend does not support authentication. \begin{quote}\index{sane\_init} \begin{verbatim} SANE_Status sane_init (SANE_Int * version_code, SANE_Authorization_Callback authorize); \end{verbatim} \end{quote} The authorization function may be called by a backend in response to any of the following calls: \begin{quote} \code{sane\_open}, \code{sane\_control\_option}, \code{sane\_start} \end{quote} If a backend was initialized without authorization function, then authorization requests that cannot be handled by the backend itself will fail automatically and the user may be prevented from accessing protected resources. Backends are encouraged to implement means of authentication that do not require user assistance. E.g., on a multi-user system that authenticates users through a login process a backend could automatically lookup the apporpriate password based on resource- and user-name. The authentication function type has the following declaration: \begin{quote}\index{SANE\_Authorization\_Callback} \index{domain}\index{username}\index{password} \begin{verbatim} #define SANE_MAX_USERNAME_LEN 128 #define SANE_MAX_PASSWORD_LEN 128 typedef void (*SANE_Authorization_Callback) (SANE_String_Const resource, SANE_Char username[SANE_MAX_USERNAME_LEN], SANE_Char password[SANE_MAX_PASSWORD_LEN]); \end{verbatim} \end{quote} Three arguments are passed to the authorization function: \code{resource} is a string specifying the name of the resource that requires authorization. A frontend should use this string to build a user-prompt requesting a username and a password. The \code{username} and \code{password} arguments are (pointers to) an array of \code{SANE\_MAX\_USERNAME\_LEN} and \code{SANE\_MAX\_PASSWORD\_LEN} characters, respectively. The authorization call should place the entered username and password in these arrays. The returned strings {\em must\/} be ASCII-NUL terminated. \subsection{\code{sane\_exit}} This function must be called to terminate use of a backend. The function will first close all device handles that still might be open (it is recommended to close device handles explicitly through a call to \code{sane\_clo\-se()}, but backends are required to release all resources upon a call to this function). After this function returns, no function other than \code{sane\_init()} may be called (regardless of the status value returned by \code{sane\_exit()}. Neglecting to call this function may result in some resources not being released properly. \begin{quote}\index{sane\_exit} \begin{verbatim} void sane_exit (void); \end{verbatim} \end{quote} \subsection{\code{sane\_get\_devices}} This function can be used to query the list of devices that are available. If the function executes successfully, it stores a pointer to a \code{NULL} terminated array of pointers to \verb|SANE_Device| structures in \code{*device\_list}. The returned list is guaranteed to remain unchanged and valid until (a) another call to this function is performed or (b) a call to \code{sane\_exit()} is performed. This function can be called repeatedly to detect when new devices become available. If argument \code{local\_only} is true, only local devices are returned (devices directly attached to the machine that SANE is running on). If it is false, the device list includes all remote devices that are accessible to the SANE library. \begin{quote}\index{sane\_get\_devices} \begin{verbatim} SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); \end{verbatim} \end{quote} This function may fail with \code{SANE\_STATUS\_NO\_MEM} if an insufficient amount of memory is available. \begin{quote} \begin{center} {\bf Backend Implementation Note} \end{center} SANE does not require that this function is called before a \code{sane\_open()} call is performed. A device name may be specified explicitly by a user which would make it unnecessary and undesirable to call this function first. \end{quote} \subsection{\code{sane\_open}} This function is used to establish a connection to a particular device. The name of the device to be opened is passed in argument \code{name}. If the call completes successfully, a handle for the device is returned in \code{*h}. As a special case, specifying a zero-length string as the device requests opening the first available device (if there is such a device). \begin{quote}\index{sane\_open} \begin{verbatim} SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h); \end{verbatim} \end{quote} This function may fail with one of the following status codes. \begin{quote} \begin{description} \item[\code{SANE\_STATUS\_DEVICE\_BUSY}:] The device is currently busy (in use by somebody else). \item[\code{SANE\_STATUS\_INVAL}:] The device name is not valid. \item[\code{SANE\_STATUS\_IO\_ERROR}:] An error occured while communicating with the device. \item[\code{SANE\_STATUS\_NO\_MEM}:] An insufficent amount of memory is available. \item[\code{SANE\_STATUS\_ACCESS\_DENIED}:] Access to the device has been denied due to insufficient or invalid authentication. \end{description} \end{quote} \subsection{\code{sane\_close}} This function terminates the association between the device handle passed in argument \code{h} and the device it represents. If the device is presently active, a call to \code{sane\_cancel()} is performed first. After this function returns, handle \code{h} must not be used anymore. \begin{quote}\index{sane\_close} \begin{verbatim} void sane_close (SANE_Handle h); \end{verbatim} \end{quote} \subsection{\code{sane\_get\_option\_descriptor}} This function is used to access option descriptors. The function returns the option descriptor for option number \code{n} of the device represented by handle \code{h}. Option number 0 is guaranteed to be a valid option. Its value is an integer that specifies the number of options that are available for device handle \code{h} (the count includes option 0). If $n$ is not a valid option index, the function returns \code{NULL}. The returned option descriptor is guaranteed to remain valid (and at the returned address) until the device is closed. \begin{quote}\index{sane\_get\_option\_descriptor} \begin{verbatim} const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int n); \end{verbatim} \end{quote} \subsection{\code{sane\_control\_option}}\label{sec:control} This function is used to set or inquire the current value of option number \code{n} of the device represented by handle \code{h}. The manner in which the option is controlled is specified by parameter \code{a}. The possible values of this parameter are described in more detail below. The value of the option is passed through argument \code{v}. It is a pointer to the memory that holds the option value. The memory area pointed to by \code{v} must be big enough to hold the entire option value (determined by member \code{size} in the corresponding option descriptor). The only exception to this rule is that when setting the value of a string option, the string pointed to by argument \code{v} may be shorter since the backend will stop reading the option value upon encountering the first \code{NUL} terminator in the string. If argument \code{i} is not \code{NULL}, the value of \code{*i} will be set to provide details on how well the request has been met. The meaning of this argument is described in more detail below. \begin{quote}\index{sane\_control\_option} \begin{verbatim} SANE_Status sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int * i); \end{verbatim} \end{quote} The way the option is affected by a call to this function is controlled by parameter \code{a} which is a value of type \code{\defn{SANE\_Action}}. The possible values and their meaning is described in Table~\ref{tab:actions}. \begin{table}[h] \begin{center} \leavevmode \begin{tabular}{|l|r|p{0.5\textwidth}|} \hline \multicolumn{1}{|c|}{\bf Symbol} & \multicolumn{1}{|c|}{\bf Code} & \multicolumn{1}{|c|}{\bf Description} \\ \hline\hline \code{\defn{SANE\_ACTION\_GET\_VALUE}} & 0 & Get current option value. \\ \code{\defn{SANE\_ACTION\_SET\_VALUE}} & 1 & Set option value. The option value passed through argument \code{v} may be modified by the backend if the value cannot be set exactly. \\ \code{\defn{SANE\_ACTION\_SET\_AUTO}} & 2 & Turn on automatic mode. Backend or device will automatically select an appropriate value. This mode remains effective until overridden by an explicit set value request. The value of parameter \code{v} is completely ignored in this case and may be \code{NULL}. \\ \hline \end{tabular} \caption{Action Values (\code{SANE\_Action})} \label{tab:actions} \end{center} \end{table} After setting a value via an action value of \verb|SANE_ACTION_SET_VALUE|, additional information on how well the request has been met is returned in \code{*i} (if \code{i} is non-\code{NULL}). The returned value is a bitset that may contain any combination of the values described in Table~\ref{tab:info}. \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{|l|r|p{0.5\textwidth}|} \hline \multicolumn{1}{|c|}{\bf Symbol} & \multicolumn{1}{|c|}{\bf Code} & \multicolumn{1}{|c|}{\bf Description} \\ \hline\hline \code{\defn{SANE\_INFO\_INEXACT}} & 1 & This value is returned when setting an option value resulted in a value being selected that does not exactly match the requested value. For example, if a scanner can adjust the resolution in increments of 30dpi only, setting the resolution to 307dpi may result in an actual setting of 300dpi. When this happens, the bitset returned in \code{*i} has this member set. In addition, the option value is modified to reflect the actual (rounded) value that was used by the backend. Note that inexact values are admissible for strings as well. A backend may choose to ``round'' a string to the closest matching legal string for a constrained string value. \\ \code{\defn{SANE\_INFO\_RELOAD\_OPTIONS}} & 2 & The setting of an option may affect the value or availability of one or more {\em other\/} options. When this happens, the SANE backend sets this member in \code{*i} to indicate that the application should reload all options. This member may be set if and only if at least one option changed. \\ \code{\defn{SANE\_INFO\_RELOAD\_PARAMS}} & 4 & The setting of an option may affect the parameter values (see \code{sane\_get\_parameters()}). If setting an option affects the parameter values, this member will be set in \code{*i}. Note that this member may be set even if the parameters did not actually change. However, it is guaranteed that the parameters never change without this member being set. \\ \hline \end{tabular} \caption{Additional Information Returned When Setting an Option} \label{tab:info} \end{center} \end{table} This function may fail with one of the following status codes. \begin{quote} \begin{description} \item[\code{SANE\_STATUS\_UNSUPPORTED}:] The operation is not supported for the specified handle and option number. \item[\code{SANE\_STATUS\_INVAL}:] The option value is not valid. \item[\code{SANE\_STATUS\_IO\_ERROR}:] An error occured while communicating with the device. \item[\code{SANE\_STATUS\_NO\_MEM}:] An insufficent amount of memory is available. \item[\code{SANE\_STATUS\_ACCESS\_DENIED}:] Access to the option has been denied due to insufficient or invalid authentication. \end{description} \end{quote} \subsection{\code{sane\_get\_parameters}} This function is used to obtain the current scan parameters. The returned parameters are guaranteed to be accurate between the time a scan has been started (\code{sane\_start()} has been called) and the completion of that request. Outside of that window, the returned values are best-effort estimates of what the parameters will be when \code{sane\_start()} gets invoked. Calling this function before a scan has actually started allows, for example, to get an estimate of how big the scanned image will be. The parameters passed to this function are the handle \code{h} of the device for which the parameters should be obtained and a pointer \code{p} to a parameter structure. The parameter structure is described in more detail below. \begin{quote}\index{sane\_get\_parameters} \begin{verbatim} SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p); \end{verbatim} \end{quote} The scan parameters are returned in a structure of type \code{\defn{SANE\_Parameters}}. The C declaration of this structure is given below. \begin{quote} \begin{verbatim} typedef struct { SANE_Frame format; SANE_Bool last_frame; SANE_Int bytes_per_line; SANE_Int pixels_per_line; SANE_Int lines; SANE_Int depth; } SANE_Parameters; \end{verbatim} \end{quote} Member \code{format} specifies the format of the next frame to be returned. The possible values for type \code{\defn{SANE\_Frame}} are described in Table~\ref{tab:frameformat}. The meaning of these values is described in more detail in Section~\ref{sec:imageformat}. \begin{table}[htbp] \begin{center} \leavevmode \begin{tabular}{|l|r|l|} \hline \multicolumn{1}{|c|}{\bf Symbol} & \multicolumn{1}{|c|}{\bf Code} & \multicolumn{1}{|c|}{\bf Description} \\ \hline\hline \code{\defn{SANE\_FRAME\_GRAY}} & 0 & Band covering human visual range. \\ \code{\defn{SANE\_FRAME\_RGB}} & 1 & Pixel-interleaved red/green/blue bands. \\ \code{\defn{SANE\_FRAME\_RED}} & 2 & Red band of a red/green/blue image. \\ \code{\defn{SANE\_FRAME\_GREEN}} & 3 & Green band of a red/green/blue image. \\ \code{\defn{SANE\_FRAME\_BLUE}} & 4 & Blue band of a red/green/blue image. \\ \hline \end{tabular} \caption{Frame Format (\code{SANE\_Frame})} \label{tab:frameformat} \end{center} \end{table} Member \code{last\_frame} is set to \code{SANE\_TRUE} if and only if the frame that is currently being acquired (or the frame that will be acquired next if there is no current frame) is the last frame of a multi frame image (e.g., the current frame is the blue component of a red, green, blue image). Member \code{lines} specifies how many scan lines the frame is comprised of. If this value is -1, the number of lines is not known a priori and the frontend should call \code{sane\_read()} until it returns a status of \code{SANE\_STATUS\_EOF}. Member \code{bytes\_per\_line} specifies the number of bytes that comprise one scan line. Member \code{depth} specifies the number of bits per sample. Member \code{pixels\_per\_line} specifies the number of pixels that comprise one scan line. Assume $B$ is the number of channels in the frame, then the bit depth $d$ (as given by member \code{depth}) and the number of pixels per line $n$ (as given by this member \code{pixels\_per\_line}) are related to $c$, the number of bytes per line (as given by member \code{bytes\_per\_line}) as follows: \[ c >= \left\{ \begin{array}{ll} B\cdot \lfloor (n + 7) / 8\rfloor & \mbox{if $d=1$}\\ B\cdot n \cdot d / 8 & \mbox{if $d>1$} \end{array} \right. \] Note that the number of bytes per line can be larger than the minimum value imposed by the right side of this equation. A frontend must be able to properly cope with such ``padded'' image formats. \subsection{\code{sane\_start}} This function initiates aquisition of an image from the device represented by handle \code{h}. \begin{quote}\index{sane\_start} \begin{verbatim} SANE_Status sane_start (SANE_Handle h); \end{verbatim} \end{quote} This function may fail with one of the following status codes. \begin{quote} \begin{description} \item[\code{SANE\_STATUS\_CANCELLED}:] The operation was cancelled through a call to \code{sane\_cancel}. \item[\code{SANE\_STATUS\_DEVICE\_BUSY}:] The device is busy. The operation should be retried later. \item[\code{SANE\_STATUS\_JAMMED}:] The document feeder is jammed. \item[\code{SANE\_STATUS\_NO\_DOCS}:] The document feeder is out of documents. \item[\code{SANE\_STATUS\_COVER\_OPEN}:] The scanner cover is open. \item[\code{SANE\_STATUS\_IO\_ERROR}:] An error occurred while communicating with the device. \item[\code{SANE\_STATUS\_NO\_MEM}:] An insufficent amount of memory is available. \item[\code{SANE\_STATUS\_INVAL}:] The scan cannot be started with the current set of options. The frontend should reload the option descriptors, as if \code{\defn{SANE\_INFO\_RELOAD\_OPTIONS}} had been returned from a call to \code{sane\_control\_option()}, since the device's capabilities may have changed. \end{description} \end{quote} \subsection{\code{sane\_read}} This function is used to read image data from the device represented by handle \code{h}. Argument \code{buf} is a pointer to a memory area that is at least \code{maxlen} bytes long. The number of bytes returned is stored in \code{*len}. A backend must set this to zero when a status other than \code{SANE\_STA\-TUS\_GOOD} is returned. When the call succeeds, the number of bytes returned can be anywhere in the range from 0 to \code{maxlen} bytes. \begin{quote}\index{sane\_read} \begin{verbatim} SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len); \end{verbatim} \end{quote} If this function is called when no data is available, one of two things may happen, depending on the I/O mode that is in effect for handle \code{h}. \begin{enumerate} \item If the device is in blocking I/O mode (the default mode), the call blocks until at least one data byte is available (or until some error occurs). \item If the device is in non-blocking I/O mode, the call returns immediately with status \code{SANE\_STA\-TUS\_GOOD} and with \code{*len} set to zero. \end{enumerate} The I/O mode of handle \code{h} can be set via a call to \code{sane\_set\_io\_mode()}. This function may fail with one of the following status codes. \begin{quote} \begin{description} \item[\code{SANE\_STATUS\_CANCELLED}:] The operation was cancelled through a call to \code{sane\_cancel}. \item[\code{SANE\_STATUS\_EOF}:] No more data is available for the current frame. \item[\code{SANE\_STATUS\_JAMMED}:] The document feeder is jammed. \item[\code{SANE\_STATUS\_NO\_DOCS}:] The document feeder is out of documents. \item[\code{SANE\_STATUS\_COVER\_OPEN}:] The scanner cover is open. \item[\code{SANE\_STATUS\_IO\_ERROR}:] An error occurred while communicating with the device. \item[\code{SANE\_STATUS\_NO\_MEM}:] An insufficent amount of memory is available. \item[\code{SANE\_STATUS\_ACCESS\_DENIED}:] Access to the device has been denied due to insufficient or invalid authentication. \end{description} \end{quote} \subsection{\code{sane\_cancel}} This function is used to immediately or as quickly as possible cancel the currently pending operation of the device represented by handle \code{h}. \begin{quote}\index{sane\_cancel} \begin{verbatim} void sane_cancel (SANE_Handle h); \end{verbatim} \end{quote} This function can be called at any time (as long as handle \code{h} is a valid handle) but usually affects long-running operations only (such as image is acquisition). It is safe to call this function asynchronously (e.g., from within a signal handler). It is important to note that completion of this operaton does {\em not\/} imply that the currently pending operation has been cancelled. It only guarantees that cancellation has been {\em initiated}. Cancellation completes only when the cancelled call returns (typically with a status value of \code{SANE\_STATUS\_CANCELLED}). Since the SANE API does not require any other operations to be re-entrant, this implies that a frontend must {\em not\/} call any other operation until the cancelled operation has returned. \subsection{\code{sane\_set\_io\_mode}} This function is used to set the I/O mode of handle \code{h}. The I/O mode can be either blocking or non-blocking. If argument \code{m} is \code{SANE\_TRUE}, the mode is set to non-blocking mode, otherwise it's set to blocking mode. This function can be called only after a call to \code{sane\_start()} has been performed. \begin{quote}\index{sane\_set\_io\_mode} \begin{verbatim} SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool m); \end{verbatim} \end{quote} By default, newly opened handles operate in blocking mode. A backend may elect not to support non-blocking I/O mode. In such a case the status value \code{SANE\_STATUS\_UNSUPPORTED} is returned. Blocking I/O must be supported by all backends, so calling this function with argument \code{m} set to \code{SANE\_FALSE} is guaranteed to complete successfully. This function may fail with one of the following status codes: \begin{quote} \begin{description} \item[\code{SANE\_STATUS\_INVAL}:] No image acquisition is pending. \item[\code{SANE\_STATUS\_UNSUPPORTED}:] The backend does not support the requested I/O mode. \end{description} \end{quote} \subsection{\code{sane\_get\_select\_fd}} This function is used to obtain a (platform-specific) file-descriptor for handle \code{h} that is readable if and only if image data is available (i.e., when a call to \code{sane\_read()} will return at least one byte of data). If the call completes successfully, the select file-descriptor is returned in \code{*fd}. \begin{quote}\index{sane\_get\_select\_fd} \begin{verbatim} SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int *fd); \end{verbatim} \end{quote} This function can be called only after a call to \code{sane\_start()} has been performed and the returned file-descriptor is guaranteed to remain valid for the duration of the current image acquisition (i.e., until \code{sane\_cancel()} or \code{sane\_start()} get called again or until \code{sane\_read()} returns with status \code{SANE\_STA\-TUS\_EOF}). Indeed, a backend must guarantee to close the returned select file descriptor at the point when the next \code{sane\_read()} call would return \code{SANE\_STA\-TUS\_EOF}. This is necessary to ensure the application can detect when this condition occurs without actually having to call \code{sane\_read()}. A backend may elect not to support this operation. In such a case, the function returns with status code \code{SANE\_STATUS\_UNSUPPORTED}. Note that the only operation supported by the returned file-descriptor is a host operating-system dependent test whether the file-descriptor is readable (e.g., this test can be implemented using \code{select()} or \code{poll()} under UNIX). If any other operation is performed on the file descriptor, the behavior of the backend becomes unpredictable. Once the file-descriptor signals ``readable'' status, it will remain in that state until a call to \code{sane\_read()} is performed. Since many input devices are very slow, support for this operation is strongly encouraged as it permits an application to do other work while image acquisition is in progress. This function may fail with one of the following status codes: \begin{quote} \begin{description} \item[\code{SANE\_STATUS\_INVAL}:] No image acquisition is pending. \item[\code{SANE\_STATUS\_UNSUPPORTED}:] The backend does not support this operation. \end{description} \end{quote} \subsection{\code{sane\_strstatus}} This function can be used to translate a SANE status code into a printable string. The returned string is a single line of text that forms a complete sentence, but without the trailing period (full-stop). The function is guaranteed to never return \code{NULL}. The returned pointer is valid at least until the next call to this function is performed. \begin{quote}\index{sane\_strstatus} \begin{verbatim} const SANE_String_Const sane_strstatus (SANE_Status status); \end{verbatim} \end{quote} \section{Code Flow}\index{code flow} The code flow for the SANE API is illustrated in Figure~\ref{fig:flow}. Functions \code{sane\_init()} and \code{sane\_exit()} initialize and exit the backend, respectively. All other calls must be performed after initialization and before exiting the backend. \begin{figure}[htb] \begin{center} \leavevmode \includegraphics[height=0.5\textheight]{figs/flow} \caption{Code flow} \label{fig:flow} \end{center} \end{figure} Function \code{sane\_get\_devices()} can be called any time after \code{sane\_init()} has been called. It returns the list of the devices that are known at the time of the call. This list may change over time since some devices may be turned on or off or a remote host may boot or shutdown between different calls. It should be noted that this operation may be relatively slow since it requires contacting all configured devices (some of which may be on remote hosts). A frontend may therefore want to provide the ability for a user to directly select a desired device without requiring a call to this function. Once a device has been chosen, it is opened using a call to \code{sane\_open()}. Multiple devices can be open at any given time. A SANE backend must not impose artificial constraints on how many devices can be open at any given time. An opened device can be setup through the corresponding device handle using functions \code{sane\_get\_opt\-ion\_desc\-riptor()} and \code{sane\_control\_option()}. While setting up a device, obtaining option descriptors and setting and reading of option values can be mixed freely. It is typical for a frontend to read out all available options at the beginning and then build a dialog (either graphical or a command-line oriented option list) that allows to control the available options. It should be noted that the number of options is fixed for a given handle. However, as options are set, other options may become active or inactive. Thus, after setting an option, it maybe necessary to re-read some or all option descriptors. While setting up the device, it is also admissible to call \code{sane\_get\_parameters()} to get an estimate of what the image parameters will look like once image acquisition begins. The device handle can be put in blocking or non-blocking mode by a call to \code{sane\_set\_io\_mode()}. Devices are required to support blocking mode (which is the default mode), but support for non-blocking I/O is strongly encouraged for operating systems such as UNIX. After the device is setup properly, image acquisition can be started by a call to \code{sane\_start()}. The backend calculates the exact image parameters at this point. So future calls to \code{sane\_get\_parameters()} will return the exact values, rather than estimates. Whether the physical image acquisition starts at this point or during the first call to \code{sane\_read()} is unspecified by the SANE API. If non-blocking I/O and/or a select-style interface is desired, the frontend may attempt to call \code{sane\_set\_io\_mode()} and/or \code{sane\_get\_select\_fd()} at this point. Either of these functions may fail if the backend does not support the requested operation. Image data is collected by repeatedly calling \code{sane\_read()}. Eventually, this function will return an end-of-file status (\code{SANE\_STATUS\_EOF}). This indicates the end of the current frame. If the frontend expects additional frames (e.g., the individual channels in of a red/green/blue image or multiple images), it can call \code{sane\_start()} again. Once all desired frames have been acquired, function \code{sane\_cancel()} must be called. This operation can also be called at any other time to cancel a pending operation. Note that \code{sane\_cancel()} must be called even if the last read operation returned \code{SANE\_STATUS\_EOF}. When done using the device, the handle should be closed by a call to \code{sane\_close()}. Finally, before exiting the application, function \code{sane\_exit()} must be called. It is important not to forget to call this function since otherwise some resources (e.g., temporary files or locks) may remain unclaimed. \section{Well-Known Options}\index{well-known options} While most backend options are completely self-describing, there are a cases where a user interface might want to special-case the handling of certain options. For example, the scan area is typically defined by four options that specify the top-left and bottom-right corners of the area. With a graphical user interface, it would be tedious to force the user to type in these four numbers. Instead, most such interfaces will want to present to the user a preview (low-resolution scan) of the scanner surface and let the user pick the scan area by dragging a rectangle into the desired position. For this reason, the SANE API specifies a small number of option names that have well-defined meanings. \subsection{Option Number Count}\index{option count} Option number 0 has an empty string as its name. The value of this option is of type \code{SANE\_TYPE\_INT} and it specifies the total number of options available for a given device (the count includes option number 0). This means that there are two ways of counting the number of options available: a frontend can either cycle through all option numbers starting at one until \code{sane\_get\_option\_descriptor()} returns \code{NULL}, or a frontend can directly read out the value of option number 0. \subsection{Scan Resolution Option}\index{scan resolution}\index{resolution option} Option \code{resolution} is used to select the resolution at which an image should be acquired. The type of this option is either \code{SANE\_TYPE\_INT} or \code{SANE\_TYPE\_FIXED}. The unit is \code{SANE\_UNIT\_DPI} (dots/inch). This option is not mandatory, but if a backend does support it, it must implement it in a manner consistent with the above definition. \subsection{Preview Mode Option}\index{preview mode} The boolean option \code{preview} is used by a frontend to inform the backend when image acquisition should be optimized for speed, rather than quality (``preview mode''). When set to \code{SANE\_TRUE}, preview mode is in effect, when set to \code{SANE\_FALSE} image acquisition should proceed in normal quality mode. The setting of this option \emph{must not\/} affect any other option. That is, as far as the other options are concerned, the preview mode is completely side effect free. A backend can assume that the frontend will take care of appropriately setting the scan resolution for preview mode (through option \code{resolution}). A backend is free to override the \code{resolution} value with its own choice for preview mode, but it is advised to leave this choice to the frontend wherever possible. This option is not mandatory, but if a backend does support it, it must implement it in a manner consistent with the above definition. \subsection{Scan Area Options}\index{scan area options} The four most important well-known options are the ones that define the scan area. The scan area is defined by two points (x/y coordinate pairs) that specify the top-left and the bottom-right corners. This is illustrated in Figure~\ref{fig:area}. Note that the origin of the coordinate system is at the top-left corner of the scan surface as seen by the sensor (which typically is a mirror image of the scan surface seen by the user). For this reason, the top-left corner is the corner for which the abscissa and ordinate values are simultaneously the {\em smallest} and the bottom-right corner is the corner for which the abscissa and ordinate values are simulatenously the {\em largest}. If this coordinate system is not natural for a given device, it is the job of the backend to perform the necessary conversions. \begin{figure}[tbp] \begin{center} \leavevmode \includegraphics[height=0.3\textheight]{figs/area} \caption{Scan area options} \label{fig:area} \end{center} \end{figure} The names of the four options that define the scan area are given in the table below: \begin{center} \begin{tabular}{ll} {\bf Name} & {\bf Description} \\ \code{\defn{tl-x}} & Top-left $x$ coordinate value \\ \code{\defn{tl-y}} & Top-left $y$ coordinate value \\ \code{\defn{br-x}} & Bottom-right $x$ coordinate value \\ \code{\defn{br-y}} & Bottom-right $y$ coordinate value \\ \end{tabular} \end{center} There are several rules that should be followed by front and backends regarding these options: \begin{itemize} \item Backends must attach a unit of either pixels (\code{SANE\_UNIT\_PIXEL}) or millimeters (\code{SANE\_UNIT\_MM}) to these options. The unit of all four options must be identical. \item Whenever meaningful, a backend should attach a range or a word-list constraint to these options. \item A frontend can determine the size of the scan surface by first checking that the options have range constraints associated. If a range or word-list constraints exist, the frontend can take the minimum and maximum values of one of the x and y option range-constraints to determine the scan surface size. \item A frontend must work properly with any or all of these options missing. \end{itemize} \input{net.tex} \chapter{Contact Information}\label{chap:contact} The SANE standard is discussed and evolved via a mailing list. Anybody with email access to the Internet can automatically join and leave the discussion group by sending mail to the following address. \begin{quote}\index{mailing list} \url{sane-devel-request@lists.alioth.debian.org} \end{quote} To subscribe, send a mail with the body ``\verb|subscribe sane-devel|'' to the above address. A complete list of commands supported can be obtained by sending a mail with a subject of ``\code{help}'' to the above address. The mailing list is archived and available through the SANE home page at URL: \begin{quote} \url{http://www.sane-project.org/} \end{quote} \newpage \input{sane.ind} \end{document} sane-backends-1.0.27/doc/sane-canon_pp.man0000664000175000017500000002050212112021330015165 00000000000000.TH sane\-canon_pp 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-canon_pp .SH NAME sane\-canon_pp \- SANE backend for Canon CanoScan Parallel Port flatbed scanners .SH DESCRIPTION The .B sane\-canon_pp library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Canon flatbed scanners: .PP .RS CanoScan FB320P .br CanoScan FB620P .br CanoScan FB330P .br CanoScan FB630P .br CanoScan N340P .br CanoScan N640P .br CanoScan N640P ex .br .RE .PP No USB scanners are supported and there are no plans to support them in the future. Other projects are working on support for USB scanners. See the .B PROJECTS file for more detail. The FB310P and FB610P are re-badged Avision scanners which use a different command set, so are unlikely to be supported by this backend in the future. .PP IMPORTANT: this is alpha code. While we have made every effort to make it as reliable as possible, it will not always work as expected. Feedback is still appreciated. Please send any bug reports to the maintainers as listed on the web page (listed in .B SEE ALSO below). .PP . .PP .SH "DEVICE NAMES" This backend expects device names of the form presented by libieee1284. These names are highly dependent on operating system and version. On Linux 2.4 kernels this will be of the form .I "parport0" or older (2.2 and before) kernels may produce names like .IR "0x378" (the base address of your port) or simply .IR "0" depending on your module configuration. Check the contents of .I /proc/parport if it exists. If you don't want to specify a default port (or don't know its name), the backend should be able to detect which port your scanner is on. .SH CONFIGURATION The contents of the .I canon_pp.conf file is a list of options for the driver to use. Empty lines and lines starting with a hash mark (#) are ignored. .PP The supported options are currently .BR ieee1284 , .BR calibrate , .BR init_mode , and .BR force_nibble Option .B ieee1284 .IR port-name defines which port to use. The format of port-name is OS dependent, based on the names presented by libieee1284. Please only have one of these lines, or all but one will be ignored. Option .B calibrate .IR cal-file .IR [port-name] defines which calibration file to use on a per-port basis. If you only have one parport, the port-name argument may be omitted \- but be careful as this will cause problems on multi-scanner systems. You may have as many of these lines as you like, as long as each has a unique port name. The tilde (`~') character is acceptable and will be expanded to the value of the HOME environment. Option .B init_mode .IR .IR [portname] defines which initialisation (wake-up) mode to use on a per-port basis. If you only have one parport, the portname argument may be omitted \- but be careful as this may cause problems on multi-scanner systems. You may have as many of these lines as you like, as long as each has a unique port name. The valid initialisation modes are FB620P (which strobes 10101010 and 01010101 on the data pins), FB630P (which strobes 11001100 and 00110011 on the data pins) and AUTO, which will try FB630P mode first then FB620P mode second. The FB620P mode is also used by the FB320P. The FB630P mode is used by the FB330P, N340P, and N640P. Option .B force_nibble forces the driver to use nibble mode even if ECP mode is reported to work by libieee1284. This works-around the rare issue of ECP mode being reported to work by the library, then not working. .SH TIPS .PP Hit the "Calibrate" button before scanning. It vastly improves the quality of scans. .PP To enable automatic detection of your scanner, uncomment the "canon_pp" line from .I @CONFIGDIR@/dll.conf .PP .SH FILES .TP .I @CONFIGDIR@/canon_pp.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-canon_pp.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-canon_pp.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_CANON_PP If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_CANON_PP=4 .SH NOTES .B Features available in the Windows interface .TP .B Brightness and Contrast These are not implemented, and probably never will be. These appear to be implemented entirely in software. Use GIMP or a similar program if you need these features. .TP .B Descreen Mode This appears on our first analysis to be just oversampling with an anti-aliasing filter. Again, it seems to be implemented entirely in software, so GIMP is your best bet for now. .TP .B Gamma Tables This is under investigation, but for now only a simple gamma profile (ie: the one returned during calibration) will be loaded. .PP .B Communication Problems .PP ECP mode in libieee1284 doesn't always work properly, even with new hardware. We believe that this is a ppdev problem. If you change the configuration file to include .B force_nibble , the problem will go away, but you will only be able to scan in nibble mode. .PP Sometimes the scanner can be left in a state where our code cannot revive it. If the backend reports no scanner present, try unplugging the power and plugging it back in. Also try unplugging printers from the pass-through port. .PP The scanner will not respond correctly to our commands when you first plug in the power. You may find if you try a scan very soon after plugging in the power that the backend will incorrectly report that you have no scanner present. To avoid this, give it about 10 seconds to reset itself before attempting any scans. .PP .B Repeated Lines .PP Sometimes at high resolutions (ie. 600dpi) you will notice lines which appear twice. These lines correspond to points where the scanner head has stopped during the scan (it stops every time the internal 64kb buffer is full). Basically it's a mechanical problem inside the scanner, that the tolerance of movement for a start/stop event is greater than 1/600 inches. I've never tried the windows driver so I'm not sure how (or if) it works around this problem, but as we don't know how to rewind the scanner head to do these bits again, there's currently no nice way to deal with the problem. .PP .B Grey-scale Scans .PP Be aware that the scanner uses the green LEDs to read grey-scale scans, meaning green coloured things will appear lighter than normal, and red and blue coloured items will appear darker than normal. For high-accuracy grey-scale scans of colour items, it's best just to scan in colour and convert to grey-scale in graphics software such as the GIMP. .PP .B FB620P/FB320P Caveats .PP These models can not be reset in the same way as the others. The windows driver doesn't know how to reset them either \- when left with an inconsistent scanner, it will start scanning half way down the page! .PP Aborting is known to work correctly on the FB*30P models, and is known to be broken on the FB*20P models. The FB620P which I tested on simply returns garbage after a scan has been aborted using the method we know. Aborting is able to leave the scanner in a state where it can be shut down, but not where another scan can be made. .SH "SEE ALSO" sane(7), sane\-dll(5) .BR http://canon\-fb330p.sourceforge.net/ .SH AUTHOR This backend is primarily the work of Simon Krix (Reverse Engineering), and Matthew Duggan (SANE interface). .PP Many thanks to Kevin Easton for his comments and help, and Kent A. Signorini for his help with the N340P. sane-backends-1.0.27/doc/descriptions.txt0000664000175000017500000001433712617742237015261 00000000000000SANE Backend specification files -------------------------------- The specification files (e.g. epson.desc) describe the capabilities of the backends. They provide information about the backend itself (e.g., name and version) and about the supported devices (e.g., manufacturer and product names). One file per backend should be used. Descriptions for backends included in the SANE distribution are located in `sane-backends/doc/descriptions/' while descriptions of external backends should be placed in `sane-backends/doc/descriptions-external/'. There is a special file `sane-backends/doc/descriptions/unsupported.desc' that doesn't belong to a backend but lists all (known) devices not supported by SANE. It may contain additional information about the device or links to non-SANE based programs. The specification files can be used to generate lists of backends and/or supported devices, hotplug/udev device lists, databases for search engines, and similar sources of information. Currently the creation of ASCII output and HTML lists is supported by `tools/sane-desc.c'. The generation of the HTML pages can be started by `make html-pages' in the doc/ directory. The file contents is basically emacs-lisp --- so ";" indicates comment to end of line. Empty lines are ignored. All syntactic elements are keyword tokens, followed by a string or keyword argument, as specified. All keyword tokens but ":backend" are optional. Backend-specific keyword tokens ------------------------------- The keyword `:backend' must be specified exactly once. It must be the first keyword in each specification file. It is followed by the name of the backend. Example: `:backend "epson"' The following backend-specific keyword tokens are optional. If they are used, they shouldn't be used more than once per file. `:version' has one string argument containing the backend's version number. The version should match the version used in the backend source code. Example: `:version: "12.3.5"'. If the backend isn't maintained, the version should be `unmaintained' or contain this tag together with the version number. `:new' indicates that the backend is brand-new in the latest SANE release if the keyword argument is `:yes'. Otherwise, `:no' should be used or `:new' should be omitted at all. Example: `:new :yes' The `:manpage' keyword token has one string argument that names the manual page for the backend. Example: `:manpage "sane-epson"' Device-specific keyword tokens ------------------------------ The keyword `:devicetype' starts a list of devices supported by the backend. It has one keyword argument. The following types are possible: `:scanner', `:stillcam' (still camera), `:vidcam' (video camera), `:meta' (meta backend like dll), `:api' (API like PINT). `:devicetype' can be used more than once. Each instance starts a new list of devices. Example: `:devicetype :scanner' `:mfg' has one string argument that defines the name of the manufacturer of the following devices. This keyword should be only used for hardware devicetypes (scanner, stillcam, vidcam). To avoid different spellings, the manufacturer list of the SANE standard should be used. `:mfg' can be used more than once. Example: `:mfg "Epson"'. The keyword token `:model' is used to specify the name of a hardware device in its string token. It must be preceded by a `:mfg' keyword. `:model' can be used more than once. Example: `:model "Perfection 636S"' `:interface' defines how the device is connected to the computer. Its string argument can be one or more of "SCSI", "USB", "Parport", "Serial port", "IEEE-1394", "JetDirect", "Ethernet", or "Proprietary". If neither one fits, please contact the SANE mailing list for advice. The "Parport" entries can be amended by "(SPP)", "(ECP)" and/or "(EPP)". The `:interface' keyword refers to the previous `:model', is optional and should be used only once per model. Example: `:interface "SCSI USB IEEE-1394"' `:usbid' defines the USB vendor and product ids of the device. It has two arguments which must be lower case hexadecimal (4 digits). The first one is the USB vendor id, the second one the USB product id. The keyword refers to the previous `:model', is optional, and applicable for devices with :interface "USB" only, and should be used only once per model. The special parameter "ignore" can be used if no vendor or product ids are given intentionally, e.g. for a group of scanners. Example: `:usbid "0x1234" "0x4321"' The keyword `:status' is an indication of the level of support for the model. It's followed by one of the following keyword arguments: `:unsupported', `:untested', `:minimal', `:basic', `:good', or `:complete'. The `:status' keyword refers to the previous `:model', is optional and should be used only once per model. `:unsupported' means the device is not supported at least by this backend. The keyword should only be used in the file `unsupported.desc', or to make clear that a specific scanner is not supported by a backend. `:untested' means the device may be supported but couldn't be tested. `:minimal' means that the device is detected and scans at least in one mode. But the quality is bad or important features won't work. `:basic' means it works at least in the most important modes but quality is not perfect. `:good' means the device is usable for day-to-day work. Some rather exotic features may be missing. `:complete' means the backends supports everything the device can do. Example: `:status :untested' The `:desc' keyword token is used for non-hardware devices (API and meta). Its string argument describes the meta backend or API. It should be used only once per device type. Example: `:desc "Scanners with the machine-independent PINT interface" Multi-level keyword tokens -------------------------- The following keyword tokens can be used after `:backend', `:mfg', `:model', and `:desc'. One or more `:url' keyword tokens can be used to point to more information about the entry the keyword refers to. The string argument contains a URL to e.g. a manufacturer's or backend's homepage. The most important URL should be listed first. Example: `:url "http://www.epson.com/"' `:comment' is used to add more information to one of the entries. The string argument can e.g. contain comments on the level of support for a model. Example: `:comment "US version of GT-5000"' sane-backends-1.0.27/doc/sane-teco1.man0000664000175000017500000001220312112021330014402 00000000000000.TH sane\-teco1 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-teco1 .SH NAME sane\-teco1 \- SANE backend for TECO / RELISYS scanners .SH DESCRIPTION The .B sane\-teco1 library implements a SANE (Scanner Access Now Easy) backend that provides access to some TECO SCSI flatbed scanners. This backend should be considered .B beta-quality software! TECO scanners are sold under various brands like RELISYS, PIOTECH, TRUST. This backend may or may not support yours. .PP The scanners that should work with this backend are: .PP .RS .ft CR .nf Vendor Model TECO model status ---------------------- -------------- ----------- Relisys AVEC 2400 VM3520 tested Relisys AVEC 2412 VM3520+ tested Relisys AVEC 4800 VM4530 untested Relisys AVEC 4816 VM4530+ untested Relisys RELI 2400 VM3530 untested Relisys RELI 2412 VM3530+ tested Relisys RELI 2412 VM3530+ untested Relisys RELI 4816 VM4540 tested Relisys RELI 4830 VM4542 tested Relisys RELI 9600 VM6530 untested Relisys RELI 9612 VM6530* untested Relisys RELI 9624 VM6530+ untested Relisys RELI 9630 VM6540 untested Relisys RELI DS15 VM3440 untested Relisys RELI DS6 VM3420 untested Dextra DF-600P VM3510 tested Dextra DF-4830T VM4542 untested Dextra DF-1200T+ VM3530+ untested Dextra DF-9624 VM6530+ untested .fi .ft R .RE Note that the untested scanner will not be directly supported. You should contact the author for that. The TECO VM number can usually be found at the back of the scanner. It is also part of the FCC ID. "sane\-find\-scanner \-v" will also show the scsi inquiry, and if it is a TECO scanner, the name will be there too. The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage or xsane. .br If you have any success with a scanner not listed here, or if you have any strange behavior, please report to the backend maintainer or to the SANE mailing list. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d teco1 .RE .TP .B Scan Mode .TP .B \-\-mode selects the basic mode of operation of the scanner valid choices are .I Black & White , .I Grayscale and .I Color The Black & White mode is black and white only (1 bit). Grayscale will produce 256 levels of gray (8 bits). Color will produce a 24 bits color image. .TP .B \-\-resolution selects the resolution for a scan. The scanner can do all resolutions between 1 and 600, in increments of 1. .TP .B Geometry options .TP .B \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters by default. .TP .B Enhancement options .TP .B \-\-custom\-gamma (color mode only) allows the user to specify a gamma table (see the next 3 parameters). .TP .B \-\-red\-gamma\-table (color mode only) can be used to download a user defined gamma table for the red channel. The table must be 256 bytes long. .TP .B \-\-green\-gamma\-table (color mode only) can be used to download a user defined gamma table for the green channel. The table must be 256 bytes long. .TP .B \-\-blue\-gamma\-table (color mode only) can be used to download a user defined gamma table for the blue channel. The table must be 256 bytes long. .TP .B \-\-dither (Black & White only) select the dither mask to use. Possible values are .I Line art , .I 2x2 , .I 3x3 , .I 4x4 bayer , .I 4x4 smooth , .I 8x8 bayer , .I 8x8 smooth , .I 8x8 horizontal and .I 8x8 vertical .TP .B \-\-preview requests a preview scan. The resolution used for that scan is 22 dpi and the scan area is the maximum allowed. The scan mode is user selected. The default is "no". .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/teco1.conf supports only one information: the device name to use (eg /dev/scanner). .SH FILES .TP .I @LIBDIR@/libsane\-teco1.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-teco1.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_TECO1 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH LIMITATIONS The windows TWAIN driver has many more options than this SANE backend. However they are only software adjustments. This backend only implements what the scanner can support. .SH BUGS None known. .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1), sane(7) .SH AUTHOR .TP The package is actively maintained by Frank Zago. .I http://www.zago.net/sane/#teco .SH CREDITS Thanks to Gerard Delafond for the VM4542 support. Thanks to Jean-Yves Simon for the VM3510 support. sane-backends-1.0.27/doc/u12/0000775000175000017500000000000013110600532012445 500000000000000sane-backends-1.0.27/doc/u12/U12.changes0000664000175000017500000000157712617742237014324 00000000000000U12.changes - Gerhard Jäger ================================================ V 0.01-1 (2004-09-01) --------------------- - initial version V 0.02-1 (2004-10-01) --------------------- - fixed autodetection problem - enabled additional scan-modes - enabled TPA scanning - fixed corrupted picture problem V 0.02-4 (2004-19-01) --------------------- - activated cancel function - added lamp off timer function V 0.02-6 (2004-21-01) --------------------- - compilation fixes - changes to some structures V 0.02-9 (2004-06-10) --------------------- - using now SANE definitions for scanmodes V 0.02-10 (2006-14-02) ---------------------- - SoftwareReset is now disabled in cancelSequence when the device is a Genius (reported by Jose Alberto Reguero ) V 0.02-11 (2006-09-08) ---------------------- - Changed sane.type to "flatbed scanner" only sane-backends-1.0.27/doc/u12/U12.todo0000664000175000017500000000040012617742237013641 00000000000000U12.todo (2004-19-01) Gerhard Jäger ========================================================= OPEN: ----- - 1200dpi modes - spurious I/O stall - binary mode inverted - preview mode - TPA does not work - reopen after lamp off on end sane-backends-1.0.27/doc/sane-canon_dr.man0000664000175000017500000001604012775312262015203 00000000000000.TH sane\-canon_dr 5 "31 Aug 2015" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-canon_dr .SH NAME sane\-canon_dr \- SANE backend for Canon DR-series scanners .SH DESCRIPTION The .B sane\-canon_dr library implements a SANE (Scanner Access Now Easy) backend which provides access to some Canon DR-series scanners. This document describes backend version 51, which shipped with SANE 1.0.25. .SH SUPPORTED HARDWARE This version has only been tested with a few scanner models. Please see http://www.sane\-project.org/sane\-supported\-devices.html for the most recent list. This backend may support other Canon scanners. The best way to determine level of support is to test the scanner directly, or to collect a trace of the windows driver in action. Please contact the author for help or with test results. In general, the larger machines (DR-4000 and up) which have been tested use a fairly complete protocol, with hardware support for many modes, resolutions and features. The smaller machines have many limitations, like missing horizontal resolutions, missing binary mode, always scanning full-width, etc. There is code in the backend to address these problems, but there seems to be no way to detect if they are required, so they must be hard-coded. .SH OPTIONS Effort has been made to expose most hardware options, including: .PP source s .RS Selects the source for the scan. Options may include "Flatbed", "ADF Front", "ADF Back", "ADF Duplex". .RE .PP mode m .RS Selects the mode for the scan. Options may include "Lineart", "Halftone", "Gray", and "Color". .RE .PP resolution .RS Controls scan resolution. .RE .PP tl\-x, tl\-y, br\-x, br\-y .RS Sets scan area upper left and lower right coordinates. These are renamed t, l, x, y by some frontends. .RE .PP page\-width, page\-height .RS Sets paper size. Used by scanner to determine centering of scan coordinates when using ADF and to detect double feed errors. .RE .PP Other options will be available based on the capabilities of the scanner: enhancement, compression, buttons and sensors, etc. .PP Additionally, several 'software' options are exposed by the backend. These are reimplementations of features provided natively by larger scanners, but running on the host computer. This enables smaller machines to have similar capabilities. Please note that these features are somewhat simplistic, and may not perform as well as the native implementations. Note also that these features all require that the driver cache the entire image in memory. This will almost certainly result in a reduction of scanning speed. .PP swcrop .RS Requests the driver to detect the extremities of the paper within the larger image, and crop the empty edges. .RE .PP swdeskew .RS Requests the driver to detect the rotation of the paper within the larger image, and counter the rotation. .RE .PP swdespeck X .RS Requests the driver to find and remove dots of X diameter or smaller from the image, and fill the space with the average surrounding color. .RE Use 'scanimage \-\-help' to get a list, but be aware that some options may be settable only when another option has been set, and that advanced options may be hidden by some frontend programs. .PP .SH CONFIGURATION FILE The configuration file "canon_dr.conf" is used to tell the backend how to look for scanners, and provide options controlling the operation of the backend. This file is read each time the frontend asks the backend for a list of scanners, generally only when the frontend starts. If the configuration file is missing, the backend will fail to run. .PP Scanners can be specified in the configuration file in 4 ways: .PP "scsi CANON DR" .RS Requests backend to search all scsi busses in the system for a device which reports itself to be a scanner made by 'CANON', with a model name starting with 'DR'. .RE .PP "scsi /dev/sg0" (or other scsi device file) .RS Requests backend to open the named scsi device. Only useful if you have multiple compatible scanners connected to your system, and need to specify one. Probably should not be used with the other "scsi" line above. .RE .PP "usb 0x04a9 0x1603" (or other vendor/product ids) .RS Requests backend to search all usb busses in the system for a device which uses that vendor and product id. The device will then be queried to determine if it is a Canon scanner. .RE .PP "usb /dev/usb/scanner0" (or other device file) .RS Some systems use a kernel driver to access usb scanners. This method is untested. .RE .PP Besides the 'scsi' and 'usb' lines, the configuration file supports the following 'option' lines: .PP "option buffer-size [number of bytes]" .RS Set the number of bytes in the data buffer to something other than the compiled\-in default of 4MB. Large values may cause timeouts or hangs, small values may cause slow scans. .PP Note: The backend does not place an upper bound on this value, as some users required it to be quite large. Values above the default are not recommended, and may crash your OS or lockup your scsi card driver. You have been warned. .RE .PP "option vendor-name [string of text]" .br "option model-name [string of text]" .br "option version-name [string of text]" .RS These options can be used collectively to override the values provided by the scanner, or to provide the values when the scanner cannot. .RE .PP "option padded-read [0|1]" .RS Some scanners prepend all data transmitted to host with 12 bytes. Enable this option if the scanner fails to respond to commands. .RE .PP "option duplex-offset [integer]" .RS Some scanners pad the upper edge of one side of a duplex scan. There is some variation in the amount of padding. Modify this option if your unit shows an unwanted band of image data on only one side. .RE .PP Note: 'option' lines may appear multiple times in the configuration file. They only apply to scanners discovered by the next 'scsi/usb' line. .PP .SH ENVIRONMENT The backend uses a single environment variable, SANE_DEBUG_CANON_DR, which enables debugging output to stderr. Valid values are: .PP .RS 5 Errors .br 10 Function trace .br 15 Function detail .br 20 Option commands .br 25 SCSI/USB trace .br 30 SCSI/USB detail .br 35 Useless noise .RE .SH KNOWN ISSUES This backend was entirely reverse engineered from usb traces of the proprietary driver. Various advanced features of the machines may not be enabled. Many machines have not been tested. Their protocol is unknown. .SH CREDITS The various authors of the sane\-fujitsu backend provided useful code .br Yabarana Corp. www.yabarana.com provided significant funding .br EvriChart, Inc. www.evrichart.com provided funding and loaned equipment .br Canon, USA. www.usa.canon.com loaned equipment .br HPrint hprint.com.br provided funding and testing for DR-2510 support .br Stone-IT www.stone-it.com provided funding for DR-2010 and DR-2050 support .br Gerhard Pfeffer provided access and testing for P-208 and P-215 .br Special thanks to: Alejandro Imass, Andre Shimakawa, Martijn van Brummelen, Thanos Diacakis and Junren Shi for testing and feedback. .SH "SEE ALSO" sane(7), sane\-scsi(5), sane\-usb(5) .SH AUTHOR m. allan noah: sane-backends-1.0.27/doc/umax/0000775000175000017500000000000013110600532013010 500000000000000sane-backends-1.0.27/doc/umax/umax.BUGS0000664000175000017500000000051412112021330014356 00000000000000BUGS FROM UMAX BACKEND FOR SANE ------------------------------- If you think that something is a bug and not a feature, please mail: Oliver Rauch KNOWN BUGS: * pixel count in x-direction is sometimes wrong if xres > 600dpi (Vista S12) * first scan with Astra 2400S produces wrong colors sane-backends-1.0.27/doc/umax/sane-umax-text.jpg0000664000175000017500000000476212112021330016315 00000000000000ÿØÿàJFIFÿþXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ-"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷Ú+#Åò'ëõá?þ‹jùlÔJV=l»+úì%.~[y_õG×tW›|!Õ¥¸ÐN`<»mÛOÕËZóŠòQõoûcÿ¢R‡++™áòïm‰žšÜ·ÖÝ»ŸHÑ_6|5ÕeÒ¼Z¯Ï…³èYOô‡âÆÝãlúßÏÿ£Žm.l²‹×•}’w·üêú+å ø‚ãÃ^#µÔ`ª«l˜dá£<0 uõàÕôÕÆ¿geá¹u»—Ûm &VÁž8Q’IÀ<’4îrc02ÃME;ÜÕ¢¾7½¼žþöâòåüË‹‰Y_nf9'É=+[Á:ŒšOŒtëØ€.ŒÀþÒ2ŸçK›S¦®Uìàæç²¾ßðO¬¨¨me3ZÅ+ue×Ê>?ñø£ÆwúŒ.ík¸Em¹ÉZŒhb c=ù¦ÝŽ6דW²GÖ”WÅ6—“é÷Ö÷¶²ywò,±>ÚÊr@ë_]xOÄx—ÃöÚŒd~ñrFG¸8î„îV' èYÞ÷7(®kÇ^¶ñ‡…æÓgÞ²+ ­äSÌr@8î0H ö'¡Á#ߨÝi—ÓY^ÀðÜÂÛdúƒþ{÷§r(ÐUWÅf}»E|ë¡üpÔ,|{c¨.uˆÐEauÁc¸¾L‚ L“’Ù¼ÕäsK=åÓË,’Oq3–wrY݉É$žI$Ò¸ÖZÝØûšŠñ‚Ú]Αâr.JµÌäœ6ÜíUƒq÷9>À{E3žI'¡‘â¿ùµ¿úðŸÿEµ|´kê¯[M{áVÖÝ7Í5œÑƹ,P€2xêkåycxdh¤FI•da‚¤uv¬êWò^ÎkÌöƒ?ê.Ïzâ>)ÿÉGÕ¿íþ‰JÖøoã='ÃQÝ&¦fO‘ &íätQèO¾‘\Ÿ‹õȼIâ«íZ^§eŽrÛUB‚qÜ…Î;g=hmr¡`°ÕiãêÔ”lõõw$ðWü6¿_ê*ŠÿäoÖÿëþýÕÁ(ÇÄö­ƒ·p÷Ȫ+ÿ‘¿[ÿ¯ùÿôcR ´xê–ìŒc]f£ã9o>ØøtWŽlÌUŠƒ "‘ü@’^ té\êÙI6™-â.VCž€àùŸÖ¨š…ÍS¬ÓþWøÿZ5£áÿù,ÿßþ†ª\ÀÖþP`At݃õ?áV¼=ÿ#—ûÿÐз9±R¡&¶³=Óâ—‰ÿ°~Ea bïUCn¼}ذ<ÃÈ#¡ ŽϑҾq'šê¾ ëÃ_ñdóE/™kl‰knp¸ÚƒœÔ.Àç¡AË+´r+©Ã)È8èGJ¦õ9°´}•º½Bâ -§xd2út?çŠõŸ‚+û£6ƒs."›÷n=ñ(Éüp÷yEÝä÷²‰geg "5\œg“îyééIa>—¨ÛßZ¶Ù péÉíØã±è}¨[‘Z›©K–[þ§Ûãßü'¦É¡|Ï¥Ü.3™óŸÝŒu=Ç=Hô ;ÅZkøA5û»´‚É!I3ä;qÔ“êI©¯™>!xÖãÆÞ$’÷3G§ÅòYÛHÃ÷i“Ææ#'¯a’U³ÉÃÓ“Ö–9#]¿Ão'ˆu6×# Äÿ ŸOsƒùW+•u>›%ìQ3Çù‚®p£«}øúSôPðÖ³©¦ÍåÜDzU׺°îÿ\`€jQÕWß‹IŸdèÚL6Ÿ¬ aG'Ö´+ž)Óü]¡Å©éÒîFùdCÃF㪰ìúÄpA­Ê£ÍjÛ‡ZóŸü4ƒYïlñÃrØþ#^EÒ«:Ræ¦ìÏœ¯>kvêX@Älæ›eðçW»Ã}™Àèwq_GÁÐ/@Ò—*:å™âåW7ýyž}á‡Qhò¥ÕÞQʨ\¿Œ~K>½sy§}¢Au+Í&ö\bIŽ™5íTSÑœÔñi6á+6y‚¾ÝYË]F6·128'`ò+¾øI}m¨2Û,’­ò— ä{ñ_@ÑE‘KY6Ôž»ž/®|(7ZM­ÄF·$b6XmÆIÎ1œóë\ýŸÂ½^ ´$ÈFFå`ÈÆAÇZú"Š,„±5Ty´>w½øCx³•µŽäÇêî¤ÿ!ZÞøSsËGx¬‘KdûW¹QE§ˆ«5iJèó{ï„zUÕŒ°e׃‚oÖ¼âçàÝüsºF“ºÃn^Gå_GÑA0«8+EØñ};áö¡7ƒäðýýΧ’HeX`‘Hsì$¨98õ>áø9~&ÊÃpP8ä{à úNŠí¦ºœƒ¼•bMäjeuÛ·(¯<ñ/Á=š´Òižy‚W.2s´ t«è (!M­ømà½cÁºÔ²(›ì÷*«21R3ƒÓ9nýëÙ(¢6Þ¬ÿÙsane-backends-1.0.27/doc/umax/umax.TODO0000664000175000017500000000120312112021330014357 00000000000000TODO UMAX BACKEND FOR SANE ========================== * When depth>8 then it is necessary to create the gray gamma table with the correct depth * Astra 2200: enable option resolution bind for grayscale/lineart it must be disabled and set "true" for color mode * change set_window if (dev->do_color_ordering != 0) {..} one of the settings makes an error for Astra 6X0S scanners * include push-button function to SANE_START (?) * add builtin halftone pattern selection * add halftone pattern doenload, dimension selection - I will NOT add support for parallel-port and USB scanners to this backend! Don`t ask for it. sane-backends-1.0.27/doc/umax/sane-umax-advanced-options-doc.html0000664000175000017500000000763412112021330021517 00000000000000 SANE-umax - Advanced options
SANE-logo
UMAX-logo

SANE-umax advanced options





This backend dynamically enabeles the options that are supported by the scanner in dependence of the scanning-mode and other options. Here is an example of the frontend XSane:


sane-umax-advanced-options-screenshot


Advanced options Remark
Set exposure time Enable selection of exposure time, if not enabled, scanner uses default values. *
Cal. exposure time Define exposure time for calibration. *
Scan exposure time Define exposure time for scan. *
Set lamp density Enable selection of lamp density, if not enabled, scanner automatically selects a value. *
Cal. lamp density Define lamp density for calibration. *
Set scan lamp density Enable selection of lamp density for scan, if not enabled scanner uses the value that was used for calibration. *
Scan lamp density Define lamp density for scan. *
lamp on Turn on scanner lamp. *
lamp off Turn off scanner lamp. *
lamp off at exit Turn off scanner lamp when program exits (when sane_close is called) *

* only available for some scanners




This page has been changed on 5th. february 2001


Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-standard-options-doc.html0000664000175000017500000001450612112021330021546 00000000000000 SANE-umax backend
SANE-logo
UMAX-logo

SANE-umax backend





This backend dynamically enabeles the options that are supported by the scanner in dependence of the scanning-mode and other options. Here is an example of the frontend XSane:


main-window


The options Gamma, brightness, contrast and negative in the main window come from xsane that calculates a gamma table using this values. These values are corelated to highlight, midlight and shadow sliders in the Histogram window.

Scan modes:

Mode Remark
Lineart 1 bit/pixel black/white mode
Halftone 1 bit/pixel dithered black/white mode
Grayscale 8 / 9 / 10 / 12 / 14 / 16 bits/pixel gray mode
Color 24 / 27 / 30 / 36 / 42 / 48 bits/pixel RGB mode

Scan sources:

Scan sources
Flatbed
Transparency adapter (UTA)
Automatic document feeder (ADF)

Standard options:

sane-umax-standard-options-screenshot


Standard options Remark
Analog gamma correction Define the value for analog gamma correction. *
Value between 1.0 and 2.0 .
(Analog gamma correction doesn't reduce the number of used colors)
Highlight Define the intensity that shall be considered white. *
Shadow Define the intensity that shall be considered black. *
Contrast Define the contrast of the image - only available in halftone-mode.
Brightness Define the brightness of the image - only available in halftone-mode.
Threshold Define the minimum intensity to get a white point- only available in lineart-mode.
Use custom gamma table Use free definable scanner internal digital gamma table.
If you enable this option, the gamma correction is done inside the scanner. If you have a scanner with more than 8/24 bits/pixel, the image is scanned with the maximum available bit depth. The gamma correction does transform the image form the internal bit depth to the selected output bit depth (see below).
The frontends do handle the usage of the gamma table different. If you use xsane, you should enable this option to use the maximum available bit depth (otherwise xsane does the conversion with the selected output bit depth).
(Side-effect: digital gamma correction may reduce the number of used colors -especally if the used bit depth is low.)
Quality calibration Use quality white calibration. *
Double optical resolution Use lens 2 on high end scanners, this reduces the scanwidth and increases the maximum scanresolution. *
Negative scan Inverts color intensity - for scanning negatives.
Bit depth Image depth in bits/sample the scanner sends to the computer, normally 8 in grayscale and color mode. Some scanners support more than 8bits/sample, but only few file formats support it. If your scanner supports more than 8bis/sample you already get an improvement if you set the bit detpth to 8 and enable the option use custom gamma table (see above) because the scanner internal gamma correction is done with the maximum available bit depth!!!
*** There is normally no reason to use more than 8 bits/sample! ***
Lamp warmup Enable extended lamp-warmup. *

* only available for some scanners


Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/negative-types.txt0000664000175000017500000000114512112021330016430 00000000000000 Negative ---- highlight ---- ------ shadow ------ Type red green blue red green blue --------------------------------------------------------------- standard 66% 33% 16% 7% 1% 0% --------------------------------------------------------------- fuji 64% 33% 16% 7% 1% 0% --------------------------------------------------------------- kodak 54% 18% 12% 9% 2% 0% --------------------------------------------------------------- konica 38% 21% 14% 3% 0% 0% --------------------------------------------------------------- agfa 61% 24% 13% 6% 2% 0% --------------------------------------------------------------- sane-backends-1.0.27/doc/umax/sane-umax-histogram.jpg0000664000175000017500000006272512112021330017331 00000000000000ÿØÿàJFIFÿþXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀq"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ô-STM.8Ù¢B…cXQŽJÜ}k3þûùàð:<_ÿýbÿÑuçwñÝ[N·6ó±RÜÄïÇêz.¿LêO‘sZç^ ±5=—:‹{_fû_¡èŸð—ÛÿÏÿ€ñÑÿ }¿üð?øp¶—+zLŠãq±Iëê}½?ǦWˆ5Ûâ?’‚â&H2À0ŸT®Ç€ è¹É9öèsĉ­ê1G},P/ÙáÔfŽ{ƒ¾o&5Ûƒ°¾O''iÀñ@»ÿ }¿üð?øð—ÛÿÏÿ€ñ×’FúïXð̉y•r“Ü»FåWœäŒû2§9ÍG‹o>Ïgy44‘]H‘ *Ñù Cd }Ñ×ð _ÿ„¾ßþxüŽøKíÿçÿÀxëÆ®¼[ªÚ[hlØ:+Å![’ò*àŒñ€Äu=3žp.^ëšÅŒr¡§Ã0‚K…·Ž9gp£·yÈ/œg àЬÿÂ_oÿ<þÇGü%öÿóÀÿà/ÑQo'ò.<ýÐdùcàO<òO¶(Óÿá/·ÿžÿã£þûùàð:òÍ“]øƒ}íÛ-½Æû¹ÞRbQŒ}PaIõ8Ê÷$ñU~Ò÷kW×o¨2ZÜËn©eqåy1Æ3¿€'œœç¶(×á/·ÿžÿã£þûùàð:óg¼ÕŸOK½:®¢’Í$™¶LÒ±¶0¸Úr@Ç#šž(¹{t½¤“É{ Ìn qóy‘œ‚á°@=oþûùàð:?á/·ÿžÿã¯$µñ.¥sÙíw½¸ƒ« Æz䓨ã®ÓÒ´<<×>²šâY%•·îy³‡$Ð¥ÿÂ_oÿ<þÇGü%öÿóÀÿà#_ݸÁ8nŸ/Í’1ž‡DÖ¯üAg¬Ýß?Øš ?Øå1%¾Ww™!e K0»}Np{Åšâê¿5«‹R‚&µ`cA¸:ìAõæŠæâÿ’%wÿ^ ÿ¢ÒŠôY\_EVÑïp"b7Ç—ïõ®dxgT ©,FdN çüþUÞ7ü}úãþ‚´ú,5&¶<Ú?_Ãuöˆ­äŒ“ʬ©·éŒô¥ŸÁ7ÜM§î–[slíç˜ÉÉ^õë]ÞŸ¬iš·™ý›¨ÙÞyXó>Í:ɳ9Æv“ŒàþUv¦0Œ~k_V»N¬®Ò¶½/o‡{¶ƒ¥|¡#B‚ã á>àu݇ÇûY§Kðùæ’YM`dJÁ.v ÇÎl+p>aƒ×žMz\³EšDK*vbG=É RE>¨Äóþ£µt¥)j$XU¦ “ï‚ sœž¹©,¼ >'™m§°,Dî<¨:(,ÇØq^•EyÇ€dºûg¦nûnÏ´~ÿö}ÞÆ=±M?œ±a¦²9î<ĹÚáØaˆ`Ù@8ö¯N¢€<Ìø½µ¿öLb+\ùJ$Q´‚ÍÈ9äƒß5ü=’Í™p’,k,¾dqïûØŒ¾=ÀÇêPŒÙü0ÔÞåŸPÓm–f–Í E÷á·$0ÆÕdðÎo]x"âòá.'Ó÷J¨cÜ& ¹ ÉVÃ|Ëìr:úפQ@ZŸZÜ[ -ŒWP×Dî ÷FKäcÚ¯CàûØ/.nã±Û=Îß5¼àwmnÀãÒ½ŠóCáóê“™¯4Ö‘Ìb"EÎÜ ;€ 0žjiüqsq-ÄÚ~ée·6ÎÞpŒœ•á¿^µéP™Ëà&¼k¹4ÌÎÒÇ1o?øã!Æìp þ´]xKÝF û3}Ô|·óñ·iÈà6&½2Šó¿øCï´~ßöô¯+Éß繜ã±Ö«Ýx kɦ–[ Î%òîŒb@2`®pHçµzeÀÇáJ(Ö8ì•UUtК†oÞÏymw%Žéí·yMç·pÁãvµè”P™Åà;ˆ.xlçä”Ìá/X+99$¨|Ê7gžéî_Oo2@]·VP:PÀ7ƒÇ+Ò¨ 1‡ÆE &”¬°´ÃLîÈ{±ç¯½W¼ø}öVzlO3ÏÎ×7,]¶ð1.âê@èyÇ#šõj(Èô¿†×°[È/tØÚîK„H¤b1°Ë´`‚=â¶,|{¦ÙÇiicåÁv¯œ2I<–ÏRkÑ( þÝWþ}ò"ÿðŽê¿óëÿ‘ük¼¢€8{è¼YrðGÿÞ46¾Y€ÜÝnedP¡þæ¸Ï3Œžµ^{_ÜK$ÏáÍ\I·3‹£æyg»¶gç3^Eyž£¤ÝèŸ 5 ÔUš+=§k£ ýA¢ºˆ¿ò$k?õèÔPRßñô?ëŒú ÓbRí4,Ÿ,¥ݸ؇ž3ÕzsÇÐÿ®1ÿè+P—dŽ]§¹oýp6šV§e¡hË"j7Oý‹±·†‰ìNëmʾHG8˜¡%ÛÉÚ¤e³2Iâ }*ÞvmFå„&D†U.Œñ”Vç÷–û£mÌÌ\ÄŒr×kçÉýïÒ¹GÇQi~(–ÂêçÊ·ÊY7Ä[I™J‚z˜G>üw­)ÒFÔí¨›±µqm©ÚønÒ6šiµ{m%Ã@ÌÀn¹F•Tõò€.=`÷®{KµÖm­4ùKjæt¶Ó%q<ÓIûÙe)t1 â02§ˆþð I5Úùò{ô£Ï“ûߥf3„´mb9¼›ÅÕÓJyîb‰nÞX0’‰#–imFèÈWŠ¢J4†ñ Õõ„’^ê"¹•TI •Ü­äÂe‘£u‰1Œ|á€çʆkwWö¯ky76ïñMº6FA<€ |$[Á*E j#D ª `@\0©9óî†{+GôÊQä'üü^ßQÿñº­çÉýïÒ>Oï~”gÈOùø¼ÿ¾£ÿãty ÿ?Ÿ÷Ôün«yò{ô£Ï“ûߥYòþ~/?ï¨ÿøÝBÏÅçýõÿªÞ|ŸÞý(óäþ÷é@|„ÿŸ‹Ïûê?þ7GŸóñyÿ}GÿÆê·Ÿ'÷¿J<ù?½úPŸ!?çâóþúÿÑä'üü^ßQÿñº­çÉýïÒ>Oï~”gÈOùø¼ÿ¾£ÿãty ÿ?Ÿ÷Ôün«yò{ô£Ï“ûߥYòþ~/?ï¨ÿøÝBÏÅçýõÿªÞ|ŸÞý(óäþ÷é@|„ÿŸ‹Ïûê?þ7GŸóñyÿ}GÿÆê·Ÿ'÷¿J<ù?½úPŸ!?çâóþúÿÑä'üü^ßQÿñº­çÉýïÒ>Oï~”gÈOùø¼ÿ¾£ÿãty ÿ?Ÿ÷Ôün«yò{ô£Ï“ûߥYòþ~/?ï¨ÿøÝBÏÅçýõÿªÞ|ŸÞý(óäþ÷é@|„ÿŸ‹Ïûê?þ7GŸóñyÿ}GÿÆê·Ÿ'÷¿J<ù?½úPŸ!?çâóþúÿÒF»nJ &uòñ!S‚ÆÕ˜Õ>Oï~”ûWg¼}Ç8¶ý:ç>"ÿÈ‘¬ÿ×£QGÄ_ù5Ÿúôj(©oøúõÆ?ýj»ÿ«—þ¾[ÿEÅVþ>‡ýqÿAZ®ÿêåÿ¯–ÿÑqPUóωœÿÂgs ¦ðú”¥Ôã Šä°9ö¯}ÔnþÁ¦]Þló>Ï Ë³8ݵIÆ{t¯žà•µ<÷L^_&[À¹Û©#Ó’xï]TäéáªÔ]’“šRW]}]øâÁâM ùìæê&ýã¸Àvrí„õ ~Œ ýoYƒCÓÅÜêÎ Š«dó óŽ˜Íx›â+W²È u¸`‘œ)¢öù˜sÚ·ß_ºÖ´ˆ¡šBLL×R ì¸`s’äF8À® Ôj<Ö;¨áiº¼²–—^[ÿÁÓ¹ípω·(vBqŽUŠ‘ùƒRW‰ÚkZ¤›­î¤Þfó¾`2T·9ä†#ßðêZw‰-ït»{¹#0¼Îˆ"v Èc\<©'¸Ñ ªAŠÀʅEV§QEQEQEQEQEQEQEQEQEQEQET¶ñøÿõìÿúuKgÿÿ^Ïÿ¡Ç@÷Ä_ù5Ÿúôj(ø‹ÿ"F³ÿ^Eu-ÿCþ¸Çÿ ­Wõrÿ×Ë踪ÃÇÐÿ®1ÿè+Ußý\¿õòßú.*ÃñMÄVÞÕ$™¶©¶xÁÁ?3 ª8õ$ ð]3þFÿ¯7þuí¾>ÿ‘'Pÿ¶ú1kÈt„FûL ëû¶÷ù ç]5ZŽ]6úÊßt’u.ú&dYB“ø²Ê7Re$záä?Òœˆ ¬Ð*C+I<„v±Œ‚‹Œð0Å8Ç—Lÿ‘ÂËþÛÿèRÒGÿöÿõÖçÿBJËk7NOM?dÌ1¬[³íù2{½VmRšÔ²´cie’bT’ çnw½úT3x†æ=bâ$Ù +ÇŠ\až%b7`àÅ€çjþ¤Ëq-Â"³ym 60qå\ýˆ+øŠæõOøùÕ¿ëûúÉ\^ÅÂ\•#gmøqaëÔ«$¦õJÿrþ¾g¥øsǺÆkàû\P˜¡É@Ò¨X·º€HO îÉ5ƒªüEÖµ;›+òCngšo³FŸ³•A8°ÜžFIô4×"[f #\îÈu Ïò¬ÖÓ@¾šUÈŠXãË„s8¿÷–³UÑíýÀ:ñ8 ‘«(A^:Û}l“𷣨ï|)ãû™î š‰Hì^@ÊȤ±Y$‘WròoêW¶=9ôû{¨n¼/¹F9ÁT0ëìE|Áuu{¤ÛXÁžY{t‘×h<‰]—¨à‚kÔü-ãhm´Ûiï.¤•¤‰UgA8àu‡AëW(;n›<ÔçF\²ÚïåoøcÔ¨¬« ~ÂôÞ!¸†)­%•&‰¤¢£¼ç.0sÐgâ¹/x¦)¼7~©rË<×íieYbCR† Üóɽ*Xj“Ÿ%¬u¹$zç~×çÒü#QÃì¶’HËg†ÍÓóê?r8êy¯B!•¢¦EPÌ™äœ=äjkЕ)8°N㨢ŠÄaEPEPEPEPEPEPEPRÙÿÇãÿ׳ÿèqÔU-Ÿü~?ý{?þ‡sßäHÖëѨ£â/ü‰Ïýz5Ô·ü}úãþ‚µ]ÿÕËÿ_-ÿ¢â« ÿCþ¸Çÿ ­Wõrÿ×Ë踨ƒø¥ÿ"Í·ý~/þ€õæš'ú›ïúíÿ´«Òþ)ȳmÿ_‹ÿ =yÞ—¥œ¬£Éf÷; +£ÿ"Õþ/ó.’»“ì¿TbiŸò8YÛý ZHÿãÞßþºÜÿèIK¦Èáeÿmÿô)i#ÿ{úësÿ¡%gñÿðý¸Ãþöýå"å§2°íåÈqﱆSùÖ&±–Ú„…‡ïo›ÐãúÖ²;FÙS‚A?Ϋê/ wRNn}[ýkØÇ`½´ÝNÑün¿C*mƧ2ícNçý}Ÿýv?úÔâ54€|ì“ì3æj¬²o¸³é3?øãÔÓJ"Aõ\ŽÇòË QÔTí©öн5T¾ŸðNòÝ&¸d‹r¼H ž:3ƒøÒ±\iñÞå!!—j«N úmvú-«A_æ´^إŴ±¢eu.Aç\ž}‡é^„ù0jš»jÿ~ßu¾óÉ©‡xÞz‘èí¯–¿›-O<š‚Kv¯(šàÉæOïJAç“ò‚zóøb”³Kw:4Ϲ¶¤`à *¨Uéè¢ÆV‚í,¢AåZËcžYJ¼¬O=r•zÊÑÒk¬0hÝ£ÚOpåOoL~µ¾4†ã'ªø{ë²ùiý#dž’²¥'§2Þíýz‰§jÙØÜÁ *Æræ=ŽXÈÇ®%'=¶÷¯@ðwˆ ½ñ©=Ü« ׿3vP>\…@xËaÔ pk„h<•†çß ?û5R²¹–ÒîÒê43‰X R¤>•P©ý£9=’š{ÿà'£V,=ã¯2ßÑ­¾ÿÀú:±`¬ S†ô8ÎàGç^GÄ;KíœÎ^(¬fò²]Ù ¸g—æ8Œq†ÏéœñWµê ¬ÛÜY%–Ú¯/<ÇØš%R¬ u Rx‡sæUŸ³ø¶þ¬yu+Fæ;KÏÛZËqÁ+Ïœ÷`e‰¶žH$ôã§åZjVðßÃdKå`Âåd`IôýÓŽ=«ÉN²×ºµþ¡2Çld´»²ÿYÑ–¸p9¸AÇ]£ÉY|ay‰n58ÞIá3<ÅpÙÚ1"Æ;à(•¾PqüëÐÂ`å^Ÿ7_øk*ݽy¬ZÛØÞÜC47ZÅ+´I(É1Œ²œgeAôÈ£SÔ†6œ¨Žêì[± ’7#•Æ;– ?õ¯ Ó¯¾É)óZF‡ÉÈ $E3®Üûjê|kã$Ö>Ç™&-ãÙsæmd–9†áŒç:wèkªYcHÅjîÊçÐõº+Ïü¨^7‰šÁ®$kEÒ­¤XXåU„Qr=>ñé×<× W^‹¥.VüËNáEPÖ/dÓ죚%Ffº·„‡²L‘·ã†8÷¯=ð‡4ëßx„Kpñ[ßͲ Ä£²â€pC>Pãrp¹¬Fz]Ôÿf³žãnï*6}¹Æp3ŠK[•¹¶·”áh„7dã?\dW#qâgÔü-À v PÝìûÚ0î‚rnCÏU`}j/k’ ZÖÒàæ$ˆÃw›#ë÷@ô•Ë,JUyzÁ9%‰J¯*Ú߭އÄÚ´^rfŽâX\@á‹p¹ذ>¸ÉíVìu$¿ãeF¶ŠáKq&ì;co¯zóïë¶ÜzsYJÌcdFB¥3·ö=Lô®›Á·/un’8PEŒü¾‹$Ê?@+E;ÎÈ÷*a}žNK_ø?ð¦Š(­8*[?øüúöý:Š¥³ÿÇÿ¯gÿÐã {â/ü‰Ïýz5|Eÿ‘#Yÿ¯F¢€:–ÿ¡ÿ\cÿÐV«¿ú¹ëå¿ô\Ua¿ãè×ÿôªïþ®_úùoýy·Å{‰V×K¶ ˆdy$eÀå”(?FoθgH.I$Ë*óè7âºßŠ÷5Ö—l3F’H˃±P~ªß•s6¬zHT¿„ŸÔÖùŽ˜ K»¨éÞòkÓúûŽwLÿ‘ÂËþÛÿèRÒGÿöÿõÖçÿBJ]3þG /ûoÿ¡KIü{Ûÿ×[Ÿý )åŸÇÿÀöã,gûÛô_”‰i 0@#¯4´WÖ™BàM^8üóþ5ºF ðX‘Dd,ŠO@A4ÚçªÎ~_«gD«7ECÏôHšØ“p™ÿ ÜšÖ€…x’åN{ €ÿÊ»ßkÿnð/ˆ,' öˆ®¥Dn0ÉÌ?–¨;ç漜uªF#Ù\è‡c–¶ñƒ§…,ïo®%/Š ãÛÂ[% +ª‚q€î¤)=N}MqúÜé÷Ðjvò–19‰±’®‘ncø…3U{™"‰ k BBäa]áLŸÄF?ïšÜð­¢Íam9Lù7²+6z+DþgoùÍxÕjZŸ7õ±•JŸ»¿ÕúsO«wfÓÏ8Æ Û¹¥•Ǯֵ4I3«ÚH¼n¹‹¯¡”×3swŸŽ‘ç}ŠöÁàœ±<+RÞvˆÀªYYŠêØ*C“‘ŠóÜlÔ»Ùÿ™­ %é©%{û6ÿòiKð_qFº?Ï0ÔÎ%qµ"EÃÜÅ=Žãǹõ®r¯è_ò0i¿õõþ†+x»3ìëÇš›G¶ÑEè-Ÿü~?ý{?þ‡ERÙÿÇãÿ׳ÿèqÐ=ñþDgþ½Š>"ÿÈ‘¬ÿ×£Q@KÇÐÿ®1ÿè+Ußý\¿õòßú.*°ßñô?ëŒú ÕwÿW/ý|·þ‹Š€<[âEßÚ|]$[6ýš‹9Îìùöûøü*•²íÓ¶ç8føá§øûþGmCþÙÿ赤ƒþgòBò–6/$b2v©Èôãõ®š"³¼žU#åYâ1€û¤þ4È•¡½Ëà´Ë:)Faøæ¤ŸþB£ýõþ•Ã99;y‘ÓC ¥QÆKE%òäWûÓ_c”ñnñprE¼Œ­ž„ ¦+¢‚t’{P¬§¡\íÈ®wZ‹„SnûÖÓ.1ÓÇÿf«º$¾tº[mÆ!eÆ}ô­çÓ^Hõ”U(Ô§Ûo¹/ÉšDÔb¯h_ò0i¿õõþ†* ؼ™•wgä½?¥7?bÔ-®¶oò%Y6ç¶qŸÂ³„“³=*U–#ªCí#Ü’D‘K#«JåNy~Nª?üyIÿ_W?ú9êýz+T|¬×,š –Ïþ?þ½ŸÿCŽ¢©lÿãñÿëÙÿô8é’sßäHÖëѨ£â/ü‰Ïýz5Ô·ü}úãþ‚µ]ÿÕËÿ_-ÿ¢â« ÿCþ¸Çÿ ­g_Ïul¤A¤j7»çgÍ´@€6F,@<ƒÓ=qM+»âþ;PÞ:¾SИ‡þCJ†ÅŒº´Í÷¥Rì@J•¿â/ x—Yñ<úŒüpJÑàJ€…Pr>†™eà¯âZ[É¢Þ ck.·iÖ¯7|ôèÆÙt× )5—Ykégúž¦Èáeÿmÿô)i#ÿ{úësÿ¡%u?<]‰-näÐ/ æîm£Œ™ã9þ!ùÒ'ÿaS ^edœŸ”pŽþƯ.j¯-6ÿÛŒñIËä¶²ü™ÎÑ]/ü+ßÿÐóþùãGü+ßÿÐóþùã_QõšξôgÊÎjŠéá^ø·þ€7Ÿ÷Èÿ?á^ø·þ€7Ÿ÷Èÿ>³Cù×Þƒ•œý·ü|/ãü«Fµ øâÄ™Y´+À„\ÿ„Äÿô¼ÿ¾+æ3©*˜„᪷Mz³è²Š´éÐjrIß«òGšjò0Ý×ÿÑF©êŸñ÷ý{Aÿ¢’»{φž3—X¸<=xbxÙU°9&=¾¾µZÿᦸG÷Œ¢Ÿ”r±¨=ýA®(§uèyx¦¥UµÞ_š9cþCwÿõó'þ„kGOÿíþ½ŸÿC–·u/…þ6¸Õ.æ‹Ã·“;©ùFAbGz¹gðÛÆQ]éŽþ¼ .’”–ŽþŒ?:RO‘/ëc,/»R“}+7ü|/áüš†ÿ…ü?“WD| â“0oì;Ìqü_ñ øÅ&`ߨw˜ãø>¿ã[òùŸAíé2ø»œåŤw1ynX ±àú‚þ„j˱s“èä1[ßðƒxŸþ€—Ÿ÷ÅðƒxŸþ€—Ÿ÷Åp8ÎNíj®>e%Tröï‹I n¾b²õ'(üöÆV­Ú;Uº.ù&.A#,ÓÕë[oÃÿ[øªkÙt+Å·hö‡Ú8^ÙÏcZïàÏ>8†‹y½[$yZSE%Ê´ýOuo‹½ôrÝûÏÃáü'ÊWÔõIÿI…wã¶àêqøUûö&çN‡ø^6$÷â)õ­uðŠ…ì²ócFŠÎ඘©îüâyol$Mð¬Q°s³¡(Ãù‘WK;lŸßm?óÐqŠ…žûv¾Ÿ›9ûû§‚xÝB’úû;U‰w¥ú;>âó qŒ ûqúVž¡àOÎÈcÐïÉù1ÕÉ¡«rø3IJO ƒD¼8b tùóü«²­*j.D®Ü¹»ÚúzhpЩ;7'¯#_znßâyö¹þ¾ßþ¸ÜèrêÖX òHcF’,þ?1®·Uøyâ뙡ht Æ Ê~P0Y0;úÕM/áÇŒí<ƒ/‡/~Iƒœü¯gøwî<Y«ñÁ?ñ$¼÷ÿ‘늟ž#Âz}–Ÿ j·K}³Qºš 9$C•" j3>TÿË}¬37ÅÚ^£ ÖšÖ£§ÝYOª£=Äw0´Mö• J@` JË4 û†€;µøÖŸø’ÞûˆGÿÆ*EøÌŸø“^ûÿŒWEÞ¬EÞ€=m~0£gþ%ƒþßãÿã"ü]FÏüJoý¿GÿÆ+Ê"ïV"ï@¦¿³ÿ»ÁÿoÑÿñŠ‘~)£gþ%—ƒþßcÿãæw«w K_‰ÈÙÿ‰uàÿ·ÈÿøÍH¿Q³ÿûÁÿo‘ÿñšóˆ»Õˆ»Ðªhž-—\¼’Ú ÀÉ|ý®.ODÄ>ó”\öÝž€Õ%ø€Ÿô+Áÿoqÿñš4]þ×ÃЬnd{Í·2ºDÌ1ƒå®FAÂ’ÙóÓ•¬¿i“Új ,Cöà]ÖE*|Ñþ³¯©!ú7à}ÚØ_£gýðÛÔüf¤_#gýðÛÔüf¸ˆ»Õˆ»Ðf¾1FÏú5àÿ·˜ÿøÕH¾,FÏî/ý¼GÿÆ«‹½X‹½ukâtlþæðÛÄüj¤_£g÷wƒþÛÇÿÆ«˜‹½X‹½tk¯#gä¼öÞ?þ5R.²ž/ý¶ÿV]êÄ]èmuDlÿÇàÿ¶Ñÿñª‘oѳó^ûkÿ¬ˆ»Õˆ»ÐšÝ#gç¼öÒ?þ7R,ÈÙýíàÿ¶‘ÿñº¡z±z¶¥?¾¼ð8ÿøÝH±£g÷÷ƒþÿ¨"ïV"ï@[dlÿ¤Þøün¨i7–Ú­î¡mÅâ›Y0§tgÌMÌ…¿ÕŒbX¦LÓ<ôa˜¼C«&•¥o ±šîUµ†æwUHY³™ ”ìPÏ´‘»nÑË ­«ø‡ÁÚ]–“u¤øƒG#GAl-ãÔ#vk6 ®ƒ,I+²98ÛÊÚ>ù •tÄlÿ¦^Æ?þ"¤]!?é·ƒþýÿñf.õb.ôIt4lÿ§Þû÷ÿÄRK¤¥¤M9º¹—hû°ž;(ÂîÚ;h|­Šö0HFbF?3!'’zš÷Fÿ¡ÿ\cÿÐV¼/â'Ãÿë~;Ôµ7D¹¹³›ÊòåM¸lDŠzŸPGá@Àø£âïùþ³ÿÁe¯ÿ§Š-?òýgÿ‚Ë_þ7M ¼sÿBÝçþ;þ4áð¯Ç#þe»Ïüwüi2ãn¢‰þ,ÿŸë?üZÿñºpøâÃÿ/¶ø,µÿãtÑð³Çô.^ã¿ãN |n?æ\¼ÿÇƧSXòu>&ø¯þlÿðYkÿÆéÃâgŠÿçöÏÿ–ßünš>xßþ…ËÏüwüiÃá¿è]¼ÿÇÆ¥ÜÖ>Ï­‡‰~*?òùgÿ‚Ûoþ7J>%x§þ,ÿð[mÿÆéÃù—o?ñßñ¥ |kÿBíçä¿ãIóGØõ·à8|IñIÿ—Ë?üÛñºpø‘âùû³ÿÁm·ÿ¦†^4ó/^~Kþ4áðÏÆô/^~Cüj}óXý_­¿Ãâ?‰ÿçîÏÿ¶ßünœ>#xœÿËÝŸþ m¿øÝ4|4ñŸý ןÿpøkã!ÿ2ýçä?Æ¥óùšÇê½yGÄ_ÏÝŸþ m¿øÝ8|Dñ7üýYÿà¶ÛÿÓGÃoпyùñ§†þ1ÿ¡~óòãRý§™´~©×—ð>!ø”ÿËÕŸþ m¿øÝ8|Bñ'üýYÿàºÛÿÓGÃù—ï?!þ4áðçÆô¼ü‡øÔ¿iæk©uåüˆ>$?òógÿ‚ëoþ7J> xþ~lÿð]mÿÆéïù€^ß#üiGÿÐóþùãK÷¾f±ú‡^OÀpñÿˆ¿çæÏÿÖßünœ<}â#ÿ/ø.·ÿãtÑðóÅßô¼ÿ¾GøÓ‡Ãßù€Þß#üj_¶óüM£ýדÿ%<{âùø³ÿÁu¿ÿ§x€ÿËÅŸþ ­ÿøÝ4|>ñgýo?ï‘þ4áðÿŃþ`WŸ÷Èÿ—í¼ÿXÿfõäÿÉE;ñü÷³ÿÁu¿ÿ§kÿóÞÏÿöÿünš<â¿ú^ß"œ<â¿ú^ß5?¿óüMcý—×Ùÿ䣇Žuóÿ-ìÿð_oÿÄS‡Ž5ïùïgÿ‚ûþ"š<â¡ÿ0;Ïûâœ<âŸúÞß/Ûùþ&ÑþÉëìÿòQÃÆúéÿ–Öø/·ÿâ)Gµßùígÿ‚ûþ"xÅ#þ`wŸ÷Å(ð7Š?èyÿ|RXóüMcý×Ùÿ䣇uÏùígÿ‚ûþ"œ׬Í_ü¸—Üe,«ü¿Šÿ2Êw©W½S]kÂãþf‹?ü¹ÿãTñ®x`ÌÏgÿ€×?üj¡ðÖnÿæ_qœ²Œgò~1ÿ2òw©S½g.½áÿ35Ÿþ\ÿñªzø‡Ãþf[?ü¹ÿãU/…ó‡¶_q“ɱ¿ÉøÇüÍ4ïZZ'ü…àÿè&¹Õñ'†üÌ–øsÿÆ«[ÃzÞƒ{¯[[Úk–ÓÎÁöDN aõhÀíÜÕPá¬ÞXÕ©‡’ŒZmÛd·f¸<£ M9Ê)'¼{ú—¾"ÿÈ‘¬ÿ×£QGÄ_ù5Ÿúôj+é¾:–ÿ¡ÿ\cÿÐV¾fø³ÿ%7Wÿ¶?ú%+é–ÿ¡ÿ\cÿÐV¹cá¿…5ýRmOR±¹–òm¾c¥Ó 8P£€8à ù`RŠúcþ¿èyÿ­þ ð7ýo?ð5¿Â©;ó@¥ô¿ü*Ð6óÿ[ü(ÿ…CàoúÞàk…jª$+4ŠZúWþÿèyÿ­þ¢ð?ýo?ð5¿Â´Uâ…cæ¡J+éOøT^ÿ mçþ·øRÿ¢ð?ýo?ð5¿ÂµX¨.Œ\¬ù¬RŠúOþ‚?èyÿþ£ðGý¯?ð1¿Â´XÚk£V|Ú)E}#ÿ “Áô¼ÿÀÆÿ _øTžÿ uçþ7øV‹0¤º?ëæ.F|Ü)E}!ÿ —Á?ô¼ÿÀÆÿ ?áRø'þןøßáZ¬ÎŠèÿó#>p¢¾Žÿ…KàŸú^àc…/ü*oÿÐ:óÿü+E›P]áþaìÙ󈥯£áSx+þןøßáGü*oÐ:óÿü+UœÐ]áþbölùÈRŠú3þ?‚¿èyÿþ§ðWýï?ð1¿Â´Yæ}™~æ/dÏ(¯¢ÿáSø+þ÷ŸøßáGü*ÿÐ>óÿü+UŸá—Ù—Ü¿Ì^ÊG΢”WÑ?ðª<ÿ@ûÏü oð£þO‚ÿèyÿþ¢â,*û2û—ù‡±‘ó¸¥ôGü*ŸÐ>óÿøQÿ «ÁŸô¼ÿÀÃþªâ\"û2û—ù‹ØÈùàRŠúþWƒ?çÂóÿøQÿ «ÁŸóáyÿ‡ü+EÅ5öe÷/ó°‘óÕ¾†ÿ…WàÏùð¼ÿÀÃþ«ðoüø^àaÿ Ñq^ }™}Ëÿ’°‘óЮ»á—ü”=/þÚÿ觯Wÿ…Wàßùð¼ÿÀ³þwIð†4=N-FÆÊånb å³Ü–r•éŽx&³ÅñF¶¥(ÆW”ZÙuVî8Ð’i•¾"ÿÈ‘¬ÿ×£QGÄ_ù5Ÿúôj+àΣ©oøúõÆ?ýi#ó¥s"„I<°ž^IùTçvî>÷§jVÿ¡ÿ\cÿÐV¢4qÍ€9¹n¿õÎ:òÿ Kocá­>mRðÊê’Ac KûJ &Î"R\|Ä7 I åMoGý¥yãEÓ¿µ¦F²Žî¶y1™Ý ÙKýß,6é1„mÆNêì>Òþ‹Y÷ZÛC©ÙÙGå™%” T©Ê¡ŽVRLæ"??jq‹–Àqþ5ÕâÓ—QKĄͥùÒC+F.Ö†D–(ön1™vFä`]™6“ƒ[·ú¦¥¦êm§^kU±ò%¹ÔLQÇöQ"Üd.àQS|¨ÞþðÄ•#jÛÄ0\Mpžmº¬rªFÞ`"PÉÙ•Gê=kCí/è´8¸îsâ/Gª^ v¶™¡´g†Í¡‘$¸Å°H ØdPe;2Ò)ø'GÃ)uâa¢Õµ![+EŽïbã}Á#r‚HÜ §æV'£ûKú-iE¤áÝGV½²Ó#¬Öñ\Iod#‚a_ìô¹,ƒË8bàŒ¨V (8"7ñ–²#¶¾’I.,V±—n<Ƕó¢SÌ1´¦8ƒ]™çiƒö—ôZ>Òþ‹@߉5(î®môý~»û0þқ˅"W%˜Ì#hÎ^8ÓpB¼ìÀ|µwz{]Üévs\ÍW4ª¶Ï·yP[ÙYF{0ÈïÍTÓìíôÏ0Û¬Œòc|“Ï$Ò3½Ø¶Ñ’@Îb{š»ö—ôZŸÊ“þÿOÿ£Ê“þÿOÿ¨>Òþ‹GÚ_Ñh*OùüOü?ür*OùüOü?ür ûKú-iE  ü©?çñ?ðÿñÊ<©?çñ?ðÿñʃí/è´}¥ý€'ò¤ÿŸÄÿÀSÿÇ(ò¤ÿŸÄÿÀSÿÇ*´¿¢Ñö—ôZŸÊ“þÿOÿ£Ê“þÿOÿ¨>Òþ‹GÚ_Ñh*OùüOü?ür*OùüOü?ür ûKú-iE  ü©?çñ?ðÿñÊ<©?çñ?ðÿñʃí/è´}¥ý€'ò¤ÿŸÄÿÀSÿÇ(ò¤ÿŸÄÿÀSÿÇ*´¿¢Ñö—ôZŸÊ“þÿOÿ£Ê“þÿOÿ¨>Òþ‹GÚ_Ñh*OùüOü?ür*OùüOü?ür ûKú-iE  ü©?çñ?ðÿñÊ8¸1´Ë ò™ø‹fdÞ9ûÇò¨>Òþ‹N·‘¤¼lųôÿ~:æþ"ÿÈ‘¬ÿ×£QGÄ_ù5Ÿúôj(©oøúõÆ?ýj»ÿ«—þ¾[ÿEÅVþ>‡ýqÿAZ¡5Ò%Ø´!¼Éd–U=°©9÷ùÇëM+ì«‹Ó¤yµ]Y]žG´³fv9,Ly$÷5ÑSÌ’ÇÈO’{ÉmŸxäyk.HÁþô‘®kJÿ‡‡ÿëÎÏÿD]×U¸Âwíþd²ŽµŽõ%vÁÓ×nŸÖº#\7VFæì¢™kŽ<Èá=úòþ¢¸¦×4íßK}Bo*9ÖmfÚQ,X®9ùA9öÇzѰdY4øøV£‡Ø3üÅc‰­yµÛúבÑKªF÷³þ¬z Ä'ˆ®-ü;}~%_¶»[Ϊ˕ Åm¼zc2c±çн¹4woa¼ù†a"9äì7­)Ïm¥@ãŽ}«)Þå–á œ9Ö×±·i«Y^£4S.ÆI9vH=æCÃÖ¯W”¥ÅŶ„ÑG#G=d;x!Öð€Aê1¸ô®‚_j_ÈrŒ!—Pˆ+‚#UtÈdŒc>„÷9¬cU5©ÕSïznë_ÁµFÃU¶Ô"G¹U`-È矕¿CV¡ž;„/nPì„ã«#óµM3†P”wD”QE2BŠ( Š( Š( Š( Š( Š( Š( Š( Š( ¥³ÿÇÿ¯gÿÐ㨪[?øüúöý:ç¾"ÿÈ‘¬ÿ×£QGÄ_ù5Ÿúôj(©oøúõÆ?ýkëþF;_úçwü­+i¿ãè×ÿô¬[¯ùíëßò´«§¿ÉþBfE¯üÂÿì1yÿ·5€oÿ²í´ÝCËó~Ë¥ÛOåîÛ»mµãc<ã8­û_ù…ÿØbóÿnkÏ|x»¼lrFÛ-4ñ߉Çõ®ÉIF3oúÕ‰&Ý‘å3¸’âIpÌHϹ®ÓJñ×Ù,^iUN£¹ ¤¤…Mš¦Ns¶ÌÍœØóÈj1ˆu;¸€$Π/A†=*µp9sûÏ©iÙÞ,ôÏøKôé´†EŠGEb“{E‚9ä–´`ǧÔWl²“â6˜ó"OM­©éê×€ ]`xC~íÙ]†:úüë]üKx¾)Ÿ\¶-Ëxn¼ƒ!*x$ØÆåʯ§Ý+WSžNS]¾î¿õ²2p“¾º_™é )ðòË4ª´¬±Ü-w•üϦZu ‰"9ÿRLóÔC†ýEy—‡üA,‰um¨]ì·F°/ ¹I±3ÓÍ<ŸoAZ6~2ò´«Hå¹ ¨Iu<÷nÑuóZ,‘´F—ÐŒvã’ÓüM¥¥MsV’8]²9BèˆXzŒ3ãìžj¥×ˆ¾Ó©ë}¬¥ZÀ,o·Z _ öä× ¡õ¯Ñu N]?T¶K‰"’i|”Nã,d7U'UGéÏ5BfÔîµ!ª%ijj3Hfy%PôéŸéŽÀS|Îñlu0Õg~Mº~+óOð=ÏMñk_\Bbù÷&#q€„BG^2²`g¾O¥uÝ[Ü©¸Š^¿qÃtÆz}Gæ+ç/xt(ÌgH”Û•Ù^V±Œ Ä/¯ôõ/ jbr ¬ˆÑùdQœîš$oÃåëYª³§;KTÙ窵hÔq¨´lô+"ÓÄsZÙHò®ùæ[fÇ “/´çé×$ŠŸZÔ†—¥Ïp ùÂ) *Àα³àã¶út®èEÎÖêwFJK™Wžø§\ºÅÒØÙßMQéÒ´±£Q ¬§ë†SÇ î:˜<@“ßEh-ØH÷Ü àêOÙÏ·Mo<4ã>êãRFÍQ\ã (¢€ (¨§¸ŠÚ1$͵K¤`àŸ™˜*Ž=I„¯¢Z(¢€ (¢€ (ªöÒ¼“Þ+ˆæ £Ä?ÌšMØMÚÅŠ[)ãmVh~õ- ²ã iÿŽŸÊ’±|#ÿ‰ÿ`+_ý†õHÖ0¼e.Ã~"ÿÈ‘¬ÿ×£QGÄ_ù5Ÿúôj)™KÇÐÿ®1ÿè+X·_ò1Úÿ×;¿åi[MÿCþ¸Çÿ ­bÝÈÇkÿ\îÿ•¥]=þOò2-æÿa‹Ïý¹¯'ø‡þ£Eÿ° ú׬ZÿÌ/þßûs^Iñ @WG¯‡íÛ9ë™øWEghKúûLº_ÉþG¬Ènÿþ¾dÿÐR«ºÇü†ïÿëæOýÕ*â‡ÂŒ©ü Ð(¢Š¢ËvŸê&ÿ?ÀôûÈ[Ç 1Ž,œû7ø e§ú‰¿Ïð=Z¹@öŽrÂGþòãÓÎpM›`ûá+ÍöR•NE»Óð=úrŒiFréý(©w /É$j̱ÝqßÌÀü²k_L¿ÃZ\"MpeI!…w°o‰Û9è1R=I¬¹¤fÒ¦>k~;ž®^ÚG,+–ýã²Åþ|×dèÂ…4«+ó_î³_©æÖìs|›$¿oÈétùާáë{™s²òIØ2?vÀ·N¤'ÿZ«Ç©^Ç¡ÝË4¢gSmnú$Mo:·çÉÏ9ÄÓn.4û‹ˆŒm®÷–ˆ ^UÈCŸûjÞ™Ï~+nH€ðÕÔ2É´.£n»Êõý?JèÂãiÆ´¡´¬»m{iò<éà«P{hÿEëägèJ~Ý3v—Cÿ%ä­­+Å-böNñK$Ñ+3Ë!ÎéÒ1žrA7 “x=j O0Þy2K;Œ’>é0È?J˹S-ƒÃÄæµ«™CSÙA_™Ûåµþöváð”åiÍ{G›×WþV=wÀ÷+sáxOœe•e—ÍfÉ;™ËòO^û×G^!áU´i5[õm¦-;ñŸ/t‘®ì`çÎ;ãÙj~?†Ç\´X.’{ˆ¦9 òÆvEå3`g÷¡Œç¥rb)J•›w¿ë©É^¤Gm5;¤š9DŽDf‰¶H(ØÐàƒô"«>©l¶ÂáY¤ŒË_*ó™ …ëŽ>u?çæðøþÛÃ+ñ›ui$Š÷ÿhW$€B+äcøQK{àŽ:ÖoƒµÛ«}hµYƒ$—jJà³…YmTt?t!ÇtÅeE:“ŒWS/i{yž¾/-ÍçÙªgÚÌPrFݹϡùÓƒýáU5ßùÅÿ_–¿ú>:òk?ÞÆ×Ó]³Ks=¼©Ñâ68‰w8V FsõÈg…õ"ö8.îü»qä$jÇ6Ý$œöàOL‘šõV[8{×Úß1ó¦{_£kéÇh‘-Òuù¹`ÌÊp=ÑÏûCñ·^QwâiuˆÖdÞLBhìYã0š1>r8 ÇNÝÈ5ØxZ½×4 ./Ýdš;†‹xP¥†òù±Æ: 毃8)¿/Ä¥+»= ×PÛËo¯µîd1D0Næ Ïo•óé^cñ3ÆÚ¶‘=½¾•'٠ɥ1“Dà Œc÷ç‚*§Šâ(õJ©gÿZ‡ý|ý•ÍøsÅÑêú´†{Ëx ºµµ’ÎÜÊŸë\ÊŠÜ*v‚;z ÖrxžO´È&]ÑOw¤ pp:dáTséïšç«^0µüÿš­xůŸásº¹º‚ΚâU“ß±ÀêxàzV_„ãñ?ìkÿ¡×)â‹ÛI¼0°Eu “ Jg1¤€°Ròàãӑϸ®À·?k˜I³fÝ(ñœýÉ™søíÏãV§y¤{ìðî}ݾæMñþDgþ½Š>"ÿÈ‘¬ÿ×£QZœRßñô?ëŒú Ö-×üŒv¿õÎïùZVÓÇÐÿ®1ÿè+X·_ò1Úÿ×;¿åiWO“ü„Ì‹_ù…ÿØbóÿnkçýGP¹Õ®/å¹øö´ŽÞ5áQ4dñž§¶I=ëè _ù…ÿØbóÿnkç}¡eÖ”t‘ÿ‘’´ÄÊÊÞ«å̼—ÞA¬Ènÿþ¾dÿÐR«ºÇü†ïÿëæOýÕ*æ‡Â…Oà^EU[´ÿQ7ùþ«“ÿÈ9ÿëÞæj§ú‰¿Ïð=\ŸþAÏÿ^ðÿ3^¦øÒ_“!î[ƒýzÛoý TVác´˜³ñ!ÿ©©`ÿ^ŸöÛÿCÿÇœ¿õæŸÉ«¾qRŸgÿ¤¢c'uÐÒµ*./3€Z?_¼?ª[±"ÈÀ·8÷ÍOêãÞ$ÿÐV¶ÿ—Oú÷?û-*tc²Ÿwú¥¡µJ­Ó„{/Õ±X“¦Îo4ûé«bçý}Ÿýv?úÖ3È:ãþÚÿ6­›ŸõöõØÿè^Nr’öVìÏO(wS¿xþfW‰'xE¾Ã‚á†{Œ9ùµ´ýdj8³¸¸ÿJººK('\bvàã }N~¢±|Sÿ.Ÿð?ý–©Ù3$Ö¬¤« +‚8 í–¼•é§×Rqóå¯RO[%ú3Ò4B.µU¸WrÐ[O Œñ“ Ÿ|mçý£YšˆŽËkr›Öá’3“÷{çò\~5‘¦ërCa¨Ü‡*±Ém+˜I wm½zaHǹ¯k]ÃP‘–9ž6`Àà09÷ÝŒW<9©U‹ìÿÉž-lK†"pZGÞŠ·ÞŠ×72ézf±ocæÄ5ã'Žp3ïU£-s5Ñ–6Tš+sØ>@H”¨8(cÊ—\•5­JÚÝÃ$Q\Ï+Ã|¨„ú÷Ï኱e:‹(e•AX¬ó€;,j>+¾iÕj¥MÒ»ùmù~,ß IÕ¥õŠË¿Þ­÷hgë1ÈuOµÆ%–G‚h¥yX»;.ø·݈ñõ«yòiçÍŒb…A >_”«sשíÀ§LÌÛwíß™ mé“#·õ©ív=¤°<žXšXrpWs¶Oo•½zxxa0«%ª·ÝÌ“8¦8{ËUþäP€$ír åe•Ö0>ò`ŸÅÿ<>›¢BÑjó¾¨Ýg²,ÂO“`ÞgwC•Èúеl-亮…Ôl]ùÿPÍÓÛ?¥tà³u*T‹}ä½4_רÕEÎãó-hE`×´»‰Yc…o#%Ù€RIôë>kOgk{dK5Å»G/yV9#¾:ŸÃ­y×ÛƲ©*«rzðBþë$ûdãñÓøVe²¹ºº›!b…fdþ,Gwáƒßå8úŠºµéW¦î÷ý$Í#.þgã-j8.ü",îËu«Dñ2ë$%J9‘‚%þ‘Ó5â"Õn5ÿ^G ËÜÛK¨M%®þ ÞUW–ä ©ôµijÚÍÅæ«¥B³þëLÑâÆ7?#‹PåºðáûŒ‘{ŠÏ¹µŠËƶÖÐŒGÖê:dðœœw=M|ܪYòù\Òu9dãÖ×/xzþîÃLƒPŠP‚ÒbˆíŒ&é l`ÿÀÍu€Ÿ·¸Ï×ø®Fâ×ì^Õm€p±jWR¿.â0k£¶ºVDº;ŠºÄüõåø×ŸYs'%çúkN£†­ÆVﬣoëÌ­!f‘™† ߟ5è¿ '’[I²°Ú* ÇAæîÇæÇó¯<Ÿý`ÿqô]ÿÂøüÕÿëÙ?ô1[Pø‘ôø¶¥½º/ÐÝø‹ÿ"F³ÿ^EäHÖëѨ®ã祿ãè×ÿô¬[¯ùíëßò´­¦ÿ¡ÿ\cÿÐV±n¿äcµÿ®wÊÒ®žÿ'ù ™6ŠHÓ¦±xô¦¾q¶‘¥ƒT‘Î]à ÇÔ™c¯¡¤½LÒ¡¿™]¢¶Ôoæp€*¿i'ïÅ|ïeÿš—ý{ýN!·'~õ ŠÐºÛó cþCwÿõó'þ„j•]Ö?ä7ÿ_2èF©TCáDÓø QEE–í?ÔMþêäÿòú÷‡ùš§iþ¢oóüW'ÿsÿ×¼?Ìש‡þô—äÈ{–àÿ^ŸöÛÿCÿÇœ¿õæŸÉªX?×§ý¶ÿÐÅD¿ñç/ýy§òjô^ËÑÿé(‚ÚÿÇä¿õÍ?›T6ßòéÿ^çÿe©—þ?%ÿ®iüÚ¡¶ÿ—Oú÷?û-l÷^¯ÿJBÿuÇýµþm[7?ëìÿë±ÿб›þA×ö×ùµlÜÿ¯³ÿ®Çÿ@zð3Ÿùuè{yFÓõæcx§þ]?àû-R´ÿYoÿ^7ú µwÅ?òéÿÿÙj•§úËúñ¸ÿÐe¯.?ÂûÿSËøµ}?È“Mÿ‘g\ÿ¶ú©õ½PK¦Ziß?î¡·q1Ÿ-‰ç¯FOÈþ5,§X|;ª£LÏ.;³sø)¬ªjšsmô¢<ˆÓR¨äú?ÑPÿÊØFóÿAJ–6+¢±ìl?8Ö¤ý|Ÿö¸ÿÐ B¿òoúô?úÕaµRÿ =| Ôã~­þ…–Œ3Hqй?‡ÿ®¡ùÍÿÿÑU°‡|‹ÆNï×5»˜Q²¸Y ‡èbZôñx¥õ9A»ß–ß}ÿCn´ÚVï÷¤V×ÂOª_K'ñYÄUmZö9upªû.,¥(änˆšÔÔ"id¿U ­Ì žÍ½Ï>ß0®~íŒÖð•'mªIlà÷qo”þ•äa'É.ñ·ßoò0§—J*Zk÷>_ørx˜iQYdy·’4qžÀ±·aŸl Ù´¸š?ù-w[dít®IÚŒ8îEQÓ­žö[6Œ¨2Ç<›»©Ž21ïû¶ôê)š›á…Nâ{sùÛ/øS§W’¢õ×úûŽj”*û«fßãoò/>•™$°Ææ-%˜ü±›wÈsÍ]’ÂÚëU¿¾1æ{{¸J¹b0&xéЛK º|1ã%ÞeÈ< HëŸÍÅ]‰´ë—Úe8·"¹«sFM­¶OÊÿð Ü!V¯7w¿-bŸßg÷˜:ôŒÚF£“÷§¹òáÿŸK¹èÐuÎÔ^G÷AZ£Maª*7>ŸåT<7*™ü¬ʲ1ôÁ(?¡­³·cÙ¡BjÑ¥nžŸjÿäu3ÿ¬î/þ‚+¿øQÿš¿ý{'þ†+†¼RÝû€ü¿ýuÜü(ÿÍ_þ½“ÿC8wy#j•L»™y/¹Ûô7~"ÿÈ‘¬ÿ×£QGÄ_ù5Ÿúôj+¼ðN¥¿ãè×ÿô¬[¯ùíëßò´­¦ÿ¡ÿ\cÿÐV¹ÍZþÞÃ\¶–s&À·*|¸šB -±\…Œín}iI^V]Ÿä&s¾"]¾ »ÿ–Ú™ÿÇ.«Â­-öè÷·;³æFÑíÇM²BsŸøé^Û®ßÅuá‹«XcºyË^¸Ak'"Dœ&>^¤Èœuç8ò{}V_OÒïD‡ÌÂwÉËÁŽ1þË~GÒ¹êshßV‡‰kÝPÚÿ«15ù ßÿ×ÌŸúªU»ªè:Ìš½ë¦“~ÈÓÈU–ÙÈ#qäqU?áÖÿè¨à3ÿ…T>E?´V—ü#Úßýõüð£þíoþ€ú‡þ?øUAiþ¢oóüW'ÿsÿ×¼?ÌÔ¶º²°ÊI¿ôͳÿqý½ÅZ›CÕ̓¨ÒïKy }óNGJôèI*-_¤¿&CÜŽõéÿm¿ô1Q/üyËÿ^iüš´áѵA2¦Þûßù`ÝÜcµDº&­öIöeîMª®>ÎÝpÜtë]îq²×£ÿÒQ¿ñù/ýsOæÕ ·üº×¹ÿÙkMt}OírìëÌQŸ!½[Ú¢ƒFÕÙs¦Þ °sp~^:Vî¤.µêÿô¤+[þA×ö×ùµlÜÿ¯³ÿ®Çÿ@z¨tmSì¯ömæãæ`y “’qÚµ®4½A¦µ"Æä…”“ˆ[±‡¥x9ÃRöv×CÚÊd¢§wÖ?™Íø§þ]?àû-R´ÿYoÿ^7ú µ·âMUŸìÞN›y&ÝùÙtôR×CÕÕàÝ¥_ YΧ6ïÁ"\NGæ+ÍŠý×ßú˜æ-:µmÛüŒx¿ä uÿ_0ÿè2Õ*ÝAÖF‘r‡I¿Þgˆ…û3䀲dô÷Tÿ„{[ÿ >¡ÿ€Ïþ¬wgŸßõÑ ëäÿ°½Çþ€jÿ#סÿд“IÔDÒ§Ý`ê“Éþ¥¾éLéÐúÔK¤j_Øå?³®÷ý”®ß%³Š1Ó­FNkög§‚ia ŸvH¿ñðßòZ³ù1ñž1ŸÀëN]2ÿÏ'ì78çŸ)½Ú¤þ;ÿŸ+ûôßáQ‰»QK/Ôõà¨ÔSSkw×Óüˆ$2G|cq'‘‡Úc»ÍÛ—’|íÏÞi"Ç_lçð÷­ïìÛïùò¸ÿ¿MþŽ—¨#Ün±¹\Ä@Ì,2|ù§¡èksEhaŒœc*0ƒÒö~…{[/ì‹ë›3Íß'vݸº{úf²u{/G¹‡v|‰ 9ÇÞÄ(¿û6 êo´ë×Õäu³¸d0F˜Œ†|Žžãó¬_IÔ¥³Ô=>íË´[BÂÇ8HóŽ=åE.g$ß—èyXxB®*|N2oÕ;¯ÈÒ³O&ÒÜç?¼“ÿ˜†ÚiÎ{xÕFÙrÅQÉãßå­l/¤ m'9$ygÞ©þ\ÕK>ùä5•Ê–$ŒÂØ?+{{Šì8û­«¸½?ð/ÇvqRº”­ü×ù©IþˆÈºM–Z“g;Õ›éû°?¥sÚ ¾EÍÌÛwyvÌØÎ3‚ u÷z^ ÖWжE™(¶OËô®oLÐõx¾Ùæi7ë¾ÙÕslü“Ž:T¨hÒ]¿${xš‰V„“Úÿ›;ßøöµÿsú í¾Çæ¯ÿ^Éÿ¡Šã.­îd‚ÝRÎì”\7ú;ñÀö®ÛádCy«yÐKm—des󎙎HYÊ-oÐÆ•H,µÂê÷zuøÛü¯ˆ¿ò$k?õèÔQñþDgþ½Šì<éoøúõÆ?ýjuždP«+ªŽÁˆ¨þ>‡ýqÿAZ}Kö™ÿ缟÷Ù£í3ÿÏy?ï³\oŒ-’÷VðåœÍ0‚{©VAÏ` vrq•¯jÃëÿþŸ­ÝæiöWÑG,/{âËȾúoU$¦7c<zôï´Ïÿ=äÿ¾ÍiŸþ{Éÿ}šó];ÃVúÅÃ[é“è7Óªhí¼cw+È!PœdŽ}Åoø;H²‰n¯¬ÝÄÓÛ:µü×(­þ[2û;AÁÇs@_Úgÿžòßf´Ïÿ=äÿ¾ÍE\÷ޤx¼ ­I²H–®ÊÊpTŽ„Zé¾Ó?ü÷“þû4}¦ùï'ýökÅu»½+GÕï,ÿ³d1[H±ùÓø†æ-ÌÑ«ôçûÞ½«=5ý"GTM>&v8U_\’O â³u`´lë†4¥ï¶Ç½}¦ùï'ýöhûLÿóÞOûì×™x"×MÖµÖŽ}2âÝíÞP?µî.@ìÜ2±“A5éi©+£ž¥9Ò›„Õš%ûLÿóÞOûìÑö™ÿ缟÷Ù¨«Èm­¢– P,ç¼»»–ùÙ¤Õî-Ñ+€›‡FQÀ)Nq„\¤ì‘J‘§9»${Úgÿžòßf´Ïÿ=äÿ¾ÍxÅÌšmœíÔ:|.7G/‹.•†FFA\ô5zÎÆÖký:)ôÖ[{ç)öÞ!»—þY¼€à…sÞ±Ž*ŒšJ[ìam 5Ë}¼ÏYûLÿóÞOûìÑö™ÿ缟÷ÙªðÚÃemommŠ8c $ýÑÉ'’{’y'“O®ƒ¨—í3ÿÏy?ï³GÚgÿžòßf¼·Å¯o»¯ÞÝCqr¶–ö>TßKl»¥‘Ð’Pÿ»Ô•È7Š4tb­¥m`pAñ5È þU½,5Z«š èM¥¹ôÚgÿžòßf´Ïÿ=äÿ¾Í|ü|O¥˜%š=IV%,Â?\±ôö¯nÑ´›='LÙh’ó1f–g•ʼnrN=³ŽO©¥WR½¢µÁ4ö4þÓ?ü÷“þû4}¦ùï'ýöj*ä¼al—º·‡,æi„ÝJ²¦x‹°”ƒŒ¨={V#;/´Ïÿ=äÿ¾ÍiŸþ{Éÿ}šàŸÃžŽþ;–ð\È»–3©ÜäŽé§SµˆHF#;[ÓÁ:DŽRü“ÿQ;Ÿþ9@—Úgÿžòßf´Ïÿ=äÿ¾Í`h>ÓtË™îm£¸2ˆp ×rÌYyØ€{ds‚Gs[T/Úgÿžòßf´Ïÿ=äÿ¾ÍE^wáßéú®’o/ ëÎ÷W*Jß΃ ;ª€ªàÚ€='í3ÿÏy?ï³GÚgÿžòßf¸¿øC4oîßÿàÎçÿŽQÿfýÛÿüÜÿñÊí>Ó?ü÷“þû4<Î¥ZWe=‹PCk •µ½´ ¶(áŒ($“÷G$žIîIäžM>€9?ˆ¿ò$k?õèÔQñþDgþ½Šê[þ>‡ýqÿAZ}1¿ãè×ÿô§Ð1â_ùü-ÿ_sÿé<•ØxþI÷†ÿìkÿ¢–¸ÿÿÈÇáoúûŸÿIä§éšÞ£kàíGþÊñÍ•¬Ë=“X6ò‘… y²0ÚO?tNE^ø+ÿ$Cÿ¶ÿú>J<1þ§Wÿ°…ÿþ–ÉY¾ºÿ„>Â->ËLñmÆŸ 2ÅkrÚqT,Û‹WV'$õb9^Å Ép9®÷ÅÕµÞ\Ç¥\Ïnn⹆Hf…C…;ƒÕOj¥}ámsP¶òdÐoS ].-ƒ#Tùœñ®©óéëï>§ SõzªNËM5¶ëTÚõ:?…‘4:ýÜO!•Ò%i«Ór~µé5Âü=Òµ; ~îâþÂKD›ìÉ’HرVŸ¸Í¾½kº®š)¨$÷êÚ¥í­åçŒe–êÖ4ŽþŵÔ)%Ná $‚IÜyÏzõ›ùxÿ®_û2Ôµá»ì½?Ìó~ËefÝ»¶ì\ãœg£@yÇ…ãÿKÿ®Z·þ–G^^}áÝ ßi·qjvSÁ=üJöâ3¹^å‰:0ëôÅ/ü¹mÌKûcì¿hþ/'í¾G—é³gðôÝóýïšK8µH'ŸM•¯nõ ØWRMƒvÙ'ÄNw`.FÔî7¿±-¾Ûço—Èó<ÿ²dy>vsæcÎyÆvîùñ»æ¦C Á ú\‹‹†Š9¤¸†ÕŠùqJû·¸!w’|É8,GÎp:‰?åŸýrOýS)òË?úäŸú¦P'ñþDgþ½Š>"ÿÈ‘¬ÿ×£Q@KÇÐÿ®1ÿè+O¬ùõ[®¹¼¶Ü±¢eQ‚>¹ßíËùû¶ÿ¿Ë@šÞ .!žH"’Xrbi6ÂF èqÆzà‘ÜÔþgý3‡þü¯øVWöå‡üýÛßå£ûrÃþ~í¿ïòЯ™ÿLáÿ¿+þy§k(XÔ0ÁÛŒ÷ì++ûrÃþ~í¿ïòÑý¹aÿ?vß÷ùhJ¢¸¶‚ò‚æšáã‘C+B{ RþܰÿŸ»oûü´nXÏÝ·ýþZÕó?éœ?÷åÂ3þ™Ãÿ~Wü++ûrÃþ~í¿ïòÑý¹aÿ?vß÷ùhYf*Á•" A/¥GY¿Û–ó÷mÿ–íËùû¶ÿ¿Ë@TËX`²·X-­­ã‰rB¬+Ôœ’xä’I'©$š¡ý¹aÿ?vß÷ùhþܰÿŸ»oûü´«æÓ8ïÊÿ…gý3‡þü¯øVWöå‡üýÛßå£ûrÃþ~í¿ïòУ¹vÜØÎàc§ÚÍþܰÿŸ»oûü´nXÏÝ·ýþZ¿C<Ó¥¼tÛD’4JÌÁzHÎNNO©©¼Ïúgýù_ð¬¯íËùû¶ÿ¿ËGöå‡üýÛßå  _3þ™Ãÿ~Wü)BÊ @U ü¾•—ý¹aÿ?vß÷ùhþܰÿŸ»oûü´¥Qµ¼\C SANE-umax - UMAX parallel port scanners
SANE-logo
UMAX-logo

UMAX parallel port scanners





The sane-umax library implements a SANE backend that provides access to several UMAX-SCSI-scanners. Parallel- and USB- scanners are not supported!

But there is an experimental parallel port driver for UMAX scanners.
Don't ask me about that driver - I do not know anything about this driver!

Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-advanced.jpg0000664000175000017500000003773412112021330017103 00000000000000ÿØÿàJFIFÿþXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀë#"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ô-STM.8Ù¢B…cXQŽJÜ}k3þûùàð:<_ÿýbÿÑuçwñÝ[N·6ó±RÜÄïÇêz.¿LêO‘sZç^ ±5=—:‹{_fû_¡èŸð—ÛÿÏÿ€ñÑÿ }¿üð?øp¶—+zLŠãq±Iëê}½?ǦWˆoÞYii-ÜK>én$²ËKj>^I±>Äw5Q’’ºØÊ½ П³¨­%ºìzü%öÿóÀÿàËý«ý›åí;ú}ýÙÇ^Û}³Þ€=_þûùàð:?á/·ÿžÿã¯$Ò¼I©_e £´Oíœ!Ec±£èÄÈí·=³»œ Ý7\¼´Ò´[‹‡k¢ñÞÊKÈáˆIØnA䃌2@=·þûùàð:?á/·ÿžÿ㯺ñf¥gdÎñÚI+éðÞÆV6U]ò*•#qÏÞë‘Ó¥^“\Õ啬61Oqg$EŒYm±º–8RAr1‚7dp:PªÿÂ_oÿ<þÇGü%öÿóÀÿà›«ØÜ=ܳ97ª•wTòŒr?½Ž¿6k=|Q©jZSªGR2{©K)áÙÓ´ŒnÏ9‘ñ%•ÅôQEm÷&#py~ÿZæG†uA!Ú’Ä`fDàzÏå]ãÇÐÿ®1ÿè+O¢ÃRkcÍ£ðUü7_hŠÞHÉ<ªÊ›~˜ÏJ—þûßí·ý‡ý+ÊòwùÃîg8Æìu¯D¢¦0Œ~k_V»N¬®Ò¶½-†é$“HÚB—œ¹”ùÿ~ ÏÍÏ ;‘ƒV‚'+f­¥ÆÂËgÝ"“ ?N½À=@¯H¢¨Äó;¯Éy4ÒϦni$ Oµd8Ü`‘ž äqŽ‚›ÃçŽ5tÖ!nEØ-s¸ù£ø‰-“øñ^EyŒ?ŒoM)HÕQæ ˆïBÅW=ðSSáÞÈdˆé^bI€ù·aŽB©f%@<ñŽ@ôêP›Ùx"ãOšy­tý’O·Ío8åz–ëÉÉêIÉɨÿá“íŸjþÌýç›çãÏù<Ìc~ÍÛw{ã=úצQ@Káï‡Z†“ciö‹žúãÌIAQ¹‰ÈŽq€N3Œâ­'Ã¥Žd•tx÷&ð Ê €ùܸݼŸ— ÉÀäרQ@[ÿ ày m-5ˆïº,B)ÈPKåFpp08©¦ð —O4ºfeãwq>rp¤ß)£é”PÙø>öŠÚÇb³—bf ÌÇ©$±$ûš«7ÃçŸPûtškƒ"J[í8ÐaNÐØà{zú×§Q@n|pn..?³ÿ{pñ<­ç˜ÆAC÷¸ÆN½ê8¼$7‹w™‰ÖY& çÿ€8ÝŽ@Ò½2Šó?ø@dþØþÖþÌÿNÿž¾û;znÇN:Uˆ|{åÍÜv;g¹Ûæ·œí£ØzW¢Q@c/ÃçšI]ôÖ"Y²F.q¸Ç,¶žƒ9÷­/øGu_ùõÿÈ‹þ5ÞQ@wÿ}ïöÛþÃþ•åy;üá÷3œcv:Õ{Üi¾X´³ž4;cûkÎ~Røî{W¦Q@c/Ãç§2i¬Và––1sˆÝˆÁb¶ç€sŒäg¯4é¼%ÄÓÍ.™™gxÝÜO†Üœ)7ÊG¨Åzeä÷õ[ag¤ZJ±ÊòH·3—æIÏBΣÓ~\A£ÚÚ_ØGq4QÞîºîû»1מy©´ÄÅWέgm–(ãżþ`CŒòþ!ë]åG?ú– –~!Èý¬×ý”QGÄ/ùµúïÿ²Š(êvÿ¡ÿ\cÿÐV‰Y•Wb†wuE p2Ì“ƒëCÇÐÿ®1ÿè+Cÿ¬·ÿ¯˜ôbÐ&©Þø‡NÓ.'™-ä´¹ÖÒæH‹:<*§zml#ñÓž‡Ö™âë‹™¬aÒí¦¸Ó—ËOy-•ç·Œ«üÿ½8¸œ§O›‚oj¶°Öö×3NÒÁn°ÆP¬‘]GjI ø`Í.ð¹L´±ÎñÕE£éÉ<‘iÖq½Ä‹4Ì(2:¶åf8åƒr äií¦Ø:25•³+,ˆÊbR ÈwHòÞ§­qwºþ¹ ‡S-m ·Ñõ)¥³#z¼°:(,RR çoË–)ó®âNF¼Úî§k­Úi71Ù­Íç’a*aù¦yÔrÛ"@ Ô¡€RèúdÑÁºuœ‰oC ¼ Dh˵•F8R¼8#Šy°‰µDÔ¦Ž‚5$mEf øõ,U3œã`Æ2r9[Œü¦×·Jàþ?!£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€¶çÖÏþþ¿ÿ£mÏ­Ÿýýþ7O¢€rÒ¬ž^csvïP?»úÒOþ¥©bÿ]uþì?ÎZIÿÔµ|³ñ þGícþ»ÿ좊>!Èý¬×ý”Q@S·ü}úãþ‚´?úËúù‡ÿF- ÿCþ¸Çÿ ­þ²ßþ¾aÿÑ‹@¢¹¿é¶ú]«ÞY[\4wöh4JåUîbW#€Ãƒê:×?¨k׺m…ð°¿Hî­–ö3¥¤Qm±‚æ0Ì.õˇ–%›Àù—‰EsF©¨ÝI¨%¥Ì:¯•.¯0û:$ÌÎ%„íF)°*Œ×~œ‚3ÏâÏútÿüþ=@UÊýŸÅŸô0éÿø*?üz³ø³þ†?ÿGÿPUEr¿gñgý :þ ÿ«~&—P·Žã_²hE,znÖ+ž@&RÇ|zß‹ýu×û°ÿ9i'ÿRÔ±®ºÿvç-$ÿêZ€>Yø…ÿ#ö±ÿ]ÿöQE¿ä~Ö?ë¿þÊ( ©Ûþ>‡ýqÿAZýe¿ý|Ãÿ£†ÿ¡ÿ\cÿÐV‡ÿYoÿ_0ÿèÅ Ô7–_ØÜYÝ'™oqE*dÊÃdr8=ªj(¢Š(¢Š(ªºvŸm¥iðXY«¥´ ²5yB«Øe‰8< À«TP&‰g‚H\¸Y©(å1Ã>àäS,í °±·³µO.ÞÞ5Š$É;UFÉäð;ÔÔPEP\׉>"ð°'í“é4µÒÒ«}èJ¸nß ü¨‡–ÿÜoÊ£¹ÕàÒ-Oo}+Êà¢ÚÙË9ã9ÎÅ!~ðëŒóŒâµþÓ?ü÷“þû4}¦ùï'ýöh˜ÿ„ÆÓþZ÷þ .?øšjx¾Ñd™Ž•¯aÄ`Ħãøwçø?ÚÔý¦ùï'ýöiß½ÄÏÛK Š$I7+)yP7ÿ §ýµïü\ñ5SÃ"Yæ×.Í¥Ü1Üê&X…Å»Ä̾LC;XÔøW_ ûÜAð]´°È¡ÒD“r²‘AE?í3ÿÏy?ï³@ž[ÿq¿*<·þã~U§ö™ÿ缟÷Ù£í3ÿÏy?ï³@ž[ÿq¿*<·þã~U§ö™ÿ缟÷Ù£í3ÿÏy?ï³@ž[ÿq¿*<·þã~U§ö™ÿ缟÷Ù£í3ÿÏy?ï³@ž[ÿq¿*<·þã~U§ö™ÿ缟÷Ù£í3ÿÏy?ï³@ž[ÿq¿*<·þã~U§ö™ÿ缟÷Ù£í3ÿÏy?ï³@ž[ÿq¿*³`Œ5 RñÚ­}¦ùï'ýöhûLÿóÞOûìÐx¿×]»ó–’õ-Kúë¯÷aþrÒOþ¥¨埈_ò?kõßÿeQñ þGícþ»ÿ좊ú¿ãè×ÿô¡ÿÖ[ÿ×Ì?ú1hoøúõÆ?ýhõ–ÿõóþŒZ«¨kf“åÿij6v~n|¿´Î±ïÆ3ÄgZ†h® Žx$Ia‘C¤ˆÁ•”Œ‚ꬿC,ú\) o# û'*ŠI ·13; >€äµÙµK{ Vx¤Õ"Ôc[÷¹“tËÛæ0ÉýÐaþþ¯çëŸã D¦¢YÒ" YÖ2Ãs( p .~£Ö¹½!u7“P[I¯!C;_V‰¤"çsùß.åÊíòñå‘s³¸¬ÿZxˆ\Ûȳ¤³­¤è×vr"ÇOi¼m3ز‘µƒ|¸ašìno-lü¯µ\à †/5ÂïsÑW=Xã€9§Ã4WG<$°È¡ÒD`ÊÊFAuW§h÷7¶=ôºŒ¥tëØšrÓ[áL±ˆÁQ!*Å Æã样Ο)cçi¿ ´é“í–ï§Û[Ü\¤ÞbJW™~yêÂ@Zìfš+x$žy(cRï#°UU$’z(†h® Žx$Ia‘C¤ˆÁ•”Œ‚ê®cTŠò/…ú¯ö¶É¥ÜËp¬û¼¹ÙäüªXªŒœ('­R¹‹Qnác­ ¹/Ñn O"D-Íâö0#ÈÎLG»Ìù±@Ýå­…«Ý^\Ãmn˜ß,Î'$ð9 ~55yÞ¥£oáýhLoŒéz²Ëö‡‘Ô¤ o÷‰ÚLEŽF ýã¸ó^‰@Q@W3â¹.ÛPЬ­u ›%»¹’9d·+¸¨…ܘÕGj騮Oûûþ†½sþúƒÿU‹O ]JÒyž*×Ê¢n½¸îüñ>´wÄVw÷ú|vÖQÛJ­:˜®&h„‘Jn Ü1  ¡aÆsU¼/ ÿ£iš¥–Ù[NHåãgMªª¥_*bÊö€ÈRiÿðŒÉÿC?ˆÿïý¿ÿ¤s/—ÿ ?ˆó°¿úë~€¨ÿží ŸÂ°Ëoàý ãx¦ŽÂxÝJ²°A„׬/øFdÿ¡ŸÄ÷þßÿŒV'ö}ìž&¿Ócñ>º°ÚÛ[Ë–x ‘¥Ï>V1„\q×>ÔÜQ\Ÿö÷ý zçýõÿ£ûûþ†½sþúƒÿPYErØßô5ëŸ÷Ôüjì ïúõÏûêþ5@eÉÿ`_Ð×®ßPñª?°/¿èk×?ï¨?øÕu”W'ý}ÿC^¹ÿ}AÿƨþÀ¾ÿ¡¯\ÿ¾ ÿãTÖQ\Ÿö÷ý zçýõÿ£ûûþ†½sþúƒÿPYErØßô5ëŸ÷Ôüj­iÞº:•·â]jhüÕ-¼!\g•%c§q@ñ®ºÿvç-$ÿêZ–/õ×_îÃü够ýKPË?¿ä~Ö?ë¿þÊ(£âüÚÇýwÿÙEõ;ÇÐÿ®1ÿè+Cÿ¬·ÿ¯˜ôbÐßñô?ëŒú Ðÿë-ÿëæý´údÐÅqOK ŠQãu ¬¤`‚PE>Š(¢Š)’ÃèhÒE ®ÔHe<÷=ú(“CÄAeëŠéh ?³ï?çÚOûæìûÏùö“þù©&š+x$žy(cRï#°UU$’z*®ŸªÚj~`·3+ÇñÏÈÎÇPÛN%HìhoìûÏùö“þù£û>óþ}¤ÿ¾j–¿a|,â‘ÜÚUK›) ÜªT1DPp]zzÖAýŸyÿ>Òß4gÞÏ´Ÿ÷ÍOEAýŸyÿ>Òß4gÞÏ´Ÿ÷ÍOEAýŸyÿ>Òß4gÞÏ´Ÿ÷ÍOEAýŸyÿ>Òß5=••ÔwÐ;Á Pà’W¥P"ÿ]uþì?ÎZIÿÔµ,_뮿݇ùËI?ú– –~!Èý¬×ý”QGÄ/ùµúïÿ²Š(êvÿ¡ÿ\cÿÐV‡ÿYoÿ_0ÿèÅ¡¿ãè×ÿô¡ÿÖ[ÿ×Ì?ú1h®¥ªÚi1Â÷foßIåD°Á$Îíµ›QIè¬zv©í.ྵK›gßç‚ à‚*À‚8 ‚¬_ØÏzºSEgyt–÷¦Y£³¹K·É•2¯½1ó:ç 8ÏZç¦ðÞ¤Ö“$š_Ú'žÙÓO”¼e´ÉZYœJìÍø’Ïöfˆ’X…,Ú>­cŸ¾|y1ÚÉò7Ë,›6/Nsæ§#žz]®RðÂËý¿ÃqçjÖw±á ÿHEò¼À70ù¸Ÿ;°˜y;A«xoRº·Ô¢·Òÿâa'ÛšMC|cíqKÂ(7nÞv™!py\•rè4W%iáÙ,<@—6vÛ[¦¢BB&Û3iÊ:'Ú mŸÞ;±Þ¦Õ¼=s§yWÔoÃÜÛŠS [Un#wuhÑ0Ula¾œâ€:D•dyUCƒmmÈT€x$|Ãr23‘ÔL‚î ™®b‰÷=´‚)†ÚÅñïòºž=k„Õ´èt}FâêúÚÍ4—¹hí!–ê;hÒCol±J¤‘åìòfPÉ™ªM3þ¼‡C¶»{Ré­ HØx¡H­Rl~BBJ¬8,#€;ë[¸/aimßz,’DNù‘Ê0çє¦®cFÒŽ•áZÎ=››ÇŽÏ÷KÚ³±Œq¡Dù€ÀÆ«ºu¦Ý]Gr~ÒZ8Jß3ò`01a™›jc “Ï™ÎçÞì¡c¨[j)3Ú³²Ã;ÀìѲ èv°€Üdddx«UÀè6muªÍr-Rù"¿¸Š9p¦ÂE¼ä'Ê]>áB¾ƒLÒü%w§ÚiþV™ öÚgÍJL%?l ƒ÷š0¡ˆûàócÛéú…¶©f·vŒí 3§ÏFÁ•а*ÀC)ŽÕj°¼!4Wω,2_ÞºHŒYMÔ¤GPEQñ}º^jž³•æXg»•dLñ  ÊAÆT½¨«¢¹øC´MCÿw?ürøC´MCÿw?ür€:ê+‘ÿ„;GôÔ?ðgsÿÇ(ÿ„;GôÔ?ðgsÿÇ(®¢¹øC´MCÿw?ürøC´MCÿw?ür€:MJÕo´»»G…'YàxŒO!\2‘´°¨9Æ@$Vƒem©_êw0j.×1ÛA¶òXZbQäËâ6òÕȼ. ØÇi'-vox~9äAky…bu[¿_úëPOá- yeûãlBØþÕ¼ÀÏüõ  Úe¤âûPÔoeÅÄžTivAaÈàî%äõnÓ÷EiÖ,¾ Ð#•Óì·‡kŸíKÎò-ax£ÃšFŸ¦Û=¬7±É5ý¬Æ©tp¯2àÈG*HüsÖ€;z+‘ÿ„;GôÔ?ðgsÿÇ(ÿ„;GôÔ?ðgsÿÇ(®¢¹øC´MCÿw?ürøC´MCÿw?ür€:ê+‘ÿ„;GôÔ?ðgsÿÇ(ÿ„;GôÔ?ðgsÿÇ(®¢¹øC´MCÿw?ür­éžÑÓTµ}—¯¶Um²j§8*\‚=ˆ ÐAúë¯÷aþrÒOþ¥©bÿ]uþì?ÎZIÿÔµ|³ñ þGícþ»ÿ좊>!Èý¬×ý”Q@S·ü}úãþ‚´?úËúù‡ÿF- ÿCþ¸Çÿ ­þ²ßþ¾aÿÑ‹@¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¬McMº¿×t -㠭IJÌìáB)…Ðu<üÌ£ŸÀÛ¢€"þΛûðÿßÕÿ?³¦þü?÷õÆ¥¢€"þΛûðÿßÕÿ?³¦þü?÷õÆ¥¢€"þΛûðÿßÕÿ?³¦þü?÷õƳ·u¨tÙt›èŒí ŽvhYPd¾Báz •ºƒ‚E ®<ºµÅ¾“}:ÛNMr‘£H€®¤áO|f€áüg-Ä’G§xy˜­ª»øùCùUy¡ñ¤ÐÉXøt+©SNLàúå]ˆíãy$g6ËN59?øÕQÔ4ë iݾ… ^Apï ìØŽEr1€rEu4P_ÙÓ~ûú¿ãGötß߇þþ¯øÔ´P_ÙÓ~ûú¿ãGötß߇þþ¯øÔ´P_ÙÓ~ûú¿ãGötß߇þþ¯øÔ´P_ÙÓ~ûú¿ãSZYÉ ä2;õ\ûÕÿJ(‘®ºÿvç-$ÿêZ–/õ×_îÃü够ýKPË?¿ä~Ö?ë¿þÊ(£âüÚÇýwÿÙEõ;ÇÐÿ®1ÿè+Cÿ¬·ÿ¯˜ôbÐßñô?ëŒú Ðÿë-ÿëæý´KUÕF–-³¹»šê"(­ö-±Üòì  ¨Ýéx‡L’VšîYndxc‚æEIT}Ž€gæ`ÿ/ËOBAÕñ>.±œ#²±½[k¿>Kkæ+‹åHv? ¸=;VCxWSK ÛHžÌ¦¥dl¦ +(²Bó2ˆ†Óæ*,ûBŸ,b%é» ©qã] ×íÞmô+ö+ج¦Ì¨0ï·Ÿ½÷F[9Á\œ|µ¦úÆ™ÕÅ«ê6kqmšxŒê$Ì3•\rxäV-Éý±ä-›}£Q´¿¶ó'eÝåy‘ð‡oúŽÝÝ9¥ªxWS¿ÓntÄ{5·^ÜA9•·»Ü$ê“nTܘ3°|£w=¦±¦_È‘Ùê6w.ñ™‘a\²ÚXy]ÀŒôÈÅZ–h @óH‘©e@ÎÀÌB¨ç¹$êH¬/ì+¯í϶ùù_ÚßmÆNv}‹ìøé÷·óéŽùâ£Ô|#kqbmá{™ƒÏnÒÇ}}=ÄmOŽ6ÈÌ2UéßšÔ[Ó¤岯ӤÈgŒ¬Î计0Ç$†õË?é—·okÜ>o™å ‹þ‘û¤—t|üêE9Ëšçµ}.çOÕouc71^I$A¶šàå†ÝK2FŒ[Øüœ 2êx,м#yiáÕ†hí¢½–}6YrÁ-ÒÜ23rAŠ\HùºŒšé4Ïéš¶™>£kw ´‚Ic–S"íO-ˆ,H$ nŸºAïZ 4R¼©ˆíl‘U(Ø ƒèpÀýõ¬(´‡O ën§Å½Ä—­ºÐ´’fw|…Ùà9@n@Æsгá«;ËM6Ô¶i\³\Ýí$s™ÉÈA¶0r~T°(Ó¼I§j|m2Zm>Ûä\ËÈ–ý¤`áqÎsÆyÁÈ©âÖôë´?`¼¶¾˜ÀÓÇ ´ñ³Ê€•ÊüÀcpÛ’@ÏŠâô ê7~ k%†Ú1y`9½ŠDš f¶¥ùFW>fNA*‚º ´{ˆ5Y57t0Gª@ª+;˜Å‘€¡I-»œ£ßŠÚÓoâÕ4»MBu†êÀ ”0Î3Î M,ðÁ6XãÏMìk3°Ëoàý ãx¦ŽÂxÝJ²°A„Êñ}¥µö±á›k»x® {ÉwE2Vż„d é>ßgÿ?pßÁGÛìÿçîûø+Ÿÿ„OÃô/é_øøQÿŸ†ÿè_Ò¿ð ?ð ƒíöó÷ýü}¾Ïþ~àÿ¿‚¹ÿøDü7ÿBþ•ÿ€Qÿ…iGáO %¬ðÞŠK!$¶ 'æ=ÊÐmü­^j7¶¬J¬ª²ƒåÄfëÑ™ÉÎ8*‘÷‘s`·z¼¦ÞàÉ ÒjËþ“Í¥â`2+)»r|¯‚§6×ü"þÿ¡kCÿÁlüM6/ xqàG>ÐòÅÁÆ›geÃè_û}ŸüýÁÿo³ÿŸ¸?ïà¬ÛŸ øvY¥_ he‘†tØq?Ý®sÃÐ.<'£M6‡¦I,–0;»ÚFY˜Æ $‘É4Úý¾Ïþ~àÿ¿‚·ÙÿÏÜ÷ðW?ÿŸ†ÿè_Ò¿ð ?ð£þ? ÿп¥àá@Ûìÿçîûø(û}ŸüýÁÿsÿð‰øoþ…ý+ÿ£ÿ ?áðßý úWþGþÐ}¾Ïþ~àÿ¿‚·ÙÿÏÜ÷ðW?ÿŸ†ÿè_Ò¿ð ?ð£þ? ÿп¥àá@Ûìÿçîûø(û}ŸüýÁÿsÿð‰øoþ…ý+ÿ£ÿ ?áðßý úWþGþÐ}¾Ïþ~àÿ¿‚·ÙÿÏÜ÷ðW?ÿŸ†ÿè_Ò¿ð ?ð«šW†Yø…ÿ#ö±ÿ]ÿöQE¿ä~Ö?ë¿þÊ( ©Ûþ>‡ýqÿAZýe¿ý|Ãÿ£†ÿ¡ÿ\cÿÐVœUXaÑ{«¨`Å-Ï"Ûþ|ìÿð?Â"Ûþ|ìÿð?€E3ȶÿŸ;?üOð£È¶ÿŸ;?üOð ÑLò-¿çÎÏÿ“ü(ò-¿çÎÏÿ“ü(ôS<‹oùó³ÿÀdÿ <‹oùó³ÿÀdÿ }Ï"Ûþ|ìÿð?Â"Ûþ|ìÿð?€E3ȶÿŸ;?üOð£È¶ÿŸ;?üOð ÖN©¤Í©k:-ÂIqYM$²—Ï Ä蜸=†öOȶÿŸ;?üOð£È¶ÿŸ;?üOð ì ÿ?qÿß-þ}?çî?ûå¿Â"Ûþ|ìÿð?Â"Ûþ|ìÿð?€°'üýÇÿ|·øV}þŸ®Í*‹i–¶è0ˆút’?©Ëy€Iè½kCȶÿŸ;?üOð£È¶ÿŸ;?üOð  _ìÿÐÙ¥ÿà¡ÿøí"èþ(Tvø ŸáG‘mÿ>vø Ÿá@Øþ~ãÿ¾[ü(ûÏÜ÷Ë…E·üùÙÿà2…E·üùÙÿà2…`Oùûþùoð£ì ÿ?qÿß-þyßóçgÿ€Éþyßóçgÿ€Éþ}?çî?ûå¿Â°'üýÇÿ|·øQä[ÏŸþ'øQä[ÏŸþ'øPöÿŸ¸ÿï–ÿ >ÀŸó÷ýòßáG‘mÿ>vø ŸáG‘mÿ>vø Ÿá@Øþ~ãÿ¾[ü*[kX๊SuÀ¿Â¢ò-¿çÎÏÿ“ü(ò-¿çÎÏÿ“ü(‹ýu×û°ÿ9i'ÿRÕ"„ Ç 1«HŽ%Lã8ι¨çÿRÔòÏÄ/ùµúïÿ²Š(ø…ÿ#ö±ÿ]ÿöQE}Nßñô?ëŒú Ò¼‰‘Õuf8‘¿ãè×ÿô¡ÿÖ[ÿ×Ì?ú1h7Z×ítm:;Ç+$o Qµ¸Úy »Høï³’*-SÄÖ:mÄv»¼Ë—¹‚ßf(idEÛ¿w…}û3¸¨Îæ¥Ôt(õmX_^ÜÝ(V ‰ hÉ9—`Ø‹ƒÀòÁMcÛx.{H~É­²Çí°Ýù?f¿rñùqn-÷qF½7]ň%HÑñš-mnY¥K«oµ@!¶’Gx²ƒpURßòÕ8Æyö8¼Y¢$‹^üæ13/”ù 2–q‘U‘ƒÀB0Ûr*ð¤N¬‘M°ßÈ®2¥•T9ÆëŸG˜°ã+)L€)Zx'ìšf³b·°¬Z‘´E†×bÁ¹¦v!w®ùÛjñ… 2NX€m?ˆt¤’â6ºÃAß»oœ† Dg¼`ä! ¸†!O$ ¥ªøÇJÓt‰ï–_9£¶yÖ=¬¸+¸‘¶þé™Ô ‚XEGsáVº±¼Óå½G°–v¹ŠÝíƒ1§Ÿ7'÷‹¼chÙò1“†®<#i—6VzŒ6Iydm.|›$UtŒ<¥\Ìàƒ¸•ÇÌ.@:w»¶‰ÊIq0ê¬àMû}ŸüýÁÿ\YæE ²º¨ìŠ_´Ïÿ=äÿ¾ÍRû}ŸüýÁÿo³ÿŸ¸?ïà«¿iŸþ{Éÿ}š>Ó?ü÷“þû4Kíöó÷ýü}¾Ïþ~àÿ¿‚®ý¦ùï'ýöhûLÿóÞOûìÐ/·ÙÿÏÜ÷ðQöû?ùûƒþþ »ö™ÿ缟÷Ù£í3ÿÏy?ï³@¾ßgÿ?pßÁGÛìÿçîûø*ïÚgÿžòßf´Ïÿ=äÿ¾ÍRû}ŸüýÁÿo³ÿŸ¸?ïà«¿iŸþ{Éÿ}š>Ó?ü÷“þû4Kíöó÷ýü}¾Ïþ~àÿ¿‚®ý¦ùï'ýöhûLÿóÞOûìÐ/·ÙÿÏÜ÷ðQöû?ùûƒþþ »ö™ÿ缟÷Ù£í3ÿÏy?ï³@¾ßgÿ?pßÁGÛìÿçîûø*ïÚgÿžòßf´Ïÿ=äÿ¾ÍRû}ŸüýÁÿo³ÿŸ¸?ïà«¿iŸþ{Éÿ}š>Ó?ü÷“þû4Kíöó÷ýü}¾Ïþ~àÿ¿‚®ý¦ùï'ýöhûLÿóÞOûìÐ/·ÙÿÏÜ÷ðQöû?ùûƒþþ »ö™ÿ缟÷Ù£í3ÿÏy?ï³@¾ßgÿ?pßÁGÛìÿçîûø*ïÚgÿžòßf´Ïÿ=äÿ¾ÍWŠh§ a•$ €Åg¦qô4“ÿ©jz»Éqt]ÙŽØFXç¼´ÉÿÔµ|³ñ þGícþ»ÿ좊>!Èý¬×ý”Q@S·ü}úãþ‚´?úËúù‡ÿF- ÿCþ¸Çÿ ­þ²ßþ¾aÿÑ‹@¢±|H&–ÞÎÚ ’Ü\ìùòAöŒFí³ÍŒwävmèÕÌA®jv­ªÝ[I¾ÛLÓ„³Ãy+LKE5Ò¼q‘·¯—´JÙl"V$àÐh®.ê0j“Ú,PÍÒ4VwF-…ÌVìó¤ÚÓsÄyòÎ2Ì%Õ­u»äG³¼¸¦Ý@¸“ÈÎí>"„æW$Å |Û€=Šäˆµ4¿ŸLy4帲ó¤žêUhá‘#HŒn&,‹€ ’àl'iÝ€_êZž¡à]Rµ¸†ÒîîM>IH™y,YPƒ·-È$år½ò:Ú+ˆ½ñýºßmŽÅ$ÓçTº[–h•VKÏ*['h0«»?Š6‚Eþ,Öln&°ŽÎÚîêͦ{‰“l1¼qLJ‰%PÅÀ÷>6´ç ÝÛ€×1À ýi~ÐÿÝþý/øQmÿPÿ¾¿Î²µ«ùtí7ÎPÌóÃn…Á*­,«b2|ã#8ÆFs@¿hîÇÿ~—ü(ûCÿv?ûô¿á\m׉5MBÎ lïI¢Ú>#2NÐ+ù Û–÷a$*Q”°ÈjËÓYø…ÿ#ö±ÿ]ÿöQE¿ä~Ö?ë¿þÊ( ©Ûþ>‡ýqÿAZýe¿ý|Ãÿ£†ÿ¡ÿ\cÿÐV•оÌ>®®nîUƒ23ÓÖ€#»³µ¿µ{[Ëhnmß♣`äd £m‚Àð +a À¶í‰v´@##¨ Ø9>µ?•'üþ'þŸþ9G•'üþ'þŸþ9@eÑôÉæšitë9%Ÿs¼ LŸ!O˜ãŸ‘™yìÄt4&¦G³ËÓ¬×fÝ»`Q·nÌcŽ1åGO-º1kÊ“þÿOÿ£Ê“þÿOÿ  ýSC¶Ô£PìÒ­ÊÝyÑA ¹‘WhoÞ# Àc#hâ¦Fý‘’öp˧ÅD¶ó/˜›SA œã¯¥Zò¤ÿŸÄÿÀSÿÇ(ò¤ÿŸÄÿÀSÿÇ(=ô+Y!I‹O{ì’dež7FAÓ@‰’'$±™4}2;[{TÓ¬ÖÞÚA4$N !”c Ù$äsÉ«^TŸóøŸø øåTŸóøŸø øåX¶ÿ¨ß_çT.'°š)m®e¶xÝLrE#) H=GlT“Z}¢ žxe†E(ñ½žåe#däYð…xwþ/þ ãÿâ¨ĶÚÑÁ°i’%¼m *é£.ÖU”¯⟠h–óÇ< §Å4p t‘+,@äFè öéU?á ðïý4_üÇÿÅQÿW‡è¢ÿàž?þ*€%‚ÃÃv°<öšL0ºº4qÇ«+€!‚®}vŒô§Åm A43E™°gÉtHÁä òžß"ªñÙ@è*¿ü!^ÿ F‹ÿ‚xÿøª?á ðïý4_üÇÿÅPûGÒl-RÖͬ­­Ó;"„¢"ääà$ŸÆ ‚Û@µ„Co™ Cf4@Úå×èä°ô$žµ_þ¯ÿÐ#EÿÁ<üUð…xwþ/þ ãÿâ¨ÜÉ¢\O$ó®Ÿ,Ò@mÞGÌÑ“'ª“Û¥i¢_º=âé÷ º#LÊ«®zQÖªÂáßúh¿ø'ÿŠ£þ¯ÿÐ#EÿÁ<üUEk£h–÷×—R]Aqö¯44RV0%*dE]û¶ %÷(ç“xntëx#‚ ­b†5‘£*ª¨ÐY¿ð…xwþ/þ ãÿâ¨ÿ„+ÿôÑðOÿ@¿o³ÿŸ¸?ïà£íöó÷ýü•ÿW‡è¢ÿàž?þ*øB¼;ÿ@ÿñÿñT«öû?ùûƒþþ >ßgÿ?pßÁY_ð…xwþ/þ ãÿâ¨ÿ„+ÿôÑðOÿ@¿o³ÿŸ¸?ïà£íöó÷ýü•ÿW‡è¢ÿàž?þ*øB¼;ÿ@ÿñÿñT«öû?ùûƒþþ >ßgÿ?pßÁY_ð…xwþ/þ ãÿâ¨ÿ„+ÿôÑðOÿ@¿o³ÿŸ¸?ïà¬ûû ꓬú…¦“w2®Á%ÄqÈÁrN2Aã$þuü!^ÿ F‹ÿ‚xÿøª?á ðïý4_üÇÿÅPaÑ<#o¦óãþ÷éGŸ÷¿Jùgþ‹è9sÿŽÿ…ð°¼[ÿAËŸüwü(êo>?ï~”yñÿ{ô¯–áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€>¦óãþ÷éGŸ÷¿Jùgþ‹è9sÿŽÿ…ð°¼[ÿAËŸüwü(êo>?ï~”yñÿ{ô¯–áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€>¦óãþ÷éGŸ÷¿Jùgþ‹è9sÿŽÿ…ð°¼[ÿAËŸüwü(êo>?ï~”yñÿ{ô¯–áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€>¦óãþ÷éGŸ÷¿Jùgþ‹è9sÿŽÿ…ð°¼[ÿAËŸüwü(êo>?ï~”yñÿ{ô¯–áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€>¦óãþ÷éGŸ÷¿Jùgþ‹è9sÿŽÿ…ð°¼[ÿAËŸüwü(êo>?ï~”yñÿ{ô¯–áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€>¦óãþ÷éGŸ÷¿Jùgþ‹è9sÿŽÿ…ð°¼[ÿAËŸüwü(êo>?ï~”yñÿ{ô¯–áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€>¦óãþ÷éGŸ÷¿Jùgþ‹è9sÿŽÿ…ð°¼[ÿAËŸüwü(êo>?ï~”yñÿ{ô¯–áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€>¦óãþ÷éGŸ÷¿Jùgþ‹è9sÿŽÿ…ð°¼[ÿAËŸüwü(êo>?ï~”yñÿ{ô¯–áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€>¦óãþ÷éL–ThÈ “ô¯—?áax·þƒ—?øïøQÿ Å¿ô¹ÿÇ€ˆ_ò?kõßÿeV õõΧ{-åä¦[‰N^B,qŽßJ(ÿÙsane-backends-1.0.27/doc/umax/sane-umax-powerlook-doc.html0000664000175000017500000001752212112021330020277 00000000000000 SANE-umax - UMAX PowerLook scanners
SANE-logo
UMAX-logo

UMAX PowerLook scanners




UMAX scanners
 Power Look series:
Name
SCSI-ID
Versions
UTA
ADF
B/W
Gray
Color
Bits/pixel
Optical resolution
PowerLook
PS-2400X
?
X
 
ok
ok
ok
1,8,10,24,30
600 x 1200
PowerLook II
PL-II
?
UTA-II
 
ok
ok
ok
1,8,12,24,36
600 x 1200
Power Look III
PowerLook III
all (1.7)
UTA-III
 
ok
ok
ok
1,8,12,14,24,36,42
1200 x 2400
PowerLook 270
Color Filmscanner____1
?
incl
 
bad
bad
bad
1,8,14,24,42
2700 x 2700
PowerLook 270plus
unknown
?
incl
 
bad
bad
bad
1,8,14,24,42
2700 x 2700
PowerLook 1100
unknown
? *
incl
 
?
?
?
1,8,14,24,42
1200 x 2400
PowerLook 2000
PowerLook 2000
?
UTA-2000
 
?
?
?
1,8,12,24,36
1000 x 2000
PowerLook 2100XL
unknown
?
UTA-2100XL
 
?
?
?
1,8,14,24,42
800 x 1600
PowerLook 3000
PowerLook 3000
all (2.0)
incl
 
ok
ok
ok
1,8,14,24,42
1220 x 3048
3048 x 3048

* Powerlook 1100 is a firewire scanner: not tested

UTA = Umax Transparancy Adapter, ADF = Automatic Document Feeder
(X = supported by scanner, incl = is included)



This page has been changed on 16th. decemnber 2001

Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-text4.jpg0000664000175000017500000000621012112021330016367 00000000000000ÿØÿàJFIFÿþXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ2È"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷ú(¢€ +Å-Ó¼)d“ß3<’6"‚<Rì=ƹË?ŠvÓørMf]"éc†àA*BÂM„Œ‚IǦ}HÒæGM<zSŒtnËÔô+ð·Ä=7ÅZŒ–6¶÷0Ì‘™zèO¨«Þ/ñ\>ÒῸ¶’â9&í€ •$uÿtÑuk“,5XÕö.>÷c¢¢¼çDøÁ¥k:Õ®›ö «v¹-$vR¡LýzWAã?CàÍ6 ë›9®a–_'÷LVÁ#¯°?•A<5XMS”lÙÓQ^[¦|pÑuRÞÉôû«a;ˆÄ²2•Rzgã8íUï>;é¶“Ú\èwé<4R&øÎÖS‚8>¢‹ xZÉÙÄõª+μ[ñwLð•í´ÚuÝÏÚ­í2 bÃ=þSUtŸzf±e©ÜÛèÚ‰þÏ€\Kì,cÎŽqÇûf‹™û)Úö=>Šó ühÐ|W¯Á£ÛYjO0;dM¤ŽqÃôŠd´ÖŒ(¢ŠQEQEQEQEQEQEy7Æ­:êX´ÍB8Ýí¡ß¬’Wn{ó‚=8µçÞñÐ5&Æ'Ón‡•y ‡Cߣ'õëÙ|sâ›}÷M³ÔmÒ}+PYcºK2´=GÌr?/ñ‡†›Ã¨…%ûEÂy¶·áÐö'¦GǨ8—OÔ¼3•yÂë$Ao)?,sm/6L¨éü|Ç&A Œ„W©ø×V{σ¾½ŽbfŽáÈ:‡DqŸ®EØy•/iZœ—Ÿù£È¦Im®9âš&*ÊÃk+È>„Ýñnuk=?ÄÉ—ûdbÞð์9ì7&ÖäüÕcÆé ñÓ¼IlSV„´ê¸nS\ wʶ{–& ð™:µ¦§á†Ú_Pͳݎ.cÉP áK ÉœŽ´üŒêÏ™*Ÿë÷¿?ä5áÿûÛÿèrTßµk YÖµ-Ná ³‚ÃtŽþ›×Œw$ðrj?‘=¿ˆô8$xôH‡¡ 5Kág…m–CàßÄ]¼±§ÊÁsÆ|¶çôÊøIÝ.up¬@m"ì6QåÒ§›cÐþˇï}çî;IXëÚF§;A§ê¶7rªï1ÛÜ$Œ gôÉÚþ¥Î°jµ…¤¬»Äw ÉÁ#ŒƒùWËÞ×fðï‰,µ¥dD,Àg ?0 u㟨‹µßøI|U¨jÁ<´¸“÷jFEW#' gœg8¥Ï å”rÕåæ÷m¿ŸcëHgŽâç‚D–:HŒYHÈ Ž ŠÍ³ñ>ƒ¨]%­–·¦ÜÜ>vE Üní“€OŸÂ¼wPñkè߬,’VkÍMZÕ7s¶òû¤&8?>GJòUºðþ³cªÛådĉƒË’ÏlŒÆ«˜ä§‚ç‹“}íæ}…¨jº~“Ï©_ZÙÂͱd¹™cRØ'bpÔEªé÷iÔ¡¾µ’À+9ºI”Äs¸ï99ã°õ=3Iø‰à´ŽP$µ¼‰f‚@0Ñ>8aèFOæAêkå;Ûûý.-KöګK¦¢dXdýÔå ãp¡Âžp0Û9éÒS[ê±4ÝsIÖ|ßì½RÊûÊÇ™ö[„—fsŒí'ÁühW™ü!ð\~ÐÆ¤e-ò+†FÈdÆAãƒ×LûšôÊf.×Ð(¢ŠQEy·Å k"M2]&Ô\›s"Ép­ómÁÀÇÊ{×;gá/j> »ðþ©¥m6ì“iÒÍ:þíù“å'‚¥±žçòöº*yUîwC0­ q¤­h»¯¾ç†hŸ üGi§j—s-ª^ÉjÐZÛ´™ûã#€v’¿^+ ÛáŒà¼‚uÒÔ4r+‚n=}!Eˆ¿íLG½vŸ1óLjþø®çÄZ…Õ­„RÃqpó#,ê0‹cœŒâ´.¾x²o†6ú1ÓÐÝÛêFuˆL¹1”#9Î:ŸZ÷z(åDK0­$“¶‡Ïº'Ã?ÜøkVе=8[#•»²•æV p¼`…nŒ¤¯·œV·ÂOYÞCuo§F³Bë"7Ú‚Gzú†ŠvD}r¦·¶§ˆüVøuâk:n©am…l £ó‚²HØõã0ïØÖ?ƒþüCðŒZ½ÞŸekýŸ‚’u;2ÙfdàsÛèj(±Š­.^Sço|/ñŽñMÖõkQäÇ+É<Í8v%•†O9$“^ãâ|GáËÝ)¥1yê6¸Ã+†@ϵlQE„ªJ2SŽ?/„£ u¯¢¨§ÊŒž2®Šû¥èt‡†-ìm‘'f_6I2ÂxÑvã$“óÀ'8#Jø«Þh7Í{"Zê l‡•b3Á=@9ëëŽ9ú:Š,fëÌòß„ºo‹ü7lú¹eöb{i•þh˜œ•#‚I9ê¨ SANE-umax - UMAX Vista scanners
SANE-logo
UMAX-logo

UMAX Vista scanners





UMAX scanners
Vista series:
Name
SCSI-ID
Versions
UTA
ADF
B/W
Gray
Color
Bits/pixel
Resolution
Vista S6
Vista-S6
all
UTA-V6
X
ok
ok
ok
1,8,24
300 x 600
Vista S6E
Vista-S6E
all
UTA-V6
X
ok
ok
ok
1,8,24
300 x 600
Vista S6E
UMAX S-6E
all
UTA-V6
X
ok
ok
ok
1,8,24
300 x 600
Vista S6E
UMAX S-6EG
all
UTA-V6
X
ok
ok
ok
1,8,24
300 x 600
Vista S8
Vista-S8
all
UTA-V6?
X
ok
ok
ok
1,8,24
400 x 800
Supervista S12
Supervista S-12
all
UTA-V12
X
ok
ok
ok
1,8,24
600 x 1200*
Supervista S12
UMAX S-12G
all
UTA-V12
X
ok
ok
ok
1,8,24
600 x 1200*
Supervista S12
UMAX S-12
all
UTA-V12
X
ok
ok
ok
1,8,24
600 x 1200*
 Old Vista scanner:
Name/ID
Versions
UTA
ADF
Lineart
B/W
Gray
Color
Bits/pixel
Resolution
Vista VT600
? (try UC630 V2.8)
--
 
?
?
?
?
1,8,24
300 x 600
Vista T630
some
X#
 
ok
--
ok
ok, 3pass
1,8,24
300 x 600

* Supervista S12 scanners allow scanning up to 1200x1200 dpi.

UTA = Umax Transparancy Adapter, ADF = Automatic Document Feeder
(X = supported by scanner, incl = is included)

# There is no UTA available for the Vista T630, the UTA-V6 is limited supported, if you have problems with your Vista T630 scanner and you have a UTA-V6 connected, try without UTA!

## 10/30 bits/pixel are used internally, the output bit depth is 8/24 bits/pixel

Suggested firmware versions for old UMAX scanners
Name
suggested firmware version
(read on UMAX's german website)
last firmware version
Vista VT600
use the UC630 firmware (2.8)
?
Vista T630
--
1.5


Here you can find information about firmware versions of UMAX scanners.



This page has been changed on 12th. february 2001

Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-mirage-doc.html0000664000175000017500000001117512112021330017520 00000000000000 SANE-umax - UMAX Mirage scanners
SANE-logo
UMAX-logo

UMAX Mirage scanners




UMAX scanners
 Mirage series:
Name
SCSI-ID
Versions
UTA
ADF
B/W
Gray
Color
Bits/pixel
Resolution
Mirage
Mirage D-16L
all (2.7)
incl
 
ok
ok
ok
1,8,10,24,30
400 x 800
800 x 1600*
Mirage II
Mirage II
all (1.6)
incl
 
ok
ok
ok
1,8,12,24,36
700 x 1400
1400 x 2800
Mirage IIse
Mirage IIse
?
incl
 
?
?
?
1,8,12,24,36
700 x 1400

* Mirage D-16L scanners allow scanning up to 800x800 / 1600x1600 dpi.

UTA = Umax Transparancy Adapter, ADF = Automatic Document Feeder
(X = supported by scanner, incl = is included)



This page has been changed on 12th. february 2001

Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-text2.jpg0000664000175000017500000000311712112021330016370 00000000000000ÿØÿàJFIFÿþXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀN"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?ôïøãþϰÄ»íŸkó?å¿—·nßöNs»ôªú·Ähtÿiþ#‚ÀÜ ©R€Í³ËbŒÇæÚs‚¸è3\ÇÇ/ùÛÇþÓ®gVÔl¥ø=¥YGy]ǨoxƒÌUÛ É^ r9÷›z³Ý¡¥:&ã~fï¿w÷·ü.Ï…_Y7ïõmM¿Ú»,vÏöHÆ?ßð7m¼i Èßcº·n`ó<Ì¡6í£¾F=½ë€#áÕÉ=õhôT•g©^éá­_Ëûe«Û¹*è˜á‡>¸#üæŽfkS-¡8IAYÞËV{mgÕâ¶¥¬“ˆü÷ºù• cq@‡œs€}³Þ»/øæÏÁšƒÁö¹®\$ÂP…Æ2X“’àJŽ3šù†ÙY5 pÃȇð$è¾'x’]Å .¶šjý’Ø‘ó/ØÉ,#U\ò(RÐç«¥í¢ ½Û]žÓà‰öþ7¾»²}èÏçwvþñ#x«Ã°j’X=Œ²ÝŸ~ÞN>l ä`ôã8í_!é3[Xk7Z„-˜pî‘‘¸¦H$g¸ÁÆqÓ·Zû;IûöM©ÓZ6²1)…£9V\pAïMW„a¢D惧ø‹O6ZŒX³¹OB‡¦Aìk…o‚Ú9¸V[ëê¤:(¢È˜b*Ó\°“KɳzëᾃsáÅÑDO"U›ÌVù÷€F"F=ë>o„š Æm§I%Áò;Ç.ï˜nÆG¿AEXJµH«)?¼eïÁÿÝÞEt$¸ŠDT£}â qø †Ûà·†íµºW¸!>Yc‚=(¢‹ ÛTµ¹½Kš×Â? kQÍjñän…ŽXzj•ßÁ_^Ám÷7²5¼~R;ÎìBHP “€1ÖŠ(©4¬™¥¨ü+ðÎ¥áû]&[]«lÛ£8pO^GcÇ8•±á/ Ûx?Jm6Êââ[o0º,Î[a=Bç Ï8õ$÷4QA7v±ÿÙsane-backends-1.0.27/doc/umax/umax.FAQ0000664000175000017500000001274512112021330014236 00000000000000------------------------------------------------------------------------------- Q: I am using an Astra 2200 Scanner and can do a preview scan but the scanner hangs or produces bad images when I start a final scan. A: Disable the option "quality calibration". This does not reduce the image quality, the scanner reports it can do a quality calibration but that is not true for the current firmware version. ------------------------------------------------------------------------------- Q: What scsi controller shall I use for UMAX scsi scanners? A: The controller cards that come with UMAX scanners are very simple ones and I suggest not to use this cards. I like the ncr53c8xx (=symbios-loigc53c8xx = lsi53c8xx) controllers because they are not too expensive and I had very good results with these cards. Especially the ncr53c810 is very interesting for scanning because this are fast scsi controllers which allow long scsi cables. The Adaptec 2904 controllers seem to make problems with UMAX scanners on linux. ------------------------------------------------------------------------------- Q: I want to use the scsi-card that comes with my umax scanner. What card is it and is it supported by my os? A: There are at least two kind of scsi controller cards that come with UMAX scanners. ISA-Card: The ISA-cards that come with the umax scanners are very simple cards. I suggest not to use these cards. If you really want to try: the UDS-IS11 ISA-card is a DTC3181E-card based on the NCR5380-chip. On linux you may have the chance to get it work with the recent g_NCR5380-driver. The card does not have IRQ/DMA. Try the following option for kernel: dtc3181e=0x280,255 or use the following command: insmod g_NCR5380 ncr_irq=255 ncr_addr=0x280 dtc3181e=1 - ncr_irq=255 : no IRQ, no DMA - ncr_irq=254 : autoprobe IRQ - ncr_addr : can be: 0x220 0x240 0x280 0x2A0 0x2C0 0x300 0x320 0x340 (Thanks to Colin Brough and Hans Schaefer for that tip) PCI-Card: Some UMAX Scanners come with a PCI SCSI controller card DOMEX DMX3191E. This card shall be compatible to the Advansys ABP940U (Chip: Advansys ASC3030). The card shall work without problems with the Advansys SCSI driver for linux. (Thanks to Volker Ossenkopf for that tip) ------------------------------------------------------------------------------- Q: I use linux with a NCR/Symbios logic SCSI-Controller, sane does not work right. A: There are two differen drivers in the linux Kernel/modules. Use the BSD-driver ncr53c8xx or sym53c8xx. ------------------------------------------------------------------------------- Q: I am using an AM53C974 based scsi card with a umax scanner, the system freezes when I start a scan, what can I do? A: Try the recent driver for the scsi card, take a look at: http://www.garloff.de/kurt/linux/dc390/index.html ------------------------------------------------------------------------------- Q: Will there be a support for the UMAX-parallel-port-scanners? A: Since sane-1.0.5 there is a separate sane-umax-pp backend that does support (some) umax parallel port scanners. ------------------------------------------------------------------------------- Q: Will there be a support for the UMAX-USB-scanners? A: UMAX published their SCSI-protocol for scanners. However they have not so far published USB protocols. This seems to be because they are using an ASIC that is produced by someone else and they had to subscribe an NDA. Without the protocol documentation it really is hard to write a driver. I will not work on a driver. The Astra 2200W does work when connected via SCSI. It could work with SCSI-via-USB-driver and connected via USB, but that is not tested. ------------------------------------------------------------------------------- Q: I get a black area at the top of the image. What's wrong? A: This is a problem of some scsi-drivers. Update the driver for your scsi-adapter or update the operating system/kernel. For advansys-scsi-cards update to a new kernel which includes at least the driver version 3.1E of the advansys-scsi-driver. Take a look at: http://www.advansys.com/linux.htm ------------------------------------------------------------------------------- Q: Does SANE and the umax backend work on LinuxPPC / big endian machine ? A: There are people using the sane-umax on a LinuxPPC (big endian) machine. Other people write that they can not scan on a LinuxPPC. It looks like this is a problem with the driver of the scsi card. The "MESH" SCSI card is reported to work. The NCR53C94 SCSI card seems not to work. ------------------------------------------------------------------------------- Q: SANE hangs or crashes when I start a frontend for sane, what can I do? A: Sometimes the backends that are not used make problems. Edit /usr/(local)/etc/sane.d/dll.conf and comment out everything but the backend you need. ------------------------------------------------------------------------------- Q: compiling sane aborts with error "virtual memory exhausted" on slackware linux with gcc. What goes wrong? A: The optimization set by "-O2" makes problems, try which one of the following calls work: make CFLAGS="-g -Wall -O1" make CFLAGS="-g -Wall -O" make CFLAGS="-g -Wall" ------------------------------------------------------------------------------- You find a lot of tips and informations in the internet. E.g. take a look at http://www.scantips.com sane-backends-1.0.27/doc/umax/sane-umax-config-doc.html0000664000175000017500000002706112775277260017560 00000000000000 SANE-umax - Configuration
SANE-logo
UMAX-logo

Configuration





CONFIGURATION:

The configuration file for this backend resides in
/usr/local/etc/sane.d/umax.conf.
Its contents is a list of options and device names that correspond to UMAX scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below:
option scsi-buffer-size-min 65536
option scsi-buffer-size-max 131072
option scan-lines 40
option preview-lines 10
option scsi-maxqueue 2
option handle-bad-sense-error 0
option execute-request-sense 0
option force-preview-bit-rgb 0
option slow-speed -1
option care-about-smearing -1
option calibration-full-ccd -1
option calibration-width-offset -1
option calibration-bytes-pixel -1
option invert-shading-data -1
option lamp-control-available 0
#scsi Vendor Model Type Bus Channel ID LUN
scsi UMAX * Scanner * * * * *
/dev/scanner
# this is a comment
/dev/sge
The special device name must be a generic SCSI device or a symlink to such a device. To find out to which device your scanner is assigned and how you have to set the permissions of that device, have a look at sane-scsi.
When the generic scsi driver of the system supports selection of scsi buffer sizes the umax backend calculates the scsi buffer sizes in dependance of the numbers of bytes per scanline. With scsi-buffer-size-min and scsi-buffer-size-max the scsi buffer size can be defined in a range between 4KB and 1MB. Especially the minimum value is very important. If this value is set too small the backend is not able to send gamma tables to the scanner or to do a correct color calibration. This may result in strange color effects. If the minimum value is set too large then the backend is not able to allocate the requested scsi buffer size and aborts with out of memory error. The default is 32KB, for some scanners it should be increased to 64KB.

The option scan-lines defines the number of lines that shall be scanned with one scsi read command for a real scan. The number of lines that are read with one scsi command for preview scans are defined by the option preview-lines. Both have to be in the range between 1 and 65536.

With the option scsi-maxqueue you can define the number of scsi commands that shall be queued. UMAX scanners do not support command queueing - as far as I know. But some scsi controller drivers do support queueing in the kernel. In this case it does not make sense to queue more than 2 commands.

When you are able to do color previews but color scans do not work you can set the option force-preview-bit-rgb 1. This always sets the preview bit when acquiring a color scan. The image quality may be reduced.

Some scanners (especally very old scanners) may need the options slow-speed and/or care-about-smearing. The value -1 uses the value defined by the driver, 0 disables the feature, 1 enables the feature. Do not change these options unless you really know what you do, you can destroy your scanner by setting wrong values for this options!!!

Some scsi drivers (or may be some scanners) do return an invalid error code when a scsi command is executed. There are different ways to handle such bad error codes. You can define the behaviour of the umax-backend by setting the option handle-bad-sense-error in umax.conf. You can set the following values:

0 : handle as device busy
1 : handle as ok
2 : handle as i/o error
3 : ignore bad error code, continue sense handler
In most cases it does work when this condition is handled as a device busy state so this is the default (0).

The option execute-request-sense disables(0) or enables(1) the scsi command REQUEST_SENSE. The command can be called when the scanner asks the driver to do calibration. The driver does not know the required calibration parameters for all scanners. Some scanners return the needed parameters when the driver executes the REQUEST_SENSE command. But there is a problem with the REQUEST_SENSE command on some systems with some scsi controller drivers. This can cause a system hang. So the safe way is to disable the REQUEST_SENSE command, but the driver may not be able to do correct calibration in this case.

For some scanners the calibration has to be done by the driver. For this the driver has to know some values about the calibration data. When the REQUEST_SENSE command is disabled or the scanner does not return the correct data the driver needs to know the correct parameters. For some scanners the parameters are stored in the driver. When these values are not set correct the image might look very strange. To be sure that you have a problem with the calibration please enable debug output.

calibration-full-ccd:
The calibration can be done for each element of the CCD (1) or for each pixel of the requested image(0). The value -1 enables the value defined in the driver.

calibration-width-offset:
Some scanners use more pixels than calculated by image/CCD parameters. A value larger or equal 0 defines the offset. The value -1 enables the value defined in the driver.

calibration-bytes-pixel:
Some scanners use 1 byte calibration data although the scanner supports more than 8 bits/pixel. You can define 1 or 2 bytes per pixel calinration data. The value -1 enables the value defined in the driver.

invert-shading-data:
Some scanners need inverted shading data (1), others need original shading data (0). The value -1 enables the value defined in the driver.

SCSI ADAPTER TIPS:

The UMAX-scanners do block the scsi-bus for a few seconds while scanning. It is not necessary to connect the scanner to its own SCSI-adapter. But if you need short response time for your SCSI-harddisk (e.g. if your computer is a file-server), I suggest you use an own SCSI-adapter for your UMAX-scanner.
The SCSI-adapters that are shipped with some Umax-scanners are very simple ones. I suggest not to use them. If you really want to try: the UDS-IS11 uses a DTC3181E chip (compatible to NCR5380). On linux you may have the chance to get it work with the recent g_NCR5380-driver. The card does not have IRQ/DMA. Try the following option for kernel boot option:

        dtc_3181e=0x280,255

 or use the following command:

        insmod g_NCR5380 ncr_irq=255 ncr_addr=0x280 dtc_3181e=1

     - ncr_irq=255 : no IRQ, no DMA
     - ncr_irq=254 : autoprobe IRQ
     - ncr_addr : can be: 0x220 0x240 0x280 0x2A0 0x2C0 0x300 0x320 0x340
 

For information about the umax-scsi-cards take a look here.

See the relevant hardware FAQs and HOWTOs for your platform for more information.
See also: sane-scsi

FILES:

  • The backend configuration file: /usr/local/etc/sane.d/umax.conf
  • The static library implementing this backend: /usr/local/lib/sane/libsane-umax.a
  • The shared library implementing this backend : /usr/local/lib/sane/libsane-umax.so
    (present on systems that support dynamic loading)

ENVIRONMENT:

  • SANE_DEBUG_UMAX
If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity:
SANE_DEBUG_UMAX values
Number
Remark
0
print important errors (printed each time)
1
print errors
2 print sense
3
print warnings
4 print scanner-inquiry
5
print information
6 print less important information
7 print called procedures
8 print reader_process messages
10
print called sane-init-routines
11
print called sane-procedures
12
print sane-infos
13
print sane option control messages

Example:

export SANE_DEBUG_UMAX=8


This page has been changed on 27th. feburary 2001


Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-scanner-clones-doc.html0000664000175000017500000002732012775277260021223 00000000000000 SANE-umax - UMAX scanner clones
SANE-logo
UMAX-logo

UMAX scanner clones





The sane-umax library implements a SANE backend that provides access to several scanners that are compatible to the UMAX-SCSI-protocoll!
Here is a list of the UMAX-compatible scanners:
UMAX compatible Linotype Hell scanners
Name
Vendor
SCSI-ID
Versions
UTA
ADF
B/W
Grays
Color
Bits/pixel
Resolution
Jade
LinoHell
Office
all
X
X
ok
ok
ok
1,8,24
600 x 1200*
Jade
LinoHell
JADE
all
X
X
ok
ok
ok
1,8,24
600 x 1200*
Jade2
LinoHell
Office2
all
X
 
ok
ok
ok
1,8,10,24,30
600 x 1200
Saphir
LinoHell
unknown
 
incl
 
 
 
 
1,8,10,24,30
600 x 1200
Saphir2
LinoHell
SAPHIR2
all
incl
 
ok
ok
ok
1,8,12,24,36
600 x 1200
Saphir Ultra
LinoHell
unknown
 
incl
 
 
 
 
1,8,12,24,36
600 x 1200
Saphir Ultra II
LinoHell
unknown
 
incl
 
 
 
 
1,8,14,24,42
1200 x 2400
Saphir HiRes
LinoHell
unknown
 
incl
 
 
 
 
1,8,14,24,42
1220 x 3048
3048 x 3048
Opal
LinoHell
unknown
 
incl
 
 
 
 
1,8,10,24,30
700 x 1400
Opal2
LinoHell
OPAL2
 
incl
 
ok
ok
ok
1,8,12,24,36
700 x 1400
Opal Ultra
LinoHell
unknown
 
incl
 
 
 
 
1,8,12,24,36
700 x 1400
1400 x 2800
Linoscan 1400
HDM
LS4H1S
?
X
 
ok
ok
ok
1,8,12,14,24,36,42
1200 x 2400

* Scanner is able to scan up to 1200 x 1200 dpi.

UTA = Umax Transparancy Adapter, ADF = Automatic Document Feeder
(X = supported by scanner, incl = is included)



Other UMAX compatible scanners
Name
Vendor
SCSI-ID
Versions
UTA
ADF
B/W
Gray
Color
Bits/pixel
Resolution
Vobis/Highscreen
Scanboostar Premium
LinoHell
Office2
all
X
 
ok
ok
ok
1,8,10,24,30
600 x 1200
Escom
Image Scanner 256
UMAX
UG80
all
--
 
ok
ok
--
1,8
300 x 300
Nikon AX-210
Nikon
AX-210
all(?)
X
X
ok
ok
ok
1,8,24
600 x 1200*
Genius Colorpage HR5
(normal and Pro)
KYE
ColorPage-HR5
all(?)
X
 
ok
ok
ok
1,8,10,24,30
600 x 1200
Epson Perfection 600
EPSON
Perfection600
all(2.3)
X
 
ok
ok
ok
1,8,10,24,30
600 x 1200
Escort Galleria 600S
ESCORT
Galleria 600S
all(1.6)
X
 
??
??
??
1,8,24
300 x 600

* Scanner is able to scan up to 1200 x 1200 dpi.

UTA = Umax Transparancy Adapter, ADF = Automatic Document Feeder
(X = supported by scanner, incl = is included)




This page has been changed on 1st. october 2004


Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax.jpg0000664000175000017500000005721612112021330015335 00000000000000ÿØÿàJFIFHHÿþCreated with The GIMPÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ¹"ÿÄÿÄV !1"4AQTVr“”²ÑÒÓRSUs’•±#23Da‘£³$56Bq%Ctu´7Ebcd¡Áð‚ƒáÿÄÿÄ3!1AQa‘q¡±ð"2bÁ3BÑáñÿÚ ?Õ%J}¹E¦Šq„àhäû©@'2ã)'ü¥ ÏáMf †Q`#Nxér¿Ç…)øò!É—)¨«˜îà n™AÒTu) ñÏ“Àðè©Þº×´WKÿ~ñÉÜcº]éX=™H †ÓƒÿÚ“å ?->m>Êã~ÔË\iQÜ*aÀž# Œñâx÷éšå––QÉr_ÇüÄHm ÿ±¦­jþ¾¬´DO#þP“òÓæÓì¨ÛöÒȱÙ$ÜŠð`[ Js’N~ ¹F¬a¹IJb†œ #ó%Í “ÒwD€@$« äçîß®ŸVŸ]5êФ_Vµž“0æyB¿ùr?D+Î#ܯ¿—ôJ¼â=ʧl%‚Û´LÝâ\‘Ö¥¦Ö›Ó‹ÃP¾…‚¤¥[ÌéIp$ZálÞÎÈ¿Ü`¹²ï[¤*æˆÑ»:òb”¥)Ë!öÕ”¾à*XÎñ8Òœ‚g¹á\/BöÓšÚf¾Sž¾¿Æ38‰ŒÂ—¼ÆKþ\Ñ*óˆ÷+ïå¹_D«Î#ܤ6ga-’eÀ¶Þ-,ÃTù3ØJߜ법¹~ktÊt(`—3¨…1_Ù-]´0‹rÛ’v=7•IL…“¿N:NWYÈÆ4„Iò_eÂâþ­½ãf<üâW¬ç©Ïåµ_DŸ8rËbþ‰>qå4Û=”Ù«4- ‰ ¬Lµõ¦áÆS%nv`kë•YN­Z“§OÝJlÎÁØëCñ\w¤í|xϸҊë[°wj#ô“’{ɨ[c²‹J[¬uœuŒúöZ+\dãòÔ¿¢OœG¹_-.}|â=Ê„k˜ÇU‡äÛ¶ysãF¼HDv¾·h¸ÙZÒ€æ4¤¤$+Ot'Á«e°¿1–ö±ËÉôH²Ý$†%È;M­(QŽèJRÒ•©8!ˆ`äbÛ=­1Šõ>óž_N«|=8íõGŽ­ý«ùˆ÷+ïåÏ¢¿˜Ÿr«}R?9t²Léë»,Wõ/²uYIuóÃô𜌠pãu´ö[s°—1ÆÞÆÎô¡ú¦÷m:—5/ i*H9< ôÔ56º¤_Ã<â{ù-ð4¢±i>þHÿË+¿E1>å–GOþÕüÄû•õ›, êc²p’ˆ“B¥>Óî)!”¿‡ó©i Ps»Á¥tf¦.Ñ­ê½DÚXÛm›2Ã\};ÀÃÎ)h­8ZŽ3œ€pR{þkihÄâ"{ýñõR4vùdž{÷òåèËßE8Ÿr¾þXžú(yÄû”íq7îŠÖ̘¾[ÐåîpüÃiÊ´©Æû ½à JJ8¥«†8¦¥¶åÖ“j‡æë ¨ÚžBŠÃÉQÅ©D¼*ý$`h<1Ý2:tˆz´6[mKE|3ïôùç·—?EòÂ÷ÑcÎ'ܯ¿•÷þ‹q>å<ÙÙ7 .ÙlîLšmz¡Äq[Û}Å¥%Þ.´‚ V rTIÎ’Js€sVmñœ€dªñ ·t¨õªÐö𑜠†Ê2qòÇ8¨Z"´Ô´ÖÕžXé9ëŸ(ôþË÷åyÿ¢ÓçSîWßÊì¢ÓçSîTCò\“Ôq­âZ«àm;¶PÞ@Òt¨ÿñ“Ý4ãjn“m–g6vê÷^]ܸú @fÜ”'°m”¤…”‘©Iìpp3ÄÔ/i…tøVÒÖŠÅ'9˜ýÝ£žž¿hîü®H?ûZ|ê}ÊûùZ“ôZ|ê}Êy©múvr×w‘m¶.*ne¨É~#Ì–J–¥%J X'_dBòIÉáU[KKìÁUÏg祄ǵÍi.:ÛÄ(âÒ Hm N­ É8Ïz¡}KÄâ%M.ÃíOÒzDâ'ž&&c¬G–1<ý#)¿ÊÌŸ¢ÓçSîTÖÍmÌ¡›"?Z¢>å‚ö¬¥yìÒœcHùYÿj…“²Pb±w”í¥­¨°ŒfaL[­<^^‚ãG²t!Z€9ࡊ³Ûvnšù´ŽA·nb´ZŽÓÆJ•Œ¡¥©'¤ä©Jù šâššÓx‰Æ?ûÿO>óiÂé¡{iVÞ(Ž\ãý>¿Õ_$·(IùióiöQÊ~Z|Ú}”Ö¾­h/ÛiÀ„¡'z¥‚¢8€1áǧñ÷?,sÊ~Z|Ú}•ðÜ$i+F¬jÆí=#=ømMn)Bb™z÷RYp •“Ä4Gù‚s¤¨c ÈI›„€+@ém…|bäpnÊN½LH IRAàz2… ÷Ò{ÆuÌŸwíšê”­#ÃVLå–C;”´„µ‚4€œž´–—¯›=2ÛÖšuô€•¼HHÁŽ=Îõ[zæGÏ»öÍ2“´PáÎf «Ë K{¦”âòp4¤œœ‘ŽíV—šZ-a“Í5Ô§i˜‹"+Wûkq¤éß²‡ßwIÊu ÞƒÄg¢Ÿµ°›tħå5¶-7&FûÈ(-Ý# ÔteXz+cë™>ïÛ4ƒ·d±)ˆ®Ür$jÜ´·°·tŒ«HÎNŽŠûwÿï/Ÿ†sý1ùÚ=“:ÇF;©Æ×ÁŠbÄÚˆ‘ãÅ–eHB7€‚€Þ5”z{Þ¥^Ø ³’û¿µ‘ÝyÆ g\É*RÚ'%²J2ROùz+dë™>ïÛ4uÌŸwíšœñíÔÎf+í G&3#©Ö×L‚Ì[OølãuÙRÛxR[ÀÀÈîWÛwS½­´o97i¢BÞãyÖÒ¤7¯Æt¶3ŒŸã[/\Èù÷~Ù£®d|û¿lÔçnf<<±òw“ až¦ÛO†Øch ´Ëo‰(m$%)t  ðPæé§ Ø=±ràÝÁͪasšN†äªd’âÇ€VŒÙ¼÷ë_ë™>ïÛ4uÌŸw횸®½¹Î=”Åá‹Êêe´Så.TÛí¾L…ã[¯<úÖ¬ ’ÞOûS¶¶kØ·›{;RÃpŠTƒäÊUCNŒ`äç¿“Z±»$EvQ¸­{ÇKÝ‚4“œ ${Ø9¥¸.K ¾Äµ:ˉ CˆsRT’2 ñwjvâ:ÖŒN=ÆóR9rd©ÖÒ†`m-Ó Zo®ÒÚV0°‘»à Î:sÆ•^ÀíK±•Í¤Š¸êm •&AIB (N4c $:xV»×2>}ß¶hë™>ïÛ59ÞjO\)CZ<½™Ø-©äÞMç$^°ð^¹‘ºý-_¡£ïÛ4uÌŸwíšœÖ%×úæë9åìËYØÝ©ÚfŒÚ‚Ê%HJ‚µ€uqÿ^5Ë;´‘úÛs´Q›ë]]o¢Cãu«ô´aŽ{¸é­S®d|û¿lÑ×2>}ß¶js¡Yww«í îÉÝz{·;‹3˜ÈirpÓÀpÈ*-¨)$ ©' c©È±.ci¯‰²¡†§´”u´W ”© “ǾNÎ*Ñ×2>}ß¶hë™>ïÛ4®…+10Ž·ÜkE¢Ñã;réÚ:GO$=1×2>}ß¶kƒpZ_CZƒËJ––Ë’’’ gˆIÉýã¿V|¤U&ã(vCO¬eM ¡<’IP(ð÷’Lµp[è+fZœHRT‡2’JT8Aw43p\–}‰ju—‡椩$dAâîÐC8Êu—T0ëY X8:Nr“ßNNqÜ#†2s•õrþì³ýsž¨­Ã®d|û¿lלú£º·¶BÔëŠ*qwKŠ”£Ý&BÉ4Œ_éIò™õ VoésvªÖ¸òæBCp¥…ÈŒÛjâW%Ä)#8'£=î5+w¹J‚·Ñ.â㛳†iOù‹‹ONx`ƒœp¨Ž_¾ø›qô¸¿‚«"5üÍœî©ì2ãῸ}Ån&y@HiIpª?(•$žÃ9Ðí‚JmPÄÕ­rƒ-hJT¥é‰ % ç<#¼H¨n_¾ø›qô¸¿Ž_¾ø›qô¸¿‚ÇUyÖ7.ÛUrKò&3ozÛ‡›i( ÊäkmJRIІtÓÐi^_¾ø›qô¸¿Ž_¾ø›qô¸¿‚dKв­á2ä‚õÚ@’T‡SQRãû †ÚR\ÒTZ9AÕ‚2KiÒ•l¼¶íÆcNOmvæÞ}Ad:¾¸Ãm¯N -@¨è ¯&w—ï¾&Ü}./Ä£—ï¾&Ü}./Ä †‡h”Ì÷™rrKmáÔ[qò¹!¥jVTºqDस5¤´Ûns'B*áxU³w)Z‚_‰«Œ} QZÔðì·¤)*8P›àfy~ûâmÇÒâüJ9~ûâmÇÒâüJ(Ní#ö×^t]EýËzUh`f"Oç  ë|0üÞk…5zE­ÌËÃËL•ª."¼Ö³¥:P­n)Ôåzð·õ4;-h)ÝÕƒ—ï¾&Ü}./Ä£—ï¾&Ü}./Ä ±ÑUÎ_¾ø›qô¸¿Ž_¾ø›qô¸¿¼ËlÃq“hn:ͺá-©‹t~­¦Æ íôµ6225uÒΡy„±ÃÚ9¯Dfå>ë.ÛÚia-8–ÌD…,º¥èKò£úìþCÂÇË÷ßn>—âQË÷ßn>—âP3°òôÛÒÕsß0Ó. ֽ֖ءºZÖÛîã§ a]%B­õ\åûK‹ñ(åûK‹ñ(,tUs—ï¾&Ü}./Ä£—ï¾&Ü}./Ä ±ÑUÎ_¾ø›qô¸¿Ž_¾ø›qô¸¿‚ÇEW9~ûâmÇÒâüJ9~ûâmÇÒâüJ \åûK‹ñ(åûK‹ñ(,tUs—ï¾&Ü}./Ä£—ï¾&Ü}./Ä ±Õzñn—7j­k.d$7 X\ˆÍ¶®%qð‚\B’3‚z3Øþã\òý÷Ä󴁿”rý÷Ä󴁿”Ël- v†Ñ•=¸è–ò‘˜ªQ|™¯—T²•!´…4[9q$aYhjàZì¿*6Äx¿ñ„ÌŠå¹–š:„v#Æ2R¡Ð•h+8s†HÝözªÛË÷ßn>—âW Þo -Õ·±3§U­Å&TPV¬äþs‰Â@Ïxõš¼ëÕ ügÿ¹Ü?®ºÙù~ûâmÇÒâüJÇú¦C—d,¬Íލï™Ó-)IQH[ªZrRHÎ:  ô¸ï’TQC¸ï’TRn)ÀãM¶”8¢;5„•Àâ{Ô QUM¦–ìYî2ÔÙjL4"rÚ$ˆ-o4ïÐr4(ïì”1¥¢¿ùE NsÏ5´OM2^v3cÅQf[ª:œÝÑ`§têIt(¬@8@â„Ð[èª=®½Ì™ -CZå¸Ò˜˜ë¦ÜaÖ¤-.%°âÕÃq¨)%@é!¥K±µ÷WîŒDDVÓ.%™¯%%RŒ ÜY* ­A !u¢«WëìøÜŒA3j·¦{èuµ-RK½‚HPÝœ2{"úc‡cŬ-£ºL”¶„=r—lm(J–¶VÐyHqÎÈ•  | Ô3¤¾ŠÏ,7Ë¿[Ù`™ ¹6u¶%¾—”•·)ÂTçd­,’ I*ÔI$:;[y-]C076ˆ‹‘ ”¯Sêmé-©(ìÄ|‚J´gs9y¢ m׉’6ŽL Š#©ª"ÛV­[¥% ì9”J â¡7¦O~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sáѦO~sáÐwEq¦O~sá×.ÚmN-PÂR ‰Þ¹Àÿ®ZÆ:½ö§ë—ꦶ§Q»uhÎt¨Œ÷ñX¯W¾Ó´ýrýTÐlîvã¾J=Q\~×ÊsúNWnvã¾J=Q\~×ÊsúNP&ì8¯ï÷Ñ™s~Øeímƒ¼@Ïb¬ô§²Wò=úáËdn-\\…sšN†ä©¤—ž<±;#Ã÷žý.^i/¡‚êËJ––ʆ¥%$@î€TœŸÞ;ôÕËÍ­®³Þ\¡£¯qÖšŸHëŒã8öYÔžŒôŽýÝšÖ̤ÊjÛ âÞ¥„……¬µgÔ '¤ãv-ì¾!Fß0§Ë›¤êmN¬¤ãQ'$tç:¢¬«d ÏÇ~\(ÒŒ­l8ëIZšVAÊI‰ÈGxRû$ k«}–©*SÄÈZ\ÒãªuHÔtêYÀÿNï‘¢‚8X,É„¸BÓEZR…0##B’•€SŒ¥(ù'¤ÒâÙ,- 0el&2› 'JšH 6F8¤+ èâ{ô»¯4ÂÞu ¤©( Z€J!){¤î’+º‡‰OÊj3-È‘§|ênéN£Òp8 ôRôQ@QEQ@QE}JTµ¥%J= šùJÇýaòêš­¤|ÿ`ÑÖÒ>aß°iœ¹l@й2W¡¤c$I$à(’$’šâÆ5É…;K!*д8Ú›Z€p¤($àƒ‚A Šým#æû޶‘óýƒIQ@¯[Hù‡~Á£­¤|ÿ`ÒTP+ÖÒ>aß°hëi0ïØ4• õ´˜wì:ÚGÌ;ö p†ÖáÂ¥œ$f»ëi0ïØ4[Hù‡~Á¨ùn¶õ²Zšq+ C¨%'8Rr•õGp‚)Ã/5%†ßaÔ:ˉ CˆPRT’2#¤ݪÆË©K؉*Q%FDòIܧÀBS3¨œƒú(I `'£¯ÈÛîFu Û/éZBUÉ28Ð¥9åè«ÿÝ=Ê9åè«ÿÝ=Ê›(˱¶:ÆÃí-§›·°…¶´”©* ¤Aè ÷*/eÀÏý|ÿü‡iÇ<¡ýû¢G¹HìÃnµ°Î‡˜y•)É®<Ú›XJžuI%*Œ‚Ý ·Ií·¼µ~5‰õ{í;O×/ÕMm’{mï-_b}^ûNÓõËõSA³¹ÛŽù(õEqû\_)Ïé9]¹ÛŽù(õEqû\_)Ïé9AÝöFåo5• 8Æ“ßÍc×.­ Û¶Æ]‰v)¨×ÃSé—•— 5èéáœgýé3Žm­fÓ޲Õ(ªÅ§n­—››0#±1.»«Iq IïÛ4 QJõÌŸwíš:æGÏ»öÍTR½s#çÝûf޹‘óîý³@•7ŸýÝ+ê—ø{×2>}ß¶j¥³N­í‹–ëŠ*qrn Rt™h-²{mï-_b}^ûNÓõËõS[džÛ{ËWãXŸW¾Ó´ýrýTÐlîvã¾J=Q\~×ÊsúNWnvã¾J=Q\~×ÊsúNPQú¤uG¼u?äÎIî¾Þï:í V4hÆ4©?,ôç¹Q,ìdÝ ·7´Òì0«ƒBàëí% S¼¤ä•wIÉ«NØl¯mºË”Ÿ˜×ZkÝõ²ÒœëÓœêIù"§äFØvfx Y·²ãÎò·i*ÂМ x#SôLã<³åêÉ›Df“‰í>ªÌX"ÂÚ(²qâ´kÀR†8¡C½ûëE¬£cº™^¶{já]%Ê€¶ש-8²£© HÆPIÚÕë«pÝ>? O_ãDóÎ1ŽØÆgË?Êz:»ÝJç{«:–óŸ//|ûŠ(¢¹TQEQ@QEQ@QEQ@QE Éí·¼µ~5E‚ü¤ll;D;tÃ~·Ûwm)Øe-±! %Çm]—b J²ž)ÔDÌͼÙ$ÌxsŽØ®Ìœ¢JTø8¤9ý²^0Û¼ø ®NfêëÈ^Ï5u[ (®"§%â´JëI‰'ûGd•GWa“ÉU:Li’î±#Ûž¿3d\–ëyRîw2w ©ïÎìã<QÊ^H™çöÉxÃnóâŽl—Œ6ï>(,tUsŸÛ%㠻ϊ9ý²^0Û¼ø ž•xdˆì«…Áˆ-‘¡.<èld “ÄàPR:¤l÷[;¹Úˆ{ÝGö‘úXáÒkç?¶KÆwŸsûd¼a·yñ@ãc¿Àöûl馣öWü ÿ×ÏÿÈvœsûd¼a·yñMvEÄ=°.ºÒÒ¶Öìå%i9 C¸ ÷EÊOm½å«ñ¬O«ßiÚ~¹~ªkl“Ûoyjükê÷ÚvŸ®_ªš ÎÜwÉGª+ÚâùNIÊíÎÜwÉGª+ÚâùNIÊ袊Š( (¢ŠŠ( (¢ŠŠ( (¢ŠŠ( (¢ŠŠ)FP•¹…gHJ‰ÁÁà  NŠWTšwÎvQþiß8=Ú¨¥uGù§|à÷hÕæóƒÝ JŠWTšwÎvQþiß8=Ú¨¥uGù§|à÷hÕæóƒÝ J›Ïþî•õKü =ÕæóƒÝªý¾è»ÆÍK˜¤%r[HHù ºâŸß¥#?¿= =¶÷–¯Æ±>¯}§iúåú©­²Om½å«ñ¬O«ßiÚ~¹~ªh6w;qß%¨®?k‹å9ý'+·;qß%¨®?k‹å9ý'(ÝãN™kz=¶ãÉÒ×§w+r—´a@žÁ\@#ýóPê»m%© 7+.,¡.(È´:5“Øå‡ ”÷µœŒwE=ºÊ‚‹¬(·›€·YÝeçeºIl6ÖôS§„£»éÒ öírâ·™ê˜ÓQK©ZcóÅi@,FFx†ßÿçÿð&‚ÁmÚ+UÚSÑ"JþÖÇëb¼Ú™y 9-¬iì“ÇãÓR•œÁ°ì•»i¬SmÛGû~zn‡¤¢qyÒÒ`8•å;Åð.#V{šÂG+F (¢ŠŠ( (¢ŠŠ( (¢ŠŠ( (¢Š•úÃä/Õ4•+õ‡È_ªh+ûY.\+‚·‘!Rc4’Àl¹…¾Ú¼ì5¢®5Ýòïi—-·Õ&Z·–Ü[‘m/%KT€ ž´izÎJ°À $ŒW)qšÊZhKºHì°´žå$ö¦³,vùï¸ûì¯~´¶óo-µ¤ ¯N•$‚“ùÇRA!DŽI;Yuy÷%ÁgþäkT˜Í…'|¡"F•$¥@$)IÔž+Ât¤ƒÙ/fm³Ð^ë7lï=pmÇû÷§JÒÎ쥼©E/·IBs¨ ©G6FÆòT‡`ëiM¡’ÊYh¡—P´éJ‰ÀÆN‘Øð¥ËÚÂ\e¸”¥-ÇÜRÝÔR\YV§BR VJHBAHÀG+h'I½ZÛb.êÞýÉø…íâT§7M¾•¤Œ£.6 JJ²s§:M¢¢Ó³¶¤Ý¹¿ÚšqN´­â´¶¥%IYBs¥:µ¬¨áG$R” 2”(8¥…„ç 8îÿæ¹yè̲ãªiÒ”$¨áÁœþ”Î|WæE,1q•¨öNF •ò{4(œ€Æ¡U²’–’•meø¤ŒUyš ;÷n»9k¸¾”%éq}i@!!J@Q9á“P»+þëçÿä;Vd­V¨væµ3„0…,‚¢”¤$ŒqÀªöÊÿŸúùÿùÐ\$öÛÞZ¿Äú½ö§ë—ꦶÉ=¶÷–¯Æ±>¯}§iúåú© ÙÜíÇ|”z¢¸ý®/”çôœ®ÜíÇ|”z¢¸ý®/”çôœ kp³ZîÛ¾R¶Ã›ºÎï®XKš3ŒãP8Îð¦<ÎÙìþ‚×»VÀN5<ÚIà…wF{Õótkø+ÙA f¬6ùH• Ém!Ðë1…§# Ž÷©JWtkø+ÙL"Ïbd©ì0¢£ ñÅw ·hs‡îÀqÇhQEQ@QEQ@QEQ@QE%%§^Œ¶˜–ôG0d ­=ü¥Iâ28ƒÓßãJÑA\æ´Ïoÿn?Á£šÓ¯}§iúåú© ÙÜíÇ|”z¢¸ý®/”çôœ®ÜíÇ|”z¢¸ý®/”çôœ ŽÛEÈog&ª$•Æ‘¹l6ò:PN‘ŸÿÊÎù^çôŒ¿>¯mh›gþ•ä3ø¢©VË{ƒÐcªk­?-µ8 JBJǬòçvµ¥6n}ÊFÔBK· ¥À¶V² ³§ ñ=Ì¿÷U‹e¿¼6Ÿþî¯è3P¶Ûw$íÓPw»ÝÖ{=:s–‰èÉïÔÖËxm?ýÝ_Ðf±ƒföVÕ´sö’EÍ3q›ª™ow=öR”nYVP°:T£ÑÝ©ÿÉ®Ëø=Çïy«V»s·ïðþSˆÆÒ©ÙvþÀõÓ}dÚBt¸B‡Úð¢a‘Ù ÍìÕò*š ¶8ãRäA(Co4X¸»$!`¨pK.¡ ë¶@àHKÃØ-¸0§¢·qq´ºã$ò¬Á…¶µ6±ÅÎâ’¡ûñÃ…8üšì¿ƒÜ~÷—ñjU¬ìÿR­­€‹'Y%|¬¡¹ ¥¥–Û¸J¿GFí°1¨` !# ‘²ÒŸ‡pA°>Ä'zÝ.AbS­çÐ]ÞÈì´þ½m OéZ·zÈ B2“]—ð{Þòþ-“]—ð{Þòþ-Xm,Éf‚ÄÒÙ–ÜvÐñmÅ­%a + Y+PÎx¨’{¼iåKòk²þqûÞ_Å£òk²þqûÞ_Å«m/É®Ëø=ÇïyÉ®Ëø=Çïy­´PT¿&»/à÷½åüZ?&»/à÷½åüZ¶ÑARüšì¿ƒÜ~÷—ñhüšì¿ƒÜ~÷—ñjÛEKòk²þqûÞ_ŮјL³: Zi¤% ¨¨þˆâIâO|ž$ñ5jªÜÖ!¨ ÚùjüQ,Þà;s~Ü_CR›|°–ZR§”C¤ g*.'=î=Î5,®ÔoËWàš§½³sܽÜ^‹>áZžƒèLpÉ <0°¥6 S («**ÒÈÄȲ±ÖòY{-¡á»p+(^t«‡ùNAÁïW \à>²†fÆqAõF)C©$:T¦øÒSÒ5 ±v—m–§þ²\Pn0u²—¤†ÙJ³Ä”ïÂp§Wؤæ£í;&ฦw'­ã¾÷\¼ã®2ÀZ¤’QYN€4 E+Õ¤¤,'hm|¹ΙŒ®\†Ýq K©?«PJ“ŒçVupÇüµü“R•^…h¸Å¹YÝWY©ˆQ¥C^ƒ»!¥-²Ê’”£IV–’”‚Nž °ÐvÛjpœp9 ük®·_ÊkΧÛL¦Î~7Ý&{«L-´‘Ç9%Å$c†8xŽ"õ}~3¬ó>âh)Ï]Å8ÈÇÎÐX!Ëbá<Ø«ÞGÚ]ix#RT2À÷j·²¿àgþ¾þCµ/³Q·ì­ž¤näG„ËN£ éRPܨ•ÿ?õóÿò ¸Ií·¼µ~5‰õ{í;O×/ÕMm’{mï-_b}^ûNÓõËõSA³¹ÛŽù(õEqû\_)Ïé9]¹ÛŽù(õEqû\_)Ïé9A yÚKjÝzÖÛĦô†ÜÝZ¤)ƒ…hÁâ8àƒP­Ü¬,¸ÛY6‘ h¶¤À˜ Î@8áÒ‰«½Ö¯6V§‰É²í¥ù«¶ËYèÇtðáOvAN<»ôµF•¹72ëBK eJNå¡*ã ö5e¢;3 ÙŒõ2·”©ÒŒ§r¤à(¥(Àx (OtñÏú >S_}ß´Ÿv˜Q@ÿ”×ßwí'Ý£”×ßwí'ݦ¢µ9knäÌ­üW\SM*;juN©*RHBR —ú =ˆ<UÐ3Acå5÷ÝûI÷hå5÷ÝûI÷j²æÔZCK2VR´ëR’Ê §%$½„þd•\Ó‚…çôU‰zü¦¾û¿i>í¦¾û¿i>í0¢ÿ)¯¾ïÚO»G)¯¾ïÚO»L( Êkï»ö“îÑÊkï»ö“îÓ (òšûîý¤û´ršûîý¤û´ÂŠü¦¾û¿i>í3uaÇ50ç cÿÅqEuÖí:Zb†mÉYq—XBxc³pðïcˆãQ¼¿}ñ6ãéq~%Xè ®rý÷Ä󴁿”rý÷Ä󴁿•c¢‚¹Ë÷ßn>—âQË÷ßn>—âUŽŠ ç/ß|M¸ú\_‰G/ß|M¸ú\_‰V:(+œ¿}ñ6ãéq~%s³ðåÀØ·Y›Qß*–éiJJŠBÝqiÉI#8Pè&¬´Þ÷t¯ª_àhÉí·¼µ~5‰õ{í;O×/ÕMm’{mï-_b}^ûNÓõËõSA³¹ÛŽù(õEqû\_)Ïé9]¹ÛŽù(õEqû\_)Ïé9A•íßUÉ[/µ‚ÏÜËÈ‹ ËS䂿 •ilƒØö'ôˆ•¨ ãÉZB°Þ¥%åZÙYŽÛùL=Õ#gàJؾTJ¿AõøÎHFRŽ•8q<“¨ÍíD‰MõHÙ–šÚÖm̯:íª/ñýÃI×úY#(ʲ(-v댙³n,?k“ ¸†šyÒ’™)Ò´àž?‡wRS#Qv¸oƸ]vç2Z’ÛO¶ˆãB{Α©?¼dw?H,ªR€¢¨“-1oyxnj¥Ø‹M¥©n´V÷QÂ2N”ô÷©Ï3,¿&Þr~%ʪˆ¶\"B€ø†·œ‡y™1QÛZ5¸Ûª’¤©A9ÃÈV ‡ ÷x§a¶u lu¤ÅÚ &ë/$”‚æþúùÌð9zÌø´åX.íÁ¼°-ëqWÈ0’—[ÄE8ü—{*’œîõñBñžÇVUÖv.Àävœ\ ).!+À»L8 w£¸j'kvfËjÙ ¼è±¥¢K[KIgBôœ+ÒÇ ÅMæe—äÏûÎOÄ£™–_“?ï9?‚åESy™eù3þó“ñ(æe—äÏûÎOÄ ¹QTÞfY~Lÿ¼äüJ9™eù3þó“ñ(.TU7™–_“?ï9?ŽfY~Lÿ¼äüJ •Mæe—äÏûÎOÄ£™–_“?ï9?‚åESy™eù3þó“ñ(æe—äÏûÎOÄ ¹QTÞfY~Lÿ¼äüJ9™eù3þó“ñ(.TU7™–_“?ï9?ŽfY~Lÿ¼äüJ •Mæe—äÏûÎOÄ£™–_“?ï9?‚åMçÿwJú¥þª¼Ì²ü™ÿyÉø•mº¡ EšÛiJ”8”¥#¤öÛÞZ¿Äú½ö§ë—ꦶÉ=¶÷–¯Æ±>¯}§iúåú© ÙÜíÇ|”z¢¸ý®/”çôœ®ÜíÇ|”z¢¸ý®/”çôœ ‡¹Y'NÚ+]É‹ìÈ‘¡êßAi)ÝÈÏÊÏÿ|…pý'²¥çZ\™~´ÜS!”"û[kЇæ´„.ɼt?¥Ðk»Õòß³Öãpº<¶b¥A*q,­À’z3  ðÉá’Iɰ´Éa·Ønêë.$-"Ñ-IRHÈ †ø‚;´ìEDw¤º““!À⻌„£¤OŽ*Éîg½2´]àßmlÜ­¯ïâ=«væ…'8QIà H=Ê{A_‹hš­°¼ÏÝ$Fyˆ­6µ8”êR7…X熴ñèãûKò|Žó^yÚsE4ÅíDKep…=tV¥0 ¼ €8dã¾i íÏÑ›=÷¢þX( ¯çmÀJSjÙÄ%)J‘tsÒßxT}òÙ¶×»ë[v}¤ÊeM¦æ²S‘ŒãwÆ®P6äùæ¼ò=´r|Žó^yÚbô©ˆÛQÈë­ò-û-âdg£»œðÄ^ÑÜ¹bã¦ÑkDô6„ ¦BÉ{±sRIÓù”ŽÀ¤öJãÑ€±r|Žó^yÚ9>Gy¯¯}§iúåú© ÙÜíÇ|”z¢¸ý®/”çôœ®ÜíÇ|”z¢¸ý®/”çôœ ‡Ûð=ÿþÛ#új£c¿Àöûl馑ۙ gbî­5d·åFr3LÄaN¬©h)€8$g$ž÷t  rlͪÜì”Iqa6Û­Ë‚ë@ƒ…”é9Æ@8==ÛÞ¹J‰ ™o™èàác¸HHÎ:NOI&QEnáµ2£_$ÚáX¥Or;m¸âÚ}¤«Oé¨qìUÑžŠK¯çú\o‰IGÿÔ ÿý/Åê›­j'¯çú\o‰G:/^'Ïô¸ß¥¨ ‰çEëÄùþ—âWmmõ÷mìlò£“ÆlQÐ3Ýr¤éÕ¿¶Ç¿PÐA*eísšš­Š–d4ÚÚBùJ'¬¤¨c{Ž% þëL¥E¸Lp.FÄÜVx…ŽZ`RTU¡ÀÈJ”€¢‘V¾¿‡ályÁ\0ž}‚©1T†Ô¥«S©áØ(Äôê"±ŠÓM\˜¸™ÍìDàö¥-)7xÅ´-YÔ´¶^Е«*©Y=‘ÊÒ6ªïk0ÝÙ¡÷›[­¡3b«)AHQÈsiéïþãV.¿‡ályÁU©¯4÷T( iÄ8‘j’2•3½fNt^¼OŸéq¾%è½xŸ?Òã|J–¢µ¨žt^¼OŸéq¾%è½xŸ?Òã|J–¢‚'¯çú\o‰G:/^'Ïô¸ß¥¨ ‰çEëÄùþ—âQ΋׉óý.7Ä©j("yÑzñ>¥Æø”s¢õâ|ÿKñ*ZŠžt^¼OŸéq¾%è½xŸ?Òã|J–¢‚'¯çú\o‰G:/^'Ïô¸ß¥¨ ‰çEëÄùþ—âUŠà•¢¤8––r3ƒœΤ/?©¸y.~±‡{mï-_b}^ûNÓõËõS[džÛ{ËWãXŸW¾Ó´ýrýTÐlîvã¾J=Q\~×ÊsúNWnvã¾J=Q\~×ÊsúNPwE!&[7=p½×IQN£ú ž“Àg$’†‡´ñÜrâ¹ELÆmÀ¨Nî'®Ù(lkk#óÙqe#wœêF3©%A`¢Š(3n„ÍÂTþ¶JäÉJâÔµ~Š3¤5(÷øÿ¦èà}¥ûÔQ@hà}¥ûÔhà}¥ûÔQ@hà}¥ûÔŒ¨6éÑ—e²,†M<´«# œ ZŠ~gì—Š–_Ds?d¼T²ú ©Š(!ùŸ²^*Y}S˜6 ±âô ¶#ªN‚¶ݨ§ ã ôpŸÑ@hà}¥ûÔhà}¥ûÔQAíæÎÅÄAq¤‡µ% PmâÚ¬iBœ‚Trœ$N¤àvC2#ø#_i~õU&[. ¸ÎŒÜ5­™·H“Ó,-¶ÐÖãRT µê;…c #²NHã‹]¢?‚5ö—ïQ¢?‚5ö—ïQE¢?‚5ö—ïQ¢?‚5ö—ïQE¢?‚5ö—ïQ¢?‚5ö—ïQE¢?‚5ö—ïQ¢?‚5ö—ïQE¢?‚5ö—ïQ¢?‚5ö—ïQE¢?‚5ö—ïR75—!LYÆTÚÉÇúZ›Ïþî•õKü Ù=¶÷–¯Æ±>¯}§iúåú©­²Om½å«ñ¬O«ßiÚ~¹~ªh6w;qß%¨®?k‹å9ý'+·;qß%¨®?k‹å9ý'( ¯I”ܶ¸HŒöΉá":·Î¡I) *ׇð –ÂAZrœ/:9¶— sû6ÊX”ÂçÌvwà!/ÛÁYÆ€\H'ˆP^Œ(¸¯®2Ó«in4…©¥kmJH% ÁNGxáDg¼O~¢àìäRoNõ´e¦ìþõôn“»J ò!jãÝq]òH=€ÜöØP¸É!íY L¤'†µñÎxçý©ÕPQ&ZbÞ6òðÜÕJ-±*›KRÝh­î£„(d)éïSžfY~Lÿ¼äüJ’‹hš­°¼ÏÝ$Fyˆ­6µ8”êR7…X熴ñèãûKò|Žó^yÚÖªÜ̲ü™ÿyÉø”s2Ëògýç'âU§“äwšóÈöÑÉò;Íyä{h*Ü̲ü™ÿyÉø”s2Ëògýç'âU§“äwšóÈöÑÉò;Íyä{h*Ü̲ü™ÿyÉø”s2Ëògýç'âU§“äwšóÈöÑÉò;Íyä{h*Ü̲ü™ÿyÉø”s2Ëògýç'âU§“äwšóÈöÑÉò;Íyä{h+ж"Ää —ž¤éQÁ¹ÊÂIî9û©ß2vwÀåýë3âÔª£Üb¡NÃ÷ÂHKoKKI99P #“Ðz1æ¢s·?Fl÷Þ‹øuŒr½‹°B I%ÅÆí0`•úÞòk¾dìïËûÖgů‰;nm[8¥':Iº9ÀFWÞ&ŒíÏÑ›=÷¢þÇf­Úø6æ™šÓ !÷nrŽ¥Jz\$`)]:¿p§¼Ì²ü™ÿyÉø”î5—håm37K¤{Sf±Ò˜³·…EkmY:’œcAî÷EOr|Žó^yÚÖªÜ̲ü™ÿyÉø”s2Ëògýç'âU§“äwšóÈöÑÉò;Íyä{h*Ü̲ü™ÿyÉø”s2Ëògýç'âU§“äwšóÈöÑÉò;Íyä{h*Ü̲ü™ÿyÉø”s2Ëògýç'âU§“äwšóÈöÑÉò;Íyä{h*Ü̲ü™ÿyÉø”s2Ëògýç'âU§“äwšóÈöÑÉò;Íyä{h*Ü̲ü™ÿyÉø•mº¡ EšÛiJ”8”¥#Ÿ'Èï5ç‘í¥nä*<ò ¥ÂÿCXÙ=¶÷–¯Æ±>¯}§iúåú©­²Om½å«ñ¬O«ßiÚ~¹~ªh6w;qß%¨®?k‹å9ý'+·;qß%¨®?k‹å9ý'(;¨èû5Õõ1n»@˜òS¬·JPN@ÎO ‘Ç÷Ö)Õ¯kæH½¯f#¸¶ ÆJ% c|ác'Ò Õ§ôÔ8ö*èÏE%΋׉óý.7Ä ´ÑUnt^¼OŸéq¾%è½xŸ?Òã|J M\fý[ØÙØN*=?êçî4§+í‰Òþñ‡ñhìåÎá%û3’¦.BnöµÏ[kBc¬{ô¤?žPìÊbž=9µÕ>W+cêz.ÄNJ´è@]Þ2ÒÒ2†Ò§ˆm<Ø ا‡b1#ÊûEât¿¼aüZ ú*¤®º®L¨éÙÊv+§€™„¨¡+;ÌÅi<;ýüÒœè½xŸ?Òã|J MVçEëÄùþ—âQ΋׉óý.7Ä ´ÑUnt^¼OŸéq¾%è½xŸ?Òã|J MVçEëÄùþ—âQ΋׉óý.7Ä ´ÑUnt^¼OŸéq¾%è½xŸ?Òã|J MVçEëÄùþ—âQ΋׉óý.7Ä ´ÑUnt^¼OŸéq¾%è½xŸ?Òã|J MVçEëÄùþ—âQ΋׉óý.7Ä ´ÓyÿÝÒ¾©ª÷:/^'Ïô¸ß¬W­%!À´´° “‘œàð y'¶ÞòÕøÖ'Õï´í?\¿U5¶Ií·¼µ~5‰õ{í;O×/ÕMÎçn;ä£ÕÇíq|§?¤åvçn;ä£ÕÁá.7{'8$Oæœè¦ƒê¿Ôö}ÂãÎK4eÊS‰Crã2•-¡إĎ9Ò’á€xä‘7Ôi-¶‚×üõÜÜ[pc'xúÁi ¤~Š u«JéP­+Züg¢¹îÑ­~ 3Ñ\÷hZ#½6s{¹óÝ2¤£ îÔ@ o#Є¡½C´jé&¤+kðižŠç»Fµø4ÏEsÝ ªGÿÔ ÿý/Åꛥك›„©ü™)rd¥qjŽÿè£:@ÃRúaÎYú-ÿG~‚>ŠË?E¿èïÑ–~‹Ñß­kˆ®!¨2âÒ„…£*QÀ\õü? cÎ B}¦ÏtÝò†Í·3wq×4çÆAÆp?…3æ–Êø•î¥ûµŒH"L ëïªL\”¶„+z\5•œãŠýß_Ãð¶<à¨Îil¯‰P~ê_»G4¶WĨ?u/Ý ŠÙõ%w=¥RH)7RA†jv—ƒo¶[,ÀÙñ¥+YCm%X8§€þç,ýÿ£¿AEHeŸ¢ßôwèË?E¿èïÖµEHeŸ¢ßôwèË?E¿èïÐGÑRgè·ýú2ÏÑoú;ôôT†Yú-ÿG~Œ³ô[þŽý}!–~‹Ñߣ,ýÿ£¿AEHeŸ¢ßôwèË?E¿èïÐGÑRgè·ýú2ÏÑoú;ôõ!yýMÃÉsð4eŸ¢ßôwé“Ëvµª4¤•6²IŒà ÷Hà+}'¶ÞòÕøÖ'Õï´í?\¿U5¶Ií·¼µ~5‰õ{í;O×/ÕMÎçn;ä£ÕÇíq|§?¤åvçn;ä£ÕÇíq|§?¤åJRP’¥(%)$œ)¿)AðØþu>Ú._Ýrþ¥~©¬ºÉn³ò}¥‡6~ÎéU’<¥ºä4)jpéI$ãN{ù©êê×J“{t†ÌcNú©iùGV£ÊP|6?O¶ŽRƒá±üê}µŸrm“òÈ<Û²u¯%õî¾±F½{ÝÎ1Œ~ìç»JÛm6)›M|¶¹³vPÌ·Ý)0Q¨ëAQÕÃ#†¯M4mzÚÕÿŒf}â>ó ™ÃDJ’´…%AIPÈ ä]%*Z‚R’¥€M)'¶ÞòÕøÑõ‡È_ªj@ëi0ïØ4u´˜wìŠj|¤\®Ÿm1-qšµs\¦Ën^¤ä)xñ9$œŽi{Ú-¨‡"±s =¡Çn[MÇi“’¥ê$•`aX áŠùqÅô-¹ÿ)H™¾qË~yÇñÖ;š³]-9ÕÔœV;§J¢ÇvD„–Xin8àÒ”$ ’Iàs_+<¼ßîw½‹Ú·^´H·[Ó0žu+R•‚@àS£±ÆFxž8}\LuûÄý¦cêsïùòúO7Hmn! QéÂFk¾¶‘óýƒC_«È²k)¿uF¼Â¿»m³¦ÅIuÆËIˆöñ$å'²Â¸‘Þ<[Co}{Mhâ÷ŠFe«u´˜wìMðbµ½7-êJ5¹ØJ!)=ÒHwI²zª]WjvS¯ÙÐúp1_R••`äêwÆ3žŽ§sÚ –ÌÄwhm¦Û/—¡6–wKoS{æˆ$(œñ'ˆáÃ÷VjhN­Y˜ÍzÇçöR+jb|3Ò?:ù4*í 8æt!JÇN‘œWª{QÏ-?‚ª,m#æû޶‘óýƒITu‚{·]œµÜ_Jô¸>´ ¥ (œðÉ ‘{û2šKÿš.¯Ca}޵`«=' QÇxÜ¢«·õ(m6Ê''Išñ#< ëW½¦¬T¡—\CkPèÊRMuÖÒ>aß°i ÝuÈÎuŽç®ðîãÞ½#N¬qÓœgqY¾Îߺ£m5†5â{*Üy´%á ,iQIÈŽ”žíŸÖÒ>aß°ieô0éyÄ©hm\¤¤€¢t¤ä÷5ýQ&íÙlµ½ûÆÒE°È¶1 :›k%äêZS©!`¥XÔ{Sžø©§Ô£Õrt‹D’x¾cØ(,UÚuÁ”6µŒ¥$ת»Q¿-_‚h¶‘óýƒG[Hù‡~Áª^ÁíËako|×Z\ÒÞñÈä—¨§zÖIÝ$`÷ 6—nX³_-–XmuÔÙScǬÜT¸®Èÿ:’Ržð*< s„2út„<âT´6® RR@QºRr{š‡~ŸýÝ+ê—ø…}J=Qà''H´I g€;æ=‚¦§ÿwJú¥þìžÛ{ËWãXŸW¾Ó´ýrýTÖÙ'¶ÞòÕøÖ'Õï´í?\¿U4;¸ï’TWµÅòœþ“•Û¸ï’TWµÅòœþ“”Ü¿ºåýJýSTû½26>Å!¤ JM­†Â”8-´’‚qÀdpñâ2 Âåý×/êWêš®ì—ø2Åÿoý4×6¥oY­º:‰Æc´òŸXž°‡å6¹ðˆK7eÚ‚wKh¤ãz¡ÅxPH#¤`:JB,p-ÍÂSï«K“$¨.KáK„ Žâ@àNI$’c¹Oå—µµÖ¼—ÖZ2uëÞëÎ1Œc÷ç=ÊžªÒö®Ÿ‚?™óüûóòÇ1LIí·¼µ~4Gýaòêš$öÛÞZ¿#þ°ù õMp)½¤äͦSî&bÚ·0AhMÝGì€%Ť'* ¢R:@DÜn-¦–‰¶Ûî·SIµË- $ç|°…6uðB³£CJÿEíÏfÙºm4›£ómêdèÜ´]é)Hì—ÃŽtŽú\N4®›.zn0@V8ïxçÎqÇ t×Äâ[}-Å5xv†5#œÞs9™ëŠÚf½fg8ëÓü\¢":c³xtëÎÚ³¸ýüóŸœãèU¯Õ¿äY5mM±]n 2ÒLçÞ.¢1S‹R—€’¬’zp2{„ÖøÚ’†$)D†òI<Ô+=V̦EÞUÂUŠ[Î*:7üIQ ô~™‰îgºUζïu¶ˆ¾Û¯Ê'îçˆN¥tâtë6ô… &ÂÈë=rf6Ó¥$¡!‚VÁ$q JÆ¥iN0u$jV8Fá«~ÆÛcI¹½<"ù2· üÛaÖ‚Pœ“„Œp‡˜E›BJEÆECÒr{ŸëÿïJêÒ"Ù-ñÌ–_-B_æ—«±ß¶8÷kͶâ|_^Ó¥»ŸÑ<ÿmcŸnqú¾W ¿Æ7ðsíŸÊñJ§µòÓø*’®Ôâ‚êÜZP´eJ8‚«Þý"†m»UùE…)#u²"bàò!­¦^oR·m——©ÀuCN®%AA&"ÓoÚWŸØ¹LIdÚ“ii1ón"3û•º”ºŒêF´¥y jÓ¤¨éÂØó‚£¬‹VÎZíÏÍŠ§¢Di…©‚’¤ $‘œpÈ Žº&R/Û ™¯2ô2F·h¶ƒý™ìa%J#†;§ÿÅZª±zËûQ²»—[sÎ…ìÎÕžUv£~Z¿Ö ²[C¶–-‹³u¬k#vT´"á08Rʔ냔«)†5iÒ5'$qÆé5þ·µ…¤³¼Ô½ØyÍÚT­#«÷àÿ¡ª†ÄÚÓbØ–l‡íî·¨Piýãn¡j*:‚’>QqSÍ=Õ šq$Z$Œ¥@Œï˜ ³RªíFüµ~ ¤«ä×úÞÖ’ÎóR÷aç7iR´Œ¬߃þ†ƒ0Ø›chú‘YQ×BžÇ\*$øê)v:‹®A’8)9â;Äme–†Ý²0á¥d¦ˆã¯:­N>âµêqÅ™DôŸö ™Ø(+Ù­‹g¸Ì·©èÊpÇ‘­+J–WžÉ)ÁʈÇŒçŽgEï‘y6M°õ…É©îu̲ޭÞp¥ éÔx÷1ÐsÀ¿ÿ©0?í¬ÅMÏþî•õKü @©æžêM8‡-FR FwÌTôÿîé_T¿ÀÐ=“Ûoyjükê÷ÚvŸ®_ªšÛ$öÛÞZ¿Äú½ö§ë—ꦃgs·òQêŠáIs|˶\Ð¥’“‚…'üÄ• íÎÜwÉGª( MIyi)T%)* ¼É}º[®®6ÿ¤µï×4Pu×W›ÒZ÷è뫇Ϳé-{õÍ•IQ$ÅY'‰%ö½úo.nWm­c¯Úyl- ÁÈÈ+ÁâÿjuE3¶Å W£ÅöÑÌíŸñBÕèñ}µ=E3¶Å W£ÅöÔßö_žgß®è e>ÚÅÕ„±q³31”«XnAaÄ…`ŒáJÛìl¥µ§›PZC1R¤¨‚Wv¦¨ ãûG‚/Ï3ïÓ+…žÛwÊV(ÓwYÝõÈŽæŒã8Ô£Œà ¢‚™Û?â…«ÑâûhævÏø¡jôx¾Úž¢‚"&ÍZmò‘*ÌÀ!Ðë-ÆBÓ‘ƒ‚‘À‘þõ)ý£Áç™÷ëº("çØm×WÒýÇgaÌy)Јî('$ã*Qá’x~úkÌíŸñBÕèñ}µ=E3¶Å W£ÅöÓ¨u©õ?nÙØpÞRt#¢;j)È8ÊT8dº¥( ãûG‚/Ï3ïÔtû ºêú_¸ìì9%:’ÅäœeJ<2OßR”P@ó;güPµz<_mÎÙÿ-^ÛSÔPEÀ°Û­O©ûvÎÆò“ ¹ÛQNAÆR¡Ã pýÔòKržˆóIˆ ¥¡Iy¬d.œQ@¤‚%Ò ¬GúÖ)Õï´í?\¿U5³Ö1Õï´í?\¿U43Ͷ¹ŽïeÌ%Þ4•ã±+Äo‡èÍû+·;qß%¨¦»¢,–I—7[SÅhº¤$à:qûèn#x?FoÙFâ7Côfý•_åûK‹ñ(åûK‹ñ(,ˆÞÑ›öQ¸àPý¿eWù~ûâmÇÒâüJ9~ûâmÇÒâüJ â7Côfý”n#x?FoÙUþ_¾ø›qô¸¿Ž_¾ø›qô¸¿‚Á¸àPý¿eˆÞÑ›öU—ï¾&Ü}./Ä£—ï¾&Ü}./Ä °n#x?FoÙFâ7Côfý•_åûK‹ñ(åûK‹ñ(,ˆÞÑ›öQ¸àPý¿eWù~ûâmÇÒâüJ9~ûâmÇÒâüJ â7Côfý”n#x?FoÙUþ_¾ø›qô¸¿Ž_¾ø›qô¸¿‚Á¸àPý¿eˆÞÑ›öU—ï¾&Ü}./Ä£—ï¾&Ü}./Ä °n#x?FoÙFâ7Côfý•_åûK‹ñ(åûK‹ñ(,ˆÞÑ›öQ¸àPý¿eWù~ûâmÇÒâüJ9~ûâmÇÒâüJ â7Côfý”n#x?FoÙUþ_¾ø›qô¸¿¤­Sn3ÒòæYŸ·!²óí,¬œôÔ®ŒqÎ:F3ÇûqÀ¡ú3~Ê7¼ £7ì§;¶’Ú· Æp”Ý#¿û«æ˜ÿ:ï›õ}Äo‡èÍû(ÜFð(~Œß²œió®ù±ïQ¦?λæÇ½@ßqÀ¡ú3~Ê7¼ £7ì§cüë¾l{Ôió®ù±ïP7ÜFð(~Œß²Äo‡èÍû)Ƙÿ:ï›õGßnQ¬– …ÐïëHëx6R¬¥$„ç'<3ƒŒÐ8ÜFð(~Œß²±¾¯)JaZB„'|æ„„ا¸8VÏXÇW¾Ó´ýrýTÐlîvã¾J=QU;ÿ_èÜü*Æçn;ä£Õ\Ûïð÷þÏ‚ÇEP@í%Îåi`ÌÖÝlÒrP¶\qO+é+I a8OëW©#VH=”[ÛYrfl­ÜDJJ%¶á¶Ã‰R‹Ip§LŒ–ÝR‹xÝ!:Ó¬çõj©ë­‘mHvtÆ£ºÙfLv–܆Îr•$”äPR¢Oá³z踩S p㯵8†]t,-Ä­ 9¨ïéYYÀNœ¿.é:t5L‡®Ü`\#) ~2”ÚÂÉÆiÏ¥µƒŒ’ØN@Q5½‹ˆ¸F!¸OÜ¡2r×öf5!E¤öšTBNóY)Ïd#ùÙ5m¡ ›mKEÇÝÕ1–ìye)h¥¶›K™RÔ\Z@JÔIaxœ&R^ÐJüž¯háEg® ´NC8t'-ë 2p3ÞÎ1”ç!ѲÊ,!'hn»ô©DH€­$  §u»#)CŽ ·l1\±¿eK5or‚–PG摤§)QêÒ@쉈áÓîÿ=ÛVÎ].,% z$G_BV IRPTÆ8dT,í§—Èsnq†Rܶ"4Óñ][ÈÔò¥¸Ð)^JV–ÆF“žÏJl78 ]mS-Ï©if[ ajAA*II#9ãƒL®=y–¡&LeITwX(ì\ezÒà IGI$¥ Êæ6Šjlrn/¥—H—¸[ SR¥¯t²VÒU¥ZŠÃyó‰"ÑP26yKµH·¢JÞå®2$­Öô„¬a Ê„·Ø„àY*”õJ§µòÓø*’¥SÚŽyiü@;ú¶<ƒë*’¨»®Öìõ©æâνÀ%ÂÙ[é FI##9=ÃL9ý²^0Û¼ø ’¾=%‹C«†ê|©J”¤‚u-)!»á„v%e9ᚯ3x»¢U¢#n-Ò«¢¢ÍLíÛo¡=l§BºJ›QÆ<x•¨8—¶{>*ãI¿[–Òñ$`‚A¥@€A €AS$_v Æ@¾Ä&<‘-ë.BJu)eZ—Ø8Q#N@Xûq"L–á5iCÓ} ·¹°Â¶ÞZ\KŽ6IË ÉJHÒAIYìj^Ç:ã.ëfj Eš–£nÜÔBK-¯i(+¤ñQ ÀG»õ;‹6<¶oRôu3ý¹e(ÊJBBJ°”©a)Æ”jV5½µÛlÉlßà¥éŠJß̲R¥%! „“„ @ÀÎqAmªæß€/¿ôn~sûd¼a·yñP{g¶{5?bï1bß ºû±Km¥á•tßA¬c«ßiÚ~¹~ªkg¬c«ßiÚ~¹~ªh6w;qß%¨¤&5è®75 .2°CÀ(g¡@ð#÷—s·òQꊮm÷øûÿFçáA`åxÞùtr¼o ‡üº‡ævËø·gô½Ú9²þ-Ùý¯v‚c•ãxL?åÑÊñ¼&òê™Û/âÝŸÐZ÷hævËø·gô½Ú ŽWá0ÿ—G+Æð˜˪íÏg6JÕj™qfmJf# }iDŠŠR’¢@ãMm– ‰Ò OÙ yl6ÛÄ0Âl¡Â°žÈ¶ƒ«-¯#Æ8œÙÊñ¼&òèåxÞùuž#›m÷v&È”ÜXCöà–[QZVãM¤=ù±»9Ötï05ôàj”‹jÙQç"ç²öHе©I™»ˆ‡PK¹IÝ…(hZÊr0xþWá0ÿ—G+Æð˜˪ik©ò[uÇ,vÖRÓkqÍõœ·§BJÔ’Øìô½¤S٤斉oØY²‘«µ// !ëFë²:¶Æ¤jÐ{-=–4ñ ¶r¼o ‡üº9^7„Ãþ]Vœ²lKR•v+8C[®NFµ‚RR4åIÀQÔ2…ä Äuæß³–Çå†v:Èû6ø‚lÕ®;hRZ%xÝ€ÙÖ¬4¾ ~'våxÞùtr¼o ‡üº©Üìó¢À²ßmÇ€}„2ØCe]mgV\F1ŒñÅÅ/9¶¦ÆØË?&)È̸ã‘ÚKÉ[éiHÃa%#~ÞN°Ge€p5Êñ¼&òèåxÞùuSoØ[tãM‚Ú ¥ÒhÖT ’ÙJRT”§9QÀ’EMu>K‰oíªQl8tYÊ´åJ@Jˆo±YZ€ƒ… 8Õ‚åÊñ¼&òèåxÞùufvB|TI³Öu´¼à˜ ‚8 ‚œ¥@‚8 ‚RÜÎÙìþ‚×»A1Êñ¼&òèåxÞùuÌí—ñnÏè-{´s;eü[³ú ^íÇ+Æð˜Ë®“pjH-6û ÿ1Kzsþ¼?Ö¡y²þ-Ùý¯v¤í¶k]¦$ŽM¶Ã…½[{ζa-ëÀV3¤ ã'øÐ= RBu €sžœwî£tkø+ÙC¿«cÈ>²©*wHð†¿‚½”n‘á {)’”ûÒi§[e-! R–Ñp¨¬¨¤ãtôÒ/ÜÛˆ¢‰âæ´«VT ‘¬Ĥ={¤xC_Á^Ê7Hð†¿‚½”ÀÍ!{£@|”èeI R ñ8O,áDLjèËYw–Yk=pÛ q)XÁÎì¸NB¿Dg8Çs9áA3ºG„5üì¦wY‘¬ö‰—)¥LÄeo-(R‚A8dã$q§N£vêÑœéQïâ«;}þ¾ÿѹøPXëê÷ÚvŸ®_ªšÙëê÷ÚvŸ®_ªš ÎÜwÉGª*¹·ßà ïýŸ…XÜíÇ|”z¢›\ Fº@z Æ÷‘ŸN‡[ÔS­=Ñ‘Äg£† š)]ê<¯â¯mÔx;_Å^Ú¨¥w¨ðv¿Š½´oQàí{h\à5uµL·>¥¥™l-…©©%$ŒçŽ 2…kžÄ¹3äÎŒìçÒË*SQTÛa¦Ô¥`$¸£¨ïµcô{Tæõ×ñW¶ê<¯â¯m=ï[EaÛ’›sbÜS¤¡(q§^ìÎðæ;YÓ»È×Ñ‘¥êöuÙ+Ü)3P©Wt¸}¶JP…)¤´ PTNPžG'<@8=ê<¯â¯mÔx;_Å^Ú •çcùY«‚:ÿu×r\;Z5Â1qúC8μÿ·ï§¼ßÿ‹õÿ]î]£wÿÒu¾ŒçÿåŸöÇv¬Ôx;_Å^Ú7¨ðv¿Š½´oÙ]zâ¹ý|´ÉKíª:ÂN`iÞ3ŒáAxY$ŒåH SANE-umax - other UMAX scanners
SANE-logo
UMAX-logo

Other UMAX scanners





The sane-umax library implements a SANE backend that provides access to several UMAX-SCSI-scanners. Parallel- and USB- scanners are not supported!
Here is a list of the UMAX-scanners:
UMAX scanners
 Other scanners:
Name
SCSI-ID
Versions
UTA
ADF
B/W
Gray
Color
Bits/pixel
Resolution
Gemini D-16
Gemini D-16
?
X
 
ok
ok
ok
1,8,10,24,30
400 x 800
800 x 1600
PageScan
PSD
all
--
 
ok
ok
ok
1,8,24
300 x 300

UTA = Umax Transparancy Adapter, ADF = Automatic Document Feeder
(X = supported by scanner, incl = is included)




This page has been changed on 12th. february 2001

Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/umax.CHANGES0000664000175000017500000011262412112021330014674 00000000000000CHANGES FOR UMAX BACKEND FOR SANE --------------------------------- umax -> sane-0.6: ----------------- * umax-sane-backend created: - umax.c splitted in: umax-cli.c, umax-scsi.c, umax-driver.c, umax-text.c - umax.h splitted in: umax-scanner.h, umax-scsi.h, umax-scsidef.h, umax-struct.h - outputs done by DBG(level,msg,args...) defined in debug.h - scsi-calls changed to sane-format (of sane-0.57) - created umax.c and umax.h for sane-backend * changed search-path for scsi.h and sg.h, now needs /usr/include/scsi * removed mistake in bound-function * added "Vista S-6E" as supported * added PowerLook-II (PL-II) as supported * added Astra 600S as supported sane-0.6 / 0.61 / 0.62 -> 0.63 ------------------------------ * added exception to gpl-licence: > This program is free software; you can redistribute it and/or > modify it under the terms of the GNU General Public License as > published by the Free Software Foundation; either version 2 of the > License, or (at your option) any later version. > > This program is distributed in the hope that it will be useful, but > WITHOUT ANY WARRANTY; without even the implied warranty of > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > General Public License for more details. > > You should have received a copy of the GNU General Public License > along with this program; if not, write to the Free Software > Foundation, Inc., 59 Temple Place - Suite 330, Boston, > MA 02111-1307, USA. > > As a special exception, the authors of SANE give permission for > additional uses of the libraries contained in this release of SANE. > > The exception is that, if you link a SANE library with other files > to produce an executable, this does not by itself cause the > resulting executable to be covered by the GNU General Public > License. Your use of that executable is in no way restricted on > account of linking the SANE library code into it. > > This exception does not, however, invalidate any other reasons why > the executable file might be covered by the GNU General Public > License. > > If you submit changes to SANE to the maintainers to be included in > a subsequent release, you agree by submitting the changes that > those changes may be distributed with this exception intact. > > If you write modifications of your own for SANE, it is your choice > whether to permit this exception to apply to your modifications. > If you do not wish that, delete this exception notice. * split resolution in x-res and y-res, flag bind-resolution * only sane_... functions will be exported from umax-backend, all umax_... functions are made static * removed umax-emergency-routine for SANE * made program-flow (esp. with do_canel) SANE-specific * fixed missing 3-pass parts * made scanmodes, sources, analog gamma, gamma download, negative, quality calibration, highlight, shadow only selectable if they are available * calibration-mode selectable in advanced options if available * warmup selectable if available * changed umax-scsi.c like described from Gordon Matzigkeit in his diff/patch-file from 21.06.97 so that the umax-backend should compile on non-linux-systems now - thanks! * split highlight and shadow in R, G and B for color-mode. * reset adf and uta flag when not used (in sane_start) * added possibilty to change calibration-mode if available * added send_halftone_pattern to umax-scsi.c * changed umax-scsi.c like described from Gordon Matzigkeit in his diff/patch-file from 21.06.97 so that the umax-backend should compile on non-linux-systems now - thanks * added support for each color (R,G,B) for highlight and shadow * added "Astra 1200S" and "UC840" as supported * added bad bugfix for preview-problem with S6E (in umax-scsi.c function start_scan) * moved resolution-check from check_values to bound_scanarea, now no floatingpoint-exception will occur if no resolution is given! * changed range-check for width and height * removed bug in set_window for three-pass-rgb-mode -selected wrong buffer for some green and blue options -scanmode now is greyscale instead of rgb * changed start_scan(us) to better use with wid-list and added missing 3 wid-bytes in scan.cmd * removed parameter color in three_pass_function_headers, the color ist taken from us->three_pass_color now. sane-0.63/0.64/0.65 -> 0.66 --------------------------- * changed gamma-data-upload for 3-pass-color-scan * corrected wrong calculation for highlight and shadow selection for rgb-values * changed gamma data to use 8 bit (256 bytes) or 10 bit (1024 bytes) * included 10/30 bits per pixel mode * changed bug in sane_exit (free()) that sometimes made a segmentation-fault * made patches runtime-selectable * changed set_window_command to support 30 bits per pixel * changed send_gamma_data to support three_pass_gamma and 10/30 bpp * changed row_len in umax_bound_scanarea to 10/30 bit mode * added halftone-support for ug630, uc630 and uc840, but I don't know if all values are ok! * changed CBHS-50-range to 78-178 (from 103-153) * changed rangecheck for highlight and shadow * fixed get_cbhs_range-bug in umax-scsidef.h * added ADF-inquiry-bits to umax-scsidef.h * added color_line_arrangement_mode-inquiry-byte to umax-scsidef.h * added CCD_line_distance-inquiry-byte to umax-scsidef.h * added all most unused bits and bytes in inquiry to umax-scsidef.h * made patches runtime-selectable sane-0.66 -> 0.67 ----------------- * removed bug in sane_start: ADF and UTA flags have not been set correct * removed bug in init_options: value range for 10 gamma-input-bits corrected * made custom gamma available for lineart and halftone for nonlinear effects * added Vista-T630 as supported scanner * removed test_warmup in wait_scanner because adaptec 1542 has problems with request_sense-command in test_warmup it was only used for printing a message, so it was not important. * if a scanner has a full inquiry-block but is not known to be supported, the driver will print a warning and continue instead of aborting, option --continue (on umax-cli) will suppress the warning! * changed ugly definition char gamma[x] -> char *gamma; gamma=alloca(x); * removed bug (wrong length for 10 bit-gamma) in send_gamma_data * changed all buffer-definitions to unsigned char and insterted type conversions, so there are no more warnings because of typemismatches. * corrected bad definition of set_DCF2_gamma_output_bits sane-0.67 -> 0.68 ----------------- * changed open config to fp = sanei_config_open(UMAX_CONFIG_FILE) * changed all set OPT...BIND commands, endless-loop happend in sane-0.67 =>ane-0.67-umax-fix.diff.gz after that patch changed same for ten_bit_mode * changed some strdup() to (SANE_Char *)strdup() * added UMAX Astra 610S as supported scanner. it has the same problems in color-mode like the Astra 600S. sane-0.68 -> 0.69 ----------------- * changed maximum y-resolution from optical_res to y_res * changed sane_cancel (waitpid) like suggested by David Mosberger * added #include for AIX-support * replaced call to umax_wait_scanner with umax_do_calibration after umax_start_scan in umax.c * moved sense_handler to umax-scsi.c * removed call to umax_get_data_buffer_status in reader_process * added umax_send_shading_data, umax_send_gain_data and umax_read_shading_data, umax_read_gain_data * changed name: umax_read_data_block -> umax_read_image_data * changed length offest in do_inquiry from 5 to 4 and changed set_inquiry_length-offset from 5 to 4 * added calib_lines to structure US and added it to set_window - command in umax-scsi.c * changed in umax-scsi.c routine identify_scanner: vendor and product is tested for each model instead of vendor=="UMAX " and only model tested! Because of that the format of scanner_str has changed from product,product,... to vendor,product, vendor,product,... * added support for Linotype Hell Jade (LinoHell Office) * added empty routine umax_do_calibration in umax-scsi.c, it shall be called after umax_start_scan! * replaced all umax_*scsi with sanei_*scsi, so the umax-driver now directly calls the sanei_scsi-commands. * moved sense-handler from umax.c to umax-scsi.c and added detection for driver-calibration-request sense_handler got a new parameter (void *arg). * changed wait_scanner for SUN: usleep(0.1sec) -> sleep(1s) this is only a bad bugfix that will be replaced one day! sane-0.69 -> 0.70 ----------------- * moved reader_process to umax-scsi.c * changed include for _AIX and non-_AIX * added missing "," in definition line for UMAX Astra 1200S in umax-scanner.h * added in umax-scsi.c in function identify_scanner a test that only warnings and errors are printed if vendor="UMAX " * added routine umax_order_line_to_pixel and umax_order_line * moved reader_process from umax.c to umax-scsi.c and added routine for color ordering. * reset length offest in do_inquiry from 4 to 5 and set_inquiry_length-offset from 4 to 5 because umax-S6E didn't work with it! * corrected error in identify-scanner in vendor-test * changed end-detection of list of known scanners from #define known_scanners 15 to last item "END_OF_LIST" * added routine that corrects wrong inquiry-data from Astra 600S and Astra 610S * added test and selection for do_color_ordering in check_values * changed __sun-code in umax_wait_scanner because the scsi-driver answers with IOERROR instead of DEVICE_BUSY (this is only a bugfix for a little time) sane-0.70/0.71 -> 0.72 ---------------------- * inactivated selection of quality calibration (until it is supported by the driver) * changed maximum x_resolution from optical_res to max_x_res * reordered DBG-levels and defined them by symbols * changed all sizes that used type int to type size_t * changed wait_scanner for testing !sane_status_good, because testing sane_status_device_busy does not work with all scsi-drivers! * changed ccd-order in umax_order_line, the order is now specified by 9 values (before by 3 values), changed order tables and added a table for Astra 600S and another table for Astra 610S * changed ccd-order, now based on optical_resolution and added new routine umax_forget_line * added inquiry-block for UC1200S: NOT TESTED! * added inquiry-block for UC1260: NOT TESTED! * included print_inquiry into umax-scsi.c * added correction-routine for x_res > 600 dpi, phys_width is corrected in umax-scsi.c: bound_scanarea * changed umax-scsi: sense_handler: changed test for valid sense-block added test for button pressed * added output of sense-code and error-code in sense_handler * added options to select calibratin and scan exposure times * added options to select calibratin and scan lamp density * moved all option-names/titles/descr. to saneopts.h * combined bind for highlight, shadow, analog-gamma and new exposure time functions to rgb-bind * added set_WD_line_arrangement(buffer_r, WD_line_arrengement_by_driver); if driver is doing color-ordering from line to pixel * included umax-scsi.c into umax.c * included umax-struct.h into umax.h * included US-structure into Umax_Device-structure * added free(scanner->device->buffer) to sane_close * added free(scanner->device->pixelbuffer) to sane_cancel * added free(scanner->device->pixelbuffer) to do_cancel * added SANE_UNIT_MICROSECOND to exposure-times * added output of status-string in wait_scanner * moved some options for Scan-mode-block to Enhancemant-block sane-0.72 -> 0.73 ----------------- * disabled RGB_BIND if no such value is available * included readproc * included bound_scanarea into check_values, problem with wrong scanarea for UTA should be solved now! * all scanmode- and scansource-strings are #DEFINEd now sane-0.73 -> 0.74 ----------------- * added support for 12/36 bits per pixel (for Astra 1220S) * added support for Astra 1220S * included inquiry data for UG80 (Escom Image Scanner 256) * moved WAIT_SCANNER from umax_read_data to umax_read_image_data, umax_read_shading_data now works! * added umax_start_scan at the end of calibration by driver, the scanner does not hang any more if quality calibration is enabled! There must'nt be a "wait_scanner" in calibration by driver routine!!! * added usage of driver internal values for calibration by driver if the scanner does not give back the informations about the shading data: width = dev->width * dev->inquiry_optical_res ( * 3 in RGB-mode ) * added 2 calibration-routines: - use last line for shading data - calculate average value for shading data - prepared routine for complex calculation * added gamma download curve format type 0 and 1 * defined gamma DCF = 1 for UC1200S and UC1260 * defined gamma DCF = 0 for UC1200SE and ARCUS PLUS * changed sense_handler: if bad sense_key => DEVICE_BUSY problem with black area at top of scan for some SCSI-adapters is solved now * changed wait_scanner: waits 0.5 sec now * disabled quality calibration in preview mode * made upper_left_x and upper_left_y even values it looks like even resolutions > 600 dpi work now! (not ok!!!) * added sigterm_handler for umax_reader_process changed sane_canel, do_canel and do_eof(=close_pipe), cancel now works! * changed trim_rowbufsize that made problems with SGI, there has been an overflow because of big buffersize sane-0.74 -> 1.00 (build 0) --------------------------- * added output of umax-backend-version in sane_init * added support for Linotype Hell Jade2 (Vobis ScanBoostar Premium) SCSI-ID "LinoHell","Office2" * changed base of calculation of scanwidth and scanlegth from pixel to resolutionbase (1/300, 1/600 or 1/1200 inch) problem with wrong pixelcount at higher resolutions should be solved now * changed selection for calibration mode * changed calculation for width in pixels for lineart and halftone mode * added inquiry for UMAX UC1200SE * corrected 12/36-bit-mode in send_gamma_data and array in umax.h * added support for Gemini D-16 sane-1.00-build-0 -> build-1 ----------------------------- * added support for Nikon AX-210 * changed all grey to gray (David Mosberger asked for it) * changed bug in gray gamma table conversion * added Linotype Hell Saphir 2 as supported scanner * changed umax-uc1260.h * added "- 1" in umax_order_line: else if (dev->pixelline_opt_res < length * 3 - CCD_distance * 3 - 1) else if (dev->pixelline_opt_res < length * 3 - CCD_distance - 1) * changed all allloca() to malloc() + free() * removed options speed and smear, I got the info from umax that these values should never be changed! * removed ten_bit_mode and twelve_bit_mode options, added option bit_depth and added support for 9, 14 and 16 bpp * replaced u10_range and u12_range by dynamically set scanner.output_range * removed static allocation for gamma_table[0..3], this is done dynamically in sane_open and freed in sane_close now. * added an empty string to the end of scan_mode_list and source_list build-1 -> build-2 ------------------ * added "*info |= SANE_INFO_RELOAD_PARAMS;" in control_option set bit_depth * added inverted calibration modes for Astra 6X0S scanners. build-2 -> build-3 (sane-1.0.1) ------------------------------- * inversion of calibration is automatically set for Astra 6X0S and Vista S6E * check for machine endianess is done only at backend start now! * made umax_do request_sense static build-3 -> build-4 ------------------ * Added option name and parameter in debug output in option set value * Added option name in debug output in option get value * Changed calculation of pixels/line and lines, may be the problem with shaered images at resolutions>600 dpi is solved now later Remark: This error does still occur, but not so often! build-4 -> build-5 ------------------ * Changed calculation in umax_order_line, color images should have the correct length now for Astra 6X0S and Vista S6E * Added DOR resolutions and area build-5 -> build-6 ------------------ * Bits for ADF and UTA in driver internal inquiry block (old UMAX scanners) are set dynamically now. * Added Genius ColorPage-HR5 (vendor KYE) (=Astra 1200S) as supported scanner * Added Astra 2400S as experimentally supported scanner * Added pauses for Astra 2400S * Removed reposition_scanner at start of scan, Astra 2400S does not work with it! * changed debug output in correct_inquiry * for UMAX S12 the driver does not wait any more until scanner is repositioned this is experimental, it may work with other scanners too! build-6 -> build-7 ------------------ * changed some int -> unsigned int (resolution and scanwidth etc) * calculate_pixel is called with right values in UTA mode now. * if DOR resolution is not defined and DOR is available the DOR resolution is set to double standard resolution * removed wait_scanner after set_window-command * added Mirage D16-L as supported scanner * Astra 2400S works stable now build-7 -> build-8 ------------------ * for Mirage D-16L the driver does not wait any more until scanner is repositioned this is experimental, it may work with other scanners too! * Mirage D-16L does not give back informations for calibration by driver, added new modus that "guesses" the values for Mirage D-16L. * Added read_shading_data to 16 bit calibration routine and made a routine for averaging with low byte first and one for high byte first * Byte order (HBT) is set always (also in lineart and halftone) because it is used in driver calibration * Added relevant_*_res the is set to normal or double resolution values * Added test if scsi buffer is large enough for one shading line * selection for Calibration mode, Shading type and Speed/Smear are only compiled in if define is set in umax.h build-8 -> build-9 ------------------ * slow speed options is preset for Vista T-630 * speed/smear can be set now (forgotten #ifdef) * selection of exposure times now is only available if it is enabeld * gamma table is disabled in lineart and halftone modes * if image is transmitted completly sane_read (close_pipe) returns with SANE_STATUS_GOOD in adf mode and in any other case with SANE_STATUS_EOF build-9 -> build-10 ------------------- * removed change about sane_read returns SANE_STATUS_GOOD in ADF mode * transformed all gif files into jpeg format because of all the trouble about the gif licence. Will never use gif again! * added correction for inquiry-ADF-bit for Astra 2400S * added second test method to detect ADF error in sane_start: inquiry block is read and cover open, jammed and no paper is tested build-10 -> build-11 -------------------- * test for adf errors (sane_start) is now only done if adf is selected build-11 -> build-12 -------------------- * moved adf error tests from sane_start to umax_start_scan * sane_control_option: printing option name is set to "(none)" if pointer is NULL * added error message after each call of sanei_scsi_cmd * changed manipulation of ADF bit for Astra 2400S in umax_correct_inquiry from dev->adf to set_inquiry_sc_adf() build-12 -> build-13 -------------------- * changed inquiry data of UC1200SE * added set_inquiry_CBHS(50) in correct_inquiry for UC1200SE * correct_inquiry is called for scanners with short inquiry now * dev->inquiry_max_calib_lines is preset to 66, problem with Vist S6E V1.6 should be solved this way. * inquiry block parameters > 0x93 are only used if block is long enough build-13 -> build-14 -------------------- * changed inquiry_cbhs_[min,max] -> inquiry_[contrast, brightness, threshold, highlight, shadow]_[min,max] and set correct values for CBHS_255 and CBHS_50 * changed cbhs_str[CBHS_50] from "78-178" to "0-50" * changed umax-uc1200se.h inquiry byte 0x64 bit 5 to 0 (gamma download format != 2) and wdb len from 0x30 to 0x31 * disabled halftone pattern download, and halftone dimension selection - not ready preselected is a 8x8 built in halftone pattern * removed set_inquiry_CBHS(50) from correct_inquiry for UC1200SE * added "Astra 2200 " as supported scanner * added cast from (void *) to (unsigned char*) in umax_send_gamma_data build-14 -> build-15 -------------------- * add "(unsigned)" to option number test in sane_control_option * for Astra 1200 the driver does not wait any more until scanner is repositioned this is experimental, it may work with other scanners too! build-15 -> build-16 -------------------- * OPT_SOURCE: removed change of width/height and "*info |= SANE_INFO_RELOAD_PARAMS;" from get_value to set_value and added "*info |= SANE_INFO_RELOAD_OPTIONS;" build-16 -> build-17 -------------------- * changed calibration mode from SHADING_TYPE_AVERAGE_INVERT to SHADING_TYPE_AVERAGE for UMAX S-6E, UMAX S-6EG and Vista-S6E * changed several int -> unsigned int * added support for sanei_scsi_open_extended and variable scsi buffer size build-17 -> build-18 (sane-1.0.2) --------------------------------- * some cosmetic changes of the form if (..) {...} => if (..) { ... } * removed unnecessary SHADING_TYPE-handling routines for UMAX S-6E, UMAX S-6EG and Vista-S6E * scsi buffer is only reallocated when size has changed build-18 -> build-19 -------------------- * added UMAX PowerLook III as supported scanner * added EPSON Perfection600 as supported scanner (is a Astra 1200S) * type of option 0 (Option numbers) is set to SANE_TYPE_INT now (undefined before) * removed bug that mixed 12 bit and 14/16 bit gamma table when 14 or 16 bit are supported and changed value range of grey custom gamma table: - maximum output value is 255 for 8 bits/pixel - maximum output value is 65535 for 9-16 bits/pixel the custom gamma table does work now with 9-16 bits/pixel output mode * added routine that reverses bit order in lineart mode when scanner sends LSB first in lineart build-19 -> build-20 -------------------- * added variable calibration_width_offset, Mirage D-16L offset of 308 is defined there and added offset of 28 for PowerLook III * umax_do_calibration: guessed calibration data vaules use 2 bytes/color if scanner supports gamma input bit depth supports 2 bytes/color * calibration by driver now does work for PowerLook III * added function umax_set_rgb_bind() that sets the sensitivity of some options that make available different settings for RGB. This function now is called when scanmode is selected. * changed some int to unsigned int * made dev->pause_after_reposition = -1; as default, so as default sane-umax does not wait any more while the scanhead is moving back - this may break the support of some scanners so it may have to be changed (dev->pause_after_reposition = 0;) for some scanners. reported to work for: - Supervista S12 - PowerLook III - Astra 2200 build-20 -> build-21 (sane-1.0.3) --------------------------------- * Added Linotype "JADE" as supported scanner * Removed bug in sane_close that caused segfault when sane_close was called twice with the same scanner handle build-21 -> build-22 -------------------- * replaced fgets() by sanei_config_read() * added command queueing for scsi read commands - removed WAIT_SCANNER scsi command call after read command - the additional buffers are allocated in the reader process - the number of buffers can be defined in umax.conf with option scsi-maxqueue [1..8] default:2 (did some tests with Supervista S12 and PowerLook III on the same scsi controller (ncr53c810): command queueing works, it is possible to start both scanners at the same time. The scanner with the higher scsi-ID (=priority) does scan without stops, the other scanner has to wait long time between the scsi-read commands, it also is possible to give bothe scanners different scsi command queueing depth). * prepared replacement of pipe by sanei_ipc_* routines * added routines umax_get_lamp_status and umax_set_lamp_status * updated inquiry output (new bits from powerlook scsi protocol 1.0 X101) * added new (powerlook scsi protocol 1.0 X101) window descriptor block entries to umax-scsidef.h * added button protocol (3 buttons, from powerlook scsi protocol 1.0 X101) * added button "lamp off" to turn off scanner lamp (this option may be remoeved again in later version, may be it will be replaced by an autmatic lamp turn off function) * added options to umax.conf lamp-off-at-exit [01] default:0 lamp-off-time [10..720] (in minutes) default:30 * if lamp_off_at_exit == 1 and lamp_control_available == 1 the scanner lamp is turned off in sane_close * renamed umax-scanner.h and umax-"scannername".h to umax*.c because these files create data code build-22 -> build-23 -------------------- * scsi commands set/get lamp control are send with a command length of 10 bytes instead of 6 bytes and control bit #7 is in byte 0x03 and not in byte 0x04 (it is described incorrect in the umax doc) * enabled lamp control for Astra 2200 * removed umax.conf options lamp-off-at-exit and lamp-off-time * added frontend option lamp-off-at-exit * added frontend option lamp-on * forcing calibration_bytespp = 1 for Astra 2200 - quality calibration does work now * for Astra 2200 selection for different x/y resolutions is disabled build-23 -> build-24 (sane-1.0.4) -------------------- * forcing calibration_bytespp = 1 for Astra 2100S * Added Astra 2100S as supported scanner * enabled lamp control for Astra 2100S * Added warning in sane_control_option if option could not be set build-24 -> build-25 -------------------- * dev->lamp_control_available is preset to 0 * dev is erased (0) after it is allocated * added special options for PowerLook 3000: - calibration is done for each CCD pixel - calibration_bytespp is set to 1 the scanner still is not listed as supported scanner because the changes are not tested * added options that are read from umax.conf: - execute-request-sense: values: 0=disabled, 1=enabled, default=0 If set to 1 umax_do_request_sense is called in umax_do_calibration. This can hang the system (but has been enabled until this version) - scsi-buffer-size-min, scsi-buffer-size-max: values: 4096-1048576, default min=65536, max=131072 - scan-lines, preview-lines: values: 1-65535, default scan-lines=40, preview-lines=10 define the maximum number of lines that are scanned into one buffer - force-preview-bit-rgb: values: 0=disabled, 1=enabled, default=0 set preview bit in rgb real scan - slow-speed, care-about-smearing: values: -1=auto, 0=disabled, 1=enabled, default=-1 dangerous options, needed for some scanners - calibration-full-ccd: values: -1=auto, 0=disabled, 1=enabled, default=-1 do calibration for each pixel of ccd instead of selected image - calibration-width-offset: values: -1=disabled, >=0 set value add an offset width to the calculated with for image/ccd - calibration-bytes-pixel: values: -1=disabled, 0=not set, 1=1 byte/pixel, 2=x bytes/pixel use # bytes per pixel for calibration - invert-shading-data: values: -1=auto, 0=disabled, 1=enabled, default=-1 invert shading data before sending it back to the scanner - lamp-control-available: values: 0=automatically set by driver - if known, 1=available, default=0 * updated html-documentation * updated sane-umax.man * added pre focus options (PowerLook 3000): - FP - fix focus position - FDC - lens calibration in doc position - PF - disable pre focus - LCL - use 0.6/0.0mm holder focus position * added #define SANE_I18N(text) text to umax.c. This is to mark the backend specific texts that shall be translated by the frontend build-25 -> build-26 -------------------- * added umax.conf option handle-bad-sense-error # * added Mirage II as supported scanner * added routine umax_set_max_geometry that defines available surface and resolution in dependance of scansource and double optical resolution (before this bugfix the change of dor mode overwrote the settings of scansource and vice versa) * added ESCORT Galleria 600S as supported scanner, is an Astra 600S * removed if (config_line[len - 1] == '\n')... while reading config file * changed some static unsigned int to static int * sane_exit does free devlist * added some options for Powerlook 3000 - still is not completly supported build-26 -> build-27 -------------------- * added Linotype Saphir4 as supported scanner (is a Powerlook III) * increased length of vendor, product and version by 1 to make sure the string always ends with '\0' * changed default minimum scsi buffer size from 64KB to 32 KB build-27 -> build-28 -------------------- * removed "#include " from umax.c, assert() is never called * added UMAX Powerlook 3000 as supported scanner * bugfix for 3 pass scanning: reposition_scanner is called in sane_start for 2nd and 3rd pass of 3 pass scan * bugfix for UTA and DOR geometry offsets: - added inquiry_uta_x_off and inquiry_uta_y_off - geometry ranges are defined from xoff..xoff+dx, yoff..yoff+dx now - check_values also does test for this range - removed dev->maxwidth and dev->maxlength, values are calculated in place now * bugfix for DOR: - bottom-right edge keeps in position if possible when DOR is switched on * bugfix for Astra 600S and 610S color mode: - scale_y is set to 0.5 if y_resolutions is smaller than optical_res/2 this does fix the color scan problems for Astra 610S. * added Heidelberg Linoscan 1400 "HDM LS4H1S" as supported scanner build-28 -> build-29 -------------------- * removed bug in umax_set_max_geomentry: now left y keeps in position when possible * rgb bind keeps unchanged when scanmode != color (only gray selection active in this case) * in function static int umax_give_scanner(Umax_Device *dev) moved umax_reposition_scanner(dev); to the end of the function * set calibration area for astra 2200 to full ccd and calibration_bytespp to 2 * UC840 does wait in reposition_scanner until scan head stops moving * set minimum resolution to 5 (was 1 before what could make problems) build-29 -> build-30 -------------------- * added EDGE KTX-9600US as supported scanner * Changing scansource does not change lower left selection edge if not necessary build-30 -> build-31 (sane-1.0.6) --------------------------------- * sane-umax.man uses @LIBDIR@ and @CONFIGFIR@ * changed automatic calibration_width_offset marker from -1 to -99999 * changed dev->calibration_area to 1 and calibration_width_offset to -1 and inquiry_max_calibration_data_lines to 66 for UMAX Supervista S-12, LinoHell Office and LinHell JADE build-31 -> build-32 (sane-1.0.7) --------------------------------- * added Nikon AX-110 as supported scanner (Vista S6E) * added umax.conf option "gamma-lsb-padded" with options: -1 = auto 0 = inactive (msb padded) 1 = active (lsb padded) activated for astra 1220s, internal 12 bit gamma correction does work now build-32 -> build-33 -------------------- * added USB support for Astra 2200 thanks to Frank Zago for creating umax-usb.c and suggesting several changes to umax.c * added umax.conf option "connection-type", values: 1=scsi, 2=usb * added umax.conf device selection "usb 0x1606 0x0230" (usb vendor_id product_id) * removed #ifdef HAVE_SANEI_IPC parts (SANEI_IPC was never defined) build-33 -> build-34 (sane-backends-1.0.8) -------------------- * removed bug in reader_process / umax_queue_read_image_data: - the integer value that keeps the length information is kept valid as long a queued scsi command is still running now - when the scsi command returns with less data than requested then the routine does handle this correct now (before the routine handled this as if the requested amount of data was returned) * backend waits until scanhead has repositioned after scan for UMAX UC1260 * y_dpi quanitsation is set to 5 (same as x_dpi quantisation - was 1) build-34 -> build-35 -------------------- * changed ID string "LS4H1S " to "LS4H1S " (remove one space) * activated lamp control for Astra 1220S V1.5 build-35 -> build-36 -------------------- * added PowerLook 2100XL as supported scanner * settings for PowerLook 2100XL: calibration_width_offest = 52 (calibration_bytespp = 2, default) (calibration area = image, default) * force_quality_calibration defined for PowerLook 2100XL: (normal calibration mode expects different calibration_width_offsets for PowerLook 2100XL, so it is not possible to calculate the correct number of calibration pixels in normal calibration mode) - disable quality calibration option for frontend - always set quality calibration bit when scanning * changes for exposure times: - Inquiry does print correct maximum value now - changed variable type from SANE_FIXED to SANE_INT - exposure times setting for colormode does work correct now - as default there is only one common setting for exposure times in rgb mode, added umax.conf option exposure-time-rgb-bind to enable different settings for each color - added option select-calibration-exposure-time, disabled by default. if disabled then the calibration expousre times are the same as the scan exposure times * added UMAX PS-2400X as supported device * added batch scanning support: Options: --batch-scan-start: calibration, scan, scanhead is not moved into home position --batch-scan-loop: no calibration, scan, scanhead is not moved into home position --batch-scan-end: no calibration, scan, scanhead is moved into home position --batch-next-tl-y: defines the y start position of the bext batch scan - calibration for batch scan needs a different offset and always is done for full ccd. PowerLook 2100XL: calibration_width_offset_batch = 1052 Powerlook III: calibration_width_offset_batch = 828 build-36 -> build-37 -------------------- * added Linotype Hell SAPHIR3 as supported scanner * if batch-next-tl-y is not set then the backend uses br_y build-37 -> build-38 (sane-backends-1.0.9) -------------------- * added Power Look 2000 as supported scanner build-38 -> build-39 (sane-backends-1.0.10) -------------------- * Power Look 2000: corrected wrong calibration-width-offset from 52 to 22 and added calibration-width-offset-batch to 24 * initialized some global pointers and num_devices in sane_init * replaced fork() by thread for OS2 build-39 -> build-40 (sane-backends-1.0.12) -------------------- * UC630: dev->pause_after_reposition = 0 build-40 -> build-41 (sane-backends-1.0.13) -------------------- * Astra 2200 SU via USB connection: quality calibration is reset and not selectable build-41 -> build-42 -------------------- * replaced fork() routines by sanei_thread routines * added call sanei_scsi_req_flush_all(); to do_cancel - in threaded case this is not done when reader_process is cancled * in reader_process: marked freed scsi buffers as freed(NULL). This is necessary when reader_process is run as thread! * Backend is compatible to Mac OS-X now. build-42 -> build-43 -------------------- * DOR mode does test for non negative upper_left_x values, set to 0 if negative build-43 -> build-44 -------------------- * the sense_hanlder stores the sense data in buffer[0] when valid sense data is avialable * do_calibration: - corrected bug in reading calibration width from scanner (added /bytespp) - when additional request sense is not called then the buffer is not erased, the sense data from the sense_handler is used - when additional request sense is called then the buffer is erased at first build-44 -> build-45 -------------------- * added defualt options for Linotype Opal2 * changed bug in highlight-blue function (using green value) sane-backends-1.0.27/doc/umax/sane-umax-not-listed-doc.html0000664000175000017500000000567212112021330020343 00000000000000 SANE-umax - Not listed UMAX scanners
SANE-logo
UMAX-logo

Not listed UMAX scanners





The sane-umax library implements a SANE backend that provides access to several UMAX-SCSI-scanners. Parallel- and USB- scanners are not supported!

If you own a UMAX-SCSI-scanner that is not listed as supported, it may work with SANE. It depends on the information the scanner returns to the umax-backend. If the data-block is large enough, the backend prints a warning and continues, but it is possible that not everything works fine.

I suggest you hold one hand on the power-button of the scanner while you try the first scans!









This page has been changed on 12th. february 2001

Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-uc-doc.html0000664000175000017500000002272412112021330016665 00000000000000 SANE-umax - UMAX UC scanners
SANE-logo
UMAX-logo

UMAX UC scanners





UMAX scanners
 UMAX UC series:
Name/ID
Versions
UTA
ADF
Lineart
B/W
Gray
Color
Bits/pixel
Resolution
UC630
not 2.8
X
 
ok
?
bad
bad
1,8,24
600 x 600
UC630
2.8
X
 
ok
?
ok
ok, 3pass
1,8,24
600 x 600
UG630
all
 
 
ok
?
ok
--
1,8
600 x 600
UG80
all
--
 
ok
?
ok
--
1,8
300 x 300
UC840
not 1.6
X
 
ok
?
bad
bad
1,8,24
800 x 800
UC840
1.6
X
 
ok
?
ok
ok, 3pass
1,8,24
800 x 800
UC1200S
?
X
 
?
?
?
?
1,8,24
10,30##
600 x 1200
UC1200SE
<3.0
X
 
?
?
?
?
1,8,24
10,30##
600 x 1200
UC1200SE
3.0
X
 
ok
ok
ok
ok
1,8,24
10,30##
600 x 1200
UC1260
not 1.6
X
 
?
?
bad
bad
1,8,24
10,30##
600 x 1200
UC1260
1.6
X
 
ok
?
ok
ok
1,8,24
10,30##
600 x 1200

UTA = Umax Transparancy Adapter, ADF = Automatic Document Feeder
(X = supported by scanner, incl = is included)


The UC-series UMAX scanners often make problems. That may have to do with the firmware version. The first firmware versions are not compatible with Windows95, so I think they will not work with this driver too. UMAX suggests to use the following firmware versions for Windows 95:

Suggested firmware versions for old UMAX scanners
Name
suggested firmware version
(read on UMAX's german website)
last firmware version
UC630 ###
2.8
2.8
UC840
1.6
1.6
UC1200S
2.5
2.5
UC1200SE
--
3.3
UC1260
1.6
1.6

### The UC630 can not be upgraded if the last 4 digits of the serial number are less than 1000!


Here you can find information about firmware versions of UMAX scanners.
 



This page has been changed on 12th. february 2001

Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-logo.jpg0000664000175000017500000001537412112021330015322 00000000000000ÿØÿàJFIFÿþhMade with GIMP CREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ–€"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷ú(¨§-ãÞà‘žƒ­ Ø j).a„‘$¨¬vÜó§^Õs­–c;NpBóôçð¬F½™ãq¹rTa{tÇå\ò®–Ũw:ÆÕ-†pY†:犤úð*è‘ ˜2û€8ïÇ<×)xò°°~_¨=È5 º3À¼òzŽ?òk'^l¥tÒø–HˆÜ"íÚr?ZŒkÒ‘¹n ‰Ã*‚ ãõ5„ˆÌ’yŽ­¸‘’:Ž˜ü©—)´Ux_LƒÜƒþMG´Ÿqò£þ ˺,¥˜tG¥Vo_E,nnI“Ƽðzàg¿b:ÙÎ5¼lЀ0¤p{ŒTË•“Ì`Ù$GQÓùZ^Ò]ÇÊŽ†/ÎrÆdSÀPÅ=úç=½*ü>#°–c™!l€<ÅàçÜgŽ:×r»p ®6ñÆAH>œzmº;BJñÁ'‘ŽÕj¼Ðœé1Ëщ"ut=NAüiÕçP  •§†vŽ`Äy‰‘ŽààqúV•·Š¯l&Hµ8ÖâØ‘›˜Æ9%@ÁçÞ`csÆ:ã“Åliß ¼¦yžFi'™ßjÝsŒg§˜[o^ØÏè+O«÷dóœT:ö˜Æ¡ ru?ç4zÕ¤åcŠh{«wïÇã]ïü!¾ÿ¡oGÿÀ¿øš­yðÿ—ÏÉ¢[DÑgiµÍ¿\uòÊîéÆsŽqÔÑõ0ö‡/çÀì`ÒSŸóúÒÅ$œI=½søt­{‡V‘Ê$Òu ‹¼7”ãÎŒ¸À†ç¯,{ñÓŽŸ©Z´–·Öªä(Û,`˜Û#³c¨Áã¯áYN”¢R’eS;åÑI?Â{ðHÇãJÏ›&CǦîÏëQɺ7Ù {Ïùê)··†$…-íßh+á?.æäeAa‘œã' $fQD]ßøgR}GJQ*…Vº·lªJ™nø?0ì{gž©iZ¶³¥[j6º ˆÃ®H%}Tà‚3ÁW ·[W´Š%)´€‡œç’I<“žsÔ“š>_Ì­â E¥…ÒM<„áe òþ6•ßêísdñ `ù“#<åž™÷®ìB²ïêÍ€?Ú$ÿŸÖ£­+Ž­ã- ã Ž“sþZÎñŒúŽƒ}“÷’+(oè?ò+J¤I@W2þ·Nj3)|Dˆ£w¡üOÖ°EGÃë‹ü¦%…¬6i^L¶ÐŒ,R¯ßÉ<œ°,KÀžMtÕåzuãx[W–þÚ/6 ­©w ¹ðN}ÆOÁÉö#Ólï-õ H®í%Y`”nG^ÿà}»W}:ŠhÆQ±=QZQE#2 Ë0ÔšÇÕoákRªëì[¾Gÿ^µ'·Šæ&Žd ¬ ú¡¨®ZûáîŸq;Oi¨YÈcÚgó#ÝÏÌÁòǶ@aÓ·Z΢“VE+-Ìp¥Äžc«n%O^G@?ϽGr˜^BòP{}9þºuç‡|I¤ÆíƒR·LÔ—É;r0“‘Ç¥85k—dmËt‡cÆã AÓθ¥ GsTÓ,B…áùHRÌ{sÓÖ¡ø\IñŸŒÁ`ÅE˜Èöó…HTÀ¯!•WsŸ_çù[à¬?k“ÅZè˜u~¶¢ ¼/”»·g<çÎéŽ6ûñ®{Í“=W®GVÓ…¬â1BåâÆÑŽW8Ó×]TõK3}§M…ó æ=Çp铃ØñКè«x‘fqÃ4‘í ÞŸÖ©JL,²>Cc#Ÿ›üój«®j¶þ³y5ï+"?súç?Ö²4 ÅÿZ ¹IѼ;9WóØÿ¤\Dsþ­yÛœ[ W)ÊLÕÉ"Ö«âý&ÆXm“72Ê-áMò;žªÉ$ãñ©ü*> M¬G}§èk§i¹¤‹TœÂ³|ÁHòÀgG8Èb£…îuáïøoÁPgO´D¹uÛ%Ü¿¼¸›îƒ–ë‚UIUƒÈ´fÖ£T  'Lù‡¦~†º!OVõ3mÈÕ¨Úâb­4a‡ÉÜkþln²LŽ¥ˆäà8ÿ?…eÞjÙy‘—±È#©Ý=ÿÁ†ùå‹ ™2¥À³“íÌdbW†Ç ãå`G ¨ úéÕ ±-Ü(¢ŠÐF=ï…tMG[µÖ/4øæ¿´`ðÈÄáXtm¹ÚHìH$`c Å‹ÛËÅ,ldËl.Ì#T÷;¹ uÈÛ=+BŠMÅ^è^1Öa6¯¦éhµ´OrÏ×;·lÛŽ1Œõ=1Îe¯Âwx_û[źµÌåŽÔ$ ·‚¬“œœçÓŽ9ôŠlåÆÏ‚p3ŒŸnjy"ºìó†øCáûyb–ëZÖåŒ8o&K”Û.>b¸T rû¤Jv¥á_Ø£³Y7«6¥:éßy>½»W7ñ'âUä:³h: ¢Þ Ä÷'¥¾{ö¿Ïæ¶vrjÞ}¶YnnV˜I;n8S–ã¦Zô°9F#RŒ;¾¾„N¬a£Õž¹á BÎh’ÊîÊC Qqa¨¼åS*K~ðãÔ”ñÓžšOíþÓÏÓüC®I¹F̨¤0<‚¦ AïÈäz^7‹a¸·‘㕃|¡ŽÒ7axéÔ7=~_jìt^^Ì/,¤Xuë8òxÈ8ܬ?‰N#¶ ÷?çõ¯H®?W´HæeEˆùrç„ÆÐFq£X×…½äTCE×.<'¨Ggu'›£\8™€û+1å²x “ó àrGp}:¼ÇQ·ŠþÒ{WŒ9u )éZ¿ 5æÔ49´{’~Û£8·`F ˆƒå€WŸ“'­U ÝYŠk©ÜÑE`ë¾!·Òì䙤 "äÔÿœ:ÚRQWd¥sVëP³±…庹Ž(Óï³7ÝúÔn§ý«w6öò-”‰½'æsÁU%HÉÉÇðã äp ðüþ1‰|Oâ…ÙNû?I–3å,y#Í‘[‡f¯U†ä‘·Óè\ÏVÁXÞ'ÔLÐî®× °Âòn-Œ8Ç çô­šæ«*Dí ¶’ÑI*®Q]¥Œ…'Ôíb=vŸCXÐøŠžÇ¬êS<›ÕI†â:ëùà~5Ák°ÇªÅ4LªVBÃÆo3k‚p§’@9Ær+gL¼¾°ˆF·RlRªI ƒjôwxÉã©ÆTe€Ëc'¥6ßS·¸]¶ïg‘†ïߊõJæu/ø{Qù’Ïì3… ³XŸ(¨?t|¤õ œaŽya×CE>ç8d…ðY‹9ã8ûÞøÿ=è‰eŠO–C€qßÿ­’2j{Ÿ‡7𴯦ëÀªÐCwlîÇF‘HàžáxŽ*ŒÞñ½¥£È Ò¯™pgevÉ9uQÇ^HéëY:Es¢À½—îG·Ûß'Š‘®ÉÁ21~‡½Ïùü†4ï™Éá’Hî/ Ïþ‡éV¾ÃãTÿÂ&0yº·Ïç¾—²Ÿ`æF‚Ir’€f8xg¿øtæ£7.˱TO7~¦©½·0qá-Þ€Þ@?óÖsi'ºÉg f–öF:nm®Në€O £ÙMôdn³ÄÍó2p‹ž¸ÿõôéU'¼·ÓŽéî‘ ¶[¯áùTqü9ñ–¡ç CÄfž#gn×õÎKlÛŽ1Œç'§}»ƒþ‚èÜßµþ®áÑÑoî2ˆTçî U`xÈ`Àã뛎½ÄæŽ|Yy®\I§xSIŸU¹O¾ñ`E ‘½Îsµ±’2Gñ]ðŽKÝBWƺ’êSÆáÓO·è ‚q¼°ÌƒîœaFA0¯K±°³Ó,ã³°´‚ÒÖ<ì†Äh¹$œ(àd’±]§ìC“aEV„…cë>#³Ñ¯,l9îuÿ3ìvp(ß?–|3•EÚ§?3 ㌞+b¹øwÃ^3Õmô›û¹àÖôø…í¬–“´SÛ£H˜ŸÂ~h€'o €-ÇâÙ[Ót»ïk6¨<‰óˆ-ÈŒä3G+m%TàÎ:t•æ–7Þ+ðÿ´Oøž÷M×í57¸–Âü[.-Þ(AbUFÀ0Σ$9%€ùk³ñ¬êztpèzïö-ÒÊ®>È—;“Úç$ƒŸozجø›Kð–uM^&ÔKY±,Àp½[,@ÉÚ¬@8­Šóƒm©øÖòmphÚV£¡\Z=®–—×YÏ2“IŸÞ€»XDaq‚ÍC‚xn­â¸·–9 •Ç$l]HÈ Ž#œÔ•æ uKÏê÷ß|As‹»M³i&YŒžu«.|´soòðFqýà Çoâ=;YÔôèáÐõßì[¥”;\}‘.w&)µÎI>Þô¡}q-¥œ“Ãe=䋌A@ï’ÙW޼‘Ó׊æ<ñ+Ãþ=ûLz[Ï Õ¿/ktª’ãç1rqÁàã dg¯¯ðáñ/¯ ê–WÒi:þžó›MNò¯Ú%Ê:äB àžç±`À‡¬øÑtoØèo¡j·7WþgØÞo²-¾ Ê¥vƒü@gfºŠñ -w]½ø½àÅ^N·¤ý¸KsMäoÉ2të±²0#±Ê¯¯ëvšö‘=¶•ªeß>ß.óìë?—†üÁÈ{g=¨ÅõĶ–rO ”÷’.1¾He^:òGO^+ðçĨ¼[§I¡øg\»µŽS >mcÀ yÁèÃó®Þ¼3à•y}à[ÙmõýKOA©H¦+XíÙIò¢ù™œóޏàqÖ€=_Eñ Ö5MGM—IÔ´Û»…äKÕ²nÚQ‘Ø0ùc¨8ܬ½.F³+¤Þj’j:‚#ÎÒ´*åÍûE8ùGMûÃcR€ ÏÔô-[ò¿µt«ÿ'>_Ú­Ò]™Æq¸gòQ@Yé:nŸquqe§Ú[Ovûî$†F™²N\–9br}O­\¢Š¯}ag©ÙÉgiݬ˜ß ñ‰°ASÁÁþ›¤éº=»[éz}¥Œ åÚ;XV%-€2B€3€}…Py¼5 ÜêƒTŸDÓeÔ«‹·µF”2ãiÞFr00sÆjQEW¾°³Ôì䳿´‚îÖLo†xÄˆØ Œ©àà€ MÒtÝÝ­ô½>ÒÆrí¬+–À!@À>Š(I¬,î/-¯&´‚K«]ÞDÏ/á†ÚÇ•Èàã­X¢ŠŽx!º·–Þâ(æ‚T)$r(eu#x Ž1Xð‚øCþ…MÿÑñ4Q@f…£èžoöV•caçcÌû-ºE¿Ævœdþf´(¢€?ÿÙsane-backends-1.0.27/doc/umax/sane-umax-standard.jpg0000664000175000017500000003634312112021330017131 00000000000000ÿØÿàJFIFÿþXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ5"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?êµMÃ:\q³xkG(V1…Ó c’€÷_­fnð§ý _þ ­ÿøšØñüzCõ‹ÿE×ßÇum:ÜÛÎÅKs¿©éüºý3©>EÍkx<2ÄÔö\ê-í}›í~‡Y»ÂŸô,iø*·ÿâhÝáOú4¿ü[ÿñ5ÎÚ\­é2+Œ!ÆÅ'¯©öôÿ”5ä¹’[%¶¹\ƒ#/´˜ç pÇ<qÓžHÅTd¤®¶2¯Bt'ìê+In»Žï б¥ÿàªßÿ‰£w…?èXÒÿðUoÿÄ×—=ýÜš}ƒYj7 6²!1ÜÆÂH²r#s¿.|žrF1Z—#¸·Õ£„ia{õ³)r™L§äÜTúg½Q‰Þîð§ý _þ ­ÿøš7xSþ…/ÿVÿüMyµ¯‹¯þÅcwumlÉuË„ˆ²a³“œgÇ>¹ç4×5Ô~×q=´a´e¹Uwu„38Á+ÉÈÎ02[‘œMÝáOú4¿ü[ÿñ4nð§ý _þ ­ÿøšói¼Y¨Ã,¶ñ[Eq4w@»¢x<Å‘Xãkœ©Êã'#œâ«ë:Ö·ý™¬[Êm šÄ@$’ÕÝI.ÙO^˜R=ÉÏbê;¼)ÿBÆ—ÿ‚«þ&Þÿ¡cKÿÁU¿ÿ\¦¹©M§Cf-Ö3-ÕÜvÊÒU7gæ ž2+jW•¾ž‘Úy­wsk$Œ¬ù`àgŽ¿w'8ê3è{¼)ÿBÆ—ÿ‚«þ&Þÿ¡cKÿÁU¿ÿ^mm¬ß꺇†.VU.„þl+¸«9äg8ã?túÔ:w‰¯äÓ#XRxôù¯]¥ó%ݶFP£/‘Ó©'¯N(Ó÷xSþ…/ÿVÿüM¼)ÿBÆ—ÿ‚«þ&¼ÚO_ˆ/îã¶¶ö±Ú˱‹"P¤®zù±Æ:ñ ÚÝü:òY]%µ¬rϲ”7ï£änY+»8; Ž g&€;Þÿ¡cKÿÁU¿ÿFï б¥ÿàªßÿ‰®3ijÍöG“,‘ùšœ(ûÊsqÔ{V¹yü%~]Üéä}“ÊÛ!^ìgo¦{â€=?w…?èXÒÿðUoÿÄѻŸô,iø*·ÿâk̯¼Cwws¢ÛÄKÈ’ÿËp6È]—ËáŽAØçuÎ:r0xàÐ_»ÂŸô,iø*·ÿâhÝáOú4¿ü[ÿñ5ÁIr‡ôf–{É®¥ vÐNQî\ ûÌ>`rN@NxÙF¡nþÑnï¤v¸ó Ìñ1G-w ×<Ž£&€;ýÞÿ¡cKÿÁU¿ÿFï б¥ÿàªßÿ‰®ÊâvmRÓMûJ^Àb>N§/™{‡fVfåFq“Î:sCkwðëÉet–Ö±Ë>ÈPß¾‘¹d®ìàì*:œšîwxSþ…/ÿVÿüM¼)ÿBÆ—ÿ‚«þ&¼Ú?_˜,.ä¶¶6÷QÝK±K Ä.zù±Îz scGÔ/ï‡ýqÿAZ}“[m‚¯áºûDVòFIåVTÛôÆzSï<w|Ñ4ö,^Lr$á20pÊÀŒŽ£5èÔTÆÂkâj×iÕ•ÚV×±æð€Éö?²ÿf~ïÍóóçüþfs¿~íÛ½óžÝ*3ðïïÒ¼µglŠãb«Œa•U€Vàr0zúšõ *ŒO1áñŠ;X×JR–¢E…Z`À >ø ·9Éëš~¢«ì…!àû;nŸvS ËvÀÁê0< õ*(ËÏö7Ü6#M«‡k²Ie$©l¿ÌFHçŽ:qN½ø|u%’ëJYP¢CçÝ·¡áºŽ™ë‚FqÅzuçwž½¿…b¹±ÞªáÔ‰‚²°èA >â±î~_>¥¦ÉŒkknóÉ0ió#»† œ–g$ä`c¥zåægÀ,mí­ÿ²cZçÊQ" Œ~nAÏ äù¨á\o ¥²"FÑ —EIF9*H|°ÎNG5êTP˜ÉðøËÔm¥(K¡Ì«0PDpŒ`tÅ;þ>Ùö¯ìÏÞy¾~<ÿ“ÌÆ7ìÝ·w¾3ß­zeçw޽Ԭ䴻±ó “—Î8 ŽCg¨WþóÿgÜX5šÞâO6Ukœ—|ƒ’ųÕGzôê(ÍæðEÅÇ—OÜÂánAó€ýâ¨Pß{Ð:Tð€Éýý“ý™þƒÿ<¼ÿö·uÝž¼õ¯L¢€<Ïþ?±ÿ²³?Ðç—ŸþÖמµbóÁ÷·ð¬W6;Õ\:‘0VV!ÜW¢Q@sgàË»• ±`ód‘çï–f$àt©§ð¶£so-¼Ö{¢• :ùª2Áô (ÌåðÓ-𵄋ö4)ncº(È€UÁèæ¤—Á7SÙ¥¬ÖRIn ÜåÕÈ!Ënß>Ý+Ò( 1‡Ï-½Ä2i¬épL^ç-&ÒJå‹dàž¹éÐNÿ„O¶}«û3÷žoŸ?äó1û7mÝïŒ÷ë^™ExݯÃmeuKYçÓlc‚ßÏ !“p˜Ic"€IÚ '“[^“O¸ºfÉ„^Nó>âS9幯öƒé”Pÿî«ÿ>¿ùÆøGu_ùõÿÈ‹þ5ÞQ@ü#º¯üúÿäEÿ?áÕç×ÿ"/ø×yEpðŽê¿óëÿ‘üjk]3]Ó&7VºtSN¨ê‰-¢’ÊW$Œž3žœãu®ÚŠàãÆpÜÏs‡44ž}¾t«tCI´aw¹8 ô¬ù|;âk¹´¸ßDÒìlì%y;)Æ>d`@] ulþué”P‚üpÿ®‘ÿ\ÿBQñÃþBºGýpýQ@îßñô?ëŒú Ñ+2ªìPÎŽY‚òp}hoøúõÆ?ýhõ–ÿõóþŒZÁñ 7ww–6pL+G,¦Ñ/§µ(<Ï:5Ýòïa7™ŸàŸeâ©n4éuym ¢KèɘÚ-ÏšDd![˜”ºÌcmt÷úm†©Á¨Y[]­¼GqÈ¡°FpAçþu'Øí~Ýöß³Cö¿/Éóö3fs·w]¹ç3@‡ˆ|C¨jk¤ýžÎÒí<ñ<·1·bÛº°%aȸÛ3ý¬Œl6µFóUðý…Ãé·Wí`ÑÈŸ9„Ë4_MÀÁŒƒÖ·m4}2ÂD’ÏN³¶tŒÂ …P¶â Âî$ã¦Njqgj-bµЋx¶yqa0: ¤=01@#ø“W}zÚô¯Ù šÙ¬ã³wó#K´[C$¬WöI+¦8Ȉ• IšÔ>"ÔÒþ}1äÓ–âËÎ’{©U£†D r1¸˜²..K°§vFÚmƒ£#Y[2²ÈŒ¦% ¬‡t€ñÑ-êzÓGÓ#µ·µM:Ímí¤ABDà’F0­’NG<šä¼%â]Vði6²Ûy–Ÿf·‚[©d]ï1´IËn/¹˜îÁ@‡»oà­vûn}lÿïëÿñº‚6ÂÞxç‚ÊÚ)£€[¤‰«,@äF(=ºUªfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>ŠfÛŸ[?ûúÿün·>¶÷õÿøÝ>Š`ó„Ñ$žF$,3ŒHÂ3t*?»Ž½éôÃÿv¿ïIÿ¢žŸ@ ñÃþBºGýpýQGÇù éõÁÿô!E{»ÇÐÿ®1ÿè+Cÿ¬·ÿ¯˜ôbÐßñô?ëŒú Ðÿë-ÿëæý´KXÖ-t;!wv³4fEˆc.Řá@QÉÉÀãÖ©éþ'·Ô¯£´ƒNÕÒGÎ}>H $³÷ç æé÷Z•¥„‘y’.£m3Á@D3I€× äÖÝ­¬°Í½ü°¡q"žªGc@º–²l/­¬âÓ¯/®.#’UKcÚ¨P1&GQÖE階èóZ5ÛjÐ[mYYæD Œ±°l•½Œa€9aÆ “KÄzº¦©§Ý/KÔá·‚xÚßPrªÚ"vüƒïUmÂWZ~½ ýíÄ7¾Dn«<™2³˜-bó9Îùç’pã““€ ÛýnÃN• štk–h€·GS&Ù%X•ö“»˜dý{ñO¼Õml.¡†íü”–9$ÈBÄ»%KÃm,Àz#Ÿá®JÓÁº®›a`N"Csay$ϸº< n±¼eb$>rw*3¸tzÖ‘.´ð[½ÃÃd«#ÈйY|ÜŒŽÂîgädt4;ëvú]¶¡¨Nšl7 ¤-ó¬,¬Ë»cdðÀg#ØÔÇR°[ij7¶ÂéÙ‘`2®ö`¡ˆ œ’•±½gê6zµö‰i’x»î(.$·Žc´†U•AxÔ1 !vžÖ.“àÛ­?HšÕ™¸7¶³¦s$Þ@ŽÜ†"'`¼€_<šé"Öì.5EÓíçIæ+1f‰Õ–6‰£WFÁá³*ñõÎ;²MvÖ+[ÉZ9·ÚÜ­«ÂÞÒ±QŽvüþdd@Æí¸8Èм9§jšl÷ÇÉÓô¶ÓVH·fPÑv$ #|œí$á›ww*Ïâ‹=Wjm†WËÆA‘¦Ëpýt -yj—Kj×0­ÃclEÀsÄ`uä#Ÿøz52K[{¤ÔlÚÞæA ‰Ô¤®ITç Ù`sÁ¬ÍOÃÚwÚÔ®ÐÇöý%tèæÙºH¹˜¹íòèp%yÆeËá¹t×!³ŠââI ¬÷—¼A‘q‘òg\F …ÕQþPq³,Ðßø‡L°Pßw ·Ïs=¬R+L¨«¸™ÈàŒg‘ëF§â3IÓ.oî.á1A²Isùmµ•A#,„Ç÷ˆMsÚ§…u;ý6çLG³[q%íÄ™[{½ÂN¡6áUMÁùƒ1;Ê7p]øWSud{?³Ée©C¦VÞÏw"È7.Ü*©d3ÁÀè:ñ“¼—3ê6pZ¬‹ÜKsŽBѬƒiÝÝ[ q‚ ²u+¼K3{l.™*ïf €¹É!YXû{×?¬[k“ëpÅc-ÌÌàÛ=Ë¢*¼VÊÇÌ’HkrÛÈ`rÅA§x2]7K–Ñ$¶’cw§¸¸ÚUž+e·71H@Éw^Mv4QEQEQEQEQEQEQEQEQE0ÿÇݯûÒè§§Óü}Úÿ½'þŠz}x/Çù éõÁÿô!E?ä+¤×ÿÐ…îíÿCþ¸Çÿ ­þ²ßþ¾aÿÑ‹CÇÐÿ®1ÿè+Cÿ¬·ÿ¯˜ôbÐè§"<‡ŒÇ®f’pmbón“åMÒ|£sª2{’@¤@ EC-å¬7PZËs w¼˜Ày6Œ¶ÑÔàrqÒŸÑN…á‘$PÌ…‘”•aÇpAЃ@¢Š†{Ë[\ý¢æqÌ|Ç „\nn„ddô5Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ ?ñ÷kþôŸú)éôÃÿv¿ïIÿ¢žŸ@ ñÃþBºGýpýQGÇù éõÁÿô!E{»ÇÐÿ®1ÿè+Cÿ¬·ÿ¯˜ôbÐßñô?ëŒú Ðÿë-ÿëæý´:2¤7 Ää’xp®WÅ—pËc§¤7¹:­ŽåG#í ×ø­Ëý6ÃT`Ô,­®áVÞ#¸‰dPØ#8 ó‚:¥…|;oÒ[™gŠÚK7ÞwÞLò‰0ê‰û£2ê|¿›¯£Ñ@h²j†[{y?¶šæM.F¾ŽIfD"[a,‘evŽØÈF,g,Ôˈ5WµŠæA«É©C¤ê–ðMw)óeߌœ1ŒðX–, 12'‰k¦ØYOq=¥•µ¼×-¾y"‰Q¥l“– |Ç$õõ5j€9+ëo‰µ[¦?eŽâòÊRÇ2Ë*0Š&-ò2£™NÓÂoÉù«CÂqÝÇ¥Ê.nnnÏ&¸·’ µxÄ®òãvþ\çÐmÛ[´PEPEPEPEPEPEPEPEPEPEPEPEPEPü}Úÿ½'þŠz}0ÿÇݯûÒ觧Ђüpÿ®‘ÿ\ÿBQñÃþBºGýpýQ@îßñô?ëŒú ÓŠ« :#¯uu àx¦·ü}úãþ‚´¯"D…äuEYŽ ò-¿çÎÏÿ“ü(ò-¿çÎÏÿ“ü+^ñJh÷v0FÚfÛ¸æO}¨}š1å”Cll±ßÓºjůŠt«‰£¶7p›£å¬‚ ÒDŒè¬ƒÍÚkoãyàrþE·üùÙÿà2…E·üùÙÿà2…ai^0ÓuM" áç’Ù'ha‚IÍ´0M«ûÝŒÁX ;OÞÛS7‹4D‘ckßœÆ&eòŸ1¡fRÎ1ò*²0bØFnEkùßóçgÿ€Éþyßóçgÿ€Éþžþ!Ò’KˆÚë w~í¾r)œ~ñƒ„&â…<*ñfŒ²,h™˜Æ$;-em¹fP¬Bü®]1a·â€5ü‹oùó³ÿÀdÿ <‹oùó³ÿÀdÿ ÏOéO%¼ku–Ÿvß!,T ?vÅÁ@i, ŽAsãm!tÍRÆG¼X-ê5X¤Q2€>éÛÈ€ägË'æÅt>E·üùÙÿà2…E·üùÙÿà2…D·ÖÆ(äi–!"U›÷mƒÓ*Ø û‘GÛìÿçîûø(_"Ûþ|ìÿð?Â"Ûþ|ìÿð?¢û}ŸüýÁÿo³ÿŸ¸?ïà  |‹oùó³ÿÀdÿ <‹oùó³ÿÀdÿ ‹íöó÷ýü}¾Ïþ~àÿ¿‚€%ò-¿çÎÏÿ“ü(ò-¿çÎÏÿ“ü*/·ÙÿÏÜ÷ðQöû?ùûƒþþ —ȶÿŸ;?üOð£È¶ÿŸ;?üOð¨¾ßgÿ?pßÁGÛìÿçîûø(_"Ûþ|ìÿð?Â"Ûþ|ìÿð?¢û}ŸüýÁÿo³ÿŸ¸?ïà  |‹oùó³ÿÀdÿ <‹oùó³ÿÀdÿ ‹íöó÷ýü}¾Ïþ~àÿ¿‚€%ò-¿çÎÏÿ“ü(ò-¿çÎÏÿ“ü*/·ÙÿÏÜ÷ðQöû?ùûƒþþ —ȶÿŸ;?üOð£È¶ÿŸ;?üOð¨¾ßgÿ?pßÁGÛìÿçîûø(_"Ûþ|ìÿð?Â"Ûþ|ìÿð?¢û}ŸüýÁÿo³ÿŸ¸?ïà  |‹oùó³ÿÀdÿ <‹oùó³ÿÀdÿ ‹íöó÷ýü}¾Ïþ~àÿ¿‚€%ò-¿çÎÏÿ“ü(ò-¿çÎÏÿ“ü*/·ÙÿÏÜ÷ðQöû?ùûƒþþ —ȶÿŸ;?üOð£È¶ÿŸ;?üOð¨¾ßgÿ?pßÁGÛìÿçîûø(tH¢mÑÛ[FØ#r@ŠFF zRÔQÝ[Í H§‰Üä…WñÉ©hÁ~8ÈWHÿ®ÿ¡ (øáÿ!]#þ¸?þ„( woøúõÆ?ýhõ–ÿõóþŒZþ>‡ýqÿAZýe¿ý|Ãÿ£€3u];P»Õ­5+ûx'‚  aslÓ‡Y g´ˆAPîzÕsáéd‚ìOx5Õý­ó²BUCB Ê€XðÆ^7wÇ;´P0þߦivnÿ ;ì90åfù¡?:î呵“?2¹jOý“LÖlVö‹Q²6ˆ°ÚìX74ÎÄ.ã•ß;m^0¡FIË¶Šæî|*×V7š|·¨öÎ×1[½°aæ4âsæäþñwŒm>F ’pÁx= B©s `ýŒì‚ÕbL/9 ªp‹•’É,rOOEr±x&Þ=^-A¤¶–EåfšÍdth’u3åœÊUŽ l#4ù|!æh–ºoÛ±äh³i>g“÷¼Å‰|ÌnãWÝÏ9ëÇ==[Ku ¼i$ù(ó QY±É “í“õ5/Úgÿžòßf¢¢€%ûLÿóÞOûìÑö™ÿ缟÷Ù¨¨  ~Ó?ü÷“þû4}¦ùï'ýöj*(_´Ïÿ=äÿ¾ÍiŸþ{Éÿ}šŠŠ—í3ÿÏy?ï³GÚgÿžòßf¢¢€%ûLÿóÞOûìÑö™ÿ缟÷Ù¨¨  ~Ó?ü÷“þû4}¦ùï'ýöj*(_´Ïÿ=äÿ¾ÍiŸþ{Éÿ}šŠŠ—í3ÿÏy?ï³GÚgÿžòßf¢¢€%ûLÿóÞOûìÑö™ÿ缟÷Ù¨¨  ~Ó?ü÷“þû4}¦ùï'ýöiòÊceUXñ±O1©þíLûCÿv?ûô¿á@Úgÿžòßf´Ïÿ=äÿ¾ÍhîÇÿ~—ü(ûCÿv?ûô¿á@Úgÿžòßf´Ïÿ=äÿ¾ÍhîÇÿ~—ü*+›ÉaµšUX‹"3 ĸÈJidºµ#°Ý!Ã1?òÊJ+³Kqá¿ Ï<,ÒY#¼ŽÅ™˜Û1$“Ô“[Tà¿?ä+¤×ÿÐ…|pÿ®‘ÿ\ÿBP»·ü}úãþ‚´?úËúù‡ÿF- ÿCþ¸Çÿ ­þ²ßþ¾aÿÑ‹@÷‹–î_ì[kBå§¿(Ñ­ì–¢Eó6 ‘‚ÀeAàr@®sûOV’Ò[{kï*{{›(šIL’ã:„ИþúîQ±T¹¤Pw`°ÛÞß鶤 ¡emw ¶ñÄK"†ÁÁœùÓ$ÑôÉmZÖM:ÍíÚ4„ÄÐ)BˆIEÆ1µI$ƒfwÁBŸ•³Çaã=fßÉ2Ú¤ÐÚéjæâE&Kd.wdää:e·ðTz-Í­ç•ö«hgòdEæ mŽ:2ç£ ðG5JóÃÚeåůÙ!ƒÎ²k6ÕdHÆÅ8áFrLö oTÖ5‹‹SoíŒsyúmÊ\[+¼f)î6Á7€S%ø¬FÕÎjÖªêqÜ@·O ¶—zµõœ@–iWd—±8 [ÀÁÝü# }L’ÖâÕôë6·¹Í±[kï'wÙ¡DžáÖß2¥è%³xUT2ç5湫_‹„¶¸†Öâ ›^@²2¹û|Ð1 æªÆ0Hä•% uÓè6WZ¼š…Êùþe²Û½¼¨ÌÃ`®CbYó‚‚*i4}2[Vµ“N³{v!14 P¢QqŒmRI ÏKB.5DešDQX–V}­árq8]ÌÄÀÏ­ª¥a¦¥„×Ò‰æ™ïnMĆ]¿)بvò…E9>¤ÕÚ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š–ãý`ÿq?ô\7…./ZûO’æy™59®ÕžååûF _¼do–Ý¿yþ®=Ëó‘Ÿ‘sÚ^\Á ʲÏlcC†p6ŠÍµMÊ{‰íO·šå·Ï$A¥l“–#ï“×ÔЕK¬qÏ#l#Î\#žj—Ûìÿçîûø*­úh𤠠º}Ü*ÛÄw$PØ#89çþtn}fíåxç³gT%WrqÀ¬}in>éÓÏ#Ë4šTNò;fc$’z’iŸðx3þ€úþCþ¡<öéR[[Kl‘¤8â”pÐvÅTðüŠžÿ¯¿ô•«v°¼ÿ"§…ÿëÂ/ý%jÝ øáÿ!]#þ¸?þ„(£ã‡ü…túàÿú¢€=Ý¿ãè×ÿô¡ÿÖ[ÿ×Ì?ú1hoøúõÆ?ýhõ–ÿõóþŒZ}$H¯¼³U\ð3ÜëT5JßI´†a¾W–ê eB»y’ULç' b}ñŽ3@è¬ÍKRº·¾¶°°´†âîxä˜ ç0Æ ù‚9Ý™ÆyÁcâk˜ÎÞEÄR,3D8WiÞÝpØåL‘°ã…ÍmQ\Þ¡ã+Ke–$rw8‘.ã–Ù¢U‚YC•dß´ù%rÿ2Tеeâ[K½VóOdš`½ûeâ ›ÉóN P:îxPs‡\€mQYï­éë¥ÛjBg{k¥V·òáwyC.á¶5‰Û“€2$ð RÔ¼W§ØØ]ÜD^v†Ñî¡ýÛ¤Wc2Žb»•ü¤œqÁÀíÍÇã-8ÈWHÿ®ÿ¡ (ÝÛþ>‡ýqÿAZýe¿ý|Ãÿ£†ÿ¡ÿ\cÿÐV‡ÿYoÿ_0ÿèÅ ¯og±³‘íôë‹ùl@Ñ©ç$»(Çã'‘ÅrÚ¤úæ¶,-†o-V=BÚw–K›vUT•Y‰ !=è v4PF±¤\_ÏÍâ[\ǶŤLr-ŽŒ­˜× Žxαð^£nˆ³êÐÊææ)nf6Ü܈îZä¡€‰‹É"Ÿ¾ FÞEv”P 7ß5fTÔaÍâ’AgûÉs4I$¿ç—ý!ÙÜýòpsw]ð¤ú’ê¬Û“Q½ŽPÈ¡ÕL" ÉbHmÑUù8gý¥ëh  ýWN–øZKmp]ZOçÂòFdMÅ3¹C)#lч8<ãžÖü Ú¼“Ju$óÞnn-D“)hL,7+(•gm€æ6ìã宯ŠäŸÁs–ÔU5m¶úŒrAs¶1É4ò¶Ó»!Àœ¨n@Á%[ -ÛŸ yú7Ø>Ñ âök½·þly’Hû$pÞ£ÌÈä|È­ÛÐQ@¬>–&%ÔPÛC” ¦Üï+kpe-¿*v·Ÿ˜`|´Gàù|»eÔQ¡ÓVlÂ[•aM „HwìEº À(c´äÕQ@¬tÿ±ÝêSù»þÛr'Û·1qã¯?êóž:ãµ]¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Šaÿ»_÷¤ÿÑOO¦øûµÿzOýôúð_ŽòÒ?ëƒÿèBŠ>8ÈWHÿ®ÿ¡ (ÝÛþ>‡ýqÿAZýe¿ý|Ãÿ£†ÿ¡ÿ\cÿÐV‡ÿYoÿ_0ÿèÅ  úާe¤Z½Bæ;kpÁL’('¦MgØø¿ÃÚìvv½­ÍÌ™ÙO¹›'è'ÐQxºÚ{»:+hdšOíKGÙ–;VUf8€Ÿ@ ­ë;[ˆî7¼ª„|–BÝ4GQÖ¬´¹à‚çí-4êïvö²ÎÅT¨cˆÕ°uëëV­®à¼ŒÉnþd\m±ÁPÀ«te!‡##¨ê sÞ$Óç¹ÖôÛµÓõ»xm®#q§Þ y¡+“æÆJጞqÇJÈÒ<ruˆ¿¶ìm®-cÕÂíò$"ÉîÆ]ÐË…+°–€;‹«¸,¡Ynb4‘Ä ùÂ(ãÕ˜ƪê:Õ–—<\ý¥¦]ãŽÞÖYت• q¶.½}k‹‡ÃºËA`o´ç¹ÔV}:i/žéwEb6"wns½$“oÜ;·_º}[E:§ˆ´éåûJÚÁir%½ÓÀÁÙá*2Œ¬AþÜsÚ€-\øƒM·ò±,×>lbdû´—?#}Ö>R¶°pOÁ¨çñ6‘o:D÷.á K6($’%‰ÉÛ#HªQTíc– `Ӛű²Öôè ì÷k«ÒͳÃÚÏ“q`~P¹”cb¿Ý?/@sï4]nû]Ø^M¨\è¶ÖÍøÎ0Ø&ð…”׉qö»ÄXî~Ñ*ɱI™fuåI*ò¢9É$m•ƒøFÞ;3W3µ¼-:9dT[@¬ŽŠ¬¨I¢‹—g9`Àm¼Eg=†¥y4W6‘é¬Ët.#Ã!XÖFàgpºŒƒŒ®AÒ¸ñŒ©wö.ú ,Ö'¸IÞ„k!p§{ʆSøXòÀu MÃÏ“ª[jÍçRF{”óÚN$‰‡™…'!3¨]ÛT¢©iþ¾’ê}CT¾š=A¼¯*xngŒÆ%Áh•VfM‚< nå˜f?Z\ɶËO¾»Ù#‚XÄj³»B³…]î¤)·e‚”Œç‘øÊÒæM¶Z}õÜnÉÆ#UÚœ*ïu ùM»,|¤g8};Âvg –ä¬j‰]”…Å¿ÙÕ:dªÇ€3ódIç&›á; .;D‚[–³¤é½”å–Ø[ à6 ÿ½íÅÞ,Ó®uk;Þ¦úžÎVxñ:.MÞbŒå‘FTŒçšçÄVv—‰4W"ÞÉXÜݬ{£‰„bR‡lì!³·o gqÛU¬¼!e§µŸÙ®ï-<¦D,„4‰‡Ì9\î1,€Bà’l0³sáÛ;»‹Çš[“oz¬.mM±ÊÆ1sŒ6v¸Ý·€q¸n  Òx²y£¶¸Òõ¯¤‘cKM‘¼‡zHÈÙG*ù2 –àŒ¶Õùª;ŸéÖ–sÝM ÌqGvöHÒùq,³#8eVvUÀ–ÜH [*-Aá¸Rþ û›ëËËÈdWMå‚B¤¨¨B"®ÑçHzg'’@žþ·ûAÍÌEw-ä7T¼RHÒÀe*F%uÁSÁõÐ-¼Mk~Äéö·—ùa–h£Ú1*ÇóUŠ2Xù€,ŠÌÒ|c%Õ‹ÜÙL×·vVÓGi 2<‚f;Y¤Û·l,À1Rä–;FÕ¶‡ù¹‚æñPáž1dyÄŒOÎͱT`±^cwÍYÖÞ ´´‚ÙbÔ/„ö°C½É1—‰b…ÀÙ´“:©ãï Ô7,Êó x<û¦.Ûd"H\îÁ(Ñ8!wêÆHÚÔõ}'M¸Ô.‹ {t2HTd…N+1|'`¶z·›rF£hmn²îl´®Î8ÀbÓÈOz`1Qx÷þD-sþ¼äþT/ü%ÿÐÄø&¸ÿâ*•®­•£[Ûé^(@×2\þƘœ¼¦V^cÆÒX¯LàõÏ5×ÜÿÇÔßï·óªw¬ÉapÊHaAää´Éí4¹â‘4Ï̶ðkHåÑæÛm +”]±ÃäN\±ùG<œé\xÆÒÒ/6çJסr¦ù4‹…˜…Q’½I R@®šà¹”@ë\dž•` 6«dQç¥'ü&¶?ô ×?ðS?ÿGü&¶?ô ×?ðS?ÿZ”P_ü&¶?ô ×?ðS?ÿGü&¶?ô ×?ðS?ÿZ”P_ü&¶?ô ×?ðS?ÿGü&¶?ô ×?ðS?ÿZ”P_ü&¶?ô ×?ðS?ÿGü&¶?ô ×?ðS?ÿZ”P_ü&¶?ô ×?ðS?ÿGü&¶?ô ×?ðS?ÿZ”P_ü&¶?ô ×?ðS?ÿGü&¶?ô ×?ðS?ÿZ”P_ü&¶?ô ×?ðS?ÿGü&¶?ô ×?ðS?ÿZ”P˜%3½„ÞT± C8IWk€ar2:ƒƒÐò;àÔôëùZ}þˆjmx/Çù éõÁÿô!E?ä+¤×ÿÐ…îíÿCþ¸Çÿ ­þ²ßþ¾aÿÑ‹CÇÐÿ®1ÿè+Cÿ¬·ÿ¯˜ôbÐè¦K4P(i¥HÔœeØŸÆ¢[û7`«w18H &€,QL3D³¤D:³¬e†æP@$à\ýG­Mè^E ÈYIVw}4ú(¢€ (¦C4WG<$°È¡ÒD`ÊÊFAuP袊(¢Š(¢Š*–¯¦C­iZmúAr†92=pH wÁúµ Ñ\AðH’Ã"‡Iƒ+)ÔL–¦Ö+¡s ·—g—(q±÷¡ÜH×#—/ƒ¼?4$±êò;rYõ›’Oã¾™ÿO‡?熩ÿƒ‹Ÿþ.·h  /øB|9ÿ<5Oü\ÿñtäð_†ãš)~˨;E"Ê‚MRw]ÊÁ”•f à€y«nŠ_*ÏþxIÿúÔyVóÂOûûÿÖ¤¢€ʳÿžßßþµUŸüð“þþÿõ©( ò¬ÿ焟÷÷ÿ­G•gÿ<$ÿ¿¿ýjJ(|«?ùá'ýýÿëQåYÿÏ ?ïïÿZ’Š_*ÏþxIÿúÔyVóÂOûûÿÖ¤¢€ʳÿžßßþµUŸüð“þþÿõ©( ò¬ÿ焟÷÷ÿ­G•gÿ<$ÿ¿¿ýjJ(™Ä—ö¬,'=!qE0ÿÇݯûÒ觧Ђüpÿ®‘ÿ\ÿBQñÃþBºGýpýQ@îßñô?ëŒú Ðÿë-ÿëæý´7ü}úãþ‚´?úËúù‡ÿF-s^;†;Æ£I"“T³GGPU”Ì ‚PjþáíÇSK›MO·M²ÃlˆË”`p@Èà‘[#‡W2œ« ã~Ô†âv¤ ðAc@ö­!±ñ©K ËÚÇisµ½»ÌÁÝáePÁ¿8ÀÇ'‘œ+X58n´çˆj1‰/ga²ÆÑKu#’Ä#˜1Y”’0±ì“qÕÊø*=a ¹:½Í̳2ÆeYmÞ5IðÞhRîÛ†vòbàl¶)XK¨Û[i—WZ-èÚ²ºI"™L¬žZ]×Ìh¸@b)NŽGoEpº$:´ÓèñÞI«“.w‰/™Ð`ùŸÌ ·w™€FpĶï,`çXè[ø^ÂãÖ¢¸G‰4èÕnmðó‚QÐ(o'wîöýß—uz]ç×6ºÌp^ÜBÚ¹¸òõK˜ÀšftSâÔÎ6”fÄ`mqŒ†ÀÇCâ/µ}ºËÚ?dòåÿ~|Ï´æ?'8ãn<ßõŸºÎ7ö®‚ªß鶤 ¡emw ¶ñÄK"†ÁÁœùИ½Çˆ[@¶¼´mPË.޾aí3´û¬ð²«(ç”]ª¾gÊ\¶ÒÕ¯¬Úë6VÚ ÓWb’Omo‰¦”ù&Å¥R7–ûAÀ“ïg>Zô(ˆžÓT³¼¹[8µK¨ÖîKXá{É€’ÜÙóŽÒg8çrœ(l µ¡áU»—MÔ,¯æ¼’#'ú<¯Å»˜Y8210q/W,8# Rºz(Í4øõ;'Ã&Ò RÜÛZ[ –Hî¤2ô„1îÚ…P1Ñ‹†U•Zf•g©Dµ[m\£±û|WhØGK›cÁ÷B¬bRvrgÏ^Er¾ XH.N¯ss,̱™V[wR|7š»¶á¼ X¸-ŽªŠ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(‡þ>íÞ“ÿE=>˜ãî×ýé?ôSÓèÁ~8ÈWHÿ®ÿ¡ (øáÿ!]#þ¸?þ„( woøúõÆ?ýiÅU†׺º†ð SANE-umax backend
SANE-logo
UMAX-logo

SANE-umax backend





Used System:
CPU AMD K6-III/400
RAM 128MB
SCSI-Controller NCR/Symbios logic 53C810
Scanner UMAX Supervista S12

RGB scan 24 bits/pixel
Resolution/dpi Size(h x v)/cm size/MB time/min:sec remark
      0:13 calibration
100 21.6 x 29.7 2.8 0:30  
200 21.6 x 29.7 11.3 0:30  
300 21.6 x 29.7 25.5 0:35  
400 21.6 x 29.7 45.5 1:00 some backtracks
>=500 21.6 x 29.7   too long not usable
500 9.0 x 13.0 12.9 0:30  
600 9.0 x 13.0 18.6 0:30  
700 9.0 x 13.0 25.4 0:55  
1200 9.0 x 13.0 74.4 5:20 lots of backtracks

Grayscale scan 8 bits/pixel
Resolution/dpi Size(h x v)/cm size/MB time/min:sec remark
      0:10 calibration
100 21.6 x 29.7 1.0 0:25  
200 21.6 x 29.7 3.7 0:30  
300 21.6 x 29.7 8.5 0:30  
400 21.6 x 29.7 15.0 0:30  
500 21.6 x 29.7 23.7 0:35  
600 21.6 x 29.7 34.1 0:45 some backtracks
700 21.6 x 29.7 46.4 0:50 some backtracks
800 21.6 x 29.7 60.6 1:20 some backtracks
900 21.6 x 29.7 76.8 1:35 some backtracks
1000 21.6 x 29.7 94.8 1:40 some backtracks
1100 21.6 x 29.7 114.7 1:40 some backtracks
1200 21.6 x 29.7 136.5 1:40 some backtracks

Lineart scan 1 bit/pixel
Resolution/dpi Size(h x v)/cm size/MB time/min:sec remark
      0:07 calibration
100 21.6 x 29.7 0.122 0:20  
1200 21.6 x 29.7 17.0 0:40  



This page has been changed on 12th. february 2001


Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-doc.html0000664000175000017500000000426112112021330016254 00000000000000 SANE-umax backend
SANE-logo
UMAX-logo

SANE-umax backend






Author: Oliver Rauch
sane-backends-1.0.27/doc/umax/sane-umax-astra-doc.html0000664000175000017500000002005712112021330017365 00000000000000 SANE-umax - UMAX Astra scanners
SANE-logo
UMAX-logo

UMAX Astra scanners




UMAX scanners
 Astra series:
Name
SCSI-ID
Versions
UTA
ADF
B/W
Gray
Color
Bits/pixel
Resolution
Astra 600S
Astra 600S
all
UTA-2a
 
ok
ok
ok
1,8,24
300 x 600
Astra 610S
Astra 610S
all
--
 
ok
ok
ok
1,8,24
300 x 600
Astra 1200S
Astra 1200S
all but 2.9 *
UTA-2a
 
ok
ok
ok
1,8,10,24,30
600 x 1200
Astra 1220S
Astra 1220S
all
UTA-3a
 
ok
ok
ok
1,8,12,24,36
600 x 1200
Astra 2100S
Astra 2100S
all
UTC-2100
 
ok
ok
ok
1,8,12,24,36
600 x 1200
Astra 2200
Astra 2200
all (2.1) **
incl
 
ok
ok
ok
1,8,12,24,36
600 x 1200
Astra 2400S
Astra 2400S
all (1.1)
UTA-2400
X
ok
ok
ok
1,8,12,24,36
600 x 2400
Astra 6400
Astra 6400
? ***
X
 
?
?
?
1,8,14,24,42
600 x 1200
Astra 6450
Astra 6450
? ***
incl
 
?
?
?
1,8,14,24,42
600 x 1200
Astra MX3
Astra 2200
? **
UTC-2100?
 
ok
ok
ok
1,8,12,24,36
600 x 1200

* Astra 1200S-C with external power supply and Firmware Version 2.9 could make problems.
** Astra 2200 and MX3 are supported via SCSI. Connection via the USB bus not tested.
*** Astra 6400 and 6450 are firewire scanners: not tested.

UTA = Umax Transparancy Adapter, ADF = Automatic Document Feeder
(X = supported by scanner, incl = is included)



This page has been changed on 16th. december 2001

Author: Oliver Rauch
sane-backends-1.0.27/doc/Makefile.in0000664000175000017500000011320513110564733014041 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_API_PS_TRUE@am__append_1 = sane.ps @WITH_API_PDF_TRUE@am__append_2 = sane.pdf @WITH_API_HTML_TRUE@am__append_3 = sane-html subdir = doc DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(srcdir)/doxygen-sanei.conf.in \ $(srcdir)/doxygen-genesys.conf.in $(dist_doc_DATA) \ $(nobase_dist_doc_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = doxygen-sanei.conf doxygen-genesys.conf CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man7dir)" \ "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docdir)" \ "$(DESTDIR)$(docdir)" "$(DESTDIR)$(docdir)" man7dir = $(mandir)/man7 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man1_MANS) $(man7_MANS) $(man8_MANS) DATA = $(dist_doc_DATA) $(doc_DATA) $(nobase_dist_doc_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ man1_MANS = scanimage.1 sane-config.1 sane-find-scanner.1 gamma4scanimage.1 EXTRA_DIST = scanimage.man sane-config.man sane-find-scanner.man \ gamma4scanimage.man sane-abaton.man sane-agfafocus.man \ sane-apple.man sane-as6e.man sane-dll.man sane-dc25.man \ sane-dmc.man sane-epson.man sane-epson2.man sane-epsonds.man \ sane-hp.man sane-gphoto2.man sane-leo.man sane-lexmark.man \ sane-matsushita.man sane-microtek.man sane-microtek2.man \ sane-mustek.man sane-nec.man sane-net.man sane-pie.man \ sane-pieusb.man sane-pint.man sane-pnm.man sane-umax.man \ sane-qcam.man sane-scsi.man sane-artec.man sane-fujitsu.man \ sane-sharp.man sane-s9036.man sane-tamarack.man sane-kodak.man \ sane-kodakaio.man sane-ricoh.man sane-avision.man \ sane-plustek.man sane-st400.man sane-mustek_pp.man \ sane-dc210.man sane-v4l.man sane-snapscan.man sane-canon.man \ sane-coolscan.man sane-bh.man sane-dc240.man sane-umax_pp.man \ sane-umax1220u.man sane-sm3600.man sane-usb.man \ sane-mustek_usb.man sane-sceptre.man sane-canon_pp.man \ sane-canon630u.man sane-teco1.man sane-teco2.man \ sane-teco3.man sane-test.man sane-sp15c.man sane-coolscan2.man \ sane-hpsj5s.man sane-gt68xx.man sane-artec_eplus48u.man \ sane-ma1509.man sane-ibm.man sane-hp5400.man \ sane-plustek_pp.man sane-u12.man sane-niash.man \ sane-sm3840.man sane-genesys.man sane-hp4200.man \ sane-mustek_usb2.man sane-hp3500.man sane-pixma.man \ sane-stv680.man sane-hp5590.man sane-hpljm1005.man \ sane-cardscan.man sane-hp3900.man sane-epjitsu.man \ sane-hs2p.man sane-canon_dr.man sane-xerox_mfp.man \ sane-rts8891.man sane-coolscan3.man sane-kvs1025.man \ sane-kvs20xx.man sane-kvs40xx.man sane-p5.man \ sane-magicolor.man sane.man saned.man descriptions.txt \ releases.txt sane-logo2.jpg sane-logo.png sane.png \ $(DESC_FILES) descriptions/template.desc. $(DESC_EXT_FILES) \ descriptions-external/template.desc. $(API_SPEC_INPUTS) \ $(API_SPEC_TEX_FIGS) $(API_SPEC_HTML_ICONS) # Create a list of man pages for only backends that are compiled in so # that is all that gets installed. Also, build a complete list of all # backend man pages. This allows a user to optionally generate all # man pages in HTML form for things like posting to a web site. # # Backend man pages bypass standard automake man5_MANS because there is not # a man page for every supported backend. We could get rid of # custom install/uninstall if we required man pages for every backend. BACKEND_5MANS = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 \ sane-dll.5 sane-dc25.5 sane-dmc.5 sane-epson.5 sane-epson2.5 sane-epsonds.5 \ sane-hp.5 sane-gphoto2.5 sane-leo.5 sane-lexmark.5 \ sane-matsushita.5 sane-microtek.5 sane-microtek2.5 sane-mustek.5 \ sane-nec.5 sane-net.5 sane-pie.5 sane-pieusb.5 sane-pint.5 sane-pnm.5 \ sane-umax.5 sane-qcam.5 sane-scsi.5 sane-artec.5 sane-kodak.5 sane-kodakaio.5 \ sane-fujitsu.5 sane-sharp.5 sane-s9036.5 sane-tamarack.5 \ sane-ricoh.5 sane-avision.5 sane-plustek.5 sane-st400.5 \ sane-mustek_pp.5 sane-dc210.5 sane-v4l.5 sane-snapscan.5 \ sane-canon.5 sane-coolscan.5 sane-bh.5 sane-dc240.5 \ sane-umax_pp.5 sane-umax1220u.5 sane-sm3600.5 sane-usb.5 \ sane-mustek_usb.5 sane-sceptre.5 sane-canon_pp.5 sane-canon630u.5 \ sane-teco1.5 sane-teco2.5 sane-teco3.5 sane-test.5 sane-sp15c.5 \ sane-coolscan2.5 sane-hpsj5s.5 sane-gt68xx.5 sane-artec_eplus48u.5 \ sane-ma1509.5 sane-ibm.5 sane-hp5400.5 sane-plustek_pp.5 sane-u12.5 \ sane-niash.5 sane-sm3840.5 sane-genesys.5 sane-hp4200.5 \ sane-mustek_usb2.5 sane-hp3500.5 sane-pixma.5 sane-stv680.5 \ sane-hp5590.5 sane-hpljm1005.5 sane-cardscan.5 sane-hp3900.5 \ sane-epjitsu.5 sane-hs2p.5 sane-canon_dr.5 sane-xerox_mfp.5 \ sane-rts8891.5 sane-coolscan3.5 sane-kvs1025.5 sane-kvs20xx.5 \ sane-kvs40xx.5 sane-p5.5 sane-magicolor.5 man7_MANS = sane.7 man8_MANS = saned.8 MANPAGES = $(man1_MANS) $(BACKEND_5MANS) $(man7_MANS) $(man8_MANS) @CROSS_COMPILING_FALSE@HTML_PAGES = sane-backends.html sane-backends-external.html \ @CROSS_COMPILING_FALSE@ sane-mfgs.html sane-mfgs-external.html @CROSS_COMPILING_TRUE@HTML_PAGES = doc_DATA = $(HTML_PAGES) $(API_SPECS) dist_doc_DATA = backend-writing.txt nobase_dist_doc_DATA = $(BEDOCS) MAN2HTML = nroff -c -man |\ man2html -compress -topm 6 -botm 6 -nodepage -title $${page} \ -cgiurl '$$title.$$section.html'|\ sed 's,,

,' beman5dir = $(mandir)/man5 BEDOCS = canon/canon.changes canon/canon.install2700F.txt \ gt68xx/gt68xx.CHANGES gt68xx/gt68xx.TODO leo/leo.txt \ matsushita/matsushita.txt mustek/mustek.CHANGES \ mustek_usb/mustek_usb.CHANGES mustek_usb/mustek_usb.TODO \ mustek_usb2/mustek_usb2.CHANGES mustek_usb2/mustek_usb2.TODO \ niash/niash.TODO plustek/FAQ plustek/MakeModule.sh \ plustek/Makefile.kernel24 plustek/Makefile.kernel26 \ plustek/Plustek-PARPORT-TODO.txt \ plustek/Plustek-PARPORT.changes plustek/Plustek-PARPORT.txt \ plustek/Plustek-USB-TODO.txt plustek/Plustek-USB.changes \ plustek/Plustek-USB.txt sceptre/s1200.txt teco/teco1.txt \ teco/teco2.txt teco/teco3.txt u12/U12.changes u12/U12.todo \ umax/negative-types.txt umax/sane-logo.jpg \ umax/sane-umax-advanced-options-doc.html \ umax/sane-umax-advanced.jpg umax/sane-umax-astra-doc.html \ umax/sane-umax-config-doc.html umax/sane-umax-doc.html \ umax/sane-umax-histogram.jpg umax/sane-umax-mirage-doc.html \ umax/sane-umax-not-listed-doc.html \ umax/sane-umax-others-doc.html umax/sane-umax-parport-doc.html \ umax/sane-umax-powerlook-doc.html \ umax/sane-umax-scanner-clones-doc.html \ umax/sane-umax-speed-doc.html \ umax/sane-umax-standard-options-doc.html \ umax/sane-umax-standard.jpg umax/sane-umax-text.jpg \ umax/sane-umax-text2.jpg umax/sane-umax-text4.jpg \ umax/sane-umax-uc-doc.html umax/sane-umax-vista-doc.html \ umax/sane-umax.jpg umax/umax.BUGS umax/umax.CHANGES \ umax/umax.FAQ umax/umax.TODO DESC_FILES = descriptions/abaton.desc descriptions/agfafocus.desc \ descriptions/apple.desc descriptions/artec.desc \ descriptions/artec_eplus48u.desc descriptions/as6e.desc \ descriptions/avision.desc descriptions/bh.desc descriptions/canon630u.desc \ descriptions/canon.desc descriptions/canon_dr.desc \ descriptions/canon_pp.desc descriptions/cardscan.desc \ descriptions/coolscan2.desc descriptions/coolscan.desc \ descriptions/coolscan3.desc \ descriptions/dc210.desc descriptions/dc240.desc descriptions/dc25.desc \ descriptions/dell1600n_net.desc descriptions/dll.desc descriptions/dmc.desc \ descriptions/epjitsu.desc descriptions/epson2.desc descriptions/epson.desc \ descriptions/epsonds.desc \ descriptions/fujitsu.desc descriptions/genesys.desc \ descriptions/gphoto2.desc descriptions/gt68xx.desc descriptions/hp3500.desc \ descriptions/hp3900.desc descriptions/hp4200.desc descriptions/hp5400.desc \ descriptions/hp5590.desc descriptions/hp.desc descriptions/hpljm1005.desc \ descriptions/hpsj5s.desc descriptions/hs2p.desc descriptions/ibm.desc \ descriptions/kodak.desc descriptions/kodakaio.desc descriptions/kvs1025.desc \ descriptions/kvs20xx.desc descriptions/kvs40xx.desc \ descriptions/leo.desc descriptions/lexmark.desc descriptions/ma1509.desc \ descriptions/magicolor.desc \ descriptions/matsushita.desc descriptions/microtek2.desc \ descriptions/microtek.desc descriptions/mustek.desc \ descriptions/mustek_pp.desc descriptions/mustek_usb2.desc \ descriptions/mustek_usb.desc descriptions/nec.desc descriptions/net.desc \ descriptions/niash.desc descriptions/pie.desc descriptions/pieusb.desc descriptions/pint.desc \ descriptions/p5.desc descriptions/pixma.desc descriptions/plustek.desc \ descriptions/plustek_pp.desc descriptions/pnm.desc descriptions/qcam.desc \ descriptions/ricoh.desc descriptions/rts8891.desc descriptions/s9036.desc \ descriptions/sceptre.desc descriptions/sharp.desc descriptions/sm3600.desc \ descriptions/sm3840.desc descriptions/snapscan.desc descriptions/sp15c.desc \ descriptions/st400.desc descriptions/stv680.desc descriptions/tamarack.desc \ descriptions/teco1.desc descriptions/teco2.desc descriptions/teco3.desc \ descriptions/test.desc descriptions/u12.desc \ descriptions/umax1220u.desc descriptions/umax.desc \ descriptions/umax_pp.desc descriptions/unsupported.desc \ descriptions/v4l.desc descriptions/xerox_mfp.desc DESC_EXT_FILES = descriptions-external/brother2.desc \ descriptions-external/brother.desc \ descriptions-external/brother-mfc4600.desc \ descriptions-external/canon_mfp.desc \ descriptions-external/cs3200f.desc \ descriptions-external/epkowa.desc \ descriptions-external/geniusvp2.desc \ descriptions-external/hp3770.desc \ descriptions-external/hp8200.desc \ descriptions-external/hpaio.desc \ descriptions-external/hpoj.desc \ descriptions-external/kodak-twain.desc \ descriptions-external/lhii.desc \ descriptions-external/mustek_a3p1.desc \ descriptions-external/panamfs.desc \ descriptions-external/primascan.desc \ descriptions-external/primax.desc \ descriptions-external/samsung.desc \ descriptions-external/scanwit.desc \ descriptions-external/utsushi.desc \ descriptions-external/v4l2.desc \ descriptions-external/viceo.desc API_SPECS = $(am__append_1) $(am__append_2) $(am__append_3) API_SPEC_INPUTS = $(srcdir)/sane.tex $(srcdir)/net.tex API_SPEC_TEX_FIGS = figs/area.fig figs/flow.fig figs/hierarchy.fig \ figs/image-data.fig figs/xfer.fig API_SPEC_EPS_FIGS = figs/area.eps figs/flow.eps figs/hierarchy.eps \ figs/image-data.eps figs/xfer.eps API_SPEC_PDF_FIGS = figs/area.pdf figs/flow.pdf figs/hierarchy.pdf \ figs/image-data.pdf figs/xfer.pdf API_SPEC_HTML_ICONS = icons/contents.gif icons/index.gif \ icons/next.gif icons/next_gr.gif icons/previous.gif \ icons/previous_gr.gif icons/references.gif \ icons/references_gr.gif icons/up.gif icons/up_gr.gif am_TEXINPUTS = TEXINPUTS="$(builddir):$(srcdir):$$TEXINPUTS" all: all-am .SUFFIXES: .SUFFIXES: .eps .fig .pdf $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): doxygen-sanei.conf: $(top_builddir)/config.status $(srcdir)/doxygen-sanei.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ doxygen-genesys.conf: $(top_builddir)/config.status $(srcdir)/doxygen-genesys.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(man1_MANS) @$(NORMAL_INSTALL) @list1='$(man1_MANS)'; \ list2=''; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-man7: $(man7_MANS) @$(NORMAL_INSTALL) @list1='$(man7_MANS)'; \ list2=''; \ test -n "$(man7dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man7dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man7dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.7[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man7dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man7dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man7dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man7dir)" || exit $$?; }; \ done; } uninstall-man7: @$(NORMAL_UNINSTALL) @list='$(man7_MANS)'; test -n "$(man7dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man7dir)'; $(am__uninstall_files_from_dir) install-man8: $(man8_MANS) @$(NORMAL_INSTALL) @list1='$(man8_MANS)'; \ list2=''; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) install-dist_docDATA: $(dist_doc_DATA) @$(NORMAL_INSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-dist_docDATA: @$(NORMAL_UNINSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) install-nobase_dist_docDATA: $(nobase_dist_doc_DATA) @$(NORMAL_INSTALL) @list='$(nobase_dist_doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)/$$dir"; }; \ echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(docdir)/$$dir'"; \ $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(docdir)/$$dir" || exit $$?; }; \ done uninstall-nobase_dist_docDATA: @$(NORMAL_UNINSTALL) @list='$(nobase_dist_doc_DATA)'; test -n "$(docdir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man7dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(docdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: html-local info: info-am info-am: install-data-am: install-data-local install-dist_docDATA \ install-docDATA install-man install-nobase_dist_docDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-man7 install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_docDATA uninstall-docDATA uninstall-local \ uninstall-man uninstall-nobase_dist_docDATA uninstall-man: uninstall-man1 uninstall-man7 uninstall-man8 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distclean-local distdir dvi dvi-am html \ html-am html-local info info-am install install-am \ install-data install-data-am install-data-local \ install-dist_docDATA install-docDATA install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man1 install-man7 install-man8 \ install-nobase_dist_docDATA install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-dist_docDATA uninstall-docDATA \ uninstall-local uninstall-man uninstall-man1 uninstall-man7 \ uninstall-man8 uninstall-nobase_dist_docDATA all: bemans $(API_SPECS) html-pages %.1 %.5 %.7 %.8: %.man @echo "Generating manpage $@..."; @sed -e 's|@DATADIR@|$(datadir)|g' \ -e 's|@CONFIGDIR@|$(configdir)|g' \ -e 's|@DOCDIR@|$(docdir)|g' \ -e 's|@LIBDIR@|$(libdir)/sane|g' \ -e 's|@BINDIR@|$(bindir)|g' \ -e 's|@SBINDIR@|$(sbindir)|g' \ -e 's|@PACKAGEVERSION@|$(package_version)|g' $^ >$@ bemans: $(BACKEND_5MANS) install-beman5: $(BACKEND_5MANS) test -z "$(beman5dir)" || $(MKDIR_P) "$(DESTDIR)$(beman5dir)" @list="$(BACKEND_MANS_ENABLED) sane-dll.5 sane-scsi.5 sane-usb.5"; for man in $$list; do \ if test ! -r $${man}; then continue; fi; \ echo "installing $${man} in $(beman5dir)/$${man}..."; \ $(INSTALL_DATA) $${man} $(DESTDIR)$(beman5dir)/$${man} \ || exit 1; \ done install-data-local: install-beman5 uninstall-local: rm -rf $(DESTDIR)$(beman5dir)/sane-*.5 sane.ind: $(API_SPEC_INPUTS) @echo Generating index for $<... @touch sane.ind @$(am_TEXINPUTS) $(LATEX) $< /dev/null && \ $(MAKEINDEX) -q sane.idx && \ $(am_TEXINPUTS) $(LATEX) $< /dev/null .fig.eps: @test -d $(@D) || $(MKDIR_P) $(@D) $(FIG2DEV) -L eps $< $@ sane.dvi: $(API_SPEC_INPUTS) $(API_SPEC_EPS_FIGS) sane.ind @echo Generating $@ from $<... @$(am_TEXINPUTS) $(LATEX) $< /dev/null sane.ps: sane.dvi @echo Generating $@ from $<... @$(am_TEXINPUTS) $(DVIPS) -q $< -o $@ .fig.pdf: @test -d $(@D) || $(MKDIR_P) $(@D) $(FIG2DEV) -L pdf $< $@ sane.pdf: $(API_SPEC_INPUTS) $(API_SPEC_PDF_FIGS) sane.ind @echo Generating $@ from $<... @$(am_TEXINPUTS) $(PDFLATEX) $< >/dev/null sane-html: sane.dvi $(am_TEXINPUTS) $(DLH) $(srcdir)/sane.tex html-man: $(MANPAGES) @for page in $(MANPAGES); do \ echo "translating $${page} to $${page}.html..."; \ cat $${page} | $(MAN2HTML) > $${page}.html; \ done ../tools/sane-desc: cd ../tools ; $(MAKE) sane-desc sane-backends.html: $(DESC_FILES) ../tools/sane-desc @../tools/sane-desc -m html-backends-split -s ${srcdir}/descriptions \ -i "The following table summarizes the backends/drivers distributed \ with $(PACKAGE)-$(VERSION), and the hardware or software they \ support." -d 0 > sane-backends.html sane-backends-external.html: $(DESC_EXT_FILES) ../tools/sane-desc @../tools/sane-desc -m html-backends-split \ -s ${srcdir}/descriptions-external \ -i "The following table summarizes the backends/drivers that \ have not yet been included in the SANE distribution, and the \ hardware or software they support." \ -t "SANE: External Backends (Drivers)" -d 0 \ > sane-backends-external.html sane-mfgs.html: $(DESC_FILES) ../tools/sane-desc @../tools/sane-desc -m html-mfgs -s ${srcdir}/descriptions \ -i "The following table summarizes the devices supported \ by $(PACKAGE)-$(VERSION)." \ -d 0 > sane-mfgs.html sane-mfgs-external.html: $(DESC_EXT_FILES) ../tools/sane-desc @../tools/sane-desc -m html-mfgs -s ${srcdir}/descriptions-external \ -i "The following table summarizes the devices that \ are supported by external backends." \ -t "SANE: Devices Supported by External Backends" -d 0 \ > sane-mfgs-external.html descriptions.db: $(DESC_FILES) ../tools/sane-desc @../tools/sane-desc -m ascii -s ${srcdir}/descriptions \ > descriptions.db descriptions-external.db: $(DESC_EXT_FILES) ../tools/sane-desc @../tools/sane-desc -m ascii -s ${srcdir}/descriptions-external \ > descriptions-external.db html-pages: $(HTML_PAGES) html-local: html-pages html-man sane-html clean-local: rm -f *.toc *.aux *.log *.cp *.fn *.tp *.vr *.pg *.ky *.blg *.idx *.cb rm -f *.ilg rm -f $(API_SPEC_EPS_FIGS) $(API_SPEC_PDF_FIGS) -rmdir figs distclean-local: rm -f $(MANPAGES) rm -f *.lot *.lof *.ind rm -f sane.dvi sane.ps sane-backends.html sane-backends-external.html rm -f sane-mfgs.html sane-mfgs-external.html rm -f sane/*.html sane/*.gif rm -f doxygen-sanei.conf doxygen-genesys.conf -rm -rf sane sanei-html for manpage in $(MANPAGES) ; do \ rm -f $${manpage}.html ; \ done # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/doc/sane-hpljm1005.man0000664000175000017500000000214712617742237015047 00000000000000.TH sane\-hpljm1005 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hpljm1005 .SH NAME sane\-hpljm1005 \- SANE backend for Hewlett-Packard LaserJet M1005 MFP Scanner .SH DESCRIPTION The .B sane\-hpljm1005 library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Hewlett-Packard scanner: .PP .RS LaserJet M1005 .RE .PP If you own a scanner other than the ones listed above that works with this backend, please let us know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .IR /proc/bus/usb/devices , .I sane\-find\-scanner or syslog) to us. Even if the scanner's name is only slightly different from the models mentioned above, please let us know. .SH CONFIGURATION None required. .SH FILES .TP .I @LIBDIR@/libsane\-hpljm1005.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hpljm1005.so The shared library implementing this backend (present on systems that support dynamic loading). .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .SH AUTHOR Philippe R\['e]tornaz sane-backends-1.0.27/doc/sane-as6e.man0000664000175000017500000000210312112021330014223 00000000000000.TH sane\-as6e 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .SH NAME sane\-as6e \- SANE backend for using the Artec AS6E parallel port interface scanner. .SH DESCRIPTION The .B sane\-as6e library implements a SANE (Scanner Access Now Easy) backend that provides access to Artec AS6E flatbed scanner. .B It requires the as6edriver program in order to operate. The as6edriver program is .B not included with the SANE package. It can be found at .BR http://as6edriver.sourceforge.net. See the as6edriver documentation for technical information. .PP The .I as6edriver program must be in the path for executables ($PATH). Especially if you run .I saned (the SANE network scanning daemon), take care to setup the path for .I inetd or .I xinetd correctly or place the program in a directory that is in the path. .PP .SH FILES .B as6edriver \- driver program that controls the scanner. .SH SEE ALSO .BR sane (7), .BR as6edriver (5), .BR saned (8), .B http://as6edriver.sourceforge.net .SH AUTHOR Eugene S. Weiss .SH EMAIL-CONTACT yossarian@users.sourceforge.net sane-backends-1.0.27/doc/sane-pint.man0000664000175000017500000001045612112021330014351 00000000000000.TH sane\-pint 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-pint .SH NAME sane\-pint \- SANE backend for scanners that use the PINT device driver .SH DESCRIPTION The .B sane\-pint library implements a SANE (Scanner Access Now Easy) backend that provides generic access to hand-held and flatbed scanners using the PINT (PINT Is Not Twain) device driver. The PINT driver is being actively developed on the OpenBSD platform, and has been ported to a few other *nix-like operating systems. .PP PINT is designed to provide an .BR ioctl (2) interface to many different scanner types. However, this backend has only been tested with flatbed single-pass scanners, and more work will probably be required to get it to use other scanner types successfully. .PP If have successfully used the PINT driver with your scanner, but it does not work using this SANE backend, please let us know. To do this, send a mail with the relevant information for your scanner to .IR sane\-devel@lists.alioth.debian.org . Have a look at http://www.sane\-project.org/mailing\-lists.html concerning subscription to sane\-devel. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the UNIX path-name for the special device that corresponds to the scanner. The special device name must be a PINT device or a symlink to such a device. For example, under NetBSD or OpenBSD, such a device name could be .I /dev/ss0 or .IR /dev/scan0 . .SH CONFIGURATION The contents of the .IR pint.conf . file is a list of device names that correspond to PINT scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS /dev/scanner .br # this is a comment .br /dev/ss1 .RE .SH FILES .TP .I @CONFIGDIR@/pint.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-pint.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-pint.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_PINT If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH SEE ALSO sane(7) .SH AUTHOR Gordon Matzigkeit, adapted from existing backends written by David Mosberger. .SH BUGS There are minor roundoff errors when adjusting the ranges, since PINT uses units of 1/1200 of an inch, and SANE normally uses millimeters. Symptoms of these errors are skewed images. This should really be fixed (no pun intended) as soon as possible, but I just don't know/care enough about fixed-point representation and roundoff errors to do this correctly. Workaround: use inches as the scanning unit, and everything usually works fine. The PINT 0.5e interface does not provide a way to determine valid ranges for DPI, modes, and scan sizes. So, the SANE backend queries the PINT device, and dynamically discovers valid ranges by doing a binary search. This means that the driver takes longer to initialize than seems necessary. Resetting the scanner does not seem to work (at least not on my HP ScanJet 4p). For that reason, the driver sends a SCIOCRESTART, then gobbles up any remaining input until it hits EOF. Not all of the scanners have been identified (i.e. whether they are flatbed or handheld). X and Y resolutions are assumed to be the same. No testing has been done on three-pass or handheld scanners, or with Automatic Document Feeder support. sane-backends-1.0.27/doc/sane.png0000664000175000017500000002500112112021330013402 00000000000000‰PNG  IHDRZuOé…`PLTE¤'t{< êËÑ“}‚üôöüþü3 ôôôôÂÌÌ»¿¼,wBN‡"T¬£¥°,dâàà\G, ïëìœ$9-/lÍÍÍÊ3“$«8ÚÝ IDATxÚí]‹–Úº’å)Ë1F€áÿÿrê%©$›îäÎÜ™¹kwNNBÔÕÅöV½eVõ_\+øÏ¾ þÕÁeåÿn¿ññß\ü~¿[øï=À¢¾_?U]Ÿ¶›ÍkºÞÎc3îv‡ûp¿\ž°ØÂº®’Ån½~|àûíæõêڸؼءT×Ðâ~Áß…’_Ãí×-nޤúº ¬½šóù_ÜSt†«i‡Úö¤Ætö ùzH,¾\š£¾ïã›ÞžÁŸSSŸ®½’ ‹/—‹Gè|åI´ÅëõO rƒ‹ÏÃØìpñtY5´ø]OÇ÷ñxê5¾½Ïéä`q ‹Ïg'‹½_Yƒ‹} kA ‹'|êêíëåAðùì+\ oЮ.´øèjXÛw(ØàÚÔ€ÅtàÆ©&•°ø8 pëÂfpñ¶ܺ=Ü’±«éíùËŠ÷ý±÷ëu× Ïþ´Ýn&Æ ï*ÔÀàÅõWãáÍz¼jþ _kèôB÷ĺ¿`¨} áÈFà\‹ÿoè·ÚøLœ{âMéð[á¦<àÞ '䜽ÝΦFbt4nWÄ‹a‚oÀµk 3þÞáæŠd65Þ뮆·'kßõ¶E˜?¨ q¹;ǵuZÛ×GXûîp|àN5¸ö6$¹¶Åµ-v5R¨·ÀÍS[[ó!&ǵöbšph™ö®õpC>Thˆ›žßÛ¡½\ b6°Ç8ÌÄ»kˆ½Ýœ¬íº‹©`í»E®†\;Õvóò/$Û`ˆ?]mÌjZÕ@ßæˆÄlÖëõ󃋻ٴ Âml‘kwX[¾°®i–kb-2ÍYÞÏç3€s µmXÛ£AyZÔÕãZ#kÇq`-è`ù¾!ÕM¿¾L¸‹>,Ý>-Rx‚½1¢°Y­h-òm¨|U䤯ù5dcÔlˆ¤ÃÉ¿µ°d ß³lŠÞÆó¿Áþ@‘–þîà­lÉæ9Dÿ†@s÷kw?¸½ÀÇËÊ (w/âœÐèýä‡ök r;þIˆÑfƒ‚¿±\ÓÔ€,YC燑ä>[ÞoAϦj•\ðkûx±Â ë‹tut[Y.é‹w ~ú„ö¡û~O`ßG–k{ãY*Rº‰‚Q,p[“¾,÷Àïª rë$¡X.€ûœ Ë}|žþ¤ÏäI*íƒvV,ɽ£¾6wË­'%¹­›‰L€kö(÷ÊÇ‘!è¦=ÉÅ}pìy úH®E3ÙÝ„uãD*¸3.ôÝäžð=Úí¶p ØÛù9´¤ïNÔ½wã3d ׃e* £_d)>´[O¸sv³Ý€`’ ›üÖ Ý™ä,×Ý äZ¶ÕžnXÝ’û:‚Kè¡€&ÀÝpúˆ`¾eˆ­kX[Øh£CƒGêÐ’­¢Üzêžt™i2q3_fòéáuÝÔ8y±ƒ{W¸)üiªÿ­öì?L¬5ï··r5áß\¸øÿîëô'Ž8Äû( ’°™ìÍì_ï^Œ$[ùê´=±1ÛL{±é°ãínÇÛ¸k︉f®’=AflŠÆ/Ûó>fK†&ý$¦×xÙm¸SDê}tÓ]|E“Loç›VÄ6¹XŽ·Á§œ‚E練µE±ÁôÂv&„Vg• ¯kšw…ʺY3Á 7AYPw¸fb¤-XDÔ–Äzå&Øœ±Û4AÙ‡ø ´}uƒ¡ÍFbÉ_¢¶hi1>E±U xJÚšvèE*lãà~6Éýà&lÇ‘MBå1ŠÌ@ çƒðBT…>¸k­H ÷¬jAî‹ävÃ@¤mm}7‹ðº#k ÷ËÙàÔNtÏNƒßlÅ«]Ûá¦@؉X;NÓÈb}æÒüûèD¬’Æ7pr¾ ÜÌp¾E±&üùÒµ‹­’;€Iw¼Ð¥‰÷9Ñ=;uÓÄ‚º6iKæñà@êüÃÐ’XŸûöA<;¸v¦zJ| âEtí›+ùJãÃv;6îA*Š­¶ qÛ‚¯”½ô§Ö=Öì*éžÀšï1UDmoÏÉŽa—‘K; TLÍ¥‹`‘\pÏÚÝ3Ø ®!¿N{Áù‘ Æázà%VQ,ê׆hó7¢nÜ·yÇŽànÉù0² ¶Älcë´¶îÆwGþêÇ}Ï!) E‡†®7ƒk$º`ÝÄ¢Ð;Û„gkW‹A`ŽGÖöèÆàñˆœ0BC±Æ·¯, `sD,¬jWϽðÖa8J¡KEu™ƒMg,à=Û ­m½`‚Ûí-;_Ú¼“q²Ë`_a˜4±ÌþxxcChƒ÷Œ ‚Ä6+€‰öê–ñ6ŸÞ‰¶o@ª¶g¹ý謘.ãƒT¼gåNbñ ÓJhÃÚ¢Ô öHQE6—V"›G7|Bd÷LLms 6–·‹%©Z, 4‘PÜ]ï`¹†S ÷Œ÷-»1^BÄ­„a(–ã%{$51‹ ©' o×h¹®­‹b[ ¸:ŽÃF —€4‡xË|Çbå–1¦ôÓz:ûËur6ˆÝ8L­QFtíet­„a"–ß{?µ õütg+‹–ˇ qcš`»(ºG¬„ žÄÂþÛ++ö6ÄlҊδM]¥Ø­iÓ%ìL£8Ì Â Ó†oc{‹Ië@Õ”YtZ^®P‚á 7®‹/úlqÔü‡…vÿñ­Ç ÏÿÉ·ùòª~ùw¿ôê [ÐôŒÑ¤&ÇQ¾É¾mß³—( wå4¤âãæÜİ­k‡ÆïM ZVJˆ)8C@ —™Ø`”ê„kš|ÔÖªBì‹a0¹¶òwé07–@•ìÒ–$u-íL*EH•ÂA7øŽueϘ@Õí(ÞØ‘È›@Ũ-䧸OSi}3´™¶ÏR[ÛGt|]Q\¸šVÔM9lÛº++ O­-+.m»;黢ä4ik‹ûŽ2šI‡fO3ädòoÒ5êûù<2ü½‘¢”\œ1;?)e“¶@…X¥¡¸ ̘ 7 °¬­_ÖöÿRûö‹¶{ 4W ”¶þÑQÝ~»ú¾ä¹”zÚ¤­ðö žæ€ÚÖ¨¯@ Lè[ïÞ³Ë!¼‘G­­·=Ø\7™02 §íÉðaÚn£¶°Á@]ËÀrF±wj“A”ŸœxœïL`x\¼€-†ÿ`6 #TŲ™™4Y†DÒ•Õ‚ºZÛÝ.1BŽû˜Þ¸Ÿ°<{ùE[†·(BEm°ì†\ŒW7iŸÙ¡iš=ï± í£xÐÏ·¶¶a‹î[kŸï3³ Õ²º/8o¦”¶d àÇì>^'#fO-ØR›Ó–LíÓMC{.°Å]´=$l-¦NƵƒÓ6Tz/ë‹Â`·Ó~ß;Ô`ô-ÙZÎ39fOû ì-ÀÏê†-FÑõJÖ\¢-¥­¢­hKº<(ƒKÅ;äö*ó ¸Ûœk‡ÜÐÂ?pF,àræß”ûêz«° n Õí Þfö‹´e]1uBc¡Óà•çõí7x©í iØ+ÀÏÞEZ Û“#_ ø’ÙP«mIݲڂ!"¶ «Ô“˜³¨¦t_o.3Je¡î#±–ªœ2Ô±ü‚êšbÄðú@Qw¡íAr&Øeç#Ì´•h¨ Ã‘Æl¥v” %¯àZÜg YδžòÖ,{2¸1¾+ˆ€ìß½òeŠ´÷»x×q©nA[÷ž(Št8ò%ÿïÝÀßPÙËKû‰4 m… Vü¨;œ6¯„«/4» Û]¾Çî'8“°µSÓTI[0¯ˆ l(•5fµÑ¾2¼öºÆª[Üa§xÉ>³âİ`=ˆcÐÁâ“Õí´¶Áë$Nh kk!9u.Øv½¬Ã˨¾c߀ÕUîvýØ­žO3ÓVÀµ!žéà‡ì3ÖÞ‚5ðíh2m#´Á;T¾5«ÎØÞho=fÓÁ{¼¬ç›TpI «X°~à›-šx½:zÏVœØÃÄf¯ˆ ~a†{4Œ™¶÷\[ÚK¶Í£ÁôíȬúö.¿‚Þ®Óõx ?ûDÚ† Gbg7„7–”½F]±j€¯sÒj3\sm-W(°z›´•Îì‚wz‡Â$ïý¾_šSÙ`ÿµŸ`¼p ÄÒ’º· YÌïÏÉ•èè ÓÚebƒVA[…mÜþâc‡6+(±·½Ž1B,â•3pÚ’›”_Û¾½ê¸–K2]0ÎÁpq¾bœ°Z-k›n>*š)*ºÆ~Wg(è †€î?ú³ŽTÕú2Õ²Õz£8®`i‚²‘ ¤íÞR_ï²ÀnÆ…b6ª Ê"G[&Ášp%K€à*Êòõ¢ˆ$f7פîù¬Ô=³ºÄÛƒäcÜЃ_Èë([­¾hKÖê(öÊ[QuE;duôCÍeØQVNàÕ†Z¢›äqÉ©Å6f„—’¶»€+cg-¶[.KL¨[Ñ2QìËdºóxÁ•ÃÈfïº.ÝÄ1¸yZ5{µÉ¢DdàµÁtÏgZv€•i[;øHá5¹žÆtÝsÜÅò%¾”âÛ¡¥þgàBC臩m]Û‚O–îÞÔºü‚F3”/ã«5 $Y¥±a]À~|[ˆ†©X;ù,Ãÿ*ô¾uóÿ¦ðU5¤XóŸ_µûGÛ›¶D÷Õ¿Tý­ Z-¼\ý™°Em½µ­$b±wZøMñ*ëÊ++™ÎÿÙíAF;{-¬6Á ‰°RÛ4Eý6ÔÁ®ÌÊ·“_*1ê"c«—ØäÚbÙ®•È1Ï ¤~;Ž:Ù¹·S‹·âÎhé*›²rLg‹Ä7¤:_´Å±4§jv–=Û)èŠn ety±¹“Ð}ÌË÷;ø£1ÕšÉSL± w6jFÅŸ¢¢3¹¤­.?Nz‰®X Kä‡1¹É2ˆñÉaM-ÎÄ™© ÚrùvE¡T›UrŽuXJÏ~ÒV*ùB®¹Â¨Ê·í)TÆyEâÜát#mÏR“À0h£Œî°i†áµÝÛ²j_$ë—R[ÿŽÚ†¡´LÛ=ñ (à ¸‰ ¥¶atµõ¤®ªäGm󢲩ʹpï mëVcËíP]lö¦ì:¸Wš« ³_A[]EÞR`4™Ä[¬1JÎÛrO•ñ9êTXLÈ×ìO©ñµÅ<÷zUayÔvœk‹÷—ÛÒ%l÷n©ï  M—n®mf äÚv­Ïú§SQÉÇ |Ÿ%¾ ÛX]‚ï“è ¶zpk^Çw˼õq›õºŸwI+óX±:iX¹ÁÜ®3ÞîJ› ¬òmmnä­]*„ryI[ëßÈ6 Ö–Ó4]Þ>§¬Úû[²`#¿AšzŠV½CØIÝÄ[»T÷ªëPhÛƒßj\ìí…ä'ïé46n2™žÂ®>Vš“²vª§E 혴ýÆ„TçŠX¡-ÜQŸê6’?Š­8¤ŽNJ(ɈEæ& ê·»ÛºB.wÙb×|-ï´#jëu—Ä´ƒíóÔç³IÛŒš]m®í+”ñ7±¬ ìínLµñCÒ–[f—Ì‚}©áWq§il±Î>‹Ñâ¦mfqzkCL9÷}qjÉ&Äڸƶ¶ÃľȄÚ}ë耓0%h9ß™oÈ·™=5MCbStIà}ÒH{æyw±….çÔh/®2m¿5 |Í>M3¡bm[ïÊvÙG·t¦Ákp7±£Cý²sîËÒ&“Ò],Z·—U ù0kª?öŸ¨¹µÝ·4(Ôz—mQßs¼vûi'—Ì­¢m0bÔhl“¶‡¨­ÅQVˆ±IÌ\±µYVTH]µÝ©<ÞwÒ‹¯Ë%çäÍìöä\êî©¢ î³XdZÆ6jKÊ^pc‚º*bÞïŸvÚ±SÚJɶ٬ùjœq‡$'wHüþ¼¤m*‰’¶+{¡:oËí¿ô"‘ºÍÔ™¨­ç8CºwŸ¼nÜfiþ—z‘YÛTÆ\®8—Lˆ]Ô”½s/’Ê<ºVó½·GÑ…‹iŒ%†å\Þf݃J[4±ôì—j˜‘‡8Ï|Yªæ³¶ˆ,E`O²ü~ðUÔ¶­Øñ-K㈥ÂÞú„¥òDÑ7«P Ï&uN¯Üa³¸Ë‚+m…IŠ }±Ñ;‘×´]Ë6‹ tÕçM­H×ï3]o¤-y*Œ&mSHÃgH’²«H/¡S×´zþ'†XºÍ°ÕÝ2Ö–§®(†>oÆíÉX[K¹+5l «Ó„ºe町Ò}lï…žYÌVÔ|â,L'P¸H½²s‰í!ô È‚Åñª•DUeia§ñð°.„10´òæ¡»ýeãt#]é×kÖè•6o™é¤ŽÿÓÍ„â$Ÿì´v¦+þÞ;=S³fm{×îí£T7l3f†zOš’6 ›K¤­3_ykßTfÒêcgZS—›PkŒ¾ÐÕIâ‘Ú{²Í¬$$Á‘øKu#ÉCÌ´Uý=0ÔãÅ’˜`3mAl5ßi¡‹£«gÖÔ¼R¤BlJ³¶ ܬÎàžÇ§¶`A[‰)R”ÀPZQá0Ä`®%K5eоCW*Zý,aXçAˆ[Em·›µÐ3"¸Wn¡çÚÆèö~AþƒOÅ;xû\ÑHBŒ ¿*ë '.dº‡Gì²Vol¡Kº êx:sðЏæÝYk{нÞPO9ÅÁþ©‹U;,R÷˜HÀàÆù„½SÃÊé&p¯R‡ Á¹_=œ 9Ï'tFi«h{‘zÂà åí uÑË£q®z.û¶»4Ž%1‡{dKhÃ6³±HC“@ÚzqÚ0b1vòÞJÚ†ø¶Au;îöv™¶Gž¦ªý^m/iúûœ½š³Ä¡ nJæÚ[Oȵ Ó¡¾5JÛ¬éì6ª+­éÎdU»°õ‘ºVnQ"fÇÄš¶S»€ì'ßfjÈŽ¯wð0…Ð ßfV4p¹Ds‹ô.ö2¬ª3”M ÞMh£?Ó.ã[ÿ&ÃJ%nþõìÇÇjØ1P¿¿ ¤cqô#ÒL˜Þe4ûàFütJ–ikíEiÛ$&ˆK \èÙÀ‰ltŸM­QÐøY$®Ý¨dÚ^u•ùLÓù\M Å“MØ#²—¶ÊÐNã9•„í¢l`nfXU5©U²’x3”C@qÐŽf?2ï`»Ø.Ó}í ×<ôhÅz}颶ª.S@^4È·QØ4§Òf&!«QØÞ3la‡¥+çí1« A*äBBs…s5ZYžY*U0cHc5³'F«Ãp,Î,Ñl NÙwÆZ¤‚hûI{Œó›ÊÆÄ<”Äqf鬯4&¬Äëb—Œ,US5™¶l˜afQ´Å3gBUíàm¶/x@V?¿@åjϯã4µÈB4œó€µEs §€2&DŽ¢Þ¯Ù8_µ¹tl¿Rô-¥û–Z7ù„á²á³.×…‘¥1ÎWíB|ë|”wƒ] &„]¦uå‰%¸axõJ§N¬‹ñw1K´§lÐŽæÁàÕ8r‚CàîgÓ`;)ÚrŒ"pÛ]²q0-kšFé2qýY=;LÌ|ŸBÚ‡T’¨sµå' l1OÙ §cä!^g1i"‹ãKŸÆÁBTÓºË\ÛpÞ¡œCêB°ö:_èÀ" BáÐV>ù…lö®{޳W›M c‹icÓšn|>óÉ1²a ŠÅE<'ÖuÝSbÞËáÂÓw„ 4“çiðJTphq„¬38»Æ­¶pÆ2^raþ*Äô&ˆÇa&@"ƹ øþéZj¬ˆbÑÈfÅ<¥Ñôššp› Ÿ-¤‰@eRss>ç6,ÏÅVÃl­šýŠ ë¶t˜´QGÜÊiü7YV¼ϧ&yðÚ\ÀWÉuS¨DkUe‰g}è·êdªá«®ÿ;Ã{þî¦×þ¹þöÿZÿ@ÿÃÐVñK–žÞÖ^½ôåúƒ©RûëµÿÁÎÿÁ·ƒª•Høm]þƒþ@0|ÃÞþ «/ï 81NÛ›÷/ºÆ= 51S¦·îS…=dtô@ÏehŠL·Ù‰üM/1, ’yÉTÎÒ !ürZ]+³'Ô«Õqx©uaˆßÐÉA—Kq­ø ®$uµ€ë CŒ!T²¿@KñÔOÑÀÞ¦¬”`Ø&h?$Åÿ ­ÂvÇÍ^ñ¼ h¨ØBØF|ÏüÅèò ‰*ƒV°Í6 Èð&²½xï Ú€maU»Ð9ý<)†½ûZ^õo+>YòÒEÖ~( _¼C{Wæª<µU¬%lñ`5œsl Ø0¤LËš*A›x»ËÎê ´˜M¶íÐ^„"°­—}¿ÏÏ'%:˜FüíS+û#m×é+@óèf€åF8ÆÝw ¤U’¥ÂÀû½‹ÐÞæ´'ø­ïæÐîôlÚáÎߨš£-B!;9`Ƭi0KúZJ‹ýŽì­]÷º%®ç7ÚVí³âÛelCã›ô…]f‚¹½ÎÅ(B»ÄÚQÆsh¬bÐilW9´„Uy&cqNåÉÐÖ”®þ­1?³6LãDÆê–@°[VnALãí'+°dÐ[K…m² ŒmakÏ9´ÑÖ†iÚ0uúK‚¬@ )ðT€­C[²ödÉŒ:> éòWâ ´õdm2µTjïBe†í€Øn3hÕIŠíKfÍõ‹ Ð6‘µÉ„)‰ Za­Çƒ­XµIHnL U¬Ý[û‹‹Bp1cú.Cëë_-¹±uŸõà´/Ú$‹r[õ8«-B‚öJØúÁvÚÖFh!úÚ¬ÓøŒµ÷d!ޤ$`—¡µ¿EVor $÷›;ûmµ›£Uöâ¹WéÜõG[Á¶mîÄæCû Øž–½ØÜÖª vfèñŠú„4ï“Akr[ë‡öÝ“® MÛ›\tcnÙ Àž0xd´ªã9æu i3ƒ ýbYªfß–Ö`+.L÷7¶ m2¶¥­-⃃š@É M†ýY$h•­õÖ½¿à›&ú®jÑ}…¶d{y dÌØq-B¯ÜÒâÐö€Fè‘  ¨6µß"„ÝÌ (cÀOÒÊY[¿3*'v™„úÏ ÅÑqÇÄEK^X…o¬EkƒOaÀoõàÈÖóTì&ùyÒ˜Ù—0B0sR„mž/$h [Ø+ûv´%kw³„¡ˆ½r[Ëýlrm—"„÷^!T»9´mý~ ¾ É£)'Ja¬Ëð@?;Dz°Kñ×>aÛç–6Ë‚A lakfNì<–!'í,>ˆÁWaêhûšTž™C[ý1´)Æ%wæÒP惤åAxàÈ"äáq#3KÁúŽ:L`«ã® Úðp‘kJ2ÒŽ Zm¾@+Øæ÷ØáImÄ.AkæÙØc‰KÆ&b{L‰Èi¶Ç[~´`¿hi[)$T… “Agˆ‡©ì§LrU¾ á­É¯ÖάA‘0ÌY Àâ9Âë ÎŒßX»p&öWâVÜ %â¿oC)ñ´HÛ<:ø‰¶Ÿãï#¡×j7)ðJ§TbêUñkVžÉLBŒî )ƒör¡†3v¥Cð5ƒ¶Ù›÷ßw‰ ¸3t[®!`à& ù}Ú·6µœ´2_ºY0.í‰Ë¬`álm$lSx« m‚6cmIÛ%hs`ñà 1?‹•/_œÃþ[Ö¸ ±3„nÁÖ&Ò&h]nh×…û|qd–ŸÈæüþ¢ãc qÌ[cû#´e=Q{± ÚJ3– ) Ï•1aG¯tGlhßGÜÉ‹U âv õZÊB‘–-è°·ëõO†6Û2’³|ˆ=¼oçN,3´\>x†ÔA»±EƒPĵêq«ÊÖ6øŒ™,@+uÁ†Àu±Í=—ÆÿXŽýBÜŠ¿Ü™1sû¸O¤]Ú8LøÈ‘ýdО>§íÜ‘´[å-±-¯n(ÌPêþ¯M”ýÂÚx|8=¾ãb¯-3öžA+.ÁE_°ÐÀáøÏ±=RËŒ‰KÏájÅFh8Þ Ú×´l[ ëÆ3ÜsGÆÐ2o'Æ6»™#›Z7!¼m5i—êµóúAm€U¥Ú,ætéš®ÊL篈{äÌ·’o¥*Á¤] m÷4û˜™ƒtþ GVåÐÊl¬ðÖv‹!m í-†·sh«ehóþÂãZ“€ § ÚŘsÞ,ÿ^é$ƒ PIDATŽ]>'›â°z>-æmªÏR¹KL>æxÌâ®t²‡>ï¤Ì+ZßÞFl²sÒ⩵[øÚ-Ô’AÈYË'Û4°ªTû-¿_ñðÃbÉpéÌ)ž.H%›ÅºLÞÚæõïÏC{0þ:]»¢"nmjä2¶à÷?º0³àÄäÜZLÆí²­Ý-C+á®{ÿ %«Ðþ¬òAï¯eª@Z¡,¦`1´Ua×'»´3Ú*h·Raê`g–v-€›RyNéÜ ,C›N… ­5cÙÌ]]¾üR¢[eàþdŽé‹Oðô)󥸴ÜS¬›%°sG¡Å WÆ€,$d¯ùüÁ3¥ekëhÚiÖâÌp7‡ö[ nÛ&[Ù|oÝ)©MØò©Ó%â¦lA5Ãt”n+”Á@»)šïZ.yq5±-ë´ËS31ux-„ØË=ÈÜŒ:Iž … ÀU2’ÿZL=ºøêg«›ÎK»Ù\†vÝ/öoç•ÄOùØä"#h7R˜áÜB0·™U¼2&ÅÎWÛQ—gf¬7ÅäÜ&´òdöYðemí¾@‹ç·CÀr¬òIóí1?þF\$­†µ_/B;»"¼×g–‘Eh%½M©Ã܇]Ë™:Ñ,]&íb½6›GºkhÈŸEèæ¶“´çŠFð«huÁc…dqs«ŽœÑQ®‚¸–Ú` Ûþk…vfh?m«/ÐØ~÷a!Ã}†Ôá ´s#¯”AB@àš1Ƶ-9<ª;µÓTfˆÝ1¨JëöX˜ìz8!‡ØjâÂÏZÏÁb8ÓÛì ­@›hkm6>b?¦9´·k1| ØÆ®Wê–âÚÃî‹=¸çs^J´µ8/ÇÌf\9N§)}åv{íQ}ø@–¡}h£ ¤PÕÜÜnDZúÇã‘Yæ«ÂöEgÒ¤fœéPØJêPÔÔs#T1QÒ2ÂVC©¸6ZÚÝ‚¥½ëÊW(TƒG[]$ÿå£ð«®›ÕkuOW¥¯Ô6 Ówöà„^q~uÉïì­]&ìúLñJñ—v`§âð÷iY›“ö•°ì)e¸75AGȦ‚×-…·<4¬k_œØ!gm¥ÂÿÉ™'>i†cû‹õÚíQ7nÃÌÔG‘ªü,ú#>c+äý˜-ýÅðüü'ˆø!¥™=•àfŽÌZÝÄ}ñ'$l³‚×ui8‘>0‚±Ýc •f—­—³…™Óñ?…¨ðFä£0V«¥†6&Yï, lßÕ>6~ Ed¥¸KœÅ@«Þ[óÉãÙ‚±³øK BÑY©ƒÕõïåáDú,Ávpm:pˆaÉ…Å£Îôù ݆tÝéc¤±Ä¨¡=†øŠ~iw†1nþ•j`,C+,Ãw½ÎçbÄ%Ù¾-c®Ó]mZ5x@èv]Hâ®b`&–i1„Ò…ºÈÚCzÌræÃY+ãÞùÉò¥Ž®ÓÑ=‹$¶d®V=“$ãk:ß{¿¤ŸUˆ¡A¨ˆ÷,°v›gdÖ³´rv*ݾٷó¸kÚ‘ÃÛtS³¶¬Ì¨“ÎK#ÔoXý1´µâ—".²ÂöuÆYÞ§Í[‹° -F‚n)–- hkmÁÙ—š§ðv–‡•–vä§1˜²ä‘„]jÛ¤ú—y³\BÙK†í7ƒ%Y®j# qûðhÍXýa:n»ì±³¸`eÃ5ªÌ,B ñ—òŒ à2§LçBÛ¬$SŒ& kñ°\1v® =ìf‰ØE%ºñÛ*¶ùý¯ÐjObÝF oÖžKòÏ–V¥±ÈÙO°²1X´²ñ‚TuaT†Ê]1u0:.,@;Îú£ÖÎ'fÔ3è\HÎÚh 2sðÍ Ä˜5˶’UÀ¶¤I¨³§(Pæµb̬j‡3°ELæ¾Á"œ¾…áÄÂ)i оæ}Á–‡À#í8žËv1A{PðÚ&P¶K~‡vvõ¡60Ä®¸íËÀöêÉO”-¬¿–¹Ò §fÃ<ˠŨˆ´MÐ*ÎJ6†·]Ѧ/¬`›—‚»]Q;8(\ ÖRZ{)¬ìϡȱÄcSWÂqŽ+ÿ:Ë´ƒUÏ1Ë-Æå`/ú=©Ã Ñ‘Y»48Ç™B oO‹Ö Gv†­°6 i³È+A[‘ûÕ´rm·mŸÇÉ®êƒ qf#õ_Y mš£Ïa‰í†ƒ´½ýFÙ­p{5O±÷ ЦBbJËtÔu[°áQ.úhfí}xiƒ€GmÕ„ýå  ¦²fk˜Cª5i”pí·«0¡cS¿6?Y£ÛÚv§¯œ ‡l¶ajÅÚWÁYݱItÝ}ŸÆ³C•ÖæGruí ‡Ý—>‚wYdmikS4•E¬bZ;‰Ãb[f ,ó&¶ ò^ÂçÙ7ïµMçÄé´EØ¥û ¡£CCàK,±gžºa ÐU™0×q‘',3´Xâê~BV¦ ¨f¹€W*vZ+'ÅwÁoÊ?k°·^ð«ÙIó»Úÿe]·phŸŠüd®á—ü‘þDì"hé‘]êÁ`Ô«l²ñ›ôä°/?Q¢á’篋qmÅS–F©h¢f]\ˆÏÝú3¡N ÿýÉ·Èçg¶îw±U1=ƒq8nøõâawšuD|yà‘”ã7øï?^ü¤1Të{°VFÐaéú…Ç“Š ´*”þí`Gø_äNCÙÑÍ{–.Ÿý¯É>S±ª«oOá©ê¦ÂÏ=m¾\Ň¢òß¿¯L?µZZå“‚Z…¹ÐŠ~5¹Èe5*õ+ûŽïoªÉuøç9_ÿ¶ë¿œßAÉÝÅ_IEND®B`‚sane-backends-1.0.27/doc/sane-pixma.man0000664000175000017500000003301313110416067014525 00000000000000.TH "sane\-pixma" "5" "20 May 2017" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-pixma .SH NAME sane\-pixma \- SANE backend for Canon Multi-Function Printers and CanoScan Scanners .SH DESCRIPTION The .B sane\-pixma library implements a SANE (Scanner Access Now Easy) backend that provides access to Canon PIXMA / i-SENSYS / imageCLASS / imageRUNNER multi-function devices (All-in-one printers) and the Canon CanoScan Flatbed/TPU scanners. The backend implements both the USB interface and network interface (using Canon's BJNP and MFNP protocols). The network interface supports scanners over IPv4 as well as IPv6 (MFNP over IPv6 is untested). .PP Currently, the following models work with this backend: .PP .RS PIXMA MG2100, MG2200, MG2400, MG2500, MG2900, MG3100, MG3200 .br PIXMA MG3500, MG3600, MG4200, MG5100, MG5200, MG5300, MG5400 .br PIXMA MG5500, MG5600, MG5700, MG6100, MG6200, MG6300, MG6400 .br PIXMA MG7100, MG7500, MG7700, MG8200 .br PIXMA MP140, MP150, MP160, MP170, MP180, MP190 .br PIXMA MP210, MP220, MP230, MP240, MP250, MP260, MP270, MP280 .br PIXMA MP360, MP370, MP390 .br PIXMA MP450, MP460, MP470, MP480, MP490 .br PIXMA MP500, MP510, MP520, MP530, MP540, MP550, MP560 .br PIXMA MP600, MP600R, MP610, MP620, MP630, MP640 .br PIXMA MP700, MP710, MP730, PIXMA MP750 (no grayscale) .br PIXMA MP800, MP800R, MP810, MP830 .br PIXMA MP960, MP970, MP980, MP990 .br PIXMA MX300, MX310, MX330, MX340, MX350, MX360, MX370 .br PIXMA MX410, MX420, MX470, MX510, MX520, MX530, MX700, MX720 .br PIXMA MX850, MX860, MX870, MX882, MX885, MX890, MX920, MX7600 .br PIXUS MP10 .br imageCLASS MF3110, MF3240, MF4010, MF4018 .br imageCLASS MF4120, MF4122, MF4140, MF4150 .br imageCLASS MF4270, MF4350d, MF4370dn, MF4380dn .br imageCLASS MF4410, MF4430, MF4570dw, MF4660, MF4690 .br imageCLASS MF5730, MF5770, MF6550, MPC200, D420, D480, D530 .br i-SENSYS MF230, MF240, MF3010, MF4320d, MF4330d, MF4500, MF4700 .br i-SENSYS MF4800, MF6100, MF8200C, MF8300 .br imageRUNNER 1020/1024/1025 .br CanoScan 8800F, 9000F, 9000F Mark II .br MAXIFY MB5000 (ADF is not working) .RE .PP The following models are not well tested and/or the scanner sometimes hangs and must be switched off and on. .PP .RS PIXMA MP760, MP770, MP780, MP790 .RE .PP The following models may use the same Pixma protocol as those listed above, but have not yet been reported to work (or not). They are declared in the backend so that they get recognized and activated. Feedback in the sane\-devel mailing list welcome. .PP .RS PIXMA E400, E460, E470, E480, E500, E510, E560, E600, E610 .br PIXMA MG3000, MG4100, MG6500, MG6600, MG6800, MG6900, MG8100 .br PIXMA MP375R, MP493, MP495, MP740 .br PIXMA MX320, MX390, MX430, MX450, MX490, MX710 .br PIXMA G3000 .br PIXMA TS9000, TS800, TS6000, TS5000 .br PIXUS MP5 .br imageCLASS MF810/820, MF5630, MF5650, MF5750, MF8030, MF8170c .br imageCLASS MPC190 .br imageRUNNER 1133 .br i-SENSYS MF210, MF220, MF5880dn, MF5900, MF6680dn, MF8500C .br MAXIFY MB2000, MB2300, MB5300 .RE .PP \#The following models may use partly the same Pixma protocol as other devices \#listed above, but may still need some work. They are declared in the backend \#as experimental. Snoop logs are required to further investigate, please contact \#the sane\-devel mailing list. \#.PP \#.RS \#PIXMA MP--- \#.RE \#.PP The backend supports: .PP .RS * resolutions of 75, 150, 300, 600, 1200, 2400, 4800, and 9600 DPI (some maybe buggy), .br * color and grayscale mode, as well as lineart on certain models, .br * a custom gamma table, .br * Automatic Document Feeder, Simplex and Duplex. .br * Transparency Unit, 24 or 48 bits depth. Infrared channel on certain models. .RE .PP The device name for USB devices is in the form pixma:xxxxyyyy_zzzzz where x, y and z are vendor ID, product ID and serial number respectively. .PP Example: pixma:04A91709_123456 is a MP150. .PP Device names for BJNP/MFNP devices is in the form pixma:aaaa_bbbbb where aaaa is the scanners model and bbbb is the hostname or ip-adress. .PP Example: pixma:MF4800_192.168.1.45 is a MF4800 Series multi-function peripheral. .PP This backend, based on cloning original Canon drivers protocols, is in a production stage. Designed has been carried out without any applicable manufacturer documentation, probably never available. However, we have tested it as well as we could, but it may not work in all situations. You will find an up-to-date status at the project homepage. (See below). Users feedback is essential to help improve features and performances. .SH OPTIONS Besides "well-known" options (e.g. resolution, mode etc.) pixma backend also provides the following options, i.e. the options might change in the future. .br The button status can be polled i.e. with 'scanimage \-A'. .br Button scan is disabled on MAC OS X due to darwin libusb not handling timeouts in usb interrupt reads, but may work when using the network protocol. .TP .I adf\-wait This option enables and sets the time in seconds waiting for a document inserted into the .BR Automatic .BR Document .BR Feeder . The maximum allowed waiting time is 3600 sec (= 1 hour). .TP .I button\-controlled This option can be used by applications (like .BR scanadf (1) and .BR scanimage (1)) in batch mode, for example when you want to scan many photos or multiple-page documents. If it is enabled (i.e. is set to true or yes), the backend waits before every scan until the user presses the "SCAN" button (for MP150) or the color-scan button (for other models). Just put the first page in the scanner, press the button, then the next page, press the button and so on. When you finished, press the gray-scan button. (For MP150 you have to stop the frontend by pressing Ctrl-C for example.) .TP .I button\-update (deprecated) (write only) In the past this option was required to be set to force reading of the button status for .I button\-1 and .I button\-2. The .B sane\-pixma no longer requires this option to be used: if no fresh data is available, it will be now requested automatically from the scanner. This option is left for backward compatibility reasons. .TP .I button\-1 button\-2 (read only) These options will return the value of the respective buttons. value 0 means that the button was not pressed, 1 is returned when the button was pressed. Some scanners with more than two buttons send the button number as target. .TP .I original (read only) Returns the value of the type or size of original to be scanned if the scanner provides that data. Known values of type: 1 = document, 2 = foto, 5 = film. Known values of size: 1 = A4, 2 = Letter, 8 = 10x15, 9 = 13x18, b = auto. Not all scanners can provide this data. .TP .I target (read only) Returns the value of the target of the scan operation if the scanner provides that data. The values depend on the scanner type. Known values: 1 = save to disk, 2 = save to pdf, 3 = send to email, 4 = send to application or 1 = JPEG, 2 = TIFF, 3 = PDF, 4 = Compact PDF. For some scanners this value is equivalent to the number of the pressed button. Not all scanners can provide this data. .TP .I scan-resolution (read only) Returns the resolution of the scan operation if the scanner provides that data. Known values: 1 = 75 dpi, 2 = 150 dpi, 3 = 300 dpi, 4 = 600 dpi. Not all scanners can provide this data. .SH FILES .TP .I @LIBDIR@/libsane\-pixma.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-pixma.so The shared library implementing this backend (present on systems that support dynamic loading). .TP .I @CONFIGDIR@/pixma.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). The file contains an optional list of networked scanners. Normally only scanners that cannot be auto-detected because they are on a different subnet shall be listed here. If your OS does not allow enumeration of interfaces (i.e. it does not support the getifaddrs() function) you also may need to add your scanner here as well. .RS .PP .I Scanners shall be listed in the configuraton file as follows: .PP .RS .I ://[:port][/timeout=] .RE .PP where method indicates the protocol used (bjnp is used for inkjet multi-functionals and mfnp is used for laser multi-functionals). .PP host is the hostname or IP address of the scanner, e.g. bjnp://10.0.1.4 for IPv4, bjnp://[2001:888:118e:18e2:21e:8fff:fe36:b64a] for a literal IPv6-address or bjnp://myscanner.mydomain.org for a hostname. .PP The port number is optional and in normally implied by the method. Port 8610 is the standard port for mfnp, 8612 for bjnp. .PP A scanner specific timeout value for the network protocol can be set using the bjnp-timeout parameter. The value is in ms. .PP Define scanners each on a new line. .PP More globally applicable tinmeouts can be set using the bjnp-timeout parameter as folllows: .PP .RS .I bjnp-timeout= .RE .PP A timeout defined using bjnp-timeout will apply to the following scanner definitions in the file. If required the bjnp-timeout setting can be defined multiple times, where each settng will apply only to the scanners that follow the setting. The last setting is used for the auto discovered scanners. If not explicitely set, the default 1000ms setting will apply. .PP Setting timeouts should only be required in exceptional cases. .PP .SH USB SUPPORT USB scanners will be auto-detected and require no configuration. .SH NETWORKING SUPPORT The pixma backend supports network scanners using the so called Canon BJNP protocol and MFNP protocol. Both IPv4 and IPv6 are supported, but IPv6 is as yet untested with MFNP. Please report your results on the mailing list. .PP Configuration is normally not required. The pixma backend will auto-detect your scanner if it is within the same subnet as your computer if your OS does support this. .PP If your scanner can not be auto-detected, you can add it to the pixma configuration file (see above). .SH FIREWALLING FOR NETWORKED SCANNERS The sane pixma backend communicates with port 8610 for MFNP or port 8612 for BJNP on the scanner. So you will have to allow outgoing traffic TO port 8610 or 8612 on the common subnet for scanning. .PP Scanner detection is slightly more complicated. The pixma backend sends a broadcast on all direct connected subnets it can find (provided your OS allows for enumeration of all netowrk interfaces). The broadcast is sent FROM port 8612 TO port 8610 or 8612 on the broadcast address of each interface. The outgoing packets will be allowed by the rule described above. .PP Responses from the scanner are sent back to the computer TO port 8612. Connection tracking however does not see a match as the response does not come from the broadcast address but from the scanners own address. For automatic detection of your scanner, you will therefore have to allow incoming packets TO port 8612 on your computer. This applies to both MFNP and BJNP. .PP So in short: open the firewall for all traffic from your computer to port 8610 (for MFNP) or 8612 (for BJNP) AND to port 8612 (for both BJNP and MFNP) to your computer. .PP With the firewall rules above there is no need to add the scanner to the pixma.conf file, unless the scanner is on a network that is not directly connected to your computer. .SH ENVIRONMENT .TP .B SANE_DEBUG_PIXMA If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend itself. Higher value increases the verbosity and includes the information printed at the lower levels. .RS 0 print nothing (default) .br 1 print error and warning messages (recommended) .br 2 print informational messages .br 3 print debug-level messages .br 4 print verbose debug-level messages .br 11 dump USB traffic .br 21 full dump USB traffic .br .RE .TP .B SANE_DEBUG_BJNP If the library was compiled with debug support enabled, this environment variable controls the debug level for the .B BJNP and MFNP network protocols for this backend. Higher value increases the verbosity and includes the information printed at the lower levels. .RS 0 print nothing (default) .br 1 Print error and warning messages (recommended) .br 2 Print high level function tracing information .br 3 Print more detailed protocol tracing information .br 4 Print protocol headers .br 5 Print full protocol contents .RE .TP .B PIXMA_EXPERIMENT Setting to a non-zero value will enable the support for experimental models. You should also set SANE_DEBUG_PIXMA to 11. .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .SH "SEE ALSO" .BR sane (7), .BR sane\-dll (5), .I http://home.arcor.de/wittawat/pixma/, .I http://mp610.blogspot.com/ .PP In case of trouble with a recent Pixma model, try the latest code for the pixma backend, available in the Sane git repository at: .br .I http://git.debian.org/?p=sane/sane-backends.git .PP You can also post into the Sane-devel mailing list for support. .SH AUTHORS Wittawat Yamwong, Nicolas Martin, Dennis Lou, Louis Lagendijk, Rolf Bensch .PP We would like to thank all testers and helpers. Without them we could not be able to write subdrivers for models we don't have. See also the project homepage. sane-backends-1.0.27/doc/sane-s9036.man0000664000175000017500000000417512112021330014164 00000000000000.TH sane\-s9036 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-s9036 .SH NAME sane\-s9036 \- SANE backend for Siemens 9036 flatbed scanners .SH DESCRIPTION The .B sane\-s9036 library implements a SANE (Scanner Access Now Easy) backend that provides access to Siemens 9036 flatbed scanners. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the path-name for the special device that corresponds to a SCSI scanner. The special device name must be a generic SCSI device or a symlink to such a device. The program .IR sane\-find\-scanner helps to find out the correct device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. See sane\-scsi(5) for details. .SH FILES .TP .I @CONFIGDIR@/s9036.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-s9036.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-s9036.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_S9036 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_S9036=4 .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHOR Ingo Schneider sane-backends-1.0.27/doc/descriptions-external/0000775000175000017500000000000013110600532016364 500000000000000sane-backends-1.0.27/doc/descriptions-external/mustek_a3p1.desc0000664000175000017500000000100412775312261021312 00000000000000:backend "mustek_a3p1" ;:version "1.0-3" ;:manpage "sane-mustek_a3p1" :url "http://www.meier-geinitz.de/sane/mustek_a3p1-backend/" :comment "Only Mustek P 3600 A3 Pro is supported at the moment" :devicetype :scanner :mfg "Mustek" :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "P 3600 A3 Pro" :interface "USB" :status :minimal :usbid "0x055f" "0x0401" :comment "Reports about scanning problems. 1800 dpi seems to work if only small scan areas are selected." sane-backends-1.0.27/doc/descriptions-external/template.desc.0000664000175000017500000000567112112021330021040 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "template" ; name of backend :version "0.42" ; version of backend (or "unmaintained") :new :yes ; Is the backend new to this SANE release? ; :yes or :no :manpage "sane-template" ; name of manpage (if it exists) :url "http://www.luser.com/temp/" ; backend's web page :url "http://www.luser.com/b/" ; another backend webpage :comment "This backend supports only the USB and SCSI models" ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "TemPlate" ; name a manufacturer :url "http://www.template.com/" ; manufacturer's URL :url "http://www.template.de/" ; another manufacturer URL :comment "TemPlate scanners are sometimes labeled \"TMP\"" ; comment about the manufacturer :model "Templ Z" ; name models for above-specified mfg. :status :untested ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "SCSI" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :usbid "0x1234" "0x4321" ; Vendor and product ids of an USB device :url "http://www.tmp.com/z.html" ; model's URL :comment "With Z-Axis scrolling" ; comment about the model :model "Templ ZS" :interface "USB" :usbid "0x1234" "0x4322" :status :unsupported :comment "No support yet, but we have docs." :model "Templ ZQ" :interface "USB" :usbid "0x1234" "0x4323" :status :minimal :model "Templ ZY" :interface "SCSI" :status :basic :model "Templ ZZ" :interface "SCSI" :status :good :mfg "ArmorPlate" ; another manufacturer... :url "http://www.armorplate.com/" :model "AmplScan II" :interface "SCSI" :status :complete :comment "AmplScan *II*, not AmplScan!" :devicetype :api ; specify a different type :desc "Interface to FrObYz API" ; describe a non-hardware device :comment "Only FrObYz version 2.0 is supported!" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; :status specifier is optional after :model and at the top-level sane-backends-1.0.27/doc/descriptions-external/samsung.desc0000664000175000017500000000452312775312261020644 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "samsung" ; name of backend ;:version "(external)" ; version of backend :url "http://product.samsung.com/cgi-bin/nabc/support/b2c_support_product_results.jsp" ; backend's web page :comment "External binary-only backend for Linux i386 (and x86_64?). See the website for the latest release." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Samsung" ; name a manufacturer :url "http://www.samsung.com/" :comment "Multi Function Peripheral. External backend made by Samsung. Please check the Samsung website and/or contact us if you have a Samsung device not mentioned here." ; name models for above-specified mfg. :model "SCX-4016" :interface "Parport USB" :status :untested :comment "Please contact us if you use this device." :model "SCX-4100" :interface "Parport USB" :usbid "0x04e8" "0x3413" :status :good :comment "Is reported to work. " :model "SCX-4200" :interface "USB" :usbid "0x04e8" "0x341b" :status :good :comment "Is reported to work. The configuration applet must be run as root." :model "SCX-4216F" :interface "Parport USB" :usbid "0x04e8" "0x3409" :status :untested :comment "Please contact us if you use this device." :model "SCX-4521F" :interface "Parport USB" :usbid "0x04e8" "0x3419" :status :basic :comment "See bug report #304052" :model "SCX-4720F" :interface "Parport USB" :status :untested :comment "Please contact us if you use this device." :model "SCX-6220" :interface "Parport USB" :status :untested :comment "Please contact us if you use this device." :model "SCX-6320F" :interface "Parport USB" :status :untested :comment "Please contact us if you use this device." :model "SF-565P" :interface "Parport USB" :status :untested :comment "Please contact us if you use this device." :model "SF-755P" :interface "Parport USB" :status :untested :comment "Please contact us if you use this device." sane-backends-1.0.27/doc/descriptions-external/viceo.desc0000664000175000017500000000432712112021330020251 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "viceo" ; name of backend :version "0.6" ; version of backend ;:manpage "sane-viceo" ; name of manpage (if it exists) :url "mailto:viceo@stevencherie.net" ; backend's web page :url "http://viceo.orcon.net.nz/" :comment "Supports E3 and E4 family USB scanners from Genius, Primax, IBM. The backend is not included because the license situation is unclear. Also it only works on Linux and needs a a patch for the kernel scanner driver which isn't available on 2.6." :devicetype :scanner :mfg "Genius" ; name a manufacturer :url "http://www.genius-kye.com/" :model "Vivid Pro USB" ; name models for above-specified mfg. :interface "USB" :usbid "0x0458" "0x2001" :status :basic :comment "Linux 2.4 only, needs a kernel patch." :mfg "Primax" :url "http://www.primax.nl/" :model "Colorado USB 19200" :interface "USB" :usbid "0x0461" "0x0360" :status :basic :comment "Linux 2.4 only, needs a kernel patch." :model "Colorado 2200 USB" :interface "USB" :usbid "0x0461" "0x0364" :status :untested :comment "Untested. See link for details. Linux 2.4 only, needs a kernel patch." :url "/unsupported/primax-colorado-2200-usb.html" :mfg "Visioneer" :model "OneTouch 6100" :interface "USB" :usbid "0x04a7" "0x0231" :status :basic :comment "Linux 2.4 only, needs a kernel patch." :model "OneTouch 7600" :interface "USB" :usbid "0x04a7" "0x0211" :status :basic :comment "Linux 2.4 only, needs a kernel patch." :model "OneTouch 8600" :interface "USB" :usbid "0x04a7" "0x0331" :status :basic :comment "Linux 2.4 only, needs a kernel patch." :mfg "IBM" :url "http://www.ibm.com/" :model "IdeaScan 2000 USB" :interface "USB" :status :basic :comment "Linux 2.4 only, needs a kernel patch." :mfg "LG Electronics" :model "Scanworks 600U" :interface "USB" :usbid "0x0461" "0x0364" :status :basic :comment "Linux 2.4 only, needs a kernel patch." sane-backends-1.0.27/doc/descriptions-external/lhii.desc0000664000175000017500000000440412112021330020065 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "lhii" ; name of backend ;:version "0.42" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://www.sane-project.org/backends/lhii/lhii-v0.2.tgz" ; backend's web page :comment "This backend is for old handscanners with proprietary adapter cards. You also need a kernel driver. You may find such drivers at that page: http://www.willamowius.de/scanner.html ." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Mustek" ; name a manufacturer :comment "Other models may also be supported." :model "CG-6000" ; name models for above-specified mfg. :status :untested ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "Proprietary" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :url "http://www.sane-project.org/backends/lhii/gi1904-v0.2.tgz" ; model's URL :comment "Old handscanner. Hasn't been tested for a long time but once worked. See link for the linux kernel driver that's necessary to run the scanner." ; comment about the model ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; :status specifier is optional after :model and at the top-level sane-backends-1.0.27/doc/descriptions-external/hp8200.desc0000664000175000017500000000371212112021330020062 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "hp8200" ; name of backend ;:version "0.0" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://www.cyberbaladeur.fr/telechargement.html" ; backend's web page :comment "This backend can't be added to the SANE distribution because it consists of binary-only code." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett Packard" ; name a manufacturer :url "http://www.hp.com/" ; manufacturer's URL :model "ScanJet 8200" ; name models for above-specified mfg. :status :good ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :usbid "0x03f0" "0x0b01" :url "http://ftp.cyberbaladeur.fr/82xxc%20Linux%20drivers.tar.gz" ; model's URL :comment "External backend. Binary-only Linux i386 code. Not supported by the SANE developers." sane-backends-1.0.27/doc/descriptions-external/brother2.desc0000664000175000017500000001215612776312542020722 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "brother2" ; name of backend ;:version "1.0.0" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://solutions.brother.com/linux/sol/printer/linux/sane_drivers.html" ; backend's web page :comment "External backend made by brother. As this software contains non-free parts, it can't be included into SANE. If you can't find your model here, please have a look at the brother website which contains the latest list." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Brother" ; name a manufacturer :url "http://www.brother.com/" ; manufacturer's URL ;:comment "" ; comment about the manufacturer ;data taken from Brother website and Brsane2.ini :model "DCP-110C" :status :good :interface "USB" :usbid "0x04f9" "0x0169" :model "DCP-115C" :status :good :interface "USB" :usbid "0x04f9" "0x018c" :model "DCP-116C" :status :untested :interface "USB" :usbid "0x04f9" "0x018d" :comment "No report yet." :model "DCP-117C" :status :good :interface "USB" :usbid "0x04f9" "0x018e" :model "DCP-120C" :status :good :interface "USB" :usbid "0x04f9" "0x0190" :model "DCP-310CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x016b" :comment "No report yet." :model "DCP-315CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0191" :comment "No report yet." :model "DCP-330C" :status :untested :interface "USB" :usbid "0x04f9" "0x01a9" :comment "No report yet." :model "DCP-340CW" :status :untested :interface "USB" :usbid "0x04f9" "0x0192" :comment "No report yet." :model "DCP-7010" :status :good :interface "USB" :usbid "0x04f9" "0x0182" :model "DCP-7020" :status :untested :interface "USB" :usbid "0x04f9" "0x0183" :comment "No report yet." :model "DCP-7025" :status :good :interface "USB" :usbid "0x04f9" "0x0184" :model "MFC-210C" :status :good :interface "USB" :usbid "0x04f9" "0x0161" :model "MFC-215C" :status :good :interface "USB" :usbid "0x04f9" "0x0193" :comment "brscan2-0.0.2 necessary" :model "MFC-240C" :status :good :interface "USB" :usbid "0x04f9" "0x01ab" :comment "Reportedly working." :model "MFC-3240C" :status :untested :interface "USB" :usbid "0x04f9" "0x0173" :comment "No report yet." :model "MFC-3340CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0174" :comment "No report yet." :model "MFC-410CN" :status :basic :interface "USB network" :usbid "0x04f9" "0x0163" :comment "Sometimes hangs and refuses to scan. A simple power off/on switch will fix things." :model "MFC-420CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0162" :comment "No report yet." :model "MFC-425CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0194" :comment "No report yet." :model "MFC-5440CN" :status :good :interface "USB network" :usbid "0x04f9" "0x016d" :model "MFC-5840CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x016e" :comment "No report yet." ;only in ini :model "MFC-610CLN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0166" :comment "No report yet." ;only in ini :model "MFC-610CLN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0168" :comment "No report yet." :model "MFC-620CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0165" :comment "No report yet." :model "MFC-640CW" :status :untested :interface "USB" :usbid "0x04f9" "0x0197" :comment "No report yet." :model "MFC-7220" :status :untested :interface "USB" :usbid "0x04f9" "0x0185" :comment "No report yet." :model "MFC-7225N" :status :untested :interface "USB network" :usbid "0x04f9" "0x0186" :comment "No report yet." :model "MFC-7420" :status :good :interface "USB" :usbid "0x04f9" "0x0180" :comment "No report yet." :model "MFC-7820N" :status :good :interface "USB network" :usbid "0x04f9" "0x0181" :comment "Network connection reported to work." :model "MFC-7840W" :status :good :interface "USB" :usbid "0x04f9" "0x01e5" :comment "Reported to work with brscan3 driver." :model "MFC-820CW" :status :untested :interface "USB" :usbid "0x04f9" "0x0195" :comment "No report yet." :model "MFC-8460N" :status :untested :interface "USB" :usbid "0x04f9" "0x01a5" :comment "No report yet." :model "MFC-8860DN" :status :untested :interface "USB" :usbid "0x04f9" "0x01a6" :comment "No report yet." :model "MFC-9420CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x018a" :comment "No report yet." sane-backends-1.0.27/doc/descriptions-external/primax.desc0000664000175000017500000000222012112021330020432 00000000000000:backend "primax" ; name of backend ;:version "1.1.beta1" ; version of backend ;:manpage "sane-primax" ; name of manpage (if it exists) :url "http://px-backend.sourceforge.net" ; backend's web page :comment "This backend is not included because it depends on the code of the primax command line program. Therefore the author wants to keep it in the primax CVS tree." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Primax" ; name a manufacturer :url "http://www.primax.nl/" :model "Colorado Direct 300" :interface "Parport" :status :good :model "Colorado Direct 600/30bit" :interface "Parport" :status :untested :mfg "Network" ; another manufacturer... :model "Scanny MM100" :interface "Parport" :status :good :mfg "Storm" :model "Totalscan" :interface "Parport" :status :untested :model "ImageWave" :interface "Parport" :status :untested :mfg "Genius" :model "Colorpage-Vivid+" :interface "Parport" :status :untested sane-backends-1.0.27/doc/descriptions-external/epkowa.desc0000664000175000017500000030625012775312261020457 00000000000000;;; epkowa.desc -*- emacs-lisp -*- (eh, sort of) ;;; Copyright (C) 2004--2015 Olaf Meeuwissen ;;; ;;; This file is part of the "Image Scan!" documentation. ;;; ;;; The "Image Scan!" documentation is free software. ;;; You can redistribute it and/or modify it under the terms of the GNU ;;; General Public License as published by the Free Software Foundation; ;;; either version 2 of the License or at your option any later version. ;;; ;;; This program is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of FITNESS ;;; FOR A PARTICULAR PURPOSE or MERCHANTABILITY. ;;; See the GNU General Public License for more details. ;;; ;;; You should have received a verbatim copy of the GNU General Public ;;; License along with this program; if not, write to: ;;; ;;; Free Software Foundation, Inc. ;;; 59 Temple Place, Suite 330 ;;; Boston, MA 02111-1307 USA ;;; This list of devices has been compiled using the following sources: ;;; ;;; * iscan-data-$version (see :version field below) ;;; * iscan-2.24.0/NEWS ;;; * iscan-2.24.0/backend/usb (since moved to iscan-data) ;;; * sane-backends/backend/epson_usb.c (CVS 1.18) ;;; * sane-backends/doc/descriptions/epson.desc (CVS 1.26) ;;; * http://www.freecolormanagement.com/sane/supported.html ;;; * http://www.sane-project.org/lists/sane-mfgs-cvs.html#Z-EPSON ;;; * http://www.epsondevelopers.com/ ;;; * http://www.epson.com/ (several representative countries) ;;; * http://www.i-love-epson.co.jp/ ;;; * messages on the sane-devel and LinuxPrinting.org epson-list ;;; mailing lists ;;; ;;; Some of the above sources may have moved or may no longer exist. ;; Backend data. ;; :backend "epkowa" :version "iscan 2.30.1/iscan-data 1.36.0" :url "http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX" ;; Device and manufacturer information. ;; :devicetype :scanner :mfg "EPSON" :url "http://www.epson.com/" :comment "" ; SEIKO EPSON CORPORATION's marketing division divides the world in ; Japan and several overseas regions. The same scanner is marketed ; under different names in the various regions. I have assumed the ; Japan-centric point of view that the scanner names for the models ; marketed in Japan are "canonical". All the other model names are ; considered overseas. ; I have marked the models for which I have been able to download a ; product specification with an indication of the site. ; ; JP = http://www.i-love-epson.co.jp/ (in Japanese) ; ; All command specs were downloaded from www.epsondevelopers.com. ; ; Note that the above location may have moved, may no longer exist ; or no longer provide (unfettered) access to the specifications. ; For the :comment sections I have tried to stick to the following ; ordering ; ; - support limitations ; - additional requirements ; - other backends that claim support ; - correspondence to other models ;; List of EPSON scanners and all-in-ones. ;; :model "AL-MX300DN Series" :interface "USB" :usbid "0x04b8" "0x08ac" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "AL-MX300DNF Series" :interface "USB" :usbid "0x04b8" "0x08ac" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Actionscanner II" :interface "parallel SCSI" :status :good :comment "overseas version of the GT-5000" :model "AcuLaser CX11" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :comment "overseas version of the LP-A500" :model "AcuLaser CX11NF" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :comment "network interface not supported
AcuLaser CX11 with network interface and fax" :model "AcuLaser CX21" :interface "USB" :usbid "0x04b8" "0x0835" :status :good :comment "network interface not supported" :model "AcuLaser MX20DN" :interface "USB" :usbid "0x04b8" "0x0866" :status :complete :comment "network interface not supported
business all-in-one" :model "AcuLaser MX20DNF" :interface "USB" :usbid "0x04b8" "0x0866" :status :complete :comment "network interface not supported
business all-in-one" :model "AcuLaser MX21DNF" :interface "USB" :usbid "0x04b8" "0x0866" :status :complete :comment "network interface not supported
business all-in-one" :model "Artisan 635" :interface "USB" :usbid "0x04b8" "0x0878" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-704A" :model "Artisan 700" :interface "USB" :usbid "0x04b8" "0x0846" :status :good :comment "network interface not supported
all-in-one
overseas version of the EP-801A" :model "Artisan 710 Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" :model "Artisan 725" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" :model "Artisan 730 Series" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Artisan 800" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface not supported
all-in-one
overseas version of the EP-901A" :model "Artisan 810 Series" :interface "USB" :usbid "0x04b8" "0x0853" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-902A" :model "Artisan 835" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" :model "Artisan 837" :interface "USB" :usbid "0x04b8" "0x0879" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-904F" :model "CC-500L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010d" :status :unsupported :comment "all-in-one" :model "CC-550L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011a" :status :unsupported :comment "all-in-one" :model "CC-570L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one" :model "CC-600PX" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one" :model "CC-700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0108" :status :unsupported :comment "all-in-one" :model "DS-30" :interface "USB" :usbid "0x04b8" "0x0147" :status :complete :comment "requires DFSG non-free iscan-plugin-ds-30" :model "EP-702A" :interface "USB" :usbid "0x04b8" "0x0850" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-703A" :interface "USB" :usbid "0x04b8" "0x0862" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-704A" :interface "USB" :usbid "0x04b8" "0x0878" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-705A" :interface "USB" :usbid "0x04b8" "0x089f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-706A" :interface "USB" :usbid "0x04b8" "0x08b7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-707A" :interface "USB" :usbid "0x04b8" "0x08c9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-774A" :interface "USB" :usbid "0x04b8" "0x0893" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-775A" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-775AW" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-776AB" :interface "USB" :usbid "0x04b8" "0x08b6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-776AW" :interface "USB" :usbid "0x04b8" "0x08b6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-777A" :interface "USB" :usbid "0x04b8" "0x08c8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-801A" :interface "USB" :usbid "0x04b8" "0x0846" :status :good :comment "network interface not supported
all-in-one" :model "EP-802A" :interface "USB" :usbid "0x04b8" "0x0852" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-803A" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-803AW" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-804A" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-804AR" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-804AW" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-805A" :interface "USB" :usbid "0x04b8" "0x089c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-805AR" :interface "USB" :usbid "0x04b8" "0x089c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-805AW" :interface "USB" :usbid "0x04b8" "0x089c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-806AB" :interface "USB" :usbid "0x04b8" "0x08b5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-806AR" :interface "USB" :usbid "0x04b8" "0x08b5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-806AW" :interface "USB" :usbid "0x04b8" "0x08b5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-807AB" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-807AR" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-807AW" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-901A" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface not supported
all-in-one" :model "EP-901F" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface not supported
all-in-one" :model "EP-902A" :interface "USB" :usbid "0x04b8" "0x0853" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-903A" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-903F" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-904A" :interface "USB" :usbid "0x04b8" "0x0879" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-904F" :interface "USB" :usbid "0x04b8" "0x0879" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-905A" :interface "USB" :usbid "0x04b8" "0x089b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-905F" :interface "USB" :usbid "0x04b8" "0x089a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-906F" :interface "USB" :usbid "0x04b8" "0x08b4" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-907F" :interface "USB" :usbid "0x04b8" "0x08c6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-976A3" :interface "USB" :usbid "0x04b8" "0x08b3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "EP-977A3" :interface "USB" :usbid "0x04b8" "0x08c5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ES-300C" :interface "SCSI parallel" :status :good :comment "overseas version of the GT-6000" :model "ES-300GS" :interface "SCSI" :status :good :model "ES-600C" :interface "parallel" :status :good :comment "overseas version of the GT-5400" :model "ES-800C" :interface "SCSI" :status :good :comment "overseas version of the GT-8000" :model "ES-1000C" :status :unsupported :comment "overseas version of the GT-8500" :model "ES-1200C" :interface "parallel" :status :good :comment "overseas version of the GT-9000" :model "ES-2000" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0107" :status :complete :comment "IEEE1394 untested" :model "ES-2200" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010e" :status :complete :comment "IEEE1394 untested" :model "ES-6000" ; product spec (JP) :interface "SCSI" :status :good :model "ES-6000H" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-6000HS" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-7000H" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0126" :status :good :comment "network interface not supported
IEEE1394 untested" :model "ES-8000" :interface "SCSI" :status :untested :model "ES-8500" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0109" :status :good :comment "IEEE1394 untested" :model "ES-9000H" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-10000G" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0129" :status :good :comment "network interface not supported
IEEE1394 untested" :model "ES-D200" :interface "USB" :usbid "0x04b8" "0x0137" :status :good :comment "requires DFSG non-free esci-interpreter-gt-s80" :model "ES-D350" :interface "USB" :usbid "0x04b8" "0x0144" :status :good :comment "requires DFSG non-free esci-interpreter-gt-s80" :model "ES-D400" :interface "USB" :usbid "0x04b8" "0x0136" :status :good :comment "requires DFSG non-free esci-interpreter-gt-s80" :model "ES-G11000" :interface "USB" :usbid "0x04b8" "0x014b" :status :good :model "ES-H300" :interface "USB" :usbid "0x04b8" "0x012b" :status :good :comment "network interface not supported" :model "ES-H7200" :interface "USB Ethernet" :usbid "0x04b8" "0x0138" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package" :model "Expression 636" :interface "SCSI" :status :complete :comment "overseas version of the GT-9500" :model "Expression 800" ; command spec :interface "SCSI" :status :complete :comment "overseas version of the GT-9600" :scsi "EPSON" "Expression800" "processor" :model "Expression 836XL" ; command spec :interface "SCSI" :status :untested :comment "overseas version of the ES-8000" :model "Expression 1600" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0107" :status :complete :comment "IEEE1394 untested
overseas version of the ES-2000" :model "Expression 1640XL" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0109" :status :good :comment "IEEE1394 untested
overseas version of the ES-8500" :model "Expression 1680" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x010e" :status :complete :comment "IEEE1394 untested
overseas version of the ES-2200" :model "Expression 1680 Pro" :interface "SCSI USB" :status :untested :comment "IEEE1394 option" :model "Expression 1680XL Pro" :interface "SCSI USB" :status :untested :model "Expression 10000XL" ; command spec :interface "USB" :usbid "0x04b8" "0x0129" :status :good :comment "network interface not supported
IEEE1394 untested
overseas version of the ES-10000G" :model "Expression 10000XL Graphic Arts" :interface "USB IEEE1394" :status :untested :comment "network interface not supported" :model "Expression 10000XL Photo" :interface "USB IEEE1394" :status :untested :comment "network interface not supported" :model "Expression 11000XL" :interface "USB" :usbid "0x04b8" "0x014b" :status :good :comment "overseas version of the ES-G11000" :model "F-3200" ; product spec (JP) :interface "USB IEEE1394" :usbid "0x04b8" "0x080a" :status :unsupported :comment "Film scanner" :model "F-3200 Photo" :interface "USB IEEE1394" :status :unsupported :model "FilmScan 200" :interface "SCSI" :status :unsupported :comment "A better backend for the FilmScan 200 can be found at http://www.vjet.demon.co.uk/scanner/." :url "http://www.vjet.demon.co.uk/scanner/" :model "GT-1500" :interface "USB" :usbid "0x04b8" "0x0133" :status :good :comment "requires DFSG non-free iscan-plugin-gt-1500
overseas version of the GT-D1000" :model "GT-2200" :interface "USB" :usbid "0x04b8" "0x0102" :status :unsupported :model "GT-2500" :interface "USB" :usbid "0x04b8" "0x012b" :status :good :comment "network interface not supported
overseas version of the ES-H300" :model "GT-4000" :status :untested :model "GT-5000" :interface "parallel SCSI" :status :good :model "GT-5400" :interface "parallel" :status :good :model "GT-5500" :interface "SCSI" :status :good :model "GT-6000" :interface "SCSI Parport" :status :good :model "GT-6500" :interface "parallel" :status :good :comment "overseas version of the GT-5400" :model "GT-6600U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0103" :status :complete :model "GT-6700U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010c" :status :complete :model "GT-7000S" :interface "SCSI" :status :complete :scsi "EPSON" "SCANNER GT-7000" "processor" :model "GT-7000U" :interface "USB" :usbid "0x04b8" "0x0101" :status :complete :model "GT-7200U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010f" :status :good :comment "requires DFSG non-free iscan-plugin-gt-7200
also supported by the plustek backend" :model "GT-7300U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-7300
also supported by the plustek backend" :model "GT-7400U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0120" :status :unsupported :comment "supported by the snapscan backend" :model "GT-7600S" ; product spec (JP) :interface "SCSI" :status :complete :comment "SCSI version of the GT-7600U" :model "GT-7600U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "USB version of the GT-7600S" :model "GT-7600UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "GT-7600U with TPU option bundled" :model "GT-7700U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010b" :status :complete :model "GT-8000" :interface "SCSI" :status :good :model "GT-8200U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0110" :status :complete :model "GT-8200UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0110" :status :good :model "GT-8300UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011e" :status :complete :model "GT-8400UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :model "GT-8500" :status :untested :model "GT-8700" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :complete :model "GT-8700F" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :good :comment "GT-8700U with TPU option bundled" :model "GT-9000" :interface "parallel" :status :good :model "GT-9300UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011b" :status :complete :model "GT-9400UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0116" :status :good :comment "requires DFSG non-free iscan-plugin-gt-9400" :model "GT-9500" :interface "SCSI" :status :complete :model "GT-9600" :interface "SCSI" :status :complete :model "GT-9700F" ; product spec (JP) :interface "USB IEEE1394" :usbid "0x04b8" "0x0112" :scsi "EPSON" "GT-9700" "processor" :status :complete :model "GT-9800F" ; product spec (JP) :interface "USB IEEE1394" :usbid "0x04b8" "0x011c" :scsi "EPSON" "GT-9800" "processor" :status :complete :model "GT-10000" :interface "SCSI" :status :good :comment "overseas version of the ES-6000" :model "GT-10000+" ; command spec :interface "SCSI" :status :good :comment "IEEE1394 untested
overseas version of the ES-6000H" :model "GT-12000" :interface "SCSI" :status :untested :comment "overseas version of the ES-8000" :model "GT-15000" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0126" :status :good :comment "IEEE1394 untested
overseas version of the ES-7000H" :model "GT-20000" :interface "USB Ethernet" :usbid "0x04b8" "0x0138" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the ES-H7200" :model "GT-30000" ; command spec :interface "SCSI" :status :good :comment "IEEE1394 untested
overseas version of the ES-9000H" :model "GT-D1000" :interface "USB" :usbid "0x04b8" "0x0133" :status :good :comment "requires DFSG non-free iscan-plugin-gt-1500" :model "GT-F500" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0121" :status :good :comment "multi photo feeder not supported
requires DFSG non-free iscan-plugin-gt-f500
also supported by the snapscan backend" :model "GT-F520" :interface "USB" :usbid "0x04b8" "0x0122" :status :good :comment "multi photo feeder not supported
requires DFSG non-free iscan-plugin-gt-f520
also supported by the snapscan backend" :model "GT-F550" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0121" :status :good :comment "auto film loader not supported
requires DFSG non-free iscan-plugin-gt-f500
also supported by the snapscan backend" :model "GT-F570" :interface "USB" :usbid "0x04b8" "0x0122" :status :good :comment "auto film loader not supported
requires DFSG non-free iscan-plugin-gt-f520
also supported by the snapscan backend" :model "GT-F600" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0118" :status :good :comment "only scans up to 2400dpi
requires DFSG non-free iscan-plugin-gt-f600" :model "GT-F650" :interface "USB" :usbid "0x04b8" "0x012d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-s600
GT-S600 with TPU" :model "GT-F670" :interface "USB" :usbid "0x04b8" "0x012e" :status :good :comment "requires DFSG non-free iscan-plugin-gt-f670" :model "GT-F700" :interface "USB" :usbid "0x04b8" "0x012f" :status :good :comment "auto film loader not supported
requires DFSG non-free iscan-plugin-gt-f700" :model "GT-F720" :interface "USB" :usbid "0x04b8" "0x0131" :status :good :comment "requires DFSG non-free esci-interpreter-gt-f720
GT-S620 with TPU" :model "GT-F730" :interface "USB" :usbid "0x04b8" "0x0142" :status :good :comment "requires DFSG non-free esci-interpreter-perfection-v330
GT-S630 with TPU" :model "GT-F740" :interface "USB" :usbid "0x04b8" "0x014a" :status :good :comment "requires DFSG non-free iscan-plugin-perfection-v370
GT-S640 with TPU" :model "GT-S50" :interface "USB" :usbid "0x04b8" "0x0137" :status :good :comment "requires DFSG non-free esci-interpreter-gt-s80
overseas version of the ES-D200" :model "GT-S55" :interface "USB" :usbid "0x04b8" "0x0143" :status :good :comment "requires DFSG non-free esci-interpreter-gt-s80" :model "GT-S80" :interface "USB" :usbid "0x04b8" "0x0136" :status :good :comment "requires DFSG non-free esci-interpreter-gt-s80
overseas version of the ES-D400" :model "GT-S85" :interface "USB" :usbid "0x04b8" "0x0144" :status :good :comment "requires DFSG non-free esci-interpreter-gt-s80" :model "GT-S600" :interface "USB" :usbid "0x04b8" "0x012d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-s600" :model "GT-S620" :interface "USB" :usbid "0x04b8" "0x0131" :status :good :comment "requires DFSG non-free esci-interpreter-gt-f720" :model "GT-S630" :interface "USB" :usbid "0x04b8" "0x0142" :status :good :comment "requires DFSG non-free esci-interpreter-perfection-v330" :model "GT-S640" :interface "USB" :usbid "0x04b8" "0x014a" :status :good :comment "requires DFSG non-free iscan-plugin-perfection-v370" :model "GT-S650" :interface "USB" :usbid "0x04b8" "0x013d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-s650" :model "GT-X700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0128" :status :complete :comment "IEEE1394 untested" :model "GT-X750" :interface "USB" :usbid "0x04b8" "0x0119" :status :good :comment "requires DFSG non-free iscan-plugin-gt-x750" :model "GT-X770" :interface "USB" :usbid "0x04b8" "0x0130" :status :good :comment "requires DFSG non-free iscan-plugin-gt-x770" :model "GT-X800" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x012a" :status :complete :comment "film area guide mode not supported
IEEE1394 untested" :model "GT-X820" :interface "USB" :usbid "0x04b8" "0x013a" :status :good :comment "requires DFSG non-free iscan-plugin-gt-x820" :model "GT-X830" :interface "USB" :usbid "0x04b8" "0x0153" :status :good :comment "requires DFSG non-free iscan-plugin-gt-x830" :model "GT-X900" :interface "USB" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested" :scsi "EPSON" "GT-X900" "processor" :model "GT-X970" :interface "USB" :usbid "0x04b8" "0x0135" :status :good :comment "IEEE1394 untested" :model "GT-X980" :interface "USB" :usbid "0x04b8" "0x0151" :status :good :model "K200 Series" :interface "USB" :usbid "0x04b8" "0x0871" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "K300 Series" :interface "USB" :usbid "0x04b8" "0x0872" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "L200 Series" :interface "USB" :usbid "0x04b8" "0x0873" :status :complete :comment "all-in-one" :model "L210 Series" :interface "USB" :usbid "0x04b8" "0x08a1" :status :complete :comment "all-in-one" :model "L350" :interface "USB" :usbid "0x04b8" "0x08a1" :status :complete :comment "all-in-one" :model "L351" :interface "USB" :usbid "0x04b8" "0x08a1" :status :complete :comment "all-in-one" :model "L355" :interface "USB" :usbid "0x04b8" "0x08a8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "L358" :interface "USB" :usbid "0x04b8" "0x08a8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "L550 Series" :interface "USB" :usbid "0x04b8" "0x08a9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "L850 Series" :interface "USB" :usbid "0x04b8" "0x08ca" :status :complete :comment "all-in-one" :model "LP-7900CS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9000CCH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9000CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9000CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9500CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9500CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9500CH2" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9800CCH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9800CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9800CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-A500" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :comment "network interface not supported
business all-in-one" :model "LP-M5000" :interface "USB" :usbid "0x04b8" "0x0843" :status :good :comment "network interface not supported
business all-in-one" :model "LP-M5300 Series" :interface "USB" :usbid "0x04b8" "0x0894" :status :good :comment "network interface not supported
business all-in-one" :model "LP-M5500" :interface "USB" :usbid "0x04b8" "0x0817" :status :good :comment "network interface not supported
business all-in-one" :model "LP-M5500F" :interface "USB" :usbid "0x04b8" "0x0817" :status :good :comment "network interface not supported
business all-in-one
LP-M5500 with the fax option bundled" :model "LP-M5600" :interface "USB" :usbid "0x04b8" "0x0833" :status :good :comment "network interface not supported
business all-in-one" :model "LP-M6000" :interface "USB" :usbid "0x04b8" "0x0834" :status :good :comment "network interface not supported
business all-in-one" :model "LP-M8040" :interface "USB" :usbid "0x04b8" "0x08ad" :status :good :comment "network interface not supported
business all-in-one" :model "LP-M8040A" :interface "USB" :usbid "0x04b8" "0x08ad" :status :good :comment "network interface not supported
business all-in-one" :model "LP-M8040F" :interface "USB" :usbid "0x04b8" "0x08ad" :status :good :comment "network interface not supported
business all-in-one" :model "M200 Series" :interface "USB" :usbid "0x04b8" "0x08aa" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME 200" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "ME 300" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "ME 320 Series" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "ME 330 Series" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "ME 340 Series" :interface "USB" :usbid "0x04b8" "0x0883" :status :complete :comment "all-in-one" :model "ME OFFICE 510" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "ME OFFICE 520 Series" :interface "USB" :usbid "0x04b8" "0x0865" :status :complete :comment "all-in-one" :model "ME OFFICE 535" :interface "USB" :usbid "0x04b8" "0x0881" :status :complete :comment "all-in-one
overseas version of the PX-404A" :model "ME OFFICE 560W Series" :interface "USB" :usbid "0x04b8" "0x0864" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 570W Series" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-434A" :model "ME Office 600F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 620F Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 650FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "ME Office 700FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface not supported
all-in-one
overseas version of the PX-601F" :model "ME OFFICE 900WD Series" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "ME OFFICE 940FW Series" :interface "USB" :usbid "0x04b8" "0x0890" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME OFFICE 960FWD Series" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME-101" :interface "USB" :usbid "0x04b8" "0x08a0" :status :complete :comment "all-in-one" :model "ME-301" :interface "USB" :usbid "0x04b8" "0x0896" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "ME-303" :interface "USB" :usbid "0x04b8" "0x0897" :status :complete :comment "all-in-one
overseas version of the PX-405A" :model "ME-401" :interface "USB" :usbid "0x04b8" "0x0898" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" :model "PM-A700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0814" :status :good :comment "all-in-one" :model "PM-A750" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one" :model "PM-A820" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one" :model "PM-A840" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one" :model "PM-A840S" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "network interface not supported
all-in-one" :model "PM-A850" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0806" :status :good :comment "all-in-one" :model "PM-A870" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one" :model "PM-A890" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one" :model "PM-A900" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0810" :status :good :comment "all-in-one" :model "PM-A920" :interface "USB" :usbid "0x04b8" "0x082a" :status :good :comment "all-in-one" :model "PM-A940" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one" :model "PM-A950" :interface "USB" :usbid "0x04b8" "0x081d" :status :good :comment "all-in-one" :model "PM-A970" :interface "USB" :usbid "0x04b8" "0x0828" :status :good :comment "all-in-one" :model "PM-T960" :interface "USB" :usbid "0x04b8" "0x0836" :status :good :comment "all-in-one" :model "PM-T990" :interface "USB" :usbid "0x04b8" "0x0829" :status :good :comment "all-in-one
PM-A970 with network interface" :model "PX-045A" :interface "USB" :usbid "0x04b8" "0x0895" :status :complete :comment "all-in-one" :model "PX-046A" :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-047A" :interface "USB" :usbid "0x04b8" "0x08c0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-1600F" :interface "USB" :usbid "0x04b8" "0x0869" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-1700F" :interface "USB" :usbid "0x04b8" "0x087c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-401A" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one" :model "PX-402A" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one" :model "PX-403A" :interface "USB" :usbid "0x04b8" "0x087f" :status :complete :comment "all-in-one" :model "PX-404A" :interface "USB" :usbid "0x04b8" "0x0881" :status :complete :comment "all-in-one" :model "PX-405A" :interface "USB" :usbid "0x04b8" "0x0897" :status :complete :comment "all-in-one" :model "PX-434A" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-435A" :interface "USB" :usbid "0x04b8" "0x0898" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-436A" :interface "USB" :usbid "0x04b8" "0x08af" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-437A" :interface "USB" :usbid "0x04b8" "0x08bf" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-501A" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface not supported
all-in-one" :model "PX-502A" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one" :model "PX-503A" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-504A" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-505F" :interface "USB" :usbid "0x04b8" "0x08a5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-535F" :interface "USB" :usbid "0x04b8" "0x08a6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-601F" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface not supported" :model "PX-602F" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-603F" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-605F" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-673F" :interface "USB" :usbid "0x04b8" "0x086a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-675F" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-A550" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one" :model "PX-A620" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one" :model "PX-A640" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one" :model "PX-A650" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one" :model "PX-A720" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one" :model "PX-A740" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one" :model "PX-B750F" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-FA700" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one" :model "PX-M350F" :interface "USB" :usbid "0x04b8" "0x08d0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M5040F" :interface "USB" :usbid "0x04b8" "0x08b9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M5041F" :interface "USB" :usbid "0x04b8" "0x08b9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M650A" :interface "USB" :usbid "0x04b8" "0x08c3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M650F" :interface "USB" :usbid "0x04b8" "0x08c3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M740F" :interface "USB" :usbid "0x04b8" "0x08b8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M741F" :interface "USB" :usbid "0x04b8" "0x08b8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "PX-M840F" :interface "USB" :usbid "0x04b8" "0x08bd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Perfection 600" :interface "SCSI" :status :unsupported :comment "supported by the umax backend
rebadged UMAX Astra 1200S" :model "Perfection 610" ; command spec :interface "USB" :usbid "0x04b8" "0x0103" :status :complete :comment "overseas version of the GT-6600U" :model "Perfection 636S" :interface "SCSI" :status :complete :comment "overseas version of the GT-7000S" :scsi "EPSON" "Perfection636" "processor" :model "Perfection 636U" ; command spec :interface "USB" :usbid "0x04b8" "0x0101" :status :complete :comment "overseas version of the GT-7000U" :model "Perfection 640U" ; command spec :interface "USB" :usbid "0x04b8" "0x010c" :status :complete :comment "overseas version of the GT-6700U" :model "Perfection 660" :interface "USB" :usbid "0x04b8" "0x0114" :status :unsupported :comment "supported by the snapscan backend" :model "Perfection 1200S" ; command spec :interface "SCSI" :status :complete :comment "overseas version of the GT-7600S" :scsi "EPSON" "Perfection1200" "processor" :model "Perfection 1200U" ; command spec :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "overseas version of the GT-7600U" :model "Perfection 1200U PHOTO" :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "Perfection 1200U with TPU option bundled
overseas version of the GT-7600UF" :model "Perfection 1240U" ; command spec :interface "USB" :usbid "0x04b8" "0x010b" :status :complete :comment "overseas version of the GT-7700U" :model "Perfection 1250" :interface "USB" :usbid "0x04b8" "0x010f" :status :good :comment "requires DFSG non-free iscan-plugin-gt-7200
also supported by the plustek backend
overseas version of the GT-7200U" :model "Perfection 1250 PHOTO" :interface "USB" :usbid "0x04b8" "0x010f" :status :good :comment "requires DFSG non-free iscan-plugin-gt-7200
also supported by the plustek backend
Perfection 1250 with TPU option bundled" :model "Perfection 1260" :interface "USB" :usbid "0x04b8" "0x011d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-7300
also supported by the plustek backend
overseas version of the GT-7300U" :model "Perfection 1260 PHOTO" :interface "USB" :usbid "0x04b8" "0x011d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-7300
also supported by the plustek backend
Perfection 1260 with TPU option bundled" :model "Perfection 1270" :interface "USB" :usbid "0x04b8" "0x0120" :status :unsupported :comment "supported by the snapscan backend
overseas version of the GT-7400" :model "Perfection 1600" :interface "SCSI" :status :unsupported :model "Perfection 1640SU" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :complete :comment "overseas version of the GT-8700" :model "Perfection 1640SU PHOTO" :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :good :comment "overseas version of the GT-8700F" :model "Perfection 1650" ; command spec :interface "USB" :usbid "0x04b8" "0x0110" :status :complete :comment "overseas version of the GT-8200U" :model "Perfection 1650 PHOTO" :interface "USB" :usbid "0x04b8" "0x0110" :status :good :comment "overseas version of the GT-8200UF" :model "Perfection 1660 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x011e" :status :complete :comment "overseas version of the GT-8300UF" :model "Perfection 1670" :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :comment "supported by the snapscan backend" :model "Perfection 1670 PHOTO" :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :comment "supported by the snapscan backend
overseas version of the GT-8400UF" :model "Perfection 2400 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x011b" :status :complete :comment "overseas version of the GT-9300UF" :model "Perfection 2450 PHOTO" ; command spec :interface "USB IEEE1394" :usbid "0x04b8" "0x0112" :scsi "EPSON" "GT-9700" "processor" :status :complete :comment "overseas version of the GT-9700F" :model "Perfection 2480 PHOTO" :interface "USB" :usbid "0x04b8" "0x0121" :status :good :comment "multi photo feeder not supported
requires DFSG non-free iscan-plugin-gt-f500
also supported by the snapscan backend
overseas version of the GT-F500" :model "Perfection 2580 PHOTO" :interface "USB" :usbid "0x04b8" "0x0121" :status :good :comment "auto film loader not supported
requires DFSG non-free iscan-plugin-gt-f500
also supported by the snapscan backend
overseas version of the GT-F550" :model "Perfection 3170 PHOTO" :interface "USB" :usbid "0x04b8" "0x0116" :status :good :comment "requires DFSG non-free iscan-plugin-gt-9400
overseas version of the GT-9400UF" :model "Perfection 3200 PHOTO" ; command spec :interface "USB IEEE1394" :usbid "0x04b8" "0x011c" :scsi "EPSON" "GT-9800" "processor" :status :complete :comment "overseas version of the GT-9800F" :model "Perfection 3490 PHOTO" :interface "USB" :usbid "0x04b8" "0x0122" :status :good :comment "multi photo feeder not supported
requires DFSG non-free iscan-plugin-gt-f520
also supported by the snapscan backend
overseas version of the GT-F520" :model "Perfection 3590 PHOTO" :interface "USB" :usbid "0x04b8" "0x0122" :status :good :comment "auto film loader not supported
requires DFSG non-free iscan-plugin-gt-f520
also supported by the snapscan backend
overseas version of the GT-F570" :model "Perfection 4180 PHOTO" :interface "USB" :usbid "0x04b8" "0x0118" :status :good :comment "only scans up to 2400dpi
requires DFSG non-free iscan-plugin-gt-f600
overseas version of the GT-F600" :model "Perfection 4490 PHOTO" :interface "USB" :usbid "0x04b8" "0x0119" :status :good :comment "requires DFSG non-free iscan-plugin-gt-x750
overseas version of the GT-X750" :model "Perfection 4870 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x0128" :status :complete :comment "IEEE1394 untested
overseas version of the GT-X700" :model "Perfection 4990 PHOTO" :interface "USB" :usbid "0x04b8" "0x012a" :status :good :comment "film area guide mode not supported
IEEE1394 untested
overseas version of the GT-X800" :model "Perfection 4990 Pro" :interface "USB IEEE1394" :status :untested :comment "seems to be a 4990 PHOTO with additional software" :model "Perfection V10" :interface "USB" :usbid "0x04b8" "0x012d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-s600
overseas version of the GT-S600" :model "Perfection V19" :interface "USB" :usbid "0x04b8" "0x013c" :status :good :comment "requires DFSG non-free iscan-plugin-gt-s650" :model "Perfection V30" :interface "USB" :usbid "0x04b8" "0x0131" :status :good :comment "requires DFSG non-free esci-interpreter-gt-f720
overseas version of the GT-S620" :model "Perfection V33" :interface "USB" :usbid "0x04b8" "0x0142" :status :good :comment "requires DFSG non-free esci-interpreter-perfection-v330
overseas version of the GT-S630" :model "Perfection V37" :interface "USB" :usbid "0x04b8" "0x014a" :status :good :comment "requires DFSG non-free iscan-plugin-perfection-v370
overseas version of the GT-S640" :model "Perfection V39" :interface "USB" :usbid "0x04b8" "0x013d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-s650
overseas version of the GT-S650" :model "Perfection V100 Photo" :interface "USB" :usbid "0x04b8" "0x012d" :status :good :comment "requires DFSG non-free iscan-plugin-gt-s600
overseas version of the GT-F650" :model "Perfection V200 Photo" :interface "USB" :usbid "0x04b8" "0x012e" :status :good :comment "requires DFSG non-free iscan-plugin-gt-f670
overseas version of the GT-F670" :model "Perfection V300 Photo" :interface "USB" :usbid "0x04b8" "0x0131" :status :good :comment "requires DFSG non-free esci-interpreter-gt-f720
overseas version of the GT-F720" :model "Perfection V330 Photo" :interface "USB" :usbid "0x04b8" "0x0142" :status :good :comment "requires DFSG non-free esci-interpreter-perfection-v330
overseas version of the GT-F730" :model "Perfection V370 Photo" :interface "USB" :usbid "0x04b8" "0x014a" :status :good :comment "requires DFSG non-free iscan-plugin-perfection-v370
overseas version of the GT-F740" :model "Perfection V350 Photo" :interface "USB" :usbid "0x04b8" "0x012f" :status :good :comment "auto film loader not supported
requires DFSG non-free iscan-plugin-gt-f700
overseas version of the GT-F700" :model "Perfection V500 Photo" :interface "USB" :usbid "0x04b8" "0x0130" :status :good :comment "requires DFSG non-free iscan-plugin-gt-x770
overseas version of the GT-X770" :model "Perfection V550 Photo" :interface "USB" :usbid "0x04b8" "0x013b" :status :good :comment "requires DFSG non-free iscan-plugin-perfection-v550" :model "Perfection V600 Photo" :interface "USB" :usbid "0x04b8" "0x013a" :status :good :comment "requires DFSG non-free iscan-plugin-gt-x820
overseas version of the GT-X820" :model "Perfection V700 Photo" :interface "USB" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested
overseas version of the GT-X900" :scsi "EPSON" "GT-X900" "processor" :model "Perfection V750 Photo" :interface "USB" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested
overseas version of the GT-X900" :scsi "EPSON" "GT-X900" "processor" :model "Perfection V800 Photo" :interface "USB" :usbid "0x04b8" "0x0151" :status :good :model "Perfection V850 Pro" :interface "USB" :usbid "0x04b8" "0x0151" :status :good :comment "overseas version of the GT-X980" :model "Stylus CX1500" ; Australia :interface "USB" :usbid "0x04b8" "0x080c" :status :unsupported :comment "supported by the snapscan backend
all-in-one" :model "Stylus CX2800" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "Stylus CX2900" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "Stylus CX3100" :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one
overseas version of the CC-570L" :model "Stylus CX3200" :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one
overseas version of the CC-570L" :model "Stylus CX3500" ; Australia :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one
overseas version of the PX-A550" :model "Stylus CX3600" ; UK :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one
overseas version of the PX-A550" :model "Stylus CX3650" ; France :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one" :model "Stylus CX3700" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus CX3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus CX3810" :interface "USB" :status :untested :comment "all-in-one" :model "Stylus CX3900" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one
overseas version of the PX-A620" :model "Stylus CX4100" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus CX4200" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus CX4300" :interface "USB" :usbid "0x04b8" "0x083f" :status :good :comment "all-in-one
requires DFSG non-free iscan-plugin-cx4400" :model "Stylus CX4400" :interface "USB" :usbid "0x04b8" "0x083f" :status :good :comment "all-in-one
requires DFSG non-free iscan-plugin-cx4400" :model "Stylus CX4500" :interface "USB" :usbid "0x04b8" "0x080d" :status :good :comment "all-in-one" :model "Stylus CX4600" :interface "USB" :usbid "0x04b8" "0x080d" :status :good :comment "all-in-one" :model "Stylus CX4700" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus CX4800" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus CX4900" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus CX5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus CX5100" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one
overseas version of the CC-600PX" :model "Stylus CX5200" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one
overseas version of the CC-600PX" :model "Stylus CX5300" :interface "USB" :usbid "0x04b8" "0x0808" :status :good :comment "all-in-one" :model "Stylus CX5400" :interface "USB" :usbid "0x04b8" "0x0808" :status :good :comment "all-in-one" :model "Stylus CX5500" :interface "USB" :usbid "0x04b8" "0x083f" :status :good :comment "all-in-one
requires DFSG non-free iscan-plugin-cx4400" :model "Stylus CX5600" :interface "USB" :usbid "0x04b8" "0x083f" :status :good :comment "all-in-one
requires DFSG non-free iscan-plugin-cx4400" :model "Stylus CX5700F" :interface "USB" :usbid "0x04b8" "0x0821" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX5800F" :interface "USB" :usbid "0x04b8" "0x0821" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX5900" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus CX6000" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus CX6300" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :comment "all-in-one
mistakenly thinks its a PX-A650" :model "Stylus CX6400" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :comment "all-in-one
mistakenly thinks its a PX-A650" :model "Stylus CX6500" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :comment "all-in-one" :model "Stylus CX6600" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :comment "all-in-one" :model "Stylus CX6900F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX7000F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX7300" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus CX7400" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus CX7700" :interface "USB" :usbid "0x04b8" "0x081f" :status :good :comment "all-in-one" :model "Stylus CX7800" :interface "USB" :usbid "0x04b8" "0x081f" :status :good :comment "all-in-one" :model "Stylus CX8300" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus CX8400" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus CX9300F" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus CX9400Fax" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus DX3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus DX3850" :interface "USB" ;:usbid "0x04b8" "0x0818" ; not confirmed :status :good :comment "all-in-one" :model "Stylus DX4000" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one
overseas version of the PX-A620" :model "Stylus DX4200" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus DX4400" :interface "USB" :usbid "0x04b8" "0x083f" :status :good :comment "all-in-one
requires DFSG non-free iscan-plugin-cx4400" :model "Stylus DX4800" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus DX4850" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
DX4800 + card reader" :model "Stylus DX5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus DX6000" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus DX7000F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus DX7400" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus DX8400" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus DX9400F" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus Office BX300F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX305F" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX305FW" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX305FW Plus" :interface "USB" :usbid "0x04b8" "0x0870" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX310FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "Stylus Office BX320FW Series" :interface "USB" :usbid "0x04b8" "0x085f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX535WD" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" :model "Stylus Office BX630FW Series" :interface "USB" :usbid "0x04b8" "0x0890" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX525WD" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "Stylus Office BX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface not supported
all-in-one
overseas version of the PX-601F" :model "Stylus Office BX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" :model "Stylus Office BX625FWD" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX635FWD" :interface "USB" :usbid "0x04b8" "0x088f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office BX925FWD" :interface "USB" :usbid "0x04b8" "0x086a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-673F" :model "Stylus Office BX935FWD" :interface "USB" :usbid "0x04b8" "0x0892" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX300F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX320F Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX510FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "Stylus Office TX525FW" :interface "USB" :usbid "0x04b8" "0x085f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Office TX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface not supported
all-in-one
overseas version of the PX-601F" :model "Stylus Office TX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" :model "Stylus Office TX620FWD Series" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Photo PX650 Series" :interface "USB" :usbid "0x04b8" "0x0850" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-702A" :model "Stylus Photo PX660 Series" :interface "USB" :usbid "0x04b8" "0x0862" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-703A" :model "Stylus Photo PX700W" :interface "USB" :usbid "0x04b8" "0x0846" :status :good :comment "network interface not supported
all-in-one
overseas version of the EP-801A" :model "Stylus Photo PX710W Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" :model "Stylus Photo PX720WD Series" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" :model "Stylus Photo PX730WD Series" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Stylus Photo PX800FW" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface not supported
all-in-one
overseas version of the EP-901A" :model "Stylus Photo PX810FW Series" :interface "USB" :usbid "0x04b8" "0x0853" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-902A" :model "Stylus Photo PX820FWD Series" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" :model "Stylus Photo PX830FWD Series" :interface "USB" :usbid "0x04b8" "0x0879" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-904F" :model "Stylus Photo RX420" :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX425" ; France :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX430" ; Australia :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX500" :interface "USB" :usbid "0x04b8" "0x0807" :status :good :comment "all-in-one" :model "Stylus Photo RX510" :interface "USB" :usbid "0x04b8" "0x0807" :status :good :comment "all-in-one" :model "Stylus Photo RX520" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one
overseas version of the PM-A750" :model "Stylus Photo RX530" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one
overseas version of the PM-A750" :model "Stylus Photo RX560" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX585" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX580" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX595" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX590" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX600" :interface "USB" :usbid "0x04b8" "0x0806" :status :good :comment "all-in-one
overseas version of the PM-A850" :model "Stylus Photo RX610" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX620" :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one
overseas version of the PM-A870" :model "Stylus Photo RX630" :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one
overseas version of the PM-A870" :model "Stylus Photo RX640" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one
overseas version of the PM-A890" :model "Stylus Photo RX650" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one
overseas version of the PM-A890" :model "Stylus Photo RX680" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX685" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX690" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX700" :interface "USB" :usbid "0x04b8" "0x0810" :status :good :comment "all-in-one
overseas version of the PM-A900" :model "Stylus Photo TX650 Series" :interface "USB" :usbid "0x04b8" "0x0850" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-702A" :model "Stylus Photo TX700W" :interface "USB" :usbid "0x04b8" "0x0846" :status :good :comment "network interface not supported
all-in-one
overseas version of the EP-801A" :model "Stylus Photo TX710W Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-802A" :model "Stylus Photo TX720WD Series" :interface "USB" :usbid "0x04b8" "0x0861" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-803A" :model "Stylus Photo TX730WD Series" :interface "USB" :usbid "0x04b8" "0x087b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-804A" :model "Stylus Photo TX800FW" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface not supported
all-in-one
overseas version of the EP-901A" :model "Stylus Photo TX820FWD Series" :interface "USB" :usbid "0x04b8" "0x0860" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-903A" :model "Stylus NX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus NX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus NX125" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "Stylus NX127" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "Stylus NX130 Series" :interface "USB" :usbid "0x04b8" "0x0883" :status :complete :comment "all-in-one" :model "Stylus NX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus NX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus NX220 Series" :interface "USB" :usbid "0x04b8" "0x0865" :status :complete :comment "all-in-one" :model "Stylus NX230 Series" :interface "USB" :usbid "0x04b8" "0x0885" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX300 Series" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX330 Series" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface not supported
all-in-one
overseas version of the PX-501A" :model "Stylus NX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface not supported
all-in-one" :model "Stylus NX420 Series" :interface "USB" :usbid "0x04b8" "0x0864" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX430W Series" :interface "USB" :usbid "0x04b8" "0x0884" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus NX510 Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "Stylus NX530 Series" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-504A" :model "Stylus NX625" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "Stylus NX635" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" :model "Stylus SX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus SX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus SX125" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "Stylus SX130 Series" :interface "USB" :usbid "0x04b8" "0x0883" :status :complete :comment "all-in-one" :model "Stylus SX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus SX205" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus SX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus SX218" :interface "USB" :usbid "0x04b8" "0x0865" :status :complete :comment "all-in-one" :model "Stylus SX230 Series" :interface "USB" :usbid "0x04b8" "0x0881" :status :complete :comment "all-in-one
overseas version of the PX-404A" :model "Stylus SX235W" :interface "USB" :usbid "0x04b8" "0x0885" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus SX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface not supported
all-in-one
overseas version of the PX-501A" :model "Stylus SX405" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "all-in-one" :model "Stylus SX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface not supported
all-in-one" :model "Stylus SX420W Series" :interface "USB" :usbid "0x04b8" "0x0864" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus SX430W Series" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus SX440W Series" :interface "USB" :usbid "0x04b8" "0x0884" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus SX510W Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "Stylus SX525WD" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "Stylus SX535WD" :interface "USB" :usbid "0x04b8" "0x0891" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
overseas version of the PX-504A" :model "Stylus SX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface not supported
all-in-one
overseas version of the PX-601F" :model "Stylus SX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" :model "Stylus SX620FW Series" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus Scan 2000" :interface "USB" :usbid "0x04b8" "0x0105" :status :untested :comment "apparently mostly the same as the Stylus Scan 2500" :model "Stylus Scan 2500" :interface "USB" :usbid "0x04b8" "0x0106" :status :untested :comment "scanner is apparently a GT-7000" :model "Stylus TX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus TX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus TX120 Series" :interface "USB" :usbid "0x04b8" "0x085c" :status :complete :comment "all-in-one" :model "Stylus TX130 Series" :interface "USB" :usbid "0x04b8" "0x0883" :status :complete :comment "all-in-one" :model "Stylus TX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX203" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX209" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus TX220 Series" :interface "USB" :usbid "0x04b8" "0x0865" :status :complete :comment "all-in-one" :model "Stylus TX230W Series" :interface "USB" :usbid "0x04b8" "0x0885" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus TX235" :interface "USB" :usbid "0x04b8" "0x0881" :status :complete :comment "all-in-one
overseas version of the PX-404A" :model "Stylus TX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface not supported
all-in-one
overseas version of the PX-501A" :model "Stylus TX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface not supported
all-in-one" :model "Stylus TX420W Series" :interface "USB" :usbid "0x04b8" "0x0864" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus TX430W Series" :interface "USB" :usbid "0x04b8" "0x0880" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus TX435W" :interface "USB" :usbid "0x04b8" "0x0884" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "Stylus TX550W Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "Stylus TX560WD Series" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "WF-2510 Series" :interface "USB" :usbid "0x04b8" "0x08a5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-505F" :model "WF-2520 Series" :interface "USB" :usbid "0x04b8" "0x08a6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" :model "WF-2530 Series" :interface "USB" :usbid "0x04b8" "0x08a6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" :model "WF-2540 Series" :interface "USB" :usbid "0x04b8" "0x08a6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-535F" :model "WF-2630 Series" :interface "USB" :usbid "0x04b8" "0x08c4" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-2650 Series" :interface "USB" :usbid "0x04b8" "0x08c3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-2660 Series" :interface "USB" :usbid "0x04b8" "0x08c3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-3520 Series" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-605F" :model "WF-3530 Series" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-675F" :model "WF-3540 Series" :interface "USB" :usbid "0x04b8" "0x0899" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-3620 Series" :interface "USB" :usbid "0x04b8" "0x08b8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M740F" :model "WF-3640 Series" :interface "USB" :usbid "0x04b8" "0x08b8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M741F" :model "WF-4630 Series" :interface "USB" :usbid "0x04b8" "0x08be" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-4640 Series" :interface "USB" :usbid "0x04b8" "0x08be" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-5620 Series" :interface "USB" :usbid "0x04b8" "0x08bd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M840F" :model "WF-5690 Series" :interface "USB" :usbid "0x04b8" "0x08bd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-7510 Series" :interface "USB" :usbid "0x04b8" "0x0869" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-1600F" :model "WF-7520 Series" :interface "USB" :usbid "0x04b8" "0x087c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-1700F" :model "WF-7610 Series" :interface "USB" :usbid "0x04b8" "0x08b9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M5040F" :model "WF-7620 Series" :interface "USB" :usbid "0x04b8" "0x08b9" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M5041F" :model "WF-M1560 Series" :interface "USB" :usbid "0x04b8" "0x08ab" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-M5690 Series" :interface "USB" :usbid "0x04b8" "0x08d0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-M350F" :model "WF-R4640 Series" :interface "USB" :usbid "0x04b8" "0x08cd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WF-R5690 Series" :interface "USB" :usbid "0x04b8" "0x08cd" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WP-4511" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4515" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WP-4521" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4525" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4530 Series" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4540 Series" :interface "USB" :usbid "0x04b8" "0x087d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-B750F" :model "WP-4590 Series" :interface "USB" :usbid "0x04b8" "0x087e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 310 Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "WorkForce 320 Series" :interface "USB" :usbid "0x04b8" "0x0863" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
some models in the series have a built-in network interface
all-in-one" :model "WorkForce 435" :interface "USB" :usbid "0x04b8" "0x0870" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 500" :interface "USB" :usbid "0x04b8" "0x084c" :status :good :comment "all-in-one" :model "WorkForce 520 Series" :interface "USB" :usbid "0x04b8" "0x085f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 545" :interface "USB" :usbid "0x04b8" "0x0890" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 600" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface not supported
all-in-one
overseas version of the PX-601F" :model "WorkForce 610 Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-602F" :model "WorkForce 625" :interface "USB" :usbid "0x04b8" "0x085e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-503A" :model "WorkForce 630 Series" :interface "USB" :usbid "0x04b8" "0x085d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 645" :interface "USB" :usbid "0x04b8" "0x088f" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce 840 Series" :interface "USB" :usbid "0x04b8" "0x086a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-673F" :model "WorkForce 845" :interface "USB" :usbid "0x04b8" "0x0892" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "WorkForce K301" :interface "USB" :usbid "0x04b8" "0x0872" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-100 Series" :interface "USB" :usbid "0x04b8" "0x0895" :status :complete :comment "all-in-one
overseas version of the PX-045A" :model "XP-200 Series" :interface "USB" :usbid "0x04b8" "0x0896" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-211" :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-046A" :model "XP-212" :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-046A" :model "XP-215" :interface "USB" :usbid "0x04b8" "0x08ae" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-046A" :model "XP-225" :interface "USB" :usbid "0x04b8" "0x08c0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-047A" :model "XP-300 Series" :interface "USB" :usbid "0x04b8" "0x0898" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" :model "XP-310 Series" :interface "USB" :usbid "0x04b8" "0x08af" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-436A" :model "XP-320 Series" :interface "USB" :usbid "0x04b8" "0x08bf" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-437A" :model "XP-400 Series" :interface "USB" :usbid "0x04b8" "0x0898" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the PX-435A" :model "XP-410 Series" :interface "USB" :usbid "0x04b8" "0x08b0" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-420 Series" :interface "USB" :usbid "0x04b8" "0x08c1" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-600 Series" :interface "USB" :usbid "0x04b8" "0x089e" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-775A" :model "XP-510 Series" :interface "USB" :usbid "0x04b8" "0x08b7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-706A" :model "XP-520 Series" :interface "USB" :usbid "0x04b8" "0x08c8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-777A" :model "XP-610 Series" :interface "USB" :usbid "0x04b8" "0x08b6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-776AB/EP-776AW" :model "XP-620 Series" :interface "USB" :usbid "0x04b8" "0x08c8" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-777A" :model "XP-700 Series" :interface "USB" :usbid "0x04b8" "0x089d" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one" :model "XP-710 Series" :interface "USB" :usbid "0x04b8" "0x08b5" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-806AB/EP-806AR/EP-806AW" :model "XP-720 Series" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-807AB/EP-807AR/EP-807AW" :model "XP-750 Series" :interface "USB" :usbid "0x04b8" "0x089c" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-805A/EP-805AR/EP-805AW" :model "XP-760 Series" :interface "USB" :usbid "0x04b8" "0x08c7" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-807AB/EP-807AR/EP-807AW" :model "XP-800 Series" :interface "USB" :usbid "0x04b8" "0x089b" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-905A" :model "XP-810 Series" :interface "USB" :usbid "0x04b8" "0x08b4" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-906F" :model "XP-820 Series" :interface "USB" :usbid "0x04b8" "0x08c6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-907F" :model "XP-850 Series" :interface "USB" :usbid "0x04b8" "0x089a" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-905F" :model "XP-860 Series" :interface "USB" :usbid "0x04b8" "0x08c6" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-907F" :model "XP-950 Series" :interface "USB" :usbid "0x04b8" "0x08b3" :status :complete :comment "network interface supported via DFSG non-free iscan-network-nt package
all-in-one
overseas version of the EP-976A3" sane-backends-1.0.27/doc/descriptions-external/hpaio.desc0000664000175000017500000013261312775312261020271 00000000000000; ; SANE Backend specification file ; :backend "hpaio" ; name of backend :version "" ; version of backend :url "http://hpinkjet.sourceforge.net/" ; backend's web page :comment "This backend isn't included in SANE because it is included in the HPLIP software." :devicetype :scanner ; start of a list of devices.... :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/united-states/consumer/gateway/printing_multifunction.html" :model "HP Officejet v30 All-in-one Printer" :status :good :model "HP Officejet v40xi All-in-one Printer" :status :good :model "HP Officejet v40s All-in-one Printer" :status :good :model "HP Officejet r40 All-in-one Printer" :status :good :model "HP Officejet v40 All-in-one Printer" :status :good :model "HP Officejet r40xi All-in-one Printer" :status :good :model "HP Officejet t45xi All-in-one Printer" :status :good :model "HP Officejet r45 All-in-one Printer" :status :good :model "HP Officejet v45 All-in-one Printer" :status :good :model "HP Officejet t45 All-in-one Printer" :status :good :model "HP Officejet g55 All-in-one Printer" :status :good :model "HP Officejet g55xi All-in-one Printer" :status :good :model "HP Officejet k60 All-in-one Printer" :status :good :model "HP Officejet r60 All-in-one Printer" :status :good :model "HP Officejet k60xi All-in-one Printer" :status :good :model "HP Officejet t65xi All-in-one Printer" :status :good :model "HP Officejet t65 All-in-one Printer" :status :good :model "HP Officejet r65 All-in-one Printer" :status :good :model "HP Officejet k80 All-in-one Printer" :status :good :model "HP Officejet k80xi All-in-one Printer" :status :good :model "HP Officejet r80xi All-in-one Printer" :status :good :model "HP Officejet r80 All-in-one Printer" :status :good :model "HP Officejet g85 All-in-one Printer" :status :good :model "HP Officejet g85xi All-in-one Printer" :status :good :model "HP Officejet g95 All-in-one Printer" :status :good :model "HP Photosmart All-in-one Printer - b109d" :status :good :model "HP Photosmart All-in-one Printer - b109e" :status :good :model "HP Photosmart All-in-one Printer - b109c" :status :good :model "HP Photosmart All-in-one Printer - b109a" :status :good :model "HP Photosmart Wireless All-in-one Printer - b109q" :status :good :model "HP Photosmart Wireless All-in-one Printer - b109n" :status :good :model "HP Photosmart Wireless All-in-one Printer - b109q=r" :status :good :model "HP Officejet d125xi All-in-one Printer" :status :good :model "HP Officejet d135 All-in-one Printer" :status :good :model "HP Officejet d135xi All-in-one Printer" :status :good :model "HP Officejet d145xi All-in-one Printer" :status :good :model "HP Officejet d145 All-in-one Printer" :status :good :model "HP Officejet d155xi All-in-one Printer" :status :good :model "HP Deskjet Ink Advantage k209a All-in-one Printer" :status :good :model "HP Photosmart Plus All-in-one Printer - b209a" :status :good :model "HP Photosmart Plus All-in-one Printer - b209b" :status :good :model "HP Photosmart Plus All-in-one Printer - b209c" :status :good :model "HP Printer Scanner Copier 300" :status :good :model "HP Photosmart Premium All-in-one Printer Series - c309h" :status :good :model "HP Photosmart Premium All-in-one Printer Series - c309g" :status :good :model "HP Photosmart Premium Fax All-in-one Printer - c309a" :status :good :model "HP Photosmart Premium Fax All-in-one Printer Series -c309c" :status :good :model "HP Photosmart Premium Fax All-in-one Printer Series -c309a" :status :good :model "HP Deskjet f310 All-in-one Printer" :status :good :model "HP Deskjet f325 All-in-one Printer" :status :good :model "HP Deskjet f335 All-in-one Printer" :status :good :model "HP Deskjet f340 All-in-one Printer" :status :good :model "HP Deskjet f350 All-in-one Printer" :status :good :model "HP Deskjet f370 All-in-one Printer" :status :good :model "HP Deskjet f375 All-in-one Printer" :status :good :model "HP Deskjet f378 All-in-one Printer" :status :good :model "HP Deskjet f379 All-in-one Printer" :status :good :model "HP Deskjet f380 All-in-one Printer" :status :good :model "HP Deskjet f385 All-in-one Printer" :status :good :model "HP Deskjet f388 All-in-one Printer" :status :good :model "HP Deskjet f390 All-in-one Printer" :status :good :model "HP Deskjet f394 All-in-one Printer" :status :good :model "HP PSC 500xi All-in-one Printer" :status :good :model "HP PSC 500 All-in-one Printer" :status :good :model "HP Officejet 500 All-in-one Printer" :status :good :model "HP Officejet 520 All-in-one Printer" :status :good :model "HP Officejet 570 All-in-one Printer" :status :good :model "HP Officejet 580 All-in-one Printer" :status :good :model "HP Officejet 590 All-in-one Printer" :status :good :model "HP Officejet 600 All-in-one Printer" :status :good :model "HP Officejet 610 All-in-one Printer" :status :good :model "HP Officejet 630 All-in-one Printer" :status :good :model "HP Officejet 635 All-in-one Printer" :status :good :model "HP Officejet 700 All-in-one Printer" :status :good :model "HP Officejet 710 All-in-one Printer" :status :good :model "HP PSC 720 All-in-one Printer" :status :good :model "HP Officejet 720 All-in-one Printer" :status :good :model "HP Officejet 725 All-in-one Printer" :status :good :model "HP Deskjet f735 All-in-one Printer" :status :good :model "HP PSC 750 All-in-one Printer" :status :good :model "HP PSC 750xi All-in-one Printer" :status :good :model "HP PSC 760 All-in-one Printer" :status :good :model "HP PSC 780 All-in-one Printer" :status :good :model "HP PSC 780xi All-in-one Printer" :status :good :model "HP PSC 900 All-in-one Printer" :status :good :model "HP 915 Inkjet All-in-one Printer" :status :good :model "HP PSC 920 All-in-one Printer" :status :good :model "HP PSC 950 All-in-one Printer" :status :good :model "HP PSC 950vr All-in-one Printer" :status :good :model "HP PSC 950xi All-in-one Printer" :status :good :model "HP LaserJet m1005 Multifunction Printer" :status :good :model "HP Color LaserJet cm1015 Multifunction Printer" :status :good :model "HP Color LaserJet cm1017 Multifunction Printer" :status :good :model "HP LaserJet 1100a Xi All-in-one Printer" :status :good :model "HP LaserJet 1100xi Printer" :status :good :model "HP LaserJet 1100a All-in-one Printer" :status :good :model "HP LaserJet 1100 Printer" :status :good :model "HP LaserJet 1100a Se All-in-one Printer" :status :good :model "HP LaserJet 1100se Printer" :status :good :model "HP PSC 1110v All-in-one Printer" :status :good :model "HP PSC 1110 All-in-one Printer" :status :good :model "HP PSC 1118 All-in-one Printer" :status :good :model "HP LaserJet m1120 Multifunction Printer" :status :good :model "HP LaserJet m1120n Multifunction Printer" :status :good :model "HP Officejet Pro 1150c All-in-one Printer" :status :good :model "HP Officejet Pro 1150cse All-in-one Printer" :status :good :model "HP Officejet Pro 1170cse All-in-one Printer" :status :good :model "HP Officejet Pro 1170c All-in-one Printer" :status :good :model "HP Officejet Pro 1170cxi All-in-one Printer" :status :good :model "HP Officejet Pro 1175cxi All-in-one Printer" :status :good :model "HP Officejet Pro 1175cse All-in-one Printer" :status :good :model "HP Officejet Pro 1175c All-in-one Printer" :status :good :model "HP PSC 1200 All-in-one Printer" :status :good :model "HP PSC 1205 All-in-one Printer" :status :good :model "HP PSC 1209 All-in-one Printer" :status :good :model "HP PSC 1210xi All-in-one Printer" :status :good :model "HP PSC 1210v All-in-one Printer" :status :good :model "HP PSC 1210 All-in-one Printer" :status :good :model "HP PSC 1213 All-in-one Printer" :status :good :model "HP PSC 1215 All-in-one Printer" :status :good :model "HP PSC 1216 All-in-one Printer" :status :good :model "HP PSC 1217 All-in-one Printer" :status :good :model "HP PSC 1218 All-in-one Printer" :status :good :model "HP PSC 1219 All-in-one Printer" :status :good :model "HP LaserJet 1220 All-in-one Printer" :status :good :model "HP LaserJet 1220se All-in-one Printer" :status :good :model "HP PSC 1300 All-in-one Printer" :status :good :model "HP PSC 1310 All-in-one Printer" :status :good :model "HP PSC 1311 All-in-one Printer" :status :good :model "HP Color LaserJet cm1312 Multifunction Printer" :status :good :model "HP Color LaserJet cm1312nfi Multifunction Printer" :status :good :model "HP PSC 1312 All-in-one Printer" :status :good :model "HP PSC 1315v All-in-one Printer" :status :good :model "HP PSC 1315s All-in-one Printer" :status :good :model "HP PSC 1315xi All-in-one Printer" :status :good :model "HP PSC 1315 All-in-one Printer" :status :good :model "HP PSC 1317 All-in-one Printer" :status :good :model "HP PSC 1318 All-in-one Printer" :status :good :model "HP LaserJet m1319f Multifunction Printer" :status :good :model "HP PSC 1340 All-in-one Printer" :status :good :model "HP PSC 1345 All-in-one Printer" :status :good :model "HP PSC 1350xi All-in-one Printer" :status :good :model "HP PSC 1350v All-in-one Printer" :status :good :model "HP PSC 1350 All-in-one Printer" :status :good :model "HP PSC 1355 All-in-one Printer" :status :good :model "HP PSC 1401 All-in-one Printer" :status :good :model "HP PSC 1402 All-in-one Printer" :status :good :model "HP PSC 1403 All-in-one Printer" :status :good :model "HP PSC 1406 All-in-one Printer" :status :good :model "HP PSC 1408 All-in-one Printer" :status :good :model "HP PSC 1410 All-in-one Printer" :status :good :model "HP PSC 1410v All-in-one Printer" :status :good :model "HP PSC 1410xi All-in-one Printer" :status :good :model "HP PSC 1415 All-in-one Printer" :status :good :model "HP PSC 1417 All-in-one Printer" :status :good :model "HP PSC 1503 All-in-one Printer" :status :good :model "HP PSC 1504 All-in-one Printer" :status :good :model "HP PSC 1507 All-in-one Printer" :status :good :model "HP PSC 1508 All-in-one Printer" :status :good :model "HP PSC 1510s All-in-one Printer" :status :good :model "HP PSC 1510xi All-in-one Printer" :status :good :model "HP PSC 1510 All-in-one Printer" :status :good :model "HP PSC 1510v All-in-one Printer" :status :good :model "HP PSC 1513s All-in-one Printer" :status :good :model "HP PSC 1513 All-in-one Printer" :status :good :model "HP PSC 1514 All-in-one Printer" :status :good :model "HP LaserJet m1522n Multifunction Printer" :status :good :model "HP LaserJet m1522nf Multifunction Printer" :status :good :model "HP LaserJet m1522 Multifunction Printer" :status :good :model "HP PSC 1600 All-in-one Printer" :status :good :model "HP PSC 1603 All-in-one Printer" :status :good :model "HP PSC 1605 All-in-one Printer" :status :good :model "HP PSC 1608 All-in-one Printer" :status :good :model "HP PSC 1610 All-in-one Printer" :status :good :model "HP PSC 1610xi All-in-one Printer" :status :good :model "HP PSC 1610v All-in-one Printer" :status :good :model "HP PSC 1613 All-in-one Printer" :status :good :model "HP PSC 1615 All-in-one Printer" :status :good :model "HP PSC 2105 All-in-one Printer" :status :good :model "HP PSC 2108 All-in-one Printer" :status :good :model "HP Deskjet f2110 All-in-one Printer" :status :good :model "HP PSC 2110 All-in-one Printer" :status :good :model "HP PSC 2110v All-in-one Printer" :status :good :model "HP PSC 2110xi All-in-one Printer" :status :good :model "HP PSC 2115 All-in-one Printer" :status :good :model "HP Deskjet f2120 All-in-one Printer" :status :good :model "HP Deskjet f2128 All-in-one Printer" :status :good :model "HP Deskjet f2140 All-in-one Printer" :status :good :model "HP PSC 2150 All-in-one Printer" :status :good :model "HP PSC 2170 All-in-one Printer" :status :good :model "HP PSC 2171 All-in-one Printer" :status :good :model "HP PSC 2175 All-in-one Printer" :status :good :model "HP PSC 2175v All-in-one Printer" :status :good :model "HP PSC 2175xi All-in-one Printer" :status :good :model "HP Deskjet f2179 All-in-one Printer" :status :good :model "HP PSC 2179 All-in-one Printer" :status :good :model "HP Deskjet f2180 All-in-one Printer" :status :good :model "HP Deskjet f2185 All-in-one Printer" :status :good :model "HP Deskjet f2187 All-in-one Printer" :status :good :model "HP Deskjet f2188 All-in-one Printer" :status :good :model "HP PSC 2200 All-in-one Printer" :status :good :model "HP PSC 2210 All-in-one Printer" :status :good :model "HP PSC 2210v All-in-one Printer" :status :good :model "HP PSC 2210xi All-in-one Printer" :status :good :model "HP Deskjet f2210 All-in-one Printer" :status :good :model "HP Deskjet f2212 All-in-one Printer" :status :good :model "HP Deskjet f2214 All-in-one Printer" :status :good :model "HP Deskjet f2224 All-in-one Printer" :status :good :model "HP Deskjet f2235 All-in-one Printer" :status :good :model "HP Deskjet f2238 All-in-one Printer" :status :good :model "HP Deskjet f2240 All-in-one Printer" :status :good :model "HP Deskjet f2250 All-in-one Printer" :status :good :model "HP Deskjet f2275 All-in-one Printer" :status :good :model "HP Deskjet f2276 All-in-one Printer" :status :good :model "HP Deskjet f2280 All-in-one Printer" :status :good :model "HP Deskjet f2288 All-in-one Printer" :status :good :model "HP Deskjet f2290 All-in-one Printer" :status :good :model "HP PSC 2300 Series All-in-one Printer" :status :good :model "HP PSC 2310 All-in-one Printer" :status :good :model "HP Color LaserJet cm2320n Multifunction Printer" :status :good :model "HP Color LaserJet cm2320nf Multifunction Printer" :status :good :model "HP Color LaserJet cm2320fxi Multifunction Printer" :status :good :model "HP Color LaserJet cm2320 Multifuntion Printer" :status :good :model "HP PSC 2350 All-in-one Printer" :status :good :model "HP PSC 2352 All-in-one Printer" :status :good :model "HP PSC 2353p All-in-one Printer" :status :good :model "HP PSC 2353 All-in-one Printer" :status :good :model "HP PSC 2355 All-in-one Printer" :status :good :model "HP PSC 2355p All-in-one Printer" :status :good :model "HP PSC 2355xi All-in-one Printer" :status :good :model "HP PSC 2355v All-in-one Printer" :status :good :model "HP PSC 2357 All-in-one Printer" :status :good :model "HP PSC 2358 All-in-one Printer" :status :good :model "HP PSC 2405 Photosmart All-in-one Printer" :status :good :model "HP PSC 2410v Photosmart All-in-one Printer" :status :good :model "HP PSC 2410xi Photosmart All-in-one Printer" :status :good :model "HP Deskjet f2410 All-in-one Printer" :status :good :model "HP PSC 2410 Photosmart All-in-one Printer" :status :good :model "HP Deskjet f2418 All-in-one Printer" :status :good :model "HP Deskjet f2420 All-in-one Printer" :status :good :model "HP PSC 2420 Photosmart All-in-one Printer" :status :good :model "HP Deskjet f2423 All-in-one Printer" :status :good :model "HP Deskjet f2430 All-in-one Printer" :status :good :model "HP Deskjet f2440 All-in-one Printer" :status :good :model "HP PSC 2450 Photosmart All-in-one Printer" :status :good :model "HP Deskjet f2476 All-in-one Printer" :status :good :model "HP Deskjet f2480 All-in-one Printer" :status :good :model "HP Deskjet f2483 All-in-one Printer" :status :good :model "HP Deskjet f2488 All-in-one Printer" :status :good :model "HP Deskjet f2492 All-in-one Printer" :status :good :model "HP Deskjet f2493 All-in-one Printer" :status :good :model "HP PSC 2500 Photosmart All-in-one Printer" :status :good :model "HP PSC 2510 Photosmart All-in-one Printer" :status :good :model "HP PSC 2510xi Photosmart All-in-one Printer" :status :good :model "HP PSC 2550 Photosmart All-in-one Printer" :status :good :model "HP Photosmart 2570 All-in-one Printer" :status :good :model "HP Photosmart 2571 All-in-one Printer" :status :good :model "HP Photosmart 2573 All-in-one Printer" :status :good :model "HP Photosmart 2574 All-in-one Printer" :status :good :model "HP Photosmart 2575a All-in-one Printer" :status :good :model "HP Photosmart 2575v All-in-one Printer" :status :good :model "HP Photosmart 2575xi All-in-one Printer" :status :good :model "HP Photosmart 2575 All-in-one Printer" :status :good :model "HP Photosmart 2578 All-in-one Printer" :status :good :model "HP Photosmart 2605 All-in-one Printer" :status :good :model "HP Photosmart 2608 All-in-one Printer" :status :good :model "HP Photosmart 2610 All-in-one Printer" :status :good :model "HP Photosmart 2610v All-in-one Printer" :status :good :model "HP Photosmart 2610xi All-in-one Printer" :status :good :model "HP Photosmart 2613 All-in-one Printer" :status :good :model "HP Photosmart 2615 All-in-one Printer" :status :good :model "HP Photosmart 2710 All-in-one Printer" :status :good :model "HP Photosmart 2710xi All-in-one Printer" :status :good :model "HP Photosmart 2713 All-in-one Printer" :status :good :model "HP LaserJet m2727nf Multifunction Printer" :status :good :model "HP LaserJet m2727 Multifunction Printer" :status :good :model "HP LaserJet m2727nfs Multifunction Printer" :status :good :model "HP Color LaserJet 2800 All-in-one Printer" :status :good :model "HP Color LaserJet 2820 All-in-one Printer" :status :good :model "HP Color LaserJet 2830 All-in-one Printer" :status :good :model "HP Color LaserJet 2840 All-in-one Printer" :status :good :model "HP LaserJet 3015 All-in-one Printer" :status :good :model "HP LaserJet 3020 All-in-one Printer" :status :good :model "HP LaserJet 3030 All-in-one Printer" :status :good :model "HP LaserJet m3035 Multifunction Printer" :status :good :model "HP LaserJet m3035xs Multifunction Printer" :status :good :model "HP LaserJet 3050z All-in-one Printer" :status :good :model "HP LaserJet 3050 All-in-one Printer" :status :good :model "HP LaserJet 3052 All-in-one Printer" :status :good :model "HP LaserJet 3055 All-in-one Printer" :status :good :model "HP LaserJet 3100xi All-in-one Printer" :status :good :model "HP LaserJet 3100se All-in-one Printer" :status :good :model "HP LaserJet 3100 All-in-one Printer" :status :good :model "HP Photosmart 3108 All-in-one Printer" :status :good :model "HP Photosmart 3110v All-in-one Printer" :status :good :model "HP Photosmart 3110 All-in-one Printer" :status :good :model "HP Photosmart c3110 All-in-one Printer" :status :good :model "HP Photosmart c3125 All-in-one Printer" :status :good :model "HP Photosmart c3135 All-in-one Printer" :status :good :model "HP Photosmart c3140 All-in-one Printer" :status :good :model "HP LaserJet 3150se All-in-one Printer" :status :good :model "HP Photosmart c3150 All-in-one Printer" :status :good :model "HP LaserJet 3150 All-in-one Printer" :status :good :model "HP LaserJet 3150xi All-in-one Printer" :status :good :model "HP Photosmart c3170 All-in-one Printer" :status :good :model "HP Photosmart c3173 All-in-one Printer" :status :good :model "HP Photosmart c3175 All-in-one Printer" :status :good :model "HP Photosmart c3180 All-in-one Printer" :status :good :model "HP Photosmart c3183 All-in-one Printer" :status :good :model "HP Photosmart c3188 All-in-one Printer" :status :good :model "HP Photosmart c3190 All-in-one Printer" :status :good :model "HP Photosmart c3193 All-in-one Printer" :status :good :model "HP Photosmart c3194 All-in-one Printer" :status :good :model "HP LaserJet 3200 All-in-one Printer" :status :good :model "HP LaserJet 3200m All-in-one Printer" :status :good :model "HP Photosmart 3207 All-in-one Printer" :status :good :model "HP Photosmart 3210a All-in-one Printer" :status :good :model "HP Photosmart 3210v All-in-one Printer" :status :good :model "HP Photosmart 3210xi All-in-one Printer" :status :good :model "HP Photosmart 3210 All-in-one Printer" :status :good :model "HP Photosmart 3213 All-in-one Printer" :status :good :model "HP Photosmart 3214 All-in-one Printer" :status :good :model "HP LaserJet 3300 Multifunction Printer" :status :good :model "HP Photosmart 3308 All-in-one Printer" :status :good :model "HP Photosmart 3310 All-in-one Printer" :status :good :model "HP Photosmart 3310xi All-in-one Printer" :status :good :model "HP LaserJet 3310 Digital Printer Copier" :status :good :model "HP Photosmart 3313 All-in-one Printer" :status :good :model "HP Photosmart 3314 All-in-one Printer" :status :good :model "HP LaserJet 3320n Multifunction Printer" :status :good :model "HP LaserJet 3320 Multifunction Printer" :status :good :model "HP LaserJet 3330 Multifunction Printer" :status :good :model "HP LaserJet 3380 All-in-one Printer" :status :good :model "HP LaserJet 3390 All-in-one Printer" :status :good :model "HP LaserJet 3392 All-in-one Printer" :status :good :model "HP Officejet j3608 All-in-one Printer" :status :good :model "HP Officejet j3625 All-in-one Printer" :status :good :model "HP Officejet j3635 All-in-one Printer" :status :good :model "HP Officejet j3640 All-in-one Printer" :status :good :model "HP Officejet j3650 All-in-one Printer" :status :good :model "HP Officejet j3680 All-in-one Printer" :status :good :model "HP Officejet 4100 Series All-in-one Printer" :status :good :model "HP LaserJet 4100 Multifunction Printer" :status :good :model "HP LaserJet 4101 Multifunction Printer" :status :good :model "HP Officejet 4105 All-in-one Printer" :status :good :model "HP Officejet 4110xi All-in-one Printer" :status :good :model "HP Photosmart c4110 All-in-one Printer" :status :good :model "HP Officejet 4110v All-in-one Printer" :status :good :model "HP Officejet 4110 All-in-one Printer" :status :good :model "HP Officejet 4115 All-in-one Printer" :status :good :model "HP Deskjet f4135 All-in-one Printer" :status :good :model "HP Photosmart c4140 All-in-one Printer" :status :good :model "HP Deskjet f4140 All-in-one Printer" :status :good :model "HP Deskjet f4150 All-in-one Printer" :status :good :model "HP Photosmart c4150 All-in-one Printer" :status :good :model "HP Photosmart c4170 All-in-one Printer" :status :good :model "HP Deskjet f4172 All-in-one Printer" :status :good :model "HP Photosmart c4173 All-in-one Printer" :status :good :model "HP Deskjet f4175 All-in-one Printer" :status :good :model "HP Photosmart c4175 All-in-one Printer" :status :good :model "HP Deskjet f4180 All-in-one Printer" :status :good :model "HP Photosmart c4180 All-in-one Printer" :status :good :model "HP Photosmart c4183 All-in-one Printer" :status :good :model "HP Deskjet f4185 All-in-one Printer" :status :good :model "HP Photosmart c4188 All-in-one Printer" :status :good :model "HP Deskjet f4188 All-in-one Printer" :status :good :model "HP Deskjet f4190 All-in-one Printer" :status :good :model "HP Photosmart c4190 All-in-one Printer" :status :good :model "HP Photosmart c4193 All-in-one Printer" :status :good :model "HP Deskjet f4194 All-in-one Printer" :status :good :model "HP Photosmart c4194 All-in-one Printer" :status :good :model "HP Officejet 4200 All-in-one Printer" :status :good :model "HP Photosmart c4205 All-in-one Printer" :status :good :model "HP Photosmart c4210 All-in-one Printer" :status :good :model "HP Deskjet f4210 All-in-one Printer" :status :good :model "HP Officejet 4211 All-in-one Printer" :status :good :model "HP Officejet 4212 All-in-one Printer" :status :good :model "HP Deskjet f4213 All-in-one Printer" :status :good :model "HP Officejet 4215 All-in-one Printer" :status :good :model "HP Officejet 4215v All-in-one Printer" :status :good :model "HP Officejet 4215xi All-in-one Printer" :status :good :model "HP Officejet 4219 All-in-one Printer" :status :good :model "HP Deskjet f4224 All-in-one Printer" :status :good :model "HP Deskjet f4230 All-in-one Printer" :status :good :model "HP Deskjet f4235 All-in-one Printer" :status :good :model "HP Photosmart c4235 All-in-one Printer" :status :good :model "HP Deskjet f4238 All-in-one Printer" :status :good :model "HP Deskjet f4240 All-in-one Printer" :status :good :model "HP Photosmart c4240 All-in-one Printer" :status :good :model "HP Photosmart c4250 All-in-one Printer" :status :good :model "HP Deskjet f4250 All-in-one Printer" :status :good :model "HP Officejet 4251 All-in-one Printer" :status :good :model "HP Officejet 4252 All-in-one Printer" :status :good :model "HP Officejet 4255 All-in-one Printer" :status :good :model "HP Officejet 4256 All-in-one Printer" :status :good :model "HP Officejet 4259 All-in-one Printer" :status :good :model "HP Photosmart c4270 All-in-one Printer" :status :good :model "HP Deskjet f4272 All-in-one Printer" :status :good :model "HP Photosmart c4272 All-in-one Printer" :status :good :model "HP Deskjet f4273 All-in-one Printer" :status :good :model "HP Photosmart c4273 All-in-one Printer" :status :good :model "HP Deskjet f4274 All-in-one Printer" :status :good :model "HP Photosmart c4275 All-in-one Printer" :status :good :model "HP Deskjet f4275 All-in-one Printer" :status :good :model "HP Deskjet f4280 All-in-one" :status :good :model "HP Photosmart c4280 All-in-one Printer" :status :good :model "HP Deskjet f4280 All-in-one Printer" :status :good :model "HP Photosmart c4283 All-in-one Printer" :status :good :model "HP Deskjet f4283 All-in-one Printer" :status :good :model "HP Photosmart c4285 All-in-one Printer" :status :good :model "HP Photosmart c4288 All-in-one Printer" :status :good :model "HP Deskjet f4288 All-in-one Printer" :status :good :model "HP Deskjet f4292 All-in-one Printer" :status :good :model "HP Deskjet f4293 All-in-one Printer" :status :good :model "HP Photosmart c4293 All-in-one Printer" :status :good :model "HP Deskjet f4294 All-in-one Printer" :status :good :model "HP Photosmart c4294 All-in-one Printer" :status :good :model "HP Officejet 4308 All-in-one Printer" :status :good :model "HP Officejet 4311 All-in-one Printer" :status :good :model "HP Officejet 4312 All-in-one Printer" :status :good :model "HP Officejet 4314 All-in-one Printer" :status :good :model "HP Officejet 4315 All-in-one Printer" :status :good :model "HP Officejet 4315xi All-in-one Printer" :status :good :model "HP Officejet 4315v All-in-one Printer" :status :good :model "HP Officejet 4317 All-in-one Printer" :status :good :model "HP Officejet 4319 All-in-one Printer" :status :good :model "HP Officejet 4338 All-in-one Printer" :status :good :model "HP Photosmart c4340 All-in-one Printer" :status :good :model "HP Photosmart c4342 All-in-one Printer" :status :good :model "HP Photosmart c4343 All-in-one Printer" :status :good :model "HP Photosmart c4344 All-in-one Printer" :status :good :model "HP LaserJet m4345 Multifunction Printer" :status :good :model "HP LaserJet 4345xm Multifunction Printer" :status :good :model "HP LaserJet 4345 Multifunction Printer" :status :good :model "HP LaserJet m4345x Multifunction Printer" :status :good :model "HP LaserJet m4345xs Multifunction Printer" :status :good :model "HP LaserJet 4345xs Multifunction Printer" :status :good :model "HP LaserJet 4345x Multifunction Printer" :status :good :model "HP Photosmart c4345 All-in-one Printer" :status :good :model "HP LaserJet m4345xm Multifunction Printer" :status :good :model "HP Photosmart c4348 All-in-one Printer" :status :good :model "HP LaserJet m4349 MFP" :status :good :model "HP Officejet 4352 All-in-one Printer" :status :good :model "HP Officejet 4353 All-in-one Printer" :status :good :model "HP Officejet 4355 All-in-one Printer" :status :good :model "HP Officejet 4357 All-in-one Printer" :status :good :model "HP Officejet 4359 All-in-one Printer" :status :good :model "HP Photosmart c4380 All-in-one Printer" :status :good :model "HP Photosmart c4383 All-in-one Printer" :status :good :model "HP Photosmart c4384 All-in-one Printer" :status :good :model "HP Photosmart c4385 All-in-one Printer" :status :good :model "HP Photosmart c4388 All-in-one Printer" :status :good :model "HP Photosmart c4410 All-in-one Printer" :status :good :model "HP Photosmart c4424 All-in-one Printer" :status :good :model "HP Deskjet f4435 All-in-one Printer" :status :good :model "HP Photosmart c4435 All-in-one Printer" :status :good :model "HP Photosmart c4440 All-in-one Printer" :status :good :model "HP Deskjet f4440 All-in-one Printer" :status :good :model "HP Photosmart c4450 All-in-one Printer" :status :good :model "HP Deskjet f4450 All-in-one Printer" :status :good :model "HP Deskjet f4470 All-in-one Printer" :status :good :model "HP Photosmart c4470 All-in-one Printer" :status :good :model "HP Photosmart c4472 All-in-one Printer" :status :good :model "HP Deskjet f4472 All-in-one Printer" :status :good :model "HP Photosmart c4473 All-in-one Printer" :status :good :model "HP Deskjet f4473 All-in-one Printer" :status :good :model "HP Deskjet f4480 All-in-one Printer" :status :good :model "HP Photosmart c4480 All-in-one Printer" :status :good :model "HP Photosmart c4483 All-in-one Printer" :status :good :model "HP Deskjet f4483 All-in-one Printer" :status :good :model "HP Photosmart c4485 All-in-one Printer" :status :good :model "HP Photosmart c4486 All-in-one Printer" :status :good :model "HP Photosmart c4488 All-in-one Printer" :status :good :model "HP Deskjet f4488 All-in-one Printer" :status :good :model "HP Photosmart c4490 All-in-one Printer" :status :good :model "HP Deskjet f4492 All-in-one Printer" :status :good :model "HP Photosmart c4493 All-in-one Printer" :status :good :model "HP Photosmart c4494 All-in-one Printer" :status :good :model "HP Deskjet f4500 All-in-one Printer Series" :status :good :model "HP Designjet 4520mfp" :status :good :model "HP Officejet j4524 All-in-one Printer" :status :good :model "HP Officejet j4525 All-in-one Printer" :status :good :model "HP Officejet j4535 All-in-one Printer" :status :good :model "HP Photosmart c4540 All-in-one Printer" :status :good :model "HP Officejet j4540 All-in-one Printer" :status :good :model "HP Photosmart c4550 All-in-one Printer" :status :good :model "HP Officejet j4550 All-in-one Printer" :status :good :model "HP Officejet j4560 All-in-one Printer" :status :good :model "HP Photosmart c4570 All-in-one Printer" :status :good :model "HP Photosmart c4572 All-in-one Printer" :status :good :model "HP Photosmart c4573 All-in-one Printer" :status :good :model "HP Photosmart c4575 All-in-one Printer" :status :good :model "HP Officejet j4580c All-in-one Printer" :status :good :model "HP Photosmart c4580 All-in-one Printer" :status :good :model "HP Officejet j4580 All-in-one Printer" :status :good :model "HP Photosmart c4583 All-in-one Printer" :status :good :model "HP Photosmart c4585 All-in-one Printer" :status :good :model "HP Officejet j4585 All-in-one Printer" :status :good :model "HP Photosmart c4588 All-in-one Printer" :status :good :model "HP Photosmart c4593 All-in-one Printer" :status :good :model "HP Photosmart c4599 All-in-one Printer" :status :good :model "HP Photosmart c4610 All-in-one Printer" :status :good :model "HP Photosmart c4635 All-in-one Printer" :status :good :model "HP Photosmart c4640 All-in-one Printer" :status :good :model "HP Photosmart c4650 All-in-one Printer" :status :good :model "HP Officejet j4660 All-in-one Printer" :status :good :model "HP Photosmart c4670 All-in-one Printer" :status :good :model "HP Photosmart c4673 All-in-one Printer" :status :good :model "HP Officejet j4680 All-in-one Printer" :status :good :model "HP Photosmart c4680 All-in-one Printer" :status :good :model "HP Officejet j4680c All-in-one Printer" :status :good :model "HP Photosmart c4683 All-in-one Printer" :status :good :model "HP Photosmart c4688 All-in-one Printer" :status :good :model "HP Color LaserJet 4730x Multifunction Printer" :status :good :model "HP Color LaserJet 4730xs Multifunction Printer" :status :good :model "HP Color LaserJet cm4730 Multifunction Printer" :status :good :model "HP Color LaserJet 4730 Multifunction Printer" :status :good :model "HP Color LaserJet cm4730fsk Multifunction Printer" :status :good :model "HP Color LaserJet cm4730fm Multifunction Printer" :status :good :model "HP Color LaserJet cm4730f Multifunction Printer" :status :good :model "HP Color LaserJet 4730xm Multifunction Printer" :status :good :model "HP Photosmart c4740 All-in-one Printer" :status :good :model "HP Photosmart c4750 All-in-one Printer" :status :good :model "HP Photosmart c4780 All-in-one Printer" :status :good :model "HP Photosmart c4783 All-in-one Printer" :status :good :model "HP Photosmart c4785 All-in-one Printer" :status :good :model "HP Photosmart c4788 All-in-one Printer" :status :good :model "HP Photosmart c4793 All-in-one Printer" :status :good :model "HP Photosmart c4795 All-in-one Printer" :status :good :model "HP Photosmart c4798 All-in-one Printer" :status :good :model "HP Photosmart c4799 All-in-one Printer" :status :good :model "HP LaserJet m5035 Multifunction Printer" :status :good :model "HP LaserJet m5035xs Multifunction Printer" :status :good :model "HP LaserJet m5035x Multifunction Printer" :status :good :model "HP Officejet 5100 All-in-one Printer" :status :good :model "HP Officejet 5105 All-in-one Printer" :status :good :model "HP Officejet 5110 All-in-one Printer" :status :good :model "HP Officejet 5110v All-in-one Printer" :status :good :model "HP Officejet 5110xi All-in-one Printer" :status :good :model "HP Photosmart c5140 All-in-one Printer" :status :good :model "HP Photosmart c5150 All-in-one Printer" :status :good :model "HP Photosmart c5170 All-in-one Printer" :status :good :model "HP Photosmart c5173 All-in-one Printer" :status :good :model "HP Photosmart c5175 All-in-one Printer" :status :good :model "HP Photosmart c5180 All-in-one Printer" :status :good :model "HP Photosmart c5183 All-in-one Printer" :status :good :model "HP Photosmart c5185 All-in-one Printer" :status :good :model "HP Photosmart c5188 All-in-one Printer" :status :good :model "HP Photosmart c5194 All-in-one Printer" :status :good :model "HP Photosmart c5240 All-in-one Printer" :status :good :model "HP Photosmart c5250 All-in-one Printer" :status :good :model "HP Photosmart c5270 All-in-one Printer" :status :good :model "HP Photosmart c5273 All-in-one Printer" :status :good :model "HP Photosmart c5275 All-in-one Printer" :status :good :model "HP Photosmart c5280 All-in-one Printer" :status :good :model "HP Photosmart c5283 All-in-one Printer" :status :good :model "HP Photosmart c5288 All-in-one Printer" :status :good :model "HP Photosmart c5290 All-in-one Printer" :status :good :model "HP Photosmart c5293 All-in-one Printer" :status :good :model "HP Photosmart c5370 All-in-one Printer" :status :good :model "HP Photosmart c5373 All-in-one Printer" :status :good :model "HP Photosmart c5380 All-in-one Printer" :status :good :model "HP Photosmart c5383 All-in-one Printer" :status :good :model "HP Photosmart c5388 All-in-one Printer" :status :good :model "HP Photosmart c5390 All-in-one Printer" :status :good :model "HP Photosmart c5393 All-in-one Printer" :status :good :model "HP Officejet 5505 All-in-one Printer" :status :good :model "HP Officejet j5505 All-in-one Printer" :status :good :model "HP Officejet 5508 All-in-one Printer" :status :good :model "HP Officejet j5508 All-in-one Printer" :status :good :model "HP Officejet j5510v All-in-one Printer" :status :good :model "HP Officejet 5510v All-in-one Printer" :status :good :model "HP Officejet 5510xi All-in-one Printer" :status :good :model "HP Officejet 5510 All-in-one Printer" :status :good :model "HP Officejet j5510xi All-in-one Printer" :status :good :model "HP Officejet j5510 All-in-one Printer" :status :good :model "HP Officejet j5515 All-in-one Printer" :status :good :model "HP Officejet 5515 All-in-one Printer" :status :good :model "HP Officejet j5520 All-in-one Printer" :status :good :model "HP Photosmart c5540 All-in-one Printer" :status :good :model "HP Photosmart c5550 All-in-one Printer" :status :good :model "HP Photosmart c5570 All-in-one Printer" :status :good :model "HP Photosmart c5580 All-in-one Printer" :status :good :model "HP Officejet 5600 Series All-in-one Printer" :status :good :model "HP Officejet 5605 All-in-one Printer" :status :good :model "HP Officejet 5607 All-in-one Printer" :status :good :model "HP Officejet 5608 All-in-one Printer" :status :good :model "HP Officejet 5609 All-in-one Printer" :status :good :model "HP Officejet 5610v All-in-one Printer" :status :good :model "HP Officejet 5610xi All-in-one Printer" :status :good :model "HP Officejet 5610 All-in-one Printer" :status :good :model "HP Officejet 5615 All-in-one Printer" :status :good :model "HP Officejet 5679 All-in-one Printer" :status :good :model "HP Officejet 5680 All-in-one Printer" :status :good :model "HP Officejet j5725 All-in-one Printer" :status :good :model "HP Officejet j5730 All-in-one Printer" :status :good :model "HP Officejet j5735 All-in-one Printer" :status :good :model "HP Officejet j5738 All-in-one Printer" :status :good :model "HP Officejet j5740 All-in-one Printer" :status :good :model "HP Officejet j5750 All-in-one Printer" :status :good :model "HP Officejet j5780 All-in-one Printer" :status :good :model "HP Officejet j5783 All-in-one Printer" :status :good :model "HP Officejet j5785 All-in-one Printer" :status :good :model "HP Officejet j5788 All-in-one Printer" :status :good :model "HP Officejet j5790 All-in-one Printer" :status :good :model "HP Officejet 6105 All-in-one Printer" :status :good :model "HP Officejet 6110v All-in-one Printer" :status :good :model "HP Officejet 6110 All-in-one Printer" :status :good :model "HP Officejet 6110xi All-in-one Printer" :status :good :model "HP Officejet 6150 All-in-one Printer" :status :good :model "HP Photosmart c6150 All-in-one Printer" :status :good :model "HP Photosmart c6154 All-in-one Printer" :status :good :model "HP Photosmart c6170 All-in-one Printer" :status :good :model "HP Photosmart c6175 All-in-one Printer" :status :good :model "HP Photosmart c6180 All-in-one Printer" :status :good :model "HP Photosmart c6183 All-in-one Printer" :status :good :model "HP Photosmart c6185 All-in-one Printer" :status :good :model "HP Photosmart c6188 All-in-one Printer" :status :good :model "HP Photosmart c6190 All-in-one Printer" :status :good :model "HP Officejet 6200 All-in-one Printer" :status :good :model "HP Officejet 6203 All-in-one Printer" :status :good :model "HP Officejet 6205 All-in-one Printer" :status :good :model "HP Officejet 6208 All-in-one Printer" :status :good :model "HP Officejet 6210xi All-in-one Printer" :status :good :model "HP Officejet 6210v All-in-one Printer" :status :good :model "HP Officejet 6210 All-in-one Printer" :status :good :model "HP Officejet 6213 All-in-one Printer" :status :good :model "HP Officejet 6215 All-in-one Printer" :status :good :model "HP Photosmart c6240 All-in-one Printer" :status :good :model "HP Photosmart c6245 All-in-one Printer" :status :good :model "HP Photosmart c6250 All-in-one Printer" :status :good :model "HP Photosmart c6260 All-in-one Printer" :status :good :model "HP Photosmart c6263 All-in-one Printer" :status :good :model "HP Photosmart c6268 All-in-one Printer" :status :good :model "HP Photosmart c6270 All-in-one Printer" :status :good :model "HP Photosmart c6275 All-in-one Printer" :status :good :model "HP Photosmart c6280 All-in-one Printer" :status :good :model "HP Photosmart c6283 All-in-one Printer" :status :good :model "HP Photosmart c6285 All-in-one Printer" :status :good :model "HP Photosmart c6286 All-in-one Printer" :status :good :model "HP Photosmart c6288 All-in-one Printer" :status :good :model "HP Officejet 6301 All-in-one Printer" :status :good :model "HP Officejet 6304 All-in-one Printer" :status :good :model "HP Officejet 6305 All-in-one Printer" :status :good :model "HP Officejet 6307 All-in-one Printer" :status :good :model "HP Officejet 6308 All-in-one Printer" :status :good :model "HP Officejet 6310 All-in-one Printer" :status :good :model "HP Officejet 6310xi All-in-one Printer" :status :good :model "HP Officejet 6310v All-in-one Printer" :status :good :model "HP Officejet 6313 All-in-one Printer" :status :good :model "HP Officejet 6315 All-in-one Printer" :status :good :model "HP Officejet 6318 All-in-one Printer" :status :good :model "HP Photosmart c6324 All-in-one Printer" :status :good :model "HP Photosmart c6340 All-in-one Printer" :status :good :model "HP Photosmart c6350 All-in-one Printer" :status :good :model "HP Photosmart c6375 All-in-one Printer" :status :good :model "HP Photosmart c6380 All-in-one Printer" :status :good :model "HP Photosmart c6383 All-in-one Printer" :status :good :model "HP Photosmart c6388 All-in-one Printer" :status :good :model "HP Officejet j6405 All-in-one Printer" :status :good :model "HP Officejet j6410 All-in-one Printer" :status :good :model "HP Officejet j6413 All-in-one Printer" :status :good :model "HP Officejet j6415 All-in-one Printer" :status :good :model "HP Officejet j6424 All-in-one Printer" :status :good :model "HP Officejet j6450 All-in-one Printer" :status :good :model "HP Officejet j6480 All-in-one Printer" :status :good :model "HP Officejet j6488 All-in-one Printer" :status :good :model "HP Officejet 6500 Wireless All-in-one Printer - e709q" :status :good :model "HP Officejet 6500 Wireless All-in-one Printer - e709n" :status :good :model "HP Officejet 6500 All-in-one Printer - e709c" :status :good :model "HP Officejet 6500 All-in-one Printer - e709a" :status :good :model "HP Officejet 7100 All-in-one Printer" :status :good :model "HP Officejet 7110xi All-in-one Printer" :status :good :model "HP Officejet 7110 All-in-one Printer" :status :good :model "HP Officejet 7115 All-in-one Printer" :status :good :model "HP Officejet 7130 All-in-one Printer" :status :good :model "HP Officejet 7130xi All-in-one Printer" :status :good :model "HP Officejet 7135xi All-in-one Printer" :status :good :model "HP Officejet 7140xi All-in-one Printer" :status :good :model "HP Photosmart c7150 All-in-one Printer" :status :good :model "HP Photosmart c7154 All-in-one Printer" :status :good :model "HP Photosmart c7170 All-in-one Printer" :status :good :model "HP Photosmart c7180 All-in-one Printer" :status :good :model "HP Photosmart c7183 All-in-one Printer" :status :good :model "HP Photosmart c7185 All-in-one Printer" :status :good :model "HP Photosmart c7188 All-in-one Printer" :status :good :model "HP Photosmart c7190 All-in-one Printer" :status :good :model "HP Officejet 7205 All-in-one Printer" :status :good :model "HP Officejet 7208 All-in-one Printer" :status :good :model "HP Officejet 7210 All-in-one Printer" :status :good :model "HP Officejet 7210v All-in-one Printer" :status :good :model "HP Officejet 7210xi All-in-one Printer" :status :good :model "HP Officejet 7213 All-in-one Printer" :status :good :model "HP Officejet 7215 All-in-one Printer" :status :good :model "HP Photosmart c7250 All-in-one Printer" :status :good :model "HP Photosmart c7275 All-in-one Printer" :status :good :model "HP Photosmart c7280 All-in-one Printer" :status :good :model "HP Photosmart c7283 All-in-one Printer" :status :good :model "HP Photosmart c7288 All-in-one Printer" :status :good :model "HP Officejet Pro l7300 Series All-in-one Printer" :status :good :model "HP Officejet 7310xi All-in-one Printer" :status :good :model "HP Officejet 7310 All-in-one Printer" :status :good :model "HP Officejet 7313 All-in-one Printer" :status :good :model "HP Officejet Pro l7380 All-in-one Printer" :status :good :model "HP Officejet 7408 All-in-one Printer" :status :good :model "HP Officejet 7410xi All-in-one Printer" :status :good :model "HP Officejet 7410 All-in-one Printer" :status :good :model "HP Officejet 7413 All-in-one Printer" :status :good :model "HP Officejet Pro l7480 All-in-one Printer" :status :good :model "HP Officejet Pro l7500 Series All-in-one Printer" :status :good :model "HP Officejet Pro l7550 All-in-one Printer" :status :good :model "HP Officejet Pro l7555 All-in-one Printer" :status :good :model "HP Officejet Pro l7580 All-in-one Printer" :status :good :model "HP Officejet Pro l7590 All-in-one Printer" :status :good :model "HP Officejet Pro l7600 Series All-in-one Printer" :status :good :model "HP Officejet Pro l7650 All-in-one Printer" :status :good :model "HP Officejet Pro l7680 All-in-one Printer" :status :good :model "HP Officejet Pro l7681 All-in-one Printer" :status :good :model "HP Officejet Pro l7700 Series All-in-one Printer" :status :good :model "HP Officejet Pro l7710 All-in-one Printer" :status :good :model "HP Officejet Pro l7750 All-in-one Printer" :status :good :model "HP Officejet Pro l7780 All-in-one Printer" :status :good :model "HP cm8050 Color Multifunction Printer With Edgeline Technology" :status :good :model "HP cm8060 Color Multifunction Printer With Edgeline Technology" :status :good :model "HP LaserJet 8100 Multifunction Printer" :status :good :model "HP LaserJet 8150 Multifunction Printer" :status :good :model "HP Photosmart c8150 All-in-one Printer" :status :good :model "HP Photosmart c8180 All-in-one Printer" :status :good :model "HP Photosmart c8183 All-in-one Printer" :status :good :model "HP Photosmart c8188 All-in-one Printer" :status :good :model "HP Officejet Pro 8500 Premier All-in-one Printer - a909n" :status :good :model "HP Officejet Pro 8500 Wireless All-in-one Printer - a909g" :status :good :model "HP Officejet Pro 8500 All-in-one Printer - a909a" :status :good :model "HP LaserJet 9000 Multifunction Printer" :status :good :model "HP LaserJet 9000l Multifunction Printer" :status :good :model "HP LaserJet 9040 Multifunction Printer" :status :good :model "HP LaserJet 9050 Multifunction Printer" :status :good :model "HP LaserJet 9055 Multifunction Printer" :status :good :model "HP LaserJet 9065 Multifunction Printer" :status :good :model "HP Officejet 9110 All-in-one Printer" :status :good :model "HP Officejet 9120 All-in-one Printer" :status :good :model "HP Officejet 9130 All-in-one Printer" :status :good :model "HP Color LaserJet 9500 Multifunction Printer" :status :good sane-backends-1.0.27/doc/descriptions-external/canon_mfp.desc0000664000175000017500000000450412112021330021101 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "canon_mfp" ; name of backend ;:version "1.0.0" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://cweb.canon.jp/drv-upd/bj/other.html#linux"; :url "http://support-asia.canon-asia.com/"; :comment "External backend made by canon. As this software contains non-free parts, it can't be included into SANE. If you can't find your model here, please have a look at the canon website which contains the latest list." :comment "Note: these backend are designed by Canon and are part of their proprietary scanning software. They may not work at all with SANE, or with SANE frontends." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" ; manufacturer's URL ;:comment "" ; comment about the manufacturer :model "MP140" :status :untested :interface "USB" :usbid "0x04a9" "0x172b" :comment "No report yet." :model "MP160" :status :untested :interface "USB" :usbid "0x04a9" "0x1714" :comment "No report yet." :model "MP210" :status :untested :interface "USB" :usbid "0x04a9" "0x1721" :comment "No report yet." :model "MP510" :status :untested :interface "USB" :usbid "0x04a9" "0x1717" :comment "No report yet." :model "MP520" :status :untested :interface "USB" :usbid "0x04a9" "0x1724" :comment "No report yet." :model "MP600" :status :untested :interface "USB" :usbid "0x04a9" "0x1718" :comment "No report yet." :model "MP610" :status :untested :interface "USB" :usbid "0x04a9" "0x1725" :comment "Could not have it working with SANE." sane-backends-1.0.27/doc/descriptions-external/brother-mfc4600.desc0000664000175000017500000000243112112021330021660 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "brother-mfc4600" ; name of backend ;:version "0.42" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://sourceforge.net/projects/brother-mfc" ;:comment "" ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Brother" :url "http://www.brother.com/" :model "MFC 4600" :status :basic :url "http://sourceforge.net/projects/brother-mfc" :interface "USB" :usbid "0x04f9" "0x0111" :comment "Only USB version of this scanner is supported. Please report how well it works. See link." sane-backends-1.0.27/doc/descriptions-external/v4l2.desc0000664000175000017500000000173512112021330017733 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "v4l2" ; name of backend ;:version "(19991125)" ; version of backend ;:manpage "sane-v4l2" ; name of manpage (if it exists) :url "http://video.inodes.org/sane-v4l2/" ; backend's web page :comment "The status of this backend is unknown. It hasn't been updated for years. The v4l2 API is now in Linux 2.5 but it's not clear if the v4l2 backend is compatible to that API." :devicetype :api ; specify a different type :desc "Interface to Video For Linux 2 API" ; describe a non-hardware device ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions-external/primascan.desc0000664000175000017500000000235312112021330021116 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "primascan" ; name of backend ;:version "0.42" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://www.geocities.com/trsh0101/index.html" ; backend's web page :comment "SANE backend and stand-alone program" ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Primax" ; name a manufacturer :url "http://www.primax.nl/" :model "Colorado 2400U" :interface "USB" :usbid "0x0461" "0x0346" :status :minimal ;:comment "" sane-backends-1.0.27/doc/descriptions-external/cs3200f.desc0000664000175000017500000000235012112021330020216 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "cs3200f" ; name of backend ;:version "0" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-cs3200f" ; name of manpage (if it exists) ;:url "http://www.luser.com/temp/" ; backend's web page :comment "Backend is in experimental CVS" ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Canon" :url "http://www.canon.com/" :model "CanoScan 3200F" :url "/unsupported/canon-3200f.html" :interface "USB" :usbid "0x04a9" "0x2216" :status :minimal :comment "Backend is in experimental CVS." sane-backends-1.0.27/doc/descriptions-external/scanwit.desc0000664000175000017500000000170712112021330020613 00000000000000; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "scanwit" ; name of backend :url "ftp://ftp.mccme.ru/users/ushakov/scanwit" ;:version "(2001-10-10)" ; version of backend ; ;:manpage "sane-ibm" ; name of manpage (if it exists) :comment "The backend is not included because it lacks code for safe detection of the scanner and documentation." :devicetype :scanner :mfg "Benq (Acer)" ; name a manufacturer :url "http://www.benq.com" :comment "Formerly Acer Peripherals" :model "ScanWit 2720S" ; name models for above-specified mfg. :interface "SCSI" :status :basic :comment "Usable, but not complete" sane-backends-1.0.27/doc/descriptions-external/brother.desc0000664000175000017500000001750012775312261020633 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "brother" ; name of backend ;:version "1.0.0" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://solutions.brother.com/linux/sol/printer/linux/sane_drivers.html" ; backend's web page :comment "External backend made by brother. As this software contains non-free parts, it can't be included into SANE. If you can't find your model here, please have a look at the brother website which contains the latest list." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Brother" ; name a manufacturer :url "http://www.brother.com/" ; manufacturer's URL ;:comment "" ; comment about the manufacturer ;data taken from Brother website and Brsane.ini :model "DCP-1000" :status :untested :interface "USB" :usbid "0x04f9" "0x0112" :comment "No report yet." :model "DCP-1000J" :status :untested :interface "USB" :usbid "0x04f9" "0x0153" :comment "No report yet." :model "DCP-1400" :status :untested :interface "USB" :usbid "0x04f9" "0x0116" :comment "No report yet." :model "DCP-3020C" :status :untested :interface "USB" :usbid "0x04f9" "0x014c" :comment "No report yet." :model "DCP-4020C" :status :untested :interface "USB" :usbid "0x04f9" "0x0144" :comment "No report yet." :model "DCP-8020" :status :untested :interface "USB" :usbid "0x04f9" "0x0140" :comment "No report yet." :model "DCP-8025D" :status :good :interface "USB" :usbid "0x04f9" "0x0141" :model "DCP-8025J" :status :good :interface "USB" :usbid "0x04f9" "0x014f" :comment "No report yet." :model "DCP-8040" :status :untested :interface "USB" :usbid "0x04f9" "0x015d" :comment "No report yet." :model "DCP-8045D" :status :good :interface "USB" :usbid "0x04f9" "0x015e" :model "DCP-8060" :status :good :interface "USB" :usbid "0x04f9" "0x01a3" :model "FAX1800C" :status :untested :interface "USB" :usbid "0x04f9" "0x0126" :comment "No report yet." :model "FAX1815C" :status :untested :interface "USB" :usbid "0x04f9" "0x014d" :comment "No report yet." :model "FAX1820C" :status :untested :interface "USB" :usbid "0x04f9" "0x0147" :comment "No report yet." :model "FAX1920CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0149" :comment "No report yet." :model "FAX-2850" :status :untested :interface "USB" :usbid "0x04f9" "0x0123" :comment "No report yet." :model "FAX-2900" :status :untested :interface "USB" :usbid "0x04f9" "0x0117" :comment "No report yet." :model "FAX-3800" :status :untested :interface "USB" :usbid "0x04f9" "0x0118" :comment "No report yet." :model "FAX-4100" :status :untested :interface "USB" :usbid "0x04f9" "0x012e" :comment "No report yet." :model "FAX-4750e" :status :untested :interface "USB" :usbid "0x04f9" "0x012f" :comment "No report yet." :model "FAX-5750e" :status :untested :interface "USB" :usbid "0x04f9" "0x0130" :comment "No report yet." :model "MFC-100" :status :untested :interface "USB" :usbid "0x04f9" "0x0135" :comment "No report yet." :model "MFC-150CL" :status :untested :interface "USB" :usbid "0x04f9" "0x0136" :comment "No report yet." :model "MFC-3100C" :status :untested :interface "USB" :usbid "0x04f9" "0x010e" :comment "No report yet." :model "MFC-3200C" :status :untested :interface "USB" :usbid "0x04f9" "0x013a" :comment "No report yet." :model "MFC-3220C" :status :untested :interface "USB" :usbid "0x04f9" "0x0146" :comment "No report yet." :model "MFC-3320CN" :status :untested :interface "USB network" :usbid "0x04f9" "0x0148" :comment "No report yet." :model "MFC-3420C" :status :good :interface "USB" :usbid "0x04f9" "0x014a" :model "MFC-3420J" :status :untested :interface "USB" :usbid "0x04f9" "0x0157" :comment "No report yet." :model "MFC-3820J" :status :untested :interface "USB" :usbid "0x04f9" "0x0158" :comment "No report yet." :model "MFC-3820CN" :status :good :interface "USB network" :usbid "0x04f9" "0x014b" :comment "Network connection is reported to work." :model "MFC-4420C" :status :untested :interface "USB" :usbid "0x04f9" "0x013e" :comment "No report yet." :model "MFC-4800" :status :good :interface "USB" :usbid "0x04f9" "0x0110" :model "MFC-4800J" :status :untested :interface "USB" :usbid "0x04f9" "0x0124" :comment "No report yet." :model "MFC-4820C" :status :good :interface "USB" :usbid "0x04f9" "0x013f" :model "MFC-5100C" :status :good :interface "USB" :usbid "0x04f9" "0x010f" :model "MFC-5100J" :status :untested :interface "USB" :usbid "0x04f9" "0x0122" :comment "No report yet." :model "MFC-5200C" :status :good :interface "USB" :usbid "0x04f9" "0x0132" :model "MFC-5200J" :status :untested :interface "USB" :usbid "0x04f9" "0x013d" :comment "No report yet." :model "MFC-580" :status :good :interface "USB" :usbid "0x04f9" "0x0120" :model "MFC-590" :status :good :interface "USB" :usbid "0x04f9" "0x0121" :model "MFC-6800" :status :untested :interface "USB" :usbid "0x04f9" "0x0111" :comment "No report yet." :model "MFC-6800J" :status :untested :interface "USB" :usbid "0x04f9" "0x0125" :comment "No report yet." :model "MFC-8210" :status :untested :interface "USB" :usbid "0x04f9" "0x0151" :comment "No report yet." :model "MFC-8220" :status :untested :interface "USB" :usbid "0x04f9" "0x0150" :comment "No report yet." :model "MFC-8420" :status :good :interface "USB" :usbid "0x04f9" "0x0142" :model "MFC-8440" :status :good :interface "USB" :usbid "0x04f9" "0x015f" :model "MFC-8500" :status :untested :interface "USB" :usbid "0x04f9" "0x0113" :comment "No report yet." :model "MFC-8500J" :status :untested :interface "USB" :usbid "0x04f9" "0x0128" :comment "No report yet." :model "MFC-8820D" :status :good :interface "USB" :usbid "0x04f9" "0x0143" :model "MFC-8820J" :status :untested :interface "USB" :usbid "0x04f9" "0x014e" :comment "No report yet." :model "MFC-8840D" :status :good :interface "USB" :usbid "0x04f9" "0x0160" :model "MFC-890" :status :good :interface "USB" :usbid "0x04f9" "0x013c" :model "MFC-9030" :status :untested :interface "USB" :usbid "0x04f9" "0x012b" :comment "No report yet." :model "MFC-9070" :status :untested :interface "USB" :usbid "0x04f9" "0x011d" :comment "No report yet." :model "MFC-9160" :status :good :interface "USB" :usbid "0x04f9" "0x011f" :comment "Is reported to work well with backend version 0.0.12." :model "MFC-9180" :status :good :interface "USB" :usbid "0x04f9" "0x011e" :comment "Reported to work well under openSUSE 10.2." :model "MFC-9660" :status :untested :interface "USB" :usbid "0x04f9" "0x0119" :comment "No report yet." :model "MFC-9700" :status :untested :interface "USB" :usbid "0x04f9" "0x0114" :comment "No report yet." :model "MFC-9760" :status :untested :interface "USB" :usbid "0x04f9" "0x011c" :comment "No report yet." :model "MFC-9800" :status :untested :interface "USB" :usbid "0x04f9" "0x0115" :comment "No report yet." :model "MFC-9800J" :status :untested :interface "USB" :usbid "0x04f9" "0x0127" :comment "No report yet." :model "MFC-9860" :status :untested :interface "USB" :usbid "0x04f9" "0x011a" :comment "No report yet." :model "MFC-9880" :status :unsupported :interface "USB" :usbid "0x04f9" "0x011b" :comment "There is a report that this scanner does not work with the brother backend (I/O errors)" sane-backends-1.0.27/doc/descriptions-external/hp3770.desc0000664000175000017500000000402312112021330020065 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "hp3770" ; name of backend ;:version "0.0" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://www.cyberbaladeur.fr/telechargement.html" ; backend's web page :comment "This backend can't be added to the SANE distribution because it consists of binary-only code." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett Packard" ; name a manufacturer :url "http://www.hp.com/" ; manufacturer's URL :model "ScanJet 3770" ; name models for above-specified mfg. :status :basic ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :usbid "0x03f0" "0x2505" :url "http://ftp.cyberbaladeur.fr/3770.tar.gz" ; model's URL :comment "External backend. Binary-only Linux i386 code. Not supported by the SANE developers. Is reported to scan only a small area? Scanning of slides or negatives is not implemented." sane-backends-1.0.27/doc/descriptions-external/utsushi.desc0000664000175000017500000002050113106201017020646 00000000000000;;; utsushi.desc -*- emacs-lisp -*- (sort of) ;;; Copyright (C) 2015, 2016 Meeuwissen ;;; ;;; License: GPL-3.0+ ;;; Author : Olaf Meeuwissen ;;; ;;; This file is part of the 'Utsushi' package. ;;; This package is free software: you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation, either version 3 of the License or, at ;;; your option, any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You ought to have received a copy of the GNU General Public License ;;; along with this package. If not, see . ;; Backend data ;; :backend "utsushi" :url "https://github.com/utsushi/utsushi" ;; Device and manufacturer information. ;; :devicetype :scanner :mfg "EPSON" :url "http://www.epson.com/" ;; List of EPSON scanners and all-in-ones. :model "DS-40" :interface "USB" :usbid "0x04b8" "0x0152" :status :good :model "DS-510" :interface "USB" :usbid "0x04b8" "0x014c" :status :good :model "DS-520" :interface "USB" :usbid "0x04b8" "0x0154" :status :good :model "DS-560" :interface "USB" :usbid "0x04b8" "0x0150" :status :good :model "DS-760" :interface "USB" :usbid "0x04b8" "0x014d" :status :good :model "DS-780N" :interface "USB" :usbid "0x04b8" "0x0164" :status :good :model "DS-860" :interface "USB" :usbid "0x04b8" "0x014d" :status :good :model "DS-5500" :interface "USB" :usbid "0x04b8" "0x0145" :status :good :model "DS-6500" :interface "USB" :usbid "0x04b8" "0x0145" :status :good :model "DS-7500" :interface "USB" :usbid "0x04b8" "0x0145" :status :good :model "DS-50000" :interface "USB" :usbid "0x04b8" "0x0146" :status :good :model "DS-60000" :interface "USB" :usbid "0x04b8" "0x0146" :status :good :model "DS-70000" :interface "USB" :usbid "0x04b8" "0x0146" :status :good :model "EP-10VA" :interface "USB" :usbid "0x04b8" "0x1108" :status :good :model "EP-808A" :interface "USB" :usbid "0x04b8" "0x110a" :status :good :model "EP-978A3" :interface "USB" :usbid "0x04b8" "0x1109" :status :good :model "ES-400" :interface "USB" :usbid "0x04b8" "0x0156" :status :good :model "ET-2500" :interface "USB" :usbid "0x04b8" "0x1105" :status :good :model "ET-2550" :interface "USB" :usbid "0x04b8" "0x1106" :status :good :model "ET-4500" :interface "USB" :usbid "0x04b8" "0x1107" :status :good :model "ET-4550" :interface "USB" :usbid "0x04b8" "0x1101" :status :good :model "L220" :interface "USB" :usbid "0x04b8" "0x08d1" :status :good :model "L360" :interface "USB" :usbid "0x04b8" "0x08d1" :status :good :model "L365" :interface "USB" :usbid "0x04b8" "0x08d2" :status :good :model "L366" :interface "USB" :usbid "0x04b8" "0x08d2" :status :good :model "L455" :interface "USB" :usbid "0x04b8" "0x08c2" :status :good :model "L565" :interface "USB" :usbid "0x04b8" "0x08d3" :status :good :model "L566" :interface "USB" :usbid "0x04b8" "0x08d3" :status :good :model "L655" :interface "USB" :usbid "0x04b8" "0x1101" :status :good :model "PX-M7050" :interface "USB" :usbid "0x04b8" "0x08bc" :status :good :model "PX-M7050FX" :interface "USB" :usbid "0x04b8" "0x08cc" :status :good :model "PX-M840FX" :interface "USB" :usbid "0x04b8" "0x08cd" :status :good :model "PX-M860F" :interface "USB" :usbid "0x04b8" "0x08ce" :status :good :model "WF-6530" :interface "USB" :usbid "0x04b8" "0x08cd" :status :good :model "WF-6590" :interface "USB" :usbid "0x04b8" "0x08cf" :status :good :model "WF-8510" :interface "USB" :usbid "0x04b8" "0x08bc" :status :good :model "WF-8590" :interface "USB" :usbid "0x04b8" "0x08bc" :status :good :model "WF-R8590" :interface "USB" :usbid "0x04b8" "0x08cc" :status :good :model "XP-220" :interface "USB" :usbid "0x04b8" "0x08c0" :status :good :model "XP-230" :interface "USB" :usbid "0x04b8" "0x1102" :status :good :model "XP-235" :interface "USB" :usbid "0x04b8" "0x1102" :status :good :model "XP-322" :interface "USB" :usbid "0x04b8" "0x1103" :status :good :model "XP-335" :interface "USB" :usbid "0x04b8" "0x1103" :status :good :model "XP-430" :interface "USB" :usbid "0x04b8" "0x1104" :status :good :model "XP-432" :interface "USB" :usbid "0x04b8" "0x1104" :status :good :model "XP-435" :interface "USB" :usbid "0x04b8" "0x1104" :status :good :model "XP-530" :interface "USB" :usbid "0x04b8" "0x110c" :status :good :model "XP-830" :interface "USB" :usbid "0x04b8" "0x110b" :status :good :model "XP-960" :interface "USB" :usbid "0x04b8" "0x1109" :status :good ; These are models for which we don't know the model name yet. ; Upstream releases have stopped providing the information we ; need to fill out the :model fields :-( :model "PID 0155" :interface "USB" :usbid "0x04b8" "0x0155" :status :good :model "PID 0157" :interface "USB" :usbid "0x04b8" "0x0157" :status :good :model "PID 0159" :interface "USB" :usbid "0x04b8" "0x0159" :status :good :model "PID 015A" :interface "USB" :usbid "0x04b8" "0x015a" :status :good :model "PID 015C" :interface "USB" :usbid "0x04b8" "0x015c" :status :good :model "PID 015D" :interface "USB" :usbid "0x04b8" "0x015d" :status :good :model "PID 015E" :interface "USB" :usbid "0x04b8" "0x015e" :status :good :model "PID 015F" :interface "USB" :usbid "0x04b8" "0x015f" :status :good :model "PID 0162" :interface "USB" :usbid "0x04b8" "0x0162" :status :good :model "PID 0163" :interface "USB" :usbid "0x04b8" "0x0163" :status :good :model "PID 110D" :interface "USB" :usbid "0x04b8" "0x110d" :status :good :model "PID 110F" :interface "USB" :usbid "0x04b8" "0x110f" :status :good :model "PID 1112" :interface "USB" :usbid "0x04b8" "0x1112" :status :good :model "PID 1113" :interface "USB" :usbid "0x04b8" "0x1113" :status :good :model "PID 1114" :interface "USB" :usbid "0x04b8" "0x1114" :status :good :model "PID 1115" :interface "USB" :usbid "0x04b8" "0x1115" :status :good :model "PID 1116" :interface "USB" :usbid "0x04b8" "0x1116" :status :good :model "PID 1117" :interface "USB" :usbid "0x04b8" "0x1117" :status :good :model "PID 1118" :interface "USB" :usbid "0x04b8" "0x1118" :status :good :model "PID 1119" :interface "USB" :usbid "0x04b8" "0x1119" :status :good :model "PID 111A" :interface "USB" :usbid "0x04b8" "0x111a" :status :good :model "PID 111B" :interface "USB" :usbid "0x04b8" "0x111b" :status :good :comment "EP-879A?" :model "PID 111C" :interface "USB" :usbid "0x04b8" "0x111c" :status :good :model "PID 111D" :interface "USB" :usbid "0x04b8" "0x111d" :status :good :model "PID 111E" :interface "USB" :usbid "0x04b8" "0x111e" :status :good :model "PID 111F" :interface "USB" :usbid "0x04b8" "0x111f" :status :good :model "PID 1120" :interface "USB" :usbid "0x04b8" "0x1120" :status :good :model "PID 1121" :interface "USB" :usbid "0x04b8" "0x1121" :status :good :model "PID 1122" :interface "USB" :usbid "0x04b8" "0x1122" :status :good :model "PID 1123" :interface "USB" :usbid "0x04b8" "0x1123" :status :good :comment "EP-30VA?" :model "PID 1125" :interface "USB" :usbid "0x04b8" "0x1125" :status :good :model "PID 1126" :interface "USB" :usbid "0x04b8" "0x1126" :status :good :model "PID 1127" :interface "USB" :usbid "0x04b8" "0x1127" :status :good :model "PID 1128" :interface "USB" :usbid "0x04b8" "0x1128" :status :good :model "PID 112B" :interface "USB" :usbid "0x04b8" "0x112b" :status :good sane-backends-1.0.27/doc/descriptions-external/geniusvp2.desc0000664000175000017500000000237712112021330021071 00000000000000; ; SANE Backend specification file ; :backend "geniusvp2" ; backend's name ;:version "0.2" ; backend's version (or "unmaintained") ;:manpage "sane-geniusvp2" ; manpage name :url "http://sourceforge.net/projects/geniusvp2/" ; backend's web page :comment "Supports color mode, bit depth of 8, 75-600 dpi resolution" ; comment about the backend :devicetype :scanner ; start of a list of devices.... :mfg "Genius" ; name a manufacturer :url "http://www.genius-kye.com/" ; manufacturer's URL :model "ColorPage-Vivid Pro II" ; name models for above-specified mfg. :status :basic ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "Parport (EPP)" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :comment "Similar to Primax Colorado Direct 9600, but with EICI 091000 ASIC" ; comment about the model sane-backends-1.0.27/doc/descriptions-external/hpoj.desc0000664000175000017500000000254712112021330020106 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hpoj" ; name of backend :version "(unmaintained)" ; version of backend :url "http://hpoj.sourceforge.net/" ; backend's web page :comment "HPOJ is not maintained anymore. It's recommended to use the hpaio (hplip) backend instead of HPOJ." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/go/all-in-one" ; name models for above-specified mfg. :model "Most HP OfficeJet, LaserJet, and PSC (Printer/Scanner/Copier) multi-function peripherals" :url "http://hpoj.sourceforge.net/suplist.shtml" :interface "Parport(ECP) USB JetDirect" :status :good :comment "HPOJ is not maintained anymore. It's recommended to use the hpaio (hplip) backend instead of hpoj." :usbid "ignore" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. sane-backends-1.0.27/doc/descriptions-external/kodak-twain.desc0000664000175000017500000000410212617742237021376 00000000000000:backend "kodak-twain" ; name of backend :version "unknown" ; version of backend (or "unmaintained") :url "http://www.kodak.com/go/scanonlinux" ; :comment "External backend developed by Kodak. Provides full access to the supported Kodak scanners by providing a SANE interface to the proprietary Kodak 32bit TWAIN stack. Several Linux distributions are supported." :devicetype :scanner ; start of a list of devices.... :mfg "Kodak" ; name a manufacturer :url "http://www.kodak.com/" ; manufacturer's URL :model "i1210" :status :untested :interface "USB" :usbid "0x040a" "0x600a" :comment "No report yet." :model "i1220" :status :untested :interface "USB" :usbid "0x040a" "0x600b" :comment "No report yet." :model "i1310" :status :untested :interface "USB" :usbid "0x040a" "0x600c" :comment "No report yet." :model "i1320" :status :untested :interface "USB" :usbid "0x040a" "0x600d" :comment "Reported to work on Fedora 12." :model "i1405" :status :untested :interface "USB" :usbid "0x040a" "0x601a" :comment "No report yet." :model "i1410" :status :untested :interface "USB" :usbid "0x040a" "0x600e" :comment "No report yet." :model "i1420" :status :untested :interface "USB" :usbid "0x040a" "0x600f" :comment "No report yet." :model "i1440" :status :untested :interface "USB" :usbid "0x040a" "0x6010" :comment "No report yet." :model "i2400" :status :untested :interface "USB" :usbid "0x040a" "0x601c" :comment "No report yet." :model "i2600" :status :untested :interface "USB" :usbid "0x040a" "0x601d" :comment "No report yet." :model "i2800" :status :untested :interface "USB" :usbid "0x040a" "0x601e" :comment "No report yet." :model "i1000 A3 accessory" :status :untested :interface "USB" :usbid "0x040a" "0x6012" :comment "Flatbed attachment for use with Kodak ADF scanner. Requires 12V power over usb cable. No report yet." :model "i1000 A4 accessory" :status :untested :interface "USB" :usbid "0x040a" "0x6011" :comment "Flatbed attachment for use with Kodak ADF scanner. Requires 12V power over usb cable. No report yet." sane-backends-1.0.27/doc/descriptions-external/panamfs.desc0000664000175000017500000000335012775312261020611 00000000000000; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "panamfs" ; name of backend ;:version "1.0.0" ; version of backend (or "unmaintained") ;:new :yes ; Is the backend new to this SANE release? ; :yes or :no ;:manpage "sane-template" ; name of manpage (if it exists) :url "http://panasonic.net/pcc/support/fax/common/table/linuxdriver.html" ; backend's web page :comment "External backend made by panasonic." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Panasonic" ; name a manufacturer :url "http://panasonic.net/" ; manufacturer's URL ;:comment "" ; comment about the manufacturer :model "DP-MC210" :status :untested :comment "No report yet." :model "DP-MB250" :status :untested :comment "No report yet." :model "DP-MB300 series" :status :untested :comment "No report yet." :model "KX-MB1500 series" :status :untested :comment "No report yet." :model "KX-MB2000 series" :status :untested :comment "No report yet." :model "KX-MB3000 series" :status :untested :comment "No report yet." :model "KX-MC6000 series" :status :untested :comment "No report yet." sane-backends-1.0.27/doc/sane-epsonds.man0000664000175000017500000000632713106201017015062 00000000000000.TH sane\-epsonds 5 "29 Mar 2015" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-epsonds .SH NAME sane\-epsonds \- SANE backend for EPSON ESC/I-2 scanners .SH DESCRIPTION The .B sane\-epsonds library implements a SANE (Scanner Access Now Easy) backend that provides access to Epson ESC/I-2 scanners. .PP Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d epsonds .RE Not all devices support all options. .TP .I Scan Mode The .I \-\-mode switch selects the basic mode of operation of the scanner. Valid choices are Lineart, Gray and Color. The Lineart mode is black and white only, Gray will produce 256 levels of gray or more depending on the scanner and Color means 24 bit color mode or more depending on the scanner. Some scanners will internally use 36 bit color, their external interface however may only support 24 bits. The .I \-\-depth option selects the bit depth the scanner is using. This option is only available for scanners that support more than one bit depth. Older scanners will always transfer the image in 8bit mode. Newer scanners allow one to select either 8 bits, 12 or 14 bits per color channel. For a color scan this means an effective color depth of 36 or 42 bits over all three channels. The valid choices depend on the scanner model. The .I \-\-resolution switch selects the resolution for a scan. Some EPSON scanners will scan in any resolution between the lowest and highest possible value. The list reported by the scanner can be displayed using the "\-\-help \-d epson" parameters to scanimage. The geometry options .I \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters. The .I \-\-source option selects the scan source. Valid options depend on the installed options. The default is "Flatbed". The .I \-\-eject option ejects the sheet in the ADF. The .I \-\-adf-mode option select the ADF mode (simplex/duplex). .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/epsonds.conf specifies the device(s) that the backend will use. Possible connection types are: .TP .I USB For not automatically detected USB scanners, their VENDOR and PRODUCT ID can be specified manually in the config file. More information about valid syntax for USB devices can be found in sane\-usb(5). .TP .I Network (not yet supported) Network scanners can be auto-discovered if .I autodiscovery is specified after .I net keyword. An IP address to connect to can also be used. .SH FILES .TP .I @LIBDIR@/libsane\-epsonds.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-epsonds.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_EPSONDS If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. Values around 11-16 will usuallybe enough for a bug report. .SH "SEE ALSO" sane\-usb(5), scanimage(1), xscanimage(1), xsane(1) .SH AUTHOR The package is written by Alessandro Zummo sane-backends-1.0.27/doc/sane-kvs40xx.man0000664000175000017500000000157312775277260014764 00000000000000.TH sane\-kvs40xx 5 "03 Jun 2011" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-kvs40xx .SH NAME sane\-kvs40xx \- SANE backend for Panasonic KV-S40xxC USB/SCSI ADF scanners. .SH DESCRIPTION The .B sane\-kvs40xx library implements a SANE (Scanner Access Now Easy) backend which provides access to the Panasonic KV-S40xxC and KV-S70xxC scanners. .SH KNOWN ISSUES This document was written by the SANE project, which has no information regarding the capabilities or reliability of the backend. All information contained here is suspect. The backend uses pthreads directly, and so requires pthreads to be enabled. .SH CREDITS The backend was written by Panasonic Russia Ltd. The backend was ported to sane-backends 1.0.23 and downgraded to C89 by m. allan noah. .SH "SEE ALSO" sane(7), sane\-usb(5), sane\-scsi(5) .SH AUTHOR m. allan noah: sane-backends-1.0.27/doc/sane-umax.man0000664000175000017500000001612512775277260014406 00000000000000.TH sane\-umax 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-umax .SH NAME sane\-umax \- SANE backend for UMAX scanners .SH ABOUT THIS FILE This file only is a short description of the umax-backend for sane! For detailed information take a look at sane\-umax\-doc.html (it is included in the sane source directory and in the xsane online help)! .SH DESCRIPTION The .B sane\-umax library implements a SANE backend that provides access to several UMAX-SCSI-scanners and some Linotye Hell SCSI-scanners, parallel- and USB-scanners are not (and probably will never be) supported! .B I suggest you hold one hand on the power-button of the scanner while you try the first scans! .SH CONFIGURATION The configuration file for this backend resides in .IR @CONFIGDIR@/umax.conf . Its contents is a list of device names that correspond to UMAX and UMAX compatible scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .nf # this is a comment # option scsi\-maxqueue 4 option scsi\-buffer\-size\-min 65536 option scsi\-buffer\-size\-max 131072 option scan\-lines 40 option preview\-lines 10 option scsi\-maxqueue 2 option execute\-request\-sense 0 option force\-preview\-bit\-rgb 0 option slow\-speed \-1 option care\-about\-smearing \-1 option calibration\-full\-ccd \-1 option calibration\-width\-offset \-1 option calibration\-bytes\-pixel \-1 option exposure\-time\-rgb\-bind \-1 option invert\-shading\-data \-1 option lamp\-control\-available 0 option gamma\-lsb\-padded 0 /dev/sge \ #scsi Vendor Model Type Bus Channel ID LUN # The following scanner supports lamp control option lamp\-control\-available 1 scsi UMAX * Scanner * * * * * \ # scanner on /dev/scanner does not support lamp control option lamp\-control\-available 0 /dev/scanner .fi .TP execute\-request\-sense: values: 0 = disabled, 1 = enabled .br default = 0 .br If set to 1 umax_do_request_sense is called in umax_do_calibration. This can hang the system (but has been enabled until this version) .TP scsi\-buffer\-size\-min, scsi\-buffer\-size\-max: values: 4096-1048576 .br default min = 32768, max = 131072 .br Especially the minimum value is very important. If this value is set too small the backend is not able to send gamma tables to the scanner or to do a correct color calibration. This may result in strange color effects. If the minimum value is set too large then the backend is not able to allocate the requested scsi buffer size and aborts with out of memory error. The default is 32KB, for some scanners it should be increased to 64KB. .TP scan\-lines, preview\-lines: values: 1-65535 .br default: scan\-lines = 40, preview\-lines = 10 .br define the maximum number of lines that are scanned into one buffer .TP force\-preview\-bit\-rgb: values: 0 = disabled, 1 = enabled .br default = 0 .br set preview bit in rgb real scan .TP slow\-speed, care\-about\-smearing: values: \-1 = auto, 0 = disabled, 1 = enabled .br default = \-1 .br dangerous options, needed for some scanners do not changed these options until you really know what you do, you may destroy your scanner when you define wrong values for this options .TP calibration\-full\-ccd: values: \-1 = auto, 0 = disabled, 1 = enabled .br default = \-1 .br do calibration for each pixel of ccd instead of selected image .TP calibration\-width\-offset: values: \-99999 = auto, > \-99999 set value .br add an offset width to the calculated with for image/ccd .TP calibration\-bytes\-pixel: values: \-1 = disabled, 0 = not set, 1 = 1 byte/pixel, 2 = 2 bytes/pixel .br use # bytes per pixel for calibration .TP exposure\-time\-rgb\-bind: values: \-1 = automatically set by driver \- if known, 0 = disabled (own selection for red, green and blue), 1 = enabled (same values for red, green and blue) .TP invert\-shading\-data: values: \-1 = automatically set by driver \- if known, 0 = disabled, 1 = enabled .br default = \-1 .br invert shading data before sending it back to the scanner .TP lamp\-control\-available: values: 0 = automatically set by driver \- if known, 1 = available .br default = 0 .TP gamma\-lsb\-padded: values: \-1 = automatically set by driver \- if known, 0 = gamma data is msb padded, 1 = gamma data is lsb padded .br default = \-1 .TP handle\-bad\-sense\-error: values: 0 = handle as device busy, 1 = handle as ok, 2 = handle as i/o error, 3 = ignore bad error code \- continue sense handler .br default = 0 .TP scsi\-maxqueue: values: 1..# (maximum defined at compile time) .br default = 2 .br most scsi drivers allow internal command queueing with a depth of 2 commands. In most cases it does not mprove anything when you increase this value. When your scsi driver does not support any command queueing you can try to set this value to 1. .PP The special device name must be a generic SCSI device or a symlink to such a device. To find out to which device your scanner is assigned and how you have to set the permissions of that device, have a look at sane\-scsi. .SH SCSI ADAPTER TIPS The ISA-SCSI-adapters that are shipped with some Umax-scanners are not supported very well by Linux (I suggest not to use it), the PCI-SCSI-adapters that come with some Umax-scanners are not supported at all (as far as I know). On other platforms these SCSI-adapters are not supported. So you typically need to purchase another SCSI-adapter that is supported by your platform. See the relevant hardware FAQs and HOWTOs for your platform for more information. The UMAX-scanners do block the scsi-bus for a few seconds while scanning. It is not necessary to connect the scanner to its own SCSI-adapter. But if you need short response time for your SCSI-harddisk (e.g. if your computer is a file-server) or other scsi devices, I suggest you use an own SCSI-adapter for your UMAX-scanner. If you have any problems with your Umax scanner, check your scsi chain (cable length, termination, ...). See also: sane\-scsi(5) .SH FILES .TP The backend configuration file: .I @CONFIGDIR@/umax.conf .TP The static library implementing this backend: .I @LIBDIR@/libsane\-umax.a .TP The shared library implementing this backend: .I @LIBDIR@/libsane\-umax.so (present on systems that support dynamic loading) .SH ENVIRONMENT .TP .B SANE_DEBUG_UMAX If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity: SANE_DEBUG_UMAX values .ft CR .nf Number Remark \ 0 print important errors (printed each time) 1 print errors 2 print sense 3 print warnings 4 print scanner-inquiry 5 print information 6 print less important information 7 print called procedures 8 print reader_process messages 10 print called sane\-init-routines 11 print called sane\-procedures 12 print sane infos 13 print sane option-control messages .fi .ft R .TP Example: export SANE_DEBUG_UMAX=8 .SH BUGS X-resolutions greater than 600 dpi sometimes make problems .SH SEE ALSO sane(7) .SH AUTHOR Oliver Rauch .SH EMAIL-CONTACT Oliver.Rauch@Rauch-Domain.DE sane-backends-1.0.27/doc/gamma4scanimage.man0000664000175000017500000000355112112021330015467 00000000000000.TH gamma4scanimage 1 "10 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX gamma4scanimage .SH NAME gamma4scanimage \- create a gamma table for scanimage .SH SYNOPSIS .B gamma4scanimage .I gamma .RI [ shadow .RI [ highlight .RI [ maxin .RI [ maxout ]]]] .SH DESCRIPTION The tool .B gamma4scanimage creates a gamma table in the format expected by scanimage. You can define a .BR gamma, a .BR shadow and a .BR highlight value. You also can specify the size .RB ( maxin ) and maximum output value .RB ( maxout ) of the gamma table. .PP .BR gamma is a floating point value, neutral value is 1.0, if the value is larger than 1.0 then the image gets brighter. .PP .BR shadow defines the minimum input value that is necessary to create an output value larger than zero. shadow has to be in the range [0..maxin]. Its default value is 0. .PP .BR highlight defines the maximum input value that produces an output value smaller than maxout. highlight has to be in the range [0..maxin], highlight has to be larger than shadow. Its default value is the same as maxin (16383 if not set). .PP .BR maxin defines the size of the gamma table. The size depends on the scanner/backend. If the scanner uses 8 bits gamma input then maxin has to be set to 255, for 10 bits 1023, for 12 bits 4095, for 14 bits 16383. The default is 16383. To find out what value maxin has to be call scanimage with a very large gamma table [0]0-[99999]255 then scanimage prints an error message with the needed size of the gamma table. .PP .BR maxout defines the maximum output value. Take a look at the output of scanimage \-h to find out what maxout has to be. The default value is 255. .PP .SH EXAMPLE .B scanimage \-\-custom\-gamma=yes \-\-gamma\-table .I `gamma4scanimage 1.8 0 11500 16383 255` >image.pnm .SH SEE ALSO .BR scanimage (1) .SH AUTHOR Oliver Rauch .SH EMAIL-CONTACT Oliver.Rauch@Rauch-Domain.DE sane-backends-1.0.27/doc/sceptre/0000775000175000017500000000000013110600532013503 500000000000000sane-backends-1.0.27/doc/sceptre/s1200.txt0000664000175000017500000000572112112021330014730 00000000000000Scanner overview - One pass scanner - 10 DPI minimum. Max X=600 dpi, max Y=1200 dpi. - A4 size /*--------------------------------------------------------------------------*/ Components: - Weltrend WT8616 - TEMIC TSC 80C31 (CMOS 0 to 44 MHz Single-Chip 8 Bit Microcontroller) /*--------------------------------------------------------------------------*/ SCSI overview - the SCSI implementation in this scanner is non-standard but simple. - there is no REQUEST SENSE command. - since there is no sense, it is impossible to know if a command has succeeded. /*--------------------------------------------------------------------------*/ SCSI commands: TEST UNIT READY 00 00 00 00 01 00 Returns 1 byte of data: 00 = scanner ready ff = scanner not ready Vendor Spec 02 00 00 00 04 00 Get 4 bytes of status. Used to check the button. Default result when the button is not pressed 06 00 00 00 INQUIRY result: 06 00 02 02 30 00 00 10 4b 49 4e 50 4f 20 20 20 ....0...KINPO 56 69 76 69 64 73 63 61 6e 20 53 31 32 30 20 20 Vividscan S120 53 31 33 20 20 20 20 20 02 01 00 00 4a 45 46 46 S13 ....JEFF ... MODE SEL 15 10 00 00 18 00 SCAN 1B 00 00 00 00 00 RECEIVE DIAG 1C 00 00 00 03 00 SEND DIAG 1D 00 80 00 00 00 SET WINDOW 24 00 00 00 00 00 00 00 52 00 The window size is always 0x52 bytes. The parameters look standard: - X/Y resolution | - Upper left X,Y |- all three coded in 600 dpi units - Width, Length | The supported scan modes are: - lineart image comp=0, halftone=0, depth=1 - halftone image comp=0, haltone=1 to 4, depth=1 - grayscale image comp=2, halftone=0, depth=8 - color image comp=5, halftone=0, depth=24 Y resolution is not used (X is also used for Y) X resolution is limited to 600 (if above, scanner defaults to 600) Y resolution is limited to 1200 (if above, scanner defaults to 1200) Image composition is byte 33, halftone is byte 36, depth is byte 34 READ (10) 28 00 00 00 00 00 00 FE 9A 00 SEND (10) 2A 00 03 00 00 02 00 03 00 00 Sends 300h bytes of gamma. 100h bytes per color. What is the color order? GET DATA BUFFER STATUS 34 01 00 00 00 00 00 00 10 00 Returns: - byte 0 to 7: ? (these bytes looks rather standard) - byte 8 to 11: total size left to read - byte 12 to 13: number of lines (constant during a scan) - byte 14 to 15: pixels per line (constant during a scan) /*--------------------------------------------------------------------------*/ Color shifts Color order returned by the scanner is Red, then Green, then Blue. There is a color shift, meaning the raster for the Red is not followed by the Green raster for the same line. The shifts are: dpi lines per color 1200 16 1125 15 1050 14 900 12 750 10 600 8 450 6 300 4 150 2 90 1 75 1 50 0 Some resolution give garbage. However that table might not be complete. sane-backends-1.0.27/doc/plustek/0000775000175000017500000000000013110600532013525 500000000000000sane-backends-1.0.27/doc/plustek/Plustek-PARPORT.txt0000664000175000017500000000314212617742237017006 00000000000000Plustek-PARPRORT.txt (2004-03-28) Gerhard Jäger ==================================================================== Beginning with SANE-1.0.13, there's a backend called plustek_pp. This is for controlling Plustek parallel-port scanner and compatible devices. For a full listing, see plustek_pp.desc. This code formerly was available for creating the Linux kernelmodule pt_drv. This should no longer be necessary. You should be able to use the backend out of the box. The kernel module ----------------- As it might be helpful to create and use the kernel-module, this way still exists. It's possible to create this module out of the backend sources in sane-backends/backend. Simply do (as root user) ./MakeModule.sh Then the module should be compiled, installed and loaded. Add the following three lines to file /etc/modules.conf alias char-major-40 pt_drv pre-install pt_drv modprobe -k parport options pt_drv lampoff=180 warmup=15 port=0x378 lOffonEnd=0 mov=0 slowIO=1 See man page for sane-plustek_pp ("man sane-plustek_pp") for explanation of these options. Now "scanimage -L" should show something like this: device `plustek:/dev/pt_drv' is a Plustek 9630P flatbed scanner Known Problems: --------------- Sometimes it is necessary to change the ioctl-interface between the driver and the backend, in this case the version number of the communication protocol will be changed and newer drivers won't work with older backends and vice versa. In this case (error -9019 in the SANE debug output!!) you have to recompile SANE AND the driver (have a look at the installation procedure above). sane-backends-1.0.27/doc/plustek/Plustek-USB-TODO.txt0000664000175000017500000000520512112021330017023 00000000000000Plustek-USB-TODO.txt (2007-12-13) Gerhard Jaeger ===================================================================== TODO (in general): - more documentation/comments for the different functions - replace mclk_fast stuff and use instead values from 75DPI grayscale KNOWN BUGS/Limitations: Model Description Workaround ------------------------------------------------------------------------------ HP 2100c Straight Line Bug none Bearpaw1200 works only once restart backend each time All with TPA Negative Scanning quality bad none CIS devices Skip calibration does not work none ********************************* DONE *************************************** all add plustek.conf presettings to done interface for frontends all Auto-warmup done all Sensor movement speedup ffw/rev done Canon fine calibration does not work fixed Canon 650 color modes >=600 dpi too dark fixed Canon 660 add support done Canon 1220 image quality not very good fixed Canon 1240 gray mode too bright fixed HP 2100c hits against scan-bed fixed Genius Devices not recognized fixed EPSON Photo Permanently warmup on TPA scanning fixed EPSON Photo Transparency mode does not work fixed correctly all binary mode does not work correctly done Canon 16bit gray mode does not work done EPSON 1250/60 Motor control settings are wrong fixed CanoScan 1240 added EPSON + HP vertical line bug fixed HP blooming on 42bit >=400dpi fixed UMAX5400 bad picture quality fixed UMAX3400 Straight Line Bug fixed all problems on ARM and XScale fixed Make the color modes > 8bit work correctly done make mono/gray modes work on Canon scanners done copy picture line by line to backend done cancel function does not work correctly in large resolutions fixed Move documents to its correct SANE place done sane-backends-1.0.27/doc/plustek/Plustek-USB.txt0000664000175000017500000003635712617742237016326 00000000000000Plustek-USB.txt (2005-08-08) Gerhard Jäger =============================================================== NOTE: ----- ALL YOU NEED TO RUN YOUR USB SCANNER IS ALREADY INCLUDED. THERE'S NO NEED TO INSTALL THE KERNEL MODULE pt_drv. THIS ONE IS ONLY NEEDED FOR THE PLUSTEK PARALLELPORT SCANNER. List of all currently implemented devices ----------------------------------------- Quite a lot of them are not tested or even identified. Please send me the ids of your device... PLUSTEK ======= Vendor ID: 0x07B3 Product ID Device-description and status 0x0005 not identified yet 0x0007 not identified yet 0x000F not identified yet 0x0010 U12 - working 0x0011 U24 (LM9831) - working 0x0012 not identified yet 0x0013 UT12 (LM9831) - working 0x0014 not identified yet 0x0015 U24 (LM9832) - working 0x0016 not identified yet 0x0017 UT12 - working, UT16 - working, UT24 - working MUSTEK ====== BearPaw vendor ID: 0x0400 (They use the NationalSemiconductors ID!!!) Product ID Device-description and status 0x1000 BearPaw 1200 (LM9831) - working 0x1001 BearPaw 1200 (LM9832) - not tested 0x1001 BearPaw 2400 (LM9832) - mostly working KYE (Genius) ============ Vendor ID: 0x0458 Product ID Device-description and status 0x2007 ColorPage-HR6 V2 - working 0x2008 ColorPage-HR6 V2 - not tested 0x2009 ColorPage-HR6A - not tested 0x2013 ColorPage-HR7 - working 0x2015 ColorPage-HR7LE - not tested 0x2016 ColorPage-HR6X - not tested Hewlett Packard =============== Vendor ID: 0x03F0 Product ID Device-description and status 0x0505 HP Scanjet 2100c - working 0x0605 HP Scanjet 2200c - working EPSON ===== Vendor ID: 0x04b8 Product ID Device-description and status 0x010F EPSON Perfection 1250/Photo - working 0x011D EPSON Perfection 1260/Photo - working UMAX ==== Vendor ID: 0x1606 Product ID Device-description and status 0x0050 UMAX 3400 - working 0x0060 UMAX 3400/3450 - working 0x0160 UMAX 5400 - working COMPAQ ====== Vendor ID: 0x049F Product ID Device-description and status 0x001A S4-100 - working, identical with UMAX 3400 CANON ===== Vendor ID: 0x04A9 Product ID Device-description and status 0x???? FB620U - not integrated 0x2206 N650U - working 0x2207 N1220U - working 0x2208 D660U - working 0x220D N670U/LiDE20 - working 0x2220 LiDE25 - working 0x220E N1240U/LiDE30 - working How to use and configure the Plustek USB backend ------------------------------------------------ Please note, that the following is only needed, if you need to upgrade a SANE version... Preparations ------------ What do we need ? a SANE backends archive (i.e. sane-backends-1.0.9.tar.gz) a driver archive (i.e. plustek-sane-0.45-1.tar.gz) The latest SANE archive can be obtained at: http://www.sane-project.org and the latest backend at: http://www.gjaeger.de/scanner/plustek.html Assumptions ----------- Our starting point is your home-directory: :~> The packages (here sane-backends-1.0.9.tar.gz und plustek-sane-0.45-1.tar.gz) are in the /tmp directory. Let's go: --------- Change to your home directory and create a sane directory cd ~ mkdir sane unpack your sane tar-ball (here "sane-backends-1.0.9.tar.gz") to this "sane" directory cd sane tar xvzf /tmp/sane-backends-1.0.9.tar.gz Now unpack your plustek-sane tarball (here "plustek-sane-0.45-1.tar.gz") to the backends directory: cd sane-backends-1.0.9 tar xvzf /tmp/plustek-sane-0.45-1.tar.gz Now do the ./configure step... Especially for SuSE with a preinstalled SANE-RPM: ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man --infodir=/usr/share/info Then do the make step and after that as root user perform the make install step. That's all! Before using, make sure that the USB scanner device driver is loaded: modprobe scanner or modprobe scanner vendor=0x7b3 product=0x17 You might need to add the following line to /etc/modules.conf, if the scanner is not supported directly - vendor and product must match your device! options scanner vendor=0x7b3 product=0x17 If you're not sure about the vendor and product id of your device, simply load the USB subsystem and plug in your scanner. Then do a cat /proc/bus/usb/devices and look for the scanner Now you have to configure the backend. Edit the file /etc/sane.d/plustek.conf and fill in the appropriate vendor and product id (see there for examples) This is it... Autoloading scanner.o --------------------- To perform an automatic load of the scanner module, you might add the modprobe line to your boot.local file. i.e. on SuSE system > 7.x /etc/init.d/boot.local An alternative way is to use the hotplug utilities. Using hotplug utilities and libusb ---------------------------------- When using libusb with SANE, then you should also use the hotplug utilities to automatically setup your device nodes (at least the permissions) and prevent scanner.o from loading. Assuming, that these utilites are properly installed on your box, you have to tweak and add some files. In directory (where of course the config files reside): /etc/hotplug Append the line scanner to file blacklist This prevents the scanner module from the usb-subsystem to be loaded. Next thing is to add a new line in usb.usermap: usbscanner 0x0003 0x1606 0x0160 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00 000000 The example line shows the vendor ID of UMAX 0x1606 and the product ID of the 5400 0x0160 - these values must match the ones of your scanner. Last step is adding a script in /etc/hotplug/usb/ It is called "usbscanner" (don't forget the executable rights) ------------------------------------------------- # !/bin/bash if [ "${ACTION}" = add ] && [ -f "${DEVICE}" ] then chgrp users "${DEVICE}" chmod ug+rw "${DEVICE}" fi ------------------------------------------------- This script will correct the access right to your scanner device when the device is plugged in. Debugging your USB scanner (written by Kev Green) ------------------------------------------------- Firstly, are you running the latest version of SANE, and the Plustek USB driver? Double check at http://www.gjaeger.de/scanner/plustek.html (Plustek USB driver) and http://www.sane-project.org (SANE Suite) to make sure you are. Now, in order to test and utilise your scanner with the Scanner Access Now Easy (SANE) system, there are basically two programs that you will need to use from the sane-frontends (versions post 1.0.3) or sane (versions pre 1.0.3) packages. Firstly, the sane-find-scanner program will allow you to locate your scanner, and help you work out if sane knows where it is. This is not definite however, as (you'll see this too when using sane-find-scanner) it will find all the scanners on your USB and SCSI bus, whereas sane will only work when you have the relevant sane backend installed and configured correctly for the relevant scanner. So, if sane-find-scanner can find your scanner, but scanimage doesn't work, then you need to check, double check, and even triple-check your SANE configuration file for plustek scanners (plustek.conf, usually in /etc/sane.d or maybe in /usr/local/sane/ or somewhere, a "find" will be able to tell you where. It may take a while though!). If sane-find-scanner doesn't find your scanner, then you should check to see if the kernel recognises it at all, which you can do with the following command, as mentioned above: cat /proc/bus/usb/devices If your scanner doesn't appear in there, then the kernel has not recognised it. There may however be a crypic-looking entry in there which doesn't name itself as plustek, in which case it is recognised as being there by the kernel, but is not know to the kernel's USB device database, in which case this should be mentioned on the plustek list (), from where the "powers that be" will deal with it. If that file does not exist in the /proc filesystem, then you don't have the "Preliminary USB filesystem" option set in your kernel, and you will need to recompile your kernel to allow you to do this step in debugging. If it exists, but is empty, you will have to make sure (use the kernel configure help information and the details of your motherboard to ascertain this!) you have the right one of UHCI or OHCI USB modules installed or compiled into your kernel. Once you've established that the kernel has recognised your scanner, you can start pointing the finger at SANE, or simply the "scanner" module. You will need to have selected the "USB Scanner" option in your kernel compilation as a module, or compiled into the kernel. If you have done neither, then SANE will simply not be able to recognise your scanner. Rectify that, if you are missing it. If you have carried out all of the above steps, then sane-find-scanner should be able to recognise your scanner correctly. sane-find-scanner probes all of the devices on the SCSI and USB busses, and so you may find that it outputs "unable to get minor data" errors or similar to your terminal, or to your error logs, you can safely ignore these as long as it does that, and has recognised your scanner. Once you have found your scanner okay using sane-find-scanner, then you are ready to start messing around with the actual scanimage program to attempt to scan an image in. Obviously (although this may turn out to be premature) you should now have something in your scanner ready to scan for verification. At this stage, you should begin to be warey, because while the USB stuff for Plustek scanners is in development it may (like any kernel/module related software) crash your system with a kernel panic, or simply just segfault, so for your own sake, close down all the applications you are running and ONLY use text console, rather than X-Windows at this point, as you will certainly want to avoid any potential filesystem corruption. At this point it's probably also good to ensure that you have selected the "Magic SysRq Key" option in the kernel hacking section of the kernel config, and done: echo 1 > /proc/sys/kernel/sysrq And of course read the readme for that in /usr/src/linux/Documentation, as that should allow you to avoid filesystem corruption during any crashes that might happen. Now, before running scanimage, you should enable the maximum levels of debugging possible in both the SANE core and in the Plustek scanner backend. To do this you should do: export SANE_DEBUG_PLUSTEK=12 export SANE_DEBUG_DLL=12 Now, if you run scanimage, you should be able to see the maximum debugging messages. If those messages don't tell you what is wrong, then take note of your scanner type, the contents of /proc/bus/usb/devices, and the contents of your error log, as well as (where possible) the output of the scanimage command (if you can't capture it directly, an as-accurate-as-possible description is MUCH better than nothing!), and try and get all of the activity that your scanner did as well (light came on? didnt? motors came on? etc?) and email that to the plustek list (). For the particularly adventurous only... You might want to try running the scanimage program through strace or gdb to see if you can go some or all of the way to debugging the problem yourself, and post the relevant (ie. last!) parts of those utilities output to the plustek-help list. If you don't know what strace or gdb are, then you should probably not try that. It's probably safe to run your scanner in a normal operating environment under Linux once you have got it working once in a text console. How to add a new LM9831/2 based device description -------------------------------------------------- If you have a LM9831 or LM9832 based scanner and your vendor and product id did not appear in the list above and you're willing to do some experiments, then simply add your device to the file plustek-devs.c at the end of the list. See the list at the end of the file how this works... Thanx guys for helping: ----------------------- Henning Meier-Geinitz henning@meier-geinitz.de for Mustek Bearpaw testing, ideas and patches Stefan Nilsen stefan.nilsen@telia.com for HP2200c testing and patches Kev Green kyrian@ore.org for Documentation, UT12 testing and RPMS. Holger Bischof bischof@cs.tu-berlin.de for OpticPro U12 testing Abhijit Sovakar a.sovakar@gmx.de for OpticPro UT24 testing Peter Koellner peter@mezzo.net for OpticPro U24 testing Gene Heskett gene_heskett@iolinc.net for EPSON 1250 testing and patches Tasnim Ahmed tasnim_ahmed@yahoo.com for KYE Colorpage HR6 testing Reinhard Max max@suse.de for EPSON 1250 testing and patches Allan N. Hessenflow allan@kallisti.com for UMAX 3400 testing and patches Craig Smoothey craig@smoothey.org for HP2100c testing and patches Till Kamppeter till.kamppeter@gmx.net for EPSON1260 testing Christopher Montgomery monty@xiph.org for CanoScan calibration works Olaf Leidinger leidola@newcon.de for CanoScan LiDE25 testing and a lot of other guys not named here... Some equations which are used to calculate some stuff ----------------------------------------------------- The stuff is used in plustek_usbscan.c to get the correct register settings out of the hardware descriptions: Crystalfrequency is 48MHz Pixel Period (seconds/pixel) ---------------------------- MCLK_DIV x 8 x CM PixelPeriod = ----------------- 48MHz Integration Time (seconds) -------------------------- Tint = PixelPeriod X LineLength MCLK_DIV x 8 x CM X LineLength Tint = ------------------------------ 48MHz Ideal MCLK Divider ------------------ 48MHz (DataPixelsEnd - DataPixelStart) MCLK_DIV = --------------------------- x -------------------------------- HostIORate x 8 x LineLength HDPI_ADJ x PP 48MHz (DataPixelsEnd - DataPixelStart) CM = ------------------------------- x -------------------------------- x ---- BytesPerSecond x 8 x LineLength HDPI_ADJ x PP CM 48MHz 1 = --------------------------- x Tint x --------- 8 x LineLength CM 48MHz (Tint * 1000) = ----------------------- x -------------------- 1000 x 8 x LineLength CM Ideal Scan Speed (inches/second) 1 1 1 ScanSpeed = ----------- x -------- x -------- PixelPeriod FSPI x 4 StepSize 48MHz 1 1 ScanSpeed = ----------------- x -------- x -------- MCLK_DIV x 8 x CM FSPI x 4 StepSize 48MHz MCLK_DIV = ------------------------------------------ ScanSpeed x 8 x CM x FSPI x 4 x StepSize ---------------- Symbols: CM - Color Mode (unitless), 3 for channel pixel rate color, else 1 ------------------------- sane-backends-1.0.27/doc/plustek/Makefile.kernel240000664000175000017500000001430512112021330016527 00000000000000# Makefile for the plustek scanner driver (kernel-module) # ############################################################################### # # define the directories # HOME_DIR := . SRC_DIR := $(HOME_DIR) INC_DIR := $(SRC_DIR) OBJ_DIR := $(HOME_DIR)/obj DOC_DIR := $(HOME_DIR)/doc BACKEND := $(SRC_DIR) # # define the used tools # MD = mkdir -p CC = gcc TAR = tar REF = cxref # # Comment/uncomment the following line to disable/enable debugging # can also be set by commandline parameter: make all DEBUG=y # #DEBUG = y # # common compiler options # OPT = -fomit-frame-pointer -D_PTDRV_VERSTR=\"$(VERSIONSTR)\" # # cxref options # REFOPT = -xref-all -index-all -html32 # # Comment out if you are not running SMP. Someone take this out of here # when the SMP stuff gets moved out of the kernel Makefile. # SMP = 1 # SMP_PROF = 1 # # add the following to get assembly listing # -Wa,-alh,-L -g # # get some version numbers # ifeq ($(LINUXVERSION),) LINUXVERSION = $(shell uname -r) endif VERSIONSTR = $(shell grep "define BACKEND_VERSION" $(SRC_DIR)/plustek_pp.c | cut -b25-50 ) # Change it here or specify it on the "make" commandline ifeq ($(HEADER_PATH),) MACHTYPE = $(shell env | grep debian-linux | wc -l | sed 's/ //g') ifeq ($(MACHTYPE),1) # debian HEADER_PATH = /usr/src/kernel-headers-$(LINUXVERSION)/include else # redhat, slackware HEADER_PATH = /usr/src/linux/include endif # HEADER_PATH = /usr/include endif ifeq ($(DEBUG),y) DEBFLAGS = -O -g -DDEBUG # "-O" is needed to expand inlines else DEBFLAGS = -O2 endif # # the new style reference # K24_HEADER_PATH = /lib/modules/$(LINUXVERSION)/build/include # # try to autodetect if we can use the new style header include references # KERNEL_HEADERS = $(shell if test -d $(K24_HEADER_PATH); then \ echo $(K24_HEADER_PATH); \ else \ echo $(HEADER_PATH); \ fi; ) # # seems to be necessary for kernels 2.4.x # MODVERFILE = $(shell if [ -e $(KERNEL_HEADERS)/linux/modversions.h ]; then \ echo $(KERNEL_HEADERS)/linux/modversions.h ; \ else \ echo $(KERNEL_HEADERS)/linux/modsetver.h ; \ fi ) MODFLAGS = -DMODULE # # set MODVERSIONS if the kernel uses it # VERSUSED = $(shell grep 'define CONFIG_MODVERSIONS' \ $(KERNEL_HEADERS)/linux/autoconf.h | wc -l | sed 's/ //g') ifeq ($(VERSUSED),1) MODFLAGS += -DMODVERSIONS -include $(MODVERFILE) endif WARNFLAGS = -Wall -Wstrict-prototypes CFLAGS = $(WARNFLAGS) $(OPT) -D__KERNEL__ -I$(KERNEL_HEADERS) -I$(INC_DIR) -I$(BACKEND) $(DEBFLAGS) $(MODFLAGS) MODLIB = /lib/modules/$(LINUXVERSION) ifdef SMP CFLAGS += -D__SMP__ ifdef SMP_PROF CFLAGS += -D__SMP_PROF__ endif endif TARGET = pt_drv OBJ = $(TARGET).o NAMES := dac detect genericio image map misc models io procfs NAMES := $(NAMES) motor p9636 ptdrv scale tpa p48xx p12 p12ccd NAMES := $(addprefix plustek-pp_, $(NAMES)) SRCS := $(addprefix $(SRC_DIR)/, $(NAMES)) SRCS := $(addsuffix .c, $(SRCS)) OBJS := $(addprefix $(OBJ_DIR)/, $(NAMES)) OBJS := $(addsuffix .o, $(OBJS)) INCS := scan dbg types scandata procs hwdefs sysdep INCS := $(addsuffix .h, $(INCS)) HDRS = $(addprefix $(INC_DIR)/plustek-pp_, $(INCS)) # # the header files we need from the backend # BACKINCS := plustek-pp.h BACKINCS := $(addprefix $(BACKEND)/, $(BACKINCS)) group = "root" mode = "644" INST_DIR = /lib/modules/$(LINUXVERSION)/kernel/drivers/char info: @clear @echo "Makefile to create the Plustek-Scanner kernel-module:" @echo "all ... builds the module" @echo "all DEBUG=y ... builds the module with debug-messages enabled" @echo "clean ... cleans up the show" @echo "install ... installs the module to the library path" @echo "uninstall ... removes the module from the library path" @echo "load ... tries to load the module and creates device nodes" @echo "unload ... unloads the module" all: .depend chkdir $(OBJ) # # create object directory # .PHONY : chkdir chkdir: @-$(MD) $(OBJ_DIR) @-$(MD) $(DOC_DIR) $(OBJ): $(OBJS) $(LD) -r $^ -o $@ $(OBJS): Makefile $(HDRS) $(BACKINCS) $(OBJ_DIR)/%.o : $(SRC_DIR)/%.c $(CC) $(CFLAGS) -c $< -o $@ $(OBJ_DIR)/$(OBJ): VERSION1 VERSION0 # # copy the driver to the modules directory # install: mkdir -p $(INST_DIR) install -c -m $(mode) $(OBJ) $(INST_DIR) /sbin/depmod -a # # remove it # uninstall: rm -f $(INST_DIR)/$(OBJ) # # use modprobe to load the driver, remember to set the # parameter in /etc/modules.conf (see sane-plustek_pp.man for more details) # load: $(INST_DIR)/$(OBJ) # invoke modprobe with all arguments we got /sbin/modprobe $(TARGET) || exit 1 # Remove stale nodes and replace them, then give gid and perms rm -f /dev/$(TARGET)* # when using the devfs support, we check the /dev/scanner entries # and only create links to the devfs nodes # at least we create one link @if [ -e /dev/scanner/$(TARGET)* ]; then \ ln -s /dev/scanner/$(TARGET)0 /dev/$(TARGET); \ for name in `ls /dev/scanner | grep $(TARGET)`; do \ ln -s /dev/scanner/$$name /dev/$$name ; \ done \ else \ mknod /dev/$(TARGET) c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 0; \ mknod /dev/$(TARGET)0 c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 0; \ mknod /dev/$(TARGET)1 c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 1; \ mknod /dev/$(TARGET)2 c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 2; \ mknod /dev/$(TARGET)3 c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 3; \ \ chgrp $(group) /dev/$(TARGET)*; \ chmod $(mode) /dev/$(TARGET)*; \ fi # # unload the driver # unload: /sbin/modprobe -r $(TARGET) || exit 1 # Remove stale nodes rm -f /dev/$(TARGET)* # # create reference docu # doc: chkdir $(REF) $(REFOPT) $(INC_DIR)/*.h $(SRC_DIR)/*.c $(BACKEND)/plustek-share.h \ -D__KERNEL__ -I$(KERNEL_HEADERS) -I$(INC_DIR) -I$(BACKEND) $(MODFLAGS) \ -D_PTDRV_V1=$(VERSION1) -D_PTDRV_V0=$(VERSION0) -D_PTDRV_BUILD=$(BUILD) -O$(DOC_DIR) clean: @-rm -f $(OBJ_DIR)/*.o .depend depend dep $(REF).* *.html $(TARGET).o @-rm -rf $(OBJ_DIR) @-rm -rf $(DOC_DIR) depend .depend dep: $(CC) $(CFLAGS) -M $(SRCS) > $@ ifeq (.depend,$(wildcard .depend)) #include .depend endif sane-backends-1.0.27/doc/plustek/Plustek-USB.changes0000664000175000017500000002040112775277260017102 00000000000000Plustek.changes - Gerhard Jaeger ===================================================== Note: All other not mentioned builds have never been released. V 0.52-11 (2013-02-13) --------------------- Added support for Q-Scan A6 scanner (see report #312073) V 0.52-10 (2012-03-19) --------------------- Fixed batch scanning V 0.52-9 (2009-04-27) --------------------- Tweaked highspeed settings for Epson 1260 V 0.52-8 (2008-08-25) --------------------- Added preliminary support for Visioneer XP100 Tweaked entry for LM9831 version of Plustek UT12 V 0.52-7 (2007-12-13) --------------------- Fixed alignment issues for archs like XScale/ARM Fixed dumppic function to get valid grayscale pictures V 0.52-6 (2007-11-23) --------------------- Tweaked TravelScan464 settings. Improved AFE gain calculation for CIS devices. This should avoid stripes in the scanned images. V 0.52-4 (2007-11-16) --------------------- Tweaked TravelScan464 settings Added possibility to disable dark-calibration with lamp on (touches devices like CanoScan1220 etc) Use attribute packed for data access structs V 0.52-4 (2007-11-07) --------------------- Added support for Syscan TravelScan464 V 0.52-3 (2007-07-26) --------------------- Checked UMAX3400/3450 models Force output bit set (MIO), when lamp is switched V 0.52-2 (2007-07-10) --------------------- Added flag to allow only 1- and 8-bit scanmodes. The Q-Scan does not seem to support 14-bit modes. V 0.52-1 (2007-06-29) --------------------- Added sheetfed device Q-Scan USB001 from Portable Peripherals Fixed Mustek Bearpaw and did some speedup (bugreports #304343 and #301763) Fixed calibration for senororders other that RGB V 0.51-16 (2007-03-05) ---------------------- Added CanoScan to all Canon device strings. Identified one more Plustek device as U24. Fixed button handling for Plustek/KYE devices and added some more debug messages. V 0.51-15 (2006-11-22) ---------------------- Fixed option descriptors (bugreport #303786) V 0.51-14 (2006-08-11) ---------------------- Lowered speed for LiDE20/30 models in low resolution mode (<75dpi) V 0.51-13 (2006-08-09) ---------------------- Changed sane.type to "flatbed scanner" only Fixed motorsettings for LiDE30 (bugreport #303722) Fixed LiDE20 settings. Got some reports of non-working devs, although my N670U is working fine. Lowered the max speeds and increased the MCLK-div for fast movement. (bugreport #303695) V 0.51-12 (2006-06-30) ---------------------- Fixed bit-depth selection V 0.51-11 (2006-06-08) ---------------------- Fixed calibration: All modes will be coarse calibrated now, fine calibration will be done only for 8 bit modes. Fixed paper eject during startup. V 0.51-10 (2006-05-28) --------------------- Released V 0.51-8 (2006-04-09) --------------------- Added cache for fine calibration (CIS devices only) Added support for sheet-fed scanner (CIS devices only) Added support for Syscan TravelScan662 V 0.50-10 (2006-01-31) --------------------- Fixed CanoScan N1220U settings. V 0.50-9 (2006-01-19) --------------------- Added high-speed setting for HP2200. Fixed constraint_type for OPT_BUTTON. V 0.50-8 (2006-01-18) --------------------- Fixed CanoScan N670U settings (bugreport #302433). V 0.50-7 (2005-10-28) --------------------- Changed high-speed setting for UMAX 3400, due to bugreport #302317. Added disable speeup feature (as option). Fixed CanoScan N650U settings (bugreport #302433). V 0.50-6 (2005-10-25) --------------------- Fixed segfault in fine calibration for CIS devices. Tweaked LiDE25 settings (thanks to Gerd Cendelin for lending me his LiDE25). Let 1200DPI CIS devices use now the green-channel for gray scans. V 0.50-5 (2005-10-21) --------------------- Fixed high-speed feature of CanoScan D660U. V 0.50-4 (2005-10-02) --------------------- Updated motor settings for Canoscan LiDE25, thanks to Stephan February for providing these values. V 0.50-3 (2005-08-22) --------------------- Fixed problem, when trying to scan at resolutions beyond the optical one (sensor stops too early) V 0.50-2 (2005-08-19) --------------------- More cleanup. Removed obsolete _WAF_BLACKFINE. LiDE20 does not seem to have a reliable black calibration area, so the devices now will switch off the lamp for dark calibration. Fixed line statistics and added calibration data output. V 0.50-1 (2005-08-15) --------------------- Cleanup Activated IPC between reader-process and parent Added button support for Plustek/Genius devices Did some whitespace cleanup and removed those *p typedefs Tried to improve CIS calibration (somewhat back to 1.0.13) Added _TWEAK_GAIN definition to allow CIS calibration increase gain values during basic lamp setup phase Added call to speedtest to CIS calibration Fixed CanoScan startup problem (the way misc I/Os will be set after power-up has done the trick) V 0.49-8 (2005-08-08) --------------------- Added LiDE25 settings V 0.49-7 (2005-07-21) --------------------- Bugfix release - fixed lampsettings for CIS calibration V 0.49-6 (2005-07-07) --------------------- Bugfix release - calibration and segfault :( V 0.49-5 (2005-07-04) --------------------- Added IPC between reader-process and parent process to be pepared for sharing calibration info. Added button support for backend V 0.49-4 (2005-06-27) --------------------- Fixed "double free" problem during sane_exit. V 0.49-3 (2005-04-18) --------------------- Fixed backtracking problem, when sensor-speedup is active. V 0.49-2 (2005-01-12) --------------------- Tweaked some device settings Updated copyright info Using now PhyDpi.y as selector for the motor MCLK range V 0.49-1 (2004-11-19) --------------------- Improved multi-device capability V 0.48-10 (2004-10-30) ---------------------- - Fixed a bug in buffer calculation for CIS devices V 0.48-9 (2004-10-19) --------------------- - Use the same option names for RGB gain as umax_pp backend V 0.48-8 (2004-10-06) --------------------- - split scanmodes & bit-depths V 0.48-7 (2004-10-04) --------------------- - changed some strings according to bug #300963 V 0.48-6 (2004-09-07) --------------------- - fixed UMAX lamp-off bug V 0.48-4 (2004-07-26) --------------------- - added speedup parameters for UMAX3400/3450 - added disableSpeedup option - added UMAX3400/3450 TPA autodetection V 0.48-3 (2004-07-16) --------------------- - improved autowarmup feature - improved speedup feature V 0.48-2 (2004-07-07) --------------------- - fixed binary mode for CanoScan D660U V 0.48-1 (2004-07-02) --------------------- - added more options to the frontend interface - added UMAX 3400 with product ID 0x0050 - added support for the UMAX 3450 - added autowarmup for CFL (most CCD-scanner) - added speedup for sensor for some devices - fixed lamp switching problem for D660U - fixed negative scanning lamp problem - fixed Gray 16 mode for CanoScan D660U - code cleanup V 0.47-11 (2004-04-21) ---------------------- - minor fixes, esp. for MacOSX - added lamp-off and warmup options to be configurable by backends V 0.47-8 - 0.47-10 ------------------ - never released V 0.47-7 (2004-02-08) --------------------- - fixed bypass calibration function for CIS devices - added lampoff stuff to config file V 0.47-6 (2004-01-21) --------------------- - Cleanup work - Changed lamp off timer for non-setitimer systems V 0.47-5 (2004-01-09) --------------------- - Added big-endian code to support also PPC architectures - Added mov (model override) to support various devices using the same product ID (namely Mustek BearPaw 1200) - Added per-model gamma values - Fixed a bug in the coarse CIS-lamp calibration - Cleanup work V 0.47-1 - 0.47-4 ----------------- - never released V 0.46-9 (2003-11-03) --------------------- - Added alternate calibration for CIS devices - Added coarse calibration data-cache - Moved parallelport code to extra backend file plustek_pp - Fixed some minor bugs - Fixed problem with CIS devices using FreeBSD V 0.46-1 - 0.46-8 ----------------- - never released V 0.45 (2003-08-05) ------------------- - Starting this changelog - Updates since V 0.44: * better CIS device support * added CanoScan N1220U, N1240U * made CanoScan N650U and N670U work * fixed EPSON 1260 motor killer-bug * improved TPA scanning * fixed TPA warmup bug on EPSON 1260/Photo * fixed Genius device detection problem * Added Compaq S4-100 (identical to UMAX3400) sane-backends-1.0.27/doc/plustek/Makefile.kernel260000664000175000017500000000562212112021330016533 00000000000000# Makefile for the plustek scanner driver (kernel-module) # ############################################################################### # # retrieve the version numbers # ifeq ($(LINUXVERSION),) LINUXVERSION = $(shell uname -r) endif LINUXRELEASE = $(shell uname -r | cut -d'.' -f3) ifeq ($(VERSIONSTR),) ifeq ($(SUBDIRS),) VERSIONSTR = $(shell grep "define BACKEND_VERSION" $(M)/plustek_pp.c | cut -b25-50 ) else VERSIONSTR = $(shell grep "define BACKEND_VERSION" $(SUBDIRS)/plustek_pp.c | cut -b25-50 ) endif endif # # extra flags # EXTRA_CFLAGS += -D_PTDRV_VERSTR=\"$(VERSIONSTR)\" ifeq ($(DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif # # the module name # TARGET := pt_drv MODULE := $(TARGET).ko # # our files... # NAMES := dac detect genericio image map misc models io procfs NAMES := $(NAMES) motor p9636 ptdrv scale tpa p48xx p12 p12ccd NAMES := $(addprefix plustek-pp_, $(NAMES)) OBJS := $(addsuffix .o, $(NAMES)) # # now the kernel magic # ifneq ($(KERNELRELEASE),) obj-m := $(TARGET).o $(TARGET)-objs := $(OBJS) else KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) M=$(PWD) modules endif # # the installation stuff # group = "root" mode = "644" INST_DIR = /lib/modules/$(LINUXVERSION)/kernel/drivers/parport # # copy the driver to the modules directory # install: mkdir -p $(INST_DIR) install -c -m $(mode) $(MODULE) $(INST_DIR) /sbin/depmod -a # # # uninstall: rm -f $(INST_DIR)/$(MODULE) # # use modprobe to load the driver, remember to set the # parameter in /etc/conf.modules (see INSTALL for more details) # load: $(INST_DIR)/$(MODULE) # invoke modprobe with all arguments we got /sbin/modprobe $(TARGET) || exit 1 # Remove stale nodes and replace them, then give gid and perms rm -f /dev/$(TARGET)* # when using the devfs support, we check the /dev/scanner entries # and only create links to the devfs nodes # at least we create one link @if [ -e /dev/scanner/$(TARGET)* ]; then \ ln -s /dev/scanner/$(TARGET)0 /dev/$(TARGET); \ for name in `ls /dev/scanner | grep $(TARGET)`; do \ ln -s /dev/scanner/$$name /dev/$$name ; \ done \ else \ mknod /dev/$(TARGET) c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 0; \ mknod /dev/$(TARGET)0 c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 0; \ mknod /dev/$(TARGET)1 c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 1; \ mknod /dev/$(TARGET)2 c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 2; \ mknod /dev/$(TARGET)3 c `cat /proc/devices | sed -ne "s/\([0-9]*\) pt_drv/\1/p"` 3; \ \ chgrp $(group) /dev/$(TARGET)*; \ chmod $(mode) /dev/$(TARGET)*; \ fi # # unload the driver # unload: /sbin/modprobe -r $(TARGET) || exit 1 # Remove stale nodes rm -f /dev/$(TARGET)* # # cleanup the show # clean: @-rm -f *.o .depend depend dep $(MODULE) $(TARGET).o $(TARGET).mod.c .*.cmd sane-backends-1.0.27/doc/plustek/MakeModule.sh0000664000175000017500000000516112775277260016057 00000000000000#!/bin/bash #****************************************************************************** # # Bash-Script to create Plustek-Scannerdriver modules for Kernel 2.4, 2.6 and 3.x # out of the backend sources... # BUILD_DIR=$PWD/build SRC_DIR=$PWD/../../backend MAKEFILE=$PWD/Makefile.kernel26 KERNEL_V=`uname -r` OSMINOR=`uname -r | cut -b 3` OSMAJOR=`uname -r | cut -b 1` # # some intro ;-) # echo "This script will try and build a suitable kernel-module for your system." echo "If you'd like to make the module WITH debug output, restart this script" echo "with as follows:" echo "./MakeModule.sh DEBUG=y" echo "Press to continue or to cancel." read # # we need to be root user... # echo -n "Check for root..." if [ $EUID -ne 0 ]; then echo -e "\b\b\b - failed" echo "Please retry as root user." exit -1 fi echo -e "\b\b\b - done." # # Version checks... # echo -e "\nCheck for kernelversion:" if [ "$OSMAJOR" == "3" ];then echo "Using makefile for kernel 2.6.x - okay for kernel 3 as well..." MAKEFILE=$PWD/Makefile.kernel26 elif [ "$OSMINOR" == "6" ]; then echo "Using makefile for kernel 2.6.x" MAKEFILE=$PWD/Makefile.kernel26 elif [ "$OSMINOR" == "4" ]; then echo "Using makefile for kernel 2.4.x" MAKEFILE=$PWD/Makefile.kernel24 else echo "Your kernelversion >"$OSMAJOR"."$OSMINOR"< is probably not supported" exit -2 fi # # Setup... # echo -e "Build-directory: \n"$BUILD_DIR echo -n "Removing build-directory..." rm -rf $BUILD_DIR echo -e "\b\b\b - done." echo -n "Creating build-directory..." mkdir $BUILD_DIR cd $BUILD_DIR echo -e "\b\b\b - done.\n" echo -n "Linking source files..." C_FILES=`ls $SRC_DIR/plustek-pp_*.c` H_FILES=`ls $SRC_DIR/plustek-pp_*.h` for F in $C_FILES $H_FILES $SRC_DIR/plustek-pp.h $SRC_DIR/plustek_pp.c; do ln -s $F . done echo -e "\b\b\b - done." echo -n "Copying Makefile to build-directory..." cp $MAKEFILE Makefile echo -e "\b\b\b - done." # # Building the module... # echo "Making the module..." if [ "$OSMAJOR" == "2" -a "$OSMINOR" == "4" ]; then make all $1 else make -C /lib/modules/$KERNEL_V/build/ SUBDIRS=$BUILD_DIR modules $1 fi RES=$? cd .. if [ $RES != 0 ]; then echo "There were some build errors..." exit -1 fi echo "done." echo "Should I install the module?" echo "Press to continue or to cancel." read make -C $BUILD_DIR install echo "Should I try and load the module?" echo "If this step fails, check the kernel-log." echo "Press to continue or to cancel." read make -C $BUILD_DIR load echo "done." echo "Should I remove the build directory?" echo "Press to continue or to cancel." read rm -rf $BUILD_DIR echo "done." sane-backends-1.0.27/doc/plustek/Plustek-PARPORT-TODO.txt0000664000175000017500000000312012617742237017545 00000000000000Plustek-PARPORT-TODO.txt (2003-29-10) Gerhard Jäger ======================================================================== TODO (in general): - more documentation/comments on the different functions - remove/check the CHECK marks - add additional button handler - adding adjustment of the scan area - checking timeout conditions (MiscCheckTimer !) and handle them correctly - let the 96001/3 based models work with the highest available phys. resolution - Create the modes out of the capability list of each device (USER-MODE): - line by line feedback to the backend KNOWN BUGS/Limitations: Model Description Workaround ------------------------------------------------------------------------------ OpticPro P9636 detected as OP12000 none Genius VividPro II Film Halftone/Gray > 450 dpi didn't work none OpticPro P4830 binary scanning does not work none OpticPro A3I bad picture quality none Genius HR6 negative scanning not okay none ********************************* DONE *************************************** - PS/2 bidi does not work (libieee1284) - Update the IOCTL interface and remove some old structs (CmdBlk) ******************************** SKIPPED ************************************* better dither maps nobody needs halftone scanning make the backtrace work for ASIC 96001/3 not possible due to ASIC limits based models sane-backends-1.0.27/doc/plustek/FAQ0000664000175000017500000003135412112021330013777 00000000000000Plustek-Driver TROUBLESHOOTING/FAQ - 19.04.2001 ----------------------------------------------- The driver exists now since March 2000, this is the first trial to setup a FAQ. This leads into the following: First we have a part, which is more a troubleshooting section and the second one is the FAQ. To search through this text, search for "SYMPTOM" or "Q:". If you have some more FAQ entries, let me know THANKS to Jochen , who roamed through the mailing-list and gathered the different questions. ******************************************************************************* * TROUBLE-SHOOTING * * * * DRIVER TOPICS * ******************************************************************************* SYMPTOM: "kernel-module version mismatch" -------- "When I try to "make load" I get an error" /sbin/modprobe pt_drv || exit 1 /lib/modules/2.2.14-6.0.6/misc/pt_drv.o: kernel-module version mismatch /lib/modules/2.2.14-6.0.1/misc/pt_drv.o was compiled for kernel version 2.2.14-5.0 while this kernel is version 2.2.14-6.0.1. PROBLEM: -------- You're using the wrong Kernel-header files. The path /usr/include/linux is a link to /usr/src/linux/include/linux and /usr/src/linux is normally a link to your current kernel, i.e: /usr/src/linux-2.2.14 If you now upgrade your kernel and you have forgotten to correct the link /usr/src/linux, then every kernel-module you build outside the kernelsource structure will include the wrong version information. SOLUTION: --------- Set the link /usr/src/linux to your current kernel-source tree before recompiling kernel-modules like pt_drv, then your version mismatch problem should be solved. SYMPTOM: "Device or resource busy" -------- Any attempt to "modprobe" or "make load" the driver leads to this message. PROBLEM: -------- The driver refuses to load. During startup, the driver performs some tests according to the parallel port and the connected scanners. If the parallel port is not supported or the scanner cannot be found, the driver returns an error and the system will report "device or resource busy" SOLUTION: --------- There's no way to provide a general solution. First of all you should check your connections and the parallel port. Also check power for your scanner. If the problem still exists, enable the debug-messages of the pt_drv module (see INSTALL). Then check the messages after loading or send the output to the mailing list. Most of these problems are related to HW-problems. Before giving up, check the scanner under Windows (not really a good advice I know, but it helps to find HW-damage). There was also one case were the internal plugs of the parport connection were wrong... SYMPTOM: "Unresolved symbols" -------- "make load" or "modprobe pt_drv" produces this message: /sbin/modprobe pt_drv || exit 1 /lib/modules/2.2.14-5.0/misc/pt_drv.o: unresolved symbol parport_unregister_device /lib/modules/2.2.14-5.0/misc/pt_drv.o: unresolved symbol parport_enumerate /lib/modules/2.2.14-5.0/misc/pt_drv.o: unresolved symbol parport_register_device /lib/modules/2.2.14-5.0/misc/pt_drv.o: unresolved symbol parport_claim /lib/modules/2.2.14-5.0/misc/pt_drv.o: unresolved symbol parport_release /lib/modules/2.2.14-5.0/misc/pt_drv.o: insmod /lib/modules/2.2.14-5.0/misc/pt_drv.o failed PROBLEM: -------- The driver needs at least the parport_pc and the parport modules to work. They MUST be loaded prior to pt_drv. If these modules are not loaded you get this message. SOLUTION: --------- Simply load the parport module. You can add this dependency to your /etc/modules.conf (or /etc/conf.modules) file (see INSTALL). Then everytime you load pt_drv with modprobe, parport will be loaded automatically. After modifying this file, call depmod -va SYMPTOM: Scanner makes awful noise -------- PROBLEM: -------- This can have two major causes: - You have an ASIC96001/3 based scanner, then the sensor hits the scanbed: !!! TURN OFF SCANNER POWER !!! - You have an ASIC98001 based scanner, then the motor control does not work correctly --> hit the cancel button SOLUTION: --------- For the first case (ASIC 96001/3), there's no solution available. This happens, when the driver can't keep track of the stepper motor. The image you get is normally unusable. The second case is often reported when the printer driver lp.o is already loaded. So remove lp.o before loading pt_drv. SYMPTOM: Printer starts to print while scanning -------- PROBLEM: -------- It has been reported, that some printers (esp. HP printers) start to print, even during startup of the driver. This is a problem to printers which use a bidirectional protocol for talking with the system. SOLUTION: --------- There is no possibility to handle this problem inside the driver. One possibility is to switch off the bidirectional communication of the printer. The other one is to connect the printer to another parallel port. ******************************************************************************* * SANE-topics * ******************************************************************************* Here you will not find how to setup xscanimage to work with GIMP or how to compile sane to obtain xscanimage, for such questions, please refer to the mailing lists at SANE (http://www.sane-project.org) SYMPTOM: error in loading shared libraries: libsane.so.1: cannot open -------- shared object file: No such file or directory PROBLEM: -------- The shared libraries for SANE have been installed to a directory which is not in your "library path" SOLUTION: --------- SANE installs its shared libraries to PREFIX/lib/sane. PREFIX is in general /usr or /usr/local. You should either add the path to your /etc/ld.so.conf file or set links to the libraries from a wellknown lib-path. (i.e. ln -s /usr/lib/sane/libsane.so.1 /usr/lib/libsane.so.1) In any case you should run "ldconfig -v" SYMPTOM: "no SANE devices found" -------- While testing with "scanimage -L" nothing happens. And when starting scanimage this message is displayed. PROBLEM: -------- The frontend cannot find any sane-device, this might have several causes: - the driver is not loaded - you have no access to the driver - the backend is not enabled - the driver is not specified - version conflict between the loaded driver and the backend SOLUTION: --------- Driver not loaded: check "cat /proc/pt_drv" if this does not exist, load the driver (see INSTALL) No access to the driver: check "ls -l /dev/pt_drv*" and you should get crw-rw-r-- 1 root root 40, 0 Aug 29 15:18 /dev/pt_drv crw-rw-r-- 1 root root 40, 0 Aug 29 15:18 /dev/pt_drv0 crw-rw-r-- 1 root root 40, 1 Aug 29 15:18 /dev/pt_drv1 crw-rw-r-- 1 root root 40, 2 Aug 29 15:18 /dev/pt_drv2 crw-rw-r-- 1 root root 40, 3 Aug 29 15:18 /dev/pt_drv3 If not, call "make load" in the driver source directory. This call sometimes fails, so you might create the entries by using mknod: mknod -m 0664 /dev/pt_drv c 40 0 mknod -m 0664 /dev/pt_drv0 c 40 0 mknod -m 0664 /dev/pt_drv1 c 40 1 mknod -m 0664 /dev/pt_drv2 c 40 2 mknod -m 0664 /dev/pt_drv3 c 40 3 The backend is not enabled: Check the SANE configuration in /etc/sane.d, /usr/etc/sane.d or /usr/local/etc/sane.d (depending on your installation). Your dll.conf MUST include an enabled "plustek" entry (no "#" in front of that line) The driver is not specified: Check the sane configuration (see above) for the file plustek.conf and make sure that it contains at least /dev/pt_drv as entry. Version conflict: After enabling the SANE debug messages you will get something like upon starting scanimage: ioctl PT_DRV_OPEN_DEVICE failed(-9019) Version problem, please recompile driver! In this case, you MUST recompile the backend AND the driver and reinstall both. This feature makes sure, that both always will use the same ioctl interface. PROBLEM: -------- I have SANE-1.0.4 and there's no backend-directory after unpacking, so what to do? SOLUTION: --------- You're wrong there is a backend directory!!! Since SANE-1.0.4, there are two packages: sane-backends sane-frontends For the installation, you need the backend tarball. This should give you something like: sane-1.0.4/sane-backends and there below sane-backends is the backend directory. So you have to unpack the plustek-sane...tgz in sane-backends. ******************************************************************************* * F A Q * ******************************************************************************* Q: What does "Turbo" mean ? A: Turbo does not mean, that the scanner is faster ;-) There are currently three OpticPro9636P Scanners. OP9636P OP9636P+ OP9636PTurbo The + and the Turbo models are quite the same and the difference between the Turbo and the non-Turbo is the scan-sensor. The Turbo uses the same like the newer OP9636T/12000T and the non-Turbo uses the older ones from the OP9630.... Q: Is it possible to use the front-button of my Plustek 9630P ? A: It is possible since version 0.37. After loading the driver, use the proc filesystem to get the button value: cat /proc/pt_drv/device0/button0 Q: Is it possible to use the scanner in gimp ? A: You should be able to use xscanimage with gimp: 1. Login as root 2. Go into the gimp plug-in directory (on SuSE it is: /usr/lib/gimp/1.1/plug-ins/ ) 3. Find xscanimage : which xscanimage 4. Create a symbolic link to xscanimage : ln -s "/path/to/"xscanimage xscanimage 5. logout as root Now call gimp, in the xtns menu you should find now the Acquire Image menu entry. That's all. If not, start gimp from an xterm and have a look at the output. Q: Is there any way to load the plustek_driver at bootup-time? A: Normally, there is no need to do so, because once you altered your /etc/conf.modules file (or /etc/modules.conf) and added the suggested stuff (see INSTALL file), you won't have to worry about loading the driver. It happens automagically. ;-) The driver will be loaded when needed (and eventually removed after a specific time of not using it). Nevertheless, another possibility is to do a modprobe pt_drv in the /etc/rc.d/boot.local (using SuSE) or /etc/rc.d/rc.local (using RedHat or Mandrake) file So the driver will be loaded at bootup-time... !!! YOUR SCANNER MUST BE ONLINE during power-up then !!! Q: I wonder if Mandrake 7.1's sane rpm file has this support already built in. My scanner light is coming on yet Xscanimage seems to report that there is no scanner present. A: The backend code will be included in Version 1.0.3 of sane and AFAIK Mandrake 7.1 only includes 1.0.2. Anyway go to the plustek-driver download page at http://home.t-online.de/home/g-jaeger/plustek.html download and install the driver. Q: Mandrake installs sane by default at install-time. Is there a way to install the driver with the preinstalled sane or should the preinstalled sane be removed first? If so, how do I remove the preinstalled sane? A: I recommend to uninstall the previous one. I think Mandrake uses RPM for managing the packages. To remove sane do the following (as root) Ask for all installed packages and filter sane: rpm -qa | grep sane you should get something like this: sane-1.0.1-94 Now remove this package: rpm -e sane-1.0.1-94 After theses steps, sane should be removed. I'm not sure, but you might have to remove the /etc/sane.d manually... Now got to your sane-1.0.3 stuff and reinstall this as described. Before using, you might have a look at the dll.conf and enable only the plustek backend. Q: Now that there's a sane 1.0.3, how do i uninstall sane 1.0.2? Or can i install it over? A: In general you can install it over. BUT this has caused quite a lot of trouble, so I recommend to remove the 1.0.2 completely and install 1.0.3... try the rpm-tool: Get a list of the installed packages and filter out sane: rpm -qa | grep sane You should get something like: sane-1.0.2-48 Then use rpm to remove sane: rpm -e sane-1.0.2-48 The other way is: rm -rf /etc/sane.d rm -rf /usr/lib/sane rm -rf /usr/lib/libsane* rm -rf /usr/include/sane rm -rf /usr/etc/sane.d rm -rf /usr/share/sane* rm -rf /usr/local/lib/sane rm -rf /usr/local/lib/libsane* rm -rf /usr/local/include/sane rm -rf /usr/local/etc/sane.d rm -rf /usr/local/share/sane* This should cover all the directories where maybe some sane files are installed... sane-backends-1.0.27/doc/plustek/Plustek-PARPORT.changes0000664000175000017500000001460512775277260017611 00000000000000Version 0.1 10/20/98 1.0 Initial release Version 0.2 10/26/98 1.0 Fix Red/Green swap, optimize ppm output for black and white. Version 0.3 10/28/98 1.0 Merge code with SANE 2.0 Put GPL/SANE license info in all files Version 0.4 10/31/98 1.0 Have driver report ASIC ID up to backend. 2.0 Put NT stuff back in so that driver may be built under NT, try to test build under NT but run out of memory in link. Version 0.5 10/31/98 1.0 Fix parameters not getting reflected from crop. Version 0.6 11/1/98 1.0 Take out unused stuff from ioctl_pt_drv.h. 2.0 Put in VERSION info in Makefile and archiver. Version 0.7 11/4/98 1.0 Fix model string when -L option is given. Add in driver version string to model. 2.0 Change Makefile so it builds without MODVERSIONS on distributions that don't have it (Slackware). Version 0.8 11/5/98 1.0 Change output when -L option is given to add status byte to try to determine any differences between the 4830 and the 9630. Version 0.9 11/6/98 1.0 Fix 4800 problem of inverse image when not in Binary mode. 2.0 Put more debug stuff in, print out all read reg's. Version 0.10 11/6/98 1.0 Get halftone working. 2.0 Put in hooks for kernel 2.1 Version 0.11 11/17/98 1.0 Put in sysdep-2.1.h to Makefile distrib Version 0.20 3/7/99 1.0 Lots of changes to support 9630/12000. ------------------------------------------------------------------------------- Version 0.3 02/29/2000 1.0 Completely rewritten, does now support Plustek OpticPro 9636T scanner Version 0.31 03/20/2000 1.0 Fix a bug in the autodetection routine 2.0 Enhanced backend, to reflect the different modes the OpticPro 9636T supports Version 0.32 - never released 1.0 Corrected warmup-behaviour 2.0 Fixed "first picture corrupted"-bug for transparency mode 3.0 Fixed a bug that causes seg-faults when using cat /dev/pt_drv 4.0 Added SCALE.C 5.0 Made 4830P work Version 0.33 - never released 1.0 Now using parport-module info for par-mode detection 2.0 Made 9630P work Version 0.34 05/10/2000 1.0 Data-recovery code for heavy load systems Version 0.35 05/19/2000 1.0 Made 12000P/96000P work 2.0 Merged parallel port code from Kevin Sisson 3.0 Added new parameter "legal" Version 0.36 07/22/2000 1.0 Improved data-recovery mechanism for ASIC96001/3 based models 2.0 Added code for OP4800 shading 3.0 Improved backend code to allow canceling the scan process 4.0 OP600 and Primax 4800 Direct are working now 5.0 Added new parameter "mov" (Model OVerride) 6.0 Removed parameter "legal", use now "mov" 7.0 Moved common headers for backend and driver to backend directory and prepared the backend for SANE distribution 8.0 OP6000 is working 9.0 added man-page 10.0 added multi-device support 11.0 added support for 12-bit scans (SANE-1.0.3 and scanimage!!) Version 0.37 11/09/2000 1.0 Added file io.c for parallel port I/O 2.0 Added file procfs.c for proc-filesystem support 3.0 Code cleanup 4.0 Added A3I support 5.0 Added Michaels backend patches Version 0.38 11/30/2000 1.0 Started integration of ASIC98003 specific stuff 2.0 renamed file transform.c tpa.c 3.0 removed portmode stuff (I decided to support SPP/BPP and EPP, that's all) 4.0 again code-cleanup 5.0 PT12 is working 6.0 Removed gray-mode scanning for TPA modes 7.0 some minor changes according to kernel 2.4.x Version 0.39 08/11/2001 1.0 Added slowIO switch 2.0 Fixed some minor bugs 3.0 Added forceMode switch 4.0 Fixed a problem in the PT12 code that causes I/O timeouts 5.0 Added Genius Colorpage Vivivd III V2 stuff 6.0 Added A3I stuff aquired from Plustek 7.0 Fixed a bug, that causes some seg-faults Version 0.40 12/17/2001 1.0 The USB stuff has been included 2.0 Fixed some minor problems 3.0 Added Kernel 2.4.17 specific stuff 4.0 Disabled A3I stuff as this refuses ASIC96003 based devices to work Version 0.41 01/10/2002 1.0 Changed IOCTL interface to the kernel module to allow adjustment of some driver internal variables 2.0 Changed plustek.conf configuration fileformat to reflect the enhanced capabilites Version 0.42 02/12/2002 1.0 Added custom gamma table support 2.0 Added configuration-file options to preset some stuff 3.0 Changed all eMail entries to gerhard@gjaeger.de Version 0.42-11 09/17/2003 1.0 Some Kernel 2.6.x additions 2.0 Added Primax 4800Direct 30Bit override switch Somewhere on the way to 0.43 I decided to split parport & usb backends, so the parport backend now is also able to run complete in userspace by using either direct port I/O or libieee1248 Version 0.43-2 04/15/2004 1.0 Fixed some kernel 2.6 issues Version 0.43-3 07/14/2004 1.0 User-space code has now the same version as the module code Version 0.43-4 07/15/2004 1.0 DevFS support for kernel 2.6 2.0 Removed floating point operations (Thanx to Rafal Rzepecki) 3.0 More cleanup work 4.0 bumped up build number Version 0.43-5 10/06/2004 1.0 Change some scanmode definitions to match the SANE predefined ones Version 0.43-6 04/25/2005 1.0 Removed inline stuff from kernel module code, as GCC3.4 will make some trouble Version 0.43-7 05/11/2005 1.0 Fixed timer issues in user-space (Thanx to Rod Roark) Version 0.43-8 08/10/2005 1.0 Fixed problem on ASIC96003/1 based devices, when scanning lineart at 200 and 300 dpi Version 0.43-9 11/14/2005 1.0 Fixed sizeof(long) issue for 64bit platforms, see bug #302195 Version 0.43-10 02/16/2006 1.0 Fixed bug, that prevents backend from working, when the device is connected to parport1 or higher, parport0 works. Bug spotted by Christoph Steinbruchel. Version 0.43-11 08/09/2006 1.0 Changed sane.type to "flatbed scanner" only Version 0.43-12 08/29/2006 1.0 Fixed "not homing" problem, the sensor did not return when the driver gets the _IOCTL_STOP command 2.0 Fixed compilation issue for kernels > 2.6.15 3.0 Fixed compiler warning conditions Version 0.43-13 06/18/2007 1.0 Removed DEVFS stuff for Kernels > 2.6.15 2.0 Added class stuff Version 0.44-1 02/13/2013 1.0 Fixed issues for Kernels > 2.6.35 2.0 Define ULong and friends to uint32_t to make the driver work in a 64 bit environmentsane-backends-1.0.27/doc/sane-hp.man0000664000175000017500000002304612112021330014005 00000000000000.TH sane\-hp 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hp .SH NAME sane\-hp \- SANE backend for HP ScanJet scanners .SH DESCRIPTION The .B sane\-hp library implements a SANE (Scanner Access Now Easy) backend that provides access to HP ScanJet scanners which support SCL (Scanner Control Language by HP). The following scanners are known positively to work with this backend: .PP .RS .ft CR .nf Model: Product id: Interface: ---------- ----------- ---------- ScanJet Plus C9195A HP Parallel Interface Card ScanJet IIc C1750A 3226 SCSI ScanJet IIcx C2500A 3332 SCSI ScanJet IIp C1790A SCSI ScanJet 3C C2520A 3503 SCSI ScanJet 3P C2570A 3406 SCSI ScanJet 4C C2520A SCSI ScanJet 4P C1130A 3540 SCSI ScanJet 4100C C6290A USB ScanJet 5P C5110A SCSI ScanJet 5100C C5190A parallel port ScanJet 5200C C7190A 3846 parallel port/USB ScanJet 6100C C2520A 3644 SCSI ScanJet 6200C C6270A 3828 SCSI/USB ScanJet 6250C C6270A 3828 SCSI/USB ScanJet 6300C C7670A SCSI/USB ScanJet 6350C C7670A SCSI/USB ScanJet 6390C C7670A SCSI/USB PhotoSmart C5100A R029,R030,R032 SCSI .fi .ft R .RE .PP Support for models 5100C/5200C connected to the parallel port requires the ppSCSI driver available at .I http://cyberelk.net/tim/parport/ppscsi.html and .IR http://penguin-breeder.org/kernel/download/ . .PP Support for models 5200C/62X0C/63X0C connected to the USB require the kernel scanner driver or libusb. See .BR sane\-usb (5) for more details. .PP The "hp" backend no longer supports OfficeJet multi-function peripherals. For these devices use the external "hpoj" backend in version 0.90 and later of the "HP OfficeJet Linux driver", available at .br .IR http://hpoj.sourceforge.net . .PP Because Hewlett-Packard does no longer produce scanners that support SCL (beside the OfficeJets), the above list of supported scanners is complete. Other HP scanners are not supported by the "hp" backend, but might be supported by another one. See .IR http://www.sane\-project.org/ . You can also watch the sane\-devel mailing list at .IR http://www.sane\-project.org/mailing\-lists.html . .PP More details about the hp backend can be found on its homepage .IR http://www.kirchgessner.net/sane.html . .PP .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the UNIX path-name for the special device that corresponds to the scanner. For SCSI scanners the special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sg2 , for example. If the special device name contains "usb", "uscanner" or "ugen", it is assumed that the scanner is connected by USB. For the HP ScanJet Plus the special device name must be the device that corresponds to the parallel interface card that was shipped with the scanner. That is .IR /dev/hpscan . A special driver is required for this card. See ftp://rvs.ctrl\-c.liu.se/pub/wingel/hpscan for details. If the link does not work, try ftp://sunsite.unc.edu/pub/Linux/kernel/patches/scanners. .SH CONFIGURATION The contents of the .I hp.conf file is a list of options and device names that correspond to HP ScanJet scanners. Empty lines and lines starting with a hash mark (#) are ignored. See .BR sane\-scsi (5) and .BR sane\-usb (5) on details of what constitutes a valid device name. .PP Options specified in front of the first line that contains a device name are defaults for all devices. Options specified below a line that contains a device name apply just to the most recently mentioned device. .PP Supported options are .BR connect\-scsi , .BR connect\-device , .BR enable\-image\-buffering , and .BR dumb\-read . Option .B connect\-scsi specifies that the scanner is connected to the system by SCSI. Input/output is performed using SCSI-commands. This is the default. But if your SCSI device name contains "usb", "uscanner" or "ugen", option connect\-scsi must be specified. Otherwise it is assumed that the scanner is connected by USB. Option .B connect\-device specifies that the scanner is connected to the system by a special device. Input/output is performed by read()/write()-operations on the device. This option must be used for HP ScanJet Plus or scanners connected to USB which are accessed through a named device (e.g. /dev/usb/scanner0). For device names that contain "usb", "uscanner" or "ugen", it is not necessary to specify option connect\-device. Option .B enable\-image\-buffering stores the scanned image in memory before passing it to the frontend. Could be used in case of forward/backward moving scanner lamp. Option .B dumb\-read can be used to work around problems with "Error during device I/O". These problems may occur with certain SCSI-to-USB converters or Buslogic SCSI cards. The option should not be used for SCSI devices which are working correctly. Otherwise startup of frontends and changing parameters might be slower. .PP A sample configuration file is shown below: .PP .RS .ft CR .nf /dev/scanner # this is a comment /dev/hpscan option connect\-device .fi .ft R .RE .PP /dev/scanner is typically a symlink to the actual SCSI scanner device. .RE .SH FILES .TP .I @CONFIGDIR@/hp.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-hp.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hp.so The shared library implementing this backend (present on systems that support dynamic loading). .TP .I $HOME/.sane/calib-hp:.dat Calibration data for HP PhotoSmart PhotoScanner that is retrieved from the scanner after calibration. The data is uploaded to the scanner at start of the backend if it is in media mode 'print media' or if the media mode is changed to 'print media'. .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_HP If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .TP .B SANE_HOME_HP Only used for OS/2 and along with use of HP PhotoSmart PhotoScanner. Must be set to the directory where the directory .sane is located. Is used to save and read the calibration file. .TP .B SANE_HP_KEEPOPEN_SCSI .TP .B SANE_HP_KEEPOPEN_USB .TP .B SANE_HP_KEEPOPEN_DEVICE For each type of connection (connect\-scsi, connect\-usb, connect\-device) it can be specified if the connection to the device should be kept open ("1") or not ("0"). Usually the connections are closed after an operation is performed. Keeping connection open to SCSI-devices can result in errors during device IO when the scanner has not been used for some time. By default, USB-connections are kept open. Other connections are closed. .TP .B SANE_HP_RDREDO Specifies number of retries for read operation before returning an EOF error. Only supported for non-SCSI devices. Default: 1 retry. Time between retries is 0.1 seconds. .SH BUGS .TP .B HP PhotoSmart PhotoScanner In media mode 'slide' and 'negative', scan resolutions are rounded to multiple of 300 dpi. The scanner does not scale the data correctly on other resolutions. Some newer models (firmware code R030 and later) do not support adjustment of contrast/intensity level and tone map. The backend will simulate this by software, but only for gray and 24 bit color. .TP .B Automatic Document Feeder (ADF) For use of the ADF with xscanimage(1), first place paper in the ADF and then change option scan source to 'ADF'. Press 'change document' to load a sheet. Then press 'scan' to start a scan. Maybe it is sufficient to press 'scan' without 'change document' for repeated scans. The use of the preview window is not recommended when working with the ADF. Setting a window to scan from ADF is not supported with xscanimage(1). Try xsane(1). .TP .B Immediate actions Some actions in xscanimage(1) (i.e. unload, select media, calibrate) have an immediate effect on the scanner without starting a scan. These options can not be used with scanimage. .SH TODO .TP .B HP PhotoSmart PhotoScanner PhotoScanners with firmware release R030 and up have no firmware support for contrast/brightness/gamma table. In the current backend this is simulated by software on 24 bits data. Simulation on 30 bits should give better results. .TP .B Data widths greater than 8 bits Custom gamma table does not work. .TP .B Parallel scanner support Beside the ScanJet Plus which came with its own parallel interface card, currently only the HP ScanJet 5100C/5200C are supported. These scanners are using an internal parallel-to-SCSI converter which is supported by the ppSCSI-driver (see above). .SH "SEE ALSO" sane(7), sane\-scsi(5), sane\-usb(5) .SH AUTHOR The sane\-hp backend was written by Geoffrey T. Dairiki. HP PhotoSmart PhotoScanner support by Peter Kirchgessner. sane-backends-1.0.27/doc/sane-dc25.man0000664000175000017500000000672212112021330014135 00000000000000.TH sane\-dc25 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-dc25 .SH NAME sane\-dc25 \- SANE backend for Kodak DC20/DC25 Digital Cameras .SH DESCRIPTION The .B sane\-dc25 library implements a SANE (Scanner Access Now Easy) backend that provides access to Kodak DC20 and DC25 cameras. At present, only the DC25 has been tested, but since the code is based on a DC20 interface program, it is likely to work for that model also. .SH "DEVICE NAMES" The current version of the backend only allows one camera to be connected. The device name is always "0". .SH CONFIGURATION The contents of the .I dc25.conf specify the serial port and baud rate to use. The baud rate specifies the maximum rate to use while downloading pictures. (The camera is always initialized using 9600 baud, then switches to the higher rate). On my 90MHz Pentium, I usually have no problems downloading at 115200 baud as long as the system is not excessively busy and the "interrupt-unmask flag" is set in the IDE driver (hdparm \-u1). Supported baud rates are: 9600, 19200, 38400, 57600, and 115200. .PP The dumpinquiry line causes some information about the camera to be printed to stderr during startup. Note: This is not compatible with saned, so make sure you don't have any dumpinquiry lines if you are using saned (i.e. scanning on a remote machine using a network). .PP Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS port=/dev/ttyS0 .br # this is a comment .br baud=115200 .br dumpinquiry .RE .PP .SH FILES .TP .I @CONFIGDIR@/dc25.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-dc25.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-dc25.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_DC25 If the library was compiled with debugging support enabled, this environment variable controls the debug level for this backend. A value of 128 requests maximally copious debug output; smaller levels reduce verbosity. .SH "SEE ALSO" sane(7) .SH AUTHOR Peter Fales, dc25\-devel@fales\-lorenz.net .SH BUGS Known bugs/limitations are: .PP I haven't figured out how to trigger an option reload following a "scan." This causes problems when a new picture is snapped for example, the slider that is used to select the picture from the camera may not be updated immediately. .PP More general comments, suggestions, and inquiries about frontends or SANE should go to the SANE Developers mailing list (see http://www.sane\-project.org/mailing\-lists.html for details). You must be subscribed to the list, otherwise your mail won't be sent to the subscribers. sane-backends-1.0.27/doc/sane-v4l.man0000664000175000017500000000551312112021330014102 00000000000000.TH sane\-v4l 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-v4l .SH NAME sane\-v4l \- SANE interface for Video for Linux API .SH DESCRIPTION The .B sane\-v4l library implements a SANE (Scanner Access Now Easy) backend that provides generic access to video cameras and similar equipment using the V4L (Video for Linux) API. .PP This is ALPHA software. Really! Important features are missing and there are lots of bugs. The code is currently only tested on a Linux 2.4 system with a Hauppauge WinTV video card. .PP .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the UNIX path-name for the special device that corresponds to the v4l device. The special device name must be a v4l device or a symlink to such a device. For example, such a device name could be .I /dev/video0 or .IR /dev/bttv0 . .SH CONFIGURATION The contents of the .I v4l.conf file is a list of device names that correspond to v4l devices. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS /dev/bttv0 .br # this is a comment .br /dev/video3 .RE .SH FILES .TP .I @CONFIGDIR@/v4l.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-v4l.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-v4l.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_V4L If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH AUTHOR Juergen G. Schimmer, Henning Meier-Geinitz .SH BUGS: If more than one video card is present, a crash may occur. Frequency and geometry selection is missing. .br Send bug reports to the SANE mailing list: sane\-devel@lists.alioth.debian.org. You must be subscribed to the list to send mail. See http://www.sane\-project.org/mailing\-lists.html for details. .SH SEE ALSO sane(7), xcam(1). sane-backends-1.0.27/doc/sane-tamarack.man0000664000175000017500000000434412112021330015161 00000000000000.TH sane\-tamarack 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-tamarack .SH NAME sane\-tamarack \- SANE backend for Tamarack flatbed scanners .SH DESCRIPTION The .B sane\-tamarack library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Tamarack flatbed scanners: .PP .RS Artiscan 6000C .br Artiscan 8000C .br Artiscan 12000C .br .RE .PP .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the path-name for the special device that corresponds to a SCSI scanner. The special device name must be a generic SCSI device or a symlink to such a device. The program .IR sane\-find\-scanner helps to find out the correct device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. See sane\-scsi(5) for details. .SH FILES .TP .I @CONFIGDIR@/tamarack.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-tamarack.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-tamarack.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_TAMARACK If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_TAMARACK=4 .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHOR Roger Wolff sane-backends-1.0.27/doc/sane-scsi.man0000664000175000017500000003027112775312262014363 00000000000000.TH sane\-scsi 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-scsi .SH NAME sane\-scsi \- SCSI adapter tips for scanners .SH DESCRIPTION This manual page contains various operating-system specific tips and tricks on how to get scanners with a SCSI interface working. .SH GENERAL INFO For scanners with a SCSI interface, it may be necessary to edit the appropriate backend configuration file before using SANE for the first time. For most systems, the configuration file should list the name of the generic SCSI device that the scanner is connected to (e.g., under Linux, .B /dev/sg4 or .B /dev/sge is such a generic SCSI device). It is customary to create a symlink from .B /dev/scanner to the generic SCSI device that the scanner is connected to. In this case, the configuration file simply lists the line .BR /dev/scanner . For a detailed description of each backend's configuration file, please refer to the relevant backend manual page (e.g., .BR sane\-epson (5) for Epson scanners, .BR sane\-hp (5) for HP scanners, etc.). .PP For some operating systems (e.g. Linux and OS/2), there is an alternate way of specifying scanner devices. This alternate way allows one to identify scanners by the SCSI vendor and model string and/or by the SCSI device address (consisting of bus number, channel number, id, and logical unit number). The syntax for specifying a scanner in this way is: .PP .RS scsi .I VENDOR MODEL TYPE BUS CHANNEL ID LUN .RE .PP where .I VENDOR is the SCSI vendor string, .I MODEL is the SCSI model string, .I TYPE is type SCSI device type string, .I BUS is the SCSI bus number (named "host" in /proc/scsi/scsi), .I CHANNEL is the SCSI channel number, .I ID is the SCSI id, and .I LUN is the logical unit number of the scanner device. The first two fields are strings which must be enclosed in double-quotes if they contain any whitespace. The remaining four fields are non-negative integer numbers. The correct values for these fields can be found by using operating system specific tools, e.g. for Linux by looking at the output of the command "cat /proc/scsi/scsi". To simplify configuration, a field's value can be replaced with an asterisk symbol (``*''). An asterisk has the effect that any value is allowed for that particular field. This can have the effect that a single scsi-line matches multiple devices. When this happens, each matching device will be probed by the backend one by one and registered if the backend thinks it is a compatible device. For example, the line .PP .RS scsi MUSTEK MFS\-06000CX Scanner 0 00 03 00 .RE .PP would attach the Mustek SCSI scanner with the following /proc/scsi/scsi entry: .PP .RS 2 .ft CR .nf Host: scsi0 Channel: 00 Id: 03 Lun: 00 Vendor: MUSTEK Model: MFS\-06000CX Rev: 4.04 Type: Scanner ANSI SCSI revision: 0 .fi .ft R .RE .PP Usually it's sufficient to use vendor and model strings only or even only the vendor string. The following example .PP .RS scsi MUSTEK * * * * * * .RE .PP would have the effect that all SCSI devices in the system with a vendor string of MUSTEK would be probed and recognized by the backend. .PP If the remainder of a scsi-string consists of asterisks only, the asterisks can be omitted. For example, the following line is equivalent to the one specified previously: .PP .RS scsi MUSTEK .RE .PP On some platforms (e.g., OpenStep), SANE device names take a special form. This is explained below in the relevant platform-specific section. .PP When using a SCSI scanner, ensure that the access permission for the generic SCSI device is set appropriately. We recommend to add a group "scanner" to /etc/group which contains all users that should have access to the scanner. The permission of the device should then be set to allow group read and write access. For example, if the scanner is at generic SCSI device .BR /dev/sg0 , then the following two commands would set the permission correctly: .PP .RS $ chgrp scanner /dev/sg0 .br $ chmod 660 /dev/sg0 .br .RE .PP When your system uses the device filesystem (devfs), you have to edit .BR /etc/devfs/perms. There you should search the line .PP .RS REGISTER ^sg[^/]* PERMISSIONS root.root 0600 .RE .PP and add a new line (eg. for changing permissions of sg4): .PP .RS REGISTER ^sg4 PERMISSIONS root.scanner 0660 .RE .PP .SH FREEBSD INFO Auto-configuration using the "scsi *" lines in the config files only works if the user running the frontend has read/write access to /dev/xpt0. Instead, you can also set a link .I /dev/scanner to the appropriate /dev/uk device. .RS .TP Adaptec AHA1542CF Reported to work fine under FreeBSD 2.2.2R with the .B aha driver. .TP Adaptec 2940 Reported to work fine under FreeBSD 2.2.2. .TP Adaptec 1522 The scanner probes ok but any attempt to access it .I hangs the entire system. It looks like something is disabling interrupts and then not re-enabling them, so it looks like a bug in the FreeBSD .B aic driver. .TP Adaptec 1505 Works on FreeBSD 2.2.5R and 3.0 using the .B aic driver, provided that Plug-and-Play support is disabled on the card. If there are no .I uk devices, just do a ``sh MAKEDEV uk0'' in the .B /dev directory. The scanner should then be accessible as .B /dev/uk0 if it was probed during boot. .TP Tekram DC390 Reported to work fine under FreeBSD 2.2.2R with the .B amd driver. .RE .SH LINUX INFO First, make sure your kernel has SCSI generic support enabled. In ``make xconfig'', this shows up under ``SCSI support->SCSI generic support''. .PP To keep scanning times to a minimum, it is strongly recommended to use a large buffer size for the generic SCSI driver. From SG driver version 2.0 on, the maximum buffer size can be changed at program run time, and there is no restriction in size. This driver version is part of the Linux kernels from version 2.2.7 on. If the new SG driver is available some backends (e.g. sane\-umax, sane\-mustek, sane\-sharp) automatically request larger scsi buffers. If a backend does not automatically request a larger scsi buffer, set the environment variable .B SANE_SG_BUFFERSIZE to the desired buffer size in bytes. It is not recommended to use more than 1 MB, because for large values the probability increases that the SG driver cannot allocate the necessary buffer(s). For ISA cards, even 1 MB might be a too large value. For a detailed discussion of memory issues of the SG driver, see http://www.torque.net/sg. .PP For Linux kernels before version 2.2.7 the size of the buffer is only 32KB. This works, but for many cheaper scanners this causes scanning to be slower by about a factor of four than when using a size of 127KB. Linux defines the size of this buffer by macro .B SG_BIG_BUFF in header file .IR /usr/include/scsi/sg.h . Unless a system is seriously short on memory, it is recommended to increase this value to the maximum legal value of 128*1024-512=130560 bytes. After changing this value, it is necessary to recompile both the kernel (or the SCSI generic module) and the SCSI backends. Keep in mind that this is only necessary with older Linux kernels. .PP A common issue with SCSI scanners is what to do when you booted the system while the scanner was turned off? In such a case, the scanner won't be recognized by the kernel and SANE won't be able to access it. Fortunately, Linux provides a simple mechanism to probe a SCSI device on demand. Suppose you have a scanner connected to SCSI bus 2 and the scanner has a SCSI id of 5. When the system is up and running and the scanner is turned on, you can issue the command: .PP .RS echo "scsi add\-single\-device 2 0 5 0" > /proc/scsi/scsi .RE .PP and the kernel will probe and recognize your scanner (this needs to be done as root). It's also possible to dynamically remove a SCSI device by using the ``remove\-single\-device'' command. For details, please refer to to the SCSI-2.4-HOWTO. .PP Scanners are known to work with the following SCSI adapters under Linux. This list isn't complete, usually any SCSI adapter supported by Linux should work. .PP .RS .TP Acard/Advance SCSI adapters Some old versions of the kernel driver (atp870u.c) cut the inquiry information. Therefore the scanner couldn't be detected correctly. Use a current kernel. .TP Adaptec AHA-1505/AHA-1542/AHA-2940 Reported to work fine with Linux since v2.0. If you encounter kernel freezes or other unexpected behaviour get the latest Linux kernel (2.2.17 seems to work) or reduce SCSI buffer size to 32 kB. .TP ASUS SC200 Reported to work fine with Linux v2.0. .TP BusLogic BT958 To configure the BusLogic card, you may need to follow these instructions (contributed by Jeremy ): During boot, when your BusLogic adapter is being initialized, press Ctrl-B to enter your BusLogic adapter setup. Choose the address which your BusLogic containing your scanner is located. Choose ``SCSI Device Configuration''. Choose ``Scan SCSI Bus''. Choose whatever SCSI id that contains your scanner and then choose ``View/Modify SCSI configuration''. Change ``Negotiation'' to ``async'' and change ``Disconnect'' to ``off''. Press Esc, save, and Esc again until you are asked to reboot. .TP NCR/Symbios 53c400/53c400a or Domex DTC3181E/L/LE (DTCT436/436P) ISA SCSI card This card is supplied by Mustek (and other vendors). It's supported since Linux 2.2. The SCSI cards are supported by the module g_NCR5380. It's necessary to tell the kernel the io port and type of card. Example for a 53c400a: ``modprobe g_NCR5380 ncr_addr=0x280 ncr_53c400a=1''. Once the kernel detects the card, it should work all right. However, while it should work, do not expect good performance out of this card---it has no interrupt line and therefore while a scan is in progress, the system becomes almost unusable. You may change the values of the USLEEP macros in drivers/scsi/g_NCR5380.c. Some documentation is in this file and NCR5380.c. .TP NCR/Symbios 810 For some scanners it may be necessary to disable disconnect/reconnect. To achieve this use the option ncr53c8xx="disc:n". Some people reported that their scanner only worked with the 53c7,8xx driver, not the ncr53c8xx. Try both if you have trouble. .br For Linux kernels before 2.0.33 it may be necessary to increase the SCSI timeout. The default timeout for the Linux kernels before 2.0.33 is 10 seconds, which is way too low when scanning large area. If you get messages of the form ``restart (ncr dead ?)'' in your /var/log/messages file or on the system console, it's an indication that the timeout is too short. In this case, find the line ``if (np->latetime>10)'' in file ncr53c8xx.c (normally in directory /usr/src/linux/drivers/scsi) and change the constant 10 to, say, 60 (one minute). Then rebuild the kernel/module and try again. .TP Tekram DC315 The driver can be downloaded from http://www.garloff.de/kurt/linux/dc395/. For some older scanners it may be necessary to disable all the more advanced features by using e.g. modprobe dc395x_trm dc395x_trm=7,5,1,32. .TP Tekram DC390 Version 1.11 of the Tekram driver seems to work fine mostly, except that the scan does not terminate properly (it causes a SCSI timeout after 10 minutes). The generic AM53C974 also seems to work fine and does not suffer from the timeout problems. .SH SOLARIS, OPENSTEP AND NEXTSTEP INFO Under Solaris, OpenStep and NeXTStep, the generic SCSI device name refers to a SCSI bus, not to an individual device. For example, .B /dev/sg0 refers to the first SCSI bus. To tell SANE which device to use, append the character 'a'+target-id to the special device name. For example, the SCSI device connected to the first SCSI controller and with target-id 0 would be called .BR /dev/sg0a , and the device with target-id 1 on that same bus would be called .BR /dev/sg0b, and so on. .SH ENVIRONMENT .TP .B SANE_DEBUG_SANEI_SCSI If the library was compiled with debug support enabled, this environment variable controls the debug level for the generic SCSI I/O subsystem. E.g., a value of 128 requests all debug output to be printed by the backend. A value of 255 also prints kernel messages from the SCSI subsystem (where available). Smaller levels reduce verbosity. .TP .B SANE_SCSICMD_TIMEOUT sets the timeout value for SCSI commands in seconds. Overriding the default value of 120 seconds should only be necessary for very slow scanners. .SH "SEE ALSO" .BR sane (7), .BR sane\-find\-scanner (1), .BR sane\-"backendname" (5), .BR sane\-usb (5) .SH AUTHOR David Mosberger sane-backends-1.0.27/doc/sane-matsushita.man0000664000175000017500000001165712112021330015565 00000000000000.TH sane\-matsushita 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-matsushita .SH NAME sane\-matsushita \- SANE backend for Panasonic KV-SS high speed scanners .SH DESCRIPTION The .B sane\-matsushita library implements a SANE (Scanner Access Now Easy) backend that provides access to some Panasonic KV-SS high speed scanners. This backend is stable. .PP At present, the following scanners are known to work with this backend: .PP .RS .ft CR .nf Product id -------------- KV-SS25 KV-SS25D KV-SS55EX (*) KV-S2025C (*) KV-S2045C (*) KV-S2065L (*) .fi .ft R .RE .PP (*) WARNING: None of the advanced options of these scanners are available (ie no color, no high resolution, no automatic cropping). Basically, the driver does no more than what it does for the KV-SS25. I don't have access to such scanners, and thus cannot add these options. Other Panasonic high speed scanners may or may not work with that backend. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d matsushita .RE .TP .B Scan Mode .TP .B \-\-mode selects the basic mode of operation of the scanner. .TP .B \-\-resolution selects the resolution for a scan. Each model supports all or a subset of these resolutions: 100, 150, 200, 240, 300, 360, 400. .TP .B \-\-duplex indicates whether to scan both side of the sheet. .TP .B \-\-feeder\-mode selects the number of pages to scan (one or until the tray is empty). .TP .B Geometry .TP .B \-\-paper\-size A4|...|Legal|Letter [A4] options selects the area to scan. It adjust the .B \-l \-t \-x \-y options accordingly. It does not need to be the real size of the paper. .TP .B \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters. It is possible to use the option .I \-\-paper\-size instead. .TP .B Enhancement .TP .B \-\-brightness controls the brightness of the acquired image. The value varies from 1 to 255, or less, depending on the scanner model. .TP .B \-\-contrast controls the contrast of the acquired image. Some models do not support that option. .TP .B \-\-automatic\-threshold automatically sets brightness, contrast, white level, gamma, noise reduction and image emphasis. These options are not available when automatic\-threshold is in use. .TP .B \-\-halftone\-pattern option sets the tonal gradation for the halftone mode. Pattern downloading is not implemented by the backend. .TP .B \-\-autoseparation provides automatic separation of text and images. .TP .B \-\-white\-level option indicate the source of the white base. .TP .B \-\-noise\-reduction reduces the isolated dot noise. This option is not supported by all scanners. .TP .B \-\-image\-emphasis option sets the image emphasis. Some selection are not available on all scanners. .TP .B \-\-gamma options set the gamma curve. It is only valid for Gray modes, and is not available on all scanners. Gamma downloading is not implemented by the backend. .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/matsushita.conf supports the device name to use (eg /dev/scanner) and the SCSI option to auto-detect the scanners supported. .SH FILES .TP .I @LIBDIR@/libsane\-matsushita.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-matsushita.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_MATSUSHITA If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH LIMITATIONS .TP .B Memory in the KV-SS 25 The KV-SS 25 has not enough internal memory to scan a whole A4 page in duplex mode at high resolution. The frontend will return a memory error in that case. Apparently, the KV-SS 25D has not that problem. .TP .B Pattern and gamma downloading The scanner, with the proper firmware, can download a halftone pattern and a gamma table. This is not implemented. .TP .B Sub-areas The scanner can support up to 3 sub-areas on each side to define some more precise enhancement options. This is not implemented. .TP .B Duplex mode The backend does not support the setting of different options for each side. The scan will occur with the same options (halftone pattern, brightness, image emphasis) for both sides. .SH SCANNING EXAMPLE To date, the only frontend capable of using this scanner at full speed is .B scanadf. A scanadf command line would be: scanadf \-d matsushita \-\-output\-file scan%04d.pbm \-\-start\-count 0 \-\-duplex \-\-resolution 300 \-\-feeder\-mode="All pages" \-\-paper\-size="A4" .SH BUGS None known. .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1), sane(7) .SH AUTHOR .TP The package is actively maintained by Frank Zago. .I http://www.zago.net/sane/#matsushita sane-backends-1.0.27/doc/sane-qcam.man0000664000175000017500000000611312112021330014313 00000000000000.TH sane\-qcam 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-qcam .SH NAME sane\-qcam \- SANE backend for Connectix QuickCam cameras .SH DESCRIPTION The .B sane\-qcam library implements a SANE (Scanner Access Now Easy) backend that provides access Connectix QuickCam cameras. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I port .RE .PP Where .I port is the I/O port address at which the device resides. This address is normally specified in hexadecimal using C syntax (e.g., 0x37b) and may be prefixed with the letter "u" (e.g., u0x37b) to force the backend to access the camera in uni-directional mode. .SH CONFIGURATION The contents of the .I qcam.conf file is a list port addresses that may be connected to a Connectix QuickCam. Empty lines and everything starting from a hash mark (#) up to the end of a line are ignored. A sample configuration file is shown below: .PP .RS 0x37b # /dev/lp0 .br 0x378 # /dev/lp1 .br u0x278 # /dev/lp2 forced in uni-directional mode .br 0x3bc # /dev/lp0 (alternate address) .RE .PP In general, it is safest to list only the port addresses that really correspond to a QuickCam. For example, if one of the listed addresses actually connect to a printer, then starting up this backend will cause the printer to perform a device reset (which is generally undesirable). .SH FILES .TP .I @CONFIGDIR@/qcam.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-qcam.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-qcam.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_QCAM If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH AUTHOR David Mosberger .SH BUGS Support is currently limited to the color version of the QuickCam. The black-and-white camera is starting to work too, but I don't believe it works in all cases yet. Reportedly, acquiring images of certain sizes work fine, but others result in shifted images (sounds like a problem due to byte-padding). .PP The program needs root-privileges since it needs to be able to access the camera's I/O ports. .SH SEE ALSO sane(7) sane-backends-1.0.27/doc/doxygen-genesys.conf.in0000664000175000017500000022523512775277260016423 00000000000000# Doxyfile 1.8.1.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = GENESYS # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = GENESYS backend documentation # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = ./ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = YES # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../include/sane/ \ ../backend # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = genesys*.[ch] # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = YES # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = ./ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = ./genesys-html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user # can expand and collapse entries dynamically later on. Doxygen will expand # the tree to such a level that at most the specified number of entries are # visible (unless a fully collapsed tree already exceeds this amount). # So setting the number of entries 1 will produce a full collapsed tree by # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = ../backend # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = NO # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES sane-backends-1.0.27/doc/sane-hp5400.man0000664000175000017500000000656112112021330014321 00000000000000.TH sane\-hp5400 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hp5400 .SH NAME sane\-hp5400 \- SANE backend for Hewlett-Packard 54XX scanners .SH DESCRIPTION The .B sane\-hp5400 library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Hewlett-Packard USB flatbed scanners: .PP .RS ScanJet 5400C .br ScanJet 5470C .br ScanJet 5490C .RE .PP More details can be found on the hp5400 backend homepage .IR http://hp5400backend.sourceforge.net/ . .PP This is ALPHA software. Keep your hand at the scanner's plug and unplug it, if the head bumps at the end of the scan area. See also the BUGS section. .PP If you own a scanner other than the ones listed above that works with this backend, please let us know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .IR /proc/bus/usb/devices , .I sane\-find\-scanner or syslog) to us. Even if the scanner's name is only slightly different from the models mentioned above, please let us know. .PP .SH CONFIGURATION The contents of the .I hp5400.conf file is a list of usb lines containing vendor and product ids that correspond to USB scanners. The file can also contain the names of device files that correspond to an HP 54XX scanner. Empty lines and lines starting with a hash mark (#) are ignored. The scanners are autodetected by .B usb vendor_id product_id statements which are already included into .IR hp5400.conf . "vendor_id" and "product_id" are hexadecimal numbers that identify the scanner. If autodetection does not work, add the device name of your scanner to the configuration file, e.g. .IR /dev/usb/scanner0 . .PP .SH FILES .TP .I @CONFIGDIR@/hp5400.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-hp5400.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hp5400.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_HP5400 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_HP5400=4 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .br .I http://hp5400backend.sourceforge.net/ .SH AUTHOR Martijn van Oosterhout , Thomas Soumarmon . Manpage by Henning Meier-Geinitz . .SH BUGS Scanning is only tested with Linux/ix86/gcc. Be careful when testing on other operating systems and especially on big-endian platforms. The scanner may get wrong data. sane-backends-1.0.27/doc/sane-mustek.man0000664000175000017500000003420312112021330014703 00000000000000.TH sane\-mustek 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-mustek .SH NAME sane\-mustek \- SANE backend for Mustek SCSI flatbed scanners (and some other devices) .SH DESCRIPTION The .B sane\-mustek library implements a SANE (Scanner Access Now Easy) backend that provides access to Mustek (and some relabeled Trust and Primax) SCSI and parport flatbed scanners. At present, the following scanners are known to work more or less with this backend: .PP .RS Paragon MFS-6000CX .br Paragon MFS-12000CX .br Paragon MFC-600S, 600 II CD, ScanMagic 600 II SP .br Paragon MFC-800S, 800 II SP .br Paragon MFS-6000SP .br Paragon MFS-8000SP .br Paragon MFS-1200SP, MFS-12000SP .br ScanExpress 6000SP .br ScanExpress 12000SP, 12000SP Plus, Paragon 1200 III SP, ScanMagic 9636S, 9636S Plus .br Paragon 1200 LS .br ScanExpress A3 SP .br Paragon 1200 SP Pro .br Paragon 1200 A3 Pro .br Paragon 600 II EP .br Paragon 600 II N .br Trust Imagery 1200 .br Trust Imagery 1200 SP .br Trust Imagery 4800 SP .br Trust SCSI Connect 19200 .br Primax Compact 4800 SCSI .br .RE .PP More details can be found on the Mustek SCSI backend homepage .IR http://www.meier\-geinitz.de/sane/mustek\-backend/ . .PP Don't mix up MFS (Paragon), Pro and ScanExpress models! They're completely different. Check the exact model name! .PP Note that most of the above scanners come with a SCSI interface. The only non-SCSI scanners that have some support at this point is the 600 II N and 600 II EP scanners. The former one comes with its own parallel port adapter (i.e., it does .I not attach to the printer port). Both scanners use the SCSI protocol internally, too. More info on how to use these parallel port scanners can be found below in section .BR "PARALLEL PORT SCANNERS" . Other parallel port scanners are not supported by this backend but you may be successful using the Mustek parallel port backend mustek_pp, see .BR sane\-mustek_pp (5). USB scanners are also not supported by this backend but the ma1509, mustek_usb, gt68xx, and plustek backends include support for some of them, see .BR sane\-ma1509 (5), .BR sane\-mustek_usb (5), .BR sane\-gt68xx "(5), and" .BR sane\-plustek (5). .PP Mustek scanners have no protection against exceeding the physical scan area height. That is, if a scan is attempted with a height that exceeds the height of the scan surface, the scanner begins making loud noises and the scan mechanism may be damaged. Thus, if you hear such a noise, IMMEDIATELY turn off the scanner. This shouldn't happen if your scanner is in the list of known scanners. There is more information in the .I @DOCDIR@/PROBLEMS file. .PP If you own a Mustek (or Trust) scanner other than the ones listed above that works with this backend, please let us know by sending the scanner's exact model name (look at the front and back of the scanner) and a debug output to .IR sane\-devel@lists.alioth.debian.org . You can get the debug output by setting the environment variable .B SANE_DEBUG_MUSTEK to 5 and showing the list of available scanners with scanimage \-L. Please send all of it to the mailing list. You must be subscribed to sane\-devel before you can send mail to the list. See .I http://www.sane\-project.org/mailing\-lists.html for details. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is either the path-name for the special device that corresponds to a SCSI scanner or the port number at which the parallel port scanners can be found (see section .B "PARALLEL PORT SCANNERS" below). For SCSI scanners, the special device name must be a generic SCSI device or a symlink to such a device. The program .I sane\-find\-scanner helps to find out the correct device. Under Linux, such a device name could be .I /dev/sg0 or .IR /dev/sg3 , for example. See .BR sane\-scsi (5) for details. .SH CONFIGURATION The contents of the .I mustek.conf file is a list of options and device names that correspond to Mustek scanners. Empty lines and lines starting with a hash mark (#) are ignored. See .BR sane\-scsi (5) on details of what constitutes a valid device name. .PP The supported options are .BR linedistance\-fix , .BR lineart\-fix , .BR legal\-size , .BR buffersize , .BR blocksize , .BR strip\-height , .BR disable\-double\-buffering , .BR disable\-backtracking , and .BR force\-wait . .PP Options come in two flavors: global and positional ones. Global options apply to all devices managed by the backend whereas positional options apply just to the most recently mentioned device. Note that this means that the order in which the options appear matters! .PP Option .B linedistance\-fix is positional and works around a problem that occurs with some SCSI controllers (notably the ncr810 controller under Linux). If color scans have horizontal stripes and/or the colors are off, then it's likely that your controller suffers from this problem. Turning on this option usually fixes the problem. .PP Option .B lineart\-fix is positional and works around a timing problem that seems to exist with certain MFS-12000SP scanners. The problem manifests itself in dropped lines when scanning in lineart mode. Turning on this option should fix the problem but may slow down scanning a bit. .PP Option .B legal\-size is positional and sets the size of the scan area to Legal format. Set this option if you own a Paragon 12000 LS. It can't be distinguished by software from a ScanExpress 12000 SP (ISO A4 format). .PP Option .B buffersize is a positional option that overrides the default value set for the size of the SCSI buffer. The buffer size is specified in kilobytes. The default value is 128. Because of double buffering the buffer actually sent to the scanner is half the size of this value. Try to increase this value to achieve higher scan speeds. Note that some ScanExpress scanners don't like buffer sizes above 64 kb (buffersize = 128). If your sg driver can't set SCSI buffer sizes at runtime you may have to change that value, too. See sane\-scsi(5) for details. .PP Option .B blocksize is a positional option that overrides the default value set for the maximum amount of data scanned in one block. The buffer size is specified in kilobytes. Some scanners freeze if this value is bigger than 2048. The default value is 1 GB (so effectively no limit) for most scanners. Don't change this value if you don't know exactly what you do. .PP Option .B strip\-height is a global option that limits the maximum height of the strip scanned with a single SCSI read command. The height is specified in inches and may contain a fractional part (e.g., 1.5). Setting the strip\-height to a small value (one inch, for example) reduces the likelihood of encountering problems with SCSI driver timeouts and/or timeouts with other devices on the same SCSI bus. Unfortunately, it also increases scan times. With current SCSI adapters and drivers this option shouldn't be needed any more. .PP Option .B disable\-double\-buffering is a global option. If set, the backend will only send one buffer at a time to the scanner. Try this option if you have trouble while scanning, e.g. SCSI errors, freezes, or the first few cm are repeated over and over again in your image. .PP Option .B disable\-backtracking is a positional option. If set, the scanner will not move back its slider after each SCSI buffer is filled (`backtracking'). Setting this option will lead to faster scans but may also produce horizontal stripes. This option doesn't work with every scanner (only some of the paragon models can modify backtracking). .PP Finally, .B force\-wait is a global option. If set, the backend will wait until the device is ready before sending the inquiry command. Further more the backend will force the scan slider to return to its starting position (not implemented for all scanners). This option may be necessary with the 600 II N or when scanimage is used multiple times (e.g. in scripts). The default is off (not set). .PP A sample configuration file is shown below: .PP .RS # limit strip height of all scanners to 1.5 inches: .br option strip\-height 1.5 .br .br /dev/scanner # first Mustek scanner .br # 1 MB buffer for /dev/scanner: .br option buffersize 1024 .br /dev/sge # second Mustek scanner .br # turn on fixes for /dev/sge: .br option lineart\-fix .br option linedistance\-fix .RE .SH "SCSI ADAPTER TIPS" .PP You need a SCSI adapter for the SCSI scanners. Even if the connector is the same as that of parallel port scanners, connecting it to the computers parallel port will NOT work. .PP Mustek SCSI scanners are typically delivered with an ISA SCSI adapter. Unfortunately, that adapter is not worth much since it is not interrupt driven. It is (sometimes) possible to get the supplied card to work, but without interrupt line, scanning will be very slow and put so much load on the system, that it becomes almost unusable for other tasks. .PP If you already have a working SCSI controller in your system, you should consider that Mustek scanners do not support the SCSI-2 disconnect/reconnect protocol and hence tie up the SCSI bus while a scan is in progress. This means that no other SCSI device on the same bus can be accessed while a scan is in progress. .PP Because the Mustek-supplied adapter is not worth much and because Mustek scanners do not support the SCSI-2 disconnect/reconnect protocol, it is recommended to install a separate (cheap) SCSI controller for Mustek scanners. For example, ncr810 based cards are known to work fine and cost as little as fifty US dollars. .PP For Mustek scanners, it is typically necessary to configure the low-level SCSI driver to disable synchronous transfers (sync negotiation), tagged command queuing, and target disconnects. See .BR sane\-scsi (5) for driver- and platform-specific information. .PP The ScanExpress models have sometimes trouble with high resolution color mode. If you encounter sporadic corrupted images (parts duplicated or shifted horizontally) kill all other applications before scanning and (if sufficient memory is available) disable swapping. .PP Details on how to get the Mustek SCSI adapters and other cards running can be found at .IR http://www.meier\-geinitz.de/sane/mustek\-backend/#SCSI . .SH "PARALLEL PORT SCANNERS" This backend has support for the Paragon 600 II EP and Paragon 600 II N parallel port scanners. Note that the latter scanner comes with its own ISA card that implements a funky parallel port (in other words, the scanner does not connected to the printer parallel port). .PP These scanners can be configured by listing the port number of the adapter or the parallel port in the mustek.conf file. Valid port numbers for the 600 II N are .IR 0x26b ", " 0x2ab ", " 0x2eb ", " 0x22b ", " 0x32b ", " 0x36b ", " .IR 0x3ab ", " 0x3eb . For the 600 II EP use one of these: .IR parport0 ", " parport1 ", " parport2 ", " 0x378 ", " 0x278 ", " 0x3bc . Pick one that doesn't conflict with the other hardware in your computer. Put only one number on a single line. Example: .PP .RS .I 0x3eb .RE .PP Note that for these scanners usually root privileges are required to access the I/O ports. Thus, either make frontends such as .BR scanimage (1) and .BR xscanimage (1) setuid root (generally not recommended for safety reasons) or, alternatively, access this backend through the network daemon .BR saned (8). .PP If the Mustek backend blocks while sending the inquiry command to the scanner, add the option .B force\-wait to .IR mustek.conf . .PP Also note that after a while of no activity, some scanners themselves (not the SANE backend) turns off their CCFL lamps. This shutdown is not always perfect with the result that the lamp sometimes continues to glow dimly at one end. This doesn't appear to be dangerous since as soon as you use the scanner again, the lamp turns back on to the normal high brightness. However, the first image scanned after such a shutdown may have stripes and appear to be over-exposed. When this happens, just take another scan, and the image will be fine. .SH FILES .TP .I @CONFIGDIR@/mustek.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-mustek.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-mustek.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_MUSTEK If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. .ft CR .nf Value Description 0 no output 1 print fatal errors 2 print important messages 3 print non-fatal errors and less important messages 4 print all but debugging messages 5 print everything .fi .ft R Example: export SANE_DEBUG_MUSTEK=4 .SH "SEE ALSO" .BR sane (7), .BR sane\-find\-scanner (1), .BR sane\-scsi (5), .BR sane\-mustek_usb (5), .BR sane\-gt68xx (5), .BR sane\-plustek (5), .BR sane\-mustek_pp (5) .br .I @DOCDIR@/mustek/mustek.CHANGES .br .I http://www.meier\-geinitz.de/sane/mustek\-backend/ .SH AUTHOR David Mosberger, Andreas Czechanowski, Andreas Bolsch (SE extensions), Henning Meier-Geinitz, James Perry (600 II EP). .SH BUGS Scanning with the SCSI adapters supplied by Mustek is very slow at high resolutions and wide scan areas. .PP Some scanners (e.g. Paragon 1200 A3 + Pro, SE A3) need more testing. .PP The gamma table supports only 256 colors, even if some scanners can do more. .PP More detailed bug information is available at the Mustek backend homepage: .IR http://www.meier\-geinitz.de/sane/mustek\-backend/ . sane-backends-1.0.27/doc/sane-plustek_pp.man0000664000175000017500000003305612775277260015624 00000000000000.TH sane\-plustek_pp 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-plustek_pp .SH NAME sane\-plustek_pp \- SANE backend for Plustek parallel port flatbed scanners .SH DESCRIPTION The .B sane\-plustek_pp library implements a SANE (Scanner Access Now Easy) backend that provides access to Plustek ASIC 9600[1/3] and P9800[1/3] based parallel port flatbed scanners. The access of the scanner is either done directly by the backend or via kernel module, called pt_drv which can be created out of the plustek_pp backend code \- see also section .B "BUILDING THE KERNEL MODULE" for further information. .SH "SUPPORTED DEVICES" At present, the following scanners should work with this backend and/or the kernel module: .PP .B "PLUSTEK SCANNERS" .PP .ft CR .nf Parallelport Model: ASIC: Properties: ---------------------- ----- ------------------------ OpticPro PT12 98003 600x1200 dpi 36bit 512Kb OpticPro P12 98003 600x1200 dpi 36bit 512Kb OpticPro 9636T/12000T 98001 600x1200 dpi 36bit 512Kb OpticPro 12000P Turbo 98001 600x1200 dpi 36bit 512Kb OpticPro 9636P+/Turbo 98001 600x1200 dpi 36bit 512Kb OpticPro 9636P 96003 600x1200 dpi 36bit 128Kb OpticPro 12000P/96000P 96003 600x1200 dpi 36bit 128Kb OpticPro 1236P 96003 600x1200 dpi 30bit 128Kb OpticPro 9600P 96003 600x1200 dpi 30bit 128Kb OpticPro 9630P/FBIV 96003 600x1200 dpi 30bit 128Kb OpticPro 9630PL (14") 96003 600x1200 dpi 30bit 128Kb OpticPro A3I 96003 400x800 dpi 36bit 128Kb OpticPro 600P/6000P 96003 300x600 dpi 30bit 32Kb OpticPro 4831P 96003 300x600 dpi 30bit 32Kb OpticPro 4830P/FBIII 96003 300x600 dpi 30bit 32Kb OpticPro 4800P/FBII 96001 300x600 dpi 24bit 32Kb .fi .ft R .PP .B "PRIMAX SCANNERS" There are some scanners sold by Primax, but they are in fact Plustek devices. These scanners are also supported. The following table will show the relationship: .PP .ft CR .nf Model: Plustek Model: Remarks: --------------------------- -------------- ------------ Colorado 4800 OpticPro 4800 not tested Compact 4800 Direct OpticPro 600 mov=2 Compact 4800 Direct 30bit OpticPro 4830 mov=7 Compact 9600 Direct 30bit OpticPro 9630 works .fi .ft R .PP .B "GENIUS SCANNERS" The following devices are sold as Genius Scanners, but are in fact Plustek devices. The table will show the relationship: .PP .ft CR .nf Model: Remarks: --------------------------- ---------------------------- Colorpage Vivid III V2 Like P12 but has two buttons and Wolfson DAC .fi .ft R .PP .B "ARIES SCANNERS" There's one scanner sold as Aries Scanner, but is in fact a Plustek device. The following table will show the relationship: .PP .ft CR .nf Model: Plustek Model: Remarks: --------------------------- -------------- ------------ Scan-It 4800 OpticPro 600 mov=2 .fi .ft R .PP .B "BrightScan SCANNERS" There's one scanner sold as BrightScan OpticPro Scanner, this is also a rebadged Plustek device. The following table will show the relationship: .PP .ft CR .nf Model: Remarks: --------------------------- ---------------------------- BrightScan OpticPro OpticPro P12 .fi .ft R .SH "DEVICE NAMES" This backend works in two modes, the so called "direct-mode" and the "kernel-mode". In direct-mode, the user-space backend is used, in kernel-mode, you should have a kernel-module named pt_drv loaded. This backends default device is: .PP .RS .I 0x378 .RE .PP This "default device" will be used, if no configuration file can be found. It is rather the base address of the parallel port on i386 machines. .PP As the backend supports up to four devices, it is possible to specify them in the configuration file .PP .RS .I @CONFIGDIR@/plustek_pp.conf .RE .PP See this file for examples. .PP .SH "CONFIGURATION" .PP This section describes the backends' configuration file entries. The file is located at: .I @CONFIGDIR@/plustek_pp.conf .PP For a proper setup, you will need at least two entries: .RS .I [direct] .br .I device 0x378 .RE .PP or .RS .I [kernel] .br .I device /dev/pt_drv .RE .PP .I direct tells the backend, that the following devicename (here .IR 0x378 ) has to be interpreted as parallel port scanner device. In fact it is the address to use, alternatively you can use .I /dev/parport0 if the backend has been compiled with libieee1284 support. .I kernel should only be used, when a kernel-module has been built out of the backend sources. See below for more instructions about this. .PP Further options: .PP option warmup t .RS .I t specifies the warmup period in seconds .RE .PP option lampOff t .RS .I t is the time in seconds for switching off the lamps in standby mode .RE .PP option lOffonEnd b .RS .I b specifies the behaviour when closing the backend, 1 --> switch lamps off, 0 --> do not change lamp status .RE .PP option mov m .RS .I m is the model override switch, which only works in direct mode. .TP .IR m " = 0" default: no override .TP .IR m " = 1" OpticPro 9630PL override (works if OP9630 has been detected) forces legal size (14") .TP .IR m " = 2" Primax 4800Direct override (works if OP600 has been detected) swaps red/green color .TP .IR m " = 3" OpticPro 9636 override (works if OP9636 has been detected) disables backends transparency/negative capabilities .TP .IR m " = 4" OpticPro 9636P override (works if OP9636 has been detected) disables backends transparency/negative capabilities .TP .IR m " = 5" OpticPro A3I override (works if OP12000 has been detected) enables A3 scanning .TP .IR m " = 6" OpticPro 4800P override (works if OP600 has been detected) swaps red/green color .TP .IR m " = 7" Primax 4800Direct 30bit override (works if OP4830 has been detected) .RE .PP See the plustek_pp.conf file for examples. .PP .SH "BUILDING THE KERNEL MODULE" As mentioned before, the plustek_pp backend code can also be compiled and installed as linux kernel module. To do so, you will need the source-files of this sane\-backend installation. Unpack this tar-ball and go to the directory: .br .I sane\-backends/doc/plustek .br Within this directory, you should find a script called: .br .I MakeModule.sh .br Now if your Linux kernelsources are installed correctly, it should be possible to build, install and load the module .B pt_drv. .B Please note, that the kernelsources need to be configured correctly. Refer to your distributions manual on how this is done. As root user, try .br .I ./MakeModule.sh .br the script will try and get all necessary information about your running kernel and will lead you through the whole installation process. .br .B Note: Installing and loading the can only be done as superuser. .PP .SH "KERNEL MODULE SETUP" The configuration of the kernel module is done by providing some or more options found below to the kernel module at load time. This can be done by invoking insmod with the appropriate parameters or appending the options to the file .B /etc/modules.conf (kernel < 2.6.x) or .B /etc/modprobe.conf (kernel >= 2.6.x) .PP .B The Options: .br lampoff=lll .RS The value .I lll tells the driver, after how many seconds to switch-off the lamp(s). The default value is 180. 0 will disable this feature. .br .B HINT: Do not use a value that is too small, because often switching on/off the lamps will reduce their lifetime. .RE .PP port=ppp .RS .I ppp specifies the port base address, where the scanner is connected to. The default value is 0x378, which is normally a standard. .RE .PP warmup=www .RS .I www specifies the time in seconds, how long a lamp has to be on, until the driver will start to scan. The default value is 30. .RE .PP lOffonEnd=e .RS .I e specifies the behaviour when unloading the driver, 1 --> switch lamps off, 0 --> do not change lamp status .RE .PP slowIO=s .RS .I s specifies which I/O functions the driver should use, 1 --> use delayed functions, 0 --> use the non-delayed ones .RE .PP forceMode=fm .RS .I fm specifies port mode which should be used, 0 --> autodetection, 1 --> use SPP mode and 2 --> use EPP mode .RE .PP mov=m .RS .TP .IR m " = 0" default: no override .TP .IR m " = 1" OpticPro 9630PL override (works if OP9630 has been detected) forces legal size (14") .TP .IR m " = 2" Primax 4800Direct override (works if OP600 has been detected) swaps red/green color .TP .IR m " = 3" OpticPro 9636 override (works if OP9636 has been detected) disables backends transparency/negative capabilities .TP .IR m " = 4" OpticPro 9636P override (works if OP9636 has been detected) disables backends transparency/negative capabilities .TP .IR m " = 5" OpticPro A3I override (works if OP12000 has been detected) enables A3 scanning .TP .IR m " = 6" OpticPro 4800P override (works if OP600 has been detected) swaps red/green color .TP .IR m " = 7" Primax 4800Direct 30bit override (works if OP4830 has been detected) .RE .PP Sample entry for file .B "/etc/modules.conf" : .br .I alias char\-major\-40 pt_drv .br .I pre-install pt_drv modprobe -k parport .br .I options pt_drv lampoff=180 warmup=15 port=0x378 lOffonEnd=0 mov=0 slowIO=0 forceMode=0 .PP For multidevice support, simply add values separated by commas to the different options .br .I options pt_drv port=0x378,0x278 mov=0,4 slowIO=0,1 forceMode=0,1 .PP Remember to call depmod after changing /etc/conf.modules. .PP .SH "PARALLEL PORT MODES" .PP The current driver works best, when the parallel port has been set to EPP-mode. When detecting any other mode such as ECP or PS/2 the driver tries to set to a faster, supported mode. If this fails, it will use the SPP mode, as this mode should work with all Linux supported parallel ports. If in doubt, enter your BIOS and set it to any mode except ECP. .PP Former Plustek scanner models (4830, 9630) supplied a ISA parallel port adapter card. This card is .BR not supported by the driver. .PP The ASIC 96001/3 based models have sometimes trouble with high resolution modes. If you encounter sporadic corrupted images (parts duplicated or shifted horizontally) kill all other applications before scanning and (if sufficient memory available) disable swapping. .PP See the plustek_pp.conf file for examples. .PP .SH FILES .TP .I @CONFIGDIR@/plustek_pp.conf The backend configuration file .TP .I @LIBDIR@/libsane\-plustek_pp.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-plustek_pp.so The shared library implementing this backend (present on systems that support dynamic loading). .TP .I /lib/modules//kernel/drivers/parport/pt_drv.o The Linux kernelmodule for kernels < 2.6.x. .TP .I /lib/modules//kernel/drivers/parport/pt_drv.ko The Linux kernelmodule for kernels >= 2.6.x. .PP .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_PLUSTEK_PP If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_PLUSTEK_PP=10 .SH "SEE ALSO" .BR sane (7), .br .I @DOCDIR@/plustek/Plustek\-PARPORT.changes .br .I http://www.gjaeger.de/scanner/plustek_pp/ .SH "CONTACT AND BUG-REPORTS" Please send any information and bug-reports to: .br .B SANE Mailing List .PP Additional info and hints can be obtained from our .br Mailing-List archive at: .br .B http://www.sane\-project.org/mailing\-lists.html .PP or directly from the projects' homepage at: .br .B http://www.gjaeger.de/scanner/plustek_pp/ .PP To obtain debug messages from the backend, please set the environment-variable .I SANE_DEBUG_PLUSTEK_PP before calling your favorite scan-frontend (i.e. xscanimage). .br .B i.e.: export SANE_DEBUG_PLUSTEK_PP=20 ; xscanimage .PP The value controls the verbosity of the backend. .PP .SH "KNOWN BUGS & RESTRICTIONS" .PP * The Halftoning works, but the quality is poor .PP * Printers (especially HP models) will start to print during scanning. This in fact is a problem to other printers too, using bidirectional protocol (see www.plustek.com (TAIWAN) page for further details) .PP * The driver does not support these manic scalings up to 16 times the physical resolution. The only scaling is done on resolutions between the physical resolution of the CCD-sensor and the stepper motor i.e. you have a 600x1200 dpi scanner and you are scanning using 800dpi, so scaling is necessary, because the sensor only delivers 600dpi but the motor is capable to perform 800dpi steps. .PP * On some devices, the pictures seems bluish .PP .I ASIC 98001 based models: .PP * The 300dpi transparency and negative mode does not work correctly. .PP * There is currently no way to distinguish a model with and without transparency unit. .PP * The scanned images seem to be too dark (P9636T) .PP .I ASIC 96003/1 based models: .PP * 30bit mode is currently not supported. .PP * On low end systems under heavy system load the driver may lose data, which can result in picture corruption or cause the sensor to hit the scan bed. .PP * The scanning speed on 600x1200 dpi models is slow. .PP * The scanning quality of the A3I is poor sane-backends-1.0.27/doc/sane-microtek2.man0000664000175000017500000002352612112021330015300 00000000000000.TH sane\-microtek2 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .SH NAME sane\-microtek2 \- SANE backend for Microtek scanners with SCSI-2 command set .SH DESCRIPTION The .B sane\-microtek2 library implements a SANE (Scanner Access Now Easy) backend that provides access to Microtek scanners with a SCSI-2 command set. This backend can be considered alpha to beta. Some scanner models are reported to work well, others not. New development versions of this backend can be obtained from .B http://karstenfestag.gmxhome.de .PP There exists a different backend for Microtek scanners with SCSI-1 command set. Refer to sane\-microtek(5) for details. .PP And there is work in progress for the ScanMaker 3600. See .B http://sourceforge.net/projects/sm3600 .PP At present, the following scanners are known positively to work with this backend: .PP .ft CR .nf Vendor Product id Remark -------------------------------------------------------------------- Microtek E3+ Parport and SCSI Microtek X6 SCSI Microtek X6EL SCSI Microtek X6USB USB Microtek ScanMaker V300 Parport and SCSI Microtek ScanMaker V310 Parport and SCSI Microtek ScanMaker V600 Parport and SCSI Microtek ScanMaker 330 SCSI Microtek ScanMaker 630 SCSI Microtek ScanMaker 636 SCSI Microtek ScanMaker 9600XL SCSI; only flatbed mode? Microtek Phantom 330CX Parport Microtek SlimScan C3 Parport Microtek SlimScan C6 USB Microtek Phantom 636 SCSI Microtek Phantom 636CX Parport Microtek V6USL SCSI and USB Microtek V6UPL USB; not stable Microtek X12USL SCSI; only 8bit color, work in progress Vobis HighScan SCSI (E3+ based models) Scanport SQ300 Parport? Scanport SQ4836 SCSI Scanpaq SQ2030 Parport .fi .ft R .PP Additional information can be found at .BR http://www.sane\-project.org/ . .PP If you own a Microtek scanner other than the ones listed above, it may or may not work with SANE! Because equal scanners are sold under different names in different countries your model may be equivalent to one of the above. .PP The parport scanners work with the ppscsi + onscsi kernel modules. See .I http://cyberelk.net/tim/parport/ppscsi.html and .IR http://penguin-breeder.org/kernel/download/ . .PP The USB scanners work with the microtek kernel module. You may have to add the vendor and model codes to microtek.c if they aren't yet listed there. .PP Both parport and USB scanners need the generic SCSI support, so check if you have loaded the scsi_mod and sg modules! .PP If you try your scanner for the first time keep an eye on it. If it gets commands that it doesn't understand the scanhead may go beyond the scan area. The scanner then makes strange noises. In this case immediately switch off the scanner or disconnect its power cable to prevent damages! .PP If your scanner is a different one than the models mentioned above and it is working please tell the author about it. It would be nice if you add a logfile to this information (creation of the logfile: see below). .PP If your scanner is not working properly you also should create a logfile and send it to the author. He will use the information to improve the backend and possibly make your scanner work. .PP .br How to create the logfile? .TP \- put the line .br "option dump 2" into your .I microtek2.conf file or change the existing "option dump" to "2" .TP \- in a terminal (bash) type .br "export SANE_DEBUG_MICROTEK2=30" and then .br "scanimage \-l0 \-t0 \-x100 \-y20 2>scan.log >sout.pnm" .br You get two files: scan.log contains the logfile and sout.pnm the scanned image (if there was scanned something). Zip them before sending. .SH "FRONTEND OPTIONS" This backend dynamically enables the options for the frontend, that are supported by the scanner in dependence of the scanning-mode and other options. Not supported options are disabled. .PP The following options are supported by the Microtek2-driver: .PP Color, grayscale, halftone and lineart scans. .PP Highlight, midtone, shadow, contrast, brightness, exposure time control, gamma correction, threshold (dependent of the scan mode and the scanner capabilities) .PP Transparency media adapter, automatic document feeder .PP Additional options can be enabled or disabled in the .I microtek2.conf file. See the configuration section of this manpage. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the UNIX path-name for the special device that corresponds to the scanner. The special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .I /dev/sge for example. .SH "CONFIGURATION" The configuration file for this backend resides in .IR @CONFIGDIR@/microtek2.conf . Its contents is a list of device names that correspond to Microtek scanners with SCSI-2 interface. Empty lines and lines starting with a hash mark (#) are ignored. .PP The configuration file may also contain options. Global options that are valid for all devices are placed above the device names. Device-specific options are placed under the device name. Note that, except for option dump and option strip-height , the entry in the microtek2.conf file only enables the corresponding option for being showed in the frontend. There, in the frontend, you can switch the options on and off. Currently the following options are supported: .PP .RS option dump .br option strip\-height .br option no\-backtrack\-option .br option lightlid\-35 .br option toggle\-lamp .br option lineart\-autoadjust .br option backend\-calibration .br option colorbalance\-adjust .RE .PP .I option dump enables printing of additional information about the SCSI commands that are sent to the scanner to stderr. This option is primarily useful for debugging purpose. This option has to be a global option and is best placed at the top of the .I microtek2.conf file. .PP If n=1 the contents of the command blocks and the results for the INQUIRY and READ SCANNER ATTRIBUTES command are printed to stderr. .PP If n=2 the contents of the command blocks for all other SCSI commands are printed to stderr, too. If n=3 the contents of the gamma table is printed, too. If n=4 all scan data is additionally printed to stderr. .PP The default is n=1. .PP .I option strip\-height , where is a floating point number, limits the amount of data that is read from the scanner with one read command. The unit is inch and defaults to 1.0, if this option is not set in the configuration file. If less than inch of data fit into the SCSI buffer, then the smaller value is used and this option has no effect. .PP If your system has a big SCSI buffer and you want to make use of the whole buffer, increase the value for . For example, if is set to 14.0, no restrictions apply for scanners with a letter, legal or A4 sized scan area. .PP .PP The following options enable or disable additional frontend options. If an option is set to an appropriate option will appear in the frontend. .PP .I option no\-backtrack\-option prevents the scanner head from moving backwards between the read commands. This speeds up scanning. Try it. .PP .I option lightlid\-35 If you use the LightLid-35 transparency adapter you get an advanced option which switches off the flatbed lamp during the scan. .PP .I option toggle\-lamp You get a button in the frontend where you can switch on and off the flatbed lamp. .PP .I option lineart\-autoadjust You can tell the backend to try to determine a good value for the lineart threshold. .PP .I option backend\-calibration Some scanners (e.g. Phantom 330CX and 636CX) need to have calibrated the data by the backend. Try this option if you see vertical stripes in your pictures. .PP .I option colorbalance\-adjust Some scanners (e.g. Phantom 330CX and 636CX) need to have corrected the color balance. If this option is enabled you get advanced options where you can balance the colors. And you will have a button to use the values that the firmware of the scanner provides. .PP A sample configuration file is shown below: .PP .RS option dump 1 .br option strip\-height 1.0 .br /dev/scanner .br option no\-backtrack\-option on .br # this is a comment .br /dev/sge .br option lightlid\-35 on .RE This backend also supports the new configuration file format which makes it easier to detect scanners under Linux. If you have only one scanner it would be best to use the following configuration file for this backend: .PP .RS option dump 1 .br option strip\-height 14.0 .br option no\-backtrack\-option on .br option backend\-calibration on .br option lightlid\-35 on .br option toggle\-lamp on .br option lineart\-autoadjust on .br option colorbalance\-adjust off .br scsi * * Scanner .RE In this case all SCSI-Scanners should be detected automatically because of the .PP scsi * * Scanner .PP line. .SH "FILES" .TP .I @CONFIGDIR@/microtek2.conf The backend configuration file. .TP .I @LIBDIR@/libsane\-microtek2.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-microtek2.so The shared library implementing this backend (present on systems that support dynamic loading). .SH "ENVIRONMENT" .TP .B SANE_DEBUG_MICROTEK2 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 255 requests all debug output to be printed. Smaller levels reduce verbosity. To see error messages on stderr set SANE_DEBUG_MICROTEK2 to 1 (Remark: The whole debugging levels should be better revised). .br E.g. just say: .br export SANE_DEBUG_MICROTEK2=128 .SH "SEE ALSO" sane\-scsi(5), sane(7) .SH "AUTHORS" Bernd Schroeder (not active anymore) .br Karsten Festag karsten.festag@gmx.de sane-backends-1.0.27/doc/sane-epson2.man0000664000175000017500000003136213106201017014612 00000000000000.TH sane\-epson2 5 "22 Jan 2009" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-epson2 .SH NAME sane\-epson2 \- SANE backend for EPSON scanners .SH DESCRIPTION The .B sane\-epson2 library implements a SANE (Scanner Access Now Easy) backend that provides access to Epson flatbed scanners. This library supports a similar set of scanners as the sane\-epson driver but was developed to support a wider range of connections to the scanner; include network access. .PP Because .B sane\-epson and .B sane\-epson2 drivers support many of the same devices, if one driver gives you problems you may try disabling it to try the other. This can be done by removing the driver name from the .I dll.conf or perhaps by commenting out the options in .I epson.conf or .I epson2.conf. .PP At present, the following scanners are known to work with this backend: .PP .RS .ft CR .nf Model: Connection Type --------------------------- ------------------- ActionScanner II SCSI, parallel AcuLaser CX11 Series USB, Network AcuLaser CX21 Series USB, Network CX-3200 USB CX-3600 USB CX-3650 USB CX-4050 USB CX-4600 USB CX-4800 USB CX-5000 USB CX-5200 USB CX-5400 USB CX-6300 USB CX-6400 USB CX-6500 USB CX-6600 USB DX-3800 USB DX-5000 USB DX-5050 USB DX-6000 USB DX-7400 USB ES-300C SCSI, parallel ES-300GS SCSI ES-600C parallel ES-1200C parallel Expression 636 SCSI Expression 800 SCSI Expression 1600 USB, SCSI, IEEE-1394 Expression 1680 USB, SCSI, IEEE-1394 FilmScan 200 SCSI GT-5000 SCSI, parallel GT-5500 SCSI GT-6000 parallel GT-6500 parallel GT-7000 SCSI GT-8000 SCSI GT-8500 SCSI Perfection 610 USB Perfection 636S SCSI Perfection 636U USB Perfection 640 USB Perfection 1200S SCSI Perfection 1200U USB Perfection 1240 USB, SCSI Perfection 1640 USB, SCSI Perfection 1650 USB Perfection 1660 USB Perfection 2400 USB Perfection 2450 USB, IEEE-1394 Perfection 3200 USB Perfection 4870 USB Perfection 4990 USB RX-425 USB RX-500 USB RX-600 USB RX-700 USB V700 USB, IEEE-1394 V750 USB, IEEE-1394 .fi .ft R and many more. The official list is on the Sane web site. .RE For other scanners the software may or may not work. Please send mail to the sane-backend mailing list to report success with scanners not on the list or problems with scanners that are listed. .SH OPTIONS The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in programs like xscanimage or xsane. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d epson2 .RE Not all devices support all options. .TP .I Scan Mode The .I \-\-mode switch selects the basic mode of operation of the scanner. Valid choices are Binary, Gray and Color. The Binary mode is black and white only, Gray will produce 256 levels of gray or more depending on the scanner and Color means 24 bit color mode or more depending on the scanner. Some scanners will internally use 36 bit color, their external interface however may only support 24 bits. The .I \-\-depth option selects the bit depth the scanner is using. This option is only available for scanners that support more than one bit depth. Older scanners will always transfer the image in 8bit mode. Newer scanners allow one to select either 8 bits, 12 or 14 bits per color channel. For a color scan this means an effective color depth of 36 or 42 bits over all three channels. The valid choices depend on the scanner model. The .I \-\-halftoning switch selects the mode that is used in Binary mode. Valid options are "None", "Halftone A (Hard Tone)", "Halftone B (Soft Tone)", "Halftone C (Net Screen)", "Dither A (4x4 Bayer)", "Dither B (4x4 Spiral)", "Dither C (4x4 Net Screen)", "Dither D (8x4 Net Screen)", "Text Enhanced Technology", "Download pattern A", and "Download pattern B". The .I \-\-dropout switch selects the so called dropout color. Valid options are None, Red, Green and Blue. The default is None. The dropout color is used for monochrome scanning and selects the color that is not scanned. This can be used to e.g. scan an original with a colored background. The .I \-\-brightness switch controls the brightness of the scan. Valid options are integer values from \-3 to 3. The default is 0. The larger the brightness value, the brighter the image gets. If a user defined table for the gamma correction is selected, the brightness parameter is not available. The .I \-\-sharpness switch sets the sharpness of the image data. Valid options are integer values from \-2 to 2, with \-2 meaning "Defocus", \-1 "Defocus slightly", 0 "Normal", 1 "Sharpen slightly" and 2 "Sharpen". The .I \-\-gamma\-correction switch controls the scanner's internal gamma correction. Valid options are "Default", "User defined", "High density printing" "Low density printing" and "High contrast printing". The .I \-\-color\-correction switch controls the scanner's internal color correction function. Valid options are "No Correction", "Impact\-dot printers", "Thermal printers", "Ink\-jet printers" and "CRT monitors". The default is "CRT monitors". The .I \-\-resolution switch selects the resolution for a scan. Some EPSON scanners will scan in any resolution between the lowest and highest possible value. The list reported by the scanner can be displayed using the "\-\-help \-d epson" parameters to scanimage. The .I \-\-threshold switch selects the minimum brightness to get a white point. The .I \-\-mirror option controls the way the image is scanned. By reading the image data from right to left the image is mirrored. Valid options are "yes" and "no". The default is "no". The .I \-\-auto\-area\-segmentation switch activates the automatic area segmentation for monochrome scans. The scanner will try to determine which areas are text and which contain images. The image areas will be halftoned, and the text will be improved. Valid options are "yes" and "no". The default is "yes". The .I \-\-red\-gamma\-table parameter can be used to download a user defined gamma table for the red channel. The valid options are the same as for \-\-gamma\-table. The .I \-\-green\-gamma\-table parameter can be used to download a user defined gamma table for the green channel. The valid options are the same as for \-\-gamma\-table. The .I \-\-blue\-gamma\-table parameter can be used to download a user defined gamma table for the blue channel. The valid options are the same as for \-\-gamma\-table. The .I --wait-for-button parameter can be used to wait until the button on the scanner is pressed to actually start the scan process. The color correction coefficients .I \-\-cct\-1 \-\-cct\-2 \-\-cct\-3 ... \-\-cct\-9 will install color correction coefficients for the user defined color correction. Values are specified as integers in the range \-127..127. The .I \-\-preview option requests a preview scan. The frontend software automatically selects a low resolution. Valid options are "yes" and "no". The default is "no". The geometry options .I \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters. The .I \-\-source option selects the scan source. Valid options depend on the installed options. The default is "Flatbed". The .I \-\-auto\-eject option will eject a page after scanning from the document feeder. The .I \-\-film\-type option will select the film type for scans with the transparency unit. This option is only activated if the TPU is selected as scan source. Valid options are "Negative Film" and "Positive Film". The .I \-\-focus\-position option selects the focus position for all scans. Valid options are "Focus 2.5mm above glass" and "Focus on glass". The focus on the 2.5mm point above the glass is necessary for scans with the transparency unit, so that the scanner can focus on the film if one of the film holders is used. This option is only functional for selected scanners, all other scanners will ignore this option. The .I \-\-bay option selects which bay to scan The .I \-\-eject option ejects the sheet in the ADF. The .I \-\-adf-mode option select the ADF mode (simplex/duplex). .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/epson2.conf specifies the device(s) that the backend will use. Possible connection types are: .TP .I SCSI This is the default, and if nothing else is specified the backend software will open a given path as SCSI device. More information about valid syntax for SCSI devices can be found in sane\-scsi(5). .br Usually SCSI scanners are configured with a line "scsi EPSON" in this file. In some cases it may be necessary to only use the string "scsi" (e.g. for the GT-6500). .TP .I PIO \- Parallel Interface The parallel interface can be configured in two ways: An integer value starting at the beginning of a line will be interpreted as the IO address of the parallel port. To make it clearer that a configured IO address is a parallel port the port address can be preceded by the string "PIO". The PIO connection does not use a special device file in the /dev directory. The IO address can be specified in hex mode (prefixed with "0x"). .TP .I USB For USB scanners not automatically detect, their VENDOR and PRODUCT ID can be specified manually in the config file. More information about valid syntax for USB devices can be found in sane\-usb(5). .TP .I Network Network scanners can be auto-discovered if .I autodiscovery is specified after .I net keyword. An IP address to connect to can also be used. .SH FILES .TP .I @LIBDIR@/libsane\-epson2.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-epson2.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_EPSON2 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .TP .B SANE_DEBUG_EPSON2_SCSI If the library was compiled with debug support enabled, this environment variable controls the SCSI related debug level for this backend. Only a value of 2 is supported. .TP .B SANE_DEBUG_EPSON2_NET If the library was compiled with debug support enabled, this environment variable controls the network related debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .TP .B SANE_EPSON2_CMD_LVL This allows one to override the function or command level that the backend uses to communicate with the scanner. The function level a scanner supports is determined during the initialization of the device. If the backend does not recognize the function level reported by the scanner it will default to function level B3. Valid function levels are A1, A2, B1, B2, B3, B4, B5, B6, B7, B8, D1 and F5. Use this feature only if you know what you are doing! .SH "SEE ALSO" sane\-scsi(5), sane\-usb(5), scanimage(1), xscanimage(1), xsane(1) .SH BUGS None :-) At least none are currently known. .SH UNSUPPORTED DEVICES The backend may be used with Epson scanners that are not yet listed under the list of supported devices. A scanner that is not recognized may default to the function level B3, which means that not all functions that the scanner may be capable of are accessible. If the scanner is not even recognized as an Epson scanner this is probably because the device name reported by the scanner is not in the correct format. Please send this information to the backend maintainer (email address is in the AUTHOR section of this man page or in the AUTHORS file of the SANE distribution). .SH AUTHOR The package is written by Alessandro Zummo and is based on previous work done by Karl Hienz Kremer in the epson package as well as based on work by Christian Bucher and Kazuhiro Sasayama sane-backends-1.0.27/doc/scanimage.man0000664000175000017500000003154312775312262014430 00000000000000.TH scanimage 1 "10 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX scanimage .SH NAME scanimage \- scan an image .SH SYNOPSIS .B scanimage .RB [ \-d | \-\-device\-name .IR dev ] .RB [ \-\-format .IR format ] .RB [ \-i | \-\-icc\-profile .IR profile ] .RB [ \-L | \-\-list\-devices ] .RB [ \-f | \-\-formatted\-device\-list .IR format ] .RB [ \-b | \-\-batch .RI [= format ]] .RB [ \-\-batch\-start .IR start ] .RB [ \-\-batch\-count .IR count ] .RB [ \-\-batch\-increment .IR increment ] .RB [ \-\-batch\-double ] .RB [ \-\-accept\-md5\-only ] .RB [ \-p | \-\-progress ] .RB [ \-n | \-\-dont\-scan ] .RB [ \-T | \-\-test ] .RB [ \-A | \-\-all-options ] .RB [ \-h | \-\-help ] .RB [ \-v | \-\-verbose ] .RB [ \-B | \-\-buffer-size .RI [= size ]] .RB [ \-V | \-\-version ] .RI [ device\-specific\-options ] .SH DESCRIPTION .B scanimage is a command-line interface to control image acquisition devices such as flatbed scanners or cameras. The device is controlled via command-line options. After command-line processing, .B scanimage normally proceeds to acquire an image. The image data is written to standard output in one of the PNM (portable aNyMaP) formats (PBM for black-and-white images, PGM for grayscale images, and PPM for color images), TIFF format (black-and-white, grayscale or color), PNG format, or JPEG format. .B scanimage accesses image acquisition devices through the .B SANE (Scanner Access Now Easy) interface and can thus support any device for which there exists a .B SANE backend (try .B apropos .I sane\- to get a list of available backends). .SH EXAMPLES To get a list of devices: scanimage \-L To scan with default settings to the file image.pnm: scanimage >image.pnm To scan 100x100 mm to the file image.tiff (\-x and \-y may not be available with all devices): scanimage \-x 100 \-y 100 \-\-format=tiff >image.tiff To print all available options: scanimage \-h .SH OPTIONS Parameters are separated by a blank from single-character options (e.g. \-d epson) and by a "=" from multi-character options (e.g. \-\-device\-name=epson). .PP The .B \-d or .B \-\-device\-name options must be followed by a .B SANE device-name like .RI ` epson:/dev/sg0 ' or .RI ` hp:/dev/usbscanner0 '. A (partial) list of available devices can be obtained with the .B \-\-list\-devices option (see below). If no device-name is specified explicitly, .B scanimage reads a device-name from the environment variable .BR SANE_DEFAULT_DEVICE . If this variable is not set, .B scanimage will attempt to open the first available device. .PP The .B \-\-format .I format option selects how image data is written to standard output. .I format can be .BR pnm , .BR tiff , .BR png , or .BR jpeg . If .B \-\-format is not used, PNM is written. .PP The .B \-i or .B \-\-icc\-profile option is used to include an ICC profile into a TIFF file. .PP The .B \-L or .B \-\-list\-devices option requests a (partial) list of devices that are available. The list is not complete since some devices may be available, but are not listed in any of the configuration files (which are typically stored in directory .IR @CONFIGDIR@ ). This is particularly the case when accessing scanners through the network. If a device is not listed in a configuration file, the only way to access it is by its full device name. You may need to consult your system administrator to find out the names of such devices. .PP The .B \-f or .B \-\-formatted\-device\-list option works similar to .BR \-\-list\-devices , but requires a format string. .B scanimage replaces the placeholders .B %d %v %m %t %i %n with the device name, vendor name, model name, scanner type, an index number and newline respectively. The command .PP .RS .B scanimage \-f .I \*(lq scanner number %i device %d is a %t, model %m, produced by %v \*(rq .PP .RE will produce something like: .PP .RS scanner number 0 device sharp:/dev/sg1 is a flatbed scanner, model JX250 SCSI, produced by SHARP .RE .PP The .B \-\-batch* options provide the features for scanning documents using document feeders. .BR \-\-batch .RI [ format ] is used to specify the format of the filename that each page will be written to. Each page is written out to a single file. If .I format is not specified, the default of out%d.pnm (or out%d.tif for \-\-format tiff, out%d.png for \-\-format png or out%d.jpg for \-\- format jpeg) will be used. .I format is given as a printf style string with one integer parameter. .B \-\-batch\-start .I start selects the page number to start naming files with. If this option is not given, the counter will start at 1. .B \-\-batch\-count .I count specifies the number of pages to attempt to scan. If not given, scanimage will continue scanning until the scanner returns a state other than OK. Not all scanners with document feeders signal when the ADF is empty, use this command to work around them. With .B \-\-batch\-increment .I increment you can change the amount that the number in the filename is incremented by. Generally this is used when you are scanning double-sided documents on a single-sided document feeder. A specific command is provided to aid this: .B \-\-batch\-double will automatically set the increment to 2. .B \-\-batch\-prompt will ask for pressing RETURN before scanning a page. This can be used for scanning multiple pages without an automatic document feeder. .PP The .B \-\-accept\-md5\-only option only accepts user authorization requests that support MD5 security. The .B SANE network daemon .RB ( saned ) is capable of doing such requests. See .BR saned (8). .PP The .B \-p or .B \-\-progress option requests that .B scanimage prints a progress counter. It shows how much image data of the current image has already been received by .B scanimage (in percent). .PP The .B \-n or .B \-\-dont\-scan option requests that .B scanimage only sets the options provided by the user but doesn't actually perform a scan. This option can be used to e.g. turn off the scanner's lamp (if supported by the backend). .PP The .B \-T or .B \-\-test option requests that .B scanimage performs a few simple sanity tests to make sure the backend works as defined by the .B SANE API (in particular the .B sane_read function is exercised by this test). .PP The .B \-A or .B \-\-all-options option requests that .B scanimage lists all available options exposed the backend, including button options. The information is printed on standard output and no scan will be done. .PP The .B \-h or .B \-\-help options request help information. The information is printed on standard output and in this case, no attempt will be made to acquire an image. .PP The .B \-v or .B \-\-verbose options increase the verbosity of the operation of .B scanimage. The option may be specified repeatedly, each time increasing the verbosity level. .PP The .B \-B option without argument changes the input buffer size from the default 32KB to 1MB. For finer grained control, use .B \-\-buffer-size= followed by the number of KB. .PP The .B \-V or .B \-\-version option requests that .B scanimage prints the program and package name, the version number of the .B SANE distribution that it came with and the version of the backend that it loads. Usually that's the dll backend. If more information about the version numbers of the backends are necessary, the .B DEBUG variable for the dll backend can be used. Example: SANE_DEBUG_DLL=3 scanimage \-L. .PP As you might imagine, much of the power of .B scanimage comes from the fact that it can control any .B SANE backend. Thus, the exact set of command-line options depends on the capabilities of the selected device. To see the options for a device named .IR dev , invoke .B scanimage via a command-line of the form: .PP .RS .B scanimage \-\-help \-\-device\-name .I dev .RE .PP The documentation for the device-specific options printed by .B \-\-help is best explained with a few examples: \-l 0..218mm [0] .br Top-left x position of scan area. .PP .RS The description above shows that option .B \-l expects an option value in the range from 0 to 218 mm. The value in square brackets indicates that the current option value is 0 mm. Most backends provide similar geometry options for top-left y position (\-t), width (\-x) and height of scan-area (\-y). .RE \-\-brightness \-100..100% [0] .br Controls the brightness of the acquired image. .PP .RS The description above shows that option .B \-\-brightness expects an option value in the range from \-100 to 100 percent. The value in square brackets indicates that the current option value is 0 percent. .RE \-\-default\-enhancements .br Set default values for enhancement controls. .PP .RS The description above shows that option .B \-\-default\-enhancements has no option value. It should be thought of as having an immediate effect at the point of the command-line at which it appears. For example, since this option resets the .B \-\-brightness option, the option-pair .B \-\-brightness 50 \-\-default\-enhancements would effectively be a no-op. .RE \-\-mode Lineart|Gray|Color [Gray] .br Selects the scan mode (e.g., lineart or color). .PP .RS The description above shows that option .B \-\-mode accepts an argument that must be one of the strings .BR Lineart , .BR Gray , or .BR Color . The value in the square bracket indicates that the option is currently set to .BR Gray . For convenience, it is legal to abbreviate the string values as long as they remain unique. Also, the case of the spelling doesn't matter. For example, option setting .B \-\-mode col is identical to .BR "\-\-mode Color" . .RE \-\-custom\-gamma[=(yes|no)] [inactive] .br Determines whether a builtin or a custom gamma-table .br should be used. .PP .RS The description above shows that option .B \-\-custom\-gamma expects either no option value, a "yes" string, or a "no" string. Specifying the option with no value is equivalent to specifying "yes". The value in square-brackets indicates that the option is not currently active. That is, attempting to set the option would result in an error message. The set of available options typically depends on the settings of other options. For example, the .B \-\-custom\-gamma table might be active only when a grayscale or color scan-mode has been requested. Note that the .B \-\-help option is processed only after all other options have been processed. This makes it possible to see the option settings for a particular mode by specifying the appropriate mode-options along with the .B \-\-help option. For example, the command-line: .PP .B scanimage \-\-help \-\-mode .I color .PP would print the option settings that are in effect when the color-mode is selected. .RE \-\-gamma\-table 0..255,... .br Gamma-correction table. In color mode this option .br equally affects the red, green, and blue channels .br simultaneously (i.e., it is an intensity gamma table). .PP .RS The description above shows that option .B \-\-gamma\-table expects zero or more values in the range 0 to 255. For example, a legal value for this option would be "3,4,5,6,7,8,9,10,11,12". Since it's cumbersome to specify long vectors in this form, the same can be expressed by the abbreviated form "[0]3-[9]12". What this means is that the first vector element is set to 3, the 9-th element is set to 12 and the values in between are interpolated linearly. Of course, it is possible to specify multiple such linear segments. For example, "[0]3-[2]3-[6]7,[7]10-[9]6" is equivalent to "3,3,3,4,5,6,7,10,8,6". The program .B gamma4scanimage can be used to generate such gamma tables (see .BR gamma4scanimage (1) for details). .RE .br \-\-filename [/tmp/input.ppm] .br The filename of the image to be loaded. .PP .RS The description above is an example of an option that takes an arbitrary string value (which happens to be a filename). Again, the value in brackets show that the option is current set to the filename .BR /tmp/input.ppm . .RE .SH ENVIRONMENT .TP .B SANE_DEFAULT_DEVICE The default device-name. .SH FILES .TP .I @CONFIGDIR@ This directory holds various configuration files. For details, please refer to the manual pages listed below. .TP .I ~/.sane/pass This file contains lines of the form .PP .RS user:password:resource .PP scanimage uses this information to answer user authorization requests automatically. The file must have 0600 permissions or stricter. You should use this file in conjunction with the \-\-accept\-md5\-only option to avoid server-side attacks. The resource may contain any character but is limited to 127 characters. .SH "SEE ALSO" .BR sane (7), .BR gamma4scanimage (1), .BR xscanimage (1), .BR xcam(1) , .BR xsane(1) , .BR scanadf (1), .BR sane\-dll (5), .BR sane\-net (5), .BR sane\-"backendname" (5) .SH AUTHOR David Mosberger, Andreas Beck, Gordon Matzigkeit, Caskey Dickson, and many others. For questions and comments contact the sane\-devel mailinglist (see http://www.sane\-project.org/mailing\-lists.html). .SH BUGS For vector options, the help output currently has no indication as to how many elements a vector-value should have. sane-backends-1.0.27/doc/niash/0000775000175000017500000000000013110600532013140 500000000000000sane-backends-1.0.27/doc/niash/niash.TODO0000664000175000017500000000406212112021330014645 00000000000000To do: ====== - implement coarse calibration to determine settings for analog-front-end All CCDs encountered so far seem to need about the same settings however. - Store analog calibration data somewhere. Use currently used values as default. - Suggestions by Marcin Cieslak: - clean up structures - clean up namespace - clean up source formatting ('indent --gnu' ?) - implement real calibration, using 12 bit data at 600 dpi instead of 8 bit data.at 150 dpi. -> is now at 600 dpi, not yet at 12 bit - design a mechanism to set the scan and calibration areas a) part of HWProps structure, or b) set by user at first scan - further investigate scanner registers a) study backtracking register more b) identify bits in bit-oriented registers. - add more error checking ('sanity checking') on parameters - figure out what the USB interrupts mean that sometimes occur. Done ==== - Get rid of mytypes.h / fix types Now an int is implicitly assumed to be 32 bit. - make backend comply with tstbackend -> all externs and publics removed when compiling towards sane - implement sane_cancel properly -> done by ullsig - implement timing mechanism for scanner lamp so scanning can only start if the lamp was already on for 30 seconds Possible implementation: On startup: if lamp is off, turn it on and start timer On scan: if lamp is off, turn it on and start timer. Wait for timer expiry. On exit: if scanner chip is niash00012 then turn off lamp, otherwise let the scanner turn it off automatically -> Implemented by Ullrich Sigwanz - try out parallel port scanning on HP3400/4300 -> parallel port support will be dropped, no people to test/develop it - investigate vertical resolution setting of hp3400/4300. -> experiment with the motor table, formula is already known to generate it -> 600 dpi is possible by doubling most values in the table -> 150 dpi can be done by using register 0x06 to skip every other line - Add separate gamma tables for R, G, B. This should be easy (look at how other backends do it) but is not really required yet. -> not required sane-backends-1.0.27/doc/mustek_usb/0000775000175000017500000000000013110600532014217 500000000000000sane-backends-1.0.27/doc/mustek_usb/mustek_usb.TODO0000664000175000017500000000044312112021330017002 000000000000002004-03-02 * Support more scanners - 1200 USB - 600 USB These are both CCD scanners. Several people tried to add support until now but I have never heard from the again ... * Remove/replace _word variables from usb_low * Check if low resolutions can be made faster. * Check fixmes. sane-backends-1.0.27/doc/mustek_usb/mustek_usb.CHANGES0000664000175000017500000003040312112021330017304 00000000000000CHANGES for the SANE Mustek USB backend 2004-03-02 * Release of version 1.0-18. 2004-03-02 * Added workaround for data0 toggle bug. I think this is a bug in the chipset. The chipset doesn't set the toggle to data0 when the endpoints are reset. As this is done whenever the device files/libusb is closed, this backend worked ony once. Now we count the number of URBs and just read/write some crap if the number is odd. 2003-09-21 * Release of version 1.0-17. 2003-09-21 * Fixed check for single quotation marks. 2003-02-22: * Release of version 1.0-16. 2003-02-22: * Iniatialize global variables explicitely. * Mention ma1509. 2002-11-20: * Man page updated concerning The BSDs. 2002-11-19: * Added desc file hint to the gt68xx backend. 2002-11-17: * Fixed minor issues in the man page. Removed beta status. Added links to other backends for Mustek scanners. 2002-07-17: * Release of version 1.0-15. 2002-07-17: * Added manufacturer comment in mustek_usb.desc. * Changed brightness to threshold. * Fixed some warnings. * Really check the status in usb_low_open. 2002-04-24: * Release of version 1.0-14. 2002-04-24: * Undef MIN and MAX if they are defined in mustek_usb_low.h to avoid warnings. 2002-04-23: * Free devlist in sane_exit. 2002-04-10: * Release of version 1.0-13. 2002-04-10: * sane_set_io_mode must return SANE_STAUS_GOOD if non_blocking is false. Check if scanning. * sane_get_select_fd: Check if scanning. * sane_control_option: Cleanup. Avoid segfaults. Catch unknown options. * sane_exit: set freed variable to 0. 2002-03-20: * Release of version 1.0-12. 2002-03-19: * Option 0 has an empty name now. * Group options have size 0 now. * Checked also for SANE_ACTION_SET_AUTO. * Removed buggy output in sane_control_option. * Added more debug output in sane_control_option. 2002-03-17: * Release of version 1.0-11. 2002-03-16: * mustek_usb.c: Fixed segfault when opening device again after closing. * mustek_usb.c: Fixed possible segfault when name="". * mustek_usb.c: Type for option 0 must be set to SANE_TYPE_INT explicitely. 2002-02-14: * Fixed some problems with wrong formats in DBG statements. 2002-02-09 * Fixed wrong output in usb_low_read_reg(). 2002-01-23: * Fixed undefined operation warnings. 2002-01-11 * Release of version 1.0-10. 2002-01-11 * mustek_usb_high.(c|h), mustek_usb_mid.(c|h): commented out unused CCD code. * mustek_usb_mid.h: Fixed OFFSET_TABLE_SIZE. * mustek_usb.c: Fixed bug concerning opening with empty name. * mustek_usb.c, mustek_usb_high.c: Make sure usb_low_exit is only called once per device. Fixed segfault. 2002-01-10 * mustek_usb.desc: Status is "beta" now. 2002-01-03 * Added link to plustek to manual page. 2001-12-08 * Release of version 1.0-9. 2001-12-08 * Added option max_block_size to limit amount of data acquired in one turn. 2001-12-07 * usb_low_read_rows: Retry until all the data is received. Set maximum size of data acquired in one turn. 2001-11-15 * Release of version 1.0-8. 2001-11-15 * Updated manual page concerning FreeBSD and kernel configuration. 2001-11-14 * Added 600 USB detection. No support at all yet. * Removed unneccessary calls to usb_low_open and usb_low_close. This fixed the FreeBSD problems. * Updated all SANE comments ("1200UB and similar"). 2001-11-11 * Added function usb_high_scan_adjust_mono_600_exposure. 2001-10-14 * Added start values for the 1200USB. * Removed load_private_profile (now in usb_high_scan_init). 2001-10-07 * Release of version 1.0-7. 2001-10-07 * usb_low: fixed output if scanner has wrong vendor/product id. * usb_high: Added the detection of 300&600 sensor again. Mustek seems to have used both sensors in the Mustek 1200 UB, so we must distinguish them. * Disabled 1200 USB for release. 2001-09-30 * 1200CU_Plus has Canon600 sensor (fixed). 2001-09-15 * Added functions for sensor nec600 (1200 USB) in mustek_usb_mid. * Changed init_asic and exposure times for 1200 USB. 2001-09-13 * Release of version 1.0-6. 2001-09-13 * Added check for negative width and height. * Changed status to NEW (internaly: beta). * Added check for too high gamma values (xscanimage is buggy). * Return SANE_STATUS_CANCELLED in sane_read if scan was cancelled. * Updated manual page. 2001-09-12 * Added support for fitting lines (recalculation of resolution) for color mode * Added support for fitting lines (recalculation of resolution) for lineart mode * Better debug output for unmatched dpi in mustek_usb_mid. * Changed default mode to "gray". * Added gamma table support (software) for color + gray, stayed with brightness for lineart. * Added output of total bytes scanned (+ check). * Decreased maximum width and height to avoid freezing the scanner. * Added check for unknown options in mustek_usb. * Code cleanup in mustek_usb, mustek_usb_high. * Added SANE_I18N macro. 2001-09-11 * Added support for idependent x and y resolution. * Changed option resolution to constraint_range. * Increased motor speed when returning back home for 600 dpi motor. * Increased resolution to 1200 dpi for 1200CU, 1200CU Plus and 1200 UB. * Increased resolution to 600 dpi for 600CU. * Added support for fitting lines (recalculation of resolution) for gray mode 2001-09-10 * Release of version 1.0-5. 2001-09-10 * mustek_usb_mid: Added functions for 300 dpi sensor. * mustek_usb_mid: Fixed 200 dpi mode. * mustek_usb_mid: added general sensor functions. 2001-09-09 * mustek_usb_mid: Added functions for 600 dpi motor. * mustek_usb_mid, usb_high: Added functions for selecting the motor functions. 2001-09-06 * Release of version 1.0-4. 2001-09-06 * usb_high: use only lower case for functions. * mustek_usb: use only lower case for variables and functions. * mustek_usb: remove unnecessary functions. 2001-09-01 * usb_high: removed unnecessary macros and types. * usb_high: use only lower case for variables and upper/lower mixed for types. 2001-08-30 * usb_low, usb_mid: use only lower case for functions. Fixed some spellings and debug messages. 2001-08-29 * usb_low: use only lower case for variables and upper/lower mixed for types. remove unnecessary types. 2001-08-28 * Also include sane-usb man page in tar.gz file to avoid make errors. * Only use arrays of SANE_Byte for data transfer to scanner in usb_low. 2001-08-26 * Check the result of all mallocs. * Sensor is now only in mustek_usb_low. * Removed gamma functions from code (weren't used anyway). * Contrast is only active for color and gray scans. 2001-08-26 * Release of version 1.0-3. 2001-08-26 * Set up motor600 functions using the motor1200 with double dpi. This doesn't work for 200 dpi, however. Removed 200 dpi from list until I understand what's going on. * Updated manual page * Updated .conf file 2001-08-25 * Used proper SANE_Status return values in mustek_usb_mid for all functions. * Used proper SANE_Status return values in mustek_usb for all functions. * Added Trust scanner to mustek_usb.desc. * Removed Mono4 and Mono1 functions. 2001-08-23 * Removed ifdefs in mustek_usb_mid. 2001-08-22 * Removed GREENGRAY macro and included code (didn't work anyway). * Removed 36 and 48 bit calibration. * Added RIE (return if error) macro. 2001-08-19 * Removed io functions in mustek_usb_low. * Used proper SANE_Status return values in mustek_usb_low for all functions. * Fixed lots of debug output in mustek_usb_low. * Formatting update in mustek_usb_low. * Used proper SANE_Status return values in mustek_usb_high for all functions. * Fixed lots of debug output in mustek_usb_high. * removed unnecessary modes in mustek_usb_high. 2001-08-18 * Added manual selection of scanner type in mustek_usb.conf * It's checked now if the scanner was autodetected or manually selected * Set maximum resolution to 300 for 600 CU. * Changed nUSBPipe to fd, which is more appropriate. * Removed #ifdef 0 code from mustek_usb_high * Used proper SANE_Status return values in mustek_usb_low for - io_Open - Open - io_WriteReg - io_ReadReg 2001-08-08 * Fixed some format issues * Better debug output * Added support for CANON300 sensor (for 600 CU) 2001-08-07 * Added support for sanei_usb v2. * Check vendor/product directly after sane_open. 2001-08-06 * Added scan buffer. It's used if the buffer suplied with sane_read is smaller than one scan line. 2001-08-06 * Released mustek_usb-backend 1.0-2. 2001-08-05 * Support more than one scanner in the .conf file * Use sanei_usb functions * Allow usb vendor device in .conf * Only use usb statements in .conf for all three scanners, comment out device files * Now the correct names are returned if autodetection works * Manual page updates 2001-08-05 * Released mustek_usb-backend 1.0-1. 2001-08-04 * mustek_usb_low: - fixed compilation warnings - fixed compilation problems - fixed C++ to C transition issues (e.g. "initializer element is not computable at load time") - fixed debug output - adjusted some names - removed MEMFREE, MALLOC, LP* * mustek_usb_mid: - fixed compilation warnings - changed printf to DBG - fixed debug output - reformatted * mustek_usb_high: - fixed some DBG statements - fixed compilation warnings - moved global variable to Mustek_Usb_Device - reformatted * mustek_usb: - fixed compilation warnings --> compile runs successfully for the first time since restructuring - removed DWORDS etc. - moved CScanner into Mustek_Usb_device - removed global variables * mustek_usb.conf: updated * removed references to "WORD" * ifdefed unused functions * fixed bug concerning wrong x-resolution after the first scan for low resolutions (e.g. preview). This also fixed the problems with 1200 CU. --> Scanning works with 1200 UB, 1200 CU and probably 1200 CU Plus. * added manual page * updated mustek_usb.desc 2001-08-02 * mustek_usb_high: - fixed lots of compilation problems. - removed LP..., huge*, far* - removed MEMFREE, MEMALLOC - added several "return SANE_TRUE" to SANE_Bool functions - changed printf to DBG - changed Sleep to usleep 2001-07-22 * mustek_usb_low: Only one data structure: ma1017. * mustek_usb_mid: - removed // - remove SANE disclaimers - use SANE types - changed to use new usb_low style - made everything static - renamed functions to usb_mid_* * mustek_usb_high: - removed remaining // - reformatted - used SANE types - made everything static - renamed * Fixed quite some compilation errors 2001-07-08 * mustek_usb_low: - renamed functions to usb_low/usb_low_io - made all functions static - used DBG instead of printf - moved all status information from global to struct ma1017 - rename constructor/destructor - included io constructor/destructor in usb_low 2001-07-01 * Added more debug output in attach () when device file couldn't be opened. * Added some tests for NULL pointers in attach () * fixed segfault in sane_exit () * indented all files * fixed mustek_usb_high: - changed // to /* */ - reformatted * fixed mustek_usb_low: - changed // to /* */ - reformatted - removed most non-standard types 2001-05-26 * Started working based on the Mustek source code from their FTP server. * Renamed backend to mustek_usb. All files start with this name. * Created: - mustek_usb(.c .h) from 1200ub(.c .h) - mustek_usb_low from ma1017 and ma1017io - mustek_usb_mid from ada* - mustek_usb_high from scanner and calibrator * Used "../include/sane" in #include statements * Used /dev/usbscanner in mustek_usb.conf * Fixed mustek_usb.desc * Fixed mustek_usb.*: - use correct names - no leading "_" - use only C-style comments - moved defines to .h, - reformatted using GNU style - use /dev/usbscanner as default - Fixed DBG output - don't use printf - added more DBG output - added "static" to internal functions - commented out all references to c_scanner - removed references to WORD and other non-standard types - moved read_rows from global to Mustek_Usb_Scanner --> mustek_usb.* compilessane-backends-1.0.27/doc/sane-teco3.man0000664000175000017500000000772212112021330014416 00000000000000.TH sane\-teco3 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-teco3 .SH NAME sane\-teco3 \- SANE backend for TECO / RELISYS scanners .SH DESCRIPTION The .B sane\-teco3 library implements a SANE (Scanner Access Now Easy) backend that provides access to some TECO SCSI flatbed scanners. This backend should be considered .B alpha-quality software! TECO scanners are sold under various brands like RELYSIS, PIOTECH, TRUST. This backend may or may not support yours. .PP The scanners that should work with this backend are: .PP .RS .ft CR .nf Vendor Model TECO model status --------------------------- ---------- ---------- Relisys Scorpio VM3552 tested Plustek OpticPro 2400SP VM3552 untested PIOTECH Splendeur 3024 VM3552 tested Trust Imagery 2400 SP VM3552 tested Trust Imagery 4800 SP+ VM3552 tested Trust Imagery 9600 SP VM3552 untested .fi .ft R .RE The TECO VM number can usually be found at the back of the scanner. It is also part of the FCC ID. The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage or xsane. .br If you have any success with a scanner not listed here, or if you have any strange behavior, please report to the backend maintainer or to the SANE mailing list. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d teco3 .RE .TP .B Scan Mode .TP .B \-\-mode selects the basic mode of operation of the scanner valid choices are .I Black & White , .I Grayscale and .I Color The Black & White mode is black and white only (1 bit). Grayscale will produce 256 levels of gray (8 bits). Color will produce a 24 bits color image. .TP .B \-\-resolution selects the resolution for a scan. The scanner can do all resolutions between 1 and 1200, in increments of 1. .TP .B Geometry options .TP .B \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters by default. .TP .B Enhancement options .TP .B \-\-custom\-gamma (color mode only) allows the user to specify a gamma table (see the next 3 parameters). .TP .B \-\-red\-gamma\-table (color mode only) can be used to download a user defined gamma table for the red channel. The table must be 1024 bytes long. .TP .B \-\-green\-gamma\-table (color mode only) can be used to download a user defined gamma table for the green channel. The table must be 1024 bytes long. .TP .B \-\-blue\-gamma\-table (color mode only) can be used to download a user defined gamma table for the blue channel. The table must be 1024 bytes long. .TP .B \-\-preview requests a preview scan. The resolution used for that scan is 22 dpi and the scan area is the maximum allowed. The scan mode is user selected. The default is "no". .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/teco3.conf supports only one information: the device name to use (eg /dev/scanner). .SH FILES .TP .I @LIBDIR@/libsane\-teco3.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-teco3.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_TECO3 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH LIMITATIONS The windows TWAIN driver has many more options than this SANE backend. However they are only software adjustments. This backend only implements what the scanner can support. .SH BUGS Not much. .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1), sane(7) .SH AUTHOR .TP The package is actively maintained by Frank Zago. .I http://www.zago.net/sane/#teco3 sane-backends-1.0.27/doc/sane-sceptre.man0000664000175000017500000001006512112021330015040 00000000000000.TH sane\-sceptre 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-sceptre .SH NAME sane\-sceptre \- SANE backend for SCEPTRE scanners .SH DESCRIPTION The .B sane\-sceptre library implements a SANE (Scanner Access Now Easy) backend that provides access to Sceptre flatbed scanners. This backend should be considered .B beta-quality software! Please report any strange behavior to the maintainer of the backend or to the SANE mailing list. .PP At present, only one scanner is known to work with this backend: .PP .RS .ft CR .nf Model Connection Type --------------------------- ------------------- Sceptre VividScan S1200 SCSI .fi .ft R .RE The make of this scanner is KINPO, so other scanners from that manufacturer may also work (eg. the S600). .SH OPTIONS The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage or xsane. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d sceptre .RE .TP .B Scan Mode .TP .B \-\-mode selects the basic mode of operation of the scanner valid choices are .I Lineart, Halftone, Gray and Color. The Lineart and Halftone mode are black and white only (1 bit). Gray will produce 256 levels of gray (8 bits). Color will produce a 24 bits color image. The scanner supports 30 bits internally but it only exports 24. .TP .B \-\-resolution selects the resolution for a scan. The scanner can do several resolutions between 50 and 1200. .TP .B \-\-halftone\-pattern selects the pattern mode that is used in Halftone mode. Valid options are 1, 2, 3 and 4. .TP .B \-\-gamma\-correction controls the scanner internal gamma correction. Valid options are "Default", "User defined", "High density printing" "Low density printing" and "High contrast printing". .TP .B \-\-custom\-gamma (color mode only) allows the user to specify a gamma table (see the next 3 parameters). .TP .B \-\-red\-gamma\-table (color mode only) can be used to download a user defined gamma table for the red channel. The table must be 256 bytes long. .TP .B \-\-green\-gamma\-table (color mode only) can be used to download a user defined gamma table for the green channel. The table must be 256 bytes long. .TP .B \-\-blue\-gamma\-table (color mode only) can be used to download a user defined gamma table for the blue channel. The table must be 256 bytes long. .TP .B \-\-threshold sets the threshold for black and white pixels in lineart mode. Possible values are from 0 (darker) to 255 (lighter). .TP .B \-\-preview requests a preview scan. The resolution used for that scan is 30 dpi and the scan area is the maximum allowed. The scan mode is user selected. The default is "no". .TP .B The geometry options .TP .B \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters by default. .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/sceptre.conf supports only one information: the device name to use (eg /dev/scanner). .SH FILES .TP .I @LIBDIR@/libsane\-sceptre.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-sceptre.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_SCEPTRE If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH LIMITATIONS .TP .B Resolutions The windows TWAIN driver can be set to any resolution between 50 to 1200 (excluding software interpolation). This backend cannot. Only a handful of resolution are available, although they should be numerous enough. .SH BUGS None known. .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1), sane(7) .SH AUTHOR .TP The package is actively maintained by Frank Zago. .I http://www.zago.net/sane/#sceptre sane-backends-1.0.27/doc/sane-dc210.man0000664000175000017500000000671212112021330014210 00000000000000.TH sane\-dc210 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-dc210 .SH NAME sane\-dc210 \- SANE backend for Kodak DC210 Digital Camera .SH DESCRIPTION The .B sane\-dc210 library implements a SANE (Scanner Access Now Easy) backend that provides access to the Kodak DC210 camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! .SH "DEVICE NAMES" The current version of the backend only allows one camera to be connected. The device name is always "0". .SH CONFIGURATION The contents of the .I dc210.conf specify the serial port and baud rate to use. The baud rate specifies the maximum rate to use while downloading pictures. (The camera is always initialized using 9600 baud, then switches to the higher rate). On my 90MHz Pentium, I usually have no problems downloading at 115200 baud as long as the system is not excessively busy and the "interrupt-unmask flag" is set in the IDE driver (hdparm \-u1). Supported baud rates are: 9600, 19200, 38400, 57600, and 115200. .PP The dumpinquiry line causes some information about the camera to be printed. .PP cmdrespause specifies how many usec (1,000,000ths of a) between writing the command and reading the result should be used. 125000 seems to be the lowest I could go reliably. .PP breakpause is the time in 1,000,000ths of a usec between sending the "back to default" break sending commands. .PP Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS port=/dev/ttyS0 .br # this is a comment .br baud=115200 .br dumpinquiry .br cmdrespause=125000 .br breakpause=1000000 .RE .PP .SH FILES .TP .I @CONFIGDIR@/dc210.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-dc210.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-dc210.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_DC210 If the library was compiled with debugging support enabled, this environment variable controls the debug level for this backend. A value of 128 requests maximally copious debug output; smaller levels reduce verbosity. .SH "SEE ALSO" sane(7) .SH AUTHOR Brian J. Murrell .PP This backend is based somewhat on the dc25 backend included in this package by Peter Fales. .PP The manpage was copied from the dc25 backend and somewhat edited by Henning Meier-Geinitz. .SH BUGS Known bugs/limitations are: ? .PP More general comments, suggestions, and inquiries about frontends or SANE should go to the SANE Developers mailing list (see http://www.sane\-project.org/mailing\-lists.html for details). You must be subscribed to the list, otherwise your mail won't be sent to the subscribers. sane-backends-1.0.27/doc/gt68xx/0000775000175000017500000000000013110600532013206 500000000000000sane-backends-1.0.27/doc/gt68xx/gt68xx.TODO0000664000175000017500000000762112112021330014765 00000000000000gt68xx.TODO -*-text-*- General: -------- - some sort of fixed lookup-table may be necessary to compensate for the non-linear CCD/CIS behaviour. A gamma value is not good enough. Or maybe line calibration can be used for that? - Some Plustek scanners are advertised with e.g. 1200x2400 but the maximum vertical resolution seems to be limited to the horizontal one. Check if that's really the case. - Keep a log of all gain/offset combinations already tested and break if one is repeated to avoid endless loops. - Print commands that are send to the scanner in clear text. - Try to implement non-blocking USB bulk reads, check libusb CVS. CCD: ---- Mustek BearPaw 2400 TA Plus: - some lines at the beginning of each image have wrong colors (linedistance?) This seems to happen with other scanners, too. - 600 dpi no backtrack, 1200, 2400 dpi backtrack (gray), check with windows for color - 600 dpi 12 bit seems to work in pixel mode only (but long lines are too big!) Mustek BearPaw 1200 TA: - similar color problem as 2400 TA Plus, doesn't always happen? Mustek BearPaw 2448 TA Plus: - all modes are slow (massive backtracking). If connected to a USB2 port, the backtracking ich much less despite this scanner can't do USB2. Strange. - Sometimes there is a USB protocol error when cancelling the scan? - top borders move with resolution (happened in the early days with 2400 TA!) - gray scans have different brightness - scan motor is bumpy and freezes sometimes, looks like accelaration is too big (firmware problem?) - vertical stripes - TA settings are wrong - no backtrack >= 600 dpi (also gray!) - don't move before and after scan - check jpeg output, maybe this can be used for faster scans Plustek 1248U: - Linedistance seems to have problems in the first few and the last lines. - Gain and offset values are quite high. Optimum values are not reached. Problem with coarse calib? Better algorithm needed. - Images in color mode sometimes look too redish (result of above problem). - quite slow when full width is selected. Lots of backtracking. - Check if pixel mode is possible. - Check again 600x1200 dpi. Plustek U16B: - 600 dpi 16 bit is limited to about half the size of the scan area because only pixel mode works and 16k is the maximum buffer size. - After scanning, a run of sane-find-scanner leads to a protocol error and scanning does no longer work. Genius ColorPage Vivid 1200XE - 16 bit per color is advertized but this mode doesn't seem to work (only 12 bit)? - 1200x1200 and 1200x2400 dpi doesn't seem to work despite being advertized - Y-positioning varies slightly with resolution (some mm) CIS: ---- - It may be necessary to do an additional exposure calibration before the offset/gain calibration to compensate for different intensities of the colored leds. Especially for the Mustek 2400 CU Plus. - Changing exposure doesn't seem to have any effect during calibration sometimes while it has an effect on the final image? Mustek BearPaw 1200 CU - ok Mustek BearPaw 1200 CU Plus (0x021b) - ok, but similar exposure problems as 2400 CU Plus Mustek BearPaw 2400 CU Plus - ok, but exposure setting may need to be done automatically if the intensity of the colors varies for different scanners. - calibration/exposure has sometimes sharp jumps in intensity. Reason is unknown. Mustek ScanExpress A3 USB - still slight vert. stripes - why is line distance setup necessary? - line distance varies with resolution (0,5,5 at 300 dpi, 0, 6, 7 with 150 dpi) - exposure doesn't seem to have any effect Mustek ScanExpress 1248 UB ok Plustek OpticSlim 2400 - only upto 1200 dpi vertical works - only 8 and 12 bit work, 16 doesn't (check Windows) - exposure is extremely high and seems to have similar problems as with other CIS scanners (reaches limit also) Mustek ScanExpress 2400 USB - make it work (nobody seems to have this device) Visioneer OneTouch 7300 - 16 bit doesn't seem to work despite beeing advertized sane-backends-1.0.27/doc/gt68xx/gt68xx.CHANGES0000664000175000017500000006554512617742237015333 00000000000000gt68xx.CHANGES -*-text-*- V 1.0.84 (2007-08-19) * Added Artec Ultima 2000 e+, Nortek Myscan 1200, NeatReceipts Scanalizer Professional, Genius Colorpage Slim-1200. * Name and email address changes. V 1.0.83 (2007-01-28) * Added .conf entry for Plustek OpticPro S12 and S24. Updated .desc file. V 1.0.82 (2006-10-03) * Added support for Genius Colorpage SF600. V 1.0.81 (2006-05-21) * Added support for Plustek OpticPro S24 (some models). Added .conf entry for Plustek OpticPro S12. V 1.0.80 (2006-01-02) * Added Plustek OpticPro S(T)12 (product id 0x040b). Mostly untested. * Print warmup message 5 seconds after starting the warm-up. V 1.0.79 (2005-12-09) sane-backends 1.0.17 * Silenced warning when scan is cancelled. * Silenced often non-fatal check_result error messages. * Reduced timeout for cancelling a scan. Some scanners freeze for 30 seconds otherwise. Repeat is_moving test even if an error was received. * Run fix_descriptors before cancelling the scan. Without that, some gt6816 scanners are not detected anymore after closing the device. * Fixed wait_lamp_stable. Wait for a maximum time of 60 seconds. Print warming up message after 5 seconds. Print how long warming up took. * For Mustek ScanExpress A3 USB, use more intelligent warm-up mechanism. The brightness for this scanner first decreases and then increases again. With the previous logic the scanner always warmed up for at least 10 seconds even if it wasn't necessary. * Warm up lamp also when changing from flatbed to transparency. Without this the lamp may be too dark directly after changing the source. * Decreased scan width of Plustek OpticPro 1248U. This fixes some strange color artifacts and results in less backtracking in some modes. V 1.0.78 (2005-10-16) * Minor modifications to sheet-fed scanner support. V 1.0.77 (2005-09-29) * Added support for Plustek OpticSlim M12 (untested). Based on patch from Gerhard Jaeger . * Fixed gt68xx homepage links in man page. Changed minimum version of libusb to 0.1.8. V 1.0.76 (2005-09-18) * Fixed segfault that may happen with Mustek ScanExpress A3 USB. V 1.0.75 (2005-09-01) * Genius ColorPage Vivid 1200 X is reported to work. * Genius ColorPage Vivid 4 XE seems to be the same as 4 X, it just doesn't have buttons. * Cleanup of .desc file. * Fixed gain setting. * Mustek ScanExpress A3 USB 600 dpi color scanning works now. V 1.0.74 (2005-08-20) * Increased number limit of scanners that can work with this backend to 50. * Added support for Genius ColorPage Vivid 1200 X (untested). V 1.0.73 (2005-08-19) * Enabled GT68XX_FLAG_NO_STOP for Mustek BearPaw 2400 CU Plus. Some of these scanners don't seem to like that command. V 1.0.72 (2005-08-18) * Finally fixed the problem concerning scanning on *BSD. Scanning only worked once. After that, the scanner wasn't even detected anymore beacuse the config descriptor returned by the device was corrupted. This is a hardware bug. When filling the internal memory of the scanner completely, the config descriptor is overwritten. The work-around is to ask the scanner for the device descriptor before closing the device. This rewrites also the config descriptor to the memory of the scanner. * Fixed compilation warnings. V 1.0.71 (2005-07-10) Included in sane-backends 1.0.16 * Changed resolution from 75 to 100 dpi and changed 16 bit/color to 12 based on a user report for the Visioneer OneTouch 7300. Updated .desc. * Moved check for stable lamp to its own function. * Mustek ScanExpress A3 USB: Use CIS calibration. Use lamp warmup. * Fixed CCD on GT6801 scanning (color scanning was broken due to a change in motormode_2. V 1.0.70 (2005-05-29) * Start exposure with the settings from the scanner entry. * CIS Calibration and exposure uses a broader spectrum now. * Expsoure limit is increased to 50 loops. * Genius Vivid 4x is reported to work so the UNTESTED label is removed now. * Visioneer 7300 is reported to work so the UNTESTED label is removed now. * Genius ColorPage Vivid 1200XE: Removed UNTESTED label. Fixed resolutions. Adjusted margins. Fixed color order. Fixed linedistance. Adjusted AFE. * Mustek ScanExpress 1248 UB: Fixed margins. Adjusted AFE. Adjusted exposure. Adjusted gamma. Changed status to "complete". * Mustek BearPaw 2400 CU Plus: Adsusted exposure and AFE parameters. Hopefully stripes and similar trouble are gone now. * Mustek BearPaw 1200 CU: Increased exposure to avoid vertical lines. * Updated manual page. V 1.0.69 (2005-05-20) * Mustek BearPaw 1200 CU Plus model 0x21b works now. Fixed firmware and offset settings. Calibration is not completely ok yet, however. * Code cleanup for setup_scan (only one function for all chipsets). * Simplified line mode/pixel mode setting * Updated TODO. * Mustek BearPaw 2448 TA Plus is now only "basic". Too much trouble for "good". * Removed option "fast preview". By default for preview mode 8 bits/pixel are used. * Fixed indentation. * Full scan really scans from y=0 on gt6816 scanners now. V 1.0.68 (2005-05-07) * GT68XX_FLAG_NO_STOP is needed for BearPaw 2448 TA Plus. * Plustek OpticSlim 2400: Fixed list of resolutions. That fixed the preview. Removed "untested" warning. Adjusted scan area. * Updated gt68xx.TODO. * Find firmwares independent of capitalization (bug #301580). V 1.0.67 (2004-11-14) * Fixed test to move home sensor at the start of scan. * Fixed gray mode linemode test. That stopped e.g. the Plustek OpticPro U 16 B from working in gray mode. V 1.0.66 (2004-10-31) * Removed unused gain and offset options. V 1.0.65 (2004-10-11) * Used new lamp option from saneopts.h. * Fixed typos. * Added Packard Bell Diamond 2450 to .conf and changed status to "good". * Avoid error message when closing scanner. * Don't print max_white warning when debugging is not enabled. V 1.0.64 (2004-10-02) * Added Trust 240TH easy Webscan Gold to list of supported devices. * Changed status of Visioneer 7300 to basic. * Changed name of Genius 1200 EX to "XE". That seems to be the real name. Fixed firmware name. Changed status to "minimal." V 1.0.63 (2004-09-03) * Fixed firmware name for Mustek 1248 UB. Changed status to basic. Removed "unsupported" warning. * Added workaround for shared memory compilation problem on Windows. * It's now possible to add a new vendor/product id line to gt68xx.conf to test yet unsupported scanners without changing the source code. V 1.0.62 (2004-08-08) * Added detection for Mustek ScanExpress 1248 UB. It's untested however and I don't even know the name of the firmware. * Added new id for Mustek BearPaw 1200 CU Plus (0x021b). It's completely untested. V 1.0-61 (2004-06-18) * General: * Re-enabled forked reader process when fork is not disabled. That's faster with high resolutions and big scan widths. * In gray and lineart mode the color to be used can be selected now. * Resolution and depth lists are now in the "correct" order. * Fixed "move to the end" bug when full scan is enabled. * Used SANE_VALUE_SCAN_MODE_* macros. * Added debugging code for brightness/calibration. * Changed status of Genius Colorpage Vivid4x too good. * Removed special command set for U16B (and Genesys Vivid4) as those scanners are quite normal GT6816 devices. * Removed special test for gt6816, 600 dpi, 16 bits -> linemode. The other tests should change the settings to linemode if necessary. * Added flag to indicate that a scanner doesn't support linemode. Print an error if linemode is activated for that sort of scanners. * Adjusted various debug levels. * Added options to force backtracking and to set the number of lines to backtrack. * Increased default lamp-warmup time to 60 seconds. Also lamp-warmup doesn't stop if lamp brightness is 0. * reader_process returns an error now if read fails. * Added gt68xx.TODO. * Removed XDBG macros. Used DBG instead. * Checks for correct gain and offset are in gt68xx_generic now. * Fixed gain setting (including multiplier). * Check for status of read_scanned_data every 10 ms. Avoids short stops before scan data comes in. * Added resolution limit for using backtracking. * Reduced deafult CCD backtracking to 0x10 lines. * CCD coarse calibration: * Check if calib has succeeded per color now (fewer loops). * Added loop detection now. * Use the brightest CCD element as max_white now. * Added debugging DEFINE to check the position of the black mark. * Print which color is currently calibrated. * Changed debug messages. * CIS coarse calibration: * Removed offset multiplier. * Changed limits. * Changed debug messages. * Incresed exposure count. * Removed special lamp-warmup in CIS calibration. * CIS coarse calibration now does gain and offset at the same time similar to CCD calibration. This change should avoid loops. * Print which color is currently calibrated. * Mustek ScanExpress A3 USB: * Fixed black mark. * Use CCD calib now. * Use inverted offset. * Warm up for 10 seconds minimum. * Fixes for geometry. * Plustek OpticPro U16B (and Genius Vivid 4): * Linemode is not supported * Reduced vertical res to 600 dpi. * Mustek BearPaw 1200 TA: * Fixed position of black mark. * Mustek BearPaw 2448 TA Plus: * Fixed position of black mark. * Mustek BearPaw 1200 CU: * Increased start of white strip. V 1.0-60 (2004-04-19) * Mustek BearPaw 2448 TA PLUS: - Fixed resolution settings (added missing 200 dpi mode) - Fixed margins - Fixed black mark - Fixed TA margins - Removed untested flag - Changed status to "good" V 1.0-59 (2004-04-10) * Used 0, 4, 4 as linedistance for Mustek A3 USB. * Other mionor fixes for A3 USB. * Removed "unsupported scanner warning" from Mustek A3 USB. * Added Genius Colorpage Vivid4 to .conf file. Changed status to good. Added to man page. * Fixed black mark for Mustek BearPaw 2448 TA Plus. This one and the Mustek A3 fixes are from Jakub Dvořák . * Status of BearPaw 2448 TA/CS Plus is "basic" now. V 1.0-58 (2004-04-04) * Added BGR color order for pixel mode. Until now, only line mode worked in that mode. * Plustek U16B uses setup_scan for gt6816 now. * Fixed linedistance for Plustek U16B. * Enabled 16 bit mode for Plustek U16B. * Fixed margins for Plustek U16B. * Made 600 dpi mode for Mustek BearPaw 2400 TA Plus a bit faster. * Changed Mustek ScanExpress A3 linedistance correction to 1, 5, 5 (?). * Added detection of Visioneer Onetouch 7300. V 1.0-57 (2004-03-28) * Plustek U16B: Added GT68XX_FLAG_SE_2400. Fixed color order. * Increased debug level for setup_scan. * Fixed CCD ocarse calibration. V 1.0-56 (2004-03-19) * Genius Vivid 4xe now has color order RGB. * Removed 50 dpi for Mustek BearPaw 2448 as that resolution doesn't work. * Make sure that the lamp of the Mustek A3 USB gets warmed up. It's a CIS scanner with a lamp. That code is untested. * Full scan starts scanning from the start position of the white strip now. V 1.0-55 (2004-03-06) * Added detection for Genius Vivid 1200 EX. * Fixed product id of Mustek BearPaw 2448 TA Plus. * Other minor updates. V 1.0-54 (2004-02-10) * Added basic support for Plustek OpticSlim 2400. Thanks to Radoslaw Grzanka and Detlef Gausepohl for providing details and testing. * Fixed calibration debug output. V 1.0-53 (2004-01-19) * Debug options are only enabled if the debug level is 1 and higher. This may stop some people from activating dangerous options. * Added product id 0x0402 for Plustek U16B. V 1.0-52 (2004-01-01) * gt68xx_gt6801.c: Fixed a bug in the stop scan function for Plustek U16b. * Added support for Genius Vivid4xe. V 1.0-51 (2003-12-14) * Changed color order to RGB vor Genius Vivid 4x. Seems to work now. Updated manpage and .desc. * Set linedistance correction to 0, 4, 2 for ScanExpress A3 USB. Not perfect yet but better than before. * Added Genius Colorpage Vivid3 V2 and Googlegear 2000 as supported deviced to manpage and .desc. * Changed Genius Colorpage Vivid3x status to good as it seems to work now. * Changed status of Mustek BearPaw 2448 TA Plus to minimal as it seems to at least scan something. V 1.0-50 (2003-11-23) * Added Mustek BearPaw 2448 TA Plus. It's completely untested. * Added special command set for Plustek U16B. Changed stop scan command and download_firmware. Everything is untested. * Added Plug-n-Scan 2400 M(T) to list of devices. No positive report yet. * Used request for memory writes and reads instead of a fixed value of 0x04. * Set Genius Vivid4x to GT6816. Untested. V 1.0-49 (2003-09-30) * Fixed wrong test for allocation in gt68xx.c. * Added ScanMagic 1200 UB Plus to man page and .desc. * Added Settings for Plustek OpticSlim 1200 * Added detection of Genius Vivid 4x. It won't work out-of-the-box, however. * CCD coarse calib shouldn't run into an endless loop anymore. Plustek 1248U is much faster now. V 1.0-48 (2003-07-25) * Added RevScan 19200i to manpage and .desc file. * Updated .desc file to new :status system. * Added Fujitsu 1200CUS to man page, .conf and .desc. * Changed .conf file to be more readable. * Added RevScan 19200i to .conf file. * Added Plustek U16B to .desc and .conf, updated UT16B. V 1.0-47 (2003-06-05) * Don't check if the firmware is loaded. The check seems to confuse the USB system on some UHCI chips. V 1.0-46 (2003-04-27) - Added Genius 3x as working scanner, removed testing flag. - Added Artec 2000 e+ to manpage. - Added detection for the Plustek OpticPro U16B. V 1.0-45 (2003-04-11) - Updated Mustek BearPaw 1200 CU Plus white strip value. - Set Mustek ScanExpress A3 USB to CCD. Black mark may be still wrong. - Minor formatting changes in the manpage. - Decreased ScanExpress A3 USB status to alpha because of CIS/CCD change. V 1.0-44 (2003-03-13) - Added Packard Bell Diamond 1200 Plus to .desc and manpage. - New flag to avoid running stop_scan before doing a scan. The Windows firmware of the BearPaw 1200 CU Plus doesn't seem to like that. V 1.0-43 (2003-03-06) - Small requests are done with a response buffer of 8 bytes (instead of 64) now. Looks like GT-6816 based scanners return 8 bytes if the firmware is loaded and 64 bytes if it's not loaded. - Changed GT-6816 firmware check to ignore errors from above change. GT-6816 scanners work with the BSDs now (at least once). - Updated manpage concerning the BSDs. V 1.0-42 (2003-03-02) - Make sure that the firmware for plustek-like scanners is loaded. Didn't work for Genius vivid3xe. - Added both Genius scanners to man page. - Removed warning from Genius Vivid3xe. V 1.0-41 (2003-02-27) - Added Genius Colorpage Vivid3xe. - Added request_type and request fields to the command set. Request is 0x01 or 0x04. V 1.0-40 (2003-02-22) - Added vid/pid 0x07b3/0x0400 to gt68xx.conf also - Added indormation about Medion 4394. - Mention ma1509 backend. - Fix segfault when calling sane_open with an empty device name. - Explicitely initialize global variables to avoid segfaults when calling sane_init/sane_exit more than once. V 1.0-39 (2003-02-16) - Added BearPaw 2400 CS Plus as supported. - Make fast preview the default (otherwise BP 2400 TA Plus wouldn't work with 12/16 bits). - Added vid/pid 0x07b3/0x0400, that's another Plustek OpticPro 1248U. V 1.0-38 (2003-02-05) - Fixed resolutions for BearPaw 1200 TA (75 instead of 100). - Increase the lowest black for CCD coarse calibration to avoid too much black. - Adjusted internal gamma correction to avoid getting 0 for high gamma values. - CCD scanners use color mode for coarse+quality cal now. This fixes the problem with extremly high gains and terrible quality cal in gray mode at least for the BearPaw 1200 TA. --> Thanks to Alexei V. Mezin for reporting these bugs. - Preview isn't always in 8 bit mode now (can be selected by option). - Upper and lower limits for coarse calibration are unified now. - Added options for adjusting gain and offset. V 1.0-37 (2003-01-18) - Removed untested flag from A3 USB and Lexmark X70/X73. V 1.0-36 (2003-01-09) - Updated manpage and .desc concerning Lexmark X70. - Updated manpage concerning kernel 2.4.21-pre3 containing the 1-endpoint fix. - Fixed A3 USB resolution setting. - Updated A3 USB margins (Pedro Morais ). - Added detection of Genius Colorpage Vivid3x. It's unknown if it works. - Updated .desc file. - Don't print calib line warnings by default. V 1.0-35 (2002-12-23) - Added "afe" option for gt68xx.conf for selecting default afe values. - Removed AFE and exposure SANE options. - Added documentation for afe option in gt68xx.conf. V 1.0-34 (2002-12-18) - fixed gt68xx_gt6801 -> lamp control. - adjusted Plustek 1248U geometry and afe values. - CCD gross calibration changed: start with the default value from module struct. Is faster now for most cases. - Only 2.5 mm of calibration for GT-6801 scanners. V 1.0-33 (2002-12-10) - Updated ScanExpress 2400 USB values (from "Fan Dan" ). - Added implementation of gt6801 lamp control for CCD scanners. - Added flag for SE 2400 USB, added some quirks in gt68xx_gt6801.c. V 1.0-32 (2002-12-08) - "Coarse calibration for first scan only" is off by default now. As at least CIS calibration is faster now, it doesn't seem to be necessary and produces wrong images sometimes. - Added gamma table. - Setup gamma to 2.0 by default. - Fixed (hopefully) sigpipe when cancelling. - No geometry quantization anymore (not necessary). That should fix scanimage warnings. - Plustek 1248U: do linemode for every resolution, fix color correction. - Set SANE_CAP_EMULATED for gamma value. - Added comments for every Model member in gt68xx_devices. - Added Plustek UT16B and Genius Vivid3x to .desc. - Added implementation for inverted offset for CCD scanners. - Added Mustek ScanExpress 2400 USB. Well, at least it's detected. - Added NEW marker to .desc. V 1.0-31 (2002-11-21) - Changed 150 to 200 dpi for Mustek BearPaw 2400 TA. - Fixed warnings in gt68xx_low.c - Used DBG instead of XDBG in gt68xx_low.c - Minor manpage fixes. Added man page links to other backends. - gt68xx_low.h: Fixed __FUNCTION__ bug on non-gcc compilers. - Added more details about the BSDs in the manpage. - Fixed color order for ScanExpress A3 USB. V 1.0-30 (2002-11-13) - Added basic support for Plustek OpticPro 1248U (from Gerhard Jaeger ). Only gray mode without calib seems to work until now. - Removed 50 and 1200 dpi from Lexmark X73 (doesn't seem to work). Decreased height. - Backend status is BETA now. V 1.0-29 (2002-11-07) - Changed option titles and descriptions to make them better readable. - Added translation markers for all options. - Added German translation for backend options. - Updated manpage and .desc file concerning scanner status. - Added untested flag for Mustek ScanEpress A3 USB and Lexmark X73. V 1.0-28 (2002-10-31) - Reduce scan width of 2400 TA Plus: otherwise the black mark would create light vertical stripes. - Removed default parameters. Set AFE and exposure in every model struct. - Faster automatic gain setting for the CIS scanners. The default values from the model struct and the last values are used for calculation. - Set default AFE values for ScanExpress 1200 UB Plus, BearPaw 1200 CU, BearPaw 2400 CU Plus. V 1.0-27 (2002-10-25) - Bugfix: override applies to all devices found by the last usb line. - Individual resolutions + depth values for every scanner. - Bugfix: Mirroring code had an off-by-one error (garbage in the first column). - Artec Ultima 2000, MD 9385: Removed 1200 dpi mode (doesn't seem to work?), added 100 and 200 dpi modes. Renamed model to Artec Ultima 2000, because that's probably the "father" of all the clones. - Mustek BearPaw 1200 CU: Added 200 dpi mode. - Added manual page. - Removed override for Packard Bell (seems to be exact Bearpaw 1200 CU Plus clone). - Removed override for Trust Copmact Scan and Medion/Tevion/Lifetec LT 9452 (Mustek ScanExpress 1200 UB Plus clones). - Removed override for Tevion MD 9458 (seems to be an Artec Ultima 2000 (e +?) clone). V 1.0-26 (2002-10-22) - Several fixes for Medion MD-9385 and Artec Ultima 2000 based scanners. The Cytron MD 9385 works now. - Diabled Plustek-like firmware check again, didn't work for MD 9385. - Splitted flags for mirror_x and sset_home. V 1.0-25 (2002-10-20) - Fixed segfault for GT-6801 based scanners. - Added override for Medion MD9385. - Changed firmware detection code for Plustek scanners. - CIS autogain seraches max white and min black now (removed segment code). Hopefully no more vertical stripes. - Adjusted ScanExpress 1200 UB Plus and BearPaw 1200 CU geometry and white strip. V 1.0-24 (2002-10-12) - Added "override" keyword for gt68xx.conf. So model settings can be changed at run-time. If set up correctly, firmware lines aren't necessary any more. - Added support for the Mustek BearPaw 2400 CU. - Tevion hack (now enabled by override option) also mirrors coordinates. - Mustek BearPaw 1200 TA 1200 dpi is set up for the Windows firmware again. - Added some basic I18N markers. - Removed option backtrack (setup automatically now). V 1.0-23 (2002-10-10), - Added detection of Mustek BearPaw A3 USB. - Added auto-detection of lamp status for CCD scanners (from David Stevenson). No wait for the fixed time of 40 seconds any more. - The scan slider of the GT-6816 bsed scanners don't move home after calibration/gain. TA mode is faster therefore. - Added hack for Tevion MD 9458 to solve the mirror and "scan-slider doesn't come home" problems. - Fixed BearPaw 1200 TA 1200 dpi problem. - Fixed manual firmware selection in gt68xx.conf. - Added warning if power supply isn't ok. V 1.0-22 (2002-10-07), - Mustek Bearpaw 2400 CU Plus works in gray mode again - Line calibration uses the bit depth of the main scan now. - Vendor, product ids and other information is printed when debugging is active - Fixed segfault in attach (). - Fixed endianess issues (untested). - Code cleanup. V 1.0-21 (2002-10-07), - Added 12 bit modes for all scanners (Sergey Vlasov). - Fixed 2400 TA Plus in 12/16 bit modes in 1200/2400 dpi. - Disable depth option in lineart mode and for some scanners in gray mode. - Scan preview in 8 bit. V 1.0-20 (2002-10-06) - Calibration of the CCD scanners in gray mode should work better now. - Added 50 dpi mode for BearPaw 2400 TA Plus. Faster preview. - By default, /usr/local/share/sane/gt68xx/ is checked for firmware files. Manual adjustment is only necessary if the firmware name is different from default or at a different path. - Mixed and lower-case is tried when loading the firmware. - Adjusted geometry of BearPaw 1200 TA and 2400 TA. - Automatic gain fixes for TA mode. - Don't show "lamp off" option for CIS scanners. V 1.0-19 (2002-10-01) - Various minor fixes and adjustments concerning calibration. - Fixed sane_open detection of already known devices. - Added missing usleep for 2400 CU Plus. - Adjusted scan area for 1200 TA. - Removed detection of Artec Umltima 2000 (product id 0x4001) as this is not a GT-68xx based scanner. - Fixed some compilation warnings. - Minor misc fixes. V 1.0-18 (2002-10-01) - Added detection of Artec Ultima 2000. - Updated Lexmark X70 settings. - Fixed segfault that occured when no device was detected. - Changed test for loaded firmware for GT-6801 scanners. V 1.0-17 (2002-10-01) - Added support for the Lexmark X70 and X73 scanners - Fixed shifted columns problem for BearPaw 2400 TA Plus and maybe 2400 TA. - Fixed y-margin for the BearPaw 1200 TA (at least I hope so) - Fixed BearPaw 2400 CU Plus firmware name - Removed gt68xx_test program from distribution. Didn't work anymore anyway. V 1.0-16 (2002-09-29) - Added calibration and auto-gain support for transparency adapter mode. - In transparency adapter mode, only the usable scan area is shown. - Autogain is repeated when source was change.d - Fixed geometry of ScanExpress 1200 UB Plus. - Fixed freeze at the end of scan for GT-6801-based scanners. V 1.0-15 (2002-09-27) - Low level reading is done in a separate process now (shm is back). Some scanners should be faster therefore. - Added option "force backtracking". If disabled, no backtracking occurs (->faster, but lines are lost). - Fixed hang in reader_process. - Fixed "auto gain once" (which really worked only once :-/) V 1.0-14 (2002-09-25) - Added basic transaprency adapter support for the Mustek Bearpaw 2400 TA Plus. Other TA models may work also. No calibration or other nice features, just pure external lamp on, internal lamp of. - Support for the Mustek BearPaw 1200 Cu Plus (hopefully). - Added Lineart (black/white) mode. - Added warming-up for CCD lamps and an option to disable shutting off the lamp. - Print scanning time (debug level 3). - Removed "safe preview". Not longer necessary. V 1.0-13 (2002-09-25) - Major rewrite of the low level scan setup functions. Probably has broken some of the supported scanners. - Geometry in the model struct is in mm now. Values for most scanners are untested. - Added support for Mustek Bearpaw 2400 CU Plus. - CCD lamp is turned on when opening the frontend and turned off when leaving. - Auto gain is done only for the first scan. - Manual gain etc. options don't show up in automatic mode. - Faster automatic gain. - Bugfixes: gain/offset options, moving top-margin and exposure control. V 1.0-12 (2002-09-23) - Fixed bug concerning too little data transferred in sane_read. - Added detection of the Packard Bell Diamond 1200. - Changed some scanner names and added support for custom names in config file. - Use the size of the scan area in the model struct. This value may need some tweaking for the gt6816 scanners. - Fixed the size of scanarea for the BearPaw 1200 CU/ScanEpress 1200 UB Plus - Disabled 16 bit mode for GT-6801 scanners. This isn't even supported by the Windows driver. - General code cleanup. Removed gt68xx_mustek.c and SHM support. - Made the .tar.gz file size smaller. V 1.0-11 (2002-09-22) - 1200 dpi works now at least for the BearPaw 1200 CU. Maybe also for the other scanners. - Added manual and automatic offset/gain/exposure control for the CIS scanners. The image should be better now. - Added debug option to scan the full scan area including the calibration strip. V 1.0-10 (2002-09-18) - 50, 75, 150, 300, 600 work now for the GT6801 scanners - Preview is fast again (can be set to safe/slow mode) - Calibration can be disabled by option - Added some more safety checks for USB commands - The gt68xx_test program can be used again V 1.0-9 (2002-09-17) - Added option to disable automatic gain (->less ugly colors for GT-6801 based models) - Fixed segfault that occured when a scan was cancelled - Preview uses slow but safe (?) 300 dpi 8 bit modes now - Fixed bug concerning X0/Y0 coordinates - Started implementing dpeth option (doesn't work yet) - Internal changes (use high_scan's wait_for_positioning) V 1.0-8 (2002-09-16) - Fixed distortion problem in color mode - Selected safer default option values - Changed file names to be more appropriate for SANE V 1.0-7 (2002-09-16) - Initial version based on Sergey Vlasov's gt68xx backend v 0.0.6 - Added basic SANE interface in gt68xx.c - Added SANE options and SANE variables to gt68xx_high.h - Minor adjustments to gt68xx_low.h - Added support for Mustek BearPaw 2400 TA Plus sane-backends-1.0.27/doc/sane-microtek.man0000664000175000017500000001272512112021330015215 00000000000000.TH sane\-microtek 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-microtek .SH NAME sane\-microtek \- SANE backend for Microtek scanners .SH DESCRIPTION The .B sane\-microtek library implements a SANE (Scanner Access Now Easy) backend that provides access to the "second generation" Microtek scanners. At present, the following hardware is known to work with this backend: .PP .RS Microtek ScanMaker E2, E3, E6 .br Microtek ScanMaker II, IIG, IIHR, IISP, III .br Microtek ScanMaker 35t, 35t+, 45t .br Microtek ScanMaker 600GS, 600ZS (see bug notes) .br Agfa StudioScan .br Agfa StudioScan II, StudioScan IIsi .br Agfa Arcus II (but not the "Arcus") .br Agfa DuoScan (preliminary) .br Vobis "Highscreen Realscan" .br Microtek Color PageWiz (preliminary) .br .PP Transparent Media Adapter .br Document AutoFeeder .br .RE .PP The driver supports line art, halftone, 8bpp gray, and 24bpp color scans at normal and "expanded" resolutions (i.e. 1200x1200 on an E6), fast scans for color previews, and downloadable gamma tables. .PP The supported scanners are all SCSI scanners. However, some parallel port models may work (under Linux), if they use a parport->scsi chip, and if you can find a scsi->parport driver. This is known to be the case for the Color PageWiz. .PP The driver does .B not support the newest Microtek scanners, such as the V330 and V660, which use a new and very different SCSI-II command set. For those, try the alternate .B microtek2 backend. Most non-SCSI scanners would use the new command set. Most scanners newer than the Scanmaker E6 would use the new command set. .PP If you own a Microtek scanner other than the ones listed above, tell us what happens --- see the .BR BUGS section at the end of this document. .PP Although this manual page is generally updated with each release, up-to-date information on new releases and extraneous helpful hints are available from the backend homepage: .br .RS .B http://www.mir.com/mtek/ .RE .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the UNIX path-name for the special device that corresponds to the scanner. The special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. .PP .SH CONFIGURATION The contents of the .I microtek.conf file is a list of device names that correspond to Microtek scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS /dev/scanner .br # this is a comment .br /dev/sge .RE .PP The configuration file may also contain the special tokens .I norealcal or .I noprecal. .I norealcal will disable the use of magic, undocumented scanner calibration commands which are known to work on the E6, but may not work with other models. .I noprecal will disable logic which tries to avoid scanner precalibration. This logic would only have been activated if the magic calibration code was turned off. .PP .SH FILES .TP .I @CONFIGDIR@/microtek.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-microtek.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-microtek.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_MICROTEK If the library was compiled with debugging support enabled, this environment variable controls the debug level for this backend. A value of 128 requests maximally copious debug output; smaller levels reduce verbosity. .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHOR Matt Marjanovic .SH BUGS Known bugs/limitations are: .PP .RS Brightness and contrast broken. .br The 600GS is grayscale only, and will lock up if you select color. (Unfortunately, the 600GS and 600ZS are indistinguishable by software.) .br .RE .PP i.e. don't complain about these --- but if brightness and/or contrast .B do work for you, please tell me. .PP If your scanner locks up, try setting the .I norealcal or .I noprecal option in the configuration file (first one, then both), and see if it helps. (If it does, report it.) .PP Send lengthy bug reports and new scanner information to .BR mtek\-bugs@mir.com . All bug reports and new scanner inquiries should include an error log file. You can generate copious stderr output by setting the SANE_DEBUG_MICROTEK environment variable described above. For example: .PP .RS setenv SANE_DEBUG_MICROTEK 128 .RE .PP More general comments, suggestions, and inquiries about frontends or SANE should go to .BR sane\-devel@lists.alioth.debian.org , the SANE Developers mailing list. Have a look at http://www.sane\-project.org/mailing\-lists.html concerning subscription to sane\-devel. sane-backends-1.0.27/doc/sane-hs2p.man0000664000175000017500000001071712775277260014311 00000000000000.TH sane\-hs2p 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hs2p .SH NAME sane\-hs2p \- SANE backend for Ricoh SCSI flatbed/ADF scanners .SH DESCRIPTION The .B sane\-hs2p library implements a SANE (Scanner Access Now Easy) backend that provides access to the Ricoh IS450 family of scanners. Should also work with the IS420, IS410, and IS430 scanners, but these are untested. Please contact the maintainer or the sane\-devel mailing list if you own such a scanner. .PP This backend is alpha-quality. It may have bugs and some scanners haven't been tested at all. Be careful and pull the plug if the scanner causes unusual noise. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is either the path-name for the special device that corresponds to a SCSI scanner. The program .I sane\-find\-scanner helps to find out the correct device. Under Linux, such a device name could be .I /dev/sg0 or .IR /dev/sga , for example. See .BR sane\-scsi (5) for details. .SH CONFIGURATION The contents of the .I hs2p.conf file is a list of device names that correspond to SCSI scanners. Empty lines and lines starting with a hash mark (#) are ignored. See .BR sane\-scsi (5) on details of what constitutes a valid device name. .SH FILES .TP .I @CONFIGDIR@/hs2p.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-hs2p.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hs2p.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_HS2P If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. A value of 255 prints all debug output. Smaller values reduce verbosity. .SH CURRENT STATUS The hs2p backend is now in version 1.00. All major scanning-related features are supported, except for those features requiring the optional IPU. Scanning from the flatbed or ADF (either simplex or duplex) is supported. Lineart, halftone, 4-bit gray, and 8-bit gray are supported. Pre-set gamma tables and halftone patterns are supported, as well as brightness, threshold, contrast. Also supported is scan wait mode, binary and gray filtering, negative scanning, and absolute or relative white setting. Printing with the optional endorser also is supported. .SH PLANNED FUNCTIONALITY This scanner can scan from the ADF in continuous simplex mode. Surprisingly, many scanners scan an entire document from the ADF into memory before ejecting the sheet. Thus if the document is too long, the scanner cannot hold the entire image data in memory. But if the scanner would send its image data when its memory got full, and then read the next buffer's worth of data, continuous scanning could be achieved. .SH MISSING FUNCTIONALITY The SCSI commands for uploading (2AH) or downloading (28H) custom halftone patterns (02H) and gamma vectors (03H) should work, but require implementing the SANE Option-Value code to allow the user to create the tables to be uploaded to the scanner. No support for Maintenance Data (80H) is planned as this functionality is more suited to a stand-alone utility to be used by a technician when replacing the lamp or ADF unit. Nor is support for reading or changing IPU (93H) parameters and adjustments planned, since my IS450 lacks such a unit. The 31-byte Auto Photo/Letter struct and 21-byte Dynamic threshold struct are documented in the hs2p-scsi.h file should someone wish to use their IPU for image data processing. .SH "SEE ALSO" .BR sane (7), .BR sane\-find\-scanner (1), .BR sane\-scsi (5), .SH AUTHOR jeremy .br Maintained by Jeremy Johnson sane-backends-1.0.27/doc/sane-st400.man0000664000175000017500000001134412112021330014246 00000000000000.TH sane\-st400 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-st400 .SH NAME sane\-st400 \- SANE backend for Siemens ST/Highscan flatbed scanners .SH DESCRIPTION The .B sane\-st400 library implements a SANE (Scanner Access Now Easy) backend that provides access to Siemens ST400 flatbed scanners and compatibles. At present, the following scanners are supported by this backend: .PP .RS Siemens ST400 (6 bit gray scale) .br Siemens ST800 (6 bit gray scale) .br .RE .PP The driver supports line art and gray scans up to 8bpp. .PP The Siemens ST/Highscan series includes several more models, e.g. the ST300 and ST600. If you own one of these scanners, or a scanner other than the ones listed above that works with this backend, please let us know by sending the scanner's model name, SCSI ID, and firmware revision to .IR sane\-devel@lists.alioth.debian.org . Have a look at http://www.sane\-project.org/mailing\-lists.html concerning subscription to sane\-devel. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is either the path-name for the special device that corresponds to a SCSI scanner. For SCSI scanners, the special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. See sane\-scsi(5) for details. .SH CONFIGURATION The contents of the .I st400.conf file is a list of device names that correspond to Siemens scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS /dev/scanner .br # this is a comment .br /dev/sge .RE .PP The default configuration file that is distributed with SANE looks like this: .PP .RS scsi SIEMENS "ST 400" Scanner * * 3 0 .RE .PP In this configuration, the driver can only access the ST400 model at SCSI ID 3 LUN 0 (see section "BUGS" below for the reason). To use the driver with other scanner models, add an appropriate line to the configuration file. For example, to use it with an ST800 at SCSI ID 3 LUN 0, add the line: .PP .RS scsi SIEMENS "ST 800" Scanner * * 3 0 .RE .SH FILES .TP .I @CONFIGDIR@/st400.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-st400.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-st400.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in /etc/sane.d. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "/etc/sane.d" being searched (in this order). .TP .B SANE_DEBUG_ST400 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH MISSING FUNCTIONALITY Everything but the most basic stuff. .SH BUGS Currently, the backend does not check if the attached device really is a ST400. It will happily accept everything that matches the configuration entries. This makes it easy to test the backend with other scanners: Just add an appropriate line to the configuration file. The configuration file as distributed (see above) only works with the ST400. Be careful: If there is no config file at all, the backend defaults to /dev/scanner. .PP The ST400 answers on all eight SCSI LUNs. Normally this is not a problem, as LUN support is usually disabled in SCSI drivers, but if you are seeing multiple instances of the scanner in a device list, either disable LUNs in your SCSI setup or change the entry in the configuration file to match LUN 0 only. .SH DEBUG If you encounter a bug please set the environment variable SANE_DEBUG_ST400 to 128 and try to regenerate the problem. Then send me a report with the log attached. .PP If you encounter a SCSI bus error or trimmed and/or displaced images please also set the environment variable SANE_DEBUG_SANEI_SCSI to 128 before sending me the report. .SH "SEE ALSO" sane(7), sane\-scsi(5) .br http://www.informatik.uni-oldenburg.de/~ingo/sane/ .SH AUTHOR Ingo Wilken sane-backends-1.0.27/doc/sane-u12.man0000664000175000017500000001143212112021330014001 00000000000000.TH sane\-u12 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-u12 .SH NAME sane\-u12 \- SANE backend for Plustek USB flatbed scanners, based on older parport designs .SH DESCRIPTION The .B sane\-u12 library implements a SANE (Scanner Access Now Easy) backend that provides access to USB flatbed scanners based on Plusteks' ASIC 98003 (parallel-port ASIC) and a GeneSys Logics' USB-parport bridge chip. .SH "SUPPORTED DEVICES" The backend is able to support some early Plustek USB scanner based their old parport design around the ASIC 98003 and other rebadged Plustek devices. The following tables will give you a short overview. If your Plustek scanner has another Product ID, then the device is .B NOT supported by this backend. .br Vendor Plustek \- ID: 0x07B3 .br .ft CR .nf ---------------------------------------------------------- Model: Vendor-ID: Product-ID: ---------------------------------------------------------- OpticPro U12 0x07B3 0x0001 OpticPro U1212 0x07B3 0x0001 OpticPro UT12 0x07B3 0x0001 .fi .ft R .PP Vendor KYE/Genius .br .ft CR .nf -------------------------------------------------------- USB Model: Vendor-ID: Product-ID: -------------------------------------------------------- ColorPage Vivid III USB 0x07B3 0x0001 ColorPage HR6 V1 0x0458 0x2004 .fi .ft R .PP .SH "CONFIGURATION" To use your scanner with this backend, you need at least two entries in the configuration file .I @CONFIGDIR@/u12.conf .RS .I [usb] vendor-id product-id .br .I device /dev/usbscanner .RE .PP .I [usb] tells the backend, that the following devicename (here .IR /dev/usbscanner ) has to be interpreted as USB scanner device. If vendor- and product-id has not been specified, the backend tries to detect this by its own. If device is set to .I auto then the next matching device is used. .PP .B The Options: .PP option warmup t .RS .I t specifies the warmup period in seconds .RE .PP option lampOff t .RS .I t is the time in seconds for switching off the lamps in standby mode .RE .PP option lOffonEnd b .RS .I b specifies the behaviour when closing the backend, 1 --> switch lamps off, 0 --> do not change lamp status .RE .PP See the u12.conf file for examples. .PP .B Note: .br You have to make sure, that the USB subsystem is loaded correctly and you have access to the device-node. For more details see .B sane\-usb (5) manpage. You might use .B sane\-find\-scanner to check that you have access to your device. .PP .B Note: .br If there's no configuration file, the backend defaults to .B device auto .SH FILES .TP .I @CONFIGDIR@/u12.conf The backend configuration file .TP .I @LIBDIR@/libsane\-u12.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-u12.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_U12 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_U12=10 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .BR sane\-plustek (5), .br .I @DOCDIR@/u12/U12.changes .br .I http://www.gjaeger.de/scanner/u12/ .SH "CONTACT AND BUG-REPORTS" Please send any information and bug-reports to: .br .B SANE Mailing List .PP Additional info and hints can be obtained from our .br Mailing-List archive at: .br .B http://www.sane\-project.org/mailing\-lists.html .PP or directly from the projects' homepage at: .br .B http://www.gjaeger.de/scanner/u12/ .PP To obtain debug messages from the backend, please set the environment-variable .I SANE_DEBUG_U12 before calling your favorite scan-frontend (i.e. xscanimage). .br .B i.e.: export SANE_DEBUG_U12=20 ; xscanimage .PP The value controls the verbosity of the backend. .SH "KNOWN BUGS & RESTRICTIONS" * The driver is in alpha state, so please don't expect too much!!! .PP * When using libusb, it might be, that the backend hangs. In that case, reconnect the scanner. sane-backends-1.0.27/doc/sane-logo.png0000664000175000017500000002614712112021330014354 00000000000000‰PNG  IHDRÀáÞõz0ÌPLTEÿÿf™f33f™™™Ìÿ™3ÿffÿ™Ìÿ333ff™fÌ™™ÿÿ™Ì3fÌÌÌÿ33f3f™™f3ÌÿÌÿ333f™3Ì™f™3f™ÌÌÌ3ÿ3f33™™33™ff™™Ì™ÿÌÌ33ÿf™ÿ33f3ff™f™ÌÌ™3Ìf3ÿ™™ÿÌÿÿ3ffff™ÌfÿÌ™33ÌÌ™ÿÿÿÿ33f3™ffÌÌf3™ÌÿÌ33ff333™f™™Ì™ÌÿÿÌÿ3fÿ’s tRNS@æØf IDATxÚí}‹bÛȱ¥<-Q²ÚY9}Û˜€b2Iïí €ZJ@(è^ˆÿÿO[§ªI"=Ö$»kxìáìg½ëTãââ+qÎ-®¢÷iã´ÖÖiã´rN¹p³¦ûtj1[Wþ¿¯èNG?ÐVkg ‡o2j\;Åòûš~OÿÅè6Õ&îõˆÝüââ“£~'Ýçk4­ç¸ÃÚqɇáçÔ“(\5¸Ž¶{b ¿ÏD™,q\§&¶.C§àZe…ìרyý;"ª7AL㽑Íoˆ³¢ý»éSKSÑî›tš9ב0Ö<*!*Z­ƒuKXzh•G÷Óuc¦õãùvÅ]f´‹Äº$óþJy—¬—¼M4ÇTæeð-Íúv SWFó핚ÓV|¨!J0ÚÃd¥¢9í™ë5J?¨ 3<¿,z_Í6$þÖSÆ ¦•©d>N³Õõh:Û¸vžÛQ÷¶}éÇÓ )ÍÕêz1kLg!Çû»Ö‰î .›ŒÇ£ÑÝjv=¾&qgÛ8eìpζPpõÕ {:}÷cg‰8ƒM‚E7ºGeŠ­hDä@aU‰ðŸÃ Öx>sà®À&iÖ°²Œå¶i¿$AŒVRëü±ÑÄÛØl¢›!N‰êÜ€ó ˜,U`¤V•“7ÅÑÃ×ÍÅ÷»âÁ7ý¡ì«þ/ã×ÿºË¸e“%Y>-߸õS’Ø%8ÞyÞLsć~Ò±–lÈØ /È,`3𾓻¨ñ¢ÐÓE…÷$`v~’±u¯Y:‘öí ê…t_d—Ld,_D?µj@â^üëTw¿hmA¥ì[-]¡ô YæíÎæÝlq‹27Gãů¬)ˆT  4U È{kïk8櫺S(u©x…Yó© e¾tkU™2Ú!þ¨–é¹NÊ$.‡ ÂGõ ‰ë¥à)šV-¤ÌÓÚôÈ)Û™¹7÷УµöÀ2¶mTûò‚*§÷,ÀŽdÙAÜSûI+-K? Ï¡‡YÙÓ:^Áü7 2†[QhWE­ÑJø/ì!QÚpqÊDTºÀ9¦¤}-ã‹Ö7aÓ*­>È^i·ŒŽ)˜V»Ü“ˆIÏd²Ý—ŸÔø}c"ÌàTÉýW2ÐÞ²WD¯ÁDl’¥J)ÆH|S[o¯o/õt”4o’6žã° ι½]•ù4KS–d¥ÿ9Êá~‚ä*#jÚ,GRMæÏ;ÔMJ Ž ¦Û#ξß±Ýöz§É({H@]\&åüžÌå>ùò„&ÈYÅãÑx:þÍô‘±Û ›E1iÜé.toK0ÁàÖó)Ý»Xlè'½A¸”XhÒÜjŸ\Åt4R]IJ÷Ö0ìLRÂ6ùºZ}½ÛL–}ã¤gÃu/]ô:F«ÕÝb6Êæ´«TîZ'ݘz:šáÔA¯‡†mfÿƒõ§¾‰ë¾Œ7›»¯×w£Í«*Û9È@™Ã*Ù"WÔÙ\ãß,£ßÉd›sMÙüÙL³ºsÈü¶¶§á+ÖØ¸×ׯß@;»a£Y3õ’ yåšDFÌ bSrßʸç³ÎhGVßê¿2jÒª`&âÛíí:DM ©õºI\`=UÆ}'Ûˆ"D¤J`ã»ýp1û+cXnpK•i®ª”#)$}Ô…‰|Õ„ÿ&U*M+]¨zÐ&›Ô¬?i…„)Äô;ê¡Fl÷ñ¥a^ÏO1”n¼Í÷/5ªâ-¯úbËo72w>?`$z—¼~êûð¾‹AË5>ÐßÞÝû­ïØ­qü¯5]ÿHY dbª$Yg>Ì(¬i„ËohXe s(ÛvüŠ ,±5‰# ±ˆo”Èð·9µm—‘ò•b‘` È ÅáÄ–`¡"С%HÂÜjöuÿîÕd£æÁÈÔµ CÏy°òÆÑ>ð¶s‘¦Þ"õîÜA{é z éÚªJÃ/}h_k%i’b˜Ulýk½„?œ×Cfæ2c˺‚Ø“QbeMiòT[-Q73Â7†¿G(…fª š«|Âqø£û]4 ¤!¾YÇ•xJ¼Þ’ºñ’qRYZpÃ;Ì&•¶:¥ŸyƒžÆSN¶º€ü‹a(,Aayö•óR³Fh”ÿ%³ › CBWVú®`;+w®œì´Ï¨_eã|¸ yE÷÷q|¿/²'už›0.Ì…É6ÅPémmÙXºÒܹB@ŠtI=Ÿ"Rj„ªJyÒåÀ ÙE\b@ÙŽyHTÙ¾ËôÇ'Ò²²#ç¡¶~ÔzOh‹ŠŠ¼1ŽtšŸŽsPžtI£Rs¦œw±O87¬ˆawÐfØz~Fó K&cP†)Š´ØjÉ¢"’Lž|åõ©²¥i²L6‚K·¤b:ƒAVMüyÃñë”\áúÔeª'b`øÌŒÄx˜ÈS·‹$‹Ñ~ÊŽ<1šàIM=9gjvÑŽuøÓºPžR­ö²·Âè?D¢Ë§ó6›œ ìWíFƒ]Èé…Y65$W}®2)™õöL6×íþ)ظ¬'Ÿ¿E}«”¼ÚÝŸñÀ%ÕÄQ¼|r³{Ñ SÌò2qÁQ!KœÞÕhõPÁrVƒ¼Ï·‡Ñ½Î²ÆO0HWI·#$¹{æ}}ÀYspK·¤DFƒ^ºní8y,ïRqÿKÉ0²=KrÞ]àtTþØ}m–¢‰+ØŒº€¤ÿv#òüµÉ’²¯t»Š&%S!E+5;a'™C6¬-‘#¶Bf :©kœþÐÒ§•89l£Ú=SÂÂh.¾u/ÆR#@±_»æ`QåÃKœÐ6²œ ÷ÌÒ6 =´¯4­0µç–¼}P¡Y¶L^wÛy)gŠóù;f£ª*NºðoؘTmŠ`ìšv‚’þ€£¦$~È1¦c"./ ‡Ë ŸÓJ+ÅÎŽEŠQìgËþxI =PCôž”PtŠ¿Rf„‘W¶ î/§ºÈÑd)Ã릦ÀlÉ@Ä«„)r†Æ*]ÂeäŠp$­<„D(,H¯üDGë`hΛ“ÉŒ¸˜0'&0/nþ¿ ýqÁÄIâ8>yŒ‡ï‡£•ñT÷þqèc¸ƒø”h?–¸÷qÀÑA­G|`™~þï‘ÿq•Ú¤\H}}j•ùïmÙÁEsËd¹ôÉèö¥ëÒÔN¥æÛ&•›}j>‘Ø´º¬ AÙÒ`Îî†BÖdë$ Ñjš÷É#íÁlíŠÑGÓdÍ%7KjF·W0klá#ž)ÏqVËŠŒ‘â¤Öu"ëÎnV…à¦n1'HÂU08,çWÀ­ †‚TæÍ@<­w’´ó® ÌBd`“ñTt‰îÃÔ©ŒÏ¤q(êèJ)硈VR]X!ʼnuÀ=–lÁÒÜÁDt ÚÖð•ôgþ¬}Ã;Ú†;*M+Ôî>Å‚×7Žð‰u½U„…q ýu ëûÀZè@ð‚2¡«ðFWå½c$8¢|ÖüõÃpû™_ ²Ã¥tñraAxÜbÛrЇ£¸Ò`e}ÂAØ›ˆÊ-SÃ%#ÉS6å%ê ø1‡ìZX£´tœ ®ñaÍʯ’Éwc}«U¶ç4G{w°ÆeIaìi€Œˆ)&$%Æraöb¢É:ñÛ ë=ÅÒWe­óÓÐ0ñ,/ Ù£Ì_t#ñM…7¬~›þgêíšÆÛßX^T±«5/9IMÉZp@ î#£~,ïBÊ.ã¸1Þ0üÔZomð’æÅËÉ|iÎઠksCqLr9^åÈ1Õ#0Ä(*+(Ÿ­EâØ3G/Sì\ª¶k™Ã †,Ü'¶Fç1ýß³½Zs¸K8̤ŒwÄÀ²gVÔ Á4»¼cNŒY˜utsss?%­?”ˆRË ZÚð É}·Bkú{¶5V˜¥a5¡'䳈èCÌPÚºJ»P ÇC v`,¼¡7÷ó(Kb2žRÞJš%!_›2ñ 4Ýœjý×al¼á&—¬*{I¢Rõ²zgxŒÏÓ€Œ- óÕƒ˜Ñ hYU‚ç=ËöS^P*+i7x’ªë€“˜`FžƒÍσ¢BÀÇè>V¥i¿ƒe¼ŽœUÎÂæó³:h>9S‰¦v\ý±ÙuÐHt)`E£oÏ «6…âL䈋^DM=U&X'êœÐ°då[8ª‘˜”îPs†5[±EÂÆDQœVõV‚.huÜV‡”­XÅ1GH0—§ån|‹¦à_±Pu\Ê£ímñ‚!¨fáõHß›òTË6 ÑÚd¶n*I^”©;±>ÛÚ§ÎÁw™xÒqLQE¾FS’”·¬ÑHÊ+H£³¢܇×q$9·L¼I!É%܆¼ø‡3shœqdÕ ór+ªæ÷–m]*@¥ˆ1g{˜…eÄ‚Íï÷:`íD}FIqãÙyÀ¼4ÁV\9°B¥®EkXs>rE4ËnÜ‘ã}6Äâ¤nǦd×ç§{Àgi¾£M$š‰©–a*Pùg‘Úù†ê ¼ŠØš„-Io©ÌääP‘﯒ÙW(ž¹£‚¿Á$á\•kúLJ¢rçÎH~€$È¥„¦Ì°ó&ã?L >®íX²åÜ ¥ `ù¥Iʽðj’eËìÒe]J[k.êaÐrÙâzæÌ fµÁ Øjž–îrÍþ8* d¦MƒÄ26š=Å3‡®U9éÇoi]¨ñ%ë<ÃŒ>…oAlÄ\z`2TåÑ.Ph°…9Ñ´2!±Á6O>º‡‰ª[îâ.ŽebIUö’°*<3¦ÿÖû;¾ƒ‚eƒ¶O–+b8ªHúI^¡K£uIp-×SŽ$² 5•‡jÖµ§a8µ©:¦H&[šÜ”¡F;_]özBŽ‚€Ça#£‡Ôyãñeè>¢ãÅ›ˆ§•ç·’™{Q¿Ø•|r®„LÈR¯Oj C¡H«œn>7úù‘1 WÓÅt:c|ÂÕ•ÜèÒ™ž¼F?•ÀiØñÕõh´@2™Þ>'78m+ئÖD§ùy&©â—)£6¦Ó¯‹ÿ½˜ù½F.~(.ðYkÕS|â å(¡6׋Åׯ×#Z§Íl¶yè {Y}…š­”ûÑkí¢GÉ„«¯ Ì×¼NÔA4à¯i£¸V î€]¾C£ÑÞ×Ñu‹{¸Ç¡’ýmæÈœ7Ô?<9\{Ä·6ñßxWG×_}û_ï3ÚÕìc®W™‡¢'”ó=ø¤÷Ñ*‰ù,°ŠÍâk‹ Y,f³Ñ­]>àqê” ½×A“ ÖzÏ¿p×½ö™-~MÔÞ¬¸Ø_#"ªëçíæI <ÇCÚ!ú'¨†ÆzLK´.÷'vVðŒz+ö‡9Ø– C6×¼_ïfŒÿ™&É.VÅaŠxží7—±¼$+wiæÀlŒ6£kÐÑìn¶råÆíÍÖ‰ó1go·Y_Bü v`–:úeÌS 9±øJ›1Ap•Æûáo%ÅÎÛxÉš­ÌCÐW<3ƺoˆ_GÀH½>4ÉÎ’JøÞ8ñÑL’HÐî€p"«³þ2½€Îf41 ­éãNûËÎÑÛvÒš&C¤7?ŒÎ¡6ÌmÔÃë+€jÄÛÊ:‹•½±~k¶Œ°D!~OˆµÙ-5UÙ6øGp¢Ú·®*½E2>r}0yñÁ¦´C¯¯²JÔÑ9$ýö/?0¼üÜÖ|;’à3@å°[\"nþ,=~IšÄmã·Îñíq;Ä_PB¥Í0`42¶ìèÐþöÆ—dd Ù!ºO·H(¸ŠÀ(!F«sU¹/Ü‚¯ØsáT’0‘kF:#ª[X·×þ…u;€¤|RƒUÃaj‹jö×I³”c4ºb÷}€S· äµ9S:ç]®ºØ3¤;Ë¡*5[rúIËÑ|Æ3×ã"sjv™¶‰EÁÛ#0¿ãQg¨ÿÉhñƒèi“an`}„N8" JÑyKIJ'™`¾ÉÑ”åÈÖkÚÓËÄÇg”²J¢ÊøÕ愉ãµÎúÈ#â‡äçyPžf÷¾Mýrd&ñe>:„|¾­>‘bx°U‚£f’н¼WH0ôQì0 ø.Ôa—õ1k‹TÒeR’ B…Ñ!2i°ç³fÆÒeŸñxx¦”¤uSøL "xrÒ@@÷ƒM×¥%.æ ‹ŒÏœqã—)IË–Oï²Ò\!Ö›ª*ØpÊgƒËúIJr³oiÖH%+Ÿ§Ó)Ç!+-Ð΂qòÈ .‡ÔœǪù%LW\±aCMxHŠ×+D&}¦ Ž~t.ÚëéIBŶ²‚÷¡‰Ê“ò¥©A„ÐõûoÂ’‘7Éèöºôõ£)*ÝéÎÑFERÄô;!ÇQIŽ¿yþD~=Ÿ?Ï¿ n~ï!|_wÿñóãºâx8Àu(¸ýƒ8\ƒíníXoßûÖWñ)ÄgvpqÔ±ûôŒ¶Ð”ÛUàûŸ·ŸÆÛ Ù‚³ˆ‡ÇÕ~|Î †nˆü.Þ›óÛ›Ê?®׿υ2e²îÉ1O–È’µŸ¡:?‘ó<œ1å¿ÓpMúßì–ÐP½ƒ²\/É+jóéýÛ5œ—Äõ0ŒòF™Ñ ÉŽÏhy³Ëì’†»Î°ÖλXþ”‚~ØÅ%þ€21kuŒÉN†ùƒ&b˜2’OI¶¦Ñ6’ñ•ôo ü`ð„ NíÒc/;$2'Yƒ³Ùy0ß­~¿y€ .yGkéÏÌЉàO¯ëÏS 8UÆÑôÖ¼Ài›<þÊŸç‹…ØçÔ¿*¾¬[‚×dDÇÓîÒ Rr°R-XíQ‚œ²×…¯+•ƒR]µ€[¿ãÓOƒ‰|Rp`ù}fe§»ËÌ“I{¾g¬"ŸãS!îcg¬+qºðÉvO1®=Ç(œÖ§mJ‹@Sä´ž®ðŽ·…¦¡~g(×¶éjß%ÏÊ£QÖƒ|ufF«S^г?×ÐHìH%Ä ™ˆo‚ƒÃJKœÌÌGús[ø`Ùo¹ŽÙTª(éÿŶ԰šAȦjS1>¸…|ÏKÎgt¶ÔËíÜSñ‘ÒJX£åmeLy&öH—~J²Þé8•r[ fAÁ+V-QTˆmð /uˆªåZí²p¢?‰%„㨡-xÀòÓ7"϶‡l‹œ® DÐʯ"DgÛ —§‘¸•’ñóO;tŠobUÂ'&,Ò•ò¥¡m„‘¶á¶<í\"?i¡Ê¨Ê쾬3maIÁ¨ jU`Ø-¦P•&lqfŠ ŒòG·ŠÌ¯o*¨ÊcøëmV§j·7E0o?Y5B÷|ôŽ5¼Êa¯ZJ"ª×$©É˜ÉÊ´Pû06ƒÓG«^ùHX€qº^Ð/Ž%úVÏ?GPd«lµöˆ*ͤèH¶ðDÓ BèÞŸ&š­"t_ÇÒ|Õ.2ŸÏ+ÒŽíZ¤W7kÌ´àâ×~°8»çpî>i~nXWÉiÏB†ÚKM£[$g•zHLàAÁÓr#"¦d=¤L ˜·ásZ˜g™w Ý˜X¼fHEµy=‚åø[?Õ“ˆÁTí¡²“ Ÿúqd4­'GŽˆ—z3„W‡A;ÌC¬0µ8Skh$=ÃÉhª¯nxåY|WйÊ#D•WМeå’ áŒâùM|sÿßyß7sÃDd_œU­mhå|0ü«·Ãq†^Z…-ØÇ$žþ[¶w­Jª¤ÊÅÄFìÁ->A­It?ž.À,Ânp¿I«Ú4?ý# ¦jÏió'úNö¶À°Õ#øBº_T¹ñV±XñV±ì¤<Š剱vç{7sËNØVKRŸ,"0•i§Úd v‘.[/Y³(Im9Ƭû]«ø™&Äyl¿ÑØiÉo¾g|æ)÷3`!j‚úó’õJ`¾JÔ1éí$ÚÁ,ɽ‚ÉaTWñÅrßäìÕ þæþ]bKeÕó4aØÂ(a›šºõßâÌÆ;Çz8ÈMð‰*6Í…q:~´Žæïƒ×”¸V½x¿OÅH;ÕÆLmòh'³Ë"Ô»ÜÎC8´·ÑÅ»àÌp½gX˜LPo‘·Âj”LÙÔèl¶ |ö“-ÖeP%• ž2æï˜RpZÑ»xkÊ[ÖŽŸ”!gR4·S’å¼ðž´¿Áœƒ9cøü÷|Eï5þdMÄ®µbrimW¶±lýÁ.1ù×&k¸îæ-;G…Ôaúro-Îâ%ø]Èg ÖeÞkëj&Å‹&TKIÞÞ á2/øq¾¢é§^©zš|÷уvöaƒ éÛ³^µ¥> ÀÎÁ3ºO.ɒֹœTkNxÆnE^×=@¯Ë໦Bµ6¼ˆH!ê¡ZÕ¦†ˆË£€¡#öOˆTr° Dè‚ï¹ %LÔÓ–r´ ÕàŸƒ€#yc„‚Ä!c|”D¬@¯Òt>’ EpߎÈX}šxÄjÚ·±¨ ó€šFrPœÈŠ,ò;Jü~Š[£øXWT çï!¸ÂÙûº³R‡øX:™ µlOš(|Ö¶QZñÈÄ¦à ™‘“÷Ó °S½™ â '³×&zxH¡úð <–BwÕý|&ûÝìxÀC‚q‹‚ð÷ …c/P~gL¥æ¬ÝÌA˜Œ\Ên9{ŠEkOs´ÁC¼ˆËØkcÃôúð¤NQÿ…ñ8lÐè%`kÝéÈ]”Ð1SUÊ;IÍ©þ€)\À_(¬i9jP¶AÁ-UŸ'wô> QB~Š#­QôÞs¨åÙ)bÕ×G b×;åµèâS`g6òtËÓì’çr–V4ï)\+Çd˜·pb½ÃiD•ñs]`Ë¥rL±Ä Jû$zžsâ\%0>ÆáÄ)p„ìm‹¾;! q8yv8ÄšÌÙ CW\¬íû |µ&o×ßõÿ =IDAT6icv<·hÊèþÍN[7 Y—ð:õ)^øèþøØiÈI¶æ|`æi)Ͱ0j{&Á}©òÈ&Ô'•Ô¡Xˆhäé“èèÑqN¢K´¢ÈK–[‡,æÖ!€ìž”½‘™~¾’Hö¬ûDƇg+QeðæØ>L5*»Ìh‘á”|jsÚ*¤ ‚Qßý…¹úi0yä‹{+Ée—ê“y>¤Ø7ÝÜ¢ÎsêU²Ý½C†Ê“( GK 8BVS·‚îA9>ÚìG¦ÙoV3…¨o´‘ $r8 gtqV¡Ÿ>æÇq HVm–µÍTi'hDsênë­éåãRUšoM¸6^˃%©4Þ¦a_ºéžnæ“)¢¬SæzdSðAIÎçûª.%Ì3U|ÒNÝî‚í’¹¾"øÛÔ=ˆ2Ÿ FáÁº¦…CXŽÅú á2ØÂU¯%´n÷†M3Åàõ'®øÞ<ï)œK“HêJ$÷7YRRW­±ð—,šnié`32Æ÷©Žð§So/òUžê `Ç9ÿ)ó6eÀ!±ª&-¦ÃQ¤> ûl_ Ÿ“û£¿?ßDóçû›x›<Çß|ž·g…‹ÿUOòäƒå¼MeÏÛ†ÏQ¥QÆ ‰ú÷º² v­JNÜß|—ïO…v…ÏCôëø¤€pIš²ü6B’Kܰ“­¶[ðZ2d$NÿæTˆÊ@{„ë zIn¨oe…‹­gÃ*"¼Î|†Á„Ȇ®Þ¦âÞZ£ •7>1n¾é¸s!"(f F< ò@¼D²Ä ÁÉ3VBb$Öp*Sq\ú{Ç¥¶{$šYrÙ±wüüøùË—/¿|þÂ)±œË²´)OÛ\R©^Œ_!ÁôN‹€Ÿã YüåO¨3Ü ÞUÜxñÓGšçÛO?N@{Ëĺ –Á;8PÁUýÇã/ÿ1¾¢?£Íh*uç£ÍÕ˜‹?æÈrÛÓÉÀ1/ù|_ÅrIJÿÞg“¥<ÒP_§4þ1ž€bÉ͈'ÂGÖO_p–:}qà:bЪ÷ˆ‘7Ô‘yº‰¿LÇ~ÕÇãñh6 ØøñÓ7ÿ,ÄéOÒ#îSŠK]HSã—ù÷A³â"ëÇ_°ørš®Ù‚Èhƒóü7xÌ>'ZúíÏœw?Ñ·ò™yˆ®‘³Ê‡ò¬¿/¹Òȃ2þÄ´Ïe¼r$ÂÝb6›]/6#™Ö¦AßÿF܉{ :Uƒw‚K„ØÐ÷äcèÛ’Æ?õçRðØgÄ›»ÕÝ×»Õ‚f@Ô$Ô5Âõâ–8—0:iY‹Dch£6çeœÒäi„Tœ¸=®™…S—Œ”U½†2oˆ!Ô?ü–èùíÌ6žT^ßÄ¿yÙɧ!,ö&ðõZÆ?ÚüRÏé QúüÖ°MYøs<¹òËcœ7*µOÃEH ?þ…Ÿ¨3£^ƒäï¶—ŸøxÁ’‰Íùí?רܷÈÖ,&€—1'Ž:bL~^5wlŸ ëà'ñGZ\!q9ænÕãâŸéýhÚîÑôAeäo ’lµ’ó¡%^Wи6‡b¼k¿úî­g}lE/Èd$.~| ŠrfC_¡p„ 14Æ¿á¹1Ÿ< $æ­.²U&‘`B8+Ò1Þù`°¤Å}d‡9†Ø…fðùÕ?–É›ô‡‡ÄÏh³€šXBa/I³<ð„Þ¾z•c‘O™â<àá hVžàÔiµò[1.H«Çé4ØAXmHSbˆ»klÊbÙäM¢Žúø+r©=ÄxZ+I;ÉÙ1tt`°ü˜rÆ^Ot΃ƒ'ŒOÈ‰ŠÆÁ˜úMƒ–6ØýØoÀ¯GE¾$”ç0p «¼°ÃiJ¦ÉÕ§ð8γWý‘˜ÓÞžÀh7Y÷W>jŸ?8‘?Г.×ù­K6x^€ÀÖ=ÖÀb0gÍ€#Ê ½Ÿ+wZç‚É W¿m,]ùt0¬”tUF>8Çë_ éáñ_$áM¶8TtVö±æÈ¹)o£ÿá=a?‹¿‹ì!;ûá/zM6©Ÿ%ª9ÔÍ´ÂèhÕVÀ¤g08{Á¸úº$enËÿy"‚ý]lqÃËŸÆì¼Œ½Ü§xù5IHª' q`ÃO+Îåu6ü¸NåÚ'e¥ºWÝ*2€ Ô§x®OÉÙ_Xñüý}‰&ãM°)-Àv’B ¤ó éÊ…~)S‡Ä£º*EdækF=Ï?ßüñ'ÖZ€ú¯=úxÿ‚ﻺÉÒô+)K®›«±“ ¦Dáñßᬠ.{BÀÇ6îcÝÌŸªxüqDÐëÇõãú÷êDó©úåTa¾O>^ï℃ì†~Ÿ:®Óo<}L{Ð}ã2½ùƒS÷*ŽwGuÞΠ¡áY v¸¯}‚Ù]¢ãuÆ\OÙîág[ÇG–ëÀzSxÇ œFMñÎu mµý$´·gÝŸ×v|îâ3eâ›Rî¼{“ÆÞ£§ õo“E?®×ÿ¥×ÿFô¸„ªk+­IEND®B`‚sane-backends-1.0.27/doc/sane-avision.man0000664000175000017500000001271613063340150015062 00000000000000.TH sane\-avision 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-avision .SH NAME sane\-avision \- SANE backend for original Avision and Avision OEM scanners (HP, Minolta, Mitsubishi, UMAX and possibly more) flatbed and film scanners. .SH ABOUT THIS FILE This file is a short description for the avision-backend shipped with SANE. .SH DESCRIPTION The .B sane\-avision library implements a SANE (Scanner Access Now Easy) backend that provides access to various Avision scanners and the Avision OEM scanners labelled by HP, Minolta, Mitsubishi or Fujitsu. It is fully big-endian aware and in every-day use on PowerPC and SPARC systems. .B I suggest you hold one hand on the power-button of the scanner while you try the first scans \- especially with film-scanners! .SH CONFIGURATION The configuration file for this backend resides in .IR @CONFIGDIR@/avision.conf . Its contents is a list of device names that correspond to Avision and Avision compatible scanners and backend-options. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .nf # this is a comment \ option force\-a4 option force\-a3 option skip\-adf option disable\-gamma\-table option disable\-calibration \ #scsi Vendor Model Type Bus Channel ID LUN scsi AVISION scsi HP scsi /dev/scanner usb 0x03f0 0x0701 .fi .TP force\-a4: Forces the backend to overwrite the scanable area returned by the scanner to ISO A4. Scanner that are known to return bogus data are marked in the backend so if you need this option please report this to the backend maintainer. USE WITH CARE! .TP force\-a3: Forces the backend to overwrite the scanable area returned by the scanner to ISO A3. Scanner that are known to return bogus data are marked in the backend so if you need this option please report this to the backend maintainer. USE WITH CARE! .TP skip\-adf: Forces the backend to ignore an inconsistent ADF status returned by the scanner (ADF not present, but ADF model number non-zero). Without this option, the backend will make several attempts to reset the ADF and retry the query in this situation, and will fail with a "not supported" error if the ADF still doesn't respond. .TP disable\-gamma\-table: Disables the usage of the scanner's gamma-table. You might try this if your scans hang or only produces random garbage. .TP disable\-calibration: Disables the scanner's color calibration. You might try this if your scans hang or only produces random garbage. .TP Note: Any option above modifies the default code-flow for your scanner. The options should only be used when you encounter problems with the default be- haviour of the backend. Please report the need of options to the backend-author so the backend can be fixed as soon as possible. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I scsi scsi-spec .I usb usb-spec .RE .PP Where .I scsi-spec is the path-name to a special device or a device ID for the device that corresponds to a SCSI scanner. The special device name must be a generic SCSI device or a symlink to such a device, for example on Linux "/dev/sga" or "/dev/sg0". The device ID is the ID returned by the scanner, for example "HP" or "AVISION". See sane\-scsi(5) for details. .TP Note: Since the backend now includes native USB access, it is no longer needed \- even considered obsolete \- to access USB scanner via the SCSI emulation (named hpusbscsi on Linux) for Avision USB devices such as the HP 53xx, HP 74xx or Minolta film-scanners. .PP .I usb-spec is the USB device name, the vendor/product ID pair or the name used by libusb corresponding to the USB scanner. For example "0x03f0 0x0701" or "libusb:002:003". See sane\-usb(5) for details. The program .IR sane\-find\-scanner helps to find out the correct scsi or usb device name. A list with supported devices is built into the avision backend so normally specifying an ID should not be necessary. .SH FILES .TP .I @CONFIGDIR@/avision.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-avision.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-avision.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_AVISION If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. The debug level 7 is the author's preferred value to debug backend problems. Example: export SANE_DEBUG_AVISION=7 .SH "SEE ALSO" sane(7), sane\-scsi(5), sane\-usb(5) .br http://exactcode.com/site/open_source/saneavision/ .SH MAINTAINER Ren\['e] Rebe .SH AUTHOR Ren\['e] Rebe and Meino Christian Cramer sane-backends-1.0.27/doc/sane-teco2.man0000664000175000017500000001542412112021330014413 00000000000000.TH sane\-teco2 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-teco2 .SH NAME sane\-teco2 \- SANE backend for TECO / RELISYS scanners .SH DESCRIPTION The .B sane\-teco2 library implements a SANE (Scanner Access Now Easy) backend that provides access to some TECO SCSI flatbed scanners. This backend should be considered .B beta-quality software! TECO scanners are sold under various brands like Mustek, Relisys, Piotech, Primax, TRUST. This backend may or may not support yours. .PP The scanners that should work with this backend are: .PP .RS .ft CR .nf Vendor Model TECO model status ---------------------- -------------- ----------- Mustek ScanMagic 4830S VM3575 untested Primax Jewel 4800 VM356A good Primax Profi 9600 VM6575 basic Primax Profi 19200 VM6586 good Relisys APOLLO Express 3 VM356A basic Relisys APOLLO Express 6 VM6565 good Relisys APOLLO Express 12 ? untested Relisys AVEC II S3 VM3564 good Relisys AVEC Super 3 VM3575 basic Relisys SCORPIO Pro VM6575 good Relisys SCORPIO Pro-S VM6586 untested Relisys SCORPIO Super 3 VM3575 good .fi .ft R .RE For all these scanners, lineart and gray mode work well. However, most of them do not support more than a handful of resolutions in color mode. See the backend home page (under AUTHOR) for the exact status of each scanner. Note that the untested scanner will not be directly supported. You should contact the author for that. The TECO VM number can usually be found at the back of the scanner. It is also part of the FCC ID. The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage, xsane, quiteinsane or kooka. .br If you have any success with a scanner not listed here, or if you have any strange behavior, please report to the backend maintainer or to the SANE mailing list. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d teco2 .RE .TP .B Scan Mode .TP .B \-\-mode selects the basic mode of operation of the scanner valid choices are .I Lineart , .I Gray and .I Color The Lineart mode is black and white only (1 bit). Gray mode will produce 256 levels of gray (8 bits). Color will produce a 24 bits color image. .TP .B \-\-resolution Lineart and Gray selects the resolution for a scan. The scanner can do all resolutions between 1 and 600, in increments of 1. Color selects the resolution for a scan. The scanner can do only the resolutions listed. All values with ydpi > 300 (300 x 600) or 600 (600 x 1200) result in a wrong proportion for the scan. The proportion can be adjusted with the following imagemagick command: convert \-geometry (dpi/max_xdpi * 100%)x100% max_xdpi is for the vm3575 constant with 300 dpi e.g. 600dpi adjust with: convert \-geometry 200%x100% .TP .B Geometry options .TP .B \-l \-t \-x \-y control the scan area: \-l sets the top left x coordinate, \-t the top left y coordinate, \-x selects the width and \-y the height of the scan area. All parameters are specified in millimeters by default. .TP .B Enhancement options .TP .B \-\-custom\-gamma (no custom gamma option for the VM3564 and VM356A) (color mode only) allows the user to specify a gamma table (see the next 3 parameters). .TP .B \-\-red\-gamma\-table (color mode only) can be used to download a user defined gamma table for the red channel. The table must be 256 bytes long. .TP .B \-\-green\-gamma\-table (color mode only) can be used to download a user defined gamma table for the green channel. The table must be 256 bytes long. .TP .B \-\-blue\-gamma\-table (color mode only) can be used to download a user defined gamma table for the blue channel. The table must be 256 bytes long. .TP .B \-\-white\-level\-r (VM3564, VM356A, VM3575 and VM6575 only) Selects what red radiance level should be considered "white", when scanning some sheets by changing the calibration value loaded into the scanner. Scale 0..64 in steps of 1. .TP .B \-\-white\-level\-g (VM3564, VM356A, VM3575 and VM6575 only) Selects what green radiance level should be considered "white", when scanning some sheets by changing the calibration i value loaded into the scanner. Scale 0..64 in steps of 1. .TP .B \-\-white\-level\-b (VM3564, VM356A, VM3575 and VM6575 only) Selects what blue radiance level should be considered "white", when scanning some sheets by changing the calibration value loaded into the scanner. Scale 0..64 in steps of 1. .TP .B \-\-preview requests a preview scan. The resolution used for that scan is 50 dpi (for VM356A and VM6575 75 dpi) and the scan area is the maximum allowed. The scan mode is user selected. The default is "no". .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/teco2.conf supports only one information: the device name to use (eg /dev/scanner). .SH FILES .TP .I @LIBDIR@/libsane\-teco2.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-teco2.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_TECO2 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .TP .B SANE_TECO2_CAL_ALGO Either 0 or 1. Selects the algorithm for the calibration. A value of 1 seems to give better scans on the VM356A, VM3575. Feedback on it is welcome. For VM3564, VM356A, VM3575, VM6575 default 1. For other supported types default 0. .SH LIMITATIONS The windows TWAIN driver has many more options than this SANE backend. However they are only software adjustments. This backend only implements what the scanner can support. .SH BUGS Plenty. Parts of this backend are still under development. .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1), sane(7) .SH AUTHORS .TP Frank Zago .I http://www.zago.net/sane/#teco2 .TP The package is actively maintained by Gerard Klaver. .I http://gkall.hobby.nl/teco2.html .SH CREDITS Thanks to: .TP Gerard Klaver for his relentless VM3575 testings and contributed a patch to support the VM3564 and VM356A. .TP Mark Plowman for providing the first SCSI traces from a VM3575. .TP Andreas Klaedtke for providing the first SCSI traces from a VM6586 and for his testing, and to Stefan von Dombrowski for his testing. .TP Nicolas Peyresaubes for providing the first SCSI traces from a VM656A and for his testing. .TP Dave Parker for testing the support for the VM6575. .TP Michael Hoeller for testing the support for the VM356A. .TP Christoph.Hoeffner for testing the support for the VM3564 (Relisys AVEC II S3 firmware 1.09). sane-backends-1.0.27/doc/sane-abaton.man0000664000175000017500000001136612112021330014644 00000000000000.TH sane\-abaton 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-abaton .SH NAME sane\-abaton \- SANE backend for Abaton flatbed scanners .SH DESCRIPTION The .B sane\-abaton library implements a SANE (Scanner Access Now Easy) backend that provides access to Abaton flatbed scanners. At present, only the Scan 300/GS (8bit, 256 levels of gray) is fully supported, due to the absence of programming information. The Scan 300/S (black and white) is recognized, but support for it is untested. .PP If you own a Abaton scanner other than the ones listed above that works with this backend, or if you own an Abaton scanner that does not work with this backend, please contact .IR sane\-devel@lists.alioth.debian.org with the model number, so that arrangements can be made to include support for it. Have a look at http://www.sane\-project.org/mailing\-lists.html concerning subscription to sane\-devel. .PP Abaton is out of business, and these scanners are not supported by Everex (the parent company of Abaton), nor is there any programming information to be found. This driver is therefore based on information obtained by running Abaton's scanning desk accessory under MacsBug and tracing the MacOS SCSI Manager calls it made during image acquisition. .PP However, the protocol is very similar to, though not compatible with, the one used by the Apple scanners, therefore, if this backend is ever extended to support the other Abaton models (they also made a color flatbed scanner), it may be possible to fill in some "missing pieces" from the (quite detailed) Apple scanner documentation. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the path-name for the special device that corresponds to a SCSI scanner. For SCSI scanners, the special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name takes a format such as .I /dev/sga or .IR /dev/sg0 , for example. See sane\-scsi(5) for details. .SH CONFIGURATION The contents of the .I abaton.conf file is a list of device names that correspond to Abaton scanners. Empty lines and lines starting with a hash mark (#) are ignored. See sane\-scsi(5) on details of what constitutes a valid device name. .SH FILES .TP .I @CONFIGDIR@/abaton.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-abaton.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-abaton.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_ABATON If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 255 requests all debug output to be printed. Smaller levels reduce verbosity. .SH BUGS There are a few known ones, and definitely some unknown ones. .TP .B Scan area miscalculations For the sake of programmer efficiency, this backend handles all measurements in millimetres, and floors (rather than rounds) values to avoid possible damage to the scanner mechanism. Therefore, it may not be possible to scan to the extreme right or bottom edges of the page. .TP .B Cancelling the scan This might not work correctly, or it might abort the frontend. The former is more likely than the latter. .PP If you have found something that you think is a bug, please attempt to recreate it with the SANE_DEBUG_ABATON environment variable set to 255, and send a report detailing the conditions surrounding the bug to .IR sane\-devel@lists.alioth.debian.org . .SH TODO .TP .B Implement non-blocking support .TP .B Finish reverse-engineering the MacOS driver This will allow me to add support for other models with reasonable confidence that it will work, as well as to fully exploit the information returned by the INQUIRY command. .SH "SEE ALSO" sane(7), sane\-scsi(5), scanimage(1) .SH AUTHOR The sane\-abaton backend was partially written by David Huggins-Daines, based on the sane\-apple backend by Milon Firikis. sane-backends-1.0.27/doc/sane-snapscan.man0000664000175000017500000000710012112021330015175 00000000000000.TH sane\-snapscan 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-snapscan .SH NAME sane\-snapscan \- SANE backend for AGFA SnapScan flatbed scanners .SH DESCRIPTION The .B sane\-snapscan library implements a SANE (Scanner Access Now Easy) backend that provides access to AGFA SnapScan flatbed scanners. At present, the following scanners are supported from this backend: AGFA SnapScan 300, 310, 600, and 1236s, 1236u, 1212u, e20, e25, e40, e50, e60, Vuego 310s, Acer 300f, 310s, 610s, 610plus, Prisa 620s, Prisa 620u, Prisa 620ut, Prisa 640u, Prisa 640bu, Prisa 1240, Prisa 3300, Prisa 4300, Prisa 5300 and Guillemot Maxi Scan A4 Deluxe (SCSI) (with varying success). .PP .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the path-name for the special device that corresponds to a SCSI scanner. For SCSI scanners, the special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. See sane\-scsi(5) for details. .P For USB scanners the devicename must contain the keyword "usb", as in .I /dev/usbscanner or .IR /dev/usb/scanner0 . For scanners that need a firmware upload before scanning add a line starting with "firmware" followed by the fully qualified path to your firmware file, e.g. .PP .RS firmware @DATADIR@/sane/snapscan/firmware.bin .RE .PP For further details read http://snapscan.sourceforge.net. .SH CONFIGURATION The contents of the .I snapscan.conf file is a list of device names that correspond to SnapScan scanners. Empty lines and lines starting with a hash mark (#) are ignored. See sane\-scsi(5) on details of what constitutes a valid device name. .SH FILES .TP .I @CONFIGDIR@/snapscan.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-snapscan.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-snapscan.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_SNAPSCAN If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 255 requests all debug output to be printed. Smaller levels reduce verbosity. .SH BUGS Man page doesn't provide much information yet. .SH "SEE ALSO" sane(7), sane\-scsi(5) .br http://www.cs.ualberta.ca/~charter/SnapScan/snapscan.html .br http://sourceforge.net/projects/snapscan/ (new development website) .SH AUTHOR Kevin Charter, Franck Schneider, Michel Roelofs, Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Oliver Schwartz and Mikael Magnusson. .br Man page by Henning Meier-Geinitz (mostly based on the web pages and source code). sane-backends-1.0.27/doc/Makefile.am0000664000175000017500000003547512775312261014047 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. man1_MANS = scanimage.1 sane-config.1 sane-find-scanner.1 gamma4scanimage.1 EXTRA_DIST = scanimage.man sane-config.man sane-find-scanner.man \ gamma4scanimage.man # Create a list of man pages for only backends that are compiled in so # that is all that gets installed. Also, build a complete list of all # backend man pages. This allows a user to optionally generate all # man pages in HTML form for things like posting to a web site. # # Backend man pages bypass standard automake man5_MANS because there is not # a man page for every supported backend. We could get rid of # custom install/uninstall if we required man pages for every backend. BACKEND_5MANS = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 \ sane-dll.5 sane-dc25.5 sane-dmc.5 sane-epson.5 sane-epson2.5 sane-epsonds.5 \ sane-hp.5 sane-gphoto2.5 sane-leo.5 sane-lexmark.5 \ sane-matsushita.5 sane-microtek.5 sane-microtek2.5 sane-mustek.5 \ sane-nec.5 sane-net.5 sane-pie.5 sane-pieusb.5 sane-pint.5 sane-pnm.5 \ sane-umax.5 sane-qcam.5 sane-scsi.5 sane-artec.5 sane-kodak.5 sane-kodakaio.5 \ sane-fujitsu.5 sane-sharp.5 sane-s9036.5 sane-tamarack.5 \ sane-ricoh.5 sane-avision.5 sane-plustek.5 sane-st400.5 \ sane-mustek_pp.5 sane-dc210.5 sane-v4l.5 sane-snapscan.5 \ sane-canon.5 sane-coolscan.5 sane-bh.5 sane-dc240.5 \ sane-umax_pp.5 sane-umax1220u.5 sane-sm3600.5 sane-usb.5 \ sane-mustek_usb.5 sane-sceptre.5 sane-canon_pp.5 sane-canon630u.5 \ sane-teco1.5 sane-teco2.5 sane-teco3.5 sane-test.5 sane-sp15c.5 \ sane-coolscan2.5 sane-hpsj5s.5 sane-gt68xx.5 sane-artec_eplus48u.5 \ sane-ma1509.5 sane-ibm.5 sane-hp5400.5 sane-plustek_pp.5 sane-u12.5 \ sane-niash.5 sane-sm3840.5 sane-genesys.5 sane-hp4200.5 \ sane-mustek_usb2.5 sane-hp3500.5 sane-pixma.5 sane-stv680.5 \ sane-hp5590.5 sane-hpljm1005.5 sane-cardscan.5 sane-hp3900.5 \ sane-epjitsu.5 sane-hs2p.5 sane-canon_dr.5 sane-xerox_mfp.5 \ sane-rts8891.5 sane-coolscan3.5 sane-kvs1025.5 sane-kvs20xx.5 \ sane-kvs40xx.5 sane-p5.5 sane-magicolor.5 EXTRA_DIST += sane-abaton.man sane-agfafocus.man sane-apple.man sane-as6e.man \ sane-dll.man sane-dc25.man sane-dmc.man sane-epson.man \ sane-epson2.man sane-epsonds.man sane-hp.man sane-gphoto2.man sane-leo.man \ sane-lexmark.man sane-matsushita.man sane-microtek.man \ sane-microtek2.man sane-mustek.man sane-nec.man sane-net.man \ sane-pie.man sane-pieusb.man sane-pint.man sane-pnm.man sane-umax.man \ sane-qcam.man sane-scsi.man sane-artec.man sane-fujitsu.man \ sane-sharp.man sane-s9036.man sane-tamarack.man sane-kodak.man sane-kodakaio.man\ sane-ricoh.man sane-avision.man sane-plustek.man sane-st400.man \ sane-mustek_pp.man sane-dc210.man sane-v4l.man sane-snapscan.man \ sane-canon.man sane-coolscan.man sane-bh.man sane-dc240.man \ sane-umax_pp.man sane-umax1220u.man sane-sm3600.man sane-usb.man \ sane-mustek_usb.man sane-sceptre.man sane-canon_pp.man \ sane-canon630u.man sane-teco1.man sane-teco2.man \ sane-teco3.man sane-test.man sane-sp15c.man sane-coolscan2.man \ sane-hpsj5s.man sane-gt68xx.man sane-artec_eplus48u.man \ sane-ma1509.man sane-ibm.man sane-hp5400.man sane-plustek_pp.man \ sane-u12.man sane-niash.man sane-sm3840.man sane-genesys.man \ sane-hp4200.man sane-mustek_usb2.man sane-hp3500.man \ sane-pixma.man sane-stv680.man sane-hp5590.man sane-hpljm1005.man \ sane-cardscan.man sane-hp3900.man sane-epjitsu.man sane-hs2p.man \ sane-canon_dr.man sane-xerox_mfp.man sane-rts8891.man \ sane-coolscan3.man sane-kvs1025.man sane-kvs20xx.man sane-kvs40xx.man \ sane-p5.man sane-magicolor.man man7_MANS = sane.7 EXTRA_DIST += sane.man man8_MANS = saned.8 EXTRA_DIST += saned.man MANPAGES = $(man1_MANS) $(BACKEND_5MANS) $(man7_MANS) $(man8_MANS) if CROSS_COMPILING HTML_PAGES = else HTML_PAGES = sane-backends.html sane-backends-external.html \ sane-mfgs.html sane-mfgs-external.html endif doc_DATA = $(HTML_PAGES) all: bemans $(API_SPECS) html-pages dist_doc_DATA = backend-writing.txt nobase_dist_doc_DATA = $(BEDOCS) doc_DATA += $(API_SPECS) EXTRA_DIST += descriptions.txt releases.txt sane-logo2.jpg sane-logo.png \ sane.png MAN2HTML = nroff -c -man |\ man2html -compress -topm 6 -botm 6 -nodepage -title $${page} \ -cgiurl '$$title.$$section.html'|\ sed 's,,

,' %.1 %.5 %.7 %.8: %.man @echo "Generating manpage $@..."; @sed -e 's|@DATADIR@|$(datadir)|g' \ -e 's|@CONFIGDIR@|$(configdir)|g' \ -e 's|@DOCDIR@|$(docdir)|g' \ -e 's|@LIBDIR@|$(libdir)/sane|g' \ -e 's|@BINDIR@|$(bindir)|g' \ -e 's|@SBINDIR@|$(sbindir)|g' \ -e 's|@PACKAGEVERSION@|$(package_version)|g' $^ >$@ bemans: $(BACKEND_5MANS) beman5dir = $(mandir)/man5 install-beman5: $(BACKEND_5MANS) test -z "$(beman5dir)" || $(MKDIR_P) "$(DESTDIR)$(beman5dir)" @list="$(BACKEND_MANS_ENABLED) sane-dll.5 sane-scsi.5 sane-usb.5"; for man in $$list; do \ if test ! -r $${man}; then continue; fi; \ echo "installing $${man} in $(beman5dir)/$${man}..."; \ $(INSTALL_DATA) $${man} $(DESTDIR)$(beman5dir)/$${man} \ || exit 1; \ done BEDOCS = canon/canon.changes canon/canon.install2700F.txt BEDOCS += gt68xx/gt68xx.CHANGES gt68xx/gt68xx.TODO BEDOCS += leo/leo.txt BEDOCS += matsushita/matsushita.txt BEDOCS += mustek/mustek.CHANGES BEDOCS += mustek_usb/mustek_usb.CHANGES mustek_usb/mustek_usb.TODO BEDOCS += mustek_usb2/mustek_usb2.CHANGES mustek_usb2/mustek_usb2.TODO BEDOCS += niash/niash.TODO BEDOCS += plustek/FAQ plustek/MakeModule.sh plustek/Makefile.kernel24 \ plustek/Makefile.kernel26 plustek/Plustek-PARPORT-TODO.txt \ plustek/Plustek-PARPORT.changes plustek/Plustek-PARPORT.txt \ plustek/Plustek-USB-TODO.txt plustek/Plustek-USB.changes \ plustek/Plustek-USB.txt BEDOCS += sceptre/s1200.txt BEDOCS += teco/teco1.txt teco/teco2.txt teco/teco3.txt BEDOCS += u12/U12.changes u12/U12.todo BEDOCS += umax/negative-types.txt umax/sane-logo.jpg \ umax/sane-umax-advanced-options-doc.html \ umax/sane-umax-advanced.jpg umax/sane-umax-astra-doc.html \ umax/sane-umax-config-doc.html umax/sane-umax-doc.html \ umax/sane-umax-histogram.jpg umax/sane-umax-mirage-doc.html \ umax/sane-umax-not-listed-doc.html umax/sane-umax-others-doc.html \ umax/sane-umax-parport-doc.html umax/sane-umax-powerlook-doc.html \ umax/sane-umax-scanner-clones-doc.html umax/sane-umax-speed-doc.html \ umax/sane-umax-standard-options-doc.html \ umax/sane-umax-standard.jpg umax/sane-umax-text.jpg \ umax/sane-umax-text2.jpg umax/sane-umax-text4.jpg \ umax/sane-umax-uc-doc.html umax/sane-umax-vista-doc.html \ umax/sane-umax.jpg umax/umax.BUGS umax/umax.CHANGES umax/umax.FAQ \ umax/umax.TODO DESC_FILES = descriptions/abaton.desc descriptions/agfafocus.desc \ descriptions/apple.desc descriptions/artec.desc \ descriptions/artec_eplus48u.desc descriptions/as6e.desc \ descriptions/avision.desc descriptions/bh.desc descriptions/canon630u.desc \ descriptions/canon.desc descriptions/canon_dr.desc \ descriptions/canon_pp.desc descriptions/cardscan.desc \ descriptions/coolscan2.desc descriptions/coolscan.desc \ descriptions/coolscan3.desc \ descriptions/dc210.desc descriptions/dc240.desc descriptions/dc25.desc \ descriptions/dell1600n_net.desc descriptions/dll.desc descriptions/dmc.desc \ descriptions/epjitsu.desc descriptions/epson2.desc descriptions/epson.desc \ descriptions/epsonds.desc \ descriptions/fujitsu.desc descriptions/genesys.desc \ descriptions/gphoto2.desc descriptions/gt68xx.desc descriptions/hp3500.desc \ descriptions/hp3900.desc descriptions/hp4200.desc descriptions/hp5400.desc \ descriptions/hp5590.desc descriptions/hp.desc descriptions/hpljm1005.desc \ descriptions/hpsj5s.desc descriptions/hs2p.desc descriptions/ibm.desc \ descriptions/kodak.desc descriptions/kodakaio.desc descriptions/kvs1025.desc \ descriptions/kvs20xx.desc descriptions/kvs40xx.desc \ descriptions/leo.desc descriptions/lexmark.desc descriptions/ma1509.desc \ descriptions/magicolor.desc \ descriptions/matsushita.desc descriptions/microtek2.desc \ descriptions/microtek.desc descriptions/mustek.desc \ descriptions/mustek_pp.desc descriptions/mustek_usb2.desc \ descriptions/mustek_usb.desc descriptions/nec.desc descriptions/net.desc \ descriptions/niash.desc descriptions/pie.desc descriptions/pieusb.desc descriptions/pint.desc \ descriptions/p5.desc descriptions/pixma.desc descriptions/plustek.desc \ descriptions/plustek_pp.desc descriptions/pnm.desc descriptions/qcam.desc \ descriptions/ricoh.desc descriptions/rts8891.desc descriptions/s9036.desc \ descriptions/sceptre.desc descriptions/sharp.desc descriptions/sm3600.desc \ descriptions/sm3840.desc descriptions/snapscan.desc descriptions/sp15c.desc \ descriptions/st400.desc descriptions/stv680.desc descriptions/tamarack.desc \ descriptions/teco1.desc descriptions/teco2.desc descriptions/teco3.desc \ descriptions/test.desc descriptions/u12.desc \ descriptions/umax1220u.desc descriptions/umax.desc \ descriptions/umax_pp.desc descriptions/unsupported.desc \ descriptions/v4l.desc descriptions/xerox_mfp.desc EXTRA_DIST += $(DESC_FILES) descriptions/template.desc. DESC_EXT_FILES = descriptions-external/brother2.desc \ descriptions-external/brother.desc \ descriptions-external/brother-mfc4600.desc \ descriptions-external/canon_mfp.desc \ descriptions-external/cs3200f.desc \ descriptions-external/epkowa.desc \ descriptions-external/geniusvp2.desc \ descriptions-external/hp3770.desc \ descriptions-external/hp8200.desc \ descriptions-external/hpaio.desc \ descriptions-external/hpoj.desc \ descriptions-external/kodak-twain.desc \ descriptions-external/lhii.desc \ descriptions-external/mustek_a3p1.desc \ descriptions-external/panamfs.desc \ descriptions-external/primascan.desc \ descriptions-external/primax.desc \ descriptions-external/samsung.desc \ descriptions-external/scanwit.desc \ descriptions-external/utsushi.desc \ descriptions-external/v4l2.desc \ descriptions-external/viceo.desc EXTRA_DIST += $(DESC_EXT_FILES) descriptions-external/template.desc. install-data-local: install-beman5 uninstall-local: rm -rf $(DESTDIR)$(beman5dir)/sane-*.5 ## SANE API specification format conversion support API_SPECS = if WITH_API_PS API_SPECS += sane.ps endif if WITH_API_PDF API_SPECS += sane.pdf endif if WITH_API_HTML API_SPECS += sane-html endif API_SPEC_INPUTS = $(srcdir)/sane.tex API_SPEC_INPUTS += $(srcdir)/net.tex EXTRA_DIST += $(API_SPEC_INPUTS) API_SPEC_TEX_FIGS = API_SPEC_TEX_FIGS += figs/area.fig API_SPEC_TEX_FIGS += figs/flow.fig API_SPEC_TEX_FIGS += figs/hierarchy.fig API_SPEC_TEX_FIGS += figs/image-data.fig API_SPEC_TEX_FIGS += figs/xfer.fig EXTRA_DIST += $(API_SPEC_TEX_FIGS) API_SPEC_EPS_FIGS = API_SPEC_EPS_FIGS += figs/area.eps API_SPEC_EPS_FIGS += figs/flow.eps API_SPEC_EPS_FIGS += figs/hierarchy.eps API_SPEC_EPS_FIGS += figs/image-data.eps API_SPEC_EPS_FIGS += figs/xfer.eps API_SPEC_PDF_FIGS = API_SPEC_PDF_FIGS += figs/area.pdf API_SPEC_PDF_FIGS += figs/flow.pdf API_SPEC_PDF_FIGS += figs/hierarchy.pdf API_SPEC_PDF_FIGS += figs/image-data.pdf API_SPEC_PDF_FIGS += figs/xfer.pdf ## These icons are referred to in the generated HTML output. API_SPEC_HTML_ICONS = API_SPEC_HTML_ICONS += icons/contents.gif API_SPEC_HTML_ICONS += icons/index.gif API_SPEC_HTML_ICONS += icons/next.gif icons/next_gr.gif API_SPEC_HTML_ICONS += icons/previous.gif icons/previous_gr.gif API_SPEC_HTML_ICONS += icons/references.gif icons/references_gr.gif API_SPEC_HTML_ICONS += icons/up.gif icons/up_gr.gif EXTRA_DIST += $(API_SPEC_HTML_ICONS) am_TEXINPUTS = TEXINPUTS="$(builddir):$(srcdir):$$TEXINPUTS" sane.ind: $(API_SPEC_INPUTS) @echo Generating index for $<... @touch sane.ind @$(am_TEXINPUTS) $(LATEX) $< /dev/null && \ $(MAKEINDEX) -q sane.idx && \ $(am_TEXINPUTS) $(LATEX) $< /dev/null .fig.eps: @test -d $(@D) || $(MKDIR_P) $(@D) $(FIG2DEV) -L eps $< $@ sane.dvi: $(API_SPEC_INPUTS) $(API_SPEC_EPS_FIGS) sane.ind @echo Generating $@ from $<... @$(am_TEXINPUTS) $(LATEX) $< /dev/null sane.ps: sane.dvi @echo Generating $@ from $<... @$(am_TEXINPUTS) $(DVIPS) -q $< -o $@ .fig.pdf: @test -d $(@D) || $(MKDIR_P) $(@D) $(FIG2DEV) -L pdf $< $@ sane.pdf: $(API_SPEC_INPUTS) $(API_SPEC_PDF_FIGS) sane.ind @echo Generating $@ from $<... @$(am_TEXINPUTS) $(PDFLATEX) $< >/dev/null sane-html: sane.dvi $(am_TEXINPUTS) $(DLH) $(srcdir)/sane.tex ## ^^ html-man: $(MANPAGES) @for page in $(MANPAGES); do \ echo "translating $${page} to $${page}.html..."; \ cat $${page} | $(MAN2HTML) > $${page}.html; \ done ../tools/sane-desc: cd ../tools ; $(MAKE) sane-desc sane-backends.html: $(DESC_FILES) ../tools/sane-desc @../tools/sane-desc -m html-backends-split -s ${srcdir}/descriptions \ -i "The following table summarizes the backends/drivers distributed \ with $(PACKAGE)-$(VERSION), and the hardware or software they \ support." -d 0 > sane-backends.html sane-backends-external.html: $(DESC_EXT_FILES) ../tools/sane-desc @../tools/sane-desc -m html-backends-split \ -s ${srcdir}/descriptions-external \ -i "The following table summarizes the backends/drivers that \ have not yet been included in the SANE distribution, and the \ hardware or software they support." \ -t "SANE: External Backends (Drivers)" -d 0 \ > sane-backends-external.html sane-mfgs.html: $(DESC_FILES) ../tools/sane-desc @../tools/sane-desc -m html-mfgs -s ${srcdir}/descriptions \ -i "The following table summarizes the devices supported \ by $(PACKAGE)-$(VERSION)." \ -d 0 > sane-mfgs.html sane-mfgs-external.html: $(DESC_EXT_FILES) ../tools/sane-desc @../tools/sane-desc -m html-mfgs -s ${srcdir}/descriptions-external \ -i "The following table summarizes the devices that \ are supported by external backends." \ -t "SANE: Devices Supported by External Backends" -d 0 \ > sane-mfgs-external.html descriptions.db: $(DESC_FILES) ../tools/sane-desc @../tools/sane-desc -m ascii -s ${srcdir}/descriptions \ > descriptions.db descriptions-external.db: $(DESC_EXT_FILES) ../tools/sane-desc @../tools/sane-desc -m ascii -s ${srcdir}/descriptions-external \ > descriptions-external.db html-pages: $(HTML_PAGES) html-local: html-pages html-man sane-html clean-local: rm -f *.toc *.aux *.log *.cp *.fn *.tp *.vr *.pg *.ky *.blg *.idx *.cb rm -f *.ilg rm -f $(API_SPEC_EPS_FIGS) $(API_SPEC_PDF_FIGS) -rmdir figs distclean-local: rm -f $(MANPAGES) rm -f *.lot *.lof *.ind rm -f sane.dvi sane.ps sane-backends.html sane-backends-external.html rm -f sane-mfgs.html sane-mfgs-external.html rm -f sane/*.html sane/*.gif rm -f doxygen-sanei.conf doxygen-genesys.conf -rm -rf sane sanei-html for manpage in $(MANPAGES) ; do \ rm -f $${manpage}.html ; \ done sane-backends-1.0.27/doc/sane-stv680.man0000664000175000017500000001110112112021330014435 00000000000000.TH sane\-stv680 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-stv680 .SH NAME sane\-stv680 \- SANE backend for STV680 camera's .SH DESCRIPTION The .B sane\-stv680 library implements a SANE (Scanner Access Now Easy) backend that provides access to some STV680 cameras. This backend should be considered .B beta-quality software! STV680 cameras are sold under various brands like Aiptek. This backend may or may not support yours. .PP The cameras that should work with this backend are: .PP .ft CR .nf Vendor Model USB vendor id USB product id status ------------------------ ------------- -------------- -------- AIPTEK stv680 0x0553 0x0202 basic Konica e-mini 0x04c8 0x0722 untested DigitalDream l'espion XS 0x1183 0x0001 untested Creative WebCam Go mini 0x041e 0x4007 untested .fi .ft R For all these cameras, see the backend home page (under AUTHOR) for the exact status of each camera. For startup of this backend check that if present the stv680 kernel module is removed or disabled. .br Also before using, enable the backend by editing the /etc/sane.d/dll.conf file, change #stv680 to stv680. For problems with the untested cameras, you should contact the author for that. The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xcam. For both programs use the \-B option needed for size buffer. Some frontends examples: .br xcam .RS xcam \-B .RE scanimage: for writing in batch mode to a file or to a new file each time. .RS scanimage \-B \-d stv680:libusb:001:002 \-\-batch=out.ppm \-\-batch-count 5 \-\-mode "Color RGB" .RE .RS scanimage \-B \-d stv680:libusb:001:002 \-\-batch=out%d.ppm \-\-batch-count 5 \-\-mode "Color RGB" .RE .br If you have any success with a camera not listed here, or if you have any strange behavior, please report to the backend maintainer or to the SANE mailing list. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d stv680 .RE .TP .B Scan Mode .TP .B \-\-mode selects the basic mode of operation of the webcams valid choices. The read resolution mode is 8 bits, output resolution is 24 bits. Selects the resolution for a scan. The camera can do only the resolutions listed. .TP .B \-\-Raw In this mode raw data is displayed .TP .B \-\-Color In this mode the bayer unshuffle is done but no color correction .TP .B \-\-Color_RGB Bayer unshuffle, color correction .TP .B \-\-Color_RGB_TXT Bayer unshuffle, color correction, textline with date and time is added .TP .B Enhancement options .TP .B \-\-white\-level\-r Selects what red radiance level should be considered "white", when scanning some sheets by changing the calibration value loaded into the scanner. Scale \-32 .. 0 .. +32 in steps of 1. .TP .B \-\-white\-level\-g Selects what green radiance level should be considered "white", when scanning some sheets by changing the calibration i value loaded into the scanner. Scale \-32 .. 0 .. +32 in steps of 1. .TP .B \-\-white\-level\-b Selects what blue radiance level should be considered "white", when scanning some sheets by changing the calibration value loaded into the scanner. Scale \-32 .. 0 .. +32 in steps of 1. .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/stv680.conf supports only one information: the device name to use (eg usb 0x.... 0x....). .SH FILES .TP .I @LIBDIR@/libsane\-stv680.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-stv680.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_STV680 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH LIMITATIONS The windows TWAIN driver has many more options than this SANE backend. However they are only software adjustments. This backend only implements what the webcam can support. .SH BUGS .TP Plenty. Parts of this backend are still under development. 1. Some untested cameras. .br 2. Video streaming slow and stops sometimes (scanimage). .br 3. Sometimes 1/3 of image is NOK (xcam). .SH "SEE ALSO" sane\-usb(5), scanimage(1), xcam(1), sane(7) .SH AUTHORS Gerard Klaver http://gkall.hobby.nl/stv680-aiptek.html .SH CREDITS .TP Thanks to developers of the other stv680 programs: STV680 kernel module .br pencam2 program .br libghoto2 program (camlib stv0680) sane-backends-1.0.27/doc/backend-writing.txt0000664000175000017500000005324412775312261015616 000000000000002006-01-01 Here are a few rules and tips that should help writing a SANE-conforming backend and including it into the SANE package: GETTING STARTED --------------- * You will need information about the protocol the scanner (or other image application device) is using. The easiest way is to ask the manufacturer about it. You should mention that the code will be open-source, however. * Read the SANE standard. * One approach is to write a stand-alone scanning program first. Debugging this program is usually easier than using the SANE libraries. However, keep in mind what you learned from the SANE standard. * Once your program works basically, insert its functions into a basically empty SANE backend. You can get one by removing everything but the SANE includes and SANE API function definitions from an existing backend (e.g. test.c). * If you have any information about the scanner you want to support that is not already mentioned in one of the .desc files, please contact the sane-devel mailing list. Especially if you have written code (e.g. a test program) or started writing a backend, contact us. * Keep other users informed about what you did and want to do. This way no work is done twice and you may get volunteers for coding or testing. Set up a website or at least write to sane-devel. If you have a website, a link to it can be included in the .desc file and users looking for that scanner will find it on the SANE website. * When you have a working backend but you don't want to have it included in the SANE distribution yet, at least the .desc file can be included (see below for details). So people will find a link to your backend at the SANE webpage. CONFIGURATION AND BUILD SYSTEM ------------------------------ Sane-backends uses the autoconf and automake tools. The configure script is generated from configure.ac and aclocal.m4 by running "autoreconf". Simple checks (e.g. for headers) should be placed into configure.ac while for more complex stuff acinclude.m4 is the right file. After changes in one of these files, "autoreconf" should be called. This will then call a chain of autotools, such as autoconf to generate configure, autoheader to generate include/sane/config.h.in, and automake to generate various Makefile.in's from Makefile.am's. All changes made by "autoreconf" must be commited together. When running configure, the Makefiles in the main and sub-directories are created from their respective Makefile.in files. Also include/sane/config.h which is included into to every c file is created from its .in file. Running "make" runs the respective targets in the sub directories recursively. The Makefile.am in each directory contains lists of files which are part of the distribution and which are therefore copied to the tar.gz archive, when a release is made. It's important that newly added files are also added to a variable that will cause them to be distributed (EXTRA_DIST at a minimum). For creating binaries and libraries libtool is used. The ltmain.sh script contains special modifications for SANE. These modifications ensure that the soname of each SANE backend library is "libsane.so". Without this change, backend libraries (like "libsane-epson.so") could not used as on-the-fly replacement for the dll backend. DIRECTORY OVERVIEW ------------------ This chapter explains some details about the files and directories used in the sane-backends distribution. sane-backends/ * acinclude.m4 aclocal.m4 compile config.guess config.sub configure configure.ac depcomp install-sh ltmain.sh Makefile.am Makefile.in missing mkinstalldirs: Part of the build system as explained above. * ChangeLog: The ChangeLog contains all the changes made since the last stable release. If anything is changed in git, write a decent commit message documenting your work. This commit message will be included as is in the ChangeLog file for the next stable release. Users of development code should refer to the `git log` output or the on-line log. For more details on the format, see the SANE git page on the website. * ChangeLog-1.0.0, ChangeLog-1.0.1 (...): These files contain the ChangeLogs of older releases. Once a new release has been made, the current ChangeLog renamed to ChangeLog-1.something.something and a new empty ChangeLog is created. * AUTHORS COPYING INSTALL LICENSE: General documentation + license. * NEWS: This is some kind of executive summary of the ChangeLog. It will be created before a release. * PROBLEMS: General (severe) problems that all SANE users should be aware. Backend-specific trouble should normally not mentioned there. * PROJECTS: Planned SANE-related development (e.g. ports, frontends). New backends won't be listed here but a new .desc file will be created for them (see below). * README: General building instructions. * README.aix README.beos (...): Platform-dependent building and usage instructions. * sane-backends.lsm: The .lsm file as used for the ibiblio archive. sane-backends/backend/ This is where the actual backend code is placed. As an example the file structure for a backend named "newbackend" is listed below. Backend names must be unique and should not contain any special characters. Lower case letters, numbers and underscores "_" are ok. Backend documentation of any kind should not be placed here but in the doc/ directory. Code which is useful for more than one backend should be placed in sanei/ instead. * newbackend.c: The main backend file, usually contains the SANE API code. Mandatory. * newbackend.h: Header file, containing includes and so on. * newbackend.conf.in: Configuration file for the backend, newbackend.conf will be created by running "make" from this file. Some variables are substituted, e.g. for installation directories. This is especially useful for firmware directories. See Makefile.am for a list. * newbackend-low.c: Contains low level code for the "newbackend" backend. Depending on the complexity of the backend, splitting it to several files can be appropriate, the total number of files shouldn't exceed approx. 10, however. Other files: * Makefile.am, Makefile.in: Makefile.am contains rather complex rules for building the backends. For adding backends, special care should be taken concerning the FIRMWARE_DIRS (add your backend name here, if your scanner needs firmware files) and other variables (see build system description). There is some documentation inside of Makefile.am on what needs to be added and where. At a minimum, a convenience library of form lib${backend}.la and a installed library libsane-${backend}.la must be defined. Any sanei objects referenced should be listed in a libsane_${backend}_la_LIBADD line. * sane_strstatus.c: Contains the code for the sane_strstatus() function to avoid code duplication in every backend. sane-backends/doc/ Documentation for SANE. For some more details, see chapter DOCUMENTATION below. Again an example for "newbackend": * sane-newbackend.man: The manual page of the backend. From this file, "sane-newbackend.5" is generated by running "make". * newbackend/ (directory) Contains additional information about newbackend, e.g. READMEs or TODO files. General files: * Makefile.am: "sane-newbackend.5" must be added to variable BACKEND_5MANS and "sane-newbackend.man" to EXTRA_DIST. A backend documentation directory (if used) must be added to the BEDOCS variable. * backend-writing.txt: This file. * descriptions.txt: Describes the format of .desc files. * doxygen-sanei.conf.in: Used by doxygen to create the documentation of the sanei code. * releases.txt: Explains how to make releases of sane-backends. * sane.tex, net.tex: Contains the LaTeX source of the SANE standard. * descriptions/ (directory) Contains the .desc files for every backend that is included into sane-backends. * descriptions-external/ (directory) Contains the .desc files for backend that are not included into sane-backends yet (external backends). These files should only be created if the code it points to is really a SANE backend (and not just a command line program). sane-backends/frontend/ Contains the frontends scanimage, saned, and tstbackend. sane-backends/include/ Header files used by the SANE backends. The main directory contains the headers used for general librar functions like getopt, while the SANE-specific headers are located in include/sane/: * config.h.in: Main header file needed for portablility. config.h is created from this file and must be included by every backend. * sane.h: Official SANE API header file. Don't change this without discussion on the sane-devel mailing list. * saneopts.h: Defines several option NAMEs, TITLEs and DESCs that are (or should be) used by several backends. * sanei_*: Sanei (SANE internal) headers. Needed for code used in several backends like USB access. For more details, see the documentaion on the SANE website. sane-backends/japi/ Contains Java interface for SANE. See README.JAVA for details. sane-backends/lib/ Contains various library functions that may miss in the standard C library of some platforms. sane-backends/po/ Translations of SANEbackend options. See README for details. sane-backends/sanei/ Sanei (SANE internal) code. Needed for code used in several backends like USB access. For more details, see the documentaion on the SANE website. sane-backends/testsuite/ Testsuite for SANE. See README for details. sane-backends/tools/ Contains several tools for SANE. There are backend-specific and general command line tools as well as the hotplug support and .desc file generation code. See README for details. PROGRAMMING ----------- * A backend library is always only one file (libsane-backendname.so). Please do not use multiple libraries e.g. for lower and higher level code. * To add the backend to the existing SANE code, the following must be done at least: - add the backend name to ALL_BACKENDS in configure.ac (and run autoreconf) - Add new backend to BACKEND_CONFS, be_convenience_libs, be_dlopen_libs, and define _lib${backend}_la_SOURCES and nodist_libsane_${backend}_la_SOURCES; using an existing backend as a template. Any sanei reference code should be listed in libsane_${backend}_la_LIBADD as well as any external libraries required to resolve all symbols. - Add the source code files to the backend/ directories. All file names must start with the backend name (e.g. newbackend.c, newbackend.h and newbackend-usb.c). * Please follow the GNU coding standards. It's clear that the style outlined there is nobody's favorite, but it's much easier to maintain SANE if everybody follows more or less the same coding style. It also looks more professional. The GNU standards can be found at: http://www.gnu.org/prep/standards_toc.html ftp://ftp.gnu.org/pub/gnu/standards/standards.text Note that GNU emacs supports automatic indentation according to this standard. The command "indent -gnu" can be used to reformat existing sources according to this standard. * Please be courteous to programmer's with terminals that are 80 characters wide. It's not difficult to avoid long lines, so please do so. Note that in standard C you can split long strings into pieces separated by white space. For example, "this is an awfully long string" can be written as "this is an " "awfully long string". * Use only standard C for your backend. ISO C99 support will be enabled if supported by the compiler detected by configure. * Please do not depend on compiler specific features or, if you do, make the dependency conditional so other compilers will still be able to compile the files. In particular: - do not declare dynamically sized automatic arrays; instead, use alloca() after including "../include/lalloca.h". For example: void func (int n) { char buf[n]; } should be re-written as: #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" : void func (int n) { char *buf = alloca (n); } - Don't use any #pragma directives---they're completely compiler-dependent. * If you use headers or libraries that may not be available on all systems, write a check for configure.ac and include it conditionally. If your backend depends on these libraries or headers, compile the backend only if they are available (see pint for an example). * Use #include ".../include/sane/..." to include the sane header files instead of #include . Otherwise problems with different installed SANE versions may occur. Also this makes clear that the local files are used. * Don't forget to #include ".../include/sane/config.h" in your backend before any other includes. This must be done for any .c file that generates its own object file. If you use lalloca.h see above for the correct includes. * Include sanei_backend.h after the other includes. * It's no longer necessary to #define PATH_MAX (now in sanei_backend.h). If you define it, do so *after* the system includes. * Please use sanei functions whenever possible (e.g. sanei_config_read()). This makes porting to other os/platforms much easier. Most of these functions are documented in their respective header files in include/sane/sanei_*.h. For most of them there is also documentation in doxygen format: http://www.sane-project.org/sanei/. These HTML pages can be generated by calling "doxygen sanei-doxygen.conf" in the doc/ directory. * Initialize global variables explicitly in sane_init. Keep in mind that sane_init can be called more than once (if sane_exit is called everytime after sane_init). Therefore don't depend on automatic initialization to 0 / NULL. * Do make sure that your code is byte-order independent. This is particularly important for networking-related code and when dealing with non-textual data files. * Don't use printf, fprintf or perror to output debug or error messages. Use the DBG macro instead. If your backend can't detect a scanner for whatever reason it shouldn't output anything as long as SANE_DEBUG_BACKENDNAME isn't set. So don't use DBG(0, ...) in this case. * Please do not assume that `size_t' is `unsigned int'. On some systems, it's `unsigned long' and the size of this type may be bigger than that of an int (this is true for practically any of the 64-bit systems). To print a variable of type size_t portably, cast the variable to u_long and print it with the %lu specifier. E.g.: size_t len; DBG(3, "len=%lu\n", (u_long) len); * Please do not assume that `void *' has the same size as `int'. On some systems, it's `long' and the size of this type may be bigger than that of an int (this is true for practically any of the 64-bit systems). Where this comes up is with opaque handles. For example: int OpaqueHandle; MyScanner *s = (MyScanner *)OpaqueHandle; will FAIL on most 64 bit systems. Please use `void *' or better `SANE_Handle'. * Don't use exit() in your backend. You will exit the whole program, not only your backend. * If you use wait() or waitpid() in your backend, check its return value. This is important, if the status value is checked for e.g. WIFEXITED after the call of wait() or waitpid(). Both functions may fail if the frontend already did a wait for the children. * Please try to avoid compilation warnings. At least with "--disable-warnings" there shouldn't be warnings when compiling backends. It's not necessary to fix every "unused parameter" warning but take care that no warnings pointing to really existing problems or ambiguities are missed. Some programming techniques generating warnings on gcc may lead to errors on other systems. * To support translation of SANE options, please mark the descriptions (desc) and title of options with SANE_I18N() and add all files using SANE_I18N() to po/POTFILES. See po/README for details. * Please check for TL_X < BR_X and TL_Y < BR_Y to avoid segfaults or even scanner damage. This should NOT be done in sane_control_option, it should be possible to temporary set TL_X > BR_X or TL_ > BR, otherwise it is hard for a frontend to set the correct values. TESTING ------- * Please test a backend with "scanimage -T" (plus other options, as appropriate/necessary) as this will make sure that sane_read() always returns the correct amount of data etc. * You can also test a backend with tstbackend. tstbackend is not compiled nor installed by default. To do that, cd into frontend and run "make tstbackend". * Please test a backend not just with scanimage and xscanimage (+ other frontends), but also with saned. Based on past experience, it is often the case that remote scanning can uncover subtle bugs. Note that you don't have to use two different machines to test "remote" scanning---you can use one and the same machine to test a backend via saned (just be sure to enable the "net" backend in dll.conf and follow the steps described in saned(8)). * Please test on every available platform/os. Even if no scanner is attached to this system, test compilation and running scanimage. If you don't have access to other platforms, ask sane-devel. * Please make sure that all global symbols exported from a SANE backend start with the prefix "sane" or "sanei" to avoid clashes with exported symbols of other backends. Only symbols mentioned in the SANE standard should start with "sane_*". Make sure, the sanei_* symbols are unique, e.g. by using sanei_backendname_*. Only export symbols that are absolutely necessary. You can verify this by running GNU "nm" on the static library. For example: nm -g backend/.libs/libsane-hp.a would list all global symbols in the HP backend. "./configure; make; make libcheck" in the sane-backends root directory will name all backend libraries, that contain "illegal" symbols. DOCUMENTATION ------------- * Even if you haven't written a man-page for your backend yet, you *must* create a .desc file which describes it. Anytime you submit source code for your backend, you should include an update to the .desc file which reflects the new state of the backend. The .desc files are used to create the HTML lists of supported devices. These lists are updated automatically when you change a .desc file in git. See e.g. http://www.sane-project.org/lists/sane-mfgs-cvs.html for the results. * The .desc files are located in the directories "doc/descriptions" and "doc/descriptions-external" (for included and external backends). * "doc/descriptions.txt" describes the format of the ".desc" files. There is also a template for new .desc files: "template.desc.". The format of the files in the two directories is very similar. If you'd like to try parsing your creation to recreate the sane-backends webpages, cd into "tools/" and enter "make sane-desc". You can either use sane-desc directly (try "./sane-desc -h") or use "make html-pages" in "doc/". * For external backends, you don't need to supply :manpage and :version. The manpage link won't work anyway and version will be outdated soon. * When your backend is included in the SANE distribution, add an entry to doc/sane.man, AUTHORS and sane-backends.lsm. The sane.man entry should point to your documentation (man-page, website, readme). Also move your .desc file from "doc/descriptions-external" to "doc/descriptions" and update them. * In your manual page (backend.man), use @LIBDIR@ and the other macros for path names to the libraries, config files and documentation. Don't use fixed paths as they will be wrong if SANE is installed with a different prefix (e.g. /usr instead of /usr/local). * If you want to include READMEs, HTML files or other documentation, please create your own directory (doc/backendname) and store your files in this directory. If you only have a manual page a subdirectory isn't necessary. * Please keep your manpages and .desc files up-to-date especially regarding version numbers. CHECKLIST: SUBMITTING A NEW BACKEND ----------------------------------- In sane-backends/ * Add the author(s) name(s) to AUTHORS * Correct any related entries in the bug-tracking system In sane-backends/backend/ * Use the command "indent -gnu" to reformat your code according to the standard. * Add the backend name to dll.conf * Check that the SANE license is in the backend source files. * Add the source file names and the .conf file to BACKEND_CONFS in Makefile.am In sane-backends/doc/ * Add an entry for the man page in sane.man * Add the man page file in doc/Makefile.am * Move the description file from descriptions-external/ to doc/descriptions/ * Check that the description file is correct: "cd doc; make html-pages" and check the html pages result with a browser. * Check that the backend version is the same in the source and in the description file. In sane-backends/po/ * Add all files using SANE_I18N() to po/POTFILES INCLUDING INTO git ------------------ * If you want to include your backend into SANE's git tree use the latest git to make patches. Check the mailing list and the bug-tracking system for information about bugs to avoid. * If your backend isn't included yet in the SANE's git tree, write an email to the SANE mailing list (sane-devel) and ask for inclusion. Usually one of the developers will check the backend for common mistakes and test compilation. If everything is ok the backend will be added to the git tree. sane-backends-1.0.27/doc/canon/0000775000175000017500000000000013110600532013134 500000000000000sane-backends-1.0.27/doc/canon/canon.install2700F.txt0000664000175000017500000001150212112021330016770 00000000000000 ----------------------------------------------------------------------- How to install a CanoScan 2700F on a Linux box ? by Stephan Hegel . Date: Fri Jan 15 16:13:15 MEZ 1999 ----------------------------------------------------------------------- Here is a short description on how to install the CanoScan 2700F film and slide scanner on a Linux box. Actually it was just written as a reminder for myself but I think it is a good idea to add it to Manuel Panea's Canon backend package. Please remember that there is NO GUARANTEE that this step by step instruction works also for you. Corrections and suggestions are welcome, of course. Thank you. 1. How to install an Adaptec AVA-1502AP ? ----------------------------------------- The AVA-1502AP is is a small ISA Adaptec SCSI controller which is shipped with the CanoScan slide scanner. Per default is has the address 0x140, the IRQ 10 and the SCSI host id 7. Check first for conflicts with your already existing hardware. Install the controller into the computer. After starting the BIOS should detect the board as a PNP board. Boot the computer with the "SCSISelect" disk which is shipped with the scanner to check that the controller is detected. Don't change any settings except address, IRQ or SCSI id if necessary. Configure a new Linux kernel (version 2.0.30 or newer) with: SCSI Support (yes) SCSI Generic support (yes) Low level driver for aha152x (yes) Note: here you can try to compile the SCSI support as modules as long as you don't boot the computer from a SCSI disk. But this is not tested. Compile and install the new Linux kernel. Add "aha152x=0x140,10,7" to the "append" line to the already existing kernel parameters in lilo.conf, e.g: ------------------- # Linux bootable partition config begins image = /vmlinuz root = /dev/hdc1 label = linux append = "sbpcd=0x230,SoundBlaster aha152x=0x140,10,7" # Linux bootable partition config ends ------------------- Invoke lilo to activate the changes. Reboot the computer and watch the boot messages. The SCSI host adapter should be there now. 2. How to connect the scanner ? ------------------------------ Shutdown and turn off the computer, connect the scanner with the SCSI cable to the SCSI adapter. Set the SCSI Id with the turn-switch at the back of the scanner body. I'm using SCSI Id 1 with "termination on" since the scanner is the one and only device connected to my host adapter. Turn on the scanner first and wait for a few second. The scanner performs a short self test. Turn on the computer. Watch the boot messages, there should be a message indicating that the SCSI host adapter and the scanner are there. Now you can check again that the scanner device is there: cat /proc/scsi/scsi Should print something like that: Host: scsi0 Channel: 00 Id: 01 Lun: 00 Vendor: CANON Model: IX-27015C Rev: 1.17 Type: Scanner ANSI SCSI revision: 02 3. How to install SANE for the Canon 2700 film scanner ? -------------------------------------------------------- Fetch the latest SANE distribution from the SANE homepage at: http://www.sane-project.org/ Unpack and configure it. Get the latest canon backend from Manuel's homepage: http://www.rzg.mpg.de/~mpd/sane Put the files in the sane/backend directory as described in the README of the package. This overwrites the existing canon.* files with the latest version of these files. Compile and install SANE. Add the "canon" scanner to the /usr/local/etc/sane.d/dll.conf file: -------- cut here ------------ # enable the next line if you want to allow access through the network: #net pnm #mustek #hp #qcam #umax canon -------- cut here ------------ Add a "canon.conf" file to the /usr/local/etc/sane.d directory: -------- cut here ------------ scsi CANON -------- cut here ------------ Check the available scanners: scanimage -L This should give something like this: device `canon:/dev/sg0' is a CANON IX-27015C film scanner device `pnm:0' is a Noname PNM file reader virtual device device `pnm:1' is a Noname PNM file reader virtual device Invoke the frontend: xscanimage & NOTE: The "xscanimage" frontend is in the SANE distribution. There is also another SANE frontend available which is called "xsane" by Oliver Rauch. It is still under heavy development and can be grabbed from: http://www.wolfsburg.de/~rauch A dialog box appears, select the canon scanner and here we go ... Happy scanning !!! ----------------------------------------------------------------------- sane-backends-1.0.27/doc/canon/canon.changes0000664000175000017500000000246312112021330015503 00000000000000 Version 991108: * Negative mask removal. This is a major change. Negatives get scanned *a lot* better now, meaning that you get good-looking colors. * Select native scanning resolutions, contributed by Stefan Scherer . * Support for Automatic Document Feeder (ADF), contributed by Jonathan Adams . * Corrected some namings of variables which caused problems when using the backend with 'xsane' or with the command-line 'scanimage'. I have not tested it myself with 'xsane' yet. * For your information, and because some users had problems with the previous versions and some kernels, I use kernel 2.2.12 and have SCSI support as modules (the modules which I have to load before using the scanner are scsi_mod, aha152x and sg). =========================================================================== Version 990201: * New code for the transparency unit by Markus Mertinat. * "Manual focus" was there, but I had not noticed that it didn't really work. Now it does. * Changed the names of some options, because xscanimage worked ok, but not scanimage. * When using high resolutions, "Auto Exposure" for slides is now much faster because it sets the resolution down first. * I have included a new directory containing scripts I find useful. sane-backends-1.0.27/doc/sane-lexmark.man0000664000175000017500000001067712775277260015105 00000000000000.TH "sane\-lexmark" "5" "12 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-lexmark .SH "NAME" sane\-lexmark \- SANE backend for Lexmark X1100/X1200 Series scanners .SH "DESCRIPTION" The .B sane\-lexmark library implements a SANE (Scanner Access Now Easy) backend that provides access to the scanner part of Lexmark X1100/X1200 AIOs. This backend should be considered .B beta-quality software! .PP The scanners that should work with this backend are: .PP .RS .ft CR .nf Vendor Model status \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\- Lexmark X74 good Lexmark X1110 untested Lexmark X1140 untested Lexmark X1150 good Lexmark X1170 good Lexmark X1180 good Lexmark X1185 complete Lexmark X12xx good in USB1.1, not fully tested in USB2.0 Dell A920 good .fi .ft R .RE The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage or xsane. .br If you have any strange behavior, please report to the backend maintainer or to the SANE mailing list. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d lexmark:usb: .RE .TP .B Scan Mode Options .TP .B \-\-mode selects the basic mode of operation of the scanner valid choices are .IR Color , .I Gray and .I Lineart The default mode is Color. The Lineart mode is black and white only (1 bit). Grayscale will produce 256 levels of gray (8 bits). Color mode allows for over 16 million different colors produced from 24 bits of color information. .TP .B \-\-resolution selects the resolution for a scan. The horizontal and vertical resolutions are set by the value of this option. The scanner is capable of the following resolutions for the specified option value: .PP .RS .ft CR .nf Value Hor. Resolution Vert. Resolution \-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- 75 75dpi 75dpi 150 150dpi 150dpi 300 300dpi 300dpi 600 600dpi 600dpi 1200 600dpi 1200dpi (only for X11xx models with 'B2' sensor) .fi .ft R .RE .TP .B \-\-preview requests a preview scan. The resolution used for that scan is 75 dpi and the scan area and the scan mode are as specified through their options, or the default if not specified. The default value for preview mode is "no". .TP .B \-\-threshold selects the minimum-brightness to get a white point. The threshold is only used with Lineart mode scans. It is specified as a percentage in the range 0..100% (in steps of 1). The default value of the threshold option is 50. .SH "CONFIGURATION FILE" The configuration file @CONFIGDIR@/lexmark.conf contains only the usb device id (eg usb 0x043d 0x007c). .SH "FILES" .TP .I @LIBDIR@/libsane\-lexmark.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-lexmark.so The shared library implementing this backend (present on systems that support dynamic loading). .SH "ENVIRONMENT" .TP .B SANE_DEBUG_LEXMARK .B SANE_DEBUG_LEXMARK_LOW If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 255 requests all debug output to be printed. Smaller levels reduce verbosity. .SH "LIMITATIONS" The windows TWAIN driver has many more options than this SANE backend. However they are only software adjustments. This backend only implements what the scanner can support. For instance, shading correction (vertical stripes due to sensor variation across its width) is done in software. Head park position is also detected by software. The data compression isn't supported for the X1200 series on USB 1.1, leading to slow scans. .SH "BUGS" .br No bugs currently known. .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1), sane(7) .SH "AUTHOR" .TP The backend was originally written by Fred Odendaal. .I http://ca.geocities.com/freshshelf@rogers.com/ .TP The new version is currently developed by St\['e]phane Voltz. .I http://stef.dev.free.fr/sane/lexmark .TP X74 support was written by Torsten Houwaart () .SH "CREDITS" .TP Many thanks go to: Julien Furgerot who lend me a Dell A920. Robert Price, Dani Ele and Dalai Felinto for the time they spent recording USB activity and testing the experimental version. sane-backends-1.0.27/doc/sane-hpsj5s.man0000664000175000017500000000664112112021330014614 00000000000000.TH sane\-hpsj5s 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hpsj5s .SH NAME sane\-hpsj5s \- SANE backend for HP ScanJet 5S sheet-fed scanner .SH DESCRIPTION The .B sane\-hpsj5s library implements a SANE (Scanner Access Now Easy) backend that provides access to a parallel port Hewlett-Packard ScanJet 5S scanner. .PP IMPORTANT: this is alpha code. Don't expect this to work correctly. Many functions are missing, others contain errors. In some cases, your computer might even hang. It cannot be excluded (although I consider it extremely improbable) that your scanner will be damaged. .PP LIMITATIONS: For now this backend works only on Linux. This limitation is due to dependence on the libieee1284 library. If your system supports libieee1284 too, this backend should work. If you ported libieee1284 for your platform, please let me know. Your system should support .B EPP (or .B EPP+ECP ) mode to operate this scanner. Future versions will support ECP and SPP (Nibble and Byte) modes also. It's planned to support scanners not only at daisy-chain position 0, but anywhere. Support for multiple scanners could be implemented too. .PP Current version implements only gray scale scanning. True Color and B/W modes are not supported for now. .PP That said, TESTERS ARE WELCOME. Send your bug reports and comments to Max Vorobiev . .PP .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the parallel port name in form, libieee1284 expects. It seems to be system dependent. Under Linux it's parport0, parport1, etc. .SH CONFIGURATION The contents of the .I hpsj5s.conf file is a list of parport names that correspond to HP ScanJet 5S scanners. Empty lines and lines starting with a hash mark (#) are ignored. Only one device name can be listed in .IR hpsj5s.conf for this moment. Future versions will support daisy chain selection. .SH TIPS .PP It seems that HP ScanJet 5S scanner uses software noise correction. This feature is not implemented for now. So does gamma correction and calibration. I'll handle it in future versions. Native resolution for this scanner is 300 DPI. Other modes could be jagged in some ways. .PP .SH FILES .TP .I @CONFIGDIR@/hpsj5s.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-hpsj5s.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hpsj5s.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .SH "SEE ALSO" sane(7) .br http://hpsj5s.sourceforge.net .br http://cyberelk.net/tim/libieee1284 .br .SH AUTHOR Max Vorobiev .br Man page mostly based on canon.man sane-backends-1.0.27/doc/sane-rts8891.man0000664000175000017500000001060512775277260014573 00000000000000.TH "sane\-rts8891" "5" "8 Dec 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .SH "NAME" sane\-rts8891 \- SANE backend for rts8891 based scanners .SH "DESCRIPTION" The .B sane\-rts8891 library implements a SANE (Scanner Access Now Easy) backend that provides access to scanners based on the rts8891 ASIC. .PP The scanners that work with this backend are: .PP .RS .ft CR .nf Vendor Model status \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\- Umax Astra 4400 untested Umax Astra 4450 untested HP scanjet 4000c good HP scanjet 4470c good .fi .ft R .RE The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage or xsane. .br If you have any strange behavior, please report to the backend maintainer or to the SANE mailing list. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d rts8891 .RE .TP .B Scan Mode Options .TP .B \-\-mode selects the basic mode of operation of the scanner valid choices are .I R Color , .I Gray and .I Lineart The default mode is Color. The Lineart mode is black and white only (1 bit). Grayscale will produce 256 levels of gray (8 bits). Color mode allows for over 16 million different colors produced from 24 bits of color information. .TP .B \-\-resolution selects the resolution for a scan. The horizontal and vertical resolutions are set by the value of this option. The scanner is capable of the following resolutions for the specified option value: .PP .RS .ft CR .nf Value Hor. Resolution Vert. Resolution \-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- 75 75dpi 75dpi 150 150dpi 150dpi 300 300dpi 300dpi 600 600dpi 600dpi 1200 1200dpi 1200dpi .fi .ft R .RE .TP .B \-\-preview requests a preview scan. The resolution used for that scan is 75 dpi and the scan area and the scan mode are as specified through their options, or the default if not specified. The default value for preview mode is "no". .TP .B \-\-threshold selects the minimum\-brightness to get a white point. The threshold is only used with Lineart mode scans. It is specified as a percentage in the range 0..100% (in steps of 1). The default value of the threshold option is 50. .SH "CONFIGURATION FILE" The configuration file .B @CONFIGDIR@/rts8891.conf contains the usb device ids of supported scanners (eg usb 0x043d 0x007c) and scanner configuration options. Empty lines and lines starting with a hash mark (#) are ignored. .PP The options supported are .B allowsharing , .B modelnumber . Option .PP .B allowsharing enables or not the sharing of the scanner between multiple frontends at the same time. .PP .B modelnumber is used to force the reported model by the backend and is only useful in the case of a scanner which NVRAM has been erased. .RS .ft CR .nf 0 to report a HP4470c. 1 to report a HP4400c. 2 to report an Astra 4400. .fi .ft R .RE .PP .SH "FILES" .TP .I @LIBDIR@/libsane\-rts8891.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-rts8891.so The shared library implementing this backend (present on systems that support dynamic loading). .SH "ENVIRONMENT" .TP .B SANE_DEBUG_RTS8891 SANE_DEBUG_RTS8891_LOW SANE_DEBUG_RTS88XX_LIB If the library was compiled with debug support enabled, these environment variables controls the debug level for this backend. E.g., a value of 255 requests all debug output to be printed. Smaller levels reduce verbosity. .SH "LIMITATIONS" Scanners of the same model exist with different sensors, due to lack of data (ie USB logs) some sensors are better supported than others. At least 75 dpi mode is working for any model. Sharing the scanner between several frontends at the same time (allowsharing option) may not work on some USB controllers. .PP XPA is no (yet) supported. .SH "BUGS" .br No bugs currently known. .SH "SEE ALSO" sane\-scsi(5), scanimage(1), xscanimage(1), xsane(1), sane(7) .SH "AUTHOR" .TP This backend has been developed by St\['e]phane Voltz. .I http://stef.dev.free.fr/sane/rts8891 .SH "CREDITS" .TP Many thanks go to: Laurent Fournier who donated me a HP4470c. Vladimir Sysoev and "TheUnruly Squash" for the time they spent recording USB activity and testing the experimental version on HP4400 models. sane-backends-1.0.27/doc/sane-kvs1025.man0000664000175000017500000000161112775277260014541 00000000000000.TH sane\-kvs1025 5 "16 Apr 2010" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-kvs1025 .SH NAME sane\-kvs1025 \- SANE backend for Panasonic KV-S102xC USB ADF scanners. .SH DESCRIPTION The .B sane\-kvs1025 library implements a SANE (Scanner Access Now Easy) backend which provides access to the Panasonic KV-S1020C/1025C and KV-S1045C scanners. .SH KNOWN ISSUES This document was written by the SANE project, which has no information regarding the capabilities or reliability of the backend. All information contained here is suspect. .SH CREDITS The backend was written by Tao Zhang / Panasonic Russia Ltd. The backend was ported to sane-backends 1.0.21 and updated to use sanei_usb instead of libusb by m. allan noah. The backend was tested on KV-S1025C and 1045C by Tiago Zaniquelli. .SH "SEE ALSO" sane(7), sane\-usb(5) .SH AUTHOR m. allan noah: sane-backends-1.0.27/doc/sane-mustek_pp.man0000664000175000017500000003537412775312262015442 00000000000000.TH sane\-mustek_pp 5 "13 Jul 2008" .de EX .sp .nf .ft CW .. .de EE .ft R .fi .sp .. .IX sane\-mustek_pp .SH NAME sane\-mustek_pp \- SANE backend for Mustek parallel port flatbed scanners .SH DESCRIPTION The .B sane\-mustek_pp library implements a SANE (Scanner Access Now Easy) backend that provides access to Mustek parallel port flatbed scanners and OEM versions. There are 2 classes of Mustek parallel port scanners: regular .B CCD (cold cathode device) scanners and .B CIS (contact image sensor) scanners. .P The current version of this backend supports both CCD type scanners and CIS type scanners. .P The following scanners might work with this backend: .SS "CCD scanners" .EX Model: ASIC ID: CCD Type: works: -------------------------------------------------------------- SE 6000 P 1013 00 yes SM 4800 P 1013/1015 04/01 yes SE 1200 ED Plus 1015 01 no SM 1200 ED Plus 1015 01 no SE 12000 P 1505 05 no 600 III EP Plus 1013/1015 00/01 yes SE 600 SEP 1013 ?? yes 600 II EP ???? ?? no MD9848 1015 00 yes Gallery 4800 ???? ?? yes Viviscan Compact II 1013 00 yes .EE .SS CIS scanners .EX Model: ASIC ID: works: ----------------------------------------------- Mustek 600 CP & 96 CP 1015 yes (*) Mustek 1200 CP 1015 yes Mustek 1200 CP+ 1015 yes .EE .EX OEM versions Original works -------------------------------------------------- Medion/LifeTec/Tevion MD/LT 9350/9351 1200 CP yes MD/LT 9850/9851 1200 CP maybe (**) MD/LT 9858 1200 CP probably MD/LT 9890/9891 1200 CP yes Targa Funline TS12EP 1200 CP yes Funline TS6EP 600 CP yes Trust Easy Connect 9600+ 600 CP yes Cybercom 9352 1200 CP yes (***) .EE .HP (*) Calibration problems existed with earlier version of this driver. They seem to be solved now. .HP (**) Problems have been reported in the past for the MD/LT9850 type (striped scans, head moving in wrong direction at some resolutions). It is not known whether the current version of the driver still has these problems. .PP .B IF YOU HEAR LOUD CLICKING NOISES, IMMEDIATELY UNPLUG THE SCANNER ! (This holds for any type of scanner). .HP (***) Possibly, the engine_delay parameter has to be set to 1 ms for accurate engine movements. .PP Please note that this backend is still under construction. Certain models are currently not supported and some may never be because the communication protocol is still unknown (eg., SE 12000 P). .PP Some scanners work faster when .B EPP/ECP is enabled in the BIOS. EPP mode however may lead to hard-locks on some Linux systems. If that is the case for you, you can either disable ECP/EPP in your BIOS or disable it in the backend itself (see GLOBAL OPTIONS). .PP Note that the backend needs to run as root or has to have appropriate access rights to /dev/parport* if libieee1284 support is compiled in. To allow user access to the scanner run the backend through the network interface (See saned(8) and sane\-net(5)). Note also that the backend .I does not support .IR "parport sharing" , i.e. if you try printing while scanning, your computer may crash. To enable parport sharing, you have to enable libieee1284 at compile time. This backend also conflicts with the .I sane\-musteka4s2 backend. You can only enable one of them in your dll.conf. However, you have to enable the backend explicitly in your dll.conf, just remove the hash mark in the line "mustek_pp". .SH "DEVICE DEFINITION" This backend allows multiple devices being defined and configured via the .B mustek_pp.conf file (even simultaneously, provided that they are connected to different parallel ports). Please make sure to edit this file .B before you use the backend. .PP A device can be defined as follows: .PP .RS .I scanner .RE .PP where .HP .B is an arbitrary name for the device, optionally enclosed by double quotes, for instance "LifeTec 9350". .HP .B is the name of the parallel port to which the device is connected. In case libieee1284 is used for communication with the port .I (default .IR setup) , valid port names are .BR parport0 , .BR parport1 , and .BR parport2 . .PP In case the backend is configured for raw IO .I (old .IR setup) , port addresses have to be used instead of port names: .BR 0x378 , .BR 0x278 , or .BR 0x3BC . The mapping of parallel ports (lp0, lp1, and lp2) to these addresses can be different for different Linux kernel versions. For instance, if you are using a Kernel 2.2.x or better and you have only one parallel port, this port is named lp0 regardless of the base address. However, this backend requires the base address of your port. If you are not sure which port your scanner is connected to, have a look at your /etc/conf.modules, /etc/modules.conf and/or /proc/ioports. .PP If you are unsure which port to use, you can use the magic value .BR * to probe for your scanner. .PP .HP .B is the driver to use for this device. Currently available drivers are: .IP .BR cis600 " : for 600 CP, 96 CP & OEM versions" .br .BR cis1200 " : for 1200 CP & OEM versions" .br .BR cis1200+ " : for 1200 CP+ & OEM versions" .br .BR ccd300 " : for 600 IIIE P & OEM version" .IP .B Choosing the wrong driver can damage your scanner! .br Especially, using the 1200CP settings on a 600CP can be harmful. If the scanner starts making a loud noise, turn it off immediately !!! .PP Using the cis600 driver on a 1200CP or a 1200CP+ is probably not dangerous. The cis1200+ driver also works for the 1200CP, and using the cis1200 driver on a 1200CP+ will typically result in scans that cover only half of the width of the scan area (also not dangerous). .PP If unsure about the exact model of your OEM version, check the optical resolution in the manual or on the box: the 600CP has a maximum optical resolution of 300x600 DPI, whereas the 1200CP and 1200CP+ have a maximum optical resolution of 600x1200 DPI. .PP Examples: .PP .RS scanner "LifeTec 9350" 0x378 cis1200 .PP scanner Mustek_600CP 0x378 cis600 .PP scanner Mustek_600IIIEP * ccd300 .RE If in doubt which port you have to use, or whether your scanner is detected at all, you can use .B sane\-find\-scanner \-p to probe all configured ports. .SH CONFIGURATION .PP The contents of the .B mustek_pp.conf file is a list of device definitions and device options that correspond to Mustek scanners. Empty lines and lines starting with a hash mark (#) are ignored. Options have the following format: .PP .RS .I option [] .RE .PP Depending on the nature of the option, a value may or may not be present. Options always apply to the scanner definition that precedes them. There are no global options. Options are also driver-specific: not all drivers support all possible options. .SS Common options .TP .B bw Black/white discrimination value to be used during lineart scanning. Pixel values below this value are assumed to be black, values above are assumed to be white. .br Default value: 127 .br Minimum: 0 .br Maximum: 255 .sp Example: option bw 150 .SS CIS driver options .TP .B top_adjust Vertical adjustment of the origin, expressed in millimeter (floating point). This option can be used to calibrate the position of the origin, within certain limits. Note that CIS scanners are probably temperature sensitive, and that a certain inaccuracy may be hard to avoid. Differences in offset between runs in the order of 1 to 2 mm are not unusual. .br Default value: 0.0 .br Minimum: \-5.0 .br Maximum: 5.0 .br .sp Example: option top_adjust \-2.5 .TP .B slow_skip Turns fast skipping to the start of the scan region off. When the region to scan does not start at the origin, the driver will try to move the scanhead to the start of the scan area at the fastest possible speed. On some models, this may not work, resulting in large inaccuracies (up to centimeters). By setting this option, the driver is forced to use normal speed during skipping, which can circumvent the accuracy problems. Currently, there are no models for which these inaccuracy problems are known to occur. .sp By default, fast skipping is used. .sp Example: option slow_skip .TP .B engine_delay Under normal circumstances, it is sufficient for the driver to wait for the scanner signaling that the engine is stable, before a new engine command can be transmitted. In rare cases, certain scanners and/or parallel port chipsets appear to prevent reliable detection of the engine state. As a result, engine commands are transmitted too soon and the movement of the scanner head becomes unreliable. Inaccuracies ranging up to 10 cm over the whole vertical scan range have been reported. To work around this problem, the engine_delay option can be set. If it is set, the driver waits an additional amount of time after every engine command, equal to the engine_delay parameter, expressed in milliseconds. It practice an engine_delay of 1 ms is usually sufficient. The maximum delay is 100 ms. .sp Note that every additional ms of delay can add up to 14 seconds to the total scanning time (highest resolution), so an as small as possible value is preferred. .sp Default value: 0 .br Minimum: 0 .br Maximum: 100 .sp Example: option engine_delay 1 .SS CCD driver options .TP .B top Number of scanlines to skip to the start of the scan area. The number can be any positive integer. Values known to me are 47 and 56. .sp Default value: 47 .br Minimum: 0 .br Maximum: none .br .sp Example: option top 56 .TP .B waitbank The number of usecs to wait for a bank change. You should not touch this value actually. May be any positive integer .sp Default value: 700 .br Minimum: 0 .br Maximum: none .sp Example: option waitbank 700 .PP A sample configuration file is shown below: .PP .EX # # LifeTec/Medion 9350 on port 0x378 # scanner "LifeTec 9350" 0x378 cis1200 # Some calibration options (examples!). option bw 127 option top_skip \-0.8 # # A Mustek 600CP on port 0x3BC # scanner "Mustek 600CP" 0x3BC cis600 # Some calibration options (examples!). option bw 120 option top_skip 1.2 # # A Mustek 1200CP+ on port 0x278 # scanner "Mustek 1200CP plus" 0x278 cis1200+ # Some calibration options (examples!). option bw 130 option top_skip 0.2 # # A Mustek 600 III EPP on port parport0 # scanner "Mustek 600 III EPP" parport0 ccd300 # Some calibration options (examples!). option bw 130 option top 56 .EE .SH GLOBAL OPTIONS .PP You can control the overall behaviour of the mustek_pp backend by global options which precede any scanner definition in the mustek_pp.conf file. .sp Currently, there is only one global option: .SS Global options .TP .B no_epp Disable parallel port mode EPP: works around a known bug in the Linux parport code. Enable this option, if the backend hangs when trying to access the parallel port in EPP mode. .sp Default value: use EPP .sp Example: option no_epp .SH FILES .TP .I @CONFIGDIR@/mustek_pp.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-mustek_pp.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-mustek_pp.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_MUSTEK_PP If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .EX level debug output -------------------------------------- 0 nothing 1 errors 2 warnings & minor errors 3 additional information 4 debug information 5 code flow (not supported yet) 6 special debug information .EE .TP .B SANE_DEBUG_SANEI_PA4S2 This variable sets the debug level for the SANE interface for the Mustek chipset A4S2. Note that enabling this will spam your terminal with some million lines of debug output. .EX level debug output ---------------------------- 0 nothing 1 errors 2 warnings 3 things nice to know 4 code flow 5 detailed code flow 6 everything .EE .SH "SEE ALSO" sane(7), sane\-mustek(5), sane\-net(5), saned(8), sane\-find\-scanner(1) .TP For latest bug fixes and information see .I http://www.penguin\-breeder.org/sane/mustek_pp/ .TP For additional information on the CIS driver, see .I http://home.scarlet.be/eddy_de_greef/ .SH AUTHORS .nf Jochen Eisinger Eddy De Greef .fi .SH BUGS Too many... please send bug reports to .I sane\-devel@lists.alioth.debian.org (note that you have to subscribe first to the list before you can send emails... see http://www.sane\-project.org/mailing\-lists.html) .SH BUG REPORTS If something doesn't work, please contact us (Jochen for the CCD scanners, Eddy for the CIS scanners). But we need some information about your scanner to be able to help you... .TP .I SANE version run "scanimage \-V" to determine this .TP .I the backend version and your scanner hardware run "SANE_DEBUG_MUSTEK_PP=128 scanimage \-L" as root. If you don't get any output from the mustek_pp backend, make sure a line "mustek_pp" is included into your @CONFIGDIR@/dll.conf. If your scanner isn't detected, make sure you've defined the right port address in your mustek_pp.conf. .TP .I the name of your scanner/vendor also a worthy information. Please also include the optical resolution and lamp type of your scanner, both can be found in the manual of your scanner. .TP .I any further comments if you have comments about the documentation (what could be done better), or you think I should know something, please include it. sane-backends-1.0.27/doc/sane-mustek_usb.man0000664000175000017500000001406513106201017015566 00000000000000.TH sane\-mustek_usb 5 "13 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-mustek_usb .SH NAME sane\-mustek_usb \- SANE backend for Mustek USB flatbed scanners .SH DESCRIPTION The .B sane\-mustek_usb library implements a SANE (Scanner Access Now Easy) backend that provides access to Mustek USB flatbed scanners (including a clone from Trust). At present, the following scanners are known to work more or less with this backend: .PP .RS Mustek 600 CU .br Mustek 1200 UB .br Mustek 1200 CU .br Mustek 1200 CU Plus .br Trust Compact Scan USB 19200 .br .RE .PP More details can be found on the Mustek USB backend homepage .IR http://www.meier\-geinitz.de/sane/mustek_usb\-backend/ . .PP The Mustek BearPaw 1200 and 2400 scanners are supported by the plustek backend. See .BR sane\-plustek (5) for details. The Mustek BearPaw 1200F is supported by the MA-1509 backend. See .BR sane\-ma1509 (5) for details. Other Mustek USB scanners are supported by the gt68xx backend, see .BR sane\-gt68xx (5). .PP This backend can only work with scanners that are already detected by the operating system. See .BR sane\-usb (5) for details. .PP If you own a Mustek (or Trust) scanner other than the ones listed above that works with this backend, please let me know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .I /proc/bus/usb/devices or syslog) to me. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is a path-name for the special device that corresponds to a USB scanner. With Linux, such a device name could be .I /dev/usb/scanner0 or .IR /dev/usbscanner1 , for example. .PP For FreeBSD use .IR /dev/uscanner0 . .SH CONFIGURATION The contents of the .I mustek_usb.conf file is a list of options and device names that correspond to Mustek USB scanners. Empty lines and lines starting with a hash mark (#) are ignored. If a device name is placed in .IR mustek_usb.conf , it must be followed by a line containing the keyword .B option and an option specifying the scanner type. The following options can be used: .BR 600cu , .BR 1200cu , .BR 1200cu_plus , .BR 1200ub . For the Trust Compact Scan USB 19200 use `option 1200ub'. .PP Instead of using the device name, the scanner can be autodetected by .B "usb vendor_id product_id" statements which are already included into .IR mustek_usb.conf . This is only supported with Linux 2.4.8 and higher and all systems that support libsub. "vendor_id" and "product_id" are hexadecimal numbers that identify the scanner. If this doesn't work, a device name and the option specifying the scanner type must be placed in .I mustek_usb.conf as described above. .PP The global .B option max_block_size can be used to limit the amount of data acquired in one turn from the USB system. It may be worth trying, if USB errors occur. .PP A sample configuration file is shown below: .PP .RS # Comment .br option max_block_size 1024 .br usb 0x055f 0x0001 .br /dev/usb/scanner0 .br option 600cu .RE .PP The first line is ignored. The second line sets the buffer size to a maximum of 1024 bytes. The third line tries to autodetect a scanner with vendor id 0x055f and product id 0x0001 (Mustek 1200 CU). The fourth line tells the backend to attach to .I /dev/usb/scanner0 and the fifth line specifies that .I /dev/usb/scanner0 is a Mustek 600 CU. .SH FILES .TP .I @CONFIGDIR@/mustek_usb.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-mustek_usb.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-mustek_usb.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_MUSTEK_USB If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. .ft CR .nf Value Description 0 no output 1 print fatal errors 2 print important messages 3 print non-fatal errors and less important messages 4 print all but debugging messages 5 print high level debugging messages 6 print medium level debugging messages 7 print low level debugging messages .fi .ft R Example: export SANE_DEBUG_MUSTEK_USB=4 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .BR sane\-mustek (5), .BR sane\-mustek_pp (5), .BR sane\-plustek (5), .BR sane\-gt68xx (5), .BR sane\-ma1509 (5) .br .IR @DOCDIR@/mustek_usb/mustek_usb.CHANGES , .br .I @DOCDIR@/mustek_usb/mustek_usb.TODO .br .I http://www.meier\-geinitz.de/sane/mustek_usb\-backend/ .SH AUTHOR Henning Meier-Geinitz .br This backend is based on the Mustek 1200ub backend from Mustek, maintained by Tom Wang. .SH BUGS These devices have a hardware bug: Once data is written to them, they can't be reset (toggle = DATA0). That means, any operation that tries to reset the device will result in running into timeouts. In earlier versions this backend failed when it was loaded the second time in some configurations. The only choice was to replug the scanner in this case. The backend uses a workaround for that bug now but it's only tested on Linux. Reports for other operating systems are appreciated. .PP More detailed bug information is available at the Mustek backend homepage .IR http://www.meier\-geinitz.de/sane/mustek_usb\-backend/ . sane-backends-1.0.27/doc/sane-hp3900.man0000664000175000017500000000727712112021330014331 00000000000000.TH sane\-hp3900 5 "06 Jan 2009" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-hp3900 .SH NAME sane\-hp3900 \- SANE backend for RTS8822 chipset based scanners .SH DESCRIPTION The .B sane\-hp3900 library implements a SANE (Scanner Access Now Easy) backend that provides access at least to the following USB flatbed scanners: .PP .RS .ft CR .nf Model: Chipset: ------ -------- HP ScanJet 3800 RTS8822BL-03A HP ScanJet 3970 RTS8822L-01H HP ScanJet 4070 Photosmart RTS8822L-01H HP ScanJet 4370 RTS8822L-02A HP ScanJet G2710 RTS8822BL-03A HP ScanJet G3010 RTS8822L-02A HP ScanJet G3110 RTS8822L-02A UMAX Astra 4900/4950 RTS8822L-01H * BenQ 5550 RTS8823L-01E * .fi .ft R .RE .PP More details can be found on the hp3900 backend homepage .IR http://sourceforge.net/projects/hp3900\-series/ . .PP This is ALPHA software. Keep your hand at the scanner's plug and unplug it, if scanner does not start to scan. See also the BUGS section. .PP If you own a scanner other than the ones listed above that works with this backend, please let us know this by sending the scanner's exact model name and the USB vendor and device ids (e.g. from .IR /proc/bus/usb/devices , .I sane\-find\-scanner or syslog) to us. Even if the scanner's name is only slightly different from the models mentioned above, please let us know. .PP .SH CONFIGURATION The contents of the .I hp3900.conf file is a list of usb lines containing vendor and product ids that correspond to USB scanners. The file can also contain the names of device files that correspond to an HP 39XX scanner. Empty lines and lines starting with a hash mark (#) are ignored. The scanners are autodetected by .B usb vendor_id product_id statements which are already included into .IR hp3900.conf . "vendor_id" and "product_id" are hexadecimal numbers that identify the scanner. If autodetection does not work, add the device name of your scanner to the configuration file, .PP .SH FILES .TP .I @CONFIGDIR@/hp3900.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-hp3900.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-hp3900.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "/etc/sane.d" being searched (in this order). .TP .B SANE_DEBUG_HP3900 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_HP3900=4 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .br .I http://sourceforge.net/projects/hp3900\-series/ .I http://jkdsoftware.dyndns.org/drupal/?q=es/books/151 .SH AUTHOR Jonathan Bravo Lopez .SH BUGS Scanning is only tested with Linux/ix86/gcc. Be careful when testing on other operating systems and especially on big-endian platforms. The scanner may get wrong data. sane-backends-1.0.27/doc/saned.man0000664000175000017500000002370013106201017013547 00000000000000.TH saned 8 "20 Apr 2009" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX saned .SH NAME saned \- SANE network daemon .SH SYNOPSIS .B saned .B [ \-a .I [ username ] .B | \-d .I [ n ] .B | \-s .I [ n ] .B | \-h .B ] .SH DESCRIPTION .B saned is the SANE (Scanner Access Now Easy) daemon that allows remote clients to access image acquisition devices available on the local host. .SH OPTIONS .PP The .B \-a flag requests that .B saned run in standalone daemon mode. In this mode, .B saned will detach from the console and run in the background, listening for incoming client connections; .B inetd is not required for .B saned operations in this mode. If the optional .B username is given after .B \-a , .B saned will drop root privileges and run as this user (and group). .PP The .B \-d and .B \-s flags request that .B saned run in debug mode (as opposed to .BR inetd (8) daemon mode). In this mode, .B saned explicitly waits for a connection request. When compiled with debugging enabled, these flags may be followed by a number to request debug info. The larger the number, the more verbose the debug output. E.g., .B \-d128 will request printing of all debug info. Debug level 0 means no debug output at all. The default value is 2. If flag .B \-d is used, the debug messages will be printed to stderr while .B \-s requests using syslog. .PP If .B saned is run from inetd, xinetd or systemd, no option can be given. .PP The .B \-h flag displays a short help message. .SH CONFIGURATION First and foremost: .B saned is not intended to be exposed to the internet or other non-trusted networks. Make sure that access is limited by tcpwrappers and/or a firewall setup. Don't depend only on .BR saned 's own authentication. Don't run .B saned as root if it's not necessary. And do .B not install .B saned as setuid root. .PP The .I saned.conf configuration file contains both options for the daemon and the access list. .TP \fBdata_portrange\fP = \fImin_port\fP - \fImax_port\fP Specify the port range to use for the data connection. Pick a port range between 1024 and 65535; don't pick a too large port range, as it may have performance issues. Use this option if your \fBsaned\fP server is sitting behind a firewall. If that firewall is a Linux machine, we strongly recommend using the Netfilter \fInf_conntrack_sane\fP module instead. .PP The access list is a list of host names, IP addresses or IP subnets (CIDR notation) that are permitted to use local SANE devices. IPv6 addresses must be enclosed in brackets, and should always be specified in their compressed form. Connections from localhost are always permitted. Empty lines and lines starting with a hash mark (#) are ignored. A line containing the single character ``+'' is interpreted to match any hostname. This allows any remote machine to use your scanner and may present a security risk, so this shouldn't be used unless you know what you're doing. .PP A sample configuration file is shown below: .PP .RS # Daemon options .br data_portrange = 10000 - 10100 .br # Access list .br scan\-client.somedomain.firm .br # this is a comment .br 192.168.0.1 .br 192.168.2.12/29 .br [::1] .br [2001:db8:185e::42:12]/64 .RE .PP The case of the host names does not matter, so AHost.COM is considered identical to ahost.com. .SH SERVER DAEMON CONFIGURATION For .B saned to work properly in its default mode of operation, it is also necessary to add the appropriate configuration for .I (x)inetd or systemd. (see below). Note that your inetd must support IPv6 if you want to connect to saned over IPv6 ; xinetd, openbsd-inetd and systemd are known to support IPv6, check the documentation for your inetd daemon. .PP In the sections below the configuration for .I inetd, xinetd and .I systemd are described in more detail. .PP For the configurations below it is necessary to add a line of the following form to .IR /etc/services : .PP .RS sane\-port 6566/tcp # SANE network scanner daemon .RE .PP The official IANA short name for port 6566 is "sane\-port". The older name "sane" is now deprecated. .SH INETD CONFIGURATION It is required to add a single line to the inetd configuration file .IR (/etc/inetd.conf) . .PP The configuration line normally looks like this: .PP .RS sane\-port stream tcp nowait saned.saned @SBINDIR@/saned saned .RE .PP However, if your system uses .BR tcpd (8) for additional security screening, you may want to disable saned access control by putting ``+'' in .IR saned.conf and use a line of the following form in .IR /etc/inetd.conf instead: .PP .RS sane\-port stream tcp nowait saned.saned /usr/sbin/tcpd @SBINDIR@/saned .RE .PP Note that both examples assume that there is a .B saned group and a .B saned user. If you follow this example, please make sure that the access permissions on the special device are set such that .B saned can access the scanner (the program generally needs read and write access to scanner devices). .SH XINETD CONFIGURATION If xinetd is installed on your system instead of inetd the following example for .I /etc/xinetd.conf may be helpful: .PP .RS .ft CR .nf # default: off # description: The sane server accepts requests # for network access to a local scanner via the # network. service sane\-port { port = 6566 socket_type = stream wait = no user = saned group = saned server = @SBINDIR@/saned } .fi .ft R .RE .SH SYSTEMD CONFIGURATION Saned can be compiled with explicit systemd support. This will allow logging debugging information to be forwarded to the systemd journal. The systemd support requires compilation with the systemd-devel package installed on the system. this is the preferred option. Saned can be used wih systemd without the systemd integration compiled in, but then logging of debug information is not supported. The systemd configuration is different for the 2 options, so both are described below. .SH Systemd configuration for saned with systemd support compiled in for the systemd configuration we need to add 2 configuration files in .I /etc/systemd/system. .PP The first file we need to add here is called .I saned.socket. It shall have the following contents: .PP .RS .ft CR .nf [Unit] Description=saned incoming socket [Socket] ListenStream=6566 Accept=yes MaxConnections=1 [Install] WantedBy=sockets.target .fi .ft R .RE .PP The second file to be added is .I saned@.service with the following contents: .PP .RS .ft CR .nf [Unit] Description=Scanner Service Requires=saned.socket [Service] ExecStart=/usr/sbin/saned User=saned Group=saned StandardInput=null StandardOutput=syslog StandardError=syslog Environment=SANE_CONFIG_DIR=@CONFIGDIR@ # If you need to debug your configuration uncomment the next line and # change it as appropriate to set the desired debug options # Environment=SANE_DEBUG_DLL=255 SANE_DEBUG_BJNP=5 [Install] Also=saned.socket .fi .ft R .RE .PP You need to set an environment variable for .B SANE_CONFIG_DIR pointing to the directory where saned can find its configuration files. you will have to remove the # on the last line and set the variables for the desired debugging information if required. Multiple variables can be set by separating the assignments by spaces as shown in the example above. .PP Unlike .I (x)inetd , systemd allows debugging output from backends set using .B SANE_DEBUG_XXX to be captured. See the man-page for your backend to see what options are supported. With the service unit as described above, the debugging output is forwarded to the system log. .SH Systemd configuration when saned is compiled without systemd support This configuration will also work when Saned is compiled WITH systemd integration support, but it does not allow debugging information to be logged. .PP for systemd configuration for saned, we need to add 2 configuration files in .I /etc/systemd/system. .PP The first file we need to add here is called .I saned.socket. It is identical to the version for systemd with the support compiled in. It shall have the following contents: .PP .RS .ft CR .nf [Unit] Description=saned incoming socket [Socket] ListenStream=6566 Accept=yes MaxConnections=1 [Install] WantedBy=sockets.target .fi .ft R .RE .PP The second file to be added is .I saned@.service This one differes from the sersion with systemd integration compiled in: .PP .RS .ft CR .nf [Unit] Description=Scanner Service Requires=saned.socket [Service] ExecStart=/usr/sbin/saned User=saned Group=saned StandardInput=socket Environment=SANE_CONFIG_DIR=/etc/sane.d [Install] Also=saned.socket .fi .ft R .RE .PP .SH FILES .TP .I /etc/hosts.equiv The hosts listed in this file are permitted to access all local SANE devices. Caveat: this file imposes serious security risks and its use is not recommended. .TP .I @CONFIGDIR@/saned.conf Contains a list of hosts permitted to access local SANE devices (see also description of .B SANE_CONFIG_DIR below). .TP .I @CONFIGDIR@/saned.users If this file contains lines of the form user:password:backend access to the listed backends is restricted. A backend may be listed multiple times for different user/password combinations. The server uses MD5 hashing if supported by the client. .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .SH "SEE ALSO" .BR sane (7), .BR scanimage (1), .BR xscanimage (1), .BR xcam (1), .BR sane\-dll (5), .BR sane\-net (5), .BR sane\-"backendname" (5) .br .I http://www.penguin-breeder.org/?page=sane\-net .SH AUTHOR David Mosberger sane-backends-1.0.27/doc/releases.txt0000664000175000017500000001014313110600276014326 000000000000002009-05-05 This text summarizes some points to pay attention to when a new release of sane-backends is planned. Timetable (approximate periods): Day 0: Announcement of upcoming release on sane-devel including timetable Day 14: Feature freeze (only bugfixes + documentation updates) Day 28: Code freeze (only fixes for bugs that can destroy hardware, can cause compilation problems or render a backend completely unusable, and documentation updates are allowed) Day 35: Release Before the release: * set :new :yes on any new backend .desc files, by looking for added files: cd backend ls | while read aa; do git log --follow --diff-filter=A --find-renames=40% --format="%ai $aa" "$aa"; done > foo.log Then inspect foo.log for any files added since the last release. * Make sure that config.guess and config.sub are up-to-date (get them from savannah.gnu.org/projects/config) (git clone is easiest) * configure.ac: remove 'git' from textual version number, and increment it * run autoreconf --force but do *NOT* use the --install option as it will overwrite our custom ltmain.sh * ChangeLog: generate from git log, something like: git log RELEASE_1_0_25..HEAD > ChangeLog * NEWS: update and enter date of release, etc Get list of heavily change backends via: git diff --stat RELEASE_1_0_25 Get other things by reading ChangeLog * sane-backends.lsm: update * git commit -a * tag git with release tag; e.g.: 'git tag -a RELEASE_1_0_15' * probably DONT want to git push here, because alioth will rebuild it's local checkout needlessly Making the release: * make tar.gz, sane-backends-x.y.z.lsm, and .md5sum with "make sane-backends" * unpack tar.gz in temporary directory * make diff from last release by unpacking it also in temporary directory and running e.g. diff -uNr sane-backends-1.0.23 sane-backends-1.0.24 > sane-backends-1.0.23-1.0.24.diff * check that the diff applies cleanly to the old version * gzip the diff * install devel headers required to build optional backends (1284,gphoto,etc) * check that the new version .tar.gz can be compiled * upload the .tar.gz, tar.gz.md5 and .diff.gz to the FTP/HTTP servers (at the moment: alioth.debian.org, ftp files are in /srv/alioth.debian.org/chroot/ftproot/pub/sane/ ) In the alioth web interface, you should upload the smallest file first, since you don't get error messages until after an upload completes, and you might need to change something. You can add the larger files afterwards. You may have to split larger files. Announcing the release: * checkout the sane/website.git module and: * copy sane-backends.html to sane-backends-"old-version".html * update sane-supported-devices.html with link to above "old" file * rebuild sane-backends.html and sane-mfgs.html (make -C doc html-pages) * use man2html from http://hydra.nac.uci.edu/indiv/ehood/man2html.html to rebuild html man pages (make -C doc html-man) (no other version works) * add md5 sum to sane-md5sums.txt * check and update platforms page (sane-support.html) * add announcement to index.html * git commit -a && git push * check that website was updated automatically. if not, see: /home/groups/sane/bin/update-htdocs.sh * rebuild descriptions.db (make -C doc descriptions.db) * scp doc/descriptions.db to alioth: /home/groups/sane/search/release * write announcements sane-devel, maybe others (e.g. freshmeat), include the md5 hash After the release: #### consider not adding old changelogs to release package * move ChangeLog to ChangeLogs/ChangeLog-"version" * start a new ChangeLog, with the following message: This file is automatically generated at release time using git commit messages. For the latest changes please refer to the output of `git log` or see: https://alioth.debian.org/plugins/scmgit/cgi-bin/gitweb.cgi?p=sane/sane-backends.git;a=log * configure.ac: bump textual version & add 'git' suffix * configure: regenerate with autoconf * remove the ':new' tag from any new backends .desc files * git add new files and commit * git push && git push --tags (one of these might give an error 'remote: fatal: bad object 0000000000000000000000000000000000000000', try the other one) sane-backends-1.0.27/doc/sane.man0000664000175000017500000006323313063340150013414 00000000000000.TH sane 7 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane .SH NAME sane \- Scanner Access Now Easy: API for accessing scanners .SH DESCRIPTION .B SANE is an application programming interface (API) that provides standardized access to any raster image scanner hardware. The standardized interface makes it possible to write just one driver for each scanner device instead of one driver for each scanner and application. While .B SANE is primarily targeted at a UNIX environment, the standard has been carefully designed to make it possible to implement the API on virtually any hardware or operating system. .PP This manual page provides a summary of the information available about .BR SANE . .PP If you have trouble getting your scanner detected, read the PROBLEMS section. .SH TERMINOLOGY An application that uses the .B SANE interface is called a .B SANE frontend. A driver that implements the .B SANE interface is called a .B SANE backend. A .B meta backend provides some means to manage one or more other backends. .SH "SOFTWARE PACKAGES" The package .RB ` sane\-backends ' contains a lot of backends, documentation (including the .B SANE standard), networking support, and the command line frontend .RB ` scanimage '. The frontends .RB ` xscanimage "', `" xcam "', and `" scanadf ' are included in the package .RB ` sane\-frontends '. Both packages can be downloaded from the .B SANE homepage .RI ( http://www.sane\-project.org/ ). Information about other frontends and backends can also be found on the .B SANE homepage. .SH "GENERAL INFORMATION" The following sections provide short descriptions and links to more information about several aspects of .B SANE. A name with a number in parenthesis (e.g. .RB ` sane\-dll (5)') points to a manual page. In this case .RB ` "man 5 sane\-dll" ' will display the page. Entries like .RI ` @DOCDIR@/sane.tex ' are references to text files that were copied to the .B SANE documentation directory .RI ( @DOCDIR@/ ) during installation. Everything else is a URL to a resource on the web. .TP 2 .B SANE homepage Information on all aspects of SANE including a tutorial and a link to the SANE FAQ can be found on the SANE homepage: .IR http://www.sane\-project.org/ . .TP .B SANE device lists The .B SANE device lists contain information about the status of .B SANE support for a specific device. If your scanner is not listed there (either supported or unsupported), please contact us. See section HOW CAN YOU HELP SANE for details. There are lists for specific releases of SANE, for the current development version and a search engine: .IR http://www.sane\-project.org/sane\-supported\-devices.html . The lists are also installed on your system at @DOCDIR@/. .TP .B SANE mailing list There is a mailing list for the purpose of discussing the SANE standard and its implementations: sane\-devel. Despite its name, the list is not only intended for developers, but also for users. There are also some more lists for special topics, however, for users, sane\-devel is the right list. How to subscribe and unsubscribe: .IR http://www.sane\-project.org/mailing\-lists.html . .TP .B SANE IRC channel The IRC (Internet Relay Chat) channel #sane can be found on the Freenode network (irc.freenode.net). It's for discussing .B SANE problems, talking about development and general .B SANE related chatting. Before asking for help, please read the other documentation mentioned in this manual page. The channel's topic is also used for announcements of problems with SANE infrastructure (mailing lists, web server, etc.). .TP .B Compiling and installing SANE Look at .I @DOCDIR@/README and the os-dependent README files for information about compiling and installing .B SANE. .TP .B SCSI configuration For information about various systems and SCSI controllers see .BR sane\-scsi (5). .TP .B USB configuration For information about USB configuration see .BR sane\-usb (5). .SH "FRONTENDS AND MISCELLANEOUS PROGRAMS" .TP 2 .B scanimage Command-line frontend. See .BR scanimage (1). .TP .B saned .B SANE network daemon that allows remote clients to access image acquisition devices available on the local host. See .BR saned (8). .TP .B sane\-find\-scanner Command-line tool to find SCSI and USB scanners and determine their Unix device files. See .BR sane\-find\-scanner (1). .PP Also, have a look at the .B sane\-frontends package (including .BR xscanimage ", " xcam ", and " scanadf ) and the frontend information page at .IR http://www.sane\-project.org/sane\-frontends.html . .SH "BACKENDS FOR SCANNERS" .TP 2 .B abaton The SANE backend for Abaton flatbed scanners supports the Scan 300/GS (8bit, 256 levels of gray) and the Scan 300/S (black and white, untested). See .BR sane\-abaton (5) for details. .TP .B agfafocus This backend supports AGFA Focus scanners and the Siemens S9036 (untested). See .BR sane\-agfafocus (5) for details. .TP .B apple The SANE backend for Apple flatbed scanners supports the following scanners: AppleScanner, OneScanner and ColorOneScanner. See .BR sane\-apple (5) for details. .TP .B artec The SANE Artec backend supports several Artec/Ultima SCSI flatbed scanners as well as the BlackWidow BW4800SP and the Plustek 19200S. See .BR sane\-artec (5) for details. .TP .B artec_eplus48u The SANE artec_eplus48u backend supports the scanner Artec E+ 48U and re-badged models like Tevion MD 9693, Medion MD 9693, Medion MD 9705 and Trust Easy Webscan 19200. See .BR sane\-artec_eplus48u (5) for details. .TP .B as6e This is a SANE backend for using the Artec AS6E parallel port interface scanner. See .BR sane\-as6e (5) for details. .TP .B avision This backend supports several Avision based scanners. This includes the original Avision scanners (like AV 630, AV 620, ...) as well as the HP ScanJet 53xx and 74xx series, Fujitsu ScanPartner, some Mitsubishi and Minolta film-scanners. See .BR sane\-avision (5) for details. .TP .B bh The bh backend provides access to Bell+Howell Copiscan II series document scanners. See .BR sane\-bh (5) for details. .TP .B canon The canon backend supports the CanoScan 300, CanoScan 600, and CanoScan 2700F SCSI flatbed scanners. See .BR sane\-canon (5) for details. .TP .B canon630u The canon630u backend supports the CanoScan 630u and 636u USB scanners. See .BR sane\-canon630u (5) for details. .TP .B canon_dr The canon_dr backend supports the Canon DR-Series ADF SCSI and USB scanners. See .BR sane\-canon_dr (5) for details. .TP .B canon_pp The canon_pp backend supports the CanoScan FB330P, FB630P, N340P and N640P parallel port scanners. See .BR sane\-canon_pp (5) for details. .TP .B cardscan This backend provides support for Corex Cardscan USB scanners. See .BR sane\-cardscan (5) for details. .TP .B coolscan This is a SANE backend for Nikon Coolscan film-scanners. See .BR sane\-coolscan (5) for details. .TP .B coolscan2 This is a SANE backend for Nikon Coolscan film-scanners. See .BR sane\-coolscan2 (5) or .I http://coolscan2.sourceforge.net for details. .TP .B epjitsu The epjitsu backend provides support for Epson-based Fujitsu USB scanners. See .BR sane\-epjitsu (5) for details. .TP .B epson The SANE epson backend provides support for Epson SCSI, parallel port and USB flatbed scanners. See .BR sane\-epson (5) for details. .TP .B fujitsu The fujitsu backend provides support for most Fujitsu SCSI and USB, flatbed and adf scanners. See .BR sane\-fujitsu (5) for details. .TP .B genesys The genesys backend provides support for several scanners based on the Genesys Logic GL646, GL841, GL843, GL847 and GL124 chips like the Medion 6471 and Hewlett-Packard 2300c. See .BR sane\-genesys (5) for details. .TP .B gt68xx The gt68xx backend provides support for scanners based on the Grandtech GT-6801 and GT-6816 chips like the Artec Ultima 2000 and several Mustek BearPaw CU and TA models. Some Genius, Lexmark, Medion, Packard Bell, Plustek, and Trust scanners are also supported. See .BR sane\-gt68xx (5) for details. .TP .B hp The SANE hp backend provides access to Hewlett-Packard ScanJet scanners which support SCL (Scanner Control Language by HP). See .BR sane\-hp (5) for details. .TP .B hpsj5s The SANE backend for the Hewlett-Packard ScanJet 5S scanner. See .BR sane\-hpsj5s (5) for details. .TP .B hp3500 The SANE backend for the Hewlett-Packard ScanJet 3500 series. See .BR sane\-hp3500 (5) for details. .TP .B hp3900 The SANE backend for the Hewlett-Packard ScanJet 3900 series. See .BR sane\-hp3900 (5) for details. .TP .B hp4200 The SANE backend for the Hewlett-Packard ScanJet 4200 series. See .BR sane\-hp4200 (5) for details. .TP .B hp5400 The SANE backend for the Hewlett-Packard ScanJet 54XXC series. See .BR sane\-hp5400 (5) for details. .TP .B hpljm1005 The SANE backend for the Hewlett-Packard LaserJet M1005 scanner. See .BR sane\-hpljm1005(5) for details. .TP .B hs2p The SANE backend for the Ricoh IS450 family of SCSI scanners. See .BR sane\-hs2p (5) for details. .TP .B ibm The SANE backend for some IBM and Ricoh SCSI scanners. See .BR sane\-ibm (5) for details. .TP .B kodak The SANE backend for some large Kodak scanners. See .BR sane\-kodak (5) for details. .TP .B kodakaio The SANE backend for Kodak AiO printer/scanners. See .BR sane\-kodakaio (5) for details. .TP .B kvs1025 The SANE backend for Panasonic KV-S102xC scanners. See .BR sane\-kvs1025 (5) for details. .TP .B leo This backend supports the Leo S3 and the Across FS-1130, which is a re-badged LEO FS-1130 scanner. See .BR sane\-leo (5) for details. .TP .B lexmark This backend supports the Lexmark X1100 series of USB scanners. See .BR sane\-lexmark (5) for details. .TP .B ma1509 The ma1509 backend supports the Mustek BearPaw 1200F USB flatbed scanner. See .BR sane\-ma1509 (5) for details. .TP .B magicolor The magicolor backend supports the KONICA MINOLTA magicolor 1690MF multi-function printer/scanner/fax. See .BR sane\-magicolor (5) for details. .TP .B matsushita This backend supports some Panasonic KVSS high speed scanners. See .BR sane\-matsushita (5) for details. .TP .B microtek The microtek backend provides access to the "second generation" Microtek scanners with SCSI-1 command set. See .BR sane\-microtek (5) for details. .TP .B microtek2 The microtek2 backend provides access to some Microtek scanners with a SCSI-2 command set. See .BR sane\-microtek2 (5) for details. .TP .B mustek The SANE mustek backend supports most Mustek SCSI flatbed scanners including the Paragon and ScanExpress series and the 600 II N and 600 II EP (non-SCSI). Some Trust scanners are also supported. See .BR sane\-mustek (5) for details. .TP .B mustek_pp The mustek_pp backend provides access to Mustek parallel port flatbed scanners. See .BR sane\-mustek_pp (5) for details. .TP .B mustek_usb The mustek_usb backend provides access to some Mustek ScanExpress USB flatbed scanners. See .BR sane\-mustek_usb (5) for details. .TP .B mustek_usb2 The mustek_usb2 backend provides access to scanners using the SQ113 chipset like the Mustek BearPaw 2448 TA Pro USB flatbed scanner. See .BR sane\-mustek_usb2 (5) for details. .TP .B nec The SANE nec backend supports the NEC PC-IN500/4C SCSI scanner. See .BR sane\-nec (5) for details. .TP .B niash The niash backend supports the Agfa Snapscan Touch and the HP ScanJet 3300c, 3400c, and 4300c USB flatbed scanners. See .BR sane\-niash (5) for details. .TP .B p5 The SANE backend for Primax PagePartner. See .BR sane\-p5 (5) for details. .TP .B pie The pie backend provides access to Pacific Image Electronics (PIE) and Devcom SCSI flatbed scanners. See .BR sane\-pie (5) for details. .TP .B pixma The pixma backend supports Canon PIXMA MP series (multi-function devices). See .BR sane\-pixma (5) or .I http://home.arcor.de/wittawat/pixma/ for details. .TP .B plustek The SANE plustek backend supports USB flatbed scanners that use the National Semiconductor LM983[1/2/3] chipset aka Merlin. Scanners using this LM983x chips include some models from Plustek, KYE/Genius, Hewlett-Packard, Mustek, Umax, Epson, and Canon. See .BR sane\-plustek (5) for details. .TP .B plustek_pp The SANE plustek_pp backend supports Plustek parallel port flatbed scanners. Scanners using the Plustek ASIC P96001, P96003, P98001 and P98003 include some models from Plustek, KYE/Genius, Primax. See .BR sane\-plustek_pp (5) for details. .TP .B ricoh The ricoh backend provides access to the following Ricoh flatbed scanners: IS50 and IS60. See .BR sane\-ricoh (5) for details. .TP .B s9036 The s9036 backend provides access to Siemens 9036 flatbed scanners. See .BR sane\-s9036 (5) for details. .TP .B sceptre The sceptre backend provides access to the Sceptre S1200 flatbed scanner. See .BR sane\-sceptre (5) for details. .TP .B sharp The SANE sharp backend supports Sharp SCSI scanners. See .BR sane\-sharp (5) for details. .TP .B sm3600 The SANE sm3600 backend supports the Microtek ScanMaker 3600 USB scanner. See .BR sane\-sm3600 (5) for details. .TP .B sm3840 The SANE sm3840 backend supports the Microtek ScanMaker 3840 USB scanner. See .BR sane\-sm3840 (5) for details. .TP .B snapscan The snapscan backend supports AGFA SnapScan flatbed scanners. See .BR sane\-snapscan (5) for details. .TP .B sp15c This backend supports the Fujitsu FCPA ScanPartner 15C flatbed scanner. See .BR sane\-sp15c (5) for details. .TP .B st400 The sane\-st400 backend provides access to Siemens ST400 and ST800. See .BR sane\-st400 (5) for details. .TP .B tamarack The SANE tamarack backend supports Tamarack Artiscan flatbed scanners. See .BR sane\-tamarack (5) for details. .TP .B teco1 teco2 teco3 The SANE teco1, teco2 and teco3 backends support some TECO scanners, usually sold under the Relisys, Trust, Primax, Piotech, Dextra names. See .BR sane\-teco1 "(5), " sane\-teco2 "(5) and " sane\-teco3 (5) for details. .TP .B u12 The sane\-u12 backend provides USB flatbed scanners based on Plustek's ASIC 98003 (parallel-port ASIC) and a GeneSys Logics' USB-parport bridge chip like the Plustek OpticPro U(T)12. See .BR sane\-u12 (5) for details. .TP .B umax The sane\-umax backend provides access to several UMAX-SCSI-scanners and some Linotype Hell SCSI-scanners. See .BR sane\-umax (5) for details. .TP .B umax_pp The sane\-umax_pp backend provides access to Umax parallel port flatbed scanners and the HP 3200C. See .BR sane\-umax_pp (5) for details. .TP .B umax1200u The sane\-umax1220u backend supports the UMAX Astra 1220U (USB) flatbed scanner (and also the UMAX Astra 2000U, sort of). See .BR sane\-umax1220u (5) for details. .TP .B xerox_mfp The sane\-xerox_mfp backend supports multiple Samsung-based Samsung, Xerox, and Dell scanners. See .BR sane\-xerox_mfp (5) for details. .PP Also, have a look at the backend information page at .I http://www.sane\-project.org/sane\-supported\-devices.html and the list of projects in .IR @DOCDIR@/PROJECTS . .SH "BACKENDS FOR DIGITAL CAMERAS" .TP 2 .B dc210 Backend for Kodak DC210 Digital Camera. See .BR sane\-dc210 (5). .TP .B dc240 Backend for Kodak DC240 Digital Camera. See .BR sane\-dc240 (5). .TP .B dc25 Backend for Kodak DC20/DC25 Digital Cameras. See .BR sane\-dc25 (5). .TP .B dmc Backend for the Polaroid Digital Microscope Camera. See .BR sane\-dmc (5). .TP .B gphoto2 Backend for digital cameras supported by the gphoto2 library package. (See .I http://www.gphoto.org for more information and a list of supported cameras.) Gphoto2 supports over 140 different camera models. However, please note that more development and testing is needed before all of these cameras will be supported by .B SANE backend. See .BR sane\-gphoto2 (5). .TP .B qcam Backend for Connectix QuickCam cameras. See .BR sane\-qcam (5). .TP .B stv680 The sane\-st680 backend provides access to webcams with a stv680 chip. See .BR sane\-st680 (5) for details. .PP Also, have a look at the backend information page at .I http://www.sane\-project.org/sane\-supported\-devices.html and the list of projects in .IR @DOCDIR@/PROJECTS . .SH "MISCELLANEOUS BACKENDS" .TP 2 .B dll The sane\-dll library implements a .B SANE backend that provides access to an arbitrary number of other .B SANE backends by dynamic loading. See .BR sane\-dll (5). .TP .B net The .B SANE network daemon saned provides access to scanners located on different computers in connection with the net backend. See .BR sane\-net "(5) and " saned (8). .TP .B pnm PNM image reader pseudo-backend. The purpose of this backend is primarily to aid in debugging of .B SANE frontends. See .BR sane\-pnm (5). .TP .B pint Backend for scanners that use the .B PINT (Pint Is Not Twain) device driver. The .B PINT driver is being actively developed on the OpenBSD platform, and has been ported to a few other *nix-like operating systems. See .BR sane\-pint (5). .TP .B test The .B SANE test backend is for testing frontends and the .B SANE installation. It provides test pictures and various test options. See .BR sane\-test (5). .TP .B v4l The sane\-v4l library implements a .B SANE backend that provides generic access to video cameras and similar equipment using the .B V4L (Video for Linux) API. See .BR sane\-v4l (5) . .PP Also, have a look at the backend information page at .I http://www.sane\-project.org/sane\-supported\-devices.html and the list of projects in .IR @DOCDIR@/PROJECTS . .SH "CHANGING THE TOP-LEVEL BACKEND" By default, all .B SANE backends (drivers) are loaded dynamically by the .B sane\-dll meta backend. If you have any questions about the dynamic loading, read .BR sane\-dll (5). .B SANE frontend can also be linked to other backends directly by copying or linking a backend to .B libsane.so in .IR @LIBDIR@ . .PP .SH "DEVELOPER'S DOCUMENTATION" It's not hard to write a .B SANE backend. It can take some time, however. You should have basic knowledge of C and enough patience to work through the documentation and find out how your scanner works. Appended is a list of some documents that help to write backends and frontends. .PP The .B SANE standard defines the application programming interface (API) that is used to communicate between frontends and backends. It can be found at .I @DOCDIR@/sane.ps (if latex is installed on your system) and on the .B SANE website: .I http://www.sane\-project.org/html/ (HTML), or .I http://www.sane\-project.org/sane.ps (Postscript). .PP There is some more information for programmers in .IR @DOCDIR@/backend\-writing.txt . Most of the internal .B SANE routines .RB ( sanei ) are documented using doxygen: .IR http://www.sane\-project.org/sanei/ . Before a new backend or frontend project is started, have a look at .I @DOCDIR@/PROJECTS for projects that are planned or not yet included into the .B SANE distribution and at our bug-tracking system: .IR http://www.http://www.sane\-project.org/bugs.html . .PP There are some links on how to find out about the protocol of a scanner: .IR http://www.meier\-geinitz.de/sane/misc/develop.html . .PP If you start writing a backend or frontend or any other part of .BR SANE, please contact the sane\-devel mailing list for coordination so the same work isn't done twice. .SH "FILES" .TP .I @CONFIGDIR@/*.conf The backend configuration files. .TP .I @LIBDIR@/libsane\-*.a The static libraries implementing the backends. .TP .I @LIBDIR@/libsane\-*.so The shared libraries implementing the backends (present on systems that support dynamic loading). .TP .I @DOCDIR@/* .B SANE documentation: The standard, READMEs, text files for backends etc. .SH "PROBLEMS" If your device isn't found but you know that it is supported, make sure that it is detected by your operating system. For SCSI and USB scanners, use the .B sane\-find\-scanner tool (see .BR sane\-find\-scanner (1) for details). It prints one line for each scanner it has detected and some comments (#). If .B sane\-find\-scanner finds your scanner only as root but not as normal user, the permissions for the device files are not adjusted correctly. If the scanner isn't found at all, the operating system hasn't detected it and may need some help. Depending on the type of your scanner, read .BR sane\-usb (5) or .BR sane\-scsi (5). If your scanner (or other device) is not connected over the SCSI bus or USB, read the backend's manual page for details on how to set it up. .PP Now your scanner is detected by the operating system but not by .BR SANE ? Try .BR "scanimage \-L" . If the scanner is not found, check that the backend's name is mentioned in .IR @CONFIGDIR@/dll.conf . Some backends are commented out by default. Remove the comment sign for your backend in this case. Also some backends aren't compiled at all if one of their prerequisites are missing. Examples include dc210, dc240, canon_pp, hpsj5s, gphoto2, pint, qcam, v4l, net, sm3600, snapscan, pnm. If you need one of these backends and they aren't available, read the build instructions in the .B README file and the individual manual pages of the backends. .PP Another reason for not being detected by .B scanimage \-L may be a missing or wrong configuration in the backend's configuration file. While .B SANE tries to automatically find most scanners, some can't be setup correctly without the intervention of the administrator. Also on some operating systems auto-detection may not work. Check the backend's manual page for details. .PP If your scanner is still not found, try setting the various environment variables that are available to assist in debugging. The environment variables are documented in the relevant manual pages. For example, to get the maximum amount of debug information when testing a Mustek SCSI scanner, set environment variables .BR SANE_DEBUG_DLL ", " SANE_DEBUG_MUSTEK ", and " SANE_DEBUG_SANEI_SCSI to 128 and then invoke .B scanimage .B \-L . The debug messages for the dll backend tell if the mustek backend was found and loaded at all. The mustek messages explain what the mustek backend is doing while the SCSI debugging shows the low level handling. If you can't find out what's going on by checking the messages carefully, contact the sane\-devel mailing list for help (see REPORTING BUGS below). .PP Now that your scanner is found by .BR "scanimage \-L" , try to do a scan: .BR "scanimage >image.pnm" . This command starts a scan for the default scanner with default settings. All the available options are listed by running .BR "scanimage \-\-help" . If scanning aborts with an error message, turn on debugging as mentioned above. Maybe the configuration file needs some tuning, e.g. to setup the path to a firmware that is needed by some scanners. See the backend's manual page for details. If you can't find out what's wrong, contact sane\-devel. .PP To check that the .B SANE libraries are installed correctly you can use the test backend, even if you don't have a scanner or other .B SANE device: .IP .B scanimage \-d .I test .B \-T .PP You should get a list of PASSed tests. You can do the same with your backend by changing "test" to your backend's name. .PP So now scanning with .B scanimage works and you want to use one of the graphical frontends like .BR xsane , .BR xscanimage ", or" .B quiteinsane but those frontends don't detect your scanner? One reason may be that you installed two versions of .BR SANE . E.g. the version that was installed by your distribution in .I /usr and one you installed from source in .IR /usr/local/ . Make sure that only one version is installed. Another possible reason is, that your system's dynamic loader can't find the .B SANE libraries. For Linux, make sure that .I /etc/ld.so.conf contains .I /usr/local/lib and does .B not contain .IR /usr/local/lib/sane . See also the documentation of the frontends. .PP .SH "HOW CAN YOU HELP SANE" We appreciate any help we can get. Please have a look at our web page about contributing to .BR SANE : .I http://www.sane\-project.org/contrib.html .PP .SH "CONTACT" For reporting bugs or requesting new features, please use our bug-tracking system: .IR http://www.sane\-project.org/bugs.html . You can also contact the author of your backend directly. Usually the email address can be found in the .I @DOCDIR@/AUTHORS file or the backend's manpage. For general discussion about SANE, please use the .B SANE mailing list sane\-devel (see .I http://www.sane\-project.org/mailing\-lists.html for details). .PP .SH "SEE ALSO" .BR saned (8), .BR sane\-find\-scanner (1), .BR scanimage (1), .BR sane\-abaton (5), .BR sane\-agfafocus (5), .BR sane\-apple (5), .BR sane\-artec (5), .BR sane\-artec_eplus48u (5), .BR sane\-as6e (5), .BR sane\-avision (5), .BR sane\-bh (5), .BR sane\-canon (5), .BR sane\-canon630u (5), .BR sane\-canon_dr (5), .BR sane\-canon_pp (5), .BR sane\-cardscan (5), .BR sane\-coolscan2 (5), .BR sane\-coolscan (5), .BR sane\-dc210 (5), .BR sane\-dc240 (5), .BR sane\-dc25 (5), .BR sane\-dll (5), .BR sane\-dmc (5), .BR sane\-epson (5), .BR sane\-fujitsu (5), .BR sane\-genesys (5), .BR sane\-gphoto2 (5), .BR sane\-gt68xx (5), .BR sane\-hp (5), .BR sane\-hpsj5s (5), .BR sane\-hp3500 (5), .BR sane\-hp3900 (5), .BR sane\-hp4200 (5), .BR sane\-hp5400 (5), .BR sane\-hpljm1005 (5), .BR sane\-ibm (5), .BR sane\-kodak (5), .BR sane\-leo (5), .BR sane\-lexmark (5), .BR sane\-ma1509 (5), .BR sane\-matsushita (5), .BR sane\-microtek2 (5), .BR sane\-microtek (5), .BR sane\-mustek (5), .BR sane\-mustek_pp (5), .BR sane\-mustek_usb (5), .BR sane\-mustek_usb2 (5), .BR sane\-nec (5), .BR sane\-net (5), .BR sane\-niash (5), .BR sane\-pie (5), .BR sane\-pint (5), .BR sane\-plustek (5), .BR sane\-plustek_pp (5), .BR sane\-pnm (5), .BR sane\-qcam (5), .BR sane\-ricoh (5), .BR sane\-s9036 (5), .BR sane\-sceptre (5), .BR sane\-scsi (5), .BR sane\-sharp (5), .BR sane\-sm3600 (5), .BR sane\-sm3840 (5), .BR sane\-snapscan (5), .BR sane\-sp15c (5), .BR sane\-st400 (5), .BR sane\-stv680 (5), .BR sane\-tamarack (5), .BR sane\-teco1 (5), .BR sane\-teco2 (5), .BR sane\-teco3 (5), .BR sane\-test (5), .BR sane\-u12 (5), .BR sane\-umax1220u (5), .BR sane\-umax (5), .BR sane\-umax_pp (5), .BR sane\-usb (5), .BR sane\-v4l (5), .BR sane\-xerox_mfp (5) .SH AUTHOR David Mosberger-Tang and many many more (see .I @DOCDIR@/AUTHORS for details). This man page was written by Henning Meier-Geinitz. Quite a lot of text was taken from the .B SANE standard, several man pages, and README files. sane-backends-1.0.27/doc/sane-pieusb.man0000664000175000017500000000616012775312262014711 00000000000000.TH sane\-pieusb 5 "10 Aug 2015" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-pieusb .SH NAME sane\-pieusb \- SANE backend for USB-connected PIE PowerSlide and Reflecta DigitDia/CrystalScan/ProScan slide scanners .SH DESCRIPTION The .B sane\-pieusb library implements a SANE (Scanner Access Now Easy) backend that provides access to USB-connected PIE and Reflecta slide scanners. .br At present, the following scanners should work with this backend: .PP .ft CR .nf Model: Status ------------------------- ------ PIE PowerSlide 3600 Untested PIE PowerSlide 3650 Untested PIE PowerSlide 4000 Untested PIE PowerSlide 5000 Untested Reflecta CrystalScan 7200 Untested Reflecta ProScan 4000 Untested Reflecta ProScan 7200 Untested Reflecta DigitDia 3600 Untested Reflecta DigitDia 4000 Untested Reflecta DigitDia 5000 Untested Reflecta DigitDia 6000 Ok .fi .ft R .PP .SH "MULTIPLE SLIDES" Support for multiple slide scanners (like the PowerSlide or DigitDia series) is done by auto-advancing ('Advance slide' setting) the slide after each scan. However, for best results, it is recommended to do a preview for every slide since this sets gamma, brightness, and contrast to optimal values. Attention: SANE does not have an automatic landscape/portrait detection and re-orientation when scanning multiple slides. You have to put all slides into one orientation first ! .SH "DIRT REMOVAL" If available, pieusb supports infrared scans for dirt detection and removal. This must be enabled via the 'Clean image' setting. .SH "KNOWN PROBLEMS" The pieusb backend supports dirt removal based on infrared scan information. Since SANE does not provide post-processing in the backend, pieusb does the scanning and dirt removal during the setup phase. The 'scan' phase is only used to transfer the completed image. Therefore pieusb does not multi-thread making a typical frontend appear as 'blocked'. Also cancel requests are only honored between scans. .SH "ENVIRONMENT" .TP .B SANE_DEBUG_PIEUSB If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .PP .RS .ft CR .nf level debug output \-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- 0 nothing 1 errors 2 warnings & minor errors 5 additional information 7 SANE api calls 9 backend functions 11 scanner functions 13 usb functions 15 image buffer functions .fi .ft R .RE .PP .SH FILES .TP .I @CONFIGDIR@/pieusb.conf The backend configuration file .TP .I @LIBDIR@/libsane\-pieusb.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-pieusb.so The shared library implementing this backend (present on systems that support dynamic loading). .PP .SH SEE ALSO sane(7) .SH "CONTACT AND BUG-REPORTS" Please send any information and bug-reports to: .br .B Klaus Kämpf .SH AUTHORS The pieusb backend is based on work by Jan Vleeshouwers, Michael Rickmann, and Klaus Kämpf sane-backends-1.0.27/doc/sane-bh.man0000664000175000017500000004565212112021330013776 00000000000000.TH sane\-bh 5 "10 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-bh .SH NAME sane\-bh \- SANE backend for Bell+Howell Copiscan II series document scanners .SH DESCRIPTION The .B sane\-bh library implements a SANE (Scanner Access Now Easy) backend that provides access to Bell+Howell Copiscan II series document scanners. The Copiscan II 6338 has been the primary scanner model used during development and testing, but since the programming interface for the entire series is consistent the backend should work for the following scanner models. .PP .RS COPISCAN II 6338 Duplex Scanner with ACE .br COPISCAN II 2135 Simplex Scanner .br COPISCAN II 2137(A) Simplex Scanner (with ACE) .br COPISCAN II 2138A Simplex Scanner with ACE .br COPISCAN II 3238 Simplex Scanner .br COPISCAN II 3338(A) Simplex Scanner (with ACE) .br .RE .PP If you have a Bell+Howell scanner and are able to test it with this backend, please contact .IR sane\-devel@lists.alioth.debian.org with the model number and testing results. Have a look at http://www.sane\-project.org/mailing\-lists.html concerning subscription to sane\-devel. Additionally, the author is curious as to the likelihood of using this backend with the newer 4000 and 8000 series scanners. If you have such a beast, please let me know. .PP The Bell+Howell Copiscan II series document scanners are high volume, high throughput scanners designed for document scanning applications. As such, they are lineart/grayscale scanners supporting a fixed number of fairly low resolutions (e.g. 200/240/300dpi). However, they do have a number of interesting and useful features suited to needs of document imaging applications. This backend attempts to support as many of these features as possible. .PP The main technical reference used in writing this backend is the .B Bell and Howell Copiscan II Remote SCSI Controller (RSC) OEM .B Technical Manual Version 1.5. The Linux SCSI programming HOWTO, the SANE API documentation, and SANE source code were also extremely valuable resources. .PP The latest backend release, additional information and helpful hints are available from the backend homepage: .br .RS .B http://www.martoneconsulting.com/sane\-bh.html .RE .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the path-name for the special device that corresponds to a SCSI scanner. For SCSI scanners, the special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name takes a format such as .I /dev/sga or .IR /dev/sg0 , for example. See sane\-scsi(5) for details. .SH CONFIGURATION The contents of the .I bh.conf file is a list of device names that correspond to Bell+Howell scanners. See sane\-scsi(5) on details of what constitutes a valid device name. Additionally, options can be specified; these lines begin with the word "option". Each option is described in detail below. Empty lines and lines starting with a hash mark (#) are ignored. .SH OPTIONS The following options can be specified in the .I bh.conf file. .TP .B disable\-optional\-frames This option prevents the backend from sending any optional frames. This option may be useful when dealing with frontends which do not support these optional frames. When this option is in effect, the data is sent in a SANE_FRAME_GRAY frame. The optional frames sent by this backend are: SANE_FRAME_G31D, SANE_FRAME_G32D, SANE_FRAME_G42D and SANE_FRAME_TEXT. These frames are generated based on the compression and barcode options. These frames are never sent in preview mode. .TP .B fake\-inquiry This option is used for debugging purposes and its use is not encouraged. Essentially, it allows the backend to initialize in the absence of a scanner. This is useful for development and not much else. This option must be specified earlier in the configuration file than the devices which are to be "faked". .SH FILES .TP .I @CONFIGDIR@/bh.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-bh.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-bh.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_BH If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 255 requests all debug output to be printed. Smaller levels reduce verbosity. .SH "SUPPORTED FEATURES" .TP .B ADF support With document scanners, automatic document feeder (ADF) support is a key feature. The backend supports the ADF by default and returns .B SANE_STATUS_NO_DOCS when the out-of-paper condition is detected. The SANE frontend .B scanadf is a command line frontend that supports multi-page scans. It has been used successfully with this backend. The SANE frontend .B xsane is an improved GUI frontend by Oliver Rauch. Support for multi-page scans is included in xsane version 0.35 and above. .TP .B Duplex scanning Some models, such as the COPISCAN II 6338, support duplex scanning. That is, they scan both sides of the document during a single pass through the scanner (the scanner has two cameras). This backend supports duplex scanning (with the .B \-\-duplex option). The front and back page images are delivered consecutively as if they were separately scanned pages. .TP .B Hardware compression The scanner is capable of compressing the data into several industry standard formats (CCITT G3, CCITT G3-2D, CCITT G4). This results in increased performance as less data is passed from the scanner to the host over the SCSI bus. The backend supports these compression formats via the .B \-\-g31d, \-\-g32d, \-\-g42d options, respectively. Many SANE frontends are not equipped to deal with these formats, however. The SANE frontend .B scanadf supports these optional frame formats. The compressed image data is written directly to a file and can then be processed by a scan-script using the .B \-\-scan\-script option. Examples of this are given on the scanadf homepage. .TP .B Automatic Border Detection The scanner can automatically detect the paper size and adjust the scanning window geometry appropriately. The backend supports this useful feature with the .B \-\-autoborder option. It is enabled by default. .TP .B Batch Mode Scanning The batch scan mode allows for maximum throughput. The Set Window parameters must remain constant during the entire batch. .TP .B Icon Generation The Icon function generates a thumbnail of the full page image, that can be transferred as if it were a separate page. This allows the host to quickly display a thumbnail representation during the scanning operation. Perhaps this would be a great way of implementing a preview scan, but since a normal scan is so quick, it might not be worth the trouble. .TP .B Multiple Sections Multiple sections (scanning sub-windows) can be defined for the front and back pages. Each section can have different characteristics (e.g. geometry, compression). The sections are returned as if they were separately scanned images. Additionally sections can be used to greatly enhance the accuracy and efficiency of the barcode/patchcode decoding process by limiting the search area to a small subset of the page. Most Copiscan II series scanners support up to 8 user-defined sections. .TP .B Support Barcode/Patchcode Decoding The RSC unit can recognize Bar and Patch Codes of various types embedded in the scanned image. The codes are decoded and the data is returned to the frontend as a text frame. The text is encoded in xml and contains a great deal of information about the decoded data such as the location where it was found, its orientation, and the time it took to find. Further information on the content of this text frame as well as some barcode decoding examples can be found on the backend homepage. .SH LIMITATIONS .TP .B Decoding a single barcode type per scan The RSC unit can search for up to six different barcode types at a time. While the code generally supports this as well, the .B \-\-barcode\-search\-bar option only allows the user to specify a single barcode type. Perhaps another option which allows a comma separated list of barcode type codes could be added to address this. .TP .B Scanning a fixed number of pages in batch mode The separation of front and back end functionality in SANE presents a problem in supporting the 'cancel batch' functionality in the scanner. In batch mode, the scanner is always a page ahead of the host. The host, knowing ahead of time which page will be the last, can cancel batch mode prior to initiating the last scan command. Currently, there is no mechanism available for the frontend to pass this knowledge to the backend. If batch mode is enabled and the \-\-end\-count terminates a scanadf session, an extra page will be pulled through the scanner, but is neither read nor delivered to the frontend. The issue can be avoided by specifying \-\-batch=no when scanning a fixed number of pages. .TP .B Revision 1.2 Patch detector There is an enhanced patchcode detection algorithm available in the RSC with revision 1.2 or higher that is faster and more reliable than the standard Bar/Patch code decoder. This is not currently supported. .SH OPTIONS .TP .B Scan Mode Options: .TP .B \-\-preview[=(yes|no)] [no] Request a preview-quality scan. When preview is set to yes image compression is disabled and the image is delivered in a SANE_FRAME_GRAY frame. .TP .B \-\-mode lineart|halftone [lineart] Selects the scan mode (e.g., lineart,monochrome, or color). .TP .B \-\-resolution 200|240|300dpi [200] Sets the resolution of the scanned image. Each scanner model supports a list of standard resolutions; only these resolutions can be used. .TP .B \-\-compression none|g31d|g32d|g42d [none] Sets the compression mode of the scanner. Determines the type of data returned from the scanner. Values are: .RS .br .B none \- uncompressed data \- delivered in a SANE_FRAME_GRAY frame .br .B g31d \- CCITT G3 1 dimension (MH) \- delivered in a SANE_FRAME_G31D frame .br .B g32d \- CCITT G3 2 dimensions (MR, K=4) \- delivered in a SANE_FRAME_G32D frame .br .B g42d \- CCITT G4 (MMR) \- delivered in a SANE_FRAME_G42D frame .br NOTE: The use of g31d, g32d, and g42d compression values causes the backend to generate optional frame formats which may not be supported by all SANE frontends. .RE .TP .B Geometry Options: .TP .B \-\-autoborder[=(yes|no)] [yes] Enable/Disable automatic image border detection. When enabled, the RSC unit automatically detects the image area and sets the window geometry to match. .TP .B \-\-paper\-size Custom|Letter|Legal|A3|A4|A5|A6|B4|B5 [Custom] Specify the scan window geometry by specifying the paper size of the documents to be scanned. .TP .B \-\-tl\-x 0..297.18mm [0] Top-left x position of scan area. .TP .B \-\-tl\-y 0..431.8mm [0] Top-left y position of scan area. .TP .B \-\-br\-x 0..297.18mm [297.18] Bottom-right x position of scan area. .TP .B \-\-br\-y 0..431.8mm [431.8] Bottom-right y position of scan area. .TP .B Feeder Options: .TP .B \-\-source Automatic Document Feeder|Manual Feed Tray [Automatic Document Feeder] Selects the scan source (such as a document feeder). This option is provided to allow multiple image scans with xsane; it has no other purpose. .TP .B \-\-batch[=(yes|no)] [no] Enable/disable batch mode scanning. Batch mode allows scanning at maximum throughput by buffering within the RSC unit. This option is recommended when performing multiple pages scans until the feeder is emptied. .TP .B \-\-duplex[=(yes|no)] [no] Enable duplex (dual-sided) scanning. The scanner takes an image of each side of the document during a single pass through the scanner. The front page is delivered followed by the back page. Most options, such as compression, affect both the front and back pages. .TP .B \-\-timeout\-adf 0..255 [0] Sets the timeout in seconds for the automatic document feeder (ADF). The value 0 specifies the hardware default value which varies based on the scanner model. .TP .B \-\-timeout\-manual 0..255 [0] Sets the timeout in seconds for semi-automatic feeder. The value 0 specifies the hardware default value which varies based on the scanner model. .TP .B \-\-check\-adf[=(yes|no)] [no] Check ADF Status prior to starting scan using the OBJECT POSITION command. Note that this feature requires RSC firmware level 1.5 or higher and dip switch 4 must be in the on position. NOTE: This option has not been tested extensively and may produce undesirable results. .TP .B Enhancement: .TP .B \-\-control\-panel[=(yes|no)] [yes] Enables the scanner's control panel for selecting image enhancement parameters. When the option is set to no the following options are used to control image enhancement. See the Bell+Howell scanner users' guide for complete information on ACE functionality. .TP .B \-\-ace\-function \-4..4 [3] Specify the Automatic Contrast Enhancement (ACE) Function. .TP .B \-\-ace\-sensitivity 0..9 [5] Specify the Automatic Contrast Enhancement (ACE) Sensitivity. .TP .B \-\-brightness 0..255 [0] Controls the brightness of the acquired image. Ignored for ACE capable scanners. .TP .B \-\-threshold 0..255 [0] Select minimum-brightness to get a white point. Ignored for ACE capable scanners. .TP .B \-\-contrast 0..255 [inactive] Controls the contrast of the acquired image. This option is not currently used by the scanner (and perhaps never will be). .TP .B \-\-negative[=(yes|no)] [no] Swap black and white, yielding a reverse-video image. .TP .B Icon: .TP .B \-\-icon\-width 0..3600pel (in steps of 8) [0] Width of icon (thumbnail) image in pixels. .TP .B \-\-icon\-length 0..3600pel (in steps of 8) [0] Length of icon (thumbnail) image in pixels. .TP .B Barcode Options: .TP .B \-\-barcode\-search\-bar [none] Specifies the barcode type to search for. If this option is not specified, or specified with a value of none, then the barcode decoding feature is completely disabled. The valid barcode type are: .RS .br .B none .br .B ean\-8 .br .B ean\-13 .br .B reserved\-ean\-add .br .B code39 .br .B code2\-5\-interleaved .br .B code2\-5\-3lines\-matrix .br .B code2\-5\-3lines\-datalogic .br .B code2\-5\-5lines\-industrial .br .B patchcode .br .B codabar .br .B codabar\-with\-start\-stop .br .B code39ascii .br .B code128 .br .B code2\-5\-5lines\-iata .br .RE .TP .B \-\-barcode\-search\-count 1..7 [3] Number of times that the RSC performs the decoding algorithm. Specify the smallest number possible to increase performance. If you are having trouble recognizing barcodes, it is suggested that you increase this option to its maximum value (7). .TP .B \-\-barcode\-search\-mode [horiz\-vert] Chooses the orientation of barcodes to be searched. The valid orientations are: .RS .br .B horiz\-vert .br .B horizontal .br .B vertical .br .B vert\-horiz .RE .TP .B \-\-barcode\-hmin 0..1660mm [5] Sets the barcode minimum height in millimeters (larger values increase recognition speed). Of course the actual barcodes in the document must be of sufficient size. .TP .B \-\-barcode\-search\-timeout 20..65535us [10000] Sets the timeout for barcode searching in milliseconds. When the timeout expires, the decoder will stop trying to decode barcodes. .TP .B \-\-section [] Specifies a series of image sections. A section can be used to gather a subset image or to provide a small area for barcode decoding. Each section is specified in the following format (units are in millimeters): .PP .B x++[:functioncode...] .PP Multiple sections can be specified by separating them with commas. .PP For example .B 76.2x25.4+50.8+0:frontbar identifies an area 3 inches wide and 1 inch high with a top left corner at the top of the page two inches from the left hand edge of the page. This section will be used for barcode decoding on the front page only. .PP For example .B 50.8x25.4+25.4+0:frontbar:front:g42d identifies an area 2 inches wide and 1 inch high with a top left corner at the top of the page one inch from the left hand edge of the page. This section will be used for barcode decoding on the front page as well as generating an image compressed in g42d format. .PP Ordinarily barcodes are searched in the entire image. However, when you specify sections all barcode searching is done within the specific sections identified. This can significantly speed up the decoding process. The following functioncodes are available: .RS .br .B front \- generate an image for the front page section .br .B back \- generate an image for the back page section .br .B frontbar \- perform barcode search in front page section .br .B backbar \- perform barcode search in back page section .br .B frontpatch \- perform patchcode search in front page section .br .B backpatch \- perform patchcode search in back page section .br .B none \- use no image compression .br .B g31d \- use Group 3 1 dimension image compression .br .B g32d \- use Group 3 2 dimensions image compression .br .B g42d \- use Group 4 2 dimensions image compression .br .RE .PP If you omit a compression functioncode, the full page compression setting is used. If you specify multiple compression functioncodes, only the last one is used. .TP .B \-\-barcode\-relmax 0..255 [0] Specifies the maximum relation from the widest to the smallest bar. .TP .B \-\-barcode\-barmin 0..255 [0] Specifies the minimum number of bars in Bar/Patch code. .TP .B \-\-barcode\-barmax 0..255 [0] Specifies the maximum number of bars in a Bar/Patch code. .TP .B \-\-barcode\-contrast 0..6 [3] Specifies the image contrast used in decoding. Use higher values when there are more white pixels in the code. .TP .B \-\-barcode\-patchmode 0..1 [0] Controls Patch Code detection. .SH BUGS This is a new backend; detailed bug reports are welcome -- and expected ;) .PP If you have found something that you think is a bug, please attempt to recreate it with the SANE_DEBUG_BH environment variable set to 255, and send a report detailing the conditions surrounding the bug to .IR sane\-devel@lists.alioth.debian.org . .SH "SEE ALSO" sane(7), sane\-scsi(5), scanimage(1), scanadf(1) .SH AUTHOR The sane\-bh backend was written by Tom Martone, based on the sane\-ricoh backend by Feico W. Dillema and the bnhscan program by Sean Reifschneider of tummy.com ltd. Some 8000 enhancements added by Mark Temple. sane-backends-1.0.27/doc/sane-sm3840.man0000664000175000017500000000457412112021330014341 00000000000000.TH sane\-sm3840 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-sm3840 .SH NAME sane\-sm3840 \- SANE backend for Microtek scanners with SCAN08 USB chip .SH DESCRIPTION The .B sane\-sm3840 library implements a SANE (Scanner Access Now Easy) backend that provides access to some Microtek scanners with the SCAN08 USB chip. .PP There exist backends for Microtek scanners with SCSI command set. Refer to sane\-microtek(5) and sane\-microtek2(5) for details. .PP There also exists a Microtek 3600 series driver, see sane\-sm3600(5) for details. .PP At present, the following scanners are known positively to work with this backend: .PP .RS .ft CR .nf Vendor Product ID: Remark: -------- -------------- ----------- Microtek ScanMaker 3840 All modes OK Microtek ScanMaker 4800 All modes OK .fi .ft R .RE .PP If you own a Microtek scanner with the SCAN08 chip other than the ones listed above, it may or may not work with SANE. Feel free to contact the backend author (earle@ziplabel.com) to report results with scanners not on the list. .SH "FRONTEND OPTIONS" .PP The following options are supported by the sm3840-driver: .PP .B \-\-mode color|gray|lineart|halftone .br Color or grayscale mode. .B \-\-resolution 150|300|600|1200 .br Pixels per inch for scans. .B \-\-depth 8|16 .br Note that the least significant bits of 16bpp mode may be noise. .B \-\-brightness 1..4096 .br Higher numbers increase brightness of returned image. .B \-\-contrast 0.1..9.9 .br Larger numbers decrease contrast of returned image. .B \-\-lamp\-timeout 1..15 .br Time in minutes until the lamp is turned off after a scan. .SH CONFIGURATION This backend does not support a configuration file right now. .SH FILES .TP .I @LIBDIR@/libsane\-sm3840.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-sm3840.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_SM3840 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. To see error messages on stderr set SANE_DEBUG_SM3840 to 1. .SH "SEE ALSO" sane\-microtek2(5), sane\-sm3600(5), http://www.ziplabel.com/sm3840 .SH AUTHOR .br Earle F. Philhower III (earle@ziplabel.com) .br sane-backends-1.0.27/doc/sane-ricoh.man0000664000175000017500000000424112112021330014476 00000000000000.TH sane\-ricoh 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-ricoh .SH NAME sane\-ricoh \- SANE backend for Ricoh flatbed scanners .SH DESCRIPTION The .B sane\-ricoh library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Ricoh flatbed scanners: .PP .RS IS50 .br IS60 .br .RE .PP .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is the path-name for the special device that corresponds to a SCSI scanner. The special device name must be a generic SCSI device or a symlink to such a device. The program .IR sane\-find\-scanner helps to find out the correct device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. See sane\-scsi(5) for details. .SH FILES .TP .I @CONFIGDIR@/ricoh.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-ricoh.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-ricoh.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_RICOH If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_RICOH=4 .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHOR Feico W. Dillema sane-backends-1.0.27/doc/sane-plustek.man0000664000175000017500000003252612775277260015126 00000000000000.TH sane\-plustek 5 "13 Feb 2013" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-plustek .SH NAME sane\-plustek \- SANE backend for LM983[1/2/3] based USB flatbed scanners .SH DESCRIPTION The .B sane\-plustek library implements a SANE (Scanner Access Now Easy) backend that provides access to USB flatbed scanners based on National Semiconductor Merlin chipsets (LM9831, 9832 and 9833). If you're looking for parallel-port support for Plustek scanner please refer to the .B sane\-plustek_pp backend. .SH "SUPPORTED DEVICES" The Backend is able to support USB scanner based on the National Semiconductor chipsets LM9831, LM9832 and LM9833. The following tables show various devices which are currently reported to work. If your Plustek scanner has another Product ID, then the device is .B NOT supported by this backend. .br Vendor Plustek \- ID: 0x07B3 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- OpticPro U12 LM9831 600x1200dpi 42bit 512Kb 0x0010 OpticPro UT12 LM9831 600x1200dpi 42bit 512Kb 0x0013 OpticPro UT12 LM9832 600x1200dpi 42bit 512Kb 0x0017 OpticPro UT16 LM9832 600x1200dpi 42bit 512Kb 0x0017 OpticPro U24 LM9831 1200x2400dpi 42bit 2Mb 0x0011 OpticPro U24 LM9832 1200x2400dpi 42bit 2Mb 0x0015 OpticPro UT24 LM9832 1200x2400dpi 42bit 2Mb 0x0017 .fi .ft R .PP Vendor KYE/Genius \- ID: 0x0458 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- Colorpage HR6 V2 LM9832 600x1200dpi 42bit 512Kb 0x2007 Colorpage HR6 V2 LM9832 600x1200dpi 42bit 512Kb 0x2008 Colorpage HR6A LM9832 600x1200dpi 42bit 512Kb 0x2009 Colorpage HR7 LM9832 600x1200dpi 42bit 512Kb 0x2013 Colorpage HR7LE LM9832 600x1200dpi 42bit 512Kb 0x2015 Colorpage HR6X LM9832 600x1200dpi 42bit 512Kb 0x2016 .fi .ft R .PP Vendor Hewlett-Packard \- ID: 0x03F0 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- ScanJet 2100C LM9831 600x1200dpi 42bit 512Kb 0x0505 ScanJet 2200C LM9832 600x1200dpi 42bit 512Kb 0x0605 .fi .ft R .PP Vendor Mustek \- ID: 0x0400 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- BearPaw 1200 LM9831 600x1200dpi 42bit 512Kb 0x1000 BearPaw 1200 LM9832 600x1200dpi 42bit 512Kb 0x1001* BearPaw 2400 LM9832 1200x2400dpi 42bit 2Mb 0x1001 .fi .ft R * see also description for model override switch below! .PP Vendor UMAX \- ID: 0x1606 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- UMAX 3400 LM9832 600x1200dpi 42bit 512Kb 0x0050 UMAX 3400/3450 LM9832 600x1200dpi 42bit 512Kb 0x0060 UMAX 5400 LM9832 1200x2400dpi 42bit 512Kb 0x0160 .fi .ft R .PP Vendor COMPAQ \- ID: 0x049F .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- S4-100 LM9832 600x1200dpi 42bit 512Kb 0x001A .fi .ft R .PP Vendor Epson \- ID: 0x04B8 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- Perfection 1250 LM9832 1200x2400dpi 42bit 512Kb 0x010F Perfection 1260 LM9832 1200x2400dpi 42bit 512Kb 0x011D .fi .ft R .PP Vendor CANON \- ID: 0x04A9 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- CanoScan N650/656U LM9832 600x1200dpi 42bit 512Kb 0x2206 CanoScan N1220U LM9832 1200x2400dpi 42bit 512Kb 0x2207 CanoScan D660U LM9832 600x1200dpi 42bit 512Kb 0x2208 CanoScan N670/676U LM9833 600x1200dpi 48bit 512Kb 0x220D CanoScan N1240U LM9833 1200x2400dpi 48bit 512Kb 0x220E CanoScan LIDE20 LM9833 600x1200dpi 48bit 512Kb 0x220D CanoScan LIDE25 LM9833 1200x2400dpi 48bit 512Kb 0x2220 CanoScan LIDE30 LM9833 1200x2400dpi 48bit 512Kb 0x220E .fi .ft R .PP Vendor Syscan \- ID: 0x0A82 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- Travelscan 662 LM9833 600x1200dpi 48bit 512Kb 0x6620 Travelscan 464 LM9833 600x1200dpi 48bit 512Kb 0x4600 .fi .ft R .PP Vendor Portable Peripheral Co., Ltd. \- ID: 0x0A53 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- Q-Scan USB001 LM9832 300x600dpi 42bit 512Kb 0x1000 Q-Scan USB201 LM9832 300x600dpi 42bit 512Kb 0x2000 .fi .ft R .PP Vendor Visioneer \- ID: 0x04A7 .br .ft CR .nf ---------------------------------------------------------- USB Model: ASIC: Properties: Prod-ID ---------------------------------------------------------- Strobe XP100 LM9833 600x1200dpi 48bit 512Kb 0x0427 .fi .ft R .PP .SH "OTHER PLUSTEK SCANNERS" For parallelport device support see the .B plustek_pp backend. .br The SCSI scanner OpticPro 19200S is a rebadged Artec AM12S scanner and is supported by the .B Artec backend. .br Only the National Semiconductor LM983[1/2/] based devices of Plustek are supported by this backend. Older versions of the U12, the UT12, the U1212 and U1248 (GrandTech chipset) are not supported. .PP .ft CR .nf Model Chipset backend ------------------------------------ U1248 GrandTech gt68xx UT16B GrandTech gt68xx OpticSlim 1200 GrandTech gt68xx OpticSlim 2400 GrandTech gt68xx U12 P98003 u12 UT12 P98003 u12 1212U P98003 u12 .fi .ft R For a more complete and up to date list see: .B http://www.sane\-project.org/sane\-supported\-devices.html .SH "CONFIGURATION" To use your scanner with this backend, you need at least two entries in the configuration file .I @CONFIGDIR@/plustek.conf .RS .I [usb] vendor-id product-id .br .I device /dev/usbscanner .RE .PP .I [usb] tells the backend, that the following devicename (here .IR /dev/usbscanner ) has to be interpreted as USB scanner device. If vendor- and product-id has not been specified, the backend tries to detect this by its own. If device is set to .I auto then the next matching device is used. .br The following options can be used for a default setup of your device. Most of them are also available through the frontend. .PP .B The Options: .PP option warmup t .RS .I t specifies the warmup period in seconds, if set to \-1, the automatic warmup function will be used .RE .PP option lampOff t .RS .I t is the time in seconds for switching off the lamps in standby mode .RE .PP option lOffonEnd b .RS .I b specifies the behaviour when closing the backend, 1 --> switch lamps off, 0 --> do not change lamp status .RE .PP option mov m .RS .I m is the model override switch. It works only with Mustek BearPaw devices. .br .br .ft CR .nf m/PID | 0x1000 | 0x1001 ------+--------------+-------------- 0 | BearPaw 1200 | BearPaw 2400 1 | no function | BearPaw 1200 .fi .ft R .RE .PP option invertNegatives b .RS .I b 0 --> do not invert the picture during negativ scans, .br 1 --> invert picture .RE .PP option cacheCalData b .RS .I b 0 --> do not save calibration results, .br 1 --> save results of calibration in ~/.sane/ directory .RE .PP option altCalibration b .RS .I b 0 --> use standard calibration routines, .br 1 --> use alternate calibration (only non Plustek devices, standard for CIS devices) .RE .PP option skipFine b .RS .I b 0 --> perform fine calibration, .br 1 --> skip fine calibration (only non Plustek devices) .RE .PP option skipFineWhite b .RS .I b 0 --> perform white fine calibration, .br 1 --> skip white fine calibration (only non Plustek devices) .RE .PP option skipDarkStrip b .RS .I b 0 --> perform dark calibration, with enabled lamp using the dark calibration strip of the scanner. If the scanner does not have such a strip, the alternative way is to switch off the lamp during this step. .br 1 --> always switch off the lamp for dark calibration, even a black strip is available .RE .PP option skipCalibration b .RS .I b 0 --> perform calibration, .br 1 --> skip calibration (only non Plustek devices) .RE .PP option enableTPA b .RS .I b 0 --> default behaviour, specified by the internal tables, .br 1 --> override internal tables and allow TPA mode (EPSON/UMAX only) .RE .PP option posOffX x .br option posOffY y .br option tpaOffX x .br option tpaOffY y .br option negOffX x .br option negOffY y .RS .I x y By using this settings, the user can adjust the given image positions. .B Please note, that there's no internal range checking for .B this feature. .RE .PP option posShadingY p .br option tpaShadingY p .br option negShadingY p .RS .I p overrides the internal shading position. The values are in steps. .B Please note, that there's no internal range checking for .B this feature. .RE .PP option redGamma r .br option greenGamma g .br option blueGamma b .br option grayGamma gr .RS .I r g b gr .RE By using these values, the internal linear gamma table (r,g,b,gr = 1.0) can be adjusted. .PP option red_gain r .br option red_offset ro .br option green_gain g .br option green_offset go .br option blue_gain b .br option blue_offset bo .RS .I r g b ro go bo These values can be used to set the gain and offset values of the AFE for each channel. The range is between 0 and 63. \-1 means autocalibration. .RE .PP See the plustek.conf file for examples. .PP .B Note: .br You have to make sure, that the USB subsystem is loaded correctly and you have access to the device-node. For more details see .B sane\-usb (5) manpage. You might use .B sane\-find\-scanner to check that you have access to your device. .PP .B Note: .br If there's no configuration file, the backend defaults to .B device auto .SH FILES .TP .I @CONFIGDIR@/plustek.conf The backend configuration file .TP .I @LIBDIR@/libsane\-plustek.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-plustek.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_PLUSTEK If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_PLUSTEK=10 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5), .BR sane\-u12 (5), .BR sane\-gt68xx (5), .br .I @DOCDIR@/plustek/Plustek-USB.changes .br .I http://www.gjaeger.de/scanner/plustek/ .SH "CONTACT AND BUG-REPORTS" Please send any information and bug-reports to: .br .B SANE Mailing List .PP Additional info and hints can be obtained from our .br Mailing-List archive at: .br .B http://www.sane\-project.org/mailing\-lists.html .PP or directly from the projects' homepage at: .br .B http://www.gjaeger.de/scanner/plustek/ .PP To obtain debug messages from the backend, please set the environment-variable .I SANE_DEBUG_PLUSTEK before calling your favorite scan-frontend (i.e. xscanimage). .br .B i.e.: export SANE_DEBUG_PLUSTEK=20 ; xscanimage .PP The value controls the verbosity of the backend. Please note, that values greater than 24 force the backend to output raw data files, which could be rather large. The ending of these files is ".raw". For problem reports it should be enough the set the verbosity to 13. .SH "KNOWN BUGS & RESTRICTIONS" .PP * The driver does not support these manic scalings up to 16 times the physical resolution. The only scaling is done on resolutions between the physical resolution of the CCD-/CIS-sensor and the stepper motor i.e. you have a 600x1200 dpi scanner and you are scanning using 800dpi, so scaling is necessary, because the sensor only delivers 600dpi but the motor is capable to perform 1200dpi steps. .PP * Plusteks' model policy is somewhat inconsistent. They sell technically different devices under the same product name. Therefore it is possible that some devices like the UT12 or U12 won't work \- please check the model list above and compare the product-id to the one your device has. .PP * Negative/Slide scanning quality is poor. sane-backends-1.0.27/doc/sane-niash.man0000664000175000017500000000363112112021330014476 00000000000000.\" $Id$ .TH sane\-niash 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-niash .SH NAME sane\-niash \- SANE backend for scanners based on the NIASH chipset. .SH DESCRIPTION The .B sane\-niash implements a SANE (Scanner Access Now Easy) backend that provides access to NIASH chipset based scanners. This backend will try to support the following models: .ft CR .nf MANUFACTURER: MODEL: USB ID: --------------- ---------------- --------- Agfa Snapscan Touch 06BD-0100 (1)(a) Trust Office Scan 19200 047B-1000 (1)(a) Hewlett-Packard Scanjet 3300c 03F0-0205 (1)(a)(b) Hewlett-Packard Scanjet 3400c 03F0-0405 (2)(b) Hewlett-Packard Scanjet 4300c 03F0-0305 (2)(a) Silitek ScanJet 4300c 047B-1002 (2)(b) .fi .ft R .PP .br ASIC: (1) \- NIASH00012/00013/00014 / (2) \- NIASH00019 .br ANALOG FRONT-END: (a) \- ESIC ES8100QA / (b) \- WM8143-12 .br .SH CONFIGURATION The .I niash.conf file is meant for future configuration options. Empty lines and lines starting with a hash mark (#) are ignored. Currently no configuration options exist. .SH FILES .TP .I @LIBDIR@/libsane\-niash.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-niash.so The shared library implementing this backend (present on systems that support dynamic loading). .SH CAVEATS If you use a .br Hewlett-Packard Scanjet 3400c or .br Hewlett-Packard Scanjet 4300c .br together with Linux kernel .BR 2.6 , kernel version .B 2.6.8 or newer is necessary. .SH ENVIRONMENT .TP .B SANE_DEBUG_NIASH If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_NIASH=255 .SH "SEE ALSO" .BR sane (7), .BR sane\-usb (5) .br http://www.sourceforge.net/projects/hp3300backend .SH AUTHOR Bertrik Sikken sane-backends-1.0.27/doc/sane-test.man0000664000175000017500000002431612775312262014404 00000000000000.TH sane\-test 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-test .SH NAME sane\-test \- SANE backend for testing frontends .SH DESCRIPTION The .B sane\-test library implements a SANE (Scanner Access Now Easy) backend that allows testing the SANE installation and SANE frontends. It provides access to a (nearly) unlimited number of virtual devices. There is no support for real scanners or cameras. However, the backend simulates scanning and setting options. .PP The idea is not only to find bugs in frontends but also to show all capabilities of SANE. Therefore .B sane\-test implements functions and options that are not (or seldom) found in other backends. .PP The backend is commented out in @CONFIGDIR@/dll.conf, so either the comment character must be removed or the backend must be called explicitly. E.g. `scanimage \-d test' or `xscanimage test'. .SH SCAN MODE OPTIONS Option .B mode selects the scan mode (Gray or Color). .PP Option .B depth determines the number of bits per sample (1. 8, or 16). Keep in mind, that this value refers to the sample, not the pixel. So depth=16 results in 48 bits per pixel in color mode. The most usual combinations are mode=Gray, depth=1 for lineart, mode=Gray, depth=8 for gray and mode=Color, depth=8 for color mode. The combination of color and 1-bit mode is quite obscure (8 colors) but allowed in the SANE standard. However, the meaning of bits is not defined. Currently 1 = high intensity and 0 = low intensity is used. .PP Setting option .B hand\-scanner results in the test-backend behaving like a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of \-1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm. .PP Setting option .B three\-pass simulates a three-pass scanner. Older color scanners needed to scan the image once per color (reg/green/blue) to get the full image. Therefore, in this mode three single frames are transmitted in color mode. .PP Option .B three\-pass\-order provides support for changing the order of the three frames (see option three-pass above). A frontend should support all orders. .PP Option .B resolution sets the resolution of the image in dots per inch. .PP .PP Option .B source can be used to simulate an Automatic Document Feeder (ADF). After 10 scans, the ADF will be "empty". .PP .SH SPECIAL OPTIONS Option .B test\-picture allows one to set the image that's returned to the frontend. While "Solid white" and "Solid black" are quite obvious, the other options need some more explanation. Color patterns are used to determine if all modes and their colors are represented correctly by the frontend. The grid should look like the same in every mode and resolution. A table of all the test pictures can be found at: http://www.meier\-geinitz.de/sane/test\-backend/test\-pictures.html. .PP If option .B invert\-endianness is set, the upper and lower bytes of image data in 16 bit modes are exchanged. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness. .PP If option .B read\-limit is set, the maximum amount of data transferred with each call to sane_read() is limited. .PP Option .B read\-limit\-size sets the limit for option read-limit. A low limit slows down scanning. It can be used to detect errors in frontend that occur because of wrong assumptions on the size of the buffer or timing problems. .PP Option .B read\-delay enables delaying data to the frontend. .PP Option .B read\-delay\-duration selects the number of microseconds the backends waits after each transfer of a buffer. This option is useful to find timing-related bugs, especially if used over the network. .PP If option .B read\-return\-value is different from "Default", the selected status will be returned by every call to sane_read(). This is useful to test the frontend's handling of the SANE statuses. .PP If option .B ppl\-loss is different from 0, it determines the number of pixels that are "lost" at the end of each line. That means, lines are padded with unused data. .PP Option .B fuzzy\-parameters selects that fuzzy (inexact) parameters are returned as long as the scan hasn't been started. This option can be used to test if the frontend uses the parameters it got before the start of the scan (which it shouldn't). .PP Option .B non\-blocking determines if non-blocking IO for sane_read() should be used if supported by the frontend. .PP If option .B select\-fd is set, the backend offers a select filedescriptor for detecting if sane_read() will return data. .PP If option .B enable\-test\-options is set, a fairly big list of options for testing the various SANE option types is enabled. .PP Option .B print\-options can be used to print a list of all options to standard error. .PP .SH GEOMETRY OPTIONS Option .B tl\-x determines the top-left x position of the scan area. .PP Option .B tl\-y determines the top-left y position of the scan area. .PP Option .B br\-x determines the bottom-right x position of the scan area. .PP Option .B br\-y determines the bottom-right y position of the scan area. .PP .SH BOOL TEST OPTIONS There are 6 bool test options in total. Each option is numbered. (3/6) means: this is option 3 of 6. The numbering scheme is intended for easier detection of options not displayed by the frontend (because of missing support or bugs). .PP Option .B bool\-soft\-select\-soft\-detect (1/6) is a bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option. .PP Option .B bool\-hard\-select\-soft\-detect (2/6) is a bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device). .PP Option .B bool\-hard\-select (3/6) is a bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend. .PP Option .B bool\-soft\-detect (4/6) is a bool test option that has soft detect (and advanced) capabilities. That means the option is read-only. .PP Option .B bool\-soft\-select\-soft\-detect\-emulated (5/6) is a Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities. .PP Option .B bool\-soft\-select\-soft\-detect\-auto (6/6) is a Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend. .PP .SH INT TEST OPTIONS There are 6 int test options in total. .PP Option .B int (1/6) is an int test option with no unit and no constraint set. .PP Option .B int\-constraint\-range (2/6) is an int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2. .PP Option .B int\-constraint\-word\-list (3/6) is an int test option with unit bits and constraint word list set. .PP Option .B int\-constraint\-array (4/6) is an int test option with unit mm and using an array without constraints. .PP Option .B int\-constraint\-array\-constraint\-range (5/6) is an int test option with unit mm and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2. .PP Option .B int\-constraint\-array\-constraint\-word\-list (6/6) is an int test option with unit percent and using an array a word list constraint. .SH FIXED TEST OPTIONS There are 3 fixed test options in total. .PP Option .B fixed (1/3) is a fixed test option with no unit and no constraint set. .PP Option .B fixed\-constraint\-range (2/3) is a fixed test option with unit microsecond and constraint range set. Minimum is \-42.17, maximum 32767.9999, and quant is 2.0. .PP Option .B fixed\-constraint\-word\-list (3/3) is a Fixed test option with no unit and constraint word list set. .PP .SH STRING TEST OPTIONS There are 3 string test options in total. .PP Option .B string (1/3) is a string test option without constraint. .PP Option .B string\-constraint\-string\-list (2/3) is a string test option with string list constraint. .PP Option .B string\-constraint\-long\-string\-list (3/3) is a string test option with string list constraint. Contains some more entries... .PP .SH BUTTON TEST OPTION Option .B button (1/1) is a Button test option. Prints some text... .PP .SH FILES .TP .I @CONFIGDIR@/test.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). The initial values of most of the basic SANE options can be configured in this file. A template containing all the default values is provided together with this backend. One of the more interesting values may be .BR number_of_devices . It can be used to check the frontend's ability to show a long list of devices. The config values concerning resolution and geometry can be useful to test the handling of big file sizes. .TP .I @LIBDIR@/libsane\-test.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-test.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_TEST If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_TEST=4 .SH "SEE ALSO" sane(7), .IR http://www.meier\-geinitz.de/sane/test\-backend/ .SH AUTHOR Henning Meier-Geinitz .SH BUGS \- config file values aren't tested for correctness sane-backends-1.0.27/doc/sane-kodak.man0000664000175000017500000001102212112021330014456 00000000000000.TH sane\-kodak 5 "10 Feb 2010" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-kodak .SH NAME sane\-kodak \- SANE backend for big Kodak flatbed and ADF scanners .SH DESCRIPTION The .B sane\-kodak library implements a SANE (Scanner Access Now Easy) backend which provides access to large Kodak flatbed and ADF scanners. This document describes backend version 7, which shipped with SANE 1.0.21. .SH SUPPORTED HARDWARE This version should support models which speak the Kodak SCSI and Firewire protocols. The i1860 was used to develop the backend, but other models may work with only minimal modifications. Please see the list at http://www.sane\-project.org/sane\-supported\-devices.html for an updated list. If you have a machine not on that list, or reported as 'untested': the best way to determine level of support is to test the scanner directly, or to collect a trace of the windows driver in action. Please contact the author for help or with test results. .SH UNSUPPORTED HARDWARE Most of the recent Kodak consumer or workgroup level machines are based on other chipsets and are not supported by this backend. Some of these scanners may be supported by another backend. .SH OPTIONS Effort has been made to expose the basic hardware options, including: .PP source s .RS Selects the source for the scan. Options may include "Flatbed", "ADF Front", "ADF Back", "ADF Duplex". .RE .PP mode m .RS Selects the mode for the scan. Options may include "Lineart", "Halftone", "Gray", and "Color". .RE .PP resolution .RS Controls scan resolution. Available choices may be limited by mode. .RE .PP tl\-x, tl\-y, br\-x, br\-y .RS Sets scan area upper left and lower right coordinates. These are renamed t, l, x, y by some frontends. .RE .PP page\-width, page\-height .RS Sets paper size. Used by scanner to determine centering of scan coordinates when using ADF and to detect double feed errors. .RE .PP Other options will be available based on the capabilities of the scanner. Use 'scanimage \-\-help' to get a list, but be aware that some options may be settable only when another option has been set, and that advanced options may be hidden by some frontend programs. .PP .SH CONFIGURATION FILE The configuration file "kodak.conf" is used to tell the backend how to look for scanners, and provide options controlling the operation of the backend. This file is read each time the frontend asks the backend for a list of scanners, generally only when the frontend starts. If the configuration file is missing, the backend will use a set of compiled defaults, which are identical to the default configuration file shipped with SANE. .PP Scanners can be specified in the configuration file in 2 ways: .PP "scsi KODAK" .RS Requests backend to search all scsi busses in the system for a device which reports itself to be a scanner made by 'KODAK'. .RE .PP "scsi /dev/sg0" (or other scsi device file) .RS Requests backend to open the named scsi device. Only useful if you have multiple compatible scanners connected to your system, and need to specify one. Probably should not be used with the other "scsi" line above. .RE .PP The only configuration option supported is "buffer\-size=xxx", allowing you to set the number of bytes in the data buffer to something other than the compiled\-in default, 32768 (32K). Some users report that their scanner will "hang" mid\-page, or fail to transmit the image if the buffer is not large enough. .PP Note: This option may appear multiple times in the configuration file. It only applies to scanners discovered by 'scsi/usb' lines that follow this option. .PP Note: The backend does not place an upper bound on this value, as some users required it to be quite large. Values above the default are not recommended, and may crash your OS or lockup your scsi card driver. You have been warned. .PP .SH ENVIRONMENT The backend uses a single environment variable, SANE_DEBUG_KODAK, which enables debugging output to stderr. Valid values are: .PP .RS 5 Errors .br 10 Function trace .br 15 Function detail .br 20 Option commands .br 25 SCSI trace .br 30 SCSI detail .br 35 Useless noise .RE .SH KNOWN ISSUES Most hardware options are either not supported or not exposed for control by the user, including: multifeed detection, image compression, autocropping, endorser, iThresholding, multi\-stream, etc. .PP .SH CREDITS The various authors of the sane\-fujitsu backend provided useful code. .br Kodak provided access to hardware, documentation and personnel. .SH "SEE ALSO" sane(7), sane\-scsi(5) .SH AUTHOR m. allan noah: sane-backends-1.0.27/doc/sane-logo2.jpg0000664000175000017500000001537412112021330014432 00000000000000ÿØÿàJFIFÿþhMade with GIMP CREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 ÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ–€"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?÷ú(¨§-ãÞà‘žƒ­ Ø j).a„‘$¨¬vÜó§^Õs­–c;NpBóôçð¬F½™ãq¹rTa{tÇå\ò®–Ũw:ÆÕ-†pY†:犤úð*è‘ ˜2û€8ïÇ<×)xò°°~_¨=È5 º3À¼òzŽ?òk'^l¥tÒø–HˆÜ"íÚr?ZŒkÒ‘¹n ‰Ã*‚ ãõ5„ˆÌ’yŽ­¸‘’:Ž˜ü©—)´Ux_LƒÜƒþMG´Ÿqò£þ ˺,¥˜tG¥Vo_E,nnI“Ƽðzàg¿b:ÙÎ5¼lЀ0¤p{ŒTË•“Ì`Ù$GQÓùZ^Ò]ÇÊŽ†/ÎrÆdSÀPÅ=úç=½*ü>#°–c™!l€<ÅàçÜgŽ:×r»p ®6ñÆAH>œzmº;BJñÁ'‘ŽÕj¼Ðœé1Ëщ"ut=NAüiÕçP  •§†vŽ`Äy‰‘ŽààqúV•·Š¯l&Hµ8ÖâØ‘›˜Æ9%@ÁçÞ`csÆ:ã“Åliß ¼¦yžFi'™ßjÝsŒg§˜[o^ØÏè+O«÷dóœT:ö˜Æ¡ ru?ç4zÕ¤åcŠh{«wïÇã]ïü!¾ÿ¡oGÿÀ¿øš­yðÿ—ÏÉ¢[DÑgiµÍ¿\uòÊîéÆsŽqÔÑõ0ö‡/çÀì`ÒSŸóúÒÅ$œI=½søt­{‡V‘Ê$Òu ‹¼7”ãÎŒ¸À†ç¯,{ñÓŽŸ©Z´–·Öªä(Û,`˜Û#³c¨Áã¯áYN”¢R’eS;åÑI?Â{ðHÇãJÏ›&CǦîÏëQɺ7Ù {Ïùê)··†$…-íßh+á?.æäeAa‘œã' $fQD]ßøgR}GJQ*…Vº·lªJ™nø?0ì{gž©iZ¶³¥[j6º ˆÃ®H%}Tà‚3ÁW ·[W´Š%)´€‡œç’I<“žsÔ“š>_Ì­â E¥…ÒM<„áe òþ6•ßêísdñ `ù“#<åž™÷®ìB²ïêÍ€?Ú$ÿŸÖ£­+Ž­ã- ã Ž“sþZÎñŒúŽƒ}“÷’+(oè?ò+J¤I@W2þ·Nj3)|Dˆ£w¡üOÖ°EGÃë‹ü¦%…¬6i^L¶ÐŒ,R¯ßÉ<œ°,KÀžMtÕåzuãx[W–þÚ/6 ­©w ¹ðN}ÆOÁÉö#Ólï-õ H®í%Y`”nG^ÿà}»W}:ŠhÆQ±=QZQE#2 Ë0ÔšÇÕoákRªëì[¾Gÿ^µ'·Šæ&Žd ¬ ú¡¨®ZûáîŸq;Oi¨YÈcÚgó#ÝÏÌÁòǶ@aÓ·Z΢“VE+-Ìp¥Äžc«n%O^G@?ϽGr˜^BòP{}9þºuç‡|I¤ÆíƒR·LÔ—É;r0“‘Ç¥85k—dmËt‡cÆã AÓθ¥ GsTÓ,B…áùHRÌ{sÓÖ¡ø\IñŸŒÁ`ÅE˜Èöó…HTÀ¯!•WsŸ_çù[à¬?k“ÅZè˜u~¶¢ ¼/”»·g<çÎéŽ6ûñ®{Í“=W®GVÓ…¬â1BåâÆÑŽW8Ó×]TõK3}§M…ó æ=Çp铃ØñКè«x‘fqÃ4‘í ÞŸÖ©JL,²>Cc#Ÿ›üój«®j¶þ³y5ï+"?súç?Ö²4 ÅÿZ ¹IѼ;9WóØÿ¤\Dsþ­yÛœ[ W)ÊLÕÉ"Ö«âý&ÆXm“72Ê-áMò;žªÉ$ãñ©ü*> M¬G}§èk§i¹¤‹TœÂ³|ÁHòÀgG8Èb£…îuáïøoÁPgO´D¹uÛ%Ü¿¼¸›îƒ–ë‚UIUƒÈ´fÖ£T  'Lù‡¦~†º!OVõ3mÈÕ¨Úâb­4a‡ÉÜkþln²LŽ¥ˆäà8ÿ?…eÞjÙy‘—±È#©Ý=ÿÁ†ùå‹ ™2¥À³“íÌdbW†Ç ãå`G ¨ úéÕ ±-Ü(¢ŠÐF=ï…tMG[µÖ/4øæ¿´`ðÈÄáXtm¹ÚHìH$`c Å‹ÛËÅ,ldËl.Ì#T÷;¹ uÈÛ=+BŠMÅ^è^1Öa6¯¦éhµ´OrÏ×;·lÛŽ1Œõ=1Îe¯Âwx_û[źµÌåŽÔ$ ·‚¬“œœçÓŽ9ôŠlåÆÏ‚p3ŒŸnjy"ºìó†øCáûyb–ëZÖåŒ8o&K”Û.>b¸T rû¤Jv¥á_Ø£³Y7«6¥:éßy>½»W7ñ'âUä:³h: ¢Þ Ä÷'¥¾{ö¿Ïæ¶vrjÞ}¶YnnV˜I;n8S–ã¦Zô°9F#RŒ;¾¾„N¬a£Õž¹á BÎh’ÊîÊC Qqa¨¼åS*K~ðãÔ”ñÓžšOíþÓÏÓüC®I¹F̨¤0<‚¦ AïÈäz^7‹a¸·‘㕃|¡ŽÒ7axéÔ7=~_jìt^^Ì/,¤Xuë8òxÈ8ܬ?‰N#¶ ÷?çõ¯H®?W´HæeEˆùrç„ÆÐFq£X×…½äTCE×.<'¨Ggu'›£\8™€û+1å²x “ó àrGp}:¼ÇQ·ŠþÒ{WŒ9u )éZ¿ 5æÔ49´{’~Û£8·`F ˆƒå€WŸ“'­U ÝYŠk©ÜÑE`ë¾!·Òì䙤 "äÔÿœ:ÚRQWd¥sVëP³±…庹Ž(Óï³7ÝúÔn§ý«w6öò-”‰½'æsÁU%HÉÉÇðã äp ðüþ1‰|Oâ…ÙNû?I–3å,y#Í‘[‡f¯U†ä‘·Óè\ÏVÁXÞ'ÔLÐî®× °Âòn-Œ8Ç çô­šæ«*Dí ¶’ÑI*®Q]¥Œ…'Ôíb=vŸCXÐøŠžÇ¬êS<›ÕI†â:ëùà~5Ák°ÇªÅ4LªVBÃÆo3k‚p§’@9Ær+gL¼¾°ˆF·RlRªI ƒjôwxÉã©ÆTe€Ëc'¥6ßS·¸]¶ïg‘†ïߊõJæu/ø{Qù’Ïì3… ³XŸ(¨?t|¤õ œaŽya×CE>ç8d…ðY‹9ã8ûÞøÿ=è‰eŠO–C€qßÿ­’2j{Ÿ‡7𴯦ëÀªÐCwlîÇF‘HàžáxŽ*ŒÞñ½¥£È Ò¯™pgevÉ9uQÇ^HéëY:Es¢À½—îG·Ûß'Š‘®ÉÁ21~‡½Ïùü†4ï™Éá’Hî/ Ïþ‡éV¾ÃãTÿÂ&0yº·Ïç¾—²Ÿ`æF‚Ir’€f8xg¿øtæ£7.˱TO7~¦©½·0qá-Þ€Þ@?óÖsi'ºÉg f–öF:nm®Në€O £ÙMôdn³ÄÍó2p‹ž¸ÿõôéU'¼·ÓŽéî‘ ¶[¯áùTqü9ñ–¡ç CÄfž#gn×õÎKlÛŽ1Œç'§}»ƒþ‚èÜßµþ®áÑÑoî2ˆTçî U`xÈ`Àã뛎½ÄæŽ|Yy®\I§xSIŸU¹O¾ñ`E ‘½Îsµ±’2Gñ]ðŽKÝBWƺ’êSÆáÓO·è ‚q¼°ÌƒîœaFA0¯K±°³Ó,ã³°´‚ÒÖ<ì†Äh¹$œ(àd’±]§ìC“aEV„…cë>#³Ñ¯,l9îuÿ3ìvp(ß?–|3•EÚ§?3 ㌞+b¹øwÃ^3Õmô›û¹àÖôø…í¬–“´SÛ£H˜ŸÂ~h€'o €-ÇâÙ[Ót»ïk6¨<‰óˆ-ÈŒä3G+m%TàÎ:t•æ–7Þ+ðÿ´Oøž÷M×í57¸–Âü[.-Þ(AbUFÀ0Σ$9%€ùk³ñ¬êztpèzïö-ÒÊ®>È—;“Úç$ƒŸozجø›Kð–uM^&ÔKY±,Àp½[,@ÉÚ¬@8­Šóƒm©øÖòmphÚV£¡\Z=®–—×YÏ2“IŸÞ€»XDaq‚ÍC‚xn­â¸·–9 •Ç$l]HÈ Ž#œÔ•æ uKÏê÷ß|As‹»M³i&YŒžu«.|´soòðFqýà Çoâ=;YÔôèáÐõßì[¥”;\}‘.w&)µÎI>Þô¡}q-¥œ“Ãe=䋌A@ï’ÙW޼‘Ó׊æ<ñ+Ãþ=ûLz[Ï Õ¿/ktª’ãç1rqÁàã dg¯¯ðáñ/¯ ê–WÒi:þžó›MNò¯Ú%Ê:äB àžç±`À‡¬øÑtoØèo¡j·7WþgØÞo²-¾ Ê¥vƒü@gfºŠñ -w]½ø½àÅ^N·¤ý¸KsMäoÉ2të±²0#±Ê¯¯ëvšö‘=¶•ªeß>ß.óìë?—†üÁÈ{g=¨ÅõĶ–rO ”÷’.1¾He^:òGO^+ðçĨ¼[§I¡øg\»µŽS >mcÀ yÁèÃó®Þ¼3à•y}à[ÙmõýKOA©H¦+XíÙIò¢ù™œóޏàqÖ€=_Eñ Ö5MGM—IÔ´Û»…äKÕ²nÚQ‘Ø0ùc¨8ܬ½.F³+¤Þj’j:‚#ÎÒ´*åÍûE8ùGMûÃcR€ ÏÔô-[ò¿µt«ÿ'>_Ú­Ò]™Æq¸gòQ@Yé:nŸquqe§Ú[Ovûî$†F™²N\–9br}O­\¢Š¯}ag©ÙÉgiݬ˜ß ñ‰°ASÁÁþ›¤éº=»[éz}¥Œ åÚ;XV%-€2B€3€}…Py¼5 ÜêƒTŸDÓeÔ«‹·µF”2ãiÞFr00sÆjQEW¾°³Ôì䳿´‚îÖLo†xÄˆØ Œ©àà€ MÒtÝÝ­ô½>ÒÆrí¬+–À!@À>Š(I¬,î/-¯&´‚K«]ÞDÏ/á†ÚÇ•Èàã­X¢ŠŽx!º·–Þâ(æ‚T)$r(eu#x Ž1Xð‚øCþ…MÿÑñ4Q@f…£èžoöV•caçcÌû-ºE¿Ævœdþf´(¢€?ÿÙsane-backends-1.0.27/doc/sane-fujitsu.man0000664000175000017500000001671213072310726015111 00000000000000.TH sane\-fujitsu 5 "08 Apr 2017" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-fujitsu .SH NAME sane\-fujitsu \- SANE backend for Fujitsu flatbed and ADF scanners .SH DESCRIPTION The .B sane\-fujitsu library implements a SANE (Scanner Access Now Easy) backend which provides access to most Fujitsu flatbed and ADF scanners. This document describes backend version 133, which shipped with SANE 1.0.26. .SH SUPPORTED HARDWARE This version supports every known model which speaks the Fujitsu SCSI and SCSI\-over\-USB protocols. Specifically, the SCSI M309x and M409x series, the SCSI fi\-series, most of the USB fi\-series, the USB ScanSnap S5xx/S15xx, and the USB iX1xx/5xx series scanners are supported. Please see the list at http://www.sane\-project.org/sane\-supported\-devices.html for details. This backend may support other Fujitsu scanners. The best way to determine level of support is to test the scanner directly, or to collect a trace of the windows driver in action. Please contact the author for help or with test results. .SH UNSUPPORTED HARDWARE The following scanners are known NOT to work with this backend, either because they have a non\-fujitsu chipset, or an unsupported interface type. Some of these scanners may be supported by another backend. .PP .RS .ft CR .nf \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- SCSI: SERIAL: USB: \-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\- ScanStation M3093E/DE/EX fi\-4110EOX/2 ScanPartner M3096EX fi\-4010CU SP\-Jr M3097E+/DE S300/S300M SP\-10/10C M3099A/EH/EX S1300/S1100 SP\-15C/300C fi\-60F SP\-600C/620C fi\-5015C SP\-2x/3x .fi .ft R .RE .P .SH OPTIONS Effort has been made to expose all hardware options, including: .PP source s .RS Selects the source for the scan. Options may include "Flatbed", "ADF Front", "ADF Back", "ADF Duplex". .RE .PP mode m .RS Selects the mode for the scan. Options may include "Lineart", "Halftone", "Gray", and "Color". .RE .PP resolution, y\-resolution .RS Controls scan resolution. Setting \-\-resolution also sets \-\-y\-resolution, though this behavior is overridden by some frontends. .RE .PP tl\-x, tl\-y, br\-x, br\-y .RS Sets scan area upper left and lower right coordinates. These are renamed t, l, x, y by some frontends. .RE .PP page\-width, page\-height .RS Sets paper size. Used by scanner to determine centering of scan coordinates when using ADF and to detect double feed errors. .RE .PP Other options will be available based on the capabilities of the scanner: machines with IPC or DTC will have additional enhancement options, those with CMP will have compression options, those with a printer will have a group of endorser options. Additionally, several 'software' options are exposed by the backend. These are reimplementations of features provided natively by larger scanners, but running on the host computer. This enables smaller machines to have similar capabilities. Please note that these features are somewhat simplistic, and may not perform as well as the native implementations. Note also that these features all require that the driver cache the entire image in memory. This will almost certainly result in a reduction of scanning speed. Use 'scanimage \-\-help' to get a list, but be aware that some options may be settable only when another option has been set, and that advanced options may be hidden by some frontend programs. .PP .SH CONFIGURATION FILE The configuration file "fujitsu.conf" is used to tell the backend how to look for scanners, and provide options controlling the operation of the backend. This file is read each time the frontend asks the backend for a list of scanners, generally only when the frontend starts. If the configuration file is missing, the backend will be unable to locate any scanners. .PP Scanners can be specified in the configuration file in 4 ways: .PP "scsi FUJITSU" .RS Requests backend to search all scsi busses in the system for a device which reports itself to be a scanner made by 'FUJITSU'. .RE .PP "scsi /dev/sg0" (or other scsi device file) .RS Requests backend to open the named scsi device. Only useful if you have multiple compatible scanners connected to your system, and need to specify one. Probably should not be used with the other "scsi" line above. .RE .PP "usb 0x04c5 0x1042" (or other vendor/product ids) .RS Requests backend to search all usb busses in the system for a device which uses that vendor and product id. The device will then be queried to determine if it is a Fujitsu scanner. .RE .PP "usb /dev/usb/scanner0" (or other device file) .RS Some systems use a kernel driver to access usb scanners. This method is untested. .RE .PP The only configuration option supported is "buffer\-size=xxx", allowing you to set the number of bytes in the data buffer to something other than the compiled\-in default, 65536 (64K). Some users report that their scanner will "hang" mid\-page, or fail to transmit the image if the buffer is not large enough. .PP Note: This option may appear multiple times in the configuration file. It only applies to scanners discovered by 'scsi/usb' lines that follow this option. .PP Note: The backend does not place an upper bound on this value, as some users required it to be quite large. Values above the default are not recommended, and may crash your OS or lockup your scsi card driver. You have been warned. .PP .SH ENVIRONMENT The backend uses a single environment variable, SANE_DEBUG_FUJITSU, which enables debugging output to stderr. Valid values are: .PP .RS 5 Errors .br 10 Function trace .br 15 Function detail .br 20 Option commands .br 25 SCSI/USB trace .br 30 SCSI/USB writes .br 31 SCSI/USB reads .br 35 Useless noise .RE .SH KNOWN ISSUES Flatbed units may fail to scan at maximum area, particularly at high resolution. .PP Any model that does not support VPD during inquiry will not function until an override is added to the backend. .PP CCITT Fax compression used by older scanners is not supported. .PP JPEG output is supported by the backend, but not by the SANE protocol, so is disabled in this release. It can be enabled if you rebuild from source. .SH CREDITS m3091 backend: Frederik Ramm .br m3096g backend: Randolph Bentson .br (with credit to the unnamed author of the coolscan driver) .br fujitsu backend, m3093, fi\-4340C, ipc, cmp, long\-time maintainer: .br Oliver Schirrmeister .br m3092: Mario Goppold .br fi\-4220C and basic USB support: Ron Cemer .br fi\-4120, fi\-series color, backend re\-write, jpeg, current maintainer: m. allan noah: JPEG output and low memory usage support funded by: Archivista GmbH www.archivista.ch Endorser support funded by: O A S Oilfield Accounting Service Ltd 1500, 840 \- 7th Avenue S.W. Calgary, Alberta T2P 3G2 Canada 1\-403\-263\-2600 www.oas.ca Automatic length detection support funded by: Martin G. Miller mgmiller at optonline.net Hardware donated, software image enhancement and fi-6/7xxx support funded by: Fujitsu Computer Products of America, Inc. www.fcpa.com iX500 support funded by: Prefix Computer Services www.prefixservice.com .SH "SEE ALSO" sane(7), sane\-scsi(5), sane\-usb(5), sane\-sp15c(5), sane\-avision(5), sane\-epjitsu(5) .SH AUTHOR m. allan noah: sane-backends-1.0.27/doc/doxygen-sanei.conf.in0000664000175000017500000017134412112021330016010 00000000000000# Doxyfile 1.5.7.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = SANEI # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = ./ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, # Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = YES # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../include/sane/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = sanei*.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = ./ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = ./sanei-html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # Qt Help Project / Namespace. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # Qt Help Project / Virtual Folders. QHP_VIRTUAL_FOLDER = doc # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file . QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to FRAME, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = NO # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO sane-backends-1.0.27/doc/sane-kvs20xx.man0000664000175000017500000000145612775277260014762 00000000000000.TH sane\-kvs20xx 5 "09 Jun 2010" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-kvs20xx .SH NAME sane\-kvs20xx \- SANE backend for Panasonic KV-S20xxC USB/SCSI ADF scanners. .SH DESCRIPTION The .B sane\-kvs20xx library implements a SANE (Scanner Access Now Easy) backend which provides access to the Panasonic KV-S202xC and KV-S204xC scanners. .SH KNOWN ISSUES This document was written by the SANE project, which has no information regarding the capabilities or reliability of the backend. All information contained here is suspect. .SH CREDITS The backend was written by Panasonic Russia Ltd. The backend was ported to sane-backends 1.0.22 and downgraded to C89 by m. allan noah. .SH "SEE ALSO" sane(7), sane\-usb(5), sane\-scsi(5) .SH AUTHOR m. allan noah: sane-backends-1.0.27/doc/sane-agfafocus.man0000664000175000017500000001270312775277260015370 00000000000000.TH sane\-agfafocus 5 "10 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-agfafocus .SH NAME sane\-agfafocus \- SANE backend for AGFA Focus flatbed scanners .SH DESCRIPTION The .B sane\-agfafocus library implements a SANE (Scanner Access Now Easy) backend that provides access to AGFA Focus flatbed scanners. At present, the following scanners are supported from this backend: .PP .RS AGFA Focus GS Scanner (6 bit gray scale) (untested) .br AGFA Focus Lineart Scanner (lineart) (untested) .br AGFA Focus II (8 bit gray scale) (untested) .br AGFA Focus Color (24 bit color 3-pass) .br AGFA Focus Color Plus (24 bit color 3-pass) .br .PP Siemens S9036 (8 bit gray scale) (untested) .br .RE .PP The driver supports line art, 6bpp and 8bpp gray, 18bpp and 24bpp color scans. .PP If you own a scanner other than the ones listed above that works with this backend, please let us know by sending the scanner's model name, SCSI id, and firmware revision to .IR sane\-devel@lists.alioth.debian.org . Have a look at http://www.sane\-project.org/mailing\-lists.html concerning subscription to sane\-devel. .PP All of these scanners are pre-SCSI-2, and do not even report properly to SCSI Inquiry. This is typically evident in SCSI bus scans, where the scanner will come up with only garbage as vendor and models strings. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .I special .RE .PP Where .I special is either the path-name for the special device that corresponds to a SCSI scanner. For SCSI scanners, the special device name must be a generic SCSI device or a symlink to such a device. Under Linux, such a device name could be .I /dev/sga or .IR /dev/sge , for example. See sane\-scsi(5) for details. .SH CONFIGURATION The contents of the .I agfafocus.conf file is a list of device names that correspond to AGFA Focus scanners. Empty lines and lines starting with a hash mark (#) are ignored. A sample configuration file is shown below: .PP .RS /dev/scanner .br # this is a comment .br /dev/sge .RE .PP .SH FILES .TP .I /etc/sane.d/agfafocus.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I /usr/lib/libsane\-agfafocus.a The static library implementing this backend. .TP .I /usr/lib/libsane\-agfafocus.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in /etc/sane.d. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "/etc/sane.d" being searched (in this order). .TP .B SANE_DEBUG_AGFAFOCUS If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. SANE_DEBUG_AGFAFOCUS values: .sp .ft CR .nf Number Remark \ 0 print important errors (printed each time) 1 print errors 2 print sense 3 print warnings 4 print scanner-inquiry 5 print information 6 print less important information 7 print called procedures 8 print reader_process messages 10 print called sane\-init-routines 11 print called sane\-procedures 12 print sane infos 13 print sane option-control messages .fi .ft R .SH MISSING FUNCTIONALITY Uploading of dither matrices and tonecurves has been implemented, but so far has not proven to be useful for anything. For this reason these options have been disabled. .SH BUGS The scanners that do not support disconnect have problems with SCSI timeouts if the SCSI bus gets loaded, eg. if you do a kernel build at the same time as scanning. To see if your scanner supports disconnect, run "SANE_DEBUG_AGFAFOCUS=128 scanimage \-L" in sh and look for the "disconnect:" line) .SH DEBUG If you have problems with SANE not detecting your scanner, make sure the Artec backend is disabled. Somehow, this backend causes at least my scanner not to respond correctly to SCSI inquiry commands. .PP If you encounter a bug please set the environment variable SANE_DEBUG_AGFAFOCUS to 128 and try to regenerate the problem. Then send me a report with the log attached. .PP If you encounter a SCSI bus error or trimmed and/or displaced images please also set the environment variable SANE_DEBUG_SANEI_SCSI to 128 before sending me the report. .SH TODO .TP .B More scanners? The AGFA ACS and ARCUS scanners are similar to the FOCUS scanners. The driver could probably be extended to support these scanners without too many changes. I do not have access to such scanners, and cannot add support for it. However, if you are in possession of such a scanner, I could be helpful in adding support for these scanners. The AGFA HORIZON scanners are SCSI-2 scanners, and it would probably be easier to support these scanners in a SCSI-2 compliant backend. .SH SEE ALSO sane(7), sane\-scsi(5) .SH AUTHOR Ingo Schneider and Karl Anders \[/O]ygard. sane-backends-1.0.27/doc/sane-coolscan3.man0000664000175000017500000001502112112021330015254 00000000000000.TH sane\-coolscan3 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-coolscan3 .SH NAME sane\-coolscan3 \- SANE backend for Nikon Coolscan film scanners .SH DESCRIPTION The .B sane\-coolscan3 library implements a SANE (Scanner Access Now Easy) backend that provides access to Nikon Coolscan film scanners. Some functions of this backend should be considered .B beta-quality software. Most functions have been stable for a long time, but of course new development can not and will not function properly from the very first day. .PP At present, the following scanners are known to work with this backend: .PP .RS .ft CR .nf Model: Connection Type --------------------------- ------------------- LS-30 (Coolscan III) SCSI LS-40 ED (Coolscan IV) USB LS-50 ED (Coolscan V) USB LS-2000 SCSI LS-4000 ED IEEE 1394 LS-8000 ED IEEE 1394 .fi .ft R .RE Please send mail to sane-devel@lists.alioth.debian.org to report successes or failures. .SH OPTIONS The options the backend supports can either be selected through command line options to programs like scanimage or through GUI elements in xscanimage or xsane. Valid command line options and their syntax can be listed by using .RS scanimage \-\-help \-d coolscan3:: .RE where and specify the device in question, as in the configuration file (see next section). The \-d parameter and its argument can be omitted to obtain information on the first scanner identified. Use the command .RS scanimage \-L .RE to list all devices recognized by your SANE installation. The options should be fully described by the description or tooltips given by frontend. Here is a description of some of the most important options, in the syntax with which they must be supplied to scanimage: .TP .I \-\-frame This option specifies which frame to operate on, if a motorized film strip feeder or APS adapter are used. The frame number .I ranges from 1 to the number of frames available, which is sensed each time the backend is initialized (usually each time you start the frontend). .TP .I \-\-subframe This option shifts the scan window by the specified amount (default unit is mm). .TP .I \-\-infrared=yes/no If set to "yes", the scanner will read the infrared channel, thus allowing defect removal in software. The infrared image is read during a second scan, with no options altered. The backend must not be restarted between the scans. If you use scanimage, perform a batch scan with batch\-count=2 to obtain the IR information. .TP .I \-\-depth Here can either be 8 or the maximum number of bits supported by the scanner (10, 12, or 14). It specifies whether or not the scanner reduces the scanned data to 8 bits before sending it to the backend. If 8 bits are used, some information and thus image quality is lost, but the amount of data is smaller compared to higher depths. Also, many imaging programs and image formats cannot handle depths greater than 8 bits. .TP .I \-\-autofocus Perform autofocus operation. Unless otherwise specified by the other options ( .I \-\-focus\-on\-centre and friends), focusing is performed on the centre of the selected scan area. .TP .I \-\-ae\-wb .TP .I \-\-ae Perform a pre-scan to calculate exposure values automatically. .I \-\-ae\-wb will maintain the white balance, while .I \-\-ae will adjust each channel separately. .TP .I \-\-exposure Multiply all exposure times with this value. This allows exposure correction without modifying white balance. .TP .I \-\-load Load the next slide when using the slide loader. .TP .I \-\-eject Eject the film strip or mounted slide when using the slide loader. .TP .I \-\-reset Reset scanner. The scanner will perform the same action as when power is turned on: it will eject the film strip and calibrate itself. Use this whenever the scanner refuses to load a film strip properly, as a result of which .I \-\-eject does not work. .SH CONFIGURATION FILE The configuration file @CONFIGDIR@/coolscan3.conf specifies the device(s) that the backend will use. Owing to the nature of the supported connection types SCSI, USB, and IEEE 1394, the default configuration file supplied with the SANE distribution should work without being edited. Each line in the configuration file is either of the following, where all entries are case-sensitive: .TP .I blank or starting with a '#' character These lines are ignored, thus '#' can be used to include comments. .TP .I containing only the word """auto""" This instructs the backend to probe for a scanner by scanning the buses for devices with know identifiers. This is the action taken when no configuration file is present. .TP .I a line of the form : Here can be one of "scsi" or "usb", and is the device file of the scanner. Note that IEEE 1394 devices are handled by the SBP-2 module in the kernel and appear to SANE as SCSI devices. .SH FILES .TP .I @LIBDIR@/libsane\-coolscan3.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-coolscan3.so The shared library implementing this backend (present on systems that support dynamic loading). .TP .I @CONFIGDIR@/coolscan3.conf Configuration file for this backend, read each time the backend is initialized. .SH ENVIRONMENT .TP .B SANE_DEBUG_COOLSCAN3 If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH "SEE ALSO" sane\-scsi(5), sane\-usb(5), scanimage(1), xscanimage(1), xsane(1) .SH BUGS Currently, the SANE protocol does not allow automatically updating options whenever the hardware changes. Thus the number of choices for the .B \-\-frame option will be fixed when the backend is initialized (usually when the user runs the frontend). In particular, if there is no film strip in the automatic film strip feeder when the backend is initialized, the frame option will not appear at all. Also, restarting the frontend after swapping film adapters is strongly recommended. Linux kernels prior to 2.4.19 had a patch that truncated INQUIRY data from IEEE 1394 scanners to 36 bytes, discarding vital information about the scanner. The IEEE 1394 models therefore only work with 2.4.19 or later. No real bugs currently known, please report any to the SANE developers' list. .SH AUTHORS coolscan3 written by A. Zummo (a.zummo@towertech.it), based heavily on coolscan2 written by Andr\['a]s Major (andras@users.sourceforge.net). sane-backends-1.0.27/doc/sane-cardscan.man0000664000175000017500000000613312775312262015200 00000000000000.TH sane\-cardscan 5 "10 Feb 2010" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-cardscan .SH NAME sane\-cardscan \- SANE backend for Corex CardScan usb scanners .SH DESCRIPTION The .B sane\-cardscan library implements a SANE (Scanner Access Now Easy) backend which provides access to the Corex CardScan 800c & 600c small-format scanners. The backend supports only grayscale and color modes and media of (theoretically) infinite length. This backend may support other scanners. The best way to determine level of support is to get a trace of the windows driver in action, and send it to the author. .SH OPTIONS The cardscan backend supports the following options: .PP mode m .RS Selects the mode for the scan. Options are "Gray" and "Color". .RE .PP .SH CONFIGURATION FILE The configuration file "cardscan.conf" is used to tell the backend how to look for scanners, and provide options controlling the operation of the backend. This file is read each time the frontend asks the backend for a list of scanners, generally only when the frontend starts. If the configuration file is missing, the backend will use a set of compiled defaults, which are identical to the default configuration file shipped with SANE. .PP Scanners can be specified in the configuration file in 2 ways: .PP "usb 0x04c5 0x1042" (or other vendor/product ids) .RS Requests backend to search all usb busses in the system for a device which uses that vendor and product id. The device will then be queried to determine if it is a cardscan scanner. .RE .PP "usb /dev/usb/scanner0" (or other device file) .RS Some systems use a kernel driver to access usb scanners. This method is untested. .RE Additionally, there are two configuration options that control the protocol used by the backend: .PP "lines_per_block 16" (or other number from 1 to 32) .RS Controls the number of lines of image data which will be acquired in each pass. Older scanners will require this number set lower, often 1. .RE .PP "has_cal_buffer 1" (1 or 0) .RS Causes the backend to get calibration data from scanner during initialization. Older scanners do not support this request, and must be set to 0. .RE .SH ENVIRONMENT The backend uses a single environment variable, SANE_DEBUG_CARDSCAN, which enables debugging output to stderr. Valid values are: .PP .RS 5 Errors .br 10 Function trace .br 15 Function detail .br 20 Option commands .br 25 SCSI/USB trace .br 30 SCSI/USB detail .br 35 Useless noise .RE .SH KNOWN ISSUES .PP .RS The scanner does not seem to have much control possible, so the backend cannot set x/y coordinate values, resolutions, etc. These things could be simulated in the backend, but there are plenty of command line tools. .br .br The backend also does not send all the commands that the windows driver does, so it may not function the same. .br .br The backend does not have the calibration or ejection options of the windows driver. .br .br .RE .SH CREDITS The hardware to build this driver was provided to the author by: Jeff Kowalczyk .SH "SEE ALSO" sane(7), sane\-usb(5) .SH AUTHOR m. allan noah: sane-backends-1.0.27/doc/sane-net.man0000664000175000017500000001063612112021330014165 00000000000000.TH sane\-net 5 "14 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-net .SH NAME sane\-net \- SANE network backend .SH DESCRIPTION The .B sane\-net library implements a SANE (Scanner Access Now Easy) backend that provides access to image acquisition devices through a network connection. This makes it possible to control devices attached to a remote host and also provides a means to grant users access to protected resources. .SH "DEVICE NAMES" This backend expects device names of the form: .PP .RS .IR host : device .RE .PP Where .I host is the name (or IP address) of the (remote) host and .I device is the name of the device on this host that should be addressed. If the device name does not contain a colon (:), then the entire string is treated as the .I device string for the default host. The default host is the host listed last in the configuration file (see below). .PP An IPv6 address can be specified enclosed in square brackets: .PP .RS .IR [::1] : device .RE .SH CONFIGURATION The .IR net.conf file contains both backend options and a list of host names (or IP addresses) that should be contacted for scan requests. Anything that isn't one of the options listed below will be treated as an host name. .PP .TP .B connect_timeout = nsecs Timeout (in seconds) for the initial connection to the .I saned server. This will prevent the backend from blocking for several minutes trying to connect to an unresponsive .I saned host (network outage, host down, ...). The environment variable .B SANE_NET_TIMEOUT can also be used to specify the timeout at runtime. .PP Empty lines and lines starting with a hash mark (#) are ignored. Note that IPv6 addresses in this file do not need to be enclosed in square brackets. A sample configuration file is shown below: .PP .RS scan\-server.somedomain.firm .br 192.168.0.1 .br # this is a comment .br localhost .br ::1 .RE .PP The above list of hosts can be extended at run-time using environment variable .BR SANE_NET_HOSTS . This environment variable is a colon-separated list of hostnames or IP addresses that should be contacted in addition to the hosts mentioned in the configuration file. For example, a user could set the environment variable to the string: .PP .RS new.scanner.com:[::1]:192.168.0.2:scanner.univ.edu .RE .PP To request that hosts .I new.scanner.com , .I [::1] , .I 192.168.0.2 and .I scanner.univ.edu are contacted in addition to the hosts listed above. .PP For this backend to function properly, it is also necessary to define the .B sane\-port service in .IR /etc/services . The .B sane service should be defined using a line of the following form: .PP .RS sane\-port 6566/tcp # SANE network scanner daemon .RE .PP .SH FILES .TP .I @CONFIGDIR@/net.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-net.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-net.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_NET_HOSTS A colon-separated list of host names or IP addresses to be contacted by this backend. .TP .B SANE_NET_TIMEOUT Number of seconds to wait for a response from the .I saned server for the initial connection request. .TP .B SANE_DEBUG_NET If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. E.g., a value of 128 requests all debug output to be printed. Smaller levels reduce verbosity. .SH BUGS If saned has timed out, the net backend may loop with authorization requests. .SH "SEE ALSO" sane(7), saned(8), sane\-dll(5), scanimage(1) .I http://www.penguin-breeder.org/?page=sane\-net .SH AUTHOR David Mosberger and Andreas Beck sane-backends-1.0.27/doc/sane-canon630u.man0000664000175000017500000000725512112021330015116 00000000000000.TH sane\-canon630u 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-canon630u .SH NAME sane\-canon630u \- SANE backend for the Canon 630u USB flatbed scanner .SH DESCRIPTION The .B sane\-canon630u library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Canon flatbed scanners: .PP .RS CanoScan 630u .br CanoScan 636u .br .RE .PP Color scanning is supported at 75, 150, 300, and 600 dpi, and gamma and analog gain are adjustable. .PP TESTERS ARE WELCOME. Send your bug reports and comments to Nathan Rutman .PP .SH CONFIGURATION The contents of the .I canon630u.conf file is a list of device names that correspond to Canon USB scanners. Empty lines and lines starting with a hash mark (#) are ignored. Only one device name can be listed in .IR canon630u.conf . The program .IR sane\-find\-scanner helps to find out the correct device. Under Linux, such a device name could be .I /dev/usb/scanner0 for example. See sane\-usb(5) for details. .PP This product-specific scanner driver uses the lower-level kernel USB driver "scanner". Check for "Driver=usbscanner" under /proc/bus/usb/devices. If "Driver=(none)", try forcing it with "insmod scanner vendor=0x04a9 product=0x2204" .SH NOTES .PP Due to Canon's unwillingness to provide scanner documentation, this software was developed by analyzing the USB traffic of the Windows 2000 driver. So things like the calibration procedure I kind of made up; it seems to work for my scanner. If you have complaints, let me know. .PP This driver requires the ability to send USB Control Messages, available in kernel 2.4.12 or later. .PP Some users have reported that this driver doesn't work at all. This seems to be a hardware specific issue, although I don't know what exactly the problem is. If you are having problems, please send me the info in /proc/bus/usb/devices, /proc/pci, the kernel scanner.c driver version from /var/log/messages, and the output from "SANE_DEBUG_CANON630U=12 scanimage > /dev/null" .PP .SH FILES .TP .I @CONFIGDIR@/canon630u.conf The backend configuration file (see also description of .B SANE_CONFIG_DIR below). .TP .I @LIBDIR@/libsane\-canon630u.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-canon630u.so The shared library implementing this backend (present on systems that support dynamic loading). .TP .I /tmp/canon.cal The calibration file used to normalize pixel brightness. This is calculated every time the scanner is first used after it has lost power. Deleting this file will force recalibration. .SH ENVIRONMENT .TP .B SANE_CONFIG_DIR This environment variable specifies the list of directories that may contain the configuration file. Under UNIX, the directories are separated by a colon (`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable is not set, the configuration file is searched in two default directories: first, the current working directory (".") and then in @CONFIGDIR@. If the value of the environment variable ends with the directory separator character, then the default directories are searched after the explicitly specified directories. For example, setting .B SANE_CONFIG_DIR to "/tmp/config:" would result in directories "tmp/config", ".", and "@CONFIGDIR@" being searched (in this order). .TP .B SANE_DEBUG_CANON630U If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: .br SANE_DEBUG_CANON630U=12 scanimage > /dev/null .SH "SEE ALSO" sane(7), sane\-usb(5), sane\-find\-scanner(1) .br http://canon-fb630u.sourceforge.net/ .br .SH AUTHOR Nathan Rutman sane-backends-1.0.27/doc/sane-config.man0000664000175000017500000000272512112021330014644 00000000000000.TH sane\-config 1 "10 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .SH NAME sane\-config \- get information about the installed version of libsane .SH SYNOPSIS .B sane\-config [\-\-prefix] [\-\-exec\-prefix] [\-\-libs] [\-\-cflags] [\-\-ldflags] [\-\-version] [\-\-help \fI[OPTION]\fP] .SH DESCRIPTION .PP .B sane\-config is a tool that is used to determine the compiler and linker flags that should be used to compile and link .B SANE frontends to a .B SANE backend library (libsane). . .SH OPTIONS .B sane\-config accepts the following options (you can't use more than one option at the same time): .TP 8 .B \-\-version Print the currently installed version of libsane on the standard output. .TP 8 .B \-\-help OPTION Print a short usage message. If OPTION is specified, help for that option (e.g. \-\-libs) is printed (if available). .TP 8 .B \-\-libs Print the additional libraries that are necessary to link a .B SANE frontend to libsane. .TP 8 .B \-\-ldflags Print the linker flags that are necessary to link a .B SANE frontend to libsane. .TP 8 .B \-\-cflags Print the compiler flags that are necessary to compile a .B SANE frontend. .TP 8 .B \-\-prefix Print the prefix used during compilation of libsane. .TP 8 .B \-\-exec\-prefix Print the exec\-prefix used during compilation of libsane. .SH "SEE ALSO" .BR sane (7) .SH AUTHOR This manual page was written by Julien BLACHE , for the Debian GNU/Linux system (but may be used by others). sane-backends-1.0.27/doc/sane-canon.man0000664000175000017500000000666012112021330014477 00000000000000.TH sane\-canon 5 "11 Jul 2008" "@PACKAGEVERSION@" "SANE Scanner Access Now Easy" .IX sane\-canon .SH NAME sane\-canon \- SANE backend for Canon SCSI scanners .SH DESCRIPTION The .B sane\-canon library implements a SANE (Scanner Access Now Easy) backend that provides access to the following Canon flatbed and film scanners: .PP .RS CanoScan 300 .br CanoScan 600 .br CanoScan FB620S .br CanoScan FB1200S .br CanoScan FS2700F .br CanoScan FS2710S .br .RE .PP Parallel port and USB scanners are not supported by this backend; see the manual pages for sane\-canon_pp and sane\-canon630u for further information. .PP IMPORTANT: This is beta code. We tested the code on the scanners listed above, using the computers and operating systems available to us, but we cannot guarantee that the backend will work smoothly with future operating systems, SCSI adapters, SANE frontend programs, or Canon scanners not contained in the list above. In some cases your computer might even hang. It cannot be excluded (although we consider it extremely unlikely) that your scanner will be damaged. .PP That said, TESTERS ARE WELCOME. Send your bug reports and comments to Manuel Panea ; for questions concerning the FB620 and FB1200S contact Mitsuru Okaniwa , for the FS2710S Ulrich Deiters . .PP .SH TIPS (FS2700F) .PP Scanning either slides or negatives has been found to require rather large gamma corrections of about 2.2 to 2.4 (same value for red, green, and blue). It is recommended to use the automatic exposure controls of the frontend xsane for best results. .PP The "Auto Focus" function triggers a special pass to determine the focus value. After that, the real scanning pass takes place. .PP Even with "Auto Focus" turned on, the scanned image is often a bit too blurred. Using the GIMP to do a "Filter->Enhance->Sharpen" at about 40 to 60 improves the image considerably. .PP .SH TIPS (FS2710S) .PP Gamma corrections are done not by the scanner, but by the backend. The scanner is always run in 12-bit mode. In "color" mode the image data are corrected for gamma, shadow point, etc., and then truncated to 8-bit intensities; the default gamma value is 2.0. In "raw" mode the image data are exported without corrections as 16-bit intensities; this mode can be recommended if extensive adjustments have to be made to a picture (and if the frontend can handle 16-bit intensities). .PP Negatives are handled by simple color inversion and may require manual removal of blue discoloration. .PP .SH FILES .TP .I @LIBDIR@/libsane\-canon.a The static library implementing this backend. .TP .I @LIBDIR@/libsane\-canon.so The shared library implementing this backend (present on systems that support dynamic loading). .SH ENVIRONMENT .TP .B SANE_DEBUG_CANON If the library was compiled with debug support enabled, this environment variable controls the debug level for this backend. Higher debug levels increase the verbosity of the output. Example: export SANE_DEBUG_CANON=4 .SH "SEE ALSO" sane\-scsi(5) .br http://www.rzg.mpg.de/~mpd/sane/ .br doc/canon.install2700F.txt (installation of a CanoScan 2700F .br .SH AUTHOR Helmut Koeberle, Manuel Panea, and Markus Mertinat; FB620S and FB1200S support by Mitsuru Okaniwa; FS2710S support by Ulrich Deiters .br Man page by Henning Meier-Geinitz (mostly based on canon.README) sane-backends-1.0.27/install-sh0000775000175000017500000003413713106201017013225 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # $RANDOM is not portable (e.g. dash); use it when possible to # lower collision chance tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # As "mkdir -p" follows symlinks and we work in /tmp possibly; so # create the $tmpdir first (and fail if unsuccessful) to make sure # that nobody tries to guess the $tmpdir name. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sane-backends-1.0.27/configure.ac0000664000175000017500000007573013110561141013515 00000000000000dnl Process this file with autoconf to produce a configure script. dnl ****************************************************************** dnl Set up autoconf and automake dnl When preparing a release, modify the numeric version components dnl and remove the git suffix. dnl ****************************************************************** AC_INIT([sane-backends],[1.0.27], [sane-devel@lists.alioth.debian.org]) AC_PREREQ(2.69) dnl minimum autoconf version required AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([include/sane/config.h]) AM_INIT_AUTOMAKE([1.11.6 subdir-objects -Wall]) AM_SILENT_RULES dnl Turn off feature were automake will automatically run autoreconf. dnl This is because we used to check in generated files into CVS which dnl has known timestamp issues. AM_MAINTAINER_MODE dnl ****************************************************************** dnl Determine SANE version components and release status dnl ****************************************************************** AS_IF([test x = "x$AWK"],[AC_PROG_AWK]) AS_IF([test x = "x`echo $VERSION | sed 's/[[.0-9]]//g'`"], [is_release=yes], [is_release=no]) V_MAJOR=`echo $VERSION | $AWK -F. '{print $1}'` V_MINOR=`echo $VERSION | $AWK -F. '{print $2}'` V_REV=`echo $VERSION | $AWK -F. '{print $3}' | sed 's/[[^0-9]]//g'`; AC_DEFINE_UNQUOTED(SANE_DLL_V_MAJOR, $V_MAJOR, [SANE DLL major number]) AC_DEFINE_UNQUOTED(SANE_DLL_V_MINOR, $V_MINOR, [SANE DLL minor number]) AC_DEFINE_UNQUOTED(SANE_DLL_V_BUILD, $V_REV, [SANE DLL revision number]) AC_SUBST(V_MAJOR) AC_SUBST(V_MINOR) AC_SUBST(V_REV) dnl ****************************************************************** dnl Set up the compiler and linker dnl ****************************************************************** AC_PROG_CC AM_PROG_CC_C_O sane_save_CC=$CC AC_PROG_CC_C99 dnl enables extensions to ISO C99 :-( AS_IF([test xno != "x$ac_cv_prog_cc_c99"], [AC_MSG_CHECKING([for $sane_save_CC option for ISO C99 w/o extensions]) AS_CASE([$ac_cv_prog_cc_c99], [-std=gnu99], [sane_prog_cc_c99="-std=c99"], [-qlanglvl=extc99],[sane_prog_cc_c99="-qlanglvl=stdc99"]) AS_IF([test "x$ac_cv_prog_cc_c99" = "x$sane_prog_cc_c99"], [AC_MSG_RESULT([$ac_cv_prog_cc_99])], [AC_MSG_RESULT([$sane_prog_cc_c99]) CC="$sane_save_CC $sane_prog_cc_c99"]) ]) AC_PROG_GCC_TRADITIONAL AC_USE_SYSTEM_EXTENSIONS dnl call before running the C compiler AM_PROG_AR LT_INIT([disable-static win32-dll]) LT_PREREQ([2.4.2]) dnl ***************************************************************** dnl Set up I18N/L10N support dnl ***************************************************************** AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.18.1]) dnl *********************************************************************** dnl Checks for programs. dnl *********************************************************************** AC_PATH_PROG(SANE_CONFIG_PATH, sane-config, no) dnl Call explicitely before using PKG_* PKG_PROG_PKG_CONFIG AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) dnl *********************************************************************** dnl set compiler/linker flags dnl *********************************************************************** SANE_SET_AM_CFLAGS([$is_release]) SANE_SET_AM_LDFLAGS dnl *********************************************************************** dnl Checks for unix variants dnl *********************************************************************** AC_SEARCH_LIBS([strerror],[cposix]) AC_NEED_BYTEORDER_H([include/byteorder.h]) AX_CREATE_STDINT_H([include/_stdint.h]) dnl *********************************************************************** dnl Checks for libraries dnl *********************************************************************** AC_ARG_ENABLE(dynamic, AS_HELP_STRING([--disable-dynamic], [Disable dynamic loading of backends]), [enable_dynamic=$enableval], [enable_dynamic=auto]) SANE_CHECK_DLL_LIB dnl Checks for Backend libraries. AC_CHECK_LIB(m, sqrt, MATH_LIB="-lm") AC_SUBST(MATH_LIB) case ${host_os} in os2*) AC_CHECK_LIB(syslog, sylog, SYSLOG_LIBS="-lsyslog") ;; beos*) AC_CHECK_LIB(be, syslog, SYSLOG_LIBS="-lbe") ;; esac AC_SUBST(SYSLOG_LIBS) SANE_CHECK_JPEG SANE_CHECK_TIFF SANE_CHECK_PNG SANE_CHECK_IEEE1284 SANE_CHECK_PTHREAD SANE_CHECK_LOCKING SANE_CHECK_GPHOTO2 AC_ARG_WITH(v4l, AS_HELP_STRING([--with-v4l], [include the v4l backend @<:@default=yes@:>@]), [# If --with-v4l=no or --without-v4l, disable backend # as "$with_v4l" will be set to "no"]) if test "$with_v4l" != "no" ; then PKG_CHECK_MODULES(LIBV4L, libv4l1, have_libv4l1=yes, have_libv4l1=no) fi AC_ARG_ENABLE(avahi, AS_HELP_STRING([--enable-avahi], [enable Avahi support for saned and the net backend]), [enable_avahi=$enableval], [enable_avahi=no]) if test "$enable_avahi" = "yes"; then PKG_CHECK_MODULES(AVAHI, [ avahi-client >= 0.6.24 ], [AC_DEFINE(WITH_AVAHI, 1, [define if Avahi support is enabled for saned and the net backend])], enable_avahi=no) fi dnl check sane to make sure we don't have two installations AC_CHECK_LIB(sane, sane_init, LIBSANE_EXISTS="yes") dnl ************************************************************** dnl SNMP CHECKS dnl ************************************************************** AC_ARG_WITH(snmp, AS_HELP_STRING([--with-snmp], [enable SNMP support @<:@default=yes@:>@])) if test "$with_snmp" = "no"; then echo "Not including SNMP support" else AC_PATH_PROG(SNMP_CONFIG_PATH, net-snmp-config, "no") AC_CHECK_LIB([netsnmp], [snmp_timeout], LIBSNMP_EXISTS="yes") AC_MSG_CHECKING(for proper SNMP version) if test "$SNMP_CONFIG_PATH" != "no" ; then snmp_version=`$SNMP_CONFIG_PATH --version 2>/dev/null` vers=`echo $snmp_version | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2);}'` if test -n "$vers" && test "$vers" -ge 5006; then SNMP_LIBS=`$SNMP_CONFIG_PATH --libs` SNMP_CFLAGS=`$SNMP_CONFIG_PATH --cflags` AC_MSG_RESULT(yes) with_snmp="yes" else AC_MSG_RESULT(no) AC_MSG_WARN([You need at least net-snmp 5.6, your version is $snmp_version]) with_snmp="no" fi else with_snmp="no" AC_MSG_RESULT(no) fi fi if test "$with_snmp" = "yes" && test "${LIBSNMP_EXISTS}x" = "yesx"; then AC_SUBST(SNMP_LIBS) AC_SUBST(SNMP_CFLAGS) AC_DEFINE(HAVE_LIBSNMP, 1, [Define to 1 if you have the net-snmp library.]) else AC_MSG_WARN([net-snmp library disabled, autodetecting network scanners will not be supported.]) fi dnl *********************************************************************** dnl Checks for header files. dnl *********************************************************************** AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h unistd.h libc.h sys/dsreq.h sys/select.h \ sys/time.h sys/shm.h sys/ipc.h sys/signal.h sys/scanio.h os2.h \ sys/socket.h sys/io.h sys/hw.h sys/types.h linux/ppdev.h \ dev/ppbus/ppi.h machine/cpufunc.h sys/sem.h sys/poll.h \ windows.h be/kernel/OS.h limits.h sys/ioctl.h asm/types.h\ netinet/in.h tiffio.h ifaddrs.h pwd.h getopt.h) AC_CHECK_HEADERS([asm/io.h],,,[#include ]) SANE_CHECK_MISSING_HEADERS AC_CHECK_HEADERS(winsock2.h, SOCKET_LIB="-lws2_32") AC_CHECK_HEADER(resmgr.h,[ AC_CHECK_LIB( resmgr, rsm_open_device,[ AC_DEFINE(HAVE_RESMGR,1,[define if you have the resmgr library]) RESMGR_LIBS="-lresmgr" ] ) ]) AC_SUBST(RESMGR_LIBS) dnl *********************************************************************** dnl Checks for types and structures dnl *********************************************************************** AC_TYPE_SIZE_T AC_TYPE_PID_T AC_TYPE_SSIZE_T SANE_CHECK_U_TYPES # from Python, check for "long long" type AC_MSG_CHECKING(for long long support) have_long_long=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[long long x; x = (long long)0;]])],[AC_DEFINE(HAVE_LONG_LONG, 1, Define if the long long type is available.) have_long_long=yes],[]) AC_MSG_RESULT($have_long_long) AC_MSG_CHECKING([for socklen_t in ]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[socklen_t len]])],AC_MSG_RESULT(yes), [AC_MSG_RESULT(no); AC_DEFINE(socklen_t,int, [Define socklen_t as \'int\' if necessary.])]) AC_MSG_CHECKING([for union semun in ]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include ]], [[union semun test_semun]])],[AC_MSG_RESULT(yes); AC_DEFINE(HAVE_UNION_SEMUN,1,[Define if union semun is available.])], [AC_MSG_RESULT(no)]) AC_MSG_CHECKING([for struct flock in fcntl.h]) AC_EGREP_HEADER([struct flock], fcntl.h, [AC_MSG_RESULT(yes) ; AC_DEFINE(HAVE_STRUCT_FLOCK, 1, [Define if struct flock is available.])], AC_MSG_RESULT(no)) AC_MSG_CHECKING([for Linux ioctl defines]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]],[[ __u32 houba = _IOR('v',14, unsigned long); ]])],[AC_MSG_RESULT(yes); have_linux_ioctl_defines="yes";],AC_MSG_RESULT(no)) dnl *********************************************************************** dnl Checks for compiler characteristics dnl *********************************************************************** AC_C_BIGENDIAN AC_C_CONST AC_C_INLINE dnl *********************************************************************** dnl Checks for library functions dnl *********************************************************************** dnl Functions for which we provide an implementation if missing AC_CONFIG_LIBOBJ_DIR([lib]) AC_FUNC_ALLOCA AC_REPLACE_FUNCS([getenv inet_ntop inet_pton isfdtype sigprocmask \ sleep snprintf strcasestr strdup strndup strsep syslog usleep \ vsyslog]) AS_IF([test x != x$ALLOCA], [LTALLOCA=`echo "$ALLOCA" | sed 's/\.o$//; s/\.obj$//'`.lo]) AC_SUBST(LTALLOCA) dnl Define SOCKET_LIB, NSL_LIB, BIND_LIB, and RESOLV_LIB when required dnl for functions we use. AC_CHECK_FUNC(gethostbyaddr,, [AC_CHECK_LIB(bind, gethostbyaddr, BIND_LIB="-lbind")]) AC_CHECK_FUNC(gethostbyaddr,, [AC_CHECK_LIB(nsl, gethostbyaddr, NSL_LIB="-lnsl")]) AC_CHECK_FUNC(socket,, [AC_CHECK_LIB(socket, socket, SOCKET_LIB="-lsocket")]) AC_CHECK_FUNC(inet_aton,, [AC_CHECK_LIB(resolv, inet_aton, RESOLV_LIB="-lresolv")]) dnl Group related network libraries together so they can always be linked dnl in. SOCKET_LIBS="$SOCKET_LIB $NSL_LIB $BIND_LIB $RESOLV_LIB" AC_SUBST(SOCKET_LIBS) dnl define HAVE_* values for network functions. This may require dnl SOCKET_LIBS so set LIBS temporarily. save_LIBS="$LIBS" LIBS="$LIBS $SOCKET_LIBS" AC_CHECK_FUNCS(inet_addr inet_aton inet_ntoa) LIBS="$save_LIBS" if test "$ac_cv_header_be_kernel_OS_h" = "yes" ; then dnl those are known to be broken in BeOS (BONE) ac_cv_func_getaddrinfo=no ac_cv_func_getnameinfo=no fi AC_FUNC_MMAP AC_CHECK_FUNCS(atexit ioperm i386_set_ioperm \ mkdir strftime strstr strtod \ cfmakeraw tcsendbreak strcasecmp strncasecmp _portaccess \ getaddrinfo getnameinfo poll setitimer iopl getuid getpass) dnl sys/io.h might provide ioperm but not inb,outb (like for dnl non i386/x32/x86_64 with musl libc) if test "${ac_cv_header_sys_io_h}" = "yes"; then AC_MSG_CHECKING([for inb,outb (provided by sys/io.h)]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[inb(0);outb(0,0);]])], [AC_MSG_RESULT([yes]) sane_cv_have_sys_io_h_with_inb_outb="yes"], [AC_MSG_RESULT([no]) sane_cv_have_sys_io_h_with_inb_outb="no" AC_MSG_WARN([sys/io.h does not provide inb,outb (non i386/x32/x86_64 arch?)])]) if test "$sane_cv_have_sys_io_h_with_inb_outb" = "yes"; then AC_DEFINE(SANE_HAVE_SYS_IO_H_WITH_INB_OUTB, 1, [Define to 1 if you have the providing inb,outb.]) fi else sane_cv_have_sys_io_h_with_inb_outb="no" fi SANE_PROTOTYPES if test "$ac_cv_header_os2_h" = "yes" ; then AC_DEFINE(strncasecmp, strnicmp, [Define for OS/2 only]) AC_DEFINE(strcasecmp, stricmp, [Define for OS/2 only]) fi if test "$ac_cv_header_getopt_h" = "yes" ; then AC_CHECK_FUNCS(getopt_long) fi # Slightly abuse the AC_LIBOBJ macro to mark files as replacement code AS_IF([test x$ac_cv_header_getopt_h != xyes \ && test x$ac_cv_func_getopt_long != xyes], [AC_LIBOBJ(getopt) AC_LIBOBJ(getopt1)]) dnl *********************************************************************** dnl checks for system services dnl *********************************************************************** if test -c /dev/urandom ; then AC_DEFINE(HAVE_DEV_URANDOM, 1, [Is /dev/urandom available?]) fi AC_ARG_WITH(systemd, AS_HELP_STRING([--with-systemd], [enable systemd support @<:@default=yes@:>@])) if test "x$with_systemd" != xno ; then PKG_CHECK_MODULES(SYSTEMD, [libsystemd], have_systemd=yes, have_systemd=no) if test "x$have_systemd" = xno; then PKG_CHECK_MODULES(SYSTEMD, [libsystemd-daemon], have_systemd=yes, have_systemd=no) fi if test "x$have_systemd" = xyes; then AC_DEFINE(HAVE_SYSTEMD, 1, [Is /usr/include/systemd/sd-daemon.h available?]) else if test "x$with_systemd" = xyes; then AC_MSG_ERROR([Systemd support was requested but systemd was not found]) fi fi fi dnl ****************************************************************** dnl Check for USB support dnl ****************************************************************** AC_ARG_WITH(usb, AS_HELP_STRING([--with-usb], [enable USB support @<:@default=check@:>@]), [], [with_usb=check]) AS_IF([test xno != "x$with_usb"], [have_usb=no AS_CASE(x$host_os, dnl odd-ball operating systems first [beos*], [AC_CHECK_HEADER(be/drivers/USB_scanner.h, [have_usb=yes])], [os2*], [AC_CHECK_HEADER(usbcalls.h, [AC_CHECK_LIB(usbcall, UsbQueryNumberDevices, [USB_LIBS="-lusbcall" have_usb=yes AC_DEFINE(HAVE_USBCALLS, [1], [Define to 1 if you have usbcall.dll.]) ]) ], [], [#include #include ]) ], [dnl default to libusb-1.x, fall back to libusb-0.x if missing PKG_CHECK_MODULES([USB], [libusb-1.0], [AC_DEFINE([HAVE_LIBUSB], [1], [Define to 1 if you have libusb-1.0]) have_usb=yes ], [PKG_CHECK_MODULES([USB], [libusb >= 0.1.8], [AC_DEFINE([HAVE_LIBUSB_LEGACY], [1], [Define to 1 if you have libusb-0.1]) have_usb=yes ], [dnl 10+ years old libusb or Windows version AC_CHECK_HEADER(usb.h, AC_CHECK_LIB(usb, usb_interrupt_read, [USB_LIBS="-lusb" have_usb=yes ])) AC_CHECK_HEADERS(lusb0_usb.h, AC_CHECK_LIB(usb, usb_interrupt_read, [USB_LIBS="-lusb" have_usb=yes ])) ]) ]) ]) ]) AS_IF([test xyes = "x$with_usb" && test xyes != "x$have_usb"], [AC_MSG_ERROR([USB support requested but required libraries not found.]) ]) AM_CONDITIONAL([have_usblib], [test x != "x$USB_LIBS"]) dnl ************ dnl SCSI Support dnl ************ dnl FIXME: These are a lot of header files to scan. We should dnl scan for just one that is unique per platform and then do dnl conditional scans for more specific only as needed. # Unset VERSION during the SCSI header check sed "s!^#define VERSION .*!/* & */!" confdefs.h > confdefs.h.tmp mv confdefs.h.tmp confdefs.h AC_CHECK_HEADERS(IOKit/scsi/SCSITaskLib.h IOKit/cdb/IOSCSILib.h \ IOKit/scsi/SCSICommandOperationCodes.h \ IOKit/scsi-commands/SCSICommandOperationCodes.h scsi.h sys/scsi.h \ sys/scsicmd.h sys/scsiio.h bsd/dev/scsireg.h scsi/sg.h \ camlib.h gscdds.h sys/scsi/scsi.h sys/scsi/sgdefs.h \ sys/scsi/targets/scgio.h apollo/scsi.h sys/sdi_comm.h \ sys/passthrudef.h) # Restore VERSION sed "s!/\* \(#define VERSION .*\) \*/!\1!" confdefs.h > confdefs.h.tmp mv confdefs.h.tmp confdefs.h AC_CHECK_HEADERS([io/cam/cam.h],,,[#include ]) AC_CHECK_HEADERS([ntddscsi.h ddk/ntddscsi.h],,,[#include ]) dnl FreeBSD < 3 if test "$ac_cv_header_sys_scsiio_h" = "yes" \ && test "$ac_cv_header_scsi_h" = "yes"; then AC_MSG_CHECKING([if 'scsireq_t' needs to be defined as 'struct scsireq']) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[scsireq_t req]])],, [AC_MSG_RESULT(yes); AC_DEFINE(scsireq_t, struct scsireq_t, [Define scsireq_t as \'struct scsireq\' if necessary.])]) fi AC_CHECK_LIB(scsi, scsireq_enter, SCSI_LIBS="-lscsi") # FreeBSD needs this dnl FreeBSD >= 3 AC_CHECK_LIB(cam, cam_open_device, SCSI_LIBS="-lcam") # FreeBSD 3+ needs this AC_CHECK_FUNCS(scsireq_enter) if test "$ac_cv_header_scsi_sg_h" = "yes"; then AC_MSG_CHECKING([for sg_header.target_status in ]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]],[[ struct sg_header hdr; hdr.target_status = 1; return 0; ]])],[AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SG_TARGET_STATUS,1, [Define if sg_header.target_status is available.])], AC_MSG_RESULT(no)) fi if test "$ac_cv_header_IOKit_scsi_SCSITaskLib_h" = "yes"; then AC_MSG_CHECKING([for SCSITaskSGElement in IOKit/scsi/SCSITaskLib.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #undef VERSION #include ]],[[ SCSITaskSGElement range; return 0; ]])],[AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SCSITASKSGELEMENT, 1, [Define if SCSITaskSGElement is available.])], AC_MSG_RESULT(no)) fi # Multiple platforms can set SCSI_LIBS so do substitution at end. AC_SUBST(SCSI_LIBS) AC_ARG_ENABLE(scsibuffersize, AS_HELP_STRING([--enable-scsibuffersize=N], [specify the default size in bytes of the buffer for SCSI commands @<:@default=131072@:>@]), [set_scsibuffersize="$enableval"], [set_scsibuffersize=131072]) AC_DEFINE_UNQUOTED(SCSIBUFFERSIZE, $set_scsibuffersize, [SCSI command buffer size]) dnl FIXME: Move tihs to configuration printout area but probably dnl but probably needs to be wrapped by what ever uses it so its dnl only printed when used. echo "scsi buffersize: $set_scsibuffersize" AC_ARG_ENABLE(scsi-directio, AS_HELP_STRING([--enable-scsi-directio], [enable SCSI direct IO (Linux only, dangerous, see README.linux)]), [ if eval "test x$enable_scsi_directio = xyes"; then AM_CFLAGS="$AM_CFLAGS -DENABLE_SCSI_DIRECTIO" fi ]) dnl **** dnl IPv6 dnl **** dnl check for IPv6 (can be overriden by --enable-ipv6) if test "$ac_cv_func_getnameinfo" = "yes" \ && test "$ac_cv_func_getaddrinfo" = "yes" ; then SANE_CHECK_IPV6 else ipv6="no" fi dnl *********************************************************************** dnl initialize libtool dnl *********************************************************************** AC_ARG_ENABLE(preload, AS_HELP_STRING([--disable-preload], [Disable preloading of backends]), [enable_preload=$enableval], [enable_preload=auto]) dnl Windows (cygwin/mingw), BeOS, and OS/2 need this. case $host_os in cygwin* | mingw* | beos* | os2*) AM_LDFLAGS="$AM_LDFLAGS -no-undefined" esac dnl Check for lock dir AC_ARG_WITH(lockdir, AS_HELP_STRING([--with-lockdir=DIR], [set SANE lockdir @<:@localstatedir/lock/sane@:>@]), [locksanedir=$withval],[locksanedir=${localstatedir}/lock/sane]) AC_SUBST(locksanedir) configdir="${sysconfdir}/sane.d" AC_SUBST(configdir) dnl *********************************************************************** dnl enable/disable backends and features based on previous tests and user's dnl choice dnl *********************************************************************** AM_CPPFLAGS="${AM_CPPFLAGS} -DPATH_SANE_CONFIG_DIR=\$(configdir) \ -DPATH_SANE_DATA_DIR=\$(datadir) \ -DPATH_SANE_LOCK_DIR=\$(locksanedir) \ -DV_MAJOR=${V_MAJOR} -DV_MINOR=${V_MINOR}" if test "${ac_cv_header_sys_socket_h}" = "no"; then echo "*** disabling saned (sys/socket.h not found)" SANED= else SANED=saned fi AM_CONDITIONAL(COMPILE_SANED, test x$SANED = xsaned) dnl These are the backends that are build in any case: AC_ARG_ENABLE(local-backends, AS_HELP_STRING([--disable-local-backends], [turn off compilation of all backends but net])) ALL_BACKENDS="abaton agfafocus apple artec artec_eplus48u as6e \ avision bh canon canon630u canon_dr canon_pp cardscan \ coolscan coolscan2 coolscan3 dc25 dc210 dc240 \ dell1600n_net dmc epjitsu epson epson2 epsonds fujitsu genesys \ gphoto2 gt68xx hp hp3500 hp3900 hp4200 hp5400 \ hp5590 hpsj5s hpljm1005 hs2p ibm kodak kodakaio kvs1025 kvs20xx \ kvs40xx leo lexmark ma1509 magicolor \ matsushita microtek microtek2 mustek mustek_pp \ mustek_usb mustek_usb2 nec net niash pie pieusb pint \ pixma plustek plustek_pp qcam ricoh rts8891 s9036 \ sceptre sharp sm3600 sm3840 snapscan sp15c st400 \ stv680 tamarack teco1 teco2 teco3 test u12 umax umax_pp umax1220u v4l xerox_mfp p5" # If user specifies backends manually then cause configure # to fail if its detected it can't be compiled. If we # are in automatic mode then remove backend from list instead. user_selected_backends="yes" AC_ARG_VAR(BACKENDS, [list of backends to compile]) if eval "test x$enable_local_backends = xno"; then BACKENDS="net" else if test "${BACKENDS}" != "" ; then AC_MSG_NOTICE([Manually selected backends: ${BACKENDS}]) else BACKENDS="$ALL_BACKENDS" user_selected_backends="no" fi fi SANE_CHECK_BACKENDS if test "${sane_cv_use_libjpeg}" = "yes"; then SANEI_SANEI_JPEG_LO="../sanei/sanei_jpeg.lo" fi AM_CONDITIONAL(HAVE_JPEG, test x$sane_cv_use_libjpeg = xyes) AC_SUBST(SANEI_SANEI_JPEG_LO) AC_ARG_ENABLE(pnm-backend, AS_HELP_STRING([--enable-pnm-backend], [enable the pnm backend for testing frontends (possible security risk, see PROBLEMS file)]), [FILTERED_BACKENDS="${FILTERED_BACKENDS} pnm"], [echo "*** pnm backend not manually selected - disabling"]) BACKENDS="$FILTERED_BACKENDS" BACKEND_LIBS_ENABLED="" BACKEND_CONFS_ENABLED="" BACKEND_MANS_ENABLED="" for backend in ${BACKENDS} ; do BACKEND_LIBS_ENABLED="${BACKEND_LIBS_ENABLED} libsane-${backend}.la" BACKEND_CONFS_ENABLED="${BACKEND_CONFS_ENABLED} ${backend}.conf" BACKEND_MANS_ENABLED="${BACKEND_MANS_ENABLED} sane-${backend}.5" if test x$backend = xumax_pp; then install_umax_pp_tools=yes fi done AC_SUBST(BACKEND_LIBS_ENABLED) AM_CONDITIONAL(INSTALL_UMAX_PP_TOOLS, test xyes = x$install_umax_pp_tools) AC_ARG_VAR(PRELOADABLE_BACKENDS, [list of backends to preload into single DLL]) if test "${enable_preload}" = "auto"; then if test "${enable_shared}" = "no" || test "${enable_dynamic}" != "yes"; then enable_preload=yes fi fi if test "${enable_preload}" = "yes"; then echo "preloading backends into DLL" # If user specifies backends manually then cause configure # to fail if its detected it can't be compiled. If we # are in automatic mode then remove backend from list instead. user_selected_backends="yes" if eval "test x$enable_local_backends = xno"; then PRELOADABLE_BACKENDS="net" else if test "${PRELOADABLE_BACKENDS}" != "" ; then AC_MSG_NOTICE([Manually selected preloadable backends: ${PRELOADABLE_BACKENDS}]) else PRELOADABLE_BACKENDS="$BACKENDS" user_selected_backends="no" fi fi saved_BACKENDS="$BACKENDS" BACKENDS="${PRELOADABLE_BACKENDS}" SANE_CHECK_BACKENDS PRELOADABLE_BACKENDS="$FILTERED_BACKENDS" BACKENDS="$saved_BACKENDS" else PRELOADABLE_BACKENDS="" fi PRELOADABLE_BACKENDS_ENABLED="" # Do not initialize BACKEND_CONFS_ENABLED so that its a combination # of all backends. for backend in ${PRELOADABLE_BACKENDS} ; do BACKEND_CONFS_ENABLED="${BACKEND_CONFS_ENABLED} ${backend}.conf" BACKEND_MANS_ENABLED="${BACKEND_MANS_ENABLED} sane-${backend}.5" # Special hacks. Normally, we create a convenience library that # matches the backend's name but in some cases that will conflict # with an external library name that also matches backend name. # Work around that here by renaming internal library. if test "${backend}" = "gphoto2"; then backend=gphoto2_i fi PRELOADABLE_BACKENDS_ENABLED="${PRELOADABLE_BACKENDS_ENABLED} lib${backend}.la" done AC_SUBST(PRELOADABLE_BACKENDS) AC_SUBST(PRELOADABLE_BACKENDS_ENABLED) AC_SUBST(BACKEND_CONFS_ENABLED) AC_SUBST(BACKEND_MANS_ENABLED) dnl in BeOS, backends are not installed in lib/sane, but add-ons/sane/ dnl we account for both installing in /boot/beos and ~/config case $host_os in beos*) libdir='${exec_prefix}/add-ons' ;; esac AC_ARG_ENABLE(parport-directio, AS_HELP_STRING([--enable-parport-directio], [enable direct hardware access to the parallel port, so frontends will require special permission level]), [ if eval "test x$enable_parport_directio = xyes"; then AM_CFLAGS="$AM_CFLAGS -DENABLE_PARPORT_DIRECTIO" fi ]) dnl ****************************************************************** dnl SANE API specification format conversion support dnl ****************************************************************** AC_ARG_WITH(api-spec, AS_HELP_STRING([--with-api-spec], [convert API spec to supported output formats @<:@default=check@:>@]), [], [with_api_spec=check]) dnl Test for all tools that may be involved. These tests are fast and dnl running them allows for the Makefile targets to be formulated such dnl that any non-requested formats can be made using a one-off without dnl the need to reconfigure. AC_PATH_PROG(MAKEINDEX, makeindex, no) AC_PATH_PROG(DVIPS, dvips, no) AC_PATH_PROG(LATEX, latex, no) AC_PATH_PROG(PDFLATEX, pdflatex, no) AC_PATH_PROG(FIG2DEV, fig2dev, no) AC_PATH_PROG(GS, gs, no) AC_PATH_PROG(DLH, dlh, no) AC_PATH_PROG(PPMTOGIF, ppmtogif, no) AS_IF([test xno != "x$with_api_spec"], [dnl Flag formats for which all required tools have been found AS_IF([ test xno != "x$MAKEINDEX" \ && test xno != "x$DVIPS" \ && test xno != "x$FIG2DEV" \ && test xno != "x$LATEX"], [with_api_ps=yes]) AS_IF([ test xno != "x$MAKEINDEX" \ && test xno != "x$PDFLATEX" \ && test xno != "x$FIG2DEV" \ && test xno != "x$GS"], [with_api_pdf=yes]) AS_IF([ test xno != "x$MAKEINDEX" \ && test xno != "x$DVIPS" \ && test xno != "x$FIG2DEV" \ && test xno != "x$DLH" \ && test xno != "x$GS" \ && test xno != "x$PPMTOFIG" ], [with_api_html=yes]) AS_IF([test xyes = "x$with_api_spec" \ && test xyes != "x$with_api_ps" \ && test xyes != "x$with_api_pdf" \ && test xyes != "x$with_api_html"], [AC_MSG_ERROR([tools to convert the API spec are missing]) ]) ]) AM_CONDITIONAL(WITH_API_PS, [test x$with_api_ps = xyes]) AM_CONDITIONAL(WITH_API_PDF, [test x$with_api_pdf = xyes]) AM_CONDITIONAL(WITH_API_HTML, [test x$with_api_html = xyes]) dnl *********************************************************************** dnl Write output files dnl *********************************************************************** AC_SUBST(AM_CPPFLAGS) AC_SUBST(AM_CFLAGS) AC_SUBST(AM_LDFLAGS) AC_CONFIG_FILES([Makefile lib/Makefile sanei/Makefile frontend/Makefile \ japi/Makefile backend/Makefile include/Makefile doc/Makefile \ po/Makefile.in testsuite/Makefile testsuite/sanei/Makefile testsuite/tools/Makefile \ tools/Makefile doc/doxygen-sanei.conf doc/doxygen-genesys.conf]) AC_CONFIG_FILES([tools/sane-config], [chmod a+x tools/sane-config]) AC_CONFIG_FILES([tools/sane-backends.pc]) AC_OUTPUT dnl *********************************************************************** dnl print configuration information dnl *********************************************************************** echo "-> Variables used for compilation/linking:" echo AM_CPPFLAGS=\"${AM_CPPFLAGS}\" echo AM_CFLAGS=\"${AM_CFLAGS}\" echo AM_LDFLAGS=\"${AM_LDFLAGS}\" echo LIBS=\"${LIBS}\" echo "-> Installation directories:" echo "Configuration: `eval eval echo ${sysconfdir}`" echo "Libraries: `eval eval echo ${libdir}`" echo "Binaries: `eval eval echo ${bindir}` and `eval eval echo ${sbindir}`" echo "Manpages: `eval eval echo ${mandir}`" echo "Documentation: `eval eval echo ${docdir}`" if eval "test x$INSTALL_LOCKPATH = xinstall-lockpath" ; then echo "Lockfiles: `eval eval echo ${locksanedir}`" else echo "Lockfiles: Feature is disabled!" fi echo "-> Network parameters:" if test "${SANED}" = "saned" ; then echo "Build saned: yes" else echo "Build saned: no" fi echo "IPv6 support: `eval eval echo ${ipv6}`" echo "Avahi support: `eval eval echo ${enable_avahi}`" echo "SNMP support: `eval eval echo ${with_snmp}`" echo "-> The following backends will be built:" for backend in ${BACKENDS} ; do echo $ECHO_N "${backend} " done echo echo echo "-> The following preload backends will be built:" for backend in ${PRELOADABLE_BACKENDS} ; do echo $ECHO_N "${backend} " done echo if test "$SANE_CONFIG_PATH" != "no" ; then SANE_INSTALLED_VERSION=`$SANE_CONFIG_PATH --version` SANE_INSTALLED_PREFIX=`$SANE_CONFIG_PATH --prefix` if test "$SANE_INSTALLED_PREFIX" != "$prefix" ; then echo "*** WARNING: SANE is already installed (version $SANE_INSTALLED_VERSION). The old" echo "*** installation is at $SANE_INSTALLED_PREFIX while SANE will now be installed" echo "*** at $prefix. It is recommended to uninstall the old SANE version" echo "*** before installing the new one to avoid problems." fi else if test "$LIBSANE_EXISTS" = "yes" ; then echo "*** Warning: An old version of SANE was detected but the sane-config program" echo "*** couldn't be found. If you encounter any problems with SANE remove the old" echo "*** SANE files and reinstall this version." fi fi if eval "test x${sysconfdir} = x/usr/etc" ; then echo "*** WARNING: Configuration files are stored in /usr/etc. If this is not" echo "*** intended, use --sysconfdir to set another path (e.g. "/etc")." fi if test "$SELECTED_BACKENDS" != "" ; then echo "*** Warning: Local backends have been disabled. This means that scanners" echo "*** connected to your local computer won't be supported. Only a network" echo "*** connection to a remote host is possible." fi if test "$with_usb" != "no" && test "$have_usb" != "yes" ; then echo "*** Warning: sane-backends will be built without USB support. There may" echo "*** be valid reasons to do so, e.g. if you don't use USB scanners or on" echo "*** platforms without USB support but generally this means that you" echo "*** can't use USB devices with SANE. The most probable cause is that" if test "${ac_cv_header_usb_h}" != "yes"; then echo "*** the libusb header file usb.h is not installed. If you use Linux" echo "*** you may need a package called 'libusb-dev', 'libusb-devel' or similar." else echo "*** libusb is not installed at all or is too old. See README." fi fi echo "****************************************************************" echo "* Please be sure to read file PROBLEMS in this directory *" echo "* BEFORE running any of the SANE applications. Some devices *" echo "* may be damaged by improper operation, so please do heed this *" echo "* advice. *" echo "****************************************************************" sane-backends-1.0.27/README.os20000664000175000017500000001730512112021330012573 000000000000002002-01-03 Look at http://home.tiscalinet.de/fbakan/sane-os2.htm for information about compiling SANE on OS/2 (from Franz Bakan). The following text was for 1.0.3, but it may help nevertheless. SANE 1.03 for OS/2 - build 1 ---------------------------- 09 Jul 2000, Yuri Dario WARNING: -------- This release of has been compiled with EMX 0.9D, so it doesn't work with the previous runtime. You must upgrade to the latest runtime before running SANE (actually EMX 0.9D fix 03). SANE (Scanner Access Now Easy) ------------------------------ For more info about the SANE Project, please visit http://www.sane-project.org/ You should also check the main site for an updated list of supported scanners. Note that I can't say you if your scanner is supported; check SANE homepage instead. SUPPORT ------- I'm sorry to tell you that it is hard for me to help you: if your scanner doesn't work or your problem can't be reproduced on my pc, there are high choices that I can't fix the bug. Most problems are specific to same PC/scanner combinations, and can't be solved without having a full developement enviroment and programming experience. I have setup a mailing list for users, where I hope most people can find an answer to their questions. You will find that I answer only sometimes, because I'm too busy. To subscribe please visit http://www.egroups.com and look for sane-os2, or fill the form available on my site. DOCUMENTATION ------------- To read docs with correct format, you should type more < doc\sane-epson.txt If someone has more ideas on how to get a correct .txt starting from a .man file, he is welcome (actually I'm using groff). INSTALLATION ------------ If you already didn't it, install the correct driver for your scsi adapter. The drivers has usually a .ADD extension and looks like BASEDEV=AHA154X.ADD Then you need the ASPI driver: this driver is already in your OS2\BOOT directory, so you have only to add BASEDEV=OS2ASPI.DMD /ALL The /ALL switch is required only if you need to use other devices with aspirout.sys, e.g. if you have a CD-RW and CDRecord/2 installed. Last, add aspirout.sys to your config.sys DEVICE=D:\OS2\BOOT\ASPIROUT.SYS N.B. you can change the path to other directories. Now reboot. To run scanimage.exe you need also to download the latest EMX runtime, available on Hobbes or Leo as emxrt.zip. find-scanner.exe can be used to recognize a scanner on the scsi bus. Then you should edit your xxx.conf file and add the scanner address, a string like b0t4l0. This can be simplified using autodetection: with autodetection you can use a string like scsi EPSON in your xxx.conf file; the autodection will enable the backend that recognize 'EPSON' in the scanner id. To test scanimage, run scanimage --help you should see your scanner following the list of internal devices: List of available devices: pnm:0 pnm:1 If it is not present, check your scsi driver, the aspi driver OS2ASPI.DMD and aspirout.sys; on Warp4 you can use the Hardware Manager to check scanner presence. Then look at your xxx.conf, maybe there is something wrong in the text. USAGE: ------ Once configured your system, create a proper .conf file (edit one of the supplied templates) and run scanimage -L The output should be like device `umax:b0t3l0' is a UMAX Vista-S8 flatbed scanner device `pnm:0' is a Noname PNM file reader virtual device device `pnm:1' is a Noname PNM file reader virtual device The pnm devices are always available, while on the first line you should read the id of your scanner. A simple scan scanimage -d umax > test.pnm will do a scan with default parameters. Run scanimage -d umax --help to get a full list of available switches. SANED: ------ In this release the SANE network daemon can be used (with a limit). First edit your \mptn\etc\services and add sane 6566/tcp # SANE network scanner daemon (maybe a reboot is required to apply that change). Create a saned.conf in the same directory of saned.exe and add a list of valid client addresses; the clients are allowed to access the local scanner. Now run the server in debug mode saned -d On the client side, you need to create a net.conf file in the same directory of scanimage.exe: here you have to add a list of valid saned servers. Run scanimage -L The output is like this device `umax:b0t3l0' is a UMAX Vista-S8 flatbed scanner device `pnm:0' is a Noname PNM file reader virtual device device `pnm:1' is a Noname PNM file reader virtual device device `net:pippo.intranet:umax:b0t3l0' is a UMAX Vista-S8 flatbed scanner device `net:pippo.intranet:pnm:0' is a Noname PNM file reader virtual device device `net:pippo.intranet:pnm:1' is a Noname PNM file reader virtual device Then saned will quit. To run it forever, you have to configure the INETD daemon: create a \mptn\etc\inetd.lst with the following line sane tcp /rd/sane/sane-1.0.1/frontend/saned.exe Be aware that this configuration shouldn't work: I have been unable to get it working on my PC without running saned under the debugger PMGDB. The correct syntax for running scanimage over the net is scanimage -d net:HOSTNAME:umax:b0t3l0 > test.pnm where HOSTNAME is a valid DNS host name. You can log server access using syslogd: if syslogd is running, saned will send to it all messages. HOW TO COMPILE: --------------- To compile SANE with emx, you need - EMX 0.9D - GNU Make 3.75 (rename to make.exe) - GNU Patch 2.5 - KSH 5.2.13 (rename to sh.exe) - GNU Bison - GNU File utilities - GNU SED (stream editor) - Autoconf 2.13 Steps: - untar the original Unix distribution; - unzip this file somewhere; - copy src\* into sane-1.0.1; - enter sane-1.0.1 directory; - apply patches to original distribution: [...\sane-1.0.1]gnupatch -p 0 < patch.os2 - run autoconf to rebuild the configure script - edit configure and change autoconf default optimization flags; search for -O2 -m486 and change to your preferred settings; - add the following line after :${LDFLAGS="...."} : ${LIBS="-lsocket"} - run configure.os2 to build all installation files; - add -Zexe to LDFLAGS in frontend\Makefile and tools\Makefile; - run make (compiler warnings are ok); - wait to complete all makes; Remember to install a Unix like shell in your path; I use ksh.exe renamed to sh.exe, and saved in d:\bin (that's because most unix scripts uses SHELL=/bin/sh) You need also a compatible dl.a and syslog.a library; look in .\contrib for a couple of simple sources. Flags needed under EMX: -Zsysv-signals enables signal management as in SystemV, otherwise emx convention is used (and it is different from sysv). -Zcrtdll link dynamically with EMXLIBCM.DLL; PARALLEL PORT ------------- This release has support for parallel port enabled: actually only the Epson backend makes uses of such support; the Epson GT-300 can be recognized, but scanning can't be completed. Also HP-5100C parallel scanner can be run under OS/2: you need to download the EPST driver from Shuttle Tech. homepage (www.shuttletech.com); follow the instruction for installation. Then the scanner is seen as a scsi HP, so the HP backend can work with it. The Quickcam backend is also included with lpt support, but I can't say how it is working. History: -------- 09 Jul 2000 release 1.03 20 Jun 1999 release 1.01 - changed runtime to EMX 0.9D - fixed: find-scanner should now work correctly. - added: how to compile instructions. 07 Mar 1999 release 1.01 pre-test3 no OS/2 specific fixes 20 Oct 1998 release 0.74 fixed fork()ing backends with new sanei_thread api. fixed scsi autodetection added parallel port support =============================================================================== Yuri Dario http://www.quasarbbs.com/yuri sane-backends-1.0.27/LICENSE0000664000175000017500000000372112112021330012213 00000000000000Sat Apr 23 2005 This files attempts to clarify the licensing situation for the SANE distribution. In case of doubt, the copyright information contained in each file overrides what is said here. SANE consists of three parts each of which has its own licensing terms: * The frontend programs. These programs are generally protected by the GNU General Public License. (See file COPYING.) * The backend libraries. Most backend libraries are protected by the GNU General Public License (see file COPYING), but as an exception, it is permissible to link against such a library without affecting the licensing status of the program that uses the libraries. For details, see the copyright notice at the head of the backend files (e.g., backend/dll.c). Note that not all of the backends apply the exception and that some have additional licensing constraints. E.g., the DC210 backend uses JPG code that is licensed as described in README.djpeg. * The SANE API and network protocol as put forth in the standard document. The standard is considered to be in the public domain. Anyone is free to implement SANE interface conforming applications or libraries in any way he or she sees fit. Frequently Asked Questions about the SANE licensing: * Why don't you use the GNU LPGL ? The reason SANE isn't licensed under the GNU LGPL is very simple: the GNU LGPL didn't exist at the time SANE was first released. So, the SANE Exception was added to the GNU GPL. * Why don't you relicense SANE, now that the GNU LGPL is available ? To relicense the various pieces of code composing SANE, each and every copyright holder needs to agree with the relicensing. Unfortunately, some of the (original) backend authors cannot be contacted any longer, for various reasons; not to mention each and every contributor who sent in a patch. This effectively makes it impossible for the SANE Project to relicense SANE. sane-backends-1.0.27/tools/0000775000175000017500000000000013110600532012431 500000000000000sane-backends-1.0.27/tools/RenSaneDlls.cmd0000664000175000017500000000335312112021330015206 00000000000000/* REXX */ /* Convert backend-DLL-filenames according to 8.3 naming convention */ /* necessary for DLLs on OS/2 (C) Franz Bakan 2004,2005 */ /* */ /* This file is part of the SANE package. */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License as */ /* published by the Free Software Foundation; either version 2 of the */ /* License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, but */ /* WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs' CALL SysLoadFuncs rc = SysFileTree('\usr\lib\sane\libsane-*.dll',dlls,O) DO i=1 TO dlls.0 PARSE VALUE dlls.i WITH front 'libsane-' backend '.dll' IF length(backend) > 7 THEN COPY dlls.i front||LEFT(backend,2)||RIGHT(backend,5,' ')||'.dll' ELSE IF length(backend) > 0 THEN COPY dlls.i front||backend||'.dll' DEL dlls.i END /* do */ sane-backends-1.0.27/tools/check-usb-chip.c0000664000175000017500000037533612775312262015343 00000000000000/* check-usb-chip.c -- Find out what USB scanner chipset is used Copyright (C) 2003-2005 Henning Meier-Geinitz Copyright (C) 2003 Gerhard Jaeger for LM983x tests Copyright (C) 2003 Gerard Klaver for ICM532B tests This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../include/sane/config.h" #ifdef HAVE_LIBUSB_LEGACY #include "../include/sane/sane.h" #include #include #include #ifdef HAVE_LUSB0_USB_H #include #else #include #endif #include "../include/_stdint.h" static int verbose = 0; static SANE_Bool no_chipset_access; #define TIMEOUT 1000 extern char *check_usb_chip (struct usb_device *dev, int verbosity, SANE_Bool from_file); static int prepare_interface (struct usb_device *dev, usb_dev_handle ** handle) { int result; if (no_chipset_access) return 0; *handle = usb_open (dev); if (*handle == 0) { if (verbose > 1) printf (" Couldn't open device: %s\n", usb_strerror ()); return 0; } result = usb_set_configuration (*handle, dev->config[0].bConfigurationValue); if (result < 0) { if (verbose > 1) printf (" Couldn't set configuration: %s\n", usb_strerror ()); usb_close (*handle); return 0; } result = usb_claim_interface (*handle, 0); if (result < 0) { if (verbose > 1) printf (" Couldn't claim interface: %s\n", usb_strerror ()); usb_close (*handle); return 0; } return 1; } static void finish_interface (usb_dev_handle * handle) { usb_release_interface (handle, 0); usb_close (handle); } /* Check for Grandtech GT-6801 */ static char * check_gt6801 (struct usb_device *dev) { char req[64]; usb_dev_handle *handle; int result; if (verbose > 2) printf (" checking for GT-6801 ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { if (verbose > 2) printf (" this is not a GT-6801 (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a GT-6801 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a GT-6801 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a GT-6801 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 1) { if (verbose > 2) printf (" this is not a GT-6801 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-6801 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } /* Now we send a control message */ result = prepare_interface (dev, &handle); if (!result) return "GT-6801?"; memset (req, 0, 64); req[0] = 0x2e; /* get identification information */ req[1] = 0x01; result = usb_control_msg (handle, 0x40, 0x01, 0x2010, 0x3f40, req, 64, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send write control message (%s)\n", strerror (errno)); finish_interface (handle); return 0; } result = usb_control_msg (handle, 0xc0, 0x01, 0x2011, 0x3f00, req, 64, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send read control message (%s)\n", strerror (errno)); finish_interface (handle); return 0; } if (req[0] != 0 || (req[1] != 0x2e && req[1] != 0)) { if (verbose > 2) printf (" Unexpected result from control message (%0x/%0x)\n", req[0], req[1]); finish_interface (handle); return 0; } finish_interface (handle); return "GT-6801"; } /* Check for Grandtech GT-6816 */ static char * check_gt6816 (struct usb_device *dev) { char req[64]; usb_dev_handle *handle; int result; int i; if (verbose > 2) printf (" checking for GT-6816 ...\n"); /* Check device descriptor */ if ((dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != USB_CLASS_VENDOR_SPEC)) { if (verbose > 2) printf (" this is not a GT-6816 (bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a GT-6816 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a GT-6816 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0x00) { if (verbose > 2) printf (" this is not a GT-6816 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } if (dev->config[0].bNumInterfaces != 0x01) { if (verbose > 2) printf (" this is not a GT-6816 (bNumInterfaces = 0x%x)\n", dev->config[0].bNumInterfaces); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 2) { if (verbose > 2) printf (" this is not a GT-6816 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-6816 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-6816 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } /* Now we send a control message */ result = prepare_interface (dev, &handle); if (!result) return "GT-6816?"; memset (req, 0, 64); for (i = 0; i < 8; i++) { req[8 * i + 0] = 0x73; /* check firmware */ req[8 * i + 1] = 0x01; } result = usb_control_msg (handle, 0x40, 0x04, 0x2012, 0x3f40, req, 64, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send write control message (%s)\n", strerror (errno)); finish_interface (handle); return 0; } result = usb_control_msg (handle, 0xc0, 0x01, 0x2013, 0x3f00, req, 64, TIMEOUT); if (result <= 0) { /* Before firmware upload, 64 bytes are returned. Some libusb implementations/operating systems can't seem to cope with short packets. */ result = usb_control_msg (handle, 0xc0, 0x01, 0x2013, 0x3f00, req, 8, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send read control message (%s)\n", strerror (errno)); finish_interface (handle); return 0; } } if (req[0] != 0) { if (verbose > 2) printf (" Unexpected result from control message (%0x/%0x)\n", req[0], req[1]); finish_interface (handle); return 0; } finish_interface (handle); return "GT-6816"; } /* Check for Grandtech GT-8911 */ static char * check_gt8911 (struct usb_device *dev) { char req[64]; usb_dev_handle *handle; int result; if (verbose > 2) printf (" checking for GT-8911 ...\n"); /* Check device descriptor */ if ((dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != USB_CLASS_VENDOR_SPEC)) { if (verbose > 2) printf (" this is not a GT-8911 (check 1, bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a GT-8911 (check 2, bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a GT-8911 (check 3, bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0x00) { if (verbose > 2) printf (" this is not a GT-8911 (check 4, bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 2) { if (verbose > 2) printf (" this is not a GT-8911 (check 5, bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } /* Check first endpoint descriptor block */ if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-8911 (check 6, bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-8911 (check 7, bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if (dev->config[0].bNumInterfaces < 2) { if (verbose > 2) printf (" this is not a GT-8911 (check 8, bNumInterfaces = %d)\n", dev->config[0].bNumInterfaces); return 0; } if (dev->config[0].interface[1].num_altsetting < 3) { if (verbose > 2) printf (" this is not a GT-8911 (check 9, num_altsetting = %d)\n", dev->config[0].interface[1].num_altsetting); return 0; } /* Check fourth endpoint descriptor block */ if ((dev->config[0].interface[1].altsetting[2].endpoint[0]. bEndpointAddress != 0x83) || (dev->config[0].interface[1].altsetting[2].endpoint[0]. bmAttributes != 0x01) || (dev->config[0].interface[1].altsetting[2].endpoint[0]. wMaxPacketSize != 0x01d0) || (dev->config[0].interface[1].altsetting[2].endpoint[0].bInterval != 0x01)) { if (verbose > 2) printf (" this is not a GT-8911 (check 10, bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[1].altsetting[2].endpoint[0]. bEndpointAddress, dev->config[0].interface[1].altsetting[2].endpoint[0].bmAttributes, dev->config[0].interface[1].altsetting[2].endpoint[0]. wMaxPacketSize, dev->config[0].interface[1].altsetting[2].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[1].altsetting[2].endpoint[1]. bEndpointAddress != 0x04) || (dev->config[0].interface[1].altsetting[2].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[1].altsetting[2].endpoint[1]. wMaxPacketSize != 0x40) || (dev->config[0].interface[1].altsetting[2].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-8911 (check 11, bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[1].altsetting[2].endpoint[1]. bEndpointAddress, dev->config[0].interface[1].altsetting[2].endpoint[1].bmAttributes, dev->config[0].interface[1].altsetting[2].endpoint[1]. wMaxPacketSize, dev->config[0].interface[1].altsetting[2].endpoint[1].bInterval); return 0; } /* Now we send a control message */ result = prepare_interface (dev, &handle); if (!result) return "GT-8911?"; memset (req, 0, 8); req[0] = 0x55; req[1] = 0x66; result = usb_control_msg (handle, 0xc0, 0x10, 0x41, 0x0000, req, 64, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" this is not a GT-8911 (check 12, couldn't send read control message (%s))\n", strerror (errno)); finish_interface (handle); return 0; } result = usb_control_msg (handle, 0xc0, 0x10, 0x05, 0x0000, req, 64, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" this is not a GT-8911 (check 13, couldn't send read control message (%s)\n", strerror (errno)); finish_interface (handle); return 0; } /* tested on model hardware version 0xffffffc0, firmware version 0x10)) */ if (verbose > 2) printf (" Check 14, control message (hardware version %0x / firmware version %0x)\n", req[0], req[1]); finish_interface (handle); return "GT-8911"; } /* Check for Mustek MA-1017 */ static char * check_ma1017 (struct usb_device *dev) { char req[2]; usb_dev_handle *handle; int result; char res; if (verbose > 2) printf (" checking for MA-1017 ...\n"); /* Check device descriptor */ if ((dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != USB_CLASS_PER_INTERFACE)) { if (verbose > 2) printf (" this is not a MA-1017 (bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->descriptor.bcdUSB != 0x100) { if (verbose > 2) printf (" this is not a MA-1017 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a MA-1017 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0x00) { if (verbose > 2) printf (" this is not a MA-1017 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a MA-1017 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a MA-1017 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x82) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a MA-1017 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0x01)) { if (verbose > 2) printf (" this is not a MA-1017 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } /* read a register value */ result = prepare_interface (dev, &handle); if (!result) return "MA-1017?"; req[0] = 0x00; req[1] = 0x02 | 0x20; result = usb_bulk_write (handle, 0x01, req, 2, 1000); if (result <= 0) { if (verbose > 2) printf (" this is not a MA-1017 (Error during bulk write)\n"); finish_interface (handle); return 0; } result = usb_bulk_read (handle, 0x82, &res, 1, 1000); if (result <= 0) { if (verbose > 2) printf (" this is not a MA-1017 (Error during bulk read)\n"); finish_interface (handle); return 0; } /* Read one byte again to work around a bug in the MA-1017 chipset that appears when an odd number of bytes is read or written. */ result = usb_bulk_write (handle, 0x01, req, 2, 1000); result = usb_bulk_read (handle, 0x82, &res, 1, 1000); finish_interface (handle); return "MA-1017"; } /* Check for Mustek MA-1015 */ static char * check_ma1015 (struct usb_device *dev) { char req[8]; usb_dev_handle *handle; int result; unsigned char res; if (verbose > 2) printf (" checking for MA-1015 ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { if (verbose > 2) printf (" this is not a MA-1015 (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x100) { if (verbose > 2) printf (" this is not a MA-1015 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a MA-1015 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a MA-1015 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 2) { if (verbose > 2) printf (" this is not a MA-1015 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a MA-1015 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x08) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a MA-1015 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } /* Now we read register 0 to find out if this is really a MA-1015 */ result = prepare_interface (dev, &handle); if (!result) return 0; memset (req, 0, 8); req[0] = 33; req[1] = 0x00; result = usb_bulk_write (handle, 0x02, req, 8, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" this is not a MA-1015 (Error during bulk write)\n"); finish_interface (handle); return 0; } result = usb_bulk_read (handle, 0x81, (char *) &res, 1, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" this is not a MA-1015 (Error during bulk read)\n"); finish_interface (handle); return 0; } if (res != 0xa5) { if (verbose > 2) printf (" this is not a MA-1015 (got 0x%x, expected 0xa5)\n", res); finish_interface (handle); return 0; } finish_interface (handle); return "MA-1015"; } /* Check for Mustek MA-1509 */ static char * check_ma1509 (struct usb_device *dev) { char req[8]; char inquiry[0x60]; usb_dev_handle *handle; int result; if (verbose > 2) printf (" checking for MA-1509 ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { if (verbose > 2) printf (" this is not a MA-1509 (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a MA-1509 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a MA-1509 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a MA-1509 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a MA-1509 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40)) { if (verbose > 2) printf (" this is not a MA-1509 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x08)) { if (verbose > 2) printf (" this is not a MA-1509 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x08) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0x10)) { if (verbose > 2) printf (" this is not a MA-1509 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } /* This is a SCSI-over-USB chip, we'll read the inquiry */ result = prepare_interface (dev, &handle); if (!result) return "MA-1509?"; memset (req, 0, 8); req[0] = 0x12; req[1] = 1; req[6] = 0x60; result = usb_bulk_write (handle, 0x02, req, 8, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" this is not a MA-1509 (Error during bulk write)\n"); finish_interface (handle); return 0; } memset (inquiry, 0, 0x60); result = usb_bulk_read (handle, 0x81, (char *) inquiry, 0x60, TIMEOUT); if (result != 0x60) { if (verbose > 2) printf (" this is not a MA-1509 (Error during bulk read: %d)\n", result); finish_interface (handle); return 0; } if ((inquiry[0] & 0x1f) != 0x06) { if (verbose > 2) printf (" this is not a MA-1509 (inquiry [0] = %d)\n", inquiry[0]); finish_interface (handle); return 0; } if (strncmp (inquiry + 8, "SCANNER ", 8) != 0) { inquiry[16] = 0; if (verbose > 2) printf (" this is not a MA-1509 (vendor=%s)\n", inquiry + 8); finish_interface (handle); return 0; } inquiry[36] = 0; if (verbose > 2) printf (" MA-1509 version %s\n", inquiry + 32); finish_interface (handle); return "MA-1509"; } /********** the lm983x section **********/ static int lm983x_wb (usb_dev_handle * handle, unsigned char reg, unsigned char val) { unsigned char buf[5]; int result; buf[0] = 0; buf[1] = reg; buf[2] = 0; buf[3] = 1; buf[4] = val; result = usb_bulk_write (handle, 3, (char *) buf, 5, TIMEOUT); if (result != 5) return 0; return 1; } static int lm983x_rb (usb_dev_handle * handle, unsigned char reg, unsigned char *val) { unsigned char buf[5]; int result; buf[0] = 1; buf[1] = reg; buf[2] = 0; buf[3] = 1; result = usb_bulk_write (handle, 3, (char *) buf, 4, TIMEOUT); if (result != 4) return 0; result = usb_bulk_read (handle, 2, (char *) val, 1, TIMEOUT); if (result != 1) return 0; return 1; } static char * check_merlin (struct usb_device *dev) { unsigned char val; int result; usb_dev_handle *handle; if (verbose > 2) printf (" checking for LM983[1,2,3] ...\n"); /* Check device descriptor */ if (((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) && (dev->descriptor.bDeviceClass != 0)) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != USB_CLASS_VENDOR_SPEC)) { if (verbose > 2) printf (" this is not a LM983x (bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if ((dev->descriptor.bcdUSB != 0x110) && (dev->descriptor.bcdUSB != 0x101) && (dev->descriptor.bcdUSB != 0x100)) { if (verbose > 2) printf (" this is not a LM983x (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a LM983x (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if ((dev->descriptor.bDeviceProtocol != 0) && (dev->descriptor.bDeviceProtocol != 0xff)) { if (verbose > 2) printf (" this is not a LM983x (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a LM983x (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x1) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x10)) { if (verbose > 2) printf (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x82) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) /* Currently disabled as we have some problems in detection here ! */ /*|| (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0) */ ) { if (verbose > 2) printf (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x40) /* Currently disabled as we have some problems in detection here ! */ /* || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0) */ ) { if (verbose > 2) printf (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } result = prepare_interface (dev, &handle); if (!result) return "LM983x?"; result = lm983x_wb (handle, 0x07, 0x00); if (1 == result) result = lm983x_wb (handle, 0x08, 0x02); if (1 == result) result = lm983x_rb (handle, 0x07, &val); if (1 == result) result = lm983x_rb (handle, 0x08, &val); if (1 == result) result = lm983x_rb (handle, 0x69, &val); if (0 == result) { if (verbose > 2) printf (" Couldn't access LM983x registers.\n"); finish_interface (handle); return 0; } finish_interface (handle); switch (val) { case 4: return "LM9832/3"; break; case 3: return "LM9831"; break; case 2: return "LM9830"; break; default: return "LM983x?"; break; } } /********** the gl646 section **********/ static int gl646_write_reg (usb_dev_handle * handle, unsigned char reg, unsigned char val) { int result; result = usb_control_msg (handle, 0x00, 0x00, 0x83, 0x00, (char *) ®, 0x01, TIMEOUT); if (result < 0) return 0; result = usb_control_msg (handle, 0x00, 0x00, 0x85, 0x00, (char *) &val, 0x01, TIMEOUT); if (result < 0) return 0; return 1; } static int gl646_read_reg (usb_dev_handle * handle, unsigned char reg, unsigned char *val) { int result; result = usb_control_msg (handle, 0x00, 0x00, 0x83, 0x00, (char *) ®, 0x01, TIMEOUT); if (result < 0) return 0; result = usb_control_msg (handle, 0x80, 0x00, 0x84, 0x00, (char *) val, 0x01, TIMEOUT); if (result < 0) return 0; return 1; } static char * check_gl646 (struct usb_device *dev) { unsigned char val; int result; usb_dev_handle *handle; if (verbose > 2) printf (" checking for GL646 ...\n"); /* Check device descriptor */ if ((dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != 0x10)) { if (verbose > 2) printf (" this is not a GL646 (bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a GL646 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a GL646 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0) { if (verbose > 2) printf (" this is not a GL646 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a GL646 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x0)) { if (verbose > 2) printf (" this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0)) { if (verbose > 2) printf (" this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x1) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 8)) { if (verbose > 2) printf (" this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } result = prepare_interface (dev, &handle); if (!result) return "GL646?"; result = gl646_write_reg (handle, 0x38, 0x15); if (!result) { if (verbose > 2) printf (" this is not a GL646 (writing register failed)\n"); finish_interface (handle); return 0; } result = gl646_read_reg (handle, 0x4e, &val); if (!result) { if (verbose > 2) printf (" this is not a GL646 (reading register failed)\n"); finish_interface (handle); return 0; } if (val != 0x15) { if (verbose > 2) printf (" this is not a GL646 (reg 0x4e != reg 0x38)\n"); finish_interface (handle); return 0; } finish_interface (handle); return "GL646"; } /* Same as check_gl646, except that sanity checks are different. */ static char * check_gl646_hp (struct usb_device *dev) { unsigned char val; int result; usb_dev_handle *handle; if (verbose > 2) printf (" checking for GL646_HP ...\n"); /* Check device descriptor */ if ((dev->descriptor.bDeviceClass != 0xff) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != 0xff)) { if (verbose > 2) printf (" this is not a GL646_HP (bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a GL646_HP (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a GL646_HP (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a GL646_HP (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a GL646_HP (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x0)) { if (verbose > 2) printf (" this is not a GL646_HP (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0)) { if (verbose > 2) printf (" this is not a GL646_HP (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x1) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 8)) { if (verbose > 2) printf (" this is not a GL646_HP (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } result = prepare_interface (dev, &handle); if (!result) return "GL646_HP?"; result = gl646_write_reg (handle, 0x38, 0x15); if (!result) { if (verbose > 2) printf (" this is not a GL646_HP (writing register failed)\n"); finish_interface (handle); return 0; } result = gl646_read_reg (handle, 0x4e, &val); if (!result) { if (verbose > 2) printf (" this is not a GL646_HP (reading register failed)\n"); finish_interface (handle); return 0; } if (val != 0x15) { if (verbose > 2) printf (" this is not a GL646_HP (reg 0x4e != reg 0x38)\n"); finish_interface (handle); return 0; } finish_interface (handle); return "GL646_HP"; } /* check for the combination of gl660 and gl646 */ static char * check_gl660_gl646 (struct usb_device *dev) { unsigned char val; int result; usb_dev_handle *handle; if (verbose > 2) printf (" checking for GL660+GL646 ...\n"); /* Check device descriptor */ if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != USB_CLASS_PER_INTERFACE)) { if (verbose > 2) printf (" this is not a GL660+GL646 (bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->descriptor.bcdUSB != 0x200) { if (verbose > 2) printf (" this is not a GL660+GL646 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a GL660+GL646 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a GL660+GL646 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a GL660+GL646 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || ((dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) && (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x200)) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x0)) { if (verbose > 2) printf (" this is not a GL660+GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || ((dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) && (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x200)) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0)) { if (verbose > 2) printf (" this is not a GL660+GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || ((dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x1) && (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x200)) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 8)) { if (verbose > 2) printf (" this is not a GL660+GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } result = prepare_interface (dev, &handle); if (!result) return "GL660+GL646?"; result = gl646_write_reg (handle, 0x38, 0x15); if (!result) { if (verbose > 2) printf (" this is not a GL660+GL646 (writing register failed)\n"); finish_interface (handle); return 0; } result = gl646_read_reg (handle, 0x4e, &val); if (!result) { if (verbose > 2) printf (" this is not a GL660+GL646 (reading register failed)\n"); finish_interface (handle); return 0; } if (val != 0x15) { if (verbose > 2) printf (" this is not a GL660+GL646 (reg 0x4e != reg 0x38)\n"); finish_interface (handle); return 0; } finish_interface (handle); return "GL660+GL646"; } /********** the gl841 section **********/ /* the various incarnations could be distinguished by the * bcdDevice entry: * 0x701 --> GL124 * 0x700 --> ? * 0x605 --> GL845 * 0x603 --> GL847 * 0x601 --> GL846 * 0x500 --> GL843 * 0x300 --> GL842 (perhaps only >= 0x303 ?) * 0x200 --> GL841 */ static char * check_gl841 (struct usb_device *dev) { unsigned char val; int result; usb_dev_handle *handle; if (verbose > 2) printf (" checking for GL84x ...\n"); /* Check device descriptor */ if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != USB_CLASS_VENDOR_SPEC)) { if (verbose > 2) printf (" this is not a GL84x (bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->descriptor.bcdUSB != 0x200) { if (verbose > 2) printf (" this is not a GL84x (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a GL84x (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a GL84x (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a GL84x (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || ((dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) && (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x200)) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x0)) { if (verbose > 2) printf (" this is not a GL84x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || ((dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) && (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x200)) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0)) { if (verbose > 2) printf (" this is not a GL84x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x1) || ((dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 8) && (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 16))) { if (verbose > 2) printf (" this is not a GL84x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } result = prepare_interface (dev, &handle); if (!result) { if (dev->descriptor.bcdDevice == 0x702) return "GL124?"; if (dev->descriptor.bcdDevice == 0x701) return "GL124?"; if (dev->descriptor.bcdDevice >= 0x700) return "GL848+?"; if (dev->descriptor.bcdDevice >= 0x603) return "GL847?"; if (dev->descriptor.bcdDevice >= 0x600) return "GL846?"; if (dev->descriptor.bcdDevice >= 0x500) return "GL845?"; if (dev->descriptor.bcdDevice >= 0x400) return "GL843?"; if (dev->descriptor.bcdDevice >= 0x300) return "GL842?"; else return "GL841?"; } result = gl646_write_reg (handle, 0x38, 0x15); if (!result) { if (verbose > 2) printf (" this is not a GL84x (writing register failed)\n"); finish_interface (handle); return 0; } result = gl646_read_reg (handle, 0x38, &val); if (!result) { if (verbose > 2) printf (" this is not a GL84x (reading register failed)\n"); finish_interface (handle); return 0; } if (val != 0x15) { if (verbose > 2) printf (" this is not a GL84x (reg 0x38 != 0x15)\n"); finish_interface (handle); return 0; } finish_interface (handle); if (dev->descriptor.bcdDevice == 0x702) return "GL128"; if (dev->descriptor.bcdDevice == 0x701) return "GL124"; if (dev->descriptor.bcdDevice >= 0x700) return "GL848+"; if (dev->descriptor.bcdDevice >= 0x605) return "GL845"; if (dev->descriptor.bcdDevice >= 0x603) return "GL847"; if (dev->descriptor.bcdDevice >= 0x600) return "GL846"; if (dev->descriptor.bcdDevice >= 0x500) return "GL843"; if (dev->descriptor.bcdDevice >= 0x300) return "GL842"; return "GL841"; } /********** the icm532b section version 0.2 **********/ /* no write and read test registers yet */ static char * check_icm532b (struct usb_device *dev) { int result; usb_dev_handle *handle; if (verbose > 2) printf (" checking for ICM532B ...\n"); /* Check device descriptor */ if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || (dev->config[0].interface[0].altsetting[0].bInterfaceClass != 0xff)) { if (verbose > 2) printf (" this is not a ICM532B (check 1, bDeviceClass = %d, bInterfaceClass = %d)\n", dev->descriptor.bDeviceClass, dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a ICM532B (check 2, bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a ICM532B (check 3, bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a ICM532B (check 4, bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 0x01) { if (verbose > 2) printf (" this is not a ICM532B (check 5, bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } /* Check bEndpointAddress */ if (dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) { if (verbose > 2) printf (" this is not a ICM532B (check 6, bEndpointAddress = %d)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress); return 0; } /* Check bmAttributes */ if (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x01) { if (verbose > 2) printf (" this is not a ICM532B (check 7, bEndpointAddress = %d)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes); return 0; } if ((dev->config[0].interface[0].altsetting[0].bAlternateSetting != 0x00) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x00)) { if (verbose > 2) printf (" this is not a ICM532B (check 8, bAlternateSetting = 0x%x, wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[0].bAlternateSetting, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[1].bAlternateSetting != 0x01) || (dev->config[0].interface[0].altsetting[1].endpoint[0]. wMaxPacketSize != 0x100)) { if (verbose > 2) printf (" this is not a ICM532B (check 9, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[1].bAlternateSetting, dev->config[0].interface[0].altsetting[1].endpoint[0]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[2].bAlternateSetting != 0x02) || (dev->config[0].interface[0].altsetting[2].endpoint[0]. wMaxPacketSize != 0x180)) { if (verbose > 2) printf (" this is not a ICM532B (check 10, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[2].bAlternateSetting, dev->config[0].interface[0].altsetting[2].endpoint[0]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[3].bAlternateSetting != 0x03) || (dev->config[0].interface[0].altsetting[3].endpoint[0]. wMaxPacketSize != 0x200)) { if (verbose > 2) printf (" this is not a ICM532B (check 11, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[3].bAlternateSetting, dev->config[0].interface[0].altsetting[3].endpoint[0]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[4].bAlternateSetting != 0x04) || (dev->config[0].interface[0].altsetting[4].endpoint[0]. wMaxPacketSize != 0x280)) { if (verbose > 2) printf (" this is not a ICM532B (check 12, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[4].bAlternateSetting, dev->config[0].interface[0].altsetting[4].endpoint[0]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[5].bAlternateSetting != 0x05) || (dev->config[0].interface[0].altsetting[5].endpoint[0]. wMaxPacketSize != 0x300)) { if (verbose > 2) printf (" this is not a ICM532B (check 13, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[5].bAlternateSetting, dev->config[0].interface[0].altsetting[5].endpoint[0]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[6].bAlternateSetting != 0x06) || (dev->config[0].interface[0].altsetting[6].endpoint[0]. wMaxPacketSize != 0x380)) { if (verbose > 2) printf (" this is not a ICM532B (check 14, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[6].bAlternateSetting, dev->config[0].interface[0].altsetting[6].endpoint[0]. wMaxPacketSize); return 0; } if ((dev->config[0].interface[0].altsetting[7].bAlternateSetting != 0x07) || (dev->config[0].interface[0].altsetting[7].endpoint[0]. wMaxPacketSize != 0x3ff)) { if (verbose > 2) printf (" this is not a ICM532B (check 15, bAlternatesetting = 0x%x, wMaxPacketSize = 0x%x)\n", dev->config[0].interface[0].altsetting[7].bAlternateSetting, dev->config[0].interface[0].altsetting[7].endpoint[0]. wMaxPacketSize); return 0; } result = prepare_interface (dev, &handle); if (!result) return "ICM532B?"; finish_interface (handle); return "ICM532B"; } /* ====================================== end of icm532b ==================*/ /* Check for the combination of a PowerVision PV8630 (USB->parport bridge) and National Semiconductor LM9830 */ static char * check_pv8630_lm9830 (struct usb_device *dev) { usb_dev_handle *handle; int result; char data; if (verbose > 2) printf (" checking for PV8630/LM9830 ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != USB_CLASS_PER_INTERFACE) { if (verbose > 2) printf (" this is not a PV8630/LM9830 (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x100) { if (verbose > 2) printf (" this is not a PV8630/LM9830 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a PV8630/LM9830 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0x00) { if (verbose > 2) printf (" this is not a PV8630/LM9830 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a PV8630/LM9830 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } /* Endpoint 0 */ if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a PV8630/LM9830 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } /* Endpoint 1 */ if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x82) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a PV8630/LM9830 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } /* Endpoint 2 */ if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0x01)) { if (verbose > 2) printf (" this is not a PV8630/LM9830 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } /* Now we write/read a register (red offset) */ result = prepare_interface (dev, &handle); if (!result) return "PV8630/LM9830?"; result = usb_control_msg (handle, 0x40, 0x01, 0x38, 0x01, NULL, 0, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't send write register number (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } result = usb_control_msg (handle, 0x40, 0x01, 0x0f, 0x00, NULL, 0, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't send register data (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } result = usb_control_msg (handle, 0x40, 0x01, 0x38, 0x01, NULL, 0, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't send read register number (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } result = usb_control_msg (handle, 0xc0, 0x00, 0, 0x00, &data, 1, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't read register data (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } if (data != 0x0f) { if (verbose > 2) printf (" Data read != data written (%d/%d)\n", data, 0x0f); finish_interface (handle); return 0; } finish_interface (handle); return "PV8630/LM9830"; } /* Check for Toshiba M011 */ static char * check_m011 (struct usb_device *dev) { usb_dev_handle *handle; int result; char data; if (verbose > 2) printf (" checking for M011 ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { if (verbose > 2) printf (" this is not a M011 (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x100) { if (verbose > 2) printf (" this is not a M011 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != USB_CLASS_VENDOR_SPEC) { if (verbose > 2) printf (" this is not a M011 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != USB_CLASS_VENDOR_SPEC) { if (verbose > 2) printf (" this is not a M011 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 1) { if (verbose > 2) printf (" this is not a M011 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } /* Endpoint 0 */ if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x82) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a M011 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } /* Now we write/read a register (red offset) */ result = prepare_interface (dev, &handle); if (!result) return "M011?"; data = 0x63; result = usb_control_msg (handle, 0x40, 0x08, 0x34, 0x00, &data, 1, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't write register (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } data = 0; result = usb_control_msg (handle, 0xc0, 0x00, 0x34, 0x00, &data, 1, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't read register (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } if (data != 0x63) { if (verbose > 2) printf (" Data read != data written (%d/%d)\n", data, 0x63); finish_interface (handle); return 0; } finish_interface (handle); return "M011"; } /* Check for Realtek rts88xx */ static int rts88xx_read_reg (usb_dev_handle * handle, unsigned char *req, unsigned char *res, int size) { int result; result = usb_bulk_write (handle, 0x02, (char *)req, 0x04, TIMEOUT); if (result < 0) return 0; result = usb_bulk_read (handle, 0x81, (char *)res, size, TIMEOUT); if (result < 0) return 0; return 1; } static char * check_rts8858c (struct usb_device *dev) { unsigned char req[4]; unsigned char res[10]; usb_dev_handle *handle; int result; if (verbose > 2) printf (" checking for rts8858c ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != 0) { if (verbose > 2) printf (" this is not a rts8858c (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a rts8858c (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0) { if (verbose > 2) printf (" this is not a rts8858c (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0) { if (verbose > 2) printf (" this is not a rts8858c (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a rts8858c (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a rts8858c (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x08) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a rts8858c (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0xFA)) { if (verbose > 2) printf (" this is not a rts8858c (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } /* Now we read 10 registers */ result = prepare_interface (dev, &handle); if (!result) return "rts8858c?"; memset (req, 0, 4); req[0] = 0x80; /* get registers 0x12-0x1c */ req[1] = 0x12; req[2] = 0x00; req[3] = 0x0a; result = rts88xx_read_reg(handle,req,res,req[3]); if (result <= 0) { if (verbose > 2) printf (" Couldn't read registers\n"); finish_interface (handle); return 0; } if (res[1] != 0x03 || res[2] != 0x00) { if (verbose > 2) printf (" Unexpected result from register reading (0x%0x/0x%0x)\n", res[1], res[2]); finish_interface (handle); return 0; } finish_interface (handle); return "rts8858c"; } /* end of rts8858 detection */ static char * check_rts88x1 (struct usb_device *dev) { unsigned char req[4]; unsigned char res[243]; usb_dev_handle *handle; int result; if (verbose > 2) printf (" checking for rts8801/rts8891 ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != 0) { if (verbose > 2) printf (" this is not a rts8801/rts8891 (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a rts8801/rts8891 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0) { if (verbose > 2) printf (" this is not a rts8801/rts8891 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0) { if (verbose > 2) printf (" this is not a rts8801/rts8891 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a rts8801/rts8891 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a rts8801/rts8891 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x08) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a rts8801/rts8891 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0xFA)) { if (verbose > 2) printf (" this is not a rts8801/rts8891 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } /* Now we read 10 registers */ result = prepare_interface (dev, &handle); if (!result) return "rts8801/rts8891?"; memset (req, 0, 4); req[0] = 0x80; /* get registers 0x00-0xF2 */ req[1] = 0x00; req[2] = 0x00; req[3] = 0xf3; result = rts88xx_read_reg(handle,req,res,req[3]); if (result <= 0) { if (verbose > 2) printf (" Couldn't read registers\n"); finish_interface (handle); return 0; } /* test CCD and link registers */ if (res[0xb0] != 0x80 || ((res[0] & 0x0f)!=0x05)) { if (verbose > 2) printf (" Unexpected result from register reading (0x%0x/0x%0x)\n", res[0xb0], res[2]); finish_interface (handle); return 0; } finish_interface (handle); return "rts8801/rts8891"; } /* end of rts8801/rts8891 detection */ /* Check for Service & Quality SQ113 */ static char * check_sq113 (struct usb_device *dev) { usb_dev_handle *handle; int result; unsigned char data; unsigned char buffer[4]; if (verbose > 2) printf (" checking for SQ113 ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != 0) { if (verbose > 2) printf (" this is not a SQ113 (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x200) { if (verbose > 2) printf (" this is not a SQ113 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0) { if (verbose > 2) printf (" this is not a SQ113 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0) { if (verbose > 2) printf (" this is not a SQ113 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check interface */ if (dev->config[0].interface[0].altsetting[0].bInterfaceClass != 255) { if (verbose > 2) printf (" this is not a SQ113 (bInterfaceClass = %d)\n", dev->config[0].interface[0].altsetting[0].bInterfaceClass); return 0; } if (dev->config[0].interface[0].altsetting[0].bInterfaceSubClass != 255) { if (verbose > 2) printf (" this is not a SQ113 (bInterfaceSubClass = %d)\n", dev->config[0].interface[0].altsetting[0].bInterfaceSubClass); return 0; } if (dev->config[0].interface[0].altsetting[0].bInterfaceProtocol != 255) { if (verbose > 2) printf (" this is not a SQ113 (bInterfaceProtocol = %d)\n", dev->config[0].interface[0].altsetting[0].bInterfaceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a SQ113 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } /* Endpoint 0 */ if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || ((dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x40) && (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x200)) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a SQ113 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } /* Endpoint 1 */ if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x82) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || ((dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x40) && (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x200)) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a SQ113 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } /* Endpoint 2 */ if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x1) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0x03)) { if (verbose > 2) printf (" this is not a SQ113 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } /* Now we read the status register */ result = prepare_interface (dev, &handle); if (!result) return "SQ113?"; buffer [0] = 0x5f; buffer [1] = 0x00; buffer [2] = 0x5f; buffer [3] = 0x00; result = usb_control_msg (handle, 0x40, 0x01, 0xb0, 0, (char *) buffer, 4, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't set bank (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } data = 0x00; buffer [0] = 0x8b; buffer [1] = data; buffer [2] = 0x8b; buffer [3] = data; result = usb_control_msg (handle, 0x40, 0x01, 0xb0, 0, (char *) buffer, 4, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't write register (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } buffer [0] = 0x8b; buffer [1] = 0x8b; buffer [2] = 0x8b; buffer [3] = 0x8b; result = usb_control_msg (handle, 0x40, 0x01, 0x04, 0x8b, (char *) buffer, 4, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't set read register address (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } result = usb_control_msg (handle, 0xc0, 0x01, 0x07, 0, (char *) buffer, 4, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't read register (%s)\n", usb_strerror ()); finish_interface (handle); return 0; } if ((buffer[0] & 0x10) != 0x10) { if (verbose > 2) printf (" Sensor not home? (0x%02x)\n", buffer[0]); finish_interface (handle); return 0; } finish_interface (handle); return "SQ113"; } /* Check for Realtek RTS8822 chipset*/ static char * check_rts8822 (struct usb_device *dev) { char data[2]; usb_dev_handle *handle; int result; if (verbose > 2) printf (" checking for RTS8822 ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != 0) { if (verbose > 2) printf (" this is not a RTS8822 (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if ((dev->descriptor.bcdUSB != 0x200)&&(dev->descriptor.bcdUSB != 0x110)) { if (verbose > 2) printf (" this is not a RTS8822 (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0) { if (verbose > 2) printf (" this is not a RTS8822 (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0) { if (verbose > 2) printf (" this is not a RTS8822 (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a RTS8822 (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x200) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a RTS8822 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x200) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a RTS8822 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0x0c)) { if (verbose > 2) printf (" this is not a RTS8822 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } /* Now we read 1 register */ result = prepare_interface (dev, &handle); if (!result) return "RTS8822?"; memset (data, 0, 2); result = usb_control_msg(handle, 0xc0, 0x04, 0xfe11, 0x100, data, 0x02, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send read control message (%s)\n", strerror (errno)); finish_interface (handle); return 0; } if ((data[0] == 0)&&(data[1] == 0)) { if (verbose > 2) printf (" Unexpected result from register 0xfe11 : 0x%0x%0x\n", data[1], data[0]); finish_interface (handle); return 0; } finish_interface (handle); return "RTS8822"; } /* end of RTS8822 detection */ /* Check for Silitek chipset found in HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 scanners */ static char * check_hp5590 (struct usb_device *dev) { usb_dev_handle *handle; int result; uint8_t status; struct usb_ctrl_setup ctrl; uint8_t data[0x32]; uint8_t ack; uint8_t *ptr; int next_packet_size; unsigned int len; #define HP5590_NAMES "HP4500C/4570C/5500C/5550C/5590/7650" if (verbose > 2) printf (" checking for " HP5590_NAMES " chipset ...\n"); /* Check device descriptor */ if (dev->descriptor.bDeviceClass != 0xff) { if (verbose > 2) printf (" this is not a " HP5590_NAMES " chipset (bDeviceClass = %d)\n", dev->descriptor.bDeviceClass); return 0; } if (dev->descriptor.bcdUSB != 0x200) { if (verbose > 2) printf (" this is not a " HP5590_NAMES " chipset (bcdUSB = 0x%x)\n", dev->descriptor.bcdUSB); return 0; } if (dev->descriptor.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a " HP5590_NAMES " chipset (bDeviceSubClass = 0x%x)\n", dev->descriptor.bDeviceSubClass); return 0; } if (dev->descriptor.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a " HP5590_NAMES " chipset (bDeviceProtocol = 0x%x)\n", dev->descriptor.bDeviceProtocol); return 0; } /* Check endpoints */ if (dev->config[0].interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a " HP5590_NAMES " chipset (bNumEndpoints = %d)\n", dev->config[0].interface[0].altsetting[0].bNumEndpoints); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress != 0x81) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize != 0x200) || (dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a " HP5590_NAMES " chipset (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[0]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[0].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[0]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. bmAttributes != 0x02) || (dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize != 0x200) || (dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a " HP5590_NAMES " chipset (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[1]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[1].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[1]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress != 0x83) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. bmAttributes != 0x03) || (dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize != 0x01) || (dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval != 0x08)) { if (verbose > 2) printf (" this is not a " HP5590_NAMES " chipset (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", dev->config[0].interface[0].altsetting[0].endpoint[2]. bEndpointAddress, dev->config[0].interface[0].altsetting[0].endpoint[2].bmAttributes, dev->config[0].interface[0].altsetting[0].endpoint[2]. wMaxPacketSize, dev->config[0].interface[0].altsetting[0].endpoint[2].bInterval); return 0; } result = prepare_interface (dev, &handle); if (!result) return NULL; /* USB-in-USB command URB - command 0x0012 (init scanner), returns 0x32 bytes */ memset (&ctrl, 0, sizeof(ctrl)); ctrl.bRequestType = 0xc0; ctrl.bRequest = 0x04; ctrl.wValue = 0x1200; ctrl.wIndex = 0x00; ctrl.wLength = sizeof(data); result = usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR, 0x04, 0x8f, 0x00, (char *) &ctrl, sizeof (ctrl), TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't send send USB-in-USB command (%s)\n", strerror (errno)); return NULL; } /* Get confirmation for USB-in-USB command */ result = usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR, 0x0c, 0x8e, 0x20, (char *) &status, sizeof(status), TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't read USB-in-USB confirmation (%s)\n", strerror (errno)); finish_interface (handle); return NULL; } /* Check the confirmation received */ if (status != 0x01) { if (verbose > 2) printf (" Didn't get correct confirmation for USB-in-USB command " "(needed: 0x01, got: 0x%02x\n", status); finish_interface (handle); return NULL; } /* Read data in 8 byte packets */ ptr = data; len = sizeof(data); while (len) { next_packet_size = 8; if (len < 8) next_packet_size = len; /* Read data packet */ result = usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR, 0x04, 0x90, 0x00, (char *) ptr, next_packet_size, TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't read USB-in-USB data (%s)\n", strerror (errno)); finish_interface (handle); return NULL; } /* Check if all of the requested data was received */ if (result != next_packet_size) { if (verbose > 2) printf (" Incomplete USB-in-USB data received (needed: %u, got: %u)\n", next_packet_size, result); finish_interface (handle); return NULL; } ptr += next_packet_size; len -= next_packet_size; } /* Acknowledge the whole received data */ ack = 0; result = usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR, 0x0c, 0x8f, 0x00, (char *) &ack, sizeof(ack), TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't send USB-in-USB data confirmation (%s)\n", strerror (errno)); finish_interface (handle); return NULL; } /* Get confirmation for acknowledge */ result = usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR, 0x0c, 0x8e, 0x20, (char *) &status, sizeof(status), TIMEOUT); if (result < 0) { if (verbose > 2) printf (" Couldn't read USB-in-USB confirmation for data confirmation (%s)\n", strerror (errno)); finish_interface (handle); return NULL; } /* Check the confirmation received */ if (status != 0x01) { if (verbose > 2) printf (" Didn't get correct confirmation for USB-in-USB command " "(needed: 0x01, got: 0x%02x\n", status); finish_interface (handle); return NULL; } /* Check vendor ID */ if (memcmp (data+1, "SILITEK", 7) != 0) { if (verbose > 2) printf (" Incorrect product ID received\n"); finish_interface (handle); return NULL; } finish_interface (handle); return HP5590_NAMES; } char * check_usb_chip (struct usb_device *dev, int verbosity, SANE_Bool from_file) { char *chip_name = 0; verbose = verbosity; no_chipset_access = from_file; if (verbose > 2) printf ("\n\n"); chip_name = check_gt6801 (dev); if (!chip_name) chip_name = check_gt6816 (dev); if (!chip_name) chip_name = check_gt8911 (dev); if (!chip_name) chip_name = check_ma1017 (dev); if (!chip_name) chip_name = check_ma1015 (dev); if (!chip_name) chip_name = check_ma1509 (dev); if (!chip_name) chip_name = check_merlin (dev); if (!chip_name) chip_name = check_gl646 (dev); if (!chip_name) chip_name = check_gl646_hp (dev); if (!chip_name) chip_name = check_gl660_gl646 (dev); if (!chip_name) chip_name = check_gl841 (dev); if (!chip_name) chip_name = check_icm532b (dev); if (!chip_name) chip_name = check_pv8630_lm9830 (dev); if (!chip_name) chip_name = check_m011 (dev); if (!chip_name) chip_name = check_rts8822 (dev); if (!chip_name) chip_name = check_rts8858c (dev); if (!chip_name) chip_name = check_sq113 (dev); if (!chip_name) chip_name = check_hp5590 (dev); if (!chip_name) chip_name = check_rts88x1 (dev); if (verbose > 2) { if (chip_name) printf ("\n\n", chip_name, PACKAGE_STRING); else printf ("\n\n", PACKAGE_STRING); } return chip_name; } #endif /* HAVE_LIBUSB_LEGACY */ #ifdef HAVE_LIBUSB #include #include "../include/sane/sane.h" #include #include #include #include "../include/_stdint.h" #define TIMEOUT 1000 /** @brief detect used chip * * Try to detect the chip used by a device that looks like a scanner by * trying some basic operation like reading/writing registers. * @param dev libusb_device to probe * @param verbosity level of messages verbosity * @param from_file SANE_True if data read from file * @return a string containing the name of the detected scanner chip */ char *check_usb_chip (int verbosity, struct libusb_device_descriptor desc, libusb_device_handle * hdl, struct libusb_config_descriptor *config0); static int verbose = 0; static int genesys_write_reg (libusb_device_handle * handle, unsigned char reg, unsigned char val) { int result; unsigned char data[2]; data[0] = reg; data[1] = val; result = libusb_control_transfer (handle, 0x40, 0x04, 0x83, 0x00, data, 0x02, TIMEOUT); if (result < 0) return 0; return 1; } static int genesys_read_reg (libusb_device_handle * handle, unsigned char reg, unsigned char *val) { int result; result = libusb_control_transfer (handle, 0x40, 0x0c, 0x83, 0x00, ®, 0x01, TIMEOUT); if (result < 0) return 0; result = libusb_control_transfer (handle, 0xc0, 0x0c, 0x84, 0x00, val, 0x01, TIMEOUT); if (result < 0) return 0; return 1; } /** @brief check for genesys GL646 chips * * @param dev libusb device * @param hdl libusb opened handle * @param config0 configuration 0 from get config _descriptor * @return a string with ASIC name, or NULL if not recognized */ static char * check_gl646 (libusb_device_handle * handle, struct libusb_device_descriptor desc, struct libusb_config_descriptor *config0) { unsigned char val; int result; if (desc.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a GL646 (bcdUSB = 0x%x)\n", desc.bcdUSB); return 0; } if (desc.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a GL646 (bDeviceSubClass = 0x%x)\n", desc.bDeviceSubClass); return 0; } if (desc.bDeviceProtocol != 0) { if (verbose > 2) printf (" this is not a GL646 (bDeviceProtocol = 0x%x)\n", desc.bDeviceProtocol); return 0; } /* Check endpoints */ if (config0->interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a GL646 (bNumEndpoints = %d)\n", config0->interface[0].altsetting[0].bNumEndpoints); return 0; } if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != 0x81) || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != 0x02) || (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x40) || (config0->interface[0].altsetting[0].endpoint[0].bInterval != 0x0)) { if (verbose > 2) printf (" this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[0].bmAttributes, config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress != 0x02) || (config0->interface[0].altsetting[0].endpoint[1].bmAttributes != 0x02) || (config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != 0x40) || (config0->interface[0].altsetting[0].endpoint[1].bInterval != 0)) { if (verbose > 2) printf (" this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[1].bmAttributes, config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress != 0x83) || (config0->interface[0].altsetting[0].endpoint[2].bmAttributes != 0x03) || (config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize != 0x1) || (config0->interface[0].altsetting[0].endpoint[2].bInterval != 8)) { if (verbose > 2) printf (" this is not a GL646 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[2].bmAttributes, config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[2].bInterval); return 0; } result = genesys_write_reg (handle, 0x38, 0x15); if (!result) { if (verbose > 2) printf (" this is not a GL646 (writing register failed)\n"); return 0; } result = genesys_read_reg (handle, 0x4e, &val); if (!result) { if (verbose > 2) printf (" this is not a GL646 (reading register failed)\n"); return 0; } if (val != 0x15) { if (verbose > 2) printf (" this is not a GL646 (reg 0x4e != reg 0x38)\n"); return 0; } return "GL646"; } /** @brief check for gt6801 chip * * @param dev libusb device * @param hdl libusb opened handle * @param config0 configuration 0 from get config _descriptor * @return a string with ASIC name, or NULL if not recognized */ static char * check_gt6801 (libusb_device_handle * handle, struct libusb_device_descriptor desc, struct libusb_config_descriptor *config0) { unsigned char req[64]; int result; if (verbose > 2) printf (" checking for GT-6801 ...\n"); /* Check device descriptor */ if (desc.bDeviceClass != LIBUSB_CLASS_VENDOR_SPEC) { if (verbose > 2) printf (" this is not a GT-6801 (bDeviceClass = %d)\n", desc.bDeviceClass); return 0; } if (desc.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a GT-6801 (bcdUSB = 0x%x)\n", desc.bcdUSB); return 0; } if (desc.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a GT-6801 (bDeviceSubClass = 0x%x)\n", desc.bDeviceSubClass); return 0; } if (desc.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a GT-6801 (bDeviceProtocol = 0x%x)\n", desc.bDeviceProtocol); return 0; } /* Check endpoints */ if (config0->interface[0].altsetting[0].bNumEndpoints != 1) { if (verbose > 2) printf (" this is not a GT-6801 (bNumEndpoints = %d)\n", config0->interface[0].altsetting[0].bNumEndpoints); return 0; } if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != 0x81) || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != 0x02) || (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x40) || (config0->interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-6801 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[0].bmAttributes, config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[0].bInterval); return 0; } /* Now we send a control message */ memset (req, 0, 64); req[0] = 0x2e; /* get identification information */ req[1] = 0x01; result = libusb_control_transfer (handle, 0x40, 0x01, 0x2010, 0x3f40, req, 64, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send write control message (%s)\n", strerror (errno)); return NULL; } result = libusb_control_transfer (handle, 0xc0, 0x01, 0x2011, 0x3f00, req, 64, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send read control message (%s)\n", strerror (errno)); return NULL; } if (req[0] != 0 || (req[1] != 0x2e && req[1] != 0)) { if (verbose > 2) printf (" Unexpected result from control message (%0x/%0x)\n", req[0], req[1]); return NULL; } return "GT-6801"; } /** @brief check for gt6816 chip * * @param dev libusb device * @param hdl libusb opened handle * @param config0 configuration 0 from get config _descriptor * @return a string with ASIC name, or NULL if not recognized */ static char * check_gt6816 (libusb_device_handle * handle, struct libusb_device_descriptor desc, struct libusb_config_descriptor *config0) { unsigned char req[64]; int result,i; if (verbose > 2) printf (" checking for GT-6816 ...\n"); /* Check device descriptor */ if ((desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) || (config0->interface[0].altsetting[0].bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)) { if (verbose > 2) printf (" this is not a GT-6816 (bDeviceClass = %d, bInterfaceClass = %d)\n", desc.bDeviceClass, config0->interface[0].altsetting[0].bInterfaceClass); return 0; } if (desc.bcdUSB != 0x110) { if (verbose > 2) printf (" this is not a GT-6816 (bcdUSB = 0x%x)\n", desc.bcdUSB); return 0; } if (desc.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a GT-6816 (bDeviceSubClass = 0x%x)\n", desc.bDeviceSubClass); return 0; } if (desc.bDeviceProtocol != 0x00) { if (verbose > 2) printf (" this is not a GT-6816 (bDeviceProtocol = 0x%x)\n", desc.bDeviceProtocol); return 0; } if (config0->bNumInterfaces != 0x01) { if (verbose > 2) printf (" this is not a GT-6816 (bNumInterfaces = 0x%x)\n", config0->bNumInterfaces); return 0; } /* Check endpoints */ if (config0->interface[0].altsetting[0].bNumEndpoints != 2) { if (verbose > 2) printf (" this is not a GT-6816 (bNumEndpoints = %d)\n", config0->interface[0].altsetting[0].bNumEndpoints); return 0; } if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != 0x81) || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != 0x02) || (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x40) || (config0->interface[0].altsetting[0].endpoint[0].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-6816 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[0].bmAttributes, config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress != 0x02) || (config0->interface[0].altsetting[0].endpoint[1].bmAttributes != 0x02) || (config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != 0x40) || (config0->interface[0].altsetting[0].endpoint[1].bInterval != 0x00)) { if (verbose > 2) printf (" this is not a GT-6816 (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[1].bmAttributes, config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[1].bInterval); return 0; } /* Now we send a control message */ memset (req, 0, 64); for (i = 0; i < 8; i++) { req[8 * i + 0] = 0x73; /* check firmware */ req[8 * i + 1] = 0x01; } result = libusb_control_transfer (handle, 0x40, 0x04, 0x2012, 0x3f40, req, 64, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send write control message (%s)\n", strerror (errno)); return NULL; } result = libusb_control_transfer (handle, 0xc0, 0x01, 0x2013, 0x3f00, req, 64, TIMEOUT); if (result <= 0) { /* Before firmware upload, 64 bytes are returned. Some libusb implementations/operating systems can't seem to cope with short packets. */ result = libusb_control_transfer (handle, 0xc0, 0x01, 0x2013, 0x3f00, req, 8, TIMEOUT); if (result <= 0) { if (verbose > 2) printf (" Couldn't send read control message (%s)\n", strerror (errno)); return NULL; } } if (req[0] != 0) { if (verbose > 2) printf (" Unexpected result from control message (%0x/%0x)\n", req[0], req[1]); return NULL; } return "GT-6816"; } /** @brief check for known genesys chip * * Try to check if the scanner use a known genesys ASIC. * The various incarnations could be distinguished by the * bcdDevice entry: * 0x701 --> GL124 * 0x700 --> ? * 0x605 --> GL845 * 0x603 --> GL847 * 0x601 --> GL846 * 0x500 --> GL843 * 0x300 --> GL842 (perhaps only >= 0x303 ?) * 0x200 --> GL841 * * @param dev libusb device * @param hdl libusb opened handle * @param config0 configuration 0 from get config _descriptor * @return a string with ASIC name, or NULL if not recognized */ static char * check_genesys (libusb_device_handle * handle, struct libusb_device_descriptor desc, struct libusb_config_descriptor *config0) { unsigned char val; int result; if (verbose > 2) printf (" checking for GLxxx ...\n"); /* Check GL646 device descriptor */ if ((desc.bDeviceClass == LIBUSB_CLASS_PER_INTERFACE) && (config0->interface[0].altsetting[0].bInterfaceClass == 0x10)) { return check_gl646 (handle, desc, config0); } if (verbose > 2) { printf (" this is not a GL646 (bDeviceClass = %d, bInterfaceClass = %d)\n", desc.bDeviceClass, config0->interface[0].altsetting[0].bInterfaceClass); } /* Check device desc */ if ((desc.bDeviceClass != LIBUSB_CLASS_VENDOR_SPEC) || (config0->interface[0].altsetting[0].bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)) { if (verbose > 2) printf (" this is not a GLxxx (bDeviceClass = %d, bInterfaceClass = %d)\n", desc.bDeviceClass, config0->interface[0].altsetting[0].bInterfaceClass); return NULL; } if (desc.bDeviceSubClass != 0xff) { if (verbose > 2) printf (" this is not a GLxxx (bDeviceSubClass = 0x%x)\n", desc.bDeviceSubClass); return NULL; } if (desc.bDeviceProtocol != 0xff) { if (verbose > 2) printf (" this is not a GLxxx (bDeviceProtocol = 0x%x)\n", desc.bDeviceProtocol); return NULL; } /* Check endpoints */ if (config0->interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a GLxxx (bNumEndpoints = %d)\n", config0->interface[0].altsetting[0].bNumEndpoints); return NULL; } if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != 0x81) || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != 0x02) || ((config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x40) && (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x200)) || (config0->interface[0].altsetting[0].endpoint[0].bInterval != 0x0)) { if (verbose > 2) printf (" this is not a GLxxx (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[0].bmAttributes, config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[0].bInterval); return NULL; } if ((config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress != 0x02) || (config0->interface[0].altsetting[0].endpoint[1].bmAttributes != 0x02) || ((config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != 0x40) && (config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != 0x200)) || (config0->interface[0].altsetting[0].endpoint[1].bInterval != 0)) { if (verbose > 2) printf (" this is not a GLxxx (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[1].bmAttributes, config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[1].bInterval); return NULL; } if ((config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress != 0x83) || (config0->interface[0].altsetting[0].endpoint[2].bmAttributes != 0x03) || (config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize != 0x1) || ((config0->interface[0].altsetting[0].endpoint[2].bInterval != 8) && (config0->interface[0].altsetting[0].endpoint[2].bInterval != 16))) { if (verbose > 2) printf (" this is not a GLxxx (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[2].bmAttributes, config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[2].bInterval); return NULL; } /* write then read a register using common read/write control message */ result = genesys_write_reg (handle, 0x38, 0x15); if (!result) { if (verbose > 2) printf (" this is not a GLxxx (writing register failed)\n"); return NULL; } result = genesys_read_reg (handle, 0x38, &val); if (!result) { if (verbose > 2) printf (" this is not a GLxxx (reading register failed)\n"); return NULL; } if (val != 0x15) { if (verbose > 2) printf (" this is not a GLxxx (reg 0x38 != 0x15)\n"); return NULL; } /* decide revision number based on bcdUsb heuristics */ if (desc.bcdDevice == 0x702) return "GL128"; if (desc.bcdDevice == 0x701) return "GL124"; if (desc.bcdDevice >= 0x700) return "GL848+"; if (desc.bcdDevice >= 0x605) return "GL845"; if (desc.bcdDevice >= 0x603) return "GL847"; if (desc.bcdDevice >= 0x600) return "GL846"; if (desc.bcdDevice >= 0x500) return "GL843"; if (desc.bcdDevice >= 0x300) return "GL842"; if (desc.bcdDevice > 0x101) return "GL841"; return "GL646_HP"; } /********** the lm983x section **********/ static int lm983x_wb (libusb_device_handle *handle, unsigned char reg, unsigned char val) { unsigned char buf[5]; int written; int result; buf[0] = 0; buf[1] = reg; buf[2] = 0; buf[3] = 1; buf[4] = val; result = libusb_bulk_transfer(handle, 0x03, buf, 5, &written, TIMEOUT); if (result < 0) return 0; if (written != 5) return 0; return 1; } static int lm983x_rb (libusb_device_handle *handle, unsigned char reg, unsigned char *val) { unsigned char buf[5]; int result; int tfx; buf[0] = 1; buf[1] = reg; buf[2] = 0; buf[3] = 1; result = libusb_bulk_transfer(handle, 0x03, buf, 4, &tfx, TIMEOUT); if (result < 0) return 0; if (tfx != 4) return 0; result = libusb_bulk_transfer(handle, 0x82, val, 1, &tfx, TIMEOUT); if (result < 0) return 0; if (tfx != 1) return 0; return 1; } /** @brief check for known LM983x chip (aka Merlin) * * Try to check if the scanner uses a LM983x ASIC. * * @param dev libusb device * @param hdl libusb opened handle * @param config0 configuration 0 from get config _descriptor * @return a string with ASIC name, or NULL if not recognized */ static char * check_merlin(libusb_device_handle * handle, struct libusb_device_descriptor desc, struct libusb_config_descriptor *config0) { unsigned char val; int result; if (verbose > 2) printf (" checking for LM983[1,2,3] ...\n"); /* Check device descriptor */ if (((desc.bDeviceClass != LIBUSB_CLASS_VENDOR_SPEC) && (desc.bDeviceClass != 0)) || (config0->interface[0].altsetting[0].bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)) { if (verbose > 2) printf (" this is not a LM983x (bDeviceClass = %d, bInterfaceClass = %d)\n", desc.bDeviceClass, config0->interface[0].altsetting[0].bInterfaceClass); return 0; } if ((desc.bcdUSB != 0x110) && (desc.bcdUSB != 0x101) && (desc.bcdUSB != 0x100)) { if (verbose > 2) printf (" this is not a LM983x (bcdUSB = 0x%x)\n", desc.bcdUSB); return 0; } if (desc.bDeviceSubClass != 0x00) { if (verbose > 2) printf (" this is not a LM983x (bDeviceSubClass = 0x%x)\n", desc.bDeviceSubClass); return 0; } if ((desc.bDeviceProtocol != 0) && (desc.bDeviceProtocol != 0xff)) { if (verbose > 2) printf (" this is not a LM983x (bDeviceProtocol = 0x%x)\n", desc.bDeviceProtocol); return 0; } /* Check endpoints */ if (config0->interface[0].altsetting[0].bNumEndpoints != 3) { if (verbose > 2) printf (" this is not a LM983x (bNumEndpoints = %d)\n", config0->interface[0].altsetting[0].bNumEndpoints); return 0; } if ((config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress != 0x81) || (config0->interface[0].altsetting[0].endpoint[0].bmAttributes != 0x03) || (config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize != 0x1) || (config0->interface[0].altsetting[0].endpoint[0].bInterval != 0x10)) { if (verbose > 2) printf (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[0].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[0].bmAttributes, config0->interface[0].altsetting[0].endpoint[0].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[0].bInterval); return 0; } if ((config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress != 0x82) || (config0->interface[0].altsetting[0].endpoint[1].bmAttributes != 0x02) || (config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize != 0x40) /* Currently disabled as we have some problems in detection here ! */ /*|| (config0->interface[0].altsetting[0].endpoint[1].bInterval != 0) */ ) { if (verbose > 2) printf (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[1].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[1].bmAttributes, config0->interface[0].altsetting[0].endpoint[1].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[1].bInterval); return 0; } if ((config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress != 0x03) || (config0->interface[0].altsetting[0].endpoint[2].bmAttributes != 0x02) || (config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize != 0x40) /* Currently disabled as we have some problems in detection here ! */ /* || (config0->interface[0].altsetting[0].endpoint[2].bInterval != 0) */ ) { if (verbose > 2) printf (" this is not a LM983x (bEndpointAddress = 0x%x, bmAttributes = 0x%x, " "wMaxPacketSize = 0x%x, bInterval = 0x%x)\n", config0->interface[0].altsetting[0].endpoint[2].bEndpointAddress, config0->interface[0].altsetting[0].endpoint[2].bmAttributes, config0->interface[0].altsetting[0].endpoint[2].wMaxPacketSize, config0->interface[0].altsetting[0].endpoint[2].bInterval); return 0; } result = lm983x_wb (handle, 0x07, 0x00); if (1 == result) result = lm983x_wb (handle, 0x08, 0x02); if (1 == result) result = lm983x_rb (handle, 0x07, &val); if (1 == result) result = lm983x_rb (handle, 0x08, &val); if (1 == result) result = lm983x_rb (handle, 0x69, &val); if (0 == result) { if (verbose > 2) printf (" Couldn't access LM983x registers.\n"); return 0; } switch (val) { case 4: return "LM9832/3"; break; case 3: return "LM9831"; break; case 2: return "LM9830"; break; default: return "LM983x?"; break; } } char * check_usb_chip (int verbosity, struct libusb_device_descriptor desc, libusb_device_handle * hdl, struct libusb_config_descriptor *config0) { char *chip_name = NULL; int ret; verbose = verbosity; if (verbose > 2) printf ("\n\n"); /* set config if needed */ if (desc.bNumConfigurations > 1) { ret = libusb_set_configuration (hdl, config0->bConfigurationValue); if (ret < 0) { if (verbose > 2) printf ("couldnt set device to configuration %d\n", config0->bConfigurationValue); return NULL; } } /* claim the interface (only interface 0 is currently handled */ ret = libusb_claim_interface (hdl, 0); if (ret < 0) { if (verbose > 2) printf ("could not claim USB device interface\n"); return NULL; } /* now USB is opened and set up, actual chip detection */ if (!chip_name) chip_name = check_merlin (hdl, desc, config0); if (!chip_name) chip_name = check_gt6801 (hdl, desc, config0); if (!chip_name) chip_name = check_gt6816 (hdl, desc, config0); if (!chip_name) chip_name = check_genesys (hdl, desc, config0); if (verbose > 2) { if (chip_name) printf ("\n\n", chip_name, PACKAGE_STRING); else printf ("\n\n", PACKAGE_STRING); } /* close USB device */ libusb_release_interface (hdl, 0); return chip_name; } #endif /* HAVE_LIBUSB */ sane-backends-1.0.27/tools/README0000664000175000017500000000562712775312262013263 000000000000002006-05-10 This directory contains various tools that may be useful: hotplug/: Linux hotplug script and an automatically generated config file (libsane.usermap) used to change the permissions on the libusb "device nodes" in /proc/bus/usb/ when a scanner is plugged in. For newer Linux kernels, you may need to use udev instead. Please read the README file in this directory for instructions. hotplug-ng/: Linux hotplug-ng script and an automatically generated config file (libsane.db) used to change the permissions on the libusb "device nodes" in /proc/bus/usb/ when a scanner is plugged in. For newer Linux kernels, you may need to use udev instead. Please read the README file in this directory for instructions. udev/: Contains a automatically generated udev rules file. udev now replaces hotplug and provides all the functionalities of hotplug. libusb 0.1.12 or newer is necessary. openbsd/: Contains example scripts for hotplugd(8) for USB scanners accessed via libusb. sane-find-scanner: Attempts to find a SCSI scanner attached to your system. Invoke with "sane-find-scanner -h" to get command-line syntax. More details can be found in the man page sane-find-scanner(1). xerox: A simple script to make photocopies ("xeroxing"). In the script, you may need to adjust the device name assigned to variable DEV and the resolution assigned to variable RES as well as the paper with and height (variables WIDTH and HEIGHT, respectively. mustek600iin-off: Allows you to turn off a Mustek 600 II N scanner. Use "make mustek600iin-off" to compile. umax_pp: Command line utility to scan on UMAX astra 1220P, 1600P and 2000P, without using the backend. So that scanner protocol can be tested directly. gamma4scanimage: Creates a gamma table in the format expected by scanimage. You can define a gamma value, shadow and highlight. Take a look at manual page gamma4scanimage for further information. RenSaneDlls.cmd: Convert backend-DLL-filenames according to 8.3 naming convention necessary for DLLs on OS/2. Maybe useful for SANE developers: sane-config: Show SANE version, linker flags etc. Might be useful for frontend developers. sane-desc: Generate SANE webpages (and ASCII lists) from backend .desc files. Run "sane-desc --help" for details. The default lists are generated in doc/Makefile. check-po.awk: Print untranslated and fuzzy messages and their line numbers in the source code and po file. Example: tools/check-po.awk po/de.po You may need to adjust the path of gawk in the first line of the script. Alternatively, run it via gawk's -f option, like so: gawk -f tools/check-po.awk po/de.po More documentation is in the script itself. sane-backends-1.0.27/tools/openbsd/0000775000175000017500000000000013110600532014063 500000000000000sane-backends-1.0.27/tools/openbsd/attach0000775000175000017500000000060212112021330015165 00000000000000#!/bin/sh DEVCLASS=$1 DEVNAME=$2 case $DEVCLASS in 0) # generic devices case "$DEVNAME" in ugen*) BUSNAME=`usbdevs -v -d | egrep "Controller|$DEVNAME\$" | grep -B 1 ugen0$ | head -n 1 | sed -e 's,Controller ,,' -e 's,:$,,' ` echo $BUSNAME > /var/run/${DEVNAME}.bus # probably our scanner chgrp usb /dev/"$DEVNAME".* chgrp usb /dev/"$BUSNAME" ;; esac ;; esac sane-backends-1.0.27/tools/openbsd/detach0000775000175000017500000000050712112021330015155 00000000000000#!/bin/sh DEVCLASS=$1 DEVNAME=$2 case $DEVCLASS in 0) # generic devices case "$DEVNAME" in ugen*) BUSNAME=`cat /var/run/${DEVNAME}.bus` rm -f /var/run/${DEVNAME}.bus # probably our scanner chgrp wheel /dev/"$DEVNAME".* if [ x$BUSNAME != x ] ; then chgrp wheel /dev/"$BUSNAME" fi ;; esac ;; esac sane-backends-1.0.27/tools/Makefile.in0000664000175000017500000007526413110564734014451 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = sane-find-scanner$(EXEEXT) gamma4scanimage$(EXEEXT) \ $(am__EXEEXT_1) noinst_PROGRAMS = sane-desc$(EXEEXT) $(am__EXEEXT_2) @INSTALL_UMAX_PP_TOOLS_TRUE@am__append_1 = umax_pp @INSTALL_UMAX_PP_TOOLS_FALSE@am__append_2 = umax_pp @have_usblib_TRUE@am__append_3 = check-usb-chip.c subdir = tools DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(srcdir)/sane-config.in \ $(srcdir)/sane-backends.pc.in $(top_srcdir)/depcomp README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = sane-config sane-backends.pc CONFIG_CLEAN_VPATH_FILES = @INSTALL_UMAX_PP_TOOLS_TRUE@am__EXEEXT_1 = umax_pp$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(pkgconfigdir)" @INSTALL_UMAX_PP_TOOLS_FALSE@am__EXEEXT_2 = umax_pp$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_gamma4scanimage_OBJECTS = gamma4scanimage.$(OBJEXT) gamma4scanimage_OBJECTS = $(am_gamma4scanimage_OBJECTS) am__DEPENDENCIES_1 = gamma4scanimage_DEPENDENCIES = $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_sane_desc_OBJECTS = sane-desc.$(OBJEXT) sane_desc_OBJECTS = $(am_sane_desc_OBJECTS) sane_desc_DEPENDENCIES = ../sanei/libsanei.la ../lib/liblib.la am__sane_find_scanner_SOURCES_DIST = sane-find-scanner.c \ check-usb-chip.c @have_usblib_TRUE@am__objects_1 = check-usb-chip.$(OBJEXT) am_sane_find_scanner_OBJECTS = sane-find-scanner.$(OBJEXT) \ $(am__objects_1) sane_find_scanner_OBJECTS = $(am_sane_find_scanner_OBJECTS) sane_find_scanner_DEPENDENCIES = ../sanei/libsanei.la ../lib/liblib.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) ../backend/sane_strstatus.lo am_umax_pp_OBJECTS = umax_pp.$(OBJEXT) umax_pp_OBJECTS = $(am_umax_pp_OBJECTS) umax_pp_DEPENDENCIES = ../sanei/libsanei.la ../lib/liblib.la \ $(am__DEPENDENCIES_1) ../backend/umax_pp_low.lo am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(bin_SCRIPTS) $(noinst_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gamma4scanimage_SOURCES) $(sane_desc_SOURCES) \ $(sane_find_scanner_SOURCES) $(umax_pp_SOURCES) DIST_SOURCES = $(gamma4scanimage_SOURCES) $(sane_desc_SOURCES) \ $(am__sane_find_scanner_SOURCES_DIST) $(umax_pp_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgconfig_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include $(USB_CFLAGS) AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @CROSS_COMPILING_FALSE@HOTPLUG = hal/libsane.fdi hotplug/libsane.usermap hotplug-ng/libsane.db \ @CROSS_COMPILING_FALSE@ udev/libsane.rules @CROSS_COMPILING_TRUE@HOTPLUG = @CROSS_COMPILING_FALSE@HOTPLUG_DIRS = hal hotplug hotplug-ng udev @CROSS_COMPILING_TRUE@HOTPLUG_DIRS = @CROSS_COMPILING_FALSE@HOTPLUG_DIR = dirs @CROSS_COMPILING_TRUE@HOTPLUG_DIR = bin_SCRIPTS = sane-config noinst_SCRIPTS = $(HOTPLUG) BUILT_SOURCES = $(HOTPLUG_DIR) CLEANFILES = $(bin_SCRIPTS) $(dist_noinst_SCRIPTS) EXTRA_DIST = check-po.awk libtool-get-dll-ext mustek600iin-off.c \ RenSaneDlls.cmd README xerox hotplug/README \ hotplug/libusbscanner hotplug-ng/README \ hotplug-ng/libsane.hotplug openbsd/attach openbsd/detach sane_find_scanner_SOURCES = sane-find-scanner.c $(am__append_3) sane_find_scanner_LDADD = ../sanei/libsanei.la ../lib/liblib.la \ $(USB_LIBS) $(IEEE1284_LIBS) $(SCSI_LIBS) \ ../backend/sane_strstatus.lo gamma4scanimage_SOURCES = gamma4scanimage.c gamma4scanimage_LDADD = $(MATH_LIB) umax_pp_SOURCES = umax_pp.c umax_pp_LDADD = ../sanei/libsanei.la ../lib/liblib.la $(MATH_LIB) \ ../backend/umax_pp_low.lo sane_desc_SOURCES = sane-desc.c sane_desc_LDADD = ../sanei/libsanei.la ../lib/liblib.la pkgconfigdir = @libdir@/pkgconfig pkgconfig_DATA = sane-backends.pc descriptions = ${top_srcdir}/doc/descriptions/*.desc ${top_srcdir}/doc/descriptions-external/*.desc all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tools/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): sane-config: $(top_builddir)/config.status $(srcdir)/sane-config.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ sane-backends.pc: $(top_builddir)/config.status $(srcdir)/sane-backends.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gamma4scanimage$(EXEEXT): $(gamma4scanimage_OBJECTS) $(gamma4scanimage_DEPENDENCIES) $(EXTRA_gamma4scanimage_DEPENDENCIES) @rm -f gamma4scanimage$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gamma4scanimage_OBJECTS) $(gamma4scanimage_LDADD) $(LIBS) sane-desc$(EXEEXT): $(sane_desc_OBJECTS) $(sane_desc_DEPENDENCIES) $(EXTRA_sane_desc_DEPENDENCIES) @rm -f sane-desc$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sane_desc_OBJECTS) $(sane_desc_LDADD) $(LIBS) sane-find-scanner$(EXEEXT): $(sane_find_scanner_OBJECTS) $(sane_find_scanner_DEPENDENCIES) $(EXTRA_sane_find_scanner_DEPENDENCIES) @rm -f sane-find-scanner$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sane_find_scanner_OBJECTS) $(sane_find_scanner_LDADD) $(LIBS) umax_pp$(EXEEXT): $(umax_pp_OBJECTS) $(umax_pp_DEPENDENCIES) $(EXTRA_umax_pp_DEPENDENCIES) @rm -f umax_pp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(umax_pp_OBJECTS) $(umax_pp_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-usb-chip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gamma4scanimage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sane-desc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sane-find-scanner.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/umax_pp.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgconfigDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-pkgconfigDATA .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-binSCRIPTS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-pkgconfigDATA # When build directory is not same as source directory then any # subdirectories that targets use must be manually created (under # the build directory that is). dirs: for subdir in $(HOTPLUG_DIRS); do \ $(MKDIR_P) $$subdir || exit 1; \ done hotplug/libsane.usermap: sane-desc $(descriptions) @./sane-desc -m usermap -s ${top_srcdir}/doc/descriptions:${top_srcdir}/doc/descriptions-external \ -d 1 > $@ hotplug-ng/libsane.db: sane-desc $(descriptions) @./sane-desc -m db -s ${top_srcdir}/doc/descriptions:${top_srcdir}/doc/descriptions-external \ -d 0 > $@ udev/libsane.rules: sane-desc $(descriptions) @./sane-desc -m udev -s ${top_srcdir}/doc/descriptions:${top_srcdir}/doc/descriptions-external \ -d 0 > $@ hal/libsane.fdi: sane-desc $(descriptions) @./sane-desc -m hal -s ${top_srcdir}/doc/descriptions:${top_srcdir}/doc/descriptions-external \ -d 0 > $@ clean-local: rm -f $(HOTPLUG) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/tools/hotplug-ng/0000775000175000017500000000000013110600532014515 500000000000000sane-backends-1.0.27/tools/hotplug-ng/libsane.hotplug0000775000175000017500000000102712112021330017453 00000000000000#!/bin/sh # # This file is part of the SANE distribution. # Hotplug USB hook for SANE if [ "$ACTION" != "add" ]; then exit 0 fi DEVVID=$(printf %4s $(echo $PRODUCT | cut -d'/' -f1) | tr ' ' 0) DEVPID=$(printf %4s $(echo $PRODUCT | cut -d'/' -f2) | tr ' ' 0) DEVCONF=$(grep -i "^0x$DEVVID[[:space:]]\+0x$DEVPID" /etc/sane.d/hotplug/*.db 2> /dev/null) if [ $? != 0 ]; then exit 0 fi set $DEVCONF chown $3 $DEVICE && chmod $4 $DEVICE if [ ! -z $5 -a -x $5 ]; then export DEVVID export DEVPID exec $5 fi exit 0 sane-backends-1.0.27/tools/hotplug-ng/README0000664000175000017500000000264712112021330015320 00000000000000hotplug/hotplug-ng hook for sane-backends ----------------------------------------- The libsane.hotplug script is intended to replace the existing hotplug scripts, as those won't be usable with the new hotplug-ng. The libsane.hotplug script works with both hotplug and hotplug-ng. For current Linux kernels, "udev" is state of the art, see the "udev" directory instead. This script is provided in the hope that it will be useful, simpler, faster and more extensible than the current usermap approach. INSTALLATION ------------ Install libsane.hotplug in /etc/hotplug/usb, and make it executable. Create the directory /etc/sane.d/hotplug and copy libsane.db there. FILE FORMAT ----------- The libsane.db contains 5 tab-separated fields: 0xVVVV0xPPPProot:scanner0660optional_script Fields: - vendor ID - product ID - ownership (user:group) - permissions - path of an optional script to run (it can be omitted) USAGE ----- When run by hotplug/hotplug-ng, the libsane.hotplug script will grep for ^0xVVVV[[:space:]]0xPPPP in /etc/sane.d/hotplug/*.db. If a match is found, the settings are applied to the device. The optional script is then run; this script can access the environment variables set by hotplug/hotplug-ng (see the documentation). The libsane.hotplug script will also set and export the DEVVID and DEVPID variables, containing the vendor and device ID of the scanner (of the form VVVV and PPPP). sane-backends-1.0.27/tools/gamma4scanimage.c0000664000175000017500000000563612112021330015537 00000000000000/* --------------------------------------------------------------------------------------------------------- */ /* sane - Scanner Access Now Easy. gamma4scanimage (C) 2002 Oliver Rauch This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* --------------------------------------------------------------------------------------------------------- */ #include #include #include int main(int argc, char **argv) { double gamma = 1.0; int maxin = 16383; /* 14 bit gamma input */ int maxout = 255; /* 8 bit gamma output */ int shadow = 0; int highlight = maxin; int in, out; float f; if ( (argc==1) || (argc>6) ) { printf("Usage: %s gamma [shadow [highlight [maxin [maxout]]]]\n", argv[0]); exit(-1); } if (argc>1) { gamma = atof(argv[1]); } if (argc>2) { shadow = atoi(argv[2]); } if (argc>3) { highlight = atoi(argv[3]); } if (argc>4) { maxin = atoi(argv[4]); } if (argc>5) { maxout = atoi(argv[5]); } if (shadow < 0) { printf("%s error: shadow=%d < 0\n", argv[0], shadow); exit(-1); } if (highlight < 0) { printf("%s error: highlight=%d < 0\n", argv[0], highlight); exit(-1); } if (maxin < 0) { printf("%s error: maxin=%d < 0\n", argv[0], maxin); exit(-1); } if (maxout < 0) { printf("%s error: maxout=%d < 0\n", argv[0], maxout); exit(-1); } if (shadow >= highlight) { printf("%s error: shadow=%d >= highlight=%d\n", argv[0], shadow, highlight); exit(-1); } if (highlight > maxin) { printf("%s error: highlight=%d > maxin=%d\n", argv[0], highlight, maxin); exit(-1); } if ((gamma < 0.1) || (gamma > 5)) { printf("%s error: gamma=%f out of range [0.1;5]\n", argv[0], gamma); exit(-1); } f = (highlight - shadow) / 255.0 + shadow; printf("[%d]%d-", 0, 0); if (shadow > 0) { printf("[%d]%d-", shadow, 0); } while (f < highlight) { in = (int) f; out = maxout * pow((double) (in - shadow)/(highlight-shadow), (1.0/gamma)); printf("[%d]%d-", in, out); f *= 1.5; } if (f > highlight) { printf("[%d]%d-", highlight, maxout); } printf("[%d]%d", maxin, maxout); return 0; } sane-backends-1.0.27/tools/libtool-get-dll-ext0000775000175000017500000000061212112021330016060 00000000000000#!/bin/sh # # Author: Petter Reinholdtsen # Date: 2000-03-18 # # Given a libtool lib*.la, return the dll extention used (ie. so, sl, # dll, etc) if test "x$1" = x; then echo "usage: $0 " exit 1 fi lafile=$1 libnames=`grep library_names= $lafile` last=`echo $libnames | cut -d\' -f2|tr " " "\n"|tail -n 1` dllend=`echo $last | cut -d. -f2` echo $dllend sane-backends-1.0.27/tools/sane-config.in0000664000175000017500000000521512775312262015115 00000000000000#!/bin/sh # # This script is part of SANE, # # Send bugreports and other requests to sane-devel@lists.alioth.debian.org PACKAGE="@PACKAGE@" scriptname="sane-config" prefix="@prefix@" exec_prefix="@exec_prefix@" # using our installed *.pc only - neither default nor user paths export PKG_CONFIG_LIBDIR="@libdir@/pkgconfig" export PKG_CONFIG_PATH="" pkgconfig_package=sane-backends usage () { echo "Usage: " 1>&2 echo "$scriptname --version - show installed script and SANE version" 1>&2 echo "$scriptname --ldflags - linker flags required to link with SANE" 1>&2 echo "$scriptname --libs - libraries required to link with SANE" 1>&2 echo "$scriptname --cflags - compiler flags required to find SANE headers" 1>&2 echo "$scriptname --help - show usage info (this message) " 1>&2 echo "$scriptname --help SUBCOMMAND - show help for SUBCOMMAND " 1>&2 echo "$scriptname --prefix - prefix used during SANE compile" 1>&2 echo "$scriptname --exec-prefix - exec-prefix used during SANE compile" 1>&2 } if test $# -eq 0; then usage exit 1 fi if test $# -gt 0; then case $1 in --version) echo @V_MAJOR@.@V_MINOR@.@V_REV@ ;; --help) if test $# -eq 1; then usage elif test $# -eq 2; then case $2 in --cflags) echo "Usage: $0 --cflags" echo " Print C compiler flags for compiling code that uses SANE." echo " This includes any \`-I' flags needed to find Sane's header files." ;; --ldflags) echo "Usage: $0 --ldflags" echo " Print linker flags for building the \`$PACKAGE' executable." echo " Print the linker command-line flags necessary to link against" echo " the SANE library. The libraries are listed with --libs." ;; --libs) echo "Usage: $0 --libs" echo " Print linker flags for building the \`$PACKAGE' executable." echo " Print the linker command-line flags necessary to link against" echo " the SANE library, and any other libraries it requires." ;; esac else usage fi exit 1 ;; --ldflags) pkg-config --libs-only-L "$pkgconfig_package" ;; --libs) pkg-config --libs "$pkgconfig_package" ;; --cflags) pkg-config --cflags "$pkgconfig_package" ;; --prefix) echo "${prefix}" ;; --exec-prefix) echo "${exec_prefix}" ;; *) usage exit 1 ;; esac fi sane-backends-1.0.27/tools/hotplug/0000775000175000017500000000000013110600532014113 500000000000000sane-backends-1.0.27/tools/hotplug/README0000664000175000017500000000346012112021330014710 00000000000000README for the USB hotplug scripts for sane-backends : ------------------------------------------------------ If you intend to use a USB scanner with libusb and older versions of Linux, you should install the hotplug package, and then take the following steps. For current Linux kernels, "udev" is state of the art, see the "udev" directory instead. o Copy the libsane.usermap and libusbscanner files from this directory to /etc/hotplug/usb/ o If you use Linux 2.6.3 or older, add scanner to /etc/hotplug/blacklist so that the scanner.o kernel driver won't be loaded by hotplug. With later kernel versions there is no scanner module and therefore it's not necessary to use the blacklist. o Check if /etc/hotplug/usb/libsane.usermap already knows about your scanner. If your scanner is not in this list,add a line similar to the other ones using the vendor ID and the product ID of your scanner. Please contact the sane-devel mailing list in this case so the ids of your scanner can be added. o Make sure that the "scanner" group exists on your system and that every user who should be allowed to acces the scanner is a member of that group. Alternatively, you can enable access for every user of your system in libusbscanner. The vendor ID and product ID of your scanner can be obtained by running sane-find-scanner (you might need to run it as root). Please note that the scanner.o (or scanner.ko in Linux 2.6) kernel module is now deprecated and marked as obsolete in Linux 2.6. It is recommended to switch to libusb. If the hotplug support doesn't work for you once you have taken the steps described above, check that your kernel has been built with hotplug support. Otherwise, you'll need to rebuild your kernel. -- Julien BLACHE , Sat, 28 Feb 2004 10:01:02 +0000 sane-backends-1.0.27/tools/hotplug/libusbscanner0000775000175000017500000000156512112021330016614 00000000000000#!/bin/sh # This file is part of sane-backends. # # This script changes the permissions and ownership of a USB device under # /proc/bus/usb to grant access to this device to users in the scanner group. # # Ownership is set to root:scanner, permissions are set to 0660. # # Arguments : # ----------- # ACTION=[add|remove] # DEVICE=/proc/bus/usb/BBB/DDD # TYPE=usb # latest hotplug doesn't set DEVICE on 2.6.x kernels if [ -z "$DEVICE" ] ; then IF=`echo $DEVPATH | sed 's/\(bus\/usb\/devices\/\)\(.*\)-\(.*\)/\2/'` DEV=$(cat /sys/${DEVPATH}/devnum) DEVICE=`printf '/proc/bus/usb/%.03d/%.03d' $IF $DEV` fi if [ "$ACTION" = "add" -a "$TYPE" = "usb" ]; then chown root:scanner "$DEVICE" chmod 0660 "$DEVICE" fi # That's an insecure but simple alternative # Everyone has access to the scanner # if [ "$ACTION" = "add" -a "$TYPE" = "usb" ]; then # chmod 0666 "$DEVICE" # fi sane-backends-1.0.27/tools/xerox0000775000175000017500000000233212112021330013436 00000000000000#!/bin/sh # # This is a xerox script for Laserjet Printer. # To get use of Postscript change the Printercommand and enable the # command at the end of this File. # DEV=mustek:/dev/scanner RES=300 PAPERTYPE=letter #PAPERTYPE=a4 PRINTERTYPE=ps #PRINTERTYPE=lj # # Non-printable area (left, right, top, and bottom margins): # LMARGIN=0.0 RMARGIN=0.0 TMARGIN=0.25 BMARGIN=0.0 # # Scanner-specific options: # DEVOPTS="--mode Gray" #DEVOPTS="$DEVOPTS --custom-gamma=yes --gamma-table [0]0-[64]128-[255]255" #DEVOPTS="$DEVOPTS --backtrack=yes" # needed for Mustek 12000SP # # Printer Command/Resolution PRES=$RES # change this if other Res. is desired # # Papersize in inch if [ "$PAPERTYPE" = "letter" ]; then WIDTH=8; HEIGHT=10 else # assume a4 paper WIDTH=8.27; HEIGHT=11.69 fi SCANWIDTH=`bc <<_EOF_ scale=3 $WIDTH-$LMARGIN-$RMARGIN _EOF_` SCANHEIGHT=`bc <<_EOF_ scale=3 $HEIGHT-$TMARGIN-$BMARGIN _EOF_` # SCALE=`bc << _EOF_ scale=3 75/$RES _EOF_` if [ "$PRINTERTYPE" = "ps" ]; then POST="pnmtops -rle -scale $SCALE -dpi $PRES | lpr" else POST="pgmtopbm | pbmtolj -resolution $PRES | lpr -Praw" fi scanimage -d $DEV \ -x $SCANWIDTH\" -y $SCANHEIGHT\" -l $LMARGIN\" -t $TMARGIN\" \ --resolution $RES $DEVOPTS | eval $POST sane-backends-1.0.27/tools/sane-desc.c0000664000175000017500000032165512775312262014413 00000000000000/* sane-desc.c -- generate list of supported SANE devices Copyright (C) 2002-2006 Henning Meier-Geinitz Copyright (C) 2004 Jose Gato (XML output) Copyright (C) 2006 Mattias Ellert (plist output) Copyright (C) 2009 Dr. Ing. Dieter Jurzitza Copyright (C) 2013 Tom Gundersen (hwdb output) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <../include/sane/config.h> #include "lgetopt.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #define SANE_DESC_VERSION "3.5" #define MAN_PAGE_LINK "http://www.sane-project.org/man/%s.5.html" #define COLOR_MINIMAL "\"#B00000\"" #define COLOR_BASIC "\"#FF9000\"" #define COLOR_GOOD "\"#90B000\"" #define COLOR_COMPLETE "\"#007000\"" #define COLOR_UNTESTED "\"#0000B0\"" #define COLOR_UNSUPPORTED "\"#F00000\"" #define COLOR_NEW "\"#F00000\"" #define COLOR_UNKNOWN "\"#000000\"" #define DEVMODE "0664" #define DEVOWNER "root" #define DEVGROUP "scanner" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define DBG_ERR current_debug_level = 0; debug_call #define DBG_WARN current_debug_level = 1; debug_call #define DBG_INFO current_debug_level = 2; debug_call #define DBG_DBG current_debug_level = 3; debug_call typedef enum output_mode { output_mode_ascii = 0, output_mode_xml, output_mode_html_backends, output_mode_html_backends_split, output_mode_html_mfgs, output_mode_statistics, output_mode_usermap, output_mode_db, output_mode_udev, output_mode_udevacl, output_mode_udevhwdb, output_mode_hwdb, output_mode_plist, output_mode_hal, output_mode_halnew } output_mode; typedef enum parameter_type { param_none = 0, param_string, param_two_strings, param_three_strings } parameter_type; typedef enum status_entry { status_unknown, status_unsupported, status_untested, status_minimal, status_basic, status_good, status_complete } status_entry; typedef enum device_type { type_unknown, type_scanner, type_stillcam, type_vidcam, type_meta, type_api } device_type; typedef enum level { level_backend, level_mfg, level_model, level_desc } level; typedef struct url_entry { struct url_entry *next; char *name; } url_entry; typedef struct model_entry { struct model_entry *next; char *name; char *interface; struct url_entry *url; char *comment; enum status_entry status; char *usb_vendor_id; char *usb_product_id; SANE_Bool ignore_usb_id; char *scsi_vendor_id; char *scsi_product_id; SANE_Bool scsi_is_processor; } model_entry; typedef struct desc_entry { struct desc_entry *next; char *desc; struct url_entry *url; char *comment; } desc_entry; typedef struct mfg_entry { struct mfg_entry *next; char *name; struct url_entry *url; char *comment; struct model_entry *model; } mfg_entry; typedef struct type_entry { struct type_entry *next; enum device_type type; struct desc_entry *desc; struct mfg_entry *mfg; } type_entry; typedef struct backend_entry { struct backend_entry *next; char *name; char *version; char *manpage; struct url_entry *url; char *comment; struct type_entry *type; SANE_Bool new; } backend_entry; typedef struct model_record_entry { struct model_record_entry *next; char *name; char *interface; struct url_entry *url; char *comment; enum status_entry status; char *usb_vendor_id; char *usb_product_id; char *scsi_vendor_id; char *scsi_product_id; SANE_Bool scsi_is_processor; struct backend_entry *be; } model_record_entry; typedef struct mfg_record_entry { struct mfg_record_entry *next; char *name; char *comment; struct url_entry *url; struct model_record_entry *model_record; } mfg_record_entry; typedef int statistics_type [status_complete + 1]; typedef struct manufacturer_model_type { struct manufacturer_model_type * next; char *name; } manufacturer_model_type; typedef struct usbid_type { struct usbid_type * next; char *usb_vendor_id; char *usb_product_id; struct manufacturer_model_type *name; } usbid_type; typedef struct scsiid_type { struct scsiid_type * next; char *scsi_vendor_id; char *scsi_product_id; SANE_Bool is_processor; struct manufacturer_model_type *name; } scsiid_type; static char *program_name; static int debug = 0; static int current_debug_level = 0; static char *search_dir_spec = 0; static backend_entry *first_backend = 0; static enum output_mode mode = output_mode_ascii; static char *title = 0; static char *intro = 0; static SANE_String desc_name = 0; static const char *status_name[] = {"Unknown", "Unsupported", "Untested", "Minimal", "Basic", "Good", "Complete"}; static const char *device_type_name[] = {"Unknown", "Scanners", "Still cameras", "Video Cameras", "Meta backends", "APIs"}; static const char *device_type_aname[] = {"UKNOWN", "SCANNERS", "STILL", "VIDEO", "META", "API"}; static const char *status_color[] = {COLOR_UNKNOWN, COLOR_UNSUPPORTED, COLOR_UNTESTED, COLOR_MINIMAL, COLOR_BASIC, COLOR_GOOD, COLOR_COMPLETE}; static void debug_call (const char *fmt, ...) { va_list ap; char *level_txt; va_start (ap, fmt); if (debug >= current_debug_level) { /* print to stderr */ switch (current_debug_level) { case 0: level_txt = "ERROR:"; break; case 1: level_txt = "Warning:"; break; case 2: level_txt = "Info:"; break; default: level_txt = ""; break; } if (desc_name) fprintf (stderr, "%s: %8s ", desc_name, level_txt); else fprintf (stderr, "[%s] %8s ", program_name, level_txt); vfprintf (stderr, fmt, ap); } va_end (ap); } static void print_usage (char *program_name) { printf ("Usage: %s [-s dir] [-m mode] [-d level] [-h] [-V]\n", program_name); printf (" -s|--search-dir dir " "Specify the directory that contains .desc files \n" " " "(multiple directories can be concatenated by \":\")\n"); printf (" -m|--mode mode " "Output mode (ascii, html-backends-split, html-mfgs,\n" " xml, statistics, usermap, db, udev, udev+acl, udev+hwdb, hwdb, plist, hal, hal-new)\n"); printf (" -t|--title \"title\" The title used for HTML pages\n"); printf (" -i|--intro \"intro\" A short description of the " "contents of the page\n"); printf (" -d|--debug-level level Specify debug level (0-3)\n"); printf (" -h|--help Print help message\n"); printf (" -V|--version Print version information\n"); printf ("Report bugs to \n"); } static void print_version (void) { printf ("sane-desc %s (%s)\n", SANE_DESC_VERSION, PACKAGE_STRING); printf ("Copyright (C) 2002-2006 Henning Meier-Geinitz " "\n" "sane-desc comes with NO WARRANTY, to the extent permitted by " "law.\n" "You may redistribute copies of sane-desc under the terms of the " "GNU General\n" "Public License.\n" "For more information about these matters, see the file named " "COPYING.\n"); } static SANE_Bool get_options (int argc, char **argv) { int longindex; int opt; static struct option desc_options[] = { {"search-dir", required_argument, NULL, 's'}, {"mode", required_argument, NULL, 'm'}, {"title", required_argument, NULL, 't'}, {"intro", required_argument, NULL, 'i'}, {"debug-level", required_argument, NULL, 'd'}, {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'V'}, {0, 0, 0, 0} }; while ((opt = getopt_long (argc, argv, "s:m:t:i:d:hV", desc_options, &longindex)) != -1) { switch (opt) { case 'h': print_usage (argv[0]); exit (0); case 'V': print_version (); exit (0); case 's': search_dir_spec = strdup (optarg); DBG_INFO ("setting search directory to `%s'\n", search_dir_spec); break; case 'm': if (strcmp (optarg, "ascii") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_ascii; } else if (strcmp (optarg, "xml") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_xml; } else if (strcmp (optarg, "html-backends-split") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_html_backends_split; } else if (strcmp (optarg, "html-mfgs") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_html_mfgs; } else if (strcmp (optarg, "statistics") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_statistics; } else if (strcmp (optarg, "usermap") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_usermap; } else if (strcmp (optarg, "db") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_db; } else if (strcmp (optarg, "udev") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_udev; } else if (strcmp (optarg, "udev+acl") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_udevacl; } else if (strcmp (optarg, "udev+hwdb") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_udevhwdb; } else if (strcmp (optarg, "hwdb") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_hwdb; } else if (strcmp (optarg, "plist") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_plist; } else if (strcmp (optarg, "hal") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_hal; } else if (strcmp (optarg, "hal-new") == 0) { DBG_INFO ("Output mode: %s\n", optarg); mode = output_mode_halnew; } else { DBG_ERR ("Unknown output mode: %s\n", optarg); exit (1); } break; case 't': title = optarg; DBG_INFO ("setting title to `%s'\n", optarg); break; case 'i': intro = optarg; DBG_INFO ("setting intro to `%s'\n", optarg); break; case 'd': debug = atoi (optarg); DBG_INFO ("setting debug level to %d\n", debug); break; case '?': DBG_ERR ("unknown option (use -h for help)\n"); return SANE_FALSE; case ':': DBG_ERR ("missing parameter (use -h for help)\n"); return SANE_FALSE; default: DBG_ERR ("missing option (use -h for help)\n"); return SANE_FALSE; } } if (!search_dir_spec) search_dir_spec = "."; return SANE_TRUE; } static int char_compare (char char1, char char2) { char1 = toupper (char1); char2 = toupper (char2); if (char1 < char2) return -1; else if (char1 > char2) return 1; else return 0; } static int num_compare (char *num_string1, char *num_string2) { int num1 = atoi (num_string1); int num2 = atoi (num_string2); if (num1 < num2) return -1; else if (num1 > num2) return 1; else return 0; } /* Compare two strings, try to sort numbers correctly (600 < 1200) */ static int string_compare (char *string1, char *string2) { int count = 0; int compare = 0; if (!string1) { if (!string2) return 0; else return 1; } else if (!string2) return -1; while (string1[count] && string2[count]) { if (isdigit (string1[count]) && isdigit (string2[count])) compare = num_compare (&string1[count], &string2[count]); else compare = char_compare (string1[count], string2[count]); if (compare != 0) return compare; count++; } return char_compare (string1[count], string2[count]); } /* Add URLs to the end of the list if they are unique */ static url_entry * update_url_list (url_entry * first_url, char *new_url) { url_entry *url = first_url; SANE_Bool found = SANE_FALSE; while (url && url->name) { if (string_compare (url->name, new_url) == 0) found = SANE_TRUE; url = url->next; } if (found) return first_url; url = first_url; if (url) { while (url->next) url = url->next; url->next = calloc (1, sizeof (url_entry)); url = url->next; } else { first_url = calloc (1, sizeof (url_entry)); url = first_url; } if (!url) { DBG_ERR ("update_url_list: couldn't calloc url_entry\n"); exit (1); } url->name = new_url; return first_url; } /* Get the next token, ignoring escaped quotation marks */ static const char * get_token (const char *str, char **string_const) { const char *start; size_t len; str = sanei_config_skip_whitespace (str); if (*str == '"') { start = ++str; while (*str && (*str != '"' || *(str - 1) == '\\')) ++str; len = str - start; if (*str == '"') ++str; else start = 0; /* final double quote is missing */ } else { start = str; while (*str && !isspace (*str)) ++str; len = str - start; } if (start) *string_const = strndup (start, len); else *string_const = NULL; return str; } /* Checks a line for a keyword token and determines keyword/string argument */ static SANE_Status read_keyword (SANE_String line, SANE_String keyword_token, parameter_type p_type, void *argument) { SANE_String_Const cp; SANE_Char *word; word = 0; cp = get_token (line, &word); if (!word) { DBG_ERR ("read_keyword: missing quotation mark: %s\n", line); return SANE_STATUS_INVAL; } if (strcmp (word, keyword_token) != 0) { free(word); return SANE_STATUS_INVAL; } free (word); word = 0; switch (p_type) { case param_none: return SANE_STATUS_GOOD; case param_string: { char *pos; cp = get_token (cp, &word); if (!word) { DBG_ERR ("read_keyword: missing quotation mark: %s\n", line); return SANE_STATUS_INVAL; } /* remove escaped quotations */ while ((pos = strstr (word, "\\\"")) != 0) *pos = ' '; DBG_DBG ("read_keyword: set entry `%s' to `%s'\n", keyword_token, word); *(SANE_String *) argument = strdup (word); break; } case param_two_strings: { char *pos; char **strings = malloc (2 * sizeof (SANE_String)); cp = get_token (cp, &word); if (!word) { free(strings); DBG_ERR ("read_keyword: missing quotation mark: %s\n", line); return SANE_STATUS_INVAL; } /* remove escaped quotations */ while ((pos = strstr (word, "\\\"")) != 0) *pos = ' '; DBG_INFO ("read_keyword: set first entry of `%s' to `%s'\n", keyword_token, word); strings[0] = strdup (word); if (word) free (word); cp = get_token (cp, &word); if (!word) { free(strings); DBG_ERR ("read_keyword: missing quotation mark: %s\n", line); return SANE_STATUS_INVAL; } /* remove escaped quotations */ while ((pos = strstr (word, "\\\"")) != 0) *pos = ' '; DBG_INFO ("read_keyword: set second entry of `%s' to `%s'\n", keyword_token, word); strings[1] = strdup (word); * (SANE_String **) argument = strings; break; } case param_three_strings: { char *pos; char **strings = malloc (3 * sizeof (SANE_String)); cp = get_token (cp, &word); if (!word) { free(strings); DBG_ERR ("read_keyword: missing quotation mark: %s\n", line); return SANE_STATUS_INVAL; } /* remove escaped quotations */ while ((pos = strstr (word, "\\\"")) != 0) *pos = ' '; DBG_INFO ("read_keyword: set first entry of `%s' to `%s'\n", keyword_token, word); strings[0] = strdup (word); if (word) free (word); cp = get_token (cp, &word); if (!word) { free(strings); DBG_ERR ("read_keyword: missing quotation mark: %s\n", line); return SANE_STATUS_INVAL; } /* remove escaped quotations */ while ((pos = strstr (word, "\\\"")) != 0) *pos = ' '; DBG_INFO ("read_keyword: set second entry of `%s' to `%s'\n", keyword_token, word); strings[1] = strdup (word); if (word) free (word); cp = get_token (cp, &word); if (!word) { free(strings); DBG_ERR ("read_keyword: missing quotation mark: %s\n", line); return SANE_STATUS_INVAL; } /* remove escaped quotations */ while ((pos = strstr (word, "\\\"")) != 0) *pos = ' '; DBG_INFO ("read_keyword: set third entry of `%s' to `%s'\n", keyword_token, word); strings[2] = strdup (word); * (SANE_String **) argument = strings; break; } default: DBG_ERR ("read_keyword: unknown param_type %d\n", p_type); return SANE_STATUS_INVAL; } if (word) free (word); word = 0; return SANE_STATUS_GOOD; } /* Check for a all-lowercase 4-digit hex number (e.g. 0x1234) */ static SANE_Bool check_hex (SANE_String string) { unsigned int i; if (strlen (string) != 6) return SANE_FALSE; if (strncmp (string, "0x", 2) != 0) return SANE_FALSE; for (i = 0; i < strlen (string); i++) { if (isupper (string[i])) return SANE_FALSE; } for (i = 2; i < strlen (string); i++) { if (!isxdigit (string[i])) return SANE_FALSE; } return SANE_TRUE; } /* Read and interprete the .desc files */ static SANE_Bool read_files (void) { struct stat stat_buf; DIR *dir; struct dirent *dir_entry; FILE *fp; char file_name[PATH_MAX]; SANE_Char line[4096], *word; SANE_String_Const cp; backend_entry *current_backend = 0; type_entry *current_type = 0; mfg_entry *current_mfg = 0; model_entry *current_model = 0; enum level current_level = level_backend; char *search_dir = search_dir_spec, *end = 0; DBG_INFO ("looking for .desc files in `%s'\n", search_dir_spec); while (search_dir && search_dir[0]) { end = strchr (search_dir, ':'); if (end) end[0] = '\0'; DBG_INFO ("reading directory `%s'\n", search_dir); if (stat (search_dir, &stat_buf) < 0) { DBG_ERR ("cannot stat `%s' (%s)\n", search_dir, strerror (errno)); return SANE_FALSE; } if (!S_ISDIR (stat_buf.st_mode)) { DBG_ERR ("`%s' is not a directory\n", search_dir); return SANE_FALSE; } if ((dir = opendir (search_dir)) == 0) { DBG_ERR ("cannot read directory `%s' (%s)\n", search_dir, strerror (errno)); return SANE_FALSE; } while ((dir_entry = readdir (dir)) != NULL) { if (strlen (dir_entry->d_name) > 5 && strcmp (dir_entry->d_name + strlen (dir_entry->d_name) - 5, ".desc") == 0) { if (strlen (search_dir) + strlen (dir_entry->d_name) + 1 + 1 > PATH_MAX) { DBG_ERR ("filename too long\n"); return SANE_FALSE; } sprintf (file_name, "%s/%s", search_dir, dir_entry->d_name); DBG_INFO ("-> reading desc file: %s\n", file_name); fp = fopen (file_name, "r"); if (!fp) { DBG_ERR ("can't open desc file: %s (%s)\n", file_name, strerror (errno)); return SANE_FALSE; } /* now we check if everything is ok with the previous backend before we read the new one */ if (current_backend) { type_entry *current_type = current_backend->type; int no_usbids = 0; int no_interface = 0; int no_status = 0; while (current_type) { if (current_type->type == type_scanner || current_type->type == type_stillcam || current_type->type == type_vidcam) { mfg_entry *current_mfg = current_type->mfg; while (current_mfg) { model_entry *current_model = current_mfg->model; while (current_model) { if (current_model->status == status_unknown) { DBG_INFO ("Backend `%s': `%s' `%s' does not have a status\n", current_backend->name, current_mfg->name, current_model->name); no_status++; } if (!current_model->interface) { DBG_INFO ("Backend `%s': `%s' `%s' does not have an interface\n", current_backend->name, current_mfg->name, current_model->name); no_interface++; } else if (strstr (current_model->interface, "USB")) { if ((!current_model->usb_vendor_id || !current_model->usb_product_id) && !current_model->ignore_usb_id) { DBG_INFO ("`%s' seems to provide a USB device " "without :usbid (%s %s)\n", current_backend->name, current_mfg->name, current_model->name); no_usbids++; } } current_model = current_model->next; } current_mfg = current_mfg->next; } } current_type = current_type->next; } if (no_status) { DBG_WARN ("Backend `%s': %d devices without :status\n", current_backend->name, no_status); } if (no_interface) { DBG_WARN ("Backend `%s': %d devices without :interface\n", current_backend->name, no_interface); } if (no_usbids) { DBG_WARN ("Backend `%s': %d USB devices without :usbid\n", current_backend->name, no_usbids); } } desc_name = dir_entry->d_name; current_backend = 0; current_type = 0; current_mfg = 0; current_model = 0; while (sanei_config_read (line, sizeof (line), fp)) { char *string_entry = 0; char **two_string_entry; char **three_string_entry; word = 0; cp = get_token (line, &word); if (!word || cp == line) { DBG_DBG ("ignoring empty line\n"); if (word) free (word); word = 0; continue; } if (word[0] == ';') { DBG_DBG ("ignoring comment line\n"); free (word); word = 0; continue; } DBG_DBG ("line: %s\n", line); if (read_keyword (line, ":backend", param_string, &string_entry) == SANE_STATUS_GOOD) { backend_entry *be = first_backend, *prev_be = 0, *new_be = 0; DBG_INFO ("creating backend entry `%s'\n", string_entry); new_be = calloc (1, sizeof (backend_entry)); if (!new_be) { DBG_ERR ("calloc failed (%s)\n", strerror (errno)); return SANE_FALSE; } new_be->name = string_entry; new_be->new = SANE_FALSE; if (!be) { first_backend = new_be; be = new_be; } else { while (be) { int compare = string_compare (new_be->name, be->name); if (compare <= 0) { backend_entry *be_tmp = be; be = new_be; be->next = be_tmp; if (!prev_be) first_backend = be; else prev_be->next = be; break; } prev_be = be; be = be->next; } if (!be) /* last entry */ { prev_be->next = new_be; be = prev_be->next; } } current_backend = be; current_type = 0; current_mfg = 0; current_model = 0; current_level = level_backend; continue; } if (!current_backend) { DBG_ERR ("use `:backend' keyword first\n"); return SANE_FALSE; } if (read_keyword (line, ":version", param_string, &string_entry) == SANE_STATUS_GOOD) { if (current_backend->version) { DBG_WARN ("overwriting version of backend `%s' to `%s'" "(was: `%s')\n", current_backend->name, string_entry, current_backend->version, current_backend->version); } DBG_INFO ("setting version of backend `%s' to `%s'\n", current_backend->name, string_entry); current_backend->version = string_entry; continue; } if (read_keyword (line, ":status", param_string, &string_entry) == SANE_STATUS_GOOD) { switch (current_level) { case level_model: if (current_model->status != status_unknown) { DBG_WARN ("overwriting status of model `%s' (backend `%s')\n", current_model->name, current_backend->name); } if (strcmp (string_entry, ":minimal") == 0) { DBG_INFO ("setting status of model `%s' to `minimal'\n", current_model->name); current_model->status = status_minimal; } else if (strcmp (string_entry, ":basic") == 0) { DBG_INFO ("setting status of model `%s' to `basic'\n", current_model->name); current_model->status = status_basic; } else if (strcmp (string_entry, ":good") == 0) { DBG_INFO ("setting status of model `%s' to `good'\n", current_model->name); current_model->status = status_good; } else if (strcmp (string_entry, ":complete") == 0) { DBG_INFO ("setting status of model `%s' to `complete'\n", current_model->name); current_model->status = status_complete; } else if (strcmp (string_entry, ":untested") == 0) { DBG_INFO ("setting status of model `%s' to `untested'\n", current_model->name); current_model->status = status_untested; } else if (strcmp (string_entry, ":unsupported") == 0) { DBG_INFO ("setting status of model `%s' to `unsupported'\n", current_model->name); current_model->status = status_unsupported; } else { DBG_ERR ("unknown status of model `%s': `%s' (backend `%s')\n", current_model->name, string_entry, current_backend->name); current_model->status = status_untested; return SANE_FALSE; } break; default: DBG_ERR ("level %d not implemented for :status (backend `%s')\n", current_level, current_backend->name); return SANE_FALSE; } continue; } if (read_keyword (line, ":new", param_string, &string_entry) == SANE_STATUS_GOOD) { if (strcmp (string_entry, ":yes") == 0) { DBG_INFO ("backend %s is new in this SANE release\n", current_backend->name); current_backend->new = SANE_TRUE; } else if (strcmp (string_entry, ":no") == 0) { DBG_INFO ("backend %s is NOT new in this SANE release\n", current_backend->name); current_backend->new = SANE_FALSE; } else { DBG_ERR ("unknown :new parameter of backend `%s': " "`%s'\n", current_backend->name, string_entry); current_backend->new = SANE_FALSE; return SANE_FALSE; } continue; } if (read_keyword (line, ":manpage", param_string, &string_entry) == SANE_STATUS_GOOD) { if (current_backend->manpage) { DBG_WARN ("overwriting manpage of backend `%s' to `%s'" "(was: `%s')\n", current_backend->name, string_entry, current_backend->manpage); } DBG_INFO ("setting manpage of backend `%s' to `%s'\n", current_backend->name, string_entry); current_backend->manpage = string_entry; continue; } if (read_keyword (line, ":devicetype", param_string, &string_entry) == SANE_STATUS_GOOD) { type_entry *type = 0; type = current_backend->type; DBG_INFO ("adding `%s' to list of device types of backend " "`%s'\n", string_entry, current_backend->name); if (type) { while (type->next) type = type->next; type->next = calloc (1, sizeof (type_entry)); type = type->next; } else { current_backend->type = calloc (1, sizeof (type_entry)); type = current_backend->type; } type->type = type_unknown; if (strcmp (string_entry, ":scanner") == 0) { DBG_INFO ("setting device type of backend `%s' to " "scanner\n", current_backend->name); type->type = type_scanner; } else if (strcmp (string_entry, ":stillcam") == 0) { DBG_INFO ("setting device type of backend `%s' to " "still camera\n", current_backend->name); type->type = type_stillcam; } else if (strcmp (string_entry, ":vidcam") == 0) { DBG_INFO ("setting device type of backend `%s' to " "video camera\n", current_backend->name); type->type = type_vidcam; } else if (strcmp (string_entry, ":api") == 0) { DBG_INFO ("setting device type of backend `%s' to " "API\n", current_backend->name); type->type = type_api; } else if (strcmp (string_entry, ":meta") == 0) { DBG_INFO ("setting device type of backend `%s' to " "meta\n", current_backend->name); type->type = type_meta; } else { DBG_ERR ("unknown device type of backend `%s': `%s'\n", current_backend->name, string_entry); type->type = type_unknown; return SANE_FALSE; } current_type = type; current_mfg = 0; current_model = 0; continue; } if (read_keyword (line, ":desc", param_string, &string_entry) == SANE_STATUS_GOOD) { if (!current_type) { DBG_ERR ("use `:devicetype' keyword first (backend `%s')\n", current_backend->name); return SANE_FALSE; } if (current_type->type < type_meta) { DBG_ERR ("use `:desc' for `:api' and `:meta' only (backend `%s')\n", current_backend->name); return SANE_FALSE; } if (current_type->desc) { DBG_WARN ("overwriting description of device type of " "backend `%s' to `%s' (was: `%s')\n", current_backend->name, string_entry, current_type->desc); } DBG_INFO ("setting description of backend `%s' to `%s'\n", current_backend->name, string_entry); current_type->desc = calloc (1, sizeof (desc_entry)); if (!current_type->desc) { DBG_ERR ("calloc failed (%s)\n", strerror (errno)); return SANE_FALSE; } current_type->desc->desc = string_entry; current_level = level_desc; current_mfg = 0; current_model = 0; continue; } if (read_keyword (line, ":mfg", param_string, &string_entry) == SANE_STATUS_GOOD) { mfg_entry *mfg = 0; if (!current_type) { DBG_ERR ("use `:devicetype' keyword first (backend `%s')\n", current_backend->name); return SANE_FALSE; } if (current_type->type >= type_meta) { DBG_ERR ("use `:mfg' for hardware devices only (backend `%s')\n", current_backend->name); return SANE_FALSE; } mfg = current_type->mfg; if (mfg) { while (mfg->next) mfg = mfg->next; mfg->next = calloc (1, sizeof (mfg_entry)); mfg = mfg->next; } else { current_type->mfg = calloc (1, sizeof (mfg_entry)); mfg = current_type->mfg; } if (!mfg) { DBG_ERR ("calloc failed (%s)\n", strerror (errno)); return SANE_FALSE; } mfg->name = string_entry; DBG_INFO ("adding mfg entry %s to backend `%s'\n", string_entry, current_backend->name); current_mfg = mfg; current_model = 0; current_level = level_mfg; continue; } if (read_keyword (line, ":model", param_string, &string_entry) == SANE_STATUS_GOOD) { model_entry *model = 0; if (!current_type) { DBG_ERR ("use `:devicetype' keyword first (backend `%s')\n", current_backend->name); return SANE_FALSE; } if (current_level != level_mfg && current_level != level_model) { DBG_ERR ("use `:mfg' keyword first (backend `%s')\n", current_backend->name); return SANE_FALSE; } model = current_mfg->model; if (model) { while (model->next) model = model->next; model->next = calloc (1, sizeof (model_entry)); model = model->next; } else { current_mfg->model = calloc (1, sizeof (model_entry)); model = current_mfg->model; } if (!model) { DBG_ERR ("calloc failed (%s)\n", strerror (errno)); return SANE_FALSE; } model->name = string_entry; model->status = status_unknown; DBG_INFO ("adding model entry %s to manufacturer `%s'\n", string_entry, current_mfg->name); current_model = model; current_level = level_model; continue; } if (read_keyword (line, ":interface", param_string, &string_entry) == SANE_STATUS_GOOD) { if (!current_model) { DBG_WARN ("ignored `%s' :interface, only allowed for " "hardware devices\n", current_backend->name); continue; } if (current_model->interface) { DBG_WARN ("overwriting `%s's interface of model " "`%s' to `%s' (was: `%s')\n", current_backend->name, current_model->name, string_entry, current_model->interface); } DBG_INFO ("setting interface of model `%s' to `%s'\n", current_model->name, string_entry); current_model->interface = string_entry; continue; } if (read_keyword (line, ":scsi", param_three_strings, &three_string_entry) == SANE_STATUS_GOOD) { if (!current_model) { DBG_WARN ("ignored `%s' :scsi, only allowed for " "hardware devices\n", current_backend->name); continue; } DBG_INFO ("setting scsi vendor and product ids of model `%s' to `%s/%s'\n", current_model->name, three_string_entry[0], three_string_entry[1]); if (strcasecmp (three_string_entry[0], "ignore") == 0) { DBG_INFO ("Ignoring `%s's scsi-entries of `%s'\n", current_backend->name, current_model->name); continue; } if (strcasecmp (three_string_entry[2], "processor") == 0){ current_model->scsi_is_processor = SANE_TRUE; current_model->scsi_vendor_id = three_string_entry[0]; current_model->scsi_product_id = three_string_entry[1]; } else { DBG_INFO ("scsi-format info in %s is invalid -> break\n", current_backend->name); continue; } continue; } if (read_keyword (line, ":usbid", param_two_strings, &two_string_entry) == SANE_STATUS_GOOD) { if (!current_model) { DBG_WARN ("ignored `%s' :usbid, only allowed for " "hardware devices\n", current_backend->name); continue; } if (strcasecmp (two_string_entry[0], "ignore") == 0) { DBG_INFO ("Ignoring `%s's USB ids of `%s'\n", current_backend->name, current_model->name); current_model->ignore_usb_id = SANE_TRUE; continue; } if (!check_hex (two_string_entry[0])) { DBG_WARN ("`%s's USB vendor id of `%s' is " "not a lowercase 4-digit hex number: " "`%s'\n", current_backend->name, current_model->name, two_string_entry[0]); continue; } if (!check_hex (two_string_entry[1])) { DBG_WARN ("`%s's USB product id of `%s' is " "not a lowercase 4-digit hex number: " "`%s'\n", current_backend->name, current_model->name, two_string_entry[1]); continue; } if (current_model->usb_vendor_id || current_model->usb_product_id) { DBG_WARN ("overwriting `%s's USB ids of model " "`%s' to `%s/%s' (was: `%s/%s')\n", current_backend->name, current_model->name, two_string_entry[0], two_string_entry[1], current_model->usb_vendor_id, current_model->usb_product_id); } DBG_INFO ("setting USB vendor and product ids of model `%s' to `%s/%s'\n", current_model->name, two_string_entry[0], two_string_entry[1]); current_model->usb_vendor_id = two_string_entry[0]; current_model->usb_product_id = two_string_entry[1]; continue; } if (read_keyword (line, ":url", param_string, &string_entry) == SANE_STATUS_GOOD) { switch (current_level) { case level_backend: current_backend->url = update_url_list (current_backend->url, string_entry); DBG_INFO ("adding `%s' to list of urls of backend " "`%s'\n", string_entry, current_backend->name); break; case level_mfg: current_mfg->url = update_url_list (current_mfg->url, string_entry); DBG_INFO ("adding `%s' to list of urls of mfg " "`%s'\n", string_entry, current_mfg->name); break; case level_desc: current_type->desc->url = update_url_list (current_type->desc->url, string_entry); DBG_INFO ("adding `%s' to list of urls of description " "for backend `%s'\n", string_entry, current_backend->name); break; case level_model: current_model->url = update_url_list (current_model->url, string_entry); DBG_INFO ("adding `%s' to list of urls of model " "`%s'\n", string_entry, current_model->name); break; default: DBG_ERR ("level %d not implemented for :url (backend `%s')\n", current_level, current_backend->name); return SANE_FALSE; } continue; } if (read_keyword (line, ":comment", param_string, &string_entry) == SANE_STATUS_GOOD) { switch (current_level) { case level_backend: current_backend->comment = string_entry; DBG_INFO ("setting comment of backend %s to `%s'\n", current_backend->name, string_entry); break; case level_mfg: current_mfg->comment = string_entry; DBG_INFO ("setting comment of manufacturer %s to `%s'\n", current_mfg->name, string_entry); break; case level_desc: current_type->desc->comment = string_entry; DBG_INFO ("setting comment of description for " "backend %s to `%s'\n", current_backend->name, string_entry); break; case level_model: current_model->comment = string_entry; DBG_INFO ("setting comment of model %s to `%s'\n", current_model->name, string_entry); break; default: DBG_ERR ("level %d not implemented for `:comment' (backend `%s')\n", current_level, current_backend->name); return SANE_FALSE; } continue; } DBG_ERR ("unknown keyword token in line `%s' of file `%s'\n", line, file_name); return SANE_FALSE; } /* while (sanei_config_readline) */ fclose (fp); } /* if (strlen) */ } /* while (direntry) */ if (closedir(dir) != 0) { DBG_ERR ("cannot close directory `%s' (%s)\n", search_dir, strerror (errno)); return SANE_FALSE; } if (end) search_dir = end + 1; else search_dir = (search_dir + strlen (search_dir)); } desc_name = 0; if (!first_backend) { DBG_ERR ("Couldn't find any .desc file\n"); return SANE_FALSE; } return SANE_TRUE; } /* Create a model_record_entry based on a model_entry */ static model_record_entry * create_model_record (model_entry * model) { model_record_entry *model_record; model_record = calloc (1, sizeof (model_record_entry)); if (!model_record) { DBG_ERR ("create_model_record: couldn't calloc model_record_entry\n"); exit (1); } model_record->name = model->name; model_record->status = model->status; model_record->interface = model->interface; model_record->url = model->url; model_record->comment = model->comment; model_record->usb_vendor_id = model->usb_vendor_id; model_record->usb_product_id = model->usb_product_id; model_record->scsi_vendor_id = model->scsi_vendor_id; model_record->scsi_product_id = model->scsi_product_id; model_record->scsi_is_processor = model->scsi_is_processor; return model_record; } /* Calculate the priority of statuses: */ /* minimal, basic, good, complete -> 2, untested -> 1, unsupported -> 0 */ static int calc_priority (status_entry status) { switch (status) { case status_untested: return 1; case status_unsupported: return 0; default: return 2; } } /* Insert model into list at the alphabetically correct position */ static model_record_entry * update_model_record_list (model_record_entry * first_model_record, model_entry * model, backend_entry * be) { model_record_entry *model_record = first_model_record; if (!first_model_record) { /* First model for this manufacturer */ first_model_record = create_model_record (model); model_record = first_model_record; } else { model_record_entry *prev_model_record = 0; while (model_record) { int compare = string_compare (model->name, model_record->name); if (compare <= 0) { model_record_entry *tmp_model_record = model_record; if ((compare == 0) && (string_compare (model->interface, model_record->interface) == 0) && (string_compare (model->usb_vendor_id, model_record->usb_vendor_id) == 0) && (string_compare (model->usb_product_id, model_record->usb_product_id) == 0)) { /* Two entries for the same model */ int new_priority = calc_priority (model->status); int old_priority = calc_priority (model_record->status); if (new_priority < old_priority) { DBG_DBG ("update_model_record_list: model %s ignored, backend %s has " "higher priority\n", model->name, model_record->be->name); return first_model_record; } if (new_priority > old_priority) { DBG_DBG ("update_model_record_list: model %s overrides the one from backend %s\n", model->name, model_record->be->name); tmp_model_record = model_record->next; } } /* correct position */ model_record = create_model_record (model); model_record->next = tmp_model_record; if (!prev_model_record) first_model_record = model_record; else prev_model_record->next = model_record; break; } prev_model_record = model_record; model_record = model_record->next; } if (!model_record) /* last entry */ { prev_model_record->next = create_model_record (model); model_record = prev_model_record->next; } } /* if (first_model_record) */ model_record->be = be; DBG_DBG ("update_model_record_list: added model %s\n", model->name); return first_model_record; } /* Insert manufacturer into list at the alphabetically correct position, */ /* create new record if neccessary */ static mfg_record_entry * update_mfg_record_list (mfg_record_entry * first_mfg_record, mfg_entry * mfg, backend_entry * be) { model_entry *model = mfg->model; mfg_record_entry *mfg_record = first_mfg_record; while (mfg_record) { if (string_compare (mfg_record->name, mfg->name) == 0) { /* Manufacturer already exists */ url_entry *mfg_url = mfg->url; /* Manufacturer comments and (additional) URLs? */ if (!mfg_record->comment) mfg_record->comment = mfg->comment; while (mfg_url && mfg_url->name) { mfg_record->url = update_url_list (mfg_record->url, mfg_url->name); mfg_url = mfg_url->next; } break; } mfg_record = mfg_record->next; } if (!mfg_record) { /* Manufacturer doesn't exist yet */ url_entry *url = mfg->url; mfg_record = calloc (1, sizeof (mfg_record_entry)); if (!mfg_record) { DBG_ERR ("update_mfg_record_list: couldn't calloc " "mfg_record_entry\n"); exit (1); } mfg_record->name = mfg->name; mfg_record->comment = mfg->comment; while (url) { mfg_record->url = update_url_list (mfg_record->url, url->name); url = url->next; } if (first_mfg_record != 0) { /* We already have one manufacturer in the list */ mfg_record_entry *new_mfg_record = mfg_record; mfg_record_entry *prev_mfg_record = 0; mfg_record = first_mfg_record; while (mfg_record) { int compare = string_compare (new_mfg_record->name, mfg_record->name); if (compare <= 0) { mfg_record_entry *tmp_mfg_record = mfg_record; mfg_record = new_mfg_record; mfg_record->next = tmp_mfg_record; if (!prev_mfg_record) first_mfg_record = mfg_record; else prev_mfg_record->next = mfg_record; break; } prev_mfg_record = mfg_record; mfg_record = mfg_record->next; } if (!mfg_record) /* last entry */ { prev_mfg_record->next = new_mfg_record; mfg_record = prev_mfg_record->next; } } else first_mfg_record = mfg_record; DBG_DBG ("update_mfg_record_list: created mfg %s\n", mfg_record->name); } /* if (!mfg_record) */ /* create model entries */ while (model) { mfg_record->model_record = update_model_record_list (mfg_record->model_record, model, be); model = model->next; } return first_mfg_record; } /* Create a sorted list of manufacturers based on the backends list */ static mfg_record_entry * create_mfg_list (device_type dev_type) { mfg_record_entry *first_mfg_record = 0; backend_entry *be = first_backend; DBG_DBG ("create_mfg_list: start\n"); while (be) { type_entry *type = be->type; while (type) { if (type->type == dev_type) { mfg_entry *mfg = type->mfg; while (mfg) { first_mfg_record = update_mfg_record_list (first_mfg_record, mfg, be); mfg = mfg->next; } } type = type->next; } be = be->next; } DBG_DBG ("create_mfg_list: exit\n"); return first_mfg_record; } /* Print an ASCII list with all the information we have */ static void ascii_print_backends (void) { backend_entry *be; be = first_backend; while (be) { url_entry *url = be->url; type_entry *type = be->type; if (be->name) printf ("backend `%s'\n", be->name); else printf ("backend *none*\n"); if (be->version) printf (" version `%s'\n", be->version); else printf (" version *none*\n"); if (be->new) printf (" NEW!\n"); if (be->manpage) printf (" manpage `%s'\n", be->manpage); else printf (" manpage *none*\n"); if (url) while (url) { printf (" url `%s'\n", url->name); url = url->next; } else printf (" url *none*\n"); if (be->comment) printf (" comment `%s'\n", be->comment); else printf (" comment *none*\n"); if (type) while (type) { switch (type->type) { case type_scanner: printf (" type scanner\n"); break; case type_stillcam: printf (" type stillcam\n"); break; case type_vidcam: printf (" type vidcam\n"); break; case type_meta: printf (" type meta\n"); break; case type_api: printf (" type api\n"); break; default: printf (" type *unknown*\n"); break; } if (type->desc) { url_entry *url = type->desc->url; printf (" desc `%s'\n", type->desc->desc); if (url) while (url) { printf (" url `%s'\n", url->name); url = url->next; } else printf (" url *none*\n"); if (type->desc->comment) printf (" comment `%s'\n", type->desc->comment); else printf (" comment *none*\n"); } else if (type->type >= type_meta) printf (" desc *none*\n"); if (type->mfg) { mfg_entry *mfg = type->mfg; while (mfg) { model_entry *model = mfg->model; url_entry *url = mfg->url; printf (" mfg `%s'\n", mfg->name); if (url) while (url) { printf (" url `%s'\n", url->name); url = url->next; } else printf (" url *none*\n"); if (mfg->comment) printf (" comment `%s'\n", mfg->comment); else printf (" comment *none*\n"); if (model) while (model) { url_entry *url = model->url; printf (" model `%s'\n", model->name); if (model->interface) printf (" interface `%s'\n", model->interface); else printf (" interface *none*\n"); if (model->usb_vendor_id) printf (" usb-vendor-id `%s'\n", model->usb_vendor_id); else printf (" usb-vendor-id *none*\n"); if (model->usb_product_id) printf (" usb-product-id `%s'\n", model->usb_product_id); else printf (" usb-product-id *none*\n"); switch (model->status) { case status_minimal: printf (" status minimal\n"); break; case status_basic: printf (" status basic\n"); break; case status_good: printf (" status good\n"); break; case status_complete: printf (" status complete\n"); break; case status_untested: printf (" status untested\n"); break; case status_unsupported: printf (" status unsupported\n"); break; default: printf (" status *unknown*\n"); break; } if (url) while (url) { printf (" url `%s'\n", url->name); url = url->next; } else printf (" url *none*\n"); if (model->comment) printf (" comment `%s'\n", model->comment); else printf (" comment *none*\n"); model = model->next; } else printf (" model *none*\n"); mfg = mfg->next; } /* while (mfg) */ } else if (type->type < type_meta) printf (" mfg *none*\n"); type = type->next; } /* while (type) */ else printf (" type *none*\n"); be = be->next; } /* while (be) */ } static char * clean_string (char *c) { /* not avoided characters */ char *aux; aux = malloc (strlen (c) * sizeof (char) * 6); *aux = '\0'; while (*c != '\0') { /*limit to printable ASCII only*/ if(*c < 0x20 || *c > 0x7e){ c++; continue; } switch (*c) { case '<': aux = strcat (aux, "<"); break; case '>': aux = strcat (aux, ">"); break; case '\'': aux = strcat (aux, "'"); break; case '&': aux = strcat (aux, "&"); break; default: aux = strncat (aux, c, 1); } c = c + 1; } return aux; } /* Print an XML list with all the information we have */ static void xml_print_backends (void) { backend_entry *be; be = first_backend; printf ("\n"); while (be) { url_entry *url = be->url; type_entry *type = be->type; if (be->name) printf ("\n", clean_string (be->name)); else printf ("\n"); if (be->version) printf ("%s \n", clean_string (be->version)); else printf ("*none*\n"); if (be->new) printf ("\n"); else printf ("\n"); if (be->manpage) printf (" %s\n", clean_string (be->manpage)); else printf (" *none*\n"); if (url) while (url) { printf (" %s\n", clean_string (url->name)); url = url->next; } else printf (" *none*\n"); if (be->comment) printf (" %s\n", clean_string (be->comment)); else printf (" *none*\n"); if (type) while (type) { switch (type->type) { case type_scanner: printf (" \n"); break; case type_stillcam: printf (" \n"); break; case type_vidcam: printf (" \n"); break; case type_meta: printf (" \n"); break; case type_api: printf (" \n"); break; default: printf (" \n"); break; } if (type->desc) { url_entry *url = type->desc->url; printf (" %s\n", clean_string (type->desc->desc)); if (url) while (url) { printf (" %s\n", clean_string (url->name)); url = url->next; } else printf (" *none*\n"); if (type->desc->comment) printf (" %s\n", clean_string (type->desc->comment)); else printf (" *none*\n"); } else if (type->type >= type_meta) printf (" *none*\n"); if (type->mfg) { mfg_entry *mfg = type->mfg; while (mfg) { model_entry *model = mfg->model; url_entry *url = mfg->url; printf (" \n", clean_string (mfg->name)); if (url) while (url) { printf (" `%s'\n", clean_string (url->name)); url = url->next; } else printf (" *none*\n"); if (mfg->comment) printf (" %s\n", clean_string (mfg->comment)); else printf (" *none*\n"); if (model) while (model) { url_entry *url = model->url; printf (" \n", clean_string (model->name)); if (model->interface) printf (" %s\n", clean_string (model->interface)); else printf (" *none*\n"); if (model->usb_vendor_id) printf (" %s\n", clean_string (model->usb_vendor_id)); else printf (" *none*\n"); if (model->usb_product_id) printf (" %s\n", clean_string (model->usb_product_id)); else printf (" *none*\n"); switch (model->status) { case status_minimal: printf (" minimal\n"); break; case status_basic: printf (" basic\n"); break; case status_good: printf (" good\n"); break; case status_complete: printf (" complete\n"); break; case status_untested: printf (" untested\n"); break; case status_unsupported: printf (" unsupported\n"); break; default: printf (" *unknown*\n"); break; } if (url) while (url) { printf (" %s\n", clean_string (url->name)); url = url->next; } else printf (" *none*\n"); if (model->comment) printf (" %s\n", clean_string (model->comment)); else printf (" *none*\n"); model = model->next; printf (" \n"); } /* while (model) */ else printf (" \n"); printf (" \n"); mfg = mfg->next; } /* while (mfg) */ } else if (type->type < type_meta) printf (" *none*\n"); type = type->next; printf (" \n"); } /* while (type) */ else printf (" *none*\n"); printf ("\n"); be = be->next; } /* while (be) */ printf ("\n"); } /* calculate statistics about supported devices per device type*/ static void calculate_statistics_per_type (device_type dev_type, statistics_type num) { backend_entry *be = first_backend; while (be) { type_entry *type = be->type; while (type) { if (type->type == dev_type) { mfg_entry *mfg = type->mfg; model_entry *model; if (type->desc) { num[status_complete]++; type = type->next; continue; } if (!mfg) { type = type->next; continue; } mfg = type->mfg; while (mfg) { model = mfg->model; if (model) { while (model) { enum status_entry status = model->status; num[status]++; model = model->next; } /* while (model) */ } /* if (num_models) */ mfg = mfg->next; } /* while (mfg) */ } /* if (type->type) */ type = type->next; } /* while (type) */ be = be->next; } /* while (be) */ } static void html_print_statistics_cell (const char * color, int number) { printf ("%d\n", color, number); } static void html_print_statistics_per_type (device_type dev_type) { statistics_type num = {0, 0, 0, 0, 0, 0, 0}; status_entry status; calculate_statistics_per_type (dev_type, num); printf ("\n"); printf("%s\n", device_type_aname [dev_type], device_type_name [dev_type]); html_print_statistics_cell (COLOR_UNKNOWN, num[status_minimal] + num[status_basic] + num[status_good] + num[status_complete] + num[status_untested] + num[status_unsupported]); if (dev_type == type_scanner || dev_type == type_stillcam || dev_type == type_vidcam) { html_print_statistics_cell (COLOR_UNKNOWN, num[status_minimal] + num[status_basic] + num[status_good] + num[status_complete]); for (status = status_complete; status >= status_unsupported; status--) html_print_statistics_cell (status_color [status], num [status]); } else { printf ("n/a\n"); } printf ("\n"); } /* print html statistcis */ static void html_print_summary (void) { device_type dev_type; status_entry status; printf ("

Summary

\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n", status_name[status_untested]); printf ("\n", status_name[status_unsupported]); printf ("\n"); printf ("\n"); printf ("\n"); for (status = status_complete; status >= status_minimal; status--) printf ("\n", status_color[status], status_name[status]); printf ("\n"); for (dev_type = type_scanner; dev_type <= type_api; dev_type++) html_print_statistics_per_type (dev_type); printf ("
Device typeNumber of devices
TotalSupported%s%s
Sum%s
\n"); } /* Generate a name used for HTML tags */ static char * html_generate_anchor_name (device_type dev_type, char *manufacturer_name) { char *name = malloc (strlen (manufacturer_name) + 1 + 2); char *pointer = name; char type_char; if (!name) { DBG_ERR ("html_generate_anchor_name: couldn't malloc\n"); return 0; } switch (dev_type) { case type_scanner: type_char = 'S'; break; case type_stillcam: type_char = 'C'; break; case type_vidcam: type_char = 'V'; break; case type_meta: type_char = 'M'; break; case type_api: type_char = 'A'; break; default: type_char = 'Z'; break; } snprintf (name, strlen (manufacturer_name) + 1 + 2, "%c-%s", type_char, manufacturer_name); while (*pointer) { if (!isalnum (*pointer)) *pointer = '-'; else *pointer = toupper (*pointer); pointer++; } return name; } /* Generate one table per backend of all backends providing models */ /* of type dev_type */ static void html_backends_split_table (device_type dev_type) { backend_entry *be = first_backend; SANE_Bool first = SANE_TRUE; printf ("

Backends: \n"); while (be) /* print link list */ { type_entry *type = be->type; SANE_Bool found = SANE_FALSE; while (type) { if (type->type == dev_type) found = SANE_TRUE; type = type->next; } if (found) { if (!first) printf (", \n"); first = SANE_FALSE; printf ("%s", html_generate_anchor_name (dev_type, be->name), be->name); } be = be->next; } be = first_backend; if (first) printf ("(none)\n"); printf ("

\n"); while (be) { type_entry *type = be->type; while (type) { if (type->type == dev_type) { mfg_entry *mfg = type->mfg; model_entry *model; printf ("

Backend: %s\n", html_generate_anchor_name (type->type, be->name), be->name); if (be->version || be->new) { printf ("("); if (be->version) { printf ("%s", be->version); if (be->new) printf (", NEW!"); } else printf ("NEW!"); printf (")\n"); } printf ("

\n"); printf ("

\n"); if (be->url && be->url->name) { url_entry *url = be->url; printf ("Link(s): \n"); while (url) { if (url != be->url) printf (", "); printf ("%s", url->name, url->name); url = url->next; } printf ("
\n"); } if (be->manpage) printf ("Manual page: %s
\n", be->manpage, be->manpage); if (be->comment) printf ("Comment: %s
\n", be->comment); if (type->desc) { if (type->desc->desc) { if (type->desc->url && type->desc->url->name) printf ("Description: " "%s
\n", type->desc->url->name, type->desc->desc); else printf ("Description: %s
\n", type->desc->desc); } if (type->desc->comment) printf ("Comment: %s
\n", type->desc->comment); printf ("

\n"); type = type->next; continue; } printf ("

\n"); if (!mfg) { type = type->next; continue; } printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); mfg = type->mfg; while (mfg) { model = mfg->model; if (model) { int num_models = 0; while (model) /* count models for rowspan */ { model = model->next; num_models++; } model = mfg->model; printf ("\n"); printf ("\n"); if (model->url && model->url->name) printf ("\n", model->url->name, model->name); else printf ("\n", model->name); if (model->interface) printf ("\n", model->interface); else printf ("\n"); if (model->usb_vendor_id && model->usb_product_id) printf ("\n", model->usb_vendor_id, model->usb_product_id); else printf ("\n"); printf ("\n", status_color[status], status_name[status]); if (model->comment && model->comment[0] != 0) printf ("\n", model->comment); else printf ("\n"); model = model->next; printf ("\n"); } /* while (model) */ } /* if (num_models) */ mfg = mfg->next; } /* while (mfg) */ printf ("
ManufacturerModelInterfaceUSB idStatusComment
\n", num_models); if (mfg->url && mfg->url->name) printf ("%s\n", mfg->url->name, mfg->name); else printf ("%s\n", mfg->name); while (model) { enum status_entry status = model->status; if (model != mfg->model) printf ("
%s%s%s?%s/%s %s%s 
\n"); } /* if (type->type) */ type = type->next; } /* while (type) */ be = be->next; } /* while (be) */ /* printf ("\n"); */ } /* Generate one table per manufacturer constructed of all backends */ /* providing models of type dev_type */ static void html_mfgs_table (device_type dev_type) { mfg_record_entry *mfg_record = 0, *first_mfg_record = 0; first_mfg_record = create_mfg_list (dev_type); mfg_record = first_mfg_record; printf ("

Manufacturers: \n"); while (mfg_record) { if (mfg_record != first_mfg_record) printf (", \n"); printf ("%s", html_generate_anchor_name (type_unknown, mfg_record->name), mfg_record->name); mfg_record = mfg_record->next; } mfg_record = first_mfg_record; if (!mfg_record) printf ("(none)\n"); printf ("

\n"); while (mfg_record) { model_record_entry *model_record = mfg_record->model_record; printf ("

Manufacturer: %s

\n", html_generate_anchor_name (type_unknown, mfg_record->name), mfg_record->name); printf ("

\n"); if (mfg_record->url && mfg_record->url->name) { url_entry *url = mfg_record->url; printf ("Link(s): \n"); while (url) { if (url != mfg_record->url) printf (", "); printf ("%s", url->name, url->name); url = url->next; } printf ("
\n"); } if (mfg_record->comment) printf ("Comment: %s
\n", mfg_record->comment); printf ("

\n"); if (!model_record) { mfg_record = mfg_record->next; continue; } printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); while (model_record) { enum status_entry status = model_record->status; if (model_record->url && model_record->url->name) printf ("\n", model_record->url->name, model_record->name); else printf ("\n", model_record->name); if (model_record->interface) printf ("\n", model_record->interface); else printf ("\n"); if (model_record->usb_vendor_id && model_record->usb_product_id) printf ("\n", model_record->usb_vendor_id, model_record->usb_product_id); else printf ("\n"); printf ("\n", status_color[status], status_name[status]); if (model_record->comment && model_record->comment[0] != 0) printf ("\n", model_record->comment); else printf ("\n"); printf ("\n"); if (model_record->be->manpage) printf ("\n", model_record->be->manpage, model_record->be->manpage); else printf ("\n"); printf ("\n"); model_record = model_record->next; } /* while model_record */ printf ("
ModelInterfaceUSB idStatusCommentBackendManpage
%s
%s%s?%s/%s %s%s \n"); if (model_record->be->url && model_record->be->url->name) printf ("%s\n", model_record->be->url->name, model_record->be->name); else printf ("%s", model_record->be->name); if (model_record->be->version || model_record->be->new) { printf ("
("); if (model_record->be->version) { printf ("%s", model_record->be->version); if (model_record->be->new) printf (", NEW!"); } else printf ("NEW!"); printf (")\n"); } printf ("
%s?
\n"); mfg_record = mfg_record->next; } /* while mfg_record */ } /* Print the HTML headers and an introduction */ static void html_print_header (void) { printf ("\n" " \n" "\n"); printf ("%s\n", title); printf ("\n" "\n" "
\n" "\"SANE\"\n"); printf ("

%s

\n", title); printf ("
\n" "
\n"); printf ("%s\n", intro); printf ("

This is only a summary!\n" "Please consult the manpages and the author-supplied webpages\n" "for more detailed (and usually important) information\n" "concerning each backend.

\n"); printf ("

If you have new information or corrections, please file a\n" "bug report\n" "with as many details as possible. Also please tell us if your scanner \n" "isn't mentioned in this list at all.

\n" "

For an explanation of the tables, see the\n" "legend.\n"); } /* Print the HTML footers and contact information */ static void html_print_footer (void) { time_t current_time = time (0); printf ("


\n" "SANE homepage\n" "
\n" "Contact\n" "
\n" "\n"); printf ("This page was last updated on %s by sane-desc %s from %s\n", asctime (localtime (¤t_time)), SANE_DESC_VERSION, PACKAGE_STRING); printf ("\n"); printf (" \n"); } /* print parts of the legend */ static void html_print_legend_backend (void) { printf ("
Backend:
\n" "
Name of the backend, in parentheses if available:\n" " Version of backend/driver; newer versions may be\n" " available from their home sites.
" " NEW! means brand-new to the\n" " current release of SANE.
\n" " UNMAINTAINED means that nobody maintains that backend. Expect no \n" " new features or newly supported devices. You are welcome to take over \n" " maintainership.\n" "
\n"); } static void html_print_legend_link (void) { printf ("
Link(s):
\n" "
Link(s) to more extensive and\n" " detailed information, if it exists, or the email address\n" " of the author or maintainer.\n"); } static void html_print_legend_manual (void) { printf ("
Manual Page:
\n" "
A link to the man-page online, if it exists.
\n"); } static void html_print_legend_comment (void) { printf ("
Comment:
\n" "
More information about the backend or model, e.g. the level of " " support and possible problems.
\n"); } static void html_print_legend_manufacturer (void) { printf ("
Manufacturer:
\n" "
Manufacturer, vendor or brand name of the device.
\n"); } static void html_print_legend_model (void) { printf ("
Model:
\n" "
Name of the device.
\n"); } static void html_print_legend_interface (void) { printf ("
Interface:
\n" "
How the device is connected to the computer.
\n"); } static void html_print_legend_usbid (void) { printf ("
USB id:
\n" "
The USB vendor and product ids as printed by sane-find-scanner -q (only applicable for USB devices).
\n"); } static void html_print_legend_status (void) { printf ("
Status:
\n" "
Indicates how many of the features the device provides \n" " are supported by SANE.\n" "
  • unsupported" " means the device is not supported at least by this backend. " " It may be supported by other backends, however.\n"); printf ("
  • untested means the " " device may be supported but couldn't be tested. Be very " " careful and report success/failure.\n" "
  • minimal means that the\n" " device is detected and scans at least in one mode. But the quality \n" " is bad or important features won't work.\n"); printf ("
  • basic means it works at \n" " least in the most important modes but quality is not perfect.\n" "
  • good means the device is usable \n" " for day-to-day work. Some rather exotic features may be missing.\n" "
  • complete means the backends \n" " supports everything the device can do.\n" "
\n"); } static void html_print_legend_description (void) { printf ("
Description:
\n" "
The scope of application of the backend.\n"); } /* Print the HTML page with one table of models per backend */ static void html_print_backends_split (void) { if (!title) title = "SANE: Backends (Drivers)"; if (!intro) intro = "

The following table summarizes the backends/drivers " "distributed with the latest version of sane-backends, and the hardware " "or software they support.

"; html_print_header (); html_print_summary (); printf ("

Scanners

\n"); html_backends_split_table (type_scanner); printf ("

Still Cameras

\n"); html_backends_split_table (type_stillcam); printf ("

Video Cameras

\n"); html_backends_split_table (type_vidcam); printf ("

APIs

\n"); html_backends_split_table (type_api); printf ("

Meta Backends

\n"); html_backends_split_table (type_meta); printf ("

Legend:

\n" "
\n"); html_print_legend_backend (); html_print_legend_link (); html_print_legend_manual (); html_print_legend_comment (); html_print_legend_manufacturer (); html_print_legend_model (); html_print_legend_interface (); html_print_legend_usbid (); html_print_legend_status (); html_print_legend_description (); printf ("
\n"); html_print_footer (); } /* Print the HTML page with one table of models per manufacturer */ static void html_print_mfgs (void) { if (!title) title = "SANE: Supported Devices"; if (!intro) intro = "

The following table summarizes the devices supported " "by the latest version of sane-backends.

"; html_print_header (); html_print_summary (); printf ("

Scanners

\n"); html_mfgs_table (type_scanner); printf ("

Still Cameras

\n"); html_mfgs_table (type_stillcam); printf ("

Video Cameras

\n"); html_mfgs_table (type_vidcam); printf ("

APIs

\n"); html_backends_split_table (type_api); printf ("

Meta Backends

\n"); html_backends_split_table (type_meta); printf ("

Legend:

\n" "
\n" "
\n"); html_print_legend_model (); html_print_legend_interface (); html_print_legend_usbid (); html_print_legend_status (); html_print_legend_comment (); html_print_legend_backend (); html_print_legend_manual (); html_print_legend_manufacturer (); html_print_legend_description (); printf ("
\n" "
\n"); html_print_footer (); } /* print statistics about supported devices */ static void print_statistics_per_type (device_type dev_type) { statistics_type num = {0, 0, 0, 0, 0, 0, 0}; calculate_statistics_per_type (dev_type, num); printf (" Total: %4d\n", num[status_minimal] + num[status_basic] + num[status_good] + num[status_complete] + num[status_untested] + num[status_untested] + num[status_unsupported]); if (dev_type == type_scanner || dev_type == type_stillcam || dev_type == type_vidcam) { printf (" Supported: %4d (complete: %d, good: %d, basic: %d, " "minimal: %d)\n", num[status_minimal] + num[status_basic] + num[status_good] + num[status_complete], num[status_complete], num[status_good], num[status_basic], num[status_minimal]); printf (" Untested: %4d\n", num[status_untested]); printf (" Unsupported: %4d\n", num[status_unsupported]); } } static void print_statistics (void) { printf ("Number of known devices:\n"); printf ("Scanners:\n"); print_statistics_per_type (type_scanner); printf ("Still cameras:\n"); print_statistics_per_type (type_stillcam); printf ("Video cameras:\n"); print_statistics_per_type (type_vidcam); printf ("Meta backends:\n"); print_statistics_per_type (type_meta); printf ("API backends:\n"); print_statistics_per_type (type_api); } static usbid_type * create_usbid (char *manufacturer, char *model, char *usb_vendor_id, char *usb_product_id) { usbid_type * usbid = calloc (1, sizeof (usbid_type)); usbid->usb_vendor_id = strdup (usb_vendor_id); usbid->usb_product_id = strdup (usb_product_id); usbid->name = calloc (1, sizeof (manufacturer_model_type)); usbid->name->name = calloc (1, strlen (manufacturer) + strlen (model) + 3); sprintf (usbid->name->name, "%s %s", manufacturer, model); usbid->name->next = 0; usbid->next = 0; DBG_DBG ("New USB ids: %s/%s (%s %s)\n", usb_vendor_id, usb_product_id, manufacturer, model); return usbid; } static scsiid_type * create_scsiid (char *manufacturer, char *model, char *scsi_vendor_id, char *scsi_product_id, SANE_Bool is_processor) { scsiid_type * scsiid = calloc (1, sizeof (scsiid_type)); scsiid->scsi_vendor_id = strdup (scsi_vendor_id); scsiid->scsi_product_id = strdup (scsi_product_id); scsiid->is_processor = is_processor; scsiid->name = calloc (1, sizeof (manufacturer_model_type)); scsiid->name->name = calloc (1, strlen (manufacturer) + strlen (model) + 3); sprintf (scsiid->name->name, "%s %s", manufacturer, model); scsiid->name->next = 0; scsiid->next = 0; DBG_DBG ("New SCSI ids: %s/%s (%s %s)\n", scsi_vendor_id, scsi_product_id, manufacturer, model); return scsiid; } static usbid_type * add_usbid (usbid_type *first_usbid, char *manufacturer, char *model, char *usb_vendor_id, char *usb_product_id) { usbid_type *usbid = first_usbid; usbid_type *prev_usbid = 0, *tmp_usbid = 0; if (!first_usbid) first_usbid = create_usbid (manufacturer, model, usb_vendor_id, usb_product_id); else { while (usbid) { if (strcmp (usb_vendor_id, usbid->usb_vendor_id) == 0 && strcmp (usb_product_id, usbid->usb_product_id) == 0) { manufacturer_model_type *man_mod = usbid->name; while (man_mod->next) man_mod = man_mod->next; man_mod->next = malloc (sizeof (manufacturer_model_type)); man_mod->next->name = malloc (strlen (manufacturer) + strlen (model) + 3); sprintf (man_mod->next->name, "%s %s", manufacturer, model); man_mod->next->next = 0; DBG_DBG ("Added manufacturer/model %s %s to USB ids %s/%s\n", manufacturer, model, usb_vendor_id, usb_product_id); break; } if (strcmp (usb_vendor_id, usbid->usb_vendor_id) < 0 || (strcmp (usb_vendor_id, usbid->usb_vendor_id) == 0 && strcmp (usb_product_id, usbid->usb_product_id) < 0)) { tmp_usbid = create_usbid (manufacturer, model, usb_vendor_id, usb_product_id); tmp_usbid->next = usbid; if (prev_usbid) prev_usbid->next = tmp_usbid; else first_usbid = tmp_usbid; break; } prev_usbid = usbid; usbid = usbid->next; } if (!usbid) { prev_usbid->next = create_usbid (manufacturer, model, usb_vendor_id, usb_product_id); usbid = prev_usbid->next; } } return first_usbid; } static scsiid_type * add_scsiid (scsiid_type *first_scsiid, char *manufacturer, char *model, char *scsi_vendor_id, char *scsi_product_id, SANE_Bool is_processor) { scsiid_type *scsiid = first_scsiid; scsiid_type *prev_scsiid = 0, *tmp_scsiid = 0; if (!first_scsiid) first_scsiid = create_scsiid (manufacturer, model, scsi_vendor_id, scsi_product_id, is_processor); else { while (scsiid) { if (strcmp (scsi_vendor_id, scsiid->scsi_vendor_id) == 0 && strcmp (scsi_product_id, scsiid->scsi_product_id) == 0) { manufacturer_model_type *man_mod = scsiid->name; while (man_mod->next) man_mod = man_mod->next; man_mod->next = malloc (sizeof (manufacturer_model_type)); man_mod->next->name = malloc (strlen (manufacturer) + strlen (model) + 3); sprintf (man_mod->next->name, "%s %s", manufacturer, model); man_mod->next->next = 0; DBG_DBG ("Added manufacturer/model %s %s to SCSI ids %s/%s\n", manufacturer, model, scsi_vendor_id, scsi_product_id); break; } if (strcmp (scsi_vendor_id, scsiid->scsi_vendor_id) < 0 || (strcmp (scsi_vendor_id, scsiid->scsi_vendor_id) == 0 && strcmp (scsi_product_id, scsiid->scsi_product_id) < 0)) { tmp_scsiid = create_scsiid (manufacturer, model, scsi_vendor_id, scsi_product_id, is_processor); tmp_scsiid->next = scsiid; if (prev_scsiid) prev_scsiid->next = tmp_scsiid; else first_scsiid = tmp_scsiid; break; } prev_scsiid = scsiid; scsiid = scsiid->next; } if (!scsiid) { prev_scsiid->next = create_scsiid (manufacturer, model, scsi_vendor_id, scsi_product_id, is_processor); scsiid = prev_scsiid->next; } } return first_scsiid; } static usbid_type * create_usbids_table (void) { backend_entry *be; usbid_type *first_usbid = NULL; if (!first_backend) return NULL; for (be = first_backend; be; be = be->next) { type_entry *type; if (!be->type) continue; for (type = be->type; type; type = type->next) { mfg_entry *mfg; if (!type->mfg) continue; for (mfg = type->mfg; mfg; mfg = mfg->next) { model_entry *model; if (!mfg->model) continue; for (model = mfg->model; model; model = model->next) { if ((model->status == status_unsupported) || (model->status == status_unknown)) continue; if (model->usb_vendor_id && model->usb_product_id) { first_usbid = add_usbid (first_usbid, mfg->name, model->name, model->usb_vendor_id, model->usb_product_id); } } /* for (model) */ } /* for (mfg) */ } /* for (type) */ } /* for (be) */ return first_usbid; } static scsiid_type * create_scsiids_table (void) { backend_entry *be; scsiid_type *first_scsiid = NULL; if (!first_backend) return NULL; for (be = first_backend; be; be = be->next) { type_entry *type; if (!be->type) continue; for (type = be->type; type; type = type->next) { mfg_entry *mfg; if (!type->mfg) continue; for (mfg = type->mfg; mfg; mfg = mfg->next) { model_entry *model; if (!mfg->model) continue; for (model = mfg->model; model; model = model->next) { if ((model->status == status_unsupported) || (model->status == status_unknown)) continue; if (model->scsi_vendor_id && model->scsi_product_id) { first_scsiid = add_scsiid (first_scsiid, mfg->name, model->name, model->scsi_vendor_id, model->scsi_product_id, model->scsi_is_processor); } } /* for (model) */ } /* for (mfg) */ } /* for (type) */ } /* for (be) */ return first_scsiid; } /* print USB usermap file to be used by the hotplug tools */ static void print_usermap_header (void) { time_t current_time = time (0); printf ("# This file was automatically created based on description files (*.desc)\n" "# by sane-desc %s from %s on %s" "#\n" , SANE_DESC_VERSION, PACKAGE_STRING, asctime (localtime (¤t_time))); printf ("# The entries below are used to detect a USB device and change owner\n" "# and permissions on the \"device node\" used by libusb.\n" "#\n" "# The 0x0003 match flag means the device is matched by its vendor and\n" "# product IDs.\n" "#\n" "# Sample entry (replace 0xVVVV and 0xPPPP with vendor ID and product ID\n" "# respectively):\n" "#\n" ); printf ("# libusbscanner 0x0003 0xVVVV 0xPPPP 0x0000 0x0000 0x00 0x00 0x00 0x00 " "0x00 0x00 0x00000000\n" "# usb module match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi " "bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass " "bInterfaceSubClass bInterfaceProtocol driver_info\n" "#\n" ); printf ("# If your scanner isn't listed below, you can add it as explained above.\n" "#\n" "# If your scanner is supported by some external backend (brother, epkowa,\n" "# hpaio, etc) please ask the author of the backend to provide proper\n" "# device detection support for your OS\n" "#\n" "# If the scanner is supported by sane-backends, please mail the entry to\n" "# the sane-devel mailing list (sane-devel@lists.alioth.debian.org).\n" "#\n" ); } static void print_usermap (void) { usbid_type *usbid = create_usbids_table (); print_usermap_header (); while (usbid) { manufacturer_model_type * name = usbid->name; printf ("# "); while (name) { if (name != usbid->name) printf (" | "); printf ("%s", name->name); name = name->next; } printf ("\n"); printf ("libusbscanner 0x0003 %s %s ", usbid->usb_vendor_id, usbid->usb_product_id); printf ("0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000\n"); usbid = usbid->next; } } /* print libsane.db file for hotplug-ng */ static void print_db_header (void) { time_t current_time = time (0); printf ("# This file was automatically created based on description files (*.desc)\n" "# by sane-desc %s from %s on %s", SANE_DESC_VERSION, PACKAGE_STRING, asctime (localtime (¤t_time))); printf ("#\n" "# The entries below are used to detect a USB device when it's plugged in\n" "# and then run a script to change the ownership and\n" "# permissions on the \"device node\" used by libusb.\n" "# Sample entry (replace 0xVVVV and 0xPPPP with vendor ID and product ID\n" "# respectively):\n"); printf ("#\n" "# 0xVVVV0xPPPP%s:%s%s[/usr/local/bin/foo.sh]\n" "# Fields:\n" "# vendor ID\n" "# product ID\n" "# ownership (user:group)\n" "# permissions\n" "# path of an optional script to run (it can be omitted)\n" "#\n" , DEVOWNER, DEVGROUP, DEVMODE); printf ("# If your scanner isn't listed below, you can add it as explained above.\n" "#\n" "# If your scanner is supported by some external backend (brother, epkowa,\n" "# hpaio, etc) please ask the author of the backend to provide proper\n" "# device detection support for your OS\n" "#\n" "# If the scanner is supported by sane-backends, please mail the entry to\n" "# the sane-devel mailing list (sane-devel@lists.alioth.debian.org).\n" "#\n" ); } static void print_db (void) { usbid_type *usbid = create_usbids_table (); print_db_header (); while (usbid) { manufacturer_model_type * name = usbid->name; printf ("# "); while (name) { if (name != usbid->name) printf (" | "); printf ("%s", name->name); name = name->next; } printf ("\n"); printf ("%s\t%s\t%s:%s\t%s\t\n", usbid->usb_vendor_id, usbid->usb_product_id, DEVOWNER, DEVGROUP, DEVMODE); usbid = usbid->next; } } /* print libsane.rules for Linux udev */ static void print_udev_header (void) { time_t current_time = time (0); printf ("# This file was automatically created based on description files (*.desc)\n" "# by sane-desc %s from %s on %s", SANE_DESC_VERSION, PACKAGE_STRING, asctime (localtime (¤t_time))); printf ("#\n" "# udev rules file for supported USB and SCSI devices\n" "#\n" "# The SCSI device support is very basic and includes only\n" "# scanners that mark themselves as type \"scanner\" or\n" "# SCSI-scanners from HP and other vendors that are entitled \"processor\"\n" "# but are treated accordingly.\n" "#\n"); printf ("# To add a USB device, add a rule to the list below between the\n" "# LABEL=\"libsane_usb_rules_begin\" and LABEL=\"libsane_usb_rules_end\" lines.\n" "#\n" "# To run a script when your device is plugged in, add RUN+=\"/path/to/script\"\n" "# to the appropriate rule.\n" "#\n" ); printf ("# If your scanner isn't listed below, you can add it as explained above.\n" "#\n" "# If your scanner is supported by some external backend (brother, epkowa,\n" "# hpaio, etc) please ask the author of the backend to provide proper\n" "# device detection support for your OS\n" "#\n" "# If the scanner is supported by sane-backends, please mail the entry to\n" "# the sane-devel mailing list (sane-devel@lists.alioth.debian.org).\n" "#\n" ); } static void print_udev (void) { usbid_type *usbid = create_usbids_table (); scsiid_type *scsiid = create_scsiids_table (); int i; print_udev_header (); printf("ACTION!=\"add\", GOTO=\"libsane_rules_end\"\n" "ENV{DEVTYPE}==\"usb_device\", GOTO=\"libsane_create_usb_dev\"\n" "SUBSYSTEMS==\"scsi\", GOTO=\"libsane_scsi_rules_begin\"\n" "SUBSYSTEM==\"usb_device\", GOTO=\"libsane_usb_rules_begin\"\n" "SUBSYSTEM!=\"usb_device\", GOTO=\"libsane_usb_rules_end\"\n" "\n"); printf("# Kernel >= 2.6.22 jumps here\n" "LABEL=\"libsane_create_usb_dev\"\n" "\n"); printf("# For Linux >= 2.6.22 without CONFIG_USB_DEVICE_CLASS=y\n" "# If the following rule does not exist on your system yet, uncomment it\n" "# ENV{DEVTYPE}==\"usb_device\", " "MODE=\"0664\", OWNER=\"root\", GROUP=\"root\"\n" "\n"); printf("# Kernel < 2.6.22 jumps here\n" "LABEL=\"libsane_usb_rules_begin\"\n" "\n"); while (usbid) { manufacturer_model_type * name = usbid->name; i = 0; printf ("# "); while (name) { if ((name != usbid->name) && (i > 0)) printf (" | "); printf ("%s", name->name); name = name->next; i++; /* * Limit the number of model names on the same line to 3, * as udev cannot handle very long lines and prints a warning * message while loading the rules files. */ if ((i == 3) && (name != NULL)) { printf("\n# "); i = 0; } } printf ("\n"); if (mode == output_mode_udevacl) printf ("ATTRS{idVendor}==\"%s\", ATTRS{idProduct}==\"%s\", ENV{libsane_matched}=\"yes\"\n", usbid->usb_vendor_id + 2, usbid->usb_product_id + 2); else printf ("ATTRS{idVendor}==\"%s\", ATTRS{idProduct}==\"%s\", MODE=\"%s\", GROUP=\"%s\", ENV{libsane_matched}=\"yes\"\n", usbid->usb_vendor_id + 2, usbid->usb_product_id + 2, DEVMODE, DEVGROUP); usbid = usbid->next; } printf("\n# The following rule will disable USB autosuspend for the device\n"); printf("ENV{libsane_matched}==\"yes\", RUN+=\"/bin/sh -c 'if test -e /sys/$env{DEVPATH}/power/control; then echo on > /sys/$env{DEVPATH}/power/control; elif test -e /sys/$env{DEVPATH}/power/level; then echo on > /sys/$env{DEVPATH}/power/level; fi'\"\n"); printf ("\nLABEL=\"libsane_usb_rules_end\"\n\n"); printf ("SUBSYSTEMS==\"scsi\", GOTO=\"libsane_scsi_rules_begin\"\n"); printf ("GOTO=\"libsane_scsi_rules_end\"\n\n"); printf ("LABEL=\"libsane_scsi_rules_begin\"\n"); printf ("# Generic: SCSI device type 6 indicates a scanner\n"); if (mode == output_mode_udevacl) printf ("KERNEL==\"sg[0-9]*\", ATTRS{type}==\"6\", ENV{libsane_matched}=\"yes\"\n"); else printf ("KERNEL==\"sg[0-9]*\", ATTRS{type}==\"6\", MODE=\"%s\", GROUP=\"%s\", ENV{libsane_matched}=\"yes\"\n", DEVMODE, DEVGROUP); printf ("# Some scanners advertise themselves as SCSI device type 3\n"); printf ("# Wildcard: for some Epson SCSI scanners\n"); if (mode == output_mode_udevacl) printf ("KERNEL==\"sg[0-9]*\", ATTRS{type}==\"3\", ATTRS{vendor}==\"EPSON\", ATTRS{model}==\"SCANNER*\", ENV{libsane_matched}=\"yes\"\n"); else printf ("KERNEL==\"sg[0-9]*\", ATTRS{type}==\"3\", ATTRS{vendor}==\"EPSON\", ATTRS{model}==\"SCANNER*\", MODE=\"%s\", GROUP=\"%s\", ENV{libsane_matched}=\"yes\"\n", DEVMODE, DEVGROUP); while (scsiid) { manufacturer_model_type * name = scsiid->name; if (!scsiid->is_processor) { scsiid = scsiid->next; continue; } /* Wildcard for Epson scanners: vendor = EPSON, product = SCANNER* */ if ((strcmp(scsiid->scsi_vendor_id, "EPSON") == 0) && (strncmp(scsiid->scsi_product_id, "SCANNER", 7) == 0)) { scsiid = scsiid->next; continue; } i = 0; printf ("# "); while (name) { if ((name != scsiid->name) && (i > 0)) printf (" | "); printf ("%s", name->name); name = name->next; i++; /* * Limit the number of model names on the same line to 3, * as udev cannot handle very long lines and prints a warning * message while loading the rules files. */ if ((i == 3) && (name != NULL)) { printf("\n# "); i = 0; } } printf ("\n"); if (mode == output_mode_udevacl) printf ("KERNEL==\"sg[0-9]*\", ATTRS{type}==\"3\", ATTRS{vendor}==\"%s\", ATTRS{model}==\"%s\", ENV{libsane_matched}=\"yes\"\n", scsiid->scsi_vendor_id, scsiid->scsi_product_id); else printf ("KERNEL==\"sg[0-9]*\", ATTRS{type}==\"3\", ATTRS{vendor}==\"%s\", ATTRS{model}==\"%s\", MODE=\"%s\", GROUP=\"%s\", ENV{libsane_matched}=\"yes\"\n", scsiid->scsi_vendor_id, scsiid->scsi_product_id, DEVMODE, DEVGROUP); scsiid = scsiid->next; } printf ("LABEL=\"libsane_scsi_rules_end\"\n"); if (mode == output_mode_udevacl) printf("\nENV{libsane_matched}==\"yes\", RUN+=\"/bin/setfacl -m g:%s:rw $env{DEVNAME}\"\n", DEVGROUP); else printf ("\nENV{libsane_matched}==\"yes\", MODE=\"664\", GROUP=\"scanner\"\n"); printf ("\nLABEL=\"libsane_rules_end\"\n"); } /* print libsane.rules for Linux udev */ static void print_udevhwdb_header (void) { time_t current_time = time (0); printf ("# This file was automatically created based on description files (*.desc)\n" "# by sane-desc %s from %s on %s", SANE_DESC_VERSION, PACKAGE_STRING, asctime (localtime (¤t_time))); printf ("#\n" "# udev rules file for supported USB and SCSI devices\n" "#\n" "# For the list of supported USB devices see /usr/lib/udev/hwdb.d/20-sane.hwdb\n" "#\n" "# The SCSI device support is very basic and includes only\n" "# scanners that mark themselves as type \"scanner\" or\n" "# SCSI-scanners from HP and other vendors that are entitled \"processor\"\n" "# but are treated accordingly.\n" "#\n"); printf ("# If your SCSI scanner isn't listed below, you can add it to a new rules\n" "# file under /etc/udev/rules.d/.\n" "#\n" "# If your scanner is supported by some external backend (brother, epkowa,\n" "# hpaio, etc) please ask the author of the backend to provide proper\n" "# device detection support for your OS\n" "#\n" "# If the scanner is supported by sane-backends, please mail the entry to\n" "# the sane-devel mailing list (sane-devel@lists.alioth.debian.org).\n" "#\n" ); } static void print_udevhwdb (void) { scsiid_type *scsiid = create_scsiids_table (); int i; print_udevhwdb_header (); printf("ACTION!=\"add\", GOTO=\"libsane_rules_end\"\n\n"); printf("# The following rule will disable USB autosuspend for the device\n"); printf("ENV{DEVTYPE}==\"usb_device\", ENV{libsane_matched}==\"yes\", TEST==\"power/control\", ATTR{power/control}=\"on\"\n\n"); printf ("SUBSYSTEMS==\"scsi\", GOTO=\"libsane_scsi_rules_begin\"\n"); printf ("GOTO=\"libsane_rules_end\"\n\n"); printf ("LABEL=\"libsane_scsi_rules_begin\"\n"); printf ("KERNEL!=\"sg[0-9]*\", GOTO=\"libsane_rules_end\"\n\n"); printf ("# Generic: SCSI device type 6 indicates a scanner\n"); printf ("ATTRS{type}==\"6\", ENV{libsane_matched}=\"yes\"\n\n"); printf ("# Some scanners advertise themselves as SCSI device type 3\n\n"); printf ("# Wildcard: for some Epson SCSI scanners\n"); printf ("ATTRS{type}==\"3\", ATTRS{vendor}==\"EPSON\", ATTRS{model}==\"SCANNER*\", ENV{libsane_matched}=\"yes\"\n\n"); while (scsiid) { manufacturer_model_type * name = scsiid->name; if (!scsiid->is_processor) { scsiid = scsiid->next; continue; } /* Wildcard for Epson scanners: vendor = EPSON, product = SCANNER* */ if ((strcmp(scsiid->scsi_vendor_id, "EPSON") == 0) && (strncmp(scsiid->scsi_product_id, "SCANNER", 7) == 0)) { scsiid = scsiid->next; continue; } i = 0; printf ("# "); while (name) { if ((name != scsiid->name) && (i > 0)) printf (" | "); printf ("%s", name->name); name = name->next; i++; /* * Limit the number of model names on the same line to 3, * as udev cannot handle very long lines and prints a warning * message while loading the rules files. */ if ((i == 3) && (name != NULL)) { printf("\n# "); i = 0; } } printf ("\n"); printf ("ATTRS{type}==\"3\", ATTRS{vendor}==\"%s\", ATTRS{model}==\"%s\", ENV{libsane_matched}=\"yes\"\n\n", scsiid->scsi_vendor_id, scsiid->scsi_product_id); scsiid = scsiid->next; } printf ("\nLABEL=\"libsane_rules_end\"\n"); } /* print /usr/lib/udev/hwdb.d/20-sane.conf for Linux hwdb */ static void print_hwdb_header (void) { time_t current_time = time (0); printf ("# This file was automatically created based on description files (*.desc)\n" "# by sane-desc %s from %s on %s", SANE_DESC_VERSION, PACKAGE_STRING, asctime (localtime (¤t_time))); printf ("#\n" "# hwdb file for supported USB devices\n" "#\n"); printf ("# If your scanner isn't listed below, you can add it to a new hwdb file\n" "# under /etc/udev/hwdb.d/.\n" "#\n" "# If your scanner is supported by some external backend (brother, epkowa,\n" "# hpaio, etc) please ask the author of the backend to provide proper\n" "# device detection support for your OS\n" "#\n" "# If the scanner is supported by sane-backends, please mail the entry to\n" "# the sane-devel mailing list (sane-devel@lists.alioth.debian.org).\n" "#\n" ); } static void print_hwdb (void) { usbid_type *usbid = create_usbids_table (); char *vendor_id; char *product_id; int i,j; print_hwdb_header (); while (usbid) { manufacturer_model_type * name = usbid->name; i = 0; printf ("# "); while (name) { if ((name != usbid->name) && (i > 0)) printf (" | "); printf ("%s", name->name); name = name->next; i++; /* * Limit the number of model names on the same line to 3, * as udev cannot handle very long lines and prints a warning * message while loading the rules files. */ if ((i == 3) && (name != NULL)) { printf("\n# "); i = 0; } } printf ("\n"); vendor_id = strdup(usbid->usb_vendor_id + 2); product_id = strdup(usbid->usb_product_id + 2); for(j = 0; j < 4; j++) { vendor_id[j] = toupper(vendor_id[j]); product_id[j] = toupper(product_id[j]); } printf ("usb:v%sp%s*\n libsane_matched=yes\n\n", vendor_id, product_id); free(vendor_id); free(product_id); usbid = usbid->next; } } static void print_plist (void) { usbid_type *usbid = create_usbids_table (); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\n"); printf ("\tdevice info version\n"); printf ("\t2.0\n"); printf ("\tusb\n"); printf ("\t\n"); printf ("\t\tIOUSBDevice\n"); printf ("\t\t\n"); while (usbid) { printf ("\t\t\t\n"); printf ("\t\t\t\tdevice type\n"); printf ("\t\t\t\tscanner\n"); printf ("\t\t\t\tproduct\n"); printf ("\t\t\t\t%s\n", usbid->usb_product_id); printf ("\t\t\t\tvendor\n"); printf ("\t\t\t\t%s\n", usbid->usb_vendor_id); printf ("\t\t\t\n"); usbid = usbid->next; } printf ("\t\t\n"); printf ("\t\n"); printf ("\n"); printf ("\n"); } static void print_hal (int new) { int i; SANE_Bool in_match; char *last_vendor; scsiid_type *scsiid = create_scsiids_table (); usbid_type *usbid = create_usbids_table (); printf ("\n"); printf ("\n"); printf (" \n"); printf (" \n"); printf (" \n"); printf (" \n"); printf (" \n"); last_vendor = ""; in_match = SANE_FALSE; while (scsiid) { manufacturer_model_type * name = scsiid->name; if (!scsiid->is_processor) { scsiid = scsiid->next; continue; } if (strcmp(last_vendor, scsiid->scsi_vendor_id) != 0) { if (in_match) printf (" \n"); printf (" \n", scsiid->scsi_vendor_id); last_vendor = scsiid->scsi_vendor_id; in_match = SANE_TRUE; } printf (" \n"); printf (" \n", scsiid->scsi_product_id); printf (" scanner\n"); printf (" \n"); scsiid = scsiid->next; } if (in_match) printf (" \n"); printf (" \n"); printf (" \n"); printf (" \n"); if (new) printf (" \n"); else printf (" \n"); last_vendor = ""; in_match = SANE_FALSE; while (usbid) { manufacturer_model_type * name = usbid->name; if (strcmp(last_vendor, usbid->usb_vendor_id) != 0) { if (in_match) printf (" \n"); printf (" \n", usbid->usb_vendor_id); last_vendor = usbid->usb_vendor_id; in_match = SANE_TRUE; } i = 0; printf (" \n"); printf (" \n", usbid->usb_product_id); printf (" scanner\n"); printf (" proprietary\n"); printf (" \n"); usbid = usbid->next; } if (in_match) printf (" \n"); printf (" \n"); printf (" \n"); printf ("\n"); } int main (int argc, char **argv) { program_name = strrchr (argv[0], '/'); if (program_name) ++program_name; else program_name = argv[0]; if (!get_options (argc, argv)) return 1; if (!read_files ()) return 1; switch (mode) { case output_mode_ascii: ascii_print_backends (); break; case output_mode_xml: xml_print_backends (); break; case output_mode_html_backends_split: html_print_backends_split (); break; case output_mode_html_mfgs: html_print_mfgs (); break; case output_mode_statistics: print_statistics (); break; case output_mode_usermap: print_usermap (); break; case output_mode_db: print_db (); break; case output_mode_udev: case output_mode_udevacl: print_udev (); break; case output_mode_udevhwdb: print_udevhwdb (); break; case output_mode_hwdb: print_hwdb (); break; case output_mode_plist: print_plist (); break; case output_mode_hal: print_hal (0); break; case output_mode_halnew: print_hal (1); break; default: DBG_ERR ("Unknown output mode\n"); return 1; } return 0; } sane-backends-1.0.27/tools/Makefile.am0000664000175000017500000000534012776312542014431 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include $(USB_CFLAGS) bin_PROGRAMS = sane-find-scanner gamma4scanimage noinst_PROGRAMS = sane-desc if INSTALL_UMAX_PP_TOOLS bin_PROGRAMS += umax_pp else noinst_PROGRAMS += umax_pp endif if CROSS_COMPILING HOTPLUG = HOTPLUG_DIRS = HOTPLUG_DIR = else HOTPLUG = hal/libsane.fdi hotplug/libsane.usermap hotplug-ng/libsane.db \ udev/libsane.rules HOTPLUG_DIRS = hal hotplug hotplug-ng udev HOTPLUG_DIR = dirs endif bin_SCRIPTS = sane-config noinst_SCRIPTS = $(HOTPLUG) BUILT_SOURCES = $(HOTPLUG_DIR) CLEANFILES = $(bin_SCRIPTS) $(dist_noinst_SCRIPTS) EXTRA_DIST = check-po.awk libtool-get-dll-ext mustek600iin-off.c \ RenSaneDlls.cmd README xerox sane_find_scanner_SOURCES = sane-find-scanner.c if have_usblib sane_find_scanner_SOURCES += check-usb-chip.c endif sane_find_scanner_LDADD = ../sanei/libsanei.la ../lib/liblib.la \ $(USB_LIBS) $(IEEE1284_LIBS) $(SCSI_LIBS) \ ../backend/sane_strstatus.lo gamma4scanimage_SOURCES = gamma4scanimage.c gamma4scanimage_LDADD = $(MATH_LIB) umax_pp_SOURCES = umax_pp.c umax_pp_LDADD = ../sanei/libsanei.la ../lib/liblib.la $(MATH_LIB) \ ../backend/umax_pp_low.lo sane_desc_SOURCES = sane-desc.c sane_desc_LDADD = ../sanei/libsanei.la ../lib/liblib.la EXTRA_DIST += hotplug/README hotplug/libusbscanner EXTRA_DIST += hotplug-ng/README hotplug-ng/libsane.hotplug EXTRA_DIST += openbsd/attach openbsd/detach pkgconfigdir = @libdir@/pkgconfig pkgconfig_DATA = sane-backends.pc # When build directory is not same as source directory then any # subdirectories that targets use must be manually created (under # the build directory that is). dirs: for subdir in $(HOTPLUG_DIRS); do \ $(MKDIR_P) $$subdir || exit 1; \ done descriptions = ${top_srcdir}/doc/descriptions/*.desc ${top_srcdir}/doc/descriptions-external/*.desc hotplug/libsane.usermap: sane-desc $(descriptions) @./sane-desc -m usermap -s ${top_srcdir}/doc/descriptions:${top_srcdir}/doc/descriptions-external \ -d 1 > $@ hotplug-ng/libsane.db: sane-desc $(descriptions) @./sane-desc -m db -s ${top_srcdir}/doc/descriptions:${top_srcdir}/doc/descriptions-external \ -d 0 > $@ udev/libsane.rules: sane-desc $(descriptions) @./sane-desc -m udev -s ${top_srcdir}/doc/descriptions:${top_srcdir}/doc/descriptions-external \ -d 0 > $@ hal/libsane.fdi: sane-desc $(descriptions) @./sane-desc -m hal -s ${top_srcdir}/doc/descriptions:${top_srcdir}/doc/descriptions-external \ -d 0 > $@ clean-local: rm -f $(HOTPLUG) sane-backends-1.0.27/tools/umax_pp.c0000664000175000017500000002773212112021330014173 00000000000000/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ /* For putenv */ #define _XOPEN_SOURCE #include #include #include #include #define __MAIN__ #include "../backend/umax_pp_low.h" #include "../backend/umax_pp_mid.h" static void Usage (char *name) { fprintf (stderr, "%s [-c color_mode] [-x coord] [-y coord] [-w width] [-h height] [-g gain] [-z offset] [-d dpi] [-t level] [-s] [-p] [-l 0|1] [-a ioport_addr] [-r]\n", name); } int main (int argc, char **argv) { char dbgstr[80]; int probe = 0; int port = 0; char *name = NULL; int scan = 0; int lamp = -1; int i, fd; int found; int recover = 0; int trace = 0; int maxw, maxh; /* scanning parameters : defaults to preview (75 dpi color, full scan area) */ int gain = 0x0; int offset = 0x646; int dpi = 75; int x = 0, y = 0; int width = -1, height = -1; int color = RGB_MODE; char **ports; int rc; /* option parsing */ /* -c --color : color mode: RGB, BW, BW12, RGB12 -x : x coordinate -y : y coordinate -w --witdh : scan width -h --height : scan height -f --file : session file -p --probe : probe scanner -s --scan : scan -t --trace : execution trace -l --lamp : turn lamp on/off 1/0 -d --dpi : set scan resolution -g --gain : set RVB gain -z --offset: set offset -a --addr : io port address -n --name : ppdev device name -r : recover from previous failed scan -m --model : model revision */ i = 1; trace = 0; sanei_umax_pp_setauto (1); while (i < argc) { found = 0; if ((strcmp (argv[i], "-p") == 0) || (strcmp (argv[i], "--probe") == 0)) { probe = 1; found = 1; } if ((strcmp (argv[i], "-c") == 0) || (strcmp (argv[i], "--color") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected color mode value\n"); return 0; } color = 0; i++; found = 1; if (strcmp (argv[i], "RGB") == 0) color = RGB_MODE; if (strcmp (argv[i], "RGB12") == 0) color = RGB12_MODE; if (strcmp (argv[i], "BW") == 0) color = BW_MODE; if (strcmp (argv[i], "BW12") == 0) color = BW12_MODE; if (color == 0) { fprintf (stderr, "unexpected color mode value <%s>\n", argv[i]); fprintf (stderr, "Must be RGB, RGB12, BW, or BW12\n"); return 0; } } if (strcmp (argv[i], "-x") == 0) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected x value\n"); return 0; } x = atoi (argv[i + 1]); i++; found = 1; } if (strcmp (argv[i], "-y") == 0) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected y value\n"); return 0; } y = atoi (argv[i + 1]); i++; found = 1; } if ((strcmp (argv[i], "-w") == 0) || (strcmp (argv[i], "--witdh") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected width value\n"); return 0; } width = atoi (argv[i + 1]); i++; found = 1; } if ((strcmp (argv[i], "-h") == 0) || (strcmp (argv[i], "--height") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected height value\n"); return 0; } height = atoi (argv[i + 1]); i++; found = 1; } if ((strcmp (argv[i], "-t") == 0) || (strcmp (argv[i], "--trace") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected trace value\n"); return 0; } trace = atoi (argv[i + 1]); i++; found = 1; } if ((strcmp (argv[i], "-r") == 0) || (strcmp (argv[i], "--recover") == 0)) { recover = 1; found = 1; } if ((strcmp (argv[i], "-s") == 0) || (strcmp (argv[i], "--scan") == 0)) { scan = 1; /* we have to probe again if we scan */ probe = 1; found = 1; } if ((strcmp (argv[i], "-d") == 0) || (strcmp (argv[i], "--dpi") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected dpi value\n"); return 0; } dpi = atoi (argv[i + 1]); if ((dpi < 75) || (dpi > 1200)) { fprintf (stderr, "dpi value has to be between 75 and 1200\n"); return 0; } if ((dpi != 75) && (dpi != 150) && (dpi != 300) && (dpi != 600) && (dpi != 1200)) { fprintf (stderr, "dpi value has to be 75, 150, 300, 600 or 1200\n"); return 0; } i++; found = 1; } if ((strcmp (argv[i], "-g") == 0) || (strcmp (argv[i], "--gain") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected hex gain value ( ex: A59 )\n"); return 0; } i++; found = 1; if (strlen (argv[i]) != 3) { Usage (argv[0]); fprintf (stderr, "expected hex gain value ( ex: A59 )\n"); return 0; } gain = strtol (argv[i], NULL, 16); sanei_umax_pp_setauto (0); } if ((strcmp (argv[i], "-z") == 0) || (strcmp (argv[i], "--offset") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected hex offset value ( ex: A59 )\n"); return 0; } i++; found = 1; if (strlen (argv[i]) != 3) { Usage (argv[0]); fprintf (stderr, "expected hex offset value ( ex: A59 )\n"); return 0; } offset = strtol (argv[i], NULL, 16); } if ((strcmp (argv[i], "-n") == 0) || (strcmp (argv[i], "--name") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected device name ( ex: /dev/parport0 )\n"); return 0; } i++; found = 1; name = argv[i]; } if ((strcmp (argv[i], "-a") == 0) || (strcmp (argv[i], "--addr") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected hex io port value ( ex: 3BC )\n"); return 0; } i++; found = 1; if ((strlen (argv[i]) < 3) || (strlen (argv[i]) > 4)) { Usage (argv[0]); fprintf (stderr, "expected hex io port value ( ex: 378 )\n"); return 0; } port = strtol (argv[i], NULL, 16); } if ((strcmp (argv[i], "-l") == 0) || (strcmp (argv[i], "--lamp") == 0)) { if (i == (argc - 1)) { Usage (argv[0]); fprintf (stderr, "expected lamp value\n"); return 0; } lamp = atoi (argv[i + 1]); i++; found = 1; } if (!found) { Usage (argv[0]); fprintf (stderr, "unexpected argument <%s>\n", argv[i]); return 0; } /* next arg */ i++; } /* since we use DBG, we have to set env var */ /* according to the required trace level */ if (trace) { sprintf (dbgstr, "SANE_DEBUG_UMAX_PP_LOW=%d", trace); putenv (dbgstr); } /* no address or device given */ rc = 0; if ((name == NULL) && (port == 0)) { /* safe tests: user parallel port devices */ ports = sanei_parport_find_device (); if (ports != NULL) { i = 0; rc = 0; while ((ports[i] != NULL) && (rc != 1)) { rc = sanei_umax_pp_initPort (port, ports[i]); i++; } } /* try for direct hardware access */ if (rc != 1) { ports = sanei_parport_find_port (); i = 0; rc = 0; while ((ports[i] != NULL) && (rc != 1)) { rc = sanei_umax_pp_initPort (strtol (ports[i], NULL, 16), NULL); i++; } } if (rc != 1) { fprintf (stderr, "failed to detect a valid device or port!\n"); return 0; } } else { if (sanei_umax_pp_initPort (port, name) != 1) { if (port) fprintf (stderr, "failed to gain direct acces to port 0x%X!\n", port); else fprintf (stderr, "failed to gain acces to device %s!\n", name); return 0; } } if (trace) { printf ("UMAX 610P/1220P/2000P scanning program version 6.4 starting ...\n"); #ifdef HAVE_LINUX_PPDEV_H printf ("ppdev character device built-in.\n"); #endif #ifdef ENABLE_PARPORT_DIRECTIO printf ("direct hardware access built-in.\n"); #endif } /* scanning is the default behaviour */ if ((!scan) && (lamp < 0) && (!probe)) scan = 1; /* probe scanner */ if ((probe) || (lamp >= 0)) { printf ("Probing scanner ....\n"); if (sanei_umax_pp_probeScanner (recover) != 1) { if (recover) { sanei_umax_pp_initTransport (recover); sanei_umax_pp_endSession (); if (sanei_umax_pp_probeScanner (recover) != 1) { printf ("Recover failed ....\n"); return 0; } printf ("Recover done !\n"); } else return 0; } /* could be written better .... but it is only test */ sanei_umax_pp_endSession (); /* init transport layer */ if (sanei_umax_pp_initTransport (0) != 1) { printf ("initTransport() failed (%s:%d)\n", __FILE__, __LINE__); return 0; } i = sanei_umax_pp_checkModel (); if (i < 600) { sanei_umax_pp_endSession (); printf ("checkModel() failed (%s:%d)\n", __FILE__, __LINE__); return 0; } printf ("UMAX Astra %dP detected \n", i); /* free scanner if a scan is planned */ if (scan) sanei_umax_pp_endSession (); printf ("Done ....\n"); } /* lamp on/off: must come after probing (610p handling) */ if (lamp >= 0) { /* init transport layer */ if (trace) printf ("Tryning to set lamp %s\n", lamp ? "on" : "off"); if (sanei_umax_pp_initTransport (recover) != 1) { printf ("initTransport() failed (%s:%d)\n", __FILE__, __LINE__); return 0; } else { if (trace) printf ("initTransport passed...\n"); } if (sanei_umax_pp_setLamp (lamp) == 0) { fprintf (stderr, "Setting lamp state failed!\n"); return 0; } else { if (trace) printf ("sanei_umax_pp_setLamp passed...\n"); } } /* scan */ if (scan) { printf ("Scanning ....\n"); if (sanei_umax_pp_getastra () < 1210) { maxw = 2550; maxh = 3500; } else { maxw = 5100; maxh = 7000; } if (width < 0) width = maxw; if (height < 0) height = maxh; if ((width < 1) || (width > maxw)) { fprintf (stderr, "width must be between 1 and %d\n", maxw); return 0; } if (x + width > maxw) { fprintf (stderr, "Right side of scan area exceed physical limits (x+witdh>%d)\n", maxw); return 0; } if (y < 0 || y > maxh) { fprintf (stderr, "y must be between 0 and %d\n", maxh - 1); return 0; } if (x < 0 || x > maxw) { fprintf (stderr, "x must be between 0 and %d\n", maxw - 1); return 0; } if ((height < 1) || (height > maxh)) { fprintf (stderr, "height must be between 1 and %d\n", maxh); return 0; } if (y + height > maxh) { fprintf (stderr, "Bottom side of scan area exceed physical limits (y+height>%d)\n", maxh); return 0; } /* init transport layer */ /* 0: failed 1: success 2: retry */ do { i = sanei_umax_pp_initTransport (recover); } while (i == 2); if (i != 1) { printf ("initTransport() failed (%s:%d)\n", __FILE__, __LINE__); return 0; } /* init scanner */ if (sanei_umax_pp_initScanner (recover) == 0) { sanei_umax_pp_endSession (); return 0; } /* set x origin left to right */ x = sanei_umax_pp_getLeft () + (maxw - x) - width; /* scan */ if (sanei_umax_pp_scan (x, y, width, height, dpi, color, gain, offset) != 1) { sanei_umax_pp_endSession (); return 0; } /* wait for head parking */ sanei_umax_pp_parkWait (); printf ("Done ....\n"); } sanei_umax_pp_endSession (); #ifdef HAVE_LINUX_PPDEV_H fd = sanei_umax_pp_getparport (); if (fd > 0) { close (fd); sanei_umax_pp_setparport (0); } #endif return 1; } sane-backends-1.0.27/tools/check-po.awk0000775000175000017500000001120512775312262014570 00000000000000#!/usr/bin/gawk -f # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA. # This script will (hopefully!) check the completeness of a .po # translation file. It will report untranslated strings, as well # as fuzzy ones. It will print a summarry at the end of the check # that says how many strings there are, how many are translated # (and the percentage it represents), how many are fuzzy (and the # percentage it represents amongst translated strings), and how # many aree un-translated (and the percentage it represents). # It will _not_ tell you wether your file is syntactically correct # (eg. check for terminating double quotes!). And of course it # will _not_ tell you wether the translations are correct! ;-] # # It was originaly been written for SANE backends translations, but # shall be able to check any .po file. # # Originally writen by Yann E. MORIN # # # Output will look like : # [./src/foobar.c:2345](321)- "This is the string" # \____________/ \__/ \_/ | \________________/ # | | | | | # | | | | \-> Original untranslated string # | | | | # | | | \-> flag telling wether it is # | | | fuzzy (F) or not (-) # | | | # | | \-> line number in the .po file # | | # | \-> line number in the source file # | # \-> filename where the original string lies # # # Last four lines will look like : # Translated : 23 (23.0%) # of which : 2 fuzzy ( 8.6%) # Not translated : 77 (77.0%) # Total : 100 # # # TODO: # - Print the fuzzy translated string at the same level as the # untranslated one; # - basic checks about syntax (missing terminating double quotes); # - option for brief mode (only last four lines); # - other? BEGIN \ { count = 0; fuzzy = 0; is_fuzzy = 0; missing = 0; first = 1; } # Is this translation fuzzy? If so count it $1 == "#," && $2 ~ /^fuzzy(|,)$/ \ { fuzzy++; # Next translation will be fuzzy! is_fuzzy = 1; } $1 == "#:" \ { file = $2; } # Skip the first msgid as it is no true translation $1 ~ /msgid/ && first == 1 \ { first = 0; next; } $1 ~ /msgid/ && first == 0 \ { # One more translation count++; line = NR; # Gets the untranslated string (with double quotes :-( ) $1 = ""; original = $0; getline; while( $1 != "msgstr" ) { original = original $0 getline; } # Now extract the translated string (with double quotes as well :-( ) $1 = ""; translation = $0; # In case we have no blank line after the last translation (EOF), # we need to stop this silly loop. Allowing a 10-line message. len = 10; getline; while( $0 != "" && $0 !~ /^#/ && len != 0 ) { translation = translation $0 getline; len--; } # Remove double quotes from multi-line messages and translations msg = "" n = split( original, a, "\"" ); # start at 2 to get rid of the preceding space for( i=2; i<=n; i++ ) { msg = msg a[i]; } trans = ""; n = split( translation, a, "\"" ); # start at 2 to get rid of the preceding space for( i=2; i<=n; i++ ) { trans = trans a[i] } # Checks wether we have a translation or not, wether it is fuzzy or not if( ( trans == "" ) || ( is_fuzzy == 1 ) ) { # Enclose original messages between double quotes printf( "[%s](%d)", file, line ); if( is_fuzzy == 1 ) { printf( "F" ); } else { printf( "-" ); } printf( " \"%s\"\n", msg ); if( trans == "" ) { missing++; } } is_fuzzy = 0; } END \ { # Lines are longer than 80 chars, but I won't cut them printf( "\n" ); printf( "Translated : %4d (%4.1f%%)\n", count-missing, 100.0*(count-missing)/count ); printf( " of which : %4d fuzzy (%4.1f%%)\n", fuzzy, 100*fuzzy/(count-missing) ); printf( "Not translated : %4d (%4.1f%%)\n", missing, 100.0*missing/count ); printf( "Total : %4d\n", count ); } sane-backends-1.0.27/tools/mustek600iin-off.c0000664000175000017500000001105112112021330015513 00000000000000/* off.c - Switch the Mustek 600 II N off This utility accesses the I/O-ports directly and must therefore be run with euid root, or must at least have access to /dev/port. Compile with: gcc -DHAVE_SYS_IO_H -O2 -Wall -s -o off off.c The -O2 optimization is needed to allow inline functions ! Copyright (C) 1997-1999 Andreas Czechanowski, DL4SDC This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. andreas.czechanowski@ins.uni-stuttgart.de */ #include "../include/sane/config.h" #include "../include/sane/sanei.h" #define MUSTEK_CONF STRINGIFY(PATH_SANE_CONFIG_DIR) "/mustek.conf" #define PORT_DEV "/dev/port" #include #include #include #include #include #include #include #ifdef HAVE_SYS_IO_H # include /* use where available (glibc 2.x, for example) */ #elif HAVE_ASM_IO_H # include /* ugly, but backwards compatible */ #elif defined(__i386__) && defined (__GNUC__) static __inline__ void outb (u_char value, u_long port) { __asm__ __volatile__ ("outb %0,%1"::"a" (value), "d" ((u_short) port)); } static __inline__ u_char inb (u_long port) { u_char value; __asm__ __volatile__ ("inb %1,%0":"=a" (value):"d" ((u_short) port)); return value; } #endif char *Mustek_Conf = MUSTEK_CONF; int allowed_ports[] = { 0x26b, 0x26c, 0x2ab, 0x2ac, 0x2eb, 0x2ec, 0x22b, 0x22c, 0x32b, 0x32c, 0x36b, 0x36c, 0x3ab, 0x3ac, 0x3eb, 0x3ec, -1 }; void usage (void) { fprintf (stderr, "Usage: off [port]\n" " switches the Mustek 600 II N off that is connected to\n" " base address . If address is not given, reads it\n" " from SANE config file <%s>.\n", Mustek_Conf); } void noaccess (int portaddr) { fprintf (stderr, "Access to port 0x%03x not allowed !\n", portaddr); } int check_port (int portaddr) { int i, j; for (i = 0; (j = allowed_ports[i]) != -1; i++) { if (j == portaddr) return j; } return -1; } int str2int (char *ch) { int i; i = strtol (ch, NULL, 0); return i; } int main (int argc, char **argv) { char *cp; int portaddr = 0; FILE *fp; int pfd; /* get config file name from environment if variable is set */ if (NULL != (cp = getenv ("MUSTEK_CONF"))) { Mustek_Conf = cp; } /* if port is explicitly given, try this one */ if (argc > 1) { portaddr = str2int (argv[1]); } /* else try to look it up from SANE's mustek.conf file */ else if (NULL != (fp = fopen (MUSTEK_CONF, "r"))) { char line[256]; while (NULL != fgets (line, 255, fp)) { if ('#' == *line) continue; if (0 != (portaddr = str2int (line))) break; } fclose (fp); } else { fprintf (stderr, "Mustek config file <%s> not found\n", Mustek_Conf); usage (); exit (1); } if (check_port (portaddr) < 0 || check_port (portaddr + 1) < 0) { fprintf (stderr, "invalid port address specified !\n"); usage (); exit (1); } /* we need the control port, not the data port, so... */ portaddr++; fprintf (stderr, "using control port address 0x%03x\n", portaddr); /* try to get I/O permission from the kernel */ if (ioperm (portaddr, 1, 1) == 0) { outb (0x00, portaddr); } /* else try to open /dev/port to access the I/O port */ else if ((pfd = open (PORT_DEV, O_RDWR, 0666)) >= 0) { char offcmd[] = {0x00}; if ((lseek (pfd, portaddr, SEEK_SET) != portaddr) || (write (pfd, offcmd, 1) != 1)) { perror ("error handling /dev/port"); exit (1); } close (pfd); } else { fprintf (stderr, "Could not get port access:\n" "Neither via ioperm(), nor via /dev/port.\n" "This program must be run setuid root,\n" "or the user must have access to /dev/port.\n"); exit (1); } printf ("successfully sent OFF-command to control port at 0x%03x.\n", portaddr); exit (0); } sane-backends-1.0.27/tools/sane-backends.pc.in0000664000175000017500000000072012112021330015771 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ ldflags=@LDFLAGS@ @GPHOTO2_LDFLAGS@ libs=@LIBS@ @DL_LIBS@ @LIBV4L_LIBS@ @MATH_LIB@ @TIFF_LIBS@ @JPEG_LIBS@ @GPHOTO2_LIBS@ @SOCKET_LIBS@ @AVAHI_LIBS@ @USB_LIBS@ @SCSI_LIBS@ @RESMGR_LIBS@ Name: SANE Backends Description: Backends for SANE, the universal scanner interface Version: @VERSION@ Requires: Libs: -L${libdir} -lsane Libs.private: ${ldflags} ${libs} Cflags: -I${includedir} sane-backends-1.0.27/tools/sane-find-scanner.c0000664000175000017500000016432613106201017016024 00000000000000/* sane-find-scanner.c Copyright (C) 1997-2013 Oliver Rauch, Henning Meier-Geinitz, and others. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #if defined (HAVE_DDK_NTDDSCSI_H) || defined (HAVE_NTDDSCSI_H) # define WIN32_SCSI # include # if defined (HAVE_DDK_NTDDSCSI_H) # include # include # elif defined (HAVE_NTDDSCSI_H) # include # endif #endif #include "../include/sane/sanei.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_pa4s2.h" #include "../include/sane/sanei_config.h" #ifdef HAVE_LIBUSB_LEGACY #ifdef HAVE_LUSB0_USB_H #include #else #include #endif extern char * check_usb_chip (struct usb_device *dev, int verbosity, SANE_Bool from_file); #endif #ifdef HAVE_LIBUSB #include extern char * check_usb_chip (int verbosity, struct libusb_device_descriptor desc, libusb_device_handle *hdl, struct libusb_config_descriptor *config0); #endif #include "../include/sane/sanei_usb.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif static const char *prog_name; static int verbose = 1; static SANE_Bool force = SANE_FALSE; static SANE_Bool device_found = SANE_FALSE; static SANE_Bool libusb_device_found = SANE_FALSE; static SANE_Bool unknown_found = SANE_FALSE; #ifdef HAVE_LIBUSB libusb_context *sfs_usb_ctx; #endif typedef struct { unsigned char *cmd; size_t size; } scsiblk; #define INQUIRY 0x12 #define set_inquiry_return_size(icb,val) icb[0x04]=val #define IN_periph_devtype_cpu 0x03 #define IN_periph_devtype_scanner 0x06 #define get_scsi_inquiry_vendor(in, buf) strncpy(buf, in + 0x08, 0x08) #define get_scsi_inquiry_product(in, buf) strncpy(buf, in + 0x10, 0x010) #define get_scsi_inquiry_version(in, buf) strncpy(buf, in + 0x20, 0x04) #define get_scsi_inquiry_periph_devtype(in) (in[0] & 0x1f) #define get_scsi_inquiry_additional_length(in) in[0x04] #define set_scsi_inquiry_length(out,n) out[0x04]=n-5 static unsigned char inquiryC[] = { INQUIRY, 0x00, 0x00, 0x00, 0xff, 0x00 }; static scsiblk inquiry = { inquiryC, sizeof (inquiryC) }; static void usage (char *msg) { fprintf (stderr, "Usage: %s [-hvqf] [devname ...]\n", prog_name); fprintf (stderr, "\t-h: print this help message\n"); fprintf (stderr, "\t-v: be more verbose (can be used multiple times)\n"); fprintf (stderr, "\t-q: be quiet (print only devices, no comments)\n"); fprintf (stderr, "\t-f: force opening devname as SCSI even if it looks " "like USB\n"); fprintf (stderr, "\t-p: enable scanning for parallel port devices\n"); #ifdef HAVE_LIBUSB_LEGACY fprintf (stderr, "\t-F file: try to detect chipset from given " "/proc/bus/usb/devices file\n"); #endif if (msg) fprintf (stderr, "\t%s\n", msg); } /* if SCSI generic is optional on your OS, and there is a software test which will determine if it is included, add it here. If you are sure that SCSI generic was found, return 1. If SCSI generic is always available in your OS, return 1 */ static int check_sg (void) { #if defined(__linux__) /* Assumption: /proc/devices lines are shorter than 256 characters */ char line[256], driver[256] = ""; FILE *stream; stream = fopen ("/proc/devices", "r"); /* Likely reason for failure, no /proc => probably no SG either */ if (stream == NULL) return 0; while (fgets (line, sizeof (line) - 1, stream)) { if (sscanf (line, " %*d %s\n", driver) > 0 && !strcmp (driver, "sg")) break; } fclose (stream); if (strcmp (driver, "sg")) { return 0; } else { return 1; } #endif return 1; /* Give up, and assume yes to avoid false negatives */ } /* Display a buffer in the log. Display by lines of 16 bytes. */ static void hexdump (const char *comment, unsigned char *buf, const int length) { int i; char line[128]; char *ptr; char asc_buf[17]; char *asc_ptr; printf (" %s\n", comment); i = 0; goto start; do { if (i < length) { ptr += sprintf (ptr, " %2.2x", *buf); if (*buf >= 32 && *buf <= 127) { asc_ptr += sprintf (asc_ptr, "%c", *buf); } else { asc_ptr += sprintf (asc_ptr, "."); } } else { /* After the length; do nothing. */ ptr += sprintf (ptr, " "); } i++; buf++; if ((i % 16) == 0) { /* It's a new line */ printf (" %s %s\n", line, asc_buf); start: ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; ptr += sprintf (ptr, " %3.3d:", i); } } while (i < ((length + 15) & ~15)); } static SANE_Status scanner_do_scsi_inquiry (unsigned char *buffer, int sfd) { size_t size; SANE_Status status; memset (buffer, '\0', 256); /* clear buffer */ size = 5; /* first get only 5 bytes to get size of inquiry_return_block */ set_inquiry_return_size (inquiry.cmd, size); status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size); if (status != SANE_STATUS_GOOD) return (status); size = get_scsi_inquiry_additional_length (buffer) + 5; /* then get inquiry with actual size */ set_inquiry_return_size (inquiry.cmd, size); status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size); return (status); } static void scanner_identify_scsi_scanner (unsigned char *buffer, int sfd, char *devicename) { unsigned char vendor[9]; unsigned char product[17]; unsigned char version[5]; unsigned char *pp; unsigned int devtype; SANE_Status status; static char *devtypes[] = { "disk", "tape", "printer", "processor", "CD-writer", "CD-drive", "scanner", "optical-drive", "jukebox", "communicator" }; status = scanner_do_scsi_inquiry (buffer, sfd); if (status != SANE_STATUS_GOOD) { if (verbose > 1) printf ("inquiry for device %s failed (%s)\n", devicename, sane_strstatus (status)); return; } if (verbose > 2) hexdump ("Inquiry for device:", buffer, get_scsi_inquiry_additional_length (buffer) + 5); devtype = get_scsi_inquiry_periph_devtype (buffer); if (verbose <= 1 && devtype != IN_periph_devtype_scanner /* old HP scanners use the CPU id ... */ && devtype != IN_periph_devtype_cpu) return; /* no, continue searching */ get_scsi_inquiry_vendor ((char *) buffer, (char *) vendor); get_scsi_inquiry_product ((char *) buffer, (char *) product); get_scsi_inquiry_version ((char *) buffer, (char *) version); pp = &vendor[7]; vendor[8] = '\0'; while (pp >= vendor && (*pp == ' ' || *pp >= 127)) *pp-- = '\0'; pp = &product[15]; product[16] = '\0'; while (pp >= product && (*pp == ' ' || *pp >= 127)) *pp-- = '\0'; pp = &version[3]; version[4] = '\0'; while (pp >= version && (*pp == ' ' || *(pp - 1) >= 127)) *pp-- = '\0'; device_found = SANE_TRUE; printf ("found SCSI %s \"%s %s %s\" at %s\n", devtype < NELEMS (devtypes) ? devtypes[devtype] : "unknown device", vendor, product, version, devicename); return; } static void check_scsi_file (char *file_name) { int result; int sfd; unsigned char buffer[16384]; if (strstr (file_name, "usb") || strstr (file_name, "uscanner") || strstr (file_name, "ugen")) { if (force) { if (verbose > 1) printf ("checking %s even though it looks like a USB device...", file_name); } else { if (verbose > 1) printf ("ignored %s (not a SCSI device)\n", file_name); return; } } else if (verbose > 1) printf ("checking %s...", file_name); result = sanei_scsi_open (file_name, &sfd, NULL, NULL); if (verbose > 1) { if (result != 0) printf (" failed to open (%s)\n", sane_strstatus (result)); else printf (" open ok\n"); } if (result == SANE_STATUS_GOOD) { scanner_identify_scsi_scanner (buffer, sfd, file_name); sanei_scsi_close (sfd); } return; } static void check_usb_file (char *file_name) { SANE_Status result; SANE_Word vendor, product; SANE_Int fd; if (!strstr (file_name, "usb") && !strstr (file_name, "uscanner") && !strstr (file_name, "ugen")) { if (force) { if (verbose > 1) printf ("checking %s even though doesn't look like a " "USB device...", file_name); } else { if (verbose > 1) printf ("ignored %s (not a USB device)\n", file_name); return; } } else if (verbose > 1) printf ("checking %s...", file_name); result = sanei_usb_open (file_name, &fd); if (result != SANE_STATUS_GOOD) { if (verbose > 1) printf (" failed to open (%s)\n", sane_strstatus (result)); } else { result = sanei_usb_get_vendor_product (fd, &vendor, &product); if (result == SANE_STATUS_GOOD) { if (verbose > 1) printf (" open ok, vendor and product ids were identified\n"); printf ("found USB scanner (vendor=0x%04x, " "product=0x%04x) at %s\n", vendor, product, file_name); } else { if (verbose > 1) printf (" open ok, but vendor and product could NOT be " "identified\n"); printf ("found USB scanner (UNKNOWN vendor and product) " "at device %s\n", file_name); unknown_found = SANE_TRUE; } device_found = SANE_TRUE; sanei_usb_close (fd); } } #ifdef HAVE_LIBUSB_LEGACY static char * get_libusb_string_descriptor (struct usb_device *dev, int index) { usb_dev_handle *handle; char *buffer, short_buffer[2]; struct usb_string_descriptor *sd; int size = 2; int i; if (!index) return 0; handle = usb_open (dev); if (!handle) return 0; sd = (struct usb_string_descriptor *) short_buffer; if (usb_control_msg (handle, USB_ENDPOINT_IN + USB_TYPE_STANDARD + USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0, short_buffer, size, 1000) < 0) { usb_close (handle); return 0; } if (sd->bLength < 2 || sd->bDescriptorType != USB_DT_STRING) { usb_close (handle); return 0; } size = sd->bLength; buffer = calloc (1, size + 1); if (!buffer) return 0; sd = (struct usb_string_descriptor *) buffer; if (usb_control_msg (handle, USB_ENDPOINT_IN + USB_TYPE_STANDARD + USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0, buffer, size, 1000) < 0) { usb_close (handle); free (buffer); return 0; } if (sd->bLength < 2 || sd->bLength > size || sd->bDescriptorType != USB_DT_STRING) { usb_close (handle); free (buffer); return 0; } size = sd->bLength - 2; for (i = 0; i < (size / 2); i++) buffer[i] = buffer[2 + 2 * i]; buffer[i] = 0; usb_close (handle); return buffer; } static char * get_libusb_vendor (struct usb_device *dev) { return get_libusb_string_descriptor (dev, dev->descriptor.iManufacturer); } static char * get_libusb_product (struct usb_device *dev) { return get_libusb_string_descriptor (dev, dev->descriptor.iProduct); } static void check_libusb_device (struct usb_device *dev, SANE_Bool from_file) { int is_scanner = 0; char *vendor; char *product; int interface_nr; if (!dev->config) { if (verbose > 1) printf ("device 0x%04x/0x%04x is not configured\n", dev->descriptor.idVendor, dev->descriptor.idProduct); return; } vendor = get_libusb_vendor (dev); product = get_libusb_product (dev); if (verbose > 2) { /* print everything we know about the device */ char *buf; int config_nr; struct usb_device_descriptor *d = &dev->descriptor; printf ("\n"); printf ("idVendor, d->idProduct, dev->bus->dirname, dev->filename); if (vendor || product) { printf (" (%s%s%s)", vendor ? vendor : "", (vendor && product) ? " " : "", product ? product : ""); } printf (">\n"); printf ("bLength %d\n", d->bLength); printf ("bDescriptorType %d\n", d->bDescriptorType); printf ("bcdUSB %d.%d%d\n", d->bcdUSB >> 8, (d->bcdUSB >> 4) & 15, d->bcdUSB & 15); printf ("bDeviceClass %d\n", d->bDeviceClass); printf ("bDeviceSubClass %d\n", d->bDeviceSubClass); printf ("bDeviceProtocol %d\n", d->bDeviceProtocol); printf ("bMaxPacketSize0 %d\n", d->bMaxPacketSize0); printf ("idVendor 0x%04X\n", d->idVendor); printf ("idProduct 0x%04X\n", d->idProduct); printf ("bcdDevice %d.%d%d\n", d->bcdDevice >> 8, (d->bcdDevice >> 4) & 15, d->bcdDevice & 15); printf ("iManufacturer %d (%s)\n", d->iManufacturer, (vendor) ? vendor : ""); printf ("iProduct %d (%s)\n", d->iProduct, (product) ? product : ""); buf = get_libusb_string_descriptor (dev, d->iSerialNumber); printf ("iSerialNumber %d (%s)\n", d->iSerialNumber, (buf) ? buf : ""); if (buf) free (buf); printf ("bNumConfigurations %d\n", d->bNumConfigurations); for (config_nr = 0; config_nr < d->bNumConfigurations; config_nr++) { struct usb_config_descriptor *c = &dev->config[config_nr]; int interface_nr; printf (" \n", config_nr); printf (" bLength %d\n", c->bLength); printf (" bDescriptorType %d\n", c->bDescriptorType); printf (" wTotalLength %d\n", c->wTotalLength); printf (" bNumInterfaces %d\n", c->bNumInterfaces); printf (" bConfigurationValue %d\n", c->bConfigurationValue); buf = get_libusb_string_descriptor (dev, c->iConfiguration); printf (" iConfiguration %d (%s)\n", c->iConfiguration, (buf) ? buf : ""); if (buf) free (buf); printf (" bmAttributes %d (%s%s)\n", c->bmAttributes, c->bmAttributes & 64 ? "Self-powered" : "", c->bmAttributes & 32 ? "Remote Wakeup" : ""); printf (" MaxPower %d mA\n", c->MaxPower * 2); for (interface_nr = 0; interface_nr < c->bNumInterfaces; interface_nr++) { struct usb_interface *interface = &c->interface[interface_nr]; int alt_setting_nr; printf (" \n", interface_nr); for (alt_setting_nr = 0; alt_setting_nr < interface->num_altsetting; alt_setting_nr++) { struct usb_interface_descriptor *i = &interface->altsetting[alt_setting_nr]; int ep_nr; printf (" \n", alt_setting_nr); printf (" bLength %d\n", i->bLength); printf (" bDescriptorType %d\n", i->bDescriptorType); printf (" bInterfaceNumber %d\n", i->bInterfaceNumber); printf (" bAlternateSetting %d\n", i->bAlternateSetting); printf (" bNumEndpoints %d\n", i->bNumEndpoints); printf (" bInterfaceClass %d\n", i->bInterfaceClass); printf (" bInterfaceSubClass %d\n", i->bInterfaceSubClass); printf (" bInterfaceProtocol %d\n", i->bInterfaceProtocol); buf = get_libusb_string_descriptor (dev, i->iInterface); printf (" iInterface %d (%s)\n", i->iInterface, (buf) ? buf : ""); if (buf) free (buf); for (ep_nr = 0; ep_nr < i->bNumEndpoints; ep_nr++) { struct usb_endpoint_descriptor *e = &i->endpoint[ep_nr]; char *ep_type; switch (e->bmAttributes & USB_ENDPOINT_TYPE_MASK) { case USB_ENDPOINT_TYPE_CONTROL: ep_type = "control"; break; case USB_ENDPOINT_TYPE_ISOCHRONOUS: ep_type = "isochronous"; break; case USB_ENDPOINT_TYPE_BULK: ep_type = "bulk"; break; case USB_ENDPOINT_TYPE_INTERRUPT: ep_type = "interrupt"; break; default: ep_type = "unknown"; break; } printf (" \n", ep_nr); printf (" bLength %d\n", e->bLength); printf (" bDescriptorType %d\n", e->bDescriptorType); printf (" bEndpointAddress 0x%02X (%s 0x%02X)\n", e->bEndpointAddress, e->bEndpointAddress & USB_ENDPOINT_DIR_MASK ? "in" : "out", e-> bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK); printf (" bmAttributes %d (%s)\n", e->bmAttributes, ep_type); printf (" wMaxPacketSize %d\n", e->wMaxPacketSize); printf (" bInterval %d ms\n", e->bInterval); printf (" bRefresh %d\n", e->bRefresh); printf (" bSynchAddress %d\n", e->bSynchAddress); } } } } } /* Some heuristics, which device may be a scanner */ if (dev->descriptor.idVendor == 0) /* hub */ --is_scanner; if (dev->descriptor.idProduct == 0) /* hub */ --is_scanner; for (interface_nr = 0; interface_nr < dev->config[0].bNumInterfaces && is_scanner <= 0; interface_nr++) { switch (dev->descriptor.bDeviceClass) { case USB_CLASS_VENDOR_SPEC: ++is_scanner; break; case USB_CLASS_PER_INTERFACE: if (dev->config[0].interface[interface_nr].num_altsetting == 0 || !dev->config[0].interface[interface_nr].altsetting) break; switch (dev->config[0].interface[interface_nr].altsetting[0].bInterfaceClass) { case USB_CLASS_VENDOR_SPEC: case USB_CLASS_PER_INTERFACE: case 16: /* data? */ ++is_scanner; break; } break; } } if (is_scanner > 0) { char * chipset = check_usb_chip (dev, verbose, from_file); printf ("found USB scanner (vendor=0x%04x", dev->descriptor.idVendor); if (vendor) printf (" [%s]", vendor); printf (", product=0x%04x", dev->descriptor.idProduct); if (product) printf (" [%s]", product); if (chipset) printf (", chip=%s", chipset); if (from_file) printf (")\n"); else printf (") at libusb:%s:%s\n", dev->bus->dirname, dev->filename); libusb_device_found = SANE_TRUE; device_found = SANE_TRUE; } if (vendor) free (vendor); if (product) free (product); } #endif /* HAVE_LIBUSB_LEGACY */ #ifdef HAVE_LIBUSB static char * sfs_libusb_strerror (int errcode) { /* Error codes & descriptions from the libusb-1.0 documentation */ switch (errcode) { case LIBUSB_SUCCESS: return "Success (no error)"; case LIBUSB_ERROR_IO: return "Input/output error"; case LIBUSB_ERROR_INVALID_PARAM: return "Invalid parameter"; case LIBUSB_ERROR_ACCESS: return "Access denied (insufficient permissions)"; case LIBUSB_ERROR_NO_DEVICE: return "No such device (it may have been disconnected)"; case LIBUSB_ERROR_NOT_FOUND: return "Entity not found"; case LIBUSB_ERROR_BUSY: return "Resource busy"; case LIBUSB_ERROR_TIMEOUT: return "Operation timed out"; case LIBUSB_ERROR_OVERFLOW: return "Overflow"; case LIBUSB_ERROR_PIPE: return "Pipe error"; case LIBUSB_ERROR_INTERRUPTED: return "System call interrupted (perhaps due to signal)"; case LIBUSB_ERROR_NO_MEM: return "Insufficient memory"; case LIBUSB_ERROR_NOT_SUPPORTED: return "Operation not supported or unimplemented on this platform"; case LIBUSB_ERROR_OTHER: return "Other error"; default: return "Unknown libusb-1.0 error code"; } } static char * get_libusb_string_descriptor (libusb_device_handle *hdl, int index) { unsigned char *buffer, short_buffer[2]; int size; int ret; int i; if (!index) return NULL; ret = libusb_get_descriptor (hdl, LIBUSB_DT_STRING, index, short_buffer, sizeof (short_buffer)); if (ret < 0) { printf ("could not fetch string descriptor: %s\n", sfs_libusb_strerror (ret)); return NULL; } if ((short_buffer[0] < 2) /* descriptor length */ || (short_buffer[1] != LIBUSB_DT_STRING)) /* descriptor type */ return NULL; size = short_buffer[0]; buffer = calloc (1, size + 1); if (!buffer) return NULL; ret = libusb_get_descriptor (hdl, LIBUSB_DT_STRING, index, buffer, size); if (ret < 0) { printf ("could not fetch string descriptor (again): %s\n", sfs_libusb_strerror (ret)); free (buffer); return NULL; } if ((buffer[0] < 2) || (buffer[0] > size) /* descriptor length */ || (buffer[1] != LIBUSB_DT_STRING)) /* descriptor type */ { free (buffer); return NULL; } size = buffer[0] - 2; for (i = 0; i < (size / 2); i++) buffer[i] = buffer[2 + 2 * i]; buffer[i] = '\0'; return (char *) buffer; } static void check_libusb_device (libusb_device *dev, SANE_Bool from_file) { libusb_device_handle *hdl; struct libusb_device_descriptor desc; struct libusb_config_descriptor *config0; int is_scanner = 0; char *vendor; char *product; unsigned short vid, pid; unsigned char busno, address; int config; int intf; int ret; busno = libusb_get_bus_number (dev); address = libusb_get_device_address (dev); ret = libusb_get_device_descriptor (dev, &desc); if (ret < 0) { printf ("could not get device descriptor for device at %03d:%03d: %s\n", busno, address, sfs_libusb_strerror (ret)); return; } vid = desc.idVendor; pid = desc.idProduct; ret = libusb_open (dev, &hdl); if (ret < 0) { printf ("could not open USB device 0x%04x/0x%04x at %03d:%03d: %s\n", vid, pid, busno, address, sfs_libusb_strerror (ret)); return; } ret = libusb_get_configuration (hdl, &config); if (ret < 0) { printf ("could not get configuration for device 0x%04x/0x%04x at %03d:%03d: %s\n", vid, pid, busno, address, sfs_libusb_strerror (ret)); libusb_close (hdl); return; } if (config == 0) { if (verbose > 1) printf ("device 0x%04x/0x%04x at %03d:%03d is not configured\n", vid, pid, busno, address); libusb_close (hdl); return; } vendor = get_libusb_string_descriptor (hdl, desc.iManufacturer); product = get_libusb_string_descriptor (hdl, desc.iProduct); if (verbose > 2) { /* print everything we know about the device */ char *buf; int config_nr; printf ("\n"); printf ("\n"); printf ("bLength %d\n", desc.bLength); printf ("bDescriptorType %d\n", desc.bDescriptorType); printf ("bcdUSB %d.%d%d\n", desc.bcdUSB >> 8, (desc.bcdUSB >> 4) & 15, desc.bcdUSB & 15); printf ("bDeviceClass %d\n", desc.bDeviceClass); printf ("bDeviceSubClass %d\n", desc.bDeviceSubClass); printf ("bDeviceProtocol %d\n", desc.bDeviceProtocol); printf ("bMaxPacketSize0 %d\n", desc.bMaxPacketSize0); printf ("idVendor 0x%04X\n", desc.idVendor); printf ("idProduct 0x%04X\n", desc.idProduct); printf ("bcdDevice %d.%d%d\n", desc.bcdDevice >> 8, (desc.bcdDevice >> 4) & 15, desc.bcdDevice & 15); printf ("iManufacturer %d (%s)\n", desc.iManufacturer, (vendor) ? vendor : ""); printf ("iProduct %d (%s)\n", desc.iProduct, (product) ? product : ""); buf = get_libusb_string_descriptor (hdl, desc.iSerialNumber); printf ("iSerialNumber %d (%s)\n", desc.iSerialNumber, (buf) ? buf : ""); if (buf) free (buf); printf ("bNumConfigurations %d\n", desc.bNumConfigurations); for (config_nr = 0; config_nr < desc.bNumConfigurations; config_nr++) { struct libusb_config_descriptor *c; ret = libusb_get_config_descriptor (dev, config_nr, &c); if (ret < 0) { printf ("could not get configuration descriptor %d: %s\n", config_nr, sfs_libusb_strerror (ret)); continue; } printf (" \n", config_nr); printf (" bLength %d\n", c->bLength); printf (" bDescriptorType %d\n", c->bDescriptorType); printf (" wTotalLength %d\n", c->wTotalLength); printf (" bNumInterfaces %d\n", c->bNumInterfaces); printf (" bConfigurationValue %d\n", c->bConfigurationValue); buf = get_libusb_string_descriptor (hdl, c->iConfiguration); printf (" iConfiguration %d (%s)\n", c->iConfiguration, (buf) ? buf : ""); free (buf); printf (" bmAttributes %d (%s%s)\n", c->bmAttributes, c->bmAttributes & 64 ? "Self-powered" : "", c->bmAttributes & 32 ? "Remote Wakeup" : ""); printf (" MaxPower %d mA\n", c->MaxPower * 2); for (intf = 0; intf < c->bNumInterfaces; intf++) { const struct libusb_interface *interface; int alt_setting_nr; interface = &c->interface[intf]; printf (" \n", intf); for (alt_setting_nr = 0; alt_setting_nr < interface->num_altsetting; alt_setting_nr++) { const struct libusb_interface_descriptor *i; int ep_nr; i = &interface->altsetting[alt_setting_nr]; printf (" \n", alt_setting_nr); printf (" bLength %d\n", i->bLength); printf (" bDescriptorType %d\n", i->bDescriptorType); printf (" bInterfaceNumber %d\n", i->bInterfaceNumber); printf (" bAlternateSetting %d\n", i->bAlternateSetting); printf (" bNumEndpoints %d\n", i->bNumEndpoints); printf (" bInterfaceClass %d\n", i->bInterfaceClass); printf (" bInterfaceSubClass %d\n", i->bInterfaceSubClass); printf (" bInterfaceProtocol %d\n", i->bInterfaceProtocol); buf = NULL; buf = get_libusb_string_descriptor (hdl, i->iInterface); printf (" iInterface %d (%s)\n", i->iInterface, (buf) ? buf : ""); free (buf); for (ep_nr = 0; ep_nr < i->bNumEndpoints; ep_nr++) { const struct libusb_endpoint_descriptor *e; char *ep_type; e = &i->endpoint[ep_nr]; switch (e->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) { case LIBUSB_TRANSFER_TYPE_CONTROL: ep_type = "control"; break; case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: ep_type = "isochronous"; break; case LIBUSB_TRANSFER_TYPE_BULK: ep_type = "bulk"; break; case LIBUSB_TRANSFER_TYPE_INTERRUPT: ep_type = "interrupt"; break; default: ep_type = "unknown"; break; } printf (" \n", ep_nr); printf (" bLength %d\n", e->bLength); printf (" bDescriptorType %d\n", e->bDescriptorType); printf (" bEndpointAddress 0x%02X (%s 0x%02X)\n", e->bEndpointAddress, e->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK ? "in" : "out", e-> bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK); printf (" bmAttributes %d (%s)\n", e->bmAttributes, ep_type); printf (" wMaxPacketSize %d\n", e->wMaxPacketSize); printf (" bInterval %d ms\n", e->bInterval); printf (" bRefresh %d\n", e->bRefresh); printf (" bSynchAddress %d\n", e->bSynchAddress); } } } } } /* Some heuristics, which device may be a scanner */ if (desc.idVendor == 0) /* hub */ --is_scanner; if (desc.idProduct == 0) /* hub */ --is_scanner; ret = libusb_get_config_descriptor (dev, 0, &config0); if (ret < 0) { printf ("could not get config[0] descriptor: %s\n", sfs_libusb_strerror (ret)); goto out_free; } for (intf = 0; (intf < config0->bNumInterfaces) && (is_scanner <= 0); intf++) { switch (desc.bDeviceClass) { case USB_CLASS_VENDOR_SPEC: ++is_scanner; break; case USB_CLASS_PER_INTERFACE: if ((config0->interface[intf].num_altsetting == 0) || !config0->interface[intf].altsetting) break; switch (config0->interface[intf].altsetting[0].bInterfaceClass) { case USB_CLASS_VENDOR_SPEC: case USB_CLASS_PER_INTERFACE: case 16: /* data? */ ++is_scanner; break; } break; } } if (is_scanner > 0) { char *chipset = NULL; if(!from_file) chipset = check_usb_chip (verbose, desc, hdl, config0); printf ("found USB scanner (vendor=0x%04x", vid); if (vendor) printf (" [%s]", vendor); printf (", product=0x%04x", pid); if (product) printf (" [%s]", product); if (chipset) printf (", chip=%s", chipset); if (from_file) printf (")\n"); else printf (") at libusb:%03d:%03d\n", busno, address); libusb_device_found = SANE_TRUE; device_found = SANE_TRUE; } libusb_free_config_descriptor (config0); out_free: libusb_close (hdl); if (vendor) free (vendor); if (product) free (product); } #endif /* HAVE_LIBUSB */ static DIR * scan_directory (char *dir_name) { struct stat stat_buf; DIR *dir; if (verbose > 2) printf ("scanning directory %s\n", dir_name); if (stat (dir_name, &stat_buf) < 0) { if (verbose > 1) printf ("cannot stat `%s' (%s)\n", dir_name, strerror (errno)); return 0; } if (!S_ISDIR (stat_buf.st_mode)) { if (verbose > 1) printf ("`%s' is not a directory\n", dir_name); return 0; } if ((dir = opendir (dir_name)) == 0) { if (verbose > 1) printf ("cannot read directory `%s' (%s)\n", dir_name, strerror (errno)); return 0; } return dir; } static char * get_next_file (char *dir_name, DIR * dir) { struct dirent *dir_entry; static char file_name[PATH_MAX]; do { dir_entry = readdir (dir); if (!dir_entry) return 0; } while (strcmp (dir_entry->d_name, ".") == 0 || strcmp (dir_entry->d_name, "..") == 0); if (strlen (dir_name) + strlen (dir_entry->d_name) + 1 > PATH_MAX) { if (verbose > 1) printf ("filename too long\n"); return 0; } sprintf (file_name, "%s%s", dir_name, dir_entry->d_name); return file_name; } #if defined(WIN32_SCSI) /* Return a list of potential scanners. There's a lot of hardcoded values here that might break on a system with lots of scsi devices. */ static char **build_scsi_dev_list(void) { char **dev_list; int dev_list_index; int hca; HANDLE fd; char scsi_hca_name[20]; char buffer[4096]; DWORD BytesReturned; BOOL ret; size_t dev_list_size; PSCSI_ADAPTER_BUS_INFO adapter; PSCSI_INQUIRY_DATA inquiry; int i; /* Allocate room for about 100 scanners. That should be enough. */ dev_list_size = 100; dev_list_index = 0; dev_list = calloc(1, dev_list_size * sizeof(char *)); hca = 0; for(hca = 0; ; hca++) { /* Open the adapter */ snprintf(scsi_hca_name, 20, "\\\\.\\Scsi%d:", hca); fd = CreateFile(scsi_hca_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL ); if (fd == INVALID_HANDLE_VALUE) { /* Assume there is no more adapter. This is wrong in the case * of hot-plug stuff, but I have yet to see it on a user * machine. */ break; } /* Get the inquiry info for the devices on that hca. */ ret = DeviceIoControl(fd, IOCTL_SCSI_GET_INQUIRY_DATA, NULL, 0, buffer, sizeof(buffer), &BytesReturned, FALSE); if(ret == 0) { CloseHandle(fd); continue; } adapter = (PSCSI_ADAPTER_BUS_INFO)buffer; for(i = 0; i < adapter->NumberOfBuses; i++) { if (adapter->BusData[i].InquiryDataOffset == 0) { /* No device here */ continue; } inquiry = (PSCSI_INQUIRY_DATA) (buffer + adapter->BusData[i].InquiryDataOffset); while(1) { /* Check if it is a scanner or a processor * device. Ignore the other * device types. */ if (inquiry->InquiryDataLength >= 5 && ((inquiry->InquiryData[0] & 0x1f) == 3 || (inquiry->InquiryData[0] & 0x1f) == 6)) { char device_name[20]; sprintf(device_name, "h%db%dt%dl%d", hca, inquiry->PathId, inquiry->TargetId, inquiry->Lun); dev_list[dev_list_index] = strdup(device_name); dev_list_index++; } if (inquiry->NextInquiryDataOffset == 0) { /* No device here */ break; } else { inquiry = (PSCSI_INQUIRY_DATA) (buffer + inquiry->NextInquiryDataOffset); } } } CloseHandle(fd); } return dev_list; } #endif #if defined (HAVE_IOKIT_CDB_IOSCSILIB_H) || \ defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) char **scsi_dev_list; int scsi_dev_list_index; static SANE_Status AddToSCSIDeviceList (const char *dev) { if (scsi_dev_list_index < 99) { scsi_dev_list [scsi_dev_list_index] = strdup (dev); scsi_dev_list_index++; return SANE_STATUS_GOOD; } else return SANE_STATUS_NO_MEM; } static char **build_scsi_dev_list(void) { scsi_dev_list_index = 0; scsi_dev_list = malloc (100 * sizeof(char *)); sanei_scsi_find_devices (NULL, NULL, NULL, -1, -1, -1, -1, AddToSCSIDeviceList); scsi_dev_list [scsi_dev_list_index] = NULL; return scsi_dev_list; } #endif static int check_mustek_pp_device (void) { const char **devices; int ctr = 0, found = 0, scsi = 0; if (verbose > 1) printf ("searching for Mustek parallel port scanners:\n"); devices = sanei_pa4s2_devices (); while (devices[ctr] != NULL) { int fd; SANE_Status result; /* ordinary parallel port scanner type */ if (verbose > 1) printf ("checking %s...", devices[ctr]); result = sanei_pa4s2_open (devices[ctr], &fd); if (verbose > 1) { if (result != 0) printf (" failed to open (%s)\n", sane_strstatus (result)); else printf (" open ok\n"); } if (result == 0) { printf ("found possible Mustek parallel port scanner at \"%s\"\n", devices[ctr]); found++; sanei_pa4s2_close(fd); } /* trying scsi over pp devices */ if (verbose > 1) printf ("checking %s (SCSI emulation)...", devices[ctr]); result = sanei_pa4s2_scsi_pp_open (devices[ctr], &fd); if (verbose > 1) { if (result != 0) printf (" failed to open (%s)\n", sane_strstatus (result)); else printf (" open ok\n"); } if (result == 0) { printf ("found possible Mustek SCSI over PP scanner at \"%s\"\n", devices[ctr]); scsi++; sanei_pa4s2_close(fd); } ctr++; } free(devices); if (found > 0 && verbose > 0) printf("\n # Your Mustek parallel port scanner was detected. It may or\n" " # may not be supported by SANE. Please read the sane-mustek_pp\n" " # man-page for setup instructions.\n"); if (scsi > 0 && verbose > 0) printf("\n # Your Mustek parallel port scanner was detected. It may or\n" " # may not be supported by SANE. Please read the sane-mustek_pp\n" " # man-page for setup instructions.\n"); return (found > 0 || scsi > 0); } #ifdef HAVE_LIBUSB_LEGACY static SANE_Bool parse_num (char* search, const char* line, int base, long int * number) { char* start_number; start_number = strstr (line, search); if (start_number == NULL) return SANE_FALSE; start_number += strlen (search); *number = strtol (start_number, NULL, base); if (verbose > 2) printf ("Found %s%ld\n", search, *number); return SANE_TRUE; } static SANE_Bool parse_bcd (char* search, const char* line, long int * number) { char* start_number; char* end_number; int first_part; int second_part; start_number = strstr (line, search); if (start_number == NULL) return SANE_FALSE; start_number += strlen (search); first_part = strtol (start_number, &end_number, 10); start_number = end_number + 1; /* skip colon */ second_part = strtol (start_number, NULL, 10); *number = ((first_part / 10) << 12) + ((first_part % 10) << 8) + ((second_part / 10) << 4) + (second_part % 10); if (verbose > 2) printf ("Found %s%ld\n", search, *number); return SANE_TRUE; } static void parse_file (char *filename) { FILE * parsefile; char line [PATH_MAX], *token; const char * p; struct usb_device *dev = 0; long int number = 0; int current_config = 1; int current_if = -1; int current_as = -1; int current_ep = -1; if (verbose > 1) printf ("trying to open %s\n", filename); parsefile = fopen (filename, "r"); if (parsefile == NULL) { if (verbose > 0) printf ("opening %s failed: %s\n", filename, strerror (errno)); return; } while (sanei_config_read (line, PATH_MAX, parsefile)) { if (verbose > 2) printf ("parsing line: `%s'\n", line); p = sanei_config_get_string (line, &token); if (!token || !p || token[0] == '\0') continue; if (token[1] != ':') { if (verbose > 2) printf ("missing `:'?\n"); continue; } switch (token[0]) { case 'T': if (dev) check_libusb_device (dev, SANE_TRUE); dev = calloc (1, sizeof (struct usb_device)); dev->bus = calloc (1, sizeof (struct usb_bus)); current_config = 1; current_if = -1; current_as = -1; current_ep = -1; break; case 'D': if (parse_bcd ("Ver=", line, &number)) dev->descriptor.bcdUSB = number; if (parse_num ("Cls=", line, 16, &number)) dev->descriptor.bDeviceClass = number; if (parse_num ("Sub=", line, 16, &number)) dev->descriptor.bDeviceSubClass = number; if (parse_num ("Prot=", line, 16, &number)) dev->descriptor.bDeviceProtocol = number; if (parse_num ("MxPS=", line, 10, &number)) dev->descriptor.bMaxPacketSize0 = number; if (parse_num ("#Cfgs=", line, 10, &number)) dev->descriptor.bNumConfigurations = number; dev->config = calloc (number, sizeof (struct usb_config_descriptor)); break; case 'P': if (parse_num ("Vendor=", line, 16, &number)) dev->descriptor.idVendor = number; if (parse_num ("ProdID=", line, 16, &number)) dev->descriptor.idProduct = number; if (parse_bcd ("Rev=", line, &number)) dev->descriptor.bcdDevice = number; break; case 'C': current_if = -1; current_as = -1; current_ep = -1; if (parse_num ("Cfg#=", line, 10, &number)) { current_config = number - 1; dev->config[current_config].bConfigurationValue = number; } if (parse_num ("Ifs=", line, 10, &number)) dev->config[current_config].bNumInterfaces = number; dev->config[current_config].interface = calloc (number, sizeof (struct usb_interface)); if (parse_num ("Atr=", line, 16, &number)) dev->config[current_config].bmAttributes = number; if (parse_num ("MxPwr=", line, 10, &number)) dev->config[current_config].MaxPower = number / 2; break; case 'I': current_ep = -1; if (parse_num ("If#=", line, 10, &number)) { if (current_if != number) { current_if = number; current_as = -1; dev->config[current_config].interface[current_if].altsetting = calloc (20, sizeof (struct usb_interface_descriptor)); /* Can't read number of altsettings */ dev->config[current_config].interface[current_if].num_altsetting = 1; } else dev->config[current_config].interface[current_if].num_altsetting++; } if (parse_num ("Alt=", line, 10, &number)) { current_as = number; dev->config[current_config].interface[current_if].altsetting[current_as].bInterfaceNumber = current_if; dev->config[current_config].interface[current_if].altsetting[current_as].bAlternateSetting = current_as; } if (parse_num ("#EPs=", line, 10, &number)) dev->config[current_config].interface[current_if].altsetting[current_as].bNumEndpoints = number; dev->config[current_config].interface[current_if].altsetting[current_as].endpoint = calloc (number, sizeof (struct usb_endpoint_descriptor)); if (parse_num ("Cls=", line, 16, &number)) dev->config[current_config].interface[current_if].altsetting[current_as].bInterfaceClass = number; if (parse_num ("Sub=", line, 16, &number)) dev->config[current_config].interface[current_if].altsetting[current_as].bInterfaceSubClass = number; if (parse_num ("Prot=", line, 16, &number)) dev->config[current_config].interface[current_if].altsetting[current_as].bInterfaceProtocol = number; break; case 'E': current_ep++; if (parse_num ("Ad=", line, 16, &number)) dev->config[current_config].interface[current_if].altsetting[current_as] .endpoint[current_ep].bEndpointAddress = number; if (parse_num ("Atr=", line, 16, &number)) dev->config[current_config].interface[current_if].altsetting[current_as] .endpoint[current_ep].bmAttributes = number; if (parse_num ("MxPS=", line, 10, &number)) dev->config[current_config].interface[current_if].altsetting[current_as] .endpoint[current_ep].wMaxPacketSize = number; if (parse_num ("Ivl=", line, 10, &number)) dev->config[current_config].interface[current_if].altsetting[current_as] .endpoint[current_ep].bInterval = number; break; case 'S': case 'B': continue; default: if (verbose > 1) printf ("ignoring unknown line identifier: %c\n", token[0]); continue; } free (token); } if (dev) check_libusb_device (dev, SANE_TRUE); fclose (parsefile); return; } #endif int main (int argc, char **argv) { char **dev_list, **usb_dev_list, *dev_name, **ap; int enable_pp_checks = SANE_FALSE; prog_name = strrchr (argv[0], '/'); if (prog_name) ++prog_name; else prog_name = argv[0]; for (ap = argv + 1; ap < argv + argc; ++ap) { if ((*ap)[0] != '-') break; switch ((*ap)[1]) { case '?': case 'h': usage (0); exit (0); case 'v': ++verbose; break; case 'q': --verbose; break; case 'f': force = SANE_TRUE; break; case 'p': enable_pp_checks = SANE_TRUE; break; case 'F': #ifdef HAVE_LIBUSB_LEGACY parse_file ((char *) (*(++ap))); #elif defined(HAVE_LIBUSB) printf ("option -F not implemented with libusb-1.0\n"); #else printf ("libusb not available: option -F can't be used\n"); #endif exit (0); default: printf ("unknown option: -%c, try -h for help\n", (*ap)[1]); exit (0); } } if (ap < argv + argc) { dev_list = ap; usb_dev_list = ap; } else { static char *default_dev_list[] = { #if defined(__sgi) "/dev/scsi/sc0d1l0", "/dev/scsi/sc0d2l0", "/dev/scsi/sc0d3l0", "/dev/scsi/sc0d4l0", "/dev/scsi/sc0d5l0", "/dev/scsi/sc0d6l0", "/dev/scsi/sc0d7l0", "/dev/scsi/sc0d8l0", "/dev/scsi/sc0d9l0", "/dev/scsi/sc0d10l0", "/dev/scsi/sc0d11l0", "/dev/scsi/sc0d12l0", "/dev/scsi/sc0d13l0", "/dev/scsi/sc0d14l0", "/dev/scsi/sc0d15l0", "/dev/scsi/sc1d1l0", "/dev/scsi/sc1d2l0", "/dev/scsi/sc1d3l0", "/dev/scsi/sc1d4l0", "/dev/scsi/sc1d5l0", "/dev/scsi/sc1d6l0", "/dev/scsi/sc1d7l0", "/dev/scsi/sc1d8l0", "/dev/scsi/sc1d9l0", "/dev/scsi/sc1d10l0", "/dev/scsi/sc1d11l0", "/dev/scsi/sc1d12l0", "/dev/scsi/sc1d13l0", "/dev/scsi/sc1d14l0", "/dev/scsi/sc1d15l0", "/dev/scsi/sc2d1l0", "/dev/scsi/sc2d2l0", "/dev/scsi/sc2d3l0", "/dev/scsi/sc2d4l0", "/dev/scsi/sc2d5l0", "/dev/scsi/sc2d6l0", "/dev/scsi/sc2d7l0", "/dev/scsi/sc2d8l0", "/dev/scsi/sc2d9l0", "/dev/scsi/sc2d10l0", "/dev/scsi/sc2d11l0", "/dev/scsi/sc2d12l0", "/dev/scsi/sc2d13l0", "/dev/scsi/sc2d14l0", "/dev/scsi/sc2d15l0", "/dev/scsi/sc3d1l0", "/dev/scsi/sc3d2l0", "/dev/scsi/sc3d3l0", "/dev/scsi/sc3d4l0", "/dev/scsi/sc3d5l0", "/dev/scsi/sc3d6l0", "/dev/scsi/sc3d7l0", "/dev/scsi/sc3d8l0", "/dev/scsi/sc3d9l0", "/dev/scsi/sc3d10l0", "/dev/scsi/sc3d11l0", "/dev/scsi/sc3d12l0", "/dev/scsi/sc3d13l0", "/dev/scsi/sc3d14l0", "/dev/scsi/sc3d15l0", "/dev/scsi/sc4d1l0", "/dev/scsi/sc4d2l0", "/dev/scsi/sc4d3l0", "/dev/scsi/sc4d4l0", "/dev/scsi/sc4d5l0", "/dev/scsi/sc4d6l0", "/dev/scsi/sc4d7l0", "/dev/scsi/sc4d8l0", "/dev/scsi/sc4d9l0", "/dev/scsi/sc4d10l0", "/dev/scsi/sc4d11l0", "/dev/scsi/sc4d12l0", "/dev/scsi/sc4d13l0", "/dev/scsi/sc4d14l0", "/dev/scsi/sc4d15l0", "/dev/scsi/sc5d1l0", "/dev/scsi/sc5d2l0", "/dev/scsi/sc5d3l0", "/dev/scsi/sc5d4l0", "/dev/scsi/sc5d5l0", "/dev/scsi/sc5d6l0", "/dev/scsi/sc5d7l0", "/dev/scsi/sc5d8l0", "/dev/scsi/sc5d9l0", "/dev/scsi/sc5d10l0", "/dev/scsi/sc5d11l0", "/dev/scsi/sc5d12l0", "/dev/scsi/sc5d13l0", "/dev/scsi/sc5d14l0", "/dev/scsi/sc5d15l0", "/dev/scsi/sc6d1l0", "/dev/scsi/sc6d2l0", "/dev/scsi/sc6d3l0", "/dev/scsi/sc6d4l0", "/dev/scsi/sc6d5l0", "/dev/scsi/sc6d6l0", "/dev/scsi/sc6d7l0", "/dev/scsi/sc6d8l0", "/dev/scsi/sc6d9l0", "/dev/scsi/sc6d10l0", "/dev/scsi/sc6d11l0", "/dev/scsi/sc6d12l0", "/dev/scsi/sc6d13l0", "/dev/scsi/sc6d14l0", "/dev/scsi/sc6d15l0", "/dev/scsi/sc7d1l0", "/dev/scsi/sc7d2l0", "/dev/scsi/sc7d3l0", "/dev/scsi/sc7d4l0", "/dev/scsi/sc7d5l0", "/dev/scsi/sc7d6l0", "/dev/scsi/sc7d7l0", "/dev/scsi/sc7d8l0", "/dev/scsi/sc7d9l0", "/dev/scsi/sc7d10l0", "/dev/scsi/sc7d11l0", "/dev/scsi/sc7d12l0", "/dev/scsi/sc7d13l0", "/dev/scsi/sc7d14l0", "/dev/scsi/sc7d15l0", "/dev/scsi/sc8d1l0", "/dev/scsi/sc8d2l0", "/dev/scsi/sc8d3l0", "/dev/scsi/sc8d4l0", "/dev/scsi/sc8d5l0", "/dev/scsi/sc8d6l0", "/dev/scsi/sc8d7l0", "/dev/scsi/sc8d8l0", "/dev/scsi/sc8d9l0", "/dev/scsi/sc8d10l0", "/dev/scsi/sc8d11l0", "/dev/scsi/sc8d12l0", "/dev/scsi/sc8d13l0", "/dev/scsi/sc8d14l0", "/dev/scsi/sc8d15l0", "/dev/scsi/sc9d1l0", "/dev/scsi/sc9d2l0", "/dev/scsi/sc9d3l0", "/dev/scsi/sc9d4l0", "/dev/scsi/sc9d5l0", "/dev/scsi/sc9d6l0", "/dev/scsi/sc9d7l0", "/dev/scsi/sc9d8l0", "/dev/scsi/sc9d9l0", "/dev/scsi/sc9d10l0", "/dev/scsi/sc9d11l0", "/dev/scsi/sc9d12l0", "/dev/scsi/sc9d13l0", "/dev/scsi/sc9d14l0", "/dev/scsi/sc9d15l0", "/dev/scsi/sc10d1l0", "/dev/scsi/sc10d2l0", "/dev/scsi/sc10d3l0", "/dev/scsi/sc10d4l0", "/dev/scsi/sc10d5l0", "/dev/scsi/sc10d6l0", "/dev/scsi/sc10d7l0", "/dev/scsi/sc10d8l0", "/dev/scsi/sc10d9l0", "/dev/scsi/sc10d10l0", "/dev/scsi/sc10d11l0", "/dev/scsi/sc10d12l0", "/dev/scsi/sc10d13l0", "/dev/scsi/sc10d14l0", "/dev/scsi/sc10d15l0", "/dev/scsi/sc11d1l0", "/dev/scsi/sc11d2l0", "/dev/scsi/sc11d3l0", "/dev/scsi/sc11d4l0", "/dev/scsi/sc11d5l0", "/dev/scsi/sc11d6l0", "/dev/scsi/sc11d7l0", "/dev/scsi/sc11d8l0", "/dev/scsi/sc11d9l0", "/dev/scsi/sc11d10l0", "/dev/scsi/sc11d11l0", "/dev/scsi/sc11d12l0", "/dev/scsi/sc11d13l0", "/dev/scsi/sc11d14l0", "/dev/scsi/sc11d15l0", "/dev/scsi/sc12d1l0", "/dev/scsi/sc12d2l0", "/dev/scsi/sc12d3l0", "/dev/scsi/sc12d4l0", "/dev/scsi/sc12d5l0", "/dev/scsi/sc12d6l0", "/dev/scsi/sc12d7l0", "/dev/scsi/sc12d8l0", "/dev/scsi/sc12d9l0", "/dev/scsi/sc12d10l0", "/dev/scsi/sc12d11l0", "/dev/scsi/sc12d12l0", "/dev/scsi/sc12d13l0", "/dev/scsi/sc12d14l0", "/dev/scsi/sc12d15l0", "/dev/scsi/sc13d1l0", "/dev/scsi/sc13d2l0", "/dev/scsi/sc13d3l0", "/dev/scsi/sc13d4l0", "/dev/scsi/sc13d5l0", "/dev/scsi/sc13d6l0", "/dev/scsi/sc13d7l0", "/dev/scsi/sc13d8l0", "/dev/scsi/sc13d9l0", "/dev/scsi/sc13d10l0", "/dev/scsi/sc13d11l0", "/dev/scsi/sc13d12l0", "/dev/scsi/sc13d13l0", "/dev/scsi/sc13d14l0", "/dev/scsi/sc13d15l0", "/dev/scsi/sc14d1l0", "/dev/scsi/sc14d2l0", "/dev/scsi/sc14d3l0", "/dev/scsi/sc14d4l0", "/dev/scsi/sc14d5l0", "/dev/scsi/sc14d6l0", "/dev/scsi/sc14d7l0", "/dev/scsi/sc14d8l0", "/dev/scsi/sc14d9l0", "/dev/scsi/sc14d10l0", "/dev/scsi/sc14d11l0", "/dev/scsi/sc14d12l0", "/dev/scsi/sc14d13l0", "/dev/scsi/sc14d14l0", "/dev/scsi/sc14d15l0", "/dev/scsi/sc15d1l0", "/dev/scsi/sc15d2l0", "/dev/scsi/sc15d3l0", "/dev/scsi/sc15d4l0", "/dev/scsi/sc15d5l0", "/dev/scsi/sc15d6l0", "/dev/scsi/sc15d7l0", "/dev/scsi/sc15d8l0", "/dev/scsi/sc15d9l0", "/dev/scsi/sc15d10l0", "/dev/scsi/sc15d11l0", "/dev/scsi/sc15d12l0", "/dev/scsi/sc15d13l0", "/dev/scsi/sc15d14l0", "/dev/scsi/sc15d15l0", #elif defined(__EMX__) "b0t0l0", "b0t1l0", "b0t2l0", "b0t3l0", "b0t4l0", "b0t5l0", "b0t6l0", "b0t7l0", "b1t0l0", "b1t1l0", "b1t2l0", "b1t3l0", "b1t4l0", "b1t5l0", "b1t6l0", "b1t7l0", "b2t0l0", "b2t1l0", "b2t2l0", "b2t3l0", "b2t4l0", "b2t5l0", "b2t6l0", "b2t7l0", "b3t0l0", "b3t1l0", "b3t2l0", "b3t3l0", "b3t4l0", "b3t5l0", "b3t6l0", "b3t7l0", #elif defined(__linux__) "/dev/scanner", "/dev/sg0", "/dev/sg1", "/dev/sg2", "/dev/sg3", "/dev/sg4", "/dev/sg5", "/dev/sg6", "/dev/sg7", "/dev/sg8", "/dev/sg9", "/dev/sga", "/dev/sgb", "/dev/sgc", "/dev/sgd", "/dev/sge", "/dev/sgf", "/dev/sgg", "/dev/sgh", "/dev/sgi", "/dev/sgj", "/dev/sgk", "/dev/sgl", "/dev/sgm", "/dev/sgn", "/dev/sgo", "/dev/sgp", "/dev/sgq", "/dev/sgr", "/dev/sgs", "/dev/sgt", "/dev/sgu", "/dev/sgv", "/dev/sgw", "/dev/sgx", "/dev/sgy", "/dev/sgz", #elif defined(__NeXT__) "/dev/sg0a", "/dev/sg0b", "/dev/sg0c", "/dev/sg0d", "/dev/sg0e", "/dev/sg0f", "/dev/sg0g", "/dev/sg0h", "/dev/sg1a", "/dev/sg1b", "/dev/sg1c", "/dev/sg1d", "/dev/sg1e", "/dev/sg1f", "/dev/sg1g", "/dev/sg1h", "/dev/sg2a", "/dev/sg2b", "/dev/sg2c", "/dev/sg2d", "/dev/sg2e", "/dev/sg2f", "/dev/sg2g", "/dev/sg2h", "/dev/sg3a", "/dev/sg3b", "/dev/sg3c", "/dev/sg3d", "/dev/sg3e", "/dev/sg3f", "/dev/sg3g", "/dev/sg3h", #elif defined(_AIX) "/dev/scanner", "/dev/gsc0", "/dev/gsc1", "/dev/gsc2", "/dev/gsc3", "/dev/gsc4", "/dev/gsc5", "/dev/gsc6", "/dev/gsc7", "/dev/gsc8", "/dev/gsc9", "/dev/gsc10", "/dev/gsc11", "/dev/gsc12", "/dev/gsc13", "/dev/gsc14", "/dev/gsc15", #elif defined(__sun) "/dev/scg0a", "/dev/scg0b", "/dev/scg0c", "/dev/scg0d", "/dev/scg0e", "/dev/scg0f", "/dev/scg0g", "/dev/scg1a", "/dev/scg1b", "/dev/scg1c", "/dev/scg1d", "/dev/scg1e", "/dev/scg1f", "/dev/scg1g", "/dev/scg2a", "/dev/scg2b", "/dev/scg2c", "/dev/scg2d", "/dev/scg2e", "/dev/scg2f", "/dev/scg2g", "/dev/sg/0", "/dev/sg/1", "/dev/sg/2", "/dev/sg/3", "/dev/sg/4", "/dev/sg/5", "/dev/sg/6", "/dev/scsi/scanner/", "/dev/scsi/processor/", #elif defined(HAVE_CAMLIB_H) "/dev/scanner", "/dev/scanner0", "/dev/scanner1", "/dev/pass0", "/dev/pass1", "/dev/pass2", "/dev/pass3", "/dev/pass4", "/dev/pass5", "/dev/pass6", "/dev/pass7", #elif defined(__FreeBSD__) || defined(__DragonFly__) "/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4", "/dev/uk5", "/dev/uk6", #elif defined(__NetBSD__) "/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4", "/dev/uk5", "/dev/uk6", "/dev/ss0", #elif defined(__OpenBSD__) "/dev/uk0", "/dev/uk1", "/dev/uk2", "/dev/uk3", "/dev/uk4", "/dev/uk5", "/dev/uk6", #elif defined(__hpux) "/dev/rscsi/", #endif 0 }; static char *usb_default_dev_list[] = { #if defined(__linux__) "/dev/usb/scanner", "/dev/usb/scanner0", "/dev/usb/scanner1", "/dev/usb/scanner2", "/dev/usb/scanner3", "/dev/usb/scanner4", "/dev/usb/scanner5", "/dev/usb/scanner5", "/dev/usb/scanner7", "/dev/usb/scanner8", "/dev/usb/scanner9", "/dev/usb/scanner10", "/dev/usb/scanner11", "/dev/usb/scanner12", "/dev/usb/scanner13", "/dev/usb/scanner14", "/dev/usb/scanner15", "/dev/usbscanner", "/dev/usbscanner0", "/dev/usbscanner1", "/dev/usbscanner2", "/dev/usbscanner3", "/dev/usbscanner4", "/dev/usbscanner5", "/dev/usbscanner6", "/dev/usbscanner7", "/dev/usbscanner8", "/dev/usbscanner9", "/dev/usbscanner10", "/dev/usbscanner11", "/dev/usbscanner12", "/dev/usbscanner13", "/dev/usbscanner14", "/dev/usbscanner15", #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) "/dev/uscanner", "/dev/uscanner0", "/dev/uscanner1", "/dev/uscanner2", "/dev/uscanner3", "/dev/uscanner4", "/dev/uscanner5", "/dev/uscanner6", "/dev/uscanner7", "/dev/uscanner8", "/dev/uscanner9", "/dev/uscanner10", "/dev/uscanner11", "/dev/uscanner12", "/dev/uscanner13", "/dev/uscanner14", "/dev/uscanner15", #endif 0 }; #if defined (WIN32_SCSI) || \ defined (HAVE_IOKIT_CDB_IOSCSILIB_H) || \ defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) /* Build a list of valid of possible scanners found */ dev_list = build_scsi_dev_list(); #else dev_list = default_dev_list; #endif usb_dev_list = usb_default_dev_list; } if (verbose > 1) printf ("This is sane-find-scanner from %s\n", PACKAGE_STRING); if (verbose > 0) printf ("\n # sane-find-scanner will now attempt to detect your scanner. If the" "\n # result is different from what you expected, first make sure your" "\n # scanner is powered up and properly connected to your computer.\n\n"); if (verbose > 1) printf ("searching for SCSI scanners:\n"); while ((dev_name = *dev_list++)) { if (strlen (dev_name) == 0) continue; /* Empty device names ... */ if (dev_name[strlen (dev_name) - 1] == '/') { /* check whole directories */ DIR *dir; char *file_name; dir = scan_directory (dev_name); if (!dir) continue; while ((file_name = get_next_file (dev_name, dir))) check_scsi_file (file_name); } else { /* check device files */ check_scsi_file (dev_name); } } if (device_found) { if (verbose > 0) printf (" # Your SCSI scanner was detected. It may or may not be " "supported by SANE. Try\n # scanimage -L and read the backend's " "manpage.\n"); } else { if (verbose > 0) printf (" # No SCSI scanners found. If you expected something different, " "make sure that\n # you have loaded a kernel SCSI driver for your SCSI " "adapter.\n"); if (!check_sg ()) { if (verbose > 0) printf (" # Also you need support for SCSI Generic (sg) in your " "operating system.\n # If using Linux, try \"modprobe " "sg\".\n"); } } if (verbose > 0) printf ("\n"); device_found = SANE_FALSE; sanei_usb_init (); if (verbose > 1) printf ("searching for USB scanners:\n"); while ((dev_name = *usb_dev_list++)) { if (strlen (dev_name) == 0) continue; /* Empty device names ... */ if (dev_name[strlen (dev_name) - 1] == '/') { /* check whole directories */ DIR *dir; char *file_name; dir = scan_directory (dev_name); if (!dir) continue; while ((file_name = get_next_file (dev_name, dir))) check_usb_file (file_name); } else { /* check device files */ check_usb_file (dev_name); } } #ifdef HAVE_LIBUSB_LEGACY /* Now the libusb devices */ { struct usb_bus *bus; struct usb_device *dev; if (ap < argv + argc) { /* user-specified devices not useful for libusb */ if (verbose > 1) printf ("ignoring libusb devices\n"); } else { if (verbose > 2) printf ("trying libusb:\n"); for (bus = usb_get_busses (); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { check_libusb_device (dev, SANE_FALSE); } /* for (dev) */ } /* for (bus) */ } } #elif defined(HAVE_LIBUSB) /* Now the libusb-1.0 devices */ { if (ap < argv + argc) { /* user-specified devices not useful for libusb */ if (verbose > 1) printf ("ignoring libusb devices\n"); } else { libusb_device **devlist; ssize_t devcnt; int i; int ret; if (verbose > 2) printf ("trying libusb:\n"); ret = libusb_init (&sfs_usb_ctx); if (ret < 0) { printf ("# Could not initialize libusb-1.0, error %d\n", ret); printf ("# Skipping libusb devices\n"); goto failed_libusb_1_0; } if (verbose > 3) libusb_set_debug (sfs_usb_ctx, 3); devcnt = libusb_get_device_list (sfs_usb_ctx, &devlist); if (devcnt < 0) { printf ("# Could not get device list, error %d\n", ret); goto deinit_libusb_1_0; } for (i = 0; i < devcnt; i++) { check_libusb_device (devlist[i], SANE_FALSE); } libusb_free_device_list (devlist, 1); deinit_libusb_1_0: libusb_exit (sfs_usb_ctx); failed_libusb_1_0: ; /* init failed, jumping here */ } } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ if (verbose > 1) printf ("libusb not available\n"); #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ if (device_found) { if (libusb_device_found) { if (verbose > 0) printf (" # Your USB scanner was (probably) detected. It " "may or may not be supported by\n # SANE. Try scanimage " "-L and read the backend's manpage.\n"); } else if (verbose > 0) printf (" # Your USB scanner was detected. It may or may not " "be supported by\n # SANE. Try scanimage -L and read the " "backend's manpage.\n"); if (unknown_found && verbose > 0) printf (" # `UNKNOWN vendor and product' means that there seems to be a " "scanner at this\n # device file but the vendor and product ids " "couldn't be identified.\n # Currently identification only works " "with Linux versions >= 2.4.8. You may\n # need to configure your " "backend manually, see the backend's manpage.\n"); } else { if (verbose > 0) printf (" # No USB scanners found. If you expected something different, " "make sure that\n # you have loaded a kernel driver for your USB host " "controller and have setup\n # the USB system correctly. " "See man sane-usb for details.\n"); #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) if (verbose > 0) printf (" # SANE has been built without libusb support. This may be a " "reason\n # for not detecting USB scanners. Read README for " "more details.\n"); #endif } if (enable_pp_checks == SANE_TRUE) { if (!check_mustek_pp_device() && verbose > 0) printf ("\n # No Mustek parallel port scanners found. If you expected" " something\n # different, make sure the scanner is correctly" " connected to your computer\n # and you have appropriate" " access rights.\n"); } else if (verbose > 0) printf ("\n # Not checking for parallel port scanners.\n"); if (verbose > 0) printf ("\n # Most Scanners connected to the parallel port or other " "proprietary ports\n # can't be detected by this program.\n"); #ifdef HAVE_GETUID if (getuid ()) if (verbose > 0) printf ("\n # You may want to run this program as root to find all devices. " "Once you\n # found the scanner devices, be sure to adjust access " "permissions as\n # necessary.\n"); #endif if (verbose > 1) printf ("done\n"); return 0; } sane-backends-1.0.27/PROBLEMS0000664000175000017500000000205712112021330012355 00000000000000Last update: 2006-01-05 - Avoiding damage on flatbed scanners Most flatbed scanners have no protection against exceeding the physical scan area height. That is, if a scan is attempted with a height that exceeds the height of the scan surface, the scanner begins making loud noises and the scan mechanism may be damaged. Thus, if you hear such a noise, IMMEDIATELY turn off the scanner. Normally, the backend will ensure that the maximum scan height is not exceeded. However, if your scanner model has not been tested yet this safety-guard may not work. Please report errors like this to the author of the backend or the sane-devel mailing list. - Security problems with saned (SANE network scanning daemon) saned is not intended to be exposed to the internet or other non-trusted networks. Make sure that access is limited by tcpwrappers and/or a firewall setup. Don't depend only on saned's own authentification. Don't run saned as root if it's not necessary. And do not install saned as setuid root. Read man saned(8) for details. sane-backends-1.0.27/include/0000775000175000017500000000000013110600530012712 500000000000000sane-backends-1.0.27/include/sane/0000775000175000017500000000000013110600530013640 500000000000000sane-backends-1.0.27/include/sane/sanei_backend.h0000664000175000017500000001147512775312262016531 00000000000000/** @file sanei_backend.h * Compatibility header file for backends * * This file provides some defines for macros missing on some platforms. * It also has the SANE API entry points. sanei_backend.h must be included * by every backend. * * @sa sanei.h sanei_thread.h */ /** @name Compatibility macros * @{ */ #include #if __STDC_VERSION__ >= 199901L /* __func__ is provided */ #elif __GNUC__ >= 5 /* __func__ is provided */ #elif __GNUC__ >= 2 # define __func__ __FUNCTION__ #else # define __func__ "(unknown)" #endif #ifdef HAVE_SYS_HW_H /* OS/2 i/o-port access compatibility macros: */ # define inb(p) _inp8 (p) # define outb(v,p) _outp8 ((p),(v)) # define ioperm(b,l,o) _portaccess ((b),(b)+(l)-1) # define HAVE_IOPERM 1 #endif #ifndef HAVE_OS2_H #include #ifndef O_NONBLOCK # ifdef O_NDELAY # define O_NONBLOCK O_NDELAY # else # ifdef FNDELAY # define O_NONBLOCK FNDELAY /* last resort */ # endif # endif #endif #endif /* HAVE_OS2_H */ #include #ifndef PATH_MAX # define PATH_MAX 1024 #endif #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef MM_PER_INCH #define MM_PER_INCH 25.4 #endif #ifdef HAVE_SIGPROCMASK # define SIGACTION sigaction #else /* Just enough backwards compatibility that we get by in the backends without making handstands. */ # ifdef sigset_t # undef sigset_t # endif # ifdef sigemptyset # undef sigemptyset # endif # ifdef sigfillset # undef sigfillset # endif # ifdef sigaddset # undef sigaddset # endif # ifdef sigdelset # undef sigdelset # endif # ifdef sigprocmask # undef sigprocmask # endif # ifdef SIG_BLOCK # undef SIG_BLOCK # endif # ifdef SIG_UNBLOCK # undef SIG_UNBLOCK # endif # ifdef SIG_SETMASK # undef SIG_SETMASK # endif # define sigset_t int # define sigemptyset(set) do { *(set) = 0; } while (0) # define sigfillset(set) do { *(set) = ~0; } while (0) # define sigaddset(set,signal) do { *(set) |= sigmask (signal); } while (0) # define sigdelset(set,signal) do { *(set) &= ~sigmask (signal); } while (0) # define sigaction(sig,new,old) sigvec (sig,new,old) /* Note: it's not safe to just declare our own "struct sigaction" since some systems (e.g., some versions of OpenStep) declare that structure, but do not implement sigprocmask(). Hard to believe, aint it? */ # define SIGACTION sigvec # define SIG_BLOCK 1 # define SIG_UNBLOCK 2 # define SIG_SETMASK 3 #endif /* !HAVE_SIGPROCMASK */ /* @} */ /** @name Declaration of entry points: * @{ */ extern SANE_Status ENTRY(init) (SANE_Int *, SANE_Auth_Callback); extern SANE_Status ENTRY(get_devices) (const SANE_Device ***, SANE_Bool); extern SANE_Status ENTRY(open) (SANE_String_Const, SANE_Handle *); extern const SANE_Option_Descriptor * ENTRY(get_option_descriptor) (SANE_Handle, SANE_Int); extern SANE_Status ENTRY(control_option) (SANE_Handle, SANE_Int, SANE_Action, void *, SANE_Word *); extern SANE_Status ENTRY(get_parameters) (SANE_Handle, SANE_Parameters *); extern SANE_Status ENTRY(start) (SANE_Handle); extern SANE_Status ENTRY(read) (SANE_Handle, SANE_Byte *, SANE_Int, SANE_Int *); extern SANE_Status ENTRY(set_io_mode) (SANE_Handle, SANE_Bool); extern SANE_Status ENTRY(get_select_fd) (SANE_Handle, SANE_Int *); extern void ENTRY(cancel) (SANE_Handle); extern void ENTRY(close) (SANE_Handle); extern void ENTRY(exit) (void); #ifndef STUBS /* Now redirect sane_* calls to backend's functions: */ #define sane_init(a,b) ENTRY(init) (a,b) #define sane_get_devices(a,b) ENTRY(get_devices) (a,b) #define sane_open(a,b) ENTRY(open) (a,b) #define sane_get_option_descriptor(a,b) ENTRY(get_option_descriptor) (a,b) #define sane_control_option(a,b,c,d,e) ENTRY(control_option) (a,b,c,d,e) #define sane_get_parameters(a,b) ENTRY(get_parameters) (a,b) #define sane_start(a) ENTRY(start) (a) #define sane_read(a,b,c,d) ENTRY(read) (a,b,c,d) #define sane_set_io_mode(a,b) ENTRY(set_io_mode) (a,b) #define sane_get_select_fd(a,b) ENTRY(get_select_fd) (a,b) #define sane_cancel(a) ENTRY(cancel) (a) #define sane_close(a) ENTRY(close) (a) #define sane_exit(a) ENTRY(exit) (a) #endif /* STUBS */ /* @} */ /** Internationalization for SANE backends * * Add SANE_I18N() to all texts that can be translated. * E.g. out_txt = SANE_I18N("Hello"); */ #ifndef SANE_I18N #define SANE_I18N(text) text #endif /** Option_Value union * * Convenience union to access option values given to the backend */ #ifndef SANE_OPTION typedef union { SANE_Bool b; /**< bool */ SANE_Word w; /**< word */ SANE_Word *wa; /**< word array */ SANE_String s; /**< string */ } Option_Value; #define SANE_OPTION 1 #endif sane-backends-1.0.27/include/sane/sane.h0000664000175000017500000001737013072306202014675 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997-1999 David Mosberger-Tang and Andreas Beck This file is part of the SANE package. This file is in the public domain. You may use and modify it as you see fit, as long as this copyright message is included and that there is an indication as to what modifications have been made (if any). SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This file declares SANE application interface. See the SANE standard for a detailed explanation of the interface. */ #ifndef sane_h #define sane_h #ifdef __cplusplus extern "C" { #endif /* * SANE types and defines */ #define SANE_CURRENT_MAJOR 1 #define SANE_CURRENT_MINOR 0 #define SANE_VERSION_CODE(major, minor, build) \ ( (((SANE_Word) (major) & 0xff) << 24) \ | (((SANE_Word) (minor) & 0xff) << 16) \ | (((SANE_Word) (build) & 0xffff) << 0)) #define SANE_VERSION_MAJOR(code) ((((SANE_Word)(code)) >> 24) & 0xff) #define SANE_VERSION_MINOR(code) ((((SANE_Word)(code)) >> 16) & 0xff) #define SANE_VERSION_BUILD(code) ((((SANE_Word)(code)) >> 0) & 0xffff) #define SANE_FALSE 0 #define SANE_TRUE 1 typedef unsigned char SANE_Byte; typedef int SANE_Word; typedef SANE_Word SANE_Bool; typedef SANE_Word SANE_Int; typedef char SANE_Char; typedef SANE_Char *SANE_String; typedef const SANE_Char *SANE_String_Const; typedef void *SANE_Handle; typedef SANE_Word SANE_Fixed; #define SANE_FIXED_SCALE_SHIFT 16 #define SANE_FIX(v) ((SANE_Word) ((v) * (1 << SANE_FIXED_SCALE_SHIFT))) #define SANE_UNFIX(v) ((double)(v) / (1 << SANE_FIXED_SCALE_SHIFT)) typedef enum { SANE_STATUS_GOOD = 0, /* everything A-OK */ SANE_STATUS_UNSUPPORTED, /* operation is not supported */ SANE_STATUS_CANCELLED, /* operation was cancelled */ SANE_STATUS_DEVICE_BUSY, /* device is busy; try again later */ SANE_STATUS_INVAL, /* data is invalid (includes no dev at open) */ SANE_STATUS_EOF, /* no more data available (end-of-file) */ SANE_STATUS_JAMMED, /* document feeder jammed */ SANE_STATUS_NO_DOCS, /* document feeder out of documents */ SANE_STATUS_COVER_OPEN, /* scanner cover is open */ SANE_STATUS_IO_ERROR, /* error during device I/O */ SANE_STATUS_NO_MEM, /* out of memory */ SANE_STATUS_ACCESS_DENIED /* access to resource has been denied */ } SANE_Status; /* following are for later sane version, older frontends wont support */ #if 0 #define SANE_STATUS_WARMING_UP 12 /* lamp not ready, please retry */ #define SANE_STATUS_HW_LOCKED 13 /* scanner mechanism locked for transport */ #endif typedef enum { SANE_TYPE_BOOL = 0, SANE_TYPE_INT, SANE_TYPE_FIXED, SANE_TYPE_STRING, SANE_TYPE_BUTTON, SANE_TYPE_GROUP } SANE_Value_Type; typedef enum { SANE_UNIT_NONE = 0, /* the value is unit-less (e.g., # of scans) */ SANE_UNIT_PIXEL, /* value is number of pixels */ SANE_UNIT_BIT, /* value is number of bits */ SANE_UNIT_MM, /* value is millimeters */ SANE_UNIT_DPI, /* value is resolution in dots/inch */ SANE_UNIT_PERCENT, /* value is a percentage */ SANE_UNIT_MICROSECOND /* value is micro seconds */ } SANE_Unit; typedef struct { SANE_String_Const name; /* unique device name */ SANE_String_Const vendor; /* device vendor string */ SANE_String_Const model; /* device model name */ SANE_String_Const type; /* device type (e.g., "flatbed scanner") */ } SANE_Device; #define SANE_CAP_SOFT_SELECT (1 << 0) #define SANE_CAP_HARD_SELECT (1 << 1) #define SANE_CAP_SOFT_DETECT (1 << 2) #define SANE_CAP_EMULATED (1 << 3) #define SANE_CAP_AUTOMATIC (1 << 4) #define SANE_CAP_INACTIVE (1 << 5) #define SANE_CAP_ADVANCED (1 << 6) #define SANE_OPTION_IS_ACTIVE(cap) (((cap) & SANE_CAP_INACTIVE) == 0) #define SANE_OPTION_IS_SETTABLE(cap) (((cap) & SANE_CAP_SOFT_SELECT) != 0) #define SANE_INFO_INEXACT (1 << 0) #define SANE_INFO_RELOAD_OPTIONS (1 << 1) #define SANE_INFO_RELOAD_PARAMS (1 << 2) typedef enum { SANE_CONSTRAINT_NONE = 0, SANE_CONSTRAINT_RANGE, SANE_CONSTRAINT_WORD_LIST, SANE_CONSTRAINT_STRING_LIST } SANE_Constraint_Type; typedef struct { SANE_Word min; /* minimum (element) value */ SANE_Word max; /* maximum (element) value */ SANE_Word quant; /* quantization value (0 if none) */ } SANE_Range; typedef struct { SANE_String_Const name; /* name of this option (command-line name) */ SANE_String_Const title; /* title of this option (single-line) */ SANE_String_Const desc; /* description of this option (multi-line) */ SANE_Value_Type type; /* how are values interpreted? */ SANE_Unit unit; /* what is the (physical) unit? */ SANE_Int size; SANE_Int cap; /* capabilities */ SANE_Constraint_Type constraint_type; union { const SANE_String_Const *string_list; /* NULL-terminated list */ const SANE_Word *word_list; /* first element is list-length */ const SANE_Range *range; } constraint; } SANE_Option_Descriptor; typedef enum { SANE_ACTION_GET_VALUE = 0, SANE_ACTION_SET_VALUE, SANE_ACTION_SET_AUTO } SANE_Action; typedef enum { SANE_FRAME_GRAY, /* band covering human visual range */ SANE_FRAME_RGB, /* pixel-interleaved red/green/blue bands */ SANE_FRAME_RED, /* red band only */ SANE_FRAME_GREEN, /* green band only */ SANE_FRAME_BLUE /* blue band only */ } SANE_Frame; /* push remaining types down to match existing backends */ /* these are to be exposed in a later version of SANE */ /* most front-ends will require updates to understand them */ #if 0 #define SANE_FRAME_TEXT 0x0A /* backend specific textual data */ #define SANE_FRAME_JPEG 0x0B /* complete baseline JPEG file */ #define SANE_FRAME_G31D 0x0C /* CCITT Group 3 1-D Compressed (MH) */ #define SANE_FRAME_G32D 0x0D /* CCITT Group 3 2-D Compressed (MR) */ #define SANE_FRAME_G42D 0x0E /* CCITT Group 4 2-D Compressed (MMR) */ #define SANE_FRAME_IR 0x0F /* bare infrared channel */ #define SANE_FRAME_RGBI 0x10 /* red+green+blue+infrared */ #define SANE_FRAME_GRAYI 0x11 /* gray+infrared */ #define SANE_FRAME_XML 0x12 /* undefined schema */ #endif typedef struct { SANE_Frame format; SANE_Bool last_frame; SANE_Int bytes_per_line; SANE_Int pixels_per_line; SANE_Int lines; SANE_Int depth; } SANE_Parameters; struct SANE_Auth_Data; #define SANE_MAX_USERNAME_LEN 128 #define SANE_MAX_PASSWORD_LEN 128 typedef void (*SANE_Auth_Callback) (SANE_String_Const resource, SANE_Char *username, SANE_Char *password); extern SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); extern void sane_exit (void); extern SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); extern SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle); extern void sane_close (SANE_Handle handle); extern const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); extern SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info); extern SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); extern SANE_Status sane_start (SANE_Handle handle); extern SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length); extern void sane_cancel (SANE_Handle handle); extern SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking); extern SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd); extern SANE_String_Const sane_strstatus (SANE_Status status); #ifdef __cplusplus } #endif #endif /* sane_h */ sane-backends-1.0.27/include/sane/sanei_config.h0000664000175000017500000001433612112021330016360 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_config.h * Generic configuration support. * * Use the functions of this header file if you want to read and analyze * configuration files. */ #ifndef sanei_config_h #define sanei_config_h 1 #include #include /** Search configuration file \a name along directory list and return file * pointer if such a file exists. * * The following directory list is used: * 1st: SANE_CONFIG_DIR environment variable. * 2nd: PATH_SANE_CONFIG_DIR set during configuration. * 3rd: Current directory. * @param name filename with extension but without path (such as "mustek.conf") * * @return file pointer, or NULL if not found * */ extern FILE *sanei_config_open (const char *name); /** Read a line from configuration file. * * Strips all unwanted chars. Use this instead of fgets() to remove * line ending chars on all known platforms. * * @param str points to the buffer for the line * @param n size of the buffer * @param stream file pointer * * @return \a str on success and NULL on error */ extern char *sanei_config_read (char *str, int n, FILE *stream); /** Remove all whitespace from the beginning of a string. * * @param str string * * @return string without leading whitespace * */ extern const char *sanei_config_skip_whitespace (const char *str); /** Scan a string constant from a line of text and return a malloced copy * of it. * * It's the responsibility of the caller to free the returned string constant * at an appropriate time. Whitespace in front of the string constant is * ignored. Whitespace can be included in the string constant by enclosing it * in double-quotes. * * @param str line of text to scan for a string constant * @param string_const copy of the string constant * * @return a pointer to the position in str where the scan stopped */ extern const char *sanei_config_get_string (const char *str, char **string_const); /** Expand device name patterns into a list of devices. * * Apart from a normal device name (such as /dev/sdb), this function currently * supports SCSI device specifications of the form: * * scsi VENDOR MODEL TYPE BUS CHANNEL ID LUN * * Where VENDOR is the desired vendor name. MODEL is the desired model name. * TYPE is the desired device type. All of these can be set to * to match * anything. To include whitespace in these strings, enclose them in * double-quotes ("). BUS, ID, and LUN are the desired SCSI bus, id, and * logical-unit numbers. These can be set to * or simply omitted to match * anything. * * @param name device name pattern * @param attach attach function */ extern void sanei_config_attach_matching_devices (const char *name, SANE_Status (*attach) (const char *dev)); /** this structure holds the description of configuration options. There is * a list for options and another for their values. * These lists are used when the configuration file is * parsed. Read values are stored in Option_Value. Helpers functions are * provided to access values easily */ typedef struct { /** number of options */ SANE_Int count; /** NULL terminated list of configuration option */ SANE_Option_Descriptor **descriptors; /** values for the configuration options */ void **values; } SANEI_Config; /** Parse configuration file, reading configuration options and trying to * attach devices found in file. * * The option are gathered in a single configuration structure. Each time * a line holds a value that is not an option, the attach function is called * with the name found and the configuration structure with it's current values. * * @param config_file name of the configuration file to read * @param config configuration structure to be filled during configuration * parsing and passed to the attach callback function * @param config_attach attach with config callback function * * @return SANE_STATUS_GOOD if no errors * SANE_STATUS_ACCESS_DENIED if configuration file can't be opened */ extern SANE_Status sanei_configure_attach ( const char *config_file, SANEI_Config *config, SANE_Status (*config_attach)(SANEI_Config *config, const char *devname) ); /** Return the list of config directories, extracted from the SANE_CONFIG_DIR * environment variable and the default paths. * @return a string containing the configuration paths, separated by the * operating system's path separator */ extern const char *sanei_config_get_paths (void); #endif /* sanei_config_h */ sane-backends-1.0.27/include/sane/sanei_pv8630.h0000664000175000017500000000666012112021330016062 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Adrian Perez Jorge Copyright (C) 2001 Frank Zago Copyright (C) 2001 Marcio Teixeira This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Interface files for the PowerVision 8630 chip, a USB to parallel converter used in many scanners. */ #ifndef sanei_pv8630_h #define sanei_pv8630_h #include "../include/sane/config.h" #include "../include/sane/sane.h" typedef enum { PV8630_REQ_READBYTE = 0x00, PV8630_REQ_WRITEBYTE = 0x01, PV8630_REQ_EPPBULKREAD = 0x02, PV8630_REQ_EPPBULKWRITE = 0x03, PV8630_REQ_FLUSHBUFFER = 0x04, PV8630_REQ_ENABLEINTERRUPT = 0x05, PV8630_REQ_DISABLEINTERRUPT = 0x06, PV8630_REQ_READWORD = 0x08, PV8630_REQ_WRITEWORD = 0x09 } SANEI_PV_Request; typedef enum { PV8630_RDATA = 0x00, PV8630_REPPADDRESS = 0x01, PV8630_UNKNOWN = 0x02, PV8630_RMODE = 0x03, PV8630_RSTATUS = 0x04 } SANEI_PV_Index; extern void sanei_pv8630_init (void); extern SANE_Status sanei_pv8630_write_byte (int fd, SANEI_PV_Index index, SANE_Byte byte); extern SANE_Status sanei_pv8630_read_byte (int fd, SANEI_PV_Index index, SANE_Byte * byte); extern SANE_Status sanei_pv8630_prep_bulkread (int fd, int len); extern SANE_Status sanei_pv8630_prep_bulkwrite (int fd, int len); extern SANE_Status sanei_pv8630_flush_buffer (int fd); extern SANE_Status sanei_pv8630_bulkwrite (int fd, const void *data, size_t * len); extern SANE_Status sanei_pv8630_bulkread (int fd, void *data, size_t * len); extern SANE_Status sanei_pv8630_xpect_byte (int fd, SANEI_PV_Index index, SANE_Byte value, SANE_Byte mask); extern SANE_Status sanei_pv8630_wait_byte (int fd, SANEI_PV_Index index, SANE_Byte value, SANE_Byte mask, int timeout); #endif /* sanei_pv8630_h */ sane-backends-1.0.27/include/sane/sanei_cderror.h0000664000175000017500000001217012112021330016545 00000000000000/* * cderror.h * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the error and message codes for the cjpeg/djpeg * applications. These strings are not needed as part of the JPEG library * proper. * Edit this file to add new codes, or to translate the message strings to * some other language. */ /* * To define the enum list of message codes, include this file without * defining macro JMESSAGE. To create a message string table, include it * again with a suitable JMESSAGE definition (see jerror.c for an example). */ #ifndef JMESSAGE #ifndef CDERROR_H #define CDERROR_H /* First time through, define the enum list */ #define JMAKE_ENUM_LIST #else /* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ #define JMESSAGE(code,string) #endif /* CDERROR_H */ #endif /* JMESSAGE */ #ifdef JMAKE_ENUM_LIST typedef enum { #define JMESSAGE(code,string) code , #endif /* JMAKE_ENUM_LIST */ JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ #ifdef BMP_SUPPORTED JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") #endif /* BMP_SUPPORTED */ #ifdef GIF_SUPPORTED JMESSAGE(JERR_GIF_BUG, "GIF output got confused") JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") JMESSAGE(JERR_GIF_NOT, "Not a GIF file") JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") JMESSAGE(JTRC_GIF_BADVERSION, "Warning: unexpected GIF version number '%c%c%c'") JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") #endif /* GIF_SUPPORTED */ #ifdef PPM_SUPPORTED JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") JMESSAGE(JERR_PPM_NOT, "Not a PPM file") JMESSAGE(JTRC_PGM, "%ux%u PGM image") JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") JMESSAGE(JTRC_PPM, "%ux%u PPM image") JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") #endif /* PPM_SUPPORTED */ #ifdef RLE_SUPPORTED JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") JMESSAGE(JERR_RLE_NOT, "Not an RLE file") JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") #endif /* RLE_SUPPORTED */ #ifdef TARGA_SUPPORTED JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") #else JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") #endif /* TARGA_SUPPORTED */ JMESSAGE(JERR_BAD_CMAP_FILE, "Color map file is invalid or of unsupported format") JMESSAGE(JERR_TOO_MANY_COLORS, "Output file format cannot handle %d colormap entries") JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") #ifdef TARGA_SUPPORTED JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format --- perhaps you need -targa") #else JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") #endif JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") #ifdef JMAKE_ENUM_LIST JMSG_LASTADDONCODE } ADDON_MESSAGE_CODE; #undef JMAKE_ENUM_LIST #endif /* JMAKE_ENUM_LIST */ /* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ #undef JMESSAGE sane-backends-1.0.27/include/sane/sanei_lm983x.h0000664000175000017500000001240712112021330016154 00000000000000/* sane - Scanner Access Now Easy. based on sources acquired from Plustek Inc. Copyright (C) 2002-2003 Gerhard Jaeger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_lm983x.h * Interface files for the NS LM9831/2/3 USB chip. * * The National Semiconductor LM9831, LM9832, and LM9833 chips are used in * many USB scanners. Examples include Plustek and Mustek devices. * * @sa sanei_usb.h */ #ifndef sanei_lm983x_h #define sanei_lm983x_h #include "../include/sane/config.h" #include "../include/sane/sane.h" /** * Read one data byte from a specific LM983x register. * * @param fd - device file descriptor (SANE_Int) * @param reg - number of register (SANE_Byte) * @param value - byte value to be written (SANE_Byte *) * * @return The SANE status code for the operation (SANE_Status): * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - system write function failed * - SANE_STATUS_INVAL - register out of range */ #define sanei_lm983x_read_byte(fd, reg, value) \ sanei_lm983x_read (fd, reg, value, 1, 0) /** * Initialize sanei_lm983x. * * Currently, this function only enables the debugging functionality. */ extern void sanei_lm983x_init( void ); /** * Write one data byte to a specific LM983x register. * * @param fd - device file descriptor * @param reg - number of register * @param value - byte value to be written * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - system write function failed * - SANE_STATUS_INVAL - register out of range */ extern SANE_Status sanei_lm983x_write_byte( SANE_Int fd, SANE_Byte reg, SANE_Byte value ); /** * Write one or more data bytes to one or more specific LM983x * registers. * * @param fd - device file descriptor * @param reg - number of start-register * @param buffer - buffer to be written * @param len - number of bytes to be written * @param increment - SANE_TRUE enables the autoincrement of the register * value during the write cycle, SANE_FALSE disables this * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - system read function failed * - SANE_STATUS_INVAL - register out of range or len field was 0 */ extern SANE_Status sanei_lm983x_write( SANE_Int fd, SANE_Byte reg, SANE_Byte *buffer, SANE_Word len, SANE_Bool increment ); /** * Read one or more data bytes from one ore more specific LM983x * registers. * * @param fd - device file descriptor * @param reg - number of start-register * @param buffer - buffer to receive the data * @param len - number of bytes to receive * @param increment - SANE_TRUE enables the autoincrement of the register * value during the read cylce, SANE_FALSE disables this * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - system read function failed * - SANE_STATUS_INVAL - register out of range * - SANE_STATUS_EOF - if nothing can't be read */ extern SANE_Status sanei_lm983x_read( SANE_Int fd, SANE_Byte reg, SANE_Byte *buffer, SANE_Word len, SANE_Bool increment ); /** * Reset the LM983x chip. * * @param fd - device file descriptor * @return * - SANE_TRUE - reset successfuly done * - SANE_FALSE - reset failed */ extern SANE_Bool sanei_lm983x_reset( SANE_Int fd ); #endif /* sanei_lm983x_h */ sane-backends-1.0.27/include/sane/sanei_codec_ascii.h0000664000175000017500000000467712112021330017347 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996 David Mosberger-Tang and Andreas Beck This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_codec_ascii.h * ASCII codec for network and file transmissions * * Instead translating data to a byte stream this codec uses ASCII hex numbers. * Therefore it can be used for streams that are not 8-bit clean or which can * only use printable characters. It's currently used for saving/restoring * data to/from disk. * * @sa sanei_codec_bin.h sanei_net.h sanei_wire.h */ #ifndef sanei_codec_ascii_h #define sanei_codec_ascii_h /** Initialize the ascii codec * * Set the i/o functions of the Wire to those of the ASCII codec. * * @param w Wire */ extern void sanei_codec_ascii_init (Wire *w); #endif /* sanei_codec_ascii_h */ sane-backends-1.0.27/include/sane/sanei_codec_bin.h0000664000175000017500000000451012112021330017011 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996 David Mosberger-Tang and Andreas Beck This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_codec_bin.h * Binary codec for network transmissions * * Transtale data to a byte stream while taking byte order problems into * account. This codec is currently used for saned and the network backend. * * @sa sanei_codec_ascii.h sanei_net.h sanei_wire.h */ #ifndef sanei_codec_bin_h #define sanei_codec_bin_h /** Initialize the binary codec * * Set the i/o functions of the Wire to those of the binary codec. * * @param w Wire */ extern void sanei_codec_bin_init (Wire *w); #endif /* sanei_codec_bin_h */ sane-backends-1.0.27/include/sane/sanei_udp.h0000664000175000017500000000263312775312262015726 00000000000000/* sane - Scanner Access Now Easy. * Copyright (C) 2007 Tower Technologies * Author: Alessandro Zummo * This file is part of the SANE package. * * This file is in the public domain. You may use and modify it as * you see fit, as long as this copyright message is included and * that there is an indication as to what modifications have been * made (if any). * * SANE is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * Header file for UDP/IP communications. */ #ifndef sanei_udp_h #define sanei_udp_h #include #ifdef HAVE_WINSOCK2_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif extern SANE_Status sanei_udp_open(const char *host, int port, int *fdp); extern SANE_Status sanei_udp_open_broadcast(int *fdp); extern void sanei_udp_close(int fd); extern void sanei_udp_set_nonblock(int fd, SANE_Bool nonblock); extern ssize_t sanei_udp_write(int fd, const u_char * buf, int count); extern ssize_t sanei_udp_read(int fd, u_char * buf, int count); extern ssize_t sanei_udp_write_broadcast(int fd, int port, const u_char * buf, int count); extern ssize_t sanei_udp_recvfrom(int fd, u_char * buf, int count, char **fromp); #endif /* sanei_udp_h */ sane-backends-1.0.27/include/sane/sanei_auth.h0000664000175000017500000000700312112021330016045 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_auth.h * Interface for authorization of resources * * This file implements an interface for user authorization. The authorization * call is forwarded to the frontend which asks for a username and password. * An MD5 digest is used if supported by the frontend. * * @sa sanei.h sanei_backend.h */ #ifndef sanei_auth_h #define sanei_auth_h #include "../include/sane/sane.h" /** Check authorization for a resource * * This function looks for the file SANE_CONFIG_DIR/backend.users. * If this file doesn't exist, sanei_authorize always returns SANE_STATUS_GOOD. * The file backend.users contains a list of usernames, passwords, and * resources: * * username:password:resource * username:password:resource * * If the requested resource isn't listed in this file, sanei_authorize * return SANE_SATUS_GOOD. In all other cases, sanei_authorize sends a * challenge to the frontend of the form * * resource$MD5$randomstring * * where randomstring consists of the PID, the time, and some random * characters. It accepts two forms of answers * * std: username:password * md5: username:$MD5$m5digest * * where md5digest is md5(randomstring password). * * If this username/password/resource triple is listed in backend.users * sanei_authorize returns SANE_STATUS_GOOD, in all other cases it returns * SANE_STATUS_ACCESS_DENIED. * * @param resource resource to authorize * @param backend backend name * @param authorize auth callback * * @return * - SANE_STATUS_GOOD - access is granted * - SANE_STATUS_ACCESS_DENIED - access is denied */ SANE_Status sanei_authorize (const char *resource, const char *backend, SANE_Auth_Callback authorize); #endif /* sanei_auth_h */ sane-backends-1.0.27/include/sane/sanei_ab306.h0000664000175000017500000000452012112021330015720 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Andreas Czechanowski This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef sanei_ab306_h #define sanei_ab306_h #include #include SANE_Status sanei_ab306_open (const char *dev, int *fd); void sanei_ab306_close (int fd); void sanei_ab306_exit (void); SANE_Status sanei_ab306_get_io_privilege (int fd); SANE_Status sanei_ab306_test_ready (int fd); SANE_Status sanei_ab306_cmd (int fd, const void *src, size_t src_size, void *dst, size_t *dst_size); SANE_Status sanei_ab306_rdata (int fd, int planes, SANE_Byte *buf, int lines, int bpl); #endif /* sanei_ab306_h */ sane-backends-1.0.27/include/sane/sanei.h0000664000175000017500000001306112775312262015053 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996 David Mosberger-Tang and Andreas Beck Copyright (C) 2002, 2003 Henning Meier-Geinitz This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei.h * Convenience macros and function declarations for backends * @sa sanei_backend.h sanei_thread.h */ /* Doxygen documentation */ /** @mainpage SANEI (SANE internal routines) documentation * * @image html sane-logo2.jpg * @section intro Introduction * * The header files in the include/sane/ directory named sanei_*.h provide * function declarations and macros that can be used by every SANE backend. * Their implementations can be found in the sanei/ directory. The code aims * to be platform-independent to avoid lots of \#ifdef code in the backends. * Please use the SANEI functions wherever possible. * * This documentation was created by the use of doxygen, the * doc/doxygen-sanei.conf configuration file and documentation in the sanei_*.h * files. * * This documentation is far from complete. Any help is appreciated. * * @section additional Additional documentation * - The SANE standard can be found at the SANE webserver, * though the PostScript version produced from the source may be more recent. * - Information on how to write a backend: backend-writing.txt. * - General SANE documentation is on the SANE documentation * page. * * @section contact Contact * * The common way to contact the developers of SANE is the sane-devel * mailing list. See the mailing list webpage * for details. That's the place to ask questions, report bugs, or announce * a new backend. * */ #ifndef sanei_h #define sanei_h #include /** @name Public macros and functions * @{ */ /** @def __sane_unused__ * Mark parameters as potentially unused. */ /** @def STRINGIFY(x) * Turn parameter into string. */ /** @def PASTE(x,y) * Concatenate parameters. * */ /** @def NELEMS(a) * Return number of elements of an array. * */ /** @fn extern SANE_Status sanei_check_value (const SANE_Option_Descriptor * opt, void * value); * Check the constraints of a SANE option. * * @param opt option to check * @param value value of the option * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if the value doesn't fit inside the constraint * or any other error occured * @sa sanei_constrain_value() */ /** @fn extern SANE_Status sanei_constrain_value (const SANE_Option_Descriptor * opt, void * value, SANE_Word * info); * Check the constraints of a SANE option and adjust its value if necessary. * * Depending on the type of the option and constraint, value is modified * to fit inside constraint. * * @param opt option to check * @param value value of the option * @param info info is set to SANE_INFO_INEXACT if value was changed * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if the function wasn't able to fit value into the * constraint or any other error occured * @sa sanei_check_value() */ /* @} */ /* A few convenience macros: */ /** @hideinitializer */ #ifdef __GNUC__ #define __sane_unused__ __attribute__((unused)) #else #define __sane_unused__ #endif /** @hideinitializer */ #define NELEMS(a) ((int)(sizeof (a) / sizeof (a[0]))) /** @hideinitializer */ #define STRINGIFY1(x) #x /** @hideinitializer */ #define STRINGIFY(x) STRINGIFY1(x) /** @hideinitializer */ #define PASTE1(x,y) x##y /** @hideinitializer */ #define PASTE(x,y) PASTE1(x,y) extern SANE_Status sanei_check_value (const SANE_Option_Descriptor * opt, void * value); extern SANE_Status sanei_constrain_value (const SANE_Option_Descriptor * opt, void * value, SANE_Word * info); #endif /* sanei_h */ sane-backends-1.0.27/include/sane/sanei_scsi.h0000664000175000017500000003043212112021330016047 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_scsi.h * Generic interface to SCSI drivers. * @sa sanei_usb.h, sanei_ab306.h,sanei_lm983x.h, sanei_pa4s2.h, sanei_pio.h, * and man sane-scsi(5) for user-oriented documentation */ #ifndef sanei_scsi_h #define sanei_scsi_h #include #include #include /** Sense handler * * The sense handler can be implemented in backends. It's for deciding * which sense codes should be considered an error and which shouldn't. * * @param fd file descriptor * @param sense_buffer pointer to buffer containing sense codes * @param arg pointer to data buffer * * @return * - SANE_STATUS_GOOD - on success (sense isn't regarded as error) * - any other status if sense code is regarded as error */ typedef SANE_Status (*SANEI_SCSI_Sense_Handler) (int fd, u_char *sense_buffer, void *arg); /** Maximum size of a SCSI request */ extern int sanei_scsi_max_request_size; /** Find SCSI devices. * * Find each SCSI device that matches the pattern specified by the * arguments. String arguments can be "omitted" by passing NULL, * integer arguments can be "omitted" by passing -1. * * Example: vendor="HP" model=NULL, type=NULL, bus=3, id=-1, lun=-1 would * attach all HP devices on SCSI bus 3. * * @param vendor * @param model * @param type * @param bus * @param channel * @param id * @param lun * @param attach callback invoked once for each device, dev is the real devicename (passed to attach callback) * */ extern void sanei_scsi_find_devices (const char *vendor, const char *model, const char *type, int bus, int channel, int id, int lun, SANE_Status (*attach) (const char *dev)); /** Open a SCSI device * * Opens a SCSI device by its device filename and returns a file descriptor. * If it's necessary to adjust the SCSI buffer size, use * sanei_scsi_open_extended(). * * @param device_name name of the devicefile, e.g. "/dev/sg0" * @param fd file descriptor * @param sense_handler called whenever the SCSI driver returns a sense buffer * @param sense_arg pointer to data for the sense handler * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_ACCESS_DENIED - if the file couldn't be accessed due to * permissions * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory) * - SANE_STATUS_INVAL - if the filename was invalid or an unknown error occured * * @sa sanei_scsi_open_extended(), HAVE_SANEI_SCSI_OPEN_EXTENDED */ extern SANE_Status sanei_scsi_open (const char * device_name, int * fd, SANEI_SCSI_Sense_Handler sense_handler, void *sense_arg); /** Open a SCSI device and set the buffer size * * The extended open call allows a backend to ask for a specific buffer * size. sanei_scsi_open_extended() tries to allocate a buffer of the size * given by *buffersize upon entry to this function. If * sanei_scsi_open_extended returns successfully, *buffersize contains the * available buffer size. This value may be both smaller or larger than the * value requested by the backend; it can even be zero. The backend must * decide, if it got enough buffer memory to work. * * Note that the value of *buffersize may differ for different files. * * @param device_name name of the devicefile, e.g. "/dev/sg0" * @param fd file descriptor * @param sense_handler called whenever the SCSI driver returns a sense buffer * @param sense_arg pointer to data for the sense handler * @param buffersize size of the SCAI request buffer (in bytes) * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_ACCESS_DENIED - if the file couldn't be accessed due to * permissions * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory) * - SANE_STATUS_INVAL - if the filename was invalid or an unknown error occured * * @sa sanei_scsi_open(), HAVE_SANEI_SCSI_OPEN_EXTENDED */ extern SANE_Status sanei_scsi_open_extended ( const char * device_name, int * fd, SANEI_SCSI_Sense_Handler sense_handler, void *sense_arg, int *buffersize); /** Do we have sanei_scsi_open_extended()? * * Let backends decide, which open call to use: if * HAVE_SANEI_SCSI_OPEN_EXTENDED is defined, sanei_scsi_open_extended may be * used. May also be used to decide, if sanei_scsi_req_flush_all or * sanei_scsi_req_flush_all_extended() should be used. * * @sa sanei_scsi_open(), sanei_scsi_open_extended() */ #define HAVE_SANEI_SCSI_OPEN_EXTENDED /** Enqueue SCSI command * * One or more scsi commands can be enqueued by calling sanei_scsi_req_enter(). * * NOTE: Some systems may not support multiple outstanding commands. On such * systems, sanei_scsi_req_enter() may block. In other words, it is not proper * to assume that enter() is a non-blocking routine. * * @param fd file descriptor * @param src pointer to the SCSI command and associated write data (if any) * @param src_size length of the command and data * @param dst pointer to a buffer in which data is returned; NULL if no data is * returned * @param dst_size on input, the size of the buffer pointed to by dst, on exit, * set to the number of bytes returned in the buffer (which is less than or equal * to the buffer size; may be NULL if no data is expected * @param idp pointer to a void* that uniquely identifies the entered request * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - if an error was received from the SCSI driver * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory) * - SANE_STATUS_INVAL - if a locking or an unknown error occured * @sa sanei_scsi_req_enter2() * */ extern SANE_Status sanei_scsi_req_enter (int fd, const void * src, size_t src_size, void * dst, size_t * dst_size, void **idp); /** Enqueue SCSI command and separated data * * Same as sanei_scsi_req_enter(), but with separate buffers for the SCSI * command and for the data to be sent to the device. * * With sanei_scsi_req_enter(), the length of te SCSI command block must be * guessed. While that works in most cases, Canon scanners for example use the * vendor specific commands 0xd4, 0xd5 and 0xd6. The Canon scanners want to * get 6 byte command blocks for these commands, but sanei_scsi_req_enter() and * sanei_scsi_cmd() send 12 bytes. * * If dst_size and *dst_size are non-zero, a "read command" (ie, data transfer * from the device to the host) is assumed. * * @param fd file descriptor * @param cmd pointer to SCSI command * @param cmd_size size of the command * @param src pointer to the buffer with data to be sent to the scanner * @param src_size size of src buffer * @param dst pointer to a buffer in which data is returned; NULL if no data is * returned * @param dst_size on input, the size of the buffer pointed to by dst, on exit, * set to the number of bytes returned in the buffer (which is less than or equal * to the buffer size; may be NULL if no data is expected * @param idp pointer to a void* that uniquely identifies the entered request * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - if an error was received from the SCSI driver * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory) * - SANE_STATUS_INVAL - if a locking or an unknown error occured * @sa sanei_scsi_req_enter() */ extern SANE_Status sanei_scsi_req_enter2 (int fd, const void * cmd, size_t cmd_size, const void * src, size_t src_size, void * dst, size_t * dst_size, void **idp); /** Wait for SCSI command * * Wait for the completion of the SCSI command with id ID. * * @param id id used in sanei_scsi_req_enter() * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_DEVICE_BUSY - if the device is busy (try again later) * - SANE_STATUS_IO_ERROR - if an error was received from the SCSI driver */ extern SANE_Status sanei_scsi_req_wait (void *id); /** Send SCSI command * * This is a convenience function that is equivalent to a pair of * sanei_scsi_req_enter()/sanei_scsi_req_wait() calls. * * @param fd file descriptor * @param src pointer to the SCSI command and associated write data (if any) * @param src_size length of the command and data * @param dst pointer to a buffer in which data is returned; NULL if no data is * returned * @param dst_size on input, the size of the buffer pointed to by dst, on exit, * set to the number of bytes returned in the buffer (which is less than or equal * to the buffer size; may be NULL if no data is expected * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - if an error was received from the SCSI driver * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory) * - SANE_STATUS_INVAL - if a locking or an unknown error occured * * @sa sanei_scsi_cmd2(), sanei_scsi_req_enter(), sanei_scsi_req_wait() */ extern SANE_Status sanei_scsi_cmd (int fd, const void * src, size_t src_size, void * dst, size_t * dst_size); /** Send SCSI command and separated data * * This is a convenience function that is equivalent to a pair of * sanei_scsi_req_enter2()/sanei_scsi_req_wait() calls. * * @param fd file descriptor * @param cmd pointer to SCSI command * @param cmd_size size of the command * @param src pointer to the buffer with data to be sent to the scanner * @param src_size size of src buffer * @param dst pointer to a buffer in which data is returned; NULL if no data is * returned * @param dst_size on input, the size of the buffer pointed to by dst, on exit, * set to the number of bytes returned in the buffer (which is less than or equal * to the buffer size; may be NULL if no data is expected * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - if an error was received from the SCSI driver * - SANE_STATUS_NO_MEM - if malloc failed (not enough memory) * - SANE_STATUS_INVAL - if a locking or an unknown error occured * * @sa sanei_scsi_cmd(), sanei_scsi_req_enter(), sanei_scsi_req_wait() */ extern SANE_Status sanei_scsi_cmd2 (int fd, const void * cmd, size_t cmd_size, const void * src, size_t src_size, void * dst, size_t * dst_size); /** Flush queue * * Flush all pending SCSI commands. This function work only, if zero or one * SCSI file handles are open. * * @sa sanei_scsi_req_flush_all_extended() */ extern void sanei_scsi_req_flush_all (void); /** Flush queue for handle * * Flush all SCSI commands pending for one handle * * @param fd file descriptor * * @sa sanei_scsi_req_flush_all() */ extern void sanei_scsi_req_flush_all_extended (int fd); /** Close a SCSI device * * @param fd file descriptor * */ extern void sanei_scsi_close (int fd); #endif /* sanei_scsi_h */ sane-backends-1.0.27/include/sane/sanei_pp.h0000664000175000017500000001316512112021330015531 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Gerhard Jaeger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_pp.h * This file implements an interface for accessing the parallel-port * * @sa sanei_pp.h */ #ifndef sanei_pp_h #define sanei_pp_h #include #include /** some modes, we'd like to see/use. */ enum sanei_pp_mode { SANEI_PP_MODE_SPP = (1<<1), /**< SPP */ SANEI_PP_MODE_BIDI = (1<<2), /**< BIDI */ SANEI_PP_MODE_EPP = (1<<4), /**< EPP */ SANEI_PP_MODE_ECP = (1<<8) /**< ECP */ }; #define SANEI_PP_DATAIN 1 #define SANEI_PP_DATAOUT 0 /* @{ */ /** Parallelport Control-Register definitions */ #define SANEI_PP_CTRL_STROBE 0x01 #define SANEI_PP_CTRL_AUTOLF 0x02 #define SANEI_PP_CTRL_NOT_INIT 0x04 #define SANEI_PP_CTRL_SELECT_IN 0x08 #define SANEI_PP_CTRL_ENABLE_IRQ 0x10 #define SANEI_PP_CTRL_DIRECTION 0x20 #define SANEI_PP_CTRL_RESERVED 0xc0 /* @} */ /** Initialize sanei_pp. * * This function must be called before any other sanei_pp function. */ extern SANE_Status sanei_pp_init( void ); /** Open a parport device. * * @param dev - name of device to open. * @param fd - pointer to variable that should revceive the handle. * @return */ extern SANE_Status sanei_pp_open( const char *dev, int *fd ); /* Close a previously opened parport device. * * @param fd - handle of the device to close */ extern void sanei_pp_close( int fd ); /** Claim a parport device * * @param fd - handle of the device to claim * @return */ extern SANE_Status sanei_pp_claim( int fd ); /** Release a previously claimed device * * @param fd - handle of the device to release * @return */ extern SANE_Status sanei_pp_release( int fd ); /** Set the data direction * * @param fd - handle of the device, where to change the direction. * @param rev - * @return SANE_STATUS_GOOD on success */ extern SANE_Status sanei_pp_set_datadir( int fd, int rev ); /** Check whether for libieee1284 usage. * * This function can be used to check if the lib uses libieee1284 or * in/out functions directly. * * @return SANE_TRUE if we use direct access, SANE_FALSE if the lib uses * libieee1284 functions. */ extern SANE_Bool sanei_pp_uses_directio( void ); /** Determine the available parallel port modes for a given device. * * @param fd - handle of the device, whose modes shall be checked for. * @param mode - pointer to variable, which should receive the modes. * @return SANE_STATUS_GOOD on success. */ extern SANE_Status sanei_pp_getmodes( int fd, int *mode ); /** Set the operation mode for a given device. * * @param fd - handle of the device, whose modes shall be set. * @param mode - mode to set, see sanei_pp_mode. * @return SANE_STATUS_GOOD on success. */ extern SANE_Status sanei_pp_setmode( int fd, int mode ); /** Write data to ports (spp-data, ctrl, epp-address and epp-data) * * @param fd - handle of device to which shall be written to. * @param val - data to write. * @return SANE_STATUS_GOOD on success. */ extern SANE_Status sanei_pp_outb_data( int fd, SANE_Byte val ); extern SANE_Status sanei_pp_outb_ctrl( int fd, SANE_Byte val ); extern SANE_Status sanei_pp_outb_addr( int fd, SANE_Byte val ); extern SANE_Status sanei_pp_outb_epp ( int fd, SANE_Byte val ); /** Read data from ports (spp-data, status, ctrl and epp-data) * @param fd - handle of device who should be read from. * @return value got from port */ extern SANE_Byte sanei_pp_inb_data( int fd ); extern SANE_Byte sanei_pp_inb_stat( int fd ); extern SANE_Byte sanei_pp_inb_ctrl( int fd ); extern SANE_Byte sanei_pp_inb_epp ( int fd ); /** Delay execution for some micro-seconds. * Please not, that the accuracy highly depends on your system architechture * and the time to delay. It is internally implemented as system calls to * gettimeofday(). * * @param usec - number of micro-seconds to delay */ extern void sanei_pp_udelay( unsigned long usec ); #endif sane-backends-1.0.27/include/sane/sanei_magic.h0000644000175000017500000001716613072433473016222 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2009 m. allan noah This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_magic.h * This file provides an interface to simple image post-processing functions * * Currently, three operations are provided: * - Deskew (correct rotated scans, by detecting media edges) * - Autocrop (reduce image size to minimum rectangle containing media) * - Despeckle (replace dots of significantly different color with background) * - Blank detection (check if density is over a threshold) * - Rotate (detect and correct 90 degree increment rotations) * * Note that these functions are simplistic, and are expected to change. * Patches and suggestions are welcome. */ #ifndef SANEI_MAGIC_H #define SANEI_MAGIC_H /** Initialize sanei_magic. * * Call this before any other sanei_magic function. */ extern void sanei_magic_init( void ); /** Update the image buffer, replacing dots with surrounding background color * * @param params describes image * @param buffer contains image data * @param diam maximum dot diameter to remove * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_INVAL - invalid image parameters */ extern SANE_Status sanei_magic_despeck (SANE_Parameters * params, SANE_Byte * buffer, SANE_Int diam); /** Find the skew of the media inside the image, via edge detection. * * @param params describes image * @param buffer contains image data * @param dpiX horizontal resolution * @param dpiY vertical resolution * @param[out] centerX horizontal coordinate of center of rotation * @param[out] centerY vertical coordinate of center of rotation * @param[out] finSlope slope of rotation * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - not enough memory * - SANE_STATUS_INVAL - invalid image parameters * - SANE_STATUS_UNSUPPORTED - slope angle too shallow to detect */ extern SANE_Status sanei_magic_findSkew(SANE_Parameters * params, SANE_Byte * buffer, int dpiX, int dpiY, int * centerX, int * centerY, double * finSlope); /** Correct the skew of the media inside the image, via simple rotation * * @param params describes image * @param buffer contains image data * @param centerX horizontal coordinate of center of rotation * @param centerY vertical coordinate of center of rotation * @param slope slope of rotation * @param bg_color the replacement color for edges exposed by rotation * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - not enough memory * - SANE_STATUS_INVAL - invalid image parameters */ extern SANE_Status sanei_magic_rotate (SANE_Parameters * params, SANE_Byte * buffer, int centerX, int centerY, double slope, int bg_color); /** Find the edges of the media inside the image, parallel to image edges * * @param params describes image * @param buffer contains image data * @param dpiX horizontal resolution * @param dpiY vertical resolution * @param[out] top vertical offset to upper edge of media * @param[out] bot vertical offset to lower edge of media * @param[out] left horizontal offset to left edge of media * @param[out] right horizontal offset to right edge of media * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - not enough memory * - SANE_STATUS_UNSUPPORTED - edges could not be detected */ extern SANE_Status sanei_magic_findEdges(SANE_Parameters * params, SANE_Byte * buffer, int dpiX, int dpiY, int * top, int * bot, int * left, int * right); /** Crop the image, parallel to image edges * * @param params describes image * @param buffer contains image data * @param top vertical offset to upper edge of crop * @param bot vertical offset to lower edge of crop * @param left horizontal offset to left edge of crop * @param right horizontal offset to right edge of crop * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - not enough memory * - SANE_STATUS_INVAL - invalid image parameters */ extern SANE_Status sanei_magic_crop(SANE_Parameters * params, SANE_Byte * buffer, int top, int bot, int left, int right); /** Determine if image is blank * * @param params describes image * @param buffer contains image data * @param thresh maximum % density for blankness (0-100) * * @return * - SANE_STATUS_GOOD - page is not blank * - SANE_STATUS_NO_DOCS - page is blank * - SANE_STATUS_NO_MEM - not enough memory * - SANE_STATUS_INVAL - invalid image parameters */ extern SANE_Status sanei_magic_isBlank(SANE_Parameters * params, SANE_Byte * buffer, double thresh); /** Determine if image is blank, enhanced version * * @param params describes image * @param buffer contains image data * @param dpiX horizontal resolution * @param dpiY vertical resolution * @param thresh maximum % density for blankness (0-100) * * @return * - SANE_STATUS_GOOD - page is not blank * - SANE_STATUS_NO_DOCS - page is blank * - SANE_STATUS_NO_MEM - not enough memory * - SANE_STATUS_INVAL - invalid image parameters */ extern SANE_Status sanei_magic_isBlank2(SANE_Parameters * params, SANE_Byte * buffer, int dpiX, int dpiY, double thresh); /** Determine coarse image rotation (90 degree increments) * * @param params describes image * @param buffer contains image data * @param dpiX horizontal resolution * @param dpiY vertical resolution * @param[out] angle amount of rotation recommended * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - not enough memory * - SANE_STATUS_INVAL - invalid image parameters */ extern SANE_Status sanei_magic_findTurn(SANE_Parameters * params, SANE_Byte * buffer, int dpiX, int dpiY, int * angle); /** Coarse image rotation (90 degree increments) * * @param params describes image * @param buffer contains image data * @param angle amount of rotation requested (multiple of 90) * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - not enough memory * - SANE_STATUS_INVAL - invalid image or angle parameters */ extern SANE_Status sanei_magic_turn(SANE_Parameters * params, SANE_Byte * buffer, int angle); #endif /* SANEI_MAGIC_H */ sane-backends-1.0.27/include/sane/sanei_usb.h0000664000175000017500000004021312775312262015723 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001, 2002 Henning Meier-Geinitz Copyright (C) 2003, 2005 Rene Rebe (sanei_read_int,sanei_set_timeout) Copyright (C) 2008 m. allan noah (sanei_usb_clear_halt) Copyright (C) 2011 Reinhold Kainhofer (sanei_usb_set_endpoint) This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_usb.h * This file provides a generic USB interface. * * Currently, two access methods to USB devices are provided: * - Access to device * files as used by the Linux kernel USB scanner driver is supported. FreeBSD * and OpenBSD with their uscanner drivers also work this way. However, * detection and control messages aren't supported on these platforms. * - Access using libusb (where available). * * A general remark: Do not mix sanei_usb functions with "normal" file-related * libc functions like open() or close. The device numbers used in sanei_usb * are not file descriptors. * * @sa sanei_lm983x.h, sanei_pa4s2.h, sanei_pio.h, sanei_scsi.h, and man sane-usb(5) * for user-oriented documentation */ #ifndef sanei_usb_h #define sanei_usb_h #include "../include/sane/config.h" #include "../include/sane/sane.h" #include /* for size_t */ /* USB spec defines */ #ifndef USB_CLASS_PER_INTERFACE /* Also defined in libusb */ /** @name Device and/or interface class codes */ /* @{ */ #define USB_CLASS_PER_INTERFACE 0x00 #define USB_CLASS_AUDIO 0x01 #define USB_CLASS_COMM 0x02 #define USB_CLASS_HID 0x03 #define USB_CLASS_PRINTER 0x07 #define USB_CLASS_MASS_STORAGE 0x08 #define USB_CLASS_HUB 0x09 #define USB_CLASS_DATA 0x0a #define USB_CLASS_VENDOR_SPEC 0xff /* @} */ /** @name USB descriptor types */ /* @{ */ #define USB_DT_DEVICE 0x01 #define USB_DT_CONFIG 0x02 #define USB_DT_STRING 0x03 #define USB_DT_INTERFACE 0x04 #define USB_DT_ENDPOINT 0x05 #define USB_DT_HID 0x21 #define USB_DT_REPORT 0x22 #define USB_DT_PHYSICAL 0x23 #define USB_DT_HUB 0x29 /* @} */ /** @name Descriptor sizes per descriptor type */ /* @{ */ #define USB_DT_DEVICE_SIZE 18 #define USB_DT_CONFIG_SIZE 9 #define USB_DT_INTERFACE_SIZE 9 #define USB_DT_ENDPOINT_SIZE 7 #define USB_DT_ENDPOINT_AUDIO_SIZE 9 #define USB_DT_HUB_NONVAR_SIZE 7 /* @} */ /** @name Endpoint descriptors */ /* @{ */ #define USB_ENDPOINT_ADDRESS_MASK 0x0f #define USB_ENDPOINT_DIR_MASK 0x80 #define USB_ENDPOINT_TYPE_MASK 0x03 #define USB_ENDPOINT_TYPE_CONTROL 0 #define USB_ENDPOINT_TYPE_ISOCHRONOUS 1 #define USB_ENDPOINT_TYPE_BULK 2 #define USB_ENDPOINT_TYPE_INTERRUPT 3 /* @} */ /** @name Standard requests */ /* @{ */ #define USB_REQ_GET_STATUS 0x00 #define USB_REQ_CLEAR_FEATURE 0x01 #define USB_REQ_SET_FEATURE 0x03 #define USB_REQ_SET_ADDRESS 0x05 #define USB_REQ_GET_DESCRIPTOR 0x06 #define USB_REQ_SET_DESCRIPTOR 0x07 #define USB_REQ_GET_CONFIGURATION 0x08 #define USB_REQ_SET_CONFIGURATION 0x09 #define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SYNCH_FRAME 0x0C /* @} */ /** @name USB types */ /* @{ */ #define USB_TYPE_STANDARD (0x00 << 5) #define USB_TYPE_CLASS (0x01 << 5) #define USB_TYPE_VENDOR (0x02 << 5) #define USB_TYPE_RESERVED (0x03 << 5) /* @} */ /** @name USB recipients */ /* @{ */ #define USB_RECIP_DEVICE 0x00 #define USB_RECIP_INTERFACE 0x01 #define USB_RECIP_ENDPOINT 0x02 #define USB_RECIP_OTHER 0x03 /* @} */ #endif /* not USB_CLASS_PER_INTERFACE */ /* Not defined in libsub */ /** @name USB Masks */ /* @{ */ #define USB_TYPE_MASK (0x03 << 5) #define USB_RECIP_MASK 0x1f /* @} */ /** @name USB directions */ /* @{ */ #define USB_DIR_OUT 0x00 #define USB_DIR_IN 0x80 /* @} */ /** */ struct sanei_usb_dev_descriptor { SANE_Byte desc_type; unsigned int bcd_usb; unsigned int bcd_dev; SANE_Byte dev_class; SANE_Byte dev_sub_class; SANE_Byte dev_protocol; SANE_Byte max_packet_size; }; /** Initialize sanei_usb. * * Call this before any other sanei_usb function. */ extern void sanei_usb_init (void); /** End sanei_usb use, freeing resources when needed. * * When the use count of sanei_usb reach 0, free resources and end * sanei_usb use. */ extern void sanei_usb_exit (void); /** Search for USB devices. * * Search USB busses for scanner devices. */ extern void sanei_usb_scan_devices (void); /** Get the vendor and product ids by device name. * * @param devname * @param vendor vendor id * @param product product id * * @return * - SANE_STATUS_GOOD - if the ids could be determined * - SANE_STATUS_INVAL - if the device is not found * - SANE_STATUS_UNSUPPORTED - if this method is not supported with the current * access method */ SANE_Status sanei_usb_get_vendor_product_byname (SANE_String_Const devname, SANE_Word * vendor, SANE_Word * product); /** Get the vendor and product ids. * * Currently, only libusb devices and scanners supported by the Linux USB * scanner module can be found. For the latter method, the Linux version * must be 2.4.8 or higher. * * @param dn device number of an already sanei_usb_opened device * @param vendor vendor id * @param product product id * * @return * - SANE_STATUS_GOOD - if the ids could be determined * - SANE_STATUS_UNSUPPORTED - if the OS doesn't support detection of ids */ extern SANE_Status sanei_usb_get_vendor_product (SANE_Int dn, SANE_Word * vendor, SANE_Word * product); /** Find devices that match given vendor and product ids. * * For limitations, see function sanei_usb_get_vendor_product(). * The function attach is called for every device which has been found. * * @param vendor vendor id * @param product product id * @param attach attach function * * @return SANE_STATUS_GOOD - on success (even if no scanner was found) */ extern SANE_Status sanei_usb_find_devices (SANE_Int vendor, SANE_Int product, SANE_Status (*attach) (SANE_String_Const devname)); /** Open a USB device. * * The device is opened by its name devname and the device number is * returned in dn on success. * * Device names can be either device file names for direct access over * kernel drivers (like /dev/usb/scanner) or libusb names. The libusb format * looks like this: "libusb:bus-id:device-id". Bus-id and device-id are * platform-dependent. An example could look like this: "libusb:001:002" * (Linux). * * @param devname name of the device to open * @param dn device number * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_ACCESS_DENIED - if the file couldn't be accessed due to * permissions * - SANE_STATUS_INVAL - on every other error */ extern SANE_Status sanei_usb_open (SANE_String_Const devname, SANE_Int * dn); /** Set the endpoint for the USB communication * * Allows to switch to a different endpoint for the USB communication than * the default (auto-detected) endpoint. This function can only be called * after sanei_usb_open. * * @param dn device number * @param ep_type type of endpoint to set (bitwise or of USB_DIR_IN/OUT and * USB_ENDPOINT_TYPE_BULK/CONTROL/INTERRUPT/ISOCHRONOUS * @param ep endpoint to use for the given type * */ extern void sanei_usb_set_endpoint (SANE_Int dn, SANE_Int ep_type, SANE_Int ep); /** Retrieve the endpoint used for the USB communication * * Returns the endpoint used for the USB communication of the given type. * This function can only be called after sanei_usb_open. * * @param dn device number * @param ep_type type of endpoint to retrieve (bitwise or of USB_DIR_IN/OUT * and USB_ENDPOINT_TYPE_BULK/CONTROL/INTERRUPT/ISOCHRONOUS * @return endpoint used for the given type * */ extern SANE_Int sanei_usb_get_endpoint (SANE_Int dn, SANE_Int ep_type); /** Close a USB device. * * @param dn device number */ extern void sanei_usb_close (SANE_Int dn); /** Set the libusb timeout for bulk and interrupt reads. * * @param timeout the new timeout in ms */ extern void sanei_usb_set_timeout (SANE_Int timeout); /** Check if sanei_usb_set_timeout() is available. */ #define HAVE_SANEI_USB_SET_TIMEOUT /** Clear halt condition on bulk endpoints * * @param dn device number */ extern SANE_Status sanei_usb_clear_halt (SANE_Int dn); /** Check if sanei_usb_clear_halt() is available. */ #define HAVE_SANEI_USB_CLEAR_HALT /** Reset device * * @param dn device number */ extern SANE_Status sanei_usb_reset (SANE_Int dn); /** Initiate a bulk transfer read. * * Read up to size bytes from the device to buffer. After the read, size * contains the number of bytes actually read. * * @param dn device number * @param buffer buffer to store read data in * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_usb_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size); /** Initiate a bulk transfer write. * * Write up to size bytes from buffer to the device. After the write size * contains the number of bytes actually written. * * @param dn device number * @param buffer buffer to write to device * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_IO_ERROR - if an error occured during the write * - SANE_STATUS_INVAL - on every other error */ extern SANE_Status sanei_usb_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size); /** Send/receive a control message to/from a USB device. * * This function is only supported for libusb devices and kernel acces with * Linux 2.4.13 and newer. * For a detailed explanation of the parameters, have a look at the USB * specification at the * www.usb.org developers information page. * * @param dn device number * @param rtype specifies the characteristics of the request (e.g. data * direction) * @param req actual request * @param value parameter specific to the request * @param index parameter specific to the request (often used to select * endpoint) * @param len length of data to send/receive * @param data buffer to send/receive data * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - on error * - SANE_STATUS_UNSUPPORTED - if the feature is not supported by the OS or * SANE. */ extern SANE_Status sanei_usb_control_msg (SANE_Int dn, SANE_Int rtype, SANE_Int req, SANE_Int value, SANE_Int index, SANE_Int len, SANE_Byte * data); /** Initiate a interrupt transfer read. * * Read up to size bytes from the interrupt endpoint from the device to * buffer. After the read, size contains the number of bytes actually read. * * @param dn device number * @param buffer buffer to store read data in * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_usb_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size); /** Expand device name patterns into a list of devices. * * Apart from a normal device name (such as /dev/usb/scanner0 or * libusb:002:003), this function currently supports USB device * specifications of the form: * * usb VENDOR PRODUCT * * VENDOR and PRODUCT are non-negative integer numbers in decimal or * hexadecimal format. A similar function for SCSI devices can be found * in include/sane/config.h. * * @param name device name pattern * @param attach attach function * */ extern void sanei_usb_attach_matching_devices (const char *name, SANE_Status (*attach) (const char *dev)); /** Initiate set configuration. * * Change set configuration * * @param dn device number * @param configuration, configuration nummber * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_usb_set_configuration (SANE_Int dn, SANE_Int configuration); /** Initiate claim interface. * * Change claim interface * * @param dn device number * @param interface_number interface number * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_usb_claim_interface (SANE_Int dn, SANE_Int interface_number); /** Initiate release interface. * * Change release interface * * @param dn device number * @param interface_number interface number * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_usb_release_interface (SANE_Int dn, SANE_Int interface_number); /** Initiate a set altinterface. * * Change set alternate * * @param dn device number * @param alternate, alternate nummber * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_usb_set_altinterface (SANE_Int dn, SANE_Int alternate); /** Get some information from the device descriptor * * Sometimes it's useful to know something about revisions and * other stuff reported by the USB system * * @param dn device number * @param desc where to put the information to * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_UNSUPPORTED - if the feature is not supported by the OS or * SANE. * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_usb_get_descriptor( SANE_Int dn, struct sanei_usb_dev_descriptor *desc ); /*------------------------------------------------------*/ #endif /* sanei_usb_h */ sane-backends-1.0.27/include/sane/sanei_debug.h0000664000175000017500000000743212112021330016200 00000000000000/** @file sanei_debug.h * Support for printing debug messages. * * Use the functions of this header file to print debug or warning messages. */ #ifndef _SANEI_DEBUG_H #define _SANEI_DEBUG_H #include /** @name Public macros * These macros can be used in backends and other SANE-related * code. * * Before including sanei_debug.h, the following macros must be set: * * - BACKEND_NAME - The name of your backend without double-quotes (must be set in any case) * - STUBS - If this is defined, no macros will be included. Used in * backends consisting of more than one .c file. * - DEBUG_DECLARE_ONLY - Generates prototypes instead of functions. Used in * backends consisting of more than one .c file. * - DEBUG_NOT_STATIC - Doesn't generate static functions. Used in header files if * they are include in more than one .c file. * * @{ */ /** @def DBG_INIT() * Initialize sanei_debug. * * Call this function before you use any DBG function. */ /** @def DBG(level, fmt, ...) * Print a message at debug level `level' or higher using a printf-like * function. Example: DBG(1, "sane_open: opening fd \%d\\n", fd). * * @param level debug level * @param fmt format (see man 3 printf for details) * @param ... additional arguments */ /** @def IF_DBG(x) * Compile code only if debugging is enabled. * * Expands to x if debug support is enabled at compile-time. If NDEBUG is * defined at compile-time this macro expands to nothing. * * @param x code to expand when debugging is enabled */ /** * @def DBG_LEVEL * Current debug level. * * You can only read this "variable". */ /** @def ENTRY(name) * Expands to sane_BACKEND_NAME_name. * * Example: ENTRY(init) in mustek.c will expand to sane_mustek_init. */ /* @} */ /** @hideinitializer*/ #define ENTRY(name) PASTE(PASTE(PASTE(sane_,BACKEND_NAME),_),name) #ifdef NDEBUG extern void sanei_debug_ndebug (int level, const char *msg, ...); # define DBG_LEVEL (0) # define DBG_INIT() # define DBG sanei_debug_ndebug # define IF_DBG(x) #else /* !NDEBUG */ /** @hideinitializer*/ # define DBG_LEVEL PASTE(sanei_debug_,BACKEND_NAME) # if defined(BACKEND_NAME) && !defined(STUBS) # ifdef DEBUG_DECLARE_ONLY extern int DBG_LEVEL; # else /* !DEBUG_DECLARE_ONLY */ int DBG_LEVEL = 0; # endif /* DEBUG_DECLARE_ONLY */ # endif /* BACKEND_NAME && !STUBS */ /** @hideinitializer*/ # define DBG_INIT() \ sanei_init_debug (STRINGIFY(BACKEND_NAME), &DBG_LEVEL) /** @hideinitializer*/ # define DBG_LOCAL PASTE(DBG_LEVEL,_call) # ifndef STUBS # ifdef DEBUG_DECLARE_ONLY extern void DBG_LOCAL (int level, const char *msg, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) #endif ; # else /* !DEBUG_DECLARE_ONLY */ # include extern void sanei_debug_msg (int level, int max_level, const char *be, const char *fmt, va_list ap); #ifdef __GNUC__ # ifndef DEBUG_NOT_STATIC static # endif /* !DEBUG_NOT_STATIC */ void DBG_LOCAL (int level, const char *msg, ...) __attribute__ ((format (printf, 2, 3))); #endif /* __GNUC__ */ # ifndef DEBUG_NOT_STATIC static # endif /* !DEBUG_NOT_STATIC */ void DBG_LOCAL (int level, const char *msg, ...) { va_list ap; va_start (ap, msg); sanei_debug_msg (level, DBG_LEVEL, STRINGIFY(BACKEND_NAME), msg, ap); va_end (ap); } # endif /* DEBUG_DECLARE_ONLY */ # endif /* !STUBS */ /** @hideinitializer*/ # define DBG DBG_LOCAL extern void sanei_init_debug (const char * backend, int * debug_level_var); /** @hideinitializer*/ # define IF_DBG(x) x #endif /* NDEBUG */ #endif /* _SANEI_DEBUG_H */ sane-backends-1.0.27/include/sane/saneopts.h0000664000175000017500000004711012112021330015564 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang and Andreas Beck This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file declares common option names, titles, and descriptions. A backend is not limited to these options but for the sake of consistency it's better to use options declared here when appropriate. */ /* This file defines several option NAMEs, TITLEs and DESCs that are (or should be) used by several backends. All well known options should be listed here. But this does not mean that all options that are listed here are well known options. To find out if an option is a well known option and how well known options have to be defined please take a look at the sane standard!!! */ #ifndef saneopts_h #define saneopts_h #ifndef SANE_I18N #define SANE_I18N(text) text #endif /* This _must_ be the first option (index 0): */ #define SANE_NAME_NUM_OPTIONS "" /* never settable */ /* The common option groups */ #define SANE_NAME_STANDARD "standard" #define SANE_NAME_GEOMETRY "geometry" #define SANE_NAME_ENHANCEMENT "enhancement" #define SANE_NAME_ADVANCED "advanced" #define SANE_NAME_SENSORS "sensors" #define SANE_NAME_PREVIEW "preview" #define SANE_NAME_GRAY_PREVIEW "preview-in-gray" #define SANE_NAME_BIT_DEPTH "depth" #define SANE_NAME_SCAN_MODE "mode" #define SANE_NAME_SCAN_SPEED "speed" #define SANE_NAME_SCAN_SOURCE "source" #define SANE_NAME_BACKTRACK "backtrack" /* Most user-interfaces will let the user specify the scan area as the top-left corner and the width/height of the scan area. The reason the backend interface uses the top-left/bottom-right corner is so that the scan area values can be properly constraint independent of any other option value. */ #define SANE_NAME_SCAN_TL_X "tl-x" #define SANE_NAME_SCAN_TL_Y "tl-y" #define SANE_NAME_SCAN_BR_X "br-x" #define SANE_NAME_SCAN_BR_Y "br-y" #define SANE_NAME_SCAN_RESOLUTION "resolution" #define SANE_NAME_SCAN_X_RESOLUTION "x-resolution" #define SANE_NAME_SCAN_Y_RESOLUTION "y-resolution" #define SANE_NAME_PAGE_WIDTH "page-width" #define SANE_NAME_PAGE_HEIGHT "page-height" #define SANE_NAME_CUSTOM_GAMMA "custom-gamma" #define SANE_NAME_GAMMA_VECTOR "gamma-table" #define SANE_NAME_GAMMA_VECTOR_R "red-gamma-table" #define SANE_NAME_GAMMA_VECTOR_G "green-gamma-table" #define SANE_NAME_GAMMA_VECTOR_B "blue-gamma-table" #define SANE_NAME_BRIGHTNESS "brightness" #define SANE_NAME_CONTRAST "contrast" #define SANE_NAME_GRAIN_SIZE "grain" #define SANE_NAME_HALFTONE "halftoning" #define SANE_NAME_BLACK_LEVEL "black-level" #define SANE_NAME_WHITE_LEVEL "white-level" #define SANE_NAME_WHITE_LEVEL_R "white-level-r" #define SANE_NAME_WHITE_LEVEL_G "white-level-g" #define SANE_NAME_WHITE_LEVEL_B "white-level-b" #define SANE_NAME_SHADOW "shadow" #define SANE_NAME_SHADOW_R "shadow-r" #define SANE_NAME_SHADOW_G "shadow-g" #define SANE_NAME_SHADOW_B "shadow-b" #define SANE_NAME_HIGHLIGHT "highlight" #define SANE_NAME_HIGHLIGHT_R "highlight-r" #define SANE_NAME_HIGHLIGHT_G "highlight-g" #define SANE_NAME_HIGHLIGHT_B "highlight-b" #define SANE_NAME_HUE "hue" #define SANE_NAME_SATURATION "saturation" #define SANE_NAME_FILE "filename" #define SANE_NAME_HALFTONE_DIMENSION "halftone-size" #define SANE_NAME_HALFTONE_PATTERN "halftone-pattern" #define SANE_NAME_RESOLUTION_BIND "resolution-bind" #define SANE_NAME_NEGATIVE "negative" #define SANE_NAME_QUALITY_CAL "quality-cal" #define SANE_NAME_DOR "double-res" #define SANE_NAME_RGB_BIND "rgb-bind" #define SANE_NAME_THRESHOLD "threshold" #define SANE_NAME_ANALOG_GAMMA "analog-gamma" #define SANE_NAME_ANALOG_GAMMA_R "analog-gamma-r" #define SANE_NAME_ANALOG_GAMMA_G "analog-gamma-g" #define SANE_NAME_ANALOG_GAMMA_B "analog-gamma-b" #define SANE_NAME_ANALOG_GAMMA_BIND "analog-gamma-bind" #define SANE_NAME_WARMUP "warmup" #define SANE_NAME_CAL_EXPOS_TIME "cal-exposure-time" #define SANE_NAME_CAL_EXPOS_TIME_R "cal-exposure-time-r" #define SANE_NAME_CAL_EXPOS_TIME_G "cal-exposure-time-g" #define SANE_NAME_CAL_EXPOS_TIME_B "cal-exposure-time-b" #define SANE_NAME_SCAN_EXPOS_TIME "scan-exposure-time" #define SANE_NAME_SCAN_EXPOS_TIME_R "scan-exposure-time-r" #define SANE_NAME_SCAN_EXPOS_TIME_G "scan-exposure-time-g" #define SANE_NAME_SCAN_EXPOS_TIME_B "scan-exposure-time-b" #define SANE_NAME_SELECT_EXPOSURE_TIME "select-exposure-time" #define SANE_NAME_CAL_LAMP_DEN "cal-lamp-density" #define SANE_NAME_SCAN_LAMP_DEN "scan-lamp-density" #define SANE_NAME_SELECT_LAMP_DENSITY "select-lamp-density" #define SANE_NAME_LAMP_OFF_AT_EXIT "lamp-off-at-exit" /* well known options from 'SENSORS' group*/ #define SANE_NAME_SCAN "scan" #define SANE_NAME_EMAIL "email" #define SANE_NAME_FAX "fax" #define SANE_NAME_COPY "copy" #define SANE_NAME_PDF "pdf" #define SANE_NAME_CANCEL "cancel" #define SANE_NAME_PAGE_LOADED "page-loaded" #define SANE_NAME_COVER_OPEN "cover-open" #define SANE_TITLE_NUM_OPTIONS SANE_I18N("Number of options") #define SANE_TITLE_STANDARD SANE_I18N("Standard") #define SANE_TITLE_GEOMETRY SANE_I18N("Geometry") #define SANE_TITLE_ENHANCEMENT SANE_I18N("Enhancement") #define SANE_TITLE_ADVANCED SANE_I18N("Advanced") #define SANE_TITLE_SENSORS SANE_I18N("Sensors") #define SANE_TITLE_PREVIEW SANE_I18N("Preview") #define SANE_TITLE_GRAY_PREVIEW SANE_I18N("Force monochrome preview") #define SANE_TITLE_BIT_DEPTH SANE_I18N("Bit depth") #define SANE_TITLE_SCAN_MODE SANE_I18N("Scan mode") #define SANE_TITLE_SCAN_SPEED SANE_I18N("Scan speed") #define SANE_TITLE_SCAN_SOURCE SANE_I18N("Scan source") #define SANE_TITLE_BACKTRACK SANE_I18N("Force backtracking") #define SANE_TITLE_SCAN_TL_X SANE_I18N("Top-left x") #define SANE_TITLE_SCAN_TL_Y SANE_I18N("Top-left y") #define SANE_TITLE_SCAN_BR_X SANE_I18N("Bottom-right x") #define SANE_TITLE_SCAN_BR_Y SANE_I18N("Bottom-right y") #define SANE_TITLE_SCAN_RESOLUTION SANE_I18N("Scan resolution") #define SANE_TITLE_SCAN_X_RESOLUTION SANE_I18N("X-resolution") #define SANE_TITLE_SCAN_Y_RESOLUTION SANE_I18N("Y-resolution") #define SANE_TITLE_PAGE_WIDTH SANE_I18N("Page width") #define SANE_TITLE_PAGE_HEIGHT SANE_I18N("Page height") #define SANE_TITLE_CUSTOM_GAMMA SANE_I18N("Use custom gamma table") #define SANE_TITLE_GAMMA_VECTOR SANE_I18N("Image intensity") #define SANE_TITLE_GAMMA_VECTOR_R SANE_I18N("Red intensity") #define SANE_TITLE_GAMMA_VECTOR_G SANE_I18N("Green intensity") #define SANE_TITLE_GAMMA_VECTOR_B SANE_I18N("Blue intensity") #define SANE_TITLE_BRIGHTNESS SANE_I18N("Brightness") #define SANE_TITLE_CONTRAST SANE_I18N("Contrast") #define SANE_TITLE_GRAIN_SIZE SANE_I18N("Grain size") #define SANE_TITLE_HALFTONE SANE_I18N("Halftoning") #define SANE_TITLE_BLACK_LEVEL SANE_I18N("Black level") #define SANE_TITLE_WHITE_LEVEL SANE_I18N("White level") #define SANE_TITLE_WHITE_LEVEL_R SANE_I18N("White level for red") #define SANE_TITLE_WHITE_LEVEL_G SANE_I18N("White level for green") #define SANE_TITLE_WHITE_LEVEL_B SANE_I18N("White level for blue") #define SANE_TITLE_SHADOW SANE_I18N("Shadow") #define SANE_TITLE_SHADOW_R SANE_I18N("Shadow for red") #define SANE_TITLE_SHADOW_G SANE_I18N("Shadow for green") #define SANE_TITLE_SHADOW_B SANE_I18N("Shadow for blue") #define SANE_TITLE_HIGHLIGHT SANE_I18N("Highlight") #define SANE_TITLE_HIGHLIGHT_R SANE_I18N("Highlight for red") #define SANE_TITLE_HIGHLIGHT_G SANE_I18N("Highlight for green") #define SANE_TITLE_HIGHLIGHT_B SANE_I18N("Highlight for blue") #define SANE_TITLE_HUE SANE_I18N("Hue") #define SANE_TITLE_SATURATION SANE_I18N("Saturation") #define SANE_TITLE_FILE SANE_I18N("Filename") #define SANE_TITLE_HALFTONE_DIMENSION SANE_I18N("Halftone pattern size") #define SANE_TITLE_HALFTONE_PATTERN SANE_I18N("Halftone pattern") #define SANE_TITLE_RESOLUTION_BIND SANE_I18N("Bind X and Y resolution") #define SANE_TITLE_NEGATIVE SANE_I18N("Negative") #define SANE_TITLE_QUALITY_CAL SANE_I18N("Quality calibration") #define SANE_TITLE_DOR SANE_I18N("Double Optical Resolution") #define SANE_TITLE_RGB_BIND SANE_I18N("Bind RGB") #define SANE_TITLE_THRESHOLD SANE_I18N("Threshold") #define SANE_TITLE_ANALOG_GAMMA SANE_I18N("Analog gamma correction") #define SANE_TITLE_ANALOG_GAMMA_R SANE_I18N("Analog gamma red") #define SANE_TITLE_ANALOG_GAMMA_G SANE_I18N("Analog gamma green") #define SANE_TITLE_ANALOG_GAMMA_B SANE_I18N("Analog gamma blue") #define SANE_TITLE_ANALOG_GAMMA_BIND SANE_I18N("Bind analog gamma") #define SANE_TITLE_WARMUP SANE_I18N("Warmup lamp") #define SANE_TITLE_CAL_EXPOS_TIME SANE_I18N("Cal. exposure-time") #define SANE_TITLE_CAL_EXPOS_TIME_R SANE_I18N("Cal. exposure-time for red") #define SANE_TITLE_CAL_EXPOS_TIME_G SANE_I18N("Cal. exposure-time for " \ "green") #define SANE_TITLE_CAL_EXPOS_TIME_B SANE_I18N("Cal. exposure-time for blue") #define SANE_TITLE_SCAN_EXPOS_TIME SANE_I18N("Scan exposure-time") #define SANE_TITLE_SCAN_EXPOS_TIME_R SANE_I18N("Scan exposure-time for red") #define SANE_TITLE_SCAN_EXPOS_TIME_G SANE_I18N("Scan exposure-time for " \ "green") #define SANE_TITLE_SCAN_EXPOS_TIME_B SANE_I18N("Scan exposure-time for blue") #define SANE_TITLE_SELECT_EXPOSURE_TIME SANE_I18N("Set exposure-time") #define SANE_TITLE_CAL_LAMP_DEN SANE_I18N("Cal. lamp density") #define SANE_TITLE_SCAN_LAMP_DEN SANE_I18N("Scan lamp density") #define SANE_TITLE_SELECT_LAMP_DENSITY SANE_I18N("Set lamp density") #define SANE_TITLE_LAMP_OFF_AT_EXIT SANE_I18N("Lamp off at exit") /* well known options from 'SENSORS' group*/ #define SANE_TITLE_SCAN "Scan button" #define SANE_TITLE_EMAIL "Email button" #define SANE_TITLE_FAX "Fax button" #define SANE_TITLE_COPY "Copy button" #define SANE_TITLE_PDF "PDF button" #define SANE_TITLE_CANCEL "Cancel button" #define SANE_TITLE_PAGE_LOADED "Page loaded" #define SANE_TITLE_COVER_OPEN "Cover open" /* Descriptive/help strings for above options: */ #define SANE_DESC_NUM_OPTIONS \ SANE_I18N("Read-only option that specifies how many options a specific " \ "devices supports.") #define SANE_DESC_STANDARD SANE_I18N("Source, mode and resolution options") #define SANE_DESC_GEOMETRY SANE_I18N("Scan area and media size options") #define SANE_DESC_ENHANCEMENT SANE_I18N("Image modification options") #define SANE_DESC_ADVANCED SANE_I18N("Hardware specific options") #define SANE_DESC_SENSORS SANE_I18N("Scanner sensors and buttons") #define SANE_DESC_PREVIEW \ SANE_I18N("Request a preview-quality scan.") #define SANE_DESC_GRAY_PREVIEW \ SANE_I18N("Request that all previews are done in monochrome mode. On a " \ "three-pass scanner this cuts down the number of passes to one and on a " \ "one-pass scanner, it reduces the memory requirements and scan-time of the " \ "preview.") #define SANE_DESC_BIT_DEPTH \ SANE_I18N("Number of bits per sample, typical values are 1 for \"line-art\" " \ "and 8 for multibit scans.") #define SANE_DESC_SCAN_MODE \ SANE_I18N("Selects the scan mode (e.g., lineart, monochrome, or color).") #define SANE_DESC_SCAN_SPEED \ SANE_I18N("Determines the speed at which the scan proceeds.") #define SANE_DESC_SCAN_SOURCE \ SANE_I18N("Selects the scan source (such as a document-feeder).") #define SANE_DESC_BACKTRACK \ SANE_I18N("Controls whether backtracking is forced.") #define SANE_DESC_SCAN_TL_X \ SANE_I18N("Top-left x position of scan area.") #define SANE_DESC_SCAN_TL_Y \ SANE_I18N("Top-left y position of scan area.") #define SANE_DESC_SCAN_BR_X \ SANE_I18N("Bottom-right x position of scan area.") #define SANE_DESC_SCAN_BR_Y \ SANE_I18N("Bottom-right y position of scan area.") #define SANE_DESC_SCAN_RESOLUTION \ SANE_I18N("Sets the resolution of the scanned image.") #define SANE_DESC_SCAN_X_RESOLUTION \ SANE_I18N("Sets the horizontal resolution of the scanned image.") #define SANE_DESC_SCAN_Y_RESOLUTION \ SANE_I18N("Sets the vertical resolution of the scanned image.") #define SANE_DESC_PAGE_WIDTH \ SANE_I18N("Specifies the width of the media. Required for automatic " \ "centering of sheet-fed scans.") #define SANE_DESC_PAGE_HEIGHT \ SANE_I18N("Specifies the height of the media.") #define SANE_DESC_CUSTOM_GAMMA \ SANE_I18N("Determines whether a builtin or a custom gamma-table should be " \ "used.") #define SANE_DESC_GAMMA_VECTOR \ SANE_I18N("Gamma-correction table. In color mode this option equally " \ "affects the red, green, and blue channels simultaneously (i.e., it is an " \ "intensity gamma table).") #define SANE_DESC_GAMMA_VECTOR_R \ SANE_I18N("Gamma-correction table for the red band.") #define SANE_DESC_GAMMA_VECTOR_G \ SANE_I18N("Gamma-correction table for the green band.") #define SANE_DESC_GAMMA_VECTOR_B \ SANE_I18N("Gamma-correction table for the blue band.") #define SANE_DESC_BRIGHTNESS \ SANE_I18N("Controls the brightness of the acquired image.") #define SANE_DESC_CONTRAST \ SANE_I18N("Controls the contrast of the acquired image.") #define SANE_DESC_GRAIN_SIZE \ SANE_I18N("Selects the \"graininess\" of the acquired image. Smaller values " \ "result in sharper images.") #define SANE_DESC_HALFTONE \ SANE_I18N("Selects whether the acquired image should be halftoned (dithered).") #define SANE_DESC_BLACK_LEVEL \ SANE_I18N("Selects what radiance level should be considered \"black\".") #define SANE_DESC_WHITE_LEVEL \ SANE_I18N("Selects what radiance level should be considered \"white\".") #define SANE_DESC_WHITE_LEVEL_R \ SANE_I18N("Selects what red radiance level should be considered \"white\".") #define SANE_DESC_WHITE_LEVEL_G \ SANE_I18N("Selects what green radiance level should be considered \"white\".") #define SANE_DESC_WHITE_LEVEL_B \ SANE_I18N("Selects what blue radiance level should be considered \"white\".") #define SANE_DESC_SHADOW \ SANE_I18N("Selects what radiance level should be considered \"black\".") #define SANE_DESC_SHADOW_R \ SANE_I18N("Selects what red radiance level should be considered \"black\".") #define SANE_DESC_SHADOW_G \ SANE_I18N("Selects what green radiance level should be considered \"black\".") #define SANE_DESC_SHADOW_B \ SANE_I18N("Selects what blue radiance level should be considered \"black\".") #define SANE_DESC_HIGHLIGHT \ SANE_I18N("Selects what radiance level should be considered \"white\".") #define SANE_DESC_HIGHLIGHT_R \ SANE_I18N("Selects what red radiance level should be considered \"full red\".") #define SANE_DESC_HIGHLIGHT_G \ SANE_I18N("Selects what green radiance level should be considered \"full " \ "green\".") #define SANE_DESC_HIGHLIGHT_B \ SANE_I18N("Selects what blue radiance level should be considered \"full " \ "blue\".") #define SANE_DESC_HUE \ SANE_I18N("Controls the \"hue\" (blue-level) of the acquired image.") #define SANE_DESC_SATURATION \ SANE_I18N("The saturation level controls the amount of \"blooming\" that " \ "occurs when acquiring an image with a camera. Larger values cause more " \ "blooming.") #define SANE_DESC_FILE \ SANE_I18N("The filename of the image to be loaded.") #define SANE_DESC_HALFTONE_DIMENSION \ SANE_I18N("Sets the size of the halftoning (dithering) pattern used when " \ "scanning halftoned images.") #define SANE_DESC_HALFTONE_PATTERN \ SANE_I18N("Defines the halftoning (dithering) pattern for scanning " \ "halftoned images.") #define SANE_DESC_RESOLUTION_BIND \ SANE_I18N("Use same values for X and Y resolution") #define SANE_DESC_NEGATIVE \ SANE_I18N("Swap black and white") #define SANE_DESC_QUALITY_CAL \ SANE_I18N("Do a quality white-calibration") #define SANE_DESC_DOR \ SANE_I18N("Use lens that doubles optical resolution") #define SANE_DESC_RGB_BIND \ SANE_I18N("In RGB-mode use same values for each color") #define SANE_DESC_THRESHOLD \ SANE_I18N("Select minimum-brightness to get a white point") #define SANE_DESC_ANALOG_GAMMA \ SANE_I18N("Analog gamma-correction") #define SANE_DESC_ANALOG_GAMMA_R \ SANE_I18N("Analog gamma-correction for red") #define SANE_DESC_ANALOG_GAMMA_G \ SANE_I18N("Analog gamma-correction for green") #define SANE_DESC_ANALOG_GAMMA_B \ SANE_I18N("Analog gamma-correction for blue") #define SANE_DESC_ANALOG_GAMMA_BIND \ SANE_I18N("In RGB-mode use same values for each color") #define SANE_DESC_WARMUP \ SANE_I18N("Warmup lamp before scanning") #define SANE_DESC_CAL_EXPOS_TIME \ SANE_I18N("Define exposure-time for calibration") #define SANE_DESC_CAL_EXPOS_TIME_R \ SANE_I18N("Define exposure-time for red calibration") #define SANE_DESC_CAL_EXPOS_TIME_G \ SANE_I18N("Define exposure-time for green calibration") #define SANE_DESC_CAL_EXPOS_TIME_B \ SANE_I18N("Define exposure-time for blue calibration") #define SANE_DESC_SCAN_EXPOS_TIME \ SANE_I18N("Define exposure-time for scan") #define SANE_DESC_SCAN_EXPOS_TIME_R \ SANE_I18N("Define exposure-time for red scan") #define SANE_DESC_SCAN_EXPOS_TIME_G \ SANE_I18N("Define exposure-time for green scan") #define SANE_DESC_SCAN_EXPOS_TIME_B \ SANE_I18N("Define exposure-time for blue scan") #define SANE_DESC_SELECT_EXPOSURE_TIME \ SANE_I18N("Enable selection of exposure-time") #define SANE_DESC_CAL_LAMP_DEN \ SANE_I18N("Define lamp density for calibration") #define SANE_DESC_SCAN_LAMP_DEN \ SANE_I18N("Define lamp density for scan") #define SANE_DESC_SELECT_LAMP_DENSITY \ SANE_I18N("Enable selection of lamp density") #define SANE_DESC_LAMP_OFF_AT_EXIT \ SANE_I18N("Turn off lamp when program exits") /* well known options from 'SENSORS' group*/ #define SANE_DESC_SCAN SANE_I18N("Scan button") #define SANE_DESC_EMAIL SANE_I18N("Email button") #define SANE_DESC_FAX SANE_I18N("Fax button") #define SANE_DESC_COPY SANE_I18N("Copy button") #define SANE_DESC_PDF SANE_I18N("PDF button") #define SANE_DESC_CANCEL SANE_I18N("Cancel button") #define SANE_DESC_PAGE_LOADED SANE_I18N("Page loaded") #define SANE_DESC_COVER_OPEN SANE_I18N("Cover open") /* Typical values for stringlists (to keep the backends consistent) */ #define SANE_VALUE_SCAN_MODE_COLOR SANE_I18N("Color") #define SANE_VALUE_SCAN_MODE_COLOR_LINEART SANE_I18N("Color Lineart") #define SANE_VALUE_SCAN_MODE_COLOR_HALFTONE SANE_I18N("Color Halftone") #define SANE_VALUE_SCAN_MODE_GRAY SANE_I18N("Gray") #define SANE_VALUE_SCAN_MODE_HALFTONE SANE_I18N("Halftone") #define SANE_VALUE_SCAN_MODE_LINEART SANE_I18N("Lineart") #endif /* saneopts_h */ sane-backends-1.0.27/include/sane/sanei_wire.h0000664000175000017500000001104012112021330016046 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Support routines to translate internal datatypes into a wire-format (used for RPCs and to save/restore options). */ #ifndef sanei_wire_h #define sanei_wire_h #include #define MAX_MEM (1024 * 1024) typedef enum { WIRE_ENCODE = 0, WIRE_DECODE, WIRE_FREE } WireDirection; struct Wire; typedef void (*WireCodecFunc) (struct Wire *w, void *val_ptr); typedef ssize_t (*WireReadFunc) (int fd, void * buf, size_t len); typedef ssize_t (*WireWriteFunc) (int fd, const void * buf, size_t len); typedef struct Wire { int version; /* protocol version in use */ WireDirection direction; int status; int allocated_memory; struct { WireCodecFunc w_byte; WireCodecFunc w_char; WireCodecFunc w_word; WireCodecFunc w_string; } codec; struct { size_t size; char *curr; char *start; char *end; } buffer; struct { int fd; WireReadFunc read; WireWriteFunc write; } io; } Wire; extern void sanei_w_init (Wire *w, void (*codec_init)(Wire *)); extern void sanei_w_exit (Wire *w); extern void sanei_w_space (Wire *w, size_t howmuch); extern void sanei_w_void (Wire *w); extern void sanei_w_byte (Wire *w, SANE_Byte *v); extern void sanei_w_char (Wire *w, SANE_Char *v); extern void sanei_w_word (Wire *w, SANE_Word *v); extern void sanei_w_bool (Wire *w, SANE_Bool *v); extern void sanei_w_ptr (Wire *w, void **v, WireCodecFunc w_value, size_t value_size); extern void sanei_w_string (Wire *w, SANE_String *v); extern void sanei_w_status (Wire *w, SANE_Status *v); extern void sanei_w_constraint_type (Wire *w, SANE_Constraint_Type *v); extern void sanei_w_value_type (Wire *w, SANE_Value_Type *v); extern void sanei_w_unit (Wire *w, SANE_Unit *v); extern void sanei_w_action (Wire *w, SANE_Action *v); extern void sanei_w_frame (Wire *w, SANE_Frame *v); extern void sanei_w_range (Wire *w, SANE_Range *v); extern void sanei_w_range_ptr (Wire *w, SANE_Range **v); extern void sanei_w_device (Wire *w, SANE_Device *v); extern void sanei_w_device_ptr (Wire *w, SANE_Device **v); extern void sanei_w_option_descriptor (Wire *w, SANE_Option_Descriptor *v); extern void sanei_w_option_descriptor_ptr (Wire *w, SANE_Option_Descriptor **v); extern void sanei_w_parameters (Wire *w, SANE_Parameters *v); extern void sanei_w_array (Wire *w, SANE_Word *len, void **v, WireCodecFunc w_element, size_t element_size); extern void sanei_w_set_dir (Wire *w, WireDirection dir); extern void sanei_w_call (Wire *w, SANE_Word proc_num, WireCodecFunc w_arg, void *arg, WireCodecFunc w_reply, void *reply); extern void sanei_w_reply (Wire *w, WireCodecFunc w_reply, void *reply); extern void sanei_w_free (Wire *w, WireCodecFunc w_reply, void *reply); #endif /* sanei_wire_h */ sane-backends-1.0.27/include/sane/sanei_thread.h0000664000175000017500000001223212775312262016401 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998-2001 Yuri Dario Copyright (C) 2002-2003 Henning Meier-Geinitz (documentation) Copyright (C) 2003-2004 Gerhard Jaeger (pthread/process support) This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_thread.h * Support for forking processes and threading. * * Backends should not use fork() directly because fork() does not work * correctly on some platforms. Use the functions provided by sanei_thread * instead. The build system decides if fork() or threads are used. * * Please keep in mind that the behaviour of the child process depends * on if it's a process or thread especially concerning variables. * * In this file we use "task" as an umbrella term for process and thread. * * @sa sanei.h sanei_backend.h */ #ifndef sanei_thread_h #define sanei_thread_h #include "../include/sane/config.h" #ifdef USE_PTHREAD #include typedef pthread_t SANE_Pid; #else typedef int SANE_Pid; #endif /** Initialize sanei_thread. * * This function must be called before any other sanei_thread function. */ extern void sanei_thread_init (void); /** Do we use processes or threads? * * This function can be used to check if processes or threads are used. * * @return * - SANE_TRUE - if processes are used (fork) * - SANE_FALSE - i threads are used */ extern SANE_Bool sanei_thread_is_forked (void); /** Is SANE_Pid valid pid? * * This function can be used to check if thread/fork creation worked * regardless of SANE_Pid's data type. * * @return * - SANE_TRUE - if pid is a valid process * - SANE_FALSE - if pid is not a valid process */ extern SANE_Bool sanei_thread_is_valid (SANE_Pid pid); /** Spawn a new task. * * This function should be used to start a new task. * * @param func() function to call as child task * @param args argument of the function (only one!) * * @return * - task id * - -1 if creating the new task failed */ extern SANE_Pid sanei_thread_begin (int (*func) (void *args), void *args); /** Terminate spawned task. * * This function terminates the task that was created with sanei_thread_begin. * * For processes, SIGTERM is sent. If threads are used, pthread_cancel() * terminates the task. * * @param pid - the id of the task * * @return * - 0 on success * - any other value if an error occured while terminating the task */ extern int sanei_thread_kill (SANE_Pid pid); /** Send a signal to a task. * * This function can be used to send a signal to a task. * * For terminating the task, sanei_thread_kill() should be used. * * @param pid - the id of the task * @param sig - the signal to send * * @return * - 0 - on success * - any other value - if an error occured while sending the signal */ extern int sanei_thread_sendsig (SANE_Pid pid, int sig); /** Wait for task termination. * * This function waits until a task that has been terminated by * sanei_thread_kill(), sanei_thread_sendsys() or by any other means * is finished. * * @param pid - the id of the task * @param status - status of the task that has just finished * * @return * - the pid of the task we have been waiting for */ extern SANE_Pid sanei_thread_waitpid (SANE_Pid pid, int *status); /** Check the current status of the spawned task * * * @param pid - the id of the task * * @return * - SANE_STATUS_GOOD - if the task finished without errors * - any other value - if the task finished unexpectantly or hasn't finished yet */ extern SANE_Status sanei_thread_get_status (SANE_Pid pid); #endif /* sanei_thread_h */ sane-backends-1.0.27/include/sane/sanei_tcp.h0000664000175000017500000000213012617742237015720 00000000000000/* sane - Scanner Access Now Easy. * Copyright (C) 2006 Tower Technologies * Author: Alessandro Zummo * This file is part of the SANE package. * * This file is in the public domain. You may use and modify it as * you see fit, as long as this copyright message is included and * that there is an indication as to what modifications have been * made (if any). * * SANE is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * Header file for TCP/IP communications. */ #ifndef sanei_tcp_h #define sanei_tcp_h #include #ifdef HAVE_WINSOCK2_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #include #endif #include extern SANE_Status sanei_tcp_open(const char *host, int port, int *fdp); extern void sanei_tcp_close(int fd); extern ssize_t sanei_tcp_write(int fd, const u_char * buf, int count); extern ssize_t sanei_tcp_read(int fd, u_char * buf, int count); #endif /* sanei_tcp_h */ sane-backends-1.0.27/include/sane/config.h.in0000664000175000017500000004442613110564732015632 00000000000000/* include/sane/config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ #undef CRAY_STACKSEG_END /* Define to 1 if using `alloca.c'. */ #undef C_ALLOCA /* Define to 1 if the system supports IPv6 */ #undef ENABLE_IPV6 /* Define to 1 if device locking should be enabled. */ #undef ENABLE_LOCKING /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS /* Define if GPLogFunc does not take a va_list. */ #undef GPLOGFUNC_NO_VARGS /* Define to 1 if struct sockaddr_storage has an ss_family member */ #undef HAS_SS_FAMILY /* Define to 1 if struct sockaddr_storage has __ss_family instead of ss_family */ #undef HAS___SS_FAMILY /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA /* Define to 1 if you have and it should be used (not on Ultrix). */ #undef HAVE_ALLOCA_H /* Define to 1 if you have the header file. */ #undef HAVE_APOLLO_SCSI_H /* Define to 1 if you have the header file. */ #undef HAVE_ASM_IO_H /* Define to 1 if you have the header file. */ #undef HAVE_ASM_TYPES_H /* Define to 1 if you have the `atexit' function. */ #undef HAVE_ATEXIT /* Define to 1 if you have the header file. */ #undef HAVE_BE_KERNEL_OS_H /* Define to 1 if you have the header file. */ #undef HAVE_BSD_DEV_SCSIREG_H /* Define to 1 if you have the header file. */ #undef HAVE_CAMLIB_H /* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework. */ #undef HAVE_CFLOCALECOPYCURRENT /* Define to 1 if you have the `cfmakeraw' function. */ #undef HAVE_CFMAKERAW /* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework. */ #undef HAVE_CFPREFERENCESCOPYAPPVALUE /* Define if the GNU dcgettext() function is already present or preinstalled. */ #undef HAVE_DCGETTEXT /* Define to 1 if you have the header file. */ #undef HAVE_DDK_NTDDSCSI_H /* Define to 1 if you have the header file. */ #undef HAVE_DEV_PPBUS_PPI_H /* Is /dev/urandom available? */ #undef HAVE_DEV_URANDOM /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `dlopen' function. */ #undef HAVE_DLOPEN /* Define to 1 if you have the header file. */ #undef HAVE_DL_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getenv' function. */ #undef HAVE_GETENV /* Define to 1 if you have the `getnameinfo' function. */ #undef HAVE_GETNAMEINFO /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H /* Define to 1 if you have the `getopt_long' function. */ #undef HAVE_GETOPT_LONG /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the `getpass' function. */ #undef HAVE_GETPASS /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define to 1 if you have the `getuid' function. */ #undef HAVE_GETUID /* Define to 1 if you have the `gp_camera_init' function. */ #undef HAVE_GP_CAMERA_INIT /* Define to 1 if you have the `gp_port_info_get_path' function. */ #undef HAVE_GP_PORT_INFO_GET_PATH /* Define to 1 if you have the header file. */ #undef HAVE_GSCDDS_H /* Define to 1 if you have the `i386_set_ioperm' function. */ #undef HAVE_I386_SET_IOPERM /* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_IFADDRS_H /* Define to 1 if you have the `inet_addr' function. */ #undef HAVE_INET_ADDR /* Define to 1 if you have the `inet_aton' function. */ #undef HAVE_INET_ATON /* Define to 1 if you have the `inet_ntoa' function. */ #undef HAVE_INET_NTOA /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP /* Define to 1 if you have the `inet_pton' function. */ #undef HAVE_INET_PTON /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_IOKIT_CDB_IOSCSILIB_H /* Define to 1 if you have the header file. */ #undef HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H /* Define to 1 if you have the header file. */ #undef HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H /* Define to 1 if you have the header file. */ #undef HAVE_IOKIT_SCSI_SCSITASKLIB_H /* Define to 1 if you have the `ioperm' function. */ #undef HAVE_IOPERM /* Define to 1 if you have the `iopl' function. */ #undef HAVE_IOPL /* Define to 1 if you have the header file. */ #undef HAVE_IO_CAM_CAM_H /* Define to 1 if you have the `isfdtype' function. */ #undef HAVE_ISFDTYPE /* Define to 1 if you have the header file. */ #undef HAVE_LIBC_H /* Define to 1 if you have the `ieee1284' library (-lcam). */ #undef HAVE_LIBIEEE1284 /* Define to 1 if you have the libjpeg library. */ #undef HAVE_LIBJPEG /* Define to 1 if you have the libpng library. */ #undef HAVE_LIBPNG /* Define to 1 if you have the net-snmp library. */ #undef HAVE_LIBSNMP /* Define to 1 if you have libusb-1.0 */ #undef HAVE_LIBUSB /* Define to 1 if you have libusb-0.1 */ #undef HAVE_LIBUSB_LEGACY /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_PPDEV_H /* Define if the long long type is available. */ #undef HAVE_LONG_LONG /* Define to 1 if you have the header file. */ #undef HAVE_LUSB0_USB_H /* Define to 1 if you have the header file. */ #undef HAVE_MACHINE_CPUFUNC_H /* Define to 1 if you have the header file. */ #undef HAVE_MACH_O_DYLD_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mkdir' function. */ #undef HAVE_MKDIR /* Define to 1 if you have a working `mmap' system call. */ #undef HAVE_MMAP /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if you have the `NSLinkModule' function. */ #undef HAVE_NSLINKMODULE /* Define to 1 if you have the header file. */ #undef HAVE_NTDDSCSI_H /* Define to 1 if you have the header file. */ #undef HAVE_OS2_H /* Define to 1 if you have the `poll' function. */ #undef HAVE_POLL /* Define to 1 if you have the `pthread_cancel' function. */ #undef HAVE_PTHREAD_CANCEL /* Define to 1 if you have the `pthread_create' function. */ #undef HAVE_PTHREAD_CREATE /* Define to 1 if you have the `pthread_detach' function. */ #undef HAVE_PTHREAD_DETACH /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Define to 1 if you have the `pthread_join' function. */ #undef HAVE_PTHREAD_JOIN /* Define to 1 if you have the `pthread_kill' function. */ #undef HAVE_PTHREAD_KILL /* Define to 1 if you have the `pthread_testcancel' function. */ #undef HAVE_PTHREAD_TESTCANCEL /* Define to 1 if you have the header file. */ #undef HAVE_PWD_H /* define if you have the resmgr library */ #undef HAVE_RESMGR /* Define to 1 if you have the `scsireq_enter' function. */ #undef HAVE_SCSIREQ_ENTER /* Define if SCSITaskSGElement is available. */ #undef HAVE_SCSITASKSGELEMENT /* Define to 1 if you have the header file. */ #undef HAVE_SCSI_H /* Define to 1 if you have the header file. */ #undef HAVE_SCSI_SG_H /* Define to 1 if you have the `setitimer' function. */ #undef HAVE_SETITIMER /* Define if sg_header.target_status is available. */ #undef HAVE_SG_TARGET_STATUS /* Define to 1 if you have the `shl_load' function. */ #undef HAVE_SHL_LOAD /* Define to 1 if you have the `sigprocmask' function. */ #undef HAVE_SIGPROCMASK /* Define to 1 if you have the `sleep' function. */ #undef HAVE_SLEEP /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strcasestr' function. */ #undef HAVE_STRCASESTR /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strncasecmp' function. */ #undef HAVE_STRNCASECMP /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the `strsep' function. */ #undef HAVE_STRSEP /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the `strtod' function. */ #undef HAVE_STRTOD /* Define if struct flock is available. */ #undef HAVE_STRUCT_FLOCK /* Define to 1 if you have the `syslog' function. */ #undef HAVE_SYSLOG /* Is /usr/include/systemd/sd-daemon.h available? */ #undef HAVE_SYSTEMD /* Define to 1 if you have the header file. */ #undef HAVE_SYS_DSREQ_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_HW_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IPC_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PASSTHRUDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SCANIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SCSICMD_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SCSIIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SCSI_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SCSI_SCSI_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SCSI_SGDEFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SCSI_TARGETS_SCGIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SDI_COMM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SEM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SHM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SIGNAL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the `tcsendbreak' function. */ #undef HAVE_TCSENDBREAK /* Define to 1 if you have the header file. */ #undef HAVE_TIFFIO_H /* Define if union semun is available. */ #undef HAVE_UNION_SEMUN /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have usbcall.dll. */ #undef HAVE_USBCALLS /* Define to 1 if you have the `usleep' function. */ #undef HAVE_USLEEP /* Define to 1 if the system has the type `u_char'. */ #undef HAVE_U_CHAR /* Define to 1 if the system has the type `u_int'. */ #undef HAVE_U_INT /* Define to 1 if the system has the type `u_long'. */ #undef HAVE_U_LONG /* Define to 1 if the system has the type `u_short'. */ #undef HAVE_U_SHORT /* Define to 1 if you have the `vsyslog' function. */ #undef HAVE_VSYSLOG /* Define to 1 if you have the header file. */ #undef HAVE_WINDOWS_H /* Define to 1 if you have the header file. */ #undef HAVE_WINSOCK2_H /* Define to 1 if you have the `_portaccess' function. */ #undef HAVE__PORTACCESS /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* SANE DLL revision number */ #undef SANE_DLL_V_BUILD /* SANE DLL major number */ #undef SANE_DLL_V_MAJOR /* SANE DLL minor number */ #undef SANE_DLL_V_MINOR /* Define to 1 if you have the providing inb,outb. */ #undef SANE_HAVE_SYS_IO_H_WITH_INB_OUTB /* SCSI command buffer size */ #undef SCSIBUFFERSIZE /* The size of `char', as computed by sizeof. */ #undef SIZEOF_CHAR /* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG /* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT /* The size of `void*', as computed by sizeof. */ #undef SIZEOF_VOIDP /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if pthreads should be used instead of forked processes. */ #undef USE_PTHREAD /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Version number of package */ #undef VERSION /* define if Avahi support is enabled for saned and the net backend */ #undef WITH_AVAHI /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to `int' if does not define. */ #undef pid_t /* Define scsireq_t as \'struct scsireq\' if necessary. */ #undef scsireq_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define socklen_t as \'int\' if necessary. */ #undef socklen_t /* Define to `int' if does not define. */ #undef ssize_t /* Define for OS/2 only */ #undef strcasecmp /* Define for OS/2 only */ #undef strncasecmp #if defined(__MINGW32__) #define _BSDTYPES_DEFINED #endif #ifndef HAVE_U_CHAR #define u_char unsigned char #endif #ifndef HAVE_U_SHORT #define u_short unsigned short #endif #ifndef HAVE_U_INT #define u_int unsigned int #endif #ifndef HAVE_U_LONG #define u_long unsigned long #endif /* Prototype for getenv */ #ifndef HAVE_GETENV #define getenv sanei_getenv char * getenv(const char *name); #endif /* Prototype for inet_ntop */ #ifndef HAVE_INET_NTOP #define inet_ntop sanei_inet_ntop #include const char * inet_ntop (int af, const void *src, char *dst, size_t cnt); #endif /* Prototype for inet_pton */ #ifndef HAVE_INET_PTON #define inet_pton sanei_inet_pton int inet_pton (int af, const char *src, void *dst); #endif /* Prototype for isfdtype */ #ifndef HAVE_ISFDTYPE #define isfdtype sanei_isfdtype int isfdtype(int fd, int fdtype); #endif /* Prototype for sigprocmask */ #ifndef HAVE_SIGPROCMASK #define sigprocmask sanei_sigprocmask int sigprocmask (int how, int *new, int *old); #endif /* Prototype for snprintf */ #ifndef HAVE_SNPRINTF #define snprintf sanei_snprintf #include int snprintf (char *str,size_t count,const char *fmt,...); #endif /* Prototype for strcasestr */ #ifndef HAVE_STRCASESTR #define strcasestr sanei_strcasestr char * strcasestr (const char *phaystack, const char *pneedle); #endif /* Prototype for strdup */ #ifndef HAVE_STRDUP #define strdup sanei_strdup char *strdup (const char * s); #endif /* Prototype for strndup */ #ifndef HAVE_STRNDUP #define strndup sanei_strndup #include char *strndup(const char * s, size_t n); #endif /* Prototype for strsep */ #ifndef HAVE_STRSEP #define strsep sanei_strsep char *strsep(char **stringp, const char *delim); #endif /* Prototype for usleep */ #ifndef HAVE_USLEEP #define usleep sanei_usleep unsigned int usleep (unsigned int useconds); #endif /* Prototype for vsyslog */ #ifndef HAVE_VSYSLOG #include void vsyslog(int priority, const char *format, va_list args); #endif sane-backends-1.0.27/include/sane/sanei_jinclude.h0000664000175000017500000000626212112021330016707 00000000000000/* * jinclude.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file exists to provide a single place to fix any problems with * including the wrong system include files. (Common problems are taken * care of by the standard jconfig symbols, but on really weird systems * you may have to edit this file.) * * NOTE: this file is NOT intended to be included by applications using the * JPEG library. Most applications need only include jpeglib.h. */ /* Include auto-config file to find out which system include files we need. */ #include "jconfig.h" /* auto configuration options */ #define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ /* * We need the NULL macro and size_t typedef. * On an ANSI-conforming system it is sufficient to include . * Otherwise, we get them from or ; we may have to * pull in as well. * Note that the core JPEG library does not require ; * only the default error handler and data source/destination modules do. * But we must pull it in because of the references to FILE in jpeglib.h. * You can remove those references if you want to compile without . */ #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include /* * We need memory copying and zeroing functions, plus strncpy(). * ANSI and System V implementations declare these in . * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). * Some systems may declare memset and memcpy in . * * NOTE: we assume the size parameters to these functions are of type size_t. * Change the casts in these macros if not! */ #ifdef NEED_BSD_STRINGS #include #define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) #define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) #else /* not BSD, assume ANSI/SysV string lib */ #include #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) #define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) #endif /* * In ANSI C, and indeed any rational implementation, size_t is also the * type returned by sizeof(). However, it seems there are some irrational * implementations out there, in which sizeof() returns an int even though * size_t is defined as long or unsigned long. To ensure consistent results * we always use this SIZEOF() macro in place of using sizeof() directly. */ #define SIZEOF(object) ((size_t) sizeof(object)) /* * The modules that use fread() and fwrite() always invoke them through * these macros. On some systems you may need to twiddle the argument casts. * CAUTION: argument order is different from underlying functions! */ #define JFREAD(file,buf,sizeofbuf) \ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFWRITE(file,buf,sizeofbuf) \ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) sane-backends-1.0.27/include/sane/sanei_pio.h0000664000175000017500000000426612112021330015703 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998 Christian Bucher Copyright (C) 1998 Kling & Hautzinger GmbH This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef sanei_pio_h #define sanei_pio_h #include #include extern SANE_Status sanei_pio_open (const char * dev, int * fd); extern void sanei_pio_close (int fd); extern int sanei_pio_read (int fd, u_char * buf, int n); extern int sanei_pio_write (int fd, const u_char * buf, int n); #endif /* sanei_pio_h */ sane-backends-1.0.27/include/sane/sanei_access.h0000664000175000017500000000701312112021330016346 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005 Gerhard Jaeger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_access.h * Interface file for the sanei_access functions. * * The idea is to provide some simple locking/unlocking mecanism, which * can be used to protect device access from more than one frontend * simultaneously. */ #ifndef sanei_access_h #define sanei_access_h #include "../include/sane/config.h" #include "../include/sane/sane.h" /** Initialize sanei_access. * * This function must be called before any other sanei_access function. * * @param backend - backend name, who uses this lib */ extern void sanei_access_init( const char * backend ); /** Set a lock. * * The function tries to open/create exclusively a lock file in * $PATH_SANE_LOCK_DIR. * If the file could be created successfully, the function fills in the * process ID. * The complete filename of the lockfile is created as follows: * $PATH_SANE_LOCK_DIR/LCK..<devicename> * If the lock could not be set, the function tries it until the timeout * period has been elapsed. * * @param devicename - unique part of the lockfile name * @param timeout - time in seconds to try to set a lock * @return * - SANE_STATUS_GOOD - if the lock has been successfully set * - SANE_STATUS_ACCESS_DENIED - the lock could not set */ extern SANE_Status sanei_access_lock( const char * devicename, SANE_Word timeout ); /** Unlock a previously set lock. * * The function tries to unlock a previously created lock. The lockfile will be * closed and removed. * * @param devicename - part of the lockfile name, use for sanei_acess_lock() * @return * - SANE_STATUS_GOOD - currently the one and only return value */ extern SANE_Status sanei_access_unlock( const char * devicename ); #endif /* sanei_access_h */ sane-backends-1.0.27/include/sane/sanei_net.h0000664000175000017500000000641012112021330015673 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997-1999 David Mosberger-Tang and Andreas Beck This file is part of the SANE package. This file is in the public domain. You may use and modify it as you see fit, as long as this copyright message is included and that there is an indication as to what modifications have been made (if any). SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This file declares SANE application interface. See the SANE standard for a detailed explanation of the interface. */ #ifndef sanei_net_h #define sanei_net_h #include #include #define SANEI_NET_PROTOCOL_VERSION 3 typedef enum { SANE_NET_LITTLE_ENDIAN = 0x1234, SANE_NET_BIG_ENDIAN = 0x4321 } SANE_Net_Byte_Order; typedef enum { SANE_NET_INIT = 0, SANE_NET_GET_DEVICES, SANE_NET_OPEN, SANE_NET_CLOSE, SANE_NET_GET_OPTION_DESCRIPTORS, SANE_NET_CONTROL_OPTION, SANE_NET_GET_PARAMETERS, SANE_NET_START, SANE_NET_CANCEL, SANE_NET_AUTHORIZE, SANE_NET_EXIT } SANE_Net_Procedure_Number; typedef struct { SANE_Word version_code; SANE_String username; } SANE_Init_Req; typedef struct { SANE_Status status; SANE_Word version_code; } SANE_Init_Reply; typedef struct { SANE_Status status; SANE_Device **device_list; } SANE_Get_Devices_Reply; typedef struct { SANE_Status status; SANE_Word handle; SANE_String resource_to_authorize; } SANE_Open_Reply; typedef struct { SANE_Word num_options; SANE_Option_Descriptor **desc; } SANE_Option_Descriptor_Array; typedef struct { SANE_Word handle; SANE_Word option; SANE_Word action; SANE_Word value_type; SANE_Word value_size; void *value; } SANE_Control_Option_Req; typedef struct { SANE_Status status; SANE_Word info; SANE_Word value_type; SANE_Word value_size; void *value; SANE_String resource_to_authorize; } SANE_Control_Option_Reply; typedef struct { SANE_Status status; SANE_Parameters params; } SANE_Get_Parameters_Reply; typedef struct { SANE_Status status; SANE_Word port; SANE_Word byte_order; SANE_String resource_to_authorize; } SANE_Start_Reply; typedef struct { SANE_String resource; SANE_String username; SANE_String password; } SANE_Authorization_Req; extern void sanei_w_init_req (Wire *w, SANE_Init_Req *req); extern void sanei_w_init_reply (Wire *w, SANE_Init_Reply *reply); extern void sanei_w_get_devices_reply (Wire *w, SANE_Get_Devices_Reply *reply); extern void sanei_w_open_reply (Wire *w, SANE_Open_Reply *reply); extern void sanei_w_option_descriptor_array (Wire *w, SANE_Option_Descriptor_Array *opt); extern void sanei_w_control_option_req (Wire *w, SANE_Control_Option_Req *req); extern void sanei_w_control_option_reply (Wire *w, SANE_Control_Option_Reply *reply); extern void sanei_w_get_parameters_reply (Wire *w, SANE_Get_Parameters_Reply *reply); extern void sanei_w_start_reply (Wire *w, SANE_Start_Reply *reply); extern void sanei_w_authorization_req (Wire *w, SANE_Authorization_Req *req); #endif /* sanei_net_h */ sane-backends-1.0.27/include/sane/sanei_jpeg.h0000664000175000017500000000347712112021330016044 00000000000000/* * cdjpeg.h * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains common declarations for the sample applications * cjpeg and djpeg. It is NOT used by the core JPEG library. */ #define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ #define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ #include "sane/sanei_jinclude.h" #include "jpeglib.h" #include "jerror.h" /* get library error codes too */ #include "sane/sanei_cderror.h" /* get application-specific error codes */ /* * Object interface for djpeg's output file encoding modules */ typedef struct djpeg_dest_struct * djpeg_dest_ptr; struct djpeg_dest_struct { /* start_output is called after jpeg_start_decompress finishes. * The color map will be ready at this time, if one is needed. */ JMETHOD(void, start_output, (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)); /* Emit the specified number of pixel rows from the buffer. */ JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied, char *data)); /* Finish up at the end of the image. */ JMETHOD(void, finish_output, (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)); /* Target file spec; filled in by djpeg.c after object is created. */ FILE * output_file; /* Output pixel-row buffer. Created by module init or start_output. * Width is cinfo->output_width * cinfo->output_components; * height is buffer_height. */ JSAMPARRAY buffer; JDIMENSION buffer_height; }; /* Module selection routines for I/O modules. */ EXTERN(djpeg_dest_ptr) sanei_jpeg_jinit_write_ppm JPP((j_decompress_ptr cinfo)); /* miscellaneous useful macros */ sane-backends-1.0.27/include/sane/sanei_ir.h0000664000175000017500000003333312775312262015551 00000000000000/** @file sanei_ir.h * * This file provides an interface to the * sanei_ir functions for utilizing the infrared plane * * Copyright (C) 2012 Michael Rickmann * * This file is part of the SANE package. * * Essentially three things have to be done: * - 1) reduce red spectral overlap from the infrared (ired) plane * - 2) find the dirt * - 3) replace the dirt * * - 1) is mainly adressed by sanei_ir_spectral_clean * - 2) by sanei_ir_filter_madmean * - 3) by sanei_ir_dilate_mean */ #ifndef SANEI_IR_H #define SANEI_IR_H #include #define SAMPLE_SIZE 40000 /**< maximal for random sampling */ #define HISTOGRAM_SHIFT 8 /**< standard histogram size */ #define HISTOGRAM_SIZE (1 << HISTOGRAM_SHIFT) #define SAFE_LOG(x) ( ((x) > 0.0) ? log ((x)) : (0.0) ) /**< define log (0) = 0 */ #define MAD_WIN2_SIZE(x) ( (((x) * 4) / 3) | 1 ) /**< MAD filter: 2nd window size */ typedef uint16_t SANE_Uint; /** * @brief Pointer to access values of different bit depths */ typedef union { uint8_t *b8; /**< <= 8 bits */ uint16_t *b16; /**< > 8, <= 16 bits */ } SANEI_IR_bufptr; /** Initialize sanei_ir. * * Call this before any other sanei_ir function. */ extern void sanei_ir_init (void); /** * @brief Create the normalized histogram of a grayscale image * * @param[in] params describes image * @param[in] img_data image pointer { grayscale } * @param[out] histogram an array of double with histogram * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * * @note * histogram has to be freed by calling routine */ extern SANE_Status sanei_ir_create_norm_histogram (const SANE_Parameters * params, const SANE_Uint *img_data, double ** histogram); /** * @brief Implements Yen's thresholding method * * @param[in] params describes image * @param[in] norm_histo points to a normalized histogram * @param[out] thresh found threshold * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * * -# Yen J.C., Chang F.J., and Chang S. (1995) "A New Criterion * for Automatic Multilevel Thresholding" IEEE Trans. on Image * Processing, 4(3): 370-378 * -# Sezgin M. and Sankur B. (2004) "Survey over Image Thresholding * Techniques and Quantitative Performance Evaluation" Journal of * Electronic Imaging, 13(1): 146-165 * -# M. Emre Celebi, 06.15.2007, fourier_0.8, * http://sourceforge.net/projects/fourier-ipal/ * -# ImageJ Multithresholder plugin, * http://rsbweb.nih.gov/ij/plugins/download/AutoThresholder.java */ extern SANE_Status sanei_ir_threshold_yen (const SANE_Parameters * params, double * norm_histo, int *thresh); /** * @brief Implements Otsu's thresholding method * * @param[in] params describes image * @param[in] norm_histo points to a normalized histogram * @param[out] thresh found threshold * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * * -# Otsu N. (1979) "A Threshold Selection Method from Gray Level Histograms" * IEEE Trans. on Systems, Man and Cybernetics, 9(1): 62-66 * -# M. Emre Celebi, 06.15.2007, fourier_0.8 * http://sourceforge.net/projects/fourier-ipal/ */ extern SANE_Status sanei_ir_threshold_otsu (const SANE_Parameters * params, double * norm_histo, int *thresh); /** * @brief Implements a Maximum Entropy thresholding method * * @param[in] params describes image * @param[in] norm_histo points to a normalized histogram * @param[out] thresh found threshold * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * * -# Kapur J.N., Sahoo P.K., and Wong A.K.C. (1985) "A New Method for * Gray-Level Picture Thresholding Using the Entropy of the Histogram" * Graphical Models and Image Processing, 29(3): 273-285 * -# M. Emre Celebi, 06.15.2007, fourier_0.8 * http://sourceforge.net/projects/fourier-ipal/ * -# ImageJ Multithresholder plugin, * http://rsbweb.nih.gov/ij/plugins/download/AutoThresholder.java */ extern SANE_Status sanei_ir_threshold_maxentropy (const SANE_Parameters * params, double * norm_histo, int *thresh); /** * @brief Generate gray scale luminance image from separate R, G, B images * * @param params points to image description * @param[in] in_img pointer to at least 3 planes of image data * @param[out] out_img newly allocated image * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * - SANE_STATUS_UNSUPPORTED - wrong input bit depth * * @note out_img has to be freed by the calling routine. * @note on input params describe a single color plane, * on output params are updated if image depth is scaled */ SANE_Status sanei_ir_RGB_luminance (SANE_Parameters * params, const SANE_Uint **in_img, SANE_Uint **out_img); /** * @brief Convert image from >8 bit depth to an 8 bit image. * * @param[in] params pimage description * @param[in] in_img points to input image data * @param[out] out_params if != NULL * receives description of new image * @param[out] out_img newly allocated 8-bit image * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * - SANE_STATUS_UNSUPPORTED - wrong input bit depth * * @note * out_img has to be freed by the calling routine, */ extern SANE_Status sanei_ir_to_8bit (SANE_Parameters * params, const SANE_Uint *in_img, SANE_Parameters * out_params, SANE_Uint **out_img); /** * @brief Allocate and initialize logarithmic lookup table * * @param[in] length of table, usually 1 << depth * @param[out] lut_ln adress of pointer to allocated table * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * * @note natural logarithms are provided */ SANE_Status sanei_ir_ln_table (int len, double **lut_ln); /** * @brief Reduces red spectral overlap from an infrared image plane * * @param[in] params pointer to image description * @param[in] lut_ln pointer lookup table * if NULL it is dynamically handled * @param[in] red_data pointer to red image plane * @param ired_data pointer to ired image plane * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * * This routine is based on the observation that the relation beween the infrared value * ired and the red value red of an image point can be described by ired = b + a * ln (red). * First points are randomly sampled to calculate the linear regression coefficent a. * Then ired' = ired - a * ln (red) is calculated for each pixel. Finally, the ir' image * is scaled between 0 and maximal value. For the logarithms a lookup table is used. * Negative films show very little spectral overlap but positive film usually has to be * cleaned. As we do a statistical measure of the film here dark margins and lumps of * dirt have to be excluded. * * @note original ired data are replaced by the cleaned ones */ extern SANE_Status sanei_ir_spectral_clean (const SANE_Parameters * params, double *lut_ln, const SANE_Uint *red_data, SANE_Uint *ir_data); /** * @brief Optimized mean filter * * @param[in] params pointer to image description * @param[in] in_img Pointer to grey scale image data * @param[out] out_img Pointer to grey scale image data * @param[in] win_rows Height of filtering window, odd * @param[in] win_cols Width of filtering window, odd * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * - SANE_STATUS_INVAL - wrong window size * * @note At the image margins the size of the filtering window * is adapted. So there is no need to pad the image. * @note Memory for the output image has to be allocated before */ extern SANE_Status sanei_ir_filter_mean (const SANE_Parameters * params, const SANE_Uint *in_img, SANE_Uint *out_img, int win_rows, int win_cols); /** * @brief Find noise by adaptive thresholding * * @param[in] params pointer to image description * @param[in] in_img pointer to grey scale image * @param[out] out_img address of pointer to newly allocated binary image * @param[in] win_size Size of filtering window * @param[in] a_val Parameter, below is definetly clean * @param[in] b_val Parameter, above is definetly noisy * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * * This routine follows the concept of Crnojevic's MAD (median of the absolute deviations * from the median) filter. The first median filter step is replaced with a mean filter. * The dirty pixels which we wish to remove are always darker than the real signal. But * at high resolutions the scanner may generate some noise and the ired cleaning step can * reverse things. So a maximum filter will not do. * The second median is replaced by a mean filter to reduce computation time. Inspite of * these changes Crnojevic's recommendations for the choice of the parameters "a" and "b" * are still valid when scaled to the color depth. * * @reco Crnojevic recommends 10 < a_val < 30 and 50 < b_val < 100 for 8 bit color depth * * @note a_val, b_val are scaled by the routine according to bit depth * @note "0" in the mask output is regarded "dirty", 255 "clean" * * -# Crnojevic V. (2005) "Impulse Noise Filter with Adaptive Mad-Based Threshold" * Proc. of the IEEE Int. Conf. on Image Processing, 3: 337-340 */ extern SANE_Status sanei_ir_filter_madmean (const SANE_Parameters * params, const SANE_Uint *in_img, SANE_Uint ** out_img, int win_size, int a_val, int b_val); /** * @brief Add dark pixels to mask from static threshold * * @param[in] params pointer to image description * @param[in] in_img pointer to grey scale image * @param mask_img pointer to binary image (0, 255) * @param[in] threshold below which the pixel is set 0 */ void sanei_ir_add_threshold (const SANE_Parameters * params, const SANE_Uint *in_img, SANE_Uint * mask_img, int threshold); /** * @brief Calculates minimal Manhattan distances for an image mask * * @param[in] params pointer to image description * @param[in] mask_img pointer to binary image (0, 255) * @param[out] dist_map integer pointer to map of closest distances * @param[out] idx_map integer pointer to indices of closest pixels * @param[in] erode == 0: closest pixel has value 0, != 0: is 255 * * manhattan_dist takes a mask image consisting of 0 or 255 values. Given that * a 0 represents a dirty pixel and erode != 0, manhattan_dist will calculate the * shortest distance to a clean (255) pixel and record which pixel that was so * that the clean parts of the image can be dilated into the dirty ones. Thresholding * can be done on the distance. Conversely, if erode == 0 the distance of a clean * pixel to the closest dirty one is calculated which can be used to dilate the mask. * * @ref extended and C version of * http://ostermiller.org/dilate_and_erode.html */ void sanei_ir_manhattan_dist (const SANE_Parameters * params, const SANE_Uint * mask_img, unsigned int *dist_map, unsigned int *idx_map, unsigned int erode); /** * @brief Dilate or erode a mask image * * @param[in] params pointer to image description * @param mask_img pointer to binary image (0, 255) * @param dist_map integer pointer to map of closest distances * @param idx_map integer pointer to indices of closest pixels * @param[in] by number of pixels, > 0 dilate, < 0 erode * * @note by > 0 will enlarge the 0 valued area */ void sanei_ir_dilate (const SANE_Parameters * params, SANE_Uint * mask_img, unsigned int *dist_map, unsigned int *idx_map, int by); /** * @brief Suggest cropping for dark margins of positive film * * @param[in] params pointer to image description * @param[in] dist_map integer pointer to map of closest distances * @param[in] inner crop within (!=0) or outside (==0) the image's edges * @param[out] edges pointer to array holding top, bottom, left * and right edges * * The distance map as calculated by sanei_ir_manhattan_dist contains * distances to the next clean pixel. Dark margins are detected as dirt. * So the first/last rows/columns tell us how to crop. This is rather * fast if the distance map has been calculated anyhow. */ void sanei_ir_find_crop (const SANE_Parameters * params, unsigned int * dist_map, int inner, int * edges); /** * @brief Dilate clean image parts into dirty ones and smooth int inner, * * @param[in] params pointer to image description * @param in_img array of pointers to color planes of image * @param[in] mask_img pointer to dirt mask image * @param[in] dist_max threshold up to which dilation is done * @param[in] expand the dirt mask before replacing the pixels * @param[in] win_size size of adaptive mean filtering window * @param[in] smooth triangular filter whole image for grain removal * @param[in] inner find crop within or outside the image's edges * @param[out] crop array of 4 integers, if non-NULL, top, bottom, * left and right values for cropping are returned. * * @return * - SANE_STATUS_GOOD - success * - SANE_STATUS_NO_MEM - if out of memory * * The main purpose of this routine is to replace dirty pixels. * As spin-off it obtains half of what is needed for film grain * smoothening and most of how to crop positive film. * To speed things up these functions are also implemented. */ SANE_Status sanei_ir_dilate_mean (const SANE_Parameters * params, SANE_Uint **in_img, SANE_Uint *mask_img, int dist_max, int expand, int win_size, SANE_Bool smooth, int inner, int *crop); #endif /* not SANEI_IR_H */ sane-backends-1.0.27/include/sane/sanei_pa4s2.h0000664000175000017500000001533112112021330016040 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2003 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_pa4s2.h * This file implements an interface for the Mustek PP chipset A4S2 * * @sa sanei_usb.h, sanei_ab306.h, sanei_lm983x.h, sanei_scsi.h, sanei_pio.h */ #ifndef sanei_pa4s2_h #define sanei_pa4s2_h #include #include /** @name Options to control interface operations */ /* @{ */ #define SANEI_PA4S2_OPT_DEFAULT 0 /* normal mode */ #define SANEI_PA4S2_OPT_TRY_MODE_UNI 1 /* enable UNI protocoll */ #define SANEI_PA4S2_OPT_ALT_LOCK 2 /* use alternative lock cmd */ #define SANEI_PA4S2_OPT_NO_EPP 4 /* do not try to use EPP */ /* @} */ /** Get list of possibly available devices * * Returns a list of arguments accepted as *dev by sanei_pa4s2_open * * @return * - array of known *devs. The last entry is marked as NULL pointer. The * user has to make sure, the array, but not the entries are freed. * * @sa sanei_pa4s2_open * */ extern const char ** sanei_pa4s2_devices(void); /** Open pa4s2 device * * Opens *dev as pa4s2 device. * * @param dev IO port address ("0x378", "0x278", or "0x3BC") * @param fd file descriptor * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if no scanner was found or the port number was wrong * - SANE_STATUS_DEVICE_BUSY - if the device is already in use * - SANE_STATUS_IO_ERROR - if the port couldn't be accessed * */ extern SANE_Status sanei_pa4s2_open (const char *dev, int *fd); /** Open pa4s2 SCSI-over-parallel device * * Opens *dev as pa4s2 SCSI-over-parallel device. * * @param dev IO port address ("0x378", "0x278", or "0x3BC") * @param fd file descriptor * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if no scanner was found or the port number was wrong * - SANE_STATUS_DEVICE_BUSY - if the device is already in use * - SANE_STATUS_IO_ERROR - if the port couldn't be accessed * */ extern SANE_Status sanei_pa4s2_scsi_pp_open (const char *dev, int *fd); /** Close pa4s2 device * * @param fd file descriptor */ extern void sanei_pa4s2_close (int fd); /** Set/get options * * Sets/gets interface options. Options will be taken over, when set is * SANE_TRUE. These options should be set before the first device is opened * * @param options pointer to options * @param set set (SANE_TRUE) or get (SANE_FALSE) options * * @return * - SANE_STATUS_GOOD - on success */ extern SANE_Status sanei_pa4s2_options (u_int * options, int set); /** Enables/disable device * * When the device is disabled, the printer can be accessed, when it's enabled * data can be read/written. * * @param fd file descriptor * @param enable enable (SANE_TRUE) or disable (SANE_FALSE) device * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if fd is invalid or device not in use */ extern SANE_Status sanei_pa4s2_enable (int fd, int enable); /** Select a register * * The function to read a register is split up in three parts, so a register * can be read more than once. * * @param fd file descriptor * @param reg register * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if fd is invalid or device not in use * * @sa sanei_pa4s2_readbyte(), sanei_pa4s2_readend() */ extern SANE_Status sanei_pa4s2_readbegin (int fd, u_char reg); /** Return port status information * * @param fd file descriptor * @param status variable to receive status * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if fd is invalid or device not in use */ extern SANE_Status sanei_pa4s2_scsi_pp_get_status (int fd, u_char *status); /** Selects a register number on a SCSI-over-parallel scanner * * @param fd file descriptor * @param reg register number * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if fd is invalid */ extern SANE_Status sanei_pa4s2_scsi_pp_reg_select (int fd, int reg); /** Read a register * * The function to read a register is split up in three parts, so a register * can be read more than once. * * @param fd file descriptor * @param val pointer to value * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if fd is invalid or device not in use * * @sa sanei_pa4s2_readbegin(), sanei_pa4s2_readend() */ extern SANE_Status sanei_pa4s2_readbyte (int fd, u_char * val); /** Terminate reading sequence * * The function to read a register is split up in three parts, so a register * can be read more than once. * * @param fd file descriptor * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if fd is invalid or device not in use * @sa sanei_pa4s2_readbegin(), sanei_pa4s2_readbyte() */ extern SANE_Status sanei_pa4s2_readend (int fd); /** Write a register * * @param fd file descriptor * @param reg register * @param val value to be written * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if fd is invalid or device not in use */ extern SANE_Status sanei_pa4s2_writebyte (int fd, u_char reg, u_char val); #endif sane-backends-1.0.27/include/lgetopt.h0000664000175000017500000001463312112021330014464 00000000000000/* Declarations for getopt. Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #if defined(HAVE_GETOPT_H) && defined(HAVE_GETOPT_LONG) #include #else #ifndef _GETOPT_H #ifndef __need_getopt # define _GETOPT_H 1 #endif /* If __GNU_LIBRARY__ is not already defined, either we are being used standalone, or this is the first header included in the source file. If we are being used with glibc, we need to include , but that does not exist if we are standalone. So: if __GNU_LIBRARY__ is not defined, include , which will pull in for us if it's from glibc. (Why ctype.h? It's guaranteed to exist and it doesn't flood the namespace with stuff the way some other headers do.) */ #if !defined __GNU_LIBRARY__ # include #endif #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; #ifndef __need_getopt /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { # if (defined __STDC__ && __STDC__) || defined __cplusplus const char *name; # else char *name; # endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ # define no_argument 0 # define required_argument 1 # define optional_argument 2 #endif /* need getopt */ /* Get definitions and prototypes for functions to process the arguments in ARGV (ARGC of them, minus the program name) for options given in OPTS. Return the option character from OPTS just read. Return -1 when there are no more options. For unrecognized options, or options missing arguments, `optopt' is set to the option letter, and '?' is returned. The OPTS string is a list of characters which are recognized option letters, optionally followed by colons, specifying that that letter takes an argument, to be placed in `optarg'. If a letter in OPTS is followed by two colons, its argument is optional. This behavior is specific to the GNU `getopt'. The argument `--' causes premature termination of argument scanning, explicitly telling `getopt' that there are no more options. If OPTS begins with `--', then non-option arguments are treated as arguments to the option '\0'. This behavior is specific to the GNU `getopt'. */ #if (defined __STDC__ && __STDC__) || defined __cplusplus # ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); # else /* not __GNU_LIBRARY__ */ extern int getopt (); # endif /* __GNU_LIBRARY__ */ # ifndef __need_getopt extern int getopt_long (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind); extern int getopt_long_only (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind, int __long_only); # endif #else /* not __STDC__ */ extern int getopt (); # ifndef __need_getopt extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); # endif #endif /* __STDC__ */ #ifdef __cplusplus } #endif /* Make sure we later can get all the definitions and declarations. */ #undef __need_getopt #endif /* lgetopt.h */ #endif /* !external getopt.h */ sane-backends-1.0.27/include/md5.h0000664000175000017500000001236512112021330013473 00000000000000/* Declaration of functions and data types used for MD5 sum computing library functions. Copyright (C) 1995,1996,1997,1999,2000,2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _MD5_H #define _MD5_H 1 #include #if defined HAVE_LIMITS_H || _LIBC # include #endif /* The following contortions are an attempt to use the C preprocessor to determine an unsigned integral type that is 32 bits wide. An alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but doing that would require that the configure script compile and *run* the resulting executable. Locally running cross-compiled executables is usually not possible. */ #ifdef _LIBC # include typedef uint32_t md5_uint32; typedef uintptr_t md5_uintptr; #else # if defined __STDC__ && __STDC__ # define UINT_MAX_32_BITS 4294967295U # else # define UINT_MAX_32_BITS 0xFFFFFFFF # endif /* If UINT_MAX isn't defined, assume it's a 32-bit type. This should be valid for all systems GNU cares about because that doesn't include 16-bit systems, and only modern systems (that certainly have ) have 64+-bit integral types. */ # ifndef UINT_MAX # define UINT_MAX UINT_MAX_32_BITS # endif # if UINT_MAX == UINT_MAX_32_BITS typedef unsigned int md5_uint32; # else # if USHRT_MAX == UINT_MAX_32_BITS typedef unsigned short md5_uint32; # else # if ULONG_MAX == UINT_MAX_32_BITS typedef unsigned long md5_uint32; # else /* The following line is intended to evoke an error. Using #error is not portable enough. */ "Cannot determine unsigned 32-bit data type." # endif # endif # endif /* We have to make a guess about the integer type equivalent in size to pointers which should always be correct. */ typedef unsigned long int md5_uintptr; #endif #undef __P #if defined (__STDC__) && __STDC__ # define __P(x) x #else # define __P(x) () #endif #define __md5_buffer md5_buffer #if defined __GNUC__ #define ALIGN __attribute__ ((__aligned__ (4))) #else #define ALIGN #endif /* Structure to save state of computation between the single steps. */ struct md5_ctx { md5_uint32 A; md5_uint32 B; md5_uint32 C; md5_uint32 D; md5_uint32 total[2]; md5_uint32 buflen; char buffer[128] ALIGN; }; /* * The following three functions are build up the low level used in * the functions `md5_stream' and `md5_buffer'. */ /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ extern void __md5_init_ctx __P ((struct md5_ctx *ctx)); /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is necessary that LEN is a multiple of 64!!! */ extern void __md5_process_block __P ((const void *buffer, size_t len, struct md5_ctx *ctx)); /* Starting with the result of former calls of this function (or the initialization function update the context for the next LEN bytes starting at BUFFER. It is NOT required that LEN is a multiple of 64. */ extern void __md5_process_bytes __P ((const void *buffer, size_t len, struct md5_ctx *ctx)); /* Process the remaining bytes in the buffer and put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ extern void *__md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf)); /* Put result from CTX in first 16 bytes following RESBUF. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ extern void *__md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf)); /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ extern int __md5_stream __P ((FILE *stream, void *resblock)); /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ extern void *__md5_buffer __P ((const char *buffer, size_t len, void *resblock)); #endif /* md5.h */ sane-backends-1.0.27/include/Makefile.in0000664000175000017500000004631313110564734014725 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = include DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(nobase_include_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(includedir)" HEADERS = $(nobase_include_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ nobase_include_HEADERS = sane/sane.h sane/saneopts.h EXTRA_DIST = lalloca.h lassert.h lgetopt.h md5.h font_6x11.h \ sane/config.h.in sane/sanei.h sane/sanei_ab306.h \ sane/sanei_access.h sane/sanei_auth.h sane/sanei_backend.h \ sane/sanei_cderror.h sane/sanei_codec_ascii.h \ sane/sanei_codec_bin.h sane/sanei_config.h sane/sanei_debug.h \ sane/sanei_jinclude.h sane/sanei_jpeg.h sane/sanei_lm983x.h \ sane/sanei_net.h sane/sanei_pa4s2.h sane/sanei_pio.h \ sane/sanei_pp.h sane/sanei_pv8630.h sane/sanei_scsi.h \ sane/sanei_tcp.h sane/sanei_thread.h sane/sanei_udp.h \ sane/sanei_usb.h sane/sanei_wire.h sane/sanei_magic.h \ sane/sanei_ir.h all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu include/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_includeHEADERS: $(nobase_include_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(HEADERS) installdirs: for dir in "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nobase_includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-nobase_includeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man \ install-nobase_includeHEADERS install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-nobase_includeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/include/Makefile.am0000664000175000017500000000160712775312262014714 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. nobase_include_HEADERS = sane/sane.h sane/saneopts.h EXTRA_DIST = lalloca.h lassert.h lgetopt.h md5.h font_6x11.h EXTRA_DIST += sane/config.h.in sane/sanei.h sane/sanei_ab306.h \ sane/sanei_access.h sane/sanei_auth.h sane/sanei_backend.h \ sane/sanei_cderror.h sane/sanei_codec_ascii.h sane/sanei_codec_bin.h \ sane/sanei_config.h sane/sanei_debug.h sane/sanei_jinclude.h \ sane/sanei_jpeg.h sane/sanei_lm983x.h sane/sanei_net.h sane/sanei_pa4s2.h \ sane/sanei_pio.h sane/sanei_pp.h sane/sanei_pv8630.h sane/sanei_scsi.h \ sane/sanei_tcp.h sane/sanei_thread.h sane/sanei_udp.h sane/sanei_usb.h \ sane/sanei_wire.h sane/sanei_magic.h sane/sanei_ir.h sane-backends-1.0.27/include/lassert.h0000664000175000017500000000453312112021330014461 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001 by Henning Meier-Geinitz This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Choose suitable implementation of assert. */ #ifndef lassert_h #define lassert_h /* The idea is from the gcc header file assert.h. */ #if defined __GNUC__ && defined _AIX /* The implementation of assert of gcc on AIX is in libgcc.a. This doesn't work with shared libraries. So let's make our own assert(). */ #define assert(arg) \ ((void) ((arg) ? 0 : lassert (arg, __FILE__, __LINE__))) #define lassert(arg, file, lineno) \ (printf ("%s:%u: failed assertion\n", file, lineno), \ abort (), 0) #else # include #endif #endif /* lassert_h */ sane-backends-1.0.27/include/font_6x11.h0000664000175000017500000020452112112021330014530 00000000000000/**********************************************/ /* */ /* Font file generated by rthelen */ /* */ /**********************************************/ static unsigned char fontdata[] = { /* 0 0x00 '^A' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 1 0x01 '^B' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 2 0x02 '^C' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 3 0x03 '^D' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 4 0x04 '^E' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 5 0x05 '^F' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 6 0x06 '^G' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 7 0x07 '^H' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 8 0x08 '^I' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 9 0x09 '^J' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 10 0x0a '^K' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 11 0x0b '^L' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 12 0x0c '^M' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 13 0x0d '^N' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 14 0x0e '^O' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 15 0x0f '^P' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 16 0x10 '^Q' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 17 0x11 '^R' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x54, /* 0 0 0 00 */ 0x38, /* 00 000 */ 0x54, /* 0 0 0 00 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 18 0x12 '^S' */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x50, /* 0 0 0000 */ 0x50, /* 0 0 0000 */ 0x20, /* 00 00000 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 19 0x13 '^T' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x7c, /* 0 00 */ 0x38, /* 00 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 20 0x14 '^U' */ 0x18, /* 000 000 */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x7c, /* 0 00 */ 0x78, /* 0 000 */ 0x78, /* 0 000 */ 0x7c, /* 0 00 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 21 0x15 '^V' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 22 0x16 '^W' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 23 0x17 '^X' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 24 0x18 '^Y' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 25 0x19 '^Z' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 26 0x1a '^[' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 27 0x1b '^\' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 28 0x1c '^]' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 29 0x1d '^^' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 30 0x1e '^_' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 31 0x1f '^`' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 32 0x20 ' ' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 33 0x21 '!' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 34 0x22 '"' */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 35 0x23 '#' */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x7c, /* 0 00 */ 0x28, /* 00 0 000 */ 0x7c, /* 0 00 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 36 0x24 '$' */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x54, /* 0 0 0 00 */ 0x50, /* 0 0 0000 */ 0x38, /* 00 000 */ 0x14, /* 000 0 00 */ 0x54, /* 0 0 0 00 */ 0x38, /* 00 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 37 0x25 '%' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x54, /* 0 0 0 00 */ 0x58, /* 0 0 000 */ 0x28, /* 00 0 000 */ 0x34, /* 00 0 00 */ 0x54, /* 0 0 0 00 */ 0x48, /* 0 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 38 0x26 '&' */ 0x00, /* 00000000 */ 0x30, /* 00 0000 */ 0x48, /* 0 00 000 */ 0x50, /* 0 0 0000 */ 0x20, /* 00 00000 */ 0x54, /* 0 0 0 00 */ 0x48, /* 0 00 000 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 39 0x27 ''' */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 40 0x28 '(' */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x04, /* 00000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 41 0x29 ')' */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 42 0x2a '*' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x54, /* 0 0 0 00 */ 0x38, /* 00 000 */ 0x54, /* 0 0 0 00 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 43 0x2b '+' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x7c, /* 0 00 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 44 0x2c ',' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x30, /* 00 0000 */ 0x30, /* 00 0000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ /* 45 0x2d '-' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 46 0x2e '.' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x18, /* 000 000 */ 0x18, /* 000 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 47 0x2f '/' */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x20, /* 00 00000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x00, /* 00000000 */ /* 48 0x30 '0' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x54, /* 0 0 0 00 */ 0x64, /* 0 00 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 49 0x31 '1' */ 0x00, /* 00000000 */ 0x08, /* 0000 000 */ 0x18, /* 000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x1c, /* 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 50 0x32 '2' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 51 0x33 '3' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x04, /* 00000 00 */ 0x18, /* 000 000 */ 0x04, /* 00000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 52 0x34 '4' */ 0x00, /* 00000000 */ 0x08, /* 0000 000 */ 0x18, /* 000 000 */ 0x28, /* 00 0 000 */ 0x48, /* 0 00 000 */ 0x7c, /* 0 00 */ 0x08, /* 0000 000 */ 0x1c, /* 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 53 0x35 '5' */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x78, /* 0 000 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 54 0x36 '6' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x40, /* 0 000000 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 55 0x37 '7' */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 56 0x38 '8' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 57 0x39 '9' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x3c, /* 00 00 */ 0x04, /* 00000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 58 0x3a ':' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x18, /* 000 000 */ 0x18, /* 000 000 */ 0x00, /* 00000000 */ 0x18, /* 000 000 */ 0x18, /* 000 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 59 0x3b ';' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x30, /* 00 0000 */ 0x30, /* 00 0000 */ 0x00, /* 00000000 */ 0x30, /* 00 0000 */ 0x30, /* 00 0000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ /* 60 0x3c '<' */ 0x00, /* 00000000 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x04, /* 00000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 61 0x3d '=' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 62 0x3e '>' */ 0x00, /* 00000000 */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 63 0x3f '?' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 64 0x40 '@' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x74, /* 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x78, /* 0 000 */ 0x40, /* 0 000000 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 65 0x41 'A' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 66 0x42 'B' */ 0x00, /* 00000000 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x78, /* 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 67 0x43 'C' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 68 0x44 'D' */ 0x00, /* 00000000 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x78, /* 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 69 0x45 'E' */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x78, /* 0 000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 70 0x46 'F' */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x78, /* 0 000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 71 0x47 'G' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x40, /* 0 000000 */ 0x4c, /* 0 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 72 0x48 'H' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 73 0x49 'I' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 74 0x4a 'J' */ 0x00, /* 00000000 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 75 0x4b 'K' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x48, /* 0 00 000 */ 0x50, /* 0 0 0000 */ 0x60, /* 0 00000 */ 0x50, /* 0 0 0000 */ 0x48, /* 0 00 000 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 76 0x4c 'L' */ 0x00, /* 00000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 77 0x4d 'M' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x6c, /* 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 78 0x4e 'N' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x64, /* 0 00 00 */ 0x54, /* 0 0 0 00 */ 0x4c, /* 0 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 79 0x4f 'O' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 80 0x50 'P' */ 0x00, /* 00000000 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x78, /* 0 000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 81 0x51 'Q' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x54, /* 0 0 0 00 */ 0x38, /* 00 000 */ 0x04, /* 00000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 82 0x52 'R' */ 0x00, /* 00000000 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 83 0x53 'S' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x40, /* 0 000000 */ 0x38, /* 00 000 */ 0x04, /* 00000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 84 0x54 'T' */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 85 0x55 'U' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 86 0x56 'V' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x28, /* 00 0 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 87 0x57 'W' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x6c, /* 0 0 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 88 0x58 'X' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x28, /* 00 0 000 */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 89 0x59 'Y' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x28, /* 00 0 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 90 0x5a 'Z' */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x40, /* 0 000000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 91 0x5b '[' */ 0x0c, /* 0000 00 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x0c, /* 0000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 92 0x5c '\' */ 0x20, /* 00 00000 */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x02, /* 000000 0 */ 0x02, /* 000000 0 */ 0x00, /* 00000000 */ /* 93 0x5d ']' */ 0x30, /* 00 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x30, /* 00 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 94 0x5e '^' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 95 0x5f '_' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x7e, /* 0 0 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 96 0x60 '`' */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 97 0x61 'a' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 98 0x62 'b' */ 0x00, /* 00000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x78, /* 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 99 0x63 'c' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x40, /* 0 000000 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 100 0x64 'd' */ 0x00, /* 00000000 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 101 0x65 'e' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 102 0x66 'f' */ 0x00, /* 00000000 */ 0x0c, /* 0000 00 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 103 0x67 'g' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x3c, /* 00 00 */ 0x04, /* 00000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ /* 104 0x68 'h' */ 0x00, /* 00000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 105 0x69 'i' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x30, /* 00 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 106 0x6a 'j' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x30, /* 00 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x60, /* 0 00000 */ 0x00, /* 00000000 */ /* 107 0x6b 'k' */ 0x00, /* 00000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x48, /* 0 00 000 */ 0x50, /* 0 0 0000 */ 0x70, /* 0 0000 */ 0x48, /* 0 00 000 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 108 0x6c 'l' */ 0x00, /* 00000000 */ 0x30, /* 00 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 109 0x6d 'm' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x78, /* 0 000 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 110 0x6e 'n' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x58, /* 0 0 000 */ 0x64, /* 0 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 111 0x6f 'o' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 112 0x70 'p' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x78, /* 0 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x78, /* 0 000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x00, /* 00000000 */ /* 113 0x71 'q' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x3c, /* 00 00 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x00, /* 00000000 */ /* 114 0x72 'r' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x58, /* 0 0 000 */ 0x64, /* 0 00 00 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 115 0x73 's' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x40, /* 0 000000 */ 0x38, /* 00 000 */ 0x04, /* 00000 00 */ 0x78, /* 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 116 0x74 't' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x0c, /* 0000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 117 0x75 'u' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 118 0x76 'v' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x28, /* 00 0 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 119 0x77 'w' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 120 0x78 'x' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x28, /* 00 0 000 */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 121 0x79 'y' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x3c, /* 00 00 */ 0x04, /* 00000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ /* 122 0x7a 'z' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 123 0x7b '{' */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x04, /* 00000 00 */ 0x00, /* 00000000 */ /* 124 0x7c '|' */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 125 0x7d '}' */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ /* 126 0x7e '~' */ 0x00, /* 00000000 */ 0x34, /* 00 0 00 */ 0x58, /* 0 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 127 0x7f '^?' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 128 0x80 '\200' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 129 0x81 '\201' */ 0x28, /* 00 0 000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 130 0x82 '\202' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 131 0x83 '\203' */ 0x10, /* 000 0000 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x78, /* 0 000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 132 0x84 '\204' */ 0x58, /* 0 0 000 */ 0x44, /* 0 000 00 */ 0x64, /* 0 00 00 */ 0x54, /* 0 0 0 00 */ 0x4c, /* 0 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 133 0x85 '\205' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 134 0x86 '\206' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 135 0x87 '\207' */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 136 0x88 '\210' */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 137 0x89 '\211' */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 138 0x8a '\212' */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 139 0x8b '\213' */ 0x34, /* 00 0 00 */ 0x58, /* 0 0 000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 140 0x8c '\214' */ 0x18, /* 000 000 */ 0x24, /* 00 00 00 */ 0x18, /* 000 000 */ 0x3c, /* 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 141 0x8d '\215' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x3c, /* 00 00 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ /* 142 0x8e '\216' */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 143 0x8f '\217' */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 144 0x90 '\220' */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 145 0x91 '\221' */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x40, /* 0 000000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 146 0x92 '\222' */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 147 0x93 '\223' */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 148 0x94 '\224' */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 149 0x95 '\225' */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 150 0x96 '\226' */ 0x34, /* 00 0 00 */ 0x58, /* 0 0 000 */ 0x00, /* 00000000 */ 0x58, /* 0 0 000 */ 0x64, /* 0 00 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 151 0x97 '\227' */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 152 0x98 '\230' */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 153 0x99 '\231' */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 154 0x9a '\232' */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 155 0x9b '\233' */ 0x34, /* 00 0 00 */ 0x58, /* 0 0 000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 156 0x9c '\234' */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 157 0x9d '\235' */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 158 0x9e '\236' */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 159 0x9f '\237' */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x34, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 160 0xa0 '\240' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 161 0xa1 '\241' */ 0x18, /* 000 000 */ 0x24, /* 00 00 00 */ 0x24, /* 00 00 00 */ 0x18, /* 000 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 162 0xa2 '\242' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x54, /* 0 0 0 00 */ 0x50, /* 0 0 0000 */ 0x54, /* 0 0 0 00 */ 0x38, /* 00 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 163 0xa3 '\243' */ 0x30, /* 00 0000 */ 0x48, /* 0 00 000 */ 0x40, /* 0 000000 */ 0x70, /* 0 0000 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x44, /* 0 000 00 */ 0x78, /* 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 164 0xa4 '\244' */ 0x44, /* 0 000 00 */ 0x24, /* 00 00 00 */ 0x50, /* 0 0 0000 */ 0x48, /* 0 00 000 */ 0x24, /* 00 00 00 */ 0x14, /* 000 0 00 */ 0x48, /* 0 00 000 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 165 0xa5 '\245' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x7c, /* 0 00 */ 0x7c, /* 0 00 */ 0x7c, /* 0 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 166 0xa6 '\246' */ 0x3c, /* 00 00 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x3c, /* 00 00 */ 0x14, /* 000 0 00 */ 0x14, /* 000 0 00 */ 0x14, /* 000 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 167 0xa7 '\247' */ 0x18, /* 000 000 */ 0x24, /* 00 00 00 */ 0x44, /* 0 000 00 */ 0x48, /* 0 00 000 */ 0x48, /* 0 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x58, /* 0 0 000 */ 0x40, /* 0 000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 168 0xa8 '\250' */ 0x00, /* 00000000 */ 0x70, /* 0 0000 */ 0x08, /* 0000 000 */ 0x64, /* 0 00 00 */ 0x54, /* 0 0 0 00 */ 0x64, /* 0 00 00 */ 0x58, /* 0 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 169 0xa9 '\251' */ 0x00, /* 00000000 */ 0x70, /* 0 0000 */ 0x08, /* 0000 000 */ 0x34, /* 00 0 00 */ 0x44, /* 0 000 00 */ 0x34, /* 00 0 00 */ 0x08, /* 0000 000 */ 0x70, /* 0 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 170 0xaa '\252' */ 0x00, /* 00000000 */ 0x7a, /* 0 0 0 */ 0x2e, /* 00 0 0 */ 0x2e, /* 00 0 0 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 171 0xab '\253' */ 0x00, /* 00000000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 172 0xac '\254' */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 173 0xad '\255' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x08, /* 0000 000 */ 0x7c, /* 0 00 */ 0x10, /* 000 0000 */ 0x7c, /* 0 00 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 174 0xae '\256' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x50, /* 0 0 0000 */ 0x50, /* 0 0 0000 */ 0x78, /* 0 000 */ 0x50, /* 0 0 0000 */ 0x50, /* 0 0 0000 */ 0x5c, /* 0 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 175 0xaf '\257' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x4c, /* 0 00 00 */ 0x54, /* 0 0 0 00 */ 0x64, /* 0 00 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 176 0xb0 '\260' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x6c, /* 0 0 00 */ 0x54, /* 0 0 0 00 */ 0x6c, /* 0 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 177 0xb1 '\261' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x7c, /* 0 00 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 178 0xb2 '\262' */ 0x00, /* 00000000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 179 0xb3 '\263' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x04, /* 00000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x1c, /* 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 180 0xb4 '\264' */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x28, /* 00 0 000 */ 0x7c, /* 0 00 */ 0x10, /* 000 0000 */ 0x7c, /* 0 00 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 181 0xb5 '\265' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x48, /* 0 00 000 */ 0x48, /* 0 00 000 */ 0x48, /* 0 00 000 */ 0x48, /* 0 00 000 */ 0x74, /* 0 0 00 */ 0x40, /* 0 000000 */ 0x40, /* 0 000000 */ 0x00, /* 00000000 */ /* 182 0xb6 '\266' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x0c, /* 0000 00 */ 0x14, /* 000 0 00 */ 0x24, /* 00 00 00 */ 0x24, /* 00 00 00 */ 0x18, /* 000 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 183 0xb7 '\267' */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x24, /* 00 00 00 */ 0x10, /* 000 0000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x24, /* 00 00 00 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 184 0xb8 '\270' */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 185 0xb9 '\271' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 186 0xba '\272' */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x60, /* 0 00000 */ 0x00, /* 00000000 */ /* 187 0xbb '\273' */ 0x00, /* 00000000 */ 0x1c, /* 000 00 */ 0x24, /* 00 00 00 */ 0x24, /* 00 00 00 */ 0x1c, /* 000 00 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 188 0xbc '\274' */ 0x00, /* 00000000 */ 0x18, /* 000 000 */ 0x24, /* 00 00 00 */ 0x24, /* 00 00 00 */ 0x18, /* 000 000 */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 189 0xbd '\275' */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x28, /* 00 0 000 */ 0x6c, /* 0 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 190 0xbe '\276' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x54, /* 0 0 0 00 */ 0x5c, /* 0 0 00 */ 0x50, /* 0 0 0000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 191 0xbf '\277' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x4c, /* 0 00 00 */ 0x54, /* 0 0 0 00 */ 0x64, /* 0 00 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 192 0xc0 '\300' */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x20, /* 00 00000 */ 0x40, /* 0 000000 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 193 0xc1 '\301' */ 0x00, /* 00000000 */ 0x08, /* 0000 000 */ 0x00, /* 00000000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x08, /* 0000 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 194 0xc2 '\302' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 195 0xc3 '\303' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x0c, /* 0000 00 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x50, /* 0 0 0000 */ 0x20, /* 00 00000 */ 0x20, /* 00 00000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 196 0xc4 '\304' */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x60, /* 0 00000 */ 0x00, /* 00000000 */ /* 197 0xc5 '\305' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x04, /* 00000 00 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x40, /* 0 000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 198 0xc6 '\306' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 199 0xc7 '\307' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x24, /* 00 00 00 */ 0x48, /* 0 00 000 */ 0x48, /* 0 00 000 */ 0x24, /* 00 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 200 0xc8 '\310' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x48, /* 0 00 000 */ 0x24, /* 00 00 00 */ 0x24, /* 00 00 00 */ 0x48, /* 0 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 201 0xc9 '\311' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x54, /* 0 0 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 202 0xca '\312' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 203 0xcb '\313' */ 0x10, /* 000 0000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 204 0xcc '\314' */ 0x58, /* 0 0 000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x7c, /* 0 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 205 0xcd '\315' */ 0x58, /* 0 0 000 */ 0x38, /* 00 000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 206 0xce '\316' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x50, /* 0 0 0000 */ 0x50, /* 0 0 0000 */ 0x58, /* 0 0 000 */ 0x50, /* 0 0 0000 */ 0x50, /* 0 0 0000 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 207 0xcf '\317' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x54, /* 0 0 0 00 */ 0x5c, /* 0 0 00 */ 0x50, /* 0 0 0000 */ 0x2c, /* 00 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 208 0xd0 '\320' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 209 0xd1 '\321' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x7e, /* 0 0 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 210 0xd2 '\322' */ 0x00, /* 00000000 */ 0x14, /* 000 0 00 */ 0x28, /* 00 0 000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 211 0xd3 '\323' */ 0x00, /* 00000000 */ 0x14, /* 000 0 00 */ 0x14, /* 000 0 00 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 212 0xd4 '\324' */ 0x00, /* 00000000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x18, /* 000 000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 213 0xd5 '\325' */ 0x00, /* 00000000 */ 0x18, /* 000 000 */ 0x08, /* 0000 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 214 0xd6 '\326' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x7c, /* 0 00 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 215 0xd7 '\327' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x10, /* 000 0000 */ 0x28, /* 00 0 000 */ 0x44, /* 0 000 00 */ 0x28, /* 00 0 000 */ 0x10, /* 000 0000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 216 0xd8 '\330' */ 0x00, /* 00000000 */ 0x28, /* 00 0 000 */ 0x00, /* 00000000 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x44, /* 0 000 00 */ 0x3c, /* 00 00 */ 0x04, /* 00000 00 */ 0x38, /* 00 000 */ 0x00, /* 00000000 */ /* 217 0xd9 '\331' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x7e, /* 0 0 */ 0x00, /* 00000000 */ 0x7e, /* 0 0 */ 0x00, /* 00000000 */ 0x7e, /* 0 0 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 218 0xda '\332' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 219 0xdb '\333' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 220 0xdc '\334' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 221 0xdd '\335' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 222 0xde '\336' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 223 0xdf '\337' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 224 0xe0 '\340' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 225 0xe1 '\341' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 226 0xe2 '\342' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 227 0xe3 '\343' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 228 0xe4 '\344' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 229 0xe5 '\345' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 230 0xe6 '\346' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 231 0xe7 '\347' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 232 0xe8 '\350' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 233 0xe9 '\351' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 234 0xea '\352' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 235 0xeb '\353' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 236 0xec '\354' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 237 0xed '\355' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 238 0xee '\356' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 239 0xef '\357' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 240 0xf0 '\360' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 241 0xf1 '\361' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 242 0xf2 '\362' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 243 0xf3 '\363' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 244 0xf4 '\364' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 245 0xf5 '\365' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 246 0xf6 '\366' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 247 0xf7 '\367' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 248 0xf8 '\370' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 249 0xf9 '\371' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 250 0xfa '\372' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 251 0xfb '\373' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 252 0xfc '\374' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 253 0xfd '\375' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 254 0xfe '\376' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ /* 255 0xff '\377' */ 0x00, /* 00000000 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x3c, /* 00 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ }; sane-backends-1.0.27/include/lalloca.h0000664000175000017500000000465312112021330014416 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Choose suitable implementation of alloca. */ #ifndef lalloca_h #define lalloca_h /* The idea how to do this is from the autoconf documenation */ /* AIX requires this to be the first thing in the file. */ #if defined(__GNUC__) # define alloca __builtin_alloca #else # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ /* Remap to internal version name as not to conflict with * other libraries that also add as util to their libraries. */ #define alloca sanei_alloca # if __STDC__ void *alloca (); # else char *alloca (); # endif # endif # endif # endif #endif #endif /* lalloca_h */ sane-backends-1.0.27/ABOUT-NLS0000664000175000017500000026713312775312260012472 000000000000001 Notes on the Free Translation Project *************************************** Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. 1.1 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. Installers may use special options at configuration time for changing the default behaviour. The command: ./configure --disable-nls will _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl' library and will decide to use it. If not, you may have to to use the `--with-libintl-prefix' option to tell `configure' where to look for it. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.2 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. If you happen to have the `LC_ALL' or some other `LC_xxx' environment variables set, you should unset them before setting `LANG', otherwise the setting of `LANG' will not have the desired effect. Here `LL' is an ISO 639 two-letter language code, and `CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). This can be done from your `.login' or `.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The country code serves to distinguish the dialects. The locale naming convention of `LL_CC', with `LL' denoting the language and `CC' denoting the country, is the one use on systems based on GNU libc. On other systems, some variations of this scheme are used, such as `LL' or `LL_CC.ENCODING'. You can get the list of locales supported by your system for your language by running the command `locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' for the purpose of message handling, but you still need to have `LANG' set to the primary language; this is required by other parts of the system libraries. For example, some Swedish users who would rather read translations in German than English for when Swedish is not available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. Special advice for Norwegian users: The language code for Norwegian bokma*l changed from `no' to `nb' recently (in 2003). During the transition period, while some message catalogs for this language are installed under `nb' and some older ones under `no', it's recommended for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and older translations are used. In the `LANGUAGE' environment variable, but not in the `LANG' environment variable, `LL_CC' combinations can be abbreviated as `LL' to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. 1.3 Translating Teams ===================== For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://translationproject.org/', in the "Teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has `-request' appended. For example, speakers of Swedish can send a message to `sv-request@li.org', having this message body: subscribe Keep in mind that team members are expected to participate _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to get started, please write to `coordinator@translationproject.org' to reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skills are praised more than programming skills, here. 1.4 Available Packages ====================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of June 2010. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files af am an ar as ast az be be@latin bg bn_IN bs ca +--------------------------------------------------+ a2ps | [] [] | aegis | | ant-phone | | anubis | | aspell | [] [] | bash | | bfd | | bibshelf | [] | binutils | | bison | | bison-runtime | [] | bluez-pin | [] [] | bombono-dvd | | buzztard | | cflow | | clisp | | coreutils | [] [] | cpio | | cppi | | cpplib | [] | cryptsetup | | dfarc | | dialog | [] [] | dico | | diffutils | [] | dink | | doodle | | e2fsprogs | [] | enscript | [] | exif | | fetchmail | [] | findutils | [] | flex | [] | freedink | | gas | | gawk | [] [] | gcal | [] | gcc | | gettext-examples | [] [] [] [] | gettext-runtime | [] [] | gettext-tools | [] [] | gip | [] | gjay | | gliv | [] | glunarclock | [] [] | gnubiff | | gnucash | [] | gnuedu | | gnulib | | gnunet | | gnunet-gtk | | gnutls | | gold | | gpe-aerial | | gpe-beam | | gpe-bluetooth | | gpe-calendar | | gpe-clock | [] | gpe-conf | | gpe-contacts | | gpe-edit | | gpe-filemanager | | gpe-go | | gpe-login | | gpe-ownerinfo | [] | gpe-package | | gpe-sketchbook | | gpe-su | [] | gpe-taskmanager | [] | gpe-timesheet | [] | gpe-today | [] | gpe-todo | | gphoto2 | | gprof | [] | gpsdrive | | gramadoir | | grep | | grub | [] [] | gsasl | | gss | | gst-plugins-bad | [] | gst-plugins-base | [] | gst-plugins-good | [] | gst-plugins-ugly | [] | gstreamer | [] [] [] | gtick | | gtkam | [] | gtkorphan | [] | gtkspell | [] [] [] | gutenprint | | hello | [] | help2man | | hylafax | | idutils | | indent | [] [] | iso_15924 | | iso_3166 | [] [] [] [] [] [] [] | iso_3166_2 | | iso_4217 | | iso_639 | [] [] [] [] | iso_639_3 | | jwhois | | kbd | | keytouch | [] | keytouch-editor | | keytouch-keyboa... | [] | klavaro | [] | latrine | | ld | [] | leafpad | [] [] | libc | [] [] | libexif | () | libextractor | | libgnutls | | libgpewidget | | libgpg-error | | libgphoto2 | | libgphoto2_port | | libgsasl | | libiconv | [] | libidn | | lifelines | | liferea | [] [] | lilypond | | linkdr | [] | lordsawar | | lprng | | lynx | [] | m4 | | mailfromd | | mailutils | | make | | man-db | | man-db-manpages | | minicom | | mkisofs | | myserver | | nano | [] [] | opcodes | | parted | | pies | | popt | | psmisc | | pspp | [] | pwdutils | | radius | [] | recode | [] [] | rosegarden | | rpm | | rush | | sarg | | screem | | scrollkeeper | [] [] [] | sed | [] [] | sharutils | [] [] | shishi | | skencil | | solfege | | solfege-manual | | soundtracker | | sp | | sysstat | | tar | [] | texinfo | | tin | | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] | vice | | vmm | | vorbis-tools | | wastesedge | | wdiff | | wget | [] [] | wyslij-po | | xchat | [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] | +--------------------------------------------------+ af am an ar as ast az be be@latin bg bn_IN bs ca 6 0 1 2 3 19 1 10 3 28 3 1 38 crh cs da de el en en_GB en_ZA eo es et eu fa +-------------------------------------------------+ a2ps | [] [] [] [] [] [] [] | aegis | [] [] [] | ant-phone | [] () | anubis | [] [] | aspell | [] [] [] [] [] | bash | [] [] [] | bfd | [] | bibshelf | [] [] [] | binutils | [] | bison | [] [] | bison-runtime | [] [] [] [] | bluez-pin | [] [] [] [] [] [] | bombono-dvd | [] | buzztard | [] [] [] | cflow | [] [] | clisp | [] [] [] [] | coreutils | [] [] [] [] | cpio | | cppi | | cpplib | [] [] [] | cryptsetup | [] | dfarc | [] [] [] | dialog | [] [] [] [] [] | dico | | diffutils | [] [] [] [] [] [] | dink | [] [] [] | doodle | [] | e2fsprogs | [] [] [] | enscript | [] [] [] | exif | () [] [] | fetchmail | [] [] () [] [] [] | findutils | [] [] [] | flex | [] [] | freedink | [] [] [] | gas | [] | gawk | [] [] [] | gcal | [] | gcc | [] [] | gettext-examples | [] [] [] [] | gettext-runtime | [] [] [] [] | gettext-tools | [] [] [] | gip | [] [] [] [] | gjay | [] | gliv | [] [] [] | glunarclock | [] [] | gnubiff | () | gnucash | [] () () () () | gnuedu | [] [] | gnulib | [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gold | [] | gpe-aerial | [] [] [] [] | gpe-beam | [] [] [] [] | gpe-bluetooth | [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] | gpe-conf | [] [] [] | gpe-contacts | [] [] [] | gpe-edit | [] [] | gpe-filemanager | [] [] [] | gpe-go | [] [] [] [] | gpe-login | [] [] | gpe-ownerinfo | [] [] [] [] | gpe-package | [] [] [] | gpe-sketchbook | [] [] [] [] | gpe-su | [] [] [] [] | gpe-taskmanager | [] [] [] [] | gpe-timesheet | [] [] [] [] | gpe-today | [] [] [] [] | gpe-todo | [] [] [] | gphoto2 | [] [] () [] [] [] | gprof | [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | [] | grub | [] [] | gsasl | [] | gss | | gst-plugins-bad | [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] () [] | gtkam | [] [] () [] [] | gtkorphan | [] [] [] [] | gtkspell | [] [] [] [] [] [] [] | gutenprint | [] [] [] | hello | [] [] [] [] | help2man | [] | hylafax | [] [] | idutils | [] [] | indent | [] [] [] [] [] [] [] | iso_15924 | [] () [] [] | iso_3166 | [] [] [] [] () [] [] [] () | iso_3166_2 | () | iso_4217 | [] [] [] () [] [] | iso_639 | [] [] [] [] () [] [] | iso_639_3 | [] | jwhois | [] | kbd | [] [] [] [] [] | keytouch | [] [] | keytouch-editor | [] [] | keytouch-keyboa... | [] | klavaro | [] [] [] [] | latrine | [] () | ld | [] [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] | libexif | [] [] () | libextractor | | libgnutls | [] | libgpewidget | [] [] | libgpg-error | [] [] | libgphoto2 | [] () | libgphoto2_port | [] () [] | libgsasl | | libiconv | [] [] [] [] [] | libidn | [] [] [] | lifelines | [] () | liferea | [] [] [] [] [] | lilypond | [] [] [] | linkdr | [] [] [] | lordsawar | [] | lprng | | lynx | [] [] [] [] | m4 | [] [] [] [] | mailfromd | | mailutils | [] | make | [] [] [] | man-db | | man-db-manpages | | minicom | [] [] [] [] | mkisofs | | myserver | | nano | [] [] [] | opcodes | [] [] | parted | [] [] | pies | | popt | [] [] [] [] [] | psmisc | [] [] [] | pspp | [] | pwdutils | [] | radius | [] | recode | [] [] [] [] [] [] | rosegarden | () () () | rpm | [] [] [] | rush | | sarg | | screem | | scrollkeeper | [] [] [] [] [] | sed | [] [] [] [] [] [] | sharutils | [] [] [] [] | shishi | | skencil | [] () [] | solfege | [] [] [] | solfege-manual | [] [] | soundtracker | [] [] [] | sp | [] | sysstat | [] [] [] | tar | [] [] [] [] | texinfo | [] [] [] | tin | [] [] | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] [] [] [] | vice | () () | vmm | [] | vorbis-tools | [] [] | wastesedge | [] | wdiff | [] [] | wget | [] [] [] | wyslij-po | | xchat | [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] [] [] | +-------------------------------------------------+ crh cs da de el en en_GB en_ZA eo es et eu fa 5 64 105 117 18 1 8 0 28 89 18 19 0 fi fr ga gl gu he hi hr hu hy id is it ja ka kn +----------------------------------------------------+ a2ps | [] [] [] [] | aegis | [] [] | ant-phone | [] [] | anubis | [] [] [] [] | aspell | [] [] [] [] | bash | [] [] [] [] | bfd | [] [] [] | bibshelf | [] [] [] [] [] | binutils | [] [] [] | bison | [] [] [] [] | bison-runtime | [] [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] | bombono-dvd | [] | buzztard | [] | cflow | [] [] [] | clisp | [] | coreutils | [] [] [] [] [] | cpio | [] [] [] [] | cppi | [] [] | cpplib | [] [] [] | cryptsetup | [] [] [] | dfarc | [] [] [] | dialog | [] [] [] [] [] [] [] | dico | | diffutils | [] [] [] [] [] [] [] [] [] | dink | [] | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] | exif | [] [] [] [] [] [] | fetchmail | [] [] [] [] | findutils | [] [] [] [] [] [] | flex | [] [] [] | freedink | [] [] [] | gas | [] [] | gawk | [] [] [] [] () [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] | gettext-tools | [] [] [] [] | gip | [] [] [] [] [] [] | gjay | [] | gliv | [] () | glunarclock | [] [] [] [] | gnubiff | () [] () | gnucash | () () () () () [] | gnuedu | [] [] | gnulib | [] [] [] [] [] [] | gnunet | | gnunet-gtk | [] | gnutls | [] [] | gold | [] [] | gpe-aerial | [] [] [] | gpe-beam | [] [] [] [] | gpe-bluetooth | [] [] [] [] | gpe-calendar | [] [] | gpe-clock | [] [] [] [] [] | gpe-conf | [] [] [] [] | gpe-contacts | [] [] [] [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] [] [] | gpe-go | [] [] [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] [] [] [] | gpe-package | [] [] [] | gpe-sketchbook | [] [] [] [] | gpe-su | [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] | gpe-todo | [] [] [] | gphoto2 | [] [] [] [] [] [] | gprof | [] [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] [] | grep | [] [] | grub | [] [] [] [] | gsasl | [] [] [] [] [] | gss | [] [] [] [] [] | gst-plugins-bad | [] [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] [] [] [] [] | gtkam | [] [] [] [] [] | gtkorphan | [] [] [] | gtkspell | [] [] [] [] [] [] [] [] [] | gutenprint | [] [] [] [] | hello | [] [] [] | help2man | [] [] | hylafax | [] | idutils | [] [] [] [] [] [] | indent | [] [] [] [] [] [] [] [] | iso_15924 | [] () [] [] | iso_3166 | [] () [] [] [] [] [] [] [] [] [] [] | iso_3166_2 | () [] [] [] | iso_4217 | [] () [] [] [] [] | iso_639 | [] () [] [] [] [] [] [] [] | iso_639_3 | () [] [] | jwhois | [] [] [] [] [] | kbd | [] [] | keytouch | [] [] [] [] [] [] | keytouch-editor | [] [] [] [] [] | keytouch-keyboa... | [] [] [] [] [] | klavaro | [] [] | latrine | [] [] [] | ld | [] [] [] [] | leafpad | [] [] [] [] [] [] [] () | libc | [] [] [] [] [] | libexif | [] | libextractor | | libgnutls | [] [] | libgpewidget | [] [] [] [] | libgpg-error | [] [] | libgphoto2 | [] [] [] | libgphoto2_port | [] [] [] | libgsasl | [] [] [] [] [] | libiconv | [] [] [] [] [] [] | libidn | [] [] [] [] | lifelines | () | liferea | [] [] [] [] | lilypond | [] [] | linkdr | [] [] [] [] [] | lordsawar | | lprng | [] | lynx | [] [] [] [] [] | m4 | [] [] [] [] [] [] | mailfromd | | mailutils | [] [] | make | [] [] [] [] [] [] [] [] [] | man-db | [] [] | man-db-manpages | [] | minicom | [] [] [] [] [] | mkisofs | [] [] [] [] | myserver | | nano | [] [] [] [] [] [] | opcodes | [] [] [] [] | parted | [] [] [] [] | pies | | popt | [] [] [] [] [] [] [] [] [] | psmisc | [] [] [] | pspp | | pwdutils | [] [] | radius | [] [] | recode | [] [] [] [] [] [] [] [] | rosegarden | () () () () () | rpm | [] [] | rush | | sarg | [] | screem | [] [] | scrollkeeper | [] [] [] [] | sed | [] [] [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] [] | shishi | [] | skencil | [] | solfege | [] [] [] [] | solfege-manual | [] [] | soundtracker | [] [] | sp | [] () | sysstat | [] [] [] [] [] | tar | [] [] [] [] [] [] [] | texinfo | [] [] [] [] | tin | [] | unicode-han-tra... | | unicode-transla... | [] [] | util-linux-ng | [] [] [] [] [] [] | vice | () () () | vmm | [] | vorbis-tools | [] | wastesedge | () () | wdiff | [] | wget | [] [] [] [] [] [] [] [] | wyslij-po | [] [] [] | xchat | [] [] [] [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] [] | +----------------------------------------------------+ fi fr ga gl gu he hi hr hu hy id is it ja ka kn 105 121 53 20 4 8 3 5 53 2 120 5 84 67 0 4 ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne +-----------------------------------------------+ a2ps | [] | aegis | | ant-phone | | anubis | [] [] | aspell | [] | bash | | bfd | | bibshelf | [] [] | binutils | | bison | [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] | bombono-dvd | | buzztard | | cflow | | clisp | | coreutils | [] | cpio | | cppi | | cpplib | | cryptsetup | | dfarc | [] | dialog | [] [] [] [] [] | dico | | diffutils | [] [] | dink | | doodle | | e2fsprogs | | enscript | | exif | [] | fetchmail | | findutils | | flex | | freedink | [] | gas | | gawk | | gcal | | gcc | | gettext-examples | [] [] [] [] | gettext-runtime | [] | gettext-tools | [] | gip | [] [] | gjay | | gliv | | glunarclock | [] | gnubiff | | gnucash | () () () () | gnuedu | | gnulib | | gnunet | | gnunet-gtk | | gnutls | [] | gold | | gpe-aerial | [] | gpe-beam | [] | gpe-bluetooth | [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] [] | gpe-conf | [] [] | gpe-contacts | [] [] | gpe-edit | [] | gpe-filemanager | [] [] | gpe-go | [] [] [] | gpe-login | [] | gpe-ownerinfo | [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] | gpe-timesheet | [] [] | gpe-today | [] [] [] [] | gpe-todo | [] [] | gphoto2 | | gprof | [] | gpsdrive | | gramadoir | | grep | | grub | | gsasl | | gss | | gst-plugins-bad | [] [] [] [] | gst-plugins-base | [] [] | gst-plugins-good | [] [] | gst-plugins-ugly | [] [] [] [] [] | gstreamer | | gtick | | gtkam | [] | gtkorphan | [] [] | gtkspell | [] [] [] [] [] [] [] | gutenprint | | hello | [] [] [] | help2man | | hylafax | | idutils | | indent | | iso_15924 | [] [] | iso_3166 | [] [] () [] [] [] [] [] | iso_3166_2 | | iso_4217 | [] [] | iso_639 | [] [] | iso_639_3 | [] | jwhois | [] | kbd | | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | klavaro | [] | latrine | [] | ld | | leafpad | [] [] [] | libc | [] | libexif | | libextractor | | libgnutls | [] | libgpewidget | [] [] | libgpg-error | | libgphoto2 | | libgphoto2_port | | libgsasl | | libiconv | | libidn | | lifelines | | liferea | | lilypond | | linkdr | | lordsawar | | lprng | | lynx | | m4 | | mailfromd | | mailutils | | make | [] | man-db | | man-db-manpages | | minicom | [] | mkisofs | | myserver | | nano | [] [] | opcodes | | parted | | pies | | popt | [] [] [] | psmisc | | pspp | | pwdutils | | radius | | recode | | rosegarden | | rpm | | rush | | sarg | | screem | | scrollkeeper | [] [] | sed | | sharutils | | shishi | | skencil | | solfege | [] | solfege-manual | | soundtracker | | sp | | sysstat | [] | tar | [] | texinfo | [] | tin | | unicode-han-tra... | | unicode-transla... | | util-linux-ng | | vice | | vmm | | vorbis-tools | | wastesedge | | wdiff | | wget | [] | wyslij-po | | xchat | [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | +-----------------------------------------------+ ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne 20 5 10 1 13 48 4 2 2 4 24 10 20 3 1 nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr +---------------------------------------------------+ a2ps | [] [] [] [] [] [] [] [] | aegis | [] [] [] | ant-phone | [] [] | anubis | [] [] [] | aspell | [] [] [] [] [] | bash | [] [] | bfd | [] | bibshelf | [] [] | binutils | [] [] | bison | [] [] [] | bison-runtime | [] [] [] [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] | bombono-dvd | [] () | buzztard | [] [] | cflow | [] | clisp | [] [] | coreutils | [] [] [] [] [] [] | cpio | [] [] [] | cppi | [] | cpplib | [] | cryptsetup | [] | dfarc | [] | dialog | [] [] [] [] | dico | [] | diffutils | [] [] [] [] [] [] | dink | () | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] [] | exif | [] [] [] () [] | fetchmail | [] [] [] [] | findutils | [] [] [] [] [] | flex | [] [] [] [] [] | freedink | [] [] | gas | | gawk | [] [] [] [] | gcal | | gcc | [] | gettext-examples | [] [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] [] [] [] | gettext-tools | [] [] [] [] [] [] | gip | [] [] [] [] [] | gjay | | gliv | [] [] [] [] [] [] | glunarclock | [] [] [] [] [] | gnubiff | [] () | gnucash | [] () () () | gnuedu | [] | gnulib | [] [] [] [] | gnunet | | gnunet-gtk | | gnutls | [] [] | gold | | gpe-aerial | [] [] [] [] [] [] [] | gpe-beam | [] [] [] [] [] [] [] | gpe-bluetooth | [] [] | gpe-calendar | [] [] [] [] | gpe-clock | [] [] [] [] [] [] [] [] | gpe-conf | [] [] [] [] [] [] [] | gpe-contacts | [] [] [] [] [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] [] | gpe-go | [] [] [] [] [] [] [] [] | gpe-login | [] [] | gpe-ownerinfo | [] [] [] [] [] [] [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] [] [] [] [] [] | gpe-su | [] [] [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] [] | gpe-todo | [] [] [] [] [] | gphoto2 | [] [] [] [] [] [] [] [] | gprof | [] [] [] | gpsdrive | [] [] | gramadoir | [] [] | grep | [] [] [] [] | grub | [] [] [] | gsasl | [] [] [] [] | gss | [] [] [] | gst-plugins-bad | [] [] [] [] [] [] | gst-plugins-base | [] [] [] [] [] | gst-plugins-good | [] [] [] [] [] | gst-plugins-ugly | [] [] [] [] [] [] | gstreamer | [] [] [] [] [] | gtick | [] [] [] | gtkam | [] [] [] [] [] [] | gtkorphan | [] | gtkspell | [] [] [] [] [] [] [] [] [] [] | gutenprint | [] [] | hello | [] [] [] [] | help2man | [] [] | hylafax | [] | idutils | [] [] [] [] [] | indent | [] [] [] [] [] [] [] | iso_15924 | [] [] [] [] | iso_3166 | [] [] [] [] [] () [] [] [] [] [] [] [] [] | iso_3166_2 | [] [] [] | iso_4217 | [] [] [] [] [] [] [] [] | iso_639 | [] [] [] [] [] [] [] [] [] | iso_639_3 | [] [] | jwhois | [] [] [] [] | kbd | [] [] [] | keytouch | [] [] [] | keytouch-editor | [] [] [] | keytouch-keyboa... | [] [] [] | klavaro | [] [] | latrine | [] [] | ld | | leafpad | [] [] [] [] [] [] [] [] [] | libc | [] [] [] [] | libexif | [] [] () [] | libextractor | | libgnutls | [] [] | libgpewidget | [] [] [] | libgpg-error | [] [] | libgphoto2 | [] [] | libgphoto2_port | [] [] [] [] [] | libgsasl | [] [] [] [] [] | libiconv | [] [] [] [] [] | libidn | [] [] | lifelines | [] [] | liferea | [] [] [] [] [] () () [] | lilypond | [] | linkdr | [] [] [] | lordsawar | | lprng | [] | lynx | [] [] [] | m4 | [] [] [] [] [] | mailfromd | [] | mailutils | [] | make | [] [] [] [] | man-db | [] [] [] | man-db-manpages | [] [] [] | minicom | [] [] [] [] | mkisofs | [] [] [] | myserver | | nano | [] [] [] [] | opcodes | [] [] | parted | [] [] [] [] | pies | [] | popt | [] [] [] [] | psmisc | [] [] [] | pspp | [] [] | pwdutils | [] | radius | [] [] [] | recode | [] [] [] [] [] [] [] [] | rosegarden | () () | rpm | [] [] [] | rush | [] [] | sarg | | screem | | scrollkeeper | [] [] [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] [] | sharutils | [] [] [] [] | shishi | [] | skencil | [] [] | solfege | [] [] [] [] | solfege-manual | [] [] [] | soundtracker | [] | sp | | sysstat | [] [] [] [] | tar | [] [] [] [] | texinfo | [] [] [] [] | tin | [] | unicode-han-tra... | | unicode-transla... | | util-linux-ng | [] [] [] [] [] | vice | [] | vmm | [] | vorbis-tools | [] [] | wastesedge | [] | wdiff | [] [] | wget | [] [] [] [] [] [] [] | wyslij-po | [] [] [] | xchat | [] [] [] [] [] [] [] [] [] | xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] | +---------------------------------------------------+ nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr 135 10 4 7 105 1 29 62 47 91 3 54 46 9 37 sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW +---------------------------------------------------+ a2ps | [] [] [] [] [] | 27 aegis | [] | 9 ant-phone | [] [] [] [] | 9 anubis | [] [] [] [] | 15 aspell | [] [] [] | 20 bash | [] [] [] | 12 bfd | [] | 6 bibshelf | [] [] [] | 16 binutils | [] [] | 8 bison | [] [] | 12 bison-runtime | [] [] [] [] [] [] | 29 bluez-pin | [] [] [] [] [] [] [] [] | 37 bombono-dvd | [] | 4 buzztard | [] | 7 cflow | [] [] [] | 9 clisp | | 10 coreutils | [] [] [] [] | 22 cpio | [] [] [] [] [] [] | 13 cppi | [] [] | 5 cpplib | [] [] [] [] [] [] | 14 cryptsetup | [] [] | 7 dfarc | [] | 9 dialog | [] [] [] [] [] [] [] | 30 dico | [] | 2 diffutils | [] [] [] [] [] [] | 30 dink | | 4 doodle | [] [] | 7 e2fsprogs | [] [] [] | 11 enscript | [] [] [] [] | 17 exif | [] [] [] | 16 fetchmail | [] [] [] | 17 findutils | [] [] [] [] [] | 20 flex | [] [] [] [] | 15 freedink | [] | 10 gas | [] | 4 gawk | [] [] [] [] | 18 gcal | [] [] | 5 gcc | [] [] [] | 7 gettext-examples | [] [] [] [] [] [] [] | 34 gettext-runtime | [] [] [] [] [] [] [] | 29 gettext-tools | [] [] [] [] [] [] | 22 gip | [] [] [] [] | 22 gjay | [] | 3 gliv | [] [] [] | 14 glunarclock | [] [] [] [] [] | 19 gnubiff | [] [] | 4 gnucash | () [] () [] () | 10 gnuedu | [] [] | 7 gnulib | [] [] [] [] | 16 gnunet | [] | 1 gnunet-gtk | [] [] [] | 5 gnutls | [] [] [] | 10 gold | [] | 4 gpe-aerial | [] [] [] | 18 gpe-beam | [] [] [] | 19 gpe-bluetooth | [] [] [] | 13 gpe-calendar | [] [] [] [] | 12 gpe-clock | [] [] [] [] [] | 28 gpe-conf | [] [] [] [] | 20 gpe-contacts | [] [] [] | 17 gpe-edit | [] [] [] | 12 gpe-filemanager | [] [] [] [] | 16 gpe-go | [] [] [] [] [] | 25 gpe-login | [] [] [] | 11 gpe-ownerinfo | [] [] [] [] [] | 25 gpe-package | [] [] [] | 13 gpe-sketchbook | [] [] [] | 20 gpe-su | [] [] [] [] [] | 30 gpe-taskmanager | [] [] [] [] [] | 29 gpe-timesheet | [] [] [] [] [] | 25 gpe-today | [] [] [] [] [] [] | 30 gpe-todo | [] [] [] [] | 17 gphoto2 | [] [] [] [] [] | 24 gprof | [] [] [] | 15 gpsdrive | [] [] [] | 11 gramadoir | [] [] [] | 11 grep | [] [] [] | 10 grub | [] [] [] | 14 gsasl | [] [] [] [] | 14 gss | [] [] [] | 11 gst-plugins-bad | [] [] [] [] | 26 gst-plugins-base | [] [] [] [] [] | 24 gst-plugins-good | [] [] [] [] | 24 gst-plugins-ugly | [] [] [] [] [] | 29 gstreamer | [] [] [] [] | 22 gtick | [] [] [] | 13 gtkam | [] [] [] | 20 gtkorphan | [] [] [] | 14 gtkspell | [] [] [] [] [] [] [] [] [] | 45 gutenprint | [] | 10 hello | [] [] [] [] [] [] | 21 help2man | [] [] | 7 hylafax | [] | 5 idutils | [] [] [] [] | 17 indent | [] [] [] [] [] [] | 30 iso_15924 | () [] () [] [] | 16 iso_3166 | [] [] () [] [] () [] [] [] () | 53 iso_3166_2 | () [] () [] | 9 iso_4217 | [] () [] [] () [] [] | 26 iso_639 | [] [] [] () [] () [] [] [] [] | 38 iso_639_3 | [] () | 8 jwhois | [] [] [] [] [] | 16 kbd | [] [] [] [] [] | 15 keytouch | [] [] [] | 16 keytouch-editor | [] [] [] | 14 keytouch-keyboa... | [] [] [] | 14 klavaro | [] | 11 latrine | [] [] [] | 10 ld | [] [] [] [] | 11 leafpad | [] [] [] [] [] [] | 33 libc | [] [] [] [] [] | 21 libexif | [] () | 7 libextractor | [] | 1 libgnutls | [] [] [] | 9 libgpewidget | [] [] [] | 14 libgpg-error | [] [] [] | 9 libgphoto2 | [] [] | 8 libgphoto2_port | [] [] [] [] | 14 libgsasl | [] [] [] | 13 libiconv | [] [] [] [] | 21 libidn | () [] [] | 11 lifelines | [] | 4 liferea | [] [] [] | 21 lilypond | [] | 7 linkdr | [] [] [] [] [] | 17 lordsawar | | 1 lprng | [] | 3 lynx | [] [] [] [] | 17 m4 | [] [] [] [] | 19 mailfromd | [] [] | 3 mailutils | [] | 5 make | [] [] [] [] | 21 man-db | [] [] [] | 8 man-db-manpages | | 4 minicom | [] [] | 16 mkisofs | [] [] | 9 myserver | | 0 nano | [] [] [] [] | 21 opcodes | [] [] [] | 11 parted | [] [] [] [] [] | 15 pies | [] [] | 3 popt | [] [] [] [] [] [] | 27 psmisc | [] [] | 11 pspp | | 4 pwdutils | [] [] | 6 radius | [] [] | 9 recode | [] [] [] [] | 28 rosegarden | () | 0 rpm | [] [] [] | 11 rush | [] [] | 4 sarg | | 1 screem | [] | 3 scrollkeeper | [] [] [] [] [] | 27 sed | [] [] [] [] [] | 30 sharutils | [] [] [] [] [] | 22 shishi | [] | 3 skencil | [] [] | 7 solfege | [] [] [] [] | 16 solfege-manual | [] | 8 soundtracker | [] [] [] | 9 sp | [] | 3 sysstat | [] [] | 15 tar | [] [] [] [] [] [] | 23 texinfo | [] [] [] [] [] | 17 tin | | 4 unicode-han-tra... | | 0 unicode-transla... | | 2 util-linux-ng | [] [] [] [] | 20 vice | () () | 1 vmm | [] | 4 vorbis-tools | [] | 6 wastesedge | | 2 wdiff | [] [] | 7 wget | [] [] [] [] [] | 26 wyslij-po | [] [] | 8 xchat | [] [] [] [] [] [] | 36 xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | 63 xkeyboard-config | [] [] [] | 22 +---------------------------------------------------+ 85 teams sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW 178 domains 119 1 3 3 0 10 65 51 155 17 98 7 41 2618 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to which it applies should also have been internationalized and distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. If June 2010 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at `http://translationproject.org/extra/matrix.html'. 1.5 Using `gettext' in new packages =================================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `coordinator@translationproject.org' to make the `.pot' files available to the translation teams. sane-backends-1.0.27/compile0000775000175000017500000001624512775312261012616 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sane-backends-1.0.27/README.unixware70000664000175000017500000000546212775312260014046 00000000000000SANE on UnixWare 7 ================== The easiest way to get SANE working on a UnixWare 7.1.X system (UW 7.0.0 and 7.0.1 are not supported) is to download and install the SANE binary distribution from SCOs Skunkware web site. The URL is: ftp://ftp.sco.com/skunkware/uw7/Packages Use the pkgadd command to install the files, e.g.: # pkgadd -d `pwd`/sane-1.0.2.pkg A web page with further information specific to SANE on UnixWare 7 can be found here: http://www.sco.com/skunkware/sane/index.html However, please note that the SANE package that is available from the Skunkware server will most likely contain the latest stable version of SANE. Since SANE is continously being worked on, you might want to download the latest source from the Git repository and build the source yourself. To build SANE on a UnixWare 7.1.X system the following packages are required: * make (GNU make) * glibs (contains gtk, glib, libjpeg, libpnm, libtiff etc.; only necessary for frontends xscanimage, xcam, and xsane which are distributed separately) The packages can be downloaded from the Skunkware ftp server (see URL above). I've used the following versions to build sane-1.0.2: * make-3.78.1.pkg * glibs-2.0.3.pkg If you want to include support for The Gimp (this is optional), you need to install the gimp package, too. This is the version I've used: * gimp-1.0.4.pkg GCC is not required. SANE compiles quite happily (and faster) with UnixWares native C compiler. Set the LD_RUN_PATH variable to add /usr/local/lib to the list of directories to be searched by the dynamic linker: $ LD_RUN_PATH=/usr/local/lib $ export LD_RUN_PATH Run the configure script as following: $ LIBS="-lsdi" ./configure (The sdi library contains the SCSI passthrough functions the UW7 port of SANE uses to access the scanner from user space.) Run gmake to build SANE: $ gmake SCSI access from user space requires special privileges. If you want users without root perms to be able to use the scanner you can use the filepriv command to change the privileges that are associated with the SANE applications: # /sbin/filepriv -f driver -f sysops /usr/local/bin/scanimage # /sbin/filepriv -f driver -f sysops /usr/local/bin/xscanimage # /sbin/filepriv -f sysops /usr/local/bin/xcam If you have built SANE with support for The Gimp you might want to create a symlink from the plug-in directory to the xscanimage and xcam binaries, e.g.: # ln -s /usr/local/bin/xscanimage \ /usr/local/lib/gimp/1.0/plug-ins/xscanimage # ln -s /usr/local/bin/xcam /usr/local/lib/gimp/1.0/plug-ins/xcam Questions? Comments? Please send e-mail to jenss@sco.com or skunkware@sco.com! sane-backends-1.0.27/aclocal.m40000664000175000017500000015244413110564727013102 00000000000000# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # PKG_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable pkgconfigdir as the location where a module # should install pkg-config .pc files. By default the directory is # $libdir/pkgconfig, but the default can be changed by passing # DIRECTORY. The user can override through the --with-pkgconfigdir # parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_INSTALLDIR # PKG_NOARCH_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable noarch_pkgconfigdir as the location where a # module should install arch-independent pkg-config .pc files. By # default the directory is $datadir/pkgconfig, but the default can be # changed by passing DIRECTORY. The user can override through the # --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_NOARCH_INSTALLDIR # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.14' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.14.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.14.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Copyright (C) 2011-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_AR([ACT-IF-FAIL]) # ------------------------- # Try to determine the archiver interface, and trigger the ar-lib wrapper # if it is needed. If the detection of archiver interface fails, run # ACT-IF-FAIL (default is to abort configure with a proper error message). AC_DEFUN([AM_PROG_AR], [AC_BEFORE([$0], [LT_INIT])dnl AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([ar-lib])dnl AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) : ${AR=ar} AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], [AC_LANG_PUSH([C]) am_cv_ar_interface=ar AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a ]) AC_LANG_POP([C])]) case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) m4_default([$1], [AC_MSG_ERROR([could not determine $AR interface])]) ;; esac AC_SUBST([AR])dnl ]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for 'mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl FIXME we are no longer going to remove this! adjust warning dnl FIXME message accordingly. AC_DIAGNOSE([obsolete], [$0: this macro is deprecated, and will soon be removed. You should use the Autoconf-provided 'AC][_PROG_MKDIR_P' macro instead, and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.]) dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/gettext.m4]) m4_include([m4/iconv.m4]) m4_include([m4/intlmacosx.m4]) m4_include([m4/lib-ld.m4]) m4_include([m4/lib-link.m4]) m4_include([m4/lib-prefix.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/nls.m4]) m4_include([m4/po.m4]) m4_include([m4/progtest.m4]) m4_include([acinclude.m4]) sane-backends-1.0.27/README.windows0000664000175000017500000000346412617742237013615 00000000000000SANE on Windows Prerequisites ============= To be able to compile sane-backends, you need to have either Cygwin or Mingw compilers and a suitable POSIX compatible environment. You can get the Cygwin POSIX compatible environment for Windows Windows and the Cygwin gcc compiler at http://www.cygwin.com You can get the MSYS POSIX compatible environment for Windows and the MinGW gcc compiler at http://www.mingw.org/wiki/MSYS The scanner must be detected by Windows and not be disabled. Check with the hardware manager. Building ======== See general README for build basics. If a given backend fails to compile, you can use the BACKENDS variable to limit compilation to backends your interested in: ./configure BACKENDS=epson2 Configuring =========== If you have more than one scanner, you should do the following: - run sane-find-scanner to get the device name of the scanner. The name for scsi devices is something like h0b0t6l0, meaning hba 0, bus 0, scsi id 6 and lun 0. - edit the config file for the backend (/path/to/sane/etc/sane.d/xxxx.conf) and add the scanner device name on an empty line. - Set environment variable SANE_CONFIG_DIR to point to the directory where the config files are located. Run "scanimage > out.pnm" to get a scan. xscanimage ans XSane have been reported to compile and run in the past under Cygwin. Notes ===== - Only SCSI, USB (with libusb-win32), and network scanners may work. No FireWire/Parallel. The Cygwin libusb port can be installed with Cygwin setup.exe or can be compiled manually under cygwin or mingw using the libusb-win32 port: http://sourceforge.net/apps/trac/libusb-win32/wiki - Tested on Windows XP, 7, and using Wine on Linux. - Some scanners' backend may not work because of requirement not supported by Cygwin or MinGW. 2011/10/08 sane-backends-1.0.27/depcomp0000775000175000017500000005601612775312261012615 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sane-backends-1.0.27/README0000664000175000017500000001623612775312260012117 00000000000000How to configure, build, and install SANE. Introduction: ============= SANE stands for Scanner Access Now Easy. This package contains the SANE libraries (this means backends and network scanning parts) and the command line frontend scanimage. You always find the most recent version of SANE on: http://www.sane-project.org/ At the same location there are also links to snapshots of the Git server and sometimes beta releases of sane-backends. These are unstable development versions, so be careful when using them. Please report any problems to us. See contact section for details. There are several graphical frontends available for SANE, see the list at http://www.sane-project.org/sane-frontends.html. Quick install: ============== ./configure make make install man sane Prerequisites ============= In order to build SANE, the following tools and libraries are required: - GNU make: version 3.70 or newer - ISO C99 compiler: GNU C (gcc) is recommended for best results, but any ISO C99 compliant compiler should do Some more libraries are not strictly necessary to compile SANE, but some functionality may be lost if they are not available. Make sure that these libraries and their respective header files are available before running configure. On some Linux distributions the header files are part of separate packages (e.g. usb.h in libusb-devel or libusb-dev). These must also be installed. - libusb: Strongly recommended if you use a USB scanner. Some backends won't work without libusb at all. - libjpeg (>=6B): For the dc210, dc240, and gphoto2 backends. - libieee1284 (>=0.1.5): For some parallel port backends. - libgphoto2 (>=2.0): For the gphoto2 backend. SANE should build on most Unix-like systems. Support for OS/2, MacOS X, BeOS, and Microsoft Windows is also available. For more details look at the operating system specific README.* files. For a detailed support matrix, see: http://www.sane-project.org/sane-support.html This table may be out of date. Please tell us about any corrections or additions. Please mention your operating system and platform and all the other details mentioned in the table. See also the contact section. Please check that there aren't any older versions of SANE installed on your system. Especially if SANE libraries are installed in a different prefix directory (e.g. /usr/lib/) this may cause problems with external frontends. Please remove these libraries (libsane.*, sane/libsane-*) by using your packet manager or manually before installing this version of SANE. Configuration ============= Simply invoke configure in the top-level directory. Besides the usual GNU configure options, there are the following SANE specific options: --disable-shared Don't use shared libraries. Useful for debugging or when there is a problem building shared libraries. This implicitly turns on --disable-dynamic --enable-static as well. --disable-dynamic Disable dynamic loading of backends (in the dll backend). configure normally turns on dynamic loading when it can find the appropriate header files and libraries ( and -ldl). --enable-static Use static libraries (turned off by default). --enable-preload Preload backends into DLL backend. This is useful for debugging, when dynamic loading is unavailable, to reduce runtime linking overheads, or when you only want to distribute a single DLL with all backends available. If dynamic loading or shared libraries are unavailable or disabled, this option is turned on automatically. --enable-scsibuffersize=N Specify the buffer size of the buffer for SCSI commands. The default value is 131072 bytes (128 kb). This may be changed at runtime by setting the environment variable SANE_SG_BUFFERSIZE to the desired value. The option is Linux-only at this time. --enable-scsibuffersize and SANE_SG_BUFFERSIZE have no effect for the Mustek, Umax and Sharp backends. For these backends, the buffer size is set automatically and/or can be specified in the backend's configuration file. Please refer to the backend's man pages for details. --enable-locking Means, that some backends will use a lockfile for allowing multiple access to one scanner. This is useful, i.e. one frontend is scanning the button status and another one will scan. The path to the lock files is define by --localstatedir at the configure step and is $localstatedir/lock/sane. The default group is uucp and can be changed by using --with-group=newgroup. If you do not want any backend to use a lockfile, simply use --disable-locking. To limit the backends that are compiled, set the variable BACKENDS to the list of backends to compile. The following will limit compiling to the epson2 and fujitsu backends: ./configure BACKENDS="epson2 fujitsu" To limit the backends that are preloaded into the DLL, set the variable PRELOADABLE_BACKENDS. The following will limit compiling to the epson2 and fujitsu backends but only preloads the epson2 backend: ./configure BACKENDS="epson2 futjisu" PRELOADABLE_BACKENDS="epson2" In addition to these configuration options, there are some more SANE-specific options and many standard-options. To get a description of available options, invoke configure with option --help. If you plan on debugging one of the SANE programs, we recommend to run configure like this: CFLAGS="-g -O -Wall" ./configure --disable-shared For operating system specific information, look at the README.* files. Build ===== To build SANE, simply type "make" in the top-level directory. To clean up the executables and libraries in the source directory, type "make clean". To restore everything to the status after unpacking the package, type "make distclean". Installation and Configuration ============================== Once the build has finished, install SANE with "make install". By default, this will place the SANE libraries in /usr/local/lib/, the configuration files in /usr/local/etc/sane.d/, and the manual pages in /usr/local/man/. The location of these directories can be overridden with configure options; see "configure --help" for details. Before running any SANE program, read the PROBLEMS file in this directory. For information on configuring and trouble-shooting the various SANE components, please refer to the manual page sane(7). The tools/ directory contains some small programs that may be helpful. They are described in tools/README. Removing ======== Type "make uninstall" to remove SANE from your system. This will also remove older versions of SANE if they have been installed at the same prefix. Warning: Your configuration files will be deleted also so make sure you have a backup. By default the configuration files are located in the directory /usr/local/etc/sane.d/. Contact ======= For questions and general discussion about SANE contact the sane-devel mailing list. You must be subscribed to the list to send mail. See http://www.sane-project.org/mailing-lists.html for details. If you want to submit a bug report or feature request please use our bug tracking system. See http://www.sane-project.org/bugs.html for details. You may also contact the author of a specific backend directly. See the AUTHORS file for a list of addresses. sane-backends-1.0.27/config.guess0000775000175000017500000012573113110434403013544 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2017 Free Software Foundation, Inc. timestamp='2017-05-11' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || \ echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; k1om:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; mips64el:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac cat >&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: sane-backends-1.0.27/test-driver0000775000175000017500000001027712775312262013436 00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2013 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then estatus=1 fi case $estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sane-backends-1.0.27/japi/0000775000175000017500000000000013110600540012213 500000000000000sane-backends-1.0.27/japi/ScanIt.java0000664000175000017500000002357312112021330014164 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** ** ScanIt.java - Do the actual scanning for SANE. ** ** Written: 11/3/97 - JSF **/ import java.util.Vector; import java.util.Enumeration; import java.awt.image.ImageProducer; import java.awt.image.ImageConsumer; import java.awt.image.ColorModel; import java.io.OutputStream; import java.io.PrintWriter; import java.io.BufferedWriter; import java.io.IOException; /* * This class uses SANE to scan an image. */ public class ScanIt implements ImageProducer { // # lines we incr. image height. private static final int STRIP_HEIGHT = 256; private Sane sane; private int handle = 0; // SANE device handle. private Vector consumers = new Vector(); // File to write to. private OutputStream outputFile = null; private SaneParameters parms = new SaneParameters(); private ColorModel cm; // RGB color model. private int width, height; // Dimensions. private int x, y; // Position. private int image[] = null; // Image that we build as we scan. private int offset; // Offset within image in pixels if // doing separate frames, bytes // (3/word) if RBG. /* * Tell consumers our status. The scan is also terminated de- * pending on the status. */ private void tellStatus(int s) { Enumeration next = consumers.elements(); while (next.hasMoreElements()) { ImageConsumer ic = (ImageConsumer) next.nextElement(); ic.imageComplete(s); } // Done? Stop scan. if (s == ImageConsumer.STATICIMAGEDONE || s == ImageConsumer.IMAGEERROR) sane.cancel(handle); } /* * Tell consumers the image size. */ private void tellDimensions(int w, int h) { System.out.println("tellDimensions: " + w + ", " + h); Enumeration next = consumers.elements(); while (next.hasMoreElements()) { ImageConsumer ic = (ImageConsumer) next.nextElement(); ic.setDimensions(w, h); } } /* * Send pixels to the clients. */ private void tellPixels(int x, int y, int w, int h) { /* System.out.println("image length=" + image.length); System.out.println("width=" + width); System.out.println("tellPixels: x="+x +" y="+y + " w="+w + " h="+h); */ Enumeration next = consumers.elements(); while (next.hasMoreElements()) { ImageConsumer ic = (ImageConsumer) next.nextElement(); ic.setPixels(x, y, w, h, cm, image, 0, width); } } /* * Construct. */ public ScanIt(Sane s, int hndl) { sane = s; handle = hndl; } /* * Add a consumer. */ public synchronized void addConsumer(ImageConsumer ic) { if (consumers.contains(ic)) return; // Already here. consumers.addElement(ic); } /* * Is a consumer in the list? */ public synchronized boolean isConsumer(ImageConsumer ic) { return consumers.contains(ic); } /* * Remove consumer. */ public synchronized void removeConsumer(ImageConsumer ic) { consumers.removeElement(ic); } /* * Add a consumer and start scanning. */ public void startProduction(ImageConsumer ic) { System.out.println("In startProduction()"); addConsumer(ic); scan(); } /* * Set file to write to. */ public void setOutputFile(OutputStream o) { outputFile = o; } /* * Ignore this: */ public void requestTopDownLeftRightResend(ImageConsumer ic) { } /* * Go to next line in image, reallocating if necessary. */ private void nextLine() { x = 0; ++y; if (y >= height || image == null) { // Got to reallocate. int oldSize = image == null ? 0 : width*height; height += STRIP_HEIGHT; // Add more lines. int newSize = width*height; int[] newImage = new int[newSize]; int i; if (oldSize != 0) // Copy old data. for (i = 0; i < oldSize; i++) newImage[i] = image[i]; // Fill new pixels with 0's, setting // alpha channel. for (i = oldSize; i < newSize; i++) newImage[i] = (255 << 24); image = newImage; System.out.println("nextLine: newSize="+newSize); // Tell clients. tellDimensions(width, height); } } /* * Process a buffer of data. */ private boolean process(byte[] data, int readLen) { int prevY = y > 0 ? y : 0; // Save current Y-coord. int i; switch (parms.format) { case SaneParameters.FRAME_RED: case SaneParameters.FRAME_GREEN: case SaneParameters.FRAME_BLUE: System.out.println("Process RED, GREEN or BLUE"); int cindex = 2 - (parms.format - SaneParameters.FRAME_RED); // Single frame. for (i = 0; i < readLen; ++i) { // Doing a single color frame. image[offset + i] |= (((int) data[i]) & 0xff) << (8*cindex); ++x; if (x >= width) nextLine(); } break; case SaneParameters.FRAME_RGB: for (i = 0; i < readLen; ++i) { int b = 2 - (offset + i)%3; image[(offset + i)/3] |= (((int) data[i]) & 0xff) << (8*b); if (b == 0) { ++x; if (x >= width) nextLine(); } } break; case SaneParameters.FRAME_GRAY: System.out.println("Process GREY"); // Single frame. for (i = 0; i < readLen; ++i) { int v = ((int) data[i]) & 0xff; image[offset + i] |= (v<<16) | (v<<8) | (v); ++x; if (x >= width) nextLine(); } break; } offset += readLen; // Update where we are. // Show it. System.out.println("PrevY = " + prevY + ", y = " + y); // tellPixels(0, prevY, width, y - prevY); tellPixels(0, 0, width, height); return true; } /* * Start scanning. */ public void scan() { int dataLen = 32*1024; byte [] data = new byte[dataLen]; int [] readLen = new int[1]; int frameCnt = 0; // For now, use default RGB model. cm = ColorModel.getRGBdefault(); int status; image = null; do // Do each frame. { frameCnt++; x = 0; // Init. position. y = -1; offset = 0; System.out.println("Reading frame #" + frameCnt); status = sane.start(handle); if (status != Sane.STATUS_GOOD) { System.out.println("start() failed. Status= " + status); tellStatus(ImageConsumer.IMAGEERROR); return; } status = sane.getParameters(handle, parms); if (status != Sane.STATUS_GOOD) { System.out.println("getParameters() failed. Status= " + status); tellStatus(ImageConsumer.IMAGEERROR); return; //++++cleanup. } if (frameCnt == 1) // First time? { width = parms.pixelsPerLine; if (parms.lines >= 0) height = parms.lines - STRIP_HEIGHT + 1; else // Hand-scanner. height = 0; nextLine(); // Allocate image. } while ((status = sane.read(handle, data, dataLen, readLen)) == Sane.STATUS_GOOD) { System.out.println("Read " + readLen[0] + " bytes."); if (!process(data, readLen[0])) { tellStatus(ImageConsumer.IMAGEERROR); return; } } if (status != Sane.STATUS_EOF) { System.out.println("read() failed. Status= " + status); tellStatus(ImageConsumer.IMAGEERROR); return; } } while (!parms.lastFrame); height = y; // For now, send whole image here. tellDimensions(width, height); tellPixels(0, 0, width, height); if (outputFile != null) // Write to file. { try { write(outputFile); } catch (IOException e) { //+++++++++++++++ System.out.println("I/O error writing file."); } outputFile = null; // Clear for next time. } tellStatus(ImageConsumer.STATICIMAGEDONE); image = null; // Allow buffer to be freed. } /* * Write ppm/pnm output for last scan to a file. */ private void write(OutputStream out) throws IOException { PrintWriter pout = new PrintWriter(out); BufferedWriter bout = new BufferedWriter(pout); int len = width*height; // Get # of pixels. int i; switch (parms.format) { case SaneParameters.FRAME_RED: case SaneParameters.FRAME_GREEN: case SaneParameters.FRAME_BLUE: case SaneParameters.FRAME_RGB: pout.print("P6\n# SANE data follows\n" + width + ' ' + height + "\n255\n"); for (i = 0; i < len; i++) { int pix = image[i]; bout.write((pix >> 16) & 0xff); bout.write((pix >> 8) & 0xff); bout.write(pix & 0xff); } break; case SaneParameters.FRAME_GRAY: pout.print("P5\n# SANE data follows\n" + width + ' ' + height + "\n255\n"); for (i = 0; i < len; i++) { int pix = image[i]; bout.write(pix & 0xff); } break; } bout.flush(); // Flush output. pout.flush(); } } sane-backends-1.0.27/japi/Sane.java0000664000175000017500000001213712112021330013663 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ // // Sane.java - Java version of SANE API. // // Written: 10/9/97 - JSF // public class Sane { // // Public constants: // public static int FIXED_SCALE_SHIFT = 16; // // Sane status values: // public static int STATUS_GOOD = 0; // everything A-OK public static int STATUS_UNSUPPORTED = 1;// operation is not supported public static int STATUS_CANCELLED = 2; // operation was cancelled public static int STATUS_DEVICE_BUSY = 3;// device is busy; try again later public static int STATUS_INVAL = 4; // data is invalid (includes no // dev at open) public static int STATUS_EOF = 5; // no more data available (end-of-file) public static int STATUS_JAMMED = 6; // document feeder jammed public static int STATUS_NO_DOCS = 7; // document feeder out of documents public static int STATUS_COVER_OPEN = 8;// scanner cover is open public static int STATUS_IO_ERROR = 9; // error during device I/O public static int STATUS_NO_MEM = 10; // out of memory // access to resource has been denied public static int STATUS_ACCESS_DENIED = 11; // // Initialize when class is loaded. // static { System.loadLibrary("sanej"); } // // Private methods: // // Get list of devices. private native int getDevicesNative( SaneDevice[] deviceList, boolean localOnly); // Get option descriptor. private native void getOptionNative(int handle, int option, SaneOption opt); // // Public methods: // public Sane() { } public int fix(double v) { return (int) ((v) * (1 << FIXED_SCALE_SHIFT)); } public double unfix(int v) { return (double)(v) / (1 << FIXED_SCALE_SHIFT); } public int versionMajor(int code) { return ((code) >> 24) & 0xff; } public int versionMinor(int code) { return ((code) >> 16) & 0xff; } public int versionBuild(int code) { return ((code) >> 0) & 0xffff; } // // SANE interface. // // Initialize, and return STATUS_ public native int init(int[] versionCode); public native void exit(); // All done. // Get list of devices. public int getDevices(SaneDevice[] deviceList, boolean localOnly) { // Create objects first. for (int i = 0; i < deviceList.length - 1; i++) deviceList[i] = new SaneDevice(); return getDevicesNative(deviceList, localOnly); } // Open a device. public native int open(String deviceName, int[] handle); // Close a device. public native void close(int handle); // Get option descriptor. public SaneOption getOptionDescriptor(int handle, int option) { SaneOption opt = new SaneOption(); opt.name = null; getOptionNative(handle, option, opt); if (opt.name == null) // Error? return (null); return (opt); } // Get each type of option: public native int getControlOption(int handle, int option, int [] value, int [] info); public native int getControlOption(int handle, int option, byte [] value, int [] info); // Set each type of option (SET_VALUE or // SET_AUTO): public native int setControlOption(int handle, int option, int action, int value, int [] info); public native int setControlOption(int handle, int option, int action, String value, int [] info); public native int getParameters(int handle, SaneParameters params); public native int start(int handle); public native int read(int handle, byte [] data, int maxLength, int [] length); public native void cancel(int handle); public native String strstatus(int status); } sane-backends-1.0.27/japi/ImageCanvasClient.java0000664000175000017500000000415212112021330016310 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** ** ImageCanvasClient.java - A client of the canvas that displays an image. ** ** Written: 11/20/97 - JSF **/ /* * This interface lets its owner know when an image canvas is through * being painted. */ interface ImageCanvasClient { void imageDone(boolean failed); // Image is complete. } sane-backends-1.0.27/japi/SaneDevice.java0000664000175000017500000000414412112021330015002 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ // // SaneDevice.java - Device Descriptor. // // Written: 10/9/97 - JSF // public class SaneDevice { public String name; // unique device name public String vendor; // device vendor string public String model; // device model name public String type; // device type (e.g., "flatbed scanner") } sane-backends-1.0.27/japi/SaneOption.java0000664000175000017500000001206212112021330015051 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ // // SaneOption.java - Sane option descriptor. // // Written: 10/9/97 - JSF // public class SaneOption { // // Sane option types: // public static final int TYPE_BOOL = 0; public static final int TYPE_INT = 1; public static final int TYPE_FIXED = 2; public static final int TYPE_STRING = 3; public static final int TYPE_BUTTON = 4; public static final int TYPE_GROUP = 5; // // Sane value units: // public static final int UNIT_NONE = 0; // the value is unit-less // (e.g., # of scans) public static final int UNIT_PIXEL = 1; // value is number of pixels public static final int UNIT_BIT = 2; // value is number of bits public static final int UNIT_MM = 3; // value is millimeters public static final int UNIT_DPI = 4; // value is res. in dots/inch public static final int UNIT_PERCENT = 5;// value is a percentage // // Option capabilities: // public static final int CAP_SOFT_SELECT = (1 << 0); public static final int CAP_HARD_SELECT = (1 << 1); public static final int CAP_SOFT_DETECT = (1 << 2); public static final int CAP_EMULATED = (1 << 3); public static final int CAP_AUTOMATIC = (1 << 4); public static final int CAP_INACTIVE = (1 << 5); public static final int CAP_ADVANCED = (1 << 6); // // Constraints: // public static final int CONSTRAINT_NONE = 0; public static final int CONSTRAINT_RANGE = 1; public static final int CONSTRAINT_WORD_LIST = 2; public static final int CONSTRAINT_STRING_LIST = 3; // // Actions for controlOption(): // public static final int ACTION_GET_VALUE = 0; public static final int ACTION_SET_VALUE = 1; public static final int ACTION_SET_AUTO = 2; // // Flags passed back in 'info' field param. of // setControlOption(): // public static final int INFO_INEXACT = (1 << 0); public static final int INFO_RELOAD_OPTIONS = (1 << 1); public static final int INFO_RELOAD_PARAMS = (1 << 2); // // Class members: // public String name; // name of this option (command-line name) public String title; // title of this option (single-line) public String desc; // description of this option (multi-line) public int type; // how are values interpreted? (TYPE_) public int unit; // what is the (physical) unit? (UNIT_) public int size; public int cap; // capabilities public int constraintType; // These are a union in the "C" API: // Null-terminated list: public String[] stringListConstraint; // First element is list-length: public int[] wordListConstraint; public SaneRange rangeConstraint; // // Public methods: // public boolean is_active() { return ((cap) & CAP_INACTIVE) == 0; } public boolean is_settable() { return ((cap) & CAP_SOFT_SELECT) == 0; } // Return string describing units. // "unitLength" is # mm. preferred. public String unitString(double unitLength) { switch (unit) { case UNIT_NONE: return "none"; case UNIT_PIXEL: return "pixel"; case UNIT_BIT: return "bit"; case UNIT_DPI: return "dpi"; case UNIT_PERCENT: return "%"; case UNIT_MM: if (unitLength > 9.9 && unitLength < 10.1) return "cm"; else if (unitLength > 25.3 && unitLength < 25.5) return "in"; return "mm"; } return ""; } } sane-backends-1.0.27/japi/SaneRange.java0000664000175000017500000000404712112021330014641 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ // // SaneRange.java - Sane range info. // // Written: 10/9/97 - JSF // public class SaneRange { public int min; // minimum (element) value public int max; // maximum (element) value public int quant; // Quantization value (0 if none) } sane-backends-1.0.27/japi/SaneParameters.java0000664000175000017500000000466612112021330015717 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ // // SaneParameters.java - Sane parameters. // // Written: 10/14/97 - JSF // public class SaneParameters { // // Frame values: // public static final int FRAME_GRAY = 0; // band covering human visual range public static final int FRAME_RGB = 1; // pixel-interleaved // red/green/blue bands public static final int FRAME_RED = 2; // red band only public static final int FRAME_GREEN = 3;// green band only public static final int FRAME_BLUE = 4; // blue band only // // Class members: // public int format; public boolean lastFrame; public int bytesPerLine; public int pixelsPerLine; public int lines; public int depth; } sane-backends-1.0.27/japi/Makefile.in0000664000175000017500000005745613110564734014237 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # Makefile for a Java project with native methods. # VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = japi DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp \ $(dist_noinst_JAVA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libsanej_la_DEPENDENCIES = $(LIBSANE) am_libsanej_la_OBJECTS = Sane.lo nodist_libsanej_la_OBJECTS = libsanej_la_OBJECTS = $(am_libsanej_la_OBJECTS) \ $(nodist_libsanej_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libsanej_la_SOURCES) $(nodist_libsanej_la_SOURCES) DIST_SOURCES = $(libsanej_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac JAVAC = javac CLASSPATH_ENV = CLASSPATH=$(JAVAROOT):$(srcdir)/$(JAVAROOT)$${CLASSPATH:+":$$CLASSPATH"} am__java_sources = $(dist_noinst_JAVA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ # We'll need something in 'configure' for the Java includes. AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include -I${JDK_HOME}/include \ -I${JDK_HOME}/include/genunix AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ $(STRICT_LDFLAGS) -version-number \ $(V_MAJOR):$(V_MINOR):$(V_REV) AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ JAVAROOT = . MY_CLASSPATH = . JAVAH = javah -jni -cp $(MY_CLASSPATH) JAVA_SRC = SaneDevice.java SaneOption.java SaneRange.java\ Sane.java SaneParameters.java ScanIt.java \ ImageCanvas.java ImageCanvasClient.java \ Test.java Jscanimage.java dist_noinst_JAVA = $(JAVA_SRC) LIBSANE = ../backend/libsane.la EXTRA_DIST = README.JAVA lib_LTLIBRARIES = libsanej.la BUILT_SOURCES = Sane.h CLEANFILES = Sane.h nodist_libsanej_la_SOURCES = Sane.h libsanej_la_SOURCES = Sane.c libsanej_la_LIBADD = $(LIBSANE) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu japi/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu japi/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libsanej.la: $(libsanej_la_OBJECTS) $(libsanej_la_DEPENDENCIES) $(EXTRA_libsanej_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libsanej_la_OBJECTS) $(libsanej_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Sane.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs classnoinst.stamp: $(am__java_sources) @list1='$?'; list2=; if test -n "$$list1"; then \ for p in $$list1; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ list2="$$list2 $$d$$p"; \ done; \ echo '$(CLASSPATH_ENV) $(JAVAC) -d $(JAVAROOT) $(AM_JAVACFLAGS) $(JAVACFLAGS) '"$$list2"; \ $(CLASSPATH_ENV) $(JAVAC) -d $(JAVAROOT) $(AM_JAVACFLAGS) $(JAVACFLAGS) $$list2; \ else :; fi echo timestamp > $@ clean-noinstJAVA: -rm -f *.class classnoinst.stamp ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) classnoinst.stamp installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstJAVA mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstJAVA \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-libLTLIBRARIES # Make sure that java classes get created before create Sane.h Sane.h: classdist_noinst.stamp $(JAVAH) Sane # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/japi/README.JAVA0000664000175000017500000000366612112021330013541 00000000000000-- 12/17/97 Most of Jscanimage's main dialog is coded, but only tested with PNM (which means most of the newly supported option types haven't been tried yet). Scanning (with PNM) does seem to work, although large files definitely take longer in JAVA then with "xscanimage". Main things left to do: 1. Provide the "preview" dialog. 2. Try it out with a real scanner, especially with large images. 3. Try it on a platform other than Linux. -- 11/18/97 This snapshot contains a partially functional "Jscanimage", which is intended to be a Java clone of "xscanimage". Only some of the controls are implemented (sliders, check-boxes, text-entry), and I've only tested it using small images with the "pnm" backend; but, it does seem to be functional, and to output .pnm files. There are also some small changes to the Java API. To do (at the least): 1. Handle "word list" controls. 2. Handle "browse" button for file selection. 3. Provide pull-down menus for choosing length units, and use them. 4. Provide the "preview" dialog. 5. Try it out with a real scanner, especially with large images. 6. Try it on a platform other than Linux. -- Jeff -- 10/17/97 NOTE: To build the Java interface, you have to cd into this directory and type "make" (after running configure in the top-level directory). --david -- This is my first pass at creating a Java API for SANE. It requires JDK 1.1.x, as it uses the new JNI for creating native methods. This is definitely not 100% pure Java, as it's really just a set of wrappers which call the actual SANE backend routines. It's also very preliminary, so feel free to suggest changes to the interface or class definitions. The 'install' installs the shared library (libsanej.*), but I'm not sure yet what to do with the generated Java class files. So for now, you should be able to run the test program after installation by typing "java Test" within the "japi" directory. -- Jeff Freedman (jsf@hevanet.com) sane-backends-1.0.27/japi/Jscanimage.java0000664000175000017500000007224512112021330015044 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** ** Jscanimage.java - Java scanner program using SANE. ** ** Written: 10/31/97 - JSF **/ import java.awt.*; import java.awt.event.*; import java.util.*; import java.awt.image.ImageConsumer; import java.awt.image.ColorModel; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.NumberFormat; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; /* * Main program. */ public class Jscanimage extends Frame implements WindowListener, ActionListener, ItemListener, ImageCanvasClient { // // Static data. // private static Sane sane; // The main class. private static SaneDevice devList[];// List of devices. // // Instance data. // private Font font; // For dialog items. private int saneHandle; // Handle of open device. private ScanIt scanIt = null; // Does the actual scan. // File to output to. private FileOutputStream outFile = null; private String outDir = null; // Stores dir. for output dialog. private Vector controls; // Dialog components for SANE controls. private double unitLength = 1; // # of mm for units to display // (mm = 1, cm = 10, in = 25.4). private ImageCanvas imageDisplay = null; // "Scan", "Preview" buttons. private JButton scanButton, previewButton; private JButton browseButton; // For choosing output filename. private JTextField outputField; // Field for output filename. private MenuItem exitMenuItem; // Menu items. private CheckboxMenuItem toolTipsMenuItem; private CheckboxMenuItem mmMenuItem; private CheckboxMenuItem cmMenuItem; private CheckboxMenuItem inMenuItem; /* * Main program. */ public static void main(String args[]) { if (!initSane()) // Initialize SANE. return; Jscanimage prog = new Jscanimage(); prog.pack(); prog.show(); } /* * Create main window. */ public Jscanimage() { super("SANE Scanimage"); addWindowListener(this); // Open SANE device. saneHandle = initSaneDevice(devList[0].name); if (saneHandle == 0) System.exit(-1); // Create scanner class. scanIt = new ScanIt(sane, saneHandle); init(); } /* * Clean up. */ public void finalize() { if (sane != null) { if (saneHandle != 0) sane.close(saneHandle); sane.exit(); sane = null; } saneHandle = 0; if (outFile != null) { try { outFile.close(); } catch (IOException e) { } outFile = null; } System.out.println("In finalize()"); } /* * Return info. */ public Sane getSane() { return sane; } public int getSaneHandle() { return saneHandle; } public double getUnitLength() { return unitLength; } /* * Initialize SANE. */ private static boolean initSane() { sane = new Sane(); int version[] = new int[1]; // Array to get version #. int status = sane.init(version); if (status != Sane.STATUS_GOOD) { System.out.println("getDevices() failed. Status= " + status); return (false); } // Get list of devices. // Allocate room for 50. devList = new SaneDevice[50]; status = sane.getDevices(devList, false); if (status != Sane.STATUS_GOOD) { System.out.println("getDevices() failed. Status= " + status); return (false); } for (int i = 0; i < 50 && devList[i] != null; i++) { System.out.println("Device '" + devList[i].name + "' is a " + devList[i].vendor + " " + devList[i].model + " " + devList[i].type); } return (true); } /* * Open device. * * Output: Handle, or 0 if error. */ private int initSaneDevice(String name) { int handle[] = new int[1]; // Open 1st device, for now. int status = sane.open(name, handle); if (status != Sane.STATUS_GOOD) { System.out.println("open() failed. Status= " + status); return (0); } setTitle("SANE - " + name); System.out.println("Open handle=" + handle[0]); return (handle[0]); } /* * Add a labeled option to the main dialog. */ private void addLabeledOption(JPanel group, String title, Component opt, GridBagConstraints c) { JLabel label = new JLabel(title); c.gridwidth = GridBagConstraints.RELATIVE; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; c.weightx = .1; group.add(label, c); c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = .4; group.add(opt, c); } /* * Get options for device. */ private boolean initSaneOptions() { JPanel group = null; GridBagConstraints c = new GridBagConstraints(); c.weightx = .4; c.weighty = .4; // Get # of device options. int numDevOptions[] = new int[1]; int status = sane.getControlOption(saneHandle, 0, numDevOptions, null); if (status != Sane.STATUS_GOOD) { System.out.println("controlOption() failed. Status= " + status); return (false); } System.out.println("Number of device options=" + numDevOptions[0]); // Do each option. for (int i = 0; i < numDevOptions[0]; i++) { SaneOption opt = sane.getOptionDescriptor(saneHandle, i); if (opt == null) { System.out.println("getOptionDescriptor() failed for " + i); continue; } /* System.out.println("Option title: " + opt.title); System.out.println("Option desc: " + opt.desc); System.out.println("Option type: " + opt.type); */ String title; // Set up title. if (opt.unit == SaneOption.UNIT_NONE) title = opt.title; else // Show units. title = opt.title + " [" + opt.unitString(unitLength) + ']'; switch (opt.type) { case SaneOption.TYPE_GROUP: // Group for a set of options. group = new JPanel(new GridBagLayout()); c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; add(group, c); group.setBorder(new TitledBorder(title)); break; case SaneOption.TYPE_BOOL: // A checkbox. SaneCheckBox cbox = new SaneCheckBox(opt.title, this, i, opt.desc); c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; if (group != null) group.add(cbox, c); addControl(cbox); break; case SaneOption.TYPE_FIXED: // Fixed-point value. if (opt.size != 4) break; // Not sure about this. switch (opt.constraintType) { case SaneOption.CONSTRAINT_RANGE: // A scale. SaneSlider slider = new FixedSaneSlider( opt.rangeConstraint.min, opt.rangeConstraint.max, opt.unit == SaneOption.UNIT_MM, this, i, opt.desc); addLabeledOption(group, title, slider, c); addControl(slider); break; case SaneOption.CONSTRAINT_WORD_LIST: // Select from a list. SaneFixedBox list = new SaneFixedBox( this, i, opt.desc); addLabeledOption(group, title, list, c); addControl(list); break; } break; case SaneOption.TYPE_INT: // Integer value. if (opt.size != 4) break; // Not sure about this. switch (opt.constraintType) { case SaneOption.CONSTRAINT_RANGE: // A scale. SaneSlider slider = new SaneSlider( opt.rangeConstraint.min, opt.rangeConstraint.max, this, i, opt.desc); addLabeledOption(group, title, slider, c); addControl(slider); break; case SaneOption.CONSTRAINT_WORD_LIST: // Select from a list. SaneIntBox list = new SaneIntBox( this, i, opt.desc); addLabeledOption(group, title, list, c); addControl(list); break; } break; case SaneOption.TYPE_STRING: // Text entry or choice box. switch (opt.constraintType) { case SaneOption.CONSTRAINT_STRING_LIST: // Make a list. SaneStringBox list = new SaneStringBox( this, i, opt.desc); addLabeledOption(group, title, list, c); addControl(list); break; case SaneOption.CONSTRAINT_NONE: SaneTextField tfield = new SaneTextField(16, this, i, opt.desc); addLabeledOption(group, title, tfield, c); addControl(tfield); break; } break; case SaneOption.TYPE_BUTTON: c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.CENTER; c.insets = new Insets(8, 4, 4, 4); JButton btn = new SaneButton(title, this, i, opt.desc); group.add(btn, c); c.insets = null; break; default: break; } } return (true); } /* * Set up "Output" panel. */ private JPanel initOutputPanel() { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); // Want 1 row. c.gridx = GridBagConstraints.RELATIVE; c.gridy = 0; c.anchor = GridBagConstraints.WEST; // c.fill = GridBagConstraints.HORIZONTAL; c.weightx = .4; c.weighty = .4; panel.setBorder(new TitledBorder("Output")); panel.add(new Label("Filename"), c); outputField = new JTextField("out.pnm", 16); panel.add(outputField, c); c.insets = new Insets(0, 8, 0, 0); browseButton = new JButton("Browse"); browseButton.addActionListener(this); panel.add(browseButton, c); return (panel); } /* * Initialize main window. */ private void init() { controls = new Vector(); // List of SaneComponent's. // Try a light blue: setBackground(new Color(140, 200, 255)); // And a larger font. font = new Font("Helvetica", Font.PLAIN, 12); setFont(font); initMenu(); // Main panel will be 1 column. setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.BOTH; c.weightx = .4; c.weighty = .4; // Panel for output: JPanel outputPanel = initOutputPanel(); add(outputPanel, c); initSaneOptions(); // Get SANE options, set up dialog. initButtons(); // Put buttons at bottom. } /* * Add a control to the dialog and set its initial value. */ private void addControl(SaneComponent comp) { controls.addElement(comp); comp.setFromControl(); // Get initial value. } /* * Reinitialize components from SANE controls. */ private void reinit() { Enumeration ctrls = controls.elements(); while (ctrls.hasMoreElements()) // Do each control. { SaneComponent comp = (SaneComponent) ctrls.nextElement(); comp.setFromControl(); } } /* * Set up the menubar. */ private void initMenu() { MenuBar mbar = new MenuBar(); Menu file = new Menu("File"); mbar.add(file); exitMenuItem = new MenuItem("Exit"); exitMenuItem.addActionListener(this); file.add(exitMenuItem); Menu pref = new Menu("Preferences"); mbar.add(pref); toolTipsMenuItem = new CheckboxMenuItem("Show tooltips", true); toolTipsMenuItem.addItemListener(this); pref.add(toolTipsMenuItem); Menu units = new Menu("Length unit"); pref.add(units); mmMenuItem = new CheckboxMenuItem("millimeters", true); mmMenuItem.addItemListener(this); units.add(mmMenuItem); cmMenuItem = new CheckboxMenuItem("centimeters", false); cmMenuItem.addItemListener(this); units.add(cmMenuItem); inMenuItem = new CheckboxMenuItem("inches", false); inMenuItem.addItemListener(this); units.add(inMenuItem); setMenuBar(mbar); } /* * Set up buttons panel at very bottom. */ private void initButtons() { // Buttons are at bottom. JPanel bottomPanel = new JPanel(new GridBagLayout()); // Indent around buttons. GridBagConstraints c = new GridBagConstraints(); c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(8, 8, 8, 8); c.weightx = .4; c.weighty = .2; c.fill = GridBagConstraints.HORIZONTAL; add(bottomPanel, c); c.weighty = c.weightx = .4; c.fill = GridBagConstraints.BOTH; c.gridwidth = c.gridheight = 1; // Create image display box. imageDisplay = new ImageCanvas(); bottomPanel.add(imageDisplay, c); // Put btns. to right in 1 column. JPanel buttonsPanel = new JPanel(new GridLayout(0, 1, 8, 8)); bottomPanel.add(buttonsPanel, c); scanButton = new JButton("Scan"); buttonsPanel.add(scanButton); scanButton.addActionListener(this); previewButton = new JButton("Preview Window"); buttonsPanel.add(previewButton); previewButton.addActionListener(this); } /* * Set a SANE integer option. */ public void setControlOption(int optNum, int val) { int [] info = new int[1]; if (sane.setControlOption(saneHandle, optNum, SaneOption.ACTION_SET_VALUE, val, info) != Sane.STATUS_GOOD) System.out.println("setControlOption() failed."); checkOptionInfo(info[0]); } /* * Set a SANE text option. */ public void setControlOption(int optNum, String val) { int [] info = new int[1]; if (sane.setControlOption(saneHandle, optNum, SaneOption.ACTION_SET_VALUE, val, info) != Sane.STATUS_GOOD) System.out.println("setControlOption() failed."); checkOptionInfo(info[0]); } /* * Check the 'info' word returned from setControlOption(). */ private void checkOptionInfo(int info) { // Does everything completely change? if ((info & SaneOption.INFO_RELOAD_OPTIONS) != 0) reinit(); // Need to update status line? if ((info & SaneOption.INFO_RELOAD_PARAMS) != 0) ; // ++++++++FILL IN. } /* * Handle a user action. */ public void actionPerformed(ActionEvent e) { if (e.getSource() == scanButton) { System.out.println("Rescanning"); // Get file name. String fname = outputField.getText(); if (fname == null || fname.length() == 0) fname = "out.pnm"; try { outFile = new FileOutputStream(fname); } catch (IOException oe) { System.out.println("Error creating file: " + fname); outFile = null; return; } // Disable "Scan" button. scanButton.setEnabled(false); scanIt.setOutputFile(outFile); imageDisplay.setImage(scanIt, this); } else if (e.getSource() == browseButton) { File file; // For working with names. FileDialog dlg = new FileDialog(this, "Output Filename", FileDialog.SAVE); if (outDir != null) // Set to last directory. dlg.setDirectory(outDir); // Get current name. String fname = outputField.getText(); if (fname != null) { file = new File(fname); dlg.setFile(file.getName()); String dname = file.getParent(); if (dname != null) dlg.setDirectory(outDir); } dlg.show(); // Wait for result. fname = dlg.getFile(); // Store dir. for next time. outDir = dlg.getDirectory(); if (fname != null) { file = new File(outDir, fname); String curDir; String fullName; try { curDir = (new File(".")).getCanonicalPath(); fullName = file.getCanonicalPath(); // Not in current directory? if (!curDir.equals( (new File(fullName)).getParent())) fname = fullName; } catch (IOException ex) { curDir = "."; fname = file.getName(); } outputField.setText(fname); } } else if (e.getSource() == exitMenuItem) { finalize(); // Just to be safe. System.exit(0); } } /* * Handle checkable menu items. */ public void itemStateChanged(ItemEvent e) { if (e.getSource() == mmMenuItem) { // Wants mm. unitLength = 1; if (e.getStateChange() == ItemEvent.SELECTED) { cmMenuItem.setState(false); inMenuItem.setState(false); reinit(); // Re-display controls. } else // Don't let him deselect. mmMenuItem.setState(true); } if (e.getSource() == cmMenuItem) { // Wants cm. unitLength = 10; if (e.getStateChange() == ItemEvent.SELECTED) { mmMenuItem.setState(false); inMenuItem.setState(false); reinit(); // Re-display controls. } else cmMenuItem.setState(true); } if (e.getSource() == inMenuItem) { // Wants inches. unitLength = 25.4; if (e.getStateChange() == ItemEvent.SELECTED) { mmMenuItem.setState(false); cmMenuItem.setState(false); reinit(); // Re-display controls. } else // Don't let him deselect. inMenuItem.setState(true); } } /* * Scan is complete. */ public void imageDone(boolean error) { if (error) System.out.println("Scanning error."); if (outFile != null) // Close file. try { outFile.close(); } catch (IOException e) { } scanButton.setEnabled(true); // Can scan again. } /* * Default window event handlers. */ public void windowClosed(WindowEvent event) { finalize(); // Just to be safe. } public void windowDeiconified(WindowEvent event) { } public void windowIconified(WindowEvent event) { } public void windowActivated(WindowEvent event) { } public void windowDeactivated(WindowEvent event) { } public void windowOpened(WindowEvent event) { } // Handle closing event. public void windowClosing(WindowEvent event) { finalize(); // Just to be safe. System.exit(0); } } /* * Interface for our dialog controls. */ interface SaneComponent { public void setFromControl(); // Ask SANE control for current value. } /* * A checkbox in our dialog. */ class SaneCheckBox extends JCheckBox implements ActionListener, SaneComponent { private Jscanimage dialog; // That which created us. private int optNum; // Option #. /* * Create with given state. */ public SaneCheckBox(String title, Jscanimage dlg, int opt, String tip) { super(title, false); dialog = dlg; optNum = opt; // Set tool tip. if (tip != null && tip.length() != 0) super.setToolTipText(tip); addActionListener(this); // Listen to ourself. } /* * Update Sane device option with current setting. */ public void actionPerformed(ActionEvent e) { System.out.println("In SaneCheckBox::actionPerformed()"); int val = isSelected() ? 1 : 0; dialog.setControlOption(optNum, val); } /* * Update from Sane control's value. */ public void setFromControl() { int [] val = new int[1]; if (dialog.getSane().getControlOption( dialog.getSaneHandle(), optNum, val, null) == Sane.STATUS_GOOD) setSelected(val[0] != 0); } } /* * A slider in our dialog. This base class handles integer ranges. * It consists of a slider and a label which shows the current value. */ class SaneSlider extends JPanel implements SaneComponent, ChangeListener { protected Jscanimage dialog; // That which created us. protected int optNum; // Option #. protected JSlider slider; // The slider itself. protected JLabel label; // Shows current value. /* * Create with given state. */ public SaneSlider(int min, int max, Jscanimage dlg, int opt, String tip) { super(new GridBagLayout()); // Create panel. dialog = dlg; optNum = opt; GridBagConstraints c = new GridBagConstraints(); // Want 1 row. c.gridx = GridBagConstraints.RELATIVE; c.gridy = 0; c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.HORIZONTAL; c.weighty = .8; c.weightx = .2; // Give less weight to value label. label = new JLabel("00", SwingConstants.RIGHT); add(label, c); c.weightx = .8; // Give most weight to slider. c.fill = GridBagConstraints.HORIZONTAL; slider = new JSlider(JSlider.HORIZONTAL, min, max, min + (max - min)/2); add(slider, c); // Set tool tip. if (tip != null && tip.length() != 0) super.setToolTipText(tip); slider.addChangeListener(this); // Listen to ourself. } /* * Update Sane device option. */ public void stateChanged(ChangeEvent e) { int val = slider.getValue(); label.setText(String.valueOf(val)); dialog.setControlOption(optNum, val); } /* * Update from Sane control's value. */ public void setFromControl() { int [] val = new int[1]; // Get current SANE control value. if (dialog.getSane().getControlOption( dialog.getSaneHandle(), optNum, val, null) == Sane.STATUS_GOOD) { slider.setValue(val[0]); label.setText(String.valueOf(val[0])); } } } /* * A slider with fixed-point values: */ class FixedSaneSlider extends SaneSlider { private static final int SCALE_MIN = -32000; private static final int SCALE_MAX = 32000; double min, max; // Min, max in floating-point. boolean optMM; // Option is in millimeters, so should // be scaled to user's pref. private NumberFormat format; // For printing label. /* * Create with given fixed-point range. */ public FixedSaneSlider(int fixed_min, int fixed_max, boolean mm, Jscanimage dlg, int opt, String tip) { // Create with large integer range. super(SCALE_MIN, SCALE_MAX, dlg, opt, tip); format = NumberFormat.getInstance(); // For now, show 1 decimal point. format.setMinimumFractionDigits(1); format.setMaximumFractionDigits(1); // Store actual range. min = dlg.getSane().unfix(fixed_min); max = dlg.getSane().unfix(fixed_max); optMM = mm; } /* * Update Sane device option. */ public void stateChanged(ChangeEvent e) { double val = (double) slider.getValue(); // Convert to actual control scale. val = min + ((val - SCALE_MIN)/(SCALE_MAX - SCALE_MIN)) * (max - min); label.setText(format.format(optMM ? val/dialog.getUnitLength() : val)); dialog.setControlOption(optNum, dialog.getSane().fix(val)); } /* * Update from Sane control's value. */ public void setFromControl() { int [] ival = new int[1]; // Get current SANE control value. if (dialog.getSane().getControlOption( dialog.getSaneHandle(), optNum, ival, null) == Sane.STATUS_GOOD) { double val = dialog.getSane().unfix(ival[0]); // Show value with user's pref. label.setText(format.format(optMM ? val/dialog.getUnitLength() : val)); val = SCALE_MIN + ((val - min)/(max - min)) * (SCALE_MAX - SCALE_MIN); slider.setValue((int) val); } } } /* * A Button in our dialog. */ class SaneButton extends JButton implements ActionListener { private Jscanimage dialog; // That which created us. private int optNum; // Option #. /* * Create with given state. */ public SaneButton(String title, Jscanimage dlg, int opt, String tip) { super(title); dialog = dlg; optNum = opt; // Set tool tip. if (tip != null && tip.length() != 0) super.setToolTipText(tip); addActionListener(this); // Listen to ourself. } /* * Update Sane device option. */ public void actionPerformed(ActionEvent e) { dialog.setControlOption(optNum, 0); System.out.println("In SaneButton::actionPerformed()"); } } /* * A combo-box for showing a list of items. */ abstract class SaneComboBox extends JComboBox implements SaneComponent, ItemListener { protected Jscanimage dialog; // That which created us. protected int optNum; // Option #. /* * Create it. */ public SaneComboBox(Jscanimage dlg, int opt, String tip) { dialog = dlg; optNum = opt; // Set tool tip. if (tip != null && tip.length() != 0) super.setToolTipText(tip); addItemListener(this); } /* * Select desired item by its text. */ protected void select(String text) { int cnt = getItemCount(); for (int i = 0; i < cnt; i++) if (text.equals(getItemAt(i))) { setSelectedIndex(i); break; } } abstract public void setFromControl(); abstract public void itemStateChanged(ItemEvent e); } /* * A list of strings. */ class SaneStringBox extends SaneComboBox { /* * Create it. */ public SaneStringBox(Jscanimage dlg, int opt, String tip) { super(dlg, opt, tip); } /* * Update from Sane control's value. */ public void setFromControl() { // Let's get the whole list. SaneOption opt = dialog.getSane().getOptionDescriptor( dialog.getSaneHandle(), optNum); if (opt == null) return; removeAllItems(); // Clear list. // Go through list from option. for (int i = 0; opt.stringListConstraint[i] != null; i++) addItem(opt.stringListConstraint[i]); // Get value. byte buf[] = new byte[opt.size + 1]; if (dialog.getSane().getControlOption( dialog.getSaneHandle(), optNum, buf, null) == Sane.STATUS_GOOD) select(new String(buf)); } /* * An item was selected. */ public void itemStateChanged(ItemEvent e) { // Get current selection. String val = (String) getSelectedItem(); if (val != null) dialog.setControlOption(optNum, val); } } /* * A list of integers. */ class SaneIntBox extends SaneComboBox { /* * Create it. */ public SaneIntBox(Jscanimage dlg, int opt, String tip) { super(dlg, opt, tip); } /* * Update from Sane control's value. */ public void setFromControl() { // Let's get the whole list. SaneOption opt = dialog.getSane().getOptionDescriptor( dialog.getSaneHandle(), optNum); if (opt == null) return; removeAllItems(); // Clear list. // Go through list from option. int cnt = opt.wordListConstraint[0]; for (int i = 0; i < cnt; i++) addItem(String.valueOf(opt.wordListConstraint[i + 1])); // Get value. int [] val = new int[1]; // Get current SANE control value. if (dialog.getSane().getControlOption( dialog.getSaneHandle(), optNum, val, null) == Sane.STATUS_GOOD) select(String.valueOf(val[0])); } /* * An item was selected. */ public void itemStateChanged(ItemEvent e) { // Get current selection. String val = (String) getSelectedItem(); if (val != null) try { Integer v = Integer.valueOf(val); dialog.setControlOption(optNum, v.intValue()); } catch (NumberFormatException ex) { } } } /* * A list of fixed-point floating point numbers. */ class SaneFixedBox extends SaneComboBox { /* * Create it. */ public SaneFixedBox(Jscanimage dlg, int opt, String tip) { super(dlg, opt, tip); } /* * Update from Sane control's value. */ public void setFromControl() { // Let's get the whole list. SaneOption opt = dialog.getSane().getOptionDescriptor( dialog.getSaneHandle(), optNum); if (opt == null) return; removeAllItems(); // Clear list. // Go through list from option. int cnt = opt.wordListConstraint[0]; for (int i = 0; i < cnt; i++) addItem(String.valueOf(dialog.getSane().unfix( opt.wordListConstraint[i + 1]))); // Get value. int [] val = new int[1]; // Get current SANE control value. if (dialog.getSane().getControlOption( dialog.getSaneHandle(), optNum, val, null) == Sane.STATUS_GOOD) select(String.valueOf(dialog.getSane().unfix(val[0]))); } /* * An item was selected. */ public void itemStateChanged(ItemEvent e) { // Get current selection. String val = (String) getSelectedItem(); if (val != null) try { Double v = Double.valueOf(val); dialog.setControlOption(optNum, dialog.getSane().fix(v.doubleValue())); } catch (NumberFormatException ex) { } } } /* * A text-entry field in our dialog. */ class SaneTextField extends JTextField implements SaneComponent { private Jscanimage dialog; // That which created us. private int optNum; // Option #. /* * Create with given state. */ public SaneTextField(int width, Jscanimage dlg, int opt, String tip) { super(width); // Set initial text, # chars. dialog = dlg; optNum = opt; // Set tool tip. if (tip != null && tip.length() != 0) super.setToolTipText(tip); } /* * Update Sane device option with current setting when user types. */ public void processKeyEvent(KeyEvent e) { super.processKeyEvent(e); // Handle it normally. if (e.getID() != KeyEvent.KEY_TYPED) return; // Just do it after keystroke. String userText = getText(); // Get what's there, & save copy. String newText = new String(userText); dialog.setControlOption(optNum, newText); if (!newText.equals(userText)) // Backend may have changed it. setText(newText); } /* * Update from Sane control's value. */ public void setFromControl() { byte buf[] = new byte[1024]; if (dialog.getSane().getControlOption( dialog.getSaneHandle(), optNum, buf, null) == Sane.STATUS_GOOD) { String text = new String(buf); System.out.println("SaneTextField::setFromControl: " + text); setText(text); // Set text in field. setScrollOffset(0); } } } sane-backends-1.0.27/japi/Sane.c0000664000175000017500000003604212112021330013165 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** ** Sane.c - Native methods for the SANE Java API. ** ** Written: 10/9/97 - JSF **/ #include "Sane.h" #include #include #include /* Debugging */ #ifdef __cplusplus extern "C" { #endif /* * Class: Sane * Method: init * Signature: ([I)I */ JNIEXPORT jint JNICALL Java_Sane_init (JNIEnv *env, jobject jobj, jintArray versionCode) { jsize len; /* Gets array length. */ jint *versionCodeBody; /* Gets ->array. */ SANE_Int version; /* Gets version. */ SANE_Status status; /* Get SANE return. */ status = sane_init(&version, 0); len = (*env)->GetArrayLength(env, versionCode); versionCodeBody = (*env)->GetIntArrayElements(env, versionCode, 0); if (len > 0) /* Return version. */ versionCodeBody[0] = version; (*env)->ReleaseIntArrayElements(env, versionCode, versionCodeBody, 0); return (status); } /* * Class: Sane * Method: exit * Signature: ()V */ JNIEXPORT void JNICALL Java_Sane_exit (JNIEnv *env, jobject jobj) { sane_exit(); } /* * Class: Sane * Method: getDevices * Signature: ([LSaneDevice;Z)I */ JNIEXPORT jint JNICALL Java_Sane_getDevicesNative (JNIEnv *env, jobject jobj, jobjectArray devList, jboolean localOnly) { /* Gets device list. */ const SANE_Device **device_list; SANE_Status status; /* Gets status. */ int devListLen; /* Gets length of devList. */ jobject devObj; /* Gets each SaneDevice object. */ jclass devClass; /* Gets SaneDevice class. */ jfieldID fid; /* Gets each field ID. */ int i; /* Get the list. */ status = sane_get_devices(&device_list, localOnly); if (status != SANE_STATUS_GOOD) return (status); /* Get length of Java array. */ devListLen = (*env)->GetArrayLength(env, devList); /* Return devices to user. */ for (i = 0; i < devListLen - 1 && device_list[i]; i++) { /* Get Java object, class. */ devObj = (*env)->GetObjectArrayElement(env, devList, i); devClass = (*env)->GetObjectClass(env, devObj); /* Fill in each member. */ fid = (*env)->GetFieldID(env, devClass, "name", "Ljava/lang/String;"); (*env)->SetObjectField(env, devObj, fid, (*env)->NewStringUTF(env, device_list[i]->name)); fid = (*env)->GetFieldID(env, devClass, "vendor", "Ljava/lang/String;"); (*env)->SetObjectField(env, devObj, fid, (*env)->NewStringUTF(env, device_list[i]->vendor)); fid = (*env)->GetFieldID(env, devClass, "model", "Ljava/lang/String;"); (*env)->SetObjectField(env, devObj, fid, (*env)->NewStringUTF(env, device_list[i]->model)); fid = (*env)->GetFieldID(env, devClass, "type", "Ljava/lang/String;"); (*env)->SetObjectField(env, devObj, fid, (*env)->NewStringUTF(env, device_list[i]->type)); } /* End list with a null. */ (*env)->SetObjectArrayElement(env, devList, i, 0); return (status); } /* * Class: Sane * Method: open * Signature: (Ljava/lang/String;[J)I */ JNIEXPORT jint JNICALL Java_Sane_open (JNIEnv *env, jobject jobj, jstring deviceName, jintArray handle) { SANE_Handle sane_handle; /* Gets handle. */ jint s_handle; const char *device_name; /* Gets dev. name. */ int status; /* Gets return code. */ device_name = (*env)->GetStringUTFChars(env, deviceName, 0); /* Open it. */ status = sane_open(device_name, &sane_handle); (*env)->ReleaseStringUTFChars(env, deviceName, device_name); /* Return handle. */ s_handle = (jint) sane_handle; (*env)->SetIntArrayRegion(env, handle, 0, 1, &s_handle); return (status); } /* * Class: Sane * Method: close * Signature: (J)V */ JNIEXPORT void JNICALL Java_Sane_close (JNIEnv *env, jobject jobj, jint handle) { sane_close((SANE_Handle) handle); } /* * Class: Sane * Method: getOptionNative * Signature: (IILSaneOption;)V */ JNIEXPORT void JNICALL Java_Sane_getOptionNative (JNIEnv *env, jobject jobj, jint handle, jint option, jobject optObj) { jclass optClass; /* Gets its class. */ jfieldID fid; /* Gets each field ID. */ jstring str; /* Gets strings. */ /* Get info from sane. */ const SANE_Option_Descriptor *sopt = sane_get_option_descriptor( (SANE_Handle) handle, option); /* Get class info. */ optClass = (*env)->GetObjectClass(env, optObj); /* Fill in each member. */ fid = (*env)->GetFieldID(env, optClass, "name", "Ljava/lang/String;"); if (!sopt) /* Failed. */ { /* Set name to null. */ (*env)->SetObjectField(env, optObj, fid, 0); return; } /* Return name. */ (*env)->SetObjectField(env, optObj, fid, (*env)->NewStringUTF(env, sopt->name)); /* Return title. */ fid = (*env)->GetFieldID(env, optClass, "title", "Ljava/lang/String;"); str = sopt->title ? (*env)->NewStringUTF(env, sopt->title) : 0; (*env)->SetObjectField(env, optObj, fid, str); /* Return descr. */ fid = (*env)->GetFieldID(env, optClass, "desc", "Ljava/lang/String;"); (*env)->SetObjectField(env, optObj, fid, (*env)->NewStringUTF(env, sopt->desc)); /* Return type. */ fid = (*env)->GetFieldID(env, optClass, "type", "I"); (*env)->SetIntField(env, optObj, fid, sopt->type); /* Return unit. */ fid = (*env)->GetFieldID(env, optClass, "unit", "I"); (*env)->SetIntField(env, optObj, fid, sopt->unit); /* Return size. */ fid = (*env)->GetFieldID(env, optClass, "size", "I"); (*env)->SetIntField(env, optObj, fid, sopt->size); /* Return cap. */ fid = (*env)->GetFieldID(env, optClass, "cap", "I"); (*env)->SetIntField(env, optObj, fid, sopt->cap); /* Return constraint_type. */ fid = (*env)->GetFieldID(env, optClass, "constraintType", "I"); (*env)->SetIntField(env, optObj, fid, sopt->constraint_type); /* * Now for the constraint itself. */ if (sopt->constraint_type == SANE_CONSTRAINT_RANGE) { /* Create range object. */ jclass rangeClass = (*env)->FindClass(env, "SaneRange"); jobject range = (*env)->AllocObject(env, rangeClass); /* Fill in fields. */ fid = (*env)->GetFieldID(env, rangeClass, "min", "I"); (*env)->SetIntField(env, range, fid, sopt->constraint.range->min); fid = (*env)->GetFieldID(env, rangeClass, "max", "I"); (*env)->SetIntField(env, range, fid, sopt->constraint.range->max); fid = (*env)->GetFieldID(env, rangeClass, "quant", "I"); (*env)->SetIntField(env, range, fid, sopt->constraint.range->quant); fid = (*env)->GetFieldID(env, optClass, "rangeConstraint", "LSaneRange;"); /* Store range. */ (*env)->SetObjectField(env, optObj, fid, range); } else if (sopt->constraint_type == SANE_CONSTRAINT_WORD_LIST) { /* Get array of integers. */ jintArray wordList; jint *elements; int i; /* First word. is the length. */ wordList = (*env)->NewIntArray(env, sopt->constraint.word_list[0]); /* Copy in the integers. */ elements = (*env)->GetIntArrayElements(env, wordList, 0); for (i = 0; i < sopt->constraint.word_list[0]; i++) elements[i] = sopt->constraint.word_list[i]; (*env)->ReleaseIntArrayElements(env, wordList, elements, 0); /* Set the field. */ fid = (*env)->GetFieldID(env, optClass, "wordListConstraint", "[I"); (*env)->SetObjectField(env, optObj, fid, wordList); } else if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) { jclass stringClass = (*env)->FindClass(env, "java/lang/String"); jobjectArray stringList; int len; /* Gets # elements */ int i; for (len = 0; sopt->constraint.string_list[len]; len++) ; stringList = (*env)->NewObjectArray(env, len + 1, stringClass, 0); /* Add each string. */ for (i = 0; i < len; i++) { (*env)->SetObjectArrayElement(env, stringList, i, (*env)->NewStringUTF(env, sopt->constraint.string_list[i])); } /* 0 at end. */ (*env)->SetObjectArrayElement(env, stringList, len, 0); /* Set the field. */ fid = (*env)->GetFieldID(env, optClass, "stringListConstraint", "[Ljava/lang/String;"); (*env)->SetObjectField(env, optObj, fid, stringList); } } /* * Class: Sane * Method: getControlOption * Signature: (II[I[I)I */ JNIEXPORT jint JNICALL Java_Sane_getControlOption__II_3I_3I (JNIEnv *env, jobject jobj, jint handle, jint option, jintArray value, jintArray info) { SANE_Status status; /* Gets status. */ SANE_Int i; /* Gets info. passed back. */ int v; status = sane_control_option((SANE_Handle) handle, option, SANE_ACTION_GET_VALUE, &v, &i); if (value) (*env)->SetIntArrayRegion(env, value, 0, 1, &v); if (info) (*env)->SetIntArrayRegion(env, info, 0, 1, &i); return (status); } /* * Class: Sane * Method: getControlOption * Signature: (II[B[I)I */ JNIEXPORT jint JNICALL Java_Sane_getControlOption__II_3B_3I (JNIEnv *env, jobject jobj, jint handle, jint option, jbyteArray value, jintArray info) { SANE_Status status; /* Gets status. */ SANE_Int i; /* Gets info. passed back. */ char *str; str = (*env)->GetByteArrayElements(env, value, 0); status = sane_control_option((SANE_Handle) handle, option, SANE_ACTION_GET_VALUE, str, &i); (*env)->ReleaseByteArrayElements(env, value, str, 0); if (info) (*env)->SetIntArrayRegion(env, info, 0, 1, &i); return (status); } /* * Class: Sane * Method: setControlOption * Signature: (IIII[I)I */ JNIEXPORT jint JNICALL Java_Sane_setControlOption__IIII_3I (JNIEnv *env, jobject jobj, jint handle, jint option, jint action, jint value, jintArray info) { SANE_Status status; /* Gets status. */ SANE_Int i; /* Gets info. passed back. */ status = sane_control_option((SANE_Handle) handle, option, action, &value, &i); if (info) (*env)->SetIntArrayRegion(env, info, 0, 1, &i); return (status); } /* * Get string length. This exists because sometimes strings seem to be * padded with negatives. */ static int String_length ( const char *str ) { const char *ptr; for (ptr = str; *ptr > 0; ptr++) ; return ((int) (ptr - str)); } /* * Class: Sane * Method: setControlOption * Signature: (IIILjava/lang/String;[I)I */ JNIEXPORT jint JNICALL Java_Sane_setControlOption__IIILjava_lang_String_2_3I (JNIEnv *env, jobject jobj, jint handle, jint option, jint action, jstring value, jintArray info) { SANE_Status status; /* Gets status. */ SANE_Int i; /* Gets info. passed back. */ const char *valuep; char buf[512]; /* Hope this is big enough. */ int len; /* Gets string length. */ valuep = (*env)->GetStringUTFChars(env, value, 0); len = String_length(valuep); if (len >= sizeof(buf)) len = sizeof(buf) - 1; strncpy(buf, valuep, len); buf[len] = 0; /* Insure it's 0-delimited. */ status = sane_control_option((SANE_Handle) handle, option, action, (void *) &buf[0], &i); /* +++++++Want to return new val? */ (*env)->ReleaseStringUTFChars(env, value, valuep); if (info) (*env)->SetIntArrayRegion(env, info, 0, 1, &i); return (status); } /* * Class: Sane * Method: getParameters * Signature: (ILSaneParameters;)I */ JNIEXPORT jint JNICALL Java_Sane_getParameters (JNIEnv *env, jobject jobj, jint handle, jobject paramsObj) { SANE_Status status; /* Gets status. */ SANE_Parameters params; /* Gets params. */ jclass paramsClass; /* Gets its class. */ jfieldID fid; /* Gets each field ID. */ status = sane_get_parameters((SANE_Handle) handle, ¶ms); /* Get class info. */ paramsClass = (*env)->GetObjectClass(env, paramsObj); /* Fill in each member. */ fid = (*env)->GetFieldID(env, paramsClass, "format", "I"); (*env)->SetIntField(env, paramsObj, fid, params.format); fid = (*env)->GetFieldID(env, paramsClass, "lastFrame", "Z"); (*env)->SetBooleanField(env, paramsObj, fid, params.last_frame); fid = (*env)->GetFieldID(env, paramsClass, "bytesPerLine", "I"); (*env)->SetIntField(env, paramsObj, fid, params.bytes_per_line); fid = (*env)->GetFieldID(env, paramsClass, "pixelsPerLine", "I"); (*env)->SetIntField(env, paramsObj, fid, params.pixels_per_line); fid = (*env)->GetFieldID(env, paramsClass, "lines", "I"); (*env)->SetIntField(env, paramsObj, fid, params.lines); fid = (*env)->GetFieldID(env, paramsClass, "depth", "I"); (*env)->SetIntField(env, paramsObj, fid, params.depth); return (status); } /* * Class: Sane * Method: start * Signature: (I)I */ JNIEXPORT jint JNICALL Java_Sane_start (JNIEnv *env, jobject jobj, jint handle) { return (sane_start((SANE_Handle) handle)); } /* * Class: Sane * Method: read * Signature: (I[BI[I)I */ JNIEXPORT jint JNICALL Java_Sane_read (JNIEnv *env, jobject jobj, jint handle, jbyteArray data, jint maxLength, jintArray length) { int status; jbyte *dataElements; int read_len; /* # bytes read. */ /* Get actual data ptr. */ dataElements = (*env)->GetByteArrayElements(env, data, 0); /* Do the read. */ status = sane_read((SANE_Handle) handle, dataElements, maxLength, &read_len); (*env)->ReleaseByteArrayElements(env, data, dataElements, 0); /* Return # bytes read. */ (*env)->SetIntArrayRegion(env, length, 0, 1, &read_len); return (status); } /* * Class: Sane * Method: cancel * Signature: (I)V */ JNIEXPORT void JNICALL Java_Sane_cancel (JNIEnv *env, jobject jobj, jint handle) { sane_cancel((SANE_Handle) handle); } /* * Class: Sane * Method: strstatus * Signature: (I)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_Sane_strstatus (JNIEnv *env, jobject jobj, jint status) { const char *str = sane_strstatus(status); return ((*env)->NewStringUTF(env, str)); } #ifdef __cplusplus } #endif sane-backends-1.0.27/japi/ImageCanvas.java0000664000175000017500000000623612112021330015156 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** ** ImageCanvas.java - A canvas that displays an image. ** ** Written: 11/4/97 - JSF **/ import java.awt.Canvas; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.image.ImageProducer; /* * Here's a canvas that just shows an image. */ public class ImageCanvas extends Canvas { Image image = null; // The image to display. ImageCanvasClient client = null; // 1 client for now. /* * Create with empty image. */ ImageCanvas() { } /* * Create image from an image producer. */ void setImage(ImageProducer iprod, ImageCanvasClient c) { client = c; image = createImage(iprod); repaint(); } /* * Paint. */ public void paint(Graphics g) { System.out.println("In ImageCanvas.paint()"); Dimension dim = getSize(); g.drawRect(0, 0, dim.width - 1, dim.height - 1); if (image != null) { g.drawImage(image, 1, 1, dim.width - 2, dim.height - 2, this); } } /* * Image has been updated. */ public boolean imageUpdate(Image theimg, int infoflags, int x, int y, int w, int h) { System.out.println("In imageUpdate()"); boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0); // repaint(); paint(getGraphics()); if (done && client != null) // Tell client when done. { client.imageDone((infoflags & ERROR) != 0); client = null; } return (!done); } } sane-backends-1.0.27/japi/Makefile.am0000664000175000017500000000227012775312262014211 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. # # Makefile for a Java project with native methods. # JAVAROOT=. MY_CLASSPATH=. JAVAH=javah -jni -cp $(MY_CLASSPATH) # We'll need something in 'configure' for the Java includes. AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include -I${JDK_HOME}/include \ -I${JDK_HOME}/include/genunix AM_LDFLAGS += $(STRICT_LDFLAGS) -version-number $(V_MAJOR):$(V_MINOR):$(V_REV) JAVA_SRC = SaneDevice.java SaneOption.java SaneRange.java\ Sane.java SaneParameters.java ScanIt.java \ ImageCanvas.java ImageCanvasClient.java \ Test.java Jscanimage.java dist_noinst_JAVA = $(JAVA_SRC) LIBSANE = ../backend/libsane.la EXTRA_DIST = README.JAVA lib_LTLIBRARIES = libsanej.la BUILT_SOURCES = Sane.h CLEANFILES = Sane.h nodist_libsanej_la_SOURCES = Sane.h libsanej_la_SOURCES = Sane.c libsanej_la_LIBADD = $(LIBSANE) # Make sure that java classes get created before create Sane.h Sane.h: classdist_noinst.stamp $(JAVAH) Sane sane-backends-1.0.27/japi/Test.java0000664000175000017500000001302212112021330013706 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ class Test { public static void main(String[] args) { Sane sane = new Sane(); int version[] = new int[1]; // Array to get version #. int status = sane.init(version); if (status != Sane.STATUS_GOOD) { System.out.println("getDevices() failed. Status= " + status); return; } System.out.println("VersionMajor =" + sane.versionMajor(version[0])); System.out.println("VersionMinor =" + sane.versionMinor(version[0])); System.out.println("VersionBuild =" + sane.versionBuild(version[0])); // Get list of devices. // Allocate room for 50. SaneDevice devList[] = new SaneDevice[50]; status = sane.getDevices(devList, false); if (status != Sane.STATUS_GOOD) { System.out.println("getDevices() failed. Status= " + status); return; } for (int i = 0; i < 50 && devList[i] != null; i++) { System.out.println("Device '" + devList[i].name + "' is a " + devList[i].vendor + " " + devList[i].model + " " + devList[i].type); } int handle[] = new int[1]; status = sane.open(devList[0].name, handle); if (status != Sane.STATUS_GOOD) { System.out.println("open() failed. Status= " + status); return; } System.out.println("Open handle=" + handle[0]); // Get # of device options. int numDevOptions[] = new int[1]; status = sane.getControlOption(handle[0], 0, numDevOptions, null); if (status != Sane.STATUS_GOOD) { System.out.println("controlOption() failed. Status= " + status); return; } System.out.println("Number of device options=" + numDevOptions[0]); for (int i = 0; i < numDevOptions[0]; i++) { SaneOption opt = sane.getOptionDescriptor(handle[0], i); if (opt == null) { System.out.println("getOptionDescriptor() failed for " + i); continue; } System.out.println("Option name: " + opt.name); System.out.println("Option title: " + opt.title); System.out.println("Option desc: " + opt.desc); switch (opt.constraintType) { case SaneOption.CONSTRAINT_RANGE: System.out.println("Range: " + opt.rangeConstraint.min + ", " + opt.rangeConstraint.max + ", " + opt.rangeConstraint.quant); break; case SaneOption.CONSTRAINT_WORD_LIST: System.out.print("Word list: "); for (int j = 0; j < opt.wordListConstraint[0]; j++) System.out.print(opt.wordListConstraint[j]); System.out.println(); break; case SaneOption.CONSTRAINT_STRING_LIST: for (int j = 0; opt.stringListConstraint[j] != null; j++) System.out.print("String constraint: " + opt.stringListConstraint[j]); break; default: System.out.println("No constraint."); break; } } status = sane.setControlOption(handle[0], 2, SaneOption.ACTION_SET_VALUE, "../test1.pnm", null); if (status != Sane.STATUS_GOOD) { System.out.println("setControlOption() failed. Status= " + status); } // // Main scanning loop. // SaneParameters parm = new SaneParameters(); int dataLen = 32*1024; byte [] data = new byte[dataLen]; int [] readLen = new int[1]; int frameCnt = 0; do { frameCnt++; System.out.println("Reading frame #" + frameCnt); status = sane.start(handle[0]); if (status != Sane.STATUS_GOOD) { System.out.println("start() failed. Status= " + status); return; } status = sane.getParameters(handle[0], parm); if (status != Sane.STATUS_GOOD) { System.out.println("getParameters() failed. Status= " + status); return; //++++cleanup. } while ((status = sane.read(handle[0], data, dataLen, readLen)) == Sane.STATUS_GOOD) { System.out.println("Read " + readLen[0] + " bytes."); // ++++++++Process data. } if (status != Sane.STATUS_EOF) { System.out.println("read() failed. Status= " + status); } } while (!parm.lastFrame); sane.close(handle[0]); } } sane-backends-1.0.27/po/0000775000175000017500000000000013110600540011706 500000000000000sane-backends-1.0.27/po/POTFILES.in0000664000175000017500000000272512775312262013432 00000000000000# List of source files containing translatable strings # paths relative to the top source directory include/sane/saneopts.h backend/sane_strstatus.c backend/artec_eplus48u.c backend/avision.h backend/canon630u.c backend/canon.c backend/canon-sane.c backend/canon_dr.c backend/canon_dr.h backend/cardscan.c backend/cardscan.h backend/epjitsu.c backend/epjitsu.h backend/epson.c backend/epson.h backend/epson2.c backend/epson2.h backend/fujitsu.c backend/fujitsu.h backend/genesys.c backend/gt68xx.c backend/gt68xx_low.h backend/hp3500.c backend/hp3900_sane.c backend/hp5400_sane.c backend/hp5590.c backend/hp-option.c backend/hp-option.h backend/kodak.c backend/kodak.h backend/kvs1025.h backend/kvs1025_opt.c backend/kvs20xx.c backend/kvs20xx_opt.c backend/kvs40xx.c backend/kvs40xx_opt.c backend/leo.c backend/leo.h backend/lexmark.c backend/ma1509.c backend/magicolor.c backend/matsushita.c backend/matsushita.h backend/microtek2.c backend/microtek2.h backend/mustek.c backend/mustek_usb.c backend/mustek_usb2.c backend/niash.c backend/pixma.c backend/pixma_sane_options.c backend/plustek.c backend/plustek_pp.c backend/pnm.c backend/rts8891.c backend/sceptre.c backend/sceptre.h backend/sm3840.c backend/snapscan.c backend/snapscan-options.c backend/stv680.c backend/stv680.h backend/teco1.c backend/teco1.h backend/teco2.c backend/teco2.h backend/teco3.c backend/teco3.h backend/test.c backend/u12.c backend/umax1220u.c backend/umax.c backend/umax_pp.c sane-backends-1.0.27/po/es.gmo0000664000175000017500000023536213110600540012754 00000000000000Þ•_ 6H H-H DH;PH ŒH,™H"ÆHzéH dI9nI¨I€ÅI#FJ5jJ" JÆÃJŠKj¥K LB1L(tLSLñLØMáMBNCNlZNÇNJ×N+"OcNO ²OzÓO'NP™vP$QW5QQžQ¯Q ·Q ÂQ ÍQ ØQãQ ëQ öQR R R R+R 4R ?R JR URbR jR xR „RŽR¡R²R ÄR ÏRÚR ãR îRÒüRÏS ÒS ßSëS ïSúSTT"T!=T_T!T ¡TÂT âTU UsU ‘U5›U ÑUÝUíUÿUV*V;V SV!tV–V¶V»VÊV áV ìV úVW W$W!>W`WuW‰W<šWG×W_XX=X>ÍX< YIYMYSYcY'sY›Y¤Y¼Y ÎY ÙY ãYïY ôYZ ZZ6Z EZ SZ_Z|ZŽZ%ZÃZ%ÒZ øZ[ [ ["[6[M[U[X[h[ l[y[Œ[¨[Å[à[ ò[ü[\))\%S\ y\…\œ\³\Ä\ Ô\â\ó\] ] ]#]5]M]T]&g]ÄŽ]S^Y^i^r^ ^ ^ œ^ ¦^°^ ¿^Í^ê^ __ 8_F_N_V_^_ t_€_‰_Ÿ_¶_Ë_ß_ô_6`.>`Bm`C°`Aô`,6a@caA¤a?æa(&b Ob![b*}b ¨b³b(ºbãbøb ccc)3c"]c$€c*¥c#Ðc(ôc!d?d#]ddžd ¾dßdIþd,He'uee0­eDÞe #f/f?f1GfyfŽf§f½f Ïfðfgg0g7gLgbg|g/–g Æg Òg%Þgh&#hJhah1zh¬h¼hÓh êh i%i8iKiSi ZiEfi¬iÃiÉiçijj(j=j Xjej#wj?›j!Ûj ýjk2k´k(Îk+÷k0#lTl hltl„l­œlJm dm om}m0‘m ÂmÍmåmìmñm n nnn &n 1n =nIn Rn \ngn lnwn ˆn”n§nºn ÂnÏnÕnínün oo7o%Hohnoe×o^=pcœpaqbbqaÅq 'r2rCr Ur_rprur{r Œr™r!ªr Ìr)Ør*s(-s›Vsòsûs tt t$t 4t@tGtMtUtftwt†t Œtšt «t¶tÒtât ñtþtu5u:uCuZuqu‰u™u©uºu ÐuÛuòu v2"v2Uvˆvœv¶v»vÒvèvw (w2wEwYwkw …wIwÚwTÞw[3xEx4Õx’ y¹yQWz€©z¢*{Í{à{æ{ø{|&|6|Q|*e|5| Æ|Ò|ã|ô|}}4}=} N} o}}}•} } ©} ¶}Ã} Ü} ç}0~9~C@~„~Œ~©~Á~Å~Ú~ð~!>BHO_gxŠ+勺倀7€I€ Y€g€n€u€|€&Ž€*µ€ à€ê€ó€ ü€ ' : DRm}‚ ‰X–Þï΂]à‚>„ Z„e„Li„¶„ӄڄ݄愅…6… I… W… b… n… z… …… ……¼…%Ñ…÷… ††† 7†D†X† `†m†s† †Mž†ì† ‡ ‡‡*‡ :‡D‡ H‡ S‡^‡Mt‡‡ ƇÒ‡á‡ê‡ ˆ ˆ ˆ*ˆFˆ dˆoˆÖˆ|f‰ ㉠ñ‰ÿ‰Š %ŠFŠdŠ{ЗбŠÌŠ[æŠB‹\‹ n‹y‹ ‹œ‹®‹Á‹ Ò‹Ü‹ ì‹ Œ Œ&Œ9ŒUŒrŒ'ŒµŒ ÇŒ Ԍތ îŒ úŒx~&” »É åòŽ.ŽEŽ^Ž#sŽg—œÿœ:´;ï9+‘,e‘Y’‘%ì‘’F*’q’/†’*¶’"á’‡“Œ“¢“'Á“<é“4&”>[”Bš”>Ý”?•D\•?¡•9á•9–=U–@“–=Ô–B—>U—>”—?Ó—=˜<Q˜Ž˜˜D¥˜,ꘙ0™B™S™?i™©™1Á™ó™;šNšašqšˆš¡š¸šÑšéš››*›>B›?›Á›D×›%œ4Bœwœ)œX¹œ2ÌEžž)ž:ž)Iž sž ~žˆžœž®žžÕžçžúž"Ÿ3Ÿ)HŸ rŸ€Ÿ—ŸüŸŸÐœ pm¡KÞ¡*¢=¢Q¢W¢^¢c¢j¢r¢ y¢ ƒ¢ ¢›¢#¬¢Тà¢"ð¢W£k£z£ƒ£%ž£Ä£Û£ï£÷£< ¤I¤ f¤ t¤¤G˜¤'à¤u¥=~¥Œ¼¥I¦SZ¦1®¦4à¦7§;M§‰§Ÿ§ µ§ ¿§à§÷§ ¨!"¨ D¨!O¨ q¨~¨“¨¥¨¸¨ ʨ بù¨©$©D©K©S©Z©k©ƒ©£©·©Ê©Ù© é©. ª9ªCOª“ª(ªªÓªAçª)«.G«&v«« »«È«á«ú«¬¬)#¬ M¬`n¬`Ϭ 0­<­X­ x­„­¨œ­>E®‹„® ¯¯1¯G¯)[¯ …¯’¯–¯Ÿ¯ §¯´¯¹¯ Яݯí¯)°,°I°h°}°° ³°À°Ô°ç°±±±&,±S±!o±‘±¢±´±б á±ï± ²/)²Y²y²²‘²÷˜² ´:´Ø´Zè´ Cµ5Pµ2†µm¹µ '¶P4¶)…¶¢¯¶+R·F~·=ŷϸ'Ó¸‹û¸4‡¹s¼¹40ºaeº(Ǻßðº1лZ¼#]¼^¼à¼Zø¼;S½R½2⽕¾?«¾‘ë¾<}¿sº¿.ÀIÀ dÀoÀ ÀŒÀ žÀ ©À ´À¾ÀÐÀ ÙÀ äÀîÀÁ ÁÁ 'Á2Á CÁNÁ ]Á jÁtÁŒÁ£Á ·ÁÁÁÓÁ ÜÁ çÁöôÁë î úÂ+Ã2ÃJÃ%[ÃÃ#šÃ+¾Ã*êÃ+Ä+AÄ+mÄ+™ÄÅÄÎÄ‹áÄmÅ:€Å»ÅÏÅéÅÿÅÆ3ÆIÆ&fÆ'Æ&µÆÜÆáÆ"ôÆÇ.ÇFÇ ZÇ {Ç+‡Ç³ÇÐÇèÇûÇOÈReÈx¸È1ÉHJÉI“ÉHÝÉ&Ê-Ê3ÊBÊ3QÊ …Ê‘Ê¬Ê ÅÊÓÊæÊõÊúÊ ËË#+ËOËbËwË)ˆË ²ËÓË/ãËÌ/#ÌSÌZÌcÌlÌ}̷̿̚ÌÂÌàÌ äÌòÌ$ Í%2Í$XÍ}Í—Í Í$µÍ1ÚÍ$ Î 1Î>ÎXÎxÎΜίÎÂÎÔÎÚÎéÎüÎ*Ï?ÏFÏ/YÏê‰ÏtÐzЊГШоÐÎÐ ÝÐçÐ÷Ð+Ñ24ÑgÑ$|ѡѲѻÑÄÑÍÑ èÑ ôÑþÑÒ5ÒPÒjÒ…Ò;ŸÒ)ÛÒ;Ó<AÓ;~Ó,ºÓ>çÓ?&Ô>fÔ"¥ÔÈÔ.ØÔ1Õ9Õ OÕB]Õ Õ¿Õ×ÕæÕöÕ7Ö2MÖ/€Ö8°Ö3éÖ7×2U×*ˆ×1³×,å×2Ø3EØ2yØU¬Ø/Ù62ÙiÙ3}ÙC±ÙõÙ Ú!ÚI*ÚtÚ‰Ú¦ÚÀÚ*×ÚÛÛ#*Û NÛYÛmÛƒÛšÛ:±ÛìÛüÛ( Ü-5Ü8cܜܭÜ3ÌÜÝ Ý";Ý(^Ý‡Ý¡ÝµÝ ÉÝ ÔÝÞÝTòÝ GÞhÞ*qÞ.œÞ$ËÞðÞ ß 'ßHß[ß#sßR—ß,êß3àKà—fà&þà@%á5fá<œáÙáòáùá âÙ(âã ã,ã,BãFoã ¶ãÂãÙãàãèãúãä ä,ä <äJä`ärä„ä–ä¨ä ­ä¸äÌäÜä÷äå å)å 1åRåeå{åŒåªå@Âåxæu|ænòæsaçqÕçrGèqºè ,é6éEé\émééŠéé ¢é¯é$Áé æé-òé. ê-Oê¦}ê $ë/ëCëUëZëkë~ë•ëë¤ë¬ëÇëâëþëìì&ì$8ì]ìqì‡ì*™ì(Äìíì õìíí=íWíkíí#—í »íÈíäíî9!î9[î•î!®îÐîÕîòî(ï"7ïZïbïtï‡ï"™ï ¼ïeÇï-ðn3ð_¢ðMñCPñº”ñOòcWó™»óÑUô'õ<õCõ%Wõ}õõ#¤õÈõ3ßõ9ö Mö!Zö|öšö¯ö2Îö÷÷7-÷e÷'…÷­÷¿÷Õ÷ó÷*ø<ø4Tø5‰ø¿øHÅøù'ùEùeùjù†ùŸù&²ù Ùùúùÿùúú "ú0úHúaú<yú¶úÌú#Üú!û""ûEûYûmûtû{û‚û‰û*šû4Åû úûü üü,üDüZü uüü ü°üÄüÌüÓüfäü×Ký#þ“7þËÿ éÿ÷ÿcÿÿ2c–¥ ¬&¸ß ÷. ?M_o€ ’&œÃ+Þ )#Aex ›°(¹âWøPh{‹© ÇÑÚí"[#„”£#´Øë)#; _2lýŸ“1FZp"³Óì &Ci_Éç ý  * 8 K _ r ‚ 3› Ï ì " $  D e .… ´ Ô é ù  " ‹7 "à +æ  % E "U x :–  Ñ  ò A UÊå°FÏGF^7¥wÝ8UŽQ¤#ö=<X'• ½^+v+¢HÎIHaMªIøIBOŒJÜC'DkH°MùIGO‘DáD&EkD±MöDUU^=´&ò7TPq ÂEã()CR–¯$Ï*ô$*D%o+•Á$Ü*E,TrÇPç-88fŸ-¾lì6Y¨ ¯ À Ò 6ã !"!*!B!Y!q!‰! !¸!6Ô! "5%"[" k"Œ""•"ò¸#…«$N1%€%Ÿ% ¿% Ë%Ø% Þ% é%÷% ý% &&$&&9&`&t& ˆ&^©&' '%'-E'!s'•'²'Ê'Tæ';(X(!w(™(G¸(()y))@£)±ä)–*X«*=+:B+:}+;¸+ô+,,,.3,(b,'‹,³,2Æ,ù,2 - ?-M-i-‚-˜-±-'Ä-ì-! .!-. O. \. h.r.&†.,­.Ú.÷./#/08/:i/¤/[À/0-;0i0E€0#Æ0@ê02+1)^1ˆ1# 1#Ä1è1ñ12>2)^2qˆ2qú2l3&†3+­3Ù3$ñ3Ç4KÞ4•*5À5Ð5ê56/6 O6!]6 6 6 À6 Î6 Û6ü67""79E7,7)¬7Ö7+î7868H8a8|8 —8 £8¯8&Å8/ì899V9p92†9!¹9Û9$ö90:HL:1•: Ç:Õ: æ:(|8ßLÏPÔ2‚Æ\£’2«oK&Úü5gb‡A fþü÷¬ñ%a9»É DmÁi×%H²‘–m,NÞÑô¾®[Jã󱆠L_êGûAøå)8«D]œ¼öd§·‰oT$Z¾zMAY¢=>ùç‚ëŽO! ;Á–§R¨‰üðVÝšÈ&p,.U¼_qœäjbqRá^•šÛ˪ ºïJ¨%ñu4í Pp 3v²ðdÅd›ÌCØÖóe3­ÙU;N<‡\I½ÆÖW3µ‹ö¨}›¬ù†*‚ÐÓ¦7>CU?··‘{ù#5&ê°ªœi]‰ryû?´Õ/’-l/ ìEF‘¾fÆŠžˆµ~â”ïôi0Ç t”•8ße"*<AŽâFtø5‹g-„–BmEá¸ÑÑsƒGa1MkýO}pò:B®¦0‹ÚÿB±<îQ^Xk­ŽÛSV½KƒìG¹7å']â—7çÈà!K{t°ÀÚ¼æxÒz)YˆŠY¡´yhËÎʧuL3PТ}ÊUÐκ:êë1%R<[þÉ„Y Ÿ x™{4h›¹˜&F~ÙJÏëôÕÎ'@"á‡ï N Œ9ì8[Œ ÅZÞI¯°Éy¶SM^(ŒóVvcE¦Ôˆ¢K“+j¡…¿:è@J˜åÊO'—÷©Za,5/Þ“ ÿ#¤Q¿ÌxäŠN+k2~ƒEÃà>è'` \ò× çÔHW©—Bvèu¹¸ ,¿Ohqݶé«)F`Ãר.0Ýðº¶Ùø÷®|±õ6$æ©]Äfí."n =(Ä ¸ÓÏ¥Üß½…à)wãW³ú…s+Ò/é`¡o¤öæ;rb†€1ÂwDòÁ6³6?õžj9žþõ z ÕDP=2¯?ËTIû4éTÿ$ÛÄ­lÌ!Q´CÇX»+ýÀ²;£™¤n$¥l„-#T_úÅÍ™XÀ:rH’g@ý¥1»[0€>4 Ü*ÇñS*Í"€Øw¬Ÿ³n-C=WQÒ(¯”“XµÍ•6Ÿ.Mä@!H£îÖRÃ\ȘVs GIeÜíî^cc|S#_ š9ªZ  úLÓ7ã(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF DuplexADF ModeADF cover openADF jamAccess to resource has been deniedAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowCancel buttonChange Document.Change documentChannelChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDisable auto document feeder and use flatbed onlyDisable backtrackingDisable gamma correctionDisable interpolationDisable pre focusDisable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEnhancementError DiffusionError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInk-jet printersInt test optionsInvalid argumentInvert endiannessLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryPDF buttonPage heightPage loadedPage widthPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner cover is openScanner mechanism locked for transportScanner modelScanner sensors and buttonsSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Speedup sensorStandardStart calibration process.Start calibration using special sheetStatus Code SimulationString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.White levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: sane-backends Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2009-06-25 10:22+0100 Last-Translator: Miguel Anxo Bouzada Language-Team: GALPon MiniNo Language: es MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 1.11.4 Plural-Forms: nplurals=2: plural=(n != 1); X-Poedit-Language: Spanish X-Poedit-Country: SPAIN (1/1) Botón(1/1) Botón de opción de prueba. Imprime algún texto...(1/3) Real fijo(1/3) Opción de prueba de valor real (coma fija) sin unidad ni conjunto de restricciones.(1/3) Cadena(1/3) Opciones de prueba de cadena sin restricciones.(1/6) Booleana configurable y legible por software(1/6) Opción de prueba booleana configurable y legible por el software. Esta es la opción booleana normal. (1/6) Entero(1/6) Opción de prueba de valor entero sin unidad ni conjunto de restricciones.(2/3) Real fijo con rango de restricción(2/3) Opción de prueba de valor real (coma fija) con unidad de microsegundo y rango de restricción. El mínimo es -42,17, el máximo 32767,9999 y el salto 2,0.(2/3) Cadena restringida a lista de cadenas(2/3) Opción de prueba de cadena con restricción de lista de cadenas(2/6) Booleana configurable por hardware legible por software(2/6) Opción de prueba booleana configurable por hardware y legible por el software. Esta opción no puede ser ajustada por la interfaz, pero si por el usuario (p.ej. pulsando un botón en el dispositivo).(2/6) Entero con rango de restricciones(2/6) Opción de prueba de valor entero con unidad de píxel y con conjunto de restricciones, El mínimo es 4, el máximo 192 y el salto 2.(3/3) Real fijo con restricción de lista de valores(3/3) Opción de prueba de valor real (coma fija) sin unidad y restringida por un conjunto de valores de una lista.(3/3) Restricción de cadenas lista larga de cadenas(3/3) Opción de prueba de cadena con restricción de lista de cadenas. Contiene más entradas...(3/6) Booleana configurable por hardware(3/6) Opción de prueba booleana configurable por hardware. Esta opción no puede ser ajustada por la interfaz, pero si por el usuario (p.ej. pulsando un botón en el dispositivo) tampoco puede ser leída por la interfaz .(3/6) Entero con restricción de lista de valores(3/6) Opción de prueba de valor entero con unidad bits y restricción de lista de valores(4/6) Booleana lexible por software(4/6) Opción de prueba booleana legible por el software Esta es una opción de sólo lectura.(4/6) Matriz de enteros(4/6) Opción de prueba de valor entero con unidad mm usando una matriz con restricciones.(5/6) Booleana configurable y legible por software, emulada(5/6) Opción de prueba booleana configurable y legible por el software y emulada.(5/6) Matriz de enteros con rango de restricciones(5/6) Opción de prueba de valor entero con unidad dpi y usando una matriz con rango de restricciones. El mínimo es 4, el máximo 192, y el salto 2.(6/6) Booleana configurable y legible por software, automática(6/6) Opción de prueba booleana configurable y legible por el software y emulada. Esta opción puede ser ajustada automáticamente por el motor.(6/6) Matriz de enteros con restricción de lista de valores(6/6) Opción de prueba de valor entero con unidad % y usando una matriz con restricciones en una lista de valores,1/2 de la velocidad normal1/3 de la velocidad normal2-píxeles2x2 personalizado2x2 normal3x3 personalizado3x3 normal4-píxeles4x4 tosco4x4 personalizado4x4 fino4x4 normal5x5 tosco5x5 personalizado5x5 fino6x4 (pulg.)6x6 personalizado6x6 normalSalida de 8 bits8-píxeles8.5x11 (pulg.)8x10 (pulg.)8x8 Bayer8x8 «Engrasado» tosco8x8 «Engrasado» fino8x8 Línea vertical8x8 tosco8x8 personalizado8x8 fino8x8 normal8x8 muy finoUna exposición prolongada permite al escáner recoger más luz. Se sugiere usar 175% para impresiones, 150% para diapositivas normales y «Negativo» para película en negativo. Para imágenes oscuras (subexpuestas) puede incrementar este valor.A4A5 apaisadoA5 verticalAlimentador automático de documentos (ADF)Alimentador a dos carasModo alimentadorla tapa del alimentador está abiertaatasco en el alimentadorSe ha denegado el acceso al recursoAñade azul basándose en el nivel de verdeAñade azul basándose en el nivel de rojoAñade verde basándose en el nivel de azulAñade verde basándose en el nivel de rojoAñade rojo basándose en el nivel de azul.Añade rojo basándose en el nivel de verdeAvanzadoOpciones avanzadasDespués de enviar la orden de escanear, esperar hasta que se presione el botón del escáner para empezar realmente el proceso de escaneo.Todas las páginasApagar siempre la lámpara cuando se calibra la oscuridad.Ganancia analógicaInterfaz analógica (AFE)Gamma analógico azulCorrección gamma analógicaGamma analógico verdeGamma analógico rojoCorrección gamma analógicaCorrección gamma analógica para azulCorrección gamma analógica para verdeCorrección gamma analógica para rojoAutoUmbral automáticoSegmentación automática de áreaExpulsión automáticaExposición automáticaEnfoque automáticoEnfoque automático solo una vezAutomáticoAlimentador automático de documentos (ADF)Ajuste automático de umbralSeparación automáticaUmbral automáticoCalentamiento automáticoExpulsar automáticamente la película del dispositivo después de cada escaneoExpulsar automáticamente la película del dispositivo antes de salir del programaAjusta automáticamente el brillo, contraste, niveles de blanco, gamma y reducción de intensidad del ruido de la imagenLineas de vuelta atrásFactor de balance para azul. Un valor de 100% significa sin corrección.Factor de balance para verde. Un valor de 100% significa sin corrección.Factor de balance para rojo. Un valor de 100% significa sin corrección.BahíaBayerTrama Bayer 16Trama Bayer 64Dos niveles blanco y negro (modo de línea de arte)Enlazar RGBEnlazar resoluciones X e YEnlazar gamma analógicoAsociar gammaBit de profundidadNivel de negroAzulBalance de azulBrillo de azulGanancia de AzulValor de ganancia de azul en el AFEIntensidad de azulApagar lámpara azulDesviación azulValor de la desviación de azul en el AFEOpciones de prueba «Booleanas»Abajo-derecha XPosición X abajo-derecha del área de escaneo.Abajo-derecha YPosición Y abajo-derecha del área de escaneo.BrilloBotón 1Botón 2Botón de estadoOpciones de botón de pruebaBotón de control de escaneoBotonesCDError de verificación de CPUCRTMonitores CRTCal. tiempo de exposiciónCal. tiempo de exposición para azulCal. tiempo de exposición para verdeCal. tiempo de exposición para rojoCal. densidad de lámparaCalibrarCalibrar el escánerCalibrar antes del siguiente escaneoCalibrar las lentes en la posición del documentoCalibrar el nivel de blanco y negro.CalibraciónCalibración por el motorCaché de datos de calibraciónModo de calibraciónCalibrar ahoraBotón de cancelarCambiar documento.Cambiar documentoCanalID del chipsetNombre del chipsetLimpiar la calibraciónLimpiar la caché de datos de calibraciónGruesaCalibración toscaCalibración tosca sólo para el primer escaneoLa calibración tosca se hace sólo para el primer escaneo. Funciona con la mayoría de escáneres y puede ahorrar tiempo de escaneo. Si el brillo de la imagen es diferente con cada escaneo, desactive esta opción. Sólo para pruebas.ColorColor (48 bits)Color 36Medios tonos a colorLinea de arte a colorMatriz de colorColor en BRUTOColor RGBColor RGB TEXTOBalance de colorAjustes de ganancia de los canales de colorAjustes del desplazamiento de los canales de colorCorrección de colorCoeficientes de corrección de colorPatrón de colorColor 24Color 36Color 48Color, líneas por lecturaCondicionalContrasteContraste de canal de azulContraste de canal de verdeContraste de canal de rojoControla el nivel de azulControla el nivel de verdeControla el nivel de rojoContola el «matiz» (nivel de azul) de la imagen obtenida.Controla el brillo de la imagen obtenida.Controla el brillo del canal de azul de la imagen obtenida.Controla el brillo del canal de verde de la imagen obtenida.Controla el brillo del canal de rojo de la imagen obtenida.Controla el contraste de la imagen obtenida.Controla el contraste del canal de azul de la imagen obtenida.Controla el contraste del canal de verde de la imagen obtenida.Controla el contraste del canal de rojo de la imagen obtenida.Controla si se fuerza el retrocesoBotón de copiaCorreción de acuerdo con el tipo de películaCorrección conforme con la tasa de transparenciaLa tapa está abiertaPersonalizadoMatriz de color personalizada para escáneres en escala de grises.Matriz de color personalizada.Opciones de depuraciónPredeterminadoPredeterminadosDefine el modo de calibraciónDefinir tiempo de exposición para calibración de azulDefinir tiempo de exposición para escaneo de azulDefinir tiempo de exposición para calibraciónDefinir tiempo de exposición para calibración de verdeDefinir tiempo de exposición para escaneo de verdeDefinir tiempo de exposición para calibración de rojoDefinir tiempo de exposición para escaneo de rojoDefinir tiempo de exposición para escaneoDefinir densidad de la lámpara para calibraciónDefinir densidad de la lámpara para escaneoDefine los parámetros de apagado de lámpara azulDefine los parámetros de apagado de lámpara verdeDefine los parámetros de apagado de lámpara rojaDefine el patrón de medios tonos (punteado) para escanear imágenes de medios tonos.Define el factor de zoom que usará el escánerRetardar la transferencia de datos a la canalización.Control de densidadDetermina la velocidad a la que se hace el escaneo.Determina si debe usarse una tabla gamma interna ó personalizada.Dispositivo ocupadoAjustes del dispositivoDiamanteDesactivar el alimentador automático de documentos y usar sólo el planoDesactivar retrocesoDesactivar corrección gammaDesactivar interpolaciónDesactivar foco previoDesactivar la corrección de sombra blancaPunto disperso 16x16Punto disperso 8x8Mostrar lista corta de resolucionesDifuminadoTrama A (4x4 Bayer)Trama B (4x4 espiral)Trama C (4x4 matizado)Trama D (8x4 matizado)Difuminado/medios tonos blanco y negro (modo medios tonos)Mapa de trama 1Mapa de trama 2Escanea en escala de grises, no en colorHacer una calibración de calidad de blancos Hacer enfoque automático solo una vez entre expulsionesNo calibrar focoNo forzar el código de estadoNo forzar al motor a devolver un código de estado.Alimentador de documentosAlimentador de documentos extrasAlimentador de documentos atascadoEl alimentador de documentos está vacioDoble resolución ópticaDescargar patrón ADescargar patrón BExclusiónDos carasEscaneo a dos carasEl escaneo a dos caras proporciona un escaneo del anverso y el reverso del documentoDuración del retardo de lecturaExpulsarExpulsar el documento después del escaneoExpulsar la película después de cada escaneoExpulsar la película antes de salirExpulsar película ahoraExpulsar la película *ahora*Expulsar la hoja del alimentadorBotón de correo-eEmular escala de grisesActiva el escaneo por las dos carasActivar la determinación automática de umbral para escaneos como línea de arte.Activar selección del tiempo de exposiciónActivar la selección de la densidad de la lámparaActivar opciones de pruebaActiva varias opciones de prueba. Esto se usa para probar la capacidad de las interfaces para ver y modificar los diferentes tipos de opciones de SANE.Activar/desactivar enfoque automáticoActivar/desactivar la característica de exposición automáticaActiva o desactiva la caché de datos de calibraciónActiva o desactiva la aceleración de movimiento del sensor.Fin de archivo alcanzadoMejoraDifusión de errorError en dispositivo de E/SIntercambia los bytes de datos superiores e inferiores de imágenes en modo de 16 bits. Esta opción puede utilizarse para la prueba de 16 bits de los modos de interfaz, p.ej. si la interfaz utiliza el orden correcto.Ejecutar calibración *ahora*ExperimentoTiempo de exposiciónRetardar el tiempo de apagado de la lámparaRetarda los tiempos de apagado de la lámpara (de 15 minutos a 1 hora)Muy rápidoAjustes de color extraExtrasRápidoModo gris rápidoVista previa rápidaEscaneo rápidoMás rápidoEl más rápidoBotón de faxModo de alimentaciónBotón de archivoNombre de archivoTipo de películaTira de películaFinaColor finoBalance de firmwarePrimera entradaFijar la posición de focoOpción de prueba «Real fijo»PlanaSólo planoEnfoqueEnfoque a 2.5mm sobre el cristalPosición del focoEnfoque en el cristalForzar retrocesoForzar vista previa monocromaForzar profundidad realFuerza la calibración del escáner antes de realizar el escaneoForzar al motor a devolver el código de estado de SANE_STATUS_ACCESS_DENIED después de haber sido llamado sane_read().Forzar al motor a devolver el código de estado de SANE_STATUS_COVER_OPEN después de haber sido llamado sane_read().Forzar al motor a devolver el código de estado de SANE_STATUS_EOF después de haber sido llamado sane_read().Forzar al motor a devolver el código de estado de SANE_STATUS_IO_ERROR después de haber sido llamado sane_read().Forzar al motor a devolver el código de estado de SANE_STATUS_JAMMED después de haber sido llamado sane_read().Forzar al motor a devolver el código de estado de SANE_STATUS_NO_DOCS después de haber sido llamado sane_read().Forzar al motor a devolver el código de estado de SANE_STATUS_NO_MEM después de haber sido llamado sane_read().Del papelDe palo blancoEsperar botón frontalEscaneo completoParámetros difusosGananciaGammaCorrección gammaTablas gammaCorrección gammaLa corrección gamma se desactivaráValor gammaTabla de corrección gama para la gamma azul.Tabla de corrección gamma para la gama verde.Tabla de corrección gamma para la gama roja.Tabla de corrección gamma. En modo color ésta opción afecta igualmente a los canales de rojo, verde y azul simultáneamente (ej. es una tabla de intensidad gamma).GeometríaGrupo de geometríaTamaño del granoGrisGanancia de grisColor en modo grisDesplazamiento de grisGris 16Gris 8AgrisarEscala de grises de 4 bitsEscala de grises de 8 bitsEscaneo en escala de grisesVerdeBalance de verdeBrillo de verdeGanancia de VerdeValor de ganancia de verde en el AFEIntensidad de verdeApagar lámpara verdeDesviación verdeValor de la desviación de verde en el AFEEscala de grises, líneas de por lecturaRejillaMedios tonosMedios tonos A (tonos duros)Medios tonos B (tonos suaves)Medios tonos C (matizado)Medio tono punto 32Medio tono punto 64Patrón de medios tonosTamaño del patrón de medios tonosMedios tonosMedios tonos no compatiblesSimulación de escáner manualSimulación de escaneo manualPosición X interna en el hardware de la zona de escaneo.Posición Y interna en el hardware de la zona de escaneo.Resolución del hardwareOpciones especificas de hardawareAltoImpresión de alto contrasteImpresión de alta densidadLa mejor calidad, pero a velocidad lentaMás rápido, pero de peor calidadResalteResalte para azulResalte para verdeResalte para rojoMarcar la posición del foco a 0mmHorizontalCuanto tiempo se esperará después de transferir cada búfer de datos a través de la canalización.MatizSi se selecciona el alimentador automático de documentos, el alimentador estará «vacío» tras 10 escaneos.Si se selecciona, el motor intenta determinar automáticamente un valor óptimo para el umbral.Si se selecciona la calibración del color antes del escaneo la hace el motorSi se selecciona, el escáner no retrocede cuando pierde una líneaSi está activada, la imagen será escaneada en modo de color y después convertida a escala de grises por software. Esto puede mejorar la calidad de la imagen en algunas circunstancias.Si está activado, sólo se realizarán correcciones de sombras durante la calibración. Se usarán los valores predeterminados de ganancia, desplazamiento y tiempo de exposición, ya sean los que trae incorporados el programa o los del archivo de configuración.Si se activa, algunas imágenes implicadas en el proceso de escaneo se guardarán para analizarlas.Si se activa, el dispositivo se calibrará antes del siguiente escaneo. En otro caso, la calibración se realizará únicamente antes del primer escaneo.Si gamma está activada, siempre se analiza en profundidad de 16 bits para mejorar la calidad de la imagen y después convertirla a la profundidad seleccionada. Esta opción evita la emulación de profundidad.Ignorar calibraciónImagenMejora de la ImagenLas imágenes de color se invertiránResalte de imagenIntensidad de imagenOpciones de modificación de imagenImpresoras matricialesEn modo RGB usar los mismos valores para cada colorAumenta o disminuye la ganancia analógica de la gama CCDInformaciónImpresoras de inyección de tintaOpciones de prueba «Entero»Argumento incorrectoInvertir el orden de los datosLa lámpara no está preparada, intentelo de nuevoApagar lámparaApagar la lámpara al salirApagar la lámpara durante la calibración de oscuridadTiempo de espera de la lámparaTiempo de apagado de lámpara (minutos)Encender lámparaEstado de la lámparaLímite de tiempo de lámparaTiempo de apagado de lámparaTiempo de apagado de lámpara en segundos.Interruptor de lámparaCalibración de lentes en la posición del documentoVeamos si la interfaz puede tratar esto correctamenteCartaLimita la cantidad de datos transferidos con cada llamada a sane_read().Línea de arteCargar la imagen como escala de grises.Pérdida de píxeles por líneaBajoImpresión de baja densidadPosición de foco manualFoco previo manualCambiar la(s) lámpara(s) manualmente.Matriz de multiplicación de RGBMáxSoporteSoporteManejar el soporteMedias tintasMedias tintas para azulMedias tintas para verdeMedias tintas para rojoMinutos que tardará la lámpara en apagarse tras el escaneoInversión horizontalInvertir imagenInvertir la imagen horizontalmente.Invertir la imagen verticalmente.Invierte la imagen horizontalmenteInvertir la imagen.Inversión verticalVariosModo 1Modo 2Modo 3Matriz monocromoMultinivel color RGB (color de una pasada)Multinivel blanco y negro (modo de escala de grises)NTSC GrisNTSC RGBNegativoPelícula en negativoDiapositiva en negativoPelícula en negativoTipo de película negativoNegativosSin correcciónSin corrección de transparenciaReducción de ruidoNingunoNormalVelocidad normalNúmero de bits por muestra, valores típicos son 1 para «linea de arte» y 8 para escaneos multibit.Número de líneas que retrocede el escáner cuando escanea más rápido de lo que el equipo puede recibir datos. Valores bajos hacen que los escaneos sean más rápidos, pero aumentan los riesgos de omitir líneas.Número de opcionesNúmero de líneas de escaneo a petición de una lectura SCSI. El cambio de este parámetro le permite ajustar la velocidad a la que se leen los datos desde el escáner durante los escaneos. Si este es demasiado bajo, el escáner tiene que parar periódicamente en medio de un escaneo, si es demasiado alto, basado en interfaces X puede dejar de responder a eventos de X y su sistema se podría atascar.Número de muestra a escanearBotón de OCRApagadoProponer la selección un descriptor de archivo para detectar si sane_read () devolverá los datos.Proponer la selección de un descriptor de archivoDesplazamientoActivoUna páginaRealizar sólo correcciones de sombrasOperación no soportadaLa operación va a ser canceladaEquipamiento opcionalNo queda memoriaBotón de PDFAltura de páginaPágina cargadaAncho de páginaTamaño del papelA travésRealizar autodiagnóstico del escánerCalibración de precisiónTamaño físico del papel en el alimentadorPositivoPelícula en positivoDiapositiva en positivoPelícula en positivo o en negativoBotón de energíaAjustes predefinidosPrevisualizarModo de vista previaImprimirImprimir una lista de todas las opcionesImprimir las opcionesProporciona superficies de escaneo estándar para fotografías, páginas impresas, etc.Calibración de calidadEscaneo de calidadFormato rápidoError de verificación de RAMError de verificación de ROMAleatorioEn brutoRetardo de lecturaLímite de lecturaOpción de prueba de sólo lecturaOpción de sólo lectura que establece cuantas opciones soporta un dispositivo específico.RojoBalance de rojoBrillo de rojoGanancia de rojoValor de ganancia de rojo en el AFEIntensidad de rojoApagar lámpara rojaDesviación rojoValor de la desviación de rojo en el AFEReduce los puntos aislados de ruidoReflectantesSolicitar una vista previa de calidad del escaneo.Solicitar que todas las vistas previas sean hechas en modo monocromo. En un escáner de tres pasadas esto reduce el número de pasadas a una, y en un escáner de una pasada esto reduce los requisitos de memoria y el tiempo de escaneo de la vista previa.Precisa que todas las vistas previas se hagan del modo más rápido (baja calidad). Este puede ser un modo sin color o un modo de baja resolución.Reiniciar el chipsetReiniciar escánerReiniciar el escánerReiniciar los datos del chipsetDevuelve SANE_STATUS_ACCESS_DENIEDDevuelve SANE_STATUS_COVER_OPENDevuelve SANE_STATUS_EOFDevuelve SANE_STATUS_IO_ERRORDevuelve SANE_STATUS_JAMMEDDevuelve SANE_STATUS_NO_DOCSDevuelve SANE_STATUS_NO_MEMDevuelve líneas difusas y bytes por línea cuando se llama a sane_start() antes que a sane_parameters().Valor de retorno de sane_readerror de paridad SCSISaturaciónGuardar imágenes de depuraciónGamma escalarGamma escalar azulGamma escalar verdeGamma escalar rojoModo de escaneoGrupo de modo de escaneoOpciones del área de escaneo y tamaño del soporteBotón de control de escaneoContador de escaneosTiempo de exposición para escaneoTiempo de exposición para azulTiempo de exposición para verdeTiempo de exposición para rojoEscanear en modo gris rápido (menor calidad).Densidad de lámpara de escaneoMárgenes de escaneoModo de escaneoResolución de escaneoOrigen de escaneoVelocidad de escaneoEscanear todo el área de escaneado incluyendo la franja de calibración. Tenga cuidado. No seleccione la altura total. Sólo para pruebas.La tapa del escáner está abiertaEl escáner está bloqueado para transporteModelo de escánerSensores y botones del escánerSegunda entradaSeleccione la bahía para escanearSeleccionar tipo de películaSeleccionar el brillo mínimo para obtener un punto blancoSeleccionar filtro de suavizado.Seleccionar el tipo de películaSelecciona el tipo de prueba de imagen. Posibles opciones: Negro sólido: llena todo el escaneo con negro. Blanco sólido: llena todo el escaneo con blanco. Patrón de color: dibuja varios patrones de prueba de color dependiendo del modo. Rejilla: dibuja una rejilla en blanco y negro con un tamaño de 10mm por cuadrado.Selecciona el modo para vista previa. La vista previa en escala de grises proporciona en general, la mejor relación entre velocidad y detalle.Seleccione el valor de retorno de sane_read(). «Predeterminado» es el normal para hacer el escaneo. Todos los demás códigos de estado son para probar la forma en que la interfaz se encarga de ellos.Seleccione la imagen de pruebaSeleccionar un valor para la corrección gamma escalar (canal de azul)Seleccionar un valor para la corrección gamma escalar (canal de verde)Seleccionar un valor para la corrección gamma escalar (canal de rojo)Seleccionar un valor para la corrección gamma escalar.Selecciona el «granulado» de la imagen obtenida. Valores más pequeños dan como resultado imágenes mejor definidas.Seleccionar el modo del alimentador (una cara/dos caras)Selecciona el brillo.Selecciona la gama de color, «Master» significa que afecta a todos los colores.Seleccionar lo que se va a excluir.Seleccionar el tipo de película, p.e. negativo o diapositivaSelecciona la curva de transferencia de la corrección gammaSelecciona el modo de corrección gammaSelecciona el valor de corrección gamma de una lista de dispositivos predefinidos o de una tabla definida por el usuario, que puede ser descargada al escáner.Selecciona medios tonosSelecciona el tipo de negativo de películaSelecciona el número de muestra a escanearSelecciona el modo de escaneo (ej. línea de arte, monocromo, ó color).Selecciona el origen del escaneo (tal como un alimentador de documentos).Selecciona que nivel de radiancia azul debe tenerse en cuenta «negro».Selecciona que nivel de radiancia azul debe tenerse en cuenta «azul total».Selecciona que nivel de radiancia azul debe tenerse en cuenta «blanco».Selecciona que nivel de radiancia verde debe tenerse en cuenta «negro».Selecciona que nivel de radiancia verde debe tenerse en cuenta «verde total».Selecciona que nivel de radiancia verde debe tenerse en cuenta «blanco».Selecciona que nivel de radiancia debe tenerse en cuenta «negro».Selecciona que nivel de radiancia debe tenerse en cuenta «blanco».Selecciona que nivel de radiancia rojo debe tenerse en cuenta «negro».Selecciona que nivel de radiancia rojo debe tenerse en cuenta «rojo total».Selecciona que nivel de radiancia rojo debe tenerse en cuenta «blanco».Selecciona si la imagen obtenida debe ser convertida a medios tonos (punteado).Selecciona que nivel de radiancia debe ser considerado «50% azul».Selecciona que nivel de radiancia debe ser considerado «50% gris».Selecciona que nivel de radiancia debe ser considerado «50% verde».Selecciona que nivel de radiancia debe ser considerado «50% rojo».Selecciona qué color de escaneo se usará en modo gris (predefinido: verde).AutodiagnósticoSensoresAjustar los valores predeterminados para los controles de mejora (brillo y contraste)Ajustar valores predeterminados para los controles de mejora.Ajustar el modo de control de densidadAjustar tiempo de exposiciónAjustar densidad de lámparaAjustar el valor de nitidez.Ajustar el sistema óptico de foco en la posición manual (predeterminado: 128).Ajustar el orden de las muestrasAjustar el orden de las muestras en el modo de tres pasadas de color.Ajustar la matriz de color del escáner.Ajustar el tiempo (en minutos) tras el que se apagará la lámpara.Ajustar tipo de soporte.Ajusta el encendido/apagado UTAAjusta la ganancia del canal de azulAjusta el desplazamiento del canal de azulAjusta la ganancia del canal de grisAjusta el desplazamiento del canal de grisAjusta la ganancia del canal de verdeAjusta el desplazamiento del canal de verdeEnciende/apaga la lámparaAjusta la ganancia del canal de rojoAjusta el desplazamiento del canal de rojoAjusta el balance de color a los valores facilitados por el firmware.Ajusta la tabla de corrección del color para el dispositivo de salida seleccionado.Ajusta el modo de alimentaciónAjusta la posición del foco, ya sea al cristal o a 2.5mm por encima del cristalAjusta el valor gamma para todos los canales.Ajusta la resolución horizontal de la imagen escaneada.Ajusta el resalte de la imagenAjusta la resolución de la imagen escaneada.Ajusta el tamaño del patrón de medios tonos (punteado) usado cuando se escanean imágenes de medios tonos.Ajusta la resolución vertical de la imagen escaneada.Configuración de la ganancia y desplazamiento para escanear automáticamente. Si esta opción está desactivada, se proporcionan las opciones de ajuste de los parámetros de forma manual en la interfaz analógica. Esta opción está activada como predefinida. Solo para pruebas.SombraSombra para azulSombra para verdeSombra para rojoSombras, medias tintas, resalte, tiempo de exposiciónNitidezEnfoqueCambiar de azul a verdeCambiar de azul a rojoCambiar de verde a azulCambiar de verde a rojoCambiar de rojo a azulCambiar de rojo a verdeLista corta de resolucionesMuestra el nombre del chipset usado en el dispositivo.Mostrar la ID del chipsetMostrar el número de escaneos hechas por el escánerApagar lámparaApagar la lámpara del escáner.Una caraSimula un escáner de mano. Los escáneres de mano a menudo no conocen a priori la distancia a la imagen. En su lugar utiliza una altura de retorno -1. Ajustando esta opción permite comprobar si una interfaz puede manejar esto correctamente. Esta opción también permite un ancho de 11cm.Simula un escáner de mano. Los escáneres de mano a menudo no conocen a priori la distancia a la imagen. En su lugar utiliza una altura de retorno -1. Ajustando esta opción permite comprobar si una interfaz puede manejar esto correctamente.Simula un escáner de tres pasadas devolviendo 3 muestras separadas. Por diversión, devuelve verde, después azul y finalmente rojo.Simula un escaneo de tres pasadas. En el modo color, se generan tres muestras.Tamaño del límite de lecturaOmitir proceso de calentamientoDiapositivaDiapositivasLentoMás lentoEl más lentoSuaveSuavizadoNegro sólidoBlanco sólidoSelección de origenOrigen, opciones de modo y resoluciónOpciones especialesOpciones especialesEspecifica la altura del soporteEspecifica la anchura del soporte. Necesario para el centrado automático de hojas de escaneo.Acelerar el sensorEstándarIniciar proceso de calibraciónIniciar calibración usando una hoja especialSimulación del código de estadoOpciones de prueba de cadenaImportación con éxitoIntercambiar blanco y negroActivar/desactivar la unidad de transparencias (FAU, unidad adaptadora de película)Enciende o apaga la lámparaAdaptador (TMA) para negativosAdaptador (TMA) para diapositivasTecnología de mejora de textoCantidad de datos (máxima) transferida con cada llamada a sane_read().Nombre de archivo de la imagen a cargar.La lámpara será apagada después del tiempo dado (en minutos). Un valor de 0 significa que la lámpara no será apagadaNúmero de píxeles que se pierden en el extremo de cada línea.El nivel de saturación controla la cantidad de «florecimiento» (halo) que ocurre cuando se obtiene una imagen con una cámara. Valores más altos producen más florecimiento.Impresoras térmicasEsta tercera entrada es muy larga. Tal vez la interfaz tiene una idea de cómo mostrarloEsta opción refleja un botón del panel frontal del escánerEsta opción refleja el estado de los botones del escánerEsta opción refleja el estado de los botones del escánerEsta opción apaga la lámpara del plano durante el escaneoSimulación de tres pasadasSimulación de tres pasadasUmbralValor de umbral para el modo de línea de arteConmutar el estado de lámpara del planoConmuta el estado de lámpara del planoArriba-izquierda XPosición X arriba-izquierda del área de escaneo.Arriba-izquierda YPosición Y arriba-izquierda del área de escaneo.TransparenciaAdaptador de transparenciasUnidad de transparenciasTasa de transparenciaUnidad de transparenciasApagar la lámparaApaga la lámpara al salir del programaApaga la lámpara del escánerEnciende la lámpara del escánerApaga la lámpara inmediatamente.UTA ActivadoDesconocidoDescargarDescargar documentoDescargar soporte después de escanearDescargar los soportes después de escanear.Actualizar estado del botónActualizar informaciónActualizar opcionesActualizar opciones.Actualiza la información acerca del dispositivoUsar la marca de posición de foco a 0mm en vez de a 0,6mmUsar composición de imagenUsar bit de profundidad mayor de ocho internamente, pero en la salida usar sólo ocho bits.Usar tabla gamma personalizadaUsar lente que duplica la resolución ópticaUsar E/S no bloqueanteUsar una E/S no bloqueante para sane_red() si lo permite la interfaz.Usar sólo resoluciones de hardwareUsar los mismos valores gamma para todos los canales de colores.Usar los mismos valores para la resolución X e Y.Usar el adaptador de diapositivas de 35mmDefinida por el usuarioDefinido por el usuario (gamma=1.0)Definido por el usuario (gamma=1.8)VerticalEsperar por el botónEsperando por el botónEsperar a que se presione en el botón frontal para escanear.Esperando por el botón antes de escanearCalentar hasta que el brillo de la lámpara sea constante en vez de esperar por los 40 segundos de calentamiento.Calentar hasta que el brillo de la lámpara sea constante en vez de esperar por los 60 segundos de calentamiento.Calentamiento de lámparaCalentar la lámpara antes de escanearEl proceso de calentamiento se desactivaráTiempo de calentamientoTiempo de calentamiento en segundos.Habilitado, el proceso de escaneo no comenzará inmediatamente. Para proceder, haga clic en el botón "SCAN" (para MP150) o "COLOR" (para otros modelos). Para cancelar, haga clic en el botón "GRAY".Cuando se usa gris o línea de arte esta opción selecciona el color usado.Cuando se usan altas resoluciones en las que la resolución horizontal es más pequeña que la vertical, esto desactiva la interpolación horizontal.Nivel de blancoNivel de blanco para azulNivel de blanco para verdeNivel de blanco para rojoLa corrección de sombra blanca se desactivaráResolución XAdaptador de transparencias (XPA)Adaptador de transparencias grisAdaptador de transparencias RGBResolución YAcercamientoerror en la secuencia de ordenesescáner de películasescáner planoerror de verificación de hardwareel iniciador detectó la recepción deun mensaje de errormensaje de bit de IDENTIFICACIÓN incorrectocódigo de orden de operación incorrectocampo incorrecto en CDBcampo incorrecto en la lista de parámetrosmensaje de error incorrectofallo de lámparalámpara no estabilizadano se encuentra el soportesin información adicionalposición Xposición Yla opción no conectaparámetro cambiado por otro iniciadorerror en la longitud de la lista de parámetrosreiniciar el encendido / reiniciar el bus del dispositivofallo al volver a escogerparámetro redondeadoerror en el posicionamiento del cabezal de escaneoescáner con cargador automáticoerror de límite de tiempose especificaron demasiadas ventanasfallo de la lámpara de unidad de transparenciasfallo de posición del cabezal de escaneo de la unidad de transparenciaserror de sombreado en la unidad de transparenciasdesconocido/aLUN no soportadocámara websane-backends-1.0.27/po/en_GB.gmo0000664000175000017500000021153713110600540013315 00000000000000Þ•6ÌI|3 D ¡D-®D ÜD;èD $E,1E"^EzE üE9F@F€]F#ÞF5G"8GÆ[G"Hj=H ¨HBÉH( IS5I‰IØ IyJB˜JÛJlòJ_KJoK+ºKcæK JLzkL'æL™M$¨MWÍM%N6NGN ON ZN eN pN{N ƒN ŽN™N ¢N ­N ¸NÃN ÌN ×N âN íNúN O O O&O9OJO \O gOrO {O †OÒ”OgP jP wPƒP ‡P’P›PªP!²PÔP!ôP Q7Q WQxQQs’Q R5R FRRRbRtRŒRŸR°R ÈR!éR S+S0S?S VS aS oSzS S™S!³SÕSêSþS<TGLT_”TôT=U>BU<U¾UÂUÈUØU'èUVV1V CV NV XVdV iVvV †VV«V ºV ÈVÔVñVW%W8W%GW mWxWW ŠW—W«W³W¶WÆW ÊW×WêWX#X>X PXZXlX)‡X%±X ×XãXúXY"Y2YCYSY [Y fYsYzY&YÄ´YyZZZ˜Z §Z µZ ÂZ ÌZÖZ åZóZ[/[@[ ^[l[t[|[„[ š[¦[¯[Å[Ü[ñ[\\6-\.d\B“\CÖ\A],\]@‰]AÊ]? ^(L^!u^*—^Â^(É^ò^__!_*_)B_"l_$_*´_#ß_(`!,`N`#l``­` Í`î`I a,Wa'„a¬a0¼aDía2bBb1Jb|b‘bªbÀb Òbóbcc3c:cOcecc/™c Éc Õc%ácd&&dMddd1}d¯d¿dÖdðdeee %eE1eweŽe”e²eÍeäeóef#f#5f?Yf!™f »fÜfðfrg(Œg+µg0ág hh­.hÜh öh ii0#i Ti_iwi~iƒi ’i Ÿi©i°i ¸iÄi Íi ×iâi çiòi jj"j5j =jJjPjhjwj†j™j²j%ÃjhéjeRk^¸kcla{lbÝla@m ¢m­m¾m ÐmÚmëmðmöm nn!%n Gn)Sn*}n(¨n›Ñnmovo …oo •oŸo ¯o»oÂoÈoÐoáoòop pp &p1pMp]p lpyp—p°pµp¾pÕpìpqq$q5q KqVqmq…q2q2Ðqrrr3rIrir ‰r“r¦rºrÌr ærIñr;sT?s[”sEðs46t’kt¹þtQ¸u€ v¢‹v.wAwGwYwxw‡w—w*«w5Öw xx)x:xLxUx fx ‡x•x­x µx Áx ÎxÛx ôx ÿx0 yQyCXyœy¤yÁyÙyÝyòyzz9zVzZz`zgzwzzz¢z+²zÞz ðzýz{1{O{a{ q{{†{{”{&¦{*Í{ ø{| | |"| 1|?| R| \|j|…|•|š| ¡|X®|Þ}æ}]ø}VrLvÃàçêó€ &€ 1€>€]€%r€˜€ ¡€¯€¾€Ø€ì€ ô€ $M2€ ” ¡®¾ ÎØ Ü çòM‚V‚ Z‚f‚u‚~‚ ˜‚ ¦‚ ³‚¾‚Ú‚ ø‚ƒÖ#ƒ|úƒ w„ …„“„¥„ ¹„Ú„ø„…+…E…`…[z…Ö…ð… † † #†0†B†U† f†p† €†† †¼†Ù†'ô†‡ .‡ ;‡E‡ U‡ a‡xl‡ å‡ ó‡ˆˆ.$ˆSˆlˆ#ˆg¥‰œ ŠªŠ:Š;ýŠ99‹,s‹Y ‹%ú‹ ŒF8ŒŒ/”Œ*ÄŒ"š°'Ï<÷44Ž>iŽB¨Ž>ëŽ?*Dj?¯9ï9)=c@¡=âB ‘>c‘>¢‘?á‘=!’<_’œ’D«’,ð’“6“H“Y“?o“¯“1Ç“ù“;”T”g”w”Ž”§”¾”×”ï” ••0•>H•?‡•Ç•DÝ•%"–4H–}–)•–X¿–2—ÌK—˜˜/˜@˜)O˜ y˜ „˜Ž˜¢˜´˜Șۘ혙"™9™)N™ x™†™™ü¥™Ð¢šps›Kä›0œCœWœ]œdœiœpœxœ œ ‰œ •œ¡œ²œœÒœáœüœ'<<y – ¤¯GÈ'žu8ž=®žŒìžyŸSŠŸ1ÞŸ7 ;H „ š  °  º Û ò  ¡!¡ ?¡!J¡ l¡y¡Ž¡ ¡³¡ Å¡ Ó¡ô¡ ¢¢?¢F¢N¢U¢f¢~¢ž¢²¢Å¢Ô¢ ä¢.£4£CJ£Ž£(¥£ΣAâ£$¤.B¤&q¤˜¤ ¶¤äܤõ¤þ¤¥)¥ H¥`i¥`Ê¥ +¦7¦S¦ s¦¦¨—¦>@§‹§ ¨¨,¨B¨)V¨ €¨¨‘¨š¨ ¢¨¯¨´¨ ˨بè¨)ý¨'©D©c©x©˜© ®©»©Ï©â©ª ªª&'ªNª!jªŒªª¯ª˪ ܪꪫ/$«T«t«|«Œ«½“« Q­-^­ Œ­;˜­ Ô­,á­"®z1® ¬®9¶®𮀠¯#ޝ5²¯"è¯Æ °Ò°jí° X±By±(¼±Så±9²ØP²)³BH³‹³l¢³´J´+j´c–´ ú´zµ'–µ™¾µ$X¶W}¶Õ¶æ¶÷¶ ÿ¶ ·· ·"· *· 5·@·I· K· V·a· j· u· €· ‹·˜·  · ®· º·Ä·×·è· ú·¸¸ ¸ ¸Ò"¸õ¸ ø¸ ¹¹ ¹ ¹)¹8¹!@¹b¹!‚¹ ¤¹Ź 幺ºs º ”º5žº Ôºâºôº»"»7»J» b»!ƒ»¥»Å»Ê»Ù» ð» û» ¼¼ )¼3¼!M¼o¼„¼˜¼<©¼Gæ¼_.½޽ž½> ½<ß½¾ ¾&¾6¾'F¾n¾w¾¾ £¾ ®¾ ¸¾ľ ɾÖ¾ æ¾ð¾ ¿ ¿ (¿4¿Q¿c¿%r¿˜¿%§¿ Ϳؿῠê¿÷¿ ÀÀÀ&À *À7ÀJÀfÀƒÀžÀ °ÀºÀÌÀ)çÀÁ ÁÁ6ÁMÁ^ÁnÁÁÁ ‰Á ”Á¡Á¨Á&»ÁÄâÁ§Â®Â ¿ÂÉÂÙ è ö Ã ÃÃ+ÃIÃiÃ{ÚéòûÃÄà ÚÃæÃïÃÄÄ1ÄEÄZÄ6mÄ.¤ÄBÓÄCÅAZÅ,œÅ@ÉÅA Æ?LÆ(ŒÆ!µÆ*ׯÇ) Ç3ÇIÇ[ÇcÇlÇ)„Ç"®Ç$ÑÇ*öÇ#!È(EÈ!nÈÈ#®ÈÒÈïÈ É0ÉIOÉ,™É'ÆÉîÉ0þÉD/ÊtÊ„Ê1ŒÊ¾ÊÓÊìÊË Ë5ËGËWËuË|ˑ˧ËÁË/ÛË Ì Ì&#ÌJÌ&iÌ̧Ì1ÀÌòÌÍÍ3ÍFÍYÍaÍ hÍEtͺÍÑÍ×ÍõÍÎ'Î6ÎKÎfÎ#xÎ?œÎ!ÜÎ þÎÏ3ϵÏ(ÏÏ+øÏ0$Ð UÐaЭqÐÑ 9Ñ DÑRÑ0fÑ —ѢѻÑÂÑÇÑ ÖÑ ãÑíÑôÑ üÑÒ Ò Ò&Ò +Ò7Ò 9ÒEÒXÒkÒ sÒ€Ò†ÒžÒ­Ò¼ÒÏÒèÒ%ùÒhÓeˆÓ^îÓcMÔa±ÔbÕavÕ ØÕãÕôÕ ÖÖ!Ö#Ö)Ö :ÖGÖ!XÖ zÖ)†Ö*°Ö(ÛÖœ×¡×ª× ¹×Ä× É×Ó× ä×ð×÷×ýרØ'Ø6Ø <ØJØ [ØfØ‚Ø’Ø ¡Ø®ØÌØåØêØóØ Ù!Ù9ÙIÙYÙjÙ €Ù‹Ù¢ÙºÙ2ÒÙ2Ú8ÚLÚQÚhÚ~ÚžÚ ¾ÚÈÚÛÚïÚÛ ÛI&ÛpÛTtÛZÉÛE$Ü3jÜ“žÜ¹2ÝQìÝ€>Þ¢¿Þbßuß{ß߬߻ßËß+ßß7 à CàOà`àqàƒàŒà à ¾àÌàäà ìà øà áá +á 6á0WáˆáCáÓáÛáøáââ)â?âAâaâ~â‚âˆââŸâ§â¸âÊâ+Úâã ã%ã@ãYãwã‰ã ™ã§ã®ãµã¼ã(Ïã*øã #ä-ä6ä ?äMä \äjä }ä ‡ä•ä°äÀäÅä ÌäXÙäÞ2åæ]#æççL¡çîç èèèè>è Qè \èièˆè%èÃè ÌèÚèéèéé é,é2é OéM]é«é ¿é ÌéÙééé ùéê ê êêM3êê …ê‘ê ê©ê Ãê Ñê Þêéêë #ë.ëÖNë}%ì £ì ±ì¿ìÑì åìí$í;íWíqíŒí[¦íîî .î9î Oî\înîî ’îœî ¬î¹îÌîèîï' ïHï Zï gïqï ï ïx˜ï ð ð,ð?ð.Pððð$–ðg»ñœ#òÀò:Øò;ó9Oó,‰óY¶ó%ô6ôFNô•ô/ªô*Úô"õ‡(õ°õÆõ'åõ= ö4Kö>€öB¿ö÷?÷DD÷?‰÷9É÷9ø==ø@{ø=¼øBúø>=ù>|ù?»ù=ûù=9úwúD†ú,Ëúøúû#û4û?JûŠû2¢ûÕû;õû1üDüTükü„ü›ü´üÌüæü÷ü ý?%ý@eý¦ýD¼ý%þ4'þ\þ)tþXžþ2÷þÌ*ÿ÷ÿþÿ). X cm“§ºÌß"õ)- We|ü„ÐpRLÃ#7=DIPX _ i u’¢²ÁÜó<Y v „G¨'ðu=ŽŒÌYSj1¾7ð;(dz  š»Ò ò!ý  !*  L Y n € “  ¥  ³ Ô ê ÿ  & . 5 F H h |  ž  ® .Ï þ C X (o ˜ A¬ î . &; b  €  ¦ ¿ È Ø )è   `3 `”  õ  =I©a? ‹K ×ãø)" LY]f n{€ —¤´)Éó/Dd z‡›®Î×à&ó!6Xi{— ¨¶Ñ/ð @HXDÎ0§EáW»ã Z^:nGÈ2¸Bñƒz¯}´NcD³˜¼x|O~XX)Tä üt©°I¡Éþ"’òáÏd‡æ•‚ÐÁxo/`ÐR2= ˜ô»â™d˜ãHìí¶‚áWñµMK÷3]/§4°Øž!Ê CCÜJI§¡Þ(žr-î×ܦ YÆ.‡½ÀP?ý“O[ „‚$nÊQŠÃñ”«bük‹ |{UK¨‘(£îRªòÅóQG®×hö{Ñ¿¹êŽ(ö@ êl‘0¤%7ôì…ÎPÀ5¥°œ²­ÓÉ1«E:5ÑógûmŸ–h¸¤nÇzÖŸ}ÔXÿ%û]ȽVgÌ F7ÔòL¡ß>ÝÛåÞ‡_-T[=Klm_æöÒ6¶³-µþy¯®šv¢é¸Åw$CvF€ùãâs—¼Uõí“Ñq„6"BØÇ¿ßÒ/›ÒĦ!_“,—Ö\«6¹MÈûc4 >2u­´* 1‹Â\`޲¨'®†ôx@ŒójÝAS èR=¼qÐÁ‘‰f–Û3% -e—Ù€ç9ƒ  Ë ½‹éQú¨’¾<oè ±iøïÔë…af,&u9œm%†?¶ÇfĬpoˆjÊspŠL怙ÀO¢ i;)G ­õ"ÄÕ2|Š3Pì' *†3D”Bt ~à×1w?l£åÏ£ÆS.•²ägdÌU<wÿ©¬4# ùÙ8}*›6&šNª~0à‰*ë;^„úï/)ÃØI+Ÿê¥]7`8èYbÁ› ÓZMbi#Üÿ¾àF…”EÃð1Ù$Û&øÕ>É5'ªtîWËeyS!¹pkV–øÓ'÷ͤ+륯þÚºL{´é+uÝÏü^aÌcšõ8ŽÞ÷çðÚå±N˺<ðV··(,Ö·TŒ )ºÍœï0.jYçžzÆý\ q.$r"Œ¬ ¦ye@&Å#¢»HA!±äs™v5³ˆÂrk µ[’Jú,ˆ•:9Aƒùýâ#ÍJ+4a;ξߩZÚ¿‰íHÕh(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF DuplexADF ModeADF cover openADF jamAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton 1Button 2Button stateButton test optionsButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowChange Document.Change documentChannelChipset IDChipset nameCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Correction according to film typeCorrection according to transparency ratioCustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device-SettingsDiamondDisable auto document feeder and use flatbed onlyDisable backtrackingDisable gamma correctionDisable interpolationDisable pre focusDisable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.EnhancementError DiffusionExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOptional equipmentPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner modelSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsSpeedup sensorStart calibration process.Status Code SimulationString test optionsSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.White levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2009-04-25 00:19+0100 Last-Translator: Andrew Coles Language-Team: British English Language: en_GB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Lokalize 0.3 Plural-Forms: nplurals=2; plural=(n != 1); (1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed2-pixel2x2 custom2x2 normal 3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine 5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse 8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF DuplexADF ModeADF cover openADF jamAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analogue GainAnalogue frontendAnalogue gamma blueAnalogue gamma correctionAnalogue gamma greenAnalogue gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBacktrack lines Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analogue gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton 1Button 2Button stateButton test optionsButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document position CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowChange Document. ChannelChipset IDChipset nameCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColourColour (48 bits)Colour 36Colour HalftoneColour LineartColour MatrixColour RAWColour RGBColour RGB TEXTColour balanceColour channels gain settingsColour channels offset settingsColour correctionColour correction coefficientsColour patternColour24Colour36Colour48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Correction according to film typeCorrection according to transparency ratioCustomCustom colour matrix for greyscale scans.Custom colour matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device-SettingsDiamondDisable auto document feeder and use flatbed onlyDisable backtrackingDisable gamma correctionDisable interpolationDisable pre focusDisable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a greyscale rather than colour scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmulate GreyscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.EnhancementError DiffusionExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra colour adjustmentsExtrasFastFast grey modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFilm-stripFineFine colour First entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parameters GammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In colour mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGreyGrey gainGrey mode colourGrey offsetGrey16Grey8GreyifyGreyscale 4 bitsGreyscale 8 bitsGreyscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If ticked the backend automatically tries to determine an optimal value for the threshold.If ticked the colour calibration before a scan is done by the backendIf ticked the scanner does not perform backtrackingIf enabled, image will be scanned in colour mode and then converted to grayscele by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyse them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colourIncrease or decrease the analogue gain of the CCD arrayInformationInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as greyscale.Loss of pixels per lineLowLow density printingManual focus position Manually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Colour MatrixMulti-level RGB colour (one pass colour)Multi-level black & white (greyscale mode)NTSC GreyNTSC RGBNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOptional equipmentPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomiseRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-colour mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast grey mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner modelSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white point Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various colour test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or colour).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue". Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % grey".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan colour is used grey mode (default: green).Self diagnosisSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass colour mode.Set the scanners colour matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets grey channel gainSets grey channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the colour balance values to the firmware provided values.Sets the colour correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In colour mode, three frames are transmitted.Size of read-limitSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsSpeedup sensorStart calibration process.Status Code SimulationString test optionsSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnknownUnloadUnload Document. Unloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOUR" button (for other models). To cancel, press "GREY" button.When using grey or lineart this option selects the used colour.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.White levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GreyXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilisedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamsane-backends-1.0.27/po/remove-potcdate.sin0000664000175000017500000000066012775312262015462 00000000000000# Sed script that remove the POT-Creation-Date line in the header entry # from a POT file. # # The distinction between the first and the following occurrences of the # pattern is achieved by looking at the hold space. /^"POT-Creation-Date: .*"$/{ x # Test if the hold space is empty. s/P/P/ ta # Yes it was empty. First occurrence. Remove the line. g d bb :a # The hold space was nonempty. Following occurrences. Do nothing. x :b } sane-backends-1.0.27/po/de.gmo0000664000175000017500000023703613110600537012743 00000000000000Þ•†L½|8pK qK-~K ¬K;¸K ôK,L".LzQL ÌL9ÖLM€-M#®M5ÒM"NÆ+NòNj O xOB™O(ÜOSPYPØpPIQBhQ«QlÂQ/RJ?R+ŠRc¶R Sz;S'¶S™ÞS$xTWTõTUUU !U.U6U ;U FU QU \UgU oU }U ˆU“U œU §U ²U½U ÆU ÑU ÜU çUôU üU V V V 2V =VHV QV \VÒjV=W @W MWYW]W fW qW{W„W•W¤W"¬W!ÏWñW!X 3XTX tX•XžXs¯X #Y5-Y cYoYY‘Y©Y¼YÍY åY!Z(ZHZMZ\Z sZ ~Z ŒZ—Z ¬Z¶Z!ÐZòZ[[<,[Gi[_±[\\=&\>d\<£\à\ä\ê\ú\' ]2];]S] e] p]z] €]Œ] ‘]ž] ®]¸]Ó] â] ð]ü]^ +^9^%H^n^%}^ £^®^Ã^Ì^ Õ^â^ö^ ___(_ ,_9_L_h_…_ _ ²_¼_Î_)é_%` 9`E`\`s`„` ”`¢`³`Ã`á` é` ô`aa+a2a&EaÄla1b7bGbPb _b mb zb „bŽb b«bÈbçbøb c$c,c4c{U{k{‹{ «{µ{È{Ü{î{ ||#|I5||Tƒ|[Ø|E4}4z}’¯}¹B~Qü~€N¢Ïr€…€‹€€¼€Ë€Û€ö€* 55 kw€‘¢³ÅÊçð ‚ "‚0‚H‚ P‚ \‚ i‚v‚ ‚ š‚0»‚ì‚Có‚7ƒ?ƒ\ƒtƒxƒƒ£ƒ´ƒÔƒñƒõƒûƒ„„„+„=„+M„y„ ‹„˜„³„Ì„ê„ü„ ……!…(…/…&A…*h… “……¦…·… À…Î…Ý… ì…ú… † † %†3†N†^†c† j†Xw†ÞІ¯‡]Á‡‰ ;‰F‰LJ‰—‰´‰»‰¾‰ljç‰ÿ‰Š *Š 8Š CŠ OŠ [Š fŠ qŠ~ŠŠ%²ŠØŠ áŠïŠþŠ ‹%‹9‹ A‹N‹T‹ q‹M‹Í‹ á‹ î‹û‹ Œ Œ%Œ )Œ 4Œ?ŒMUŒ£Œ §Œ³ŒÂŒËŒ åŒ óŒ  ' EPÖp|GŽ ÄŽ ÒŽàŽòŽ 'E\x’­[Ç#=O T_ u‚”§ ¸Â Ò ó ÿ ‘‘;‘X‘'s‘›‘ ­‘ º‘Ä‘ Ô‘ à‘xë‘d’&z’ ¡’¯’ Ë’Ø’ë’.ü’+“D“#Y“g}”œå”‚•:š•;Õ•9–,K–Yx–%Ò–ø–F—W—/l—*œ—"Ç—‡ê—r˜ˆ˜'§˜<Ϙ4 ™†A™>È™Bš>Jš?‰šDÉš?›9N›9ˆ›=›@œ=AœBœ>œ>?@=€<¾û žDž,Wž„žž¯žÀž?ÖžŸ1.Ÿ`Ÿ;Ÿ»ŸΟÞŸõŸ % > V p  — >¯ ?î .¡DD¡%‰¡4¯¡ä¡)ü¡X&¢2¢Ì²¢£†£–£§£)¶£ ࣠ë£õ£ ¤¤/¤B¤T¤g¤"}¤ ¤)µ¤ ߤí¤¥ü ¥Ð ¦pÚ¦KK§—§ª§¾§ħ˧Ч×§ß§ æ§ ð§ ü§¨#¨=¨M¨"]¨W€¨بç¨ð¨% ©1©H©M©a©i©<~©»© Ø© æ©ñ©ªG ª'hªuª=«ŒD«6Ñ«¬S¬1m¬4Ÿ¬7Ô¬; ­H­^­ t­~­ Ž­¯­Æ­ æ­ ô­!ÿ­ !®!,® N®[®p®‚®•® §® µ®Ö®ì®¯!¯:¯A¯I¯P¯a¯y¯™¯­¯À¯ϯ ߯.°/°CE°‰°( °ɰAݰ±.=±&l±“± ±±¾±×±ð± ² ² ²0²)@² j²`‹²`ì² M³Y³u³ •³¡³¨¹³zb´>Ý´‹µ¨µ ®µºµϵåµ)ùµ #¶0¶4¶=¶ E¶R¶W¶ n¶{¶‹¶) ¶ʶç¶··;· Q·^·r·…·¥·®···&Ê·ñ·! ¸/¸@¸R¸n¸ ¸¸¨¸/Ǹ÷¸¹¹/¹Å6¹ üº/ » 9»;E» »+Ž»"º»–Ý» t¼4~¼³¼¤Ð¼#u½=™½"×½ÿú½ú¾¿ £¿KÄ¿(Àa9À›À0²ÀãÁOÂRÂiÂùÂL Ã+VÂà Äš#Ä'¾ÄºæÄ$¡Å[ÆÅ"Æ<ÆVÆ[Æ`ÆrÆzÆÆ •Æ Æ ¶ÆÁÆ ÉÆÖÆ߯õÆ þÆ ÇÇ(Ç 1Ç<ÇRÇ [ÇiÇ qÇ Ç ‹Ç•ǩDzÇÈÇ ÑÇ ÜÇòêÇÝÈàÈèÈðÈ%ôÈ É$%É JÉ TÉ*bÉ"É-°É2ÞÉ0Ê2BÊ1uÊ0§Ê1ØÊ ËËi(Ë ’Ë>žËÝËòËÌÌ1ÌJÌaÌ!yÌ"›Ì ¾ÌßÌäÌ%þÌ$Í:ÍRÍ)fÍ ÍšÍ%²ÍØÍîÍÎ@!ÎJbÎe­ÎÏÏ?+Ï@kÏ>¬ÏëÏóÏùÏ Ð.Ð JÐWÐtÐФЭеÐÇÐÌÐÛÐôÐ*Ñ9ÑJÑiÑ$}ѢѴÑÄÑ(ËÑôÑ(úÑ #Ò.ÒEÒMÒUÒeÒyÒÒ—Ò šÒ»Ò ÊÒ ×Ò)øÒ*"Ó(MÓvÓ ’ÓŸÓ"³Ó,ÖÓ"Ô &Ô3ÔKÔfÔzԌԜԯÔ2ÁÔ ôÔ þÔ ÕÕ!9Õ[Õ`Õ%qÕ —Õ¡Ö§Ö¶Ö ¿ÖÌÖ áÖ ìÖ öÖ× ×$×)@× j×x× “מקׯ׸×Ó× Û׿×ïר.ØNØe؃Ø8›Ø%ÔØFúØGAÙE‰Ù#ÏÙDóÙE8ÚC~Ú,ÂÚïÚ#þÚ/"ÛRÛbÛ3tÛ¨ÛÇÛËÛäÛøÛ ÜJ'ÜBrÜ4µÜKêÜC6ÝIzÝAÄÝ,Þ*3Þ&^Þ2…Þ3¸Þ1ìÞAßA`ß0¢ßÓß"æßX àbàvà‹à “àBààà%òàá2áKá"aá„á–á$¦áËáÓáëáâ!â%>âdâtâ9„â+¾â-êâã0ãALãŽã«ã&Èã!ïãä1äEä Yädä käOväÆäCâä &å&0å!Wåyå”å©å8Àå ùåæ*æWFæ/žæ#Îæòæ´ ç+Áç1íç1è)Qè{è—è¨èºèÊèÛè>êèí)éê 7êBêRêArê´êÆêãêêêòêëë-ë 5ë Bë Lë Yë eëoë wë…ëŠëë¬ëÁë Ôë Þëìëòë ìì/ìEìZì,oìuœìrík…ípñínbîoÑînAï °ï»ïÔïÚïôïð ð$ð*ð 9ðGð$Vð{ð Šð1”ð2Æð0ùðš*ñ Åñ Ññ Ûñ çñòñ òò2ò:ò AòLò]ònò~ò„ò”ò®ò+Éòõòó'ó%<ó bóƒóŠó’ó£ó µó¿óÐóáóðó ôô3ôJô+aô+ô¹ôÌôêôïô õ+'õ-Sõõ ‡õ ’õ žõ¨õ ÂõÍõÞõ[ðõLö^Töw³ök+÷T—÷¡ì÷áŽøUpù¢ÆùØiúBûZû _ûmûŠû™û©û Çû8ÔûF ü Tü`üiü}üŽü£ü·ü-¼ü êüôü&ý:ýNýmý výƒý—ý «ýÌýÛý.úý)þS0þ„þ”þ®þÅþÍþíþ ÿ ÿ%;ÿaÿiÿpÿwÿÿœÿ±ÿÇÿBÛÿ 2@Zr‹ ¯½ÅÍÕ&æ,  :DMe m y„ –¢²ÉÒâý[4£¶·n Ž˜tœ18 ;"Fi†¢¶ Ï Ù å ó  *F(`‰ ‘ ¨ÂÑí ö# -P?© ¸,Æ ó  " + < K R_ ²  ¶ Ä Ü )õ  / M #` '„ ¬ +µ ãá ´Å z ‘ § &½ )ä & 5 $U "z # "Á ˆä m‰ž £®ËÞõ  # -47 l v‚%Ÿ&Å$ì8Ja q{ Š•’©$<3a •£Á"ÑôE!MoZ†Žá¶p'?Vn „\¥14LK˜.¯&Þ–¶Î.îA5_Á•ZWX²Z [fYÂ[DxB½YWZY²A >N>?Ì= UJ  «U´7 Bb}%‘F·$þ9# *] Gˆ Ð ï ,!&5!,\!&‰!-°!'Þ!"+ "%L"?r"B²"õ"9#*J#/u#¥#$À#Iå#-/$Û]$9% B%P% _% l%w%€%‰%¤%½%Ø%ò% &%&,<&i&ˆ&¦&¸& Ò&æÜ&æÃ'ª(P;)Œ)§)Å)É)Î)Ö) Þ)ë)ñ)ú) * *.'*V*f*v*g–*þ*+!+6>+u+‹+‘+ ¥+8±+=ê+(, G,T,],f,Vƒ,%Ú,…-;†-‹Â-IN.˜.c«.6/7F/;~/’º/M0c0 y0…0,–0Ã05Ù011'%1M1'R1 z1…1—1©1¹1Ë1,á12'2@2 _2k2 s2 }2‡2!›2#½2á2û23,31D3/v3¦3HÂ3( 4C44x4^Ž4"í4-5/>5n5ˆ5š5¸5Ö5õ5þ5 6"6986#r6_–6_ö6V7%g7%7 ³7À7ÀÚ7v›8R9™e9ÿ9 ::#:8:(K: t::…:Ž: –:£:²: Ò:Þ:ï:. ;';;$c;ˆ;& ;Ç; â;ï;<$< C< M<W<.n<%<%Ã<é<ý<+===L=`="{=3ž=#Ò= ö=>>6>3!˜qÛðCAh£» „iYUD}]âÇ#ûÿ›yrQq€uªÄ)–R‘ò~£èf^  Ê&% ÜpaÀ_{ ?‡ý1ì/¼VÝ­bV>áê¢0•Î=†Þ\¾¶äüŸE*â»o×Vóíj «6³!Ѝˆ~ä+`³á²ñXM¯,R­yú®Ùø".׃@ôzS•_Ór#ç »·€ÍÏ5Gm ‹…HuŽ-1:ÌT=leÈqÊh¬’x€a~ gÄY‚Oðl*Ç{]«sò×Pœö™‡RÊ´üÎÜnLž¤7•™K(M·½Å% wÐ dT)ˆv:b+ ZAó7å3¦…à †³Ag'¶¾îÏ\?É#hüÑ¢k“Ìåù Že®’C±œäP“v…ðj§YÂ&Õð°‚[m4˜ƒÀøÌ÷®*+e¸ú|ÔÅFUŠW†Ò`*¹1cþŠæuIK æ‹V,Ë$ùÉÙ7mí^òÖt˜š ¢/š‚T/)F6ïûÓdUE5Zýf2wãPÖdF-ß(.)ïçxéÞ }ö=”Dݦ.dõÝc!jn',´`€ìB—pñTRm–H„™èHIO<1x!$/DPH.úËz90Ð wùôM;| çaÁ…y^WŒJJt‘v\¨ c},‰žŸÖìØ‰ÈŽ8%làäjEé`ík·¸;Ï-oÿa(% ëu‰ctêi¼—²;ê+›D@$”ƸnÐãDZÂî§32”k ËóŒƒgN¬µ‡::æ¯#G“Qßî3›s¥L¾£eZnB7 ©ëž¡?2¨ÕsÆš"B©L¿4Ñ{º>±|Ù 5âNpº¼M¡W=’ØÃf$S|ø0B§oQ&­\´>~bYþ^ܯ–(ôN_¹hpŜԶ[C¦ºlKXr6Eb©Œ{ˆ¹ÛŸ8z ¿o9&}Jª88ÛØ<Iz[fɃQ¡9g'i4éÁ„„ iJ@Óªkå뫵÷ÔNI_xáWy"5ÁþÕÍöU4KÑà¬S'vÚ½Ò"XÄO÷¥SÚèCqûÎÍ‘-Þ¤µ°ã½õ[<]ß‹A9G2s¥Æ†;?À0Èý<LÒÚñ õXFOrt@]¿—ÿZGw(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm16 bits gray2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel48 bits color4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF BackADF DuplexADF FrontADF ModeADF Waiting TimeADF cover openADF jamAccess to resource has been deniedAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBackBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowCancel buttonChange Document.Change documentChanges intensity of midtonesChannelChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCustomCustom color matrix for grayscale scans.Custom color matrix.DTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEnhance BlueEnhance GreenEnhance RedEnhancementError DiffusionError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFrontFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma function exponentGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInk-jet printersInt test optionsInvalid argumentInvert endiannessJPEGLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative colorNegative filmNegative film typeNegative grayNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryPDF buttonPage heightPage loadedPage widthPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner cover is openScanner mechanism locked for transportScanner modelScanner sensors and buttonsSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Speedup sensorStandardStart calibration process.Start calibration using special sheetStatus Code SimulationStopString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesTarget operation typeText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.Type of original to scanUTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: sane-backends Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2010-08-06 17:17+0100 Last-Translator: Rolf Bensch Language-Team: German Language: de MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Lokalize 0.3 Plural-Forms: nplurals=2; plural=n != 1; (1/1) Button(1/1) Button-Testoption. Gibt etwas Text aus...(1/3) Fixed(1/3) Fixed-Testoption ohne Einheit und ohne Beschränkung.(1/3) String(1/3) String-Testoption ohne Beschränkung.(1/6) Bool soft select soft detect(1/6) Dies ist eine Bool-Testoption, welche die Fähigkeiten "soft select" und "soft detect" (und "advanced") hat. Also eine ganz normale Bool-Option.(1/6) Int(1/6) Int-Testoption ohne Einheit und Beschränkung.(2/3) Fixed constraint range(2/3) Fixed-Testoption mit der Einheit "Mikrosekunde" und einer Bereichsbeschränkung. Das Minimum ist -42.17, das Maximum 32767.9999, und die Schrittweite ist 2.0.(2/3) String constraint string list(2/3) String-Testoption mit einer Stringlisten-Beschränkung.(2/6) Bool hard select soft detect(2/6) Dies ist eine Bool-Testoption, welche die Fähigkeiten "hard select" und "soft detect" (und "advanced") hat. Das bedeutet, dass die Option nicht vom Frontend geändert werden kann, sondern vom Benutzer (z. B. indem er einen Knopf am Gerät drückt).(2/6) Int constraint range(2/6) Int-Testoption mit der Einheit "Pixel" und einer Bereichsbeschränkung. Das Minimum ist 4, das Maximum 192, und die Schrittweite ist 2.(3/3) Fixed constraint word list(3/3) Fixed-Testoption ohne Einheit und mit einer Wortlisten-Beschränkung.(3/3) String constraint long string list(3/3) String-Testoption mit einer Stringlisten-Beschränkung. Enthält ein paar mehr Einträge...(3/6) Bool hard select(3/6) Dies is eine Bool-Testoption, welche die Fähigkieten "hard select" (und "advanced") hat. Das bedeutet, dass die Option nicht vom Frontend geändert werden kann, sondern vom Benutzer (z. B. indem er einen Knopf am Gerät drückt). Außerdem kann sie nicht vom Frontend gelesen werden.(3/6) Int constraint word list(3/6) Int-Testoption mit der Einheit "Bits" und einer Wortlisten-Beschränkung.(4/6) Bool soft detect(4/6) Die ist eine Bool-Testoption, welche die Fähigkeiten "soft detect" (und "advanced") hat. Das heißt, dass dies eine Nur-Lese-Option ist.(4/6) Int array(4/6) Int-Testoption mit der Einheit "mm" und einem Feld ohne Beschränkung.(5/6) Bool soft select soft detect emulated(5/6) Dies ist eine Bool-Testoption, welche die Fähigkeiten "soft select", "soft detect", und "emulated" (und "advanced") hat.(5/6) Int array constraint range(5/6) Int-Testoption mit der Einheit "dpi" und einem Feld mit einer Bereichsbeschränkung. Das Minimum ist 4, das Maximum 192, und die Schrittweite ist 2.(6/6) Bool soft select soft detect auto(6/6) Dies ist eine Bool-Testoption, welche die Fähigkeiten "soft select", "soft detect", und "automatic" (und "advanced") hat. Diese Option kann vom Backend automatisch gesetzt werden.(6/6) Int array constraint word list(6/6) Int-Testoption mit der Einheit "Prozent" und einem Feld mit einer Wort-Beschränkung.1/2 Normalgeschwindigkeit1/3 Normalgeschwindigkeit10mm15mm16 Bit Graustufen2 Pixel20mm2x2 benutzerdefiniert2x2 normal3x3 benutzerdefiniert3x3 normal4 Pixel48 Bit Farbe4x4 grob4x4 benutzerdefiniert4x4 fein4x4 normal5x5 grob5x5 benutzerdefiniert5x5 fein6x4 (Zoll)6x6 benutzerdefiniert6x6 grob8-Bit-Ausgabe8 Pixel8.5x11 (Zoll)8x10 (Zoll)8x8 Bayer8x8 Vertikale Linie8x8 grob8x8 benutzerdefiniert8x8 fein8x8 normal8x8 sehr feinBei einer längeren Belichtungszeit kann der Scanner mehr Licht auffangen. Empfohlene Werte: 175% für Fotos, 150% für normale Dias und "Negativ" für Negativ-Filme. Für dunkle (unterentwickelte) Bilder kann dieser Wert vergrößert werden.A4A5 querA5 hochADFAutomatischer Dokumenteneinzug hintenADF-DuplexAutomatischer Dokumenteneinzug vorneADF-ModusADF WartezeitAbdeckung des automatischen Einzuges offenPapierstau im automatischem EinzugDer Zugriff auf die Ressource wurde abgelehntErhöhe den Blauanteil basierend auf dem GrünwertErhöhe den Blauanteil basierend auf dem RotwertErhöhe den Grünanteil basierend auf dem BlauwertErhöhe den Grünanteil basierend auf dem RotwertErhöhe den Rotanteil basierend auf dem BlauwertErhöhe den Rotanteil basierend auf dem GrünwertErweitertErweiterte OptionenBeginne mit dem Scannen erst, wenn nach dem Senden des Scankommandos der Knopf am Scanner gedrückt wird.Alle SeitenSchaltet die Lampe immer während der Schwarzkalibrierung aus.Analoge VerstärkungAnalog FrontendAnaloger Gammawert BlauAnaloge GammakorrekturAnaloger Gammawert GrünAnaloger Gammawert RotAnaloge Gammakorrektur.Analoge Gammakorrektur für Blau.Analoge Gammakorrektur für Grün.Analoge Gammakorrektur für Rot.AutoAutomatischer SchwellwertAutomatische Auswahl des ScanbereichsAutomatischer AuswurfAutomatische BelichtungAutomatischer FokusAutomatischen Fokus nur einmal aktivierenAutomatikAutom. DokumenteneinzugAutomatische schwarz/weiß - SchwelleAutomatische TrennungAutomatischer SchwellwertAutomatisches AufwärmenWirft den Film automatisch nach jedem Scannen aus dem Gerät ausDen Film automatisch aus dem Gerät auswerfen bevor das Programm schließtLegt automatisch Helligkeit, Kontrast, Weißwert, Gamma, Rauschunterdrückung und Bildgewichtung festHintenBacktrack-ZeilenFarbbalance-Faktor für Blau: 100% bedeutet keine FarbkorrekturFarbbalance-Faktor für Grün: 100% bedeutet keine FarbkorrekturFarbbalance-Faktor für Rot: 100% bedeutet keine FarbkorrekturSchachtBayerBayer Halbton 16Bayer Halbton 642 Level schwarz/weiss (Strichzeichnungs Modus)Verbinde RGBVerbinde X- und Y-AuflösungVerbinde analoge GammawerteVerbinde GammawerteBittiefeSchwarzWert für SchwarzBlauBlau - BalanceHelligkeit des BlauwertsVerstärkung blauer KanalVerstärkung blauer Kanal des AD-Wandlers.Intensität BlauAusschaltzeitpunkt blaue LampeOffset blauer KanalOffset blauer Kanal des AD-Wandlers.Bool-TestoptionenUnten nach obenRechtsRechte Kante des zu scannenden Bereichs.UntenUntere Kante des zu scannenden Bereichs.HelligkeitEingebautes CCT-ProfilKnopf 1Knopf 2Schalter StatusButton-TestoptionenScanen auf KnopfdruckKnöpfeCDFehler bei der CPU-ÜberprüfungRöhrenmonitorCRT-MonitoreBeleuchtungszeit zum KalibrierenBeleuchtungszeit zum Kalibrieren von BlauBeleuchtungszeit zum Kalibrieren von GrünBeleuchtungszeit zum Kalibrieren von RotLichtwert für KalibrierungKalibrierungScanner kalibrierenVor dem nächsten Scan kalibrierenFocus der Linse auf dem Dokument kalibrierenKalibriert Schwarz- und Weisswert.KalibrierungSoftware - KalibrierungKalibrierungsdatenspeicherKalibrierungs ModusJetzt kalibrierenAbbrechen-KnopfDokument wechseln.Dokument wechselnVerändert die Intensität der mittleren FarbtöneFarbkanalChipsatz-IDName des ChipsatzesKalibrierung zurücksetzenLöscht den KalibrierungsspeicherGrobGrobkalibrierungGrobkalibrierung nur für ersten ScanDie Grobkalibrierung wird nur für den ersten Scan durchgeführt. Das funktioniert mit den meisten Scannern und kann einiges an Scanzeit sparen. Wenn die Helligkeit der Bilder von Scan zu Scan schwankt, sollte diese Option ausgeschaltet werden. Nur für Testzwecke.FarbeFarbe (48 Bit)Farbe 36Farb-HalbtonFarb-StrichzeichnungFarbmatrixFarbe RAWFarbe RGBFarbe RGB TEXTFarbbalanceFarbkanal VerstärkungseinstellungenEinstellungen des Offsets der FarbkanäleFarbkorrekturFarbkorrekturkoeffizientenFarbmusterFarbe 24Farbe36Farbe 48Farbzeilen pro LesevorgangBedingtFortfahrenKontrastKontrast der blauen KomponenteKontrast der grünen KomponenteKontrast der grünen KomponenteLegt den Blauwert festLegt den den Grünanteil festLegt den Rotanteil festLegt den Farbwert (Blauwert) des gescannten Bildes fest.Stellt die Helligkeit des Bildes ein.Stellt die Helligkeit der blauen Komponente des gescannten Bildes ein.Stellt die Helligkeit der grünen Komponente des gescannten Bildes ein.Stellt die Helligkeit der roten Komponente des gescannten Bildes ein.Stellt den Kontrast des Bildes ein.Stellt den Kontrast der blauen Komponente des gescannten Bildes ein.Stellt den Kontrast der grünen Komponente des gescannten Bildes ein.Stellt den Kontrast der roten Komponente des gescannten Bildes ein.Legt fest, dass Backtracking verwendet wird.Kopieren-KnopfKorrektur entsprechend des FilmtypsKorrektur entsprechend des SeitenverhältnissesAbdeckung offenBenutzerdefiniertBenutzerdefinierte Farbmatrix für Graustufenscans.Benutzerdefinierte Farbmatrix.DTCOptionen zur FehlersucheStandardeinstellungDefaulteinstellungenKalibriermodus definierenBestimmt die Beleuchtungszeit für die Kalibrierung der blauen Komponente.Bestimmt die Beleuchtungszeit für den Scan der blauen Komponente.Bestimmt die Beleuchtungszeit für die Kalibrierung.Bestimmt die Beleuchtungszeit für die Kalibrierung der grünen Komponente.Bestimmt die Beleuchtungszeit für den Scan der grünen Komponente.Bestimmt die Beleuchtungszeit für die Kalibrierung der roten Komponente.Bestimmt die Beleuchtungszeit für den Scan der roten Komponente.Bestimmt die Beleuchtungszeit für den Scan.Definiere die Lichtwerte beim Kalibrieren.Definiere die Lichtwerte beim Scannen.Definiert den Ausschaltzeitpunkt der blauen Lampe.Definiert den Ausschaltzeitpunkt der grünen Lampe.Definiert den Ausschaltzeitpunkt der roten Lampe.Definiert die für den Scanvorgang zu verwendende Halbton-Matrix.Definiert den Vergrösserungsfaktor, der vom Scanner benutzt wirdVerzögere die Datenübertragung durch die Pipe.Dichte EinstellungLegt die Scangeschwindigkeit fest.Bestimmt ob die scannerinterne oder eine benutzerdefinierte Gammatabelle verwendet wird.Gerät nicht bereitGeräteeinstellungenDiamantDiffusionAutomatischen Dokumenteinzug abschalten und nur Flachbett benutzenkein Backtrackingdynamische Strichzeichnung abschaltenGammakorrektur abschaltenInterpolation abschaltenPre-Focus ausschaltenWeißabgleichskorrektur abschaltenDispersedDot16x16DispersedDot8x8Zeige eine kurze Auflösungsliste anHalbtonDithering A (4x4 Bayer)Dithering B (4x4 Spiral)Dithering C (4x4 Net Screen)Dithering D (8x4 Net Screen)Halbton schwarz/weiss (Halbton Modus)Halbtonmuster 1Halbtonmuster 2Führe einen Graustufen-Scan statt eines Farb-Scans durchFühre einen Qualitätsweißabgleich durch.Auto-Fokus nur einmal zwischen den AuswürfenFocus nicht kalibrierenKeinen Statuscode erzwingenZwinge das Backend nicht dazu, einen Statuscode zurückzuliefern.Automatischer DokumenteinzugAutomatischer DokumenteinzugAutomatischer Dokumenteinzug blockiertAutomatischer Dokumenteinzug leerVerdoppelte optische AuflösungÜbertrage Muster AÜbertrage Muster BBlindfarbeDuplexDuplexscanDuplex Scan ermöglicht das Scannen der Vorder- und Rückseite eines Dokuments.Dauer der Leseverzögerung.Dynamische Schwellwertkurve, von hell zu dunkel, nomalerweise 50-65auswerfenAuswurf des Dokuments nach dem ScannenFilm nach jedem Scannen auswerfenFilm vor Beenden auswerfenFilm jetzt auswerfenFilm *jetzt* auswerfenWirft das Blatt aus dem automatischen Dokumenteinzug ausE-Mail-KnopfGraustufen emulierenSchalte Duplex- (zweiseitiges) Scannen einSchaltet die automatische Bestimmung des Schwellwerts für den Schwarz-Weiß-Modus ein.Ermögliche Einstellung der Beleuchtungszeiten.Ermögliche Auswahl der Lichtwerte.Test-Optionen einschaltenSchalte verschiedene Testoptionen ein. Mit diesen Optionen kann man die Fähigkeit des Frontends feststellen, die verschiedenen Typen von SANE-Optionen darzustellen und zu ändern.Aktiviere/Deaktiviere automatischen Fokus Aktiviert/Deaktiviert die automatische BelichtungSchaltet Kalibrierungsdatenspeicher ein oder aus.Schaltet Sensorbeschleunigung an oder ab.Ende der Datei ist erreichtBlau verstärkenGrün verstärkenRot verstärkenFarbverbesserungFehlerstreuung Copy text Fehler während der Datenübermittlung des GerätsTausche das untere und das obere Byte der Bilddaten im 16-Bit-Modus aus. Diese Option kann dazu benutzt werden, den 16-Bit-Modus der Frontends zu testen, beispielsweise um festzustellen, ob das Frontend die richtige Endianness verwendet.Kalibrierung *jetzt* ausführenExperimentBelichtungszeitLampenausschaltzeit verlängernVerländert die Lampenausschaltzeit (von 15 Minuten bis 1 Stunde)Besonders schnellErweiterte FarbeinstellungenExtrasSchnellSchneller GraumodusSchnelle VorschauHohe GeschwindigkeitSchnellSehr schnellFax-KnopfEinzugsmodusDatei-KnopfDateinameFilmtypFilm-StreifenFeinStandard - BalanceErster EintragFeste Focus-PositionFixed-TestoptionenFlachbettNur FlachbettFokusFokus 2.5mm über dem GlasFokus PositionFokus auf dem GlasErzwinge BacktrackingVorschauscan in grauerzwinge echte TiefeErzwinge Scannerkalibrierung vor dem ScannenZwinge das Backend dazu, nach einem Aufruf von sane_read() den Statuscode SANE_STATUS_ACCESS_DENIED zurückzuliefern.Zwinge das Backend dazu, nach einem Aufruf von sane_read() den Statuscode SANE_STATUS_COVER_OPEN zurückzuliefern.Zwinge das Backend dazu, nach einem Aufruf von sane_read() den Statuscode SANE_STATUS_EOF zurückzuliefern.Zwinge das Backend dazu, nach einem Aufruf von sane_read() den Statuscode SANE_STATUS_IO_ERROR zurückzuliefern.Zwinge das Backend dazu, nach einem Aufruf von sane_read() den Statuscode SANE_STATUS_JAMMED zurückzuliefern.Zwinge das Backend dazu, nach einem Aufruf von sane_read() den Statuscode SANE_STATUS_NO_DOCS zurückzuliefern.Zwinge das Backend dazu, nach einem Aufruf von sane_read() den Statuscode SANE_STATUS_NO_MEM zurückzuliefern.Vom PapierVom KalibrierungstreifenVorneWarten auf vorderen KnopfKompletter ScanUngenaue ParameterVerstärkungGammaGammakorrekturGammatabellenGammakorrekturDie Gammakorrektur wird abgeschaltetGamma-ExponentGammawertGamma-Korrekturtabelle für die blaue Komponente.Gamma-Korrekturtabelle für die grüne Komponente.Gamma-Korrekturtabelle für die rote Komponente.Gamma-Korrekturtabelle. Im Farbmodus wirkt sich diese Option auf die rote, grüne und blaue Farbkomponente aus. Es ist also eine Helligkeits-Gammatabelle.ScanbereichGeometrieKorngrößeGraustufenVerstärkung grauer KanalGraustufen-FarbeOffset grüner KanalGrau 16Grau 8Graustufen4 Bit Graustufen8 Bit GraustufenGraustufen-ScanGrünGrün - BalanceHelligkeit des GrünwertsVerstärkung grüner KanalVerstärkung grüner Kanal des AD-Wandlers.Intensität GrünAusschaltzeitpunkt grüne LampeOffset grüner KanalOffset grüner Kanal des AD-Wandlers.Graustufenzeilen pro LesevorgangGitterHalbtonHalbton A (hart)Halbton B (weich)Halbton CHalbton Punkt 32Halbton Punkt 64Halbton-MatrixGröße der Halbton-MatrixHalbtonmodusHalbton nicht unterstütztHandscanner SimulationHandscanner-Simulationhardwareinterne X-Position des Scanbereichshardwareinterne Y-Position des ScanbereichsHardwareauflösungHardware-spezifische OptionenHochDrucken mit hohem KontrastDrucken mit hoher AuflösungHohe Qualität bei geringer GeschwindigkeitHohe Geschwindigkeit bei geringerer QualitätLichtLicht BlauLicht GrünLicht RotHalter Focus Position 0mmHorizontalhorizontal breithorizontal schmalLegt fest, wie lange nach der Übertragung eines Datenpuffers durch die Pipe gewartet wird.FarbtonFalls der automatische Vorlageneinzug ausgewählt ist, meldet der Einzug "leer" nach 10 Scans.Bei einem Strichzeichnungsscan versucht die Software einen optimalen Wert für die schwarz/weiß- Schwelle zu bestimmeneinige Scanner benötigen eine Kalibrierung durch die Software, sonst entstehen senkrechte Streifen im Bildwenn aktiviert, erfolgt kein Rücklauf des Scankopfes während der DatenübertragungFalls verwendet, wird das Bild im Farbmodus gescannt und dann per Software in Graustufen umgewandelt. Unter manchen Umständen verbessert dies die Bildqualität.Ist diese Option eingeschaltet, dann wird während der Kalibrierung nur die Shading-Korrektur durchgeführt. Andere Kalibrierungswerte werden aus der Konfigurationsdatei oder aus den Voreinstellungen des Backends übernommen.Wenn aktiviert werden einige Bilder im Scanprozess gespeichert um sie zu analysieren.Wenn diese Option eingeschaltet ist, wird vor dem nächsten Scan eine Kalibrierung durchgeführt. Ansonsten findet die Kalibrierung nur vor dem ersten Scan statt.Falls Gamma verwendet wird, werden Scans mit einer Farbtiefe von 16 Bit ausgeführt und danach in die gewählte Farbtiefe umgewandelt, um die Bildqualität zu verbessern. Diese Option verhindert Farbtiefen-Emulation.Kalibrierung ignorierenBildBildkorrekturBildfarben werden invertiertBildgewichtungBildintensitätOptionen für BildbearbeitungNadeldruckerBenutze die gleichen Wert für alle Farben im RGB Modus.Vergrößere oder verkleinere die analoge Verstärkung des CCD-SensorsInformationInfrarotTintenstrahldruckerInt-TestoptionenUngültiges ArgumentKehre Endianness umJPEGDie Lampe ist nicht bereit, bitte wiederholenLampe ausLampe beim Beenden ausschaltenLampe aus während SchwarzkalibrierungLampenausschaltzeitLampenausschaltzeit (Minuten).Lampe anLampenstatusLampenausschaltzeitLampenausschaltzeitLampenausschaltzeit in Sekunden.LampenschalterLinse auf Dokument kalibrierenMal sehen, ob das Frontend damit umgehen kann.LetterBegrenzt die Menge an Daten, die mit jedem Aufruf von sane_read() übertragen wird.StrichzeichnungBild in Graustufen laden.Pixelverlust pro ZeileNiedrigDrucken mit geringer AuflösungManuelle Einstellung des FokusManueller Pre-FocusLampe(n) ein-/ausschalten.Matritzenmultiplikation der RGB-WerteMaximalMediumMittelHandhabung der MedienMittelgrauwertMittelwert für BlauMittelwert für GrünMittelwert für RotAnzahl der Minuten, bis die Lampe nach dem Scan ausgeschaltet wirdHorizontal spiegelnBild spiegelnBild horizontal spiegeln.Bild vertikal spiegeln.Bild horizontal spiegelnDas Bild spiegelnVertikal spiegelnVerschiedenesModus 1Modus 2Modus 3Graue FarbmatrixMulti-Level RGB Farbe (ein-Pass-Farbe)Multi-Level schwarz&weiss (Graustufen Modus)NTSC GrauNTSC RGBbenötigt KalibirierungNegativFilmnegativDianegativNegativfilm FarbeNegativfilmNegativ FilmtypNegativfilm GraustufenNegativeKeine KorrekturKeine TransparenzkorrekturRauschunterdrückungKeinNormalNormalgeschwindigkeitAnzahl der Bits pro Farbwert, typische Werte sind 1 für Lineart- und 8 für Multibit-ScansAnzahl der Zeilen, die der Scanschlitten zurückfährt, wenn Backtracking auftritt. Das passiert, wenn der Scanner schneller scant, als der Computer die Daten aufnehmen kann. Niedrigere Werte sorgen für schnellere Scans, erhöhen jedoch das Risiko, Zeilen zu überspringen.Anzahl der OptionenAnzahl der Zeilen, die pro SCSI Lesevorgang angefordert werden. Eine Änderung dieses Parameters erlaubt die Feineinstellung der Geschwindigkeit, mit der Daten vom Scanner gelesen werden. Wenn die Geschwindigkeit zu niedrig ist, muss der Scanner in regelmäßigen Abständen mitten im Scanvorgang anhalten. Falls sie zu groß ist, reagiert die Scan-Anwendung möglicherweise nicht mehr auf Eingaben und das System kann unbenutzbar werden.Nummer des zu scannenden BildesOCR-KnopfAusBiete einen Select-Dateideskriptor an, damit das Frontend erkennen kann, ob sane_read() Daten zurückliefern würde.Biete Select-Dateideskriptor anOffsetAnEine SeiteNur Shading-Korrektur durchführenOperation nicht unterstütztOperation wurde abgebrochenOptionales ZubehörNicht genügend SpeicherPDF-KnopfSeitenhöheSeite geladenSeitenbreitePapiergrößeUnverändertFührt einen Selbsttest des Scanners durchFührt Kalibrierung durchTatsächliche Größe des Papiers im ADFPositivFilmpositivDiapositivPositiv- oder NegativfilmEinschaltknopfVordefinierte EinstellungenVorschauVorschaumodusFotoGibt eine Liste aller Optionen aus.Gebe Optionen ausStellt Standardgrößen für Fotographien, bedruckte Seiten etc. zur Verfügung.Qualitäts-WeißabgleichHohe QualitätSchnellformatFehler bei der Arbeitsspeicher-ÜberprüfungFehler bei der ROM-ÜberprüfungZufallsmusterRohdatenLeseverzögerungLesebegrenzungNur-Lese-TestoptionNur-Lese-Option, die angibt, wieviele Optionen ein bestimmtes Gerät unterstützt.RotRot - BalanceHelligkeit des RotwertsVerstärkung roter KanalVerstärkung roter Kanal des AD-Wandlers.Intensität RotAusschaltzeitpunkt rote LampeOffset roter KanalOffset roter Kanal des AD-Wandlers.Reduziert das Rauschen einzelner PunkteAufsichtFordere einen Scan in Vorschauqualität an.Legt fest, dass alle Vorschauscans im Graustufenmodus durchgeführt werden. Bei einem Three-Pass-Scanner wird dadurch nur ein Pass benötigt, bei einem Single-Pass-Scanner wird der Speicherverbrauch und die Scanzeit verringert.Legt fest, dass alle Vorschau-Scans im schnellsten Modus (mit geringer Qualität) durchgeführt werden. Das kann ein Schwarzweißmodus oder ein Modus mit niedriger Auflösung sein.Chipsatz zurücksetzenScanner zurücksetzenScanner zurücksetzenSetzt die Daten des Chipsatzes zurückLiefere SANE_STATUS_ACCESS_DENIED zurückLiefere SANE_STATUS_COVER_OPEN zurückLiefere SANE_STATUS_EOF zurückLiefere SANE_STATUS_IO_ERROR zurückLiefere SANE_STATUS_JAMMED zurückLiefere SANE_STATUS_NO_DOCS zurückLiefere SANE_STATUS_NO_MEM zurückGebe ungenaue Werte für die Anzahl der Zeilen und die Bytes pro Zeile zurück, wenn sane_parameters() vor sane_start() aufgerufen wird.Rückgabewert von sane_readSCSI-ParitätsfehlerSDTCSättigungDebugging Bilder abspeichernGamma - ZahlenwertGamma - Wert für BlauGamma - Wert für GrünGamma - Wert für RotScanmodusScanmodusOptionen für den Scanbereich und für MedienformateScanknopfScanzählerBeleuchtungszeit zum ScannenBeleuchtungszeit zum Scannen von BlauBeleuchtungszeit zum Scannen von GrünBeleuchtungszeit zum Scannen von RotScanne im schnellen Graumodus (geringere Bildqualität).Lichtwert beim ScannenScan SeitenrandScanmodusScanauflösungScanquelleScangeschwindigkeitScanne den gesamten möglichen Scanbereich inklusive des Kalibrierungsstreifens. Vorsicht, keine zu große Länge auswählen. Nur für Testzwecke.Die Abdeckung des Scanners ist offenMechanik des Scanners für den Transport verriegeltScannermodellScanner-Sensoren und -KnöpfeZweiter EintragWähle den Schacht zum Scannen ausFilmtyp auswählenWähle die minimale Helligkeit, die als Weiß betrachtet werden soll.Wählt den Glättungs-Filter aus.Wählt den Filmtyp ausWählt die Art des Testbildes aus. Verfügbare Testbilder: Komplett schwarz: füllt das ganze Bild schwarz. Komplett weiß: füllt das ganze Bild weiß. Farbmuster: zeichnet verschiedene Farbmuster, die vom ausgewählten Modus abhängen. Gitter: zeichnet ein Schwarz-Weiß-Gitter mit einer Höhe und Breite der einzelnen Felder von jeweils 10 mm.Wählt den Scanmodus für die Vorschau aus. Vorschau in Graustufen ist normalerweise der beste Kompromiss aus Geschwindigkeit und Detailtreue.Legt den Rückgabewert von sane_read() fest. "Default" ist die normale Einstellung für's Scannen. Alle anderen Rückgabewerte dienen dazu, das Verhalten des Frontends festzustellen.Wählt das Testbild ausGamma - Wert für BlauGamma - Wert für GrünGamma - Wert für RotGibt einen Gamma - Zahlenwert anLegt die "Körnigkeit" des gescannten Bildes fest. Kleinere Werte ergeben schärfere Bilder.Wählt den ADF-Modus aus (einseitig/doppelseitig)Wählt die Helligkeit.Wählt den Farbkanal; "Master" bedeutet, dass alle Farben beeinflusst werdenWählt die Blindfarbe.Auswahl des Film-Typs (z. B. Negativ oder Dia)Wählt die korrigierte Gammakurve aus.Modus der Gammakorrektur.Wählt die Gammakorrektur aus einer Liste von vordefinierten Geräten aus oder eine benutzerdefinierte Tabelle, die in den Scanner geladen werden kannWählt den Halbton aus.Wählt den Typ des NegativfilmsWählt die Nummer des zu scannenden Bildes ausWählt den Scanmodus aus (z.B. Strichzeichnung, Grau oder Farbe).Legt die Scanquelle fest (wie z.B. Dokumenteneinzug).Legt die Scanquelle fest (wie z.B. Dokumenteneinzug). Die Scanquelle muss vor Scanmodus und Scanauflösung ausgewählt werden. Setzt die Einstellungen für Scanmodus und Scanauflösung zurück.Bestimmt, welcher Helligkeitswert der blauen Komponente als Schwarz angesehen werden soll.Bestimmt, welcher Helligkeitswert der blauen Komponente als Weiß angesehen werden soll.Bestimmt, welcher Helligkeitswert der blauen Komponente als "Weiß" angesehen werden soll.Bestimmt, welcher Helligkeitswert der grünen Komponente als Schwarz angesehen werden soll.Bestimmt, welcher Helligkeitswert der grünen Komponente als Weiß angesehen werden soll.Bestimmt, welcher Helligkeitswert der grünen Komponente als "Weiß" angesehen werden soll.Bestimmt, welcher Helligkeitswert als Schwarz angesehen werden soll.Bestimmt, welcher Helligkeitswert als Weiß angesehen werden soll.Bestimmt, welcher Helligkeitswert der roten Komponente als Schwarz angesehen werden soll.Bestimmt, welcher Helligkeitswert der roten Komponente als Weiß angesehen werden soll.Bestimmt, welcher Helligkeitswert der roten Komponente als "Weiß" angesehen werden soll.Legt fest, ob das Bild im Halbtonmodus (Dithering) gescannt wird.Bestimmt, welcher Helligkeitswert als 50% Blau angenommen wirdBestimmt, welcher Helligkeitswert als 50% Grau angenommen wirdBestimmt, welcher Helligkeitswert als 50% Grün angenommen wirdBestimmt, welcher Helligkeitswert als 50% Rot angenommen wirdLegt fest, welche SCanfarbe im Garustufen-Modus verwendet wird (Standardwert: Grün).SelbsttestSensorenStellt die Farbverbesserungseinstellungen (Helligkeit und Kontrast) auf Defaultwerte.Auf Voreinstellungen für Verbesserungen zurücksetzen.Dichte Einstellungsmodus setzenDefiniere BeleuchtungszeitDefiniere LichtwertLegt den Wert für die Schärfe fest.Setzt die Fokusposition des optischen System von Hand (Standard: 128).Legt die Reihenfolge der Frames festLegt die Reihenfolge der Frames im Three-Pass-Modus fest.Legt die Farbmatrix für den Scanner fest.Legt die Zeit (in Minuten) fest, nach der die Lampe ausgeschaltet wird.Legt den Typ des Mediums fest.Schaltet den UTA ein/ausLegt die Verstärkung des blauen Kanals festLegt den Offset des blauen Kanals festLegt die Verstärkung des grauen Kanals festLegt den Offset des grauen Kanals festLegt die Verstärkung des grünen Kanals festLegt den Offset des grünen Kanals festSchaltet die Lampe an/ausLegt die Verstärkung des roten Kanals festLegt den Offset des roten Kanals festSetzt die Farbbalance auf die vom Hersteller vorgegebenen WerteSetzt die Farbkorrekturtabelle für das ausgewählte AusgabegerätLegt den Einzugsmodus festSetzt den Fokus entweder auf das Glas oder 2.5mm darüberLegt den Gammawert für alle Kanäle fest.Bestimmt die horizontale Auflösung des Bildes.Wählt die Bildgewichtung.Legt die Auflösung des Bildes fest.Legt die Größe der für den Scanvorgang verwendeten Halbtonmatrix fest.Bestimmt die vertikale Auflösung des Bildes.Stelle Verstärkung und Versatz automatisch ein. Wenn dies Option ausgeschaltet ist, können die Parameter des AFE ("Analog Frontend") manuell eingestellt werden. Diese Option is standardmäßig an. Nur für Testzwecke.SchattenSchatten BlauSchatten GrünSchatten RotLichtwerteSchärfeSchärfeVerschiebt Blau nach GrünVerschiebt Blau nach RotVerschiebt Grün nach BlauVerschiebt Grün nach RotVerschiebt Rot nach BlauVerschiebt Rot nach GrünKurze AuflösungslisteZeigt den im Gerät verwendeten Chipsatz an.Zeigt die ID des Chipsatzes anZeigt die Anzahl der Scans anLampe ausschaltenSchalte Scannerlampe aus.EinseitigSimuliere einen Handscanner. Bei Handscannern steht meistens die Bildhöhe nicht von vornherein fest. Stattdessen geben sie eine Höhe von -1 zurück. Mit dieser Option kann man prüfen, ob das Frontend damit richtig umgehen kann.Simuliere einen Handscanner. Bei Handscannern steht meistens die Bildhöhe nicht von vornherein fest. Stattdessen geben sie eine Höhe von -1 zurück. Mit dieser Option kann man prüfen, ob das Frontend damit richtig umgehen kann.Simuliere einen Three-Pass Scanner, indem hintereinander je ein Frame für jede Grundfarbe übertragen wird. Die Reihenfolge ist grün-blau-rot.Simuliere einen Three-Pass-Scanner. Im Farbmodus werden drei Frames übertragen.Größe der LesebegrenzungAufwärmprozess überspringenDiaDiasLangsamLangsamSehr langsamGlattGlättenKomplett schwarzKomplett weißDateiauswahlOptionen für Zuführung, Modus und AuflösungSpezialoptionenSpezialoptionenLegt die Höhe der Medien fest.Legt die Breite des Mediums fest. Erforderlich für die automatische Zentrierung bei Einzelblatt-Scans.SensorbeschleunigungStandardStartet den Kalibrierungsprozess.Starte den Kalibrierungsprozess mit einem SpezialblattStatuscode SimulationStoppString-TestoptionenErfolgreichInvertiere die Farben, z.B. tausche Schwarz gegen Weiß.Die Durchlichteinheit (FAU, film adapter unit) an/ausschaltenSchaltet die Lampe an oder ausTMA-NegativeTMA-DiasScanzielTechnik zur TextverbesserungDie (maximale) Menge and Daten, die bei jedem Aufruf von sane_read() übertragen wird.Der Dateiname des zu ladenden Bildes.Die Lampe wird nach der angegebenen Zeit (in Minuten) ausgeschaltet. Ein Wert von 0 bedeutet, dass die Lampe nich ausgeschaltet wird.Die Anzahl der Pixel, die am Ende der Zeile ungenutzt sind.Der Sättigungsgrad steuert die Belichtung einesmit einer Kamera aufgenommenen Bildes. Höhere Werte sorgen für eine stärkere Belichtung.Der Scanner benötigt eine Kalibrierung für die momentanen EinstellungenThermische DruckerDies ist der sehr lange dritte Eintrag. Vielleicht weiß das Frontend, wie man ihn darstellen kann.Diese Option spiegelt den vorderen Scannerknopf wiederDiese Option zeigt den Zustand eines Scannerknopfes an.Diese Option spiegelt den Zustand der Scannerknöpfe wider.Bei der Benutzung des LIGHTLID 35 Durchlichtadapters wird während des Scans die Flachbett - Lampe ausgeschaltet um besseren Kontrast zu erreichenThree-Pass SimulationThree-Pass-SimulationSchwellwertSchwellwertkurveSchwellenwert für den StrichzeichnungsmodusLampe ein/ausschaltenSchaltet die Lampe des Flachbettscanners ein bzw. ausOben nach untenLinksLinke Kante des zu scannenden Bereichs.ObenObere Kante des zu scannenden Bereichs.DurchlichtDurchlichteinheitDurchlichtaufsatzTransparenzgradDurchlichtaufsatzSchalte die Lampe ausSchalte Lampe beim Beenden des Programms ausSchalte Scannerlampe ausSchalte Scannerlampe einSchaltet die Lampe sofort aus.VorlagentypUTA einUnbekanntAuswerfenDokument auswerfen.Medium nach dem Scannen auswerfenWirft das Medium nach dem Scan aus.Knopfstatus aktualisierenInformation aktualisierenOptionen aktualisierenOptionen aktualisieren.Aktualisiert alle Informationnen über das GerätBenutze 0mm Halter Focus Position anstatt 0.6mmBenutze BildzusammensetzungBenutze intern eine Frabtiefe von mehr als 8 Bit, extern aber nur 8 Bit.Verwende benutzerdefinierte GammatabelleBenutze die Linse, mit der die optische Auflösung verdoppelt wird.Nichtblockierendes IOVerwende nichtblockierndes IO für sane_read(), wenn das durch das Frontend unterstützt wird.Nur Hardwareauflösungen verwendenAlle Farben benutzen dieselbe Gammakorrektur.Benutze die gleichen Auflösungen für X und Y.Benutzung des LIGHTLID 35BenutzerdefiniertBenutzerdefiniert (Gamma=1.0)Benutzerdefiniert (Gamma=1.8)Benutzerdefiniertes CCT-ProfilVertikalvertikal breitWarte auf KnopfdruckWarten auf KnopfdruckWarte mit dem Scan aud das Drücken des vorderen Knopfes.Scannen beginnt erst mit KnopfdruckWarte solange, bis die Helligkeit der Lampe konstant ist anstatt einfach 40 Sekunden zu warten.Warte solange, bis die Helligkeit der Lampe konstant ist anstatt einfach 60 Sekunden zu warten.Lampe aufwärmenWärme die Lampe vor dem Scannen auf.Der Aufwärmprozess wird überspungenAufwärmzeitAufwärmzeit in Sekunden.Falls aktiviert startet der Scanprozess nicht automatisch. Zum Starten drücken Sie die Taste "SCAN" beim MP1500 oder "COLOR" bei anderen Modellen. Zum Abbrechen drücken Sie die Taste "GRAY".Der Scanner sucht während der Wartezeit (in Sekunden) nach einem Dokument, welches in den Scanschacht eingelegt wird.Wenn Graustufen oder Strichzeichnung verwendet wird, wählt diese Option die FarbeWenn Sie hohe Auflösungen verwenden, bei denen die horizontale Auflösung kleiner ist als die vertikale, schaltet dies die horizontale Interpolation ausWeißWeißwertWeißwert für BlauWeißwert für GrünWeißwert für RotWeißabgleichkorrektur wird abgeschaltetX-AuflösungXPAXPA GrauXPA RGBY-AuflösungVergrösserungFalsche Reihenfolge der BefehleFilmscannerFlachbettscannerHardwareüberprüfungsfehlervom Initiator bemerkte Fehlermeldung empfangenungültiger Teil der IDENTIFY NachrichtUngültiger Befehlsausführungs-CodeUngültiges Feld in CDBUngültiges Feld in der Parameterlisteungültige FehlernachrichtLampenfehlerLampe nicht stabilisiertKein Medium eingelegtkeine zusätzliche SinnesinformationX-AbstandY-AbstandOption nicht verbundenParameter von einem anderen Initator geändertFalsche Länge bei der ParameterlisteNetzschalter Reset / Bus-Gerät ResetWiederauswahlfehlerGerundete ParameterFehler beim Positionieren des ScannerkopfesEinzugsscannerZeitüberschreitungZu viele Fenster angegebenLampe der Durchlichteinheit defektPositionsfehler der Durchlichteinheit beim ScankopfDurchlichtaufsatzabschattungsfehlerunbekanntLUN nicht unterstütztWebcamsane-backends-1.0.27/po/pl.po0000664000175000017500000046576713110600537012640 00000000000000# Polish translation for SANE backend options # Copyright (c) 2002-2003 Piotr Gogolewski # Piotr Gogolewski , 2003-2005. # Jakub Bogusz , 2005-2010. msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.21\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2010-11-06 19:33+0100\n" "Last-Translator: Jakub Bogusz \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Liczba opcji" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Standardowe" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "KrawÄ™dzie obszaru skanowania" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Ulepszanie" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Zaawansowane" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Czujniki" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "PodglÄ…d" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Wymuszaj podglÄ…d czarnobiaÅ‚y" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Głębokość bitowa" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Tryb skanowania" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "PrÄ™dkość skanowania" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "ŹródÅ‚o skanowania" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Wymuszaj nawracanie" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Lewa" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Górna" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Prawa" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Dolna" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Rozdzielczość skanowania" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Rozdzielczość X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Rozdzielczość Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Szerokość strony" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Wysokość strony" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Użyj tablicÄ™ kolorów użytkownika" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "GÄ™stość obrazka" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Natężenie czerwieni" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Natężenie zieleni" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Natężenie błękitu" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Jasność" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Wielkość ziarna" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Tworzenie półtonów" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Poziom czerni" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Poziom bieli" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Poziom bieli dla czerwonego" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Poziom bieli dla zielonego" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Poziom bieli dla niebieskiego" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "CieÅ„" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "CieÅ„ dla czerwonego" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "CieÅ„ dla zielonego" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "CieÅ„ dla niebieskiego" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "ÅšwiatÅ‚o" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "ÅšwiatÅ‚o dla czerwonego" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "ÅšwiatÅ‚o dla zielonego" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "ÅšwiatÅ‚o dla niebieskiego" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "OdcieÅ„" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Nasycenie" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Nazwa pliku" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Rozmiar wzoru półcienia" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Wzór półcienia" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Zrównaj rozdzielczość w osi X i Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negatyw" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Kalibracja jakoÅ›ci" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Podwójna rozdzielczość optyczna" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Zepnij RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Próg" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analogowa korekcja gamma" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analogowa gamma czerwieni" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analogowa gamma zieleni" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analogowa gamma błękitu" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Zepnij analogowÄ… gammÄ™" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Rozgrzej lampÄ™" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Kal. czasu ekspozycji" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "dla czerwieni" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "dla zieleni" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "dla błękitu" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Czas ekspozycji" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Czas ekspozycji dla czerwonego" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Czas ekspozycji dla zielonego" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Czas ekspozycji dla niebieskiego" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Ustawia czas ekspozycji" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Kal. gÄ™stoÅ›ci lampy" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Skan gÄ™stoÅ›ci lampy" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Ustaw gÄ™stość lampy" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Wyłącz lampÄ™ przy wyjÅ›ciu" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "Opcja tylko do odczytu, mówiÄ…ca ile opcji wspiera dane urzÄ…dzenie." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Opecje źródÅ‚a, trybu i rozdzielczoÅ›ci" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Opcje obszaru skanowania i rozmiaru obiektu" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Opcje modyfikacji obrazu" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Opcje specyficzne dla sprzÄ™tu" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Czujniki i przyciski skanera" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Zażądaj skanu w jakoÅ›ci podglÄ…du." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Żądanie aby wszystkie podglÄ…dy byÅ‚y wykonywane w trybie " "monochromatycznym. W skanerze trójprzebiegowym ogranicza to liczbÄ™ " "przebiegów do jednego a na jednoprzebiegowym zmniejsza zapotrzebowanie " "na pamięć i czas pobierania podglÄ…du." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Ilość bitów na próbkÄ™; typowe wartoÅ›ci to 1 dla trybu kreski i 8 dla " "skanów kolorowych i w skali szaroÅ›ci." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Ustawia tryb skanowania, np. tryb kreski, skala szaroÅ›ci lub kolorowy" #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "OkreÅ›la prÄ™dkość przy której postÄ™puje skanowanie." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Wybierz źródÅ‚o skanowania (np. podajnik)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Steruje wymuszaniem nawracania" #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Lewa krawÄ™dź skanowanego obszaru (górny lewy x)." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Górna krawÄ™dź skanowanego obszaru (górny lewy y)." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Prawa krawÄ™dź skanowanego obszaru (dolny prawy x)." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Dolna krawÄ™dź skanowanego obszaru (dolny prawy y)." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Ustawia rozdzielczość skanowanego obrazka." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Ustawia poziomÄ… rozdzielczość skanowanego obrazka." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Ustawia pionowÄ… rozdzielczość skanowanego obrazka." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "OkreÅ›la szerokość obiektu. Wymagane do automatycznego centrowania " "skanowania." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "OkreÅ›la wysokość obiektu." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "OkreÅ›la czy powinna być użyta wbudowana tabela gamma czy użytkownika" #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Tabela korekcji gamma. W trybie kolorowym ta opcja równomiernie wpÅ‚ywa " "na wszystkie kanaÅ‚y jednoczeÅ›nie (staje siÄ™ tabelÄ… intensywnoÅ›ci)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Tabela korekcji gamma dla pasma czerwieni" #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Tabela korekcji gamma dla pasma zieleni" #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Tabela korekcji gamma dla pasma błękitu" #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Ustawia jasność uzyskanego obrazka." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Ustawia kontrast uzyskanego obrazka." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Ustawia \"ziarnistość\" uzyskanego obrazka. Mniejsze wartoÅ›ci dadzÄ… " "ostrzejsze obrazki." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Ustawia czy uzyskany obrazek powinien być stonowany (ditherowany)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za \"czarny\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za \"biaÅ‚y\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci czerwieni ma być uznawany za \"biaÅ‚y" "\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci zieleni ma być uznawany za \"biaÅ‚y\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci błękitu ma być uznawany za \"biaÅ‚y\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci czerwieni ma być uznawany za \"czarny" "\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci zieleni ma być uznawany za \"czarny" "\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci błękitu ma być uznawany za \"czarny" "\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci czerwonego ma być uznawany jako " "czysty czerwony." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci niebieskiego ma być uznawany jako " "czysty niebieski." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci zielonego ma być uznawany jako " "czysty zielony." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Ustawia \"odcieÅ„\" (poziom błękitu) otrzymanego obrazja" #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Poziom nasycenia ustawia ilość \"wykwitu\" który ukazuje siÄ™, kiedy " "pobieramy obraz z kamery. WiÄ™ksze wartoÅ›ci powodujÄ… wiÄ™kszy wykwit." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Nazwa pliku, który ma zostać zaÅ‚adowany." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Ustawia rozmiar wzorca tonowania (ditheringu) używanego podczas " "skanowania tonowanych obrazków." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Definiuje wzorzec tonowania (ditheringu) dla skanowania tonowanych " "obrazków." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "" "Użyj tych samych wartoÅ›ci dla rozdzielczoÅ›ci w osi X i Y (poziomie i " "pionie)" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "ZamieÅ„ czarny z biaÅ‚ym" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Przeprowadź jakoÅ›ciowÄ… kalibracjÄ™ biaÅ‚ego" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Użyj soczewek które podwajajÄ… rozdzielczość optycznÄ…" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "W trybie RGB użyj tych samych wartoÅ›ci dla każdego koloru" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Wybierz minimalnÄ… jasność by uzyskać biaÅ‚y punkt" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analogowa korekcja gamma" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analogowa korekcja gamma dla czerwieni" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analogowa korekcja gamma dla zieleni" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analogowa korekcja gamma dla niebieskiego" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Rozgrzej lampÄ™ przed skanowaniem" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Ustawia czas ekspozycji dla kalibracji" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Ustawia czas ekspozycji dla kalibracji czerwonego" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Ustawia czas ekspozycji dla kalibracji zielonego" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Ustawia czas ekspozycji dla kalibracji niebieskiego" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Ustawia czas ekspozycji dla skanowania" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Ustawia czas ekspozycji dla skanowania czerwonego" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Ustawia czas ekspozycji dla skanowania zielonego" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Ustawia czas ekspozycji dla skanowania niebieskiego" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Włącz wybór czasu ekspozycji" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Ustaw gÄ™stość lampy do kalibracji" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Ustaw gÄ™stość lampy do skanowania" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Włącz wybór gÄ™stoÅ›ci lampy" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Wyłącz lampÄ™ przy wyjÅ›ciu z programu" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Przycisk skanowania" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "Przycisk E-maila" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Przycisk faksu" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Przycisk kopiowania" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "Przycisk PDF" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Przycisk anulowania" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Strona wÅ‚ożona" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Pokrywa otwarta" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Kolor" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Kolorowy tryb kreski" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Kolorowy tryb półcieni" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Skala szaroÅ›ci" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Półtony" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Tryb kreski" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "Sukces" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Operacja nieobsÅ‚ugiwana" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "Operacja anulowana" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "UrzÄ…dzenie zajÄ™te" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Błędny argument" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "OsiÄ…gniÄ™to koniec pliku" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Zakleszczenie podajnika dokumentów" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "Koniec dokumentów w podajniku" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "Pokrywa skanera jest otwarta" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Błąd podczas operacji we/wy" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Brak pamiÄ™ci" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "Brak dostÄ™pu do zasobu" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "Lampa nie gotowa, proszÄ™ spróbować powtórnie" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "Mechanizm skanera zablokowany w celu transportu" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "WartoÅ›ci domyÅ›lne" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Ustaw domyÅ›lne wartoÅ›ci ustawieÅ„ ulepszania" #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibracja" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Kalibruj przed nastÄ™pnym skanowaniem" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "JeÅ›li jest zaznaczone, urzÄ…dzenie bÄ™dzie kalibrowane przed nastÄ™pnym " "skanowaniem. W innym przypadku kalibracja zostanie wykonana przed " "pierwszym przebiegiem" #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Przeprowadź tylko korektÄ™ cieniowania" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Jeżeli włączone, tylko korekcja cieniowania jest przeprowadzana w czasie " "kalibracji. DomyÅ›lne sÄ… używane wartoÅ›ci dla wzmocnienia offsetu i czasu " "ekspozycji wbudowane lub z pliku konfiguracyjnego" #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Stan przycisku" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Numer ramki do skanowania" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Wybiera numer ramki do skanowania" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Skanowanie dwustronne" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "Skanowanie dwustronne pozwala na skanowanie przedniej i tylnej strony " "dokumentu" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Kalibruj Skaner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "WymuÅ› kalibracjÄ™ przed skanowaniem" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Skanowanie w odcieniach szaroÅ›ci" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Skanuj raczej w odcieniach szaroÅ›ci niż w kolorze" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Wzmocnienie analogowe" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "ZwiÄ™ksz lub zmniejsz wzmocnienie analogowe matrycy CCD" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Korekcja Gamma" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Wybiera poprawionÄ… krzywÄ… przejÅ›cia" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Surowy" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Dobry kolor" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Brak korekcji dla klisz" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Korekcja zgodna z rodzajem filmu" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Korekcja zgodna ze współczynnikiem przezroczystoÅ›ci" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negatywy" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Slajdy" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatycznie" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "ZwykÅ‚a prÄ™dkość" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 zwykÅ‚ej prÄ™dkoÅ›ci" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 zwykÅ‚ej prÄ™dkoÅ›ci" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "parametr zaokrÄ…glony" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "nieznany" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "zakleszczenie ADF" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "pokrywa ADF otwarta" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "awaria lampy" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "błąd pozycjonowania gÅ‚owicy skanera" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "błąd kontroli CPU" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "błąd kontroli RAM" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "błąd kontroli ROM" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "błąd kontroli sprzÄ™tu" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "awaria lampy do skanowania przezroczy" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "błąd pozycjonowania gÅ‚owicy do skanowania przezroczy" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "błąd dÅ‚ugoÅ›ci listy parametrów" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "błędny kod operacji" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "błędne pole w CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "nieobsÅ‚ugiwany LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "błędne pole w liÅ›cie parametrów" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "błąd sekwencji poleceÅ„" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "podano zbyt dużo okien" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "brak noÅ›nika" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "błędny komunikat bitowy IDENTIFY" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "opcja nie podłączona" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "reset po włączeniu zasilania / reset szyny" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parametr zmieniony przez inny inicjator" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "brak dodatkowej informacji o stanie" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "niepowodzenie ponownego wyboru" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "błąd parzystoÅ›ci SCSI" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "otrzymano komunikat błędu wykryty przez inicjator" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "błędny komunikat" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "błąd przekroczenia czasu" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "błąd cieniowania moduÅ‚u do skanowania przezroczy" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lampa nie ustabilizowana" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "skaner filmów" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "skaner pÅ‚aski" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Rodzaj filmu" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Wybór rodzaju filmu, np. negatywów lub slajdów" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Rodzaj negatywu" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Wybór rodzaju negatywu" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Rozdzielczość sprzÄ™towa" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Użycie tylko rozdzielczoÅ›ci sprzÄ™towych" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Ostrość" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Ostrość automatyczna" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Włączenie/wyłączenie automatycznego ustawiania ostroÅ›ci" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Jednokrotny autofocus" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Automatyczne ustawianie ostroÅ›ci tylko po wymianie noÅ›nika" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "RÄ™czne ustawianie ostroÅ›ci" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "RÄ™czne ustawianie pozycji ostroÅ›ci optyki (domyÅ›lnie: 128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Marginesy skanowania" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Dodatkowe ustawienia kolorów" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Odbicie lustrzane obrazka" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Poziome odbicie lustrzane obrazu" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Ekspozycja automatyczna" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Włączenie/wyłączenie automatycznego wyboru ekspozycji" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Kalibruj teraz" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Uruchomienie kalibracji *teraz*" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Autodiagnostyka" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Wykonanie autodiagnostyki skanera" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Reset skanera" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Zresetowanie skanera" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "ObsÅ‚uga medium" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "WysuÅ„ film po zeskanowaniu" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Automatyczne wysuwanie filmu z urzÄ…dzenia po każdym skanowaniu" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "WysuÅ„ film przed zakoÅ„czeniem" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Automatyczne wysuwanie filmu z urzÄ…dzenia przed zakoÅ„czeniem programu" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "WysuÅ„ film teraz" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "WysuniÄ™cie filmu *teraz*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Dodatkowy podajnik dokumentów" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Tylko pÅ‚yta" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" "Wyłączenie automatycznego podajnika dokumentów, używanie tylko pÅ‚yty" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "ModuÅ‚ do skanowania przezroczy" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "Włączenie/wyłączenie moduÅ‚u do skanowania przezroczy (FAU)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Negatyw" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Pozytyw lub negatyw" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Kontrola gÄ™stoÅ›ci" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Ustawienie trybu kontroli gÄ™stoÅ›ci" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Współczynnik przezroczystoÅ›ci" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Rodzaj filmu" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Wybór rodzaju filmu" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "PÅ‚yta" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "ADF przód" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "ADF tyÅ‚" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "ADF dwustronny" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Przód" #: backend/canon_dr.c:413 #, fuzzy, no-c-format msgid "Card Back" msgstr "TyÅ‚" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Dwustronny" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Czerwony" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Zielony" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Niebieski" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "Rozszerzenie czerwieni" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "Rozszerzenie zieleni" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "Rozszerzenie błękitu" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Brak" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "JPEG" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Jednostronny" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Dwustronny" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "ModuÅ‚ do skanowania przezroczy" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatyczny podajnik dokumentów" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Pozytyw" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negatyw" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Ostrość na szybie" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Ostrość 2.5mm powyżej szyby" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Półton A (Twardy)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Półton B (MiÄ™kki)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Półton C (Siatka)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Ziarnistość A (4x4 Bayera)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Ziarnistość B (4x4 Spiralna)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Ziarnistość C (4x4 Siatka)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Ziarnistość D (8x4 Siatka)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Technologia Uwydatniania Tekstu" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Pobierz wzór A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Pobierz wzór B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Brak korekcji" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Zdefiniowane przez użytkownika" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Drukarki igÅ‚owe" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Drukarki termiczne" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Drukarki atramentowe" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Monitory CRT" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "DomyÅ›lny" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Druk wysokiej gÄ™stoÅ›ci" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Druk niskiej gÄ™stoÅ›ci" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Druk o wysokim kontraÅ›cie" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Zdefiniowane przez użytkownika (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Zdefiniowane przez użytkownika (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 portret" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 krajobraz" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "List" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Maksimum" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Tryb skanowania" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Wybór półcieni" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Dropout" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Wybiera dropout" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Wybiera jasność" #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Ostrość" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Korekcja koloru" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "Ustawia tablicÄ™ korekcji koloru dla wybranego urzÄ…dzenia wyjÅ›ciowego." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Współczynnik korekcji koloru" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Macierz mnożenia RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "PrzesuÅ„ zieleÅ„ do czerwieni" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "PrzesuÅ„ zieleÅ„ do błękitu" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "PrzesuÅ„ czerwieÅ„ do zieleni" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "PrzesuÅ„ czerwieÅ„ do błękitu" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "PrzesuÅ„ błękit do zieleni" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "PrzesuÅ„ błękit do czerwieni" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Nadzoruje poziom zieleni" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Dodaje do czerwieni bazujÄ…c na poziomie zieleni" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Dodaje do błękitu bazujÄ…c na poziomie zieleni" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Dodaje do zieleni bazujÄ…c na poziomie czerwieni" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Nadzoruje poziom czerwieni" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Dodaje do błękitu bazujÄ…c na poziomie czerwieni" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Dodaje do zieleni bazujÄ…c na poziomie błękitu" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Dodaje do czerwieni bazujÄ…c na poziomie błękitu" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Nadzoruje poziom błękitu" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Utwórz odbicie lustrzane obrazka" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Szybki podglÄ…d" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Automatyczny podziaÅ‚ obszaru" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Krótka lista rozdzielczoÅ›ci" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "WyÅ›wietl krótkÄ… listÄ™ rozdzielczoÅ›ci" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "PowiÄ™kszenie" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Definiuje współczynnik powiÄ™kszenia dla skanera" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Szybkie formatowanie" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Wyposażenie opcjonalne" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "WysuÅ„" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "WysuÅ„ arkusz z ADF" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Wysuwanie automatyczne" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "WysuÅ„ dokument po zeskanowaniu" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Tryb ADF" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Wybiera tryb ADF (jedno/dwustronny)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "WnÄ™ka" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Wybierz wnÄ™kÄ™ do skanowania" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Wybiera wartość korekcji gamma z listy zdefiniowanych urzÄ…dzeÅ„ lub " "tabeli użytkownika, która może być zaÅ‚adowana do skanera" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Pozycja skupienia (ostroÅ›ci)" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "Ustawia skupienie (ostrość) na szybÄ™ lub 2.5mm powyżej szyby" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Czekaj na Przycisk" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Po wysÅ‚aniu komendy skanowania, czekaj aż przycisk na skanerze jest " "naciÅ›niÄ™ty, aby naprawdÄ™ rozpocząć skanowanie" #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "PodczerwieÅ„" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Pozytyw" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Negatyw" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "Wbudowany profil CCT" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "Profil CCT zdefiniowany przez użytkownika" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Włączony" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Wyłącz" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "DTC" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "SDTC" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Ditheruj" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "Dyfuzja" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "Biel" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "CzerÅ„" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Kontynuacja" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Stop" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10mm" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15mm" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20mm" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Poziomy" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "Poziomy pogrubiony" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "Poziomy cienki" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Pionowy" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "Pionowy pogrubiony" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "Od góry do doÅ‚u" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "Od doÅ‚u do góry" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "Przód" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "TyÅ‚" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Półtony" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Wykonuje kalibracjÄ™" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Emfaza obrazka" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Nasycenie" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "Włącz automatyczne rozpoznawanie progu dla skanów w trybie kreski." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Odbicie lustrzane obrazka" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Poziome, lustrzane odbicie obrazka." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Poziom bieli dla niebieskiego" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Nadzoruje poziom czerwieni" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Filtr kolorów" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "WygÅ‚adzanie" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Wartość gamma" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "Krzywa progowa" #: backend/fujitsu.c:3347 #, fuzzy, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "Dynamiczna krzywa progowa, od ciemnego do jasnego, zwykle 50-65" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Próg" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Redukcja szumów" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Brak korekcji" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Brak korekcji" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "pokrywa ADF otwarta" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Opcje zaawansowane" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Brak korekcji" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Dropout" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "tryb podajnika" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Czas wyłączania lampy" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Offset błękitu" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Offset zieleni" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Offset zieleni" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Offset błękitu" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Ustawienie offsetu kanaÅ‚u błękitu" #: backend/fujitsu.c:3980 #, fuzzy, no-c-format msgid "Low Memory" msgstr "Brak pamiÄ™ci" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Skanowanie dwustronne" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Opcje zaawansowane" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Redukcja szumów" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Od papieru" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Od papieru" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Od papieru" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Od papieru" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "Pokrywa skanera jest otwarta" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "RÄ™czne wstÄ™pne ustawianie ostroÅ›ci" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "RÄ™czne wstÄ™pne ustawianie ostroÅ›ci" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "błąd kontroli sprzÄ™tu" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Poziom bieli" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Kontrola gÄ™stoÅ›ci" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Kontrola gÄ™stoÅ›ci" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Skanowanie dwustronne" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Dodatki" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "Dynamiczna krzywa progowa, od ciemnego do jasnego, zwykle 50-65" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "Wyłączenie dynamicznego trybu kreski" #: backend/genesys.c:5844 #, fuzzy, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" "Wyłączenie użycia algorytmu adaptacyjnego do generowania linii zamiast " "polegania na trybie sprzÄ™towym" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Wyłącz interpolacjÄ™" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "Przy wysokich rozdzielczoÅ›ciach kiedy rozdzielczość pozioma jest " "mniejsza niż rozdzielczość pionowa, ta opcja wyłącza interpolacjÄ™ " "poziomÄ…." #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Filtr kolorów" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "W trybie szaroÅ›ci lub kreski ta opcja wybiera używany kolor." #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibracja" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Zdefiniuj tryb kalibracji" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Pamięć podrÄ™czna danych kalibracji" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Czas wyłączania lampy" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "Lampa zostanie wyłączona po podanym czasie (w minutach). Wartość 0 " "oznacza, że lampa nie bÄ™dzie wyłączana." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Wyłącz lampÄ™ podczas kalibracji ciemnoÅ›ci" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "Liczba minut do wyłączenia lampy po skanowaniu" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Przycisk pliku" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "Przycisk OCR" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Przycisk zasilania" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Przycisk E-maila" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "Wymaga kalibracji" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Skaner wymaga kalibracji dla obecnych ustawieÅ„" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Przyciski" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibracja" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Rozpocznij kalibracjÄ™ przy użyciu specjalnej kartki" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Wyczyść kalibracjÄ™" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Wyczyść pamięć podrÄ™cznÄ… kalibracji" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "ModuÅ‚ do skanowania negatywów" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Kolor trybu odcieni szaroÅ›ci" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Wybiera który kolor skanowania jest używany w trybie odcieni szaroÅ›ci " "(domyÅ›lnie: zielony)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Opcje odpluskwiania" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatyczne rozgrzewanie" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Rozgrzewaj dopóki jasność lampy bÄ™dzie staÅ‚a, zamiast przyjmować staÅ‚y " "czas 60 sekund." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "PeÅ‚ny ekran" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Skanuj caÅ‚y dostÄ™pny obszar, łącznie z paskiem kalibracyjnym. BÄ…dź " "ostrożny. Nie wybieraj peÅ‚nej wysokoÅ›ci. Opcja tylko do celów testowych" #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Kalibracja ziarnistoÅ›ci" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Ustaw wzmocnienie i offset dla skanowania automatycznego. Jeżeli ta " "opcja jest zablokowana, wówczas dostÄ™pne sÄ… opcje rÄ™cznego ustawiania " "parametrów analogowych. Ta opcja jest odblokowana domyÅ›lnie. Opcja tylko " "do testów." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Kalibracja ziarnistoÅ›ci tylko dla pierwszego skanu" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Kalibracja ziarnistoÅ›ci jest robiona tylko dla pierwszego przebiegu. " "DziaÅ‚a z wiÄ™kszoÅ›ciÄ… skanerów i pozwala zaoszczÄ™dzić czas. Jeżeli " "jasność obrazka jest różna za każdym skanem, wyłącz tÄ™ opcjÄ™. Opcja " "tylko dla testów." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Wymuszaj nawracanie" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Liczba linii o które powraca gÅ‚owica, gdy wystÄ…pi nawracanie. To siÄ™ " "zdarza gdy skaner skanuje szybciej niż komputer może odebrać dane. " "Niskie wartoÅ›ci mogÄ… powodować szybsze skanowanie lecz zwiÄ™kszajÄ… ryzyko " "pominiÄ™cia niektórych linii." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Wartość gamma" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Ustawia wartość gamma dla wszystkich kanałów" #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Grupa geometrii" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Grupa trybu skanowania" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Slajd" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Model skanera" #: backend/hp3900_sane.c:1408 #, fuzzy, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" "Umożliwia sprawdzenie zachowania urzÄ…dzenia z innymi obsÅ‚ugiwanymi " "modelami" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Kolory obrazu bÄ™dÄ… odwrócone" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Wyłącz korekcjÄ™ gamma" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "Korekcja gamma bÄ™dzie wyłączona" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Wyłącz korekcjÄ™ cieniowania bieli" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "Korekcja cieniowania bieli bÄ™dzie wyłączona" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "PomiÅ„ proces rozgrzewania" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "Proces rozgrzewania bÄ™dzie pominiÄ™ty" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "WymuÅ› prawdziwÄ… głębiÄ™" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "JeÅ›li korekcja gamma jest wyłączona, wszystkie skanowania bÄ™dÄ… wykonane " "z 16-bitowÄ… głębiÄ… w celu poprawy jakoÅ›ci obrazu, a nastÄ™pnie " "konwertowane do wybranej głębi. Ta opcja zapobiega emulacji głębi." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Emulacja skali szaroÅ›ci" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "JeÅ›li jest włączona, obraz bÄ™dzie skanowany w trybie kolorowym, a " "nastÄ™pnie konwertowany programowo do skali szaroÅ›ci. Może to poprawić " "jakość obrazu w pewnych przypadkach." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Zapisuj obrazy diagnostyczne" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "JeÅ›li jest włączona, obrazy uczestniczÄ…ce w dostrajaniu skanera sÄ… " "zapisywane w celu analizy." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Reset ukÅ‚adów" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Zresetowanie danych ukÅ‚adów" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Informacje" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Nazwa ukÅ‚adów" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Pokazuje nazwy ukÅ‚adów (chipsetu) użytych w urzÄ…dzeniu." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Nieznany" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "ID chipsetu" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Pokazuje ID chipsetu" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Licznik skanowaÅ„" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Pokazuje liczbÄ™ wykonanych skanowaÅ„" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Aktualizuj informacje" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Uaktualnia informacje o urzÄ…dzeniu" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Opcja ta odzwierciedla stan przycisku przedniego panelu skanera" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Obraz" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Różne" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "przesuniÄ™cie X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "WewnÄ™trzne sprzÄ™towe poÅ‚ożenie poziome (X) obszaru skanowania." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "przesuniÄ™cie Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "WewnÄ™trzne sprzÄ™towe poÅ‚ożenie pionowe (Y) obszaru skanowania." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Status lampy" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Włącza lub wyłącza lampÄ™." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Kalibruje poziom dla czerni i bieli." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMA - slajdy" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMA - negatywy" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Kolor (48 bitów)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "PowiÄ™ksz czas wyłączenia lampy" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "PowiÄ™ksza czas wyłączenia lampy (z 15 minut do 1 godziny)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Czekaj na przycisk" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Oczekiwanie na naciÅ›niÄ™cie przycisku przed skanowaniem" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Opcje zaawansowane" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Ziarnistość" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "DokÅ‚adny" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayera" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Użytkownika" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automatyczny" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Åšrodkowoprzepustowy" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "Skala szaroÅ›ci NTSC" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "Skala szaroÅ›ci XPA" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Powolny" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "ZwykÅ‚y" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Szybki" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Bardzo szybki" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-pikselowy" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-pikselowy" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-pikselowy" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Drukuj" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Pasek filmu" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Warunkowy" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Eksperyment" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Wyostrzanie" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Ustaw wartość wyostrzania." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Automatyczne progowanie" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "Włącz automatyczne rozpoznawanie progu dla skanów w trybie kreski." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Wybierz filtr wygÅ‚adzajÄ…cy." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "WysuÅ„ noÅ›nik po skanowaniu" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Wysuwa noÅ›nik po skanowaniu." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "ZmieÅ„ dokument" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "ZmieÅ„ Dokument." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "WysuÅ„" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "WysuÅ„ Dokument." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Rozpocznij proces kalibracji." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "NoÅ›nik" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Ustaw rodzaj noÅ›nika." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Czas ekspozycji" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "DÅ‚uższy czas ekspozycji pozwala gÅ‚owicy odebrać wiÄ™cej Å›wiatÅ‚a. " "Sugerowane jest 175% dla wydruków, 150% dla zwykÅ‚ych slajdów i \"Negatyw" "\" dla filmu negatywowego. Dla ciemnych (nie doÅ›wietlonych) obrazków " "możesz zwiÄ™kszyć tÄ™ wartość." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Matryca kolorów" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Ustaw matrycÄ™ kolorów skanera." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Matryca kolorów użytkownika" #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Monochromatyczna matryca kolorów" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Matryca kolorów użytkownika dla skanów w skali szaroÅ›ci." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Odbicie poziome" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Poziome, lustrzane odbicie obrazka." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Odbij pionowo." #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Pionowe, lustrzane odbicie obrazka." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Aktualizuj opcje" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Aktualizuj opcje." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8-bitowe wyjÅ›cie" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Użyj wewnÄ™trznie głębi wiÄ™kszej niż osiem bitów, lecz na wyjÅ›ciu daj " "równe osiem." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Oczekiwanie na przycisk panelu" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Czekaj ze skanowaniem na naciÅ›niÄ™cie przycisku na przednim panelu." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Wyłącz lampÄ™" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Wyłącz lampÄ™ skanera." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Rozmiar papieru" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatyczna separacja" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 krajobraz" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "Ustawienie trybu kontroli gÄ™stoÅ›ci" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "RÄ™czne wstÄ™pne ustawianie ostroÅ›ci" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "RÄ™czne wstÄ™pne ustawianie ostroÅ›ci" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Włącz skanowanie dwustronne" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Fizyczny rozmiar papieru w ADF" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Półtony" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Kolor" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Kontynuacja" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Wyłącz" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayera" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayera" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Półtony" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Półtony" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Dyfuzja" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "ZwykÅ‚y" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "ÅšwiatÅ‚o" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "skaner filmów" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Od papieru" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "DomyÅ›lny" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "WygÅ‚adzanie" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Powolny" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Åšredni" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Czerwony" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Zielony" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "ŹródÅ‚o skanowania" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "tryb podajnika" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Ustawia tryb podajnika" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Włączenie/wyłączenie automatycznego ustawiania ostroÅ›ci" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Ustawienie trybu kontroli gÄ™stoÅ›ci" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Ustawia tryb podajnika" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Ustawia tryb podajnika" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatyczne progowanie" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Automatycznie ustawia jasność, kontrast, poziom bieli, gammÄ™, redukcjÄ™ " "szumów i emfazÄ™ obrazka" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Redukcja szumów" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Zmniejsz szum izolowanych punktów" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Emfaza obrazka" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Ustawia emfazÄ™ obrazka" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Włącz lampÄ™" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Włącza lub wyłącza lampÄ™." #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Pionowe, lustrzane odbicie obrazka." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Korekcja gamma" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Druk wysokiej gÄ™stoÅ›ci" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Druk niskiej gÄ™stoÅ›ci" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Dyfuzja" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Brak korekcji" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "ZwykÅ‚y" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Ulepszanie" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Automatyczne progowanie" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Automatyczne progowanie" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Ustaw kolejność ramek" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "CieÅ„ dla niebieskiego" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "PrzesuÅ„ czerwieÅ„ do błękitu" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamentowy" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "Pogrubianie ziarniste 8x8" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "Pogrubianie dokÅ‚adne 8x8" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "Pogrubianie Bayera 8x8" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "Linie pionowe 8x8" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Wzmocnienie" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Ustawienia wzmocnienia kanałów kolorów" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Wzmocnienie szaroÅ›ci" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Ustawia wzmocnienie kanaÅ‚u szaroÅ›ci" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Wzmocnienie czerwieni" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Ustawia wzmocnienie kanaÅ‚u czerwieni" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Wzmocnienie zieleni" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Ustawia wzmocnienie kanaÅ‚u zieleni" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Wzmocnienie błękitu" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Ustawia wzmocnienie kanaÅ‚u błękitu" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Ditherowanie Bayera 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Ditherowanie Bayera 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Półtonu Punkt 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Półton Punkt 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "\"Przenikanie błędów\"" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Tryb 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Tryb 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Tryb 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "Od biaÅ‚ego elementu" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "WygÅ‚adzanie" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Niski" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Åšredni" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Wysoki" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Jedna strona" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Wszystkie strony" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "skaner arkuszy" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Skala szaroÅ›ci w 4-bitach" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Skala szaroÅ›ci w 8-bitach" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Cienie, półtony, Å›wiatÅ‚a, czas ekspozycji" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Opcje dodatkowe" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Balans kolorów" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Nie wykonuj nawracania" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "JeÅ›li zaznaczone, skaner nie wykonuje nawracania gÅ‚owicy" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Włącz / wyłącz lampÄ™ głównÄ… skanera" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Włącza bÄ…dź wyłącza lampÄ™ głównÄ… skanera" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Kalibracja wykonywana przez sterownik" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "JeÅ›li zaznaczone, sterownik wykonuje kalibracjÄ™ kolorów przed skanowaniem" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Używaj przystawki lightlid-35mm" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "" "Ta opcja wyłącza lampÄ™ głównÄ… skanera podczas używania przystawki do " "materiałów przezroczystych" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Skan dobrej jakoÅ›ci" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Najwyższa jakość, ale maÅ‚a prÄ™dkość" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Szybki skan" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "NajwiÄ™ksza szybkość, ale gorsza jakość" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatyczne dostosowanie progu" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Jeżeli zaznaczone, sterownik automatycznie próbuje znaleźć optymalnÄ… " "wartość dla progu." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Ustawia sposób korekcji gamma." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Identyczna gamma dla wszystkich kanałów" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Użyj takiej samej wartoÅ›ci dla wszystkich kolorów" #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Liniowa gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Ustawia wartość dla liniowej korekcji gamma." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Liniowa gamma, czerwony" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Ustawia wartość liniowej korekcji gamma dla czerwonego kanaÅ‚u" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Liniowa gamma, zielony" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Ustawia wartość liniowej korekcji gamma dla zielonego kanaÅ‚u" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Liniowa gamma, niebieski" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Ustawia wartość liniowej korekcji gamma dla niebieskiego kanaÅ‚u" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "KanaÅ‚" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "Wybiera zakres kolorów, \"Główny\" ma wpÅ‚yw na wszystkie kolory." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "PółcieÅ„" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za \"50% szarego\"" #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "PółcieÅ„ dla czerwonego" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za \"50% czerwonego\"" #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "PółcieÅ„ dla zielonego" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za \"50% zielonego\"" #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "PółcieÅ„ dla niebieskiego" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" "Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za \"50% niebieskiego" "\"" #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Balans czerwonego" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" "Współczynnik balansu dla czerwonego. Wartość 100% oznacza brak korekcji." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Balans zielonego" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" "Współczynnik balansu dla zielonego. Wartość 100% oznacza brak korekcji." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Balans niebieskiego" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" "Współczynnik balansu dla niebieskiego. Wartość 100% oznacza brak " "korekcji." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Balans firmware-owy" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" "Ustawia balans kolorów na wartoÅ›ci podane przez oprogramowania skanera" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Najwolniejszy" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Wolniejszy" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Szybszy" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Najszybszy" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 chropowaty" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 zwykÅ‚y" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 dobry" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 bardzo dobry" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 zwykÅ‚y" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 chropowaty" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 dobry" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 chropowaty" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 zwykÅ‚y" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 dobry" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 zwykÅ‚y" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 zwykÅ‚y" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 ustawiany" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 ustawiany" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 ustawiany" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 ustawiany" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 ustawiany" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 ustawiany" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Szybki tryb szaroÅ›ci" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Skanuj w szybkim trybie odcieni szaroÅ›ci (niższa jakość)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Żądanie aby wszystkie podglÄ…dy byÅ‚y wykonywane w najszybszym trybie " "(niskiej jakoÅ›ci). To może być tryb niekolorowy lub niskiej " "rozdzielczoÅ›ci." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Czas wyłączenia lampy (w minutach)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Czas (w minutach), po którym lampa jest wyłączana." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Wyłącz lampÄ™" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Wyłącza lampÄ™ natychmiast." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Jasność czerwieni" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Steruje jasnoÅ›ciÄ… kanaÅ‚u czerwieni." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Jasność zieleni" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Steruje jasnoÅ›ciÄ… kanaÅ‚u zieleni." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Jasność błękitu" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Steruje jasnoÅ›ciÄ… kanaÅ‚u błękitu." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Kontrast kanaÅ‚u czerwieni" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Steruje kontrastem kanaÅ‚u czerwieni." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Kontrast kanaÅ‚u zieleni" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Steruje kontrastem kanaÅ‚u zieleni." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Kontrast kanaÅ‚u " #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Steruje kontrastem kanaÅ‚u błękitu." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Kolor 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Kolor 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Skala szaroÅ›ci 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Skala szaroÅ›ci 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "OdbijajÄ…cy Å›wiatÅ‚o" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Pozytyw" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Rozgrzewaj dopóki jasność lampy bÄ™dzie staÅ‚a, zamiast przyjmować staÅ‚y " "czas 40 sekund." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Negatyw" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negatyw" #: backend/pixma.c:396 #, fuzzy, no-c-format msgid "48 bits color" msgstr "Dobry kolor" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Skanowanie sterowane przyciskiem" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Kiedy jest włączone, proces skanowania nie zacznie siÄ™ natychmiast. Aby " "kontynuować, należy nacisnąć przycisk \"SCAN\" (dla MP150) lub przycisk " "\"COLOR\" (dla innych modeli). Aby anulować, należy nacisnąć przycisk " "\"GRAY\"." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Uaktualnij stan przycisku" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Przycisk 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Przycisk 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "MateriaÅ‚y fotograficzne" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Ustawienia urzÄ…dzenia" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Przełącznik lampy" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "RÄ™czne włączanie lamp(y)." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Wyłącz lampÄ™ podczas kalibracji ciemnoÅ›ci" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Wyłączanie lampy zawsze podczas kalibracji ciemnoÅ›ci." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Pamięć podrÄ™czna danych kalibracji" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Włącza lub wyłącza pamięć podrÄ™cznÄ… danych kalibracji." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Wykonuje kalibracjÄ™" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Przyspieszenie czujnika" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Włącza lub wyłącza przyspieszanie ruchu czujnika." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Czas rozgrzewania" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Czas rozgrzewania w sekundach" #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Czas wyłączenia lampy" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Czas wyłączenia lampy w sekundach." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Frontend analogowy" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Wartość AFE wzmocnienia czerwieni" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Offset czerwieni" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Wartość AFE offsetu czerwieni" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Wartość AFE wzmocnienia zieleni" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Wartość AFE offsetu " #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Wartość AFE wzmocnienia błękitu" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Wartość AFE offsetu zieleni" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Wyłącz czerwonÄ… lampÄ™" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Definiuje parametr wyłączenia czerwonej lampy" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Wyłącz zielonÄ… lampÄ™" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Definiuje parametr wyłączenia zielonej lampy" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Wyłącz niebieskÄ… lampÄ™" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Definiuje parametr wyłączenia niebieskiej lampy" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Opcja ta odzwierciedla stan przycisków skanera." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Kolor 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Mapa Ditheringu 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Mapa Ditheringu 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Porozrzucaj" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Wybór źródÅ‚a" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Ulepszanie obrazu" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Wyszarz" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "ZaÅ‚aduj obrazek jako szaroÅ›ci" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Symulacja trójprzebiegowa" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Symuluje skaner trójprzebiegowy zwracajÄ…c trzy oddzielne ramki: zielonÄ…, " "potem niebieskÄ… a na koÅ„cu czerwonÄ…." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Symulacja skanera rÄ™cznego" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Symuluje skaner rÄ™czny. Skanery rÄ™czne zwykle nie znajÄ… wysokoÅ›ci " "obrazka. Zamiast tego zwracajÄ… wysokość -1. Ustawienie tej opcji pozwala " "sprawdzić czy frontend obsÅ‚uguje to poprawnie." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Przywróć domyÅ›lne wartoÅ›ci dla ustawieÅ„ ulepszania (jasnoÅ›ci i " "kontrastu)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Tylko do odczytu (opcja testowa)" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Sprawdzam czy frontendy interpretujÄ… to poprawnie" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Tablice gamma" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Symulacja kodu statusu" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Nie wymuszaj kodu statusu" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Nie wymuszaj na frontendzie zwracania kodu statusu." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Zwróć SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_EOF po tym jak zostaÅ‚a " "wywoÅ‚ana funkcja sane_read()." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Zwróć SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_JAMMED po tym jak zostaÅ‚a " "wywoÅ‚ana funkcja sane_read()." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Zwróć SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_NO_DOCS po tym jak zostaÅ‚a " "wywoÅ‚ana funkcja sane_read()." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Zwróć SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_COVER_OPEN po tym jak zostaÅ‚a " "wywoÅ‚ana funkcja sane_read()." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Zwróć SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_IO_ERROR po tym jak zostaÅ‚a " "wywoÅ‚ana funkcja sane_read()." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Zwróć SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "ZmuÅ› sterownik by zwróciÅ‚ kod po tym jak zostaÅ‚a wywoÅ‚ana funkcja " "sane_read()." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Zwróć SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_ACCESS_DENIED po tym jak " "zostaÅ‚a wywoÅ‚ana funkcja sane_read()." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Opcja ta odzwierciedla stan przycisku skanera." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Włącz lampÄ™" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Włącza lampÄ™ skanera" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Wyłącz lampÄ™" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Wyłącza lampÄ™ skanera" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Czas wyłączenia lampy" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Liczba minut do wyłączenia lampy po skanowaniu" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Wartość progowa dla trybu kreski" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "podajnik dokumentów" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (cale)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (cale)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (cale)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Półcienie nie wspierane" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "RozproszonaKropka8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "RozproszonaKropka16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Liczba skanowanych linii w jednym żądaniu odczytu SCSI. Zmiana tego " "parametru umożliwia dostrojenie prÄ™dkoÅ›ci przy której dane sÄ… " "odczytywane ze skanera podczas skanowania. Jeżeli parametr jest " "ustawiony zbyt nisko, skaner bÄ™dzie musiaÅ‚ siÄ™ okresowo zatrzymywać w " "poÅ‚owie pracy; jeżeli za wysoko, graficzne frontendy mogÄ… przestać " "odpowiadać." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "WysuÅ„ dokument po zeskanowaniu" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Tryb podglÄ…du" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Wybierz tryb dla podglÄ…dów. PodglÄ…dy w skali szaroÅ›ci zwykle dajÄ… " "najlepszÄ… kombinacjÄ™ szybkoÅ›ci i detali." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Ustawienia zdefiniowane" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "UdostÄ™pnia standardowe obszary skanowania dla fotografii, druków itp." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "skaner pÅ‚aski" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Ostrość" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Ostrość automatyczna" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Pozycja skupienia (ostroÅ›ci)" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Pozycja skupienia (ostroÅ›ci)" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Liczba kolorów na odczyt" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Liczba linii w skali szaroÅ›ci na odczyt" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "kamera internetowa" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Kolor RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Kolor RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Kolor RGB TEKST" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "CaÅ‚kowicie czarny" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "CaÅ‚kowicie biaÅ‚y" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Wzorzec kolorów" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Siatka" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Pierwsza pozycja" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Druga pozycja" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "To jest bardzo dÅ‚uga trzecia pozycja. Być może frontend ma jakiÅ› pomysÅ‚ " "jak jÄ… wyÅ›wietlić" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Symulacja skanera rÄ™cznego" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Symuluje skaner rÄ™czny. Skanery rÄ™czne zwykle nie znajÄ… wysokoÅ›ci " "obrazka. Zamiast tego zwracajÄ… wysokość -1. Ustawienie tej opcji pozwala " "sprawdzić czy frontend obsÅ‚uguje to poprawnie. Ta opcja również włącza " "szerokość ustalonÄ… 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Symulacja skanera trójprzebiegowego" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Symuluje skaner trójprzebiegowy. W trybie kolorowym przesyÅ‚ane sÄ… trzy " "ramki." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Ustaw kolejność ramek" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Ustaw kolejność ramek w kolorowym trybie trójprzebiegowym" #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "JeÅ›li wybrano automatyczny podajnij dokumentów (ADF), podajnik bÄ™dzie " "'pusty' po 10 skanach." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Opcje Specjalne" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Wybierz obraz testowy" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Wybierz rodzaj obrazu testowego. DostÄ™pne opcje:\n" "CaÅ‚kowicie czarny: wypeÅ‚nia skan czerniÄ….\n" "CaÅ‚kowicie biaÅ‚y: wypeÅ‚nia skan bielÄ….\n" "Wzorzec kolorów: rysuje różne kolorowe wzory testowe, zależne od trybu.\n" "Siatka: rysuje czarno-białą siatkÄ™ o rozmiarach 10x10mm na kwadrat." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Odwróć kolejność bajtów" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Zamienia górny i dolny bajt danych obrazu w trybach 15-bitowych. Ta " "opcja może być używana do testowania 16-bitowych trybów frontendów, np. " "czy frontend używa odpowiedniej kolejnoÅ›ci." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Granica odczytu" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Ogranicza ilość danych przesyÅ‚anych przy każdym wywoÅ‚aniu funkcji " "sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Rozmiar limitu odczytu" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "(maksymalna) ilość danych transmitowanych z każdym wywoÅ‚aniem " "sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Opóźnienie odczytu" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Opóźnia transfer danych do potoku." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Okres opóźnienia odczytu" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "Jak dÅ‚ugo czekać po transmisji każdego bufora danych przez potok." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Wartość powrotna sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Ustawia wartość powrotnÄ… sane_read(). \"DomyÅ›lne\" jest zwykÅ‚e " "skanowanie. Wszystkie inne kody statusu sÅ‚użą do testowania jak traktuje " "je frontend." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Utrata pikseli na liniÄ™" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Liczba pikseli które sÄ… tracone przy koÅ„cu każdej linii." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Parametry rozmyte" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Zwraca rozmyte linie i bajty na liniÄ™ gdy wywoÅ‚ywany jest " "sane_parameters() przed sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Używaj nie blokujÄ…cego IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Użyj nie blokujÄ…cego IO dla sane_read jeżeli jest to wspierane przez " "frontend." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Proponuj deskryptor pliku \"select\"" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Proponuj deskryptor pliku \"select\" jeżeli sane_read() bÄ™dzie zwracaj " "dane." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "UdostÄ™pnij opcje testowe" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "UdostÄ™pnia różne opcje testowe. SÅ‚uży do testowania możliwoÅ›ci " "frontendów do przeglÄ…dania i modyfikowania różnych typów opcji SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Opcje drukowania" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Drukuj listÄ™ wszystkich opcji." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Opcje testowe (typu logicznego)" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) logiczny miÄ™kki wybór miÄ™kkie wykrywanie" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) logiczna opcja testowa, która umożliwia miÄ™kki wybór i miÄ™kkie " "(oraz zaawansowane) wykrywanie możliwoÅ›ci. Jest to zwykÅ‚a opcja logiczna." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Logiczny twardy wybór miÄ™kkie wykrywanie" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Logiczna opcja testowa, która umożliwia twardy wybór i miÄ™kkie " "wykrywanie (również zaawansowanych) możliwoÅ›ci. Oznacza to, że opcja nie " "może być ustawiona przez frontend, tylko przez użytkownika (np. przez " "przyciÅ›niÄ™cie przycisku na urzÄ…dzeniu)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Logiczny twardy wybór" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Logiczna opcja testowa, która umożliwia twardy wybór możliwoÅ›ci. " "Oznacza to, że opcja nie może być ustawiona przez frontend, tylko przez " "użytkownika (np. przez przyciÅ›niÄ™cie przycisku na urzÄ…dzeniu) i nie może " "być odczytywana przez frontend" #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Logiczne miÄ™kkie wykrywanie" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Logiczna opcja testowa, która umożliwia miÄ™kkie wykrywanie " "(również zaawansowanych) możliwoÅ›ci. Oznacza to, że jest tylko do " "odczytu." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Emulowany logiczny miÄ™kki wybór miÄ™kkie wykrywanie" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Logiczna opcja testowa, która umożliwia miÄ™kki wybór, miÄ™kkie " "wykrywanie i emulowanie (również zaawansowanych) możliwoÅ›ci" #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Logiczny miÄ™kki wybór miÄ™kkie wykrywanie automatyczne" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Logiczna opcja testowa, która umożliwia miÄ™kki wybór, miÄ™kkie " "wykrywanie i automatyczne (oraz zaawansowane) możliwoÅ›ci. Ta opcja może " "być automatycznie ustawiania przez sterownik." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Opcje testowe typu caÅ‚kowitego (int)" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Typ caÅ‚kowity (int)" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" "(1/6) Opcja testowa typu caÅ‚kowitego bez narzuconych jednostek i " "ograniczeÅ„" #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Typ caÅ‚kowity o ograniczonym zasiÄ™gu" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "(2/6) Opcja testowa typu caÅ‚kowitego " #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(/6) Typ caÅ‚kowity" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Opcja testowa typu caÅ‚kowitego posiadajÄ…ca bity jednostek oraz " "ograniczona sÅ‚ownikiem" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Macierz typu caÅ‚kowitego" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Opcja testowa typu caÅ‚kowitego z jednostkÄ… w mm, używajÄ…ca " "macierzy nieograniczonej" #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Macierz typu caÅ‚kowitego z ograniczonym zasiÄ™giem" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Opcja testowa typu caÅ‚kowitego z jednostkÄ… w dpi, używajÄ…ca " "tablicy z ograniczeniem zasiÄ™gu. Minimum to 4, maksimum 192, a kwant to " "2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Macierz typu caÅ‚kowitego ograniczona sÅ‚ownikiem" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Opcja testowa typu caÅ‚kowitego z jednostkÄ… w procentach, używajÄ…ca " "tablicy ograniczonej sÅ‚ownikiem" #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Opcje testowe staÅ‚oprzecinkowe" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Typ staÅ‚oprzecinkowy" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" "(1/3) Opcja testowa staÅ‚oprzecinkowa bez jednostek i bez ograniczeÅ„" #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Typ staÅ‚oprzecinkowy o ograniczonym zasiÄ™gu" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Opcja testowa staÅ‚oprzecinkowa z jednostkÄ… w mikrosekundach i " "ograniczonym zasiÄ™giem. Minimum to -42.17, maksimum 32767.9999 a kwant " "to 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Typ staÅ‚oprzecinkowy ograniczony sÅ‚ownikiem" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Opcja testowa staÅ‚oprzecinkowa bez jednostek, ograniczona " "sÅ‚ownikiem" #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Opcje testowe typu ciÄ…g znakowy" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) CiÄ…g znakowy" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Opcja testowa typu ciÄ…g znakowy bez narzuconych ograniczeÅ„" #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) CiÄ…g znakowy ograniczony listÄ…" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) Opcja testowa typu ciÄ…g znakowy ograniczona listÄ…" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) CiÄ…g znakowy ograniczony dÅ‚ugÄ… listÄ…" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(/3) Opcja testowa typu ciÄ…g znakowy ograniczony listÄ…. Zawiera trochÄ™ " "wiÄ™cej pozycji..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Opcje testowe przycisków" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Przycisk" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Opcja testowa przycisku. WyÅ›wietla trochÄ™ tekstu..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Kolor 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Użyj SkÅ‚adania Obrazków" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Dwupoziomowa czerÅ„ i biel (tryb kreski)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Ditherowana/półcieniowa czerÅ„ i biel (tryb półtonów)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Wielopoziomowa czerÅ„ i biel (tryb szaroÅ›ci)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Wielopoziomowy kolor RGB (kolor jednoprzebiegowy)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignoruj kalibracjÄ™" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Zablokuj wstÄ™pne ustawianie ostroÅ›ci" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Nie kalibruj ostroÅ›ci" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "RÄ™czne wstÄ™pne ustawianie ostroÅ›ci" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Popraw pozycjÄ™ skupienia" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Kalibracja soczewek w pozycji dokumentu" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Kaibruj skupienie soczewek w pozycji dokumentu" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Pozycja skupienia uchwytu 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Użyj pozycji skupienia uchwytu 0mm zamiast 0.6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Tryb kalibracji" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Zdefiniuj tryb kalibracji" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Ustawia lapÄ™ jako włączonÄ… lub wyłączonÄ…" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "Włącz UTA" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Ustawia UTA jako włączone lub wyłączone" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Offset" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Ustawienia offsetu kanałów koloru" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "PrzesuniÄ™cie (offset) skali szaroÅ›ci" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Ustawienie offsetu kanaÅ‚u szaroÅ›ci" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Ustawienie offsetu kanaÅ‚u czerwieni" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Ustawienie offsetu kanaÅ‚u zieleni" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Ustawienie offsetu kanaÅ‚u błękitu" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Tryb podglÄ…du" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "problem nie przeanalizowany (nieznana klasa SCSI)" sane-backends-1.0.27/po/uk.gmo0000664000175000017500000043055513110600540012765 00000000000000Þ•%+ìI˜b ™b-¦b Ôb;àb c,)c"Vczyc ôc9þc8d€Ud#Öd5úd"0eÆSefj5f  fBÁf(gS-ggؘgqhBhÓhlêhWiJgi+²icÞi Bjzcj'Þj™k$ kWÅkl.l?lDl IlVl^l cl nl yl „ll —l ¥l °l»l Äl Ïl Úlål îl ùl m mm $m 2m >mHm[mlm ~m ‰m”m m ¨mÒ¶m‰nŒn•n§nªn³nÅn Èn Õnánänèn ñn ünoo o/o"7o"Zo$}o!¢o!Äoæo!p (pIp ipŠp¡pºpÒpÛpìpsq zq?„q5Äq úqrr(r@rSrdr |r!r¿rßrärór s s #s.sCsYsns ƒss!§sÉsÞsòs t<tGYt_¡tuu uu"u+u=u @uJuOu`u=pu>®u<íu*v.v4vDv'Tv|v…vv ¯v ºvÄv ÊvÖv Ûvèv øvww ,w :wFwcw uwƒw%’w¸w%Çw íw øwxx"x +x8xLxcxkxnx~x ‚xx¢x¾xÛxöx yy$y)?y%iy y›y!²yÔyëyüy z z +z 5z AzLz]z9mz§zÅzÍz Óz Þzëzýz{{&/{ÄV{Ç|ã|é|ù|} } } ,} 6}@} O}]}z}™}ª} È} Õ}ã}ë}ó}û} ~~ 2~>~G~P~f~}~"’~µ~Õ~ò~!66I.€B¯CòA6€,x€@¥€Aæ€?((h ‘!*¿ êõ ‚(‚<‚ Q‚ [‚e‚z‚‹‚ “‚ ‚¤‚¶‚¾‚Ç‚)ß‚" ƒ$,ƒ*Qƒ#|ƒ( ƒ!Ƀëƒ# „-„J„ j„‹„Iª„,ô„'!…I…Q… a…n…*†…0±…Dâ… '†3†C†6K† ‚†1Œ†¾†Ó†ë†‡‡e,‡ ’‡³‡ŇÕ‡ó‡ú‡ˆ%ˆ?ˆ/Yˆ ‰ˆ •ˆ%¡ˆLj&æˆ ‰$‰1=‰'o‰—‰§‰¾‰ Õ‰ö‰ ŠŠ1Š GŠhŠŠ’ХР­Š»Š Š ЊEÜŠ "‹ .‹<‹;S‹‹•‹³‹΋å‹ô‹ Œ $Œ1Œ:Œ#LŒ?pŒ-°Œ8ÞŒ,/D$t™!® Ð!ñŽ'Ž$©Ž"ÎŽñŽ(*+S0°ÄÍ Þ`é JX k(y¢¿;× ‘ !‘/‘?‘ N‘ [‘ i‘ u‘ ƒ‘‘ Ÿ‘ª‘­Â‘p’ Š’ •’£’0·’ è’ ó’“““$“ 3“ @“J“Q“ Y“ d“ p“|“ …“ “š“ Ÿ“ª“ »“ Ǔӓæ“ù“ ”””,”;” J”V” p” {”‡”𔳔%Ä”hê”eS•^¹•c–a|–bÞ–aA—£—4©—Þ— ò— ý— ˜˜!˜ 3˜=˜F˜c˜t˜y˜˜ ˜˜!®˜ И;ܘ™ 0™)<™*f™(‘™›º™Vš_š nšyš ~šˆš ˜š¤š«š±š¹šÊšÛšêš ðšþš ››6›F› U›b›€›™›ž›§›¾›Õ›í›ý› œœ 4œ BœMœdœsœ‹œ£œ¼œ2М26Jdi€–¥Å åïžž(ž BžMž]žIož¹žT½ž[ŸEnŸ4´Ÿ’韹| Q6¡€ˆ¡¢ ¢¬¢ ¿¢à¢ÿ¢£%£7£V£e£u££¤£¸£7Ò£* ¤55¤ k¤w¤€¤ ¤ ¨¤¶¤Ǥؤ é¤÷¤%¥7¥I¥h¥=m¥«¥?¼¥ ü¥¦$¦-¦ >¦_¦ t¦‚¦𦠢¦ ®¦ »¦Ȧ ᦠì¦ö¦yü¦v§ Ч0«§ܧUã§9¨C:©~©†©Š£©.ª>ªVª Zªeª zª ˆª”ª¥ªºªΪäªõª « « +« 6«A«^«1b«2”«Ç«Í«Ô«ä«ì«ý«¬+¬K¬ ]¬j¬‰¬¤¬½¬Û¬í¬ ý¬ ­­­#­*­&<­*c­ Ž­˜­¡­²­ »­É­Ø­ ç­õ­ ®/® F® P® ^®k®†® –®¤®©® °® ¼®XÉ®Þ"¯°]°q± ± ˜±¢±¾± ±Ḻ²6²=²@²dI²®²βæ²þ² ³³'³ 0³ ;³ G³ S³^³~³ ³ š³§³³á³%ö³´ %´3´B´ \´ i´v´Š´’´ š´§´­´ Ê´MØ´&µ :µ GµTµdµhµ xµ‚µ †µ ‘µœµM²µ¶ ¶¶¶(¶ B¶ P¶ ]¶h¶„¶!¢¶ Ķ϶ë¶·#·?·5_·=•·?Ó·B¸GV¸4ž¸5Ó¸0 ¹/:¹0j¹;›¹*×¹*ºA-ºCoº,³º3àºÖ»|ë»&h¼ ¼ ¼«¼½¼ Ѽò¼½'½C½]½x½[’½î½¾¾4¾F¾ K¾V¾ l¾y¾‹¾ž¾ ¯¾¹¾ ɾ ê¾ ö¾¿¿2¿O¿'j¿’¿ ¤¿ ±¿»¿ Ë¿ ׿xâ¿3[ÀÀ=¥À7ãÀÁ&8Á _ÁmÁ)‰Á3³Á çÁôÁÂ.ÂGÂ`Â#uÂg™ÃœÄžÄ:¶Ä;ñÄ9-Å,gÅY”Å%îÅÆF,ÆsÆ/ˆÆ*¸Æ"ãÆ‡ÇŽÇ¤Ç'ÃÇ<ëÇ4(Ȇ]È>äÈB#É>fÉ?¥ÉDåÉ?*Ê9jÊ9¤Ê=ÞÊ@Ë=]ËB›Ë>ÞË>Ì?\Ì=œÌ<ÚÌÍ&Í .Í29ÍlÍÍD‘ÍDÖÍ,ÎHÎaÎsÎ;„Î7ÀÎøÎ(Ï?7ÏwÏ1ÏÁÏ;àÏÐ/Ð?ÐVÐoІПзÐÑÐâÐøÐ!Ñ>2Ñ?qѱÑDÇÑ% Ò42ÒgÒ#Ò£Ò'½Ò)åÒÓX$Ó2}Ó̰Ó}Ô„Ô”Ô¥Ô)´Ô ÞÔ éÔóÔÕÕ-Õ@ÕRÕeÕ"{ÕžÕ)³Õ ÝÕëÕÖü ÖÐ×pØ×KIØ•Ø¨Ø ¸ØÃØ רãØéØðØõØüØÙ ÙÙ1Ù PÙ^ÙpÙ€Ù œÙ ¨Ù´Ù#ÅÙéÙùÙ" ÚW,Ú#„Ú¨Ú·ÚÀÚÑÚ%ìÚÛ)Û*.ÛYÛmÛuÛ<ŠÛÇÛ äÛ òÛýÛÜ[ÜwÜGÜ'ØÜuÝ)vÝ= ÝŒÞÝ6kÞ¢ÞS³Þ1ß49ß7nß;¦ßâßøß ààD(à màŽàˆžàŒ'áF´áûáâ2â ;â Iâ!Tâ vâ!â £â°âÅâ×âêâ üâ ã+ãAãVãvãã–ãžã¥ã¶ãÎãîãää$ä 4ä.Uä„äCšäÞä(õä1åPåAdå¦å.Äå&óåæ 8æEæ^æwææ™æ ¢æ°æÀæ)Ðæ úæ`ç`|ç Ýçéçè %è1è¨Ièzòè>m鋬é8ê >êJê_êtêŠê)žê ÈêÕêÙêâê êê÷êüêë ëë ë%ë(ë 7ëEëKë bëmëqëvë ~ë ˆë–ë ™ë ¦ë²ëÂëÇëÍë Öë âëîëì)ì2ìOìnìƒì£ì¹ì Êì×ìëìñìøìüìíí6í;íBíFíOíXí&kí’í!®íÐíÔíåí÷íî$î+î 2î@î[î/zîªîÊîÒîâîëîôîïï ï"ñP5ñ$†ñ”«ñ@òMQò\Ÿò&üò #ô‰Dô>Îô õFölcöZÐöË+÷D÷øô<ùC1ú¥uúSû£oû2üûFüGBþ¦Šþ71ÿ&iÿ+¼¼vyðVò*Ivt‰ëYu´Ï)„)®Øßæ4I^sŽ«ºÏÞó  & 9 N c  š ° Ä !Õ #÷ % A P e t ‰ æ¡ ˆ  ‹ ™ ¸  » É è ë ÿ   4 R 2j 0 "Î Eñ ;75sz©B$DgP¬RýPPT¡RöTI^ž`ýb^Á%Ô.ú°)Ú¡òx”' #5*Y2„,·.ä2HFJLÚ'807i"¡Ä-á3)C?m'­Õ8ìQ%1w+©KÕ)!KËÙ\6 9Gf iw–™ «¸Ê…ê‡p‰ø ‚ &œ&ÃLê7EQ/—Ç-ä    ; F #b #† 8ª )ã , !:!4Z!6!Æ!1Þ!d"1u"d§" #!!#'C#k#z#‰#2Ÿ#4Ò# $$B$\$c$.~$D­$Fò$H9%<‚%¿%#Ü%K&[L&W¨&':'3T'6ˆ'!¿'#á'((6($R(w( •(¶(¡Ö(<x) µ)À)/Ç))÷)6!*4X* *#˜*_¼*Ä+>á, /(5/^/(v/'Ÿ/Ç/ç/0070GU0=0)Û0>1D1'`1ˆ1 1¸1>Ð12#"2 F2S2h26ƒ28º2:ó2A.3=p3=®3,ì324(L4*u4j 4J 5iV5kÀ5m,6Pš6oë6q[7sÍ7aA8£8F¹8b9c9Nƒ9Ò9aã91E: w:ƒ:)ž:-È:&ö:;8;-<;j; y;4†;`»;W<Jt<b¿<W"=]z=YØ=F2>My>TÇ>N?Pk?R¼?”@Z¤@Eÿ@EA%XA!~A2 A_ÓA]3Br‘BC#$CHC›WCóCƒD2†D:¹D0ôD)%E:OEêŠEGuF½FÏFXßF8G%IG'oG#—G#»GaßGAHaHcHCåHx)I2¢IDÕIeJ_€J!àJ6K<9K8vKE¯K#õK4L:NL\‰L.æL%M%;M aM$lM‘M%¢M%ÈMÌîM"»N'ÞN4Oˆ;OÄOGÛOT#PTxP#ÍP4ñPJ&QqQˆQ(¡Q8ÊQ§Rg«R°SpÄSp5To¦T0U7GUZUNÚU8)VöbVeYWR¿WJXQ]XY¯XZ YTdY(¹YâY#ñYZ®(Z×Z!ñZ[U/[…[¢[‹¿[K\c\}\!™\»\!Ù\#û\]?]!T]v]QŒ]ŒÞ]8k_¤_»_;×_``t`Š`4ª`ß` ò`/ÿ`/a!Oa qa~a‘a¦a¾aÔaêa þa b'b?b_bwb<‹bBÈb cc8c%Oc%uc›c!´c>Öc!d!7d'Yd;d.½dbìd…Oe‚Õe{Xf€Ôf~UgÔg~ThÓhaÜh.>imii •i ¶iWÁij9j;Hj'„j¬jÁjÊjêjk9$k^krk(ôkBlN`lP¯lRm/Sm ƒn#¤nÈn àn!ën* o8oNogo$o-¤o-Òo5p6pEp%cp%‰p:¯p+êp.q!Eq6gq?žq Þqëq&úq'!rIr$gr$Œr!±r0ÓrssK/s.{s.ªs.ÙsJt(St^|t^Ût6:u'qu™u5¨u-Þu! v6.v4evšv0µv2æv4w;NwŠw(¦w*Ïwyúwtx¾…xÜDy³!zwÕzŽM{ŸÜ|Ç|~'DÀl€--‚`[‚T¼‚Vƒhƒ)}ƒC§ƒ)ëƒ/„:E„!€„3¢„@Ö„`…yx…hò…[†p†J‰†'Ô†ü†#‡>@‡'‡)§‡Qчo#ˆ2“ˆ;ƈ‰e‰m‰v…‰ü‰RŠeŠ/ŠS±Š@‹$F‹:k‹¦‹Ä‹&Ø‹ÿ‹9ŒSŒqŒ ‚ŒÿŒ.F¼rŽvŽ}Ž<}K‘É‘DÚ‘6’&V“'}“¥“"´“-ד!”'”*G”9r”:¬”=ç”6%•-\•Š••°•Õ%Ö•ü•Ž–”– $—/—@—\—&m—(”—*½—„è—5m˜/£˜vÓ˜LJ™H—™Kà™0,š1]šš ¬š ·š Äš Ñš3ÞšW›_j›Ê›ã›)웜%œAœ#[œœ$Žœ$³œ†Øœ_pŽ2¨#Ûÿ ž&ž7ž#Už²yžü,Ÿ')¡èQ¡1:¤l¤¤?‘¤Ѥ⤛¥Cž¥â¥ë¥þ¥A¦AZ§&œ§"ç+æ§#¨ 6¨C¨L¨a¨'¨§¨WŨ©7©Q©6f©>©'Ü©dªiªxª”ª>®ªíª%«:*«'e««6ž«Õ«BÞ«!¬¸?¬%ø¬!­%@­?f­¦­3ª­Þ­ñ­®'®@E®®†®5¯F¯'f¯'ޝ<¶¯-ó¯0!°#R°8v°@¯°\ð°M±U^±U´±U ²U`²R¶²ž ³–¨³œ?´«Ü´»ˆµ‹D¶ŒÐ¶~]·ˆÜ·‰e¸ˆï¸}x¹xö¹¶oºŸ&»sÆ»†:¼ÿÁ¼>Á¾BÀ:CÀ0~À0¯ÀMàÀ,.Á)[Á"…Á'¨Á%ÐÁ&öÁ%ÂCÂ-áÂ8ÃCHÃ$ŒÃ±Ã¶ÃBÍÃÄ(*Ä*SÄ,~Ä«Ä.ËÄ`úÄ[Å'qÅ,™ÅBÆÅD ÆFNÆh•Æ:þÆ,9ÇfÇ:†Ç#ÁÇ'åÇä ÈsòÈ.fɶ•ÉjLÊU·Ê6 ËDË-`ËhŽËq÷ËiÌAÌ"ÃÌjæÌ9QÍ$‹Íb°ÍÕÐ!éÐ2 Òz>Ò|¹Ò~6Ó^µÓßÔkôÔ&`Õƒ‡Õ ÖO(Ö=xÖh¶Ö:×ZØ2yØL¬ØùØx‡ÙlÚsmÛ~áÛq`ÜuÒÜ„HÝsÍÝdAÞb¦Þw ߈ßu à€€àRájTáV¿áXâ¯oâã>ãMãpbã>ÓãBä Uä’öäf‰åEðå,6æ:cæqžækçH|çqÅç7è.ÅèrôèBgéhªé%ê'9êAaê5£ê?Ùê3ëCMë7‘ëHÉëEì9Xì`’ìzóì‘ní*î–+îsÂî‚6ï:¹ïRôï?GðU‡ðcÝð8AñÓzñ~NòqÍò?ô,Vô.ƒô0²ô]ãô%Aõgõ-xõ/¦õ-Öõ1ö/6ö1föG˜ö]àö>>÷o}÷í÷+ ø5ø&Hø¾oú÷.ü¡&ý*Èý1óý!%þ:Gþ#‚þ ¦þ ±þ¾þÏþàþûþ ÿ<#ÿv`ÿ%×ÿ6ýÿ64Fk²Òðe #p'”)¼¿æc¦#  .;9Wc‘$õX+4„ ¹:Ä_ÿ._Ž£´<¼æù6à‘S©ÑýIÏp *Š oµ !% ~G bÆ T) T~ šÓ 9n 9¨  â í ’ Jœç‰ýG‡—ÏEgC­ñ 1sO1Ãsõi~"š1½"ïJ.*y,¤)Ñ5û1HY(pE™@ß$ E!]"1¢SÔL(ÞuOTh¤y N‡©ÖI€zÊE>Å+707h@ áô$ 414f„›l šš( à Cß ?#!c!.}!\¬! # $ Î$ Ü%ç%.&/0&1`&3’&NÆ&,'B'F'^',f'“'¢' ©' µ' Á'Ì'æ')ë'-(C(WV(®(Å( Ì( ×(ä(õ( ))<)!P) r)})Œ)›)±)DÇ) *„*Fž*3å*$+B>+-+¯+Ç+*ä+ ,, +,8,G,,e, ’,,®,¿,Ï,Jß,^*-Y‰-Vã-:.0K.%|.O¢.-ò. / 5/4B/*w/8¢/iÛ/LE0’01£0!Õ0÷0-1A1Y1áU @p™œk_lèÕ¯xqt¡jQ¼“` [º^X¶¸’ÀØKÎB ÆKsY‚¢J˜Œ¹nLÕá’%„`Ê­:\Ìø²°(„$?#Ó^â* ðO“%'fZÇ¢£JøEMgòñ&HåìYíB Q“÷mubSr0)Ô Ž³£´8#C¹ËoÚ¨ óSÙƒe£iÂÓ>7>ßïLØCJ«I]¤’þ³aI*‰\b¬|þƒ«Ö°©:lN8¹¿=ðþwZÚŠù(×~md—5öõ4•Gdcp–' ŒBA‰Àržeð„áÊy¬ZÅ“&sI™ÉȘ,”…HžÝëð˜ÿ.‹z'ëA`Šé”åÏúܕ풧0;Vfwz=Y#7h훤B;• 7µ ¶*Æh$R©ôÂóW÷]”-9μ9qZNV¦ 7ÛÑ1 œˆ¼T" 6½¾Íªbì•ýCæ m+äàÓ²ç3rÀíøÞ”õtc[h\p_oÚ(Ey Íëk;3Õk09<Þ>üŽ+y%a5ï5!©W ô ³ÁÒqœRJ¸öUz€ŸL—D}%tõ¾oFOÀ1}ùï¬-á÷Ï4jØÊgô´ÍɽèøLÐA#¹aD—é¡E,)êäúD86®P¶†ÓÇDsAàÂuÒS»`ÌóÕ )±†ÝÝ>@(§F~ÃÈ&cšUÖâÎK渆‹/ažs@ëËAd½ žªVgj†±åý‹Tsî\v…chöf<êv˜@X“»klP"È`H?R¸®+ÄIßLû¨€¥·| x›üÔÔg=ŸþNà»qxÜý‘çŒÙ:ÆQ_·¯ ƒ1[zgΰ‡ãÉÖû~¿,f„Ћ_u@?Ö«Û/=‚MúÐCÌ×…6ORòT§ µRèˆä/G)ñœî~¯2W¥eZ%F›æ:ÙêšFw™| f™„¬ÇiS\wô·­ ¤ö¾€¤ KN–´}W™Ç.¢pWMnñ¨Ê*‘P9¦[d&j4=‡|ò?®–äÒDIMPSV;J–ÿ8µË#â¡‘”< Tã3ý"…uUМÄjª›!üGPXÌ»]׉Û{r-oêOÛ–ú.ì;iT¥É›vmr3!{Å |Ã/v?æ7Ánh>€Qd¾z.å2㱘u¡4ïtHˆçóˆUÁYÁeÿiâÃ6­€‡šì¦©ÍBòNYVÿ-X¢!³Úû_¿X'°"i$ }bŸÈ½à‚Ŷ}~ćFçét®x߯{ˆŠŠ0xk.&4Üpù<2Žw’Ÿ^ÑO †G² n5Ñ{v,Þ+ã26²ÝÔ´$î"oû¼Ä,Q Å*-C]G÷ÏŽ•‚º:(b]õŽ 5µ‰3—)Ø^…èE{é^ܧ¨Ñ9a±ŒÙl‘e0yºc<8î‘ßˉlE'×m¿K¥Œ1ªãMù·—«2ƒ1!ºÆñÏ[ƒ +H­‚$¦‹üŠš/yšn‡qÞÒ(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm16 bits gray2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel48 bits color4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A3A3 paperA3 paper detectedA4A4 paperA4 paper detectedA5A5 landscapeA5 portraitA6ADFADF BackADF DuplexADF FrontADF ModeADF Waiting TimeADF cover openADF jamAccess to resource has been deniedAction following double feed errorAddition of space in bottom positionAddition of space in top positionAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdjust blue/red offsetAdjust front/back offsetAdjust green/red offsetAdvancedAdvanced OptionsAdvanced paper protectionAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAllows one to test device behaviour with other supported modelsAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAuto length detectionAuto or manual focusAuto width detectionAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic threshold modeAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisB4B4 paperB4 paper detectedB5B5 paperB5 paper detectedB6BP filterBackBackground colorBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuffer modeBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration cache expiration timeCalibration data cacheCalibration fileCalibration modeCalibration nowCancel buttonCard BackCard DuplexCard FrontChange Document.Change documentChange endorser counter value by this much for each page.Changes intensity of midtonesChannelCheckChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.Collect a few mm of background on top side of scan, before paper enters ADF, and increase maximum scan area beyond paper size, to allow collection on remaining sides. May conflict with bgcolor optionColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor filterColor patternColor24Color36Color48Colour lines per readCompressionCompression argumentConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControl pattern of halftone filterControl type of halftone filterControl white level followerControls blue levelControls for endorser unitControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCrop actual image areaCustomCustom color matrix for grayscale scans.Custom color matrix.DF actionDF lengthDF length differenceDF recovery modeDF skewDF thicknessDTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.DensityDensity controlDensity dialDetect stapled documentDetermines maximum endorser counter value.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDifference in page length to trigger double feed errorDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart.Disable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Do not stop after double feed detectionDocument FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDouble feedDouble feed detectedDouble feed detectionDouble feed detector sensitivityDouble letter 11x17 inDownload pattern ADownload pattern BDropoutDropout colorDuplexDuplex offsetDuplex scanDuplex scan provide a scan of the front and back side of the documentDuplex sideDuplex switchDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmphasisEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable automatic separation of image and textEnable compressed data. May crash your front-end programEnable double feed error due to paper lengthEnable double feed error due to paper thicknessEnable double feed error due to skewEnable endorser unitEnable selection of exposure-timeEnable selection of lamp densityEnable smoothing for improved OCREnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/Disable double feed detectionEnable/Disable length control modeEnable/Disable long paper modeEnable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEndorserEndorser OptionsEndorser YEndorser alphanumeric print format. %05ud or %08ud at the end will be replaced by counter value.Endorser bitsEndorser directionEndorser fontEndorser print offset from top of paper.Endorser printing direction.Endorser printing font.Endorser printing side, requires hardware support to changeEndorser sideEndorser stepEndorser stringEndorser valueEnhance BlueEnhance GreenEnhance RedEnhanced modeEnhancementError DiffusionError codeError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra buttonExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFit to pageFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassFocus pointFocus point for scanning.Focus-modeFocus-pointForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.FrameFrame number of media holder that should be scanned.Frame to be scannedFrom paperFrom scannerFrom white stickFrontFront button waitFull scanFunctionFunction character on screenFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma curveGamma curve, from light to dark, but upper two may not workGamma function exponentGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftone typeHalftoningHalftoning UnsupportedHalt on CancelHand-Scanner SimulationHand-scanner simulationHardware deskew and cropHardware error codeHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHigh sensivityHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationIgnore center double feed sensorIgnore left double feed sensorIgnore right double feed sensorImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersImprinter ink levelImprinter ink running lowImproves quality of high resolution ball-point pen textIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInitial endorser counter value.Ink lowInk remainingInk-jet printersInt test optionsInvalid argumentInverse ImageInverse image in B/W modeInverse image in B/W or halftone modeInvert endiannessIt is right and left reversingJPEGJPEG Image Compression with Q parameter, '0' - no compressionJPEG compressionJPEG compression (yours application must be able to uncompress)Lamp colorLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off during scanLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLandscapeLegalLength Control Mode is a mode that the scanner reads up to the shorter length of actual paper or logical document length.Length control modeLens calibration in doc positionLet's see whether frontends can treat this rightLetterLevel of JPEG compression. 1 is small file, 7 is large file. 0 (default) is same as 4Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option 'side' can be used to determine correct image. This option should only be used with custom front-end software.Limit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Long Paper Mode is a mode that the scanner reads the image after it divides long paper by the length which is set in Document Size option.Long paper modeLoss of pixels per lineLowLow MemoryLow density printingLow sensivityManual feedManual feed modeManual feed selectedManual feed timeoutManual focus positionManual pre focusManually switching the lamp(s).Matrix 2x2Matrix 3x3Matrix 4x4Matrix 5x5Matrix multiplication of RGBMaxMaximum diameter of lone dots to remove from scanMaximum diameter of lone dots to remove from scan.MediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image (left/right flip)Mirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMirroringMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative colorNegative filmNegative film typeNegative grayNegative to smooth or positive to sharpen imageNegativesNo CorrectionNo detectionNo transparency correctionNoise reductionNoise removalNoneNormalNormal modeNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOMR or DFOMR or double feed detectedOffOff timerOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOne-pass scanners use only one color during gray or binary scanning, useful for colored paper or inkOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryOutlineOverscanPDF buttonPage heightPage loadedPage widthPaper is pulled partly into adfPaper protectionPaper sizePass-throughPerform outline extractionPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPower savingPredefined settingsPrepickPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorRIFROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflect output image horizontallyReflectiveRemove 2 pixel square noiseRemove 3 pixel square noiseRemove 4 pixel square noiseRemove 5 pixel square noiseRequest a preview-quality scan.Request backend to remove border from pages digitallyRequest driver to detect and correct 90 degree image rotationRequest driver to discard pages with low numbers of dark pixelsRequest driver to discard pages with low percentage of dark pixelsRequest driver to halt the paper feed instead of eject during a cancel.Request driver to remove border from pages digitallyRequest driver to remove border from pages digitally.Request driver to rotate pages by a fixed amountRequest driver to rotate skewed pages digitallyRequest driver to rotate skewed pages digitally.Request scanner to detect jams in the ADF caused by staplesRequest scanner to grab next page from ADFRequest scanner to predict jams in the ADFRequest scanner to predict jams in the ADF using improved sensorsRequest scanner to read pages quickly from ADF into internal memoryRequest scanner to reverse feed on paper jamRequest scanner to rotate and crop pages digitally.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Requires black background for scanningReset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readReverse image formatRotate image clockwiseSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner automatically detect image area and crop itScanner cover is openScanner detects paper lower edge. May confuse some frontends.Scanner detects paper sides. May reduce scanning speed.Scanner in power saving modeScanner mechanism locked for transportScanner modelScanner sensors and buttonsScanner shrinks image to fit scanned pageScanner will be stop when a paper have been skewedSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSeparationSet SDTC variance rate (sensitivity), 0 equals 127Set chroma of blueSet chroma of redSet color of background for scans. May conflict with overscan optionSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet paper position : true for landscape, false for portraitSet pixels equal to threshold to white instead of blackSet sharpening value.Set the double feed detector sensitivitySet the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the automatic threshold modeSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the lamp color (color dropout)Sets the manual feed modeSets the manual feed timeout in secondsSets the resolution of the scanned image.Sets the scan sourceSets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkew adjustmentSkew angleSkip warmup processSleep timerSlideSlidesSlowSlowerSlowestSmoothSmoothingSoftware automatic croppingSoftware blank skip percentageSoftware cropSoftware derotateSoftware deskewSoftware despeckle diameterSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Specify the calibration file to useSpeedup sensorStandardStaple detectionStart calibration process.Start calibration using special sheetStatus Code SimulationStopStop scanner when a paper have been skewedString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesTPU8x10Target operation typeTells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The lamp will be turned off during scan. The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold curve, from light to dark, but upper two may not be linearThreshold value for lineart modeThreshold whiteTime (in minutes) before a cached calibration expires. A value of 0 means cache is not used. A negative value means cache never expires.Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off.Time in minutes until the internal power supply switches to sleep modeToggle lamp of flatbedToggles the lamp of the flatbedTop edgeTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.Type of original to scanUTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse manual or automatic selection of focus point.Use non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVarianceVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level followerWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomadfbayer_16bayer_64bluebusiness_cardbwchroma of bluechroma of redcolorcommand sequence errorcontinuouscrtdarkdefaultdiffusionerr_diffusionfbfilm scannerfit-to-pageflatbed scannergraygreenhalftonehalftone_32halftone_64hardware check errorhighinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorjpeg compressionlamp failurelamp not stabilizedlightlinierlowmediummedium not presentno additional sense informationnonenormaloffoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetredreselect failurerounded parameterscan head positioning errorsheetfed scannersinglesmoothtimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNuser_defwait_docwait_doc_hopper_upwait_keywebcamProject-Id-Version: sane-backends Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2017-04-28 19:32+0300 Last-Translator: Yuri Chornoivan Language-Team: Ukrainian Language: uk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Lokalize 1.5 Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); (1/1) Кнопка(1/1) Варіант перевірки кнопок. Друкує текÑÑ‚...(1/3) ДробовочиÑловий(1/3) ДробовочиÑловий параметр перевірки без одиниці виміру Ñ– без набору обмежень.(1/3) РÑдок(1/3) Варіант перевірки Ñ€Ñдків без обмежень.(1/6) Булевий програмний вибір програмне визначеннÑ(1/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей програмного вибору Ñ– програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ (та додаткових). Це звичайний булевий параметр.(1/6) ЦілочиÑельний(1/6) ЦілочиÑельний параметр перевірки без одиниці виміру Ñ– набору обмежень.(2/3) ФікÑований обмежений діапазон(2/3) ДробовочиÑловий параметр з розмірніÑтю у міліÑекундах Ñ– набором обмежень. Мінімальним значеннÑм може бути -42.17, макÑимальним — 32767.9999, крок — 2.0.(2/3) РÑдкова з обмеженим ÑпиÑком Ñ€Ñдків(2/3) Варіант перевірки Ñ€Ñдків з обмеженнÑм на ÑпиÑок Ñ€Ñдків.(2/6) Булевий апаратний вибір програмне визначеннÑ(2/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей апаратного вибору Ñ– програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ (та додаткових). Це означає, що параметр не може бути вÑтановлено оболонкою, лише кориÑтувачем (наприклад, натиÑканнÑм кнопки на приÑтрої).(2/6) ЦілочиÑельний діапазон обмеженнÑ(2/6) ЦілочиÑельний параметр з розмірніÑтю у пікÑелÑÑ… Ñ– набором обмежень. Мінімальним значеннÑм може бути 4, макÑимальним — 192, крок — 2.(3/3) ФікÑований обмежений ÑпиÑок Ñлів(3/3) ДробовочиÑловий параметр перевірки без одиниці виміру Ñ– набором обмежень ÑпиÑку Ñлів.(3/3) РÑдкова з обмеженим довгим ÑпиÑком Ñ€Ñдків(3/3) Варіант перевірки Ñ€Ñдків з обмеженнÑм на ÑпиÑок Ñ€Ñдків. МіÑтить дещо більше запиÑів...(3/6) Булевий апаратний вибір(3/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей апаратного вибору (та додаткових). Це означає, що параметр не може бути вÑтановлено оболонкою, лише кориÑтувачем (наприклад, натиÑканнÑм кнопки на приÑтрої), оболонка не може читати дані за такої конфігурації.(3/6) ЦілочиÑельний ÑпиÑок обмежень Ñлів(3/6) ЦілочиÑельний параметр перевірки з одиницею виміру біт Ñ– набором обмежень ÑпиÑку Ñлів.(4/6) М’Ñке булівÑьке виÑвленнÑ(4/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ (та додаткових). Це означає, що параметр призначено лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ.(4/6) ЦілочиÑельний маÑив(4/6) ЦілочиÑельний параметр перевірки з одиницею виміру міліметри Ñ– викориÑтаннÑм маÑиву без обмежень.(5/6) Булева емулÑÑ†Ñ–Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð½Ð¾Ð³Ð¾ вибору Ñ– програмного визначеннÑ(5/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей програмного вибору, програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð° емулÑції (та додаткових).(2/6) ЦілочиÑельний маÑив з діапазоном обмеженнÑ(5/6) ЦілочиÑельний параметр з розмірніÑтю у точках на дюйм з викориÑтаннÑм маÑиву обмежень діапазону. Мінімальним значеннÑм може бути 4, макÑимальним — 192, крок — 2.(6/6) Булевий автоматичний програмний вибір, програмне визначеннÑ(6/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей програмного вибору, програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ– автоматичних (та додаткових) можливоÑтей. Цей параметри може автоматично вÑтановлюватиÑÑ Ñервером.(6/6) ЦілочиÑельний маÑив зі ÑпиÑком обмежень Ñлів(6/6) ЦілочиÑельний параметр з розмірніÑтю у відÑотках з викориÑтаннÑм маÑиву обмежень ÑпиÑку Ñлів.1/2 звичайної швидкоÑті1/3 звичайної швидкоÑті10мм15мм16-бітовий ÑірийДвоточкове20мм2x2 нетипове2x2 звичайне3x3 нетипове3x3 звичайнеЧотириточкове48-бітовий колір4x4 грубе4x4 нетипове4x4 добре4x4 звичайне5x5 грубе5x5 нетипове5x5 добре6x4 (дюймів)6x6 нетипове6x6 звичайне8-бітовий вивідВоÑьмиточкове8.5x11 (дюймів)8x10 (дюймів)Ð¡ÐµÐºÑ†Ñ–Ñ 8x88x8 Значна жирніÑть8x8 Помірна жирніÑть8x8 Вертикальна лініÑ8x8 грубе8x8 нетипове8x8 добре8x8 звичайне8x8 дуже добреТриваліша витримка надаÑть змогу Ñканеру накопичити більше Ñвітла. Рекомендуємо вам ÑкориÑтатиÑÑ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñм 175% Ð´Ð»Ñ Ð´Ñ€ÑƒÐºÐ¾Ð²Ð°Ð½Ð¸Ñ… документів, 150% Ð´Ð»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¸Ñ… Ñлайдів та «Ðегатив» Ð´Ð»Ñ Ð½ÐµÐ³Ð°Ñ‚Ð¸Ð²Ñ–Ð². Ð”Ð»Ñ Ñ‚ÐµÐ¼Ð½Ð¸Ñ… (недоекÑпонованих) зображень ви можете збільшити це значеннÑ.A3Папір A3ВиÑвлено папір A3A4Папір A4ВиÑвлено папір A4A5A5 альбомнаA5 книжковаA6ÐПДЗворот протÑжного механізмуДвобічна ÐПДПеред протÑжного механізмуРежим протÑжного приÑÑ‚Ñ€Ð¾ÑŽÐ§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐПДВідкрито кришку протÑжного Ð¼ÐµÑ…Ð°Ð½Ñ–Ð·Ð¼ÑƒÐ—Ð°Ñ—Ð´Ð°Ð½Ð½Ñ Ñƒ протÑжному механізміДоÑтуп до реÑурÑу забороненоДіÑ, Ñку буде виконано у відповідь на помилку подвійного подаваннÑÐ”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñтору у нижній чаÑÑ‚Ð¸Ð½Ñ–Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñтору у верхній чаÑтиніДодаток до Ñинього на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð”Ð¾Ð´Ð°Ñ‚Ð¾Ðº до Ñинього на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð”Ð¾Ð´Ð°Ñ‚Ð¾Ðº до зеленого на оÑнові Ñ€Ñ–Ð²Ð½Ñ ÑиньогоДодаток до зеленого на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð”Ð¾Ð´Ð°Ñ‚Ð¾Ðº до червоного на оÑнові Ñ€Ñ–Ð²Ð½Ñ ÑиньогоДодаток до червоного на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾ÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ Ñинім Ñ– червоним ÐºÐ°Ð½Ð°Ð»Ð°Ð¼Ð¸ÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ переднім Ñ– зворотним Ð±Ð¾ÐºÐ¾Ð¼ÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ зеленим Ñ– червоним каналамиДодатковоДодаткові параметриДодатковий захиÑÑ‚ паперуПіÑÐ»Ñ Ð½Ð°Ð´ÑÐ¸Ð»Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ розпочинати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ на Ñканері.Ð’ÑÑ– ÑторінкиÐадає змогу перевірити поведінку приÑтрою з викориÑтаннÑм інших підтримуваних моделейЗавжди вимикати лампу під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ñ— зониÐналогове підÑиленнÑÐналогова оболонкаÐналогова гама ÑиньогоÐналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸Ðналогова гама зеленогоÐналогова гама червоногоÐналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸Ðналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ ÑиньогоÐналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ðналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾ÐвтоÐвтоматичне порогове значеннÑÐвтоматичний поділ на облаÑтіÐвтовиштовхуваннÑÐвтоекÑпозиціÑÐвтоматичне фокуÑуваннÑОдноразове автофокуÑуваннÑÐвтовиÑÐ²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¸Ðвтоматичне або ручне фокуÑуваннÑÐвтовиÑÐ²Ð»ÐµÐ½Ð½Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ð¸ÐвтоматичноÐвтоматична подача документівÐвтоматичне Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð³Ð¾Ð²Ð¾Ð³Ð¾ значеннÑÐвтоматичне відокремленнÑÐвтоматичне визначеннÑРежим автоматичного порогового значеннÑÐвтоматичний розігрівÐвтоматично виштовхувати плівку з приÑтрою піÑÐ»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ ÑкануваннÑÐвтоматично виштовхувати плівку з приÑтрою перед завершеннÑм роботи програмиВÑтановлювати ÑÑкравіÑть, контраÑтніÑть, рівень білого, гаму, Ð·Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ ÑˆÑƒÐ¼Ð½Ð¾Ñті Ñ– виразніÑть Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾B4Папір B4ВиÑвлено папір B4B5Папір B5ВиÑвлено папір B5B6Фільтр СПЗворотКолір тлаЛіній поверненнÑКоефіцієнт баланÑу Ð´Ð»Ñ Ñинього. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ 100% означає «без виправленнÑ».Коефіцієнт баланÑу Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ 100% означає «без виправленнÑ».Коефіцієнт баланÑу Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ 100% означає «без виправленнÑ».СекціÑСекціÑСекційний дизеринг 16Секційний дизеринг 64Дворівневий чорно-білий (штриховий режим)Пов’Ñзаний RGBПов’Ñзати роздільні здатноÑті за X Ñ– YПов’Ñзана аналогова гамаПов’Ñзана гамаКількіÑть бітів на колірЧорнийРівень Ñ‡Ð¾Ñ€Ð½Ð¾Ð³Ð¾Ð¡Ð¸Ð½Ñ–Ð¹Ð‘Ð°Ð»Ð°Ð½Ñ ÑиньогоЯÑкравіÑть ÑиньогоПідÑÐ¸Ð»ÐµÐ½Ð½Ñ ÑÐ¸Ð½ÑŒÐ¾Ð³Ð¾Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñинього AFEІнтенÑивніÑть ÑÐ¸Ð½ÑŒÐ¾Ð³Ð¾Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ ÑÐ¸Ð½ÑŒÐ¾Ð³Ð¾Ð—Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ ÑÐ¸Ð½ÑŒÐ¾Ð³Ð¾Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñинього AFEДвійкові параметри перевіркиЗнизу догориÐÐ¸Ð¶Ð½Ñ Ð¿Ñ€Ð°Ð²Ð° координата за XКоордината X правого нижнього кута облаÑті ÑкануваннÑ.ÐÐ¸Ð¶Ð½Ñ Ð¿Ñ€Ð°Ð²Ð° координата за YКоордината Y правого нижнього кута облаÑті ÑкануваннÑ.ЯÑкравіÑтьРежим буферизаціїВбудований профіль CCTКнопка 1Кнопка 2Стан кнопкиПараметри перевірки кнопокКероване кнопкою ÑкануваннÑКнопкиКДПомилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ процеÑораЕПТМонітори з ЕПТКалібрувати Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ÐšÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ñ‚Ð¸ Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑиньогоКалібрувати Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾ÐšÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ñ‚Ð¸ Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾ÐšÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ñ‚Ð¸ інтенÑивніÑть лампиВідкалібруватиКалібрувати ÑканерКалібрувати перед наÑтупним ÑкануваннÑмКалібрувати фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ð½Ð· у облаÑті документаКалібрує Ð´Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ñ–Ð²Ð½Ñ Ñ‡Ð¾Ñ€Ð½Ð¾Ð³Ð¾ и білого.КалібруваннÑÐšÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¾ÑŽ обробкиСтрок дії кешу калібруваннÑÐšÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… калібруваннÑФайл калібруваннÑРежим калібруваннÑКалібруваннÑКнопка «Cancel»Картка (зворот)Картка (обидва боки)Картка (профіль)Змінити документ.Змінити документЗмінювати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ° наддруку на вказане чиÑло Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ñ— наÑтупної Ñторінки.Змінює інтенÑивніÑть напівтонівКаналЧекІдентифікатор мікроÑхемиÐазва мікроконтролераСпорожнити дані калібруваннÑСпорожнити кеш калібруваннÑГрубеГрубе калібруваннÑГрубе ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ð³Ð¾ ÑкануваннÑВиконувати грубе ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ð³Ð¾ ÑкануваннÑ. Працює на більшоÑті Ñканерів Ñ– надає змогу зекономити Ñ‡Ð°Ñ Ð½Ð° ÑкануваннÑ. Якщо ÑÑкравіÑть Ñканованих зображень значно змінюєтьÑÑ, зніміть позначку з цього пункту. Лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸.Зібрати дані щодо декількох міліметрів у верхній чаÑтині Ñканованого зображеннÑ, перш ніж аркуш потрапить до протÑжного приÑтрою, Ñ– збільшити макÑимальну облаÑть ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° межі вÑтановленого розміру паперу, а також дозволити Ð·Ð±Ð¸Ñ€Ð°Ð½Ð½Ñ Ñ€ÐµÑˆÑ‚Ð¸ даних з бічних полів. Може конфліктувати з параметром кольору тла.КольоровийКольоровий (48-бітовий)Кольоровий 36Кольоровий, напівтониКольоровий ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¸Ð¹ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²ÐšÐ¾Ð»ÑŒÐ¾Ñ€Ð¾Ð²Ð¸Ð¹ RAWКольоровий RGBКольоровий RGB TEXTÐ‘Ð°Ð»Ð°Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²ÐŸÐ°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¸ підÑÐ¸Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñ–Ð² кольорівПараметри зÑуву каналів кольорівКольорова компенÑаціÑКоефіцієнти Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²Ð¤Ñ–Ð»ÑŒÑ‚Ñ€ кольоруКольоровий візерунокКольоровий 24Кольоровий 36Кольоровий 48Кольорових ліній на ÑÐµÐ°Ð½Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½ÑСтиÑненнÑÐргумент ÑтиÑканнÑУмовноПродовжитиКонтраÑтніÑтьКонтраÑтніÑть Ñинього каналуКонтраÑтніÑть зеленого каналуКонтраÑтніÑть червоного ÐºÐ°Ð½Ð°Ð»ÑƒÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð·Ñ–Ñ€Ñ†ÐµÐ¼ фільтра Ð¿Ñ–Ð²Ñ‚Ð¾Ð½Ñ–Ð²ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ фільтра півтонівКерує відповідником Ñ€Ñ–Ð²Ð½Ñ Ð±Ñ–Ð»Ð¾Ð³Ð¾Ð’Ð¸Ð·Ð½Ð°Ñ‡Ð°Ñ” рівень ÑÐ¸Ð½ÑŒÐ¾Ð³Ð¾ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð´ÑƒÐ»ÐµÐ¼ наддрукуКерує рівнем зеленогоКерує рівнем червоногоКерує «відтінком» (рівнем Ñинього) отриманого зображеннÑ.Керує ÑÑкравіÑтю отриманого зображеннÑ.Керує ÑÑкравіÑтю каналу Ñинього у отриманому зображенні.Керує ÑÑкравіÑтю каналу зеленого у отриманому зображенні.Керує ÑÑкравіÑтю каналу червоного у отриманому зображенні.Керує контраÑтніÑтю отриманого зображеннÑ.Керує контраÑтніÑтю каналу Ñинього у отриманому зображенні.Керує контраÑтніÑтю каналу зеленого у отриманому зображенні.Керує контраÑтніÑтю каналу червоного у отриманому зображенні.Визначає, чи буде виконуватиÑÑ Ð¿Ñ€Ð¸Ð¼ÑƒÑове поверненнÑ.Кнопка «CopyÂ»Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ до типу Ð¿Ð»Ñ–Ð²ÐºÐ¸Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ до ÑÐ¿Ñ–Ð²Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€Ð¾ÑтіКришку відчиненоОбрізати до Ñправжньої облаÑті зображеннÑÐетиповаÐетипова Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð² Ð´Ð»Ñ Ñ‡Ð¾Ñ€Ð½Ð¾-білих зображень.Ðетипова Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð².Ð”Ñ–Ñ ÐŸÐŸÐŸÐŸ Ð´Ð»Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¸Ð Ñ–Ð·Ð½Ð¸Ñ†Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¸ Ð´Ð»Ñ ÐŸÐŸÐ ÐµÐ¶Ð¸Ð¼ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐŸÐŸÐŸÐŸ Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ¾ÑˆÑƒÐ²Ð°Ð½Ð½ÑПП Ð´Ð»Ñ Ñ‚Ð¾Ð²Ñ‰Ð¸Ð½Ð¸DTCПараметри зневаджуваннÑТиповийТиповіВизначає режим калібруваннÑВизначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑиньогоВизначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð’Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½ÑВизначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð’Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð’Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð’Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð’Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑкануваннÑВизначити інтенÑивніÑть Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½ÑВизначити інтенÑивніÑть лампи Ð´Ð»Ñ ÑкануваннÑВизначає параметр Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ ÑиньогоВизначає параметр Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ зеленогоВизначає параметр Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ червоногоВизначає напівтонового шаблон (дизеринг) Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð¿Ñ–Ð²Ñ‚Ð¾Ð½Ð¾Ð²Ð¸Ñ… зображень.Визначає маÑштаб, Ñкий буде викориÑтано ÑканеромЗатримка Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… до каналу.ЩільніÑÑ‚ÑŒÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‰Ñ–Ð»ÑŒÐ½Ñ–ÑтюÐабирач щільноÑтіВиÑвлÑти підшиті документиВизначає макÑимальне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ° наддруку.Визначає швидкіÑть, з Ñкою виконуєтьÑÑ ÑкануваннÑ.Визначає буде викориÑтано вбудовану чи нетипову таблицю гами.ПриÑтрій зайнÑтоПараметри приÑÑ‚Ñ€Ð¾ÑŽÐ”Ñ–Ð°Ð¼Ð°Ð½Ñ‚Ð Ñ–Ð·Ð½Ð¸Ñ†Ñ Ñƒ довжинах аркушів паперу, Ñка призводитиме до помилки подвійного подаваннÑДифузіÑВимкнути автоматичну подачу, викориÑтовувати лише планшетний механізмВимкнути зворотне ÑтеженнÑВимкнути динамічне штрихуваннÑВимкнути Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸Ð’Ð¸Ð¼ÐºÐ½ÑƒÑ‚Ð¸ інтерполÑціюВимкнути попереднє фокуÑуваннÑВимкнути викориÑÑ‚Ð°Ð½Ð½Ñ Ð°Ð´Ð°Ð¿Ñ‚Ð¸Ð²Ð½Ð¾Ð³Ð¾ програмного алгоритму Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑˆÑ‚Ñ€Ð¸Ñ…ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¼Ñ–Ñть апаратного алгоритму штрихуваннÑ.Вимкнути Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ñ‚Ñ–Ð½ÐºÑ–Ð² білогоDispersedDot16x16DispersedDot8x8Показати короткий ÑпиÑок роздільних здатноÑтейДизерингДизеринг A (ÑÐµÐºÑ†Ñ–Ñ 4x4)Дизеринг B (Ñпіраль 4x4)Дизеринг C (4x4 Net Screen)Дизеринг D (8x4 Net Screen)Дизеринг/Ðапівтони чорно-білого (напівтоновий режим)Карта дизерингу 1Карта дизерингу 2Виконувати чорно-біле ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¼Ñ–Ñть кольоровогоВиконати ÑкіÑне ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ñ–Ð»Ð¾Ð³Ð¾Ð’Ð¸ÐºÐ¾Ð½ÑƒÐ²Ð°Ñ‚Ð¸ автоматичне фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ раз між виштовхуваннÑмиÐе калібрувати фокуÑуваннÑÐе вÑтановлювати код Ñтану примуÑовоÐе примушувати інÑтрумент обробки повертати код Ñтану.Ðе зупинÑтиÑÑ Ð¿Ñ–ÑÐ»Ñ Ð²Ð¸ÑÐ²Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð´Ð²Ñ–Ð¹Ð½Ð¾Ð³Ð¾ подаваннÑПодача документівДодаткові інÑтрументи Ð¿Ð¾Ð´Ð°Ñ‡Ñ–Ð—Ð°Ñ—Ð´Ð°Ð½Ð½Ñ Ð½Ð¾ÑÑ–Ñ Ñƒ приÑтрої подачіУ приÑтрої подачі немає ноÑіївПодвоїти оптичну роздільну здатніÑтьПодвійне подаваннÑВиÑвлено подвійне подаваннÑВиÑÐ²Ð»ÐµÐ½Ð½Ñ Ð´Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð¾Ð³Ð¾ подаваннÑÐ—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‡ÑƒÑ‚Ð»Ð¸Ð²Ð¾Ñті датчика подвійного подаваннÑПодвійний лиÑÑ‚ 11x17 дюймівЗавантажити шаблон AЗавантажити шаблон BМаÑкаКолір Ð´Ð»Ñ Ð²Ð¸ÐºÐ¸Ð´Ð°Ð½Ð½ÑÐ”Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð°Ð—Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð´Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð¾Ð³Ð¾Ð”Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ðµ ÑкануваннÑЗа викориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð¾Ð³Ð¾ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ отримаєте одразу Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð»Ð¸Ñ†ÑŒÐ¾Ð²Ð¾Ð³Ð¾ та зворотного боків документаБік Ð´Ð»Ñ Ð´Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð¾Ð³Ð¾ÐŸÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡ двобічногоТриваліÑть затримки читаннÑКрива динамічного порогового значеннÑ, від Ñвітлого до темного, типово 50-65ВиштовхнутиВиштовхнути документ піÑÐ»Ñ ÑкануваннÑВиштовхувати плівку піÑÐ»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ ÑкануваннÑВиштовхувати плівку перед завершеннÑм роботиВиштовхнути плівкуВиштовхнути плівку *негайно*Виштовхнути аркуш з протÑжного приÑтроюКнопка «Email»ВиокремленнÑÐ†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ‡Ð¾Ñ€Ð½Ð¾-білогоУвімкнути двобічне ÑкануваннÑУвімкнути автоматичне Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð³Ð¾Ð²Ð¾Ð³Ð¾ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¸Ñ… зображень.Увімкнути автоматичне Ð²Ñ–Ð´Ð¾ÐºÑ€ÐµÐ¼Ð»ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ Ñ– текÑтуУвімкнути ÑтиÑÐºÐ°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ…. Може призвеÑти до аварійного Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ програмних оболонок.Увімкнути помилку подвійного Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· довжину паперуУвімкнути помилку подвійного Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· товщину паперуУвімкнути помилку подвійного Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· перекошуваннÑУвімкнути модуль наддрукуУвімкнути вибір чаÑу витримкиУвімкнути можливіÑть вибору інтенÑивноÑті лампиУвімкнути Ð·Ð³Ð»Ð°Ð´Ð¶ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»Ñ–Ð¿ÑˆÐµÐ½Ð½Ñ ÐžÐ Ð¢Ð£Ð²Ñ–Ð¼ÐºÐ½ÑƒÑ‚Ð¸ параметри перевіркиУвімкнути різноманітні параметри перевірки. Призначено Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ можливоÑтей оболонки переглÑдати Ñ– змінювати вÑÑ– параметри SANE.Увімкнути або вимкнути виÑÐ²Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð´Ð²Ñ–Ð¹Ð½Ð¾Ð³Ð¾ подаваннÑУвімкнути/Вимкнути режим ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¾ÑŽÐ£Ð²Ñ–Ð¼ÐºÐ½ÑƒÑ‚Ð¸/Вимкнути режим довгого паперуУвімкнути/Вимкнути автоматичне фокуÑуваннÑУвімкнути/Вимкнути можливіÑть автоекÑпонуваннÑВмикає або вимикає ÐºÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… калібруваннÑ.Вмикає або вимикає Ð¿Ñ€Ð¸ÑˆÐ²Ð¸Ð´ÑˆÐµÐ½Ð½Ñ Ñ€ÑƒÑ…Ñƒ датчика.ДоÑÑгнуто ÐºÑ–Ð½Ñ†Ñ Ñ„Ð°Ð¹Ð»Ð°ÐаддрукПараметри наддрукуY наддрукуБуквенно-цифровий формат наддруку. %05ud або %08ud наприкінці буде замінено на Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ°.Біти наддрукуÐапрÑмок наддрукуШрифт наддрукуЗÑув мітки наддруку від верхнього краю паперу.ÐапрÑмок друку.Шрифт наддруку.Бік, з Ñкого буде друкуватиÑÑ Ð¼Ñ–Ñ‚ÐºÐ°. Потребує апаратної підтримки Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸.Бік наддрукуКрок наддрукуРÑдок Ð½Ð°Ð´Ð´Ñ€ÑƒÐºÑƒÐ—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð½Ð°Ð´Ð´Ñ€ÑƒÐºÑƒÐŸÐ¾ÐºÑ€Ð°Ñ‰Ð¸Ñ‚Ð¸ ÑинійПокращити зеленийПокращити червонийРозширений режимПокращеннÑÐŸÐ¾ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¼Ð¸Ð»Ð¾ÐºÐšÐ¾Ð´ помилкиПомилка під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð´Ñ–Ð¹ з вводу-виводуПомінÑти міÑцÑми Ñтарший Ñ– молодший байти даних Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ 16-бітовий режимах. Цей пункт можна викориÑтовувати Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ 16-бітових режимів оболонок, наприклад, перевірки правильноÑті порÑдку байтів у оболонці.Виконати ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ³Ð°Ð¹Ð½Ð¾Ð•ÐºÑÐ¿ÐµÑ€Ð¸Ð¼ÐµÐ½Ñ‚Ð§Ð°Ñ ÐµÐºÑпозиціїЗбільшений Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸Ð—Ð±Ñ–Ð»ÑŒÑˆÑƒÑ” Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ (з 15 хвилин до 1 години)Дуже швидкоДодаткова кнопкаДодаткова ÐºÐ¾Ñ€ÐµÐºÑ†Ñ–Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²Ð”Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ–Ð¨Ð²Ð¸Ð´ÐºÐ¾Ð¨Ð²Ð¸Ð´ÐºÐ¸Ð¹ чорно-білий режимШвидкий переглÑдШвидке ÑкануваннÑШвидшаÐайшвидшаКнопка «Fax»Режим подачіКнопка «File»Ðазва файлаТип плівкиПлівкаВиÑокої ÑкоÑтіЧиÑтий ÐºÐ¾Ð»Ñ–Ñ€Ð‘Ð°Ð»Ð°Ð½Ñ Ð¼Ñ–ÐºÑ€Ð¾ÐºÐ¾Ð´ÑƒÐŸÐµÑ€ÑˆÐ¸Ð¹ запиÑЗа аркушемЗафікÑувати позицію фокуÑуваннÑДробовочиÑлові параметри перевіркиПланшетЛише планшетнийФокуÑуваннÑÐ¤Ð¾ÐºÑƒÑ 2,5 мм над ÑÐºÐ»Ð¾Ð¼ÐŸÐ¾Ð·Ð¸Ñ†Ñ–Ñ Ñ„Ð¾ÐºÑƒÑуваннÑÐ¤Ð¾ÐºÑƒÑ Ð½Ð° ÑкліТочка фокуÑуваннÑТочка фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑкануваннÑ.Режим фокуÑуваннÑТочка фокуÑуваннÑПримуÑове поверненнÑПримуÑовий чорно-білий переглÑдВказати Ñправжню глибинуВиконувати примуÑове ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´ ÑкануваннÑмÐаказати Ñерверу повертати код Ñтану SANE_STATUS_ACCESS_DENIED піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ sane_read().Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_COVER_OPEN піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ sane_read().Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_EOF піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ sane_read().Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_IO_ERROR піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ sane_read().Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_JAMMED піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ sane_read().Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_NO_DOCS піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ sane_read().Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_NO_MEM піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ sane_read().КадрКількіÑть кадрів на шаблоні, Ñкий має бути Ñкановано.Кадр, Ñкий буде ÑканованоВід паперуЗі ÑканераВід білої паличкиПередОчікувати натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ у передній чаÑтиніПовне ÑкануваннÑФункціÑФункціональний Ñимвол на екраніПараметри нечіткоÑтіПідÑиленнÑÐ“Ð°Ð¼Ð°Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ– Ð³Ð°Ð¼Ð¼Ð¸Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ буде вимкненоКрива гамиКрива гами, від Ñвітлого до темного, але верхні дві можуть не працюватиПоказник функції Ð³Ð°Ð¼Ð¸Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÐ¾ÐµÑ„Ñ–Ñ†Ñ–Ñ”Ð½Ñ‚Ð° контраÑтноÑÑ‚Ñ–Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ñиньої Ñмуги.Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ñ— Ñмуги.Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ñ— Ñмуги.Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸. Ð’ кольоровому режимі цей параметр одночаÑно змінює параметри червоного, зеленого та Ñинього каналів (тобто Ñ” таблицею інтенÑивноÑті гами).ÐŸÐ¾Ð·Ð¸Ñ†Ñ–Ñ Ñ– розміриГрупа розташуваннÑРозмір зернаСірийПідÑÐ¸Ð»ÐµÐ½Ð½Ñ ÑірогоРежим відтінків ÑірогоЗÑув ÑірогоЧорно-білий 16Чорно-білий 8Зробити чорно-білимВідтінки Ñірого, 4-бітоваВідтінки Ñірого, 8-бітоваСканувати у відтінках ÑÑ–Ñ€Ð¾Ð³Ð¾Ð—ÐµÐ»ÐµÐ½Ð¸Ð¹Ð‘Ð°Ð»Ð°Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð¯ÑкравіÑть зеленогоПідÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾ AFEІнтенÑивніÑть Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð—Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾ AFEЧорно-білих ліній на ÑÐµÐ°Ð½Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½ÑÒраткаПівтониПівтони A (Різкі тони)Півтони B (М’Ñкі тони)Півтони C (Net Screen)Ðапівтонова точка 32Ðапівтонова точка 64Шаблон напівтонівРозмір шаблону напівтонівТип півтонівÐапівтониÐапівтонове ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ підтримуєтьÑÑПерервати при ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ–Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ ÑÐºÐ°Ð½ÐµÑ€Ð°Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ ÑканераÐпаратне Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ñ…Ð¸Ð»Ñƒ Ñ– обрізаннÑКод апаратної помилкиÐпаратна Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð·Ð° X облаÑті ÑкануваннÑ.Ðпаратна Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð·Ð° Y облаÑті ÑкануваннÑ.Ðпаратна роздільна здатніÑтьПараметри обладнаннÑВиÑокийДрук з виÑокою контраÑтніÑтюДрук з виÑокою щільніÑтюВиÑока чутливіÑтьÐайкраща ÑкіÑть, але повільноÐайшвидше, але низька ÑкіÑтьПідÑвічуваннÑПідÑÐ²Ñ–Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑиньогоПідÑÐ²Ñ–Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾ÐŸÑ–Ð´ÑÐ²Ñ–Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾ÐŸÐ¾Ð·Ð¸Ñ†Ñ–Ñ Ñ„Ð¾ÐºÑƒÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´ÐµÑ€Ð¶Ð°ÐºÐ° 0 ммПо горизонталіЖирний по горизонталіВузький по Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»Ñ–Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ з буферів даних каналом.ВідтінокЯкщо обрано режим автоматичної подачі документів, приÑтрій подачі буде «Ñпорожнено» піÑÐ»Ñ 10 Ñканувань.Якщо буде позначено цей пункт, програма обробки Ñпробує визначити оптимальне порогове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ автоматичному режимі.Якщо позначено цей пункт, ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð² перед ÑкануваннÑм виконуєтьÑÑ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¾ÑŽ обробкиЯкщо буде позначено цей пункт, Ñканер не виконуватиме поверненнÑЯкщо буде позначено цей пункт, Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ заÑкановано у кольоровому режимі, а вже потім програмно перетворено на Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ тонах Ñірого. ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð±Ð½Ð¾Ð³Ð¾ підходу іноді може покращити ÑкіÑть зображеннÑ.Якщо позначено цей пункт, під Ñ‡Ð°Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ виконано лише Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð´Ð°Ñ†Ñ–Ñ—. ВикориÑтовуютьÑÑ Ñ‚Ð¸Ð¿Ð¾Ð²Ñ– (вбудовані або запозичені з файла налаштувань) Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾ÐµÑ„Ñ–Ñ†Ñ–Ñ”Ð½Ñ‚Ð° підÑиленнÑ, Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ð° чаÑу екÑпозиції.Якщо буде позначено цей пункт, деÑкі з зображень з процеÑу ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ збережено Ð´Ð»Ñ Ð¿Ð¾Ð´Ð°Ð»ÑŒÑˆÐ¾Ð³Ð¾ аналізу.Якщо позначити цей пункт, приÑтрій буде калібровано перед наÑтупним ÑкануваннÑм. У іншому випадку ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½ÑƒÐ²Ð°Ñ‚Ð¸Ð¼ÐµÑ‚ÑŒÑÑ Ð»Ð¸ÑˆÐµ перед першим ÑкануваннÑм.Якщо буде увімкнено гаму, ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð¶Ð´Ð¸ виконуватиметьÑÑ Ð· глибиною кольорів у 16 бітів Ð´Ð»Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ ÑкоÑті зображеннÑ, а вже потім перетворюватиметьÑÑ Ð´Ð¾ обраної глибини кольорів. За допомогою цього пункту можна уникнути такої емулÑції.Ігнорувати калібруваннÑІгнорувати центральний датчик подвійного подаваннÑІгнорувати лівий датчик подвійного подаваннÑІгнорувати правий датчик подвійного подаваннÑЗображеннÑÐŸÐ¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½ÑКольори Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ інвертованоВиразніÑть зображеннÑІнтенÑивніÑть зображеннÑПараметри видозміни зображеннÑМатричні принтериРівень чорнила Ð´Ð»Ñ Ð½Ð°Ð´Ð´Ñ€ÑƒÐºÑƒÐ›Ð¸ÑˆÐ¸Ð»Ð¾ÑÑ Ð¼Ð°Ð»Ð¾ чорнила Ð´Ð»Ñ Ð½Ð°Ð´Ð´Ñ€ÑƒÐºÑƒÐŸÐ¾Ð»Ñ–Ð¿ÑˆÑƒÑ” ÑкіÑть текÑту, напиÑаного кульковою ручкоюУ режимі RGB викориÑтовувати однакові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ кольоруЗбільшити або зменшити аналогове підÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ñ– ПЗЗІнформаціÑІнфрачервонеПочаткове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ° наддруку.ЗакінчуютьÑÑ Ñ‡Ð¾Ñ€Ð½Ð¸Ð»Ð°Ð›Ð¸ÑˆÐ¸Ð»Ð¾ÑÑ Ñ‡Ð¾Ñ€Ð½Ð¸Ð»Ð°Ð¡Ñ‚Ñ€ÑƒÐ¼Ð¸Ð½Ð½Ñ– принтериЦілочиÑельні параметри перевіркиÐекоректний аргументІнверÑивне зображеннÑІнверÑивне Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ чорно-білому режиміІнверÑивне Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ чорно-білому або півтоновому режиміІнвертувати порÑдок Ð±Ð°Ð¹Ñ‚Ñ–Ð²ÐŸÐµÑ€ÐµÐ²ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ð»Ñ–Ð²Ð¾Ñ€ÑƒÑ‡ Ñ– праворучJPEGСтиÑÐºÐ°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ JPEG з параметром Q, «0» — не ÑтиÑкатиСтиÑÐºÐ°Ð½Ð½Ñ JPEGСтиÑÐºÐ°Ð½Ð½Ñ JPEG (ваша програма повинна мати змогу розпакувати дані)Колір лампиЛампа не готова, будь лаÑка, повторіть ÑпробуВимкнути лампуВимикати лампу при Ð²Ð¸Ñ…Ð¾Ð´Ñ–Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ під Ñ‡Ð°Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ð³Ð¾Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ під Ñ‡Ð°Ñ ÑкануваннÑÐ§Ð°Ñ Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸Ð§Ð°Ñ Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ (у хвилинах)Увімкнути лампуСтан Ð»Ð°Ð¼Ð¿Ð¸Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸Ð§Ð°Ñ Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½ÑÐ§Ð°Ñ Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ у Ñекундах.Перемикач лампиÐльбомнаЛегалУ режимі ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¾ÑŽ Ñканер читає дані до найкоротшої з таких довжин: дійÑної довжини аркуша паперу або логічної довжини документа.Режим ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¾ÑŽÐšÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ð½Ð· у облаÑті документаДавайте переконаємоÑÑ Ñƒ правильноÑті обробки даних оболонкоюLetterРівень ÑтиÑÐºÐ°Ð½Ð½Ñ JPEG. 1 — малий файл, 7 — великий файл. 0 (типовий) — те Ñаме, що Ñ– 4.Обмежити викориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ð°Ð¼â€™Ñті драйвером на вбудованих ÑиÑтемах. Призводить до Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ð½Ð½Ñ Ð¾ÐºÑ€ÐµÐ¼Ð¸Ñ… боків аркуша у відповідь на кожен виклик sane_read. Відповідне Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ð½Ð° визначити за параметром «side». Цим параметром Ñлід кориÑтуватиÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð½ÐµÑ‚Ð¸Ð¿Ð¾Ð²Ð¾Ð³Ð¾ зовнішнього інтерфейÑу програмного забезпеченнÑ.Обмежити об’єм даних, що передаютьÑÑ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ виклику sane_read().ШтриховеЗавантажити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñк чорно-білеУ режимі довгого паперу Ñканер виконує Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ Ð¿Ð¾Ð´Ñ–Ð»Ñƒ довгого лиÑта паперу на відрізки довжини, вÑтановлені за допомогою параметра «Розмір документа»Режим довгого паперуВтрата точок на лініюÐÐ¸Ð·ÑŒÐºÐ¸Ð¹ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð°Ð¼â€™ÑтіДрук з низькою щільніÑтюÐизька чутливіÑÑ‚ÑŒÐŸÐ¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÐ ÐµÐ¶Ð¸Ð¼ Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÐ’Ð¸Ð±Ñ€Ð°Ð½Ð¾ режим Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÐ§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° подачу Ð²Ñ€ÑƒÑ‡Ð½ÑƒÐ’Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ— фокуÑа вручнуПопереднє фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÐŸÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿ вручну.ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ 2x2ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ 3x3ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ 4x4ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ 5x5Матричний множник RGBМакÑМінімальний діаметр окремих плÑм, Ñкі Ñлід уÑунути зі Ñканованого зображеннÑМінімальний діаметр окремих плÑм, Ñкі Ñлід уÑунути зі Ñканованого зображеннÑ.ÐоÑійСереднійОбробка ноÑіївÐапівтонÐапівтон Ð´Ð»Ñ ÑиньогоÐапівтон Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ðапівтон Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾ÐšÑ–Ð»ÑŒÐºÑ–Ñть хвилин, за Ñкі лампу буде вимкнено піÑÐ»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÑкануваннÑВіддзеркалити горизонтальноВіддзеркалити зображеннÑВіддзеркалити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ (Ð¿ÐµÑ€ÐµÐ²ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· лівий/правий край)Віддзеркалити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ горизонталі.Віддзеркалити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ вертикалі.Віддзеркалити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð¾.Віддзеркалити зображеннÑ.Віддзеркалити вертикальноВіддзеркаленнÑРізнеРежим 1Режим 2Режим 3Чорно-біла Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²Ð‘Ð°Ð³Ð°Ñ‚Ð¾Ñ€Ñ–Ð²Ð½ÐµÐ²Ð¸Ð¹ колір RGB (колір з одним проходом)Багаторівневий чорно-білий (режим відтінків Ñірого)Чорно-біле NTSCNTSC RGBПотребує калібруваннÑÐегативПлівка-негативСлайд-негативКольоровий негативÐегативТип плівки негативаЧорно-білий негативÐегатив Ð´Ð»Ñ Ð·Ð³Ð»Ð°Ð´Ð¶ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ позитив Ð´Ð»Ñ Ð·Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ Ñ€Ñ–Ð·ÐºÐ¾Ñті зображеннÑÐегативиБез виправленнÑБез виÑвленнÑБез Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€Ð¾ÑÑ‚Ñ–Ð—Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ ÑˆÑƒÐ¼Ð½Ð¾ÑÑ‚Ñ–Ð’Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ ÑˆÑƒÐ¼ÑƒÐемаєЗвичайнаЗвичайний режимЗвичайна швидкіÑтьКількіÑть бітів на колір, типовими значеннÑми Ñ” 1 Ð´Ð»Ñ ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¾Ð³Ð¾ Ñ– 8 Ð´Ð»Ñ Ð½Ð°Ð¿Ñ–Ð²Ñ‚Ð¾Ð½Ð¾Ð²Ð¾Ð³Ð¾ ÑкануваннÑ.КількіÑть ліній, на Ñкі повзунок ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð°Ñ” відÑтупити у разі потреби у поверненні. Подібне Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ðµ знадобитиÑÑ, Ñкщо ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð±ÑƒÐ²Ð°Ñ”Ñ‚ÑŒÑÑ ÑˆÐ²Ð¸Ð´ÑˆÐµ за Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð¿â€™ÑŽÑ‚ÐµÑ€Ð¾Ð¼ даних. Менші Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸ÑˆÐ²Ð¸Ð´ÑˆÐ°Ñ‚ÑŒ ÑкануваннÑ, але збільшать ймовірніÑть пропуÑку ліній.КількіÑть параметрівКількіÑть ліній ÑкануваннÑ, на Ñкі Ñлід надÑилати запит під Ñ‡Ð°Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð·Ñ– SCSI. За допомогою цього параметра ви зможете налаштувати швидкіÑть Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… зі Ñканера під Ñ‡Ð°Ñ ÑкануваннÑ. Якщо вÑтановити мале значеннÑ, під Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñканер зупинÑтиметьÑÑ Ñƒ процеÑÑ– ÑкануваннÑ. Якщо ж Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ завеликим, заÑновані на Ñервері X оболонки не відповідатимуть на події X, а ÑиÑтема значно уповільнитьÑÑ.Ðомер кадру Ð´Ð»Ñ ÑкануваннÑКнопка «OCR»OMR або ППВиÑвлено OMR або подвійне подаваннÑВимкнутиТаймер вимиканнÑПропонувати обрати деÑкриптор файла Ð´Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð¾Ð³Ð¾, чи повертатиме sane_read() дані.Пропонувати обрати деÑкриптор файлаЗÑувУвімкнутиОдна ÑторінкаОднопрохідні Ñканери викориÑтовують лише один колір під Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ відтінках Ñірого або чорно-білого ÑкануваннÑ, кориÑно Ð´Ð»Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ð¾Ð²Ð¾Ð³Ð¾ паперу або чорнильних запиÑівВиконати лише ÐºÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€Ð°Ð´Ð°Ñ†Ñ–Ñ—Ð”Ñ–Ñ Ð½Ðµ підтримуєтьÑÑДію було ÑкаÑованоДодаткове уÑтаткуваннÑÐе виÑтачає пам'ÑтіКонтурПолÑКнопка «PDF»ВиÑота ÑторінкиСторінку завантаженоШирина ÑторінкиПапір чаÑтково втÑгнуто до протÑжного приÑтроюЗахиÑÑ‚ паперуРозмір паперуПропуÑкатиВиконати Ð²Ð¸Ð´Ð¾Ð±ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÑƒÑ€ÑƒÐ’Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ ÑамодіагноÑтику ÑканераВиконує калібруваннÑФізичний розмір паперу у приÑтрої автоматичної подачіПозитивПлівка-позитивСлайд-позитивПозитивною чи негативною Ñ” плівкаКнопка «PowerÂ»Ð—Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ ÐµÐ½ÐµÑ€Ð³Ñ–Ñ—ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾ визначені параметриПопереднє захопленнÑПереглÑдРежим попереднього переглÑдуДрукÐадрукувати ÑпиÑок вÑÑ–Ñ… параметрів.Параметри друкуВизначає Ñтандартні облаÑті ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ð¹, друкованих Ñторінок та подібних документів.ЯкіÑне калібруваннÑЯкіÑне ÑкануваннÑШвидке форматуваннÑПомилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ пам’ÑтіRIFПомилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ ROMВипадковоБез обробкиЗатримка читаннÑÐ“Ñ€Ð°Ð½Ð¸Ñ†Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½ÑТеÑтовий параметр лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½ÑПараметр лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ, Ñкий визначає кількіÑть параметрів, Ñкі підтримують певні приÑтрої.Ð§ÐµÑ€Ð²Ð¾Ð½Ð¸Ð¹Ð‘Ð°Ð»Ð°Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð¯ÑкравіÑть червоногоПідÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾ AFEІнтенÑивніÑть Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð—Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾ AFEЗменшити шум від ізольованих точокВіддзеркалити отримане Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ горизонталіВідбитокВилучати пікÑельний шум розміром до 2 пікÑелівВилучати пікÑельний шум розміром до 3 пікÑелівВилучати пікÑельний шум розміром до 4 пікÑелівВилучати пікÑельний шум розміром до 5 пікÑелівЗапитати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду.Вимагати від програмного Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ñ– зі Ñторінок у автоматичному режиміВимагати від драйвера виÑÐ²Ð»ÐµÐ½Ð½Ñ Ñ– Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð° 90 градуÑівВимагати від драйвера Ð²Ñ–Ð´ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ñторінок з надто низькою кількіÑтю темних пікÑелівВимагати від драйвера Ð²Ñ–Ð´ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ñторінок з надто низькою питомою кількіÑтю темних пікÑелівÐаказати драйверу перервати Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°Ð¿ÐµÑ€Ñƒ, заміÑть його виштовхуваннÑ, Ñкщо ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÑкаÑовано.Вимагати від драйвера Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ñ– зі Ñторінок у автоматичному режиміВимагати від драйвера Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ñ– зі Ñторінок у автоматичному режимі.Вимагати від драйвера Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñторінок на фікÑований вказаний кутВимагати від драйвера уÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñторінок у автоматичному режиміВимагати від драйвера уÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñторінок у автоматичному режимі.Вимагати від Ñканера виÑвлÑти зам’ÑÑ‚Ñ‚Ñ Ñƒ протÑжному приÑтрої через ÑкобиÐаказати Ñканеру захопити наÑтупну Ñторінку із протÑжного приÑтроюВимагати від Ñканера передбачати зам’ÑÑ‚Ñ‚Ñ Ñƒ протÑжному приÑтроїВимагати від Ñканера передбачати зам’ÑÑ‚Ñ‚Ñ Ñƒ протÑжному приÑтрої за допомогою поліпшених датчиківÐаказати Ñканеру швидко читати Ñторінки з протÑжного приÑтрою до внутрішньої пам’ÑтіВимагати від Ñканера зворотного подаваннÑ, Ñкщо папір зам’ÑтоВимагати від Ñканера Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð° Ð¾Ð±Ñ€Ñ–Ð·Ð°Ð½Ð½Ñ Ñторінок у цифровому режимі.Ðаказати програмі виконувати вÑÑ– ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ–Ñ… переглÑдів у чорно-білому режимі. У режимі з трьома проходами кількіÑть проходів буде зменшено до одного, а на Ñканерах з одним проходом зменшує Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð° пам’Ñть Ñ– Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду.Ðаказує програмі Ñтворювати вÑÑ– попередні переглÑди у найшвидшому (низькоÑкіÑному) режимі. Цим режимом може бути чорно-білий режим або режим з низькою роздільною здатніÑтю.Потребує чорного тла Ð´Ð»Ñ ÑкануваннÑВідновити дані мікроконтролераСкинути параметри ÑканераСкинути параметри ÑканераВідновити початкові дані мікроконтролераПовернути SANE_STATUS_ACCESS_DENIEDПовернути SANE_STATUS_COVER_OPENПовернути SANE_STATUS_EOFПовернути SANE_STATUS_IO_ERRORПовернути SANE_STATUS_JAMMEDПовернути SANE_STATUS_NO_DOCSПовернути SANE_STATUS_NO_MEMКількіÑть повернутих неточних Ñ€Ñдків Ñ– байтів, Ñкщо sane_parameters() викликаєтьÑÑ Ð´Ð¾ sane_start().Повернуте Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ sane_readІнверÑивний формат зображеннÑОбернути Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð° год. ÑтрілкоюПомилка парноÑті SCSISDTCÐаÑиченіÑтьЗберегти зневаджувальні зображеннÑСкалÑрна гамаСкалÑрна гама ÑиньогоСкалÑрна гама зеленогоСкалÑрна гама червоногоРежим ÑкануваннÑГрупа режимів ÑкануваннÑПараметри облаÑті ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ– розмірів ноÑÑ–Ñ Ð´Ð°Ð½Ð¸Ñ…ÐšÐ½Ð¾Ð¿ÐºÐ° «Scan»Лічильник ÑкануваннÑÐ§Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ ÑкануваннÑÐ§Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑÐ¸Ð½ÑŒÐ¾Ð³Ð¾Ð§Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð§Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ñ‚Ð¸ у швидкому чорно-білому режимі (погана ÑкіÑть).ІнтенÑивніÑть лампи ÑкануваннÑÐŸÐ¾Ð»Ñ Ð¾Ð±Ð»Ð°Ñті ÑкануваннÑРежим ÑкануваннÑРоздільна здатніÑть ÑкануваннÑДжерело ÑкануваннÑШвидкіÑть ÑкануваннÑСканувати вÑÑŽ облаÑть ÑкануваннÑ, зокрема Ñмугу калібруваннÑ. Будьте обережні. Ðе вказуйте повну виÑоту. Лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸.Сканер автоматично визначає облаÑть Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ– обрізає йогоВідчинено кришку ÑканераСканер виÑвлÑÑ” нижній край паперу. Може призвеÑти до помилкової роботи деÑких програмних оболонок.Сканер визначає краї паперу. Може уповільнити ÑкануваннÑ.Сканер перебуває у режимі Ð·Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ ÐµÐ½ÐµÑ€Ð³Ñ–Ñ—ÐœÐµÑ…Ð°Ð½Ñ–Ð·Ð¼ Ñканера заблокованоМодель ÑканераДатчики Ñ– кнопки ÑканераСканер ÑтиÑкає Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ до розмірів Ð°Ñ€ÐºÑƒÑˆÐ°Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ зупинено, Ñкщо папір було вÑтавлено з нахиломДругий запиÑВизначає Ñекцію, Ñку буде ÑканованоОберіть тип плівкиОберіть мінімальну ÑÑкравіÑть Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ‚Ð¾Ñ‡ÐºÐ¸ білогоВизначити фільтр згладжуваннÑ.Визначає тип плівкиОберіть різновид теÑтового зображеннÑ. Можливі варіанти: Суцільний чорний: вÑÑŽ облаÑть ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñ„Ð°Ñ€Ð±Ð¾Ð²Ð°Ð½Ð¾ чорним. Суцільний білий: вÑÑŽ облаÑть ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñ„Ð°Ñ€Ð±Ð¾Ð²Ð°Ð½Ð¾ білим. Кольоровий візерунок: намалює різноманітні кольорові візерунки, залежно від режиму. Òратка: намалює чорно-білу ґратку з шириною Ñ– виÑотою 10 мм на квадрат.Оберіть режим попереднього переглÑду. Чорно-білий режим, зазвичай, дає найкращу комбінацію швидкоÑті Ñ– деталізації.Вкажіть повернуте Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ sane_read(). «Типове» означає звичайну обробку ÑкануваннÑ. Ð’ÑÑ– інші коди Ñтану призначено Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ ÑпоÑобів Ñ—Ñ… обробки оболонкою.Оберіть теÑтове зображеннÑВизначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑкалÑрного Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ (канал Ñинього).Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑкалÑрного Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ (канал зеленого).Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑкалÑрного Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ (канал червоного).Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑкалÑрного Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸.Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Â«Ð·ÐµÑ€Ð½Ð¸ÑтоÑті» Ñканованого зображеннÑ. Менші Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚Ð¸Ð¼ÑƒÑ‚ÑŒ до ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‡Ñ–Ñ‚ÐºÑ–ÑˆÐ¸Ñ… зображень.Визначає режим протÑжного приÑтрою (однобічний/двобічний)Визначає ÑÑкравіÑть.Визначає зв’Ñзок кольорів. «ОÑновний» визначає зв’Ñзок вÑÑ–Ñ… кольорів.Визначає маÑку.Визначає тип плівки, тобто негатив чи ÑлайдВизначити криву Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸Ð’Ð¸Ð·Ð½Ð°Ñ‡Ð°Ñ” режим Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ (ÑÑ‚ÑƒÐ¿ÐµÐ½Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð°ÑтноÑті).Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ñ€Ñ–Ð²Ð½Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð°ÑтноÑті (гами) зі ÑпиÑку попереднього визначених приÑтроїв або визначеної кориÑтувачем таблиці, Ñку можна завантажити у ÑканерВизначає півтон.Оберіть теÑтове зображеннÑВизначає кількіÑть кадрів Ð´Ð»Ñ ÑкануваннÑВизначає режим ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ (наприклад, штриховий, чорно-білий або кольоровий).Визначає джерело ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ (зокрема приÑтрій подачі документів)Визначає джерело ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ (зокрема приÑтрій подачі документів). Ð’Ñтановіть джерело перед режимом Ñ– роздільною здатніÑтю. Відновлює автоматично визначені Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ та роздільної здатноÑті.Визначає рівень ÑвітноÑті Ñинього, Ñкий Ñлід вважати «чорним».Визначає рівень ÑвітноÑті Ñинього, Ñкий Ñлід вважати «цілком Ñинім».Визначає рівень ÑвітноÑті Ñинього, Ñкий Ñлід вважати «білим».Визначає рівень ÑвітноÑті зеленого, Ñкий Ñлід вважати «чорним».Визначає рівень ÑвітноÑті зеленого, Ñкий Ñлід вважати «цілком зеленим».Визначає рівень ÑвітноÑті зеленого, Ñкий Ñлід вважати «білим».Визначає рівень ÑвітноÑті, Ñкий Ñлід вважати «чорним».Визначає рівень ÑвітноÑті, Ñкий Ñлід вважати «білим».Визначає рівень ÑвітноÑті червоного, Ñкий Ñлід вважати «чорним».Визначає рівень ÑвітноÑті червоного, Ñкий Ñлід вважати «цілком червоним».Визначає рівень ÑвітноÑті червоного, Ñкий Ñлід вважати «білим».Визначає, чи має бути отримане Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð¿Ñ–Ð²Ñ‚Ð¾Ð½Ð¾Ð²Ð¸Ð¼ (з дизерингом).Визначає рівень ÑвітноÑті, Ñкий Ñ” «50 % Ñинім».Визначає рівень ÑвітноÑті, Ñкий вважатиметьÑÑ Â«50 % Ñірим».Визначає рівень ÑвітноÑті, Ñкий Ñ” «50 % зеленим».Визначає рівень ÑвітноÑті, Ñкий Ñ” «50 % червоним».Визначає, Ñкий колір ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ викориÑтано у режимі напівтонів Ñірого (типово — зелений).СамодіагноÑтикаДатчикиРозділеннÑÐ’Ñтановити величину диÑперÑÑ–Ñ— SDTC (чутливіÑть), 0 відповідає 127Ð’Ñтановити інтенÑивніÑть ÑиньогоВÑтановити інтенÑивніÑть червоногоВÑтановити колір Ð´Ð»Ñ Ñ‚Ð»Ð° Ñканованих зображень. Може конфліктувати із параметром полів.Ð’Ñтановити типові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñм (ÑÑкравіÑтю Ñ– контраÑтніÑтю).Ð’Ñтановити типові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€ÐµÐ³ÑƒÐ»Ñторів покращеннÑ.Ð’Ñтановити режим ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‰Ñ–Ð»ÑŒÐ½Ñ–ÑтюВÑтановити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸Ð’Ñтановити інтенÑивніÑть лампиВÑтановлює Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ñ€ÐºÑƒÑˆÐ°: true — альбомне, false — книжковеВÑтановити Ð´Ð»Ñ Ð¿Ð¾Ñ€Ð¾Ð³Ð¾Ð²Ð¸Ñ… пікÑелів білий колір, а не чорнийВизначає величину Ð·Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ Ñ€Ñ–Ð·ÐºÐ¾Ñті.Ð’Ñтановити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‡ÑƒÑ‚Ð»Ð¸Ð²Ð¾Ñті датчика подвійного подаваннÑÐ’Ñтановити позицію фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— ÑиÑтеми вручну (типове значеннÑ: 128).Визначити порÑдок кадрівВизначити порÑдок кадрів у кольоровому режимі трьох проходів.Визначити матрицю кольорів Ñканера.Визначає Ñ‡Ð°Ñ (у хвилинах), через Ñкий лампу буде вимкнено.Визначити тип ноÑÑ–Ñ.Увімкнути/Вимкнути UTAВизначає підÑÐ¸Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñƒ ÑиньогоВизначає зÑув каналу ÑиньогоВизначає підÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñірого каналуВизначає зÑув каналу ÑірогоВизначає підÑÐ¸Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñƒ зеленогоВизначає зÑув каналу зеленогоВизначає Ñтан вмиканнÑ/Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸Ð’Ð¸Ð·Ð½Ð°Ñ‡Ð°Ñ” підÑÐ¸Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñƒ червоногоВизначає зÑув каналу червоногоВÑтановлює режим автоматичного порогового значеннÑÐ’Ñтановлює значеннÑ баланÑу кольорів на оÑнові даних з мікрокоду.Визначає таблицю Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð² Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ приÑтрою Ð²Ð¸Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ….Визначити режим подачіВизначає позицію фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° рівень від поверхні Ñкла до виÑоти 2,5 мм над ÑкломВизначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÐ¾ÐµÑ„Ñ–Ñ†Ñ–Ñ”Ð½Ñ‚Ð° контраÑтноÑті Ð´Ð»Ñ Ð²ÑÑ–Ñ… каналів.Визначає горизонтальну роздільну здатніÑть заÑканованого зображеннÑ.Визначає виразніÑть зображеннÑÐ’Ñтановлює колір лампи (Ð²Ñ–Ð´ÐºÐ¸Ð´Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²)Ð’Ñтановлює режим Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÐ’Ñтановлює Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½ÑƒÐ’Ð¸Ð·Ð½Ð°Ñ‡Ð°Ñ” роздільну здатніÑть Ñканованого зображеннÑ.Ð’Ñтановлює джерело ÑкануваннÑВизначає розмір напівтонового шаблону (дизерингу), що викориÑтовуєтьÑÑ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð¿Ñ–Ð²Ñ‚Ð¾Ð½Ð¾Ð²Ð¸Ñ… зображень.Визначає вертикальну роздільну здатніÑть заÑканованого зображеннÑ.Визначає автоматичний режим підÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñ– Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ ÑкануваннÑ. Якщо цей пункт не буде позначено, ви зможете вказати параметри аналогової оболонки вручну. Типово цей пункт позначено. Лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸.ЗатіненіÑтьЗатіненіÑть Ð´Ð»Ñ ÑиньогоЗатіненіÑть Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð—Ð°Ñ‚Ñ–Ð½ÐµÐ½Ñ–Ñть Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð—Ð°Ñ‚Ñ–Ð½ÐµÐ½Ñ–Ñть, напівтон, підÑвічуваннÑ, Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸Ð—Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ– різкоÑтіРізкіÑтьЗÑув Ñинього до зеленогоЗÑув Ñинього до червоногоЗÑув зеленого до ÑиньогоЗÑув зеленого до червоногоЗÑув червоного до ÑиньогоЗÑув червоного до зеленогоКороткий ÑпиÑок роздільних здатноÑтейПоказує назву мікроÑхеми, викориÑтаної у приÑтрої.Показує ідентифікатор мікроÑхемиПоказує кількіÑть Ñканувань, виконаних за допомогою ÑканераВимкнути лампуВимкнути лампу Ñканера.ОднобічнаІмітує ручний Ñканер. Ручні Ñканери попередньо не отримують даних щодо виÑоти зображеннÑ. ЗаміÑть цього, вони повертають виÑоту рівну -1. Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ параметра надає змогу перевірити, чи може оболонка правильно обробити такі дані. ÐŸÐ¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ пункту також увімкне фікÑовану ширину у 11 Ñм.Імітує ручний Ñканер. Ручні Ñканери чаÑто попередньо не отримують даних щодо виÑоти зображеннÑ. ЗаміÑть цього, вони повертають виÑоту рівну -1. Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ параметра надає змогу перевірити, чи може оболонка правильно обробити такі дані.Імітувати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ три проходи поверненнÑм 3 окремих кадрів. Буде повернено кадри Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾, Ñинього, а потім червоного кольору.Імітувати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð· трьома проходами. У кольоровому режимі буде повернуто три кадри.Розмір границі читаннÑÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐºÐ¾ÑˆÑƒÐ²Ð°Ð½Ð½ÑКут перекошуваннÑПропуÑтити процедуру розігрівуТаймер приÑиплÑннÑСлайдСлайдиПовільноПовільнаÐайповільнішаПлавнийЗгладжуваннÑПрограмне автоматичне обрізаннÑПорогове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ–Ñ… Ñторінок Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð½Ð¾Ð³Ð¾ відкиданнÑПрограмне обрізаннÑПрограмне уÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½ÑПрограмне уÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½ÑДіаметр плÑм Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð½Ð¾Ð³Ð¾ уÑуваннÑСуцільний чорнийСуцільний білийВибір джерелаПараметри джерела даних, режиму Ñ– роздільної здатноÑтіОÑобливі параметриСпеціальні параметриВизначає виÑоту ноÑÑ–Ñ.Визначає ширину ноÑÑ–Ñ. Це Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±Ð½Ðµ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ Ñ†ÐµÐ½Ñ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸Ñткових друкованих джерел.Вкажіть файл даних калібруваннÑ, Ñкі буде викориÑтаноПришвидшити датчикТиповоВиÑÐ²Ð»ÐµÐ½Ð½Ñ ÑкобПочати процедуру калібруваннÑ.Почати ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° допомогою Ñпеціального Ð°Ñ€ÐºÑƒÑˆÐ°Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ ÐºÐ¾Ð´Ñƒ ÑтануЗупинитиЗупинити ÑкануваннÑ, Ñкщо папір було перекошеноРÑдкові параметри перевіркиУÑпіхОбмінÑти міÑцÑми чорний Ñ– білийУвімкнути/Вимкнути модуль Ð´Ð»Ñ Ñлайдів (FAU, film adapter unit)Вмикає або вимикає лампу.Ðегативи TMAСлайди TMATPU8x10Тип дії Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚ÑƒÐ’Ð¸Ð·Ð½Ð°Ñ‡Ð°Ñ”, Ñкий бік (0=передній, 1=зворотний) двобічного Ñканованого Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ повернуто під Ñ‡Ð°Ñ Ð½Ð°Ñтупного виклику sane_read.Ð¢ÐµÑ…Ð½Ð¾Ð»Ð¾Ð³Ñ–Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ñ‚ÐµÐºÑтуОб’єм (макÑимальний) даних, Ñкі буде передано під Ñ‡Ð°Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ з викликів sane_read().Ðазва файла зображеннÑ, Ñке буде завантажено.Лампу буде вимкнено, коли Ñпливе вказаний Ñ‡Ð°Ñ (у хвилинах). Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ñ–Ð²Ð½Ðµ 0 означатиме, що лампа не вимикатиметьÑÑ.Лампу буде вимкнено під Ñ‡Ð°Ñ ÑкануваннÑ. КількіÑть точок, Ñкі було втрачено наприкінці кожної з ліній.Рівень наÑиченоÑті керує значеннÑм «вуалюваннÑ», Ñке додаватиметьÑÑ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð· фотоапарата. Більші Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ñ‚Ð¸Ð¼ÑƒÑ‚ÑŒ більше вуалюваннÑ.Ð”Ð»Ñ Ð·Ð°ÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ‚Ð¾Ñ‡Ð½Ð¸Ñ… параметрів потрібне калібруваннÑТермічні принтериТретій Ð·Ð°Ð¿Ð¸Ñ Ñ” затримуєтьÑÑ. Можливо, оболонка не може його показати.Цей пункт відповідає кнопці передньої панелі ÑканераЦей пункт відповідає Ñтану кнопки ÑкануваннÑ.Цей параметр відповідає Ñтану кнопок Ñканера.Якщо позначити цей пункт, лампу планшетного Ñканера на Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ трьох Ð¿Ñ€Ð¾Ñ…Ð¾Ð´Ñ–Ð²Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ трьох проходівПорігПорогова криваПорогова крива, від Ñвітлого до темного, але верхні дві не можуть бути лінійнимиПорогове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¾Ð³Ð¾ режимуБілий Ð¿Ð¾Ñ€Ñ–Ð³Ð§Ð°Ñ (у хвилинах), перш ніж завершитьÑÑ Ñтрок дії кешованих даних щодо калібруваннÑ. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ 0 означає, що кеш не викориÑтовуватиметьÑÑ. Від’ємні Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¾Ð·Ð½Ð°Ñ‡Ð°ÑŽÑ‚ÑŒ, що обмежень на Ñтрок дії кешу не накладатиметьÑÑ.Ð§Ð°Ñ Ñƒ хвилинах, по завершенню Ñкого внутрішнє Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ вимкнено. Буде округлено до найближчого кратного до 15 хвилин. Ðульове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¾Ð·Ð½Ð°Ñ‡Ð°Ñ”, що Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ðµ вимикатиметьÑÑ.Ð§Ð°Ñ Ñƒ хвилинах, по завершенню Ñкого внутрішнє Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ переведено у режим ÑнуПеремкнути лампу планшетного ÑканераПеремикає лампу планшетного ÑканераВерхній крайЗгори Ð²Ð½Ð¸Ð·Ð’ÐµÑ€Ñ…Ð½Ñ Ð»Ñ–Ð²Ð° координата за XКоордината X правого верхнього лівого кута облаÑті ÑкануваннÑ.Ð’ÐµÑ€Ñ…Ð½Ñ Ð»Ñ–Ð²Ð° координата за YКоордината Y правого верхнього лівого кута облаÑті ÑкануваннÑ.ПрозоріÑтьÐдаптер плівокМодуль Ð´Ð»Ñ ÑÐ»Ð°Ð¹Ð´Ñ–Ð²Ð¡Ð¿Ñ–Ð²Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€Ð¾ÑтіМодуль Ð´Ð»Ñ ÑлайдівВимкнути лампуВимкнути лампу під Ñ‡Ð°Ñ Ð²Ð¸Ñ…Ð¾Ð´Ñƒ з програмиВимкнути лампу ÑканераУвімкнути лампу ÑканераÐегайно вимикає лампу.Тип оригіналу Ð´Ð»Ñ ÑкануваннÑУвімкнути UTAÐевідомаВивантажитиВивантажити документ.Вивантажувати ноÑій піÑÐ»Ñ ÑкануваннÑВивантажує ноÑій піÑÐ»Ñ ÑкануваннÑ.Оновити Ñтан кнопкиОновити даніОновити параметриОновити параметри.Оновлює дані щодо приÑÑ‚Ñ€Ð¾ÑŽÐŸÐ¾Ð·Ð¸Ñ†Ñ–Ñ Ñ„Ð¾ÐºÑƒÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´ÐµÑ€Ð¶Ð°ÐºÐ° 0 мм заміÑть 0,6 ммВикориÑтовувати ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½ÑÐ”Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½ÑŒÐ¾Ñ— обробки викориÑтовувати глибини кольорів, більші за 8-бітові, але виводити дані лише у 8-бітовому форматі.ВикориÑтовувати неÑтандартну таблицю гамиВикориÑтовувати лінзу, Ñка подвоює оптичну роздільніÑтьВикориÑтовувати ручний або автоматичний вибір точки фокуÑуваннÑ.ВикориÑтовувати ввід-вивід без блокуваннÑВикориÑтовувати режим вводу-виводу без Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ sane_read(), Ñкщо підтримуєтьÑÑ Ð¾Ð±Ð¾Ð»Ð¾Ð½ÐºÐ¾ÑŽ.ВикориÑтовувати лише апаратні значеннÑВикориÑтовувати однакові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ð²ÑÑ–Ñ… каналів кольорів.ВикориÑтовувати однакові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð´Ñ–Ð»ÑŒÐ½Ð¸Ñ… здатноÑтей за X та YВикориÑтовувати 35 мм адаптер lightlidВизначене кориÑтувачемВизначене кориÑтувачем (Gamma=1.0)Визначена кориÑтувачем (Gamma=1.8)Визначений кориÑтувачем профіль CCTДиÑперÑÑ–ÑПо вертикаліЖирний по вертикаліОчікувати натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸Ðе починати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ на передній панелі Ñканера.Очікувати на натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸, перш ніж почати ÑкануваннÑРозігрівати, до Ñталої ÑÑкравоÑті лампи, не наполÑгати на 40-ти Ñекундному розігріві.Розігрівати, до Ñталої ÑÑкравоÑті лампи, не наполÑгати на 60-ти Ñекундному розігріві.Розігрів лампиРозігрівати лампу перед ÑкануваннÑÐ¼ÐŸÑ€Ð¾Ñ†ÐµÑ Ñ€Ð¾Ð·Ñ–Ð³Ñ€Ñ–Ð²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾Ð§Ð°Ñ Ñ€Ð¾Ð·Ñ–Ð³Ñ€Ñ–Ð²ÑƒÐ§Ð°Ñ Ñ€Ð¾Ð·Ñ–Ð³Ñ€Ñ–Ð²Ñƒ у Ñекундах.Якщо буде позначено цей пункт, Ð¿Ñ€Ð¾Ñ†ÐµÑ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ розпочинатиметьÑÑ Ð½ÐµÐ³Ð°Ð¹Ð½Ð¾. Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ, натиÑніть кнопку «SCAN» (MP150) або «COLOR» (Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… моделей). Ð”Ð»Ñ ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ñ‚Ð¸Ñніть кнопку «GRAY».Якщо визначено, Ñканер шукатиме новий документ, вÑтавлений до приÑтрою автоматичної подачі документів, протÑгом вказаної кількоÑті Ñекунд.За викориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ñ€ÑƒÐºÑƒ у півтонах або штрихового друку за допомогою цього пункту можна обрати колір друку.За викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ñоких роздільних здатноÑтей, коли горизонтальна роздільна здатніÑть менша за вертикальну, вимикає горизонтальну інтерполÑцію.БілийРівень білогоВідповідник Ñ€Ñ–Ð²Ð½Ñ Ð±Ñ–Ð»Ð¾Ð³Ð¾Ð Ñ–Ð²ÐµÐ½ÑŒ білого Ð´Ð»Ñ ÑиньогоРівень білого Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾Ð Ñ–Ð²ÐµÐ½ÑŒ білого Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð´Ð°Ñ†Ñ–Ñ— білого буде вимкненоРоздільна здатніÑть за XXPAЧорно-біле XPAXPA RGBРоздільна здатніÑть за YМаÑштабÐПДбаєр_16баєр_64ÑинійбізнеÑ_карткачбінтенÑивніÑть ÑиньогоінтенÑивніÑть червоногокольоровеПомилка під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð¿Ð¾ÑлідовноÑті командбезперервнеЕПТтемнетиповерозÑÑ–Ñнепомилка_розÑпланшетплівковий Ñканерза аркушемпланшетний ÑканерÑірийзеленийпівтонинапівтони_32напівтони_64Помилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ обладнаннÑвиÑокеОтримано Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ помилку виÑÐ²Ð»ÐµÐ½Ð½Ñ Ñ–Ð½Ñтрументу Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·Ð°Ñ†Ñ–Ñ—ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ некоректний біт IDENTIFYÐекоректний код команди діїÐекоректне поле у CDBÐекоректне поле у ÑпиÑку параметрівÐекоректне повідомленнÑÑтиÑÐºÐ°Ð½Ð½Ñ jpegЛампа не працюєЛампу не ÑтабілізованоÑвітлелінійнанизькеÑереднєВідÑутній ноÑійвідÑутні додаткові данінемаєзвичайневимкненоЗÑув за XЗÑув за YДодаткову функціональніÑть не з’єднаноПараметр змінено іншим інÑтрументом ініціалізаціїПомилка, пов’Ñзана з довжиною ÑпиÑку параметрівÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð²Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ / Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸ÑтроючервонийПомилка повторного виборуокруглений параметрпомилка Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ð¾Ð»Ñ–Ð²ÐºÐ¸ ÑкануваннÑÑканер з подачею Ð°Ñ€ÐºÑƒÑˆÑ–Ð²Ð¾Ð´Ð½Ð¾Ð±Ñ–Ñ‡Ð½Ð¸Ð¹Ð³Ð»Ð°Ð´ÐºÐµÐŸÐµÑ€ÐµÐ²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу очікуваннÑВказано забагато віконÐе працює лампа Ð¼Ð¾Ð´ÑƒÐ»Ñ ÑлайдівПомилка Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ð¾Ð»Ñ–Ð²ÐºÐ¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¿Ð»Ñ–Ð²Ð¾ÐºÐŸÐ¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð³Ñ€Ð°Ð´Ð°Ñ†Ñ–Ñ— у модулі ÑлайдівневідомаÐепідтримуване Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ LUNвизн_кориÑтувачемочік_документаочік_документа_з_бункераочік_клавішіВеб-камераsane-backends-1.0.27/po/pt.gmo0000664000175000017500000004513113110600540012761 00000000000000Þ•L]|ð ñ ü   #/AYl} •!¶Øøý +?PYq ƒ” ¤® ½É%Øþ%  3 >KN R_rŽ«Æ Øäõû&Ä5ú   !+:BJR[qˆ.,Ì(ù"4<E)]$‡*¬(×!"0@Dq¶¾Ø$î"6 Ua fpw ˆ ”  ¨²·È Ù)å*(:c lw | †’™Ÿ§­ ¾É Ùæëü  7AEXjz*޹ Ê%Ø=þ< M U _ s z ‚ ’ £ · 1» í  !!! !!+! 4! B!P!W!i!p! y! …! !ž!¦! Ã!Ñ! å!ò!ö!" " "'"?G"4‡"/¼" ì" ÷" #"#5#Q#n#‰# ›#¥# µ# Á#xÌ#E$)a$ ‹$.˜$<Ç$4%B9%|%Ž%;Ÿ%Û%ò% &"&;&S&m&ƒ&%›&4Á&#ö&''4')\'2†'̹'†(((®(½(Ð(Õ(Ü(ä())/)#K)o)")¢);³) ï) ù)!* &*!1* S*`*u*‡*(ž* Ç*`Ô*`5+ –+¢+ ¾+Ê+ß+õ+ ,, , ,,:, =,H, M,Y,^,o,u,|,,…,Œ,•,rž, . . (.3.6.H.Y.n.Œ.¢.».$Ö.%û.(!/ J/V/ l/x//¦/ ¾/Ë/ç/000 $020F0[08n0§08º0ó0ú0 11 1 1#:1$^1'ƒ1«1 Ã1Ð1 å1ï1:2òB25393 @3N3V3 ^3k3r3y3 €3Š3¢3»3&×3)þ3%(4N4f4u4…46¥4.Ü47 5:C5=~51¼5'î5E6\6e6!~62 6+Ó6ÿ6 7)717I7 Q7^7o7€7 “77¶7¼7Ñ7æ7&÷7'8*F8 q8{8Œ8•8§8 À8 Ì8 ×8â8è8ø8992999)S9}9!’9´9 ¼9È9ß9ó9 :0 :Q:o:4~:B³:ö:;!;*;J;Q;X;l;-‰;·;I¿; <<!<(< /<=<F<U<e<l< €< <™<¨<¸< Ç<'Ñ<ù< =%=B=K=^=p=ˆ=>¡=Mà=@.>Co> ³>¿>-×>$?.*?/Y?2‰? ¼?Ý?õ?@+@‹I@Õ@:ò@-A1=ADoA.´AJãA.BKBGdB¬BÀBÛBóBC'CCC[C-zC(¨C&ÑC#øC7DTD'pD¶˜DOEVEgEyEŽE­E³E ¹EÄE ÕEöE F%FEFXFvF:ŒFÇFàF9ôF.G:BG}GŒG©GÄG-âGHj)Hj”HÿH%I=INIiI…I ¤I ²I ¿IÍIßI âIìIóIJ JJ"J)J1J9J ?J KJsèÑSCpþÍݬäv‚§Š|W¨žHId¤ÉÊœ9Ö17‹šU¾&÷Pý:?†ÃLÅÒaÄ—O8¿J;”gÂG£Ïç<å^yŒØAõ¸ÚVƒB»îÿ·l Á¯®ö_“kbð"45„ß‘ˆâ$ã+±ø²ÛìŽ!ëº-¶#é]}¼fnwá™6…%­.>,{¦j'³ÌDÀz@æ=°` ò\½‡• ÆËNúh0X’– ÇoÙ´ê~óÎÞ‰ñ×eÈMF3YÜ*Ô€mÐZuŸRµà©ûTí¹c›Õ r(«xq¡ù tüKª/ÓQ¥¢ )2˜Eiïô[6x4 (inch)8.5x11 (inch)8x10 (inch)A4All pagesAnalog GainAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAutomaticAutomatic separationAutomatic thresholdAutomatic warmupBind RGBBind X and Y resolutionBind analog gammaBlack levelBlueBlue brightnessBlue gainBlue intensityBlue offsetBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton stateCDCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrationCalibration modeCheckCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor 36Color LineartColor RAWColor RGBColor RGB TEXTColor24Color36Color48ContrastContrast blue channelContrast green channelContrast red channelControls the brightness of the acquired image.Controls the contrast of the acquired image.Controls whether backtracking is forced.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.DiamondDouble Optical ResolutionDouble feed detectionEnable/Disable double feed detectionEnable/Disable length control modeEnable/Disable long paper modeEnhancementFastFast scanFasterFastestFilenameFirst entryFit to pageFlatbedFull scanGainGamma CorrectionGamma correctionGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.GeometryGrain sizeGrayGray gainGray offsetGray16Gray8GrayifyGreenGreen brightnessGreen gainGreen intensityGreen offsetGridHalftone patternHalftone pattern sizeHalftoningHardware specific optionsHighlightHueIgnore calibrationImage EnhancementImage intensityImpact-dot printersIn RGB-mode use same values for each colorInk-jet printersInverse ImageInverse image in B/W or halftone modeJPEG Image Compression with Q parameter, '0' - no compressionLamp off at exitLamp onLandscapeLength control modeLetterLineartLong paper modeManual feed modeManual feed timeoutMaxMaximum diameter of lone dots to remove from scanMirror image (left/right flip)Mode 1Mode 2Mode 3NTSC GrayNegativeNegative FilmNo CorrectionNormalNumber of optionsOffsetOne pagePage heightPage widthPositive FilmPreviewPrint a list of all options.Print optionsQuality calibrationQuality scanRedRed brightnessRed gainRed intensityRed offsetRequest a preview-quality scan.Request driver to discard pages with low numbers of dark pixelsRequest driver to remove border from pages digitallyRequest driver to rotate skewed pages digitallySaturationScan ModeScan area and media size optionsScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan lamp densityScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner sensors and buttonsScanner shrinks image to fit scanned pageSecond entrySelect minimum-brightness to get a white pointSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects whether the acquired image should be halftoned (dithered).Set exposure-timeSet lamp densitySet paper position : true for landscape, false for portraitSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets red channel gainSets red channel offsetSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the lamp color (color dropout)Sets the manual feed modeSets the manual feed timeout in secondsSets the resolution of the scanned image.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShift red to greenSlowSlowerSlowestSoftware automatic croppingSoftware blank skip percentageSoftware deskewSoftware despeckle diameterSource, mode and resolution optionsSpecial OptionsSpecifies the height of the media.Thermal printersThis option turns off the lamp of the flatbed during a scanThresholdTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitUse custom gamma tableUse lens that doubles optical resolutionUser definedWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWhite levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPA GrayY-resolutionbusiness_cardbwcontinuousdarkfit-to-pagehighjpeg compressionlightmediumnoneoffsmoothwait_docwait_keyProject-Id-Version: sane-backends 1.0.10 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-05-08 13:31+0200 Last-Translator: Pedro Morais Language-Team: pt Language: pt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 6x4 (pol)8.5x11 (pol)8x10 (pol)A4Todas as páginasGanho analógicoGama analógico azulCorreção analógica do gamaGama analógico verdeGama analógico vermelhoCorreção analógica gamaCorreção analógica gama para AzulCorreção analógica gama para VerdeCorreção analógica gama para VermelhoAutomáticoLimiar de aquecimentoAutomáticoSeparação automáticaLimiar de aquecimentoAquecimento automáticoVincular RGBVincular resoluções X e YVincular gama analógicoNível de pretoAzulBrilho do azulGanho do azulIntensidade do azulDeslocamento do azulInferior-direita xPosição de área de digitalização Inferior-direita xInferior-direita yPosição de área de digitalização Inferior-direita yBrilhoEstado do botãoCDCRTMonitores CRTTempo de exposição Cal.Tempo de exposição Cal. para azulTempo de exposição Cal. para VerdeTempo de exposição Cal. para VermelhoDensidade lâmpada Cal.CalibraçãoModo de calibraçãoVerificarCalibração rudimentarCalibração rudimentar apenas na primeira digitalizaçãoA calibração rudimentar apenas é realizada na primeira digitalização. Funciona com quase todos os digitalizadores e pode poupar tempo. Se o briho da imagem é diferente em cada digitalização, desactive esta opção. Apenas para testes.CorCor 36Linhas em corCor RAWCor RGBCor RGB TEXTCor 24Cor 36Cor 48ContrasteContraste do canal azulContraste do canal verdeContraste do canal vermelhoControla o brilho da imagem adquirida.Controla o contraste da imagem adquirida.ontrola se o backtracking é forçadoOpções de DepuraçãoPredefiniçãoPredefiniçõesDefinine o modo de calibraçãoDefinir tempo de exposição para calibração do azulDefinir tempo de exposição para calibraçãoDefinir tempo de exposição para calibração do verdeDefinir tempo de exposição para calibração do vermelhoDefinir tempo de exposição para digitalização do vermelhoDefinir tempo de exposição para digitalizaçãoDetermina em qual velocidade digitalizaDetermine se um builtin ou tabela customizada gama deve ser utilizadaDiamanteResolução ótica duplaDetecção de dupla alimentaçãoLiga / Desliga Modo de detecção de alimentaçãoLiga / Desliga Modo Controle do ComprimentoLiga / Desliga Modo Papel LongoMelhoriasRápidoDigitalização rápidaRápidoMais rápidoNome do ficheiroPrimeira entradaAdequar à páginaFlachbettDigitalização completaGanhoCorrecção do gammaCorrecção do gammaValor de 'gamma'Tabela correção Gama para banda azulTabela correção Gama para banda verdeTabela correção Gama para banda vermelhaGeometriaTamanho do grãoCinzentoGanho do cinzentoDeslocamento do cinzentoCinzento 16Cinzento 8AcinzentarVerdeBrilho do verdeGanho do verdeIntensidade do verdeDeslocamento do verdeGrelhaSimulação cinza padrãoTamanho padrão ponto - simulação cinzaSimulação de cinzaOpções específicas de hardwareClarearNatural-HueIgnorar a calibraçãoMelhorias de ImagemIntensidade da imagemImpressoras de agulhasEm modo RGB usar os mesmos valores para cada corImpressoras de jacto de tintaInverte imagemInverte imagem nos modos P/B ou simulação de cinzaCompressão da imagem JPEG com parâmetro Q, '0' - sem compressãoDesligar lâmpada na saídaLâmpada acesaPaisagemModo de Controle do ComprimentoLetterLinhasModo de Papel LongoModo de Alimentação manualTempo de desligamento da alimentação manualMáximoDiâmetro máximo de pontos isolados a serem removidos da digitalizaçãoImagem espelhadaModo 1Modo 2Modo 3NTSC cinzentoNegativoFilme NegativoSem CorrecçãoNormalNúmero de opçõesDeslocamentoUma páginaAltura páginaLargura páginaFilme PositivoPrevisãoImprime uma lista de todas as opções.Imprimir opçõesCalibração de qualidadeDigitalização de qualidadeVermelhoBrilho do vermelhoGanho do vermelhoIntensidade do vermelhoDeslocamento do vermelhoSolicitar pré-visualização com qualidade da digitalizaçãoSolicita ao driver para eliminar páginas com baixo número de pixels escurosSolicita ao driver para remover digitalmente bordas das páginasSolicita ao driver para rotacionar digitalmente páginas inclinadasSaturaçãoModo de DigitalizaçãoOpções de digitalização de área e mídiaTempo de exposição digitalizaçãoTempo de exposição digitalização para AzulTempo de exposição digitalização para VerdeTempo de exposição digitalização para VermelhoDensidade luz de digitalizaçãoModo de digitalizaçãoResolução digitalizaçãoOrigem da digitalizaçãoVelocidade de digitalizaçãoDigitalizar toda a área de digitalização, incluindo a faixa de calibração. Cuidado: não seleccione toda a altura. Apenas para testes.ensores e botôes do scannerScanner diminui imagem para adequar à pagina digitalizadaSegunda entradaSelecionar brilho mínimo para obter ponto brancoSelecionar Modo de digitalização ex. monocromático, colorido, ...Seleciona fonte para digitalização (ex. ADF)Defina se a imagem inserida deve ser simulada em cinza (halftone-dithered)Definir tempo de exposiçãoDefinir densidade da luzDefine posição do papel: Verdadeiro para Paisagem, Falso para RetratoGanho do canal azulDeslocamento do canal azulGanho do canal cinzentoDeslocamento do canal cinzentoGanho do canal verdeDeslocamento do canal verdeGanho do canal vermelhoDeslocamento do canal vermelhoDefine o valor de 'gamma' em todos os canais.Define resolução horizontal de saída Define cor da lâmpada (Color dropout)Define modo de alimentação manualDefine desligamento de alimentação manual em segundosefine resolução de saídaDefine resolução horizontal de saídaConfigurar automaticamente o ganho e deslocamento de digitalização. Se estiver desactivada são fornecidas opções para configurar manualmente este parâmetro. Apenas para testes.SombraSombra para azulSombra para verdeSombra para vermelhoDeslocar vermelho para o verdeLentoLentoMais lentoCrop automáticoDesconsiderar porcentagem brancoAlinhamento - DeskewDiâmetro despeckleOpções de Fonte, Modo e ResoluçãoOpções EspeciaisEspecifica a altura da mídiaImpressoras térmicasEsta opção desligar a lâmpada durante a digitalizaçãoValor do pixel-ThresholdSuperior-esquerda xPosição de área de digitalização Superior-esquerda xSuperior-esquerda yPosição de área de digitalização Superior-esquerda y TransparênciaAdaptador de TransparênciasUnidade de TransparênciasUsar tabela customizada gammaUsar lentes que duplicam a resolução óticaDefinido pelo utilizadorAquecer até o brilho da lâmpada ser constante em ver de insistir em 40 segundos de tempo de aquecimento.Aquecer até o brilho da lâmpada ser constante em ver de insistir em 60 segundos de tempo de aquecimento.Aquecimento da lâmpadaAquecer lâmpada antes de digitalizarNível de brancoNível de branco para azulNível de branco para verdeNível de branco para vermelhoX-ResoluçãoXPA cinzentoY-ResoluçãoCartão de visitaPBcontínuoescuroAdequar à páginaAltaCompressão JPEGclaroMédiaNenhumadesligaSuaveAguarde_docAguarde-Chavesane-backends-1.0.27/po/da.gmo0000664000175000017500000017105713110600537012737 00000000000000Þ•¨\‹œ*È8 É8-Ö8 9;9 L9,Y9"†9z©9 $:9.:h:€…:#;5*;"`;ƃ;J<je< Ð<Bñ<(4=S]=±=ØÈ=¡>BÀ>?l?‡?J—?+â?c@ r@z“@'A™6A$ÐAWõAMB UB `B kB vBB ‰B ”BŸB ¨B ³B ¾BÉB ÒB ÝB èB óBC C C "C,C?CPC bC mCxC C ŒCÒšCmD pD }D‰DD!–D¸D!ØD úDE ;E\EeEsvE êE ôEFF"F:FMF^F vF!—F¹FÙFÞFíF G GG!3GUGjG~G_GïG=ÿG>=H<|H¹H½HÃHÓH'ãH II,I >I II SI_I dIqI I‹I¦I µI ÃIÏIìIþI% J3J%BJ hJsJ|J …J’J¦J®J±J µJÂJÕJñJK)K ;KEKWK)rK%œK ÂKÎKåKüK LL.L6L=L&PLÄwLOyBŽy>Ñy?zDPz?•z9Õz9{=I{@‡{=È{B|>I|>ˆ|?Ç|=}<E}D‚},Ç}ô}~~-~1E~w~;–~Ò~å~õ~ %<Um‡˜®>Æ?€E€D[€% €4Æ€û€)X=2–ÌÉ–‚‚­‚¾‚)Í‚ ÷‚ ƒ ƒ ƒ2ƒFƒYƒkƒ~ƒ ”ƒ¢ƒ¹ƒüÁƒÐ¾„p…K†L†_†e†j†q†y† €† І –†¢†³†ÆÓ†â†ý†‡(‡=‡Z‡Gs‡'»‡uã‡=YˆŒ—ˆ$‰S5‰7‰‰;Á‰ý‰Š )Š3ŠJŠ jŠ!uŠ —Š!¢Š ÄŠÑŠæŠ øŠ ‹'‹=‹R‹r‹y‹€‹‘‹©‹É‹Ø‹.苌C-ŒqŒ(ˆŒ±ŒAÅŒ.&6] {ˆ¡ºÃÓ)ã` Ž`nŽ ÏŽÛŽ ÷Ž '<R fsw€ ˆ•šª» Ì‘4ב ’D’ ]’2j’$’ˆÂ’ K“?X“˜“·“&G”=n”$¬”àÑ”!²•€Ô• U–Ev–+¼–`è–I—öb—"Y˜J|˜ǘ„à˜e™Px™-É™l÷™)dšŒŽš)›¤E›*ê›Zœpœ xœ †œ ‘œ Ÿœªœ²œ »œÉœ ќܜ åœóœ ûœ   !.6 F T^r…– Ÿ­ µ ÀÚΩž¬ž »žÇž Ëž)Øž(Ÿ++Ÿ+WŸ)ƒŸ*­Ÿ ØŸâŸdûŸ ` k €  ¡ ¸ Ë Ý ô  ¡5¡ U¡`¡z¡•¡ ¨¡³¡(Í¡ö¡ ¢&¢a<¢ž¢4²¢5ç¢5£S£Z£`£p£*€£«£º£ Ø£ ù£ ¤ ¤¤ "¤ /¤;¤1N¤€¤¤£¤/´¤ä¤þ¤*¥:¥*K¥v¥}¥„¥ ‹¥™¥°¥¸¥ »¥ Æ¥Ò¥"ì¥#¦"3¦V¦ o¦{¦¦)¬¦$Ö¦ û¦§§5§J§Z§i§o§t§%„§Ðª§{¨¨Ѝ™¨ ¬¨ ¹¨ èͨ ݨ%ê¨-©>©N© l©z©ƒ©Œ©•©®©·©À©Ô©é©ý©ª1ªAJª/Œª@¼ªCýªAA«1ƒ«Bµ«Eø«C>¬4‚¬ ·¬,Á¬î¬­!­*­3­4P­1…­#·­5Û­2®4D®1y® «®$Ì®!ñ®0¯1D¯0v¯Z§¯-°'0°'X°G€°Ȱܰä°±±1±&E±l±s±‹±¤±Á±.Þ± ²"²47²&l²“²¨²4Ųú² ³$³4³D³ K³ X³.d³“³°³!¸³)Ú³&´O+´{´™´¸´Ó´0aµ)’µ ¼µ ǵ¼Õµ ’¶ž¶ ®¶»¶¶ɶá¶ù¶ ···/·7· @·L·P·d·v·‰·¡·©·É·Ú·ò·¸%/¸hU¸e¾¸^$¹cƒ¹aç¹bIºa¬º »»0» C»Q» b»l»r»‚»‘» ¡»&®»'Õ»&ý»”$¼ ¹¼żÔ¼ݼð¼ ½½%½ ,½7½G½W½i½ o½ }½н2ž½ѽâ½ö½0¾9¾V¾]¾f¾~¾–¾®¾À¾Ò¾ã¾ÿ¾¿'¿?¿W¿\¿w¿&”¿&»¿â¿ê¿û¿ ÀÀ7À\?À œÀQ¦À@øÀ>9ÁÓxÁLÂÜÂðÂøÂ ÃÃ*Ã5:Ã:pëúÃÏà äÃïà ÄÄ :Ä GÄTÄcÄ~Ä%Ä3³ÄçÄBîÄ 1Å>Å[ÅsÅwÅ“Å(¤ÅÍÅêÅïÅõÅ üÅÆÆ1ÆEÆWÆfÆ‚ÆÆ±ÆÂÆ ÊÆ ÕÆ àÆëÆ*ûÆ(&Ç OÇYÇbÇ jÇwLjǗÇÇ^¤ÇûÈÿÈvÉ–Ê´ÊP¼Ê Ë +Ë7Ë>ËFËbËqË Ë#ŒË °Ë½ËÛËãËóË(ùË"Ì58ÌnÌƒÌ –̤̹ÌÊÌ ÜÌeýÌcÍ hÍ uÍÍ1”ÍÆÍÖÍéÍ/úÍ *Î"KÎËn΀:Ï"»ÏÞÏþÏÐ5ÐQÐnÐ^ŠÐéÐÑ ÑÑ-ÑAÑTÑeÑ%‚Ñ&¨Ñ%ÏÑ0õÑ&Ò=ÒMÒaÒpÒvƒÒúÒ) Ó34ÓhÓ0Óy²Ô«,ÕØÕ7êÕ8"Ö7[Ö+“Ö\¿Ö/×L×D\ס×)³×!ÝׄÿׄØ1–ØFÈØ7Ù<GÙB„Ù=ÇÙ=ÚDCÚ>ˆÚ6ÇÚ6þÚ<5ÛBrÛ=µÛRóÛ:FÜ:Ü;¼Ü;øÜN4ÝEƒÝ2ÉÝüÝÞ-Þ(IÞDrÞ$·Þ;ÜÞß)ß%Dß)jß%”ß)ºß&äß* à6à%Qà)wàH¡à?êà*áEIá,á=¼áúá1âlGâ<´âÁñâ³ãºãÊãÛã,ëã ä&ä/äHä`äyä’äªäÃä Ùäåä åýåÛ æŒéæPvç Çç èçóç ûç èè è $è .è 9èCèXèmè‡è¥è¼è1Õèé"éF<é*ƒém®é8ê…UêÛê_êê7Jë<‚ë¿ëÚëõëì#ì:ì+Lìxì+Šì¶ì »ì Çì Ñì6Ýìí.íFí aílítí‹í-©í×íîí2î9î;RîŽî1¨îÚîOòî/Bï*rïï½ïÍïéïð ð ð7(ðe`ðeÆð,ñ=ñZñiñ „ññ¥ñ»ñ ÐñÝñáñêñ òñ ÿñ òò“”b=  X¡¨5ˆ‰á¤@lZ…¸$"­<ôtÈ걃l± »*ây—c½Ò'V6ñAAVwuHs<À²1€&o’FCú¢ÅòȂίQT"|}9¼Hì«LÄBº;Z•?i tòM%¿2‹™ÔJ[°aFëc&³PW}žå£\s¹‹6`aœ+þ(##‡£¢zbþ< ìüKGxéO›´”H²_N2JKÉ¥U`¾¾:O™ß“|䧆— %˜Ã¢ßL\ SÚú'Ø©ŠnJ^:j6‘!¡8KÁ.3›ÊºrNoˆd¥{éÞ´móA•‰Æ4öIÙæd‚jŸù‰ý¶QfÓû$‡†íí®¼ ¿cvOsZ eŽxD! ãØÕ1Sø*›n–@£ ž¦ÐqŠhè4SeÂGYÝ)P.|œ ·^æê0(MžŘœEt*×"Ï×7Í-Mãu—D}rç Q9`Ç»yi’ËÇ>~ø>l7b¤{)ýÃ=1çµf_¤ïIðЬËNR­‚-‡ÖÎÔïð…Œjö€?/uš+®R ¦‘V³Yp[E(^ÊÑÌ5¸ˆ]e¹÷: $T]”àYfñµ=y½Œ~™hXá]ÿq[9_ h.\õvCª78~W/ûÐ÷‘dXŸE-3¯ÀÛàÉÍÁ!Ö¡U Uša0) /qÝ#42wW¨˜k‹ƒ…åBwI–rk§0¨zÑFRóxÙÚC§@'Lgù,ÿ„5Ïškp„ôÒîv’Ó·mëTÜŒ„Ä•¶ âÌ–&ünpèä{ÆÕƒ+ª%Þ Ž«;gmŸõ8?¦ÛPDB†,ig©¥°;>,3zÂoÜ“ ¬G(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF ModeAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAnalog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton 1Button 2Button stateButton test optionsButtonsCDCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeChange Document.Change documentChannelCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.CustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device-SettingsDiamondDisable backtrackingDisable pre focusDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject the sheet in the ADFEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enables or disables calibration data cache.Enables or disables speeding up sensor movement.EnhancementError DiffusionExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.ExperimentExposure timeExtra FastExtrasFastFast gray modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFilm-stripFineFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.Ignore calibrationImageImage EnhancementImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp off timeLamp off time (minutes)Lamp onLamp statusLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMidtoneMidtone for blueMidtone for greenMidtone for redMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNo CorrectionNoise reductionNoneNormalNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOptional equipmentPaper sizePass-throughPhysical size of the paper in the ADFPositive FilmPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRandomizeRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Return SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSaturationScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Second entrySelect bay to scanSelect minimum-brightness to get a white pointSelect smoothing filter.Select the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Set default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set exposure-timeSet lamp densitySet sharpening value.Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSlideSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsSpeedup sensorStart calibration process.Status Code SimulationString test optionsSwap black and whiteSwitches the lamp on or off.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update optionsUpdate options.Use 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Warm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup-timeWarmup-time in seconds.White levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomflatbed scannersheetfed scannerProject-Id-Version: sane-backends 1.0.17 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-12-17 22:59+0100 Last-Translator: Mogens Jaeger Language-Team: Danish Language: da MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 1.10 Plural-Forms: nplurals=2; plural=(n != 1); X-Poedit-Language: Danish X-Poedit-Country: DENMARK X-Poedit-SourceCharset: utf-8 (1/1) Knap(1/1) Knap testindstilling. Udskriver noget tekst...(1/3) Faste(1/3) Faste testindstillinger uden enhed og ingen restriktioner sat.(1/3) Streng(1/3) Streng testindstillinger uden restriktioner.(1/6) Boolsk soft select soft detect(1/6) Dette er en boolsk testindstilling, som er "soft select" og "soft detect" (og "avanceret"). Dette er en normal boolsk indstilling.(1/6) Heltal(1/6) Heltal testindstilling uden enhed og uden begrænsninger.(2/3) Fast restriktionsomrÃ¥de(2/3) Fast testindstilling, med enhed i microsekund og restriktionsomrÃ¥de sat. Minimalt er -42.17, og maksimalt 32767.9999, og mængde er 2.0.(2/3) Streng restriktioner strengliste(2/3) Streng testindstillinger med strengliste restriktioner.(2/6) Boolsk hard select soft detect(2/6) Dette er en boolsk testindstilling, som er "hard select" og "soft detect" (og "avanceret"). Dette betyder, at indstillingen ikke kan ændres fra forenden, men af brugeren (f.eks. ved at trykke pÃ¥ en knap pÃ¥ enheden).(2/6) HeltalsbegrænsningsomrÃ¥de(2/6) Heltal testindstilling med enheden "pixel" og et begrænsningsomrÃ¥de. Minimum er 4, maksimum 192, og skridtlængden er 2.(3/3) Fast restriktions ordliste(3/3) Fast testindstilling uden enheder og restriktions ordliste sat.(3/3) Streng restriktioner lang strengliste(3/3) Streng testindstillinger med strengliste restriktioner. Indeholder nogle flere indgange...(3/6) Boolsk hard select(3/6) Dette er en boolsk testindstilling, som er "hard select" (og "avanceret"). Dette betyder, at indstillingen ikke kan ændres fra forenden, men af brugeren (f.eks. ved at trykke pÃ¥ en knap pÃ¥ enheden), og at det ikke kan læses af forenden.(3/6) Heltalsbegrænsningsordliste(3/6) Heltal testindstilling med enheden "bit" og en ordlistebegrænsning.(4/6) Boolsk soft detect(4/6) Dette er en boolsk testindstilling, som er "soft detect" (og "avanceret"). Dette betyder, at indstillingen er skrivebeskyttet.(4/6) Heltal tabel(4/6) Heltal testindstilling med enheden "mm" og en tabel uden indskrænkninger.(5/6) Boolsk soft select soft detect emulered(5/6) Dette er en boolsk testindstilling, som er "soft select" ,"soft detect"og "emulated" (og "avanceret").(5/6) Heltal tabel med begrænset omrÃ¥de(5/6) Heltal testindstilling med enheden "dpi" og en tabel med et begrænset omrÃ¥de. minimum er 4, og maksimum 192, og skridtlængden er 2.(6/6) Boolsk soft select soft detect auto(6/6) Dette er en boolsk testindstilling, som er "soft select" ,"soft detect"og "automatic" (og "avanceret"). Denne indstilling kan sættes automatisk fra bagenden.(6/6) Heltal tabel med begrænset ordliste(6/6) Heltal testindstilling med enheden "procent" og en tabel med en begrænset ordliste.2-pixel2x2 tilpasset2x2 normal3x3 tilpasset3x3 normal4-pixel4x4 grov4x4 tilpasset4x4 fin4x4 normal5x5 grov5x5 tilpasset5x5 fin6x4 (tommer)6x6 tilpasset6x6 normal8 bit uddata8-pixel8.5x11 (tommer)8x10 (tommer)8x8 Bayer8x8 grov fortykning8x8 fin fortykning8x8 lodret linie8x8 grov8x8 tilpasset8x8 fin8x8 normal8x8 meget finEn længere eksponeringstid lader skanneren indsamle mere lys. Anbefalet brug er 175% for papirbilleder, 150% for diapositiver og "Negativ" for negativer. Ved mørke (undereksponerede) billeder, kan denne værdi øges.A4A5 tværformatA5 portrætADFADF-tilstandØger det blÃ¥, baseret pÃ¥ grønt niveauØger det blÃ¥, baseret pÃ¥ rødt niveauØger det grønne, baseret pÃ¥ blÃ¥t niveauØger det grønne, baseret pÃ¥ rødt niveauØger det røde, baseret pÃ¥ blÃ¥t niveauØger det røde, baseret pÃ¥ grønt niveauAvanceretAvancerede indstillingerNÃ¥r skankommando er sendt, starter skanningen først nÃ¥r der er trykket pÃ¥ knappen pÃ¥ skanneren.Alle siderAnalog forstærkningAnalog forendeAnalog gamma blÃ¥Analog gammakorrektionAnalog gamma grønAnalog gamma rødAnalog gammakorrektionAnalog gammakorrektion for blÃ¥Analog gammakorrektion for grønAnalog gammakorrektion for rødAutomatiskAutomatisk tærskelværdiAutomatisk omrÃ¥deopdelingAutomatisk skub udAutomatiskAutomatisk dokumentføderAutomatisk justering af tærskelværdierAutomatisk separeringAutomatisk tærskelværdiAutomatisk opvarmningAutomatisk indstilling af lyshed, kontrast, hvid balance, gamma, støjreduktion og billedbetoningBagudrettede linierBalancefaktor for blÃ¥. 100% giver ingen korrektion.Balancefaktor for grøn. 100% giver ingen korrektion.Balancefaktor for rød. 100 % giver ingen korrektion.SkuffeBayerBayer dither 16Bayer dither 642 niveau sort/hvid (stregtegningstilstand)Sammenbind RGBSammenbind X- og Y-opløsningSammenbind analoge gammaværdierFælles gammaBit dybdeSort niveauBlÃ¥BlÃ¥ balanceBlÃ¥ lyshedBlÃ¥ forstærkningBlÃ¥ forstærkningsværdi for den analoge forendeBlÃ¥ intensitetBlÃ¥ lampe slukketBlÃ¥ forskydningBlÃ¥ forskydningsværdi for den analoge forendeBoolske testindstillingerNederst-højre xNederste-højre x position af skanomrÃ¥de.Nederst-højre yNederste-højre y position af skanomrÃ¥de.LyshedKnap 1Knap 2Knap tilstandKnap testindstillingerKnapperCDCRT skærmCRT skærmeKalibrér eksponeringstidKalibrér eksponeringstid for blÃ¥Kalibrér eksponeringstid for grønKalibrér eksponeringstid for rødKalibrér lampe densitetKalibreringKalibrér skannerKalibrér før næste skanningKalibrér linsefokus pÃ¥ dokumentpositionKalibrerer for sort og hvidt niveau.KalibreringKalibrering ved bagendeKalibreringsdatacacheKalibreringstilstandSkift dokument.Skift dokumentKanalGrovGrovkalibreringGrovkalibrering kun for første skan.Grovkalibrering udføres kun for første skanning. Virker med de fleste skannere og kan spare skanningstid. Hvis billedets lyshed er forskellig for hvert skan, fravælg denne indstilling. Kun til testformÃ¥l.FarveFarve 36Farve halvtoneFarve stregtegningFarve matrixFarve RAWFarve RGBFarve RGB TEKSTFarvebalanceFarvekanalforstærkningsindstillingerIndstillinger for farvekanalernes forskydningFarvekorrektionFarvekorrektionskoefficienterFarvemønsterFarve 24Farve 36Farve 48Farvelinier pr. læsningBetingetKontrastKontrast blÃ¥ kanalKontrast grøn kanalKontrast rød kanalFastsætter blÃ¥t niveauKontrollerer grønt niveauFastsætter rødt niveauFastsætter farvetone (blÃ¥t niveau) for det rekvirerede billede.Fastsætter lyshed for det rekvirerede billede.Fastsætter lysheden i den blÃ¥ kanal i det rekvirerede billede.Fastsætter lysheden i den grønne kanal i det rekvirerede billede.Fastsætter lysheden i den røde kanal i det rekvirerede billede.Fastsætter kontrast for det rekvirerede billede.Fastsætter kontrasten i den blÃ¥ kanal i det rekvirerede billede.Fastsætter kontrasten i den grønne kanal i det rekvirerede billede.Fastsætter kontrasten i den røde kanal i det rekvirerede billede.Fastsætter om bagudrettet sporing er gennemtvunget.TilpassetTilpasset farve matrix for grÃ¥toneskanning.Tilpasset farve matrix.FejlsøgningsindstillingerStandardStandardDefiner kalibreringstilstandAngiv belysningstid for kalibrering af blÃ¥ farvedelAngiv belysningstid for skanning af blÃ¥ farvedelAngiv belysningstid for kalibreringAngiv belysningstid for kalibrering af grøn farvedelAngiv belysningstid for skanning af grøn farvedelAngiv belysningstid for kalibrering af rød farvedelAngiv belysningstid for skanning af rød farvedelAngiv belysningstid for skanningAngiv lampe densitet for kalibreringAngiv lampe densitet for skanningFastsætter parametre for slukning af blÃ¥ lampeFastsætter parametre for slukning af grøn lampeFastsætter parametre for slukning af rød lampeAngiver det halvtonegitter (dithering) der skal anvendes ved skanning af halvtonebilleder.Angiver zoomfaktoren som skanneren skal brugeForsink overførsel af data til røret.Fastlægger hastigheden for skanningen.Fastlægger om en indbygget eller en tilpasset gamma-tabel skal bruges.EnhedsindstillingerDiamantDeaktiver bagudrettet sporingDeaktiver pre-fokuseringSpredte punkter 16x16Spredte punkter 8x8Vis kort liste med mulige opløsningerDitherDithering A (4x4 Bayer)Dithering B (4x4 spiral)Dithering C (4x4 net/skærm)Dithering D (8x4 net/skærm)Dithered/halvtone sort/hvid (halvtonetilstand)Ditheringsmønster 1Ditheringsmønster 2Udfør en grÃ¥skalaskanning fremfor en farveskanningForetag en kvalitets hvid-kalibrering.Kalibrér ikke fokusGennemtving ikke status kodeTving ikke bagenden til at returnere en status kode.Dokument føderDobbelt optisk opløsningHent mønster AHent mønster BUdfaldDobbeltsidetDuplex skanDuplex skan, skanner begge sider af dokumentetVarighed af læseforsinkelseSkub udSkub dokumentet ud efter skanningSkub arket i den automatiske arkføder udAktiver Duplex (dobbeltsidet) skanningAktiver automatisk fastsættelse af tærskelværdi for stregtegningsskanninger.Aktiver valg af belysningstidAktiver valg af lampe densitetAktivér testindstillingerAktivér forskellige testindstillinger. Dette er til at afprøve om forenderne kan vise og ændre alle de forskellige SANE indstillingstyper.Aktivér eller deaktivér kalibreringsdatacache.Til/fra for øgning af sensors hastighed.ForbedringFejlspredningBytter om pÃ¥ den øvre og nedre byte i billedata i 16 bit tilstand. Denne indstilling kan bruges til at teste forendens 16 bit tilstand, d.v.s. om forenden anvender en korrekt endianness.EksperimentEksponeringstidMeget hurtigEkstraHurtigHurtig grÃ¥tonetilstandHurtig forhÃ¥ndsvisningHurtig skanningHurtigereHurtigstArkføder tilstandFilnavnFilmtypeFilm-stribeFinFastprogram balanceFørste angivelseFast fokuspositionFaste testindstillingerFlatbedFokusér 2,5 mm over glaspladenFokuseringspunktFokusér pÃ¥ glaspladenGennemtving bagudrettet sporingGennemtving monokrom smugkigGennemtving kalibrering før skanningTving bagenden til at returnere statuskoden SANE_STATUS_ACCESS_DENIED efter sane_read() er blevet kaldt.Tving bagenden til at returnere statuskoden SANE_STATUS_COVER_OPEN efter sane_read() er blevet kaldt.Tving bagenden til at returnere statuskoden SANE_STATUS_EOF efter sane_read() er blevet kaldt.Tving bagenden til at returnere statuskoden SANE_STATUS_IO_ERROR efter sane_read() er blevet kaldt.Tving bagenden til at returnere statuskoden SANE_STATUS_JAMMED efter sane_read() er blevet kaldt.Tving bagenden til at returnere statuskoden SANE_STATUS_NO_DOCS efter sane_read() er blevet kaldt.Tving bagenden til at returnere statuskoden SANE_STATUS_NO_MEM efter sane_read() er blevet kaldt.Fra papirFra kalibreringsstriberVent pÃ¥ frontknapFuld skanningUklare parametreForstærkGammaGammakorrektionGamma tabellerGammakorrektionGamma værdiGamma korrektionstabel for blÃ¥ kanal.Gamma korrektionstabel for grøn kanal.Gamma korrektionstabel for rød kanal.Gamma korrektionstabel. I farve tilstand pÃ¥virker denne indstilling de røde, blÃ¥ og grønne kanaler ens (dvs., der er en intensitets gammatabel).SkanomrÃ¥deKornstørrelseGrÃ¥toneGrÃ¥-forstærkningFarve ved grÃ¥tone tilstandGrÃ¥-forskydningGrÃ¥ 16GrÃ¥ 8Gøre grÃ¥4 bit grÃ¥skala8 bit grÃ¥skalaGrÃ¥skalaskanningGrønGrøn balanceGrøn lyshedGrøn forstærkningGrøn forstærkningsværdi for den analoge forendeGrøn intensitetGrøn lampe slukketGrøn forskydningGrøn forskydningsværdi for den analoge forendeGrÃ¥skalalinier pr. læsningGitterHalvtoneHalvtone A (hÃ¥rd tone)Halvtone B (blød tone)Halvtone C (net/skærm)Halvtone punkt 32Halvtone punkt 64HalvtonemønsterHalvtonemønster størrelseHalvtoneHalvtone er ikke understøttetHÃ¥ndskanner simuleringHÃ¥ndskanner simuleringHøjUdskrift med høj kontrastUdskrift med høj opløsningHøjeste kvalitet men lavere hastighedHøjeste hastighed men lavere kvalitetHøjlysHøjlys for blÃ¥Højlys for grønHøjlys for rødHolder fokusposition 0mmVandretFastlægger, hvor længe der skal ventes efter overførsel af hver databuffer gennem røret.FarvetoneHvis aktiveret prøver bagenden automatisk at bestemme en optimal tærskelværdi.Hvis valgt, udføres farvekalibreringen før et skan af bagendenHvis aktiveret udfører skanneren ikke en bagudrettet sporing.Hvis aktiveret, bliver der kun gennemført skyggekorrektion under kalibreringen. Standardværdierne for forstærkning, forskydning og eksponeringstid, enten indbygget eller fra konfigurationsfilen, bliver brugt.Hvis denne indstilling er sat til, vil enheden blive kalibreret før næste scanning. Ellers foretages kalibreringen kun før første skanning.Ignorer kalibreringBilledeBilledforbedringBilledbetoningBilledeintensitetMatrix printereAnvend samme værdi for hver farve i RGB indstilling.Forøg eller formindsk CCD sensorens analoge forstærkningBlæk printereHeltalsindstillingerInvertér endiannessSluk lampeLampe slukkes ved afslutningSluk-lampe tidLampe slukkes efter (minutter)Lampe tændtLampe statusSluk lampe tidSluk lampe tid i sekunder.Lampe afbryderLinsekalibrering pÃ¥ dokumentpositionLad os se om forenderne kan hÃ¥ndtere dette rigtigtLetterBegræns mængden af overført data ved hvert kald af sane_read().StregtegningHent billedet som grÃ¥skala.Tab af pixler pr. linieLavUdskrift med lav opløsningManuel pre-fokusManuelt tænd/sluk for lampen(lamperne).Matrix multiplikation af RGBMaksMedieMellemMellemtoneMellemtone for blÃ¥Mellemtone for grøntMellemtone for rødSpejlvend vandretSpejl billedetSpejlvend billedet vandret.Spejlvend billedet lodret.Spejlvend billedet.Spejlvend lodretDiverseTilstand 1Tilstand 2Tilstand 3En farve matrixFlerniveau RGB farve (et-gennemløb farve)Flerniveau sort/hvid (grÃ¥skalatilstand)NTSC grÃ¥NTSC RGBNegativNegativ filmIngen korrektionStøjreduktionIngenNormalAntal bit pr. farve, typisk bruges værdien 1 for "stregtegning" og 8 for multibit skanninger.Antal linier skannervognen flyttes tilbage nÃ¥r bagudrettet sporing opstÃ¥r. Det sker nÃ¥r skanneren skanner hurtigere end computeren kan modtage dataene. SmÃ¥ værdier giver hurtigere skanninger, men øger risikoen for at linier bliver sprunget over.Antal af indstillingsmulighederAntal skanlinier der skal forlanges pr. SCSI-læsning. En ændring af denne parameter tillader en fintuning af hastigheden, hvormed der læses data fra skanneren under skanningen. Hvis dette er sat for lavt, stopper skanneren periodisk midt i skanningerne. Hvis det sættes for højt, kan X-baserede forender stoppe med at reagere pÃ¥ X begivenheder, og dit system gÃ¥r ned.Billednummer der skal skannesSlukketTilbyd en vælg fil beskriver for at bestemme om sane_read() vil returnere data.Tilbyd en vælg fil beskriverForskydningTændtEn sideUdfør kun skyggekorrektionTilvalgsudstyrPapirstørrelseUforandretReel størrelse af papiret i ADF'enPositiv filmForuddefinerede indstillingerSmugkigSmugkigtilstandPrintUdskriv en liste med alle indstillinger.Udskriv indstillingerGiver standard skanomrÃ¥de for fotografier, tryk o.l.KvalitetskalibreringKvalitets skanningHurtig formatUdvælge tilfældigtLæseforsinkelseLæsebegrænsningSkrivebeskyttet test-indstillingSkrivebeskyttet indstilling der specificerer hvor mange indstillinger en bestemt enhed understøtter.RødRød balanceRød lyshedRød forstærkningRød forstærkningsværdi for den analoge forendeRød intensitetRød lampe slukketRød forskydningRød forskydningsværdi for den analoge forendeReducer støj fra enkelt punkterForlang et skan i smugkigkvalitet.Forlang at alle smugkig laves i monokrom tilstand. PÃ¥ en tre-gennemløbs skanner, reduceres antal gennemløb til et, og pÃ¥ en en-gennemløbs skanner reducerer det hukommelsesforbruget og tidsforbruget.Forlang at alle forhÃ¥ndsvisninger udføres i hurtigste (lav kvalitet) tilstand. Dette kan være grÃ¥tone, eller lav-opløsning.Returner SANE_STATUS_ACCESS_DENIEDReturner SANE_STATUS_COVER_OPENReturner SANE_STATUS_EOFReturner SANE_STATUS_IO_ERRORReturner SANE_STATUS_JAMMEDReturner SANE_STATUS_NO_DOCSReturner SANE_STATUS_NO_MEMReturner uafklarede linier og bytes pr. linie nÃ¥r sane_parameters() kaldes før sane_start().Retur værdi af sane_readMætningSkalær gammaSkalær gamma blÃ¥Skalær gamma grønSkalær gamma rødSkanner tilstandEksponeringstid til skanningEksponeringstid til skanning for blÃ¥Eksponeringstid til skanning for grønEksponeringstid til skanning for rødSkan i hurtig grÃ¥tonetilstand (lavere kvalitet)Skanner lampe densitetSkannertilstandSkanningsopløsningSkanningskildeSkanningshastighedSkan hele skanningsarealet inklsive kalibreringsstriben. Vær forsigtig. Vælg ikke fuld højde. Kun til test formÃ¥l.Anden angivelseVælg fra hvilken skuffe der skal skannesVælg minimum-lyshed, der skal betragtes som hvidt.Vælg udglatningsfilter.Vælger type af testbillede. Mulige indstillinger: Helt sort: fylder hele skanningen med sort. Helt hvidt: fylder hele skanningen med hvidt. Farve mønster: tegner forskellige farvemønstre afhængig af tilstand. Gitter: tegner et sort/hvidt gitter med en bredde og højde af de enkelte felter pÃ¥ 10 mm.Vælg tilstand for forhÃ¥ndsvisning. GrÃ¥skala smugkig er normalt det bedste kompromis mellem hastighed og detaljerigdom.Fastlægger returværdien af sane_read(). "Standard" er den normale indstilling ved skanning. Alle andre returværdier er til for at teste hvordan forenden hÃ¥ndterer dem.Vælg testbilledeVælger værdi for skalær gammakorrektion (blÃ¥ kanal)Vælger værdi for skalær gammakorrektion (grøn kanal)Vælger værdi for skalær gammakorrektion (rød kanal)Vælger værdi for skalær gammakorrektion.Vælger "kornethed" for det rekvirerede billede. Mindre værdier giver et skarpere billeder.Vælger ADF tilstand (enkeltsidet/dobbeltsidet)Vælger lyshed.Vælger farvekanal, "Master" betyder at alle farvekanaler pÃ¥virkes.Vælger udfaldet.Vælger gammakorrigeret overføringskurveVælger gammakorrektionstilstand.Vælger gammakorrektionsværdi fra en liste med foruddefinerede enheder eller en brugerdefineret tabel, som kan hentes til skannerenVælger halvtone.Vælger nummeret pÃ¥ det billede der skal skannesVælger skanningstilstand (f.eks. stregtegning, monokrom eller farve).Vælger skanningskilde (som f.eks. en dokument-føder).Vælger hvilket blÃ¥t glansniveau der skal anses for "sort".Vælger hvilket blÃ¥t glansniveau der skal anses for "helt blÃ¥t".Vælger hvilket blÃ¥t glansniveau der skal anses for "hvidt".Vælger hvilket grønt glansniveau der skal anses for "sort".Vælger hvilket grønt glansniveau der skal anses for "helt grønt".Vælger hvilket grønt glansniveau der skal anses for "hvidt".Vælger hvilket glansniveau der skal anses for "sort".Vælger hvilket glansniveau der skal anses for "hvid".Vælger hvilket rødt glansniveau der skal anses for "sort".Vælger hvilket rødt glansniveau der skal anses for "helt rødt".Vælger hvilket rødt glansniveau der skal anses for "hvidt".Vælger om det rekvirerede billede skal skannes i halvtoneindstilling (dithering).Vælger hvilket glansniveau der skal anses for "50% blÃ¥".Vælger hvilket glansniveau der skal anses for "50% grÃ¥".Vælger hvilket glansniveau der skal anses for "50% grøn".Vælger hvilket glansniveau der skal anses for "50 % rød".Vælger hvilken skan farve der bruges i grÃ¥tone tilstand (standard er grøn).Sæt standardværdier for forbedringskontroller (lyshed og kontrast).Anvend standardværdier for forbedringskontroller.Fastsæt eksponeringstidFastsæt lampe densitetAngiv niveau for skærpningFastsætter billedrammernes rækkefølgeFastsætter billedrammernes rækkefølge i tre-gennemløbs tilstand.Fastlægger skannerens farve matrix.Angiv efter hvor lang tid (i minutter) lampen skal slukkes.Vælg medietype.Tænder/slukker for UTA'enFastsætter blÃ¥-kanals forstærkningIndstillinger for blÃ¥-kanals forskydningFastsætter grÃ¥-kanals forstærkningIndstillinger for grÃ¥-kanals forskydningFastsætter grøn-kanals forstærkningIndstillinger for grøn-kanals forskydningTænder/slukker for lampenFastsætter rød-kanals forstærkningIndstillinger for rød-kanals forskydningFastsætter farvebalanceværdierne til værdierne fra det faste program.Fastsætter farvekorrektiontabellen for den valgte uddataenhed.Fastætter fødningstilstandenFastsætter fokuseringen enten pÃ¥ glaspladen eller 2,5 mm over denneFastsætter gamma værdien for alle kanaler.Fastsætter den vandrette opløsning af det skannede billede.Fastsætter billedbetoningFastsætter opløsningen af det skannede billede.Fastsætter størrelsen pÃ¥ det halvtonegitter (dithering) der skal bruges ved skanning af halvtonebilleder.Fastsætter den lodrette opløsning af det skannede billede.Indstil forstærkning og forskydning for skanning automatisk. Hvis dette er fravalgt, kan de analoge brugerfladeparametre manuelt indstilles. Denne indstilling er forvalgt. Kun til testformÃ¥l.SkyggeSkygge for blÃ¥Skygge for grønSkygge for rødSkygge, mellemtone, højlys, eksponeringstidGør skarpereSkarphedForskyder blÃ¥ mod grønForskyder blÃ¥ mod rødForskyder grøn mod blÃ¥Forskyder grøn mod rødForskyder rød mod blÃ¥Forskyder rød mod grønKort opløsningslisteSluk lampenSlukker for skannerens lampe.EnkeltsidetSimulerer en hÃ¥ndskanner. HÃ¥ndskannere kender ikke forud billedhøjden. I stedet for angiver de en billedhøjde pÃ¥ 1. Denne indstilling tillader test af forenden, om den kan hÃ¥ndtere dette korrekt. Indstillingen giver ogsÃ¥ en fast bredde pÃ¥ 11 cm.Simulerer en hÃ¥ndskanner. Oftest kender en hÃ¥ndskanner ikke billedhøjden i forvejen. I stedet for returnerer de en højde pÃ¥ -1. Sættes denne indstilling tillades test af, om en forende kan hÃ¥ndtere dette korrekt.Simuler en tre-gennemløbs skanner ved at returnere 3 separate billedrammer, én for hver grundfarve. Rækkefølgen er: grøn, blÃ¥ og rød.Simuler en tre-gennemløbs skanner. I farvetilstand overføres tre billedrammer.Størrelsen af læsebegrænsningDiapositivLangsomLangsommereLangsomsteUdglatUdglatningHelt sortHelt hvidtKildevalgSpecialindstillingerSpecialindstillingerHastighedsøgnings sensorBegynd kalibreringsprocessen.Status kode simuleringStreng testindstillingerInvertér farver, f.eks. byt om pÃ¥ sort og hvid.Tænder/slukker for lampenTekstforbedringsteknologiDen (maksimale) mængde data overført, ved hvert kald af sane_read().Filnavnet pÃ¥ det billede der skal hentes.Lampen bliver slukket efter den angivne tid (i minutter). Værdien 0 bevirker, at lampen ikke bliver slukket.Antal pixler, der er ubenyttede ved enden af hver linie.Mætningsgraden styrer belysningen af ethvert enkeltbillede taget med et kamera. Højere værdier sørger for en stærkere belysning.Termo printereDette er den meget lange tredie angivelse. MÃ¥ske har forenden en ide om hvordan det skal visesDenne indstilling reflekterer skannerknappernes status.Denne indstilling slukker lampen i flatbed'en under skanningTre-gennemløbs simuleringTre-gennemløbs simuleringTærskelværdiTænd/sluk lampenTænder/slukker lampen i flatbed'enØverst-venstre xØverste-venstre x position af skanomrÃ¥de.Øverst-venstre yØverste-venstre y position af skanomrÃ¥de.FilmFilmadapterFilmenhedSluk lampenSlukker for skannerens lampe, nÃ¥r programmet stoppes.Sluk for skannerens lampeTænd for skannerlampenSluk lampen med det samme.UTA tændtSkub udSkubber dokumentet ud.Skub mediet ud efter skanningSkubber mediet ud efter gennemført skanning.Opdatér indstillingerOpdatér indstillinger.Anvend 0mm holder fokusposition i stedet for 0,6mmAnvend billedkompositionBrug bit dybde større end 8 internt, men uddata kun 8 bit.Brug tilpasset gammatabelBrug linse, der fordobler den optiske opløsning.Brug ikke blokerende IOBrug ikke blokerende IO for sane_read(), hvis det er understøttet af forenden.Anvend samme gammaværdi for alle farvekanaler.Brug samme værdier for X og Y opløsning.Anvend lightlid-35 mm-adapterenBrugerdefineretBrugerdefineret (gamma=1,0)Brugerdefineret (gamma=1,8)LodretVent pÃ¥ knapVent pÃ¥ knapVent med at begynde skanning, til frontknappen trykkes.Varm op indtil lampens lyshed er konstant, i stedet for at insistere pÃ¥ 40 sekunders opvarmningstid.Varm op indtil lampens lyshed er konstant, i stedet for at insistere pÃ¥ 60 sekunders opvarmningstid.Varmer lampen opVarm lampen op før skanningOpvarmningstidOpvarmningstid i sekunder.Hvid niveauHvid niveau for blÃ¥Hvid niveau for grønHvid niveau for rødX-opløsningXPAXPA GrÃ¥XPA RGBY-opløsningForstørrelseFlatbed skannerarkføder skannersane-backends-1.0.27/po/gl.gmo0000664000175000017500000023363513110600540012750 00000000000000Þ•_ 6H H-H DH;PH ŒH,™H"ÆHzéH dI9nI¨I€ÅI#FJ5jJ" JÆÃJŠKj¥K LB1L(tLSLñLØMáMBNCNlZNÇNJ×N+"OcNO ²OzÓO'NP™vP$QW5QQžQ¯Q ·Q ÂQ ÍQ ØQãQ ëQ öQR R R R+R 4R ?R JR URbR jR xR „RŽR¡R²R ÄR ÏRÚR ãR îRÒüRÏS ÒS ßSëS ïSúSTT"T!=T_T!T ¡TÂT âTU UsU ‘U5›U ÑUÝUíUÿUV*V;V SV!tV–V¶V»VÊV áV ìV úVW W$W!>W`WuW‰W<šWG×W_XX=X>ÍX< YIYMYSYcY'sY›Y¤Y¼Y ÎY ÙY ãYïY ôYZ ZZ6Z EZ SZ_Z|ZŽZ%ZÃZ%ÒZ øZ[ [ ["[6[M[U[X[h[ l[y[Œ[¨[Å[à[ ò[ü[\))\%S\ y\…\œ\³\Ä\ Ô\â\ó\] ] ]#]5]M]T]&g]ÄŽ]S^Y^i^r^ ^ ^ œ^ ¦^°^ ¿^Í^ê^ __ 8_F_N_V_^_ t_€_‰_Ÿ_¶_Ë_ß_ô_6`.>`Bm`C°`Aô`,6a@caA¤a?æa(&b Ob![b*}b ¨b³b(ºbãbøb ccc)3c"]c$€c*¥c#Ðc(ôc!d?d#]ddžd ¾dßdIþd,He'uee0­eDÞe #f/f?f1GfyfŽf§f½f Ïfðfgg0g7gLgbg|g/–g Æg Òg%Þgh&#hJhah1zh¬h¼hÓh êh i%i8iKiSi ZiEfi¬iÃiÉiçijj(j=j Xjej#wj?›j!Ûj ýjk2k´k(Îk+÷k0#lTl hltl„l­œlJm dm om}m0‘m ÂmÍmåmìmñm n nnn &n 1n =nIn Rn \ngn lnwn ˆn”n§nºn ÂnÏnÕnínün oo7o%Hohnoe×o^=pcœpaqbbqaÅq 'r2rCr Ur_rprur{r Œr™r!ªr Ìr)Ør*s(-s›Vsòsûs tt t$t 4t@tGtMtUtftwt†t Œtšt «t¶tÒtât ñtþtu5u:uCuZuqu‰u™u©uºu ÐuÛuòu v2"v2Uvˆvœv¶v»vÒvèvw (w2wEwYwkw …wIwÚwTÞw[3xEx4Õx’ y¹yQWz€©z¢*{Í{à{æ{ø{|&|6|Q|*e|5| Æ|Ò|ã|ô|}}4}=} N} o}}}•} } ©} ¶}Ã} Ü} ç}0~9~C@~„~Œ~©~Á~Å~Ú~ð~!>BHO_gxŠ+勺倀7€I€ Y€g€n€u€|€&Ž€*µ€ à€ê€ó€ ü€ ' : DRm}‚ ‰X–Þï΂]à‚>„ Z„e„Li„¶„ӄڄ݄愅…6… I… W… b… n… z… …… ……¼…%Ñ…÷… ††† 7†D†X† `†m†s† †Mž†ì† ‡ ‡‡*‡ :‡D‡ H‡ S‡^‡Mt‡‡ ƇÒ‡á‡ê‡ ˆ ˆ ˆ*ˆFˆ dˆoˆÖˆ|f‰ ㉠ñ‰ÿ‰Š %ŠFŠdŠ{ЗбŠÌŠ[æŠB‹\‹ n‹y‹ ‹œ‹®‹Á‹ Ò‹Ü‹ ì‹ Œ Œ&Œ9ŒUŒrŒ'ŒµŒ ÇŒ Ԍތ îŒ úŒx~&” »É åòŽ.ŽEŽ^Ž#sŽg—œÿœ:´;ï9+‘,e‘Y’‘%ì‘’F*’q’/†’*¶’"á’‡“Œ“¢“'Á“<é“4&”>[”Bš”>Ý”?•D\•?¡•9á•9–=U–@“–=Ô–B—>U—>”—?Ó—=˜<Q˜Ž˜˜D¥˜,ꘙ0™B™S™?i™©™1Á™ó™;šNšašqšˆš¡š¸šÑšéš››*›>B›?›Á›D×›%œ4Bœwœ)œX¹œ2ÌEžž)ž:ž)Iž sž ~žˆžœž®žžÕžçžúž"Ÿ3Ÿ)HŸ rŸ€Ÿ—ŸüŸŸÐœ pm¡KÞ¡*¢=¢Q¢W¢^¢c¢j¢r¢ y¢ ƒ¢ ¢›¢#¬¢Тà¢"ð¢W£k£z£ƒ£%ž£Ä£Û£ï£÷£< ¤I¤ f¤ t¤¤G˜¤'à¤u¥=~¥Œ¼¥I¦SZ¦1®¦4à¦7§;M§‰§Ÿ§ µ§ ¿§à§÷§ ¨!"¨ D¨!O¨ q¨~¨“¨¥¨¸¨ ʨ بù¨©$©D©K©S©Z©k©ƒ©£©·©Ê©Ù© é©. ª9ªCOª“ª(ªªÓªAçª)«.G«&v«« »«È«á«ú«¬¬)#¬ M¬`n¬`Ϭ 0­<­X­ x­„­¨œ­>E®‹„® ¯¯1¯G¯)[¯ …¯’¯–¯Ÿ¯ §¯´¯¹¯ Яݯí¯)°,°I°h°}°° ³°À°Ô°ç°±±±&,±S±!o±‘±¢±´±б á±ï± ²/)²Y²y²²‘²õ˜² Ž´9›´Õ´Zå´ @µ2Lµ4µi´µ ¶Q,¶,~¶¢«¶)N·Bx·?»·Ëû·'Ǹˆï¸3x¹r¬¹1º\Qº)®ºØØº1±»Zã»$>¼[c¼¿¼[ؼ=4½Pr½3ý˜÷½A¾ŽÒ¾<a¿už¿À-À FÀQÀ cÀnÀ €À ‹À –À À²À »À ÆÀÐÀâÀ ëÀ÷À ÁÁ %Á0Á ?Á LÁVÁnÁ…Á ˜Á¢Á´Á ½Á ÈÁòÕÁÈ Ë ×Â+ãÂÃ#Ã"4ÃWÃpÃ)ŽÃ,¸Ã)åÃ-Ä,=Ä-jĘġć³Ä;Å7MŅřŴÅÊÅçÅþÅÆ&5Æ'\Æ*„Æ ¯Æ»Æ"ÎÆñÆÇ Ç 4Ç UÇ+aÇǪÇÂÇÕÇGìÇJ4ÈqÈñÈHÉINÉL˜ÉåÉìÉòÉÊ2Ê CÊMÊfÊ}ʌʠʯʴÊÄÊ ÓÊáÊÿÊË(Ë 9ËZËvË/‡Ë·Ë/ÈËøËÿËÌÌ"Ì>Ì[ÌcÌfÌƒÌ ‡Ì•Ì#¯Ì$ÓÌ'øÌ Í;ÍDÍ"XÍ,{Í#¨Í ÌÍÙÍñÍÎ&Î5ÎHÎ]ÎqÎ w΅ΕÎ(«ÎÔÎÚÎ.íÎØÏõÏ ùÏÐÐ'Ð ?ÐMÐ^Ð fÐtÐ%ƒÐ*©ÐÔÐ"çÐ ÑÑ!Ñ)Ñ1Ñ IÑ UÑ_ÑwÑѬÑÅÑßÑ3üÑ"0Ò3SÒ4‡Ò7¼Ò%ôÒ3Ó4NÓ7ƒÓ »ÓÜÓ%ìÓ.ÔAÔ UÔ@cÔ¤ÔÁÔÙÔèÔøÔ5Õ0MÕ0~Õ6¯Õ1æÕ9Ö4RÖ+‡Ö1³Ö,åÖ1×2D×5w×R­×/Ø30ØdØ/yØG©ØñØÙÙE%Ùkق١ٻÙ)ÒÙüÙÚ"$ÚGÚPÚdÚzÚ‘Ú<¨ÚåÚõÚ)Û//Û8_Û˜Û¬Û3ËÛÿÛ Ü#:Ü)^ÜˆÜ¢Ü¶Ü ÊÜ ÕÜàÜHðÜ9ÝYÝ'bÝ(ŠÝ³ÝÓÝêÝÞ#Þ6Þ"NÞPqÞ*ÂÞ-íÞß’5ß&Èß?ïß5/à:eà à »àÉàÛàÎöàÅá åáñá'âA.â pâ|â‘â˜â â²âÇâ ×âåâ õâãã,ã =ã KãYã^ãgã{ãŒã!¦ãÈã ÎãØãàãää%ä6äTä4oäs¤äpåi‰ånóålbæmÏæl=çªç ³çÁçØçéçÿçèè è.è#@è dè-pè.žè1Íè›ÿè ›é¦éºéÊéÏéàéñéêêêê9êTêpêvê‡ê—ê¦êÅêÚêðê!ë$$ëIë Oë[ëvë’ë«ë¾ëÑë!èë ìì3ìRì3qì3¥ìÙì!ñìíí5í*Rí$}í¢í«í½íÐí æí îaîtîkzîZæîEAï=‡ï²ÅïùxðZrñÍñË[ò'ó<óBóYóxóŠó"ŸóÂó0Øó4 ô >ô!KômôŠôŸô.¹ôèôøô6õJõ&iõõ¡õ´õÑõ(îõö0/ö5`ö–öHœö åö%óö÷5÷;÷Y÷r÷%…÷ «÷Ì÷Ñ÷Ù÷á÷ ó÷ÿ÷ø,ø>Fø…ø!˜øºøÚø ùøù-ù >ùJùQùXù_ù(pù7™ù ÑùÛùäùíùÿùú)ú @úJú Zú{úú—úžúe°ú˜û¯ü‰ÃüMþ jþ xþQ„þ-Öþ ÿÿ ÿ!(ÿJÿdÿƒÿ˜ÿ ªÿ¸ÿÊÿÚÿëÿ üÿ*1'Lt} §ÈÛ ðý( IU^´Íáñ +5>QdU„Úã÷ !>Vq$†"« Î2Ûñ“”¨½Ò!ð1Ifg¸ > T` €Ž¡µÌÜ1õ'D!Y{š"º/Ý . @ P g x ƒŽ  *2 ] p  Ÿ ¾ 7Õ  + $D i Áù » >Ô ?BS2–^É5(^Hp¹6Ù8&I™p & &GDnK³FÿKFG’GÚM"HpA¹BûJ>S‰KÝF)tp:å; >\K›çûYB^&¡ÈåL!n:‰$Ä>é(A_$"¤$Ç ì% 3$K(p=™P×(MG*•3Àô(g81  ÒÝäõ6S[c{–®Êå-K0a’¢ ÁËðê †Û!ˆb"ë" # &# 2#?# E# Q#_# e# o#}#Œ#%#Ã#Ö#è#]$e$ w$$1¡$ Ó$ô$%%Q2%„%Ÿ%!¾%$à%H&#N&}r&;ð&¬,'Ù'Uî'<D(6(6¸(8ï(()D)`),g)&”)%»)á)0ó)$*06* g*u*‘*«*Á*Û*%í*+0+ N+ o+ |+ ‰+“+*©+*Ô+ÿ+,5,L,.d,;“,Ï,Xê,C-,c--F¨-!ï-;.0M.(~.§.!½.!ß./ //72/'j/h’/hû/d0#{0'Ÿ0Ç0Û0Âû0H¾1Ž2–2¦2À2Û2.ù2 (3!63 X3y3 ™3§3¬3Ç3Ú3!é37 4,C4(p4™4(±4Ú4õ45!5 85 Y5 e5q5'‡5)¯55Ù56)6,?6!l6Ž6!§6.É6Eø6.>7 m7z7 ‘7(|8ßLÏPÔ2‚Æ\£’2«oK&Úü5gb‡A fþü÷¬ñ%a9»É DmÁi×%H²‘–m,NÞÑô¾®[Jã󱆠L_êGûAøå)8«D]œ¼öd§·‰oT$Z¾zMAY¢=>ùç‚ëŽO! ;Á–§R¨‰üðVÝšÈ&p,.U¼_qœäjbqRá^•šÛ˪ ºïJ¨%ñu4í Pp 3v²ðdÅd›ÌCØÖóe3­ÙU;N<‡\I½ÆÖW3µ‹ö¨}›¬ù†*‚ÐÓ¦7>CU?··‘{ù#5&ê°ªœi]‰ryû?´Õ/’-l/ ìEF‘¾fÆŠžˆµ~â”ïôi0Ç t”•8ße"*<AŽâFtø5‹g-„–BmEá¸ÑÑsƒGa1MkýO}pò:B®¦0‹ÚÿB±<îQ^Xk­ŽÛSV½KƒìG¹7å']â—7çÈà!K{t°ÀÚ¼æxÒz)YˆŠY¡´yhËÎʧuL3PТ}ÊUÐκ:êë1%R<[þÉ„Y Ÿ x™{4h›¹˜&F~ÙJÏëôÕÎ'@"á‡ï N Œ9ì8[Œ ÅZÞI¯°Éy¶SM^(ŒóVvcE¦Ôˆ¢K“+j¡…¿:è@J˜åÊO'—÷©Za,5/Þ“ ÿ#¤Q¿ÌxäŠN+k2~ƒEÃà>è'` \ò× çÔHW©—Bvèu¹¸ ,¿Ohqݶé«)F`Ãר.0Ýðº¶Ùø÷®|±õ6$æ©]Äfí."n =(Ä ¸ÓÏ¥Üß½…à)wãW³ú…s+Ò/é`¡o¤öæ;rb†€1ÂwDòÁ6³6?õžj9žþõ z ÕDP=2¯?ËTIû4éTÿ$ÛÄ­lÌ!Q´CÇX»+ýÀ²;£™¤n$¥l„-#T_úÅÍ™XÀ:rH’g@ý¥1»[0€>4 Ü*ÇñS*Í"€Øw¬Ÿ³n-C=WQÒ(¯”“XµÍ•6Ÿ.Mä@!H£îÖRÃ\ȘVs GIeÜíî^cc|S#_ š9ªZ  úLÓ7ã(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF DuplexADF ModeADF cover openADF jamAccess to resource has been deniedAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowCancel buttonChange Document.Change documentChannelChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDisable auto document feeder and use flatbed onlyDisable backtrackingDisable gamma correctionDisable interpolationDisable pre focusDisable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEnhancementError DiffusionError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInk-jet printersInt test optionsInvalid argumentInvert endiannessLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryPDF buttonPage heightPage loadedPage widthPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner cover is openScanner mechanism locked for transportScanner modelScanner sensors and buttonsSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Speedup sensorStandardStart calibration process.Start calibration using special sheetStatus Code SimulationString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.White levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: sane-backends Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2009-06-25 10:22+0100 Last-Translator: Miguel Anxo Bouzada Language-Team: Galician Language: gl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 1.11.4 Plural-Forms: nplurals=2: plural=(n != 1); X-Poedit-Language: Galician X-Poedit-Country: SPAIN (1/1) Botón(1/1) Botón de opción de proba. Imprime algún texto...(1/3) Real fixo(1/3) Opción de proba de valor real (coma fixa) sen unidade nin conxunto de restricións.(1/3) Cadea(1/3) Opcións de proba de cadea sen restricións.(1/6) Booleana configurábel e lexíbel por software(1/6) Opción de proba booleana configurábel e lexíbel por software. Esta é a opción booleana normal.(1/6) Enteiro(1/6) Opción de proba de valor enteiro sen unidade nin conxunto de restricións.(2/3) Real fixo con intervalo de restrición(2/3) Opción de proba de valor real (coma fixa) con unidade de microsegundo e intervalo de restrición. O mínimo é -42,17, o máximo 32767,9999 e o salto 2,0.(2/3) Cadea restrinxida a lista de cadeas(2/3) Opción de proba de cadea con restrición de lista de cadeas(2/6) Booleana configurábel por hardware lexíbel por software(2/6) Opción de proba booleana configurábel por hardware e lexíbel polo software. Esta opción non pode ser configurada pola interface, mais si polo usuario (p.ex. premendo un botón no dispositivo).(2/6) Enteiro con rango de restricións(2/6) Opción de proba de valor enteiro con unidade de píxel e con conxunto de restricións. O mínimo é 4, o máximo 192 e o salto 2.(3/3) Real fixo con restrición de lista de valores(3/3) Opción de proba de valor real (coma fixa) sen unidade e restrinxida por un conxunto de valores dunha lista.(3/3) Restrición de cadeas lista longa de cadeas(3/3) Opción de proba de cadea con restrición de lista de cadeas. Conten máis entradas...(3/6) Booleana configurábel por hardware(3/6) Opción de proba booleana configurábel por hardware. Esta opción non pode ser configurada pola interface, mais si polo usuario (p.ex. premendo un botón no dispositivo) tampouco pode ser lida pola interface.(3/6) Enteiro con restrición de lista de valores(3/6) Opción de proba de valor enteiro con unidade bits e restrición de lista de valores(4/6) Booleana lexíbel por software(4/6) Opción de proba booleana lexíbel por software. Esta é unha opción de só lectura.(4/6) Matriz de enteiros(4/6) Opción de proba de valor enteiro con unidade mm usando unha Matriz con restricións.(5/6) Booleana configurábel e lexíbel por software, emulada(5/6) Opción de proba booleana configurábel e lexíbel por software e emulada.(5/6) Matriz de enteiros con rango de restriciónsv(5/6) Opción de proba de valor enteiro con unidade dpi e usando unha matriz con intervalo de restricións. O mínimo é 4, o máximo 192, e o salto 2.v(6/6) Booleana configurábel e lexíbel por software, automática(6/6) Opción de proba booleana configurábel e lexíbel por software e emulada. Esta opción pode ser configurada automaticamente polo motor.(6/6) Matriz de enteiros con restrición de lista de valores(6/6) Opción de proba de valor enteiro con unidade e% e usando unha matriz con restricións nunha lista de valores.1/2 da velocidade normal1/3 da velocidade normal2-píxeles2x2 personalizado2x2 normal3x3 personalizado3x3 normal4-píxeles4x4 groso4x4 personalizado4x4 fino4x4 normal5x5 groso5x5 personalizado5x5 fino6x4 (polg.)6x6 personalizado6x6 normalSaída de 8 bits8-píxeles8.5x11 (polg.)8x10 (polg.)8x8 Bayer8x8 «Engraxado» groso8x8 «Engraxado» fino8x8 Liña vertical8x8 groso8x8 personalizado8x8 fino8x8 normal8x8 moi finoUnha exposición prolongada permítelle ao escáner recoller máis luz. Suxírese usar 175% para impresións, 150% para diapositivas normais e «Negativo» para filme en negativo. Para imaxes escuras (subexpostas) pode incrementar este valor.A4A5 apaisadoA5 verticalAlimentador automático de documentos (ADF)Alimentador dúplexModo alimentadorA tapa do alimentador está abertaAtoamento no alimentadorDenegouse o acceso ao recursoEngade azul baseándose no nivel de verdeEngade azul baseándose no nivel de vermelloEngade verde baseándose no nivel de azulEngade verde baseándose no nivel de vermelloEngade vermello baseándose no nivel de azulEngade vermello baseándose no nivel de verdeAvanzadoOpcions avanzadasDespois de enviar a orde de escaneo, agardar até que se prema no botón do escáner para comezar verdadeiramente o proceso de escaneo.Todas as páxinasApagar sempre a lámpada cando se calibra a escuridade.Ganancia analóxicaInterface analóxica (AFE)Gamma analóxica azulCorrección gamma analóxicaGamma analóxica verdeGamma analóxica vermellaCorrección gamma analóxicaCorrección gamma analóxica para azulCorrección gamma analóxica para verdeCorrección gamma analóxica para vermelloAutomáticoLimiar automáticoSegmentación automática da áreaExpulsión automáticaExposición automáticaEnfoque automáticoEnfoque automático só unha vezAutomáticoAlimentador automático de documentos (ADF)Axuste automático de limiarSeparación automáticaLimiar automáticoQuecemento automáticoExpulsar automaticamente o filme do dispositivo despois de cada escaneoExpulsar automaticamente o filme do dispositivo antes de saír do programaAxusta automaticamente o brillo, contraste, niveis de branco, gamma e redución da intensidade do ruído da imaxeLiñas de retrocesoFactor de balance para azul. Un valor de 100% significa sen corrección.Factor de balance para verde. Un valor de 100% significa sen corrección.Factor de balance para vermello. Un valor de 100% significa sen corrección.BadíaBayerTrama Bayer 16Trama Bayer 64Dous niveis branco e negro (modo de liña de arte)Ligar RGBLigar resolucións X e YLigar gamma analógicoConectar gammaBit de profundidadeNivel do negroAzulBalance de azulBrillo de azulGanancia azulValor de ganancia azul no AFEIntensidade de azulApagar lámpada azulDesviación azulValor da desviación azul no AFEOpcións de proba booleanasAbaixo-dereita XPosición X abaixo-dereita da área de escaneo.Abaixo-dereita YPosición Y abaixo-dereita da área de escaneo.BrilloBotón 1Botón 2Botón de estadoOpcións de botón de probaBotón de control de escaneoBotónsCDerro de verificación de CPUCRTMonitores CRTCal. tempo de exposiciónCal. tempo de exposición para azulCal. tempo de exposición para verdeCal. tempo de exposición para vermelloCal. densidade da lámpadaCalibrarCalibrar o escánerCalibrar antes do seguinte escaneoCalibrar as lentes na posición do documentoCalibrar o nivel de branco e negro.CalibraciónCalibración polo motorCaché de datos de calibraciónModo de calibraciónCalibrar agoraBotón de cancelarCambiar o documento.Cambiar o documentoCanleID do chipsetNome do chipsetLimpar a calibraciónLimpar a caché de datos de calibraciónGrosoCalibración grosaCalibración grosa só para o primeiro escaneoA calibración grosa faise só para o primeiro escaneo. Funciona coa maioría de escáners e pode aforrar tempo de escaneo. Se o brillo da imaxe é diferente con cada escaneo, desactive esta opción. Só para probas.CorCor (48 bits)Color 36Medios tons coloreadosLiña de arte coloreadaMatriz de corCor de texto RGBCor RGBCor RGB TEXTOBalance de corAxustes de ganancia das canles de corAxustes do desprazamento das canles de corCorrección da corCoeficientes de corrección da corPatrón de corColor24Color36Color48Cor, liñas por lecturaCondicionalContrasteContraste da canle azulContraste da canle verdeContraste da canle vermellaControla o nivel de azulControla o nivel de verdeControla o nivel de vermelloControla o "matiz" (nivel de azul) da imaxe obtida.Controla o brillo da imaxe obtida.Controla o brillo da canle de azul da imaxe obtida.Controla o brillo da canle de verde da imaxe obtida.Controla o brillo da canle de vermello da imaxe obtida.Controla o contraste da imaxe obtida.Controla o contraste da canle azul da imaxe obtida.Controla o contraste da canle verde da imaxe obtida.Controla o contraste da canle vermella da imaxe obtida.Controla se se forza o retrocesoBotón de copiaCorrección conforme co tipo de filmeCorrección conforme coa taxa de transparenciaA tapa está abertaPersonalizadoMatriz de cor personalizada para escáneres en escala de grises.Matriz de cor personalizada.Opcións de depuraciónPredeterminadoPredeterminadosDefinir o modo de calibraciónDefinir tempo de exposición para a calibración azulDefinir tempo de exposición para o escaneo azulDefinir tempo de exposición para a calibraciónDefinir tempo de exposición para a calibración verdeDefinir tempo de exposición para o escaneo verdeDefinir tempo de exposición para a calibración vermellaDefinir tempo de exposición para o escaneo vermelloDefinir tempo de exposición para o escaneoDefinir densidade da lámpada para a calibraciónDefinir densidade da lámpada para o escaneoDefine os parámetros de apagado da lámpada azulDefine os parámetros de apagado da lámpada verdeDefine os parámetros de apagado da lámpada vermellaDefine o patrón de medios tons (punteado) para escanear as imaxes de medios tons.Define o factor de zoom que vai usar o escánerRetardar a transferencia de datos á canalización.Control de densidadeDetermina a velocidade á que se fai o escaneo.Determina se se debe usarse unha táboa gamma interna ou personalizada.Dispositivo ocupadoAxustes do dispositivoDiamanteDesactivar o alimentador automático de documentos e usar só o planoDesactivar o retrocesoDesactivar a corrección gammaDesactivar interpolaciónDesactivar foco previoDesactivar a corrección de sombra brancaPunto disperso 16x16Punto disperso 8x8Amosar lista curta de resoluciónsEsfumadoTrama A (4x4 Bayer)Trama B (4x4 espiral)Trama C (4x4 matizado)Trama D (8x4 matizado)Esfumado/medios tons de branco e negro (modo de medios tons)Mapa de trama 1Mapa de trama 2Escanea en escala de grises, non en coresFacer unha calibración de calidade dos brancosFacer enfoque automático só unha vez entre expulsiónsNon calibrar o focoNon forzar o código de estadoNon forzar o motor a devolver un código de estado.Alimentador de documentosAlimentador de documentos extrasAlimentador de documentos atrancadoO alimentador de documentos está baleiroDobre resolución ópticaDescargar patrón ADescargar patrón BExclusiónDuas carasEscaneo dúplexO escaneo dúplex fornece un escaneo do anverso e o reverso do documentoDuración do retardo de lecturaExpulsarExpulsar o documento despois do escaneoExpulsar o filme despois de cada escaneoExpulsar o filme antes de saírExpulsar o filme agoraExpulsar o filme *agora*Expulsar a folla do alimentadorBotón de correo-eEmular escala de grisesActiva o escaneo polas dúas carasActivar a determinación automática do limiar para escaneos como liña de arte.Activar selección do tempo de exposiciónActivar a selección da densidade da lámpadaActivar opcións de probaActiva varias opcións de proba. Isto úsase para probar a capacidade das interfaces para ver e modificar os diferentes tipos de opcións de SANE.Activar/desactivar enfoque automáticoActivar/desactivar a característica de exposición automáticaActiva ou desactiva a caché de datos de calibraciónActiva ou desactiva a aceleración de movimento do sensor.Acadouse o fin do ficheiroOptimizaciónDifusión de erroErro en dispositivo de E/SIntercambia os bytes de datos superiores e inferiores de imaxes en modo de 16 bits. Esta opción pode utilizarse para a proba de 16 bits dos modos de interface, p.ex. se a interface utiliza a orde correcta.Executar a calibración *agora*ExperimentoTempo de exposiciónRetardar o tempo de apagado da lámpadaRetarda os tempos de apagado da lámpada (de 15 minutos a 1 hora)Moi rápidoAxustes de cor extraExtrasRápidoModo gris rápidoVista previa rápidaEscaneo rápidoMáis rápidoO máis rápidoBotón de faxModo de alimentaciónBotón de ficheiroNome do ficheiroTipo de filmeTira de filmeFinaCor finaBalance de firmwarePrimeira entradaFixar a posición do focoOpcións de proba «reais fixos»PlanoSó planoEnfoqueEnfoque a 2.5mm sobre o cristalPosición do focoEnfoque no cristalForzar retrocesoForzar vista previa monocromaForzar a profundidade realForza a calibrar o escáner antes de facer o escaneoForzar o motor a devolver o código de estado de SANE_STATUS_ACCESS_DENIED despois de ter sido chamado sane_read().Forzar o motor a devolver o código de estado de SANE_STATUS_COVER_OPEN despois de ter sido chamado sane_read().Forzar o motor a devolver o código de estado de SANE_STATUS_EOF despois de ter sido chamado sane_read().Forzar o motor a devolver o código de estado de SANE_STATUS_IO_ERROR despois de ter sido chamado sane_read().Forzar o motor a devolver o código de estado de SANE_STATUS_JAMMED despois de ter sido chamado sane_read().Forzar o motor a devolver o código de estado de SANE_STATUS_NO_DOCS despois de ter sido chamado sane_read().Forzar o motor a devolver o código de estado de SANE_STATUS_NO_MEM despois de ter sido chamado sane_read().De papelDe pau brancoAgardar botón frontalEscaneo completoParámetros dubidososGananciaGammaCorrección gammaTáboas gammaCorrección gammaA corrección gamma hase desactivarValor gammaTáboa de corrección gamma para a gama azul.Táboa de corrección gamma para a gama verde.Táboa de corrección gamma para a gama vermella.Táboa de corrección gamma. No modo cor, esta opción afecta igualmente as canles vermella, verde e azul de vez (ex. é unha táboa de intensidade gamma).XeometríaGrupo de xeometríaTamaño do granGrisGanancia de grisCor en modo grisDesprazamento de grisGris 16Gris 8AgrisarEscala de grises de 4 bitsEscala de grises de 8 bitsEscaneo en escala de grisesVerdeBalance de verdeBrillo de verdeGanancia verdeValor de ganancia verde no AFEIntensidade de verdeApagar lámpada verdeDesviación verdeValor da desviación verde no AFEEscala de grises, liñas por lecturaGradeMedios tonsMedios tons A (tons duros)Medios tons B (tons suaves)Medios tons C (matizado)Medio ton punto 32Medio ton punto 64Patrón de medios tonsTamaño do patrón de medios tonsMedios tonsMedios tons non compatíbeisSimulación de escáner de manSimulación de escáner manualPosición X interna no hardware da zona de escaneo.Posición Y interna no hardware da zona de escaneo.Resolución do hardwareOpcións especificas de hardawareAltaImpresión de alto contrasteImpresión de alta densidadeA mellor calidade, pero a velocidade lentaMáis rápido, pero de pior calidadeResaltarResalte para azulResalte para verdeResalte para vermelloMarcar a posición do foco a 0mmHorizontalCanto tempo se vai agardar despois de transferir cada búfer de datos a través da canalización.MatizSe escolle o alimentador automático de documentos, o alimentador estará "baleiro" despois de 10 escaneos.Se se selecciona, o motor tenta determinar automaticamente un valor óptimo para o limiar.Se se selecciona a calibración da cor antes do escaneo faina o motorSe se activa, o escáner non retrocede cando perde unha liñaSe está activada, a imaxe vai ser escaneada en modo de cor e despois convertida a escala de grises por software. Isto pode mellorar a calidade da imaxe nalgunhas circunstancias.Se está activado, só se farán correccións de sombras durante a calibración. Usaranse os valores predeterminados de ganancia, desprazamento e tempo de exposición, xa sexan os que trae incorporados o programa ou os do ficheiro de configuración.Se se activa, algunhas imaxes implicadas no proceso de escaneo gardaranse para analizalas.Se se activa, o dispositivo hase calibrar antes do seguinte escaneo. Noutro caso, a calibración farase unicamente antes do primeiro escaneo.Se gamma está activada, sempre se analisa en profundidade de 16 bits para mellorar a calidade da imaxe e despois convertila á profundidade seleccionada. Esta opción evita a emulación da profundidade.Ignorar calibraciónImaxeOptimización da imaxeAs imaxes a cor hanse inverterDestaque da imaxeIntensidade da imaxeOpcións de modificación de imaxeImpresoras matriciaisEn modo RGB usar os mesmos valores para cada corAumenta o diminúe a ganancia analóxica da gama CCDInformaciónImpresoras de inxección de tintaOpción de proba «Enteiro»Argumento incorrectoInverter a orde dos datosA lámpada non está preparada, tenteo de novoApagar lámpadaApagar a lámpada ao saírApagar a lámpada durante a calibración de escuridadeTempo para apagado da lámpadaTempo de apagado de lámpada (minutos)Acender lámpadaEstado da lámpadaLímite de tempo da lámpadaTempo de apagado da lámpadaTempo de apagado da lámpada en segundosInterruptor de lámpadaCalibración de lentes na posición do documentoVexamos se a interface pode tratar isto correctamenteCartaLimita a cantidade de datos transferidos con cada chamada a sane_read().Liña de arteCargar a imaxe como escala de grises.Perda de píxeles por liñaBaixoImpresión de baixa densidadePosición de foco manualFoco previo manualCambiar a(s) lámpada(s) manualmente.Matriz de multiplicación de RGBMáxSoporteSoporteManexar o soporteMedios tonsMedios tons para azulMedios tons para verdeMedios tons para vermelloMinutos que tardará a lámpada en apagarse despois do escaneoEspello horizontalReflectir a imaxe horizontalmenteReflectir a imaxe en horizontalReflectir a imaxe en verticalvInverter a imaxe horizontalmenteReflectir a imaxe.Espello verticalMisceláneaModo 1Modo 2Modo 3Matriz monocromaMultinivel de cor RGB (cor dunha pasada)Multinivel de branco e negro (modo de escala de grises)NTSC GrisNTSC RGBNegativoFilme en negativoDiapositiva en negativoFilme en negativoTipo de filme negativoNegativosSen correcciónSen corrección de transparenciaRedución de ruídoNingúnNormalVelocidade normalNúmero de bits por mostra, valores típicos son 1 para «liña de arte» e 8 para escaneos multibit.Número de liñas que o escáner retrocede cando escanea máis rápido do que o equipo pode recibir datos. Valores baixos fan que os escaneos sexan más rápidos, pero aumentan os riscos de omitir liñas.Número de liñas que o escáner retrocede cando escanea máis rápido do que o equipo pode recibir datos. Valores baixos fan que os escaneos sexan más rápidos, pero aumentan os riscos de omitir liñas.Número de opciónsNúmero de liñas de escaneo por solicitude dunha lectura SCSI. O cambio deste parámetro permítelle axustar a velocidade á que se len os datos desde o escáner durante os escaneos. Se este é demasiado baixo, o escáner ten que parar periodicamente no medio dun escaneo, se é demasiado alto, baseado en interfaces X pode deixar de responder a eventos de X e o seu sistema poderíase atoar.Número de mostra a escanearBotón de OCRDesactivadoPropor un descritor de fichero para detectar si sane_read () devolverá os datos.Propor a selección dun descritor de ficheiroDesprazamentoActivadoUnha páxinaFacer só correccións de sombrasOperación non compatibleA operación vai ser canceladaEquipamento opcionalNon queda memoriaBotón de PDFAltura de páxinaPáxina cargadaAncho de páxinaTamaño do papelA travésFacer unha diagnose automatica do escánerCalibración de precisiónTamaño físico do papel no alimentadorPositivoFilme en positivoDiapositiva en positivoFilme en positivo ou en negativoBotón de enerxíaAxustes predefinidosVista previaModo de previsualizaciónImprimirImprimir unha lista de todas ls opciónsImprimir as opciónsFornece superficies de escaneado estándar para fotografías, páxinas impresas, etc.Calibración da calidadeEscaneo de calidadeFormato rápidoerro de verificación de RAMerro de verificación de ROMAleatorioEn brutoRetardo de lecturaLímite de lecturaOpción de proba de só lecturaOpción de só lectura que define cantas opcións soporta un dispositivo específico.VermelloBalance de vermelloBrillo de vermelloGanancia vermellaValor de ganancia vermella no AFEIntensidade de vermelloApagar alámpada vermellaDesviación vermellaValor da desviación vermella no AFEReduce os puntos illados de ruídoReflectantesSolicitar unha vista previa de calidade d escaneo.Solicitar que todas as vistas previas sexan feitas en modo monocromo. Nun escáner de tres pasadas isto reduce o número de pasadas a unha, e nun escáner dunha pasada isto reduce o requisitos de memoria e o tempo de escaneo da vista previa.Precisa que todas as vistas previas se fagan do modo máis rápido (baixa calidade). Este pode ser un modo sen cor ou un modo de baixa resolución.Reiniciar o chipsetReiniciar o escánerReiniciar o escánerReiniciar os datos do chipsetDevolve SANE_STATUS_ACCESS_DENIEDDevolve SANE_STATUS_COVER_OPENDevolve SANE_STATUS_EOFDevolve SANE_STATUS_IO_ERRORDevolve SANE_STATUS_JAMMEDDevolve SANE_STATUS_NO_DOCSDevolve SANE_STATUS_NO_MEMDevolve liñas dubidosas e bytes por liña cando se chama a sane_start() antes que a sane_parameters().Valor de retorno de sane_readerro de paridade SCSISaturaciónGardar as imaxes de depuraciónGamma escalarGamma escalar azulGamma escalar verdeGamma escalar vermellaModo de escaneoGrupo de modo de escaneoOpcións da área de escaneo e tamaño do soporteBotón de control de escaneoContador de escaneosTempo de exposición para escaneoTempo de exposición para azulTempo de exposición para verdeTempo de exposición para vermelloEscanear en modo gris rápido (menor calidade).Densidade da lámpada de escaneoMarxes de escaneoModo de escaneoResolución de escaneoOrixe de escaneoVelocidade de escaneoEscanear toda a área de escaneo incluindo a franxa de calibración. Teña cuidado. Non seleccione a altura total. Só para probas.A tapa do escáner está abertaO escáner está bloqueado para transporteModelo de escánerSensores e botóns do escánerSegunda entradaEscolla a badía para escanearEscoller tipo de filmeSeleccionar o brillo mínimo para obter un punto brancoEscoller filtro de suavizado.Escoller o tipo de filmeDefine o tipo de proba de imaxe. Posíbeis opcións: Negro sólido: enche todo o escaneo con negro. Branco sólido: enche todo o escaneo con branco. Patrón de cor: debuxa varios patróns de proba dependendo do modo. Grade: debuxa unha grade en branco e negro cun tamaño de 10mm por cadrado.Escolle o modo para previsualización. A previsualización en escala de grises fornece en xeral, a mellor relación entre velocidade e detalle.Escolla o valor de retorno de sane_read(). «Predeterminado» é o normal para facer o escaneo. Todos os demáis códigos de estado son para probar a forma en que a interface se fai cargo delesEscolla a imaxe de probaEscolle un valor para a corrección gamma escalar (canle azul)Escolle un valor para a corrección gamma escalar (canle verde)Escolle un valor para a corrección gamma escalar (canle vermella)Escolle un valor para a corrección gamma escalar.Escolle o «granulado» da imaxe obtida. Valores máis pequenos fornecen imaxes máis nitidas.Escoller o modo do alimentador (unha cara/duas caras)Escoller o brilloEscolle a gama de cor, «Master» significa que afecta a todas as cores.Escoller o que se vai a excluirEscoller o tipo de filme, p.e. negativo ou diapositivaSelecciona a curva de transferencia da corrección gammaSelecciona o modo de corrección gammaEscolla o valor de corrección gamma dunha lista de dispositivos predefinidos ou dunha táboa definida polo usuario, que pode ser descargada ao escáner.Escolle o medios tonsSelecciona o tipo de negativo de filmeEscolle o número de mostra a escanearSelecciona o modo de escaneo (ex. liña de arte, monocromo, ou cor).Selecciona a orixe do escaneo (como pode ser un alimentador de documentos).Selecciona que nivel de radiancia azul debe ser tida en conta "negro".Selecciona que nivel de radiancia azul debe ser tida en conta "azul total".Selecciona que nivel de radiancia azul debe ser tida en conta "branco".Selecciona que nivel de radiancia verde debe ser tida en conta "negro".Selecciona que nivel de radiancia verde debe ser tida en conta "verde total".Selecciona que nivel de radiancia verde debe ser tida en conta "branco".Selecciona que nivel de radiancia debe ser tida en conta "negro".Selecciona que nivel de radiancia debe ser tida en conta "branco".Selecciona que nivel de radiancia vermella debe ser tida en conta "negro".Selecciona que nivel de radiancia vermella debe ser tida en conta "vermello total".Selecciona que nivel de radiancia vermella debe ser tida en conta "branco".Define se a imaxe obtida debe ser convertida a medios tons (punteado).Selecciona o nivel de radiancia a ter en conta "50% azul".Selecciona o nivel de radiancia a ter en conta "50% azul".Selecciona o nivel de radiancia a ter en conta "50% gris".Selecciona o nivel de radiancia a ter en conta "50% verde".Selecciona o nivel de radiancia a ter en conta "50% vermello".Escolle que cor de escaneo vai ser usada en modo gris (predefinido: verde).Diagnose automaticaSensoresAxustar os valores predeterminados para os controis de optimización (brillo e contraste)Axustar valores predeterminados para os controis de optimización.Axustar o modo de control de densidadeAxustar tempo de exposiciónAxustar a densidade da lámpadaAxustar o valor de nitidez.Axustar o sistema óptico de foco na posición manual (predeterminado: 128).Axustar a orde das mostrasAxustar a orde das mostras no modo de tres pasadas de cor.Axustar a matriz de cor do escáner.Axusta o tempo (en minutos) tras o que se apagará a lámpada.Axustar tipo de soporte.Axusta o acendido/apagado UTAAxusta a ganancia da canle azulAxusta o desprazamento da canle azulAxusta a ganancia da canle de grisAxusta o desprazamento da canle grisAxusta a ganancia da canle verdeAxusta o desprazamento da canle verdeAcende/apaga a lámpadaAxustar a ganancia da canle vermellaAxusta o desprazamento da canle vermelloAxusta o balance de cor aos valores fornecidos polo firmware.Axusta a táboa de corrección da cor para o dispositivo de saída seleccionado.Axusta o modo de alimentaciónAxusta a posición do foco, xa sexa ao cristal ou a 2.5mm por riba do cristalAxusta o valor gamma para todas as canles.Axusta a resolución horizontal da imaxe escaneada.Axusta o destaque da imaxeAxusta a resolución da imaxe escaneada.Axusta o tamaño do patrón de medios tons (punteado) usado cando se escanean as imaxes de medios tons.Axusta a resolución vertical da imaxe escaneada.Configuración da ganancia e desprazamento para escanear automaticamente. Se esta opción está desactivada, proporciónanse as opcións de axuste dos parámetros de xeito manual na interface analóxica. Esta opción está activada como predefinida. Só para probas.SombraSombra para azulSombra para verdeSombra para vermelloSombras, medias tintas, destaque, tempo de exposiciónNitidezNitidezCambiar de azul a verdeCambiar de azul a vermelloCambiar de verde a azulCambiar de verde a vermelloCambiar de vermello a azulCambiar de vermello a verdeLista curta de resoluciónsAmosa o nome do chipset usado no dispositivo.Amosa o ID do chipsetAmosa o número de escaneos feitas polo escánerApagar lámpadaApagar a lámpada do escáner.Unha caraSemella un escáner de man. Os escáneres de man adoitan descoñecer a priori a distancia á imaxe. Na súa vez utiliza unha altura de retorno -1. Axustar esta opción permítelle comprobar se unha interface pode manexar isto correctamente. Esta opción tamén permite un ancho de 11cm.Semella un escáner de man. Os escáneres de man adoitan descoñecer a priori a distancia á imaxe. Na súa vez utiliza unha altura de retorno -1. Axustar esta opción permítelle comprobar se unha interface pode manexar isto correctamente.Semella un escáner de tres pasadas devolvendo 3 mostras separadas. Por diversión, devolve verde, despois azul y finalmente vermello.Semella un escáner de tres pasadas devolvendo 3 mostras separadas. Por diversión, devolve verde, despois azul e para rematar vermello.Tamaño do límite de lecturaOmitir proceso de quecementoDiapositivaDiapositivasLentoMáis lentoO máis lentoSuaveSuavizadoNegro sólidoBranco sólidoEscoller a orixeOrixe, opcións de modo e resoluciónOpcións especiaisOpciós especiaisEspecifica a altura do soporteEspecifica a anchura do soporte. É preciso para o centrado automático de follas de escaneo.Acelerar o sensorEstándarIniciar proceso de calibraciónIniciar a calibración usando unha folla especialSimulación do código de estadoOpcións de proba de cadeaÉxitoIntercambiar branco e negroActivar/desactivar a unidade de transparencias (FAU, unidade adaptadora de filme)Acende ou apaga a lámpadaAdaptador (TMA) para negativosAdaptador (TMA) para diapositivasTecnoloxia de optimización de textoCantidade de datos (máxima) transferida con cada chamada a sane_read().Nome do ficheiro da imaxe a cargar.A lámpada vai ser apagada despois do tempo indicado (en minutos). Un valor de 0 significa que a lámpada no vai ser apagada.Número de píxeles que se perden no extremo de cada liña.O nivel de saturación controla a cantidade de «florecemento» (halo) que ocorre cando se obtén unha imaxe cunha cámara. Valores máis altos producen máis florecemento.Impresoras térmicasEsta terceira entrada é moi longa. Quizais a interface ten unha idea de como amosaloEsta opción reflicte un botón do panel frontal do escánerEsta opción reflicte o estado dos botóns do escánerEsta opción reflicte o estado dos botóns do escánerEsta opción apaga a lámpada do plano durante o escaneoSimulación de tres pasadasSimulación de tres pasadasLimiarValor do limiar para o modo de liña de arteAlternar o estado da lámpada do planoAlterna o estado da lámpada do planoArriba-esquerda XPosición X arriba-esquerda da área de escaneo.Arriba-esquerda YPosición Y arriba-esquerda da área de escaneo.TransparenciaAdaptador de transparenciasUnidade de transparenciasTaxa de transparenciaUnidade de transparenciasApagar a lámpadaApaga a lámpada ao saír do programaApaga a lámpada do escánerAcende a lámpada do escánerApaga a lámpada inmediatamente.UTA ActivadoDescoñecidoDescargarDescargar o documentoDescargar os soportes despois de escanear.Descargar as unidades despois de escanear.Actualizar estado do botónActualizar a informaciónActualizar as opciónsActualizar as opcións.Actualiza a información acerca do dispositivoUsar a marca de posición de foco a 0mm no canto de a 0,6mmUsar composición de imaxeUsar profundidade de bits maior de oito internamente, mais na saída usar só oito bits.Usar táboa gamma personalizadaUsar lente que duplica a resolución ópticaUsar E/S non bloqueanteUsar unha E/S non bloqueante para sane_red() se o permite a interface.Usar só resolucións do hardwareUsar os mesmos valores gamma para todas as canles de cores.Usar os mesmos valores para a resolución X e Y.Usar o adaptador de diapositivas de 35mmDefinida polo usuarioDefinido polo usuario (gamma=1.0)Definido polo usuario (gamma=1.8)VerticalAgardar ao botónAgardando polo botónAgardar a que se prema no botón frontal para escanear.Agardando polo botón antes de escanearQuecer até que o brillo da lámpada sexa constante no canto de agardar polos 40 segundos de quecemento.Quecer até que o brillo da lámpada sexa constante no canto de agardar polos 60 segundos de quecemento.Quecemento da lámpadaQuecer a lámpada antes de escanearO proceso de quecemento hase desactivarTempo de quecementoTempo de quecemento en segundosActivado, o proceso de escaneo non comezará inmediatamente. Para proceder, faga clic no botón «SCAN» (para MP150) ou «COLOR» (para outros modelos). Para cancelar, prema no botón «GRAY».Cando se usa gris ou liña de arte esta opción selecciona a cor a usar.Cando se usan altas resolucións nas que a resolución horizontal é máis pequena que a vertical, isto desactiva a interpolación horizontal.Nivel do brancoNivel do branco para azulNivel do branco para verdeNivel do branco para vermelloA corrección de sombra branca hase desactivarResolución XAdaptador de transparencias (XPA)Adaptador de transparencias grisAdaptador de transparencias RGBResolución YZoomerro na secuencia de ordesescáner de filmesescáner planoerro de verificación de hardwareo iniciador detectou a recepción dunha mensaxe de erromensaxe de bit de IDENTIFICACIÓN incorrectacódigo de orde de operación incorrectocampo incorrecto en CDBcampo incorrecto na lista de parámetrosmensaxe de erro incorrectafallo de lámpadalámpada non estabilizadanon se atopa o soporteinformación sen senso adicionalposición Xposición Ya opción non conectaparámetro cambiado por outro iniciadorerro na lonxitude da lista de parámetrosreiniciar o acendido / reiniciar o bus do dispositivoFallou a volta a escollerparámetro redondeadoerro no posicionamento do cabezal de escaneoescáner con cargador automáticoerro de límite de tempoespecifícanse demasiadas xanelasfallo da lámpada da unidade de transparenciasfallo de posición do cabezal de escaneo da unidade de transparenciaserro de sombreado na unidade de transparenciasdescoñecidoLUN non é compatíbelcámara websane-backends-1.0.27/po/en@boldquot.gmo0000664000175000017500000027716113110600540014624 00000000000000Þ•%+ìI˜b ™b-¦b Ôb;àb c,)c"Vczyc ôc9þc8d€Ud#Öd5úd"0eÆSefj5f  fBÁf(gS-ggؘgqhBhÓhlêhWiJgi+²icÞi Bjzcj'Þj™k$ kWÅkl.l?lDl IlVl^l cl nl yl „ll —l ¥l °l»l Äl Ïl Úlål îl ùl m mm $m 2m >mHm[mlm ~m ‰m”m m ¨mÒ¶m‰nŒn•n§nªn³nÅn Èn Õnánänèn ñn ünoo o/o"7o"Zo$}o!¢o!Äoæo!p (pIp ipŠp¡pºpÒpÛpìpsq zq?„q5Äq úqrr(r@rSrdr |r!r¿rßrärór s s #s.sCsYsns ƒss!§sÉsÞsòs t<tGYt_¡tuu uu"u+u=u @uJuOu`u=pu>®u<íu*v.v4vDv'Tv|v…vv ¯v ºvÄv ÊvÖv Ûvèv øvww ,w :wFwcw uwƒw%’w¸w%Çw íw øwxx"x +x8xLxcxkxnx~x ‚xx¢x¾xÛxöx yy$y)?y%iy y›y!²yÔyëyüy z z +z 5z AzLz]z9mz§zÅzÍz Óz Þzëzýz{{&/{ÄV{Ç|ã|é|ù|} } } ,} 6}@} O}]}z}™}ª} È} Õ}ã}ë}ó}û} ~~ 2~>~G~P~f~}~"’~µ~Õ~ò~!66I.€B¯CòA6€,x€@¥€Aæ€?((h ‘!*¿ êõ ‚(‚<‚ Q‚ [‚e‚z‚‹‚ “‚ ‚¤‚¶‚¾‚Ç‚)ß‚" ƒ$,ƒ*Qƒ#|ƒ( ƒ!Ƀëƒ# „-„J„ j„‹„Iª„,ô„'!…I…Q… a…n…*†…0±…Dâ… '†3†C†6K† ‚†1Œ†¾†Ó†ë†‡‡e,‡ ’‡³‡ŇÕ‡ó‡ú‡ˆ%ˆ?ˆ/Yˆ ‰ˆ •ˆ%¡ˆLj&æˆ ‰$‰1=‰'o‰—‰§‰¾‰ Õ‰ö‰ ŠŠ1Š GŠhŠŠ’ХР­Š»Š Š ЊEÜŠ "‹ .‹<‹;S‹‹•‹³‹΋å‹ô‹ Œ $Œ1Œ:Œ#LŒ?pŒ-°Œ8ÞŒ,/D$t™!® Ð!ñŽ'Ž$©Ž"ÎŽñŽ(*+S0°ÄÍ Þ`é JX k(y¢¿;× ‘ !‘/‘?‘ N‘ [‘ i‘ u‘ ƒ‘‘ Ÿ‘ª‘­Â‘p’ Š’ •’£’0·’ è’ ó’“““$“ 3“ @“J“Q“ Y“ d“ p“|“ …“ “š“ Ÿ“ª“ »“ Ǔӓæ“ù“ ”””,”;” J”V” p” {”‡”𔳔%Ä”hê”eS•^¹•c–a|–bÞ–aA—£—4©—Þ— ò— ý— ˜˜!˜ 3˜=˜F˜c˜t˜y˜˜ ˜˜!®˜ И;ܘ™ 0™)<™*f™(‘™›º™Vš_š nšyš ~šˆš ˜š¤š«š±š¹šÊšÛšêš ðšþš ››6›F› U›b›€›™›ž›§›¾›Õ›í›ý› œœ 4œ BœMœdœsœ‹œ£œ¼œ2М26Jdi€–¥Å åïžž(ž BžMž]žIož¹žT½ž[ŸEnŸ4´Ÿ’韹| Q6¡€ˆ¡¢ ¢¬¢ ¿¢à¢ÿ¢£%£7£V£e£u££¤£¸£7Ò£* ¤55¤ k¤w¤€¤ ¤ ¨¤¶¤Ǥؤ é¤÷¤%¥7¥I¥h¥=m¥«¥?¼¥ ü¥¦$¦-¦ >¦_¦ t¦‚¦𦠢¦ ®¦ »¦Ȧ ᦠì¦ö¦yü¦v§ Ч0«§ܧUã§9¨C:©~©†©Š£©.ª>ªVª Zªeª zª ˆª”ª¥ªºªΪäªõª « « +« 6«A«^«1b«2”«Ç«Í«Ô«ä«ì«ý«¬+¬K¬ ]¬j¬‰¬¤¬½¬Û¬í¬ ý¬ ­­­#­*­&<­*c­ Ž­˜­¡­²­ »­É­Ø­ ç­õ­ ®/® F® P® ^®k®†® –®¤®©® °® ¼®XÉ®Þ"¯°]°q± ± ˜±¢±¾± ±Ḻ²6²=²@²dI²®²βæ²þ² ³³'³ 0³ ;³ G³ S³^³~³ ³ š³§³³á³%ö³´ %´3´B´ \´ i´v´Š´’´ š´§´­´ Ê´MØ´&µ :µ GµTµdµhµ xµ‚µ †µ ‘µœµM²µ¶ ¶¶¶(¶ B¶ P¶ ]¶h¶„¶!¢¶ Ķ϶ë¶·#·?·5_·=•·?Ó·B¸GV¸4ž¸5Ó¸0 ¹/:¹0j¹;›¹*×¹*ºA-ºCoº,³º3àºÖ»|ë»&h¼ ¼ ¼«¼½¼ Ѽò¼½'½C½]½x½[’½î½¾¾4¾F¾ K¾V¾ l¾y¾‹¾ž¾ ¯¾¹¾ ɾ ê¾ ö¾¿¿2¿O¿'j¿’¿ ¤¿ ±¿»¿ Ë¿ ׿xâ¿3[ÀÀ=¥À7ãÀÁ&8Á _ÁmÁ)‰Á3³Á çÁôÁÂ.ÂGÂ`Â#uÂg™ÃœÄžÄ:¶Ä;ñÄ9-Å,gÅY”Å%îÅÆF,ÆsÆ/ˆÆ*¸Æ"ãÆ‡ÇŽÇ¤Ç'ÃÇ<ëÇ4(Ȇ]È>äÈB#É>fÉ?¥ÉDåÉ?*Ê9jÊ9¤Ê=ÞÊ@Ë=]ËB›Ë>ÞË>Ì?\Ì=œÌ<ÚÌÍ&Í .Í29ÍlÍÍD‘ÍDÖÍ,ÎHÎaÎsÎ;„Î7ÀÎøÎ(Ï?7ÏwÏ1ÏÁÏ;àÏÐ/Ð?ÐVÐoІПзÐÑÐâÐøÐ!Ñ>2Ñ?qѱÑDÇÑ% Ò42ÒgÒ#Ò£Ò'½Ò)åÒÓX$Ó2}Ó̰Ó}Ô„Ô”Ô¥Ô)´Ô ÞÔ éÔóÔÕÕ-Õ@ÕRÕeÕ"{ÕžÕ)³Õ ÝÕëÕÖü ÖÐ×pØ×KIØ•Ø¨Ø ¸ØÃØ רãØéØðØõØüØÙ ÙÙ1Ù PÙ^ÙpÙ€Ù œÙ ¨Ù´Ù#ÅÙéÙùÙ" ÚW,Ú#„Ú¨Ú·ÚÀÚÑÚ%ìÚÛ)Û*.ÛYÛmÛuÛ<ŠÛÇÛ äÛ òÛýÛÜ[ÜwÜGÜ'ØÜuÝ)vÝ= ÝŒÞÝ6kÞ¢ÞS³Þ1ß49ß7nß;¦ßâßøß ààD(à màŽàˆžàŒ'áF´áûáâ2â ;â Iâ!Tâ vâ!â £â°âÅâ×âêâ üâ ã+ãAãVãvãã–ãžã¥ã¶ãÎãîãää$ä 4ä.Uä„äCšäÞä(õä1åPåAdå¦å.Äå&óåæ 8æEæ^æwææ™æ ¢æ°æÀæ)Ðæ úæ`ç`|ç Ýçéçè %è1è¨Ièzòè>m鋬é8ê >êJê_êtêŠê)žê ÈêÕêÙêâê êê÷êüêë ëë ë%ë(ë 7ëEëKë bëmëqëvë ~ë ˆë–ë ™ë ¦ë²ëÂëÇëÍë Öë âëîëì)ì2ìOìnìƒì£ì¹ì Êì×ìëìñìøìüìíí6í;íBíFíOíXí&kí’í!®íÐíÔíåí÷íî$î+î 2î@î[î/zîªîÊîÒîâîëîôîïï‹ï £ð-°ð Þð;êð &ñ,3ñ"`ñzƒñ þñ9òBò€_ò#àò5ó":óÆ]ó$ôj?ô ªôBËô(õS7õ‹õØ¢õ{öBšöÝölôöa÷Jq÷+¼÷cè÷ Løzmø'èø™ù$ªùWÏù'ú8úIúNú Sú`úhú mú xú ƒú Žú™ú ¡ú ¯ú ºúÅú Îú Ùú äúïú øú û û û&û .û <û HûRûeûvû ˆû “ûžû §û ²ûÞÀûŸü¢ü«ü½üÀüÉüÛü Þü ëü÷üúüþü ý ýý%ý6ýEý"Mý"pý$“ý!¸ý!Úýüý!þ >þ_þ þ þ·þÐþèþñþÿsÿ ÿ?šÿ5Úÿ ,>Viz ’!³Õõú   + 9DYo„ ™£!½ßô!<2Go_·#58AS V`ev=†>Ä<@DJZ'j’›³ Å ÐÚ àì ñþ 3 B P\y ‹™%¨Î%Ý  /8 ANby„” ˜¥¸Ôñ  (:)U% ¥±!Èê# 3 A K Wbs9ƒ½Ûã é ô  + 2 &E Äl Ç1 ù ÿ    '  5  B  L V  e s  ¯ À  Þ  ë ù     ' 3  H T ] f | “ "¨ Ë ë   7 L B_ .¢ BÑ CAX,š@ÇA?J(Š ³!¿*á .(5^ s }‡œ­ µÂÆØàé)"+$N*s#ž(Â!ë #+Ol Œ­IÌ,'Cks ƒ*¨0ÓD IUe6m ¤1®àõ &<eN ´Õç÷1Ga/{ « ·%Ãé&/F1_'‘¹Éà ÷ 2>S iŠ¡´Ç ÏÝ ä òEþ D P^;u±·Õð+ FS\#n?’-Ò8,9/f$–»!Ð ò!5I$Ë"ð2(L+u0¡Òæï `  lz (›Äá;ù 5 CQa p } ‹ — ¥± ÁÌ­ä’  ¬  · Å 0Ù  ! !"!:!A!F! U! b!l!s! {! †! ’!ž! §! ±!¼! Á!Ì! Ý! é!õ!"" #"0"6"N"]" l"x" ’" "©"¼"Õ"%æ"h #eu#^Û#c:$až$b%ac%Å%4Ë%& & &,&=&C& U&_&h&…&–&›&¡& ²&¿&!Ð& ò&;þ&:' R')^'*ˆ'(³'›Ü'x(( (›(  (ª( º(Æ(Í(Ó(Û(ì(ý( ) ) ) 1)<)X)h) w)„)¢)»)À)É)à)÷)**/*@* V* d*o*†*•*­*Å*Þ*2ò*2%+X+l+†+‹+¢+¸+Ç+ç+ ,,$,8,J, d,o,,I‘,Û,`ß,[@-Eœ-4â-’.¹ª.Qd/€¶/¢70Ú0 í01-1M1S1e1„1“1£1¾1Ò1æ172*825c2 ™2¥2®2Î2 Ö2ä2õ23 3%3%?3e3w3–3I›3å3?ö3 64A4^4g4 x4™4 ®4¼4Ô4 Ü4 è4 õ45 5 &505y65°5 Ä50å56U6 s6C€7Ä7Ì7Šé7t8„8œ8  8«8 À8 Î8Ú8ë899*9;9 [9 f9 q9 |9‡9¤91¨92Ú9 :::*:2:C:U:+e:‘: £:°:Ï:ê:;!;3; C; M;[;b;i;p;&‚;*©; Ô;Þ;ç;ø; <<< -<;< N</\< Œ< –< ¤<±<Ì< Ü<ê<ï< ö< =d=Þt=S>]e>Ã? ß? ê?ô?@ @L@k@ˆ@@’@d›@A A8APA cAqAyA ‚A A ™A ¥A°AÐA áA ìAùAB3B%HBnB wB…B”B ®B »BÈBÜBäB ìBùBÿB CM*CxC ŒC ™C¦C¶CºC ÊCÔC ØC ãCîCMDRD VDbDqDzD ”D ¢D ¯DºDÖD!ôD E!E=EYEuE‘E5±E=çE?%FBeFG¨F4ðF5%G0[G/ŒG0¼G;íG*)H*THAHCÁH,I32IÖfI|=J&ºJ áJ ïJýJK #KDKbKyK•K¯KÊK[äK@LZLoL†L˜L L¨L ¾LËLÝLðL M M M \`?›`Û`Dñ`%6a4\a‘a#©aÍa'ça)b9bXNb2§bÌÚb§c®c¾cÏc)Þc d dd1dCdWdjd|dd"¥dÈd)Ýd ee,eü4eÐ1fpgKsg¿gÒg âgíg h hhhh&h.h 5h?h[h zhˆhšhªh Æh ÒhÞh#ïhi#i"3iWVi#®iÒiáiêiûi%jÇx‹y’y ˜y¤y¹yÎyäy)øy "z/z3z7>ßïLØCJ«I]¤’þ³aI*‰\b¬|þƒ«Ö°©:lN8¹¿=ðþwZÚŠù(×~md—5öõ4•Gdcp–' ŒBA‰Àržeð„áÊy¬ZÅ“&sI™ÉȘ,”…HžÝëð˜ÿ.‹z'ëA`Šé”åÏúܕ풧0;Vfwz=Y#7h훤B;• 7µ ¶*Æh$R©ôÂóW÷]”-9μ9qZNV¦ 7ÛÑ1 œˆ¼T" 6½¾Íªbì•ýCæ m+äàÓ²ç3rÀíøÞ”õtc[h\p_oÚ(Ey Íëk;3Õk09<Þ>üŽ+y%a5ï5!©W ô ³ÁÒqœRJ¸öUz€ŸL—D}%tõ¾oFOÀ1}ùï¬-á÷Ï4jØÊgô´ÍɽèøLÐA#¹aD—é¡E,)êäúD86®P¶†ÓÇDsAàÂuÒS»`ÌóÕ )±†ÝÝ>@(§F~ÃÈ&cšUÖâÎK渆‹/ažs@ëËAd½ žªVgj†±åý‹Tsî\v…chöf<êv˜@X“»klP"È`H?R¸®+ÄIßLû¨€¥·| x›üÔÔg=ŸþNà»qxÜý‘çŒÙ:ÆQ_·¯ ƒ1[zgΰ‡ãÉÖû~¿,f„Ћ_u@?Ö«Û/=‚MúÐCÌ×…6ORòT§ µRèˆä/G)ñœî~¯2W¥eZ%F›æ:ÙêšFw™| f™„¬ÇiS\wô·­ ¤ö¾€¤ KN–´}W™Ç.¢pWMnñ¨Ê*‘P9¦[d&j4=‡|ò?®–äÒDIMPSV;J–ÿ8µË#â¡‘”< Tã3ý"…uUМÄjª›!üGPXÌ»]׉Û{r-oêOÛ–ú.ì;iT¥É›vmr3!{Å |Ã/v?æ7Ánh>€Qd¾z.å2㱘u¡4ïtHˆçóˆUÁYÁeÿiâÃ6­€‡šì¦©ÍBòNYVÿ-X¢!³Úû_¿X'°"i$ }bŸÈ½à‚Ŷ}~ćFçét®x߯{ˆŠŠ0xk.&4Üpù<2Žw’Ÿ^ÑO †G² n5Ñ{v,Þ+ã26²ÝÔ´$î"oû¼Ä,Q Å*-C]G÷ÏŽ•‚º:(b]õŽ 5µ‰3—)Ø^…èE{é^ܧ¨Ñ9a±ŒÙl‘e0yºc<8î‘ßˉlE'×m¿K¥Œ1ªãMù·—«2ƒ1!ºÆñÏ[ƒ +H­‚$¦‹üŠš/yšn‡qÞÒ(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm16 bits gray2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel48 bits color4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A3A3 paperA3 paper detectedA4A4 paperA4 paper detectedA5A5 landscapeA5 portraitA6ADFADF BackADF DuplexADF FrontADF ModeADF Waiting TimeADF cover openADF jamAccess to resource has been deniedAction following double feed errorAddition of space in bottom positionAddition of space in top positionAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdjust blue/red offsetAdjust front/back offsetAdjust green/red offsetAdvancedAdvanced OptionsAdvanced paper protectionAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAllows one to test device behaviour with other supported modelsAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAuto length detectionAuto or manual focusAuto width detectionAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic threshold modeAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisB4B4 paperB4 paper detectedB5B5 paperB5 paper detectedB6BP filterBackBackground colorBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuffer modeBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration cache expiration timeCalibration data cacheCalibration fileCalibration modeCalibration nowCancel buttonCard BackCard DuplexCard FrontChange Document.Change documentChange endorser counter value by this much for each page.Changes intensity of midtonesChannelCheckChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.Collect a few mm of background on top side of scan, before paper enters ADF, and increase maximum scan area beyond paper size, to allow collection on remaining sides. May conflict with bgcolor optionColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor filterColor patternColor24Color36Color48Colour lines per readCompressionCompression argumentConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControl pattern of halftone filterControl type of halftone filterControl white level followerControls blue levelControls for endorser unitControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCrop actual image areaCustomCustom color matrix for grayscale scans.Custom color matrix.DF actionDF lengthDF length differenceDF recovery modeDF skewDF thicknessDTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.DensityDensity controlDensity dialDetect stapled documentDetermines maximum endorser counter value.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDifference in page length to trigger double feed errorDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart.Disable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Do not stop after double feed detectionDocument FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDouble feedDouble feed detectedDouble feed detectionDouble feed detector sensitivityDouble letter 11x17 inDownload pattern ADownload pattern BDropoutDropout colorDuplexDuplex offsetDuplex scanDuplex scan provide a scan of the front and back side of the documentDuplex sideDuplex switchDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmphasisEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable automatic separation of image and textEnable compressed data. May crash your front-end programEnable double feed error due to paper lengthEnable double feed error due to paper thicknessEnable double feed error due to skewEnable endorser unitEnable selection of exposure-timeEnable selection of lamp densityEnable smoothing for improved OCREnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/Disable double feed detectionEnable/Disable length control modeEnable/Disable long paper modeEnable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEndorserEndorser OptionsEndorser YEndorser alphanumeric print format. %05ud or %08ud at the end will be replaced by counter value.Endorser bitsEndorser directionEndorser fontEndorser print offset from top of paper.Endorser printing direction.Endorser printing font.Endorser printing side, requires hardware support to changeEndorser sideEndorser stepEndorser stringEndorser valueEnhance BlueEnhance GreenEnhance RedEnhanced modeEnhancementError DiffusionError codeError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra buttonExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFit to pageFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassFocus pointFocus point for scanning.Focus-modeFocus-pointForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.FrameFrame number of media holder that should be scanned.Frame to be scannedFrom paperFrom scannerFrom white stickFrontFront button waitFull scanFunctionFunction character on screenFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma curveGamma curve, from light to dark, but upper two may not workGamma function exponentGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftone typeHalftoningHalftoning UnsupportedHalt on CancelHand-Scanner SimulationHand-scanner simulationHardware deskew and cropHardware error codeHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHigh sensivityHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationIgnore center double feed sensorIgnore left double feed sensorIgnore right double feed sensorImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersImprinter ink levelImprinter ink running lowImproves quality of high resolution ball-point pen textIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInitial endorser counter value.Ink lowInk remainingInk-jet printersInt test optionsInvalid argumentInverse ImageInverse image in B/W modeInverse image in B/W or halftone modeInvert endiannessIt is right and left reversingJPEGJPEG Image Compression with Q parameter, '0' - no compressionJPEG compressionJPEG compression (yours application must be able to uncompress)Lamp colorLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off during scanLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLandscapeLegalLength Control Mode is a mode that the scanner reads up to the shorter length of actual paper or logical document length.Length control modeLens calibration in doc positionLet's see whether frontends can treat this rightLetterLevel of JPEG compression. 1 is small file, 7 is large file. 0 (default) is same as 4Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option 'side' can be used to determine correct image. This option should only be used with custom front-end software.Limit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Long Paper Mode is a mode that the scanner reads the image after it divides long paper by the length which is set in Document Size option.Long paper modeLoss of pixels per lineLowLow MemoryLow density printingLow sensivityManual feedManual feed modeManual feed selectedManual feed timeoutManual focus positionManual pre focusManually switching the lamp(s).Matrix 2x2Matrix 3x3Matrix 4x4Matrix 5x5Matrix multiplication of RGBMaxMaximum diameter of lone dots to remove from scanMaximum diameter of lone dots to remove from scan.MediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image (left/right flip)Mirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMirroringMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative colorNegative filmNegative film typeNegative grayNegative to smooth or positive to sharpen imageNegativesNo CorrectionNo detectionNo transparency correctionNoise reductionNoise removalNoneNormalNormal modeNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOMR or DFOMR or double feed detectedOffOff timerOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOne-pass scanners use only one color during gray or binary scanning, useful for colored paper or inkOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryOutlineOverscanPDF buttonPage heightPage loadedPage widthPaper is pulled partly into adfPaper protectionPaper sizePass-throughPerform outline extractionPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPower savingPredefined settingsPrepickPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorRIFROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflect output image horizontallyReflectiveRemove 2 pixel square noiseRemove 3 pixel square noiseRemove 4 pixel square noiseRemove 5 pixel square noiseRequest a preview-quality scan.Request backend to remove border from pages digitallyRequest driver to detect and correct 90 degree image rotationRequest driver to discard pages with low numbers of dark pixelsRequest driver to discard pages with low percentage of dark pixelsRequest driver to halt the paper feed instead of eject during a cancel.Request driver to remove border from pages digitallyRequest driver to remove border from pages digitally.Request driver to rotate pages by a fixed amountRequest driver to rotate skewed pages digitallyRequest driver to rotate skewed pages digitally.Request scanner to detect jams in the ADF caused by staplesRequest scanner to grab next page from ADFRequest scanner to predict jams in the ADFRequest scanner to predict jams in the ADF using improved sensorsRequest scanner to read pages quickly from ADF into internal memoryRequest scanner to reverse feed on paper jamRequest scanner to rotate and crop pages digitally.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Requires black background for scanningReset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readReverse image formatRotate image clockwiseSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner automatically detect image area and crop itScanner cover is openScanner detects paper lower edge. May confuse some frontends.Scanner detects paper sides. May reduce scanning speed.Scanner in power saving modeScanner mechanism locked for transportScanner modelScanner sensors and buttonsScanner shrinks image to fit scanned pageScanner will be stop when a paper have been skewedSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSeparationSet SDTC variance rate (sensitivity), 0 equals 127Set chroma of blueSet chroma of redSet color of background for scans. May conflict with overscan optionSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet paper position : true for landscape, false for portraitSet pixels equal to threshold to white instead of blackSet sharpening value.Set the double feed detector sensitivitySet the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the automatic threshold modeSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the lamp color (color dropout)Sets the manual feed modeSets the manual feed timeout in secondsSets the resolution of the scanned image.Sets the scan sourceSets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkew adjustmentSkew angleSkip warmup processSleep timerSlideSlidesSlowSlowerSlowestSmoothSmoothingSoftware automatic croppingSoftware blank skip percentageSoftware cropSoftware derotateSoftware deskewSoftware despeckle diameterSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Specify the calibration file to useSpeedup sensorStandardStaple detectionStart calibration process.Start calibration using special sheetStatus Code SimulationStopStop scanner when a paper have been skewedString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesTPU8x10Target operation typeTells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The lamp will be turned off during scan. The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold curve, from light to dark, but upper two may not be linearThreshold value for lineart modeThreshold whiteTime (in minutes) before a cached calibration expires. A value of 0 means cache is not used. A negative value means cache never expires.Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off.Time in minutes until the internal power supply switches to sleep modeToggle lamp of flatbedToggles the lamp of the flatbedTop edgeTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.Type of original to scanUTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse manual or automatic selection of focus point.Use non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVarianceVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level followerWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomadfbayer_16bayer_64bluebusiness_cardbwchroma of bluechroma of redcolorcommand sequence errorcontinuouscrtdarkdefaultdiffusionerr_diffusionfbfilm scannerfit-to-pageflatbed scannergraygreenhalftonehalftone_32halftone_64hardware check errorhighinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorjpeg compressionlamp failurelamp not stabilizedlightlinierlowmediummedium not presentno additional sense informationnonenormaloffoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetredreselect failurerounded parameterscan head positioning errorsheetfed scannersinglesmoothtimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNuser_defwait_docwait_doc_hopper_upwait_keywebcamProject-Id-Version: sane-backends 1.0.27 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2017-05-22 11:18-0400 Last-Translator: Automatically generated Language-Team: none Language: en@boldquot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); (1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm16 bits gray2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel48 bits color4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and “Negative†for negative film. For dark (underexposed) images you can increase this value.A3A3 paperA3 paper detectedA4A4 paperA4 paper detectedA5A5 landscapeA5 portraitA6ADFADF BackADF DuplexADF FrontADF ModeADF Waiting TimeADF cover openADF jamAccess to resource has been deniedAction following double feed errorAddition of space in bottom positionAddition of space in top positionAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdjust blue/red offsetAdjust front/back offsetAdjust green/red offsetAdvancedAdvanced OptionsAdvanced paper protectionAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAllows one to test device behaviour with other supported modelsAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAuto length detectionAuto or manual focusAuto width detectionAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic threshold modeAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisB4B4 paperB4 paper detectedB5B5 paperB5 paper detectedB6BP filterBackBackground colorBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuffer modeBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration cache expiration timeCalibration data cacheCalibration fileCalibration modeCalibration nowCancel buttonCard BackCard DuplexCard FrontChange Document.Change documentChange endorser counter value by this much for each page.Changes intensity of midtonesChannelCheckChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.Collect a few mm of background on top side of scan, before paper enters ADF, and increase maximum scan area beyond paper size, to allow collection on remaining sides. May conflict with bgcolor optionColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor filterColor patternColor24Color36Color48Colour lines per readCompressionCompression argumentConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControl pattern of halftone filterControl type of halftone filterControl white level followerControls blue levelControls for endorser unitControls green levelControls red levelControls the “hue†(blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCrop actual image areaCustomCustom color matrix for grayscale scans.Custom color matrix.DF actionDF lengthDF length differenceDF recovery modeDF skewDF thicknessDTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.DensityDensity controlDensity dialDetect stapled documentDetermines maximum endorser counter value.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDifference in page length to trigger double feed errorDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart.Disable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Do not stop after double feed detectionDocument FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDouble feedDouble feed detectedDouble feed detectionDouble feed detector sensitivityDouble letter 11x17 inDownload pattern ADownload pattern BDropoutDropout colorDuplexDuplex offsetDuplex scanDuplex scan provide a scan of the front and back side of the documentDuplex sideDuplex switchDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmphasisEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable automatic separation of image and textEnable compressed data. May crash your front-end programEnable double feed error due to paper lengthEnable double feed error due to paper thicknessEnable double feed error due to skewEnable endorser unitEnable selection of exposure-timeEnable selection of lamp densityEnable smoothing for improved OCREnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/Disable double feed detectionEnable/Disable length control modeEnable/Disable long paper modeEnable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEndorserEndorser OptionsEndorser YEndorser alphanumeric print format. %05ud or %08ud at the end will be replaced by counter value.Endorser bitsEndorser directionEndorser fontEndorser print offset from top of paper.Endorser printing direction.Endorser printing font.Endorser printing side, requires hardware support to changeEndorser sideEndorser stepEndorser stringEndorser valueEnhance BlueEnhance GreenEnhance RedEnhanced modeEnhancementError DiffusionError codeError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra buttonExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFit to pageFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassFocus pointFocus point for scanning.Focus-modeFocus-pointForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.FrameFrame number of media holder that should be scanned.Frame to be scannedFrom paperFrom scannerFrom white stickFrontFront button waitFull scanFunctionFunction character on screenFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma curveGamma curve, from light to dark, but upper two may not workGamma function exponentGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftone typeHalftoningHalftoning UnsupportedHalt on CancelHand-Scanner SimulationHand-scanner simulationHardware deskew and cropHardware error codeHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHigh sensivityHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be ‘empty’ after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationIgnore center double feed sensorIgnore left double feed sensorIgnore right double feed sensorImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersImprinter ink levelImprinter ink running lowImproves quality of high resolution ball-point pen textIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInitial endorser counter value.Ink lowInk remainingInk-jet printersInt test optionsInvalid argumentInverse ImageInverse image in B/W modeInverse image in B/W or halftone modeInvert endiannessIt is right and left reversingJPEGJPEG Image Compression with Q parameter, ‘0’ - no compressionJPEG compressionJPEG compression (yours application must be able to uncompress)Lamp colorLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off during scanLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLandscapeLegalLength Control Mode is a mode that the scanner reads up to the shorter length of actual paper or logical document length.Length control modeLens calibration in doc positionLet's see whether frontends can treat this rightLetterLevel of JPEG compression. 1 is small file, 7 is large file. 0 (default) is same as 4Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option ‘side’ can be used to determine correct image. This option should only be used with custom front-end software.Limit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Long Paper Mode is a mode that the scanner reads the image after it divides long paper by the length which is set in Document Size option.Long paper modeLoss of pixels per lineLowLow MemoryLow density printingLow sensivityManual feedManual feed modeManual feed selectedManual feed timeoutManual focus positionManual pre focusManually switching the lamp(s).Matrix 2x2Matrix 3x3Matrix 4x4Matrix 5x5Matrix multiplication of RGBMaxMaximum diameter of lone dots to remove from scanMaximum diameter of lone dots to remove from scan.MediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image (left/right flip)Mirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMirroringMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative colorNegative filmNegative film typeNegative grayNegative to smooth or positive to sharpen imageNegativesNo CorrectionNo detectionNo transparency correctionNoise reductionNoise removalNoneNormalNormal modeNormal speedNumber of bits per sample, typical values are 1 for “line-art†and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOMR or DFOMR or double feed detectedOffOff timerOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOne-pass scanners use only one color during gray or binary scanning, useful for colored paper or inkOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryOutlineOverscanPDF buttonPage heightPage loadedPage widthPaper is pulled partly into adfPaper protectionPaper sizePass-throughPerform outline extractionPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPower savingPredefined settingsPrepickPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorRIFROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflect output image horizontallyReflectiveRemove 2 pixel square noiseRemove 3 pixel square noiseRemove 4 pixel square noiseRemove 5 pixel square noiseRequest a preview-quality scan.Request backend to remove border from pages digitallyRequest driver to detect and correct 90 degree image rotationRequest driver to discard pages with low numbers of dark pixelsRequest driver to discard pages with low percentage of dark pixelsRequest driver to halt the paper feed instead of eject during a cancel.Request driver to remove border from pages digitallyRequest driver to remove border from pages digitally.Request driver to rotate pages by a fixed amountRequest driver to rotate skewed pages digitallyRequest driver to rotate skewed pages digitally.Request scanner to detect jams in the ADF caused by staplesRequest scanner to grab next page from ADFRequest scanner to predict jams in the ADFRequest scanner to predict jams in the ADF using improved sensorsRequest scanner to read pages quickly from ADF into internal memoryRequest scanner to reverse feed on paper jamRequest scanner to rotate and crop pages digitally.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Requires black background for scanningReset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readReverse image formatRotate image clockwiseSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner automatically detect image area and crop itScanner cover is openScanner detects paper lower edge. May confuse some frontends.Scanner detects paper sides. May reduce scanning speed.Scanner in power saving modeScanner mechanism locked for transportScanner modelScanner sensors and buttonsScanner shrinks image to fit scanned pageScanner will be stop when a paper have been skewedSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). “Default†is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the “graininess†of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, “Master†means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.Selects what blue radiance level should be considered “blackâ€.Selects what blue radiance level should be considered “full blueâ€.Selects what blue radiance level should be considered “whiteâ€.Selects what green radiance level should be considered “blackâ€.Selects what green radiance level should be considered “full greenâ€.Selects what green radiance level should be considered “whiteâ€.Selects what radiance level should be considered “blackâ€.Selects what radiance level should be considered “whiteâ€.Selects what red radiance level should be considered “blackâ€.Selects what red radiance level should be considered “full redâ€.Selects what red radiance level should be considered “whiteâ€.Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered “50 % blueâ€.Selects which radiance level should be considered “50 % grayâ€.Selects which radiance level should be considered “50 % greenâ€.Selects which radiance level should be considered “50 % redâ€.Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSeparationSet SDTC variance rate (sensitivity), 0 equals 127Set chroma of blueSet chroma of redSet color of background for scans. May conflict with overscan optionSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet paper position : true for landscape, false for portraitSet pixels equal to threshold to white instead of blackSet sharpening value.Set the double feed detector sensitivitySet the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the automatic threshold modeSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the lamp color (color dropout)Sets the manual feed modeSets the manual feed timeout in secondsSets the resolution of the scanned image.Sets the scan sourceSets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkew adjustmentSkew angleSkip warmup processSleep timerSlideSlidesSlowSlowerSlowestSmoothSmoothingSoftware automatic croppingSoftware blank skip percentageSoftware cropSoftware derotateSoftware deskewSoftware despeckle diameterSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Specify the calibration file to useSpeedup sensorStandardStaple detectionStart calibration process.Start calibration using special sheetStatus Code SimulationStopStop scanner when a paper have been skewedString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesTPU8x10Target operation typeTells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The lamp will be turned off during scan. The number of pixels that are wasted at the end of each line.The saturation level controls the amount of “blooming†that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold curve, from light to dark, but upper two may not be linearThreshold value for lineart modeThreshold whiteTime (in minutes) before a cached calibration expires. A value of 0 means cache is not used. A negative value means cache never expires.Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off.Time in minutes until the internal power supply switches to sleep modeToggle lamp of flatbedToggles the lamp of the flatbedTop edgeTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.Type of original to scanUTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse manual or automatic selection of focus point.Use non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVarianceVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press “SCAN†button (for MP150) or “COLOR†button (for other models). To cancel, press “GRAY†button.When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level followerWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomadfbayer_16bayer_64bluebusiness_cardbwchroma of bluechroma of redcolorcommand sequence errorcontinuouscrtdarkdefaultdiffusionerr_diffusionfbfilm scannerfit-to-pageflatbed scannergraygreenhalftonehalftone_32halftone_64hardware check errorhighinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorjpeg compressionlamp failurelamp not stabilizedlightlinierlowmediummedium not presentno additional sense informationnonenormaloffoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetredreselect failurerounded parameterscan head positioning errorsheetfed scannersinglesmoothtimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNuser_defwait_docwait_doc_hopper_upwait_keywebcamsane-backends-1.0.27/po/Makevars0000664000175000017500000000346712775312262013355 00000000000000# Makevars -- snippet for inclusion in po/ -*- Makefile -*- # Copyright (C) 2016 Olaf Meeuwissen and the SANE developers # # This file is part of the SANE build infra-structure. See the # included LICENSE file for license information. # Message domain to use. # Normally this is the same as the $(PACKAGE_TARNAME), but note that # gettext does not support that variable (last checked for 0.18.1). DOMAIN = $(PACKAGE) # Copyright holder for the messages in the $(DOMAIN).pot file. # This is the (set of) copyright holder(s) of files listed in the # POTFILES.in file (insofar they contributed translatable strings). # The translators are expected to transfer the copyright for their # translations to the $(COPYRIGHT_HOLDER)(s), or to disclaim their # copyright thereby putting their strings in the public domain. COPYRIGHT_HOLDER = The SANE developers # Where to report problems with translatable strings, that is, the # strings in $(DOMAIN).pot or those that really should be in there. MSGID_BUGS_ADDRESS = $(PACKAGE_BUGREPORT) # Directory locations. # The $(top_builddir) should be relative to the directory that holds # this Makevars file. The $(subdir) ought to be set such that a `cd # $(top_builddir)/$(subdir)` has no effect (assuming no symlinks in # the path). top_builddir = .. subdir = po # Options to pass to xgettext and other gettext utilities. # Additional options may also by specified using AM_XGETTEXT_OPTION # in `$(top_srcdir)/configure.ac`. See Makefile.in.in and Rules-* # for variables available XGETTEXT_OPTIONS = --keyword=SANE_I18N XGETTEXT_OPTIONS += --flag=SANE_I18N:1:no-c-format MSGMERGE_OPTIONS = --width=75 # Locale categories, in addition to LC_MESSAGES, for which message # catalogs are to be used. EXTRA_LOCALE_CATEGORIES = EXTRA_DIST = README EXTRA_DIST += Rules-automake sane-backends-1.0.27/po/en@boldquot.header0000664000175000017500000000247112775312262015301 00000000000000# All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # # This catalog furthermore displays the text between the quotation marks in # bold face, assuming the VT100/XTerm escape sequences. # sane-backends-1.0.27/po/en@quot.gmo0000664000175000017500000027661513110600540013766 00000000000000Þ•%+ìI˜b ™b-¦b Ôb;àb c,)c"Vczyc ôc9þc8d€Ud#Öd5úd"0eÆSefj5f  fBÁf(gS-ggؘgqhBhÓhlêhWiJgi+²icÞi Bjzcj'Þj™k$ kWÅkl.l?lDl IlVl^l cl nl yl „ll —l ¥l °l»l Äl Ïl Úlål îl ùl m mm $m 2m >mHm[mlm ~m ‰m”m m ¨mÒ¶m‰nŒn•n§nªn³nÅn Èn Õnánänèn ñn ünoo o/o"7o"Zo$}o!¢o!Äoæo!p (pIp ipŠp¡pºpÒpÛpìpsq zq?„q5Äq úqrr(r@rSrdr |r!r¿rßrärór s s #s.sCsYsns ƒss!§sÉsÞsòs t<tGYt_¡tuu uu"u+u=u @uJuOu`u=pu>®u<íu*v.v4vDv'Tv|v…vv ¯v ºvÄv ÊvÖv Ûvèv øvww ,w :wFwcw uwƒw%’w¸w%Çw íw øwxx"x +x8xLxcxkxnx~x ‚xx¢x¾xÛxöx yy$y)?y%iy y›y!²yÔyëyüy z z +z 5z AzLz]z9mz§zÅzÍz Óz Þzëzýz{{&/{ÄV{Ç|ã|é|ù|} } } ,} 6}@} O}]}z}™}ª} È} Õ}ã}ë}ó}û} ~~ 2~>~G~P~f~}~"’~µ~Õ~ò~!66I.€B¯CòA6€,x€@¥€Aæ€?((h ‘!*¿ êõ ‚(‚<‚ Q‚ [‚e‚z‚‹‚ “‚ ‚¤‚¶‚¾‚Ç‚)ß‚" ƒ$,ƒ*Qƒ#|ƒ( ƒ!Ƀëƒ# „-„J„ j„‹„Iª„,ô„'!…I…Q… a…n…*†…0±…Dâ… '†3†C†6K† ‚†1Œ†¾†Ó†ë†‡‡e,‡ ’‡³‡ŇÕ‡ó‡ú‡ˆ%ˆ?ˆ/Yˆ ‰ˆ •ˆ%¡ˆLj&æˆ ‰$‰1=‰'o‰—‰§‰¾‰ Õ‰ö‰ ŠŠ1Š GŠhŠŠ’ХР­Š»Š Š ЊEÜŠ "‹ .‹<‹;S‹‹•‹³‹΋å‹ô‹ Œ $Œ1Œ:Œ#LŒ?pŒ-°Œ8ÞŒ,/D$t™!® Ð!ñŽ'Ž$©Ž"ÎŽñŽ(*+S0°ÄÍ Þ`é JX k(y¢¿;× ‘ !‘/‘?‘ N‘ [‘ i‘ u‘ ƒ‘‘ Ÿ‘ª‘­Â‘p’ Š’ •’£’0·’ è’ ó’“““$“ 3“ @“J“Q“ Y“ d“ p“|“ …“ “š“ Ÿ“ª“ »“ Ǔӓæ“ù“ ”””,”;” J”V” p” {”‡”𔳔%Ä”hê”eS•^¹•c–a|–bÞ–aA—£—4©—Þ— ò— ý— ˜˜!˜ 3˜=˜F˜c˜t˜y˜˜ ˜˜!®˜ И;ܘ™ 0™)<™*f™(‘™›º™Vš_š nšyš ~šˆš ˜š¤š«š±š¹šÊšÛšêš ðšþš ››6›F› U›b›€›™›ž›§›¾›Õ›í›ý› œœ 4œ BœMœdœsœ‹œ£œ¼œ2М26Jdi€–¥Å åïžž(ž BžMž]žIož¹žT½ž[ŸEnŸ4´Ÿ’韹| Q6¡€ˆ¡¢ ¢¬¢ ¿¢à¢ÿ¢£%£7£V£e£u££¤£¸£7Ò£* ¤55¤ k¤w¤€¤ ¤ ¨¤¶¤Ǥؤ é¤÷¤%¥7¥I¥h¥=m¥«¥?¼¥ ü¥¦$¦-¦ >¦_¦ t¦‚¦𦠢¦ ®¦ »¦Ȧ ᦠì¦ö¦yü¦v§ Ч0«§ܧUã§9¨C:©~©†©Š£©.ª>ªVª Zªeª zª ˆª”ª¥ªºªΪäªõª « « +« 6«A«^«1b«2”«Ç«Í«Ô«ä«ì«ý«¬+¬K¬ ]¬j¬‰¬¤¬½¬Û¬í¬ ý¬ ­­­#­*­&<­*c­ Ž­˜­¡­²­ »­É­Ø­ ç­õ­ ®/® F® P® ^®k®†® –®¤®©® °® ¼®XÉ®Þ"¯°]°q± ± ˜±¢±¾± ±Ḻ²6²=²@²dI²®²βæ²þ² ³³'³ 0³ ;³ G³ S³^³~³ ³ š³§³³á³%ö³´ %´3´B´ \´ i´v´Š´’´ š´§´­´ Ê´MØ´&µ :µ GµTµdµhµ xµ‚µ †µ ‘µœµM²µ¶ ¶¶¶(¶ B¶ P¶ ]¶h¶„¶!¢¶ Ķ϶ë¶·#·?·5_·=•·?Ó·B¸GV¸4ž¸5Ó¸0 ¹/:¹0j¹;›¹*×¹*ºA-ºCoº,³º3àºÖ»|ë»&h¼ ¼ ¼«¼½¼ Ѽò¼½'½C½]½x½[’½î½¾¾4¾F¾ K¾V¾ l¾y¾‹¾ž¾ ¯¾¹¾ ɾ ê¾ ö¾¿¿2¿O¿'j¿’¿ ¤¿ ±¿»¿ Ë¿ ׿xâ¿3[ÀÀ=¥À7ãÀÁ&8Á _ÁmÁ)‰Á3³Á çÁôÁÂ.ÂGÂ`Â#uÂg™ÃœÄžÄ:¶Ä;ñÄ9-Å,gÅY”Å%îÅÆF,ÆsÆ/ˆÆ*¸Æ"ãÆ‡ÇŽÇ¤Ç'ÃÇ<ëÇ4(Ȇ]È>äÈB#É>fÉ?¥ÉDåÉ?*Ê9jÊ9¤Ê=ÞÊ@Ë=]ËB›Ë>ÞË>Ì?\Ì=œÌ<ÚÌÍ&Í .Í29ÍlÍÍD‘ÍDÖÍ,ÎHÎaÎsÎ;„Î7ÀÎøÎ(Ï?7ÏwÏ1ÏÁÏ;àÏÐ/Ð?ÐVÐoІПзÐÑÐâÐøÐ!Ñ>2Ñ?qѱÑDÇÑ% Ò42ÒgÒ#Ò£Ò'½Ò)åÒÓX$Ó2}Ó̰Ó}Ô„Ô”Ô¥Ô)´Ô ÞÔ éÔóÔÕÕ-Õ@ÕRÕeÕ"{ÕžÕ)³Õ ÝÕëÕÖü ÖÐ×pØ×KIØ•Ø¨Ø ¸ØÃØ רãØéØðØõØüØÙ ÙÙ1Ù PÙ^ÙpÙ€Ù œÙ ¨Ù´Ù#ÅÙéÙùÙ" ÚW,Ú#„Ú¨Ú·ÚÀÚÑÚ%ìÚÛ)Û*.ÛYÛmÛuÛ<ŠÛÇÛ äÛ òÛýÛÜ[ÜwÜGÜ'ØÜuÝ)vÝ= ÝŒÞÝ6kÞ¢ÞS³Þ1ß49ß7nß;¦ßâßøß ààD(à màŽàˆžàŒ'áF´áûáâ2â ;â Iâ!Tâ vâ!â £â°âÅâ×âêâ üâ ã+ãAãVãvãã–ãžã¥ã¶ãÎãîãää$ä 4ä.Uä„äCšäÞä(õä1åPåAdå¦å.Äå&óåæ 8æEæ^æwææ™æ ¢æ°æÀæ)Ðæ úæ`ç`|ç Ýçéçè %è1è¨Ièzòè>m鋬é8ê >êJê_êtêŠê)žê ÈêÕêÙêâê êê÷êüêë ëë ë%ë(ë 7ëEëKë bëmëqëvë ~ë ˆë–ë ™ë ¦ë²ëÂëÇëÍë Öë âëîëì)ì2ìOìnìƒì£ì¹ì Êì×ìëìñìøìüìíí6í;íBíFíOíXí&kí’í!®íÐíÔíåí÷íî$î+î 2î@î[î/zîªîÊîÒîâîëîôîïï‡ï Ÿð-¬ð Úð;æð "ñ,/ñ"\ñzñ úñ9ò>ò€[ò#Üò5ó"6óÆYó ôj;ô ¦ôBÇô( õS3õ‡õØžõwöB–öÙölðö]÷Jm÷+¸÷cä÷ Høziø'äø™ ù$¦ùWËù#ú4úEúJú Oú\údú iú tú ú Šú•ú ú «ú ¶úÁú Êú Õú àúëú ôú ÿú û û"û *û 8û DûNûaûrû „û ûšû £û ®ûÖ¼û“ü–üŸü±ü´ü½üÏü Òü ßüëüîüòü ûü ýýý*ý9ý"Aý"dý$‡ý!¬ý!Îýðý!þ 2þSþ sþ”þ«þÄþÜþåþöþsÿ „ÿ?Žÿ5Îÿ  2J]n †!§Ééîý   -8Mcx —!±Óèü<&Gc_« ),5G JTYj=z>¸<÷48>N'^†§ ¹ ÄÎ Ôà åò  ' 6 DPm %œÂ%Ñ ÷ #, 5BVmuxˆ Œ™¬Èå .)I%s ™¥!¼Þõ ' 5 ? KVg9w±Ï× Ý èõ  & &9 Ä` Ç% í ó      )  6  @ J  Y g „ £ ´  Ò  ß í õ ý    '  < H Q Z p ‡ "œ ¿ ß ü  + @ :S .Ž B½ CAD,†@³Aô?6(v Ÿ!«*Í ø(!J _ isˆ™ ¡®²ÄÌÕ)í"$:*_#Š(®!×ù#;X x™I¸,'/W_ o|*”0¿Dð 5AQ6Y 1šÌáù(e:  ÁÓã3M/g — £%¯Õ&ô21K'}¥µÌ ã *? Uv ³ »É Ð ÞEê 0 <J;a£ÁÜó 2?H#Z?~-¾8ì,%/R$‚§!¼ Þ!ÿ!5$·"Üÿ(8+a0¾ÒÛ ì`÷ Xf y(‡°Í;å ! /=M \ i w ƒ ‘ ­¸­Ð~  ˜  £ ± 0Å  ö  !!&!-!2! A! N!X!_! g! r! ~!Š! “! !¨! ­!¸! É! Õ!á!ô!" """":"I" X"d" ~" ‰"•"¨"Á"%Ò"hø"ea#^Ç#c&$aŠ$bì$aO%±%4·%ì% & &&)&/& A&K&T&q&‚&‡&& ž&«&!¼& Þ&;ê&&' >')J'*t'(Ÿ'›È'd(m( |(‡( Œ(–( ¦(²(¹(¿(Ç(Ø(é(ø( þ( ) )()D)T) c)p)Ž)§)¬)µ)Ì)ã)û) **,* B* P*[*r**™*±*Ê*2Þ*2+D+X+r+w+Ž+¤+³+Ó+ ó+ý+,$,6, P,[,k,I},Ç,XË,[$-E€-4Æ-’û-¹Ž.QH/€š/¢0¾0 Ñ0ò011171I1h1w1‡1¢1¶1Ê17ä1*25G2 }2‰2’2²2 º2È2Ù2ê2 û2 3%#3I3[3z3A3Á3?Ò3 44:4C4 T4u4 Š4˜4°4 ¸4 Ä4 Ñ4Þ4 ÷4 5 5y5Œ5  50Á5ò5Uù5O6CT7˜7 7н7H8X8p8 t88 ”8 ¢8®8¿8Ô8è8þ89 /9 :9 E9 P9[9x91|92®9á9ç9î9þ9::):+9:e: w:„:£:¾:×:õ:; ; !;/;6;=;D;&V;*}; ¨;²;»;Ì; Õ;ã;ò; << "</0< `< j< x<…< < °<¾<Ã< Ê< Ö<\ã<Þ@=>]1>? «? ¶?À?Ü? à?Lê?7@T@[@^@dg@Ì@ì@AA /A=AEA NA YA eA qA|AœA ­A ¸AÅAàAÿA%B:B CBQB`B zB ‡B”B¨B°B ¸BÅBËB èBMöBDC XC eCrC‚C†C –C C ¤C ¯CºCMÐCD "D.D=DFD `D nD {D†D¢D!ÀD âDíD E%EAE]E5}E=³E?ñEB1FGtF4¼F5ñF0'G/XG0ˆG;¹G*õG* HAKHCH,ÑH3þHÖ2I| J&†J ­J »JÉJÛJ ïJK.KEKaK{K–K[°K L&L;LRLdL iLtL ŠL—L©L¼L ÍL×L çL M M!M4MPMmM'ˆM°M ÂM ÏMÙM éM õMxN3yN­N=ÃN7O9O&VO }O‹O)§O3ÑO PP%P.6PeP~P#“Pg·Q RÀR:ØR;S9OS,‰S]¶S%T:TJRTT/²T*âT" U‡0U¸UÎU'íU<V4RV†‡VBWFQWB˜WCÛWHXChX=¬X=êXA(YDjYA¯YBñYB4ZBwZCºZAþZ<@[}[Œ[ ”[2Ÿ[Ò[å[D÷[D<\,\®\Ç\Ù\;ê\7&]^](t]?]Ý]1õ]'^;F^‚^•^¥^¼^Õ^ì^__7_H_^_!v_>˜_?×_`D-`%r`4˜`Í`#å` a'#a)KauaXŠa2ãaÌbãbêbúb c)c Dc OcYcmcc“c¦c¸cËc"ácd)d CdQdhdüpdÐmep>fK¯fûfg g)g =gIgOgVg[gbgjg qg{g—g ¶gÄgÖgæg h hh#+hOh_h"ohW’h#êhii&i7i%Rixii*”i¿iÓiÛi<ði-j Jj Xjcjkj[jÝjGöj'>kufk)Ük=lDl6Õl mSm1qm4£m7Øm;nLnbn xn‚nD’n ×nønˆoŒ‘oFpep|pœp ¥p ³p!¾p àp!ëp qq/qAqTq fq tq•q«qÀqàqùqrrr r8rXrlrrŽr žr.¿rîrCsHs(_s1ˆsºsAÎst..t&]t„t ¢t¯tÈtátútu uu*u):u du`…u`æu GvSvov v›v´³vzhw>ãw‹"x®x ´xÀxÕxêxy)y >yKyOyXy `ymyryvyyˆy y›yžy ­y»yÁy Øyãyçyìy ôy þy z z z(z8z=zCz Lz Xzdzyz)~z¨zÅzäzùz{/{ @{M{a{g{n{r{y{Œ{¬{±{¸{¼{Å{Î{&á{|!$|F|J|[|m|‰|š|¡| ¨|¶|Ñ|/ð| }@}H}X}a}j}}}†}áU @p™œk_lèÕ¯xqt¡jQ¼“` [º^X¶¸’ÀØKÎB ÆKsY‚¢J˜Œ¹nLÕá’%„`Ê­:\Ìø²°(„$?#Ó^â* ðO“%'fZÇ¢£JøEMgòñ&HåìYíB Q“÷mubSr0)Ô Ž³£´8#C¹ËoÚ¨ óSÙƒe£iÂÓ>7>ßïLØCJ«I]¤’þ³aI*‰\b¬|þƒ«Ö°©:lN8¹¿=ðþwZÚŠù(×~md—5öõ4•Gdcp–' ŒBA‰Àržeð„áÊy¬ZÅ“&sI™ÉȘ,”…HžÝëð˜ÿ.‹z'ëA`Šé”åÏúܕ풧0;Vfwz=Y#7h훤B;• 7µ ¶*Æh$R©ôÂóW÷]”-9μ9qZNV¦ 7ÛÑ1 œˆ¼T" 6½¾Íªbì•ýCæ m+äàÓ²ç3rÀíøÞ”õtc[h\p_oÚ(Ey Íëk;3Õk09<Þ>üŽ+y%a5ï5!©W ô ³ÁÒqœRJ¸öUz€ŸL—D}%tõ¾oFOÀ1}ùï¬-á÷Ï4jØÊgô´ÍɽèøLÐA#¹aD—é¡E,)êäúD86®P¶†ÓÇDsAàÂuÒS»`ÌóÕ )±†ÝÝ>@(§F~ÃÈ&cšUÖâÎK渆‹/ažs@ëËAd½ žªVgj†±åý‹Tsî\v…chöf<êv˜@X“»klP"È`H?R¸®+ÄIßLû¨€¥·| x›üÔÔg=ŸþNà»qxÜý‘çŒÙ:ÆQ_·¯ ƒ1[zgΰ‡ãÉÖû~¿,f„Ћ_u@?Ö«Û/=‚MúÐCÌ×…6ORòT§ µRèˆä/G)ñœî~¯2W¥eZ%F›æ:ÙêšFw™| f™„¬ÇiS\wô·­ ¤ö¾€¤ KN–´}W™Ç.¢pWMnñ¨Ê*‘P9¦[d&j4=‡|ò?®–äÒDIMPSV;J–ÿ8µË#â¡‘”< Tã3ý"…uUМÄjª›!üGPXÌ»]׉Û{r-oêOÛ–ú.ì;iT¥É›vmr3!{Å |Ã/v?æ7Ánh>€Qd¾z.å2㱘u¡4ïtHˆçóˆUÁYÁeÿiâÃ6­€‡šì¦©ÍBòNYVÿ-X¢!³Úû_¿X'°"i$ }bŸÈ½à‚Ŷ}~ćFçét®x߯{ˆŠŠ0xk.&4Üpù<2Žw’Ÿ^ÑO †G² n5Ñ{v,Þ+ã26²ÝÔ´$î"oû¼Ä,Q Å*-C]G÷ÏŽ•‚º:(b]õŽ 5µ‰3—)Ø^…èE{é^ܧ¨Ñ9a±ŒÙl‘e0yºc<8î‘ßˉlE'×m¿K¥Œ1ªãMù·—«2ƒ1!ºÆñÏ[ƒ +H­‚$¦‹üŠš/yšn‡qÞÒ(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm16 bits gray2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel48 bits color4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A3A3 paperA3 paper detectedA4A4 paperA4 paper detectedA5A5 landscapeA5 portraitA6ADFADF BackADF DuplexADF FrontADF ModeADF Waiting TimeADF cover openADF jamAccess to resource has been deniedAction following double feed errorAddition of space in bottom positionAddition of space in top positionAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdjust blue/red offsetAdjust front/back offsetAdjust green/red offsetAdvancedAdvanced OptionsAdvanced paper protectionAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAllows one to test device behaviour with other supported modelsAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAuto length detectionAuto or manual focusAuto width detectionAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic threshold modeAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisB4B4 paperB4 paper detectedB5B5 paperB5 paper detectedB6BP filterBackBackground colorBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuffer modeBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration cache expiration timeCalibration data cacheCalibration fileCalibration modeCalibration nowCancel buttonCard BackCard DuplexCard FrontChange Document.Change documentChange endorser counter value by this much for each page.Changes intensity of midtonesChannelCheckChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.Collect a few mm of background on top side of scan, before paper enters ADF, and increase maximum scan area beyond paper size, to allow collection on remaining sides. May conflict with bgcolor optionColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor filterColor patternColor24Color36Color48Colour lines per readCompressionCompression argumentConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControl pattern of halftone filterControl type of halftone filterControl white level followerControls blue levelControls for endorser unitControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCrop actual image areaCustomCustom color matrix for grayscale scans.Custom color matrix.DF actionDF lengthDF length differenceDF recovery modeDF skewDF thicknessDTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.DensityDensity controlDensity dialDetect stapled documentDetermines maximum endorser counter value.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDifference in page length to trigger double feed errorDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart.Disable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Do not stop after double feed detectionDocument FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDouble feedDouble feed detectedDouble feed detectionDouble feed detector sensitivityDouble letter 11x17 inDownload pattern ADownload pattern BDropoutDropout colorDuplexDuplex offsetDuplex scanDuplex scan provide a scan of the front and back side of the documentDuplex sideDuplex switchDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmphasisEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable automatic separation of image and textEnable compressed data. May crash your front-end programEnable double feed error due to paper lengthEnable double feed error due to paper thicknessEnable double feed error due to skewEnable endorser unitEnable selection of exposure-timeEnable selection of lamp densityEnable smoothing for improved OCREnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/Disable double feed detectionEnable/Disable length control modeEnable/Disable long paper modeEnable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEndorserEndorser OptionsEndorser YEndorser alphanumeric print format. %05ud or %08ud at the end will be replaced by counter value.Endorser bitsEndorser directionEndorser fontEndorser print offset from top of paper.Endorser printing direction.Endorser printing font.Endorser printing side, requires hardware support to changeEndorser sideEndorser stepEndorser stringEndorser valueEnhance BlueEnhance GreenEnhance RedEnhanced modeEnhancementError DiffusionError codeError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra buttonExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFit to pageFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassFocus pointFocus point for scanning.Focus-modeFocus-pointForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.FrameFrame number of media holder that should be scanned.Frame to be scannedFrom paperFrom scannerFrom white stickFrontFront button waitFull scanFunctionFunction character on screenFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma curveGamma curve, from light to dark, but upper two may not workGamma function exponentGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftone typeHalftoningHalftoning UnsupportedHalt on CancelHand-Scanner SimulationHand-scanner simulationHardware deskew and cropHardware error codeHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHigh sensivityHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationIgnore center double feed sensorIgnore left double feed sensorIgnore right double feed sensorImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersImprinter ink levelImprinter ink running lowImproves quality of high resolution ball-point pen textIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInitial endorser counter value.Ink lowInk remainingInk-jet printersInt test optionsInvalid argumentInverse ImageInverse image in B/W modeInverse image in B/W or halftone modeInvert endiannessIt is right and left reversingJPEGJPEG Image Compression with Q parameter, '0' - no compressionJPEG compressionJPEG compression (yours application must be able to uncompress)Lamp colorLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off during scanLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLandscapeLegalLength Control Mode is a mode that the scanner reads up to the shorter length of actual paper or logical document length.Length control modeLens calibration in doc positionLet's see whether frontends can treat this rightLetterLevel of JPEG compression. 1 is small file, 7 is large file. 0 (default) is same as 4Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option 'side' can be used to determine correct image. This option should only be used with custom front-end software.Limit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Long Paper Mode is a mode that the scanner reads the image after it divides long paper by the length which is set in Document Size option.Long paper modeLoss of pixels per lineLowLow MemoryLow density printingLow sensivityManual feedManual feed modeManual feed selectedManual feed timeoutManual focus positionManual pre focusManually switching the lamp(s).Matrix 2x2Matrix 3x3Matrix 4x4Matrix 5x5Matrix multiplication of RGBMaxMaximum diameter of lone dots to remove from scanMaximum diameter of lone dots to remove from scan.MediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image (left/right flip)Mirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMirroringMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative colorNegative filmNegative film typeNegative grayNegative to smooth or positive to sharpen imageNegativesNo CorrectionNo detectionNo transparency correctionNoise reductionNoise removalNoneNormalNormal modeNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOMR or DFOMR or double feed detectedOffOff timerOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOne-pass scanners use only one color during gray or binary scanning, useful for colored paper or inkOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryOutlineOverscanPDF buttonPage heightPage loadedPage widthPaper is pulled partly into adfPaper protectionPaper sizePass-throughPerform outline extractionPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPower savingPredefined settingsPrepickPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorRIFROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflect output image horizontallyReflectiveRemove 2 pixel square noiseRemove 3 pixel square noiseRemove 4 pixel square noiseRemove 5 pixel square noiseRequest a preview-quality scan.Request backend to remove border from pages digitallyRequest driver to detect and correct 90 degree image rotationRequest driver to discard pages with low numbers of dark pixelsRequest driver to discard pages with low percentage of dark pixelsRequest driver to halt the paper feed instead of eject during a cancel.Request driver to remove border from pages digitallyRequest driver to remove border from pages digitally.Request driver to rotate pages by a fixed amountRequest driver to rotate skewed pages digitallyRequest driver to rotate skewed pages digitally.Request scanner to detect jams in the ADF caused by staplesRequest scanner to grab next page from ADFRequest scanner to predict jams in the ADFRequest scanner to predict jams in the ADF using improved sensorsRequest scanner to read pages quickly from ADF into internal memoryRequest scanner to reverse feed on paper jamRequest scanner to rotate and crop pages digitally.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Requires black background for scanningReset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readReverse image formatRotate image clockwiseSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner automatically detect image area and crop itScanner cover is openScanner detects paper lower edge. May confuse some frontends.Scanner detects paper sides. May reduce scanning speed.Scanner in power saving modeScanner mechanism locked for transportScanner modelScanner sensors and buttonsScanner shrinks image to fit scanned pageScanner will be stop when a paper have been skewedSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSeparationSet SDTC variance rate (sensitivity), 0 equals 127Set chroma of blueSet chroma of redSet color of background for scans. May conflict with overscan optionSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet paper position : true for landscape, false for portraitSet pixels equal to threshold to white instead of blackSet sharpening value.Set the double feed detector sensitivitySet the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the automatic threshold modeSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the lamp color (color dropout)Sets the manual feed modeSets the manual feed timeout in secondsSets the resolution of the scanned image.Sets the scan sourceSets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkew adjustmentSkew angleSkip warmup processSleep timerSlideSlidesSlowSlowerSlowestSmoothSmoothingSoftware automatic croppingSoftware blank skip percentageSoftware cropSoftware derotateSoftware deskewSoftware despeckle diameterSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Specify the calibration file to useSpeedup sensorStandardStaple detectionStart calibration process.Start calibration using special sheetStatus Code SimulationStopStop scanner when a paper have been skewedString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesTPU8x10Target operation typeTells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The lamp will be turned off during scan. The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold curve, from light to dark, but upper two may not be linearThreshold value for lineart modeThreshold whiteTime (in minutes) before a cached calibration expires. A value of 0 means cache is not used. A negative value means cache never expires.Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off.Time in minutes until the internal power supply switches to sleep modeToggle lamp of flatbedToggles the lamp of the flatbedTop edgeTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.Type of original to scanUTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse manual or automatic selection of focus point.Use non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVarianceVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level followerWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomadfbayer_16bayer_64bluebusiness_cardbwchroma of bluechroma of redcolorcommand sequence errorcontinuouscrtdarkdefaultdiffusionerr_diffusionfbfilm scannerfit-to-pageflatbed scannergraygreenhalftonehalftone_32halftone_64hardware check errorhighinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorjpeg compressionlamp failurelamp not stabilizedlightlinierlowmediummedium not presentno additional sense informationnonenormaloffoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetredreselect failurerounded parameterscan head positioning errorsheetfed scannersinglesmoothtimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNuser_defwait_docwait_doc_hopper_upwait_keywebcamProject-Id-Version: sane-backends 1.0.27 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2017-05-22 11:18-0400 Last-Translator: Automatically generated Language-Team: none Language: en@quot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); (1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm16 bits gray2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel48 bits color4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and “Negative†for negative film. For dark (underexposed) images you can increase this value.A3A3 paperA3 paper detectedA4A4 paperA4 paper detectedA5A5 landscapeA5 portraitA6ADFADF BackADF DuplexADF FrontADF ModeADF Waiting TimeADF cover openADF jamAccess to resource has been deniedAction following double feed errorAddition of space in bottom positionAddition of space in top positionAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdjust blue/red offsetAdjust front/back offsetAdjust green/red offsetAdvancedAdvanced OptionsAdvanced paper protectionAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAllows one to test device behaviour with other supported modelsAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAuto length detectionAuto or manual focusAuto width detectionAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic threshold modeAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisB4B4 paperB4 paper detectedB5B5 paperB5 paper detectedB6BP filterBackBackground colorBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuffer modeBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration cache expiration timeCalibration data cacheCalibration fileCalibration modeCalibration nowCancel buttonCard BackCard DuplexCard FrontChange Document.Change documentChange endorser counter value by this much for each page.Changes intensity of midtonesChannelCheckChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.Collect a few mm of background on top side of scan, before paper enters ADF, and increase maximum scan area beyond paper size, to allow collection on remaining sides. May conflict with bgcolor optionColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor filterColor patternColor24Color36Color48Colour lines per readCompressionCompression argumentConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControl pattern of halftone filterControl type of halftone filterControl white level followerControls blue levelControls for endorser unitControls green levelControls red levelControls the “hue†(blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCrop actual image areaCustomCustom color matrix for grayscale scans.Custom color matrix.DF actionDF lengthDF length differenceDF recovery modeDF skewDF thicknessDTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.DensityDensity controlDensity dialDetect stapled documentDetermines maximum endorser counter value.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDifference in page length to trigger double feed errorDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart.Disable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Do not stop after double feed detectionDocument FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDouble feedDouble feed detectedDouble feed detectionDouble feed detector sensitivityDouble letter 11x17 inDownload pattern ADownload pattern BDropoutDropout colorDuplexDuplex offsetDuplex scanDuplex scan provide a scan of the front and back side of the documentDuplex sideDuplex switchDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmphasisEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable automatic separation of image and textEnable compressed data. May crash your front-end programEnable double feed error due to paper lengthEnable double feed error due to paper thicknessEnable double feed error due to skewEnable endorser unitEnable selection of exposure-timeEnable selection of lamp densityEnable smoothing for improved OCREnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/Disable double feed detectionEnable/Disable length control modeEnable/Disable long paper modeEnable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEndorserEndorser OptionsEndorser YEndorser alphanumeric print format. %05ud or %08ud at the end will be replaced by counter value.Endorser bitsEndorser directionEndorser fontEndorser print offset from top of paper.Endorser printing direction.Endorser printing font.Endorser printing side, requires hardware support to changeEndorser sideEndorser stepEndorser stringEndorser valueEnhance BlueEnhance GreenEnhance RedEnhanced modeEnhancementError DiffusionError codeError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra buttonExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFit to pageFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassFocus pointFocus point for scanning.Focus-modeFocus-pointForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.FrameFrame number of media holder that should be scanned.Frame to be scannedFrom paperFrom scannerFrom white stickFrontFront button waitFull scanFunctionFunction character on screenFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma curveGamma curve, from light to dark, but upper two may not workGamma function exponentGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftone typeHalftoningHalftoning UnsupportedHalt on CancelHand-Scanner SimulationHand-scanner simulationHardware deskew and cropHardware error codeHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHigh sensivityHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be ‘empty’ after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationIgnore center double feed sensorIgnore left double feed sensorIgnore right double feed sensorImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersImprinter ink levelImprinter ink running lowImproves quality of high resolution ball-point pen textIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInitial endorser counter value.Ink lowInk remainingInk-jet printersInt test optionsInvalid argumentInverse ImageInverse image in B/W modeInverse image in B/W or halftone modeInvert endiannessIt is right and left reversingJPEGJPEG Image Compression with Q parameter, ‘0’ - no compressionJPEG compressionJPEG compression (yours application must be able to uncompress)Lamp colorLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off during scanLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLandscapeLegalLength Control Mode is a mode that the scanner reads up to the shorter length of actual paper or logical document length.Length control modeLens calibration in doc positionLet's see whether frontends can treat this rightLetterLevel of JPEG compression. 1 is small file, 7 is large file. 0 (default) is same as 4Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option ‘side’ can be used to determine correct image. This option should only be used with custom front-end software.Limit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Long Paper Mode is a mode that the scanner reads the image after it divides long paper by the length which is set in Document Size option.Long paper modeLoss of pixels per lineLowLow MemoryLow density printingLow sensivityManual feedManual feed modeManual feed selectedManual feed timeoutManual focus positionManual pre focusManually switching the lamp(s).Matrix 2x2Matrix 3x3Matrix 4x4Matrix 5x5Matrix multiplication of RGBMaxMaximum diameter of lone dots to remove from scanMaximum diameter of lone dots to remove from scan.MediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image (left/right flip)Mirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMirroringMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative colorNegative filmNegative film typeNegative grayNegative to smooth or positive to sharpen imageNegativesNo CorrectionNo detectionNo transparency correctionNoise reductionNoise removalNoneNormalNormal modeNormal speedNumber of bits per sample, typical values are 1 for “line-art†and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOMR or DFOMR or double feed detectedOffOff timerOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOne-pass scanners use only one color during gray or binary scanning, useful for colored paper or inkOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryOutlineOverscanPDF buttonPage heightPage loadedPage widthPaper is pulled partly into adfPaper protectionPaper sizePass-throughPerform outline extractionPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPower savingPredefined settingsPrepickPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorRIFROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflect output image horizontallyReflectiveRemove 2 pixel square noiseRemove 3 pixel square noiseRemove 4 pixel square noiseRemove 5 pixel square noiseRequest a preview-quality scan.Request backend to remove border from pages digitallyRequest driver to detect and correct 90 degree image rotationRequest driver to discard pages with low numbers of dark pixelsRequest driver to discard pages with low percentage of dark pixelsRequest driver to halt the paper feed instead of eject during a cancel.Request driver to remove border from pages digitallyRequest driver to remove border from pages digitally.Request driver to rotate pages by a fixed amountRequest driver to rotate skewed pages digitallyRequest driver to rotate skewed pages digitally.Request scanner to detect jams in the ADF caused by staplesRequest scanner to grab next page from ADFRequest scanner to predict jams in the ADFRequest scanner to predict jams in the ADF using improved sensorsRequest scanner to read pages quickly from ADF into internal memoryRequest scanner to reverse feed on paper jamRequest scanner to rotate and crop pages digitally.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Requires black background for scanningReset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readReverse image formatRotate image clockwiseSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner automatically detect image area and crop itScanner cover is openScanner detects paper lower edge. May confuse some frontends.Scanner detects paper sides. May reduce scanning speed.Scanner in power saving modeScanner mechanism locked for transportScanner modelScanner sensors and buttonsScanner shrinks image to fit scanned pageScanner will be stop when a paper have been skewedSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). “Default†is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the “graininess†of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, “Master†means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.Selects what blue radiance level should be considered “blackâ€.Selects what blue radiance level should be considered “full blueâ€.Selects what blue radiance level should be considered “whiteâ€.Selects what green radiance level should be considered “blackâ€.Selects what green radiance level should be considered “full greenâ€.Selects what green radiance level should be considered “whiteâ€.Selects what radiance level should be considered “blackâ€.Selects what radiance level should be considered “whiteâ€.Selects what red radiance level should be considered “blackâ€.Selects what red radiance level should be considered “full redâ€.Selects what red radiance level should be considered “whiteâ€.Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered “50 % blueâ€.Selects which radiance level should be considered “50 % grayâ€.Selects which radiance level should be considered “50 % greenâ€.Selects which radiance level should be considered “50 % redâ€.Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSeparationSet SDTC variance rate (sensitivity), 0 equals 127Set chroma of blueSet chroma of redSet color of background for scans. May conflict with overscan optionSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet paper position : true for landscape, false for portraitSet pixels equal to threshold to white instead of blackSet sharpening value.Set the double feed detector sensitivitySet the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the automatic threshold modeSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the lamp color (color dropout)Sets the manual feed modeSets the manual feed timeout in secondsSets the resolution of the scanned image.Sets the scan sourceSets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkew adjustmentSkew angleSkip warmup processSleep timerSlideSlidesSlowSlowerSlowestSmoothSmoothingSoftware automatic croppingSoftware blank skip percentageSoftware cropSoftware derotateSoftware deskewSoftware despeckle diameterSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Specify the calibration file to useSpeedup sensorStandardStaple detectionStart calibration process.Start calibration using special sheetStatus Code SimulationStopStop scanner when a paper have been skewedString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesTPU8x10Target operation typeTells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The lamp will be turned off during scan. The number of pixels that are wasted at the end of each line.The saturation level controls the amount of “blooming†that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold curve, from light to dark, but upper two may not be linearThreshold value for lineart modeThreshold whiteTime (in minutes) before a cached calibration expires. A value of 0 means cache is not used. A negative value means cache never expires.Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off.Time in minutes until the internal power supply switches to sleep modeToggle lamp of flatbedToggles the lamp of the flatbedTop edgeTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.Type of original to scanUTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse manual or automatic selection of focus point.Use non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVarianceVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press “SCAN†button (for MP150) or “COLOR†button (for other models). To cancel, press “GRAY†button.When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level followerWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomadfbayer_16bayer_64bluebusiness_cardbwchroma of bluechroma of redcolorcommand sequence errorcontinuouscrtdarkdefaultdiffusionerr_diffusionfbfilm scannerfit-to-pageflatbed scannergraygreenhalftonehalftone_32halftone_64hardware check errorhighinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorjpeg compressionlamp failurelamp not stabilizedlightlinierlowmediummedium not presentno additional sense informationnonenormaloffoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetredreselect failurerounded parameterscan head positioning errorsheetfed scannersinglesmoothtimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNuser_defwait_docwait_doc_hopper_upwait_keywebcamsane-backends-1.0.27/po/it.po0000664000175000017500000047033513110600537012624 00000000000000# Italian translation for SANE backend package # Copyright (C) SANE Project. # Luca Clemente, , 2003. # Giuseppe Sacco, , 2004-2007 msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.18\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-08-28 23:11+0200\n" "Last-Translator: Giuseppe Sacco \n" "Language-Team: italian translation project \n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Numero di opzioni" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometria" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Miglioramento" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Avanzato" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Anteprima" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Forza anteprima in bianco e nero" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Profondità in bit" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Modalità di scansione" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Velocità scanner" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Sorgente scanner" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Forza il backtracking" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "X in alto a sinistra" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Y in alto a sinistra" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "X in basso a destra" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Y in basso a destra" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Risoluzione della scansione" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Risoluzione X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Risoluzione Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, fuzzy, no-c-format msgid "Page height" msgstr "Contrasto" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Personalizzare la correzione gamma" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Intensità dell'immagine" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Intensità del rosso" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Intensità del verde" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Intensità del blu" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Brillantezza" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contrasto" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Grana" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Mezzi-toni" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Livello nero" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Livello bianco" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Livello di bianco sul rosso" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Livello di bianco sul verde" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Livello di bianco sul blu" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Ombreggiatura" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Ombreggiatura per il rosso" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Ombreggiatura per il verde" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Ombreggiatura per il blu" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Contrasto" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Contrasto per il rosso" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Contrasto per il verde" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Contrasto per il blu" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Tonalità" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturazione" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Nome file" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Dimensione del modello mezzi-toni" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Modello mezzi-toni" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Lega la risoluzione X e Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativo" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Qualità della calibrazione" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Raddoppia la risoluzione ottica" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Lega i canali RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Soglia" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Correzione gamma analogica" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Correzione gamma del rosso analogica" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Correzione gamma del verde analogica" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Correzione gamma del blu analogica" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Lega i valori gamma RGB" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Preriscaldamento lampada" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Cal. tempo di esposizione" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Cal. tempo di esposizione per il rosso" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Cal. tempo di esposizione per il verde" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Cal. tempo di esposizione per il blu" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Tempo di esposizione in scansione" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Tempo di esposizione in scansione per il rosso" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Tempo di esposizione in scansione per il verde" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Tempo di esposizione in scansione per il blu" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Determinare il tempo di esposizione" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Cal. potenza della lampada" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Potenza della lampada in scansione" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Determina la potenza della lampada in scansione" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lampada spenta in uscita" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Opzione che visualizza quante opzioni sono supportate da uno specifico " "dispositivo." #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Lista ridotta delle risoluzioni disponibili" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "Numero di opzioni" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Risoluzione hardware" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Richiede la qualità in anteprima di scansione." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Richiede che tutte le anteprime siano eseguite in bianco e nero. Nel " "caso in cui lo scanner sia a 3 passate ne verrà quindi effettuata una " "sola, invece in quelli ad una passata riduce la memoria e il tempo " "richiesti per l'anteprima." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Numero di bit per campione, il valore usuale è 1 per \"Binario\" e 8 per " "le scansioni ad alta risoluzione." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Seleziona la modalità di scansione (ad esempio binaria, monocromatica o " "colore)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Determina la velocità di scansione" #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "" "Seleziona la sorgente per la scansione (come ad esempio il vassoio)" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Verifica se il backtracking è stato impostato." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Posizione X in alto a sinistra dell'area di scansione." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Posizione Y in alto a sinistra dell'area di scansione." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Posizione X in basso a destra dell'area di scansione." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Posizione Y in basso a destra dell'area di scansione." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Determina la risoluzione di acquisizione dell'immagine." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "" "Determina la risoluzione orizzontale di acquisizione dell'immagine." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Determina la risoluzione verticale di acquisizione dell'immagine." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, fuzzy, no-c-format msgid "Specifies the height of the media." msgstr "Determina la risoluzione di acquisizione dell'immagine." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Determina se utilizzare per la correzione gamma dei valori predefiniti " "oppure quelli personalizzati dall'utente." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Tabella di correzione gamma. In modalità colore tale opzione influenza " "in modo simultaneo i 3 canali (rosso, verde, blu) ed è quindi una " "tabella gamma di intensità." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Tabella di correzione gamma per il colore rosso." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Tabella di correzione gamma per il colore verde." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Tabella di correzione gamma per il colore blu." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Controlla la brillantezza dell'immagine acquisita." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Controlla il contrasto dell'immagine acquisita." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Seleziona la \"granulosità\" dell'immagine acquisita: valori minori " "determinano immagini più nitide." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Determina se l'immagine acquisita deve essere a mezzi-toni (sfumata)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" "Imposta quale livello di luminosità debba essere considerato \"nero\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" "Imposta quale livello di luminosità debba essere considerato \"bianco\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Imposta quale livello di luminosità rossa debba essere considerato " "\"bianco\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Imposta quale livello di luminosità verde debba essere considerato " "\"bianco\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Imposta quale livello di luminosità blu debba essere considerato \"bianco" "\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Imposta quale livello di luminosità rossa debba essere considerato \"nero" "\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Imposta quale livello di luminosità verde debba essere considerato \"nero" "\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Imposta quale livello di luminosità blu debba essere considerato \"nero" "\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Imposta quale livello di luminosità rossa debba essere considerato " "\"rosso completo\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Imposta quale livello di luminosità verde debba essere considerato " "\"verde completo\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Imposta quale livello di luminosità blu debba essere considerato \"blu " "completo\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Controlla la tonalità (livello di blu) dell'immagine acquisita." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Il livello di saturazione determina la quantità di «fioritura» qualora " "l'immagine venga acquisita con una fotocamera. Valori maggiori " "determinano una fioritura maggiore." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Il nome del file contenente l'immagine da caricare." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Determina la dimensione del modello mezzi-toni (sfumatura) utilizzato " "con immagini a mezzi-toni." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Definisce il modello mezzi-toni (sfumatura) utilizzato con immagini a " "mezzi-toni." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Usa lo stesso valore per la risoluzione X e Y" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Inverte bianco e nero" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Esegue una calibrazione qualitativa sul bianco" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Utilizzo della lente per duplicare la risoluzione ottica" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Utilizza lo stesso valore per tutti i canali in modalità RGB" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Imposta la brillantezza minima corrispondente a un punto bianco" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Correzione gamma analogica" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Correzione gamma del rosso analogica" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Correzione gamma del verde analogica" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Correzione gamma del blu analogica" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Preriscaldamento della lampada prima della scansione" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Definisce il tempo di esposizione per la calibrazione" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Definisce il tempo di esposizione per la calibrazione del rosso" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Definisce il tempo di esposizione per la calibrazione del verde" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Definisce il tempo di esposizione per la calibrazione del blu" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Definisce il tempo di esposizione per la scansione" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Definisce il tempo di esposizione per la scansione del rosso" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Definisce il tempo di esposizione per la scansione del verde" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Definisce il tempo di esposizione per la scansione del blu" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Abilita la selezione del tempo di esposizione" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Determina l'intensità della lampada per la calibrazione" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Determina l'intensità della lampada in scansione" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Abilita la selezione dell'intensità della lampada" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Spegnere la lampada in uscita dal programma" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Risoluzione della scansione" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "Attendi il tasto" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "Attendi il tasto" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "Attendi il tasto" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Coperchio ADF aperto" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Colore" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Colore binario" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Mezzi-toni colore" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Grigio" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Mezzi toni" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Binario" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, fuzzy, no-c-format msgid "Operation not supported" msgstr "Mezzi-toni non supportati" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "Opzioni dell'alimentatore automatico" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "Opzioni dell'alimentatore automatico" #: backend/sane_strstatus.c:83 #, fuzzy, no-c-format msgid "Scanner cover is open" msgstr "Coperchio ADF aperto" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Predefiniti" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Imposta i valori predefiniti per i controlli del miglioramento" #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Calibrazione" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Calibrare lo scanner prima della prossima scansione" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Il dispositivo verrà calibrato prima della prossima scansione solamente " "se tale funzione sarrà abilitata, altrimenti la calibrazione verrà " "eseguita solamente alla prima scansione." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Esegue solamente la correzione delle ombre" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Se abilitata verrà eseguita solo la correzione delle ombre, qualora sia " "stata abilitata, mentre per guadagno, scarto e tempo di esposizione " "verranno utilizzati i valori predefiniti o quelli presenti nel file di " "configurazione" #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Stato del pulsante" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Numero di fotogrammi da acquisire" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Selezionare il numero di fotogrammi da acquisire" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Scansione Duplex" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "La scansione duplex è quella di entrambi i lati del documento" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Calibrare lo scanner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Forza la calibrazione dello scanner prima della scansione" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Scansione in scala di grigi" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Effettuare una scansione in scala di grigi invece che a colori" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Guadagno analogico" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Aumenta o diminuisce il guadagno analogico del sensore CCD" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Correzione gamma" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Selezionare la curva di correzione gamma" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Grezzo" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Colore ad alta qualità" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Nessuna correzione della trasparenza" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Correzione in base al tipo di pellicola" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Correzione in base al rapporto di trasparenza" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negativi" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Diapositive" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatico" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Velocità normale" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "Velocità normale dimezzata" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 della velocità normale" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "parametri arrotondati" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "sconosciuto" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "ADF inceppato" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "Coperchio ADF aperto" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "lampada guasta" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "errore nel posizionamento della testa di scansione" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "Errore nel controllo della CPU" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "Error nel controllo della RAM" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "Errore nel controllo della ROM" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "errore nei controlli hardware" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "guasto della lampada dell'adattatore per trasparenze" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" "errore durante il posizionamento della testa di scansione per " "l'adatattore per trasparenze" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "errore nella lunghezza della lista di parametri" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "codice di comando non valido" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "campo non valido in CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "LUN non supportato" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "campo non valido nella lista di parametri" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "errore nella sequenza di comandi" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "sono state specificate troppe finestre" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "supporto non presente" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "messaggio con bit IDENTIFY non valido" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "opzione non connesso" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "reset dell'alimentazione elettrica / reset del bus dei dispositivi" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parametro cambiato da un altro iniziatore" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "nessun altra informazione aggiuntiva sul «sense»" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "errore durante la reselezione" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "errore di parità SCSI" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "ricevuto un messaggio di errore per rilevamento di iniziatore" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "errore di messaggio non valido" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "errore di timeout" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "errore nel mascheramento della unità per la trasparenza" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lampada non stabilizzata" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "scanner da negativi" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "scanner piano" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Pellicola" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Imposta il tipo di pellicola: negativi o diapositive" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Tipo di pellicola negativa" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Seleziona il tipo di pellicola negativa" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Risoluzione hardware" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Mostra solo le risoluzioni hardware" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Fuoco" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Autofocus" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Abilita/disabilita la messa a fuoco automatica" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Autofocus unico" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Effettua l'autofocus una sola volta per ogni pellicola inserita" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Posizione di messa a fuoco manuale" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" "Imposta manualmente la posizione del sistema di messa a fuoco " "(normalmente alla posizione 128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Margini di scansione" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Altre impostazioni del colore" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Immagine riflessa" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Riflette l'immagine orizzontalmente" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Esposizione automatica" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Abilita/disabilita l'esposizione automatica" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Calibrazione immediata" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Esegue adesso la calibrazione" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Auto diagnostica" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Effettua i controlli automatici" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Reimposta scanner" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Reimposta lo scanner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Gestione del supporto" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Espelle la pellicola dopo ogni scansione" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Espelle automaticamente la pellicola dopo ogni scansione" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Espelle la pellicola all'uscita" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "Espelle automaticamente la pellicola alla chiusura del programma" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Espulsione della pellicola immediata" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Espelle la pellicola adesso" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Opzioni dell'alimentatore automatico" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Solo piano fisso" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "Disabilita l'alimentatore di fogli e usa solo il piano fisso" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Adattatore per trasparenze" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" "Abilita/disabilita l'adattatore per le trasparenze (FAU, «film adapter " "unit»)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Pellicola negativa" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Pellicola positiva o negativa" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Controllo della densità" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Imposta la modalità di controllo della densità" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Rapporto per trasparenze" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Seleziona tipo pellicola" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Seleziona il tipo di pellicola" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Piano fisso" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, fuzzy, no-c-format msgid "ADF Front" msgstr "Coperchio ADF aperto" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "ADF inceppato" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "ADF Duplex" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Stampa" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Fronte e retro" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Rosso" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Verde" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Blu" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Miglioramento" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Miglioramento" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Miglioramento" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Nessuno" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Solo fronte" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Fronte e retro" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Adattatore per trasparenze" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Caricatore automatico fogli" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Pellicola positiva" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Pellicola negativa" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Messa a fuoco sul piano di vetro" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Messa a fuoco 2,5mm sopra piano di vetro" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Mezzi Toni A (hard tone)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Mezzi Toni B (soft tone)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Mezzi Toni C (net screen)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Dither A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Dither B (4x4 Spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Dither C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Dither D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Tecnologia di miglioramento del testo" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Scarica il modello A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Scarica il modello B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Nessuna correzione" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Definito dall'utente" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Stampanti a impatto" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Stampanti termiche" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Stampanti a getto d'inchiostro" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Monitor CRT" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Default" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Stampa ad alta definizione" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Stampa a bassa definizione" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Stampa a contrasto elevato" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Definito dall'utente (gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Definito dall'utente (gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 verticale" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 orizzontale" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Massimo" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Modalità di scansione" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Seleziona i mezzi toni" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Esclusione" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Seleziona l'esclusione." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Seleziona la brillantezza." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Nitidezza" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Correzione del colore" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "Imposta la tabella di correzione dei colori per il dispositivo " "selezionato." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Coefficienti di correzione del colore" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Moltiplicazione matriciale dei valori RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Spostamento da verde a rosso" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Spostamento da verde a blu" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Spostamento da rosso a verde" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Spostamento da rosso a blu" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Spostamento da blu a verde" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Spostamento da blu a rosso" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Controlla il livello del verde" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Modula il rosso sulla base del livello del verde" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Modula il blu sulla base del livello del verde" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Modula il verde sulla base del livello del rosso" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Controlla il livello del rosso" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Modula il blu sulla base del livello del rosso" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Modula il verde sulla base del livello del blu" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Modula il rosso sulla base del livello del blu" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Controlla del livello del blu" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Effettua una riflessione dell'immagine lungo l'asse verticale" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Anteprima veloce" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Sezionamento automatico dell'area" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Lista ridotta delle risoluzioni disponibili" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Mostra la lista ridotta delle risoluzioni disponibili" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Zoom" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Definisce il fattore di zoom usato dallo scanner" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Formato rapido" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Dispositivi opzionali" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Espulsione" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Espelle il foglio dall'alimentatore automatico" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Espulsione automatica" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Espelle il documento dopo la sua scansione" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Modalità ADF" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Seleziona la modalità ADF (solo fronte/fronte-retro)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Cassetto" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Seleziona il cassetto per la scansione" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Seleziona la correzione gamma da una lista di dispositivi predefiniti, " "oppure dalla tabella personalizzata, con la quale verrà configurato lo " "scanner" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Posizione della messa a fuoco" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Seleziona la messa a fuoco sul piano di vetro o 2,5mm sopra lo stesso" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Attendi il tasto" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Dopo aver inviato il comando di scansione, attendere finché non viene " "premuto il tasto dello scanner per fare partire il processo di " "acquisizione." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Diapositiva positiva" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Diapositiva negativa" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Definito dall'utente" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Attivo" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Disattivo" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Sfumatura" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "Diffusione d'errore" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Livello bianco" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Livello nero" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "Condizionale" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Orizzontale" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Orizzontale" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Orizzontale" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Verticale" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Verticale" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Stampa" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Mezzi toni" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Effettua calibrazione" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Accentuazione dell'immagine" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Saturazione" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "" "Abilita la valutazione automatica della soglia per la scansione binaria." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Immagine riflessa" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Riflette l'immagine orizzontalmente." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Livello di bianco sul blu" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Controlla il livello del rosso" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Filtro colore" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Ammorbidimento" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Valore gamma" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Soglia" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Soglia" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Riduzione del rumore" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Nessuna correzione" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Nessuna correzione" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Coperchio ADF aperto" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Opzioni avanzate" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Nessuna correzione" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Esclusione" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Modalità di caricamento" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Durata spegnimento lampada" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Scarto sul blu" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Scarto sul verde" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Scarto sul verde" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Scarto sul blu" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Imposta lo scarto sul blu" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Scansione Duplex" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Opzioni avanzate" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Riduzione del rumore" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Da carta" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Da carta" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Da carta" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Da carta" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "Coperchio ADF aperto" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Messa a fuoco preliminare manuale" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Messa a fuoco preliminare manuale" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "errore nei controlli hardware" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Livello bianco" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Controllo della densità" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Controllo della densità" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Scansione Duplex" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extra" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Disattiva interpolazione" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "Quando si usano alte risoluzione con quella orizzontale minore della " "verticale, l'interpolazione orizzontale viene disabilitata." #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Filtro colore" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "Quando si usano i grigi o il binario questa opzione seleziona il colore " "usato." #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Calibrazione" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Definire la modalità di calibrazione" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Cache per la calibrazione" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Durata spegnimento lampada" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "La lampada verrà spenta allo scadere del tempo impostato (in minuti). Il " "valore 0 indica che la lampada non deve mai essere spenta." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Calibrazione granulosa" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" "Numero di minuti prima che la lampada venga spenta dopo la scansione" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "Attendi il tasto" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "Attendi il tasto" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Attendi il tasto" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Calibrazione granulosa" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Forza la calibrazione dello scanner prima della scansione" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Pulsanti" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Calibrazione" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Inizia la calibrazione." #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Calibrazione granulosa" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Cache per la calibrazione" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Adattatore per trasparenza" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Modalità a scala di grigi" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Seleziona il colore di scansione da usare per la scala di grigi " "(predefinito: verde)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Opzioni per il debugging" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Preriscaldamento automatico" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Preriscalda fino a che la luminisità della lampada sia costante invece " "di attendere 60 secondi." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Scansione completa" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Effettua la scansione su tutta l'area possibile, compresa la striscia di " "calibrazione. Fare attenzione a non selezionare l'altezza completa. Da " "usare solo per effettuare test." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Calibrazione granulosa" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Definisce guadagno e scarto per la scansione automatica. Se questa " "opzione è disabilitata allora saranno presenti nel frontend alcune " "opzioni per la parametrizzazione manuale analogica. Questa opzione è " "attiva in maniera predefinita. Da usare solo per effettuare test." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Calibrazione granulosa solo per la prima scansione" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "La calibrazione granulosa è effettuata solo durante la prima scansione. " "Funziona con la maggior parte degli scanner e può fare risparmiare " "parecchio tempo. Disabilitarla se la brillantezza è diversa per ciascuna " "delle immagini da acquisire. Da usare solo per effettuare test." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Linee del backtrack" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Numero di linee che di cui fare arretrare il cursore della scansione " "durante il backtrack. Questo capita quando lo scanner è più veloce del " "computer durante la ricezione dei dati. Valori bassi permettono una " "scansione più veloce, ma aumentano il rischio di linee mancanti." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Valore gamma" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Imposta il valore gamma per tutti i canali." #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "Geometria" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, fuzzy, no-c-format msgid "Scan Mode Group" msgstr "Modalità di scansione" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Diapositiva" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Modalità di scansione" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "Correzione gamma analogica" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "Correzione gamma" #: backend/hp3900_sane.c:1451 #, fuzzy, no-c-format msgid "Disable white shading correction" msgstr "Esegue solamente la correzione delle ombre" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "Scala di grigi" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "Reimposta scanner" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Ignora la calibrazione" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Nome file" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, fuzzy, no-c-format msgid "Unknown" msgstr "sconosciuto" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "Reimposta scanner" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "Sorgente scanner" #: backend/hp3900_sane.c:1584 #, fuzzy, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Selezionare il numero di fotogrammi da acquisire" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Opzioni di aggiornamento" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, fuzzy, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Queste opzioni riflettono lo stato dei pulsanti dello scanner." #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Immagine" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Varie" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "Scarto X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Posizione interna X dell'area di scansione." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "Scarto Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Posizione interna Y dell'area di scansione." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Stato della lampada" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Accendi o spegni la lampada" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Calibrare i livelli del bianco e nero" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, fuzzy, no-c-format msgid "TMA Slides" msgstr "Diapositive" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Negativi" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "Colore a 48 bit" #: backend/hp5590.c:95 #, fuzzy, no-c-format msgid "Extend lamp timeout" msgstr "Timeout della lampada" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, fuzzy, no-c-format msgid "Wait for button" msgstr "Attendi il tasto" #: backend/hp5590.c:99 #, fuzzy, no-c-format msgid "Waits for button before scanning" msgstr "Preriscaldamento della lampada prima della scansione" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Opzioni avanzate" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Granuloso" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "A grana fine" # Bayer è il nome della persona che ha inventato questa matrice per il # dithering. #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Personalizzato" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automatico" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Passante" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "Grigio NTSC" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA Grigio" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Lento" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normale" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Veloce" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Extra veloce" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-pixel" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-pixel" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-pixel" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Stampa" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Pellicola" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Condizionale" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Esperimento" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Nitidezza" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Imposta il valore di nitidezza." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Soglia automatica" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Abilita la valutazione automatica della soglia per la scansione binaria." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Seleziona il filtro per l'ammorbidimento (smoothing)." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Espelle il supporto dopo la scansione" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Estrae il supporto originale dopo aver effettuato la scansione." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Cambia il documento" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Cambia il documento." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Espulsione" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Espelle il documento." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Inizia la calibrazione." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Supporto" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Imposta il tipo di supporto." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Tempo di esposizione" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Un maggiore tempo di esposizione permette allo scanner di raccogliere " "più luce. I valori suggeriti sono 175% per le stampe, 150% per le " "normali diapositive e \"Negativo\" per le pellicole. Per immagini scure " "(sottoesposte) si può aumentare questo valore." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Matrice del colore" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Imposta la matrice del colore." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Matrice personalizzata del colore." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Matrice del colore mono" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Matrice personalizzata del colore per scansioni a scale di grigi." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Specchio orizzontale" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Riflette l'immagine orizzontalmente." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Specchio verticale" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Riflette l'immagine verticalmente." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Opzioni di aggiornamento" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Opzioni di aggiornamento." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "uscita a 8 bit" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "Usa internamente più di 8 bit, ma produce solo 8 bit." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Attesa del bottone frontale" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" "Viene attesa la pressione del bottone frontale prima di effettuare la " "scansione." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Spegnimento della lampada" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Spegne la lampada dello scanner." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Dimensione del foglio" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Separazione automatica" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 orizzontale" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "Imposta la modalità di controllo della densità" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Messa a fuoco preliminare manuale" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Messa a fuoco preliminare manuale" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Attiva la scansione fronte-retro" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Dimensione del foglio nel caricatore automatico" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Mezzi toni" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Colore" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Condizionale" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Disattivo" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" # Bayer è il nome della persona che ha inventato questa matrice per il # dithering. #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" # Bayer è il nome della persona che ha inventato questa matrice per il # dithering. #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Mezzi toni" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Mezzi toni" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Diffusione d'errore" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normale" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Contrasto" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "scanner da negativi" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Da carta" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Default" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Morbido" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Lento" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Medio" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Rosso" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Verde" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Sorgente scanner" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Modalità di caricamento" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Selezionare la modalità di caricamento" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Abilita/disabilita la messa a fuoco automatica" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Imposta la modalità di controllo della densità" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Selezionare la modalità di caricamento" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Selezionare la modalità di caricamento" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Soglia automatica" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Brillantezza, contrasto, livello del bianco, correzione gamma, riduzione " "del rumore e accentuazione dell'immagine vengono determinati " "automaticamente" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Riduzione del rumore" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Riduce il rumore dei punti isolati" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Accentuazione dell'immagine" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Imposta l'accentuazione dell'immagine" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Lampada accesa" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Accendi o spegni la lampada" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Riflette l'immagine verticalmente." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Correzione gamma" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Stampa ad alta definizione" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Stampa a bassa definizione" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Diffusione d'errore" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Nessuna correzione" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normale" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Miglioramento" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Soglia automatica" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Soglia automatica" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Determina l'ordine delle immagini" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Ombreggiatura per il blu" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Spostamento da rosso a blu" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamante" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 grana grossa" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 grana fine" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 linea verticale" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Guadagno" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Regolazione del guadagno sui canali di colore" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Guadagno sul grigio" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Imposta il guadagno sul canale grigio" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Guadagno sul rosso" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Imposta il guadagno sul canale rosso" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Guadagno sul verde" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Imposta il guadagno sul canale verde" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Guadagno sul blu" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Imposta il guadagno sul canale blu" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Dither Bayer 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Dither Bayer 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Halftone Dot 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Halftone Dot 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Diffusione d'errore" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Modo 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Modo 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Modo 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "Da bastoncino bianco" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Morbido" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Basso" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Medio" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Alto" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Pagina singola" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Tutte le pagine" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "Scanner con alimentatore automatico dei fogli" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Scala di grigi a 4 bit" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Scala di grigi a 8 bit" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Ombre, toni medi, contrasto, tempo di esposizione" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Opzioni speciali" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Bilanciamento del colore" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Disattiva backtracking" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Se abilitato lo scanner non esegue il backtracking" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Commuta lo stato della lampada dello scanner" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Commuta lo stato della lampada dello scanner (accesa/spenta)" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Calibrazione automatica" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Se abilitato la calibrazione del colore viene eseguita automaticamente " "prima della scansione" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Utilizza l'adattatore per diapositive" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Questa opzione spegne la lampada del piano durante la scansione" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Qualità di scansione" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Massima qualità/Bassa velocità" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Scansione rapida" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Massima velocità/Bassa qualità" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Determinazione automatica della soglia" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Se abilitato viene determinato in maniera automatica il valore ottimale " "della soglia." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Selezionare la modalità di correzione gamma." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Fissa il valore gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Utilizza lo stesso valore di correzione gamma per tutti i canali." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Scalare gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Selezionare il valore per la correzione gamma scalare." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Valore gamma per il canale rosso" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Selezionare il valore per la correzione gamma (canale rosso)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Valore gamma per il canale verde" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Selezionare il valore per la correzione gamma (canale verde)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Valore gamma per il canale blu" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Selezionare il valore per la correzione gamma (canale blu)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Canale" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Selezionare la banda di colore, \"Master\" significa che tutti i colori " "saranno influenzati." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Mezzi toni" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Imposta il livello di luminosità da considerare \"50% grigio\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Mezzi toni rossi" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Imposta il livello di luminosità da considerare \"50 % rosso\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Mezzi toni verdi" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Imposta il livello di luminosità da considerare \"50 % verde\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Mezzi toni blu" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Selezionare il livello di luminosità da considerare \"50 % blu\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Bilanciamento del rosso" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" "Fattore di bilanciamento per il rosso. 100% equivale a nessuna " "correzione." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Bilanciamento del verde" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" "Fattore di bilanciamento per il verde. 100% equivale a nessuna " "correzione." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Bilanciamento del blu" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" "Fattore di bilanciamento per il blu. 100% equivale a nessuna correzione." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Bilanciamento (valori preimpostati)" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Resetta i valori di bilanciamento ai valori preimpostati" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Lentissimo" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Più lento" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Più veloce" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Velocissimo" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 di massima" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normale" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 preciso" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 molto preciso" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normale" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 di massima" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 preciso" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 di massima" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normale" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 preciso" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normale" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normale" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 personalizzato" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 personalizzato" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 personalizzato" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 personalizzato" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 personalizzato" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 personalizzato" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Scala di grigi rapido" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Scansione rapida con scala di grigi (bassa qualità)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Richiede che tutte le anteprime siano fatte nella modalità più veloce " "possibile (a bassa qualità). Questa potrebbe essere senza i colori o a " "bassa risoluzione." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Durata in minuti dello spegnimento della lampada." #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Imposta il ritardo (in minuti) dopo il quale spegnere la lampada." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Spegne la lampada" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Spegne subito la lampada." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Luminosità del rosso" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Controlla la luminosità del canale rosso dell'immagine acquisita." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Luminosità del verde" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Controlla la luminosità del canale verde dell'immagine acquisita." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Luminosità del blu" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Controlla la luminosità del canale blu dell'immagine acquisita." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contrasto canale rosso" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Controlla il contrasto del canale rosso dell'immagine acquisita." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contrasto canale verde" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Controlla il contrasto del canale verde dell'immagine acquisita." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contrasto canale blu" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Controlla il contrasto del canale blu dell'immagine acquisita." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Colore a 48 bit" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Colore a 24 bit" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Grigio a 16 bit" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Grigio a 8 bit" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Riflesso" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Pellicola positiva" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Preriscalda fino a che la luminisità della lampada sia costante invece " "di attendere 40 secondi." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Pellicola negativa" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negativo" #: backend/pixma.c:396 #, fuzzy, no-c-format msgid "48 bits color" msgstr "Colore ad alta qualità" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Scansione controllata da pulsante" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Quando abilitato, l'acquisizione non partirà immediatamente. Per " "procedere premere il pulsante \"SCAN\" (per ML150) oppure \"COLOR\" (per " "altri modelli). Per annullare premere il pulsante \"GRAY\"." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Aggiorna lo stato del pulsante" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Pulsante 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Pulsante 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Trasparenze" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Impostazioni-dispositivo" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Pulsante lampada" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Accensione manuale della/e lampada/e." #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Calibrazione granulosa" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Cache per la calibrazione" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Abilita o disabilita la cache per la calibrazione." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Effettua calibrazione" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Sensore di accelerazione" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Abilita o disabilita il movimento del sensore di accelerazione." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Durata del preriscaldamento" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Durata in secondi del preriscaldamento della lampada." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Durata spegnimento lampada" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Durata in secondi dello spegnimento della lampada." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Frontend analogico" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Valore del guadagno sul rosso per AFE (Analog FrontEnd)" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Scarto sul rosso" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Valore dello scarto sul rosso per AFE (Analog FrontEnd)" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Valore del guadagno sul verde per AFE (Analog FrontEnd)" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Valore dello scarto sul verde per AFE (Analog FrontEnd)" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Valore del guadagno sul blu per AFE (Analog FrontEnd)" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Valore dello scarto sul blu per AFE (Analog FrontEnd)" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Lampada rossa spenta" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Imposta il parametro spegnimento della lampada rossa" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Lampada verde spenta" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Imposta il parametro spegnimento lampada verde" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Lampada blu spenta" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Imposta il parametro spegnimento lampada blu" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Queste opzioni riflettono lo stato dei pulsanti dello scanner." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Colore a 36 bit" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Mappa dither 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Mappa dither 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Aleatorizzato" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Selezione della sorgente" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Miglioramento dell'immagine" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Rendi grigio" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Caricare l'immagine con scala di grigi" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Simulazione dell'acquisizione in 3 passate" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simula l'acquisizione in 3 passate e ritorna 3 diverse immagini. Per " "primo il verde, poi il blue e poi il rosso." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Simulazione di uno scanner manuale" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simula l'acquisizione mediante uno scanner manuale; questi scanner " "spesso non conoscono l'altezza dell'immagine a priori e restituiscono " "quindi il valore -1. Impostando questa opzione sarà possibile " "verificare se il frontend funziona correttamente." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Imposta i valori predefiniti per il miglioramento della qualità " "dell'immagine (brillantezza e contrasto)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Opzione per il test di sola lettura" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Verifica se in questo caso il frontend funziona correttamente" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Tabelle gamma" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Simulazione del valore di ritorno" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Non forzare il valore di ritorno" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Non obbliga l'interfaccia a fornire un valore di ritorno." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Ritorna SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Obbliga il programma a fornire il valore di ritorno SANE_STATUS_EOF dopo " "che sia stata chiamata la funzione sane_read()." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Ritorna SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Obbliga il programma a fornire il valore di ritorno SANE_STATUS_JAMMED " "dopo che sia stata chiamata la funzione sane_read()." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Ritorna SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Obbliga il programma a fornire il valore di ritorno SANE_STATUS_NO_DOCS " "dopo che sia stata chiamata la funzione sane_read()." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Ritorna SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Obbliga il programma a fornire il valore di ritorno " "SANE_STATUS_COVER_OPEN dopo che sia stata chiamata la funzione " "sane_read()." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Ritorna SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Obbliga il programma a fornire il valore di ritorno SANE_STATUS_IO_ERROR " "dopo che sia stata chiamata la funzione sane_read()." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Ritorna SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Obbliga il programma a fornire il valore di ritorno SANE_STATUS_NO_MEM " "dopo che sia stata chiamata la funzione sane_read()." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Ritorna SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Obbliga il programma a fornire il valore di ritorno " "SANE_STATUS_ACCESS_DENIED dopo che sia stata chiamata la funzione " "sane_read()." #: backend/rts8891.c:2809 #, fuzzy, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Queste opzioni riflettono lo stato dei pulsanti dello scanner." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lampada accesa" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Accendere la lampada" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lampada spenta" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Spegnere la lampada" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Timeout della lampada" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" "Numero di minuti prima che la lampada venga spenta dopo la scansione" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Valore soglia per modalità binaria" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Alimentatore automatico dei fogli" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 pollici (~15x10 cm)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 pollici (~20x25 cm)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 pollici (~21x28 cm)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Mezzi-toni non supportati" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Numero di linee da trasferire per ogni lettura SCSI. Cambiando tale " "parametro è possibile modulare la velocità alla quale i dati sono letti " "durante le scansioni. Un valore troppo basso produce un funzionamento " "\"a scatti\" dello scanner, un valore troppo grande può bloccare le " "interfacce X-Window dal rispondere agli eventi X e bloccare il sistema." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Espelle il documento dopo la sua scansione" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Anteprima" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Determina come eseguire l'anteprima: un'anteprima con scala di grigi " "fornisce solitamente il miglior rapporto velocità/qualità." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Valori predefiniti" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Fornisce le aree di scansione standard per fotografie, pagine stampate, " "etc." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "scanner piano" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Fuoco" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Autofocus" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Posizione della messa a fuoco" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Posizione della messa a fuoco" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Numero di linee colore per ciclo di lettura" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Numero di linee in scala di grigi per ciclo di lettura" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "webcam" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Colore RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Colore RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Colore RGB TESTO" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Nero pieno" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Bianco pieno" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Modello di colori" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Griglia" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Prima scelta" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Seconda scelta" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Questa è una terza scelta molto lunga. Il programma potrebbe riuscire a " "visualizzarla." #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Simulazione di uno scanner manuale" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulazione di acquisizione mediante uno scanner manuale; questi scanner " "spesso non conoscono l'altezza dell'immagine a priori restituendo quindi " "il valore -1. Impostando tale opzione sarà possibile verificare se il " "frontend funziona correttamente. Questa opzione imposta inoltre la " "larghezza al valore fisso di 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Simulazione di una scansione a 3 passate" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simulazione di uno scanner a 3 passate. In modalità colore verranno " "trasmesse 3 immagini." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Determina l'ordine delle immagini" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Determina l'ordine delle immagini in una scansione a 3 passate" #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Se viene selezionato il caricatore automatico di fogli, questo sarà " "vuoto dopo 10 scansioni." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Opzioni speciali" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Seleziona l'immagine di prova" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Seleziona il tipo di immagine di test tra quelle disponibili:\n" "Nero pieno: riempie l'intera area di nero.\n" "Bianco pieno: riempie l'intera area di bianco.\n" "Modello di colori: disegna vari colori di test dipendentemente dalla " "modalità scelta\n" "Griglia: disegna una griglia di quadrati bianchi e neri aventi larghezza " "e altezza uguali a 10 mm." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Inversione della «endianness»" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Inverte i due byte di dati nella modalità a 16 bit. Questa opzione può " "essere utilizzata per verificare la modalità a 16 bit dei frontend, vale " "a dire per vedere se il frontend utilizza correttamente l'«endianness»." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Limiti in lettura" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "Limita i dati passati ad ogni chiamata della funzione sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Dimensione del limite in lettura" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "La quantità (massima) di dati passati ad ogni chiamata della funzione " "sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Ritardo in lettura" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Ritarda il trasferimento dei dati" #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Durata del ritardo in lettura" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "Quanto attendere dopo avere tarsferito ogni singolo pacchetto di dati" #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Valore di ritorno della funzione sane_read()" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Seleziona il valore di ritorno della funzione sane_read(). \"Default\" è " "il corretto funzionamento del processo di scansione. Tutti gli altri " "valori di ritorno sono utilizzati per testare come vengono gestiti dal " "frontend." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Perdita di pixel per linea" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Numero di pixel sprecati alla fine di ogni linea" #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Parametri «fuzzy»" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Restituisce dei valori «fuzzy» per il numero di linee e quello di byte " "per linea se sane_parameters() è chiamata prima di sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Uso dell'I/O asincrono" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Usa la modalità non bloccante di I/O per sane_read() se il frontend la " "supporta." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Proponi «select file descriptor»" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Propone «select file descriptor» per verificare se sane_read() " "restituisce dati." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Abilita le opzioni di test" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Abilita le varie opzioni di test. Usabile per verificare la capacità dei " "frontend di vedere e modificare tutti i tipi di opzioni di SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Stampa le opzioni" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Stampa un elenco di tutte le opzioni." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Opzioni booleane di test" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) bool, soft select soft detect" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) opzione booleana di test che ha capacità di soft select e soft " "detect (e oltre). Si tratta di una normale opzione booleana." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) bool, hard select soft detect" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) opzione booleana test che ha una capacità di hard select e soft " "detect e oltre. Vale a dire che questa opzione non può essere impostata " "dal frontend, ma dall'utente (come, ad esempio, premendo un pulsante sul " "dispositivo)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) bool, hard select" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) opzione booleana di test che ha capacità di hard select (e oltre). " "Vale a dire che non può essere impostata dal fronted, ma dall'utente " "(come, ad esempio, la pressione di un pulsante sul dispositivo) e non " "può essere letta dal frontend." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) bool, soft detect" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) opzione booleana di test che ha la capacità di soft detect (e " "oltre). Vale a dire che l'opzione è di sola lettura." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) bool, soft select soft detect emulazione" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "opzione di test booleana che ha la capacità di soft select, soft detect " "e emulazione (e oltre)." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) bool, soft select soft detect auto" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) opzione di test booleana che ha la capacità soft select, soft " "detect e automatica (e oltre). Questa opzione può essere automaticamente " "impostata dal backend." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Opzioni intere di test" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) intero" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) opzione intera di test senza unità di misura e vincoli." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) intero con intervallo" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) opzione intera di test che ha l'unità pixel e un vincolo di " "intervallo. Il minimo è 4, il massimo è 192, il passo è 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) intero con valori da una lista" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) opzione intera con il bit come unità e il vincolo di valori da una " "lista." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) array di interi" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) opzione intera di test con il mm come unità e un array senza " "limiti." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) array di interi con vincolo" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) opzione intera di test con unità punti per pollice e un array con " "un vincolo di intervallo. Il minimo è 4, il massimo 192 e il passo 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) array di interi con lista di valori" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) opzione intera di test con unità percentuale e un array con una " "lista di valori come vincolo." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Opzioni di test a virgola fissa" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) virgola fissa" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "Opzione a virgola fissa di test senza unità e vincoli." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) virgola fissa con vincolo di intervallo" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) opzione a virgola fissa di test con microsecondo come unità e " "vincolo di intervallo. Il minimo è -42,17, il massimo è 32767,9999 e il " "passo è 2,0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) virgola fissa con lista di valori" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) opzione a virgola fissa di test senza unità e con il vincolo lista " "di valori." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Opzioni stringa di test" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) stringa" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) opzione stringa di test senza vincoli." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) stringa con lista di valori" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) opzione stringa di test con vincolo lista di valori." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) stringa con lunga lista di valori" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) opzione stringa di test con vincolo lista di valori. Contiene più " "elementi..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Opzioni pulsanti di test" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) pulsante" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) opzione pulsante di test. Stampa un testo..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Colore a 36 bit" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Usa la composizione di immagini" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Bianco e nero (binario)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Bianco e nero (mezzi-toni sfumato)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Scala di grigi" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Colore RGB (singola passata)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignora la calibrazione" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Disabilita la messa a fuoco preliminare" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Non calibrare la messa a fuoco" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Messa a fuoco preliminare manuale" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Fissa la posizione di messa a fuoco" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Calibrazione della lente sul documento" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "" "Calibrazione della messa a fuoco della lente nella posizione del " "documento" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Messa a fuoco sul piano di vetro" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Messa a fuoco sul piano di vetro invece che 0,6mm sopra il piano" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Modalità di calibrazione" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Definire la modalità di calibrazione" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Commuta lo stato della lampada" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "Adattatore per trasparenze acceso" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Accendere/spegnere l'adattatore per trasparenze" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Scarto" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Impostazione dello scarto sui canali del colore" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Scarto sul grigio" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Imposta lo scarto sul grigio" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Imposta lo scarto sul rosso" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Imposta lo scarto sul verde" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Imposta lo scarto sul blu" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Anteprima" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "problema non analizzato (classe SCSI sconosciuta)" #~ msgid "Grayscale" #~ msgstr "Scala di grigi" #~ msgid "Binary" #~ msgstr "Binario" #, fuzzy #~ msgid "Display a shortened resolution list" #~ msgstr "Mostra la lista ridotta delle risoluzioni disponibili" #~ msgid "Black & White" #~ msgstr "Bianco e nero" sane-backends-1.0.27/po/ru.gmo0000664000175000017500000021406613110600540012771 00000000000000Þ•Pœ%1 ‘1ž1 ¦1 ±1 ¼1 Ç1Ò1 Ú1 å1ð1 ù1 2 22 #2 .2 92 D2Q2 Y2 g2s2 …2 2›2 ¤2 ¯2Ò½23 “3  3¬3°3!¹3Û3!û3 4>4 ^44ˆ4s™4 5 5#555M5`5q5 ‰5!ª5Ì5ì5ñ56 6 "6,6!F6h6}6‘6_¢67=7>P7<7Ì7'Ð7ø788 +8 68 @8L8 Q8^8 n8x8 ‡8 •8¡8³8%Â8è8%÷8 9 (959I9Q9T9 X9e9x9”9±9Ì9 Þ9è9ú9%: ;:G:^:u:†:—:§:¯:¶:&É:Äð:µ;»;Ä; Ó; á; î; ø;< <<<<[<l< Š<˜< <¨<°< Æ<Ò<Û<ñ<==1=F=6Y=.=B¿=C>AF>,ˆ>@µ>Aö>?8?(x?¡?(¨?Ñ?æ?ø?@ @)!@"K@$n@*“@#¾@(â@! A-A#KAoAŒA ¬AÍAIìA,6B'cB0‹BD¼BCC&C8CJCZCxC/C%¯CÕCôC D1$DVDfD€D“D¦D ­DE¹DÿDEE:E#UE?yE!¹E ÛEüEF+’F ¾FÊF ÚF åF óFþFG G G &G0G7G ?GKG TG ^GiGnG G‹GžG±G¹GÑGàGïGH%H AHLH]H oHyHŠHH•H ¦H³H ÄH)ÐH*úH(%I›NIêIóI øIJ JJ%J+J3JDJUJdJ jJxJ ‰J”J¤J ³JÀJÙJÞJçJþJK-K=KMK^K tKK–K®KÆKËKâKøKL 8LBLULiL{L •LI LêL[îLEJM4M¹ÅM€NOOO+O:OJO*^O5‰O¿OÐOáOóOüO PP3P ;P GPTP mPxPCPÃPËPèPQQQ*QJQgQkQqQxQ€Q‘Q£Q³Q ÅQÒQíQRR (R6R=RDRKR&]R*„R ¯R¹RÂR ËR ÙRçR÷RüRXSÞ\S;T]MT«UÇUËUÒUÕUÞUþU V V%)V OV]VqV yV†VŒV ©VM·VW W &W 3W =W HWSWMiW·W »WÇWÖW ßW íW úWX#XÖCX|Y—Y ±Y ¼YÉYÛYîY ÿY ZZ8ZUZ'pZ˜Z ªZ´Z ÄZ ÐZxÛZ T[a[.t[£[#¼[gà\H]:`];›]9×],^%>^d^F|^*Ã^"î^‡_™_'¯_<×_4`>I`Bˆ`>Ë`? aDJa?a9Ïa9 b=Cb@b=ÂbBc>Cc>‚c?Ác=d<?dD|d,Ádîdee'e1?eqe;eÌeßeïeff6fOfgff’f¨f>Àf?ÿf?gDUg%šg4Àgõg) hX7h2hÌÃhi—i§i¸i)Çi ñi üijj,j@jSjejxj Žjœj³jü»jиkp‰lKúlFmYm_mdmkmsm zm „m mœm­m½mÍmèmÿmn(nEnG^n'¦nuÎn=DoŒ‚opS p7tp;¬pèpþp qq5q Uq!`q ‚q!q ¯q¼qÑq ãq ñqr(r=r]rdrkr|r”r´rÃr.ÓrsCs\s(ssœsA°s.òs&!tHt ftstŒt¥t®t¾t)Ît`øt`Yu ºuÆu âuîu vv'v=v Qv^vgv ov|vv‘vÒ¢vuxˆx¡x¸xÑxèxy y1yHy[yty…yœy¯yÂyÙy#òyz3zIz']z…z–z­zÀzÙzÁ÷z¹|¼|Ð|â|é|] }]g}]Å}a#~]…~aã~E/`þ€%§€,Í€2ú€0-0^2FÂJ ‚JT‚Ÿ‚'º‚Aâ‚$ƒAƒB\ƒBŸƒ1âƒ'„+<„áh„J…†b…Šé…Št† ÿ†T ‡_‡@v‡2·‡ê‡ˆˆ ;ˆFˆ`ˆ|ˆ'šˆ*ˆíˆ2 ‰0>‰fo‰0Ö‰fŠnŠ}Š7Š ÕŠâŠåŠìŠ2‹F:‹J‹JÌ‹4ŒLŒ#aŒO…ŒFÕŒ<1>n­"Íð Ž Ž!(Ž]JŽÒ¨Ž{Š%œ!Âä‘‘*‘B‘C`‘C¤‘è‘<’E’c’u’‡’=™’×’æ’4“86“8o“.¨“2ד2 ”l=”Tª”lÿ”pl•pÝ•`N–x¯–|(—|¥—e"˜ ˆ˜u©˜@™!`™‚™š™,²™Yß™]9šL—š]äšaB›]¤›aœPdœNµœRRWVªVž³Xž“ Ÿ= ŸkÞŸ§J 'ò +¡<F¡!ƒ¡¥¡GÅ¡ ¢P¢_o¢MÏ¢&£/D£Xt£Í£<ë£!(¤!J¤l¤3‡¤³»¤=o¥­¥C¼¥W¦BX¦œ›¦;8§9t§4®§$ã§g©p©ƒ©¡©¸©Ô©ì© ª/ª>Dª'ƒª«ªºªÔªìª« « )«:6«q«6‹«B«¬(¬%C¬i¬3†¬cº¬\­{­­<¬­%é­#®3® D®O®m®‡®¥®TÁ®X¯Xo¯ȯå°þ°±.2±a±±˜±$°±&Õ±$ü±.!²P²_²}²!²+¿².ë²!³D<³ ³#Œ³/°³/à³$´$5´$Z´"´3¢´Ö´Qç´.9µ.hµ—µ6¦µ.ݵM ¶GZ¶¢¶&µ¶*ܶ*·52·h·|ƒ·¸ ¸†¨¸X/¹sˆ¹'üº-$¼R¼5i¼5Ÿ¼1Õ¼#½s+½eŸ½!¾>'¾2f¾™¾1·¾*é¾>¿S¿o¿*¿?¸¿!ø¿À~!À ÀF³À'úÀ "Á./ÁB^Á/¡Á)ÑÁûÁÂÂ*Â"9Â&\Â&ƒÂ/ªÂ+ÚÂHÃDOÃ;”Ã+ÐÃüà Ä Ä )Ä46ÄQkÄ]½ÄÅ6Å?ÅNÅ]ÅwÅ —ŤÅÇ·ÅÆ)‚Èg¬ÈAÌVÌ_ÌpÌwÌA‘Ì5ÓÌ Í!#Í[EÍ¡Í8°Í/éÍ>ÎXÎ@mÎ'®Î³ÖÎ%ŠÏ1°ÏâÏþÏ$Ð6ÐBPв“ÐFÑUÑsÑ!“Ñ+µÑ.áÑ!ÒX2Òz‹Ò½Ó%ÄÔ3êÕÖ7Ö*UÖ.€Ö.¯Ö#ÞÖ2×F5×J|×JÇ×rØ4…Ø#ºØ-ÞØ) Ù)6Ù`ÙtÚ@ŽÚfÏÚ<6ÛTsÛÿÈÝ8ÈÞsßwußwíßZeàhÀà )áˆJá;Óá:âòJâ"=ãR`㉳ã¢=äàäšpå æ“™æ¢-ç‘Ðç„bè‚çè“jé¢þé‘¡ê¡3ë‰Õë‰_ìéìwíÀî¨Æîuoï0åï2ðAIð0‹ðq¼ðJ.ñxyñ-òñ' òEHòEŽòEÔòEóI`óIªó.ôóI#ôImô¡·ôŽYõ2èõˆöO¤ö}ôöPr÷`Ã÷Æ$øyëø‰eùïú,û05û0fûY—ûñûü+ü+Cü+oü/›ü+Ëü/÷ü2'ýZý-xý¦ýÁýÞÿï|‹l(ø !,=Pnƒš¸)Ô)þ)(1R,„5±:ç/"4R‚‡l Åwg= ¥'±„ÙZ^ †¹ :@ :{  ¶ GÁ G 0Q f‚ 0é f  – "® ,Ñ Iþ ,H *u =  Þ ó $G+Hs#¼&à>DF~‹> jIG´»üz¸37Á3ù?-?m­*Æ*ñwÀ”ÀUE0&v;Ù/õ3%3Y©ÃËç!ö¸ïªP8r•ç«õPœLV¿ Il:,¸ôÁ±Cþ·góÄÉâ$Ûá‚2ú’Éñ@+Æ3k6qvédì%«Ã@ò—2kùué D˜·º4è¦F0N:XôöÄi.ˆÂ= `ö‘_–e…m¹øB1y U"Àã ¬Ó?ÒǤJ× <!C™âG’^I µ³&+ñͰ¥AE Ë5Ë6f}3ä ›£.?Å;Ð!-U†uÒÈ‹?^DcJªÚMÖÚQG ®BÕ>4³î‘d}”Ü%‡ŸYú'á oÔ_´ßµ¶09> *]§W[€Ù€„(0¯1{½RÿOz9°óE*Q®WãÏ()¶Š I 5êîýTO‡a6“Ôàr8ƒ7 ­(M“h—Ñ¡NMÛ²x;vά ȉ ¨]~Hšþs/ÝÎÍå¾'ðü<¼:ë"ìPNŒä•œCwæ§3åR»~[f±¦‚¢ÆA`9‹t†*,¨Žƒ5ü&ùû1)YpZ–„÷Ã'oòÊa<n‰ûÏj|Ê$mÕb$Ð¥/#ZÌ.Hs&ëg=Ÿ7!+½ÜK# Fl›SD ÀÁÅy™¤àAÞTtš×>ŽSqKß,h-ç"z/ÝÙKceÞýÑ8EØw-©í7žØ˜´GF”LÓbn©%\æH2jV#¼JXê÷ø¹Ç ¯žxº)¢=ÌÖˆ£;|ðO­õÿ\оp¡{LèíBi»4¿²@(1/1) Button2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF ModeAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAnalog GainAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue intensityBlue lamp offBlue offsetBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton stateButton test optionsButtonsCDCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeChange Document.Change documentChannelCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.CustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device-SettingsDisable backtrackingDisable pre focusDispersedDot16x16DispersedDot8x8Display short resolution listDitherDithered/halftone black & white (halftone mode)Do a grayscale rather than color scanDo a quality white-calibrationDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDouble Optical ResolutionDownload pattern ADownload pattern BDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject the sheet in the ADFEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enables or disables calibration data cache.EnhancementError DiffusionExperimentExposure timeExtra FastExtrasFastFast gray modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFilm-stripFineFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce scanner calibration before scanFrom paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen intensityGreen lamp offGreen offsetGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.Ignore calibrationImageImage EnhancementImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp off timeLamp off time (minutes)Lamp onLamp statusLampoff-timeLampoff-time in seconds.LampswitchLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMidtoneMidtone for blueMidtone for greenMidtone for redMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNo CorrectionNoise reductionNoneNormalNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffOffsetOnOne pageOnly perform shading-correctionOptional equipmentPaper sizePass-throughPhysical size of the paper in the ADFPositive FilmPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRandomizeRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed intensityRed lamp offRed offsetReduce the isolated dot noiseRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Return-value of sane_readSaturationScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Second entrySelect bay to scanSelect minimum-brightness to get a white pointSelect smoothing filter.Select the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Set default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set exposure-timeSet lamp densitySet sharpening value.Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSlideSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsStart calibration process.Status Code SimulationString test optionsSwap black and whiteSwitches the lamp on or off.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update optionsUpdate options.Use 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Warm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup-timeWarmup-time in seconds.White levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPA GrayXPA RGBY-resolutionZoomflatbed scannersheetfed scannerProject-Id-Version: sane-backends Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-12-17 23:05+0100 Last-Translator: Language-Team: Language: ru MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 1.10.1 Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); (1/1) КнопкаДвухточечное2x2 выборочно2x2 нормальное3x3 выборочно3x3 нормальноеЧетырёхточечное4x4 грубое4x4 выборочно4x4 хорошее4x4 нормальное5x5 грубое5x5 выборочно5x5 хорошее6x4 (дюймов)6x6 выборочно6x6 нормальноеВоÑьмибитный выводВоÑьмиточечное8.5x11 (дюймов)8x10 (дюймов)8x8 Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ8x8 грубое8x8 выборочно8x8 хорошее8x8 нормальное8x8 очень хорошееДлительное Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ позволÑет Ñканеру Ñобрать больше Ñвета. РекомендуетÑÑ Ð¸Ñпользовать 175% Ð´Ð»Ñ Ñ€Ð°Ñпечаток, 150% Ð´Ð»Ñ Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ñ‹Ñ… Ñлайдов и "Ðегатив" Ð´Ð»Ñ Ð½ÐµÐ³Ð°Ñ‚Ð¸Ð²Ð¾Ð². Ð”Ð»Ñ Ñ‚Ñ‘Ð¼Ð½Ñ‹Ñ… (недоÑкÑпонированных) изображений вы можете увеличить Ñто значение.A4A5 ландшафтA5 портретÐПДРежим автоподачиДобавлÑет к Ñинему, оÑнованному на уровне зелёногоДобавлÑет к Ñинему, оÑнованному на уровне краÑногоДобавлÑет к зелёному, оÑнованному на уровне ÑинегоДобавлÑет к зелёному, оÑнованному на уровне краÑногоДобавлÑет к краÑному, оÑнованному на уровне ÑинегоДобавлÑет к краÑному, оÑнованному на уровне зелёногоДополнительноДополнительные параметрыПоÑле подачи команды "Ñканировать", будет ожидать пока не будет нажата кнопка на Ñканере, чтобы дейÑтвительно начать процеÑÑ ÑканированиÑ.Ð’Ñе ÑтраницыÐналоговое уÑилениеÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° ÑинегоÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° зелёногоÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° краÑногоÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ Ð´Ð»Ñ ÑинегоÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ Ð´Ð»Ñ ÐºÑ€Ð°ÑногоÐвтоматичеÑкиÐвтоматичеÑкий порогÐвтоматичеÑки разделÑть на облаÑтиÐвтоизвлечениеÐвтоматичеÑкиÐвтоматичеÑкий податчик документовÐвтоматичеÑкое наÑтраивание порогаÐвтоматичеÑкое разделениеÐвтоматичеÑкий порогÐвтоматичеÑкий прогревÐвтоматичеÑки уÑтанавливает ÑркоÑть, контраÑтноÑть, уровень белого, гамму, уменьшение шума и выразительноÑть изображениÑЛинии откатаКоÑффициент Ð´Ð»Ñ Ñинего цвета. Значение 100% означает отÑутÑтвие коррекции.КоÑффициент Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾ цвета. Значение 100% означает отÑутÑтвие коррекции.КоÑффициент Ð´Ð»Ñ ÐºÑ€Ð°Ñного цвета. Значение 100% означает отÑутÑтвие коррекции.ОтÑекТолько чёрный и только белый (штриховой режим)СвÑзывать RGBСоглаÑовывать разрешение по X и по YСвÑзывать аналоговые гаммыСвÑзывать гаммыБит на цветУровень Ñ‡Ñ‘Ñ€Ð½Ð¾Ð³Ð¾Ð¡Ð¸Ð½Ð¸Ð¹Ð‘Ð°Ð»Ð°Ð½Ñ ÑинегоЯркоÑть ÑинегоУÑиление ÑинегоИнтенÑивноÑть ÑинегоВыключение Ñиней лампыСмещение ÑинегоДвочные теÑтовые Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ‹ÐŸÑ€Ð°Ð²Ð°Ñ Ð½Ð¸Ð¶Ð½ÑÑ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° XКоордината X правого нижнего угла облаÑти ÑканированиÑ.ÐŸÑ€Ð°Ð²Ð°Ñ Ð½Ð¸Ð¶Ð½ÑÑ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° YКоордината Y правого нижнего угла облаÑти ÑканированиÑ.ЯркоÑтьСоÑтоÑние кнопкиТеÑтовые параметры Ð´Ð»Ñ ÐºÐ½Ð¾Ð¿Ð¾ÐºÐšÐ½Ð¾Ð¿ÐºÐ¸CDЭЛТМониторы Ñ Ð­Ð›Ð¢ÐšÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ÐšÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑинегоКалибровать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾ÐšÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÑ€Ð°ÑногоКалибровать плотноÑть лампыКалибровкаКалибровать ÑканерКалибровать перед Ñледующим ÑканированиемКалибрует Ð´Ð»Ñ Ñ‡Ñ‘Ñ€Ð½Ð¾Ð³Ð¾ и белого уровнÑ.КалибровкаКалибровка производитÑÑ Ð´Ð²Ð¸Ð¶ÐºÐ¾Ð¼ÐšÑширование калибровочных данныхРежим калибровкиИзменить документ.Сменить Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚ÐšÐ°Ð½Ð°Ð»Ð“Ñ€ÑƒÐ±Ð¾ÐµÐ“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ°Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ° только Ð´Ð»Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ ÑканированиÑВыполнÑть грубую калибровку только во Ð²Ñ€ÐµÐ¼ÐµÐ½Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ ÑканированиÑ. Работает Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð½Ñтвом Ñканеров и может ÑÑкономить Ð²Ñ€ÐµÐ¼Ñ ÑканированиÑ. ЕÑли ÑркоÑть Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¾Ñ‚Ð»Ð¸Ñ‡Ð°ÐµÑ‚ÑÑ Ð¿Ñ€Ð¸ каждом Ñканировании, выключите Ñтот параметр. Только Ð´Ð»Ñ Ñ‚ÐµÑтированиÑ.ЦветнойЦветное 36Цветное полутоновоеЦветное ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¾ÐµÐ¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð°Ð¦Ð²ÐµÑ‚Ð½Ð¾Ð¹ RAWЦветной RGBЦветной RGB TEXTЦветовой баланÑÐаÑтройки уÑÐ¸Ð»ÐµÐ½Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ñ‹Ñ… каналовÐаÑтройки ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ñ‹Ñ… ÐºÐ°Ð½Ð°Ð»Ð¾Ð²ÐšÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²ÐšÐ¾Ñффициенты цветовой коррекцииЦветовой шаблонЦветной 24Цветное 36Цветной 48Цветных Ñтрок за Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° чтениеУÑловноКонтраÑтноÑтьКонтраÑтноÑть Ñинего каналаКонтраÑтноÑть зелёного каналаКонтраÑтноÑть краÑного каналаУправлÑет уровнем ÑинегоУправлÑет уровнем зелёногоУправлÑет уровнем краÑногоУправлÑет "тоном" (уровнем Ñинего) полученного изображениÑ.Управление ÑркоÑтью полученного изображениÑ.УправлÑет ÑркоÑтью Ñинего канала полученного изображениÑ.УправлÑет ÑркоÑтью зелёного канала полученного изображениÑ.УправлÑет ÑркоÑтью краÑного канала полученного изображениÑ.Управление контраÑтноÑтью полученного изображениÑ.УправлÑет контраÑтноÑтью Ñинего канала полученного изображениÑ.УправлÑет контраÑтноÑтью зелёного канала полученного изображениÑ.УправлÑет контраÑтноÑтью краÑного канала полученного изображениÑ.ОпределÑет, будет ли ÑовершатьÑÑ Ð¿Ñ€Ð¸Ð½ÑƒÐ´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ð¹ откат.ПользовательÑкоеПользовательÑÐºÐ°Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð° Ð´Ð»Ñ Ñ‡Ñ‘Ñ€Ð½Ð¾-белых изображений.ПользовательÑÐºÐ°Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð°ÐŸÐ°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ‹ отладкиПо умолчаниюПо умолчаниюЗадать режим калибровкиУÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ ÑинегоУÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÑинегоУÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸Ð£Ñтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ зелёногоУÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾Ð£Ñтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ краÑногоУÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÑ€Ð°ÑногоУÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑканированиÑОпределить плотноÑть лампы Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ÐžÐ¿Ñ€ÐµÐ´ÐµÐ»Ð¸Ñ‚ÑŒ плотноÑть лампы Ð´Ð»Ñ ÑканированиÑОпределÑет параметры Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñиней лампыОпределÑет параметры Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð¹ лампыОпределÑет параметры Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ ÐºÑ€Ð°Ñной лампыУÑтанавливает полутоновый (dithering) шаблон, иÑпользуемый при Ñканировании полутоновых изображений.ОпределÑет коÑффициент маÑштабированиÑ, который будет иÑпользоватьÑÑ ÑканеромЗадержка передачи данных в канал.ОпределÑет ÑкороÑть, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ производитÑÑ Ñканирование.ОпределÑет, будет ли иÑпользоватьÑÑ Ð²ÑÑ‚Ñ€Ð¾ÐµÐ½Ð½Ð°Ñ Ð¸Ð»Ð¸ неÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° гамма-коррекции.ÐаÑтройки уÑтройÑтваВыключить отÑлеживаниеВыключить предварительный фокуÑТочка Ñ€Ð°Ð·Ð¼Ñ‹Ñ‚Ð¸Ñ 16x16Точка Ñ€Ð°Ð·Ð¼Ñ‹Ñ‚Ð¸Ñ 8x8Показывать короткий ÑпиÑок разрешенийРазмытиеПолутоновый чёрно-белый (полутоновый режим)ВыполнÑть чёрно-белое Ñканирование вмеÑто цветногоВыполнить качеÑтвенную калибровку белогоÐе калибровать фокуÑÐе получать код ÑоÑтоÑниÑÐе принуждать драйвер возвращать код ÑоÑтоÑниÑ.Податчик лиÑтовУдваивать оптичеÑкое разрешениеЗагрузить шаблон AЗагрузить шаблон BДвухÑтороннийДвухÑтороннее ÑканированиеДвухÑтороннее Ñканирование позволÑет получить изображение лицевой и обратной Ñтороны документаДлительноÑть задержки при чтенииИзвлечьИзвлечь документ поÑле ÑканированиÑÐ’Ñтавить бумагу в уÑтройÑтво подачи документовВключить двуÑтороннее ÑканированиеВключает автоматичеÑкое определение порога при Ñканировании штриховых изображений.Включить выбор времени выдержкиВключить выбор плотноÑти лампыВключить теÑтовые параметрыВключить различные теÑтовые параметры. ПрименÑетÑÑ Ð´Ð»Ñ Ñ‚ÐµÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÑпоÑобноÑти графичеÑких оболочек проÑматривать и изменÑть различные типы параметров SANE.Включает или выключает кÑширование данных о калибровке.ÐŸÐ¾Ð²Ñ‹ÑˆÐµÐ½Ð¸ÐµÐ”Ð¸Ñ„Ñ„ÑƒÐ·Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾ÐºÐ­ÐºÑÐ¿ÐµÑ€Ð¸Ð¼ÐµÐ½Ñ‚Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ÐžÑ‡ÐµÐ½ÑŒ быÑтроДополнительноБыÑтроБыÑтрый чёрно-белый режимБыÑтрый предварительный проÑмотрБыÑтрое ÑканированиеБыÑтраÑÐ¡Ð°Ð¼Ð°Ñ Ð±Ñ‹ÑтраÑРежим подачиÐазвание файлаТип плёнкиПлёнкаТочноеБаланÑ, уÑтановленный на Ð·Ð°Ð²Ð¾Ð´ÐµÐŸÐµÑ€Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑьЗафикÑировать позицию фокуÑаДробночиÑленные теÑтовые Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ‹ÐŸÐ»Ð°Ð½ÑˆÐµÑ‚Ð½Ñ‹Ð¹Ð¤Ð¾ÐºÑƒÑ 2.5мм над ÑтекломРаÑположение фокуÑÐ°Ð¤Ð¾ÐºÑƒÑ Ð½Ð° ÑтеклеПринудительно откатыватьÑÑПринудительный одноцветный предварительный проÑмотрВыполнÑть калибровку Ñканера перед ÑканированиемОт бумагиОт белой палочкиОжидать кнопки на лицевой панелиПолное ÑканированиеÐечёткие параметрыУÑÐ¸Ð»ÐµÐ½Ð¸ÐµÐ“Ð°Ð¼Ð¼Ð°ÐšÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹Ð¢Ð°Ð±Ð»Ð¸Ñ†Ð° Ð³Ð°Ð¼Ð¼Ñ‹ÐšÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ðµ гаммыТаблица коррекции гаммы Ð´Ð»Ñ Ñиней компоненты.Таблица коррекции гаммы Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð¹ компоненты.Таблица коррекции гаммы Ð´Ð»Ñ ÐºÑ€Ð°Ñной компоненты.Таблица коррекции гаммы. Ð’ цветном режиме Ñтот параметр дейÑтвует одинаково на краÑный, зелёный и Ñиний каналы (то еÑть Ñто интенÑивноÑть коррекции гаммы).РаÑположениеЧёрно-белыйУÑиление ÑерогоЦвет полутонового режимаСмещение ÑерогоЧёрно-белый 16Чёрно-белый 8Сделать чёрно-белымОттенки Ñерого 4 битаОттенки Ñерого 8 битЧёрно-белое ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸ÐµÐ—ÐµÐ»Ñ‘Ð½Ñ‹Ð¹Ð‘Ð°Ð»Ð°Ð½Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾Ð¯Ñ€ÐºÐ¾Ñть зелёногоУÑиление зелёногоИнтенÑивноÑть зелёногоВыключение зелёной лампыСмещение зелёногоЧёрно-белых Ñтрок за Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° чтениеСеткаПолутоновый (раÑтр)Чёрно-белый A (Резкие тона)Чёрно-белый B (МÑгкие тона)Чёрно-белый C (Net Screen)Полутоновый пункт 32Полутоновый пункт 64Чёрно-белый шаблонРазмер чёрно-белого шаблонаПолутонаПолутоновое Ñканирование не поддерживаетÑÑÐ˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ ÑÐºÐ°Ð½ÐµÑ€Ð°Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ ÑканераВыÑокийПечать выÑокой контраÑтноÑтиПечать выÑокой плотноÑтиÐаивыÑшее качеÑтво, но Ð¼ÐµÐ´Ð»ÐµÐ½Ð½Ð°Ñ ÑкороÑтьÐаивыÑÑˆÐ°Ñ ÑкороÑть, но низкое качеÑтвоПодÑветкаПодÑветка Ð´Ð»Ñ ÑинегоПодÑветка Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾ÐŸÐ¾Ð´Ñветка Ð´Ð»Ñ ÐºÑ€Ð°ÑногоДержать позицию фокуÑа на 0ммГоризонтальноКак долго ожидать поÑле передачи каждого буфера данных через канал.ТонЕÑли отмечено, движок автоматичеÑки попробует определить оптимальное значение порога.ЕÑли отмечено, калибровка цвета перед Ñканированием выполнÑетÑÑ Ð´Ð²Ð¸Ð¶ÐºÐ¾Ð¼Ð•Ñли отмечено, Ñканер не выполнÑет отÑлеживаниеЕÑли отмечено, во Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ выполнÑетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð¾Ñ‚Ñ‚ÐµÐ½ÐºÐ¾Ð². Ð”Ð»Ñ ÑƒÑилениÑ, ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¸ времени выдержки иÑпользуютÑÑ Ð»Ð¸Ð±Ð¾ вÑтроенные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию, либо из конфигурационного файла.ЕÑли отмечено, уÑтройÑтво будет откалибровано перед Ñледующим Ñканированием. Ð’ противном Ñлучае, калибровка будет выполнена только перед первым Ñканированием.Игнорировать калибровкуИзображениеВыразительноÑть изображениÑВыразительноÑть изображениÑИнтенÑивноÑть изображениÑМатричные принтерыВ режиме RGB иÑпользовать одинаковые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ цветаУвеличить или уменьшить аналоговое уÑиление матрицы CCDСтруйные принтерыЦелочиÑленные теÑтовые параметрыИнвертировать порÑдок байтВыключить лампуВыключить лампу при Ð²Ñ‹Ñ…Ð¾Ð´ÐµÐ’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹ (в минутах)Включить лампуСоÑтоÑние Ð»Ð°Ð¼Ð¿Ñ‹Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹ в Ñекундах.Выключатель лампыLetterОграничить количеÑтво данных, передаваемых при каждом вызове sane_read().ШтриховойЗагрузить изображение как чёрно-белоеПотери точек на линиюÐизкийПечать выÑокой плотноÑÑ‚Ð¸Ð ÑƒÑ‡Ð½Ð°Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ„Ð¾ÐºÑƒÑировкаВручную управлÑет лампой.Матричный множитель RGBМакÑÐоÑительÐормальныйПолутонПолутон Ð´Ð»Ñ ÑинегоПолутон Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾ÐŸÐ¾Ð»ÑƒÑ‚Ð¾Ð½ Ð´Ð»Ñ ÐºÑ€Ð°ÑногоОтобразить горизонтальноЗеркальное изображениеОтображает изображение по горизонтали.Отображает изображение по вертикали.Сделать изображение зеркальным.Отобразить вертикальноРазличноеРежим 1Режим 2Режим 3ÐžÐ´Ð½Ð¾Ñ‚Ð¾Ð½Ð½Ð°Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð°ÐœÐ½Ð¾Ð³Ð¾ÑƒÑ€Ð¾Ð²Ð½ÐµÐ²Ñ‹Ðµ цвета RGB (однопроходной цвет)Многоуровневый чёрно-белый (режим оттенков Ñерого)Чёрно-белое NTSCNTSC RGBÐегативÐегативБез коррекцииУменьшение шумовÐичегоÐормальноКоличеÑтво бит на цвет, обычным значением ÑвлÑетÑÑ 1 Ð´Ð»Ñ ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¾Ð³Ð¾ и 8 Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ð¾Ð³Ð¾ режима ÑканированиÑ.КоличеÑтво линий, на которые Ñчитыватель возвращаетÑÑ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾ при необходимоÑти. Это проиÑходит когда Ñканер Ñчитывает изображение быÑтрее, чем компьютер может принимать данные. Ðизкое значение приводит к более быÑтрому Ñканированию, но увеличивает вероÑтноÑть пропуÑка линий.КоличеÑтво параметровКоличеÑтво Ñтрок ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² запроÑе Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¿Ð¾ SCSI.Изменение Ñтого параметра позволит вам наÑтроить ÑкороÑть, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ данный будут передаватьÑÑ Ñо Ñканера во Ð²Ñ€ÐµÐ¼Ñ ÑканированиÑ. ЕÑли он уÑтановлен очень низким, Ñканер будет периодичеÑки оÑтанавливатьÑÑ Ð²Ð¾ Ð²Ñ€ÐµÐ¼Ñ ÑканированиÑ, еÑли же Ñтот параметр будет уÑтановлен очень выÑоким, графичеÑÐºÐ°Ñ Ð¾Ð±Ð¾Ð»Ð¾Ñ‡ÐºÐ° может переÑтать принимать ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¾Ñ‚ ÑиÑтемы X Window и не будет реагировать на ваши команды до Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ ÑканированиÑ.КоличеÑтво кадров Ð´Ð»Ñ ÑканированиÑВыклСмещениеВклОдна ÑтраницаВыполнÑть только коррекцию оттенкаДополнительное оборудованиеРазмер бумагиПропуÑкать ÑквозьФизичеÑкий размер бумаги в уÑтройÑтве автоподачиПозитивЗаранее наÑтроенные параметрыПредварительный проÑмотрРежим предварительного проÑмотраРаÑпечаткаÐапечатать ÑпиÑок вÑех параметров.Ðапечатать параметрыПредоÑтавлÑÑŽÑ‚ Ñтандартные облаÑти ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ð¹, раÑпечатанных Ñтраниц и прочего.Калибровка качеÑтваКачеÑтвенное ÑканированиеБыÑтрый форматСлучайныйЗадержка при чтенииПредел чтениÑТеÑтовый параметр только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸ÑПараметр только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ, указывающий как много параметров указанное уÑтройÑтво поддерживает.КраÑÐ½Ñ‹Ð¹Ð‘Ð°Ð»Ð°Ð½Ñ ÐºÑ€Ð°ÑногоЯркоÑть краÑногоУÑиление краÑногоИнтенÑивноÑть краÑногоВыключение краÑной лампыСмещение краÑногоУменьшает количеÑтво отдельных Ñлучайных точекЗапроÑить Ñканирование качеÑтва как у предварительного проÑмотраЗапроÑить, чтобы вÑе предварительные проÑмотры были в одноцветном режиме. Ðа трёхпроходных Ñканерах Ñто уменьшит количеÑтво проходов до одного, а на однопроходных Ñканерах Ñократит Ñ‚Ñ€ÐµÐ±Ð¾Ð²Ð°Ð½Ð¸Ñ Ðº памÑти и Ð²Ñ€ÐµÐ¼Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ ÑканированиÑ.ПредпиÑывает вÑе предварительные проÑмотры выполнÑть в быÑтрейшем (низкокачеÑтвенном) режиме. Это может быть чёрно-белый режим или режим Ñ Ð½Ð¸Ð·ÐºÐ¸Ð¼ разрешением.Возвращаемое значение sane_readÐаÑыщенноÑтьСкалÑÑ€Ð½Ð°Ñ Ð³Ð°Ð¼Ð¼Ð°Ð¡ÐºÐ°Ð»ÑÑ€Ð½Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° ÑинегоСкалÑÑ€Ð½Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° зелёногоСкалÑÑ€Ð½Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° краÑногоРежим ÑканированиÑСканировать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸Ð¡ÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑинегоСканировать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾Ð¡ÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÑ€Ð°ÑногоСканировать в быÑтром чёрно-белом режиме (наихудшее качеÑтво).Сканировать плотноÑть лампыРежим ÑканированиÑРазрешение ÑканированиÑИÑточник ÑканированиÑСкороÑть ÑканированиÑСканировать полноÑтью вÑÑŽ облаÑть ÑканированиÑ, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð¾Ñ‡Ð½ÑƒÑŽ полоÑу. Будьте оÑторожны. Ðе выбирайте полную выÑоту. Только Ð´Ð»Ñ Ñ‚ÐµÑтированиÑ.Ð’Ñ‚Ð¾Ñ€Ð°Ñ Ð·Ð°Ð¿Ð¸ÑьВыбрать отÑек, который ÑканироватьВыберите минимальную ÑркоÑть Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð±ÐµÐ»Ð¾Ð¹ точкиВыберите фильтр Ð´Ð»Ñ ÑглаживаниÑ.Выберите вид теÑтовой картинки. ДоÑтупные параметры: Сплошной чёрный: вÑÑ Ð¾Ð±Ð»Ð°Ñть ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð° чёрным. Сполной белый: вÑÑ Ð¾Ð±Ð»Ð°Ñть ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð° белым. Цветной шаблон: риÑует теÑтовые шаблоны различными цветами, в завиÑимоÑти от режима. Сетка: риÑует чёрно-белую Ñетку Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð¾Ð¼ каждого квадрата 10 на 10 мм.Выберите режим Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ проÑмотра. Чёрно-белый предварительный проÑмотр обычно даёт лучшее Ñочетание ÑкороÑти и детализации.Выберите теÑтовое изображениеВыбирает значение Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ð¸ ÑкалÑрной гаммы (канал Ñинего)Выбирает значение Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ð¸ ÑкалÑрной гаммы (канал зелёного)Выбирает значение Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ð¸ ÑкалÑрной гаммы (канал краÑного)Выбирает значение Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ð¸ ÑкалÑрной гаммы.Выбирает режим автоподачи (одноÑторонний/двухÑторонний)Выбирает ÑркоÑть.Выбирает ÑвÑзь цветов, "ОÑновной" означает, что будут подвержены вÑе цвета.Выберите кривую гамма-коррекцииВыберите режим коррекции гаммы.Выбирает значение гамма-коррекции из ÑпиÑка предопределённых или наÑтроенных пользователем, которое может быть загружено в ÑканерВыбирает полутона.Выберите количеÑтво кадров Ð´Ð»Ñ ÑканированиÑВыберите режим ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ (например, штриховой, чёрно-белый или цветной).Выберите иÑточник Ñканирование (такой как уÑтройÑтво автоматичеÑкой подачи документов)ОпределÑет, какой Ñиний уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "чёрный".ОпределÑет, какой Ñиний уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "полный Ñиний".ОпределÑет, какой Ñиний уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "белый".ОпределÑет, какой зелёный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "чёрный".ОпределÑет, какой зелёный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "полный зелёный".ОпределÑет, какой зелёный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "белый".ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "чёрный".ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "белый".ОпределÑет, какой краÑный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "чёрный".ОпределÑет, какой краÑный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "полный краÑный".ОпределÑет, какой краÑный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "белый".ОпределÑет, должно ли полученное изображение быть превращено в полутоновое (размытием).ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "50 % Ñинего".ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "50 % Ñерого".ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "50 % зелёного".ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как "50 % краÑного".Выбирает, какой цвет будет иÑпользоватьÑÑ Ð¿Ñ€Ð¸ Ñканировании в полутоновом режиме (по умолчанию - зелёный).УÑтанавливает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð²Ñ‹ÑˆÐµÐ½Ð¸ÐµÐ¼ (ÑркоÑтью и контраÑтноÑтью).УÑтанавливает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð²Ñ‹ÑˆÐµÐ½Ð¸ÐµÐ¼.УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸Ð£Ñтановить плотноÑть лампыУÑтанавливает величину заоÑтрениÑ.УÑтановить порÑдок кадровУÑтанавливает порÑдок кадров в трёхпроходном цветном режиме.УÑтанавливает цветовую матрицу Ñканера.Указывает Ð²Ñ€ÐµÐ¼Ñ (в минутах), поÑле которого лампа будет выключена.УÑтановить тип ноÑителÑ.Включить/выключить UTAУÑтанавливает уÑиление Ñинего каналаУÑтанавливает Ñмещение канала ÑинегоУÑтанавливает уÑиление Ñерого каналаУÑтанавливает Ñмещение канала ÑерогоУÑтанавливает уÑиление зелёного каналаУÑтанавливает Ñмещение канала зелёногоВключить/выключить лампуУÑтанавливает уÑиление краÑного каналаУÑтанавливает Ñмещение канала краÑногоУÑтанавливает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð¾Ð³Ð¾ баланÑа в иÑходные значениÑ, уÑтановленные на заводе.УÑтанавливает таблицу коррекции цветов Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ выходного уÑтройÑтва.УÑтанавливает режим подачиУÑтанавливает раÑположение фокуÑа либо на Ñтекле, либо на 2.5мм выше ÑтеклаУÑтанавливает значение гаммы вÑех каналов.УÑтанавливает горизонтальное разрешение Ñканируемого изображениÑ.УÑтанавливает выразительноÑть изображениÑУÑтанавливает разрешение Ñканируемого изображениÑ.УÑтанавливает размер полутонового (dithering) шаблона, иÑпользуемого при Ñканировании полутоновых изображений.УÑтанавливает вертикальное разрешение Ñканируемого изображениÑ.ÐаÑтраивает уÑиление и Ñмещение Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки. ЕÑли Ñтот параметр выключен, будут предоÑтавлены параметры Ð´Ð»Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð¹ аналоговой наÑтройки. Параметр включен по умолчанию. Только Ð´Ð»Ñ Ñ‚ÐµÑтированиÑ.ЗатенённоÑтьЗатенённоÑть Ð´Ð»Ñ ÑинегоЗатенённоÑть Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾Ð—Ð°Ñ‚ÐµÐ½Ñ‘Ð½Ð½Ð¾Ñть Ð´Ð»Ñ ÐºÑ€Ð°ÑногоЗатенённоÑть, полутон, подÑветка, Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸Ð—Ð°Ð¾ÑтрениÑРезкоÑтьСдвиг Ñинего к зелёномуСдвиг Ñинего к краÑномуСдвиг зелёного к ÑинемуСдвиг зелёного к краÑномуСдвиг краÑного к ÑинемуСдвиг краÑного к зелёномуКороткий ÑпиÑок разрешенийВыключить лампуВыключает лампу Ñканера.ОдноÑтороннийИмитировать ручной Ñканер. Ручные Ñканеры никогда не знают о выÑоте изображениÑ. ВмеÑто Ñтого они возвращают выÑоту, равную -1. УÑтановка Ñтого параметра позволÑет протеÑтировать, будет ли графичеÑÐºÐ°Ñ Ð¾Ð±Ð¾Ð»Ð¾Ñ‡ÐºÐ° обрабатывать Ñто корректно. Этот параметр также включает фикÑированную ширину 11 Ñм.Имитирует ручной Ñканер. Ручные Ñканеры чаÑто не имеют информации о длине изображениÑ. ВмеÑто Ñтого они возвращает длину -1. УÑтановка Ñтого параметра позволит проверить будет ли фронтенд корректно обрабатывать Ñту Ñитуацию.Имитирует трёхпроходной Ñкнер возвращениём трёх различных кадров. То еÑть возвращает Ñначала зелёный, потом Ñиний, потом краÑный.Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ‚Ñ€Ñ‘Ñ…Ð¿Ñ€Ð¾Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ Ñканера. Ð’ цветном режиме будет передано три кадра.Размер предела чтениÑСлайдМедленноМедленнаÑÐ¡Ð°Ð¼Ð°Ñ Ð¼ÐµÐ´Ð»ÐµÐ½Ð½Ð°ÑСглаживатьСглаживаниеСплошной чёрныйСплошной белыйИÑточник ÑканированиÑСпециальные параметрыСпециальные параметрыÐачать процеÑÑ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸.Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð´Ð° ÑоÑтоÑниÑТеÑтовые параметры Ð´Ð»Ñ ÑтрокПоменÑть меÑтами чёрный и белыйВключить/выключить лампу.Ð¢ÐµÑ…Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ ÑƒÐ»ÑƒÑ‡ÑˆÐµÐ½Ð¸Ñ Ñ‚ÐµÐºÑтаМакÑимальное количеÑтво данных, передаваемых при каждом вызове sane_read().Ðазвание файла изображениÑ, которое должно быть загружено.Лампа будет выключена через указанное Ð²Ñ€ÐµÐ¼Ñ (в минутах). Значение 0 означает, что лампа выключатьÑÑ Ð½Ðµ будет.КоличеÑтво точек, которые потерÑны в конце каждой линии.Уровень наÑыщенноÑти управлÑет количеÑтвом "blooming", который получаетÑÑ Ð¿Ñ€Ð¸ получении Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñ ÐºÐ°Ð¼ÐµÑ€Ñ‹. Большие Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð·Ñ‹Ð²Ð°ÑŽÑ‚ больше blooming.ТермичеÑкие принтерыЭто очень Ð´Ð»Ð¸Ð½Ð½Ð°Ñ Ñ‚Ñ€ÐµÑ‚ÑŒÑ Ð·Ð°Ð¿Ð¸ÑÑŒ. Может быть фронтенд Ñможет показать её.Этот параметр отражает ÑоÑтоÑние кнопок Ñканера.Этот параметр выключает лампу планшетного Ñканера во Ð²Ñ€ÐµÐ¼Ñ ÑканированиÑÐ˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ‚Ñ€Ñ‘Ñ…Ð¿Ñ€Ð¾Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ Ñ€ÐµÐ¶Ð¸Ð¼Ð°Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ‚Ñ€Ñ‘Ñ…Ð¿Ñ€Ð¾Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ режимаПорогПереключить лампу планшетного ÑканераПереключает лампу планшетного ÑÐºÐ°Ð½ÐµÑ€Ð°Ð›ÐµÐ²Ð°Ñ Ð²ÐµÑ€Ñ…Ð½ÑÑ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° XКоордината X левого верхнего угла облаÑти ÑканированиÑ.Ð›ÐµÐ²Ð°Ñ Ð²ÐµÑ€Ñ…Ð½ÑÑ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° YКоордината Y левого верхнего угла облаÑти ÑканированиÑ.ПрозрачныйСлайд-модульМодуль Ð´Ð»Ñ ÑлайдовВыключить лампу ÑканераВыключить лампу при выходе из программыВыключить лампу ÑканераВключить лампу ÑканераВыключает лампу незамедлительно.включить UTAВыгрузитьВыгрузить документ.Выгружать ноÑитель поÑле ÑканированиÑВыгружает ноÑитель поÑле ÑканированиÑ.Обновить параметрыОбновлÑет параметры.ИÑпользовать Ñ„Ð¾ÐºÑƒÑ 0мм вмеÑто 0.6ммИÑпользовать компоновку изображенийВнутри иÑпользовать разрÑдноÑть более 8 бит, но выводить только 8 бит.ИÑпользовать неÑтандартную гаммуИÑпользовать lens, которое удваивает оптичеÑкое разрешениеИÑпользовать неблокирующий ввод-выводИÑпользовать неблокируемый ввод-вывод Ð´Ð»Ñ sane_read(), еÑли таковой поддерживаетÑÑ Ð³Ñ€Ð°Ñ„Ð¸Ñ‡ÐµÑкой оболочкой.ИÑпользовать те же Ñамые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ Ð´Ð»Ñ Ð²Ñех цветовых каналов.ИÑпользовать одинаковые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ð¹ по горизонтали и вертикали.ИÑпользовать 35мм адаптер lightlidОпределÑемое пользователемОпределённое пользователем (Gamma=1.0)Определённое пользователем (Gamma=1.8)ВертикальноеОжидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ÐžÐ¶Ð¸Ð´Ð°Ñ‚ÑŒ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸Ð–Ð´Ð°Ñ‚ÑŒ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ на передней панели Ð´Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° ÑканированиÑ.Разогревать пока ÑркоÑть лампы не Ñтанет поÑтоÑнной, вмеÑто проÑтого 40-тиÑекундного Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñ€Ð°Ð·Ð¾Ð³Ñ€ÐµÐ²Ð°.Разогревать пока ÑркоÑть лампы не Ñтанет поÑтоÑнной, вмеÑто проÑтого 60-тиÑекундного Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñ€Ð°Ð·Ð¾Ð³Ñ€ÐµÐ²Ð°.Прогрев лампыПрогревать лампу перед ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸ÐµÐ¼Ð’Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¾Ð³Ñ€ÐµÐ²Ð° Ð»Ð°Ð¼Ð¿Ñ‹Ð’Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¾Ð³Ñ€ÐµÐ²Ð° лампы в Ñекундах.Уровень белогоУровень белого Ð´Ð»Ñ ÑинегоУровень белого Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾Ð£Ñ€Ð¾Ð²ÐµÐ½ÑŒ белого Ð´Ð»Ñ ÐºÑ€Ð°ÑногоРазрешение по XЧёрно-белое XPAXPA RGBРазрешение по YМаÑштабпланшетный ÑканерлиÑтовой Ñканерsane-backends-1.0.27/po/ja.po0000664000175000017500000044116313110600537012577 00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.20\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2009-10-31 10:30+0900\n" "Last-Translator: Hiroshi Miura \n" "Language-Team: Japanese \n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Japanese\n" "X-Poedit-Country: JAPAN\n" "X-Poedit-SourceCharset: utf-8\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "オプション数" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "標準" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "é…ç½®" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "増強" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "上級" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "センサー" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "プレビュー" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "モノクロームプレビューを強制ã™ã‚‹" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "ビット深度" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "走査モード" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "走査速度" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "走査æº" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "左上ã®x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "左上ã®y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "å³ä¸‹ã®x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "å³ä¸‹ã®y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "走査解åƒåº¦" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Xè§£åƒåº¦" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Yè§£åƒåº¦" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "ページ幅" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "ページ高" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "カスタムガンマテーブルを使ã†" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "ç”»åƒã®æ˜Žæš—度" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "明暗度赤" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "明暗度緑" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "明暗度é’" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "è¼åº¦" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "コントラスト" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "粒径" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "ãƒãƒ¼ãƒ•トーン処ç†" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "黒レベル" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "ホワイトレベル" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "ホワイトレベルã®èµ¤å€¤" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "ホワイトレベルã®ç·‘値" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "ホワイトレベルã®é’値" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "最å°è¼åº¦ã€å½±" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "èµ¤ã®æœ€å°è¼åº¦" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "ç·‘ã®æœ€å°è¼åº¦" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "é’ã®æœ€å°è¼åº¦" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "ãƒã‚¤ãƒ©ã‚¤ãƒˆ" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "赤ã®ãƒã‚¤ãƒ©ã‚¤ãƒˆ" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "ç·‘ã®ãƒã‚¤ãƒ©ã‚¤ãƒˆ" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "é’ã®ãƒã‚¤ãƒ©ã‚¤ãƒˆ" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "色相" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "彩度" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "ファイルå" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "ãƒãƒ¼ãƒ•トーンパターンã®å¤§ãã•" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "ãƒãƒ¼ãƒ•トーンã®ãƒ‘ターン" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Xã¨Yè§£åƒåº¦ã‚’拘æŸ" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "ãƒã‚¬" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "å“質較正" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "ï¼’å€å…‰å­¦è§£åƒåº¦" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "RGB値を拘æŸ" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "閾値" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "アナログガンマ補正" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "アナログガンマ赤" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "アナログガンマ緑" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "アナログガンマé’" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "アナログガンマ値を拘æŸ" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "ãƒ©ãƒ³ãƒ—ã®æš–æ©Ÿ" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "露出時間を較正" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "赤ã®éœ²å‡ºæ™‚間を較正" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "ç·‘ã®éœ²å‡ºæ™‚間を較正" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "é’ã®éœ²å‡ºæ™‚間を較正" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "走査露出時間" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "赤ã®èµ°æŸ»éœ²å‡ºæ™‚é–“" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "ç·‘ã®èµ°æŸ»éœ²å‡ºæ™‚é–“" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "é’ã®èµ°æŸ»éœ²å‡ºæ™‚é–“" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "露出時間を設定" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "ãƒ©ãƒ³ãƒ—å¯†åº¦ã®æ ¡æ­£" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "ランプ密度ã®èµ°æŸ»" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "ランプ密度ã®è¨­å®š" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "終了時ã«ãƒ©ãƒ³ãƒ—ã‚’åœæ­¢ã™ã‚‹" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "特定ã®ãƒ‡ãƒã‚¤ã‚¹ãŒã‚µãƒãƒ¼ãƒˆã™ã‚‹ã‚ªãƒ—ションãŒã©ã‚Œã ã‘ã‚ã‚‹ã‹ã‚’指定ã™ã‚‹èª­ã¿å–り" "ã®ã¿ã‚ªãƒ—ション" #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "入力元ã€ãƒ¢ãƒ¼ãƒ‰ã¨è§£åƒåº¦ã®ã‚ªãƒ—ション" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "走査領域ã¨ãƒ¡ãƒ‡ã‚£ã‚¢ã‚µã‚¤ã‚ºã®ã‚ªãƒ—ション" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "イメージ修正オプション" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢ç‹¬è‡ªã®ã‚ªãƒ—ション" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "スキャナーã®ã‚»ãƒ³ã‚µãƒ¼ã‚„ボタン" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "プレビューå“質ã®èµ°æŸ»ã‚’è¦æ±‚ã™ã‚‹ã€‚" #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "" #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "" #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "走査エリアã®å·¦ä¸Šã®ä½ç½®" #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "走査エリアã®å³ä¸Šã®ä½ç½®" #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "走査エリアã®å³ä¸‹ã®xä½ç½®" #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "走査エリアã®å³ä¸‹ã®ä½ç½®ã‚’決ã‚る。" #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "走査イメージã®è§£åƒåº¦ã‚’設定。" #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "走査ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã®æ°´å¹³è§£åƒåº¦ã‚’設定ã™ã‚‹ã€‚" #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "走査ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã®åž‚直改造度を設定ã™ã‚‹ã€‚" #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "媒体ã®é«˜ã•を指定" #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "赤ãƒãƒ³ãƒ‰ã®ã‚¬ãƒ³ãƒžè£œæ­£ãƒ†ãƒ¼ãƒ–ル。" #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "ç·‘ãƒãƒ³ãƒ‰ã®ã‚¬ãƒ³ãƒžè£œæ­£ãƒ†ãƒ¼ãƒ–ル。" #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "é’ãƒãƒ³ãƒ‰ã®ã‚¬ãƒ³ãƒžè£œæ­£ãƒ†ãƒ¼ãƒ–ル。" #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "å–å¾—ã—ãŸç”»åƒã®è¼åº¦ã‚’制御ã™ã‚‹ã€‚" #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "å–å¾—ã—ãŸç”»åƒã®ã‚³ãƒ³ãƒˆãƒ©ã‚¹ãƒˆã‚’制御ã™ã‚‹ã€‚" #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "" #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "ロードã•れる画åƒã®ãƒ•ァイルå" #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "é»’ã¨ç™½ã‚’å転ã™ã‚‹" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "ï¼’å€å…‰å­¦è§£åƒåº¦ã®ãƒ¬ãƒ³ã‚ºã‚’使ã†" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "RGBモードã«ãŠã„ã¦å„色ã«å¯¾ã—ã¦åŒã˜å€¤ã‚’使ã†" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "白ã®ç‚¹ã‚’å¾—ã‚‹ãŸã‚ã€æœ€å°è¼åº¦ã‚’é¸æŠž" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "アナログガンマ補正" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "赤ã®ã‚¢ãƒŠãƒ­ã‚°ã‚¬ãƒ³ãƒžè£œæ­£" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "ç·‘ã®ã‚¢ãƒŠãƒ­ã‚°ã‚¬ãƒ³ãƒžè£œæ­£" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "é’ã®ã‚¢ãƒŠãƒ­ã‚°ã‚¬ãƒ³ãƒžè£œæ­£" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "走査å‰ã®ãƒ©ãƒ³ãƒ—ã®æš–æ©Ÿ" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "赤較正ã®ãŸã‚ã®éœ²å‡ºæ™‚é–“ã®å®šç¾©" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "緑較正ã®ãŸã‚ã®éœ²å‡ºæ™‚é–“ã®å®šç¾©" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "é’較正ã®ãŸã‚ã®éœ²å‡ºæ™‚é–“ã®å®šç¾©" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "走査ã®éœ²å‡ºæ™‚間を設定" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "赤走査ã®éœ²å‡ºæ™‚間を設定" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "緑スキャンã®éœ²å‡ºæ™‚間を設定" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "é’スキャンã®éœ²å‡ºæ™‚間を設定" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "露出時間ã®é¸æŠžã‚’有効ã«ã™ã‚‹ã€‚" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "較正ã®ãƒ©ãƒ³ãƒ—密度を定義" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "走査ã®ãƒ©ãƒ³ãƒ—密度を定義" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "プログラム終了時ã«ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "スキャンボタン" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "é›»å­ãƒ¡ãƒ¼ãƒ«ãƒœã‚¿ãƒ³" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "ファックスボタン" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "コピーボタン" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "PDFボタン" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "キャンセルボタン" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "ページãŒãƒ­ãƒ¼ãƒ‰ã•れãŸ" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "ã‚«ãƒãƒ¼ãŒé–‹ã„ã¦ã„ã‚‹" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "カラー" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "グレー" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "網版" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "ç·šç”»" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "æˆåŠŸ" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "æ“作ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "æ“作ã¯ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•れã¾ã—ãŸã€‚" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "デãƒã‚¤ã‚¹ãƒ“ジー" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "䏿­£ãªå¼•æ•°" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ€å¾Œã«åˆ°é”" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "書類é€ã‚ŠãŒè©°ã¾ã‚Šã¾ã—ãŸ" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "書類é€ã‚ŠãŒç©ºã«ãªã‚Šã¾ã—ãŸ" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "スキャナーã®ã‚«ãƒãƒ¼ãŒé–‹ã„ã¦ã„ã¾ã™" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "デãƒã‚¤ã‚¹å…¥å‡ºåЛ䏭ã«ã‚¨ãƒ©ãƒ¼" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "メモリä¸è¶³" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "資æºã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯æ‹’å¦ã•れã¾ã—ãŸã€‚" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "ãƒ©ãƒ³ãƒ—ã®æº–å‚™ãŒæ•´ã„ã¾ã›ã‚“。å†åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "移動ã®ãŸã‚ã«ã€èµ°æŸ»æ©Ÿæ§‹ã‚’ロックã™ã‚‹ã€‚" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "既定" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "å¢—å¼·åˆ¶å¾¡ã®æ—¢å®šå€¤ã‚’設定ã™ã‚‹" #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "æ ¡æ­£" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "次ã®èµ°æŸ»ã®ã¾ãˆã«æ ¡æ­£ã™ã‚‹" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "有効ã«ã•れるã¨ã€ãƒ‡ãƒã‚¤ã‚¹ã¯æ¬¡ã®èµ°æŸ»ã®å‰ã«ã‹ãªã‚‰ãšæ ¡æ­£ã‚’è¡Œã„ã¾ã™ã€‚ãã†ã§ãª" "ã‘れã°ã€æ ¡æ­£ã¯æœ€åˆã®é–‹å§‹å‰ã®ä¸€åº¦ã ã‘行ã‚れã¾ã™ã€‚" #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "シェーディング補正ã ã‘を行ã†" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "有効ã®å ´åˆã€è¼ƒæ­£ã«ãŠã„ã¦ã¯ã‚·ã‚§ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°è£œæ­£ã ã‘ãŒå®Ÿè¡Œã•れã¾ã™ã€‚利得ã€ã‚ª" "フセットã¨éœ²å…‰æ™‚é–“ã®æ—¢å®šå€¤ã¯ã€çµ„ã¿è¾¼ã¾ã‚Œã¦ã„る値ã‹ã€è¨­å®šãƒ•ァイルã‹ã‚‰èª­ã¿" "è¾¼ã¾ã‚ŒãŸå€¤ãŒä½¿ã‚れã¾ã™ã€‚" #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "ボタンã®çŠ¶æ…‹" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "走査ã™ã‚‹ãƒ•レーム数" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "走査ã™ã‚‹ãƒ•ãƒ¬ãƒ¼ãƒ ã®æ•°ã‚’é¸ã‚“ã§ãã ã•ã„。" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "両é¢ã‚¹ã‚­ãƒ£ãƒ³" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "両é¢ã‚¹ã‚­ãƒ£ãƒ³ã§ã¯ã€æ–‡æ›¸ã®è¡¨é¢ã¨è£é¢ã®èµ°æŸ»ãŒè¡Œã‚れã¾ã™ã€‚" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã®æ ¡æ­£" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "走査å‰ã«ã‚¹ã‚­ãƒ£ãƒŠã®æ ¡æ­£ã‚’強制ã™ã‚‹" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "グレースケール走査" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "カラーã®ä»£ã‚りã«ã€ã‚°ãƒ¬ãƒ¼ã‚¹ã‚±ãƒ¼ãƒ«ã§èµ°æŸ»ã—ã¾ã™ã€‚" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "アナログ利得" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "CCDé…列ã®ã‚¢ãƒŠãƒ­ã‚°åˆ©å¾—を増加ã¾ãŸã¯æ¸›å°‘" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "ガンマ校正" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "ガンマ補正ã•れãŸå¤‰æ›ã‚«ãƒ¼ãƒ–ã‚’é¸æŠž" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "無加工" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "高精彩" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "逿˜Žåº¦è£œæ­£ã¯è¡Œã‚ãªã„" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "フィルムã®ç¨®é¡žã«å¾“ã£ãŸè£œæ­£" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "é€éŽçއã«å¾“ã£ã¦ã€è£œæ­£ã•れã¾ã™ã€‚" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "ãƒã‚¬ç”»åƒ" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "スライド" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "自動" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "普通ã®é€Ÿåº¦" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "åŠåˆ†ã®é€Ÿåº¦" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "3分ã®ï¼‘ã®é€Ÿåº¦" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "丸ã‚られãŸãƒ‘ラメター値" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "䏿˜Ž" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "ADFãŒè©°ã¾ã‚Šã¾ã—ãŸ" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "ADFã®ã‚«ãƒãƒ¼ãŒé–‹ã„ã¦ã„ã¾ã™" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "ランプä¸è‰¯" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "走査ヘッドã®ä½ç½®ã‚¨ãƒ©ãƒ¼" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "CPUãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "RAMãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "ROMãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢ãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "フィルムユニットã®ãƒ©ãƒ³ãƒ—ä¸è‰¯" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "フィルムユニットã®ãƒ˜ãƒƒãƒ‰ä½ç½®ä¸è‰¯" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "パラメターリストã®é•·ã•エラー" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "䏿­£ãªã‚³ãƒžãƒ³ãƒ‰æ“作コード" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "CDBã«ä¸æ­£ãªãƒ•ィールド" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "サãƒãƒ¼ãƒˆã•れãªã„LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "パラメターリストã«ä¸æ­£ãªãƒ•ィールド" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "コマンドã®é †åºã‚¨ãƒ©ãƒ¼" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "指定ã•れãŸã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ãŒå¤šã™ãŽã¾ã™" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "媒体ãŒå­˜åœ¨ã—ã¾ã›ã‚“" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "IDENTIFYメッセージã«ä¸æ­£ãªãƒ“ット" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "ã‚ªãƒ—ã‚·ãƒ§ãƒ³ãŒæ­£ã—ãã‚りã¾ã›ã‚“" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "é›»æºONリセット/ãƒã‚¹ãƒ‡ãƒã‚¤ã‚¹ãƒªã‚»ãƒƒãƒˆ" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "ã»ã‹ã®åˆæœŸåŒ–プログラムã«ã‚ˆã£ã¦ãƒ‘ラメターãŒå¤‰æ›´ã•れã¾ã—ãŸ" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "追加センサー情報ã¯ã‚りã¾ã›ã‚“。" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "å†é¸æŠžå¤±æ•—" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "SCSIパリティエラー" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "åˆæœŸåŒ–ルーãƒãƒ³ãŒã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å—ä¿¡ã—ã¾ã—ãŸã€‚" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "䏿­£ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚¨ãƒ©ãƒ¼" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "タイムアウトエラー" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "é€éŽãƒ¦ãƒ‹ãƒƒãƒˆã®ã‚·ã‚§ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚¨ãƒ©ãƒ¼" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "ランプãŒå®‰å®šã—ã¾ã›ã‚“" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "フィルムスキャナー" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "フラットベッド(平å°åž‹ï¼‰ã‚¹ã‚­ãƒ£ãƒŠ" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "フィルムã®ç¨®é¡ž" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "フィルムã®ç¨®é¡žã‚’é¸æŠžï¼ˆä¾‹ã€ãƒã‚¬ã€ã‚¹ãƒ©ã‚¤ãƒ‰ï¼‰" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "ãƒã‚¬ãƒ•ィルム" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "ãƒã‚¬ãƒ•ã‚£ãƒ«ãƒ ã‚’é¸æŠž" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢è§£åƒåº¦" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢è§£åƒåº¦ã ã‘を使用" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "焦点" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "自動焦点" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "自動焦点を有効ï¼ç„¡åй" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "自動焦点を一回ã ã‘行ã†" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "排出ã—ã¦ã„ã‚‹é–“ã«ã€ä¸€åº¦ã ã‘自動焦点補正を行ã„ã¾ã™ã€‚" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "手動焦点ä½ç½®" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "光学系ã®ç„¦ç‚¹ä½ç½®ã‚’手動ã§è¨­å®šã—ã¾ã™ï¼ˆæ—¢å®šå€¤ï¼šï¼‘28)" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "走査ã®ä½™ç™½" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "追加色調整" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "é¡åƒç”»åƒ" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "æ°´å¹³ã«ç”»åƒã®é¡åƒã«ã™ã‚‹" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "自動露出" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "自動露光機能を有効ï¼ç„¡åйã«ã™ã‚‹" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "校正中" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "較正を「ã™ãã«ã€å®Ÿè¡Œã—ã¾ã™" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "自己診断" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "スキャナーã®è‡ªå·±è¨ºæ–­ã‚’実行" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "スキャナーã®ãƒªã‚»ãƒƒãƒˆ" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "スキャナーをリセットã™ã‚‹" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "åª’ä½“ã®æ‰±ã„" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "å„走査ã®å¾Œãƒ•ィルムを排出ã™ã‚‹" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "自動的ã«ã€å„走査ã®å¾Œã€ãƒ•ィルムを装置ã‹ã‚‰æŽ’出ã™ã‚‹ã€‚" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "終了å‰ã«ãƒ•ィルムを排出ã™ã‚‹" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "自動的ã«ã€ãƒ—ログラム終了å‰ã«è£…ç½®ã‹ã‚‰ãƒ•ィルムを排出ã™ã‚‹" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "フィルムを今排出" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "フィルムを今ã™ãã€æŽ’å‡ºã™ã‚‹ã€‚" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "文書供給装置拡張" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "フラットベッドã®ã¿" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "自動書類é€ã‚Šã‚’無効ã«ã—ã€å¹³å°ã ã‘を使ã„ã¾ã™" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "é€éŽãƒ¦ãƒ‹ãƒƒãƒˆ" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" "é€éŽãƒ¦ãƒ‹ãƒƒãƒˆã®ã‚ªãƒ•・オンを切り替ãˆã¾ã™ã€‚(FAU,フィルムアダプター装置)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "ãƒã‚¬ãƒ•ィルム" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "ãƒã‚¸ã‚ã‚‹ã„ã¯ãƒã‚¬ãƒ•ィルム" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "濃度制御" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "濃度制御モードを設定" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "é€éŽçއ" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "フィルムã®ç¨®é¡žã‚’é¸æŠž" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "フィルムã®ç¨®é¡žã‚’é¸ã¶" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "フラットベッド" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "ADF表é¢" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "ADFè£é¢" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "ADF両é¢" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "ADF表é¢" #: backend/canon_dr.c:413 #, fuzzy, no-c-format msgid "Card Back" msgstr "ADFè£é¢" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "両é¢" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "赤" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "ç·‘" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "é’" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "増強" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "増強" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "増強" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr " ãªã—" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "片é¢" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "両é¢" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "é€éŽãƒ¦ãƒ‹ãƒƒãƒˆ" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "自動原稿é€ã‚Šè£…ç½®" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "ãƒã‚¸ãƒ•ィルム" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "ãƒã‚¬ãƒ•ィルム" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "ガラス表é¢ã«ç„¦ç‚¹ã‚’åˆã‚ã›ã‚‹" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "ガラスã‹ã‚‰2.5mmã®å ´æ‰€ã«ç„¦ç‚¹ã‚’åˆã‚ã›ã‚‹" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "ãƒãƒ¼ãƒ•トーン A(ãƒãƒ¼ãƒ‰ãƒˆãƒ¼ãƒ³ï¼‰" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "ãƒãƒ¼ãƒ•トーンB(ソフトトーン)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "ãƒãƒ¼ãƒ•トーンC(ãƒãƒƒãƒˆãƒˆãƒ¼ãƒ³ï¼‰" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "ディザーA(4x4ãƒã‚¤ã‚¨ãƒ«ï¼‰" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "ディザーB(4x4スパイラル)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "ディザーC(4x4網スクリーン)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "ディザーD(8x4ã®ç¶²ã‚¹ã‚¯ãƒªãƒ¼ãƒ³)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "テキスト強調技術" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "パターンAã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "パターンBã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "補正をã—ãªã„" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "ユーザ定義" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "ドットインパクトプリンタ" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "熱転写プリンタ" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "インクジェットプリンタ" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRTモニター" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "既定" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "高密度å°åˆ·" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "低密度å°åˆ·" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "高コントラストå°åˆ·" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "ユーザ定義(ガンマï¼ï¼‘.ï¼ï¼‰" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "ユーザ定義(ガンマï¼ï¼‘.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5縦" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5横" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "USレターサイズ" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "最大" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "走査モード" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "ãƒãƒ¼ãƒ•ãƒˆãƒ¼ãƒ³ã‚’é¸æŠžã™ã‚‹ã€‚" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "å–り出ã—å£" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "å–り出ã—å£ã®é¸æŠž" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "è¼åº¦ã®é¸æŠž" #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "鮮鋭度" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "カラー補正" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "é¸æŠžã—ãŸå‡ºåŠ›ãƒ‡ãƒã‚¤ã‚¹ã®ãŸã‚ã®è‰²è£œæ­£ãƒ†ãƒ¼ãƒ–ルを設定ã™ã‚‹ã€‚" #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "RGBã®å€çŽ‡ãƒžãƒˆãƒªãƒƒã‚¯ã‚¹" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "緑を赤ã«ã‚·ãƒ•ト" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "ç·‘ã‚’é’ã«ã‚·ãƒ•ト" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "赤を緑ã«ã‚·ãƒ•ト" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "赤をé’ã«ã‚·ãƒ•ト" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "é’ã‚’ç·‘ã«ã‚·ãƒ•ト" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "é’を赤ã«ã‚·ãƒ•ト" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "緑レベルã®åˆ¶å¾¡" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "緑レベルを基準ã«èµ¤ã‚’増加" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "緑レベルを基準ã«é’を増加" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "赤レベルを基準ã«ç·‘を増加" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "赤レベルã®åˆ¶å¾¡" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "赤レベルを基準ã«é’を増加" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "é’レベルを基準ã¨ã—ã¦ç·‘を増加" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "é’レベルを基準ã¨ã—ã¦èµ¤ã‚’増加" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "é’レベルã®åˆ¶å¾¡" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "é¡åƒã‚’ã¨ã‚‹ã€‚" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "高速プレビュー" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "自動領域分割" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "短ã„è§£åƒåº¦ä¸€è¦§" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "è§£åƒåº¦ã®ãƒªã‚¹ãƒˆã‚’短ã表示" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "ズーム" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "スキャナーãŒä½¿ã†ã¹ãズーム値を定義" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "簡易フォーマット" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "光学装置" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "排出" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "ADFã®æ›¸é¡žã‚’排出ã™ã‚‹" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "自動排出" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "èµ°æŸ»å¾Œã€æ›¸é¡žã‚’排出" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "ADFモード" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "ADFモードã®é¸æŠžï¼ˆç‰‡é¢ã€ä¸¡é¢ï¼‰" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "ガンマ補正値を事å‰å®šç¾©ã®ãƒ‡ãƒã‚¤ã‚¹ã®ãƒªã‚¹ãƒˆã‹ã‚‰é¸æŠžã™ã‚‹ã€‚" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "焦点ä½ç½®" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "焦点ä½ç½®ã‚’ã€ã‚¬ãƒ©ã‚¹é¢ãªã„ã—ã¯ã€ã‚¬ãƒ©ã‚¹é¢ã‹ã‚‰2.5mmã®ä½ç½®ã«è¨­å®š" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "ボタンを待ã¤" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "スキャンコマンドをé€ä¿¡å¾Œã€å®Ÿéš›ã«èµ°æŸ»å‡¦ç†ãŒå§‹ã¾ã‚‹ã€ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã®ãƒœã‚¿ãƒ³ãŒæŠ¼" "ã•れるã®ã‚’ã¾ã¤ã€‚" #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "ãƒã‚¸ã‚¹ãƒ©ã‚¤ãƒ‰" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "ãƒã‚¬ã‚¹ãƒ©ã‚¤ãƒ‰" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "ユーザ定義" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "オン" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "オフ" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "ディザー" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "エラー拡散" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "ホワイトレベル" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "黒レベル" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "æ¡ä»¶ä»˜ã" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "æ°´å¹³ã®" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "æ°´å¹³ã®" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "æ°´å¹³ã®" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "垂直ã®" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "垂直ã®" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "ADF表é¢" #: backend/fujitsu.c:718 #, fuzzy, no-c-format msgid "Back" msgstr "ADFè£é¢" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "網版" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "較正ã®å®Ÿè¡Œ" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "ç”»åƒå¼·èª¿" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "彩度" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "ç·šç”»ã®èµ°æŸ»ã§é–¾å€¤ã®è‡ªå‹•判定を有効ã«ã™ã‚‹" #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "é¡åƒç”»åƒ" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "æ°´å¹³ã«é¡åƒã‚’ã¨ã‚‹ã€‚" #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "ホワイトレベルã®é’値" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "赤レベルã®åˆ¶å¾¡" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "カラーフィルタ" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "スムージング" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "ガンマ値" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "閾値" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "閾値" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "ノイズ除去" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "補正をã—ãªã„" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "補正をã—ãªã„" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "ADFã®ã‚«ãƒãƒ¼ãŒé–‹ã„ã¦ã„ã¾ã™" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "上級オプション" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "補正をã—ãªã„" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "å–り出ã—å£" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "フィーダーモード" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "ランプをオフã«ã™ã‚‹æ™‚é–“" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "赤オフセット" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "緑オフセット" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "緑オフセット" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "" #: backend/fujitsu.c:3967 #, no-c-format msgid "Adjust blue/red offset" msgstr "" #: backend/fujitsu.c:3980 #, fuzzy, no-c-format msgid "Low Memory" msgstr "メモリä¸è¶³" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "両é¢ã‚¹ã‚­ãƒ£ãƒ³" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "上級オプション" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "ノイズ除去" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "ç´™ã‹ã‚‰" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "ç´™ã‹ã‚‰" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "ç´™ã‹ã‚‰" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "ç´™ã‹ã‚‰" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "スキャナーã®ã‚«ãƒãƒ¼ãŒé–‹ã„ã¦ã„ã¾ã™" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "手動焦点ä½ç½®" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "手動焦点ä½ç½®" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢ãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "ホワイトレベル" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "濃度制御" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "濃度制御" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "両é¢ã‚¹ã‚­ãƒ£ãƒ³" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "追加" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "水平解åƒåº¦ãŒåž‚ç›´è§£åƒåº¦ã‚ˆã‚Šä½Žã„よã†ãªé«˜è§£åƒåº¦ã‚’使ã†ã¨ãã¯ã€æ°´å¹³" "interpolationを無効ã«ã—ã¾ã™ã€‚" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "カラーフィルタ" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "æ ¡æ­£" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "較正を「ã™ãã«ã€å®Ÿè¡Œã—ã¾ã™" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "較正データã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "ランプをオフã«ã™ã‚‹æ™‚é–“" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "ãƒ©ãƒ³ãƒ—ã¯æŒ‡å®šã•ã‚ŒãŸæ™‚間(分)ãŒçµŒéŽã—ãŸã‚‰ã‚ªãƒ•ã«ã•れã¾ã™ã€‚値ãŒï¼ã®ã¨ãã¯ã€" "ã“ã®æ©Ÿèƒ½ã¯åƒãã¾ã›ã‚“。" #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "ダーク補正時ã«ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "走査ã—ãŸå¾Œã€ãƒ©ãƒ³ãƒ—ãŒã‚ªãƒ•ã«ãªã‚‹ã¾ã§ã®æ™‚間(分)" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "ファイルボタン" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "OCRボタン" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "é›»æºãƒœã‚¿ãƒ³" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "é›»å­ãƒ¡ãƒ¼ãƒ«ãƒœã‚¿ãƒ³" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "較正ã®ã‚¯ãƒªã‚¢" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "走査å‰ã«ã‚¹ã‚­ãƒ£ãƒŠã®æ ¡æ­£ã‚’強制ã™ã‚‹" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "ボタン" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "較正" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "特殊シートを用ã„ãŸè£œæ­£ã‚’é–‹å§‹" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "較正ã®ã‚¯ãƒªã‚¢" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "校正キャッシュを消去ã™ã‚‹" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "é€éŽã‚¢ãƒ€ãƒ—ター" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "グレーモード色" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "ã©ã®è‰²ã‚’用ã„ã¦ã‚°ãƒ¬ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã‚’実ç¾ã™ã‚‹ã‹ã‚’é¸æŠžï¼ˆæ—¢å®šï¼šç·‘ï¼‰" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "デãƒãƒƒã‚°ã‚ªãƒ—ション" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "自動暖機" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "ï¼–ï¼ç§’ã®æš–æ©Ÿæ™‚間を使ã†ä»£ã‚りã«ã€ãƒ©ãƒ³ãƒ—ã®è¼åº¦ãŒä¸€å®šã«ãªã‚‹ã¾ã§æš–機ã—ã¾ã™ã€‚" #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "全走査" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "補正領域をå«ã‚ã¦ã€å…¨é ˜åŸŸã‚’走査ã—ã¾ã™ã€‚注æ„ï¼šå…¨é«˜ã‚’é¸æŠžã—ãªã„ã“ã¨ã€‚ã“れã¯" "テスト用ã§ã™ã€‚" #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "ç²—æ ¡æ­£" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "自動走査ã®åˆ©å¾—ã¨ã‚ªãƒ•セットを設定ã™ã‚‹ã€‚ã‚‚ã—ã€ã“ã®ã‚ªãƒ—ションãŒä¸å¯ã«ã•れã¦" "ã„ã‚‹ã¨ãã¯ã€ã‚¢ãƒŠãƒ­ã‚°ãƒ•ロントエンドパラメータã®è¨­å®šã®é¸æŠžè‚¢ã¯ã€æ‰‹å‹•ã§è¨­å®š" "ãŒå¿…è¦ã§ã™ã€‚ã“ã®ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã¯æ—¢å®šã§æœ‰åйã«ã•れã¦ã„ã¾ã™ã€‚テスト用途ã§å­˜åœ¨ã™" "るオプションã§ã™ã€‚" #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "粗調整を最åˆã®èµ°æŸ»ã ã‘行ã†" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "ガンマ値" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "ã™ã¹ã¦ã®ãƒãƒ£ãƒãƒ«ã®ã‚¬ãƒ³ãƒžå€¤ã‚’設定" #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "é…置グループ" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "スキャンモードグループ" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "スライド" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "スキャナーモデル" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "イメージカラーãŒå転ã•れã¾ã™" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "ガンマ補正を無効" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "ガンマ補正ã¯ç„¡åйã«ã•れã¾ã™" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "ホワイト・シェーディング較正を無効" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "白シャドー補正ã¯ç„¡åйã«ã•れã¾ã™ã€‚" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "暖機プロセスをスキップ" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "暖機プロセスãŒç„¡åйã«ãªã‚Šã¾ã™" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "çœŸã®æ·±åº¦ã‚’強制ã—ã¾ã™ã€‚" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "ã‚¬ãƒ³ãƒžãŒæœ‰åйã§ã‚れã°ã€ç”»åƒå“質を高ã‚ã‚‹ãŸã‚ã€èµ°æŸ»ã¯ã¤ã­ã«ï¼‘6ビット深度ã§" "行ã‚れã¾ã™ã€‚ãれã‹ã‚‰ã€é¸æŠžã•れãŸè‰²æ·±åº¦ã«å¤‰æ›ã•れã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションã¯ã€" "深度エミュレーションを回é¿ã—ã¾ã™ã€‚" #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "グレースケールã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆ" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "有効ã«ãªã‚‹ã¨ã€ç”»åƒã¯ã‚«ãƒ©ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§èµ°æŸ»ã•れã€ã‚°ãƒ¬ãƒ¼ã‚¹ã‚±ãƒ¼ãƒ«ã«ã‚½ãƒ•トウエア" "ã«ã‚ˆã£ã¦å¤‰æ›ã•れã¾ã™ã€‚ã“れã¯ã€ä¸€éƒ¨ã®ç’°å¢ƒã§ã¯ã€ç”»åƒå“質を高ã‚ã‚‹ã“ã¨ãŒã‚り" "ã¾ã™ã€‚" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "デãƒãƒƒã‚°ã‚¤ãƒ¡ãƒ¼ã‚¸ã®ä¿å­˜" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "有効ã«ãªã‚‹ã¨ã€ã‚¹ã‚­ãƒ£ãƒŠãŒå‡¦ç†ã™ã‚‹ç”»åƒã®ä¸€éƒ¨ãŒã€åˆ†æžã®ãŸã‚ã«ä¿å­˜ã•れã¾ã™ã€‚" #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "ãƒãƒƒãƒ—セットã®ãƒªã‚»ãƒƒãƒˆ" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "ãƒãƒƒãƒ—セットデータをリセット" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "情報" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "ãƒãƒƒãƒ—セットå" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "装置ã«ä½¿ã‚れã¦ã„ã‚‹ãƒãƒƒãƒ—セットåを表示ã™ã‚‹ã€‚" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "䏿˜Ž" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "ãƒãƒƒãƒ—セットID" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "ãƒãƒƒãƒ—セットIDを表示" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "走査カウンター" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "スキャナーãŒè¡Œã£ãŸèµ°æŸ»å›žæ•°ã‚’表示ã—ã¾ã™ã€‚" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "情報更新" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "è£…ç½®ã®æƒ…報を更新" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "ç”»åƒ" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "å„種" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "オフセットX" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "走査領域ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢ã®å†…部Xä½ç½®" #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "オフセットY" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "走査領域ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢å†…部Yä½ç½®" #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "ランプã®çŠ¶æ…‹" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "ランプã®ã‚ªãƒ•ï¼ã‚ªãƒ³ã‚’切り替ãˆ" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "白黒レベルを較正" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMAスライド" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMAãƒã‚¬" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "カラー(48ビット)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "ãƒ©ãƒ³ãƒ—ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã®æ‹¡å¤§" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "ボタン待ã¡" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "上級オプション" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "ç²—" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "密" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "ãƒã‚¤ã‚¨ãƒ«" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "カスタム" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "自動" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSCæ–¹å¼RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPAæ–¹å¼RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "パススルー" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSCã®ã‚°ãƒ¬ãƒ¼" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPAã®ã‚°ãƒ¬ãƒ¼" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "é…ã„" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "普通" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "速ã„" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "超高速" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2ピクセル" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4ピクセル" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8ピクセル" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "å°åˆ·" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "フィルムã®ä¸€ç‰‡" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "æ¡ä»¶ä»˜ã" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "実験的" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "鮮鋭化" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "鮮鋭化値を設定" #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "自動閾値" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "ç·šç”»ã®èµ°æŸ»ã§é–¾å€¤ã®è‡ªå‹•判定を有効ã«ã™ã‚‹" #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "ã‚¹ãƒ ãƒ¼ã‚¸ãƒ³ã‚°ãƒ•ã‚£ãƒ«ã‚¿ã‚’é¸æŠž" #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "走査後ã€ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’å–り出ã™" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "走査後ã«ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’å–り出ã™ã€‚" #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "書類をæ›ãˆã‚‹ã€‚" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "書類をå–りæ›ãˆã‚‹ã€‚" #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "å–り出ã—" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "書類ã®å–り出ã—" #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "校正プロセスを開始。" #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "メディア" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "メディアã®ç¨®é¡žã‚’設定" #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "露出時間" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "カラーマトリックス" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "スキャナーã®ã‚«ãƒ©ãƒ¼ãƒžãƒˆãƒªãƒƒã‚¯ã‚¹ã‚’設定ã™ã‚‹ã€‚" #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "カスタムカラーマトリックス" #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "モノクロ・カラーマトリックス" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "グレースケール走査ã®ã‚«ã‚¹ã‚¿ãƒ ãƒ»ã‚«ãƒ©ãƒ¼ãƒžãƒˆãƒªãƒƒã‚¯ã‚¹" #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "æ°´å¹³ã®é¡åƒ" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "æ°´å¹³ã«é¡åƒã‚’ã¨ã‚‹ã€‚" #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "垂直é¡åƒ" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "垂直ã«é¡åƒã‚’ã¨ã‚‹ã€‚" #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã®æ›´æ–°" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "オプションを更新ã™ã‚‹ã€‚" #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8ビット出力" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "å‰é¢ãƒœã‚¿ãƒ³ã‚’å¾…ã¤" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "ランプã®åœæ­¢" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "スキャナーã®ãƒ©ãƒ³ãƒ—ã‚’åœæ­¢ã™ã‚‹ã€‚" #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "紙サイズ" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5横" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "濃度制御モードを設定" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "手動焦点ä½ç½®" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "両é¢èµ°æŸ»ã‚’有効ã«ã™ã‚‹ã€‚" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "ADFã«ã‚ã‚‹ç´™ã®ç‰©ç†ã‚µã‚¤ã‚º" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "網版" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "カラー" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "æ¡ä»¶ä»˜ã" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "オフ" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "ãƒã‚¤ã‚¨ãƒ«" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "ãƒã‚¤ã‚¨ãƒ«" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "網版" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "網版" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "エラー拡散" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "普通" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "ãƒã‚¤ãƒ©ã‚¤ãƒˆ" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "フィルムスキャナー" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "ç´™ã‹ã‚‰" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "既定" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "スムース" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "é…ã„" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "中" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "赤" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "ç·‘" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "走査æº" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "フィーダーモード" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "シートé€ã‚Šãƒ¢ãƒ¼ãƒ‰ã®è¨­å®š" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "自動焦点を有効ï¼ç„¡åй" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "濃度制御モードを設定" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "シートé€ã‚Šãƒ¢ãƒ¼ãƒ‰ã®è¨­å®š" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "シートé€ã‚Šãƒ¢ãƒ¼ãƒ‰ã®è¨­å®š" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "自動閾値" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "自動的ã«è¼åº¦ã€ã‚³ãƒ³ãƒˆãƒ©ã‚¹ãƒˆã€ãƒ›ãƒ¯ã‚¤ãƒˆãƒ¬ãƒ™ãƒ«ã€ã‚¬ãƒ³ãƒžå€¤ã€ãƒŽã‚¤ã‚ºä½Žæ¸›ã¨ã‚¤ãƒ¡ãƒ¼" "ジ強調を設定ã™ã‚‹ã€‚" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "ノイズ除去" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "ç”»åƒå¼·èª¿" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "イメージ強調を設定" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "ガンマ" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "ランプをオン" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "ランプã®ã‚ªãƒ•ï¼ã‚ªãƒ³ã‚’切り替ãˆ" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "垂直ã«é¡åƒã‚’ã¨ã‚‹ã€‚" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "ガンマ補正" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "高密度å°åˆ·" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "低密度å°åˆ·" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "エラー拡散" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "補正をã—ãªã„" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "普通" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "増強" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "自動閾値" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "自動閾値" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "フレームã®é †åºã‚’設定" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "é’ã®æœ€å°è¼åº¦" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "赤をé’ã«ã‚·ãƒ•ト" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "ダイアモンド" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 ç²—Fatting" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 微細fatting" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 ãƒã‚¤ã‚¨ãƒ«" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8縦ã®ç·š" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "利得" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "カラーãƒãƒ£ãƒãƒ«ã®åˆ©å¾—設定" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "グレー利得" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "グレーãƒãƒ£ãƒãƒ«åˆ©å¾—を設定" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "赤利得" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "赤ãƒãƒ£ãƒãƒ«åˆ©å¾—を設定" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "緑利得" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "ç·‘ãƒãƒ£ãƒãƒ«åˆ©å¾—を設定" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "é’利得" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "é’ãƒãƒ£ãƒãƒ«åˆ©å¾—を設定" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "ãƒã‚¤ã‚¨ãƒ«ãƒ‡ã‚£ã‚¶ 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "ãƒã‚¤ã‚¨ãƒ«ãƒ‡ã‚£ã‚¶ 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "ãƒãƒ¼ãƒ•トーンドット32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "ãƒãƒ¼ãƒ•トーンドット64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "エラー拡散" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "モード1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "モード2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "モード3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "白サンプルã‹ã‚‰" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "スムース" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "低" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "中" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "高" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "1ページ" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "全ページ" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "シートフィーダスキャナー" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "グレースケール4ビット" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "グレースケール8ビット" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "シャドーã€ãƒŸãƒƒãƒ‰ãƒˆãƒ¼ãƒ³ã€ãƒã‚¤ãƒ©ã‚¤ãƒˆã€éœ²å…‰æ™‚é–“" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "特殊オプション" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "カラーãƒãƒ©ãƒ³ã‚¹" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "ãƒãƒƒã‚¯ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã‚’無効" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "å¹³å°ã®ãƒ©ãƒ³ãƒ—切り替ãˆ" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "å¹³å°ã®ãƒ©ãƒ³ãƒ—を切り替ãˆ" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã«ã‚ˆã‚‹è¼ƒæ­£" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "lightlid-35mmアダプターを使ã†" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "ã“ã®ã‚ªãƒ—ションã¯ã€èµ°æŸ»ä¸­ã«å¹³å°ã®ãƒ©ãƒ³ãƒ—をオフã«ã—ã¾ã™ã€‚" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "å“質優先走査" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "最高å“質ã ãŒã€ã‚¹ãƒ”ードã¯é…ã„" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "高速走査" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "最高速度ã ãŒã€å“質ã¯ä½Žã„" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "閾値ã®è‡ªå‹•判定" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "ã‚‚ã—ãƒã‚§ãƒƒã‚¯ã•れるã¨ã€ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã¯è‡ªå‹•çš„ã«æœ€é©ãªé–¾å€¤ã‚’探ãã†ã¨ã—ã¾ã™ã€‚" #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "ã‚¬ãƒ³ãƒžè£œæ­£ãƒ¢ãƒ¼ãƒ‰ã‚’é¸æŠžã™ã‚‹ã€‚" #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "ã‚¬ãƒ³ãƒžå€¤ã®æ¯”を固定" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "" #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "スカラーガンマ" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "" #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "ガンマ赤スカラー" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "ガンマ緑スカラー" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "ガンマé’スカラー" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "ãƒãƒ£ãƒãƒ«" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "" #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "赤ãƒãƒ©ãƒ³ã‚¹" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "ç·‘ãƒãƒ©ãƒ³ã‚¹" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "é’ãƒãƒ©ãƒ³ã‚¹" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "ファームウエアãƒãƒ©ãƒ³ã‚¹" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "最é…" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "é…ã" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "速ã" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "最速" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 ç²—" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 通常" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 微細" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 通常" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 通常" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 カスタム" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 カスタム" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 カスタム" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 カスタム" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 カスタム" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 カスタム" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "高速グレーモード" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "高速グレーモードã§èµ°æŸ»ï¼ˆä½Žå“質)" #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "ã™ã¹ã¦ã®ãƒ—レビューを最高速モード(低å“質)ã§è¡Œã†ã‚ˆã†ã«ã™ã‚‹ã€‚" #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "ランプオフ時間(分)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "ランプãŒåœæ­¢ã™ã‚‹ã¾ã§ã®æ™‚間(分)を設定ã™ã‚‹" #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "ランプをオフã«" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "ã™ãã«ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹ã€‚" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "赤ã®è¼åº¦" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "å–å¾—ã•れãŸç”»åƒã®èµ¤ãƒãƒ£ãƒãƒ«ã®è¼åº¦ã‚’制御ã—ã¾ã™ã€‚" #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "ç·‘ã®è¼åº¦" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "å–å¾—ã•れãŸç”»åƒã®ç·‘ãƒãƒ£ãƒãƒ«ã®è¼åº¦ã‚’制御ã—ã¾ã™ã€‚" #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "é’ã®è¼åº¦" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "å–å¾—ã•れãŸç”»åƒã®é’ãƒãƒ£ãƒãƒ«ã®è¼åº¦ã‚’制御ã—ã¾ã™ã€‚" #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "" #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "" #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "" #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "ãƒã‚¬ãƒ•ィルム" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "ãƒã‚¬" #: backend/pixma.c:396 #, fuzzy, no-c-format msgid "48 bits color" msgstr "高精彩" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "ボタン制御走査" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "ãƒœã‚¿ãƒ³çŠ¶æ…‹ã®æ›´æ–°" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "ボタン1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "ボタン2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "é€éŽæ€§" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "装置設定" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "ランプã®ã‚¹ã‚¤ãƒƒãƒ" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "ランプを手動ã§ã‚ªãƒ•オンã™ã‚‹" #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "ダーク補正時ã«ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "較正データã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "" #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "較正ã®å®Ÿè¡Œ" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "センサーをスピードアップ" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "暖機時間" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "暖機時間を秒ã§è¨­å®šã€‚" #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "ランプオフ時間" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "ランプオフ時間を秒ã§è¨­å®šã€‚" #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "アナログフロントエンド" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "AFEã®èµ¤ã®åˆ©å¾—値" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "赤オフセット" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "AFEã®èµ¤ã®ã‚ªãƒ•セット値" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "AFEã®ç·‘ã®åˆ©å¾—値" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "AFEã®ç·‘ã®ã‚ªãƒ•セット値" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "AFEã®é’ã®åˆ©å¾—値" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "緑ランプをオフ" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "緑ランプオフパラメータを定義" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "é’ランプをオフ" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "é’ランプオフパラメータを定義" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "色36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "ディザ マップ1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "ディザ マップ2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "ランダマイズ" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "情報æºé¸æŠž" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "イメージ強調" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "グレー化" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "イメージをグレースケールã¨ã—ã¦èª­ã¿è¾¼ã‚€" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "3パス シミュレーション" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "3ã¤ã«åˆ†å‰²ã•れãŸãƒ•レームを返ã™ï¼“パススキャナーをシミュレートã—ã¾ã™ã€‚ãŠã‚‚" "ã—ã‚åŠåˆ†ã«ã€ç·‘ã€é’ãã—ã¦èµ¤ã®é †åºã§è¿”ã—ã¾ã™ã€‚" #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã€€ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã‚’シミュレートã—ã¾ã™ã€‚ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã¯ã€ãŸã„ã¦ã„ã®å ´" "åˆã€ã‚¤ãƒ¡ãƒ¼ã‚¸ã®é«˜ã•ãŒäº‹å‰ã«ã¯ã‚ã‹ã‚Šã¾ã›ã‚“。ãã®ä»£ã‚りã€é«˜ã•ã¨ã—ã¦ãƒ¼ï¼‘ã‚’è¿”" "ã—ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションを設定ã™ã‚‹ã¨ã€ãƒ•ãƒ­ãƒ³ãƒˆã‚¨ãƒ³ãƒ‰ãŒæ­£ã—ããれを扱ãˆã‚‹" "ã‹ã€ãƒ†ã‚¹ãƒˆã—ã¾ã™ã€‚" #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "ガンマテーブル" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "ステータスコード シミュレーション" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "ステータスコードを強制ã—ãªã„" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "" #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "SANE_STATUS_EOFã‚’è¿”ã™ã€‚" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã«å¯¾ã—ã€sane_read()ãŒå‘¼ã°ã‚ŒãŸå¾Œã«ã€ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚³ãƒ¼ãƒ‰ã¨ã—ã¦ã€" "SANE_STATUS_EOFã‚’è¿”ã™ã‚ˆã†å¼·åˆ¶ã™ã‚‹ã€‚" #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "SANE_STATUS_JAMMEDã‚’è¿”ã™" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã«å¯¾ã—ã¦ã€ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚³ãƒ¼ãƒ‰ã¨ã—ã¦SANE_STATUS_JAMMEDã‚’è¿”ã™ã‚ˆã†" "ã«å¼·åˆ¶ã™ã‚‹ã€‚" #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "SANE_STATUS_NO_DOCSã‚’è¿”ã™" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "sane_read()ãŒå‘¼ã°ã‚ŒãŸå¾Œã€SANE_STATUS_NO_DOCS状態コードを返ã™ã‚ˆã†ãƒãƒƒã‚¯ã‚¨" "ンドを強制ã—ã¾ã™ã€‚" #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "SANE_STATUS_COVER_OPENã‚’è¿”ã™" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "SANE_STATUS_IO_ERRORã‚’è¿”ã™" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "SANE_STATUS_NO_MEMã‚’è¿”ã™" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "SANE_STATUS_ACCESS_DENIEDã‚’è¿”ã™" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "ã“ã®ã‚ªãƒ—ションã¯ã€ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ãƒœã‚¿ãƒ³ã®çŠ¶æ…‹ã‚’åæ˜ ã—ã¾ã™ã€‚" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "ランプをオン" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "スキャナーã®ãƒ©ãƒ³ãƒ—をオンã«ã™ã‚‹ã€‚" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "ランプオフ" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "スキャナーã®ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹ã€‚" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "ランプãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ãŸ" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "走査ã—ãŸå¾Œã€ãƒ©ãƒ³ãƒ—ãŒã‚ªãƒ•ã«ãªã‚‹ã¾ã§ã®æ™‚間(分)" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "線画モードã®é–¾å€¤" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "書類é€ã‚Šè£…ç½®" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "ï¼–x4(インãƒï¼‰" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10(インãƒï¼‰" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11(インãƒï¼‰" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "ãƒãƒ¼ãƒ•トーンã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "èµ°æŸ»å¾Œã€æ›¸é¡žã‚’排出" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "プレビューモード" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "ãƒ—ãƒ¬ãƒ“ãƒ¥ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã‚’é¸æŠžã€‚ã‚°ãƒ¬ãƒ¼ã‚¹ã‚±ãƒ¼ãƒ«ãƒ—ãƒ¬ãƒ“ãƒ¥ãƒ¼ãŒé€šå¸¸ã‚‚ã£ã¨ã‚‚よã„速度ã¨" "詳細ã•ã‚’æä¾›ã—ã¾ã™ã€‚" #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "事å‰å®šç¾©ã•れãŸè¨­å®š" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "写真やå°åˆ·ç‰©ãªã©ã®æ¨™æº–çš„ãªèµ°æŸ»é ˜åŸŸã‚’æä¾›ã—ã¾ã™ã€‚" #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "フラットベッド(平å°åž‹ï¼‰ã‚¹ã‚­ãƒ£ãƒŠ" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "焦点" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "自動焦点" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "焦点ä½ç½®" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "焦点ä½ç½®" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "ウエブカメラ" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "カラー RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "カラーRGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "カラーRGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "カラーパターン" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "グリッド" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "最åˆã®ã‚¨ãƒ³ãƒˆãƒªãƒ¼" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "ï¼’ã¤ã‚ã®ã‚¨ãƒ³ãƒˆãƒªãƒ¼" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã‚’シミュレート" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "3パスシミュレーション" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "3パススキャナーをシミュレート。カラーモードã«ãŠã„ã¦ã€ï¼“フレームãŒè»¢é€ã•" "れる。" #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "フレームã®é †åºã‚’設定" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "3パスカラーモードã«ãŠã„ã¦ã€ãƒ•レームã®é †åºã‚’設定。" #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "特殊オプション" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "テスト画åƒã‚’é¸æŠž" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "エンディアンをå転" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "読ã¿å–り制é™" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "sane_read()ã®å‘¼ã³å‡ºã—ã”ã¨ã«è»¢é€ã§ãるデータé‡ã®åˆ¶é™" #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "読ã¿è¾¼ã¿åˆ¶é™ã‚µã‚¤ã‚º" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "å„sane_read()ã«ãŠã‘る転é€ã§ãる(最大)データé‡" #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "読ã¿å–りé…å»¶" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "パイプã«ãƒ‡ãƒ¼ã‚¿ã‚’転é€ã™ã‚‹é…å»¶" #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "読ã¿å–りé…å»¶ã®å¤§ãã•" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "パイプを通ã—ã¦å„データã®ãƒãƒƒãƒ•ã‚¡ãŒè»¢é€ã•れãŸå¾Œã€ã©ã‚Œãらã„å¾…ã¤ã‹ã€‚" #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "sane_readã®è¿”値" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "ラインã”ã¨ã®ãƒ”ã‚¯ã‚»ãƒ«ã®æå¤±" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "" #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "曖昧ãªãƒ‘ラメータ" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "sane_start()を呼ã³å‡ºã™å‰ã«ã€sane_parameters()を呼んã ã¨ãã«ã€æ›–昧ãªãƒ©ã‚¤ãƒ³" "ã‚„ãã®ãƒ©ã‚¤ãƒ³ã«å¯¾ã—ã¦æ›–昧ãªãƒã‚¤ãƒˆã‚’è¿”ã™ã€‚" #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "ノンブロッキングIOを使ã†" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "フロントエンドãŒã‚µãƒãƒ¼ãƒˆã™ã‚‹ã¨ãã¯ã€sane_read()ã«ãƒŽãƒ³ãƒ–ロッキングIOを使" "ã†ã€‚" #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "ファイルディスクリプタã®é¸æŠžã‚’æä¾›ã™ã‚‹" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "sane_read()ãŒãƒ‡ãƒ¼ã‚¿ã‚’è¿”ã™ã‹ã©ã†ã‹æ¤œå‡ºã™ã‚‹ãŸã‚ã®ã€ãƒ•ァイルディスクリプタã®" "é¸æŠžã‚’æä¾›ã™ã‚‹ã€‚" #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "テストオプション有効" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "様々ãªãƒ†ã‚¹ãƒˆã‚ªãƒ—ションを有効ã«ã—ã¾ã™ã€‚ã“れã¯ã€ãƒ•ロントエンドãŒã€ã™ã¹ã¦ã®" "ç•°ãªã‚‹SANEオプションタイプã®è¡¨ç¤ºã‚„変更ãŒã§ãã‚‹ã‹ãƒ†ã‚¹ãƒˆã™ã‚‹ç”¨é€”ã§ä½¿ã‚れã¾" "ã™ã€‚" #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "オプション表示" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "ã™ã¹ã¦ã®ã‚ªãƒ—ションã®ãƒªã‚¹ãƒˆã‚’表示ã™ã‚‹ã€‚" #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "" #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "" #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "" #, fuzzy #~ msgid "IPC mode" #~ msgstr "プレビューモード" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "å•題ãŒè§£æžã§ãã¾ã›ã‚“ã§ã—ãŸï¼ˆä¸æ˜ŽãªSCSIクラス)" #~ msgid "Grayscale" #~ msgstr "グレースケール" #~ msgid "Binary" #~ msgstr "ãƒã‚¤ãƒŠãƒª" #~ msgid "Display a shortened resolution list" #~ msgstr "è§£åƒåº¦ã®çŸ­ç¸®ãƒªã‚¹ãƒˆã‚’表示" #~ msgid "Black & White" #~ msgstr "白黒" sane-backends-1.0.27/po/cs.po0000664000175000017500000044746513110600533012621 00000000000000# Czech translation for SANE backend options # Copyright (C) 2003 SANE Project. # Josef , 2003 msgid "" msgstr "" "Project-Id-Version: sane-backends.cs\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-12-17 22:59+0100\n" "Last-Translator: Josef \n" "Language-Team: \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 0.9.5\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Množství voleb" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometrie" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "VylepÅ¡ení" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "PokroÄilé" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Náhled" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Vynutit monochromatický náhled" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bitová hloubka" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Režim skenu" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Rychlost skenu" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Zdroj" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Skenovat pÅ™i zpÄ›tném chodu" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Levý horní roh x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Levý horní roh y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Pravý dolní roh x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Pravý dolní roh y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "RozliÅ¡ení" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "RozliÅ¡ení X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "RozliÅ¡ení Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, fuzzy, no-c-format msgid "Page height" msgstr "SvÄ›tlé body" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Použít uživatelskou tabulku gama" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Intenzita obrázku" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Intenzita Äervené" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Intenzita zelené" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Intenzita modré" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Jas" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "RozmÄ›r zrna" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Polotóny" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Úroveň Äerné" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Úroveň bílé" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Úroveň bílé Äervené" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Úroveň bílé zelené" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Úroveň bílé modré" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Stíny" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Stíny Äervené" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Stíny zelené" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Stíny modré" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "SvÄ›tlé body" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "SvÄ›tlé body Äervené" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "SvÄ›tlé body zelené" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "SvÄ›tlé body modré" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Odstín" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Sytost" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Jméno souboru" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "RozmÄ›r vzorku polotónu" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Vzorek polotónu" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Svázat rozliÅ¡ení X a Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativ" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Kalibrace kvality" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Dvojnásobné optické rozliÅ¡ení" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Svázat RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Prahová hodnota" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analogová korekce gama" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analogová korekce gama pro Äervenou" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analogová korekce gama pro zelenou" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analogová korekce gama pro modrou" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Svázat analogovou hodnotu gama" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Zahřát lampu" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Kalibr. expoziÄní Äas" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Kalibr. expoziÄní Äas pro Äervenou" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Kalibr. expoziÄní Äas pro zelenou" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Kalibr. expoziÄní Äas pro modrou" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Zjistit expoziÄní Äas" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Zjistit expoziÄní Äas pro Äervenou" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Zjistit expoziÄní Äas pro zelenou" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Zjistit expoziÄní Äas pro modrou" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Nastavit expoziÄní Äas" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Kalibrovat svítivost (density) lampy" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Zjistit svítivost (density) lampy" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Nastavit svítivost (density) lampy" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Vypnout lampu pÅ™i ukonÄení" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Hodnota pouze pro Ätení, která udává, kolik voleb dané zařízení " "podporuje." #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Zkrácený seznam rozliÅ¡ení" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "Množství voleb" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "RozliÅ¡ení" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Požaduje sken v kvalitÄ› náhledu." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Požaduje, aby se vÅ¡echny náhledy provádÄ›ly v monochromatickém režimu. Na " "trojprůchodovém skeneru to snižuje poÄet průchodů na jeden, na " "jednoprůchodovém skeneru to snižuje paměťové nároky a Äas skenování " "náhledu." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "PoÄet bitů na vzorek, typicky je 1 pro \"perokresbu\" a 8 pro vícebitové " "skeny." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Zvolí režim skenování (tj. perokresba, stupnÄ› Å¡edé nebo barva)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "UrÄuje, jakou rychlostí se skenuje." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Volí zdroj skenování (napÅ™. automatický podavaÄ)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Nastavuje, zda je povolen ypÄ›tný průchod." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Levý horní roh x skenované plochy." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Levý horní roh y skenované plochy." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Pravý dolní roh x skenované plochy." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Pravý dolní roh y skenované plochy." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Nastavuje rozliÅ¡ení skenovaného obrázku." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Nastavuje horizontální rozliÅ¡ení skenovaného obrázku." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Nastavuje vertikální rozliÅ¡ení skenovaného obrázku." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, fuzzy, no-c-format msgid "Specifies the height of the media." msgstr "Nastavuje rozliÅ¡ení skenovaného obrázku." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Volí, zda má být použita vestavÄ›ná nebo uživatelem definovaná tabulka " "gama korekcí." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Tabluka gama korekcí. V barevném režimu ovlivňuje Äervený, zelený a " "modrý kanál souÄasnÄ› (tj. jde o tabulku gama korekcí intenzity)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Tabulka gama korekcí pro Äervené pásmo." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Tabulka gama korekcí pro zelené pásmo." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Tabulka gama korekcí pro modré pásmo." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Ovládá jas naskenovaného obrázku." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Ovládá kontrast naskenovaného obrázku." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Ovládá \"zrnitost\" naskenovaného obrázku. Nižší hodnoty znamenají " "ostÅ™ejší obrázek." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Volí, zda naskenovaný obrázek má být pÅ™eveden na Äernobílý pomocí " "rozptylu." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Nastavuje, jaká úroveň jasu má být považována za \"Äernou\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Nastavuje, jaká úroveň jasu má být považována za \"bílou\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "Nastavuje, jaká úroveň Äervené má být považována za \"bílou\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "Nastavuje, jaká úroveň zelené má být považována za \"bílou\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "Nastavuje, jaká úroveň modré má být považována za \"bílou\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "Nastavuje, jaká úroveň Äervené má být považována za \"Äernou\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "Nastavuje, jaká úroveň zelené má být považována za \"Äernou\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "Nastavuje, jaká úroveň modré má být považována za \"Äernou\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Nastavuje, jaká úroveň Äervené má být považována za \"zcela Äervenou\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Nastavuje, jaká úroveň zelené má být považována za \"zcela zelenou\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Nastavuje, jaká úroveň modré má být považována za \"zcela modrou\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Nastavuje \"odstín\" (úroveň modré) naskenovaného obrázku." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Úroveň nasycení ovládá úroveň \"sytosti\" barev, obzvláštÄ› patrné u " "fotografií. Vyšší hodnoty znamenají výraznÄ›jší barvy." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Jméno souboru obrázku, který bude naÄten." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Nastaví rozmÄ›r polotónového (rozptylového) vzoru pÅ™i skenování " "polotónových obrázků." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Definuje polotónový (rozptylový) vzor pÅ™i skenování polotónových obrázků." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Použít shodné rozliÅ¡ení pro osu X a Y" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "ZamÄ›nit Äernou a bílou" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Provést kvalitní kalibraci bílé" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Použít dvojité optické rozližení objektivu" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "V režimu RGB použít stejné hodnoty pro vÅ¡echny barvy" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Zvolit minimální jas pro bílý bod" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analogová korekce gama" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analogová korekce gama pro Äervenou" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analogová korekce gama pro zelenou" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analogová korekce gama pro modrou" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Zahřát lampu pÅ™ed skenováním" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Nastavit expoziÄní dobu pro kalibraci" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Nastavit expoziÄní dobu pro kalibraci Äervené" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Nastavit expoziÄní dobu pro kalibraci zelené" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Nastavit expoziÄní dobu pro kalibraci modré" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Nastavit expoziÄní dobu pro sken" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Nastavit expoziÄní dobu pro sken Äervené" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Nastavit expoziÄní dobu pro sken zelené" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Nastavit expoziÄní dobu pro sken modré" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Povolit volbu expoziÄních Äasů" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Definovat svítivost (density) lampy pro kalibraci" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Definovat svítivost (density) lampy pro sken" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Povolit volbu svítivosti (density) lampy" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Vypnout lampu pÅ™i ukonÄení programu" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "RozliÅ¡ení" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "ÄŒekat na tlaÄítko" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "ÄŒekat na tlaÄítko" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "ÄŒekat na tlaÄítko" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Barevný vzorek" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Barva" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Barevná perokresba" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Barevný polotón" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Å edá" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Polotóny" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Perokresba" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, fuzzy, no-c-format msgid "Operation not supported" msgstr "Polotón není podporován" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "PodavaÄ dokumentů" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "PodavaÄ dokumentů" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Standardní nastavení" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Nastavit standardní hodnoty prvků pro vylepÅ¡ení obrázku" #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibrace" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Kalibrovat pÅ™ed dalším skenem" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Pokud je zvolena tato volba, je skener kalibrován pÅ™ed každým dalším " "skenem. Jinak se kalibruje pouze pÅ™ed prvním skenem." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Provést pouze korekci stínů" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Pokud je tato volba zapnuta, pÅ™i kalibraci se provede pouze korekce " "stínů. Pro zisk, odstup a expozici jsou použity standardní hodnoty - buÄ " "vestavÄ›né nebo z konfiguraÄního souboru." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Stav tlaÄítek" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Číslo políÄka pro sken" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Zvolí Äíslo políÄka, které bude naskenováno" #: backend/avision.h:782 #, fuzzy, no-c-format msgid "Duplex scan" msgstr "OboustranÄ›" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Kalibrovat skener" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Vynutit kalibraci skeneru pÅ™ed skenováním" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "StupnÄ› Å¡edé" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Skenovat ve stupních Å¡edé místo v barvÄ›" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analogový zisk" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Zvýšit nebo snížit analogový zisk CCD pole" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Korekce gama" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Nastaví gama korekci pÅ™enosové kÅ™ivky" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, fuzzy, no-c-format msgid "No transparency correction" msgstr "Barevná korekce" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, fuzzy, no-c-format msgid "Negatives" msgstr "Negativ" #: backend/canon.c:176 #, fuzzy, no-c-format msgid "Slides" msgstr "Zcela bílá" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automaticky" #: backend/canon.c:186 #, fuzzy, no-c-format msgid "Normal speed" msgstr "Normální" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/2 normal speed" msgstr "2x2 normální" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/3 normal speed" msgstr "3x3 normální" #: backend/canon.c:365 #, fuzzy, no-c-format msgid "rounded parameter" msgstr "NepÅ™esné (fuzzy) parametry" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, fuzzy, no-c-format msgid "lamp failure" msgstr "Hodnota gama" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, fuzzy, no-c-format msgid "transparency unit lamp failure" msgstr "ProsvÄ›tlovací jednotka" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, fuzzy, no-c-format msgid "transparency unit shading error" msgstr "ProsvÄ›tlovací jednotka" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, fuzzy, no-c-format msgid "film scanner" msgstr "Stolní skener" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "Stolní skener" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Typ filmu" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, fuzzy, no-c-format msgid "Negative film type" msgstr "Negativní film" #: backend/canon.c:1197 #, fuzzy, no-c-format msgid "Selects the negative film type" msgstr "Zvolit testovací obrázek" #: backend/canon.c:1236 #, fuzzy, no-c-format msgid "Hardware resolution" msgstr "RozliÅ¡ení" #: backend/canon.c:1237 #, fuzzy, no-c-format msgid "Use only hardware resolutions" msgstr "Zobrazí zkrácený seznam rozliÅ¡ení" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, fuzzy, no-c-format msgid "Auto focus" msgstr "Automaticky vysunout" #: backend/canon.c:1329 #, fuzzy, no-c-format msgid "Enable/disable auto focus" msgstr "VyÅ™adit pÅ™edběžné zaostÅ™ení" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, fuzzy, no-c-format msgid "Manual focus position" msgstr "Pozice pevného zaostÅ™ení" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Zrcadlit obrázek" #: backend/canon.c:1539 #, fuzzy, no-c-format msgid "Mirror the image horizontally" msgstr "Zrcadlit obrázek" #: backend/canon.c:1608 #, fuzzy, no-c-format msgid "Auto exposure" msgstr "Nastavit expoziÄní Äas" #: backend/canon.c:1609 #, fuzzy, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Povolit volbu expoziÄních Äasů" #: backend/canon.c:1625 #, fuzzy, no-c-format msgid "Calibration now" msgstr "Kalibrace" #: backend/canon.c:1626 #, fuzzy, no-c-format msgid "Execute calibration *now*" msgstr "Definovat režim kalibrace" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, fuzzy, no-c-format msgid "Reset scanner" msgstr "skener s podavaÄem" #: backend/canon.c:1649 #, fuzzy, no-c-format msgid "Reset the scanner" msgstr "skener s podavaÄem" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, fuzzy, no-c-format msgid "Eject film after each scan" msgstr "Vysunout dokument po naskenování" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, fuzzy, no-c-format msgid "Document feeder extras" msgstr "PodavaÄ dokumentů" #: backend/canon.c:1707 #, fuzzy, no-c-format msgid "Flatbed only" msgstr "Stolní" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, fuzzy, no-c-format msgid "Transparency unit" msgstr "ProsvÄ›tlovací jednotka" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, fuzzy, no-c-format msgid "Negative film" msgstr "Negativní film" #: backend/canon.c:1740 #, fuzzy, no-c-format msgid "Positive or negative film" msgstr "Pozitivní film" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, fuzzy, no-c-format msgid "Transparency ratio" msgstr "ProsvÄ›tlovací jednotka" #: backend/canon.c:1775 #, fuzzy, no-c-format msgid "Select film type" msgstr "Typ filmu" #: backend/canon.c:1776 #, fuzzy, no-c-format msgid "Select the film type" msgstr "Zvolit polotóny" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Stolní" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, fuzzy, no-c-format msgid "ADF Duplex" msgstr "OboustranÄ›" #: backend/canon_dr.c:412 #, no-c-format msgid "Card Front" msgstr "" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "OboustranÄ›" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "ÄŒervená" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Zelená" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Modrá" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "VylepÅ¡ení" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "VylepÅ¡ení" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "VylepÅ¡ení" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Žádné" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "JednostranÄ›" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "OboustranÄ›" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "ProsvÄ›tlovací jednotka" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatický podavaÄ dokumentů" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Pozitivní film" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negativní film" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "ZaostÅ™ení na sklo" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "ZaostÅ™ení 2,5 mm nad sklo" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Polotón A (ostrý)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Polotón B (mÄ›kký)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Polotón C (síť - \"Net Screen\")" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Rozptyl A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Rozptyl B (4x4 Spirálový)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Rozptyl C (4x4 Síťový)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Rozptyl D (8x4 Síťový)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Technika vylepÅ¡ení textu" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Download vzor A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Download vzor B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Bez korekce" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Uživatelské nastavení" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "JehliÄkové tiskárny" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Teplocitlivé tiskárny" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Inkoustové tiskárny" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT monitory" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Standard" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Tisk ve vysoké kvalitÄ›" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Tisk v nízké kvalitÄ›" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Tisk s vysokým kontrastem" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Uživatelsky definováno (Gama=1,0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Uživatelsky definováno (Gama=1,8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 na výšku" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 na šířku" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Max" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Režim skenování" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Zvolit polotóny" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Výpadek" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Nastaví výpadek." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Nastaví jas." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "ZaostÅ™ení" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Barevná korekce" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Nastaví tabulku barevných korekcí pro vybrané výstupní zařízení." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Koeficienty barevných korekcí" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Násobící matice RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Posun zelená-Äervená" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Posun zelená-modrá" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Posun Äervená-zelená" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Posun Äervená-modrá" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Posun modrá-zelená" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Posun modrá-Äervená" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Ovládá úroveň zelené" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "PÅ™idává Äervenou v závislosti na úrovni zelené" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "PÅ™idává modrou v závislosti na úrovni zelené" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "PÅ™idává zelenou v závislosti na úrovni Äervené" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Ovládá úroveň Äervené" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "PÅ™idává modrou v závislosti na úrovni Äervené" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "PÅ™idává zelenou v závislosti na úrovni modré" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "PÅ™idává Äervenou v závislosti na úrovni modré" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Ovládá úroveň modré" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Zrcadlí obrázek." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Rychlý náhled" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Automatické rozložení plochy" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Zkrácený seznam rozliÅ¡ení" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Zobrazí zkrácený seznam rozliÅ¡ení" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "PÅ™iblížení" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Nastaví faktor pÅ™iblížení, který skener použije" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Rychlý formát" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Volitelné přísluÅ¡enství" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Vysunout" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Vysunout papír z automatického podavaÄe" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Automaticky vysunout" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Vysunout dokument po naskenování" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Pozice" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Zvolte pozici pro sken" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Zvolit gama korekci ze seznamu pÅ™eddefinovaných zařízení nebo " "uživatelské tabulky, kterou lze nahrát do skeneru" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Pozice zaostÅ™ení" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "Nastaví pozici zaostÅ™ení buÄ na sklo nebo 2,5 mm nad sklo" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "ÄŒekat na tlaÄítko" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Po odeslání příkazu ke skenování se s vlastním skenem Äeká až na stisk " "tlaÄítka na skeneru." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, fuzzy, no-c-format msgid "Positive Slide" msgstr "Pozitivní film" #: backend/epson2.c:137 #, fuzzy, no-c-format msgid "Negative Slide" msgstr "Negativní film" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Uživatelské nastavení" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Rozptyl" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "Chybový rozptyl" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Úroveň bílé" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Úroveň Äerné" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontální" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Horizontální" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Horizontální" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertikální" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Vertikální" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Polotóny" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Hrubá kalibrace" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "ZvýraznÄ›ní obrázku" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Sytost" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "" #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Zrcadlit obrázek" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Zrcadlit obrázek" #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Úroveň bílé modré" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Ovládá úroveň Äervené" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Barevná perokresba" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, fuzzy, no-c-format msgid "Smoothing" msgstr "Jemný" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Hodnota gama" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Prahová hodnota" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Prahová hodnota" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Redukce Å¡umu" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Bez korekce" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Bez korekce" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Režim podavaÄe" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Zvláštní volby" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Bez korekce" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Výpadek" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Režim podavaÄe" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Vypnout lampu" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Odstup modré" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Odstup zelené" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Odstup zelené" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Odstup modré" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Nastavuje odstup modrého kanálu" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "OboustranÄ›" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Zvláštní volby" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Redukce Å¡umu" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Z papíru" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Z papíru" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Z papíru" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Z papíru" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Manuální pÅ™edběžné zaostÅ™ení" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Manuální pÅ™edběžné zaostÅ™ení" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "RozliÅ¡ení" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Úroveň bílé" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Intenzita Äervené" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "OboustranÄ›" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, fuzzy, no-c-format msgid "Extras" msgstr "Velmi rychlý" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, fuzzy, no-c-format msgid "Disable interpolation" msgstr "VyÅ™adit zpÄ›tný chod" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Barevná perokresba" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibrace" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Definovat režim kalibrace" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Režim kalibrace" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, fuzzy, no-c-format msgid "Lamp off time" msgstr "Vypnout lampu" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Hrubá kalibrace" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "ÄŒekat na tlaÄítko" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "ÄŒekat na tlaÄítko" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "ÄŒekat na tlaÄítko" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Hrubá kalibrace" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Vynutit kalibraci skeneru pÅ™ed skenováním" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, fuzzy, no-c-format msgid "Buttons" msgstr "Stav tlaÄítek" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibrovat" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Hrubá kalibrace" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Hrubá kalibrace" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Režim kalibrace" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "ProsvÄ›tlovací adaptér" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Volby pro ladÄ›ní" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automaticky zahřát" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Zahřát lampu dokud její jas není konstantní namísto standardního 60ti " "sekundového zahřívání." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Plný sken" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Naskenovat kompletní skenovací plochu vÄetnÄ› kalibraÄního proužku. " "OpatrnÄ›! Nenastavujte plnou výšku! Pouze pro testování!" #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Hrubá kalibrace" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Nastavit zisk a odstup pro skenování automaticky. Pokud je toto vypnuto, " "jsou zobrazeny ovádací prvky pro mauální nastavení. Tato volba je " "standardnÄ› zapnuta. Pouze pro testování!" #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Hrubá kalibrace pouze pro první sken" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Hrubá kalibrace se provádí pouze pro první sken. Ve vÄ›tÅ¡inÄ› případů " "funguje a může zkrátit Äas skenování. Pokud se obrázek s každým dalším " "skenem mÄ›ní, vyÅ™aÄte tuto volbu. Pouze pro testování!" #: backend/gt68xx.c:654 #, fuzzy, no-c-format msgid "Backtrack lines" msgstr "Skenovat pÅ™i zpÄ›tném chodu" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Hodnota gama" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Nastavuje hodnotu gama pro vÅ¡echny kanály." #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "Geometrie" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, fuzzy, no-c-format msgid "Scan Mode Group" msgstr "Režim skenování" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, fuzzy, no-c-format msgid "Slide" msgstr "Zcela bílá" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Režim skenu" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "Analogová korekce gama" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "Korekce gama" #: backend/hp3900_sane.c:1451 #, fuzzy, no-c-format msgid "Disable white shading correction" msgstr "Provést pouze korekci stínů" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "StupnÄ› Å¡edé" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "skener s podavaÄem" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Ignorovat kalibraci" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Jméno souboru" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "skener s podavaÄem" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "Zdroj" #: backend/hp3900_sane.c:1584 #, fuzzy, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Zvolí Äíslo políÄka, které bude naskenováno" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Zvláštní volby" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Obrázek" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Různé" #: backend/hp5400_sane.c:358 #, fuzzy, no-c-format msgid "offset X" msgstr "Odstup" #: backend/hp5400_sane.c:359 #, fuzzy, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Levý horní roh x skenované plochy." #: backend/hp5400_sane.c:368 #, fuzzy, no-c-format msgid "offset Y" msgstr "Odstup" #: backend/hp5400_sane.c:369 #, fuzzy, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Levý horní roh x skenované plochy." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Stav lampy" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Zapíná a vypíná lampu." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Kalibruje úrovnÄ› Äerné a bílé." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "" #: backend/hp5590.c:88 #, fuzzy, no-c-format msgid "TMA Slides" msgstr "Zcela bílá" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Negativ" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "Barva 48" #: backend/hp5590.c:95 #, fuzzy, no-c-format msgid "Extend lamp timeout" msgstr "Vypnout lampu" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "ÄŒekat na tlaÄítko" #: backend/hp5590.c:99 #, fuzzy, no-c-format msgid "Waits for button before scanning" msgstr "Zahřát lampu pÅ™ed skenováním" #: backend/hp-option.c:2984 #, fuzzy, no-c-format msgid "Advanced Options" msgstr "Zvláštní volby" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Hrubý" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Jemný" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Volitelný" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automaticky" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Å¡edá" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA Å¡edá" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Pomalý" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normální" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Rychlý" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Velmi rychlý" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "" #: backend/hp-option.c:3175 #, fuzzy, no-c-format msgid "Film-strip" msgstr "Typ filmu" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "" #: backend/hp-option.c:3414 #, fuzzy, no-c-format msgid "Experiment" msgstr "ExpoziÄní Äas" #: backend/hp-option.h:60 #, fuzzy, no-c-format msgid "Sharpening" msgstr "ZaostÅ™ení" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "" #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Automatické nastavení prahových hodnot" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" #: backend/hp-option.h:74 #, fuzzy, no-c-format msgid "Select smoothing filter." msgstr "Zvolit polotóny" #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "" #: backend/hp-option.h:80 #, fuzzy, no-c-format msgid "Unloads the media after a scan." msgstr "NaÄíst obrázek v úrovních Å¡edé." #: backend/hp-option.h:85 #, fuzzy, no-c-format msgid "Change document" msgstr "VylepÅ¡ení" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "" #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "" #: backend/hp-option.h:98 #, fuzzy, no-c-format msgid "Start calibration process." msgstr "Hrubá kalibrace" #: backend/hp-option.h:103 #, fuzzy, no-c-format msgid "Media" msgstr "StÅ™ední" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "" #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "ExpoziÄní Äas" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" #: backend/hp-option.h:119 backend/hp-option.h:126 #, fuzzy, no-c-format msgid "Color Matrix" msgstr "Barevný vzorek" #: backend/hp-option.h:121 #, fuzzy, no-c-format msgid "Set the scanners color matrix." msgstr "Nastavuje kontrast Äerveného kanálu" #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "" #: backend/hp-option.h:132 #, fuzzy, no-c-format msgid "Mono Color Matrix" msgstr "Barevný vzorek" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "" #: backend/hp-option.h:138 #, fuzzy, no-c-format msgid "Mirror horizontal" msgstr "Zrcadlit obrázek" #: backend/hp-option.h:139 #, fuzzy, no-c-format msgid "Mirror image horizontally." msgstr "Zrcadlit obrázek" #: backend/hp-option.h:144 #, fuzzy, no-c-format msgid "Mirror vertical" msgstr "Zrcadlit obrázek" #: backend/hp-option.h:145 #, fuzzy, no-c-format msgid "Mirror image vertically." msgstr "Zrcadlit obrázek" #: backend/hp-option.h:150 #, fuzzy, no-c-format msgid "Update options" msgstr "Zvláštní volby" #: backend/hp-option.h:151 #, fuzzy, no-c-format msgid "Update options." msgstr "Testovací volby s pevnou des. Äárkou" #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Vypnout lampu" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Vypnout lampu skeneru." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "RozmÄ›r papíru" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatické oddÄ›lení" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 na šířku" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Manuální pÅ™edběžné zaostÅ™ení" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Manuální pÅ™edběžné zaostÅ™ení" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Zapnout oboustranné (duplexní) skenování" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Fyzická velikost papíru v automatikém podavaÄi" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Polotóny" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Barva" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Polotóny" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Polotóny" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Chybový rozptyl" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normální" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "SvÄ›tlé body" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "Stolní skener" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Z papíru" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Standard" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Jemný" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Pomalý" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "StÅ™ední" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "ÄŒervená" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Zelená" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Zdroj" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Režim podavaÄe" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Nastavuje režim podavaÄe" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "VyÅ™adit pÅ™edběžné zaostÅ™ení" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "VyÅ™adit pÅ™edběžné zaostÅ™ení" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Nastavuje režim podavaÄe" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Nastavuje režim podavaÄe" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatické nastavení prahových hodnot" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Automaticky nastaví jas, kontrast, úroveň bílé, gama korekci, redukci " "Å¡umu a zvýraznÄ›ní obrázku" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Redukce Å¡umu" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Redukuje izolovaný bodový Å¡um" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "ZvýraznÄ›ní obrázku" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Nastaví zvýraznÄ›ní obrázku" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gama" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Zapnout lampu" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Zapíná a vypíná lampu." #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Zrcadlit obrázek" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Korekce gama" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Tisk ve vysoké kvalitÄ›" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Tisk v nízké kvalitÄ›" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Chybový rozptyl" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Bez korekce" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normální" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "VylepÅ¡ení" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Automatické nastavení prahových hodnot" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Automatické nastavení prahových hodnot" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Nastavit poÅ™adí kanálů" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Stíny modré" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Posun Äervená-modrá" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamant" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 hrubé zvýraznÄ›ní (fatting)" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 jemné zvýranÄ›ní (fatting)" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 vertikála" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Zisk" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Nastavení zisku barevných kanálů" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Zisk Å¡edé" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Nastavuje zisk Å¡edého kanálu" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Zisk Äervené" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Nastavuje zisk Äerveného kanálu" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Zisk zelené" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Nastavuje zisk zeleného kanálu" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Zisk modré" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Nastavuje zisk modrého kanálu" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Rozptyl 16 Bayer" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Rozptyl 64 Bayer" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Polotón - 32 bodů" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Polotón 64 bodů" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Chybový rozptyl" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Režim 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Režim 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Režim 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "Z bílého bodu" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Jemný" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Nízká" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "StÅ™ední" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Vysoká" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Jedna strana" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "VÅ¡echny strany" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "skener s podavaÄem" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "StupnÄ› Å¡edé 4 bity" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "StupnÄ› Å¡edé 8 bitů" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Stíny, polotóny, svÄ›tlé body, expozice" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Zvláštní volby" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Barevné vyvážení" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "VyÅ™adit zpÄ›tný chod" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Pokud je zvoleno, skener neskenuje pÅ™i zpÄ›tném průchodu." #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Vypnout lampu plochého skeneru" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Vypne lampu plochého skeneru" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Kalibrace backendem" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "Pokud je zvoleno, kalibraci pÅ™ed skenováním provede backend" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Použít prosvÄ›tlovací adaptér pro film 35mm" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Tato volba vypne bÄ›hem skenu lampu plochého skeneru" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Sken v plné kvalitÄ›" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Vysoká kvalita ale nižší rychlost" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Rychlý sken" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Nejvyšší rychlost ale nižší kvalita" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatické nastavení prahových hodnot" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Pokud je zvoleno, optimální prahové hodnoty se pokusí nastavit backend." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Zvolí režim gama korekce." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Svázat hodnoty gama" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Použít shodné hodnoty gama pro vÅ¡echny ÄtyÅ™i barevné kanály." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Skalární gama" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Nastaví hodnotu skalární gama korekce." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Skalární gama Äervené" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Nastaví hodnotu skalární gama korekce pro Äervený kanál" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Skalární gama zelené" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Nastaví hodnotu skalární gama korekce pro zelený kanál" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Skalární gama modré" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Nastaví hodnotu skalární gama korekce pro modrý kanál" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Kanál" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Nastaví barevné pásmo, \"SpoleÄné\" znamená, že jsou ovlivnÄ›ny vÅ¡echny " "barvy." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Polotóny" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Nastaví, která úroveň jasu má být považována za \"50% Å¡edou\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Polotóny pro Äervenou" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Nastaví, která úroveň jasu má být považována za \"50% Äervenou\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Polotóny pro zelenou" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Nastaví, která úroveň jasu má být považována za \"50% zelenou\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Polotóny pro modrou" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Nastaví, která úroveň jasu má být považována za \"50% modrou\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Vyvážení Äervené" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Vyvážení Äervené. Hodnota 100% znamená bez korekce." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Vyvážení zelené" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Vyvážení zelené. Hodnota 100% znamená bez korekce." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Vyvážení modré" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Vyvážení modré. Hodnota 100% znamená bez korekce." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Vyvážení firmwarem" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Nastaví barevné vyvážení na hodnoty poskytované firmwarem." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Nejpomalejší" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Pomalejší" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Rychlejší" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Nejrychlejší" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 hrubý" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normální" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 jemný" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 velmi jemný" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normální" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 hrubý" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 jemný" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 hrubý" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normální" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 jemný" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normální" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normální" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 volitelný" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 volitelný" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 volitelný" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 volitelný" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 volitelný" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 volitelný" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "StupnÄ› Å¡edé - rychlý režim" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Skenuje se ve stupních Å¡edé v rychlé režimu (nižší kvalitÄ›)" #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Požaduje, aby se vÅ¡echny náhledy dÄ›laly v nejrychleším režimu (s nízkou " "kvalitou). To může znamenat napÅ™. Äernobílý režim nebo nízké rozliÅ¡ení." #: backend/mustek.c:4341 #, fuzzy, no-c-format msgid "Lamp off time (minutes)" msgstr "Zahřát lampu" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "" #: backend/mustek.c:4353 #, fuzzy, no-c-format msgid "Turn lamp off" msgstr "Zapíná/vypíná lampu" #: backend/mustek.c:4354 #, fuzzy, no-c-format msgid "Turns the lamp off immediately." msgstr "Vypne lampu plochého skeneru" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Jas Äervené" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Nastavuje jas Äerveného kanálu naskenovaného obrázku." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Jas zelené" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Nastavuje jas zeleného kanálu naskenovaného obrázku." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Jas modré" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Nastavuje jas modrého kanálu naskenovaného obrázku." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Kontrast Äerveného kanálu" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Nastavuje kontrast Äerveného kanálu naskenovaného obrázku." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Kontrast zeleného kanálu" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Nastavuje kontrast zeleného kanálu naskenovaného obrázku." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Kontrast modrého kanálu" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Nastavuje kontrast modrého kanálu naskenovaného obrázku." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Barva 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Barva 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Å edá 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Å edá 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, fuzzy, no-c-format msgid "Positive" msgstr "Pozitivní film" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Zahřát lampu dokud její jas není konstantní namísto standardního 40ti " "sekundového zahřívání." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Negativní film" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negativ" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, fuzzy, no-c-format msgid "Update button state" msgstr "Stav tlaÄítek" #: backend/pixma_sane_options.c:244 #, fuzzy, no-c-format msgid "Button 1" msgstr "Stav tlaÄítek" #: backend/pixma_sane_options.c:258 #, fuzzy, no-c-format msgid "Button 2" msgstr "Stav tlaÄítek" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Průsvitná pÅ™edloha" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "" #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Hrubá kalibrace" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, fuzzy, no-c-format msgid "Calibration data cache" msgstr "Režim kalibrace" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "" #: backend/plustek.c:942 #, fuzzy, no-c-format msgid "Performs calibration" msgstr "Hrubá kalibrace" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, fuzzy, no-c-format msgid "Warmup-time" msgstr "Zahřát lampu" #: backend/plustek.c:975 #, fuzzy, no-c-format msgid "Warmup-time in seconds." msgstr "Zahřát lampu" #: backend/plustek.c:987 #, fuzzy, no-c-format msgid "Lampoff-time" msgstr "Vypnout lampu" #: backend/plustek.c:988 #, fuzzy, no-c-format msgid "Lampoff-time in seconds." msgstr "Zahřát lampu" #: backend/plustek.c:995 #, fuzzy, no-c-format msgid "Analog frontend" msgstr "Analogová korekce gama pro Äervenou" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Odstup Äervené" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, fuzzy, no-c-format msgid "Red lamp off" msgstr "Zapíná/vypíná lampu" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "" #: backend/plustek.c:1057 #, fuzzy, no-c-format msgid "Green lamp off" msgstr "Zapíná/vypíná lampu" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "" #: backend/plustek.c:1065 #, fuzzy, no-c-format msgid "Blue lamp off" msgstr "Zapíná/vypíná lampu" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Barva 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Rozptyl 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Rozptyl 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Náhodný" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Volba zdroje" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "VylepÅ¡ení obrázku" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "PÅ™evod do úrovní Å¡edé" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "NaÄíst obrázek v úrovních Å¡edé." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Simulace trojitého průchodu" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simuluje trojprůchodový skener tak, že vrací 3 oddÄ›lené obrázky. Pro ty " "pomalejší z vás to znamená zelený, modrý a pak Äervený." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Simulace ruÄního skeneru" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simuluje ruÄní skener. RuÄní skenery obvykle neznají výšku obrázku " "pÅ™edem. Proto vracejí výšku 1. Tato volba umožnuje otestovat, jestli se " "s tím frontend vyrovná." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Nastaví standardní hodnoty prvků vylepÅ¡ení obrázku (jas a kontrast)" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Volba testu pouhého Ätení" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Uvidíme, jestli se s tím frontend vyrovná" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Tabulky gama" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Simulace stavových kódů" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "NetlaÄit stavový kód" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Nenutit backend, aby vrátil stavový kód." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Vrátit SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód " "SANE_STATUS_EOF." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Vrátit SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód " "SANE_STATUS_JAMMED." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Vrátit SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód " "SANE_STATUS_NO_DOCS." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Vrátit SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód " "SANE_STATUS_COVER_OPEN." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Vrátit SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód " "SANE_STATUS_IO_ERROR." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Vrátit SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód " "SANE_STATUS_NO_MEM." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Vrátit SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód " "SANE_STATUS_ACCESS_DENIED." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Zapnout lampu" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Zapnout lampu skeneru" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Vypnout lampu" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Vypnout lampu skeneru" #: backend/sm3840.c:760 #, fuzzy, no-c-format msgid "Lamp timeout" msgstr "Vypnout lampu" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "PodavaÄ dokumentů" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "15 x 10 (cm)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "20x24 (cm)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "22x28 (cm)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Polotón není podporován" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "Bodový rozptyl 8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "Bodový rozptyl 16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "PoÄet řádek skenu požadovaný v jednom příkazu Ätení SCSI. ZmÄ›nou tohoto " "parametru lze doladit rychlost, jakou jsou Ätena data pÅ™i skenování. " "Pokud je toto nastavení příliÅ¡ nízké, skener musí periodicky pÅ™i " "skenování zastavovat, pokud je příliÅ¡ vysoké, skenovací rozhraní v " "prostÅ™edí X mohou pÅ™estat reagovat a systém může zkolabovat." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Vysunout dokument po naskenování" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Režim náhledu" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Volí režim náhledu. Náhled ve stupních Å¡edé obvykle nabízí nejlepší " "kombinaci rychlosti a detailu." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "PÅ™ednastavené hodnoty" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Poskytuje standardní skenovací plochu pro fotografie, vytiÅ¡tÄ›né stránky " "apod." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "Stolní skener" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Automaticky vysunout" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Pozice zaostÅ™ení" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Pozice zaostÅ™ení" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "PoÄet barevných Äar na jedno Ätení" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "PoÄet Äar ve stupních Å¡edi na jedno Ätení" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Barva RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Barva RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Barva RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Zcela Äerná" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Zcela bílá" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Barevný vzorek" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Mřížka" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "První položka" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Druhá položka" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Toto je velice dlouhá tÅ™etí položka. Doufejme, že frontend tuší, jak ji " "správnÄ› zobrazit" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Simulace ruÄního skeneru" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simuluje ruÄní skener. RuÄní skenery obvykle neznají výšku obrázku " "pÅ™edem. Proto vracejí výšku 1. Tato volba umožnuje otestovat, jestli se " "s tím frontend vyrovná." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Simulace trojitého průchodu" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "Simuluje trojprůchodový skener tak, že vrací 3 oddÄ›lené obrázky." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Nastavit poÅ™adí kanálů" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Nastavit poÅ™adí kanálů v trojprůchodovém barevném režimu." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Zvláštní volby" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Zvolit testovací obrázek" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Zvolte druh testovacího obrázku. Možnosti:\n" "Zcela Äerný: vyplní celý sken Äernou barvou.\n" "Zcela bílý: vyplní celý sken bílou barvou.\n" "Barevný vzorek: vykreslí různé testovací barevné vzorky podle zvoleného " "režimu.\n" "Mřížka: vykreslí Äernobílou mřížku o šířce a výšce 10 mm / ÄtvereÄek." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "PÅ™evrátit endian (invert endianness)" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "ZamÄ›nit horní a spodní bajt obrázkových dat v 16-bitových režimech. Tuto " "volbu lze použít k testu 16-bitových režimů frontendů, napÅ™. zda " "frontend používá správný endian." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Limit Ätení" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "Omezit množství dat, pÅ™enášených každým voláním sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Velikost limitu Ätení" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "Maximální velikost dat, pÅ™enášených pÅ™i kaýždém volání sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Prodleva Ätení" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Prodleva pro pÅ™enos dat do roury." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Doba prodlevy Ätení" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "Jak dlouho se má Äekat po pÅ™enesení každé dávky dat rourou." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Návratová hodnota sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Zvolte naávratovou hodnotu sane_read(). \"Standard\" je normální " "zpracování pÅ™i skenování. VÅ¡echny ostatní stavové hodnoty jsou pro " "testování, jak si s nimi frontend poradí." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Ztráta bodů na řádku" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "PoÄet bodů na konci každé řádky, které nejsou využity." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "NepÅ™esné (fuzzy) parametry" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Vrátit nepÅ™esné (fuzzy) řádky bajty na řádku, pokud je volána funkce " "sane_parameters() pÅ™ed sane_start()" #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Použít neblokující V/V" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Použít neblokující V/V pro sane_read(), pokud to frontend podporuje." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Nabídnout select file descriptor" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Nabídnout select file descriptor pro detekci, zda sane_read() vrátí data." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Povolit testovací volby" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Povoluje různé testovací volby. Je tu pro testování schopností frontendů " "zobrazit a zmÄ›nit vÅ¡echny možné typy voleb SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Tisk voleb" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Vytisknout seznam vÅ¡ech voleb" #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Boolovské (ano/ne) testovací volby" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Boolovská softwarová volba, softwarová detekce" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Boolovská volba, která umožňuje softwarovou volbu a softwarovou " "detekci (a pokroÄilejší). Je to v podstatÄ› normální boolovská volba." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Boolovská s hardwarovým výbÄ›rem a softwarovou detekcí" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Boolovská volba, která podporuje hardwarovou volbu a softwarovou " "detekci (a pokroÄilejší). To znamená, že volbu nelze nastavit frontendem " "ale je nastavena uživatelem (napÅ™. stisknutím tlaÄítka na zařízení)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Boolovská volba s hardwarovým výbÄ›rem" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Boolovská testovací volba, která podporuje hardwarový (a " "pokroÄilejší) výbÄ›r. To znamená, že volbu nelze zmÄ›nit frontendem ale " "jen uživatelem (napÅ™. stiskem tlaÄítka na zařízení) a frontend ji nemůže " "ani naÄíst." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Boolovská volba se softwarovou detekcí" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Boolovská testovací volba podporující softwarovou detekci (a " "pokroÄilejší). To znamená, že jde o volbu pouze ke Ätení." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Boolovská volba s emulací softwarové volby" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Boolovská testovací volba, která podporuje softwarovou volbu, " "detekci a emulaci (plus pokroÄilejší)." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "" "(6/6) Boolovská volba se softwarovou volbou a automatickou softwarovou " "detekcí" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Boolovská testovací volba, která podporuje softwarovou volbu, " "softwarovou detekci (a pokroÄilejší). Tato volba může být automaticky " "nastavena backendem." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "CeloÄíselné (Int) testovací volby" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) CeloÄíselná" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" "(1/6) CeloÄíselná testovací volba bez jednotek a nastavených omezení." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) CeloÄíselná volba s omezením rozsahu" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) CeloÄíselná testovací volba s jednotkou bod a omezením rozsahu. " "Minimum is 4, maximum 192, krok je 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) CeloÄíselný seznam s omezením" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) CeloÄíselná testovací volba s jednokou bit a omezením množinou " "slov." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) CeloÄíselné pole" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) CeloÄíselné testovací pole s jednotkou mm a polem bez omezení." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) CeloÄíselné pole s omezením rozsahu" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) CeloÄíselné testovací pole s jednotkou dpi a omezením rozsahu. " "Minimum je 4, maximum 192, krok 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) CeloÄíselné pole s omezením množinou slov" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) CeloÄíselné testovací pole s jednotkou procenta a omezením rozsahu " "pomocí množiny slov." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Testovací volby s pevnou des. Äárkou" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Číslo s pevnou des. Äárkou" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" "(1/3) Číslo s pevnou desetinnou Äárkou, bez jednotek a bez omezení." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Číslo s pevnou des. Äárkou a omezeným rozsahem" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Číslo s pevnou des. Äárkou, jednotkou mikrosekundy a omezením " "rozsahu. Minimum je -42,17, maximum 32767,9999, krok 2,0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Číslo s pevnou desetinnou Äárkou s omezením seznamem slov" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Číslo s pevnou desetinnou Äárkou bez jednotky a s omezením " "seznamem slov." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Testovací volby Å™etÄ›zcové" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) ŘetÄ›zec" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) ŘetÄ›zcová volba bez omezení." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) ŘetÄ›zcová volba s omezením seznamem" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) ŘetÄ›zcová volba s omezením seznamem." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) ŘetÄ›zcová volba s omezením dlouhým seznamem" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) ŘetÄ›zcová volba s dlouhými Å™etÄ›zci s omezením seznamem. Obsahuje " "ponÄ›kud více položek..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Testovací volby tlaÄítkové" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) TlaÄítko" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Testovací tlaÄítková volba. Vytiskne nÄ›jaký text..." #: backend/u12.c:149 #, fuzzy, no-c-format msgid "Color 36" msgstr "Barva 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Uživatelské nastavení obrázku" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Dvouúrovňová Äernobílá (perokresba)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Polotónová Äernobílá s rozptylem (polotón)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Víceúrovňová Äernobílá (úrovnÄ› Å¡edé)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Víceúrovňová RGB barva (jednoprůchodová barva)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignorovat kalibraci" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "VyÅ™adit pÅ™edběžné zaostÅ™ení" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Nekalibrovat zaostÅ™ení" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Manuální pÅ™edběžné zaostÅ™ení" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Pozice pevného zaostÅ™ení" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Kalibrace ÄoÄky na pozici dokumentu" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Kalibrovat zaostÅ™ení ÄoÄky na pozici dokumentu" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Pozice zaostÅ™ení podavaÄe 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Použít pozici 0mm zaostÅ™ení podavaÄe místo 0,6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Režim kalibrace" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Definovat režim kalibrace" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Zapíná/vypíná lampu" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA zapnuto" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Zapíná/vypíná UTA" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Odstup" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Nastavení odstupu barevných kanálů" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Odstup Å¡edé" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Nastavuje odstup Å¡edého kanálu" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Nastavuje odstup Äerveného kanálu" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Nastavuje odstup zeleného kanálu" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Nastavuje odstup modrého kanálu" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Režim náhledu" #~ msgid "Grayscale" #~ msgstr "StupnÄ› Å¡edé" #~ msgid "Binary" #~ msgstr "Binární" #, fuzzy #~ msgid "Display a shortened resolution list" #~ msgstr "Zobrazí zkrácený seznam rozliÅ¡ení" #~ msgid "Black & White" #~ msgstr "ÄŒernobílý" sane-backends-1.0.27/po/bg.gmo0000664000175000017500000022211113110600537012727 00000000000000Þ•q¤G,'H4 I4-V4 „4;4 Ì4,Ù4"5z)5 ¤59®5è5€6#†65ª6"à6Æ7Ê7jå7 P8Bq8(´8SÝ819ØH9!:B@:ƒ:lš:;J;+b;cŽ; ò;z<'Ž<™¶<$P=Wu=Í= Õ= à= ë= ö=> > >> (> 3> >>I> R> ]> h> s>€> ˆ> –> ¢>¬>¿>Ð> â> í>ø> ? ?Ò?í? ð? ý? @! @/@!O@ q@’@ ²@Ó@sÜ@ PA ZAfAxAA£A´A ÌA!íAB/B4BCB ZB eBoB!‰B«BÀBÔB_åB=EC>ƒC<ÂCÿCDD'%DMDVDnD €D ‹D •D¡D ¦D³D ÃDÍD ÜDèDúD% E/E%>E dEoEƒE†E ŠE—EªEÆEãEþE FF,F)GF qF}F”F¥F¶FÆFÎFÕF&èFÄGÔGÚGãG òG H H H!H 0H>H[HzH‹H ©H·H¿HÇHÏH åHñHúHI'IT%WTh}TeæT^LUc«UaVbqVaÔV 6WAWRW dWnWW„WŠW ›W¨W ¹W)ÅW*ïW(X›CXßX èXóX øX YYYY#Y4YEYTY ZYhY yY„Y ”Y¡YºY¿YÈYßYöYZZ.Z?Z UZ`ZwZZ§Z¬ZÃZÙZùZ [#[6[J[\[ v[I[Ë[[Ï[E+\4q\¹¦\€`]á]ô]ú] ^^+^*?^5j^ ^±^Â^Ô^Ý^î^ ö^0_H_CO_“_›_¸_Ð_Ô_é_ú_``!`(`0`A`S`c` u`‚``¶`È`Ø`ß`æ`í`&ÿ`*&a Qa[ada ma {a‰a™ažaX¥aþa]bncŠcLŽcÛcøcÿcd d+d >d%Id od}d‘d ™d¦d¬d ÉdM×d%e 9e Fe Se ]e heseM‰e×e Ûeçeöe ÿe ff6fÖVf|-g ªgËgéghh6hQh[khÇh áh ìhùh ii /i9iLihi…i' iÈi Úiäi ôi jx j „j.‘jÀj#Ùjgýkœelm:m;Um9‘m,ËmYømRnFjn±n*Æn"ñn‡oœo'²o<Úo4p>LpB‹p>Îp? qDMq?’q9Òq9 r=Fr@„r=ÅrBs>Fs>…s?Äs=tDBt,‡t´tÆt×tít1u7uVuiuyuu©uÀuÙuñu vv2v>Jv?‰vÉvDßv%$w4Jww)—wXÁw2xÌMxy!y1yBy)Qy {y †yy¤y¶yÊyÝyïyz z&z=züEzÐB{p|K„|Ð|ã|é|î|õ|ý| } } }&}7}G}W}r}‰}}²}Ï}Gè}'0~=X~Œ–~#S4;ˆÄÚ ðú€ 1€!<€ ^€!i€ ‹€˜€­€ ¿€à€ö€ *Bbq.°CÆ ‚(!‚J‚A^‚. ‚&Ï‚ö‚ ƒ!ƒ:ƒSƒ\ƒlƒ)|ƒ`¦ƒ`„ h„t„ „œ„±„Ç„ Û„è„ì„õ„ ý„ ……q… ‘†[ž†ú†v‡ ЇQ—‡8é‡Ë"ˆ îˆeøˆ<^‰í›‰+‰ŠUµŠ? ‹€K‹)ÌŒáöŒ5ØŽ3ŽŽÂŽ(Rž{&‘A‘&Á‘Íè‘¶’‚Æ’KI“›•“/1”Öa”A8•z•,}–Žª–9—L—a—w—Œ—¢—µ—Å— Ú—è—þ—˜ #˜1˜@˜U˜"k˜Ž˜¡˜´˜ ŘϘä˜#÷˜™+™ @™N™d™Ã}™A›D›T›f›Rj›T½›RœVeœT¼œVhä{`ž'~ž(¦ž5Ïž*Ÿ,0Ÿ,]Ÿ<ŠŸ>ÇŸ@ G P ;p ¬ È ?ß ;¡+[¡‡¡)§¡ÊÑ¡lœ¢n £px£é£ï£ÿ£>¤N¤-]¤*‹¤¶¤ Τ ï¤ ¥¥5¥!O¥!q¥“¥&«¥Ò¥Qê¥<¦QT¦ ¦¦(³¦ܦߦã¦5ø¦B.§Dq§F¶§7ý§5¨#L¨Gp¨V¸¨©($©M©m©Œ© ª©µ©Å©Oå©c5ª™« ¢«$®«Ó«è« ¬ ¬¬0¬OL¬Gœ¬ ä¬;­A­ [­ g­ s­)­©­Ä­$Õ­(ú­*#®/N®1~®3°®nä®US¯l©¯p°r‡°Wú°nR±rÁ±t4²Q©²û²[³,l³™³´³Ò³9ê³e$´cŠ´Uî´gDµe¬µi¶g|¶Sä¶U8·WŽ·žæ·M…¸MÓ¸_!¹„¹º1º%@ºfºxº<ˆºź̺áº÷º»H+»Kt»AÀ»&¼))¼HS¼œ¼2»¼î¼½½&½L9½ †½;“½ ϽKð½o<¾C¬¾Cð¾(4¿]¿mÀ&€À¿§À$gŒ¤´ÂÏÂåÂÃÃ$%ÃJÃaÃzÊÃ"¡ÃÄÃ1âÃ,ÄAÄ+IÄ uÄ&–Ä/½Ä,íÄKÅ‹fňòÅ…{ƆljˆÇ‰È„œÈ!É 3É?É#[É*ɪɿÉ"ÈÉ ëÉ" Ê"/ÊMRÊQ ÊSòÊ"FËiÌ |ÌÌ¦ÌÆÌ ÜÌ èÌ óÌÍÍ)>Í hÍuÍ‘Í#­Í#ÑÍõÍ5ÎEÎTÎ$cÎ ˆÎ©ÎÇÎÝÎóÎ3ÏEÏ5TÏ/ŠÏ/ºÏ êÏ3÷Ï3+ÐD_ÐD¤ÐéÐ!þÐ# Ñ%DÑ-jјÑo±Ñ !Ò”,ÒÁÒWQÓ†©Óø0Õ+)ÖUÖ&lÖ*“Ö&¾Ö!åÖ^×hf×1ÏרØ5Ø&JØqØI„ØXÎØ'Ù.Ù®Ù7¶Ù0îÙ Ú1*Ú!\Ú.~Ú ­Ú ·Ú ÂÚÏÚÞÚúÚÛ)8ÛbÛB€Û=ÃÛLÜ%NÜ tÜ Ü ŽÜ#›ÜF¿ÜNÝ UÝcÝlÝ{Ý—Ý"¯ÝÒÝÛÝšì݇ޮ›Þ4Já á}‰á'â /â:âBâ@\â$â"Ââ<åâ"ã-@ã nãyã ”ãAŸãáã–ä.—ä'Æä!îä#å$4åYå#v刚å#æ2æPæ%næ%”æºæ5ÖæL ç†Yçëàè$Ìé!ñéê.êNêlê‹ê“©ê.=ëlëë&›ë(Âë*ëë"ì79ìDqìF¶ìHýìRFí9™í"Óí*öí(!î&Jîõqîgï_…ïåï/ðÈ3ò/üò3,ôf`ôjÇôk2õRžõºñõ¬ö€ËöL÷Be÷B¨÷ ë÷ùøCùd[ùkÀùb,úoú`ÿúf`ûuÇûd=üY¢üWüühTýy½ýf7þxžþcÿa{ÿdÝÿgBsªX7w9¯<é@&€gCè#,#P>t6³>ê6)B`:£.ÞD <Rrƒ5†w¼U4rŠ=ýY;וnm „Ü  a l „ ž cº  1 -@ /n -ž 1Ì /þ 1. ,`  3« ß òô ŽçËv…B0Èù!1CXm‡ ŸÀÞ1ü+.,Z%‡/­HÝ&]¨]+d°k>5ª5à13Q…O™éOýM4d™O°3/4 dp$G¦>î-IVfL½’ 5^Ó*2t]_ÒX2Q‹2ÝA AR #” 3¸ 3ì W !¬x!¬%"Ò"9î"(#+G#-s#/¡#Ñ#ì# ð#ý#$$4$6Ëyª }7ÌAð0ÞMê[ü˜©‡øYYC©ø*’ãYéax\yEd›÷³ Çèߨ ?2e¾~‚Å\ñ–gEKjp†GȲÂÅ;9"‰ÒµcNz{ 6hXÃ-ÆŒƒ~w‘ö¸c ò"Ú>³þ“‰¡Û2¥R<9ËIb‚J|hqsÝ*fÍÿ.Xð_QÝKRéAõ/3ý3ŒT‹!‘Øœ;Na»'ë]ÍR$1bkF&C"ÿKSÞLî—Ná+B â¦7TO: nЊÇAɹ®ZûùXj/£žuL°%<@½.MM|[ã7zU%¡í·Jb`%+Ô•P¤-4 ,âºqÜl!µ_¾išp,l™¯{}L¹æ?Ze ƒ=Q Î d»mrgicDà(®)±¿–Oå]È#óÖÊ5$íPÙC@ó'5½^4_¨”VáÓÊš*DSà­r›™ÕôiÁdx-„>Æk1)ìÁ£—0Üw S(ýB°Ô8Po[×'ÛÀ¤ú3k¢±´`ï÷=ç ´DŽØä… 8·ïû¼ÌŠ&îõ l5VÑtžn W1<pÏæHÎ ¿FÙ¯6úQoÀ#ÚW0¦V’ Ua@Gev?•¼I§#­˜œ(öÏç.¸8=\fŸ¬€E²¬ÒTüÉ`4Ðu‹×¢Bëôf:¥F§ò&€†äåWtŸ9Hh/],‡n«Žmv„m^Z$“ù>GO…jÄqñ!ì:ªêoJþºè«ÄÖ+g^Ñ”U߈s2IÓ¶H)Õˆö; (1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAnalog GainAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue intensityBlue offsetBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton test optionsCDCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrationCalibration by backendCalibration modeChange Document.Change documentChannelCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.CustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.DiamondDisable backtrackingDisable pre focusDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Do a grayscale rather than color scanDo a quality white-calibrationDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuration of read-delayEjectEject document after scanningEject the sheet in the ADFEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.EnhancementError DiffusionExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Exposure timeExtra FastFastFast gray modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFilm-stripFineFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGrain sizeGrayGray gainGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen intensityGreen offsetGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.Ignore calibrationImageImage EnhancementImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp onLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual pre focusMatrix multiplication of RGBMaxMediaMediumMidtoneMidtone for blueMidtone for greenMidtone for redMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image.Mirror verticalMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNo CorrectionNoise reductionNoneNormalNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOptional equipmentPaper sizePhysical size of the paper in the ADFPositive FilmPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRandomizeRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed intensityRed offsetReduce the isolated dot noiseRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Return SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSaturationScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Second entrySelect minimum-brightness to get a white pointSelect smoothing filter.Select the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Set default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set exposure-timeSet lamp densitySet sharpening value.Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSlideSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsStart calibration process.Status Code SimulationString test optionsSwap black and whiteSwitches the lamp on or off.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampUTA onUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update optionsUpdate options.Use 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Warm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWhite levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomflatbed scannerProject-Id-Version: sane-backends 1.0.11 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-12-17 22:59+0100 Last-Translator: Pavel Constantinov Language-Team: <> Language: bg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (1/1) Button(1/1) Бутонна теÑтова опциÑ. Извежда нÑкакъв текÑÑ‚...(1/3) ФикÑирана(1/3) ФикÑирана теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ· наглаÑена единица и ограничениÑ.(1/3) String(1/3) Стрингова теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ· ограничение.(1/6) Булева мек избор мек детект(1/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¼ÐµÐº избор и мек детект (и разширени) възможноÑти. Това е проÑто нормална булева опциÑ.(1/6) Int(1/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ· Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¸ единица.(2/3) ФикÑирана ограничение обхват(2/3) ФикÑирана теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° микроÑекунда и наглаÑен ограничен обхват. Минимумът е -42,17, макÑимумът 32767,9999, а Ñтъпката е 2,0.(2/3) String ограничен string list(2/3) Стрингова теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ string list.(2/6) Булева твърд избор и мек детект(2/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ñ‚Ð²ÑŠÑ€Ð´ избор и мек детект (и разширени) възможноÑти. Това означава, че опциÑта не може да Ñе наглаÑи от фронтенда, а Ñамо от Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ (напр. чрез натиÑкане на бутон върху уÑтройÑтвото).(2/6) Int ограничен обхват(2/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° пикÑел и наглаÑен обхват на ограничение. Минимумът е 4, макÑимумът е 192, а Ñтъпката е 2.(3/3) ФикÑирана ограничен word list(3/3) ФикÑирана теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ· наглаÑена единица и Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ word list.(3/3) String Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ long string list(3/3) Стрингова теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÐµÐ½ string list. Съдържа повече ÑтойноÑти...(3/6) Булева твърд избор(3/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ñ‚Ð²ÑŠÑ€Ð´ избор (и разширени) възможноÑти. Това означава, че опциÑта не може да Ñе налаÑÑ Ð¾Ñ‚ фронтенда, а Ñамо от Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ (напр. чрез натиÑкане на бутон върху уÑтройÑтвото) и фронтендът не може да Ñ Ñ‡ÐµÑ‚Ðµ.(3/6) Int ограничен word list(3/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° бит и наглаÑен ограничен word list.(4/6) Булева мек детект(4/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¼ÐµÐº детект (и разширени) възможноÑти. Това означава, че опциÑта е Ñамо за четене (read-only).(4/6) Int array(4/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° мм; използва array без ограничениÑ.(5/6) Булева мек избор мек детект емулирана(5/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¼ÐµÐº избор, мек детект и емулирани (и разширени възможноÑти.(5/6) Int array ограничен обхват(5/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° dpi; използва array Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ обхват. Минимумът е 4, макÑимумът е 192, а Ñтъпката е 2.(6/6) Булева мек избор мек детект авто(6/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¼ÐµÐº избор, мек детект и автоматични (и разширени) възможноÑти. Тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¼Ð¾Ð¶Ðµ автоматично да Ñе наглаÑи от бекенда.(6/6) Int array ограничен word list(6/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° процент; използва array Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ word list.2-пикÑелно2Ñ…2 по избор2Ñ…2 нормално3Ñ…3 по избор3Ñ…3 нормално4-пикÑелно4Ñ…4 грубо4Ñ…4 по избор4Ñ…4 фино4Ñ…4 нормално5Ñ…5 грубо5Ñ…5 по избор5Ñ…5 фино6x4 (инча)6Ñ…6 по избор6Ñ…6 нормално8-битово извеждане.8-пикÑелно8,5Ñ…11 (инча)8Ñ…10 (инча)8x8 Bayer8x8 груб Fatting8x8 фин Fatting8x8 вертикална черта8Ñ…8 грубо8Ñ…8 по избор8Ñ…8 фино8Ñ…8 нормално8Ñ…8 много финоПо-дългото време на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñва на Ñкенера да Ñъбере повече Ñветлина. Предложената употреба е 175% за разпечатки, 150% за нормални Ñлайдове и "Ðегатив" за негативен филм. За тъмни (подекÑпонирани) Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚Ðµ да завишите тази ÑтойноÑÑ‚.A4A5 пейзажA5 портретADFÐ”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ Ñиньото Ñпоред Ñтепента на Ð·ÐµÐ»ÐµÐ½Ð¾Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ Ñиньото Ñпоред Ñтепента на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¾Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ зеленото Ñпоред Ñтепента на ÑÐ¸Ð½ÑŒÐ¾Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ зеленото Ñпоред Ñтепента на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¾Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ червеното Ñпоред Ñтепента на ÑÐ¸Ð½ÑŒÐ¾Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ червеното Ñпоред Ñтепента на зеленоРазширеноСлед изпращане на команда за Ñканиране, изчакай, докато бутонът на Ñкенера не е натиÑнат, преди да започнеш Ñамото Ñканиране.Ð’Ñички ÑтранициÐналогово увеличениеÐналогова гама - ÑÐ¸Ð½ÑŒÐ¾ÐšÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° аналоговата гамаÐналогова гама - зеленоÐналогова гама - червеноÐналогова гама-корекциÑÐналогова гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð·Ð° ÑиньоÐналогова гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð·Ð° зеленоÐналогова гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð·Ð° червеноÐвтоÐвтоматичен прагÐвтоматична ÑÐµÐ³Ð¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ð° площÐвто изважданеÐвтоматичноÐвтоматично подаване на документиÐвтоматично пригаждане на прагаÐвтоматично разделениеÐвтоматичен прагÐвтоматично загрÑванеÐвтоматично наглаÑÑ ÑркоÑтта, контраÑта, нивото на бÑло, гамата, редукциÑта на шума и подчертаването на образаФактор за баланÑиране на Ñиньото. 100% означава без корекциÑ.Фактор за баланÑиране на зеленото. 100% означава без корекциÑ.Фактор за баланÑиране на червеното. 100% означава без корекциÑ.BayerBayer Dither 16Bayer Dither 64Черно и бÑло в две нива (режим lineart)Вържи RGBВържи резолюциÑта по X и YВържи аналоговата гамаВържи гаматаДълбочина на битаСтепен на Ñ‡ÐµÑ€Ð½Ð¾Ñ‚Ð¾Ð¡Ð¸Ð½ÑŒÐ¾Ð‘Ð°Ð»Ð°Ð½Ñ - ÑиньоЯркоÑÑ‚ - ÑиньоУвеличение - ÑиньоИнтензитет - ÑиньоОфÑет - ÑиньоБулеви теÑтови опцииДолен деÑен xДолна дÑÑна x Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране.Долен деÑен yДолна дÑÑна y Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране.ЯркоÑтБутонни теÑтови опцииCDCRTCRT мониториÐаглаÑи време за екÑпониранеÐаглаÑи време за екÑпониране - ÑиньоÐаглаÑи време за екÑпониране - зеленоÐаглаÑи време за екÑпониране - червеноÐаглаÑи плътноÑтта на лампатаКалибриранеКалибрирай ÑкенераКалибрирай преди Ñледващото ÑканиранеКалибрирай фокуÑа на лещата в Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚ÐšÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸ÑÐšÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ бекендаРежим калибрациÑСмени документа.Смени документаКанал8Ñ…8 грубоГруба калибрациÑГруба ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ñамо за първото ÑканиранеГрубата ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ñе прави Ñамо за първото Ñканиране. Работи Ñ Ð²Ñички Ñкенери и пеÑти време. Ðко ÑркоÑтта на изображението е различна при вÑÑко Ñканиране, забранете тази опциÑ. Само за теÑтванеЦвÑтЦвÑÑ‚ 36Цветно Ñ Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²ÐµÐ¦Ð²ÐµÑ‚Ð½Ð¾ LineartЦветна матрицаЦвÑÑ‚ RAWЦвÑÑ‚ RGBЦвÑÑ‚ RGB TEXTЦветови баланÑÐаÑтройки по увеличение на цветните каналиÐаÑтройки по офÑета на цветните каналиЦветова корекциÑ.Коефициенти на цветова корекциÑЦветови деÑенЦвÑÑ‚ 24ЦвÑÑ‚ 36ЦвÑÑ‚ 48Цветни линии на четенеКондиционалноКонтраÑтКонтраÑÑ‚ - Ñин каналКонтраÑÑ‚ - зелен каналКонтраÑÑ‚ - червен каналÐаглаÑÑ Ñтепента на ÑиньоÐаглаÑÑ Ñтепента на зеленоÐаглаÑÑ Ñтепента на червеноÐаглаÑÑ Ð¾Ñ‚Ñ‚ÐµÐ½ÑŠÐºÐ° (в Ñиньото ниво) на полученото изображение.ÐаÑтройва ÑркоÑтта на полученото изображение.ÐаглаÑÑ ÑркоÑтта на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение.ÐаглаÑÑ ÑркоÑтта на Ð·ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение.ÐаглаÑÑ ÑркоÑтта на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение.ÐаÑтройва контраÑта на полученото изображение.ÐаглаÑÑ ÐºÐ¾Ð½Ñ‚Ñ€Ð°Ñта на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение.ÐаглаÑÑ ÐºÐ¾Ð½Ñ‚Ñ€Ð°Ñта на Ð·ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение.ÐаглаÑÑ ÐºÐ¾Ð½Ñ‚Ñ€Ð°Ñта на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение.Оттук можете да наложите връщане на главата.8Ñ…8 по изборЦветна матрица по избор за Ñканиране в Ñива Ñкала.Цветна матрица по избор.Опции за дебъгПо подразбиранеВиÑÑщи опцииДефинирай режима на калибрациÑДефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° ÑиньоДефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° Ñканиране на ÑиньоДефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° калибрациÑДефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° зеленоДефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° Ñканиране на зеленоДефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° червеноДефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° Ñканиране на червеноДефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° ÑканиранеДефинирай плътноÑтта на лампата за калибрациÑДефинирай плътноÑтта на лампата за ÑÐºÐ°Ð½Ð¸Ñ€Ð°Ð½ÐµÑ‚Ð¾ÐžÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð´ÐµÑена за полутонизиране (dithering) при Ñканирането на Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ðµ.ÐžÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð° на увеличение за ÑкенераЗабавÑне на транÑфера на данни по линиÑта.Указва ÑкороÑтта, Ñ ÐºÐ¾Ñто ще Ñе извърши Ñканирането.ÐžÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð´Ð°Ð»Ð¸ да Ñе използва вградена или перÑонализирана гама-таблица.DiamondЗабрани връщане на главатаЗабрани предв. фокуÑDispersedDot16x16DispersedDot8x8Покажи кратък ÑпиÑък Ñ Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ð¸DitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dither/полутон черно и бÑло (режим полутон)Ðаправи Ñканиране в Ñива Ñкала, не цветноИзвърши качеÑтвена бÑла калибрациÑÐе калибрирай фокуÑаÐе наÑилвай ÑтатуÑ-кодÐе наÑилвай бекенда да връща ÑтатуÑ-кодFeeder за документиДвойна оптичеÑка резолюциÑСвали деÑен BСвали деÑен BDropoutДуплекÑноПродължителноÑÑ‚ на забавÑнето при четенеИзвадиИзвади документа Ñлед ÑканиранеИзвади лиÑта от ADFПозволи дупрекÑно (двуÑтранно) ÑканиранеПозволÑва автоматично определÑне на прага за lineart Ñканиране.Позволи избор на време за екÑпонациÑПозволи избор на плътноÑÑ‚ на лампатаПозволи теÑтови опцииПозволÑва различни теÑтови опции. Използвайте го, за да теÑтвате ÑпоÑобноÑтта на фронтендовете да виждат и модифицират вÑичките типове опции на SANE.ПовишениеРазÑейка на Ð³Ñ€ÐµÑˆÐºÐ¸Ñ‚ÐµÐ¡Ð¼ÐµÐ½Ñ Ð¼ÐµÑтата на Ð³Ð¾Ñ€Ð½Ð¸Ñ Ð¸ Ð´Ð¾Ð»Ð½Ð¸Ñ Ð±Ð°Ð¹Ñ‚ данни в 16-битовите режими. Тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¼Ð¾Ð¶Ðµ да Ñе използва за теÑтване на 16-битовите режими на фронтендовете, напр. дали фронтендът използва Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð½Ð¸Ñ endianness (метод за запазване на данни в паметта на компютъра.Време за екÑпонациÑЕкÑтра бързоПо-бързоБърз Ñив режимБързо превюБързо ÑканиранеПо-бързоÐай-бързоРежим на захранванеИме на файлаТип екран (film)Тип филмИме на Ñ„Ð°Ð¹Ð»Ð°Ð‘Ð°Ð»Ð°Ð½Ñ Ð¾Ñ‚ фърмуераПърво въвежданеФикÑирай Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° фокуÑаФикÑирани теÑтови опцииFlatbedÐ¤Ð¾ÐºÑƒÑ 2,5 мм над ÑÑ‚ÑŠÐºÐ»Ð¾Ñ‚Ð¾ÐŸÐ¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° фокуÑÐ°Ð¤Ð¾ÐºÑƒÑ Ð²ÑŠÑ€Ñ…Ñƒ ÑтъклотоÐаложи връщане на главатаÐаложи монохромно превюЗадължителна ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¸ ÑканиранеÐакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_ACCESS_DENIED Ñлед повикване на sane_read().Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_COVER_OPEN Ñлед повикване на sane_read().Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_EOF Ñлед повикването на sane_read().Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_IO_ERROR Ñлед повикване на sane_read().Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_JAMMED, Ñлед повикването на sane_read().Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_NO_DOCS Ñлед повикването на sane_read().Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_NO_MEM Ñлед повикване на sane_read().От хартиÑОт бÑлИзчакай бутонаЦÑлоÑтно ÑканиранеПараметри за мъглÑвоÑÑ‚Ð£Ð²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸ÐµÐ“Ð°Ð¼Ð°ÐšÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° гаматаТаблици за Ð³Ð°Ð¼Ð°Ñ‚Ð°ÐšÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° гаматаСтойноÑÑ‚ на гаматаТаблица Ñ Ð³Ð°Ð¼Ð°-корекциÑта на ÑÐ¸Ð½Ð¸Ñ Ñектор.Таблица Ñ Ð³Ð°Ð¼Ð°-корекциÑта за Ð·ÐµÐ»ÐµÐ½Ð¸Ñ Ñектор.Таблица Ñ Ð³Ð°Ð¼Ð°-корекциÑта за Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ Ñектор.Таблица за гама-корекциÑ. Ð’ цветен режим, тази Ð¾Ð¿Ñ†Ð¸Ñ Ð·Ð°ÑÑга по равно червениÑ, Ð·ÐµÐ»ÐµÐ½Ð¸Ñ Ð¸ ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» едновременно (Ñ‚.е., това е таблица на гамата за интензитета).ГеометриÑРазмер на зърнотоСивоУвеличение - ÑивоОфÑет - ÑивоСиво 16Сиво 8ПоÑивиСива Ñкала 4 битаСива Ñкала 8 битаСканиране в Ñива ÑÐºÐ°Ð»Ð°Ð—ÐµÐ»ÐµÐ½Ð¾Ð‘Ð°Ð»Ð°Ð½Ñ - зеленоЯркоÑÑ‚ - зеленоУвеличение - зеленоИнтензитет - зеленоОфÑет - зеленоЛинии на четене по Ñива ÑкалаРешеткаПолутонПолутон A (Твърд тон)Полутон B (Мек тон)Полутон C (Net Screen)Полутон Dot 32Полутон Dot 64Полутонов деÑенРазмер на Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ð¸Ñ Ð´ÐµÑенПолутонÐÑма поддръжка на Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²ÐµÐ¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° ръчен ÑÐºÐµÐ½ÐµÑ€Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° ръчен ÑкенерВиÑокоПринтиране Ñ Ð²Ð¸Ñок контраÑтПринтиране Ñ Ð²Ð¸Ñока гъÑтотаÐай-виÑоко качеÑтво, по-ниÑка ÑкороÑÑ‚Ðай-виÑока ÑкороÑÑ‚, по-ниÑко качеÑтвоОÑветлениеОÑветление - ÑиньоОÑветление - зеленоОÑветление - Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¾ÐŸÐ¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° holder фокуÑа 0ммХоризонталноКолко дълго да Ñе чака Ñлед предаването на вÑеки буфер данни.ÐюанÑÐко отметнете тук, бекендът автоматично ще потърÑи оптимална ÑтойноÑта за прага.Ðко отметнете тук, цветовата ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¸ Ñканирането Ñе прави от бекендаПри отмÑтане, Ñкенерът не връща главата обратноÐко това е позволено, Ñамо ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° отÑенките Ñе извършва през калибрациÑта. Използват Ñе ÑтойноÑтите по подразбиране за увеличение, офÑет и време на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ - вÑе едно вградени или от ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð».Ðко това е позволено, уÑтройÑтвото ще Ñе калибрира преди Ñледващото Ñканиране. Иначе, калибрациÑта Ñе прави Ñамо преди първото пуÑкане.Игнорирай калибрациÑтаИзображениеПодобрение на образаПодчертаване на образаИнтензитет на образаМатрични принтериВ RGB режим, използвай Ñъщите ÑтойноÑти за вÑеки цвÑтПовиши или намали аналоговото увеличение на CCD матрицатаМаÑтиленоÑтруйни принтериInt теÑтови опцииСмени endiannessИзкл. лампаИзкл. лампа при изходВкл. Ð»Ð°Ð¼Ð¿Ð°ÐšÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° лещата в Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð”Ð° видим дали фронтендовете ще Ñе ÑправÑÑ‚ Ñ Ñ‚Ð¾Ð²Ð°LetterОграничава количеÑтвото данни, предадени Ñ Ð²ÑÑко повикване на sane_read().LineartЗареди образа като Ñива Ñкала.Загуба на пикÑели на линиÑÐиÑкоПринтиране Ñ Ð½Ð¸Ñка гъÑтотаРъчен предв. фокуÑМатрично умножаване на RGBМакÑ.МедиÑСредноПолутонПолутон - ÑиньоПолутон - зеленоПолутон - червеноОгледало хоризонталноОгледален образПрави хоризонтален огледален образ.Прави вертикален огледален образÐаправи огледален образ на изображениетоОгледало вертикалноРежим 1Режим 2Режим 3Едноцветна матрицаRGB цветно в много нива (Ñ ÐµÐ´Ð½Ð¾ минаване)Черно и бÑло в много нива (режим Ñива Ñкала)NTSC ÑивоNTSC RGBÐегативÐегативен филмБез корекциÑРедуциране на шумаÐищоÐормалноБрой битове на Ñемпъл, типичните ÑтойноÑти Ñа 1 за "line-art" и 8 за мултибитово Ñканиране.Брой опцииБрой на Ñканиращите линии, които ще бъдат поиÑкани при SCSI четене. ПромÑната на този параметър позволÑва да Ñе наÑтрои ÑкороÑтта, Ñ ÐºÐ¾Ñто Ñе четат данни от Ñкенера по време на Ñканиране. Ðко е прекалено ниÑък, Ñкенерът ще Ñпира периодично по Ñредата на Ñканирането; ако е твърде виÑок, X-базираните четци могат да Ñпрат да отговарÑÑ‚ на ÑъбитиÑта по X и ÑиÑтемата ви може да увиÑне.Ðомер на кадъра за ÑканиранеИзкл.Предлага Ñпециален filedescriptor за детектване дали sane_read() ще върне данни.Предложи select file descriptorОфÑетВкл.Една ÑтраницаИзвърши Ñамо ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° отÑенкитеОборудване по изборРазмер на хартиÑтаФизичеÑки размер на хартиÑта в ADFПозитивен екранПредефинирани наÑтройкиПревюРежим на превюПечатИзважда разпечатка на вÑички опции.Принт на опциитеОÑигурÑва Ñтандартни площи за Ñканиране за Ñнимки, принтирани Ñтраници и подобни.ÐšÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° качеÑтвотоКачеÑтвено ÑканиранеБързо форматиранеÐаправи произволноЗабавÑне при четенеЛимит на четенеТеÑÑ‚ Ñамо за Ñ‡ÐµÑ‚ÐµÐ½ÐµÐžÐ¿Ñ†Ð¸Ñ Ñамо за четене, коÑто указва колко опции поддържа дадено уÑтройÑтво.Ð§ÐµÑ€Ð²ÐµÐ½Ð¾Ð‘Ð°Ð»Ð°Ð½Ñ - червеноЯркоÑÑ‚ - червеноУвеличение - червеноИнтензитет - червеноОфÑет - червеноÐамали Ð¸Ð·Ð¾Ð»Ð¸Ñ€Ð°Ð½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ¾Ð² шумПоиÑкай Ñканиране за превю на качеÑтвото.ПоиÑкай вÑички превюта да Ñе правÑÑ‚ в монохромен режим. Ðа Ñкенер Ñ Ñ‚Ñ€Ð¸ минаваниÑ, това намалÑва минаваниÑта до една, а на Ñкенер Ñ ÐµÐ´Ð½Ð¾ минаване намалÑва изиÑкваниÑта към паметта и времето за Ñканиране на превюто.ПоиÑкай вÑички превюта да Ñе правÑÑ‚ в най-бърз (ниÑкокачеÑтвен) режим. Това може да е безцветен режим или режим Ñ Ð½Ð¸Ñка резолюциÑ.Върни SANE_STATUS_ACCESS_DENIEDВърни SANE_STATUS_COVER_OPENВърни SANE_STATUS_EOFВърни SANE_STATUS_IO_ERRORВърни SANE_STATUS_JAMMEDВърни SANE_STATUS_NO_DOCSВърни SANE_STATUS_NO_MEMВърни мъглÑви линии и байтове на линиÑ, когато sane_parameters() е извикано преди sane_start().Връщана ÑтойноÑÑ‚ на sane_readÐаÑитеноÑтСкаларна гамаСкаларна гама - ÑиньоСкаларна гама - зеленоСкаларна гама - червеноРежим на ÑканиранеСканирай време за екÑпониранеСканирай време за екÑпониране - ÑиньоСканирай време за екÑпониране - зеленоСканирай време за екÑпониране - червеноСканирай в бърз Ñив режим (по-ниÑко качеÑтво).Сканирай плътноÑтта на лампатаРежим на ÑÐºÐ°Ð½Ð¸Ñ€Ð°Ð½ÐµÐ ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° ÑканиранеИзточник на ÑканиранеСкороÑÑ‚ на ÑканиранеСканирай цÑлата площ за Ñканиране, вкл. парчето за калибрациÑ. Внимавайте. Ðе избирайте цÑлата виÑочина. Тази Ð¾Ð¿Ñ†Ð¸Ñ Ðµ Ñамо за теÑтване.Второ въвежданеИзбери минимална ÑркоÑÑ‚ за получаване на бÑла точкаИзбира полутонаИзбира вида на картинката за теÑтване. Възможни опции: Солидно черно: запълва цÑлото изображение Ñ Ñ‡ÐµÑ€Ð½Ð¾. Солидно бÑло: запълва цÑлото изображение Ñ Ð±Ñло. Цветен деÑен: риÑува различни цветни теÑтови деÑени, в завиÑимоÑÑ‚ от режима. Решетка: риÑува черно-бÑла решетка Ñ ÑˆÐ¸Ñ€Ð¾Ñ‡Ð¸Ð½Ð° и виÑочина от 10 мм на квадрат.Избира режима на превю. Превю по Ñива Ñкала обикновено дава най-добро Ñъотношение между ÑкороÑÑ‚ и детайлноÑÑ‚.Избира връщаната ÑтойноÑÑ‚ на sane_read(). "ВиÑÑща" (Default) е нормалната ÑтойноÑÑ‚ за Ñканиране. Ð’Ñички други ÑтатуÑ-кодове Ñа за теÑтване на това как Ñе ÑÐ¿Ñ€Ð°Ð²Ñ Ñ„Ñ€Ð¾Ð½Ñ‚ÐµÐ½Ð´Ð° Ñ Ñ‚ÑÑ….Избира картинка за теÑтванеИзбира ÑтойноÑÑ‚ за Ñкаларната гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ (Ñин канал).Избира ÑтойноÑÑ‚ за Ñкаларната гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ (зелен канал).Избира ÑтойноÑÑ‚ за Ñкаларната гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ (червен канал)Избира ÑтойноÑÑ‚ за Ñкаларната гама-корекциÑ.Избира " зърненоÑтта" на полученото изображение. По-ниÑките ÑтойноÑти дават по-изоÑтрени изображениÑ.Избира ÑркоÑтта.Избира цветовата лента. "Master" означава, че вÑички цветова Ñа заÑегнати.Избира dropout-а.Избира кривата на коригираната гамаИзбира режима за ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° гамата.Избира ÑтойноÑтта за гама ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð¾Ñ‚ ÑпиÑък предефинирани уÑтройÑтва или таблицата, определена от потребителÑ, коÑто може да Ñе Ñвали на Ñкенера.Избира полутонаИзбира номера на кадъра за ÑканиранеИзбира режим на Ñканиране (lineart, монохромно или цветно).Избира източника за Ñканирането (напр. фидер за документи).Избира кое ниво на ÑÐ¸Ð½Ñ Ð¾ÑветеноÑÑ‚ Ñе ÑмÑта за "черно".Избира кое ниво на ÑÐ¸Ð½Ñ Ð¾ÑветеноÑÑ‚ Ñе ÑмÑта за "изцÑло Ñиньо".Избира кое ниво на ÑÐ¸Ð½Ñ Ð¾ÑветеноÑÑ‚ Ñе ÑмÑта за "бÑло".Избира кое ниво на зелена оÑветеноÑÑ‚ Ñе ÑмÑта за "черно".Избира кое ниво на зелена оÑветеноÑÑ‚ Ñе ÑмÑта за "изцÑло зелено".Избира кое ниво на зелена оÑветеноÑÑ‚ Ñе ÑмÑта за "бÑло".Избира кое ниво на оÑветеноÑÑ‚ Ñе ÑмÑта за "черно".Избира кое ниво на оÑветеноÑÑ‚ Ñе ÑмÑта за "бÑло".Избира кое ниво на червена оÑветеноÑÑ‚ Ñе ÑмÑта за "черно".Избира кое ниво на червена оÑветеноÑÑ‚ Ñе ÑмÑта за "изцÑло червено".Избира кое ниво на червена оÑветеноÑÑ‚ Ñе ÑмÑта за "бÑло".Избира дали полученото изображение да бъде полутонизирано (dithered).Избира кое ниво на оÑветеноÑÑ‚ ще Ñе Ñчита за "50 % Ñиньо".Избира кое ниво на оÑветеноÑÑ‚ ще Ñе ÑмÑта за "50 % Ñиво".Избира кое ниво на оÑветеноÑÑ‚ ще Ñе ÑмÑта за "50% зелено".Избира кое ниво на оÑветеноÑÑ‚ ще Ñе ÑмÑта за "50 % червено".ÐаглаÑи виÑÑщите опции за подобрение (за ÑркоÑтта и контраÑта).ÐаглаÑи виÑÑщи опции за повишителните контроли.УÑтанови време за екÑпониранеУÑтанови плътноÑтта на лампатаÐаглаÑи ÑтойноÑтта за изоÑтрÑне.ÐаглаÑÑ Ð¿Ð¾Ñ€ÐµÐ´Ð½Ð¾Ñтта на фреймовете.ÐаглаÑÑ Ð¿Ð¾Ñ€ÐµÐ´Ð½Ð¾Ñтта на фреймовете в цветен режим при тройно минаване.ÐаглаÑÑ Ñ†Ð²ÐµÑ‚Ð½Ð°Ñ‚Ð° матрица на Ñкенера.ÐаглаÑи типа медиÑ.Включва/изключва UTAÐаглаÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ðµ на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»ÐаглаÑÑ Ð¾Ñ„Ñета на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»ÐаглаÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ðµ на ÑÐ¸Ð²Ð¸Ñ ÐºÐ°Ð½Ð°Ð»ÐаглаÑÑ Ð¾Ñ„Ñета на ÑÐ¸Ð²Ð¸Ñ ÐºÐ°Ð½Ð°Ð»ÐаглаÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ðµ на Ð·ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»ÐаглаÑÑ Ð¾Ñ„Ñета на Ð·ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»Ð’ÐºÐ»ÑŽÑ‡Ð²Ð°/изключва лампатаÐаглаÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ðµ на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»ÐаглаÑÑ Ð¾Ñ„Ñета на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»ÐаглаÑÑ Ð·Ð° ÑтойноÑти на цветови Ð±Ð°Ð»Ð°Ð½Ñ Ð¿Ñ€ÐµÐ´Ð²Ð¸Ð´ÐµÐ½Ð¸Ñ‚Ðµ от firmware-а.ÐаглаÑÑ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð°Ñ‚Ð° за цветова ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° избраното изходно уÑтройÑтво.ÐаглаÑÑ Ñ€ÐµÐ¶Ð¸Ð¼Ð° на захранванеÐаглаÑÑ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñта на фокуÑа или върху Ñтъклото, или 2,5 мм над негоÐаглаÑÑ ÑтойноÑтта на гамата за вÑички канали.ÐаглаÑÑ Ñ…Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»Ð½Ð°Ñ‚Ð° Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканираното изображение.ÐаглаÑÑ Ð¿Ð¾Ð´Ñ‡ÐµÑ€Ñ‚Ð°Ð²Ð°Ð½ÐµÑ‚Ð¾ на образаÐаглаÑÑ Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñта на Ñканираното изображение.ÐаглаÑÑ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð° на деÑена за полутонизиране (dithering), който ще Ñе използва при Ñканирането на Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ðµ.ÐаглаÑÑ Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»Ð½Ð°Ñ‚Ð° Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканираното изображение.Ðвтоматична наÑтройка на офÑет и увеличение при Ñканиране. Ðко тази Ð¾Ð¿Ñ†Ð¸Ñ Ðµ забранена, има опции за ръчната наглаÑа на аналоговите параметри на фронтенда. Тази Ð¾Ð¿Ñ†Ð¸Ñ Ðµ разрешена по подразбиране. Само за теÑтване.СÑнкаСÑнка - ÑиньоСÑнка - зеленоСÑнка - червеноСенки, полутонове, Ñветли тонове, време за екÑпониранеИзоÑтрÑнеОÑтротаИзмеÑти Ñиньо към зеленоИзмеÑти Ñиньо към червеноИзмеÑти зелено към ÑиньоИзмеÑти зелено към червеноИзмеÑти червено към ÑиньоИзмеÑти червено към зеленоКратък ÑпиÑък резолюцииИзключи лампатаИзключва лампата на ÑкенераСимплекÑноСимулира ръчен Ñкенер. Ръчните Ñкенери не знаÑÑ‚ виÑочината на изображението а приори. ВмеÑто това, те връщат виÑочина от -1. ÐаÑтройката на тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñва да теÑтвате дали четецът може правилно да Ñе Ñправи Ñ Ñ‚Ð¾Ð²Ð°. Също така, опциÑта позволÑва фикÑирана ширина от 11 Ñм.Симулира ръчен Ñкенер. Ръчните Ñкенери чеÑто не знаÑÑ‚ виÑочината на образа а приори. ВмеÑто това, те връщат ÑтойноÑÑ‚ от -1. ПуÑкането на тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñва да теÑтвате дали фронтендът може да Ñе Ñправи правилно Ñ Ñ‚Ð¾Ð²Ð°.Симулира Ñкенер Ñ Ñ‚Ñ€Ð¾Ð¹Ð½Ð¾ минаване, като връща 3 отделни пъти. Първо връща зелено, поÑле Ñиньо, а Ð½Ð°ÐºÑ€Ð°Ñ - червено.Симулира Ñкенер Ñ Ñ‚Ñ€Ð¾Ð¹Ð½Ð¾ минаване. Ð’ цветен режим Ñе предават три фрейма.Размер на лимита на четенеСолидно бÑлоПо-бавноПо-бавноÐай-бавноИзглажданеИзглажданеСолидно черноСолидно бÑлоИзбор на източникСпециални опцииСпециални опцииЗапочване на калибрациÑта.Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° ÑтатуÑ-кодСтрингови теÑтови опцииРазмени черно и бÑлоВключва/изключва лампата.Ð¢ÐµÑ…Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ Ð·Ð° оконтраÑтиране на текÑта(МакÑималното) количеÑтво данни, предадени Ñ Ð²ÑÑко повикване на sane_read().Файловото име на изображението, което ще Ñе зареди.БроÑÑ‚ пикÑели, които Ñе губÑÑ‚ в ÐºÑ€Ð°Ñ Ð½Ð° вÑÑка линиÑ.Ðивото на наÑитеноÑÑ‚ контролира нивото на "blooming" ефекта, който Ñе поÑвÑва при добиването на изображение Ñ Ñ„Ð¾Ñ‚Ð¾Ð°Ð¿Ð°Ñ€Ð°Ñ‚. По-големите ÑтойноÑти причинÑват повече blooming.Лазерни принтериТова е много дългото трето въвеждане. Може би фронтендът ще може да го покаже.Тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¸Ð·ÐºÐ»ÑŽÑ‡Ð²Ð° лампата на flatbed-а по време на ÑÐºÐ°Ð½Ð¸Ñ€Ð°Ð½ÐµÐ¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° тройно Ð¼Ð¸Ð½Ð°Ð²Ð°Ð½ÐµÐ¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° тройно минаванеПрагПревключи лампата на flatbed-аПревключва лампата на flatbed-аГорен лÑв xГорна лÑва x Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране.Горен лÑв yГорна лÑва y Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране.ПрозрачноÑÑ‚Ðдаптиране на прозрачноÑттаПрозрачноÑтИзключи лампата при излизане от програматаИзключва лампата на ÑкенераВключи лампата на ÑкенераUTA вкл.ОтзаредиОтзареди документа.Отзареждане на медиÑта Ñлед Ñканиране.Отзарежда медиÑта Ñлед Ñканиране.Обнови опциитеОбнови опциите.Използвай 0мм Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° holder фокуÑа, вмеÑто 0,6ммИзползвай композициÑта на изображението.Вътрешно използвай по-голÑма дълбочина от оÑем бита, но извеждай Ñамо оÑем бита.Използвай лична гама-таблицаИзползвай лещи, които удвоÑват оптичната резолюциÑИзползвай неблокиращ IOИзползва неблокиращ IO порт за sane_read(), ако фронтенда го поддържа.Използва Ñъщите ÑтойноÑти за вÑички цветови канали.Използвай еднакви ÑтойноÑти за X и Y резолюциÑта.Използвай адаптера за 35мм Ñветлинна капачкаПо потребителÑка дефинициÑПо потребителÑка Ð´ÐµÑ„Ð¸Ð½Ð¸Ñ†Ð¸Ñ (Гама=1,0)По потребителÑка Ð´ÐµÑ„Ð¸Ð½Ð¸Ñ†Ð¸Ñ (Гама=1,8)8x8 вертикална чертаИзчакай натиÑкане на бутонаИзчакай натиÑкане на бутонаИзчакай за натиÑкане на бутона преди Ñканиране.ЗагрÑвай, докато ÑркоÑтта на лампата е поÑтоÑнна, вмеÑто да наÑтоÑваш за 40 Ñекундно загрÑване.ЗагрÑвай, докато ÑркоÑтта на лампата е поÑтоÑнна, вмеÑто да наÑтоÑваш за 60 Ñекундно загрÑване.Загрей лампатаЗагрей лампата преди ÑканиранеСтепен на бÑлотоСтепен на бÑлото - ÑиньоСтепен на бÑлото - зеленоСтепен на бÑлото - Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¾Ð ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð¿Ð¾ Ð¥XPAXPA ÑивоXPA RGBÐ ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð¿Ð¾ YУвеличениеflatbed Ñкенерsane-backends-1.0.27/po/en@quot.po0000664000175000017500000046774013110600536013630 00000000000000# English translations for sane-backends package. # Copyright (C) 2017 The SANE developers # This file is distributed under the same license as the sane-backends package. # Automatically generated, 2017. # # All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.27\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2017-05-22 11:18-0400\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: en@quot\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Number of options" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Standard" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometry" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Enhancement" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Advanced" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Sensors" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Preview" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Force monochrome preview" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bit depth" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Scan mode" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Scan speed" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Scan source" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Force backtracking" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Top-left x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Top-left y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Bottom-right x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Bottom-right y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Scan resolution" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-resolution" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-resolution" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Page width" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Page height" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Use custom gamma table" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Image intensity" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Red intensity" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Green intensity" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Blue intensity" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Brightness" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Grain size" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Halftoning" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Black level" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "White level" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "White level for red" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "White level for green" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "White level for blue" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Shadow" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Shadow for red" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Shadow for green" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Shadow for blue" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Highlight" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Highlight for red" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Highlight for green" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Highlight for blue" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Hue" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturation" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Filename" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Halftone pattern size" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Halftone pattern" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Bind X and Y resolution" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negative" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Quality calibration" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Double Optical Resolution" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Bind RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Threshold" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analog gamma correction" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analog gamma red" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analog gamma green" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analog gamma blue" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Bind analog gamma" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Warmup lamp" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Cal. exposure-time" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Cal. exposure-time for red" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Cal. exposure-time for green" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Cal. exposure-time for blue" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Scan exposure-time" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Scan exposure-time for red" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Scan exposure-time for green" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Scan exposure-time for blue" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Set exposure-time" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Cal. lamp density" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Scan lamp density" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Set lamp density" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lamp off at exit" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Read-only option that specifies how many options a specific devices " "supports." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Source, mode and resolution options" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Scan area and media size options" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Image modification options" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Hardware specific options" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Scanner sensors and buttons" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Request a preview-quality scan." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Number of bits per sample, typical values are 1 for “line-art†and 8 for " "multibit scans." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Selects the scan mode (e.g., lineart, monochrome, or color)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Determines the speed at which the scan proceeds." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Selects the scan source (such as a document-feeder)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Controls whether backtracking is forced." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Top-left x position of scan area." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Top-left y position of scan area." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Bottom-right x position of scan area." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Bottom-right y position of scan area." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Sets the resolution of the scanned image." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Sets the horizontal resolution of the scanned image." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Sets the vertical resolution of the scanned image." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Specifies the height of the media." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Determines whether a builtin or a custom gamma-table should be used." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Gamma-correction table for the red band." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Gamma-correction table for the green band." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Gamma-correction table for the blue band." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Controls the brightness of the acquired image." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Controls the contrast of the acquired image." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Selects the “graininess†of the acquired image. Smaller values result " "in sharper images." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Selects whether the acquired image should be halftoned (dithered)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Selects what radiance level should be considered “blackâ€." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Selects what radiance level should be considered “whiteâ€." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "Selects what red radiance level should be considered “whiteâ€." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "Selects what green radiance level should be considered “whiteâ€." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "Selects what blue radiance level should be considered “whiteâ€." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "Selects what red radiance level should be considered “blackâ€." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "Selects what green radiance level should be considered “blackâ€." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "Selects what blue radiance level should be considered “blackâ€." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "Selects what red radiance level should be considered “full redâ€." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Selects what green radiance level should be considered “full greenâ€." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "Selects what blue radiance level should be considered “full blueâ€." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Controls the “hue†(blue-level) of the acquired image." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "The saturation level controls the amount of “blooming†that occurs when " "acquiring an image with a camera. Larger values cause more blooming." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "The filename of the image to be loaded." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Defines the halftoning (dithering) pattern for scanning halftoned images." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Use same values for X and Y resolution" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Swap black and white" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Do a quality white-calibration" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Use lens that doubles optical resolution" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "In RGB-mode use same values for each color" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Select minimum-brightness to get a white point" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analog gamma-correction" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analog gamma-correction for red" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analog gamma-correction for green" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analog gamma-correction for blue" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Warmup lamp before scanning" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Define exposure-time for calibration" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Define exposure-time for red calibration" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Define exposure-time for green calibration" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Define exposure-time for blue calibration" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Define exposure-time for scan" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Define exposure-time for red scan" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Define exposure-time for green scan" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Define exposure-time for blue scan" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Enable selection of exposure-time" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Define lamp density for calibration" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Define lamp density for scan" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Enable selection of lamp density" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Turn off lamp when program exits" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Scan button" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "Email button" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Fax button" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Copy button" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "PDF button" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Cancel button" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Page loaded" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Cover open" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Color" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Color Lineart" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Color Halftone" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Gray" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Halftone" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Lineart" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "Success" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Operation not supported" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "Operation was cancelled" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "Device busy" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Invalid argument" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "End of file reached" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Document feeder jammed" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "Document feeder out of documents" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "Scanner cover is open" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Error during device I/O" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Out of memory" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "Access to resource has been denied" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "Lamp not ready, please retry" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "Scanner mechanism locked for transport" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Defaults" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Set default values for enhancement controls." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Calibration" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Calibrate before next scan" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Only perform shading-correction" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Button state" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Number of the frame to scan" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Selects the number of the frame to scan" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Duplex scan" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "Duplex scan provide a scan of the front and back side of the document" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Calibrate Scanner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Force scanner calibration before scan" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Grayscale scan" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Do a grayscale rather than color scan" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analog Gain" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Increase or decrease the analog gain of the CCD array" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gamma Correction" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Selects the gamma corrected transfer curve" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Raw" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Fine color" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "No transparency correction" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Correction according to film type" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Correction according to transparency ratio" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negatives" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Slides" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatic" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Normal speed" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 normal speed" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 normal speed" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "rounded parameter" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "unknown" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "ADF jam" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "ADF cover open" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "lamp failure" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "scan head positioning error" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "CPU check error" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "RAM check error" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "ROM check error" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "hardware check error" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "transparency unit lamp failure" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "transparency unit scan head positioning failure" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "parameter list length error" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "invalid command operation code" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "invalid field in CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "unsupported LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "invalid field in parameter list" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "command sequence error" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "too many windows specified" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "medium not present" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "invalid bit IDENTIFY message" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "option not connect" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "power on reset / bus device reset" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parameter changed by another initiator" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "no additional sense information" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "reselect failure" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "SCSI parity error" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "initiator detected error message received" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "invalid message error" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "timeout error" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "transparency unit shading error" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lamp not stabilized" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "film scanner" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "flatbed scanner" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Film type" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Selects the film type, i.e. negatives or slides" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Negative film type" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Selects the negative film type" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Hardware resolution" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Use only hardware resolutions" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Focus" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Auto focus" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Enable/disable auto focus" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Auto focus only once" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Do auto focus only once between ejects" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Manual focus position" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "Set the optical system's focus position by hand (default: 128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Scan margins" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Extra color adjustments" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Mirror image" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Mirror the image horizontally" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Auto exposure" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Enable/disable the auto exposure feature" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Calibration now" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Execute calibration *now*" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Self diagnosis" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Perform scanner self diagnosis" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Reset scanner" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Reset the scanner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Medium handling" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Eject film after each scan" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Automatically eject the film from the device after each scan" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Eject film before exit" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Automatically eject the film from the device before exiting the program" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Eject film now" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Eject the film *now*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Document feeder extras" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Flatbed only" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "Disable auto document feeder and use flatbed only" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Transparency unit" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "Switch on/off the transparency unit (FAU, film adapter unit)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Negative film" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Positive or negative film" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Density control" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Set density control mode" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Transparency ratio" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Select film type" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Select the film type" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flatbed" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "ADF Front" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "ADF Back" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "ADF Duplex" #: backend/canon_dr.c:412 #, no-c-format msgid "Card Front" msgstr "Card Front" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "Card Back" #: backend/canon_dr.c:414 #, no-c-format msgid "Card Duplex" msgstr "Card Duplex" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Red" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Green" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Blue" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "Enhance Red" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "Enhance Green" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "Enhance Blue" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "None" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "JPEG" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "Software blank skip percentage" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "Request driver to discard pages with low percentage of dark pixels" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Simplex" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Duplex" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Transparency Unit" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatic Document Feeder" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Positive Film" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negative Film" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Focus on glass" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Focus 2.5mm above glass" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Halftone A (Hard Tone)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Halftone B (Soft Tone)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Halftone C (Net Screen)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Dither A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Dither B (4x4 Spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Dither C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Dither D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Text Enhanced Technology" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Download pattern A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Download pattern B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "No Correction" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "User defined" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Impact-dot printers" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Thermal printers" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Ink-jet printers" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT monitors" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Default" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "High density printing" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Low density printing" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "High contrast printing" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "User defined (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "User defined (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 portrait" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 landscape" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Max" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Scan Mode" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Selects the halftone." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Dropout" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Selects the dropout." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Selects the brightness." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Sharpness" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Color correction" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Sets the color correction table for the selected output device." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Color correction coefficients" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matrix multiplication of RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Shift green to red" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Shift green to blue" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Shift red to green" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Shift red to blue" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Shift blue to green" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Shift blue to red" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Controls green level" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Adds to red based on green level" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Adds to blue based on green level" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Adds to green based on red level" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Controls red level" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Adds to blue based on red level" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Adds to green based on blue level" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Adds to red based on blue level" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Controls blue level" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Mirror the image." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Fast preview" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Auto area segmentation" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Short resolution list" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Display short resolution list" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Zoom" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Defines the zoom factor the scanner will use" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Quick format" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Optional equipment" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Eject" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Eject the sheet in the ADF" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Auto eject" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Eject document after scanning" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "ADF Mode" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Selects the ADF mode (simplex/duplex)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Bay" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Select bay to scan" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Focus Position" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Sets the focus position to either the glass or 2.5mm above the glass" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Wait for Button" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "Infrared" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "TPU8x10" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Positive Slide" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Negative Slide" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "Built in CCT profile" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "User defined CCT profile" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "On" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Off" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "DTC" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "SDTC" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Dither" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "Diffusion" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "White" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "Black" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Continue" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Stop" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10mm" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15mm" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20mm" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontal" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "Horizontal bold" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "Horizontal narrow" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertical" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "Vertical bold" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "Top to bottom" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "Bottom to top" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "Front" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "Back" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "Gamma function exponent" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "Changes intensity of midtones" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "RIF" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "Reverse image format" #: backend/fujitsu.c:3165 #, no-c-format msgid "Halftone type" msgstr "Halftone type" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "Control type of halftone filter" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "Control pattern of halftone filter" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "Outline" #: backend/fujitsu.c:3210 #, no-c-format msgid "Perform outline extraction" msgstr "Perform outline extraction" #: backend/fujitsu.c:3221 #, no-c-format msgid "Emphasis" msgstr "Emphasis" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "Negative to smooth or positive to sharpen image" #: backend/fujitsu.c:3240 #, no-c-format msgid "Separation" msgstr "Separation" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "Enable automatic separation of image and text" #: backend/fujitsu.c:3252 #, no-c-format msgid "Mirroring" msgstr "Mirroring" #: backend/fujitsu.c:3253 #, no-c-format msgid "Reflect output image horizontally" msgstr "Reflect output image horizontally" #: backend/fujitsu.c:3270 #, no-c-format msgid "White level follower" msgstr "White level follower" #: backend/fujitsu.c:3271 #, no-c-format msgid "Control white level follower" msgstr "Control white level follower" #: backend/fujitsu.c:3289 #, no-c-format msgid "BP filter" msgstr "BP filter" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "Improves quality of high resolution ball-point pen text" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Smoothing" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "Enable smoothing for improved OCR" #: backend/fujitsu.c:3323 #, no-c-format msgid "Gamma curve" msgstr "Gamma curve" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "Gamma curve, from light to dark, but upper two may not work" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "Threshold curve" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" "Threshold curve, from light to dark, but upper two may not be linear" #: backend/fujitsu.c:3369 #, no-c-format msgid "Threshold white" msgstr "Threshold white" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "Set pixels equal to threshold to white instead of black" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, no-c-format msgid "Noise removal" msgstr "Noise removal" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "Matrix 5x5" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "Remove 5 pixel square noise" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "Matrix 4x4" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "Remove 4 pixel square noise" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "Matrix 3x3" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "Remove 3 pixel square noise" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "Matrix 2x2" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "Remove 2 pixel square noise" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "Variance" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "Set SDTC variance rate (sensitivity), 0 equals 127" #: backend/fujitsu.c:3508 #, no-c-format msgid "Auto width detection" msgstr "Auto width detection" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "Scanner detects paper sides. May reduce scanning speed." #: backend/fujitsu.c:3526 #, no-c-format msgid "Auto length detection" msgstr "Auto length detection" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "Scanner detects paper lower edge. May confuse some frontends." #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "Compression" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "Enable compressed data. May crash your front-end program" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "Compression argument" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "DF action" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "Action following double feed error" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "DF skew" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "Enable double feed error due to skew" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "DF thickness" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "Enable double feed error due to paper thickness" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "DF length" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "Enable double feed error due to paper length" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "DF length difference" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "Difference in page length to trigger double feed error" #: backend/fujitsu.c:3708 #, no-c-format msgid "DF recovery mode" msgstr "DF recovery mode" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "Request scanner to reverse feed on paper jam" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "Paper protection" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "Request scanner to predict jams in the ADF" #: backend/fujitsu.c:3748 #, no-c-format msgid "Advanced paper protection" msgstr "Advanced paper protection" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "Request scanner to predict jams in the ADF using improved sensors" #: backend/fujitsu.c:3768 #, no-c-format msgid "Staple detection" msgstr "Staple detection" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "Request scanner to detect jams in the ADF caused by staples" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "Background color" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" "Set color of background for scans. May conflict with overscan option" #: backend/fujitsu.c:3809 #, no-c-format msgid "Dropout color" msgstr "Dropout color" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" #: backend/fujitsu.c:3833 #, no-c-format msgid "Buffer mode" msgstr "Buffer mode" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" "Request scanner to read pages quickly from ADF into internal memory" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "Prepick" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "Request scanner to grab next page from ADF" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "Overscan" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "Sleep timer" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" "Time in minutes until the internal power supply switches to sleep mode" #: backend/fujitsu.c:3911 #, no-c-format msgid "Off timer" msgstr "Off timer" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." #: backend/fujitsu.c:3930 #, no-c-format msgid "Duplex offset" msgstr "Duplex offset" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "Adjust front/back offset" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Green offset" #: backend/fujitsu.c:3949 #, no-c-format msgid "Adjust green/red offset" msgstr "Adjust green/red offset" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Blue offset" #: backend/fujitsu.c:3967 #, no-c-format msgid "Adjust blue/red offset" msgstr "Adjust blue/red offset" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "Low Memory" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option ‘side’ can be used to determine correct image. This option should " "only be used with custom front-end software." #: backend/fujitsu.c:3996 #, no-c-format msgid "Duplex side" msgstr "Duplex side" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "Hardware deskew and crop" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "Request scanner to rotate and crop pages digitally." #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "Software deskew" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "Request driver to rotate skewed pages digitally." #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "Software despeckle diameter" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "Maximum diameter of lone dots to remove from scan." #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "Software crop" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "Request driver to remove border from pages digitally." #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "Halt on Cancel" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" "Request driver to halt the paper feed instead of eject during a cancel." #: backend/fujitsu.c:4095 #, no-c-format msgid "Endorser Options" msgstr "Endorser Options" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "Controls for endorser unit" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "Endorser" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "Enable endorser unit" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "Endorser bits" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "Determines maximum endorser counter value." #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "Endorser value" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "Initial endorser counter value." #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "Endorser step" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "Change endorser counter value by this much for each page." #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "Endorser Y" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "Endorser print offset from top of paper." #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "Endorser font" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "Endorser printing font." #: backend/fujitsu.c:4253 #, no-c-format msgid "Endorser direction" msgstr "Endorser direction" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "Endorser printing direction." #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "Endorser side" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "Endorser printing side, requires hardware support to change" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "Endorser string" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "Top edge" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "Paper is pulled partly into adf" #: backend/fujitsu.c:4344 #, no-c-format msgid "A3 paper" msgstr "A3 paper" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "A3 paper detected" #: backend/fujitsu.c:4356 #, no-c-format msgid "B4 paper" msgstr "B4 paper" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "B4 paper detected" #: backend/fujitsu.c:4368 #, no-c-format msgid "A4 paper" msgstr "A4 paper" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "A4 paper detected" #: backend/fujitsu.c:4380 #, no-c-format msgid "B5 paper" msgstr "B5 paper" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "B5 paper detected" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "OMR or DF" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "OMR or double feed detected" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "Power saving" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "Scanner in power saving mode" #: backend/fujitsu.c:4452 #, no-c-format msgid "Manual feed" msgstr "Manual feed" #: backend/fujitsu.c:4453 #, no-c-format msgid "Manual feed selected" msgstr "Manual feed selected" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "Function" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "Function character on screen" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "Ink low" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "Imprinter ink running low" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "Double feed" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "Double feed detected" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "Error code" #: backend/fujitsu.c:4513 #, no-c-format msgid "Hardware error code" msgstr "Hardware error code" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "Skew angle" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "Requires black background for scanning" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "Ink remaining" #: backend/fujitsu.c:4537 #, no-c-format msgid "Imprinter ink level" msgstr "Imprinter ink level" #: backend/fujitsu.c:4548 #, no-c-format msgid "Density" msgstr "Density" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "Density dial" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, no-c-format msgid "Duplex switch" msgstr "Duplex switch" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "Request backend to remove border from pages digitally" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "Request driver to discard pages with low numbers of dark pixels" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "Software derotate" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "Request driver to detect and correct 90 degree image rotation" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extras" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "Dynamic threshold curve, from light to dark, normally 50-65" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "Disable dynamic lineart" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Disable interpolation" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." #: backend/genesys.c:5872 #, no-c-format msgid "Color filter" msgstr "Color filter" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "When using gray or lineart this option selects the used color." #: backend/genesys.c:5901 #, no-c-format msgid "Calibration file" msgstr "Calibration file" #: backend/genesys.c:5902 #, no-c-format msgid "Specify the calibration file to use" msgstr "Specify the calibration file to use" #: backend/genesys.c:5919 #, no-c-format msgid "Calibration cache expiration time" msgstr "Calibration cache expiration time" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Lamp off time" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." #: backend/genesys.c:5943 #, no-c-format msgid "Lamp off during scan" msgstr "Lamp off during scan" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "The lamp will be turned off during scan. " #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "File button" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "OCR button" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Power button" #: backend/genesys.c:6053 backend/genesys.c:6054 #, no-c-format msgid "Extra button" msgstr "Extra button" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "Need calibration" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "The scanner needs calibration for the current settings" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Buttons" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Calibrate" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Start calibration using special sheet" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Clear calibration" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Clear calibration cache" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Transparency Adapter" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Gray mode color" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "Selects which scan color is used gray mode (default: green)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Debugging Options" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatic warmup" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Full scan" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Coarse calibration" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Coarse calibration for first scan only" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Backtrack lines" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gamma value" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Sets the gamma value of all channels." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Geometry Group" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Scan Mode Group" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Slide" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Scanner model" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "Allows one to test device behaviour with other supported models" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Image colours will be inverted" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Disable gamma correction" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "Gamma correction will be disabled" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Disable white shading correction" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "White shading correction will be disabled" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Skip warmup process" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "Warmup process will be disabled" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Force real depth" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Emulate Grayscale" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Save debugging images" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "If enabled, some images involved in scanner processing are saved to " "analyze them." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Reset chipset" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Resets chipset data" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Information" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Chipset name" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Shows chipset name used in device." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Unknown" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "Chipset ID" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Shows the chipset ID" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Scan counter" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Shows the number of scans made by scanner" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Update information" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Updates information about device" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "This option reflects a front panel scanner button" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Image" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Miscellaneous" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "offset X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Hardware internal X position of the scanning area." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "offset Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Hardware internal Y position of the scanning area." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Lamp status" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Switches the lamp on or off." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Calibrates for black and white level." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMA Slides" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMA Negatives" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Color (48 bits)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Extend lamp timeout" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Extends lamp timeout (from 15 minutes to 1 hour)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Wait for button" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Waits for button before scanning" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Advanced Options" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Coarse" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fine" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Custom" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Auto" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Pass-through" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Gray" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA Gray" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Slow" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Fast" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Extra Fast" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-pixel" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-pixel" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-pixel" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Print" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Film-strip" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Conditional" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Experiment" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Sharpening" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Set sharpening value." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Auto Threshold" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "Enable automatic determination of threshold for line-art scans." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Select smoothing filter." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Unload media after scan" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Unloads the media after a scan." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Change document" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Change Document." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Unload" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Unload Document." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Start calibration process." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Media" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Set type of media." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Exposure time" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and “Negative†for " "negative film. For dark (underexposed) images you can increase this " "value." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Color Matrix" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Set the scanners color matrix." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Custom color matrix." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Mono Color Matrix" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Custom color matrix for grayscale scans." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Mirror horizontal" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Mirror image horizontally." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Mirror vertical" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Mirror image vertically." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Update options" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Update options." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8 bit output" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Use bit depth greater eight internally, but output only eight bits." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Front button wait" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Wait to scan for front-panel button push." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Shut off lamp" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Shut off scanner lamp." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Paper size" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatic separation" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, no-c-format msgid "Landscape" msgstr "Landscape" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "Inverse Image" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "Long paper mode" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "Length control mode" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "Manual feed mode" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, no-c-format msgid "Manual feed timeout" msgstr "Manual feed timeout" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "Double feed detection" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Enable Duplex (Dual-Sided) Scanning" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Physical size of the paper in the ADF" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "bw" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "halftone" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "gray" #: backend/kvs1025_opt.c:42 #, no-c-format msgid "color" msgstr "color" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "adf" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "fb" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "single" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "continuous" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "off" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "wait_doc" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "wait_key" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "user_def" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "business_card" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "Check" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "A5" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "A6" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "B5" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "B6" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "Legal" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "bayer_64" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "bayer_16" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "halftone_32" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "halftone_64" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "diffusion" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, no-c-format msgid "normal" msgstr "normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, no-c-format msgid "light" msgstr "light" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "dark" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, no-c-format msgid "From scanner" msgstr "From scanner" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "From paper" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, no-c-format msgid "default" msgstr "default" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "smooth" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "none" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, no-c-format msgid "low" msgstr "low" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, no-c-format msgid "medium" msgstr "medium" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "high" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "crt" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "linier" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, no-c-format msgid "red" msgstr "red" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, no-c-format msgid "green" msgstr "green" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "blue" #: backend/kvs1025_opt.c:562 #, no-c-format msgid "Sets the scan source" msgstr "Sets the scan source" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Feeder mode" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Sets the feeding mode" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "Enable/Disable long paper mode" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "Enable/Disable length control mode" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, no-c-format msgid "Sets the manual feed mode" msgstr "Sets the manual feed mode" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Sets the manual feed timeout in seconds" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "Enable/Disable double feed detection" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "fit-to-page" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "Fit to page" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "Scanner shrinks image to fit scanned page" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "Set paper position : true for landscape, false for portrait" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatic threshold" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Noise reduction" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Reduce the isolated dot noise" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Image emphasis" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Sets the image emphasis" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, no-c-format msgid "Lamp color" msgstr "Lamp color" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Sets the lamp color (color dropout)" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "Inverse image in B/W or halftone mode" #: backend/kvs1025_opt.c:840 #, no-c-format msgid "Mirror image (left/right flip)" msgstr "Mirror image (left/right flip)" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "jpeg compression" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "JPEG Image Compression with Q parameter, ‘0’ - no compression" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "Rotate image clockwise" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "Request driver to rotate pages by a fixed amount" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "Request driver to rotate skewed pages digitally" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "Maximum diameter of lone dots to remove from scan" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "Software automatic cropping" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "Request driver to remove border from pages digitally" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gamma correction" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "wait_doc_hopper_up" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "A3" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "Double letter 11x17 in" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "B4" #: backend/kvs40xx_opt.c:231 #, no-c-format msgid "High sensivity" msgstr "High sensivity" #: backend/kvs40xx_opt.c:232 #, no-c-format msgid "Low sensivity" msgstr "Low sensivity" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "err_diffusion" #: backend/kvs40xx_opt.c:249 #, no-c-format msgid "No detection" msgstr "No detection" #: backend/kvs40xx_opt.c:250 #, no-c-format msgid "Normal mode" msgstr "Normal mode" #: backend/kvs40xx_opt.c:251 #, no-c-format msgid "Enhanced mode" msgstr "Enhanced mode" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "Double feed detector sensitivity" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "Set the double feed detector sensitivity" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "Do not stop after double feed detection" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "Ignore left double feed sensor" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "Ignore center double feed sensor" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "Ignore right double feed sensor" #: backend/kvs40xx_opt.c:642 #, no-c-format msgid "Automatic threshold mode" msgstr "Automatic threshold mode" #: backend/kvs40xx_opt.c:643 #, no-c-format msgid "Sets the automatic threshold mode" msgstr "Sets the automatic threshold mode" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "Inverse image in B/W mode" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "JPEG compression" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "JPEG compression (yours application must be able to uncompress)" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "Detect stapled document" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "chroma of red" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "Set chroma of red" #: backend/kvs40xx_opt.c:787 #, no-c-format msgid "chroma of blue" msgstr "chroma of blue" #: backend/kvs40xx_opt.c:788 #, no-c-format msgid "Set chroma of blue" msgstr "Set chroma of blue" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "Skew adjustment" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "Stop scanner when a paper have been skewed" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "Scanner will be stop when a paper have been skewed" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "Crop actual image area" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "Scanner automatically detect image area and crop it" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "It is right and left reversing" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "Addition of space in top position" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "Addition of space in bottom position" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamond" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 Coarse Fatting" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 Fine Fatting" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Vertical Line" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Gain" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Color channels gain settings" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Gray gain" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Sets gray channel gain" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Red gain" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Sets red channel gain" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Green gain" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Sets green channel gain" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Blue gain" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Sets blue channel gain" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer Dither 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer Dither 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Halftone Dot 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Halftone Dot 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Error Diffusion" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Mode 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Mode 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Mode 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "From white stick" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Smooth" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Low" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Medium" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "High" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "One page" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "All pages" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "sheetfed scanner" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Grayscale 4 bits" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Grayscale 8 bits" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Shadow, midtone, highlight, exposure time" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Special options" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Color balance" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Disable backtracking" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "If checked the scanner does not perform backtracking" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Toggle lamp of flatbed" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Toggles the lamp of the flatbed" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Calibration by backend" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "If checked the color calibration before a scan is done by the backend" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Use the lightlid-35mm adapter" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "This option turns off the lamp of the flatbed during a scan" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Quality scan" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Highest quality but lower speed" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Fast scan" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Highest speed but lower quality" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatic adjustment of threshold" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Selects the gamma correction mode." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Bind gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Use same gamma values for all colour channels." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Scalar gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Selects a value for scalar gamma correction." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Scalar gamma red" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Selects a value for scalar gamma correction (red channel)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Scalar gamma green" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Selects a value for scalar gamma correction (green channel)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Scalar gamma blue" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Selects a value for scalar gamma correction (blue channel)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Channel" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Selects the colour band, “Master†means that all colours are affected." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Midtone" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Selects which radiance level should be considered “50 % grayâ€." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Midtone for red" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Selects which radiance level should be considered “50 % redâ€." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Midtone for green" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Selects which radiance level should be considered “50 % greenâ€." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Midtone for blue" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Selects which radiance level should be considered “50 % blueâ€." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Red balance" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Balance factor for red. A value of 100% means no correction." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Green balance" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Balance factor for green. A value of 100% means no correction." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Blue balance" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Balance factor for blue. A value of 100% means no correction." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Firmware balance" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Sets the color balance values to the firmware provided values." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Slowest" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Slower" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Faster" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Fastest" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 coarse" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fine" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 very fine" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normal" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 coarse" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fine" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 coarse" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normal" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fine" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 custom" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 custom" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 custom" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 custom" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 custom" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 custom" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Fast gray mode" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Scan in fast gray mode (lower quality)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Lamp off time (minutes)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Set the time (in minutes) after which the lamp is shut off." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Turn lamp off" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Turns the lamp off immediately." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Red brightness" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Controls the brightness of the red channel of the acquired image." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Green brightness" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "" "Controls the brightness of the green channel of the acquired image." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Blue brightness" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Controls the brightness of the blue channel of the acquired image." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contrast red channel" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Controls the contrast of the red channel of the acquired image." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contrast green channel" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Controls the contrast of the green channel of the acquired image." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contrast blue channel" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Controls the contrast of the blue channel of the acquired image." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Color48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Color24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Gray16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Gray8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Reflective" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positive" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." #: backend/pixma.c:378 #, no-c-format msgid "Negative color" msgstr "Negative color" #: backend/pixma.c:383 #, no-c-format msgid "Negative gray" msgstr "Negative gray" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "48 bits color" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "16 bits gray" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Button-controlled scan" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "When enabled, scan process will not start immediately. To proceed, press " "“SCAN†button (for MP150) or “COLOR†button (for other models). To " "cancel, press “GRAY†button." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Update button state" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Button 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Button 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "Type of original to scan" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "Target operation type" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "ADF Waiting Time" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Transparency" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Device-Settings" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Lampswitch" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Manually switching the lamp(s)." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Lamp off during dark calibration" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Always switches lamp off when doing dark calibration." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Calibration data cache" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Enables or disables calibration data cache." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Performs calibration" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Speedup sensor" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Enables or disables speeding up sensor movement." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Warmup-time" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Warmup-time in seconds." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Lampoff-time" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Lampoff-time in seconds." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Analog frontend" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Red gain value of the AFE" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Red offset" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Red offset value of the AFE" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Green gain value of the AFE" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Green offset value of the AFE" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Blue gain value of the AFE" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Blue offset value of the AFE" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Red lamp off" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Defines red lamp off parameter" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Green lamp off" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Defines green lamp off parameter" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Blue lamp off" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Defines blue lamp off parameter" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "This option reflects the status of the scanner buttons." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Color36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Dithermap 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Dithermap 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Randomize" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Source Selection" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Image Enhancement" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Grayify" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Load the image as grayscale." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Three-Pass Simulation" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Hand-Scanner Simulation" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Set default values for enhancement controls (brightness & contrast)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Read only test-option" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Let's see whether frontends can treat this right" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Gamma Tables" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Status Code Simulation" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Do not force status code" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Do not force the backend to return a status code." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Return SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Return SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Return SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Return SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Return SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Return SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Return SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "This option reflects the status of a scanner button." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lamp on" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Turn on scanner lamp" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lamp off" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Turn off scanner lamp" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Lamp timeout" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Minutes until lamp is turned off after scan" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Threshold value for lineart mode" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Document Feeder" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (inch)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (inch)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (inch)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Halftoning Unsupported" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "Frame number of media holder that should be scanned." #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "Use manual or automatic selection of focus point." #: backend/snapscan-options.c:117 #, no-c-format msgid "Focus point for scanning." msgstr "Focus point for scanning." #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Preview mode" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Predefined settings" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Provides standard scanning areas for photographs, printed pages and the " "like." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "Frame" #: backend/snapscan-options.c:885 #, no-c-format msgid "Frame to be scanned" msgstr "Frame to be scanned" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "Focus-mode" #: backend/snapscan-options.c:898 #, no-c-format msgid "Auto or manual focus" msgstr "Auto or manual focus" #: backend/snapscan-options.c:911 #, no-c-format msgid "Focus-point" msgstr "Focus-point" #: backend/snapscan-options.c:912 #, no-c-format msgid "Focus point" msgstr "Focus point" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Colour lines per read" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Greyscale lines per read" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "webcam" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Color RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Color RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Color RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Solid black" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Solid white" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Color pattern" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Grid" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "First entry" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Second entry" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Hand-scanner simulation" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Three-pass simulation" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Set the order of frames" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Set the order of frames in three-pass color mode." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "If Automatic Document Feeder is selected, the feeder will be ‘empty’ " "after 10 scans." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Special Options" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Select the test picture" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Invert endianness" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Read limit" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Limit the amount of data transferred with each call to sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Size of read-limit" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "The (maximum) amount of data transferred with each call to sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Read delay" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Delay the transfer of data to the pipe." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Duration of read-delay" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "How long to wait after transferring each buffer of data through the pipe." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Return-value of sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Select the return-value of sane_read(). “Default†is the normal handling " "for scanning. All other status codes are for testing how the frontend " "handles them." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Loss of pixels per line" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "The number of pixels that are wasted at the end of each line." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Fuzzy parameters" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Use non-blocking IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "Use non-blocking IO for sane_read() if supported by the frontend." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Offer select file descriptor" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Enable test options" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Print options" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Print a list of all options." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Bool test options" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Bool soft select soft detect" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Bool hard select soft detect" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Bool hard select" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Bool soft detect" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Bool soft select soft detect emulated" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Bool soft select soft detect auto" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Int test options" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Int" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Int test option with no unit and no constraint set." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Int constraint range" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Int constraint word list" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "(3/6) Int test option with unit bits and constraint word list set." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Int array" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Int test option with unit mm and using an array without " "constraints." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Int array constraint range" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Int array constraint word list" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Fixed test options" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Fixed" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) Fixed test option with no unit and no constraint set." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Fixed constraint range" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Fixed constraint word list" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "(3/3) Fixed test option with no unit and constraint word list set." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "String test options" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) String" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) String test option without constraint." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) String constraint string list" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) String test option with string list constraint." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) String constraint long string list" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) String test option with string list constraint. Contains some more " "entries..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Button test options" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Button" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Button test option. Prints some text..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Color 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Use Image Composition" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Bi-level black and white (lineart mode)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Dithered/halftone black & white (halftone mode)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Multi-level black & white (grayscale mode)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Multi-level RGB color (one pass color)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignore calibration" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Disable pre focus" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Do not calibrate focus" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Manual pre focus" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Fix focus position" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Lens calibration in doc position" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Calibrate lens focus in document position" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Holder focus position 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Use 0mm holder focus position instead of 0.6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Calibration mode" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Define calibration mode" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Sets lamp on/off" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA on" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Sets UTA on/off" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Offset" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Color channels offset settings" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Gray offset" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Sets gray channel offset" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Sets red channel offset" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Sets green channel offset" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Sets blue channel offset" sane-backends-1.0.27/po/insert-header.sin0000664000175000017500000000124012775312262015111 00000000000000# Sed script that inserts the file called HEADER before the header entry. # # At each occurrence of a line starting with "msgid ", we execute the following # commands. At the first occurrence, insert the file. At the following # occurrences, do nothing. The distinction between the first and the following # occurrences is achieved by looking at the hold space. /^msgid /{ x # Test if the hold space is empty. s/m/m/ ta # Yes it was empty. First occurrence. Read the file. r HEADER # Output the file's contents by reading the next line. But don't lose the # current line while doing this. g N bb :a # The hold space was nonempty. Following occurrences. Do nothing. x :b } sane-backends-1.0.27/po/gl.po0000664000175000017500000047066313110600537012616 00000000000000# Galiciantranslation of sane-backends.po # Copyright (C) 2002 SANE Project. # This file is distributed under the same license as the sane-backends package. # Miguel Anxo Bouzada ,2009. # Anton Meixome , 2009. msgid "" msgstr "" "Project-Id-Version: sane-backends\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2009-06-25 10:22+0100\n" "Last-Translator: Miguel Anxo Bouzada \n" "Language-Team: Galician \n" "Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" "Plural-Forms: nplurals=2: plural=(n != 1);\n" "X-Poedit-Language: Galician\n" "X-Poedit-Country: SPAIN\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Número de opcións" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Estándar" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Xeometría" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Optimización" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Avanzado" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Sensores" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Vista previa" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Forzar vista previa monocroma" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bit de profundidade" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Modo de escaneo" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Velocidade de escaneo" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Orixe de escaneo" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Forzar retroceso" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Arriba-esquerda X" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Arriba-esquerda Y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Abaixo-dereita X" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Abaixo-dereita Y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Resolución de escaneo" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Resolución X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Resolución Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Ancho de páxina" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Altura de páxina" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Usar táboa gamma personalizada" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Intensidade da imaxe" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Intensidade de vermello" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Intensidade de verde" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Intensidade de azul" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Brillo" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contraste" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Tamaño do gran" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Medios tons" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Nivel do negro" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Nivel do branco" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Nivel do branco para vermello" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Nivel do branco para verde" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Nivel do branco para azul" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Sombra" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Sombra para vermello" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Sombra para verde" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Sombra para azul" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Resaltar" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Resalte para vermello" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Resalte para verde" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Resalte para azul" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Matiz" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturación" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Nome do ficheiro" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Tamaño do patrón de medios tons" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Patrón de medios tons" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Ligar resolucións X e Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativo" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Calibración da calidade" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Dobre resolución óptica" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Ligar RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Limiar" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Corrección gamma analóxica" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Gamma analóxica vermella" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Gamma analóxica verde" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Gamma analóxica azul" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Ligar gamma analógico" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Quecemento da lámpada" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Cal. tempo de exposición" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Cal. tempo de exposición para vermello" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Cal. tempo de exposición para verde" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Cal. tempo de exposición para azul" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Tempo de exposición para escaneo" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Tempo de exposición para vermello" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Tempo de exposición para verde" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Tempo de exposición para azul" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Axustar tempo de exposición" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Cal. densidade da lámpada" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Densidade da lámpada de escaneo" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Axustar a densidade da lámpada" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Apagar a lámpada ao saír" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Opción de só lectura que define cantas opcións soporta un dispositivo " "específico." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Orixe, opcións de modo e resolución" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Opcións da área de escaneo e tamaño do soporte" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Opcións de modificación de imaxe" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Opcións especificas de hardaware" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Sensores e botóns do escáner" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Solicitar unha vista previa de calidade d escaneo." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Solicitar que todas as vistas previas sexan feitas en modo monocromo. " "Nun escáner de tres pasadas isto reduce o número de pasadas a unha, e " "nun escáner dunha pasada isto reduce o requisitos de memoria e o tempo " "de escaneo da vista previa." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Número de bits por mostra, valores típicos son 1 para «liña de arte» e 8 " "para escaneos multibit." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Selecciona o modo de escaneo (ex. liña de arte, monocromo, ou cor)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Determina a velocidade á que se fai o escaneo." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "" "Selecciona a orixe do escaneo (como pode ser un alimentador de " "documentos)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Controla se se forza o retroceso" #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Posición X arriba-esquerda da área de escaneo." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Posición Y arriba-esquerda da área de escaneo." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Posición X abaixo-dereita da área de escaneo." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Posición Y abaixo-dereita da área de escaneo." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Axusta a resolución da imaxe escaneada." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Axusta a resolución horizontal da imaxe escaneada." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Axusta a resolución vertical da imaxe escaneada." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Especifica a anchura do soporte. É preciso para o centrado automático de " "follas de escaneo." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Especifica a altura do soporte" #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Determina se se debe usarse unha táboa gamma interna ou personalizada." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Táboa de corrección gamma. No modo cor, esta opción afecta igualmente as " "canles vermella, verde e azul de vez (ex. é unha táboa de intensidade " "gamma)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Táboa de corrección gamma para a gama vermella." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Táboa de corrección gamma para a gama verde." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Táboa de corrección gamma para a gama azul." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Controla o brillo da imaxe obtida." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Controla o contraste da imaxe obtida." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Escolle o «granulado» da imaxe obtida. Valores máis pequenos fornecen " "imaxes máis nitidas." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Define se a imaxe obtida debe ser convertida a medios tons (punteado)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" "Selecciona que nivel de radiancia debe ser tida en conta \"negro\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" "Selecciona que nivel de radiancia debe ser tida en conta \"branco\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Selecciona que nivel de radiancia vermella debe ser tida en conta " "\"branco\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Selecciona que nivel de radiancia verde debe ser tida en conta \"branco" "\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Selecciona que nivel de radiancia azul debe ser tida en conta \"branco\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Selecciona que nivel de radiancia vermella debe ser tida en conta \"negro" "\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Selecciona que nivel de radiancia verde debe ser tida en conta \"negro\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Selecciona que nivel de radiancia azul debe ser tida en conta \"negro\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Selecciona que nivel de radiancia vermella debe ser tida en conta " "\"vermello total\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Selecciona que nivel de radiancia verde debe ser tida en conta \"verde " "total\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Selecciona que nivel de radiancia azul debe ser tida en conta \"azul " "total\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Controla o \"matiz\" (nivel de azul) da imaxe obtida." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "O nivel de saturación controla a cantidade de «florecemento» (halo) que " "ocorre cando se obtén unha imaxe cunha cámara. Valores máis altos " "producen máis florecemento." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Nome do ficheiro da imaxe a cargar." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Axusta o tamaño do patrón de medios tons (punteado) usado cando se " "escanean as imaxes de medios tons." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Define o patrón de medios tons (punteado) para escanear as imaxes de " "medios tons." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Usar os mesmos valores para a resolución X e Y." #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Intercambiar branco e negro" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Facer unha calibración de calidade dos brancos" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Usar lente que duplica a resolución óptica" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "En modo RGB usar os mesmos valores para cada cor" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Seleccionar o brillo mínimo para obter un punto branco" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Corrección gamma analóxica" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Corrección gamma analóxica para vermello" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Corrección gamma analóxica para verde" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Corrección gamma analóxica para azul" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Quecer a lámpada antes de escanear" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Definir tempo de exposición para a calibración" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Definir tempo de exposición para a calibración vermella" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Definir tempo de exposición para a calibración verde" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Definir tempo de exposición para a calibración azul" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Definir tempo de exposición para o escaneo" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Definir tempo de exposición para o escaneo vermello" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Definir tempo de exposición para o escaneo verde" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Definir tempo de exposición para o escaneo azul" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Activar selección do tempo de exposición" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Definir densidade da lámpada para a calibración" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Definir densidade da lámpada para o escaneo" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Activar a selección da densidade da lámpada" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Apaga a lámpada ao saír do programa" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Botón de control de escaneo" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "Botón de correo-e" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Botón de fax" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Botón de copia" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "Botón de PDF" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Botón de cancelar" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Páxina cargada" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "A tapa está aberta" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Cor" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Liña de arte coloreada" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Medios tons coloreados" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Gris" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Medios tons" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Liña de arte" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "Éxito" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Operación non compatible" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "A operación vai ser cancelada" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "Dispositivo ocupado" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Argumento incorrecto" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "Acadouse o fin do ficheiro" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Alimentador de documentos atrancado" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "O alimentador de documentos está baleiro" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "A tapa do escáner está aberta" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Erro en dispositivo de E/S" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Non queda memoria" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "Denegouse o acceso ao recurso" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "A lámpada non está preparada, tenteo de novo" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "O escáner está bloqueado para transporte" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Predeterminados" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Axustar valores predeterminados para os controis de optimización." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Calibración" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Calibrar antes do seguinte escaneo" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Se se activa, o dispositivo hase calibrar antes do seguinte escaneo. " "Noutro caso, a calibración farase unicamente antes do primeiro escaneo." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Facer só correccións de sombras" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Se está activado, só se farán correccións de sombras durante a " "calibración. Usaranse os valores predeterminados de ganancia, " "desprazamento e tempo de exposición, xa sexan os que trae incorporados o " "programa ou os do ficheiro de configuración." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Botón de estado" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Número de mostra a escanear" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Escolle o número de mostra a escanear" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Escaneo dúplex" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "O escaneo dúplex fornece un escaneo do anverso e o reverso do documento" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Calibrar o escáner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Forza a calibrar o escáner antes de facer o escaneo" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Escaneo en escala de grises" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Escanea en escala de grises, non en cores" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Ganancia analóxica" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Aumenta o diminúe a ganancia analóxica da gama CCD" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Corrección gamma" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Selecciona a curva de transferencia da corrección gamma" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "En bruto" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Cor fina" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Sen corrección de transparencia" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Corrección conforme co tipo de filme" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Corrección conforme coa taxa de transparencia" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negativos" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Diapositivas" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automático" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Velocidade normal" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 da velocidade normal" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 da velocidade normal" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "parámetro redondeado" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "descoñecido" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "Atoamento no alimentador" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "A tapa do alimentador está aberta" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "fallo de lámpada" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "erro no posicionamento do cabezal de escaneo" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "erro de verificación de CPU" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "erro de verificación de RAM" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "erro de verificación de ROM" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "erro de verificación de hardware" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "fallo da lámpada da unidade de transparencias" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" "fallo de posición do cabezal de escaneo da unidade de transparencias" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "erro na lonxitude da lista de parámetros" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "código de orde de operación incorrecto" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "campo incorrecto en CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "LUN non é compatíbel" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "campo incorrecto na lista de parámetros" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "erro na secuencia de ordes" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "especifícanse demasiadas xanelas" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "non se atopa o soporte" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "mensaxe de bit de IDENTIFICACIÓN incorrecta" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "a opción non conecta" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "reiniciar o acendido / reiniciar o bus do dispositivo" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parámetro cambiado por outro iniciador" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "información sen senso adicional" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "Fallou a volta a escoller" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "erro de paridade SCSI" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "o iniciador detectou a recepción dunha mensaxe de erro" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "mensaxe de erro incorrecta" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "erro de límite de tempo" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "erro de sombreado na unidade de transparencias" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lámpada non estabilizada" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "escáner de filmes" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "escáner plano" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Tipo de filme" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Escoller o tipo de filme, p.e. negativo ou diapositiva" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Tipo de filme negativo" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Selecciona o tipo de negativo de filme" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Resolución do hardware" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Usar só resolucións do hardware" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Enfoque" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Enfoque automático" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Activar/desactivar enfoque automático" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Enfoque automático só unha vez" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Facer enfoque automático só unha vez entre expulsións" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Posición de foco manual" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" "Axustar o sistema óptico de foco na posición manual (predeterminado: " "128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Marxes de escaneo" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Axustes de cor extra" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Reflectir a imaxe horizontalmente" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Inverter a imaxe horizontalmente" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Exposición automática" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Activar/desactivar a característica de exposición automática" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Calibrar agora" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Executar a calibración *agora*" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Diagnose automatica" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Facer unha diagnose automatica do escáner" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Reiniciar o escáner" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Reiniciar o escáner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Manexar o soporte" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Expulsar o filme despois de cada escaneo" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" "Expulsar automaticamente o filme do dispositivo despois de cada escaneo" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Expulsar o filme antes de saír" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Expulsar automaticamente o filme do dispositivo antes de saír do programa" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Expulsar o filme agora" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Expulsar o filme *agora*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Alimentador de documentos extras" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Só plano" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" "Desactivar o alimentador automático de documentos e usar só o plano" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Unidade de transparencias" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" "Activar/desactivar a unidade de transparencias (FAU, unidade adaptadora " "de filme)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Filme en negativo" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Filme en positivo ou en negativo" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Control de densidade" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Axustar o modo de control de densidade" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Taxa de transparencia" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Escoller tipo de filme" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Escoller o tipo de filme" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Plano" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, fuzzy, no-c-format msgid "ADF Front" msgstr "A tapa do alimentador está aberta" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "Atoamento no alimentador" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "Alimentador dúplex" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Imprimir" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Duas caras" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Vermello" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Verde" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Azul" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Optimización" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Optimización" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Optimización" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Ningún" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Unha cara" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Duas caras" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Unidade de transparencias" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Alimentador automático de documentos (ADF)" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Filme en positivo" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Filme en negativo" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Enfoque no cristal" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Enfoque a 2.5mm sobre o cristal" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Medios tons A (tons duros)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Medios tons B (tons suaves)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Medios tons C (matizado)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Trama A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Trama B (4x4 espiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Trama C (4x4 matizado)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Trama D (8x4 matizado)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Tecnoloxia de optimización de texto" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Descargar patrón A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Descargar patrón B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Sen corrección" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Definida polo usuario" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Impresoras matriciais" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Impresoras térmicas" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Impresoras de inxección de tinta" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Monitores CRT" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Predeterminado" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Impresión de alta densidade" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Impresión de baixa densidade" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Impresión de alto contraste" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Definido polo usuario (gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Definido polo usuario (gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 vertical" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 apaisado" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Carta" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Máx" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Modo de escaneo" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Escolle o medios tons" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Exclusión" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Escoller o que se vai a excluir" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Escoller o brillo" #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Nitidez" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Corrección da cor" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "Axusta a táboa de corrección da cor para o dispositivo de saída " "seleccionado." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Coeficientes de corrección da cor" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matriz de multiplicación de RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Cambiar de verde a vermello" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Cambiar de verde a azul" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Cambiar de vermello a verde" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Cambiar de vermello a azul" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Cambiar de azul a verde" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Cambiar de azul a vermello" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Controla o nivel de verde" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Engade vermello baseándose no nivel de verde" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Engade azul baseándose no nivel de verde" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Engade verde baseándose no nivel de vermello" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Controla o nivel de vermello" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Engade azul baseándose no nivel de vermello" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Engade verde baseándose no nivel de azul" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Engade vermello baseándose no nivel de azul" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Controla o nivel de azul" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Reflectir a imaxe." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Vista previa rápida" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Segmentación automática da área" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Lista curta de resolucións" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Amosar lista curta de resolucións" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Zoom" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Define o factor de zoom que vai usar o escáner" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Formato rápido" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Equipamento opcional" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Expulsar" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Expulsar a folla do alimentador" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Expulsión automática" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Expulsar o documento despois do escaneo" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Modo alimentador" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Escoller o modo do alimentador (unha cara/duas caras)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Badía" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Escolla a badía para escanear" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Escolla o valor de corrección gamma dunha lista de dispositivos " "predefinidos ou dunha táboa definida polo usuario, que pode ser " "descargada ao escáner." #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Posición do foco" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Axusta a posición do foco, xa sexa ao cristal ou a 2.5mm por riba do " "cristal" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Agardar ao botón" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Despois de enviar a orde de escaneo, agardar até que se prema no botón " "do escáner para comezar verdadeiramente o proceso de escaneo." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Diapositiva en positivo" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Diapositiva en negativo" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Definida polo usuario" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Activado" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Desactivado" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Esfumado" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "Difusión de erro" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Nivel do branco" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Nivel do negro" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "Condicional" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontal" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Horizontal" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Horizontal" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertical" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Vertical" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Imprimir" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Medios tons" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Calibración de precisión" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Destaque da imaxe" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Saturación" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "" "Activar a determinación automática do limiar para escaneos como liña de " "arte." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Reflectir a imaxe horizontalmente" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Reflectir a imaxe en horizontal" #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Nivel do branco para azul" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Controla o nivel de vermello" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Filtro de cor" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Suavizado" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Valor gamma" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Limiar" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Limiar" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Redución de ruído" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Sen corrección" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Sen corrección" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "A tapa do alimentador está aberta" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Opcions avanzadas" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Sen corrección" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Exclusión" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Modo de alimentación" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Tempo para apagado da lámpada" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Desviación azul" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Desviación verde" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Desviación verde" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Desviación azul" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Axusta o desprazamento da canle azul" #: backend/fujitsu.c:3980 #, fuzzy, no-c-format msgid "Low Memory" msgstr "Non queda memoria" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Escaneo dúplex" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Opcions avanzadas" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Redución de ruído" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "De papel" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "De papel" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "De papel" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "De papel" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "A tapa do escáner está aberta" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Foco previo manual" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Foco previo manual" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "erro de verificación de hardware" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Nivel do branco" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Control de densidade" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Control de densidade" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Escaneo dúplex" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extras" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Desactivar interpolación" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "Cando se usan altas resolucións nas que a resolución horizontal é máis " "pequena que a vertical, isto desactiva a interpolación horizontal." #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Filtro de cor" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "Cando se usa gris ou liña de arte esta opción selecciona a cor a usar." #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Calibración" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Definir o modo de calibración" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Caché de datos de calibración" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Tempo para apagado da lámpada" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "A lámpada vai ser apagada despois do tempo indicado (en minutos). Un " "valor de 0 significa que a lámpada no vai ser apagada." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Apagar a lámpada durante a calibración de escuridade" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "Minutos que tardará a lámpada en apagarse despois do escaneo" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Botón de ficheiro" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "Botón de OCR" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Botón de enerxía" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Botón de correo-e" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Limpar a calibración" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Forza a calibrar o escáner antes de facer o escaneo" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Botóns" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Calibrar" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Iniciar a calibración usando unha folla especial" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Limpar a calibración" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Limpar a caché de datos de calibración" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Adaptador de transparencias" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Cor en modo gris" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Escolle que cor de escaneo vai ser usada en modo gris (predefinido: " "verde)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Opcións de depuración" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Quecemento automático" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Quecer até que o brillo da lámpada sexa constante no canto de agardar " "polos 60 segundos de quecemento." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Escaneo completo" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Escanear toda a área de escaneo incluindo a franxa de calibración. Teña " "cuidado. Non seleccione a altura total. Só para probas." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Calibración grosa" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Configuración da ganancia e desprazamento para escanear automaticamente. " "Se esta opción está desactivada, proporciónanse as opcións de axuste dos " "parámetros de xeito manual na interface analóxica. Esta opción está " "activada como predefinida. Só para probas." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Calibración grosa só para o primeiro escaneo" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "A calibración grosa faise só para o primeiro escaneo. Funciona coa " "maioría de escáners e pode aforrar tempo de escaneo. Se o brillo da " "imaxe é diferente con cada escaneo, desactive esta opción. Só para " "probas." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Liñas de retroceso" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Número de liñas que o escáner retrocede cando escanea máis rápido do que " "o equipo pode recibir datos. Valores baixos fan que os escaneos sexan " "más rápidos, pero aumentan os riscos de omitir liñas.Número de liñas que " "o escáner retrocede cando escanea máis rápido do que o equipo pode " "recibir datos. Valores baixos fan que os escaneos sexan más rápidos, " "pero aumentan os riscos de omitir liñas." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Valor gamma" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Axusta o valor gamma para todas as canles." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Grupo de xeometría" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Grupo de modo de escaneo" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Diapositiva" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Modelo de escáner" #: backend/hp3900_sane.c:1408 #, fuzzy, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" "Permite comprobar o comportamento do dispositivo con outros modelos " "compatíbeisPermite comprobar o comportamento do dispositivo con outros " "modelos compatíbeis" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "As imaxes a cor hanse inverter" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Desactivar a corrección gamma" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "A corrección gamma hase desactivar" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Desactivar a corrección de sombra branca" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "A corrección de sombra branca hase desactivar" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Omitir proceso de quecemento" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "O proceso de quecemento hase desactivar" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Forzar a profundidade real" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "Se gamma está activada, sempre se analisa en profundidade de 16 bits " "para mellorar a calidade da imaxe e despois convertila á profundidade " "seleccionada. Esta opción evita a emulación da profundidade." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Emular escala de grises" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "Se está activada, a imaxe vai ser escaneada en modo de cor e despois " "convertida a escala de grises por software. Isto pode mellorar a " "calidade da imaxe nalgunhas circunstancias." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Gardar as imaxes de depuración" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "Se se activa, algunhas imaxes implicadas no proceso de escaneo " "gardaranse para analizalas." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Reiniciar o chipset" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Reiniciar os datos do chipset" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Información" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Nome do chipset" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Amosa o nome do chipset usado no dispositivo." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Descoñecido" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "ID do chipset" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Amosa o ID do chipset" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Contador de escaneos" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Amosa o número de escaneos feitas polo escáner" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Actualizar a información" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Actualiza a información acerca do dispositivo" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Esta opción reflicte un botón do panel frontal do escáner" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Imaxe" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Miscelánea" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "posición X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Posición X interna no hardware da zona de escaneo." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "posición Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Posición Y interna no hardware da zona de escaneo." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Estado da lámpada" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Acende ou apaga a lámpada" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Calibrar o nivel de branco e negro." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "Alimentador automático de documentos (ADF)" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "Adaptador (TMA) para diapositivas" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "Adaptador (TMA) para negativos" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Cor (48 bits)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Retardar o tempo de apagado da lámpada" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Retarda os tempos de apagado da lámpada (de 15 minutos a 1 hora)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Agardando polo botón" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Agardando polo botón antes de escanear" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Opcions avanzadas" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Groso" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fina" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Personalizado" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automático" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "Adaptador de transparencias RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "A través" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Gris" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "Adaptador de transparencias gris" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Lento" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Rápido" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Moi rápido" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-píxeles" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-píxeles" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-píxeles" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Imprimir" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Tira de filme" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "Adaptador de transparencias (XPA)" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Condicional" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Experimento" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Nitidez" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Axustar o valor de nitidez." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Limiar automático" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Activar a determinación automática do limiar para escaneos como liña de " "arte." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Escoller filtro de suavizado." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Descargar os soportes despois de escanear." #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Descargar as unidades despois de escanear." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Cambiar o documento" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Cambiar o documento." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Descargar" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Descargar o documento" #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Iniciar proceso de calibración" #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Soporte" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Axustar tipo de soporte." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Tempo de exposición" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Unha exposición prolongada permítelle ao escáner recoller máis luz. " "Suxírese usar 175% para impresións, 150% para diapositivas normais e " "«Negativo» para filme en negativo. Para imaxes escuras (subexpostas) " "pode incrementar este valor." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Matriz de cor" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Axustar a matriz de cor do escáner." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Matriz de cor personalizada." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Matriz monocroma" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Matriz de cor personalizada para escáneres en escala de grises." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Espello horizontal" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Reflectir a imaxe en horizontal" #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Espello vertical" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Reflectir a imaxe en verticalv" #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Actualizar as opcións" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Actualizar as opcións." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "Saída de 8 bits" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Usar profundidade de bits maior de oito internamente, mais na saída usar " "só oito bits." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Agardar botón frontal" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Agardar a que se prema no botón frontal para escanear." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Apagar lámpada" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Apagar a lámpada do escáner." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Tamaño do papel" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Separación automática" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 apaisado" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "Axustar o modo de control de densidade" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Foco previo manual" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Foco previo manual" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Activa o escaneo polas dúas caras" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Tamaño físico do papel no alimentador" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Medios tons" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Cor" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Condicional" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Desactivado" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Medios tons" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Medios tons" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Difusión de erro" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Resaltar" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "escáner de filmes" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "De papel" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Predeterminado" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Suave" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Lento" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Soporte" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Vermello" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Verde" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Orixe de escaneo" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Modo de alimentación" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Axusta o modo de alimentación" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Activar/desactivar enfoque automático" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Axustar o modo de control de densidade" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Axusta o modo de alimentación" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Axusta o modo de alimentación" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Limiar automático" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Axusta automaticamente o brillo, contraste, niveis de branco, gamma e " "redución da intensidade do ruído da imaxe" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Redución de ruído" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Reduce os puntos illados de ruído" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Destaque da imaxe" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Axusta o destaque da imaxe" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Acender lámpada" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Acende ou apaga a lámpada" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Reflectir a imaxe en verticalv" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Corrección gamma" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Impresión de alta densidade" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Impresión de baixa densidade" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Difusión de erro" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Sen corrección" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normal" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Optimización" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Limiar automático" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Limiar automático" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Axustar a orde das mostras" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Sombra para azul" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Cambiar de vermello a azul" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamante" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 «Engraxado» groso" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 «Engraxado» fino" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Liña vertical" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Ganancia" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Axustes de ganancia das canles de cor" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Ganancia de gris" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Axusta a ganancia da canle de gris" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Ganancia vermella" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Axustar a ganancia da canle vermella" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Ganancia verde" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Axusta a ganancia da canle verde" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Ganancia azul" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Axusta a ganancia da canle azul" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Trama Bayer 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Trama Bayer 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Medio ton punto 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Medio ton punto 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Difusión de erro" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Modo 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Modo 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Modo 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "De pau branco" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Suave" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Baixo" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Soporte" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Alta" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Unha páxina" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Todas as páxinas" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "escáner con cargador automático" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Escala de grises de 4 bits" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Escala de grises de 8 bits" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Sombras, medias tintas, destaque, tempo de exposición" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Opciós especiais" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Balance de cor" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Desactivar o retroceso" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Se se activa, o escáner non retrocede cando perde unha liña" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Alternar o estado da lámpada do plano" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Alterna o estado da lámpada do plano" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Calibración polo motor" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Se se selecciona a calibración da cor antes do escaneo faina o motor" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Usar o adaptador de diapositivas de 35mm" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Esta opción apaga a lámpada do plano durante o escaneo" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Escaneo de calidade" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "A mellor calidade, pero a velocidade lenta" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Escaneo rápido" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Máis rápido, pero de pior calidade" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Axuste automático de limiar" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Se se selecciona, o motor tenta determinar automaticamente un valor " "óptimo para o limiar." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Selecciona o modo de corrección gamma" #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Conectar gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Usar os mesmos valores gamma para todas as canles de cores." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Gamma escalar" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Escolle un valor para a corrección gamma escalar." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Gamma escalar vermella" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Escolle un valor para a corrección gamma escalar (canle vermella)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Gamma escalar verde" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Escolle un valor para a corrección gamma escalar (canle verde)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Gamma escalar azul" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Escolle un valor para a corrección gamma escalar (canle azul)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Canle" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Escolle a gama de cor, «Master» significa que afecta a todas as cores." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Medios tons" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Selecciona o nivel de radiancia a ter en conta \"50% gris\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Medios tons para vermello" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Selecciona o nivel de radiancia a ter en conta \"50% vermello\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Medios tons para verde" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Selecciona o nivel de radiancia a ter en conta \"50% verde\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Medios tons para azul" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" "Selecciona o nivel de radiancia a ter en conta \"50% azul\".Selecciona o " "nivel de radiancia a ter en conta \"50% azul\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Balance de vermello" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" "Factor de balance para vermello. Un valor de 100% significa sen " "corrección." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Balance de verde" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" "Factor de balance para verde. Un valor de 100% significa sen corrección." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Balance de azul" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" "Factor de balance para azul. Un valor de 100% significa sen corrección." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Balance de firmware" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Axusta o balance de cor aos valores fornecidos polo firmware." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "O máis lento" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Máis lento" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Máis rápido" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "O máis rápido" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 groso" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fino" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 moi fino" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normal" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 groso" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fino" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 groso" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normal" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fino" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 personalizado" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 personalizado" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 personalizado" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 personalizado" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 personalizado" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 personalizado" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Modo gris rápido" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Escanear en modo gris rápido (menor calidade)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Precisa que todas as vistas previas se fagan do modo máis rápido (baixa " "calidade). Este pode ser un modo sen cor ou un modo de baixa resolución." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Tempo de apagado de lámpada (minutos)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Axusta o tempo (en minutos) tras o que se apagará a lámpada." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Apagar a lámpada" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Apaga a lámpada inmediatamente." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Brillo de vermello" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Controla o brillo da canle de vermello da imaxe obtida." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Brillo de verde" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Controla o brillo da canle de verde da imaxe obtida." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Brillo de azul" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Controla o brillo da canle de azul da imaxe obtida." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contraste da canle vermella" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Controla o contraste da canle vermella da imaxe obtida." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contraste da canle verde" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Controla o contraste da canle verde da imaxe obtida." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contraste da canle azul" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Controla o contraste da canle azul da imaxe obtida." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Color48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Color24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Gris 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Gris 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Reflectantes" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positivo" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Quecer até que o brillo da lámpada sexa constante no canto de agardar " "polos 40 segundos de quecemento." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Filme en negativo" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negativo" #: backend/pixma.c:396 #, fuzzy, no-c-format msgid "48 bits color" msgstr "Cor fina" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Botón de control de escaneo" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Activado, o proceso de escaneo non comezará inmediatamente. Para " "proceder, faga clic no botón «SCAN» (para MP150) ou «COLOR» (para outros " "modelos). Para cancelar, prema no botón «GRAY»." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Actualizar estado do botón" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Botón 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Botón 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Transparencia" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Axustes do dispositivo" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Interruptor de lámpada" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Cambiar a(s) lámpada(s) manualmente." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Apagar a lámpada durante a calibración de escuridade" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Apagar sempre a lámpada cando se calibra a escuridade." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Caché de datos de calibración" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Activa ou desactiva a caché de datos de calibración" #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Calibración de precisión" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Acelerar o sensor" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Activa ou desactiva a aceleración de movimento do sensor." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Tempo de quecemento" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Tempo de quecemento en segundos" #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Tempo de apagado da lámpada" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Tempo de apagado da lámpada en segundos" #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Interface analóxica (AFE)" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Valor de ganancia vermella no AFE" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Desviación vermella" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Valor da desviación vermella no AFE" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Valor de ganancia verde no AFE" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Valor da desviación verde no AFE" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Valor de ganancia azul no AFE" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Valor da desviación azul no AFE" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Apagar alámpada vermella" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Define os parámetros de apagado da lámpada vermella" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Apagar lámpada verde" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Define os parámetros de apagado da lámpada verde" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Apagar lámpada azul" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Define os parámetros de apagado da lámpada azul" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Esta opción reflicte o estado dos botóns do escáner" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Color36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Mapa de trama 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Mapa de trama 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Aleatorio" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Escoller a orixe" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Optimización da imaxe" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Agrisar" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Cargar a imaxe como escala de grises." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Simulación de tres pasadas" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Semella un escáner de tres pasadas devolvendo 3 mostras separadas. Por " "diversión, devolve verde, despois azul y finalmente vermello." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Simulación de escáner de man" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Semella un escáner de man. Os escáneres de man adoitan descoñecer a " "priori a distancia á imaxe. Na súa vez utiliza unha altura de retorno " "-1. Axustar esta opción permítelle comprobar se unha interface pode " "manexar isto correctamente." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Axustar os valores predeterminados para os controis de optimización " "(brillo e contraste)" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Opción de proba de só lectura" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Vexamos se a interface pode tratar isto correctamente" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Táboas gamma" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Simulación do código de estado" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Non forzar o código de estado" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Non forzar o motor a devolver un código de estado." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Devolve SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Forzar o motor a devolver o código de estado de SANE_STATUS_EOF despois " "de ter sido chamado sane_read()." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Devolve SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Forzar o motor a devolver o código de estado de SANE_STATUS_JAMMED " "despois de ter sido chamado sane_read()." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Devolve SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Forzar o motor a devolver o código de estado de SANE_STATUS_NO_DOCS " "despois de ter sido chamado sane_read()." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Devolve SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Forzar o motor a devolver o código de estado de SANE_STATUS_COVER_OPEN " "despois de ter sido chamado sane_read()." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Devolve SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Forzar o motor a devolver o código de estado de SANE_STATUS_IO_ERROR " "despois de ter sido chamado sane_read()." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Devolve SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Forzar o motor a devolver o código de estado de SANE_STATUS_NO_MEM " "despois de ter sido chamado sane_read()." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Devolve SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Forzar o motor a devolver o código de estado de " "SANE_STATUS_ACCESS_DENIED despois de ter sido chamado sane_read()." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Esta opción reflicte o estado dos botóns do escáner" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Acender lámpada" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Acende a lámpada do escáner" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Apagar lámpada" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Apaga a lámpada do escáner" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Límite de tempo da lámpada" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Minutos que tardará a lámpada en apagarse despois do escaneo" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Valor do limiar para o modo de liña de arte" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Alimentador de documentos" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (polg.)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (polg.)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (polg.)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Medios tons non compatíbeis" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "Punto disperso 8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "Punto disperso 16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Número de liñas de escaneo por solicitude dunha lectura SCSI. O cambio " "deste parámetro permítelle axustar a velocidade á que se len os datos " "desde o escáner durante os escaneos. Se este é demasiado baixo, o " "escáner ten que parar periodicamente no medio dun escaneo, se é " "demasiado alto, baseado en interfaces X pode deixar de responder a " "eventos de X e o seu sistema poderíase atoar." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Expulsar o documento despois do escaneo" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Modo de previsualización" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Escolle o modo para previsualización. A previsualización en escala de " "grises fornece en xeral, a mellor relación entre velocidade e detalle." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Axustes predefinidos" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Fornece superficies de escaneado estándar para fotografías, páxinas " "impresas, etc." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "escáner plano" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Enfoque" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Enfoque automático" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Posición do foco" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Posición do foco" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Cor, liñas por lectura" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Escala de grises, liñas por lectura" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "cámara web" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Cor de texto RGB" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Cor RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Cor RGB TEXTO" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Negro sólido" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Branco sólido" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Patrón de cor" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Grade" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Primeira entrada" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Segunda entrada" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Esta terceira entrada é moi longa. Quizais a interface ten unha idea de " "como amosalo" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Simulación de escáner manual" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Semella un escáner de man. Os escáneres de man adoitan descoñecer a " "priori a distancia á imaxe. Na súa vez utiliza unha altura de retorno " "-1. Axustar esta opción permítelle comprobar se unha interface pode " "manexar isto correctamente. Esta opción tamén permite un ancho de 11cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Simulación de tres pasadas" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Semella un escáner de tres pasadas devolvendo 3 mostras separadas. Por " "diversión, devolve verde, despois azul e para rematar vermello." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Axustar a orde das mostras" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Axustar a orde das mostras no modo de tres pasadas de cor." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Se escolle o alimentador automático de documentos, o alimentador estará " "\"baleiro\" despois de 10 escaneos." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Opcións especiais" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Escolla a imaxe de proba" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Define o tipo de proba de imaxe. Posíbeis opcións:\n" "Negro sólido: enche todo o escaneo con negro.\n" "Branco sólido: enche todo o escaneo con branco.\n" "Patrón de cor: debuxa varios patróns de proba dependendo do modo.\n" "Grade: debuxa unha grade en branco e negro cun tamaño de 10mm por " "cadrado." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Inverter a orde dos datos" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Intercambia os bytes de datos superiores e inferiores de imaxes en modo " "de 16 bits. Esta opción pode utilizarse para a proba de 16 bits dos " "modos de interface, p.ex. se a interface utiliza a orde correcta." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Límite de lectura" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Limita a cantidade de datos transferidos con cada chamada a sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Tamaño do límite de lectura" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "Cantidade de datos (máxima) transferida con cada chamada a sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Retardo de lectura" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Retardar a transferencia de datos á canalización." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Duración do retardo de lectura" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "Canto tempo se vai agardar despois de transferir cada búfer de datos a " "través da canalización." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Valor de retorno de sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Escolla o valor de retorno de sane_read(). «Predeterminado» é o normal " "para facer o escaneo. Todos os demáis códigos de estado son para probar " "a forma en que a interface se fai cargo deles" #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Perda de píxeles por liña" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Número de píxeles que se perden no extremo de cada liña." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Parámetros dubidosos" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Devolve liñas dubidosas e bytes por liña cando se chama a sane_start() " "antes que a sane_parameters()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Usar E/S non bloqueante" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Usar unha E/S non bloqueante para sane_red() se o permite a interface." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Propor a selección dun descritor de ficheiro" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Propor un descritor de fichero para detectar si sane_read () devolverá " "os datos." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Activar opcións de proba" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Activa varias opcións de proba. Isto úsase para probar a capacidade das " "interfaces para ver e modificar os diferentes tipos de opcións de SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Imprimir as opcións" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Imprimir unha lista de todas ls opcións" #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Opcións de proba booleanas" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Booleana configurábel e lexíbel por software" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Opción de proba booleana configurábel e lexíbel por software. Esta " "é a opción booleana normal." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Booleana configurábel por hardware lexíbel por software" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Opción de proba booleana configurábel por hardware e lexíbel polo " "software. Esta opción non pode ser configurada pola interface, mais si " "polo usuario (p.ex. premendo un botón no dispositivo)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Booleana configurábel por hardware" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Opción de proba booleana configurábel por hardware. Esta opción " "non pode ser configurada pola interface, mais si polo usuario (p.ex. " "premendo un botón no dispositivo) tampouco pode ser lida pola interface." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Booleana lexíbel por software" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Opción de proba booleana lexíbel por software. Esta é unha opción " "de só lectura." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Booleana configurábel e lexíbel por software, emulada" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Opción de proba booleana configurábel e lexíbel por software e " "emulada." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Booleana configurábel e lexíbel por software, automática" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Opción de proba booleana configurábel e lexíbel por software e " "emulada. Esta opción pode ser configurada automaticamente polo motor." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Opción de proba «Enteiro»" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Enteiro" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" "(1/6) Opción de proba de valor enteiro sen unidade nin conxunto de " "restricións." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Enteiro con rango de restricións" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Opción de proba de valor enteiro con unidade de píxel e con " "conxunto de restricións. O mínimo é 4, o máximo 192 e o salto 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Enteiro con restrición de lista de valores" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Opción de proba de valor enteiro con unidade bits e restrición de " "lista de valores" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Matriz de enteiros" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Opción de proba de valor enteiro con unidade mm usando unha Matriz " "con restricións." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Matriz de enteiros con rango de restriciónsv" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Opción de proba de valor enteiro con unidade dpi e usando unha " "matriz con intervalo de restricións. O mínimo é 4, o máximo 192, e o " "salto 2.v" #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Matriz de enteiros con restrición de lista de valores" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Opción de proba de valor enteiro con unidade e% e usando unha " "matriz con restricións nunha lista de valores." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Opcións de proba «reais fixos»" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Real fixo" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" "(1/3) Opción de proba de valor real (coma fixa) sen unidade nin conxunto " "de restricións." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Real fixo con intervalo de restrición" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Opción de proba de valor real (coma fixa) con unidade de " "microsegundo e intervalo de restrición. O mínimo é -42,17, o máximo " "32767,9999 e o salto 2,0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Real fixo con restrición de lista de valores" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Opción de proba de valor real (coma fixa) sen unidade e " "restrinxida por un conxunto de valores dunha lista." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Opcións de proba de cadea" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) Cadea" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Opcións de proba de cadea sen restricións." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) Cadea restrinxida a lista de cadeas" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) Opción de proba de cadea con restrición de lista de cadeas" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) Restrición de cadeas lista longa de cadeas" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) Opción de proba de cadea con restrición de lista de cadeas. Conten " "máis entradas..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Opcións de botón de proba" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Botón" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Botón de opción de proba. Imprime algún texto..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Color 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Usar composición de imaxe" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Dous niveis branco e negro (modo de liña de arte)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Esfumado/medios tons de branco e negro (modo de medios tons)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Multinivel de branco e negro (modo de escala de grises)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Multinivel de cor RGB (cor dunha pasada)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignorar calibración" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Desactivar foco previo" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Non calibrar o foco" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Foco previo manual" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Fixar a posición do foco" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Calibración de lentes na posición do documento" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Calibrar as lentes na posición do documento" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Marcar a posición do foco a 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Usar a marca de posición de foco a 0mm no canto de a 0,6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Modo de calibración" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Definir o modo de calibración" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Acende/apaga a lámpada" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA Activado" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Axusta o acendido/apagado UTA" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Desprazamento" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Axustes do desprazamento das canles de cor" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Desprazamento de gris" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Axusta o desprazamento da canle gris" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Axusta o desprazamento da canle vermello" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Axusta o desprazamento da canle verde" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Axusta o desprazamento da canle azul" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Modo de previsualización" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "problema sen analizar (clase de SCSI descoñecida)" #~ msgid "Grayscale" #~ msgstr "Escala de grises" #~ msgid "Binary" #~ msgstr "Binaria" #~ msgid "Display a shortened resolution list" #~ msgstr "Amosar unha lista de resolucións ordenada" #~ msgid "Black & White" #~ msgstr "Branco e negro" sane-backends-1.0.27/po/hu.gmo0000664000175000017500000002263613110600540012757 00000000000000Þ•¼üûÜ ÈÉÎÓÛà èó û   %15 > HT Yc } ‡“ ˜¥µÄ%Óù% .9A E R\n ‰ •£ «¸&Ëò ø(>U j vˆ¡³»Ä ÌÙ í ù   ' / :F O Ye mz’¡ ºÄÊÛ ìø    &4EUZr†‹« Ë Õàä êö% 7D_xŠ š¨¯¶½Æ Ï Ýëû ": R ` k w ƒ Ž™ ¢° ¸Å ËÙ íúþ  + 0 ; E Q[ k vƒ‹’—ž¦·Ç×àû & 0!; ]!h Š—Ÿ ¨ ´ÁÅ ÍÚßïh÷`ejrw Š ’  ¬ ¯ ¹ÃÇ ÏÜ ðü% 4@ ERa r/ ¯/¼ ìöý  -1 _ lx Ž.¡Ð Øå õ  &C bn}„šž¾Ï à ê#õ !-3DV\e n y ƒŽ Ÿª ºÛî- > L Vdlˆ Žœ¬¾Äàô,ú%' M W c m r  –  ¥ ® ² » Ó å !!(!;!T![!b!i!p!y! ‚!! ¡!­!³!»!Ä!Ç! Ê!Ô!ï!"" %"2"B"Q"`" i" w"‚" “"ž"¹"Î"å"ë"ó"##)# .#<# U#c#z#’#©# ½#Ç#Ð#×#Þ#æ#û#$ /$";$ ^$"i$ Œ$™$ ¢$/¯$ ß$/ì$ % (% 3% @% L%Y%]% e% r%}% “%Zz`‰A†‡kD›7B<g¢·«ny8|TM/š¦2Nl•‘мeu~9¯(£ª“Y>$&± °+j[ It—-U S"»1F¸;G\© .”O:}C –‚®¥V­'QœWŸŽºxµ²R„pm*{^§Hd€4sJ™?ž¨³,c…´qK¡#o%ƒh3‹a_)¤0ˆ r¬vw!6ifPb¹E= ¶X’˜5@Œ]L10mm15mm2-pixel20mm4-pixel6x4 (inch)8-pixel8.5x11 (inch)8x10 (inch)A4A5 landscapeA5 portraitADFAdvancedAll pagesAnalog GainAutoAutomaticAutomatic Document FeederBit depthBlack levelBlueBlue balanceBlue brightnessBlue intensityBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButtonsCRTCRT monitorsCalibrateCalibrate ScannerCalibrate before next scanCalibrationCancel buttonChannelChipset nameCoarse calibrationCoarse calibration for first scan onlyColorColor MatrixColor correctionContinueContrastContrast blue channelContrast green channelContrast red channelCopy buttonCover openCustomCustom color matrix.DTCDebugging OptionsDefaultDefaultsDiamondEmail buttonEnable test optionsEnhancementExtra FastFastFast previewFast scanFasterFastestFax buttonFile buttonFilenameFilm typeFirst entryFlatbedFlatbed onlyFocus 2.5mm above glassFocus on glassForce monochrome previewFull scanGammaGamma CorrectionGamma correctionGamma valueGeometryGrain sizeGrayGrayscale scanGreenGreen balanceGreen brightnessGreen intensityGridHand-scanner simulationHardware resolutionHighHighest quality but lower speedHighest speed but lower qualityHighlightHorizontalHueImageInformationInk-jet printersLetterLineartLowMaxMediumMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3NTSC RGBNegativeNegative FilmNo CorrectionNoise reductionNoneNormalOCR buttonOffOnOne pageOperation not supportedOperation was cancelledOut of memoryPDF buttonPage heightPage loadedPage widthPaper sizePositivePositive FilmPreviewPreview modePrintPrint optionsQuality calibrationQuality scanRawRedRed balanceRed brightnessRed intensitySDTCSaturationScan ModeScan buttonScan modeScan resolutionScan speedSecond entrySensorsShadowSlowSlowerSlowestSource SelectionSpecial OptionsSpecial optionsStandardStart calibration process.StopSwap black and whiteThermal printersThresholdTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyUnknownVerticalWhite levelX-resolutionXPAXPA RGBY-resolutionZoomflatbed scannerunknownProject-Id-Version: sane-backends Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2011-04-06 19:50+0200 Last-Translator: Németh Tamás Language-Team: Hungarian Language: hu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 10mm15mm2-pixel20mm4-pixel6x4 (inch)8-pixel8.5x11 (inch)8x10 (inch)A4A5 fekvÅ‘A% állóADFHaladóMinden oldalAnalóg erÅ‘sítésAutomatikusAutomataAutomatikus dokumentum adagolóSzínmélységFeketeszintKékKék balanszKék fényerÅ‘Kék intenzitásJobb-alsó xA beolvasási terület jobb-alsó x pozíciójaJobb-alsó yA beolvasási terület jobb-alsó y pozíciójaFényerÅ‘GombokCRTCRT monitorKalibrálásSzkenner kalibrálásaKalibrálás a következÅ‘ szkennelés elÅ‘ttKalibrációMégse gombCsatornaChipset névFinom beállításFinom beállítás csak az elsÅ‘ szkeneléskorSzínesSzínmátrixSzínkorrekcióFolytatásKontrasztA kék csatorna kontrasztjaA zöld csatorna kontrasztjaA vörös csatorna kontrasztjaMásol gombFedél nyitásEgyediEgyéni színmátrix.DTC Nyomkövetési beállítások AlapértelmezettAlapértelmezettGyémántEmail gombTesztbeállítások engedélyezéseHaladóExtra gyorsGyorsGyors elÅ‘nézetGyors szkennelésGyorsGyorsabbFax gombFájl gombFájlnévFilmtípusElsÅ‘ bejegyzésSíkágyasCsak síkágyasFókusz 2,5mm-el az üveg felettFókusz az üvegenMonokróm elÅ‘nézetTeljes szkennelésGammaGamma korrekcióGamma korrekcióGamma értékGeometriaSzemcseméretSzürkeSzürkeskálás szkennelésZöldZöld balanszZöld fényerÅ‘Zöld intenzitásRácsKézi szkenner szimulációEszköz felbontásaMagasMinÅ‘ségi szkennelés alacsony sebességgelGyors sebesség alacsony minÅ‘séggelKiemelésVízszintesÃrnyalatKépInformációTintasugaras nyomtatóLetterVonalasAlacsonyMaxKözepesVízszintes tükrözésKép tükrözéseA kép vízszintes tükrözése.A kép függÅ‘leges tükrözése.Kép tükrözése.FüggÅ‘leges tükrözésEgyébMode 1Mode 2Mode 3NTSC RGBNegatívNegatív filmNincs korrekcióZajszűrésNincsNormálOCR gombKiBeEgy oldalA művelet nem támogatottA művelet megszakítvaNincs elég memóriaPDF gombLapmagasságOldal betöltveLapszélességPapír méretePozitívPozitív filmElÅ‘nézetElÅ‘nézeti módNyomtatásNyomtatási beállításokPrecíz beállításMinÅ‘ségi szkennelésNyersVörösVörös balanszVörös fényerÅ‘Vörös intenzitásSDTCTelítettség Szkennelési üzemmód Szkennel gombSzkennelési üzemmódSzkennelés felbontásaSzkennelési sebességMásodik bejegyzésSzenzorokÃrnyékLassúLassúLassabbForrás kijelöléseSpeciális beállításokSpeciális beállításokÃltalánosKalibrálási folyamat indítása.MegállítA fekete és fehér felcseréléseHÅ‘nyomtatóKüszöbBal-felsÅ‘ xA beolvasási terület bal-felsÅ‘ x pozíciójaBal-felsÅ‘ yA beolvasási terület bal-felsÅ‘ y pozíciójaÃtlátszóIsmeretlenFüggÅ‘legesFehérszintX felbontásXPAXPA RGBY felbontásNagyítássíkágyas lapolvasóismeretlensane-backends-1.0.27/po/sv.po0000664000175000017500000047067513110600537012647 00000000000000# Swedish translation for SANE backend options. # Copyright (C) 2002, 2003 SANE Project. # Dennis Björklund , 2002. # Mattias Ellert , 2003, 2004, 2005, 2006, 2007. # # Engelskans "Halftone" motsvaras av "Raster" pÃ¥ svenska och # svenskans "Halvton" heter "Continuous tone" pÃ¥ engelska. Dessa # skall inte blandas ihop. # msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.18\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2012-10-22 11:17+0200\n" "Last-Translator: Mattias Ellert \n" "Language-Team: Swedish \n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Antal inställningsvärden" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Standard" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometri" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Förbättring" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Avancerat" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Sensorer" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Förhandsgranskning" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Använd monokrom förhandsgranskning" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bitdjup" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Bildläsarläge" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Inläsningshastighet" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Bildläsarkälla" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Använd bakspÃ¥rning" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Vänster" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Övre" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Höger" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Nedre" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Upplösning" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-upplösning" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-upplösning" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Sidans bredd" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Sidans höjd" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Använd användardefinierad gammatabell" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Bildintensitet" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Röd intensitet" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Grön intensitet" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "BlÃ¥ intensitet" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Ljusstyrka" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Kornstorlek" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Rastrering" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "SvartnivÃ¥" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "VitnivÃ¥" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "VitninÃ¥ för rött" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "VitnivÃ¥ för grönt" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "VitnivÃ¥ för blÃ¥tt" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Skugga" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Skugga för rött" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Skugga för grönt" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Skugga för blÃ¥tt" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Belysning" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Belysning för rött" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Belysning för grönt" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Belysning för blÃ¥tt" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Nyans" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Mättnad" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Filnamn" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Rastermönstersstorlek" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Rastermönster" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Koppla X- och Y-upplösning" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativ" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Kvalitetskalibrering" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Dubbel optisk upplösning" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Koppla RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Tröskelvärde" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analog gammakorrigering" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analogt gamma rött" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analogt gamma grönt" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analogt gamma blÃ¥tt" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Koppla analogt gamma" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Värm upp lampa" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Kalibreringsexponeringstid" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Kalibreringsexponeringstid för rött" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Kalibreringsexponeringstid för grönt" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Kalibreringsexponeringstid för blÃ¥tt" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Inläsningsexponeringstid" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Inläsningsexponeringstid för rött" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Inläsningsexponeringstid för grönt" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Inläsningsexponeringstid för blÃ¥tt" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Ställ in exponeringstid" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Kalibreringslampdensitet" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Inläsningslampdensitet" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Ställ in lampdensitet" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lampa av vid avslut" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Skrivskyddat värde som anger hur mÃ¥nga parametrar en specifik enhet " "stödjer." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Bildkälla, bildläsarläge och upplösningsinsällningar" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "InläsningsomrÃ¥des- och orginalstorleksinställningar" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Bildförändringsinställningar" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "HÃ¥rdvaruspecifika inställningar" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Bildläsarsensorer och -knappar" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Begär en inläsning i förhandsgranskningskvalitet." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Begär att alla förhandsgranskningar görs i monokromt läge. PÃ¥ en " "trepassläsare sÃ¥ begränsar det antalet pass till ett och pÃ¥ en " "enpassläsare sÃ¥ reduceras bÃ¥de minnesÃ¥tgÃ¥ng och inläsningstid för en " "förhandsgranskning." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Antal bitar per sampel, typiska värden är 1 för \"streckteckningar\" och " "8 för flerbitinläsningar." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Väljer inläsningsläge (t.ex. streckteckning, monokrom eller färg)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Bestämmer hastigheten med vilken inläsningen sker." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Väljer inläsningskälla (som t.ex. en dokumentmatare)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Bestämmer ifall bakspÃ¥rning används." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Vänster kant av inläsningsytan." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Övre kant av inläsningsytan." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Höger kant av inläsningsytan." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Nedre kant av inläsningsytan." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Ställer in upplösningen pÃ¥ den inlästa bilden." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Ställer in den horisontella upplösningen pÃ¥ den inlästa bilden." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Ställer in den vertikala upplösningen pÃ¥ den inlästa bilden." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Anger bredden pÃ¥ orginalet. Nödvändigt för automatisk centrering av " "arkmatade inläsningar." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Anger höjden pÃ¥ orginalet." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Bestämmer ifall en inbyggd eller användardefinierad gammatabell skall " "användas." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Gammakorrigeringstabell. I färgläge pÃ¥verkar denna inställning de röda, " "gröna och blÃ¥ kanalerna samtidigt (dvs det är en intensitetsgammatabell)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Gammakorrigeringstabell för den röda kanalen." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Gammakorrigeringstabell för den gröna kanalen." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Gammakorrigeringstabell för den blÃ¥ kanalen." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Bestämmer ljusstyrkan för den inlästa bilden." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Bestämmer kontrasten för den inlästa bilden." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Väljer \"kornigheten\" för den inlästa bilden. Mindre värden ger " "skarpare bilder." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Väljer ifall den inlästa bilden skall rasteras (gittras)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som \"svart\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som \"vit\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "Väljer vilken röd strÃ¥lglansnivÃ¥ som skall tolkas som \"vit\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "Väljer vilken grön strÃ¥lglansnivÃ¥ som skall tolkas som \"vit\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "Väljer vilken blÃ¥ strÃ¥lglansnivÃ¥ som skall tolkas som \"vit\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "Väljer vilken röd strÃ¥lglansnivÃ¥ som skall tolkas som \"svart\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "Väljer vilken grön strÃ¥lglansnivÃ¥ som skall tolkas som \"svart\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "Väljer vilken blÃ¥ strÃ¥lglansnivÃ¥ som skall tolkas som \"svart\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Väljer vilken röd strÃ¥lglansnivÃ¥ som skall tolkas som \"helt röd\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Väljer vilken grön strÃ¥lglansnivÃ¥ som skall tolkas som \"helt grön\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Väljer vilken blÃ¥ strÃ¥lglansnivÃ¥ som skall tolkas som \"helt blÃ¥\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Bestämmer \"nyansen\" (blÃ¥nivÃ¥n) pÃ¥ den inhämtade bilden." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "MättnadsnivÃ¥n bestämmer mängden \"blomning\" som förekommer när man " "läser in en bild med kamera. Större värden ger mer blomning." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Filnamnet pÃ¥ bilden som skall läsas." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Ställer in storleken pÃ¥ rastermönstret (gittret) som används vid " "inläsning av rastrerade bilder." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "Anger rastermönster (gitter) för inläsning av rastrerade bilder." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Använd samma värde för bÃ¥de X- och Y-upplösning" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Kasta om svart och vit" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Utför en kvalitetsvitkalibrering" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Använd lins som dubblar den optiska upplösningen" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Använd samma värden för varje färg i RGB-läge" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Välj minsta ljusstyrkan för att fÃ¥ en vitpunkt" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analog gammakorrigering" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analog gammakorrigering för rött" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analog gammakorrigering för grönt" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analog gammakorrigering för blÃ¥tt" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Värm upp lampan innan inläsning" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Ange exponeringstid för kalibrering" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Ange exponeringstid för röd kalibrering" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Ange exponeringstid för grön kalibrering" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Ange exponeringstid för blÃ¥ kalibrering" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Ange exponeringstid för inläsning" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Ange exponeringstid för röd inläsning" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Ange exponeringstid för grön inläsning" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Ange exponeringstid för blÃ¥ inläsning" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Möjliggör val av exponeringstid" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Ange lampdensitet för kalibrering" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Ange lampdensitet för inläsning" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Möjliggör val av lampdensitet" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "SlÃ¥ av lampan när programmet avslutas" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Inläsningsknapp" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "E-postknapp" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Faxknapp" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Kopieringsknapp" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "PDF-knapp" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Avbrytknapp" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Sida laddad" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Locket öppet" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Färg" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Färgstreckteckning" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Färgraster" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "GrÃ¥" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Raster" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Streckteckning" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "OK" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Kommandot ej understött" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "Kommandot avbröts" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "Enheten upptagen" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Ogiltigt argument" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "Filslut nÃ¥tt" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Stopp i dokumentmataren" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "Slut pÃ¥ dokument i dokumentmataren" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "Bildläsarens lock är öppet" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Fel under enhets-I/O" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Slut pÃ¥ minne" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "Tillträde till resursen har förvägrats" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "Lampan ej klar, vanligen försök igen" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "Bildläsaren lÃ¥st för transport" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Standardvärden" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Använd standardvärden för förbättringsinställningar." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibrering" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Kalibrera före nästa inläsning" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Om denna inställning är vald kommer enheten att kalibreras före nästa " "inläsning. Annars utförs kalibrering endast före första inläsningen." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Utför endast skuggkorrigering" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Om denna inställning är vald utförs endast skuggkorrigering vid " "kalibrering. Standardvärden för förstärkning, offset och exponeringstid, " "endera inbyggda eller frÃ¥n konfigureringsfilen, kommer att användas." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Knappläge" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Bildruta att läsa in" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Väljer numret pÃ¥ den bildruta som ska läsas in" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Dubbelsidig inläsning" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "Dubbelsidig inläsning läser in dokumentets framsida och baksida" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Kalibrera bildläsaren" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Utför bildläsarkalibrering före inläsning" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "GrÃ¥skaleinläsning" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Gör en grÃ¥skaleinläsning i stället för en färginläsning" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analog förstärkning" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Öka eller minska CCD-sensorns analoga förstärkning" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gammakorrigering" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Väljer gammakorrigerad överföringskurva" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "RÃ¥" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Fin färg" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Ingen genomlysningskorrigering" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Korrigering beroende pÃ¥ filmtyp" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Korrigering beroende pÃ¥ genomlysningskvot" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negativ" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Diapositiv" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatisk" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Normal hastighet" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 av normal hastighet" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 av normal hastighet" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "avrundad parameter" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "okänd" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "stopp i den automatiska dokumentmataren" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "automatiska dokumentmatarens lock är öppet" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "lampfel" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "inläsningshuvudspositioneringsfel" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "CPU-kontrollfel" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "RAM-kontrollfel" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "ROM-kontrollfel" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "hÃ¥rdvarukontrollfel" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "genomlysningsenhetslampfel" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "genomlysningsenhetsinläsningshuvudspositioneringsfel" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "parameterlistlängdsfel" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "ogiltig kommandooperationskod" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "ogiltigt fält i CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "ostött LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "ogiltigt fält i parameterlista" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "kommandosekvensfel" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "för mÃ¥nga fönster specificerade" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "media icke närvarande" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "ogiltigt bit-IDENTIFY-meddelande" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "inställning inte anslut" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "pÃ¥slagningsÃ¥terställning / bussenhetsÃ¥terställning" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parameter ändrad av en annan initiator" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "ingen ytterligare sense-information" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "Ã¥tervalsfel" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "SCSI-paritetsfel" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "intitator upptäckte mottaget felmeddelande" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "ogiltigt meddelande-fel" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "timeoutfel" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "genomlysningsenhetsskuggningsfel" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lampa ej stabiliserad" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "filmbildläsare" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "flatbäddsbildläsare" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Filmtyp" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Väljer filmtyp, t.ex. negativ eller diapositiv" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Negativfilmtyp" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Väljer negativfilmtyp" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "HÃ¥rdvaruupplösning" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Använd endast hÃ¥rdvaruupplösningar" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Fokus" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Autofokus" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Aktivera/avaktivera autofokus" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Autofokusera endast en gÃ¥ng" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Autofokusera endast en gÃ¥ng mellan utmatningar" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Manuell fokuseringspunkt" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" "Ställ in det optiska systemets fokuseringspunkt för hand (förval: 128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Inläsningsmarginaler" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Extra färgjusteringar" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Spegla bild" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Spegla bilden vÃ¥grätt" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Automatisk exponeringstid" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Aktivera/avaktivera automatisk exponeringstid" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Kalibrera nu" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Genomför kalibrering *nu*" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Självdiagnos" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Genomför bildläsarsjälvdiagnos" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Ã…terställ bildläsare" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Ã…terställ bildläsaren" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Mediahantering" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Mata ut film efter varje inläsning" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Mata ut filmen frÃ¥n enheten efter varje inläsning automatiskt" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Mata ut filmen före avslut" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "Mata ut filmen frÃ¥n enheten automatiskt före programmet avslutas" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Mata ut filmen nu" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Mata ut filmen *nu*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Dokumentmatarinställningar" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Endast flatbädd" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" "Stäng av den automatiska dokumentmataren och använd endast flatbädden" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Genomlysningsenhet" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "SlÃ¥ pÃ¥/av genomlysningsenheten (filmadapterenheten)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Negativ film" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Positiv eller negativ film" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Densitetsinställning" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Ställer in densitetsinställningsläge" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Genomlysningskvot" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Välj filmtyp" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Välj filmtyp" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flatbädd" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "Automatisk dokumentmatare framsida" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "Automatisk dokumentmatare baksida" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "Automatisk dokumentmatare dubbelsidigt" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Framsida" #: backend/canon_dr.c:413 #, fuzzy, no-c-format msgid "Card Back" msgstr "Baksida" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Dubbelsidigt" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Röd" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Grön" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "BlÃ¥" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "Framhäv rött" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "Framhäv grönt" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "Framhäv blÃ¥tt" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Inget" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "JPEG" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "Procentsats för hoppa över blanka sidor" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, fuzzy, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "Begär att drivrutinen hoppar över sidor med fÃ¥ mörka pixlar" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Enkelsidigt" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Dubbelsidigt" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Genomlysningsenhet" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatisk dokumentmatare" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Positiv film" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negativ film" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Fokusera pÃ¥ glaset" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Fokusera 2,5 mm ovanför glaset" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Raster A (hÃ¥rt)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Raster B (mjukt)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Raster C (nätskärm)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Gitter A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Gitter B (4x4 spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Gitter C (4x4 nätskärm)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Gitter D (8x4 nätskärm)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Textförbättringsteknik" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Nedladdat mönster A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Nedladdat mönster B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Ingen korrigering" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Användardefinierat" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Matrisskrivare" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Termoskrivare" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "BläckstrÃ¥leskrivare" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Bildskärmar (CRT)" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Standard" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Utskrift med hög densitet" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Utskrift med lÃ¥g densitet" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Utskrift med hög kontrast" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Användardefinierat (gamma=1,0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Användardefinierat (gamma=1,8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 stÃ¥ende" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 liggande" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "US-Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Max" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Bildläsarläge" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Väljer raster." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Blindfärg" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Väljer blindfärg." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Väljer ljusstyrka." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Skärpa" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Färgkorrigering" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Ställer in färgkorrigeringstabellen för den valda utdataenheten." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Färgkorrigeringskoefficienter" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matrismultiplikation av RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Skifta grön till röd" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Skifta grön till blÃ¥" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Skifta röd till grön" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Skifta röd till blÃ¥" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Skifta blÃ¥ till grön" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Skifta blÃ¥ till röd" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Bestämmer grönnivÃ¥n" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Lägger till till rött beroende pÃ¥ grönnivÃ¥n" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Lägger till till blÃ¥tt beroende pÃ¥ grönnivÃ¥n" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Lägger till till grönt beroende pÃ¥ rödnivÃ¥n" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Bestämmer rödnivÃ¥n" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Lägger till till blÃ¥tt beroende pÃ¥ rödnivÃ¥n" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Lägger till till grönt beroende pÃ¥ blÃ¥nivÃ¥n" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Lägger till till rött beroende pÃ¥ blÃ¥nivÃ¥n" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Bestämmer blÃ¥nivÃ¥n" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Spegla bilden." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Snabb förhandsgranskning" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Automatisk ytuppdelning" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Kort lista med upplösningar" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Visa en kort lista med upplösningar" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Zoom" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Anger zoom-faktorn som bildläsaren kommer att använda" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Snabbformatera" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Tillvalsutrustning" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Mata ut" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Mata ut bladet i dokumentmataren" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Mata ut automatiskt" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Mata ut dokument efter inläsning" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Dokumentmatarläge" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" "Väljer läge för den automatiska dokumentmataren (enkelsidigt/" "dubbelsidigt)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Fack" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Välj fack att läsa in frÃ¥n" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Väljer gammakorrigeringsvärdet frÃ¥n en lista av fördefinierade enheter " "eller en användardefinierad tabell som kan laddas ner till bildläsaren" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Fokuseringspunkt" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Ställer in fokuseringspunkten antingen pÃ¥ glaset eller 2,5 mm ovanför " "glaset" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Vänta pÃ¥ knapp" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Efter att ha skickat inläsningskommandot, vänta tills knappen pÃ¥ läsaren " "trycks in för att starta inläsningen." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "Infraröd" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "TPU 8x10" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Diapositiv" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Dianegativ" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "Inbyggd CCT-profil" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "Användardefinierad CCT-profil" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "PÃ¥" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Av" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "DTC" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "SDTC" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Gitter" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "Diffusion" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "Vit" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "Svart" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Fortsätt" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Avsluta" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10 mm" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15 mm" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20 mm" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "VÃ¥grätt" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "VÃ¥grätt fetstil" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "VÃ¥grätt smal" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Lodrätt" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "Lodrätt fetstil" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "UppifrÃ¥n och ner" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "NerifrÃ¥n och upp" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "Framsida" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "Baksida" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "Gammafunktionsexponent" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "Ändrar intensitet hos mellantoner" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, fuzzy, no-c-format msgid "Reverse image format" msgstr "Inverterad bild" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Raster" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Utför kalibrering" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Bildton" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Mättnad" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "" "Möjliggör automatisk bestämning av tröskelvärde för " "streckteckningsinläsningar." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Spegla bild" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Spegla bilden vÃ¥grätt." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "VitnivÃ¥ för blÃ¥tt" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Bestämmer rödnivÃ¥n" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Färgfilter" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Utjämning" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Gammavärde" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "Tröskelkurva" #: backend/fujitsu.c:3347 #, fuzzy, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "Dynamisk tröskelkurva, frÃ¥n ljust till mörkt, vanligen 50-65" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Tröskelvärde" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Brusreducering" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Ingen detektering" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Ingen detektering" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, fuzzy, no-c-format msgid "Compression" msgstr "jpeg-komprimmering" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, fuzzy, no-c-format msgid "Action following double feed error" msgstr "Ignorera högra dubbelmatningssensorn" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, fuzzy, no-c-format msgid "Enable double feed error due to skew" msgstr "Aktivera/avaktivera dubbelmatningsdetekteing" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, fuzzy, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "Aktivera/avaktivera dubbelmatningsdetekteing" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, fuzzy, no-c-format msgid "Enable double feed error due to paper length" msgstr "Aktivera/avaktivera dubbelmatningsdetekteing" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "automatiska dokumentmatarens lock är öppet" #: backend/fujitsu.c:3709 #, fuzzy, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "Begär att drivrutinen tar bort ramar frÃ¥n sidor auomatiskt" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Avancerade inställningar" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Ingen detektering" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Blindfärg" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Dokumentmatarläge" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Lampavstängningstid" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "BlÃ¥ offset" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Grön offset" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Grön offset" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "BlÃ¥ offset" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Ställer in den blÃ¥ kanalens offset" #: backend/fujitsu.c:3980 #, fuzzy, no-c-format msgid "Low Memory" msgstr "Slut pÃ¥ minne" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Dubbelsidig inläsning" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, fuzzy, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "Begär att drivrutinen linjerar upp sneda sidor digitalt" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "Mjukvaruupplinjering" #: backend/fujitsu.c:4021 #, fuzzy, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "Begär att drivrutinen linjerar upp sneda sidor digitalt" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "Mjukvarufläckborttagningsdiameter" #: backend/fujitsu.c:4034 #, fuzzy, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" "Maximal diameter för ensamma prickar som tas bort frÃ¥n den inlästa bilden" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "Mjukvarubeskärning" #: backend/fujitsu.c:4054 #, fuzzy, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "Begär att drivrutinen tar bort ramar frÃ¥n sidor auomatiskt" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Avancerade inställningar" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Brusreducering" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "FrÃ¥n papper" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "FrÃ¥n papper" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "FrÃ¥n papper" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "FrÃ¥n papper" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, fuzzy, no-c-format msgid "OMR or double feed detected" msgstr "Dubbelmatningsdetektering" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "Bildläsarens lock är öppet" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Manuell matning" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Manuell matning" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, fuzzy, no-c-format msgid "Double feed" msgstr "Dubbelmatningsdetektering" #: backend/fujitsu.c:4501 #, fuzzy, no-c-format msgid "Double feed detected" msgstr "Dubbelmatningsdetektering" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "hÃ¥rdvarukontrollfel" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "VitnivÃ¥" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Densitetsinställning" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Densitetsinställning" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Dubbelsidig inläsning" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "Begär att drivrutinen tar bort ram frÃ¥n sidor automatiskt" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "Begär att drivrutinen hoppar över sidor med fÃ¥ mörka pixlar" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "Mjukvaruavrotera" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" "Begär att drivrutinen detekterar och korrigerar 90 graders bildrotation" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Övrigt" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "Dynamisk tröskelkurva, frÃ¥n ljust till mörkt, vanligen 50-65" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "Avaktivera dynamisk streckteckning" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" "Stäng av användandet av en adaptiv algoritm i mjukvaran för att generera " "streckteckningsinläsningar för att i stället använda hÃ¥rdvarans " "streckteckningsinläsningsläge." #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Stäng av interpolering" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "När höga upplösningar används där den horisontella upplösningen är " "mindre än den vertikala upplösningen stänger detta av den horisontella " "interpoleringen." #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Färgfilter" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "När grÃ¥skala eller streckteckning används väljer denna inställning den " "använda färgen." #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibrering" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Definiera kalibreringsläge" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Kalibreringsdatacache" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Lampavstängningstid" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "Lampan kommer att stängas av efter den angivna tiden (i minuter). Värdet " "0 betyder att lampan inte kommer att stängas av." #: backend/genesys.c:5943 #, no-c-format msgid "Lamp off during scan" msgstr "Stäng av lampan under inläsning" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "Lampan kommer att stängas av under inläsningen." #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Filknapp" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "Optisk teckenigenkännings-knapp" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "PÃ¥slagningsknapp" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "E-postknapp" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "Behöver kalibrering" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Bildläsaren behöver kalibrering för nuvarande inställningar" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Knappar" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibrera" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "PÃ¥börja kalibrering med specialark" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Rensa kalibrering" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Rensa kalibreringsdatacache" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Genomlysningsadapter" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "GrÃ¥lägesfärg" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Väljer vilken inläsningsfärg som används i grÃ¥läge (förval: grönt)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Debuggningsinställningar" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatisk uppvärmning" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Värm upp tills lampans ljusstyrka är konstant i stället för att " "insistera pÃ¥ 60 sekunders uppvärmningstid." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Fullständig inläsning" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Läs in hela inläsningsytan inklusive kalibreringsraden. Var försiktig. " "Välj inte för stor höjd. Endast för test." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Grovkalibrering" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Ställ in förstärkning och offset för inläsning automatiskt. Om denna " "inställning inte är vald kan de analoga parametrarna ställas in för " "hand. Denna inställning är förvald som standard. Endast för test." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Grovkalibrering endast för första inläsningen" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Grovkalibrering görs endast för första inläsningen. Fungerar för de " "flesta bildläsare och kan spara tid. Välj inte denna inställning om " "bildens ljusstyrka är olika för varje inläsning. Endast för test." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "BakspÃ¥rningslinjer" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Antal linjer inläsningshuvudet flyttar sig bakÃ¥t när bakspÃ¥rning sker. " "Detta händer när bildläsaren läser in fortare än datorn kan ta emot " "data. LÃ¥ga värden ger snabbare inläsningar men ökar risken för att " "utelämna linjer." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gammavärde" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Ställer in gammavärdet för alla kanaler." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Geometrigrupp" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Bildläsarlägesgrupp" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Diapositiv" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Bildläsarmodel" #: backend/hp3900_sane.c:1408 #, fuzzy, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "TillÃ¥ter att testa enhetsbeteende med andra understötta modeller" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Bildens färger kommer att inverteras" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Stäng av gammakorrigering" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "Gammakorrigering kommer att stängas av" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Stäng av vit skuggkorrigering" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "Vit skuggkorrigering kommer att stängas av" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Hoppa över uppvärmningsprocessen" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "Uppvärmningsprocessen kommer att stängas av" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Använd verkligt bitdjup" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "Om gamma är aktiverat görs inläsningar alltid med 16 bitars djup för att " "förbättra bildkvaliteten för att sedan konvertera till det valda " "bitdjupet. Denna inställning undviker bitdjupsemulering." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Emulera grÃ¥skala" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "Om aktiverad, kommer bilden att läsas in i färg för att sedan " "konverteras till grÃ¥skala av mjukvara. Detta kan förbättra " "bildkvaliteten under vissa omständigheter." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Spara debuggningsbilder" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "Om aktiverad kommer ett antal bilder inblandade i " "inläsningsprocesseringen att sparas för analys." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Ã…terställ chipset" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Ã…terställer chipsetdata" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Information" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Chipsetsnamn" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Visar chipsetnamn använt i enheten." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Okänd" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "Chipset-ID" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Visar chipset-ID" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Inläsningsräknare" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Visar antalet inläsningar som gjorts med bildläsaren" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Uppdatera informationen" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Uppdaterar informationen om enheten" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Denna inställing avspeglar en knapp pÃ¥ bildläsarens panel" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Bild" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Diverse" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "offset X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Inläsningsytans hÃ¥rdvaruinterna X-position." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "offset Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Inläsningsytans hÃ¥rdvaruinterna Y-position." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Lampstatus" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Sätter pÃ¥ eller av lampan." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Kalibrerar för svart- och vitnivÃ¥." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "Automatisk dokumentmatare" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMA-positiv" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMA-negativ" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Färg (48 bitar)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Utöka lampavstängningstid" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Utökar lampavstängningstiden (frÃ¥n 15 minuter till 1 timme)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Vänta pÃ¥ knapp" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Vänta pÃ¥ knapp innan inläsning" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Avancerade inställningar" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Grovt" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fint" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Användardefinierat" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automatiskt" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC-RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA-RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Oförändrat" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC-grÃ¥" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA-grÃ¥" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "LÃ¥ngsam" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Snabb" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Extra snabb" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2 pixlar" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4 pixlar" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8 pixlar" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Fotografi" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Filmremsa" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Villkorlig" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Experiment" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Skärpa" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Ställer in skärpevärdet." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Automatiskt tröskelvärde" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Möjliggör automatisk bestämning av tröskelvärde för " "streckteckningsinläsningar." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Välj utjämningsfilter." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Mata ut media efter inläsning" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Matar ut media efter en inläsning." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Byt dokument" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Byt dokument." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Mata ut" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Mata ut dokument." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "PÃ¥börja kalibreringsprocessen." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Media" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Välj mediatyp." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Exponeringstid" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "En längre exponeringstid lÃ¥ter bildläsaren samla in mer ljus. Föreslagen " "användning är 175% för fotografier, 150% för diapositiv och \"Negativ\" " "för negativ film. För mörka (underexponerade) bilder kan du öka detta " "värde." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Färgmatris" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Ställer in bildläsarens färgmatris." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Användardefinierad färgmatris." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Enfärgsmatris" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Användardefinierad färgmatris för grÃ¥skaleinläsningar." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Spegla vÃ¥grätt" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Spegla bilden vÃ¥grätt." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Spegla lodrätt" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Spegla bilden lodrätt." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Uppdatera inställningsvärden" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Uppdatera inställningsvärden." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8 bitars utdata" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Använd ett bitdjup större än 8 internt, men ge endast 8 bitars utdata." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Invänta knapptryck" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" "Vänta med inläsningen tills dess att knappen pÃ¥ frontpanelen trycks in." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "SlÃ¥ av lampan" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "SlÃ¥ av bildläsarlampan." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Pappersstorlek" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatisk separering" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, no-c-format msgid "Landscape" msgstr "Liggande" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "Inverterad bild" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "Läge för lÃ¥nga papper" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "Längdkontrollsläge" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "Manuell matning" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, no-c-format msgid "Manual feed timeout" msgstr "Timeout för manuell matning" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "Dubbelmatningsdetektering" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Sätt pÃ¥ dubbelsidig inläsning" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Verklig storlek pÃ¥ papperet i den automatiska dokumentmataren" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "s/v" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "raster" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "grÃ¥skala" #: backend/kvs1025_opt.c:42 #, no-c-format msgid "color" msgstr "färg" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "adf" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "fb" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "ensidigt" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "kontinuerligt" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "av" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "invänta dokument" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "invänta knapptryckning" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "användardefinierat" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "visitkort" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "Check" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "A5" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "A6" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "B5" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "B6" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "US-Legal" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "Bayer 64" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "Bayer 16" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "Raster 32" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "Raster 64" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "diffusion" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, no-c-format msgid "normal" msgstr "normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, no-c-format msgid "light" msgstr "ljus" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "mörk" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, no-c-format msgid "From scanner" msgstr "FrÃ¥n bildläsare" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "FrÃ¥n papper" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, no-c-format msgid "default" msgstr "standard" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "jämn" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "ingen" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, no-c-format msgid "low" msgstr "lÃ¥g" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, no-c-format msgid "medium" msgstr "medel" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "hög" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "bildskärm" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "linjär" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, no-c-format msgid "red" msgstr "röd" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, no-c-format msgid "green" msgstr "grön" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "blÃ¥" #: backend/kvs1025_opt.c:562 #, no-c-format msgid "Sets the scan source" msgstr "Väljer bildläsarkälla" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Dokumentmatarläge" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Ställer in dokumentmatarläge" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "Aktivera/avaktivera läge för lÃ¥ngt papper" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "Aktivera/avaktivera läge för längdkontroll" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, no-c-format msgid "Sets the manual feed mode" msgstr "Ställer in manuellt matningsläge" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Ställer in timeout för manuell matning i sekunder" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "Aktivera/avaktivera dubbelmatningsdetekteing" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "anpassa till sida" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "Anpassa till sida" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "Bildläsaren krymper sidan för att rymmas pÃ¥ den inlästa sidan" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "Ställ in pappersläge: sant för liggande, falskt för stÃ¥ende" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatiskt tröskelvärde" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Ställer in ljusstyrka, kontrast, vitnivÃ¥, gamma, brusreduktion och " "bildton automatiskt" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Brusreducering" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Minska bruset frÃ¥n isolerade punkter" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Bildton" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Ställer in bildton" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, no-c-format msgid "Lamp color" msgstr "Lampfärg" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Ställer in lampfärg (blindfärg)" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "Invertera bild i svart-vitt eller rasterläge" #: backend/kvs1025_opt.c:840 #, no-c-format msgid "Mirror image (left/right flip)" msgstr "Spegla bilden (vänster/höger)" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "jpeg-komprimmering" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "JPEG-bildkomprimmering med Q-parameter, '0' - ingen komprimmering" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "Rotera bilden medurs" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "Begär att drivrutinen roterar sidor med ett fixt värde" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "Begär att drivrutinen linjerar upp sneda sidor digitalt" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" "Maximal diameter för ensamma prickar som tas bort frÃ¥n den inlästa bilden" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "Automatisk beskärning i mjukvara" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "Begär att drivrutinen tar bort ramar frÃ¥n sidor auomatiskt" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" "I längdkontrolläge läser bildläsaren upp till den kortare av verklig " "papperslängd och logisk dokumentlängd." #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gammakorrigering" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "invänta dokument \"hopper\"" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "A3" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "Dubbelt US-Letter 11x17 tum" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "B4" #: backend/kvs40xx_opt.c:231 #, no-c-format msgid "High sensivity" msgstr "Hög känsighet" #: backend/kvs40xx_opt.c:232 #, no-c-format msgid "Low sensivity" msgstr "LÃ¥g känsighet" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "Feldiffusion" #: backend/kvs40xx_opt.c:249 #, no-c-format msgid "No detection" msgstr "Ingen detektering" #: backend/kvs40xx_opt.c:250 #, no-c-format msgid "Normal mode" msgstr "Normalläge" #: backend/kvs40xx_opt.c:251 #, no-c-format msgid "Enhanced mode" msgstr "Förbättringsläge" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" "I lÃ¥ngpappersläge läser bildläsaren in bilden efter att den delat upp " "lÃ¥nga papper i delar med en längd som angetts in " "dokumentstorleksparametrarna." #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "Dubbelmatningsdetektionskänslighet" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "Ställ in dubbelmatningsdetektionskänsligheten" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "Avbryt inte efter dubbelmatningsdetektering" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "Ignorera vänstra dubbelmatningssensorn" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "Ignorera mellersta dubbelmatningssensorn" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "Ignorera högra dubbelmatningssensorn" #: backend/kvs40xx_opt.c:642 #, no-c-format msgid "Automatic threshold mode" msgstr "Automatiskt tröskelläge" #: backend/kvs40xx_opt.c:643 #, no-c-format msgid "Sets the automatic threshold mode" msgstr "Väljer automatiskt tröskelläge" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "Invertera bilden i svart-vitt läge" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "JPEG-komprimmering" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "JPEG-komprimmering (din applikation mÃ¥ste kunna dekomprimmera)" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "Detektera häftade dokument" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "Röd färgmättnad" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "Ställ in färgmättnad för rött" #: backend/kvs40xx_opt.c:787 #, no-c-format msgid "chroma of blue" msgstr "BlÃ¥ färgmättnad" #: backend/kvs40xx_opt.c:788 #, no-c-format msgid "Set chroma of blue" msgstr "Ställ in färgmättnad för blÃ¥tt" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "Justering för sned inmatning" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "Stoppa bildläsaren när ett papper har inmatats snett" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "Stoppa bildläsaren när ett papper har inmatats snett" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "Beskär verklig bildarea" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "Bildläsaren detecterar automatiskt verklig bildarea och beskär den" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "Den kastar om höger och vänster" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "Lägg till utrymme ovanför bilden" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "Lägg till utrymme nedanför bilden" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamant" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 grov förtjockning" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 fin förtjockning" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 lodrät linje" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Förstärking" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Inställningar för färgkanalernas förstärkning" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "GrÃ¥ förstärkning" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Ställer in den grÃ¥ kanalens förstärkning" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Röd förstärkning" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Ställer in den röda kanalens förstärkning" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Grön förstärkning" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Ställer in den gröna kanalens förstärkning" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "BlÃ¥ förstärkning" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Ställer in den blÃ¥ kanalens förstärkning" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayergitter 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayergitter 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Rasterpunkt 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Rasterpunkt 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Feldiffusion" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Läge 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Läge 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Läge 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "FrÃ¥n kalibreringsraden" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Jämn" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "LÃ¥g" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Medel" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Hög" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "Bildskärm" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "En sida" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Alla sidor" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "arkmatad bildläsare" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "4 bitars grÃ¥skala" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "8 bitars grÃ¥skala" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Skugga, mittvärde, belysning, exponeringstid" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Specialinställningar" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Färgbalans" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Stäng av bakspÃ¥rning" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Om denna inställning är vald utför bildläsaren ingen bakspÃ¥rning" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "SlÃ¥ av eller pÃ¥ lampan" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "SlÃ¥r av eller pÃ¥ flatbäddsbildläsarens lampa" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Bakplanskalibrering" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Om denna inställning är vald utförs färgkalibreringen före en inläsning " "av bakplanet" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Använd lightlid-35 mm-adaptern" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "" "Denna inställning slÃ¥r av lampan pÃ¥ flatbäddsbildläsaren under en " "inläsning" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Kvalitetsinläsning" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Högsta kvalitet men lägre hastighet" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Snabbinläsning" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Högsta hastighet men lägre kvalitet" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatisk inställning av tröskelvärde" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Om denna inställning är vald försöker bakplanet automatiskt bestämma ett " "optimalt tröskelvärde." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Väljer gammakorrigeringsläge." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Koppla gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Använd samma gammavärde för alla färgkanaler." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Skalärt gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Väljer värde för skalär gammakorrigering." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Skalärt gamma rött" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Väljer värde för skalär gammakorrigering (röd kanal)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Skalärt gamma grönt" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Väljer värde för skalär gammakorrigering (grön kanal)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Skalärt gamma blÃ¥tt" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Väljer värde för skalär gammakorrigering (blÃ¥ kanal)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Kanal" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Väljer färgkanal, \"Master\" betyder att alla färgkanaler pÃ¥verkas." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Mittvärde" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som \"50% grÃ¥\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Mittvärde för rött" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som \"50% röd\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Mittvärde för grönt" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som \"50% grön\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Mittvärde för blÃ¥tt" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som \"50% blÃ¥\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Röd färgbalans" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Balanseringsfaktor för rött. 100% betyder ingen korrigering." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Grön färgbalans" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Balanseringsfaktor för grönt. 100% betyder ingen korrigering." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "BlÃ¥ färgbalans" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Balanseringsfaktor för blÃ¥tt. 100% betyder ingen korrigering." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Färgbalans frÃ¥n fast programvara" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" "Ställer in färgbalansvärdena till de värden som ges frÃ¥n den fasta " "programvaran." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "LÃ¥ngsammast" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "LÃ¥ngsammare" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Snabbare" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Snabbast" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 grovt" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normalt" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fint" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 mycket fint" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normalt" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 grovt" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fint" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 grovt" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normalt" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fint" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normalt" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normalt" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 användardefinierat" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 användardefinierat" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 användardefinierat" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 användardefinierat" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 användardefinierat" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 användardefinierat" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Snabbt grÃ¥skaleläge" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Läs in i snabbt grÃ¥skaleläge (lägre kvalitet)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Begär att alla förhandsgranskningar görs i det snabbaste " "(lÃ¥gkvalitets-)läget. Detta kan vara en icke-färginläsning eller en " "lÃ¥gupplösningsinläsning." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Lampavstängningstid (minuter)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Ställer in tiden (i minuter) efter vilken lampan stängs av." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Stäng av lampan" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Stänger av lampan omedelbart." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Röd ljusstyrka" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Bestämmer ljusstyrkan för den röda kanalen i den inlästa bilden." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Grön ljusstyrka" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Bestämmer ljusstyrkan för den gröna kanalen i den inlästa bilden." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "BlÃ¥ ljusstyrka" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Bestämmer ljusstyrkan för den blÃ¥ kanalen i den inlästa bilden." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Kontrast röd kanal" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Bestämmer kontrasten för den röda kanalen i den inlästa bilden." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Kontrast grön kanal" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Bestämmer kontrasten för den gröna kanalen i den inlästa bilden." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Kontrast blÃ¥ kanal" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Bestämmer kontrasten för den blÃ¥ kanalen i den inlästa bilden." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Färg 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Färg 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "GrÃ¥ 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "GrÃ¥ 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Speglande" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positiv" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Värm upp tills lampans ljusstyrka är konstant i stället för att " "insistera pÃ¥ 40 sekunders uppvärmningstid." #: backend/pixma.c:378 #, no-c-format msgid "Negative color" msgstr "Negativ färg" #: backend/pixma.c:383 #, no-c-format msgid "Negative gray" msgstr "Negativ grÃ¥skala" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "48 bitars färg" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "16 bitars grÃ¥skala" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" "Väljer inläsningskälla (som t.ex. dokumentmatare). Välj källa före läge " "och upplösning. Ã…terställer läge och upplösning till förvalsvärden." #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Knappkontrollerad inläsning" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Om denna inställning är vald kommer inläsningen inte att starta " "omedelbart. För att forsätta, tryck SCAN-knappen (för MP150) eller COLOR-" "knappen (för andra modeller). För att avbryta, tryck GRAY-knappen." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Uppdatera knappläge" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Knapp 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Knapp 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Skrivfilm" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Enhetsinställningar" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Lampströmbrytare" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "SlÃ¥r av/pÃ¥ lamp(an/orna) manuellt." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Stäng av lampan under mörkerkalibrering" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Stäng alltid av lampan när mörkerkalibrering görs" #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Kalibreringsdatacache" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Aktiverar eller deaktiverar kaliberingsdatacache." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Utför kalibrering" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Öka givarens hastighet" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Aktiverar eller deaktiverar ökning av givarens rörelsehastighet." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Uppvärmningstid" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Uppvärmningstid i sekunder." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Lampavstängningstid" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Lampavstängningstid i sekunder." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Analogt framplan" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Det analoga framplanets rödförstärkningsvärde" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Röd offset" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Det analoga framplanets rödoffsetvärde" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Det analoga framplanets grönförstärkningsvärde" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Det analoga framplanets grönoffsetvärde" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Det analoga framplanets blÃ¥förstärkningsvärde" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Det analoga framplanets blÃ¥offsetsvärde" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Röd lampa av" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Definierar röd-lampa-av-parameter" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Grön lampa av" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Definierar grön-lampa-av-parameter" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "BlÃ¥ lampa av" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Definierar blÃ¥-lampa-av-parameter" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Denna inställing avspeglar status pÃ¥ bildläsarens knappar." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Färg 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Gitterkarta 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Gitterkarta 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Slumpvist" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Val av bildkälla" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Bildförbättring" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Gör grÃ¥" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Läs in bilden som grÃ¥skala" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Trepassimulering" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simulera en trepassbildläsare genom att returnera 3 separata bildrutor. " "För att retas returnerar den först grönt, sedan blÃ¥tt och sist rött." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Handbildläsarsimulering" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simulera en handbildläsare. Handbildläsare vet oftast inte bildhöjden i " "förväg. I stället returnerar de en höjd som är -1. Om denna inställning " "är vald kan man testa om ett framplan kan hantera detta pÃ¥ rätt sätt." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Använd standardvärden för förbättringsinställningar (ljusstyrka och " "kontrast)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Skrivskyddad testinställning" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "LÃ¥t oss se om framplan kan hantera detta" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Gammatabeller" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Statuskodsimulering" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Framtvinga inte statuskod" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Tvinga inte bakplanet att returnera en statuskod." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Returnera SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Tvinga bakplanet att returnera statuskoden SANE_STATUS_EOF efter det att " "sane_read() har anropats." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Returnera SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Tvinga bakplanet att returnera statuskoden SANE_STATUS_JAMMED efter det " "att sane_read() har anropats." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Returnera SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Tvinga bakplanet att returnera statuskoden SANE_STATUS_NO_DOCS efter det " "att sane_read() har anropats." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Returnera SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Tvinga bakplanet att returnera statuskoden SANE_STATUS_COVER_OPEN efter " "det att sane_read() har anropats." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Returnera SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Tvinga bakplanet att returnera statuskoden SANE_STATUS_IO_ERROR efter " "det att sane_read() har anropats." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Returnera SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Tvinga bakplanet att returnera statuskoden SANE_STATUS_NO_MEM efter det " "att sane_read() har anropats." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Returnera SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Tvinga bakplanet att returnera statuskoden SANE_STATUS_ACCESS_DENIED " "efter det att sane_read() har anropats." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Denna inställing avspeglar status pÃ¥ en av bildläsarens knappar." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lampa pÃ¥" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "SlÃ¥ pÃ¥ bildläsarlampan" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lampa av" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "SlÃ¥ av bildläsarlampan" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Lampavstängningstid" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Antal minuter innan lampan stängs av efter en inläsning" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Tröskelvärde för streckteckningsläge" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Dokumentmatare" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (tum)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (tum)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8,5x11 (tum)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Rastrering stöds inte" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "Upplöst punkt 8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "Upplöst punkt 16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Antal inläsningslinjer som skall begäras vid en SCSI-läsning. Genom att " "ändra denna parameter kan du ställa in hastigheten med vilken data läses " "frÃ¥n bildläsaren under inläsningar. Om den sätts för lÃ¥g, kommer " "bildläsaren att behöva stanna med jämna mellanrum under inläsningen. Om " "den sätts för hög kan X-baserade framplan sluta svara pÃ¥ X-händelser och " "ditt system kan gÃ¥ ned." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Mata ut dokument efter inläsning" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Förhandsgranskningsläge" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Välj förhandsgranskningsläge. GrÃ¥skaleförhandsgranskningar ger oftast " "den bästa kombinationen av hastighet och detaljrikedom." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Fördefinierade inställningar" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Ger standardinläsningsytor för fotografier, tryckta sidor och liknande." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "flatbäddsbildläsare" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Fokus" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Autofokus" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Fokuseringspunkt" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Fokuseringspunkt" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Färglinjer per inläsning" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "GrÃ¥skalelinjer per inläsning" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "webbkamera" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Färg RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Färg RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Färg RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Helsvart" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Helvit" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Färgmönster" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Rutnät" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Första punkten" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Andra punkten" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Detta är den mycket lÃ¥nga tredje punkten. Kanske har framplanet nÃ¥gon " "idé om hur det skall visa den" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Handbildläsarsimulering" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulera en handbildläsare. Handbildläsare vet oftast inte bildhöjden i " "förväg. I stället returnerar de en höjd som är -1. Om denna inställning " "är vald kan man testa om ett framplan kan hantera detta pÃ¥ rätt sätt. " "Denna inställning ger ocksÃ¥ en fast bredd pÃ¥ 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Trepassimulering" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "Simulera en trepassbildläsare. I färgläge överförs tre bildrutor." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Ställ in ordningen för bildrutorna" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Ställ in ordningen för bildrutorna i trepass-färgläge." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Om Automatisk dokumentmatare valts kommer mataren att vara 'tom' efter " "10 inläsningar." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Specialinställningar" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Välj testbild" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Väljer typ av testbild. Möjliga val:\n" "Helsvart: fyller hela bilden med svart.\n" "Helvit: fyller hela bilden med vitt.\n" "Färgmönster: ritar olika testfärgmönster beroende pÃ¥ bildläsarläget.\n" "Rutnät: ritar ett svart-vitt rutnät med en bredd och höjd pÃ¥ 10 mm per " "ruta." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Invertera endianness" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Kastar om den högre och lägre byten i bilddata i 16-bitarslägen. Denna " "inställning kan användas för att testa 16-bitarslägen pÃ¥ framplan, dvs " "om framplanet använder rätt endianness." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Läsbegränsning" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Begränsa mängden data som överförs vid varje anrop till sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Storlek pÃ¥ läsbegränsning" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "Den (största) mängd data som överförs vid varje anrop till sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Läsfördröjning" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Fördröj överföringen av data." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Längd pÃ¥ läsfördröjning" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "Längden pÃ¥ fördröjningen efter varje databuffer som överförts." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Returvärde för sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Väljer returvärde för sane_read(). \"Standard\" är den normala hantering " "för inläsning. Alla andra statuskoder är till för att testa hur " "framplanet hanterar dem." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Pixelförlust per rad" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Antal pixlar som kastas i slutet av varje rad." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Oklara parametrar" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Returnera oklara lines och bytes_per_line när sane_parameters() anropas " "före sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Använd icke-blockerande IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Använd icke-blockerande IO för sane_read() om det stöds av framplanet." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Erbjud en select file descriptor" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Erbjud en select file descriptor för att detektera om sane_read() kommer " "att returnera data." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Aktivera testinställningar" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Aktivera diverse testinställningar. Detta är till för att testa förmÃ¥gan " "hos framplan att visa och ändra de olika typerna av SANE-inställningar." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Skriv ut inställningar" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Skriv ut en lista med alla inställningar." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Booleska testinställningar" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Boolesk mjukvaruvald mjukvarudetekterad" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Boolesk testinställning som är mjukvaruvald och mjukvarudetekterad " "(och avancerad). Detta är en normal Boolesk inställning." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Boolesk hÃ¥rdvaruvald mjukvarudetekterad" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Boolesk testinställning som är hÃ¥rdvaruvald och mjukvarudetekterad " "(och avancerad). Det betyder att inställningen inte kan ställas in av " "framplanet, men av användaren (t.ex. genom att trycka pÃ¥ en knapp pÃ¥ " "enheten)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Boolesk hÃ¥rdvaruvald" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Boolesk testinställning som är hÃ¥rdvaruvald (och avancerad). Det " "betyder att inställningen inte kan ställas in av framplanet, men av " "användaren (t.ex. genom att trycka pÃ¥ en knapp pÃ¥ enheten) och att den " "inte kan läsas av framplanet." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Boolesk mjukvarudetekterad" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Boolesk testinställning som är mjukvarudetekterad (och avancerad). " "Detta betyder att inställningen är skrivskyddad." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Boolesk mjukvaruvald mjukvarudetekterad emulerad" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Boolesk testinställning som är mjukvaruvald, mjukvarudetekterad " "och emulerad (och avancerad)." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Boolesk mjukvaruvald mjukvarudetekterad automatisk" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Boolesk testinställning som är mjukvaruvald, mjukvarudetekterad " "och automatisk (och avancerad). Denna inställning kan ställas in " "automatiskt av bakplanet." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Heltalsinställningar" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Heltal" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Heltalstestinställning utan enhet och utan villkor." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Heltal intervallvillkor" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Heltalstestinställning med enheten pixlar och ett " "intervallvillkor. Minimum är 4, maximum 192 och steglängden är 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Heltal listvillkor" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Heltalstestinställning med enheten bitar och ett listvillkor." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Heltalsvektor" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "(4/6) Heltalsvektorstestinställning med enheten mm utan villkor." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Heltalsvektor intervallvillkor" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Heltalsvektorstestinställning med enheten punkter per tum och " "intervallvillkor. Minimum är 4, maximum 192 och steglängden är 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Heltalsvektor listvillkor" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Heltalsvektorstestinställning med enheten procent och listvillkor." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "BrÃ¥ktalstestinställningar" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) BrÃ¥ktal" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) BrÃ¥ktalstestinställning utan enhet och utan villkor." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) BrÃ¥ktal intervallvillkor" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) BrÃ¥ktalstestinställning med enheten mikrosekunder och " "intervallvillkor. Minimum är -42.17, maximum är 32767.9999 och " "steglängden är 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) BrÃ¥ktal listvillkor" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "(3/3) BrÃ¥ktalstestinställning utan enhet med listvillkor." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Strängtestinställningar" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) Sträng" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Strängtestinställning utan villkor." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) Sträng stränglistevillkor" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) Strängtestinställning med stränglistevillkor." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) Sträng stränglistevillkor (lÃ¥ng lista)" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) Strängtestinställning med stränglistevillkor. InnehÃ¥ller nÃ¥gra " "fler punkter..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Knapptestinställningar" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Knapp" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Knapptestinställning. Skriver ut lite text..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Färg 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Använd bildkomponering" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "TvÃ¥nivÃ¥-svart-vit (streckteckningsläge)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Gittrad/rastrerad svart-vit (rasterläge)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "FlernivÃ¥-svart-vit (grÃ¥skaleläge)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "FlernivÃ¥-RGB-färg (enpass-färg)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignorera kalibrering" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Stäng av förfokusering" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Kalibrera inte fokus" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Manuell förfokusering" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Fast fokuseringspunkt" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Kalibrera linsen i dokumentets läge" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Kalibrera linsens fokus i dokumentets läge" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "HÃ¥llarens fokuseringspunkt 0 mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Använd 0 mm i stället för 0,6 mm för hÃ¥llarens fokuseringspunkt" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Kalibreringsläge" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Definiera kalibreringsläge" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Sätt pÃ¥/av lampan" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA pÃ¥" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Sätter pÃ¥/av UTA" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Offset" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Inställningar för färgkanalernas offset" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "GrÃ¥ offset" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Ställer in den grÃ¥ kanalens offset" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Ställer in den röda kanalens offset" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Ställer in den gröna kanalens offset" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Ställer in den blÃ¥ kanalens offset" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Förhandsgranskningsläge" sane-backends-1.0.27/po/fi.gmo0000664000175000017500000015467513110600540012752 00000000000000Þ•s´GL'h4 i4-v4 ¤4;°4 ì4,ù4"&5zI5 Ä59Î56€%6#¦65Ê6"7Æ#7ê7j8 p8B‘8(Ô8Sý8Q9Øh9A:B`:£:lº:';J7;+‚;c®; <z3<'®<™Ö<$p=W•=í= õ= > > >!> )> 4>?> H> S> ^>i> r> }> ˆ> “> > ¨> ¶> Â>Ì>ß>ð> ? ?? !? ,?Ò:? @ @ @)@-@!6@X@!x@ š@»@ Û@ü@sA yA ƒAA¡A¹AÌAÝA õA!B8BXB]BlB ƒB ŽB˜B!²BÔBéBýB_C=nC>¬C<ëC(D,D2DBD'RDzDƒD›D ­D ¸D ÂDÎD ÓDàD ðDúD EE'E%6E\E%kE ‘E œE©E½EÀE ÄEÑEäEFF8F JFTFfF)F «F·FÎFßFðFGGG&"GÄIGHHH ,H :H GH QH[H jHxH•H´HÅH ãHñHùHI I I+I4IJIaIvIŠIŸI6²I.éIBJC[JAŸJ,áJ@KAOK?‘K(ÑKúK(L*L?LQLYLbL)zL"¤L$ÇL*ìL#M(;M!dM†M#¤MÈMIåM,/N'\N0„NDµNúNOO)O;OKOiOpO…O›OµO/ÏO ÿO P%P=P\PsP1ŒP¾PÎPèPûPQQ,Q2QPQ#kQ?Q!ÏQ ñQR&R ¨R­´R bS pS{S€S S œS¦S­S µSÁS ÊS ÔSßSäS õSTT'T/TGTVTeTxT%‘Th·Te U^†UcåUaIVb«VaW pW{W W—W¨W­W³W ÄWÑW âW)îW*X(CX›lXY YY !Y +Y7Y>YDYLY]YnY}Y ƒY‘Y ¢Y­Y ½YÊYãYèYñYZZ7ZGZWZhZ ~Z‰Z Z¸ZÐZÕZìZ["[ B[L[_[s[…[ Ÿ[Iª[ô[[ø[ET\4š\¹Ï\€‰] ^^/^>^N^*b^5^Ã^Ô^å^÷^__ _0:_k_Cr_¶_¾_Û_ó_÷_ ``:`>`D`K`S`d`v`†` ˜`¥`À`Ù`ë`û`a aa&"a*Ia ta~a‡a a ža¬a¼aÁaXÈa!b]3b‘c­cL±cþcd"d%d.dNd ad%ld ’d d´d ¼dÉdÏd ìdMúdHe \e ie ve €e ‹e–eM¬eúe þe ff "f 0f;fYfÖyf|Pg Ígîg h#h?hYhth[Žhêh i ii.iAi Ri\ioi‹i¨i'Ãiëi ýij j #jx.j §j´j.Çjöj#kg3lœ›l8m:Pm;‹m9Çm,nY.n%ˆn®nFÆn* o"8o‡[oão'ùo<!p4^p>“pBÒp>q?TqD”q?Ùq9r9Sr=r@Ër= sBJs>s>Ìs? t=KtD‰t,Îtût uu4u1Lu~uu°uÀu×uðuv v8vRvcvyv>‘v?ÐvwD&w%kw4‘wÆw)ÞwXx2axÌ”xayhyxy‰y)˜y Ây Íy×yëyýyz$z6zIz _zmz„züŒzЉ{pZ|KË|}*}0}5}<}D} K} U} a}m}~}Ž}ž}¹}Ð}ä}ù}G~'Z~=‚~ŒÀ~MS^;²î€ €$€;€ [€!f€ ˆ€!“€ µ€€×€ é€  5<CTlŒ›.«ÚCð4‚(K‚t‚Aˆ‚.Ê‚&ù‚ ƒ >ƒKƒdƒ}ƒ†ƒ–ƒ)¦ƒ`Ѓ`1„ ’„ž„ º„Ƅۄñ„ ………… '…4…9…I…—Z… ò†!‡"‡>2‡q‡#‚‡(¦‡yχIˆ3\ˆ!ˆƒ²ˆ6‰'T‰'|‰Ë¤‰$pŠd•Š-úŠM(‹(v‹EŸ‹勿þ‹åŒ?EdaÆIá4+ŽO`Ž,°ŽlÝŽ-J‘x' M2 €Œ ”¡ © ¶ ÂÌ Ô Þ ëõ ý ‘‘ ‘)‘ :‘F‘ V‘ d‘n‘ƒ‘˜‘ §‘±‘ ¹‘ ÑБéߑɒ̒Ւޒ â’/í’/“/M“0}“.®“/Ý“ ”” ž”«”À”Û”ó”•*•"C•#f•#Š• ®•¼•Еç• ü• –!–@–W–l–g„–:ì–;'—;c—Ÿ—¤—ª—»—'Ì—ô—ý—˜ )˜ 4˜ @˜J˜ R˜`˜q˜ƒ˜–˜¨˜À˜,јþ˜,™<™E™U™m™ p™|™™¡™¼™Ø™ô™šš#$š)Hš rš~šš š «š¸š¿šÅš2Öšâ ›ì›ò› û›œ œ (œ 2œ<œMœ\œtœ Œœ™œ ¯œºœÜ̜՜ éœ ôœþœ#6Sq("¸#Û$ÿ$$ž#Iž#mž$‘ž$¶ž(ÛžŸ+Ÿ4ŸGŸWŸ ^ŸhŸ(„Ÿ(­Ÿ ÖŸ)÷Ÿ)! )K )u Ÿ +¾ )ê 3¡3H¡|¡™¡Z·¡¢¢,¢@¢R¢ b¢ƒ¢‹¢¡¢¸¢Ó¢î¢ £ £%£>£Z£t£-‹£¹£ Уñ£¤ ¤¤1¤ 8¤Y¤y¤A‘¤Ó¤ë¤¥’¥®¥Õ·¥ ¦ ™¦¥¦ «¦¸¦ɦϦئ ߦ ì¦ ù¦ §§§ ,§9§O§i§#n§’§¡§³§ȧ'è§[¨Xl¨QŨV©Tn©UéTª nªxª ‰ª“ª ¯ª¹ª ¿ª ͪ Ûªèª+îª+«+F«¨r« ¬ %¬ 1¬=¬O¬a¬ p¬ ~¬Ь ¬ ¶¬¬ʬÙ¬ë¬þ¬­%­?­H­P­f­|­“­¤­ ´­Á­ Ô­à­ú­®0®7®S®p®Š®¦®¯®À®Ò®ä®¯=¯E¯KK¯—¯¶¯Ìί…›°!±>±M±\±m±/‚±>²±ñ±²$² =²G² _²m²?в ʲNÔ² #³0³N³l³s³³©³ Á³˳ ѳ Û³æ³ù³ ´!´ 7´A´]´ z´ˆ´ž´¥´¬´³´É´ è´ ô´µ µµ "µ/µ >µJµgSµ»µwεF·`·Zg·· à· ê· ô·þ· ¸ ¸*¸J¸Y¸ s¸~¸¸"•¸¸¸Iʸ¹ %¹1¹ A¹ M¹W¹`¹Ax¹º¹ ùѹã¹ö¹ º&ºDºÒdº{7»!³»Õ»ô» ¼)¼D¼`¼b{¼Þ¼ ô¼½ ½ ½"½1½ :½F½Z½o½0„½µ½ɽÒ½æ½í½Œý½о‘¾)­¾×¾ò¾bô¿–WÀîÀ0þÀ0/Á1`Á ’ÁM³Á,Â.Â<C€Ÿ‰»ÂEÃ#WÃG{Ã=ÃÃ9ÄB;Ä<~Ä:»ÄDöÄ=;Å1yÅ4«Å:àÅDÆ=`Æ žÆ6¿Æ7öÆ7.Ç7fÇ8žÇ#×ÇûÇ È'È?È1YÈ!‹È ­È»È#ÖÈ"úÈ#É"AÉ$dÉ#‰É­É$ÉÉ#îÉ5Ê8HÊÊ@—Ê'ØÊ(Ë)Ë!CË3eË(™ËÉÂËŒÌ ’̠̯Ì(¾Ì çÌ ôÌþÌÍ7ÍSÍpÍŒÍªÍ ¾ÍËÍ çÍöôÍÛëΕÇÏK]ЩимÐÂÐËÐÒÐ ÚÐ äÐñÐÑÑ$Ñ5ÑIÑ]Ñ%xÑžÑI¹ÑÒ,"ÒwOÒÇÒ\ÛÒ:8ÓsÓˆÓÓ¤Ó(ÄÓíÓ/ÿÓ/Ô/AÔqÔ€Ô—Ô(®Ô×Ô#ôÔ Õ&Õ -Õ ;Õ#\Õ€Õ”Õ5¬ÕâÕmùÕgÖ/ƒÖ³Ö(ËÖ-ôÖ*"×M×m×(Š×(³×Ü×â×ó×FØQKØQØïØ!Ù "Ù,Ù>ÙQÙ dÙoÙ sÙ~Ù †Ù ‘Ù›Ù«Ù8Í{­ ~8ÎAò2àNì\ÿ›ª ˆûZáC¬ú,•åZíbz]zGeœùs´"Êìá« A2f¿… È ]õ—hLkà‰GÉkµÅÆ;;$ŠÕ¸dO{|7iYÄ-É€y„’ø»d ö$Ý@¶–Œ¢Þ4‘¦S=:ÎIcÃL}iruß,gÏ.ØYô`SâLTëB÷/5ÿFVŽ#”=Ob¾)í^О&1clF&D"MTãMò˜Pæ+C ä§7UQ"<oÓÈCʺ±[ýûY„k‚1¤ŸvM±%>BÀ0NO~\è9|V'!¤ñޏKc€a'-Ö–R§/4 ,ç½sÞn#¶`Ájr.mœ°}N¼j@[f†?RJÐe¼n“thjdFâ*¯+²À™Pç^Ë%õÙÍ‚&ïQÜE@r'6¾_5`©• WãÖË› *DUå®sžšØö Âey/…>Çl3+ðĦš2ßxT*D³×9Qq\Ú)ÝÃ¥ý3m£´µañú>é¡·E‘Ûæ†£:ºóþ½Ï‹(ðø m5WÓu¡o  X3<qÑè’JÑ ÂHÛ²6üRpZqÁ#ÜX0!©W“ VbAIfw?˜¿Jª%°™Ÿ(ƹÒë0¹8=]g¢¯E³­ÔUþÌa6ÌÒwŒÚ¥Bï÷g:¨G¨ô(ƒ‡éêXv 9Ii 1^.Šp®nx‡o_[$”ü?HPˆlÅó!î;«îpK»ê¬ÇÙ-h_Ô—S7ä‰t4KÕ·H)׋ù< (1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF ModeAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAnalog GainAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue intensityBlue offsetBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton stateButton test optionsCDCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrationCalibration by backendCalibration modeChange Document.Change documentChannelCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.CustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.DiamondDisable backtrackingDisable pre focusDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDouble Optical ResolutionDownload pattern ADownload pattern BDuplexDuration of read-delayEjectEject document after scanningEject the sheet in the ADFEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.EnhancementExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Exposure timeExtra FastFastFast gray modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFilm-stripFineFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGrain sizeGrayGray gainGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen intensityGreen offsetGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.Ignore calibrationImage EnhancementImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp onLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual pre focusMatrix multiplication of RGBMaxMediaMediumMidtoneMidtone for blueMidtone for greenMidtone for redMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image.Mirror verticalMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNo CorrectionNoise reductionNoneNormalNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOptional equipmentPaper sizePhysical size of the paper in the ADFPositive FilmPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRandomizeRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed intensityRed offsetReduce the isolated dot noiseRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Return SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSaturationScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Second entrySelect bay to scanSelect minimum-brightness to get a white pointSelect smoothing filter.Select the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Set default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set exposure-timeSet lamp densitySet sharpening value.Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSlideSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsStart calibration process.Status Code SimulationString test optionsSwap black and whiteText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampUTA onUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update optionsUpdate options.Use 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Warm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWhite levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomflatbed scannersheetfed scannerProject-Id-Version: sane-backends 1.0.11 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-12-17 23:00+0100 Last-Translator: Harri Järvi Language-Team: Debian l10n Finnish Language: fi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (1/1) Painike(1/1) Painike. Tulostaa tekstiä.(1/3) Murtoluku(1/3) Murtoluku kokeiluasetus ilman yksikköä ja rajoituksia.(1/3) Merkkijono(1/3) Merkkijono ilman rajoituksia.(1/6) Boolen pehmovalinta pehmotunnistus(1/6) Boolen kokeiluasetus, jolla on pehmovalinta- ja pehmotunnistus- ominaisuuksia. Se on vain tavallinen boolen asetus.(1/6) Kokonaisluku(1/6) Kokonaisluku ilman yksikköä ja rajoituksia.(2/3) Murtoluku aluerajoituksella(2/3) Murtoluku kokeiluasetus mikrosekunti-yksiköllä ja aluerajoituksella. Minimi on -42,17, maksimi 32767,9999, ja askel on 2,0.(2/3) Merkkijono sanalistalla(2/3) Merkkijono sanalistarajoituksella(2/6) Boolen kovavalinta pehmotunnistus(3/6) Boolen kokeiluasetus, jolla on kovavalinta ja pehmotunnistus. Tämä tarkoittaa, että käyttöliittymä ei voi itse muttaa asetusta, mutta käyttäjä voi (esim. painamalla painiketta laitteessa).(2/6) Kokonaisluku aluerajoituksella(2/6) Koknaisluku pikseli-yksiköllä ja aluerajoituksella. Minimi on 4, maksimi 192, ja askel on 2.(3/3) Murtoluku rajoituksella ja sanalistalla(3/3) Murtolukukokeiluasetus ilman yksikköä, rajoituksella ja sanalistalla.(3/3) Merkkijono pitkällä sanalistalla(3/3) Merkkijono sanalistalla. Sanalista sisältää enemmän sanoja.(3/6) Boolen kovavalinta(3/6) Boolen kokeiluasetus, jolla on kovavalinta. Tämä tarkoittaa, että käyttöliittymä ei voi itse muuttaa asetusta, mutta käyttäjä voi (esim. painamalla painiketta laitteessa), eikä käyttöliittymä voi lukea asetusta.(3/6) Kokonaisluku sanalistalla(3/6) Kokonaisluku bitti-yksiköllä ja sanalistarajoituksella.(4/6) Boolen pehmotunnistus(4/6) Boolen kokeiluasetus, jolla on pehmotunnistus. Se tarkoittaa, että asetus voidaan vain lukea.(4/6) Kokonaislukutaulukko(4/6) Kokonaisluku mm-yksiköllä käyttäen taulukkoa ilman rajoituksia.(5/6) Boolen pehmovalinta ja pehmotunnistus emuloita(5/6) Boolen kokeiluasetus, jolla on pehmovalinta, pehmotunnistus ja emulointi.(5/6) Kokonaislukutaulukko aluerajoituksella(5/6) Kokonaisluku dpi-yksiköllä ja taulukolla aluerajoituksella. Minimi on 4, maksimi 192, ja askel on 2.(6/6) Boolen pehmovalinta pehmotunnistus auto(6/6) Boolen kokeiluasetus, jolla on pehmovalinta, pehmotunnitus ja automaattiominaisuudet. Ajuri voi säätää tätä asetusta automaattisesti.(6/6) Kokonaislukutaulukko sanalistalla(6/6) Kokonaisluku prosenttiyksiköllä ja taulukolla sanalistarajoituksella.2 pikseliä2x2 oma2x2 normaali3x3 oma3x3 normaali4 pikseliä4x4 raaka4x4 oma4x4 hieno4x4 normaali5x5 raaka5x5 oma5x5 hieno6x4 (tuumaa)6x6 oma6x6 normaali8-bittinen tulos8 pikseliä8.5x11 (tuumaa)8x10 (tuumaa)8x8 Bayer8x8 raaka lihavointi8x8 hieno lihavointi8x8 pystyviiva8x8 raaka8x8 oma8x8 hieno8x8 normaali8x8 tosi hienoPidempi valotusaika antaa kuvanlukijan kerätä enemmän valoa. Ehdotetut arvot ovat 175% painotuotteille, 150% normaaleille dioille ja "Negatiivi" negatiivifilmeille. Tummille (alivalottuneille) kuville, voit kasvattaa tätä arvoa.A4A5 vaakaA5 pystyADFSyötttapaLisää sinistä vihreän määrän perusteellaLisää sinistä punaisen määrän perusteellaLisää vihreää sinisen määrän perusteellaLisää vihreää punaisen määrän perusteellaLisää punaista sinisen määrän perusteellaLisää punaista vihreän määrän perusteellaLisäasetuksetKuvanlukukomennon lähettämisen jälkeen, odota kunnes kuvanlukijan painiketta todella painetaan, ennen kuvanluvun aloittamista.Kaikki sivutAnaloginen vahvistusAnaloginen gamma (sininen)Analoginen gammakorjausAnaloginen gamma (vihreä)Analoginen gamma (punainen)Analoginen gamma-korjausAnaloginen gamma-korjaus siniselleAnaloginen gamma-korjaus vihreälleAnalgoinen gamma-korjaus punaiselleAutomaattinenAutomaatinen kynnysAutomaattinen ositteluAutomaattinen poistoAutomaattinenAutomaattinen syöttöAutomaattinen kynnyksen asetusAutomaattinen osiointiAutomaattinen kynnysAutomaattinen lämmitysAsettaa automaattisesti kirkkauden, kontrastin, valkotasapainon, gamman, kohinan poiston ja korostuksenTasapainokerroin siniselle. 100% tarkoittaa: ei korjausta.Tasapainokerroin vihreälle. 100% tarkoittaa: ei korjausta.Tasapainokerroin punaiselle. 100% tarkoittaa: ei korjausta.TasoBayerBayer-rasteri 16Bayer-rasteri 64Kaksitasoinen mustavalko (viivapiirros)Sido RGBSido X- ja Y-tarkkuusSido analoginen gammaSido gammaBittisyvyysMustatasoSininenSinitasapainoSinisen kirkkausSinisen vahvistusSinisen voimakkuusSinisen siirtymäBoolen kokeiluasetuksetOikea alakulma xKuva-alueen oikean alakulman x-koordinaatti.Oikea alakulma yKuva-alueen oikean alakulman y-koordinaatti.KirkkausPainikkeen tilaPainikekokeiluasetuksetCDLoisteputkiLoisteputkinäytötKal. valotusaikaKal. valotusaika siniselleKal. valotusaika vihreälleKal. valotusaika punaiselleKal. valomääräKalibroiKalibroi kuvanlukijaKalibroi ennen seuraavaa kuvanlukuaTarkentaa linssin tarkennuksen kohteeseenKalibrointiAjuri kalibroiKalibrointitilaVaihda kohde.Vaihda kohdeKanavaRaakaRaakakalibrointiRaakakalibrointi vain ensimmäisellä kuvanluvullaRaakakalibrointi tehdään vain ensimmäisellä kuvanluvulla. Toimii useimpien kuvanlukijoiden kanssa ja voi säästää aikaa. Jos kuvien kirkkaus on eri joka kerralla, poista tämä asetus. Tämä asetus on testausta varten.VäriVäri 36VärirasteriVäriviivapiirrosVärimatriisiVäri RAWVäri RGBVäri RGB TEKSTIVäritasapainoVärikanavien vahvistusVärikanavien siirtymäVärikorjausVärikorjauskertoimetVärikuvioVäri 24Väri 36Väri 48Väririvejä / lukuEhdollinenKontrastiSinisen kontrastiVihreän kontrastiPunaisen kontrastiMäärää sinisen määränMäärää vihreän määränMäärää punaisen määränMäärää kuvan "sävyä" (sinistasoa).Asettaa luettavan kuvan kirkkaudenAsettaa sinisen kanavan kirkkauden.Asettaa vihreän kanavan kirkkauden.Asettaa punaisen kanavan kirkkauden.Asettaa luettavan kuvan kontrastin.Asettaa sinisen kanavan kontrastin.Asettaa vihreän kanavan kontrastin.Asettaa punaisen kanavan kontrastin.Määrää käytetäänkö jäljitystä.OmaOma värimatriisi harmaasävy lukua varten.Oma värimatriisi.Debug-asetuksetOletusOletuksetMäärää kalibraatiotavanAseta valotusaika sinisen kalibroinnilleAseta valotusaika siniselle kuvanluvulleAseta valotusaika kalibroinnilleAseta valotusaika vihreän kalibroinnilleAseta valotusaika vihreälle kuvanluvulleAseta valotusaika punaisen kalibroinnilleAseta valotusaika punaiselle kuvanluvulleAseta valotusaika kuvanluvulleMääritä valomäärä kalibrointia vartenMääritä valomäärä kuvanlukua vartenAsettaa rasterikuvion koon rasterikuvia luettaessa.Määrää kuvanlukijan käyttämän zoom-kertoimenViivästää tiedon siirtoa.Määrää kuvanlukunopeuden.Päättää käytetäänkö sisäänrakennettua vai käyttäjän asettamaa gammataulukkoa.TimanttiPoista peruutus.Poista esitarkennusHajapisteet 16x16Hajapisteet 8x8Näyttää lyhyen tarkkuuslistanRasteriRasteri A (4x4 Bayer)Rasteri B (4x4 Spiral)Rasteri C (4x4 Net Screen)Rasteri D (8x4 Net Screen)Rasteroitu mustavalkoRasteri 1Rasteri 2Lue harmaasävykuva värikuvan sijaanTee tarkka valkokalibrointiEi kalibroida tarkennustaEi pakoteta paluuarvoaEi pakoteta ajuria palauttamaan statuskoodia.Asiakirjan syöttäjäKaksinkertainen optinen tarkkuusLadattu kuvio ALadattu kuvio BKaksipuolinenLukuviiveen kestoPoistaPoista kohde kuvanluvun jälkeenPoista kohde syöttölaitteestaKaksipuolinen kuvanlukuAseta automaattinen kynnysarvon päättely viivapiirrosta varten.Valotusajan asettaminenValomäärän valintaKokeiluasetukset päälleAsettaa päälle useita kokeiluasetuksia. Asetuksilla voidaan tarkistaa käyttöliittymän kyky näyttää ja muokata kaikenlaisia SANE-asetuksia.ParannusKäännä ylemmän ja alemman tavun järjestys 16-bittisessä tilassa. Tällä toiminnolla voidaan kokeilla 16-bittisiä tiloja käyttöliittymissä, esim. käyttääkö käyttöliittymä oikeaa tavujärjestystä.ValotusaikaHyvin nopeaNopeaNopea harmaaNopea esikatseluNopeaNopeampiNopeinSyöttötapaTiedostonimiFilmin tyyppiFilmiliuskaHienoFirmware-tasapainoEnsimmäinenKorjaa tarkennuspisteMurtolukukokeiluasetuksetTasoKohdistus 2,5 mm lasin yläpuolellaKohdistuspisteKohdistus lasissaKäytä jäljitystäPakota yksiväriset esikatselutPakottaa kalibroinnin ennen kuvanlukua.Pakota ajuri palauttamaan paluuarvo SANE_STATUS_ACCESS_DENIED, kun sane_read() on kutsuttu.Pakota ajuri palauttamaan paluuarvo SANE_STATUS_COVER_OPEN, kun sane_read() on kutsuttu.Pakota ajuri palauttamaan paluuarvo SANE_STATUS_EOF, kun sane_read() on kutsuttu.Pakota ajuri palauttamaan paluuarvo SANE_STATUS_IO_ERROR, kun sane_read() on kutsuttu.Pakota ajuri palauttamaan paluuarvo SANE_STATUS_JAMMED, kun sane_read() on kutsuttu.Pakota ajuri palauttamaan paluuarvo SANE_STATUS_NO_DOCS, kun sane_read() on kutsuttu.Pakota ajuri palauttamaan paluuarvo SANE_STATUS_NO_MEM, kun sane_read() on kutsuttu.PaperiltaOdota painikettaKoko alueEpämääräiset parametritVahvistusGammaGamma-korjausGammataulukotGammakorjausGammaGamma-korjaus taulukko siniselle kaistalle.Gamma-korjaustaulukko vihreälle kaistalle.Gamma-korjaustaulukko punaiselle kaistalle.Gamma-korjaustaulukko. Väritilassa tämä asetus vaikuttaa yhtä paljon punaiseen, vihreään ja siniseen kanavaan yhtä aikaa. Se on siis intensiteettigamma-taulukko.GeometriaHiukkaskokoHarmaasävyHarmaan vahvistusHarmaan siirtymäHarmaasävy 16Harmaasävy 8HarmaannutaHarmaasävy 4 bittiäHarmaasävy 8 bittiäHarmaasävyVihreäVihertasapainoVihreän kirkkausVihreän vahvistusVihreän voimakkuusVihreän siirtymäHarmaasävyrivejä / lukuRuudukkoRasteriRasteri A (Hard Tone)Rasteri B (Soft Tone)Rasteri C (Net Screen)Taseteripiste 32Rasteripiste 64RasterikuvioRasterikuvion kokoRasterointiRasterointi ei ole tuettuKäsikuvanlukijasimulaatioKäsikuvanlukijasimulaatioKorkeaSuuri kontrastinen tulostusKorkeatarkkuuksinen tulostusParas laatu, mutta hitainNopea, mutta huonolaatuinenKorostusSinisen korostusVihreän korostusPunaisen korostusPidikkeen tarkennuspiste 0mmVaakaKuinka kauan odotetaan jokaisen lähetetyn puskurin jälkeen.SävyJos valittu, ajuri yrittää automaattisesti selvittää parhaan kynnyksen.Ajuri tekee värikalibroinnin.Kuvanlukija ei peruuta.Jos asetus on päällä, kalibroinnissa suoritetaan vain sävykorjaus. Oletusasetukset vahvistukselle, siirtymälle ja valotusajalle, joko asetustiedostosta tai ohjelman sisäänrakennetuista asetuksista.Jos asetus on päällä, laite kalibroidaan ennen seuraavaa kuvanlukua. Muuten kalibrointi suoritetaan vain ensimmäisellä kerralla.Jätä kalibrointi huomiottaKuvan parannusKuvan korostusKuvan voimakkuusMatriisikirjoittimetRGB-tilassa käytä samoja arvoja joka värilleKasvattaa tai vähentää analogista vahvistusta CCD-kennossa.MustesuihkutulostimetKokonaislukukokeiluasetuksetKäännä tavujärjestysValo poisValo pois lopetettaessaValo päälleLinssin tarkennus kohteeseenKatsotaanko osaako käyttöliittymä käsitellä tämän oikeinUS-LetterRajoittaa tiedon määrää, joka voidaan lukea yhdellä sane_read()-kutsulla.ViivapiirrosLataa kuva harmaasävykuvana.Kadonneita pikseleitä / riviMatalaMatalatarkkuuksinen tulostusManuaalinen esitarkennusMatriisikerroin RGB:lleKoko alueMediaKeskitasoKeskisävySinisen keskisävyVihreän keskisävyPunaisen keskisävyPeilaa vaakasuunnassaPeilikuvaPeilaa kuvan vaakasuunnassaPeilaa kuvan pystysuunnassa.Peilaa kuvan.Peilaa pystysuunnassaTila 1Tila 2Tila 3Yksivärinen matriisiMonitaso RGB-väri (yksivaihe)HarmaasävyNTSC-harmaaNTSC-RGBNegatiiviNegatiivifilmiEi korjaustaKohinan poistoEi mikäänNormaaliBittien määrä näytettä kohden. Tyypillisiä arvoja ovat 1 viivapiirrokselle ja 8 monibittikuville.Asetusten määräSCSI-pyynnöllä luettavien rivien määrä. Säätämällä tätä asetusta, voidaan vaikuttaa tiedon lukemisen nopeuteen kuvanlukijalta. Jos tämä asetetaan liian matalaksi, kuvanlukija voi joutua välillä pysähtymään kesken luvun. Jos se asetetaan liian suureksi, X-pohjaiset käyttöliittymät voivat lakata vastaamasta X-tapahtumiin ja järjestelmä saattaa kaatua.Luettavan kehyksen numeroPoissaTarjoaa select file descriptorin, jolla voidaan tarkistaa palauttaisiko sane_read() dataa.Tarjoa select file descriptorSiirtymäPäälläYksi sivuVain sävykorjausLisävarustePaperin kokoPaperin koko syöttölaitteessaPositiivifilmiEsimääritetyt asetuksetEsikatseluEsikatselutilaTulostaTulosta lista kaikista asetuksistaTulostusasetuksetTarjoaa vakioalueet valokuville ja tulostetuille sivuille ja vastaaville.LaatukalibrointiParas laatuNopea formaattiSatunnaistaLukuviiveLukurajaVain-luku kokeiluasetusAsetus, joka määrää kuinka monta asetusta tietty laite tukee.PunainenPunatasapainoPunaisen kirkkausPunaisen vahvistusPunaisen voimakkuusPunaisen siirtymäVähentää yksittäistä pistekohinaaPyydä laadukas esikatselukuva.Pyytää, että kaikki esikatselut tehdään yksivärisenä. Kolmivaihekuvanlukijalla tämä laskee vaiheiden määrän yhteen. Yksivaihekuvanlukijalla, se vähentää muistinkulutusta ja esikatselun lukuaikaa.Kaikki esikatselut luetaan nopeimmalla tavalla (huonoimmalla laadulla). Tämä voi olla väritön matalatarkkuuksinen tila.Palauta SANE_STATUS_ACCESS_DENIEDPalauta SANE_STATUS_COVER_OPENPalauta SANE_STATUS_EOFPalauta SANE_STATUS_IO_ERRORPalauta SANE_STATUS_JAMMEDPalauta SANE_STATUS_NO_DOCSPalauta SANE_STATUS_NO_MEMPalauttaa epämääräisiä rivejä ja tavuja, kun sane_parameters() kutsutaan ennen sane_start().sane_read() paluuarvoKylläisyysGammaGamma sininenGamma vihreäGamma punainenLukutapaValotusaikaSinisen valotusaikaVihreän valotusaikaPunaisen valotusaikaLue nopeassa harmaassa tilassa (huonompi laatu).Lampun valomääräLukutapaKuvanluvun tarkkuusLähdeKuvanlukunopeusLukee koko alueen, mukaan lukien kalibrointinauha. Ole varovainen. Älä valitse täyttä korkeutta. Tämä asetus on vain testausta varten.ToinenValitsee kuvanluvun tasoltaValitse valkoisen pisteen pienin kirkkausValitse pehmennyssuodatin.Valitse testikuva. Vaihtoehtoina ovat: Täysi musta: täyttää koko kuvan mustalla. Täysi valkoinen: täyttää koko kuvan valkoisella. Värikuvio: piirtää erilaisia värikuvioita tilasta riippuen. Ruudukko: piirtää mustavalkoruudukon 10 mm ruuduilla.Valitse esikatselutila. Harmaasävy antaa yleensä parhaan yhdistelmän nopeutta ja yksityiskohtiaValitse sane_read()-kutsun paluuarvo. "Oletus" on tavallinen kuvanluvun käsittely. Kaikki muut paluuarvot ovat käyttöliittymän testaamista varten.Valitse koekuvaAsettaa arvon gammakorjaukselle (sininen kanava)Asettaa arvon gammakorjaukselle (vihreä kanava)Asettaa arvon gammakorjaukselle (punainen kanava)Asettaa arvon gammakorjaukselle.Asettaa kuvien "rakeisuuden". Pienemmät arvot tuottavat terävämpiä kuvia.Valitsee syöttötavan (yksi-/kaksipuolinen)Valitsee kirkkauden.Valitsee värikaistan, "Master" tarkoittaa kaikkia värejä.Valitsee gamma-korjauskäyränValitsee gammakorjaustilan.Valitsee gamma-korjauksen esiasetettujen laitteiden listalta tai käyttäjän määrämän taulukon, joka voidaan siirtää kuvanlukijaanValitsee rasterinValitsee luettavan kehyksen numeronValitsee kuvanlukutavan (esim. viivapiirros, mustavalkoinen tai väri).Määrää kuvanlukulähteen (kuten dokumentin syöttäjän).Asettaa sinisen kirkkaustason, joka tulkitaan "mustaksi".Asettaa sinisen kirkkaustason, joka tulkitaan "täysin siniseksi".Asettaa sinisen kirkkaustason, joka tulkitaan "valkoiseksi".Asettaa vihreän kirkkaustason, joka tulkitaan "mustaksi".Asettaa vihreän kirkkaustason, joka tulkitaan "täysin vihreäksi".Asettaa vihreän kirkkaustason, joka tulkitaan "valkoiseksi".Asettaa kirkkaustason, joka tulkitaan "mustaksi".Asettaa kirkkaustason, joka tulkitaan "valkoiseksi".Asettaa punaisen kirkkaustason, joka tulkitaan "mustaksi".Asettaa punaisen kirkkaustason, joka tulkitaan "täysin punaiseksi".Asettaa punaisen kirkkaustason, joka tulkitaan "valkoiseksi".Määrää, rasteroidaanko kuva.Asettaa kirkkaustason, joka tulkitaan "50% siniseksi".Asettaa kirkkaustason, joka tulkitaan "50% vihreäksi".Asettaa kirkkaustason, joka tulkitaan "50% vihreäksi".Asettaa kirkkaustason, joka tulkitaan "50% punaiseksi".Asettaa oletusarvot parantimille (kirkkaus ja kontrasti)Aseta oletusasetukset parantimille.Aseta valotusaikaAseta lampun valomääräAseta terävöintiarvo.Aseta kehysten järjestysAsettaa kehysten järjestyksen kolmivaihetilassa.Aseta kuvanlukijan värimatriisi.Valitse mediaAsettaa UTAN päälle/poisAsettaa sinisen kanavan vahvistustaAsettaa sinisen kanavan siirtymänAsettaa harmaan kanavan vahvistustaAsettaa harmaan kanavan siirtymänAsettaa vihreän kanavan vahvistustaAsettaa vihreän kanavan siirtymänAsettaa valon päälle/poisAsettaa punaisen kanavan vahvistustaAsettaa punaisen kanavan siirtymänAsettaa väritasapainot Firmwaressa oleviin arvoihin.Valitsee värikorjaustaulukon valitulle tuloslaitteelle.Asettaa syöttötavanAsettaa kohdistuspisteen joko lasiin tai 2,5 mm sen yläpuolelleAsettaa gamma-arvon kaikille kanaville.Asettaa luettavan kuvan vaakatarkkuuden.Asettaa kuvan korostuksenAsettaa luettavan kuvan tarkkuus.Asettaa rasterikuvion koon rasterikuvia luettaessa.Asettaa luettavan kuvan pystytarkkuuden.Säädetään vahvistus ja siirtymä automaattisesti. Jos tämä asetus on poissa, voit asettaa analogia-asetukset manuaalisesti. Asetus on oletuksena päällä. Tämä asetus on vain testausta varten.VarjoSinisen varjoVihreän varjoPunaisen varjoVarjo, keskisävy, korostus, valotusaikaTerävöintiTerävyysSinisen siirtymä vihreäänSinisen siirtymä punaiseenVihreän siirtymä siniseenVihreän siirtymä punaiseenPunaisen siirtymä siniseenPunaisen siirtymä virheäänLyhyt tarkkuuslistaSulje lamppuSulkee kuvanlukijan lampun.YksipuolinenSimuloi käsikuvnalukijaa. Käsikuvanlukijat eivät tiedä kuvan korkeutta etukäteen. Sen sijaan, ne palauttavat korkeuden -1. Tämä asetus mahdollistaa osaako ohjelma käsitellä tätä tilannetta. Tämä asetus asettaa kuvan leveydeksi 11 cm.Simuloi käsiskanneria. Käsiskannerit eivät yleensä tiedä kuvan kokoa etukäteen. Sen sijaan, ne palauttavat kuvan korkeudeksi -1. Tällä asetuksella voidaan kokeilla, selviääkö käyttöliittymä tästä oikein.Simuloi kolmivaiheskanneria palauttamalla kolme erillistä kehystä. Huvin vuoksi se palauttaa kehykset järjestyksessä: vihreä, sininen, punainen.Simuloi kolmivaihekuvanlukijaa. Väritilassa, kolme kehystä lähetetään.Lukurajan kokoDiaHidasHitaampiHitainPehmeäPehmennysTäysi mustaTäysi valkoinenLähteen valintaErikoisasetuksetErikoisasetuksetAloita kalibrointi.PaluuarvosimulaatioMerkkijonokokeiluasetuksetVaihda musta ja valkoinen keskenäänTekstin parannusmenetelmäSuurin tiedon määrä, joka välitetään yhdellä sane_read()-kutsulla.Ladattavan kuvan tiedostonimi.Rivin lopusta puuttuvien pikselien määrä.Kylläisyystaso vaikuttaa "puhkipalamiseen" kameralla kuvattaessa. Suuremmat arvot aiheuttavat enemmän puhkipalamista.LämpökirjoittimetTämä on erittäin pitkä kolmas rivi. Ehkä käyttöliittymä keksii miten se näytetäänTämä asetus sulkee kuvanlukijan lampun kuvanluvun ajaksiKolmivaihesimulaatioKolmivaihesimulaatioKynnysKuvanlukijan valo päälle/poisAsettaa kuvanlukijan valon päälle/poisVasen yläkulma xKuva-alueen vasemman yläkulman x-koordinaatti.Vasen yläkulma yKuva-alueen vasemman yläkulman y-koordinaatti.LäpinäkyvyysLäpinäkyvyysyksikköLäpinäkyvyysyksikköSammuttaa valon ohjelmasta poistuttaessaSammuttaa kuvanlukijan valonLaittaa kuvanlukijan valon päälleUTA päälläPoistaPoista kohde.Poista media kuvanluvun jälkeenPoistaa median kuvanluvun jälkeen.Päivitä asetuksetPäivittää asetukset.Käytä 0mm pidikkeen tarkennuspisteenä 0,6mm sijaanKäytä kuvanasetteluaKäyttää sisäisesti kahdeksaa bittiä syvempää esitystä, mutta antaa tuloksen vain kahdeksanbittisenä.Käytä omaa gammataulukkoaKäytä linssiä joka tuplaa optisen tarkkuudenKäytä non-blocking IOsane_read käyttää non-blocking IO:ta.Käytä gamma-arvoja kaikille värikanaville.Käytä samoja arvoja X- ja Y-tarkkuudelleKäytä lightlid-35mm sovitintaKäyttäjän määrittelemäKäyttäjän määrittelemä (Gamma=1.0)Käyttäjän määrittelemä (Gamma=1.8)PystyOdota painikettaOdota painikettaOdottaa kuvanlukijan painikkeen painamista ennen kuvanluvun alkamista.Lämmittää kunnes lampun kirkkaus tasaantuu. Muuten lämmitetään 40 sekuntia.Lämmittää kunnes lampun kirkkaus tasaantuu. Muuten lämmitetään 60 sekuntia.Lämmitä lamppuLämmitä lamppu ennen kuvanlukuaValkotasoSinisen valkotasoVihreän valkotasoPunaisen valkotasoX-tarkkuusXPAXPA-harmaaXPA-RGBY-tarkkuusSuurennusTasokuvanlukijaarkkisyöttöinensane-backends-1.0.27/po/LINGUAS0000664000175000017500000000021012775312262012665 00000000000000# List of languages # try to keep this list ordered bg cs da de en@boldquot en@quot en_GB eo es fi fr gl hu it ja nb nl pl pt ru sv uk sane-backends-1.0.27/po/nl.gmo0000664000175000017500000031306413110600540012752 00000000000000Þ•˜Ü$#œI(b )b-6b db;pb ¬b,¹b"æbz c „c9ŽcÈc€åc#fd5Šd"ÀdÆãdªejÅe 0fBQf(”fS½fgØ(ghB hchlzhçhJ÷h+Bicni Òizói'nj™–j$0kWUk­k¾kÏkÔk Ùkækîk ók þk l ll 'l 5l @lKl Tl _l jlul ~l ‰l ”l Ÿl¬l ´l Âl ÎlØlëlül m m$m -m 8mÒFmnn%n7n:nCnUn Xn enqntnxn n Œn–nŸn°n¿n"Çn"ên$ o!2o!Tovo!–o ¸oÙo ùop1pJpbpkp|ps–p q?q5Tq Šq–q¦q¸qÐqãqôq r!-rOrortrƒr šr ¥r ³r¾rÓrérþr ss!7sYsns‚s›s<¬sGés_1t‘t”tt¯t²t»tÍt ÐtÚtßtðt=u>>u<}uºu¾uÄuÔu'äu vv-v ?v JvTv Zvfv kvxv ˆv’v­v ¼v ÊvÖvóv ww%"wHw%Ww }w ˆw”w©w²w »wÈwÜwówûwþwx xx2xNxkx†x ˜x¢x´x)Ïx%ùx y+y!Bydy{yŒyy ­y »y Åy ÑyÜyíy9ýy7zUz]z cz nz{zz¥z¬z&¿zÄæzÇ«{s|y|‰|’| ¡| ¯| ¼| Æ|Ð| ß|í| })}:} X} e}s}{}ƒ}‹} ¡}­} Â}Î}×}à}ö} ~""~E~e~‚~–~±~Æ~6Ù~.B?C‚AÆ,€@5€Av€?¸€(ø€ !!-*O z…œ(£Ì á ëõ ‚‚ #‚0‚4‚F‚N‚W‚)o‚"™‚$¼‚*á‚# ƒ(0ƒ!Yƒ{ƒ#™ƒ½ƒÚƒ úƒ„I:„,„„'±„Ù„á„ ñ„þ„*…0A…Dr… ·…Ã…Ó…6Û… †1†N†c†{†”†ª†e¼† "‡C‡U‡e‡ƒ‡ЇŸ‡µ‡χ/é‡ ˆ %ˆ%1ˆWˆ&vˆˆ´ˆ1͈'ÿˆ'‰7‰N‰ e‰†‰  ‰¬‰Á‰ ׉ø‰Š"Š5Š =ŠKŠ RŠ `ŠElŠ ²Š ¾ŠÌŠ;㊋%‹C‹^‹u‹„‹™‹ ´‹Á‹Ê‹#Ü‹?Œ-@Œ8nŒ,§Œ/ÔŒ$)!> `!£·$9Ž"^ŽŽ Ž(ºŽ+ãŽ0@T] n`y Úè û( 2O;g £ ±¿Ï Þ ë ù ‘ ‘‘ /‘:‘­R‘’ ’ %’3’0G’ x’ ƒ’’¨’¯’´’ Ã’ Ð’Ú’á’ é’ ô’ “ “ “ “*“ /“:“ K“ W“c“v“‰“ ‘“ž“¤“¼“Ë“ Ú“æ“ ” ””*”C”%T”hz”eã”^I•c¨•a –bn–aÑ–3—49—n— ‚— —š—«—±— ×Í—Ö—ó—˜ ˜˜ ˜-˜!>˜ `˜;l˜¨˜ À˜)̘*ö˜(!™›J™æ™ï™ þ™ š šš (š4š;šAšIšZškšzš €šŽš ŸšªšÆšÖš åšòš›)›.›7›N›e›}›››®› Ä› қݛô›œœ3œLœ2`œ2“œÆœÚœôœùœ&5U u’¦¸ ÒÝíIÿIžTMž[¢žEþž4DŸ’yŸ¹  QÆ €¡¢™¡<¢ O¢p¢¢¯¢µ¢Ç¢æ¢õ¢£ £4£H£7b£*š£5Å£ û£¤¤0¤ 8¤F¤W¤h¤ y¤‡¤%¡¤ǤÙ¤ø¤=ý¤;¥?L¥ Œ¥—¥´¥½¥ Î¥ï¥ ¦¦*¦ 2¦ >¦ K¦X¦ q¦ |¦†¦yŒ¦§ §0;§l§Us§ɧCʨ©©Š3©¾©Ωæ© ê©õ© ª ª$ª5ªJª^ªtª…ª ¥ª °ª »ª ƪѪîª1òª2$«W«]«d«t«|««Ÿ«+¯«Û« í«ú«¬4¬M¬k¬}¬ ¬ —¬¥¬¬¬³¬º¬&̬*ó¬ ­(­1­B­ K­Y­h­ w­…­ ˜­/¦­ Ö­ à­ î­û­® &®4®9® @® L®XY®Þ²®‘¯]£¯± ± (±2±N± R±L\±©±ƱͱбdÙ±>²^²v²޲ ¡²¯² ¸² ò ϲ ۲河 ³ "³/³N³%c³‰³ ’³ ³¯³ ɳ Ö³ã³÷³ÿ³ ´´´ 7´ME´“´ §´ ´´Á´Ñ´Õ´ å´ï´ ó´ þ´ µMµmµ qµ}µŒµ•µ ¯µ ½µ ʵÕµñµ!¶ 1¶<¶X¶5x¶=®¶?ì¶B,·Go·4··5ì·0"¸/S¸0ƒ¸;´¸*ð¸*¹AF¹Cˆ¹,̹3ù¹Ö-º|»&» ¨» ¶»Ä»Ö» ê» ¼)¼@¼\¼v¼‘¼[«¼½!½6½M½_½ d½o½ …½’½¤½·½ ȽÒ½ â½ ¾ ¾¾/¾K¾h¾'ƒ¾«¾ ½¾ ʾÔ¾ ä¾ ð¾xû¾3t¿¨¿=¾¿7ü¿4À&QÀ xÀ†À)¢À3ÌÀ Á Á Á.1Á`ÁyÁ#ŽÁg²ÂœÃ·Ã:ÏÃ; Ä9FÄ,€ÄY­Ä%Å-ÅFEÅŒÅ/¡Å*ÑÅ"üŇÆ§Æ½Æ'ÜÆ<Ç4AdžvÇ>ýÇB<È>È?¾ÈDþÈ?CÉ9ƒÉ9½É=÷É@5Ê=vÊB´Ê>÷Ê>6Ë?uË=µË<óË0Ì?Ì GÌ2R̘̅ÌDªÌDïÌ,4ÍaÍzÍŒÍ;Í7ÙÍÎ('Î?PÎÎ1¨ÎÚÎ;ùÎ5ÏHÏXÏoψϟϸÏÐÏêÏûÏÐ!)Ð>KÐ?ŠÐÊÐDàÐ%%Ñ4KÑ€Ñ#˜Ñ¼Ñ'ÖÑ)þÑ(ÒX=Ò2–ÒÌÉÒ–ÓÓ­Ó¾Ó)ÍÓ ÷Ó Ô Ô Ô2ÔFÔYÔkÔ~Ô"”Ô·Ô)ÌÔ öÔÕÕü#ÕÐ ÖpñÖKb×®×Á× Ñ×Ü× ð×üר ØØØØ $Ø.ØJØ iØwØ‰Ø™Ø µØ ÁØÍØ#ÞØÙÙ""ÙWEÙ#ÙÁÙÐÙÙÙêÙ%Ú+ÚBÚ*GÚrÚ†ÚŽÚ<£ÚàÚ ýÚ ÛÛÛ[4ÛÛG©Û'ñÛuÜ)Ü=¹ÜŒ÷Ü6„Ý»ÝSÌÝ1 Þ4RÞ7‡Þ;¿ÞûÞß 'ß1ßDAß †ß§ßˆ·ßŒ@àFÍàá+áKá Tá bá!má á!šá ¼áÉáÞáðáâ â #âDâZâoââ¨â¯â·â¾âÏâçâãã.ã=ã Mã.nããC³ã÷ã(ä17äiäA}ä¿ä.Ýä& å3å Qå^åwåå©å²å »åÉåÙå)éå æ`4æ`•æ öæçç >çJç¨bçz è>†è‹ÅèQé Wécéxéé£é)·é áéîéòéûé êêêê"ê+ê 0ê>êAê Pê^êdê {ê†êŠêê —ê ¡ê¯ê ²ê ¿êËêÛêàêæê ïê ûêëë)!ëKëhë‡ëœë¼ëÒë ãëðëì ìììì/ìOìTì[ì_ìhìqì&„ì«ì!Çìéìíìþìí,í=íDí KíYítí/“íÃíãíëíûíî î î)î·0î èï1óï %ð90ð jð*wð&¢ð‰Éð Sñ2]ññ’¬ñ#?ò6cò&šòóÁòµó|Ïó!LôFnô)µôVßô6õOõjöHŠöÓöìö n÷F|÷1Ã÷oõ÷eø‡ƒø+ ù¡7ù#ÙùVýùTúrúú•ú šú ¨ú´ú"¹ú Üú"èú û û #û1û":û]û fûrû"{ûžû §û"²û Õûáû ñû ýû ü ü!ü4üGüZü"cü†ü ü ›üì©ü–ý ™ý£ýºý ½ýÇýÞý áý ìýöýùý'þ(=þ%fþ!Œþ ®þ+¼þ)èþÿ(0ÿ"Yÿ"|ÿ+Ÿÿ)Ëÿ*õÿ* )K)uŸ¾Þ ý{9 µaÃ5%[j}—®Èá!ø! < ]i,„±Æ Þèü)E eq,ºÖ ñ4'I\b¦  - 0:Q T ^j|OOßN/~‚ˆ˜'¨ ÐÞú ,6 <H N Z {‡¥¸ÈÚ÷   ,,  Y ,g  ”  Ÿ « Á È Ï â ô    3  7 E %` %† $¬ Ñ  è ó   +& #R  v  "ž Á Ú ì  û    ( ; K ] Cn +² Þ  å  ð û   6 ; +L çx `ek{„“ ¦ ² ¼Æ Ö&â+ 5D b p}…• ²½Ñ àìõ3$P!u—±Çæü7-IDwD¼B,DCqCµAù); er1’ Ä&Ð÷?+V‚ ‹•¨ ¹ÇÐÔã÷ D#>h,§DÔ>BX<›&Ø5ÿ05$f$‹"°TÓ<(/e •Ÿ²!Ã'å* V8¡ ¶AÁ AR$f‹¦¿Û#iŸ ¯Ð×ì!#;_o6%¶.Ü &9C+}©!¸ Úû.?]/y©ÇÚí ÿ  2 6E  | ‰ › >¶  õ $ÿ $!2B!u!‰!7Ÿ! ×!ã!ê!(ü!Q%"7w"N¯":þ"99#:s#®#0Ê#1û#,-$Z$™q$, %(8%+a%%0­%Þ%(þ%'&@&I& Y&md&Ò&á&ó&='E'^'Ky'Å' Ô'â'ñ'(( ( -(;(L(_(h(Ђ(S) l)w)‡)3œ) Ð) Û)æ)þ)* ** 2*@*H*P* Y* g* t** Š*•*š*©* ¾*Ì*ä*ú* ++"+(+ C+Q+c+"v+™+©+»+Ð+ï+$,n(,k—,d-ih-gÒ-h:.g£. /+/C/ ^/k/}/ Ž/˜/®/½/Å/ä/ü/0 0 0&0"50 X0Ld0±0 Ç0-Ó0-1+/1 [1 ü12 2$2 *262J2[2c2 j2v2†2 –2¤2 ª2 ¶2 ×2ã233$363 S3t3{3„3–3 ©3´3Å3Ö3æ3 4 4"4<4R4h4!~4 4.²4.á45#5>5C5_5{5/5/½5 í5ù56'6=6 V6b6r6Tƒ6Ø6TÝ6^27X‘7<ê7°'8àØ8}¹9Š7:ÍÂ:;(¢;%Ë;&ñ;<<*/<Z<k<|<˜<§<½<<Ø<7=9M= ‡= ’= œ= ½=Ë=ç=ö=>>*>,G>t>‹>«><°>í>Bý> @? K?l?u?"•?¸? Õ?ã?û? @ @ @+@F@U@]@™c@ý@&A29AlAdsAIØAX"C {CˆC´§C\DwD“D˜D·DÓDåDùD E3EOEgE&E ¨E ³E ¾E ÉE ÔEõEdþEgcF ËF ÕFßF ñFüFG(G@=G~G”G(¦GÏGëGH#H6H JHTH[HbHiHpH-H(¯H ØHãHìHýH III+I=I OI7]I •I I¯I¿IÝIïIJJ JJ].JûŒJ ˆKÈ–K%_M…M ŽM$˜M½MÁMkÛM%GN mNyN }Nv‰N$O%O@OZO mOzOƒO ŒOšO©O*¸OãO ôOP# P/PCDP ˆP”P˜PœP µPÂPÔP óP ýP QQ"!QDQBSQ–Q«Q ¿Q&ÍQôQ&øQR.R>RMR\RIsR½R ÂRÍR ìR÷RS %S3SDS*`S*‹S ¶S,ÃS*ðS9TLUTC¢TAæTa(UEŠUEÐUFVF]VG¤VYìV:FW8WYºW\X>qX?°XÞðXƒÏY+SZ Z Z›Z¬Z$ÃZ!èZ [%[E[c[‚[k [ \$\=\Z\p\u\†\\®\Ê\æ\ ] ]-] I] S] a]*‚]*­])Ø]0^3^ O^ Z^ d^r^ {^ˆ^C_L_Sj_>¾_"ý_, ` M`[`Aw`:¹` ô`aa?0apa†a žay«b¯%cÕc9èc9"d8\d,•dbÂdJ%epeL‚eÏe9èe-"fPf¤mfg "g/Cg9sg;­g–égI€hSÊhGiIfiS°iGjBLj@jGÐjPkEik9¯kBékB,lBolA²lNôlCmLm Um@_m m¾mPÛmV,n6ƒnºnÚnònAoBHo‹o:¤oCßo&#pBJp%p@³pôp q)!q-Kq)yq-£q)Ñq-ûq)r'Br+jr&–rO½rA sOs0is*šs9Åsÿs(t$Bt3gt-›tÉt\Þt;;uÏwuGvOvbvuv3‡v»vÊvÓvïv w&wAw\www6ŽwÅw3Ùw x!x =x IxçWy”?zUÔz*{H{]{m{†{¢{¦{¬{ µ{ ¿{ Ë{ ×{$â{4|<|'U|#}| ¡|Â| Ò|à|$ò| } $}$1}]V}.´}ã} ü}~~22~e~}~1…~·~É~$Ð~Bõ~8U dn!v}˜€[3€)€¹€/9@i„ª@/‚p‚Z„‚7ß‚4ƒ6LƒBƒƒƃ܃ ñƒ ÿƒT „%b„ ˆ„°”„}E…HÃ…# †.0† _†i† €†+† ¹†+Ɔ ò†‡ ‡"‡:‡O‡4c‡˜‡³‡ˇç‡ˆ ˆ ˆˆ2ˆ$Qˆvˆ•ˆ¬ˆ½ˆ)ψ4ùˆ.‰?F‰2†‰?¹‰?ù‰9ŠOUŠ"¥Š5ÈŠ0þŠ$/‹T‹'p‹'˜‹'À‹ è‹ ò‹ ü‹ Œ'Œ9DŒ0~Œw¯Œw' Ÿ#­#Ñ õŽÃŽ‘ÜŽ]n¡Ìn r|¢·+Ë ÷‘ ‘‘ ‘ %‘/‘3‘<‘E‘ K‘W‘[‘q‘†‘"Œ‘¯‘·‘»‘‘ Ö‘ã‘ô‘ ÷‘’’*’0’6’ ?’ K’!W’y’4~’(³’Ü’ó’"“+“D“ T“^“w“}“…“ Š“”“%©“ϓԓܓ à“ î“ ü“- ”'8”*`”‹””§”$»”à”ð” ö”• •&*•FQ•4˜•Í•Ö•ì• – – !–-–ñq¾Äáôð‚76øýGF+ p“£fe'ݰûgœC|2aÀ Fc¨ÆÎ1ƒ@?â—í·,`CX4O~IGj¦0r5úµî¾)ƒ×El[roxÎb¯6**͇€PÜ^ ð|¿Q}ÐDïÇí³“`:¤Eì5MM Óݬ…4ÝkW pZà0ÈÕ³[L’½S±ô‰~v€„Øânñ5²r*ÇïmzŒq7DY\:rckÞ TR^[ú,~”SÙžI¾ ,áë^¹' œþÓ'²_N­s|ýÛ /ßcORzb…K¥)&¶Æ Ÿ…¿=uä °ÓÉ_ 6DDÙ¹]’é>›`²aiJu–› ™‡q —ø±ÁàÏ„éª#¥–æ¡¢£„ºÍ®ò37äèÁc2åŒwT¦eætA^¯Æx]üsnØmàÆíH=×ãOųԟÖÞâäþ#2<ÒawÍ»mλÈÊ>Wÿ›h°©* Cÿ»áˆ}âÒbûw—5€¨·T7ƒ ¤pfF µc’ËGÞv.VAŠ.%}Êʺm\?xõº¢ëN’ø÷ ‰yBƒNb0´KÉe½q)F˜Þë_0&¤“¸ˆö¼1‘?<¥Hs‡BG/C< fl-%ò\…MŒÌJ¬S?{¥I`ï†ÏU_h>l¾#\.“O 訂9¶¸ÑÜEž‚"V=ytï@J]œ%Q&£‰N3!lÔjšçÿîžìÑ”Qu˜´!xž-zÕ{À$¶ |ŠÌÁi÷:yv˜ädÔ„~'ÂîS"¨f À³²;˜ìHgK|€C;°ùŠ&þ6sróÖÜ­sùdûh·šU§jç.·‹q+•ZÑ!–($¢åÚ.X® 5ðóW1/ù¶ÊûjAkP‘n`ñ‚ÓüŠÅôiŒaÏîýZ[é o¹öHBULxzW8¯y3åÛ¸ó´_O”V•<Ðvo µ(u9Ž„£b+•JÕ;á†Ù#w»†}›U!½0ؽKÄÕ1€¦T ,8LMPSVA¢ËãÇZQ d‘”—ñéÔ9Y{M’¼È–!ˆ>Ñú[†ÖÝÏÃko–«© RGç•e§n3®Ŏ“(ÚêWa‹2ÃdT…‘¡eùå*]P 7u¤Üf@t¼%ªêgõçö©ü;ÍHß;‚ËÐYœ?d}ƒßÿp$¯3p$ìRyÅ­ŽŽ2‡‡¡%ð{\Ÿ8‹ÚèêYRk-‘Ç Ã8ë<:4ê(šõÉ­«Û æ$XY-¹—iòºJ߬ÒF‰^×g/o=Ù‰ò9Ú©¼Z1«ÉÖ>´8ü#”ª†PãàtEúXE"í±i§I¸ª™nãŒËÁŽˆN]LÀŠ Ã˜Dm‹ýÎ ±÷®ÌÄ+Ì¿«¦vØ@)Ûµw•ÂIõšQŸg׋"(j™óþlö§~™øÈBh)B69¡,AL=&Uˆ{'KÄ"Ð/è4V h:÷4+æ@tz¿¬XÒ-Âô(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm16 bits gray2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel48 bits color4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A3A3 paperA3 paper detectedA4A4 paperA4 paper detectedA5A5 landscapeA5 portraitA6ADFADF BackADF DuplexADF FrontADF ModeADF Waiting TimeADF cover openADF jamAccess to resource has been deniedAction following double feed errorAddition of space in bottom positionAddition of space in top positionAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdjust blue/red offsetAdjust front/back offsetAdjust green/red offsetAdvancedAdvanced OptionsAdvanced paper protectionAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAllows one to test device behaviour with other supported modelsAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAuto length detectionAuto or manual focusAuto width detectionAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic threshold modeAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisB4B4 paperB4 paper detectedB5B5 paperB5 paper detectedB6BP filterBackBackground colorBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuffer modeBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration cache expiration timeCalibration data cacheCalibration fileCalibration modeCalibration nowCancel buttonCard BackCard DuplexCard FrontChange Document.Change documentChange endorser counter value by this much for each page.Changes intensity of midtonesChannelCheckChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.Collect a few mm of background on top side of scan, before paper enters ADF, and increase maximum scan area beyond paper size, to allow collection on remaining sides. May conflict with bgcolor optionColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor filterColor patternColor24Color36Color48Colour lines per readCompressionCompression argumentConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControl pattern of halftone filterControl type of halftone filterControl white level followerControls blue levelControls for endorser unitControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCrop actual image areaCustomCustom color matrix for grayscale scans.Custom color matrix.DF actionDF lengthDF length differenceDF recovery modeDF skewDF thicknessDTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.DensityDensity controlDensity dialDetect stapled documentDetermines maximum endorser counter value.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDifference in page length to trigger double feed errorDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart.Disable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Do not stop after double feed detectionDocument FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDouble feedDouble feed detectedDouble feed detectionDouble feed detector sensitivityDouble letter 11x17 inDownload pattern ADownload pattern BDropoutDropout colorDuplexDuplex offsetDuplex scanDuplex scan provide a scan of the front and back side of the documentDuplex sideDuplex switchDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmphasisEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable automatic separation of image and textEnable compressed data. May crash your front-end programEnable double feed error due to paper lengthEnable double feed error due to paper thicknessEnable double feed error due to skewEnable endorser unitEnable selection of exposure-timeEnable selection of lamp densityEnable smoothing for improved OCREnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/Disable double feed detectionEnable/Disable length control modeEnable/Disable long paper modeEnable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEndorserEndorser OptionsEndorser YEndorser alphanumeric print format. %05ud or %08ud at the end will be replaced by counter value.Endorser bitsEndorser directionEndorser fontEndorser print offset from top of paper.Endorser printing direction.Endorser printing font.Endorser printing side, requires hardware support to changeEndorser sideEndorser stepEndorser stringEndorser valueEnhance BlueEnhance GreenEnhance RedEnhanced modeEnhancementError DiffusionError codeError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra buttonExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFit to pageFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassFocus pointFocus point for scanning.Focus-modeFocus-pointForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.FrameFrame number of media holder that should be scanned.Frame to be scannedFrom paperFrom scannerFrom white stickFrontFront button waitFull scanFunctionFunction character on screenFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma curveGamma curve, from light to dark, but upper two may not workGamma function exponentGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftone typeHalftoningHalftoning UnsupportedHalt on CancelHand-Scanner SimulationHand-scanner simulationHardware deskew and cropHardware error codeHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHigh sensivityHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationIgnore center double feed sensorIgnore left double feed sensorIgnore right double feed sensorImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersImprinter ink levelImprinter ink running lowImproves quality of high resolution ball-point pen textIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInitial endorser counter value.Ink lowInk remainingInk-jet printersInt test optionsInvalid argumentInverse ImageInverse image in B/W modeInverse image in B/W or halftone modeInvert endiannessIt is right and left reversingJPEGJPEG Image Compression with Q parameter, '0' - no compressionJPEG compressionJPEG compression (yours application must be able to uncompress)Lamp colorLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off during scanLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLandscapeLegalLength Control Mode is a mode that the scanner reads up to the shorter length of actual paper or logical document length.Length control modeLens calibration in doc positionLet's see whether frontends can treat this rightLetterLevel of JPEG compression. 1 is small file, 7 is large file. 0 (default) is same as 4Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option 'side' can be used to determine correct image. This option should only be used with custom front-end software.Limit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Long Paper Mode is a mode that the scanner reads the image after it divides long paper by the length which is set in Document Size option.Long paper modeLoss of pixels per lineLowLow MemoryLow density printingLow sensivityManual feedManual feed modeManual feed selectedManual feed timeoutManual focus positionManual pre focusManually switching the lamp(s).Matrix 2x2Matrix 3x3Matrix 4x4Matrix 5x5Matrix multiplication of RGBMaxMaximum diameter of lone dots to remove from scanMaximum diameter of lone dots to remove from scan.MediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image (left/right flip)Mirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMirroringMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative colorNegative filmNegative film typeNegative grayNegative to smooth or positive to sharpen imageNegativesNo CorrectionNo detectionNo transparency correctionNoise reductionNoise removalNoneNormalNormal modeNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOMR or DFOMR or double feed detectedOffOff timerOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOne-pass scanners use only one color during gray or binary scanning, useful for colored paper or inkOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryOverscanPDF buttonPage heightPage loadedPage widthPaper is pulled partly into adfPaper protectionPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPower savingPredefined settingsPrepickPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorRIFROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflect output image horizontallyReflectiveRemove 2 pixel square noiseRequest a preview-quality scan.Request backend to remove border from pages digitallyRequest driver to detect and correct 90 degree image rotationRequest driver to discard pages with low numbers of dark pixelsRequest driver to discard pages with low percentage of dark pixelsRequest driver to halt the paper feed instead of eject during a cancel.Request driver to remove border from pages digitallyRequest driver to remove border from pages digitally.Request driver to rotate pages by a fixed amountRequest driver to rotate skewed pages digitallyRequest driver to rotate skewed pages digitally.Request scanner to detect jams in the ADF caused by staplesRequest scanner to grab next page from ADFRequest scanner to predict jams in the ADFRequest scanner to predict jams in the ADF using improved sensorsRequest scanner to read pages quickly from ADF into internal memoryRequest scanner to reverse feed on paper jamRequest scanner to rotate and crop pages digitally.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Requires black background for scanningReset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readReverse image formatRotate image clockwiseSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner automatically detect image area and crop itScanner cover is openScanner detects paper lower edge. May confuse some frontends.Scanner detects paper sides. May reduce scanning speed.Scanner in power saving modeScanner mechanism locked for transportScanner modelScanner sensors and buttonsScanner shrinks image to fit scanned pageScanner will be stop when a paper have been skewedSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSeparationSet SDTC variance rate (sensitivity), 0 equals 127Set chroma of blueSet chroma of redSet color of background for scans. May conflict with overscan optionSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet paper position : true for landscape, false for portraitSet pixels equal to threshold to white instead of blackSet sharpening value.Set the double feed detector sensitivitySet the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the automatic threshold modeSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the lamp color (color dropout)Sets the manual feed modeSets the manual feed timeout in secondsSets the resolution of the scanned image.Sets the scan sourceSets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkew adjustmentSkew angleSkip warmup processSleep timerSlideSlidesSlowSlowerSlowestSmoothSmoothingSoftware automatic croppingSoftware blank skip percentageSoftware cropSoftware derotateSoftware deskewSoftware despeckle diameterSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Specify the calibration file to useSpeedup sensorStandardStaple detectionStart calibration process.Start calibration using special sheetStatus Code SimulationStopStop scanner when a paper have been skewedString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesTPU8x10Target operation typeTells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The lamp will be turned off during scan. The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold curve, from light to dark, but upper two may not be linearThreshold value for lineart modeThreshold whiteTime (in minutes) before a cached calibration expires. A value of 0 means cache is not used. A negative value means cache never expires.Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off.Time in minutes until the internal power supply switches to sleep modeToggle lamp of flatbedToggles the lamp of the flatbedTop edgeTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.Type of original to scanUTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse manual or automatic selection of focus point.Use non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVarianceVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level followerWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomadfbayer_16bayer_64bluebusiness_cardbwchroma of bluechroma of redcolorcommand sequence errorcontinuouscrtdarkdefaultdiffusionerr_diffusionfbfilm scannerfit-to-pageflatbed scannergraygreenhalftonehalftone_32halftone_64hardware check errorhighinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorjpeg compressionlamp failurelamp not stabilizedlightlinierlowmediummedium not presentno additional sense informationnonenormaloffoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetredreselect failurerounded parameterscan head positioning errorsheetfed scannersinglesmoothtimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNuser_defwait_docwait_doc_hopper_upwait_keywebcamProject-Id-Version: sane-backends.nl Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2017-05-19 17:02+0100 Last-Translator: Martin Kho Language-Team: English Language: nl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: Lokalize 2.0 Plural-Forms: nplurals=2; plural=(n != 1); (1/1) Knop(1/1) Knoppen-testoptie. Levert enige tekst op...(1/3) Vast(1/3) Vaste testoptie zonder eenheid en zonder beperking.(1/3) String(1/3) String-testoptie zonder beperkingen.(1/6) Bool "soft select" "soft detect"(1/6) Dit is een bool-testoptie, met "soft select" en "soft detect" (en "advanced") mogelijkheden. Dit is slechts een normale bool-optie.(1/6) Int(1/6) Int-testoptie zonder eenheid en beperkingen.(2/3) Vaste bereikbeperking(2/3) Vaste testoptie met de eenheid "microseconde" en een beperkt bereik. Het minimum is -42.17, het maximum 32767.9999 en de stapgrootte is 2.0.(2/3) String beperkte "string list"(2/3) String-testoptie met een beperkte "string list".(2/6) Bool "hard select" "soft detect"(2/6) Dit is een bool-testoptie, met "hard select" en "soft detect" (en "advanced") mogelijkheden. Dit betekent dat de "frontend" de optie niet kan instellen, maar de gebruiker dat moet doen (b.v. door op een knop van het apparaat te drukken).(2/6) Int bereikbeperking(2/6) Int-testoptie met de eenheid "Pixel" en een beperkt bereik. Het minimum is 4, het maximum 192, en de stapgrootte is 2.(3/3) Vaste beperkte woordenlijst(3/3) Vaste-testoptie zonder eenheid en met een beperkte woordenlijst.(3/3) String beperkte lange "string list"(3/3) String-testoptie met een beperkte "string list". Bevat enkele andere ingangen...(3/6) Bool "hard select"(3/6) Dit is een bool-testoptie, met "hard select" (en "advanced") mogelijkheden. Dit betekent dat de "frontend" de optie niet kan instellen maar de gebruiker dat moet doen (b.v. door een knop van het apparaat in te drukken). Bovendien kan de "frontend" de instelling niet lezen.(3/6) Int beperkte woordenlijst(3/6) Int-testoptie met de eenheid "bits" en een woordenlijst-beperking.(4/6) Bool "soft detect"(4/6) Dit is een bool-testoptie, met "soft detect" (en "advanced") mogelijkheden. Dit betekent dat het een alleen-lezen optie is.(4/6) Int rij(4/6) Int-testoptie met de eenheid "mm" en een rij zonder beperkingen.(5/6) Bool "soft select" "soft detect" geemuleerd(5/6) Dit is een bool-testoptie, met "soft select", "soft detect", en "emulated" (en "advanced") mogelijkheden.(5/6) Int rij bereikbeperking(5/6) Int-testoptie met de eenheid "dpi" en een rij met een bereikbeperking. Het minimum is 4, het maximum 192, en de stapgrootte is 2.(6/6) Bool "soft select" "soft detect" auto(6/6) Dit is een bool-testoptie, met "soft select", "soft detect", en "automatic" (en "advanced") mogelijkheden. Deze optie kan de backend automatisch instellen.(6/6) Int rij beperkte woordenlijst(6/6) Int-testoptie met de eenheid "procent" en een rij met een woordenlijstbeperking.1/2 van de standaard snelheid1/3 van de standaard snelheid10mm15mm16 bits grijs2-beeldpunt20mm2x2 door de gebruiker gedefinieerd2x2 normaal3x3 door de gebruiker gedefinieerd3x3 normaal4-beeldpunt48 bits kleur4x4 grof4x4 door de gebruiker gedefinieerd4x4 fijn4x4 normaal5x5 grof5x5 door de gebruiker gedefinieerd5x5 fijn6x4 (inch)6x6 door de gebruiker gedefinieerd6x6 normaal8-bit resultaat8-beeldpunt8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Grof Aandikken8x8 Fijn Aandikken8x8 Verticale Lijn8x8 grof8x8 door de gebruiker gedefinieerd8x8 fijn8x8 normaal8x8 zeer fijnEen langere belichtingstijd laat de scanner meer licht verzamelen. Advies is om 175% voor papieren originelen, 150% voor dia's en "Negatief" voor negatieven te gebruiken. Voor donkere (onderbelichte) beelden kun je deze waarde verhogen.A3A3 papierA3 papier gedetecteerdA4A4 papierA4 papier gedetecteerdA5A5 liggendA5 staandA6Automatische documentinvoerAutomatische documentinvoer achterzijdeAutomatische documentinvoer dubbelzijdigAutomatische documentinvoer voorzijdeAutomatische documentinvoer ModusADF wachttijdDeksel van automatische documentinvoer openOpstopping in automatische documentinvoerToegang tot bron is geweigerdActie die volgt op dubbele doorvoer foutRuimte toevoegen aan de onderzijdeRuimte toevoegen aan de bovenzijdeVerhoogt blauw op basis van het groenwaardeVerhoogt blauw op basis van de roodwaardeVerhoogt groen op basis van de blauwwaardeVerhoogt groen op basis van het roodwaardeVerhoogt rood op basis van de blauwwaardeVerhoogt rood op basis van de groenwaardePas blauw-/roodcompensatie aanPas voor-/achtercompensatie aanPas groen-/roodcompensatie aanGevorderdGeavanceerde optiesGeavanceerde papier protectieBegin pas met scannen als eerst het scancommando naar de scanner is gestuurd en daarna de knop van de scanner is ingedrukt.Alle pagina'sBiedt men de mogelijkheid de werking van het apparaat te testen met andere ondersteunde modellen.Schakel altijd de lamp uit tijdens donker kalibreren.Analoog bereikAnaloge "frontend"Analoge gammawaarde blauwAnaloge gammacorrectieAnaloge gammawaarde groenAnaloge gammawaarde roodAnaloge gammacorrectieAnaloge gammacorrectie voor blauwAnaloge gammacorrectie voor groenAnaloge gammacorrectie voor roodAutomatischAutomatische drempelwaardeAutomatische verdeling van het scanoppervlakAutomatische uitworpAutomatische belichtingAutofocusEén keer autofocusAutomatische lengte herkenningAutomatische of handmatige scherpstellingAutomatische breedte herkenningAutomatischAutomatische documentinvoerAutomatische aanpassing van de drempelwaardeAutomatische kleurscheidingAutomatische drempelwaardeAutomatische drempelwaarde modusAutomatisch opwarmenWerp de film automatisch uit de scanner na elke scanWerp de film automatisch uit de scanner voor het programma wordt verlatenStelt automatisch helderheid, contrast, witwaarde, gamma, ruisonderdrukking en beeldverbetering inB4B4 papierB4 papier gedetecteerdB5B5 papierB5 papier gedetecteerdB6BP filterAchterzijdeAchtergrond kleur"Backtrack" lijnenKleurbalansfactor voor blauw: Een waarde van 100% betekent geen kleurcorrectie.Kleurbalansfactor voor groen: Een waarde van 100% betekent geen kleurcorrectie.Kleurbalansfactor voor rood: Een waarde van 100% betekent geen kleurcorrectie.BakBayerBayer Dither 16Bayer Dither 642-niveau zwart/wit (lijntekening modus)Combineer RGBCombineer X- en Y-resolutieCombineer analoge gammawaardeGecombineerde gammaBitdiepteZwartZwartwaardeBlauwBlauwbalansHelderheid van het blauwe kanaalBlauwbereikBlauwbereik waarde van de AFEBlauwe intensiteitBlauwe lamp uitBlauw compensatieBlauw compensatie van de AFEBool-testoptiesVan beneden naar bovenRechtsonder xRechtsonder x positie van het scanoppervlak.Rechtsonder yRechtsonder y positie van het scanoppervlak.HelderheidBuffermodusIngebouwd CCT profielKnop 1Knop 2Status van de knopKnoppen testoptieKnop-gestuurde scanKnoppenCDfout bij controle van processorCRTCRT-monitorenBelichtingstijd kalibrerenBelichtingstijd kalibreren voor blauwBelichtingstijd kalibreren voor groenBelichtingstijd kalibreren voor roodLichtwaarde kalibrerenKalibrerenKalibreer scannerVoor de volgende scan kalibrerenKalibreer focus van de lens op het documentKalibreert voor de zwart-/witwaardeKalibrerenKalibratie door de "backend"Vervaltijd van de kalibratie cacheKalibratie gegevenscacheKalibratiebestandKalibreermodusKalibreer nuAnnuleer-knopKaart achterzijdeKaart dubbelzijdigKaart voorzijdeWijzig Origineel.Wijzig origineelWijzig Endorser teller waarde met deze hoeveelheid voor elke paginaVerandert de intensiteit van de middentonenKanaalControleerChipset IDNaam van de chipsetReset kalibratieReset kalibratiecacheGrofGrove kalibratieGrove kalibratie alleen voor de eerste scanGrove kalibratie wordt alleen voor de eerste scan uitgevoerd. Dit werkt bij de meeste scanners en kan scantijd schelen. Wanneer de helderheid van het beeld per scan verschilt, schakel deze optie dan uit. Alleen voor testdoeleinden.Selecteer een paar mm van de achtergrond aan de bovenkant van de scan, voordat het papier de ADF ingaat, en vergroot het maximale scan oppervlak t.o.v. het papierformaat, om de inzameling van de overige kanten toe te staan. Kan conflicteren met 'bgcolor' optieKleurKleur (48 bits)Kleur 36Kleur HalftoonKleur lijntekeningKleurmatrixKleur RAWKleur RGBKleur RGB TEKSTKleurbalansBereikinstellingen van de kleurkanalenCompensatieinstellingen van de kleurkanalenKleurcorrectieKleurcorrectiecoëfficiëntenKleurenfilterKleurpatroonKleur24Kleur36Kleur48Kleurlijnen per leesopdrachtCompressieCompressie argumentVoorwaardelijkVoortzettenContrastContrast van het blauwe kanaalContrast van het groene kanaalContrast van het rode kanaalRegelpatroon van het halftoon filterRegeltype van het halftoon filterRegel de witwaarde volgerRegelt de blauwwaardeStuurt de Endorser eenheid aanRegelt de groenwaardeRegelt de roodwaardeRegelt de "tint" (blauwwaarde) van het verkregen beeld.Regelt de helderheid van het verkregen beeld.Bepaalt de helderheid van het blauwe kanaal van het verkregen beeld.Bepaalt de helderheid van het groene kanaal van het verkregen beeld.Bepaalt de helderheid van het rode kanaal van het verkregen beeld.Regelt het contrast van het verkregen beeld.Bepaalt het contrast van het blauwe kanaal van het verkregen beeld.Bepaalt het contrast van het groene kanaal van het verkregen beeld.Bepaalt het contrast van het rode kanaal van het verkregen beeld.Regelt dat "backtracking" wordt gebruikt.Kopieer-knopCorrectie op basis van filmtypeCorrectie op basis van de transparantieverhoudingDeksel openSnij het effectieve beeldoppervlak uitDoor de gebruiker gedefinieerdDoor de gebruiker gedefinieerd kleurmatrix voor grijstint scansDoor de gebruiker gedefinieerde kleurmatrixDF actieDF lengteDF lengte verschilDF herstel modusDF scheefheidDF dikteDTCFoutzoekoptiesStandaardinstellingStandaardinstellingenBepaal kalibreermodusBepaal de belichtingstijd voor de kalibratie van de blauwe componentBepaal de belichtingstijd voor de scan van de blauwe componentBepaal de belichtingstijd voor de kalibratieBepaal de belichtingstijd voor de kalibratie van de groene componentBepaal de belichtingstijd voor de scan van de groene componentBepaal de belichtingstijd voor de kalibratie van de rode componentBepaal de belichtingstijd voor de scan van de rode componentBepaal de belichtingstijd voor de scanBepaal de lichthoeveelheid waarmee wordt gekalibreerdBepaal de lichthoeveelheid waarmee wordt gescandBepaalt de blauwe lamp uit parameterBepaalt de groene lamp uit parameterBepaalt de rode lamp uit parameterDefinieert het halftoon patroon (dithering) waarmee halftoon beelden worden gescand.Definieert de vergrotingsfactor die de scanner zal gebruikenVertraag de gegevensoverdracht door de databus.DichtheidDichtheidscontroleDichtheid schaalHerken aan elkaar geniet documentBepaald maximale Endorser teller waardeBepaald de snelheid waarmee wordt gescand.Bepaalt of de interne of de door de gebruiker gedefinieerde gammatabel wordt gebruikt.Apparaat is bezetApparaatinstellingenRuitvormigVerschil in papier lengte om dubbele doorvoer fout te veroorzakenVerspreidingSchakel automatische documentinvoer uit en gebruik alleen flatbedGeen "backtracking"Dynamische lijntekening uitschakelenSchakel gammacorrectie uitSchakel interpolatie uitVoorfocusering uitschakelenSchakel, om een lijntekening te genereren het gebruik van een software aanpassend algoritme uit en vertrouw in plaats daarvan op de hardware.Schakel witte schaduw correctie uitDispersedDot16x16DispersedDot8x8Toon korte lijst met oplossingenDitherDither A (4x4 Bayer)Dither B (4x4 Spiraalvorm)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Halftoon zwart/wit (halftoon modus)Ditherpatroon 1Ditherpatroon 2Voer een grijstrap-, in plaats van een kleurenscan uitVoer een kwaliteit wit-kalibratie uitVoer alleen een autofocus uit tussen uitworpenFocusering niet kalibrerenStatusbericht niet opdringenDwing de "backend" niet een statusbericht terug te geven.Stop niet na de dubbele doorvoer verklikkerDocumentinvoerExtra's van de documentendoorvoerOpstopping in documentendoorvoerDocumentendoorvoer leegDubbele optische resolutieDubbele doorvoerDubbele doorvoer gedetecteerdDubbele doorvoer herkenningGevoeligheid van de dubbele doorvoer verklikkerDubbel briefpapier 11x17 inc.Download patroon ADownload patroon BKleuronderdrukkenUitvalkleurDubbelzijdigDubbelzijdige compensatieDubbelzijdige scanDubbelzijdige scan scant beide zijden van een documentDuplex zijdeDuplex schakelaarDuur van de leesvertragingDynamische drempel curve, van licht naar donker, normaal 50-65UitwerpenWerp het document uit na het scannenWerp de film uit na elke scanWerp de film uit voor het programma wordt verlatenWerp de film nu uitWerp de film *NU* uitWerp het document in de automatische documentinvoer uitE-mail-knopNadrukEmuleer grijstrapSchakel dubbelzijdig (duplex) scannen inMaak automatische bepaling mogelijk van de drempelwaarde voor lijntekening scans.Schakel automatische scheiding tussen beeld en tekst inSchakelt gecomprimeerde gegevens in. Kan je front-end programma laten crashen.Stelt dubbele doorvoer fout in als gevolg van papierlengteStelt dubbele doorvoer fout in als gevolg van papierdikteSchakel dubbele doorvoer fout in als gevolg van scheefheidSchakel Endorser eenheid inSchakelt de instelling van de belichtingstijd inSchakelt de instelling van de lichthoeveelheid inSchakelt verzachting in om OCR te verbeterenTestopties inschakelenSchakel diverse testopties in. Met deze optie kan worden getest in hoeverre "frontends" de verschillende SANE-optietypes laten zien en kunnen veranderen.Dubbele doorvoer herkenning in/uit schakelenFormaat gestuurde modus in/uit schakelenGroot formaat papier modus in/uit schakelenAan/uit schakelen van autofocusSchakel de automatische belichtingsoptie aan/uitSchakelt kalibratiecache in/uitSchakelt snellere sensor beweging in/uitEind van bestand bereiktEndorserEndorser-optiesEndorser YEndorser alfanumerieke afdrukformaat. %05ud of %08ud zal aan het eind worden vervangen door de teller waarde.Endorser delenEndorser richtingEndorser lettertypeEndorser afdruk compensatie vanaf de bovenkant van het papierEndorser afdruk richtingEndorser afdruk lettertypeEndorser afdrukzijde, vereist hardware ondersteuning om te worden gewijzigdEndorser zijdeEndorser stapEndorser tekstEndorser waardeVerbeter blauwVerbeter groenVerbeter roodVerbetermodusKleurverbeteringFoutenverspreidingFoutcodeFout tijdens apparaat I/OVerwissel de hoge en lage byte van de beeldgegevens in 16-bit-modus. Deze optie kan worden gebruikt om de 16-bit-modus van "frontends" te testen, bijvoorbeeld of de "frontend" de juiste "endianness" gebruikt.Voer kalibratie *NU* uitExperimentBelichtingstijdVerleng lamp timeoutVerlengt de lamp timeout (van 15 minuten tot 1 uur)Extra snelExtra-knopExtra kleuraanpassingenExtra'sSnelSnelle grijsmodusSnelle voorbeeldscanHoge snelheidSnellerSnelsteFax-knopDoorvoermodusBestand-knopBestandsnaamFilmtypeFilmstrookFijnFraaie kleurenStandaardkleurbalansEerste ingangAangepast aan de paginaZet focuspositie vastVaste testoptiesFlatbedAlleen flatbedFocusFocus 2.5mm boven het glasFocus positieFocus op het glasScherpstel positieScherpstelpositie voor het scannenScherpstelmodusScherpstelpositieDwing "backtracking"Dwing monochroom voorbeeldscanForceer ware diepteDwing te kalibreren voor het scannenDwing de "backend", na een aanroep van sane_read() het statusbericht SANE_STATUS_ACCESS_DENIED terug te geven.Dwing de "backend", na een aanroep van sane_read() het statusbericht SANE_STATUS_COVER_OPEN terug te geven.Dwing de "backend", na een aanroep van sane_read() het statusbericht SANE_STATUS_EOF terug te geven.Dwing de "backend", na een aanroep van sane_read() het statusbericht SANE_STATUS_IO_ERROR terug te geven.Dwing de "backend", na een aanroep van sane_read() het statusbericht SANE_STATUS_JAMMED terug te geven.Dwing de "backend", na een aanroep van sane_read() het statusbericht SANE_STATUS_NO_DOCS terug te geven.Dwing de "backend", na een aanroep van sane_read() het statusbericht SANE_STATUS_NO_MEM terug te geven.ScannerraamHet te scannen raamnummer van de filmhouderHet te scannen scannerraamVanaf papierVanuit de scannerVanaf witte puntVoorzijdeVoorpaneel knop wachtVolledige scanFunctieFunctie karakter op het schermOnduidelijke parametersBereikGammaGammacorrectieGammatabellenGammacorrectieGammacorrectie wordt uitgeschakeldGammakrommeGammakromme, van licht naar donker, maar bovenste twee werken misschien nietGammafunctie exponentGammawaardeGammacorrectietabel voor de blauwe component.Gammacorrectietabel voor de groene component.Gammacorrectietabel voor de rode component.Gammacorrectietabel. In kleurmodus beïnvloedt deze optie tegelijkertijd de rode, groene en blauwe kleurcomponenten. (d.w.z. Het is een helderheids-gammatabel).GeometrieGeometrie groepKorrelgrootteGrijsGrijsbereikKleur in grijsmodusGrijscompensatieGrijs16Grijs8Grijs maken4 bit grijstrap8 bit grijstrapGrijstrapscanGroenGroenbalansHelderheid van het groene kanaalGroenbereikGroenbereik waarde van de AFEGroene intensiteitGroene lamp uitGroen compensatieGroen compensatie van de AFEGrijstraplijnen per leesopdrachtRasterHalftoonHalftoon A (hard)Halftoon B (zacht)Halftoon CHalftoon punt 32Halftoon punt 64HalftoonpatroonGrootte van het halftoonpatroonHalftoon typeHalftoonmodusHalftoon niet ondersteundStoppen bij annulerenHandscanner simulatieHandscanner-simulatieHardware rechtzetten en afknippenHardware foutcodeX positie in de scanner van het scanoppervlak.Y positie in de scanner van het scanoppervlak.Hardware resolutieHardware specifieke optiesHoogAfdrukken met hoog contrastAfdrukken op hoge kwaliteitHoge gevoeligheidHoogste kwaliteit, maar met een lagere snelheidHoogste snelheid, maar met een lagere kwaliteitLichteffectLichteffect voor blauwLichteffect voor groenLichteffect voor roodHouder focus positie 0mmHorizontaalHorizontaal vetHorizontaal smalHoe lang wordt gewacht nadat de gegevensverzameling door de databus is overgebracht.TintAls de automatische documentinvoer is gekozen, zal de invoerna 10 scans 'leeg' zijn.Indien aangevinkt, probeert de "backend" een optimale waarde te bepalen voor de drempelwaarde.Wanneer aangevinkt, wordt de kleur kalibratie voor een scan uitgevoerd door de "backend"Wanneer aangevinkt, voert de scanner geen "backtracking" uitIndien ingeschakeld, wordt het beeld in kleurmodus gescand en daarna door de software geconverteerd naar grijswaardes. Dit kan de beeldkwaliteit in sommige gevallen verbeteren.Indien ingeschakeld, wordt tijdens het kalibreren alleen de schaduw-correctie uitgevoerd. De standaard waarden voor bereik, compensatie en belichtingstijd bepaald door de hardware of het configuratiebestand, worden gebruikt.Indien ingeschakeld, worden enkele beelden die deel uitmaken van het scanproces bewaard, zodat ze kunnen worden geanalyseerd.Indien ingeschakeld, wordt de scanner voor de volgende scan gekalibreerd. Anders wordt de scanner alleen voor de eerste scan gekalibreerd.Als gammacorrectie is ingeschakeld, worden scans altijd met 16 bit diepte gemaakt om de beeldkwaliteit te verbeteren en daarna geconverteerd naar de gekozen diepte. Deze optie schakelt diepte emulatie uit.Negeer kalibratieNegeer middelste dubbele doorvoer voelerNegeer linker dubbele doorvoor voelerNegeer rechter dubbele doorvoer voelerBeeldBeeldverbeteringKleuren van het beeld worden geïnverteerdBeeldverbeteringBeeldintensiteitOpties voor beeldaanpassingMatrixprintersImprinter inkt niveauImprinter inkt is bijna opVerbeterd de kwaliteit van hoog resolutie bal-punt pen tekstGebruik in RGB-modus voor alle kleuren dezelfde waardenVergroot of verklein het analoge bereik van de CCD-sensorInformatieInfraroodInitiële Endorser teller waardeInkt bijna opResterende hoeveelheid inktInkjetprintersInt-testoptiesOngeldige waardeGeïnverteerd beeldInverteer beeld in Z/W modusGeïnverteerd beeld in Z/W of halftoon modusInverteer "endianness"Het is rechts en links omkeringJPEGJPEG beeld compressie met Q parameter, '0' - geen compressieJPEG compressieJPEG compressie (je programma moet in staat zijn te decomprimeren)Lamp kleurLamp niet klaar, probeer opnieuwLamp uitLamp aan het einde uitschakelenLamp uit tijdens donker kalibrerenLamp uit tijdens het scannenLamp-uit tijdLamp uit tijd (minuten)Lamp aanLamp statusLamp timeoutLamp uit tijdLamp uit tijd in seconden.LampschakelaarLiggendLegalFormaat Controle Modus is een modus waarbij de scanner leest tot aan de kortste lengte van het gebruikte papier of de feitelijke lengte van het document.Lengte-controlemodusKalibratie van de lens op het documentEens kijken of "frontends" hiermee om kunnen gaan.LetterNiveau van JPEG compressie. 1 is klein bestand, 7 is groot bestand. 0 (standaard) is hetzelfde als 4Beperk het geheugengebruik door het stuurprogramma in ingebedde systemen. Zorgt bij sommige duplex scans voor wisselende zijden bij de aanroep van sane_read. De waarde van de optie 'zijde' kan worden gebruikt om het juiste beeld vast te stellen. Deze optie dient uitsluitend te worden gebruikt door aangepaste front-end software.Begrens de hoeveelheid gegevens die bij elke aanroep van sane_read() wordt overgedragen.LijntekeningScan het beeld in grijstinten.Groot Papier Modus is een modus waarin de scanner het beeld leest nadat hij het formaat van het papier heeft gedeeld door de lengte, die is ingesteld bij de optie Document FormaatGroot formaat papier modusVerlies van pixels per lijnLaagTe weinig geheugen beschikbaarAfdrukken op lage kwaliteitLage gevoeligheidHandmatige doorvoerHandmatige doorvoermodusHandmatige doorvoer geselecteerdHandmatige doorvoer timeoutHandmatige focuspositieHandmatige voorfocuseringSchakel de lamp(en) handmatig aan/uit.Matrix 2x2Matrix 3x3Matrix 4x4Matrix 5x5Matrix vermenigvuldiging van RGBMaximaalMaximale omvang van verspreid liggende spikkels, die van het gescande beeld moeten worden verwijderdMaximale diameter van verspreid liggende spikkels, die van het gescande beeld moeten worden verwijderd.OrigineelGemiddeldGemiddeld gebruikMiddentoonMiddentoon voor blauwMiddentoon voor groenMiddentoon voor roodTijd (in minuten) totdat de lamp wordt uitgeschakeld na een scanHorizontaal spiegelenSpiegel het beeldSpiegel beeld (links/rechts verwisselen)Beeld horizontaal spiegelenBeeld verticaal spiegelenSpiegel het beeld horizontaalSpiegel het beeld.Verticaal spiegelenSpiegelenOverigMode 1Mode 2Mode 3Mono KleurmatrixMulti-niveau RGB kleur (één-doorgang-kleur)Multi-niveau zwart/wit (grijstrap modus)NTSC GrijsNTSC RGBKalibratie nodigNegatiefTransparantNegatiefKleurennegatiefNegatief filmtypeNegatief filmtypeGrijsnegatiefNegatief naar geleidelijk of positief naar scherp beeldNegatievenGeen correctieGeen herkenningOngecorrigeerde transparantieRuisonderdrukkingRuisverwijderingGeenNormaalNormale modusStandaard snelheidAantal bits per kleurwaarde, typische waarden zijn 1 voor zwart/wit en 8 voor multibit-scans.Het aantal scanlijnen dat de scannerwagen teruggaat als "backtracking" optreedt. Dit gebeurt als de scanner sneller scant dan de computer de data kan verwerken. Lage waarden zorgen voor snellere scans, maar vergroten het risico van gemiste scanlijnen.Aantal optiesAantal scanlijnen dat bij een SCSI-leesopdracht wordt gevraagd. Verandering van deze parameter geeft je de mogelijkheid om de snelheid waarmee gegevens van de scanner wordt gelezen nauwkeurig af te stellen. Wanneer deze te laag is ingesteld moet de scanner tijdens het scannen regelmatig stoppen. Als deze te hoog is ingesteld bestaat de kans dat het scanprogramma niet meer reageert op invoer van de gebruiker en kan het gehele systeem onbruikbaar worden.Nummer van het te scannen scannerraamOCR-knopOMR of DFOMR of dubbele doorvoer gedetecteerdUitTijdschakelaar - uitstandBiedt een "kies-bestandsbeschrijving" aan, om te kunnen achterhalen of sane_read() gegevens zal teruggeven.Biedt "kies-bestandsbeschrijving" aanCompensatieAanEén paginaOne-pass scanners gebruiken slechts een kleur bij grijstrap of binair scannen, bruikbaar voor gekleurd papier of inkt.Voer alleen een schaduwcorrectie uitHandeling niet ondersteundHandeling was geannuleerdOptioneel hulpstukGeheugen volOverscanPDF-knopPagina hoogtePagina geladenPagina breedtePapier is gedeeltelijk in de ADF getrokkenPapier protectiePapierformaatDoorgangVoer de zelftest van de scanner uitVoert kalibratie uitFeitelijke formaat van het papier in de Automatische documentinvoerDiapositiefDiaDiaDia of negatief filmtypeAan/Uit-knopEnergiebesparendeVoorgedefinieerde instellingenVoorkeuzeVoorbeeldscanVoorbeeldmodusAfdrukDruk een lijst met alle opties af.Druk opties afBiedt standaard scanoppervlaktes voor foto's, afdrukken enzovoort.Kwaliteit kalibrerenHoge kwaliteit scanSnelle opmaakfout bij controle van het RAM geheugenGBFfout bij controle van het ROM geheugenToevalspatroonOngecomprimeerdLeesvertragingLeesbegrenzingAlleen-lezen testoptieAlleen-lezen optie, die aangeeft hoeveel opties een apparaat ondersteunt.RoodRoodbalansHelderheid van het rode kanaalRoodbereikRoodbereik waarde van de AFERode intensiteitRode lamp uitRood compensatieRood compensatie van de AFEVerminder de ruis van afzonderlijke puntenSpiegel het resulterende beeld horizontaalReflecterendVerwijder 2 beeldpunten in een vierkant ruisVerzoek om een scan in voorbeeldkwaliteit.Vraag backend randen van pagina's digitaal te verwijderenVraag stuurprogramma een 90 graden gedraaid beeld te herkennen en corrigerenVraag het stuurprogramma pagina's met weinig dekking te verwijderenVerzoek het stuurprogramma pagina's met weinig dekking te negerenVraag het stuurprogramma de papierdoorvoer te stoppen i.p.v. uit te werpen tijdens een annuleringVraag het stuurprogramma randen van pagina's digitaal te verwijderen Vraag het stuurprogramma randen van pagina's digitaal te verwijderen.Vraag het stuurprogramma pagina's met een vaste hoeveelheid te roterenVraag het stuurprogramma scheef getrokken pagina's digitaal te roterenVraag het stuurprogramma scheef getrokken pagina's digitaal te roteren.Vraag de scanner opstoppingen in de ADF te detecteren die worden veroorzaakt door nietjesVraag de scanner de volgende pagina uit de ADF op te halenVraag de scanner opstoppingen in de ADF te voorspellen Vraag de scanner opstoppingen in de ADF te voorspellen met behulp van verbeterde sensorenVraag de scanner pagina's vanuit de ADF zo snel mogelijk in te lezen in het interne geheugenVraag de scanner de doorvoer om te keren bij papier opstoppingVraag de scanner pagina's digitaal te roteren en af te knippen.Legt vast dat alle voorbeeldscans in grijswaardemodus worden uitgevoerd. Bij een Three-Pass-Scanner is daardoor slechts één doorgang nodig, bij een Single-Pass-Scanner wordt het geheugengebruik en de scantijd verminderd.Vraag de snelste (lage kwaliteit) modus te gebruiken voor alle voorbeeldscans. Dit kan een niet-kleur of lage resolutie modus zijn.Vereist zwarte achtergrond voor het scannenReset chipsetReset scannerReset de scannerReset chipset gegevensGeef SANE_STATUS_ACCESS_DENIED terugGeef SANE_STATUS_COVER_OPEN terugGeef SANE_STATUS_EOF terugGeef SANE_STATUS_IO_ERROR terugGeef SANE_STATUS_JAMMED terugGeef SANE_STATUS_NO_DOCS terugGeef SANE_STATUS_NO_MEM terugGeef onduidelijke lijnen en bytes per lijn terug als sane_parameters() voor sane_start() wordt aangeroepen.Resultaat van sane_readGespiegeld beeld formaatRoteer beeld met de klok meefout in SCSI pariteitSDTCKleurverzadigingBewaar foutzoekbeeldenGammagetalwaardeGammagetalwaarde voor blauwGammagetalwaarde voor groenGammagetalwaarde voor roodScanmodusScanmodus groepOpties voor scanoppervlak en origineelgrootteScan-knopScannertellerBelichtingstijd voor het scannenBelichtingstijd voor het scannen van blauwBelichtingstijd voor het scannen van groenBelichtingstijd voor het scannen van roodScan in snelle grijsmodus (lage beeldkwaliteit).Lichtwaarde bij het scannenScanmargesScanmodusScanresolutieScanbronScansnelheidScan het volledige scanbereik inclusief de kalibereerstrook. Pas op! Kies niet een te grote hoogte. Alleen voor testdoeleinden.De scanner herkent automatisch het beeldoppervlak en snijdt die uitDeksel van de scanner is openScanner herkent onderzijde van het papier. Kan sommige frontends in de war brengen.Scanner herkent paper zijden. Kan de scansnelheid verminderen.Scanner in energiebesparende modusScannerwagen geblokkeerd (in transportstand)Scanner modelScannersensoren en -knoppenScanner verkleint het beeld zodat deze op de gescande pagina pastDe scanner wordt gestopt als het papier is scheefgetrokkenTweede ingangKies de bak om te scannenSelecteert filmtypeKiest de minimale helderheid waarmee witte punt wordt verkregenKies halftoon filter.Selecteert het filmtypeKies het soort testbeeld. Beschikbare opties: Egaal zwart: maakt het gehele beeld zwart. Egaal wit: maakt het gehele beeld wit. Kleurpatroon: tekent verschillende kleurtestpatronen, afhankelijk van de modus. Raster: tekent een zwart/wit raster ter grootte van 10 mm².Kies de scanmodus voor voorbeeldscans. Grijstrap voorbeeldscans geven meestal de beste combinatie van snelheid en detail.Kies het resultaat van sane_read(). "Default" is de normale instelling voor het scannen. Alle andere resultaten zijn bedoeld om vast te stellen hoe "frontends" hiermee omgaan.Kies het testbeeldKiest een getalwaarde voor gammacorrectie (blauwe kanaal)Kiest een getalwaarde voor gammacorrectie (groene kanaal)Kiest een getalswaarde voor gammacorrectie (rode kanaal)Kiest een getalwaarde voor de gammacorrectieBepaalt de "gekorreldheid" van het verkregen beeld. Kleine waarden zorgen voor een scherper beeld.Selecteert de Automatische documentinvoer modus (enkelzijdig/dubbelzijdig)Kiest helderheid.Kiest de kleurengroep, "Master" betekent dat alle kleuren worden beïnvloed.Kiest kleuronderdrukken.Selecteert het filmtype, bijvoorbeeld negatieven of dia'sKiest de gamma gecorrigeerde overdrachtscurveKiest de gammacorrectiemodusSelecteert de gammacorrectiewaarde uit een lijst met voorgedefinieerde apparaten of de door de gebruiker gedefinieerde tabel die naar de scanner kan worden gestuurdKiest halftoon.Selecteert het negatief filmtypeKiest het nummer van het te scannen scannerraamKiest de scanmodus (b.v. zwart/wit, monochroom of kleur).Selecteert de scanbron (zoals b.v. een documentendoorvoer).Kiest de scanbron (zoals b.v. documentendoorvoer). Stel de bron in voor de modus en resolutie. Zet modus en resolutie terug naar automatische waarden.Bepaalt welke blauwe helderheidswaarde als "zwart" moet worden beschouwd.Bepaalt welke blauwe helderheidswaarde als "verzadigd blauw" moet worden beschouwd.Bepaalt welke blauwe helderheidswaarde als "wit" moet worden beschouwd.Bepaalt welke groene helderheidswaarde als "zwart" moet worden beschouwd.Bepaalt welke groene helderheidswaarde als "verzadigd groen" moet worden beschouwd.Bepaalt welke groene helderheidswaarde als "wit" moet worden beschouwd.Bepaalt welke helderheidswaarde als "zwart" moet worden beschouwd.Bepaalt welke helderheidswaarde als "wit" moet worden beschouwd.Bepaalt welke rode helderheidswaarde als "zwart" moet worden beschouwd.Bepaalt welke rode helderheidswaarde als "verzadigd rood" moet worden beschouwd.Bepaalt welke rode helderheidswaarde als "wit" moet worden beschouwd.Bepaalt of een halftoon beeld (dithered) wordt verkregen.Kiest welke helderheidswaarde als 50% blauw moet worden beschouwd.Kiest welke helderheidswaarde als 50% grijs moet worden beschouwd.Kiest welke helderheidswaarde als 50% groen moet worden beschouwd.Kiest welke helderheidswaarde als 50% rood moet worden beschouwd.Selecteert de scankleur die in de grijsmodus wordt gebruikt (Standaard: groen)ZelftestSensorenScheidingStelt SDTC variantie rato in (gevoeligheid), 0 is gelijk aan 127Stel kleurwaarde van blauw inStel kleurwaarde van rood inStel de achtergrond kleur van scans in. Kan conflicteren met de 'overscan' optieStel de kleurverbeteringsinstellingen (helderheid en contrast) in op standaardwaarden.Stel standaardwaarden in om verbeteropties te krijgen.Kies de dichtheidscontrolemodusStel belichtingstijd inStel lichtwaarde inStelt de papier positie in: waar voor liggend, onwaar voor staandStelt schermpunten in overeenkomstig de drempel voor wit ipv zwartStel scherpte waarde in.Stel de gevoeligheid van de dubbele doorvoer verklikker inStel de optische focus van de scanner handmatig in (standaard: 128)Bepaal de volgorde van de afbeeldingenBepaal de volgorde van de afbeeldingen in Three-Pass kleurenmodus.Stel de kleurmatrix in van de scannerStel de tijd (in minuten) in waarna de lamp wordt uitgeschakeld.Stel origineel type in.Schakelt UTA aan/uitStelt het bereik in van het blauwe kanaalStelt de compensatie in van het blauwe kanaalStelt het bereik in van het grijze kanaalStelt de compensatie in van het grijze kanaalStelt het bereik in van het groene kanaalStelt de compensatie in van het groene kanaalSchakelt de lamp aan/uitStelt het bereik in van het rode kanaalStelt de compensatie in van het rode kanaalStelt de automatische drempelwaarde inStelt de kleurbalanswaarden in op de waarden zoals opgegeven door de fabrikant.Stelt de kleurcorrectietabel in voor het gekozen uitvoerapparaat.Stelt de doorvoermodus inStelt de focus in op het glas of 2.5mm daarbovenStelt de gammawaarde voor alle kanalen in.Stelt de horizontale resolutie in van het gescande beeld.Stelt beeldverbetering inSchakelt de lamp kleur in (kleur uitval)Stelt de handmatige doorvoermodus inStelt de handmatige doorvoer timeout in seconden inStelt de resolutie in van het gescande beeld.Stelt de scanbron inStelt het halftoon patroon (dithering) in dat wordt gebruikt om halftoon beelden te scannen.Stelt de verticale resolutie in van het gescande origineel.Stel bereik en compensatie automatisch in. Wanneer deze optie is uitgeschakeld, kunnen de analoge "frontend" parameters handmatig worden ingesteld. Deze optie staat standaard aan. Alleen voor testdoeleinden.SchaduwSchaduw voor blauwSchaduw voor groenSchaduw voor roodSchaduw, middentoon, lichteffecten, belichtingstijdScherper makenScherpteVerschuift blauw naar groenVerschuift blauw naar roodVerschuift groen naar blauwVerschuift groen naar roodVerschuift rood naar blauwVerschuift rood naar groenKorte oplossingenlijstToont de naam van de chipset gebruikt in het apparaat.Toont de chipset IDToont het aantal scans dat de scanner heeft gemaaktSchakel de lamp uitSchakel de scannerlamp uit.enkelzijdigSimuleer een handscanner. Bij handscanners staat tenminste de beeldhoogte vooraf niet vast. In plaats daarvan geeft deze een hoogte van -1 terug. Met deze optie is te testen of de "frontend" daarmee juist kan omgaan. Deze optie stelt ook een vaste breedte van 11 cm in.Simuleer een handscanner. Bij handscanners staat meestal de beeldhoogte van te voren niet vast. In plaats daarvan geven zij een hoogte van -1 terug. Met deze optie kan worden vastgesteld, of een "frontend" hiermee juist kan omgaan.Simuleer een Three-Pass Scanner door drie afzonderlijke afbeeldingen te retourneren. Bij voorkeur is de volgorde groen, dan blauw en tenslotte rood.Simuleer een Three-Pass-Scanner. In kleurmodus worden drie afbeeldingen overgedragen.Grootte van de leesbegrenzingScheefheid correctieScheefheidshoekSla opwarmprocedure overTijdschakelaar - slaapstandDiaDia'sLangzaamLangzamerLangzaamsteGelijkmatigVerzachtenSoftwarematig automatisch uitsnijdenSoftwarematig over te slaan percentage lege pagina'sSoftwarematig uitsnijdenSoftwarematige rotatie tegen de klok inSoftwarematige scheefheid correctieSoftwarematige ontspikkel omvangVerzadigd zwartVerzadigd witKeuze van de bronOpties voor bron, modus en resolutieExtra optiesExtra optiesBepaalt de hoogte van het origineel.Bepaalt de breedte van het origineel. Nodig om doorvoerscans automatisch te kunnen centreren.Specificeer het te gebruiken kalibratiebestandSnellere sensor bewegingStandaardNietjes detectieBegin het kalibreer procesBegin kalibreerproces met een speciale transparantStatusbericht simulatieStoppenStop de scanner als het papier is scheefgetrokkenString-testoptiesSuccesVerwissel zwart en wit (inverteren).Schakel de transparanteneenheid aan/uit (FAU, film adaptereenheid)Schakelt de lamp aan of uit.TMA NegatievenTMA dia'sTPU8x10Soort bewerking van het resultaatVertelt welke zijde (0=voorkant, 1=achterkant) van een duplex scan bij de volgende aanroep van sane_read wordt geretourneerd.TekstverbeteringstechnologieDe (maximale) hoeveelheid gegevens die bij elke aanroep van sane_read() wordt overgedragen.De bestandsnaam van het te scannen beeld.De lamp wordt uitgeschakeld na de opgegeven tijd (in minuten). Een waarde van 0 betekent, dat de lamp niet wordt uitgeschakeld.De lamp wordt uitgeschakeld tijdens het scannenHet aantal pixels dat aan het einde van elke lijn verloren gaat.De verzadigingsgraad bepaalt de "kleuring" van een met een camera opgenomen beeld. Hogere waarden zorgen voor een sterkere kleuring.De scanner moet worden gekalibreerd voor de huidige instellingenThermische printersDit is de erg lange derde ingang. Misschien weet de "frontend" hoe deze kan worden getoondDeze optie geeft de scannerknoppen op het apparaat weerDeze optie geeft de status weer van een scannerknop.Deze optie geeft de status weer van de scannerknoppen.Deze optie schakelt de lamp van de flatbed uit tijdens het scannenThree-Pass SimulationThree-Pass simulatieDrempelwaardeDrempel curveDrempel curve, van licht naar donker, maar bovenste twee zijn misschien niet liniairDrempelwaarde voor lijntekening modusDrempel witTijd (in minuten) voordat een gecachete kalibratie verloopt. Een waarde van 0 betekent dat geen cache wordt gebruikt. Een negatieve waarde betekent dat de cache nooit verloopt.Tijd in minuten voordat de interne voeding de scanner uitschakelt. In stappen van 15 minuten. Nul betekent nooit uitschakelenTijd in minuten voordat de interne voeding overschakelt naar slaap modusSchakel lamp van de flatbed aan/uitSchakelt de lamp van de flatbedscanner aan/uitBovenrandVan boven naar benedenLinksboven xLinksboven x positie van het scanoppervlak.Linksboven yLinksboven y positie van het scanoppervlak.TransparantieTransparantenhulpstukFilmeenheidTransparantieverhoudingTransparanteneenheidSchakel de lamp uitSchakel de lamp uit als het programma wordt verlatenSchakel de scannerlamp uitSchakel scannerlamp aanSchakelt de lamp direct uitSoort te scannen origineelUTA aanOnbekendVerwijderVerwijder Origineel.Verwijder origineel na de scanVerwijdert het origineel na de scan.Werk de status van de knop bijWerk de informatie bijOpties bijwerkenOpties bijwerken.Werkt de informatie over het apparaat bijGebruik 0mm houder focus positie in plaats van 0.6mmGebruik beeldcompositieGebruik intern meer dan acht bits, maar geef slechts acht bits.Gebruik door de gebruiker gedefinieerde gammatabelGebruik de lens waarmee de optische resolutie wordt verdubbeld.Gebruik handmatige of automatische keuze voor scherpstelpositieGebruik niet-blokkerende IOGebruik niet-blokkerende IO voor sane_read() als de "frontend" dat ondersteunt.Gebruik alleen hardware resolutiesGebruik dezelfde gammawaarden voor alle kleurkanalen.Gebruik dezelfde waarden voor X en Y resoluties.Gebruik het "lightlid-35mm" hulpstukDoor gebruiker gedefinieerdDoor gebruiker gedefinieerd (Gamma=1.0)Door gebruiker gedefinieerd (Gamma=1.8)Door gebruiker gedefinieerd CCT profielVariantieVerticaalVerticaal vetWacht op een druk op de knopWacht op een druk op de knopWacht met scannen totdat knop op voorpaneel is ingedrukt.Wacht op een druk op de knop alvorens te scannenWarm op totdat de helderheid van de lamp constant is in plaats van de 'verplichte' 40 seconde opwarmtijd aan te houden.Warm op totdat de helderheid van de lamp constant is in plaats van de 'verplichte' 60 seconde opwarmtijd aan te houden.Lamp opwarmenWarm de lamp op alvorens te scannenOpwarmprocedure wordt uitgeschakeldOpwarmtijdOpwarmtijd in seconden.Wanneer ingeschakeld, zal het scanproces niet direct starten. Om door te gaan, druk op de "SCAN" knop (voor MP150) of "COLOR" knop (voor andere modellen). Om te annuleren, druk op de "GRAY" knop.Wanneer ingesteld, zoekt de scanner gedurende de wachttijd in seconden naar een nieuw document dat in de automatisch document doorvoer is gelegd.Wanneer grijs of lijntekening wordt gebruikt, selecteert deze optie de huidige actieve kleur.Wanneer hoge resoluties worden gebruikt, waarbij de horizontale resolutie kleiner is dan de verticale resolutie, wordt de horizontale interpolatie uitgeschakeld.WitWitwaardeWitwaarde volgerWitwaarde voor blauwWitwaarde voor groenWitwaarde voor roodWitte schaduw correctie wordt uitgeschakeldX-resolutieXPAXPA GrijsXPA RGBY-resolutieVergrotenadfbayer 16bayer 64blauwvisitekaartz/wkleurwaarde van blauwkleurwaarde van roodkleurfout in volgorde van de opdrachtencontinucrtdonkerstandaardinstellingverspreidingerr_verspreidingfbFilmscanneraangepast aan de paginaFlatbedscannergrijsgroenhalftoonhalftoon 32halftoon 64fout bij controle van de hardwarehoogDoor initiator gesignaleerde foutboodschap ontvangenongeldig onderdeel in IDENTIFY boodschapongeldige opdrachtcodeongeldig veld in CDBongeldig veld in de parameterlijstongeldige boodschap foutjpeg compressielampfalenlamp niet gestabiliseerdlichtlineairlaaggemiddeldmedium niet aanweziggeen zinvolle, aanvullende informatiegeennormaaluitcompensatie Xcompensatie Yoptie onjuistparameter gewijzigd door een andere initiatorfout in de lengte van de parameterlijstscanner aan reset / scannerinterface resetroodopnieuw kiezen misluktAfgeronde parameterfout in positionering van scannerkopDoorvoerscannerenkelgelijkmatigtimeoutte veel vensters gespecificeerdlampfalen van de transparanten eenheidfout in de positionering van de scannerkop in de transparanten eenheidfout in de afscherming van de transparantie-eenheid onbekendniet-ondersteunde LUNgebruiker_gedefinieerdwacht_docwacht_doc_spring_opwacht_toetswebcamsane-backends-1.0.27/po/Rules-quot0000664000175000017500000000340012775312262013647 00000000000000# Special Makefile rules for English message catalogs with quotation marks. DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot .SUFFIXES: .insert-header .po-update-en en@quot.po-create: $(MAKE) en@quot.po-update en@boldquot.po-create: $(MAKE) en@boldquot.po-update en@quot.po-update: en@quot.po-update-en en@boldquot.po-update: en@boldquot.po-update-en .insert-header.po-update-en: @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ ll=`echo $$lang | sed -e 's/@.*//'`; \ LC_ALL=C; export LC_ALL; \ cd $(srcdir); \ if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "creation of $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi en@quot.insert-header: insert-header.sin sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header en@boldquot.insert-header: insert-header.sin sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header mostlyclean: mostlyclean-quot mostlyclean-quot: rm -f *.insert-header sane-backends-1.0.27/po/sv.gmo0000664000175000017500000025360413110600540012774 00000000000000Þ•ùäQ¬?ðT ñT-þT ,U;8U tU,U"®UzÑU LV9VVV€­V#.W5RW"ˆWÆ«WrXjX øXBY(\YS…YÙYØðYÉZBèZ+[lB[¯[J¿[+ \c6\ š\z»\'6]™^]$ø]W^u^†^—^œ^ ¡^®^¶^ »^ Æ^ Ñ^ Ü^ç^ ï^ ý^ __ _ '_ 2_=_ F_ Q_ \_ g_t_ |_ Š_ –_ _³_Ä_ Ö_ á_ì_ õ_ `Ò`á`ä`ç` ê` ÷`aa a a a(a1a@a"Ha$ka!a!²aÔa!ôa b7b Wbxbbs’b c5c FcRcbctcŒcŸc°c Èc!éc d+d0d?d Vd ad odzd d™d!³dÕdêdþde<(eGee_­e fffff=+f>if<¨fåféfïfÿf'g7g@gXg jg ugg …g‘g –g£g ³g½gØg çg õghh 0h>h%Mhsh%‚h ¨h³hÈhÑh Úhçhûhiii-i 1i>iQimiŠi¥i ·iÁiÓi)îi%j >jJjajxj‰j ™j§j¸jÈjæjîj ôj ÿj kk6k=k&PkÄwk%OhueÞ^D€c£€abiaÌ .‚ 9‚F‚W‚]‚ o‚y‚Š‚‚•‚ ¦‚³‚!Ä‚æ‚ þ‚) ƒ*4ƒ(_ƒ›ˆƒ$„-„ <„G„ L„V„ f„r„y„„‡„˜„©„¸„ ¾„Ì„ ݄脅… #…0…N…g…l…u…Œ…£…»…Ë…Û…ì… † †$†<†2T†2‡†º†Άè†í†‡‡)‡I‡ i‡s‡†‡š‡¬‡ Ƈчá‡Ió‡=ˆTAˆ[–ˆEòˆ48‰’m‰¹ŠQºŠ€ ‹¢‹0Œ CŒdŒƒŒ£Œ©Œ»ŒÚŒéŒùŒ*(5S ‰•ž¯À Ñß%ùŽ1ŽPŽ=UŽ“Ž?¤Ž äŽïŽ  &G \j‚ Š – £° É ÔÞyä^ r0“ÄCË‘‘Š4‘¿‘Ï‘ç‘ë‘ ’’’3’I’Z’z’—’1›’Í’Ó’Ú’ê’ò’““+%“Q“ c“p““ª“Óá“ó“ ””””&”&8”*_” Š””””®” ·”ŔԔ ã”ñ” • • • *•7•R•b•g• n• z•X‡•Þà•¿–]Ñ–/˜ K˜V˜LZ˜§˜Ę˘Θט÷˜™'™ :™ H™ S™ _™ k™ v™ ™Ž™­™%™è™ ñ™ÿ™š (š5šIš Qš^šdš šMšÝš ñš þš ›› +›5› 9› D›O›Me›³› ·›ÛÒ›Û› õ› œ œœ7œ Uœ`œ5€œ=¶œ?ôœ440i/šÖÊ|¡ž Ÿ ,Ÿ:ŸLŸ `ŸŸŸŸ¶ŸÒŸìŸ [! } — ® À  Å Р æ ó ¡¡ )¡3¡ C¡ d¡ p¡}¡¡¬¡É¡'ä¡ ¢ ¢ +¢5¢ E¢ Q¢x\¢3Õ¢ £&£ F£T£)p£3š£ ΣÛ£î£.ÿ£.¤G¤#\¤g€¥œè¥…¦:¦;ئ9§,N§Y{§%Õ§û§F¨Z¨/o¨*Ÿ¨"ʨ‡í¨u©‹©'ª©<Ò©4ª†Dª>˪B «>M«?Œ«DÌ«?¬9Q¬9‹¬=Ŭ@­=D­B‚­>Å­>®?C®=ƒ®<Á®þ® ¯¯(¯D:¯,¯¬¯ůׯ;è¯$°(:°?c°£°1»°í°; ±H±[±k±‚±›±²±˱ã±ý±²$²!<²>^²?²ݲDó²%8³4^³“³#«³ϳ'é³)´;´XP´2©´ÌÜ´©µ°µÀµѵ)ൠ¶ ¶¶3¶E¶Y¶l¶~¶‘¶"§¶ʶ)ß¶ ··.·ü6·Ð3¸p¹Ku¹Á¹Ô¹ä¹ø¹þ¹º ººº º*ºFº eºsº…º•º ±º ½ºɺ#Úºþº»"»WA»™»¨»±»%Ì»ò» ¼*¼9¼M¼U¼<j¼§¼ ļ Ò¼ݼå¼Gþ¼'F½un½)ä½=¾ŒL¾6Ù¾¿S!¿1u¿4§¿7Ü¿;ÀPÀfÀ |À†À –À·ÀÎÀ îÀ üÀ!Á )Á!4Á VÁcÁxÁŠÁÁ ¯Á ½ÁÞÁôÁ Â)Â0Â8Â?ÂPÂhˆœ¯¾ ÎÂ.ïÂÃC4ÃxÃ(øÃAÌÃÄ.,Ä&[Ä‚Ä  Ä­ÄÆÄßÄøÄ ÅÅÅ)/Å YÅ`zÅ`ÛÅ <ÆHÆdÆ „Æƨ¨Æ>QÇ‹ÇÈ "È.ÈCÈYÈ)mÈ —È¤È¨È±È ¹ÈÆÈËÈÏÈØÈáÈ æÈôÈ÷È ÉÉÉ 1É<É@ÉEÉ MÉ WÉeÉ hÉ uÉÉ‘É–ÉœÉ ¥É ±É½ÉÒÉ)×ÉÊÊ=ÊRÊrÊˆÊ ™Ê¦ÊºÊÀÊÇÊËÊÒÊåÊË ËËËË'Ë&:ËaË!}ËŸË£Ë´ËÆËâËóËúË ÌÌ*Ì/IÌy̡̙̱̺ÌÃÌÖÌßÌ{æÌ bÎ4nΣÎ<²Î ïÎ+ýÎ-)Ï…WÏ ÝÏ:êÏ%ДEÐ!ÚÐ6üÐ.3ÑåbÑHÒ}fÒäÒ;ÿÒ/;ÓYkÓÅÓøáÓÚÔDóÔ 8Õ}YÕ×ÕAëÕ6-ÖedÖ$ÊÖ‰ïÖ8yפ²×WØIwØÁØÙØñØ÷ØýØÙÙ Ù 8ÙDÙ \ÙhÙq٠ً٣٠¬Ù ¸ÙÂÙÚÙ ãÙíÙ ÚÚ!Ú *Ú 7Ú BÚLÚcÚyÚ ‹Ú•Ú­Ú ¶ÚÂÚèÒÚ»Û¾ÛÁÛ ÄÛ ÐÛÜÛßÛ!ùÛ&Ü"BÜeÜ,xÜ'¥Ü)ÍÜ#÷Ü"Ý1>Ý0pÝ0¡Ý0ÒÝ/Þ03Þ dÞnÞtˆÞ ýÞ5ß>ßTßeßzß’ß§ß»ß#Óß#÷ß"à >àJàeà}à‘à «àµà ÒàÝà)÷à!á7áRálá?„áBÄáXâ`âcâfâiâqâ?…â?Åâ>ãDãIãOã^ã*mã ˜ã£ã¿ã Ôãáãéã ïãúãÿãä ä14äfä vä „ä)äºäÖäèäïäåå 4å?åRåZå båmå…å¢åªå­å ½åÈåÛå&öå&æ%Dæjæ ƒææ!¤æ+Ææ$òæ ç#ç7çMç _ç lç xç †ç"“ç¶ç¼ç Âç ÍçÚçìçèè0èÕOè%é+é<é EéQé eé qé {é…é ”é2 é*Óéþéê .ê<êEêNêWê rê }ê‡êê¤ê¹êÍêãêúê<ë0MëC~ëEÂëDì/MìB}ìDÀìCí'Iíqí í*¢í ÍíÛíôí;î DîeîiîƒîŒîœî)¸î(âî$ ï*0ï)[ï)…ï(¯ï#Øï"üï!ð"Að#dð"ˆðC«ð7ïð!'ñIñ_ñ4{ñR°ñòò)ò 1òH;ò„ò"›ò¾òÙòñò± ó¼óÛóðó$ô(ô/ôDôZôtô)Žô ¸ô Æô>Ôô!õ/5õeõzõ1”õ+Æõòõöö#5öYösö#ö±öÍöâö ÷ö ÷÷A&÷h÷?…÷Å÷!Í÷#ï÷ø/øAø Uø vø‚ø ”øVµø! ù.ùNù—jù,ú-/ú,]úŠú-¨ú1ÖúBû KûYûiûyûˆû œû ªû·û¿ÌûŒü §ü²üÁü>Ýü ý(ý?ýGýMýcý}ýý–ýŸý¨ý»ýÄýÌý ÔýÞý ãý"íýþ þ2þHþ dþnþþ…þ¥þ¶þÊþ$ßþÿ-ÿlKÿi¸ÿb"g…eífSeº -?W`tŒ ž¬² ÃÑ'â  !.-0\/™½W ` nz“ £¯· ¾ÈÛî+2@s„ “) Êéñø 0?N] t–¯-È-ö$!9[`{–%¦%Ì òü( = ^hzD‰ÎWÔf, Z“ Eî ª4 Öß c¶ “ Ê® y (Ž '· %ß  %BJYy2ˆ5» ñ ý3E#U-y§!¼ÞAã%?8 x&‚©²)Æ!ð' F P[p …¦¸ÁqÊ<$Q)v  HªóšºÓéî )F_$v›·L» #.E\9r¬ ½Éé2AQYaiq"€$£ ÈÒÛð ø   +:LTfx—¦¬ ³¿eÐí6$?Ð æ]  h‰”œ»Ôçú    ,9 H!Uw>ŠÉ Ñ Þé5I c*m˜I°ú#2B R\`rƒO¡ñö1+] m {(‡%° Ö4à; HQ ?š <Ú 8!8P!é‰!Ÿs"#'#?#X##r# –#·#Ñ#ð# $+$\H$¥$À$Õ$æ$ë$ô$ %%1%G%\%l%6‚%¹%Ê%Þ%%ø%%&$D&2i&œ&´&Ê& Ú&æ&÷&w 'D„'É'!ç' ((A9(6{( ²(À( Þ(1ì() 7)E)ƒV*§Ú*‚+9‘+:Ë+9,-@,Sn,MÂ,-E$-j-/~-*®-Ù-“ù-..1´.Fæ.8-/™f/B0FC0@Š0CË0H1AX1=š1;Ø1B2FW2@ž2;ß2@3@\3A3@ß3K 4 l4z4#ƒ4"§4TÊ4:5'Z5‚5›5@²5ó5/6J?6$Š6:¯6&ê6=7O7_7,r7$Ÿ7,Ä7$ñ7.8&E8l8-€8%®8!Ô8Uö8CL99O¯9+ÿ9C+:o:"ƒ:"¦:3É:2ý:0;eI;@¯;×ð;È<Ï<â<õ<-=5===E=\=r=‰= =¶=Í=$ê=>6 >W>f> €>Œ>â¦?’‰@FAcA€A"žA ÁA ÌA×A àA íAúA B! B)-BWBkB|B"‘B´B½BÄB9ÖBC&CRBRKR`RuR+‰R µRÃRÇRÐR ØRæRëRïRøRS SSS'S:S@S SS aSlSrS {S …S’S•S¥S·S ÍS×SÝS äS îSøS T+T >T_T}T’T²TÊTÝTåTûTUU UU#*UNUTU[U^UgUpU'‰U±U7ÉUV VV"&VIV^VgV mV"xV›V5¶V ìV W W W4WFWaW yWPψ§ dXã½ZUúožìœ¶yÉwWöÙµFœl·Ü¸S€,aŒæ¿. ‡€]‘:‰q;kNP‘ÜÉ4‚G!2?r²ËZÖSª<˜bè¶ñBÃôü==лi¿Hp‹Õ·í1Œ#Á–ºx/“&†ÝATeÅíp£r—óP¾Åýáš~mì]ÚàMÒ¨K"~{à5JnýÊBYaIõÒs´ŸØïyü9z  þc90f®@o¸<óH¡J˜ôe¤y‘‚±£þxPÛÕ¯=-t7¬É}œ[ÓÔu=ÜsV,÷Æn¼,½ áÿQ°·Ï™©YÈ4Ðæ Ÿ±„^}\Ysš€«kˆUæ³ÐŽàéAu¤Är¡ÊdT ‹ öÞÀ1¬˜•h÷  ”Ú@SñÙQj乺  ˆW{-_m¤¿SÍë¡Ôð»Ùé©â{…8[-ó;³¶¥k@Vï¯Îã!ï­J\ð꥜Žybò¢ä‡hÓN*i õ(ÞòÎ×x­ß$–ÿ༗)"ß)ÚÕ¦2ôߘ.&Àì¯]NTØj\Ú8«’2´0I¹‹„²(åCeTî›f»!çÆƒØ|å×"Çk'ë!&ùO3¿ñl&®Æ4•FçÇCXꉉÆ\)¨U Ëò/ƒ„{÷‚üQ’>ñÂX´c@µB8±3÷ EK~<wøt?C+qãÖYsG> ç¦^vLM®ml™¢²ª/¢¤xQ¦c5ìzŠ#7‚ÈŽoiZGú†åcÝn%$ò”KW¾L±Eî›Ë£>`Ì’<RUFif­Gι «îJ}‡vë•>3^|§öRp56%tÑ%Àzg ð¸¼;°¢Û)aþ#åÀ2½ÄŸbÓø”‹l…OumÒ¥z KÈ´ÄZÁhê+žÑ0ûud¯Cû³ƒ¦ïtè†ѵL7.9›5ˬŠÖÝv“ F•Á~‰[IgŠÅͧõ¥ež†¸çRš°õÎ^pvAÑÞ Ï`ð(I—_©ÈùH8nÃÖ«“ˆ—HšÍ”é×gÌ?ÂV°wŽÜºoqÝó»gø+èÊMNORDö“ â탄…áÄ?1–+²`6ùý[¬DÛ·EŸŠ‘®jª€êVÃé’$£Íä Åë*_ ­Ãž›–0.ÌØb*71:DB™$%M`Ò½ãæÐ4û|XrÔ™;*(…ä6fE-ÿ:j/ 6 ¼ßôÕ'ǾO|Çdèø× ¨],'ºùʶŒDú¾ÁW :³áâ¹ÏhÛÉ3‡¡La}Ô'"Âqâwµí#ŒAÙÌÓÞ¨©_9(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm16 bits gray2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel48 bits color4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A3A4A5A5 landscapeA5 portraitA6ADFADF BackADF DuplexADF FrontADF ModeADF cover openADF jamAccess to resource has been deniedAddition of space in bottom positionAddition of space in top positionAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic threshold modeAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisB4B5B6BackBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowCancel buttonChange Document.Change documentChanges intensity of midtonesChannelCheckChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCrop actual image areaCustomCustom color matrix for grayscale scans.Custom color matrix.DTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetect stapled documentDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart.Disable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Do not stop after double feed detectionDocument FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDouble feed detectionDouble feed detector sensitivityDouble letter 11x17 inDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/Disable double feed detectionEnable/Disable length control modeEnable/Disable long paper modeEnable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEnhance BlueEnhance GreenEnhance RedEnhanced modeEnhancementError DiffusionError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFit to pageFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom scannerFrom white stickFrontFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma function exponentGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHigh sensivityHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationIgnore center double feed sensorIgnore left double feed sensorIgnore right double feed sensorImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInk-jet printersInt test optionsInvalid argumentInverse ImageInverse image in B/W modeInverse image in B/W or halftone modeInvert endiannessIt is right and left reversingJPEGJPEG Image Compression with Q parameter, '0' - no compressionJPEG compressionJPEG compression (yours application must be able to uncompress)Lamp colorLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off during scanLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLandscapeLegalLength Control Mode is a mode that the scanner reads up to the shorter length of actual paper or logical document length.Length control modeLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Long Paper Mode is a mode that the scanner reads the image after it divides long paper by the length which is set in Document Size option.Long paper modeLoss of pixels per lineLowLow density printingLow sensivityManual feed modeManual feed timeoutManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMaximum diameter of lone dots to remove from scanMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image (left/right flip)Mirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative colorNegative filmNegative film typeNegative grayNegativesNo CorrectionNo detectionNo transparency correctionNoise reductionNoneNormalNormal modeNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryPDF buttonPage heightPage loadedPage widthPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request backend to remove border from pages digitallyRequest driver to detect and correct 90 degree image rotationRequest driver to discard pages with low numbers of dark pixelsRequest driver to remove border from pages digitallyRequest driver to rotate pages by a fixed amountRequest driver to rotate skewed pages digitallyRequest that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readRotate image clockwiseSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner automatically detect image area and crop itScanner cover is openScanner mechanism locked for transportScanner modelScanner sensors and buttonsScanner shrinks image to fit scanned pageScanner will be stop when a paper have been skewedSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSet chroma of blueSet chroma of redSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet paper position : true for landscape, false for portraitSet sharpening value.Set the double feed detector sensitivitySet the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the automatic threshold modeSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the lamp color (color dropout)Sets the manual feed modeSets the manual feed timeout in secondsSets the resolution of the scanned image.Sets the scan sourceSets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkew adjustmentSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSoftware automatic croppingSoftware blank skip percentageSoftware cropSoftware derotateSoftware deskewSoftware despeckle diameterSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Speedup sensorStandardStart calibration process.Start calibration using special sheetStatus Code SimulationStopStop scanner when a paper have been skewedString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesTPU8x10Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The lamp will be turned off during scan. The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomadfbayer_16bayer_64bluebusiness_cardbwchroma of bluechroma of redcolorcommand sequence errorcontinuouscrtdarkdefaultdiffusionerr_diffusionfbfilm scannerfit-to-pageflatbed scannergraygreenhalftonehalftone_32halftone_64hardware check errorhighinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorjpeg compressionlamp failurelamp not stabilizedlightlinierlowmediummedium not presentno additional sense informationnonenormaloffoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetredreselect failurerounded parameterscan head positioning errorsheetfed scannersinglesmoothtimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNuser_defwait_docwait_doc_hopper_upwait_keywebcamProject-Id-Version: sane-backends 1.0.18 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2012-10-22 11:17+0200 Last-Translator: Mattias Ellert Language-Team: Swedish Language: sv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (1/1) Knapp(1/1) Knapptestinställning. Skriver ut lite text...(1/3) BrÃ¥ktal(1/3) BrÃ¥ktalstestinställning utan enhet och utan villkor.(1/3) Sträng(1/3) Strängtestinställning utan villkor.(1/6) Boolesk mjukvaruvald mjukvarudetekterad(1/6) Boolesk testinställning som är mjukvaruvald och mjukvarudetekterad (och avancerad). Detta är en normal Boolesk inställning.(1/6) Heltal(1/6) Heltalstestinställning utan enhet och utan villkor.(2/3) BrÃ¥ktal intervallvillkor(2/3) BrÃ¥ktalstestinställning med enheten mikrosekunder och intervallvillkor. Minimum är -42.17, maximum är 32767.9999 och steglängden är 2.0.(2/3) Sträng stränglistevillkor(2/3) Strängtestinställning med stränglistevillkor.(2/6) Boolesk hÃ¥rdvaruvald mjukvarudetekterad(2/6) Boolesk testinställning som är hÃ¥rdvaruvald och mjukvarudetekterad (och avancerad). Det betyder att inställningen inte kan ställas in av framplanet, men av användaren (t.ex. genom att trycka pÃ¥ en knapp pÃ¥ enheten).(2/6) Heltal intervallvillkor(2/6) Heltalstestinställning med enheten pixlar och ett intervallvillkor. Minimum är 4, maximum 192 och steglängden är 2.(3/3) BrÃ¥ktal listvillkor(3/3) BrÃ¥ktalstestinställning utan enhet med listvillkor.(3/3) Sträng stränglistevillkor (lÃ¥ng lista)(3/3) Strängtestinställning med stränglistevillkor. InnehÃ¥ller nÃ¥gra fler punkter...(3/6) Boolesk hÃ¥rdvaruvald(3/6) Boolesk testinställning som är hÃ¥rdvaruvald (och avancerad). Det betyder att inställningen inte kan ställas in av framplanet, men av användaren (t.ex. genom att trycka pÃ¥ en knapp pÃ¥ enheten) och att den inte kan läsas av framplanet.(3/6) Heltal listvillkor(3/6) Heltalstestinställning med enheten bitar och ett listvillkor.(4/6) Boolesk mjukvarudetekterad(4/6) Boolesk testinställning som är mjukvarudetekterad (och avancerad). Detta betyder att inställningen är skrivskyddad.(4/6) Heltalsvektor(4/6) Heltalsvektorstestinställning med enheten mm utan villkor.(5/6) Boolesk mjukvaruvald mjukvarudetekterad emulerad(5/6) Boolesk testinställning som är mjukvaruvald, mjukvarudetekterad och emulerad (och avancerad).(5/6) Heltalsvektor intervallvillkor(5/6) Heltalsvektorstestinställning med enheten punkter per tum och intervallvillkor. Minimum är 4, maximum 192 och steglängden är 2.(6/6) Boolesk mjukvaruvald mjukvarudetekterad automatisk(6/6) Boolesk testinställning som är mjukvaruvald, mjukvarudetekterad och automatisk (och avancerad). Denna inställning kan ställas in automatiskt av bakplanet.(6/6) Heltalsvektor listvillkor(6/6) Heltalsvektorstestinställning med enheten procent och listvillkor.1/2 av normal hastighet1/3 av normal hastighet10 mm15 mm16 bitars grÃ¥skala2 pixlar20 mm2x2 användardefinierat2x2 normalt3x3 användardefinierat3x3 normalt4 pixlar48 bitars färg4x4 grovt4x4 användardefinierat4x4 fint4x4 normalt5x5 grovt5x5 användardefinierat5x5 fint6x4 (tum)6x6 användardefinierat6x6 normalt8 bitars utdata8 pixlar8,5x11 (tum)8x10 (tum)8x8 Bayer8x8 grov förtjockning8x8 fin förtjockning8x8 lodrät linje8x8 grovt8x8 användardefinierat8x8 fint8x8 normalt8x8 mycket fintEn längre exponeringstid lÃ¥ter bildläsaren samla in mer ljus. Föreslagen användning är 175% för fotografier, 150% för diapositiv och "Negativ" för negativ film. För mörka (underexponerade) bilder kan du öka detta värde.A3A4A5A5 liggandeA5 stÃ¥endeA6Automatisk dokumentmatareAutomatisk dokumentmatare baksidaAutomatisk dokumentmatare dubbelsidigtAutomatisk dokumentmatare framsidaDokumentmatarlägeautomatiska dokumentmatarens lock är öppetstopp i den automatiska dokumentmatarenTillträde till resursen har förvägratsLägg till utrymme nedanför bildenLägg till utrymme ovanför bildenLägger till till blÃ¥tt beroende pÃ¥ grönnivÃ¥nLägger till till blÃ¥tt beroende pÃ¥ rödnivÃ¥nLägger till till grönt beroende pÃ¥ blÃ¥nivÃ¥nLägger till till grönt beroende pÃ¥ rödnivÃ¥nLägger till till rött beroende pÃ¥ blÃ¥nivÃ¥nLägger till till rött beroende pÃ¥ grönnivÃ¥nAvanceratAvancerade inställningarEfter att ha skickat inläsningskommandot, vänta tills knappen pÃ¥ läsaren trycks in för att starta inläsningen.Alla sidorStäng alltid av lampan när mörkerkalibrering görsAnalog förstärkningAnalogt framplanAnalogt gamma blÃ¥ttAnalog gammakorrigeringAnalogt gamma gröntAnalogt gamma röttAnalog gammakorrigeringAnalog gammakorrigering för blÃ¥ttAnalog gammakorrigering för gröntAnalog gammakorrigering för röttAutomatisktAutomatiskt tröskelvärdeAutomatisk ytuppdelningMata ut automatisktAutomatisk exponeringstidAutofokusAutofokusera endast en gÃ¥ngAutomatiskAutomatisk dokumentmatareAutomatisk inställning av tröskelvärdeAutomatisk separeringAutomatiskt tröskelvärdeAutomatiskt tröskellägeAutomatisk uppvärmningMata ut filmen frÃ¥n enheten efter varje inläsning automatisktMata ut filmen frÃ¥n enheten automatiskt före programmet avslutasStäller in ljusstyrka, kontrast, vitnivÃ¥, gamma, brusreduktion och bildton automatisktB4B5B6BaksidaBakspÃ¥rningslinjerBalanseringsfaktor för blÃ¥tt. 100% betyder ingen korrigering.Balanseringsfaktor för grönt. 100% betyder ingen korrigering.Balanseringsfaktor för rött. 100% betyder ingen korrigering.FackBayerBayergitter 16Bayergitter 64TvÃ¥nivÃ¥-svart-vit (streckteckningsläge)Koppla RGBKoppla X- och Y-upplösningKoppla analogt gammaKoppla gammaBitdjupSvartSvartnivÃ¥BlÃ¥BlÃ¥ färgbalansBlÃ¥ ljusstyrkaBlÃ¥ förstärkningDet analoga framplanets blÃ¥förstärkningsvärdeBlÃ¥ intensitetBlÃ¥ lampa avBlÃ¥ offsetDet analoga framplanets blÃ¥offsetsvärdeBooleska testinställningarNerifrÃ¥n och uppHögerHöger kant av inläsningsytan.NedreNedre kant av inläsningsytan.LjusstyrkaInbyggd CCT-profilKnapp 1Knapp 2KnapplägeKnapptestinställningarKnappkontrollerad inläsningKnapparCDCPU-kontrollfelBildskärmBildskärmar (CRT)KalibreringsexponeringstidKalibreringsexponeringstid för blÃ¥ttKalibreringsexponeringstid för gröntKalibreringsexponeringstid för röttKalibreringslampdensitetKalibreraKalibrera bildläsarenKalibrera före nästa inläsningKalibrera linsens fokus i dokumentets lägeKalibrerar för svart- och vitnivÃ¥.KalibreringBakplanskalibreringKalibreringsdatacacheKalibreringslägeKalibrera nuAvbrytknappByt dokument.Byt dokumentÄndrar intensitet hos mellantonerKanalCheckChipset-IDChipsetsnamnRensa kalibreringRensa kalibreringsdatacacheGrovtGrovkalibreringGrovkalibrering endast för första inläsningenGrovkalibrering görs endast för första inläsningen. Fungerar för de flesta bildläsare och kan spara tid. Välj inte denna inställning om bildens ljusstyrka är olika för varje inläsning. Endast för test.FärgFärg (48 bitar)Färg 36FärgrasterFärgstreckteckningFärgmatrisFärg RAWFärg RGBFärg RGB TEXTFärgbalansInställningar för färgkanalernas förstärkningInställningar för färgkanalernas offsetFärgkorrigeringFärgkorrigeringskoefficienterFärgmönsterFärg 24Färg 36Färg 48Färglinjer per inläsningVillkorligFortsättKontrastKontrast blÃ¥ kanalKontrast grön kanalKontrast röd kanalBestämmer blÃ¥nivÃ¥nBestämmer grönnivÃ¥nBestämmer rödnivÃ¥nBestämmer "nyansen" (blÃ¥nivÃ¥n) pÃ¥ den inhämtade bilden.Bestämmer ljusstyrkan för den inlästa bilden.Bestämmer ljusstyrkan för den blÃ¥ kanalen i den inlästa bilden.Bestämmer ljusstyrkan för den gröna kanalen i den inlästa bilden.Bestämmer ljusstyrkan för den röda kanalen i den inlästa bilden.Bestämmer kontrasten för den inlästa bilden.Bestämmer kontrasten för den blÃ¥ kanalen i den inlästa bilden.Bestämmer kontrasten för den gröna kanalen i den inlästa bilden.Bestämmer kontrasten för den röda kanalen i den inlästa bilden.Bestämmer ifall bakspÃ¥rning används.KopieringsknappKorrigering beroende pÃ¥ filmtypKorrigering beroende pÃ¥ genomlysningskvotLocket öppetBeskär verklig bildareaAnvändardefinieratAnvändardefinierad färgmatris för grÃ¥skaleinläsningar.Användardefinierad färgmatris.DTCDebuggningsinställningarStandardStandardvärdenDefiniera kalibreringslägeAnge exponeringstid för blÃ¥ kalibreringAnge exponeringstid för blÃ¥ inläsningAnge exponeringstid för kalibreringAnge exponeringstid för grön kalibreringAnge exponeringstid för grön inläsningAnge exponeringstid för röd kalibreringAnge exponeringstid för röd inläsningAnge exponeringstid för inläsningAnge lampdensitet för kalibreringAnge lampdensitet för inläsningDefinierar blÃ¥-lampa-av-parameterDefinierar grön-lampa-av-parameterDefinierar röd-lampa-av-parameterAnger rastermönster (gitter) för inläsning av rastrerade bilder.Anger zoom-faktorn som bildläsaren kommer att användaFördröj överföringen av data.DensitetsinställningDetektera häftade dokumentBestämmer hastigheten med vilken inläsningen sker.Bestämmer ifall en inbyggd eller användardefinierad gammatabell skall användas.Enheten upptagenEnhetsinställningarDiamantDiffusionStäng av den automatiska dokumentmataren och använd endast flatbäddenStäng av bakspÃ¥rningAvaktivera dynamisk streckteckningStäng av gammakorrigeringStäng av interpoleringStäng av förfokuseringStäng av användandet av en adaptiv algoritm i mjukvaran för att generera streckteckningsinläsningar för att i stället använda hÃ¥rdvarans streckteckningsinläsningsläge.Stäng av vit skuggkorrigeringUpplöst punkt 16x16Upplöst punkt 8x8Visa en kort lista med upplösningarGitterGitter A (4x4 Bayer)Gitter B (4x4 spiral)Gitter C (4x4 nätskärm)Gitter D (8x4 nätskärm)Gittrad/rastrerad svart-vit (rasterläge)Gitterkarta 1Gitterkarta 2Gör en grÃ¥skaleinläsning i stället för en färginläsningUtför en kvalitetsvitkalibreringAutofokusera endast en gÃ¥ng mellan utmatningarKalibrera inte fokusFramtvinga inte statuskodTvinga inte bakplanet att returnera en statuskod.Avbryt inte efter dubbelmatningsdetekteringDokumentmatareDokumentmatarinställningarStopp i dokumentmatarenSlut pÃ¥ dokument i dokumentmatarenDubbel optisk upplösningDubbelmatningsdetekteringDubbelmatningsdetektionskänslighetDubbelt US-Letter 11x17 tumNedladdat mönster ANedladdat mönster BBlindfärgDubbelsidigtDubbelsidig inläsningDubbelsidig inläsning läser in dokumentets framsida och baksidaLängd pÃ¥ läsfördröjningDynamisk tröskelkurva, frÃ¥n ljust till mörkt, vanligen 50-65Mata utMata ut dokument efter inläsningMata ut film efter varje inläsningMata ut filmen före avslutMata ut filmen nuMata ut filmen *nu*Mata ut bladet i dokumentmatarenE-postknappEmulera grÃ¥skalaSätt pÃ¥ dubbelsidig inläsningMöjliggör automatisk bestämning av tröskelvärde för streckteckningsinläsningar.Möjliggör val av exponeringstidMöjliggör val av lampdensitetAktivera testinställningarAktivera diverse testinställningar. Detta är till för att testa förmÃ¥gan hos framplan att visa och ändra de olika typerna av SANE-inställningar.Aktivera/avaktivera dubbelmatningsdetekteingAktivera/avaktivera läge för längdkontrollAktivera/avaktivera läge för lÃ¥ngt papperAktivera/avaktivera autofokusAktivera/avaktivera automatisk exponeringstidAktiverar eller deaktiverar kaliberingsdatacache.Aktiverar eller deaktiverar ökning av givarens rörelsehastighet.Filslut nÃ¥ttFramhäv blÃ¥ttFramhäv gröntFramhäv röttFörbättringslägeFörbättringFeldiffusionFel under enhets-I/OKastar om den högre och lägre byten i bilddata i 16-bitarslägen. Denna inställning kan användas för att testa 16-bitarslägen pÃ¥ framplan, dvs om framplanet använder rätt endianness.Genomför kalibrering *nu*ExperimentExponeringstidUtöka lampavstängningstidUtökar lampavstängningstiden (frÃ¥n 15 minuter till 1 timme)Extra snabbExtra färgjusteringarÖvrigtSnabbSnabbt grÃ¥skalelägeSnabb förhandsgranskningSnabbinläsningSnabbareSnabbastFaxknappDokumentmatarlägeFilknappFilnamnFilmtypFilmremsaFintFin färgFärgbalans frÃ¥n fast programvaraFörsta punktenAnpassa till sidaFast fokuseringspunktBrÃ¥ktalstestinställningarFlatbäddEndast flatbäddFokusFokusera 2,5 mm ovanför glasetFokuseringspunktFokusera pÃ¥ glasetAnvänd bakspÃ¥rningAnvänd monokrom förhandsgranskningAnvänd verkligt bitdjupUtför bildläsarkalibrering före inläsningTvinga bakplanet att returnera statuskoden SANE_STATUS_ACCESS_DENIED efter det att sane_read() har anropats.Tvinga bakplanet att returnera statuskoden SANE_STATUS_COVER_OPEN efter det att sane_read() har anropats.Tvinga bakplanet att returnera statuskoden SANE_STATUS_EOF efter det att sane_read() har anropats.Tvinga bakplanet att returnera statuskoden SANE_STATUS_IO_ERROR efter det att sane_read() har anropats.Tvinga bakplanet att returnera statuskoden SANE_STATUS_JAMMED efter det att sane_read() har anropats.Tvinga bakplanet att returnera statuskoden SANE_STATUS_NO_DOCS efter det att sane_read() har anropats.Tvinga bakplanet att returnera statuskoden SANE_STATUS_NO_MEM efter det att sane_read() har anropats.FrÃ¥n papperFrÃ¥n bildläsareFrÃ¥n kalibreringsradenFramsidaInvänta knapptryckFullständig inläsningOklara parametrarFörstärkingGammaGammakorrigeringGammatabellerGammakorrigeringGammakorrigering kommer att stängas avGammafunktionsexponentGammavärdeGammakorrigeringstabell för den blÃ¥ kanalen.Gammakorrigeringstabell för den gröna kanalen.Gammakorrigeringstabell för den röda kanalen.Gammakorrigeringstabell. I färgläge pÃ¥verkar denna inställning de röda, gröna och blÃ¥ kanalerna samtidigt (dvs det är en intensitetsgammatabell).GeometriGeometrigruppKornstorlekGrÃ¥GrÃ¥ förstärkningGrÃ¥lägesfärgGrÃ¥ offsetGrÃ¥ 16GrÃ¥ 8Gör grÃ¥4 bitars grÃ¥skala8 bitars grÃ¥skalaGrÃ¥skaleinläsningGrönGrön färgbalansGrön ljusstyrkaGrön förstärkningDet analoga framplanets grönförstärkningsvärdeGrön intensitetGrön lampa avGrön offsetDet analoga framplanets grönoffsetvärdeGrÃ¥skalelinjer per inläsningRutnätRasterRaster A (hÃ¥rt)Raster B (mjukt)Raster C (nätskärm)Rasterpunkt 32Rasterpunkt 64RastermönsterRastermönstersstorlekRastreringRastrering stöds inteHandbildläsarsimuleringHandbildläsarsimuleringInläsningsytans hÃ¥rdvaruinterna X-position.Inläsningsytans hÃ¥rdvaruinterna Y-position.HÃ¥rdvaruupplösningHÃ¥rdvaruspecifika inställningarHögUtskrift med hög kontrastUtskrift med hög densitetHög känsighetHögsta kvalitet men lägre hastighetHögsta hastighet men lägre kvalitetBelysningBelysning för blÃ¥ttBelysning för gröntBelysning för röttHÃ¥llarens fokuseringspunkt 0 mmVÃ¥grättVÃ¥grätt fetstilVÃ¥grätt smalLängden pÃ¥ fördröjningen efter varje databuffer som överförts.NyansOm Automatisk dokumentmatare valts kommer mataren att vara 'tom' efter 10 inläsningar.Om denna inställning är vald försöker bakplanet automatiskt bestämma ett optimalt tröskelvärde.Om denna inställning är vald utförs färgkalibreringen före en inläsning av bakplanetOm denna inställning är vald utför bildläsaren ingen bakspÃ¥rningOm aktiverad, kommer bilden att läsas in i färg för att sedan konverteras till grÃ¥skala av mjukvara. Detta kan förbättra bildkvaliteten under vissa omständigheter.Om denna inställning är vald utförs endast skuggkorrigering vid kalibrering. Standardvärden för förstärkning, offset och exponeringstid, endera inbyggda eller frÃ¥n konfigureringsfilen, kommer att användas.Om aktiverad kommer ett antal bilder inblandade i inläsningsprocesseringen att sparas för analys.Om denna inställning är vald kommer enheten att kalibreras före nästa inläsning. Annars utförs kalibrering endast före första inläsningen.Om gamma är aktiverat görs inläsningar alltid med 16 bitars djup för att förbättra bildkvaliteten för att sedan konvertera till det valda bitdjupet. Denna inställning undviker bitdjupsemulering.Ignorera kalibreringIgnorera mellersta dubbelmatningssensornIgnorera vänstra dubbelmatningssensornIgnorera högra dubbelmatningssensornBildBildförbättringBildens färger kommer att inverterasBildtonBildintensitetBildförändringsinställningarMatrisskrivareAnvänd samma värden för varje färg i RGB-lägeÖka eller minska CCD-sensorns analoga förstärkningInformationInfrarödBläckstrÃ¥leskrivareHeltalsinställningarOgiltigt argumentInverterad bildInvertera bilden i svart-vitt lägeInvertera bild i svart-vitt eller rasterlägeInvertera endiannessDen kastar om höger och vänsterJPEGJPEG-bildkomprimmering med Q-parameter, '0' - ingen komprimmeringJPEG-komprimmeringJPEG-komprimmering (din applikation mÃ¥ste kunna dekomprimmera)LampfärgLampan ej klar, vanligen försök igenLampa avLampa av vid avslutStäng av lampan under mörkerkalibreringStäng av lampan under inläsningLampavstängningstidLampavstängningstid (minuter)Lampa pÃ¥LampstatusLampavstängningstidLampavstängningstidLampavstängningstid i sekunder.LampströmbrytareLiggandeUS-LegalI längdkontrolläge läser bildläsaren upp till den kortare av verklig papperslängd och logisk dokumentlängd.LängdkontrollslägeKalibrera linsen i dokumentets lägeLÃ¥t oss se om framplan kan hantera dettaUS-LetterBegränsa mängden data som överförs vid varje anrop till sane_read().StreckteckningLäs in bilden som grÃ¥skalaI lÃ¥ngpappersläge läser bildläsaren in bilden efter att den delat upp lÃ¥nga papper i delar med en längd som angetts in dokumentstorleksparametrarna.Läge för lÃ¥nga papperPixelförlust per radLÃ¥gUtskrift med lÃ¥g densitetLÃ¥g känsighetManuell matningTimeout för manuell matningManuell fokuseringspunktManuell förfokuseringSlÃ¥r av/pÃ¥ lamp(an/orna) manuellt.Matrismultiplikation av RGBMaxMaximal diameter för ensamma prickar som tas bort frÃ¥n den inlästa bildenMediaMedelMediahanteringMittvärdeMittvärde för blÃ¥ttMittvärde för gröntMittvärde för röttAntal minuter innan lampan stängs av efter en inläsningSpegla vÃ¥grättSpegla bildSpegla bilden (vänster/höger)Spegla bilden vÃ¥grätt.Spegla bilden lodrätt.Spegla bilden vÃ¥grättSpegla bilden.Spegla lodrättDiverseLäge 1Läge 2Läge 3EnfärgsmatrisFlernivÃ¥-RGB-färg (enpass-färg)FlernivÃ¥-svart-vit (grÃ¥skaleläge)NTSC-grÃ¥NTSC-RGBBehöver kalibreringNegativNegativ filmDianegativNegativ färgNegativ filmNegativfilmtypNegativ grÃ¥skalaNegativIngen korrigeringIngen detekteringIngen genomlysningskorrigeringBrusreduceringIngetNormalNormallägeNormal hastighetAntal bitar per sampel, typiska värden är 1 för "streckteckningar" och 8 för flerbitinläsningar.Antal linjer inläsningshuvudet flyttar sig bakÃ¥t när bakspÃ¥rning sker. Detta händer när bildläsaren läser in fortare än datorn kan ta emot data. LÃ¥ga värden ger snabbare inläsningar men ökar risken för att utelämna linjer.Antal inställningsvärdenAntal inläsningslinjer som skall begäras vid en SCSI-läsning. Genom att ändra denna parameter kan du ställa in hastigheten med vilken data läses frÃ¥n bildläsaren under inläsningar. Om den sätts för lÃ¥g, kommer bildläsaren att behöva stanna med jämna mellanrum under inläsningen. Om den sätts för hög kan X-baserade framplan sluta svara pÃ¥ X-händelser och ditt system kan gÃ¥ ned.Bildruta att läsa inOptisk teckenigenkännings-knappAvErbjud en select file descriptor för att detektera om sane_read() kommer att returnera data.Erbjud en select file descriptorOffsetPÃ¥En sidaUtför endast skuggkorrigeringKommandot ej understöttKommandot avbrötsTillvalsutrustningSlut pÃ¥ minnePDF-knappSidans höjdSida laddadSidans breddPappersstorlekOförändratGenomför bildläsarsjälvdiagnosUtför kalibreringVerklig storlek pÃ¥ papperet i den automatiska dokumentmatarenPositivPositiv filmDiapositivPositiv eller negativ filmPÃ¥slagningsknappFördefinierade inställningarFörhandsgranskningFörhandsgranskningslägeFotografiSkriv ut en lista med alla inställningar.Skriv ut inställningarGer standardinläsningsytor för fotografier, tryckta sidor och liknande.KvalitetskalibreringKvalitetsinläsningSnabbformateraRAM-kontrollfelROM-kontrollfelSlumpvistRÃ¥LäsfördröjningLäsbegränsningSkrivskyddad testinställningSkrivskyddat värde som anger hur mÃ¥nga parametrar en specifik enhet stödjer.RödRöd färgbalansRöd ljusstyrkaRöd förstärkningDet analoga framplanets rödförstärkningsvärdeRöd intensitetRöd lampa avRöd offsetDet analoga framplanets rödoffsetvärdeMinska bruset frÃ¥n isolerade punkterSpeglandeBegär en inläsning i förhandsgranskningskvalitet.Begär att drivrutinen tar bort ram frÃ¥n sidor automatisktBegär att drivrutinen detekterar och korrigerar 90 graders bildrotationBegär att drivrutinen hoppar över sidor med fÃ¥ mörka pixlarBegär att drivrutinen tar bort ramar frÃ¥n sidor auomatisktBegär att drivrutinen roterar sidor med ett fixt värdeBegär att drivrutinen linjerar upp sneda sidor digitaltBegär att alla förhandsgranskningar görs i monokromt läge. PÃ¥ en trepassläsare sÃ¥ begränsar det antalet pass till ett och pÃ¥ en enpassläsare sÃ¥ reduceras bÃ¥de minnesÃ¥tgÃ¥ng och inläsningstid för en förhandsgranskning.Begär att alla förhandsgranskningar görs i det snabbaste (lÃ¥gkvalitets-)läget. Detta kan vara en icke-färginläsning eller en lÃ¥gupplösningsinläsning.Ã…terställ chipsetÃ…terställ bildläsareÃ…terställ bildläsarenÃ…terställer chipsetdataReturnera SANE_STATUS_ACCESS_DENIEDReturnera SANE_STATUS_COVER_OPENReturnera SANE_STATUS_EOFReturnera SANE_STATUS_IO_ERRORReturnera SANE_STATUS_JAMMEDReturnera SANE_STATUS_NO_DOCSReturnera SANE_STATUS_NO_MEMReturnera oklara lines och bytes_per_line när sane_parameters() anropas före sane_start().Returvärde för sane_readRotera bilden medursSCSI-paritetsfelSDTCMättnadSpara debuggningsbilderSkalärt gammaSkalärt gamma blÃ¥ttSkalärt gamma gröntSkalärt gamma röttBildläsarlägeBildläsarlägesgruppInläsningsomrÃ¥des- och orginalstorleksinställningarInläsningsknappInläsningsräknareInläsningsexponeringstidInläsningsexponeringstid för blÃ¥ttInläsningsexponeringstid för gröntInläsningsexponeringstid för röttLäs in i snabbt grÃ¥skaleläge (lägre kvalitet).InläsningslampdensitetInläsningsmarginalerBildläsarlägeUpplösningBildläsarkällaInläsningshastighetLäs in hela inläsningsytan inklusive kalibreringsraden. Var försiktig. Välj inte för stor höjd. Endast för test.Bildläsaren detecterar automatiskt verklig bildarea och beskär denBildläsarens lock är öppetBildläsaren lÃ¥st för transportBildläsarmodelBildläsarsensorer och -knapparBildläsaren krymper sidan för att rymmas pÃ¥ den inlästa sidanStoppa bildläsaren när ett papper har inmatats snettAndra punktenVälj fack att läsa in frÃ¥nVälj filmtypVälj minsta ljusstyrkan för att fÃ¥ en vitpunktVälj utjämningsfilter.Välj filmtypVäljer typ av testbild. Möjliga val: Helsvart: fyller hela bilden med svart. Helvit: fyller hela bilden med vitt. Färgmönster: ritar olika testfärgmönster beroende pÃ¥ bildläsarläget. Rutnät: ritar ett svart-vitt rutnät med en bredd och höjd pÃ¥ 10 mm per ruta.Välj förhandsgranskningsläge. GrÃ¥skaleförhandsgranskningar ger oftast den bästa kombinationen av hastighet och detaljrikedom.Väljer returvärde för sane_read(). "Standard" är den normala hantering för inläsning. Alla andra statuskoder är till för att testa hur framplanet hanterar dem.Välj testbildVäljer värde för skalär gammakorrigering (blÃ¥ kanal)Väljer värde för skalär gammakorrigering (grön kanal)Väljer värde för skalär gammakorrigering (röd kanal)Väljer värde för skalär gammakorrigering.Väljer "kornigheten" för den inlästa bilden. Mindre värden ger skarpare bilder.Väljer läge för den automatiska dokumentmataren (enkelsidigt/dubbelsidigt)Väljer ljusstyrka.Väljer färgkanal, "Master" betyder att alla färgkanaler pÃ¥verkas.Väljer blindfärg.Väljer filmtyp, t.ex. negativ eller diapositivVäljer gammakorrigerad överföringskurvaVäljer gammakorrigeringsläge.Väljer gammakorrigeringsvärdet frÃ¥n en lista av fördefinierade enheter eller en användardefinierad tabell som kan laddas ner till bildläsarenVäljer raster.Väljer negativfilmtypVäljer numret pÃ¥ den bildruta som ska läsas inVäljer inläsningsläge (t.ex. streckteckning, monokrom eller färg).Väljer inläsningskälla (som t.ex. en dokumentmatare).Väljer inläsningskälla (som t.ex. dokumentmatare). Välj källa före läge och upplösning. Ã…terställer läge och upplösning till förvalsvärden.Väljer vilken blÃ¥ strÃ¥lglansnivÃ¥ som skall tolkas som "svart".Väljer vilken blÃ¥ strÃ¥lglansnivÃ¥ som skall tolkas som "helt blÃ¥".Väljer vilken blÃ¥ strÃ¥lglansnivÃ¥ som skall tolkas som "vit".Väljer vilken grön strÃ¥lglansnivÃ¥ som skall tolkas som "svart".Väljer vilken grön strÃ¥lglansnivÃ¥ som skall tolkas som "helt grön".Väljer vilken grön strÃ¥lglansnivÃ¥ som skall tolkas som "vit".Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som "svart".Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som "vit".Väljer vilken röd strÃ¥lglansnivÃ¥ som skall tolkas som "svart".Väljer vilken röd strÃ¥lglansnivÃ¥ som skall tolkas som "helt röd".Väljer vilken röd strÃ¥lglansnivÃ¥ som skall tolkas som "vit".Väljer ifall den inlästa bilden skall rasteras (gittras).Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som "50% blÃ¥".Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som "50% grÃ¥".Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som "50% grön".Väljer vilken strÃ¥lglansnivÃ¥ som skall tolkas som "50% röd".Väljer vilken inläsningsfärg som används i grÃ¥läge (förval: grönt).SjälvdiagnosSensorerStäll in färgmättnad för blÃ¥ttStäll in färgmättnad för röttAnvänd standardvärden för förbättringsinställningar (ljusstyrka och kontrast).Använd standardvärden för förbättringsinställningar.Ställer in densitetsinställningslägeStäll in exponeringstidStäll in lampdensitetStäll in pappersläge: sant för liggande, falskt för stÃ¥endeStäller in skärpevärdet.Ställ in dubbelmatningsdetektionskänslighetenStäll in det optiska systemets fokuseringspunkt för hand (förval: 128).Ställ in ordningen för bildrutornaStäll in ordningen för bildrutorna i trepass-färgläge.Ställer in bildläsarens färgmatris.Ställer in tiden (i minuter) efter vilken lampan stängs av.Välj mediatyp.Sätter pÃ¥/av UTAStäller in den blÃ¥ kanalens förstärkningStäller in den blÃ¥ kanalens offsetStäller in den grÃ¥ kanalens förstärkningStäller in den grÃ¥ kanalens offsetStäller in den gröna kanalens förstärkningStäller in den gröna kanalens offsetSätt pÃ¥/av lampanStäller in den röda kanalens förstärkningStäller in den röda kanalens offsetVäljer automatiskt tröskellägeStäller in färgbalansvärdena till de värden som ges frÃ¥n den fasta programvaran.Ställer in färgkorrigeringstabellen för den valda utdataenheten.Ställer in dokumentmatarlägeStäller in fokuseringspunkten antingen pÃ¥ glaset eller 2,5 mm ovanför glasetStäller in gammavärdet för alla kanaler.Ställer in den horisontella upplösningen pÃ¥ den inlästa bilden.Ställer in bildtonStäller in lampfärg (blindfärg)Ställer in manuellt matningslägeStäller in timeout för manuell matning i sekunderStäller in upplösningen pÃ¥ den inlästa bilden.Väljer bildläsarkällaStäller in storleken pÃ¥ rastermönstret (gittret) som används vid inläsning av rastrerade bilder.Ställer in den vertikala upplösningen pÃ¥ den inlästa bilden.Ställ in förstärkning och offset för inläsning automatiskt. Om denna inställning inte är vald kan de analoga parametrarna ställas in för hand. Denna inställning är förvald som standard. Endast för test.SkuggaSkugga för blÃ¥ttSkugga för gröntSkugga för röttSkugga, mittvärde, belysning, exponeringstidSkärpaSkärpaSkifta blÃ¥ till grönSkifta blÃ¥ till rödSkifta grön till blÃ¥Skifta grön till rödSkifta röd till blÃ¥Skifta röd till grönKort lista med upplösningarVisar chipsetnamn använt i enheten.Visar chipset-IDVisar antalet inläsningar som gjorts med bildläsarenSlÃ¥ av lampanSlÃ¥ av bildläsarlampan.EnkelsidigtSimulera en handbildläsare. Handbildläsare vet oftast inte bildhöjden i förväg. I stället returnerar de en höjd som är -1. Om denna inställning är vald kan man testa om ett framplan kan hantera detta pÃ¥ rätt sätt. Denna inställning ger ocksÃ¥ en fast bredd pÃ¥ 11 cm.Simulera en handbildläsare. Handbildläsare vet oftast inte bildhöjden i förväg. I stället returnerar de en höjd som är -1. Om denna inställning är vald kan man testa om ett framplan kan hantera detta pÃ¥ rätt sätt.Simulera en trepassbildläsare genom att returnera 3 separata bildrutor. För att retas returnerar den först grönt, sedan blÃ¥tt och sist rött.Simulera en trepassbildläsare. I färgläge överförs tre bildrutor.Storlek pÃ¥ läsbegränsningJustering för sned inmatningHoppa över uppvärmningsprocessenDiapositivDiapositivLÃ¥ngsamLÃ¥ngsammareLÃ¥ngsammastJämnUtjämningAutomatisk beskärning i mjukvaraProcentsats för hoppa över blanka sidorMjukvarubeskärningMjukvaruavroteraMjukvaruupplinjeringMjukvarufläckborttagningsdiameterHelsvartHelvitVal av bildkällaBildkälla, bildläsarläge och upplösningsinsällningarSpecialinställningarSpecialinställningarAnger höjden pÃ¥ orginalet.Anger bredden pÃ¥ orginalet. Nödvändigt för automatisk centrering av arkmatade inläsningar.Öka givarens hastighetStandardPÃ¥börja kalibreringsprocessen.PÃ¥börja kalibrering med specialarkStatuskodsimuleringAvslutaStoppa bildläsaren när ett papper har inmatats snettSträngtestinställningarOKKasta om svart och vitSlÃ¥ pÃ¥/av genomlysningsenheten (filmadapterenheten)Sätter pÃ¥ eller av lampan.TMA-negativTMA-positivTPU 8x10TextförbättringsteknikDen (största) mängd data som överförs vid varje anrop till sane_read().Filnamnet pÃ¥ bilden som skall läsas.Lampan kommer att stängas av efter den angivna tiden (i minuter). Värdet 0 betyder att lampan inte kommer att stängas av.Lampan kommer att stängas av under inläsningen.Antal pixlar som kastas i slutet av varje rad.MättnadsnivÃ¥n bestämmer mängden "blomning" som förekommer när man läser in en bild med kamera. Större värden ger mer blomning.Bildläsaren behöver kalibrering för nuvarande inställningarTermoskrivareDetta är den mycket lÃ¥nga tredje punkten. Kanske har framplanet nÃ¥gon idé om hur det skall visa denDenna inställing avspeglar en knapp pÃ¥ bildläsarens panelDenna inställing avspeglar status pÃ¥ en av bildläsarens knappar.Denna inställing avspeglar status pÃ¥ bildläsarens knappar.Denna inställning slÃ¥r av lampan pÃ¥ flatbäddsbildläsaren under en inläsningTrepassimuleringTrepassimuleringTröskelvärdeTröskelkurvaTröskelvärde för streckteckningslägeSlÃ¥ av eller pÃ¥ lampanSlÃ¥r av eller pÃ¥ flatbäddsbildläsarens lampaUppifrÃ¥n och nerVänsterVänster kant av inläsningsytan.ÖvreÖvre kant av inläsningsytan.SkrivfilmGenomlysningsadapterGenomlysningsenhetGenomlysningskvotGenomlysningsenhetStäng av lampanSlÃ¥ av lampan när programmet avslutasSlÃ¥ av bildläsarlampanSlÃ¥ pÃ¥ bildläsarlampanStänger av lampan omedelbart.UTA pÃ¥OkändMata utMata ut dokument.Mata ut media efter inläsningMatar ut media efter en inläsning.Uppdatera knapplägeUppdatera informationenUppdatera inställningsvärdenUppdatera inställningsvärden.Uppdaterar informationen om enhetenAnvänd 0 mm i stället för 0,6 mm för hÃ¥llarens fokuseringspunktAnvänd bildkomponeringAnvänd ett bitdjup större än 8 internt, men ge endast 8 bitars utdata.Använd användardefinierad gammatabellAnvänd lins som dubblar den optiska upplösningenAnvänd icke-blockerande IOAnvänd icke-blockerande IO för sane_read() om det stöds av framplanet.Använd endast hÃ¥rdvaruupplösningarAnvänd samma gammavärde för alla färgkanaler.Använd samma värde för bÃ¥de X- och Y-upplösningAnvänd lightlid-35 mm-adapternAnvändardefinieratAnvändardefinierat (gamma=1,0)Användardefinierat (gamma=1,8)Användardefinierad CCT-profilLodrättLodrätt fetstilVänta pÃ¥ knappVänta pÃ¥ knappVänta med inläsningen tills dess att knappen pÃ¥ frontpanelen trycks in.Vänta pÃ¥ knapp innan inläsningVärm upp tills lampans ljusstyrka är konstant i stället för att insistera pÃ¥ 40 sekunders uppvärmningstid.Värm upp tills lampans ljusstyrka är konstant i stället för att insistera pÃ¥ 60 sekunders uppvärmningstid.Värm upp lampaVärm upp lampan innan inläsningUppvärmningsprocessen kommer att stängas avUppvärmningstidUppvärmningstid i sekunder.Om denna inställning är vald kommer inläsningen inte att starta omedelbart. För att forsätta, tryck SCAN-knappen (för MP150) eller COLOR-knappen (för andra modeller). För att avbryta, tryck GRAY-knappen.När grÃ¥skala eller streckteckning används väljer denna inställning den använda färgen.När höga upplösningar används där den horisontella upplösningen är mindre än den vertikala upplösningen stänger detta av den horisontella interpoleringen.VitVitnivÃ¥VitnivÃ¥ för blÃ¥ttVitnivÃ¥ för gröntVitninÃ¥ för röttVit skuggkorrigering kommer att stängas avX-upplösningXPAXPA-grÃ¥XPA-RGBY-upplösningZoomadfBayer 16Bayer 64blÃ¥visitkorts/vBlÃ¥ färgmättnadRöd färgmättnadfärgkommandosekvensfelkontinuerligtbildskärmmörkstandarddiffusionFeldiffusionfbfilmbildläsareanpassa till sidaflatbäddsbildläsaregrÃ¥skalagrönrasterRaster 32Raster 64hÃ¥rdvarukontrollfelhögintitator upptäckte mottaget felmeddelandeogiltigt bit-IDENTIFY-meddelandeogiltig kommandooperationskodogiltigt fält i CDBogiltigt fält i parameterlistaogiltigt meddelande-feljpeg-komprimmeringlampfellampa ej stabiliseradljuslinjärlÃ¥gmedelmedia icke närvarandeingen ytterligare sense-informationingennormalavoffset Xoffset Yinställning inte anslutparameter ändrad av en annan initiatorparameterlistlängdsfelpÃ¥slagningsÃ¥terställning / bussenhetsÃ¥terställningrödÃ¥tervalsfelavrundad parameterinläsningshuvudspositioneringsfelarkmatad bildläsareensidigtjämntimeoutfelför mÃ¥nga fönster specificeradegenomlysningsenhetslampfelgenomlysningsenhetsinläsningshuvudspositioneringsfelgenomlysningsenhetsskuggningsfelokändostött LUNanvändardefinieratinvänta dokumentinvänta dokument "hopper"invänta knapptryckningwebbkamerasane-backends-1.0.27/po/nb.gmo0000664000175000017500000003041213110600540012731 00000000000000Þ•ËtÌ     *5 > IT ] h s~ ‡ • ¢!®Ð!ð 3 Sts} ñû  ",==>{<º'÷  )5 :G%V|%‹ ±¾ Ùåíô&.4 = K U_ n| «¹ÁÉÑÚð0EX_gpx%–¼Ûò 5H[a 𦠫 ¸ÂÉÑ Úäé 8 CM^ o{ „”›¡²ÃÒ Øæþ0Ppƒ”®¶¾Ûßô  &/*V ‹ ” ¢°ÀÅáê  %( N\d x… ‰• ¥ ±*¼"ç' 42,g”›«¼ ËÕë'7Nc'|¤ º!Å ç!ò 5K`(v.Ÿ&Î õ4D T` |ˆ³ ÇÔ Ýeê P! \!h! q!}!…! Ž!š! ¢!®! ·!Ã!Ë! Ú! æ!)ò!'"'D"'l"&”"(»"ä"kí" Y# d#(o#˜# ®#¹#FÏ#F$F]$*¤$ Ï$ Ù$ä$ é$ õ$$% (%$6% [%g% €%Œ%’%—%%¨%Î%Ô%Ý% ï% ù%& & &1& Q&_&h&q&z&ƒ&–&«&¾&Ö&ð&'''"'!*'(L'$u'š'®' É'×'ñ'(( (@( S(^(c( s(~(†(Ž(–(Ÿ(£(¾(Ñ(å( ) ))') 8)C)L)[)`)h)o)€)‘) ) §)µ)Í)Ò)ê)$*%'*M* e*s*|* ›* ¥*²*Ì*Ð*ç*ù*þ* + +&+)E+ o+y+ +Ž+ +¯+µ+Ë+Ó+ò+, , 2, @,K, a,o, t,€, , š,/¨,,Ø,-%"-0H-y-€--¢-²-»-Ù-ñ-÷-. ..&.=.Q.(m.–.©.%¸.Þ.%í.(/»ˆ2³4®}†Ç¨Æoz8~ i‚É-B„¹¿¤[¯¡”T¢—´b€IL•§Z«hÁʾ|–À‹W°…\yžŒ]!¼™ƒJPuÃ_se`nŸxUŽ7ËpVM¥vjq;.+¦œ‘0d<F&ªD½6kÈESC(X l') ,2x2 custom3x3 custom4x4 coarse4x4 custom4x4 fine5x5 coarse5x5 custom5x5 fine6x6 custom8x8 coarse8x8 custom8x8 fine8x8 very fineA5 landscapeA5 portraitAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAutoAuto area segmentationAuto ejectAutomaticAutomatic warmupBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.Bi-level black and white (lineart mode)Bit depthBlack levelBlueBlue balanceBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.Button stateCalibrate before next scanCalibrationChannelCoarseCoarse calibrationCoarse calibration for first scan onlyColorColor 36Color LineartColor RAWColor RGBColor RGB TEXTColor balanceColor correctionColor correction coefficientsColor patternColor24Color36Color48ContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelCustomDefaultDefaultsDiamondDisplay short resolution listDo a grayscale rather than color scanDo a quality white-calibrationDo not calibrate focusDo not force status codeDocument FeederDouble Optical ResolutionDownload pattern ADownload pattern BEjectEject document after scanningEject the sheet in the ADFEnhancementFastFast previewFast scanFasterFastestFilenameFilm typeFineFocus 2.5mm above glassFocus PositionFocus on glassForce monochrome previewFrom paperFull scanGamma CorrectionGamma correctionGamma valueGeometryGrain sizeGrayGray16Gray8Grayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceHand-Scanner SimulationHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityIgnore calibrationInk-jet printersLamp offLamp off at exitLamp onLineartLoad the image as grayscale.LowLow density printingManual pre focusMaxMediumMirror imageMirror the image.Multi-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNegativeNegative FilmNo CorrectionNoise reductionNoneNumber of the frame to scanOne pageOnly perform shading-correctionOptional equipmentPaper sizePhysical size of the paper in the ADFPositive FilmPreviewQuality calibrationQuality scanRedRed balanceScan resolutionScan sourceScan speedSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the number of the frame to scanSelects the scan source (such as a document-feeder).Set default values for enhancement controls.ShadowShadow for blueShadow for greenShadow for redSharpnessShort resolution listShut off scanner lamp.SlowSlowerSlowestSource SelectionSpecial optionsStatus Code SimulationSwap black and whiteText Enhanced TechnologyThe filename of the image to be loaded.Three-Pass SimulationTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.Turn off lamp when program exitsTurn off scanner lampTurn on scanner lampUse Image CompositionUse lens that doubles optical resolutionUse same gamma values for all colour channels.Use same values for X and Y resolutionUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)Wait for ButtonWait for buttonWarmup lampWarmup lamp before scanningWhite levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPA GrayY-resolutionProject-Id-Version: sane-backends 1.0.12 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-12-17 23:01+0100 Last-Translator: Sigurd Stordal Language-Team: Language: nb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2x2 valgfri3x3 valgfri4x4 grov4x4 valgfri4x4 fin5x5 grov5x5 valgfri5x5 fin6x6 valgfri8x8 grov8x8 valgfri8x8 fin8x8 veldig finA5 landskapA5 portrettLegger til blÃ¥tt basert pÃ¥ grønn-nivÃ¥Legger til blÃ¥tt basert pÃ¥ rød-nivÃ¥Legger til grønt basert pÃ¥ blÃ¥-nivÃ¥Legger til grønt basert pÃ¥ rød-nivÃ¥Legger til rødt basert pÃ¥ blÃ¥-nivÃ¥Legger til rødt basert pÃ¥ grønn-nivÃ¥AvansertEtter at kommandoen for skan er sendt, vent til skannerens knapp ertrykket før skanings prossesen startes.Alle siderAutomatiskAutomatisk oppdeling av areal i delarealAutomatisk utløsningAutomatiskAutomatisk oppvarmingBalansefaktor for blÃ¥tt. Med en verdi pÃ¥ 100% menes ingen korreksjonBalansefaktor for grønt. Med en verdi pÃ¥ 100% menes ingen korreksjonBalansefaktor for rødt. Med en verdi pÃ¥ 100 % menes ingen korreksjonTonivÃ¥ svart og hvitt (strektegningmodus)Bit dybdeSvartnivÃ¥BlÃ¥BlÃ¥balanseBunn-høyre xHøyre bunn x posisjon av skan-arealBunn-høyre yHøyre bunn y posisjon av skan-arealKnappstatusKalibrer før neste scanKalibreringKanalGrovGrov kalibreringGrov kalibrering kun for første skanFargeFarge 36FargestrektegningFarge RAWFarge RGBFarge RGB TEKSTFargebalanseFarge korreksjonFarge korreksjons koeffisienterFargemønsterFarge 24Farge 36Farge 48KontrastKontrast blÃ¥kanalKontrast grønnkanalKontrast rødkanalKontrollerer blÃ¥-nivÃ¥Kontrollerer grønn-nivÃ¥Kontrollerer rød-nivÃ¥ValgfriStandardStandardDiamantVis kort liste over oppløsningerGjør et grÃ¥skala heller enn farge scanForeta en kvalitets hvit-kalibreringIkke kalibrer fokusIkke fremtving status kodeDokumentmaterDobble Optisk OppløsningLast ned mønster ALast ned mønster BUtløsLøs ut dokoment etter skanningUtløs arket i ADFForbedringRaskRask forvisningRaskt skanRaskereRaskestFilnavnFilmtypeFinFokuser 2.5mm over glassetFokuseringposisjonFokuser pÃ¥ glassetFremtving enfarge forvisningFra papirFull skanGamma korreksjonGamma korreksjonGammaverdiGeometriKornstørrelseGrÃ¥GrÃ¥ 16GrÃ¥ 8GrÃ¥skala 4 bitsGrÃ¥skala 8 bitsGrÃ¥skala scanGrønnGrønnbalanseHÃ¥ndskanner simuleringHøyHøy kontrasts utskriftHøy densitets utskriftHøyest kvalitet men laver hastighetHøyest hastighet men lavest kvalitetSe bort fra kalibreringBlekkskrivereLampe avLampen slÃ¥s av ved avslutningLampe pÃ¥StrektegningLast bildet som grÃ¥skalaLavlav densitets utskriftManuell førfokusMaksMiddelsSpeilbildeSpeil bildetFlernivÃ¥ RGB farge (en omgangs farge)FlernivÃ¥ svart og hvitt (grÃ¥skalamodus)NTSC-grÃ¥NegativNegativ FilmIngen korrigeringStøyreduksjonIngenRammenummer Ã¥ skanneEn sideBare utfør skygge-korrigeringTilleggsutstyrPapirstørrelseFysisk størrelse av papir i ADFLysbilde FilmForvisningKvalitets kalibreringKvalitetsskanRødRødbalanseSkanoppløsningSkankildeSkanhastighetVelger den gamma korrigerte overførsels kurvenVelger mÃ¥ten Ã¥ foreta gamma korreksjon pÃ¥Velger rammenummer Ã¥ skanneVelger skan kilde (slik som arkmater)Velg standard verdier for kontroll av forbedringSkyggeSkygge for blÃ¥Skygge for grønnSkygge for rødSkarphetKort liste over oppløsningerSlÃ¥ av skanner lampen.TreigTreigereTreigestValg av kildeSpesielle valgStatus Kode SimuleringBytt svart og hvittTekst Fremhevings TeknologiFilnavnet pÃ¥ bildet som skal lastes oppTrepass simuleringTopp-venstre xvenstre topp x posisjon av skan-arealTopp-venstre yVenstre topp y posisjon av skan-arealSlÃ¥ av lampen nÃ¥r programmet avslutterSlÃ¥ av skanner lampenSlÃ¥ pÃ¥ skanner lampenBruk Bilde KomposisjonBruk linser som dobbler den optiske oppløsningenBruk samme gamma verdi for alle farge kanaleneBruk samme verdier for X og Y oppløsningBrukerdefinertBrukerdefinert (Gamma=1.0)Brukerdefinert (Gamma=1.8)Vent pÃ¥ knappenVent pÃ¥ knappenVarmopp lampeVarm opp lampen før skanningHvitnivÃ¥HvitnivÃ¥ for blÃ¥HvitnivÃ¥ for grønnHvitnivÃ¥ for rødX-oppløsningXPA-grÃ¥Y-oppløsningsane-backends-1.0.27/po/boldquot.sed0000664000175000017500000000033112775312262014172 00000000000000s/"\([^"]*\)"/“\1â€/g s/`\([^`']*\)'/‘\1’/g s/ '\([^`']*\)' / ‘\1’ /g s/ '\([^`']*\)'$/ ‘\1’/g s/^'\([^`']*\)' /‘\1’ /g s/“â€/""/g s/“/“/g s/â€/â€/g s/‘/‘/g s/’/’/g sane-backends-1.0.27/po/hu.po0000664000175000017500000037317213110600537012625 00000000000000# Hungarian translation for sane-backends # Copyright (C) 2011 SANE Project. # This file is distributed under the same license as the sane-backends package. # Gabor Sari , 2003, 2004. # Németh Tamás , 2011. msgid "" msgstr "" "Project-Id-Version: sane-backends\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2011-04-06 19:50+0200\n" "Last-Translator: Németh Tamás \n" "Language-Team: Hungarian \n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Ãltalános" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometria" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Haladó" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Haladó" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Szenzorok" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "ElÅ‘nézet" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Monokróm elÅ‘nézet" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Színmélység" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Szkennelési üzemmód" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Szkennelési sebesség" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Bal-felsÅ‘ x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Bal-felsÅ‘ y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Jobb-alsó x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Jobb-alsó y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Szkennelés felbontása" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X felbontás" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y felbontás" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Lapszélesség" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Lapmagasság" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Vörös intenzitás" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Zöld intenzitás" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Kék intenzitás" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "FényerÅ‘" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontraszt" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Szemcseméret" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Feketeszint" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Fehérszint" #: include/sane/saneopts.h:189 #, fuzzy, no-c-format msgid "White level for red" msgstr "Fehérszint" #: include/sane/saneopts.h:190 #, fuzzy, no-c-format msgid "White level for green" msgstr "Fehérszint" #: include/sane/saneopts.h:191 #, fuzzy, no-c-format msgid "White level for blue" msgstr "Fehérszint" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Ãrnyék" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Kiemelés" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Ãrnyalat" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Telítettség" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Fájlnév" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negatív" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Precíz beállítás" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Küszöb" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Szkennelés felbontása" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Speciális beállítások" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "" #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "" #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "" #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "A beolvasási terület bal-felsÅ‘ x pozíciója" #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "A beolvasási terület bal-felsÅ‘ y pozíciója" #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "A beolvasási terület jobb-alsó x pozíciója" #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "A beolvasási terület jobb-alsó y pozíciója" #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "" #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "" #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "" #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "" #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "" #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "" #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "" #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "" #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "A fekete és fehér felcserélése" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Szkennel gomb" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "Email gomb" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Fax gomb" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Másol gomb" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "PDF gomb" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Mégse gomb" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Oldal betöltve" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Fedél nyitás" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Színes" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Szürke" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Vonalas" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "A művelet nem támogatott" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "A művelet megszakítva" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Nincs elég memória" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Alapértelmezett" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "" #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibráció" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Kalibrálás a következÅ‘ szkennelés elÅ‘tt" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "" #: backend/avision.h:782 #, fuzzy, no-c-format msgid "Duplex scan" msgstr "Teljes szkennelés" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Szkenner kalibrálása" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Szürkeskálás szkennelés" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analóg erÅ‘sítés" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gamma korrekció" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Nyers" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, fuzzy, no-c-format msgid "No transparency correction" msgstr "ErÅ‘sítés korrekció" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, fuzzy, no-c-format msgid "Negatives" msgstr "Negatív" #: backend/canon.c:176 #, fuzzy, no-c-format msgid "Slides" msgstr "Lassabb" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automata" #: backend/canon.c:186 #, fuzzy, no-c-format msgid "Normal speed" msgstr "Normál" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "ismeretlen" #: backend/canon.c:378 #, fuzzy, no-c-format msgid "ADF jam" msgstr "ADF" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, fuzzy, no-c-format msgid "lamp failure" msgstr "Gamma érték" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, fuzzy, no-c-format msgid "film scanner" msgstr "lapolvasó" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "síkágyas lapolvasó" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Filmtípus" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, fuzzy, no-c-format msgid "Negative film type" msgstr "Negatív film" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Eszköz felbontása" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Kép tükrözése" #: backend/canon.c:1539 #, fuzzy, no-c-format msgid "Mirror the image horizontally" msgstr "A kép vízszintes tükrözése." #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "" #: backend/canon.c:1625 #, fuzzy, no-c-format msgid "Calibration now" msgstr "Kalibráció" #: backend/canon.c:1626 #, fuzzy, no-c-format msgid "Execute calibration *now*" msgstr "Precíz beállítás" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, fuzzy, no-c-format msgid "Reset scanner" msgstr "lapolvasó" #: backend/canon.c:1649 #, fuzzy, no-c-format msgid "Reset the scanner" msgstr "lapolvasó" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Csak síkágyas" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, fuzzy, no-c-format msgid "Transparency unit" msgstr "Ãtlátszó" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, fuzzy, no-c-format msgid "Negative film" msgstr "Negatív film" #: backend/canon.c:1740 #, fuzzy, no-c-format msgid "Positive or negative film" msgstr "Pozitív film" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, fuzzy, no-c-format msgid "Transparency ratio" msgstr "Ãtlátszó" #: backend/canon.c:1775 #, fuzzy, no-c-format msgid "Select film type" msgstr "Filmtípus" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Síkágyas" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Nyomtatás" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, no-c-format msgid "Card Duplex" msgstr "" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Vörös" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Zöld" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Kék" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Haladó" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Haladó" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Haladó" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Nincs" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatikus dokumentum adagoló" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Pozitív film" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negatív film" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Fókusz az üvegen" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Fókusz 2,5mm-el az üveg felett" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Nincs korrekció" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "HÅ‘nyomtató" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Tintasugaras nyomtató" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT monitor" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Alapértelmezett" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A% álló" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 fekvÅ‘" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Max" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr " Szkennelési üzemmód " #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "" #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Színkorrekció" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "" #: backend/epson.c:3110 #, fuzzy, no-c-format msgid "Controls blue level" msgstr "A kék csatorna kontrasztja" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Kép tükrözése." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Gyors elÅ‘nézet" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Nagyítás" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, fuzzy, no-c-format msgid "Positive Slide" msgstr "Pozitív film" #: backend/epson2.c:137 #, fuzzy, no-c-format msgid "Negative Slide" msgstr "Negatív film" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Be" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Ki" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "DTC" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "SDTC" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Fehérszint" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Feketeszint" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Folytatás" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Megállít" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10mm" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15mm" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20mm" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Vízszintes" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Vízszintes" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Vízszintes" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "FüggÅ‘leges" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "FüggÅ‘leges" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Nyomtatás" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, no-c-format msgid "Halftone type" msgstr "" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Finom beállítás" #: backend/fujitsu.c:3221 #, no-c-format msgid "Emphasis" msgstr "" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Telítettség" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "" #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Kép tükrözése" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "A kép vízszintes tükrözése." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Fehérszint" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "A kék csatorna kontrasztja" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Színmátrix" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Gamma érték" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Küszöb" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Zajszűrés" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Nincs korrekció" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Nincs korrekció" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "ElÅ‘nézeti mód" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Haladó" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Nincs korrekció" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, no-c-format msgid "Dropout color" msgstr "" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, no-c-format msgid "Buffer mode" msgstr "" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, no-c-format msgid "Off timer" msgstr "" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Teljes szkennelés" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "A zöld csatorna kontrasztja" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "A kék csatorna kontrasztja" #: backend/fujitsu.c:3980 #, fuzzy, no-c-format msgid "Low Memory" msgstr "Nincs elég memória" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Teljes szkennelés" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Haladó" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Zajszűrés" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, no-c-format msgid "A3 paper" msgstr "" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, no-c-format msgid "B4 paper" msgstr "" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, no-c-format msgid "A4 paper" msgstr "" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, no-c-format msgid "B5 paper" msgstr "" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, no-c-format msgid "Manual feed" msgstr "" #: backend/fujitsu.c:4453 #, no-c-format msgid "Manual feed selected" msgstr "" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "Eszköz felbontása" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Fehérszint" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Vörös intenzitás" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Teljes szkennelés" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, fuzzy, no-c-format msgid "Extras" msgstr "Extra gyors" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, fuzzy, no-c-format msgid "Disable interpolation" msgstr "Tesztbeállítások engedélyezése" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Színmátrix" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibráció" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Precíz beállítás" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Kalibráció" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Finom beállítás" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Fájl gomb" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "OCR gomb" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Email gomb" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Finom beállítás" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Gombok" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibrálás" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Kalibrálási folyamat indítása." #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Finom beállítás" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Finom beállítás" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr " Nyomkövetési beállítások " #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Teljes szkennelés" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Finom beállítás" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Finom beállítás csak az elsÅ‘ szkeneléskor" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gamma érték" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "" #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "Geometria" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, fuzzy, no-c-format msgid "Scan Mode Group" msgstr " Szkennelési üzemmód " #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Szkennelési üzemmód" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "Gamma korrekció" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "Gamma korrekció" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "Szürkeárnyalatos" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Információ" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Chipset név" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Ismeretlen" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr " Szkennelési üzemmód " #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Kép" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Egyéb" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "" #: backend/hp5400_sane.c:359 #, fuzzy, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "A beolvasási terület bal-felsÅ‘ x pozíciója" #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "" #: backend/hp5400_sane.c:369 #, fuzzy, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "A beolvasási terület bal-felsÅ‘ x pozíciója" #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Negatív" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "Színes 42/48" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "" #: backend/hp-option.c:2984 #, fuzzy, no-c-format msgid "Advanced Options" msgstr "Haladó" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Egyedi" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automatikus" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Lassú" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normál" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Gyors" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Extra gyors" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-pixel" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-pixel" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-pixel" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Nyomtatás" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "" #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "" #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "" #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "" #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "" #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Kalibrálási folyamat indítása." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "" #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Színmátrix" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "" #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Egyéni színmátrix." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "" #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Vízszintes tükrözés" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "A kép vízszintes tükrözése." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "FüggÅ‘leges tükrözés" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "A kép függÅ‘leges tükrözése." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "" #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "" #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Papír mérete" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 fekvÅ‘" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, no-c-format msgid "Manual feed timeout" msgstr "" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Színes" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Folytatás" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Ki" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normál" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Kiemelés" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "lapolvasó" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Alapértelmezett" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Lassú" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Közepes" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Vörös" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Zöld" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "lapolvasó" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, no-c-format msgid "Sets the manual feed mode" msgstr "" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Zajszűrés" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, no-c-format msgid "Lamp color" msgstr "" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "A kép függÅ‘leges tükrözése." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gamma korrekció" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, no-c-format msgid "High sensivity" msgstr "" #: backend/kvs40xx_opt.c:232 #, no-c-format msgid "Low sensivity" msgstr "" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Nincs korrekció" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normál" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Haladó" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, no-c-format msgid "Automatic threshold mode" msgstr "" #: backend/kvs40xx_opt.c:643 #, no-c-format msgid "Sets the automatic threshold mode" msgstr "" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "" #: backend/kvs40xx_opt.c:787 #, no-c-format msgid "chroma of blue" msgstr "" #: backend/kvs40xx_opt.c:788 #, no-c-format msgid "Set chroma of blue" msgstr "" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Gyémánt" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, fuzzy, no-c-format msgid "Gray gain" msgstr "Szürke" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, fuzzy, no-c-format msgid "Red gain" msgstr "Vörös balansz" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, fuzzy, no-c-format msgid "Sets red channel gain" msgstr "A vörös csatorna kontrasztja" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, fuzzy, no-c-format msgid "Green gain" msgstr "Zöld balansz" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, fuzzy, no-c-format msgid "Sets green channel gain" msgstr "A zöld csatorna kontrasztja" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, fuzzy, no-c-format msgid "Blue gain" msgstr "Kék balansz" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, fuzzy, no-c-format msgid "Sets blue channel gain" msgstr "A kék csatorna kontrasztja" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Mode 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Mode 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Mode 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Alacsony" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Közepes" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Magas" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Egy oldal" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Minden oldal" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Speciális beállítások" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "MinÅ‘ségi szkennelés" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "MinÅ‘ségi szkennelés alacsony sebességgel" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Gyors szkennelés" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Gyors sebesség alacsony minÅ‘séggel" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "" #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "" #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "" #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Csatorna" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "" #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Vörös balansz" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Zöld balansz" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Kék balansz" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Lassabb" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Lassú" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Gyors" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Gyorsabb" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "" #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "" #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Vörös fényerÅ‘" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "" #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Zöld fényerÅ‘" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "" #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Kék fényerÅ‘" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "" #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "A vörös csatorna kontrasztja" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "" #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "A zöld csatorna kontrasztja" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "" #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "A kék csatorna kontrasztja" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "" #: backend/mustek_usb2.c:105 #, fuzzy, no-c-format msgid "Color48" msgstr "Színes" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, fuzzy, no-c-format msgid "Color24" msgstr "Színes" #: backend/mustek_usb2.c:107 #, fuzzy, no-c-format msgid "Gray16" msgstr "Szürke" #: backend/mustek_usb2.c:108 #, fuzzy, no-c-format msgid "Gray8" msgstr "Szürke" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Pozitív" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Negatív film" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negatív" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Ãtlátszó" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "" #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Finom beállítás" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, fuzzy, no-c-format msgid "Calibration data cache" msgstr "Kalibráció" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "" #: backend/plustek.c:942 #, fuzzy, no-c-format msgid "Performs calibration" msgstr "Finom beállítás" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "" #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "" #: backend/plustek.c:995 #, fuzzy, no-c-format msgid "Analog frontend" msgstr "Analóg erÅ‘sítés" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Forrás kijelölése" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "" #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (inch)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (inch)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (inch)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, no-c-format msgid "Focus point for scanning." msgstr "" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "ElÅ‘nézeti mód" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "síkágyas lapolvasó" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, no-c-format msgid "Auto or manual focus" msgstr "" #: backend/snapscan-options.c:911 #, no-c-format msgid "Focus-point" msgstr "" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Fókusz az üvegen" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, fuzzy, no-c-format msgid "Color RAW" msgstr "Színes" #: backend/stv680.h:116 #, fuzzy, no-c-format msgid "Color RGB" msgstr "Színes" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Rács" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "ElsÅ‘ bejegyzés" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Második bejegyzés" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Kézi szkenner szimuláció" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "" #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Speciális beállítások" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "" #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "" #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Tesztbeállítások engedélyezése" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Nyomtatási beállítások" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "" #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "" #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "" #: backend/u12.c:149 #, fuzzy, no-c-format msgid "Color 36" msgstr "Színes" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "" #: backend/umax_pp.c:771 #, fuzzy, no-c-format msgid "Offset" msgstr "Ki" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "" #: backend/umax_pp.c:780 #, fuzzy, no-c-format msgid "Gray offset" msgstr "Szürke kontraszt" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "" #: backend/umax_pp.c:793 #, fuzzy, no-c-format msgid "Sets red channel offset" msgstr "A vörös csatorna kontrasztja" #: backend/umax_pp.c:805 #, fuzzy, no-c-format msgid "Sets green channel offset" msgstr "A zöld csatorna kontrasztja" #: backend/umax_pp.c:817 #, fuzzy, no-c-format msgid "Sets blue channel offset" msgstr "A kék csatorna kontrasztja" #, fuzzy #~ msgid "IPC mode" #~ msgstr "ElÅ‘nézeti mód" sane-backends-1.0.27/po/da.po0000664000175000017500000045204313110600533012564 00000000000000# translation of sane-backends.po to Danish # Oversættelse af sane-backends meddelelser til Dansk # Copyright (C) 2002 SANE Project. # Mogens Jaeger , 2004, 2005. msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.17\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-12-17 22:59+0100\n" "Last-Translator: Mogens Jaeger \n" "Language-Team: Danish \n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.10\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Poedit-Language: Danish\n" "X-Poedit-Country: DENMARK\n" "X-Poedit-SourceCharset: utf-8\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Antal af indstillingsmuligheder" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "SkanomrÃ¥de" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Forbedring" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Avanceret" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Smugkig" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Gennemtving monokrom smugkig" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bit dybde" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Skannertilstand" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Skanningshastighed" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Skanningskilde" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Gennemtving bagudrettet sporing" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Øverst-venstre x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Øverst-venstre y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Nederst-højre x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Nederst-højre y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Skanningsopløsning" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-opløsning" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-opløsning" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, fuzzy, no-c-format msgid "Page height" msgstr "Højlys" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Brug tilpasset gammatabel" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Billedeintensitet" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Rød intensitet" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Grøn intensitet" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "BlÃ¥ intensitet" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Lyshed" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Kornstørrelse" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Halvtone" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Sort niveau" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Hvid niveau" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Hvid niveau for rød" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Hvid niveau for grøn" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Hvid niveau for blÃ¥" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Skygge" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Skygge for rød" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Skygge for grøn" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Skygge for blÃ¥" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Højlys" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Højlys for rød" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Højlys for grøn" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Højlys for blÃ¥" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Farvetone" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Mætning" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Filnavn" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Halvtonemønster størrelse" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Halvtonemønster" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Sammenbind X- og Y-opløsning" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativ" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Kvalitetskalibrering" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Dobbelt optisk opløsning" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Sammenbind RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Tærskelværdi" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analog gammakorrektion" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analog gamma rød" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analog gamma grøn" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analog gamma blÃ¥" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Sammenbind analoge gammaværdier" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Varmer lampen op" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Kalibrér eksponeringstid" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Kalibrér eksponeringstid for rød" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Kalibrér eksponeringstid for grøn" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Kalibrér eksponeringstid for blÃ¥" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Eksponeringstid til skanning" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Eksponeringstid til skanning for rød" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Eksponeringstid til skanning for grøn" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Eksponeringstid til skanning for blÃ¥" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Fastsæt eksponeringstid" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Kalibrér lampe densitet" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Skanner lampe densitet" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Fastsæt lampe densitet" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lampe slukkes ved afslutning" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Skrivebeskyttet indstilling der specificerer hvor mange indstillinger en " "bestemt enhed understøtter." #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Kort opløsningsliste" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "Antal af indstillingsmuligheder" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Skanningsopløsning" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Forlang et skan i smugkigkvalitet." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Forlang at alle smugkig laves i monokrom tilstand. PÃ¥ en tre-gennemløbs " "skanner, reduceres antal gennemløb til et, og pÃ¥ en en-gennemløbs " "skanner reducerer det hukommelsesforbruget og tidsforbruget." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Antal bit pr. farve, typisk bruges værdien 1 for \"stregtegning\" og 8 " "for multibit skanninger." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Vælger skanningstilstand (f.eks. stregtegning, monokrom eller farve)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Fastlægger hastigheden for skanningen." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Vælger skanningskilde (som f.eks. en dokument-føder)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Fastsætter om bagudrettet sporing er gennemtvunget." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Øverste-venstre x position af skanomrÃ¥de." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Øverste-venstre y position af skanomrÃ¥de." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Nederste-højre x position af skanomrÃ¥de." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Nederste-højre y position af skanomrÃ¥de." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Fastsætter opløsningen af det skannede billede." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Fastsætter den vandrette opløsning af det skannede billede." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Fastsætter den lodrette opløsning af det skannede billede." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, fuzzy, no-c-format msgid "Specifies the height of the media." msgstr "Fastsætter opløsningen af det skannede billede." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Fastlægger om en indbygget eller en tilpasset gamma-tabel skal bruges." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Gamma korrektionstabel. I farve tilstand pÃ¥virker denne indstilling de " "røde, blÃ¥ og grønne kanaler ens (dvs., der er en intensitets gammatabel)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Gamma korrektionstabel for rød kanal." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Gamma korrektionstabel for grøn kanal." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Gamma korrektionstabel for blÃ¥ kanal." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Fastsætter lyshed for det rekvirerede billede." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Fastsætter kontrast for det rekvirerede billede." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Vælger \"kornethed\" for det rekvirerede billede. Mindre værdier giver " "et skarpere billeder." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Vælger om det rekvirerede billede skal skannes i halvtoneindstilling " "(dithering)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Vælger hvilket glansniveau der skal anses for \"sort\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Vælger hvilket glansniveau der skal anses for \"hvid\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "Vælger hvilket rødt glansniveau der skal anses for \"hvidt\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "Vælger hvilket grønt glansniveau der skal anses for \"hvidt\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "Vælger hvilket blÃ¥t glansniveau der skal anses for \"hvidt\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "Vælger hvilket rødt glansniveau der skal anses for \"sort\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "Vælger hvilket grønt glansniveau der skal anses for \"sort\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "Vælger hvilket blÃ¥t glansniveau der skal anses for \"sort\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "Vælger hvilket rødt glansniveau der skal anses for \"helt rødt\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Vælger hvilket grønt glansniveau der skal anses for \"helt grønt\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "Vælger hvilket blÃ¥t glansniveau der skal anses for \"helt blÃ¥t\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Fastsætter farvetone (blÃ¥t niveau) for det rekvirerede billede." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Mætningsgraden styrer belysningen af ethvert enkeltbillede taget med et " "kamera. Højere værdier sørger for en stærkere belysning." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Filnavnet pÃ¥ det billede der skal hentes." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Fastsætter størrelsen pÃ¥ det halvtonegitter (dithering) der skal bruges " "ved skanning af halvtonebilleder." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Angiver det halvtonegitter (dithering) der skal anvendes ved skanning af " "halvtonebilleder." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Brug samme værdier for X og Y opløsning." #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Invertér farver, f.eks. byt om pÃ¥ sort og hvid." #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Foretag en kvalitets hvid-kalibrering." #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Brug linse, der fordobler den optiske opløsning." #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Anvend samme værdi for hver farve i RGB indstilling." #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Vælg minimum-lyshed, der skal betragtes som hvidt." #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analog gammakorrektion" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analog gammakorrektion for rød" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analog gammakorrektion for grøn" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analog gammakorrektion for blÃ¥" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Varm lampen op før skanning" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Angiv belysningstid for kalibrering" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Angiv belysningstid for kalibrering af rød farvedel" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Angiv belysningstid for kalibrering af grøn farvedel" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Angiv belysningstid for kalibrering af blÃ¥ farvedel" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Angiv belysningstid for skanning" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Angiv belysningstid for skanning af rød farvedel" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Angiv belysningstid for skanning af grøn farvedel" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Angiv belysningstid for skanning af blÃ¥ farvedel" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Aktiver valg af belysningstid" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Angiv lampe densitet for kalibrering" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Angiv lampe densitet for skanning" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Aktiver valg af lampe densitet" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Slukker for skannerens lampe, nÃ¥r programmet stoppes." #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Skanningsopløsning" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "Vent pÃ¥ knap" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "Vent pÃ¥ knap" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "Vent pÃ¥ knap" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Farvemønster" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Farve" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Farve stregtegning" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Farve halvtone" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "GrÃ¥tone" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Halvtone" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Stregtegning" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, fuzzy, no-c-format msgid "Operation not supported" msgstr "Halvtone er ikke understøttet" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "Dokument føder" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "Dokument føder" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Standard" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Anvend standardværdier for forbedringskontroller." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibrering" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Kalibrér før næste skanning" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Hvis denne indstilling er sat til, vil enheden blive kalibreret før " "næste scanning. Ellers foretages kalibreringen kun før første skanning." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Udfør kun skyggekorrektion" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Hvis aktiveret, bliver der kun gennemført skyggekorrektion under " "kalibreringen. Standardværdierne for forstærkning, forskydning og " "eksponeringstid, enten indbygget eller fra konfigurationsfilen, bliver " "brugt." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Knap tilstand" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Billednummer der skal skannes" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Vælger nummeret pÃ¥ det billede der skal skannes" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Duplex skan" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "Duplex skan, skanner begge sider af dokumentet" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Kalibrér skanner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Gennemtving kalibrering før skanning" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "GrÃ¥skalaskanning" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Udfør en grÃ¥skalaskanning fremfor en farveskanning" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analog forstærkning" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Forøg eller formindsk CCD sensorens analoge forstærkning" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gammakorrektion" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Vælger gammakorrigeret overføringskurve" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, fuzzy, no-c-format msgid "No transparency correction" msgstr "Farvekorrektion" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, fuzzy, no-c-format msgid "Negatives" msgstr "Negativ" #: backend/canon.c:176 #, fuzzy, no-c-format msgid "Slides" msgstr "Diapositiv" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatisk" #: backend/canon.c:186 #, fuzzy, no-c-format msgid "Normal speed" msgstr "Normal" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/2 normal speed" msgstr "2x2 normal" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/3 normal speed" msgstr "3x3 normal" #: backend/canon.c:365 #, fuzzy, no-c-format msgid "rounded parameter" msgstr "Uklare parametre" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "" #: backend/canon.c:378 #, fuzzy, no-c-format msgid "ADF jam" msgstr "ADF" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, fuzzy, no-c-format msgid "lamp failure" msgstr "Gamma værdi" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, fuzzy, no-c-format msgid "transparency unit lamp failure" msgstr "Filmenhed" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, fuzzy, no-c-format msgid "transparency unit shading error" msgstr "Filmenhed" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, fuzzy, no-c-format msgid "film scanner" msgstr "Flatbed skanner" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "Flatbed skanner" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Filmtype" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, fuzzy, no-c-format msgid "Negative film type" msgstr "Negativ film" #: backend/canon.c:1197 #, fuzzy, no-c-format msgid "Selects the negative film type" msgstr "Vælg testbillede" #: backend/canon.c:1236 #, fuzzy, no-c-format msgid "Hardware resolution" msgstr "Skanningsopløsning" #: backend/canon.c:1237 #, fuzzy, no-c-format msgid "Use only hardware resolutions" msgstr "Vis kort liste med mulige opløsninger" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, fuzzy, no-c-format msgid "Auto focus" msgstr "Automatisk skub ud" #: backend/canon.c:1329 #, fuzzy, no-c-format msgid "Enable/disable auto focus" msgstr "Deaktiver pre-fokusering" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, fuzzy, no-c-format msgid "Manual focus position" msgstr "Fast fokusposition" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Spejl billedet" #: backend/canon.c:1539 #, fuzzy, no-c-format msgid "Mirror the image horizontally" msgstr "Spejlvend billedet vandret." #: backend/canon.c:1608 #, fuzzy, no-c-format msgid "Auto exposure" msgstr "Fastsæt eksponeringstid" #: backend/canon.c:1609 #, fuzzy, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Aktiver valg af belysningstid" #: backend/canon.c:1625 #, fuzzy, no-c-format msgid "Calibration now" msgstr "Kalibrering" #: backend/canon.c:1626 #, fuzzy, no-c-format msgid "Execute calibration *now*" msgstr "Definer kalibreringstilstand" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, fuzzy, no-c-format msgid "Reset scanner" msgstr "arkføder skanner" #: backend/canon.c:1649 #, fuzzy, no-c-format msgid "Reset the scanner" msgstr "arkføder skanner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, fuzzy, no-c-format msgid "Eject film after each scan" msgstr "Skub dokumentet ud efter skanning" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, fuzzy, no-c-format msgid "Document feeder extras" msgstr "Dokument føder" #: backend/canon.c:1707 #, fuzzy, no-c-format msgid "Flatbed only" msgstr "Flatbed" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, fuzzy, no-c-format msgid "Transparency unit" msgstr "Filmenhed" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, fuzzy, no-c-format msgid "Negative film" msgstr "Negativ film" #: backend/canon.c:1740 #, fuzzy, no-c-format msgid "Positive or negative film" msgstr "Positiv film" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, fuzzy, no-c-format msgid "Transparency ratio" msgstr "Filmenhed" #: backend/canon.c:1775 #, fuzzy, no-c-format msgid "Select film type" msgstr "Filmtype" #: backend/canon.c:1776 #, fuzzy, no-c-format msgid "Select the film type" msgstr "Vælger halvtone." #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flatbed" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "ADF" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, fuzzy, no-c-format msgid "ADF Duplex" msgstr "Dobbeltsidet" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Print" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Dobbeltsidet" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Rød" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Grøn" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "BlÃ¥" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Forbedring" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Forbedring" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Forbedring" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Ingen" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Enkeltsidet" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Dobbeltsidet" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Filmenhed" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatisk dokumentføder" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Positiv film" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negativ film" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Fokusér pÃ¥ glaspladen" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Fokusér 2,5 mm over glaspladen" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Halvtone A (hÃ¥rd tone)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Halvtone B (blød tone)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Halvtone C (net/skærm)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Dithering A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Dithering B (4x4 spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Dithering C (4x4 net/skærm)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Dithering D (8x4 net/skærm)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Tekstforbedringsteknologi" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Hent mønster A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Hent mønster B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Ingen korrektion" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Brugerdefineret" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Matrix printere" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Termo printere" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Blæk printere" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT skærme" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Standard" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Udskrift med høj opløsning" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Udskrift med lav opløsning" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Udskrift med høj kontrast" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Brugerdefineret (gamma=1,0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Brugerdefineret (gamma=1,8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 portræt" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 tværformat" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Maks" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Skanner tilstand" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Vælger halvtone." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Udfald" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Vælger udfaldet." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Vælger lyshed." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Skarphed" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Farvekorrektion" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Fastsætter farvekorrektiontabellen for den valgte uddataenhed." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Farvekorrektionskoefficienter" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matrix multiplikation af RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Forskyder grøn mod rød" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Forskyder grøn mod blÃ¥" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Forskyder rød mod grøn" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Forskyder rød mod blÃ¥" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Forskyder blÃ¥ mod grøn" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Forskyder blÃ¥ mod rød" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Kontrollerer grønt niveau" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Øger det røde, baseret pÃ¥ grønt niveau" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Øger det blÃ¥, baseret pÃ¥ grønt niveau" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Øger det grønne, baseret pÃ¥ rødt niveau" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Fastsætter rødt niveau" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Øger det blÃ¥, baseret pÃ¥ rødt niveau" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Øger det grønne, baseret pÃ¥ blÃ¥t niveau" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Øger det røde, baseret pÃ¥ blÃ¥t niveau" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Fastsætter blÃ¥t niveau" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Spejlvend billedet." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Hurtig forhÃ¥ndsvisning" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Automatisk omrÃ¥deopdeling" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Kort opløsningsliste" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Vis kort liste med mulige opløsninger" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Forstørrelse" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Angiver zoomfaktoren som skanneren skal bruge" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Hurtig format" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Tilvalgsudstyr" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Skub ud" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Skub arket i den automatiske arkføder ud" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Automatisk skub ud" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Skub dokumentet ud efter skanning" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "ADF-tilstand" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Vælger ADF tilstand (enkeltsidet/dobbeltsidet)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Skuffe" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Vælg fra hvilken skuffe der skal skannes" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Vælger gammakorrektionsværdi fra en liste med foruddefinerede enheder " "eller en brugerdefineret tabel, som kan hentes til skanneren" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Fokuseringspunkt" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Fastsætter fokuseringen enten pÃ¥ glaspladen eller 2,5 mm over denne" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Vent pÃ¥ knap" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "NÃ¥r skankommando er sendt, starter skanningen først nÃ¥r der er trykket " "pÃ¥ knappen pÃ¥ skanneren." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, fuzzy, no-c-format msgid "Positive Slide" msgstr "Positiv film" #: backend/epson2.c:137 #, fuzzy, no-c-format msgid "Negative Slide" msgstr "Negativ film" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Brugerdefineret" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Tændt" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Slukket" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Dither" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "Fejlspredning" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Hvid niveau" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Sort niveau" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "Betinget" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Vandret" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Vandret" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Vandret" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Lodret" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Lodret" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Print" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Halvtone" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Grovkalibrering" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Billedbetoning" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Mætning" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "" "Aktiver automatisk fastsættelse af tærskelværdi for " "stregtegningsskanninger." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Spejl billedet" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Spejlvend billedet vandret." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Hvid niveau for blÃ¥" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Fastsætter rødt niveau" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Farve stregtegning" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Udglatning" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Gamma værdi" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Tærskelværdi" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Tærskelværdi" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Støjreduktion" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Ingen korrektion" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Ingen korrektion" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Arkføder tilstand" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Avancerede indstillinger" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Ingen korrektion" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Udfald" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Arkføder tilstand" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Sluk-lampe tid" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "BlÃ¥ forskydning" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Grøn forskydning" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Grøn forskydning" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "BlÃ¥ forskydning" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Indstillinger for blÃ¥-kanals forskydning" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Duplex skan" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Avancerede indstillinger" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Støjreduktion" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Fra papir" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Fra papir" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Fra papir" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Fra papir" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Manuel pre-fokus" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Manuel pre-fokus" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "Skanningsopløsning" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Hvid niveau" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Rød intensitet" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Duplex skan" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Ekstra" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, fuzzy, no-c-format msgid "Disable interpolation" msgstr "Deaktiver bagudrettet sporing" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Farve stregtegning" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibrering" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Definer kalibreringstilstand" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Kalibreringsdatacache" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Sluk-lampe tid" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "Lampen bliver slukket efter den angivne tid (i minutter). Værdien 0 " "bevirker, at lampen ikke bliver slukket." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Grovkalibrering" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "Vent pÃ¥ knap" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "Vent pÃ¥ knap" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Vent pÃ¥ knap" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Grovkalibrering" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Gennemtving kalibrering før skanning" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Knapper" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibrering" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Begynd kalibreringsprocessen." #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Grovkalibrering" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Kalibreringsdatacache" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Filmadapter" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Farve ved grÃ¥tone tilstand" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Vælger hvilken skan farve der bruges i grÃ¥tone tilstand (standard er " "grøn)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Fejlsøgningsindstillinger" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatisk opvarmning" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Varm op indtil lampens lyshed er konstant, i stedet for at insistere pÃ¥ " "60 sekunders opvarmningstid." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Fuld skanning" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Skan hele skanningsarealet inklsive kalibreringsstriben. Vær forsigtig. " "Vælg ikke fuld højde. Kun til test formÃ¥l." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Grovkalibrering" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Indstil forstærkning og forskydning for skanning automatisk. Hvis dette " "er fravalgt, kan de analoge brugerfladeparametre manuelt indstilles. " "Denne indstilling er forvalgt. Kun til testformÃ¥l." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Grovkalibrering kun for første skan." #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Grovkalibrering udføres kun for første skanning. Virker med de fleste " "skannere og kan spare skanningstid. Hvis billedets lyshed er forskellig " "for hvert skan, fravælg denne indstilling. Kun til testformÃ¥l." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Bagudrettede linier" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Antal linier skannervognen flyttes tilbage nÃ¥r bagudrettet sporing " "opstÃ¥r. Det sker nÃ¥r skanneren skanner hurtigere end computeren kan " "modtage dataene. SmÃ¥ værdier giver hurtigere skanninger, men øger " "risikoen for at linier bliver sprunget over." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gamma værdi" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Fastsætter gamma værdien for alle kanaler." #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "SkanomrÃ¥de" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, fuzzy, no-c-format msgid "Scan Mode Group" msgstr "Skanner tilstand" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Diapositiv" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Skannertilstand" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "Analog gammakorrektion" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "Gammakorrektion" #: backend/hp3900_sane.c:1451 #, fuzzy, no-c-format msgid "Disable white shading correction" msgstr "Udfør kun skyggekorrektion" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "GrÃ¥skala" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "arkføder skanner" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Ignorer kalibrering" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Filnavn" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "arkføder skanner" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "Skanningskilde" #: backend/hp3900_sane.c:1584 #, fuzzy, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Vælger nummeret pÃ¥ det billede der skal skannes" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Opdatér indstillinger" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, fuzzy, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Denne indstilling reflekterer skannerknappernes status." #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Billede" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Diverse" #: backend/hp5400_sane.c:358 #, fuzzy, no-c-format msgid "offset X" msgstr "Forskydning" #: backend/hp5400_sane.c:359 #, fuzzy, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Øverste-venstre x position af skanomrÃ¥de." #: backend/hp5400_sane.c:368 #, fuzzy, no-c-format msgid "offset Y" msgstr "Forskydning" #: backend/hp5400_sane.c:369 #, fuzzy, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Øverste-venstre x position af skanomrÃ¥de." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Lampe status" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Tænder/slukker for lampen" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Kalibrerer for sort og hvidt niveau." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, fuzzy, no-c-format msgid "TMA Slides" msgstr "Diapositiv" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Negativ" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "Farve 48" #: backend/hp5590.c:95 #, fuzzy, no-c-format msgid "Extend lamp timeout" msgstr "Sluk-lampe tid" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Vent pÃ¥ knap" #: backend/hp5590.c:99 #, fuzzy, no-c-format msgid "Waits for button before scanning" msgstr "Varm lampen op før skanning" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Avancerede indstillinger" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Grov" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fin" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Tilpasset" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automatisk" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Uforandret" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC grÃ¥" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA GrÃ¥" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Langsom" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Hurtig" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Meget hurtig" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-pixel" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-pixel" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-pixel" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Print" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Film-stribe" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Betinget" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Eksperiment" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Gør skarpere" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Angiv niveau for skærpning" #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Automatisk tærskelværdi" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Aktiver automatisk fastsættelse af tærskelværdi for " "stregtegningsskanninger." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Vælg udglatningsfilter." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Skub mediet ud efter skanning" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Skubber mediet ud efter gennemført skanning." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Skift dokument" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Skift dokument." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Skub ud" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Skubber dokumentet ud." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Begynd kalibreringsprocessen." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Medie" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Vælg medietype." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Eksponeringstid" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "En længere eksponeringstid lader skanneren indsamle mere lys. Anbefalet " "brug er 175% for papirbilleder, 150% for diapositiver og \"Negativ\" for " "negativer. Ved mørke (undereksponerede) billeder, kan denne værdi øges." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Farve matrix" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Fastlægger skannerens farve matrix." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Tilpasset farve matrix." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "En farve matrix" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Tilpasset farve matrix for grÃ¥toneskanning." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Spejlvend vandret" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Spejlvend billedet vandret." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Spejlvend lodret" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Spejlvend billedet lodret." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Opdatér indstillinger" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Opdatér indstillinger." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8 bit uddata" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "Brug bit dybde større end 8 internt, men uddata kun 8 bit." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Vent pÃ¥ frontknap" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Vent med at begynde skanning, til frontknappen trykkes." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Sluk lampen" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Slukker for skannerens lampe." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Papirstørrelse" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatisk separering" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 tværformat" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Manuel pre-fokus" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Manuel pre-fokus" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Aktiver Duplex (dobbeltsidet) skanning" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Reel størrelse af papiret i ADF'en" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Halvtone" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Farve" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Betinget" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Slukket" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Halvtone" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Halvtone" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Fejlspredning" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Højlys" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "Flatbed skanner" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Fra papir" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Standard" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Udglat" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Langsom" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Mellem" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Rød" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Grøn" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Skanningskilde" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Arkføder tilstand" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Fastætter fødningstilstanden" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Deaktiver pre-fokusering" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Deaktiver pre-fokusering" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Fastætter fødningstilstanden" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Fastætter fødningstilstanden" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatisk tærskelværdi" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Automatisk indstilling af lyshed, kontrast, hvid balance, gamma, " "støjreduktion og billedbetoning" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Støjreduktion" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Reducer støj fra enkelt punkter" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Billedbetoning" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Fastsætter billedbetoning" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Lampe tændt" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Tænder/slukker for lampen" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Spejlvend billedet lodret." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gammakorrektion" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Udskrift med høj opløsning" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Udskrift med lav opløsning" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Fejlspredning" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Ingen korrektion" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normal" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Forbedring" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Automatisk tærskelværdi" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Automatisk tærskelværdi" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Fastsætter billedrammernes rækkefølge" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Skygge for blÃ¥" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Forskyder rød mod blÃ¥" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamant" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 grov fortykning" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 fin fortykning" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 lodret linie" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Forstærk" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Farvekanalforstærkningsindstillinger" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "GrÃ¥-forstærkning" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Fastsætter grÃ¥-kanals forstærkning" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Rød forstærkning" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Fastsætter rød-kanals forstærkning" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Grøn forstærkning" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Fastsætter grøn-kanals forstærkning" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "BlÃ¥ forstærkning" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Fastsætter blÃ¥-kanals forstærkning" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer dither 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer dither 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Halvtone punkt 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Halvtone punkt 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Fejlspredning" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Tilstand 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Tilstand 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Tilstand 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "Fra kalibreringsstriber" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Udglat" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Lav" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Mellem" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Høj" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT skærm" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "En side" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Alle sider" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "arkføder skanner" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "4 bit grÃ¥skala" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "8 bit grÃ¥skala" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Skygge, mellemtone, højlys, eksponeringstid" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Specialindstillinger" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Farvebalance" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Deaktiver bagudrettet sporing" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Hvis aktiveret udfører skanneren ikke en bagudrettet sporing." #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Tænd/sluk lampen" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Tænder/slukker lampen i flatbed'en" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Kalibrering ved bagende" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "Hvis valgt, udføres farvekalibreringen før et skan af bagenden" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Anvend lightlid-35 mm-adapteren" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Denne indstilling slukker lampen i flatbed'en under skanning" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Kvalitets skanning" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Højeste kvalitet men lavere hastighed" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Hurtig skanning" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Højeste hastighed men lavere kvalitet" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatisk justering af tærskelværdier" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Hvis aktiveret prøver bagenden automatisk at bestemme en optimal " "tærskelværdi." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Vælger gammakorrektionstilstand." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Fælles gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Anvend samme gammaværdi for alle farvekanaler." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Skalær gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Vælger værdi for skalær gammakorrektion." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Skalær gamma rød" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Vælger værdi for skalær gammakorrektion (rød kanal)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Skalær gamma grøn" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Vælger værdi for skalær gammakorrektion (grøn kanal)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Skalær gamma blÃ¥" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Vælger værdi for skalær gammakorrektion (blÃ¥ kanal)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Kanal" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Vælger farvekanal, \"Master\" betyder at alle farvekanaler pÃ¥virkes." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Mellemtone" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Vælger hvilket glansniveau der skal anses for \"50% grÃ¥\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Mellemtone for rød" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Vælger hvilket glansniveau der skal anses for \"50 % rød\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Mellemtone for grønt" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Vælger hvilket glansniveau der skal anses for \"50% grøn\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Mellemtone for blÃ¥" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Vælger hvilket glansniveau der skal anses for \"50% blÃ¥\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Rød balance" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Balancefaktor for rød. 100 % giver ingen korrektion." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Grøn balance" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Balancefaktor for grøn. 100% giver ingen korrektion." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "BlÃ¥ balance" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Balancefaktor for blÃ¥. 100% giver ingen korrektion." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Fastprogram balance" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" "Fastsætter farvebalanceværdierne til værdierne fra det faste program." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Langsomste" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Langsommere" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Hurtigere" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Hurtigst" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 grov" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fin" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 meget fin" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normal" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 grov" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fin" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 grov" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normal" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fin" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 tilpasset" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 tilpasset" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 tilpasset" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 tilpasset" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 tilpasset" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 tilpasset" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Hurtig grÃ¥tonetilstand" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Skan i hurtig grÃ¥tonetilstand (lavere kvalitet)" #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Forlang at alle forhÃ¥ndsvisninger udføres i hurtigste (lav kvalitet) " "tilstand. Dette kan være grÃ¥tone, eller lav-opløsning." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Lampe slukkes efter (minutter)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Angiv efter hvor lang tid (i minutter) lampen skal slukkes." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Sluk lampen" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Sluk lampen med det samme." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Rød lyshed" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Fastsætter lysheden i den røde kanal i det rekvirerede billede." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Grøn lyshed" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Fastsætter lysheden i den grønne kanal i det rekvirerede billede." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "BlÃ¥ lyshed" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Fastsætter lysheden i den blÃ¥ kanal i det rekvirerede billede." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Kontrast rød kanal" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Fastsætter kontrasten i den røde kanal i det rekvirerede billede." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Kontrast grøn kanal" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "" "Fastsætter kontrasten i den grønne kanal i det rekvirerede billede." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Kontrast blÃ¥ kanal" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Fastsætter kontrasten i den blÃ¥ kanal i det rekvirerede billede." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Farve 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Farve 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "GrÃ¥ 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "GrÃ¥ 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, fuzzy, no-c-format msgid "Positive" msgstr "Positiv film" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Varm op indtil lampens lyshed er konstant, i stedet for at insistere pÃ¥ " "40 sekunders opvarmningstid." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Negativ film" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negativ" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, fuzzy, no-c-format msgid "Update button state" msgstr "Knap tilstand" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Knap 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Knap 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Film" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Enhedsindstillinger" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Lampe afbryder" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Manuelt tænd/sluk for lampen(lamperne)." #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Grovkalibrering" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Kalibreringsdatacache" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Aktivér eller deaktivér kalibreringsdatacache." #: backend/plustek.c:942 #, fuzzy, no-c-format msgid "Performs calibration" msgstr "Grovkalibrering" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Hastighedsøgnings sensor" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Til/fra for øgning af sensors hastighed." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Opvarmningstid" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Opvarmningstid i sekunder." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Sluk lampe tid" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Sluk lampe tid i sekunder." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Analog forende" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Rød forstærkningsværdi for den analoge forende" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Rød forskydning" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Rød forskydningsværdi for den analoge forende" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Grøn forstærkningsværdi for den analoge forende" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Grøn forskydningsværdi for den analoge forende" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "BlÃ¥ forstærkningsværdi for den analoge forende" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "BlÃ¥ forskydningsværdi for den analoge forende" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Rød lampe slukket" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Fastsætter parametre for slukning af rød lampe" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Grøn lampe slukket" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Fastsætter parametre for slukning af grøn lampe" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "BlÃ¥ lampe slukket" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Fastsætter parametre for slukning af blÃ¥ lampe" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Denne indstilling reflekterer skannerknappernes status." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Farve 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Ditheringsmønster 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Ditheringsmønster 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Udvælge tilfældigt" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Kildevalg" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Billedforbedring" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Gøre grÃ¥" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Hent billedet som grÃ¥skala." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Tre-gennemløbs simulering" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simuler en tre-gennemløbs skanner ved at returnere 3 separate " "billedrammer, én for hver grundfarve. Rækkefølgen er: grøn, blÃ¥ og rød." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "HÃ¥ndskanner simulering" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simulerer en hÃ¥ndskanner. Oftest kender en hÃ¥ndskanner ikke billedhøjden " "i forvejen. I stedet for returnerer de en højde pÃ¥ -1. Sættes denne " "indstilling tillades test af, om en forende kan hÃ¥ndtere dette korrekt." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Sæt standardværdier for forbedringskontroller (lyshed og kontrast)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Skrivebeskyttet test-indstilling" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Lad os se om forenderne kan hÃ¥ndtere dette rigtigt" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Gamma tabeller" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Status kode simulering" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Gennemtving ikke status kode" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Tving ikke bagenden til at returnere en status kode." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Returner SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Tving bagenden til at returnere statuskoden SANE_STATUS_EOF efter " "sane_read() er blevet kaldt." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Returner SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Tving bagenden til at returnere statuskoden SANE_STATUS_JAMMED efter " "sane_read() er blevet kaldt." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Returner SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Tving bagenden til at returnere statuskoden SANE_STATUS_NO_DOCS efter " "sane_read() er blevet kaldt." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Returner SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Tving bagenden til at returnere statuskoden SANE_STATUS_COVER_OPEN efter " "sane_read() er blevet kaldt." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Returner SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Tving bagenden til at returnere statuskoden SANE_STATUS_IO_ERROR efter " "sane_read() er blevet kaldt." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Returner SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Tving bagenden til at returnere statuskoden SANE_STATUS_NO_MEM efter " "sane_read() er blevet kaldt." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Returner SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Tving bagenden til at returnere statuskoden SANE_STATUS_ACCESS_DENIED " "efter sane_read() er blevet kaldt." #: backend/rts8891.c:2809 #, fuzzy, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Denne indstilling reflekterer skannerknappernes status." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lampe tændt" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Tænd for skannerlampen" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Sluk lampe" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Sluk for skannerens lampe" #: backend/sm3840.c:760 #, fuzzy, no-c-format msgid "Lamp timeout" msgstr "Sluk-lampe tid" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Dokument føder" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (tommer)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (tommer)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (tommer)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Halvtone er ikke understøttet" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "Spredte punkter 8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "Spredte punkter 16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Antal skanlinier der skal forlanges pr. SCSI-læsning. En ændring af " "denne parameter tillader en fintuning af hastigheden, hvormed der læses " "data fra skanneren under skanningen. Hvis dette er sat for lavt, stopper " "skanneren periodisk midt i skanningerne. Hvis det sættes for højt, kan X-" "baserede forender stoppe med at reagere pÃ¥ X begivenheder, og dit system " "gÃ¥r ned." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Skub dokumentet ud efter skanning" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Smugkigtilstand" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Vælg tilstand for forhÃ¥ndsvisning. GrÃ¥skala smugkig er normalt det " "bedste kompromis mellem hastighed og detaljerigdom." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Foruddefinerede indstillinger" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "Giver standard skanomrÃ¥de for fotografier, tryk o.l." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "Flatbed skanner" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Automatisk skub ud" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Fokuseringspunkt" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Fokuseringspunkt" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Farvelinier pr. læsning" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "GrÃ¥skalalinier pr. læsning" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Farve RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Farve RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Farve RGB TEKST" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Helt sort" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Helt hvidt" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Farvemønster" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Gitter" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Første angivelse" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Anden angivelse" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Dette er den meget lange tredie angivelse. MÃ¥ske har forenden en ide om " "hvordan det skal vises" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "HÃ¥ndskanner simulering" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulerer en hÃ¥ndskanner. HÃ¥ndskannere kender ikke forud billedhøjden. I " "stedet for angiver de en billedhøjde pÃ¥ 1. Denne indstilling tillader " "test af forenden, om den kan hÃ¥ndtere dette korrekt. Indstillingen giver " "ogsÃ¥ en fast bredde pÃ¥ 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Tre-gennemløbs simulering" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simuler en tre-gennemløbs skanner. I farvetilstand overføres tre " "billedrammer." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Fastsætter billedrammernes rækkefølge" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Fastsætter billedrammernes rækkefølge i tre-gennemløbs tilstand." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Specialindstillinger" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Vælg testbillede" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Vælger type af testbillede. Mulige indstillinger:\n" "Helt sort: fylder hele skanningen med sort.\n" "Helt hvidt: fylder hele skanningen med hvidt.\n" "Farve mønster: tegner forskellige farvemønstre afhængig af tilstand.\n" "Gitter: tegner et sort/hvidt gitter med en bredde og højde af de enkelte " "felter pÃ¥ 10 mm." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Invertér endianness" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Bytter om pÃ¥ den øvre og nedre byte i billedata i 16 bit tilstand. Denne " "indstilling kan bruges til at teste forendens 16 bit tilstand, d.v.s. om " "forenden anvender en korrekt endianness." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Læsebegrænsning" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "Begræns mængden af overført data ved hvert kald af sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Størrelsen af læsebegrænsning" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "Den (maksimale) mængde data overført, ved hvert kald af sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Læseforsinkelse" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Forsink overførsel af data til røret." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Varighed af læseforsinkelse" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "Fastlægger, hvor længe der skal ventes efter overførsel af hver " "databuffer gennem røret." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Retur værdi af sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Fastlægger returværdien af sane_read(). \"Standard\" er den normale " "indstilling ved skanning. Alle andre returværdier er til for at teste " "hvordan forenden hÃ¥ndterer dem." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Tab af pixler pr. linie" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Antal pixler, der er ubenyttede ved enden af hver linie." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Uklare parametre" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Returner uafklarede linier og bytes pr. linie nÃ¥r sane_parameters() " "kaldes før sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Brug ikke blokerende IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Brug ikke blokerende IO for sane_read(), hvis det er understøttet af " "forenden." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Tilbyd en vælg fil beskriver" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Tilbyd en vælg fil beskriver for at bestemme om sane_read() vil " "returnere data." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Aktivér testindstillinger" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Aktivér forskellige testindstillinger. Dette er til at afprøve om " "forenderne kan vise og ændre alle de forskellige SANE indstillingstyper." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Udskriv indstillinger" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Udskriv en liste med alle indstillinger." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Boolske testindstillinger" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Boolsk soft select soft detect" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Dette er en boolsk testindstilling, som er \"soft select\" og " "\"soft detect\" (og \"avanceret\"). Dette er en normal boolsk " "indstilling." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Boolsk hard select soft detect" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Dette er en boolsk testindstilling, som er \"hard select\" og " "\"soft detect\" (og \"avanceret\"). Dette betyder, at indstillingen ikke " "kan ændres fra forenden, men af brugeren (f.eks. ved at trykke pÃ¥ en " "knap pÃ¥ enheden)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Boolsk hard select" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Dette er en boolsk testindstilling, som er \"hard select\" (og " "\"avanceret\"). Dette betyder, at indstillingen ikke kan ændres fra " "forenden, men af brugeren (f.eks. ved at trykke pÃ¥ en knap pÃ¥ enheden), " "og at det ikke kan læses af forenden." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Boolsk soft detect" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Dette er en boolsk testindstilling, som er \"soft detect\" (og " "\"avanceret\"). Dette betyder, at indstillingen er skrivebeskyttet." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Boolsk soft select soft detect emulered" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Dette er en boolsk testindstilling, som er \"soft select\" ,\"soft " "detect\"og \"emulated\" (og \"avanceret\")." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Boolsk soft select soft detect auto" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Dette er en boolsk testindstilling, som er \"soft select\" ,\"soft " "detect\"og \"automatic\" (og \"avanceret\"). Denne indstilling kan " "sættes automatisk fra bagenden." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Heltalsindstillinger" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Heltal" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Heltal testindstilling uden enhed og uden begrænsninger." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) HeltalsbegrænsningsomrÃ¥de" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Heltal testindstilling med enheden \"pixel\" og et " "begrænsningsomrÃ¥de. Minimum er 4, maksimum 192, og skridtlængden er 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Heltalsbegrænsningsordliste" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Heltal testindstilling med enheden \"bit\" og en " "ordlistebegrænsning." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Heltal tabel" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Heltal testindstilling med enheden \"mm\" og en tabel uden " "indskrænkninger." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Heltal tabel med begrænset omrÃ¥de" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Heltal testindstilling med enheden \"dpi\" og en tabel med et " "begrænset omrÃ¥de. minimum er 4, og maksimum 192, og skridtlængden er 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Heltal tabel med begrænset ordliste" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Heltal testindstilling med enheden \"procent\" og en tabel med en " "begrænset ordliste." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Faste testindstillinger" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Faste" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" "(1/3) Faste testindstillinger uden enhed og ingen restriktioner sat." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Fast restriktionsomrÃ¥de" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Fast testindstilling, med enhed i microsekund og " "restriktionsomrÃ¥de sat. Minimalt er -42.17, og maksimalt 32767.9999, og " "mængde er 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Fast restriktions ordliste" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Fast testindstilling uden enheder og restriktions ordliste sat." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Streng testindstillinger" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) Streng" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Streng testindstillinger uden restriktioner." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) Streng restriktioner strengliste" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) Streng testindstillinger med strengliste restriktioner." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) Streng restriktioner lang strengliste" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) Streng testindstillinger med strengliste restriktioner. Indeholder " "nogle flere indgange..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Knap testindstillinger" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Knap" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Knap testindstilling. Udskriver noget tekst..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Farve 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Anvend billedkomposition" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "2 niveau sort/hvid (stregtegningstilstand)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Dithered/halvtone sort/hvid (halvtonetilstand)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Flerniveau sort/hvid (grÃ¥skalatilstand)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Flerniveau RGB farve (et-gennemløb farve)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignorer kalibrering" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Deaktiver pre-fokusering" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Kalibrér ikke fokus" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Manuel pre-fokus" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Fast fokusposition" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Linsekalibrering pÃ¥ dokumentposition" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Kalibrér linsefokus pÃ¥ dokumentposition" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Holder fokusposition 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Anvend 0mm holder fokusposition i stedet for 0,6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Kalibreringstilstand" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Definer kalibreringstilstand" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Tænder/slukker for lampen" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA tændt" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Tænder/slukker for UTA'en" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Forskydning" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Indstillinger for farvekanalernes forskydning" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "GrÃ¥-forskydning" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Indstillinger for grÃ¥-kanals forskydning" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Indstillinger for rød-kanals forskydning" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Indstillinger for grøn-kanals forskydning" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Indstillinger for blÃ¥-kanals forskydning" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Smugkigtilstand" #~ msgid "Grayscale" #~ msgstr "GrÃ¥skala" #~ msgid "Binary" #~ msgstr "Sort/hvid" #, fuzzy #~ msgid "Display a shortened resolution list" #~ msgstr "Vis kort liste med mulige opløsninger" #~ msgid "Black & White" #~ msgstr "Sort/hvid" sane-backends-1.0.27/po/fr.po0000664000175000017500000047762613110600537012631 00000000000000# French translation for SANE backend options # Copyright (C) 2002, 2003 SANE Project. # Frank Zago , 2002. # Yann E. MORIN # # Permission is granted to copy, distribute and/or modify this document # under the terms of the GNU Free Documentation License, Version 1.1 # or any later version published by the Free Software Foundation; # with no Invariant Sections, with no Front-Cover Texts, and with # no Back-Cover. # A copy of the license is included in the section entitled "GNU # Free Documentation License". # # #################################################### # YEM-20100606 : Updates, with fixes from Nicolas. # ---------------------------------------------------- # YEM-20080115 : Fixes from Stef and Patrick. Thanks! # ---------------------------------------------------- # YEM-20080112 : Updates for sane-backends 1.0.19 # 100% translated # ---------------------------------------------------- # YEM-20030511 : Acknowledgements # Thanks to all that helped on this update : now # reaching 97.2% complete with no fuzzyness! # ---------------------------------------------------- # YEM-20030504 : Updates for sane-backends 1.0.12 # ---------------------------------------------------- # YEM-20030225 : Acknowledgements # Thanks to all that helped on translations, those are: # Henning, Stef and Frank! # ---------------------------------------------------- # YEM-20030216 : Notes on translations # In french, the word 'numériseur' that is the correct translation for # 'scanner' is less and less used, in favor of the english word. Therefore I # won't translate it. # On the other hand, the verb 'to scan' is correctly translated into # 'numériser', and I'll use that. # ---------------------------------------------------- # Some words pertaining to methods (such as dithering) won't be translated # for the simple reason there is no single word, to my knowledge, that fit. # I'll keep the english there as well. # #################################################### msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.19\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2008-01-17 22:25+0100\n" "Last-Translator: Yann E. MORIN \n" "Language-Team:\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 0.9.5\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Nombre d'options" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Général" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Aire de numérisation" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Réglages fins" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Avancé" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Capteurs" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Aperçu" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Force l'aperçu en noir et blanc" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Profondeur" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Mode de numérisation" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Vitesse de numérisation" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Source de numérisation" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Forcer l'utilisation du retour arrière" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "X haut-gauche" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Y haut-gauche" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "X bas-droit" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Y bas-droit" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Echantillonnage" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Echantillonnage X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Echantillonnage Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Largeur de la page" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Hauteur de la page" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Utiliser une table gamma personnalisée" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Intensité de l'image" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Intensité rouge" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Intensité verte" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Intensité bleue" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Luminosité" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contraste" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Grain" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Demi-teinte" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Niveau noir" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Niveau blanc" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Niveau blanc des rouges" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Niveau blanc des verts" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Niveau blanc des bleus" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Ombré" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Ombré rouge" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Ombré vert" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Ombré bleu" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Contraste" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Contraste rouge" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Contraste vert" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Contraste bleu" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Teinte" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturation" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Nom de fichier" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Taille du motif demi-teinte" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Motif demi-teinte" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Lier les échantillonnage X et Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Négatif" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Calibration de la qualité" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Doubler la résolution optique" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Lier RVB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Seuil" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Correction gamma analogique" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Gamma analogique rouge" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Gamma analogique vert" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Gamma analogique bleu" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Lier les gamma analogiques RVB" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Préchauffage de la lampe" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Calibrer le temps d'exposition" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Calibrer le temps d'exposition pour le rouge" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Calibrer le temps d'exposition pour le vert" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Calibrer le temps d'exposition pour le bleu" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Temps d'exposition pendant numérisation" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Temps d'exposition pour le rouge pendant numérisation" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Temps d'exposition pour le vert pendant numérisation" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Temps d'exposition pour le bleu pendant numérisation" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Fixer le temps d'exposition" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Calibrer la puissance de la lampe" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Puissance de la lampe pendant la numérisation" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Fixer la puissance de la lampe" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Eteindre la lampe à la sortie" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Option, lecture seule, qui indique le nombre d'options supportées par un " "périphérique spécifique." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Options pour la source, le mode et la résolution" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" "Options de la zone de numérisation et la taille de l'image à numériser" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Options modifiant l'image" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Options spécifiques au matériel" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Capteurs et boutons du scanner" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Demande une numérisation de basse qualité" #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Requière que toutes les prévisualisations soient faites en monochrome. " "Sur un scanner à 3 passes, cela réduit le nombre de passes à 1. Sur un " "scanner à 1 passe, cela réduit l'espace mémoire nécessaire et le temps " "de numérisation de la prévisualisation." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Nombre de bits par échantillon. Les valeurs typiques sont de 1 pour " "\"Trait\" et de 8 pour les numérisation \"haute-résolution\"" #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Choisit le mode de numérisation (comme Trait, Monochrome ou Couleur)" #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Détermine la vitesse de numérisation." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Choisit la source de numérisation." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "" "Si l'interface à laquelle votre scanner est connectée n'est pas assez " "rapide, cette option ne permettra pas de reprendre la numérisation, et " "les données manquantes seront perdues." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Position X en haut à gauche de l'aire de numérisation" #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Position Y en haut à gauche de l'aire de numérisation" #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Position X en bas à droite de l'aire de numérisation" #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Position Y en bas à droite de l'aire de numérisation" #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Choisit la résolution de l'image à numériser" #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Choisit la résolution horizontale de l'image à numériser" #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Choisit la résolution verticale de l'image à numériser" #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Spécifie la largeur de la source. Requis pour le centrage automatique " "des numérisations effectuées à partir du chargeur automatique." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Spécifie la hauteur de la source." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Détermine si une table gamma standard ou personnalisée doit être " "utilisée." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Table de correction gamma. En mode couleur, cette option affecte " "simultanément les bandes rouge, verte et bleue (c.-à-d. que c'est une " "table gamme d'intensité.)" #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Table de correction gamma pour le rouge." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Table de correction gamma pour le vert." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Table de correction gamma pour le bleu" #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Contrôle la brillance de l'image à numériser." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Contrôle le contraste de l'image à numériser." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Sélectionne le \"grain\" de l'image numérisée. De petites valeurs " "donnent des images plus nettes." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Spécifie si l'image numérisée doit etre en demi-teinte (tramée)" #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" "Spécifie quel niveau de luminosité est considéré comme étant \"noir\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" "Spécifie quel niveau de luminosité est considéré comme étant \"blanc\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Spécifie quel niveau de luminosité rouge est considéré comme étant " "\"blanc\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Spécifie quel niveau de luminosité verte est considéré comme étant " "\"blanc\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Spécifie quel niveau de luminosité bleue est considéré comme étant " "\"blanc\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Spécifie quel niveau de luminosité rouge est considéré comme étant \"noir" "\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Spécifie quel niveau de luminosité verte est considéré comme étant \"noir" "\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Spécifie quel niveau de luminosité bleue est considéré comme étant \"noir" "\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Spécifie quel niveau de luminosité rouge est considéré comme étant " "\"rouge max.\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Spécifie quel niveau de luminosité verte est considéré comme étant " "\"vert max.\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Spécifie quel niveau de luminosité bleue est considéré comme étant " "\"bleu max.\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Contrôle la teinte (bleue) de l'image numérisée." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Le niveau de saturation contrôle l'éclairage qui se produit lors de " "l'acquisition par un appareil-photo. Une valeur importante cause plus " "d'éclairage." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Le nom de fichier de l'image à charger." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Choisit la taille du motif de demi-ton utilisé pour numériser les images " "demi-ton." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Définit le motif de demi-ton utilisé pour numériser les images demi-ton." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Utilise la même résolution pour X et Y" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Inverse le noir et le blanc" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Faire une calibration de qualité pour les blancs" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Utilise une lentille qui double la résolution optique" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Utilise les même paramètres pour chaque couleur en mode RVB" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Choisit la luminosité minimum pour avoir un point blanc" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Correction gamma analogique" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Correction gamma analogique pour le rouge" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Correction gamma analogique pour le vert" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Correction gamma analogique pour le bleu" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Préchauffer la lampe avant la numérisation" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Définit le temps d'exposition pour la calibration" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Définit le temps d'exposition pour la calibration du rouge" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Définit le temps d'exposition pour la calibration du vert" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Définit le temps d'exposition pour la calibration du bleu" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Définit le temps d'exposition pour la numérisation" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Définit le temps d'exposition pour la numérisation du rouge" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Définit le temps d'exposition pour la numérisation du vert" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Définit le temps d'exposition pour la numérisation du bleu" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Autorise la sélection du temps d'exposition" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Définit la puissance de la lampe pour la calibration" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Définit la puissance de la lampe pour la numérisation" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Autorise la sélection de la puissance de la lampe" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Eteindre la lampe à la sortie du programme" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Bouton 'numérisation'" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "Bouton 'courrier électronique'" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Bouton 'Fax'" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Bouton 'copie'" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "Bouton 'PDF'" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Bouton 'annuler'" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Page chargée" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Couvercle ouvert" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Couleur" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Trait couleur" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Demi-ton couleur" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Gris" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Demi-teinte" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Trait" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "Succès" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Opération non-supportée" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "Opération annulée" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "Périphérique occupé" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Argument incorrect" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "Fin de fichier atteinte" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Bourrage dans le chargeur automatique de documents" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "Chargeur automatique de documents vide" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "Couvercle du scanner ouvert" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Erreur d'entrée-sortie" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "A court de mémoire" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "L'accés à la ressource a été refusé" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "La lampe n'est pas prète, veuillez ré-essayer" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" "Le méchanisme de blocage pour le transport du scanner est vérouillé" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Valeurs par défaut" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Valeurs par défaut pour les réglages fins." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Calibration" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Calibrer avant la prochaine numérisation" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Si activé, le scanner sera calibré avant la prochaine numérisation. " "Sinon la calibration est effectuée seulement avant la première " "numérisation." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Effectuer uniquement la correction des ombres" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Si activé, seule la correction des ombres est effectuée pendant la " "calibration. Les valeurs par défaut du gain, le décalage et le temps " "d'exposition, internes ou lues dans le fichier de configuration, sont " "utilisées." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Etat du bouton" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Numéro de la trame à numériser" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Sélectionner le numéro de la trame à numériser" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Numérisation recto-verso" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "La numérisation recto-verso permet de numériser les deux cotés d'un " "document" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Calibrer le scanner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Forcer la calibration du scanner avant la numérisation" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Niveaux de gris" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Effectue une numérisation en niveaux de gris plutôt qu'en couleurs" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Gain analogique" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Augmenter/diminuer le gain analogique du capteur CCD" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Correction gamma" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Sélectionne la courbe de correction gamma" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Brut" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Couleurs précises" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Pas de correction de transparence" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Correction en fonction du support" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Correction en fonction du rapport de transparence" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Négatifs" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Diapositives" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatique" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Vitesse normale" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "Vitesse 1/2" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "Vitesse 1/3" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "Paramètres arrondis" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "inconnu(e)" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "Bourrage du chargeur automatique" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "Couvercle du chargeur automatique ouvert" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "lampe défectueuse" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "erreur de positionnement du capteur" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "erreur de test du processeur (CPU)" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "erreur de test de la mémoire RAM" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "erreur de test de la mémoire ROM" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "erreur de test du matériel" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "lampe de l'adaptateur de transparent défectueuse" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "erreur de positionnement du capteur pour transparents" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "longueur de la liste de paramètres incorrecte" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "code commande invalide" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "champ du bloc de description de commande (CDB) invalide" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "Numéro d'unité logique (LUN) non supporté" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "champ invalide dans la liste des paramètres" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "erreur dans la séquence de commandes" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "trop de fenêtres spécifiées" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "document absent" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "message d'identification (IDENTIFY) invalide" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "option non connectée" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "Réinitialisation au démarrage / du bus" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "paramètre modifié par un autre maître" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "pas d'information supplémentaire" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "échec de re-sélection" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "erreur de parité SCSI" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "message d'erreur détecté " #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "message d'erreur invalide" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "erreur de dépassement de temps" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "erreur de l'adaptateur pour transparents" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lampe non stabilisée" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "numériseur de transparents" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "numériseur à plat" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Type de film" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Sélectionne le type de transparents (négatifs ou diapositives)" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Film négatif" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Sélectionne l'utilisation de film négatif" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Echantillonnage matériel" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Utilise seulement les valeurs d'échantillonnage matériel" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Mise au point" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Mise au point automatique" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Activer/désactiver la mise au point automatique" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Une seule mise au point automatique" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" "Effectuer la mise au point automatique une seule fois entre chaque " "éjection" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Mise au point manuelle" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "Effectuer manuellement la mise au point (128 par défaut)" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Marges" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Plus de réglages de couleur" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Image miroir" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Image miroir horizontal" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Temps d'exposition automatique" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Activer/désactiver le temps d'exposition automatique" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Calibrer maintenant" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Effectue la calibration *maintenant*" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Diagnostic automatique" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Effectue le diagnostic automatique du scanner" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Réinitialiser le scanner" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Réinitialiser le scanner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Maniement des documents" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Ejecte le film après chaque numérisation" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Ejecte automatiquement le film après chaque numérisation" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Ejecte le film avant de quitter" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "Ejecte automatiquement le film avant de quitter le programme" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Ejecte le film maintenant" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Ejecte le film *maintenant*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Chargeur automatique de document, options avancées" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "A plat seulement" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" "Ne pas utiliser le chargeur automatique, seulement le scanner à plat" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Adaptateur pour transparents" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "Allumer/éteindre l'adaptateur pour transparents" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Film négatif" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Film positif ou négatif" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Contrôle de densité" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Positionne le mode de contrôle de la densité" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Rapport de transparence" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Type de film" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Sélectionne le type de film" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "A plat" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "Chargeur automatique de documents, recto" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "Chargeur automatique de documents, verso" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "Chargeur automatique de documents, recto-verso" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Avant" #: backend/canon_dr.c:413 #, fuzzy, no-c-format msgid "Card Back" msgstr "Arrière" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Recto-verso" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Rouge" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Vert" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Bleu" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "Augmente le rouge" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "Augmente le vert" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "Augmente le bleu" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Aucun(e)" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "JPEG" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Recto" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Recto-verso" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Adaptateur pour transparents" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Chargeur automatique de document" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Positif" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Négatif" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Mettre au point sur la vitre" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Mettre au point 2,5 mm au-dessus de la vitre" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Motif demi-teinte A (teinte dure)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Motif demi-teinte B (teinte douce)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Motif demi-teinte C" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "/wiki/Filmstrip A (Bayer 4x4)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "'Dither' B (Spiral 4x4)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "'Dither' C ('Net Screen' 4x4)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "'Dither' C ('Net Screen' 4x4)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Technologie d'amélioration du texte" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Télécharger le motif A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Télécharger le motif B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Pas de correction" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Spécifié par l'utilisateur" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Imprimantes à impact" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Imprimantes thermiques" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Imprimantes à jet d'encre" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Moniteurs à tube cathodique" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Valeur par défaut" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Impression haute définition" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Impression basse définition" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Impression avec contraste élevé" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Spécifié par l'utilisateur (gamma=1,0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Spécifié par l'utilisateur (gamma=1,8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 - portrait" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 - paysage" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Max" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Mode de numérisation" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Sélectionne la demi-teinte." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Exclusion" # Dictionnary gives me 'marginal' for dropout. Sounds like # a part of the scan area is 'droped out', I mean excluded. # No, it is one of the colours that is excluded. #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Sélectionne le couleur exclu." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Sélectionne la brillance." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Netteté" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Correction de couleur" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "Remplit la table de correction de couleur pour le périphérique de " "destination sélectionné." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Coefficients de correction de couleur" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matrice de multiplication RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Décalage vert -> rouge" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Décalage vert -> bleu" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Décalage rouge -> vert" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Décalage rouge -> bleu" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Décalage bleu -> vert" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Décalage bleu -> rouge" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Contrôle le niveau de vert" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Ajoute au rouge en fonction du niveau de vert" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Ajoute au bleu en fonction du niveau de vert" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Ajoute au vert en fonction du niveau de rouge" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Contrôle le niveau de rouge" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Ajoute au bleu en fonction du niveau de rouge" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Ajoute au vert en fonction du niveau de bleu" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Ajoute au rouge en fonction du niveau de bleu" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Contrôle le niveau de bleu" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Effectue une symétrie verticale de l'image." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Aperçu rapide" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Séparation automatique" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Liste réduite de résolutions" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Affiche une liste réduite d'échantillonnage" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Zoom" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Définit le facteur de zoom utilisé par le scanner" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Format rapide" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Equipement optionnel" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Ejecter" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Ejecter la feuille du chargeur automatique" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Ejection automatique" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Ejecte le document après la numérisation" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Mode du chargeur automatique de documents" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" "Sélectionne le mode du chargeur automatique de documents (recto/recto-" "verso)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Baie" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Sélectionne la baie contenant le document à numériser" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Selectionne la correction gamma à partir d'une liste de périphériques " "pré-configurés ou de la table utilisateur, et qui sera téléchargée dans " "le scanner" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Mise-au-point" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "Effectue la mise-au-point soit sur la vitre, soit 2,5 mm au-dessus" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Attendre le bouton" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Aprés avoir envoyé la commande de numérisation, attendre l'appui du " "bouton avant de commencer la numérisation." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "Infra-rouge" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Diapositive positive" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Diapositive négative" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "Profil de température de couleurs interne" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "Profil de température de couleurs utilsateur" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Activé" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Aucun" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "Seuil dynamique (DTC)" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "Seuil dynamique simplifié (SDTC)" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Tramage" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "Diffusion d'erreur" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "Blanc" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "Noir" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Continuer" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Arréter" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10mm" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15mm" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20mm" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontal" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "Horizontal large" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "Horizontal étroit" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertical" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "Vertical large" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "De haut en bas" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "De bas en haut" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "Avant" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "Arrière" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Demi-teinte" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Effectue la calibration" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Accentuation de l'image" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Saturation" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "" "Active la détection automatique du seuil pour la numérisation en mode " "trait." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Image miroir" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Renverse l'image horizontalement." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Niveau blanc des bleus" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Contrôle le niveau de rouge" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Filtre de couleur" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Lissage" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Valeur de gamma" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "Courbe du seuil" #: backend/fujitsu.c:3347 #, fuzzy, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" "Courbe dynamique de seuil, de clair à foncé, normallement entre 50-65" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Seuil" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Réduction du bruit" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Pas de correction" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Pas de correction" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Couvercle du chargeur automatique ouvert" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Options avancées" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Pas de correction" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Exclusion" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Mode de chargement" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Temps avant extinction de la lampe" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Décalage des bleus" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Décalage des verts" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Décalage des verts" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Décalage des bleus" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Fixe le décalage pour le bleu" #: backend/fujitsu.c:3980 #, fuzzy, no-c-format msgid "Low Memory" msgstr "A court de mémoire" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Numérisation recto-verso" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Options avancées" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Réduction du bruit" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Avec du papier" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Avec du papier" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Avec du papier" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Avec du papier" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "Couvercle du scanner ouvert" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Mise au point manuelle" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Mise au point manuelle" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "erreur de test du matériel" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Niveau blanc" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Contrôle de densité" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Contrôle de densité" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Numérisation recto-verso" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extras" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" "Courbe dynamique de seuil, de clair à foncé, normallement entre 50-65" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "Désactiver le mode Trait dynamique" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" "Utilise le mode Trait du matériel, au lieu d'utiliser un algorithme " "logiciel adaptatif." #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Désactiver l'interpolation" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "Pour de hautes résolutions, et lorsque la résolution horizontale est " "plus faible que la résolution verticale, ne pas faire d'interpolation " "horizontale." #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Filtre de couleur" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "En niveaux de gris ou en mode trait, sélectionne la couleur à utiliser." #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Calibration" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Définit le mode de calibration" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Cache des données de calibration" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Temps avant extinction de la lampe" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "La lampe sera éteinte après ce laps de temps (en minutes). Entrer 0 pour " "ne pas éteindre la lampe automatiquement." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Eteindre la lampe durant la calibration des noirs" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "Délai en minutes avant d'éteindre la lampe après une numérisation." #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Bouton 'fichier'" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "Bouton 'reconnaissance de caractères (OCR)'" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Bouton 'marche'" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Bouton 'courrier électronique'" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "Calibration requise" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Le scanner a besoin d'être calibré avec les paramètres actuels" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Boutons" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Calibration" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Démarrer la calibration avec la feuille spéciale" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Effacer la calibration" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Efface le cache des données de calibration" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Adaptateur pour transparents" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Couleur du mode niveaux de gris" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Sélectionne la couleur à utiliser en niveaux de gris (défaut: vert)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Options de déboggage" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Préchauffage automatique" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Préchauffer jusqu'à ce que l'intensité de la lampe soit constante, au " "lieu d'attendre 60 secondes." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Numérisation complète" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Numérise la totalité de la surface, en incluant les bandes de " "calibration. ATTENTION! Ne pas sélectionner la hauteur complète. " "Seulement pour tester." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Calibration grossière" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Renseigne automatiquement le gain et le décalage pour numériser. Lorsque " "cette option n'est pas activée, il est possible de renseigner " "manuellement les paramètres gain et décalage dans l'application. Activée " "par défaut. Pour tester seulement." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "" "Utiliser la calibration grosière seulement à la première numérisation" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "La calibration grossière est effectuée uniquement à la première " "numérisation. Fonctionne avec la plupart des scanners et peut faire " "gagner du temps. Si l'intensité de chaque image est différente, " "désactiver cette option. Seulement pour tester." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Nombre de lignes de retour arrière" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Lorsque le scanner scanne plus vite qu'il ne peut envoyer les données, " "il doit ramener le chariot du capteur en arrière afin de reprendre la " "numérisation. Des valeurs petites permettent une numérisation plus " "rapide, au risque de perdre quelques lignes." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Valeur de gamma" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Sélectionne la valeur de gamma pour tous les canaux." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Géométrie" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Mode de numérisation" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Diapositive" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Modèle de scanner" #: backend/hp3900_sane.c:1408 #, fuzzy, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" "Permet de tester le comportement du périphérique en l'utilisant comme un " "autre modèle compatible" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Les couleurs de l'image seront inversées" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Désactiver la correction gamma" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "La correction gamma sera désactivée" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Désactiver la correction des ombres blanches" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "La correction des ombres blanches sera désactivée" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Omettre le préchauffage" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "Le préchauffage sera désactivé" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Forcer l'utilisation de la profondeur réelle" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "Si la correction gamma est activée, la numérisation sera toujours " "effectuée en 16 bits par couleur pour améliorer la qualité de l'image, " "puis convertie dans la profondeur demandée. Cette option évite de " "simuler la profondeur." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Simuler en niveaux de gris" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "Si activé, l'image sera numérisée en couleurs, puis convertie em niveaux " "de gris par logiciel. Cela peut permettre d'améliorer la qualité de " "l'image dans certaines circonstances." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Sauver les images de déboggage" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "Si activé, les images intermédiaires utilisées pendant la numérisation " "seront sauvegardées pour analyse." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Réinitialiser la puce" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Réinitialise les données de la puce" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Informations" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Nom de la puce" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Affiche le nom de la puce utilisée dans le périphérique" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Inconnu(e)" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "Identifiant de la puce" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Affiche l'identifiant de la puce" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Compteur de numérisations" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Affiche le nombre de numérisations effectuées par le scanner" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Rafraîchir les informations" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Rafraîchit les informations du périphérique" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Cette option reflète l'état d'un bouton de la façade du scanner" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Image" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Divers" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "décalage en X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Position X en haut à gauche de l'aire de numérisation" #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "décalage en Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Position Y en haut à gauche de l'aire de numérisation" #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Etat de la lampe" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Allume/éteint la lampe." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Calibration des niveaux noir et blanc." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "Chargeur automatique de documents" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "Adaptateur pour transparents - diapositives" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "Adaptateur pour transparents - négatifs" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Couleur (48 bits)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Délai allongé avant extinction de la lampe" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" "Allonge le délai avant l'extinction de la lampe (de 15 minutes à une " "heure)." #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Attendre le bouton" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Attend l'appui sur le bouton avant la numérisation" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Options avancées" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Grossier" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Précis" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Personnalisé" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automatique" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "RVB NTSC" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "RVB (pour transparents)" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Direct" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "Gris NTSC" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "Gris (pour transparents)" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Lent" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Rapide" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Très rapide" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2 pixels" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4 pixels" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8 pixels" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Imprimer" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Film-strip" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "Adaptateur pour transparents" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Conditionnel" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Essais" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Netteté" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Choisir la netteté" #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Seuil automatique" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Active la détection automatique du seuil pour la numérisation en mode " "trait." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Sélectionne le filtre de lissage." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Ejecter le document après la numérisation" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Ejecte le document après la numérisation." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Changer de document" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Change de document." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Ejecter" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Ejecter le document." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Démarrer la calibration." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Document" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Sélectionne le type de document." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Temps d'exposition" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Un temps d'exposition plus long permet au scanner de recevoir plus de " "lumière. Les valeurs suggérées sont : 175% pour des impressions, 150% " "pour des diapositives normales, et \"Négatif\" pour des négatifs. Pour " "les images sombres (sous-exposées), vous pouvez augmenter cette valeur." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Matrice de couleurs" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Sélectionne la matrice de couleurs du scanner." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Matrice personnalisée." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Matrice monochrome" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Matrice personnalisée pour numérisation en niveaux de gris." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Miroir horizontal" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Renverse l'image horizontalement." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Miroir vertical" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Renverse l'image verticalement." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Mettre les options à jour" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Mets à jour les options." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "Sortie en 8 bits" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Utilise plus de 8 bits de profondeur en interne, mais sort en 8 bits." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Attente de bouton avant" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Attendre l'appui sur le bouton du scanner avant de numériser." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Eteindre la lampe" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Eteint la lampe du scanner." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Taille du papier" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Séparation automatique" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 - paysage" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "Positionne le mode de contrôle de la densité" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Mise au point manuelle" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Mise au point manuelle" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Active la numérisation recto-verso" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Taille physique du papier dans le chargeur" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Demi-teinte" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Couleur" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Continuer" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Aucun" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Demi-teinte" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Demi-teinte" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Diffusion d'erreur" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Contraste" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "numériseur de transparents" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Avec du papier" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Valeur par défaut" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Lisse" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Lent" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Moyen" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Rouge" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Vert" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Source de numérisation" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Mode de chargement" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Sélectionne le mode de chargement" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Activer/désactiver la mise au point automatique" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Positionne le mode de contrôle de la densité" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Sélectionne le mode de chargement" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Sélectionne le mode de chargement" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Seuil automatique" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Fixe automatiquement la luminosité, le contraste, le niveau du blanc, le " "gamma, la réduction du bruit et l'accentuation de l'image" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Réduction du bruit" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Réduit le bruit isolé" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Accentuation de l'image" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Sélectionne l'accentuation de l'image" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Lampe allumée" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Allume/éteint la lampe." #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Renverse l'image verticalement." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Correction gamma" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Impression haute définition" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Impression basse définition" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Diffusion d'erreur" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Pas de correction" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normal" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Réglages fins" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Seuil automatique" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Seuil automatique" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Fixe l'orde des trames" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Ombré bleu" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Décalage rouge -> bleu" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamant" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "\"Graissage\" grossier 8x8" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "\"Graissage\" fin 8x8" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "Bayer 8x8" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "Ligne verticale 8x8" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Gain" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Réglages de gain des couleurs" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Gain des gris" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Fixe le gain pour le gris" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Gain des rouges" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Fixe le gain pour le rouge" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Gain des verts" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Fixe le gain pour le vert" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Gain des bleus" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Fixe le gain pour le bleu" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "'Dither' Bayer 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "'Dither' Bayer 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Demi-ton 32 points" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Demi-ton 64 points" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Diffusion d'erreur" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Mode 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Mode 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Mode 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "Avec le batonnet blanc" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Lisse" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Bas" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Moyen" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Haut" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "Tube cathodique" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Une page" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Toutes les pages" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "scanner avec chargeur automatique" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Niveau de gris 4 bits" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Niveau de gris 8 bits" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Ombrage, teinte moyenne, contraste, temps d'exposition" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Options spéciales" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Balance des couleurs" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Ne pas utiliser de retour arrière" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Si sélectionné, le scanner ne fera pas de retour arrière" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Allumer/éteindre la lampe du scanner" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Allumer/éteindre la lampe du scanner" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Calibration par le pilote" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Lorsque sélectionné, la calibration avant numérisation est effectuée par " "le pilote" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Utiliser l'adaptateur de diapositives" # flatbed is un-necessary here. Isn't it? #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Cette option éteint la lampe pendant la numérisation" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Numérisation de qualité" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Qualité maximale, mais vitesse réduite" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Numérisation rapide" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Vitesse maximale, mais qualité réduite" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Seuil automatique" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Lorsque sélectionné, le pilote détermine automatiquement la meilleure " "valeur du seuil." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Sélectionne le mode de correction gamma." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Lier les valeurs gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Utilise la même valeur gamma pour toutes les couleurs." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Valeur de gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Sélectionne une valeur numérique pour la correction gamma" #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Valeur de gamma rouge" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "" "Sélectionne une valeur numérique pour la correction gamma (canal rouge)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Valeur de gamma vert" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "" "Sélectionne une valeur numérique pour la correction gamma (canal vert)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Valeur de gamma bleu" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "" "Sélectionne une valeur numérique pour la correction gamma (canal bleu)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Canal" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Sélectionne la bande de couleur, \"Toutes\" signifie que toutes les " "couleurs sont affectées." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Teinte moyenne" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Sélectionne le niveau de luminosité équivalant à \"50% gris\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Teinte moyenne rouge" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Sélectionne le niveau de luminosité équivalant à \"50% rouge\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Teinte moyenne verte" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Sélectionne le niveau de luminosité équivalant à \"50% vert\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Teinte moyenne bleue" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Sélectionne le niveau de luminosité équivalant à \"50% bleu\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Balance des rouges" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Facteur de balance des rouges. 100% équivaut à pas de correction." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "balance des verts" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Facteur de balance des verts. 100% équivaut à pas de correction." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "balance des bleus" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Facteur de balance des bleus. 100% équivaut à pas de correction." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Balance (valeurs d'usines)" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Règle les valeurs de balance avec les valeurs d'usine." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Le plus lent" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Plus lent" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Plus rapide" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Le plus rapide" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 - Grossier" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 - Normal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 - Précis" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 - Très précis" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 - Normal" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 - Grossier" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 - Précis" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 - Grossier" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 - Normal" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 - Précis" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 - Normal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 - Normal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 - Personnalisé" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 - Personnalisé" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 - Personnalisé" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 - Personnalisé" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 - Personnalisé" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 - Personnalisé" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Mode gris rapide" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Numérise rapidement en mode gris (qualité réduite)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Les aperçus seront effectués dans le mode le plus rapide (basse " "qualité). Ce peut etre en noir et blanc, et/ou dans une basse en " "résolution." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Temps avant extinction de la lampe (en minutes)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Fixe le temps (en minutes) au-delà du quel la lampe est éteinte." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Eteint la lampe." #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Eteint la lampe du scanner maintenant" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Luminosité des rouges" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Contrôle la brillance rouge de l'image à numériser." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Luminosité des verts" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Contrôle la brillance verte de l'image à numériser." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Luminosité des bleus" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Contrôle la brillance bleue de l'image à numériser." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contraste - rouge" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Contrôle le contraste rouge de l'image à numériser." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contraste - vert" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Contrôle le contraste vert de l'image à numériser." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contraste - bleu" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Contrôle le contraste bleu de l'image à numériser." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Couleur 48 bits" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Couleur 24 bits" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Gris 16 bits" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Gris 8 bits" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Réfléchissant" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positif" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Préchauffer jusqu'à ce que l'intensité de la lampe soit constante, au " "lieu d'attendre 40 secondes." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Film négatif" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Négatif" #: backend/pixma.c:396 #, fuzzy, no-c-format msgid "48 bits color" msgstr "Couleurs précises" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Numérisation contrôlée par le bouton du scanner" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Si activé, la numérisation commencera à l'appui du bouton \"SCAN" "\" (MP150), ou du bouton \"COLOR\" (autres modèles). Appuyez sur le " "bouton \"GRAY\" pour annuler la numérisation." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Rafraîchir l'état du bouton" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Bouton 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Bouton 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Transparence" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Paramètres du périphérique" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Eteindre/allumer la (les) lampes" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Eteindre/allumer la (les) lampes manuellement." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Eteindre la lampe durant la calibration des noirs" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Toujours éteindre la lampe durant la calibration des noirs" #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Cache des données de calibration" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Active/désactive le cache des données de calibration" #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Effectue la calibration" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Accélérer le capteur" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Active l'accélération du mouvement du capteur." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Temps de préchauffage" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Temps de préchauffage en secondes." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Temps avant extinction de la lampe" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Temps avant extinction de la lampe en secondes." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Frontal analogique (AFE)" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Gain des rouges du frontal analogique (AFE)" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Décalage des rouges" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Décalage des rouges du frontal analogique (AFE)" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Gain des verts du frontal analogique (AFE)" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Décalage des verts du frontal analogique (AFE)" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Gain des bleus du frontal analogique (AFE)" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Décalage des bleus du frontal analogique (AFE)" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Délai avant extinction de la lampe rouge." #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Définit le délai avant extinction de la lampe rouge." #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Délai avant extinction de la lampe verte." #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Définit le délai avant extinction de la lampe verte." #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Délai avant extinction de la lampe bleue." #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Définit le délai avant extinction de la lampe bleue." #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Cette option affiche l'état des boutons du scanner." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Couleur 36 bits" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Carte de 'dither' 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Carte de 'dither' 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Aléatoire" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Sélection de la source" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Amélioration de l'image" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Griser" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Charger l'image en tant que niveaux de gris." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Simulation d'une numérisation à trois passes" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simule une numérisation à trois passes, en renvoyant 3 trames séparées. " "Pour le fun, renvoie la trame verte, puis bleue, puis rouge." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Simulation de scanner à main." #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simule une numérisation avec un scanner à main. Les scanners à main ne " "connaissent pas à priori la hauteur de l'image. A la place, ils " "renvoient une hauteur de -1. Sélectionner cette option permet de tester " "si une interface peut le supporter correctement." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Sélectionne les valeurs par défaut pour les contrles d'amélioration " "(luminosité et contraste)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Option de test de lecture seule" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Voyons si l'interface traite correctement ceci" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Tables de gamma" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Simulation du code d'état" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Ne pas forcer le code d'état" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Ne pas obliger le pilote à renvoyer un code d'état." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Renvoie SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Oblige le pilote à renvoyer le code SANE_STATUS_EOF (fin de fichier) " "après un appel à sane_read()." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Renvoie SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Oblige le pilote à renvoyer le code SANE_STATUS_JAMMED (bourrage) après " "un appel à sane_read()." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Renvoie SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Oblige le pilote à renvoyer le code SANE_STATUS_NO_DOCS (pas de ) " "après un appel à sane_read()." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Renvoie SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Oblige le pilote à renvoyer le code SANE_STATUS_COVER_OPEN (couvercle " "soulevé) après un appel à sane_read()." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Renvoie SANE_SATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Oblige le pilote à renvoyer le code SANE_STATUS_IO_ERROR (erreur " "d'entrée/sortie après un appel à sane_read()." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Renvoie SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Oblige le pilote à renvoyer le code SANE_STATUS_NO_MEM (pas de mémoire) " "après un appel à sane_read()." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Renvoie SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Oblige le pilote à renvoyer le code SANE_STATUS_ACCESS_DENIED (acces " "refusé) après un appel à sane_read()." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Cette option affiche l'état d'un bouton du scanner." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lampe allumée" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Allume la lampe du scanner" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lampe éteinte" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Eteint la lampe du scanner" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Délai avant extinction de la lampe" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Délai en minutes avant d'éteindre la lampe après une numérisation." #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Seuil pour le mode trait" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Chargeur automatique de document" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6\"x4\" (~15x10 cm)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8\"x10\" (~20x25 cm)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5\"x11\" (~21x28 cm)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Demi-teinte non-supportée" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "Points dispersés 8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "Points dispersés 16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Nombre de lignes à transférer en un cycle de lecture SCSI. Changer ce " "paramètre vous permet de contrôler la vitesse à laquelle les données " "sont lues à partir du scanner. Une valeur trop basse obligera le scanner " "à faire des pauses lors du transfert, tandis qu'une valeur trop élevée " "pourrait empécher les applications Xwindow de traiter les évènements X, " "et votre système pourrait s'écrouler." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Ejecte le document après la numérisation" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Aperçu" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Sélectionne le mode de prévisualisation. Les aperçus en niveaux de gris " "donnent habituellement le meilleur compromis entre vitesse et détails." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Valeurs prédéfinies" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Fournit des emplacements standards pour la numérisation de photos, de " "pages imprimées, etc..." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "numériseur à plat" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Mise au point" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Mise au point automatique" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Mise-au-point" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Mise-au-point" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Nombre de lignes en couleurs par cycle de lecture" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Nombre de lignes en niveaux de gris par cycle de lecture" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "webcam" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Couleur RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Couleur RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Couleur RGB TEXTE" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Noir pur" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Blanc pur" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Motif couleur" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Grille" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Premier choix" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Second choix" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Ceci est la troisième entrée, la plus longue. Peut-etre l'application " "sait-elle comment l'afficher..." #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Simulation de scanner à main" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simule un scanner à main. Les scanners à main ne connaissent pas à " "priori la hauteur de l'image. A la place, ils renvoient une auteur de " "-1. Sélectionner cette option permet de tester si une interface peut le " "supporter correctement. Cette option fixe aussi la largeur de " "numérisation à 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Simulation d'une numérisation à trois passes" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simule une numérisation à trois passes, en renvoyant 3 trames séparées." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Fixe l'orde des trames" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Fixe l'ordre des trames dans une numérisation à trois passes." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Si le chargeur de document est sélectionné, il sera 'vide' après 10 " "numérisations." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Options spéciales" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Sélectionne l'image de test" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Sélectionne le type d'image de test parmi :\n" "Noir complet : la numérisation est toute noire.\n" "Blanc complet : la numèrisation est toute blanche.\n" "Motif en couleurs : la numérisation est composée de différents motifs, " "en fonction du mode.\n" "Grille : la numérisation donne une grille noire sur fond blanc, dont " "lescarrés font 10 mm de coté." # YEM-20030211 : As foolish as it may appear, endian has been translated # into french as 'indien', although it has nothing to do with 'Indians'. #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Inversion petit/grand indien" # YEM-20030211 : As foolish as it may appear, endian has been translated # into french as 'indien', although it has nothing to do with 'Indians'. #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Inverse les octets de poids faible et de poids fort dans les résolutions " "à 1- bits. Ce peut-etre utile pour tester le support petit/grand indien " "d'une interface." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Limite de lecture" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Limite la quantité de données qui sont transmises à chaque appel à " "sane_read()" #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Taille de la limite de lecture" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "La taille maximale des données transférées à chaque appel à sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Délai à la lecture" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Retarde le transfert des données lues." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Durée du délai de lecture" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "Temps à attendre après avoir transféré les données lues." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Valeur de retour de sane_read()" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Fixe la valeur de retour de sane_read(). \"Défaut\" sélectionne le " "fonctionnement normal pour la numérisation. Toute autre valeur permet de " "tester les applications." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Nombre de pixels perdus par ligne" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Le nombre de pixels perdus à la fin de chaque ligne lue." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Paramètres délirants" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Renvoie des valeurs abhérantes pour le nombre de lignes et d'octets par " "ligne quand sane_parameters() est appelé avant sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "E/S non bloquantes" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Utilise un méchanisme d'E/S non bloquantes pour sane_read(), si supporté " "par l'application." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Proposer un descripteur de fichier pour select(2)" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Présente un descripteur de fichier de type select(2) pour tester si un " "appel a sane_read() renverra des données." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Active les options de test" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Active diverses options de test. Pour tester la capacité des " "applications à obtenir et modifier tous les types d'options de SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Liste des options" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Affiche une liste de toutes les options." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Options test - booléens" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Modification et lecture logicielles" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Option booléenne lisible et modifiable par l'application. C'est " "juste une option 'normale'." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Modification matérielle et lecture logicielle" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Option booléenne lisible par l'application et modifiable par le " "matériel (ex. un bouton sur le périphérique)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Option booléenne modifiable par le matériel." #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Option booléenne modifiable par le matériel (ex. un bouton sur le " "périphérique) et dont le status ne peut pas etre lu par l'application." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Option booléenne lisible par logiciel" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Option booléenne lisible par le logiciel. Cette option est en " "lecture seule." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Option booléenne émulée" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Options booléenne émulée, lisible et modifiable par le logiciel." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Option booléenne automatique" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Option booléenne lisible et modifiable par le logiciel. Cette " "option peut être modifiée automatiquement par le pilote." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Options test - entiers" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Entier" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Option à valeur entière sans unité ni domaine de variations." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Entière avec domaine." #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Option à valeur entière avec domaine de variations. Unité: pixel. " "Min: 4. Max: 192. Pas: 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Entier listé" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Option à valeur entière dont les valeurs possibles sont contenues " "dans une liste. Untié : bit." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Tableau d'entiers" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Tableau d'options à valeur entière sans domaine de variations. " "Unité : mm." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Tableau d'entiers avec domaine" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Tableau d'options à valeur entière avec domaine de variations. " "Unité: dpi. Min: 4. Max: 192. Pas: 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Tableau d'entiers à valeurs listées" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Tableau d'options à valeur entière dont les valeurs possibles sont " "contenues dans des listes. Unité : %." # YEM-20030216 : I understand that 'fixed' is to be opposed to 'float'. #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Options test - réels fixes" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Réel fixe" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" "(1/3) Option à valeur réelle (virgule fixe) sans unité ni domaine de " "variations." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Réel fixe avec domaine" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Option à valeur réelle (virgule fixe) avec domaine de variations. " "Unité: µs. Min: -42,17. Max: 32767,9999. Pas: 2,0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Réel fixe listé" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Option à valeur réelle (vurgule fixe) sans unité et dont les " "valeurs possibles sont dans une liste." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Options test - chaînes de caractères" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) Chaîne" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Chaîne de caractères sans contrainte." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) Chaîne listée" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "" "(2/3) Chaîne de caractères dont les valeurs possibles sont dans une " "liste." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) Chaine listée (longue)" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) Chaine de caractères dont les valeurs possibles sont dans une " "liste. Plus de choix..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Options test - boutons" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Bouton" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Bouton de test. Affiche du texte..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Couleur 36 bits" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Utiliser la composition d'images" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Noir et blanc (mode trait)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Noir et blanc (mode tramé)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Niveaux de gris" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Couleur RVB (une passe)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignorer la calibration" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Désactiver la mise au point" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Ne calibre pas la mise au point" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Mise au point manuelle" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Mise au point fixe" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Calibration de la lentille en mode document" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Calibre la lentille en mode document." #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Mise au point au niveau de la vitre" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Effectue la mise au point à 0mm de la vitre au lieu de 0.6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Mode de calibration" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Définit le mode de calibration" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Allume/éteint la lampe." #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "Activer l'UTA" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Activer/déactiver l'adaptateur universel de transparents (UTA)" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Décalage" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Réglages de décalage des couleurs" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Décalage des gris" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Fixe le décalage pour le gris" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Fixe le décalage pour le rouge" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Fixe le décalage pour le vert" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Fixe le décalage pour le bleu" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Aperçu" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "problème non traité (classe SCSI inconnue)" #~ msgid "Grayscale" #~ msgstr "Niveaux de gris" #~ msgid "Binary" #~ msgstr "Noir et blanc" #~ msgid "Display a shortened resolution list" #~ msgstr "Affiche une liste réduite d'échantillonnage" #~ msgid "Black & White" #~ msgstr "Noir & blanc" sane-backends-1.0.27/po/nb.po0000664000175000017500000037764213110600537012616 00000000000000# Norwegian translation for SANE backend options # Copyright (C) 2003 SANE Project. # Sigurd Stordal, polarbear42@phreaker.net, 2003. msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.12\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-12-17 23:01+0100\n" "Last-Translator: Sigurd Stordal \n" "Language-Team: \n" "Language: nb\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometri" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Forbedring" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Avansert" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Forvisning" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Fremtving enfarge forvisning" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bit dybde" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Skanhastighet" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Skankilde" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Topp-venstre x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Topp-venstre y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Bunn-høyre x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Bunn-høyre y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Skanoppløsning" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-oppløsning" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-oppløsning" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Kornstørrelse" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "SvartnivÃ¥" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "HvitnivÃ¥" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "HvitnivÃ¥ for rød" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "HvitnivÃ¥ for grønn" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "HvitnivÃ¥ for blÃ¥" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Skygge" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Skygge for rød" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Skygge for grønn" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Skygge for blÃ¥" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Filnavn" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativ" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Kvalitets kalibrering" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Dobble Optisk Oppløsning" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Varmopp lampe" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lampen slÃ¥s av ved avslutning" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Kort liste over oppløsninger" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Skanoppløsning" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "" #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "" #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Velger skan kilde (slik som arkmater)" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "" #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "venstre topp x posisjon av skan-areal" #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Venstre topp y posisjon av skan-areal" #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Høyre bunn x posisjon av skan-areal" #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Høyre bunn y posisjon av skan-areal" #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "" #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "" #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "" #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "" #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "" #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "" #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "" #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Filnavnet pÃ¥ bildet som skal lastes opp" #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Bruk samme verdier for X og Y oppløsning" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Bytt svart og hvitt" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Foreta en kvalitets hvit-kalibrering" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Bruk linser som dobbler den optiske oppløsningen" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Varm opp lampen før skanning" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "SlÃ¥ av lampen nÃ¥r programmet avslutter" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Skanoppløsning" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "Vent pÃ¥ knappen" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "Vent pÃ¥ knappen" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "Vent pÃ¥ knappen" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Fargemønster" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Farge" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Fargestrektegning" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "GrÃ¥" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Strektegning" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "Dokumentmater" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "Dokumentmater" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Standard" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Velg standard verdier for kontroll av forbedring" #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibrering" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Kalibrer før neste scan" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Bare utfør skygge-korrigering" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Knappstatus" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Rammenummer Ã¥ skanne" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Velger rammenummer Ã¥ skanne" #: backend/avision.h:782 #, fuzzy, no-c-format msgid "Duplex scan" msgstr "Full skan" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" #: backend/canon630u.c:159 #, fuzzy, no-c-format msgid "Calibrate Scanner" msgstr "Kalibrering" #: backend/canon630u.c:160 #, fuzzy, no-c-format msgid "Force scanner calibration before scan" msgstr "Grov kalibrering kun for første skan" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "GrÃ¥skala scan" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Gjør et grÃ¥skala heller enn farge scan" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gamma korreksjon" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Velger den gamma korrigerte overførsels kurven" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, fuzzy, no-c-format msgid "No transparency correction" msgstr "Farge korreksjon" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, fuzzy, no-c-format msgid "Negatives" msgstr "Negativ" #: backend/canon.c:176 #, fuzzy, no-c-format msgid "Slides" msgstr "Treigest" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatisk" #: backend/canon.c:186 #, fuzzy, no-c-format msgid "Normal speed" msgstr "Skanhastighet" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, fuzzy, no-c-format msgid "lamp failure" msgstr "Gammaverdi" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Filmtype" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, fuzzy, no-c-format msgid "Negative film type" msgstr "Negativ Film" #: backend/canon.c:1197 #, fuzzy, no-c-format msgid "Selects the negative film type" msgstr "Velger rammenummer Ã¥ skanne" #: backend/canon.c:1236 #, fuzzy, no-c-format msgid "Hardware resolution" msgstr "Skanoppløsning" #: backend/canon.c:1237 #, fuzzy, no-c-format msgid "Use only hardware resolutions" msgstr "Vis kort liste over oppløsninger" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, fuzzy, no-c-format msgid "Auto focus" msgstr "Automatisk utløsning" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, fuzzy, no-c-format msgid "Manual focus position" msgstr "Fokuseringposisjon" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Speilbilde" #: backend/canon.c:1539 #, fuzzy, no-c-format msgid "Mirror the image horizontally" msgstr "Speilbilde" #: backend/canon.c:1608 #, fuzzy, no-c-format msgid "Auto exposure" msgstr "Automatisk utløsning" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "" #: backend/canon.c:1625 #, fuzzy, no-c-format msgid "Calibration now" msgstr "Kalibrering" #: backend/canon.c:1626 #, fuzzy, no-c-format msgid "Execute calibration *now*" msgstr "Kvalitets kalibrering" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, fuzzy, no-c-format msgid "Reset scanner" msgstr "Raskt skan" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, fuzzy, no-c-format msgid "Eject film after each scan" msgstr "Løs ut dokoment etter skanning" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, fuzzy, no-c-format msgid "Document feeder extras" msgstr "Dokumentmater" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, fuzzy, no-c-format msgid "Negative film" msgstr "Negativ Film" #: backend/canon.c:1740 #, fuzzy, no-c-format msgid "Positive or negative film" msgstr "Lysbilde Film" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "" #: backend/canon.c:1775 #, fuzzy, no-c-format msgid "Select film type" msgstr "Filmtype" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "" #: backend/canon_dr.c:412 #, no-c-format msgid "Card Front" msgstr "" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, no-c-format msgid "Card Duplex" msgstr "" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Rød" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Grønn" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "BlÃ¥" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Forbedring" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Forbedring" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Forbedring" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Ingen" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Lysbilde Film" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negativ Film" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Fokuser pÃ¥ glasset" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Fokuser 2.5mm over glasset" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Tekst Fremhevings Teknologi" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Last ned mønster A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Last ned mønster B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Ingen korrigering" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Brukerdefinert" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Blekkskrivere" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Standard" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Høy densitets utskrift" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "lav densitets utskrift" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Høy kontrasts utskrift" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Brukerdefinert (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Brukerdefinert (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 portrett" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 landskap" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Maks" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "" #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Skarphet" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Farge korreksjon" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Farge korreksjons koeffisienter" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Kontrollerer grønn-nivÃ¥" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Legger til rødt basert pÃ¥ grønn-nivÃ¥" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Legger til blÃ¥tt basert pÃ¥ grønn-nivÃ¥" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Legger til grønt basert pÃ¥ rød-nivÃ¥" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Kontrollerer rød-nivÃ¥" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Legger til blÃ¥tt basert pÃ¥ rød-nivÃ¥" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Legger til grønt basert pÃ¥ blÃ¥-nivÃ¥" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Legger til rødt basert pÃ¥ blÃ¥-nivÃ¥" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Kontrollerer blÃ¥-nivÃ¥" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Speil bildet" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Rask forvisning" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Automatisk oppdeling av areal i delareal" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Kort liste over oppløsninger" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Vis kort liste over oppløsninger" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Tilleggsutstyr" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Utløs" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Utløs arket i ADF" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Automatisk utløsning" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Løs ut dokoment etter skanning" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Fokuseringposisjon" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Vent pÃ¥ knappen" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Etter at kommandoen for skan er sendt, vent til skannerens knapp " "ertrykket før skanings prossesen startes." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, fuzzy, no-c-format msgid "Positive Slide" msgstr "Lysbilde Film" #: backend/epson2.c:137 #, fuzzy, no-c-format msgid "Negative Slide" msgstr "Negativ Film" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Brukerdefinert" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "HvitnivÃ¥" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "SvartnivÃ¥" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, no-c-format msgid "Halftone type" msgstr "" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Grov kalibrering" #: backend/fujitsu.c:3221 #, no-c-format msgid "Emphasis" msgstr "" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Kalibrering" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "" #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Speilbilde" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Speilbilde" #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "HvitnivÃ¥ for blÃ¥" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Kontrollerer rød-nivÃ¥" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Fargestrektegning" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Gammaverdi" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, no-c-format msgid "Threshold white" msgstr "" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Støyreduksjon" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Ingen korrigering" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Ingen korrigering" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, no-c-format msgid "DF recovery mode" msgstr "" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Spesielle valg" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Ingen korrigering" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Lampe pÃ¥" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, no-c-format msgid "Buffer mode" msgstr "" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Lampe av" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Lampe av" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, fuzzy, no-c-format msgid "Green offset" msgstr "Lampe av" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Lampe av" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, fuzzy, no-c-format msgid "Blue offset" msgstr "Lampe av" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Kontrast blÃ¥kanal" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Full skan" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Spesielle valg" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Støyreduksjon" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Fra papir" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Fra papir" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Fra papir" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Fra papir" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Manuell førfokus" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Manuell førfokus" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "Skanoppløsning" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "HvitnivÃ¥" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "lav densitets utskrift" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Full skan" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Fargestrektegning" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibrering" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Kvalitets kalibrering" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Kalibrering" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, fuzzy, no-c-format msgid "Lamp off time" msgstr "Lampe av" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Grov kalibrering" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "Vent pÃ¥ knappen" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "Vent pÃ¥ knappen" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Vent pÃ¥ knappen" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Grov kalibrering" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Grov kalibrering kun for første skan" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, fuzzy, no-c-format msgid "Buttons" msgstr "Knappstatus" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, fuzzy, no-c-format msgid "Calibrate" msgstr "Kalibrering" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Grov kalibrering" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Grov kalibrering" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Kalibrering" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatisk oppvarming" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Full skan" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Grov kalibrering" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Grov kalibrering kun for første skan" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gammaverdi" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "" #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "Geometri" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "Gamma korreksjon" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "Gamma korreksjon" #: backend/hp3900_sane.c:1451 #, fuzzy, no-c-format msgid "Disable white shading correction" msgstr "Bare utfør skygge-korrigering" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "GrÃ¥skala" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "Raskt skan" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Se bort fra kalibrering" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Filnavn" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "Raskt skan" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "Skankilde" #: backend/hp3900_sane.c:1584 #, fuzzy, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Velger rammenummer Ã¥ skanne" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Spesielle valg" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "" #: backend/hp5400_sane.c:358 #, fuzzy, no-c-format msgid "offset X" msgstr "Lampe av" #: backend/hp5400_sane.c:359 #, fuzzy, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "venstre topp x posisjon av skan-areal" #: backend/hp5400_sane.c:368 #, fuzzy, no-c-format msgid "offset Y" msgstr "Lampe av" #: backend/hp5400_sane.c:369 #, fuzzy, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "venstre topp x posisjon av skan-areal" #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "" #: backend/hp5590.c:88 #, fuzzy, no-c-format msgid "TMA Slides" msgstr "Treigest" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Negativ" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "Farge 48" #: backend/hp5590.c:95 #, fuzzy, no-c-format msgid "Extend lamp timeout" msgstr "Lampe av" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Vent pÃ¥ knappen" #: backend/hp5590.c:99 #, fuzzy, no-c-format msgid "Waits for button before scanning" msgstr "Varm opp lampen før skanning" #: backend/hp-option.c:2984 #, fuzzy, no-c-format msgid "Advanced Options" msgstr "Spesielle valg" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Grov" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fin" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Valgfri" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automatisk" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC-grÃ¥" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA-grÃ¥" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Treig" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Rask" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "" #: backend/hp-option.c:3175 #, fuzzy, no-c-format msgid "Film-strip" msgstr "Filmtype" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "" #: backend/hp-option.h:60 #, fuzzy, no-c-format msgid "Sharpening" msgstr "Skarphet" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "" #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "" #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "" #: backend/hp-option.h:80 #, fuzzy, no-c-format msgid "Unloads the media after a scan." msgstr "Last bildet som grÃ¥skala" #: backend/hp-option.h:85 #, fuzzy, no-c-format msgid "Change document" msgstr "Forbedring" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "" #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "" #: backend/hp-option.h:98 #, fuzzy, no-c-format msgid "Start calibration process." msgstr "Grov kalibrering" #: backend/hp-option.h:103 #, fuzzy, no-c-format msgid "Media" msgstr "Middels" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "" #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" #: backend/hp-option.h:119 backend/hp-option.h:126 #, fuzzy, no-c-format msgid "Color Matrix" msgstr "Fargemønster" #: backend/hp-option.h:121 #, fuzzy, no-c-format msgid "Set the scanners color matrix." msgstr "Kontrast rødkanal" #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "" #: backend/hp-option.h:132 #, fuzzy, no-c-format msgid "Mono Color Matrix" msgstr "Fargemønster" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "" #: backend/hp-option.h:138 #, fuzzy, no-c-format msgid "Mirror horizontal" msgstr "Speilbilde" #: backend/hp-option.h:139 #, fuzzy, no-c-format msgid "Mirror image horizontally." msgstr "Speilbilde" #: backend/hp-option.h:144 #, fuzzy, no-c-format msgid "Mirror vertical" msgstr "Speilbilde" #: backend/hp-option.h:145 #, fuzzy, no-c-format msgid "Mirror image vertically." msgstr "Speilbilde" #: backend/hp-option.h:150 #, fuzzy, no-c-format msgid "Update options" msgstr "Spesielle valg" #: backend/hp-option.h:151 #, fuzzy, no-c-format msgid "Update options." msgstr "Spesielle valg" #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "SlÃ¥ av skanner lampen." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Papirstørrelse" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 landskap" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Manuell førfokus" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Manuell førfokus" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Fysisk størrelse av papir i ADF" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Farge" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, no-c-format msgid "normal" msgstr "" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, no-c-format msgid "light" msgstr "" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "Fra papir" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Fra papir" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Standard" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Treig" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Middels" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Rød" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Grønn" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Skankilde" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Velger mÃ¥ten Ã¥ foreta gamma korreksjon pÃ¥" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Støyreduksjon" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Lampe pÃ¥" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Speilbilde" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gamma korreksjon" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Høy densitets utskrift" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "lav densitets utskrift" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Ingen korrigering" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Skanhastighet" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Forbedring" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Automatisk oppvarming" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Velger mÃ¥ten Ã¥ foreta gamma korreksjon pÃ¥" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Skygge for blÃ¥" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Skygge for blÃ¥" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamant" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, fuzzy, no-c-format msgid "Gray gain" msgstr "Grønn" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, fuzzy, no-c-format msgid "Sets gray channel gain" msgstr "Kontrast grønnkanal" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, fuzzy, no-c-format msgid "Red gain" msgstr "Rødbalanse" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, fuzzy, no-c-format msgid "Sets red channel gain" msgstr "Kontrast rødkanal" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, fuzzy, no-c-format msgid "Green gain" msgstr "Grønn" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, fuzzy, no-c-format msgid "Sets green channel gain" msgstr "Kontrast grønnkanal" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, fuzzy, no-c-format msgid "Blue gain" msgstr "BlÃ¥" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, fuzzy, no-c-format msgid "Sets blue channel gain" msgstr "Kontrast blÃ¥kanal" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Lav" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Middels" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Høy" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "En side" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Alle sider" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "GrÃ¥skala 4 bits" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "GrÃ¥skala 8 bits" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Spesielle valg" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Fargebalanse" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Kvalitetsskan" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Høyest kvalitet men laver hastighet" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Raskt skan" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Høyest hastighet men lavest kvalitet" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Velger mÃ¥ten Ã¥ foreta gamma korreksjon pÃ¥" #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Bruk samme gamma verdi for alle farge kanalene" #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "" #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Kanal" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "" #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Rødbalanse" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" "Balansefaktor for rødt. Med en verdi pÃ¥ 100 % menes ingen korreksjon" #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Grønnbalanse" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" "Balansefaktor for grønt. Med en verdi pÃ¥ 100% menes ingen korreksjon" #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "BlÃ¥balanse" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" "Balansefaktor for blÃ¥tt. Med en verdi pÃ¥ 100% menes ingen korreksjon" #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Treigest" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Treigere" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Raskere" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Raskest" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 grov" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fin" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 veldig fin" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 grov" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fin" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 grov" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fin" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 valgfri" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 valgfri" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 valgfri" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 valgfri" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 valgfri" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 valgfri" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "" #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" #: backend/mustek.c:4341 #, fuzzy, no-c-format msgid "Lamp off time (minutes)" msgstr "Varmopp lampe" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "" #: backend/mustek.c:4353 #, fuzzy, no-c-format msgid "Turn lamp off" msgstr "Lampe av" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "" #: backend/mustek.c:4444 #, fuzzy, no-c-format msgid "Green brightness" msgstr "Grønnbalanse" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "" #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "" #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Kontrast rødkanal" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "" #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Kontrast grønnkanal" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "" #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Kontrast blÃ¥kanal" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "" #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Farge 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Farge 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "GrÃ¥ 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "GrÃ¥ 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, fuzzy, no-c-format msgid "Positive" msgstr "Lysbilde Film" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Negativ Film" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negativ" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, fuzzy, no-c-format msgid "Update button state" msgstr "Knappstatus" #: backend/pixma_sane_options.c:244 #, fuzzy, no-c-format msgid "Button 1" msgstr "Knappstatus" #: backend/pixma_sane_options.c:258 #, fuzzy, no-c-format msgid "Button 2" msgstr "Knappstatus" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "" #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Grov kalibrering" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, fuzzy, no-c-format msgid "Calibration data cache" msgstr "Kalibrering" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "" #: backend/plustek.c:942 #, fuzzy, no-c-format msgid "Performs calibration" msgstr "Grov kalibrering" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, fuzzy, no-c-format msgid "Warmup-time" msgstr "Varmopp lampe" #: backend/plustek.c:975 #, fuzzy, no-c-format msgid "Warmup-time in seconds." msgstr "Varmopp lampe" #: backend/plustek.c:987 #, fuzzy, no-c-format msgid "Lampoff-time" msgstr "Lampe av" #: backend/plustek.c:988 #, fuzzy, no-c-format msgid "Lampoff-time in seconds." msgstr "Varmopp lampe" #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, fuzzy, no-c-format msgid "Red offset" msgstr "Lampe av" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, fuzzy, no-c-format msgid "Red lamp off" msgstr "Lampe av" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "" #: backend/plustek.c:1057 #, fuzzy, no-c-format msgid "Green lamp off" msgstr "Lampe av" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "" #: backend/plustek.c:1065 #, fuzzy, no-c-format msgid "Blue lamp off" msgstr "Lampe av" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Farge 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Valg av kilde" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Last bildet som grÃ¥skala" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Trepass simulering" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "HÃ¥ndskanner simulering" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Status Kode Simulering" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Ikke fremtving status kode" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "" #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lampe pÃ¥" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "SlÃ¥ pÃ¥ skanner lampen" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lampe av" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "SlÃ¥ av skanner lampen" #: backend/sm3840.c:760 #, fuzzy, no-c-format msgid "Lamp timeout" msgstr "Lampe av" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Dokumentmater" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Løs ut dokoment etter skanning" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "Fra papir" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Automatisk utløsning" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Fokuseringposisjon" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Fokuseringposisjon" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Farge RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Farge RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Farge RGB TEKST" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Fargemønster" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "" #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "" #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "" #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "" #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "" #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "" #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Farge 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Bruk Bilde Komposisjon" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "TonivÃ¥ svart og hvitt (strektegningmodus)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "FlernivÃ¥ svart og hvitt (grÃ¥skalamodus)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "FlernivÃ¥ RGB farge (en omgangs farge)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Se bort fra kalibrering" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Ikke kalibrer fokus" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Manuell førfokus" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "" #: backend/umax_pp.c:780 #, fuzzy, no-c-format msgid "Gray offset" msgstr "Lampe av" #: backend/umax_pp.c:781 #, fuzzy, no-c-format msgid "Sets gray channel offset" msgstr "Kontrast grønnkanal" #: backend/umax_pp.c:793 #, fuzzy, no-c-format msgid "Sets red channel offset" msgstr "Kontrast rødkanal" #: backend/umax_pp.c:805 #, fuzzy, no-c-format msgid "Sets green channel offset" msgstr "Kontrast grønnkanal" #: backend/umax_pp.c:817 #, fuzzy, no-c-format msgid "Sets blue channel offset" msgstr "Kontrast blÃ¥kanal" #~ msgid "Grayscale" #~ msgstr "GrÃ¥skala" #~ msgid "Binary" #~ msgstr "Binær" #, fuzzy #~ msgid "Display a shortened resolution list" #~ msgstr "Vis kort liste over oppløsninger" #~ msgid "Black & White" #~ msgstr "Svart og hvit" sane-backends-1.0.27/po/ja.gmo0000664000175000017500000015117513110600540012736 00000000000000Þ•£4‹L*x8y8Š8›8 £8 ®8 ¹8 Ä8Ï8 ×8 â8í8 ö8 9 9 9 "9/9 79 E9 Q9[9n99 ‘9œ9 Ÿ9 ¬9¸9¼9 Å9 Ð9Ú9ã9ò9"ú9!:?:!_: :¢: Â:ã:ì:sý: q; {;‡;—;©;Á;Ô;å; ý;!<@<`<e<t< ‹< –< ¤<¯< Ä<Î<!è< ==</=Gl=_´=>>*>:>C>[> m> x> ‚>Ž> “> > °>º>Õ> ä>ò>%?'?%6? \?g?p? y?†??¥?¨?¸? ¼?É?Ü?ø?@0@ B@L@^@%y@ Ÿ@«@Â@Ù@ é@÷@AA A +A8AJAbAiA&|A£A©A ¹A ÆA ÐAÚA éA÷AB %B3B ;BGBPBdByB.ŒBB»BCþBABC,„C ±C!½C*ßC DD(DEDZDlDtD)}D"§D*ÊD#õD(E!BEdE#‚E¦EÃE ãE,F'1FYF iFuF…F1F¿FÔF íFG,G3GHG^GxG ’G žG%ªG&ÐG÷GH H7H NHoH‰HœH¯H·H ¾HEÊHI'I-IKIfI}IŒI¡I ¼IÉI#ÛI?ÿI!?JaJuJ÷J(K:K NKZKjK‚K œK §KµK ÉKÔKìKóKøK L LL%L -L 8L DLPL YL cLnL sL~L L›L £L°L¶LÎLÝLìLM%M^\ J\ U\ `\m\Œ\%¡\ Ç\Õ\ä\ þ\ ]] ']4]:] W]Me]³] Ç] Ô]á]ñ] ^ ^ ^ ^M%^s^ w^ƒ^’^›^ µ^ Ã^Î^ê^| _ ‡_ •_£_µ_ É_ê_``;`U`p`[Š`æ`a aa 3a@aRaea va€a a ±a ½aÊaÝaùab'1bYb kb xb‚b ’b žbx©b"c&8c _cmc ‰c–c.§cÖcïcgdld%„dªdÂd/×d*e"2e‡UeÝeóe'f<:fwf†f,Žf»fÔfæf÷f? gMg1eg—g;¶gòghh3hKh?ah¡hD·h%üh4"iWi)oi2™iÌÌi™j j°jÁj)Ðj új kk#k5kIk\knkk"—kºk)Ïk ùkllÐ&lp÷lKhm´mÇmÛmámèmímômüm n n#nBnRn"bn…n”nn%¸nÞnõnýn<oOo lo zo…oGžo'æoup„p4•p;Êpqq 2q *Z'…­*Æñ ‘*&‘!Q‘9s‘*­‘Ø‘Ü÷‘Ô’-ó’!“@“G“$W“'|“ ¤“ ®“$»“ à“ê“ú“””!” 7”D”K”R”k”„”š”ª”À”Ö” Ú”!䔕•5•Q•5X• Ž•'›•0Õ!ô•0–’G–uÚ–xP— É—Ó—é— ˜ ˜%˜ ,˜6˜F˜\˜'l˜ ”˜-¡˜-Ϙ-ý˜+™2™E™ L™V™f™ |™!‰™!«™Í™é™í™ ý™ šš *š7šMš`š šŒš.“š+š+îš›8›!V›*x›£›0¼›3í›-!œ1Oœ.œ°œ*Ìœ÷œûœ*'$Rw‡³ ÉcÓ7žl>žá«žüŸlŠ ´÷  ¬¡¸¢¿¢*Ò¢ ý¢ £!£$?£<d£6¡£Ø£!ߣ¤¤K-¤y¤$‰¤0®¤!ߤ¥ ¥3¥$F¥k¥'¥©¥Â¥G×¥¦9&¦'`¦ˆ¦Œ¦œ¦'¯¦צö¦ ý¦ §§E§d§ t§§§!¹§Û§ î§û§ ¨ ¨ ¨*)¨T¨ e¨s¨z¨¨ ¨³¨ ƨӨ権©©$©4©G© c©p©€w©9ø©2ª 9ª*Fª-qª*Ÿª ʪת çª ôª« « -«:«'J«r«!‚«¤«·«$Ê«ï«ÿ«¬+¬D¬9K¬…¬H›¬ ä¬ñ¬­­6­O­ b­l­­’­®® (® 5®?® U®b®u®0”®ZÅ®! ¯B¯$a¯*†¯"±¯Ô¯ô¯°.°J°g°›ƒ°±2±L±!S±u±‹±¤±½±Ö±!æ±6²?²U²k²~²—²°²0ɲú²³#³3³ C³ M³Z³0ܳ6 ´D´*]´ˆ´¤´0ô'ô´µŠ;µƵ*ßµ ¶¶?3¶0s¶*¤¶Q϶$!·F·9b·Tœ· ñ· þ·' ¸3¸R¸h¸¸N—¸æ¸K¹?Q¹?‘¹ѹð¹$º4ºSºQrº!ĺVæº0=»<n»«»*Ç»<ò»_/¼½¢½µ½ȽBÛ½ ¾ (¾2¾H¾^¾t¾о ¾¶¾B̾¿<-¿j¿-}¿«¿Y²¿® Áu»Á1Â!M o |‰Â— žÂ«Â¾Â3ÎÂÃÃ.Ã$GÃlÃsÃ*’Ã3½ÃñÃøÃgÄ*yÄ ¤Ä®Ä¾ÄA×Ä*ÅDÅÒÅQèÅQ:Æ$ŒÆ!±ÆÓÆÚÆóÆ!Ç 4Ç!?Ç aÇ!lÇ ŽÇ˜Ç®Ç ÁÇËÇÞÇ6ôÇ0+È0\È'ÈµÈ ¼ÈÉÈ'ßÈ*É2É KÉXÉ!qÉ“É*¬É*×É#Êj&Ê*‘Ê%¼ÊâÊ*òÊ*Ë HËRËeËluËâËõË*Ì ?ÌLÌ‚kÌîÌÍ#ÍBÍ0aÍ ’ÍÍ¡Í ±Í ¾Í ÉÍÓÍòÍ0Î'?ÎHgÎ,°Î$ÝÎÏ3!Ï!UÏwχϦÏ-ÂÏðÏÐ*ÐT=Ð*’Ð3½ÐñÐ!Ñ!#Ñ$EÑjÑ0†Ñ*·Ñ0âÑ3ÒGÒNÒjÒi‹5tÛu2v›z]^ÍP4]Ž®aøû¼Lº´[>®i\Òm>ŒÎ-nä–ÝW%RMîŒKŽrˆ¿ö2|IhSèĉ=Þšªf²á Ÿ!.ðQ£ ™Ù °dW¶‚}’dkáÏË‘îeôF$õHªa÷„ë5ò±†46üŠcUt‚€6yVe3;—q^8€»FV¼Lsÿ}Ê–RE1<b@È?Ó`‚Ý%³)ompÎà…D"—$:Y;ƒ©oGT¯/ìjËö•ú»LóÄ×+–xw"'êv€_¾ÔšDü  ÐiX«v¯~Mž^¬SШˆæ.u!f¨~¥Y¥£tkÇ›+“9ŸÅ¢¶E\_·”Ø…‹ó@Qâfké_ûBd7l0÷­º¸? *èplxë/gDÏ!-B‰0ý&6•êpÚr”Õx 'zrwÅ).£ýc}y ›7“Ȥh=…‡5çj:”©˜ÚMGh°s[ŠUeÂÆ@ <«—S8œäÑ‘ñŒ¡ÔÀ`Ø+ŽÜˆ„™(,†„9‘  ¸¹aE½]ú¿§(Ö"yg0G(Jæq˜¦Õµš Š78Á &,í4jÜ3ÒžQœV‹n;',ÉJ* 9P Í3åBNT&ßѽK´mAÉPu†’T ¢§w­H⇹/J|-ÛøÞ CÂù ðNK1ÇXZínO˜RYÙ2z{ç³gßUlÆô㙓$é¦ q#>NÃÿ #A×oñA\à=Iò·<Öµ#Á•bc’̾Ÿ¬1ÊžsZI²XZ¡å`¤þ‰ÃO±CƒC?{¡ ãWÓÀ*{ï[):ùF|~‡bOÌH%ìõþƒ1/2 normal speed1/3 normal speed2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 custom6x4 (inch)6x6 custom8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 customA4A5 landscapeA5 portraitADFADF BackADF DuplexADF FrontADF ModeADF cover openADF jamAccess to resource has been deniedAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAnalog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBayerBayer Dither 16Bayer Dither 64Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton 1Button 2Button stateButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration nowCancel buttonChange Document.Change documentChannelChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyColorColor (48 bits)Color MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor correctionColor patternColor36ConditionalContrastControls blue levelControls green levelControls red levelControls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDevice busyDevice-SettingsDiamondDisable auto document feeder and use flatbed onlyDisable backtrackingDisable gamma correctionDisable white shading correctionDisplay short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo auto focus only once between ejectsDo not force status codeDocument FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnd of file reachedEnhancementError DiffusionError during device I/OExecute calibration *now*ExperimentExposure timeExtend lamp timeoutExtra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf checked the backend automatically tries to determine an optimal value for the threshold.If enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.ImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInk-jet printersInvalid argumentInvert endiannessLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixNTSC GrayNTSC RGBNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of optionsNumber of the frame to scanOCR buttonOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOnOne pageOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryPDF buttonPage heightPage loadedPage widthPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositive FilmPositive SlidePositive or negative filmPower buttonPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed offsetRed offset value of the AFERequest a preview-quality scan.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner cover is openScanner mechanism locked for transportScanner modelScanner sensors and buttonsSecond entrySelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the test pictureSelects the ADF mode (simplex/duplex)Selects the brightness.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects which scan color is used gray mode (default: green).Self diagnosisSensorsSet default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets blue channel gainSets gray channel gainSets green channel gainSets red channel gainSets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Speedup sensorStandardStart calibration process.Start calibration using special sheetStatus Code SimulationSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.Thermal printersThis option reflects the status of a scanner button.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWarm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.White levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: sane-backends 1.0.20 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2009-10-31 10:30+0900 Last-Translator: Hiroshi Miura Language-Team: Japanese Language: ja MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Poedit-Language: Japanese X-Poedit-Country: JAPAN X-Poedit-SourceCharset: utf-8 åŠåˆ†ã®é€Ÿåº¦ï¼“分ã®ï¼‘ã®é€Ÿåº¦ï¼’ピクセル2x2 カスタム2x2 通常3x3 カスタム3x3 通常4ピクセル4x4 ç²—4x4 カスタム4x4 微細4x4 通常5x5 カスタム6x4(インãƒï¼‰6x6 カスタム8ビット出力8ピクセル8.5x11(インãƒï¼‰8x10(インãƒï¼‰8x8 ãƒã‚¤ã‚¨ãƒ«8x8 ç²—Fatting8x8 微細fatting8x8縦ã®ç·š8x8 カスタムA4A5横A5縦ADFADFè£é¢ADF両é¢ADF表é¢ADFモードADFã®ã‚«ãƒãƒ¼ãŒé–‹ã„ã¦ã„ã¾ã™ADFãŒè©°ã¾ã‚Šã¾ã—ãŸè³‡æºã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯æ‹’å¦ã•れã¾ã—ãŸã€‚緑レベルを基準ã«é’を増加赤レベルを基準ã«é’を増加é’レベルを基準ã¨ã—ã¦ç·‘を増加赤レベルを基準ã«ç·‘を増加é’レベルを基準ã¨ã—ã¦èµ¤ã‚’増加緑レベルを基準ã«èµ¤ã‚’増加上級上級オプションスキャンコマンドをé€ä¿¡å¾Œã€å®Ÿéš›ã«èµ°æŸ»å‡¦ç†ãŒå§‹ã¾ã‚‹ã€ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã®ãƒœã‚¿ãƒ³ãŒæŠ¼ã•れるã®ã‚’ã¾ã¤ã€‚全ページアナログ利得アナログフロントエンドアナログガンマé’アナログガンマ補正アナログガンマ緑アナログガンマ赤アナログガンマ補正é’ã®ã‚¢ãƒŠãƒ­ã‚°ã‚¬ãƒ³ãƒžè£œæ­£ç·‘ã®ã‚¢ãƒŠãƒ­ã‚°ã‚¬ãƒ³ãƒžè£œæ­£èµ¤ã®ã‚¢ãƒŠãƒ­ã‚°ã‚¬ãƒ³ãƒžè£œæ­£è‡ªå‹•自動閾値自動領域分割自動排出自動露出自動焦点自動焦点を一回ã ã‘行ã†è‡ªå‹•自動原稿é€ã‚Šè£…置閾値ã®è‡ªå‹•判定自動閾値自動暖機自動的ã«ã€å„走査ã®å¾Œã€ãƒ•ィルムを装置ã‹ã‚‰æŽ’出ã™ã‚‹ã€‚自動的ã«ã€ãƒ—ログラム終了å‰ã«è£…ç½®ã‹ã‚‰ãƒ•ィルムを排出ã™ã‚‹è‡ªå‹•çš„ã«è¼åº¦ã€ã‚³ãƒ³ãƒˆãƒ©ã‚¹ãƒˆã€ãƒ›ãƒ¯ã‚¤ãƒˆãƒ¬ãƒ™ãƒ«ã€ã‚¬ãƒ³ãƒžå€¤ã€ãƒŽã‚¤ã‚ºä½Žæ¸›ã¨ã‚¤ãƒ¡ãƒ¼ã‚¸å¼·èª¿ã‚’設定ã™ã‚‹ã€‚ãƒã‚¤ã‚¨ãƒ«ãƒã‚¤ã‚¨ãƒ«ãƒ‡ã‚£ã‚¶ 16ãƒã‚¤ã‚¨ãƒ«ãƒ‡ã‚£ã‚¶ 64RGB値を拘æŸXã¨Yè§£åƒåº¦ã‚’拘æŸã‚¢ãƒŠãƒ­ã‚°ã‚¬ãƒ³ãƒžå€¤ã‚’拘æŸã‚¬ãƒ³ãƒžå€¤ã®æ¯”を固定ビット深度黒レベルé’é’ãƒãƒ©ãƒ³ã‚¹é’ã®è¼åº¦é’利得AFEã®é’ã®åˆ©å¾—値明暗度é’é’ランプをオフå³ä¸‹ã®x走査エリアã®å³ä¸‹ã®xä½ç½®å³ä¸‹ã®y走査エリアã®å³ä¸‹ã®ä½ç½®ã‚’決ã‚る。è¼åº¦ãƒœã‚¿ãƒ³ï¼‘ボタン2ボタンã®çŠ¶æ…‹ãƒœã‚¿ãƒ³åˆ¶å¾¡èµ°æŸ»ãƒœã‚¿ãƒ³CDCPUãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼CRTCRTモニター露出時間を較正é’ã®éœ²å‡ºæ™‚間を較正緑ã®éœ²å‡ºæ™‚間を較正赤ã®éœ²å‡ºæ™‚é–“ã‚’è¼ƒæ­£ãƒ©ãƒ³ãƒ—å¯†åº¦ã®æ ¡æ­£è¼ƒæ­£ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã®æ ¡æ­£æ¬¡ã®èµ°æŸ»ã®ã¾ãˆã«æ ¡æ­£ã™ã‚‹ç™½é»’レベルを較正校正ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã«ã‚ˆã‚‹è¼ƒæ­£è¼ƒæ­£ãƒ‡ãƒ¼ã‚¿ã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥æ ¡æ­£ä¸­ã‚­ãƒ£ãƒ³ã‚»ãƒ«ãƒœã‚¿ãƒ³æ›¸é¡žã‚’å–りæ›ãˆã‚‹ã€‚書類をæ›ãˆã‚‹ã€‚ãƒãƒ£ãƒãƒ«ãƒãƒƒãƒ—セットIDãƒãƒƒãƒ—セットå較正ã®ã‚¯ãƒªã‚¢æ ¡æ­£ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’消去ã™ã‚‹ç²—粗校正粗調整を最åˆã®èµ°æŸ»ã ã‘行ã†ã‚«ãƒ©ãƒ¼ã‚«ãƒ©ãƒ¼ï¼ˆï¼”8ビット)カラーマトリックスカラー RAWカラーRGBカラーRGB TEXTカラーãƒãƒ©ãƒ³ã‚¹ã‚«ãƒ©ãƒ¼ãƒãƒ£ãƒãƒ«ã®åˆ©å¾—設定カラー補正カラーパターン色36æ¡ä»¶ä»˜ãコントラストé’レベルã®åˆ¶å¾¡ç·‘レベルã®åˆ¶å¾¡èµ¤ãƒ¬ãƒ™ãƒ«ã®åˆ¶å¾¡å–å¾—ã—ãŸç”»åƒã®è¼åº¦ã‚’制御ã™ã‚‹ã€‚å–å¾—ã•れãŸç”»åƒã®é’ãƒãƒ£ãƒãƒ«ã®è¼åº¦ã‚’制御ã—ã¾ã™ã€‚å–å¾—ã•れãŸç”»åƒã®ç·‘ãƒãƒ£ãƒãƒ«ã®è¼åº¦ã‚’制御ã—ã¾ã™ã€‚å–å¾—ã•れãŸç”»åƒã®èµ¤ãƒãƒ£ãƒãƒ«ã®è¼åº¦ã‚’制御ã—ã¾ã™ã€‚å–å¾—ã—ãŸç”»åƒã®ã‚³ãƒ³ãƒˆãƒ©ã‚¹ãƒˆã‚’制御ã™ã‚‹ã€‚コピーボタンフィルムã®ç¨®é¡žã«å¾“ã£ãŸè£œæ­£é€éŽçއã«å¾“ã£ã¦ã€è£œæ­£ã•れã¾ã™ã€‚ã‚«ãƒãƒ¼ãŒé–‹ã„ã¦ã„るカスタムグレースケール走査ã®ã‚«ã‚¹ã‚¿ãƒ ãƒ»ã‚«ãƒ©ãƒ¼ãƒžãƒˆãƒªãƒƒã‚¯ã‚¹ã‚«ã‚¹ã‚¿ãƒ ã‚«ãƒ©ãƒ¼ãƒžãƒˆãƒªãƒƒã‚¯ã‚¹ãƒ‡ãƒãƒƒã‚°ã‚ªãƒ—ション既定既定é’較正ã®ãŸã‚ã®éœ²å‡ºæ™‚é–“ã®å®šç¾©é’スキャンã®éœ²å‡ºæ™‚間を設定緑較正ã®ãŸã‚ã®éœ²å‡ºæ™‚é–“ã®å®šç¾©ç·‘スキャンã®éœ²å‡ºæ™‚間を設定赤較正ã®ãŸã‚ã®éœ²å‡ºæ™‚é–“ã®å®šç¾©èµ¤èµ°æŸ»ã®éœ²å‡ºæ™‚間を設定走査ã®éœ²å‡ºæ™‚間を設定較正ã®ãƒ©ãƒ³ãƒ—密度を定義走査ã®ãƒ©ãƒ³ãƒ—密度を定義é’ランプオフパラメータを定義緑ランプオフパラメータを定義スキャナーãŒä½¿ã†ã¹ãズーム値を定義パイプã«ãƒ‡ãƒ¼ã‚¿ã‚’転é€ã™ã‚‹é…延濃度制御デãƒã‚¤ã‚¹ãƒ“ジー装置設定ダイアモンド自動書類é€ã‚Šã‚’無効ã«ã—ã€å¹³å°ã ã‘を使ã„ã¾ã™ãƒãƒƒã‚¯ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã‚’無効ガンマ補正を無効ホワイト・シェーディング較正を無効解åƒåº¦ã®ãƒªã‚¹ãƒˆã‚’短ã表示ディザーディザーA(4x4ãƒã‚¤ã‚¨ãƒ«ï¼‰ãƒ‡ã‚£ã‚¶ãƒ¼B(4x4スパイラル)ディザーC(4x4網スクリーン)ディザーD(8x4ã®ç¶²ã‚¹ã‚¯ãƒªãƒ¼ãƒ³)ディザ マップ1ディザ マップ2カラーã®ä»£ã‚りã«ã€ã‚°ãƒ¬ãƒ¼ã‚¹ã‚±ãƒ¼ãƒ«ã§èµ°æŸ»ã—ã¾ã™ã€‚排出ã—ã¦ã„ã‚‹é–“ã«ã€ä¸€åº¦ã ã‘自動焦点補正を行ã„ã¾ã™ã€‚ステータスコードを強制ã—ãªã„書類é€ã‚Šè£…置文書供給装置拡張書類é€ã‚ŠãŒè©°ã¾ã‚Šã¾ã—ãŸæ›¸é¡žé€ã‚ŠãŒç©ºã«ãªã‚Šã¾ã—ãŸï¼’å€å…‰å­¦è§£åƒåº¦ãƒ‘ターンAã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ãƒ‘ターンBã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰å–り出ã—å£ä¸¡é¢ä¸¡é¢ã‚¹ã‚­ãƒ£ãƒ³ä¸¡é¢ã‚¹ã‚­ãƒ£ãƒ³ã§ã¯ã€æ–‡æ›¸ã®è¡¨é¢ã¨è£é¢ã®èµ°æŸ»ãŒè¡Œã‚れã¾ã™ã€‚読ã¿å–りé…å»¶ã®å¤§ãã•æŽ’å‡ºèµ°æŸ»å¾Œã€æ›¸é¡žã‚’排出å„走査ã®å¾Œãƒ•ィルムを排出ã™ã‚‹çµ‚了å‰ã«ãƒ•ィルムを排出ã™ã‚‹ãƒ•ィルムを今排出フィルムを今ã™ãã€æŽ’å‡ºã™ã‚‹ã€‚ADFã®æ›¸é¡žã‚’排出ã™ã‚‹é›»å­ãƒ¡ãƒ¼ãƒ«ãƒœã‚¿ãƒ³ã‚°ãƒ¬ãƒ¼ã‚¹ã‚±ãƒ¼ãƒ«ã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆä¸¡é¢èµ°æŸ»ã‚’有効ã«ã™ã‚‹ã€‚ç·šç”»ã®èµ°æŸ»ã§é–¾å€¤ã®è‡ªå‹•判定を有効ã«ã™ã‚‹éœ²å‡ºæ™‚é–“ã®é¸æŠžã‚’有効ã«ã™ã‚‹ã€‚テストオプション有効様々ãªãƒ†ã‚¹ãƒˆã‚ªãƒ—ションを有効ã«ã—ã¾ã™ã€‚ã“れã¯ã€ãƒ•ロントエンドãŒã€ã™ã¹ã¦ã®ç•°ãªã‚‹SANEオプションタイプã®è¡¨ç¤ºã‚„変更ãŒã§ãã‚‹ã‹ãƒ†ã‚¹ãƒˆã™ã‚‹ç”¨é€”ã§ä½¿ã‚れã¾ã™ã€‚自動焦点を有効ï¼ç„¡åŠ¹è‡ªå‹•éœ²å…‰æ©Ÿèƒ½ã‚’æœ‰åŠ¹ï¼ç„¡åйã«ã™ã‚‹ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ€å¾Œã«åˆ°é”増強エラー拡散デãƒã‚¤ã‚¹å…¥å‡ºåЛ䏭ã«ã‚¨ãƒ©ãƒ¼è¼ƒæ­£ã‚’「ã™ãã«ã€å®Ÿè¡Œã—ã¾ã™å®Ÿé¨“çš„éœ²å‡ºæ™‚é–“ãƒ©ãƒ³ãƒ—ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã®æ‹¡å¤§è¶…高速追加色調整追加速ã„é«˜é€Ÿã‚°ãƒ¬ãƒ¼ãƒ¢ãƒ¼ãƒ‰é«˜é€Ÿãƒ—ãƒ¬ãƒ“ãƒ¥ãƒ¼é«˜é€Ÿèµ°æŸ»é€Ÿãæœ€é€Ÿãƒ•ァックスボタンフィーダーモードファイルボタンファイルåフィルムã®ç¨®é¡žãƒ•ィルムã®ä¸€ç‰‡å¯†é«˜ç²¾å½©ãƒ•ァームウエアãƒãƒ©ãƒ³ã‚¹æœ€åˆã®ã‚¨ãƒ³ãƒˆãƒªãƒ¼ãƒ•ラットベッドフラットベッドã®ã¿ç„¦ç‚¹ã‚¬ãƒ©ã‚¹ã‹ã‚‰2.5mmã®å ´æ‰€ã«ç„¦ç‚¹ã‚’åˆã‚ã›ã‚‹ç„¦ç‚¹ä½ç½®ã‚¬ãƒ©ã‚¹è¡¨é¢ã«ç„¦ç‚¹ã‚’åˆã‚ã›ã‚‹ãƒ¢ãƒŽã‚¯ãƒ­ãƒ¼ãƒ ãƒ—レビューを強制ã™ã‚‹çœŸã®æ·±åº¦ã‚’強制ã—ã¾ã™ã€‚走査å‰ã«ã‚¹ã‚­ãƒ£ãƒŠã®æ ¡æ­£ã‚’強制ã™ã‚‹ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã«å¯¾ã—ã€sane_read()ãŒå‘¼ã°ã‚ŒãŸå¾Œã«ã€ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚³ãƒ¼ãƒ‰ã¨ã—ã¦ã€SANE_STATUS_EOFã‚’è¿”ã™ã‚ˆã†å¼·åˆ¶ã™ã‚‹ã€‚ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã«å¯¾ã—ã¦ã€ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚³ãƒ¼ãƒ‰ã¨ã—ã¦SANE_STATUS_JAMMEDã‚’è¿”ã™ã‚ˆã†ã«å¼·åˆ¶ã™ã‚‹ã€‚sane_read()ãŒå‘¼ã°ã‚ŒãŸå¾Œã€SANE_STATUS_NO_DOCS状態コードを返ã™ã‚ˆã†ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã‚’強制ã—ã¾ã™ã€‚ç´™ã‹ã‚‰ç™½ã‚µãƒ³ãƒ—ルã‹ã‚‰å‰é¢ãƒœã‚¿ãƒ³ã‚’å¾…ã¤å…¨èµ°æŸ»æ›–昧ãªãƒ‘ラメータ利得ガンマガンマ校正ガンマテーブルガンマ補正ガンマ補正ã¯ç„¡åйã«ã•れã¾ã™ã‚¬ãƒ³ãƒžå€¤é’ãƒãƒ³ãƒ‰ã®ã‚¬ãƒ³ãƒžè£œæ­£ãƒ†ãƒ¼ãƒ–ル。緑ãƒãƒ³ãƒ‰ã®ã‚¬ãƒ³ãƒžè£œæ­£ãƒ†ãƒ¼ãƒ–ル。赤ãƒãƒ³ãƒ‰ã®ã‚¬ãƒ³ãƒžè£œæ­£ãƒ†ãƒ¼ãƒ–ル。é…ç½®é…置グループ粒径グレーグレー利得グレーモード色グレー化グレースケール4ビットグレースケール8ビットグレースケール走査緑緑ãƒãƒ©ãƒ³ã‚¹ç·‘ã®è¼åº¦ç·‘利得AFEã®ç·‘ã®åˆ©å¾—値明暗度緑緑ランプをオフ緑オフセットAFEã®ç·‘ã®ã‚ªãƒ•セット値グリッド網版ãƒãƒ¼ãƒ•トーン A(ãƒãƒ¼ãƒ‰ãƒˆãƒ¼ãƒ³ï¼‰ãƒãƒ¼ãƒ•トーンB(ソフトトーン)ãƒãƒ¼ãƒ•トーンC(ãƒãƒƒãƒˆãƒˆãƒ¼ãƒ³ï¼‰ãƒãƒ¼ãƒ•トーンドット32ãƒãƒ¼ãƒ•トーンドット64ãƒãƒ¼ãƒ•トーンã®ãƒ‘ターンãƒãƒ¼ãƒ•トーンパターンã®å¤§ãã•ãƒãƒ¼ãƒ•トーン処ç†ãƒãƒ¼ãƒ•トーンã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã€€ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã‚’シミュレート走査領域ã®ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢ã®å†…部Xä½ç½®èµ°æŸ»é ˜åŸŸã®ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢å†…部Yä½ç½®ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢è§£åƒåº¦ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢ç‹¬è‡ªã®ã‚ªãƒ—ション高高コントラストå°åˆ·é«˜å¯†åº¦å°åˆ·æœ€é«˜å“質ã ãŒã€ã‚¹ãƒ”ードã¯é…ã„æœ€é«˜é€Ÿåº¦ã ãŒã€å“質ã¯ä½Žã„ãƒã‚¤ãƒ©ã‚¤ãƒˆé’ã®ãƒã‚¤ãƒ©ã‚¤ãƒˆç·‘ã®ãƒã‚¤ãƒ©ã‚¤ãƒˆèµ¤ã®ãƒã‚¤ãƒ©ã‚¤ãƒˆæ°´å¹³ã®ãƒ‘イプを通ã—ã¦å„データã®ãƒãƒƒãƒ•ã‚¡ãŒè»¢é€ã•れãŸå¾Œã€ã©ã‚Œãらã„å¾…ã¤ã‹ã€‚色相もã—ãƒã‚§ãƒƒã‚¯ã•れるã¨ã€ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ã¯è‡ªå‹•çš„ã«æœ€é©ãªé–¾å€¤ã‚’探ãã†ã¨ã—ã¾ã™ã€‚有効ã«ãªã‚‹ã¨ã€ç”»åƒã¯ã‚«ãƒ©ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã§èµ°æŸ»ã•れã€ã‚°ãƒ¬ãƒ¼ã‚¹ã‚±ãƒ¼ãƒ«ã«ã‚½ãƒ•トウエアã«ã‚ˆã£ã¦å¤‰æ›ã•れã¾ã™ã€‚ã“れã¯ã€ä¸€éƒ¨ã®ç’°å¢ƒã§ã¯ã€ç”»åƒå“質を高ã‚ã‚‹ã“ã¨ãŒã‚りã¾ã™ã€‚有効ã®å ´åˆã€è¼ƒæ­£ã«ãŠã„ã¦ã¯ã‚·ã‚§ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°è£œæ­£ã ã‘ãŒå®Ÿè¡Œã•れã¾ã™ã€‚利得ã€ã‚ªãƒ•セットã¨éœ²å…‰æ™‚é–“ã®æ—¢å®šå€¤ã¯ã€çµ„ã¿è¾¼ã¾ã‚Œã¦ã„る値ã‹ã€è¨­å®šãƒ•ァイルã‹ã‚‰èª­ã¿è¾¼ã¾ã‚ŒãŸå€¤ãŒä½¿ã‚れã¾ã™ã€‚有効ã«ãªã‚‹ã¨ã€ã‚¹ã‚­ãƒ£ãƒŠãŒå‡¦ç†ã™ã‚‹ç”»åƒã®ä¸€éƒ¨ãŒã€åˆ†æžã®ãŸã‚ã«ä¿å­˜ã•れã¾ã™ã€‚有効ã«ã•れるã¨ã€ãƒ‡ãƒã‚¤ã‚¹ã¯æ¬¡ã®èµ°æŸ»ã®å‰ã«ã‹ãªã‚‰ãšæ ¡æ­£ã‚’è¡Œã„ã¾ã™ã€‚ãã†ã§ãªã‘れã°ã€æ ¡æ­£ã¯æœ€åˆã®é–‹å§‹å‰ã®ä¸€åº¦ã ã‘行ã‚れã¾ã™ã€‚ã‚¬ãƒ³ãƒžãŒæœ‰åйã§ã‚れã°ã€ç”»åƒå“質を高ã‚ã‚‹ãŸã‚ã€èµ°æŸ»ã¯ã¤ã­ã«ï¼‘6ビット深度ã§è¡Œã‚れã¾ã™ã€‚ãれã‹ã‚‰ã€é¸æŠžã•れãŸè‰²æ·±åº¦ã«å¤‰æ›ã•れã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションã¯ã€æ·±åº¦ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’回é¿ã—ã¾ã™ã€‚ç”»åƒã‚¤ãƒ¡ãƒ¼ã‚¸å¼·èª¿ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚«ãƒ©ãƒ¼ãŒå転ã•れã¾ã™ç”»åƒå¼·èª¿ç”»åƒã®æ˜Žæš—度イメージ修正オプションドットインパクトプリンタRGBモードã«ãŠã„ã¦å„色ã«å¯¾ã—ã¦åŒã˜å€¤ã‚’使ã†CCDé…列ã®ã‚¢ãƒŠãƒ­ã‚°åˆ©å¾—を増加ã¾ãŸã¯æ¸›å°‘æƒ…å ±ã‚¤ãƒ³ã‚¯ã‚¸ã‚§ãƒƒãƒˆãƒ—ãƒªãƒ³ã‚¿ä¸æ­£ãªå¼•数エンディアンをåè»¢ãƒ©ãƒ³ãƒ—ã®æº–å‚™ãŒæ•´ã„ã¾ã›ã‚“。å†åº¦è©¦ã—ã¦ã¿ã¦ãã ã•ã„。ランプオフ終了時ã«ãƒ©ãƒ³ãƒ—ã‚’åœæ­¢ã™ã‚‹ãƒ€ãƒ¼ã‚¯è£œæ­£æ™‚ã«ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹æ™‚間ランプオフ時間(分)ランプをオンランプã®çŠ¶æ…‹ãƒ©ãƒ³ãƒ—ãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ãŸãƒ©ãƒ³ãƒ—オフ時間ランプオフ時間を秒ã§è¨­å®šã€‚ランプã®ã‚¹ã‚¤ãƒƒãƒUSレターサイズsane_read()ã®å‘¼ã³å‡ºã—ã”ã¨ã«è»¢é€ã§ãるデータé‡ã®åˆ¶é™ç·šç”»ã‚¤ãƒ¡ãƒ¼ã‚¸ã‚’グレースケールã¨ã—ã¦èª­ã¿è¾¼ã‚€ãƒ©ã‚¤ãƒ³ã”ã¨ã®ãƒ”ã‚¯ã‚»ãƒ«ã®æå¤±ä½Žä½Žå¯†åº¦å°åˆ·æ‰‹å‹•焦点ä½ç½®ãƒ©ãƒ³ãƒ—を手動ã§ã‚ªãƒ•オンã™ã‚‹RGBã®å€çŽ‡ãƒžãƒˆãƒªãƒƒã‚¯ã‚¹æœ€å¤§ãƒ¡ãƒ‡ã‚£ã‚¢ä¸­åª’ä½“ã®æ‰±ã„走査ã—ãŸå¾Œã€ãƒ©ãƒ³ãƒ—ãŒã‚ªãƒ•ã«ãªã‚‹ã¾ã§ã®æ™‚間(分)水平ã®é¡åƒé¡åƒç”»åƒæ°´å¹³ã«é¡åƒã‚’ã¨ã‚‹ã€‚垂直ã«é¡åƒã‚’ã¨ã‚‹ã€‚æ°´å¹³ã«ç”»åƒã®é¡åƒã«ã™ã‚‹é¡åƒã‚’ã¨ã‚‹ã€‚垂直é¡åƒå„種モード1モード2モード3モノクロ・カラーマトリックスNTSCã®ã‚°ãƒ¬ãƒ¼NTSCæ–¹å¼RGBãƒã‚¬ãƒã‚¬ãƒ•ィルムãƒã‚¬ã‚¹ãƒ©ã‚¤ãƒ‰ãƒã‚¬ãƒ•ィルムãƒã‚¬ãƒ•ィルムãƒã‚¬ç”»åƒè£œæ­£ã‚’ã—ãªã„逿˜Žåº¦è£œæ­£ã¯è¡Œã‚ãªã„ノイズ除去 ãªã—普通普通ã®é€Ÿåº¦ã‚ªãƒ—ション数走査ã™ã‚‹ãƒ•レーム数OCRボタンオフsane_read()ãŒãƒ‡ãƒ¼ã‚¿ã‚’è¿”ã™ã‹ã©ã†ã‹æ¤œå‡ºã™ã‚‹ãŸã‚ã®ã€ãƒ•ァイルディスクリプタã®é¸æŠžã‚’æä¾›ã™ã‚‹ã€‚ファイルディスクリプタã®é¸æŠžã‚’æä¾›ã™ã‚‹ã‚ªãƒ³ï¼‘ページシェーディング補正ã ã‘ã‚’è¡Œã†æ“作ã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“。æ“作ã¯ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•れã¾ã—ãŸã€‚光学装置メモリä¸è¶³PDFボタンページ高ページãŒãƒ­ãƒ¼ãƒ‰ã•れãŸãƒšãƒ¼ã‚¸å¹…紙サイズパススルースキャナーã®è‡ªå·±è¨ºæ–­ã‚’実行較正ã®å®Ÿè¡ŒADFã«ã‚ã‚‹ç´™ã®ç‰©ç†ã‚µã‚¤ã‚ºãƒã‚¸ãƒ•ィルムãƒã‚¸ã‚¹ãƒ©ã‚¤ãƒ‰ãƒã‚¸ã‚ã‚‹ã„ã¯ãƒã‚¬ãƒ•ィルム電æºãƒœã‚¿ãƒ³äº‹å‰å®šç¾©ã•れãŸè¨­å®šãƒ—レビュープレビューモードå°åˆ·ã™ã¹ã¦ã®ã‚ªãƒ—ションã®ãƒªã‚¹ãƒˆã‚’表示ã™ã‚‹ã€‚オプション表示写真やå°åˆ·ç‰©ãªã©ã®æ¨™æº–çš„ãªèµ°æŸ»é ˜åŸŸã‚’æä¾›ã—ã¾ã™ã€‚å“質較正å“質優先走査簡易フォーマットRAMãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼ROMãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼ãƒ©ãƒ³ãƒ€ãƒžã‚¤ã‚ºç„¡åŠ å·¥èª­ã¿å–りé…延読ã¿å–り制é™ç‰¹å®šã®ãƒ‡ãƒã‚¤ã‚¹ãŒã‚µãƒãƒ¼ãƒˆã™ã‚‹ã‚ªãƒ—ションãŒã©ã‚Œã ã‘ã‚ã‚‹ã‹ã‚’指定ã™ã‚‹èª­ã¿å–りã®ã¿ã‚ªãƒ—ション赤赤ãƒãƒ©ãƒ³ã‚¹èµ¤ã®è¼åº¦èµ¤åˆ©å¾—AFEã®èµ¤ã®åˆ©å¾—値明暗度赤赤オフセットAFEã®èµ¤ã®ã‚ªãƒ•セット値プレビューå“質ã®èµ°æŸ»ã‚’è¦æ±‚ã™ã‚‹ã€‚ã™ã¹ã¦ã®ãƒ—レビューを最高速モード(低å“質)ã§è¡Œã†ã‚ˆã†ã«ã™ã‚‹ã€‚ãƒãƒƒãƒ—セットã®ãƒªã‚»ãƒƒãƒˆã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã®ãƒªã‚»ãƒƒãƒˆã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã‚’リセットã™ã‚‹ãƒãƒƒãƒ—セットデータをリセットSANE_STATUS_ACCESS_DENIEDã‚’è¿”ã™SANE_STATUS_COVER_OPENã‚’è¿”ã™SANE_STATUS_EOFã‚’è¿”ã™ã€‚SANE_STATUS_IO_ERRORã‚’è¿”ã™SANE_STATUS_JAMMEDã‚’è¿”ã™SANE_STATUS_NO_DOCSã‚’è¿”ã™SANE_STATUS_NO_MEMã‚’è¿”ã™sane_start()を呼ã³å‡ºã™å‰ã«ã€sane_parameters()を呼んã ã¨ãã«ã€æ›–昧ãªãƒ©ã‚¤ãƒ³ã‚„ãã®ãƒ©ã‚¤ãƒ³ã«å¯¾ã—ã¦æ›–昧ãªãƒã‚¤ãƒˆã‚’è¿”ã™ã€‚sane_readã®è¿”値SCSIパリティエラー彩度デãƒãƒƒã‚°ã‚¤ãƒ¡ãƒ¼ã‚¸ã®ä¿å­˜ã‚¹ã‚«ãƒ©ãƒ¼ã‚¬ãƒ³ãƒžã‚¬ãƒ³ãƒžé’スカラーガンマ緑スカラーガンマ赤スカラー走査モードスキャンモードグループ走査領域ã¨ãƒ¡ãƒ‡ã‚£ã‚¢ã‚µã‚¤ã‚ºã®ã‚ªãƒ—ションスキャンボタン走査カウンター走査露出時間é’ã®èµ°æŸ»éœ²å‡ºæ™‚é–“ç·‘ã®èµ°æŸ»éœ²å‡ºæ™‚間赤ã®èµ°æŸ»éœ²å‡ºæ™‚間高速グレーモードã§èµ°æŸ»ï¼ˆä½Žå“質)ランプ密度ã®èµ°æŸ»èµ°æŸ»ã®ä½™ç™½èµ°æŸ»ãƒ¢ãƒ¼ãƒ‰èµ°æŸ»è§£åƒåº¦èµ°æŸ»æºèµ°æŸ»é€Ÿåº¦è£œæ­£é ˜åŸŸã‚’å«ã‚ã¦ã€å…¨é ˜åŸŸã‚’走査ã—ã¾ã™ã€‚注æ„ï¼šå…¨é«˜ã‚’é¸æŠžã—ãªã„ã“ã¨ã€‚ã“れã¯ãƒ†ã‚¹ãƒˆç”¨ã§ã™ã€‚スキャナーã®ã‚«ãƒãƒ¼ãŒé–‹ã„ã¦ã„ã¾ã™ç§»å‹•ã®ãŸã‚ã«ã€èµ°æŸ»æ©Ÿæ§‹ã‚’ロックã™ã‚‹ã€‚スキャナーモデルスキャナーã®ã‚»ãƒ³ã‚µãƒ¼ã‚„ボタン2ã¤ã‚ã®ã‚¨ãƒ³ãƒˆãƒªãƒ¼ãƒ•ィルムã®ç¨®é¡žã‚’é¸æŠžç™½ã®ç‚¹ã‚’å¾—ã‚‹ãŸã‚ã€æœ€å°è¼åº¦ã‚’é¸æŠžã‚¹ãƒ ãƒ¼ã‚¸ãƒ³ã‚°ãƒ•ã‚£ãƒ«ã‚¿ã‚’é¸æŠžãƒ•ã‚£ãƒ«ãƒ ã®ç¨®é¡žã‚’é¸ã¶ãƒ—ãƒ¬ãƒ“ãƒ¥ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã‚’é¸æŠžã€‚ã‚°ãƒ¬ãƒ¼ã‚¹ã‚±ãƒ¼ãƒ«ãƒ—ãƒ¬ãƒ“ãƒ¥ãƒ¼ãŒé€šå¸¸ã‚‚ã£ã¨ã‚‚よã„速度ã¨è©³ç´°ã•ã‚’æä¾›ã—ã¾ã™ã€‚テスト画åƒã‚’é¸æŠžADFモードã®é¸æŠžï¼ˆç‰‡é¢ã€ä¸¡é¢ï¼‰è¼åº¦ã®é¸æŠžå–り出ã—å£ã®é¸æŠžãƒ•ィルムã®ç¨®é¡žã‚’é¸æŠžï¼ˆä¾‹ã€ãƒã‚¬ã€ã‚¹ãƒ©ã‚¤ãƒ‰ï¼‰ã‚¬ãƒ³ãƒžè£œæ­£ã•れãŸå¤‰æ›ã‚«ãƒ¼ãƒ–ã‚’é¸æŠžã‚¬ãƒ³ãƒžè£œæ­£ãƒ¢ãƒ¼ãƒ‰ã‚’é¸æŠžã™ã‚‹ã€‚ガンマ補正値を事å‰å®šç¾©ã®ãƒ‡ãƒã‚¤ã‚¹ã®ãƒªã‚¹ãƒˆã‹ã‚‰é¸æŠžã™ã‚‹ã€‚ãƒãƒ¼ãƒ•ãƒˆãƒ¼ãƒ³ã‚’é¸æŠžã™ã‚‹ã€‚ãƒã‚¬ãƒ•ã‚£ãƒ«ãƒ ã‚’é¸æŠžèµ°æŸ»ã™ã‚‹ãƒ•ãƒ¬ãƒ¼ãƒ ã®æ•°ã‚’é¸ã‚“ã§ãã ã•ã„。ã©ã®è‰²ã‚’用ã„ã¦ã‚°ãƒ¬ãƒ¼ãƒ¢ãƒ¼ãƒ‰ã‚’実ç¾ã™ã‚‹ã‹ã‚’é¸æŠžï¼ˆæ—¢å®šï¼šç·‘ï¼‰è‡ªå·±è¨ºæ–­ã‚»ãƒ³ã‚µãƒ¼å¢—å¼·åˆ¶å¾¡ã®æ—¢å®šå€¤ã‚’設定ã™ã‚‹æ¿ƒåº¦åˆ¶å¾¡ãƒ¢ãƒ¼ãƒ‰ã‚’設定露出時間を設定ランプ密度ã®è¨­å®šé®®é‹­åŒ–値を設定光学系ã®ç„¦ç‚¹ä½ç½®ã‚’手動ã§è¨­å®šã—ã¾ã™ï¼ˆæ—¢å®šå€¤ï¼šï¼‘28)フレームã®é †åºã‚’設定3パスカラーモードã«ãŠã„ã¦ã€ãƒ•レームã®é †åºã‚’設定。スキャナーã®ã‚«ãƒ©ãƒ¼ãƒžãƒˆãƒªãƒƒã‚¯ã‚¹ã‚’設定ã™ã‚‹ã€‚ランプãŒåœæ­¢ã™ã‚‹ã¾ã§ã®æ™‚間(分)を設定ã™ã‚‹ãƒ¡ãƒ‡ã‚£ã‚¢ã®ç¨®é¡žã‚’設定é’ãƒãƒ£ãƒãƒ«åˆ©å¾—を設定グレーãƒãƒ£ãƒãƒ«åˆ©å¾—を設定緑ãƒãƒ£ãƒãƒ«åˆ©å¾—を設定赤ãƒãƒ£ãƒãƒ«åˆ©å¾—ã‚’è¨­å®šé¸æŠžã—ãŸå‡ºåŠ›ãƒ‡ãƒã‚¤ã‚¹ã®ãŸã‚ã®è‰²è£œæ­£ãƒ†ãƒ¼ãƒ–ルを設定ã™ã‚‹ã€‚シートé€ã‚Šãƒ¢ãƒ¼ãƒ‰ã®è¨­å®šç„¦ç‚¹ä½ç½®ã‚’ã€ã‚¬ãƒ©ã‚¹é¢ãªã„ã—ã¯ã€ã‚¬ãƒ©ã‚¹é¢ã‹ã‚‰2.5mmã®ä½ç½®ã«è¨­å®šã™ã¹ã¦ã®ãƒãƒ£ãƒãƒ«ã®ã‚¬ãƒ³ãƒžå€¤ã‚’設定走査ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã®æ°´å¹³è§£åƒåº¦ã‚’設定ã™ã‚‹ã€‚イメージ強調を設定走査イメージã®è§£åƒåº¦ã‚’設定。走査ã—ãŸã‚¤ãƒ¡ãƒ¼ã‚¸ã®åž‚直改造度を設定ã™ã‚‹ã€‚自動走査ã®åˆ©å¾—ã¨ã‚ªãƒ•セットを設定ã™ã‚‹ã€‚ã‚‚ã—ã€ã“ã®ã‚ªãƒ—ションãŒä¸å¯ã«ã•れã¦ã„ã‚‹ã¨ãã¯ã€ã‚¢ãƒŠãƒ­ã‚°ãƒ•ロントエンドパラメータã®è¨­å®šã®é¸æŠžè‚¢ã¯ã€æ‰‹å‹•ã§è¨­å®šãŒå¿…è¦ã§ã™ã€‚ã“ã®ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã¯æ—¢å®šã§æœ‰åйã«ã•れã¦ã„ã¾ã™ã€‚テスト用途ã§å­˜åœ¨ã™ã‚‹ã‚ªãƒ—ションã§ã™ã€‚最å°è¼åº¦ã€å½±é’ã®æœ€å°è¼åº¦ç·‘ã®æœ€å°è¼åº¦èµ¤ã®æœ€å°è¼åº¦ã‚·ãƒ£ãƒ‰ãƒ¼ã€ãƒŸãƒƒãƒ‰ãƒˆãƒ¼ãƒ³ã€ãƒã‚¤ãƒ©ã‚¤ãƒˆã€éœ²å…‰æ™‚間鮮鋭化鮮鋭度é’ã‚’ç·‘ã«ã‚·ãƒ•トé’を赤ã«ã‚·ãƒ•ト緑をé’ã«ã‚·ãƒ•ト緑を赤ã«ã‚·ãƒ•ト赤をé’ã«ã‚·ãƒ•ト赤を緑ã«ã‚·ãƒ•ト短ã„è§£åƒåº¦ä¸€è¦§è£…ç½®ã«ä½¿ã‚れã¦ã„ã‚‹ãƒãƒƒãƒ—セットåを表示ã™ã‚‹ã€‚ãƒãƒƒãƒ—セットIDを表示スキャナーãŒè¡Œã£ãŸèµ°æŸ»å›žæ•°ã‚’表示ã—ã¾ã™ã€‚ランプã®åœæ­¢ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã®ãƒ©ãƒ³ãƒ—ã‚’åœæ­¢ã™ã‚‹ã€‚片é¢ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã‚’シミュレートã—ã¾ã™ã€‚ãƒãƒ³ãƒ‰ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã¯ã€ãŸã„ã¦ã„ã®å ´åˆã€ã‚¤ãƒ¡ãƒ¼ã‚¸ã®é«˜ã•ãŒäº‹å‰ã«ã¯ã‚ã‹ã‚Šã¾ã›ã‚“。ãã®ä»£ã‚りã€é«˜ã•ã¨ã—ã¦ãƒ¼ï¼‘ã‚’è¿”ã—ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションを設定ã™ã‚‹ã¨ã€ãƒ•ãƒ­ãƒ³ãƒˆã‚¨ãƒ³ãƒ‰ãŒæ­£ã—ããれを扱ãˆã‚‹ã‹ã€ãƒ†ã‚¹ãƒˆã—ã¾ã™ã€‚3ã¤ã«åˆ†å‰²ã•れãŸãƒ•レームを返ã™ï¼“パススキャナーをシミュレートã—ã¾ã™ã€‚ãŠã‚‚ã—ã‚åŠåˆ†ã«ã€ç·‘ã€é’ãã—ã¦èµ¤ã®é †åºã§è¿”ã—ã¾ã™ã€‚3パススキャナーをシミュレート。カラーモードã«ãŠã„ã¦ã€ï¼“フレームãŒè»¢é€ã•れる。読ã¿è¾¼ã¿åˆ¶é™ã‚µã‚¤ã‚ºæš–機プロセスをスキップスライドスライドé…ã„é…ãæœ€é…スムーススムージング情報æºé¸æŠžå…¥åŠ›å…ƒã€ãƒ¢ãƒ¼ãƒ‰ã¨è§£åƒåº¦ã®ã‚ªãƒ—ション特殊オプション特殊オプション媒体ã®é«˜ã•を指定センサーをスピードアップ標準校正プロセスを開始。特殊シートを用ã„ãŸè£œæ­£ã‚’開始ステータスコード シミュレーションæˆåŠŸé»’ã¨ç™½ã‚’å転ã™ã‚‹é€éŽãƒ¦ãƒ‹ãƒƒãƒˆã®ã‚ªãƒ•・オンを切り替ãˆã¾ã™ã€‚(FAU,フィルムアダプター装置)ランプã®ã‚ªãƒ•ï¼ã‚ªãƒ³ã‚’切り替ãˆTMAãƒã‚¬TMAスライドテキスト強調技術å„sane_read()ã«ãŠã‘る転é€ã§ãる(最大)データé‡ãƒ­ãƒ¼ãƒ‰ã•れる画åƒã®ãƒ•ァイルåãƒ©ãƒ³ãƒ—ã¯æŒ‡å®šã•ã‚ŒãŸæ™‚間(分)ãŒçµŒéŽã—ãŸã‚‰ã‚ªãƒ•ã«ã•れã¾ã™ã€‚値ãŒï¼ã®ã¨ãã¯ã€ã“ã®æ©Ÿèƒ½ã¯åƒãã¾ã›ã‚“。熱転写プリンタã“ã®ã‚ªãƒ—ションã¯ã€ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ãƒœã‚¿ãƒ³ã®çŠ¶æ…‹ã‚’åæ˜ ã—ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションã¯ã€èµ°æŸ»ä¸­ã«å¹³å°ã®ãƒ©ãƒ³ãƒ—をオフã«ã—ã¾ã™ã€‚3パス シミュレーション3パスシミュレーション閾値線画モードã®é–¾å€¤å¹³å°ã®ãƒ©ãƒ³ãƒ—切り替ãˆå¹³å°ã®ãƒ©ãƒ³ãƒ—を切り替ãˆå·¦ä¸Šã®x走査エリアã®å·¦ä¸Šã®ä½ç½®å·¦ä¸Šã®y走査エリアã®å³ä¸Šã®ä½ç½®é€éŽæ€§é€éŽã‚¢ãƒ€ãƒ—ターé€éŽãƒ¦ãƒ‹ãƒƒãƒˆé€éŽçއé€éŽãƒ¦ãƒ‹ãƒƒãƒˆãƒ©ãƒ³ãƒ—をオフã«ãƒ—ログラム終了時ã«ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹ã‚¹ã‚­ãƒ£ãƒŠãƒ¼ã®ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹ã€‚スキャナーã®ãƒ©ãƒ³ãƒ—をオンã«ã™ã‚‹ã€‚ã™ãã«ãƒ©ãƒ³ãƒ—をオフã«ã™ã‚‹ã€‚䏿˜Žå–ã‚Šå‡ºã—æ›¸é¡žã®å–り出ã—走査後ã€ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’å–り出ã™èµ°æŸ»å¾Œã«ãƒ¡ãƒ‡ã‚£ã‚¢ã‚’å–り出ã™ã€‚ãƒœã‚¿ãƒ³çŠ¶æ…‹ã®æ›´æ–°æƒ…å ±æ›´æ–°ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã®æ›´æ–°ã‚ªãƒ—ションを更新ã™ã‚‹ã€‚è£…ç½®ã®æƒ…報を更新カスタムガンマテーブルを使ã†ï¼’å€å…‰å­¦è§£åƒåº¦ã®ãƒ¬ãƒ³ã‚ºã‚’使ã†ãƒŽãƒ³ãƒ–ロッキングIOを使ã†ãƒ•ロントエンドãŒã‚µãƒãƒ¼ãƒˆã™ã‚‹ã¨ãã¯ã€sane_read()ã«ãƒŽãƒ³ãƒ–ロッキングIOを使ã†ã€‚ãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢è§£åƒåº¦ã ã‘を使用lightlid-35mmアダプターを使ã†ãƒ¦ãƒ¼ã‚¶å®šç¾©ãƒ¦ãƒ¼ã‚¶å®šç¾©ï¼ˆã‚¬ãƒ³ãƒžï¼ï¼‘.ï¼ï¼‰ãƒ¦ãƒ¼ã‚¶å®šç¾©ï¼ˆã‚¬ãƒ³ãƒžï¼ï¼‘.8)垂直ã®ãƒœã‚¿ãƒ³ã‚’å¾…ã¤ãƒœã‚¿ãƒ³å¾…ã¡ï¼–ï¼ç§’ã®æš–æ©Ÿæ™‚間を使ã†ä»£ã‚りã«ã€ãƒ©ãƒ³ãƒ—ã®è¼åº¦ãŒä¸€å®šã«ãªã‚‹ã¾ã§æš–機ã—ã¾ã™ã€‚ãƒ©ãƒ³ãƒ—ã®æš–æ©Ÿèµ°æŸ»å‰ã®ãƒ©ãƒ³ãƒ—ã®æš–æ©Ÿæš–機プロセスãŒç„¡åйã«ãªã‚Šã¾ã™æš–機時間暖機時間を秒ã§è¨­å®šã€‚水平解åƒåº¦ãŒåž‚ç›´è§£åƒåº¦ã‚ˆã‚Šä½Žã„よã†ãªé«˜è§£åƒåº¦ã‚’使ã†ã¨ãã¯ã€æ°´å¹³interpolationを無効ã«ã—ã¾ã™ã€‚ホワイトレベルホワイトレベルã®é’値ホワイトレベルã®ç·‘値ホワイトレベルã®èµ¤å€¤ç™½ã‚·ãƒ£ãƒ‰ãƒ¼è£œæ­£ã¯ç„¡åйã«ã•れã¾ã™ã€‚Xè§£åƒåº¦XPAXPAã®ã‚°ãƒ¬ãƒ¼XPAæ–¹å¼RGBYè§£åƒåº¦ã‚ºãƒ¼ãƒ ã‚³ãƒžãƒ³ãƒ‰ã®é †åºã‚¨ãƒ©ãƒ¼ãƒ•ィルムスキャナーフラットベッド(平å°åž‹ï¼‰ã‚¹ã‚­ãƒ£ãƒŠãƒãƒ¼ãƒ‰ã‚¦ã‚¨ã‚¢ãƒã‚§ãƒƒã‚¯ã‚¨ãƒ©ãƒ¼åˆæœŸåŒ–ルーãƒãƒ³ãŒã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’å—ä¿¡ã—ã¾ã—ãŸã€‚IDENTIFYメッセージã«ä¸æ­£ãªãƒ“ãƒƒãƒˆä¸æ­£ãªã‚³ãƒžãƒ³ãƒ‰æ“作コードCDBã«ä¸æ­£ãªãƒ•ィールドパラメターリストã«ä¸æ­£ãªãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ä¸æ­£ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚¨ãƒ©ãƒ¼ãƒ©ãƒ³ãƒ—ä¸è‰¯ãƒ©ãƒ³ãƒ—ãŒå®‰å®šã—ã¾ã›ã‚“媒体ãŒå­˜åœ¨ã—ã¾ã›ã‚“追加センサー情報ã¯ã‚りã¾ã›ã‚“。オフセットXオフセットYã‚ªãƒ—ã‚·ãƒ§ãƒ³ãŒæ­£ã—ãã‚りã¾ã›ã‚“ã»ã‹ã®åˆæœŸåŒ–プログラムã«ã‚ˆã£ã¦ãƒ‘ラメターãŒå¤‰æ›´ã•れã¾ã—ãŸãƒ‘ラメターリストã®é•·ã•エラー電æºONリセット/ãƒã‚¹ãƒ‡ãƒã‚¤ã‚¹ãƒªã‚»ãƒƒãƒˆå†é¸æŠžå¤±æ•—丸ã‚られãŸãƒ‘ラメター値走査ヘッドã®ä½ç½®ã‚¨ãƒ©ãƒ¼ã‚·ãƒ¼ãƒˆãƒ•ィーダスキャナータイムアウトエラー指定ã•れãŸã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ãŒå¤šã™ãŽã¾ã™ãƒ•ィルムユニットã®ãƒ©ãƒ³ãƒ—ä¸è‰¯ãƒ•ィルムユニットã®ãƒ˜ãƒƒãƒ‰ä½ç½®ä¸è‰¯é€éŽãƒ¦ãƒ‹ãƒƒãƒˆã®ã‚·ã‚§ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã‚¨ãƒ©ãƒ¼ä¸æ˜Žã‚µãƒãƒ¼ãƒˆã•れãªã„LUNウエブカメラsane-backends-1.0.27/po/stamp-po0000664000175000017500000000001213110600540013302 00000000000000timestamp sane-backends-1.0.27/po/ru.po0000664000175000017500000052152513110600537012634 00000000000000# translation of sane-backends.po to # Russian translation for SANE backend options # Copyright (C) 2002, 2003, 2004, 2005 SANE Project # Vitaly Lipatov , 2002, 2003, 2004. 2005. # Vitaly Lipatov , 2005. # msgid "" msgstr "" "Project-Id-Version: sane-backends\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-12-17 23:05+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.10.1\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "КоличеÑтво параметров" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "РаÑположение" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Повышение" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Дополнительно" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Предварительный проÑмотр" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Принудительный одноцветный предварительный проÑмотр" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Бит на цвет" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Режим ÑканированиÑ" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "СкороÑть ÑканированиÑ" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "ИÑточник ÑканированиÑ" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Принудительно откатыватьÑÑ" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Ð›ÐµÐ²Ð°Ñ Ð²ÐµÑ€Ñ…Ð½ÑÑ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° X" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Ð›ÐµÐ²Ð°Ñ Ð²ÐµÑ€Ñ…Ð½ÑÑ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° Y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "ÐŸÑ€Ð°Ð²Ð°Ñ Ð½Ð¸Ð¶Ð½ÑÑ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° X" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "ÐŸÑ€Ð°Ð²Ð°Ñ Ð½Ð¸Ð¶Ð½ÑÑ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° Y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Разрешение ÑканированиÑ" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Разрешение по X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Разрешение по Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, fuzzy, no-c-format msgid "Page height" msgstr "ПодÑветка" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "ИÑпользовать неÑтандартную гамму" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "ИнтенÑивноÑть изображениÑ" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "ИнтенÑивноÑть краÑного" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "ИнтенÑивноÑть зелёного" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "ИнтенÑивноÑть Ñинего" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "ЯркоÑть" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "КонтраÑтноÑть" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Полутона" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Уровень чёрного" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Уровень белого" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Уровень белого Ð´Ð»Ñ ÐºÑ€Ð°Ñного" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Уровень белого Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Уровень белого Ð´Ð»Ñ Ñинего" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "ЗатенённоÑть" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "ЗатенённоÑть Ð´Ð»Ñ ÐºÑ€Ð°Ñного" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "ЗатенённоÑть Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "ЗатенённоÑть Ð´Ð»Ñ Ñинего" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "ПодÑветка" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "ПодÑветка Ð´Ð»Ñ ÐºÑ€Ð°Ñного" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "ПодÑветка Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "ПодÑветка Ð´Ð»Ñ Ñинего" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Тон" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "ÐаÑыщенноÑть" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Ðазвание файла" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Размер чёрно-белого шаблона" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Чёрно-белый шаблон" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "СоглаÑовывать разрешение по X и по Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Ðегатив" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Калибровка качеÑтва" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Удваивать оптичеÑкое разрешение" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "СвÑзывать RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Порог" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° краÑного" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° зелёного" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° Ñинего" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "СвÑзывать аналоговые гаммы" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Прогрев лампы" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Калибровать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Калибровать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÑ€Ð°Ñного" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Калибровать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Калибровать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ Ñинего" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Сканировать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Сканировать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÑ€Ð°Ñного" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Сканировать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Сканировать Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ Ñинего" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Калибровать плотноÑть лампы" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Сканировать плотноÑть лампы" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "УÑтановить плотноÑть лампы" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Выключить лампу при выходе" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Параметр только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ, указывающий как много параметров указанное " "уÑтройÑтво поддерживает." #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Короткий ÑпиÑок разрешений" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "КоличеÑтво параметров" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Разрешение ÑканированиÑ" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "ЗапроÑить Ñканирование качеÑтва как у предварительного проÑмотра" #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "ЗапроÑить, чтобы вÑе предварительные проÑмотры были в одноцветном " "режиме. Ðа трёхпроходных Ñканерах Ñто уменьшит количеÑтво проходов до " "одного, а на однопроходных Ñканерах Ñократит Ñ‚Ñ€ÐµÐ±Ð¾Ð²Ð°Ð½Ð¸Ñ Ðº памÑти и Ð²Ñ€ÐµÐ¼Ñ " "предварительного ÑканированиÑ." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "КоличеÑтво бит на цвет, обычным значением ÑвлÑетÑÑ 1 Ð´Ð»Ñ ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¾Ð³Ð¾ и 8 " "Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ð¾Ð³Ð¾ режима ÑканированиÑ." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Выберите режим ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ (например, штриховой, чёрно-белый или " "цветной)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "ОпределÑет ÑкороÑть, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ производитÑÑ Ñканирование." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "" "Выберите иÑточник Ñканирование (такой как уÑтройÑтво автоматичеÑкой " "подачи документов)" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "ОпределÑет, будет ли ÑовершатьÑÑ Ð¿Ñ€Ð¸Ð½ÑƒÐ´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ð¹ откат." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Координата X левого верхнего угла облаÑти ÑканированиÑ." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Координата Y левого верхнего угла облаÑти ÑканированиÑ." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Координата X правого нижнего угла облаÑти ÑканированиÑ." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Координата Y правого нижнего угла облаÑти ÑканированиÑ." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "УÑтанавливает разрешение Ñканируемого изображениÑ." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "УÑтанавливает горизонтальное разрешение Ñканируемого изображениÑ." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "УÑтанавливает вертикальное разрешение Ñканируемого изображениÑ." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, fuzzy, no-c-format msgid "Specifies the height of the media." msgstr "УÑтанавливает разрешение Ñканируемого изображениÑ." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "ОпределÑет, будет ли иÑпользоватьÑÑ Ð²ÑÑ‚Ñ€Ð¾ÐµÐ½Ð½Ð°Ñ Ð¸Ð»Ð¸ неÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð°Ñ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð° " "гамма-коррекции." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Таблица коррекции гаммы. Ð’ цветном режиме Ñтот параметр дейÑтвует " "одинаково на краÑный, зелёный и Ñиний каналы (то еÑть Ñто интенÑивноÑть " "коррекции гаммы)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Таблица коррекции гаммы Ð´Ð»Ñ ÐºÑ€Ð°Ñной компоненты." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Таблица коррекции гаммы Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð¹ компоненты." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Таблица коррекции гаммы Ð´Ð»Ñ Ñиней компоненты." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Управление ÑркоÑтью полученного изображениÑ." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Управление контраÑтноÑтью полученного изображениÑ." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "ОпределÑет, должно ли полученное изображение быть превращено в " "полутоновое (размытием)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" "ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как \"чёрный" "\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" "ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как \"белый\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "ОпределÑет, какой краÑный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"белый\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "ОпределÑет, какой зелёный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"белый\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "ОпределÑет, какой Ñиний уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"белый\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "ОпределÑет, какой краÑный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"чёрный\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "ОпределÑет, какой зелёный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"чёрный\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "ОпределÑет, какой Ñиний уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"чёрный\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "ОпределÑет, какой краÑный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"полный краÑный\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "ОпределÑет, какой зелёный уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"полный зелёный\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "ОпределÑет, какой Ñиний уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как " "\"полный Ñиний\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "УправлÑет \"тоном\" (уровнем Ñинего) полученного изображениÑ." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Уровень наÑыщенноÑти управлÑет количеÑтвом \"blooming\", который " "получаетÑÑ Ð¿Ñ€Ð¸ получении Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñ ÐºÐ°Ð¼ÐµÑ€Ñ‹. Большие Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð·Ñ‹Ð²Ð°ÑŽÑ‚ " "больше blooming." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Ðазвание файла изображениÑ, которое должно быть загружено." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "УÑтанавливает размер полутонового (dithering) шаблона, иÑпользуемого при " "Ñканировании полутоновых изображений." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "УÑтанавливает полутоновый (dithering) шаблон, иÑпользуемый при " "Ñканировании полутоновых изображений." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "" "ИÑпользовать одинаковые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ð¹ по горизонтали и " "вертикали." #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "ПоменÑть меÑтами чёрный и белый" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Выполнить качеÑтвенную калибровку белого" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "ИÑпользовать lens, которое удваивает оптичеÑкое разрешение" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Ð’ режиме RGB иÑпользовать одинаковые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ цвета" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Выберите минимальную ÑркоÑть Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð±ÐµÐ»Ð¾Ð¹ точки" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ Ð´Ð»Ñ ÐºÑ€Ð°Ñного" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ Ð´Ð»Ñ Ñинего" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Прогревать лампу перед Ñканированием" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ краÑного" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ зелёного" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ Ñинего" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑканированиÑ" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÑ€Ð°Ñного" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñинего" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Включить выбор времени выдержки" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Определить плотноÑть лампы Ð´Ð»Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Определить плотноÑть лампы Ð´Ð»Ñ ÑканированиÑ" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Включить выбор плотноÑти лампы" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Выключить лампу при выходе из программы" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Разрешение ÑканированиÑ" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "Ожидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "Ожидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "Ожидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Цветовой шаблон" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Цветной" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Цветное штриховое" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Цветное полутоновое" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Чёрно-белый" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Полутоновый (раÑтр)" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Штриховой" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, fuzzy, no-c-format msgid "Operation not supported" msgstr "Полутоновое Ñканирование не поддерживаетÑÑ" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "Податчик лиÑтов" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "Податчик лиÑтов" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "По умолчанию" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "УÑтанавливает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð²Ñ‹ÑˆÐµÐ½Ð¸ÐµÐ¼." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Калибровка" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Калибровать перед Ñледующим Ñканированием" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "ЕÑли отмечено, уÑтройÑтво будет откалибровано перед Ñледующим " "Ñканированием. Ð’ противном Ñлучае, калибровка будет выполнена только " "перед первым Ñканированием." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "ВыполнÑть только коррекцию оттенка" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "ЕÑли отмечено, во Ð²Ñ€ÐµÐ¼Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸ выполнÑетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ " "оттенков. Ð”Ð»Ñ ÑƒÑилениÑ, ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¸ времени выдержки иÑпользуютÑÑ Ð»Ð¸Ð±Ð¾ " "вÑтроенные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию, либо из конфигурационного файла." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "СоÑтоÑние кнопки" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "КоличеÑтво кадров Ð´Ð»Ñ ÑканированиÑ" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Выберите количеÑтво кадров Ð´Ð»Ñ ÑканированиÑ" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "ДвухÑтороннее Ñканирование" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "ДвухÑтороннее Ñканирование позволÑет получить изображение лицевой и " "обратной Ñтороны документа" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Калибровать Ñканер" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "ВыполнÑть калибровку Ñканера перед Ñканированием" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Чёрно-белое Ñканирование" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "ВыполнÑть чёрно-белое Ñканирование вмеÑто цветного" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Ðналоговое уÑиление" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Увеличить или уменьшить аналоговое уÑиление матрицы CCD" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "ÐšÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Выберите кривую гамма-коррекции" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, fuzzy, no-c-format msgid "No transparency correction" msgstr "ÐšÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, fuzzy, no-c-format msgid "Negatives" msgstr "Ðегатив" #: backend/canon.c:176 #, fuzzy, no-c-format msgid "Slides" msgstr "Слайд" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "ÐвтоматичеÑки" #: backend/canon.c:186 #, fuzzy, no-c-format msgid "Normal speed" msgstr "Ðормально" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/2 normal speed" msgstr "2x2 нормальное" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/3 normal speed" msgstr "3x3 нормальное" #: backend/canon.c:365 #, fuzzy, no-c-format msgid "rounded parameter" msgstr "Ðечёткие параметры" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "" #: backend/canon.c:378 #, fuzzy, no-c-format msgid "ADF jam" msgstr "ÐПД" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, fuzzy, no-c-format msgid "lamp failure" msgstr "Значение гаммы" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, fuzzy, no-c-format msgid "transparency unit lamp failure" msgstr "Модуль Ð´Ð»Ñ Ñлайдов" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, fuzzy, no-c-format msgid "transparency unit shading error" msgstr "Модуль Ð´Ð»Ñ Ñлайдов" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, fuzzy, no-c-format msgid "film scanner" msgstr "планшетный Ñканер" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "планшетный Ñканер" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Тип плёнки" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, fuzzy, no-c-format msgid "Negative film type" msgstr "Ðегатив" #: backend/canon.c:1197 #, fuzzy, no-c-format msgid "Selects the negative film type" msgstr "Выберите теÑтовое изображение" #: backend/canon.c:1236 #, fuzzy, no-c-format msgid "Hardware resolution" msgstr "Разрешение ÑканированиÑ" #: backend/canon.c:1237 #, fuzzy, no-c-format msgid "Use only hardware resolutions" msgstr "Показывать короткий ÑпиÑок разрешений" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, fuzzy, no-c-format msgid "Auto focus" msgstr "Ðвтоизвлечение" #: backend/canon.c:1329 #, fuzzy, no-c-format msgid "Enable/disable auto focus" msgstr "Выключить предварительный фокуÑ" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, fuzzy, no-c-format msgid "Manual focus position" msgstr "ЗафикÑировать позицию фокуÑа" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Зеркальное изображение" #: backend/canon.c:1539 #, fuzzy, no-c-format msgid "Mirror the image horizontally" msgstr "Отображает изображение по горизонтали." #: backend/canon.c:1608 #, fuzzy, no-c-format msgid "Auto exposure" msgstr "УÑтановить Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸" #: backend/canon.c:1609 #, fuzzy, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Включить выбор времени выдержки" #: backend/canon.c:1625 #, fuzzy, no-c-format msgid "Calibration now" msgstr "Калибровка" #: backend/canon.c:1626 #, fuzzy, no-c-format msgid "Execute calibration *now*" msgstr "Задать режим калибровки" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, fuzzy, no-c-format msgid "Reset scanner" msgstr "лиÑтовой Ñканер" #: backend/canon.c:1649 #, fuzzy, no-c-format msgid "Reset the scanner" msgstr "лиÑтовой Ñканер" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, fuzzy, no-c-format msgid "Eject film after each scan" msgstr "Извлечь документ поÑле ÑканированиÑ" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, fuzzy, no-c-format msgid "Document feeder extras" msgstr "Податчик лиÑтов" #: backend/canon.c:1707 #, fuzzy, no-c-format msgid "Flatbed only" msgstr "Планшетный" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, fuzzy, no-c-format msgid "Transparency unit" msgstr "Модуль Ð´Ð»Ñ Ñлайдов" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, fuzzy, no-c-format msgid "Negative film" msgstr "Ðегатив" #: backend/canon.c:1740 #, fuzzy, no-c-format msgid "Positive or negative film" msgstr "Позитив" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, fuzzy, no-c-format msgid "Transparency ratio" msgstr "Модуль Ð´Ð»Ñ Ñлайдов" #: backend/canon.c:1775 #, fuzzy, no-c-format msgid "Select film type" msgstr "Тип плёнки" #: backend/canon.c:1776 #, fuzzy, no-c-format msgid "Select the film type" msgstr "Выбирает полутона." #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Планшетный" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "ÐПД" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, fuzzy, no-c-format msgid "ADF Duplex" msgstr "ДвухÑторонний" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "РаÑпечатка" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "ДвухÑторонний" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "КраÑный" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Зелёный" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Синий" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Повышение" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Повышение" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Повышение" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Ðичего" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "ОдноÑторонний" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "ДвухÑторонний" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Модуль Ð´Ð»Ñ Ñлайдов" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "ÐвтоматичеÑкий податчик документов" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Позитив" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Ðегатив" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Ð¤Ð¾ÐºÑƒÑ Ð½Ð° Ñтекле" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Ð¤Ð¾ÐºÑƒÑ 2.5мм над Ñтеклом" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Чёрно-белый A (Резкие тона)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Чёрно-белый B (МÑгкие тона)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Чёрно-белый C (Net Screen)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Ð¢ÐµÑ…Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ ÑƒÐ»ÑƒÑ‡ÑˆÐµÐ½Ð¸Ñ Ñ‚ÐµÐºÑта" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Загрузить шаблон A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Загрузить шаблон B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Без коррекции" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "ОпределÑемое пользователем" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Матричные принтеры" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "ТермичеÑкие принтеры" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Струйные принтеры" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Мониторы Ñ Ð­Ð›Ð¢" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "По умолчанию" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Печать выÑокой плотноÑти" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Печать выÑокой плотноÑти" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Печать выÑокой контраÑтноÑти" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Определённое пользователем (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Определённое пользователем (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 портрет" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 ландшафт" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "МакÑ" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Режим ÑканированиÑ" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Выбирает полутона." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Выбирает ÑркоÑть." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "РезкоÑть" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "ÐšÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "УÑтанавливает таблицу коррекции цветов Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ выходного " "уÑтройÑтва." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "КоÑффициенты цветовой коррекции" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Матричный множитель RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Сдвиг зелёного к краÑному" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Сдвиг зелёного к Ñинему" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Сдвиг краÑного к зелёному" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Сдвиг краÑного к Ñинему" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Сдвиг Ñинего к зелёному" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Сдвиг Ñинего к краÑному" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "УправлÑет уровнем зелёного" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "ДобавлÑет к краÑному, оÑнованному на уровне зелёного" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "ДобавлÑет к Ñинему, оÑнованному на уровне зелёного" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "ДобавлÑет к зелёному, оÑнованному на уровне краÑного" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "УправлÑет уровнем краÑного" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "ДобавлÑет к Ñинему, оÑнованному на уровне краÑного" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "ДобавлÑет к зелёному, оÑнованному на уровне Ñинего" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "ДобавлÑет к краÑному, оÑнованному на уровне Ñинего" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "УправлÑет уровнем Ñинего" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Сделать изображение зеркальным." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "БыÑтрый предварительный проÑмотр" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "ÐвтоматичеÑки разделÑть на облаÑти" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Короткий ÑпиÑок разрешений" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Показывать короткий ÑпиÑок разрешений" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "МаÑштаб" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "" "ОпределÑет коÑффициент маÑштабированиÑ, который будет иÑпользоватьÑÑ " "Ñканером" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "БыÑтрый формат" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Дополнительное оборудование" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Извлечь" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Ð’Ñтавить бумагу в уÑтройÑтво подачи документов" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Ðвтоизвлечение" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Извлечь документ поÑле ÑканированиÑ" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Режим автоподачи" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Выбирает режим автоподачи (одноÑторонний/двухÑторонний)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "ОтÑек" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Выбрать отÑек, который Ñканировать" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Выбирает значение гамма-коррекции из ÑпиÑка предопределённых или " "наÑтроенных пользователем, которое может быть загружено в Ñканер" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "РаÑположение фокуÑа" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "УÑтанавливает раÑположение фокуÑа либо на Ñтекле, либо на 2.5мм выше " "Ñтекла" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Ожидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "ПоÑле подачи команды \"Ñканировать\", будет ожидать пока не будет нажата " "кнопка на Ñканере, чтобы дейÑтвительно начать процеÑÑ ÑканированиÑ." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, fuzzy, no-c-format msgid "Positive Slide" msgstr "Позитив" #: backend/epson2.c:137 #, fuzzy, no-c-format msgid "Negative Slide" msgstr "Ðегатив" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "ОпределÑемое пользователем" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Вкл" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Выкл" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Размытие" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "Ð”Ð¸Ñ„Ñ„ÑƒÐ·Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Уровень белого" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Уровень чёрного" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "УÑловно" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Горизонтально" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Горизонтально" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Горизонтально" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Вертикальное" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Вертикальное" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "РаÑпечатка" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Полутоновый (раÑтр)" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ°" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "ВыразительноÑть изображениÑ" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "ÐаÑыщенноÑть" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "" "Включает автоматичеÑкое определение порога при Ñканировании штриховых " "изображений." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Зеркальное изображение" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Отображает изображение по горизонтали." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Уровень белого Ð´Ð»Ñ Ñинего" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "УправлÑет уровнем краÑного" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Цветное штриховое" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Сглаживание" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Значение гаммы" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Порог" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Порог" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Уменьшение шумов" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Без коррекции" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Без коррекции" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Режим подачи" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Дополнительные параметры" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Без коррекции" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Включить лампу" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Режим подачи" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Смещение Ñинего" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Смещение зелёного" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Смещение зелёного" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Смещение Ñинего" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "УÑтанавливает Ñмещение канала Ñинего" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "ДвухÑтороннее Ñканирование" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Дополнительные параметры" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Уменьшение шумов" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "От бумаги" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "От бумаги" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "От бумаги" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "От бумаги" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Ð ÑƒÑ‡Ð½Ð°Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ„Ð¾ÐºÑƒÑировка" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Ð ÑƒÑ‡Ð½Ð°Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ„Ð¾ÐºÑƒÑировка" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "Разрешение ÑканированиÑ" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Уровень белого" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "ИнтенÑивноÑть краÑного" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "ДвухÑтороннее Ñканирование" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Дополнительно" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, fuzzy, no-c-format msgid "Disable interpolation" msgstr "Выключить отÑлеживание" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Цветное штриховое" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Калибровка" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Задать режим калибровки" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "КÑширование калибровочных данных" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "Лампа будет выключена через указанное Ð²Ñ€ÐµÐ¼Ñ (в минутах). Значение 0 " "означает, что лампа выключатьÑÑ Ð½Ðµ будет." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ°" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "Ожидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "Ожидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Ожидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ°" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "ВыполнÑть калибровку Ñканера перед Ñканированием" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Кнопки" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Калибровка" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Ðачать процеÑÑ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸." #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ°" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "КÑширование калибровочных данных" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Слайд-модуль" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Цвет полутонового режима" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Выбирает, какой цвет будет иÑпользоватьÑÑ Ð¿Ñ€Ð¸ Ñканировании в полутоновом " "режиме (по умолчанию - зелёный)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Параметры отладки" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "ÐвтоматичеÑкий прогрев" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Разогревать пока ÑркоÑть лампы не Ñтанет поÑтоÑнной, вмеÑто проÑтого 60-" "тиÑекундного Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñ€Ð°Ð·Ð¾Ð³Ñ€ÐµÐ²Ð°." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Полное Ñканирование" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Сканировать полноÑтью вÑÑŽ облаÑть ÑканированиÑ, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²Ð¾Ñ‡Ð½ÑƒÑŽ " "полоÑу. Будьте оÑторожны. Ðе выбирайте полную выÑоту. Только Ð´Ð»Ñ " "теÑтированиÑ." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ°" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "ÐаÑтраивает уÑиление и Ñмещение Ð´Ð»Ñ ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки. ЕÑли " "Ñтот параметр выключен, будут предоÑтавлены параметры Ð´Ð»Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð¹ " "аналоговой наÑтройки. Параметр включен по умолчанию. Только Ð´Ð»Ñ " "теÑтированиÑ." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ° только Ð´Ð»Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ ÑканированиÑ" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "ВыполнÑть грубую калибровку только во Ð²Ñ€ÐµÐ¼ÐµÐ½Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ ÑканированиÑ. " "Работает Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð½Ñтвом Ñканеров и может ÑÑкономить Ð²Ñ€ÐµÐ¼Ñ ÑканированиÑ. " "ЕÑли ÑркоÑть Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¾Ñ‚Ð»Ð¸Ñ‡Ð°ÐµÑ‚ÑÑ Ð¿Ñ€Ð¸ каждом Ñканировании, выключите " "Ñтот параметр. Только Ð´Ð»Ñ Ñ‚ÐµÑтированиÑ." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Линии отката" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "КоличеÑтво линий, на которые Ñчитыватель возвращаетÑÑ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾ при " "необходимоÑти. Это проиÑходит когда Ñканер Ñчитывает изображение " "быÑтрее, чем компьютер может принимать данные. Ðизкое значение приводит " "к более быÑтрому Ñканированию, но увеличивает вероÑтноÑть пропуÑка линий." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Значение гаммы" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "УÑтанавливает значение гаммы вÑех каналов." #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "РаÑположение" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, fuzzy, no-c-format msgid "Scan Mode Group" msgstr "Режим ÑканированиÑ" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Слайд" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Режим ÑканированиÑ" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "ÐÐ½Ð°Ð»Ð¾Ð³Ð¾Ð²Ð°Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "ÐšÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹" #: backend/hp3900_sane.c:1451 #, fuzzy, no-c-format msgid "Disable white shading correction" msgstr "ВыполнÑть только коррекцию оттенка" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "Чёрно-белый" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "лиÑтовой Ñканер" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Игнорировать калибровку" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Ðазвание файла" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "лиÑтовой Ñканер" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "ИÑточник ÑканированиÑ" #: backend/hp3900_sane.c:1584 #, fuzzy, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Выберите количеÑтво кадров Ð´Ð»Ñ ÑканированиÑ" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Обновить параметры" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, fuzzy, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Этот параметр отражает ÑоÑтоÑние кнопок Ñканера." #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Изображение" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Различное" #: backend/hp5400_sane.c:358 #, fuzzy, no-c-format msgid "offset X" msgstr "Смещение" #: backend/hp5400_sane.c:359 #, fuzzy, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Координата X левого верхнего угла облаÑти ÑканированиÑ." #: backend/hp5400_sane.c:368 #, fuzzy, no-c-format msgid "offset Y" msgstr "Смещение" #: backend/hp5400_sane.c:369 #, fuzzy, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Координата X левого верхнего угла облаÑти ÑканированиÑ." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "СоÑтоÑние лампы" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Включить/выключить лампу." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Калибрует Ð´Ð»Ñ Ñ‡Ñ‘Ñ€Ð½Ð¾Ð³Ð¾ и белого уровнÑ." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ÐПД" #: backend/hp5590.c:88 #, fuzzy, no-c-format msgid "TMA Slides" msgstr "Слайд" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Ðегатив" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "Цветной 48" #: backend/hp5590.c:95 #, fuzzy, no-c-format msgid "Extend lamp timeout" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Ожидать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: backend/hp5590.c:99 #, fuzzy, no-c-format msgid "Waits for button before scanning" msgstr "Прогревать лампу перед Ñканированием" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Дополнительные параметры" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Грубое" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Точное" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "ПользовательÑкое" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "ÐвтоматичеÑки" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "ПропуÑкать Ñквозь" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "Чёрно-белое NTSC" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "Чёрно-белое XPA" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Медленно" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Ðормально" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "БыÑтро" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Очень быÑтро" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "Двухточечное" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "Четырёхточечное" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "ВоÑьмиточечное" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "РаÑпечатка" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Плёнка" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "УÑловно" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "ЭкÑперимент" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "ЗаоÑтрениÑ" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "УÑтанавливает величину заоÑтрениÑ." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "ÐвтоматичеÑкий порог" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Включает автоматичеÑкое определение порога при Ñканировании штриховых " "изображений." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Выберите фильтр Ð´Ð»Ñ ÑглаживаниÑ." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Выгружать ноÑитель поÑле ÑканированиÑ" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Выгружает ноÑитель поÑле ÑканированиÑ." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Сменить документ" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Изменить документ." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Выгрузить" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Выгрузить документ." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Ðачать процеÑÑ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ¸." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "ÐоÑитель" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "УÑтановить тип ноÑителÑ." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Длительное Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸ позволÑет Ñканеру Ñобрать больше Ñвета. " "РекомендуетÑÑ Ð¸Ñпользовать 175% Ð´Ð»Ñ Ñ€Ð°Ñпечаток, 150% Ð´Ð»Ñ Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ñ‹Ñ… " "Ñлайдов и \"Ðегатив\" Ð´Ð»Ñ Ð½ÐµÐ³Ð°Ñ‚Ð¸Ð²Ð¾Ð². Ð”Ð»Ñ Ñ‚Ñ‘Ð¼Ð½Ñ‹Ñ… (недоÑкÑпонированных) " "изображений вы можете увеличить Ñто значение." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Ð¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð°" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "УÑтанавливает цветовую матрицу Ñканера." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "ПользовательÑÐºÐ°Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð°" #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "ÐžÐ´Ð½Ð¾Ñ‚Ð¾Ð½Ð½Ð°Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð°" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "ПользовательÑÐºÐ°Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ð° Ð´Ð»Ñ Ñ‡Ñ‘Ñ€Ð½Ð¾-белых изображений." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Отобразить горизонтально" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Отображает изображение по горизонтали." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Отобразить вертикально" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Отображает изображение по вертикали." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Обновить параметры" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "ОбновлÑет параметры." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "ВоÑьмибитный вывод" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Внутри иÑпользовать разрÑдноÑть более 8 бит, но выводить только 8 бит." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Ожидать кнопки на лицевой панели" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Ждать Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ на передней панели Ð´Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° ÑканированиÑ." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Выключить лампу" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Выключает лампу Ñканера." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Размер бумаги" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "ÐвтоматичеÑкое разделение" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 ландшафт" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Ð ÑƒÑ‡Ð½Ð°Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ„Ð¾ÐºÑƒÑировка" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Ð ÑƒÑ‡Ð½Ð°Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ„Ð¾ÐºÑƒÑировка" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Включить двуÑтороннее Ñканирование" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "ФизичеÑкий размер бумаги в уÑтройÑтве автоподачи" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Полутоновый (раÑтр)" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Цветной" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "УÑловно" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Выкл" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Полутоновый (раÑтр)" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Полутоновый (раÑтр)" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Ð”Ð¸Ñ„Ñ„ÑƒÐ·Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Ðормально" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "ПодÑветка" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "планшетный Ñканер" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "От бумаги" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "По умолчанию" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Сглаживать" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Медленно" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Ðормальный" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "КраÑный" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Зелёный" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "ИÑточник ÑканированиÑ" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Режим подачи" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "УÑтанавливает режим подачи" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Выключить предварительный фокуÑ" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Выключить предварительный фокуÑ" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "УÑтанавливает режим подачи" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "УÑтанавливает режим подачи" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "ÐвтоматичеÑкий порог" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "ÐвтоматичеÑки уÑтанавливает ÑркоÑть, контраÑтноÑть, уровень белого, " "гамму, уменьшение шума и выразительноÑть изображениÑ" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Уменьшение шумов" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Уменьшает количеÑтво отдельных Ñлучайных точек" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "ВыразительноÑть изображениÑ" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "УÑтанавливает выразительноÑть изображениÑ" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Гамма" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Включить лампу" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Включить/выключить лампу." #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Отображает изображение по вертикали." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "ÐšÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Печать выÑокой плотноÑти" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Печать выÑокой плотноÑти" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Ð”Ð¸Ñ„Ñ„ÑƒÐ·Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Без коррекции" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Ðормально" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Повышение" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "ÐвтоматичеÑкий порог" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "ÐвтоматичеÑкий порог" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "УÑтановить порÑдок кадров" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "ЗатенённоÑть Ð´Ð»Ñ Ñинего" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Сдвиг краÑного к Ñинему" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "УÑиление" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "ÐаÑтройки уÑÐ¸Ð»ÐµÐ½Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ñ‹Ñ… каналов" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "УÑиление Ñерого" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "УÑтанавливает уÑиление Ñерого канала" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "УÑиление краÑного" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "УÑтанавливает уÑиление краÑного канала" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "УÑиление зелёного" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "УÑтанавливает уÑиление зелёного канала" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "УÑиление Ñинего" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "УÑтанавливает уÑиление Ñинего канала" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Полутоновый пункт 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Полутоновый пункт 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Ð”Ð¸Ñ„Ñ„ÑƒÐ·Ð¸Ñ Ð¾ÑˆÐ¸Ð±Ð¾Ðº" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Режим 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Режим 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Режим 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "От белой палочки" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Сглаживать" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Ðизкий" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Ðормальный" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Ð’Ñ‹Ñокий" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "ЭЛТ" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Одна Ñтраница" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Ð’Ñе Ñтраницы" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "лиÑтовой Ñканер" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Оттенки Ñерого 4 бита" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Оттенки Ñерого 8 бит" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "ЗатенённоÑть, полутон, подÑветка, Ð²Ñ€ÐµÐ¼Ñ Ð²Ñ‹Ð´ÐµÑ€Ð¶ÐºÐ¸" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Специальные параметры" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Цветовой баланÑ" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Выключить отÑлеживание" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "ЕÑли отмечено, Ñканер не выполнÑет отÑлеживание" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Переключить лампу планшетного Ñканера" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Переключает лампу планшетного Ñканера" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Калибровка производитÑÑ Ð´Ð²Ð¸Ð¶ÐºÐ¾Ð¼" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "ЕÑли отмечено, калибровка цвета перед Ñканированием выполнÑетÑÑ Ð´Ð²Ð¸Ð¶ÐºÐ¾Ð¼" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "ИÑпользовать 35мм адаптер lightlid" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "" "Этот параметр выключает лампу планшетного Ñканера во Ð²Ñ€ÐµÐ¼Ñ ÑканированиÑ" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "КачеÑтвенное Ñканирование" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "ÐаивыÑшее качеÑтво, но Ð¼ÐµÐ´Ð»ÐµÐ½Ð½Ð°Ñ ÑкороÑть" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "БыÑтрое Ñканирование" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "ÐаивыÑÑˆÐ°Ñ ÑкороÑть, но низкое качеÑтво" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "ÐвтоматичеÑкое наÑтраивание порога" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "ЕÑли отмечено, движок автоматичеÑки попробует определить оптимальное " "значение порога." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Выберите режим коррекции гаммы." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "СвÑзывать гаммы" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "ИÑпользовать те же Ñамые Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð³Ð°Ð¼Ð¼Ñ‹ Ð´Ð»Ñ Ð²Ñех цветовых каналов." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "СкалÑÑ€Ð½Ð°Ñ Ð³Ð°Ð¼Ð¼Ð°" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Выбирает значение Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ð¸ ÑкалÑрной гаммы." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "СкалÑÑ€Ð½Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° краÑного" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Выбирает значение Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ð¸ ÑкалÑрной гаммы (канал краÑного)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "СкалÑÑ€Ð½Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° зелёного" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Выбирает значение Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ð¸ ÑкалÑрной гаммы (канал зелёного)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "СкалÑÑ€Ð½Ð°Ñ Ð³Ð°Ð¼Ð¼Ð° Ñинего" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Выбирает значение Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ†Ð¸Ð¸ ÑкалÑрной гаммы (канал Ñинего)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Канал" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Выбирает ÑвÑзь цветов, \"ОÑновной\" означает, что будут подвержены вÑе " "цвета." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Полутон" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" "ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как \"50 % " "Ñерого\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Полутон Ð´Ð»Ñ ÐºÑ€Ð°Ñного" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "" "ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как \"50 % " "краÑного\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Полутон Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" "ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как \"50 % " "зелёного\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Полутон Ð´Ð»Ñ Ñинего" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" "ОпределÑет, какой уровень Ð¸Ð·Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ быть раÑÑмотрен как \"50 % " "Ñинего\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ ÐºÑ€Ð°Ñного" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" "КоÑффициент Ð´Ð»Ñ ÐºÑ€Ð°Ñного цвета. Значение 100% означает отÑутÑтвие " "коррекции." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" "КоÑффициент Ð´Ð»Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð³Ð¾ цвета. Значение 100% означает отÑутÑтвие " "коррекции." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ Ñинего" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" "КоÑффициент Ð´Ð»Ñ Ñинего цвета. Значение 100% означает отÑутÑтвие " "коррекции." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "БаланÑ, уÑтановленный на заводе" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" "УÑтанавливает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ð¾Ð³Ð¾ баланÑа в иÑходные значениÑ, " "уÑтановленные на заводе." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Ð¡Ð°Ð¼Ð°Ñ Ð¼ÐµÐ´Ð»ÐµÐ½Ð½Ð°Ñ" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "МедленнаÑ" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "БыÑтраÑ" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Ð¡Ð°Ð¼Ð°Ñ Ð±Ñ‹ÑтраÑ" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 грубое" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 нормальное" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 хорошее" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 очень хорошее" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 нормальное" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 грубое" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 хорошее" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 грубое" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 нормальное" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 хорошее" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 нормальное" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 нормальное" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 выборочно" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 выборочно" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 выборочно" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 выборочно" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 выборочно" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 выборочно" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "БыÑтрый чёрно-белый режим" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Сканировать в быÑтром чёрно-белом режиме (наихудшее качеÑтво)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "ПредпиÑывает вÑе предварительные проÑмотры выполнÑть в быÑтрейшем " "(низкокачеÑтвенном) режиме. Это может быть чёрно-белый режим или режим Ñ " "низким разрешением." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹ (в минутах)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Указывает Ð²Ñ€ÐµÐ¼Ñ (в минутах), поÑле которого лампа будет выключена." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Выключить лампу Ñканера" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Выключает лампу незамедлительно." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "ЯркоÑть краÑного" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "УправлÑет ÑркоÑтью краÑного канала полученного изображениÑ." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "ЯркоÑть зелёного" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "УправлÑет ÑркоÑтью зелёного канала полученного изображениÑ." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "ЯркоÑть Ñинего" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "УправлÑет ÑркоÑтью Ñинего канала полученного изображениÑ." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "КонтраÑтноÑть краÑного канала" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "УправлÑет контраÑтноÑтью краÑного канала полученного изображениÑ." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "КонтраÑтноÑть зелёного канала" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "УправлÑет контраÑтноÑтью зелёного канала полученного изображениÑ." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "КонтраÑтноÑть Ñинего канала" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "УправлÑет контраÑтноÑтью Ñинего канала полученного изображениÑ." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Цветной 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Цветной 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Чёрно-белый 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Чёрно-белый 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, fuzzy, no-c-format msgid "Positive" msgstr "Позитив" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Разогревать пока ÑркоÑть лампы не Ñтанет поÑтоÑнной, вмеÑто проÑтого 40-" "тиÑекундного Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñ€Ð°Ð·Ð¾Ð³Ñ€ÐµÐ²Ð°." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Ðегатив" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Ðегатив" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, fuzzy, no-c-format msgid "Update button state" msgstr "СоÑтоÑние кнопки" #: backend/pixma_sane_options.c:244 #, fuzzy, no-c-format msgid "Button 1" msgstr "Кнопки" #: backend/pixma_sane_options.c:258 #, fuzzy, no-c-format msgid "Button 2" msgstr "Кнопки" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Прозрачный" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "ÐаÑтройки уÑтройÑтва" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Выключатель лампы" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Вручную управлÑет лампой." #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ°" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "КÑширование калибровочных данных" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Включает или выключает кÑширование данных о калибровке." #: backend/plustek.c:942 #, fuzzy, no-c-format msgid "Performs calibration" msgstr "Ð“Ñ€ÑƒÐ±Ð°Ñ ÐºÐ°Ð»Ð¸Ð±Ñ€Ð¾Ð²ÐºÐ°" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¾Ð³Ñ€ÐµÐ²Ð° лампы" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð¿Ñ€Ð¾Ð³Ñ€ÐµÐ²Ð° лампы в Ñекундах." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹ в Ñекундах." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Смещение краÑного" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Выключение краÑной лампы" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "ОпределÑет параметры Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ ÐºÑ€Ð°Ñной лампы" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Выключение зелёной лампы" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "ОпределÑет параметры Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð·ÐµÐ»Ñ‘Ð½Ð¾Ð¹ лампы" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Выключение Ñиней лампы" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "ОпределÑет параметры Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ñиней лампы" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Этот параметр отражает ÑоÑтоÑние кнопок Ñканера." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Цветное 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Случайный" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "ИÑточник ÑканированиÑ" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "ВыразительноÑть изображениÑ" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Сделать чёрно-белым" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Загрузить изображение как чёрно-белое" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ‚Ñ€Ñ‘Ñ…Ð¿Ñ€Ð¾Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ режима" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Имитирует трёхпроходной Ñкнер возвращениём трёх различных кадров. То " "еÑть возвращает Ñначала зелёный, потом Ñиний, потом краÑный." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ñканера" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Имитирует ручной Ñканер. Ручные Ñканеры чаÑто не имеют информации о " "длине изображениÑ. ВмеÑто Ñтого они возвращает длину -1. УÑтановка Ñтого " "параметра позволит проверить будет ли фронтенд корректно обрабатывать " "Ñту Ñитуацию." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "УÑтанавливает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ умолчанию Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð²Ñ‹ÑˆÐµÐ½Ð¸ÐµÐ¼ (ÑркоÑтью " "и контраÑтноÑтью)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "ТеÑтовый параметр только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Таблица гаммы" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ ÐºÐ¾Ð´Ð° ÑоÑтоÑниÑ" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Ðе получать код ÑоÑтоÑниÑ" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Ðе принуждать драйвер возвращать код ÑоÑтоÑниÑ." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" #: backend/rts8891.c:2809 #, fuzzy, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Этот параметр отражает ÑоÑтоÑние кнопок Ñканера." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Включить лампу" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Включить лампу Ñканера" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Выключить лампу" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Выключить лампу Ñканера" #: backend/sm3840.c:760 #, fuzzy, no-c-format msgid "Lamp timeout" msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð»Ð°Ð¼Ð¿Ñ‹" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Податчик лиÑтов" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (дюймов)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (дюймов)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (дюймов)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Полутоновое Ñканирование не поддерживаетÑÑ" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "Точка Ñ€Ð°Ð·Ð¼Ñ‹Ñ‚Ð¸Ñ 8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "Точка Ñ€Ð°Ð·Ð¼Ñ‹Ñ‚Ð¸Ñ 16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "КоличеÑтво Ñтрок ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² запроÑе Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¿Ð¾ SCSI.Изменение Ñтого " "параметра позволит вам наÑтроить ÑкороÑть, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ данный будут " "передаватьÑÑ Ñо Ñканера во Ð²Ñ€ÐµÐ¼Ñ ÑканированиÑ. ЕÑли он уÑтановлен очень " "низким, Ñканер будет периодичеÑки оÑтанавливатьÑÑ Ð²Ð¾ Ð²Ñ€ÐµÐ¼Ñ ÑканированиÑ, " "еÑли же Ñтот параметр будет уÑтановлен очень выÑоким, графичеÑÐºÐ°Ñ " "оболочка может переÑтать принимать ÑÐ¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¾Ñ‚ ÑиÑтемы X Window и не " "будет реагировать на ваши команды до Ð¾ÐºÐ¾Ð½Ñ‡Ð°Ð½Ð¸Ñ ÑканированиÑ." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Извлечь документ поÑле ÑканированиÑ" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Режим предварительного проÑмотра" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Выберите режим Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ проÑмотра. Чёрно-белый " "предварительный проÑмотр обычно даёт лучшее Ñочетание ÑкороÑти и " "детализации." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Заранее наÑтроенные параметры" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "ПредоÑтавлÑÑŽÑ‚ Ñтандартные облаÑти ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ð¸Ð¹, " "раÑпечатанных Ñтраниц и прочего." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "планшетный Ñканер" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Ðвтоизвлечение" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "РаÑположение фокуÑа" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "РаÑположение фокуÑа" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Цветных Ñтрок за Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° чтение" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Чёрно-белых Ñтрок за Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° чтение" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Цветной RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Цветной RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Цветной RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Сплошной чёрный" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Сплошной белый" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Цветовой шаблон" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Сетка" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "ÐŸÐµÑ€Ð²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Ð’Ñ‚Ð¾Ñ€Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Это очень Ð´Ð»Ð¸Ð½Ð½Ð°Ñ Ñ‚Ñ€ÐµÑ‚ÑŒÑ Ð·Ð°Ð¿Ð¸ÑÑŒ. Может быть фронтенд Ñможет показать её." #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ñканера" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Имитировать ручной Ñканер. Ручные Ñканеры никогда не знают о выÑоте " "изображениÑ. ВмеÑто Ñтого они возвращают выÑоту, равную -1. УÑтановка " "Ñтого параметра позволÑет протеÑтировать, будет ли графичеÑÐºÐ°Ñ Ð¾Ð±Ð¾Ð»Ð¾Ñ‡ÐºÐ° " "обрабатывать Ñто корректно. Этот параметр также включает фикÑированную " "ширину 11 Ñм." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ‚Ñ€Ñ‘Ñ…Ð¿Ñ€Ð¾Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ режима" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Ð˜Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸Ñ Ñ‚Ñ€Ñ‘Ñ…Ð¿Ñ€Ð¾Ñ…Ð¾Ð´Ð½Ð¾Ð³Ð¾ Ñканера. Ð’ цветном режиме будет передано три " "кадра." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "УÑтановить порÑдок кадров" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "УÑтанавливает порÑдок кадров в трёхпроходном цветном режиме." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Специальные параметры" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Выберите теÑтовое изображение" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Выберите вид теÑтовой картинки. ДоÑтупные параметры:\n" "Сплошной чёрный: вÑÑ Ð¾Ð±Ð»Ð°Ñть ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð° чёрным.\n" "Сполной белый: вÑÑ Ð¾Ð±Ð»Ð°Ñть ÑÐºÐ°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð° белым.\n" "Цветной шаблон: риÑует теÑтовые шаблоны различными цветами, в " "завиÑимоÑти от режима.\n" "Сетка: риÑует чёрно-белую Ñетку Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð¾Ð¼ каждого квадрата 10 на 10 мм." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Инвертировать порÑдок байт" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Предел чтениÑ" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Ограничить количеÑтво данных, передаваемых при каждом вызове sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Размер предела чтениÑ" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "МакÑимальное количеÑтво данных, передаваемых при каждом вызове " "sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Задержка при чтении" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Задержка передачи данных в канал." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "ДлительноÑть задержки при чтении" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "Как долго ожидать поÑле передачи каждого буфера данных через канал." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Возвращаемое значение sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Потери точек на линию" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "КоличеÑтво точек, которые потерÑны в конце каждой линии." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Ðечёткие параметры" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "ИÑпользовать неблокирующий ввод-вывод" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "ИÑпользовать неблокируемый ввод-вывод Ð´Ð»Ñ sane_read(), еÑли таковой " "поддерживаетÑÑ Ð³Ñ€Ð°Ñ„Ð¸Ñ‡ÐµÑкой оболочкой." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Включить теÑтовые параметры" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Включить различные теÑтовые параметры. ПрименÑетÑÑ Ð´Ð»Ñ Ñ‚ÐµÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ " "ÑпоÑобноÑти графичеÑких оболочек проÑматривать и изменÑть различные типы " "параметров SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Ðапечатать параметры" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Ðапечатать ÑпиÑок вÑех параметров." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Двочные теÑтовые параметры" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "ЦелочиÑленные теÑтовые параметры" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "ДробночиÑленные теÑтовые параметры" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "ТеÑтовые параметры Ð´Ð»Ñ Ñтрок" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "" #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "ТеÑтовые параметры Ð´Ð»Ñ ÐºÐ½Ð¾Ð¿Ð¾Ðº" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Кнопка" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "" #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Цветное 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "ИÑпользовать компоновку изображений" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Только чёрный и только белый (штриховой режим)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Полутоновый чёрно-белый (полутоновый режим)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Многоуровневый чёрно-белый (режим оттенков Ñерого)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Многоуровневые цвета RGB (однопроходной цвет)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Игнорировать калибровку" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Выключить предварительный фокуÑ" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Ðе калибровать фокуÑ" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Ð ÑƒÑ‡Ð½Ð°Ñ Ð¿Ñ€ÐµÐ´Ð²Ð°Ñ€Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ñ„Ð¾ÐºÑƒÑировка" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "ЗафикÑировать позицию фокуÑа" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Держать позицию фокуÑа на 0мм" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "ИÑпользовать Ñ„Ð¾ÐºÑƒÑ 0мм вмеÑто 0.6мм" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Режим калибровки" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Задать режим калибровки" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Включить/выключить лампу" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "включить UTA" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Включить/выключить UTA" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Смещение" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "ÐаÑтройки ÑÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ñ†Ð²ÐµÑ‚Ð¾Ð²Ñ‹Ñ… каналов" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Смещение Ñерого" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "УÑтанавливает Ñмещение канала Ñерого" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "УÑтанавливает Ñмещение канала краÑного" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "УÑтанавливает Ñмещение канала зелёного" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "УÑтанавливает Ñмещение канала Ñинего" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Режим предварительного проÑмотра" #~ msgid "Grayscale" #~ msgstr "Чёрно-белый" #~ msgid "Binary" #~ msgstr "Одноцветный" #, fuzzy #~ msgid "Display a shortened resolution list" #~ msgstr "Показывать короткий ÑпиÑок разрешений" #~ msgid "Black & White" #~ msgstr "Чёрный и белый" sane-backends-1.0.27/po/fi.po0000664000175000017500000044316313110600537012605 00000000000000# Finnish translation for SANE backend options # Copyright (C) 2003 SANE Project. # Harri Järvi, harri.jarvi@tut.fi, 2004. # -*-mode: po; coding: utf-8;-*- msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.11\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-12-17 23:00+0100\n" "Last-Translator: Harri Järvi \n" "Language-Team: Debian l10n Finnish \n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Asetusten määrä" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometria" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Parannus" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Lisäasetukset" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Esikatselu" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Pakota yksiväriset esikatselut" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bittisyvyys" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Lukutapa" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Kuvanlukunopeus" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Lähde" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Käytä jäljitystä" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Vasen yläkulma x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Vasen yläkulma y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Oikea alakulma x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Oikea alakulma y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Kuvanluvun tarkkuus" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-tarkkuus" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-tarkkuus" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, fuzzy, no-c-format msgid "Page height" msgstr "Korostus" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Käytä omaa gammataulukkoa" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Kuvan voimakkuus" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Punaisen voimakkuus" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Vihreän voimakkuus" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Sinisen voimakkuus" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Kirkkaus" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontrasti" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Hiukkaskoko" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Rasterointi" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Mustataso" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Valkotaso" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Punaisen valkotaso" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Vihreän valkotaso" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Sinisen valkotaso" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Varjo" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Punaisen varjo" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Vihreän varjo" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Sinisen varjo" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Korostus" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Punaisen korostus" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Vihreän korostus" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Sinisen korostus" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Sävy" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Kylläisyys" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Tiedostonimi" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Rasterikuvion koko" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Rasterikuvio" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Sido X- ja Y-tarkkuus" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negatiivi" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Laatukalibrointi" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Kaksinkertainen optinen tarkkuus" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Sido RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Kynnys" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analoginen gammakorjaus" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analoginen gamma (punainen)" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analoginen gamma (vihreä)" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analoginen gamma (sininen)" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Sido analoginen gamma" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Lämmitä lamppu" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Kal. valotusaika" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Kal. valotusaika punaiselle" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Kal. valotusaika vihreälle" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Kal. valotusaika siniselle" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Valotusaika" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Punaisen valotusaika" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Vihreän valotusaika" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Sinisen valotusaika" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Aseta valotusaika" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Kal. valomäärä" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Lampun valomäärä" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Aseta lampun valomäärä" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Valo pois lopetettaessa" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "Asetus, joka määrää kuinka monta asetusta tietty laite tukee." #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Lyhyt tarkkuuslista" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "Asetusten määrä" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Kuvanluvun tarkkuus" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Pyydä laadukas esikatselukuva." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Pyytää, että kaikki esikatselut tehdään yksivärisenä. " "Kolmivaihekuvanlukijalla tämä laskee vaiheiden määrän yhteen. " "Yksivaihekuvanlukijalla, se vähentää muistinkulutusta ja esikatselun " "lukuaikaa." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Bittien määrä näytettä kohden. Tyypillisiä arvoja ovat 1 " "viivapiirrokselle ja 8 monibittikuville." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Valitsee kuvanlukutavan (esim. viivapiirros, mustavalkoinen tai väri)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Määrää kuvanlukunopeuden." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Määrää kuvanlukulähteen (kuten dokumentin syöttäjän)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Määrää käytetäänkö jäljitystä." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Kuva-alueen vasemman yläkulman x-koordinaatti." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Kuva-alueen vasemman yläkulman y-koordinaatti." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Kuva-alueen oikean alakulman x-koordinaatti." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Kuva-alueen oikean alakulman y-koordinaatti." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Asettaa luettavan kuvan tarkkuus." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Asettaa luettavan kuvan vaakatarkkuuden." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Asettaa luettavan kuvan pystytarkkuuden." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, fuzzy, no-c-format msgid "Specifies the height of the media." msgstr "Asettaa luettavan kuvan tarkkuus." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Päättää käytetäänkö sisäänrakennettua vai käyttäjän asettamaa " "gammataulukkoa." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Gamma-korjaustaulukko. Väritilassa tämä asetus vaikuttaa yhtä paljon " "punaiseen, vihreään ja siniseen kanavaan yhtä aikaa. Se on siis " "intensiteettigamma-taulukko." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Gamma-korjaustaulukko punaiselle kaistalle." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Gamma-korjaustaulukko vihreälle kaistalle." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Gamma-korjaus taulukko siniselle kaistalle." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Asettaa luettavan kuvan kirkkauden" #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Asettaa luettavan kuvan kontrastin." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Asettaa kuvien \"rakeisuuden\". Pienemmät arvot tuottavat terävämpiä " "kuvia." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Määrää, rasteroidaanko kuva." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Asettaa kirkkaustason, joka tulkitaan \"mustaksi\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Asettaa kirkkaustason, joka tulkitaan \"valkoiseksi\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "Asettaa punaisen kirkkaustason, joka tulkitaan \"valkoiseksi\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "Asettaa vihreän kirkkaustason, joka tulkitaan \"valkoiseksi\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "Asettaa sinisen kirkkaustason, joka tulkitaan \"valkoiseksi\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "Asettaa punaisen kirkkaustason, joka tulkitaan \"mustaksi\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "Asettaa vihreän kirkkaustason, joka tulkitaan \"mustaksi\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "Asettaa sinisen kirkkaustason, joka tulkitaan \"mustaksi\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Asettaa punaisen kirkkaustason, joka tulkitaan \"täysin punaiseksi\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Asettaa vihreän kirkkaustason, joka tulkitaan \"täysin vihreäksi\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Asettaa sinisen kirkkaustason, joka tulkitaan \"täysin siniseksi\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Määrää kuvan \"sävyä\" (sinistasoa)." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Kylläisyystaso vaikuttaa \"puhkipalamiseen\" kameralla kuvattaessa. " "Suuremmat arvot aiheuttavat enemmän puhkipalamista." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Ladattavan kuvan tiedostonimi." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "Asettaa rasterikuvion koon rasterikuvia luettaessa." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "Asettaa rasterikuvion koon rasterikuvia luettaessa." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Käytä samoja arvoja X- ja Y-tarkkuudelle" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Vaihda musta ja valkoinen keskenään" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Tee tarkka valkokalibrointi" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Käytä linssiä joka tuplaa optisen tarkkuuden" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "RGB-tilassa käytä samoja arvoja joka värille" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Valitse valkoisen pisteen pienin kirkkaus" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analoginen gamma-korjaus" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analgoinen gamma-korjaus punaiselle" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analoginen gamma-korjaus vihreälle" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analoginen gamma-korjaus siniselle" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Lämmitä lamppu ennen kuvanlukua" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Aseta valotusaika kalibroinnille" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Aseta valotusaika punaisen kalibroinnille" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Aseta valotusaika vihreän kalibroinnille" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Aseta valotusaika sinisen kalibroinnille" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Aseta valotusaika kuvanluvulle" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Aseta valotusaika punaiselle kuvanluvulle" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Aseta valotusaika vihreälle kuvanluvulle" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Aseta valotusaika siniselle kuvanluvulle" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Valotusajan asettaminen" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Määritä valomäärä kalibrointia varten" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Määritä valomäärä kuvanlukua varten" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Valomäärän valinta" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Sammuttaa valon ohjelmasta poistuttaessa" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Kuvanluvun tarkkuus" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "Odota painiketta" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "Odota painiketta" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "Odota painiketta" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Värikuvio" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Väri" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Väriviivapiirros" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Värirasteri" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Harmaasävy" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Rasteri" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Viivapiirros" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, fuzzy, no-c-format msgid "Operation not supported" msgstr "Rasterointi ei ole tuettu" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "Asiakirjan syöttäjä" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "Asiakirjan syöttäjä" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Oletukset" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Aseta oletusasetukset parantimille." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibrointi" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Kalibroi ennen seuraavaa kuvanlukua" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Jos asetus on päällä, laite kalibroidaan ennen seuraavaa kuvanlukua. " "Muuten kalibrointi suoritetaan vain ensimmäisellä kerralla." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Vain sävykorjaus" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Jos asetus on päällä, kalibroinnissa suoritetaan vain sävykorjaus. " "Oletusasetukset vahvistukselle, siirtymälle ja valotusajalle, joko " "asetustiedostosta tai ohjelman sisäänrakennetuista asetuksista." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Painikkeen tila" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Luettavan kehyksen numero" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Valitsee luettavan kehyksen numeron" #: backend/avision.h:782 #, fuzzy, no-c-format msgid "Duplex scan" msgstr "Kaksipuolinen" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Kalibroi kuvanlukija" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Pakottaa kalibroinnin ennen kuvanlukua." #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Harmaasävy" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Lue harmaasävykuva värikuvan sijaan" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analoginen vahvistus" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Kasvattaa tai vähentää analogista vahvistusta CCD-kennossa." #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gamma-korjaus" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Valitsee gamma-korjauskäyrän" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, fuzzy, no-c-format msgid "No transparency correction" msgstr "Värikorjaus" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, fuzzy, no-c-format msgid "Negatives" msgstr "Negatiivi" #: backend/canon.c:176 #, fuzzy, no-c-format msgid "Slides" msgstr "Dia" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automaattinen" #: backend/canon.c:186 #, fuzzy, no-c-format msgid "Normal speed" msgstr "Normaali" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/2 normal speed" msgstr "2x2 normaali" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/3 normal speed" msgstr "3x3 normaali" #: backend/canon.c:365 #, fuzzy, no-c-format msgid "rounded parameter" msgstr "Epämääräiset parametrit" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "" #: backend/canon.c:378 #, fuzzy, no-c-format msgid "ADF jam" msgstr "ADF" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, fuzzy, no-c-format msgid "lamp failure" msgstr "Gamma" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, fuzzy, no-c-format msgid "transparency unit lamp failure" msgstr "Läpinäkyvyysyksikkö" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, fuzzy, no-c-format msgid "transparency unit shading error" msgstr "Läpinäkyvyysyksikkö" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, fuzzy, no-c-format msgid "film scanner" msgstr "Tasokuvanlukija" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "Tasokuvanlukija" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Filmin tyyppi" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, fuzzy, no-c-format msgid "Negative film type" msgstr "Negatiivifilmi" #: backend/canon.c:1197 #, fuzzy, no-c-format msgid "Selects the negative film type" msgstr "Valitse koekuva" #: backend/canon.c:1236 #, fuzzy, no-c-format msgid "Hardware resolution" msgstr "Kuvanluvun tarkkuus" #: backend/canon.c:1237 #, fuzzy, no-c-format msgid "Use only hardware resolutions" msgstr "Näyttää lyhyen tarkkuuslistan" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, fuzzy, no-c-format msgid "Auto focus" msgstr "Automaattinen poisto" #: backend/canon.c:1329 #, fuzzy, no-c-format msgid "Enable/disable auto focus" msgstr "Poista esitarkennus" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, fuzzy, no-c-format msgid "Manual focus position" msgstr "Korjaa tarkennuspiste" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Peilikuva" #: backend/canon.c:1539 #, fuzzy, no-c-format msgid "Mirror the image horizontally" msgstr "Peilaa kuvan vaakasuunnassa" #: backend/canon.c:1608 #, fuzzy, no-c-format msgid "Auto exposure" msgstr "Aseta valotusaika" #: backend/canon.c:1609 #, fuzzy, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Valotusajan asettaminen" #: backend/canon.c:1625 #, fuzzy, no-c-format msgid "Calibration now" msgstr "Kalibrointi" #: backend/canon.c:1626 #, fuzzy, no-c-format msgid "Execute calibration *now*" msgstr "Määrää kalibraatiotavan" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, fuzzy, no-c-format msgid "Reset scanner" msgstr "arkkisyöttöinen" #: backend/canon.c:1649 #, fuzzy, no-c-format msgid "Reset the scanner" msgstr "arkkisyöttöinen" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, fuzzy, no-c-format msgid "Eject film after each scan" msgstr "Poista kohde kuvanluvun jälkeen" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, fuzzy, no-c-format msgid "Document feeder extras" msgstr "Asiakirjan syöttäjä" #: backend/canon.c:1707 #, fuzzy, no-c-format msgid "Flatbed only" msgstr "Taso" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, fuzzy, no-c-format msgid "Transparency unit" msgstr "Läpinäkyvyysyksikkö" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, fuzzy, no-c-format msgid "Negative film" msgstr "Negatiivifilmi" #: backend/canon.c:1740 #, fuzzy, no-c-format msgid "Positive or negative film" msgstr "Positiivifilmi" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, fuzzy, no-c-format msgid "Transparency ratio" msgstr "Läpinäkyvyysyksikkö" #: backend/canon.c:1775 #, fuzzy, no-c-format msgid "Select film type" msgstr "Filmin tyyppi" #: backend/canon.c:1776 #, fuzzy, no-c-format msgid "Select the film type" msgstr "Valitsee rasterin" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Taso" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "ADF" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, fuzzy, no-c-format msgid "ADF Duplex" msgstr "Kaksipuolinen" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Tulosta" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Kaksipuolinen" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Punainen" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Vihreä" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Sininen" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Parannus" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Parannus" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Parannus" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Ei mikään" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Yksipuolinen" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Kaksipuolinen" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Läpinäkyvyysyksikkö" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automaattinen syöttö" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Positiivifilmi" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negatiivifilmi" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Kohdistus lasissa" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Kohdistus 2,5 mm lasin yläpuolella" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Rasteri A (Hard Tone)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Rasteri B (Soft Tone)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Rasteri C (Net Screen)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Rasteri A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Rasteri B (4x4 Spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Rasteri C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Rasteri D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Tekstin parannusmenetelmä" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Ladattu kuvio A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Ladattu kuvio B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Ei korjausta" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Käyttäjän määrittelemä" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Matriisikirjoittimet" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Lämpökirjoittimet" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Mustesuihkutulostimet" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Loisteputkinäytöt" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Oletus" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Korkeatarkkuuksinen tulostus" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Matalatarkkuuksinen tulostus" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Suuri kontrastinen tulostus" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Käyttäjän määrittelemä (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Käyttäjän määrittelemä (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 pysty" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 vaaka" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "US-Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Koko alue" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Lukutapa" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Valitsee rasterin" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Valitsee kirkkauden." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Terävyys" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Värikorjaus" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Valitsee värikorjaustaulukon valitulle tuloslaitteelle." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Värikorjauskertoimet" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matriisikerroin RGB:lle" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Vihreän siirtymä punaiseen" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Vihreän siirtymä siniseen" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Punaisen siirtymä virheään" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Punaisen siirtymä siniseen" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Sinisen siirtymä vihreään" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Sinisen siirtymä punaiseen" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Määrää vihreän määrän" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Lisää punaista vihreän määrän perusteella" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Lisää sinistä vihreän määrän perusteella" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Lisää vihreää punaisen määrän perusteella" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Määrää punaisen määrän" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Lisää sinistä punaisen määrän perusteella" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Lisää vihreää sinisen määrän perusteella" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Lisää punaista sinisen määrän perusteella" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Määrää sinisen määrän" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Peilaa kuvan." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Nopea esikatselu" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Automaattinen osittelu" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Lyhyt tarkkuuslista" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Näyttää lyhyen tarkkuuslistan" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Suurennus" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Määrää kuvanlukijan käyttämän zoom-kertoimen" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Nopea formaatti" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Lisävaruste" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Poista" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Poista kohde syöttölaitteesta" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Automaattinen poisto" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Poista kohde kuvanluvun jälkeen" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Syötttapa" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Valitsee syöttötavan (yksi-/kaksipuolinen)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Taso" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Valitsee kuvanluvun tasolta" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Valitsee gamma-korjauksen esiasetettujen laitteiden listalta tai " "käyttäjän määrämän taulukon, joka voidaan siirtää kuvanlukijaan" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Kohdistuspiste" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "Asettaa kohdistuspisteen joko lasiin tai 2,5 mm sen yläpuolelle" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Odota painiketta" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Kuvanlukukomennon lähettämisen jälkeen, odota kunnes kuvanlukijan " "painiketta todella painetaan, ennen kuvanluvun aloittamista." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, fuzzy, no-c-format msgid "Positive Slide" msgstr "Positiivifilmi" #: backend/epson2.c:137 #, fuzzy, no-c-format msgid "Negative Slide" msgstr "Negatiivifilmi" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Käyttäjän määrittelemä" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Päällä" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Poissa" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Rasteri" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Valkotaso" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Mustataso" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "Ehdollinen" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Vaaka" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Vaaka" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Vaaka" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Pysty" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Pysty" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Tulosta" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Rasteri" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Raakakalibrointi" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Kuvan korostus" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Kylläisyys" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "Aseta automaattinen kynnysarvon päättely viivapiirrosta varten." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Peilikuva" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Peilaa kuvan vaakasuunnassa" #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Sinisen valkotaso" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Määrää punaisen määrän" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Väriviivapiirros" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Pehmennys" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Gamma" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Kynnys" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Kynnys" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Kohinan poisto" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Ei korjausta" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Ei korjausta" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Syöttötapa" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Päivitä asetukset" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Ei korjausta" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Valo päälle" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Syöttötapa" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Valo pois" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Sinisen siirtymä" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Vihreän siirtymä" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Vihreän siirtymä" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Sinisen siirtymä" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Asettaa sinisen kanavan siirtymän" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Kaksipuolinen" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Päivitä asetukset" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Kohinan poisto" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Paperilta" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Paperilta" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Paperilta" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Paperilta" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Manuaalinen esitarkennus" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Manuaalinen esitarkennus" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "Kuvanluvun tarkkuus" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Valkotaso" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Punaisen voimakkuus" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Kaksipuolinen" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, fuzzy, no-c-format msgid "Extras" msgstr "Hyvin nopea" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, fuzzy, no-c-format msgid "Disable interpolation" msgstr "Poista peruutus." #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Väriviivapiirros" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibrointi" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Määrää kalibraatiotavan" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Kalibrointitila" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, fuzzy, no-c-format msgid "Lamp off time" msgstr "Valo pois" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Raakakalibrointi" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "Odota painiketta" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "Odota painiketta" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Odota painiketta" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Raakakalibrointi" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Pakottaa kalibroinnin ennen kuvanlukua." #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, fuzzy, no-c-format msgid "Buttons" msgstr "Painikkeen tila" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibroi" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Aloita kalibrointi." #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Raakakalibrointi" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Kalibrointitila" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Läpinäkyvyysyksikkö" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Debug-asetukset" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automaattinen lämmitys" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Lämmittää kunnes lampun kirkkaus tasaantuu. Muuten lämmitetään 60 " "sekuntia." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Koko alue" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Lukee koko alueen, mukaan lukien kalibrointinauha. Ole varovainen. Älä " "valitse täyttä korkeutta. Tämä asetus on vain testausta varten." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Raakakalibrointi" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Säädetään vahvistus ja siirtymä automaattisesti. Jos tämä asetus on " "poissa, voit asettaa analogia-asetukset manuaalisesti. Asetus on " "oletuksena päällä. Tämä asetus on vain testausta varten." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Raakakalibrointi vain ensimmäisellä kuvanluvulla" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Raakakalibrointi tehdään vain ensimmäisellä kuvanluvulla. Toimii " "useimpien kuvanlukijoiden kanssa ja voi säästää aikaa. Jos kuvien " "kirkkaus on eri joka kerralla, poista tämä asetus. Tämä asetus on " "testausta varten." #: backend/gt68xx.c:654 #, fuzzy, no-c-format msgid "Backtrack lines" msgstr "Käytä jäljitystä" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gamma" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Asettaa gamma-arvon kaikille kanaville." #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "Geometria" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, fuzzy, no-c-format msgid "Scan Mode Group" msgstr "Lukutapa" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Dia" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Lukutapa" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "Analoginen gammakorjaus" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "Gammakorjaus" #: backend/hp3900_sane.c:1451 #, fuzzy, no-c-format msgid "Disable white shading correction" msgstr "Vain sävykorjaus" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "Harmaasävy" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "arkkisyöttöinen" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Jätä kalibrointi huomiotta" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Tiedostonimi" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "arkkisyöttöinen" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "Lähde" #: backend/hp3900_sane.c:1584 #, fuzzy, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Valitsee luettavan kehyksen numeron" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Päivitä asetukset" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "" #: backend/hp5400_sane.c:358 #, fuzzy, no-c-format msgid "offset X" msgstr "Siirtymä" #: backend/hp5400_sane.c:359 #, fuzzy, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Kuva-alueen vasemman yläkulman x-koordinaatti." #: backend/hp5400_sane.c:368 #, fuzzy, no-c-format msgid "offset Y" msgstr "Siirtymä" #: backend/hp5400_sane.c:369 #, fuzzy, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Kuva-alueen vasemman yläkulman x-koordinaatti." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, fuzzy, no-c-format msgid "Switches the lamp on or off." msgstr "Asettaa valon päälle/pois" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, fuzzy, no-c-format msgid "TMA Slides" msgstr "Dia" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Negatiivi" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "Väri 48" #: backend/hp5590.c:95 #, fuzzy, no-c-format msgid "Extend lamp timeout" msgstr "Valo pois" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Odota painiketta" #: backend/hp5590.c:99 #, fuzzy, no-c-format msgid "Waits for button before scanning" msgstr "Lämmitä lamppu ennen kuvanlukua" #: backend/hp-option.c:2984 #, fuzzy, no-c-format msgid "Advanced Options" msgstr "Päivitä asetukset" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Raaka" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Hieno" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Oma" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automaattinen" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC-RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA-RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC-harmaa" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA-harmaa" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Hidas" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normaali" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Nopea" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Hyvin nopea" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2 pikseliä" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4 pikseliä" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8 pikseliä" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Tulosta" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Filmiliuska" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Ehdollinen" #: backend/hp-option.c:3414 #, fuzzy, no-c-format msgid "Experiment" msgstr "Valotusaika" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Terävöinti" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Aseta terävöintiarvo." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Automaatinen kynnys" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "Aseta automaattinen kynnysarvon päättely viivapiirrosta varten." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Valitse pehmennyssuodatin." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Poista media kuvanluvun jälkeen" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Poistaa median kuvanluvun jälkeen." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Vaihda kohde" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Vaihda kohde." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Poista" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Poista kohde." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Aloita kalibrointi." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Media" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Valitse media" #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Valotusaika" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Pidempi valotusaika antaa kuvanlukijan kerätä enemmän valoa. Ehdotetut " "arvot ovat 175% painotuotteille, 150% normaaleille dioille ja \"Negatiivi" "\" negatiivifilmeille. Tummille (alivalottuneille) kuville, voit " "kasvattaa tätä arvoa." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Värimatriisi" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Aseta kuvanlukijan värimatriisi." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Oma värimatriisi." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Yksivärinen matriisi" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Oma värimatriisi harmaasävy lukua varten." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Peilaa vaakasuunnassa" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Peilaa kuvan vaakasuunnassa" #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Peilaa pystysuunnassa" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Peilaa kuvan pystysuunnassa." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Päivitä asetukset" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Päivittää asetukset." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8-bittinen tulos" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Käyttää sisäisesti kahdeksaa bittiä syvempää esitystä, mutta antaa " "tuloksen vain kahdeksanbittisenä." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Odota painiketta" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" "Odottaa kuvanlukijan painikkeen painamista ennen kuvanluvun alkamista." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Sulje lamppu" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Sulkee kuvanlukijan lampun." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Paperin koko" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automaattinen osiointi" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 vaaka" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Manuaalinen esitarkennus" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Manuaalinen esitarkennus" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Kaksipuolinen kuvanluku" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Paperin koko syöttölaitteessa" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Rasteri" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Väri" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Ehdollinen" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Poissa" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Rasteri" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Rasteri" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normaali" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Korostus" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "Tasokuvanlukija" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Paperilta" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Oletus" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Pehmeä" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Hidas" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Keskitaso" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Punainen" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Vihreä" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Lähde" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Syöttötapa" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Asettaa syöttötavan" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Poista esitarkennus" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Poista esitarkennus" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Asettaa syöttötavan" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Asettaa syöttötavan" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automaattinen kynnys" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Asettaa automaattisesti kirkkauden, kontrastin, valkotasapainon, gamman, " "kohinan poiston ja korostuksen" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Kohinan poisto" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Vähentää yksittäistä pistekohinaa" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Kuvan korostus" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Asettaa kuvan korostuksen" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Valo päälle" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Asettaa valon päälle/pois" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Peilaa kuvan pystysuunnassa." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gammakorjaus" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Korkeatarkkuuksinen tulostus" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Matalatarkkuuksinen tulostus" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Ei korjausta" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normaali" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Parannus" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Automaattinen kynnys" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Automaattinen kynnys" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Aseta kehysten järjestys" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Sinisen varjo" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Punaisen siirtymä siniseen" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Timantti" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 raaka lihavointi" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 hieno lihavointi" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 pystyviiva" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Vahvistus" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Värikanavien vahvistus" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Harmaan vahvistus" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Asettaa harmaan kanavan vahvistusta" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Punaisen vahvistus" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Asettaa punaisen kanavan vahvistusta" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Vihreän vahvistus" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Asettaa vihreän kanavan vahvistusta" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Sinisen vahvistus" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Asettaa sinisen kanavan vahvistusta" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer-rasteri 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer-rasteri 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Taseteripiste 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Rasteripiste 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Tila 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Tila 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Tila 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Pehmeä" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Matala" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Keskitaso" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Korkea" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "Loisteputki" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Yksi sivu" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Kaikki sivut" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "arkkisyöttöinen" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Harmaasävy 4 bittiä" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Harmaasävy 8 bittiä" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Varjo, keskisävy, korostus, valotusaika" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Erikoisasetukset" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Väritasapaino" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Poista peruutus." #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Kuvanlukija ei peruuta." #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Kuvanlukijan valo päälle/pois" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Asettaa kuvanlukijan valon päälle/pois" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Ajuri kalibroi" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "Ajuri tekee värikalibroinnin." #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Käytä lightlid-35mm sovitinta" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Tämä asetus sulkee kuvanlukijan lampun kuvanluvun ajaksi" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Paras laatu" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Paras laatu, mutta hitain" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Nopea" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Nopea, mutta huonolaatuinen" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automaattinen kynnyksen asetus" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Jos valittu, ajuri yrittää automaattisesti selvittää parhaan kynnyksen." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Valitsee gammakorjaustilan." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Sido gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Käytä gamma-arvoja kaikille värikanaville." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Asettaa arvon gammakorjaukselle." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Gamma punainen" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Asettaa arvon gammakorjaukselle (punainen kanava)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Gamma vihreä" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Asettaa arvon gammakorjaukselle (vihreä kanava)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Gamma sininen" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Asettaa arvon gammakorjaukselle (sininen kanava)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Kanava" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "Valitsee värikaistan, \"Master\" tarkoittaa kaikkia värejä." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Keskisävy" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Asettaa kirkkaustason, joka tulkitaan \"50% vihreäksi\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Punaisen keskisävy" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Asettaa kirkkaustason, joka tulkitaan \"50% punaiseksi\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Vihreän keskisävy" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Asettaa kirkkaustason, joka tulkitaan \"50% vihreäksi\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Sinisen keskisävy" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Asettaa kirkkaustason, joka tulkitaan \"50% siniseksi\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Punatasapaino" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Tasapainokerroin punaiselle. 100% tarkoittaa: ei korjausta." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Vihertasapaino" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Tasapainokerroin vihreälle. 100% tarkoittaa: ei korjausta." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Sinitasapaino" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Tasapainokerroin siniselle. 100% tarkoittaa: ei korjausta." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Firmware-tasapaino" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Asettaa väritasapainot Firmwaressa oleviin arvoihin." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Hitain" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Hitaampi" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Nopeampi" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Nopein" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 raaka" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normaali" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 hieno" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 tosi hieno" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normaali" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 raaka" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 hieno" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 raaka" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normaali" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 hieno" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normaali" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normaali" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 oma" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 oma" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 oma" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 oma" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 oma" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 oma" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Nopea harmaa" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Lue nopeassa harmaassa tilassa (huonompi laatu)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Kaikki esikatselut luetaan nopeimmalla tavalla (huonoimmalla laadulla). " "Tämä voi olla väritön matalatarkkuuksinen tila." #: backend/mustek.c:4341 #, fuzzy, no-c-format msgid "Lamp off time (minutes)" msgstr "Valo pois lopetettaessa" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "" #: backend/mustek.c:4353 #, fuzzy, no-c-format msgid "Turn lamp off" msgstr "Asettaa valon päälle/pois" #: backend/mustek.c:4354 #, fuzzy, no-c-format msgid "Turns the lamp off immediately." msgstr "Asettaa kuvanlukijan valon päälle/pois" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Punaisen kirkkaus" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Asettaa punaisen kanavan kirkkauden." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Vihreän kirkkaus" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Asettaa vihreän kanavan kirkkauden." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Sinisen kirkkaus" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Asettaa sinisen kanavan kirkkauden." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Punaisen kontrasti" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Asettaa punaisen kanavan kontrastin." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Vihreän kontrasti" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Asettaa vihreän kanavan kontrastin." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Sinisen kontrasti" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Asettaa sinisen kanavan kontrastin." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Väri 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Väri 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Harmaasävy 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Harmaasävy 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, fuzzy, no-c-format msgid "Positive" msgstr "Positiivifilmi" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Lämmittää kunnes lampun kirkkaus tasaantuu. Muuten lämmitetään 40 " "sekuntia." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Negatiivifilmi" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negatiivi" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, fuzzy, no-c-format msgid "Update button state" msgstr "Painikkeen tila" #: backend/pixma_sane_options.c:244 #, fuzzy, no-c-format msgid "Button 1" msgstr "Painikkeen tila" #: backend/pixma_sane_options.c:258 #, fuzzy, no-c-format msgid "Button 2" msgstr "Painikkeen tila" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Läpinäkyvyys" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "" #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Raakakalibrointi" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, fuzzy, no-c-format msgid "Calibration data cache" msgstr "Kalibrointitila" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "" #: backend/plustek.c:942 #, fuzzy, no-c-format msgid "Performs calibration" msgstr "Raakakalibrointi" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, fuzzy, no-c-format msgid "Warmup-time" msgstr "Lämmitä lamppu" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "" #: backend/plustek.c:987 #, fuzzy, no-c-format msgid "Lampoff-time" msgstr "Valo pois" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "" #: backend/plustek.c:995 #, fuzzy, no-c-format msgid "Analog frontend" msgstr "Analoginen gamma (punainen)" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Punaisen siirtymä" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, fuzzy, no-c-format msgid "Red lamp off" msgstr "Asettaa valon päälle/pois" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "" #: backend/plustek.c:1057 #, fuzzy, no-c-format msgid "Green lamp off" msgstr "Asettaa valon päälle/pois" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "" #: backend/plustek.c:1065 #, fuzzy, no-c-format msgid "Blue lamp off" msgstr "Asettaa valon päälle/pois" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Väri 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Rasteri 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Rasteri 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Satunnaista" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Lähteen valinta" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Kuvan parannus" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Harmaannuta" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Lataa kuva harmaasävykuvana." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Kolmivaihesimulaatio" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simuloi kolmivaiheskanneria palauttamalla kolme erillistä kehystä. Huvin " "vuoksi se palauttaa kehykset järjestyksessä: vihreä, sininen, punainen." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Käsikuvanlukijasimulaatio" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simuloi käsiskanneria. Käsiskannerit eivät yleensä tiedä kuvan kokoa " "etukäteen. Sen sijaan, ne palauttavat kuvan korkeudeksi -1. Tällä " "asetuksella voidaan kokeilla, selviääkö käyttöliittymä tästä oikein." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "Asettaa oletusarvot parantimille (kirkkaus ja kontrasti)" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Vain-luku kokeiluasetus" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Katsotaanko osaako käyttöliittymä käsitellä tämän oikein" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Gammataulukot" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Paluuarvosimulaatio" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Ei pakoteta paluuarvoa" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Ei pakoteta ajuria palauttamaan statuskoodia." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Palauta SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Pakota ajuri palauttamaan paluuarvo SANE_STATUS_EOF, kun sane_read() on " "kutsuttu." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Palauta SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Pakota ajuri palauttamaan paluuarvo SANE_STATUS_JAMMED, kun sane_read() " "on kutsuttu." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Palauta SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Pakota ajuri palauttamaan paluuarvo SANE_STATUS_NO_DOCS, kun sane_read() " "on kutsuttu." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Palauta SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Pakota ajuri palauttamaan paluuarvo SANE_STATUS_COVER_OPEN, kun " "sane_read() on kutsuttu." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Palauta SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Pakota ajuri palauttamaan paluuarvo SANE_STATUS_IO_ERROR, kun " "sane_read() on kutsuttu." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Palauta SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Pakota ajuri palauttamaan paluuarvo SANE_STATUS_NO_MEM, kun sane_read() " "on kutsuttu." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Palauta SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Pakota ajuri palauttamaan paluuarvo SANE_STATUS_ACCESS_DENIED, kun " "sane_read() on kutsuttu." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Valo päälle" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Laittaa kuvanlukijan valon päälle" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Valo pois" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Sammuttaa kuvanlukijan valon" #: backend/sm3840.c:760 #, fuzzy, no-c-format msgid "Lamp timeout" msgstr "Valo pois" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Asiakirjan syöttäjä" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (tuumaa)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (tuumaa)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (tuumaa)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Rasterointi ei ole tuettu" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "Hajapisteet 8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "Hajapisteet 16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "SCSI-pyynnöllä luettavien rivien määrä. Säätämällä tätä asetusta, " "voidaan vaikuttaa tiedon lukemisen nopeuteen kuvanlukijalta. Jos tämä " "asetetaan liian matalaksi, kuvanlukija voi joutua välillä pysähtymään " "kesken luvun. Jos se asetetaan liian suureksi, X-pohjaiset " "käyttöliittymät voivat lakata vastaamasta X-tapahtumiin ja järjestelmä " "saattaa kaatua." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Poista kohde kuvanluvun jälkeen" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Esikatselutila" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Valitse esikatselutila. Harmaasävy antaa yleensä parhaan yhdistelmän " "nopeutta ja yksityiskohtia" #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Esimääritetyt asetukset" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Tarjoaa vakioalueet valokuville ja tulostetuille sivuille ja vastaaville." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "Tasokuvanlukija" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Automaattinen poisto" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Kohdistuspiste" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Kohdistuspiste" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Väririvejä / luku" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Harmaasävyrivejä / luku" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Väri RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Väri RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Väri RGB TEKSTI" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Täysi musta" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Täysi valkoinen" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Värikuvio" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Ruudukko" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Ensimmäinen" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Toinen" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Tämä on erittäin pitkä kolmas rivi. Ehkä käyttöliittymä keksii miten se " "näytetään" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Käsikuvanlukijasimulaatio" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simuloi käsikuvnalukijaa. Käsikuvanlukijat eivät tiedä kuvan korkeutta " "etukäteen. Sen sijaan, ne palauttavat korkeuden -1. Tämä asetus " "mahdollistaa osaako ohjelma käsitellä tätä tilannetta. Tämä asetus " "asettaa kuvan leveydeksi 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Kolmivaihesimulaatio" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simuloi kolmivaihekuvanlukijaa. Väritilassa, kolme kehystä lähetetään." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Aseta kehysten järjestys" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Asettaa kehysten järjestyksen kolmivaihetilassa." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Erikoisasetukset" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Valitse koekuva" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Valitse testikuva. Vaihtoehtoina ovat:\n" "Täysi musta: täyttää koko kuvan mustalla.\n" "Täysi valkoinen: täyttää koko kuvan valkoisella.\n" "Värikuvio: piirtää erilaisia värikuvioita tilasta riippuen.\n" "Ruudukko: piirtää mustavalkoruudukon 10 mm ruuduilla." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Käännä tavujärjestys" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Käännä ylemmän ja alemman tavun järjestys 16-bittisessä tilassa. Tällä " "toiminnolla voidaan kokeilla 16-bittisiä tiloja käyttöliittymissä, esim. " "käyttääkö käyttöliittymä oikeaa tavujärjestystä." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Lukuraja" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Rajoittaa tiedon määrää, joka voidaan lukea yhdellä sane_read()-kutsulla." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Lukurajan koko" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "Suurin tiedon määrä, joka välitetään yhdellä sane_read()-kutsulla." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Lukuviive" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Viivästää tiedon siirtoa." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Lukuviiveen kesto" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "Kuinka kauan odotetaan jokaisen lähetetyn puskurin jälkeen." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "sane_read() paluuarvo" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Valitse sane_read()-kutsun paluuarvo. \"Oletus\" on tavallinen " "kuvanluvun käsittely. Kaikki muut paluuarvot ovat käyttöliittymän " "testaamista varten." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Kadonneita pikseleitä / rivi" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Rivin lopusta puuttuvien pikselien määrä." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Epämääräiset parametrit" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Palauttaa epämääräisiä rivejä ja tavuja, kun sane_parameters() kutsutaan " "ennen sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Käytä non-blocking IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "sane_read käyttää non-blocking IO:ta." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Tarjoa select file descriptor" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Tarjoaa select file descriptorin, jolla voidaan tarkistaa palauttaisiko " "sane_read() dataa." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Kokeiluasetukset päälle" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Asettaa päälle useita kokeiluasetuksia. Asetuksilla voidaan tarkistaa " "käyttöliittymän kyky näyttää ja muokata kaikenlaisia SANE-asetuksia." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Tulostusasetukset" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Tulosta lista kaikista asetuksista" #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Boolen kokeiluasetukset" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Boolen pehmovalinta pehmotunnistus" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Boolen kokeiluasetus, jolla on pehmovalinta- ja pehmotunnistus- " "ominaisuuksia. Se on vain tavallinen boolen asetus." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Boolen kovavalinta pehmotunnistus" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(3/6) Boolen kokeiluasetus, jolla on kovavalinta ja pehmotunnistus. Tämä " "tarkoittaa, että käyttöliittymä ei voi itse muttaa asetusta, mutta " "käyttäjä voi (esim. painamalla painiketta laitteessa)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Boolen kovavalinta" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Boolen kokeiluasetus, jolla on kovavalinta. Tämä tarkoittaa, että " "käyttöliittymä ei voi itse muuttaa asetusta, mutta käyttäjä voi (esim. " "painamalla painiketta laitteessa), eikä käyttöliittymä voi lukea " "asetusta." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Boolen pehmotunnistus" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Boolen kokeiluasetus, jolla on pehmotunnistus. Se tarkoittaa, että " "asetus voidaan vain lukea." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Boolen pehmovalinta ja pehmotunnistus emuloita" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Boolen kokeiluasetus, jolla on pehmovalinta, pehmotunnistus ja " "emulointi." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Boolen pehmovalinta pehmotunnistus auto" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Boolen kokeiluasetus, jolla on pehmovalinta, pehmotunnitus ja " "automaattiominaisuudet. Ajuri voi säätää tätä asetusta automaattisesti." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Kokonaislukukokeiluasetukset" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Kokonaisluku" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Kokonaisluku ilman yksikköä ja rajoituksia." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Kokonaisluku aluerajoituksella" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Koknaisluku pikseli-yksiköllä ja aluerajoituksella. Minimi on 4, " "maksimi 192, ja askel on 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Kokonaisluku sanalistalla" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "(3/6) Kokonaisluku bitti-yksiköllä ja sanalistarajoituksella." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Kokonaislukutaulukko" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Kokonaisluku mm-yksiköllä käyttäen taulukkoa ilman rajoituksia." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Kokonaislukutaulukko aluerajoituksella" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Kokonaisluku dpi-yksiköllä ja taulukolla aluerajoituksella. Minimi " "on 4, maksimi 192, ja askel on 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Kokonaislukutaulukko sanalistalla" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Kokonaisluku prosenttiyksiköllä ja taulukolla " "sanalistarajoituksella." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Murtolukukokeiluasetukset" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Murtoluku" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) Murtoluku kokeiluasetus ilman yksikköä ja rajoituksia." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Murtoluku aluerajoituksella" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Murtoluku kokeiluasetus mikrosekunti-yksiköllä ja " "aluerajoituksella. Minimi on -42,17, maksimi 32767,9999, ja askel on 2,0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Murtoluku rajoituksella ja sanalistalla" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Murtolukukokeiluasetus ilman yksikköä, rajoituksella ja " "sanalistalla." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Merkkijonokokeiluasetukset" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) Merkkijono" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Merkkijono ilman rajoituksia." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) Merkkijono sanalistalla" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) Merkkijono sanalistarajoituksella" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) Merkkijono pitkällä sanalistalla" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "(3/3) Merkkijono sanalistalla. Sanalista sisältää enemmän sanoja." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Painikekokeiluasetukset" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Painike" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Painike. Tulostaa tekstiä." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Väri 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Käytä kuvanasettelua" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Kaksitasoinen mustavalko (viivapiirros)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Rasteroitu mustavalko" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Harmaasävy" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Monitaso RGB-väri (yksivaihe)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Jätä kalibrointi huomiotta" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Poista esitarkennus" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Ei kalibroida tarkennusta" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Manuaalinen esitarkennus" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Korjaa tarkennuspiste" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Linssin tarkennus kohteeseen" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Tarkentaa linssin tarkennuksen kohteeseen" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Pidikkeen tarkennuspiste 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Käytä 0mm pidikkeen tarkennuspisteenä 0,6mm sijaan" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Kalibrointitila" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Määrää kalibraatiotavan" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Asettaa valon päälle/pois" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA päällä" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Asettaa UTAN päälle/pois" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Siirtymä" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Värikanavien siirtymä" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Harmaan siirtymä" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Asettaa harmaan kanavan siirtymän" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Asettaa punaisen kanavan siirtymän" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Asettaa vihreän kanavan siirtymän" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Asettaa sinisen kanavan siirtymän" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Esikatselutila" #~ msgid "Grayscale" #~ msgstr "Harmaasävy" #~ msgid "Binary" #~ msgstr "Binaari" #, fuzzy #~ msgid "Display a shortened resolution list" #~ msgstr "Näyttää lyhyen tarkkuuslistan" #~ msgid "Black & White" #~ msgstr "Mustavalko" sane-backends-1.0.27/po/pt.po0000664000175000017500000041004613110600537012624 00000000000000# Translation file for SANE backends. # Copyright (C) 2003 Pedro Morais. # msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.10\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-05-08 13:31+0200\n" "Last-Translator: Pedro Morais \n" "Language-Team: pt \n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Número de opções" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometria" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Melhorias" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Previsão" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Modo de digitalização" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Velocidade de digitalização" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Origem da digitalização" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Superior-esquerda x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Superior-esquerda y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Inferior-direita x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Inferior-direita y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Resolução digitalização" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-Resolução" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-Resolução" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Largura página" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Altura página" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Usar tabela customizada gamma" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Intensidade da imagem" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Intensidade do vermelho" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Intensidade do verde" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Intensidade do azul" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Brilho" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contraste" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Tamanho do grão" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Simulação de cinza" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Nível de preto" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Nível de branco" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Nível de branco para vermelho" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Nível de branco para verde" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Nível de branco para azul" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Sombra" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Sombra para vermelho" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Sombra para verde" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Sombra para azul" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Clarear" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Natural-Hue" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturação" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Nome do ficheiro" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Tamanho padrão ponto - simulação cinza" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Simulação cinza padrão" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Vincular resoluções X e Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativo" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Calibração de qualidade" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Resolução ótica dupla" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Vincular RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Valor do pixel-Threshold" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Correção analógica do gama" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Gama analógico vermelho" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Gama analógico verde" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Gama analógico azul" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Vincular gama analógico" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Aquecimento da lâmpada" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Tempo de exposição Cal." #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Tempo de exposição Cal. para Vermelho" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Tempo de exposição Cal. para Verde" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Tempo de exposição Cal. para azul" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Tempo de exposição digitalização" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Tempo de exposição digitalização para Vermelho" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Tempo de exposição digitalização para Verde" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Tempo de exposição digitalização para Azul" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Definir tempo de exposição" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Densidade lâmpada Cal." #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Densidade luz de digitalização" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Definir densidade da luz" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Desligar lâmpada na saída" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Opções de Fonte, Modo e Resolução" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Opções de digitalização de área e mídia" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "Opções para alteração de imagens" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Opções específicas de hardware" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "ensores e botôes do scanner" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Solicitar pré-visualização com qualidade da digitalização" #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Selecionar Modo de digitalização ex. monocromático, colorido, ..." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Determina em qual velocidade digitaliza" #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Seleciona fonte para digitalização (ex. ADF)" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "ontrola se o backtracking é forçado" #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Posição de área de digitalização Superior-esquerda x" #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Posição de área de digitalização Superior-esquerda y " #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Posição de área de digitalização Inferior-direita x" #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Posição de área de digitalização Inferior-direita y" #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "efine resolução de saída" #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Define resolução horizontal de saída " #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Define resolução horizontal de saída" #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Especifica a altura da mídia" #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Determine se um builtin ou tabela customizada gama deve ser utilizada" #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Tabela correção Gama para banda vermelha" #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Tabela correção Gama para banda verde" #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Tabela correção Gama para banda azul" #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Controla o brilho da imagem adquirida." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Controla o contraste da imagem adquirida." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Defina se a imagem inserida deve ser simulada em cinza (halftone-" "dithered)" #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "" #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "" #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Usar lentes que duplicam a resolução ótica" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Em modo RGB usar os mesmos valores para cada cor" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Selecionar brilho mínimo para obter ponto branco" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Correção analógica gama" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Correção analógica gama para Vermelho" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Correção analógica gama para Verde" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Correção analógica gama para Azul" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Aquecer lâmpada antes de digitalizar" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Definir tempo de exposição para calibração" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Definir tempo de exposição para calibração do vermelho" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Definir tempo de exposição para calibração do verde" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Definir tempo de exposição para calibração do azul" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Definir tempo de exposição para digitalização" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Definir tempo de exposição para digitalização do vermelho" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Origem da digitalização" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Linhas em cor" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Cor" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Linhas em cor" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Cinzento" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Linhas" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Predefinições" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "" #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Calibração" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Estado do botão" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "" #: backend/avision.h:782 #, fuzzy, no-c-format msgid "Duplex scan" msgstr "Digitalização completa" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" #: backend/canon630u.c:159 #, fuzzy, no-c-format msgid "Calibrate Scanner" msgstr "Calibração" #: backend/canon630u.c:160 #, fuzzy, no-c-format msgid "Force scanner calibration before scan" msgstr "Calibração rudimentar apenas na primeira digitalização" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Ganho analógico" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Correcção do gamma" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, fuzzy, no-c-format msgid "No transparency correction" msgstr "Correcção do gamma" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, fuzzy, no-c-format msgid "Negatives" msgstr "Negativo" #: backend/canon.c:176 #, fuzzy, no-c-format msgid "Slides" msgstr "Mais lento" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automático" #: backend/canon.c:186 #, fuzzy, no-c-format msgid "Normal speed" msgstr "Normal" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, fuzzy, no-c-format msgid "lamp failure" msgstr "Valor de 'gamma'" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, fuzzy, no-c-format msgid "transparency unit lamp failure" msgstr "Unidade de Transparências" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, fuzzy, no-c-format msgid "transparency unit shading error" msgstr "Unidade de Transparências" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, fuzzy, no-c-format msgid "Negative film type" msgstr "Filme Negativo" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "" #: backend/canon.c:1625 #, fuzzy, no-c-format msgid "Calibration now" msgstr "Calibração" #: backend/canon.c:1626 #, fuzzy, no-c-format msgid "Execute calibration *now*" msgstr "Definine o modo de calibração" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, fuzzy, no-c-format msgid "Reset scanner" msgstr "Digitalização rápida" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "" #: backend/canon.c:1707 #, fuzzy, no-c-format msgid "Flatbed only" msgstr "Flachbett" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, fuzzy, no-c-format msgid "Transparency unit" msgstr "Unidade de Transparências" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, fuzzy, no-c-format msgid "Negative film" msgstr "Filme Negativo" #: backend/canon.c:1740 #, fuzzy, no-c-format msgid "Positive or negative film" msgstr "Filme Positivo" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, fuzzy, no-c-format msgid "Transparency ratio" msgstr "Unidade de Transparências" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flachbett" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "" #: backend/canon_dr.c:412 #, no-c-format msgid "Card Front" msgstr "" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, no-c-format msgid "Card Duplex" msgstr "" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Vermelho" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Verde" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Azul" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Melhorias" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Melhorias" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Melhorias" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "Desconsiderar porcentagem branco" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, fuzzy, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" "Solicita ao driver para eliminar páginas com baixo número de pixels " "escuros" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Unidade de Transparências" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Filme Positivo" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Filme Negativo" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Sem Correcção" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Definido pelo utilizador" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Impressoras de agulhas" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Impressoras térmicas" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Impressoras de jacto de tinta" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Monitores CRT" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Predefinição" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Máximo" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Modo de Digitalização" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "" #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Deslocar vermelho para o verde" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "" #: backend/epson.c:3110 #, fuzzy, no-c-format msgid "Controls blue level" msgstr "Contraste do canal azul" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, fuzzy, no-c-format msgid "Positive Slide" msgstr "Filme Positivo" #: backend/epson2.c:137 #, fuzzy, no-c-format msgid "Negative Slide" msgstr "Filme Negativo" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Definido pelo utilizador" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Nível de branco" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Nível de preto" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, fuzzy, no-c-format msgid "Reverse image format" msgstr "Inverte imagem" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Simulação cinza padrão" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Calibração rudimentar" #: backend/fujitsu.c:3221 #, no-c-format msgid "Emphasis" msgstr "" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Saturação" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "" #: backend/fujitsu.c:3252 #, no-c-format msgid "Mirroring" msgstr "" #: backend/fujitsu.c:3253 #, no-c-format msgid "Reflect output image horizontally" msgstr "" #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Nível de branco para azul" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Contraste do canal azul" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Linhas em cor" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Valor de 'gamma'" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Limiar de aquecimento" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Valor do pixel-Threshold" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, no-c-format msgid "Noise removal" msgstr "" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Sem Correcção" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Sem Correcção" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, fuzzy, no-c-format msgid "Compression" msgstr "Compressão JPEG" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, fuzzy, no-c-format msgid "Enable double feed error due to skew" msgstr "Liga / Desliga Modo de detecção de alimentação" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, fuzzy, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "Liga / Desliga Modo de detecção de alimentação" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, fuzzy, no-c-format msgid "Enable double feed error due to paper length" msgstr "Liga / Desliga Modo de detecção de alimentação" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, no-c-format msgid "DF recovery mode" msgstr "" #: backend/fujitsu.c:3709 #, fuzzy, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "Solicita ao driver para remover digitalmente bordas das páginas" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Imprimir opções" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Sem Correcção" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Cor da lâmpada" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, no-c-format msgid "Buffer mode" msgstr "" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Lâmpada acesa" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Deslocamento do azul" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Deslocamento do verde" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Deslocamento do verde" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Deslocamento do azul" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Deslocamento do canal azul" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Digitalização completa" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, fuzzy, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "Solicita ao driver para rotacionar digitalmente páginas inclinadas" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "Alinhamento - Deskew" #: backend/fujitsu.c:4021 #, fuzzy, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "Solicita ao driver para rotacionar digitalmente páginas inclinadas" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "Diâmetro despeckle" #: backend/fujitsu.c:4034 #, fuzzy, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" "Diâmetro máximo de pontos isolados a serem removidos da digitalização" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, fuzzy, no-c-format msgid "Software crop" msgstr "Crop automático" #: backend/fujitsu.c:4054 #, fuzzy, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "Solicita ao driver para remover digitalmente bordas das páginas" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Imprimir opções" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Calibração rudimentar" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, no-c-format msgid "A3 paper" msgstr "" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, no-c-format msgid "B4 paper" msgstr "" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, no-c-format msgid "A4 paper" msgstr "" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, no-c-format msgid "B5 paper" msgstr "" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, fuzzy, no-c-format msgid "OMR or double feed detected" msgstr "Detecção de dupla alimentação" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Modo de Alimentação manual" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Modo de Alimentação manual" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, fuzzy, no-c-format msgid "Double feed" msgstr "Detecção de dupla alimentação" #: backend/fujitsu.c:4501 #, fuzzy, no-c-format msgid "Double feed detected" msgstr "Detecção de dupla alimentação" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, no-c-format msgid "Hardware error code" msgstr "" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Nível de branco" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Intensidade do vermelho" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Digitalização completa" #: backend/genesys.c:5761 #, fuzzy, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "Solicita ao driver para remover digitalmente bordas das páginas" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" "Solicita ao driver para eliminar páginas com baixo número de pixels " "escuros" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, fuzzy, no-c-format msgid "Software derotate" msgstr "Alinhamento - Deskew" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, fuzzy, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "Solicita ao driver para remover digitalmente bordas das páginas" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Linhas em cor" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Calibração" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Definine o modo de calibração" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Modo de calibração" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, fuzzy, no-c-format msgid "Lamp off time" msgstr "Lâmpada acesa" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Calibração rudimentar" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Origem da digitalização" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Calibração rudimentar" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Calibração rudimentar apenas na primeira digitalização" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, fuzzy, no-c-format msgid "Buttons" msgstr "Estado do botão" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, fuzzy, no-c-format msgid "Calibrate" msgstr "Calibração" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Calibração rudimentar" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Calibração rudimentar" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Modo de calibração" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Adaptador de Transparências" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Opções de Depuração" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Aquecimento automático" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Aquecer até o brilho da lâmpada ser constante em ver de insistir em 60 " "segundos de tempo de aquecimento." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Digitalização completa" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Digitalizar toda a área de digitalização, incluindo a faixa de " "calibração. Cuidado: não seleccione toda a altura. Apenas para testes." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Calibração rudimentar" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Configurar automaticamente o ganho e deslocamento de digitalização. Se " "estiver desactivada são fornecidas opções para configurar manualmente " "este parâmetro. Apenas para testes." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Calibração rudimentar apenas na primeira digitalização" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "A calibração rudimentar apenas é realizada na primeira digitalização. " "Funciona com quase todos os digitalizadores e pode poupar tempo. Se o " "briho da imagem é diferente em cada digitalização, desactive esta opção. " "Apenas para testes." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Valor de 'gamma'" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Define o valor de 'gamma' em todos os canais." #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "Geometria" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, fuzzy, no-c-format msgid "Scan Mode Group" msgstr "Modo de Digitalização" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Modo de digitalização" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "Correcção do gamma" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "Correcção do gamma" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "Cinzento" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "Digitalização rápida" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Ignorar a calibração" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Nome do ficheiro" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "Digitalização rápida" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "Origem da digitalização" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Imprimir opções" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "" #: backend/hp5400_sane.c:358 #, fuzzy, no-c-format msgid "offset X" msgstr "Deslocamento" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "" #: backend/hp5400_sane.c:368 #, fuzzy, no-c-format msgid "offset Y" msgstr "Deslocamento" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "" #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "" #: backend/hp5590.c:88 #, fuzzy, no-c-format msgid "TMA Slides" msgstr "Mais lento" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Negativo" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "Cor 48" #: backend/hp5590.c:95 #, fuzzy, no-c-format msgid "Extend lamp timeout" msgstr "Lâmpada acesa" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "" #: backend/hp-option.c:2984 #, fuzzy, no-c-format msgid "Advanced Options" msgstr "Imprimir opções" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "" #: backend/hp-option.c:3042 #, fuzzy, no-c-format msgid "Fine" msgstr "Nome do ficheiro" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automático" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC cinzento" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA cinzento" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Lento" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Rápido" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "" #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Limiar de aquecimento" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "" #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "" #: backend/hp-option.h:85 #, fuzzy, no-c-format msgid "Change document" msgstr "Melhorias" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "" #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "" #: backend/hp-option.h:98 #, fuzzy, no-c-format msgid "Start calibration process." msgstr "Calibração rudimentar" #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "" #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" #: backend/hp-option.h:119 backend/hp-option.h:126 #, fuzzy, no-c-format msgid "Color Matrix" msgstr "Linhas em cor" #: backend/hp-option.h:121 #, fuzzy, no-c-format msgid "Set the scanners color matrix." msgstr "Contraste do canal vermelho." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "" #: backend/hp-option.h:132 #, fuzzy, no-c-format msgid "Mono Color Matrix" msgstr "Linhas em cor" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "" #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "" #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "" #: backend/hp-option.h:150 #, fuzzy, no-c-format msgid "Update options" msgstr "Imprimir opções" #: backend/hp-option.h:151 #, fuzzy, no-c-format msgid "Update options." msgstr "Imprimir opções" #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "" #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Separação automática" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, no-c-format msgid "Landscape" msgstr "Paisagem" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "Inverte imagem" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "Modo de Papel Longo" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "Modo de Controle do Comprimento" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "Modo de Alimentação manual" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, no-c-format msgid "Manual feed timeout" msgstr "Tempo de desligamento da alimentação manual" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "Detecção de dupla alimentação" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "PB" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "" #: backend/kvs1025_opt.c:41 #, fuzzy, no-c-format msgid "gray" msgstr "Cinzento" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Cor" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, fuzzy, no-c-format msgid "single" msgstr "simples" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "contínuo" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "desliga" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "Aguarde_doc" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "Aguarde-Chave" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, fuzzy, no-c-format msgid "user_def" msgstr "Definido pelo utilizador" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "Cartão de visita" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "Verificar" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, no-c-format msgid "light" msgstr "claro" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "escuro" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "Digitalização rápida" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Predefinição" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "Suave" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "Nenhuma" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Lento" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, no-c-format msgid "medium" msgstr "Média" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "Alta" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, fuzzy, no-c-format msgid "linier" msgstr "Linhas" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Vermelho" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Verde" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, fuzzy, no-c-format msgid "blue" msgstr "Azul" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Origem da digitalização" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "Liga / Desliga Modo Papel Longo" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "Liga / Desliga Modo Controle do Comprimento" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, no-c-format msgid "Sets the manual feed mode" msgstr "Define modo de alimentação manual" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Define desligamento de alimentação manual em segundos" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "Liga / Desliga Modo de detecção de alimentação" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "Adequar à página" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "Adequar à página" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "Scanner diminui imagem para adequar à pagina digitalizada" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" "Define posição do papel: Verdadeiro para Paisagem, Falso para Retrato" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Limiar de aquecimento" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Cor da lâmpada" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Define cor da lâmpada (Color dropout)" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "Inverte imagem nos modos P/B ou simulação de cinza" #: backend/kvs1025_opt.c:840 #, no-c-format msgid "Mirror image (left/right flip)" msgstr "Imagem espelhada" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "Compressão JPEG" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "Compressão da imagem JPEG com parâmetro Q, '0' - sem compressão" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, fuzzy, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "Solicita ao driver para rotacionar digitalmente páginas inclinadas" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "Solicita ao driver para rotacionar digitalmente páginas inclinadas" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" "Diâmetro máximo de pontos isolados a serem removidos da digitalização" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "Crop automático" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "Solicita ao driver para remover digitalmente bordas das páginas" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Correcção do gamma" #: backend/kvs40xx_opt.c:117 #, fuzzy, no-c-format msgid "wait_doc_hopper_up" msgstr "Aguarde_doc" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, no-c-format msgid "High sensivity" msgstr "" #: backend/kvs40xx_opt.c:232 #, no-c-format msgid "Low sensivity" msgstr "" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Sem Correcção" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normal" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Melhorias" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, fuzzy, no-c-format msgid "Double feed detector sensitivity" msgstr "Detecção de dupla alimentação" #: backend/kvs40xx_opt.c:450 #, fuzzy, no-c-format msgid "Set the double feed detector sensitivity" msgstr "Detecção de dupla alimentação" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, fuzzy, no-c-format msgid "Do not stop after double feed detection" msgstr "Detecção de dupla alimentação" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Limiar de aquecimento" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Limiar de aquecimento" #: backend/kvs40xx_opt.c:694 #, fuzzy, no-c-format msgid "Inverse image in B/W mode" msgstr "Inverte imagem nos modos P/B ou simulação de cinza" #: backend/kvs40xx_opt.c:715 #, fuzzy, no-c-format msgid "JPEG compression" msgstr "Compressão JPEG" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Sombra para azul" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Sombra para azul" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamante" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Ganho" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Ganho do cinzento" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Ganho do canal cinzento" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Ganho do vermelho" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Ganho do canal vermelho" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Ganho do verde" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Ganho do canal verde" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Ganho do azul" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Ganho do canal azul" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Modo 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Modo 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Modo 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Uma página" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Todas as páginas" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Esta opção desligar a lâmpada durante a digitalização" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Digitalização de qualidade" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Digitalização rápida" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "" #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "" #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "" #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "" #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Mais lento" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Lento" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Rápido" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Mais rápido" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "" #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "" #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Brilho do vermelho" #: backend/mustek.c:4432 #, fuzzy, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Deslocamento (brilho) do canal vermelho." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Brilho do verde" #: backend/mustek.c:4445 #, fuzzy, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Deslocamento (brilho) do canal vermelho." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Brilho do azul" #: backend/mustek.c:4458 #, fuzzy, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Deslocamento (brilho) do canal azul." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contraste do canal vermelho" #: backend/mustek.c:4484 #, fuzzy, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Ganho (contraste) do canal vermelho." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contraste do canal verde" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "" #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contraste do canal azul" #: backend/mustek.c:4510 #, fuzzy, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Ganho (contraste) do canal azul." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Cor 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Cor 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Cinzento 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Cinzento 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, fuzzy, no-c-format msgid "Positive" msgstr "Filme Positivo" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Aquecer até o brilho da lâmpada ser constante em ver de insistir em 40 " "segundos de tempo de aquecimento." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Filme Negativo" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negativo" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, fuzzy, no-c-format msgid "Update button state" msgstr "Estado do botão" #: backend/pixma_sane_options.c:244 #, fuzzy, no-c-format msgid "Button 1" msgstr "Estado do botão" #: backend/pixma_sane_options.c:258 #, fuzzy, no-c-format msgid "Button 2" msgstr "Estado do botão" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Transparência" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "" #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Calibração rudimentar" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, fuzzy, no-c-format msgid "Calibration data cache" msgstr "Modo de calibração" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "" #: backend/plustek.c:942 #, fuzzy, no-c-format msgid "Performs calibration" msgstr "Calibração rudimentar" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "" #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "" #: backend/plustek.c:995 #, fuzzy, no-c-format msgid "Analog frontend" msgstr "Ganho analógico" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Deslocamento do vermelho" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Cor 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Melhorias de Imagem" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Acinzentar" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "" #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lâmpada acesa" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "" #: backend/sm3840.c:760 #, fuzzy, no-c-format msgid "Lamp timeout" msgstr "Lâmpada acesa" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (pol)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (pol)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (pol)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Aquecer lâmpada antes de digitalizar" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "Digitalização rápida" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, no-c-format msgid "Auto or manual focus" msgstr "" #: backend/snapscan-options.c:911 #, no-c-format msgid "Focus-point" msgstr "" #: backend/snapscan-options.c:912 #, no-c-format msgid "Focus point" msgstr "" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Cor RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Cor RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Cor RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "" #: backend/test.c:138 #, fuzzy, no-c-format msgid "Color pattern" msgstr "Linhas em cor" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Grelha" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Primeira entrada" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Segunda entrada" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "" #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Opções Especiais" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "" #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "" #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Imprimir opções" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Imprime uma lista de todas as opções." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "" #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "" #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Cor 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignorar a calibração" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Modo de calibração" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Definine o modo de calibração" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Deslocamento" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Deslocamento do cinzento" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Deslocamento do canal cinzento" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Deslocamento do canal vermelho" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Deslocamento do canal verde" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Deslocamento do canal azul" #, fuzzy #~ msgid "Request backend to rotate skewed pages digitally" #~ msgstr "" #~ "Solicita ao driver para rotacionar digitalmente páginas inclinadas" #, fuzzy #~ msgid "Software despeck" #~ msgstr "Alinhamento - Deskew" #, fuzzy #~ msgid "Request backend to remove lone dots digitally" #~ msgstr "Solicita ao driver para remover digitalmente bordas das páginas" #~ msgid "Grayscale" #~ msgstr "Cinzento" #~ msgid "Binary" #~ msgstr "Binário" #~ msgid "Black & White" #~ msgstr "Preto e Branco" sane-backends-1.0.27/po/en@quot.header0000664000175000017500000000226312775312262014437 00000000000000# All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # sane-backends-1.0.27/po/sane-backends.pot0000664000175000017500000035772213110600533015072 00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR The SANE developers # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.27\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 backend/mustek_usb2.c:465 #: backend/pixma_sane_options.c:160 backend/plustek.c:808 #: backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 backend/teco2.c:1914 #: backend/teco3.c:920 backend/test.c:647 backend/u12.c:546 #: backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 backend/mustek_usb2.c:431 #: backend/niash.c:754 backend/plustek.c:854 backend/plustek_pp.c:793 #: backend/sceptre.c:750 backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 backend/rts8891.c:2831 #: backend/snapscan-options.c:923 backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 backend/plustek.c:236 #: backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices supports." msgstr "" #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "" #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 for " "multibit scans." msgstr "" #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "" #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "" #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "" #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "" #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "" #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "" #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "" #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of sheet-" "fed scans." msgstr "" #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "" #: include/sane/saneopts.h:308 #, no-c-format msgid "Determines whether a builtin or a custom gamma-table should be used." msgstr "" #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the red, " "green, and blue channels simultaneously (i.e., it is an intensity gamma " "table)." msgstr "" #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "" #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "" #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "" #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "" #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "" #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result in " "sharper images." msgstr "" #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" #: include/sane/saneopts.h:367 #, no-c-format msgid "Selects what green radiance level should be considered \"full green\"." msgstr "" #: include/sane/saneopts.h:370 #, no-c-format msgid "Selects what blue radiance level should be considered \"full blue\"." msgstr "" #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "" #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs when " "acquiring an image with a camera. Larger values cause more blooming." msgstr "" #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "" #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "" #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. Otherwise, " "calibration is performed only before the first start." msgstr "" #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. The " "default values for gain, offset and exposure time, either build-in or from " "the configuration file, are used." msgstr "" #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "" #: backend/avision.h:783 #, no-c-format msgid "Duplex scan provide a scan of the front and back side of the document" msgstr "" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 backend/pixma_sane_options.c:92 #: backend/snapscan-options.c:86 backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "" #: backend/canon_dr.c:412 #, no-c-format msgid "Card Front" msgstr "" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, no-c-format msgid "Card Duplex" msgstr "" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 backend/magicolor.c:175 #: backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 backend/ma1509.c:501 #: backend/matsushita.c:1084 backend/microtek2.h:598 backend/mustek.c:4203 #: backend/mustek_usb.c:260 backend/mustek_usb2.c:344 backend/niash.c:734 #: backend/plustek.c:721 backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 backend/teco2.c:1886 #: backend/test.c:306 backend/u12.c:473 backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "" #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "" #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or the " "user defined table, which can be downloaded to the scanner" msgstr "" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, no-c-format msgid "Halftone type" msgstr "" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, no-c-format msgid "Perform outline extraction" msgstr "" #: backend/fujitsu.c:3221 #, no-c-format msgid "Emphasis" msgstr "" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, no-c-format msgid "Separation" msgstr "" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "" #: backend/fujitsu.c:3252 #, no-c-format msgid "Mirroring" msgstr "" #: backend/fujitsu.c:3253 #, no-c-format msgid "Reflect output image horizontally" msgstr "" #: backend/fujitsu.c:3270 #, no-c-format msgid "White level follower" msgstr "" #: backend/fujitsu.c:3271 #, no-c-format msgid "Control white level follower" msgstr "" #: backend/fujitsu.c:3289 #, no-c-format msgid "BP filter" msgstr "" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, no-c-format msgid "Gamma curve" msgstr "" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "" #: backend/fujitsu.c:3347 #, no-c-format msgid "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, no-c-format msgid "Threshold white" msgstr "" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, no-c-format msgid "Noise removal" msgstr "" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, no-c-format msgid "Auto width detection" msgstr "" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, no-c-format msgid "Auto length detection" msgstr "" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) is " "same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, no-c-format msgid "DF recovery mode" msgstr "" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, no-c-format msgid "Advanced paper protection" msgstr "" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, no-c-format msgid "Staple detection" msgstr "" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, no-c-format msgid "Dropout color" msgstr "" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, useful " "for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, no-c-format msgid "Buffer mode" msgstr "" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters ADF, " "and increase maximum scan area beyond paper size, to allow collection on " "remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, no-c-format msgid "Off timer" msgstr "" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner off. " "Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, no-c-format msgid "Duplex offset" msgstr "" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "" #: backend/fujitsu.c:3949 #, no-c-format msgid "Adjust green/red offset" msgstr "" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "" #: backend/fujitsu.c:3967 #, no-c-format msgid "Adjust blue/red offset" msgstr "" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some duplex " "transfers to alternate sides on each call to sane_read. Value of option " "'side' can be used to determine correct image. This option should only be " "used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, no-c-format msgid "Duplex side" msgstr "" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, no-c-format msgid "Endorser Options" msgstr "" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, no-c-format msgid "Endorser direction" msgstr "" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, no-c-format msgid "A3 paper" msgstr "" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, no-c-format msgid "B4 paper" msgstr "" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, no-c-format msgid "A4 paper" msgstr "" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, no-c-format msgid "B5 paper" msgstr "" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, no-c-format msgid "Manual feed" msgstr "" #: backend/fujitsu.c:4453 #, no-c-format msgid "Manual feed selected" msgstr "" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, no-c-format msgid "Hardware error code" msgstr "" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, no-c-format msgid "Imprinter ink level" msgstr "" #: backend/fujitsu.c:4548 #, no-c-format msgid "Density" msgstr "" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, no-c-format msgid "Duplex switch" msgstr "" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller than " "the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, no-c-format msgid "Color filter" msgstr "" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, no-c-format msgid "Calibration file" msgstr "" #: backend/genesys.c:5902 #, no-c-format msgid "Specify the calibration file to use" msgstr "" #: backend/genesys.c:5919 #, no-c-format msgid "Calibration cache expiration time" msgstr "" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 means " "cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value of 0 " "means, that the lamp won't be turned off." msgstr "" #: backend/genesys.c:5943 #, no-c-format msgid "Lamp off during scan" msgstr "" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "" #: backend/genesys.c:6053 backend/genesys.c:6054 #, no-c-format msgid "Extra button" msgstr "" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on 60 " "seconds warm-up time." msgstr "" #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually are " "provided. This option is enabled by default. For testing only." msgstr "" #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most scanners " "and can save scanning time. If the image brightness is different with each " "scan, disable this option. For testing only." msgstr "" #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. That " "happens when the scanner scans faster than the computer can receive the " "data. Low values cause faster scans but increase the risk of omitting lines." msgstr "" #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "" #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve image " "quality and then converted to the selected depth. This option avoids depth " "emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to analyze " "them." msgstr "" #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "" #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "" #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "" #: backend/hp-option.c:3087 backend/hp-option.c:3143 backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "" #: backend/hp-option.c:3145 backend/hp-option.c:3252 backend/kvs40xx_opt.c:230 #: backend/matsushita.c:244 backend/mustek.c:149 backend/plustek.c:234 #: backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "" #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "" #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "" #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "" #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "" #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "" #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "" #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested use is " "175% for prints, 150% for normal slides and \"Negative\" for negative film. " "For dark (underexposed) images you can increase this value." msgstr "" #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "" #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "" #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "" #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "" #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "" #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "" #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "" #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 backend/kvs40xx_opt.c:516 #: backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 backend/kvs40xx_opt.c:531 #, no-c-format msgid "Landscape" msgstr "" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 backend/kvs40xx_opt.c:428 #, no-c-format msgid "Manual feed timeout" msgstr "" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 backend/kvs40xx_opt.c:354 #: backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 backend/kvs40xx_opt.c:517 #: backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, no-c-format msgid "color" msgstr "" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 backend/kvs40xx_opt.c:124 #: backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 backend/kvs40xx_opt.c:125 #: backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, no-c-format msgid "normal" msgstr "" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, no-c-format msgid "light" msgstr "" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, no-c-format msgid "From scanner" msgstr "" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, no-c-format msgid "default" msgstr "" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, no-c-format msgid "low" msgstr "" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, no-c-format msgid "medium" msgstr "" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, no-c-format msgid "red" msgstr "" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, no-c-format msgid "green" msgstr "" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, no-c-format msgid "Sets the scan source" msgstr "" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, no-c-format msgid "Sets the manual feed mode" msgstr "" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise reduction " "and image emphasis" msgstr "" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, no-c-format msgid "Lamp color" msgstr "" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, no-c-format msgid "Mirror image (left/right flip)" msgstr "" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, no-c-format msgid "High sensivity" msgstr "" #: backend/kvs40xx_opt.c:232 #, no-c-format msgid "Low sensivity" msgstr "" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "" #: backend/kvs40xx_opt.c:249 #, no-c-format msgid "No detection" msgstr "" #: backend/kvs40xx_opt.c:250 #, no-c-format msgid "Normal mode" msgstr "" #: backend/kvs40xx_opt.c:251 #, no-c-format msgid "Enhanced mode" msgstr "" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it divides " "long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, no-c-format msgid "Automatic threshold mode" msgstr "" #: backend/kvs40xx_opt.c:643 #, no-c-format msgid "Sets the automatic threshold mode" msgstr "" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "" #: backend/kvs40xx_opt.c:787 #, no-c-format msgid "chroma of blue" msgstr "" #: backend/kvs40xx_opt.c:788 #, no-c-format msgid "Set chroma of blue" msgstr "" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "" #: backend/matsushita.c:215 backend/matsushita.c:230 backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "" #: backend/microtek2.h:617 #, no-c-format msgid "If checked the color calibration before a scan is done by the backend" msgstr "" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value for " "the threshold." msgstr "" #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "" #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "" #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "" #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "" #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "" #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. This " "may be a non-color mode or a low resolution mode." msgstr "" #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "" #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "" #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "" #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "" #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "" #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "" #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "" #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on 40 " "seconds warm-up time." msgstr "" #: backend/pixma.c:378 #, no-c-format msgid "Negative color" msgstr "" #: backend/pixma.c:383 #, no-c-format msgid "Negative gray" msgstr "" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before mode " "and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "" #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "" #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "" #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "" #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For kicks, it " "returns green, then blue, then red." msgstr "" #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image height a " "priori. Instead, they return a height of -1. Setting this option allows " "one to test whether a frontend can handle this correctly." msgstr "" #: backend/pnm.c:283 #, no-c-format msgid "Set default values for enhancement controls (brightness & contrast)." msgstr "" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "" #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED after " "sane_read() has been called." msgstr "" #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner during " "scans. If this is set too low, the scanner will have to stop periodically in " "the middle of a scan; if it's set too high, X-based frontends may stop " "responding to X events and your system could bog down." msgstr "" #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, no-c-format msgid "Focus point for scanning." msgstr "" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the like." msgstr "" #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, no-c-format msgid "Frame to be scanned" msgstr "" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, no-c-format msgid "Auto or manual focus" msgstr "" #: backend/snapscan-options.c:911 #, no-c-format msgid "Focus-point" msgstr "" #: backend/snapscan-options.c:912 #, no-c-format msgid "Focus point" msgstr "" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option allows " "one to test whether a frontend can handle this correctly. This option also " "enables a fixed width of 11 cm." msgstr "" #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are transmitted." msgstr "" #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "" #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' after " "10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per square." msgstr "" #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option can " "be used to test the 16 bit modes of frontends, e.g. if the frontend uses the " "correct endianness." msgstr "" #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "" #: backend/test.c:499 #, no-c-format msgid "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "" #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal handling " "for scanning. All other status codes are for testing how the frontend " "handles them." msgstr "" #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "" #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return data." msgstr "" #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of frontends to " "view and modify all the different SANE option types." msgstr "" #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "" #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and advanced) " "capabilities. That's just a normal bool option." msgstr "" #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and advanced) " "capabilities. That means the option can't be set by the frontend but by the " "user (e.g. by pressing a button at the device)." msgstr "" #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. by " "pressing a button at the device) and can't be read by the frontend." msgstr "" #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated (and " "advanced) capabilities." msgstr "" #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic (and " "advanced) capabilities. This option can be automatically set by the backend." msgstr "" #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum is " "4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without constraints." msgstr "" #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word list " "constraint." msgstr "" #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "" #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "" #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "" sane-backends-1.0.27/po/en_GB.po0000664000175000017500000045135413110600536013161 00000000000000# Copyright (C) 2009 Andrew Coles # This file is distributed under the same license as the sane-backends package. # # Andrew Coles , 2009. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2009-04-25 00:19+0100\n" "Last-Translator: Andrew Coles \n" "Language-Team: British English \n" "Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 0.3\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Number of options" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometry" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Enhancement" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Advanced" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Preview" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Force monochrome preview" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bit depth" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Scan mode" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Scan speed" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Scan source" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Force backtracking" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Top-left x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Top-left y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Bottom-right x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Bottom-right y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Scan resolution" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-resolution" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-resolution" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, fuzzy, no-c-format msgid "Page height" msgstr "Highlight" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Use custom gamma table" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Image intensity" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Red intensity" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Green intensity" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Blue intensity" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Brightness" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Grain size" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Halftoning" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Black level" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "White level" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "White level for red" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "White level for green" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "White level for blue" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Shadow" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Shadow for red" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Shadow for green" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Shadow for blue" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Highlight" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Highlight for red" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Highlight for green" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Highlight for blue" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Hue" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturation" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Filename" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Halftone pattern size" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Halftone pattern" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Bind X and Y resolution" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negative" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Quality calibration" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Double Optical Resolution" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Bind RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Threshold" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analogue gamma correction" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analogue gamma red" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analogue gamma green" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analogue gamma blue" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Bind analogue gamma" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Warmup lamp" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Cal. exposure-time" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Cal. exposure-time for red" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Cal. exposure-time for green" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Cal. exposure-time for blue" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Scan exposure-time" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Scan exposure-time for red" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Scan exposure-time for green" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Scan exposure-time for blue" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Set exposure-time" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Cal. lamp density" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Scan lamp density" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Set lamp density" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lamp off at exit" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Read-only option that specifies how many options a specific devices " "supports." #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Short resolution list" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "Number of options" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Hardware resolution" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Request a preview-quality scan." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Selects the scan mode (e.g., lineart, monochrome, or colour)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Determines the speed at which the scan proceeds." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Selects the scan source (such as a document-feeder)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Controls whether backtracking is forced." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Top-left x position of scan area." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Top-left y position of scan area." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Bottom-right x position of scan area." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Bottom-right y position of scan area." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Sets the resolution of the scanned image." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Sets the horizontal resolution of the scanned image." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Sets the vertical resolution of the scanned image." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, fuzzy, no-c-format msgid "Specifies the height of the media." msgstr "Sets the resolution of the scanned image." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Determines whether a builtin or a custom gamma-table should be used." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Gamma-correction table. In colour mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Gamma-correction table for the red band." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Gamma-correction table for the green band." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Gamma-correction table for the blue band." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Controls the brightness of the acquired image." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Controls the contrast of the acquired image." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Selects whether the acquired image should be halftoned (dithered)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Selects what radiance level should be considered \"black\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Selects what radiance level should be considered \"white\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "Selects what red radiance level should be considered \"white\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "Selects what green radiance level should be considered \"white\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr " " #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "Selects what red radiance level should be considered \"black\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "Selects what green radiance level should be considered \"black\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "Selects what blue radiance level should be considered \"black\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "Selects what red radiance level should be considered \"full red\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Selects what green radiance level should be considered \"full green\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Selects what blue radiance level should be considered \"full blue\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Controls the \"hue\" (blue-level) of the acquired image." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "The filename of the image to be loaded." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Defines the halftoning (dithering) pattern for scanning halftoned images." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Use same values for X and Y resolution" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Swap black and white" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Do a quality white-calibration" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Use lens that doubles optical resolution" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "In RGB-mode use same values for each colour" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Select minimum-brightness to get a white point" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analog gamma-correction" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analog gamma-correction for red" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analog gamma-correction for green" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analog gamma-correction for blue" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Warmup lamp before scanning" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Define exposure-time for calibration" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Define exposure-time for red calibration" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Define exposure-time for green calibration" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Define exposure-time for blue calibration" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Define exposure-time for scan" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Define exposure-time for red scan" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Define exposure-time for green scan" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Define exposure-time for blue scan" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Enable selection of exposure-time" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Define lamp density for calibration" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Define lamp density for scan" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Enable selection of lamp density" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Turn off lamp when program exits" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Scan resolution" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "Wait for button" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "Wait for button" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "Wait for button" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "ADF cover open" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Colour" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Colour Lineart" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Colour Halftone" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Grey" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Halftone" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Lineart" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, fuzzy, no-c-format msgid "Operation not supported" msgstr "Halftoning Unsupported" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "Document feeder extras" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "Document feeder extras" #: backend/sane_strstatus.c:83 #, fuzzy, no-c-format msgid "Scanner cover is open" msgstr "ADF cover open" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Defaults" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Set default values for enhancement controls." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Calibration" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Calibrate before next scan" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Only perform shading-correction" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Button state" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Number of the frame to scan" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Selects the number of the frame to scan" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Duplex scan" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "Duplex scan provide a scan of the front and back side of the document" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Calibrate Scanner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Force scanner calibration before scan" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Greyscale scan" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Do a greyscale rather than colour scan" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analogue Gain" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Increase or decrease the analogue gain of the CCD array" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gamma Correction" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Selects the gamma corrected transfer curve" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Raw" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Fine colour" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "No transparency correction" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Correction according to film type" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Correction according to transparency ratio" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negatives" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Slides" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatic" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Normal speed" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 normal speed" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 normal speed" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "rounded parameter" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "unknown" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "ADF jam" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "ADF cover open" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "lamp failure" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "scan head positioning error" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "CPU check error" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "RAM check error" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "ROM check error" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "hardware check error" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "transparency unit lamp failure" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "transparency unit scan head positioning failure" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "parameter list length error" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "invalid command operation code" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "invalid field in CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "unsupported LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "invalid field in parameter list" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "command sequence error" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "too many windows specified" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "medium not present" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "invalid bit IDENTIFY message" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "option not connect" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "power on reset / bus device reset" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parameter changed by another initiator" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "no additional sense information" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "reselect failure" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "SCSI parity error" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "initiator detected error message received" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "invalid message error" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "timeout error" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "transparency unit shading error" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lamp not stabilised" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "film scanner" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "flatbed scanner" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Film type" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Selects the film type, i.e. negatives or slides" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Negative film type" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Selects the negative film type" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Hardware resolution" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Use only hardware resolutions" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Focus" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Auto focus" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Enable/disable auto focus" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Auto focus only once" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Do auto focus only once between ejects" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Manual focus position" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "Set the optical system's focus position by hand (default: 128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Scan margins" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Extra colour adjustments" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Mirror image" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Mirror the image horizontally" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Auto exposure" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Enable/disable the auto exposure feature" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Calibration now" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Execute calibration *now*" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Self diagnosis" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Perform scanner self diagnosis" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Reset scanner" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Reset the scanner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Medium handling" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Eject film after each scan" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Automatically eject the film from the device after each scan" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Eject film before exit" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Automatically eject the film from the device before exiting the program" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Eject film now" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Eject the film *now*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Document feeder extras" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Flatbed only" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "Disable auto document feeder and use flatbed only" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Transparency unit" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "Switch on/off the transparency unit (FAU, film adapter unit)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Negative film" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Positive or negative film" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Density control" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Set density control mode" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Transparency ratio" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Select film type" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Select the film type" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flatbed" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, fuzzy, no-c-format msgid "ADF Front" msgstr "ADF cover open" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "ADF jam" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "ADF Duplex" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Print" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Duplex" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Red" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Green" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Blue" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Enhancement" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Enhancement" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Enhancement" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "None" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Simplex" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Duplex" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Transparency Unit" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatic Document Feeder" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Positive Film" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negative Film" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Focus on glass" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Focus 2.5mm above glass" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Halftone A (Hard Tone)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Halftone B (Soft Tone)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Halftone C (Net Screen)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Dither A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Dither B (4x4 Spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Dither C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Dither D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Text Enhanced Technology" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Download pattern A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Download pattern B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "No Correction" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "User defined" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Impact-dot printers" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Thermal printers" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Ink-jet printers" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT monitors" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Default" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "High density printing" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Low density printing" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "High contrast printing" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "User defined (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "User defined (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 portrait" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 landscape" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Max" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Scan Mode" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Selects the halftone." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Dropout" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Selects the dropout." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Selects the brightness." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Sharpness" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Colour correction" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Sets the colour correction table for the selected output device." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Colour correction coefficients" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matrix multiplication of RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Shift green to red" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Shift green to blue" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Shift red to green" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Shift red to blue" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Shift blue to green" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Shift blue to red" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Controls green level" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Adds to red based on green level" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Adds to blue based on green level" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Adds to green based on red level" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Controls red level" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Adds to blue based on red level" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Adds to green based on blue level" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Adds to red based on blue level" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Controls blue level" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Mirror the image." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Fast preview" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Auto area segmentation" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Short resolution list" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Display short resolution list" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Zoom" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Defines the zoom factor the scanner will use" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Quick format" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Optional equipment" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Eject" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Eject the sheet in the ADF" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Auto eject" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Eject document after scanning" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "ADF Mode" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Selects the ADF mode (simplex/duplex)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Bay" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Select bay to scan" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Focus Position" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Sets the focus position to either the glass or 2.5mm above the glass" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Wait for Button" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Positive Slide" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Negative Slide" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "User defined" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "On" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Off" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Dither" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "Error Diffusion" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "White level" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Black level" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "Conditional" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontal" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Horizontal" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Horizontal" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertical" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Vertical" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Print" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Halftone" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Performs calibration" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Image emphasis" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Saturation" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "Enable automatic determination of threshold for line-art scans." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Mirror image" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Mirror image horizontally." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "White level for blue" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Controls red level" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Colour Filter" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Smoothing" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Gamma value" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Threshold" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Threshold" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Noise reduction" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "No Correction" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "No Correction" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "ADF cover open" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Advanced Options" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "No Correction" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Dropout" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Feeder mode" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Lamp off time" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Blue offset" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Green offset" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Green offset" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Blue offset" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Sets blue channel offset" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Duplex scan" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Advanced Options" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Noise reduction" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "From paper" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "From paper" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "From paper" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "From paper" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "ADF cover open" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr " " #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr " " #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "hardware check error" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "White level" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Density control" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Density control" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Duplex scan" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extras" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Disable interpolation" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Colour Filter" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "When using grey or lineart this option selects the used colour." #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Calibration" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Define calibration mode" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Calibration data cache" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Lamp off time" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Lamp off during dark calibration" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "Minutes until lamp is turned off after scan" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "Wait for button" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "Wait for button" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Wait for button" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Coarse calibration" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Force scanner calibration before scan" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Buttons" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Calibrate" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Start calibration process." #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Coarse calibration" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Calibration data cache" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Transparency Adapter" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Grey mode colour" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "Selects which scan colour is used grey mode (default: green)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Debugging Options" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatic warmup" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Full scan" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Coarse calibration" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Coarse calibration for first scan only" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Backtrack lines" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gamma value" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Sets the gamma value of all channels." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Geometry Group" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Scan Mode Group" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Slide" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Scanner model" #: backend/hp3900_sane.c:1408 #, fuzzy, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "Allows to test device behaviour with other supported models" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Image colours will be inverted" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Disable gamma correction" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "Gamma correction will be disabled" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Disable white shading correction" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "White shading correction will be disabled" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Skip warmup process" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "Warmup process will be disabled" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Force real depth" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Emulate Greyscale" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "If enabled, image will be scanned in colour mode and then converted to " "grayscele by software. This may improve image quality in some " "circumstances." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Save debugging images" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "If enabled, some images involved in scanner processing are saved to " "analyse them." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Reset chipset" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Resets chipset data" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Information" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Chipset name" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Shows chipset name used in device." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Unknown" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "Chipset ID" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Shows the chipset ID" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Scan counter" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Shows the number of scans made by scanner" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Update information" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Updates information about device" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "This option reflects a front panel scanner button" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Image" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Miscellaneous" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "offset X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Hardware internal X position of the scanning area." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "offset Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Hardware internal Y position of the scanning area." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Lamp status" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Switches the lamp on or off." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr " " #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMA Slides" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMA Negatives" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Colour (48 bits)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Extend lamp timeout" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Extends lamp timeout (from 15 minutes to 1 hour)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Wait for button" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Waits for button before scanning" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Advanced Options" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Coarse" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fine" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Custom" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Auto" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Pass-through" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Grey" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA Grey" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Slow" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Fast" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Extra Fast" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-pixel" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-pixel" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-pixel" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Print" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Film-strip" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Conditional" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Experiment" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Sharpening" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Set sharpening value." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Auto Threshold" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "Enable automatic determination of threshold for line-art scans." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr " " #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr " " #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Unloads the media after a scan." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr " " #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Change Document." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Unload" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Unload Document." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Start calibration process." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Media" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Set type of media." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Exposure time" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Colour Matrix" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Set the scanners colour matrix." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Custom colour matrix." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Mono Colour Matrix" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Custom colour matrix for greyscale scans." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Mirror horizontal" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Mirror image horizontally." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Mirror vertical" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Mirror image vertically." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Update options" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Update options." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8 bit output" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Use bit depth greater eight internally, but output only eight bits." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Front button wait" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Wait to scan for front-panel button push." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Shut off lamp" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Shut off scanner lamp." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Paper size" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatic separation" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 landscape" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "Set density control mode" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr " " #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr " " #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Enable Duplex (Dual-Sided) Scanning" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Physical size of the paper in the ADF" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Halftone" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Colour" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Conditional" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Off" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Halftone" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Halftone" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Error Diffusion" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Highlight" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "film scanner" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "From paper" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Default" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Smooth" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Slow" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Medium" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Red" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Green" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Scan source" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Feeder mode" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Sets the feeding mode" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Enable/disable auto focus" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Set density control mode" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Sets the feeding mode" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Sets the feeding mode" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatic threshold" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Noise reduction" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Reduce the isolated dot noise" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Image emphasis" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Sets the image emphasis" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Lamp on" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Switches the lamp on or off." #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Mirror image vertically." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gamma correction" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "High density printing" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Low density printing" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Error Diffusion" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "No Correction" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normal" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Enhancement" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Automatic threshold" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Automatic threshold" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Set the order of frames" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Shadow for blue" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Shift red to blue" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamond" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 Coarse Fatting" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 Fine Fatting" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Vertical Line" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr " " #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Colour channels gain settings" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Grey gain" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Sets grey channel gain" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Red gain" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Sets red channel gain" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Green gain" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Sets green channel gain" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Blue gain" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Sets blue channel gain" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer Dither 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer Dither 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Halftone Dot 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Halftone Dot 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Error Diffusion" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Mode 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Mode 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Mode 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "From white stick" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Smooth" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Low" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Medium" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "High" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "One page" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "All pages" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "sheetfed scanner" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Greyscale 4 bits" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Greyscale 8 bits" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Shadow, midtone, highlight, exposure time" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Special options" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Colour balance" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Disable backtracking" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "If ticked the scanner does not perform backtracking" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Toggle lamp of flatbed" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Toggles the lamp of the flatbed" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Calibration by backend" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "If ticked the colour calibration before a scan is done by the backend" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Use the lightlid-35mm adapter" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "This option turns off the lamp of the flatbed during a scan" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Quality scan" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Highest quality but lower speed" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Fast scan" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Highest speed but lower quality" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatic adjustment of threshold" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "If ticked the backend automatically tries to determine an optimal value " "for the threshold." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Selects the gamma correction mode." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Bind gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Use same gamma values for all colour channels." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Scalar gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Selects a value for scalar gamma correction." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Scalar gamma red" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Selects a value for scalar gamma correction (red channel)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Scalar gamma green" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Selects a value for scalar gamma correction (green channel)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Scalar gamma blue" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Selects a value for scalar gamma correction (blue channel)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Channel" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Selects the colour band, \"Master\" means that all colours are affected." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Midtone" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Selects which radiance level should be considered \"50 % grey\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Midtone for red" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Selects which radiance level should be considered \"50 % red\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Midtone for green" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Selects which radiance level should be considered \"50 % green\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Midtone for blue" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Selects which radiance level should be considered \"50 % blue\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Red balance" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Balance factor for red. A value of 100% means no correction." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Green balance" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Balance factor for green. A value of 100% means no correction." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Blue balance" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr " " #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr " " #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Sets the colour balance values to the firmware provided values." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Slowest" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Slower" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Faster" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Fastest" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 coarse" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr " " #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 very fine" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normal" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 coarse" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fine" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 coarse" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr " " #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fine" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr " " #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 custom" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 custom" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 custom" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr " " #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 custom" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Fast grey mode" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Scan in fast grey mode (lower quality)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-colour mode or a low resolution mode." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Lamp off time (minutes)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Set the time (in minutes) after which the lamp is shut off." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Turn lamp off" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Turns the lamp off immediately." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Red brightness" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Controls the brightness of the red channel of the acquired image." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Green brightness" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "" "Controls the brightness of the green channel of the acquired image." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Blue brightness" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Controls the brightness of the blue channel of the acquired image." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contrast red channel" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Controls the contrast of the red channel of the acquired image." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contrast green channel" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Controls the contrast of the green channel of the acquired image." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contrast blue channel" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Controls the contrast of the blue channel of the acquired image." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Colour48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Colour24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Grey16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Grey8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Reflective" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positive" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Negative film" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negative" #: backend/pixma.c:396 #, fuzzy, no-c-format msgid "48 bits color" msgstr "Fine colour" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, fuzzy, no-c-format msgid "Button-controlled scan" msgstr "Button-controlled scan (experimental)" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOUR\" button (for other models). To " "cancel, press \"GREY\" button." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Update button state" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Button 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Button 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Transparency" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Device-Settings" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Lampswitch" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Manually switching the lamp(s)." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Lamp off during dark calibration" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Always switches lamp off when doing dark calibration." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Calibration data cache" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Enables or disables calibration data cache." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Performs calibration" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Speedup sensor" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Enables or disables speeding up sensor movement." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Warmup-time" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Warmup-time in seconds." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Lampoff-time" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Lampoff-time in seconds." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Analogue frontend" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Red gain value of the AFE" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Red offset" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Red offset value of the AFE" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Green gain value of the AFE" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Green offset value of the AFE" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Blue gain value of the AFE" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Blue offset value of the AFE" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Red lamp off" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Defines red lamp off parameter" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Green lamp off" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Defines green lamp off parameter" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Blue lamp off" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Defines blue lamp off parameter" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "This option reflects the status of the scanner buttons." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Colour36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Dithermap 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Dithermap 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Randomise" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Source Selection" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Image Enhancement" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Greyify" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Load the image as greyscale." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Three-Pass Simulation" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Hand-Scanner Simulation" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Set default values for enhancement controls (brightness & contrast)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Read only test-option" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Let's see whether frontends can treat this right" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Gamma Tables" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Status Code Simulation" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Do not force status code" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Do not force the backend to return a status code." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Return SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Return SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Return SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Return SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Return SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Return SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Return SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." #: backend/rts8891.c:2809 #, fuzzy, no-c-format msgid "This option reflects the status of a scanner button." msgstr "This option reflects the status of the scanner buttons." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lamp on" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Turn on scanner lamp" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lamp off" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Turn off scanner lamp" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Lamp timeout" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Minutes until lamp is turned off after scan" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Threshold value for lineart mode" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Document Feeder" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (inch)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (inch)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (inch)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Halftoning Unsupported" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Eject document after scanning" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Preview mode" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Predefined settings" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Provides standard scanning areas for photographs, printed pages and the " "like." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "flatbed scanner" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Focus" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Auto focus" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Focus Position" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Focus Position" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Colour lines per read" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Greyscale lines per read" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "webcam" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Colour RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Colour RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Colour RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Solid black" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Solid white" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Colour pattern" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Grid" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "First entry" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Second entry" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Hand-scanner simulation" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Three-pass simulation" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simulate a three-pass scanner. In colour mode, three frames are " "transmitted." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Set the order of frames" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Set the order of frames in three-pass colour mode." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Special Options" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Select the test picture" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various colour test patterns depending on the " "mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Invert endianness" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Read limit" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Limit the amount of data transferred with each call to sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Size of read-limit" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "The (maximum) amount of data transferred with each call to sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Read delay" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Delay the transfer of data to the pipe." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Duration of read-delay" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "How long to wait after transferring each buffer of data through the pipe." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Return-value of sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Loss of pixels per line" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "The number of pixels that are wasted at the end of each line." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Fuzzy parameters" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Use non-blocking IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "Use non-blocking IO for sane_read() if supported by the frontend." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Offer select file descriptor" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Enable test options" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Print options" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Print a list of all options." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Bool test options" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Bool soft select soft detect" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Bool hard select soft detect" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Bool hard select" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Bool soft detect" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Bool soft select soft detect emulated" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Bool soft select soft detect auto" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Int test options" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Int" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Int test option with no unit and no constraint set." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Int constraint range" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Int constraint word list" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "(3/6) Int test option with unit bits and constraint word list set." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Int array" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Int test option with unit mm and using an array without " "constraints." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Int array constraint range" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Int array constraint word list" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Fixed test options" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Fixed" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) Fixed test option with no unit and no constraint set." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Fixed constraint range" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Fixed constraint word list" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "(3/3) Fixed test option with no unit and constraint word list set." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "String test options" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) String" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) String test option without constraint." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) String constraint string list" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) String test option with string list constraint." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) String constraint long string list" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) String test option with string list constraint. Contains some more " "entries..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Button test options" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Button" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Button test option. Prints some text..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Colour 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Use Image Composition" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Bi-level black and white (lineart mode)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Dithered/halftone black & white (halftone mode)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Multi-level black & white (greyscale mode)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Multi-level RGB colour (one pass colour)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignore calibration" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Disable pre focus" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Do not calibrate focus" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr " " #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Fix focus position" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Lens calibration in doc position" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Calibrate lens focus in document position" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Holder focus position 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Use 0mm holder focus position instead of 0.6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Calibration mode" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Define calibration mode" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Sets lamp on/off" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA on" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Sets UTA on/off" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Offset" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Colour channels offset settings" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Grey offset" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Sets grey channel offset" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Sets red channel offset" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Sets green channel offset" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Sets blue channel offset" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Preview mode" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "problem not analysed (unknown SCSI class)" #~ msgid "Grayscale" #~ msgstr "Greyscale" #~ msgid "Binary" #~ msgstr "Binary" #~ msgid "Display a shortened resolution list" #~ msgstr "Display a shortened resolution list" #~ msgid "Black & White" #~ msgstr "Black & White" sane-backends-1.0.27/po/eo.po0000664000175000017500000046250713110600537012615 00000000000000# translation of sane-backends.eo.po to # Esperanto translation for SANE backend package # Copyright (C) SANE Project. # # Esperanto special letters = ĉÅÄĥĵŭ # # Antonio Codazzi, , 2007. # msgid "" msgstr "" "Project-Id-Version: sane-backends.eo\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-12-08 13:28+0100\n" "Last-Translator: A.C.Codazzi\n" "Language-Team: \n" "Language: eo\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.0.2\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Nombro da opcioj" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometrio" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Plibonigo" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Avana" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "AntaÅ­montro" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Perfortu monokromatan antaÅ­montron" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Profundeco en bitoj" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Moduso de skanado" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Rapideco de skanilo" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Fonto de skanilo" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Perfortu malavancon" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Supre-maldekstre X" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Supre-maldekstre Y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Sube-dekstre X" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Sube-dekstre Y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Difino de skanado" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Distingo de X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Distingo de Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, fuzzy, no-c-format msgid "Page height" msgstr "Lumbrilo" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Uzu personigitan tabelon de gama" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Intenso de bildo" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Intenso de ruÄo" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Intenso de verdo" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Intenso de bluo" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Heleco" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontrasto" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Grajno" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Meznuancoj" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Nivelo de nigro" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Nivelo de blanko" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Nivelo de blanko laÅ­ ruÄo" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Nivelo de blanko laÅ­ verdo" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Nivelo de blanko laÅ­ bluo" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Ombrumo" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Ombrumo laÅ­ ruÄo" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Ombrumo laÅ­ verdo" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Ombrumo laÅ­ bluo" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Lumbrilo" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Lumbrilo laÅ­ ruÄo" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Lumbrilo laÅ­ verdo" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Lumbrilo laÅ­ bluo" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Nuanco" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturado" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Dosiernomo" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Grado de modelo por meznuancoj" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Modelo por meznuanco" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Bindu distindon de X kaj Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativo" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Kvalito de kalibrigo" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Duobligu Optikan Distingon" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Bindu RGB-kanalojn" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Sojlo" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Korektado de analoga gama" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "RuÄo de analoga gama" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Verdo de analoga gama" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Bluo de analoga gama" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Bindu analogan gaman" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Varmigo de lampo" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Kal. ekspontempon" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Kal. ekspontempon por ruÄo" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Kal. ekspontempon por verdo" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Kal. ekspontempon por bluo" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Ekspontempo de skanado" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Ekspontempo de skanado por ruÄo" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Ekspontempo de skanado por verdo" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Ekspontempo de skanado por verdo" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Agordu ekspontempon" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Kal. potencon de lampo" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Potenco de lampo en skanado" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Agordu potencon de lampo" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "ElÅaltu lampon kaj eliru" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Äœi estas nurlega opcio kiu priskribas kiom da opcioj subtenas specifa " "aparato." #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Listeto pri distingoj" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "Nombro da opcioj" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Hardvara difino" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Äœi mendas antaÅ­montra-kvalitan skanadon." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Äœi mendas ke ĉiuj antaÅ­montroj estas plenumitaj per monokromata moduso. " "Kun 3-pasoj-skanilo, Äi reduktas la nombron da pasadoj al unu, kaj do " "kun 1-paso-skaniloÄi malpliigas la memoron kiu necesas kaj la tempo de " "skanado por la antaÅ­montro." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Nombro da bitoj por specimeno, kutima valoro estas 1 por \"duuma\" kaj 8 " "por multbitaj skanadoj." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Äœi elektas la moduson de skanado (ekz. duuma, monokromata aÅ­ koloro)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Äœi determinas la rapidecon de skanado." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Äœi elektas la fonton por la skanado (ekz. provizilo)" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Kontrolu ke la malavanco estas perfortita." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Supra-maldekstra posicio de X en areo de skanado." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Supra-maldekstra posicio de Y en areo de skanado." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Suba-dekstra posicio de X en areo de skanado.." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Suba-dekstra posicio de Y en areo de skanado." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Äœi agordas la difinon de la skanita bildo." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Äœi agordas la horizontalan difinon de la skanita bildo." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Äœi agordas la vertikalan difinon de la skanita bildo." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, fuzzy, no-c-format msgid "Specifies the height of the media." msgstr "Äœi agordas la difinon de la skanita bildo." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Äœi determinas uzi antaÅ­difinitan tabelon de gama aÅ­ personigitan tabelon." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Tabelo de gama-korektado. En moduso de koloro tiu ĉi opcio efikas " "samtempe sur 3 kanaloj (ruÄo, verdo, bluo) kaj do Äi estas gama-tabelo " "de intenseco. " #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Tabelo de gama-korektado laÅ­ ruÄo." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Tabelo de gama-korektado laÅ­ verdo." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Tabelo de gama-korektado laÅ­ bluo" #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Äœi kontrolas la helecon de la akirita bildo." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Äœi kontrolas la kontraston de la akirita bildo." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Äœi elektas la \"grajneco\" de la akirita bildo. Malpli grandaj valoroj " "donas pli netajn bildojn." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Äœi elektas se la akirita bildon devas esti neznuancigita (stompita)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Äœi elektas la nivelon de heleco kiu estas konsiderenda \"nigro\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Äœi elektas la nivelon de heleco kiu estas konsiderenda \"blanko\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Äœi elektas la nivelon de ruÄa heleco kiu estas konsiderenda \"blanko\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Äœi elektas la nivelon de verda heleco kiu estas konsiderenda \"blanko\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Äœi elektas la nivelon de blua heleco kiu estas konsiderenda \"blanko\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Äœi elektas la nivelon de ruÄa heleco kiu estas konsiderenda \"nigro\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Äœi elektas la nivelon de verda heleco kiu estas konsiderenda \"nigro\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Äœi elektas la nivelon de blua heleco kiu estas konsiderenda \"nigro\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Äœi elektas la nivelon de ruÄa heleco kiu estas konsiderenda \"tuta ruÄo" "\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Äœi elektas la nivelon de verda heleco kiu estas konsiderenda \"tuta verdo" "\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Äœi elektas la nivelon de blua heleco kiu estas konsiderenda \"tuta bluo" "\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Äœi kontrolas la nuancon (nivelon de bluo) de la akirita bildo." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "La nivelo de saturado mastrumas la kvanton da \"florado\" kiu okazas " "kiam oni akiras bildon per kamerao. Pli larÄaj valoroj kaÅ­zas pli " "floradon." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "La dosiernomo de la Åargenda bildo." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Äœi agordas la grandon de modelo por meznuanco (stompado/punktismo) uzata " "kun neznuancaj bildoj." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Äœi agordas la modelon por meznuanco (stompado/punktismo) uzata kun " "neznuancaj bildoj." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Uzu la saman valoron por distingo de X kaj Y" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "InterÅanÄu blankon kaj nigron" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Plenumu kvalitan kalibrigon laÅ­ blanko" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Uzu la lensojn kiuj duobligas optikan distingon" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Uzu la samajn valorojn por ĉiu koloro en RGB-moduso" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Agordu minimuman helecon por havi blankan punkton" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analoga korektado de gama" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analoga korektado de gama por ruÄo" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analoga korektado de gama por verdo" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analoga korektado de gama por bluo" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Varmigu lampon antaÅ­ la skanado" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Difinu la ekspontempon por la kalibrigo" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Difinu la ekspontempon por la kalibrigo de ruÄo" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Difinu la ekspontempon por la kalibrigo de verdo" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Difinu la ekspontempon por la kalibrigo de bluo" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Difinu la ekspontempon por la skanado" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Difinu la ekspontempon por la skanado de ruÄo" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Difinu la ekspontempon por la skanado de verdo" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Difinu la ekspontempon por la skanado de bluo" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Ebligu la elektadon de ekspontempo" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Definu la intenson de la lampo por la kalibrigo" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Definu la intenson de la lampo por la skanado" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Ebligu la elektadon de la intenson de la lampo" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "ElÅaltu la lampon elirante de la programo" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Difino de skanado" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "Atendu butonon" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "Atendu butonon" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "Atendu butonon" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Kovrilo de ADF estas malfermita" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Koloro" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Duuma Koloro" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Meznuanca Koloro" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Grizo" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Meznuancoj" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Duuma" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, fuzzy, no-c-format msgid "Operation not supported" msgstr "Mez-nuancoj Nesubtenitaj" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "Aliaj agordoj pri provizilo de dokumentoj" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "Aliaj agordoj pri provizilo de dokumentoj" #: backend/sane_strstatus.c:83 #, fuzzy, no-c-format msgid "Scanner cover is open" msgstr "Kovrilo de ADF estas malfermita" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "DefaÅ­ltaj valoroj" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Uzu la defaÅ­ltajn valorojn por la regilojn de plibonigo." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibrigo" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Kalibrigu la skanilon antaÅ­ la venonta skanado" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Se Äi estas ebligita, la skanilo estos kalibrigita antaÅ­ la venonta " "skanado. Alie la kalibrigo plenumiÄos nur antaÅ­ la unua starto." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Plenumu nur korektadon de ombroj" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Se Äi estas ebligita, oni plemunas nur la korektadon de ombroj dum " "kalibrigo. La defaÅ­ltaj valoroj (aÅ­ tiuj en la agorddosiero) estos " "uzataj por gajno, deÅovo kaj ekspontempo." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Stato de butono" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Nombro da skanendaj filmeroj" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Elektu nombron da skanendaj filmeroj" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Fronta-dorsa skanado" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "Äœi plenumas frontan-dorsan skanadon de la dokumento" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Kalibrigu Skanilon" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Äœi devigas kalibrigon de skanilon antaÅ­ la skanado" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Grizgama skanado" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Äœi plenumas grizgaman anstataÅ­ kolora skanadon" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analoga Gajno" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Äœi pliigas aÅ­ malpliigas la analogan gajnon de la CCD-sentilo" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Korektado de Gama" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Äœi elektas la kurbon de korektado de gama" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Kruda" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Fajna koloro" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Neniu korektado de diafaneco" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Korektado rilata al la filmospeco" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Korektado rilata al la rejÅo de diafaneco" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negativoj" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Lumbildoj" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "AÅ­tomata" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Normala rapideco" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "Duono de la normala radipeco" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "Triono de la normala radipeco" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "rondigitaj parametroj" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "nekonata" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "ADF estas blokita" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "Kovrilo de ADF estas malfermita" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "lampo malfunkcias" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "eraro de lokiÄo de skan-kapeto" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "Eraro de kontrolo de CPU" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "Eraro de kontrolo de RAM" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "Eraro de kontrolo de ROM" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "Eraro de kontrolo de la aparataro" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "la lampo de diafanecoj malfunkcias" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "eraro de lokiÄo de la skan-kapeto por diafanecoj" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "eraro de longo de listo pri parametroj" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "nevalida kodo de komando" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "nevalida kampo en CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "nesubtenita LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "nevalida kampo en la listo pri parametroj" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "eraro en la vico de komandoj" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "la difinitaj fenestroj estas troaj" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "la aparato estas neĉeestanta" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "mesaÄo kun nevalida IDENTIFY-bito" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "opcio de ne-konektado" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "re-agordo de nutro / re-agordo de buso de aparatoj" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parametro estis ÅanÄita de alia pravaloranto" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "neniu alia aldona informo pri «senso»" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "re-elektado malsukcesis" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "eraro de pareco de SCSI" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "oni ricevis mesaÄon pri eraro rekonita de pravaloranto" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "eraro de nevalida mesaÄo" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "eraro de tempofino" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "eraro de vualo de diafaneco" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "nestabiligita lampo" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "skanilo por negativoj" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "plata skanilo" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Filmo" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Äœi elektas specon de filmo: negativoj aÅ­ lumbildoj" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Speco de negativa filmo" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Äœi elektas la specon de negativa filmo" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Hardvara difino" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Uzu nur hardvarajn difinojn" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Fokuso" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Mem-fokusigo" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Äœi ebligas/malebligas aÅ­tomatan fokusigon" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Memfokusigo nur unu-foje" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Äœi plenumas memfokusigon nur unu-foje por ĉiu enigo de filmo" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Lokado de mana fokusigo" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "Äœi mane agordas lokadon de optika fokusigo (defaÅ­to: 128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "MarÄenoj por skanado" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Aliaj aranÄoj de koloro" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Spegula bildo" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Äœi reflektas bildon horizontale" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Mem-ekspono" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Äœi ebligas/malebligas aÅ­tomatan eksponon" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Tuja kalibrigo" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Äœi plenumas kalibrigon tuj" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Mem-diagnozo" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Äœi plenumas aÅ­tomatajn kontrolojn" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Re-agordu skanilon" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Äœi ree agordas la skanilon" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Mastrumado de aparato" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Elpelu filmon post ĉiu skanado" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Äœi aÅ­tomate elpelas filmon post ĉiu skanado" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Elpelu filmon antaÅ­ eliri" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "Äœi aÅ­tomate elpelas filmon antaÅ­ la eliro de la programo" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Elpelu filmon nun" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Äœi elpelas filmon *nun*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Aliaj agordoj pri provizilo de dokumentoj" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Nur fiksa ebeno" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "Äœi malebligas provizilon de dokumentoj kaj uzas nur fiksan ebeno" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Reguligilo de diafaneco" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" "Äœi evligas/malebligas la reguligilon de diafaneco (FAU, «film adapter " "unit»)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Negativa filmo" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Pozitiva aÅ­ negativa filmo" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Regilo de denseco" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Äœi ebligas moduson de la regado de denseco" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "RejÅo de diafaneco" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Elektu specon de filmo" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Äœi elektas specon de filmo" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Fiksa ebeno" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, fuzzy, no-c-format msgid "ADF Front" msgstr "Kovrilo de ADF estas malfermita" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "ADF estas blokita" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "Fronta-dorsa ADF" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Presu" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Fronta-dorsa" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "RuÄo" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Verdo" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Bluo" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Plibonigo" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Plibonigo" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Plibonigo" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Nenio" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Unuopa" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Fronta-dorsa" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Reguligilo de Diafaneco" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "AÅ­tomata Provizilo de Dokumentoj" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Pozitiva filmo" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negativa filmo" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Fokusigo sur la vitro" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Fokusigo je 2.5mm super la vitro" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Meznuanco A (Duraj tonoj)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Meznuanco B (Delikataj tonoj)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Meznuanco C (Reta ekrano)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Punktismo A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Punktismo B (4x4 Spiralo)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Punktismo C (4x4 Reta ekrano)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Punktismo D (8x4 Reta ekrano)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Teknologio por Plibonigo de Teksto" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "ElÅutu modelon A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "ElÅutu modelon B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Neniu korektado" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Agordita de la uzanto" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Kontaktaj printiloj" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Termikaj printiloj" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "InkoÅprucaj printiloj" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT ekranoj" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "DefaÅ­lto" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Altdensa printado" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Malaltdensa printado" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Altkontrasta printado" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Agordita de la uzanto (Gama=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Agordita de la uzanto (Gama=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "KD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 verticala" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 horizontala" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letero" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Maks" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Moduso de Skanado" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Elektu meznuancojn." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Eskludado" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Äœi elektas la eskludadon." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Äœi elektas la helecon." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Neteco" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Korektado de koloro" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "Äœi ebligas la tabelon de la korektado de koloro por la elektita aparato." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Koeficientoj de korektado de koloro" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matrica multipliko de RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Åœovu verdon al ruÄo" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Åœovu verdon al bluo" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Åœovu ruÄon al verdo" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Åœovu ruÄon al bluo" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Åœovu bluon al verdo" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Åœovu bluon al ruÄo" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Mastrumu nivelon de verdo" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Aldonu ruÄon surbaze de nivelo de verdo" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Aldonu bluon surbaze de nivelo de verdo" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Aldonu verdon surbaze de nivelo de ruÄo" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Mastrumu nivelon de ruÄo" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Aldonu bluon surbaze de nivelo de ruÄo" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Aldonu verdon surbaze de nivelo de bluo" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Aldonu ruÄon surbaze de nivelo de bluo" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Mastrumu nivelon de bluo" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Spegulu bildon" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Tuja antaÅ­montro" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "AÅ­tomata segmentado de areo" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Listeto pri distingoj" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Vidigu etan liston pri disponeblaj distingoj" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Zomo" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Äœi agordas la faktoron de zomo kiun la skanilo uzos" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Formato rapido" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Akcesora ekipaĵo" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Elpelo" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Äœi elpelas la folion el aÅ­tomata provizilo" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Mem-elpelo" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Äœi elpelas la dokumento post la skanado" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Moduso por ADF" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Äœi elektas la ADF-moduso (unuopa/fronta-dorsa)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Kesto" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Äœi elektas la keston por skani" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Äœi elektas korektadon de gama el listo de antaÅ­difinitaj aparatoj aÅ­ el " "la personigita tabelo, kiu esti alÅutebla en skanilon scanner" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "LokiÄo de Fokusigo" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Äœi agordas la lokiÄon de la fokusigo aÅ­ sur la vitro aÅ­ je 2,5mm super Äi" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Atendu Butonon" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Post la sendo de la skan-komando, Äi atendas la premon de la butono de " "la skanilo por startigi la skanadon." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Pozitiva lumbildo" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Negativa lumbildo" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Agordita de la uzanto" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Kondukta" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Elkluda" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Punktismo" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "Difuzo de Eraro" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Nivelo de blanko" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Nivelo de nigro" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "Kondiĉa" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontala" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Horizontala" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Horizontala" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertikala" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Vertikala" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Presu" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Meznuancoj" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Plenumu kalibrigon" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Emfazo de bildo" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Saturado" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "Äœi elbligas aÅ­tomatan elekton de sojlo por duuma skanado." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Spegula bildo" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Äœi reflektas bildon horizontale." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Nivelo de blanko laÅ­ bluo" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Mastrumu nivelon de ruÄo" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Filtrilo de Koloro" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Glatigo" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Valoro de Gama" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Sojlo" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Sojlo" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Redukto de bruo" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Neniu korektado" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Neniu korektado" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Kovrilo de ADF estas malfermita" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Avanaj Opcioj" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Neniu korektado" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Eskludado" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Moduso de provizilo" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Ripozo de lampo" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "DeÅovo laÅ­ bluo" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "DeÅovo laÅ­ verdo" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "DeÅovo laÅ­ verdo" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "DeÅovo laÅ­ bluo" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Äœi agordas la deÅovon de la blua kanalo" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Fronta-dorsa skanado" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Avanaj Opcioj" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Redukto de bruo" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "El papero" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "El papero" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "El papero" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "El papero" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "Kovrilo de ADF estas malfermita" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Mana prepara fokusigo" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Mana prepara fokusigo" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "Eraro de kontrolo de la aparataro" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Nivelo de blanko" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Regilo de denseco" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Regilo de denseco" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Fronta-dorsa skanado" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Ekstraĵoj" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Malebligu interpoladon" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "Kiam oni uzas altajn distingojn kun la horizontala malpli alta ol la " "verticala, la horizontala interpolado estas malebligata." #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Filtrilo de Koloro" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "Kiam oni uzas grizan aÅ­ duuman kolorojn, tiu elektas uzatan koloron." #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibrigo" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Difinu moduson de kalibrigo" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "KaÅmemoro por kalibrigo" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Ripozo de lampo" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "La lampo estos elÅaltata post la fiksita tempo (en minutoj). La valoro " "signifas ke la lampo neniam ripozos." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "ElÅaltita lampo dum kalibrigo de nigro" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" "Nombro da minutoj pasantaj inter la skanado kaj la elÅalto de la lampo" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "Atendu butonon" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "Atendu butonon" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Atendu butonon" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Grajneca kalibrigo" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Äœi devigas kalibrigon de skanilon antaÅ­ la skanado" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Butonoj" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibrigu" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Startigu kalibrigadon." #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Grajneca kalibrigo" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "KaÅmemoro por kalibrigo" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "reguligilo de Diafaneco" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Koloro por grizgamo" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Äœi elektas la skan-koloron uzendan por la grizgamo (defaÅ­lto: verdo)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Opcioj de Sencimigo" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "AÅ­tomata varmigo" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Äœi varmigas la lampon tiel ke Äia heleco estas sensanÄa anstataÅ­ ĉiufoja " "varmigo je 60 sekundoj." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Plena skanado" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Äœi skanas la tutan areon, do Äi skanas ankaÅ­ la strion de kalibrigo. " "Atentu. Ne elektu plenan alton. Äœi estas uzenda nur por testi." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Grajneca kalibrigo" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Äœi agordas gajnon kaj deÅovon por aÅ­tomate skani. Se tiu ĉi opcio estas " "malebligita, mane agordado de la parametroj estas ebligita. Tiu ĉi opcio " "estas defaÅ­lta. Äœi estas uzenda nur por testi." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Grajneca kalibrigo nur por unua skanado" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "La grajneca kalibrigo plenumas nur laÅ­ la unua skanado. Äœi funkcias kun " "la plejmulto de skaniloj kaj Äi Åparas multe da tempo. Malebligu tiu ĉi " "opcio se la heleco estas malsama en ĉiu skanita bildo. Äœi estas uzenda " "nur por testi." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Linioj de malavanco" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Nombro da linioj kiujn retroiras la skan-Åovpeco dum la malavanco. Tio " "okazas se la skanilo estas pli rapida ol komputilo kiu ricevas datumojn. " "Malaltaj valoroj ebligas pli rapidan skanadon sed pliigas la riskon pri " "mankantaj linioj." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Valoro de Gama" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Äœi agordas valoron de gama por ĉiuj kanaloj." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Geometria Grupo" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Grupo de Moduso de Skanado" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Lumbildo" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Moduso de skanado" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "Korektado de analoga gama" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "Korektado de gama" #: backend/hp3900_sane.c:1451 #, fuzzy, no-c-format msgid "Disable white shading correction" msgstr "Plenumu nur korektadon de ombroj" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "Grizgamo" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "Re-agordu skanilon" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Ignoru kalibrigon" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Dosiernomo" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, fuzzy, no-c-format msgid "Unknown" msgstr "nekonata" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "Re-agordu skanilon" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "Fonto de skanilo" #: backend/hp3900_sane.c:1584 #, fuzzy, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Elektu nombron da skanendaj filmeroj" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Opcioj de Äisdatigo" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, fuzzy, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Tiuj ĉi opcioj agas sur la stato de la butonoj de la skanilo." #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Bildo" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Diversaĵoj" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "deÅovo X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Hardvara interna pozicio de X en la skanada areo." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "deÅovo Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Hardvara interna pozicio de Y en la skanada areo." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Stato de la lampo" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Åœaltu aÅ­ elÅaltu la lampon." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Kalibrigu la nivelojn de nigro kaj blanko." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMA-Lumbildoj" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMA-Negativoj" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Koloro (48 bitoj)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Prokastu elÅalton de lampo" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Äœi prokastas elÅalton de lampo (de 15 minutoj Äis 1 horo)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Atendu butonon" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Äœi atendas butonpremon antaÅ­ skanado" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Avanaj Opcioj" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Grajna" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fajna" # Bayer è il nome della persona che ha inventato questa matrice per il # dithering. #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Personigita" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "AÅ­tomata" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Trapasanta" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC-Grizo" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA-Grizo" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Malrapida" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normala" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Rapida" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Tre Rapida" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-bilderoj" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-bilderoj" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-bilderoj" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Presu" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Filmo" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Kondiĉa" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Eksperimento" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Neteco" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Äœi agordas la valoron de neteco." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "AÅ­tomata Sojlo" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "Äœi elbligas aÅ­tomatan elekton de sojlo por duuma skanado." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Elektu filtrilon por glatigi." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Elpelu bazon post skanado" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Äœi elpelas la bazon post skanado." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Åœangu dokumenton" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Äœi Åangas dokumenton." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Elpelu" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Elpelu Dokumenton." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Startigu kalibrigadon." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Bazo" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Agordu specon de bazo." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Ekspontempo" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Pli longa ekspontempo ebligas la skanilon preni pli multe da lumo. " "Oportunajvaloroj estas 175% por presaĵoj, 150% por normalaj lumbildoj " "kaj \"Negativo\" por filmoj. Por malhelaj bildoj (subeksponitaj) pliigu " "tiun ĉi valoro." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Matrico de Koloro" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Äœi agordas matricon de koloro." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Personigita matrico de koloro." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Matrico de Monokromata Koloro" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Personigita matrico de koloro por grizgamaj skanadoj." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Spegulu horizontale" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Äœi reflektas bildon horizontale." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Spegulu vertikale" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Äœi reflektas bildon vertikale." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Opcioj de Äisdatigo" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Opcioj de Äisdatigo." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8-bita eligo" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "Uzu ene pli ol 8 bitoj de profundeco, sed eligu nur 8-bitojn." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Atendante frontan butonon" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Äœi atendas premon de la fronta butono de lo skanilo por skani." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "ElÅaltu lampon" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Äœi elÅaltas la lampon de la skanilo." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Grando de folio" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Mem-dividado" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 horizontala" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "Äœi ebligas moduson de la regado de denseco" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Mana prepara fokusigo" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Mana prepara fokusigo" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Ebligu frontan-dorsan skanado" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Grando de folio en provizilo" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Meznuancoj" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Koloro" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Kondiĉa" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Elkluda" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" # Bayer è il nome della persona che ha inventato questa matrice per il # dithering. #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" # Bayer è il nome della persona che ha inventato questa matrice per il # dithering. #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Meznuancoj" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Meznuancoj" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Difuzo de Eraro" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normala" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Lumbrilo" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "skanilo por negativoj" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "El papero" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "DefaÅ­lto" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Milda" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Malrapida" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Meza" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "RuÄo" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Verdo" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Fonto de skanilo" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Moduso de provizilo" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Agordu moduson de provizilo" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Äœi ebligas/malebligas aÅ­tomatan fokusigon" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Äœi ebligas moduson de la regado de denseco" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Agordu moduson de provizilo" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Agordu moduson de provizilo" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "AÅ­tomata sojlo" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Heleco, kontrasto, nivelo de blanko, gama, redukto de bruo kaj emfazo de " "bildo estos aÅ­tomate agorditaj" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Redukto de bruo" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Äœi reduktas bruon de izolitaj punktoj" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Emfazo de bildo" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Äœiu ebligas emfazon de bildo" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gama" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Åœaltu lampon" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Åœaltu aÅ­ elÅaltu la lampon." #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Äœi reflektas bildon vertikale." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Korektado de gama" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Altdensa printado" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Malaltdensa printado" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Difuzo de Eraro" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Neniu korektado" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normala" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Plibonigo" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "AÅ­tomata sojlo" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "AÅ­tomata sojlo" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Agordu ordon por la bildoj" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Ombrumo laÅ­ bluo" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Åœovu ruÄon al bluo" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamanto" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 grajna" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 fajna" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 vertikal-linia" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Gajno" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Agordaĵoj pri la gajno de la kanaloj de koloro" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Gajno laÅ­ grizo" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Äœi agordas la gajnon de la griza kanalo" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Gajno laÅ­ ruÄo" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Äœi agordas la gajnon de la ruÄa kanalo" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Gajno laÅ­ verdo" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Äœi agordas la gajnon de la verda kanalo" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Gajno laÅ­ bluo" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Äœi agordas la gajnon de la blua kanalo" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer-punktismo 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer-punktismo 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Meznuanca punkto 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Meznuanca punkto 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Difuzo de Eraro" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Moduso 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Moduso 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Moduso 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "El blanka batoneto" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Milda" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Malalta" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Meza" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Alta" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Unu paÄo" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Ĉiuj paÄoj" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "skaner kun aÅ­tomata provizilo" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Grizgamo je 4 bitoj" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Grizgamo je 8 bitoj" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Ombroj, meznuancoj, kontrasto, ekspontempo" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Specialaj opcioj" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Ekvilibrigo de koloro" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Malebligu malavancon" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Se Äi estas ebligita, la skanilo ne plenumas malavancon" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "ÅœanÄu staton de lampo de skanilo" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Äœi Åaltas aÅ­ elÅaltas la lampon de skanilo" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Mem-kalibrigo" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Se Äi estas ebligita, la kalibrigo de koloro estas farita de " "internainterfaco" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Uzu adaptilon de lumbildoj je 35mm" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Äœi elÅaltas la lampon de la skanilo dum la skanado" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Kvalito de skanado" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Maks. kvalito sed min. rapideco" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Rapida skanado" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Maks. rapideco sed min. kvalito" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Mem-aranÄo de sojlo" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Se Äi estas markita, la interna interfaco aÅ­tomate provas determini " "optimuman valoron de sojlo." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Äœi elektas la moduson de korektado de gama." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Fiksa gama" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Äœi uzas la saman valoron de gama por ĉiuj kanaloj." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Skalara gama" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Äœi elektas valoron por korektado de skalara gama." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Skalara gama laÅ­ ruÄo" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Äœi elektas valoron por korektado de skalara gama laÅ­ ruÄa kanalo" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Skalara gama laÅ­ verdo" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Äœi elektas valoron por korektado de skalara gama laÅ­ verda kanalo" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Skalara gama laÅ­ bluo" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Äœi elektas valoron por korektado de skalara gama laÅ­ blua kanalo" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Kanalo" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Elektu bendon de koloro, \"Ĉefa\" signifas ke ĉiuj koloroj eltenas " "influon.saranno influenzati." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Meznuanco" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" "Elektu nivelon de heleco kiu estus konsiderenda kiel \"50% grizo\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Meznuanco laÅ­ ruÄo" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Elektu nivelon de heleco kiu estus konsiderenda kiel \"50% ruÄo\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Meznuanco laÅ­ verdo" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" "Elektu nivelon de heleco kiu estus konsiderenda kiel \"50% verdo\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Meznuanco laÅ­ bluo" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Elektu nivelon de heleco kiu estus konsiderenda kiel \"50% bluo\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Ekvilibrigo de ruÄo" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Faktoro de ekvilibriÄo leÅ­ ruÄo. 100% signifas neniun korekton." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Ekvilibrigo de verdo" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Faktoro de ekvilibriÄo leÅ­ verdo. 100% signifas neniun korekton." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Ekvilibrigo de bluo" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Faktoro de ekvilibriÄo leÅ­ bluo. 100% signifas neniun korekton." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "HardvardefaÅ­lta ekvilibrigo" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" "Äœi re-agordas la valorojn de ekvilibrigo per la defaÅ­taj valoroj " "konservitaj en firmvaro" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Plej malrapida" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Pli malrapida" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Pli rapida" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Plej rapida" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 grajna" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normala" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fajna" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 tre fajna" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normala" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 grajna" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fajna" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 grajna" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normala" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fajna" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normala" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normala" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 personigita" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 personigita" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 personigita" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 personigita" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 personigita" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 personigita" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Rapida griza moduso" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Äœi estas rapida skanado per grizgamo (malalta kvalito)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Äœi mendas ke ĉiuj antaÅ­montroj estu skanitaj per la plej rapida moduso " "(malalta kvalito). Tiu ĉi povus esti sen koloroj aÅ­ kun malalta difino." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Ripozo de la lampo (en minutoj)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Äœi agordas la tempon (en minutoj) post kiu lampo estas elÅaltata." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "ElÅaltu lampon" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Äœi elÅaltas la lampon tuj." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Heleco de ruÄo" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Äœi mastrumas la helecon de la ruÄa kanalo de la akirita bildo." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Heleco de verdo" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Äœi mastrumas la helecon de la verda kanalo de la akirita bildo." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Heleco de bluo" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Äœi mastrumas la helecon de la blua kanalo de la akirita bildo." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Kontrasto de ruÄa kanalo" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Äœi mastrumas la kontraston de la ruÄa kanalo de la akirita bildo." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Kontrasto de verda kanalo" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Äœi mastrumas la kontraston de la verda kanalo de la akirita bildo." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Kontrasto de blua kanalo" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Äœi mastrumas la kontraston de la blua kanalo de la akirita bildo." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Koloro je 48 bitoj" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Koloro je 24 bitoj" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Grizo je 16 bitoj" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Grizo je 8 bitoj" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Reflektita" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positiva filmo" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Äœi varmigas la lampon tiel ke Äia heleco estas sensanÄa anstataÅ­ ĉiufoja " "varmigo je 40 sekundoj." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Negativa filmo" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negativo" #: backend/pixma.c:396 #, fuzzy, no-c-format msgid "48 bits color" msgstr "Fajna koloro" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Skanado mastrumita de butono" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Se Äi estas ebligita, la skanado ne startas tuj. Por plenumi, premu la " "butonon \"SCAN\" (por ML150) aÅ­ \"COLOR\" (por aliaj modeloj). Por " "refuzi, premu la butonon \"GRAY\"." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Äœisdatigu staton de butono" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Butono 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Butono 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Diafaneco" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Agordoj de aparato" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Butono de lampo" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Mane Åalto de la lampo(j)." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "ElÅaltita lampo dum kalibrigo de nigro" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Äœi ĉiam elÅaltas la lampon dum la kalibrigo de nigro." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "KaÅmemoro por kalibrigo" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Äœi ebligas aÅ­ malebligas kaÅmemoron por kalibrigo." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Plenumu kalibrigon" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Sentilo de akcelo" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Äœi ebligas aÅ­ malebligas movadon de la sentilo de akcelo." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Tempo de varmigo" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Tempo en sekundoj por varmigi la lampon." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Ripoztempo de lampo" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Tempo en sekundoj dum kiu la lampo restas elÅaltata." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Analoga fasado" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Valoro de gajno laÅ­ ruÄo de la analoga fasado" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "DeÅovo laÅ­ ruÄo" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Valoro de deÅovo laÅ­ ruÄo de la analoga fasado" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Valoro de gajno laÅ­ verdo de la analoga fasado" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Valoro de deÅovo laÅ­ verdo de la analoga fasado" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Valoro de gajno laÅ­ bluo de la analoga fasado" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Valoro de deÅovo laÅ­ bluo de la analoga fasado" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "RuÄa lampo elÅaltita" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Äœi agordas la parametron pri elÅaltado de la ruÄa lampo" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "RuÄa lampo elÅaltita" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Äœi agordas la parametron pri elÅaltado de la verda lampo" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "RuÄa lampo elÅaltita" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Äœi agordas la parametron pri elÅaltado de la blua lampo" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Tiuj ĉi opcioj agas sur la stato de la butonoj de la skanilo." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Koloro je 36 bitoj" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Punktismmapo 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Punktismmapo 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Aleatorigu" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Elekto de Fonto" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Plibonigo de Bildo" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Grizigu" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Äœi Åargas la bildon kiel grizgaman" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Simulado de 3-pasa skanilo" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Äœi simulas akiradon en tri pasadoj per reveno de tri bildoj: unue la " "verda, poste la blua kaj fine la ruÄa." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Simulado de mana skanilo" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Äœi simulas akiradon per mana skanilo. La manaj skaniloj ofte ne rekonas " "la alton de la bildon apriore, do ili revenigas alton kun valoro -1. Per " "tiu ĉi opcio, oni povas testi ke la fasado estas Äuste mastrumita." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Uzu defaÅ­ltajn valorojn por regiloj de plibonigo (kontrasto kaj heleco)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Opcio por nurlega testado" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Äœi kontrolas ke la fasado plenumas tion korekte aÅ­ ne." #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Tabeloj de Gama" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Simulado de valoro pri stato" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Ne perfortu la valoron pri stato" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Ne perfortu la internan interfacon revenigi valoron pri stato." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Revenigu SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Äœi perfortas la internan interfacon revenigi la valoron pri stato " "SANE_STATUS_EOF post la alvoko de la funkcio sane_read()." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Revenigu SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Äœi perfortas la internan interfacon revenigi la valoron pri stato " "SANE_STATUS_JAMMED post la alvoko de la funkcio sane_read()." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Revenigu SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Äœi perfortas la internan interfacon revenigi la valoron pri stato " "SANE_STATUS_NO_DOCS post la alvoko de la funkcio sane_read()." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Revenigu SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Äœi perfortas la internan interfacon revenigi la valoron pri stato " "SANE_STATUS_COVER_OPEN post la alvoko de la funkcio sane_read()." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Revenigu SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Äœi perfortas la internan interfacon revenigi la valoron pri stato " "SANE_STATUS_IO_ERROR post la alvoko de la funkcio sane_read()." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Revenigu SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Äœi perfortas la internan interfacon revenigi la valoron pri stato " "SANE_STATUS_NO_MEM post la alvoko de la funkcio sane_read()." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Revenigu SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Äœi perfortas la internan interfacon revenigi la valoron pri stato " "SANE_STATUS_ACCESS_DENIED post la alvoko de la funkcio sane_read()." #: backend/rts8891.c:2809 #, fuzzy, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Tiuj ĉi opcioj agas sur la stato de la butonoj de la skanilo." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Åœaltu lampon" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Äœi Åaltas la lampon de la skanilo" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "ElÅaltu lampon" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Äœi elÅaltas la lampon de la skanilo" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Tempo antaÅ­ la ripozo de la lampo" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" "Nombro da minutoj pasantaj inter la skanado kaj la elÅalto de la lampo" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Valoro de sojlo por duuma moduso" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Provizilo por dokumentoj" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 coloj (~15x10 cm)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 coloj (~20x25 cm)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 coloj (~21x28 cm)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Mez-nuancoj Nesubtenitaj" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Nombro da skanaj linioj necesaj por SCSI-legado. ÅœanÄante tiun ĉi " "parametron, oni ebligas agordi la rapidecon laÅ­ kiu la datumoj estas " "legataj dum la skanado. Se tiu valoro estas tro malalta, la skanilo " "povus halti de tempo al tempo en la mezo de la skanado; se tiu valoro " "estas tro alta, X-bazitaj fasadoj povus halti respondante al X-eventoj, " "kaj do tiu povus kraÅi aÅ­ bloki la sistemon." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Äœi elpelas la dokumento post la skanado" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Moduso de antaÅ­montro" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Äœi elektas la moduson de la antaÅ­montro: grizgama antaÅ­montro kutime " "donas la plej bonan kompromison inter rapideco kaj detaleco." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "AntaÅ­determinitaj valoroj" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Äœi havigas standartajn areojn de skanado por fotoj, presitaj paÄoj k.t.p." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "plata skanilo" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Fokuso" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Mem-fokusigo" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "LokiÄo de Fokusigo" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "LokiÄo de Fokusigo" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Koloraj linioj por ĉiu legado" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Äœrizgamaj linioj por ĉiu legado" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "retkamerao" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "RAW-koloro" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "RGB-koloro" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Koloro RGB-TEKSTO" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Solida negro" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Solida blanko" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Åœablono de koloro" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Krado" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Unua enigo" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Dua enigo" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Tiu ĉi estas tre longa tria enigo. Eble la fasado havas ideon por " "kiamaniere montri Äin." #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Simulado de mana skanilo" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Äœi simulas akiradon per mana skanilo. La manaj skaniloj ofte ne rekonas " "la alton de la bildon apriore. Do, anstataÅ­e ili revenigas alton kun " "valoro -1. Per tiu ĉi opcio, oni povas testi ke la fasado estas Äuste " "mastrumita. Tiu ĉi opcio ebligas ankaÅ­ fiksan alton je 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Simulado de 3-pasa skanilo" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Äœi simulas akiradon (de 3-pasa skanilo) en tri pasadoj. En moduso de " "koloro, Äi redonas tri bildojn." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Agordu ordon por la bildoj" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "" "Äœi agordas la sinsekvon de la bildojn en moduso de koloro de 3-pasa " "skanado." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Se la aÅ­tomata provizilo por dokumentoj estas elektita, la provizilo " "estos malplena post 10 skanadoj." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Specialaj Agordoj" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Elektu la bildon de testo" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Äœi elektas la specon de bildo por testi. La disponeblaj:\n" "Solida nigro: Äi plenigas a tutan areon per nigro.\n" "Solida blanko: Äi plenigas a tutan areon per blanko.\n" "Åœablono de koloro: Äi desegnas diversajn kolorajn test-Åablonojn " "dependantaj de la moduso\n" "Krado: Äi desegnas kradon per blankaj-nigraj fakoj je 10mm." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Inverigu la \"endianness\"" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "InterÅanÄas la superan kaj malsuperan bitojn de datuma bildo en moduso " "de 16 bitoj. Tiu ĉi opcio estas uzebla por testi la 16-bita moduson de " "la fasadoj, t.e. se la fasado korekte uzas la \"endianness\"." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Limo de legado" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Äœi limigas la kvanton da datumoj transigitan kun ĉiu alvoko al " "sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Grando de la legadlimo" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "La (maksimuma) kvanto da datumoj transigita kun ĉiu alvoko al " "sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Malfruo de legado" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Äœi malfruigas la transigon de datumoj al la dukto." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "DaÅ­ro de legad-malfruo" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "Kiom da tempo Äi atendas poste ke oni transigis ĉiun bufron de datumoj " "tra la dukto." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Reven-valoro de sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Äœi elektas la reven-valoron de sane_read(). \"DefaÅ­lta\" estas la " "korekta mastrumo de la skanado. Ĉiuj aliaj stat-kodoj utilas por testi " "kiamaniere la fasado mastrumas ilin." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Bilderperdo por ĉiu linio" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Nombro da bilderoj fuÅuzitaj en la fino de ĉiu linio." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Svagaj parametroj" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Äœi revenigas svagajn liniojn kaj bitojn por ĉiu linio kiam " "sane_parameters() estas alvokata antaÅ­ sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Uszi ne-blokantan eneligon" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Äœi uzas ne-blokantan eneligon por sane_read() se la fasado subtenas Äin." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Proponu la priskribilon de elektita dosiero" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Äœi proponas la priskribilon de dosiero por kontroli se sane_read() " "revenigos datumojn." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Ebligu opciojn por testi" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Äœi ebligas plurajn opciojn por testi. Tio estas uzebla por testi la " "kapablon de la fasado vidi kaj modifi ĉiujn diversajn specojn de opcio " "de SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Presu la opciojn" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Äœi presas la liston de ĉiuj opcioj." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Buleaj opcioj por testi" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Bulea, simbola elektado simbola rekonado" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Bulea test-opcio kiu havas simbola-elektantan kaj simbola-" "rekonantan (kaj avanajn) kapablojn. Äœi estas ordinara bulea opcio." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Bulea, rekta elektado simbola rekonado" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Bulea test-opcio kiu havas rekta-elektantan kaj simbola-" "rekonantan(kaj avanajn) kapablojn. Tio signifas ke la opcio ne estas " "agordebla de la fasado, sed nur de la uzanto mem (t.e. per premo de " "butono sur la aparato).dispositivo)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Bulea, rekta elektado" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Bulea test-opcio kiu havas rekta-elektantan (kaj avanajn) " "kapablojn VTio signifas ke la opcio ne estas agordebla de la fasado, sed " "nur de la uzanto mem (t.e. per premo de butono sur la aparato) kaj Äi ne " "estas legebla de la fasado." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Bulea, simbola rekonado" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Bulea test-opcio kiu havas simbola-rekonantan (kaj avanajn) " "kapablojn. Tio signifas ke la opcio estas nur-legebla." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Bulea, simbola elektado simbola rekonado emulado" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "Bulea test-opcio kiu havas simbola-rekonantan, simbola-elektantan kaj " "emulan (kaj avanajn) kapablojn." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Bulea, simbola elektado simbola rekonado aÅ­tomata" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Bulea test-opcio kiu havas simbola-rekonantan, simbola-elektantan " "kaj aÅ­tomatan kaj avanajn) kapablojn. Tiu ĉi opcio estas aÅ­tomate " "agordebla de la interna intefaco." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Entjeraj test-opcioj" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Entjero" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Entjera test-opcio sen mezurunito kaj trudoj." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Entjera kun intervalo" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Entjera test-opcio kun bilder-unito kaj trudo de intervalo. La " "minimuma valoro estas 4, la maksimuma estas 192, la paÅo estas 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Entjera kun listo" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Entjera test-opcio kun bit-mezurunito kaj trudo de valor-listo." "lista." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Entjera tabelo" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "(4/6) Entjera test-opcio kun mm kaj uzo de iu tabelo sen trudoj." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Entjera tabelo kun intervalo" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Entjera test-opcio kun dpi-mezurunito (punktoj por colo) kaj " "tabelo kiu havas trudon de intervalo. La minimuna valoro estas 4, la " "maksimuma estas 192 kaj la paÅo estas 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Entjera tabelo kun listo" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Entjera test-opcio kun procenta mezurunito kaj tabelo kiu havas " "trudon de listo de valoroj." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Test-opcioj laÅ­ fiksa komo" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Fiksa komo" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) LaÅ­ fiksa komo testopcio sen mezurunito kaj sen trudoj." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Fiksa komo kun intervalo" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) LaÅ­ fiksa komo testopcio kun mezurunito de mikrosekundo kaj trudo " "de intervalo. La minimuma valoro estas -42,17, la maksimuma estas " "32767,9999 kaj la paÅo estas 2,0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3)Fiksa komo kun listo" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) LaÅ­ fiksa komo testopcio sen mezurunito kaj kun trudo de listo de " "valoroj." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Ĉenaj test-opcioj" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) Ĉeno" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Ĉena test-opcio sen trudoj." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) Ĉeno kun listo de ĉenoj" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) Ĉena test-opcio kun trudo de listo de ĉenoj." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) Ĉeno kun longa listo de ĉenoj" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) Ĉena test-opcio kun trudo de listo de ĉenoj. Äœi entenas pli enigoj " "ol la alia ĉena opcio kun listo..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Butonaj test-opcioj" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1)Butono" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Butona test-opcio. Äœi presas tekston..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Koloro je 36 bitoj" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Uzu Kunmetadon de Bildoj" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Du-nivela nigro-blanko (duuma)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Puntkisma/meznuanca nigro-blanko (stompita meznuanco)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Plurnivela nigro-blanko (grizgamo)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Plur-nivela RGB-koloro (unu-pasa koloro)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignoru kalibrigon" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Malebligu preparan fokusigon" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Ne kalibrigu fokusigon" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Mana prepara fokusigo" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Pozicio de fiksa fokuso" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Kalibrigo de la lenso en la lokiÄo de la dokumento" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Kalibrigo de fokuso de la lenso en la lokiÄo de la dokumento" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Fokusigo je 0mm (sur la vitro)" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Uzu fokusiÄon je 0mm anstataÅ­ 0.6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Moduso de kalibrigo" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Difinu moduson de kalibrigo" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Äœi Åaltas/elÅaltas la lampon" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "Åœaltu UTA" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Äœi Åaltas/elÅaltas la reguligilon de diafaneco" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "DeÅovo" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Agordoj de deÅovo laÅ­ kanaloj de koloro" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "DeÅovo laÅ­ grizo" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Äœi agordas la deÅovon de la griza kanalo" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Äœi agordas la deÅovon de la ruÄa kanalo" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Äœi agordas la deÅovon de la verda kanalo" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Äœi agordas la deÅovon de la blua kanalo" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Moduso de antaÅ­montro" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "la problemo ne estis analizita (nekonata SCSI-klaso)" #~ msgid "Grayscale" #~ msgstr "Grizgamo" #~ msgid "Binary" #~ msgstr "Duuma" #~ msgid "Display a shortened resolution list" #~ msgstr "Tio vidigas reduktitan liston pri disponeblaj distingoj" #~ msgid "Black & White" #~ msgstr "Blanka kaj Nigra" sane-backends-1.0.27/po/eo.gmo0000664000175000017500000021534313110600540012745 00000000000000Þ•ü%Ü1pB qB-~B ¬B;¸B ôB,C".CzQC ÌC9ÖCD€-D#®D5ÒD"EÆ+EòEj F xFB™F(ÜFSGYGØpGIHBhH«HlÂH/IJ?I+ŠIc¶I Jz;J'¶J™ÞJ$xKWKõKLL L *L 5L @LKL SL ^LiL rL }L ˆL“L œL §L ²L ½LÊL ÒL àL ìLöL MM ,M 7MBM KM VMÒdM7N :N GNSN WNbNkNzN!‚N¤N!ÄN æNO 'OHOQOsbO ÖO5àO P"P2PDP\PoP€P ˜P!¹PÛPûPQQ &Q 1Q ?QJQ _QiQ!ƒQ¥QºQÎQ<ßQGR_dRÄR=ÔR>S<QSŽS’S˜S¨S'¸SàSéST T T (T4T 9TFT VT`T{T ŠT ˜T¤TÁTÓT%âTU%U =UHUQU ZUgU{U’UšUU­U ±U¾UÑUíU V%V 7VAVSV)nV%˜V ¾VÊVáVøV WW*W:WBWIW&\WăWHXNX^XgX vX „X ‘X ›X¥X ´XÂXßXþXY -Y;YCYKYSY iYuY~Y”Y«YÀYÔYéY6üY.3ZBbZC¥ZAéZ,+[@X[A™[?Û[(\!D\*f\‘\(˜\Á\Ö\è\ð\ù\)]";]$^]*ƒ]#®](Ò]!û]^#;^_^|^ œ^½^IÜ^,&_'S_{_0‹_D¼_``1`K```v`ˆ`š`ª`È`Ï`ä`ú`a/.a ^a ja%vaœa&»aâaùa1bDbTbkb…b˜b«b³b ºbEÆb c#c)cGcbcycˆcc#¸c?Üc!d >d_dsdõd(e+8e0de •e¡e­±e_f yf „f’f0¦f ×fâfúfgg g "g,g3g ;gGg Pg Zgeg jgug †g’g¥g¸g ÀgÍgÓgëgúg hh%5hh[heÄh^*ic‰iaíibOja²j kk0k BkLk]kbkhk yk†k —k)£k*Ík(øk›!l½lÆl Õlàl ålïl ÿl mmm m1mBmQm Wmem vmmm­m ¼mÉmçmnnn%nxXKxÞ¤xƒy]•yóz{L{`{}{„{‡{{°{ Ã{ Î{Û{ú{%|5| >|L|[|u|‰| ‘|ž|¤| Á|MÏ|} 1} >}K}[} k}u} y} „}}M¥}ó} ÷}~~~ 5~ C~ P~[~w~ •~ ~ÖÀ~|— €"€ 4€U€s€Š€¦€À€Û€[õ€Qk } ˆ•§º ËÕåø‚1‚'L‚t‚ †‚ “‚‚ ­‚ ¹‚xÄ‚ =ƒJƒ]ƒ.nƒƒ¶ƒ#˃gW…ô…: †;G†9ƒ†,½†Yê†%D‡j‡F‚‡ɇ/Þ‡*ˆ"9ˆ‡\ˆäˆúˆ'‰<A‰4~‰>³‰Bò‰>5Š?tŠD´Š?ùŠ99‹9s‹=­‹@ë‹=,ŒBjŒ>­Œ>ìŒ?+=k<©æDõ,:ŽgހޒޣŽ?¹ŽùŽ1C;bž±ÁØñ!9Sdz>’?Ñ‘D'‘%l‘4’‘Ç‘)ß‘X ’2b’Ì•’b“i“y“Š“)™“ Ó ΓØ“ì“þ“”%”7”J” `”n”…”ü”Њ•p[–KÌ–—+—1—8—=—D—L— S— ]— i—u—†—–—¦—µ—Зç—û—<˜M˜ j˜ x˜ƒ˜Gœ˜'ä˜u ™=‚™ŒÀ™MšS^š7²š;êš&›<› R› \›}›”› ´›!¿› á›!ì› œœ0œBœUœ gœ uœ–œ¬œÁœáœèœïœ8L[.kšC°ô( ž4žAHžŠž.¨ž&מþž Ÿ)ŸBŸ[ŸdŸtŸ)„Ÿ ®Ÿ`ÏŸ`0  ‘   ¹ Å ¨Ý >†¡‹Å¡ Q¢]¢r¢ˆ¢ œ¢©¢­¢¶¢ ¾¢Ë¢Т ç¢ô¢£)£C£`££”£´£ Ê£×£ë£þ£¤'¤0¤&C¤j¤!†¤¨¤¹¤ˤç¤ ø¤¥!¥/@¥p¥¥˜¥¨¥i¯¥ §.%§T§>e§ ¤§"°§.Ó§ƒ¨ †¨3”¨Ȩ­ç¨•©4µ©,ê©ëª«‡«§«QÁ«%¬o9¬©¬îŬ´­KÌ­®x6®¯®@Ä®6¯e<¯"¢¯±Å¯8w°®°°_±a~±à±ý± ²&² 6²B² R² ^² i²t² „² ޲ š²¥² µ²¿²Õ² å² ñ² þ² ³"³ 9³ C³ N³X³ k³v³ †³ ³ œ³àª³‹´Ž´ ´ª´®´¿´δî´'µ'(µ'Pµ(xµ'¡µ(ɵòµ øµl¶ s¶8€¶ ¹¶ǶÖ¶ë¶··1·"K·#n·#’· ¶·À·з í· ø· ¸¸ *¸!4¸V¸ k¸x¸ˆ¸.š¸;ɸh¹n¹A‚¹BĹBºJºPºVºiº|º›º®ºɺ Þºéºýº »»&»5».E»t»„»›»0­»Þ»ö».¼4¼-C¼q¼x¼¼мš¼®¼˼Ó¼Ö¼ï¼ ó¼ÿ¼½,½H½d½ {½…½/˜½=Ƚ*¾ 1¾ ;¾I¾b¾v¾…¾¾¯¾¶¾½¾'Ð¾ìø¾å¿ì¿þ¿À "À/À AÀ LÀWÀiÀ/À)¯ÀÙÀ#íÀÁ$Á7ÁJÁ]Á|Á …ÁÁ¨ÁÂÁÜÁõÁÂ?)Â-iÂ?—Â@×Â@Ã0YÃBŠÃCÍÃCÄ*UÄ!€Ä*¢Ä ÍÄ5ÙÄÅ.Å BÅLÅ_Å/{Å-«Å'ÙÅ0Æ.2Æ0aÆ.’Æ%ÁÆ/çÆ-Ç9EÇ:Ç:ºÇVõÇ4LÈ3ȵÈ'ÇÈLïÈ<ÉOÉAXÉšÉ¯ÉÆÉãÉõÉ,Ê 2Ê<ÊTÊnÊŒÊ5ªÊàÊïÊ0þÊ'/Ë>WË–Ë ­Ë>ÎË Ì)&ÌPÌkÌ}Ì Ì ™Ì¦Ì4»ÌðÌÍ(Í8ÍXÍsÍ…Í,žÍËÍ;éÍ"%Î.HÎwΕÎ+&Ï*RÏ5}Ï;³Ï ïÏùÏÌ ÐÖÐ òÐ ÿÐ Ñ<'Ñ dÑoÑ ˆÑ“њѮÑÀÑ ÏÑ ÚÑæÑ úÑÒ ÒÒ Ò$Ò AÒLÒdÒ €ÒŒÒœÒ £ÒÄÒØÒîÒ#Ó4&Ó†[ÓƒâÓ|fÔãÔeÕ€åÕfÖ æÖðÖ× ×+×=×C×H×Z×j×|×"‹×$®×$Óךø× “ØØ­Ø´ØºØËØߨòØÙÙÙ1ÙEÙVÙ\ÙqÙÙ/’ÙÂÙÓÙêÙ1ýÙ!/ÚQÚ WÚbÚ|ÚšÚ´ÚÈÚÜÚñÚ ÛÛ4ÛMÛ1fÛ1˜ÛÊÛÚÛßÛõÛÜ'ÜGÜPÜcÜwÜ‹Ü ªÜV¶Ü ÝfÝa{ÝNÝÝ8,Þ³eއߡ߳߹ßÌßÜßíß4à?6àvàà¢à»àËà'åà áá =áKá"]á€á5”áÊá3Úá8âGâMNâœâ$¢âÇâââêâÿâã-ãIãcãhãmãrã ˆã’ã¦ã»ãGÐãä ,ä!:ä\ä |ää¬ä ¾äÊäÓäÜäåä(å",å OåZåcålå{ååœå ´å¾åÎåëåûåæ æ^æêyædç‹uçééW&é+~éªé²é »é Åéæéøé ê#ê7êJêgêvê…ê—ê³ê ÎêÛêòê%øêëK/ë{ëë£ë²ëËë äëïëõëììO0ì€ì†ì›ì«ì/¼ìììýìí1'í&Yí €í*‹íö¶í“­îAïTï"pï“ï³ïÌïêïð#ðs?ð³ðÍðåð îðûðñ*ñBñTñoñ †ñ §ñ Èñ8éñ"ò>òTòfòxò‰ò‡ò %ó/óOó1fó˜ó¶ó=Òó„õ®•õDöB^öC¡öCåö2)÷_\÷/¼÷ì÷_ødø4ø*´ø,ßø‰ ù–ù'ªù$ÒùG÷ù5?úEuúI»úFûFLûK“ûGßû@'üAhüFªüKñüG=ýE…ý@ËýA þANþAþGÒþ ÿI'ÿ9qÿ+«ÿ×ÿëÿ!<&cM~ÌCì01G'y)¡(Ë*ô(*Hs(“*¼ZçIBŒN¨.÷8&_+}`©6 ÆA"5*Hsz–«ÀÖë&'NUÖlmC f±  /  8  B  L Z i o  w  „ ’ ¢ ´ Å × î   O> Ž  ­  » "É Kì $8 l] 7Ê  “ Z¦ >4@u« ±"Ò.õ$17i1| ®¸Ðèü*$%O#u™ ¶ÁÈÛ"õ4I%_…=ž Ü/ý-JH“4¯,ä"4 J k Œ–¥?´&ôeeç ø(*¨SEü}BÀÑì $2 6@ HV[x Ž!œ7¾"ö2)HrŒž²'Ð ø  ."&Q2x«ÃÙù"+"N1q£¿È ؆'=t8eÍåoƒ–eê•áŎ׼H­ŠÀu+ jøyî½Aȇ!zr‹ fRnTlàœûWÝ™Ùõÿ,=I’Õâ„ #¥3pË0|ÊŸ‘ø«J9óôC¾ÝâD '«– 2Œ›¯;ùtçd±ÑÓ2ÛG(½?Ø¢•ÁyÜiNf–&³ÿ°vIð$cÀGÃ⣮¥jþÔ‘d4&´žöä3k\ 0 ìl»·W*ÌLvÅnmÉ€?œ @“aØMDŠQmÒ¯RMü€íº¶¬ÀžhvÅ*gõþ{Ó9w [·²¶-öò:}Q™,"ºI Æí_7´òC²°œ6^f;>k-#xuÙ®Z‹µ%G\ÃãPèã%×.q†—Š#ŽwåÍÁbp+©¶"¾Ö/÷ÔÞôU ‰5| ïcÑŸE‘8Jß´mT¬7<ú¨”UB*ƒÐ” 16ƒ\PñŒÛè{éšuÛÿà r› VéYO’eª ßûž&„˜Éy2di<¹,…®Ç¯4šøN1íù.¼™Pk`]×¾B¦s‡óERÇ÷:w‚¤/SÂëÎÏÐ!ï…NÄiïê{¸Sú~ú]ãësÊ:Üsˆ¥x8¤(µ¡ H²ÕX’ìù)QϤg=o‰Z­æÜ·æ “ û¿¬ðë“”ä>a>µ˜YÇ«¿Fa0< ©^oFÚ ¼1çÖócº/9^Èý‚ˆ§r»Ht¦•¿¨˜Ò¢ß÷ébL.[(ä°b€Ò;Þ}JÎ?î7Ë Tñ—S›å‚WüO[K'¹$þ§…±-†³!£`¸£ìͨð~Új¢`îÆÞ³ÏÕKExÊq» æýL~¹+]OÉÈôö̪­üĪàÚ‹ADZAè%ÌÂXÝ}çpˆõŒ¡@Ñê_ÃÓ$ËÔ@5áŸÐÄ6šMÁ3á)Ʀ_ÎUCY¡ØB‰ý§V½‡4z± òg „ñnhq)F"|Ž—©KÖ5¸XÙÂz lhV(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF DuplexADF ModeADF cover openADF jamAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowChange Document.Change documentChannelCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Correction according to film typeCorrection according to transparency ratioCustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device-SettingsDiamondDisable auto document feeder and use flatbed onlyDisable backtrackingDisable interpolationDisable pre focusDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.EnhancementError DiffusionExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.Ignore calibrationImageImage EnhancementImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOptional equipmentPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset scannerReset the scannerReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSaturationScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Second entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsSpeedup sensorStart calibration process.Status Code SimulationString test optionsSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate optionsUpdate options.Use 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.White levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: sane-backends.eo Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-12-08 13:28+0100 Last-Translator: A.C.Codazzi Language-Team: Language: eo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 1.0.2 (1/1)Butono(1/1) Butona test-opcio. Äœi presas tekston...(1/3) Fiksa komo(1/3) LaÅ­ fiksa komo testopcio sen mezurunito kaj sen trudoj.(1/3) Ĉeno(1/3) Ĉena test-opcio sen trudoj.(1/6) Bulea, simbola elektado simbola rekonado(1/6) Bulea test-opcio kiu havas simbola-elektantan kaj simbola-rekonantan (kaj avanajn) kapablojn. Äœi estas ordinara bulea opcio.(1/6) Entjero(1/6) Entjera test-opcio sen mezurunito kaj trudoj.(2/3) Fiksa komo kun intervalo(2/3) LaÅ­ fiksa komo testopcio kun mezurunito de mikrosekundo kaj trudo de intervalo. La minimuma valoro estas -42,17, la maksimuma estas 32767,9999 kaj la paÅo estas 2,0.(2/3) Ĉeno kun listo de ĉenoj(2/3) Ĉena test-opcio kun trudo de listo de ĉenoj.(2/6) Bulea, rekta elektado simbola rekonado(2/6) Bulea test-opcio kiu havas rekta-elektantan kaj simbola-rekonantan(kaj avanajn) kapablojn. Tio signifas ke la opcio ne estas agordebla de la fasado, sed nur de la uzanto mem (t.e. per premo de butono sur la aparato).dispositivo).(2/6) Entjera kun intervalo(2/6) Entjera test-opcio kun bilder-unito kaj trudo de intervalo. La minimuma valoro estas 4, la maksimuma estas 192, la paÅo estas 2.(3/3)Fiksa komo kun listo(3/3) LaÅ­ fiksa komo testopcio sen mezurunito kaj kun trudo de listo de valoroj.(3/3) Ĉeno kun longa listo de ĉenoj(3/3) Ĉena test-opcio kun trudo de listo de ĉenoj. Äœi entenas pli enigoj ol la alia ĉena opcio kun listo...(3/6) Bulea, rekta elektado(3/6) Bulea test-opcio kiu havas rekta-elektantan (kaj avanajn) kapablojn VTio signifas ke la opcio ne estas agordebla de la fasado, sed nur de la uzanto mem (t.e. per premo de butono sur la aparato) kaj Äi ne estas legebla de la fasado.(3/6) Entjera kun listo(3/6) Entjera test-opcio kun bit-mezurunito kaj trudo de valor-listo.lista.(4/6) Bulea, simbola rekonado(4/6) Bulea test-opcio kiu havas simbola-rekonantan (kaj avanajn) kapablojn. Tio signifas ke la opcio estas nur-legebla.(4/6) Entjera tabelo(4/6) Entjera test-opcio kun mm kaj uzo de iu tabelo sen trudoj.(5/6) Bulea, simbola elektado simbola rekonado emuladoBulea test-opcio kiu havas simbola-rekonantan, simbola-elektantan kaj emulan (kaj avanajn) kapablojn.(5/6) Entjera tabelo kun intervalo(5/6) Entjera test-opcio kun dpi-mezurunito (punktoj por colo) kaj tabelo kiu havas trudon de intervalo. La minimuna valoro estas 4, la maksimuma estas 192 kaj la paÅo estas 2.(6/6) Bulea, simbola elektado simbola rekonado aÅ­tomata(6/6) Bulea test-opcio kiu havas simbola-rekonantan, simbola-elektantan kaj aÅ­tomatan kaj avanajn) kapablojn. Tiu ĉi opcio estas aÅ­tomate agordebla de la interna intefaco.(6/6) Entjera tabelo kun listo(6/6) Entjera test-opcio kun procenta mezurunito kaj tabelo kiu havas trudon de listo de valoroj.Duono de la normala radipecoTriono de la normala radipeco2-bilderoj2x2 personigita2x2 normala3x3 personigita3x3 normala4-bilderoj4x4 grajna4x4 personigita4x4 fajna4x4 normala5x5 grajna5x5 personigita5x5 fajna6x4 coloj (~15x10 cm)6x6 personigita6x6 normala8-bita eligo8-bilderoj8.5x11 coloj (~21x28 cm)8x10 coloj (~20x25 cm)8x8 Bayer8x8 grajna8x8 fajna8x8 vertikal-linia8x8 grajna8x8 personigita8x8 fajna8x8 normala8x8 tre fajnaPli longa ekspontempo ebligas la skanilon preni pli multe da lumo. Oportunajvaloroj estas 175% por presaĵoj, 150% por normalaj lumbildoj kaj "Negativo" por filmoj. Por malhelaj bildoj (subeksponitaj) pliigu tiun ĉi valoro.A4A5 horizontalaA5 verticalaADFFronta-dorsa ADFModuso por ADFKovrilo de ADF estas malfermitaADF estas blokitaAldonu bluon surbaze de nivelo de verdoAldonu bluon surbaze de nivelo de ruÄoAldonu verdon surbaze de nivelo de bluoAldonu verdon surbaze de nivelo de ruÄoAldonu ruÄon surbaze de nivelo de bluoAldonu ruÄon surbaze de nivelo de verdoAvanaAvanaj OpciojPost la sendo de la skan-komando, Äi atendas la premon de la butono de la skanilo por startigi la skanadon.Ĉiuj paÄojÄœi ĉiam elÅaltas la lampon dum la kalibrigo de nigro.Analoga GajnoAnaloga fasadoBluo de analoga gamaKorektado de analoga gamaVerdo de analoga gamaRuÄo de analoga gamaAnaloga korektado de gamaAnaloga korektado de gama por bluoAnaloga korektado de gama por verdoAnaloga korektado de gama por ruÄoAÅ­tomataAÅ­tomata SojloAÅ­tomata segmentado de areoMem-elpeloMem-eksponoMem-fokusigoMemfokusigo nur unu-fojeAÅ­tomataAÅ­tomata Provizilo de DokumentojMem-aranÄo de sojloMem-dividadoAÅ­tomata sojloAÅ­tomata varmigoÄœi aÅ­tomate elpelas filmon post ĉiu skanadoÄœi aÅ­tomate elpelas filmon antaÅ­ la eliro de la programoHeleco, kontrasto, nivelo de blanko, gama, redukto de bruo kaj emfazo de bildo estos aÅ­tomate agorditajLinioj de malavancoFaktoro de ekvilibriÄo leÅ­ bluo. 100% signifas neniun korekton.Faktoro de ekvilibriÄo leÅ­ verdo. 100% signifas neniun korekton.Faktoro de ekvilibriÄo leÅ­ ruÄo. 100% signifas neniun korekton.KestoBayerBayer-punktismo 16Bayer-punktismo 64Du-nivela nigro-blanko (duuma)Bindu RGB-kanalojnBindu distindon de X kaj YBindu analogan gamanFiksa gamaProfundeco en bitojNivelo de nigroBluoEkvilibrigo de bluoHeleco de bluoGajno laÅ­ bluoValoro de gajno laÅ­ bluo de la analoga fasadoIntenso de bluoRuÄa lampo elÅaltitaDeÅovo laÅ­ bluoValoro de deÅovo laÅ­ bluo de la analoga fasadoBuleaj opcioj por testiSube-dekstre XSuba-dekstra posicio de X en areo de skanado..Sube-dekstre YSuba-dekstra posicio de Y en areo de skanado.HelecoButono 1Butono 2Stato de butonoButonaj test-opciojSkanado mastrumita de butonoButonojKDEraro de kontrolo de CPUCRTCRT ekranojKal. ekspontemponKal. ekspontempon por bluoKal. ekspontempon por verdoKal. ekspontempon por ruÄoKal. potencon de lampoKalibriguKalibrigu SkanilonKalibrigu la skanilon antaÅ­ la venonta skanadoKalibrigo de fokuso de la lenso en la lokiÄo de la dokumentoKalibrigu la nivelojn de nigro kaj blanko.KalibrigoMem-kalibrigoKaÅmemoro por kalibrigoModuso de kalibrigoTuja kalibrigoÄœi Åangas dokumenton.Åœangu dokumentonKanaloGrajnaGrajneca kalibrigoGrajneca kalibrigo nur por unua skanadoLa grajneca kalibrigo plenumas nur laÅ­ la unua skanado. Äœi funkcias kun la plejmulto de skaniloj kaj Äi Åparas multe da tempo. Malebligu tiu ĉi opcio se la heleco estas malsama en ĉiu skanita bildo. Äœi estas uzenda nur por testi.KoloroKoloro (48 bitoj)Koloro je 36 bitojMeznuanca KoloroDuuma KoloroMatrico de KoloroRAW-koloroRGB-koloroKoloro RGB-TEKSTOEkvilibrigo de koloroAgordaĵoj pri la gajno de la kanaloj de koloroAgordoj de deÅovo laÅ­ kanaloj de koloroKorektado de koloroKoeficientoj de korektado de koloroÅœablono de koloroKoloro je 24 bitojKoloro je 36 bitojKoloro je 48 bitojKoloraj linioj por ĉiu legadoKondiĉaKontrastoKontrasto de blua kanaloKontrasto de verda kanaloKontrasto de ruÄa kanaloMastrumu nivelon de bluoMastrumu nivelon de verdoMastrumu nivelon de ruÄoÄœi kontrolas la nuancon (nivelon de bluo) de la akirita bildo.Äœi kontrolas la helecon de la akirita bildo.Äœi mastrumas la helecon de la blua kanalo de la akirita bildo.Äœi mastrumas la helecon de la verda kanalo de la akirita bildo.Äœi mastrumas la helecon de la ruÄa kanalo de la akirita bildo.Äœi kontrolas la kontraston de la akirita bildo.Äœi mastrumas la kontraston de la blua kanalo de la akirita bildo.Äœi mastrumas la kontraston de la verda kanalo de la akirita bildo.Äœi mastrumas la kontraston de la ruÄa kanalo de la akirita bildo.Kontrolu ke la malavanco estas perfortita.Korektado rilata al la filmospecoKorektado rilata al la rejÅo de diafanecoPersonigitaPersonigita matrico de koloro por grizgamaj skanadoj.Personigita matrico de koloro.Opcioj de SencimigoDefaÅ­ltoDefaÅ­ltaj valorojDifinu moduson de kalibrigoDifinu la ekspontempon por la kalibrigo de bluoDifinu la ekspontempon por la skanado de bluoDifinu la ekspontempon por la kalibrigoDifinu la ekspontempon por la kalibrigo de verdoDifinu la ekspontempon por la skanado de verdoDifinu la ekspontempon por la kalibrigo de ruÄoDifinu la ekspontempon por la skanado de ruÄoDifinu la ekspontempon por la skanadoDefinu la intenson de la lampo por la kalibrigoDefinu la intenson de la lampo por la skanadoÄœi agordas la parametron pri elÅaltado de la blua lampoÄœi agordas la parametron pri elÅaltado de la verda lampoÄœi agordas la parametron pri elÅaltado de la ruÄa lampoÄœi agordas la modelon por meznuanco (stompado/punktismo) uzata kun neznuancaj bildoj.Äœi agordas la faktoron de zomo kiun la skanilo uzosÄœi malfruigas la transigon de datumoj al la dukto.Regilo de densecoÄœi determinas la rapidecon de skanado.Äœi determinas uzi antaÅ­difinitan tabelon de gama aÅ­ personigitan tabelon.Agordoj de aparatoDiamantoÄœi malebligas provizilon de dokumentoj kaj uzas nur fiksan ebenoMalebligu malavanconMalebligu interpoladonMalebligu preparan fokusigonDispersedDot16x16DispersedDot8x8Vidigu etan liston pri disponeblaj distingojPunktismoPunktismo A (4x4 Bayer)Punktismo B (4x4 Spiralo)Punktismo C (4x4 Reta ekrano)Punktismo D (8x4 Reta ekrano)Puntkisma/meznuanca nigro-blanko (stompita meznuanco)Punktismmapo 1Punktismmapo 2Äœi plenumas grizgaman anstataÅ­ kolora skanadonPlenumu kvalitan kalibrigon laÅ­ blankoÄœi plenumas memfokusigon nur unu-foje por ĉiu enigo de filmoNe kalibrigu fokusigonNe perfortu la valoron pri statoNe perfortu la internan interfacon revenigi valoron pri stato.Provizilo por dokumentojAliaj agordoj pri provizilo de dokumentojDuobligu Optikan DistingonElÅutu modelon AElÅutu modelon BEskludadoFronta-dorsaFronta-dorsa skanadoÄœi plenumas frontan-dorsan skanadon de la dokumentoDaÅ­ro de legad-malfruoElpeloÄœi elpelas la dokumento post la skanadoElpelu filmon post ĉiu skanadoElpelu filmon antaÅ­ eliriElpelu filmon nunÄœi elpelas filmon *nun*Äœi elpelas la folion el aÅ­tomata proviziloEbligu frontan-dorsan skanadoÄœi elbligas aÅ­tomatan elekton de sojlo por duuma skanado.Ebligu la elektadon de ekspontempoEbligu la elektadon de la intenson de la lampoEbligu opciojn por testiÄœi ebligas plurajn opciojn por testi. Tio estas uzebla por testi la kapablon de la fasado vidi kaj modifi ĉiujn diversajn specojn de opcio de SANE.Äœi ebligas/malebligas aÅ­tomatan fokusigonÄœi ebligas/malebligas aÅ­tomatan ekspononÄœi ebligas aÅ­ malebligas kaÅmemoron por kalibrigo.Äœi ebligas aÅ­ malebligas movadon de la sentilo de akcelo.PlibonigoDifuzo de EraroInterÅanÄas la superan kaj malsuperan bitojn de datuma bildo en moduso de 16 bitoj. Tiu ĉi opcio estas uzebla por testi la 16-bita moduson de la fasadoj, t.e. se la fasado korekte uzas la "endianness".Äœi plenumas kalibrigon tujEksperimentoEkspontempoProkastu elÅalton de lampoÄœi prokastas elÅalton de lampo (de 15 minutoj Äis 1 horo)Tre RapidaAliaj aranÄoj de koloroEkstraĵojRapidaRapida griza modusoTuja antaÅ­montroRapida skanadoPli rapidaPlej rapidaModuso de proviziloDosiernomoFilmoFilmoFajnaFajna koloroHardvardefaÅ­lta ekvilibrigoUnua enigoPozicio de fiksa fokusoTest-opcioj laÅ­ fiksa komoFiksa ebenoNur fiksa ebenoFokusoFokusigo je 2.5mm super la vitroLokiÄo de FokusigoFokusigo sur la vitroPerfortu malavanconPerfortu monokromatan antaÅ­montronÄœi devigas kalibrigon de skanilon antaÅ­ la skanadoÄœi perfortas la internan interfacon revenigi la valoron pri stato SANE_STATUS_ACCESS_DENIED post la alvoko de la funkcio sane_read().Äœi perfortas la internan interfacon revenigi la valoron pri stato SANE_STATUS_COVER_OPEN post la alvoko de la funkcio sane_read().Äœi perfortas la internan interfacon revenigi la valoron pri stato SANE_STATUS_EOF post la alvoko de la funkcio sane_read().Äœi perfortas la internan interfacon revenigi la valoron pri stato SANE_STATUS_IO_ERROR post la alvoko de la funkcio sane_read().Äœi perfortas la internan interfacon revenigi la valoron pri stato SANE_STATUS_JAMMED post la alvoko de la funkcio sane_read().Äœi perfortas la internan interfacon revenigi la valoron pri stato SANE_STATUS_NO_DOCS post la alvoko de la funkcio sane_read().Äœi perfortas la internan interfacon revenigi la valoron pri stato SANE_STATUS_NO_MEM post la alvoko de la funkcio sane_read().El paperoEl blanka batonetoAtendante frontan butononPlena skanadoSvagaj parametrojGajnoGamaKorektado de GamaTabeloj de GamaKorektado de gamaValoro de GamaTabelo de gama-korektado laÅ­ bluoTabelo de gama-korektado laÅ­ verdo.Tabelo de gama-korektado laÅ­ ruÄo.Tabelo de gama-korektado. En moduso de koloro tiu ĉi opcio efikas samtempe sur 3 kanaloj (ruÄo, verdo, bluo) kaj do Äi estas gama-tabelo de intenseco. GeometrioGeometria GrupoGrajnoGrizoGajno laÅ­ grizoKoloro por grizgamoDeÅovo laÅ­ grizoGrizo je 16 bitojGrizo je 8 bitojGriziguGrizgamo je 4 bitojGrizgamo je 8 bitojGrizgama skanadoVerdoEkvilibrigo de verdoHeleco de verdoGajno laÅ­ verdoValoro de gajno laÅ­ verdo de la analoga fasadoIntenso de verdoRuÄa lampo elÅaltitaDeÅovo laÅ­ verdoValoro de deÅovo laÅ­ verdo de la analoga fasadoÄœrizgamaj linioj por ĉiu legadoKradoMeznuancojMeznuanco A (Duraj tonoj)Meznuanco B (Delikataj tonoj)Meznuanco C (Reta ekrano)Meznuanca punkto 32Meznuanca punkto 64Modelo por meznuancoGrado de modelo por meznuancojMeznuancojMez-nuancoj NesubtenitajSimulado de mana skaniloSimulado de mana skaniloHardvara interna pozicio de X en la skanada areo.Hardvara interna pozicio de Y en la skanada areo.Hardvara difinoAltaAltkontrasta printadoAltdensa printadoMaks. kvalito sed min. rapidecoMaks. rapideco sed min. kvalitoLumbriloLumbrilo laÅ­ bluoLumbrilo laÅ­ verdoLumbrilo laÅ­ ruÄoFokusigo je 0mm (sur la vitro)HorizontalaKiom da tempo Äi atendas poste ke oni transigis ĉiun bufron de datumoj tra la dukto.NuancoSe la aÅ­tomata provizilo por dokumentoj estas elektita, la provizilo estos malplena post 10 skanadoj.Se Äi estas markita, la interna interfaco aÅ­tomate provas determini optimuman valoron de sojlo.Se Äi estas ebligita, la kalibrigo de koloro estas farita de internainterfacoSe Äi estas ebligita, la skanilo ne plenumas malavanconSe Äi estas ebligita, oni plemunas nur la korektadon de ombroj dum kalibrigo. La defaÅ­ltaj valoroj (aÅ­ tiuj en la agorddosiero) estos uzataj por gajno, deÅovo kaj ekspontempo.Se Äi estas ebligita, la skanilo estos kalibrigita antaÅ­ la venonta skanado. Alie la kalibrigo plenumiÄos nur antaÅ­ la unua starto.Ignoru kalibrigonBildoPlibonigo de BildoEmfazo de bildoIntenso de bildoKontaktaj printilojUzu la samajn valorojn por ĉiu koloro en RGB-modusoÄœi pliigas aÅ­ malpliigas la analogan gajnon de la CCD-sentiloInkoÅprucaj printilojEntjeraj test-opciojInverigu la "endianness"ElÅaltu lamponElÅaltu lampon kaj eliruElÅaltita lampo dum kalibrigo de nigroRipozo de lampoRipozo de la lampo (en minutoj)Åœaltu lamponStato de la lampoTempo antaÅ­ la ripozo de la lampoRipoztempo de lampoTempo en sekundoj dum kiu la lampo restas elÅaltata.Butono de lampoKalibrigo de la lenso en la lokiÄo de la dokumentoÄœi kontrolas ke la fasado plenumas tion korekte aÅ­ ne.LeteroÄœi limigas la kvanton da datumoj transigitan kun ĉiu alvoko al sane_read().DuumaÄœi Åargas la bildon kiel grizgamanBilderperdo por ĉiu linioMalaltaMalaltdensa printadoLokado de mana fokusigoMana prepara fokusigoMane Åalto de la lampo(j).Matrica multipliko de RGBMaksBazoMezaMastrumado de aparatoMeznuancoMeznuanco laÅ­ bluoMeznuanco laÅ­ verdoMeznuanco laÅ­ ruÄoNombro da minutoj pasantaj inter la skanado kaj la elÅalto de la lampoSpegulu horizontaleSpegula bildoÄœi reflektas bildon horizontale.Äœi reflektas bildon vertikale.Äœi reflektas bildon horizontaleSpegulu bildonSpegulu vertikaleDiversaĵojModuso 1Moduso 2Moduso 3Matrico de Monokromata KoloroPlur-nivela RGB-koloro (unu-pasa koloro)Plurnivela nigro-blanko (grizgamo)NTSC-GrizoNTSC RGBNegativoNegativa filmoNegativa lumbildoNegativa filmoSpeco de negativa filmoNegativojNeniu korektadoNeniu korektado de diafanecoRedukto de bruoNenioNormalaNormala rapidecoNombro da bitoj por specimeno, kutima valoro estas 1 por "duuma" kaj 8 por multbitaj skanadoj.Nombro da linioj kiujn retroiras la skan-Åovpeco dum la malavanco. Tio okazas se la skanilo estas pli rapida ol komputilo kiu ricevas datumojn. Malaltaj valoroj ebligas pli rapidan skanadon sed pliigas la riskon pri mankantaj linioj.Nombro da opciojNombro da skanaj linioj necesaj por SCSI-legado. ÅœanÄante tiun ĉi parametron, oni ebligas agordi la rapidecon laÅ­ kiu la datumoj estas legataj dum la skanado. Se tiu valoro estas tro malalta, la skanilo povus halti de tempo al tempo en la mezo de la skanado; se tiu valoro estas tro alta, X-bazitaj fasadoj povus halti respondante al X-eventoj, kaj do tiu povus kraÅi aÅ­ bloki la sistemon.Nombro da skanendaj filmerojElkludaÄœi proponas la priskribilon de dosiero por kontroli se sane_read() revenigos datumojn.Proponu la priskribilon de elektita dosieroDeÅovoKonduktaUnu paÄoPlenumu nur korektadon de ombrojAkcesora ekipaĵoGrando de folioTrapasantaÄœi plenumas aÅ­tomatajn kontrolojnPlenumu kalibrigonGrando de folio en proviziloPositiva filmoPozitiva filmoPozitiva lumbildoPozitiva aÅ­ negativa filmoAntaÅ­determinitaj valorojAntaÅ­montroModuso de antaÅ­montroPresuÄœi presas la liston de ĉiuj opcioj.Presu la opciojnÄœi havigas standartajn areojn de skanado por fotoj, presitaj paÄoj k.t.p.Kvalito de kalibrigoKvalito de skanadoFormato rapidoEraro de kontrolo de RAMEraro de kontrolo de ROMAleatoriguKrudaMalfruo de legadoLimo de legadoOpcio por nurlega testadoÄœi estas nurlega opcio kiu priskribas kiom da opcioj subtenas specifa aparato.RuÄoEkvilibrigo de ruÄoHeleco de ruÄoGajno laÅ­ ruÄoValoro de gajno laÅ­ ruÄo de la analoga fasadoIntenso de ruÄoRuÄa lampo elÅaltitaDeÅovo laÅ­ ruÄoValoro de deÅovo laÅ­ ruÄo de la analoga fasadoÄœi reduktas bruon de izolitaj punktojReflektitaÄœi mendas antaÅ­montra-kvalitan skanadon.Äœi mendas ke ĉiuj antaÅ­montroj estas plenumitaj per monokromata moduso. Kun 3-pasoj-skanilo, Äi reduktas la nombron da pasadoj al unu, kaj do kun 1-paso-skaniloÄi malpliigas la memoron kiu necesas kaj la tempo de skanado por la antaÅ­montro.Äœi mendas ke ĉiuj antaÅ­montroj estu skanitaj per la plej rapida moduso (malalta kvalito). Tiu ĉi povus esti sen koloroj aÅ­ kun malalta difino.Re-agordu skanilonÄœi ree agordas la skanilonRevenigu SANE_STATUS_ACCESS_DENIEDRevenigu SANE_STATUS_COVER_OPENRevenigu SANE_STATUS_EOFRevenigu SANE_STATUS_IO_ERRORRevenigu SANE_STATUS_JAMMEDRevenigu SANE_STATUS_NO_DOCSRevenigu SANE_STATUS_NO_MEMÄœi revenigas svagajn liniojn kaj bitojn por ĉiu linio kiam sane_parameters() estas alvokata antaÅ­ sane_start().Reven-valoro de sane_readeraro de pareco de SCSISaturadoSkalara gamaSkalara gama laÅ­ bluoSkalara gama laÅ­ verdoSkalara gama laÅ­ ruÄoModuso de SkanadoGrupo de Moduso de SkanadoEkspontempo de skanadoEkspontempo de skanado por verdoEkspontempo de skanado por verdoEkspontempo de skanado por ruÄoÄœi estas rapida skanado per grizgamo (malalta kvalito).Potenco de lampo en skanadoMarÄenoj por skanadoModuso de skanadoDifino de skanadoFonto de skaniloRapideco de skaniloÄœi skanas la tutan areon, do Äi skanas ankaÅ­ la strion de kalibrigo. Atentu. Ne elektu plenan alton. Äœi estas uzenda nur por testi.Dua enigoÄœi elektas la keston por skaniElektu specon de filmoAgordu minimuman helecon por havi blankan punktonElektu filtrilon por glatigi.Äœi elektas specon de filmoÄœi elektas la specon de bildo por testi. La disponeblaj: Solida nigro: Äi plenigas a tutan areon per nigro. Solida blanko: Äi plenigas a tutan areon per blanko. Åœablono de koloro: Äi desegnas diversajn kolorajn test-Åablonojn dependantaj de la moduso Krado: Äi desegnas kradon per blankaj-nigraj fakoj je 10mm.Äœi elektas la moduson de la antaÅ­montro: grizgama antaÅ­montro kutime donas la plej bonan kompromison inter rapideco kaj detaleco.Äœi elektas la reven-valoron de sane_read(). "DefaÅ­lta" estas la korekta mastrumo de la skanado. Ĉiuj aliaj stat-kodoj utilas por testi kiamaniere la fasado mastrumas ilin.Elektu la bildon de testoÄœi elektas valoron por korektado de skalara gama laÅ­ blua kanaloÄœi elektas valoron por korektado de skalara gama laÅ­ verda kanaloÄœi elektas valoron por korektado de skalara gama laÅ­ ruÄa kanaloÄœi elektas valoron por korektado de skalara gama.Äœi elektas la "grajneco" de la akirita bildo. Malpli grandaj valoroj donas pli netajn bildojn.Äœi elektas la ADF-moduso (unuopa/fronta-dorsa)Äœi elektas la helecon.Elektu bendon de koloro, "Ĉefa" signifas ke ĉiuj koloroj eltenas influon.saranno influenzati.Äœi elektas la eskludadon.Äœi elektas specon de filmo: negativoj aÅ­ lumbildojÄœi elektas la kurbon de korektado de gamaÄœi elektas la moduson de korektado de gama.Äœi elektas korektadon de gama el listo de antaÅ­difinitaj aparatoj aÅ­ el la personigita tabelo, kiu esti alÅutebla en skanilon scannerElektu meznuancojn.Äœi elektas la specon de negativa filmoElektu nombron da skanendaj filmerojÄœi elektas la moduson de skanado (ekz. duuma, monokromata aÅ­ koloro).Äœi elektas la fonton por la skanado (ekz. provizilo)Äœi elektas la nivelon de blua heleco kiu estas konsiderenda "nigro".Äœi elektas la nivelon de blua heleco kiu estas konsiderenda "tuta bluo".Äœi elektas la nivelon de blua heleco kiu estas konsiderenda "blanko".Äœi elektas la nivelon de verda heleco kiu estas konsiderenda "nigro".Äœi elektas la nivelon de verda heleco kiu estas konsiderenda "tuta verdo".Äœi elektas la nivelon de verda heleco kiu estas konsiderenda "blanko".Äœi elektas la nivelon de heleco kiu estas konsiderenda "nigro".Äœi elektas la nivelon de heleco kiu estas konsiderenda "blanko".Äœi elektas la nivelon de ruÄa heleco kiu estas konsiderenda "nigro".Äœi elektas la nivelon de ruÄa heleco kiu estas konsiderenda "tuta ruÄo".Äœi elektas la nivelon de ruÄa heleco kiu estas konsiderenda "blanko".Äœi elektas se la akirita bildon devas esti neznuancigita (stompita).Elektu nivelon de heleco kiu estus konsiderenda kiel "50% bluo".Elektu nivelon de heleco kiu estus konsiderenda kiel "50% grizo".Elektu nivelon de heleco kiu estus konsiderenda kiel "50% verdo".Elektu nivelon de heleco kiu estus konsiderenda kiel "50% ruÄo".Äœi elektas la skan-koloron uzendan por la grizgamo (defaÅ­lto: verdo).Mem-diagnozoUzu defaÅ­ltajn valorojn por regiloj de plibonigo (kontrasto kaj heleco).Uzu la defaÅ­ltajn valorojn por la regilojn de plibonigo.Äœi ebligas moduson de la regado de densecoAgordu ekspontemponAgordu potencon de lampoÄœi agordas la valoron de neteco.Äœi mane agordas lokadon de optika fokusigo (defaÅ­to: 128).Agordu ordon por la bildojÄœi agordas la sinsekvon de la bildojn en moduso de koloro de 3-pasa skanado.Äœi agordas matricon de koloro.Äœi agordas la tempon (en minutoj) post kiu lampo estas elÅaltata.Agordu specon de bazo.Äœi Åaltas/elÅaltas la reguligilon de diafanecoÄœi agordas la gajnon de la blua kanaloÄœi agordas la deÅovon de la blua kanaloÄœi agordas la gajnon de la griza kanaloÄœi agordas la deÅovon de la griza kanaloÄœi agordas la gajnon de la verda kanaloÄœi agordas la deÅovon de la verda kanaloÄœi Åaltas/elÅaltas la lamponÄœi agordas la gajnon de la ruÄa kanaloÄœi agordas la deÅovon de la ruÄa kanaloÄœi re-agordas la valorojn de ekvilibrigo per la defaÅ­taj valoroj konservitaj en firmvaroÄœi ebligas la tabelon de la korektado de koloro por la elektita aparato.Agordu moduson de proviziloÄœi agordas la lokiÄon de la fokusigo aÅ­ sur la vitro aÅ­ je 2,5mm super ÄiÄœi agordas valoron de gama por ĉiuj kanaloj.Äœi agordas la horizontalan difinon de la skanita bildo.Äœiu ebligas emfazon de bildoÄœi agordas la difinon de la skanita bildo.Äœi agordas la grandon de modelo por meznuanco (stompado/punktismo) uzata kun neznuancaj bildoj.Äœi agordas la vertikalan difinon de la skanita bildo.Äœi agordas gajnon kaj deÅovon por aÅ­tomate skani. Se tiu ĉi opcio estas malebligita, mane agordado de la parametroj estas ebligita. Tiu ĉi opcio estas defaÅ­lta. Äœi estas uzenda nur por testi.OmbrumoOmbrumo laÅ­ bluoOmbrumo laÅ­ verdoOmbrumo laÅ­ ruÄoOmbroj, meznuancoj, kontrasto, ekspontempoNetecoNetecoÅœovu bluon al verdoÅœovu bluon al ruÄoÅœovu verdon al bluoÅœovu verdon al ruÄoÅœovu ruÄon al bluoÅœovu ruÄon al verdoListeto pri distingojElÅaltu lamponÄœi elÅaltas la lampon de la skanilo.UnuopaÄœi simulas akiradon per mana skanilo. La manaj skaniloj ofte ne rekonas la alton de la bildon apriore. Do, anstataÅ­e ili revenigas alton kun valoro -1. Per tiu ĉi opcio, oni povas testi ke la fasado estas Äuste mastrumita. Tiu ĉi opcio ebligas ankaÅ­ fiksan alton je 11 cm.Äœi simulas akiradon per mana skanilo. La manaj skaniloj ofte ne rekonas la alton de la bildon apriore, do ili revenigas alton kun valoro -1. Per tiu ĉi opcio, oni povas testi ke la fasado estas Äuste mastrumita.Äœi simulas akiradon en tri pasadoj per reveno de tri bildoj: unue la verda, poste la blua kaj fine la ruÄa.Äœi simulas akiradon (de 3-pasa skanilo) en tri pasadoj. En moduso de koloro, Äi redonas tri bildojn.Grando de la legadlimoLumbildoLumbildojMalrapidaPli malrapidaPlej malrapidaMildaGlatigoSolida negroSolida blankoElekto de FontoSpecialaj AgordojSpecialaj opciojSentilo de akceloStartigu kalibrigadon.Simulado de valoro pri statoĈenaj test-opciojInterÅanÄu blankon kaj nigronÄœi evligas/malebligas la reguligilon de diafaneco (FAU, «film adapter unit»)Åœaltu aÅ­ elÅaltu la lampon.TMA-NegativojTMA-LumbildojTeknologio por Plibonigo de TekstoLa (maksimuma) kvanto da datumoj transigita kun ĉiu alvoko al sane_read().La dosiernomo de la Åargenda bildo.La lampo estos elÅaltata post la fiksita tempo (en minutoj). La valoro signifas ke la lampo neniam ripozos.Nombro da bilderoj fuÅuzitaj en la fino de ĉiu linio.La nivelo de saturado mastrumas la kvanton da "florado" kiu okazas kiam oni akiras bildon per kamerao. Pli larÄaj valoroj kaÅ­zas pli floradon.Termikaj printilojTiu ĉi estas tre longa tria enigo. Eble la fasado havas ideon por kiamaniere montri Äin.Tiuj ĉi opcioj agas sur la stato de la butonoj de la skanilo.Äœi elÅaltas la lampon de la skanilo dum la skanadoSimulado de 3-pasa skaniloSimulado de 3-pasa skaniloSojloValoro de sojlo por duuma modusoÅœanÄu staton de lampo de skaniloÄœi Åaltas aÅ­ elÅaltas la lampon de skaniloSupre-maldekstre XSupra-maldekstra posicio de X en areo de skanado.Supre-maldekstre YSupra-maldekstra posicio de Y en areo de skanado.Diafanecoreguligilo de DiafanecoReguligilo de DiafanecoRejÅo de diafanecoReguligilo de diafanecoElÅaltu lamponElÅaltu la lampon elirante de la programoÄœi elÅaltas la lampon de la skaniloÄœi Åaltas la lampon de la skaniloÄœi elÅaltas la lampon tuj.Åœaltu UTAElpeluElpelu Dokumenton.Elpelu bazon post skanadoÄœi elpelas la bazon post skanado.Äœisdatigu staton de butonoOpcioj de ÄisdatigoOpcioj de Äisdatigo.Uzu fokusiÄon je 0mm anstataÅ­ 0.6mmUzu Kunmetadon de BildojUzu ene pli ol 8 bitoj de profundeco, sed eligu nur 8-bitojn.Uzu personigitan tabelon de gamaUzu la lensojn kiuj duobligas optikan distingonUszi ne-blokantan eneligonÄœi uzas ne-blokantan eneligon por sane_read() se la fasado subtenas Äin.Uzu nur hardvarajn difinojnÄœi uzas la saman valoron de gama por ĉiuj kanaloj.Uzu la saman valoron por distingo de X kaj YUzu adaptilon de lumbildoj je 35mmAgordita de la uzantoAgordita de la uzanto (Gama=1.0)Agordita de la uzanto (Gama=1.8)VertikalaAtendu ButononAtendu butononÄœi atendas premon de la fronta butono de lo skanilo por skani.Äœi atendas butonpremon antaÅ­ skanadoÄœi varmigas la lampon tiel ke Äia heleco estas sensanÄa anstataÅ­ ĉiufoja varmigo je 40 sekundoj.Äœi varmigas la lampon tiel ke Äia heleco estas sensanÄa anstataÅ­ ĉiufoja varmigo je 60 sekundoj.Varmigo de lampoVarmigu lampon antaÅ­ la skanadoTempo de varmigoTempo en sekundoj por varmigi la lampon.Se Äi estas ebligita, la skanado ne startas tuj. Por plenumi, premu la butonon "SCAN" (por ML150) aÅ­ "COLOR" (por aliaj modeloj). Por refuzi, premu la butonon "GRAY".Kiam oni uzas grizan aÅ­ duuman kolorojn, tiu elektas uzatan koloron.Kiam oni uzas altajn distingojn kun la horizontala malpli alta ol la verticala, la horizontala interpolado estas malebligata.Nivelo de blankoNivelo de blanko laÅ­ bluoNivelo de blanko laÅ­ verdoNivelo de blanko laÅ­ ruÄoDistingo de XXPAXPA-GrizoXPA RGBDistingo de YZomoeraro en la vico de komandojskanilo por negativojplata skaniloEraro de kontrolo de la aparatarooni ricevis mesaÄon pri eraro rekonita de pravalorantomesaÄo kun nevalida IDENTIFY-bitonevalida kodo de komandonevalida kampo en CDBnevalida kampo en la listo pri parametrojeraro de nevalida mesaÄolampo malfunkciasnestabiligita lampola aparato estas neĉeestantaneniu alia aldona informo pri «senso»deÅovo XdeÅovo Yopcio de ne-konektadoparametro estis ÅanÄita de alia pravalorantoeraro de longo de listo pri parametrojre-agordo de nutro / re-agordo de buso de aparatojre-elektado malsukcesisrondigitaj parametrojeraro de lokiÄo de skan-kapetoskaner kun aÅ­tomata proviziloeraro de tempofinola difinitaj fenestroj estas troajla lampo de diafanecoj malfunkciaseraro de lokiÄo de la skan-kapeto por diafanecojeraro de vualo de diafaneconekonatanesubtenita LUNretkameraosane-backends-1.0.27/po/bg.po0000664000175000017500000051747313110600533012601 00000000000000# Bulgarian translation for SANE backend options # Copyright (C) 2003 SANE Project. # Pavel Constantinov , 2003. msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.11\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2007-12-17 22:59+0100\n" "Last-Translator: Pavel Constantinov \n" "Language-Team: <>\n" "Language: bg\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Брой опции" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "ГеометриÑ" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Повишение" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Разширено" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Превю" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Ðаложи монохромно превю" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Дълбочина на бита" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Режим на Ñканиране" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "СкороÑÑ‚ на Ñканиране" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Източник на Ñканиране" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Ðаложи връщане на главата" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Горен лÑв x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Горен лÑв y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Долен деÑен x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Долен деÑен y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Ð ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканиране" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Ð ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð¿Ð¾ Ð¥" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Ð ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð¿Ð¾ Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "" #: include/sane/saneopts.h:177 #, fuzzy, no-c-format msgid "Page height" msgstr "ОÑветление" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Използвай лична гама-таблица" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Интензитет на образа" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Интензитет - червено" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Интензитет - зелено" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Интензитет - Ñиньо" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "ЯркоÑÑ‚" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "КонтраÑÑ‚" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Размер на зърното" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Полутон" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Степен на черното" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Степен на бÑлото" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Степен на бÑлото - червено" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Степен на бÑлото - зелено" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Степен на бÑлото - Ñиньо" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "СÑнка" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "СÑнка - червено" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "СÑнка - зелено" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "СÑнка - Ñиньо" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "ОÑветление" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "ОÑветление - червено" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "ОÑветление - зелено" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "ОÑветление - Ñиньо" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "ÐюанÑ" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "ÐаÑитеноÑÑ‚" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Име на файла" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Размер на Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ð¸Ñ Ð´ÐµÑен" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Полутонов деÑен" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Вържи резолюциÑта по X и Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Ðегатив" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "ÐšÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° качеÑтвото" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Двойна оптичеÑка резолюциÑ" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Вържи RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Праг" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "ÐšÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° аналоговата гама" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Ðналогова гама - червено" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Ðналогова гама - зелено" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Ðналогова гама - Ñиньо" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Вържи аналоговата гама" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Загрей лампата" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "ÐаглаÑи време за екÑпониране" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "ÐаглаÑи време за екÑпониране - червено" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "ÐаглаÑи време за екÑпониране - зелено" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "ÐаглаÑи време за екÑпониране - Ñиньо" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Сканирай време за екÑпониране" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Сканирай време за екÑпониране - червено" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Сканирай време за екÑпониране - зелено" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Сканирай време за екÑпониране - Ñиньо" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "УÑтанови време за екÑпониране" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "ÐаглаÑи плътноÑтта на лампата" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Сканирай плътноÑтта на лампата" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "УÑтанови плътноÑтта на лампата" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Изкл. лампа при изход" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "ÐžÐ¿Ñ†Ð¸Ñ Ñамо за четене, коÑто указва колко опции поддържа дадено " "уÑтройÑтво." #: include/sane/saneopts.h:248 #, fuzzy, no-c-format msgid "Source, mode and resolution options" msgstr "Кратък ÑпиÑък резолюции" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "" #: include/sane/saneopts.h:250 #, fuzzy, no-c-format msgid "Image modification options" msgstr "Брой опции" #: include/sane/saneopts.h:251 #, fuzzy, no-c-format msgid "Hardware specific options" msgstr "Ð ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканиране" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "ПоиÑкай Ñканиране за превю на качеÑтвото." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "ПоиÑкай вÑички превюта да Ñе правÑÑ‚ в монохромен режим. Ðа Ñкенер Ñ Ñ‚Ñ€Ð¸ " "минаваниÑ, това намалÑва минаваниÑта до една, а на Ñкенер Ñ ÐµÐ´Ð½Ð¾ " "минаване намалÑва изиÑкваниÑта към паметта и времето за Ñканиране на " "превюто." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Брой битове на Ñемпъл, типичните ÑтойноÑти Ñа 1 за \"line-art\" и 8 за " "мултибитово Ñканиране." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Избира режим на Ñканиране (lineart, монохромно или цветно)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Указва ÑкороÑтта, Ñ ÐºÐ¾Ñто ще Ñе извърши Ñканирането." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Избира източника за Ñканирането (напр. фидер за документи)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Оттук можете да наложите връщане на главата." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Горна лÑва x Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Горна лÑва y Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Долна дÑÑна x Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Долна дÑÑна y Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "ÐаглаÑÑ Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñта на Ñканираното изображение." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "ÐаглаÑÑ Ñ…Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»Ð½Ð°Ñ‚Ð° Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканираното изображение." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "ÐаглаÑÑ Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»Ð½Ð°Ñ‚Ð° Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканираното изображение." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" #: include/sane/saneopts.h:305 #, fuzzy, no-c-format msgid "Specifies the height of the media." msgstr "ÐаглаÑÑ Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñта на Ñканираното изображение." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "ÐžÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð´Ð°Ð»Ð¸ да Ñе използва вградена или перÑонализирана гама-таблица." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Таблица за гама-корекциÑ. Ð’ цветен режим, тази Ð¾Ð¿Ñ†Ð¸Ñ Ð·Ð°ÑÑга по равно " "червениÑ, Ð·ÐµÐ»ÐµÐ½Ð¸Ñ Ð¸ ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» едновременно (Ñ‚.е., това е таблица на " "гамата за интензитета)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Таблица Ñ Ð³Ð°Ð¼Ð°-корекциÑта за Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ Ñектор." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Таблица Ñ Ð³Ð°Ð¼Ð°-корекциÑта за Ð·ÐµÐ»ÐµÐ½Ð¸Ñ Ñектор." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Таблица Ñ Ð³Ð°Ð¼Ð°-корекциÑта на ÑÐ¸Ð½Ð¸Ñ Ñектор." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "ÐаÑтройва ÑркоÑтта на полученото изображение." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "ÐаÑтройва контраÑта на полученото изображение." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Избира \" зърненоÑтта\" на полученото изображение. По-ниÑките ÑтойноÑти " "дават по-изоÑтрени изображениÑ." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Избира дали полученото изображение да бъде полутонизирано (dithered)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Избира кое ниво на оÑветеноÑÑ‚ Ñе ÑмÑта за \"черно\"." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Избира кое ниво на оÑветеноÑÑ‚ Ñе ÑмÑта за \"бÑло\"." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "Избира кое ниво на червена оÑветеноÑÑ‚ Ñе ÑмÑта за \"бÑло\"." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "Избира кое ниво на зелена оÑветеноÑÑ‚ Ñе ÑмÑта за \"бÑло\"." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "Избира кое ниво на ÑÐ¸Ð½Ñ Ð¾ÑветеноÑÑ‚ Ñе ÑмÑта за \"бÑло\"." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "Избира кое ниво на червена оÑветеноÑÑ‚ Ñе ÑмÑта за \"черно\"." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "Избира кое ниво на зелена оÑветеноÑÑ‚ Ñе ÑмÑта за \"черно\"." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "Избира кое ниво на ÑÐ¸Ð½Ñ Ð¾ÑветеноÑÑ‚ Ñе ÑмÑта за \"черно\"." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Избира кое ниво на червена оÑветеноÑÑ‚ Ñе ÑмÑта за \"изцÑло червено\"." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Избира кое ниво на зелена оÑветеноÑÑ‚ Ñе ÑмÑта за \"изцÑло зелено\"." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "Избира кое ниво на ÑÐ¸Ð½Ñ Ð¾ÑветеноÑÑ‚ Ñе ÑмÑта за \"изцÑло Ñиньо\"." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "ÐаглаÑÑ Ð¾Ñ‚Ñ‚ÐµÐ½ÑŠÐºÐ° (в Ñиньото ниво) на полученото изображение." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Ðивото на наÑитеноÑÑ‚ контролира нивото на \"blooming\" ефекта, който Ñе " "поÑвÑва при добиването на изображение Ñ Ñ„Ð¾Ñ‚Ð¾Ð°Ð¿Ð°Ñ€Ð°Ñ‚. По-големите " "ÑтойноÑти причинÑват повече blooming." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Файловото име на изображението, което ще Ñе зареди." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "ÐаглаÑÑ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð° на деÑена за полутонизиране (dithering), който ще Ñе " "използва при Ñканирането на Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ðµ." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "ÐžÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð´ÐµÑена за полутонизиране (dithering) при Ñканирането на " "Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ñ Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ðµ." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Използвай еднакви ÑтойноÑти за X и Y резолюциÑта." #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Размени черно и бÑло" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Извърши качеÑтвена бÑла калибрациÑ" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Използвай лещи, които удвоÑват оптичната резолюциÑ" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Ð’ RGB режим, използвай Ñъщите ÑтойноÑти за вÑеки цвÑÑ‚" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Избери минимална ÑркоÑÑ‚ за получаване на бÑла точка" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Ðналогова гама-корекциÑ" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Ðналогова гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð·Ð° червено" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Ðналогова гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð·Ð° зелено" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Ðналогова гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð·Ð° Ñиньо" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Загрей лампата преди Ñканиране" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Дефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° калибрациÑ" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Дефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° червено" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Дефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° зелено" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Дефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° Ñиньо" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Дефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° Ñканиране" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Дефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° Ñканиране на червено" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Дефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° Ñканиране на зелено" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Дефинирай времето на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð·Ð° Ñканиране на Ñиньо" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Позволи избор на време за екÑпонациÑ" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Дефинирай плътноÑтта на лампата за калибрациÑ" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Дефинирай плътноÑтта на лампата за Ñканирането" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Позволи избор на плътноÑÑ‚ на лампата" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Изключи лампата при излизане от програмата" #: include/sane/saneopts.h:444 #, fuzzy, no-c-format msgid "Scan button" msgstr "Ð ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканиране" #: include/sane/saneopts.h:445 #, fuzzy, no-c-format msgid "Email button" msgstr "Изчакай натиÑкане на бутона" #: include/sane/saneopts.h:446 #, fuzzy, no-c-format msgid "Fax button" msgstr "Изчакай натиÑкане на бутона" #: include/sane/saneopts.h:447 #, fuzzy, no-c-format msgid "Copy button" msgstr "Изчакай натиÑкане на бутона" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "" #: include/sane/saneopts.h:451 #, fuzzy, no-c-format msgid "Cover open" msgstr "Цветови деÑен" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "ЦвÑÑ‚" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Цветно Lineart" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Цветно Ñ Ð¿Ð¾Ð»ÑƒÑ‚Ð¾Ð½Ð¾Ð²Ðµ" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Сиво" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Полутон" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Lineart" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "" #: backend/sane_strstatus.c:62 #, fuzzy, no-c-format msgid "Operation not supported" msgstr "ÐÑма поддръжка на полутонове" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "" #: backend/sane_strstatus.c:77 #, fuzzy, no-c-format msgid "Document feeder jammed" msgstr "Feeder за документи" #: backend/sane_strstatus.c:80 #, fuzzy, no-c-format msgid "Document feeder out of documents" msgstr "Feeder за документи" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "ВиÑÑщи опции" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "ÐаглаÑи виÑÑщи опции за повишителните контроли." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "КалибрациÑ" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Калибрирай преди Ñледващото Ñканиране" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Ðко това е позволено, уÑтройÑтвото ще Ñе калибрира преди Ñледващото " "Ñканиране. Иначе, калибрациÑта Ñе прави Ñамо преди първото пуÑкане." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Извърши Ñамо ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° отÑенките" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Ðко това е позволено, Ñамо ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° отÑенките Ñе извършва през " "калибрациÑта. Използват Ñе ÑтойноÑтите по подразбиране за увеличение, " "офÑет и време на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ - вÑе едно вградени или от ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ " "файл." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Ðомер на кадъра за Ñканиране" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Избира номера на кадъра за Ñканиране" #: backend/avision.h:782 #, fuzzy, no-c-format msgid "Duplex scan" msgstr "ДуплекÑно" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Калибрирай Ñкенера" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Задължителна ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¸ Ñканиране" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Сканиране в Ñива Ñкала" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Ðаправи Ñканиране в Ñива Ñкала, не цветно" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Ðналогово увеличение" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Повиши или намали аналоговото увеличение на CCD матрицата" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "ÐšÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° гамата" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Избира кривата на коригираната гама" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, fuzzy, no-c-format msgid "No transparency correction" msgstr "Цветова корекциÑ." #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "" #: backend/canon.c:176 backend/canon-sane.c:776 #, fuzzy, no-c-format msgid "Negatives" msgstr "Ðегатив" #: backend/canon.c:176 #, fuzzy, no-c-format msgid "Slides" msgstr "Солидно бÑло" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Ðвтоматично" #: backend/canon.c:186 #, fuzzy, no-c-format msgid "Normal speed" msgstr "Ðормално" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/2 normal speed" msgstr "2Ñ…2 нормално" #: backend/canon.c:187 #, fuzzy, no-c-format msgid "1/3 normal speed" msgstr "3Ñ…3 нормално" #: backend/canon.c:365 #, fuzzy, no-c-format msgid "rounded parameter" msgstr "Параметри за мъглÑвоÑÑ‚" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "" #: backend/canon.c:378 #, fuzzy, no-c-format msgid "ADF jam" msgstr "ADF" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "" #: backend/canon.c:394 #, fuzzy, no-c-format msgid "lamp failure" msgstr "СтойноÑÑ‚ на гамата" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "" #: backend/canon.c:412 #, fuzzy, no-c-format msgid "transparency unit lamp failure" msgstr "ПрозрачноÑÑ‚" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "" #: backend/canon.c:522 #, fuzzy, no-c-format msgid "transparency unit shading error" msgstr "ПрозрачноÑÑ‚" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "" #: backend/canon.c:852 backend/canon.c:867 #, fuzzy, no-c-format msgid "film scanner" msgstr "flatbed Ñкенер" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "flatbed Ñкенер" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Тип екран (film)" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "" #: backend/canon.c:1196 #, fuzzy, no-c-format msgid "Negative film type" msgstr "Ðегативен филм" #: backend/canon.c:1197 #, fuzzy, no-c-format msgid "Selects the negative film type" msgstr "Избира картинка за теÑтване" #: backend/canon.c:1236 #, fuzzy, no-c-format msgid "Hardware resolution" msgstr "Ð ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканиране" #: backend/canon.c:1237 #, fuzzy, no-c-format msgid "Use only hardware resolutions" msgstr "Покажи кратък ÑпиÑък Ñ Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ð¸" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "" #: backend/canon.c:1328 #, fuzzy, no-c-format msgid "Auto focus" msgstr "Ðвто изваждане" #: backend/canon.c:1329 #, fuzzy, no-c-format msgid "Enable/disable auto focus" msgstr "Забрани предв. фокуÑ" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "" #: backend/canon.c:1345 #, fuzzy, no-c-format msgid "Manual focus position" msgstr "ФикÑирай Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° фокуÑа" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Огледален образ" #: backend/canon.c:1539 #, fuzzy, no-c-format msgid "Mirror the image horizontally" msgstr "Прави хоризонтален огледален образ." #: backend/canon.c:1608 #, fuzzy, no-c-format msgid "Auto exposure" msgstr "УÑтанови време за екÑпониране" #: backend/canon.c:1609 #, fuzzy, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Позволи избор на време за екÑпонациÑ" #: backend/canon.c:1625 #, fuzzy, no-c-format msgid "Calibration now" msgstr "КалибрациÑ" #: backend/canon.c:1626 #, fuzzy, no-c-format msgid "Execute calibration *now*" msgstr "Дефинирай режима на калибрациÑ" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "" #: backend/canon.c:1648 #, fuzzy, no-c-format msgid "Reset scanner" msgstr "Ñкенер Ñ sheetfeed" #: backend/canon.c:1649 #, fuzzy, no-c-format msgid "Reset the scanner" msgstr "Ñкенер Ñ sheetfeed" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "" #: backend/canon.c:1668 #, fuzzy, no-c-format msgid "Eject film after each scan" msgstr "Извади документа Ñлед Ñканиране" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "" #: backend/canon.c:1700 #, fuzzy, no-c-format msgid "Document feeder extras" msgstr "Feeder за документи" #: backend/canon.c:1707 #, fuzzy, no-c-format msgid "Flatbed only" msgstr "Flatbed" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" #: backend/canon.c:1718 backend/canon.c:1728 #, fuzzy, no-c-format msgid "Transparency unit" msgstr "ПрозрачноÑÑ‚" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" #: backend/canon.c:1739 #, fuzzy, no-c-format msgid "Negative film" msgstr "Ðегативен филм" #: backend/canon.c:1740 #, fuzzy, no-c-format msgid "Positive or negative film" msgstr "Позитивен екран" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "" #: backend/canon.c:1761 #, fuzzy, no-c-format msgid "Transparency ratio" msgstr "ПрозрачноÑÑ‚" #: backend/canon.c:1775 #, fuzzy, no-c-format msgid "Select film type" msgstr "Тип екран (film)" #: backend/canon.c:1776 #, fuzzy, no-c-format msgid "Select the film type" msgstr "Избира полутона" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flatbed" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "ADF" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, fuzzy, no-c-format msgid "ADF Duplex" msgstr "ДуплекÑно" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Печат" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "ДуплекÑно" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Червено" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Зелено" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Синьо" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Повишение" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Повишение" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Повишение" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Ðищо" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "СимплекÑно" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "ДуплекÑно" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "ПрозрачноÑÑ‚" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Ðвтоматично подаване на документи" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Позитивен екран" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Ðегативен филм" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Ð¤Ð¾ÐºÑƒÑ Ð²ÑŠÑ€Ñ…Ñƒ Ñтъклото" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Ð¤Ð¾ÐºÑƒÑ 2,5 мм над Ñтъклото" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Полутон A (Твърд тон)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Полутон B (Мек тон)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Полутон C (Net Screen)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Dither A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Dither B (4x4 Spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Dither C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Dither D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Ð¢ÐµÑ…Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ Ð·Ð° оконтраÑтиране на текÑта" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Свали деÑен B" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Свали деÑен B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Без корекциÑ" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "По потребителÑка дефинициÑ" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Матрични принтери" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Лазерни принтери" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "МаÑтиленоÑтруйни принтери" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT монитори" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "По подразбиране" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Принтиране Ñ Ð²Ð¸Ñока гъÑтота" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Принтиране Ñ Ð½Ð¸Ñка гъÑтота" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Принтиране Ñ Ð²Ð¸Ñок контраÑÑ‚" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "По потребителÑка Ð´ÐµÑ„Ð¸Ð½Ð¸Ñ†Ð¸Ñ (Гама=1,0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "По потребителÑка Ð´ÐµÑ„Ð¸Ð½Ð¸Ñ†Ð¸Ñ (Гама=1,8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 портрет" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 пейзаж" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "МакÑ." #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Режим на Ñканиране" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Избира полутона" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Dropout" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Избира dropout-а." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Избира ÑркоÑтта." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "ОÑтрота" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Цветова корекциÑ." #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "ÐаглаÑÑ Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ð°Ñ‚Ð° за цветова ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° избраното изходно уÑтройÑтво." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Коефициенти на цветова корекциÑ" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Матрично умножаване на RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "ИзмеÑти зелено към червено" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "ИзмеÑти зелено към Ñиньо" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "ИзмеÑти червено към зелено" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "ИзмеÑти червено към Ñиньо" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "ИзмеÑти Ñиньо към зелено" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "ИзмеÑти Ñиньо към червено" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "ÐаглаÑÑ Ñтепента на зелено" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ червеното Ñпоред Ñтепента на зелено" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ Ñиньото Ñпоред Ñтепента на зелено" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ зеленото Ñпоред Ñтепента на червено" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "ÐаглаÑÑ Ñтепента на червено" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ Ñиньото Ñпоред Ñтепента на червено" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ зеленото Ñпоред Ñтепента на Ñиньо" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Ð”Ð¾Ð±Ð°Ð²Ñ ÐºÑŠÐ¼ червеното Ñпоред Ñтепента на Ñиньо" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "ÐаглаÑÑ Ñтепента на Ñиньо" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Ðаправи огледален образ на изображението" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Бързо превю" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Ðвтоматична ÑÐµÐ³Ð¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð½Ð° площ" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Кратък ÑпиÑък резолюции" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Покажи кратък ÑпиÑък Ñ Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ð¸" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Увеличение" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "ÐžÐ¿Ñ€ÐµÐ´ÐµÐ»Ñ Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð° на увеличение за Ñкенера" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Бързо форматиране" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Оборудване по избор" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Извади" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Извади лиÑта от ADF" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Ðвто изваждане" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Извади документа Ñлед Ñканиране" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" #: backend/epson.c:3473 backend/epson2.c:1431 #, fuzzy, no-c-format msgid "Bay" msgstr "Bay" #: backend/epson.c:3474 backend/epson2.c:1432 #, fuzzy, no-c-format msgid "Select bay to scan" msgstr "Избор на bay за Ñканиране" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Избира ÑтойноÑтта за гама ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð¾Ñ‚ ÑпиÑък предефинирани уÑтройÑтва " "или таблицата, определена от потребителÑ, коÑто може да Ñе Ñвали на " "Ñкенера." #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "ÐŸÐ¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° фокуÑа" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "ÐаглаÑÑ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñта на фокуÑа или върху Ñтъклото, или 2,5 мм над него" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Изчакай натиÑкане на бутона" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "След изпращане на команда за Ñканиране, изчакай, докато бутонът на " "Ñкенера не е натиÑнат, преди да започнеш Ñамото Ñканиране." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, fuzzy, no-c-format msgid "Positive Slide" msgstr "Позитивен екран" #: backend/epson2.c:137 #, fuzzy, no-c-format msgid "Negative Slide" msgstr "Ðегативен филм" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "По потребителÑка дефинициÑ" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Вкл." #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Изкл." #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Dither" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "РазÑейка на грешките" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Степен на бÑлото" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Степен на черното" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "Кондиционално" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Хоризонтално" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Хоризонтално" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Хоризонтално" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "8x8 вертикална черта" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "8x8 вертикална черта" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Печат" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Полутон" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Груба калибрациÑ" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Подчертаване на образа" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "ÐаÑитеноÑÑ‚" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "ПозволÑва автоматично определÑне на прага за lineart Ñканиране." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Огледален образ" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Прави хоризонтален огледален образ." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Степен на бÑлото - Ñиньо" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "ÐаглаÑÑ Ñтепента на червено" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Цветно Lineart" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Изглаждане" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "СтойноÑÑ‚ на гамата" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Праг" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Праг" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Редуциране на шума" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Без корекциÑ" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Без корекциÑ" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Режим на захранване" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Обнови опциите" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Без корекциÑ" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Dropout" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Режим на захранване" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Изкл. лампа" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "ОфÑет - Ñиньо" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "ОфÑет - зелено" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "ОфÑет - зелено" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "ОфÑет - Ñиньо" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "ÐаглаÑÑ Ð¾Ñ„Ñета на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "ДуплекÑно" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Обнови опциите" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Редуциране на шума" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "От хартиÑ" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "От хартиÑ" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "От хартиÑ" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "От хартиÑ" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Ръчен предв. фокуÑ" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Ръчен предв. фокуÑ" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "Ð ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° Ñканиране" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Степен на бÑлото" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Интензитет - червено" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "ДуплекÑно" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, fuzzy, no-c-format msgid "Extras" msgstr "ЕкÑтра бързо" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, fuzzy, no-c-format msgid "Disable interpolation" msgstr "Забрани връщане на главата" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Цветно Lineart" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "КалибрациÑ" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Дефинирай режима на калибрациÑ" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Режим калибрациÑ" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, fuzzy, no-c-format msgid "Lamp off time" msgstr "Изкл. лампа" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Груба калибрациÑ" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "" #: backend/genesys.c:5972 backend/genesys.c:5973 #, fuzzy, no-c-format msgid "File button" msgstr "Изчакай натиÑкане на бутона" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "" #: backend/genesys.c:6039 backend/genesys.c:6040 #, fuzzy, no-c-format msgid "Power button" msgstr "Изчакай натиÑкане на бутона" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Изчакай натиÑкане на бутона" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Груба калибрациÑ" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Задължителна ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¸ Ñканиране" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Калибриране" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, fuzzy, no-c-format msgid "Start calibration using special sheet" msgstr "Започване на калибрациÑта." #: backend/genesys.c:6105 backend/gt68xx.c:809 #, fuzzy, no-c-format msgid "Clear calibration" msgstr "Груба калибрациÑ" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, fuzzy, no-c-format msgid "Clear calibration cache" msgstr "Режим калибрациÑ" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Ðдаптиране на прозрачноÑтта" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Опции за дебъг" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Ðвтоматично загрÑване" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "ЗагрÑвай, докато ÑркоÑтта на лампата е поÑтоÑнна, вмеÑто да наÑтоÑваш за " "60 Ñекундно загрÑване." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "ЦÑлоÑтно Ñканиране" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Сканирай цÑлата площ за Ñканиране, вкл. парчето за калибрациÑ. " "Внимавайте. Ðе избирайте цÑлата виÑочина. Тази Ð¾Ð¿Ñ†Ð¸Ñ Ðµ Ñамо за теÑтване." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Груба калибрациÑ" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Ðвтоматична наÑтройка на офÑет и увеличение при Ñканиране. Ðко тази " "Ð¾Ð¿Ñ†Ð¸Ñ Ðµ забранена, има опции за ръчната наглаÑа на аналоговите параметри " "на фронтенда. Тази Ð¾Ð¿Ñ†Ð¸Ñ Ðµ разрешена по подразбиране. Само за теÑтване." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Груба ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ñамо за първото Ñканиране" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Грубата ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ñе прави Ñамо за първото Ñканиране. Работи Ñ Ð²Ñички " "Ñкенери и пеÑти време. Ðко ÑркоÑтта на изображението е различна при " "вÑÑко Ñканиране, забранете тази опциÑ. Само за теÑтване" #: backend/gt68xx.c:654 #, fuzzy, no-c-format msgid "Backtrack lines" msgstr "Ðаложи връщане на главата" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "СтойноÑÑ‚ на гамата" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "ÐаглаÑÑ ÑтойноÑтта на гамата за вÑички канали." #: backend/hp3500.c:1020 #, fuzzy, no-c-format msgid "Geometry Group" msgstr "ГеометриÑ" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, fuzzy, no-c-format msgid "Scan Mode Group" msgstr "Режим на Ñканиране" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Солидно бÑло" #: backend/hp3900_sane.c:1405 #, fuzzy, no-c-format msgid "Scanner model" msgstr "Режим на Ñканиране" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "" #: backend/hp3900_sane.c:1436 #, fuzzy, no-c-format msgid "Disable gamma correction" msgstr "ÐšÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° аналоговата гама" #: backend/hp3900_sane.c:1437 #, fuzzy, no-c-format msgid "Gamma correction will be disabled" msgstr "ÐšÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° гамата" #: backend/hp3900_sane.c:1451 #, fuzzy, no-c-format msgid "Disable white shading correction" msgstr "Извърши Ñамо ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° отÑенките" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" #: backend/hp3900_sane.c:1499 #, fuzzy, no-c-format msgid "Emulate Grayscale" msgstr "Ð’ Ñива Ñкала" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" #: backend/hp3900_sane.c:1533 #, fuzzy, no-c-format msgid "Reset chipset" msgstr "Ñкенер Ñ sheetfeed" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "" #: backend/hp3900_sane.c:1547 #, fuzzy, no-c-format msgid "Information" msgstr "Игнорирай калибрациÑта" #: backend/hp3900_sane.c:1560 #, fuzzy, no-c-format msgid "Chipset name" msgstr "Име на файла" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "" #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "" #: backend/hp3900_sane.c:1572 #, fuzzy, no-c-format msgid "Shows the chipset ID" msgstr "Ñкенер Ñ sheetfeed" #: backend/hp3900_sane.c:1582 #, fuzzy, no-c-format msgid "Scan counter" msgstr "Източник на Ñканиране" #: backend/hp3900_sane.c:1584 #, fuzzy, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Избира номера на кадъра за Ñканиране" #: backend/hp3900_sane.c:1594 #, fuzzy, no-c-format msgid "Update information" msgstr "Обнови опциите" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Изображение" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "" #: backend/hp5400_sane.c:358 #, fuzzy, no-c-format msgid "offset X" msgstr "ОфÑет" #: backend/hp5400_sane.c:359 #, fuzzy, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Горна лÑва x Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране." #: backend/hp5400_sane.c:368 #, fuzzy, no-c-format msgid "offset Y" msgstr "ОфÑет" #: backend/hp5400_sane.c:369 #, fuzzy, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Горна лÑва x Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° площта за Ñканиране." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Включва/изключва лампата." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, fuzzy, no-c-format msgid "TMA Slides" msgstr "Солидно бÑло" #: backend/hp5590.c:89 #, fuzzy, no-c-format msgid "TMA Negatives" msgstr "Ðегатив" #: backend/hp5590.c:92 #, fuzzy, no-c-format msgid "Color (48 bits)" msgstr "ЦвÑÑ‚ 48" #: backend/hp5590.c:95 #, fuzzy, no-c-format msgid "Extend lamp timeout" msgstr "Изкл. лампа" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Изчакай натиÑкане на бутона" #: backend/hp5590.c:99 #, fuzzy, no-c-format msgid "Waits for button before scanning" msgstr "Загрей лампата преди Ñканиране" #: backend/hp-option.c:2984 #, fuzzy, no-c-format msgid "Advanced Options" msgstr "Обнови опциите" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "8Ñ…8 грубо" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Име на файла" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "8Ñ…8 по избор" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Ðвто" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, fuzzy, no-c-format msgid "Pass-through" msgstr "Pass-through" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Ñиво" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA Ñиво" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "По-бавно" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Ðормално" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "По-бързо" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "ЕкÑтра бързо" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-пикÑелно" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-пикÑелно" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-пикÑелно" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Печат" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Тип филм" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Кондиционално" #: backend/hp-option.c:3414 #, fuzzy, no-c-format msgid "Experiment" msgstr "Време за екÑпонациÑ" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "ИзоÑтрÑне" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "ÐаглаÑи ÑтойноÑтта за изоÑтрÑне." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Ðвтоматичен праг" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "ПозволÑва автоматично определÑне на прага за lineart Ñканиране." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Избира полутона" #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Отзареждане на медиÑта Ñлед Ñканиране." #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Отзарежда медиÑта Ñлед Ñканиране." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Смени документа" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Смени документа." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Отзареди" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Отзареди документа." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Започване на калибрациÑта." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "МедиÑ" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "ÐаглаÑи типа медиÑ." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Време за екÑпонациÑ" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "По-дългото време на екÑÐ¿Ð¾Ð½Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñва на Ñкенера да Ñъбере повече " "Ñветлина. Предложената употреба е 175% за разпечатки, 150% за нормални " "Ñлайдове и \"Ðегатив\" за негативен филм. За тъмни (подекÑпонирани) " "Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚Ðµ да завишите тази ÑтойноÑÑ‚." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Цветна матрица" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "ÐаглаÑÑ Ñ†Ð²ÐµÑ‚Ð½Ð°Ñ‚Ð° матрица на Ñкенера." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Цветна матрица по избор." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Едноцветна матрица" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Цветна матрица по избор за Ñканиране в Ñива Ñкала." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Огледало хоризонтално" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Прави хоризонтален огледален образ." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Огледало вертикално" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Прави вертикален огледален образ" #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Обнови опциите" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Обнови опциите." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8-битово извеждане." #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Вътрешно използвай по-голÑма дълбочина от оÑем бита, но извеждай Ñамо " "оÑем бита." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Изчакай бутона" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Изчакай за натиÑкане на бутона преди Ñканиране." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Изключи лампата" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Изключва лампата на Ñкенера" #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Размер на хартиÑта" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Ðвтоматично разделение" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 пейзаж" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Ръчен предв. фокуÑ" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Ръчен предв. фокуÑ" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Позволи дупрекÑно (двуÑтранно) Ñканиране" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "ФизичеÑки размер на хартиÑта в ADF" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Полутон" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "ЦвÑÑ‚" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Кондиционално" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Изкл." #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Полутон" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Полутон" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "РазÑейка на грешките" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Ðормално" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "ОÑветление" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "flatbed Ñкенер" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "От хартиÑ" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "По подразбиране" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Изглаждане" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "По-бавно" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Средно" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Червено" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Зелено" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Източник на Ñканиране" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Режим на захранване" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "ÐаглаÑÑ Ñ€ÐµÐ¶Ð¸Ð¼Ð° на захранване" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Забрани предв. фокуÑ" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Забрани предв. фокуÑ" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "ÐаглаÑÑ Ñ€ÐµÐ¶Ð¸Ð¼Ð° на захранване" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "ÐаглаÑÑ Ñ€ÐµÐ¶Ð¸Ð¼Ð° на захранване" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Ðвтоматичен праг" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Ðвтоматично наглаÑÑ ÑркоÑтта, контраÑта, нивото на бÑло, гамата, " "редукциÑта на шума и подчертаването на образа" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Редуциране на шума" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Ðамали Ð¸Ð·Ð¾Ð»Ð¸Ñ€Ð°Ð½Ð¸Ñ Ñ‚Ð¾Ñ‡ÐºÐ¾Ð² шум" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Подчертаване на образа" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "ÐаглаÑÑ Ð¿Ð¾Ð´Ñ‡ÐµÑ€Ñ‚Ð°Ð²Ð°Ð½ÐµÑ‚Ð¾ на образа" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Гама" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Вкл. лампа" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Включва/изключва лампата." #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Прави вертикален огледален образ" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "ÐšÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° гамата" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Принтиране Ñ Ð²Ð¸Ñока гъÑтота" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Принтиране Ñ Ð½Ð¸Ñка гъÑтота" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "РазÑейка на грешките" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Без корекциÑ" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Ðормално" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Повишение" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Ðвтоматичен праг" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Ðвтоматичен праг" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "ÐаглаÑÑ Ð¿Ð¾Ñ€ÐµÐ´Ð½Ð¾Ñтта на фреймовете." #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "СÑнка - Ñиньо" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "ИзмеÑти червено към Ñиньо" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamond" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 груб Fatting" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 фин Fatting" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 вертикална черта" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Увеличение" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "ÐаÑтройки по увеличение на цветните канали" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Увеличение - Ñиво" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "ÐаглаÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ðµ на ÑÐ¸Ð²Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Увеличение - червено" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "ÐаглаÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ðµ на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Увеличение - зелено" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "ÐаглаÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ðµ на Ð·ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Увеличение - Ñиньо" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "ÐаглаÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡ÐµÐ½Ð¸Ðµ на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer Dither 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer Dither 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Полутон Dot 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Полутон Dot 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "РазÑейка на грешките" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Режим 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Режим 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Режим 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "От бÑл" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Изглаждане" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "ÐиÑко" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Средно" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "ВиÑоко" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Една Ñтраница" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Ð’Ñички Ñтраници" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, fuzzy, no-c-format msgid "sheetfed scanner" msgstr "Ñкенер Ñ sheetfeed" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Сива Ñкала 4 бита" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Сива Ñкала 8 бита" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Сенки, полутонове, Ñветли тонове, време за екÑпониране" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Специални опции" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Цветови баланÑ" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Забрани връщане на главата" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "При отмÑтане, Ñкенерът не връща главата обратно" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Превключи лампата на flatbed-а" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Превключва лампата на flatbed-а" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "ÐšÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ бекенда" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Ðко отметнете тук, цветовата ÐºÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€ÐµÐ´Ð¸ Ñканирането Ñе прави от " "бекенда" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Използвай адаптера за 35мм Ñветлинна капачка" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¸Ð·ÐºÐ»ÑŽÑ‡Ð²Ð° лампата на flatbed-а по време на Ñканиране" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "КачеÑтвено Ñканиране" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Ðай-виÑоко качеÑтво, по-ниÑка ÑкороÑÑ‚" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Бързо Ñканиране" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Ðай-виÑока ÑкороÑÑ‚, по-ниÑко качеÑтво" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Ðвтоматично пригаждане на прага" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Ðко отметнете тук, бекендът автоматично ще потърÑи оптимална ÑтойноÑта " "за прага." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Избира режима за ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ Ð½Ð° гамата." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Вържи гамата" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Използва Ñъщите ÑтойноÑти за вÑички цветови канали." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Скаларна гама" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Избира ÑтойноÑÑ‚ за Ñкаларната гама-корекциÑ." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Скаларна гама - червено" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Избира ÑтойноÑÑ‚ за Ñкаларната гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ (червен канал)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Скаларна гама - зелено" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Избира ÑтойноÑÑ‚ за Ñкаларната гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ (зелен канал)." #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Скаларна гама - Ñиньо" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Избира ÑтойноÑÑ‚ за Ñкаларната гама-ÐºÐ¾Ñ€ÐµÐºÑ†Ð¸Ñ (Ñин канал)." #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Канал" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Избира цветовата лента. \"Master\" означава, че вÑички цветова Ñа " "заÑегнати." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Полутон" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Избира кое ниво на оÑветеноÑÑ‚ ще Ñе ÑмÑта за \"50 % Ñиво\"." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Полутон - червено" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Избира кое ниво на оÑветеноÑÑ‚ ще Ñе ÑмÑта за \"50 % червено\"." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Полутон - зелено" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Избира кое ниво на оÑветеноÑÑ‚ ще Ñе ÑмÑта за \"50% зелено\"." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Полутон - Ñиньо" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Избира кое ниво на оÑветеноÑÑ‚ ще Ñе Ñчита за \"50 % Ñиньо\"." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ - червено" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Фактор за баланÑиране на червеното. 100% означава без корекциÑ." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ - зелено" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Фактор за баланÑиране на зеленото. 100% означава без корекциÑ." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ - Ñиньо" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Фактор за баланÑиране на Ñиньото. 100% означава без корекциÑ." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ Ð¾Ñ‚ фърмуера" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "ÐаглаÑÑ Ð·Ð° ÑтойноÑти на цветови Ð±Ð°Ð»Ð°Ð½Ñ Ð¿Ñ€ÐµÐ´Ð²Ð¸Ð´ÐµÐ½Ð¸Ñ‚Ðµ от firmware-а." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Ðай-бавно" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "По-бавно" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "По-бързо" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Ðай-бързо" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8Ñ…8 грубо" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8Ñ…8 нормално" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8Ñ…8 фино" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8Ñ…8 много фино" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6Ñ…6 нормално" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5Ñ…5 грубо" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5Ñ…5 фино" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4Ñ…4 грубо" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4Ñ…4 нормално" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4Ñ…4 фино" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3Ñ…3 нормално" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2Ñ…2 нормално" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8Ñ…8 по избор" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6Ñ…6 по избор" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5Ñ…5 по избор" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4Ñ…4 по избор" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3Ñ…3 по избор" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2Ñ…2 по избор" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Бърз Ñив режим" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Сканирай в бърз Ñив режим (по-ниÑко качеÑтво)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "ПоиÑкай вÑички превюта да Ñе правÑÑ‚ в най-бърз (ниÑкокачеÑтвен) режим. " "Това може да е безцветен режим или режим Ñ Ð½Ð¸Ñка резолюциÑ." #: backend/mustek.c:4341 #, fuzzy, no-c-format msgid "Lamp off time (minutes)" msgstr "Загрей лампата" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "" #: backend/mustek.c:4353 #, fuzzy, no-c-format msgid "Turn lamp off" msgstr "Включва/изключва лампата" #: backend/mustek.c:4354 #, fuzzy, no-c-format msgid "Turns the lamp off immediately." msgstr "Превключва лампата на flatbed-а" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "ЯркоÑÑ‚ - червено" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "ÐаглаÑÑ ÑркоÑтта на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "ЯркоÑÑ‚ - зелено" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "ÐаглаÑÑ ÑркоÑтта на Ð·ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "ЯркоÑÑ‚ - Ñиньо" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "ÐаглаÑÑ ÑркоÑтта на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "КонтраÑÑ‚ - червен канал" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "ÐаглаÑÑ ÐºÐ¾Ð½Ñ‚Ñ€Ð°Ñта на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "КонтраÑÑ‚ - зелен канал" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "ÐаглаÑÑ ÐºÐ¾Ð½Ñ‚Ñ€Ð°Ñта на Ð·ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "КонтраÑÑ‚ - Ñин канал" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "ÐаглаÑÑ ÐºÐ¾Ð½Ñ‚Ñ€Ð°Ñта на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð» на полученото изображение." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "ЦвÑÑ‚ 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "ЦвÑÑ‚ 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Сиво 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Сиво 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "" #: backend/mustek_usb2.c:120 #, fuzzy, no-c-format msgid "Positive" msgstr "Позитивен екран" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "ЗагрÑвай, докато ÑркоÑтта на лампата е поÑтоÑнна, вмеÑто да наÑтоÑваш за " "40 Ñекундно загрÑване." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Ðегативен филм" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Ðегатив" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "ПрозрачноÑÑ‚" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "" #: backend/plustek.c:926 #, fuzzy, no-c-format msgid "Lamp off during dark calibration" msgstr "Груба калибрациÑ" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "" #: backend/plustek.c:935 #, fuzzy, no-c-format msgid "Calibration data cache" msgstr "Режим калибрациÑ" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "" #: backend/plustek.c:942 #, fuzzy, no-c-format msgid "Performs calibration" msgstr "Груба калибрациÑ" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "" #: backend/plustek.c:974 #, fuzzy, no-c-format msgid "Warmup-time" msgstr "Загрей лампата" #: backend/plustek.c:975 #, fuzzy, no-c-format msgid "Warmup-time in seconds." msgstr "Загрей лампата" #: backend/plustek.c:987 #, fuzzy, no-c-format msgid "Lampoff-time" msgstr "Изкл. лампа" #: backend/plustek.c:988 #, fuzzy, no-c-format msgid "Lampoff-time in seconds." msgstr "Загрей лампата" #: backend/plustek.c:995 #, fuzzy, no-c-format msgid "Analog frontend" msgstr "Ðналогова гама - червено" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "ОфÑет - червено" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "" #: backend/plustek.c:1049 #, fuzzy, no-c-format msgid "Red lamp off" msgstr "Включва/изключва лампата" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "" #: backend/plustek.c:1057 #, fuzzy, no-c-format msgid "Green lamp off" msgstr "Включва/изключва лампата" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "" #: backend/plustek.c:1065 #, fuzzy, no-c-format msgid "Blue lamp off" msgstr "Включва/изключва лампата" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "ЦвÑÑ‚ 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Ðаправи произволно" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Избор на източник" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Подобрение на образа" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "ПоÑиви" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Зареди образа като Ñива Ñкала." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° тройно минаване" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Симулира Ñкенер Ñ Ñ‚Ñ€Ð¾Ð¹Ð½Ð¾ минаване, като връща 3 отделни пъти. Първо " "връща зелено, поÑле Ñиньо, а Ð½Ð°ÐºÑ€Ð°Ñ - червено." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° ръчен Ñкенер" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Симулира ръчен Ñкенер. Ръчните Ñкенери чеÑто не знаÑÑ‚ виÑочината на " "образа а приори. ВмеÑто това, те връщат ÑтойноÑÑ‚ от -1. ПуÑкането на " "тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñва да теÑтвате дали фронтендът може да Ñе Ñправи " "правилно Ñ Ñ‚Ð¾Ð²Ð°." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "ÐаглаÑи виÑÑщите опции за подобрение (за ÑркоÑтта и контраÑта)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "ТеÑÑ‚ Ñамо за четене" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Да видим дали фронтендовете ще Ñе ÑправÑÑ‚ Ñ Ñ‚Ð¾Ð²Ð°" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Таблици за гамата" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° ÑтатуÑ-код" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Ðе наÑилвай ÑтатуÑ-код" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Ðе наÑилвай бекенда да връща ÑтатуÑ-код" #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Върни SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_EOF Ñлед повикването на " "sane_read()." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Върни SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_JAMMED, Ñлед " "повикването на sane_read()." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Върни SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_NO_DOCS Ñлед " "повикването на sane_read()." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Върни SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_COVER_OPEN Ñлед " "повикване на sane_read()." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Върни SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_IO_ERROR Ñлед повикване " "на sane_read()." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Върни SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_NO_MEM Ñлед повикване " "на sane_read()." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Върни SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Ðакарай бекенда да върне ÑтатуÑ-кода SANE_STATUS_ACCESS_DENIED Ñлед " "повикване на sane_read()." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Вкл. лампа" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Включи лампата на Ñкенера" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Изкл. лампа" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Изключва лампата на Ñкенера" #: backend/sm3840.c:760 #, fuzzy, no-c-format msgid "Lamp timeout" msgstr "Изкл. лампа" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Feeder за документи" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (инча)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8Ñ…10 (инча)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8,5Ñ…11 (инча)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "ÐÑма поддръжка на полутонове" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Брой на Ñканиращите линии, които ще бъдат поиÑкани при SCSI четене. " "ПромÑната на този параметър позволÑва да Ñе наÑтрои ÑкороÑтта, Ñ ÐºÐ¾Ñто " "Ñе четат данни от Ñкенера по време на Ñканиране. Ðко е прекалено ниÑък, " "Ñкенерът ще Ñпира периодично по Ñредата на Ñканирането; ако е твърде " "виÑок, X-базираните четци могат да Ñпрат да отговарÑÑ‚ на ÑъбитиÑта по X " "и ÑиÑтемата ви може да увиÑне." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Извади документа Ñлед Ñканиране" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Режим на превю" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Избира режима на превю. Превю по Ñива Ñкала обикновено дава най-добро " "Ñъотношение между ÑкороÑÑ‚ и детайлноÑÑ‚." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Предефинирани наÑтройки" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "ОÑигурÑва Ñтандартни площи за Ñканиране за Ñнимки, принтирани Ñтраници и " "подобни." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "flatbed Ñкенер" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Ðвто изваждане" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "ÐŸÐ¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° фокуÑа" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "ÐŸÐ¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° фокуÑа" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Цветни линии на четене" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Линии на четене по Ñива Ñкала" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "ЦвÑÑ‚ RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "ЦвÑÑ‚ RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "ЦвÑÑ‚ RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Солидно черно" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Солидно бÑло" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Цветови деÑен" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Решетка" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Първо въвеждане" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Второ въвеждане" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Това е много дългото трето въвеждане. Може би фронтендът ще може да го " "покаже." #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° ръчен Ñкенер" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Симулира ръчен Ñкенер. Ръчните Ñкенери не знаÑÑ‚ виÑочината на " "изображението а приори. ВмеÑто това, те връщат виÑочина от -1. " "ÐаÑтройката на тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñва да теÑтвате дали четецът може " "правилно да Ñе Ñправи Ñ Ñ‚Ð¾Ð²Ð°. Също така, опциÑта позволÑва фикÑирана " "ширина от 11 Ñм." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Ð¡Ð¸Ð¼ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð½Ð° тройно минаване" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Симулира Ñкенер Ñ Ñ‚Ñ€Ð¾Ð¹Ð½Ð¾ минаване. Ð’ цветен режим Ñе предават три фрейма." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "ÐаглаÑÑ Ð¿Ð¾Ñ€ÐµÐ´Ð½Ð¾Ñтта на фреймовете." #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "" "ÐаглаÑÑ Ð¿Ð¾Ñ€ÐµÐ´Ð½Ð¾Ñтта на фреймовете в цветен режим при тройно минаване." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Специални опции" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Избира картинка за теÑтване" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Избира вида на картинката за теÑтване. Възможни опции:\n" "Солидно черно: запълва цÑлото изображение Ñ Ñ‡ÐµÑ€Ð½Ð¾.\n" "Солидно бÑло: запълва цÑлото изображение Ñ Ð±Ñло.\n" "Цветен деÑен: риÑува различни цветни теÑтови деÑени, в завиÑимоÑÑ‚ от " "режима.\n" "Решетка: риÑува черно-бÑла решетка Ñ ÑˆÐ¸Ñ€Ð¾Ñ‡Ð¸Ð½Ð° и виÑочина от 10 мм на " "квадрат." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Смени endianness" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Ð¡Ð¼ÐµÐ½Ñ Ð¼ÐµÑтата на Ð³Ð¾Ñ€Ð½Ð¸Ñ Ð¸ Ð´Ð¾Ð»Ð½Ð¸Ñ Ð±Ð°Ð¹Ñ‚ данни в 16-битовите режими. Тази " "Ð¾Ð¿Ñ†Ð¸Ñ Ð¼Ð¾Ð¶Ðµ да Ñе използва за теÑтване на 16-битовите режими на " "фронтендовете, напр. дали фронтендът използва Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð½Ð¸Ñ endianness " "(метод за запазване на данни в паметта на компютъра." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Лимит на четене" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Ограничава количеÑтвото данни, предадени Ñ Ð²ÑÑко повикване на " "sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Размер на лимита на четене" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "(МакÑималното) количеÑтво данни, предадени Ñ Ð²ÑÑко повикване на " "sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "ЗабавÑне при четене" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "ЗабавÑне на транÑфера на данни по линиÑта." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "ПродължителноÑÑ‚ на забавÑнето при четене" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "Колко дълго да Ñе чака Ñлед предаването на вÑеки буфер данни." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Връщана ÑтойноÑÑ‚ на sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Избира връщаната ÑтойноÑÑ‚ на sane_read(). \"ВиÑÑща\" (Default) е " "нормалната ÑтойноÑÑ‚ за Ñканиране. Ð’Ñички други ÑтатуÑ-кодове Ñа за " "теÑтване на това как Ñе ÑÐ¿Ñ€Ð°Ð²Ñ Ñ„Ñ€Ð¾Ð½Ñ‚ÐµÐ½Ð´Ð° Ñ Ñ‚ÑÑ…." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Загуба на пикÑели на линиÑ" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "БроÑÑ‚ пикÑели, които Ñе губÑÑ‚ в ÐºÑ€Ð°Ñ Ð½Ð° вÑÑка линиÑ." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Параметри за мъглÑвоÑÑ‚" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Върни мъглÑви линии и байтове на линиÑ, когато sane_parameters() е " "извикано преди sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Използвай неблокиращ IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Използва неблокиращ IO порт за sane_read(), ако фронтенда го поддържа." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Предложи select file descriptor" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Предлага Ñпециален filedescriptor за детектване дали sane_read() ще " "върне данни." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Позволи теÑтови опции" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "ПозволÑва различни теÑтови опции. Използвайте го, за да теÑтвате " "ÑпоÑобноÑтта на фронтендовете да виждат и модифицират вÑичките типове " "опции на SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Принт на опциите" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Изважда разпечатка на вÑички опции." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Булеви теÑтови опции" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Булева мек избор мек детект" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¼ÐµÐº избор и мек детект (и разширени) " "възможноÑти. Това е проÑто нормална булева опциÑ." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Булева твърд избор и мек детект" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ñ‚Ð²ÑŠÑ€Ð´ избор и мек детект (и разширени) " "възможноÑти. Това означава, че опциÑта не може да Ñе наглаÑи от " "фронтенда, а Ñамо от Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ (напр. чрез натиÑкане на бутон върху " "уÑтройÑтвото)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Булева твърд избор" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ñ‚Ð²ÑŠÑ€Ð´ избор (и разширени) възможноÑти. Това " "означава, че опциÑта не може да Ñе налаÑÑ Ð¾Ñ‚ фронтенда, а Ñамо от " "Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ (напр. чрез натиÑкане на бутон върху уÑтройÑтвото) и " "фронтендът не може да Ñ Ñ‡ÐµÑ‚Ðµ." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Булева мек детект" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¼ÐµÐº детект (и разширени) възможноÑти. Това " "означава, че опциÑта е Ñамо за четене (read-only)." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Булева мек избор мек детект емулирана" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¼ÐµÐº избор, мек детект и емулирани (и " "разширени възможноÑти." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Булева мек избор мек детект авто" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Булева теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¼ÐµÐº избор, мек детект и автоматични (и " "разширени) възможноÑти. Тази Ð¾Ð¿Ñ†Ð¸Ñ Ð¼Ð¾Ð¶Ðµ автоматично да Ñе наглаÑи от " "бекенда." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Int теÑтови опции" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Int" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ· Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð¸ единица." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Int ограничен обхват" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° пикÑел и наглаÑен обхват на " "ограничение. Минимумът е 4, макÑимумът е 192, а Ñтъпката е 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Int ограничен word list" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° бит и наглаÑен ограничен word " "list." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Int array" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° мм; използва array без " "ограничениÑ." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Int array ограничен обхват" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° dpi; използва array Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ " "обхват. Минимумът е 4, макÑимумът е 192, а Ñтъпката е 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Int array ограничен word list" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Интегрална теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° процент; използва array Ñ " "ограничен word list." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "ФикÑирани теÑтови опции" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) ФикÑирана" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) ФикÑирана теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ· наглаÑена единица и ограничениÑ." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) ФикÑирана ограничение обхват" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) ФикÑирана теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ ÐµÐ´Ð¸Ð½Ð¸Ñ†Ð° микроÑекунда и наглаÑен " "ограничен обхват. Минимумът е -42,17, макÑимумът 32767,9999, а Ñтъпката " "е 2,0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) ФикÑирана ограничен word list" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) ФикÑирана теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ· наглаÑена единица и Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ word " "list." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Стрингови теÑтови опции" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) String" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Стрингова теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ð±ÐµÐ· ограничение." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) String ограничен string list" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) Стрингова теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ string list." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) String Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½ long string list" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) Стрингова теÑтова Ð¾Ð¿Ñ†Ð¸Ñ Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡Ð¸Ñ‚ÐµÐ»ÐµÐ½ string list. Съдържа " "повече ÑтойноÑти..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Бутонни теÑтови опции" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Button" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Бутонна теÑтова опциÑ. Извежда нÑкакъв текÑÑ‚..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "ЦвÑÑ‚ 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Използвай композициÑта на изображението." #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Черно и бÑло в две нива (режим lineart)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Dither/полутон черно и бÑло (режим полутон)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Черно и бÑло в много нива (режим Ñива Ñкала)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "RGB цветно в много нива (Ñ ÐµÐ´Ð½Ð¾ минаване)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Игнорирай калибрациÑта" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Забрани предв. фокуÑ" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Ðе калибрирай фокуÑа" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Ръчен предв. фокуÑ" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "ФикÑирай Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° фокуÑа" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "ÐšÐ°Ð»Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° лещата в Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Калибрирай фокуÑа на лещата в Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "ÐŸÐ¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° holder фокуÑа 0мм" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Използвай 0мм Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° holder фокуÑа, вмеÑто 0,6мм" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Режим калибрациÑ" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Дефинирай режима на калибрациÑ" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Включва/изключва лампата" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA вкл." #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Включва/изключва UTA" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "ОфÑет" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "ÐаÑтройки по офÑета на цветните канали" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "ОфÑет - Ñиво" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "ÐаглаÑÑ Ð¾Ñ„Ñета на ÑÐ¸Ð²Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "ÐаглаÑÑ Ð¾Ñ„Ñета на Ñ‡ÐµÑ€Ð²ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "ÐаглаÑÑ Ð¾Ñ„Ñета на Ð·ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "ÐаглаÑÑ Ð¾Ñ„Ñета на ÑÐ¸Ð½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Режим на превю" #~ msgid "Grayscale" #~ msgstr "Ð’ Ñива Ñкала" #~ msgid "Binary" #~ msgstr "Двоичен" #, fuzzy #~ msgid "Display a shortened resolution list" #~ msgstr "Покажи кратък ÑпиÑък Ñ Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ð¸" #~ msgid "Black & White" #~ msgstr "Черно и бÑло" sane-backends-1.0.27/po/es.po0000664000175000017500000047224013110600537012614 00000000000000# Spanish (Castilian)translation of sane-backends.po # Copyright (C) 2002 SANE Project. # This file is distributed under the same license as the sane-backends package. # Miguel Anxo Bouzada ,2009. msgid "" msgstr "" "Project-Id-Version: sane-backends\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2009-06-25 10:22+0100\n" "Last-Translator: Miguel Anxo Bouzada \n" "Language-Team: GALPon MiniNo \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" "Plural-Forms: nplurals=2: plural=(n != 1);\n" "X-Poedit-Language: Spanish\n" "X-Poedit-Country: SPAIN\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Número de opciones" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Estándar" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometría" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Mejora" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Avanzado" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Sensores" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Previsualizar" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Forzar vista previa monocroma" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bit de profundidad" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Modo de escaneo" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Velocidad de escaneo" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Origen de escaneo" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Forzar retroceso" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Arriba-izquierda X" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Arriba-izquierda Y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Abajo-derecha X" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Abajo-derecha Y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Resolución de escaneo" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Resolución X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Resolución Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Ancho de página" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Altura de página" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Usar tabla gamma personalizada" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Intensidad de imagen" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Intensidad de rojo" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Intensidad de verde" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Intensidad de azul" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Brillo" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contraste" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Tamaño del grano" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Medios tonos" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Nivel de negro" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Nivel de blanco" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Nivel de blanco para rojo" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Nivel de blanco para verde" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Nivel de blanco para azul" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Sombra" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Sombra para rojo" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Sombra para verde" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Sombra para azul" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Resalte" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Resalte para rojo" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Resalte para verde" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Resalte para azul" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Matiz" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturación" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Nombre de archivo" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Tamaño del patrón de medios tonos" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Patrón de medios tonos" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Enlazar resoluciones X e Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativo" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Calibración de calidad" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Doble resolución óptica" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Enlazar RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Umbral" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Corrección gamma analógica" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Gamma analógico rojo" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Gamma analógico verde" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Gamma analógico azul" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Enlazar gamma analógico" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Calentamiento de lámpara" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Cal. tiempo de exposición" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Cal. tiempo de exposición para rojo" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Cal. tiempo de exposición para verde" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Cal. tiempo de exposición para azul" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Tiempo de exposición para escaneo" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Tiempo de exposición para rojo" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Tiempo de exposición para verde" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Tiempo de exposición para azul" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Ajustar tiempo de exposición" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Cal. densidad de lámpara" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Densidad de lámpara de escaneo" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Ajustar densidad de lámpara" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Apagar la lámpara al salir" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Opción de sólo lectura que establece cuantas opciones soporta un " "dispositivo específico." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Origen, opciones de modo y resolución" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Opciones del área de escaneo y tamaño del soporte" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Opciones de modificación de imagen" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Opciones especificas de hardaware" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Sensores y botones del escáner" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Solicitar una vista previa de calidad del escaneo." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Solicitar que todas las vistas previas sean hechas en modo monocromo. En " "un escáner de tres pasadas esto reduce el número de pasadas a una, y en " "un escáner de una pasada esto reduce los requisitos de memoria y el " "tiempo de escaneo de la vista previa." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Número de bits por muestra, valores típicos son 1 para «linea de arte» y " "8 para escaneos multibit." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Selecciona el modo de escaneo (ej. línea de arte, monocromo, ó color)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Determina la velocidad a la que se hace el escaneo." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "" "Selecciona el origen del escaneo (tal como un alimentador de documentos)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Controla si se fuerza el retroceso" #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Posición X arriba-izquierda del área de escaneo." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Posición Y arriba-izquierda del área de escaneo." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Posición X abajo-derecha del área de escaneo." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Posición Y abajo-derecha del área de escaneo." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Ajusta la resolución de la imagen escaneada." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Ajusta la resolución horizontal de la imagen escaneada." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Ajusta la resolución vertical de la imagen escaneada." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Especifica la anchura del soporte. Necesario para el centrado automático " "de hojas de escaneo." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Especifica la altura del soporte" #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "Determina si debe usarse una tabla gamma interna ó personalizada." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Tabla de corrección gamma. En modo color ésta opción afecta igualmente a " "los canales de rojo, verde y azul simultáneamente (ej. es una tabla de " "intensidad gamma)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Tabla de corrección gamma para la gama roja." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Tabla de corrección gamma para la gama verde." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Tabla de corrección gama para la gamma azul." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Controla el brillo de la imagen obtenida." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Controla el contraste de la imagen obtenida." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Selecciona el «granulado» de la imagen obtenida. Valores más pequeños " "dan como resultado imágenes mejor definidas." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Selecciona si la imagen obtenida debe ser convertida a medios tonos " "(punteado)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Selecciona que nivel de radiancia debe tenerse en cuenta «negro»." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Selecciona que nivel de radiancia debe tenerse en cuenta «blanco»." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Selecciona que nivel de radiancia rojo debe tenerse en cuenta «blanco»." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Selecciona que nivel de radiancia verde debe tenerse en cuenta «blanco»." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Selecciona que nivel de radiancia azul debe tenerse en cuenta «blanco»." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Selecciona que nivel de radiancia rojo debe tenerse en cuenta «negro»." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Selecciona que nivel de radiancia verde debe tenerse en cuenta «negro»." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Selecciona que nivel de radiancia azul debe tenerse en cuenta «negro»." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Selecciona que nivel de radiancia rojo debe tenerse en cuenta «rojo " "total»." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Selecciona que nivel de radiancia verde debe tenerse en cuenta «verde " "total»." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Selecciona que nivel de radiancia azul debe tenerse en cuenta «azul " "total»." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Contola el «matiz» (nivel de azul) de la imagen obtenida." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "El nivel de saturación controla la cantidad de «florecimiento» (halo) " "que ocurre cuando se obtiene una imagen con una cámara. Valores más " "altos producen más florecimiento." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Nombre de archivo de la imagen a cargar." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Ajusta el tamaño del patrón de medios tonos (punteado) usado cuando se " "escanean imágenes de medios tonos." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Define el patrón de medios tonos (punteado) para escanear imágenes de " "medios tonos." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Usar los mismos valores para la resolución X e Y." #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Intercambiar blanco y negro" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Hacer una calibración de calidad de blancos " #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Usar lente que duplica la resolución óptica" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "En modo RGB usar los mismos valores para cada color" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Seleccionar el brillo mínimo para obtener un punto blanco" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Corrección gamma analógica" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Corrección gamma analógica para rojo" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Corrección gamma analógica para verde" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Corrección gamma analógica para azul" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Calentar la lámpara antes de escanear" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Definir tiempo de exposición para calibración" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Definir tiempo de exposición para calibración de rojo" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Definir tiempo de exposición para calibración de verde" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Definir tiempo de exposición para calibración de azul" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Definir tiempo de exposición para escaneo" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Definir tiempo de exposición para escaneo de rojo" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Definir tiempo de exposición para escaneo de verde" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Definir tiempo de exposición para escaneo de azul" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Activar selección del tiempo de exposición" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Definir densidad de la lámpara para calibración" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Definir densidad de la lámpara para escaneo" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Activar la selección de la densidad de la lámpara" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Apaga la lámpara al salir del programa" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Botón de control de escaneo" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "Botón de correo-e" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Botón de fax" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Botón de copia" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "Botón de PDF" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Botón de cancelar" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Página cargada" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "La tapa está abierta" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Color" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Linea de arte a color" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Medios tonos a color" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Gris" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Medios tonos" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Línea de arte" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "Importación con éxito" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Operación no soportada" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "La operación va a ser cancelada" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "Dispositivo ocupado" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Argumento incorrecto" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "Fin de archivo alcanzado" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Alimentador de documentos atascado" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "El alimentador de documentos está vacio" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "La tapa del escáner está abierta" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Error en dispositivo de E/S" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "No queda memoria" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "Se ha denegado el acceso al recurso" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "La lámpara no está preparada, intentelo de nuevo" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "El escáner está bloqueado para transporte" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Predeterminados" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Ajustar valores predeterminados para los controles de mejora." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Calibración" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Calibrar antes del siguiente escaneo" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Si se activa, el dispositivo se calibrará antes del siguiente escaneo. " "En otro caso, la calibración se realizará únicamente antes del primer " "escaneo." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Realizar sólo correcciones de sombras" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Si está activado, sólo se realizarán correcciones de sombras durante la " "calibración. Se usarán los valores predeterminados de ganancia, " "desplazamiento y tiempo de exposición, ya sean los que trae incorporados " "el programa o los del archivo de configuración." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Botón de estado" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Número de muestra a escanear" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Selecciona el número de muestra a escanear" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Escaneo a dos caras" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "El escaneo a dos caras proporciona un escaneo del anverso y el reverso " "del documento" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Calibrar el escáner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Fuerza la calibración del escáner antes de realizar el escaneo" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Escaneo en escala de grises" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Escanea en escala de grises, no en color" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Ganancia analógica" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Aumenta o disminuye la ganancia analógica de la gama CCD" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Corrección gamma" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Selecciona la curva de transferencia de la corrección gamma" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "En bruto" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Color fino" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Sin corrección de transparencia" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Correción de acuerdo con el tipo de película" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Corrección conforme con la tasa de transparencia" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negativos" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Diapositivas" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automático" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Velocidad normal" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 de la velocidad normal" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 de la velocidad normal" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "parámetro redondeado" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "desconocido/a" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "atasco en el alimentador" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "la tapa del alimentador está abierta" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "fallo de lámpara" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "error en el posicionamiento del cabezal de escaneo" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "Error de verificación de CPU" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "Error de verificación de RAM" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "Error de verificación de ROM" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "error de verificación de hardware" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "fallo de la lámpara de unidad de transparencias" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" "fallo de posición del cabezal de escaneo de la unidad de transparencias" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "error en la longitud de la lista de parámetros" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "código de orden de operación incorrecto" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "campo incorrecto en CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "LUN no soportado" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "campo incorrecto en la lista de parámetros" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "error en la secuencia de ordenes" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "se especificaron demasiadas ventanas" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "no se encuentra el soporte" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "mensaje de bit de IDENTIFICACIÓN incorrecto" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "la opción no conecta" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "reiniciar el encendido / reiniciar el bus del dispositivo" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parámetro cambiado por otro iniciador" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "sin información adicional" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "fallo al volver a escoger" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "error de paridad SCSI" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "el iniciador detectó la recepción deun mensaje de error" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "mensaje de error incorrecto" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "error de límite de tiempo" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "error de sombreado en la unidad de transparencias" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lámpara no estabilizada" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "escáner de películas" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "escáner plano" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Tipo de película" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Seleccionar el tipo de película, p.e. negativo o diapositiva" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Tipo de película negativo" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Selecciona el tipo de negativo de película" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Resolución del hardware" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Usar sólo resoluciones de hardware" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Enfoque" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Enfoque automático" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Activar/desactivar enfoque automático" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Enfoque automático solo una vez" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Hacer enfoque automático solo una vez entre expulsiones" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Posición de foco manual" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" "Ajustar el sistema óptico de foco en la posición manual (predeterminado: " "128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Márgenes de escaneo" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Ajustes de color extra" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Invertir imagen" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Invierte la imagen horizontalmente" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Exposición automática" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Activar/desactivar la característica de exposición automática" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Calibrar ahora" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Ejecutar calibración *ahora*" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Autodiagnóstico" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Realizar autodiagnóstico del escáner" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Reiniciar escáner" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Reiniciar el escáner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Manejar el soporte" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Expulsar la película después de cada escaneo" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" "Expulsar automáticamente la película del dispositivo después de cada " "escaneo" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Expulsar la película antes de salir" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Expulsar automáticamente la película del dispositivo antes de salir del " "programa" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Expulsar película ahora" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Expulsar la película *ahora*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Alimentador de documentos extras" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Sólo plano" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" "Desactivar el alimentador automático de documentos y usar sólo el plano" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Unidad de transparencias" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "" "Activar/desactivar la unidad de transparencias (FAU, unidad adaptadora " "de película)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Película en negativo" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Película en positivo o en negativo" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Control de densidad" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Ajustar el modo de control de densidad" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Tasa de transparencia" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Seleccionar tipo de película" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Seleccionar el tipo de película" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Plana" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, fuzzy, no-c-format msgid "ADF Front" msgstr "la tapa del alimentador está abierta" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, fuzzy, no-c-format msgid "ADF Back" msgstr "atasco en el alimentador" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "Alimentador a dos caras" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Imprimir" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Dos caras" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Rojo" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Verde" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Azul" #: backend/canon_dr.c:424 #, fuzzy, no-c-format msgid "Enhance Red" msgstr "Mejora" #: backend/canon_dr.c:425 #, fuzzy, no-c-format msgid "Enhance Green" msgstr "Mejora" #: backend/canon_dr.c:426 #, fuzzy, no-c-format msgid "Enhance Blue" msgstr "Mejora" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Ninguno" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Una cara" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Dos caras" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Unidad de transparencias" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Alimentador automático de documentos (ADF)" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Película en positivo" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Película en negativo" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Enfoque en el cristal" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Enfoque a 2.5mm sobre el cristal" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Medios tonos A (tonos duros)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Medios tonos B (tonos suaves)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Medios tonos C (matizado)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Trama A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Trama B (4x4 espiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Trama C (4x4 matizado)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Trama D (8x4 matizado)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Tecnología de mejora de texto" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Descargar patrón A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Descargar patrón B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Sin corrección" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Definida por el usuario" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Impresoras matriciales" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Impresoras térmicas" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Impresoras de inyección de tinta" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Monitores CRT" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Predeterminado" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Impresión de alta densidad" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Impresión de baja densidad" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Impresión de alto contraste" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Definido por el usuario (gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Definido por el usuario (gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 vertical" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 apaisado" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Carta" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Máx" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Modo de escaneo" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Selecciona medios tonos" #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Exclusión" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Seleccionar lo que se va a excluir." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Selecciona el brillo." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Enfoque" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Corrección de color" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "Ajusta la tabla de corrección del color para el dispositivo de salida " "seleccionado." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Coeficientes de corrección de color" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matriz de multiplicación de RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Cambiar de verde a rojo" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Cambiar de verde a azul" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Cambiar de rojo a verde" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Cambiar de rojo a azul" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Cambiar de azul a verde" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Cambiar de azul a rojo" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Controla el nivel de verde" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Añade rojo basándose en el nivel de verde" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Añade azul basándose en el nivel de verde" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Añade verde basándose en el nivel de rojo" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Controla el nivel de rojo" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Añade azul basándose en el nivel de rojo" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Añade verde basándose en el nivel de azul" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Añade rojo basándose en el nivel de azul." #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Controla el nivel de azul" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Invertir la imagen." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Vista previa rápida" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Segmentación automática de área" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Lista corta de resoluciones" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Mostrar lista corta de resoluciones" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Acercamiento" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Define el factor de zoom que usará el escáner" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Formato rápido" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Equipamiento opcional" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Expulsar" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Expulsar la hoja del alimentador" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Expulsión automática" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Expulsar el documento después del escaneo" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Modo alimentador" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Seleccionar el modo del alimentador (una cara/dos caras)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Bahía" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Seleccione la bahía para escanear" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Selecciona el valor de corrección gamma de una lista de dispositivos " "predefinidos o de una tabla definida por el usuario, que puede ser " "descargada al escáner." #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Posición del foco" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Ajusta la posición del foco, ya sea al cristal o a 2.5mm por encima del " "cristal" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Esperar por el botón" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Después de enviar la orden de escanear, esperar hasta que se presione el " "botón del escáner para empezar realmente el proceso de escaneo." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Diapositiva en positivo" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Diapositiva en negativo" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "" #: backend/epson2.c:216 #, fuzzy, no-c-format msgid "User defined CCT profile" msgstr "Definida por el usuario" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Activo" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Apagado" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Difuminado" #: backend/fujitsu.c:690 #, fuzzy, no-c-format msgid "Diffusion" msgstr "Difusión de error" #: backend/fujitsu.c:695 #, fuzzy, no-c-format msgid "White" msgstr "Nivel de blanco" #: backend/fujitsu.c:696 #, fuzzy, no-c-format msgid "Black" msgstr "Nivel de negro" #: backend/fujitsu.c:701 #, fuzzy, no-c-format msgid "Continue" msgstr "Condicional" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontal" #: backend/fujitsu.c:709 #, fuzzy, no-c-format msgid "Horizontal bold" msgstr "Horizontal" #: backend/fujitsu.c:710 #, fuzzy, no-c-format msgid "Horizontal narrow" msgstr "Horizontal" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertical" #: backend/fujitsu.c:712 #, fuzzy, no-c-format msgid "Vertical bold" msgstr "Vertical" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "" #: backend/fujitsu.c:717 #, fuzzy, no-c-format msgid "Front" msgstr "Imprimir" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Medios tonos" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Calibración de precisión" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Resalte de imagen" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Saturación" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "" "Activar la determinación automática de umbral para escaneos como línea " "de arte." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Invertir imagen" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Invertir la imagen horizontalmente." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Nivel de blanco para azul" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Controla el nivel de rojo" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Filtro de color" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Suavizado" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Valor gamma" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, fuzzy, no-c-format msgid "Threshold curve" msgstr "Umbral" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Umbral" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Reducción de ruido" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Sin corrección" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Sin corrección" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "la tapa del alimentador está abierta" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Opciones avanzadas" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Sin corrección" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Exclusión" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Modo de alimentación" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Tiempo de espera de la lámpara" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Desviación azul" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Desviación verde" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Desviación verde" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Desviación azul" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Ajusta el desplazamiento del canal de azul" #: backend/fujitsu.c:3980 #, fuzzy, no-c-format msgid "Low Memory" msgstr "No queda memoria" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Escaneo a dos caras" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Opciones avanzadas" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Reducción de ruido" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Del papel" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Del papel" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Del papel" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Del papel" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "La tapa del escáner está abierta" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Foco previo manual" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Foco previo manual" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "error de verificación de hardware" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Nivel de blanco" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Control de densidad" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Control de densidad" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Escaneo a dos caras" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extras" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Desactivar interpolación" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "Cuando se usan altas resoluciones en las que la resolución horizontal es " "más pequeña que la vertical, esto desactiva la interpolación horizontal." #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Filtro de color" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "Cuando se usa gris o línea de arte esta opción selecciona el color usado." #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Calibración" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Define el modo de calibración" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Caché de datos de calibración" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Tiempo de espera de la lámpara" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "La lámpara será apagada después del tiempo dado (en minutos). Un valor " "de 0 significa que la lámpara no será apagada" #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Apagar la lámpara durante la calibración de oscuridad" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "Minutos que tardará la lámpara en apagarse tras el escaneo" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Botón de archivo" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "Botón de OCR" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Botón de energía" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "Botón de correo-e" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, fuzzy, no-c-format msgid "Need calibration" msgstr "Limpiar la calibración" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, fuzzy, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Fuerza la calibración del escáner antes de realizar el escaneo" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Botones" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Calibrar" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Iniciar calibración usando una hoja especial" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Limpiar la calibración" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Limpiar la caché de datos de calibración" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Adaptador de transparencias" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Color en modo gris" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Selecciona qué color de escaneo se usará en modo gris (predefinido: " "verde)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Opciones de depuración" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Calentamiento automático" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Calentar hasta que el brillo de la lámpara sea constante en vez de " "esperar por los 60 segundos de calentamiento." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Escaneo completo" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Escanear todo el área de escaneado incluyendo la franja de calibración. " "Tenga cuidado. No seleccione la altura total. Sólo para pruebas." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Calibración tosca" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Configuración de la ganancia y desplazamiento para escanear " "automáticamente. Si esta opción está desactivada, se proporcionan las " "opciones de ajuste de los parámetros de forma manual en la interfaz " "analógica. Esta opción está activada como predefinida. Solo para pruebas." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Calibración tosca sólo para el primer escaneo" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "La calibración tosca se hace sólo para el primer escaneo. Funciona con " "la mayoría de escáneres y puede ahorrar tiempo de escaneo. Si el brillo " "de la imagen es diferente con cada escaneo, desactive esta opción. Sólo " "para pruebas." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Lineas de vuelta atrás" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Número de líneas que retrocede el escáner cuando escanea más rápido de " "lo que el equipo puede recibir datos. Valores bajos hacen que los " "escaneos sean más rápidos, pero aumentan los riesgos de omitir líneas." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Valor gamma" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Ajusta el valor gamma para todos los canales." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Grupo de geometría" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Grupo de modo de escaneo" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Diapositiva" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Modelo de escáner" #: backend/hp3900_sane.c:1408 #, fuzzy, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" "Permite comprobar el comportamiento del dispositivo con otros modelos " "soportados" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Las imágenes de color se invertirán" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Desactivar corrección gamma" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "La corrección gamma se desactivará" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Desactivar la corrección de sombra blanca" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "La corrección de sombra blanca se desactivará" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Omitir proceso de calentamiento" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "El proceso de calentamiento se desactivará" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Forzar profundidad real" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "Si gamma está activada, siempre se analiza en profundidad de 16 bits " "para mejorar la calidad de la imagen y después convertirla a la " "profundidad seleccionada. Esta opción evita la emulación de profundidad." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Emular escala de grises" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "Si está activada, la imagen será escaneada en modo de color y después " "convertida a escala de grises por software. Esto puede mejorar la " "calidad de la imagen en algunas circunstancias." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Guardar imágenes de depuración" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "Si se activa, algunas imágenes implicadas en el proceso de escaneo se " "guardarán para analizarlas." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Reiniciar el chipset" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Reiniciar los datos del chipset" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Información" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Nombre del chipset" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Muestra el nombre del chipset usado en el dispositivo." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Desconocido" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "ID del chipset" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Mostrar la ID del chipset" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Contador de escaneos" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Mostrar el número de escaneos hechas por el escáner" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Actualizar información" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Actualiza la información acerca del dispositivo" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Esta opción refleja un botón del panel frontal del escáner" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Imagen" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Varios" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "posición X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Posición X interna en el hardware de la zona de escaneo." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "posición Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Posición Y interna en el hardware de la zona de escaneo." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Estado de la lámpara" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Enciende o apaga la lámpara" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Calibrar el nivel de blanco y negro." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "Alimentador automático de documentos (ADF)" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "Adaptador (TMA) para diapositivas" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "Adaptador (TMA) para negativos" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Color (48 bits)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Retardar el tiempo de apagado de la lámpara" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "" "Retarda los tiempos de apagado de la lámpara (de 15 minutos a 1 hora)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Esperando por el botón" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Esperando por el botón antes de escanear" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Opciones avanzadas" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Gruesa" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fina" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Personalizado" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Auto" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "Adaptador de transparencias RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "A través" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Gris" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "Adaptador de transparencias gris" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Lento" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Rápido" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Muy rápido" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-píxeles" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-píxeles" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-píxeles" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Imprimir" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Tira de película" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "Adaptador de transparencias (XPA)" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Condicional" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Experimento" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Nitidez" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Ajustar el valor de nitidez." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Umbral automático" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Activar la determinación automática de umbral para escaneos como línea " "de arte." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Seleccionar filtro de suavizado." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Descargar soporte después de escanear" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Descargar los soportes después de escanear." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Cambiar documento" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Cambiar documento." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Descargar" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Descargar documento" #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Iniciar proceso de calibración" #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Soporte" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Ajustar tipo de soporte." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Tiempo de exposición" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Una exposición prolongada permite al escáner recoger más luz. Se sugiere " "usar 175% para impresiones, 150% para diapositivas normales y «Negativo» " "para película en negativo. Para imágenes oscuras (subexpuestas) puede " "incrementar este valor." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Matriz de color" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Ajustar la matriz de color del escáner." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Matriz de color personalizada." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Matriz monocromo" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Matriz de color personalizada para escáneres en escala de grises." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Inversión horizontal" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Invertir la imagen horizontalmente." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Inversión vertical" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Invertir la imagen verticalmente." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Actualizar opciones" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Actualizar opciones." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "Salida de 8 bits" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Usar bit de profundidad mayor de ocho internamente, pero en la salida " "usar sólo ocho bits." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Esperar botón frontal" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Esperar a que se presione en el botón frontal para escanear." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Apagar lámpara" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Apagar la lámpara del escáner." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Tamaño del papel" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Separación automática" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 apaisado" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "Ajustar el modo de control de densidad" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Foco previo manual" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Foco previo manual" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Activa el escaneo por las dos caras" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Tamaño físico del papel en el alimentador" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Medios tonos" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Color" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Condicional" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Apagado" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Medios tonos" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Medios tonos" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Difusión de error" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Resalte" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "escáner de películas" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Del papel" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Predeterminado" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Suave" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Lento" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Soporte" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Rojo" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Verde" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Origen de escaneo" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Modo de alimentación" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Ajusta el modo de alimentación" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Activar/desactivar enfoque automático" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Ajustar el modo de control de densidad" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Ajusta el modo de alimentación" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Ajusta el modo de alimentación" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Umbral automático" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Ajusta automáticamente el brillo, contraste, niveles de blanco, gamma y " "reducción de intensidad del ruido de la imagen" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Reducción de ruido" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Reduce los puntos aislados de ruido" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Resalte de imagen" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Ajusta el resalte de la imagen" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Encender lámpara" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Enciende o apaga la lámpara" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Invertir la imagen verticalmente." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Corrección gamma" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Impresión de alta densidad" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Impresión de baja densidad" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Difusión de error" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Sin corrección" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normal" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Mejora" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Umbral automático" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Umbral automático" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Ajustar el orden de las muestras" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Sombra para azul" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Cambiar de rojo a azul" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamante" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 «Engrasado» tosco" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 «Engrasado» fino" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Línea vertical" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Ganancia" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Ajustes de ganancia de los canales de color" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Ganancia de gris" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Ajusta la ganancia del canal de gris" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Ganancia de rojo" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Ajusta la ganancia del canal de rojo" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Ganancia de Verde" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Ajusta la ganancia del canal de verde" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Ganancia de Azul" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Ajusta la ganancia del canal de azul" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Trama Bayer 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Trama Bayer 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Medio tono punto 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Medio tono punto 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Difusión de error" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Modo 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Modo 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Modo 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "De palo blanco" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Suave" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Bajo" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Soporte" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Alto" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Una página" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Todas las páginas" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "escáner con cargador automático" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Escala de grises de 4 bits" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Escala de grises de 8 bits" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Sombras, medias tintas, resalte, tiempo de exposición" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Opciones especiales" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Balance de color" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Desactivar retroceso" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Si se selecciona, el escáner no retrocede cuando pierde una línea" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Conmutar el estado de lámpara del plano" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Conmuta el estado de lámpara del plano" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Calibración por el motor" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Si se selecciona la calibración del color antes del escaneo la hace el " "motor" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Usar el adaptador de diapositivas de 35mm" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Esta opción apaga la lámpara del plano durante el escaneo" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Escaneo de calidad" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "La mejor calidad, pero a velocidad lenta" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Escaneo rápido" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Más rápido, pero de peor calidad" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Ajuste automático de umbral" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Si se selecciona, el motor intenta determinar automáticamente un valor " "óptimo para el umbral." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Selecciona el modo de corrección gamma" #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Asociar gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Usar los mismos valores gamma para todos los canales de colores." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Gamma escalar" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Seleccionar un valor para la corrección gamma escalar." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Gamma escalar rojo" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "" "Seleccionar un valor para la corrección gamma escalar (canal de rojo)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Gamma escalar verde" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "" "Seleccionar un valor para la corrección gamma escalar (canal de verde)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Gamma escalar azul" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "" "Seleccionar un valor para la corrección gamma escalar (canal de azul)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Canal" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Selecciona la gama de color, «Master» significa que afecta a todos los " "colores." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Medias tintas" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Selecciona que nivel de radiancia debe ser considerado «50% gris»." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Medias tintas para rojo" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Selecciona que nivel de radiancia debe ser considerado «50% rojo»." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Medias tintas para verde" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" "Selecciona que nivel de radiancia debe ser considerado «50% verde»." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Medias tintas para azul" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Selecciona que nivel de radiancia debe ser considerado «50% azul»." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Balance de rojo" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" "Factor de balance para rojo. Un valor de 100% significa sin corrección." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Balance de verde" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" "Factor de balance para verde. Un valor de 100% significa sin corrección." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Balance de azul" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" "Factor de balance para azul. Un valor de 100% significa sin corrección." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Balance de firmware" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" "Ajusta el balance de color a los valores facilitados por el firmware." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "El más lento" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Más lento" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Más rápido" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "El más rápido" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 tosco" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fino" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 muy fino" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normal" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 tosco" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fino" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 tosco" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normal" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fino" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 personalizado" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 personalizado" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 personalizado" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 personalizado" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 personalizado" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 personalizado" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Modo gris rápido" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Escanear en modo gris rápido (menor calidad)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Precisa que todas las vistas previas se hagan del modo más rápido (baja " "calidad). Este puede ser un modo sin color o un modo de baja resolución." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Tiempo de apagado de lámpara (minutos)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Ajustar el tiempo (en minutos) tras el que se apagará la lámpara." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Apagar la lámpara" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Apaga la lámpara inmediatamente." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Brillo de rojo" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Controla el brillo del canal de rojo de la imagen obtenida." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Brillo de verde" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Controla el brillo del canal de verde de la imagen obtenida." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Brillo de azul" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Controla el brillo del canal de azul de la imagen obtenida." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contraste de canal de rojo" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Controla el contraste del canal de rojo de la imagen obtenida." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contraste de canal de verde" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Controla el contraste del canal de verde de la imagen obtenida." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contraste de canal de azul" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Controla el contraste del canal de azul de la imagen obtenida." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Color 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Color 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Gris 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Gris 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Reflectantes" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positivo" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Calentar hasta que el brillo de la lámpara sea constante en vez de " "esperar por los 40 segundos de calentamiento." #: backend/pixma.c:378 #, fuzzy, no-c-format msgid "Negative color" msgstr "Película en negativo" #: backend/pixma.c:383 #, fuzzy, no-c-format msgid "Negative gray" msgstr "Negativo" #: backend/pixma.c:396 #, fuzzy, no-c-format msgid "48 bits color" msgstr "Color fino" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Botón de control de escaneo" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Habilitado, el proceso de escaneo no comenzará inmediatamente. Para " "proceder, haga clic en el botón \"SCAN\" (para MP150) o \"COLOR\" (para " "otros modelos). Para cancelar, haga clic en el botón \"GRAY\"." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Actualizar estado del botón" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Botón 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Botón 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Transparencia" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Ajustes del dispositivo" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Interruptor de lámpara" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Cambiar la(s) lámpara(s) manualmente." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Apagar la lámpara durante la calibración de oscuridad" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Apagar siempre la lámpara cuando se calibra la oscuridad." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Caché de datos de calibración" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Activa o desactiva la caché de datos de calibración" #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Calibración de precisión" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Acelerar el sensor" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Activa o desactiva la aceleración de movimiento del sensor." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Tiempo de calentamiento" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Tiempo de calentamiento en segundos." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Tiempo de apagado de lámpara" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Tiempo de apagado de lámpara en segundos." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Interfaz analógica (AFE)" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Valor de ganancia de rojo en el AFE" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Desviación rojo" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Valor de la desviación de rojo en el AFE" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Valor de ganancia de verde en el AFE" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Valor de la desviación de verde en el AFE" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Valor de ganancia de azul en el AFE" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Valor de la desviación de azul en el AFE" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Apagar lámpara roja" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Define los parámetros de apagado de lámpara roja" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Apagar lámpara verde" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Define los parámetros de apagado de lámpara verde" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Apagar lámpara azul" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Define los parámetros de apagado de lámpara azul" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Esta opción refleja el estado de los botones del escáner" #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Color 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Mapa de trama 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Mapa de trama 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Aleatorio" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Selección de origen" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Mejora de la Imagen" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Agrisar" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Cargar la imagen como escala de grises." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Simulación de tres pasadas" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simula un escáner de tres pasadas devolviendo 3 muestras separadas. Por " "diversión, devuelve verde, después azul y finalmente rojo." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Simulación de escáner manual" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simula un escáner de mano. Los escáneres de mano a menudo no conocen a " "priori la distancia a la imagen. En su lugar utiliza una altura de " "retorno -1. Ajustando esta opción permite comprobar si una interfaz " "puede manejar esto correctamente." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Ajustar los valores predeterminados para los controles de mejora (brillo " "y contraste)" #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Opción de prueba de sólo lectura" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Veamos si la interfaz puede tratar esto correctamente" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Tablas gamma" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Simulación del código de estado" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "No forzar el código de estado" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "No forzar al motor a devolver un código de estado." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Devuelve SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Forzar al motor a devolver el código de estado de SANE_STATUS_EOF " "después de haber sido llamado sane_read()." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Devuelve SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Forzar al motor a devolver el código de estado de SANE_STATUS_JAMMED " "después de haber sido llamado sane_read()." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Devuelve SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Forzar al motor a devolver el código de estado de SANE_STATUS_NO_DOCS " "después de haber sido llamado sane_read()." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Devuelve SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Forzar al motor a devolver el código de estado de SANE_STATUS_COVER_OPEN " "después de haber sido llamado sane_read()." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Devuelve SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Forzar al motor a devolver el código de estado de SANE_STATUS_IO_ERROR " "después de haber sido llamado sane_read()." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Devuelve SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Forzar al motor a devolver el código de estado de SANE_STATUS_NO_MEM " "después de haber sido llamado sane_read()." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Devuelve SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Forzar al motor a devolver el código de estado de " "SANE_STATUS_ACCESS_DENIED después de haber sido llamado sane_read()." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Esta opción refleja el estado de los botones del escáner" #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Encender lámpara" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Enciende la lámpara del escáner" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Apagar lámpara" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Apaga la lámpara del escáner" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Límite de tiempo de lámpara" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Minutos que tardará la lámpara en apagarse tras el escaneo" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Valor de umbral para el modo de línea de arte" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Alimentador de documentos" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (pulg.)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (pulg.)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (pulg.)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Medios tonos no compatibles" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "Punto disperso 8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "Punto disperso 16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Número de líneas de escaneo a petición de una lectura SCSI. El cambio de " "este parámetro le permite ajustar la velocidad a la que se leen los " "datos desde el escáner durante los escaneos. Si este es demasiado bajo, " "el escáner tiene que parar periódicamente en medio de un escaneo, si es " "demasiado alto, basado en interfaces X puede dejar de responder a " "eventos de X y su sistema se podría atascar." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Expulsar el documento después del escaneo" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Modo de vista previa" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Selecciona el modo para vista previa. La vista previa en escala de " "grises proporciona en general, la mejor relación entre velocidad y " "detalle." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Ajustes predefinidos" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Proporciona superficies de escaneo estándar para fotografías, páginas " "impresas, etc." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "escáner plano" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Enfoque" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Enfoque automático" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Posición del foco" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Posición del foco" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Color, líneas por lectura" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Escala de grises, líneas de por lectura" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "cámara web" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Color en BRUTO" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Color RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Color RGB TEXTO" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Negro sólido" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Blanco sólido" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Patrón de color" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Rejilla" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Primera entrada" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Segunda entrada" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Esta tercera entrada es muy larga. Tal vez la interfaz tiene una idea de " "cómo mostrarlo" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Simulación de escaneo manual" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simula un escáner de mano. Los escáneres de mano a menudo no conocen a " "priori la distancia a la imagen. En su lugar utiliza una altura de " "retorno -1. Ajustando esta opción permite comprobar si una interfaz " "puede manejar esto correctamente. Esta opción también permite un ancho " "de 11cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Simulación de tres pasadas" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simula un escaneo de tres pasadas. En el modo color, se generan tres " "muestras." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Ajustar el orden de las muestras" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "" "Ajustar el orden de las muestras en el modo de tres pasadas de color." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Si se selecciona el alimentador automático de documentos, el alimentador " "estará «vacío» tras 10 escaneos." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Opciones especiales" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Seleccione la imagen de prueba" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Selecciona el tipo de prueba de imagen. Posibles opciones:\n" "Negro sólido: llena todo el escaneo con negro.\n" "Blanco sólido: llena todo el escaneo con blanco.\n" "Patrón de color: dibuja varios patrones de prueba de color dependiendo " "del modo.\n" "Rejilla: dibuja una rejilla en blanco y negro con un tamaño de 10mm por " "cuadrado." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Invertir el orden de los datos" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Intercambia los bytes de datos superiores e inferiores de imágenes en " "modo de 16 bits. Esta opción puede utilizarse para la prueba de 16 bits " "de los modos de interfaz, p.ej. si la interfaz utiliza el orden correcto." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Límite de lectura" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Limita la cantidad de datos transferidos con cada llamada a sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Tamaño del límite de lectura" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "Cantidad de datos (máxima) transferida con cada llamada a sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Retardo de lectura" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Retardar la transferencia de datos a la canalización." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Duración del retardo de lectura" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "Cuanto tiempo se esperará después de transferir cada búfer de datos a " "través de la canalización." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Valor de retorno de sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Seleccione el valor de retorno de sane_read(). «Predeterminado» es el " "normal para hacer el escaneo. Todos los demás códigos de estado son para " "probar la forma en que la interfaz se encarga de ellos." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Pérdida de píxeles por línea" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Número de píxeles que se pierden en el extremo de cada línea." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Parámetros difusos" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Devuelve líneas difusas y bytes por línea cuando se llama a sane_start() " "antes que a sane_parameters()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Usar E/S no bloqueante" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Usar una E/S no bloqueante para sane_red() si lo permite la interfaz." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Proponer la selección de un descriptor de archivo" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Proponer la selección un descriptor de archivo para detectar si " "sane_read () devolverá los datos." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Activar opciones de prueba" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Activa varias opciones de prueba. Esto se usa para probar la capacidad " "de las interfaces para ver y modificar los diferentes tipos de opciones " "de SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Imprimir las opciones" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Imprimir una lista de todas las opciones" #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Opciones de prueba «Booleanas»" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Booleana configurable y legible por software" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Opción de prueba booleana configurable y legible por el software. " "Esta es la opción booleana normal. " #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Booleana configurable por hardware legible por software" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Opción de prueba booleana configurable por hardware y legible por " "el software. Esta opción no puede ser ajustada por la interfaz, pero si " "por el usuario (p.ej. pulsando un botón en el dispositivo)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Booleana configurable por hardware" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Opción de prueba booleana configurable por hardware. Esta opción " "no puede ser ajustada por la interfaz, pero si por el usuario (p.ej. " "pulsando un botón en el dispositivo) tampoco puede ser leída por la " "interfaz ." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Booleana lexible por software" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Opción de prueba booleana legible por el software Esta es una " "opción de sólo lectura." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Booleana configurable y legible por software, emulada" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Opción de prueba booleana configurable y legible por el software y " "emulada." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Booleana configurable y legible por software, automática" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Opción de prueba booleana configurable y legible por el software y " "emulada. Esta opción puede ser ajustada automáticamente por el motor." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Opciones de prueba «Entero»" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Entero" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" "(1/6) Opción de prueba de valor entero sin unidad ni conjunto de " "restricciones." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Entero con rango de restricciones" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Opción de prueba de valor entero con unidad de píxel y con " "conjunto de restricciones, El mínimo es 4, el máximo 192 y el salto 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Entero con restricción de lista de valores" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Opción de prueba de valor entero con unidad bits y restricción de " "lista de valores" #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Matriz de enteros" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Opción de prueba de valor entero con unidad mm usando una matriz " "con restricciones." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Matriz de enteros con rango de restricciones" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Opción de prueba de valor entero con unidad dpi y usando una " "matriz con rango de restricciones. El mínimo es 4, el máximo 192, y el " "salto 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Matriz de enteros con restricción de lista de valores" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Opción de prueba de valor entero con unidad % y usando una matriz " "con restricciones en una lista de valores," #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Opción de prueba «Real fijo»" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Real fijo" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" "(1/3) Opción de prueba de valor real (coma fija) sin unidad ni conjunto " "de restricciones." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Real fijo con rango de restricción" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Opción de prueba de valor real (coma fija) con unidad de " "microsegundo y rango de restricción. El mínimo es -42,17, el máximo " "32767,9999 y el salto 2,0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Real fijo con restricción de lista de valores" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Opción de prueba de valor real (coma fija) sin unidad y " "restringida por un conjunto de valores de una lista." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "Opciones de prueba de cadena" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) Cadena" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Opciones de prueba de cadena sin restricciones." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) Cadena restringida a lista de cadenas" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "" "(2/3) Opción de prueba de cadena con restricción de lista de cadenas" #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) Restricción de cadenas lista larga de cadenas" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) Opción de prueba de cadena con restricción de lista de cadenas. " "Contiene más entradas..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Opciones de botón de prueba" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Botón" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Botón de opción de prueba. Imprime algún texto..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Color 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Usar composición de imagen" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Dos niveles blanco y negro (modo de línea de arte)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Difuminado/medios tonos blanco y negro (modo medios tonos)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Multinivel blanco y negro (modo de escala de grises)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Multinivel color RGB (color de una pasada)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignorar calibración" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Desactivar foco previo" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "No calibrar foco" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Foco previo manual" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Fijar la posición de foco" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Calibración de lentes en la posición del documento" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Calibrar las lentes en la posición del documento" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Marcar la posición del foco a 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Usar la marca de posición de foco a 0mm en vez de a 0,6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Modo de calibración" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Define el modo de calibración" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Enciende/apaga la lámpara" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA Activado" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Ajusta el encendido/apagado UTA" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Desplazamiento" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Ajustes del desplazamiento de los canales de color" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Desplazamiento de gris" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Ajusta el desplazamiento del canal de gris" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Ajusta el desplazamiento del canal de rojo" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Ajusta el desplazamiento del canal de verde" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Ajusta el desplazamiento del canal de azul" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Modo de vista previa" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "problema no analizado (clase de SCSI desconocido)" #~ msgid "Grayscale" #~ msgstr "Escala de grises" #~ msgid "Binary" #~ msgstr "Binaria" #~ msgid "Display a shortened resolution list" #~ msgstr "Mostrar una lista de resoluciones ordenada" #~ msgid "Black & White" #~ msgstr "Blanco y negro" sane-backends-1.0.27/po/uk.po0000664000175000017500000062054713110600537012631 00000000000000# Copyright (C) 2009 # This file is distributed under the same license as the sane-backends package. # # Yuri Chornoivan , 2009, 2010, 2011, 2012, 2013, 2015, 2017. msgid "" msgstr "" "Project-Id-Version: sane-backends\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2017-04-28 19:32+0300\n" "Last-Translator: Yuri Chornoivan \n" "Language-Team: Ukrainian \n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 1.5\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "КількіÑть параметрів" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Типово" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "ÐŸÐ¾Ð·Ð¸Ñ†Ñ–Ñ Ñ– розміри" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "ПокращеннÑ" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Додатково" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Датчики" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "ПереглÑд" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "ПримуÑовий чорно-білий переглÑд" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "КількіÑть бітів на колір" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Режим ÑкануваннÑ" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "ШвидкіÑть ÑкануваннÑ" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Джерело ÑкануваннÑ" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "ПримуÑове поверненнÑ" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Ð’ÐµÑ€Ñ…Ð½Ñ Ð»Ñ–Ð²Ð° координата за X" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Ð’ÐµÑ€Ñ…Ð½Ñ Ð»Ñ–Ð²Ð° координата за Y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "ÐÐ¸Ð¶Ð½Ñ Ð¿Ñ€Ð°Ð²Ð° координата за X" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "ÐÐ¸Ð¶Ð½Ñ Ð¿Ñ€Ð°Ð²Ð° координата за Y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Роздільна здатніÑть ÑкануваннÑ" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "Роздільна здатніÑть за X" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Роздільна здатніÑть за Y" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Ширина Ñторінки" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "ВиÑота Ñторінки" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "ВикориÑтовувати неÑтандартну таблицю гами" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "ІнтенÑивніÑть зображеннÑ" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "ІнтенÑивніÑть червоного" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "ІнтенÑивніÑть зеленого" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "ІнтенÑивніÑть Ñинього" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "ЯÑкравіÑть" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "КонтраÑтніÑть" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Розмір зерна" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Ðапівтони" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Рівень чорного" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Рівень білого" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Рівень білого Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Рівень білого Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Рівень білого Ð´Ð»Ñ Ñинього" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "ЗатіненіÑть" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "ЗатіненіÑть Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "ЗатіненіÑть Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "ЗатіненіÑть Ð´Ð»Ñ Ñинього" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "ПідÑвічуваннÑ" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "ПідÑÐ²Ñ–Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "ПідÑÐ²Ñ–Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "ПідÑÐ²Ñ–Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñинього" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Відтінок" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "ÐаÑиченіÑть" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Ðазва файла" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Розмір шаблону напівтонів" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Шаблон напівтонів" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Пов’Ñзати роздільні здатноÑті за X Ñ– Y" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Ðегатив" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "ЯкіÑне калібруваннÑ" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Подвоїти оптичну роздільну здатніÑть" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Пов’Ñзаний RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Поріг" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Ðналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Ðналогова гама червоного" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Ðналогова гама зеленого" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Ðналогова гама Ñинього" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Пов’Ñзана аналогова гама" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Розігрів лампи" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Калібрувати Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Калібрувати Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Калібрувати Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Калібрувати Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ Ñинього" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Ð§Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ ÑкануваннÑ" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Ð§Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Ð§Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Ð§Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñинього" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Ð’Ñтановити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Калібрувати інтенÑивніÑть лампи" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "ІнтенÑивніÑть лампи ÑкануваннÑ" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Ð’Ñтановити інтенÑивніÑть лампи" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Вимикати лампу при виході" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Параметр лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ, Ñкий визначає кількіÑть параметрів, Ñкі " "підтримують певні приÑтрої." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Параметри джерела даних, режиму Ñ– роздільної здатноÑті" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Параметри облаÑті ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ– розмірів ноÑÑ–Ñ Ð´Ð°Ð½Ð¸Ñ…" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Параметри видозміни зображеннÑ" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Параметри обладнаннÑ" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Датчики Ñ– кнопки Ñканера" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Запитати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Ðаказати програмі виконувати вÑÑ– ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ–Ñ… переглÑдів у " "чорно-білому режимі. У режимі з трьома проходами кількіÑть проходів буде " "зменшено до одного, а на Ñканерах з одним проходом зменшує Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ " "на пам’Ñть Ñ– Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "КількіÑть бітів на колір, типовими значеннÑми Ñ” 1 Ð´Ð»Ñ ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¾Ð³Ð¾ Ñ– 8 Ð´Ð»Ñ " "напівтонового ÑкануваннÑ." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "" "Визначає режим ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ (наприклад, штриховий, чорно-білий або " "кольоровий)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Визначає швидкіÑть, з Ñкою виконуєтьÑÑ ÑкануваннÑ." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Визначає джерело ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ (зокрема приÑтрій подачі документів)" #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Визначає, чи буде виконуватиÑÑ Ð¿Ñ€Ð¸Ð¼ÑƒÑове поверненнÑ." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Координата X правого верхнього лівого кута облаÑті ÑкануваннÑ." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Координата Y правого верхнього лівого кута облаÑті ÑкануваннÑ." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Координата X правого нижнього кута облаÑті ÑкануваннÑ." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Координата Y правого нижнього кута облаÑті ÑкануваннÑ." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Визначає роздільну здатніÑть Ñканованого зображеннÑ." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "" "Визначає горизонтальну роздільну здатніÑть заÑканованого зображеннÑ." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Визначає вертикальну роздільну здатніÑть заÑканованого зображеннÑ." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Визначає ширину ноÑÑ–Ñ. Це Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ‚Ñ€Ñ–Ð±Ð½Ðµ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ " "Ñ†ÐµÐ½Ñ‚Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸Ñткових друкованих джерел." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Визначає виÑоту ноÑÑ–Ñ." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "Визначає буде викориÑтано вбудовану чи нетипову таблицю гами." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸. Ð’ кольоровому режимі цей параметр одночаÑно " "змінює параметри червоного, зеленого та Ñинього каналів (тобто Ñ” " "таблицею інтенÑивноÑті гами)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ñ— Ñмуги." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ñ— Ñмуги." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ñиньої Ñмуги." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Керує ÑÑкравіÑтю отриманого зображеннÑ." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Керує контраÑтніÑтю отриманого зображеннÑ." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Â«Ð·ÐµÑ€Ð½Ð¸ÑтоÑті» Ñканованого зображеннÑ. Менші Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ " "призводитимуть до ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‡Ñ–Ñ‚ÐºÑ–ÑˆÐ¸Ñ… зображень." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "" "Визначає, чи має бути отримане Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð¿Ñ–Ð²Ñ‚Ð¾Ð½Ð¾Ð²Ð¸Ð¼ (з дизерингом)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Визначає рівень ÑвітноÑті, Ñкий Ñлід вважати «чорним»." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Визначає рівень ÑвітноÑті, Ñкий Ñлід вважати «білим»." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "Визначає рівень ÑвітноÑті червоного, Ñкий Ñлід вважати «білим»." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "Визначає рівень ÑвітноÑті зеленого, Ñкий Ñлід вважати «білим»." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "Визначає рівень ÑвітноÑті Ñинього, Ñкий Ñлід вважати «білим»." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "Визначає рівень ÑвітноÑті червоного, Ñкий Ñлід вважати «чорним»." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "Визначає рівень ÑвітноÑті зеленого, Ñкий Ñлід вважати «чорним»." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "Визначає рівень ÑвітноÑті Ñинього, Ñкий Ñлід вважати «чорним»." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Визначає рівень ÑвітноÑті червоного, Ñкий Ñлід вважати «цілком червоним»." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Визначає рівень ÑвітноÑті зеленого, Ñкий Ñлід вважати «цілком зеленим»." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Визначає рівень ÑвітноÑті Ñинього, Ñкий Ñлід вважати «цілком Ñинім»." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Керує «відтінком» (рівнем Ñинього) отриманого зображеннÑ." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Рівень наÑиченоÑті керує значеннÑм «вуалюваннÑ», Ñке додаватиметьÑÑ Ð¿Ñ–Ð´ " "Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð· фотоапарата. Більші Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ñ‚Ð¸Ð¼ÑƒÑ‚ÑŒ " "більше вуалюваннÑ." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Ðазва файла зображеннÑ, Ñке буде завантажено." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Визначає розмір напівтонового шаблону (дизерингу), що викориÑтовуєтьÑÑ " "під Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð¿Ñ–Ð²Ñ‚Ð¾Ð½Ð¾Ð²Ð¸Ñ… зображень." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Визначає напівтонового шаблон (дизеринг) Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ð¿Ñ–Ð²Ñ‚Ð¾Ð½Ð¾Ð²Ð¸Ñ… " "зображень." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "" "ВикориÑтовувати однакові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð´Ñ–Ð»ÑŒÐ½Ð¸Ñ… здатноÑтей за X та Y" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "ОбмінÑти міÑцÑми чорний Ñ– білий" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Виконати ÑкіÑне ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð±Ñ–Ð»Ð¾Ð³Ð¾" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "ВикориÑтовувати лінзу, Ñка подвоює оптичну роздільніÑть" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "У режимі RGB викориÑтовувати однакові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ кольору" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Оберіть мінімальну ÑÑкравіÑть Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ‚Ð¾Ñ‡ÐºÐ¸ білого" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Ðналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Ðналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Ðналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Ðналогове Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ñинього" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Розігрівати лампу перед ÑкануваннÑм" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Визначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Визначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Визначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Визначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñинього" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Визначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑкануваннÑ" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Визначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Визначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Визначити Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Увімкнути вибір чаÑу витримки" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Визначити інтенÑивніÑть Ð´Ð»Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Визначити інтенÑивніÑть лампи Ð´Ð»Ñ ÑкануваннÑ" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Увімкнути можливіÑть вибору інтенÑивноÑті лампи" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Вимкнути лампу під Ñ‡Ð°Ñ Ð²Ð¸Ñ…Ð¾Ð´Ñƒ з програми" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Кнопка «Scan»" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "Кнопка «Email»" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Кнопка «Fax»" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Кнопка «Copy»" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "Кнопка «PDF»" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Кнопка «Cancel»" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Сторінку завантажено" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Кришку відчинено" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Кольоровий" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Кольоровий штриховий" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Кольоровий, напівтони" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Сірий" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Півтони" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Штрихове" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "УÑпіх" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Ð”Ñ–Ñ Ð½Ðµ підтримуєтьÑÑ" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "Дію було ÑкаÑовано" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "ПриÑтрій зайнÑто" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Ðекоректний аргумент" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "ДоÑÑгнуто ÐºÑ–Ð½Ñ†Ñ Ñ„Ð°Ð¹Ð»Ð°" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Ð—Ð°Ñ—Ð´Ð°Ð½Ð½Ñ Ð½Ð¾ÑÑ–Ñ Ñƒ приÑтрої подачі" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "У приÑтрої подачі немає ноÑіїв" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "Відчинено кришку Ñканера" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Помилка під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð´Ñ–Ð¹ з вводу-виводу" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Ðе виÑтачає пам'Ñті" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "ДоÑтуп до реÑурÑу заборонено" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "Лампа не готова, будь лаÑка, повторіть Ñпробу" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "Механізм Ñканера заблоковано" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Типові" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Ð’Ñтановити типові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ€ÐµÐ³ÑƒÐ»Ñторів покращеннÑ." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "КалібруваннÑ" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Калібрувати перед наÑтупним ÑкануваннÑм" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Якщо позначити цей пункт, приÑтрій буде калібровано перед наÑтупним " "ÑкануваннÑм. У іншому випадку ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½ÑƒÐ²Ð°Ñ‚Ð¸Ð¼ÐµÑ‚ÑŒÑÑ Ð»Ð¸ÑˆÐµ перед " "першим ÑкануваннÑм." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Виконати лише ÐºÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€Ð°Ð´Ð°Ñ†Ñ–Ñ—" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Якщо позначено цей пункт, під Ñ‡Ð°Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ виконано лише " "Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð´Ð°Ñ†Ñ–Ñ—. ВикориÑтовуютьÑÑ Ñ‚Ð¸Ð¿Ð¾Ð²Ñ– (вбудовані або запозичені " "з файла налаштувань) Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾ÐµÑ„Ñ–Ñ†Ñ–Ñ”Ð½Ñ‚Ð° підÑиленнÑ, Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ð° " "чаÑу екÑпозиції." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Стан кнопки" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Ðомер кадру Ð´Ð»Ñ ÑкануваннÑ" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Визначає кількіÑть кадрів Ð´Ð»Ñ ÑкануваннÑ" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Двобічне ÑкануваннÑ" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "За викориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð¾Ð³Ð¾ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸ отримаєте одразу Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ " "лицьового та зворотного боків документа" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Калібрувати Ñканер" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Виконувати примуÑове ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´ ÑкануваннÑм" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Сканувати у відтінках Ñірого" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Виконувати чорно-біле ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¼Ñ–Ñть кольорового" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Ðналогове підÑиленнÑ" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Збільшити або зменшити аналогове підÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ñ– ПЗЗ" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Визначити криву Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Без обробки" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "ЧиÑтий колір" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Без Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€Ð¾Ñті" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ до типу плівки" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ до ÑÐ¿Ñ–Ð²Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€Ð¾Ñті" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Ðегативи" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Слайди" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Ðвтоматично" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Звичайна швидкіÑть" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 звичайної швидкоÑті" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 звичайної швидкоÑті" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "округлений параметр" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "невідома" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "Ð—Ð°Ñ—Ð´Ð°Ð½Ð½Ñ Ñƒ протÑжному механізмі" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "Відкрито кришку протÑжного механізму" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "Лампа не працює" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "помилка Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ð¾Ð»Ñ–Ð²ÐºÐ¸ ÑкануваннÑ" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "Помилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ процеÑора" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "Помилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ пам’Ñті" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "Помилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ ROM" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "Помилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ обладнаннÑ" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "Ðе працює лампа Ð¼Ð¾Ð´ÑƒÐ»Ñ Ñлайдів" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "Помилка Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ð¾Ð»Ñ–Ð²ÐºÐ¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð¿Ð»Ñ–Ð²Ð¾Ðº" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "Помилка, пов’Ñзана з довжиною ÑпиÑку параметрів" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "Ðекоректний код команди дії" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "Ðекоректне поле у CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "Ðепідтримуване Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "Ðекоректне поле у ÑпиÑку параметрів" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "Помилка під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð¿Ð¾ÑлідовноÑті команд" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "Вказано забагато вікон" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "ВідÑутній ноÑій" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ некоректний біт IDENTIFY" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "Додаткову функціональніÑть не з’єднано" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð²Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ / Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ñтрою" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "Параметр змінено іншим інÑтрументом ініціалізації" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "відÑутні додаткові дані" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "Помилка повторного вибору" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "Помилка парноÑті SCSI" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "" "Отримано Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ помилку виÑÐ²Ð»ÐµÐ½Ð½Ñ Ñ–Ð½Ñтрументу ініціалізації" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "Ðекоректне повідомленнÑ" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "ÐŸÐµÑ€ÐµÐ²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу очікуваннÑ" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "Помилка під Ñ‡Ð°Ñ Ð³Ñ€Ð°Ð´Ð°Ñ†Ñ–Ñ— у модулі Ñлайдів" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "Лампу не Ñтабілізовано" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "плівковий Ñканер" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "планшетний Ñканер" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Тип плівки" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Визначає тип плівки, тобто негатив чи Ñлайд" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Тип плівки негатива" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Оберіть теÑтове зображеннÑ" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Ðпаратна роздільна здатніÑть" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "ВикориÑтовувати лише апаратні значеннÑ" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "ФокуÑуваннÑ" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Ðвтоматичне фокуÑуваннÑ" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Увімкнути/Вимкнути автоматичне фокуÑуваннÑ" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Одноразове автофокуÑуваннÑ" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Виконувати автоматичне фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ раз між виштовхуваннÑми" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Ð’Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ— фокуÑа вручну" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" "Ð’Ñтановити позицію фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— ÑиÑтеми вручну (типове значеннÑ: " "128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "ÐŸÐ¾Ð»Ñ Ð¾Ð±Ð»Ð°Ñті ÑкануваннÑ" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Додаткова ÐºÐ¾Ñ€ÐµÐºÑ†Ñ–Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Віддзеркалити зображеннÑ" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Віддзеркалити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð¾." #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "ÐвтоекÑпозиціÑ" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Увімкнути/Вимкнути можливіÑть автоекÑпонуваннÑ" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "КалібруваннÑ" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Виконати ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ³Ð°Ð¹Ð½Ð¾" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "СамодіагноÑтика" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Виконати ÑамодіагноÑтику Ñканера" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Скинути параметри Ñканера" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Скинути параметри Ñканера" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Обробка ноÑіїв" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Виштовхувати плівку піÑÐ»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ ÑкануваннÑ" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "" "Ðвтоматично виштовхувати плівку з приÑтрою піÑÐ»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ ÑкануваннÑ" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Виштовхувати плівку перед завершеннÑм роботи" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Ðвтоматично виштовхувати плівку з приÑтрою перед завершеннÑм роботи " "програми" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Виштовхнути плівку" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Виштовхнути плівку *негайно*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Додаткові інÑтрументи подачі" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Лише планшетний" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "" "Вимкнути автоматичну подачу, викориÑтовувати лише планшетний механізм" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Модуль Ð´Ð»Ñ Ñлайдів" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "Увімкнути/Вимкнути модуль Ð´Ð»Ñ Ñлайдів (FAU, film adapter unit)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Ðегатив" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Позитивною чи негативною Ñ” плівка" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‰Ñ–Ð»ÑŒÐ½Ñ–Ñтю" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Ð’Ñтановити режим ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‰Ñ–Ð»ÑŒÐ½Ñ–Ñтю" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Ð¡Ð¿Ñ–Ð²Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€Ð¾Ñті" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Оберіть тип плівки" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Визначає тип плівки" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Планшет" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "Перед протÑжного механізму" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "Зворот протÑжного механізму" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "Двобічна ÐПД" #: backend/canon_dr.c:412 #, no-c-format msgid "Card Front" msgstr "Картка (профіль)" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "Картка (зворот)" #: backend/canon_dr.c:414 #, no-c-format msgid "Card Duplex" msgstr "Картка (обидва боки)" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Червоний" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Зелений" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Синій" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "Покращити червоний" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "Покращити зелений" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "Покращити Ñиній" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Ðемає" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "JPEG" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "Порогове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ–Ñ… Ñторінок Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð½Ð¾Ð³Ð¾ відкиданнÑ" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" "Вимагати від драйвера Ð²Ñ–Ð´ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ñторінок з надто низькою питомою " "кількіÑтю темних пікÑелів" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Однобічна" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Двобічна" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Модуль Ð´Ð»Ñ Ñлайдів" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Ðвтоматична подача документів" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Плівка-позитив" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Плівка-негатив" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Ð¤Ð¾ÐºÑƒÑ Ð½Ð° Ñклі" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Ð¤Ð¾ÐºÑƒÑ 2,5 мм над Ñклом" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Півтони A (Різкі тони)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Півтони B (М’Ñкі тони)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Півтони C (Net Screen)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Дизеринг A (ÑÐµÐºÑ†Ñ–Ñ 4x4)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Дизеринг B (Ñпіраль 4x4)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Дизеринг C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Дизеринг D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Ð¢ÐµÑ…Ð½Ð¾Ð»Ð¾Ð³Ñ–Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ñ‚ÐµÐºÑту" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Завантажити шаблон A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Завантажити шаблон B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Без виправленнÑ" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Визначене кориÑтувачем" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Матричні принтери" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Термічні принтери" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Струминні принтери" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "Монітори з ЕПТ" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Типовий" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Друк з виÑокою щільніÑтю" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Друк з низькою щільніÑтю" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Друк з виÑокою контраÑтніÑтю" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Визначене кориÑтувачем (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Визначена кориÑтувачем (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "КД" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 книжкова" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 альбомна" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "МакÑ" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Режим ÑкануваннÑ" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Визначає півтон." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "МаÑка" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Визначає маÑку." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Визначає ÑÑкравіÑть." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "РізкіÑть" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Кольорова компенÑаціÑ" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "" "Визначає таблицю Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð² Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ приÑтрою Ð²Ð¸Ð²ÐµÐ´ÐµÐ½Ð½Ñ " "даних." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Коефіцієнти Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Матричний множник RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "ЗÑув зеленого до червоного" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "ЗÑув зеленого до Ñинього" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "ЗÑув червоного до зеленого" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "ЗÑув червоного до Ñинього" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "ЗÑув Ñинього до зеленого" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "ЗÑув Ñинього до червоного" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Керує рівнем зеленого" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Додаток до червоного на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Додаток до Ñинього на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Додаток до зеленого на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Керує рівнем червоного" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Додаток до Ñинього на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Додаток до зеленого на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ñинього" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Додаток до червоного на оÑнові Ñ€Ñ–Ð²Ð½Ñ Ñинього" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Визначає рівень Ñинього" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Віддзеркалити зображеннÑ." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Швидкий переглÑд" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Ðвтоматичний поділ на облаÑті" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Короткий ÑпиÑок роздільних здатноÑтей" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Показати короткий ÑпиÑок роздільних здатноÑтей" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "МаÑштаб" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Визначає маÑштаб, Ñкий буде викориÑтано Ñканером" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Швидке форматуваннÑ" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Додаткове уÑтаткуваннÑ" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Виштовхнути" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Виштовхнути аркуш з протÑжного приÑтрою" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "ÐвтовиштовхуваннÑ" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Виштовхнути документ піÑÐ»Ñ ÑкануваннÑ" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Режим протÑжного приÑтрою" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Визначає режим протÑжного приÑтрою (однобічний/двобічний)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "СекціÑ" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Визначає Ñекцію, Ñку буде Ñкановано" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ñ€Ñ–Ð²Ð½Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð°ÑтноÑті (гами) зі ÑпиÑку " "попереднього визначених приÑтроїв або визначеної кориÑтувачем таблиці, " "Ñку можна завантажити у Ñканер" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "ÐŸÐ¾Ð·Ð¸Ñ†Ñ–Ñ Ñ„Ð¾ÐºÑƒÑуваннÑ" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Визначає позицію фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° рівень від поверхні Ñкла до виÑоти 2,5 " "мм над Ñклом" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Очікувати натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "ПіÑÐ»Ñ Ð½Ð°Ð´ÑÐ¸Ð»Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð¸ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ розпочинати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ " "натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ на Ñканері." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "Інфрачервоне" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "TPU8x10" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Слайд-позитив" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Слайд-негатив" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "Вбудований профіль CCT" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "Визначений кориÑтувачем профіль CCT" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Увімкнути" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Вимкнути" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "DTC" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "SDTC" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Дизеринг" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "ДифузіÑ" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "Білий" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "Чорний" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Продовжити" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Зупинити" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10мм" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15мм" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20мм" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "По горизонталі" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "Жирний по горизонталі" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "Вузький по горизонталі" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "По вертикалі" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "Жирний по вертикалі" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "Згори вниз" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "Знизу догори" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "Перед" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "Зворот" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "Показник функції гами" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "Змінює інтенÑивніÑть напівтонів" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "RIF" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "ІнверÑивний формат зображеннÑ" #: backend/fujitsu.c:3165 #, no-c-format msgid "Halftone type" msgstr "Тип півтонів" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð¸Ð¿Ð¾Ð¼ фільтра півтонів" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð·Ñ–Ñ€Ñ†ÐµÐ¼ фільтра півтонів" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "Контур" #: backend/fujitsu.c:3210 #, no-c-format msgid "Perform outline extraction" msgstr "Виконати Ð²Ð¸Ð´Ð¾Ð±ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÑƒÑ€Ñƒ" #: backend/fujitsu.c:3221 #, no-c-format msgid "Emphasis" msgstr "ВиокремленнÑ" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" "Ðегатив Ð´Ð»Ñ Ð·Ð³Ð»Ð°Ð´Ð¶ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ позитив Ð´Ð»Ñ Ð·Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ Ñ€Ñ–Ð·ÐºÐ¾Ñті зображеннÑ" #: backend/fujitsu.c:3240 #, no-c-format msgid "Separation" msgstr "РозділеннÑ" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "Увімкнути автоматичне Ð²Ñ–Ð´Ð¾ÐºÑ€ÐµÐ¼Ð»ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ Ñ– текÑту" #: backend/fujitsu.c:3252 #, no-c-format msgid "Mirroring" msgstr "ВіддзеркаленнÑ" #: backend/fujitsu.c:3253 #, no-c-format msgid "Reflect output image horizontally" msgstr "Віддзеркалити отримане Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ горизонталі" #: backend/fujitsu.c:3270 #, no-c-format msgid "White level follower" msgstr "Відповідник Ñ€Ñ–Ð²Ð½Ñ Ð±Ñ–Ð»Ð¾Ð³Ð¾" #: backend/fujitsu.c:3271 #, no-c-format msgid "Control white level follower" msgstr "Керує відповідником Ñ€Ñ–Ð²Ð½Ñ Ð±Ñ–Ð»Ð¾Ð³Ð¾" #: backend/fujitsu.c:3289 #, no-c-format msgid "BP filter" msgstr "Фільтр СП" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "Поліпшує ÑкіÑть текÑту, напиÑаного кульковою ручкою" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "ЗгладжуваннÑ" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "Увімкнути Ð·Ð³Ð»Ð°Ð´Ð¶ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»Ñ–Ð¿ÑˆÐµÐ½Ð½Ñ ÐžÐ Ð¢" #: backend/fujitsu.c:3323 #, no-c-format msgid "Gamma curve" msgstr "Крива гами" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" "Крива гами, від Ñвітлого до темного, але верхні дві можуть не працювати" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "Порогова крива" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" "Порогова крива, від Ñвітлого до темного, але верхні дві не можуть бути " "лінійними" #: backend/fujitsu.c:3369 #, no-c-format msgid "Threshold white" msgstr "Білий поріг" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "Ð’Ñтановити Ð´Ð»Ñ Ð¿Ð¾Ñ€Ð¾Ð³Ð¾Ð²Ð¸Ñ… пікÑелів білий колір, а не чорний" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, no-c-format msgid "Noise removal" msgstr "Ð’Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ ÑˆÑƒÐ¼Ñƒ" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ 5x5" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "Вилучати пікÑельний шум розміром до 5 пікÑелів" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ 4x4" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "Вилучати пікÑельний шум розміром до 4 пікÑелів" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ 3x3" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "Вилучати пікÑельний шум розміром до 3 пікÑелів" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ 2x2" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "Вилучати пікÑельний шум розміром до 2 пікÑелів" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "ДиÑперÑÑ–Ñ" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "Ð’Ñтановити величину диÑперÑÑ–Ñ— SDTC (чутливіÑть), 0 відповідає 127" #: backend/fujitsu.c:3508 #, no-c-format msgid "Auto width detection" msgstr "ÐвтовиÑÐ²Ð»ÐµÐ½Ð½Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ð¸" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "Сканер визначає краї паперу. Може уповільнити ÑкануваннÑ." #: backend/fujitsu.c:3526 #, no-c-format msgid "Auto length detection" msgstr "ÐвтовиÑÐ²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¸" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" "Сканер виÑвлÑÑ” нижній край паперу. Може призвеÑти до помилкової роботи " "деÑких програмних оболонок." #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "СтиÑненнÑ" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" "Увімкнути ÑтиÑÐºÐ°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ…. Може призвеÑти до аварійного Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ " "роботи програмних оболонок." #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "Ðргумент ÑтиÑканнÑ" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" "Рівень ÑтиÑÐºÐ°Ð½Ð½Ñ JPEG. 1 — малий файл, 7 — великий файл. 0 (типовий) — " "те Ñаме, що Ñ– 4." #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "Ð”Ñ–Ñ ÐŸÐŸ" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "ДіÑ, Ñку буде виконано у відповідь на помилку подвійного подаваннÑ" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "ПП Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ¾ÑˆÑƒÐ²Ð°Ð½Ð½Ñ" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "Увімкнути помилку подвійного Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· перекошуваннÑ" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "ПП Ð´Ð»Ñ Ñ‚Ð¾Ð²Ñ‰Ð¸Ð½Ð¸" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "Увімкнути помилку подвійного Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· товщину паперу" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "ПП Ð´Ð»Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¸" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "Увімкнути помилку подвійного Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· довжину паперу" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "Ð Ñ–Ð·Ð½Ð¸Ñ†Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¸ Ð´Ð»Ñ ÐŸÐŸ" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" "Ð Ñ–Ð·Ð½Ð¸Ñ†Ñ Ñƒ довжинах аркушів паперу, Ñка призводитиме до помилки " "подвійного подаваннÑ" #: backend/fujitsu.c:3708 #, no-c-format msgid "DF recovery mode" msgstr "Режим Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐŸÐŸ" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "Вимагати від Ñканера зворотного подаваннÑ, Ñкщо папір зам’Ñто" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "ЗахиÑÑ‚ паперу" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "Вимагати від Ñканера передбачати зам’ÑÑ‚Ñ‚Ñ Ñƒ протÑжному приÑтрої" #: backend/fujitsu.c:3748 #, no-c-format msgid "Advanced paper protection" msgstr "Додатковий захиÑÑ‚ паперу" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" "Вимагати від Ñканера передбачати зам’ÑÑ‚Ñ‚Ñ Ñƒ протÑжному приÑтрої за " "допомогою поліпшених датчиків" #: backend/fujitsu.c:3768 #, no-c-format msgid "Staple detection" msgstr "ВиÑÐ²Ð»ÐµÐ½Ð½Ñ Ñкоб" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" "Вимагати від Ñканера виÑвлÑти зам’ÑÑ‚Ñ‚Ñ Ñƒ протÑжному приÑтрої через Ñкоби" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "Колір тла" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" "Ð’Ñтановити колір Ð´Ð»Ñ Ñ‚Ð»Ð° Ñканованих зображень. Може конфліктувати із " "параметром полів." #: backend/fujitsu.c:3809 #, no-c-format msgid "Dropout color" msgstr "Колір Ð´Ð»Ñ Ð²Ð¸ÐºÐ¸Ð´Ð°Ð½Ð½Ñ" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" "Однопрохідні Ñканери викориÑтовують лише один колір під Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ " "відтінках Ñірого або чорно-білого ÑкануваннÑ, кориÑно Ð´Ð»Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ð¾Ð²Ð¾Ð³Ð¾ " "паперу або чорнильних запиÑів" #: backend/fujitsu.c:3833 #, no-c-format msgid "Buffer mode" msgstr "Режим буферизації" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" "Ðаказати Ñканеру швидко читати Ñторінки з протÑжного приÑтрою до " "внутрішньої пам’Ñті" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "Попереднє захопленнÑ" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "Ðаказати Ñканеру захопити наÑтупну Ñторінку із протÑжного приÑтрою" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "ПолÑ" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" "Зібрати дані щодо декількох міліметрів у верхній чаÑтині Ñканованого " "зображеннÑ, перш ніж аркуш потрапить до протÑжного приÑтрою, Ñ– збільшити " "макÑимальну облаÑть ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° межі вÑтановленого розміру паперу, а " "також дозволити Ð·Ð±Ð¸Ñ€Ð°Ð½Ð½Ñ Ñ€ÐµÑˆÑ‚Ð¸ даних з бічних полів. Може конфліктувати " "з параметром кольору тла." #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "Таймер приÑиплÑннÑ" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" "Ð§Ð°Ñ Ñƒ хвилинах, по завершенню Ñкого внутрішнє Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ переведено у " "режим Ñну" #: backend/fujitsu.c:3911 #, no-c-format msgid "Off timer" msgstr "Таймер вимиканнÑ" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" "Ð§Ð°Ñ Ñƒ хвилинах, по завершенню Ñкого внутрішнє Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ вимкнено. " "Буде округлено до найближчого кратного до 15 хвилин. Ðульове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ " "означає, що Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ðµ вимикатиметьÑÑ." #: backend/fujitsu.c:3930 #, no-c-format msgid "Duplex offset" msgstr "Ð—Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð´Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð¾Ð³Ð¾" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "ÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ переднім Ñ– зворотним боком" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Ð—Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: backend/fujitsu.c:3949 #, no-c-format msgid "Adjust green/red offset" msgstr "ÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ зеленим Ñ– червоним каналами" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Ð—Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñинього" #: backend/fujitsu.c:3967 #, no-c-format msgid "Adjust blue/red offset" msgstr "ÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ð¶ Ñинім Ñ– червоним каналами" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð°Ð¼â€™Ñті" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" "Обмежити викориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ð°Ð¼â€™Ñті драйвером на вбудованих ÑиÑтемах. " "Призводить до Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ð½Ð½Ñ Ð¾ÐºÑ€ÐµÐ¼Ð¸Ñ… боків аркуша у відповідь на кожен " "виклик sane_read. Відповідне Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ð½Ð° визначити за параметром " "«side». Цим параметром Ñлід кориÑтуватиÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð½ÐµÑ‚Ð¸Ð¿Ð¾Ð²Ð¾Ð³Ð¾ " "зовнішнього інтерфейÑу програмного забезпеченнÑ." #: backend/fujitsu.c:3996 #, no-c-format msgid "Duplex side" msgstr "Бік Ð´Ð»Ñ Ð´Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð¾Ð³Ð¾" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" "Визначає, Ñкий бік (0=передній, 1=зворотний) двобічного Ñканованого " "Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ повернуто під Ñ‡Ð°Ñ Ð½Ð°Ñтупного виклику sane_read." #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "Ðпаратне Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ñ…Ð¸Ð»Ñƒ Ñ– обрізаннÑ" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" "Вимагати від Ñканера Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð° Ð¾Ð±Ñ€Ñ–Ð·Ð°Ð½Ð½Ñ Ñторінок у цифровому режимі." #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "Програмне уÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" "Вимагати від драйвера уÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñторінок у автоматичному режимі." #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "Діаметр плÑм Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð½Ð¾Ð³Ð¾ уÑуваннÑ" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" "Мінімальний діаметр окремих плÑм, Ñкі Ñлід уÑунути зі Ñканованого " "зображеннÑ." #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "Програмне обрізаннÑ" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" "Вимагати від драйвера Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ñ– зі Ñторінок у автоматичному " "режимі." #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "Перервати при ÑкаÑуванні" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" "Ðаказати драйверу перервати Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°Ð¿ÐµÑ€Ñƒ, заміÑть його " "виштовхуваннÑ, Ñкщо ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÑкаÑовано." #: backend/fujitsu.c:4095 #, no-c-format msgid "Endorser Options" msgstr "Параметри наддруку" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð´ÑƒÐ»ÐµÐ¼ наддруку" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "Ðаддрук" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "Увімкнути модуль наддруку" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "Біти наддруку" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "Визначає макÑимальне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ° наддруку." #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð½Ð°Ð´Ð´Ñ€ÑƒÐºÑƒ" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "Початкове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ° наддруку." #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "Крок наддруку" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" "Змінювати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ° наддруку на вказане чиÑло Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ñ— " "наÑтупної Ñторінки." #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "Y наддруку" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "ЗÑув мітки наддруку від верхнього краю паперу." #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "Шрифт наддруку" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "Шрифт наддруку." #: backend/fujitsu.c:4253 #, no-c-format msgid "Endorser direction" msgstr "ÐапрÑмок наддруку" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "ÐапрÑмок друку." #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "Бік наддруку" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" "Бік, з Ñкого буде друкуватиÑÑ Ð¼Ñ–Ñ‚ÐºÐ°. Потребує апаратної підтримки Ð´Ð»Ñ " "зміни." #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "РÑдок наддруку" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" "Буквенно-цифровий формат наддруку. %05ud або %08ud наприкінці буде " "замінено на Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð»Ñ–Ñ‡Ð¸Ð»ÑŒÐ½Ð¸ÐºÐ°." #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "Верхній край" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "Папір чаÑтково втÑгнуто до протÑжного приÑтрою" #: backend/fujitsu.c:4344 #, no-c-format msgid "A3 paper" msgstr "Папір A3" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "ВиÑвлено папір A3" #: backend/fujitsu.c:4356 #, no-c-format msgid "B4 paper" msgstr "Папір B4" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "ВиÑвлено папір B4" #: backend/fujitsu.c:4368 #, no-c-format msgid "A4 paper" msgstr "Папір A4" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "ВиÑвлено папір A4" #: backend/fujitsu.c:4380 #, no-c-format msgid "B5 paper" msgstr "Папір B5" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "ВиÑвлено папір B5" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "OMR або ПП" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "ВиÑвлено OMR або подвійне подаваннÑ" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "Ð—Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ ÐµÐ½ÐµÑ€Ð³Ñ–Ñ—" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "Сканер перебуває у режимі Ð·Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ ÐµÐ½ÐµÑ€Ð³Ñ–Ñ—" #: backend/fujitsu.c:4452 #, no-c-format msgid "Manual feed" msgstr "ÐŸÐ¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ" #: backend/fujitsu.c:4453 #, no-c-format msgid "Manual feed selected" msgstr "Вибрано режим Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "ФункціÑ" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "Функціональний Ñимвол на екрані" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "ЗакінчуютьÑÑ Ñ‡Ð¾Ñ€Ð½Ð¸Ð»Ð°" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "ЛишилоÑÑ Ð¼Ð°Ð»Ð¾ чорнила Ð´Ð»Ñ Ð½Ð°Ð´Ð´Ñ€ÑƒÐºÑƒ" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "Подвійне подаваннÑ" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "ВиÑвлено подвійне подаваннÑ" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "Код помилки" #: backend/fujitsu.c:4513 #, no-c-format msgid "Hardware error code" msgstr "Код апаратної помилки" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "Кут перекошуваннÑ" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "Потребує чорного тла Ð´Ð»Ñ ÑкануваннÑ" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "ЛишилоÑÑ Ñ‡Ð¾Ñ€Ð½Ð¸Ð»Ð°" #: backend/fujitsu.c:4537 #, no-c-format msgid "Imprinter ink level" msgstr "Рівень чорнила Ð´Ð»Ñ Ð½Ð°Ð´Ð´Ñ€ÑƒÐºÑƒ" #: backend/fujitsu.c:4548 #, no-c-format msgid "Density" msgstr "ЩільніÑть" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "Ðабирач щільноÑті" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, no-c-format msgid "Duplex switch" msgstr "Перемикач двобічного" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" "Вимагати від програмного Ð¼Ð¾Ð´ÑƒÐ»Ñ Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ñ– зі Ñторінок у " "автоматичному режимі" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" "Вимагати від драйвера Ð²Ñ–Ð´ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ñторінок з надто низькою кількіÑтю " "темних пікÑелів" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "Програмне уÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" "Вимагати від драйвера виÑÐ²Ð»ÐµÐ½Ð½Ñ Ñ– Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð° 90 " "градуÑів" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Додаткові" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" "Крива динамічного порогового значеннÑ, від Ñвітлого до темного, типово " "50-65" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "Вимкнути динамічне штрихуваннÑ" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" "Вимкнути викориÑÑ‚Ð°Ð½Ð½Ñ Ð°Ð´Ð°Ð¿Ñ‚Ð¸Ð²Ð½Ð¾Ð³Ð¾ програмного алгоритму Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ " "ÑˆÑ‚Ñ€Ð¸Ñ…ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¼Ñ–Ñть апаратного алгоритму штрихуваннÑ." #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Вимкнути інтерполÑцію" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "За викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ñоких роздільних здатноÑтей, коли горизонтальна " "роздільна здатніÑть менша за вертикальну, вимикає горизонтальну " "інтерполÑцію." #: backend/genesys.c:5872 #, no-c-format msgid "Color filter" msgstr "Фільтр кольору" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "За викориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ñ€ÑƒÐºÑƒ у півтонах або штрихового друку за допомогою цього " "пункту можна обрати колір друку." #: backend/genesys.c:5901 #, no-c-format msgid "Calibration file" msgstr "Файл калібруваннÑ" #: backend/genesys.c:5902 #, no-c-format msgid "Specify the calibration file to use" msgstr "Вкажіть файл даних калібруваннÑ, Ñкі буде викориÑтано" #: backend/genesys.c:5919 #, no-c-format msgid "Calibration cache expiration time" msgstr "Строк дії кешу калібруваннÑ" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" "Ð§Ð°Ñ (у хвилинах), перш ніж завершитьÑÑ Ñтрок дії кешованих даних щодо " "калібруваннÑ. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ 0 означає, що кеш не викориÑтовуватиметьÑÑ. " "Від’ємні Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¾Ð·Ð½Ð°Ñ‡Ð°ÑŽÑ‚ÑŒ, що обмежень на Ñтрок дії кешу не " "накладатиметьÑÑ." #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Ð§Ð°Ñ Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "Лампу буде вимкнено, коли Ñпливе вказаний Ñ‡Ð°Ñ (у хвилинах). Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ " "рівне 0 означатиме, що лампа не вимикатиметьÑÑ." #: backend/genesys.c:5943 #, no-c-format msgid "Lamp off during scan" msgstr "Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ під Ñ‡Ð°Ñ ÑкануваннÑ" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "Лампу буде вимкнено під Ñ‡Ð°Ñ ÑкануваннÑ. " #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Кнопка «File»" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "Кнопка «OCR»" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Кнопка «Power»" #: backend/genesys.c:6053 backend/genesys.c:6054 #, no-c-format msgid "Extra button" msgstr "Додаткова кнопка" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "Потребує калібруваннÑ" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "Ð”Ð»Ñ Ð·Ð°ÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ‚Ð¾Ñ‡Ð½Ð¸Ñ… параметрів потрібне калібруваннÑ" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Кнопки" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Відкалібрувати" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Почати ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° допомогою Ñпеціального аркуша" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Спорожнити дані калібруваннÑ" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Спорожнити кеш калібруваннÑ" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Ðдаптер плівок" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Режим відтінків Ñірого" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Визначає, Ñкий колір ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ викориÑтано у режимі напівтонів " "Ñірого (типово — зелений)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Параметри зневаджуваннÑ" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Ðвтоматичний розігрів" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Розігрівати, до Ñталої ÑÑкравоÑті лампи, не наполÑгати на 60-ти " "Ñекундному розігріві." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Повне ÑкануваннÑ" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Сканувати вÑÑŽ облаÑть ÑкануваннÑ, зокрема Ñмугу калібруваннÑ. Будьте " "обережні. Ðе вказуйте повну виÑоту. Лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Грубе калібруваннÑ" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Визначає автоматичний режим підÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñ– Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ ÑкануваннÑ. Якщо цей " "пункт не буде позначено, ви зможете вказати параметри аналогової " "оболонки вручну. Типово цей пункт позначено. Лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Грубе ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ð³Ð¾ ÑкануваннÑ" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Виконувати грубе ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ð³Ð¾ ÑкануваннÑ. Працює на " "більшоÑті Ñканерів Ñ– надає змогу зекономити Ñ‡Ð°Ñ Ð½Ð° ÑкануваннÑ. Якщо " "ÑÑкравіÑть Ñканованих зображень значно змінюєтьÑÑ, зніміть позначку з " "цього пункту. Лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Ліній поверненнÑ" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "КількіÑть ліній, на Ñкі повзунок ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð°Ñ” відÑтупити у разі " "потреби у поверненні. Подібне Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ðµ знадобитиÑÑ, Ñкщо " "ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð±ÑƒÐ²Ð°Ñ”Ñ‚ÑŒÑÑ ÑˆÐ²Ð¸Ð´ÑˆÐµ за Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð¿â€™ÑŽÑ‚ÐµÑ€Ð¾Ð¼ даних. Менші " "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸ÑˆÐ²Ð¸Ð´ÑˆÐ°Ñ‚ÑŒ ÑкануваннÑ, але збільшать ймовірніÑть пропуÑку " "ліній." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÐ¾ÐµÑ„Ñ–Ñ†Ñ–Ñ”Ð½Ñ‚Ð° контраÑтноÑті" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÐ¾ÐµÑ„Ñ–Ñ†Ñ–Ñ”Ð½Ñ‚Ð° контраÑтноÑті Ð´Ð»Ñ Ð²ÑÑ–Ñ… каналів." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Група розташуваннÑ" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Група режимів ÑкануваннÑ" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Слайд" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Модель Ñканера" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" "Ðадає змогу перевірити поведінку приÑтрою з викориÑтаннÑм інших " "підтримуваних моделей" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Кольори Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ інвертовано" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Вимкнути Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ буде вимкнено" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Вимкнути Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ñ‚Ñ–Ð½ÐºÑ–Ð² білого" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð´Ð°Ñ†Ñ–Ñ— білого буде вимкнено" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "ПропуÑтити процедуру розігріву" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "ÐŸÑ€Ð¾Ñ†ÐµÑ Ñ€Ð¾Ð·Ñ–Ð³Ñ€Ñ–Ð²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ вимкнено" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Вказати Ñправжню глибину" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "Якщо буде увімкнено гаму, ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð¶Ð´Ð¸ виконуватиметьÑÑ Ð· глибиною " "кольорів у 16 бітів Ð´Ð»Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ ÑкоÑті зображеннÑ, а вже потім " "перетворюватиметьÑÑ Ð´Ð¾ обраної глибини кольорів. За допомогою цього " "пункту можна уникнути такої емулÑції." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ‡Ð¾Ñ€Ð½Ð¾-білого" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "Якщо буде позначено цей пункт, Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ заÑкановано у кольоровому " "режимі, а вже потім програмно перетворено на Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ тонах Ñірого. " "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð±Ð½Ð¾Ð³Ð¾ підходу іноді може покращити ÑкіÑть зображеннÑ." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Зберегти зневаджувальні зображеннÑ" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "Якщо буде позначено цей пункт, деÑкі з зображень з процеÑу ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ " "буде збережено Ð´Ð»Ñ Ð¿Ð¾Ð´Ð°Ð»ÑŒÑˆÐ¾Ð³Ð¾ аналізу." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Відновити дані мікроконтролера" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Відновити початкові дані мікроконтролера" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "ІнформаціÑ" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Ðазва мікроконтролера" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Показує назву мікроÑхеми, викориÑтаної у приÑтрої." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Ðевідома" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "Ідентифікатор мікроÑхеми" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Показує ідентифікатор мікроÑхеми" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Лічильник ÑкануваннÑ" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Показує кількіÑть Ñканувань, виконаних за допомогою Ñканера" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Оновити дані" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Оновлює дані щодо приÑтрою" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Цей пункт відповідає кнопці передньої панелі Ñканера" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "ЗображеннÑ" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Різне" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "ЗÑув за X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Ðпаратна Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð·Ð° X облаÑті ÑкануваннÑ." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "ЗÑув за Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Ðпаратна Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð·Ð° Y облаÑті ÑкануваннÑ." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Стан лампи" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Вмикає або вимикає лампу." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Калібрує Ð´Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€Ñ–Ð²Ð½Ñ Ñ‡Ð¾Ñ€Ð½Ð¾Ð³Ð¾ и білого." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ÐПД" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "Слайди TMA" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "Ðегативи TMA" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Кольоровий (48-бітовий)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Збільшений Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Збільшує Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ (з 15 хвилин до 1 години)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Очікувати натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Очікувати на натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸, перш ніж почати ÑкануваннÑ" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Додаткові параметри" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Грубе" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "ВиÑокої ÑкоÑті" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "СекціÑ" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Ðетипова" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Ðвто" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "ПропуÑкати" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "Чорно-біле NTSC" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "Чорно-біле XPA" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Повільно" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Звичайна" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Швидко" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Дуже швидко" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "Двоточкове" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "Чотириточкове" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "ВоÑьмиточкове" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Друк" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Плівка" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Умовно" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "ЕкÑперимент" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Збільшенні різкоÑті" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Визначає величину Ð·Ð±Ñ–Ð»ÑŒÑˆÐµÐ½Ð½Ñ Ñ€Ñ–Ð·ÐºÐ¾Ñті." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Ðвтоматичне порогове значеннÑ" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Увімкнути автоматичне Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð³Ð¾Ð²Ð¾Ð³Ð¾ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ " "штрихових зображень." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Визначити фільтр згладжуваннÑ." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Вивантажувати ноÑій піÑÐ»Ñ ÑкануваннÑ" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Вивантажує ноÑій піÑÐ»Ñ ÑкануваннÑ." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Змінити документ" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Змінити документ." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Вивантажити" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Вивантажити документ." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Почати процедуру калібруваннÑ." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "ÐоÑій" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Визначити тип ноÑÑ–Ñ." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Ð§Ð°Ñ ÐµÐºÑпозиції" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Триваліша витримка надаÑть змогу Ñканеру накопичити більше Ñвітла. " "Рекомендуємо вам ÑкориÑтатиÑÑ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñм 175% Ð´Ð»Ñ Ð´Ñ€ÑƒÐºÐ¾Ð²Ð°Ð½Ð¸Ñ… документів, " "150% Ð´Ð»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¸Ñ… Ñлайдів та «Ðегатив» Ð´Ð»Ñ Ð½ÐµÐ³Ð°Ñ‚Ð¸Ð²Ñ–Ð². Ð”Ð»Ñ Ñ‚ÐµÐ¼Ð½Ð¸Ñ… " "(недоекÑпонованих) зображень ви можете збільшити це значеннÑ." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "ÐœÐ°Ñ‚Ñ€Ð¸Ñ†Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Визначити матрицю кольорів Ñканера." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Ðетипова Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Чорно-біла Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Ðетипова Ð¼Ð°Ñ‚Ñ€Ð¸Ñ†Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð² Ð´Ð»Ñ Ñ‡Ð¾Ñ€Ð½Ð¾-білих зображень." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Віддзеркалити горизонтально" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Віддзеркалити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ горизонталі." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Віддзеркалити вертикально" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Віддзеркалити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ вертикалі." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Оновити параметри" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Оновити параметри." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8-бітовий вивід" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Ð”Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½ÑŒÐ¾Ñ— обробки викориÑтовувати глибини кольорів, більші за 8-" "бітові, але виводити дані лише у 8-бітовому форматі." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Очікувати натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ у передній чаÑтині" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "" "Ðе починати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ на передній панелі Ñканера." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Вимкнути лампу" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Вимкнути лампу Ñканера." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Розмір паперу" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Ðвтоматичне відокремленнÑ" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, no-c-format msgid "Landscape" msgstr "Ðльбомна" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "ІнверÑивне зображеннÑ" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "Режим довгого паперу" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "Режим ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¾ÑŽ" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "Режим Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, no-c-format msgid "Manual feed timeout" msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° подачу вручну" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "ВиÑÐ²Ð»ÐµÐ½Ð½Ñ Ð´Ð²Ð¾Ð±Ñ–Ñ‡Ð½Ð¾Ð³Ð¾ подаваннÑ" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Увімкнути двобічне ÑкануваннÑ" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Фізичний розмір паперу у приÑтрої автоматичної подачі" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "чб" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "півтони" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "Ñірий" #: backend/kvs1025_opt.c:42 #, no-c-format msgid "color" msgstr "кольорове" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "ÐПД" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "планшет" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "однобічний" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "безперервне" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "вимкнено" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "очік_документа" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "очік_клавіші" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "визн_кориÑтувачем" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "бізнеÑ_картка" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "Чек" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "A5" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "A6" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "B5" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "B6" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "Легал" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "баєр_64" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "баєр_16" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "напівтони_32" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "напівтони_64" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "розÑÑ–Ñне" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, no-c-format msgid "normal" msgstr "звичайне" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, no-c-format msgid "light" msgstr "Ñвітле" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "темне" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, no-c-format msgid "From scanner" msgstr "Зі Ñканера" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Від паперу" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, no-c-format msgid "default" msgstr "типове" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "гладке" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "немає" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, no-c-format msgid "low" msgstr "низьке" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, no-c-format msgid "medium" msgstr "Ñереднє" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "виÑоке" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "ЕПТ" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "лінійна" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, no-c-format msgid "red" msgstr "червоний" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, no-c-format msgid "green" msgstr "зелений" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "Ñиній" #: backend/kvs1025_opt.c:562 #, no-c-format msgid "Sets the scan source" msgstr "Ð’Ñтановлює джерело ÑкануваннÑ" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Режим подачі" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Визначити режим подачі" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "Увімкнути/Вимкнути режим довгого паперу" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "Увімкнути/Вимкнути режим ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¾ÑŽ" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, no-c-format msgid "Sets the manual feed mode" msgstr "Ð’Ñтановлює режим Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Ð’Ñтановлює Ñ‡Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "Увімкнути або вимкнути виÑÐ²Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð´Ð²Ñ–Ð¹Ð½Ð¾Ð³Ð¾ подаваннÑ" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "за аркушем" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "За аркушем" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "Сканер ÑтиÑкає Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ до розмірів аркуша" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "Ð’Ñтановлює Ñ€Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ñ€ÐºÑƒÑˆÐ°: true — альбомне, false — книжкове" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Ðвтоматичне визначеннÑ" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Ð’Ñтановлювати ÑÑкравіÑть, контраÑтніÑть, рівень білого, гаму, Ð·Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ " "шумноÑті Ñ– виразніÑть Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Ð—Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ ÑˆÑƒÐ¼Ð½Ð¾Ñті" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Зменшити шум від ізольованих точок" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "ВиразніÑть зображеннÑ" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Визначає виразніÑть зображеннÑ" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Гама" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, no-c-format msgid "Lamp color" msgstr "Колір лампи" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Ð’Ñтановлює колір лампи (Ð²Ñ–Ð´ÐºÐ¸Ð´Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²)" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "ІнверÑивне Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ чорно-білому або півтоновому режимі" #: backend/kvs1025_opt.c:840 #, no-c-format msgid "Mirror image (left/right flip)" msgstr "Віддзеркалити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ (Ð¿ÐµÑ€ÐµÐ²ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· лівий/правий край)" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "ÑтиÑÐºÐ°Ð½Ð½Ñ jpeg" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "СтиÑÐºÐ°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ JPEG з параметром Q, «0» — не ÑтиÑкати" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "Обернути Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð° год. Ñтрілкою" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" "Вимагати від драйвера Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñторінок на фікÑований вказаний кут" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" "Вимагати від драйвера уÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ñторінок у автоматичному режимі" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" "Мінімальний діаметр окремих плÑм, Ñкі Ñлід уÑунути зі Ñканованого " "зображеннÑ" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "Програмне автоматичне обрізаннÑ" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" "Вимагати від драйвера Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ð½Ð¸Ñ†Ñ– зі Ñторінок у автоматичному " "режимі" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" "У режимі ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð²Ð¶Ð¸Ð½Ð¾ÑŽ Ñканер читає дані до найкоротшої з таких " "довжин: дійÑної довжини аркуша паперу або логічної довжини документа." #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Ð’Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "очік_документа_з_бункера" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "A3" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "Подвійний лиÑÑ‚ 11x17 дюймів" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "B4" #: backend/kvs40xx_opt.c:231 #, no-c-format msgid "High sensivity" msgstr "ВиÑока чутливіÑть" #: backend/kvs40xx_opt.c:232 #, no-c-format msgid "Low sensivity" msgstr "Ðизька чутливіÑть" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "помилка_розÑ" #: backend/kvs40xx_opt.c:249 #, no-c-format msgid "No detection" msgstr "Без виÑвленнÑ" #: backend/kvs40xx_opt.c:250 #, no-c-format msgid "Normal mode" msgstr "Звичайний режим" #: backend/kvs40xx_opt.c:251 #, no-c-format msgid "Enhanced mode" msgstr "Розширений режим" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" "У режимі довгого паперу Ñканер виконує Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ Ð¿Ð¾Ð´Ñ–Ð»Ñƒ " "довгого лиÑта паперу на відрізки довжини, вÑтановлені за допомогою " "параметра «Розмір документа»" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‡ÑƒÑ‚Ð»Ð¸Ð²Ð¾Ñті датчика подвійного подаваннÑ" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "Ð’Ñтановити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‡ÑƒÑ‚Ð»Ð¸Ð²Ð¾Ñті датчика подвійного подаваннÑ" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "Ðе зупинÑтиÑÑ Ð¿Ñ–ÑÐ»Ñ Ð²Ð¸ÑÐ²Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð´Ð²Ñ–Ð¹Ð½Ð¾Ð³Ð¾ подаваннÑ" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "Ігнорувати лівий датчик подвійного подаваннÑ" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "Ігнорувати центральний датчик подвійного подаваннÑ" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "Ігнорувати правий датчик подвійного подаваннÑ" #: backend/kvs40xx_opt.c:642 #, no-c-format msgid "Automatic threshold mode" msgstr "Режим автоматичного порогового значеннÑ" #: backend/kvs40xx_opt.c:643 #, no-c-format msgid "Sets the automatic threshold mode" msgstr "Ð’Ñтановлює режим автоматичного порогового значеннÑ" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "ІнверÑивне Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ чорно-білому режимі" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "СтиÑÐºÐ°Ð½Ð½Ñ JPEG" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "СтиÑÐºÐ°Ð½Ð½Ñ JPEG (ваша програма повинна мати змогу розпакувати дані)" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "ВиÑвлÑти підшиті документи" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "інтенÑивніÑть червоного" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "Ð’Ñтановити інтенÑивніÑть червоного" #: backend/kvs40xx_opt.c:787 #, no-c-format msgid "chroma of blue" msgstr "інтенÑивніÑть Ñинього" #: backend/kvs40xx_opt.c:788 #, no-c-format msgid "Set chroma of blue" msgstr "Ð’Ñтановити інтенÑивніÑть Ñинього" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "ÐšÐ¾Ñ€Ð¸Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐºÐ¾ÑˆÑƒÐ²Ð°Ð½Ð½Ñ" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "Зупинити ÑкануваннÑ, Ñкщо папір було перекошено" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ зупинено, Ñкщо папір було вÑтавлено з нахилом" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "Обрізати до Ñправжньої облаÑті зображеннÑ" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "Сканер автоматично визначає облаÑть Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ– обрізає його" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "ÐŸÐµÑ€ÐµÐ²ÐµÑ€Ñ‚Ð°Ð½Ð½Ñ Ð»Ñ–Ð²Ð¾Ñ€ÑƒÑ‡ Ñ– праворуч" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñтору у верхній чаÑтині" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñтору у нижній чаÑтині" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Діамант" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 Значна жирніÑть" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 Помірна жирніÑть" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "Ð¡ÐµÐºÑ†Ñ–Ñ 8x8" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Вертикальна лініÑ" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "ПідÑиленнÑ" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Параметри підÑÐ¸Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñ–Ð² кольорів" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "ПідÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñірого" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Визначає підÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñірого каналу" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "ПідÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Визначає підÑÐ¸Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñƒ червоного" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "ПідÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Визначає підÑÐ¸Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñƒ зеленого" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "ПідÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñинього" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Визначає підÑÐ¸Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñƒ Ñинього" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Секційний дизеринг 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Секційний дизеринг 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Ðапівтонова точка 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Ðапівтонова точка 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "ÐŸÐ¾ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾Ð¼Ð¸Ð»Ð¾Ðº" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Режим 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Режим 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Режим 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "Від білої палички" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Плавний" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Ðизький" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Середній" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "ВиÑокий" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "ЕПТ" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Одна Ñторінка" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Ð’ÑÑ– Ñторінки" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "Ñканер з подачею аркушів" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Відтінки Ñірого, 4-бітова" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Відтінки Ñірого, 8-бітова" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "ЗатіненіÑть, напівтон, підÑвічуваннÑ, Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Спеціальні параметри" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð²" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Вимкнути зворотне ÑтеженнÑ" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Якщо буде позначено цей пункт, Ñканер не виконуватиме поверненнÑ" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Перемкнути лампу планшетного Ñканера" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Перемикає лампу планшетного Ñканера" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "ÐšÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¾ÑŽ обробки" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Якщо позначено цей пункт, ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð² перед ÑкануваннÑм " "виконуєтьÑÑ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¾ÑŽ обробки" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "ВикориÑтовувати 35 мм адаптер lightlid" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "" "Якщо позначити цей пункт, лампу планшетного Ñканера на Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ " "буде вимкнено" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "ЯкіÑне ÑкануваннÑ" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Ðайкраща ÑкіÑть, але повільно" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Швидке ÑкануваннÑ" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Ðайшвидше, але низька ÑкіÑть" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Ðвтоматичне Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð³Ð¾Ð²Ð¾Ð³Ð¾ значеннÑ" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Якщо буде позначено цей пункт, програма обробки Ñпробує визначити " "оптимальне порогове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ автоматичному режимі." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Визначає режим Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ (ÑÑ‚ÑƒÐ¿ÐµÐ½Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð°ÑтноÑті)." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Пов’Ñзана гама" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "ВикориÑтовувати однакові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ Ð´Ð»Ñ Ð²ÑÑ–Ñ… каналів кольорів." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "СкалÑрна гама" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑкалÑрного Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "СкалÑрна гама червоного" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "" "Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑкалÑрного Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ (канал червоного)." #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "СкалÑрна гама зеленого" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "" "Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑкалÑрного Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ (канал зеленого)." #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "СкалÑрна гама Ñинього" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Визначає Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑкалÑрного Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð¸ (канал Ñинього)." #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Канал" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Визначає зв’Ñзок кольорів. «ОÑновний» визначає зв’Ñзок вÑÑ–Ñ… кольорів." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Ðапівтон" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Визначає рівень ÑвітноÑті, Ñкий вважатиметьÑÑ Â«50 % Ñірим»." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Ðапівтон Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Визначає рівень ÑвітноÑті, Ñкий Ñ” «50 % червоним»." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Ðапівтон Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Визначає рівень ÑвітноÑті, Ñкий Ñ” «50 % зеленим»." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Ðапівтон Ð´Ð»Ñ Ñинього" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Визначає рівень ÑвітноÑті, Ñкий Ñ” «50 % Ñинім»." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" "Коефіцієнт баланÑу Ð´Ð»Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ 100% означає «без " "виправленнÑ»." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" "Коефіцієнт баланÑу Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ 100% означає «без " "виправленнÑ»." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ Ñинього" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" "Коефіцієнт баланÑу Ð´Ð»Ñ Ñинього. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñƒ 100% означає «без " "виправленнÑ»." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Ð‘Ð°Ð»Ð°Ð½Ñ Ð¼Ñ–ÐºÑ€Ð¾ÐºÐ¾Ð´Ñƒ" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Ð’Ñтановлює значеннÑ баланÑу кольорів на оÑнові даних з мікрокоду." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Ðайповільніша" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Повільна" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Швидша" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Ðайшвидша" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 грубе" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 звичайне" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 добре" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 дуже добре" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 звичайне" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 грубе" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 добре" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 грубе" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 звичайне" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 добре" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 звичайне" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 звичайне" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 нетипове" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 нетипове" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 нетипове" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 нетипове" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 нетипове" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 нетипове" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Швидкий чорно-білий режим" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Сканувати у швидкому чорно-білому режимі (погана ÑкіÑть)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Ðаказує програмі Ñтворювати вÑÑ– попередні переглÑди у найшвидшому " "(низькоÑкіÑному) режимі. Цим режимом може бути чорно-білий режим або " "режим з низькою роздільною здатніÑтю." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Ð§Ð°Ñ Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ (у хвилинах)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Визначає Ñ‡Ð°Ñ (у хвилинах), через Ñкий лампу буде вимкнено." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Вимкнути лампу" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Ðегайно вимикає лампу." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "ЯÑкравіÑть червоного" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Керує ÑÑкравіÑтю каналу червоного у отриманому зображенні." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "ЯÑкравіÑть зеленого" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "Керує ÑÑкравіÑтю каналу зеленого у отриманому зображенні." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "ЯÑкравіÑть Ñинього" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Керує ÑÑкравіÑтю каналу Ñинього у отриманому зображенні." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "КонтраÑтніÑть червоного каналу" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Керує контраÑтніÑтю каналу червоного у отриманому зображенні." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "КонтраÑтніÑть зеленого каналу" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Керує контраÑтніÑтю каналу зеленого у отриманому зображенні." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "КонтраÑтніÑть Ñинього каналу" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Керує контраÑтніÑтю каналу Ñинього у отриманому зображенні." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Кольоровий 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Кольоровий 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Чорно-білий 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Чорно-білий 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Відбиток" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Позитив" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Розігрівати, до Ñталої ÑÑкравоÑті лампи, не наполÑгати на 40-ти " "Ñекундному розігріві." #: backend/pixma.c:378 #, no-c-format msgid "Negative color" msgstr "Кольоровий негатив" #: backend/pixma.c:383 #, no-c-format msgid "Negative gray" msgstr "Чорно-білий негатив" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "48-бітовий колір" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "16-бітовий Ñірий" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" "Визначає джерело ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ (зокрема приÑтрій подачі документів). " "Ð’Ñтановіть джерело перед режимом Ñ– роздільною здатніÑтю. Відновлює " "автоматично визначені Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ та роздільної здатноÑті." #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Кероване кнопкою ÑкануваннÑ" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Якщо буде позначено цей пункт, Ð¿Ñ€Ð¾Ñ†ÐµÑ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ розпочинатиметьÑÑ " "негайно. Ð”Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ, натиÑніть кнопку «SCAN» (MP150) або " "«COLOR» (Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… моделей). Ð”Ð»Ñ ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ñ‚Ð¸Ñніть кнопку «GRAY»." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Оновити Ñтан кнопки" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Кнопка 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Кнопка 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "Тип оригіналу Ð´Ð»Ñ ÑкануваннÑ" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "Тип дії Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ñƒ" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐПД" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" "Якщо визначено, Ñканер шукатиме новий документ, вÑтавлений до приÑтрою " "автоматичної подачі документів, протÑгом вказаної кількоÑті Ñекунд." #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "ПрозоріÑть" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Параметри приÑтрою" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Перемикач лампи" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "ÐŸÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿ вручну." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ під Ñ‡Ð°Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ð³Ð¾" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Завжди вимикати лампу під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ñ— зони" #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "ÐšÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… калібруваннÑ" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Вмикає або вимикає ÐºÐµÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… калібруваннÑ." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Виконує калібруваннÑ" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Пришвидшити датчик" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Вмикає або вимикає Ð¿Ñ€Ð¸ÑˆÐ²Ð¸Ð´ÑˆÐµÐ½Ð½Ñ Ñ€ÑƒÑ…Ñƒ датчика." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Ð§Ð°Ñ Ñ€Ð¾Ð·Ñ–Ð³Ñ€Ñ–Ð²Ñƒ" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Ð§Ð°Ñ Ñ€Ð¾Ð·Ñ–Ð³Ñ€Ñ–Ð²Ñƒ у Ñекундах." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Ð§Ð°Ñ Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Ð§Ð°Ñ Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ у Ñекундах." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Ðналогова оболонка" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾ AFE" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Ð—Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð²Ð¾Ð½Ð¾Ð³Ð¾ AFE" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ÑÐ¸Ð»ÐµÐ½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾ AFE" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾ AFE" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ÑÐ¸Ð»ÐµÐ½Ð½Ñ Ñинього AFE" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñинього AFE" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ червоного" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Визначає параметр Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ червоного" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ зеленого" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Визначає параметр Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ зеленого" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Ð’Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ Ñинього" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Визначає параметр Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸ Ñинього" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Цей параметр відповідає Ñтану кнопок Ñканера." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Кольоровий 36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Карта дизерингу 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Карта дизерингу 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Випадково" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Вибір джерела" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "ÐŸÐ¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Зробити чорно-білим" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Завантажити Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñк чорно-біле" #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ трьох проходів" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Імітувати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñƒ три проходи поверненнÑм 3 окремих кадрів. Буде " "повернено кадри Ð´Ð»Ñ Ð·ÐµÐ»ÐµÐ½Ð¾Ð³Ð¾, Ñинього, а потім червоного кольору." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ñканера" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Імітує ручний Ñканер. Ручні Ñканери чаÑто попередньо не отримують даних " "щодо виÑоти зображеннÑ. ЗаміÑть цього, вони повертають виÑоту рівну -1. " "Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ параметра надає змогу перевірити, чи може оболонка " "правильно обробити такі дані." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Ð’Ñтановити типові Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñм (ÑÑкравіÑтю Ñ– " "контраÑтніÑтю)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "ТеÑтовий параметр лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Давайте переконаємоÑÑ Ñƒ правильноÑті обробки даних оболонкою" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Таблиці гамми" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ ÐºÐ¾Ð´Ñƒ Ñтану" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Ðе вÑтановлювати код Ñтану примуÑово" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Ðе примушувати інÑтрумент обробки повертати код Ñтану." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Повернути SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_EOF піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ " "sane_read()." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Повернути SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_JAMMED піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ " "sane_read()." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Повернути SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_NO_DOCS піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ " "sane_read()." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Повернути SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_COVER_OPEN піÑÐ»Ñ " "виклику sane_read()." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Повернути SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_IO_ERROR піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ " "sane_read()." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Повернути SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_NO_MEM піÑÐ»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ " "sane_read()." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Повернути SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Ðаказати Ñерверу повертати код Ñтану SANE_STATUS_ACCESS_DENIED піÑÐ»Ñ " "виклику sane_read()." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Цей пункт відповідає Ñтану кнопки ÑкануваннÑ." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Увімкнути лампу" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Увімкнути лампу Ñканера" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Вимкнути лампу" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Вимкнути лампу Ñканера" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "" "КількіÑть хвилин, за Ñкі лампу буде вимкнено піÑÐ»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÑкануваннÑ" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Порогове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÑˆÑ‚Ñ€Ð¸Ñ…Ð¾Ð²Ð¾Ð³Ð¾ режиму" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Подача документів" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (дюймів)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (дюймів)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (дюймів)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Ðапівтонове ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ підтримуєтьÑÑ" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "КількіÑть ліній ÑкануваннÑ, на Ñкі Ñлід надÑилати запит під Ñ‡Ð°Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ " "зі SCSI. За допомогою цього параметра ви зможете налаштувати швидкіÑть " "Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… зі Ñканера під Ñ‡Ð°Ñ ÑкануваннÑ. Якщо вÑтановити мале " "значеннÑ, під Ñ‡Ð°Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñканер зупинÑтиметьÑÑ Ñƒ процеÑÑ– ÑкануваннÑ. " "Якщо ж Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ завеликим, заÑновані на Ñервері X оболонки не " "відповідатимуть на події X, а ÑиÑтема значно уповільнитьÑÑ." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "КількіÑть кадрів на шаблоні, Ñкий має бути Ñкановано." #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "ВикориÑтовувати ручний або автоматичний вибір точки фокуÑуваннÑ." #: backend/snapscan-options.c:117 #, no-c-format msgid "Focus point for scanning." msgstr "Точка фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑкануваннÑ." #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Режим попереднього переглÑду" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Оберіть режим попереднього переглÑду. Чорно-білий режим, зазвичай, дає " "найкращу комбінацію швидкоÑті Ñ– деталізації." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Попередньо визначені параметри" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Визначає Ñтандартні облаÑті ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ñ„Ð¾Ñ‚Ð¾Ð³Ñ€Ð°Ñ„Ñ–Ð¹, друкованих " "Ñторінок та подібних документів." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "Кадр" #: backend/snapscan-options.c:885 #, no-c-format msgid "Frame to be scanned" msgstr "Кадр, Ñкий буде Ñкановано" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "Режим фокуÑуваннÑ" #: backend/snapscan-options.c:898 #, no-c-format msgid "Auto or manual focus" msgstr "Ðвтоматичне або ручне фокуÑуваннÑ" #: backend/snapscan-options.c:911 #, no-c-format msgid "Focus-point" msgstr "Точка фокуÑуваннÑ" #: backend/snapscan-options.c:912 #, no-c-format msgid "Focus point" msgstr "Точка фокуÑуваннÑ" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Кольорових ліній на ÑÐµÐ°Ð½Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Чорно-білих ліній на ÑÐµÐ°Ð½Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "Веб-камера" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Кольоровий RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Кольоровий RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Кольоровий RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Суцільний чорний" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Суцільний білий" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Кольоровий візерунок" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Òратка" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Перший запиÑ" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Другий запиÑ" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Третій Ð·Ð°Ð¿Ð¸Ñ Ñ” затримуєтьÑÑ. Можливо, оболонка не може його показати." #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÑƒÑ‡Ð½Ð¾Ð³Ð¾ Ñканера" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Імітує ручний Ñканер. Ручні Ñканери попередньо не отримують даних щодо " "виÑоти зображеннÑ. ЗаміÑть цього, вони повертають виÑоту рівну -1. " "Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ параметра надає змогу перевірити, чи може оболонка " "правильно обробити такі дані. ÐŸÐ¾Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ пункту також увімкне " "фікÑовану ширину у 11 Ñм." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Ð†Ð¼Ñ–Ñ‚Ð°Ñ†Ñ–Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ трьох проходів" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Імітувати ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð· трьома проходами. У кольоровому режимі буде " "повернуто три кадри." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Визначити порÑдок кадрів" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Визначити порÑдок кадрів у кольоровому режимі трьох проходів." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Якщо обрано режим автоматичної подачі документів, приÑтрій подачі буде " "«Ñпорожнено» піÑÐ»Ñ 10 Ñканувань." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "ОÑобливі параметри" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Оберіть теÑтове зображеннÑ" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Оберіть різновид теÑтового зображеннÑ. Можливі варіанти:\n" "Суцільний чорний: вÑÑŽ облаÑть ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñ„Ð°Ñ€Ð±Ð¾Ð²Ð°Ð½Ð¾ чорним.\n" "Суцільний білий: вÑÑŽ облаÑть ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñ„Ð°Ñ€Ð±Ð¾Ð²Ð°Ð½Ð¾ білим.\n" "Кольоровий візерунок: намалює різноманітні кольорові візерунки, залежно " "від режиму.\n" "Òратка: намалює чорно-білу ґратку з шириною Ñ– виÑотою 10 мм на квадрат." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Інвертувати порÑдок байтів" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "ПомінÑти міÑцÑми Ñтарший Ñ– молодший байти даних Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñƒ 16-бітовий " "режимах. Цей пункт можна викориÑтовувати Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ 16-бітових " "режимів оболонок, наприклад, перевірки правильноÑті порÑдку байтів у " "оболонці." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Ð“Ñ€Ð°Ð½Ð¸Ñ†Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Обмежити об’єм даних, що передаютьÑÑ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ виклику sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Розмір границі читаннÑ" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "Об’єм (макÑимальний) даних, Ñкі буде передано під Ñ‡Ð°Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ з викликів " "sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Затримка читаннÑ" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Затримка Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… до каналу." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "ТриваліÑть затримки читаннÑ" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ з буферів даних каналом." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Повернуте Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Вкажіть повернуте Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ sane_read(). «Типове» означає звичайну " "обробку ÑкануваннÑ. Ð’ÑÑ– інші коди Ñтану призначено Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ " "ÑпоÑобів Ñ—Ñ… обробки оболонкою." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Втрата точок на лінію" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "КількіÑть точок, Ñкі було втрачено наприкінці кожної з ліній." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Параметри нечіткоÑті" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "КількіÑть повернутих неточних Ñ€Ñдків Ñ– байтів, Ñкщо sane_parameters() " "викликаєтьÑÑ Ð´Ð¾ sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "ВикориÑтовувати ввід-вивід без блокуваннÑ" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "ВикориÑтовувати режим вводу-виводу без Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ sane_read(), Ñкщо " "підтримуєтьÑÑ Ð¾Ð±Ð¾Ð»Ð¾Ð½ÐºÐ¾ÑŽ." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Пропонувати обрати деÑкриптор файла" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Пропонувати обрати деÑкриптор файла Ð´Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð¾Ð³Ð¾, чи повертатиме " "sane_read() дані." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Увімкнути параметри перевірки" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Увімкнути різноманітні параметри перевірки. Призначено Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ " "можливоÑтей оболонки переглÑдати Ñ– змінювати вÑÑ– параметри SANE." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Параметри друку" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Ðадрукувати ÑпиÑок вÑÑ–Ñ… параметрів." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Двійкові параметри перевірки" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Булевий програмний вибір програмне визначеннÑ" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей " "програмного вибору Ñ– програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ (та додаткових). Це " "звичайний булевий параметр." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Булевий апаратний вибір програмне визначеннÑ" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей " "апаратного вибору Ñ– програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ (та додаткових). Це означає, " "що параметр не може бути вÑтановлено оболонкою, лише кориÑтувачем " "(наприклад, натиÑканнÑм кнопки на приÑтрої)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Булевий апаратний вибір" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей " "апаратного вибору (та додаткових). Це означає, що параметр не може бути " "вÑтановлено оболонкою, лише кориÑтувачем (наприклад, натиÑканнÑм кнопки " "на приÑтрої), оболонка не може читати дані за такої конфігурації." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) М’Ñке булівÑьке виÑвленнÑ" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей " "програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ (та додаткових). Це означає, що параметр " "призначено лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Булева емулÑÑ†Ñ–Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð½Ð¾Ð³Ð¾ вибору Ñ– програмного визначеннÑ" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей " "програмного вибору, програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‚Ð° емулÑції (та додаткових)." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Булевий автоматичний програмний вибір, програмне визначеннÑ" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Булевий параметр перевірки, Ñкий визначає наÑвніÑть можливоÑтей " "програмного вибору, програмного Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ– автоматичних (та " "додаткових) можливоÑтей. Цей параметри може автоматично вÑтановлюватиÑÑ " "Ñервером." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "ЦілочиÑельні параметри перевірки" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) ЦілочиÑельний" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "" "(1/6) ЦілочиÑельний параметр перевірки без одиниці виміру Ñ– набору " "обмежень." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) ЦілочиÑельний діапазон обмеженнÑ" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) ЦілочиÑельний параметр з розмірніÑтю у пікÑелÑÑ… Ñ– набором " "обмежень. Мінімальним значеннÑм може бути 4, макÑимальним — 192, крок — " "2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) ЦілочиÑельний ÑпиÑок обмежень Ñлів" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) ЦілочиÑельний параметр перевірки з одиницею виміру біт Ñ– набором " "обмежень ÑпиÑку Ñлів." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) ЦілочиÑельний маÑив" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) ЦілочиÑельний параметр перевірки з одиницею виміру міліметри Ñ– " "викориÑтаннÑм маÑиву без обмежень." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(2/6) ЦілочиÑельний маÑив з діапазоном обмеженнÑ" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) ЦілочиÑельний параметр з розмірніÑтю у точках на дюйм з " "викориÑтаннÑм маÑиву обмежень діапазону. Мінімальним значеннÑм може бути " "4, макÑимальним — 192, крок — 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) ЦілочиÑельний маÑив зі ÑпиÑком обмежень Ñлів" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) ЦілочиÑельний параметр з розмірніÑтю у відÑотках з викориÑтаннÑм " "маÑиву обмежень ÑпиÑку Ñлів." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "ДробовочиÑлові параметри перевірки" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) ДробовочиÑловий" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "" "(1/3) ДробовочиÑловий параметр перевірки без одиниці виміру Ñ– без набору " "обмежень." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) ФікÑований обмежений діапазон" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) ДробовочиÑловий параметр з розмірніÑтю у міліÑекундах Ñ– набором " "обмежень. Мінімальним значеннÑм може бути -42.17, макÑимальним — " "32767.9999, крок — 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) ФікÑований обмежений ÑпиÑок Ñлів" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) ДробовочиÑловий параметр перевірки без одиниці виміру Ñ– набором " "обмежень ÑпиÑку Ñлів." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "РÑдкові параметри перевірки" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) РÑдок" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) Варіант перевірки Ñ€Ñдків без обмежень." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) РÑдкова з обмеженим ÑпиÑком Ñ€Ñдків" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) Варіант перевірки Ñ€Ñдків з обмеженнÑм на ÑпиÑок Ñ€Ñдків." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) РÑдкова з обмеженим довгим ÑпиÑком Ñ€Ñдків" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) Варіант перевірки Ñ€Ñдків з обмеженнÑм на ÑпиÑок Ñ€Ñдків. МіÑтить " "дещо більше запиÑів..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Параметри перевірки кнопок" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Кнопка" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Варіант перевірки кнопок. Друкує текÑÑ‚..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Кольоровий 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "ВикориÑтовувати ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Дворівневий чорно-білий (штриховий режим)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Дизеринг/Ðапівтони чорно-білого (напівтоновий режим)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Багаторівневий чорно-білий (режим відтінків Ñірого)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Багаторівневий колір RGB (колір з одним проходом)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ігнорувати калібруваннÑ" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Вимкнути попереднє фокуÑуваннÑ" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Ðе калібрувати фокуÑуваннÑ" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Попереднє фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "ЗафікÑувати позицію фокуÑуваннÑ" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "ÐšÐ°Ð»Ñ–Ð±Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ð½Ð· у облаÑті документа" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Калібрувати фокуÑÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ð½Ð· у облаÑті документа" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "ÐŸÐ¾Ð·Ð¸Ñ†Ñ–Ñ Ñ„Ð¾ÐºÑƒÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´ÐµÑ€Ð¶Ð°ÐºÐ° 0 мм" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "ÐŸÐ¾Ð·Ð¸Ñ†Ñ–Ñ Ñ„Ð¾ÐºÑƒÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´ÐµÑ€Ð¶Ð°ÐºÐ° 0 мм заміÑть 0,6 мм" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Режим калібруваннÑ" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Визначає режим калібруваннÑ" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Визначає Ñтан вмиканнÑ/Ð²Ð¸Ð¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð»Ð°Ð¼Ð¿Ð¸" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "Увімкнути UTA" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Увімкнути/Вимкнути UTA" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "ЗÑув" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Параметри зÑуву каналів кольорів" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "ЗÑув Ñірого" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Визначає зÑув каналу Ñірого" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Визначає зÑув каналу червоного" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Визначає зÑув каналу зеленого" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Визначає зÑув каналу Ñинього" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Режим попереднього переглÑду" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "Проблема не піддаєтьÑÑ Ð°Ð½Ð°Ð»Ñ–Ð·Ñƒ (невідомий ÐºÐ»Ð°Ñ SCSI)" sane-backends-1.0.27/po/pl.gmo0000664000175000017500000023434513110600540012760 00000000000000Þ•~ ©ü7 J ¡J-®J ÜJ;èJ $K,1K"^KzK üK9L@L€]L#ÞL5M"8MÆ[M"Nj=N ¨NBÉN( OS5O‰OØ OyPB˜PÛPlòP_QJoQ+ºQcæQ JRzkR'æR™S$¨SWÍS%T6TGTLTQTYT ^T iT tT TŠT ’T T¨T ±T ¼T ÇTÒT ÛT æT ñT üT U U U +U5UHUYU kU vUU ŠU •UÒ£UvV yV †V’V–V ŸV ªV´V½VÌV"ÔV!÷VW!9W [W|W œW½WÆWs×W KX5UX ‹X—X§X¹XÑXäXõX Y!.YPYpYuY„Y ›Y ¦Y ´Y¿Y ÔYÞY!øYZ/ZCZ<TZG‘Z_ÙZ9[>[=N[>Œ[<Ë[\ \\"\'2\Z\c\{\ \ ˜\¢\ ¨\´\ ¹\Æ\ Ö\à\û\ ] ]$]A] S]a]%p]–]%¥] Ë]Ö]ë]ô] ý] ^^5^=^@^P^ T^a^t^^­^È^ Ú^ä^ö^)_%;_ a_m_„_›_¬_ ¼_Ê_Û_ë_ ó_ þ_ ``5`<`&O`Äv`;aAaQaZa ia wa „a Ža˜a §aµaÒañab b.b6b>bFb \bhbqbzbb§b¼bÐbåb6øb./cB^cC¡cAåc,'d@TdA•d?×d(e @e!Le*ne ™e¤e(«eÔeéeíeÿeff)(f"Rf$uf*šf#Åf(éf!g4g#Rgvg“g ³gÔgIóg,=h'jh’h0¢hDÓh i$i4i „*e„ „š„£„´„ ½„Ë„ Ú„è„ û„ …….…>…C… J…XW…Þ°…†]¡†ÿ‡ ˆ&ˆL*ˆwˆ”ˆ›ˆžˆ§ˆLj߈÷ˆ ‰ ‰ #‰ /‰ ;‰ F‰ Q‰^‰}‰%’‰¸‰ Á‰ωÞ‰ ø‰ŠŠ !Š.Š4Š QŠM_Š­Š ÁŠ ÎŠÛŠëŠ ûŠ‹ ‹ ‹‹M5‹ƒ‹ ‡‹“‹¢‹«‹ Å‹ Ó‹ à‹ë‹Œ %Œ0ŒÖPŒ|' ¤ ²ÀÒ æŽ%Ž<ŽXŽrŽŽ[§Ž/ 4? Ubt‡ ˜¢ ² Ó ßìÿ8'S{ 𤠴 ÀxËD‘&Z‘ ‘‘ «‘¸‘Ë‘.Ü‘ ’$’#9’g]“œÅ“b”:z”;µ”9ñ”,+•YX•%²•Ø•Fð•7–/L–*|–"§–‡Ê–R—h—'‡—<¯—4ì—>!˜B`˜>£˜?â˜D"™?g™9§™9á™=š@Yš=ššBØš>›>Z›?™›=Ù›<œTœcœDkœ,°œÝœöœ?/o1‡¹;Øž'ž7žNžgž~ž—ž¯žÉžÚžðž>Ÿ?GŸ‡ŸDŸ%âŸ4 = )U X 2Ø Ì ¡Ø¡ß¡ï¡¢)¢ 9¢ D¢N¢b¢t¢ˆ¢›¢­¢À¢"Ö¢ù¢)£ 8£F£]£üe£Ðb¤p3¥K¤¥ð¥¦¦¦$¦)¦0¦8¦ ?¦ I¦ U¦a¦#r¦–¦¦¦"¶¦WÙ¦1§@§I§%d§Ч¡§¦§º§§<×§¨ 1¨ ?¨J¨Gc¨'«¨uÓ¨=I©Œ‡©6ªKªS\ª1°ª4âª7«;O«‹«¡« ·«Á« Ñ«ò« ¬ )¬ 7¬!B¬ d¬!o¬ ‘¬ž¬³¬Ŭج ê¬ ø¬­/­D­d­k­s­z­‹­£­í×­ê­ù­ ®.*®Y®Co®³®(Ê®ó®A¯I¯.g¯&–¯½¯ ۯ诰°3° <°J°Z°)j° ”°`µ°`± w±ƒ±Ÿ± ¿±˱¨ã±>Œ²‹Ë²W³ ]³i³~³”³)¨³ ҳ߳ã³ì³ ô³´´ ´*´:´)O´y´–´µ´Ê´ê´ µ µ!µ4µTµ]µfµ&yµ µ!¼µÞµïµ¶¶ .¶<¶W¶/v¶¦¶ƶζÞ¶‘å¶w¸;†¸¸EÞ¸$¹B8¹1{¹–­¹DºM_º3­º•áº&w»9ž»0Ø»  ¼,½&A½3h½Lœ½.é½\¾u¾’¾—¿^«¿" À“-ÀÁÀ]áÀ;?Áˆ{Á9‘>Â>ÐÂÂÃ7ÒÃm ÄxÄ‘ÄªÄ¯Ä ´ÄÀÄ ÅÄ ÓÄ ßÄ íÄ ùÄÅ Å "Å ,Å8Å GÅ UÅ _Å jÅ xńŠ–Å ¢Å °Å¼ÅÓÅíÅÆÆ (Æ 6Æ @ÆLÆù]ÆWÇ ZÇ gÇrÇvÇÇ ŽÇ™Ç¢Ç¶ÇÈÇ0àÇ2È0DÈ0uÈ2¦È0ÙÈ ÉÉx*É£É8´ÉíÉÊÊ0ÊIÊaÊ{Ê)”Ê$¾Ê&ãÊ ËË/ËMËdË|Ë“Ë ©Ë!·ËÙËùËÌ(Ì@BÌGƒÌdËÌ0Í5ÍNIÍK˜ÍLäÍ1Î8Î?ÎVÎ(mÎ –Î$¡ÎÆÎ)ßÎ ÏÏ %Ï 3Ï=ÏQÏeÏ#{ϟϵÏÐÏáÏÿÏÐ1Ð47ÐlÐ4rÐ §Ð±Ð ÆÐ ÑÐÜÐëÐ Ñ &Ñ0Ñ3ÑGÑ KÑXÑ nÑ |Ñ ˆÑ–Ñ ¬Ñ·Ñ%ÇÑ.íÑ$Ò AÒ%LÒ%rÒ˜Ò¨Ò·ÒËÒÜÒìÒ óÒÿÒÓ)%Ó OÓ]Ó3vÓïªÓšÔ Ô²Ô»ÔÔÔéÔ úÔ ÕÕÕ).Õ#XÕ|ՌիռÕÅÕÎÕ×Õ ñÕ ûÕÖÖ"Ö;ÖVÖqÖŠÖ8¥Ö%ÞÖ&×$+×&P×$w×%œ×#Â×%æ× Ø+Ø ?Ø6`Ø—Ø §Ø<´ØñØÙÙ 'Ù1ÙEÙ3_Ù3“Ù&ÇÙ0îÙ0Ú1PÚ1‚Ú&´Ú$ÛÚ$Û1%Û.WÛ/†ÛM¶Û2Ü$7Ü\Ü8pÜH©ÜòÜÝ Ý(ÝI0ÝzÝ&‘ݸÝÑÝ&èÝ$Þ4ÞKÞ)`ÞŠÞ“Þ°ÞÏÞìÞ: ßDßVß3hß.œß<Ëßàà39àmà‚à#¡àÅà"äàáá'á /á:áOPá á?»áûáâ"â>â^âpâŠâžâ¯âÈâEæâ,ãLãlã†ã<ä9Sä>ä5Ìäåå3åHå _åjå‚å¿ å`æ €æŒæ!œæ<¾æ ûæ ç'ç/ç6çLç \çhç pç{çŠç™ç ¨ç ´ç Áç Íç ×çãç÷çè"èBè Iè Vè`èèè±èÅèäè$ém%éj“écþéhbêfËêg2ëTšë ïëúëìì 5ìBì Tì`ìfì uìƒì"’ìµì)Åì'ïì)íAíÒíðíîî"î8î&Vî}îî¢îªîÅî!àîï ïï-ï!AïcïwïïŸï(¶ïßï æïðïðð-ð@ðRðdð~ð”ð®ðÊðBæðB)ñlñ‡ñ¦ñ­ñÈñ*áñ+ ò 8òBò]òuòŽò¬ò´òÇòDÖòó_#ó^ƒóLâó:/ô¶jôÊ!õbìõ Oö×ðöÈ÷Ü÷â÷ô÷ø#ø6øOø<`ø7ø Õø àøíø%ù(ù:ùWù0\ùùù-»ùéù$ú&ú 5úBúZú$rú—ú'«ú2ÓúûS û _ûkû‹û¤ûªûÂû%ßûü"ü8üAüIüQü aülüˆü¡ü0»üìüüü#ý#:ý ^ý!ý¡ý°ý¸ý¿ýÆý!Íý1ïý-!þOþdþmþþ‡þþ—þŸþ¯þ ¸þÆþÞþïþôþüþrÿûƒÿ gŒô L$"q” › ¦'³Ûô  -:L]p€!•·Ìëóû*BKZaG’Úî, @LSh xE™ßèú#$H^x‰"©Ì%âñ—ú’ ¢°Å!ã $ < Y t  a«  * C  H R  o } – ­ Å Õ +ì  , >  N o  =¬ ê   % @ U ”l  /  N \  y ‡  ¥ 5² è r9š¬GB]? @à.!YP#ªÎBà#13&eŒ„¬1C![F},ÄLñT>L“JàY+J…BÐBLVV£LúCGK‹F×HIg_±!P*.{$ªÏçþ>Z<r ¯5Ð+%I$o%”$º#ß"/&%V$|H¡Hê3@J0‹5¼ò, a75™åϵ»Òæ-û )  5 ? \ { ™ · × õ ;!O!%d!Š!š! ³!ûÀ!¼"s#Pó#D$[$v$|$ƒ$ ‹$ –$ ¤$ ±$¾$Ñ$ä$)õ$%/%?%P\%­% Å%Ñ%5ï%%&<& A&b&i&?‚&Â&á& ð&ý&N'+l'r˜'< (H(/Ö()a)?{).»)0ê)h*„*$Ÿ*Ä*Ê*"Ù*+ü*2(+[+m+3r+¦+5­+ã+ü+, <,],},(,¶,Ï,ç, ---!-2-O-m-‡--®-#À-1ä-.Z1.$Œ.:±.ì.Q/*Z/4…/Oº/ 0+0+K0+w0*£0Î0Ö0é0ü0D18T1]1]ë1I2!Y2&{2¢2´2äÒ2>·3•ö3Œ4 ‘4ž4¼4×4.ó4"54585L5T5 f5t5Ž55¬53Å5"ù5626#F6j6 }6Š6 £6#±6Õ6å6õ6' 7#47,X7…7¤7&º7á7ð7 8%#87I838µ8¾8Ò8¨¬ ‰æc©¡°9…Oƒg<}aS^A*—å2d¶uâýhHÌÛ‘¼DÚ– Gð¤þ’.><?®¬ô@IQ¢ÿ› á†ü†| 3HA4R i-J|¹*l¬Êî¢àÅË8½ò„ˆX¿tYp0¸©S6^´R¤m= LônbIvKÚ@’"Zé4ÔÜWH=¤œx"+.,]c__ñ4úé©fó O¼C6oá[m·-‡¥F;,§V£÷¯Ÿ–~](9)ó´ ã ŸƒŒW×xÏÆe3~-<„ZÙeTifw XkV^mÎVÐs‚¹ê5}ÕI þ{³y$JÍõ×}ºzÐÔt1@òýçÒ›­s®¹‹Ø×º¾Ql‰=Hpá T{qÌ#UU*oO¶ÇMYùôh5/ƒ(ªpàd;Ðb)Å%µ)7ûÆâÚ<Öhg¿v¦+q gtl>8œÞGr¾èí PY%lWQgø^ï‘þú9˜˜=é_>ΧÛÂsÛfŒùc06~šÓï¦ë2D™~ß­z.eFžN !ó5V0q[ ÁðýB»Ç&ûjÑ;(C‚"ÖM3ÿ6‡##å:FS“Âðæ bKšW-Ž!c è¢+õÂ'XÈ‚L8ãQ÷ÓÄ¥I`Á¸ã3qüˆz|€D¨æ€­owAì”Ö± Ê“LªÝ‹õR/›YÑ :f‡²Ó“7°4Ü…{n}``"ªÒwÙš«Š¯¶dÅÕrÆ|uhËx7KxP—/€À,1@âÃöÏŠG±„?ÕG¡a[Bÿȳ(»1øiÌø™'Á?ÉØ¥½À§ rj*0yõŽž½`BeR;ìÞoŸÝ”Z[dµMÊûF’²2êaŒ 1´ '8àsŽSï!ží&ˆ#vJ˜TmuPE¡ñ'/?D\ö•9ÉB U”üëjä$Ñ\jÀn†w{CEùk·¿]Uî&‘%î]b–ØÔyßvö‹«NA2p\M, ñ‰·º$TyÄê¸úkÙÍzr!$:åE¾¦Š ÏÜ»%K.J•NLëOkįiËu®ßÃÈÇnçÒ>P÷•œ£Éè³£Et™Îäòa+°Z5Í\7 &—X¼:Þì±Ý²ç_«…¨Nä)Cí(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF BackADF DuplexADF FrontADF ModeADF cover openADF jamAccess to resource has been deniedAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBackBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowCancel buttonChange Document.Change documentChannelChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCustomCustom color matrix for grayscale scans.Custom color matrix.DTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEnhance BlueEnhance GreenEnhance RedEnhancementError DiffusionError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFrontFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInk-jet printersInt test optionsInvalid argumentInvert endiannessJPEGLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryPDF buttonPage heightPage loadedPage widthPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner cover is openScanner mechanism locked for transportScanner modelScanner sensors and buttonsSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Speedup sensorStandardStart calibration process.Start calibration using special sheetStatus Code SimulationStopString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: sane-backends 1.0.21 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2010-11-06 19:33+0100 Last-Translator: Jakub Bogusz Language-Team: Polish Language: pl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (1/1) Przycisk(1/1) Opcja testowa przycisku. WyÅ›wietla trochÄ™ tekstu...(1/3) Typ staÅ‚oprzecinkowy(1/3) Opcja testowa staÅ‚oprzecinkowa bez jednostek i bez ograniczeÅ„(1/3) CiÄ…g znakowy(1/3) Opcja testowa typu ciÄ…g znakowy bez narzuconych ograniczeÅ„(1/6) logiczny miÄ™kki wybór miÄ™kkie wykrywanie(1/6) logiczna opcja testowa, która umożliwia miÄ™kki wybór i miÄ™kkie (oraz zaawansowane) wykrywanie możliwoÅ›ci. Jest to zwykÅ‚a opcja logiczna.(1/6) Typ caÅ‚kowity (int)(1/6) Opcja testowa typu caÅ‚kowitego bez narzuconych jednostek i ograniczeÅ„(2/3) Typ staÅ‚oprzecinkowy o ograniczonym zasiÄ™gu(2/3) Opcja testowa staÅ‚oprzecinkowa z jednostkÄ… w mikrosekundach i ograniczonym zasiÄ™giem. Minimum to -42.17, maksimum 32767.9999 a kwant to 2.0.(2/3) CiÄ…g znakowy ograniczony listÄ…(2/3) Opcja testowa typu ciÄ…g znakowy ograniczona listÄ…(2/6) Logiczny twardy wybór miÄ™kkie wykrywanie(2/6) Logiczna opcja testowa, która umożliwia twardy wybór i miÄ™kkie wykrywanie (również zaawansowanych) możliwoÅ›ci. Oznacza to, że opcja nie może być ustawiona przez frontend, tylko przez użytkownika (np. przez przyciÅ›niÄ™cie przycisku na urzÄ…dzeniu).(2/6) Typ caÅ‚kowity o ograniczonym zasiÄ™gu(2/6) Opcja testowa typu caÅ‚kowitego (3/3) Typ staÅ‚oprzecinkowy ograniczony sÅ‚ownikiem(3/3) Opcja testowa staÅ‚oprzecinkowa bez jednostek, ograniczona sÅ‚ownikiem(3/3) CiÄ…g znakowy ograniczony dÅ‚ugÄ… listÄ…(/3) Opcja testowa typu ciÄ…g znakowy ograniczony listÄ…. Zawiera trochÄ™ wiÄ™cej pozycji...(3/6) Logiczny twardy wybór(3/6) Logiczna opcja testowa, która umożliwia twardy wybór możliwoÅ›ci. Oznacza to, że opcja nie może być ustawiona przez frontend, tylko przez użytkownika (np. przez przyciÅ›niÄ™cie przycisku na urzÄ…dzeniu) i nie może być odczytywana przez frontend(/6) Typ caÅ‚kowity(3/6) Opcja testowa typu caÅ‚kowitego posiadajÄ…ca bity jednostek oraz ograniczona sÅ‚ownikiem(4/6) Logiczne miÄ™kkie wykrywanie(4/6) Logiczna opcja testowa, która umożliwia miÄ™kkie wykrywanie (również zaawansowanych) możliwoÅ›ci. Oznacza to, że jest tylko do odczytu.(4/6) Macierz typu caÅ‚kowitego(4/6) Opcja testowa typu caÅ‚kowitego z jednostkÄ… w mm, używajÄ…ca macierzy nieograniczonej(5/6) Emulowany logiczny miÄ™kki wybór miÄ™kkie wykrywanie(5/6) Logiczna opcja testowa, która umożliwia miÄ™kki wybór, miÄ™kkie wykrywanie i emulowanie (również zaawansowanych) możliwoÅ›ci(5/6) Macierz typu caÅ‚kowitego z ograniczonym zasiÄ™giem(5/6) Opcja testowa typu caÅ‚kowitego z jednostkÄ… w dpi, używajÄ…ca tablicy z ograniczeniem zasiÄ™gu. Minimum to 4, maksimum 192, a kwant to 2.(6/6) Logiczny miÄ™kki wybór miÄ™kkie wykrywanie automatyczne(6/6) Logiczna opcja testowa, która umożliwia miÄ™kki wybór, miÄ™kkie wykrywanie i automatyczne (oraz zaawansowane) możliwoÅ›ci. Ta opcja może być automatycznie ustawiania przez sterownik.(6/6) Macierz typu caÅ‚kowitego ograniczona sÅ‚ownikiem(6/6) Opcja testowa typu caÅ‚kowitego z jednostkÄ… w procentach, używajÄ…ca tablicy ograniczonej sÅ‚ownikiem1/2 zwykÅ‚ej prÄ™dkoÅ›ci1/3 zwykÅ‚ej prÄ™dkoÅ›ci10mm15mm2-pikselowy20mm2x2 ustawiany2x2 zwykÅ‚y3x3 ustawiany3x3 zwykÅ‚y4-pikselowy4x4 chropowaty4x4 ustawiany4x4 dobry4x4 zwykÅ‚y5x5 chropowaty5x5 ustawiany5x5 dobry6x4 (cale)6x6 ustawiany6x6 zwykÅ‚y8-bitowe wyjÅ›cie8-pikselowy8.5x11 (cale)8x10 (cale)Pogrubianie Bayera 8x8Pogrubianie ziarniste 8x8Pogrubianie dokÅ‚adne 8x8Linie pionowe 8x88x8 chropowaty8x8 ustawiany8x8 dobry8x8 zwykÅ‚y8x8 bardzo dobryDÅ‚uższy czas ekspozycji pozwala gÅ‚owicy odebrać wiÄ™cej Å›wiatÅ‚a. Sugerowane jest 175% dla wydruków, 150% dla zwykÅ‚ych slajdów i "Negatyw" dla filmu negatywowego. Dla ciemnych (nie doÅ›wietlonych) obrazków możesz zwiÄ™kszyć tÄ™ wartość.A4A5 krajobrazA5 portretADFADF tyÅ‚ADF dwustronnyADF przódTryb ADFpokrywa ADF otwartazakleszczenie ADFBrak dostÄ™pu do zasobuDodaje do błękitu bazujÄ…c na poziomie zieleniDodaje do błękitu bazujÄ…c na poziomie czerwieniDodaje do zieleni bazujÄ…c na poziomie błękituDodaje do zieleni bazujÄ…c na poziomie czerwieniDodaje do czerwieni bazujÄ…c na poziomie błękituDodaje do czerwieni bazujÄ…c na poziomie zieleniZaawansowaneOpcje zaawansowanePo wysÅ‚aniu komendy skanowania, czekaj aż przycisk na skanerze jest naciÅ›niÄ™ty, aby naprawdÄ™ rozpocząć skanowanieWszystkie stronyWyłączanie lampy zawsze podczas kalibracji ciemnoÅ›ci.Wzmocnienie analogoweFrontend analogowyAnalogowa gamma błękituAnalogowa korekcja gammaAnalogowa gamma zieleniAnalogowa gamma czerwieniAnalogowa korekcja gammaAnalogowa korekcja gamma dla niebieskiegoAnalogowa korekcja gamma dla zieleniAnalogowa korekcja gamma dla czerwieniAutomatycznyAutomatyczne progowanieAutomatyczny podziaÅ‚ obszaruWysuwanie automatyczneEkspozycja automatycznaOstrość automatycznaJednokrotny autofocusAutomatycznieAutomatyczny podajnik dokumentówAutomatyczne dostosowanie proguAutomatyczna separacjaAutomatyczne progowanieAutomatyczne rozgrzewanieAutomatyczne wysuwanie filmu z urzÄ…dzenia po każdym skanowaniuAutomatyczne wysuwanie filmu z urzÄ…dzenia przed zakoÅ„czeniem programuAutomatycznie ustawia jasność, kontrast, poziom bieli, gammÄ™, redukcjÄ™ szumów i emfazÄ™ obrazkaTyÅ‚Wymuszaj nawracanieWspółczynnik balansu dla niebieskiego. Wartość 100% oznacza brak korekcji.Współczynnik balansu dla zielonego. Wartość 100% oznacza brak korekcji.Współczynnik balansu dla czerwonego. Wartość 100% oznacza brak korekcji.WnÄ™kaBayeraDitherowanie Bayera 16Ditherowanie Bayera 64Dwupoziomowa czerÅ„ i biel (tryb kreski)Zepnij RGBZrównaj rozdzielczość w osi X i YZepnij analogowÄ… gammÄ™Identyczna gamma dla wszystkich kanałówGłębokość bitowaCzerÅ„Poziom czerniNiebieskiBalans niebieskiegoJasność błękituWzmocnienie błękituWartość AFE wzmocnienia błękituNatężenie błękituWyłącz niebieskÄ… lampÄ™Offset błękituWartość AFE offsetu zieleniOpcje testowe (typu logicznego)Od doÅ‚u do góryPrawaPrawa krawÄ™dź skanowanego obszaru (dolny prawy x).DolnaDolna krawÄ™dź skanowanego obszaru (dolny prawy y).JasnośćWbudowany profil CCTPrzycisk 1Przycisk 2Stan przyciskuOpcje testowe przyciskówSkanowanie sterowane przyciskiemPrzyciskiCDbłąd kontroli CPUCRTMonitory CRTKal. czasu ekspozycjidla błękitudla zielenidla czerwieniKal. gÄ™stoÅ›ci lampyKalibracjaKalibruj SkanerKalibruj przed nastÄ™pnym skanowaniemKaibruj skupienie soczewek w pozycji dokumentuKalibruje poziom dla czerni i bieli.KalibracjaKalibracja wykonywana przez sterownikPamięć podrÄ™czna danych kalibracjiTryb kalibracjiKalibruj terazPrzycisk anulowaniaZmieÅ„ Dokument.ZmieÅ„ dokumentKanaÅ‚ID chipsetuNazwa ukÅ‚adówWyczyść kalibracjÄ™Wyczyść pamięć podrÄ™cznÄ… kalibracjiZiarnistośćKalibracja ziarnistoÅ›ciKalibracja ziarnistoÅ›ci tylko dla pierwszego skanuKalibracja ziarnistoÅ›ci jest robiona tylko dla pierwszego przebiegu. DziaÅ‚a z wiÄ™kszoÅ›ciÄ… skanerów i pozwala zaoszczÄ™dzić czas. Jeżeli jasność obrazka jest różna za każdym skanem, wyłącz tÄ™ opcjÄ™. Opcja tylko dla testów.KolorKolor (48 bitów)Kolor 36Kolorowy tryb półcieniKolorowy tryb kreskiMatryca kolorówKolor RAWKolor RGBKolor RGB TEKSTBalans kolorówUstawienia wzmocnienia kanałów kolorówUstawienia offsetu kanałów koloruKorekcja koloruWspółczynnik korekcji koloruWzorzec kolorówKolor 24Kolor 36Kolor 48Liczba kolorów na odczytWarunkowyKontynuacjaKontrastKontrast kanaÅ‚u Kontrast kanaÅ‚u zieleniKontrast kanaÅ‚u czerwieniNadzoruje poziom błękituNadzoruje poziom zieleniNadzoruje poziom czerwieniUstawia "odcieÅ„" (poziom błękitu) otrzymanego obrazjaUstawia jasność uzyskanego obrazka.Steruje jasnoÅ›ciÄ… kanaÅ‚u błękitu.Steruje jasnoÅ›ciÄ… kanaÅ‚u zieleni.Steruje jasnoÅ›ciÄ… kanaÅ‚u czerwieni.Ustawia kontrast uzyskanego obrazka.Steruje kontrastem kanaÅ‚u błękitu.Steruje kontrastem kanaÅ‚u zieleni.Steruje kontrastem kanaÅ‚u czerwieni.Steruje wymuszaniem nawracaniaPrzycisk kopiowaniaKorekcja zgodna z rodzajem filmuKorekcja zgodna ze współczynnikiem przezroczystoÅ›ciPokrywa otwartaUżytkownikaMatryca kolorów użytkownika dla skanów w skali szaroÅ›ci.Matryca kolorów użytkownikaDTCOpcje odpluskwianiaDomyÅ›lnyWartoÅ›ci domyÅ›lneZdefiniuj tryb kalibracjiUstawia czas ekspozycji dla kalibracji niebieskiegoUstawia czas ekspozycji dla skanowania niebieskiegoUstawia czas ekspozycji dla kalibracjiUstawia czas ekspozycji dla kalibracji zielonegoUstawia czas ekspozycji dla skanowania zielonegoUstawia czas ekspozycji dla kalibracji czerwonegoUstawia czas ekspozycji dla skanowania czerwonegoUstawia czas ekspozycji dla skanowaniaUstaw gÄ™stość lampy do kalibracjiUstaw gÄ™stość lampy do skanowaniaDefiniuje parametr wyłączenia niebieskiej lampyDefiniuje parametr wyłączenia zielonej lampyDefiniuje parametr wyłączenia czerwonej lampyDefiniuje wzorzec tonowania (ditheringu) dla skanowania tonowanych obrazków.Definiuje współczynnik powiÄ™kszenia dla skaneraOpóźnia transfer danych do potoku.Kontrola gÄ™stoÅ›ciOkreÅ›la prÄ™dkość przy której postÄ™puje skanowanie.OkreÅ›la czy powinna być użyta wbudowana tabela gamma czy użytkownikaUrzÄ…dzenie zajÄ™teUstawienia urzÄ…dzeniaDiamentowyDyfuzjaWyłączenie automatycznego podajnika dokumentów, używanie tylko pÅ‚ytyNie wykonuj nawracaniaWyłączenie dynamicznego trybu kreskiWyłącz korekcjÄ™ gammaWyłącz interpolacjÄ™Zablokuj wstÄ™pne ustawianie ostroÅ›ciWyłącz korekcjÄ™ cieniowania bieliRozproszonaKropka16x16RozproszonaKropka8x8WyÅ›wietl krótkÄ… listÄ™ rozdzielczoÅ›ciDitherujZiarnistość A (4x4 Bayera)Ziarnistość B (4x4 Spiralna)Ziarnistość C (4x4 Siatka)Ziarnistość D (8x4 Siatka)Ditherowana/półcieniowa czerÅ„ i biel (tryb półtonów)Mapa Ditheringu 1Mapa Ditheringu 2Skanuj raczej w odcieniach szaroÅ›ci niż w kolorzePrzeprowadź jakoÅ›ciowÄ… kalibracjÄ™ biaÅ‚egoAutomatyczne ustawianie ostroÅ›ci tylko po wymianie noÅ›nikaNie kalibruj ostroÅ›ciNie wymuszaj kodu statusuNie wymuszaj na frontendzie zwracania kodu statusu.podajnik dokumentówDodatkowy podajnik dokumentówZakleszczenie podajnika dokumentówKoniec dokumentów w podajnikuPodwójna rozdzielczość optycznaPobierz wzór APobierz wzór BDropoutDwustronnySkanowanie dwustronneSkanowanie dwustronne pozwala na skanowanie przedniej i tylnej strony dokumentuOkres opóźnienia odczytuDynamiczna krzywa progowa, od ciemnego do jasnego, zwykle 50-65WysuÅ„WysuÅ„ dokument po zeskanowaniuWysuÅ„ film po zeskanowaniuWysuÅ„ film przed zakoÅ„czeniemWysuÅ„ film terazWysuniÄ™cie filmu *teraz*WysuÅ„ arkusz z ADFPrzycisk E-mailaEmulacja skali szaroÅ›ciWłącz skanowanie dwustronneWłącz automatyczne rozpoznawanie progu dla skanów w trybie kreski.Włącz wybór czasu ekspozycjiWłącz wybór gÄ™stoÅ›ci lampyUdostÄ™pnij opcje testoweUdostÄ™pnia różne opcje testowe. SÅ‚uży do testowania możliwoÅ›ci frontendów do przeglÄ…dania i modyfikowania różnych typów opcji SANE.Włączenie/wyłączenie automatycznego ustawiania ostroÅ›ciWłączenie/wyłączenie automatycznego wyboru ekspozycjiWłącza lub wyłącza pamięć podrÄ™cznÄ… danych kalibracji.Włącza lub wyłącza przyspieszanie ruchu czujnika.OsiÄ…gniÄ™to koniec plikuRozszerzenie błękituRozszerzenie zieleniRozszerzenie czerwieniUlepszanie"Przenikanie błędów"Błąd podczas operacji we/wyZamienia górny i dolny bajt danych obrazu w trybach 15-bitowych. Ta opcja może być używana do testowania 16-bitowych trybów frontendów, np. czy frontend używa odpowiedniej kolejnoÅ›ci.Uruchomienie kalibracji *teraz*EksperymentCzas ekspozycjiPowiÄ™ksz czas wyłączenia lampyPowiÄ™ksza czas wyłączenia lampy (z 15 minut do 1 godziny)Bardzo szybkiDodatkowe ustawienia kolorówDodatkiSzybkiSzybki tryb szaroÅ›ciSzybki podglÄ…dSzybki skanSzybszyNajszybszyPrzycisk faksutryb podajnikaPrzycisk plikuNazwa plikuRodzaj filmuPasek filmuDokÅ‚adnyDobry kolorBalans firmware-owyPierwsza pozycjaPopraw pozycjÄ™ skupieniaOpcje testowe staÅ‚oprzecinkowePÅ‚ytaTylko pÅ‚ytaOstrośćOstrość 2.5mm powyżej szybyPozycja skupienia (ostroÅ›ci)Ostrość na szybieWymuszaj nawracanieWymuszaj podglÄ…d czarnobiaÅ‚yWymuÅ› prawdziwÄ… głębiÄ™WymuÅ› kalibracjÄ™ przed skanowaniemZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_ACCESS_DENIED po tym jak zostaÅ‚a wywoÅ‚ana funkcja sane_read().ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_COVER_OPEN po tym jak zostaÅ‚a wywoÅ‚ana funkcja sane_read().ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_EOF po tym jak zostaÅ‚a wywoÅ‚ana funkcja sane_read().ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_IO_ERROR po tym jak zostaÅ‚a wywoÅ‚ana funkcja sane_read().ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_JAMMED po tym jak zostaÅ‚a wywoÅ‚ana funkcja sane_read().ZmuÅ› sterownik by zwróciÅ‚ kod SANE_STATUS_NO_DOCS po tym jak zostaÅ‚a wywoÅ‚ana funkcja sane_read().ZmuÅ› sterownik by zwróciÅ‚ kod po tym jak zostaÅ‚a wywoÅ‚ana funkcja sane_read().Od papieruOd biaÅ‚ego elementuPrzódOczekiwanie na przycisk paneluPeÅ‚ny ekranParametry rozmyteWzmocnienieGammaKorekcja GammaTablice gammaKorekcja gammaKorekcja gamma bÄ™dzie wyłączonaWartość gammaTabela korekcji gamma dla pasma błękituTabela korekcji gamma dla pasma zieleniTabela korekcji gamma dla pasma czerwieniTabela korekcji gamma. W trybie kolorowym ta opcja równomiernie wpÅ‚ywa na wszystkie kanaÅ‚y jednoczeÅ›nie (staje siÄ™ tabelÄ… intensywnoÅ›ci).KrawÄ™dzie obszaru skanowaniaGrupa geometriiWielkość ziarnaSkala szaroÅ›ciWzmocnienie szaroÅ›ciKolor trybu odcieni szaroÅ›ciPrzesuniÄ™cie (offset) skali szaroÅ›ciSkala szaroÅ›ci 16Skala szaroÅ›ci 8WyszarzSkala szaroÅ›ci w 4-bitachSkala szaroÅ›ci w 8-bitachSkanowanie w odcieniach szaroÅ›ciZielonyBalans zielonegoJasność zieleniWzmocnienie zieleniWartość AFE wzmocnienia zieleniNatężenie zieleniWyłącz zielonÄ… lampÄ™Offset zieleniWartość AFE offsetu Liczba linii w skali szaroÅ›ci na odczytSiatkaPółtonyPółton A (Twardy)Półton B (MiÄ™kki)Półton C (Siatka)Półtonu Punkt 32Półton Punkt 64Wzór półcieniaRozmiar wzoru półcieniaTworzenie półtonówPółcienie nie wspieraneSymulacja skanera rÄ™cznegoSymulacja skanera rÄ™cznegoWewnÄ™trzne sprzÄ™towe poÅ‚ożenie poziome (X) obszaru skanowania.WewnÄ™trzne sprzÄ™towe poÅ‚ożenie pionowe (Y) obszaru skanowania.Rozdzielczość sprzÄ™towaOpcje specyficzne dla sprzÄ™tuWysokiDruk o wysokim kontraÅ›cieDruk wysokiej gÄ™stoÅ›ciNajwyższa jakość, ale maÅ‚a prÄ™dkośćNajwiÄ™ksza szybkość, ale gorsza jakośćŚwiatÅ‚oÅšwiatÅ‚o dla niebieskiegoÅšwiatÅ‚o dla zielonegoÅšwiatÅ‚o dla czerwonegoPozycja skupienia uchwytu 0mmPoziomyPoziomy pogrubionyPoziomy cienkiJak dÅ‚ugo czekać po transmisji każdego bufora danych przez potok.OdcieÅ„JeÅ›li wybrano automatyczny podajnij dokumentów (ADF), podajnik bÄ™dzie 'pusty' po 10 skanach.Jeżeli zaznaczone, sterownik automatycznie próbuje znaleźć optymalnÄ… wartość dla progu.JeÅ›li zaznaczone, sterownik wykonuje kalibracjÄ™ kolorów przed skanowaniemJeÅ›li zaznaczone, skaner nie wykonuje nawracania gÅ‚owicyJeÅ›li jest włączona, obraz bÄ™dzie skanowany w trybie kolorowym, a nastÄ™pnie konwertowany programowo do skali szaroÅ›ci. Może to poprawić jakość obrazu w pewnych przypadkach.Jeżeli włączone, tylko korekcja cieniowania jest przeprowadzana w czasie kalibracji. DomyÅ›lne sÄ… używane wartoÅ›ci dla wzmocnienia offsetu i czasu ekspozycji wbudowane lub z pliku konfiguracyjnegoJeÅ›li jest włączona, obrazy uczestniczÄ…ce w dostrajaniu skanera sÄ… zapisywane w celu analizy.JeÅ›li jest zaznaczone, urzÄ…dzenie bÄ™dzie kalibrowane przed nastÄ™pnym skanowaniem. W innym przypadku kalibracja zostanie wykonana przed pierwszym przebiegiemJeÅ›li korekcja gamma jest wyłączona, wszystkie skanowania bÄ™dÄ… wykonane z 16-bitowÄ… głębiÄ… w celu poprawy jakoÅ›ci obrazu, a nastÄ™pnie konwertowane do wybranej głębi. Ta opcja zapobiega emulacji głębi.Ignoruj kalibracjÄ™ObrazUlepszanie obrazuKolory obrazu bÄ™dÄ… odwróconeEmfaza obrazkaGÄ™stość obrazkaOpcje modyfikacji obrazuDrukarki igÅ‚oweW trybie RGB użyj tych samych wartoÅ›ci dla każdego koloruZwiÄ™ksz lub zmniejsz wzmocnienie analogowe matrycy CCDInformacjePodczerwieÅ„Drukarki atramentoweOpcje testowe typu caÅ‚kowitego (int)Błędny argumentOdwróć kolejność bajtówJPEGLampa nie gotowa, proszÄ™ spróbować powtórnieWyłącz lampÄ™Wyłącz lampÄ™ przy wyjÅ›ciuWyłącz lampÄ™ podczas kalibracji ciemnoÅ›ciCzas wyłączania lampyCzas wyłączenia lampy (w minutach)Włącz lampÄ™Status lampyCzas wyłączenia lampyCzas wyłączenia lampyCzas wyłączenia lampy w sekundach.Przełącznik lampyKalibracja soczewek w pozycji dokumentuSprawdzam czy frontendy interpretujÄ… to poprawnieListOgranicza ilość danych przesyÅ‚anych przy każdym wywoÅ‚aniu funkcji sane_read().Tryb kreskiZaÅ‚aduj obrazek jako szaroÅ›ciUtrata pikseli na liniÄ™NiskiDruk niskiej gÄ™stoÅ›ciRÄ™czne ustawianie ostroÅ›ciRÄ™czne wstÄ™pne ustawianie ostroÅ›ciRÄ™czne włączanie lamp(y).Macierz mnożenia RGBMaksimumNoÅ›nikÅšredniObsÅ‚uga mediumPółcieÅ„PółcieÅ„ dla niebieskiegoPółcieÅ„ dla zielonegoPółcieÅ„ dla czerwonegoLiczba minut do wyłączenia lampy po skanowaniuOdbicie poziomeOdbicie lustrzane obrazkaPoziome, lustrzane odbicie obrazka.Pionowe, lustrzane odbicie obrazka.Poziome odbicie lustrzane obrazuUtwórz odbicie lustrzane obrazkaOdbij pionowo.RóżneTryb 1Tryb 2Tryb 3Monochromatyczna matryca kolorówWielopoziomowy kolor RGB (kolor jednoprzebiegowy)Wielopoziomowa czerÅ„ i biel (tryb szaroÅ›ci)Skala szaroÅ›ci NTSCNTSC RGBWymaga kalibracjiNegatywNegatywNegatywNegatywRodzaj negatywuNegatywyBrak korekcjiBrak korekcji dla kliszRedukcja szumówBrakZwykÅ‚yZwykÅ‚a prÄ™dkośćIlość bitów na próbkÄ™; typowe wartoÅ›ci to 1 dla trybu kreski i 8 dla skanów kolorowych i w skali szaroÅ›ci.Liczba linii o które powraca gÅ‚owica, gdy wystÄ…pi nawracanie. To siÄ™ zdarza gdy skaner skanuje szybciej niż komputer może odebrać dane. Niskie wartoÅ›ci mogÄ… powodować szybsze skanowanie lecz zwiÄ™kszajÄ… ryzyko pominiÄ™cia niektórych linii.Liczba opcjiLiczba skanowanych linii w jednym żądaniu odczytu SCSI. Zmiana tego parametru umożliwia dostrojenie prÄ™dkoÅ›ci przy której dane sÄ… odczytywane ze skanera podczas skanowania. Jeżeli parametr jest ustawiony zbyt nisko, skaner bÄ™dzie musiaÅ‚ siÄ™ okresowo zatrzymywać w poÅ‚owie pracy; jeżeli za wysoko, graficzne frontendy mogÄ… przestać odpowiadać.Numer ramki do skanowaniaPrzycisk OCRWyłączProponuj deskryptor pliku "select" jeżeli sane_read() bÄ™dzie zwracaj dane.Proponuj deskryptor pliku "select"OffsetWłączonyJedna stronaPrzeprowadź tylko korektÄ™ cieniowaniaOperacja nieobsÅ‚ugiwanaOperacja anulowanaWyposażenie opcjonalneBrak pamiÄ™ciPrzycisk PDFWysokość stronyStrona wÅ‚ożonaSzerokość stronyRozmiar papieruÅšrodkowoprzepustowyWykonanie autodiagnostyki skaneraWykonuje kalibracjÄ™Fizyczny rozmiar papieru w ADFPozytywPozytywPozytywPozytyw lub negatywPrzycisk zasilaniaUstawienia zdefiniowanePodglÄ…dTryb podglÄ…duDrukujDrukuj listÄ™ wszystkich opcji.Opcje drukowaniaUdostÄ™pnia standardowe obszary skanowania dla fotografii, druków itp.Kalibracja jakoÅ›ciSkan dobrej jakoÅ›ciSzybkie formatowaniebłąd kontroli RAMbłąd kontroli ROMPorozrzucajSurowyOpóźnienie odczytuGranica odczytuTylko do odczytu (opcja testowa)Opcja tylko do odczytu, mówiÄ…ca ile opcji wspiera dane urzÄ…dzenie.CzerwonyBalans czerwonegoJasność czerwieniWzmocnienie czerwieniWartość AFE wzmocnienia czerwieniNatężenie czerwieniWyłącz czerwonÄ… lampÄ™Offset czerwieniWartość AFE offsetu czerwieniZmniejsz szum izolowanych punktówOdbijajÄ…cy Å›wiatÅ‚oZażądaj skanu w jakoÅ›ci podglÄ…du.Żądanie aby wszystkie podglÄ…dy byÅ‚y wykonywane w trybie monochromatycznym. W skanerze trójprzebiegowym ogranicza to liczbÄ™ przebiegów do jednego a na jednoprzebiegowym zmniejsza zapotrzebowanie na pamięć i czas pobierania podglÄ…du.Żądanie aby wszystkie podglÄ…dy byÅ‚y wykonywane w najszybszym trybie (niskiej jakoÅ›ci). To może być tryb niekolorowy lub niskiej rozdzielczoÅ›ci.Reset ukÅ‚adówReset skaneraZresetowanie skaneraZresetowanie danych ukÅ‚adówZwróć SANE_STATUS_ACCESS_DENIEDZwróć SANE_STATUS_COVER_OPENZwróć SANE_STATUS_EOFZwróć SANE_STATUS_IO_ERRORZwróć SANE_STATUS_JAMMEDZwróć SANE_STATUS_NO_DOCSZwróć SANE_STATUS_NO_MEMZwraca rozmyte linie i bajty na liniÄ™ gdy wywoÅ‚ywany jest sane_parameters() przed sane_start().Wartość powrotna sane_readbłąd parzystoÅ›ci SCSISDTCNasycenieZapisuj obrazy diagnostyczneLiniowa gammaLiniowa gamma, niebieskiLiniowa gamma, zielonyLiniowa gamma, czerwonyTryb skanowaniaGrupa trybu skanowaniaOpcje obszaru skanowania i rozmiaru obiektuPrzycisk skanowaniaLicznik skanowaÅ„Czas ekspozycjiCzas ekspozycji dla niebieskiegoCzas ekspozycji dla zielonegoCzas ekspozycji dla czerwonegoSkanuj w szybkim trybie odcieni szaroÅ›ci (niższa jakość).Skan gÄ™stoÅ›ci lampyMarginesy skanowaniaTryb skanowaniaRozdzielczość skanowaniaŹródÅ‚o skanowaniaPrÄ™dkość skanowaniaSkanuj caÅ‚y dostÄ™pny obszar, łącznie z paskiem kalibracyjnym. BÄ…dź ostrożny. Nie wybieraj peÅ‚nej wysokoÅ›ci. Opcja tylko do celów testowychPokrywa skanera jest otwartaMechanizm skanera zablokowany w celu transportuModel skaneraCzujniki i przyciski skaneraDruga pozycjaWybierz wnÄ™kÄ™ do skanowaniaRodzaj filmuWybierz minimalnÄ… jasność by uzyskać biaÅ‚y punktWybierz filtr wygÅ‚adzajÄ…cy.Wybór rodzaju filmuWybierz rodzaj obrazu testowego. DostÄ™pne opcje: CaÅ‚kowicie czarny: wypeÅ‚nia skan czerniÄ…. CaÅ‚kowicie biaÅ‚y: wypeÅ‚nia skan bielÄ…. Wzorzec kolorów: rysuje różne kolorowe wzory testowe, zależne od trybu. Siatka: rysuje czarno-białą siatkÄ™ o rozmiarach 10x10mm na kwadrat.Wybierz tryb dla podglÄ…dów. PodglÄ…dy w skali szaroÅ›ci zwykle dajÄ… najlepszÄ… kombinacjÄ™ szybkoÅ›ci i detali.Ustawia wartość powrotnÄ… sane_read(). "DomyÅ›lne" jest zwykÅ‚e skanowanie. Wszystkie inne kody statusu sÅ‚użą do testowania jak traktuje je frontend.Wybierz obraz testowyUstawia wartość liniowej korekcji gamma dla niebieskiego kanaÅ‚uUstawia wartość liniowej korekcji gamma dla zielonego kanaÅ‚uUstawia wartość liniowej korekcji gamma dla czerwonego kanaÅ‚uUstawia wartość dla liniowej korekcji gamma.Ustawia "ziarnistość" uzyskanego obrazka. Mniejsze wartoÅ›ci dadzÄ… ostrzejsze obrazki.Wybiera tryb ADF (jedno/dwustronny)Wybiera jasnośćWybiera zakres kolorów, "Główny" ma wpÅ‚yw na wszystkie kolory.Wybiera dropoutWybór rodzaju filmu, np. negatywów lub slajdówWybiera poprawionÄ… krzywÄ… przejÅ›ciaUstawia sposób korekcji gamma.Wybiera wartość korekcji gamma z listy zdefiniowanych urzÄ…dzeÅ„ lub tabeli użytkownika, która może być zaÅ‚adowana do skaneraWybór półcieniWybór rodzaju negatywuWybiera numer ramki do skanowaniaUstawia tryb skanowania, np. tryb kreski, skala szaroÅ›ci lub kolorowyWybierz źródÅ‚o skanowania (np. podajnik).Decyduje o tym jaki poziom jasnoÅ›ci błękitu ma być uznawany za "czarny".Decyduje o tym jaki poziom jasnoÅ›ci zielonego ma być uznawany jako czysty zielony.Decyduje o tym jaki poziom jasnoÅ›ci błękitu ma być uznawany za "biaÅ‚y".Decyduje o tym jaki poziom jasnoÅ›ci zieleni ma być uznawany za "czarny".Decyduje o tym jaki poziom jasnoÅ›ci niebieskiego ma być uznawany jako czysty niebieski.Decyduje o tym jaki poziom jasnoÅ›ci zieleni ma być uznawany za "biaÅ‚y".Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za "czarny".Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za "biaÅ‚y".Decyduje o tym jaki poziom jasnoÅ›ci czerwieni ma być uznawany za "czarny".Decyduje o tym jaki poziom jasnoÅ›ci czerwonego ma być uznawany jako czysty czerwony.Decyduje o tym jaki poziom jasnoÅ›ci czerwieni ma być uznawany za "biaÅ‚y".Ustawia czy uzyskany obrazek powinien być stonowany (ditherowany).Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za "50% niebieskiego"Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za "50% szarego"Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za "50% zielonego"Decyduje o tym jaki poziom jasnoÅ›ci ma być uznawany za "50% czerwonego"Wybiera który kolor skanowania jest używany w trybie odcieni szaroÅ›ci (domyÅ›lnie: zielony).AutodiagnostykaCzujnikiPrzywróć domyÅ›lne wartoÅ›ci dla ustawieÅ„ ulepszania (jasnoÅ›ci i kontrastu).Ustaw domyÅ›lne wartoÅ›ci ustawieÅ„ ulepszaniaUstawienie trybu kontroli gÄ™stoÅ›ciUstawia czas ekspozycjiUstaw gÄ™stość lampyUstaw wartość wyostrzania.RÄ™czne ustawianie pozycji ostroÅ›ci optyki (domyÅ›lnie: 128).Ustaw kolejność ramekUstaw kolejność ramek w kolorowym trybie trójprzebiegowymUstaw matrycÄ™ kolorów skanera.Czas (w minutach), po którym lampa jest wyłączana.Ustaw rodzaj noÅ›nika.Ustawia UTA jako włączone lub wyłączoneUstawia wzmocnienie kanaÅ‚u błękituUstawienie offsetu kanaÅ‚u błękituUstawia wzmocnienie kanaÅ‚u szaroÅ›ciUstawienie offsetu kanaÅ‚u szaroÅ›ciUstawia wzmocnienie kanaÅ‚u zieleniUstawienie offsetu kanaÅ‚u zieleniUstawia lapÄ™ jako włączonÄ… lub wyłączonÄ…Ustawia wzmocnienie kanaÅ‚u czerwieniUstawienie offsetu kanaÅ‚u czerwieniUstawia balans kolorów na wartoÅ›ci podane przez oprogramowania skaneraUstawia tablicÄ™ korekcji koloru dla wybranego urzÄ…dzenia wyjÅ›ciowego.Ustawia tryb podajnikaUstawia skupienie (ostrość) na szybÄ™ lub 2.5mm powyżej szybyUstawia wartość gamma dla wszystkich kanałówUstawia poziomÄ… rozdzielczość skanowanego obrazka.Ustawia emfazÄ™ obrazkaUstawia rozdzielczość skanowanego obrazka.Ustawia rozmiar wzorca tonowania (ditheringu) używanego podczas skanowania tonowanych obrazków.Ustawia pionowÄ… rozdzielczość skanowanego obrazka.Ustaw wzmocnienie i offset dla skanowania automatycznego. Jeżeli ta opcja jest zablokowana, wówczas dostÄ™pne sÄ… opcje rÄ™cznego ustawiania parametrów analogowych. Ta opcja jest odblokowana domyÅ›lnie. Opcja tylko do testów.CieÅ„CieÅ„ dla niebieskiegoCieÅ„ dla zielonegoCieÅ„ dla czerwonegoCienie, półtony, Å›wiatÅ‚a, czas ekspozycjiWyostrzanieOstrośćPrzesuÅ„ błękit do zieleniPrzesuÅ„ błękit do czerwieniPrzesuÅ„ zieleÅ„ do błękituPrzesuÅ„ zieleÅ„ do czerwieniPrzesuÅ„ czerwieÅ„ do błękituPrzesuÅ„ czerwieÅ„ do zieleniKrótka lista rozdzielczoÅ›ciPokazuje nazwy ukÅ‚adów (chipsetu) użytych w urzÄ…dzeniu.Pokazuje ID chipsetuPokazuje liczbÄ™ wykonanych skanowaÅ„Wyłącz lampÄ™Wyłącz lampÄ™ skanera.JednostronnySymuluje skaner rÄ™czny. Skanery rÄ™czne zwykle nie znajÄ… wysokoÅ›ci obrazka. Zamiast tego zwracajÄ… wysokość -1. Ustawienie tej opcji pozwala sprawdzić czy frontend obsÅ‚uguje to poprawnie. Ta opcja również włącza szerokość ustalonÄ… 11 cm.Symuluje skaner rÄ™czny. Skanery rÄ™czne zwykle nie znajÄ… wysokoÅ›ci obrazka. Zamiast tego zwracajÄ… wysokość -1. Ustawienie tej opcji pozwala sprawdzić czy frontend obsÅ‚uguje to poprawnie.Symuluje skaner trójprzebiegowy zwracajÄ…c trzy oddzielne ramki: zielonÄ…, potem niebieskÄ… a na koÅ„cu czerwonÄ….Symuluje skaner trójprzebiegowy. W trybie kolorowym przesyÅ‚ane sÄ… trzy ramki.Rozmiar limitu odczytuPomiÅ„ proces rozgrzewaniaSlajdSlajdyPowolnyWolniejszyNajwolniejszyWygÅ‚adzanieWygÅ‚adzanieCaÅ‚kowicie czarnyCaÅ‚kowicie biaÅ‚yWybór źródÅ‚aOpecje źródÅ‚a, trybu i rozdzielczoÅ›ciOpcje SpecjalneOpcje dodatkoweOkreÅ›la wysokość obiektu.OkreÅ›la szerokość obiektu. Wymagane do automatycznego centrowania skanowania.Przyspieszenie czujnikaStandardoweRozpocznij proces kalibracji.Rozpocznij kalibracjÄ™ przy użyciu specjalnej kartkiSymulacja kodu statusuStopOpcje testowe typu ciÄ…g znakowySukcesZamieÅ„ czarny z biaÅ‚ymWłączenie/wyłączenie moduÅ‚u do skanowania przezroczy (FAU)Włącza lub wyłącza lampÄ™.TMA - negatywyTMA - slajdyTechnologia Uwydatniania Tekstu(maksymalna) ilość danych transmitowanych z każdym wywoÅ‚aniem sane_read().Nazwa pliku, który ma zostać zaÅ‚adowany.Lampa zostanie wyłączona po podanym czasie (w minutach). Wartość 0 oznacza, że lampa nie bÄ™dzie wyłączana.Liczba pikseli które sÄ… tracone przy koÅ„cu każdej linii.Poziom nasycenia ustawia ilość "wykwitu" który ukazuje siÄ™, kiedy pobieramy obraz z kamery. WiÄ™ksze wartoÅ›ci powodujÄ… wiÄ™kszy wykwit.Skaner wymaga kalibracji dla obecnych ustawieÅ„Drukarki termiczneTo jest bardzo dÅ‚uga trzecia pozycja. Być może frontend ma jakiÅ› pomysÅ‚ jak jÄ… wyÅ›wietlićOpcja ta odzwierciedla stan przycisku przedniego panelu skaneraOpcja ta odzwierciedla stan przycisku skanera.Opcja ta odzwierciedla stan przycisków skanera.Ta opcja wyłącza lampÄ™ głównÄ… skanera podczas używania przystawki do materiałów przezroczystychSymulacja trójprzebiegowaSymulacja skanera trójprzebiegowegoPrógKrzywa progowaWartość progowa dla trybu kreskiWłącz / wyłącz lampÄ™ głównÄ… skaneraWłącza bÄ…dź wyłącza lampÄ™ głównÄ… skaneraOd góry do doÅ‚uLewaLewa krawÄ™dź skanowanego obszaru (górny lewy x).GórnaGórna krawÄ™dź skanowanego obszaru (górny lewy y).MateriaÅ‚y fotograficzneModuÅ‚ do skanowania negatywówModuÅ‚ do skanowania przezroczyWspółczynnik przezroczystoÅ›ciModuÅ‚ do skanowania przezroczyWyłącz lampÄ™Wyłącz lampÄ™ przy wyjÅ›ciu z programuWyłącza lampÄ™ skaneraWłącza lampÄ™ skaneraWyłącza lampÄ™ natychmiast.Włącz UTANieznanyWysuÅ„WysuÅ„ Dokument.WysuÅ„ noÅ›nik po skanowaniuWysuwa noÅ›nik po skanowaniu.Uaktualnij stan przyciskuAktualizuj informacjeAktualizuj opcjeAktualizuj opcje.Uaktualnia informacje o urzÄ…dzeniuUżyj pozycji skupienia uchwytu 0mm zamiast 0.6mmUżyj SkÅ‚adania ObrazkówUżyj wewnÄ™trznie głębi wiÄ™kszej niż osiem bitów, lecz na wyjÅ›ciu daj równe osiem.Użyj tablicÄ™ kolorów użytkownikaUżyj soczewek które podwajajÄ… rozdzielczość optycznÄ…Używaj nie blokujÄ…cego IOUżyj nie blokujÄ…cego IO dla sane_read jeżeli jest to wspierane przez frontend.Użycie tylko rozdzielczoÅ›ci sprzÄ™towychUżyj takiej samej wartoÅ›ci dla wszystkich kolorówUżyj tych samych wartoÅ›ci dla rozdzielczoÅ›ci w osi X i Y (poziomie i pionie)Używaj przystawki lightlid-35mmZdefiniowane przez użytkownikaZdefiniowane przez użytkownika (Gamma=1.0)Zdefiniowane przez użytkownika (Gamma=1.8)Profil CCT zdefiniowany przez użytkownikaPionowyPionowy pogrubionyCzekaj na PrzyciskCzekaj na przyciskCzekaj ze skanowaniem na naciÅ›niÄ™cie przycisku na przednim panelu.Oczekiwanie na naciÅ›niÄ™cie przycisku przed skanowaniemRozgrzewaj dopóki jasność lampy bÄ™dzie staÅ‚a, zamiast przyjmować staÅ‚y czas 40 sekund.Rozgrzewaj dopóki jasność lampy bÄ™dzie staÅ‚a, zamiast przyjmować staÅ‚y czas 60 sekund.Rozgrzej lampÄ™Rozgrzej lampÄ™ przed skanowaniemProces rozgrzewania bÄ™dzie pominiÄ™tyCzas rozgrzewaniaCzas rozgrzewania w sekundachKiedy jest włączone, proces skanowania nie zacznie siÄ™ natychmiast. Aby kontynuować, należy nacisnąć przycisk "SCAN" (dla MP150) lub przycisk "COLOR" (dla innych modeli). Aby anulować, należy nacisnąć przycisk "GRAY".W trybie szaroÅ›ci lub kreski ta opcja wybiera używany kolor.Przy wysokich rozdzielczoÅ›ciach kiedy rozdzielczość pozioma jest mniejsza niż rozdzielczość pionowa, ta opcja wyłącza interpolacjÄ™ poziomÄ….BielPoziom bieliPoziom bieli dla niebieskiegoPoziom bieli dla zielonegoPoziom bieli dla czerwonegoKorekcja cieniowania bieli bÄ™dzie wyłączonaRozdzielczość XXPASkala szaroÅ›ci XPAXPA RGBRozdzielczość YPowiÄ™kszeniebłąd sekwencji poleceÅ„skaner filmówskaner pÅ‚askibłąd kontroli sprzÄ™tuotrzymano komunikat błędu wykryty przez inicjatorbłędny komunikat bitowy IDENTIFYbłędny kod operacjibłędne pole w CDBbłędne pole w liÅ›cie parametrówbłędny komunikatawaria lampylampa nie ustabilizowanabrak noÅ›nikabrak dodatkowej informacji o stanieprzesuniÄ™cie XprzesuniÄ™cie Yopcja nie podłączonaparametr zmieniony przez inny inicjatorbłąd dÅ‚ugoÅ›ci listy parametrówreset po włączeniu zasilania / reset szynyniepowodzenie ponownego wyboruparametr zaokrÄ…glonybłąd pozycjonowania gÅ‚owicy skaneraskaner arkuszybłąd przekroczenia czasupodano zbyt dużo okienawaria lampy do skanowania przezroczybłąd pozycjonowania gÅ‚owicy do skanowania przezroczybłąd cieniowania moduÅ‚u do skanowania przezroczynieznanynieobsÅ‚ugiwany LUNkamera internetowasane-backends-1.0.27/po/quot.sed0000664000175000017500000000023112775312262013330 00000000000000s/"\([^"]*\)"/“\1â€/g s/`\([^`']*\)'/‘\1’/g s/ '\([^`']*\)' / ‘\1’ /g s/ '\([^`']*\)'$/ ‘\1’/g s/^'\([^`']*\)' /‘\1’ /g s/“â€/""/g sane-backends-1.0.27/po/en@boldquot.po0000664000175000017500000047056713110600535014471 00000000000000# English translations for sane-backends package. # Copyright (C) 2017 The SANE developers # This file is distributed under the same license as the sane-backends package. # Automatically generated, 2017. # # All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # # This catalog furthermore displays the text between the quotation marks in # bold face, assuming the VT100/XTerm escape sequences. # msgid "" msgstr "" "Project-Id-Version: sane-backends 1.0.27\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2017-05-22 11:18-0400\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: en@boldquot\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Number of options" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Standard" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometry" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Enhancement" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Advanced" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Sensors" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Preview" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Force monochrome preview" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bit depth" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Scan mode" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Scan speed" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Scan source" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Force backtracking" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Top-left x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Top-left y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Bottom-right x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Bottom-right y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Scan resolution" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-resolution" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-resolution" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Page width" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Page height" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Use custom gamma table" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Image intensity" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Red intensity" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Green intensity" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Blue intensity" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Brightness" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Grain size" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Halftoning" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Black level" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "White level" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "White level for red" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "White level for green" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "White level for blue" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Shadow" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Shadow for red" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Shadow for green" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Shadow for blue" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Highlight" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Highlight for red" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Highlight for green" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Highlight for blue" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Hue" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Saturation" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Filename" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Halftone pattern size" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Halftone pattern" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Bind X and Y resolution" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negative" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Quality calibration" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Double Optical Resolution" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Bind RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Threshold" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analog gamma correction" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analog gamma red" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analog gamma green" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analog gamma blue" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Bind analog gamma" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Warmup lamp" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Cal. exposure-time" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Cal. exposure-time for red" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Cal. exposure-time for green" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Cal. exposure-time for blue" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Scan exposure-time" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Scan exposure-time for red" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Scan exposure-time for green" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Scan exposure-time for blue" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Set exposure-time" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Cal. lamp density" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Scan lamp density" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Set lamp density" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lamp off at exit" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Read-only option that specifies how many options a specific devices " "supports." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Source, mode and resolution options" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Scan area and media size options" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Image modification options" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Hardware specific options" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Scanner sensors and buttons" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Request a preview-quality scan." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Number of bits per sample, typical values are 1 for “line-art†and " "8 for multibit scans." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Selects the scan mode (e.g., lineart, monochrome, or color)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Determines the speed at which the scan proceeds." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Selects the scan source (such as a document-feeder)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Controls whether backtracking is forced." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Top-left x position of scan area." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Top-left y position of scan area." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Bottom-right x position of scan area." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Bottom-right y position of scan area." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Sets the resolution of the scanned image." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Sets the horizontal resolution of the scanned image." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Sets the vertical resolution of the scanned image." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Specifies the height of the media." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Determines whether a builtin or a custom gamma-table should be used." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Gamma-correction table for the red band." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Gamma-correction table for the green band." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Gamma-correction table for the blue band." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Controls the brightness of the acquired image." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Controls the contrast of the acquired image." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Selects the “graininess†of the acquired image. Smaller values " "result in sharper images." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Selects whether the acquired image should be halftoned (dithered)." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "Selects what radiance level should be considered “blackâ€." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Selects what radiance level should be considered “whiteâ€." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Selects what red radiance level should be considered “whiteâ€." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Selects what green radiance level should be considered “whiteâ€." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Selects what blue radiance level should be considered “whiteâ€." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Selects what red radiance level should be considered “blackâ€." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Selects what green radiance level should be considered “blackâ€." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Selects what blue radiance level should be considered “blackâ€." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Selects what red radiance level should be considered “full redâ€." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Selects what green radiance level should be considered “full " "greenâ€." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Selects what blue radiance level should be considered “full blueâ€." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Controls the “hue†(blue-level) of the acquired image." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "The saturation level controls the amount of “blooming†that occurs " "when acquiring an image with a camera. Larger values cause more blooming." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "The filename of the image to be loaded." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Defines the halftoning (dithering) pattern for scanning halftoned images." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Use same values for X and Y resolution" #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Swap black and white" #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Do a quality white-calibration" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Use lens that doubles optical resolution" #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "In RGB-mode use same values for each color" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Select minimum-brightness to get a white point" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analog gamma-correction" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analog gamma-correction for red" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analog gamma-correction for green" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analog gamma-correction for blue" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Warmup lamp before scanning" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Define exposure-time for calibration" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Define exposure-time for red calibration" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "Define exposure-time for green calibration" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "Define exposure-time for blue calibration" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Define exposure-time for scan" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Define exposure-time for red scan" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Define exposure-time for green scan" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Define exposure-time for blue scan" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Enable selection of exposure-time" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Define lamp density for calibration" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Define lamp density for scan" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Enable selection of lamp density" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Turn off lamp when program exits" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Scan button" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "Email button" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Fax button" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Copy button" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "PDF button" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Cancel button" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Page loaded" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Cover open" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Color" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Color Lineart" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Color Halftone" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Gray" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Halftone" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Lineart" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "Success" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Operation not supported" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "Operation was cancelled" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "Device busy" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Invalid argument" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "End of file reached" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Document feeder jammed" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "Document feeder out of documents" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "Scanner cover is open" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Error during device I/O" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Out of memory" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "Access to resource has been denied" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "Lamp not ready, please retry" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "Scanner mechanism locked for transport" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Defaults" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Set default values for enhancement controls." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Calibration" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Calibrate before next scan" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Only perform shading-correction" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Button state" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Number of the frame to scan" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Selects the number of the frame to scan" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Duplex scan" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "Duplex scan provide a scan of the front and back side of the document" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Calibrate Scanner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Force scanner calibration before scan" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Grayscale scan" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Do a grayscale rather than color scan" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analog Gain" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Increase or decrease the analog gain of the CCD array" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gamma Correction" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Selects the gamma corrected transfer curve" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Raw" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Fine color" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "No transparency correction" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Correction according to film type" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Correction according to transparency ratio" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negatives" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Slides" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatic" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Normal speed" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 normal speed" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 normal speed" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "rounded parameter" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "unknown" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "ADF jam" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "ADF cover open" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "lamp failure" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "scan head positioning error" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "CPU check error" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "RAM check error" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "ROM check error" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "hardware check error" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "transparency unit lamp failure" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "transparency unit scan head positioning failure" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "parameter list length error" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "invalid command operation code" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "invalid field in CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "unsupported LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "invalid field in parameter list" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "command sequence error" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "too many windows specified" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "medium not present" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "invalid bit IDENTIFY message" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "option not connect" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "power on reset / bus device reset" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parameter changed by another initiator" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "no additional sense information" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "reselect failure" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "SCSI parity error" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "initiator detected error message received" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "invalid message error" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "timeout error" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "transparency unit shading error" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lamp not stabilized" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "film scanner" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "flatbed scanner" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Film type" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Selects the film type, i.e. negatives or slides" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Negative film type" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Selects the negative film type" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Hardware resolution" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Use only hardware resolutions" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Focus" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Auto focus" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Enable/disable auto focus" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Auto focus only once" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Do auto focus only once between ejects" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Manual focus position" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "Set the optical system's focus position by hand (default: 128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Scan margins" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Extra color adjustments" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Mirror image" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Mirror the image horizontally" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Auto exposure" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Enable/disable the auto exposure feature" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Calibration now" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Execute calibration *now*" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Self diagnosis" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Perform scanner self diagnosis" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Reset scanner" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Reset the scanner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Medium handling" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Eject film after each scan" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Automatically eject the film from the device after each scan" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Eject film before exit" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Automatically eject the film from the device before exiting the program" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Eject film now" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Eject the film *now*" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Document feeder extras" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Flatbed only" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "Disable auto document feeder and use flatbed only" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Transparency unit" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "Switch on/off the transparency unit (FAU, film adapter unit)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Negative film" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Positive or negative film" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Density control" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Set density control mode" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Transparency ratio" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Select film type" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Select the film type" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flatbed" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "ADF Front" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "ADF Back" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "ADF Duplex" #: backend/canon_dr.c:412 #, no-c-format msgid "Card Front" msgstr "Card Front" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "Card Back" #: backend/canon_dr.c:414 #, no-c-format msgid "Card Duplex" msgstr "Card Duplex" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Red" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Green" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Blue" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "Enhance Red" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "Enhance Green" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "Enhance Blue" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "None" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "JPEG" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "Software blank skip percentage" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "Request driver to discard pages with low percentage of dark pixels" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Simplex" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Duplex" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Transparency Unit" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatic Document Feeder" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Positive Film" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Negative Film" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Focus on glass" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Focus 2.5mm above glass" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Halftone A (Hard Tone)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Halftone B (Soft Tone)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Halftone C (Net Screen)" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Dither A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Dither B (4x4 Spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Dither C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Dither D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Text Enhanced Technology" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Download pattern A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Download pattern B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "No Correction" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "User defined" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Impact-dot printers" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Thermal printers" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Ink-jet printers" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT monitors" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Default" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "High density printing" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Low density printing" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "High contrast printing" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "User defined (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "User defined (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 portrait" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 landscape" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Max" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Scan Mode" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Selects the halftone." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Dropout" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Selects the dropout." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Selects the brightness." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Sharpness" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Color correction" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Sets the color correction table for the selected output device." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Color correction coefficients" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matrix multiplication of RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Shift green to red" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Shift green to blue" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Shift red to green" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Shift red to blue" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Shift blue to green" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Shift blue to red" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Controls green level" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Adds to red based on green level" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Adds to blue based on green level" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Adds to green based on red level" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Controls red level" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Adds to blue based on red level" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Adds to green based on blue level" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Adds to red based on blue level" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Controls blue level" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Mirror the image." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Fast preview" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Auto area segmentation" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Short resolution list" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Display short resolution list" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Zoom" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Defines the zoom factor the scanner will use" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Quick format" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Optional equipment" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Eject" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Eject the sheet in the ADF" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Auto eject" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Eject document after scanning" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "ADF Mode" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Selects the ADF mode (simplex/duplex)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Bay" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Select bay to scan" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Focus Position" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "" "Sets the focus position to either the glass or 2.5mm above the glass" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Wait for Button" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "Infrared" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "TPU8x10" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Positive Slide" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Negative Slide" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "Built in CCT profile" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "User defined CCT profile" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "On" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Off" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "DTC" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "SDTC" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Dither" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "Diffusion" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "White" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "Black" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Continue" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Stop" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10mm" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15mm" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20mm" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontal" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "Horizontal bold" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "Horizontal narrow" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertical" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "Vertical bold" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "Top to bottom" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "Bottom to top" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "Front" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "Back" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "Gamma function exponent" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "Changes intensity of midtones" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "RIF" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "Reverse image format" #: backend/fujitsu.c:3165 #, no-c-format msgid "Halftone type" msgstr "Halftone type" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "Control type of halftone filter" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "Control pattern of halftone filter" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "Outline" #: backend/fujitsu.c:3210 #, no-c-format msgid "Perform outline extraction" msgstr "Perform outline extraction" #: backend/fujitsu.c:3221 #, no-c-format msgid "Emphasis" msgstr "Emphasis" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "Negative to smooth or positive to sharpen image" #: backend/fujitsu.c:3240 #, no-c-format msgid "Separation" msgstr "Separation" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "Enable automatic separation of image and text" #: backend/fujitsu.c:3252 #, no-c-format msgid "Mirroring" msgstr "Mirroring" #: backend/fujitsu.c:3253 #, no-c-format msgid "Reflect output image horizontally" msgstr "Reflect output image horizontally" #: backend/fujitsu.c:3270 #, no-c-format msgid "White level follower" msgstr "White level follower" #: backend/fujitsu.c:3271 #, no-c-format msgid "Control white level follower" msgstr "Control white level follower" #: backend/fujitsu.c:3289 #, no-c-format msgid "BP filter" msgstr "BP filter" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "Improves quality of high resolution ball-point pen text" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Smoothing" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "Enable smoothing for improved OCR" #: backend/fujitsu.c:3323 #, no-c-format msgid "Gamma curve" msgstr "Gamma curve" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "Gamma curve, from light to dark, but upper two may not work" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "Threshold curve" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" "Threshold curve, from light to dark, but upper two may not be linear" #: backend/fujitsu.c:3369 #, no-c-format msgid "Threshold white" msgstr "Threshold white" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "Set pixels equal to threshold to white instead of black" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, no-c-format msgid "Noise removal" msgstr "Noise removal" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "Matrix 5x5" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "Remove 5 pixel square noise" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "Matrix 4x4" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "Remove 4 pixel square noise" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "Matrix 3x3" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "Remove 3 pixel square noise" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "Matrix 2x2" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "Remove 2 pixel square noise" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "Variance" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "Set SDTC variance rate (sensitivity), 0 equals 127" #: backend/fujitsu.c:3508 #, no-c-format msgid "Auto width detection" msgstr "Auto width detection" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "Scanner detects paper sides. May reduce scanning speed." #: backend/fujitsu.c:3526 #, no-c-format msgid "Auto length detection" msgstr "Auto length detection" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "Scanner detects paper lower edge. May confuse some frontends." #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "Compression" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "Enable compressed data. May crash your front-end program" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "Compression argument" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "DF action" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "Action following double feed error" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "DF skew" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "Enable double feed error due to skew" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "DF thickness" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "Enable double feed error due to paper thickness" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "DF length" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "Enable double feed error due to paper length" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "DF length difference" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "Difference in page length to trigger double feed error" #: backend/fujitsu.c:3708 #, no-c-format msgid "DF recovery mode" msgstr "DF recovery mode" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "Request scanner to reverse feed on paper jam" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "Paper protection" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "Request scanner to predict jams in the ADF" #: backend/fujitsu.c:3748 #, no-c-format msgid "Advanced paper protection" msgstr "Advanced paper protection" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "Request scanner to predict jams in the ADF using improved sensors" #: backend/fujitsu.c:3768 #, no-c-format msgid "Staple detection" msgstr "Staple detection" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "Request scanner to detect jams in the ADF caused by staples" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "Background color" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" "Set color of background for scans. May conflict with overscan option" #: backend/fujitsu.c:3809 #, no-c-format msgid "Dropout color" msgstr "Dropout color" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" #: backend/fujitsu.c:3833 #, no-c-format msgid "Buffer mode" msgstr "Buffer mode" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" "Request scanner to read pages quickly from ADF into internal memory" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "Prepick" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "Request scanner to grab next page from ADF" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "Overscan" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "Sleep timer" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" "Time in minutes until the internal power supply switches to sleep mode" #: backend/fujitsu.c:3911 #, no-c-format msgid "Off timer" msgstr "Off timer" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." #: backend/fujitsu.c:3930 #, no-c-format msgid "Duplex offset" msgstr "Duplex offset" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "Adjust front/back offset" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Green offset" #: backend/fujitsu.c:3949 #, no-c-format msgid "Adjust green/red offset" msgstr "Adjust green/red offset" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Blue offset" #: backend/fujitsu.c:3967 #, no-c-format msgid "Adjust blue/red offset" msgstr "Adjust blue/red offset" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "Low Memory" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option ‘side’ can be used to determine correct image. This option " "should only be used with custom front-end software." #: backend/fujitsu.c:3996 #, no-c-format msgid "Duplex side" msgstr "Duplex side" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "Hardware deskew and crop" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "Request scanner to rotate and crop pages digitally." #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "Software deskew" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "Request driver to rotate skewed pages digitally." #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "Software despeckle diameter" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "Maximum diameter of lone dots to remove from scan." #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "Software crop" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "Request driver to remove border from pages digitally." #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "Halt on Cancel" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" "Request driver to halt the paper feed instead of eject during a cancel." #: backend/fujitsu.c:4095 #, no-c-format msgid "Endorser Options" msgstr "Endorser Options" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "Controls for endorser unit" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "Endorser" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "Enable endorser unit" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "Endorser bits" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "Determines maximum endorser counter value." #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "Endorser value" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "Initial endorser counter value." #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "Endorser step" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "Change endorser counter value by this much for each page." #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "Endorser Y" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "Endorser print offset from top of paper." #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "Endorser font" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "Endorser printing font." #: backend/fujitsu.c:4253 #, no-c-format msgid "Endorser direction" msgstr "Endorser direction" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "Endorser printing direction." #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "Endorser side" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "Endorser printing side, requires hardware support to change" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "Endorser string" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "Top edge" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "Paper is pulled partly into adf" #: backend/fujitsu.c:4344 #, no-c-format msgid "A3 paper" msgstr "A3 paper" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "A3 paper detected" #: backend/fujitsu.c:4356 #, no-c-format msgid "B4 paper" msgstr "B4 paper" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "B4 paper detected" #: backend/fujitsu.c:4368 #, no-c-format msgid "A4 paper" msgstr "A4 paper" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "A4 paper detected" #: backend/fujitsu.c:4380 #, no-c-format msgid "B5 paper" msgstr "B5 paper" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "B5 paper detected" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "OMR or DF" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "OMR or double feed detected" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "Power saving" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "Scanner in power saving mode" #: backend/fujitsu.c:4452 #, no-c-format msgid "Manual feed" msgstr "Manual feed" #: backend/fujitsu.c:4453 #, no-c-format msgid "Manual feed selected" msgstr "Manual feed selected" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "Function" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "Function character on screen" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "Ink low" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "Imprinter ink running low" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "Double feed" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "Double feed detected" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "Error code" #: backend/fujitsu.c:4513 #, no-c-format msgid "Hardware error code" msgstr "Hardware error code" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "Skew angle" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "Requires black background for scanning" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "Ink remaining" #: backend/fujitsu.c:4537 #, no-c-format msgid "Imprinter ink level" msgstr "Imprinter ink level" #: backend/fujitsu.c:4548 #, no-c-format msgid "Density" msgstr "Density" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "Density dial" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, no-c-format msgid "Duplex switch" msgstr "Duplex switch" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "Request backend to remove border from pages digitally" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "Request driver to discard pages with low numbers of dark pixels" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "Software derotate" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "Request driver to detect and correct 90 degree image rotation" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extras" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "Dynamic threshold curve, from light to dark, normally 50-65" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "Disable dynamic lineart" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Disable interpolation" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." #: backend/genesys.c:5872 #, no-c-format msgid "Color filter" msgstr "Color filter" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "When using gray or lineart this option selects the used color." #: backend/genesys.c:5901 #, no-c-format msgid "Calibration file" msgstr "Calibration file" #: backend/genesys.c:5902 #, no-c-format msgid "Specify the calibration file to use" msgstr "Specify the calibration file to use" #: backend/genesys.c:5919 #, no-c-format msgid "Calibration cache expiration time" msgstr "Calibration cache expiration time" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Lamp off time" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." #: backend/genesys.c:5943 #, no-c-format msgid "Lamp off during scan" msgstr "Lamp off during scan" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "The lamp will be turned off during scan. " #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "File button" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "OCR button" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Power button" #: backend/genesys.c:6053 backend/genesys.c:6054 #, no-c-format msgid "Extra button" msgstr "Extra button" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "Need calibration" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "The scanner needs calibration for the current settings" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Buttons" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Calibrate" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Start calibration using special sheet" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Clear calibration" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Clear calibration cache" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Transparency Adapter" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Gray mode color" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "Selects which scan color is used gray mode (default: green)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Debugging Options" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatic warmup" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Full scan" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Coarse calibration" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Coarse calibration for first scan only" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Backtrack lines" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gamma value" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Sets the gamma value of all channels." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Geometry Group" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Scan Mode Group" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Slide" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Scanner model" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "Allows one to test device behaviour with other supported models" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Image colours will be inverted" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Disable gamma correction" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "Gamma correction will be disabled" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Disable white shading correction" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "White shading correction will be disabled" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Skip warmup process" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "Warmup process will be disabled" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Force real depth" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Emulate Grayscale" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Save debugging images" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "If enabled, some images involved in scanner processing are saved to " "analyze them." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Reset chipset" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Resets chipset data" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Information" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Chipset name" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Shows chipset name used in device." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Unknown" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "Chipset ID" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Shows the chipset ID" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Scan counter" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Shows the number of scans made by scanner" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Update information" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Updates information about device" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "This option reflects a front panel scanner button" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Image" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Miscellaneous" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "offset X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "Hardware internal X position of the scanning area." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "offset Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Hardware internal Y position of the scanning area." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Lamp status" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Switches the lamp on or off." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Calibrates for black and white level." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMA Slides" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMA Negatives" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Color (48 bits)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Extend lamp timeout" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Extends lamp timeout (from 15 minutes to 1 hour)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Wait for button" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Waits for button before scanning" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Advanced Options" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Coarse" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fine" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Custom" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Auto" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Pass-through" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Gray" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA Gray" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Slow" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Fast" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Extra Fast" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-pixel" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-pixel" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-pixel" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Print" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Film-strip" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Conditional" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Experiment" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Sharpening" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Set sharpening value." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Auto Threshold" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "Enable automatic determination of threshold for line-art scans." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Select smoothing filter." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Unload media after scan" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Unloads the media after a scan." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Change document" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Change Document." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Unload" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Unload Document." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Start calibration process." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Media" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Set type of media." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Exposure time" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and “Negative†for " "negative film. For dark (underexposed) images you can increase this " "value." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Color Matrix" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Set the scanners color matrix." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Custom color matrix." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Mono Color Matrix" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Custom color matrix for grayscale scans." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Mirror horizontal" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Mirror image horizontally." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Mirror vertical" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Mirror image vertically." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Update options" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Update options." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8 bit output" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Use bit depth greater eight internally, but output only eight bits." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Front button wait" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Wait to scan for front-panel button push." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Shut off lamp" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Shut off scanner lamp." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Paper size" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatic separation" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, no-c-format msgid "Landscape" msgstr "Landscape" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "Inverse Image" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "Long paper mode" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "Length control mode" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "Manual feed mode" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, no-c-format msgid "Manual feed timeout" msgstr "Manual feed timeout" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "Double feed detection" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Enable Duplex (Dual-Sided) Scanning" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Physical size of the paper in the ADF" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "bw" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "halftone" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "gray" #: backend/kvs1025_opt.c:42 #, no-c-format msgid "color" msgstr "color" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "adf" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "fb" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "single" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "continuous" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "off" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "wait_doc" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "wait_key" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "user_def" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "business_card" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "Check" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "A5" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "A6" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "B5" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "B6" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "Legal" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "bayer_64" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "bayer_16" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "halftone_32" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "halftone_64" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "diffusion" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, no-c-format msgid "normal" msgstr "normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, no-c-format msgid "light" msgstr "light" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "dark" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, no-c-format msgid "From scanner" msgstr "From scanner" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "From paper" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, no-c-format msgid "default" msgstr "default" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "smooth" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "none" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, no-c-format msgid "low" msgstr "low" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, no-c-format msgid "medium" msgstr "medium" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "high" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "crt" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "linier" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, no-c-format msgid "red" msgstr "red" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, no-c-format msgid "green" msgstr "green" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "blue" #: backend/kvs1025_opt.c:562 #, no-c-format msgid "Sets the scan source" msgstr "Sets the scan source" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Feeder mode" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Sets the feeding mode" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "Enable/Disable long paper mode" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "Enable/Disable length control mode" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, no-c-format msgid "Sets the manual feed mode" msgstr "Sets the manual feed mode" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Sets the manual feed timeout in seconds" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "Enable/Disable double feed detection" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "fit-to-page" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "Fit to page" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "Scanner shrinks image to fit scanned page" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "Set paper position : true for landscape, false for portrait" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatic threshold" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Noise reduction" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Reduce the isolated dot noise" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Image emphasis" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Sets the image emphasis" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, no-c-format msgid "Lamp color" msgstr "Lamp color" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Sets the lamp color (color dropout)" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "Inverse image in B/W or halftone mode" #: backend/kvs1025_opt.c:840 #, no-c-format msgid "Mirror image (left/right flip)" msgstr "Mirror image (left/right flip)" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "jpeg compression" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" "JPEG Image Compression with Q parameter, ‘0’ - no compression" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "Rotate image clockwise" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "Request driver to rotate pages by a fixed amount" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "Request driver to rotate skewed pages digitally" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "Maximum diameter of lone dots to remove from scan" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "Software automatic cropping" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "Request driver to remove border from pages digitally" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gamma correction" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "wait_doc_hopper_up" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "A3" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "Double letter 11x17 in" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "B4" #: backend/kvs40xx_opt.c:231 #, no-c-format msgid "High sensivity" msgstr "High sensivity" #: backend/kvs40xx_opt.c:232 #, no-c-format msgid "Low sensivity" msgstr "Low sensivity" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "err_diffusion" #: backend/kvs40xx_opt.c:249 #, no-c-format msgid "No detection" msgstr "No detection" #: backend/kvs40xx_opt.c:250 #, no-c-format msgid "Normal mode" msgstr "Normal mode" #: backend/kvs40xx_opt.c:251 #, no-c-format msgid "Enhanced mode" msgstr "Enhanced mode" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "Double feed detector sensitivity" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "Set the double feed detector sensitivity" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "Do not stop after double feed detection" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "Ignore left double feed sensor" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "Ignore center double feed sensor" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "Ignore right double feed sensor" #: backend/kvs40xx_opt.c:642 #, no-c-format msgid "Automatic threshold mode" msgstr "Automatic threshold mode" #: backend/kvs40xx_opt.c:643 #, no-c-format msgid "Sets the automatic threshold mode" msgstr "Sets the automatic threshold mode" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "Inverse image in B/W mode" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "JPEG compression" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "JPEG compression (yours application must be able to uncompress)" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "Detect stapled document" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "chroma of red" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "Set chroma of red" #: backend/kvs40xx_opt.c:787 #, no-c-format msgid "chroma of blue" msgstr "chroma of blue" #: backend/kvs40xx_opt.c:788 #, no-c-format msgid "Set chroma of blue" msgstr "Set chroma of blue" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "Skew adjustment" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "Stop scanner when a paper have been skewed" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "Scanner will be stop when a paper have been skewed" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "Crop actual image area" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "Scanner automatically detect image area and crop it" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "It is right and left reversing" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "Addition of space in top position" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "Addition of space in bottom position" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamond" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 Coarse Fatting" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 Fine Fatting" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Vertical Line" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Gain" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Color channels gain settings" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Gray gain" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Sets gray channel gain" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Red gain" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Sets red channel gain" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Green gain" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Sets green channel gain" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Blue gain" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Sets blue channel gain" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer Dither 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer Dither 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Halftone Dot 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Halftone Dot 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Error Diffusion" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Mode 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Mode 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Mode 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "From white stick" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Smooth" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Low" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Medium" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "High" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "One page" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "All pages" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "sheetfed scanner" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "Grayscale 4 bits" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "Grayscale 8 bits" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Shadow, midtone, highlight, exposure time" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Special options" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Color balance" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Disable backtracking" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "If checked the scanner does not perform backtracking" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Toggle lamp of flatbed" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Toggles the lamp of the flatbed" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Calibration by backend" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "If checked the color calibration before a scan is done by the backend" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Use the lightlid-35mm adapter" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "This option turns off the lamp of the flatbed during a scan" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Quality scan" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Highest quality but lower speed" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Fast scan" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Highest speed but lower quality" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatic adjustment of threshold" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Selects the gamma correction mode." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Bind gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Use same gamma values for all colour channels." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Scalar gamma" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Selects a value for scalar gamma correction." #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Scalar gamma red" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Selects a value for scalar gamma correction (red channel)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Scalar gamma green" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Selects a value for scalar gamma correction (green channel)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Scalar gamma blue" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Selects a value for scalar gamma correction (blue channel)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Channel" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Selects the colour band, “Master†means that all colours are " "affected." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Midtone" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "" "Selects which radiance level should be considered “50 % grayâ€." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Midtone for red" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "" "Selects which radiance level should be considered “50 % redâ€." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Midtone for green" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "" "Selects which radiance level should be considered “50 % greenâ€." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Midtone for blue" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "" "Selects which radiance level should be considered “50 % blueâ€." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Red balance" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Balance factor for red. A value of 100% means no correction." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Green balance" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Balance factor for green. A value of 100% means no correction." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Blue balance" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Balance factor for blue. A value of 100% means no correction." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Firmware balance" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Sets the color balance values to the firmware provided values." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Slowest" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Slower" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Faster" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Fastest" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 coarse" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fine" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 very fine" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normal" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 coarse" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fine" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 coarse" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normal" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fine" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 custom" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 custom" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 custom" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 custom" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 custom" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 custom" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Fast gray mode" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Scan in fast gray mode (lower quality)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Lamp off time (minutes)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Set the time (in minutes) after which the lamp is shut off." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Turn lamp off" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Turns the lamp off immediately." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Red brightness" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Controls the brightness of the red channel of the acquired image." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Green brightness" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "" "Controls the brightness of the green channel of the acquired image." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Blue brightness" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "Controls the brightness of the blue channel of the acquired image." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contrast red channel" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Controls the contrast of the red channel of the acquired image." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contrast green channel" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "Controls the contrast of the green channel of the acquired image." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contrast blue channel" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "Controls the contrast of the blue channel of the acquired image." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Color48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Color24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Gray16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Gray8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Reflective" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positive" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." #: backend/pixma.c:378 #, no-c-format msgid "Negative color" msgstr "Negative color" #: backend/pixma.c:383 #, no-c-format msgid "Negative gray" msgstr "Negative gray" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "48 bits color" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "16 bits gray" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Button-controlled scan" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "When enabled, scan process will not start immediately. To proceed, press " "“SCAN†button (for MP150) or “COLOR†button (for other " "models). To cancel, press “GRAY†button." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Update button state" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Button 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Button 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "Type of original to scan" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "Target operation type" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "ADF Waiting Time" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Transparency" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Device-Settings" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Lampswitch" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Manually switching the lamp(s)." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Lamp off during dark calibration" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Always switches lamp off when doing dark calibration." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Calibration data cache" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Enables or disables calibration data cache." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Performs calibration" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Speedup sensor" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Enables or disables speeding up sensor movement." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Warmup-time" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Warmup-time in seconds." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Lampoff-time" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Lampoff-time in seconds." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Analog frontend" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Red gain value of the AFE" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Red offset" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Red offset value of the AFE" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Green gain value of the AFE" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Green offset value of the AFE" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Blue gain value of the AFE" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Blue offset value of the AFE" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Red lamp off" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Defines red lamp off parameter" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Green lamp off" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Defines green lamp off parameter" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Blue lamp off" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Defines blue lamp off parameter" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "This option reflects the status of the scanner buttons." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Color36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Dithermap 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Dithermap 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Randomize" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Source Selection" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Image Enhancement" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Grayify" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Load the image as grayscale." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Three-Pass Simulation" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Hand-Scanner Simulation" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Set default values for enhancement controls (brightness & contrast)." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Read only test-option" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Let's see whether frontends can treat this right" #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Gamma Tables" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Status Code Simulation" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Do not force status code" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Do not force the backend to return a status code." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Return SANE_STATUS_EOF" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Return SANE_STATUS_JAMMED" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Return SANE_STATUS_NO_DOCS" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Return SANE_STATUS_COVER_OPEN" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Return SANE_STATUS_IO_ERROR" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Return SANE_STATUS_NO_MEM" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Return SANE_STATUS_ACCESS_DENIED" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "This option reflects the status of a scanner button." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lamp on" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Turn on scanner lamp" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lamp off" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Turn off scanner lamp" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Lamp timeout" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Minutes until lamp is turned off after scan" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Threshold value for lineart mode" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Document Feeder" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (inch)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (inch)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (inch)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Halftoning Unsupported" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "Frame number of media holder that should be scanned." #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "Use manual or automatic selection of focus point." #: backend/snapscan-options.c:117 #, no-c-format msgid "Focus point for scanning." msgstr "Focus point for scanning." #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Preview mode" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Predefined settings" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Provides standard scanning areas for photographs, printed pages and the " "like." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "Frame" #: backend/snapscan-options.c:885 #, no-c-format msgid "Frame to be scanned" msgstr "Frame to be scanned" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "Focus-mode" #: backend/snapscan-options.c:898 #, no-c-format msgid "Auto or manual focus" msgstr "Auto or manual focus" #: backend/snapscan-options.c:911 #, no-c-format msgid "Focus-point" msgstr "Focus-point" #: backend/snapscan-options.c:912 #, no-c-format msgid "Focus point" msgstr "Focus point" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Colour lines per read" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Greyscale lines per read" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "webcam" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Color RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Color RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Color RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Solid black" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Solid white" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Color pattern" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Grid" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "First entry" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Second entry" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Hand-scanner simulation" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Three-pass simulation" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Set the order of frames" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Set the order of frames in three-pass color mode." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "If Automatic Document Feeder is selected, the feeder will be " "‘empty’ after 10 scans." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Special Options" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Select the test picture" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Invert endianness" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Read limit" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Limit the amount of data transferred with each call to sane_read()." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Size of read-limit" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "The (maximum) amount of data transferred with each call to sane_read()." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Read delay" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Delay the transfer of data to the pipe." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Duration of read-delay" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "How long to wait after transferring each buffer of data through the pipe." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Return-value of sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Select the return-value of sane_read(). “Default†is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Loss of pixels per line" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "The number of pixels that are wasted at the end of each line." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Fuzzy parameters" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Use non-blocking IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "Use non-blocking IO for sane_read() if supported by the frontend." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Offer select file descriptor" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Enable test options" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Print options" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Print a list of all options." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Bool test options" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Bool soft select soft detect" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Bool hard select soft detect" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Bool hard select" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Bool soft detect" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Bool soft select soft detect emulated" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Bool soft select soft detect auto" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Int test options" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Int" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Int test option with no unit and no constraint set." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Int constraint range" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Int constraint word list" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "(3/6) Int test option with unit bits and constraint word list set." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Int array" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Int test option with unit mm and using an array without " "constraints." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Int array constraint range" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Int array constraint word list" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Fixed test options" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Fixed" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) Fixed test option with no unit and no constraint set." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Fixed constraint range" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Fixed constraint word list" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "(3/3) Fixed test option with no unit and constraint word list set." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "String test options" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) String" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) String test option without constraint." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) String constraint string list" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) String test option with string list constraint." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) String constraint long string list" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) String test option with string list constraint. Contains some more " "entries..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Button test options" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Button" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Button test option. Prints some text..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Color 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Use Image Composition" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "Bi-level black and white (lineart mode)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Dithered/halftone black & white (halftone mode)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Multi-level black & white (grayscale mode)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Multi-level RGB color (one pass color)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Ignore calibration" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Disable pre focus" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Do not calibrate focus" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Manual pre focus" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Fix focus position" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Lens calibration in doc position" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Calibrate lens focus in document position" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Holder focus position 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Use 0mm holder focus position instead of 0.6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Calibration mode" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Define calibration mode" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Sets lamp on/off" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA on" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Sets UTA on/off" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Offset" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Color channels offset settings" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Gray offset" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Sets gray channel offset" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Sets red channel offset" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Sets green channel offset" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Sets blue channel offset" sane-backends-1.0.27/po/de.po0000664000175000017500000047015013110600533012567 00000000000000# translation of sane-backends.po to # German translation for SANE backend options # Copyright (C) 2002-2005 SANE Project. # Burma Group Karlsruhe, Heiko Schaefer , 2002. # Gerhard Jaeger , 2002-2006, 2007. # Henning Meier-Geinitz , 2002-2005. # Michael Herder , 2002. # Oliver Rauch , 2002. # Oliver Schwartz , 2002, 2004. # Karsten Festag , 2002. # Burkhard Lück , 2009. # Rolf Bensch , 2012. msgid "" msgstr "" "Project-Id-Version: sane-backends\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2010-08-06 17:17+0100\n" "Last-Translator: Rolf Bensch \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 0.3\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Anzahl der Optionen" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Standard" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Scanbereich" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Farbverbesserung" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Erweitert" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Sensoren" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Vorschau" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Vorschauscan in grau" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bittiefe" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Scanmodus" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Scangeschwindigkeit" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Scanquelle" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Erzwinge Backtracking" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Links" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Oben" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Rechts" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Unten" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Scanauflösung" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-Auflösung" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-Auflösung" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Seitenbreite" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Seitenhöhe" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Verwende benutzerdefinierte Gammatabelle" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Bildintensität" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Intensität Rot" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Intensität Grün" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Intensität Blau" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Helligkeit" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Kontrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Korngröße" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Halbtonmodus" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Wert für Schwarz" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Weißwert" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Weißwert für Rot" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Weißwert für Grün" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Weißwert für Blau" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Schatten" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Schatten Rot" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Schatten Grün" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Schatten Blau" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Licht" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Licht Rot" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Licht Grün" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Licht Blau" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Farbton" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Sättigung" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Dateiname" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Größe der Halbton-Matrix" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Halbton-Matrix" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Verbinde X- und Y-Auflösung" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negativ" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Qualitäts-Weißabgleich" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Verdoppelte optische Auflösung" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Verbinde RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Schwellwert" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analoge Gammakorrektur" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analoger Gammawert Rot" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analoger Gammawert Grün" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analoger Gammawert Blau" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Verbinde analoge Gammawerte" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Lampe aufwärmen" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Beleuchtungszeit zum Kalibrieren" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Beleuchtungszeit zum Kalibrieren von Rot" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Beleuchtungszeit zum Kalibrieren von Grün" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Beleuchtungszeit zum Kalibrieren von Blau" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Beleuchtungszeit zum Scannen" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Beleuchtungszeit zum Scannen von Rot" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Beleuchtungszeit zum Scannen von Grün" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Beleuchtungszeit zum Scannen von Blau" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Definiere Beleuchtungszeit" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Lichtwert für Kalibrierung" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Lichtwert beim Scannen" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Definiere Lichtwert" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lampe beim Beenden ausschalten" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Nur-Lese-Option, die angibt, wieviele Optionen ein bestimmtes Gerät " "unterstützt." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Optionen für Zuführung, Modus und Auflösung" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Optionen für den Scanbereich und für Medienformate" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Optionen für Bildbearbeitung" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Hardware-spezifische Optionen" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Scanner-Sensoren und -Knöpfe" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Fordere einen Scan in Vorschauqualität an." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Legt fest, dass alle Vorschauscans im Graustufenmodus durchgeführt " "werden. Bei einem Three-Pass-Scanner wird dadurch nur ein Pass benötigt, " "bei einem Single-Pass-Scanner wird der Speicherverbrauch und die " "Scanzeit verringert." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Anzahl der Bits pro Farbwert, typische Werte sind 1 für Lineart- und 8 " "für Multibit-Scans" #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Wählt den Scanmodus aus (z.B. Strichzeichnung, Grau oder Farbe)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Legt die Scangeschwindigkeit fest." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Legt die Scanquelle fest (wie z.B. Dokumenteneinzug)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Legt fest, dass Backtracking verwendet wird." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Linke Kante des zu scannenden Bereichs." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Obere Kante des zu scannenden Bereichs." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Rechte Kante des zu scannenden Bereichs." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Untere Kante des zu scannenden Bereichs." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Legt die Auflösung des Bildes fest." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Bestimmt die horizontale Auflösung des Bildes." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Bestimmt die vertikale Auflösung des Bildes." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Legt die Breite des Mediums fest. Erforderlich für die automatische " "Zentrierung bei Einzelblatt-Scans." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Legt die Höhe der Medien fest." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Bestimmt ob die scannerinterne oder eine benutzerdefinierte Gammatabelle " "verwendet wird." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Gamma-Korrekturtabelle. Im Farbmodus wirkt sich diese Option auf die " "rote, grüne und blaue Farbkomponente aus. Es ist also eine Helligkeits-" "Gammatabelle." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Gamma-Korrekturtabelle für die rote Komponente." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Gamma-Korrekturtabelle für die grüne Komponente." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Gamma-Korrekturtabelle für die blaue Komponente." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Stellt die Helligkeit des Bildes ein." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Stellt den Kontrast des Bildes ein." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Legt die \"Körnigkeit\" des gescannten Bildes fest. Kleinere Werte " "ergeben schärfere Bilder." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Legt fest, ob das Bild im Halbtonmodus (Dithering) gescannt wird." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" "Bestimmt, welcher Helligkeitswert als Schwarz angesehen werden soll." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Bestimmt, welcher Helligkeitswert als Weiß angesehen werden soll." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Bestimmt, welcher Helligkeitswert der roten Komponente als \"Weiß\" " "angesehen werden soll." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Bestimmt, welcher Helligkeitswert der grünen Komponente als \"Weiß\" " "angesehen werden soll." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Bestimmt, welcher Helligkeitswert der blauen Komponente als \"Weiß\" " "angesehen werden soll." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Bestimmt, welcher Helligkeitswert der roten Komponente als Schwarz " "angesehen werden soll." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Bestimmt, welcher Helligkeitswert der grünen Komponente als Schwarz " "angesehen werden soll." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Bestimmt, welcher Helligkeitswert der blauen Komponente als Schwarz " "angesehen werden soll." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Bestimmt, welcher Helligkeitswert der roten Komponente als Weiß " "angesehen werden soll." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Bestimmt, welcher Helligkeitswert der grünen Komponente als Weiß " "angesehen werden soll." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Bestimmt, welcher Helligkeitswert der blauen Komponente als Weiß " "angesehen werden soll." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Legt den Farbwert (Blauwert) des gescannten Bildes fest." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "Der Sättigungsgrad steuert die Belichtung einesmit einer Kamera " "aufgenommenen Bildes. Höhere Werte sorgen für eine stärkere Belichtung." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "Der Dateiname des zu ladenden Bildes." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Legt die Größe der für den Scanvorgang verwendeten Halbtonmatrix fest." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "Definiert die für den Scanvorgang zu verwendende Halbton-Matrix." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Benutze die gleichen Auflösungen für X und Y." #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Invertiere die Farben, z.B. tausche Schwarz gegen Weiß." #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Führe einen Qualitätsweißabgleich durch." #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Benutze die Linse, mit der die optische Auflösung verdoppelt wird." #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Benutze die gleichen Wert für alle Farben im RGB Modus." #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "" "Wähle die minimale Helligkeit, die als Weiß betrachtet werden soll." #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analoge Gammakorrektur." #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analoge Gammakorrektur für Rot." #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analoge Gammakorrektur für Grün." #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analoge Gammakorrektur für Blau." #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Wärme die Lampe vor dem Scannen auf." #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Bestimmt die Beleuchtungszeit für die Kalibrierung." #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "" "Bestimmt die Beleuchtungszeit für die Kalibrierung der roten Komponente." #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "" "Bestimmt die Beleuchtungszeit für die Kalibrierung der grünen Komponente." #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "" "Bestimmt die Beleuchtungszeit für die Kalibrierung der blauen Komponente." #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Bestimmt die Beleuchtungszeit für den Scan." #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Bestimmt die Beleuchtungszeit für den Scan der roten Komponente." #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Bestimmt die Beleuchtungszeit für den Scan der grünen Komponente." #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Bestimmt die Beleuchtungszeit für den Scan der blauen Komponente." #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Ermögliche Einstellung der Beleuchtungszeiten." #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Definiere die Lichtwerte beim Kalibrieren." #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Definiere die Lichtwerte beim Scannen." #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Ermögliche Auswahl der Lichtwerte." #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Schalte Lampe beim Beenden des Programms aus" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Scanknopf" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "E-Mail-Knopf" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Fax-Knopf" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Kopieren-Knopf" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "PDF-Knopf" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Abbrechen-Knopf" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Seite geladen" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Abdeckung offen" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Farbe" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Farb-Strichzeichnung" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Farb-Halbton" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Graustufen" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Halbton" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Strichzeichnung" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "Erfolgreich" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Operation nicht unterstützt" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "Operation wurde abgebrochen" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "Gerät nicht bereit" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Ungültiges Argument" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "Ende der Datei ist erreicht" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Automatischer Dokumenteinzug blockiert" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "Automatischer Dokumenteinzug leer" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "Die Abdeckung des Scanners ist offen" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "\tCopy text \tFehler während der Datenübermittlung des Geräts" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Nicht genügend Speicher" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "Der Zugriff auf die Ressource wurde abgelehnt" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "Die Lampe ist nicht bereit, bitte wiederholen" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "Mechanik des Scanners für den Transport verriegelt" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Defaulteinstellungen" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Auf Voreinstellungen für Verbesserungen zurücksetzen." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibrierung" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Vor dem nächsten Scan kalibrieren" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Wenn diese Option eingeschaltet ist, wird vor dem nächsten Scan eine " "Kalibrierung durchgeführt. Ansonsten findet die Kalibrierung nur vor dem " "ersten Scan statt." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Nur Shading-Korrektur durchführen" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Ist diese Option eingeschaltet, dann wird während der Kalibrierung nur " "die Shading-Korrektur durchgeführt. Andere Kalibrierungswerte werden aus " "der Konfigurationsdatei oder aus den Voreinstellungen des Backends " "übernommen." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Schalter Status" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Nummer des zu scannenden Bildes" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Wählt die Nummer des zu scannenden Bildes aus" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Duplexscan" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "" "Duplex Scan ermöglicht das Scannen der Vorder- und Rückseite eines " "Dokuments." #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Scanner kalibrieren" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Erzwinge Scannerkalibrierung vor dem Scannen" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Graustufen-Scan" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Führe einen Graustufen-Scan statt eines Farb-Scans durch" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analoge Verstärkung" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "" "Vergrößere oder verkleinere die analoge Verstärkung des CCD-Sensors" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gammakorrektur" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Wählt die korrigierte Gammakurve aus." #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Rohdaten" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Keine Transparenzkorrektur" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Korrektur entsprechend des Filmtyps" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Korrektur entsprechend des Seitenverhältnisses" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negative" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Dias" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatik" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Normalgeschwindigkeit" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 Normalgeschwindigkeit" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 Normalgeschwindigkeit" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "Gerundete Parameter" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "unbekannt" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "Papierstau im automatischem Einzug" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "Abdeckung des automatischen Einzuges offen" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "Lampenfehler" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "Fehler beim Positionieren des Scannerkopfes" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "Fehler bei der CPU-Überprüfung" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "Fehler bei der Arbeitsspeicher-Überprüfung" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "Fehler bei der ROM-Überprüfung" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "Hardwareüberprüfungsfehler" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "Lampe der Durchlichteinheit defekt" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "Positionsfehler der Durchlichteinheit beim Scankopf" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "Falsche Länge bei der Parameterliste" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "Ungültiger Befehlsausführungs-Code" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "Ungültiges Feld in CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "LUN nicht unterstützt" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "Ungültiges Feld in der Parameterliste" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "Falsche Reihenfolge der Befehle" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "Zu viele Fenster angegeben" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "Kein Medium eingelegt" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "ungültiger Teil der IDENTIFY Nachricht" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "Option nicht verbunden" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "Netzschalter Reset / Bus-Gerät Reset" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "Parameter von einem anderen Initator geändert" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "keine zusätzliche Sinnesinformation" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "Wiederauswahlfehler" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "SCSI-Paritätsfehler" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "vom Initiator bemerkte Fehlermeldung empfangen" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "ungültige Fehlernachricht" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "Zeitüberschreitung" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "Durchlichtaufsatzabschattungsfehler" #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "Lampe nicht stabilisiert" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "Filmscanner" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "Flachbettscanner" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Filmtyp" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Auswahl des Film-Typs (z. B. Negativ oder Dia)" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Negativ Filmtyp" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Wählt den Typ des Negativfilms" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Hardwareauflösung" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Nur Hardwareauflösungen verwenden" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Fokus" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Automatischer Fokus" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Aktiviere/Deaktiviere automatischen Fokus\t\t" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Automatischen Fokus nur einmal aktivieren" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Auto-Fokus nur einmal zwischen den Auswürfen" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Manuelle Einstellung des Fokus" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" "Setzt die Fokusposition des optischen System von Hand (Standard: 128)." #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Scan Seitenrand" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Erweiterte Farbeinstellungen" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Bild spiegeln" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Bild horizontal spiegeln" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Automatische Belichtung" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Aktiviert/Deaktiviert die automatische Belichtung" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Jetzt kalibrieren" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Kalibrierung *jetzt* ausführen" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Selbsttest" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Führt einen Selbsttest des Scanners durch" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Scanner zurücksetzen" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Scanner zurücksetzen" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Handhabung der Medien" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Film nach jedem Scannen auswerfen" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Wirft den Film automatisch nach jedem Scannen aus dem Gerät aus" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Film vor Beenden auswerfen" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Den Film automatisch aus dem Gerät auswerfen bevor das Programm schließt" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Film jetzt auswerfen" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Film *jetzt* auswerfen" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Automatischer Dokumenteinzug" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Nur Flachbett" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "Automatischen Dokumenteinzug abschalten und nur Flachbett benutzen" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Durchlichtaufsatz" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "Die Durchlichteinheit (FAU, film adapter unit) an/ausschalten" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Negativfilm" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Positiv- oder Negativfilm" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Dichte Einstellung" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Dichte Einstellungsmodus setzen" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Transparenzgrad" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Filmtyp auswählen" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Wählt den Filmtyp aus" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flachbett" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "Automatischer Dokumenteneinzug vorne" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "Automatischer Dokumenteneinzug hinten" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "ADF-Duplex" #: backend/canon_dr.c:412 #, fuzzy, no-c-format msgid "Card Front" msgstr "Vorne" #: backend/canon_dr.c:413 #, fuzzy, no-c-format msgid "Card Back" msgstr "Hinten" #: backend/canon_dr.c:414 #, fuzzy, no-c-format msgid "Card Duplex" msgstr "Duplex" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Rot" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Grün" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Blau" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "Rot verstärken" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "Grün verstärken" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "Blau verstärken" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Kein" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "JPEG" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "Einseitig" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Duplex" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Durchlichtaufsatz" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Autom. Dokumenteneinzug" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Filmpositiv" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Filmnegativ" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Fokus auf dem Glas" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Fokus 2.5mm über dem Glas" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Halbton A (hart)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Halbton B (weich)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Halbton C" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Dithering A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Dithering B (4x4 Spiral)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Dithering C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Dithering D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Technik zur Textverbesserung" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Übertrage Muster A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Übertrage Muster B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Keine Korrektur" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Benutzerdefiniert" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Nadeldrucker" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Thermische Drucker" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Tintenstrahldrucker" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT-Monitore" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Standardeinstellung" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Drucken mit hoher Auflösung" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Drucken mit geringer Auflösung" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Drucken mit hohem Kontrast" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Benutzerdefiniert (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Benutzerdefiniert (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 hoch" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 quer" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Maximal" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Scanmodus" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Wählt den Halbton aus." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Blindfarbe" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Wählt die Blindfarbe." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Wählt die Helligkeit." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Schärfe" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Farbkorrektur" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Setzt die Farbkorrekturtabelle für das ausgewählte Ausgabegerät" #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Farbkorrekturkoeffizienten" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matritzenmultiplikation der RGB-Werte" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Verschiebt Grün nach Rot" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Verschiebt Grün nach Blau" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Verschiebt Rot nach Grün" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Verschiebt Rot nach Blau" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Verschiebt Blau nach Grün" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Verschiebt Blau nach Rot" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Legt den den Grünanteil fest" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Erhöhe den Rotanteil basierend auf dem Grünwert" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Erhöhe den Blauanteil basierend auf dem Grünwert" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Erhöhe den Grünanteil basierend auf dem Rotwert" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Legt den Rotanteil fest" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Erhöhe den Blauanteil basierend auf dem Rotwert" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Erhöhe den Grünanteil basierend auf dem Blauwert" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Erhöhe den Rotanteil basierend auf dem Blauwert" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Legt den Blauwert fest" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Das Bild spiegeln" #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Schnelle Vorschau" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Automatische Auswahl des Scanbereichs" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Kurze Auflösungsliste" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Zeige eine kurze Auflösungsliste an" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Vergrösserung" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Definiert den Vergrösserungsfaktor, der vom Scanner benutzt wird" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Schnellformat" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Optionales Zubehör" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "auswerfen" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Wirft das Blatt aus dem automatischen Dokumenteinzug aus" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Automatischer Auswurf" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Auswurf des Dokuments nach dem Scannen" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "ADF-Modus" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "Wählt den ADF-Modus aus (einseitig/doppelseitig)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Schacht" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Wähle den Schacht zum Scannen aus" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Wählt die Gammakorrektur aus einer Liste von vordefinierten Geräten aus " "oder eine benutzerdefinierte Tabelle, die in den Scanner geladen werden " "kann" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Fokus Position" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "Setzt den Fokus entweder auf das Glas oder 2.5mm darüber" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Warte auf Knopfdruck" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Beginne mit dem Scannen erst, wenn nach dem Senden des Scankommandos der " "Knopf am Scanner gedrückt wird." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "Infrarot" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Diapositiv" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Dianegativ" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "Eingebautes CCT-Profil" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "Benutzerdefiniertes CCT-Profil" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "An" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Aus" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "DTC" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "SDTC" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Halbton" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "Diffusion" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "Weiß" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "Schwarz" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Fortfahren" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Stopp" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10mm" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15mm" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20mm" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontal" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "horizontal breit" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "horizontal schmal" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Vertikal" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "vertikal breit" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "Oben nach unten" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "Unten nach oben" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "Vorne" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "Hinten" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "Gamma-Exponent" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "Verändert die Intensität der mittleren Farbtöne" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "" #: backend/fujitsu.c:3165 #, fuzzy, no-c-format msgid "Halftone type" msgstr "Halbton" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "" #: backend/fujitsu.c:3209 #, no-c-format msgid "Outline" msgstr "" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Führt Kalibrierung durch" #: backend/fujitsu.c:3221 #, fuzzy, no-c-format msgid "Emphasis" msgstr "Bildgewichtung" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "" #: backend/fujitsu.c:3240 #, fuzzy, no-c-format msgid "Separation" msgstr "Sättigung" #: backend/fujitsu.c:3241 #, fuzzy, no-c-format msgid "Enable automatic separation of image and text" msgstr "" "Schaltet die automatische Bestimmung des Schwellwerts für den Schwarz-" "Weiß-Modus ein." #: backend/fujitsu.c:3252 #, fuzzy, no-c-format msgid "Mirroring" msgstr "Bild spiegeln" #: backend/fujitsu.c:3253 #, fuzzy, no-c-format msgid "Reflect output image horizontally" msgstr "Bild horizontal spiegeln." #: backend/fujitsu.c:3270 #, fuzzy, no-c-format msgid "White level follower" msgstr "Weißwert für Blau" #: backend/fujitsu.c:3271 #, fuzzy, no-c-format msgid "Control white level follower" msgstr "Legt den Rotanteil fest" #: backend/fujitsu.c:3289 #, fuzzy, no-c-format msgid "BP filter" msgstr "Farbfilter" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Glätten" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "" #: backend/fujitsu.c:3323 #, fuzzy, no-c-format msgid "Gamma curve" msgstr "Gammawert" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "Schwellwertkurve" #: backend/fujitsu.c:3347 #, fuzzy, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" "Dynamische Schwellwertkurve, von hell zu dunkel, nomalerweise 50-65" #: backend/fujitsu.c:3369 #, fuzzy, no-c-format msgid "Threshold white" msgstr "Schwellwert" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, fuzzy, no-c-format msgid "Noise removal" msgstr "Rauschunterdrückung" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "" #: backend/fujitsu.c:3404 #, no-c-format msgid "Remove 5 pixel square noise" msgstr "" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "" #: backend/fujitsu.c:3421 #, no-c-format msgid "Remove 4 pixel square noise" msgstr "" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "" #: backend/fujitsu.c:3438 #, no-c-format msgid "Remove 3 pixel square noise" msgstr "" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "" #: backend/fujitsu.c:3508 #, fuzzy, no-c-format msgid "Auto width detection" msgstr "Keine Korrektur" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "" #: backend/fujitsu.c:3526 #, fuzzy, no-c-format msgid "Auto length detection" msgstr "Keine Korrektur" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "" #: backend/fujitsu.c:3708 #, fuzzy, no-c-format msgid "DF recovery mode" msgstr "Abdeckung des automatischen Einzuges offen" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "" #: backend/fujitsu.c:3748 #, fuzzy, no-c-format msgid "Advanced paper protection" msgstr "Erweiterte Optionen" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" #: backend/fujitsu.c:3768 #, fuzzy, no-c-format msgid "Staple detection" msgstr "Keine Korrektur" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" #: backend/fujitsu.c:3809 #, fuzzy, no-c-format msgid "Dropout color" msgstr "Blindfarbe" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" #: backend/fujitsu.c:3833 #, fuzzy, no-c-format msgid "Buffer mode" msgstr "Einzugsmodus" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" #: backend/fujitsu.c:3911 #, fuzzy, no-c-format msgid "Off timer" msgstr "Lampenausschaltzeit" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" #: backend/fujitsu.c:3930 #, fuzzy, no-c-format msgid "Duplex offset" msgstr "Offset blauer Kanal" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Offset grüner Kanal" #: backend/fujitsu.c:3949 #, fuzzy, no-c-format msgid "Adjust green/red offset" msgstr "Offset grüner Kanal" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Offset blauer Kanal" #: backend/fujitsu.c:3967 #, fuzzy, no-c-format msgid "Adjust blue/red offset" msgstr "Legt den Offset des blauen Kanals fest" #: backend/fujitsu.c:3980 #, fuzzy, no-c-format msgid "Low Memory" msgstr "Nicht genügend Speicher" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" #: backend/fujitsu.c:3996 #, fuzzy, no-c-format msgid "Duplex side" msgstr "Duplexscan" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "" #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" #: backend/fujitsu.c:4095 #, fuzzy, no-c-format msgid "Endorser Options" msgstr "Erweiterte Optionen" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "" #: backend/fujitsu.c:4253 #, fuzzy, no-c-format msgid "Endorser direction" msgstr "Rauschunterdrückung" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "" #: backend/fujitsu.c:4344 #, fuzzy, no-c-format msgid "A3 paper" msgstr "Vom Papier" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "" #: backend/fujitsu.c:4356 #, fuzzy, no-c-format msgid "B4 paper" msgstr "Vom Papier" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "" #: backend/fujitsu.c:4368 #, fuzzy, no-c-format msgid "A4 paper" msgstr "Vom Papier" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "" #: backend/fujitsu.c:4380 #, fuzzy, no-c-format msgid "B5 paper" msgstr "Vom Papier" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "" #: backend/fujitsu.c:4429 #, fuzzy, no-c-format msgid "Scanner in power saving mode" msgstr "Die Abdeckung des Scanners ist offen" #: backend/fujitsu.c:4452 #, fuzzy, no-c-format msgid "Manual feed" msgstr "Manueller Pre-Focus" #: backend/fujitsu.c:4453 #, fuzzy, no-c-format msgid "Manual feed selected" msgstr "Manueller Pre-Focus" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "" #: backend/fujitsu.c:4513 #, fuzzy, no-c-format msgid "Hardware error code" msgstr "Hardwareüberprüfungsfehler" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "" #: backend/fujitsu.c:4537 #, fuzzy, no-c-format msgid "Imprinter ink level" msgstr "Weißwert" #: backend/fujitsu.c:4548 #, fuzzy, no-c-format msgid "Density" msgstr "Dichte Einstellung" #: backend/fujitsu.c:4549 #, fuzzy, no-c-format msgid "Density dial" msgstr "Dichte Einstellung" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, fuzzy, no-c-format msgid "Duplex switch" msgstr "Duplexscan" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extras" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "" "Dynamische Schwellwertkurve, von hell zu dunkel, nomalerweise 50-65" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "dynamische Strichzeichnung abschalten" #: backend/genesys.c:5844 #, fuzzy, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" "Abschalten um einen Software angepassten Algorithmus zur Erstellung von " "Strichzeichnungen zu verwenden anstatt die Hardwarefunktion zu nutzen" #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Interpolation abschalten" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "Wenn Sie hohe Auflösungen verwenden, bei denen die horizontale Auflösung " "kleiner ist als die vertikale, schaltet dies die horizontale " "Interpolation aus" #: backend/genesys.c:5872 #, fuzzy, no-c-format msgid "Color filter" msgstr "Farbfilter" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "Wenn Graustufen oder Strichzeichnung verwendet wird, wählt diese Option " "die Farbe" #: backend/genesys.c:5901 #, fuzzy, no-c-format msgid "Calibration file" msgstr "Kalibrierung" #: backend/genesys.c:5902 #, fuzzy, no-c-format msgid "Specify the calibration file to use" msgstr "Kalibriermodus definieren" #: backend/genesys.c:5919 #, fuzzy, no-c-format msgid "Calibration cache expiration time" msgstr "Kalibrierungsdatenspeicher" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Lampenausschaltzeit" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "Die Lampe wird nach der angegebenen Zeit (in Minuten) ausgeschaltet. Ein " "Wert von 0 bedeutet, dass die Lampe nich ausgeschaltet wird." #: backend/genesys.c:5943 #, fuzzy, no-c-format msgid "Lamp off during scan" msgstr "Lampe aus während Schwarzkalibrierung" #: backend/genesys.c:5944 #, fuzzy, no-c-format msgid "The lamp will be turned off during scan. " msgstr "Anzahl der Minuten, bis die Lampe nach dem Scan ausgeschaltet wird" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Datei-Knopf" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "OCR-Knopf" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Einschaltknopf" #: backend/genesys.c:6053 backend/genesys.c:6054 #, fuzzy, no-c-format msgid "Extra button" msgstr "E-Mail-Knopf" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "benötigt Kalibirierung" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "" "Der Scanner benötigt eine Kalibrierung für die momentanen Einstellungen" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Knöpfe" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibrierung" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Starte den Kalibrierungsprozess mit einem Spezialblatt" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Kalibrierung zurücksetzen" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Löscht den Kalibrierungsspeicher" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Durchlichteinheit" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Graustufen-Farbe" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Legt fest, welche SCanfarbe im Garustufen-Modus verwendet wird " "(Standardwert: Grün)." #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Optionen zur Fehlersuche" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatisches Aufwärmen" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Warte solange, bis die Helligkeit der Lampe konstant ist anstatt einfach " "60 Sekunden zu warten." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Kompletter Scan" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Scanne den gesamten möglichen Scanbereich inklusive des " "Kalibrierungsstreifens. Vorsicht, keine zu große Länge auswählen. Nur " "für Testzwecke." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Grobkalibrierung" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Stelle Verstärkung und Versatz automatisch ein. Wenn dies Option " "ausgeschaltet ist, können die Parameter des AFE (\"Analog Frontend\") " "manuell eingestellt werden. Diese Option is standardmäßig an. Nur für " "Testzwecke." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Grobkalibrierung nur für ersten Scan" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Die Grobkalibrierung wird nur für den ersten Scan durchgeführt. Das " "funktioniert mit den meisten Scannern und kann einiges an Scanzeit " "sparen. Wenn die Helligkeit der Bilder von Scan zu Scan schwankt, sollte " "diese Option ausgeschaltet werden. Nur für Testzwecke." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "Backtrack-Zeilen" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Anzahl der Zeilen, die der Scanschlitten zurückfährt, wenn Backtracking " "auftritt. Das passiert, wenn der Scanner schneller scant, als der " "Computer die Daten aufnehmen kann. Niedrigere Werte sorgen für " "schnellere Scans, erhöhen jedoch das Risiko, Zeilen zu überspringen." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gammawert" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Legt den Gammawert für alle Kanäle fest." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Geometrie" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Scanmodus" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Dia" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Scannermodell" #: backend/hp3900_sane.c:1408 #, fuzzy, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" "Erlaubt Geräteverhalten mit anderen unterstützten Modellen zu testen" #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Bildfarben werden invertiert" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Gammakorrektur abschalten" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "Die Gammakorrektur wird abgeschaltet" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Weißabgleichskorrektur abschalten" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "Weißabgleichkorrektur wird abgeschaltet" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Aufwärmprozess überspringen" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "Der Aufwärmprozess wird überspungen" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "erzwinge echte Tiefe" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "Falls Gamma verwendet wird, werden Scans mit einer Farbtiefe von 16 Bit " "ausgeführt und danach in die gewählte Farbtiefe umgewandelt, um die " "Bildqualität zu verbessern. Diese Option verhindert Farbtiefen-Emulation." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Graustufen emulieren" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "Falls verwendet, wird das Bild im Farbmodus gescannt und dann per " "Software in Graustufen umgewandelt. Unter manchen Umständen verbessert " "dies die Bildqualität." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Debugging Bilder abspeichern" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "Wenn aktiviert werden einige Bilder im Scanprozess gespeichert um sie zu " "analysieren." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Chipsatz zurücksetzen" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Setzt die Daten des Chipsatzes zurück" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Information" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Name des Chipsatzes" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Zeigt den im Gerät verwendeten Chipsatz an." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Unbekannt" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "Chipsatz-ID" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Zeigt die ID des Chipsatzes an" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Scanzähler" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Zeigt die Anzahl der Scans an" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Information aktualisieren" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Aktualisiert alle Informationnen über das Gerät" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Diese Option spiegelt den vorderen Scannerknopf wieder" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Bild" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Verschiedenes" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "X-Abstand" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "hardwareinterne X-Position des Scanbereichs" #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "Y-Abstand" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "hardwareinterne Y-Position des Scanbereichs" #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Lampenstatus" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Schaltet die Lampe an oder aus" #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Kalibriert Schwarz- und Weisswert." #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "ADF" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMA-Dias" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMA-Negative" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Farbe (48 Bit)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Lampenausschaltzeit verlängern" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Verländert die Lampenausschaltzeit (von 15 Minuten bis 1 Stunde)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Warten auf Knopfdruck" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Scannen beginnt erst mit Knopfdruck" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Erweiterte Optionen" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Grob" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fein" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Benutzerdefiniert" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Auto" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Unverändert" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Grau" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA Grau" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Langsam" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Schnell" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Besonders schnell" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2 Pixel" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4 Pixel" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8 Pixel" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Foto" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Film-Streifen" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Bedingt" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Experiment" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Schärfe" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Legt den Wert für die Schärfe fest." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Automatischer Schwellwert" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Schaltet die automatische Bestimmung des Schwellwerts für den Schwarz-" "Weiß-Modus ein." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Wählt den Glättungs-Filter aus." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Medium nach dem Scannen auswerfen" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Wirft das Medium nach dem Scan aus." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Dokument wechseln" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Dokument wechseln." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Auswerfen" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Dokument auswerfen." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Startet den Kalibrierungsprozess." #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Medium" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Legt den Typ des Mediums fest." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Belichtungszeit" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Bei einer längeren Belichtungszeit kann der Scanner mehr Licht " "auffangen. Empfohlene Werte: 175% für Fotos, 150% für normale Dias und " "\"Negativ\" für Negativ-Filme. Für dunkle (unterentwickelte) Bilder kann " "dieser Wert vergrößert werden." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Farbmatrix" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Legt die Farbmatrix für den Scanner fest." #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Benutzerdefinierte Farbmatrix." #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Graue Farbmatrix" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Benutzerdefinierte Farbmatrix für Graustufenscans." #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Horizontal spiegeln" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Bild horizontal spiegeln." #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Vertikal spiegeln" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Bild vertikal spiegeln." #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Optionen aktualisieren" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Optionen aktualisieren." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8-Bit-Ausgabe" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "" "Benutze intern eine Frabtiefe von mehr als 8 Bit, extern aber nur 8 Bit." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Warten auf vorderen Knopf" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Warte mit dem Scan aud das Drücken des vorderen Knopfes." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Lampe ausschalten" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Schalte Scannerlampe aus." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Papiergröße" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatische Trennung" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, fuzzy, no-c-format msgid "Landscape" msgstr "A5 quer" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, fuzzy, no-c-format msgid "Length control mode" msgstr "Dichte Einstellungsmodus setzen" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, fuzzy, no-c-format msgid "Manual feed mode" msgstr "Manueller Pre-Focus" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, fuzzy, no-c-format msgid "Manual feed timeout" msgstr "Manueller Pre-Focus" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Schalte Duplex- (zweiseitiges) Scannen ein" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "Tatsächliche Größe des Papiers im ADF" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "" #: backend/kvs1025_opt.c:40 #, fuzzy, no-c-format msgid "halftone" msgstr "Halbton" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "" #: backend/kvs1025_opt.c:42 #, fuzzy, no-c-format msgid "color" msgstr "Farbe" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, fuzzy, no-c-format msgid "continuous" msgstr "Fortfahren" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, fuzzy, no-c-format msgid "off" msgstr "Aus" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, fuzzy, no-c-format msgid "bayer_64" msgstr "Bayer" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, fuzzy, no-c-format msgid "bayer_16" msgstr "Bayer" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, fuzzy, no-c-format msgid "halftone_32" msgstr "Halbton" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, fuzzy, no-c-format msgid "halftone_64" msgstr "Halbton" #: backend/kvs1025_opt.c:153 #, fuzzy, no-c-format msgid "diffusion" msgstr "Diffusion" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, fuzzy, no-c-format msgid "normal" msgstr "Normal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, fuzzy, no-c-format msgid "light" msgstr "Licht" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, fuzzy, no-c-format msgid "From scanner" msgstr "Filmscanner" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Vom Papier" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, fuzzy, no-c-format msgid "default" msgstr "Standardeinstellung" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, fuzzy, no-c-format msgid "smooth" msgstr "Glatt" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, fuzzy, no-c-format msgid "low" msgstr "Langsam" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, fuzzy, no-c-format msgid "medium" msgstr "Mittel" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, fuzzy, no-c-format msgid "red" msgstr "Rot" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, fuzzy, no-c-format msgid "green" msgstr "Grün" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "" #: backend/kvs1025_opt.c:562 #, fuzzy, no-c-format msgid "Sets the scan source" msgstr "Scanquelle" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Einzugsmodus" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Legt den Einzugsmodus fest" #: backend/kvs1025_opt.c:584 #, fuzzy, no-c-format msgid "Enable/Disable long paper mode" msgstr "Aktiviere/Deaktiviere automatischen Fokus\t\t" #: backend/kvs1025_opt.c:593 #, fuzzy, no-c-format msgid "Enable/Disable length control mode" msgstr "Dichte Einstellungsmodus setzen" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, fuzzy, no-c-format msgid "Sets the manual feed mode" msgstr "Legt den Einzugsmodus fest" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, fuzzy, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Legt den Einzugsmodus fest" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatischer Schwellwert" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Legt automatisch Helligkeit, Kontrast, Weißwert, Gamma, " "Rauschunterdrückung und Bildgewichtung fest" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Rauschunterdrückung" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Reduziert das Rauschen einzelner Punkte" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Bildgewichtung" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Wählt die Bildgewichtung." #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, fuzzy, no-c-format msgid "Lamp color" msgstr "Lampe an" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, fuzzy, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Schaltet die Lampe an oder aus" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "" #: backend/kvs1025_opt.c:840 #, fuzzy, no-c-format msgid "Mirror image (left/right flip)" msgstr "Bild vertikal spiegeln." #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gammakorrektur" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "" #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "" #: backend/kvs40xx_opt.c:231 #, fuzzy, no-c-format msgid "High sensivity" msgstr "Drucken mit hoher Auflösung" #: backend/kvs40xx_opt.c:232 #, fuzzy, no-c-format msgid "Low sensivity" msgstr "Drucken mit geringer Auflösung" #: backend/kvs40xx_opt.c:243 #, fuzzy, no-c-format msgid "err_diffusion" msgstr "Diffusion" #: backend/kvs40xx_opt.c:249 #, fuzzy, no-c-format msgid "No detection" msgstr "Keine Korrektur" #: backend/kvs40xx_opt.c:250 #, fuzzy, no-c-format msgid "Normal mode" msgstr "Normal" #: backend/kvs40xx_opt.c:251 #, fuzzy, no-c-format msgid "Enhanced mode" msgstr "Farbverbesserung" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "" #: backend/kvs40xx_opt.c:642 #, fuzzy, no-c-format msgid "Automatic threshold mode" msgstr "Automatischer Schwellwert" #: backend/kvs40xx_opt.c:643 #, fuzzy, no-c-format msgid "Sets the automatic threshold mode" msgstr "Automatischer Schwellwert" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "" #: backend/kvs40xx_opt.c:777 #, fuzzy, no-c-format msgid "Set chroma of red" msgstr "Legt die Reihenfolge der Frames fest" #: backend/kvs40xx_opt.c:787 #, fuzzy, no-c-format msgid "chroma of blue" msgstr "Schatten Blau" #: backend/kvs40xx_opt.c:788 #, fuzzy, no-c-format msgid "Set chroma of blue" msgstr "Verschiebt Rot nach Blau" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Diamant" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Vertikale Linie" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Verstärkung" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Farbkanal Verstärkungseinstellungen" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Verstärkung grauer Kanal" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Legt die Verstärkung des grauen Kanals fest" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Verstärkung roter Kanal" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Legt die Verstärkung des roten Kanals fest" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Verstärkung grüner Kanal" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Legt die Verstärkung des grünen Kanals fest" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Verstärkung blauer Kanal" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Legt die Verstärkung des blauen Kanals fest" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer Halbton 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer Halbton 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Halbton Punkt 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Halbton Punkt 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Fehlerstreuung" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Modus 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Modus 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Modus 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "Vom Kalibrierungstreifen" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Glatt" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Niedrig" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Mittel" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Hoch" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "Röhrenmonitor" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Eine Seite" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Alle Seiten" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "Einzugsscanner" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "4 Bit Graustufen" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "8 Bit Graustufen" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Lichtwerte" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Spezialoptionen" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Farbbalance" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "kein Backtracking" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "" "wenn aktiviert, erfolgt kein Rücklauf des Scankopfes während der " "Datenübertragung" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Lampe ein/ausschalten" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Schaltet die Lampe des Flachbettscanners ein bzw. aus" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Software - Kalibrierung" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "einige Scanner benötigen eine Kalibrierung durch die Software, sonst " "entstehen senkrechte Streifen im Bild" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Benutzung des LIGHTLID 35" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "" "Bei der Benutzung des LIGHTLID 35 Durchlichtadapters wird während des " "Scans die Flachbett - Lampe ausgeschaltet um besseren Kontrast zu " "erreichen" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Hohe Qualität" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Hohe Qualität bei geringer Geschwindigkeit" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Hohe Geschwindigkeit" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Hohe Geschwindigkeit bei geringerer Qualität" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatische schwarz/weiß - Schwelle" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Bei einem Strichzeichnungsscan versucht die Software einen optimalen " "Wert für die schwarz/weiß- Schwelle zu bestimmen" #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Modus der Gammakorrektur." #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Verbinde Gammawerte" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Alle Farben benutzen dieselbe Gammakorrektur." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Gamma - Zahlenwert" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Gibt einen Gamma - Zahlenwert an" #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Gamma - Wert für Rot" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Gamma - Wert für Rot" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Gamma - Wert für Grün" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Gamma - Wert für Grün" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Gamma - Wert für Blau" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Gamma - Wert für Blau" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Farbkanal" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Wählt den Farbkanal; \"Master\" bedeutet, dass alle Farben beeinflusst " "werden" #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Mittelgrauwert" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Bestimmt, welcher Helligkeitswert als 50% Grau angenommen wird" #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Mittelwert für Rot" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Bestimmt, welcher Helligkeitswert als 50% Rot angenommen wird" #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Mittelwert für Grün" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Bestimmt, welcher Helligkeitswert als 50% Grün angenommen wird" #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Mittelwert für Blau" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Bestimmt, welcher Helligkeitswert als 50% Blau angenommen wird" #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Rot - Balance" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "Farbbalance-Faktor für Rot: 100% bedeutet keine Farbkorrektur" #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Grün - Balance" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "Farbbalance-Faktor für Grün: 100% bedeutet keine Farbkorrektur" #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Blau - Balance" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "Farbbalance-Faktor für Blau: 100% bedeutet keine Farbkorrektur" #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Standard - Balance" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "Setzt die Farbbalance auf die vom Hersteller vorgegebenen Werte" #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Sehr langsam" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Langsam" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Schnell" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Sehr schnell" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 grob" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fein" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 sehr fein" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 grob" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 grob" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fein" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 grob" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normal" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fein" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 benutzerdefiniert" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 benutzerdefiniert" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 benutzerdefiniert" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 benutzerdefiniert" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 benutzerdefiniert" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 benutzerdefiniert" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Schneller Graumodus" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Scanne im schnellen Graumodus (geringere Bildqualität)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Legt fest, dass alle Vorschau-Scans im schnellsten Modus (mit geringer " "Qualität) durchgeführt werden. Das kann ein Schwarzweißmodus oder ein " "Modus mit niedriger Auflösung sein." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Lampenausschaltzeit (Minuten)." #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "" "Legt die Zeit (in Minuten) fest, nach der die Lampe ausgeschaltet wird." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Schalte die Lampe aus" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Schaltet die Lampe sofort aus." #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Helligkeit des Rotwerts" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "" "Stellt die Helligkeit der roten Komponente des gescannten Bildes ein." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Helligkeit des Grünwerts" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "" "Stellt die Helligkeit der grünen Komponente des gescannten Bildes ein." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Helligkeit des Blauwerts" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "" "Stellt die Helligkeit der blauen Komponente des gescannten Bildes ein." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Kontrast der grünen Komponente" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "" "Stellt den Kontrast der roten Komponente des gescannten Bildes ein." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Kontrast der grünen Komponente" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "" "Stellt den Kontrast der grünen Komponente des gescannten Bildes ein." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Kontrast der blauen Komponente" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "" "Stellt den Kontrast der blauen Komponente des gescannten Bildes ein." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Farbe 48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Farbe 24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Grau 16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Grau 8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Aufsicht" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Positiv" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Warte solange, bis die Helligkeit der Lampe konstant ist anstatt einfach " "40 Sekunden zu warten." #: backend/pixma.c:378 #, no-c-format msgid "Negative color" msgstr "Negativfilm Farbe" #: backend/pixma.c:383 #, no-c-format msgid "Negative gray" msgstr "Negativfilm Graustufen" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "48 Bit Farbe" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "16 Bit Graustufen" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" "Legt die Scanquelle fest (wie z.B. Dokumenteneinzug). Die Scanquelle " "muss vor Scanmodus und Scanauflösung ausgewählt werden. Setzt die " "Einstellungen für Scanmodus und Scanauflösung zurück." #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Scanen auf Knopfdruck" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Falls aktiviert startet der Scanprozess nicht automatisch. Zum Starten " "drücken Sie die Taste \"SCAN\" beim MP1500 oder \"COLOR\" bei anderen " "Modellen. Zum Abbrechen drücken Sie die Taste \"GRAY\"." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Knopfstatus aktualisieren" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Knopf 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Knopf 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "Vorlagentyp" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "Scanziel" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "ADF Wartezeit" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" "Der Scanner sucht während der Wartezeit (in Sekunden) nach einem " "Dokument, welches in den Scanschacht eingelegt wird." #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Durchlicht" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Geräteeinstellungen" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Lampenschalter" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Lampe(n) ein-/ausschalten." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Lampe aus während Schwarzkalibrierung" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Schaltet die Lampe immer während der Schwarzkalibrierung aus." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Kalibrierungsdatenspeicher" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Schaltet Kalibrierungsdatenspeicher ein oder aus." #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Führt Kalibrierung durch" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Sensorbeschleunigung" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Schaltet Sensorbeschleunigung an oder ab." #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Aufwärmzeit" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Aufwärmzeit in Sekunden." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Lampenausschaltzeit" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Lampenausschaltzeit in Sekunden." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Analog Frontend" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Verstärkung roter Kanal des AD-Wandlers." #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Offset roter Kanal" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Offset roter Kanal des AD-Wandlers." #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Verstärkung grüner Kanal des AD-Wandlers." #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Offset grüner Kanal des AD-Wandlers." #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Verstärkung blauer Kanal des AD-Wandlers." #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Offset blauer Kanal des AD-Wandlers." #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Ausschaltzeitpunkt rote Lampe" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Definiert den Ausschaltzeitpunkt der roten Lampe." #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Ausschaltzeitpunkt grüne Lampe" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Definiert den Ausschaltzeitpunkt der grünen Lampe." #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Ausschaltzeitpunkt blaue Lampe" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Definiert den Ausschaltzeitpunkt der blauen Lampe." #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Diese Option spiegelt den Zustand der Scannerknöpfe wider." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Farbe36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Halbtonmuster 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Halbtonmuster 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Zufallsmuster" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Dateiauswahl" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Bildkorrektur" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Graustufen" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Bild in Graustufen laden." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Three-Pass Simulation" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simuliere einen Three-Pass Scanner, indem hintereinander je ein Frame " "für jede Grundfarbe übertragen wird. Die Reihenfolge ist grün-blau-rot." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Handscanner Simulation" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simuliere einen Handscanner. Bei Handscannern steht meistens die " "Bildhöhe nicht von vornherein fest. Stattdessen geben sie eine Höhe von " "-1 zurück. Mit dieser Option kann man prüfen, ob das Frontend damit " "richtig umgehen kann." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Stellt die Farbverbesserungseinstellungen (Helligkeit und Kontrast) auf " "Defaultwerte." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Nur-Lese-Testoption" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Mal sehen, ob das Frontend damit umgehen kann." #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Gammatabellen" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Statuscode Simulation" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Keinen Statuscode erzwingen" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Zwinge das Backend nicht dazu, einen Statuscode zurückzuliefern." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Liefere SANE_STATUS_EOF zurück" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Zwinge das Backend dazu, nach einem Aufruf von sane_read() den " "Statuscode SANE_STATUS_EOF zurückzuliefern." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Liefere SANE_STATUS_JAMMED zurück" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Zwinge das Backend dazu, nach einem Aufruf von sane_read() den " "Statuscode SANE_STATUS_JAMMED zurückzuliefern." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Liefere SANE_STATUS_NO_DOCS zurück" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Zwinge das Backend dazu, nach einem Aufruf von sane_read() den " "Statuscode SANE_STATUS_NO_DOCS zurückzuliefern." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Liefere SANE_STATUS_COVER_OPEN zurück" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Zwinge das Backend dazu, nach einem Aufruf von sane_read() den " "Statuscode SANE_STATUS_COVER_OPEN zurückzuliefern." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Liefere SANE_STATUS_IO_ERROR zurück" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Zwinge das Backend dazu, nach einem Aufruf von sane_read() den " "Statuscode SANE_STATUS_IO_ERROR zurückzuliefern." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Liefere SANE_STATUS_NO_MEM zurück" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Zwinge das Backend dazu, nach einem Aufruf von sane_read() den " "Statuscode SANE_STATUS_NO_MEM zurückzuliefern." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Liefere SANE_STATUS_ACCESS_DENIED zurück" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Zwinge das Backend dazu, nach einem Aufruf von sane_read() den " "Statuscode SANE_STATUS_ACCESS_DENIED zurückzuliefern." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Diese Option zeigt den Zustand eines Scannerknopfes an." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lampe an" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Schalte Scannerlampe ein" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lampe aus" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Schalte Scannerlampe aus" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Lampenausschaltzeit" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Anzahl der Minuten, bis die Lampe nach dem Scan ausgeschaltet wird" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Schwellenwert für den Strichzeichnungsmodus" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Automatischer Dokumenteinzug" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (Zoll)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (Zoll)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (Zoll)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Halbton nicht unterstützt" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Anzahl der Zeilen, die pro SCSI Lesevorgang angefordert werden. Eine " "Änderung dieses Parameters erlaubt die Feineinstellung der " "Geschwindigkeit, mit der Daten vom Scanner gelesen werden. Wenn die " "Geschwindigkeit zu niedrig ist, muss der Scanner in regelmäßigen " "Abständen mitten im Scanvorgang anhalten. Falls sie zu groß ist, " "reagiert die Scan-Anwendung möglicherweise nicht mehr auf Eingaben und " "das System kann unbenutzbar werden." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "" #: backend/snapscan-options.c:117 #, fuzzy, no-c-format msgid "Focus point for scanning." msgstr "Auswurf des Dokuments nach dem Scannen" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Vorschaumodus" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Wählt den Scanmodus für die Vorschau aus. Vorschau in Graustufen ist " "normalerweise der beste Kompromiss aus Geschwindigkeit und Detailtreue." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Vordefinierte Einstellungen" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "" "Stellt Standardgrößen für Fotographien, bedruckte Seiten etc. zur " "Verfügung." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "" #: backend/snapscan-options.c:885 #, fuzzy, no-c-format msgid "Frame to be scanned" msgstr "Flachbettscanner" #: backend/snapscan-options.c:897 #, fuzzy, no-c-format msgid "Focus-mode" msgstr "Fokus" #: backend/snapscan-options.c:898 #, fuzzy, no-c-format msgid "Auto or manual focus" msgstr "Automatischer Fokus" #: backend/snapscan-options.c:911 #, fuzzy, no-c-format msgid "Focus-point" msgstr "Fokus Position" #: backend/snapscan-options.c:912 #, fuzzy, no-c-format msgid "Focus point" msgstr "Fokus Position" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Farbzeilen pro Lesevorgang" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Graustufenzeilen pro Lesevorgang" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "Webcam" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Farbe RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Farbe RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Farbe RGB TEXT" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Komplett schwarz" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Komplett weiß" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Farbmuster" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Gitter" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Erster Eintrag" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Zweiter Eintrag" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Dies ist der sehr lange dritte Eintrag. Vielleicht weiß das Frontend, " "wie man ihn darstellen kann." #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Handscanner-Simulation" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simuliere einen Handscanner. Bei Handscannern steht meistens die " "Bildhöhe nicht von vornherein fest. Stattdessen geben sie eine Höhe von " "-1 zurück. Mit dieser Option kann man prüfen, ob das Frontend damit " "richtig umgehen kann." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Three-Pass-Simulation" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simuliere einen Three-Pass-Scanner. Im Farbmodus werden drei Frames " "übertragen." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Legt die Reihenfolge der Frames fest" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Legt die Reihenfolge der Frames im Three-Pass-Modus fest." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Falls der automatische Vorlageneinzug ausgewählt ist, meldet der Einzug " "\"leer\" nach 10 Scans." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Spezialoptionen" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Wählt das Testbild aus" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Wählt die Art des Testbildes aus. Verfügbare Testbilder:\n" "Komplett schwarz: füllt das ganze Bild schwarz.\n" "Komplett weiß: füllt das ganze Bild weiß.\n" "Farbmuster: zeichnet verschiedene Farbmuster, die vom ausgewählten Modus " "abhängen.\n" "Gitter: zeichnet ein Schwarz-Weiß-Gitter mit einer Höhe und Breite der " "einzelnen Felder von jeweils 10 mm." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Kehre Endianness um" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Tausche das untere und das obere Byte der Bilddaten im 16-Bit-Modus aus. " "Diese Option kann dazu benutzt werden, den 16-Bit-Modus der Frontends zu " "testen, beispielsweise um festzustellen, ob das Frontend die richtige " "Endianness verwendet." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Lesebegrenzung" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Begrenzt die Menge an Daten, die mit jedem Aufruf von sane_read() " "übertragen wird." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Größe der Lesebegrenzung" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "Die (maximale) Menge and Daten, die bei jedem Aufruf von sane_read() " "übertragen wird." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Leseverzögerung" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Verzögere die Datenübertragung durch die Pipe." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Dauer der Leseverzögerung." #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "Legt fest, wie lange nach der Übertragung eines Datenpuffers durch die " "Pipe gewartet wird." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Rückgabewert von sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Legt den Rückgabewert von sane_read() fest. \"Default\" ist die normale " "Einstellung für's Scannen. Alle anderen Rückgabewerte dienen dazu, das " "Verhalten des Frontends festzustellen." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Pixelverlust pro Zeile" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Die Anzahl der Pixel, die am Ende der Zeile ungenutzt sind." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Ungenaue Parameter" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Gebe ungenaue Werte für die Anzahl der Zeilen und die Bytes pro Zeile " "zurück, wenn sane_parameters() vor sane_start() aufgerufen wird." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Nichtblockierendes IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Verwende nichtblockierndes IO für sane_read(), wenn das durch das " "Frontend unterstützt wird." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Biete Select-Dateideskriptor an" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Biete einen Select-Dateideskriptor an, damit das Frontend erkennen kann, " "ob sane_read() Daten zurückliefern würde." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Test-Optionen einschalten" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Schalte verschiedene Testoptionen ein. Mit diesen Optionen kann man die " "Fähigkeit des Frontends feststellen, die verschiedenen Typen von SANE-" "Optionen darzustellen und zu ändern." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Gebe Optionen aus" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Gibt eine Liste aller Optionen aus." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Bool-Testoptionen" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Bool soft select soft detect" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Dies ist eine Bool-Testoption, welche die Fähigkeiten \"soft select" "\" und \"soft detect\" (und \"advanced\") hat. Also eine ganz normale " "Bool-Option." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Bool hard select soft detect" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Dies ist eine Bool-Testoption, welche die Fähigkeiten \"hard select" "\" und \"soft detect\" (und \"advanced\") hat. Das bedeutet, dass die " "Option nicht vom Frontend geändert werden kann, sondern vom Benutzer (z. " "B. indem er einen Knopf am Gerät drückt)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Bool hard select" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Dies is eine Bool-Testoption, welche die Fähigkieten \"hard select" "\" (und \"advanced\") hat. Das bedeutet, dass die Option " "nicht vom Frontend geändert " "werden kann, sondern vom Benutzer (z. B. indem er einen Knopf am " "Gerät drückt). Außerdem kann sie nicht vom Frontend gelesen werden." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Bool soft detect" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Die ist eine Bool-Testoption, welche die Fähigkeiten \"soft detect" "\" (und \"advanced\") hat. Das heißt, dass dies eine Nur-Lese-Option ist." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Bool soft select soft detect emulated" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Dies ist eine Bool-Testoption, welche die Fähigkeiten \"soft select" "\", \"soft detect\", und \"emulated\" (und \"advanced\") hat." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Bool soft select soft detect auto" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Dies ist eine Bool-Testoption, welche die Fähigkeiten \"soft select" "\", \"soft detect\", und \"automatic\" (und \"advanced\") hat. Diese " "Option kann vom Backend automatisch gesetzt werden." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Int-Testoptionen" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Int" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Int-Testoption ohne Einheit und Beschränkung." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Int constraint range" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Int-Testoption mit der Einheit \"Pixel\" und einer " "Bereichsbeschränkung. Das Minimum ist 4, das Maximum 192, und die " "Schrittweite ist 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Int constraint word list" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Int-Testoption mit der Einheit \"Bits\" und einer Wortlisten-" "Beschränkung." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Int array" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Int-Testoption mit der Einheit \"mm\" und einem Feld ohne " "Beschränkung." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Int array constraint range" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Int-Testoption mit der Einheit \"dpi\" und einem Feld mit einer " "Bereichsbeschränkung. Das Minimum ist 4, das Maximum 192, und die " "Schrittweite ist 2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Int array constraint word list" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Int-Testoption mit der Einheit \"Prozent\" und einem Feld mit " "einer Wort-Beschränkung." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Fixed-Testoptionen" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Fixed" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) Fixed-Testoption ohne Einheit und ohne Beschränkung." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Fixed constraint range" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Fixed-Testoption mit der Einheit \"Mikrosekunde\" und einer " "Bereichsbeschränkung. Das Minimum ist -42.17, das Maximum 32767.9999, " "und die Schrittweite ist 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Fixed constraint word list" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Fixed-Testoption ohne Einheit und mit einer Wortlisten-" "Beschränkung." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "String-Testoptionen" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) String" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) String-Testoption ohne Beschränkung." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) String constraint string list" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) String-Testoption mit einer Stringlisten-Beschränkung." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) String constraint long string list" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) String-Testoption mit einer Stringlisten-Beschränkung. Enthält ein " "paar mehr Einträge..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Button-Testoptionen" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Button" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Button-Testoption. Gibt etwas Text aus..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Farbe 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Benutze Bildzusammensetzung" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "2 Level schwarz/weiss (Strichzeichnungs Modus)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Halbton schwarz/weiss (Halbton Modus)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Multi-Level schwarz&weiss (Graustufen Modus)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Multi-Level RGB Farbe (ein-Pass-Farbe)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Kalibrierung ignorieren" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Pre-Focus ausschalten" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Focus nicht kalibrieren" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Manueller Pre-Focus" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Feste Focus-Position" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Linse auf Dokument kalibrieren" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Focus der Linse auf dem Dokument kalibrieren" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Halter Focus Position 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Benutze 0mm Halter Focus Position anstatt 0.6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Kalibrierungs Modus" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Kalibriermodus definieren" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Schaltet die Lampe an/aus" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA ein" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Schaltet den UTA ein/aus" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Offset" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Einstellungen des Offsets der Farbkanäle" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Offset grüner Kanal" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Legt den Offset des grauen Kanals fest" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Legt den Offset des roten Kanals fest" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Legt den Offset des grünen Kanals fest" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Legt den Offset des blauen Kanals fest" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Vorschaumodus" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "Problem nicht analysiert (unbekannte SCSI-Klasse)" sane-backends-1.0.27/po/fr.gmo0000664000175000017500000024075113110600540012752 00000000000000Þ•© 8°J ±J-¾J ìJ;øJ 4K,AK"nKz‘K L9LPL€mL#îL5M"HMÆkM2NjMN ¸NBÙN(OSEO™OذO‰PB¨PëPlQoQJQ+ÊQcöQ ZRz{R'öR™S$¸SWÝS5TFTWT\TaTiT nT yT „T TšT ¢T ­T¸T ÁT ÌT ×TâT ëT öT U UU !U /U ;UEUXUiU {U †U‘U šU ¥UÒ³U†V ‰V –V¢V¦V ¯V ºVÄVÍVÜV"äV!W)W!IW kWŒW ¬WÍWÖWsçW [X5eX ›X§X·XÉXáXôXY Y!>Y`Y€Y…Y”Y «Y ¶Y ÄYÏY äYîY!Z*Z?ZSZ<dZG¡Z_éZI[N[=^[>œ[<Û[\\"\2\'B\j\s\‹\ \ ¨\²\ ¸\Ä\ É\Ö\ æ\ð\ ] ] (]4]Q] c]q]%€]¦]%µ] Û]æ]û]^ ^^.^E^M^P^`^ d^q^„^ ^½^Ø^ ê^ô^_)!_%K_ q_}_”_«_¼_ Ì_Ú_ë_û_ ` ``-`E`L`&_`Ć`KaQaaaja ya ‡a ”a ža¨a ·aÅaâabb 0b>bFbNbVb lbxbbŠb b·bÌbàbõb6c.?cBncC±cAõc,7d@ddA¥d?çd('e Pe!\e*~e ©e´e(»eäeùeýeff f)8f"bf$…f*ªf#Õf(ùf!"gDg#bg†g£g ÃgägIh,Mh'zh¢h0²hDãh (i4iDi Li1ViˆiiµiÎiäieöi \j}jjŸj½jÄjÙjïj k/#k Sk _k%kk‘k&°k×kîk1l9lIl`l wl˜l²lÅlØlàl çlEól9m;PmŒm’m°mËmâmñmn !n.n#@n?dn!¤n Ænçnûn}o(—o+Ào0ìop 1p >p Lp Xpdptp­Œp:q Tq _qmq0q ²q½qÕqÜqáq ðq ýqrr r !r -r9r Br LrWr \rgr xr„r—rªr ²r¿rÅrÝrìrûrs's%8sh^seÇs^-tcŒtaðtbRuaµu v"v3v9v KvUvfvkvqv ‚vv! v Âv)Îv*øv(#w›Lwèwñw x x xx *x6x=xCxKx\xmx|x ‚xx ¡x¬xÈxØx çxôxy+y0y9yPygyyyŸy°y ÆyÑyèyz2z2Kz~z’z¬z±zÈzÞzþz {({;{O{a{ {{†{–{I¨{ò{Tö{[K|E§|4í|’"}¹µ}Qo~€Á~¢Båøþ€/€>€N€i€*}€5¨€ Þ€ê€ó€&8=Zc t •£» Ã Ï Üé ‚ ‚0.‚_‚Cf‚ª‚²‚Ï‚ç‚낃ƒ'ƒGƒdƒhƒnƒuƒ…ƒƒžƒ°ƒ+Àƒìƒ þƒ „&„?„]„o„ „„”„›„¢„&´„*Û„ ………*… 3…A… P…^… q… {…‰…¤…´…¹… À…XÍ…Þ&†‡]‡uˆ ‘ˆœˆL ˆíˆ ‰‰‰‰=‰U‰m‰ €‰ މ ™‰ ¥‰ ±‰ ¼‰ ljÔ‰ó‰%Š.Š 7ŠEŠTŠ nŠ{ŠŠ —Š¤ŠªŠ ÇŠMÕŠ#‹ 7‹ D‹Q‹a‹ q‹{‹ ‹ Š‹•‹M«‹ù‹ ý‹ ŒŒ!Œ ;Œ IŒ VŒaŒ}Œ ›Œ¦ŒÖÆŒ| Ž (Ž6ŽHŽ \Ž}ޛ޲ŽÎŽèŽ[y“¥ ªµ ËØêý  ( I Ubu‘®'Éñ ‘ ‘‘ *‘ 6‘xA‘º‘&Б ÷‘’ !’.’A’.R’’š’#¯’gÓ“œ;”Ø”:ð”;+•9g•,¡•YΕ%(–N–Ff–­–/–*ò–"—‡@—È—Þ—'ý—<%˜4b˜>—˜BÖ˜>™?X™D˜™?Ý™9š9Wš=‘š@Ïš=›BN›>‘›>Л?œ=Oœ<œÊœÙœDáœ,&Sl~?¥å1ý/ž;NžŠžž­žÄžÝžôž Ÿ%Ÿ?ŸPŸfŸ>~Ÿ?½ŸýŸD %X 4~ ³ )Ë Xõ 2N¡Ì¡N¢U¢e¢v¢)…¢ ¯¢ º¢Ä¢Ø¢ê¢þ¢£#£6£"L£o£)„£ ®£¼£Ó£üÛ£ÐØ¤p©¥K¦f¦y¦¦“¦š¦Ÿ¦¦¦®¦ µ¦ ¿¦ ˦צ#è¦ §§",§WO§§§¶§¿§%Ú§¨¨¨0¨8¨<M¨Ѝ §¨ µ¨À¨GÙ¨'!©uI©=¿©Œý©6ŠªÁªSÒª1&«4X«7«;Å«¬¬ -¬7¬ G¬h¬¬ Ÿ¬ ­¬!¸¬ Ú¬!å¬ ­­)­;­N­ `­ n­­¥­º­Ú­á­é­ð­®®9®M®`®o® ®. ®Ï®Cå®)¯(@¯i¯A}¯¿¯.ݯ& °3° Q°^°w°°©° ²°À°а)à° ±`+±`Œ± í±ù±² 5²A²¨Y²>³‹A³ͳ ӳ߳ô³ ´)´ H´U´Y´b´ j´w´|´ “´ ´°´)Å´ï´ µ+µ@µ`µ vµƒµ—µªµʵÓµܵ&ïµ¶!2¶T¶e¶w¶“¶ ¤¶²¶Ͷ/ì¶·<·D·T·—[· ó¸)¹*¹S;¹ ¹-¹)˹bõ¹ XºEeº«º~ɺH»L^»4«»wà»X¼du¼Ú¼lò¼_½\}½4Ú½’¾¢¾g¶¾,¿SK¿Ÿ¿S·¿ ÀI,À$vÀm›À# Á-Á+­ÁqÙÁ K WÂcÂhÂmÂvÂ{ ÂœÂ °Â½ÂÆÂÕ é ÷ÂÃà 'Ã5ÃGà [ÃhÃyÃ‚Ã—à ªÃ´ÃÍÃáÃõÃÄ Ä &Ä3ÄGÄfÅ iÅ vÅ!„Å(¦Å.ÏÅ(þÅ)'Æ(QÆ zÆ(›Æ,ÄÆ-ñÆ,Ç-LÇ-zÇ-¨ÇÖÇÞÇrðÇcÈ;tȰÈÀÈÙÈïÈ É!É8É(TÉ(}É)¦É ÐÉÜÉîÉÊÊ:Ê#TÊ xÊ „ʥʷÊÏÊáÊ:ûÊ<6Ë„sËøË#ÌB%ÌBhÌC«ÌïÌôÌúÌ ÍÍ9Í BÍcÍ‚Í ™Í¤Í ©ÍµÍºÍÌÍâÍ*ñÍÎ*-ÎXÎ/lΜεΠÄÎ6ÐÎ Ï6Ï JÏ*VÏϊϓϢÏ2¹ÏìÏôÏ"÷ÏÐ*ÐGÐ+fÐ+’Ð,¾Ð!ëÐ ÑÑ)-Ñ%WÑ&}Ñ ¤Ñ°Ñ!ÊÑìÑÒÒ%Ò9ÒMÒSÒjÒyÒ+Ò¼ÒÅÒIÜÒû&Ó"Ô*Ô<ÔLÔ ]ÔkÔ Ô ‹Ô—Ô©Ô¾Ô#ÝÔÕ%Õ =ÕKÕ[ÕkÕ1{Õ ­Õ ºÕ ÄÕÎÕßÕðÕÖÖ:Ö3WÖ0‹Ö6¼Ö6óÖ6*×0a×5’×5È×6þ×·5ØíØ!üØ1ÙPÙ aÙ=oÙ­ÙÅÙÛÙñÙÚÚ:8Ú<sÚ2°Ú:ãÚ<Û;[Û=—Û4ÕÛ5 Ü7@Ü6xÜ6¯Ü6æÜKÝ3iÝ'ÝÅÝ'ÛÝNÞRÞiÞ‡ÞÞE¢Þ"èÞ# ß/ßOßkßXˆß-áßà'à-=àkàsà‘à©àÇàåàááD)á1náL áíá â5+â aâ3‚â2¶â&éâã/ãHã aã kãwãO‘ãáãGýãEä*Mä*xä£äÃäÝä*ùä$åDå#_åNƒå,Òå2ÿå2æƒMæ0Ñæ5ç68ç0oç ç¸çÉçÚçìçûçè£&è$Êèïèöè, éN6é …é’é¯é¶é½éÎéÝé òéþé êê-ê>ê Mê Zêeêmê€ê ›ê©ê¼êØêßê ðê,þê +ë9ë'Vë ~ë-Ÿë7ÍënìptìeåìrKíb¾íh!îiŠîôîïï ï8ïPïgïlïrïƒï“ï%¤ïÊï&Úï'ð()ð£Rðöð ñññ #ñ1ñQñ dñ qñ}ñ„ñšñ°ñÀñÅñ×ñíñ*üñ'ò*8òcò/wò8§òàò çò!óò"ó8óLó_óró„ó  ó¬óÇóæó7ô7<ôtô!Žô°ô!µô×ô(ôô(õ FõPõ_õnõ#~õ ¢õ­õ¾õ=ÑõöVöYmöVÇö;÷·Z÷Ýømðø–^ùèõùÞúõúûú)û>ûVûlû†û=œû4Úû ü ü(üCüZümüŠü/ü¿üÎü1íü"ý/Býrýý#’ý"¶ý/Ùý þ+*þ.Vþ…þRŒþßþ,åþ!ÿ4ÿ8ÿUÿlÿ.ƒÿ²ÿÐÿÔÿÝÿãÿûÿ 4FI ¢!¯Ññ, 6FMT[bu §°ÄÍÖ ì ú !$FZcjzúû— !¤,Æórù1l ž¨°-¹ç* >K ^l-—Å*Ý-FVlt|(…®_À ;  U !c !…  § ² · Ì Þ eþ d j } ” +¤ Ð *á  0! R j +z ¦ ® ? V p %Š !° Ò ñ  %@\†wþ!5 Wb‚’§¼ÒèIþH_(z5£5Ù66F.}¬³ÉÙñ™ ¤FÀ 98F 8Œ"ÅèV’\¥ï•H²HûID;ŽbÊM-{\–ó@*S)~ ¨I+f2’EÅ# O/TPÔO%TuPÊIJeO°UPVC§@ë@,@mA®Gð8 O bX ,» .è !3!R!9f! !?·!/÷!B'"!j"?Œ"Ì"æ"##>#X#w##«#7Ë#^$"b$B…$5È$;þ$&:%/a%T‘%9æ%ù &' !' -' 9'6F'}'†''¦'¾'Õ'í'((:<( w(>˜(×(é()* )6*ˆ;+KÄ+,/, H, T,a, f, p,},ƒ,‹, ”,ž,1¶,è,û,"-ˆ1-º- Ñ-Û-2õ-(.C.&L.s.{.0—.È.(á.+ /$6/M[/(©/uÒ/9H0™‚0A1^1gu1BÝ14 24U26Š2.Á2.ð23%353%N3%t3š3 ©37·3 ï37ý3 54B4_4|4”4±4+Â4î4 5%$5 J5 X5c5k5+€5+¬5Ø5ö56.6.H6=w6 µ6EÖ6'76D7{7]Ž7:ì77'8(_8%ˆ8®8(Ë8(ô8-9K9T9c9v9>‰93È9eü9eb:È:,â:!;1;#H;°l;I<šg<= ==,=C=3[==¡=¾=×=ï=>%>,>H>\>x>,”>Á>7Ø>,?=?W?j?€?!?²?Á?Ð?(æ?.@(>@g@@#”@!¸@Ú@ú@1A5KA(A ªA,µAâA©­Šçc©¢±:†P„h=~ bT_B+˜æ3e·uãþiIÌÛ’¼DÚ–Hñ¥þ“/?=@¯¬ôAJR¢ÿœ¡â‡ý†} 4HB5S i.K}º*l­Ëî£áÅÌ9¾ó…‰YÀuŽZp0¸ ªT7^´S¥n> MõobJwLÛA’"[ê5ÔÜXI>¤œy#+/-^d``ñ5ûêªgó P½C6pâ\m¸.ˆ¦G<-§W¤÷°Ÿ—^):*ôµ ä  „XØyÏÇf3.<…[ÚfUjfw YlV_nÏWÑtƒºë6~ÖI ÿ|³z%KÎöØ~»zÐÕu2AòþèÓ›®t¯¹ŒØ×º¾QmŠ>Iqá T |rÍ$VV+‘pP·ÇMYúõi6/ƒ(«qáe;Ñc*Æ%¶)8 üÇãÛ=×hg¿w§,r htm?9ßHs¿éí QZ&mWRhù_ð’ÿú:˜™=é_?ϨÜÂsÜgŒúd17›Ôð§ë3E™~ß®{.fGŸO "ô6W1q\ ÂðýC¼È'ûjÑ<)D‚#ÖN47ˆ$$å;FS“‘Ãñæ!cL›X-"d é£,õÃ(XȃM9äRøÔÅ¥Ja¹ã€4rý‰{|€E¨ç­pxAì•ײ Ê”LªžÝ‹öS0œZÒ ;g‡³Ó”8°4݆|n}`Ža#«ÒxÙš¬‹°¶dÆÖrÆ}viÌx7LyQ—0À,2@âÄ÷ЊH±„@ÕG¡b\CÉ´)¼2øjÍùš(Á?ÉÙ¦¾Á¨ sk+1zõŽŸ½aCeR<íßo Þ”Z[e¶NËüG“²2ëb 1µ‚ '8àtTï!žî'ˆ#wK™UnvQE¢ò(0@E]ö–9ÊB!U•üìkå%Ò]kÁo‡x{DFùl¸žÀ^Vï&‘&ï]c—ÙÕzàv÷Œ«OB3q]N-!ò‰·»%€UyÅê¹ûlÚÎ{s"$:æF¿¦‹¡ÐÝ»&K/J•NM ìOkįjËv®àÄÉÈ‚oèÓ>Pø–¤Êè´£FušÎåóa,±[5Í\8 '˜Y½;Þí²Þ³ç`¬…©Oä*Dî(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed10mm15mm2-pixel20mm2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF BackADF DuplexADF FrontADF ModeADF cover openADF jamAccess to resource has been deniedAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAlways switches lamp off when doing dark calibration.Analog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBackBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlackBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom to topBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessBuilt in CCT profileButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowCancel buttonChange Document.Change documentChannelChipset IDChipset nameClear calibrationClear calibration cacheCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor (48 bits)Color 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContinueContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Copy buttonCorrection according to film typeCorrection according to transparency ratioCover openCustomCustom color matrix for grayscale scans.Custom color matrix.DTCDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device busyDevice-SettingsDiamondDiffusionDisable auto document feeder and use flatbed onlyDisable backtrackingDisable dynamic lineartDisable gamma correctionDisable interpolationDisable pre focusDisable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart.Disable white shading correctionDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDocument feeder jammedDocument feeder out of documentsDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayDynamic threshold curve, from light to dark, normally 50-65EjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEmail buttonEmulate GrayscaleEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.End of file reachedEnhance BlueEnhance GreenEnhance RedEnhancementError DiffusionError during device I/OExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtend lamp timeoutExtends lamp timeout (from 15 minutes to 1 hour)Extra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFax buttonFeeder modeFile buttonFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce real depthForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFrontFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma correction will be disabledGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGeometry GroupGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHardware specific optionsHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHorizontal boldHorizontal narrowHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances.If enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, some images involved in scanner processing are saved to analyze them.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation.Ignore calibrationImageImage EnhancementImage colours will be invertedImage emphasisImage intensityImage modification optionsImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInformationInfraredInk-jet printersInt test optionsInvalid argumentInvert endiannessJPEGLamp not ready, please retryLamp offLamp off at exitLamp off during dark calibrationLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNeed calibrationNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOCR buttonOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOperation not supportedOperation was cancelledOptional equipmentOut of memoryPDF buttonPage heightPage loadedPage widthPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPower buttonPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset chipsetReset scannerReset the scannerResets chipset dataReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSDTCSaturationSave debugging imagesScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan Mode GroupScan area and media size optionsScan buttonScan counterScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Scanner cover is openScanner mechanism locked for transportScanner modelScanner sensors and buttonsSecond entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSensorsSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShows chipset name used in device.Shows the chipset IDShows the number of scans made by scannerShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSkip warmup processSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSource, mode and resolution optionsSpecial OptionsSpecial optionsSpecifies the height of the media.Specifies the width of the media. Required for automatic centering of sheet-fed scans.Speedup sensorStandardStart calibration process.Start calibration using special sheetStatus Code SimulationStopString test optionsSuccessSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.TMA NegativesTMA SlidesText Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.The scanner needs calibration for the current settingsThermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects a front panel scanner buttonThis option reflects the status of a scanner button.This option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold curveThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop to bottomTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnknownUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate informationUpdate optionsUpdate options.Updates information about deviceUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)User defined CCT profileVerticalVertical boldWait for ButtonWait for buttonWait to scan for front-panel button push.Waits for button before scanningWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup process will be disabledWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.WhiteWhite levelWhite level for blueWhite level for greenWhite level for redWhite shading correction will be disabledX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: sane-backends 1.0.19 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2008-01-17 22:25+0100 Last-Translator: Yann E. MORIN Language-Team: Language: fr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 0.9.5 (1/1) Bouton(1/1) Bouton de test. Affiche du texte...(1/3) Réel fixe(1/3) Option à valeur réelle (virgule fixe) sans unité ni domaine de variations.(1/3) Chaîne(1/3) Chaîne de caractères sans contrainte.(1/6) Modification et lecture logicielles(1/6) Option booléenne lisible et modifiable par l'application. C'est juste une option 'normale'.(1/6) Entier(1/6) Option à valeur entière sans unité ni domaine de variations.(2/3) Réel fixe avec domaine(2/3) Option à valeur réelle (virgule fixe) avec domaine de variations. Unité: µs. Min: -42,17. Max: 32767,9999. Pas: 2,0.(2/3) Chaîne listée(2/3) Chaîne de caractères dont les valeurs possibles sont dans une liste.(2/6) Modification matérielle et lecture logicielle(2/6) Option booléenne lisible par l'application et modifiable par le matériel (ex. un bouton sur le périphérique).(2/6) Entière avec domaine.(2/6) Option à valeur entière avec domaine de variations. Unité: pixel. Min: 4. Max: 192. Pas: 2.(3/3) Réel fixe listé(3/3) Option à valeur réelle (vurgule fixe) sans unité et dont les valeurs possibles sont dans une liste.(3/3) Chaine listée (longue)(3/3) Chaine de caractères dont les valeurs possibles sont dans une liste. Plus de choix...(3/6) Option booléenne modifiable par le matériel.(3/6) Option booléenne modifiable par le matériel (ex. un bouton sur le périphérique) et dont le status ne peut pas etre lu par l'application.(3/6) Entier listé(3/6) Option à valeur entière dont les valeurs possibles sont contenues dans une liste. Untié : bit.(4/6) Option booléenne lisible par logiciel(4/6) Option booléenne lisible par le logiciel. Cette option est en lecture seule.(4/6) Tableau d'entiers(4/6) Tableau d'options à valeur entière sans domaine de variations. Unité : mm.(5/6) Option booléenne émulée(5/6) Options booléenne émulée, lisible et modifiable par le logiciel.(5/6) Tableau d'entiers avec domaine(5/6) Tableau d'options à valeur entière avec domaine de variations. Unité: dpi. Min: 4. Max: 192. Pas: 2.(6/6) Option booléenne automatique(6/6) Option booléenne lisible et modifiable par le logiciel. Cette option peut être modifiée automatiquement par le pilote.(6/6) Tableau d'entiers à valeurs listées(6/6) Tableau d'options à valeur entière dont les valeurs possibles sont contenues dans des listes. Unité : %.Vitesse 1/2Vitesse 1/310mm15mm2 pixels20mm2x2 - Personnalisé2x2 - Normal3x3 - Personnalisé3x3 - Normal4 pixels4x4 - Grossier4x4 - Personnalisé4x4 - Précis4x4 - Normal5x5 - Grossier5x5 - Personnalisé5x5 - Précis6"x4" (~15x10 cm)6x6 - Personnalisé6x6 - NormalSortie en 8 bits8 pixels8.5"x11" (~21x28 cm)8"x10" (~20x25 cm)Bayer 8x8"Graissage" grossier 8x8"Graissage" fin 8x8Ligne verticale 8x88x8 - Grossier8x8 - Personnalisé8x8 - Précis8x8 - Normal8x8 - Très précisUn temps d'exposition plus long permet au scanner de recevoir plus de lumière. Les valeurs suggérées sont : 175% pour des impressions, 150% pour des diapositives normales, et "Négatif" pour des négatifs. Pour les images sombres (sous-exposées), vous pouvez augmenter cette valeur.A4A5 - paysageA5 - portraitChargeur automatique de documentsChargeur automatique de documents, versoChargeur automatique de documents, recto-versoChargeur automatique de documents, rectoMode du chargeur automatique de documentsCouvercle du chargeur automatique ouvertBourrage du chargeur automatiqueL'accés à la ressource a été refuséAjoute au bleu en fonction du niveau de vertAjoute au bleu en fonction du niveau de rougeAjoute au vert en fonction du niveau de bleuAjoute au vert en fonction du niveau de rougeAjoute au rouge en fonction du niveau de bleuAjoute au rouge en fonction du niveau de vertAvancéOptions avancéesAprés avoir envoyé la commande de numérisation, attendre l'appui du bouton avant de commencer la numérisation.Toutes les pagesToujours éteindre la lampe durant la calibration des noirsGain analogiqueFrontal analogique (AFE)Gamma analogique bleuCorrection gamma analogiqueGamma analogique vertGamma analogique rougeCorrection gamma analogiqueCorrection gamma analogique pour le bleuCorrection gamma analogique pour le vertCorrection gamma analogique pour le rougeAutomatiqueSeuil automatiqueSéparation automatiqueEjection automatiqueTemps d'exposition automatiqueMise au point automatiqueUne seule mise au point automatiqueAutomatiqueChargeur automatique de documentSeuil automatiqueSéparation automatiqueSeuil automatiquePréchauffage automatiqueEjecte automatiquement le film après chaque numérisationEjecte automatiquement le film avant de quitter le programmeFixe automatiquement la luminosité, le contraste, le niveau du blanc, le gamma, la réduction du bruit et l'accentuation de l'imageArrièreNombre de lignes de retour arrièreFacteur de balance des bleus. 100% équivaut à pas de correction.Facteur de balance des verts. 100% équivaut à pas de correction.Facteur de balance des rouges. 100% équivaut à pas de correction.BaieBayer'Dither' Bayer 16'Dither' Bayer 64Noir et blanc (mode trait)Lier RVBLier les échantillonnage X et YLier les gamma analogiques RVBLier les valeurs gammaProfondeurNoirNiveau noirBleubalance des bleusLuminosité des bleusGain des bleusGain des bleus du frontal analogique (AFE)Intensité bleueDélai avant extinction de la lampe bleue.Décalage des bleusDécalage des bleus du frontal analogique (AFE)Options test - booléensDe bas en hautX bas-droitPosition X en bas à droite de l'aire de numérisationY bas-droitPosition Y en bas à droite de l'aire de numérisationLuminositéProfil de température de couleurs interneBouton 1Bouton 2Etat du boutonOptions test - boutonsNumérisation contrôlée par le bouton du scannerBoutonsCDerreur de test du processeur (CPU)Tube cathodiqueMoniteurs à tube cathodiqueCalibrer le temps d'expositionCalibrer le temps d'exposition pour le bleuCalibrer le temps d'exposition pour le vertCalibrer le temps d'exposition pour le rougeCalibrer la puissance de la lampeCalibrationCalibrer le scannerCalibrer avant la prochaine numérisationCalibre la lentille en mode document.Calibration des niveaux noir et blanc.CalibrationCalibration par le piloteCache des données de calibrationMode de calibrationCalibrer maintenantBouton 'annuler'Change de document.Changer de documentCanalIdentifiant de la puceNom de la puceEffacer la calibrationEfface le cache des données de calibrationGrossierCalibration grossièreUtiliser la calibration grosière seulement à la première numérisationLa calibration grossière est effectuée uniquement à la première numérisation. Fonctionne avec la plupart des scanners et peut faire gagner du temps. Si l'intensité de chaque image est différente, désactiver cette option. Seulement pour tester.CouleurCouleur (48 bits)Couleur 36 bitsDemi-ton couleurTrait couleurMatrice de couleursCouleur RAWCouleur RGBCouleur RGB TEXTEBalance des couleursRéglages de gain des couleursRéglages de décalage des couleursCorrection de couleurCoefficients de correction de couleurMotif couleurCouleur 24 bitsCouleur 36 bitsCouleur 48 bitsNombre de lignes en couleurs par cycle de lectureConditionnelContinuerContrasteContraste - bleuContraste - vertContraste - rougeContrôle le niveau de bleuContrôle le niveau de vertContrôle le niveau de rougeContrôle la teinte (bleue) de l'image numérisée.Contrôle la brillance de l'image à numériser.Contrôle la brillance bleue de l'image à numériser.Contrôle la brillance verte de l'image à numériser.Contrôle la brillance rouge de l'image à numériser.Contrôle le contraste de l'image à numériser.Contrôle le contraste bleu de l'image à numériser.Contrôle le contraste vert de l'image à numériser.Contrôle le contraste rouge de l'image à numériser.Si l'interface à laquelle votre scanner est connectée n'est pas assez rapide, cette option ne permettra pas de reprendre la numérisation, et les données manquantes seront perdues.Bouton 'copie'Correction en fonction du supportCorrection en fonction du rapport de transparenceCouvercle ouvertPersonnaliséMatrice personnalisée pour numérisation en niveaux de gris.Matrice personnalisée.Seuil dynamique (DTC)Options de déboggageValeur par défautValeurs par défautDéfinit le mode de calibrationDéfinit le temps d'exposition pour la calibration du bleuDéfinit le temps d'exposition pour la numérisation du bleuDéfinit le temps d'exposition pour la calibrationDéfinit le temps d'exposition pour la calibration du vertDéfinit le temps d'exposition pour la numérisation du vertDéfinit le temps d'exposition pour la calibration du rougeDéfinit le temps d'exposition pour la numérisation du rougeDéfinit le temps d'exposition pour la numérisationDéfinit la puissance de la lampe pour la calibrationDéfinit la puissance de la lampe pour la numérisationDéfinit le délai avant extinction de la lampe bleue.Définit le délai avant extinction de la lampe verte.Définit le délai avant extinction de la lampe rouge.Définit le motif de demi-ton utilisé pour numériser les images demi-ton.Définit le facteur de zoom utilisé par le scannerRetarde le transfert des données lues.Contrôle de densitéDétermine la vitesse de numérisation.Détermine si une table gamma standard ou personnalisée doit être utilisée.Périphérique occupéParamètres du périphériqueDiamantDiffusion d'erreurNe pas utiliser le chargeur automatique, seulement le scanner à platNe pas utiliser de retour arrièreDésactiver le mode Trait dynamiqueDésactiver la correction gammaDésactiver l'interpolationDésactiver la mise au pointUtilise le mode Trait du matériel, au lieu d'utiliser un algorithme logiciel adaptatif.Désactiver la correction des ombres blanchesPoints dispersés 16x16Points dispersés 8x8Affiche une liste réduite d'échantillonnageTramage/wiki/Filmstrip A (Bayer 4x4)'Dither' B (Spiral 4x4)'Dither' C ('Net Screen' 4x4)'Dither' C ('Net Screen' 4x4)Noir et blanc (mode tramé)Carte de 'dither' 1Carte de 'dither' 2Effectue une numérisation en niveaux de gris plutôt qu'en couleursFaire une calibration de qualité pour les blancsEffectuer la mise au point automatique une seule fois entre chaque éjectionNe calibre pas la mise au pointNe pas forcer le code d'étatNe pas obliger le pilote à renvoyer un code d'état.Chargeur automatique de documentChargeur automatique de document, options avancéesBourrage dans le chargeur automatique de documentsChargeur automatique de documents videDoubler la résolution optiqueTélécharger le motif ATélécharger le motif BExclusionRecto-versoNumérisation recto-versoLa numérisation recto-verso permet de numériser les deux cotés d'un documentDurée du délai de lectureCourbe dynamique de seuil, de clair à foncé, normallement entre 50-65EjecterEjecte le document après la numérisationEjecte le film après chaque numérisationEjecte le film avant de quitterEjecte le film maintenantEjecte le film *maintenant*Ejecter la feuille du chargeur automatiqueBouton 'courrier électronique'Simuler en niveaux de grisActive la numérisation recto-versoActive la détection automatique du seuil pour la numérisation en mode trait.Autorise la sélection du temps d'expositionAutorise la sélection de la puissance de la lampeActive les options de testActive diverses options de test. Pour tester la capacité des applications à obtenir et modifier tous les types d'options de SANE.Activer/désactiver la mise au point automatiqueActiver/désactiver le temps d'exposition automatiqueActive/désactive le cache des données de calibrationActive l'accélération du mouvement du capteur.Fin de fichier atteinteAugmente le bleuAugmente le vertAugmente le rougeRéglages finsDiffusion d'erreurErreur d'entrée-sortieInverse les octets de poids faible et de poids fort dans les résolutions à 1- bits. Ce peut-etre utile pour tester le support petit/grand indien d'une interface.Effectue la calibration *maintenant*EssaisTemps d'expositionDélai allongé avant extinction de la lampeAllonge le délai avant l'extinction de la lampe (de 15 minutes à une heure).Très rapidePlus de réglages de couleurExtrasRapideMode gris rapideAperçu rapideNumérisation rapidePlus rapideLe plus rapideBouton 'Fax'Mode de chargementBouton 'fichier'Nom de fichierType de filmFilm-stripPrécisCouleurs précisesBalance (valeurs d'usines)Premier choixMise au point fixeOptions test - réels fixesA platA plat seulementMise au pointMettre au point 2,5 mm au-dessus de la vitreMise-au-pointMettre au point sur la vitreForcer l'utilisation du retour arrièreForce l'aperçu en noir et blancForcer l'utilisation de la profondeur réelleForcer la calibration du scanner avant la numérisationOblige le pilote à renvoyer le code SANE_STATUS_ACCESS_DENIED (acces refusé) après un appel à sane_read().Oblige le pilote à renvoyer le code SANE_STATUS_COVER_OPEN (couvercle soulevé) après un appel à sane_read().Oblige le pilote à renvoyer le code SANE_STATUS_EOF (fin de fichier) après un appel à sane_read().Oblige le pilote à renvoyer le code SANE_STATUS_IO_ERROR (erreur d'entrée/sortie après un appel à sane_read().Oblige le pilote à renvoyer le code SANE_STATUS_JAMMED (bourrage) après un appel à sane_read().Oblige le pilote à renvoyer le code SANE_STATUS_NO_DOCS (pas de ) après un appel à sane_read().Oblige le pilote à renvoyer le code SANE_STATUS_NO_MEM (pas de mémoire) après un appel à sane_read().Avec du papierAvec le batonnet blancAvantAttente de bouton avantNumérisation complèteParamètres délirantsGainGammaCorrection gammaTables de gammaCorrection gammaLa correction gamma sera désactivéeValeur de gammaTable de correction gamma pour le bleuTable de correction gamma pour le vert.Table de correction gamma pour le rouge.Table de correction gamma. En mode couleur, cette option affecte simultanément les bandes rouge, verte et bleue (c.-à-d. que c'est une table gamme d'intensité.)Aire de numérisationGéométrieGrainGrisGain des grisCouleur du mode niveaux de grisDécalage des grisGris 16 bitsGris 8 bitsGriserNiveau de gris 4 bitsNiveau de gris 8 bitsNiveaux de grisVertbalance des vertsLuminosité des vertsGain des vertsGain des verts du frontal analogique (AFE)Intensité verteDélai avant extinction de la lampe verte.Décalage des vertsDécalage des verts du frontal analogique (AFE)Nombre de lignes en niveaux de gris par cycle de lectureGrilleDemi-teinteMotif demi-teinte A (teinte dure)Motif demi-teinte B (teinte douce)Motif demi-teinte CDemi-ton 32 pointsDemi-ton 64 pointsMotif demi-teinteTaille du motif demi-teinteDemi-teinteDemi-teinte non-supportéeSimulation de scanner à main.Simulation de scanner à mainPosition X en haut à gauche de l'aire de numérisationPosition Y en haut à gauche de l'aire de numérisationEchantillonnage matérielOptions spécifiques au matérielHautImpression avec contraste élevéImpression haute définitionQualité maximale, mais vitesse réduiteVitesse maximale, mais qualité réduiteContrasteContraste bleuContraste vertContraste rougeMise au point au niveau de la vitreHorizontalHorizontal largeHorizontal étroitTemps à attendre après avoir transféré les données lues.TeinteSi le chargeur de document est sélectionné, il sera 'vide' après 10 numérisations.Lorsque sélectionné, le pilote détermine automatiquement la meilleure valeur du seuil.Lorsque sélectionné, la calibration avant numérisation est effectuée par le piloteSi sélectionné, le scanner ne fera pas de retour arrièreSi activé, l'image sera numérisée en couleurs, puis convertie em niveaux de gris par logiciel. Cela peut permettre d'améliorer la qualité de l'image dans certaines circonstances.Si activé, seule la correction des ombres est effectuée pendant la calibration. Les valeurs par défaut du gain, le décalage et le temps d'exposition, internes ou lues dans le fichier de configuration, sont utilisées.Si activé, les images intermédiaires utilisées pendant la numérisation seront sauvegardées pour analyse.Si activé, le scanner sera calibré avant la prochaine numérisation. Sinon la calibration est effectuée seulement avant la première numérisation.Si la correction gamma est activée, la numérisation sera toujours effectuée en 16 bits par couleur pour améliorer la qualité de l'image, puis convertie dans la profondeur demandée. Cette option évite de simuler la profondeur.Ignorer la calibrationImageAmélioration de l'imageLes couleurs de l'image seront inverséesAccentuation de l'imageIntensité de l'imageOptions modifiant l'imageImprimantes à impactUtilise les même paramètres pour chaque couleur en mode RVBAugmenter/diminuer le gain analogique du capteur CCDInformationsInfra-rougeImprimantes à jet d'encreOptions test - entiersArgument incorrectInversion petit/grand indienJPEGLa lampe n'est pas prète, veuillez ré-essayerLampe éteinteEteindre la lampe à la sortieEteindre la lampe durant la calibration des noirsTemps avant extinction de la lampeTemps avant extinction de la lampe (en minutes)Lampe alluméeEtat de la lampeDélai avant extinction de la lampeTemps avant extinction de la lampeTemps avant extinction de la lampe en secondes.Eteindre/allumer la (les) lampesCalibration de la lentille en mode documentVoyons si l'interface traite correctement ceciLetterLimite la quantité de données qui sont transmises à chaque appel à sane_read()TraitCharger l'image en tant que niveaux de gris.Nombre de pixels perdus par ligneBasImpression basse définitionMise au point manuelleMise au point manuelleEteindre/allumer la (les) lampes manuellement.Matrice de multiplication RGBMaxDocumentMoyenManiement des documentsTeinte moyenneTeinte moyenne bleueTeinte moyenne verteTeinte moyenne rougeDélai en minutes avant d'éteindre la lampe après une numérisation.Miroir horizontalImage miroirRenverse l'image horizontalement.Renverse l'image verticalement.Image miroir horizontalEffectue une symétrie verticale de l'image.Miroir verticalDiversMode 1Mode 2Mode 3Matrice monochromeCouleur RVB (une passe)Niveaux de grisGris NTSCRVB NTSCCalibration requiseNégatifNégatifDiapositive négativeFilm négatifFilm négatifNégatifsPas de correctionPas de correction de transparenceRéduction du bruitAucun(e)NormalVitesse normaleNombre de bits par échantillon. Les valeurs typiques sont de 1 pour "Trait" et de 8 pour les numérisation "haute-résolution"Lorsque le scanner scanne plus vite qu'il ne peut envoyer les données, il doit ramener le chariot du capteur en arrière afin de reprendre la numérisation. Des valeurs petites permettent une numérisation plus rapide, au risque de perdre quelques lignes.Nombre d'optionsNombre de lignes à transférer en un cycle de lecture SCSI. Changer ce paramètre vous permet de contrôler la vitesse à laquelle les données sont lues à partir du scanner. Une valeur trop basse obligera le scanner à faire des pauses lors du transfert, tandis qu'une valeur trop élevée pourrait empécher les applications Xwindow de traiter les évènements X, et votre système pourrait s'écrouler.Numéro de la trame à numériserBouton 'reconnaissance de caractères (OCR)'AucunPrésente un descripteur de fichier de type select(2) pour tester si un appel a sane_read() renverra des données.Proposer un descripteur de fichier pour select(2)DécalageActivéUne pageEffectuer uniquement la correction des ombresOpération non-supportéeOpération annuléeEquipement optionnelA court de mémoireBouton 'PDF'Hauteur de la pagePage chargéeLargeur de la pageTaille du papierDirectEffectue le diagnostic automatique du scannerEffectue la calibrationTaille physique du papier dans le chargeurPositifPositifDiapositive positiveFilm positif ou négatifBouton 'marche'Valeurs prédéfiniesAperçuAperçuImprimerAffiche une liste de toutes les options.Liste des optionsFournit des emplacements standards pour la numérisation de photos, de pages imprimées, etc...Calibration de la qualitéNumérisation de qualitéFormat rapideerreur de test de la mémoire RAMerreur de test de la mémoire ROMAléatoireBrutDélai à la lectureLimite de lectureOption de test de lecture seuleOption, lecture seule, qui indique le nombre d'options supportées par un périphérique spécifique.RougeBalance des rougesLuminosité des rougesGain des rougesGain des rouges du frontal analogique (AFE)Intensité rougeDélai avant extinction de la lampe rouge.Décalage des rougesDécalage des rouges du frontal analogique (AFE)Réduit le bruit isoléRéfléchissantDemande une numérisation de basse qualitéRequière que toutes les prévisualisations soient faites en monochrome. Sur un scanner à 3 passes, cela réduit le nombre de passes à 1. Sur un scanner à 1 passe, cela réduit l'espace mémoire nécessaire et le temps de numérisation de la prévisualisation.Les aperçus seront effectués dans le mode le plus rapide (basse qualité). Ce peut etre en noir et blanc, et/ou dans une basse en résolution.Réinitialiser la puceRéinitialiser le scannerRéinitialiser le scannerRéinitialise les données de la puceRenvoie SANE_STATUS_ACCESS_DENIEDRenvoie SANE_STATUS_COVER_OPENRenvoie SANE_STATUS_EOFRenvoie SANE_SATUS_IO_ERRORRenvoie SANE_STATUS_JAMMEDRenvoie SANE_STATUS_NO_DOCSRenvoie SANE_STATUS_NO_MEMRenvoie des valeurs abhérantes pour le nombre de lignes et d'octets par ligne quand sane_parameters() est appelé avant sane_start().Valeur de retour de sane_read()erreur de parité SCSISeuil dynamique simplifié (SDTC)SaturationSauver les images de déboggageValeur de gammaValeur de gamma bleuValeur de gamma vertValeur de gamma rougeMode de numérisationMode de numérisationOptions de la zone de numérisation et la taille de l'image à numériserBouton 'numérisation'Compteur de numérisationsTemps d'exposition pendant numérisationTemps d'exposition pour le bleu pendant numérisationTemps d'exposition pour le vert pendant numérisationTemps d'exposition pour le rouge pendant numérisationNumérise rapidement en mode gris (qualité réduite).Puissance de la lampe pendant la numérisationMargesMode de numérisationEchantillonnageSource de numérisationVitesse de numérisationNumérise la totalité de la surface, en incluant les bandes de calibration. ATTENTION! Ne pas sélectionner la hauteur complète. Seulement pour tester.Couvercle du scanner ouvertLe méchanisme de blocage pour le transport du scanner est vérouilléModèle de scannerCapteurs et boutons du scannerSecond choixSélectionne la baie contenant le document à numériserType de filmChoisit la luminosité minimum pour avoir un point blancSélectionne le filtre de lissage.Sélectionne le type de filmSélectionne le type d'image de test parmi : Noir complet : la numérisation est toute noire. Blanc complet : la numèrisation est toute blanche. Motif en couleurs : la numérisation est composée de différents motifs, en fonction du mode. Grille : la numérisation donne une grille noire sur fond blanc, dont lescarrés font 10 mm de coté.Sélectionne le mode de prévisualisation. Les aperçus en niveaux de gris donnent habituellement le meilleur compromis entre vitesse et détails.Fixe la valeur de retour de sane_read(). "Défaut" sélectionne le fonctionnement normal pour la numérisation. Toute autre valeur permet de tester les applications.Sélectionne l'image de testSélectionne une valeur numérique pour la correction gamma (canal bleu)Sélectionne une valeur numérique pour la correction gamma (canal vert)Sélectionne une valeur numérique pour la correction gamma (canal rouge)Sélectionne une valeur numérique pour la correction gammaSélectionne le "grain" de l'image numérisée. De petites valeurs donnent des images plus nettes.Sélectionne le mode du chargeur automatique de documents (recto/recto-verso)Sélectionne la brillance.Sélectionne la bande de couleur, "Toutes" signifie que toutes les couleurs sont affectées.Sélectionne le couleur exclu.Sélectionne le type de transparents (négatifs ou diapositives)Sélectionne la courbe de correction gammaSélectionne le mode de correction gamma.Selectionne la correction gamma à partir d'une liste de périphériques pré-configurés ou de la table utilisateur, et qui sera téléchargée dans le scannerSélectionne la demi-teinte.Sélectionne l'utilisation de film négatifSélectionner le numéro de la trame à numériserChoisit le mode de numérisation (comme Trait, Monochrome ou Couleur)Choisit la source de numérisation.Spécifie quel niveau de luminosité bleue est considéré comme étant "noir".Spécifie quel niveau de luminosité bleue est considéré comme étant "bleu max.".Spécifie quel niveau de luminosité bleue est considéré comme étant "blanc".Spécifie quel niveau de luminosité verte est considéré comme étant "noir".Spécifie quel niveau de luminosité verte est considéré comme étant "vert max.".Spécifie quel niveau de luminosité verte est considéré comme étant "blanc".Spécifie quel niveau de luminosité est considéré comme étant "noir".Spécifie quel niveau de luminosité est considéré comme étant "blanc".Spécifie quel niveau de luminosité rouge est considéré comme étant "noir".Spécifie quel niveau de luminosité rouge est considéré comme étant "rouge max.".Spécifie quel niveau de luminosité rouge est considéré comme étant "blanc".Spécifie si l'image numérisée doit etre en demi-teinte (tramée)Sélectionne le niveau de luminosité équivalant à "50% bleu".Sélectionne le niveau de luminosité équivalant à "50% gris".Sélectionne le niveau de luminosité équivalant à "50% vert".Sélectionne le niveau de luminosité équivalant à "50% rouge".Sélectionne la couleur à utiliser en niveaux de gris (défaut: vert).Diagnostic automatiqueCapteursSélectionne les valeurs par défaut pour les contrles d'amélioration (luminosité et contraste).Valeurs par défaut pour les réglages fins.Positionne le mode de contrôle de la densitéFixer le temps d'expositionFixer la puissance de la lampeChoisir la nettetéEffectuer manuellement la mise au point (128 par défaut)Fixe l'orde des tramesFixe l'ordre des trames dans une numérisation à trois passes.Sélectionne la matrice de couleurs du scanner.Fixe le temps (en minutes) au-delà du quel la lampe est éteinte.Sélectionne le type de document.Activer/déactiver l'adaptateur universel de transparents (UTA)Fixe le gain pour le bleuFixe le décalage pour le bleuFixe le gain pour le grisFixe le décalage pour le grisFixe le gain pour le vertFixe le décalage pour le vertAllume/éteint la lampe.Fixe le gain pour le rougeFixe le décalage pour le rougeRègle les valeurs de balance avec les valeurs d'usine.Remplit la table de correction de couleur pour le périphérique de destination sélectionné.Sélectionne le mode de chargementEffectue la mise-au-point soit sur la vitre, soit 2,5 mm au-dessusSélectionne la valeur de gamma pour tous les canaux.Choisit la résolution horizontale de l'image à numériserSélectionne l'accentuation de l'imageChoisit la résolution de l'image à numériserChoisit la taille du motif de demi-ton utilisé pour numériser les images demi-ton.Choisit la résolution verticale de l'image à numériserRenseigne automatiquement le gain et le décalage pour numériser. Lorsque cette option n'est pas activée, il est possible de renseigner manuellement les paramètres gain et décalage dans l'application. Activée par défaut. Pour tester seulement.OmbréOmbré bleuOmbré vertOmbré rougeOmbrage, teinte moyenne, contraste, temps d'expositionNettetéNettetéDécalage bleu -> vertDécalage bleu -> rougeDécalage vert -> bleuDécalage vert -> rougeDécalage rouge -> bleuDécalage rouge -> vertListe réduite de résolutionsAffiche le nom de la puce utilisée dans le périphériqueAffiche l'identifiant de la puceAffiche le nombre de numérisations effectuées par le scannerEteindre la lampeEteint la lampe du scanner.RectoSimule un scanner à main. Les scanners à main ne connaissent pas à priori la hauteur de l'image. A la place, ils renvoient une auteur de -1. Sélectionner cette option permet de tester si une interface peut le supporter correctement. Cette option fixe aussi la largeur de numérisation à 11 cm.Simule une numérisation avec un scanner à main. Les scanners à main ne connaissent pas à priori la hauteur de l'image. A la place, ils renvoient une hauteur de -1. Sélectionner cette option permet de tester si une interface peut le supporter correctement.Simule une numérisation à trois passes, en renvoyant 3 trames séparées. Pour le fun, renvoie la trame verte, puis bleue, puis rouge.Simule une numérisation à trois passes, en renvoyant 3 trames séparées.Taille de la limite de lectureOmettre le préchauffageDiapositiveDiapositivesLentPlus lentLe plus lentLisseLissageNoir purBlanc purSélection de la sourceOptions pour la source, le mode et la résolutionOptions spécialesOptions spécialesSpécifie la hauteur de la source.Spécifie la largeur de la source. Requis pour le centrage automatique des numérisations effectuées à partir du chargeur automatique.Accélérer le capteurGénéralDémarrer la calibration.Démarrer la calibration avec la feuille spécialeSimulation du code d'étatArréterOptions test - chaînes de caractèresSuccèsInverse le noir et le blancAllumer/éteindre l'adaptateur pour transparentsAllume/éteint la lampe.Adaptateur pour transparents - négatifsAdaptateur pour transparents - diapositivesTechnologie d'amélioration du texteLa taille maximale des données transférées à chaque appel à sane_read().Le nom de fichier de l'image à charger.La lampe sera éteinte après ce laps de temps (en minutes). Entrer 0 pour ne pas éteindre la lampe automatiquement.Le nombre de pixels perdus à la fin de chaque ligne lue.Le niveau de saturation contrôle l'éclairage qui se produit lors de l'acquisition par un appareil-photo. Une valeur importante cause plus d'éclairage.Le scanner a besoin d'être calibré avec les paramètres actuelsImprimantes thermiquesCeci est la troisième entrée, la plus longue. Peut-etre l'application sait-elle comment l'afficher...Cette option reflète l'état d'un bouton de la façade du scannerCette option affiche l'état d'un bouton du scanner.Cette option affiche l'état des boutons du scanner.Cette option éteint la lampe pendant la numérisationSimulation d'une numérisation à trois passesSimulation d'une numérisation à trois passesSeuilCourbe du seuilSeuil pour le mode traitAllumer/éteindre la lampe du scannerAllumer/éteindre la lampe du scannerDe haut en basX haut-gauchePosition X en haut à gauche de l'aire de numérisationY haut-gauchePosition Y en haut à gauche de l'aire de numérisationTransparenceAdaptateur pour transparentsAdaptateur pour transparentsRapport de transparenceAdaptateur pour transparentsEteint la lampe.Eteindre la lampe à la sortie du programmeEteint la lampe du scannerAllume la lampe du scannerEteint la lampe du scanner maintenantActiver l'UTAInconnu(e)EjecterEjecter le document.Ejecter le document après la numérisationEjecte le document après la numérisation.Rafraîchir l'état du boutonRafraîchir les informationsMettre les options à jourMets à jour les options.Rafraîchit les informations du périphériqueEffectue la mise au point à 0mm de la vitre au lieu de 0.6mmUtiliser la composition d'imagesUtilise plus de 8 bits de profondeur en interne, mais sort en 8 bits.Utiliser une table gamma personnaliséeUtilise une lentille qui double la résolution optiqueE/S non bloquantesUtilise un méchanisme d'E/S non bloquantes pour sane_read(), si supporté par l'application.Utilise seulement les valeurs d'échantillonnage matérielUtilise la même valeur gamma pour toutes les couleurs.Utilise la même résolution pour X et YUtiliser l'adaptateur de diapositivesSpécifié par l'utilisateurSpécifié par l'utilisateur (gamma=1,0)Spécifié par l'utilisateur (gamma=1,8)Profil de température de couleurs utilsateurVerticalVertical largeAttendre le boutonAttendre le boutonAttendre l'appui sur le bouton du scanner avant de numériser.Attend l'appui sur le bouton avant la numérisationPréchauffer jusqu'à ce que l'intensité de la lampe soit constante, au lieu d'attendre 40 secondes.Préchauffer jusqu'à ce que l'intensité de la lampe soit constante, au lieu d'attendre 60 secondes.Préchauffage de la lampePréchauffer la lampe avant la numérisationLe préchauffage sera désactivéTemps de préchauffageTemps de préchauffage en secondes.Si activé, la numérisation commencera à l'appui du bouton "SCAN" (MP150), ou du bouton "COLOR" (autres modèles). Appuyez sur le bouton "GRAY" pour annuler la numérisation.En niveaux de gris ou en mode trait, sélectionne la couleur à utiliser.Pour de hautes résolutions, et lorsque la résolution horizontale est plus faible que la résolution verticale, ne pas faire d'interpolation horizontale.BlancNiveau blancNiveau blanc des bleusNiveau blanc des vertsNiveau blanc des rougesLa correction des ombres blanches sera désactivéeEchantillonnage XAdaptateur pour transparentsGris (pour transparents)RVB (pour transparents)Echantillonnage YZoomerreur dans la séquence de commandesnumériseur de transparentsnumériseur à platerreur de test du matérielmessage d'erreur détecté message d'identification (IDENTIFY) invalidecode commande invalidechamp du bloc de description de commande (CDB) invalidechamp invalide dans la liste des paramètresmessage d'erreur invalidelampe défectueuselampe non stabiliséedocument absentpas d'information supplémentairedécalage en Xdécalage en Yoption non connectéeparamètre modifié par un autre maîtrelongueur de la liste de paramètres incorrecteRéinitialisation au démarrage / du buséchec de re-sélectionParamètres arrondiserreur de positionnement du capteurscanner avec chargeur automatiqueerreur de dépassement de tempstrop de fenêtres spécifiéeslampe de l'adaptateur de transparent défectueuseerreur de positionnement du capteur pour transparentserreur de l'adaptateur pour transparentsinconnu(e)Numéro d'unité logique (LUN) non supportéwebcamsane-backends-1.0.27/po/nl.po0000664000175000017500000050462113110600537012615 00000000000000# translation of sane-backends.nl.po to Nederlands # Dutch translation for SANE backend options # Copyright (C) 2002 SANE Project. # Martin Kho , 2003, 2009. # Bertrik Sikken , 2003. # Martin Kho , 2010. # Martin Kho , 2011, 2012, 2013, 2015, 2017. msgid "" msgstr "" "Project-Id-Version: sane-backends.nl\n" "Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org\n" "POT-Creation-Date: 2017-05-22 11:18-0400\n" "PO-Revision-Date: 2017-05-19 17:02+0100\n" "Last-Translator: Martin Kho \n" "Language-Team: English \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 2.0\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: include/sane/saneopts.h:154 #, no-c-format msgid "Number of options" msgstr "Aantal opties" #: include/sane/saneopts.h:156 #, no-c-format msgid "Standard" msgstr "Standaard" #: include/sane/saneopts.h:157 backend/artec_eplus48u.c:2884 #: backend/epson.c:3298 backend/epson2.c:1291 backend/genesys.c:5618 #: backend/gt68xx.c:703 backend/hp3500.c:1019 backend/hp-option.c:3297 #: backend/kvs1025_opt.c:640 backend/kvs20xx_opt.c:285 #: backend/kvs40xx_opt.c:506 backend/leo.c:823 backend/lexmark.c:199 #: backend/ma1509.c:551 backend/matsushita.c:1135 backend/microtek2.h:599 #: backend/mustek.c:4361 backend/mustek_usb.c:305 #: backend/mustek_usb2.c:465 backend/pixma_sane_options.c:160 #: backend/plustek.c:808 backend/plustek_pp.c:747 backend/sceptre.c:702 #: backend/snapscan-options.c:550 backend/teco1.c:1095 #: backend/teco2.c:1914 backend/teco3.c:920 backend/test.c:647 #: backend/u12.c:546 backend/umax.c:5176 backend/umax_pp.c:580 #, no-c-format msgid "Geometry" msgstr "Geometrie" #: include/sane/saneopts.h:158 backend/artec_eplus48u.c:2805 #: backend/canon.c:1498 backend/genesys.c:5678 backend/gt68xx.c:672 #: backend/hp-option.c:2953 backend/kvs1025_opt.c:704 backend/leo.c:871 #: backend/ma1509.c:599 backend/matsushita.c:1189 backend/microtek2.h:600 #: backend/mustek.c:4409 backend/mustek_usb.c:353 #: backend/mustek_usb2.c:431 backend/niash.c:754 backend/plustek.c:854 #: backend/plustek_pp.c:793 backend/sceptre.c:750 #: backend/snapscan-options.c:617 backend/stv680.c:1067 #: backend/teco1.c:1143 backend/teco2.c:1962 backend/teco3.c:968 #: backend/u12.c:592 backend/umax.c:5226 backend/umax_pp.c:629 #, no-c-format msgid "Enhancement" msgstr "Kleurverbetering" #: include/sane/saneopts.h:159 backend/epson.c:3197 backend/epson2.c:1216 #: backend/kvs20xx_opt.c:366 backend/kvs40xx_opt.c:597 #: backend/rts8891.c:2831 backend/snapscan-options.c:923 #: backend/umax.c:5565 #, no-c-format msgid "Advanced" msgstr "Gevorderd" #: include/sane/saneopts.h:160 #, no-c-format msgid "Sensors" msgstr "Sensoren" #: include/sane/saneopts.h:162 #, no-c-format msgid "Preview" msgstr "Voorbeeldscan" #: include/sane/saneopts.h:163 #, no-c-format msgid "Force monochrome preview" msgstr "Dwing monochroom voorbeeldscan" #: include/sane/saneopts.h:164 #, no-c-format msgid "Bit depth" msgstr "Bitdiepte" #: include/sane/saneopts.h:165 backend/canon.c:1145 backend/leo.c:781 #: backend/pixma_sane_options.c:47 #, no-c-format msgid "Scan mode" msgstr "Scanmodus" #: include/sane/saneopts.h:166 #, no-c-format msgid "Scan speed" msgstr "Scansnelheid" #: include/sane/saneopts.h:167 #, no-c-format msgid "Scan source" msgstr "Scanbron" #: include/sane/saneopts.h:168 #, no-c-format msgid "Force backtracking" msgstr "Dwing \"backtracking\"" #: include/sane/saneopts.h:169 #, no-c-format msgid "Top-left x" msgstr "Linksboven x" #: include/sane/saneopts.h:170 #, no-c-format msgid "Top-left y" msgstr "Linksboven y" #: include/sane/saneopts.h:171 #, no-c-format msgid "Bottom-right x" msgstr "Rechtsonder x" #: include/sane/saneopts.h:172 #, no-c-format msgid "Bottom-right y" msgstr "Rechtsonder y" #: include/sane/saneopts.h:173 backend/canon.c:1221 #: backend/pixma_sane_options.c:300 #, no-c-format msgid "Scan resolution" msgstr "Scanresolutie" #: include/sane/saneopts.h:174 #, no-c-format msgid "X-resolution" msgstr "X-resolutie" #: include/sane/saneopts.h:175 #, no-c-format msgid "Y-resolution" msgstr "Y-resolutie" #: include/sane/saneopts.h:176 #, no-c-format msgid "Page width" msgstr "Pagina breedte" #: include/sane/saneopts.h:177 #, no-c-format msgid "Page height" msgstr "Pagina hoogte" #: include/sane/saneopts.h:178 #, no-c-format msgid "Use custom gamma table" msgstr "Gebruik door de gebruiker gedefinieerde gammatabel" #: include/sane/saneopts.h:179 #, no-c-format msgid "Image intensity" msgstr "Beeldintensiteit" #: include/sane/saneopts.h:180 #, no-c-format msgid "Red intensity" msgstr "Rode intensiteit" #: include/sane/saneopts.h:181 #, no-c-format msgid "Green intensity" msgstr "Groene intensiteit" #: include/sane/saneopts.h:182 #, no-c-format msgid "Blue intensity" msgstr "Blauwe intensiteit" #: include/sane/saneopts.h:183 #, no-c-format msgid "Brightness" msgstr "Helderheid" #: include/sane/saneopts.h:184 #, no-c-format msgid "Contrast" msgstr "Contrast" #: include/sane/saneopts.h:185 #, no-c-format msgid "Grain size" msgstr "Korrelgrootte" #: include/sane/saneopts.h:186 #, no-c-format msgid "Halftoning" msgstr "Halftoonmodus" #: include/sane/saneopts.h:187 #, no-c-format msgid "Black level" msgstr "Zwartwaarde" #: include/sane/saneopts.h:188 #, no-c-format msgid "White level" msgstr "Witwaarde" #: include/sane/saneopts.h:189 #, no-c-format msgid "White level for red" msgstr "Witwaarde voor rood" #: include/sane/saneopts.h:190 #, no-c-format msgid "White level for green" msgstr "Witwaarde voor groen" #: include/sane/saneopts.h:191 #, no-c-format msgid "White level for blue" msgstr "Witwaarde voor blauw" #: include/sane/saneopts.h:192 #, no-c-format msgid "Shadow" msgstr "Schaduw" #: include/sane/saneopts.h:193 #, no-c-format msgid "Shadow for red" msgstr "Schaduw voor rood" #: include/sane/saneopts.h:194 #, no-c-format msgid "Shadow for green" msgstr "Schaduw voor groen" #: include/sane/saneopts.h:195 #, no-c-format msgid "Shadow for blue" msgstr "Schaduw voor blauw" #: include/sane/saneopts.h:196 #, no-c-format msgid "Highlight" msgstr "Lichteffect" #: include/sane/saneopts.h:197 #, no-c-format msgid "Highlight for red" msgstr "Lichteffect voor rood" #: include/sane/saneopts.h:198 #, no-c-format msgid "Highlight for green" msgstr "Lichteffect voor groen" #: include/sane/saneopts.h:199 #, no-c-format msgid "Highlight for blue" msgstr "Lichteffect voor blauw" #: include/sane/saneopts.h:200 #, no-c-format msgid "Hue" msgstr "Tint" #: include/sane/saneopts.h:201 #, no-c-format msgid "Saturation" msgstr "Kleurverzadiging" #: include/sane/saneopts.h:202 #, no-c-format msgid "Filename" msgstr "Bestandsnaam" #: include/sane/saneopts.h:203 #, no-c-format msgid "Halftone pattern size" msgstr "Grootte van het halftoonpatroon" #: include/sane/saneopts.h:204 backend/fujitsu.c:3186 #, no-c-format msgid "Halftone pattern" msgstr "Halftoonpatroon" #: include/sane/saneopts.h:205 #, no-c-format msgid "Bind X and Y resolution" msgstr "Combineer X- en Y-resolutie" #: include/sane/saneopts.h:206 backend/hp3900_sane.c:428 #: backend/hp3900_sane.c:1021 backend/hp3900_sane.c:1421 #: backend/hp-option.c:3235 backend/mustek_usb2.c:121 #: backend/plustek.c:236 backend/plustek_pp.c:205 backend/u12.c:157 #, no-c-format msgid "Negative" msgstr "Negatief" #: include/sane/saneopts.h:207 #, no-c-format msgid "Quality calibration" msgstr "Kwaliteit kalibreren" #: include/sane/saneopts.h:208 #, no-c-format msgid "Double Optical Resolution" msgstr "Dubbele optische resolutie" #: include/sane/saneopts.h:209 #, no-c-format msgid "Bind RGB" msgstr "Combineer RGB" #: include/sane/saneopts.h:210 backend/sm3840.c:770 #, no-c-format msgid "Threshold" msgstr "Drempelwaarde" #: include/sane/saneopts.h:211 #, no-c-format msgid "Analog gamma correction" msgstr "Analoge gammacorrectie" #: include/sane/saneopts.h:212 #, no-c-format msgid "Analog gamma red" msgstr "Analoge gammawaarde rood" #: include/sane/saneopts.h:213 #, no-c-format msgid "Analog gamma green" msgstr "Analoge gammawaarde groen" #: include/sane/saneopts.h:214 #, no-c-format msgid "Analog gamma blue" msgstr "Analoge gammawaarde blauw" #: include/sane/saneopts.h:215 #, no-c-format msgid "Bind analog gamma" msgstr "Combineer analoge gammawaarde" #: include/sane/saneopts.h:216 #, no-c-format msgid "Warmup lamp" msgstr "Lamp opwarmen" #: include/sane/saneopts.h:217 #, no-c-format msgid "Cal. exposure-time" msgstr "Belichtingstijd kalibreren" #: include/sane/saneopts.h:218 #, no-c-format msgid "Cal. exposure-time for red" msgstr "Belichtingstijd kalibreren voor rood" #: include/sane/saneopts.h:219 #, no-c-format msgid "Cal. exposure-time for green" msgstr "Belichtingstijd kalibreren voor groen" #: include/sane/saneopts.h:221 #, no-c-format msgid "Cal. exposure-time for blue" msgstr "Belichtingstijd kalibreren voor blauw" #: include/sane/saneopts.h:222 #, no-c-format msgid "Scan exposure-time" msgstr "Belichtingstijd voor het scannen" #: include/sane/saneopts.h:223 #, no-c-format msgid "Scan exposure-time for red" msgstr "Belichtingstijd voor het scannen van rood" #: include/sane/saneopts.h:224 #, no-c-format msgid "Scan exposure-time for green" msgstr "Belichtingstijd voor het scannen van groen" #: include/sane/saneopts.h:226 #, no-c-format msgid "Scan exposure-time for blue" msgstr "Belichtingstijd voor het scannen van blauw" #: include/sane/saneopts.h:227 #, no-c-format msgid "Set exposure-time" msgstr "Stel belichtingstijd in" #: include/sane/saneopts.h:228 #, no-c-format msgid "Cal. lamp density" msgstr "Lichtwaarde kalibreren" #: include/sane/saneopts.h:229 #, no-c-format msgid "Scan lamp density" msgstr "Lichtwaarde bij het scannen" #: include/sane/saneopts.h:230 #, no-c-format msgid "Set lamp density" msgstr "Stel lichtwaarde in" #: include/sane/saneopts.h:231 backend/umax.c:5829 #, no-c-format msgid "Lamp off at exit" msgstr "Lamp aan het einde uitschakelen" #: include/sane/saneopts.h:245 #, no-c-format msgid "" "Read-only option that specifies how many options a specific devices " "supports." msgstr "" "Alleen-lezen optie, die aangeeft hoeveel opties een apparaat ondersteunt." #: include/sane/saneopts.h:248 #, no-c-format msgid "Source, mode and resolution options" msgstr "Opties voor bron, modus en resolutie" #: include/sane/saneopts.h:249 #, no-c-format msgid "Scan area and media size options" msgstr "Opties voor scanoppervlak en origineelgrootte" #: include/sane/saneopts.h:250 #, no-c-format msgid "Image modification options" msgstr "Opties voor beeldaanpassing" #: include/sane/saneopts.h:251 #, no-c-format msgid "Hardware specific options" msgstr "Hardware specifieke opties" #: include/sane/saneopts.h:252 #, no-c-format msgid "Scanner sensors and buttons" msgstr "Scannersensoren en -knoppen" #: include/sane/saneopts.h:255 #, no-c-format msgid "Request a preview-quality scan." msgstr "Verzoek om een scan in voorbeeldkwaliteit." #: include/sane/saneopts.h:258 #, no-c-format msgid "" "Request that all previews are done in monochrome mode. On a three-pass " "scanner this cuts down the number of passes to one and on a one-pass " "scanner, it reduces the memory requirements and scan-time of the preview." msgstr "" "Legt vast dat alle voorbeeldscans in grijswaardemodus worden uitgevoerd. " "Bij een Three-Pass-Scanner is daardoor slechts één doorgang nodig, bij " "een Single-Pass-Scanner wordt het geheugengebruik en de scantijd " "verminderd." #: include/sane/saneopts.h:264 #, no-c-format msgid "" "Number of bits per sample, typical values are 1 for \"line-art\" and 8 " "for multibit scans." msgstr "" "Aantal bits per kleurwaarde, typische waarden zijn 1 voor zwart/wit en 8 " "voor multibit-scans." #: include/sane/saneopts.h:268 #, no-c-format msgid "Selects the scan mode (e.g., lineart, monochrome, or color)." msgstr "Kiest de scanmodus (b.v. zwart/wit, monochroom of kleur)." #: include/sane/saneopts.h:271 #, no-c-format msgid "Determines the speed at which the scan proceeds." msgstr "Bepaald de snelheid waarmee wordt gescand." #: include/sane/saneopts.h:274 #, no-c-format msgid "Selects the scan source (such as a document-feeder)." msgstr "Selecteert de scanbron (zoals b.v. een documentendoorvoer)." #: include/sane/saneopts.h:277 #, no-c-format msgid "Controls whether backtracking is forced." msgstr "Regelt dat \"backtracking\" wordt gebruikt." #: include/sane/saneopts.h:280 #, no-c-format msgid "Top-left x position of scan area." msgstr "Linksboven x positie van het scanoppervlak." #: include/sane/saneopts.h:283 #, no-c-format msgid "Top-left y position of scan area." msgstr "Linksboven y positie van het scanoppervlak." #: include/sane/saneopts.h:286 #, no-c-format msgid "Bottom-right x position of scan area." msgstr "Rechtsonder x positie van het scanoppervlak." #: include/sane/saneopts.h:289 #, no-c-format msgid "Bottom-right y position of scan area." msgstr "Rechtsonder y positie van het scanoppervlak." #: include/sane/saneopts.h:292 #, no-c-format msgid "Sets the resolution of the scanned image." msgstr "Stelt de resolutie in van het gescande beeld." #: include/sane/saneopts.h:295 #, no-c-format msgid "Sets the horizontal resolution of the scanned image." msgstr "Stelt de horizontale resolutie in van het gescande beeld." #: include/sane/saneopts.h:298 #, no-c-format msgid "Sets the vertical resolution of the scanned image." msgstr "Stelt de verticale resolutie in van het gescande origineel." #: include/sane/saneopts.h:301 #, no-c-format msgid "" "Specifies the width of the media. Required for automatic centering of " "sheet-fed scans." msgstr "" "Bepaalt de breedte van het origineel. Nodig om doorvoerscans automatisch " "te kunnen centreren." #: include/sane/saneopts.h:305 #, no-c-format msgid "Specifies the height of the media." msgstr "Bepaalt de hoogte van het origineel." #: include/sane/saneopts.h:308 #, no-c-format msgid "" "Determines whether a builtin or a custom gamma-table should be used." msgstr "" "Bepaalt of de interne of de door de gebruiker gedefinieerde gammatabel " "wordt gebruikt." #: include/sane/saneopts.h:312 #, no-c-format msgid "" "Gamma-correction table. In color mode this option equally affects the " "red, green, and blue channels simultaneously (i.e., it is an intensity " "gamma table)." msgstr "" "Gammacorrectietabel. In kleurmodus beïnvloedt deze optie tegelijkertijd " "de rode, groene en blauwe kleurcomponenten. (d.w.z. Het is een " "helderheids-gammatabel)." #: include/sane/saneopts.h:317 #, no-c-format msgid "Gamma-correction table for the red band." msgstr "Gammacorrectietabel voor de rode component." #: include/sane/saneopts.h:320 #, no-c-format msgid "Gamma-correction table for the green band." msgstr "Gammacorrectietabel voor de groene component." #: include/sane/saneopts.h:323 #, no-c-format msgid "Gamma-correction table for the blue band." msgstr "Gammacorrectietabel voor de blauwe component." #: include/sane/saneopts.h:326 #, no-c-format msgid "Controls the brightness of the acquired image." msgstr "Regelt de helderheid van het verkregen beeld." #: include/sane/saneopts.h:329 #, no-c-format msgid "Controls the contrast of the acquired image." msgstr "Regelt het contrast van het verkregen beeld." #: include/sane/saneopts.h:332 #, no-c-format msgid "" "Selects the \"graininess\" of the acquired image. Smaller values result " "in sharper images." msgstr "" "Bepaalt de \"gekorreldheid\" van het verkregen beeld. Kleine waarden " "zorgen voor een scherper beeld." #: include/sane/saneopts.h:336 #, no-c-format msgid "Selects whether the acquired image should be halftoned (dithered)." msgstr "Bepaalt of een halftoon beeld (dithered) wordt verkregen." #: include/sane/saneopts.h:339 include/sane/saneopts.h:354 #, no-c-format msgid "Selects what radiance level should be considered \"black\"." msgstr "" "Bepaalt welke helderheidswaarde als \"zwart\" moet worden beschouwd." #: include/sane/saneopts.h:342 include/sane/saneopts.h:363 #, no-c-format msgid "Selects what radiance level should be considered \"white\"." msgstr "Bepaalt welke helderheidswaarde als \"wit\" moet worden beschouwd." #: include/sane/saneopts.h:345 #, no-c-format msgid "Selects what red radiance level should be considered \"white\"." msgstr "" "Bepaalt welke rode helderheidswaarde als \"wit\" moet worden beschouwd." #: include/sane/saneopts.h:348 #, no-c-format msgid "Selects what green radiance level should be considered \"white\"." msgstr "" "Bepaalt welke groene helderheidswaarde als \"wit\" moet worden beschouwd." #: include/sane/saneopts.h:351 #, no-c-format msgid "Selects what blue radiance level should be considered \"white\"." msgstr "" "Bepaalt welke blauwe helderheidswaarde als \"wit\" moet worden beschouwd." #: include/sane/saneopts.h:356 #, no-c-format msgid "Selects what red radiance level should be considered \"black\"." msgstr "" "Bepaalt welke rode helderheidswaarde als \"zwart\" moet worden beschouwd." #: include/sane/saneopts.h:358 #, no-c-format msgid "Selects what green radiance level should be considered \"black\"." msgstr "" "Bepaalt welke groene helderheidswaarde als \"zwart\" moet worden " "beschouwd." #: include/sane/saneopts.h:360 #, no-c-format msgid "Selects what blue radiance level should be considered \"black\"." msgstr "" "Bepaalt welke blauwe helderheidswaarde als \"zwart\" moet worden " "beschouwd." #: include/sane/saneopts.h:365 #, no-c-format msgid "Selects what red radiance level should be considered \"full red\"." msgstr "" "Bepaalt welke rode helderheidswaarde als \"verzadigd rood\" moet worden " "beschouwd." #: include/sane/saneopts.h:367 #, no-c-format msgid "" "Selects what green radiance level should be considered \"full green\"." msgstr "" "Bepaalt welke groene helderheidswaarde als \"verzadigd groen\" moet " "worden beschouwd." #: include/sane/saneopts.h:370 #, no-c-format msgid "" "Selects what blue radiance level should be considered \"full blue\"." msgstr "" "Bepaalt welke blauwe helderheidswaarde als \"verzadigd blauw\" moet " "worden beschouwd." #: include/sane/saneopts.h:374 #, no-c-format msgid "Controls the \"hue\" (blue-level) of the acquired image." msgstr "Regelt de \"tint\" (blauwwaarde) van het verkregen beeld." #: include/sane/saneopts.h:377 #, no-c-format msgid "" "The saturation level controls the amount of \"blooming\" that occurs " "when acquiring an image with a camera. Larger values cause more blooming." msgstr "" "De verzadigingsgraad bepaalt de \"kleuring\" van een met een camera " "opgenomen beeld. Hogere waarden zorgen voor een sterkere kleuring." #: include/sane/saneopts.h:382 #, no-c-format msgid "The filename of the image to be loaded." msgstr "De bestandsnaam van het te scannen beeld." #: include/sane/saneopts.h:385 #, no-c-format msgid "" "Sets the size of the halftoning (dithering) pattern used when scanning " "halftoned images." msgstr "" "Stelt het halftoon patroon (dithering) in dat wordt gebruikt om halftoon " "beelden te scannen." #: include/sane/saneopts.h:389 #, no-c-format msgid "" "Defines the halftoning (dithering) pattern for scanning halftoned images." msgstr "" "Definieert het halftoon patroon (dithering) waarmee halftoon beelden " "worden gescand." #: include/sane/saneopts.h:393 #, no-c-format msgid "Use same values for X and Y resolution" msgstr "Gebruik dezelfde waarden voor X en Y resoluties." #: include/sane/saneopts.h:395 #, no-c-format msgid "Swap black and white" msgstr "Verwissel zwart en wit (inverteren)." #: include/sane/saneopts.h:397 #, no-c-format msgid "Do a quality white-calibration" msgstr "Voer een kwaliteit wit-kalibratie uit" #: include/sane/saneopts.h:399 #, no-c-format msgid "Use lens that doubles optical resolution" msgstr "Gebruik de lens waarmee de optische resolutie wordt verdubbeld." #: include/sane/saneopts.h:401 include/sane/saneopts.h:413 #, no-c-format msgid "In RGB-mode use same values for each color" msgstr "Gebruik in RGB-modus voor alle kleuren dezelfde waarden" #: include/sane/saneopts.h:403 #, no-c-format msgid "Select minimum-brightness to get a white point" msgstr "Kiest de minimale helderheid waarmee witte punt wordt verkregen" #: include/sane/saneopts.h:405 #, no-c-format msgid "Analog gamma-correction" msgstr "Analoge gammacorrectie" #: include/sane/saneopts.h:407 #, no-c-format msgid "Analog gamma-correction for red" msgstr "Analoge gammacorrectie voor rood" #: include/sane/saneopts.h:409 #, no-c-format msgid "Analog gamma-correction for green" msgstr "Analoge gammacorrectie voor groen" #: include/sane/saneopts.h:411 #, no-c-format msgid "Analog gamma-correction for blue" msgstr "Analoge gammacorrectie voor blauw" #: include/sane/saneopts.h:415 #, no-c-format msgid "Warmup lamp before scanning" msgstr "Warm de lamp op alvorens te scannen" #: include/sane/saneopts.h:417 #, no-c-format msgid "Define exposure-time for calibration" msgstr "Bepaal de belichtingstijd voor de kalibratie" #: include/sane/saneopts.h:419 #, no-c-format msgid "Define exposure-time for red calibration" msgstr "Bepaal de belichtingstijd voor de kalibratie van de rode component" #: include/sane/saneopts.h:421 #, no-c-format msgid "Define exposure-time for green calibration" msgstr "" "Bepaal de belichtingstijd voor de kalibratie van de groene component" #: include/sane/saneopts.h:423 #, no-c-format msgid "Define exposure-time for blue calibration" msgstr "" "Bepaal de belichtingstijd voor de kalibratie van de blauwe component" #: include/sane/saneopts.h:425 #, no-c-format msgid "Define exposure-time for scan" msgstr "Bepaal de belichtingstijd voor de scan" #: include/sane/saneopts.h:427 #, no-c-format msgid "Define exposure-time for red scan" msgstr "Bepaal de belichtingstijd voor de scan van de rode component" #: include/sane/saneopts.h:429 #, no-c-format msgid "Define exposure-time for green scan" msgstr "Bepaal de belichtingstijd voor de scan van de groene component" #: include/sane/saneopts.h:431 #, no-c-format msgid "Define exposure-time for blue scan" msgstr "Bepaal de belichtingstijd voor de scan van de blauwe component" #: include/sane/saneopts.h:433 #, no-c-format msgid "Enable selection of exposure-time" msgstr "Schakelt de instelling van de belichtingstijd in" #: include/sane/saneopts.h:435 #, no-c-format msgid "Define lamp density for calibration" msgstr "Bepaal de lichthoeveelheid waarmee wordt gekalibreerd" #: include/sane/saneopts.h:437 #, no-c-format msgid "Define lamp density for scan" msgstr "Bepaal de lichthoeveelheid waarmee wordt gescand" #: include/sane/saneopts.h:439 #, no-c-format msgid "Enable selection of lamp density" msgstr "Schakelt de instelling van de lichthoeveelheid in" #: include/sane/saneopts.h:441 backend/umax.c:5830 #, no-c-format msgid "Turn off lamp when program exits" msgstr "Schakel de lamp uit als het programma wordt verlaten" #: include/sane/saneopts.h:444 #, no-c-format msgid "Scan button" msgstr "Scan-knop" #: include/sane/saneopts.h:445 #, no-c-format msgid "Email button" msgstr "E-mail-knop" #: include/sane/saneopts.h:446 #, no-c-format msgid "Fax button" msgstr "Fax-knop" #: include/sane/saneopts.h:447 #, no-c-format msgid "Copy button" msgstr "Kopieer-knop" #: include/sane/saneopts.h:448 #, no-c-format msgid "PDF button" msgstr "PDF-knop" #: include/sane/saneopts.h:449 #, no-c-format msgid "Cancel button" msgstr "Annuleer-knop" #: include/sane/saneopts.h:450 #, no-c-format msgid "Page loaded" msgstr "Pagina geladen" #: include/sane/saneopts.h:451 #, no-c-format msgid "Cover open" msgstr "Deksel open" #: include/sane/saneopts.h:454 #, no-c-format msgid "Color" msgstr "Kleur" #: include/sane/saneopts.h:455 #, no-c-format msgid "Color Lineart" msgstr "Kleur lijntekening" #: include/sane/saneopts.h:456 #, no-c-format msgid "Color Halftone" msgstr "Kleur Halftoon" #: include/sane/saneopts.h:457 #, no-c-format msgid "Gray" msgstr "Grijs" #: include/sane/saneopts.h:458 #, no-c-format msgid "Halftone" msgstr "Halftoon" #: include/sane/saneopts.h:459 #, no-c-format msgid "Lineart" msgstr "Lijntekening" #: backend/sane_strstatus.c:59 #, no-c-format msgid "Success" msgstr "Succes" #: backend/sane_strstatus.c:62 #, no-c-format msgid "Operation not supported" msgstr "Handeling niet ondersteund" #: backend/sane_strstatus.c:65 #, no-c-format msgid "Operation was cancelled" msgstr "Handeling was geannuleerd" #: backend/sane_strstatus.c:68 #, no-c-format msgid "Device busy" msgstr "Apparaat is bezet" #: backend/sane_strstatus.c:71 #, no-c-format msgid "Invalid argument" msgstr "Ongeldige waarde" #: backend/sane_strstatus.c:74 #, no-c-format msgid "End of file reached" msgstr "Eind van bestand bereikt" #: backend/sane_strstatus.c:77 #, no-c-format msgid "Document feeder jammed" msgstr "Opstopping in documentendoorvoer" #: backend/sane_strstatus.c:80 #, no-c-format msgid "Document feeder out of documents" msgstr "Documentendoorvoer leeg" #: backend/sane_strstatus.c:83 #, no-c-format msgid "Scanner cover is open" msgstr "Deksel van de scanner is open" #: backend/sane_strstatus.c:86 #, no-c-format msgid "Error during device I/O" msgstr "Fout tijdens apparaat I/O" #: backend/sane_strstatus.c:89 #, no-c-format msgid "Out of memory" msgstr "Geheugen vol" #: backend/sane_strstatus.c:92 #, no-c-format msgid "Access to resource has been denied" msgstr "Toegang tot bron is geweigerd" #: backend/sane_strstatus.c:96 #, no-c-format msgid "Lamp not ready, please retry" msgstr "Lamp niet klaar, probeer opnieuw" #: backend/sane_strstatus.c:101 #, no-c-format msgid "Scanner mechanism locked for transport" msgstr "Scannerwagen geblokkeerd (in transportstand)" #: backend/artec_eplus48u.c:2874 backend/pnm.c:282 #, no-c-format msgid "Defaults" msgstr "Standaardinstellingen" #: backend/artec_eplus48u.c:2876 #, no-c-format msgid "Set default values for enhancement controls." msgstr "Stel standaardwaarden in om verbeteropties te krijgen." #: backend/artec_eplus48u.c:2932 backend/canon.c:1616 #, no-c-format msgid "Calibration" msgstr "Kalibreren" #: backend/artec_eplus48u.c:2941 #, no-c-format msgid "Calibrate before next scan" msgstr "Voor de volgende scan kalibreren" #: backend/artec_eplus48u.c:2943 #, no-c-format msgid "" "If enabled, the device will be calibrated before the next scan. " "Otherwise, calibration is performed only before the first start." msgstr "" "Indien ingeschakeld, wordt de scanner voor de volgende scan " "gekalibreerd. Anders wordt de scanner alleen voor de eerste scan " "gekalibreerd." #: backend/artec_eplus48u.c:2954 #, no-c-format msgid "Only perform shading-correction" msgstr "Voer alleen een schaduwcorrectie uit" #: backend/artec_eplus48u.c:2956 #, no-c-format msgid "" "If enabled, only the shading correction is performed during calibration. " "The default values for gain, offset and exposure time, either build-in " "or from the configuration file, are used." msgstr "" "Indien ingeschakeld, wordt tijdens het kalibreren alleen de schaduw-" "correctie uitgevoerd. De standaard waarden voor bereik, compensatie en " "belichtingstijd bepaald door de hardware of het configuratiebestand, " "worden gebruikt." #: backend/artec_eplus48u.c:2967 #, no-c-format msgid "Button state" msgstr "Status van de knop" #: backend/avision.h:778 #, no-c-format msgid "Number of the frame to scan" msgstr "Nummer van het te scannen scannerraam" #: backend/avision.h:779 #, no-c-format msgid "Selects the number of the frame to scan" msgstr "Kiest het nummer van het te scannen scannerraam" #: backend/avision.h:782 #, no-c-format msgid "Duplex scan" msgstr "Dubbelzijdige scan" #: backend/avision.h:783 #, no-c-format msgid "" "Duplex scan provide a scan of the front and back side of the document" msgstr "Dubbelzijdige scan scant beide zijden van een document" #: backend/canon630u.c:159 #, no-c-format msgid "Calibrate Scanner" msgstr "Kalibreer scanner" #: backend/canon630u.c:160 #, no-c-format msgid "Force scanner calibration before scan" msgstr "Dwing te kalibreren voor het scannen" #: backend/canon630u.c:259 backend/umax1220u.c:208 #, no-c-format msgid "Grayscale scan" msgstr "Grijstrapscan" #: backend/canon630u.c:260 backend/umax1220u.c:209 #, no-c-format msgid "Do a grayscale rather than color scan" msgstr "Voer een grijstrap-, in plaats van een kleurenscan uit" #: backend/canon630u.c:306 #, no-c-format msgid "Analog Gain" msgstr "Analoog bereik" #: backend/canon630u.c:307 #, no-c-format msgid "Increase or decrease the analog gain of the CCD array" msgstr "Vergroot of verklein het analoge bereik van de CCD-sensor" #: backend/canon630u.c:347 backend/epson.h:68 backend/epson2.h:67 #, no-c-format msgid "Gamma Correction" msgstr "Gammacorrectie" #: backend/canon630u.c:348 #, no-c-format msgid "Selects the gamma corrected transfer curve" msgstr "Kiest de gamma gecorrigeerde overdrachtscurve" #: backend/canon.c:149 backend/canon-sane.c:1318 #, no-c-format msgid "Raw" msgstr "Ongecomprimeerd" #: backend/canon.c:157 backend/canon-sane.c:732 backend/canon-sane.c:940 #: backend/canon-sane.c:1076 backend/canon-sane.c:1314 #: backend/canon-sane.c:1494 backend/canon-sane.c:1643 #, no-c-format msgid "Fine color" msgstr "Fraaie kleuren" #: backend/canon.c:169 #, no-c-format msgid "No transparency correction" msgstr "Ongecorrigeerde transparantie" #: backend/canon.c:170 backend/canon-sane.c:680 #, no-c-format msgid "Correction according to film type" msgstr "Correctie op basis van filmtype" #: backend/canon.c:171 backend/canon-sane.c:674 #, no-c-format msgid "Correction according to transparency ratio" msgstr "Correctie op basis van de transparantieverhouding" #: backend/canon.c:176 backend/canon-sane.c:776 #, no-c-format msgid "Negatives" msgstr "Negatieven" #: backend/canon.c:176 #, no-c-format msgid "Slides" msgstr "Dia's" #: backend/canon.c:186 backend/kvs1025_opt.c:181 backend/kvs40xx_opt.c:273 #: backend/matsushita.c:178 #, no-c-format msgid "Automatic" msgstr "Automatisch" #: backend/canon.c:186 #, no-c-format msgid "Normal speed" msgstr "Standaard snelheid" #: backend/canon.c:187 #, no-c-format msgid "1/2 normal speed" msgstr "1/2 van de standaard snelheid" #: backend/canon.c:187 #, no-c-format msgid "1/3 normal speed" msgstr "1/3 van de standaard snelheid" #: backend/canon.c:365 #, no-c-format msgid "rounded parameter" msgstr "Afgeronde parameter" #: backend/canon.c:368 backend/canon.c:384 backend/canon.c:419 #: backend/canon.c:469 backend/canon.c:487 backend/canon.c:530 #, no-c-format msgid "unknown" msgstr "onbekend" #: backend/canon.c:378 #, no-c-format msgid "ADF jam" msgstr "Opstopping in automatische documentinvoer" #: backend/canon.c:381 #, no-c-format msgid "ADF cover open" msgstr "Deksel van automatische documentinvoer open" #: backend/canon.c:394 #, no-c-format msgid "lamp failure" msgstr "lampfalen" #: backend/canon.c:397 #, no-c-format msgid "scan head positioning error" msgstr "fout in positionering van scannerkop" #: backend/canon.c:400 #, no-c-format msgid "CPU check error" msgstr "fout bij controle van processor" #: backend/canon.c:403 #, no-c-format msgid "RAM check error" msgstr "fout bij controle van het RAM geheugen" #: backend/canon.c:406 #, no-c-format msgid "ROM check error" msgstr "fout bij controle van het ROM geheugen" #: backend/canon.c:409 #, no-c-format msgid "hardware check error" msgstr "fout bij controle van de hardware" #: backend/canon.c:412 #, no-c-format msgid "transparency unit lamp failure" msgstr "lampfalen van de transparanten eenheid" #: backend/canon.c:415 #, no-c-format msgid "transparency unit scan head positioning failure" msgstr "" "fout in de positionering van de scannerkop in de transparanten eenheid" #: backend/canon.c:429 #, no-c-format msgid "parameter list length error" msgstr "fout in de lengte van de parameterlijst" #: backend/canon.c:433 #, no-c-format msgid "invalid command operation code" msgstr "ongeldige opdrachtcode" #: backend/canon.c:437 #, no-c-format msgid "invalid field in CDB" msgstr "ongeldig veld in CDB" #: backend/canon.c:441 #, no-c-format msgid "unsupported LUN" msgstr "niet-ondersteunde LUN" #: backend/canon.c:445 #, no-c-format msgid "invalid field in parameter list" msgstr "ongeldig veld in de parameterlijst" #: backend/canon.c:449 #, no-c-format msgid "command sequence error" msgstr "fout in volgorde van de opdrachten" #: backend/canon.c:453 #, no-c-format msgid "too many windows specified" msgstr "te veel vensters gespecificeerd" #: backend/canon.c:457 #, no-c-format msgid "medium not present" msgstr "medium niet aanwezig" #: backend/canon.c:461 #, no-c-format msgid "invalid bit IDENTIFY message" msgstr "ongeldig onderdeel in IDENTIFY boodschap" #: backend/canon.c:465 #, no-c-format msgid "option not connect" msgstr "optie onjuist" #: backend/canon.c:479 #, no-c-format msgid "power on reset / bus device reset" msgstr "scanner aan reset / scannerinterface reset" #: backend/canon.c:483 #, no-c-format msgid "parameter changed by another initiator" msgstr "parameter gewijzigd door een andere initiator" #: backend/canon.c:497 #, no-c-format msgid "no additional sense information" msgstr "geen zinvolle, aanvullende informatie" #: backend/canon.c:501 #, no-c-format msgid "reselect failure" msgstr "opnieuw kiezen mislukt" #: backend/canon.c:505 #, no-c-format msgid "SCSI parity error" msgstr "fout in SCSI pariteit" #: backend/canon.c:509 #, no-c-format msgid "initiator detected error message received" msgstr "Door initiator gesignaleerde foutboodschap ontvangen" #: backend/canon.c:514 #, no-c-format msgid "invalid message error" msgstr "ongeldige boodschap fout" #: backend/canon.c:518 #, no-c-format msgid "timeout error" msgstr "timeout" #: backend/canon.c:522 #, no-c-format msgid "transparency unit shading error" msgstr "fout in de afscherming van de transparantie-eenheid " #: backend/canon.c:526 #, no-c-format msgid "lamp not stabilized" msgstr "lamp niet gestabiliseerd" #: backend/canon.c:852 backend/canon.c:867 #, no-c-format msgid "film scanner" msgstr "Filmscanner" #: backend/canon.c:882 backend/canon.c:897 backend/canon.c:912 #: backend/canon.c:927 backend/hp3900_sane.c:1683 backend/plustek.c:1335 #: backend/plustek_pp.c:1014 backend/sceptre.c:593 backend/teco2.c:1836 #: backend/u12.c:851 #, no-c-format msgid "flatbed scanner" msgstr "Flatbedscanner" #: backend/canon.c:1183 backend/epson.c:3386 backend/epson2.c:1365 #, no-c-format msgid "Film type" msgstr "Filmtype" #: backend/canon.c:1184 #, no-c-format msgid "Selects the film type, i.e. negatives or slides" msgstr "Selecteert het filmtype, bijvoorbeeld negatieven of dia's" #: backend/canon.c:1196 #, no-c-format msgid "Negative film type" msgstr "Negatief filmtype" #: backend/canon.c:1197 #, no-c-format msgid "Selects the negative film type" msgstr "Selecteert het negatief filmtype" #: backend/canon.c:1236 #, no-c-format msgid "Hardware resolution" msgstr "Hardware resolutie" #: backend/canon.c:1237 #, no-c-format msgid "Use only hardware resolutions" msgstr "Gebruik alleen hardware resoluties" #: backend/canon.c:1318 #, no-c-format msgid "Focus" msgstr "Focus" #: backend/canon.c:1328 #, no-c-format msgid "Auto focus" msgstr "Autofocus" #: backend/canon.c:1329 #, no-c-format msgid "Enable/disable auto focus" msgstr "Aan/uit schakelen van autofocus" #: backend/canon.c:1336 #, no-c-format msgid "Auto focus only once" msgstr "Eén keer autofocus" #: backend/canon.c:1337 #, no-c-format msgid "Do auto focus only once between ejects" msgstr "Voer alleen een autofocus uit tussen uitworpen" #: backend/canon.c:1345 #, no-c-format msgid "Manual focus position" msgstr "Handmatige focuspositie" #: backend/canon.c:1346 #, no-c-format msgid "Set the optical system's focus position by hand (default: 128)." msgstr "" "Stel de optische focus van de scanner handmatig in (standaard: 128)" #: backend/canon.c:1356 #, no-c-format msgid "Scan margins" msgstr "Scanmarges" #: backend/canon.c:1403 #, no-c-format msgid "Extra color adjustments" msgstr "Extra kleuraanpassingen" #: backend/canon.c:1538 backend/epson.c:3205 backend/epson2.c:1255 #: backend/kvs1025.h:55 backend/kvs40xx_opt.c:826 #, no-c-format msgid "Mirror image" msgstr "Spiegel het beeld" #: backend/canon.c:1539 #, no-c-format msgid "Mirror the image horizontally" msgstr "Spiegel het beeld horizontaal" #: backend/canon.c:1608 #, no-c-format msgid "Auto exposure" msgstr "Automatische belichting" #: backend/canon.c:1609 #, no-c-format msgid "Enable/disable the auto exposure feature" msgstr "Schakel de automatische belichtingsoptie aan/uit" #: backend/canon.c:1625 #, no-c-format msgid "Calibration now" msgstr "Kalibreer nu" #: backend/canon.c:1626 #, no-c-format msgid "Execute calibration *now*" msgstr "Voer kalibratie *NU* uit" #: backend/canon.c:1636 #, no-c-format msgid "Self diagnosis" msgstr "Zelftest" #: backend/canon.c:1637 #, no-c-format msgid "Perform scanner self diagnosis" msgstr "Voer de zelftest van de scanner uit" #: backend/canon.c:1648 #, no-c-format msgid "Reset scanner" msgstr "Reset scanner" #: backend/canon.c:1649 #, no-c-format msgid "Reset the scanner" msgstr "Reset de scanner" #: backend/canon.c:1659 #, no-c-format msgid "Medium handling" msgstr "Gemiddeld gebruik" #: backend/canon.c:1668 #, no-c-format msgid "Eject film after each scan" msgstr "Werp de film uit na elke scan" #: backend/canon.c:1669 #, no-c-format msgid "Automatically eject the film from the device after each scan" msgstr "Werp de film automatisch uit de scanner na elke scan" #: backend/canon.c:1680 #, no-c-format msgid "Eject film before exit" msgstr "Werp de film uit voor het programma wordt verlaten" #: backend/canon.c:1681 #, no-c-format msgid "" "Automatically eject the film from the device before exiting the program" msgstr "" "Werp de film automatisch uit de scanner voor het programma wordt verlaten" #: backend/canon.c:1690 #, no-c-format msgid "Eject film now" msgstr "Werp de film nu uit" #: backend/canon.c:1691 #, no-c-format msgid "Eject the film *now*" msgstr "Werp de film *NU* uit" #: backend/canon.c:1700 #, no-c-format msgid "Document feeder extras" msgstr "Extra's van de documentendoorvoer" #: backend/canon.c:1707 #, no-c-format msgid "Flatbed only" msgstr "Alleen flatbed" #: backend/canon.c:1708 #, no-c-format msgid "Disable auto document feeder and use flatbed only" msgstr "Schakel automatische documentinvoer uit en gebruik alleen flatbed" #: backend/canon.c:1718 backend/canon.c:1728 #, no-c-format msgid "Transparency unit" msgstr "Transparanteneenheid" #: backend/canon.c:1729 #, no-c-format msgid "Switch on/off the transparency unit (FAU, film adapter unit)" msgstr "Schakel de transparanteneenheid aan/uit (FAU, film adaptereenheid)" #: backend/canon.c:1739 #, no-c-format msgid "Negative film" msgstr "Negatief filmtype" #: backend/canon.c:1740 #, no-c-format msgid "Positive or negative film" msgstr "Dia of negatief filmtype" #: backend/canon.c:1749 #, no-c-format msgid "Density control" msgstr "Dichtheidscontrole" #: backend/canon.c:1750 #, no-c-format msgid "Set density control mode" msgstr "Kies de dichtheidscontrolemodus" #: backend/canon.c:1761 #, no-c-format msgid "Transparency ratio" msgstr "Transparantieverhouding" #: backend/canon.c:1775 #, no-c-format msgid "Select film type" msgstr "Selecteert filmtype" #: backend/canon.c:1776 #, no-c-format msgid "Select the film type" msgstr "Selecteert het filmtype" #: backend/canon_dr.c:408 backend/epjitsu.c:233 backend/epson.c:501 #: backend/epson2.c:115 backend/fujitsu.c:672 backend/gt68xx.c:148 #: backend/hp3900_sane.c:418 backend/hp3900_sane.c:427 #: backend/hp3900_sane.c:1017 backend/hp5590.c:85 backend/ma1509.c:108 #: backend/magicolor.c:181 backend/mustek.c:156 backend/mustek.c:160 #: backend/mustek.c:164 backend/pixma.c:901 #: backend/pixma_sane_options.c:92 backend/snapscan-options.c:86 #: backend/test.c:192 backend/umax.c:181 #, no-c-format msgid "Flatbed" msgstr "Flatbed" #: backend/canon_dr.c:409 backend/epjitsu.c:234 backend/fujitsu.c:673 #: backend/kodak.c:140 #, no-c-format msgid "ADF Front" msgstr "Automatische documentinvoer voorzijde" #: backend/canon_dr.c:410 backend/epjitsu.c:235 backend/fujitsu.c:674 #: backend/kodak.c:141 #, no-c-format msgid "ADF Back" msgstr "Automatische documentinvoer achterzijde" #: backend/canon_dr.c:411 backend/epjitsu.c:236 backend/fujitsu.c:675 #: backend/hp5590.c:87 backend/kodak.c:142 backend/pixma.c:912 #, no-c-format msgid "ADF Duplex" msgstr "Automatische documentinvoer dubbelzijdig" #: backend/canon_dr.c:412 #, no-c-format msgid "Card Front" msgstr "Kaart voorzijde" #: backend/canon_dr.c:413 #, no-c-format msgid "Card Back" msgstr "Kaart achterzijde" #: backend/canon_dr.c:414 #, no-c-format msgid "Card Duplex" msgstr "Kaart dubbelzijdig" #: backend/canon_dr.c:421 backend/epson.c:599 backend/epson.c:3096 #: backend/epson2.c:201 backend/fujitsu.c:692 backend/genesys.c:89 #: backend/genesys.c:96 backend/gt68xx_low.h:133 backend/hp-option.c:3093 #, no-c-format msgid "Red" msgstr "Rood" #: backend/canon_dr.c:422 backend/epson.c:600 backend/epson.c:3092 #: backend/epson2.c:202 backend/fujitsu.c:693 backend/genesys.c:90 #: backend/genesys.c:97 backend/gt68xx_low.h:134 backend/hp-option.c:3094 #, no-c-format msgid "Green" msgstr "Groen" #: backend/canon_dr.c:423 backend/epson.c:601 backend/epson.c:3100 #: backend/epson2.c:203 backend/fujitsu.c:694 backend/genesys.c:91 #: backend/genesys.c:98 backend/gt68xx_low.h:135 backend/hp-option.c:3095 #, no-c-format msgid "Blue" msgstr "Blauw" #: backend/canon_dr.c:424 #, no-c-format msgid "Enhance Red" msgstr "Verbeter rood" #: backend/canon_dr.c:425 #, no-c-format msgid "Enhance Green" msgstr "Verbeter groen" #: backend/canon_dr.c:426 #, no-c-format msgid "Enhance Blue" msgstr "Verbeter blauw" #: backend/canon_dr.c:428 backend/epson.c:556 backend/epson.c:564 #: backend/epson.c:576 backend/epson.c:598 backend/epson2.c:165 #: backend/epson2.c:173 backend/epson2.c:185 backend/epson2.c:200 #: backend/epson2.c:214 backend/fujitsu.c:698 backend/genesys.c:99 #: backend/leo.c:109 backend/matsushita.c:138 backend/matsushita.c:159 #: backend/matsushita.c:191 backend/matsushita.c:213 #: backend/snapscan-options.c:91 #, no-c-format msgid "None" msgstr "Geen" #: backend/canon_dr.c:429 backend/fujitsu.c:699 #, no-c-format msgid "JPEG" msgstr "JPEG" #: backend/canon_dr.c:2449 backend/fujitsu.c:4066 backend/genesys.c:5769 #: backend/kvs1025_opt.c:911 #, no-c-format msgid "Software blank skip percentage" msgstr "Softwarematig over te slaan percentage lege pagina's" #: backend/canon_dr.c:2450 backend/fujitsu.c:4067 #, no-c-format msgid "Request driver to discard pages with low percentage of dark pixels" msgstr "Verzoek het stuurprogramma pagina's met weinig dekking te negeren" #: backend/epson.c:491 backend/epson2.c:108 backend/magicolor.c:174 #, no-c-format msgid "Simplex" msgstr "enkelzijdig" #: backend/epson.c:492 backend/epson2.c:109 backend/kvs1025.h:50 #: backend/kvs20xx_opt.c:204 backend/kvs40xx_opt.c:353 #: backend/magicolor.c:175 backend/matsushita.h:218 #, no-c-format msgid "Duplex" msgstr "Dubbelzijdig" #: backend/epson.c:502 backend/epson2.c:116 backend/pixma.c:918 #, no-c-format msgid "Transparency Unit" msgstr "Filmeenheid" #: backend/epson.c:503 backend/epson2.c:118 backend/magicolor.c:182 #: backend/mustek.c:160 backend/pixma.c:906 backend/test.c:192 #: backend/umax.c:183 #, no-c-format msgid "Automatic Document Feeder" msgstr "Automatische documentinvoer" #: backend/epson.c:523 backend/epson2.c:134 #, no-c-format msgid "Positive Film" msgstr "Dia" #: backend/epson.c:524 backend/epson2.c:135 #, no-c-format msgid "Negative Film" msgstr "Transparant" #: backend/epson.c:529 backend/epson2.c:142 #, no-c-format msgid "Focus on glass" msgstr "Focus op het glas" #: backend/epson.c:530 backend/epson2.c:143 #, no-c-format msgid "Focus 2.5mm above glass" msgstr "Focus 2.5mm boven het glas" #: backend/epson.c:557 backend/epson.c:565 backend/epson.c:577 #: backend/epson2.c:166 backend/epson2.c:174 backend/epson2.c:186 #, no-c-format msgid "Halftone A (Hard Tone)" msgstr "Halftoon A (hard)" #: backend/epson.c:558 backend/epson.c:566 backend/epson.c:578 #: backend/epson2.c:167 backend/epson2.c:175 backend/epson2.c:187 #, no-c-format msgid "Halftone B (Soft Tone)" msgstr "Halftoon B (zacht)" #: backend/epson.c:559 backend/epson.c:567 backend/epson.c:579 #: backend/epson2.c:168 backend/epson2.c:176 backend/epson2.c:188 #, no-c-format msgid "Halftone C (Net Screen)" msgstr "Halftoon C" #: backend/epson.c:568 backend/epson.c:580 backend/epson2.c:177 #: backend/epson2.c:189 #, no-c-format msgid "Dither A (4x4 Bayer)" msgstr "Dither A (4x4 Bayer)" #: backend/epson.c:569 backend/epson.c:581 backend/epson2.c:178 #: backend/epson2.c:190 #, no-c-format msgid "Dither B (4x4 Spiral)" msgstr "Dither B (4x4 Spiraalvorm)" #: backend/epson.c:570 backend/epson.c:582 backend/epson2.c:179 #: backend/epson2.c:191 #, no-c-format msgid "Dither C (4x4 Net Screen)" msgstr "Dither C (4x4 Net Screen)" #: backend/epson.c:571 backend/epson.c:583 backend/epson2.c:180 #: backend/epson2.c:192 #, no-c-format msgid "Dither D (8x4 Net Screen)" msgstr "Dither D (8x4 Net Screen)" #: backend/epson.c:584 backend/epson2.c:193 #, no-c-format msgid "Text Enhanced Technology" msgstr "Tekstverbeteringstechnologie" #: backend/epson.c:585 backend/epson2.c:194 #, no-c-format msgid "Download pattern A" msgstr "Download patroon A" #: backend/epson.c:586 backend/epson2.c:195 #, no-c-format msgid "Download pattern B" msgstr "Download patroon B" #: backend/epson.c:631 #, no-c-format msgid "No Correction" msgstr "Geen correctie" #: backend/epson.c:632 backend/epson.c:657 backend/epson2.c:255 #, no-c-format msgid "User defined" msgstr "Door gebruiker gedefinieerd" #: backend/epson.c:633 #, no-c-format msgid "Impact-dot printers" msgstr "Matrixprinters" #: backend/epson.c:634 #, no-c-format msgid "Thermal printers" msgstr "Thermische printers" #: backend/epson.c:635 #, no-c-format msgid "Ink-jet printers" msgstr "Inkjetprinters" #: backend/epson.c:636 #, no-c-format msgid "CRT monitors" msgstr "CRT-monitoren" #: backend/epson.c:656 backend/epson2.c:254 backend/fujitsu.c:682 #: backend/hp-option.c:3226 backend/test.c:143 #, no-c-format msgid "Default" msgstr "Standaardinstelling" #: backend/epson.c:658 backend/epson2.c:256 #, no-c-format msgid "High density printing" msgstr "Afdrukken op hoge kwaliteit" #: backend/epson.c:659 backend/epson2.c:257 #, no-c-format msgid "Low density printing" msgstr "Afdrukken op lage kwaliteit" #: backend/epson.c:660 backend/epson2.c:258 #, no-c-format msgid "High contrast printing" msgstr "Afdrukken met hoog contrast" #: backend/epson.c:678 backend/epson2.c:276 #, no-c-format msgid "User defined (Gamma=1.0)" msgstr "Door gebruiker gedefinieerd (Gamma=1.0)" #: backend/epson.c:679 backend/epson2.c:277 #, no-c-format msgid "User defined (Gamma=1.8)" msgstr "Door gebruiker gedefinieerd (Gamma=1.8)" #: backend/epson.c:757 #, no-c-format msgid "CD" msgstr "CD" #: backend/epson.c:758 #, no-c-format msgid "A5 portrait" msgstr "A5 staand" #: backend/epson.c:759 #, no-c-format msgid "A5 landscape" msgstr "A5 liggend" #: backend/epson.c:760 backend/kvs1025_opt.c:103 backend/kvs20xx_opt.c:77 #: backend/kvs40xx_opt.c:131 backend/kvs40xx_opt.c:148 #, no-c-format msgid "Letter" msgstr "Letter" #: backend/epson.c:761 backend/kvs1025_opt.c:100 backend/kvs20xx_opt.c:74 #: backend/kvs20xx_opt.c:302 backend/kvs40xx_opt.c:128 #: backend/kvs40xx_opt.c:145 backend/kvs40xx_opt.c:526 #, no-c-format msgid "A4" msgstr "A4" #: backend/epson.c:762 #, no-c-format msgid "Max" msgstr "Maximaal" #: backend/epson.c:2813 backend/epson2.c:977 backend/genesys.c:5535 #: backend/gt68xx.c:458 backend/hp-option.c:2914 backend/kvs1025_opt.c:522 #: backend/kvs20xx_opt.c:171 backend/kvs40xx_opt.c:320 #: backend/ma1509.c:501 backend/matsushita.c:1084 backend/microtek2.h:598 #: backend/mustek.c:4203 backend/mustek_usb.c:260 #: backend/mustek_usb2.c:344 backend/niash.c:734 backend/plustek.c:721 #: backend/plustek_pp.c:658 backend/sceptre.c:673 #: backend/snapscan-options.c:354 backend/stv680.c:1030 #: backend/teco2.c:1886 backend/test.c:306 backend/u12.c:473 #: backend/umax.c:5054 #, no-c-format msgid "Scan Mode" msgstr "Scanmodus" #: backend/epson.c:2845 backend/epson2.c:1012 #, no-c-format msgid "Selects the halftone." msgstr "Kiest halftoon." #: backend/epson.c:2867 backend/epson2.c:1033 #, no-c-format msgid "Dropout" msgstr "Kleuronderdrukken" #: backend/epson.c:2868 backend/epson2.c:1034 #, no-c-format msgid "Selects the dropout." msgstr "Kiest kleuronderdrukken." #: backend/epson.c:2880 backend/epson2.c:1046 #, no-c-format msgid "Selects the brightness." msgstr "Kiest helderheid." #: backend/epson.c:2895 backend/epson2.c:1059 #, no-c-format msgid "Sharpness" msgstr "Scherpte" #: backend/epson.c:3031 backend/epson2.c:1175 backend/epson2.c:1222 #, no-c-format msgid "Color correction" msgstr "Kleurcorrectie" #: backend/epson.c:3034 backend/epson2.c:1177 #, no-c-format msgid "Sets the color correction table for the selected output device." msgstr "Stelt de kleurcorrectietabel in voor het gekozen uitvoerapparaat." #: backend/epson.c:3075 #, no-c-format msgid "Color correction coefficients" msgstr "Kleurcorrectiecoëfficiënten" #: backend/epson.c:3076 #, no-c-format msgid "Matrix multiplication of RGB" msgstr "Matrix vermenigvuldiging van RGB" #: backend/epson.c:3093 #, no-c-format msgid "Shift green to red" msgstr "Verschuift groen naar rood" #: backend/epson.c:3094 #, no-c-format msgid "Shift green to blue" msgstr "Verschuift groen naar blauw" #: backend/epson.c:3095 #, no-c-format msgid "Shift red to green" msgstr "Verschuift rood naar groen" #: backend/epson.c:3097 #, no-c-format msgid "Shift red to blue" msgstr "Verschuift rood naar blauw" #: backend/epson.c:3098 #, no-c-format msgid "Shift blue to green" msgstr "Verschuift blauw naar groen" #: backend/epson.c:3099 #, no-c-format msgid "Shift blue to red" msgstr "Verschuift blauw naar rood" #: backend/epson.c:3102 #, no-c-format msgid "Controls green level" msgstr "Regelt de groenwaarde" #: backend/epson.c:3103 #, no-c-format msgid "Adds to red based on green level" msgstr "Verhoogt rood op basis van de groenwaarde" #: backend/epson.c:3104 #, no-c-format msgid "Adds to blue based on green level" msgstr "Verhoogt blauw op basis van het groenwaarde" #: backend/epson.c:3105 #, no-c-format msgid "Adds to green based on red level" msgstr "Verhoogt groen op basis van het roodwaarde" #: backend/epson.c:3106 #, no-c-format msgid "Controls red level" msgstr "Regelt de roodwaarde" #: backend/epson.c:3107 #, no-c-format msgid "Adds to blue based on red level" msgstr "Verhoogt blauw op basis van de roodwaarde" #: backend/epson.c:3108 #, no-c-format msgid "Adds to green based on blue level" msgstr "Verhoogt groen op basis van de blauwwaarde" #: backend/epson.c:3109 #, no-c-format msgid "Adds to red based on blue level" msgstr "Verhoogt rood op basis van de blauwwaarde" #: backend/epson.c:3110 #, no-c-format msgid "Controls blue level" msgstr "Regelt de blauwwaarde" #: backend/epson.c:3206 backend/epson2.c:1256 #, no-c-format msgid "Mirror the image." msgstr "Spiegel het beeld." #: backend/epson.c:3232 backend/mustek.c:4332 #, no-c-format msgid "Fast preview" msgstr "Snelle voorbeeldscan" #: backend/epson.c:3245 backend/epson2.c:1266 #, no-c-format msgid "Auto area segmentation" msgstr "Automatische verdeling van het scanoppervlak" #: backend/epson.c:3258 #, no-c-format msgid "Short resolution list" msgstr "Korte oplossingenlijst" #: backend/epson.c:3260 #, no-c-format msgid "Display short resolution list" msgstr "Toon korte lijst met oplossingen" #: backend/epson.c:3267 #, no-c-format msgid "Zoom" msgstr "Vergroten" #: backend/epson.c:3269 #, no-c-format msgid "Defines the zoom factor the scanner will use" msgstr "Definieert de vergrotingsfactor die de scanner zal gebruiken" #: backend/epson.c:3349 #, no-c-format msgid "Quick format" msgstr "Snelle opmaak" #: backend/epson.c:3360 backend/epson2.c:1341 #, no-c-format msgid "Optional equipment" msgstr "Optioneel hulpstuk" #: backend/epson.c:3431 backend/epson2.c:1394 #, no-c-format msgid "Eject" msgstr "Uitwerpen" #: backend/epson.c:3432 backend/epson2.c:1395 #, no-c-format msgid "Eject the sheet in the ADF" msgstr "Werp het document in de automatische documentinvoer uit" #: backend/epson.c:3444 backend/epson2.c:1405 #, no-c-format msgid "Auto eject" msgstr "Automatische uitworp" #: backend/epson.c:3445 backend/epson2.c:1407 #, no-c-format msgid "Eject document after scanning" msgstr "Werp het document uit na het scannen" #: backend/epson.c:3457 backend/epson2.c:1417 backend/magicolor.c:2419 #, no-c-format msgid "ADF Mode" msgstr "Automatische documentinvoer Modus" #: backend/epson.c:3459 backend/epson2.c:1419 backend/magicolor.c:2421 #, no-c-format msgid "Selects the ADF mode (simplex/duplex)" msgstr "" "Selecteert de Automatische documentinvoer modus (enkelzijdig/" "dubbelzijdig)" #: backend/epson.c:3473 backend/epson2.c:1431 #, no-c-format msgid "Bay" msgstr "Bak" #: backend/epson.c:3474 backend/epson2.c:1432 #, no-c-format msgid "Select bay to scan" msgstr "Kies de bak om te scannen" #: backend/epson.h:69 backend/epson2.h:68 #, no-c-format msgid "" "Selects the gamma correction value from a list of pre-defined devices or " "the user defined table, which can be downloaded to the scanner" msgstr "" "Selecteert de gammacorrectiewaarde uit een lijst met voorgedefinieerde " "apparaten of de door de gebruiker gedefinieerde tabel die naar de " "scanner kan worden gestuurd" #: backend/epson.h:72 backend/epson2.h:71 #, no-c-format msgid "Focus Position" msgstr "Focus positie" #: backend/epson.h:73 backend/epson2.h:72 #, no-c-format msgid "" "Sets the focus position to either the glass or 2.5mm above the glass" msgstr "Stelt de focus in op het glas of 2.5mm daarboven" #: backend/epson.h:75 backend/epson2.h:74 #, no-c-format msgid "Wait for Button" msgstr "Wacht op een druk op de knop" #: backend/epson.h:76 backend/epson2.h:75 #, no-c-format msgid "" "After sending the scan command, wait until the button on the scanner is " "pressed to actually start the scan process." msgstr "" "Begin pas met scannen als eerst het scancommando naar de scanner is " "gestuurd en daarna de knop van de scanner is ingedrukt." #: backend/epson2.c:102 backend/pixma.c:390 #, no-c-format msgid "Infrared" msgstr "Infrarood" #: backend/epson2.c:117 #, no-c-format msgid "TPU8x10" msgstr "TPU8x10" #: backend/epson2.c:136 #, no-c-format msgid "Positive Slide" msgstr "Dia" #: backend/epson2.c:137 #, no-c-format msgid "Negative Slide" msgstr "Negatief" #: backend/epson2.c:215 #, no-c-format msgid "Built in CCT profile" msgstr "Ingebouwd CCT profiel" #: backend/epson2.c:216 #, no-c-format msgid "User defined CCT profile" msgstr "Door gebruiker gedefinieerd CCT profiel" #: backend/fujitsu.c:683 backend/hp-option.c:3327 backend/hp-option.c:3340 #, no-c-format msgid "On" msgstr "Aan" #: backend/fujitsu.c:684 backend/hp-option.c:3159 backend/hp-option.c:3326 #: backend/hp-option.c:3339 #, no-c-format msgid "Off" msgstr "Uit" #: backend/fujitsu.c:686 #, no-c-format msgid "DTC" msgstr "DTC" #: backend/fujitsu.c:687 #, no-c-format msgid "SDTC" msgstr "SDTC" #: backend/fujitsu.c:689 backend/teco1.c:1152 backend/teco1.c:1153 #: backend/teco2.c:1971 backend/teco2.c:1972 backend/teco3.c:977 #: backend/teco3.c:978 #, no-c-format msgid "Dither" msgstr "Dither" #: backend/fujitsu.c:690 #, no-c-format msgid "Diffusion" msgstr "Verspreiding" #: backend/fujitsu.c:695 #, no-c-format msgid "White" msgstr "Wit" #: backend/fujitsu.c:696 #, no-c-format msgid "Black" msgstr "Zwart" #: backend/fujitsu.c:701 #, no-c-format msgid "Continue" msgstr "Voortzetten" #: backend/fujitsu.c:702 #, no-c-format msgid "Stop" msgstr "Stoppen" #: backend/fujitsu.c:704 #, no-c-format msgid "10mm" msgstr "10mm" #: backend/fujitsu.c:705 #, no-c-format msgid "15mm" msgstr "15mm" #: backend/fujitsu.c:706 #, no-c-format msgid "20mm" msgstr "20mm" #: backend/fujitsu.c:708 backend/hp-option.c:3045 #, no-c-format msgid "Horizontal" msgstr "Horizontaal" #: backend/fujitsu.c:709 #, no-c-format msgid "Horizontal bold" msgstr "Horizontaal vet" #: backend/fujitsu.c:710 #, no-c-format msgid "Horizontal narrow" msgstr "Horizontaal smal" #: backend/fujitsu.c:711 backend/hp-option.c:3044 #, no-c-format msgid "Vertical" msgstr "Verticaal" #: backend/fujitsu.c:712 #, no-c-format msgid "Vertical bold" msgstr "Verticaal vet" #: backend/fujitsu.c:714 #, no-c-format msgid "Top to bottom" msgstr "Van boven naar beneden" #: backend/fujitsu.c:715 #, no-c-format msgid "Bottom to top" msgstr "Van beneden naar boven" #: backend/fujitsu.c:717 #, no-c-format msgid "Front" msgstr "Voorzijde" #: backend/fujitsu.c:718 #, no-c-format msgid "Back" msgstr "Achterzijde" #: backend/fujitsu.c:3097 backend/pixma_sane_options.c:145 #, no-c-format msgid "Gamma function exponent" msgstr "Gammafunctie exponent" #: backend/fujitsu.c:3098 backend/pixma_sane_options.c:146 #, no-c-format msgid "Changes intensity of midtones" msgstr "Verandert de intensiteit van de middentonen" #: backend/fujitsu.c:3147 #, no-c-format msgid "RIF" msgstr "GBF" #: backend/fujitsu.c:3148 #, no-c-format msgid "Reverse image format" msgstr "Gespiegeld beeld formaat" #: backend/fujitsu.c:3165 #, no-c-format msgid "Halftone type" msgstr "Halftoon type" #: backend/fujitsu.c:3166 #, no-c-format msgid "Control type of halftone filter" msgstr "Regeltype van het halftoon filter" #: backend/fujitsu.c:3187 #, no-c-format msgid "Control pattern of halftone filter" msgstr "Regelpatroon van het halftoon filter" #: backend/fujitsu.c:3209 #, fuzzy, no-c-format msgid "Outline" msgstr "Omtrek" #: backend/fujitsu.c:3210 #, fuzzy, no-c-format msgid "Perform outline extraction" msgstr "Voer omtrek extractie uit" #: backend/fujitsu.c:3221 #, no-c-format msgid "Emphasis" msgstr "Nadruk" #: backend/fujitsu.c:3222 #, no-c-format msgid "Negative to smooth or positive to sharpen image" msgstr "Negatief naar geleidelijk of positief naar scherp beeld" #: backend/fujitsu.c:3240 #, no-c-format msgid "Separation" msgstr "Scheiding" #: backend/fujitsu.c:3241 #, no-c-format msgid "Enable automatic separation of image and text" msgstr "Schakel automatische scheiding tussen beeld en tekst in" #: backend/fujitsu.c:3252 #, no-c-format msgid "Mirroring" msgstr "Spiegelen" #: backend/fujitsu.c:3253 #, no-c-format msgid "Reflect output image horizontally" msgstr "Spiegel het resulterende beeld horizontaal" #: backend/fujitsu.c:3270 #, no-c-format msgid "White level follower" msgstr "Witwaarde volger" #: backend/fujitsu.c:3271 #, no-c-format msgid "Control white level follower" msgstr "Regel de witwaarde volger" #: backend/fujitsu.c:3289 #, no-c-format msgid "BP filter" msgstr "BP filter" #: backend/fujitsu.c:3290 #, no-c-format msgid "Improves quality of high resolution ball-point pen text" msgstr "Verbeterd de kwaliteit van hoog resolutie bal-punt pen tekst" #: backend/fujitsu.c:3306 backend/hp-option.h:73 #, no-c-format msgid "Smoothing" msgstr "Verzachten" #: backend/fujitsu.c:3307 #, no-c-format msgid "Enable smoothing for improved OCR" msgstr "Schakelt verzachting in om OCR te verbeteren" #: backend/fujitsu.c:3323 #, no-c-format msgid "Gamma curve" msgstr "Gammakromme" #: backend/fujitsu.c:3324 #, no-c-format msgid "Gamma curve, from light to dark, but upper two may not work" msgstr "" "Gammakromme, van licht naar donker, maar bovenste twee werken misschien " "niet" #: backend/fujitsu.c:3346 backend/genesys.c:5832 #: backend/pixma_sane_options.c:335 #, no-c-format msgid "Threshold curve" msgstr "Drempel curve" #: backend/fujitsu.c:3347 #, no-c-format msgid "" "Threshold curve, from light to dark, but upper two may not be linear" msgstr "" "Drempel curve, van licht naar donker, maar bovenste twee zijn misschien " "niet liniair" #: backend/fujitsu.c:3369 #, no-c-format msgid "Threshold white" msgstr "Drempel wit" #: backend/fujitsu.c:3370 #, no-c-format msgid "Set pixels equal to threshold to white instead of black" msgstr "Stelt schermpunten in overeenkomstig de drempel voor wit ipv zwart" #: backend/fujitsu.c:3386 backend/fujitsu.c:3387 #, no-c-format msgid "Noise removal" msgstr "Ruisverwijdering" #: backend/fujitsu.c:3403 #, no-c-format msgid "Matrix 5x5" msgstr "Matrix 5x5" #: backend/fujitsu.c:3404 #, fuzzy, no-c-format msgid "Remove 5 pixel square noise" msgstr "Verwijder 5 beeldpunten in een vierkant ruis" #: backend/fujitsu.c:3420 #, no-c-format msgid "Matrix 4x4" msgstr "Matrix 4x4" #: backend/fujitsu.c:3421 #, fuzzy, no-c-format msgid "Remove 4 pixel square noise" msgstr "Verwijder 4 beeldpunten in een vierkant ruis" #: backend/fujitsu.c:3437 #, no-c-format msgid "Matrix 3x3" msgstr "Matrix 3x3" #: backend/fujitsu.c:3438 #, fuzzy, no-c-format msgid "Remove 3 pixel square noise" msgstr "Verwijder 3 beeldpunten in een vierkant ruis" #: backend/fujitsu.c:3454 #, no-c-format msgid "Matrix 2x2" msgstr "Matrix 2x2" #: backend/fujitsu.c:3455 #, no-c-format msgid "Remove 2 pixel square noise" msgstr "Verwijder 2 beeldpunten in een vierkant ruis" #: backend/fujitsu.c:3474 #, no-c-format msgid "Variance" msgstr "Variantie" #: backend/fujitsu.c:3475 #, no-c-format msgid "Set SDTC variance rate (sensitivity), 0 equals 127" msgstr "Stelt SDTC variantie rato in (gevoeligheid), 0 is gelijk aan 127" #: backend/fujitsu.c:3508 #, no-c-format msgid "Auto width detection" msgstr "Automatische breedte herkenning" #: backend/fujitsu.c:3509 #, no-c-format msgid "Scanner detects paper sides. May reduce scanning speed." msgstr "Scanner herkent paper zijden. Kan de scansnelheid verminderen." #: backend/fujitsu.c:3526 #, no-c-format msgid "Auto length detection" msgstr "Automatische lengte herkenning" #: backend/fujitsu.c:3527 #, no-c-format msgid "Scanner detects paper lower edge. May confuse some frontends." msgstr "" "Scanner herkent onderzijde van het papier. Kan sommige frontends in de " "war brengen." #: backend/fujitsu.c:3553 #, no-c-format msgid "Compression" msgstr "Compressie" #: backend/fujitsu.c:3554 #, no-c-format msgid "Enable compressed data. May crash your front-end program" msgstr "" "Schakelt gecomprimeerde gegevens in. Kan je front-end programma laten " "crashen." #: backend/fujitsu.c:3574 #, no-c-format msgid "Compression argument" msgstr "Compressie argument" #: backend/fujitsu.c:3575 #, no-c-format msgid "" "Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) " "is same as 4" msgstr "" "Niveau van JPEG compressie. 1 is klein bestand, 7 is groot bestand. 0 " "(standaard) is hetzelfde als 4" #: backend/fujitsu.c:3605 #, no-c-format msgid "DF action" msgstr "DF actie" #: backend/fujitsu.c:3606 #, no-c-format msgid "Action following double feed error" msgstr "Actie die volgt op dubbele doorvoer fout" #: backend/fujitsu.c:3622 #, no-c-format msgid "DF skew" msgstr "DF scheefheid" #: backend/fujitsu.c:3623 #, no-c-format msgid "Enable double feed error due to skew" msgstr "Schakel dubbele doorvoer fout in als gevolg van scheefheid" #: backend/fujitsu.c:3641 #, no-c-format msgid "DF thickness" msgstr "DF dikte" #: backend/fujitsu.c:3642 #, no-c-format msgid "Enable double feed error due to paper thickness" msgstr "Stelt dubbele doorvoer fout in als gevolg van papierdikte" #: backend/fujitsu.c:3660 #, no-c-format msgid "DF length" msgstr "DF lengte" #: backend/fujitsu.c:3661 #, no-c-format msgid "Enable double feed error due to paper length" msgstr "Stelt dubbele doorvoer fout in als gevolg van papierlengte" #: backend/fujitsu.c:3684 #, no-c-format msgid "DF length difference" msgstr "DF lengte verschil" #: backend/fujitsu.c:3685 #, no-c-format msgid "Difference in page length to trigger double feed error" msgstr "Verschil in papier lengte om dubbele doorvoer fout te veroorzaken" #: backend/fujitsu.c:3708 #, no-c-format msgid "DF recovery mode" msgstr "DF herstel modus" #: backend/fujitsu.c:3709 #, no-c-format msgid "Request scanner to reverse feed on paper jam" msgstr "Vraag de scanner de doorvoer om te keren bij papier opstopping" #: backend/fujitsu.c:3728 #, no-c-format msgid "Paper protection" msgstr "Papier protectie" #: backend/fujitsu.c:3729 #, no-c-format msgid "Request scanner to predict jams in the ADF" msgstr "Vraag de scanner opstoppingen in de ADF te voorspellen " #: backend/fujitsu.c:3748 #, no-c-format msgid "Advanced paper protection" msgstr "Geavanceerde papier protectie" #: backend/fujitsu.c:3749 #, no-c-format msgid "Request scanner to predict jams in the ADF using improved sensors" msgstr "" "Vraag de scanner opstoppingen in de ADF te voorspellen met behulp van " "verbeterde sensoren" #: backend/fujitsu.c:3768 #, no-c-format msgid "Staple detection" msgstr "Nietjes detectie" #: backend/fujitsu.c:3769 #, no-c-format msgid "Request scanner to detect jams in the ADF caused by staples" msgstr "" "Vraag de scanner opstoppingen in de ADF te detecteren die worden " "veroorzaakt door nietjes" #: backend/fujitsu.c:3788 #, no-c-format msgid "Background color" msgstr "Achtergrond kleur" #: backend/fujitsu.c:3789 #, no-c-format msgid "" "Set color of background for scans. May conflict with overscan option" msgstr "" "Stel de achtergrond kleur van scans in. Kan conflicteren met de " "'overscan' optie" #: backend/fujitsu.c:3809 #, no-c-format msgid "Dropout color" msgstr "Uitvalkleur" #: backend/fujitsu.c:3810 #, no-c-format msgid "" "One-pass scanners use only one color during gray or binary scanning, " "useful for colored paper or ink" msgstr "" "One-pass scanners gebruiken slechts een kleur bij grijstrap of binair " "scannen, bruikbaar voor gekleurd papier of inkt." #: backend/fujitsu.c:3833 #, no-c-format msgid "Buffer mode" msgstr "Buffermodus" #: backend/fujitsu.c:3834 #, no-c-format msgid "Request scanner to read pages quickly from ADF into internal memory" msgstr "" "Vraag de scanner pagina's vanuit de ADF zo snel mogelijk in te lezen in " "het interne geheugen" #: backend/fujitsu.c:3853 #, no-c-format msgid "Prepick" msgstr "Voorkeuze" #: backend/fujitsu.c:3854 #, no-c-format msgid "Request scanner to grab next page from ADF" msgstr "Vraag de scanner de volgende pagina uit de ADF op te halen" #: backend/fujitsu.c:3873 #, no-c-format msgid "Overscan" msgstr "Overscan" #: backend/fujitsu.c:3874 #, no-c-format msgid "" "Collect a few mm of background on top side of scan, before paper enters " "ADF, and increase maximum scan area beyond paper size, to allow " "collection on remaining sides. May conflict with bgcolor option" msgstr "" "Selecteer een paar mm van de achtergrond aan de bovenkant van de scan, " "voordat het papier de ADF ingaat, en vergroot het maximale scan " "oppervlak t.o.v. het papierformaat, om de inzameling van de overige " "kanten toe te staan. Kan conflicteren met 'bgcolor' optie" #: backend/fujitsu.c:3892 #, no-c-format msgid "Sleep timer" msgstr "Tijdschakelaar - slaapstand" #: backend/fujitsu.c:3893 #, no-c-format msgid "" "Time in minutes until the internal power supply switches to sleep mode" msgstr "" "Tijd in minuten voordat de interne voeding overschakelt naar slaap modus" #: backend/fujitsu.c:3911 #, no-c-format msgid "Off timer" msgstr "Tijdschakelaar - uitstand" #: backend/fujitsu.c:3912 #, no-c-format msgid "" "Time in minutes until the internal power supply switches the scanner " "off. Will be rounded to nearest 15 minutes. Zero means never power off." msgstr "" "Tijd in minuten voordat de interne voeding de scanner uitschakelt. In " "stappen van 15 minuten. Nul betekent nooit uitschakelen" #: backend/fujitsu.c:3930 #, no-c-format msgid "Duplex offset" msgstr "Dubbelzijdige compensatie" #: backend/fujitsu.c:3931 #, no-c-format msgid "Adjust front/back offset" msgstr "Pas voor-/achtercompensatie aan" #: backend/fujitsu.c:3948 backend/plustek.c:1025 backend/umax_pp.c:804 #, no-c-format msgid "Green offset" msgstr "Groen compensatie" #: backend/fujitsu.c:3949 #, no-c-format msgid "Adjust green/red offset" msgstr "Pas groen-/roodcompensatie aan" #: backend/fujitsu.c:3966 backend/plustek.c:1041 backend/umax_pp.c:816 #, no-c-format msgid "Blue offset" msgstr "Blauw compensatie" #: backend/fujitsu.c:3967 #, no-c-format msgid "Adjust blue/red offset" msgstr "Pas blauw-/roodcompensatie aan" #: backend/fujitsu.c:3980 #, no-c-format msgid "Low Memory" msgstr "Te weinig geheugen beschikbaar" #: backend/fujitsu.c:3981 #, no-c-format msgid "" "Limit driver memory usage for use in embedded systems. Causes some " "duplex transfers to alternate sides on each call to sane_read. Value of " "option 'side' can be used to determine correct image. This option should " "only be used with custom front-end software." msgstr "" "Beperk het geheugengebruik door het stuurprogramma in ingebedde " "systemen. Zorgt bij sommige duplex scans voor wisselende zijden bij de " "aanroep van sane_read. De waarde van de optie 'zijde' kan worden " "gebruikt om het juiste beeld vast te stellen. Deze optie dient " "uitsluitend te worden gebruikt door aangepaste front-end software." #: backend/fujitsu.c:3996 #, no-c-format msgid "Duplex side" msgstr "Duplex zijde" #: backend/fujitsu.c:3997 #, no-c-format msgid "" "Tells which side (0=front, 1=back) of a duplex scan the next call to " "sane_read will return." msgstr "" "Vertelt welke zijde (0=voorkant, 1=achterkant) van een duplex scan bij " "de volgende aanroep van sane_read wordt geretourneerd." #: backend/fujitsu.c:4008 #, no-c-format msgid "Hardware deskew and crop" msgstr "Hardware rechtzetten en afknippen" #: backend/fujitsu.c:4009 #, no-c-format msgid "Request scanner to rotate and crop pages digitally." msgstr "Vraag de scanner pagina's digitaal te roteren en af te knippen." #: backend/fujitsu.c:4020 backend/kvs1025_opt.c:872 #, no-c-format msgid "Software deskew" msgstr "Softwarematige scheefheid correctie" #: backend/fujitsu.c:4021 #, no-c-format msgid "Request driver to rotate skewed pages digitally." msgstr "" "Vraag het stuurprogramma scheef getrokken pagina's digitaal te roteren." #: backend/fujitsu.c:4033 backend/kvs1025_opt.c:881 #, no-c-format msgid "Software despeckle diameter" msgstr "Softwarematige ontspikkel omvang" #: backend/fujitsu.c:4034 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan." msgstr "" "Maximale diameter van verspreid liggende spikkels, die van het gescande " "beeld moeten worden verwijderd." #: backend/fujitsu.c:4053 backend/genesys.c:5760 #, no-c-format msgid "Software crop" msgstr "Softwarematig uitsnijden" #: backend/fujitsu.c:4054 #, no-c-format msgid "Request driver to remove border from pages digitally." msgstr "" "Vraag het stuurprogramma randen van pagina's digitaal te verwijderen." #: backend/fujitsu.c:4083 #, no-c-format msgid "Halt on Cancel" msgstr "Stoppen bij annuleren" #: backend/fujitsu.c:4084 #, no-c-format msgid "" "Request driver to halt the paper feed instead of eject during a cancel." msgstr "" "Vraag het stuurprogramma de papierdoorvoer te stoppen i.p.v. uit te " "werpen tijdens een annulering" #: backend/fujitsu.c:4095 #, no-c-format msgid "Endorser Options" msgstr "Endorser-opties" #: backend/fujitsu.c:4096 #, no-c-format msgid "Controls for endorser unit" msgstr "Stuurt de Endorser eenheid aan" #: backend/fujitsu.c:4107 #, no-c-format msgid "Endorser" msgstr "Endorser" #: backend/fujitsu.c:4108 #, no-c-format msgid "Enable endorser unit" msgstr "Schakel Endorser eenheid in" #: backend/fujitsu.c:4123 #, no-c-format msgid "Endorser bits" msgstr "Endorser delen" #: backend/fujitsu.c:4124 #, no-c-format msgid "Determines maximum endorser counter value." msgstr "Bepaald maximale Endorser teller waarde" #: backend/fujitsu.c:4149 #, no-c-format msgid "Endorser value" msgstr "Endorser waarde" #: backend/fujitsu.c:4150 #, no-c-format msgid "Initial endorser counter value." msgstr "Initiële Endorser teller waarde" #: backend/fujitsu.c:4173 #, no-c-format msgid "Endorser step" msgstr "Endorser stap" #: backend/fujitsu.c:4174 #, no-c-format msgid "Change endorser counter value by this much for each page." msgstr "" "Wijzig Endorser teller waarde met deze hoeveelheid voor elke pagina" #: backend/fujitsu.c:4197 #, no-c-format msgid "Endorser Y" msgstr "Endorser Y" #: backend/fujitsu.c:4198 #, no-c-format msgid "Endorser print offset from top of paper." msgstr "Endorser afdruk compensatie vanaf de bovenkant van het papier" #: backend/fujitsu.c:4223 #, no-c-format msgid "Endorser font" msgstr "Endorser lettertype" #: backend/fujitsu.c:4224 #, no-c-format msgid "Endorser printing font." msgstr "Endorser afdruk lettertype" #: backend/fujitsu.c:4253 #, no-c-format msgid "Endorser direction" msgstr "Endorser richting" #: backend/fujitsu.c:4254 #, no-c-format msgid "Endorser printing direction." msgstr "Endorser afdruk richting" #: backend/fujitsu.c:4278 #, no-c-format msgid "Endorser side" msgstr "Endorser zijde" #: backend/fujitsu.c:4279 #, no-c-format msgid "Endorser printing side, requires hardware support to change" msgstr "" "Endorser afdrukzijde, vereist hardware ondersteuning om te worden " "gewijzigd" #: backend/fujitsu.c:4304 #, no-c-format msgid "Endorser string" msgstr "Endorser tekst" #: backend/fujitsu.c:4305 #, no-c-format msgid "" "Endorser alphanumeric print format. %05ud or %08ud at the end will be " "replaced by counter value." msgstr "" "Endorser alfanumerieke afdrukformaat. %05ud of %08ud zal aan het eind " "worden vervangen door de teller waarde." #: backend/fujitsu.c:4332 #, no-c-format msgid "Top edge" msgstr "Bovenrand" #: backend/fujitsu.c:4333 #, no-c-format msgid "Paper is pulled partly into adf" msgstr "Papier is gedeeltelijk in de ADF getrokken" #: backend/fujitsu.c:4344 #, no-c-format msgid "A3 paper" msgstr "A3 papier" #: backend/fujitsu.c:4345 #, no-c-format msgid "A3 paper detected" msgstr "A3 papier gedetecteerd" #: backend/fujitsu.c:4356 #, no-c-format msgid "B4 paper" msgstr "B4 papier" #: backend/fujitsu.c:4357 #, no-c-format msgid "B4 paper detected" msgstr "B4 papier gedetecteerd" #: backend/fujitsu.c:4368 #, no-c-format msgid "A4 paper" msgstr "A4 papier" #: backend/fujitsu.c:4369 #, no-c-format msgid "A4 paper detected" msgstr "A4 papier gedetecteerd" #: backend/fujitsu.c:4380 #, no-c-format msgid "B5 paper" msgstr "B5 papier" #: backend/fujitsu.c:4381 #, no-c-format msgid "B5 paper detected" msgstr "B5 papier gedetecteerd" #: backend/fujitsu.c:4404 #, no-c-format msgid "OMR or DF" msgstr "OMR of DF" #: backend/fujitsu.c:4405 #, no-c-format msgid "OMR or double feed detected" msgstr "OMR of dubbele doorvoer gedetecteerd" #: backend/fujitsu.c:4428 #, no-c-format msgid "Power saving" msgstr "Energiebesparende" #: backend/fujitsu.c:4429 #, no-c-format msgid "Scanner in power saving mode" msgstr "Scanner in energiebesparende modus" #: backend/fujitsu.c:4452 #, no-c-format msgid "Manual feed" msgstr "Handmatige doorvoer" #: backend/fujitsu.c:4453 #, no-c-format msgid "Manual feed selected" msgstr "Handmatige doorvoer geselecteerd" #: backend/fujitsu.c:4476 #, no-c-format msgid "Function" msgstr "Functie" #: backend/fujitsu.c:4477 #, no-c-format msgid "Function character on screen" msgstr "Functie karakter op het scherm" #: backend/fujitsu.c:4488 #, no-c-format msgid "Ink low" msgstr "Inkt bijna op" #: backend/fujitsu.c:4489 #, no-c-format msgid "Imprinter ink running low" msgstr "Imprinter inkt is bijna op" #: backend/fujitsu.c:4500 #, no-c-format msgid "Double feed" msgstr "Dubbele doorvoer" #: backend/fujitsu.c:4501 #, no-c-format msgid "Double feed detected" msgstr "Dubbele doorvoer gedetecteerd" #: backend/fujitsu.c:4512 #, no-c-format msgid "Error code" msgstr "Foutcode" #: backend/fujitsu.c:4513 #, no-c-format msgid "Hardware error code" msgstr "Hardware foutcode" #: backend/fujitsu.c:4524 #, no-c-format msgid "Skew angle" msgstr "Scheefheidshoek" #: backend/fujitsu.c:4525 #, no-c-format msgid "Requires black background for scanning" msgstr "Vereist zwarte achtergrond voor het scannen" #: backend/fujitsu.c:4536 #, no-c-format msgid "Ink remaining" msgstr "Resterende hoeveelheid inkt" #: backend/fujitsu.c:4537 #, no-c-format msgid "Imprinter ink level" msgstr "Imprinter inkt niveau" #: backend/fujitsu.c:4548 #, no-c-format msgid "Density" msgstr "Dichtheid" #: backend/fujitsu.c:4549 #, no-c-format msgid "Density dial" msgstr "Dichtheid schaal" #: backend/fujitsu.c:4560 backend/fujitsu.c:4561 #, no-c-format msgid "Duplex switch" msgstr "Duplex schakelaar" #: backend/genesys.c:5761 #, no-c-format msgid "Request backend to remove border from pages digitally" msgstr "Vraag backend randen van pagina's digitaal te verwijderen" #: backend/genesys.c:5770 backend/kvs1025_opt.c:913 #, no-c-format msgid "Request driver to discard pages with low numbers of dark pixels" msgstr "" "Vraag het stuurprogramma pagina's met weinig dekking te verwijderen" #: backend/genesys.c:5781 backend/kvs1025_opt.c:893 #, no-c-format msgid "Software derotate" msgstr "Softwarematige rotatie tegen de klok in" #: backend/genesys.c:5782 backend/kvs1025_opt.c:895 #, no-c-format msgid "Request driver to detect and correct 90 degree image rotation" msgstr "" "Vraag stuurprogramma een 90 graden gedraaid beeld te herkennen en " "corrigeren" #: backend/genesys.c:5813 backend/pixma_sane_options.c:314 #, no-c-format msgid "Extras" msgstr "Extra's" #: backend/genesys.c:5833 backend/pixma_sane_options.c:336 #, no-c-format msgid "Dynamic threshold curve, from light to dark, normally 50-65" msgstr "Dynamische drempel curve, van licht naar donker, normaal 50-65" #: backend/genesys.c:5842 #, no-c-format msgid "Disable dynamic lineart" msgstr "Dynamische lijntekening uitschakelen" #: backend/genesys.c:5844 #, no-c-format msgid "" "Disable use of a software adaptive algorithm to generate lineart relying " "instead on hardware lineart." msgstr "" "Schakel, om een lijntekening te genereren het gebruik van een software " "aanpassend algoritme uit en vertrouw in plaats daarvan op de hardware." #: backend/genesys.c:5860 #, no-c-format msgid "Disable interpolation" msgstr "Schakel interpolatie uit" #: backend/genesys.c:5863 #, no-c-format msgid "" "When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation." msgstr "" "Wanneer hoge resoluties worden gebruikt, waarbij de horizontale " "resolutie kleiner is dan de verticale resolutie, wordt de horizontale " "interpolatie uitgeschakeld." #: backend/genesys.c:5872 #, no-c-format msgid "Color filter" msgstr "Kleurenfilter" #: backend/genesys.c:5875 #, no-c-format msgid "When using gray or lineart this option selects the used color." msgstr "" "Wanneer grijs of lijntekening wordt gebruikt, selecteert deze optie de " "huidige actieve kleur." #: backend/genesys.c:5901 #, no-c-format msgid "Calibration file" msgstr "Kalibratiebestand" #: backend/genesys.c:5902 #, no-c-format msgid "Specify the calibration file to use" msgstr "Specificeer het te gebruiken kalibratiebestand" #: backend/genesys.c:5919 #, no-c-format msgid "Calibration cache expiration time" msgstr "Vervaltijd van de kalibratie cache" #: backend/genesys.c:5920 #, no-c-format msgid "" "Time (in minutes) before a cached calibration expires. A value of 0 " "means cache is not used. A negative value means cache never expires." msgstr "" "Tijd (in minuten) voordat een gecachete kalibratie verloopt. Een waarde " "van 0 betekent dat geen cache wordt gebruikt. Een negatieve waarde " "betekent dat de cache nooit verloopt." #: backend/genesys.c:5930 #, no-c-format msgid "Lamp off time" msgstr "Lamp-uit tijd" #: backend/genesys.c:5933 #, no-c-format msgid "" "The lamp will be turned off after the given time (in minutes). A value " "of 0 means, that the lamp won't be turned off." msgstr "" "De lamp wordt uitgeschakeld na de opgegeven tijd (in minuten). Een " "waarde van 0 betekent, dat de lamp niet wordt uitgeschakeld." #: backend/genesys.c:5943 #, no-c-format msgid "Lamp off during scan" msgstr "Lamp uit tijdens het scannen" #: backend/genesys.c:5944 #, no-c-format msgid "The lamp will be turned off during scan. " msgstr "De lamp wordt uitgeschakeld tijdens het scannen" #: backend/genesys.c:5972 backend/genesys.c:5973 #, no-c-format msgid "File button" msgstr "Bestand-knop" #: backend/genesys.c:6025 backend/genesys.c:6026 #, no-c-format msgid "OCR button" msgstr "OCR-knop" #: backend/genesys.c:6039 backend/genesys.c:6040 #, no-c-format msgid "Power button" msgstr "Aan/Uit-knop" #: backend/genesys.c:6053 backend/genesys.c:6054 #, no-c-format msgid "Extra button" msgstr "Extra-knop" #: backend/genesys.c:6067 backend/gt68xx.c:762 #, no-c-format msgid "Need calibration" msgstr "Kalibratie nodig" #: backend/genesys.c:6068 backend/gt68xx.c:763 #, no-c-format msgid "The scanner needs calibration for the current settings" msgstr "De scanner moet worden gekalibreerd voor de huidige instellingen" #: backend/genesys.c:6080 backend/gt68xx.c:787 backend/gt68xx.c:788 #: backend/pixma_sane_options.c:226 backend/plustek.c:1080 #, no-c-format msgid "Buttons" msgstr "Knoppen" #: backend/genesys.c:6089 backend/gt68xx.c:794 backend/hp5400_sane.c:392 #: backend/hp-option.h:97 backend/niash.c:726 backend/plustek.c:941 #, no-c-format msgid "Calibrate" msgstr "Kalibreren" #: backend/genesys.c:6091 backend/gt68xx.c:796 #, no-c-format msgid "Start calibration using special sheet" msgstr "Begin kalibreerproces met een speciale transparant" #: backend/genesys.c:6105 backend/gt68xx.c:809 #, no-c-format msgid "Clear calibration" msgstr "Reset kalibratie" #: backend/genesys.c:6106 backend/gt68xx.c:810 #, no-c-format msgid "Clear calibration cache" msgstr "Reset kalibratiecache" #: backend/gt68xx.c:149 backend/ma1509.c:108 backend/mustek.c:164 #: backend/snapscan-options.c:87 backend/umax.c:182 #, no-c-format msgid "Transparency Adapter" msgstr "Transparantenhulpstuk" #: backend/gt68xx.c:477 #, no-c-format msgid "Gray mode color" msgstr "Kleur in grijsmodus" #: backend/gt68xx.c:479 #, no-c-format msgid "Selects which scan color is used gray mode (default: green)." msgstr "" "Selecteert de scankleur die in de grijsmodus wordt gebruikt (Standaard: " "groen)" #: backend/gt68xx.c:560 backend/hp3900_sane.c:1392 #: backend/mustek_usb2.c:410 #, no-c-format msgid "Debugging Options" msgstr "Foutzoekopties" #: backend/gt68xx.c:571 backend/mustek_usb2.c:419 #, no-c-format msgid "Automatic warmup" msgstr "Automatisch opwarmen" #: backend/gt68xx.c:573 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "60 seconds warm-up time." msgstr "" "Warm op totdat de helderheid van de lamp constant is in plaats van de " "'verplichte' 60 seconde opwarmtijd aan te houden." #: backend/gt68xx.c:585 #, no-c-format msgid "Full scan" msgstr "Volledige scan" #: backend/gt68xx.c:587 #, no-c-format msgid "" "Scan the complete scanning area including calibration strip. Be careful. " "Don't select the full height. For testing only." msgstr "" "Scan het volledige scanbereik inclusief de kalibereerstrook. Pas op! " "Kies niet een te grote hoogte. Alleen voor testdoeleinden." #: backend/gt68xx.c:598 #, no-c-format msgid "Coarse calibration" msgstr "Grove kalibratie" #: backend/gt68xx.c:600 #, no-c-format msgid "" "Setup gain and offset for scanning automatically. If this option is " "disabled, options for setting the analog frontend parameters manually " "are provided. This option is enabled by default. For testing only." msgstr "" "Stel bereik en compensatie automatisch in. Wanneer deze optie is " "uitgeschakeld, kunnen de analoge \"frontend\" parameters handmatig " "worden ingesteld. Deze optie staat standaard aan. Alleen voor " "testdoeleinden." #: backend/gt68xx.c:619 #, no-c-format msgid "Coarse calibration for first scan only" msgstr "Grove kalibratie alleen voor de eerste scan" #: backend/gt68xx.c:621 #, no-c-format msgid "" "Coarse calibration is only done for the first scan. Works with most " "scanners and can save scanning time. If the image brightness is " "different with each scan, disable this option. For testing only." msgstr "" "Grove kalibratie wordt alleen voor de eerste scan uitgevoerd. Dit werkt " "bij de meeste scanners en kan scantijd schelen. Wanneer de helderheid " "van het beeld per scan verschilt, schakel deze optie dan uit. Alleen " "voor testdoeleinden." #: backend/gt68xx.c:654 #, no-c-format msgid "Backtrack lines" msgstr "\"Backtrack\" lijnen" #: backend/gt68xx.c:656 #, no-c-format msgid "" "Number of lines the scan slider moves back when backtracking occurs. " "That happens when the scanner scans faster than the computer can receive " "the data. Low values cause faster scans but increase the risk of " "omitting lines." msgstr "" "Het aantal scanlijnen dat de scannerwagen teruggaat als \"backtracking\" " "optreedt. Dit gebeurt als de scanner sneller scant dan de computer de " "data kan verwerken. Lage waarden zorgen voor snellere scans, maar " "vergroten het risico van gemiste scanlijnen." #: backend/gt68xx.c:681 backend/mustek_usb2.c:452 #, no-c-format msgid "Gamma value" msgstr "Gammawaarde" #: backend/gt68xx.c:683 backend/mustek_usb2.c:454 #, no-c-format msgid "Sets the gamma value of all channels." msgstr "Stelt de gammawaarde voor alle kanalen in." #: backend/hp3500.c:1020 #, no-c-format msgid "Geometry Group" msgstr "Geometrie groep" #: backend/hp3500.c:1073 backend/hp3500.c:1074 #, no-c-format msgid "Scan Mode Group" msgstr "Scanmodus groep" #: backend/hp3900_sane.c:427 backend/hp3900_sane.c:1019 #: backend/hp-option.c:3174 #, no-c-format msgid "Slide" msgstr "Dia" #: backend/hp3900_sane.c:1405 #, no-c-format msgid "Scanner model" msgstr "Scanner model" #: backend/hp3900_sane.c:1408 #, no-c-format msgid "Allows one to test device behaviour with other supported models" msgstr "" "Biedt men de mogelijkheid de werking van het apparaat te testen met " "andere ondersteunde modellen." #: backend/hp3900_sane.c:1422 #, no-c-format msgid "Image colours will be inverted" msgstr "Kleuren van het beeld worden geïnverteerd" #: backend/hp3900_sane.c:1436 #, no-c-format msgid "Disable gamma correction" msgstr "Schakel gammacorrectie uit" #: backend/hp3900_sane.c:1437 #, no-c-format msgid "Gamma correction will be disabled" msgstr "Gammacorrectie wordt uitgeschakeld" #: backend/hp3900_sane.c:1451 #, no-c-format msgid "Disable white shading correction" msgstr "Schakel witte schaduw correctie uit" #: backend/hp3900_sane.c:1453 #, no-c-format msgid "White shading correction will be disabled" msgstr "Witte schaduw correctie wordt uitgeschakeld" #: backend/hp3900_sane.c:1467 #, no-c-format msgid "Skip warmup process" msgstr "Sla opwarmprocedure over" #: backend/hp3900_sane.c:1468 #, no-c-format msgid "Warmup process will be disabled" msgstr "Opwarmprocedure wordt uitgeschakeld" #: backend/hp3900_sane.c:1482 #, no-c-format msgid "Force real depth" msgstr "Forceer ware diepte" #: backend/hp3900_sane.c:1485 #, no-c-format msgid "" "If gamma is enabled, scans are always made in 16 bits depth to improve " "image quality and then converted to the selected depth. This option " "avoids depth emulation." msgstr "" "Als gammacorrectie is ingeschakeld, worden scans altijd met 16 bit " "diepte gemaakt om de beeldkwaliteit te verbeteren en daarna " "geconverteerd naar de gekozen diepte. Deze optie schakelt diepte " "emulatie uit." #: backend/hp3900_sane.c:1499 #, no-c-format msgid "Emulate Grayscale" msgstr "Emuleer grijstrap" #: backend/hp3900_sane.c:1502 #, no-c-format msgid "" "If enabled, image will be scanned in color mode and then converted to " "grayscale by software. This may improve image quality in some " "circumstances." msgstr "" "Indien ingeschakeld, wordt het beeld in kleurmodus gescand en daarna " "door de software geconverteerd naar grijswaardes. Dit kan de " "beeldkwaliteit in sommige gevallen verbeteren." #: backend/hp3900_sane.c:1516 #, no-c-format msgid "Save debugging images" msgstr "Bewaar foutzoekbeelden" #: backend/hp3900_sane.c:1519 #, no-c-format msgid "" "If enabled, some images involved in scanner processing are saved to " "analyze them." msgstr "" "Indien ingeschakeld, worden enkele beelden die deel uitmaken van het " "scanproces bewaard, zodat ze kunnen worden geanalyseerd." #: backend/hp3900_sane.c:1533 #, no-c-format msgid "Reset chipset" msgstr "Reset chipset" #: backend/hp3900_sane.c:1534 #, no-c-format msgid "Resets chipset data" msgstr "Reset chipset gegevens" #: backend/hp3900_sane.c:1547 #, no-c-format msgid "Information" msgstr "Informatie" #: backend/hp3900_sane.c:1560 #, no-c-format msgid "Chipset name" msgstr "Naam van de chipset" #: backend/hp3900_sane.c:1561 #, no-c-format msgid "Shows chipset name used in device." msgstr "Toont de naam van de chipset gebruikt in het apparaat." #: backend/hp3900_sane.c:1565 #, no-c-format msgid "Unknown" msgstr "Onbekend" #: backend/hp3900_sane.c:1571 #, no-c-format msgid "Chipset ID" msgstr "Chipset ID" #: backend/hp3900_sane.c:1572 #, no-c-format msgid "Shows the chipset ID" msgstr "Toont de chipset ID" #: backend/hp3900_sane.c:1582 #, no-c-format msgid "Scan counter" msgstr "Scannerteller" #: backend/hp3900_sane.c:1584 #, no-c-format msgid "Shows the number of scans made by scanner" msgstr "Toont het aantal scans dat de scanner heeft gemaakt" #: backend/hp3900_sane.c:1594 #, no-c-format msgid "Update information" msgstr "Werk de informatie bij" #: backend/hp3900_sane.c:1595 #, no-c-format msgid "Updates information about device" msgstr "Werkt de informatie over het apparaat bij" #: backend/hp3900_sane.c:1635 #, no-c-format msgid "This option reflects a front panel scanner button" msgstr "Deze optie geeft de scannerknoppen op het apparaat weer" #: backend/hp5400_sane.c:313 backend/niash.c:678 #, no-c-format msgid "Image" msgstr "Beeld" #: backend/hp5400_sane.c:352 backend/niash.c:709 #, no-c-format msgid "Miscellaneous" msgstr "Overig" #: backend/hp5400_sane.c:358 #, no-c-format msgid "offset X" msgstr "compensatie X" #: backend/hp5400_sane.c:359 #, no-c-format msgid "Hardware internal X position of the scanning area." msgstr "X positie in de scanner van het scanoppervlak." #: backend/hp5400_sane.c:368 #, no-c-format msgid "offset Y" msgstr "compensatie Y" #: backend/hp5400_sane.c:369 #, no-c-format msgid "Hardware internal Y position of the scanning area." msgstr "Y positie in de scanner van het scanoppervlak." #: backend/hp5400_sane.c:381 backend/niash.c:716 #, no-c-format msgid "Lamp status" msgstr "Lamp status" #: backend/hp5400_sane.c:382 backend/niash.c:717 #, no-c-format msgid "Switches the lamp on or off." msgstr "Schakelt de lamp aan of uit." #: backend/hp5400_sane.c:393 backend/niash.c:727 #, no-c-format msgid "Calibrates for black and white level." msgstr "Kalibreert voor de zwart-/witwaarde" #: backend/hp5590.c:86 backend/hp-option.c:3253 #, no-c-format msgid "ADF" msgstr "Automatische documentinvoer" #: backend/hp5590.c:88 #, no-c-format msgid "TMA Slides" msgstr "TMA dia's" #: backend/hp5590.c:89 #, no-c-format msgid "TMA Negatives" msgstr "TMA Negatieven" #: backend/hp5590.c:92 #, no-c-format msgid "Color (48 bits)" msgstr "Kleur (48 bits)" #: backend/hp5590.c:95 #, no-c-format msgid "Extend lamp timeout" msgstr "Verleng lamp timeout" #: backend/hp5590.c:96 #, no-c-format msgid "Extends lamp timeout (from 15 minutes to 1 hour)" msgstr "Verlengt de lamp timeout (van 15 minuten tot 1 uur)" #: backend/hp5590.c:98 #, no-c-format msgid "Wait for button" msgstr "Wacht op een druk op de knop" #: backend/hp5590.c:99 #, no-c-format msgid "Waits for button before scanning" msgstr "Wacht op een druk op de knop alvorens te scannen" #: backend/hp-option.c:2984 #, no-c-format msgid "Advanced Options" msgstr "Geavanceerde opties" #: backend/hp-option.c:3041 #, no-c-format msgid "Coarse" msgstr "Grof" #: backend/hp-option.c:3042 #, no-c-format msgid "Fine" msgstr "Fijn" #: backend/hp-option.c:3043 #, no-c-format msgid "Bayer" msgstr "Bayer" #: backend/hp-option.c:3046 backend/hp-option.c:3097 #, no-c-format msgid "Custom" msgstr "Door de gebruiker gedefinieerd" #: backend/hp-option.c:3087 backend/hp-option.c:3143 #: backend/hp-option.c:3158 #, no-c-format msgid "Auto" msgstr "Automatisch" #: backend/hp-option.c:3088 #, no-c-format msgid "NTSC RGB" msgstr "NTSC RGB" #: backend/hp-option.c:3089 #, no-c-format msgid "XPA RGB" msgstr "XPA RGB" #: backend/hp-option.c:3090 #, no-c-format msgid "Pass-through" msgstr "Doorgang" #: backend/hp-option.c:3091 #, no-c-format msgid "NTSC Gray" msgstr "NTSC Grijs" #: backend/hp-option.c:3092 #, no-c-format msgid "XPA Gray" msgstr "XPA Grijs" #: backend/hp-option.c:3144 #, no-c-format msgid "Slow" msgstr "Langzaam" #: backend/hp-option.c:3145 backend/hp-option.c:3252 #: backend/kvs40xx_opt.c:230 backend/matsushita.c:244 backend/mustek.c:149 #: backend/plustek.c:234 backend/plustek_pp.c:203 backend/u12.c:155 #, no-c-format msgid "Normal" msgstr "Normaal" #: backend/hp-option.c:3146 #, no-c-format msgid "Fast" msgstr "Snel" #: backend/hp-option.c:3147 #, no-c-format msgid "Extra Fast" msgstr "Extra snel" #: backend/hp-option.c:3160 #, no-c-format msgid "2-pixel" msgstr "2-beeldpunt" #: backend/hp-option.c:3161 #, no-c-format msgid "4-pixel" msgstr "4-beeldpunt" #: backend/hp-option.c:3162 #, no-c-format msgid "8-pixel" msgstr "8-beeldpunt" #: backend/hp-option.c:3173 #, no-c-format msgid "Print" msgstr "Afdruk" #: backend/hp-option.c:3175 #, no-c-format msgid "Film-strip" msgstr "Filmstrook" #: backend/hp-option.c:3254 #, no-c-format msgid "XPA" msgstr "XPA" #: backend/hp-option.c:3328 backend/hp-option.c:3341 #, no-c-format msgid "Conditional" msgstr "Voorwaardelijk" #: backend/hp-option.c:3414 #, no-c-format msgid "Experiment" msgstr "Experiment" #: backend/hp-option.h:60 #, no-c-format msgid "Sharpening" msgstr "Scherper maken" #: backend/hp-option.h:61 #, no-c-format msgid "Set sharpening value." msgstr "Stel scherpte waarde in." #: backend/hp-option.h:66 #, no-c-format msgid "Auto Threshold" msgstr "Automatische drempelwaarde" #: backend/hp-option.h:68 #, no-c-format msgid "Enable automatic determination of threshold for line-art scans." msgstr "" "Maak automatische bepaling mogelijk van de drempelwaarde voor " "lijntekening scans." #: backend/hp-option.h:74 #, no-c-format msgid "Select smoothing filter." msgstr "Kies halftoon filter." #: backend/hp-option.h:79 #, no-c-format msgid "Unload media after scan" msgstr "Verwijder origineel na de scan" #: backend/hp-option.h:80 #, no-c-format msgid "Unloads the media after a scan." msgstr "Verwijdert het origineel na de scan." #: backend/hp-option.h:85 #, no-c-format msgid "Change document" msgstr "Wijzig origineel" #: backend/hp-option.h:86 #, no-c-format msgid "Change Document." msgstr "Wijzig Origineel." #: backend/hp-option.h:91 #, no-c-format msgid "Unload" msgstr "Verwijder" #: backend/hp-option.h:92 #, no-c-format msgid "Unload Document." msgstr "Verwijder Origineel." #: backend/hp-option.h:98 #, no-c-format msgid "Start calibration process." msgstr "Begin het kalibreer proces" #: backend/hp-option.h:103 #, no-c-format msgid "Media" msgstr "Origineel" #: backend/hp-option.h:104 #, no-c-format msgid "Set type of media." msgstr "Stel origineel type in." #: backend/hp-option.h:109 #, no-c-format msgid "Exposure time" msgstr "Belichtingstijd" #: backend/hp-option.h:111 #, no-c-format msgid "" "A longer exposure time lets the scanner collect more light. Suggested " "use is 175% for prints, 150% for normal slides and \"Negative\" for " "negative film. For dark (underexposed) images you can increase this " "value." msgstr "" "Een langere belichtingstijd laat de scanner meer licht verzamelen. " "Advies is om 175% voor papieren originelen, 150% voor dia's en \"Negatief" "\" voor negatieven te gebruiken. Voor donkere (onderbelichte) beelden " "kun je deze waarde verhogen." #: backend/hp-option.h:119 backend/hp-option.h:126 #, no-c-format msgid "Color Matrix" msgstr "Kleurmatrix" #: backend/hp-option.h:121 #, no-c-format msgid "Set the scanners color matrix." msgstr "Stel de kleurmatrix in van de scanner" #: backend/hp-option.h:127 #, no-c-format msgid "Custom color matrix." msgstr "Door de gebruiker gedefinieerde kleurmatrix" #: backend/hp-option.h:132 #, no-c-format msgid "Mono Color Matrix" msgstr "Mono Kleurmatrix" #: backend/hp-option.h:133 #, no-c-format msgid "Custom color matrix for grayscale scans." msgstr "Door de gebruiker gedefinieerd kleurmatrix voor grijstint scans" #: backend/hp-option.h:138 #, no-c-format msgid "Mirror horizontal" msgstr "Horizontaal spiegelen" #: backend/hp-option.h:139 #, no-c-format msgid "Mirror image horizontally." msgstr "Beeld horizontaal spiegelen" #: backend/hp-option.h:144 #, no-c-format msgid "Mirror vertical" msgstr "Verticaal spiegelen" #: backend/hp-option.h:145 #, no-c-format msgid "Mirror image vertically." msgstr "Beeld verticaal spiegelen" #: backend/hp-option.h:150 #, no-c-format msgid "Update options" msgstr "Opties bijwerken" #: backend/hp-option.h:151 #, no-c-format msgid "Update options." msgstr "Opties bijwerken." #: backend/hp-option.h:156 #, no-c-format msgid "8 bit output" msgstr "8-bit resultaat" #: backend/hp-option.h:158 #, no-c-format msgid "Use bit depth greater eight internally, but output only eight bits." msgstr "Gebruik intern meer dan acht bits, maar geef slechts acht bits." #: backend/hp-option.h:164 #, no-c-format msgid "Front button wait" msgstr "Voorpaneel knop wacht" #: backend/hp-option.h:165 #, no-c-format msgid "Wait to scan for front-panel button push." msgstr "Wacht met scannen totdat knop op voorpaneel is ingedrukt." #: backend/hp-option.h:172 #, no-c-format msgid "Shut off lamp" msgstr "Schakel de lamp uit" #: backend/hp-option.h:173 #, no-c-format msgid "Shut off scanner lamp." msgstr "Schakel de scannerlamp uit." #: backend/kvs1025.h:51 backend/kvs20xx_opt.c:295 #: backend/kvs40xx_opt.c:516 backend/matsushita.h:219 #, no-c-format msgid "Paper size" msgstr "Papierformaat" #: backend/kvs1025.h:52 backend/kvs1025.h:67 backend/matsushita.h:220 #: backend/matsushita.h:227 #, no-c-format msgid "Automatic separation" msgstr "Automatische kleurscheiding" #: backend/kvs1025.h:53 backend/kvs20xx_opt.c:307 #: backend/kvs40xx_opt.c:531 #, no-c-format msgid "Landscape" msgstr "Liggend" #: backend/kvs1025.h:54 backend/kvs40xx_opt.c:693 #, no-c-format msgid "Inverse Image" msgstr "Geïnverteerd beeld" #: backend/kvs1025.h:56 backend/kvs40xx_opt.c:404 #, no-c-format msgid "Long paper mode" msgstr "Groot formaat papier modus" #: backend/kvs1025.h:57 backend/kvs20xx_opt.c:230 #: backend/kvs40xx_opt.c:393 #, no-c-format msgid "Length control mode" msgstr "Lengte-controlemodus" #: backend/kvs1025.h:58 backend/kvs20xx_opt.c:242 #: backend/kvs40xx_opt.c:416 #, no-c-format msgid "Manual feed mode" msgstr "Handmatige doorvoermodus" #: backend/kvs1025.h:59 backend/kvs20xx_opt.c:254 #: backend/kvs40xx_opt.c:428 #, no-c-format msgid "Manual feed timeout" msgstr "Handmatige doorvoer timeout" #: backend/kvs1025.h:60 backend/kvs20xx_opt.c:267 #: backend/kvs40xx_opt.c:441 #, no-c-format msgid "Double feed detection" msgstr "Dubbele doorvoer herkenning" #: backend/kvs1025.h:63 backend/kvs20xx_opt.c:205 #: backend/kvs40xx_opt.c:354 backend/matsushita.h:223 #, no-c-format msgid "Enable Duplex (Dual-Sided) Scanning" msgstr "Schakel dubbelzijdig (duplex) scannen in" #: backend/kvs1025.h:65 backend/kvs20xx_opt.c:296 #: backend/kvs40xx_opt.c:517 backend/matsushita.h:225 #, no-c-format msgid "Physical size of the paper in the ADF" msgstr "" "Feitelijke formaat van het papier in de Automatische documentinvoer" #: backend/kvs1025_opt.c:39 #, no-c-format msgid "bw" msgstr "z/w" #: backend/kvs1025_opt.c:40 #, no-c-format msgid "halftone" msgstr "halftoon" #: backend/kvs1025_opt.c:41 #, no-c-format msgid "gray" msgstr "grijs" #: backend/kvs1025_opt.c:42 #, no-c-format msgid "color" msgstr "kleur" #: backend/kvs1025_opt.c:61 backend/kvs40xx_opt.c:108 #: backend/kvs40xx_opt.c:1047 #, no-c-format msgid "adf" msgstr "adf" #: backend/kvs1025_opt.c:62 backend/kvs40xx_opt.c:50 #: backend/kvs40xx_opt.c:109 #, no-c-format msgid "fb" msgstr "fb" #: backend/kvs1025_opt.c:72 backend/kvs20xx_opt.c:55 #: backend/kvs40xx_opt.c:101 #, no-c-format msgid "single" msgstr "enkel" #: backend/kvs1025_opt.c:73 backend/kvs20xx.c:462 backend/kvs20xx_opt.c:56 #: backend/kvs40xx.c:704 backend/kvs40xx.c:722 backend/kvs40xx_opt.c:102 #: backend/kvs40xx_opt.c:1087 #, no-c-format msgid "continuous" msgstr "continu" #: backend/kvs1025_opt.c:83 backend/kvs20xx_opt.c:62 #: backend/kvs40xx_opt.c:115 #, no-c-format msgid "off" msgstr "uit" #: backend/kvs1025_opt.c:84 backend/kvs20xx_opt.c:63 #: backend/kvs40xx_opt.c:116 #, no-c-format msgid "wait_doc" msgstr "wacht_doc" #: backend/kvs1025_opt.c:85 backend/kvs20xx_opt.c:64 #: backend/kvs40xx_opt.c:118 #, no-c-format msgid "wait_key" msgstr "wacht_toets" #: backend/kvs1025_opt.c:96 backend/kvs20xx_opt.c:70 #: backend/kvs40xx_opt.c:124 backend/kvs40xx_opt.c:141 #, no-c-format msgid "user_def" msgstr "gebruiker_gedefinieerd" #: backend/kvs1025_opt.c:97 backend/kvs20xx_opt.c:71 #: backend/kvs40xx_opt.c:125 backend/kvs40xx_opt.c:142 #, no-c-format msgid "business_card" msgstr "visitekaart" #: backend/kvs1025_opt.c:98 backend/kvs40xx_opt.c:126 #: backend/kvs40xx_opt.c:143 #, no-c-format msgid "Check" msgstr "Controleer" #: backend/kvs1025_opt.c:101 backend/kvs20xx_opt.c:75 #: backend/kvs40xx_opt.c:129 backend/kvs40xx_opt.c:146 #, no-c-format msgid "A5" msgstr "A5" #: backend/kvs1025_opt.c:102 backend/kvs20xx_opt.c:76 #: backend/kvs40xx_opt.c:130 backend/kvs40xx_opt.c:147 #, no-c-format msgid "A6" msgstr "A6" #: backend/kvs1025_opt.c:106 backend/kvs20xx_opt.c:80 #: backend/kvs40xx_opt.c:134 backend/kvs40xx_opt.c:151 #, no-c-format msgid "B5" msgstr "B5" #: backend/kvs1025_opt.c:107 backend/kvs20xx_opt.c:81 #: backend/kvs40xx_opt.c:135 backend/kvs40xx_opt.c:152 #, no-c-format msgid "B6" msgstr "B6" #: backend/kvs1025_opt.c:108 backend/kvs20xx_opt.c:82 #: backend/kvs40xx_opt.c:136 backend/kvs40xx_opt.c:153 #, no-c-format msgid "Legal" msgstr "Legal" #: backend/kvs1025_opt.c:149 backend/kvs40xx_opt.c:239 #, no-c-format msgid "bayer_64" msgstr "bayer 64" #: backend/kvs1025_opt.c:150 backend/kvs40xx_opt.c:240 #, no-c-format msgid "bayer_16" msgstr "bayer 16" #: backend/kvs1025_opt.c:151 backend/kvs40xx_opt.c:241 #, no-c-format msgid "halftone_32" msgstr "halftoon 32" #: backend/kvs1025_opt.c:152 backend/kvs40xx_opt.c:242 #, no-c-format msgid "halftone_64" msgstr "halftoon 64" #: backend/kvs1025_opt.c:153 #, no-c-format msgid "diffusion" msgstr "verspreiding" #: backend/kvs1025_opt.c:166 backend/kvs1025_opt.c:228 #: backend/kvs1025_opt.c:241 backend/kvs20xx_opt.c:129 #: backend/kvs20xx_opt.c:137 backend/kvs40xx_opt.c:215 #: backend/kvs40xx_opt.c:223 backend/kvs40xx_opt.c:258 #, no-c-format msgid "normal" msgstr "normaal" #: backend/kvs1025_opt.c:167 backend/kvs40xx_opt.c:259 #, no-c-format msgid "light" msgstr "licht" #: backend/kvs1025_opt.c:168 backend/kvs40xx_opt.c:260 #, no-c-format msgid "dark" msgstr "donker" #: backend/kvs1025_opt.c:179 backend/kvs40xx_opt.c:271 #, no-c-format msgid "From scanner" msgstr "Vanuit de scanner" #: backend/kvs1025_opt.c:180 backend/kvs40xx_opt.c:272 #: backend/matsushita.c:177 #, no-c-format msgid "From paper" msgstr "Vanaf papier" #: backend/kvs1025_opt.c:192 backend/kvs40xx_opt.c:284 #, no-c-format msgid "default" msgstr "standaardinstelling" #: backend/kvs1025_opt.c:211 backend/kvs20xx_opt.c:123 #: backend/kvs40xx_opt.c:209 #, no-c-format msgid "smooth" msgstr "gelijkmatig" #: backend/kvs1025_opt.c:212 backend/kvs20xx_opt.c:119 #: backend/kvs40xx_opt.c:205 #, no-c-format msgid "none" msgstr "geen" #: backend/kvs1025_opt.c:213 backend/kvs20xx_opt.c:120 #: backend/kvs40xx_opt.c:206 #, no-c-format msgid "low" msgstr "laag" #: backend/kvs1025_opt.c:214 backend/kvs1025_opt.c:804 #: backend/kvs20xx_opt.c:121 backend/kvs40xx_opt.c:207 #, no-c-format msgid "medium" msgstr "gemiddeld" #: backend/kvs1025_opt.c:215 backend/kvs20xx_opt.c:122 #: backend/kvs40xx_opt.c:208 #, no-c-format msgid "high" msgstr "hoog" #: backend/kvs1025_opt.c:229 backend/kvs20xx_opt.c:130 #: backend/kvs40xx_opt.c:216 #, no-c-format msgid "crt" msgstr "crt" #: backend/kvs1025_opt.c:230 #, no-c-format msgid "linier" msgstr "lineair" #: backend/kvs1025_opt.c:242 backend/kvs20xx_opt.c:138 #: backend/kvs40xx_opt.c:224 #, no-c-format msgid "red" msgstr "rood" #: backend/kvs1025_opt.c:243 backend/kvs20xx_opt.c:139 #: backend/kvs40xx_opt.c:225 #, no-c-format msgid "green" msgstr "groen" #: backend/kvs1025_opt.c:244 backend/kvs20xx_opt.c:140 #: backend/kvs40xx_opt.c:226 #, no-c-format msgid "blue" msgstr "blauw" #: backend/kvs1025_opt.c:562 #, no-c-format msgid "Sets the scan source" msgstr "Stelt de scanbron in" #: backend/kvs1025_opt.c:573 backend/kvs20xx_opt.c:218 #: backend/kvs40xx_opt.c:367 backend/matsushita.c:1126 #, no-c-format msgid "Feeder mode" msgstr "Doorvoermodus" #: backend/kvs1025_opt.c:574 backend/kvs20xx_opt.c:219 #: backend/kvs40xx_opt.c:368 backend/matsushita.c:1127 #, no-c-format msgid "Sets the feeding mode" msgstr "Stelt de doorvoermodus in" #: backend/kvs1025_opt.c:584 #, no-c-format msgid "Enable/Disable long paper mode" msgstr "Groot formaat papier modus in/uit schakelen" #: backend/kvs1025_opt.c:593 #, no-c-format msgid "Enable/Disable length control mode" msgstr "Formaat gestuurde modus in/uit schakelen" #: backend/kvs1025_opt.c:601 backend/kvs20xx_opt.c:243 #: backend/kvs40xx_opt.c:417 #, no-c-format msgid "Sets the manual feed mode" msgstr "Stelt de handmatige doorvoermodus in" #: backend/kvs1025_opt.c:612 backend/kvs20xx_opt.c:255 #: backend/kvs40xx_opt.c:429 #, no-c-format msgid "Sets the manual feed timeout in seconds" msgstr "Stelt de handmatige doorvoer timeout in seconden in" #: backend/kvs1025_opt.c:625 backend/kvs20xx_opt.c:268 #: backend/kvs40xx_opt.c:442 #, no-c-format msgid "Enable/Disable double feed detection" msgstr "Dubbele doorvoer herkenning in/uit schakelen" #: backend/kvs1025_opt.c:631 backend/kvs20xx_opt.c:276 #: backend/kvs40xx_opt.c:497 #, no-c-format msgid "fit-to-page" msgstr "aangepast aan de pagina" #: backend/kvs1025_opt.c:632 backend/kvs20xx_opt.c:277 #: backend/kvs40xx_opt.c:498 #, no-c-format msgid "Fit to page" msgstr "Aangepast aan de pagina" #: backend/kvs1025_opt.c:634 backend/kvs20xx_opt.c:278 #: backend/kvs40xx_opt.c:499 #, no-c-format msgid "Scanner shrinks image to fit scanned page" msgstr "Scanner verkleint het beeld zodat deze op de gescande pagina past" #: backend/kvs1025_opt.c:661 backend/kvs20xx_opt.c:309 #: backend/kvs40xx_opt.c:533 #, no-c-format msgid "Set paper position : true for landscape, false for portrait" msgstr "Stelt de papier positie in: waar voor liggend, onwaar voor staand" #: backend/kvs1025_opt.c:735 backend/matsushita.c:1224 #, no-c-format msgid "Automatic threshold" msgstr "Automatische drempelwaarde" #: backend/kvs1025_opt.c:738 backend/matsushita.c:1227 #, no-c-format msgid "" "Automatically sets brightness, contrast, white level, gamma, noise " "reduction and image emphasis" msgstr "" "Stelt automatisch helderheid, contrast, witwaarde, gamma, " "ruisonderdrukking en beeldverbetering in" #: backend/kvs1025_opt.c:783 backend/kvs40xx_opt.c:764 #: backend/matsushita.c:1275 #, no-c-format msgid "Noise reduction" msgstr "Ruisonderdrukking" #: backend/kvs1025_opt.c:785 backend/kvs40xx_opt.c:765 #: backend/matsushita.c:1277 #, no-c-format msgid "Reduce the isolated dot noise" msgstr "Verminder de ruis van afzonderlijke punten" #: backend/kvs1025_opt.c:796 backend/kvs20xx_opt.c:412 #: backend/kvs40xx_opt.c:655 backend/matsushita.c:1288 #, no-c-format msgid "Image emphasis" msgstr "Beeldverbetering" #: backend/kvs1025_opt.c:797 backend/kvs20xx_opt.c:413 #: backend/kvs40xx_opt.c:656 backend/matsushita.c:1289 #, no-c-format msgid "Sets the image emphasis" msgstr "Stelt beeldverbetering in" #: backend/kvs1025_opt.c:808 backend/kvs1025_opt.c:809 #: backend/matsushita.c:1300 backend/matsushita.c:1301 #: backend/pixma_sane_options.c:112 #, no-c-format msgid "Gamma" msgstr "Gamma" #: backend/kvs1025_opt.c:818 backend/kvs20xx_opt.c:436 #: backend/kvs40xx_opt.c:681 #, no-c-format msgid "Lamp color" msgstr "Lamp kleur" #: backend/kvs1025_opt.c:819 backend/kvs20xx_opt.c:437 #: backend/kvs40xx_opt.c:682 #, no-c-format msgid "Sets the lamp color (color dropout)" msgstr "Schakelt de lamp kleur in (kleur uitval)" #: backend/kvs1025_opt.c:832 #, no-c-format msgid "Inverse image in B/W or halftone mode" msgstr "Geïnverteerd beeld in Z/W of halftoon modus" #: backend/kvs1025_opt.c:840 #, no-c-format msgid "Mirror image (left/right flip)" msgstr "Spiegel beeld (links/rechts verwisselen)" #: backend/kvs1025_opt.c:847 #, no-c-format msgid "jpeg compression" msgstr "jpeg compressie" #: backend/kvs1025_opt.c:850 #, no-c-format msgid "JPEG Image Compression with Q parameter, '0' - no compression" msgstr "JPEG beeld compressie met Q parameter, '0' - geen compressie" #: backend/kvs1025_opt.c:860 #, no-c-format msgid "Rotate image clockwise" msgstr "Roteer beeld met de klok mee" #: backend/kvs1025_opt.c:862 #, no-c-format msgid "Request driver to rotate pages by a fixed amount" msgstr "" "Vraag het stuurprogramma pagina's met een vaste hoeveelheid te roteren" #: backend/kvs1025_opt.c:874 #, no-c-format msgid "Request driver to rotate skewed pages digitally" msgstr "" "Vraag het stuurprogramma scheef getrokken pagina's digitaal te roteren" #: backend/kvs1025_opt.c:883 #, no-c-format msgid "Maximum diameter of lone dots to remove from scan" msgstr "" "Maximale omvang van verspreid liggende spikkels, die van het gescande " "beeld moeten worden verwijderd" #: backend/kvs1025_opt.c:902 #, no-c-format msgid "Software automatic cropping" msgstr "Softwarematig automatisch uitsnijden" #: backend/kvs1025_opt.c:904 #, no-c-format msgid "Request driver to remove border from pages digitally" msgstr "" "Vraag het stuurprogramma randen van pagina's digitaal te verwijderen " #: backend/kvs20xx_opt.c:233 backend/kvs40xx_opt.c:396 #, no-c-format msgid "" "Length Control Mode is a mode that the scanner reads up to the shorter " "length of actual paper or logical document length." msgstr "" "Formaat Controle Modus is een modus waarbij de scanner leest tot aan de " "kortste lengte van het gebruikte papier of de feitelijke lengte van het " "document." #: backend/kvs20xx_opt.c:424 backend/kvs20xx_opt.c:425 #: backend/kvs40xx_opt.c:668 backend/kvs40xx_opt.c:669 #: backend/microtek2.h:640 #, no-c-format msgid "Gamma correction" msgstr "Gammacorrectie" #: backend/kvs40xx_opt.c:117 #, no-c-format msgid "wait_doc_hopper_up" msgstr "wacht_doc_spring_op" #: backend/kvs40xx_opt.c:127 #, no-c-format msgid "A3" msgstr "A3" #: backend/kvs40xx_opt.c:132 #, no-c-format msgid "Double letter 11x17 in" msgstr "Dubbel briefpapier 11x17 inc." #: backend/kvs40xx_opt.c:133 #, no-c-format msgid "B4" msgstr "B4" #: backend/kvs40xx_opt.c:231 #, no-c-format msgid "High sensivity" msgstr "Hoge gevoeligheid" #: backend/kvs40xx_opt.c:232 #, no-c-format msgid "Low sensivity" msgstr "Lage gevoeligheid" #: backend/kvs40xx_opt.c:243 #, no-c-format msgid "err_diffusion" msgstr "err_verspreiding" #: backend/kvs40xx_opt.c:249 #, no-c-format msgid "No detection" msgstr "Geen herkenning" #: backend/kvs40xx_opt.c:250 #, no-c-format msgid "Normal mode" msgstr "Normale modus" #: backend/kvs40xx_opt.c:251 #, no-c-format msgid "Enhanced mode" msgstr "Verbetermodus" #: backend/kvs40xx_opt.c:405 #, no-c-format msgid "" "Long Paper Mode is a mode that the scanner reads the image after it " "divides long paper by the length which is set in Document Size option." msgstr "" "Groot Papier Modus is een modus waarin de scanner het beeld leest nadat " "hij het formaat van het papier heeft gedeeld door de lengte, die is " "ingesteld bij de optie Document Formaat" #: backend/kvs40xx_opt.c:449 #, no-c-format msgid "Double feed detector sensitivity" msgstr "Gevoeligheid van de dubbele doorvoer verklikker" #: backend/kvs40xx_opt.c:450 #, no-c-format msgid "Set the double feed detector sensitivity" msgstr "Stel de gevoeligheid van de dubbele doorvoer verklikker in" #: backend/kvs40xx_opt.c:461 backend/kvs40xx_opt.c:462 #, no-c-format msgid "Do not stop after double feed detection" msgstr "Stop niet na de dubbele doorvoer verklikker" #: backend/kvs40xx_opt.c:470 backend/kvs40xx_opt.c:471 #, no-c-format msgid "Ignore left double feed sensor" msgstr "Negeer linker dubbele doorvoor voeler" #: backend/kvs40xx_opt.c:479 backend/kvs40xx_opt.c:480 #, no-c-format msgid "Ignore center double feed sensor" msgstr "Negeer middelste dubbele doorvoer voeler" #: backend/kvs40xx_opt.c:488 backend/kvs40xx_opt.c:489 #, no-c-format msgid "Ignore right double feed sensor" msgstr "Negeer rechter dubbele doorvoer voeler" #: backend/kvs40xx_opt.c:642 #, no-c-format msgid "Automatic threshold mode" msgstr "Automatische drempelwaarde modus" #: backend/kvs40xx_opt.c:643 #, no-c-format msgid "Sets the automatic threshold mode" msgstr "Stelt de automatische drempelwaarde in" #: backend/kvs40xx_opt.c:694 #, no-c-format msgid "Inverse image in B/W mode" msgstr "Inverteer beeld in Z/W modus" #: backend/kvs40xx_opt.c:715 #, no-c-format msgid "JPEG compression" msgstr "JPEG compressie" #: backend/kvs40xx_opt.c:718 #, no-c-format msgid "JPEG compression (yours application must be able to uncompress)" msgstr "JPEG compressie (je programma moet in staat zijn te decomprimeren)" #: backend/kvs40xx_opt.c:737 backend/kvs40xx_opt.c:738 #, no-c-format msgid "Detect stapled document" msgstr "Herken aan elkaar geniet document" #: backend/kvs40xx_opt.c:776 #, no-c-format msgid "chroma of red" msgstr "kleurwaarde van rood" #: backend/kvs40xx_opt.c:777 #, no-c-format msgid "Set chroma of red" msgstr "Stel kleurwaarde van rood in" #: backend/kvs40xx_opt.c:787 #, no-c-format msgid "chroma of blue" msgstr "kleurwaarde van blauw" #: backend/kvs40xx_opt.c:788 #, no-c-format msgid "Set chroma of blue" msgstr "Stel kleurwaarde van blauw in" #: backend/kvs40xx_opt.c:798 backend/kvs40xx_opt.c:799 #, no-c-format msgid "Skew adjustment" msgstr "Scheefheid correctie" #: backend/kvs40xx_opt.c:808 #, no-c-format msgid "Stop scanner when a paper have been skewed" msgstr "Stop de scanner als het papier is scheefgetrokken" #: backend/kvs40xx_opt.c:809 #, no-c-format msgid "Scanner will be stop when a paper have been skewed" msgstr "De scanner wordt gestopt als het papier is scheefgetrokken" #: backend/kvs40xx_opt.c:816 #, no-c-format msgid "Crop actual image area" msgstr "Snij het effectieve beeldoppervlak uit" #: backend/kvs40xx_opt.c:817 #, no-c-format msgid "Scanner automatically detect image area and crop it" msgstr "" "De scanner herkent automatisch het beeldoppervlak en snijdt die uit" #: backend/kvs40xx_opt.c:827 #, no-c-format msgid "It is right and left reversing" msgstr "Het is rechts en links omkering" #: backend/kvs40xx_opt.c:834 backend/kvs40xx_opt.c:835 #, no-c-format msgid "Addition of space in top position" msgstr "Ruimte toevoegen aan de bovenzijde" #: backend/kvs40xx_opt.c:842 backend/kvs40xx_opt.c:843 #, no-c-format msgid "Addition of space in bottom position" msgstr "Ruimte toevoegen aan de onderzijde" #: backend/leo.c:110 #, no-c-format msgid "Diamond" msgstr "Ruitvormig" #: backend/leo.c:111 #, no-c-format msgid "8x8 Coarse Fatting" msgstr "8x8 Grof Aandikken" #: backend/leo.c:112 #, no-c-format msgid "8x8 Fine Fatting" msgstr "8x8 Fijn Aandikken" #: backend/leo.c:113 #, no-c-format msgid "8x8 Bayer" msgstr "8x8 Bayer" #: backend/leo.c:114 #, no-c-format msgid "8x8 Vertical Line" msgstr "8x8 Verticale Lijn" #: backend/lexmark.c:273 backend/umax_pp.c:715 #, no-c-format msgid "Gain" msgstr "Bereik" #: backend/lexmark.c:274 backend/umax_pp.c:716 #, no-c-format msgid "Color channels gain settings" msgstr "Bereikinstellingen van de kleurkanalen" #: backend/lexmark.c:283 backend/umax_pp.c:723 #, no-c-format msgid "Gray gain" msgstr "Grijsbereik" #: backend/lexmark.c:284 backend/umax_pp.c:724 #, no-c-format msgid "Sets gray channel gain" msgstr "Stelt het bereik in van het grijze kanaal" #: backend/lexmark.c:297 backend/plustek.c:1001 backend/umax_pp.c:735 #, no-c-format msgid "Red gain" msgstr "Roodbereik" #: backend/lexmark.c:298 backend/umax_pp.c:736 #, no-c-format msgid "Sets red channel gain" msgstr "Stelt het bereik in van het rode kanaal" #: backend/lexmark.c:311 backend/plustek.c:1017 backend/umax_pp.c:747 #, no-c-format msgid "Green gain" msgstr "Groenbereik" #: backend/lexmark.c:312 backend/umax_pp.c:748 #, no-c-format msgid "Sets green channel gain" msgstr "Stelt het bereik in van het groene kanaal" #: backend/lexmark.c:325 backend/plustek.c:1033 backend/umax_pp.c:759 #, no-c-format msgid "Blue gain" msgstr "Blauwbereik" #: backend/lexmark.c:326 backend/umax_pp.c:760 #, no-c-format msgid "Sets blue channel gain" msgstr "Stelt het bereik in van het blauwe kanaal" #: backend/matsushita.c:139 #, no-c-format msgid "Bayer Dither 16" msgstr "Bayer Dither 16" #: backend/matsushita.c:140 #, no-c-format msgid "Bayer Dither 64" msgstr "Bayer Dither 64" #: backend/matsushita.c:141 #, no-c-format msgid "Halftone Dot 32" msgstr "Halftoon punt 32" #: backend/matsushita.c:142 #, no-c-format msgid "Halftone Dot 64" msgstr "Halftoon punt 64" #: backend/matsushita.c:143 #, no-c-format msgid "Error Diffusion" msgstr "Foutenverspreiding" #: backend/matsushita.c:160 #, no-c-format msgid "Mode 1" msgstr "Mode 1" #: backend/matsushita.c:161 #, no-c-format msgid "Mode 2" msgstr "Mode 2" #: backend/matsushita.c:162 #, no-c-format msgid "Mode 3" msgstr "Mode 3" #: backend/matsushita.c:176 #, no-c-format msgid "From white stick" msgstr "Vanaf witte punt" #: backend/matsushita.c:212 #, no-c-format msgid "Smooth" msgstr "Gelijkmatig" #: backend/matsushita.c:214 backend/matsushita.c:229 #, no-c-format msgid "Low" msgstr "Laag" #: backend/matsushita.c:215 backend/matsushita.c:230 #: backend/matsushita.c:1296 #, no-c-format msgid "Medium" msgstr "Gemiddeld" #: backend/matsushita.c:216 backend/matsushita.c:231 #, no-c-format msgid "High" msgstr "Hoog" #: backend/matsushita.c:245 #, no-c-format msgid "CRT" msgstr "CRT" #: backend/matsushita.c:257 #, no-c-format msgid "One page" msgstr "Eén pagina" #: backend/matsushita.c:258 #, no-c-format msgid "All pages" msgstr "Alle pagina's" #: backend/matsushita.c:1034 backend/plustek.c:1333 #, no-c-format msgid "sheetfed scanner" msgstr "Doorvoerscanner" #: backend/matsushita.h:209 #, no-c-format msgid "Grayscale 4 bits" msgstr "4 bit grijstrap" #: backend/matsushita.h:210 #, no-c-format msgid "Grayscale 8 bits" msgstr "8 bit grijstrap" #: backend/microtek2.h:601 #, no-c-format msgid "Shadow, midtone, highlight, exposure time" msgstr "Schaduw, middentoon, lichteffecten, belichtingstijd" #: backend/microtek2.h:603 #, no-c-format msgid "Special options" msgstr "Extra opties" #: backend/microtek2.h:604 #, no-c-format msgid "Color balance" msgstr "Kleurbalans" #: backend/microtek2.h:607 #, no-c-format msgid "Disable backtracking" msgstr "Geen \"backtracking\"" #: backend/microtek2.h:608 #, no-c-format msgid "If checked the scanner does not perform backtracking" msgstr "Wanneer aangevinkt, voert de scanner geen \"backtracking\" uit" #: backend/microtek2.h:612 #, no-c-format msgid "Toggle lamp of flatbed" msgstr "Schakel lamp van de flatbed aan/uit" #: backend/microtek2.h:613 #, no-c-format msgid "Toggles the lamp of the flatbed" msgstr "Schakelt de lamp van de flatbedscanner aan/uit" #: backend/microtek2.h:616 #, no-c-format msgid "Calibration by backend" msgstr "Kalibratie door de \"backend\"" #: backend/microtek2.h:617 #, no-c-format msgid "" "If checked the color calibration before a scan is done by the backend" msgstr "" "Wanneer aangevinkt, wordt de kleur kalibratie voor een scan uitgevoerd " "door de \"backend\"" #: backend/microtek2.h:621 #, no-c-format msgid "Use the lightlid-35mm adapter" msgstr "Gebruik het \"lightlid-35mm\" hulpstuk" #: backend/microtek2.h:622 #, no-c-format msgid "This option turns off the lamp of the flatbed during a scan" msgstr "Deze optie schakelt de lamp van de flatbed uit tijdens het scannen" #: backend/microtek2.h:626 backend/snapscan-options.c:421 #, no-c-format msgid "Quality scan" msgstr "Hoge kwaliteit scan" #: backend/microtek2.h:627 backend/snapscan-options.c:422 #, no-c-format msgid "Highest quality but lower speed" msgstr "Hoogste kwaliteit, maar met een lagere snelheid" #: backend/microtek2.h:630 #, no-c-format msgid "Fast scan" msgstr "Hoge snelheid" #: backend/microtek2.h:631 #, no-c-format msgid "Highest speed but lower quality" msgstr "Hoogste snelheid, maar met een lagere kwaliteit" #: backend/microtek2.h:634 #, no-c-format msgid "Automatic adjustment of threshold" msgstr "Automatische aanpassing van de drempelwaarde" #: backend/microtek2.h:635 #, no-c-format msgid "" "If checked the backend automatically tries to determine an optimal value " "for the threshold." msgstr "" "Indien aangevinkt, probeert de \"backend\" een optimale waarde te " "bepalen voor de drempelwaarde." #: backend/microtek2.h:641 #, no-c-format msgid "Selects the gamma correction mode." msgstr "Kiest de gammacorrectiemodus" #: backend/microtek2.h:644 #, no-c-format msgid "Bind gamma" msgstr "Gecombineerde gamma" #: backend/microtek2.h:645 #, no-c-format msgid "Use same gamma values for all colour channels." msgstr "Gebruik dezelfde gammawaarden voor alle kleurkanalen." #: backend/microtek2.h:649 #, no-c-format msgid "Scalar gamma" msgstr "Gammagetalwaarde" #: backend/microtek2.h:650 #, no-c-format msgid "Selects a value for scalar gamma correction." msgstr "Kiest een getalwaarde voor de gammacorrectie" #: backend/microtek2.h:654 #, no-c-format msgid "Scalar gamma red" msgstr "Gammagetalwaarde voor rood" #: backend/microtek2.h:655 #, no-c-format msgid "Selects a value for scalar gamma correction (red channel)" msgstr "Kiest een getalswaarde voor gammacorrectie (rode kanaal)" #: backend/microtek2.h:659 #, no-c-format msgid "Scalar gamma green" msgstr "Gammagetalwaarde voor groen" #: backend/microtek2.h:660 #, no-c-format msgid "Selects a value for scalar gamma correction (green channel)" msgstr "Kiest een getalwaarde voor gammacorrectie (groene kanaal)" #: backend/microtek2.h:664 #, no-c-format msgid "Scalar gamma blue" msgstr "Gammagetalwaarde voor blauw" #: backend/microtek2.h:665 #, no-c-format msgid "Selects a value for scalar gamma correction (blue channel)" msgstr "Kiest een getalwaarde voor gammacorrectie (blauwe kanaal)" #: backend/microtek2.h:669 #, no-c-format msgid "Channel" msgstr "Kanaal" #: backend/microtek2.h:670 #, no-c-format msgid "" "Selects the colour band, \"Master\" means that all colours are affected." msgstr "" "Kiest de kleurengroep, \"Master\" betekent dat alle kleuren worden " "beïnvloed." #: backend/microtek2.h:674 #, no-c-format msgid "Midtone" msgstr "Middentoon" #: backend/microtek2.h:675 #, no-c-format msgid "Selects which radiance level should be considered \"50 % gray\"." msgstr "Kiest welke helderheidswaarde als 50% grijs moet worden beschouwd." #: backend/microtek2.h:679 #, no-c-format msgid "Midtone for red" msgstr "Middentoon voor rood" #: backend/microtek2.h:680 #, no-c-format msgid "Selects which radiance level should be considered \"50 % red\"." msgstr "Kiest welke helderheidswaarde als 50% rood moet worden beschouwd." #: backend/microtek2.h:684 #, no-c-format msgid "Midtone for green" msgstr "Middentoon voor groen" #: backend/microtek2.h:685 #, no-c-format msgid "Selects which radiance level should be considered \"50 % green\"." msgstr "Kiest welke helderheidswaarde als 50% groen moet worden beschouwd." #: backend/microtek2.h:689 #, no-c-format msgid "Midtone for blue" msgstr "Middentoon voor blauw" #: backend/microtek2.h:690 #, no-c-format msgid "Selects which radiance level should be considered \"50 % blue\"." msgstr "Kiest welke helderheidswaarde als 50% blauw moet worden beschouwd." #: backend/microtek2.h:694 #, no-c-format msgid "Red balance" msgstr "Roodbalans" #: backend/microtek2.h:695 #, no-c-format msgid "Balance factor for red. A value of 100% means no correction." msgstr "" "Kleurbalansfactor voor rood: Een waarde van 100% betekent geen " "kleurcorrectie." #: backend/microtek2.h:699 #, no-c-format msgid "Green balance" msgstr "Groenbalans" #: backend/microtek2.h:700 #, no-c-format msgid "Balance factor for green. A value of 100% means no correction." msgstr "" "Kleurbalansfactor voor groen: Een waarde van 100% betekent geen " "kleurcorrectie." #: backend/microtek2.h:704 #, no-c-format msgid "Blue balance" msgstr "Blauwbalans" #: backend/microtek2.h:705 #, no-c-format msgid "Balance factor for blue. A value of 100% means no correction." msgstr "" "Kleurbalansfactor voor blauw: Een waarde van 100% betekent geen " "kleurcorrectie." #: backend/microtek2.h:709 #, no-c-format msgid "Firmware balance" msgstr "Standaardkleurbalans" #: backend/microtek2.h:710 #, no-c-format msgid "Sets the color balance values to the firmware provided values." msgstr "" "Stelt de kleurbalanswaarden in op de waarden zoals opgegeven door de " "fabrikant." #: backend/mustek.c:149 #, no-c-format msgid "Slowest" msgstr "Langzaamste" #: backend/mustek.c:149 #, no-c-format msgid "Slower" msgstr "Langzamer" #: backend/mustek.c:150 #, no-c-format msgid "Faster" msgstr "Sneller" #: backend/mustek.c:150 #, no-c-format msgid "Fastest" msgstr "Snelste" #: backend/mustek.c:177 #, no-c-format msgid "8x8 coarse" msgstr "8x8 grof" #: backend/mustek.c:177 #, no-c-format msgid "8x8 normal" msgstr "8x8 normaal" #: backend/mustek.c:177 #, no-c-format msgid "8x8 fine" msgstr "8x8 fijn" #: backend/mustek.c:178 #, no-c-format msgid "8x8 very fine" msgstr "8x8 zeer fijn" #: backend/mustek.c:178 #, no-c-format msgid "6x6 normal" msgstr "6x6 normaal" #: backend/mustek.c:179 #, no-c-format msgid "5x5 coarse" msgstr "5x5 grof" #: backend/mustek.c:179 #, no-c-format msgid "5x5 fine" msgstr "5x5 fijn" #: backend/mustek.c:179 #, no-c-format msgid "4x4 coarse" msgstr "4x4 grof" #: backend/mustek.c:180 #, no-c-format msgid "4x4 normal" msgstr "4x4 normaal" #: backend/mustek.c:180 #, no-c-format msgid "4x4 fine" msgstr "4x4 fijn" #: backend/mustek.c:180 #, no-c-format msgid "3x3 normal" msgstr "3x3 normaal" #: backend/mustek.c:181 #, no-c-format msgid "2x2 normal" msgstr "2x2 normaal" #: backend/mustek.c:181 #, no-c-format msgid "8x8 custom" msgstr "8x8 door de gebruiker gedefinieerd" #: backend/mustek.c:182 #, no-c-format msgid "6x6 custom" msgstr "6x6 door de gebruiker gedefinieerd" #: backend/mustek.c:183 #, no-c-format msgid "5x5 custom" msgstr "5x5 door de gebruiker gedefinieerd" #: backend/mustek.c:183 #, no-c-format msgid "4x4 custom" msgstr "4x4 door de gebruiker gedefinieerd" #: backend/mustek.c:184 #, no-c-format msgid "3x3 custom" msgstr "3x3 door de gebruiker gedefinieerd" #: backend/mustek.c:185 #, no-c-format msgid "2x2 custom" msgstr "2x2 door de gebruiker gedefinieerd" #: backend/mustek.c:4235 #, no-c-format msgid "Fast gray mode" msgstr "Snelle grijsmodus" #: backend/mustek.c:4236 #, no-c-format msgid "Scan in fast gray mode (lower quality)." msgstr "Scan in snelle grijsmodus (lage beeldkwaliteit)." #: backend/mustek.c:4333 #, no-c-format msgid "" "Request that all previews are done in the fastest (low-quality) mode. " "This may be a non-color mode or a low resolution mode." msgstr "" "Vraag de snelste (lage kwaliteit) modus te gebruiken voor alle " "voorbeeldscans. Dit kan een niet-kleur of lage resolutie modus zijn." #: backend/mustek.c:4341 #, no-c-format msgid "Lamp off time (minutes)" msgstr "Lamp uit tijd (minuten)" #: backend/mustek.c:4342 #, no-c-format msgid "Set the time (in minutes) after which the lamp is shut off." msgstr "Stel de tijd (in minuten) in waarna de lamp wordt uitgeschakeld." #: backend/mustek.c:4353 #, no-c-format msgid "Turn lamp off" msgstr "Schakel de lamp uit" #: backend/mustek.c:4354 #, no-c-format msgid "Turns the lamp off immediately." msgstr "Schakelt de lamp direct uit" #: backend/mustek.c:4431 #, no-c-format msgid "Red brightness" msgstr "Helderheid van het rode kanaal" #: backend/mustek.c:4432 #, no-c-format msgid "Controls the brightness of the red channel of the acquired image." msgstr "Bepaalt de helderheid van het rode kanaal van het verkregen beeld." #: backend/mustek.c:4444 #, no-c-format msgid "Green brightness" msgstr "Helderheid van het groene kanaal" #: backend/mustek.c:4445 #, no-c-format msgid "Controls the brightness of the green channel of the acquired image." msgstr "" "Bepaalt de helderheid van het groene kanaal van het verkregen beeld." #: backend/mustek.c:4457 #, no-c-format msgid "Blue brightness" msgstr "Helderheid van het blauwe kanaal" #: backend/mustek.c:4458 #, no-c-format msgid "Controls the brightness of the blue channel of the acquired image." msgstr "" "Bepaalt de helderheid van het blauwe kanaal van het verkregen beeld." #: backend/mustek.c:4483 #, no-c-format msgid "Contrast red channel" msgstr "Contrast van het rode kanaal" #: backend/mustek.c:4484 #, no-c-format msgid "Controls the contrast of the red channel of the acquired image." msgstr "Bepaalt het contrast van het rode kanaal van het verkregen beeld." #: backend/mustek.c:4496 #, no-c-format msgid "Contrast green channel" msgstr "Contrast van het groene kanaal" #: backend/mustek.c:4497 #, no-c-format msgid "Controls the contrast of the green channel of the acquired image." msgstr "" "Bepaalt het contrast van het groene kanaal van het verkregen beeld." #: backend/mustek.c:4509 #, no-c-format msgid "Contrast blue channel" msgstr "Contrast van het blauwe kanaal" #: backend/mustek.c:4510 #, no-c-format msgid "Controls the contrast of the blue channel of the acquired image." msgstr "" "Bepaalt het contrast van het blauwe kanaal van het verkregen beeld." #: backend/mustek_usb2.c:105 #, no-c-format msgid "Color48" msgstr "Kleur48" #: backend/mustek_usb2.c:106 backend/mustek_usb2.c:114 #, no-c-format msgid "Color24" msgstr "Kleur24" #: backend/mustek_usb2.c:107 #, no-c-format msgid "Gray16" msgstr "Grijs16" #: backend/mustek_usb2.c:108 #, no-c-format msgid "Gray8" msgstr "Grijs8" #: backend/mustek_usb2.c:119 #, no-c-format msgid "Reflective" msgstr "Reflecterend" #: backend/mustek_usb2.c:120 #, no-c-format msgid "Positive" msgstr "Diapositief" #: backend/mustek_usb2.c:421 #, no-c-format msgid "" "Warm-up until the lamp's brightness is constant instead of insisting on " "40 seconds warm-up time." msgstr "" "Warm op totdat de helderheid van de lamp constant is in plaats van de " "'verplichte' 40 seconde opwarmtijd aan te houden." #: backend/pixma.c:378 #, no-c-format msgid "Negative color" msgstr "Kleurennegatief" #: backend/pixma.c:383 #, no-c-format msgid "Negative gray" msgstr "Grijsnegatief" #: backend/pixma.c:396 #, no-c-format msgid "48 bits color" msgstr "48 bits kleur" #: backend/pixma.c:401 #, no-c-format msgid "16 bits gray" msgstr "16 bits grijs" #: backend/pixma_sane_options.c:84 #, no-c-format msgid "" "Selects the scan source (such as a document-feeder). Set source before " "mode and resolution. Resets mode and resolution to auto values." msgstr "" "Kiest de scanbron (zoals b.v. documentendoorvoer). Stel de bron in voor " "de modus en resolutie. Zet modus en resolutie terug naar automatische " "waarden." #: backend/pixma_sane_options.c:98 #, no-c-format msgid "Button-controlled scan" msgstr "Knop-gestuurde scan" #: backend/pixma_sane_options.c:99 #, no-c-format msgid "" "When enabled, scan process will not start immediately. To proceed, press " "\"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To " "cancel, press \"GRAY\" button." msgstr "" "Wanneer ingeschakeld, zal het scanproces niet direct starten. Om door te " "gaan, druk op de \"SCAN\" knop (voor MP150) of \"COLOR\" knop (voor " "andere modellen). Om te annuleren, druk op de \"GRAY\" knop." #: backend/pixma_sane_options.c:232 #, no-c-format msgid "Update button state" msgstr "Werk de status van de knop bij" #: backend/pixma_sane_options.c:244 #, no-c-format msgid "Button 1" msgstr "Knop 1" #: backend/pixma_sane_options.c:258 #, no-c-format msgid "Button 2" msgstr "Knop 2" #: backend/pixma_sane_options.c:272 #, no-c-format msgid "Type of original to scan" msgstr "Soort te scannen origineel" #: backend/pixma_sane_options.c:286 #, no-c-format msgid "Target operation type" msgstr "Soort bewerking van het resultaat" #: backend/pixma_sane_options.c:348 #, no-c-format msgid "ADF Waiting Time" msgstr "ADF wachttijd" #: backend/pixma_sane_options.c:349 #, no-c-format msgid "" "When set, the scanner searches the waiting time in seconds for a new " "document inserted into the automatic document feeder." msgstr "" "Wanneer ingesteld, zoekt de scanner gedurende de wachttijd in seconden " "naar een nieuw document dat in de automatisch document doorvoer is " "gelegd." #: backend/plustek.c:235 backend/plustek_pp.c:204 backend/u12.c:156 #, no-c-format msgid "Transparency" msgstr "Transparantie" #: backend/plustek.c:913 #, no-c-format msgid "Device-Settings" msgstr "Apparaatinstellingen" #: backend/plustek.c:920 #, no-c-format msgid "Lampswitch" msgstr "Lampschakelaar" #: backend/plustek.c:921 #, no-c-format msgid "Manually switching the lamp(s)." msgstr "Schakel de lamp(en) handmatig aan/uit." #: backend/plustek.c:926 #, no-c-format msgid "Lamp off during dark calibration" msgstr "Lamp uit tijdens donker kalibreren" #: backend/plustek.c:927 #, no-c-format msgid "Always switches lamp off when doing dark calibration." msgstr "Schakel altijd de lamp uit tijdens donker kalibreren." #: backend/plustek.c:935 #, no-c-format msgid "Calibration data cache" msgstr "Kalibratie gegevenscache" #: backend/plustek.c:936 #, no-c-format msgid "Enables or disables calibration data cache." msgstr "Schakelt kalibratiecache in/uit" #: backend/plustek.c:942 #, no-c-format msgid "Performs calibration" msgstr "Voert kalibratie uit" #: backend/plustek.c:959 #, no-c-format msgid "Speedup sensor" msgstr "Snellere sensor beweging" #: backend/plustek.c:960 #, no-c-format msgid "Enables or disables speeding up sensor movement." msgstr "Schakelt snellere sensor beweging in/uit" #: backend/plustek.c:974 #, no-c-format msgid "Warmup-time" msgstr "Opwarmtijd" #: backend/plustek.c:975 #, no-c-format msgid "Warmup-time in seconds." msgstr "Opwarmtijd in seconden." #: backend/plustek.c:987 #, no-c-format msgid "Lampoff-time" msgstr "Lamp uit tijd" #: backend/plustek.c:988 #, no-c-format msgid "Lampoff-time in seconds." msgstr "Lamp uit tijd in seconden." #: backend/plustek.c:995 #, no-c-format msgid "Analog frontend" msgstr "Analoge \"frontend\"" #: backend/plustek.c:1002 #, no-c-format msgid "Red gain value of the AFE" msgstr "Roodbereik waarde van de AFE" #: backend/plustek.c:1009 backend/umax_pp.c:792 #, no-c-format msgid "Red offset" msgstr "Rood compensatie" #: backend/plustek.c:1010 #, no-c-format msgid "Red offset value of the AFE" msgstr "Rood compensatie van de AFE" #: backend/plustek.c:1018 #, no-c-format msgid "Green gain value of the AFE" msgstr "Groenbereik waarde van de AFE" #: backend/plustek.c:1026 #, no-c-format msgid "Green offset value of the AFE" msgstr "Groen compensatie van de AFE" #: backend/plustek.c:1034 #, no-c-format msgid "Blue gain value of the AFE" msgstr "Blauwbereik waarde van de AFE" #: backend/plustek.c:1042 #, no-c-format msgid "Blue offset value of the AFE" msgstr "Blauw compensatie van de AFE" #: backend/plustek.c:1049 #, no-c-format msgid "Red lamp off" msgstr "Rode lamp uit" #: backend/plustek.c:1050 #, no-c-format msgid "Defines red lamp off parameter" msgstr "Bepaalt de rode lamp uit parameter" #: backend/plustek.c:1057 #, no-c-format msgid "Green lamp off" msgstr "Groene lamp uit" #: backend/plustek.c:1058 #, no-c-format msgid "Defines green lamp off parameter" msgstr "Bepaalt de groene lamp uit parameter" #: backend/plustek.c:1065 #, no-c-format msgid "Blue lamp off" msgstr "Blauwe lamp uit" #: backend/plustek.c:1066 #, no-c-format msgid "Defines blue lamp off parameter" msgstr "Bepaalt de blauwe lamp uit parameter" #: backend/plustek.c:1096 #, no-c-format msgid "This option reflects the status of the scanner buttons." msgstr "Deze optie geeft de status weer van de scannerknoppen." #: backend/plustek_pp.c:197 #, no-c-format msgid "Color36" msgstr "Kleur36" #: backend/plustek_pp.c:211 #, no-c-format msgid "Dithermap 1" msgstr "Ditherpatroon 1" #: backend/plustek_pp.c:212 #, no-c-format msgid "Dithermap 2" msgstr "Ditherpatroon 2" #: backend/plustek_pp.c:213 #, no-c-format msgid "Randomize" msgstr "Toevalspatroon" #: backend/pnm.c:168 #, no-c-format msgid "Source Selection" msgstr "Keuze van de bron" #: backend/pnm.c:205 #, no-c-format msgid "Image Enhancement" msgstr "Beeldverbetering" #: backend/pnm.c:241 #, no-c-format msgid "Grayify" msgstr "Grijs maken" #: backend/pnm.c:242 #, no-c-format msgid "Load the image as grayscale." msgstr "Scan het beeld in grijstinten." #: backend/pnm.c:253 #, no-c-format msgid "Three-Pass Simulation" msgstr "Three-Pass Simulation" #: backend/pnm.c:255 #, no-c-format msgid "" "Simulate a three-pass scanner by returning 3 separate frames. For " "kicks, it returns green, then blue, then red." msgstr "" "Simuleer een Three-Pass Scanner door drie afzonderlijke afbeeldingen te " "retourneren. Bij voorkeur is de volgorde groen, dan blauw en tenslotte " "rood." #: backend/pnm.c:267 #, no-c-format msgid "Hand-Scanner Simulation" msgstr "Handscanner simulatie" #: backend/pnm.c:268 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners often do not know the image " "height a priori. Instead, they return a height of -1. Setting this " "option allows one to test whether a frontend can handle this correctly." msgstr "" "Simuleer een handscanner. Bij handscanners staat meestal de beeldhoogte " "van te voren niet vast. In plaats daarvan geven zij een hoogte van -1 " "terug. Met deze optie kan worden vastgesteld, of een \"frontend\" " "hiermee juist kan omgaan." #: backend/pnm.c:283 #, no-c-format msgid "" "Set default values for enhancement controls (brightness & contrast)." msgstr "" "Stel de kleurverbeteringsinstellingen (helderheid en contrast) in op " "standaardwaarden." #: backend/pnm.c:295 #, no-c-format msgid "Read only test-option" msgstr "Alleen-lezen testoptie" #: backend/pnm.c:296 #, no-c-format msgid "Let's see whether frontends can treat this right" msgstr "Eens kijken of \"frontends\" hiermee om kunnen gaan." #: backend/pnm.c:307 #, no-c-format msgid "Gamma Tables" msgstr "Gammatabellen" #: backend/pnm.c:379 #, no-c-format msgid "Status Code Simulation" msgstr "Statusbericht simulatie" #: backend/pnm.c:391 #, no-c-format msgid "Do not force status code" msgstr "Statusbericht niet opdringen" #: backend/pnm.c:392 #, no-c-format msgid "Do not force the backend to return a status code." msgstr "Dwing de \"backend\" niet een statusbericht terug te geven." #: backend/pnm.c:403 #, no-c-format msgid "Return SANE_STATUS_EOF" msgstr "Geef SANE_STATUS_EOF terug" #: backend/pnm.c:404 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_EOF after " "sane_read() has been called." msgstr "" "Dwing de \"backend\", na een aanroep van sane_read() het statusbericht " "SANE_STATUS_EOF terug te geven." #: backend/pnm.c:416 #, no-c-format msgid "Return SANE_STATUS_JAMMED" msgstr "Geef SANE_STATUS_JAMMED terug" #: backend/pnm.c:418 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_JAMMED after " "sane_read() has been called." msgstr "" "Dwing de \"backend\", na een aanroep van sane_read() het statusbericht " "SANE_STATUS_JAMMED terug te geven." #: backend/pnm.c:430 #, no-c-format msgid "Return SANE_STATUS_NO_DOCS" msgstr "Geef SANE_STATUS_NO_DOCS terug" #: backend/pnm.c:431 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_DOCS after " "sane_read() has been called." msgstr "" "Dwing de \"backend\", na een aanroep van sane_read() het statusbericht " "SANE_STATUS_NO_DOCS terug te geven." #: backend/pnm.c:443 #, no-c-format msgid "Return SANE_STATUS_COVER_OPEN" msgstr "Geef SANE_STATUS_COVER_OPEN terug" #: backend/pnm.c:444 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_COVER_OPEN after " "sane_read() has been called." msgstr "" "Dwing de \"backend\", na een aanroep van sane_read() het statusbericht " "SANE_STATUS_COVER_OPEN terug te geven." #: backend/pnm.c:456 #, no-c-format msgid "Return SANE_STATUS_IO_ERROR" msgstr "Geef SANE_STATUS_IO_ERROR terug" #: backend/pnm.c:457 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_IO_ERROR after " "sane_read() has been called." msgstr "" "Dwing de \"backend\", na een aanroep van sane_read() het statusbericht " "SANE_STATUS_IO_ERROR terug te geven." #: backend/pnm.c:469 #, no-c-format msgid "Return SANE_STATUS_NO_MEM" msgstr "Geef SANE_STATUS_NO_MEM terug" #: backend/pnm.c:471 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_NO_MEM after " "sane_read() has been called." msgstr "" "Dwing de \"backend\", na een aanroep van sane_read() het statusbericht " "SANE_STATUS_NO_MEM terug te geven." #: backend/pnm.c:483 #, no-c-format msgid "Return SANE_STATUS_ACCESS_DENIED" msgstr "Geef SANE_STATUS_ACCESS_DENIED terug" #: backend/pnm.c:484 #, no-c-format msgid "" "Force the backend to return the status code SANE_STATUS_ACCESS_DENIED " "after sane_read() has been called." msgstr "" "Dwing de \"backend\", na een aanroep van sane_read() het statusbericht " "SANE_STATUS_ACCESS_DENIED terug te geven." #: backend/rts8891.c:2809 #, no-c-format msgid "This option reflects the status of a scanner button." msgstr "Deze optie geeft de status weer van een scannerknop." #: backend/rts8891.c:2840 backend/umax.c:5795 backend/umax_pp.c:639 #, no-c-format msgid "Lamp on" msgstr "Lamp aan" #: backend/rts8891.c:2841 backend/umax.c:5796 #, no-c-format msgid "Turn on scanner lamp" msgstr "Schakel scannerlamp aan" #: backend/rts8891.c:2851 backend/umax1220u.c:248 backend/umax.c:5812 #, no-c-format msgid "Lamp off" msgstr "Lamp uit" #: backend/rts8891.c:2852 backend/umax1220u.c:249 backend/umax.c:5813 #, no-c-format msgid "Turn off scanner lamp" msgstr "Schakel de scannerlamp uit" #: backend/sm3840.c:760 #, no-c-format msgid "Lamp timeout" msgstr "Lamp timeout" #: backend/sm3840.c:762 #, no-c-format msgid "Minutes until lamp is turned off after scan" msgstr "Tijd (in minuten) totdat de lamp wordt uitgeschakeld na een scan" #: backend/sm3840.c:772 #, no-c-format msgid "Threshold value for lineart mode" msgstr "Drempelwaarde voor lijntekening modus" #: backend/snapscan-options.c:88 #, no-c-format msgid "Document Feeder" msgstr "Documentinvoer" #: backend/snapscan-options.c:92 #, no-c-format msgid "6x4 (inch)" msgstr "6x4 (inch)" #: backend/snapscan-options.c:93 #, no-c-format msgid "8x10 (inch)" msgstr "8x10 (inch)" #: backend/snapscan-options.c:94 #, no-c-format msgid "8.5x11 (inch)" msgstr "8.5x11 (inch)" #: backend/snapscan-options.c:97 #, no-c-format msgid "Halftoning Unsupported" msgstr "Halftoon niet ondersteund" #: backend/snapscan-options.c:98 #, no-c-format msgid "DispersedDot8x8" msgstr "DispersedDot8x8" #: backend/snapscan-options.c:99 #, no-c-format msgid "DispersedDot16x16" msgstr "DispersedDot16x16" #: backend/snapscan-options.c:103 #, no-c-format msgid "" "Number of scan lines to request in a SCSI read. Changing this parameter " "allows you to tune the speed at which data is read from the scanner " "during scans. If this is set too low, the scanner will have to stop " "periodically in the middle of a scan; if it's set too high, X-based " "frontends may stop responding to X events and your system could bog down." msgstr "" "Aantal scanlijnen dat bij een SCSI-leesopdracht wordt gevraagd. " "Verandering van deze parameter geeft je de mogelijkheid om de snelheid " "waarmee gegevens van de scanner wordt gelezen nauwkeurig af te stellen. " "Wanneer deze te laag is ingesteld moet de scanner tijdens het scannen " "regelmatig stoppen. Als deze te hoog is ingesteld bestaat de kans dat " "het scanprogramma niet meer reageert op invoer van de gebruiker en kan " "het gehele systeem onbruikbaar worden." #: backend/snapscan-options.c:111 #, no-c-format msgid "Frame number of media holder that should be scanned." msgstr "Het te scannen raamnummer van de filmhouder" #: backend/snapscan-options.c:114 #, no-c-format msgid "Use manual or automatic selection of focus point." msgstr "Gebruik handmatige of automatische keuze voor scherpstelpositie" #: backend/snapscan-options.c:117 #, no-c-format msgid "Focus point for scanning." msgstr "Scherpstelpositie voor het scannen" #: backend/snapscan-options.c:482 #, no-c-format msgid "Preview mode" msgstr "Voorbeeldmodus" #: backend/snapscan-options.c:484 #, no-c-format msgid "" "Select the mode for previews. Greyscale previews usually give the best " "combination of speed and detail." msgstr "" "Kies de scanmodus voor voorbeeldscans. Grijstrap voorbeeldscans geven " "meestal de beste combinatie van snelheid en detail." #: backend/snapscan-options.c:601 #, no-c-format msgid "Predefined settings" msgstr "Voorgedefinieerde instellingen" #: backend/snapscan-options.c:603 #, no-c-format msgid "" "Provides standard scanning areas for photographs, printed pages and the " "like." msgstr "Biedt standaard scanoppervlaktes voor foto's, afdrukken enzovoort." #: backend/snapscan-options.c:884 #, no-c-format msgid "Frame" msgstr "Scannerraam" #: backend/snapscan-options.c:885 #, no-c-format msgid "Frame to be scanned" msgstr "Het te scannen scannerraam" #: backend/snapscan-options.c:897 #, no-c-format msgid "Focus-mode" msgstr "Scherpstelmodus" #: backend/snapscan-options.c:898 #, no-c-format msgid "Auto or manual focus" msgstr "Automatische of handmatige scherpstelling" #: backend/snapscan-options.c:911 #, no-c-format msgid "Focus-point" msgstr "Scherpstelpositie" #: backend/snapscan-options.c:912 #, no-c-format msgid "Focus point" msgstr "Scherpstel positie" #: backend/snapscan-options.c:930 #, no-c-format msgid "Colour lines per read" msgstr "Kleurlijnen per leesopdracht" #: backend/snapscan-options.c:942 #, no-c-format msgid "Greyscale lines per read" msgstr "Grijstraplijnen per leesopdracht" #: backend/stv680.c:974 #, no-c-format msgid "webcam" msgstr "webcam" #: backend/stv680.h:115 #, no-c-format msgid "Color RAW" msgstr "Kleur RAW" #: backend/stv680.h:116 #, no-c-format msgid "Color RGB" msgstr "Kleur RGB" #: backend/stv680.h:117 #, no-c-format msgid "Color RGB TEXT" msgstr "Kleur RGB TEKST" #: backend/test.c:137 #, no-c-format msgid "Solid black" msgstr "Verzadigd zwart" #: backend/test.c:137 #, no-c-format msgid "Solid white" msgstr "Verzadigd wit" #: backend/test.c:138 #, no-c-format msgid "Color pattern" msgstr "Kleurpatroon" #: backend/test.c:138 #, no-c-format msgid "Grid" msgstr "Raster" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "First entry" msgstr "Eerste ingang" #: backend/test.c:163 backend/test.c:171 #, no-c-format msgid "Second entry" msgstr "Tweede ingang" #: backend/test.c:165 #, no-c-format msgid "" "This is the very long third entry. Maybe the frontend has an idea how to " "display it" msgstr "" "Dit is de erg lange derde ingang. Misschien weet de \"frontend\" hoe " "deze kan worden getoond" #: backend/test.c:348 #, no-c-format msgid "Hand-scanner simulation" msgstr "Handscanner-simulatie" #: backend/test.c:349 #, no-c-format msgid "" "Simulate a hand-scanner. Hand-scanners do not know the image height a " "priori. Instead, they return a height of -1. Setting this option " "allows one to test whether a frontend can handle this correctly. This " "option also enables a fixed width of 11 cm." msgstr "" "Simuleer een handscanner. Bij handscanners staat tenminste de " "beeldhoogte vooraf niet vast. In plaats daarvan geeft deze een hoogte " "van -1 terug. Met deze optie is te testen of de \"frontend\" daarmee " "juist kan omgaan. Deze optie stelt ook een vaste breedte van 11 cm in." #: backend/test.c:366 #, no-c-format msgid "Three-pass simulation" msgstr "Three-Pass simulatie" #: backend/test.c:367 #, no-c-format msgid "" "Simulate a three-pass scanner. In color mode, three frames are " "transmitted." msgstr "" "Simuleer een Three-Pass-Scanner. In kleurmodus worden drie afbeeldingen " "overgedragen." #: backend/test.c:382 #, no-c-format msgid "Set the order of frames" msgstr "Bepaal de volgorde van de afbeeldingen" #: backend/test.c:383 #, no-c-format msgid "Set the order of frames in three-pass color mode." msgstr "Bepaal de volgorde van de afbeeldingen in Three-Pass kleurenmodus." #: backend/test.c:416 #, no-c-format msgid "" "If Automatic Document Feeder is selected, the feeder will be 'empty' " "after 10 scans." msgstr "" "Als de automatische documentinvoer is gekozen, zal de invoerna 10 scans " "'leeg' zijn." #: backend/test.c:431 #, no-c-format msgid "Special Options" msgstr "Extra opties" #: backend/test.c:444 #, no-c-format msgid "Select the test picture" msgstr "Kies het testbeeld" #: backend/test.c:446 #, no-c-format msgid "" "Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns depending on the mode.\n" "Grid: draws a black/white grid with a width and height of 10 mm per " "square." msgstr "" "Kies het soort testbeeld. Beschikbare opties:\n" "Egaal zwart: maakt het gehele beeld zwart.\n" "Egaal wit: maakt het gehele beeld wit.\n" "Kleurpatroon: tekent verschillende kleurtestpatronen, afhankelijk van de " "modus.\n" "Raster: tekent een zwart/wit raster ter grootte van 10 mm²." #: backend/test.c:467 #, no-c-format msgid "Invert endianness" msgstr "Inverteer \"endianness\"" #: backend/test.c:468 #, no-c-format msgid "" "Exchange upper and lower byte of image data in 16 bit modes. This option " "can be used to test the 16 bit modes of frontends, e.g. if the frontend " "uses the correct endianness." msgstr "" "Verwissel de hoge en lage byte van de beeldgegevens in 16-bit-modus. " "Deze optie kan worden gebruikt om de 16-bit-modus van \"frontends\" te " "testen, bijvoorbeeld of de \"frontend\" de juiste \"endianness\" " "gebruikt." #: backend/test.c:484 #, no-c-format msgid "Read limit" msgstr "Leesbegrenzing" #: backend/test.c:485 #, no-c-format msgid "Limit the amount of data transferred with each call to sane_read()." msgstr "" "Begrens de hoeveelheid gegevens die bij elke aanroep van sane_read() " "wordt overgedragen." #: backend/test.c:498 #, no-c-format msgid "Size of read-limit" msgstr "Grootte van de leesbegrenzing" #: backend/test.c:499 #, no-c-format msgid "" "The (maximum) amount of data transferred with each call to sane_read()." msgstr "" "De (maximale) hoeveelheid gegevens die bij elke aanroep van sane_read() " "wordt overgedragen." #: backend/test.c:514 #, no-c-format msgid "Read delay" msgstr "Leesvertraging" #: backend/test.c:515 #, no-c-format msgid "Delay the transfer of data to the pipe." msgstr "Vertraag de gegevensoverdracht door de databus." #: backend/test.c:527 #, no-c-format msgid "Duration of read-delay" msgstr "Duur van de leesvertraging" #: backend/test.c:528 #, no-c-format msgid "" "How long to wait after transferring each buffer of data through the pipe." msgstr "" "Hoe lang wordt gewacht nadat de gegevensverzameling door de databus is " "overgebracht." #: backend/test.c:543 #, no-c-format msgid "Return-value of sane_read" msgstr "Resultaat van sane_read" #: backend/test.c:545 #, no-c-format msgid "" "Select the return-value of sane_read(). \"Default\" is the normal " "handling for scanning. All other status codes are for testing how the " "frontend handles them." msgstr "" "Kies het resultaat van sane_read(). \"Default\" is de normale instelling " "voor het scannen. Alle andere resultaten zijn bedoeld om vast te stellen " "hoe \"frontends\" hiermee omgaan." #: backend/test.c:562 #, no-c-format msgid "Loss of pixels per line" msgstr "Verlies van pixels per lijn" #: backend/test.c:564 #, no-c-format msgid "The number of pixels that are wasted at the end of each line." msgstr "Het aantal pixels dat aan het einde van elke lijn verloren gaat." #: backend/test.c:577 #, no-c-format msgid "Fuzzy parameters" msgstr "Onduidelijke parameters" #: backend/test.c:578 #, no-c-format msgid "" "Return fuzzy lines and bytes per line when sane_parameters() is called " "before sane_start()." msgstr "" "Geef onduidelijke lijnen en bytes per lijn terug als sane_parameters() " "voor sane_start() wordt aangeroepen." #: backend/test.c:591 #, no-c-format msgid "Use non-blocking IO" msgstr "Gebruik niet-blokkerende IO" #: backend/test.c:592 #, no-c-format msgid "Use non-blocking IO for sane_read() if supported by the frontend." msgstr "" "Gebruik niet-blokkerende IO voor sane_read() als de \"frontend\" dat " "ondersteunt." #: backend/test.c:605 #, no-c-format msgid "Offer select file descriptor" msgstr "Biedt \"kies-bestandsbeschrijving\" aan" #: backend/test.c:606 #, no-c-format msgid "" "Offer a select filedescriptor for detecting if sane_read() will return " "data." msgstr "" "Biedt een \"kies-bestandsbeschrijving\" aan, om te kunnen achterhalen of " "sane_read() gegevens zal teruggeven." #: backend/test.c:619 #, no-c-format msgid "Enable test options" msgstr "Testopties inschakelen" #: backend/test.c:620 #, no-c-format msgid "" "Enable various test options. This is for testing the ability of " "frontends to view and modify all the different SANE option types." msgstr "" "Schakel diverse testopties in. Met deze optie kan worden getest in " "hoeverre \"frontends\" de verschillende SANE-optietypes laten zien en " "kunnen veranderen." #: backend/test.c:634 #, no-c-format msgid "Print options" msgstr "Druk opties af" #: backend/test.c:635 #, no-c-format msgid "Print a list of all options." msgstr "Druk een lijst met alle opties af." #: backend/test.c:712 #, no-c-format msgid "Bool test options" msgstr "Bool-testopties" #: backend/test.c:725 #, no-c-format msgid "(1/6) Bool soft select soft detect" msgstr "(1/6) Bool \"soft select\" \"soft detect\"" #: backend/test.c:727 #, no-c-format msgid "" "(1/6) Bool test option that has soft select and soft detect (and " "advanced) capabilities. That's just a normal bool option." msgstr "" "(1/6) Dit is een bool-testoptie, met \"soft select\" en \"soft detect" "\" (en \"advanced\") mogelijkheden. Dit is slechts een normale bool-" "optie." #: backend/test.c:743 #, no-c-format msgid "(2/6) Bool hard select soft detect" msgstr "(2/6) Bool \"hard select\" \"soft detect\"" #: backend/test.c:745 #, no-c-format msgid "" "(2/6) Bool test option that has hard select and soft detect (and " "advanced) capabilities. That means the option can't be set by the " "frontend but by the user (e.g. by pressing a button at the device)." msgstr "" "(2/6) Dit is een bool-testoptie, met \"hard select\" en \"soft detect" "\" (en \"advanced\") mogelijkheden. Dit betekent dat de \"frontend\" de " "optie niet kan instellen, maar de gebruiker dat moet doen (b.v. door op " "een knop van het apparaat te drukken)." #: backend/test.c:762 #, no-c-format msgid "(3/6) Bool hard select" msgstr "(3/6) Bool \"hard select\"" #: backend/test.c:763 #, no-c-format msgid "" "(3/6) Bool test option that has hard select (and advanced) capabilities. " "That means the option can't be set by the frontend but by the user (e.g. " "by pressing a button at the device) and can't be read by the frontend." msgstr "" "(3/6) Dit is een bool-testoptie, met \"hard select\" (en \"advanced\") " "mogelijkheden. Dit betekent dat de \"frontend\" de optie niet kan " "instellen maar de gebruiker dat moet doen (b.v. door een knop van het " "apparaat in te drukken). Bovendien kan de \"frontend\" de instelling " "niet lezen." #: backend/test.c:781 #, no-c-format msgid "(4/6) Bool soft detect" msgstr "(4/6) Bool \"soft detect\"" #: backend/test.c:782 #, no-c-format msgid "" "(4/6) Bool test option that has soft detect (and advanced) capabilities. " "That means the option is read-only." msgstr "" "(4/6) Dit is een bool-testoptie, met \"soft detect\" (en \"advanced\") " "mogelijkheden. Dit betekent dat het een alleen-lezen optie is." #: backend/test.c:798 #, no-c-format msgid "(5/6) Bool soft select soft detect emulated" msgstr "(5/6) Bool \"soft select\" \"soft detect\" geemuleerd" #: backend/test.c:799 #, no-c-format msgid "" "(5/6) Bool test option that has soft select, soft detect, and emulated " "(and advanced) capabilities." msgstr "" "(5/6) Dit is een bool-testoptie, met \"soft select\", \"soft detect\", " "en \"emulated\" (en \"advanced\") mogelijkheden." #: backend/test.c:815 #, no-c-format msgid "(6/6) Bool soft select soft detect auto" msgstr "(6/6) Bool \"soft select\" \"soft detect\" auto" #: backend/test.c:816 #, no-c-format msgid "" "(6/6) Bool test option that has soft select, soft detect, and automatic " "(and advanced) capabilities. This option can be automatically set by the " "backend." msgstr "" "(6/6) Dit is een bool-testoptie, met \"soft select\", \"soft detect\", " "en \"automatic\" (en \"advanced\") mogelijkheden. Deze optie kan de " "backend automatisch instellen." #: backend/test.c:833 #, no-c-format msgid "Int test options" msgstr "Int-testopties" #: backend/test.c:846 #, no-c-format msgid "(1/6) Int" msgstr "(1/6) Int" #: backend/test.c:847 #, no-c-format msgid "(1/6) Int test option with no unit and no constraint set." msgstr "(1/6) Int-testoptie zonder eenheid en beperkingen." #: backend/test.c:862 #, no-c-format msgid "(2/6) Int constraint range" msgstr "(2/6) Int bereikbeperking" #: backend/test.c:863 #, no-c-format msgid "" "(2/6) Int test option with unit pixel and constraint range set. Minimum " "is 4, maximum 192, and quant is 2." msgstr "" "(2/6) Int-testoptie met de eenheid \"Pixel\" en een beperkt bereik. Het " "minimum is 4, het maximum 192, en de stapgrootte is 2." #: backend/test.c:879 #, no-c-format msgid "(3/6) Int constraint word list" msgstr "(3/6) Int beperkte woordenlijst" #: backend/test.c:880 #, no-c-format msgid "(3/6) Int test option with unit bits and constraint word list set." msgstr "" "(3/6) Int-testoptie met de eenheid \"bits\" en een woordenlijst-" "beperking." #: backend/test.c:895 #, no-c-format msgid "(4/6) Int array" msgstr "(4/6) Int rij" #: backend/test.c:896 #, no-c-format msgid "" "(4/6) Int test option with unit mm and using an array without " "constraints." msgstr "" "(4/6) Int-testoptie met de eenheid \"mm\" en een rij zonder beperkingen." #: backend/test.c:911 #, no-c-format msgid "(5/6) Int array constraint range" msgstr "(5/6) Int rij bereikbeperking" #: backend/test.c:912 #, no-c-format msgid "" "(5/6) Int test option with unit dpi and using an array with a range " "constraint. Minimum is 4, maximum 192, and quant is 2." msgstr "" "(5/6) Int-testoptie met de eenheid \"dpi\" en een rij met een " "bereikbeperking. Het minimum is 4, het maximum 192, en de stapgrootte is " "2." #: backend/test.c:929 #, no-c-format msgid "(6/6) Int array constraint word list" msgstr "(6/6) Int rij beperkte woordenlijst" #: backend/test.c:930 #, no-c-format msgid "" "(6/6) Int test option with unit percent and using an array with a word " "list constraint." msgstr "" "(6/6) Int-testoptie met de eenheid \"procent\" en een rij met een " "woordenlijstbeperking." #: backend/test.c:946 #, no-c-format msgid "Fixed test options" msgstr "Vaste testopties" #: backend/test.c:959 #, no-c-format msgid "(1/3) Fixed" msgstr "(1/3) Vast" #: backend/test.c:960 #, no-c-format msgid "(1/3) Fixed test option with no unit and no constraint set." msgstr "(1/3) Vaste testoptie zonder eenheid en zonder beperking." #: backend/test.c:975 #, no-c-format msgid "(2/3) Fixed constraint range" msgstr "(2/3) Vaste bereikbeperking" #: backend/test.c:976 #, no-c-format msgid "" "(2/3) Fixed test option with unit microsecond and constraint range set. " "Minimum is -42.17, maximum 32767.9999, and quant is 2.0." msgstr "" "(2/3) Vaste testoptie met de eenheid \"microseconde\" en een beperkt " "bereik. Het minimum is -42.17, het maximum 32767.9999 en de stapgrootte " "is 2.0." #: backend/test.c:992 #, no-c-format msgid "(3/3) Fixed constraint word list" msgstr "(3/3) Vaste beperkte woordenlijst" #: backend/test.c:993 #, no-c-format msgid "(3/3) Fixed test option with no unit and constraint word list set." msgstr "" "(3/3) Vaste-testoptie zonder eenheid en met een beperkte woordenlijst." #: backend/test.c:1008 #, no-c-format msgid "String test options" msgstr "String-testopties" #: backend/test.c:1021 #, no-c-format msgid "(1/3) String" msgstr "(1/3) String" #: backend/test.c:1022 #, no-c-format msgid "(1/3) String test option without constraint." msgstr "(1/3) String-testoptie zonder beperkingen." #: backend/test.c:1039 #, no-c-format msgid "(2/3) String constraint string list" msgstr "(2/3) String beperkte \"string list\"" #: backend/test.c:1040 #, no-c-format msgid "(2/3) String test option with string list constraint." msgstr "(2/3) String-testoptie met een beperkte \"string list\"." #: backend/test.c:1059 #, no-c-format msgid "(3/3) String constraint long string list" msgstr "(3/3) String beperkte lange \"string list\"" #: backend/test.c:1060 #, no-c-format msgid "" "(3/3) String test option with string list constraint. Contains some more " "entries..." msgstr "" "(3/3) String-testoptie met een beperkte \"string list\". Bevat enkele " "andere ingangen..." #: backend/test.c:1080 #, no-c-format msgid "Button test options" msgstr "Knoppen testoptie" #: backend/test.c:1093 #, no-c-format msgid "(1/1) Button" msgstr "(1/1) Knop" #: backend/test.c:1094 #, no-c-format msgid "(1/1) Button test option. Prints some text..." msgstr "(1/1) Knoppen-testoptie. Levert enige tekst op..." #: backend/u12.c:149 #, no-c-format msgid "Color 36" msgstr "Kleur 36" #: backend/umax.c:235 #, no-c-format msgid "Use Image Composition" msgstr "Gebruik beeldcompositie" #: backend/umax.c:236 #, no-c-format msgid "Bi-level black and white (lineart mode)" msgstr "2-niveau zwart/wit (lijntekening modus)" #: backend/umax.c:237 #, no-c-format msgid "Dithered/halftone black & white (halftone mode)" msgstr "Halftoon zwart/wit (halftoon modus)" #: backend/umax.c:238 #, no-c-format msgid "Multi-level black & white (grayscale mode)" msgstr "Multi-niveau zwart/wit (grijstrap modus)" #: backend/umax.c:239 #, no-c-format msgid "Multi-level RGB color (one pass color)" msgstr "Multi-niveau RGB kleur (één-doorgang-kleur)" #: backend/umax.c:240 #, no-c-format msgid "Ignore calibration" msgstr "Negeer kalibratie" #: backend/umax.c:5733 #, no-c-format msgid "Disable pre focus" msgstr "Voorfocusering uitschakelen" #: backend/umax.c:5734 #, no-c-format msgid "Do not calibrate focus" msgstr "Focusering niet kalibreren" #: backend/umax.c:5745 #, no-c-format msgid "Manual pre focus" msgstr "Handmatige voorfocusering" #: backend/umax.c:5757 #, no-c-format msgid "Fix focus position" msgstr "Zet focuspositie vast" #: backend/umax.c:5769 #, no-c-format msgid "Lens calibration in doc position" msgstr "Kalibratie van de lens op het document" #: backend/umax.c:5770 #, no-c-format msgid "Calibrate lens focus in document position" msgstr "Kalibreer focus van de lens op het document" #: backend/umax.c:5781 #, no-c-format msgid "Holder focus position 0mm" msgstr "Houder focus positie 0mm" #: backend/umax.c:5782 #, no-c-format msgid "Use 0mm holder focus position instead of 0.6mm" msgstr "Gebruik 0mm houder focus positie in plaats van 0.6mm" #: backend/umax.c:5885 #, no-c-format msgid "Calibration mode" msgstr "Kalibreermodus" #: backend/umax.c:5886 #, no-c-format msgid "Define calibration mode" msgstr "Bepaal kalibreermodus" #: backend/umax_pp.c:640 #, no-c-format msgid "Sets lamp on/off" msgstr "Schakelt de lamp aan/uit" #: backend/umax_pp.c:649 #, no-c-format msgid "UTA on" msgstr "UTA aan" #: backend/umax_pp.c:650 #, no-c-format msgid "Sets UTA on/off" msgstr "Schakelt UTA aan/uit" #: backend/umax_pp.c:771 #, no-c-format msgid "Offset" msgstr "Compensatie" #: backend/umax_pp.c:773 #, no-c-format msgid "Color channels offset settings" msgstr "Compensatieinstellingen van de kleurkanalen" #: backend/umax_pp.c:780 #, no-c-format msgid "Gray offset" msgstr "Grijscompensatie" #: backend/umax_pp.c:781 #, no-c-format msgid "Sets gray channel offset" msgstr "Stelt de compensatie in van het grijze kanaal" #: backend/umax_pp.c:793 #, no-c-format msgid "Sets red channel offset" msgstr "Stelt de compensatie in van het rode kanaal" #: backend/umax_pp.c:805 #, no-c-format msgid "Sets green channel offset" msgstr "Stelt de compensatie in van het groene kanaal" #: backend/umax_pp.c:817 #, no-c-format msgid "Sets blue channel offset" msgstr "Stelt de compensatie in van het blauwe kanaal" #, fuzzy #~ msgid "IPC mode" #~ msgstr "Voorbeeldmodus" #~ msgid "problem not analyzed (unknown SCSI class)" #~ msgstr "probleem niet geanalyseerd (onbekende SCSI klasse)" #~ msgid "Grayscale" #~ msgstr "Grijstrap" #~ msgid "Binary" #~ msgstr "Binair (zwart/wit)" #~ msgid "Display a shortened resolution list" #~ msgstr "Toon een verkorte lijst met oplossende vermogens" #~ msgid "Black & White" #~ msgstr "Zwart/wit" sane-backends-1.0.27/po/Makefile.in.in0000664000175000017500000003744212775312262014333 00000000000000# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public # License but which still want to provide support for the GNU gettext # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. # # Origin: gettext-0.18 GETTEXT_MACRO_VERSION = 0.18 PACKAGE = @PACKAGE@ VERSION = @VERSION@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ localedir = @localedir@ gettextsrcdir = $(datadir)/gettext/po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ # We use $(mkdir_p). # In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as # "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, # @install_sh@ does not start with $(SHELL), so we add it. # In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined # either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake # versions, $(mkinstalldirs) and $(install_sh) are unused. mkinstalldirs = $(SHELL) @install_sh@ -d install_sh = $(SHELL) @install_sh@ MKDIR_P = @MKDIR_P@ mkdir_p = @mkdir_p@ GMSGFMT_ = @GMSGFMT@ GMSGFMT_no = @GMSGFMT@ GMSGFMT_yes = @GMSGFMT_015@ GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) MSGFMT_ = @MSGFMT@ MSGFMT_no = @MSGFMT@ MSGFMT_yes = @MSGFMT_015@ MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) XGETTEXT_ = @XGETTEXT@ XGETTEXT_no = @XGETTEXT@ XGETTEXT_yes = @XGETTEXT_015@ XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) MSGMERGE = msgmerge MSGMERGE_UPDATE = @MSGMERGE@ --update MSGINIT = msginit MSGCONV = msgconv MSGFILTER = msgfilter POFILES = @POFILES@ GMOFILES = @GMOFILES@ UPDATEPOFILES = @UPDATEPOFILES@ DUMMYPOFILES = @DUMMYPOFILES@ DISTFILES.common = Makefile.in.in remove-potcdate.sin \ $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ $(POFILES) $(GMOFILES) \ $(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) POTFILES = \ CATALOGS = @CATALOGS@ # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: .SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update .po.mo: @echo "$(MSGFMT) -c -o $@ $<"; \ $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ .po.gmo: @lang=`echo $* | sed -e 's,.*/,,'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo .sin.sed: sed -e '/^#/d' $< > t-$@ mv t-$@ $@ all: check-macro-version all-@USE_NLS@ all-yes: stamp-po all-no: # Ensure that the gettext macros and this Makefile.in.in are in sync. check-macro-version: @test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ exit 1; \ } # $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no # internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because # we don't want to bother translators with empty POT files). We assume that # LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. # In this case, stamp-po is a nop (i.e. a phony target). # stamp-po is a timestamp denoting the last time at which the CATALOGS have # been loosely updated. Its purpose is that when a developer or translator # checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, # "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent # invocations of "make" will do nothing. This timestamp would not be necessary # if updating the $(CATALOGS) would always touch them; however, the rule for # $(POFILES) has been designed to not touch files that don't need to be # changed. stamp-po: $(srcdir)/$(DOMAIN).pot test ! -f $(srcdir)/$(DOMAIN).pot || \ test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @test ! -f $(srcdir)/$(DOMAIN).pot || { \ echo "touch stamp-po" && \ echo timestamp > stamp-poT && \ mv stamp-poT stamp-po; \ } # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. # This target rebuilds $(DOMAIN).pot; it is an expensive operation. # Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed if LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null | grep -v 'libtool:' >/dev/null; then \ package_gnu='GNU '; \ else \ package_gnu=''; \ fi; \ if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ else \ msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ fi; \ case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ --msgid-bugs-address="$$msgid_bugs_address" \ ;; \ *) \ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ --package-name="$${package_gnu}@PACKAGE@" \ --package-version='@VERSION@' \ --msgid-bugs-address="$$msgid_bugs_address" \ ;; \ esac test ! -f $(DOMAIN).po || { \ if test -f $(srcdir)/$(DOMAIN).pot; then \ sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ else \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ else \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ } # This rule has no dependencies: we don't need to update $(DOMAIN).pot at # every "make" invocation, only create it when it is missing. # Only "make $(DOMAIN).pot-update" or "make dist" will force an update. $(srcdir)/$(DOMAIN).pot: $(MAKE) $(DOMAIN).pot-update # This target rebuilds a PO file if $(DOMAIN).pot has changed. # Note that a PO file is not touched if it doesn't need to be changed. $(POFILES): $(srcdir)/$(DOMAIN).pot @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ if test -f "$(srcdir)/$${lang}.po"; then \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) \ && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ *) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ esac; \ }; \ else \ $(MAKE) $${lang}.po-create; \ fi install: install-exec install-data install-exec: install-data: install-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ for file in $(DISTFILES.common) Makevars.template; do \ $(INSTALL_DATA) $(srcdir)/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ for file in Makevars; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi install-data-no: all install-data-yes: all @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $(DESTDIR)$$dir; \ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ fi; \ done; \ done install-strip: install installdirs: installdirs-exec installdirs-data installdirs-exec: installdirs-data: installdirs-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi installdirs-data-no: installdirs-data-yes: @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $(DESTDIR)$$dir; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ fi; \ done; \ done # Define this as empty until I found a useful application. installcheck: uninstall: uninstall-exec uninstall-data uninstall-exec: uninstall-data: uninstall-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ for file in $(DISTFILES.common) Makevars.template; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi uninstall-data-no: uninstall-data-yes: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ done; \ done check: all info dvi ps pdf html tags TAGS ctags CTAGS ID: mostlyclean: rm -f remove-potcdate.sed rm -f stamp-poT rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po rm -fr *.o clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES *.mo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f stamp-po $(GMOFILES) distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(MAKE) update-po @$(MAKE) dist2 # This is a separate target because 'update-po' must be executed before. dist2: stamp-po $(DISTFILES) dists="$(DISTFILES)"; \ if test "$(PACKAGE)" = "gettext-tools"; then \ dists="$$dists Makevars.template"; \ fi; \ if test -f $(srcdir)/$(DOMAIN).pot; then \ dists="$$dists $(DOMAIN).pot stamp-po"; \ fi; \ if test -f $(srcdir)/ChangeLog; then \ dists="$$dists ChangeLog"; \ fi; \ for i in 0 1 2 3 4 5 6 7 8 9; do \ if test -f $(srcdir)/ChangeLog.$$i; then \ dists="$$dists ChangeLog.$$i"; \ fi; \ done; \ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ for file in $$dists; do \ if test -f $$file; then \ cp -p $$file $(distdir) || exit 1; \ else \ cp -p $(srcdir)/$$file $(distdir) || exit 1; \ fi; \ done update-po: Makefile $(MAKE) $(DOMAIN).pot-update test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for creating PO files. .nop.po-create: @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ exit 1 # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ *) \ $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ esac; \ }; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: Makefile $(GMOFILES) @: # Recreate Makefile by invoking config.status. Explicitly invoke the shell, # because execution permission bits may not work on the current file system. # Use @SHELL@, which is the shell determined by autoconf for the use by its # scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ cd $(top_builddir) \ && @SHELL@ ./config.status $(subdir)/$@.in po-directories force: # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/po/cs.gmo0000664000175000017500000015442013110600537012753 00000000000000Þ•NŒü$H1 I1-V1 „1;1 Ì1,Ù1"2z)2 ¤29®2è2€3#†35ª3"à3Æ4Ê4jå4 P5Bq5(´5SÝ516ØH6!7B@7ƒ7lš78J8+b8cŽ8 ò8z9'Ž9™¶9$P:Wu: Í: Ø: ã: î: ù: ;; ; #; .;9; B; M; X; c; q; };‡;š;«; ½; È;Ó; Ü; ç;õ; ø; <!<3<!S< u<–< ¶<×<sà< T= ^=j=|=”=§=¸= Ð=!ñ=>3>8>G> ^> i>s>!>¯>Ä>Ø>_é>=I?>‡?<Æ?@@ @@'-@U@^@v@ ˆ@ “@ @©@ ®@»@ Ë@Õ@ ä@ð@A%A7A%FA lA wA„A˜A›A ŸA¬A¿AÛAøAB %B/BAB)\B%†B ¬B¸BÏBàBèBïB&CÄ)CîCôC D D D%D 4DBD_D~DD ­D»DÃDËDÓDéDòDEE4EHE]E6pE.§EBÖECFA]F,ŸF@ÌFA G?OG(G¸G¿GÑGÙGâG)úG"$H$GH*lH#—H(»H!äHI#$IHIIeI,¯I'ÜI0JD5JzJ‚J—J©J»JËJéJðJKK5K/OK K ‹K%—K½KÜKóK1 L>LNLhL{LŽL–LL´LºLØL#óL!M 9MZMnM ðMüM­ N ºN ÈNÓNØN çN ôNþNO OO "O,O1O BONOaOtO|O”O£O²OÅO%ÞOhPemP^ÓPc2Qa–QbøQa[R ½RÈR ÙRãRôRùRÿR SS .S):S*dS(S›¸STT ]ThT mT wTƒTŠTT˜T©TºTÉT ÏTÝT îTùT UU/U4U=UTUkUƒU“U£U´U ÊUÕUìUVV!V8VNVnV ŽV˜V«V¿VÑV ëVIöV@W[DWE W4æW¹X€ÕXVYiYoYYY Y*´Y5ßYZ&Z7ZIZRZcZ kZ wZ0˜ZÉZCÐZ[[9[Q[U[j[{[˜[œ[£[«[¼[Î[ Þ[ë[ ý[ \\\& \*G\ r\|\ …\ “\¡\±\¶\X½\]](]†^L¢^ï^ ___<_ O_%Z_ €_Ž_¢_ ª_·_ Ô_Mâ_0` D` Q` ^` h` s`~`M”`â` æ`ò`a a a#aAaÖaa|8b µbÖbôb c'cAc\c[vcÒc ìc ÷cdd)d :dDdWdsdd'«dÓd ådïd ÿd exe eœe.¯e#Þeggœjgh:h;Zh9–h,ÐhYýhWiFoi¶i*Ëi"öi‡j¡j'·j<ßj4k>QkBk>Ók?lDRl?—l9×l9m=Km@‰m=ÊmBn>Kn>Šn?Én= oDGo,Œo¹oËoÜo1ôo&p6pMpfp}p–p®pÈpÙpïp>q?Fq†qDœq%áq4r™%Z™7€™8¸™:ñ™*,š<Wš=”š?Òš,› ?›J›]›f›}›.˜›)Ç›'ñ›/œ*Iœ1tœ,¦œ"Óœ2öœ-)SW6«"â%ž\+žˆžž"§žÊžàž&ôžŸ#Ÿ9ŸUŸoŸ0‰Ÿ ºŸ ÄŸ,Ο#ûŸ 8 +P | " ³ àÓ  Ü è þ "¡**¡,U¡"‚¡)¥¡Ï¡„è¡ m¢y¢½Š¢H£ Y£g£o££ Ÿ£ ¬£¸£Ç£Ø£ ç£ñ£ø£¤¤':¤b¤j¤†¤™¤­¤ ˤ,ì¤_¥\y¥UÖ¥Z,¦X‡¦Yà¦X:§ “§§ ­§¸§Õ§Ú§ ß§ ì§ ù§ ¨(¨)<¨+f¨’¨ #© -©:© A© M© [©e©n©‰©Ÿ©¶©Å©Í© á© í©ú© ª/ª Kª Uª_ªsª!ˆªªª¾ªЪ᪠úª««:«U«]«x«%‘«)·« á«ï«¬¬ 2¬S¬Bb¬¥¬K­¬>ù¬<8­¿u­5®·®Ë®Ô®é®¯¯9*¯/d¯”¯%ª¯&Я ÷¯° #° 1°%<°,b°°F–° ݰ&è°±(±0±$H±m±„± ˆ± ’±œ±±±DZß±ñ±² ²²²4'²/\² Œ²˜² ² °² ¼²ʲ Ó²QÞ²0³qA³³´Lδ!µ=µ DµQµpµµ2µеàµøµ¶¶ /¶S:¶޶ ¶¶¶ ƶж á¶ï¶S · `·j· €·Ž··±· ·#ã·ì¸¢ô¸!—¹¹¹عð¹ º(ºDºq_ºѺïºöº»»5»O»b»#{»$Ÿ»&Ä»Dë»"0¼ S¼ `¼l¼r¼†¼½½%/½=U½m“¾¹¿»¿:Ö¿;À=MÀ)‹À^µÀ ÁT"ÁwÁ)ŠÁ´ÁwÐÁHÂ2YÂFŒÂ7ÓÂD ÃIPÃCšÃEÞÃK$ÄDpÄBµÄAøÄG:ÅO‚ÅFÒÅUÆEoÆEµÆFûÆHBÇI‹Ç<ÕÇÈ#,ÈPÈAkÈ­ÈÃÈ!ãÈÉ!%É GÉ"hÉ‹É"£É$ÆÉ@ëÉI,ÊvÊ=‘Ê,ÏÊ;üÊ8Ë,XË`…Ë9æË½ ÌÞÌ åÌóÌÍ*Í >ÍJÍ_Ív͋ͣͺÍÒÍ ðÍþÍ α"αÔÎŽ†ÏGÐ]ÐuÐ }ЉИРŸÐ ­Ð ºÐÇÐÙÐëÐÑ$Ñ>ÑYÑOtÑ-ÄÑ>òÑ‹1Ò½ÒaÕÒ57ÓmÓ‹Ó©ÓºÓÚÓøÓ% Ô1Ô%DÔjÔ€Ô™Ô&²ÔÙÔïÔ Õ6Õ!HÕ#jÕ0ŽÕ¿ÕHÚÕD#Ö*hÖ/“ÖÃÖ#ÜÖ#× $×1×F×h[×hÄ×-Ø!<Ø^ØnØ…ØØ ·Ø ÅØ ÐØÞØíØüØ'\sÞ™{UÑùÅp¢ÂǽñthàÈI\K+<šØJ"äDÊÄÕ…úÚ/O' C(kS*¹ýÌ£A wéñæ;Õ<ŒùêI}Š_1!€?`2b¤L×wßò„É.‹Yø¡Rcó óàHn× Û"rÜK8Ƴˆä;©pö`#· >Ñ]Þ/ïJ?Íx•°a)o›¦ $ðB7¦1û“F ±G¿åCžš?ξÆuÌ!¬.HŸÄ¤Ö(&t0†ë:q Šÿ{PÐì¬rÛî-1qn3—^¡ &.ëE¯èA2þ*ÿ~é^‡÷= -»v8õeJ|‰·7ßÅØÒm5gjM- #8´YWy½ÙT‘¾GŸHú–ç['õ"F™Z >XÈ‹˜®¨–¿9Á˜Ó,:!áÙÉFe|Ý3>Ã~=Òüއæ3/„¶áœÚd@‚67D5Bj0Х퉮¸Œ[DÀê±IVÀLô©†E@6Ôý’M9Í%s@f³aN44Nkž¶=ª£PœQUE,ËôuÁâþo% ¥(µ6NãX§­vxüÓÔσh<&#Mgˆð S*ï:€û4_§èBb9¯Î)²fzdÖ l¸$Ïì¢A øƒiÊ””÷‘;“Vª²])+ö»’çCL0Ëi2ºÝ•,ÇG +¨ â}z¼Rí¹OåKlmc‚5ãòy—T ¼Qî…´%µºZÜ ›««Ã$­Wް(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.2x2 custom2x2 normal3x3 custom3x3 normal4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA4A5 landscapeA5 portraitAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAnalog GainAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue intensityBlue offsetBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton stateButton test optionsCDCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration modeChannelCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor HalftoneColor LineartColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.CustomDebugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Determines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.DiamondDisable backtrackingDisable pre focusDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuration of read-delayEjectEject document after scanningEject the sheet in the ADFEnable Duplex (Dual-Sided) ScanningEnable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.EnhancementError DiffusionExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Exposure timeExtra FastFastFast gray modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFineFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGrain sizeGrayGray gainGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen intensityGreen offsetGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.Ignore calibrationImageImage EnhancementImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp onLamp statusLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual pre focusMatrix multiplication of RGBMaxMediumMidtoneMidtone for blueMidtone for greenMidtone for redMirror imageMirror the image.MiscellaneousMode 1Mode 2Mode 3Multi-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNegativeNegative FilmNo CorrectionNoise reductionNoneNormalNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOne pageOnly perform shading-correctionOptional equipmentPaper sizePhysical size of the paper in the ADFPositive FilmPredefined settingsPreviewPreview modePrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRandomizeRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed intensityRed offsetReduce the isolated dot noiseRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Return SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSaturationScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Second entrySelect bay to scanSelect minimum-brightness to get a white pointSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Set default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set exposure-timeSet lamp densitySet the order of framesSet the order of frames in three-pass color mode.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSlowSlowerSlowestSmoothSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsStatus Code SimulationString test optionsSwap black and whiteSwitches the lamp on or off.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampUTA onUse 0mm holder focus position instead of 0.6mmUse Image CompositionUse custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait for buttonWarm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWhite levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPA GrayY-resolutionZoomflatbed scannersheetfed scannerProject-Id-Version: sane-backends.cs Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-12-17 22:59+0100 Last-Translator: Josef Language-Team: Language: cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 0.9.5 (1/1) TlaÄítko(1/1) Testovací tlaÄítková volba. Vytiskne nÄ›jaký text...(1/3) Číslo s pevnou des. Äárkou(1/3) Číslo s pevnou desetinnou Äárkou, bez jednotek a bez omezení.(1/3) ŘetÄ›zec(1/3) ŘetÄ›zcová volba bez omezení.(1/6) Boolovská softwarová volba, softwarová detekce(1/6) Boolovská volba, která umožňuje softwarovou volbu a softwarovou detekci (a pokroÄilejší). Je to v podstatÄ› normální boolovská volba.(1/6) CeloÄíselná(1/6) CeloÄíselná testovací volba bez jednotek a nastavených omezení.(2/3) Číslo s pevnou des. Äárkou a omezeným rozsahem(2/3) Číslo s pevnou des. Äárkou, jednotkou mikrosekundy a omezením rozsahu. Minimum je -42,17, maximum 32767,9999, krok 2,0.(2/3) ŘetÄ›zcová volba s omezením seznamem(2/3) ŘetÄ›zcová volba s omezením seznamem.(2/6) Boolovská s hardwarovým výbÄ›rem a softwarovou detekcí(2/6) Boolovská volba, která podporuje hardwarovou volbu a softwarovou detekci (a pokroÄilejší). To znamená, že volbu nelze nastavit frontendem ale je nastavena uživatelem (napÅ™. stisknutím tlaÄítka na zařízení).(2/6) CeloÄíselná volba s omezením rozsahu(2/6) CeloÄíselná testovací volba s jednotkou bod a omezením rozsahu. Minimum is 4, maximum 192, krok je 2.(3/3) Číslo s pevnou desetinnou Äárkou s omezením seznamem slov(3/3) Číslo s pevnou desetinnou Äárkou bez jednotky a s omezením seznamem slov.(3/3) ŘetÄ›zcová volba s omezením dlouhým seznamem(3/3) ŘetÄ›zcová volba s dlouhými Å™etÄ›zci s omezením seznamem. Obsahuje ponÄ›kud více položek...(3/6) Boolovská volba s hardwarovým výbÄ›rem(3/6) Boolovská testovací volba, která podporuje hardwarový (a pokroÄilejší) výbÄ›r. To znamená, že volbu nelze zmÄ›nit frontendem ale jen uživatelem (napÅ™. stiskem tlaÄítka na zařízení) a frontend ji nemůže ani naÄíst.(3/6) CeloÄíselný seznam s omezením(3/6) CeloÄíselná testovací volba s jednokou bit a omezením množinou slov.(4/6) Boolovská volba se softwarovou detekcí(4/6) Boolovská testovací volba podporující softwarovou detekci (a pokroÄilejší). To znamená, že jde o volbu pouze ke Ätení.(4/6) CeloÄíselné pole(4/6) CeloÄíselné testovací pole s jednotkou mm a polem bez omezení.(5/6) Boolovská volba s emulací softwarové volby(5/6) Boolovská testovací volba, která podporuje softwarovou volbu, detekci a emulaci (plus pokroÄilejší).(5/6) CeloÄíselné pole s omezením rozsahu(5/6) CeloÄíselné testovací pole s jednotkou dpi a omezením rozsahu. Minimum je 4, maximum 192, krok 2.(6/6) Boolovská volba se softwarovou volbou a automatickou softwarovou detekcí(6/6) Boolovská testovací volba, která podporuje softwarovou volbu, softwarovou detekci (a pokroÄilejší). Tato volba může být automaticky nastavena backendem.(6/6) CeloÄíselné pole s omezením množinou slov(6/6) CeloÄíselné testovací pole s jednotkou procenta a omezením rozsahu pomocí množiny slov.2x2 volitelný2x2 normální3x3 volitelný3x3 normální4x4 hrubý4x4 volitelný4x4 jemný4x4 normální5x5 hrubý5x5 volitelný5x5 jemný15 x 10 (cm)6x6 volitelný6x6 normální22x28 (cm)20x24 (cm)8x8 Bayer8x8 hrubé zvýraznÄ›ní (fatting)8x8 jemné zvýranÄ›ní (fatting)8x8 vertikála8x8 hrubý8x8 volitelný8x8 jemný8x8 normální8x8 velmi jemnýA4A5 na šířkuA5 na výškuPÅ™idává modrou v závislosti na úrovni zelenéPÅ™idává modrou v závislosti na úrovni ÄervenéPÅ™idává zelenou v závislosti na úrovni modréPÅ™idává zelenou v závislosti na úrovni ÄervenéPÅ™idává Äervenou v závislosti na úrovni modréPÅ™idává Äervenou v závislosti na úrovni zelenéPokroÄiléPo odeslání příkazu ke skenování se s vlastním skenem Äeká až na stisk tlaÄítka na skeneru.VÅ¡echny stranyAnalogový ziskAnalogová korekce gama pro modrouAnalogová korekce gamaAnalogová korekce gama pro zelenouAnalogová korekce gama pro ÄervenouAnalogová korekce gamaAnalogová korekce gama pro modrouAnalogová korekce gama pro zelenouAnalogová korekce gama pro ÄervenouAutomatickyAutomatické nastavení prahových hodnotAutomatické rozložení plochyAutomaticky vysunoutAutomatickyAutomatický podavaÄ dokumentůAutomatické nastavení prahových hodnotAutomatické oddÄ›leníAutomatické nastavení prahových hodnotAutomaticky zahřátAutomaticky nastaví jas, kontrast, úroveň bílé, gama korekci, redukci Å¡umu a zvýraznÄ›ní obrázkuVyvážení modré. Hodnota 100% znamená bez korekce.Vyvážení zelené. Hodnota 100% znamená bez korekce.Vyvážení Äervené. Hodnota 100% znamená bez korekce.PoziceBayerRozptyl 16 BayerRozptyl 64 BayerDvouúrovňová Äernobílá (perokresba)Svázat RGBSvázat rozliÅ¡ení X a YSvázat analogovou hodnotu gamaSvázat hodnoty gamaBitová hloubkaÚroveň ÄernéModráVyvážení modréJas modréZisk modréIntenzita modréOdstup modréBoolovské (ano/ne) testovací volbyPravý dolní roh xPravý dolní roh x skenované plochy.Pravý dolní roh yPravý dolní roh y skenované plochy.JasStav tlaÄítekTestovací volby tlaÄítkovéCDCRTCRT monitoryKalibr. expoziÄní ÄasKalibr. expoziÄní Äas pro modrouKalibr. expoziÄní Äas pro zelenouKalibr. expoziÄní Äas pro ÄervenouKalibrovat svítivost (density) lampyKalibrovatKalibrovat skenerKalibrovat pÅ™ed dalším skenemKalibrovat zaostÅ™ení ÄoÄky na pozici dokumentuKalibruje úrovnÄ› Äerné a bílé.KalibraceKalibrace backendemRežim kalibraceKanálHrubýHrubá kalibraceHrubá kalibrace pouze pro první skenHrubá kalibrace se provádí pouze pro první sken. Ve vÄ›tÅ¡inÄ› případů funguje a může zkrátit Äas skenování. Pokud se obrázek s každým dalším skenem mÄ›ní, vyÅ™aÄte tuto volbu. Pouze pro testování!BarvaBarevný polotónBarevná perokresbaBarva RAWBarva RGBBarva RGB TEXTBarevné vyváženíNastavení zisku barevných kanálůNastavení odstupu barevných kanálůBarevná korekceKoeficienty barevných korekcíBarevný vzorekBarva 24Barva 36Barva 48PoÄet barevných Äar na jedno ÄteníKontrastKontrast modrého kanáluKontrast zeleného kanáluKontrast Äerveného kanáluOvládá úroveň modréOvládá úroveň zelenéOvládá úroveň ÄervenéNastavuje "odstín" (úroveň modré) naskenovaného obrázku.Ovládá jas naskenovaného obrázku.Nastavuje jas modrého kanálu naskenovaného obrázku.Nastavuje jas zeleného kanálu naskenovaného obrázku.Nastavuje jas Äerveného kanálu naskenovaného obrázku.Ovládá kontrast naskenovaného obrázku.Nastavuje kontrast modrého kanálu naskenovaného obrázku.Nastavuje kontrast zeleného kanálu naskenovaného obrázku.Nastavuje kontrast Äerveného kanálu naskenovaného obrázku.Nastavuje, zda je povolen ypÄ›tný průchod.VolitelnýVolby pro ladÄ›níStandardStandardní nastaveníDefinovat režim kalibraceNastavit expoziÄní dobu pro kalibraci modréNastavit expoziÄní dobu pro sken modréNastavit expoziÄní dobu pro kalibraciNastavit expoziÄní dobu pro kalibraci zelenéNastavit expoziÄní dobu pro sken zelenéNastavit expoziÄní dobu pro kalibraci ÄervenéNastavit expoziÄní dobu pro sken ÄervenéNastavit expoziÄní dobu pro skenDefinovat svítivost (density) lampy pro kalibraciDefinovat svítivost (density) lampy pro skenDefinuje polotónový (rozptylový) vzor pÅ™i skenování polotónových obrázků.Nastaví faktor pÅ™iblížení, který skener použijeProdleva pro pÅ™enos dat do roury.UrÄuje, jakou rychlostí se skenuje.Volí, zda má být použita vestavÄ›ná nebo uživatelem definovaná tabulka gama korekcí.DiamantVyÅ™adit zpÄ›tný chodVyÅ™adit pÅ™edběžné zaostÅ™eníBodový rozptyl 16x16Bodový rozptyl 8x8Zobrazí zkrácený seznam rozliÅ¡eníRozptylRozptyl A (4x4 Bayer)Rozptyl B (4x4 Spirálový)Rozptyl C (4x4 Síťový)Rozptyl D (8x4 Síťový)Polotónová Äernobílá s rozptylem (polotón)Rozptyl 1Rozptyl 2Skenovat ve stupních Å¡edé místo v barvÄ›Provést kvalitní kalibraci bíléNekalibrovat zaostÅ™eníNetlaÄit stavový kódNenutit backend, aby vrátil stavový kód.PodavaÄ dokumentůDvojnásobné optické rozliÅ¡eníDownload vzor ADownload vzor BVýpadekOboustranÄ›Doba prodlevy ÄteníVysunoutVysunout dokument po naskenováníVysunout papír z automatického podavaÄeZapnout oboustranné (duplexní) skenováníPovolit volbu expoziÄních ÄasůPovolit volbu svítivosti (density) lampyPovolit testovací volbyPovoluje různé testovací volby. Je tu pro testování schopností frontendů zobrazit a zmÄ›nit vÅ¡echny možné typy voleb SANE.VylepÅ¡eníChybový rozptylZamÄ›nit horní a spodní bajt obrázkových dat v 16-bitových režimech. Tuto volbu lze použít k testu 16-bitových režimů frontendů, napÅ™. zda frontend používá správný endian.ExpoziÄní ÄasVelmi rychlýRychlýStupnÄ› Å¡edé - rychlý režimRychlý náhledRychlý skenRychlejšíNejrychlejšíRežim podavaÄeJméno souboruTyp filmuJemnýVyvážení firmwaremPrvní položkaPozice pevného zaostÅ™eníTestovací volby s pevnou des. ÄárkouStolníZaostÅ™ení 2,5 mm nad skloPozice zaostÅ™eníZaostÅ™ení na skloSkenovat pÅ™i zpÄ›tném choduVynutit monochromatický náhledVynutit kalibraci skeneru pÅ™ed skenovánímPÅ™inutit backend, aby po volání sane_read() vrátil stavový kód SANE_STATUS_ACCESS_DENIED.PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód SANE_STATUS_COVER_OPEN.PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód SANE_STATUS_EOF.PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód SANE_STATUS_IO_ERROR.PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód SANE_STATUS_JAMMED.PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód SANE_STATUS_NO_DOCS.PÅ™inutit backend, aby po volání sane_read() vrátil stavový kód SANE_STATUS_NO_MEM.Z papíruZ bílého boduPlný skenNepÅ™esné (fuzzy) parametryZiskGamaKorekce gamaTabulky gamaKorekce gamaHodnota gamaTabulka gama korekcí pro modré pásmo.Tabulka gama korekcí pro zelené pásmo.Tabulka gama korekcí pro Äervené pásmo.Tabluka gama korekcí. V barevném režimu ovlivňuje Äervený, zelený a modrý kanál souÄasnÄ› (tj. jde o tabulku gama korekcí intenzity).GeometrieRozmÄ›r zrnaÅ edáZisk Å¡edéOdstup Å¡edéŠedá 16Å edá 8PÅ™evod do úrovní Å¡edéStupnÄ› Å¡edé 4 bityStupnÄ› Å¡edé 8 bitůStupnÄ› Å¡edéZelenáVyvážení zelenéJas zelenéZisk zelenéIntenzita zelenéOdstup zelenéPoÄet Äar ve stupních Å¡edi na jedno ÄteníMřížkaPolotónyPolotón A (ostrý)Polotón B (mÄ›kký)Polotón C (síť - "Net Screen")Polotón - 32 bodůPolotón 64 bodůVzorek polotónuRozmÄ›r vzorku polotónuPolotónyPolotón není podporovánSimulace ruÄního skeneruSimulace ruÄního skeneruVysokáTisk s vysokým kontrastemTisk ve vysoké kvalitÄ›Vysoká kvalita ale nižší rychlostNejvyšší rychlost ale nižší kvalitaSvÄ›tlé bodySvÄ›tlé body modréSvÄ›tlé body zelenéSvÄ›tlé body ÄervenéPozice zaostÅ™ení podavaÄe 0mmHorizontálníJak dlouho se má Äekat po pÅ™enesení každé dávky dat rourou.OdstínPokud je zvoleno, optimální prahové hodnoty se pokusí nastavit backend.Pokud je zvoleno, kalibraci pÅ™ed skenováním provede backendPokud je zvoleno, skener neskenuje pÅ™i zpÄ›tném průchodu.Pokud je tato volba zapnuta, pÅ™i kalibraci se provede pouze korekce stínů. Pro zisk, odstup a expozici jsou použity standardní hodnoty - buÄ vestavÄ›né nebo z konfiguraÄního souboru.Pokud je zvolena tato volba, je skener kalibrován pÅ™ed každým dalším skenem. Jinak se kalibruje pouze pÅ™ed prvním skenem.Ignorovat kalibraciObrázekVylepÅ¡ení obrázkuZvýraznÄ›ní obrázkuIntenzita obrázkuJehliÄkové tiskárnyV režimu RGB použít stejné hodnoty pro vÅ¡echny barvyZvýšit nebo snížit analogový zisk CCD poleInkoustové tiskárnyCeloÄíselné (Int) testovací volbyPÅ™evrátit endian (invert endianness)Vypnout lampuVypnout lampu pÅ™i ukonÄeníZapnout lampuStav lampyKalibrace ÄoÄky na pozici dokumentuUvidíme, jestli se s tím frontend vyrovnáLetterOmezit množství dat, pÅ™enášených každým voláním sane_read().PerokresbaNaÄíst obrázek v úrovních Å¡edé.Ztráta bodů na řádkuNízkáTisk v nízké kvalitÄ›Manuální pÅ™edběžné zaostÅ™eníNásobící matice RGBMaxStÅ™edníPolotónyPolotóny pro modrouPolotóny pro zelenouPolotóny pro ÄervenouZrcadlit obrázekZrcadlí obrázek.RůznéRežim 1Režim 2Režim 3Víceúrovňová RGB barva (jednoprůchodová barva)Víceúrovňová Äernobílá (úrovnÄ› Å¡edé)NTSC Å¡edáNegativNegativní filmBez korekceRedukce Å¡umuŽádnéNormálníPoÄet bitů na vzorek, typicky je 1 pro "perokresbu" a 8 pro vícebitové skeny.Množství volebPoÄet řádek skenu požadovaný v jednom příkazu Ätení SCSI. ZmÄ›nou tohoto parametru lze doladit rychlost, jakou jsou Ätena data pÅ™i skenování. Pokud je toto nastavení příliÅ¡ nízké, skener musí periodicky pÅ™i skenování zastavovat, pokud je příliÅ¡ vysoké, skenovací rozhraní v prostÅ™edí X mohou pÅ™estat reagovat a systém může zkolabovat.Číslo políÄka pro skenNabídnout select file descriptor pro detekci, zda sane_read() vrátí data.Nabídnout select file descriptorOdstupJedna stranaProvést pouze korekci stínůVolitelné přísluÅ¡enstvíRozmÄ›r papíruFyzická velikost papíru v automatikém podavaÄiPozitivní filmPÅ™ednastavené hodnotyNáhledRežim náhleduVytisknout seznam vÅ¡ech volebTisk volebPoskytuje standardní skenovací plochu pro fotografie, vytiÅ¡tÄ›né stránky apod.Kalibrace kvalitySken v plné kvalitÄ›Rychlý formátNáhodnýProdleva ÄteníLimit ÄteníVolba testu pouhého ÄteníHodnota pouze pro Ätení, která udává, kolik voleb dané zařízení podporuje.ÄŒervenáVyvážení ÄervenéJas ÄervenéZisk ÄervenéIntenzita ÄervenéOdstup ÄervenéRedukuje izolovaný bodový Å¡umPožaduje sken v kvalitÄ› náhledu.Požaduje, aby se vÅ¡echny náhledy provádÄ›ly v monochromatickém režimu. Na trojprůchodovém skeneru to snižuje poÄet průchodů na jeden, na jednoprůchodovém skeneru to snižuje paměťové nároky a Äas skenování náhledu.Požaduje, aby se vÅ¡echny náhledy dÄ›laly v nejrychleším režimu (s nízkou kvalitou). To může znamenat napÅ™. Äernobílý režim nebo nízké rozliÅ¡ení.Vrátit SANE_STATUS_ACCESS_DENIEDVrátit SANE_STATUS_COVER_OPENVrátit SANE_STATUS_EOFVrátit SANE_STATUS_IO_ERRORVrátit SANE_STATUS_JAMMEDVrátit SANE_STATUS_NO_DOCSVrátit SANE_STATUS_NO_MEMVrátit nepÅ™esné (fuzzy) řádky bajty na řádku, pokud je volána funkce sane_parameters() pÅ™ed sane_start()Návratová hodnota sane_readSytostSkalární gamaSkalární gama modréSkalární gama zelenéSkalární gama ÄervenéRežim skenováníZjistit expoziÄní ÄasZjistit expoziÄní Äas pro modrouZjistit expoziÄní Äas pro zelenouZjistit expoziÄní Äas pro ÄervenouSkenuje se ve stupních Å¡edé v rychlé režimu (nižší kvalitÄ›)Zjistit svítivost (density) lampyRežim skenuRozliÅ¡eníZdrojRychlost skenuNaskenovat kompletní skenovací plochu vÄetnÄ› kalibraÄního proužku. OpatrnÄ›! Nenastavujte plnou výšku! Pouze pro testování!Druhá položkaZvolte pozici pro skenZvolit minimální jas pro bílý bodZvolte druh testovacího obrázku. Možnosti: Zcela Äerný: vyplní celý sken Äernou barvou. Zcela bílý: vyplní celý sken bílou barvou. Barevný vzorek: vykreslí různé testovací barevné vzorky podle zvoleného režimu. Mřížka: vykreslí Äernobílou mřížku o šířce a výšce 10 mm / ÄtvereÄek.Volí režim náhledu. Náhled ve stupních Å¡edé obvykle nabízí nejlepší kombinaci rychlosti a detailu.Zvolte naávratovou hodnotu sane_read(). "Standard" je normální zpracování pÅ™i skenování. VÅ¡echny ostatní stavové hodnoty jsou pro testování, jak si s nimi frontend poradí.Zvolit testovací obrázekNastaví hodnotu skalární gama korekce pro modrý kanálNastaví hodnotu skalární gama korekce pro zelený kanálNastaví hodnotu skalární gama korekce pro Äervený kanálNastaví hodnotu skalární gama korekce.Ovládá "zrnitost" naskenovaného obrázku. Nižší hodnoty znamenají ostÅ™ejší obrázek.Nastaví jas.Nastaví barevné pásmo, "SpoleÄné" znamená, že jsou ovlivnÄ›ny vÅ¡echny barvy.Nastaví výpadek.Nastaví gama korekci pÅ™enosové kÅ™ivkyZvolí režim gama korekce.Zvolit gama korekci ze seznamu pÅ™eddefinovaných zařízení nebo uživatelské tabulky, kterou lze nahrát do skeneruZvolit polotónyZvolí Äíslo políÄka, které bude naskenovánoZvolí režim skenování (tj. perokresba, stupnÄ› Å¡edé nebo barva).Volí zdroj skenování (napÅ™. automatický podavaÄ).Nastavuje, jaká úroveň modré má být považována za "Äernou".Nastavuje, jaká úroveň modré má být považována za "zcela modrou".Nastavuje, jaká úroveň modré má být považována za "bílou".Nastavuje, jaká úroveň zelené má být považována za "Äernou".Nastavuje, jaká úroveň zelené má být považována za "zcela zelenou".Nastavuje, jaká úroveň zelené má být považována za "bílou".Nastavuje, jaká úroveň jasu má být považována za "Äernou".Nastavuje, jaká úroveň jasu má být považována za "bílou".Nastavuje, jaká úroveň Äervené má být považována za "Äernou".Nastavuje, jaká úroveň Äervené má být považována za "zcela Äervenou".Nastavuje, jaká úroveň Äervené má být považována za "bílou".Volí, zda naskenovaný obrázek má být pÅ™eveden na Äernobílý pomocí rozptylu.Nastaví, která úroveň jasu má být považována za "50% modrou".Nastaví, která úroveň jasu má být považována za "50% Å¡edou".Nastaví, která úroveň jasu má být považována za "50% zelenou".Nastaví, která úroveň jasu má být považována za "50% Äervenou".Nastaví standardní hodnoty prvků vylepÅ¡ení obrázku (jas a kontrast)Nastavit standardní hodnoty prvků pro vylepÅ¡ení obrázkuNastavit expoziÄní ÄasNastavit svítivost (density) lampyNastavit poÅ™adí kanálůNastavit poÅ™adí kanálů v trojprůchodovém barevném režimu.Zapíná/vypíná UTANastavuje zisk modrého kanáluNastavuje odstup modrého kanáluNastavuje zisk Å¡edého kanáluNastavuje odstup Å¡edého kanáluNastavuje zisk zeleného kanáluNastavuje odstup zeleného kanáluZapíná/vypíná lampuNastavuje zisk Äerveného kanáluNastavuje odstup Äerveného kanáluNastaví barevné vyvážení na hodnoty poskytované firmwarem.Nastaví tabulku barevných korekcí pro vybrané výstupní zařízení.Nastavuje režim podavaÄeNastaví pozici zaostÅ™ení buÄ na sklo nebo 2,5 mm nad skloNastavuje hodnotu gama pro vÅ¡echny kanály.Nastavuje horizontální rozliÅ¡ení skenovaného obrázku.Nastaví zvýraznÄ›ní obrázkuNastavuje rozliÅ¡ení skenovaného obrázku.Nastaví rozmÄ›r polotónového (rozptylového) vzoru pÅ™i skenování polotónových obrázků.Nastavuje vertikální rozliÅ¡ení skenovaného obrázku.Nastavit zisk a odstup pro skenování automaticky. Pokud je toto vypnuto, jsou zobrazeny ovádací prvky pro mauální nastavení. Tato volba je standardnÄ› zapnuta. Pouze pro testování!StínyStíny modréStíny zelenéStíny ÄervenéStíny, polotóny, svÄ›tlé body, expoziceZaostÅ™eníPosun modrá-zelenáPosun modrá-ÄervenáPosun zelená-modráPosun zelená-ÄervenáPosun Äervená-modráPosun Äervená-zelenáZkrácený seznam rozliÅ¡eníVypnout lampuVypnout lampu skeneru.JednostranÄ›Simuluje ruÄní skener. RuÄní skenery obvykle neznají výšku obrázku pÅ™edem. Proto vracejí výšku 1. Tato volba umožnuje otestovat, jestli se s tím frontend vyrovná.Simuluje ruÄní skener. RuÄní skenery obvykle neznají výšku obrázku pÅ™edem. Proto vracejí výšku 1. Tato volba umožnuje otestovat, jestli se s tím frontend vyrovná.Simuluje trojprůchodový skener tak, že vrací 3 oddÄ›lené obrázky. Pro ty pomalejší z vás to znamená zelený, modrý a pak Äervený.Simuluje trojprůchodový skener tak, že vrací 3 oddÄ›lené obrázky.Velikost limitu ÄteníPomalýPomalejšíNejpomalejšíJemnýZcela ÄernáZcela bíláVolba zdrojeZvláštní volbyZvláštní volbySimulace stavových kódůTestovací volby Å™etÄ›zcovéZamÄ›nit Äernou a bílouZapíná a vypíná lampu.Technika vylepÅ¡ení textuMaximální velikost dat, pÅ™enášených pÅ™i kaýždém volání sane_read().Jméno souboru obrázku, který bude naÄten.PoÄet bodů na konci každé řádky, které nejsou využity.Úroveň nasycení ovládá úroveň "sytosti" barev, obzvláštÄ› patrné u fotografií. Vyšší hodnoty znamenají výraznÄ›jší barvy.Teplocitlivé tiskárnyToto je velice dlouhá tÅ™etí položka. Doufejme, že frontend tuší, jak ji správnÄ› zobrazitTato volba vypne bÄ›hem skenu lampu plochého skeneruSimulace trojitého průchoduSimulace trojitého průchoduPrahová hodnotaVypnout lampu plochého skeneruVypne lampu plochého skeneruLevý horní roh xLevý horní roh x skenované plochy.Levý horní roh yLevý horní roh y skenované plochy.Průsvitná pÅ™edlohaProsvÄ›tlovací adaptérProsvÄ›tlovací jednotkaVypnout lampu pÅ™i ukonÄení programuVypnout lampu skeneruZapnout lampu skeneruUTA zapnutoPoužít pozici 0mm zaostÅ™ení podavaÄe místo 0,6mmUživatelské nastavení obrázkuPoužít uživatelskou tabulku gamaPoužít dvojité optické rozližení objektivuPoužít neblokující V/VPoužít neblokující V/V pro sane_read(), pokud to frontend podporuje.Použít shodné hodnoty gama pro vÅ¡echny ÄtyÅ™i barevné kanály.Použít shodné rozliÅ¡ení pro osu X a YPoužít prosvÄ›tlovací adaptér pro film 35mmUživatelské nastaveníUživatelsky definováno (Gama=1,0)Uživatelsky definováno (Gama=1,8)VertikálníČekat na tlaÄítkoÄŒekat na tlaÄítkoZahřát lampu dokud její jas není konstantní namísto standardního 40ti sekundového zahřívání.Zahřát lampu dokud její jas není konstantní namísto standardního 60ti sekundového zahřívání.Zahřát lampuZahřát lampu pÅ™ed skenovánímÚroveň bíléÚroveň bílé modréÚroveň bílé zelenéÚroveň bílé ÄervenéRozliÅ¡ení XXPA Å¡edáRozliÅ¡ení YPÅ™iblíženíStolní skenerskener s podavaÄemsane-backends-1.0.27/po/it.gmo0000664000175000017500000022105513110600540012753 00000000000000Þ•¤,1A ‘A-žA ÌA;ØA B,!B"NBzqB ìB9öB0C€MC#ÎC5òC"(DÆKDEj-E ˜EB¹E(üES%FyFØFiGBˆGËGlâGOHJ_H+ªHcÖH :Iz[I'ÖI™þI$˜JW½JK&K7K ?K JK UK `KkK sK ~K‰K ’K K ¨K³K ¼K ÇK ÒK ÝKêK òK L LL)L:L LL WLbL kL vLÒ„LWM ZM gMsM wM‚M‹MšM!¢MÄM!äM N'N GNhNqNs‚N öN O OO.OFOYOjO ‚O!£OÅOåOêOùO P P )P4P IPSP!mPP¤P¸P<ÉPGQ_NQ®Q=¾Q>üQ<;RxR|R‚R’R'¢RÊRÓRëR ýR S SS #S0S @SJSeS tS ‚SŽS«S½S%ÌSòS%T 'T2T;T DTQTeT|T„T‡T—T ›T¨T»T×TôTU !U+U=U)XU%‚U ¨U´UËUâUóUVV$V,V3V&FVÄmV2W8WAW PW ^W kW uWW ŽWœW¹WØWéW XXX%X-X CXOXXXnX…XšX®XÃX6ÖX. YBd od{d­‹d9e Se ^e lewee–e›e ªe ·eÁeÈe ÐeÜe åe ïeúe ÿe f f'f:fMf Ufbfhf€ffžf±f%ÊfhðfeYg^¿gcha‚hbähaGi ©i´iÅi ×iáiòi÷iýi jj ,j)8j*bj(j›¶jRk [kfk kkuk …k‘k˜kžk¦k·kÈk×k Ýkëk ükl#l3l BlOlml†l‹l”l«lÂlÚlêlúl m !m,mCm[m2sm2¦mÙmímòm nn?n _nin|nn¢n ¼nIÇnoTo[joEÆo4 p¹Ap€ûp|qq•q§q¶qÆq*Úq5r;rLr]rorxr ‰r—r¯r ·r Ãr ÐrÝr ör s0"sSsCZsžs¦sÃsÛsßsôs tt;tXt\tbtitytt’t¤t+´tàt òtÿtu3uQucu suuˆuu–u&¨u*Ïu úuv v v$v 3vAv Tv ^vlv‡v—vœv £vX°vÞ wèw]úwXytyLxyÅyâyéyìyõyz (z 3z@z_z%tzšz £z±zÀzÚzîz öz{ { &{M4{‚{ –{ £{°{À{ Ð{Ú{ Þ{ é{ô{M |X| \|h|w|€| š| ¨| µ|À|Ü| ú|}Ö%}|ü} y~‡~ ™~º~Ø~ï~ %@[Z¶Ð â íú €€ 0€:€M€i€†€'¡€É€ Û€ è€ò€  x ’Ÿ².Ãò ‚# ‚gDƒœ¬ƒI„:a„;œ„9Ø„,…Y?…%™…¿…F×…†/3†*c†"ކ‡±†9‡O‡'n‡<–‡4Ó‡>ˆBGˆ>Šˆ?ɈD ‰?N‰9މ9ȉ=Š@@Š=ŠB¿Š>‹>A‹?€‹=À‹<þ‹;ŒDJŒ,Œ¼ŒÕŒçŒøŒ?N1f˜;·óŽŽ-ŽFŽ]ŽvŽŽŽ¨Ž¹ŽÏŽ>çŽ?&fD|%Á4ç)4X^2·Ìê·‘¾‘Αß‘)î‘ ’ #’-’A’S’g’z’Œ’Ÿ’ µ’Ã’Ú’üâ’Ðß“p°”K!•m•€•†••’•™•¡• ¨• ²• ¾•ʕەë•û• –%–<–P–<e–¢–¿–GØ–' —uH—=¾—Œü—‰˜Sš˜7î˜;&™b™x™ Ž™ ˜™¹™Й ð™!û™ š!(š JšWšlš~š‘š £š ±šÒšèšýš›$›+›<›T›t›ˆ›—›.§›Ö›Cì›0œ(GœpœA„œÆœ.äœ&: Xe~— )°`Ú`;ž œž¨ž ÄžО¨èž>‘Ÿ‹ÐŸ \ h } “  § ´ ¸ Á  É Ö Û  ò ÿ ¡)$¡N¡k¡Š¡Ÿ¡¿¡ Õ¡â¡ö¡ ¢)¢2¢;¢&N¢u¢!‘¢³¢Ä¢Ö¢ò¢ ££,£/K£{£›£££³£º£J¥2Y¥Œ¥7 ¥ Ø¥,æ¥#¦‚7¦ º¦>Ǧ-§œ4§!ѧ:ó§#.¨æR¨9©€U©'Ö©Tþ©'SªT{ªЪõèª$Þ«P¬T¬zl¬ç¬Ký¬.I­`x­!Ù­û­(‹®¥´®)Z¯d„¯é¯°!°)° <°H° [°g°o°~° ‘° °©°¸° ˰×°ï° ±±±%±@± Y±c±t±ƒ±—±¦± ¹± űѱþã±â²å² ô²³ ³ ³³ 3³.A³.p³.Ÿ³0γ.ÿ³0.´_´h´“y´ µµ0µ"Cµfµ$µ$¦µ˵"æµ$ ¶$.¶ S¶^¶!p¶’¶¨¶ ¿¶ɶ Ù¶ä¶&·'·>·P·8l·@¥·•æ·|¸H¸JÙ¸J$¹o¹x¹~¹޹ž¹¶¹ȹâ¹ú¹º #º0º4ºJº^º5oº¥º¸º˺5Úº»)»5=»s»5‡» ½» Ê» Õ»à»ó»! ¼.¼7¼:¼Y¼ ]¼i¼$ƒ¼&¨¼&ϼö¼ ½½33½Jg½%²½ ؽå½ý½¾1¾H¾]¾q¾ x¾‚¾2™¾̾ã¿ê¿ú¿ ÀÀ .À 9ÀDÀUÀ-nÀ/œÀÌÀ%âÀÁÁ*Á:Á+JÁ vÁ ƒÁÁ¢Á¹ÁÐÁîÁ Â@,Â2mÂ@ ÂBáÂB$Ã/gÃ>—Ã@ÖÃ@Ä/XÄ'ˆÄ-°ÄÞÄAíÄ"/ÅRÅkÅ sÅ%Å=¥Å:ãÅ5Æ?TÆ<”Æ?ÑÆ<Ç2NÇ8Ç1ºÇ,ìÇ.È4HÈQ}È0ÏÈ!É"É#;Ép_ÉÐÉéÉ<òÉ/ÊFÊ'_ʇʙÊ5©Ê ßÊéÊþÊË.Ë"HËkËzË>‰Ë.ÈË?÷Ë7Ì VÌ9wÌ!±Ì$ÓÌøÌÍ-Í BÍMÍ\Í>mÍ¬Í ÊÍ*ÕÍ(Î)Î$IÎnÎ.ŠÎ ¹ÎHÚÎ-#Ï2QτϊŸÏ.*Ð+YÐ2…Ð?¸Ð øÐÑÜÑ÷Ñ Ò!Ò 6ÒCÒaÒgÒnÒ„Ò•Ò ¦Ò ²Ò¾Ò ×Ò áÒ ëÒ õÒÓ#Ó >Ó#KÓoÓ Ó›Ó¬Ó(²ÓÛÓ ùÓÔ 0Ô9QÔ‚‹ÔÕxŽÕ}Ö{…Ö|×{~×úרØ4ØGØ[ØdØjØ {Ø‰Ø šØ.§Ø0ÖØ0Ù§8Ù àÙêÙðÙ÷Ù Ú&Ú8ÚHÚ WÚdÚ{Ú’Ú®Ú´ÚÌÚâÚ7õÚ-ÛBÛWÛ7hÛ6 Û×Û ßÛêÛÜÜ6ÜFÜVÜ!iÜ ‹Ü–Ü"°Ü"ÓÜ+öÜ+"ÝNÝcÝhÝƒÝ žÝ ¿Ý àÝêÝÿÝÞ -Þ NÞEZÞ  Þ]ªÞUß\^ß2»ßâîß¶ÑàˆáŸá¨áÄáàáùá= â:Kâ†â¥â¼âÜâëâã1ãQã`ãtãŠã2¥ãØã&éã=äNäBUä˜ä& äÇäâäèä"å!&å%Hå)nå˜å å©å¯å ÅåÐåßåðåDæFæ[æ$mæ"’æ#µæ=Ùæç*ç0ç7ç>çEç]çzç ‰ç•çžç§çºçÏçâçýçè$è>èSè[ècèiuèßèóé^ê!dë †ëRë"ãëì ìì*#ìNìdìzìƒì£ì/¹ìéìüìí$íBí Uí _íií%pí–íL¨íõíî'î6îTî sîîˆî›î#­îSÑî%ï+ïCïYï7lï¤ï¹ïÎï7ßï"ð:ð/Cðésð¢]ñòò!'òIòhò€òò¸òÔòŠïò,zó§ó ¾ó ÊóØó ÷ó ô9ô!Pô,rô.Ÿô.Îô5ýô"3õVõkõ‚õžõ¯õ¯Áõqö&€ö§ö?Àö5÷6÷PU÷¦øÝ(ùú:$ú<_ú<œú6Ùúdû5uû«ûZÆû!ü49ü(nü-—ü–Åü\ý'sý0›ýQÌýCþIbþQ¬þKþþKJÿU–ÿMìÿE:G€KÈUMjE¸@þ>?>~>½UüRjc>Î0 #>/b’_²!>4sA’Ô/ñ"!D%^„$¡Æâ$&8BK{'ÇEï+5Ca%¥7Ë` Ad ¦  µ à Ü ÷ 1  D  N X s Ž © Æ á +þ *  D  e ?q ú± p¬Z x ™ ¥± · ÂÍÕ ä ïü&7P!hŠ¢O¸%$SJ3ž„Ò0W¬ˆ5WH> ?ß*(Js#z,ž<Ë6T6i  ¬Çâû+(Th}!— ¹Ä%Ú?@_x@’Ó6ó"*8M†Q#ïA-U%ƒ© ¾ ß  P`l`Í.4G|5˜ÀÎN€Þ_nˆ¤ ÀÎ ÒÝ åó ø -;=Y%—½Ú)ò;Jc2y¬µ¾)Ó/ýB- p Ž 2¤ -× !&!4>!Zs!8Î! ""&"LÄê§<½j&6?^ÆÎàЍl`‡E¤h6âä®iH¸€xæpÂîlÔüÚ|AUãPz5 ˆÍÀê‹¡Ä õ¹Žpr˜~wa¯Þ+2u±Û5ZA:U^';¹½£æì¨}†¬hïw™9gRC «”   óbaåƒt=•Š8ŠË„Ã;nÍNH/†¦3gšÈ yìGs˜/³»×b“!v²ºü'@ç ðù¾´§PÉ£`¿ÄOd~5¦ Ö‹Òœ¯–k o޼‚¤Î“Êξ«"f}4¡Œcœ,@M´ÌÝÅ …{a é˙̕ñØ8s[x=óªtÌÏ 24Z¼ïߥñ”° Ÿœ}±÷\žµþoˆ¾šê¨ó  ;D.!ŸþŒÂ²·G7)ÝlûÁÊ7d.Auc¡¯Å„+ß‘Tÿí>ÚÙO%rá&Xª0v­×ä0èF0YIÛdzpÞ»›ºQî•É‚tÜ$¥E³`"åÕÑYéXjÜM‡b²+û¶¶CÈÃ3¸®P¿õiWúÑCþ„ù@<Iž›ÓyÛ{…ñ2 ÊÇc_£èòÅT>!WTîöÝž®Æ[)|ÖÙZáq—–ØzRLÐFËqeŒOìÍå(ô<YN âÖ†ï_)nÑ?L#wàßäýÔÒ%Ks‰^¤gë¬ÐV$­ö‹#3š 4Èç9¼Æ÷(€Ïx[9?E]D½ú µºi ­H ‰Ü71’“—UøQ|Ÿ–u%Dm S1f'¥KÇÕ6WíòõÏQ:÷ª_-*øvÀùeVã…M.kâôÕ]‘-·J¹ònƒ¦(׬ð”’ €RXB™&öSüV=*fèëµ³>hÓÒ8ˆÉ-¿y»ÔÞ B¢¸çjý¶o›à‰rôÿǧ¢,øÃ]I°‡Á·ëÚN* ˜«m´á©~,k\Ž—©ƒqSí$ÿãÁûÐÓ#æée:KG1©¢‚úmýØÙB\°‘J’/J±ðFÀ"{(1/1) Button(1/1) Button test option. Prints some text...(1/3) Fixed(1/3) Fixed test option with no unit and no constraint set.(1/3) String(1/3) String test option without constraint.(1/6) Bool soft select soft detect(1/6) Bool test option that has soft select and soft detect (and advanced) capabilities. That's just a normal bool option.(1/6) Int(1/6) Int test option with no unit and no constraint set.(2/3) Fixed constraint range(2/3) Fixed test option with unit microsecond and constraint range set. Minimum is -42.17, maximum 32767.9999, and quant is 2.0.(2/3) String constraint string list(2/3) String test option with string list constraint.(2/6) Bool hard select soft detect(2/6) Bool test option that has hard select and soft detect (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device).(2/6) Int constraint range(2/6) Int test option with unit pixel and constraint range set. Minimum is 4, maximum 192, and quant is 2.(3/3) Fixed constraint word list(3/3) Fixed test option with no unit and constraint word list set.(3/3) String constraint long string list(3/3) String test option with string list constraint. Contains some more entries...(3/6) Bool hard select(3/6) Bool test option that has hard select (and advanced) capabilities. That means the option can't be set by the frontend but by the user (e.g. by pressing a button at the device) and can't be read by the frontend.(3/6) Int constraint word list(3/6) Int test option with unit bits and constraint word list set.(4/6) Bool soft detect(4/6) Bool test option that has soft detect (and advanced) capabilities. That means the option is read-only.(4/6) Int array(4/6) Int test option with unit mm and using an array without constraints.(5/6) Bool soft select soft detect emulated(5/6) Bool test option that has soft select, soft detect, and emulated (and advanced) capabilities.(5/6) Int array constraint range(5/6) Int test option with unit dpi and using an array with a range constraint. Minimum is 4, maximum 192, and quant is 2.(6/6) Bool soft select soft detect auto(6/6) Bool test option that has soft select, soft detect, and automatic (and advanced) capabilities. This option can be automatically set by the backend.(6/6) Int array constraint word list(6/6) Int test option with unit percent and using an array with a word list constraint.1/2 normal speed1/3 normal speed2-pixel2x2 custom2x2 normal3x3 custom3x3 normal4-pixel4x4 coarse4x4 custom4x4 fine4x4 normal5x5 coarse5x5 custom5x5 fine6x4 (inch)6x6 custom6x6 normal8 bit output8-pixel8.5x11 (inch)8x10 (inch)8x8 Bayer8x8 Coarse Fatting8x8 Fine Fatting8x8 Vertical Line8x8 coarse8x8 custom8x8 fine8x8 normal8x8 very fineA longer exposure time lets the scanner collect more light. Suggested use is 175% for prints, 150% for normal slides and "Negative" for negative film. For dark (underexposed) images you can increase this value.A4A5 landscapeA5 portraitADFADF DuplexADF ModeADF cover openADF jamAdds to blue based on green levelAdds to blue based on red levelAdds to green based on blue levelAdds to green based on red levelAdds to red based on blue levelAdds to red based on green levelAdvancedAdvanced OptionsAfter sending the scan command, wait until the button on the scanner is pressed to actually start the scan process.All pagesAnalog GainAnalog frontendAnalog gamma blueAnalog gamma correctionAnalog gamma greenAnalog gamma redAnalog gamma-correctionAnalog gamma-correction for blueAnalog gamma-correction for greenAnalog gamma-correction for redAutoAuto ThresholdAuto area segmentationAuto ejectAuto exposureAuto focusAuto focus only onceAutomaticAutomatic Document FeederAutomatic adjustment of thresholdAutomatic separationAutomatic thresholdAutomatic warmupAutomatically eject the film from the device after each scanAutomatically eject the film from the device before exiting the programAutomatically sets brightness, contrast, white level, gamma, noise reduction and image emphasisBacktrack linesBalance factor for blue. A value of 100% means no correction.Balance factor for green. A value of 100% means no correction.Balance factor for red. A value of 100% means no correction.BayBayerBayer Dither 16Bayer Dither 64Bi-level black and white (lineart mode)Bind RGBBind X and Y resolutionBind analog gammaBind gammaBit depthBlack levelBlueBlue balanceBlue brightnessBlue gainBlue gain value of the AFEBlue intensityBlue lamp offBlue offsetBlue offset value of the AFEBool test optionsBottom-right xBottom-right x position of scan area.Bottom-right yBottom-right y position of scan area.BrightnessButton 1Button 2Button stateButton test optionsButton-controlled scanButtonsCDCPU check errorCRTCRT monitorsCal. exposure-timeCal. exposure-time for blueCal. exposure-time for greenCal. exposure-time for redCal. lamp densityCalibrateCalibrate ScannerCalibrate before next scanCalibrate lens focus in document positionCalibrates for black and white level.CalibrationCalibration by backendCalibration data cacheCalibration modeCalibration nowChange Document.Change documentChannelCoarseCoarse calibrationCoarse calibration for first scan onlyCoarse calibration is only done for the first scan. Works with most scanners and can save scanning time. If the image brightness is different with each scan, disable this option. For testing only.ColorColor 36Color HalftoneColor LineartColor MatrixColor RAWColor RGBColor RGB TEXTColor balanceColor channels gain settingsColor channels offset settingsColor correctionColor correction coefficientsColor patternColor24Color36Color48Colour lines per readConditionalContrastContrast blue channelContrast green channelContrast red channelControls blue levelControls green levelControls red levelControls the "hue" (blue-level) of the acquired image.Controls the brightness of the acquired image.Controls the brightness of the blue channel of the acquired image.Controls the brightness of the green channel of the acquired image.Controls the brightness of the red channel of the acquired image.Controls the contrast of the acquired image.Controls the contrast of the blue channel of the acquired image.Controls the contrast of the green channel of the acquired image.Controls the contrast of the red channel of the acquired image.Controls whether backtracking is forced.Correction according to film typeCorrection according to transparency ratioCustomCustom color matrix for grayscale scans.Custom color matrix.Debugging OptionsDefaultDefaultsDefine calibration modeDefine exposure-time for blue calibrationDefine exposure-time for blue scanDefine exposure-time for calibrationDefine exposure-time for green calibrationDefine exposure-time for green scanDefine exposure-time for red calibrationDefine exposure-time for red scanDefine exposure-time for scanDefine lamp density for calibrationDefine lamp density for scanDefines blue lamp off parameterDefines green lamp off parameterDefines red lamp off parameterDefines the halftoning (dithering) pattern for scanning halftoned images.Defines the zoom factor the scanner will useDelay the transfer of data to the pipe.Density controlDetermines the speed at which the scan proceeds.Determines whether a builtin or a custom gamma-table should be used.Device-SettingsDiamondDisable auto document feeder and use flatbed onlyDisable backtrackingDisable interpolationDisable pre focusDispersedDot16x16DispersedDot8x8Display short resolution listDitherDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Dithered/halftone black & white (halftone mode)Dithermap 1Dithermap 2Do a grayscale rather than color scanDo a quality white-calibrationDo auto focus only once between ejectsDo not calibrate focusDo not force status codeDo not force the backend to return a status code.Document FeederDocument feeder extrasDouble Optical ResolutionDownload pattern ADownload pattern BDropoutDuplexDuplex scanDuplex scan provide a scan of the front and back side of the documentDuration of read-delayEjectEject document after scanningEject film after each scanEject film before exitEject film nowEject the film *now*Eject the sheet in the ADFEnable Duplex (Dual-Sided) ScanningEnable automatic determination of threshold for line-art scans.Enable selection of exposure-timeEnable selection of lamp densityEnable test optionsEnable various test options. This is for testing the ability of frontends to view and modify all the different SANE option types.Enable/disable auto focusEnable/disable the auto exposure featureEnables or disables calibration data cache.Enables or disables speeding up sensor movement.EnhancementError DiffusionExchange upper and lower byte of image data in 16 bit modes. This option can be used to test the 16 bit modes of frontends, e.g. if the frontend uses the correct endianness.Execute calibration *now*ExperimentExposure timeExtra FastExtra color adjustmentsExtrasFastFast gray modeFast previewFast scanFasterFastestFeeder modeFilenameFilm typeFilm-stripFineFine colorFirmware balanceFirst entryFix focus positionFixed test optionsFlatbedFlatbed onlyFocusFocus 2.5mm above glassFocus PositionFocus on glassForce backtrackingForce monochrome previewForce scanner calibration before scanForce the backend to return the status code SANE_STATUS_ACCESS_DENIED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_COVER_OPEN after sane_read() has been called.Force the backend to return the status code SANE_STATUS_EOF after sane_read() has been called.Force the backend to return the status code SANE_STATUS_IO_ERROR after sane_read() has been called.Force the backend to return the status code SANE_STATUS_JAMMED after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_DOCS after sane_read() has been called.Force the backend to return the status code SANE_STATUS_NO_MEM after sane_read() has been called.From paperFrom white stickFront button waitFull scanFuzzy parametersGainGammaGamma CorrectionGamma TablesGamma correctionGamma valueGamma-correction table for the blue band.Gamma-correction table for the green band.Gamma-correction table for the red band.Gamma-correction table. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).GeometryGrain sizeGrayGray gainGray mode colorGray offsetGray16Gray8GrayifyGrayscale 4 bitsGrayscale 8 bitsGrayscale scanGreenGreen balanceGreen brightnessGreen gainGreen gain value of the AFEGreen intensityGreen lamp offGreen offsetGreen offset value of the AFEGreyscale lines per readGridHalftoneHalftone A (Hard Tone)Halftone B (Soft Tone)Halftone C (Net Screen)Halftone Dot 32Halftone Dot 64Halftone patternHalftone pattern sizeHalftoningHalftoning UnsupportedHand-Scanner SimulationHand-scanner simulationHardware internal X position of the scanning area.Hardware internal Y position of the scanning area.Hardware resolutionHighHigh contrast printingHigh density printingHighest quality but lower speedHighest speed but lower qualityHighlightHighlight for blueHighlight for greenHighlight for redHolder focus position 0mmHorizontalHow long to wait after transferring each buffer of data through the pipe.HueIf Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans.If checked the backend automatically tries to determine an optimal value for the threshold.If checked the color calibration before a scan is done by the backendIf checked the scanner does not perform backtrackingIf enabled, only the shading correction is performed during calibration. The default values for gain, offset and exposure time, either build-in or from the configuration file, are used.If enabled, the device will be calibrated before the next scan. Otherwise, calibration is performed only before the first start.Ignore calibrationImageImage EnhancementImage emphasisImage intensityImpact-dot printersIn RGB-mode use same values for each colorIncrease or decrease the analog gain of the CCD arrayInk-jet printersInt test optionsInvert endiannessLamp offLamp off at exitLamp off timeLamp off time (minutes)Lamp onLamp statusLamp timeoutLampoff-timeLampoff-time in seconds.LampswitchLens calibration in doc positionLet's see whether frontends can treat this rightLetterLimit the amount of data transferred with each call to sane_read().LineartLoad the image as grayscale.Loss of pixels per lineLowLow density printingManual focus positionManual pre focusManually switching the lamp(s).Matrix multiplication of RGBMaxMediaMediumMedium handlingMidtoneMidtone for blueMidtone for greenMidtone for redMinutes until lamp is turned off after scanMirror horizontalMirror imageMirror image horizontally.Mirror image vertically.Mirror the image horizontallyMirror the image.Mirror verticalMiscellaneousMode 1Mode 2Mode 3Mono Color MatrixMulti-level RGB color (one pass color)Multi-level black & white (grayscale mode)NTSC GrayNTSC RGBNegativeNegative FilmNegative SlideNegative filmNegative film typeNegativesNo CorrectionNo transparency correctionNoise reductionNoneNormalNormal speedNumber of bits per sample, typical values are 1 for "line-art" and 8 for multibit scans.Number of lines the scan slider moves back when backtracking occurs. That happens when the scanner scans faster than the computer can receive the data. Low values cause faster scans but increase the risk of omitting lines.Number of optionsNumber of scan lines to request in a SCSI read. Changing this parameter allows you to tune the speed at which data is read from the scanner during scans. If this is set too low, the scanner will have to stop periodically in the middle of a scan; if it's set too high, X-based frontends may stop responding to X events and your system could bog down.Number of the frame to scanOffOffer a select filedescriptor for detecting if sane_read() will return data.Offer select file descriptorOffsetOnOne pageOnly perform shading-correctionOptional equipmentPaper sizePass-throughPerform scanner self diagnosisPerforms calibrationPhysical size of the paper in the ADFPositivePositive FilmPositive SlidePositive or negative filmPredefined settingsPreviewPreview modePrintPrint a list of all options.Print optionsProvides standard scanning areas for photographs, printed pages and the like.Quality calibrationQuality scanQuick formatRAM check errorROM check errorRandomizeRawRead delayRead limitRead only test-optionRead-only option that specifies how many options a specific devices supports.RedRed balanceRed brightnessRed gainRed gain value of the AFERed intensityRed lamp offRed offsetRed offset value of the AFEReduce the isolated dot noiseReflectiveRequest a preview-quality scan.Request that all previews are done in monochrome mode. On a three-pass scanner this cuts down the number of passes to one and on a one-pass scanner, it reduces the memory requirements and scan-time of the preview.Request that all previews are done in the fastest (low-quality) mode. This may be a non-color mode or a low resolution mode.Reset scannerReset the scannerReturn SANE_STATUS_ACCESS_DENIEDReturn SANE_STATUS_COVER_OPENReturn SANE_STATUS_EOFReturn SANE_STATUS_IO_ERRORReturn SANE_STATUS_JAMMEDReturn SANE_STATUS_NO_DOCSReturn SANE_STATUS_NO_MEMReturn fuzzy lines and bytes per line when sane_parameters() is called before sane_start().Return-value of sane_readSCSI parity errorSaturationScalar gammaScalar gamma blueScalar gamma greenScalar gamma redScan ModeScan exposure-timeScan exposure-time for blueScan exposure-time for greenScan exposure-time for redScan in fast gray mode (lower quality).Scan lamp densityScan marginsScan modeScan resolutionScan sourceScan speedScan the complete scanning area including calibration strip. Be careful. Don't select the full height. For testing only.Second entrySelect bay to scanSelect film typeSelect minimum-brightness to get a white pointSelect smoothing filter.Select the film typeSelect the kind of test picture. Available options: Solid black: fills the whole scan with black. Solid white: fills the whole scan with white. Color pattern: draws various color test patterns depending on the mode. Grid: draws a black/white grid with a width and height of 10 mm per square.Select the mode for previews. Greyscale previews usually give the best combination of speed and detail.Select the return-value of sane_read(). "Default" is the normal handling for scanning. All other status codes are for testing how the frontend handles them.Select the test pictureSelects a value for scalar gamma correction (blue channel)Selects a value for scalar gamma correction (green channel)Selects a value for scalar gamma correction (red channel)Selects a value for scalar gamma correction.Selects the "graininess" of the acquired image. Smaller values result in sharper images.Selects the ADF mode (simplex/duplex)Selects the brightness.Selects the colour band, "Master" means that all colours are affected.Selects the dropout.Selects the film type, i.e. negatives or slidesSelects the gamma corrected transfer curveSelects the gamma correction mode.Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scannerSelects the halftone.Selects the negative film typeSelects the number of the frame to scanSelects the scan mode (e.g., lineart, monochrome, or color).Selects the scan source (such as a document-feeder).Selects what blue radiance level should be considered "black".Selects what blue radiance level should be considered "full blue".Selects what blue radiance level should be considered "white".Selects what green radiance level should be considered "black".Selects what green radiance level should be considered "full green".Selects what green radiance level should be considered "white".Selects what radiance level should be considered "black".Selects what radiance level should be considered "white".Selects what red radiance level should be considered "black".Selects what red radiance level should be considered "full red".Selects what red radiance level should be considered "white".Selects whether the acquired image should be halftoned (dithered).Selects which radiance level should be considered "50 % blue".Selects which radiance level should be considered "50 % gray".Selects which radiance level should be considered "50 % green".Selects which radiance level should be considered "50 % red".Selects which scan color is used gray mode (default: green).Self diagnosisSet default values for enhancement controls (brightness & contrast).Set default values for enhancement controls.Set density control modeSet exposure-timeSet lamp densitySet sharpening value.Set the optical system's focus position by hand (default: 128).Set the order of framesSet the order of frames in three-pass color mode.Set the scanners color matrix.Set the time (in minutes) after which the lamp is shut off.Set type of media.Sets UTA on/offSets blue channel gainSets blue channel offsetSets gray channel gainSets gray channel offsetSets green channel gainSets green channel offsetSets lamp on/offSets red channel gainSets red channel offsetSets the color balance values to the firmware provided values.Sets the color correction table for the selected output device.Sets the feeding modeSets the focus position to either the glass or 2.5mm above the glassSets the gamma value of all channels.Sets the horizontal resolution of the scanned image.Sets the image emphasisSets the resolution of the scanned image.Sets the size of the halftoning (dithering) pattern used when scanning halftoned images.Sets the vertical resolution of the scanned image.Setup gain and offset for scanning automatically. If this option is disabled, options for setting the analog frontend parameters manually are provided. This option is enabled by default. For testing only.ShadowShadow for blueShadow for greenShadow for redShadow, midtone, highlight, exposure timeSharpeningSharpnessShift blue to greenShift blue to redShift green to blueShift green to redShift red to blueShift red to greenShort resolution listShut off lampShut off scanner lamp.SimplexSimulate a hand-scanner. Hand-scanners do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly. This option also enables a fixed width of 11 cm.Simulate a hand-scanner. Hand-scanners often do not know the image height a priori. Instead, they return a height of -1. Setting this option allows one to test whether a frontend can handle this correctly.Simulate a three-pass scanner by returning 3 separate frames. For kicks, it returns green, then blue, then red.Simulate a three-pass scanner. In color mode, three frames are transmitted.Size of read-limitSlideSlidesSlowSlowerSlowestSmoothSmoothingSolid blackSolid whiteSource SelectionSpecial OptionsSpecial optionsSpeedup sensorStart calibration process.Status Code SimulationString test optionsSwap black and whiteSwitch on/off the transparency unit (FAU, film adapter unit)Switches the lamp on or off.Text Enhanced TechnologyThe (maximum) amount of data transferred with each call to sane_read().The filename of the image to be loaded.The lamp will be turned off after the given time (in minutes). A value of 0 means, that the lamp won't be turned off.The number of pixels that are wasted at the end of each line.The saturation level controls the amount of "blooming" that occurs when acquiring an image with a camera. Larger values cause more blooming.Thermal printersThis is the very long third entry. Maybe the frontend has an idea how to display itThis option reflects the status of the scanner buttons.This option turns off the lamp of the flatbed during a scanThree-Pass SimulationThree-pass simulationThresholdThreshold value for lineart modeToggle lamp of flatbedToggles the lamp of the flatbedTop-left xTop-left x position of scan area.Top-left yTop-left y position of scan area.TransparencyTransparency AdapterTransparency UnitTransparency ratioTransparency unitTurn lamp offTurn off lamp when program exitsTurn off scanner lampTurn on scanner lampTurns the lamp off immediately.UTA onUnloadUnload Document.Unload media after scanUnloads the media after a scan.Update button stateUpdate optionsUpdate options.Use 0mm holder focus position instead of 0.6mmUse Image CompositionUse bit depth greater eight internally, but output only eight bits.Use custom gamma tableUse lens that doubles optical resolutionUse non-blocking IOUse non-blocking IO for sane_read() if supported by the frontend.Use only hardware resolutionsUse same gamma values for all colour channels.Use same values for X and Y resolutionUse the lightlid-35mm adapterUser definedUser defined (Gamma=1.0)User defined (Gamma=1.8)VerticalWait for ButtonWait to scan for front-panel button push.Warm-up until the lamp's brightness is constant instead of insisting on 40 seconds warm-up time.Warm-up until the lamp's brightness is constant instead of insisting on 60 seconds warm-up time.Warmup lampWarmup lamp before scanningWarmup-timeWarmup-time in seconds.When enabled, scan process will not start immediately. To proceed, press "SCAN" button (for MP150) or "COLOR" button (for other models). To cancel, press "GRAY" button.When using gray or lineart this option selects the used color.When using high resolutions where the horizontal resolution is smaller than the vertical resolution this disables horizontal interpolation.White levelWhite level for blueWhite level for greenWhite level for redX-resolutionXPAXPA GrayXPA RGBY-resolutionZoomcommand sequence errorfilm scannerflatbed scannerhardware check errorinitiator detected error message receivedinvalid bit IDENTIFY messageinvalid command operation codeinvalid field in CDBinvalid field in parameter listinvalid message errorlamp failurelamp not stabilizedmedium not presentno additional sense informationoffset Xoffset Yoption not connectparameter changed by another initiatorparameter list length errorpower on reset / bus device resetreselect failurerounded parameterscan head positioning errorsheetfed scannertimeout errortoo many windows specifiedtransparency unit lamp failuretransparency unit scan head positioning failuretransparency unit shading errorunknownunsupported LUNwebcamProject-Id-Version: sane-backends 1.0.18 Report-Msgid-Bugs-To: sane-devel@lists.alioth.debian.org POT-Creation-Date: 2017-05-22 11:18-0400 PO-Revision-Date: 2007-08-28 23:11+0200 Last-Translator: Giuseppe Sacco Language-Team: italian translation project Language: it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (1/1) pulsante(1/1) opzione pulsante di test. Stampa un testo...(1/3) virgola fissaOpzione a virgola fissa di test senza unità e vincoli.(1/3) stringa(1/3) opzione stringa di test senza vincoli.(1/6) bool, soft select soft detect(1/6) opzione booleana di test che ha capacità di soft select e soft detect (e oltre). Si tratta di una normale opzione booleana.(1/6) intero(1/6) opzione intera di test senza unità di misura e vincoli.(2/3) virgola fissa con vincolo di intervallo(2/3) opzione a virgola fissa di test con microsecondo come unità e vincolo di intervallo. Il minimo è -42,17, il massimo è 32767,9999 e il passo è 2,0.(2/3) stringa con lista di valori(2/3) opzione stringa di test con vincolo lista di valori.(2/6) bool, hard select soft detect(2/6) opzione booleana test che ha una capacità di hard select e soft detect e oltre. Vale a dire che questa opzione non può essere impostata dal frontend, ma dall'utente (come, ad esempio, premendo un pulsante sul dispositivo).(2/6) intero con intervallo(2/6) opzione intera di test che ha l'unità pixel e un vincolo di intervallo. Il minimo è 4, il massimo è 192, il passo è 2.(3/3) virgola fissa con lista di valori(3/3) opzione a virgola fissa di test senza unità e con il vincolo lista di valori.(3/3) stringa con lunga lista di valori(3/3) opzione stringa di test con vincolo lista di valori. Contiene più elementi...(3/6) bool, hard select(3/6) opzione booleana di test che ha capacità di hard select (e oltre). Vale a dire che non può essere impostata dal fronted, ma dall'utente (come, ad esempio, la pressione di un pulsante sul dispositivo) e non può essere letta dal frontend.(3/6) intero con valori da una lista(3/6) opzione intera con il bit come unità e il vincolo di valori da una lista.(4/6) bool, soft detect(4/6) opzione booleana di test che ha la capacità di soft detect (e oltre). Vale a dire che l'opzione è di sola lettura.(4/6) array di interi(4/6) opzione intera di test con il mm come unità e un array senza limiti.(5/6) bool, soft select soft detect emulazioneopzione di test booleana che ha la capacità di soft select, soft detect e emulazione (e oltre).(5/6) array di interi con vincolo(5/6) opzione intera di test con unità punti per pollice e un array con un vincolo di intervallo. Il minimo è 4, il massimo 192 e il passo 2.(6/6) bool, soft select soft detect auto(6/6) opzione di test booleana che ha la capacità soft select, soft detect e automatica (e oltre). Questa opzione può essere automaticamente impostata dal backend.(6/6) array di interi con lista di valori(6/6) opzione intera di test con unità percentuale e un array con una lista di valori come vincolo.Velocità normale dimezzata1/3 della velocità normale2-pixel2x2 personalizzato2x2 normale3x3 personalizzato3x3 normale4-pixel4x4 di massima4x4 personalizzato4x4 preciso4x4 normale5x5 di massima5x5 personalizzato5x5 preciso6x4 pollici (~15x10 cm)6x6 personalizzato6x6 normaleuscita a 8 bit8-pixel8.5x11 pollici (~21x28 cm)8x10 pollici (~20x25 cm)8x8 Bayer8x8 grana grossa8x8 grana fine8x8 linea verticale8x8 di massima8x8 personalizzato8x8 preciso8x8 normale8x8 molto precisoUn maggiore tempo di esposizione permette allo scanner di raccogliere più luce. I valori suggeriti sono 175% per le stampe, 150% per le normali diapositive e "Negativo" per le pellicole. Per immagini scure (sottoesposte) si può aumentare questo valore.A4A5 orizzontaleA5 verticaleADFADF DuplexModalità ADFCoperchio ADF apertoADF inceppatoModula il blu sulla base del livello del verdeModula il blu sulla base del livello del rossoModula il verde sulla base del livello del bluModula il verde sulla base del livello del rossoModula il rosso sulla base del livello del bluModula il rosso sulla base del livello del verdeAvanzatoOpzioni avanzateDopo aver inviato il comando di scansione, attendere finché non viene premuto il tasto dello scanner per fare partire il processo di acquisizione.Tutte le pagineGuadagno analogicoFrontend analogicoCorrezione gamma del blu analogicaCorrezione gamma analogicaCorrezione gamma del verde analogicaCorrezione gamma del rosso analogicaCorrezione gamma analogicaCorrezione gamma del blu analogicaCorrezione gamma del verde analogicaCorrezione gamma del rosso analogicaAutomaticoSoglia automaticaSezionamento automatico dell'areaEspulsione automaticaEsposizione automaticaAutofocusAutofocus unicoAutomaticoCaricatore automatico fogliDeterminazione automatica della sogliaSeparazione automaticaSoglia automaticaPreriscaldamento automaticoEspelle automaticamente la pellicola dopo ogni scansioneEspelle automaticamente la pellicola alla chiusura del programmaBrillantezza, contrasto, livello del bianco, correzione gamma, riduzione del rumore e accentuazione dell'immagine vengono determinati automaticamenteLinee del backtrackFattore di bilanciamento per il blu. 100% equivale a nessuna correzione.Fattore di bilanciamento per il verde. 100% equivale a nessuna correzione.Fattore di bilanciamento per il rosso. 100% equivale a nessuna correzione.CassettoBayerDither Bayer 16Dither Bayer 64Bianco e nero (binario)Lega i canali RGBLega la risoluzione X e YLega i valori gamma RGBFissa il valore gammaProfondità in bitLivello neroBluBilanciamento del bluLuminosità del bluGuadagno sul bluValore del guadagno sul blu per AFE (Analog FrontEnd)Intensità del bluLampada blu spentaScarto sul bluValore dello scarto sul blu per AFE (Analog FrontEnd)Opzioni booleane di testX in basso a destraPosizione X in basso a destra dell'area di scansione.Y in basso a destraPosizione Y in basso a destra dell'area di scansione.BrillantezzaPulsante 1Pulsante 2Stato del pulsanteOpzioni pulsanti di testScansione controllata da pulsantePulsantiCDErrore nel controllo della CPUCRTMonitor CRTCal. tempo di esposizioneCal. tempo di esposizione per il bluCal. tempo di esposizione per il verdeCal. tempo di esposizione per il rossoCal. potenza della lampadaCalibrazioneCalibrare lo scannerCalibrare lo scanner prima della prossima scansioneCalibrazione della messa a fuoco della lente nella posizione del documentoCalibrare i livelli del bianco e neroCalibrazioneCalibrazione automaticaCache per la calibrazioneModalità di calibrazioneCalibrazione immediataCambia il documento.Cambia il documentoCanaleGranulosoCalibrazione granulosaCalibrazione granulosa solo per la prima scansioneLa calibrazione granulosa è effettuata solo durante la prima scansione. Funziona con la maggior parte degli scanner e può fare risparmiare parecchio tempo. Disabilitarla se la brillantezza è diversa per ciascuna delle immagini da acquisire. Da usare solo per effettuare test.ColoreColore a 36 bitMezzi-toni coloreColore binarioMatrice del coloreColore RAWColore RGBColore RGB TESTOBilanciamento del coloreRegolazione del guadagno sui canali di coloreImpostazione dello scarto sui canali del coloreCorrezione del coloreCoefficienti di correzione del coloreModello di coloriColore a 24 bitColore a 36 bitColore a 48 bitNumero di linee colore per ciclo di letturaCondizionaleContrastoContrasto canale bluContrasto canale verdeContrasto canale rossoControlla del livello del bluControlla il livello del verdeControlla il livello del rossoControlla la tonalità (livello di blu) dell'immagine acquisita.Controlla la brillantezza dell'immagine acquisita.Controlla la luminosità del canale blu dell'immagine acquisita.Controlla la luminosità del canale verde dell'immagine acquisita.Controlla la luminosità del canale rosso dell'immagine acquisita.Controlla il contrasto dell'immagine acquisita.Controlla il contrasto del canale blu dell'immagine acquisita.Controlla il contrasto del canale verde dell'immagine acquisita.Controlla il contrasto del canale rosso dell'immagine acquisita.Verifica se il backtracking è stato impostato.Correzione in base al tipo di pellicolaCorrezione in base al rapporto di trasparenzaPersonalizzatoMatrice personalizzata del colore per scansioni a scale di grigi.Matrice personalizzata del colore.Opzioni per il debuggingDefaultPredefinitiDefinire la modalità di calibrazioneDefinisce il tempo di esposizione per la calibrazione del bluDefinisce il tempo di esposizione per la scansione del bluDefinisce il tempo di esposizione per la calibrazioneDefinisce il tempo di esposizione per la calibrazione del verdeDefinisce il tempo di esposizione per la scansione del verdeDefinisce il tempo di esposizione per la calibrazione del rossoDefinisce il tempo di esposizione per la scansione del rossoDefinisce il tempo di esposizione per la scansioneDetermina l'intensità della lampada per la calibrazioneDetermina l'intensità della lampada in scansioneImposta il parametro spegnimento lampada bluImposta il parametro spegnimento lampada verdeImposta il parametro spegnimento della lampada rossaDefinisce il modello mezzi-toni (sfumatura) utilizzato con immagini a mezzi-toni.Definisce il fattore di zoom usato dallo scannerRitarda il trasferimento dei datiControllo della densitàDetermina la velocità di scansioneDetermina se utilizzare per la correzione gamma dei valori predefiniti oppure quelli personalizzati dall'utente.Impostazioni-dispositivoDiamanteDisabilita l'alimentatore di fogli e usa solo il piano fissoDisattiva backtrackingDisattiva interpolazioneDisabilita la messa a fuoco preliminareDispersedDot16x16DispersedDot8x8Mostra la lista ridotta delle risoluzioni disponibiliSfumaturaDither A (4x4 Bayer)Dither B (4x4 Spiral)Dither C (4x4 Net Screen)Dither D (8x4 Net Screen)Bianco e nero (mezzi-toni sfumato)Mappa dither 1Mappa dither 2Effettuare una scansione in scala di grigi invece che a coloriEsegue una calibrazione qualitativa sul biancoEffettua l'autofocus una sola volta per ogni pellicola inseritaNon calibrare la messa a fuocoNon forzare il valore di ritornoNon obbliga l'interfaccia a fornire un valore di ritorno.Alimentatore automatico dei fogliOpzioni dell'alimentatore automaticoRaddoppia la risoluzione otticaScarica il modello AScarica il modello BEsclusioneFronte e retroScansione DuplexLa scansione duplex è quella di entrambi i lati del documentoDurata del ritardo in letturaEspulsioneEspelle il documento dopo la sua scansioneEspelle la pellicola dopo ogni scansioneEspelle la pellicola all'uscitaEspulsione della pellicola immediataEspelle la pellicola adessoEspelle il foglio dall'alimentatore automaticoAttiva la scansione fronte-retroAbilita la valutazione automatica della soglia per la scansione binaria.Abilita la selezione del tempo di esposizioneAbilita la selezione dell'intensità della lampadaAbilita le opzioni di testAbilita le varie opzioni di test. Usabile per verificare la capacità dei frontend di vedere e modificare tutti i tipi di opzioni di SANE.Abilita/disabilita la messa a fuoco automaticaAbilita/disabilita l'esposizione automaticaAbilita o disabilita la cache per la calibrazione.Abilita o disabilita il movimento del sensore di accelerazione.MiglioramentoDiffusione d'erroreInverte i due byte di dati nella modalità a 16 bit. Questa opzione può essere utilizzata per verificare la modalità a 16 bit dei frontend, vale a dire per vedere se il frontend utilizza correttamente l'«endianness».Esegue adesso la calibrazioneEsperimentoTempo di esposizioneExtra veloceAltre impostazioni del coloreExtraVeloceScala di grigi rapidoAnteprima veloceScansione rapidaPiù veloceVelocissimoModalità di caricamentoNome filePellicolaPellicolaA grana fineColore ad alta qualitàBilanciamento (valori preimpostati)Prima sceltaFissa la posizione di messa a fuocoOpzioni di test a virgola fissaPiano fissoSolo piano fissoFuocoMessa a fuoco 2,5mm sopra piano di vetroPosizione della messa a fuocoMessa a fuoco sul piano di vetroForza il backtrackingForza anteprima in bianco e neroForza la calibrazione dello scanner prima della scansioneObbliga il programma a fornire il valore di ritorno SANE_STATUS_ACCESS_DENIED dopo che sia stata chiamata la funzione sane_read().Obbliga il programma a fornire il valore di ritorno SANE_STATUS_COVER_OPEN dopo che sia stata chiamata la funzione sane_read().Obbliga il programma a fornire il valore di ritorno SANE_STATUS_EOF dopo che sia stata chiamata la funzione sane_read().Obbliga il programma a fornire il valore di ritorno SANE_STATUS_IO_ERROR dopo che sia stata chiamata la funzione sane_read().Obbliga il programma a fornire il valore di ritorno SANE_STATUS_JAMMED dopo che sia stata chiamata la funzione sane_read().Obbliga il programma a fornire il valore di ritorno SANE_STATUS_NO_DOCS dopo che sia stata chiamata la funzione sane_read().Obbliga il programma a fornire il valore di ritorno SANE_STATUS_NO_MEM dopo che sia stata chiamata la funzione sane_read().Da cartaDa bastoncino biancoAttesa del bottone frontaleScansione completaParametri «fuzzy»GuadagnoGammaCorrezione gammaTabelle gammaCorrezione gammaValore gammaTabella di correzione gamma per il colore blu.Tabella di correzione gamma per il colore verde.Tabella di correzione gamma per il colore rosso.Tabella di correzione gamma. In modalità colore tale opzione influenza in modo simultaneo i 3 canali (rosso, verde, blu) ed è quindi una tabella gamma di intensità.GeometriaGranaGrigioGuadagno sul grigioModalità a scala di grigiScarto sul grigioGrigio a 16 bitGrigio a 8 bitRendi grigioScala di grigi a 4 bitScala di grigi a 8 bitScansione in scala di grigiVerdeBilanciamento del verdeLuminosità del verdeGuadagno sul verdeValore del guadagno sul verde per AFE (Analog FrontEnd)Intensità del verdeLampada verde spentaScarto sul verdeValore dello scarto sul verde per AFE (Analog FrontEnd)Numero di linee in scala di grigi per ciclo di letturaGrigliaMezzi toniMezzi Toni A (hard tone)Mezzi Toni B (soft tone)Mezzi Toni C (net screen)Halftone Dot 32Halftone Dot 64Modello mezzi-toniDimensione del modello mezzi-toniMezzi-toniMezzi-toni non supportatiSimulazione di uno scanner manualeSimulazione di uno scanner manualePosizione interna X dell'area di scansione.Posizione interna Y dell'area di scansione.Risoluzione hardwareAltoStampa a contrasto elevatoStampa ad alta definizioneMassima qualità/Bassa velocitàMassima velocità/Bassa qualitàContrastoContrasto per il bluContrasto per il verdeContrasto per il rossoMessa a fuoco sul piano di vetroOrizzontaleQuanto attendere dopo avere tarsferito ogni singolo pacchetto di datiTonalitàSe viene selezionato il caricatore automatico di fogli, questo sarà vuoto dopo 10 scansioni.Se abilitato viene determinato in maniera automatica il valore ottimale della soglia.Se abilitato la calibrazione del colore viene eseguita automaticamente prima della scansioneSe abilitato lo scanner non esegue il backtrackingSe abilitata verrà eseguita solo la correzione delle ombre, qualora sia stata abilitata, mentre per guadagno, scarto e tempo di esposizione verranno utilizzati i valori predefiniti o quelli presenti nel file di configurazioneIl dispositivo verrà calibrato prima della prossima scansione solamente se tale funzione sarrà abilitata, altrimenti la calibrazione verrà eseguita solamente alla prima scansione.Ignora la calibrazioneImmagineMiglioramento dell'immagineAccentuazione dell'immagineIntensità dell'immagineStampanti a impattoUtilizza lo stesso valore per tutti i canali in modalità RGBAumenta o diminuisce il guadagno analogico del sensore CCDStampanti a getto d'inchiostroOpzioni intere di testInversione della «endianness»Lampada spentaLampada spenta in uscitaDurata spegnimento lampadaDurata in minuti dello spegnimento della lampada.Lampada accesaStato della lampadaTimeout della lampadaDurata spegnimento lampadaDurata in secondi dello spegnimento della lampada.Pulsante lampadaCalibrazione della lente sul documentoVerifica se in questo caso il frontend funziona correttamenteLetterLimita i dati passati ad ogni chiamata della funzione sane_read().BinarioCaricare l'immagine con scala di grigiPerdita di pixel per lineaBassoStampa a bassa definizionePosizione di messa a fuoco manualeMessa a fuoco preliminare manualeAccensione manuale della/e lampada/e.Moltiplicazione matriciale dei valori RGBMassimoSupportoMedioGestione del supportoMezzi toniMezzi toni bluMezzi toni verdiMezzi toni rossiNumero di minuti prima che la lampada venga spenta dopo la scansioneSpecchio orizzontaleImmagine riflessaRiflette l'immagine orizzontalmente.Riflette l'immagine verticalmente.Riflette l'immagine orizzontalmenteEffettua una riflessione dell'immagine lungo l'asse verticaleSpecchio verticaleVarieModo 1Modo 2Modo 3Matrice del colore monoColore RGB (singola passata)Scala di grigiGrigio NTSCNTSC RGBNegativoPellicola negativaDiapositiva negativaPellicola negativaTipo di pellicola negativaNegativiNessuna correzioneNessuna correzione della trasparenzaRiduzione del rumoreNessunoNormaleVelocità normaleNumero di bit per campione, il valore usuale è 1 per "Binario" e 8 per le scansioni ad alta risoluzione.Numero di linee che di cui fare arretrare il cursore della scansione durante il backtrack. Questo capita quando lo scanner è più veloce del computer durante la ricezione dei dati. Valori bassi permettono una scansione più veloce, ma aumentano il rischio di linee mancanti.Numero di opzioniNumero di linee da trasferire per ogni lettura SCSI. Cambiando tale parametro è possibile modulare la velocità alla quale i dati sono letti durante le scansioni. Un valore troppo basso produce un funzionamento "a scatti" dello scanner, un valore troppo grande può bloccare le interfacce X-Window dal rispondere agli eventi X e bloccare il sistema.Numero di fotogrammi da acquisireDisattivoPropone «select file descriptor» per verificare se sane_read() restituisce dati.Proponi «select file descriptor»ScartoAttivoPagina singolaEsegue solamente la correzione delle ombreDispositivi opzionaliDimensione del foglioPassanteEffettua i controlli automaticiEffettua calibrazioneDimensione del foglio nel caricatore automaticoPellicola positivaPellicola positivaDiapositiva positivaPellicola positiva o negativaValori predefinitiAnteprimaAnteprimaStampaStampa un elenco di tutte le opzioni.Stampa le opzioniFornisce le aree di scansione standard per fotografie, pagine stampate, etc.Qualità della calibrazioneQualità di scansioneFormato rapidoError nel controllo della RAMErrore nel controllo della ROMAleatorizzatoGrezzoRitardo in letturaLimiti in letturaOpzione per il test di sola letturaOpzione che visualizza quante opzioni sono supportate da uno specifico dispositivo.RossoBilanciamento del rossoLuminosità del rossoGuadagno sul rossoValore del guadagno sul rosso per AFE (Analog FrontEnd)Intensità del rossoLampada rossa spentaScarto sul rossoValore dello scarto sul rosso per AFE (Analog FrontEnd)Riduce il rumore dei punti isolatiRiflessoRichiede la qualità in anteprima di scansione.Richiede che tutte le anteprime siano eseguite in bianco e nero. Nel caso in cui lo scanner sia a 3 passate ne verrà quindi effettuata una sola, invece in quelli ad una passata riduce la memoria e il tempo richiesti per l'anteprima.Richiede che tutte le anteprime siano fatte nella modalità più veloce possibile (a bassa qualità). Questa potrebbe essere senza i colori o a bassa risoluzione.Reimposta scannerReimposta lo scannerRitorna SANE_STATUS_ACCESS_DENIEDRitorna SANE_STATUS_COVER_OPENRitorna SANE_STATUS_EOFRitorna SANE_STATUS_IO_ERRORRitorna SANE_STATUS_JAMMEDRitorna SANE_STATUS_NO_DOCSRitorna SANE_STATUS_NO_MEMRestituisce dei valori «fuzzy» per il numero di linee e quello di byte per linea se sane_parameters() è chiamata prima di sane_start().Valore di ritorno della funzione sane_read()errore di parità SCSISaturazioneScalare gammaValore gamma per il canale bluValore gamma per il canale verdeValore gamma per il canale rossoModalità di scansioneTempo di esposizione in scansioneTempo di esposizione in scansione per il bluTempo di esposizione in scansione per il verdeTempo di esposizione in scansione per il rossoScansione rapida con scala di grigi (bassa qualità).Potenza della lampada in scansioneMargini di scansioneModalità di scansioneRisoluzione della scansioneSorgente scannerVelocità scannerEffettua la scansione su tutta l'area possibile, compresa la striscia di calibrazione. Fare attenzione a non selezionare l'altezza completa. Da usare solo per effettuare test.Seconda sceltaSeleziona il cassetto per la scansioneSeleziona tipo pellicolaImposta la brillantezza minima corrispondente a un punto biancoSeleziona il filtro per l'ammorbidimento (smoothing).Seleziona il tipo di pellicolaSeleziona il tipo di immagine di test tra quelle disponibili: Nero pieno: riempie l'intera area di nero. Bianco pieno: riempie l'intera area di bianco. Modello di colori: disegna vari colori di test dipendentemente dalla modalità scelta Griglia: disegna una griglia di quadrati bianchi e neri aventi larghezza e altezza uguali a 10 mm.Determina come eseguire l'anteprima: un'anteprima con scala di grigi fornisce solitamente il miglior rapporto velocità/qualità.Seleziona il valore di ritorno della funzione sane_read(). "Default" è il corretto funzionamento del processo di scansione. Tutti gli altri valori di ritorno sono utilizzati per testare come vengono gestiti dal frontend.Seleziona l'immagine di provaSelezionare il valore per la correzione gamma (canale blu)Selezionare il valore per la correzione gamma (canale verde)Selezionare il valore per la correzione gamma (canale rosso)Selezionare il valore per la correzione gamma scalare.Seleziona la "granulosità" dell'immagine acquisita: valori minori determinano immagini più nitide.Seleziona la modalità ADF (solo fronte/fronte-retro)Seleziona la brillantezza.Selezionare la banda di colore, "Master" significa che tutti i colori saranno influenzati.Seleziona l'esclusione.Imposta il tipo di pellicola: negativi o diapositiveSelezionare la curva di correzione gammaSelezionare la modalità di correzione gamma.Seleziona la correzione gamma da una lista di dispositivi predefiniti, oppure dalla tabella personalizzata, con la quale verrà configurato lo scannerSeleziona i mezzi toniSeleziona il tipo di pellicola negativaSelezionare il numero di fotogrammi da acquisireSeleziona la modalità di scansione (ad esempio binaria, monocromatica o colore).Seleziona la sorgente per la scansione (come ad esempio il vassoio)Imposta quale livello di luminosità blu debba essere considerato "nero".Imposta quale livello di luminosità blu debba essere considerato "blu completo".Imposta quale livello di luminosità blu debba essere considerato "bianco".Imposta quale livello di luminosità verde debba essere considerato "nero".Imposta quale livello di luminosità verde debba essere considerato "verde completo".Imposta quale livello di luminosità verde debba essere considerato "bianco".Imposta quale livello di luminosità debba essere considerato "nero".Imposta quale livello di luminosità debba essere considerato "bianco".Imposta quale livello di luminosità rossa debba essere considerato "nero".Imposta quale livello di luminosità rossa debba essere considerato "rosso completo".Imposta quale livello di luminosità rossa debba essere considerato "bianco".Determina se l'immagine acquisita deve essere a mezzi-toni (sfumata).Selezionare il livello di luminosità da considerare "50 % blu".Imposta il livello di luminosità da considerare "50% grigio".Imposta il livello di luminosità da considerare "50 % verde".Imposta il livello di luminosità da considerare "50 % rosso".Seleziona il colore di scansione da usare per la scala di grigi (predefinito: verde).Auto diagnosticaImposta i valori predefiniti per il miglioramento della qualità dell'immagine (brillantezza e contrasto).Imposta i valori predefiniti per i controlli del miglioramentoImposta la modalità di controllo della densitàDeterminare il tempo di esposizioneDetermina la potenza della lampada in scansioneImposta il valore di nitidezza.Imposta manualmente la posizione del sistema di messa a fuoco (normalmente alla posizione 128).Determina l'ordine delle immaginiDetermina l'ordine delle immagini in una scansione a 3 passateImposta la matrice del colore.Imposta il ritardo (in minuti) dopo il quale spegnere la lampada.Imposta il tipo di supporto.Accendere/spegnere l'adattatore per trasparenzeImposta il guadagno sul canale bluImposta lo scarto sul bluImposta il guadagno sul canale grigioImposta lo scarto sul grigioImposta il guadagno sul canale verdeImposta lo scarto sul verdeCommuta lo stato della lampadaImposta il guadagno sul canale rossoImposta lo scarto sul rossoResetta i valori di bilanciamento ai valori preimpostatiImposta la tabella di correzione dei colori per il dispositivo selezionato.Selezionare la modalità di caricamentoSeleziona la messa a fuoco sul piano di vetro o 2,5mm sopra lo stessoImposta il valore gamma per tutti i canali.Determina la risoluzione orizzontale di acquisizione dell'immagine.Imposta l'accentuazione dell'immagineDetermina la risoluzione di acquisizione dell'immagine.Determina la dimensione del modello mezzi-toni (sfumatura) utilizzato con immagini a mezzi-toni.Determina la risoluzione verticale di acquisizione dell'immagine.Definisce guadagno e scarto per la scansione automatica. Se questa opzione è disabilitata allora saranno presenti nel frontend alcune opzioni per la parametrizzazione manuale analogica. Questa opzione è attiva in maniera predefinita. Da usare solo per effettuare test.OmbreggiaturaOmbreggiatura per il bluOmbreggiatura per il verdeOmbreggiatura per il rossoOmbre, toni medi, contrasto, tempo di esposizioneNitidezzaNitidezzaSpostamento da blu a verdeSpostamento da blu a rossoSpostamento da verde a bluSpostamento da verde a rossoSpostamento da rosso a bluSpostamento da rosso a verdeLista ridotta delle risoluzioni disponibiliSpegnimento della lampadaSpegne la lampada dello scanner.Solo fronteSimulazione di acquisizione mediante uno scanner manuale; questi scanner spesso non conoscono l'altezza dell'immagine a priori restituendo quindi il valore -1. Impostando tale opzione sarà possibile verificare se il frontend funziona correttamente. Questa opzione imposta inoltre la larghezza al valore fisso di 11 cm.Simula l'acquisizione mediante uno scanner manuale; questi scanner spesso non conoscono l'altezza dell'immagine a priori e restituiscono quindi il valore -1. Impostando questa opzione sarà possibile verificare se il frontend funziona correttamente.Simula l'acquisizione in 3 passate e ritorna 3 diverse immagini. Per primo il verde, poi il blue e poi il rosso.Simulazione di uno scanner a 3 passate. In modalità colore verranno trasmesse 3 immagini.Dimensione del limite in letturaDiapositivaDiapositiveLentoPiù lentoLentissimoMorbidoAmmorbidimentoNero pienoBianco pienoSelezione della sorgenteOpzioni specialiOpzioni specialiSensore di accelerazioneInizia la calibrazione.Simulazione del valore di ritornoOpzioni stringa di testInverte bianco e neroAbilita/disabilita l'adattatore per le trasparenze (FAU, «film adapter unit»)Accendi o spegni la lampadaTecnologia di miglioramento del testoLa quantità (massima) di dati passati ad ogni chiamata della funzione sane_read().Il nome del file contenente l'immagine da caricare.La lampada verrà spenta allo scadere del tempo impostato (in minuti). Il valore 0 indica che la lampada non deve mai essere spenta.Numero di pixel sprecati alla fine di ogni lineaIl livello di saturazione determina la quantità di «fioritura» qualora l'immagine venga acquisita con una fotocamera. Valori maggiori determinano una fioritura maggiore.Stampanti termicheQuesta è una terza scelta molto lunga. Il programma potrebbe riuscire a visualizzarla.Queste opzioni riflettono lo stato dei pulsanti dello scanner.Questa opzione spegne la lampada del piano durante la scansioneSimulazione dell'acquisizione in 3 passateSimulazione di una scansione a 3 passateSogliaValore soglia per modalità binariaCommuta lo stato della lampada dello scannerCommuta lo stato della lampada dello scanner (accesa/spenta)X in alto a sinistraPosizione X in alto a sinistra dell'area di scansione.Y in alto a sinistraPosizione Y in alto a sinistra dell'area di scansione.TrasparenzeAdattatore per trasparenzaAdattatore per trasparenzeRapporto per trasparenzeAdattatore per trasparenzeSpegne la lampadaSpegnere la lampada in uscita dal programmaSpegnere la lampadaAccendere la lampadaSpegne subito la lampada.Adattatore per trasparenze accesoEspulsioneEspelle il documento.Espelle il supporto dopo la scansioneEstrae il supporto originale dopo aver effettuato la scansione.Aggiorna lo stato del pulsanteOpzioni di aggiornamentoOpzioni di aggiornamento.Messa a fuoco sul piano di vetro invece che 0,6mm sopra il pianoUsa la composizione di immaginiUsa internamente più di 8 bit, ma produce solo 8 bit.Personalizzare la correzione gammaUtilizzo della lente per duplicare la risoluzione otticaUso dell'I/O asincronoUsa la modalità non bloccante di I/O per sane_read() se il frontend la supporta.Mostra solo le risoluzioni hardwareUtilizza lo stesso valore di correzione gamma per tutti i canali.Usa lo stesso valore per la risoluzione X e YUtilizza l'adattatore per diapositiveDefinito dall'utenteDefinito dall'utente (gamma=1.0)Definito dall'utente (gamma=1.8)VerticaleAttendi il tastoViene attesa la pressione del bottone frontale prima di effettuare la scansione.Preriscalda fino a che la luminisità della lampada sia costante invece di attendere 40 secondi.Preriscalda fino a che la luminisità della lampada sia costante invece di attendere 60 secondi.Preriscaldamento lampadaPreriscaldamento della lampada prima della scansioneDurata del preriscaldamentoDurata in secondi del preriscaldamento della lampada.Quando abilitato, l'acquisizione non partirà immediatamente. Per procedere premere il pulsante "SCAN" (per ML150) oppure "COLOR" (per altri modelli). Per annullare premere il pulsante "GRAY".Quando si usano i grigi o il binario questa opzione seleziona il colore usato.Quando si usano alte risoluzione con quella orizzontale minore della verticale, l'interpolazione orizzontale viene disabilitata.Livello biancoLivello di bianco sul bluLivello di bianco sul verdeLivello di bianco sul rossoRisoluzione XXPAXPA GrigioXPA RGBRisoluzione YZoomerrore nella sequenza di comandiscanner da negativiscanner pianoerrore nei controlli hardwarericevuto un messaggio di errore per rilevamento di iniziatoremessaggio con bit IDENTIFY non validocodice di comando non validocampo non valido in CDBcampo non valido nella lista di parametrierrore di messaggio non validolampada guastalampada non stabilizzatasupporto non presentenessun altra informazione aggiuntiva sul «sense»Scarto XScarto Yopzione non connessoparametro cambiato da un altro iniziatoreerrore nella lunghezza della lista di parametrireset dell'alimentazione elettrica / reset del bus dei dispositivierrore durante la reselezioneparametri arrotondatierrore nel posizionamento della testa di scansioneScanner con alimentatore automatico dei foglierrore di timeoutsono state specificate troppe finestreguasto della lampada dell'adattatore per trasparenzeerrore durante il posizionamento della testa di scansione per l'adatattore per trasparenzeerrore nel mascheramento della unità per la trasparenzasconosciutoLUN non supportatowebcamsane-backends-1.0.27/ar-lib0000775000175000017500000001330212775312260012322 00000000000000#! /bin/sh # Wrapper for Microsoft lib.exe me=ar-lib scriptversion=2012-03-01.08; # UTC # Copyright (C) 2010-2013 Free Software Foundation, Inc. # Written by Peter Rosin . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # func_error message func_error () { echo "$me: $1" 1>&2 exit 1 } file_conv= # func_file_conv build_file # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv in mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin) file=`cygpath -m "$file" || echo "$file"` ;; wine) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_at_file at_file operation archive # Iterate over all members in AT_FILE performing OPERATION on ARCHIVE # for each of them. # When interpreting the content of the @FILE, do NOT use func_file_conv, # since the user would need to supply preconverted file names to # binutils ar, at least for MinGW. func_at_file () { operation=$2 archive=$3 at_file_contents=`cat "$1"` eval set x "$at_file_contents" shift for member do $AR -NOLOGO $operation:"$member" "$archive" || exit $? done } case $1 in '') func_error "no command. Try '$0 --help' for more information." ;; -h | --h*) cat < Date: Sat May 20 14:13:19 2017 +0200 pixma: i-SENSYS MF240 Series is working commit ad5fd9edc83f2c6b6e27e9a366cd8ff5e00376b8 Author: m. allan noah Date: Fri May 19 20:24:14 2017 -0400 Updated NL translation from Martin Kho commit baf786742f0382bed3f1b58d9977229826e3df5f Author: Olaf Meeuwissen Date: Mon May 15 21:37:34 2017 +0900 po/*.po: sync with source code commit 05553c679fd02648fc5b6dd3a4abf75fe67e1d27 Author: m. allan noah Date: Sun May 14 21:34:36 2017 -0400 updated uk.po translation Update from Yuri Chornoivan commit 479ccaedddcb0a491b351e20cac22595196df02a Author: Olaf Meeuwissen Date: Sun May 14 19:48:41 2017 +0900 autotools: Sync derived files This was done by running autoreconf --force --install on Debian GNU/Linux 8.8 and reverting the removal of SANE specific tweaks to ltmain.sh. commit 02037adb134a2b533bb3201833444aed7bedc8f6 Author: Olaf Meeuwissen Date: Sun May 14 19:47:31 2017 +0900 Fix unused parameter compiler warnings in check tools commit 85b91bcd248d2a40300b9fda76bdb88853fbcd0b Author: Jörg Frings-Fürst Date: Sat May 13 18:11:40 2017 +0900 doc: fix typos, formatting and stylistic issues commit 1808a63b0091f0e5562586278b13d7ae63184f43 Author: Jörg Frings-Fürst Date: Sat May 13 18:07:26 2017 +0900 Replace the startup gamma with the same from the standalone version Fixes https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=629470 commit 5c0812c51b6d48516acb9dd9efcfbe2b34f04a79 Author: Jörg Frings-Fürst Date: Sat May 13 18:05:43 2017 +0900 genesys.conf: fix comment typo commit e21bb28e5051d8fdd64df3c4ea2625b9f45538c8 Author: Jörg Frings-Fürst Date: Sat May 13 18:03:42 2017 +0900 Source code string typo fixes commit 09cf70563a1129116ab6888e944bfcb44fec8dd0 Author: Olaf Meeuwissen Date: Sat May 13 16:33:23 2017 +0900 configure.ac: Fix condition commit 9230e0c251f2351ce1c7b8d7fca08dc39c320925 Author: Olaf Meeuwissen Date: Sat May 13 13:12:06 2017 +0900 saned: Link against Avahi library commit da5ce7216cf63a454411fa781bc2ea30fa881974 Author: Olaf Meeuwissen Date: Sat May 13 13:09:25 2017 +0900 Add a header to dll.conf Document dll.conf in a header, point to the dll.d directory for external backends and document the net backend w/ pointers to the manpages. Based on a patch by Julien BLACHE commit 77dcf26860b239dafb3094c863691aaef304805a Author: Christopher James Halse Rogers Date: Sat May 13 13:07:01 2017 +0900 Fix potential assert in avahi backend avahi_browser contains a reference to an AvahiClient, which may be avahi_client. If it does, then freeing avahi_browser references avahi_client, resulting in an assert() in Avahi's linked list macro. Fix this by freeing avahi_browser before avahi_client. See https://bugs.launchpad.net/bugs/831867 commit e6711c377f266d33a3d8bc28d7a508e3c4c29c79 Author: Rolf Bensch Date: Wed May 10 19:10:26 2017 +0200 remove unused entry from ChangeLog commit 0cf531e44528a541d76c3571bca72f395b7892ae Author: Klaus Kämpf Date: Tue May 9 10:52:12 2017 +0200 Update pieusb.conf and pieusb.desc commit 135b4a3909e0fe0d14062dc009bfba8085ebf167 Author: Rolf Bensch Date: Wed May 10 11:51:35 2017 +0200 pixma.desc: fix version of backend commit 5b10b0b635157cdb9766197a5f2ea7f1d24a402a Author: René Rebe Date: Fri May 5 07:05:30 2017 +0200 epson2: fixed network transport for new scanners increased command buffer due memory overrun, and always read receive status, even for zero length on network scanenrs, should fix #315552 commit 6ffeb9097386268e425ae2390ed2835853dbd439 Author: Olaf Meeuwissen Date: Sat May 6 20:40:25 2017 +0900 Fix test for API specification generation If none of the formats can be generated but API specs are requested, bomb. The original test aimed to do so but was testing against "no", a value that was never assigned. commit f3f8afb08c2098d9659757a8e7b8c212a09ddf79 Author: Olaf Meeuwissen Date: Sat May 6 12:24:13 2017 +0900 kvs20xx.c: don't assume sane_get_devices() has been called Nor that that function is called with a non-NULL argument. This aligns the implementation with that of kvs40xx.c. Fixes 315625. commit 8995b1fc81e4378d2b5b0b6b0d354735403210ed Author: Martin Husemann Date: Tue Mar 15 18:07:00 2016 +0900 sanei_usb: fix number of bytes read for 64bit big-endian systems Fixes 315337. commit b1a2c6105443c5279684f0c6827c268594aa234d Author: Louis Lagendijk Date: Fri May 5 19:46:28 2017 +0200 pixma: backend version 0.17.37 commit 09c467deab5ca4301ab7da37241c3fc072b94399 Author: Klaus Kaempf Date: Wed May 3 17:52:15 2017 +0200 pieusb: Support ProScan 10T and Reflecta CrystalScan 3600 Neither of these scanner have an automated slide transport and fail on respective SCSI commands. - Add flags parameter to control if automatic slide transport is available - Reflect flags in pieusb.conf.in - rename SLIDE_LAMP_ON to SLIDE_INIT it fails on scanners without automatic slide transport, so it has nothing to do with the lamp. - run SLIDE_INIT only FLAG_SLIDE_TRANSPORT is set - pieusb.conf.in: Add Reflecta CrystalScan 3600 commit 801558f959a03b5042d6df288cb1fd2c87035798 Author: Aaron Muir Hamilton Date: Mon May 1 20:15:23 2017 +0000 Write density (resolution) JFIF header information with JPEG files. commit b219bc2c73113fd9d8f7c5795bd662f03a8610ea Merge: f624a9f 92e5979 Author: Olaf Meeuwissen Date: Thu May 4 18:26:55 2017 +0900 Merge branch 'icc-profiles' commit f624a9f72527fc2896562e338f9b7c07549af0f0 Author: Olaf Meeuwissen Date: Mon May 1 09:39:59 2017 +0900 utsushi.desc: sync with upstream commit 0ca2fc46136dbaa30da25f4b79b67871c7e2d39b Author: Louis Lagendijk Date: Wed May 3 13:52:06 2017 +0200 fix 1200 dpi scanning for MB5000 series commit ff5c11622dafe58d1025f34a3672c7a059e963a7 Author: Louis Lagendijk Date: Wed May 3 13:48:20 2017 +0200 Fix scanbutton detection for MB5000 series commit 6af0e32bd6bd9e2c1b2adc5cb2a0561902eef526 Author: Paul Newall Date: Mon May 1 19:49:41 2017 +0100 kodakaio.c patched to change avahi callback variable from global to local. Bug 315705 commit e0741f71e289b878f0efad6cbb56b15d73b49f4e Author: Paul Newall Date: Sun Apr 30 18:09:59 2017 +0100 deleted a line in configure.ac. This was a commented out line left from when the backend kodakaio used CUPS to autodetect printers. commit 92e59791d2e478484409f5f2e634196863d7dafb Author: Olaf Meeuwissen Date: Sun Apr 30 20:05:12 2017 +0900 Fix [-Werror=implicit-function-declaration] compiler error The fileno() is only available if its feature test macro passes. The various symbols are defined appropriately in ../include/sane/config.h during configuration of the build. commit adebd37b5cb3ec0cab3025300db5cdd03c2173cc Author: Olaf Meeuwissen Date: Sun Apr 30 20:00:28 2017 +0900 Fix [-Wpointer-arith] compiler warnings commit c3903cc476909884ace9fedbea5f69b3a4085b70 Author: Aaron Muir Hamilton Date: Mon Apr 17 12:07:40 2017 +0000 Avoid attaching grayscale ICC profiles to rgb images, or vice-versa. If the ICC profile added does not match the colour format of the image, libpng will abort. This can leave the scanner motors in an incorrect state and possibly cause permanent damage. commit a907b61bd58f00fd6b1d8468d9d28d6d39232c79 Author: Aaron Muir Hamilton Date: Mon Apr 17 12:07:39 2017 +0000 Add ICC profile embedding for PNG output. commit 2c653a926af83d7bb910307f441055a6d7603f0b Author: Aaron Muir Hamilton Date: Sun Apr 16 15:13:06 2017 +0000 Separate ICC profile loading into a separate file. This cuts out some duplicate code, and enables us to reuse this logic for PNG, JPEG, and any other future output format. sanei_load_icc_profile also allows us to know that an ICC profile file is not long enough before we start to write it to the output; this should prevent poorly-written software from overflowing into image data when they read the bad profile based on its length. commit 611388db1d56b0ffd74af05c4a51fe518269c90d Author: Rolf Bensch Date: Thu Apr 27 21:59:24 2017 +0200 pixma.desc: fix usbid for PIXMA TS5000 Series commit 5389301a40d67ed627b1998e19a1af60da26e93f Author: Olaf Meeuwissen Date: Thu Apr 27 22:26:01 2017 +0900 utsushi.desc: PID 0156 is a ES-400 See Alioth issue 315695. commit a0321d2a92286afbc9557fa44e2de4f706cf2407 Author: Aaron Muir Hamilton Date: Sun Apr 16 09:06:48 2017 +0000 Include physical resolution (pHYs section) in PNG output. commit 469dc738aafe42b231ecae778e393263028ab1b9 Author: Olaf Meeuwissen Date: Thu Apr 27 21:17:34 2017 +0900 Only swap 16-bit PNG bytes on machines that are not big-endian The SANE API specifies that image bytes are in machine native order. commit 28eb09eec4c64d9070b5747c93c25134395cab53 Author: Aaron Muir Hamilton Date: Sun Apr 16 00:27:54 2017 +0000 Swap bytes in 16-bit PNGs, because PNG is big-endian. commit 5fa4be5ae4f9937d79f076f7004a4b48ba765e8a Author: Rolf Bensch Date: Wed Apr 26 11:06:00 2017 +0200 pixma: backend version 0.17.36 commit 879565cefcac61e371581d09696ef6d738c2a720 Author: Rolf Bensch Date: Wed Apr 26 11:43:30 2017 +0200 new scanners Canon i-SENSYS MF230 and MF240 Series commit ddccf956b44509fc21cdcd4c52b6750e2ddab37a Author: Rolf Bensch Date: Wed Apr 26 11:02:46 2017 +0200 pixma_mp150: MG5400 Series has button scan support commit f14285dba30404f23fc9de13d632e69f23f7cb75 Author: Rolf Bensch Date: Thu Apr 6 11:20:40 2017 +0200 pixma_mp150: MG5400 Series doesn't need special image format post processing @ high dpi commit 0960bf9c72d25a0f8686314fbe9a6a0f9002ea3c Author: Olaf Meeuwissen Date: Tue Apr 18 20:12:31 2017 +0900 utsushi.desc: sync with upstream commit dcddb9505c88485bda6cdcf77927d14008b449ee Author: m. allan noah Date: Tue Apr 11 21:22:05 2017 -0400 epjitsu backend v31 - hardware gray support for fi-60F/65F (disabled pending calibration) - merge fi-60F/65F settings - improve desc, conf and man files commit 34e4dbf6c35946ca52678f6a7a61ef002fddb1c2 Author: Olaf Meeuwissen Date: Mon Apr 10 20:23:03 2017 +0900 Bump Alpine and Fedora builder versions commit 9712e2aa2595f440252d40c26b680c3cf2b8ae30 Author: m. allan noah Date: Sat Apr 8 21:44:27 2017 -0400 fujitsu backend v133 2017-04-08, MAN - initial support for fi-7600/7700 - autodetect various double feed capabilities using VPD - call send_lut if we are using a downloaded gamma table commit 5edb87f9ac950473f8c3a57b4071c970887d8440 Author: Olaf Meeuwissen Date: Sat Apr 8 21:08:12 2017 +0900 genesys: Trigger reallocation of gamma tables on next sane_open() Fixes 315491. commit 6eb4a1f164ef116a3ed10ee42883a15c268ea01e Author: Robert Ancell Date: Tue Apr 4 11:36:05 2017 +1200 kodakaio: Fix crash when Avahi search fails commit ccb47215e653724f317f7d40138098762578a6f9 Author: Olaf Meeuwissen Date: Fri Apr 7 20:28:02 2017 +0900 Add missing double quote Accidently removed in 38ce7fc086a6ecbee94ef31901a6eb874fb611b1. Thanks to Jon Nelson for pointing this out. commit 38ce7fc086a6ecbee94ef31901a6eb874fb611b1 Author: Olaf Meeuwissen Date: Wed Apr 5 18:29:41 2017 +0900 Update SANE developer and backend maintenance status commit cbcab6dffadffdb40f87ddffaf2aa7e1618bb72b Author: Rolf Bensch Date: Tue Apr 4 11:28:18 2017 +0200 pixma: backend version 0.17.35 commit 66ce95a5a1a716a92260701c76c0989abf4196bb Author: Rolf Bensch Date: Tue Apr 4 11:59:56 2017 +0200 new scanners Canon PIXMA G3000, E470, G3000, TS5000, TS6000, TS8000 and TS9000 [#315658] commit a2e26572729d62123b2f167fee9e671bf26b8987 Author: Rolf Bensch Date: Tue Apr 4 11:27:38 2017 +0200 pixma: signal scan cancel from the frontend with new parameter s->param->frontend_cancel commit c5bfbc5a3a43a81776841289cd164a584c2e8ec2 Author: Rolf Bensch Date: Tue Apr 4 11:25:53 2017 +0200 pixma: implement adf-wait for imageclass scanners commit 17f3899b1583971351ea7ac40e92660f6558268d Author: Rolf Bensch Date: Tue Apr 4 11:23:03 2017 +0200 pixma: new option adf-wait commit 3ef45ec3c3d56bfc60b339dac8a2f19543387ef3 Author: Rolf Bensch Date: Tue Apr 4 11:16:20 2017 +0200 pixma: update docs for MG5400 Series commit e6c8ea6f0bcb2c6b6f7004feadc7db6cbfc3ee2b Author: m. allan noah Date: Wed Mar 22 12:33:27 2017 -0400 epjitsu backend v30 again - typo in previous commit broke low resolution scans on fi-65F commit a7fde11e15e5604c7b37bc9553cbd08086c08e53 Author: m. allan noah Date: Tue Mar 21 21:35:59 2017 -0400 epjitsu backend v30 - bump build number commit 891e3984d0410fa8c698d99d79948df3237e258d Author: m. allan noah Date: Tue Mar 21 20:39:47 2017 -0400 epjitsu v30 - fix image truncation when using 150 DPI in Y direction - add 200 and 400 DPI Y direction support for fi-60F/65F commit 42896939822b44f44ecd1b6d35afdfa4473ed35d Author: Olaf Meeuwissen Date: Sun Feb 19 16:45:45 2017 +0900 Address memory corruption and information leakage. Addresses CVE-2017-6318, Alioth#315576 and Debian's BTS#854804. commit eaa4d4407d96585b7cdbe194d8ac295eee3e6299 Author: m. allan noah Date: Sat Mar 18 19:15:03 2017 -0400 epjitsu backend v29 - fix infinite loop when scaling in Y direction commit 2f9ea038b157fc6d08ce882a1d9984d37b46d809 Author: Olaf Meeuwissen Date: Sat Mar 11 10:48:35 2017 +0900 Fix typo See http://lists.alioth.debian.org/pipermail/sane-devel/2017-March/035099.html commit 1e028b72cae0f4caaf48868504bd2cd1667d6da7 Author: Olaf Meeuwissen Date: Mon Mar 6 20:54:59 2017 +0900 pixma: updated status for MG5400 Series See http://lists.alioth.debian.org/pipermail/sane-devel/2017-March/035072.html and http://lists.alioth.debian.org/pipermail/sane-devel/2017-March/035082.html commit 928b803ef1f1bc1007ca3fa83418f103c6a7bdd7 Author: Olaf Meeuwissen Date: Sun Mar 5 15:35:06 2017 +0900 utsushi.desc: sync with upstream commit f450049bccc1e331790cb2546c2c1440fa3d24c0 Author: Olaf Meeuwissen Date: Tue Feb 14 18:52:25 2017 +0900 utsushi.desc: sync with upstream commit e3ed043500e786724cc77fdd0565993e878a51fc Author: Olaf Meeuwissen Date: Mon Dec 26 08:13:33 2016 +0900 Update backend maintenance status Following the project member list cleanup, only backends that list a project member with git write access in the AUTHORS file are now considered maintained. commit 7a0e1126b3eebd38944b8b281e6a481b95a35bbd Author: Louis Lagendijk Date: Fri Jan 6 23:30:31 2017 +0100 Revert "pixma_mp150.c: Fix scanbutton detection for MB5000 series" This reverts commit 53aa78df3a6980791ce250c471d019c5c59b83ec. commit 306f8f16e78b52948a6e09fa0957b3e364e0189f Author: Louis Lagendijk Date: Fri Jan 6 23:29:59 2017 +0100 Revert "pixma_mp150.c: fix 1200 dpi scanning for MB5000 series" This reverts commit dfc5487571ed2915bda7bdedbd4c79015004361b. commit 9bc734042f6a2af159772eef412efe7c65ebb02f Author: Louis Lagendijk Date: Fri Jan 6 23:28:56 2017 +0100 Revert "pixma_mp150.c: scan param 0x26-0x29 should contain localtime HHMM, also for MB5000 series" This reverts commit eb712c6bd8ca6a42a1d3941583fa18b9981b8712. commit 6c439bce791522aa9cd3fc04cf62087bdd6c6875 Author: Louis Lagendijk Date: Fri Jan 6 23:28:31 2017 +0100 Revert "pixma_mp150.c: replace multiple if statements with case statement in handle_interrupt" This reverts commit 28dcd0aef4ac91b87527c17c8aa89e879f39f20d. commit 06b4b27ecfad1aa30c772fa0fac15d1c144c1e7a Author: Louis Lagendijk Date: Fri Jan 6 23:28:09 2017 +0100 Revert "pixma_mp150.c: fix parameter settings for MB5000 in send_scan_param" This reverts commit 1d2a40ec96aea0ba183415efea570301159d4159. commit 589e011992a21ae1edb4684eb89582350c47333f Author: Louis Lagendijk Date: Fri Jan 6 22:15:24 2017 +0100 Update the sane-pixma man-page for the new timout setting option. commit 1b442ce1ea7068bda1129c061071dc94bfd6a8d2 Author: Louis Lagendijk Date: Fri Jan 6 21:37:52 2017 +0100 Added examples for new bjnp timer settings in the pixma config file commit cfc7a069d2696942bfeac90e0ff7aa50f83d0ec1 Author: Louis Lagendijk Date: Sat Dec 31 17:56:06 2016 +0100 Added timeout options for the bjnp protocol commit c2898cb6021fac6e2a526c2ce4692783ca69b18d Author: Louis Lagendijk Date: Fri Dec 30 21:36:26 2016 +0100 Remove incorrect comment left from old version commit 526f642f6487cd348b39a6e138c2bffa9a88d0f6 Merge: 32be261 68cd274 Author: Louis Lagendijk Date: Fri Dec 30 20:04:53 2016 +0100 Merge branch 'master' of ssh://git.debian.org/git/sane/sane-backends commit 68cd2744d1906ebf00b2bfdc90662992f8e5385c Author: Olaf Meeuwissen Date: Sun Dec 18 16:53:26 2016 +0900 Sort backends with LC_COLLATE=C commit d47957075ff0859f5bd52c683f5b6408c63d1e46 Author: Olaf Meeuwissen Date: Sat Dec 17 17:03:32 2016 +0900 Update git repositor write access info commit 078435eaf19d00e6b863a7802073863604c9e9dc Author: Olaf Meeuwissen Date: Mon Sep 12 19:58:42 2016 +0900 Fix typo commit 755e829caa23b9781863e4b1e1d24c3cfee9e8bf Author: Dave Platt Date: Thu Dec 15 23:12:07 2016 -0800 avision.c: abort "wait for light" loop if interrupted Adds a "cancelled" flag to the Avision device structure, cleared in sane_start() and set in sane_cancel(). Test this flag in wait_4_light() and bail out of the 90-second "wait for the light to warm up" loop if the scan is cancelled. commit 28963459a4ac43100b8e377d65332d81a2660c0d Author: Dave Platt Date: Thu Dec 15 23:02:42 2016 -0800 avision.c: Recognize "backlight on" status Avision scanners can return an additional light-status value meaning "Transparent Media Adapter back-light is on". Accept this as equivalent to "on" during the lamp-warmup check prior to starting a scan. Re-check the light status after sending the window command, as the light selection might have been changed and a further warm-up may be required. commit 6585b6f60d07a196e42c99b935e2754bbc80b3c8 Author: Dave Platt Date: Thu Dec 15 22:29:16 2016 -0800 avision.c: Add "skip-adf" option The code which tries aggressively to reset/initialize HP 82xx/83xx Automatic Document Feeders doesn't work well if there's no ADF attached, because the scanner reports a non-zero ADF model type in this case. The retry code makes several attempts to initialize the ADF, and then bails out with an "Operation not supported" error. Add a new "option skip-adf" which will cause the backend to believe the "ADF not present" status if that's what the scanner reports. Fixes #313751 commit f58ce8f9201364bd0fe28ef736d4b1345f3f71b2 Author: Troy Rollo Date: Fri Dec 2 01:37:23 2016 +1100 HP3500: Always enable the second set of CCDs. This prevents ghosting that occurs when only enabling the first set of CCDs, even though at some resolutions we will not get any data from the second set. commit 77986b1d14db5ba285d595ab7630748b3c6d9284 Author: Troy Rollo Date: Fri Dec 2 01:20:43 2016 +1100 HP3500: Move to scan area more quickly if it is a long way from the home position commit b1f3815014f11bbadd74d255ee4343e16ffee6b8 Author: Troy Rollo Date: Tue Nov 29 21:11:06 2016 +1100 Add missing math library to HP3500 backend link flags commit fd7a3505f644573e832f417c7f0f62ca8ddeb7c8 Author: Troy Rollo Date: Tue Nov 29 20:47:59 2016 +1100 HP3500 backend: fix #314811, greatly improve calibration, support harware calibration in 120DPI and 400DPI, and add support for hardware gamma correction. commit 6484ff8fc368db24b567e1d2fbb44cd86e0f9e43 Author: Alex Belkin Date: Sun Nov 6 23:03:23 2016 +0300 Forgoten comma in backends man pages list. commit 69a008830b84437701022cbd96a8863ac61d3ddf Author: Alex Belkin Date: Sun Nov 6 22:28:03 2016 +0300 Pre-create temporary file for Jpeg scanning. Jpeg mode (as submitted by Samsung developer) uses temporary file with fixed name. This opens attacks on reading its content or overwriting any other user-writable file (with symlink). This change pre-creates temporary file with O_CREAT|O_EXCL and mode 0600. Assuming usual +t permissions for tmp this should mitigate issue. commit 226c2b9deb2f4f4b1d7c51ad4bb83d181e5e31b5 Author: Alex Belkin Date: Sun Nov 6 21:50:06 2016 +0300 Update header and copyright statements for xerox_mfp. commit 58c1e43b83712899162030d83df3ecac151d69d3 Author: Alex Belkin Date: Sun Nov 6 21:38:47 2016 +0300 Indent of xerox_mfp-tcp.c and xerox_mfp-usb.c This is purely indent commit without any code changes, in follow-up to 83bbcfe7d546b4d0cd28269b647fb558c6a1e00a. Indent command used: astyle -A8 -U -H -k3 -W3 -o xerox_mfp-{usb,tcp}.c Proof that code is not changed: git log -w -p xerox_mfp-{usb,tcp}.c commit 610533a9a66d7232a8a0ecd360871e3a6fa67980 Author: Alex Belkin Date: Sun Nov 6 21:24:38 2016 +0300 Update xerox_mfp man page. commit ba6a5710b508e73f4cb7152d034adc865f5201d7 Author: Alex Belkin Date: Sun Nov 6 21:00:58 2016 +0300 Update sane.man to index xerox_mfp backend. commit 83bbcfe7d546b4d0cd28269b647fb558c6a1e00a Author: Alex Belkin Date: Sun Nov 6 20:24:02 2016 +0300 Run indent: astyle -A8 -U -H -k3 -W3 -o xerox_mfp.[ch] This is purely indent commit w/o any code changes. To prove run `git diff -w`. commit e4aed53a1e46b9d46a76f814d414ef8d2c2276e3 Author: m. allan noah Date: Sat Oct 8 19:32:43 2016 -0400 fujitsu backend v132 - remove ipc_mode option and variables - set ipc mode based on other options - cleanup inverted logic DTC options - fixes threshold option reported in #315069 commit cfa98fd0d1271dd426ff2d6c565790d87cf3986d Author: Rolf Bensch Date: Sat Oct 8 14:25:33 2016 +0200 pixma: backend version 0.17.34 commit 7e20475c8b45249d05315d5a889551924210666d Author: Rolf Bensch Date: Sat Oct 8 14:24:53 2016 +0200 pixma: new scanner Canon PIXMA MG3000 Series see bug report #315521 commit 3b63fdab2b94f14765f8ba165546f6d69fc23ea9 Author: Rolf Bensch Date: Wed Oct 5 20:05:37 2016 +0200 pixma: backend version 0.17.33 commit c751a9ca22934ef93ca6b7afd3d0aaea4969c5fc Author: Rolf Bensch Date: Wed Oct 5 19:51:35 2016 +0200 fix ADF scanning for Canon MF57x0 devices - ignore result from calibrate(): don't interrupt @ PIXMA_STATUS_BUSY - MF57x0 devices don't require abort_session() after the last page - reported by Dmitry Deshevoy commit a9806de08ea65acb8a1109b480147a4a7ec76cb5 Author: Olaf Meeuwissen Date: Sun Sep 25 17:06:15 2016 +0900 AWARE: Treat compiler warnings as errors on debian-8-mini too! commit 490c4501c7ca59568bd9611665386c512163b51b Author: Olaf Meeuwissen Date: Sun Sep 25 17:04:23 2016 +0900 Sync autofoo commit da49686efe16bc5f7b4ddef18ea0dcb5f7c18d77 Author: Olaf Meeuwissen Date: Sun Sep 25 17:00:54 2016 +0900 sane-find-scanner: disable USB if not supported This fixes a [-Wpedantic] compiler warning about ISO C forbidding empty translation units. The check-usb-chip.c file reduces to such a file in the case USB support was explicitly disabled or no usable library found. commit 471e8ac0c1b565e5aea92f35ae173e167f3b61c7 Author: Olaf Meeuwissen Date: Sun Sep 25 16:28:11 2016 +0900 sanei_pp: fix [-Wcpp] compiler warning The `#warning` directive is turned into an error by `-Werror`. The directive triggers is guaranteed to trigger with __GNUC__ when no parallel support is available. This would prevent strict CI builds. Output a message with all compilers that understand the pragma. Those that don't should ignore it, according to C99. commit 7d7030a40986d97d3cf7a5313bf889bce4af8131 Author: Olaf Meeuwissen Date: Sun Sep 25 15:53:46 2016 +0900 sanei_usb: : fix [-Wunused-parameter] compiler warnings These were issued in the absence of libusb. commit e6faafcdc94e253f7f4fe793fec6110ce37e8014 Author: Olaf Meeuwissen Date: Sun Sep 25 15:44:36 2016 +0900 xerox_mfp: fix [-Wunused-parameter] compiler warnings These are issued when libjpeg was not found during configuration. commit 32be261254a78d1f314b3ee86fd5e5b40ab91a86 Merge: ec8bf64 97d2a3d Author: Louis Lagendijk Date: Wed Sep 21 22:35:10 2016 +0200 Merge branch 'master' of ssh://git.debian.org/git/sane/sane-backends commit 97d2a3d22d9c6a6d0a277de0066c73e9059abd92 Author: Olaf Meeuwissen Date: Wed Sep 21 22:11:09 2016 +0900 AWARE: Treat compiler warnings as errors on debian-8-full This build became compiler warning free in ee550e5d. Let's keep it that way! commit 4119f05d5f400803a9c952896125e9feabb07393 Author: Olaf Meeuwissen Date: Wed Sep 21 21:54:39 2016 +0900 Fix USB ID typo commit ee550e5de8e636642b9895d54f6740aa38ee6ff8 Author: Olaf Meeuwissen Date: Mon Sep 19 12:52:31 2016 +0900 pieusb: fix [-Wunused-parameter] compiler warnings The functions that trigger these warnings were not used. commit bf088a6ed15733237df446a84d6659c4e0145c9a Author: Olaf Meeuwissen Date: Mon Sep 19 17:45:35 2016 +0900 Merge comments This gets rid of a missing :usbid warning. commit e01f574b19be74081650e9be9bcb16a3420068ef Author: Olaf Meeuwissen Date: Mon Sep 19 17:44:48 2016 +0900 Merge duplicate entry commit 1a328e412fb7bf3872de20fe6e57b00ab913a75d Author: Olaf Meeuwissen Date: Mon Sep 19 15:26:14 2016 +0900 Add missing USB IDs Taken from http://www.linux-usb.org/usb.ids commit dd940a1f612f56d2acb929afd54614ebc6dfb309 Author: Olaf Meeuwissen Date: Sat Sep 17 20:43:44 2016 +0900 utsushi.desc: sync with upstream commit fb0464d9e3e39a93306e98602ff879c43276de5c Author: Olaf Meeuwissen Date: Mon Sep 12 20:12:28 2016 +0900 niash: fix [-Wunused-but-set-variable] compiler warning This makes explicit what the compiler has effectively been doing all along anyway since at least 727dd4ab (2004-08-03). commit 6f4b88b6173745f09e4ce1fa465db534eca85751 Author: Olaf Meeuwissen Date: Mon Sep 12 20:05:42 2016 +0900 epson2: fix [-Wunused-but-set-variable] compiler warning This makes explicit what the compiler has effectively been doing all along anyway since at least 728e032a (2009-06-01). commit 4dce101c05515200a6cd337451da664c1978f115 Author: Olaf Meeuwissen Date: Mon Sep 19 10:04:35 2016 +0900 Keep generated *.eps and *.pdf files out of the repository commit 46bc0ff1c89a6759fd22f80fd1ceb9551268da4f Author: Olaf Meeuwissen Date: Sun Sep 18 21:41:03 2016 +0900 Sync autofoo commit 2b973d75fed73771664958ea6cb5b4b8fd7b1307 Author: Olaf Meeuwissen Date: Sun Sep 18 21:21:35 2016 +0900 Add fig2dev as prerequisite for API HTML docs The target for sane-html depends on sane.dvi which requires fig2dev. Thanks to: - https://lists.debian.org/debian-user/2016/08/msg00484.html - http://superuser.com/questions/1101439/error-building-sane-backend-on-debian commit db22a031d130d533f5fd41710ddabdc61280d313 Author: Olaf Meeuwissen Date: Sun Sep 18 21:19:12 2016 +0900 Fix typo introduced in fa41b180. Fixes 315435 commit 9d388c35937b75cf5f47410ead07ef2226ac8005 Author: m. allan noah Date: Sun Sep 11 19:03:23 2016 -0400 canon_dr v56 - add initial support for P-150M (and probably P-150) commit 39ceeae616a2e1638c2760d4364adcaa210a413b Author: Olaf Meeuwissen Date: Wed Sep 7 21:03:30 2016 +0900 md5: fix [-Wstrict-aliasing] compiler warnings commit 27a4da41b1761acba33e99aab4d782e726934c04 Author: Olaf Meeuwissen Date: Wed Sep 7 21:01:26 2016 +0900 Prefer *our* `include/` files This fixes discrepancies in build results for VPATH builds. commit 737977199ccd2419a51e120c472981b1a1263ab0 Author: Olaf Meeuwissen Date: Mon Sep 5 23:40:39 2016 +0900 umax_pp: fix [-Wunused-but-set-variable] compiler warning commit 50fa8efdcff0dd159d3ff51e219a3c08020ca54c Author: Olaf Meeuwissen Date: Sun Sep 4 14:39:52 2016 +0900 gphoto2: fix libgphoto2 logging integration In libgphoto2-2.5.0 (tagged for release on 2012-07-10) the GPLogFunc no longer takes a va_list. Instead, it passes a formatted message. commit 23f052113b5567033da0d9c4679451d97c484220 Author: Olaf Meeuwissen Date: Sun Sep 4 12:50:19 2016 +0900 saned: fix [-Wunused-parameter] compiler warning The `__sane_unused__` attribute has been moved from sanei_backend.h to sanei.h to make it generally useful instead of limited to backends. commit 0d527f6659e06175d855aaa1a70fc2be52aad1a7 Author: Olaf Meeuwissen Date: Sun Sep 4 12:13:16 2016 +0900 Drop build environments Adding them did not quite have the effect I thought it would. I had thought it would allow for easy linking to build logs by environment name. Alas, no such luck. This reverts commits: - 9c44317289f1be0a72089ffd030be84caf75b58c - 6209fecf3a11e90e2e5efc057cf650f4ab792b50 commit 74b4a34e82124621616c699ac0d5ba0d5e93b6a1 Author: Olaf Meeuwissen Date: Sun Sep 4 12:12:14 2016 +0900 dll: fix pedantic compiler warning commit 246673715d9abdbfbea349de4636322b242f9700 Author: Olaf Meeuwissen Date: Sat Sep 3 14:36:49 2016 +0900 utsushi.desc: sync with upstream commit a65e74fe83ae96d5d00af6a05c751086cdae8d38 Author: Olaf Meeuwissen Date: Sun Aug 28 15:49:44 2016 +0900 umax_pp: fix [-Werror=unused-but-set-parameter] compiler warnings commit 4eaefe43713036f73ab322e8d6b519589055540d Author: Olaf Meeuwissen Date: Sun Aug 28 15:27:50 2016 +0900 magicolor: fix [-Werror] compiler warning This casts away const-ness in the hope that libsnmp doesn't change the session.peername. commit 31ac0db73672347732dc80cf8f2afe8e6f3d466b Author: Olaf Meeuwissen Date: Sun Aug 28 15:25:43 2016 +0900 magicolor: fix [-Werror=pointer-sign] compiler warnings The libsnmp API requires a u_char *session.community :-( commit c32d48ef5fd4a47a93933e6ffba5c8a93d26e43f Author: Olaf Meeuwissen Date: Sun Aug 28 14:18:48 2016 +0900 kodakaio: fix [-Weror=format=] compiler warning commit 0337514b8f0e484c11b668d8ca0e0af998d3dfbc Author: Olaf Meeuwissen Date: Sun Aug 28 14:18:00 2016 +0900 kodakaio: fix [-Werror=sign-compare] compiler warning commit 763816814bc072b19f1178e0d92031217d7f5f06 Author: Olaf Meeuwissen Date: Sun Aug 28 13:55:30 2016 +0900 hp5400: fix [-Werror=overflow] compiler warning This explicitly implements what gcc and clang assign. commit 9c44317289f1be0a72089ffd030be84caf75b58c Author: Olaf Meeuwissen Date: Sun Aug 28 13:24:17 2016 +0900 Fix environment name (periods are not allowed) commit 984fefd55173f30f4cde3ed7acb462d660c676eb Author: Olaf Meeuwissen Date: Sun Aug 28 13:21:11 2016 +0900 plustek_pp: fix [-Werror=sign-compare] compiler warning commit f0153bc7fe7fd79ef2b1b41d259adf3d20b9d641 Author: Olaf Meeuwissen Date: Sun Aug 28 12:57:17 2016 +0900 v4l: fix [-Werror=sign-compare] compiler warning commit 6209fecf3a11e90e2e5efc057cf650f4ab792b50 Author: Olaf Meeuwissen Date: Sun Aug 28 12:17:46 2016 +0900 Make referencing builds easier commit 235de98784897edb63d1ed1a32609b7786d799d0 Author: Olaf Meeuwissen Date: Sun Aug 28 11:58:16 2016 +0900 md5: fix [-Wpointer-arith] compiler warnings This reverts commits 9aecb00947e6bf7ef1cf412aff2ab41202617b30 and cdad5961f3888f0a3c0c525d0efab33174c11a24 which fixed a different compiler warning that seems to have disappeared (at least on the debian-8-full builds). commit bf53c714348dbf4654de887ae7e649fbad6b2288 Author: Olaf Meeuwissen Date: Thu Aug 4 22:47:01 2016 +0900 Sync with upstream commit ffd93a9fad10ced31de037f2c6180f328a38b547 Author: Olaf Meeuwissen Date: Wed Aug 3 22:43:06 2016 +0900 Sync autofoo commit cb3090cb5472b63d5cdfb5110652f568bd9477ad Author: Olaf Meeuwissen Date: Wed Aug 3 22:16:26 2016 +0900 pixma: Fix include guard typo This was introduced in f573865 on 2008-10-18. commit 23cc2e1ba043ea8309923f5f1dcc5acaeee38a95 Author: Olaf Meeuwissen Date: Wed Aug 3 22:08:49 2016 +0900 Fix include guard typo This seems to have been present since the beginning of sanei/sanei_scsi.c. commit 63b55e2b591ba977a285a4c91fde0118c25246e7 Author: Olaf Meeuwissen Date: Wed Aug 3 22:05:03 2016 +0900 Drop check for sys/bitypes.h It was obsoleted in 70f3fdf on 2009-02-26. commit d263f25911a0b359b7edec0faa9320d5d13928da Author: Olaf Meeuwissen Date: Wed Aug 3 21:48:54 2016 +0900 Fix typo Appears to have been introduced in 0330a4d on 2009-02-02. There is no evidence that a scdds.h file has ever existed. commit 970464f7332a1995bfd825de285425f0c957b1da Author: Olaf Meeuwissen Date: Wed Aug 3 20:53:06 2016 +0900 Drop unused CPP define The last reference to it was removed in 5dcf165 on 2007-06-21. commit 5389808029f0f81d204630f6e78abe11dfd61122 Author: Olaf Meeuwissen Date: Tue Aug 2 21:56:09 2016 +0900 Fix memory leak commit 1006445982877970d376c0f657e04fc1481e2459 Author: Olaf Meeuwissen Date: Tue Aug 2 21:38:43 2016 +0900 Use DIR_SEP instead of hard-coding ":" Fixes 313540 commit b021c3bee8e9edc7854050a3975cef003586b2e5 Author: Troy Rollo Date: Sun Jul 31 22:47:25 2016 +1000 Fix bug 314571 - hp3500 backend does not set correct size for string option. commit 1859803563f8baadeb6c0926610b2f782350d1e4 Author: Olaf Meeuwissen Date: Wed Jul 27 21:17:08 2016 +0900 Add a Fedora 24 Clang builder commit f6c8be1380c2f12080cdbd7a81eb2d5156eaa154 Author: Olaf Meeuwissen Date: Mon Jul 18 20:55:14 2016 +0900 kvs40xx: fix [-Wunused-function] compiler warning This rather unceremoniously removed the function. Note that a near copy can be found in the kvs20xx backend code. commit effc26e4028f2d21a5bd9fec0458a78c0f6dc330 Author: Olaf Meeuwissen Date: Mon Jul 18 20:53:51 2016 +0900 kvs20xx: fix [-Wunused-function] compiler warning This rather unceremoniously removed the function. Note that a near copy can be found in the kvs40xx backend code. commit 2d468852288b5d80e9e8b6831467081fe3ec874e Author: Olaf Meeuwissen Date: Mon Jul 18 17:32:21 2016 +0900 pnm: fix [-Wformat=] compiler warning commit 2f39c7227021e85b8fdde8161358858797bd7461 Author: Olaf Meeuwissen Date: Mon Jul 18 17:11:26 2016 +0900 v4l: fix [Wunused-parameter] compiler warnings commit 880992739020eee8cc0e005e6bdf853f2ff3572f Author: Olaf Meeuwissen Date: Mon Jul 18 17:10:56 2016 +0900 sm3600: fix [-Wunused-parameter] compiler warning commit 99c14f2d9503cd9a6c77d71d590e434e504052c6 Author: Olaf Meeuwissen Date: Mon Jul 18 16:51:08 2016 +0900 Use a single symbol to flag unused parameters The __sane_unused__ symbol was used slightly more often then UNUSEDARG and, more importantly, defined in include/sane/sanei_backend.h. That makes it readily available to virtually all backends. commit b73a6e5017f6d4d2d0ef7a61bf6e2113f848be94 Author: Olaf Meeuwissen Date: Mon Jul 18 16:14:20 2016 +0900 niash: fix [-Wunused-parameter] compiler warning The attribute needs to go before the pointer designation for it to have any effect. commit 61719e0a131a6f0d4bf53aa98ecf510ce7081ca7 Author: Olaf Meeuwissen Date: Mon Jul 18 16:11:39 2016 +0900 dc240: fix [-Wunused-parameter] compiler warning The attribute needs to go before the pointer designation for it to have any effect. commit ef8e258165526175c9ac2d262448f16b551d19e9 Author: Olaf Meeuwissen Date: Thu Jul 14 21:12:38 2016 +0900 Sync autofoo commit 57350969f6f46195c5fd5e255b3d1906df401d19 Author: Olaf Meeuwissen Date: Thu Jul 14 20:51:42 2016 +0900 sane.tex: mark up email as a URL commit 707baa0d160ff13331bed6063d2502b09f902f38 Author: Olaf Meeuwissen Date: Thu Jul 14 20:50:14 2016 +0900 doc/sane.tex: drop html.sty in favour of url.sty The latter is part of the core TeX Live distribution which is readily available on all major operating systems. commit bfd1626c4b119404429a847aaa92df77ca3fbb40 Author: Olaf Meeuwissen Date: Wed Jul 13 23:44:26 2016 +0900 Sync autofoo commit 8598f81d0b9542b6f4928b8b870a26b50f440379 Author: Olaf Meeuwissen Date: Wed Jul 13 23:43:35 2016 +0900 Fix figure orientation commit 00bc3e9b451f8dfb89553305cce89172be520bb1 Author: Olaf Meeuwissen Date: Wed Jul 13 23:40:19 2016 +0900 Generate EPS figures too It's good to know how this is done so that we can modify any original figure if need be. commit cc8f99b900d5ae44248677f6881f1b74d7885bfb Author: Olaf Meeuwissen Date: Wed Jul 13 23:24:29 2016 +0900 Generate PDF figures explicitly with fig2dev This utility has less dependencies and supports conversion to a pile of other formats that may come in handy as well. Clean up of generated PDF figures has been moved to the clean target as well. commit d7e1995d001b0d16b9920e751be923f6a8393bf1 Author: Olaf Meeuwissen Date: Wed Jul 13 22:37:44 2016 +0900 doc/sane.tex: Replace epsfig with graphicx The graphicx package allows for file specification without a hardcoded extension. This provides more freedom in chosing how to prepare images in *.eps and *.pdf formats. Moreover, epsfig is considered mostly obsolete in the TeX community and graphicx is the "current 'preferred' solution" to embed figures. See https://www.ctan.org/pkg/epsfig. commit 0aab12b934a9f9620fb1236e13dd2b71a7426000 Author: Olaf Meeuwissen Date: Mon Jul 11 20:41:54 2016 +0900 Bump standard minor version This is to acknowledge the SANE_STATUS_GOOD fixes in net.tex that were committed in 4daf488 and 1100883. commit 1ed3b9fa86e6bc6875a72a9b347164a5879ffe8b Author: Olaf Meeuwissen Date: Mon Jul 11 20:37:08 2016 +0900 Reclassify doc/html.sty It is a package used by doc/sane.tex. commit 2481e1e98b02e927cdb9c2e6e404252ef9e49041 Author: Olaf Meeuwissen Date: Sun Jul 10 15:43:42 2016 +0900 Sync autofoo commit fa41b18001f74e8941813709f15a15cc9ea299e1 Author: Olaf Meeuwissen Date: Sun Jul 10 20:35:04 2016 +0900 Refactor API spec conversion support Unless explicitly asked to do without, all formats for which required tools are found will be built. Checks cover PostScript, PDF and HTML. All logic and files involved are now collected in a single "section" and grouped in such a way that their function should be clearer. fixup! Refactor API spec conversion support commit d7c69d141ffb4f456d659b443aa4c3d3be82793e Author: Olaf Meeuwissen Date: Sun Jul 10 19:40:04 2016 +0900 Add test for the TeX to HTML converter commit fe2fbe06e1b7db42ea2578e8d853cf83d7bb72a9 Author: Olaf Meeuwissen Date: Sun Jul 10 19:29:55 2016 +0900 Refactor TEXINPUTS handling commit f322cbc7f950b087e969ac115a5b4e14735881e4 Author: Olaf Meeuwissen Date: Sun Jul 10 15:41:08 2016 +0900 Add support for PDF API spec output Note that pdflatex internally uses epstopdf which in turn requires a working ghostscript. commit 5a73fb24d1e7a5dcdd287ce7654050b1703cc9c6 Author: Olaf Meeuwissen Date: Sun Jul 10 14:48:43 2016 +0900 Be quiet but do not hide errors commit e0fd693bb170813f95241898a53ba3f9c261c22a Author: Olaf Meeuwissen Date: Sun Jul 10 13:32:22 2016 +0900 Fix API spec generation for VPATH builds commit cb04102a20bc5b1e9cbb990805de3586a0a940c0 Author: Olaf Meeuwissen Date: Sat Jul 9 15:10:00 2016 +0900 Add GitLab CI musl build job commit be7af6835741c18ea93babd421c083c377b1f88d Author: Ruslan Nabioullin Date: Sat Oct 29 20:27:47 2011 -0400 Fixed scanning status messages. Fixes 313411 commit d62d0a2e452e9ed1ae74cc20c01488543cda8ef9 Author: Olaf Meeuwissen Date: Wed Jul 6 20:23:12 2016 +0900 check-po.awk: fix awk invocation The awk utility has been moved to /usr/bin and the script relies on features present in gawk but not in mawk. commit ddbdfd6206e30e513509720dd5137c26c9efc248 Author: Olaf Meeuwissen Date: Sun Jul 3 21:11:04 2016 +0900 Fix configure time test commit c17821e3609080309bcb8a3173cb071e1493a62c Author: Olaf Meeuwissen Date: Sat Jul 2 19:23:01 2016 +0900 Fix configure time warning during CI build commit c96236862635f74d8a1c01654430d93bed83f756 Author: Olaf Meeuwissen Date: Fri Jul 1 23:45:43 2016 +0900 Sync autofoo commit a9c813944e9aa0ceb6c153d06dff286ba855b90e Author: Olaf Meeuwissen Date: Fri Jul 1 23:37:49 2016 +0900 Make libusb-1.0 the default for USB support When libusb-1.0 is not found, libusb-0.1 will be tried. On BeOS and OS2, nothing should have changed in terms of detection of USB support. On all systems the --enable-libusb* flags are now ignored. Instead, the --with-usb and --without-usb flags now control support. When neither is given USB support will be enable if possible and disabled otherwise. If --with-usb is requested but not possible, ./configure will fail. There is no support to prefer libusb-0.1 over libusb-1.0. commit 418fbb987d731ed2468f48a6fb162f47ea7da55e Author: Olaf Meeuwissen Date: Thu Jun 30 21:50:33 2016 +0900 Sync autofoo, once again ... commit 602182931dceeedddcc6be3b144cbc1423bd9b4a Author: Olaf Meeuwissen Date: Thu Jun 30 21:49:25 2016 +0900 Improve test shell builtin invocation portability Looks like I missed this when committing 309a8140. commit 828cd013e9a4411158af8816a63b133b6da19ed5 Author: Olaf Meeuwissen Date: Thu Jun 30 21:38:04 2016 +0900 Compile getopt replacement functions only if needed This ought to get rid of the last empty compilation unit warnings. This merges libfelib.la with liblib.la. The former was always used together with the latter. The latter was only ever used without the former when linking backends and tools. Tools might want to use the getopt functions, backends might just want to use MD5. commit 89dc05006ec93e8fd8a103504701db720814669a Author: Olaf Meeuwissen Date: Wed Jun 29 22:21:10 2016 +0900 Sync autofoo Looks like the sorting of the DIST_COMMON file list is not stable. commit a298bfe5a8c65236ac13130e891a93bf3cf58976 Author: Olaf Meeuwissen Date: Wed Jun 29 22:20:51 2016 +0900 Fix AS_IF condition commit f03f1f66d4a7704c20d221897665509d7f1a626a Author: Olaf Meeuwissen Date: Wed Jun 29 22:15:06 2016 +0900 Sync autofoo files commit 1c946f7c194869966f6d3af9df499184d3035c20 Author: Olaf Meeuwissen Date: Tue Jun 28 22:42:09 2016 +0900 Compile replacement functions only if needed This ought to get rid of most empty compilation warnings. commit 0c2b86ac0b56ee7cb8b962102c54855f05887b08 Author: Olaf Meeuwissen Date: Mon Jun 27 22:33:28 2016 +0900 Fix distcheck issues in tools/ Automake is smart enough these days to compile the *.lo files that are used when linking. The umax_pp_CPPFLAGS are useless because backend/umax_pp_low.c undefines BACKEND_NAME unconditionally and sets it to what was passed here ;-) commit 81f9557966ad335a76deff57a112607d9813ba7a Author: Olaf Meeuwissen Date: Mon Jun 27 22:08:20 2016 +0900 Clean up .gitignore file content Removes empty lines and duplicates (note that .gitignore patterns are recursive unless anchored with a leading /). commit 61f3fec68e14944be7ecf219ec604e599141cbdf Author: Olaf Meeuwissen Date: Mon Jun 27 22:05:50 2016 +0900 Remove references to SANE CVS The references in in-file changelogs and the ChangeLog files have not been modified. Only those references that refer to current practices or locations. commit c23791cbd71d58b2627cfc65bbf2cb20aeb51bba Author: Olaf Meeuwissen Date: Mon Jun 27 21:51:43 2016 +0900 Sync AUTHORS content with current status We've been using git for a while ;-). Also updates the write access info and fixes encoding issues. commit cb4924f210bf758558b583220a14ed5a62f178dc Author: Olaf Meeuwissen Date: Sun Jun 26 10:22:35 2016 +0900 Stop distclean from removing files willy-nilly The distclean target should only remove files that make creates. If there are any that need taking care of, they should be added in on a per file basis in the Makefile.am that creates it. commit 0065aaa1c8cb823d20b1e0ff32b3f6197e73db3f Author: Olaf Meeuwissen Date: Sun Jun 26 10:11:42 2016 +0900 Remove overly zealous ignore patterns Text editor backup and temporary files like *~ are a per developer issue, add them to your global .gitignore. Other dot-files should be ignored on a case-by-case basis. commit 8274a52eec3c20becf9901acaab4837b6b61c2f7 Author: Olaf Meeuwissen Date: Sun Jun 26 10:07:26 2016 +0900 Sort .gitignore files commit b25ef62c2bb163fffea56000ef25544a236d2096 Author: Olaf Meeuwissen Date: Sun Jun 26 10:05:12 2016 +0900 Fix sorting of ignore files We haven't been using CVS since ... 2009-05-04 :-| commit 0bc7b6aed7e3ac8ee78190f0e795ce9c62c3f36e Author: Olaf Meeuwissen Date: Sun Jun 26 09:16:54 2016 +0900 Sync *.po files with previous changes This changes the file/line references in all files (and picks up any new messages as a side effect). commit bdade6bb07a0ec27e3930c0b3b86c28a5c2a5bd9 Author: Olaf Meeuwissen Date: Sun Jun 26 09:15:24 2016 +0900 Sync derived files with previous changes commit ec4fe7ec7200a881feba5b539256dc58ae1edbaf Author: Olaf Meeuwissen Date: Sun Jun 26 08:50:04 2016 +0900 Prefer gettext's --disable-nls option commit c676acbe472f2a57763d0ce198e50b048d37bbda Author: Olaf Meeuwissen Date: Sun Jun 26 08:49:14 2016 +0900 Switch to using the gettext build machinery This adds two automatically maintained English variants that handle quote substitution in onrder to provide smart quotes. commit 0286bf46fc2992dfd2e9539fb939c243db13e91f Author: Olaf Meeuwissen Date: Sun Jun 26 08:30:45 2016 +0900 Add gettext build machinery files for I18N/L10N support These are courtesy of autopoint and target gettext-0.18.1 because that is the version in Debian 7 (which is what Alioth is running). The one warning this produces on autoreconf is fixed in gettext-0.18.2, BTW. commit eecee6d1014537cabe427d44168fce9ac9894301 Author: Olaf Meeuwissen Date: Sat Jun 25 15:23:05 2016 +0900 Fix VPATH build issue The source *.po files weren't found when you configured outside of the top source directory. commit 00984cd1119bb9bb5b794bfc0f1ef77369978d68 Author: Yurii Kolesnykov Date: Sat Jun 25 03:34:12 2016 +0300 Fix compilation of saned.c under OS X commit ad176ba9fe1f7608d8ad8032407cf1f7dc66dad6 Author: Alessandro Zummo Date: Tue Jun 21 00:50:02 2016 +0200 epsonds: remove unused var commit 1dbabdce5d34e686608bb997245c49a823e19fb5 Author: Alessandro Zummo Date: Tue Jun 21 00:49:08 2016 +0200 epsonds: fix compilation commit 9b389a61c5e698e8bffb186bdbc005739128b427 Author: Alessandro Zummo Date: Tue Jun 21 00:43:39 2016 +0200 epsonds: added support for network scanners commit f13ca02b86a4d27951149723ca2ae81491991c18 Author: Olaf Meeuwissen Date: Mon Jun 20 21:42:56 2016 +0900 Fix variable name typo and other typographic nit-picks commit e7100e275d58d67b903e883e7a02e45d18f81ef7 Author: Olaf Meeuwissen Date: Wed Jun 15 20:47:28 2016 +0900 Update documentation to reflect recent changes commit 5695d01077c7e575808a37a66df37d1f9fafa637 Author: Olaf Meeuwissen Date: Wed Jun 15 20:23:33 2016 +0900 Silence overly verbose targets This only takes effect with silent rules enabled. commit 43cdc1056af899520797b09f3f78ba64703ed74d Author: Olaf Meeuwissen Date: Wed Jun 15 20:18:25 2016 +0900 Do not duplicate Warning on output commit 40bfec7a6b4a804201bad7f0517f16b0c6ae4110 Author: Olaf Meeuwissen Date: Wed Jun 15 20:17:29 2016 +0900 GitLab-CI: fix configure option commit f75e271853f40c6cb00ce59cbb4e9d62d083a1b2 Author: Olaf Meeuwissen Date: Tue Jun 14 21:24:53 2016 +0900 Tweak GitLab CI builds The idea is to build as much as possible for the *-full flavour build, make compiler warnings stand out and muddle on after errors so that we get all the problems in a single log. commit ef7deff36c759efa8d371251febef6d37d4eb94b Author: Olaf Meeuwissen Date: Tue Jun 14 21:20:48 2016 +0900 Add missing autofoo file This should have gone in with d853463e. commit d853463ef1b97082d657a0be32d1b27a04940ea2 Author: Olaf Meeuwissen Date: Tue Jun 14 06:30:48 2016 +0900 Sync derived files This was done with AUTOMAKE="automake --add-missing --copy" autoreconf --force on Debian GNU/Linux 8.5. commit 17d78ab7c326069c3a596f17ded6418ef42930bc Author: Olaf Meeuwissen Date: Fri Feb 12 21:09:32 2016 +0900 Fix warnings of "newer" automake versions commit a7376ffa6dd1796c1678b33bd03bf19766e227de Author: Olaf Meeuwissen Date: Fri Feb 12 20:52:57 2016 +0900 Fix libtoolize warning commit 7675cb7c3eb5b6e97fb87adc464b6bcc67cfd7dd Author: Olaf Meeuwissen Date: Thu Feb 11 17:43:14 2016 +0900 Drop Makefile.in from EXTRA_DIST Automake is smart enough to include this on its own. commit 7bfa818c57485310994650528124a7036894eb36 Author: Olaf Meeuwissen Date: Thu Jan 14 21:22:00 2016 +0900 Set up compiler and linker early and in one place commit f80cf1dbbdd85f2a0b595aef83cc63faa0c91c04 Author: Olaf Meeuwissen Date: Thu Jan 14 20:21:49 2016 +0900 Remove unused SANE_LINKER_RPATH macro commit e4ad1f58f31ec7110df716494b13cf96156b6a7c Author: Olaf Meeuwissen Date: Thu Jan 14 18:50:47 2016 +0900 Enable ISO C99 support for more compilers commit 444b572d1a559d93a6ad172f86bdcc9197377e75 Author: Olaf Meeuwissen Date: Sat Jan 9 18:43:36 2016 +0900 Use autoconf provided --docdir commit f1f4180e5b6f71bf3a674bbfcbf7932b401d7a96 Author: Olaf Meeuwissen Date: Sat Jan 9 18:24:20 2016 +0900 Collect autoconf bits in one place commit 35f1936aeba18b34628d35938529e0d2af0e58c7 Author: Olaf Meeuwissen Date: Sat Jan 9 18:11:53 2016 +0900 Determine version bits and release programmatically commit 16497dc13838e14784778883fb2837fbcf9e288e Author: Olaf Meeuwissen Date: Sat Jan 9 17:59:20 2016 +0900 Replace convenience variable by its expansion commit 9a52b5bc27c2a50e14161b4dcaba43f825cf91a4 Author: Olaf Meeuwissen Date: Sat Jan 9 17:48:27 2016 +0900 Fix variable name typo commit 79c623628a28b6c28321cad6518bf98cf7a705a4 Author: Olaf Meeuwissen Date: Sat Jan 9 17:48:03 2016 +0900 Fix new automake warnings commit 97fed76717367289a8e160dab4341d79586c1079 Author: Olaf Meeuwissen Date: Sat Jan 9 17:22:31 2016 +0900 Replace obsolescent macro with LT_INIT option commit c868a2e8d48e3c31051b6a8978c9b1df494bc36b Author: Olaf Meeuwissen Date: Sat Jan 9 17:22:07 2016 +0900 Remove commented out code commit 4894b1513d829957e109e5c49b812dc688fe78b3 Author: Olaf Meeuwissen Date: Sat Jan 9 17:11:19 2016 +0900 Drop a pile of unnecessary macro invocations These are already taken care of by other macros. commit ae89c8f98362a4e50d4b1a0ce8f3586b77a81989 Author: Olaf Meeuwissen Date: Sat Jan 9 15:59:35 2016 +0900 Update to automake-1.11.6 This turns on additional warnings and adds support for silent make rules (so compiler warning really stand out ;-). commit 87e12bbf2e4312bf0bd18656afe579919c8788e1 Author: Olaf Meeuwissen Date: Mon Jun 13 22:24:21 2016 +0900 Sync derived files with autoreconf --force For the record, this was done on Debian GNU/Linux 8.5. commit 309a8140e7285f87d5fc5ee24b942f1713e80be8 Author: Olaf Meeuwissen Date: Wed Oct 28 21:59:42 2015 +0900 Improve test shell builtin invocation portability POSIX 2008 obsoletes the -a and -o operands (according to the autoconf documentation). commit d9e2f441139c0514c3d388976d1f8fc78a04de95 Author: Olaf Meeuwissen Date: Wed Oct 28 20:59:22 2015 +0900 Double quote code passed to AC_LANG_PROGRAM Upon re-reading the autoconf documentation, this seemed the right thing to do. The AC_LANG_PROGRAM macro does not quote its arguments so any occurence of [ and ] will get stripped out if not double quoted. Current code snippets passed do not use them but it is better to use a consistent quoting approach for such snippets. In other places in the configure.ac file double quoting is used already. commit d3d5dc3da04cce842f7fa8d941676f2f5abc3bbd Author: Olaf Meeuwissen Date: Thu Oct 22 22:18:19 2015 +0900 Update to autoconf-2.69 This gets rid of a number of obsoleted macros and replaces RETSIGTYPE with a void literal which can be assumed for C89 and later. This changeset was prepared using autoupdate and modified to get rid of whitespace and doubled [] changes. Changes to acinclude.m4 were added by hand. commit 2d6fad58b4c61d59bec3879dab9ccf0c1b88dd11 Author: Olaf Meeuwissen Date: Thu Oct 22 20:15:45 2015 +0900 Respect GNU Standards user variables Several variables are considered "user variables" by the GNU Standards. This means that the user can pass these to their ./configure and make invocations as they see fit. These variables include CPPFLAGS, CFLAGS and LDFLAGS. This changeset pushes our use of these variables to the automake shadow variables, AM_CPPFLAGS, AM_CFLAGS and AM_LDFLAGS, so that user variables will no longer clobber flags required in order to build. commit 7a2b112d20e08337528128745bf7cc1d6096a1d8 Author: Olaf Meeuwissen Date: Wed Oct 21 22:33:53 2015 +0900 Prefer make variables over literal substitutions The AC_SUBST and PKG_CHECK_MODULE invocations in configure.ac as well as acinclude.m4 are sufficient to trigger automake to insert initialization logic for the variables these introduce. There is no need to do this by hand. Wherever these values are needed, it is better to use a variable. This allows for one-off overrides on the make command-line (without the need to run ./configure) for one thing. commit 2745528b60617d737a7a597c4ee5397359a6ddfd Author: Olaf Meeuwissen Date: Mon Oct 19 21:52:47 2015 +0900 Fix non-POSIX automake file variable warning This addresses warnings about the use of the $(wildcard) function. It has been replaced by a plain shell glob. There is one case where this will result in an error, when there are no matches, but that is when the targets that use it make no sense. It is probably good to get an error in that case. commit d81836bd2332e42136a15a72961c0b9295d94b58 Author: Olaf Meeuwissen Date: Mon Oct 19 21:04:53 2015 +0900 Add automake subdir-objects option This addresses autoreconf output such as: tools/Makefile.am:37: warning: source file '../backend/sane_strstatus.c' is in a subdirectory, tools/Makefile.am:37: but option 'subdir-objects' is disabled The option was introduced in automake version 1.9 and is slated for unconditional activation with automake-2.0. commit d38a098ec6fce0aa18dd757677c5a07ff1a44163 Author: Olaf Meeuwissen Date: Mon Oct 19 20:20:56 2015 +0900 Rename configure.in to configure.ac This name has been preferred since autoconf-2.52 and automake-1.5. Both were released in the summer of 2001. Support for configure.in is slated for removal in automake-2.0. The configure.ac file itself requires autoconf-2.54 or later (and does not care about the automake version). commit c9027378a12a6f67b22ee5fe203df1739486e3ad Author: Olaf Meeuwissen Date: Mon Jun 13 20:35:34 2016 +0900 xerox_mpf: Make JPEG support an option commit 359bb9c3d48c87324b2ead602de76e0e35daadba Author: Olaf Meeuwissen Date: Sun Jun 12 20:32:30 2016 +0900 Add CI support to test selected build scenarios commit 5ba37467e88ca8052973b37128ce8fd36ad5d61d Author: m. allan noah Date: Thu Jun 9 21:51:18 2016 -0400 fujitsu backend v131 - hide compression-arg option when jpeg disabled - add Send/SC/GHS macros for recent scanners - add initial support for fi-74x0 - add initial support for fi-7030 - set has_MS_lamp=0 for fi-71x0 - add I18N macros to all option titles and descriptions - add usb ids for many newer scanners commit ec8bf64396b394c4d483b811f9948871f12882b4 Merge: 1d2a40e 1e01365 Author: Louis Lagendijk Date: Sat May 21 22:06:57 2016 +0200 Merge branch 'master' of ssh://git.debian.org/git/sane/sane-backends commit 1e013654cc3af09f4731ab9ec8d8324d03a7de4a Author: Alessandro Zummo Date: Mon May 9 11:10:35 2016 +0200 pieusb: mkostemp -> mkstemp commit 926bfade544de4a4fd5f1a8082b85a97e2443770 Author: Alex Belkin Date: Sat May 7 22:33:03 2016 +0300 Color scanning for Samsung models, which support JPEG Lossy compression. Patch is submitted by Laxmeesh Onkar Markod Patch to code is applied almost verbatim, except, insignificant formatting fixes and making new functions static. Also, new USB ids added and scanner support is changed as reported. commit 1d2a40ec96aea0ba183415efea570301159d4159 Author: Louis Lagendijk Date: Sat Apr 30 15:32:55 2016 +0200 pixma_mp150.c: fix parameter settings for MB5000 in send_scan_param commit 28dcd0aef4ac91b87527c17c8aa89e879f39f20d Author: Louis Lagendijk Date: Wed Apr 27 18:45:22 2016 +0200 pixma_mp150.c: replace multiple if statements with case statement in handle_interrupt commit eb712c6bd8ca6a42a1d3941583fa18b9981b8712 Author: Louis Lagendijk Date: Wed Apr 27 17:55:52 2016 +0200 pixma_mp150.c: scan param 0x26-0x29 should contain localtime HHMM, also for MB5000 series commit c8169b1e656f7f95c67946298da5a0e1c143f8e8 Author: Louis Lagendijk Date: Fri Apr 22 23:58:23 2016 +0200 pixma.h: step version of the backend to 0.17.32 sane-pixma.man pixma.desc: mark Maxify MB5000 as complete (but ADF does not work) commit dfc5487571ed2915bda7bdedbd4c79015004361b Author: Louis Lagendijk Date: Fri Apr 22 22:42:48 2016 +0200 pixma_mp150.c: fix 1200 dpi scanning for MB5000 series commit d5e1323738a4ed2edc96b566138c7cc6c55f3f5e Author: Louis Lagendijk Date: Fri Apr 22 21:05:40 2016 +0200 pixma.h: step pixma backend version to 0.17.31 commit c2985f0fd60279bca0dcfed3d3fb60cc33cfe4dc Author: Louis Lagendijk Date: Fri Apr 22 21:03:48 2016 +0200 pixma_bjnp_private.h: change minimum timeout value for the bjnp protocol to 1 sec as 500 ms gives errors on scanimage -A (it workked for scanbd) commit 4b2f171a13248a8e3d79379e368c54fb71ed97e2 Author: Louis Lagendijk Date: Wed Apr 20 11:19:32 2016 +0200 pixma_bjnp.c pixma_bjnp_private.h: set minimum timeout for network operations to 500ms commit affe1ac821b17813188bd91045ced32fe4fcfe56 Author: Louis Lagendijk Date: Wed Apr 20 10:58:54 2016 +0200 pixma_bjnp.c pixma_bjnp_private.h: make bjnp protocol follow timeouts set by backend commit 53aa78df3a6980791ce250c471d019c5c59b83ec Author: Louis Lagendijk Date: Mon Apr 18 22:00:15 2016 +0200 pixma_mp150.c: Fix scanbutton detection for MB5000 series commit 1452cf2e0d9f56602a5ca9b07e52f8d8f6b9ec8a Author: Louis Lagendijk Date: Sat Apr 16 21:37:25 2016 +0200 pixma_bjnp: Remove dead code in polling commit 19c128a23e27c1ab5a030fa6ff74da1b740629bb Author: Rolf Bensch Date: Tue Apr 12 18:30:24 2016 +0200 README.linux: move installation description into new document INSTALL.linux commit 51943537c314c9060138df8b37307377c307ba3a Author: Rolf Bensch Date: Tue Apr 12 18:14:55 2016 +0200 pixma: backend version 0.17.30 commit 270a8cd3bebfb2a630a1b74d5abd0b6fe2fc2e5d Author: Rolf Bensch Date: Tue Apr 12 18:13:36 2016 +0200 pixma: Canon PIXMA MG7700 Series is working commit 2556ffc2c593c3408cc554ecc97e07db457c975d Author: Rolf Bensch Date: Thu Mar 31 11:21:27 2016 +0200 pixma_mp150: MG7700 Series doesn't need special image format post processing @ high dpi commit e6b6ad9d4847e86aed8be0837a19bfada881f52d Author: m. allan noah Date: Tue Apr 5 20:30:10 2016 -0400 canon_dr backend v55 fixed-width scanners were calculating left-side offset incorrectly in color initial support for DR-F120 rename all DUPLEX_INTERLACE_* to indicate start and end of line commit 41a416e4afcf6cada69193dc408ef184d0e5f678 Author: Alessandro Zummo Date: Mon Mar 21 18:59:47 2016 +0100 epsonds: fixed resolution setting bug, DS-60000 workaround is needed no more commit 52bc4d241c9587e99be2ae4566ad01469a3ecab9 Author: Rolf Bensch Date: Mon Mar 21 10:53:29 2016 +0100 pixma: backend version 0.17.29 commit bc1637bb39794b415a2e73ee990e4763c73be3f9 Author: Rolf Bensch Date: Tue Feb 16 16:20:58 2016 +0100 pixma_mp150: MG3600 Series doesn't need special image format post processing @ 1200dpi commit 23eb95582da718791103b83ea002e947caa0f5fc Author: Rolf Bensch Date: Fri Mar 4 13:38:12 2016 +0100 pixma: backend version 0.17.28 commit eba9c9e2391d59459e5fa3f362d8dc08d14c7b9c Author: Rolf Bensch Date: Fri Mar 4 13:36:08 2016 +0100 pixma_imageclass: software lineart for all imageCLASS, imageRUNNER, i-SENSYS and laserBase scanners, supported by this sub-backend imageCLASS scanners: D420, D480, D530, MF810/820, MF3240, MF4010, MF4150, MF4270, MF4320, MF4360, MF4410, MF4570dw, MF4690, MF5630, MF6500, MF8030, MF8170c i-SENSYS scanners: MF210, MF220, MF3010, MF4500, MF4700, MF4800, MF5880dn, MF5900, MF6100, MF6680dn, MF8200C, MF8300, MF8500C imageRUNNER scanners: iR1133 laserBase scanners: MF5650 commit 38d6f1ba6dd48d8139b3ef504b4c7920d0e4736b Author: Rolf Bensch Date: Fri Mar 4 13:08:31 2016 +0100 pixma_imageclass: MF6100 Series document feeder does not have 600DPI capability commit 328e9b93d71d1f9b031c4066e4cba00893703c4a Author: Stéphane Voltz Date: Thu Mar 3 21:59:24 2016 +0100 raise build number commit 8ad2c60d82797cc3495f63f8230bdf6f999067a1 Author: Stéphane Voltz Date: Thu Mar 3 21:58:55 2016 +0100 use half step mode for LiDE 110 600 dpi scan commit 52ea420d44a26832f662c837bbbe4d2f7002875a Author: Stéphane Voltz Date: Thu Mar 3 21:46:43 2016 +0100 use half step for LiDE 210 600 dpi scans commit bd0b0cd218504868f32962a5558449956c8ce242 Author: Stéphane Voltz Date: Thu Mar 3 21:39:25 2016 +0100 use rewind instead of slow_back_home - if required by flags, do a rewind instead a slow_back_home that pollutes shading settings commit 3dee0f8d48e26e3aceb0243d03199af5870f30e2 Author: Stéphane Voltz Date: Thu Mar 3 21:31:01 2016 +0100 implement rewind for gl847 and gl124 commit de635a32f9638f5fad5806ab5de9498f5fa47ca9 Author: Stéphane Voltz Date: Thu Mar 3 21:12:29 2016 +0100 add rewind function to command set commit 270d6a4242c95d6d376f442ca701e067e3fc74d1 Author: Stéphane Voltz Date: Mon Feb 29 21:14:30 2016 +0100 fix Lide 110 gray mode max speed commit 2f891c13bb5cb1728479ee08ba45b756f68a3287 Author: Rolf Bensch Date: Thu Mar 3 13:40:46 2016 +0100 pixma: backend version 0.17.27 commit bbd327f5e7c973db331f3f309788d852367bc79a Author: Rolf Bensch Date: Thu Mar 3 13:38:33 2016 +0100 pixma_imageclass: reduce timeout for failed first usb command to 2 seconds commit c41640f36433e646989665bac0ac5da460f2d9a9 Author: Rolf Bensch Date: Thu Mar 3 13:36:44 2016 +0100 pixma: new global parameter to set duration of receive timeout loop The default value for receive timeout loop duration has not been changed. The loop still takes 8 seconds if a timeout occurs. commit 9897357727b65d13167b89cd1d1fe816f4d72563 Author: Stéphane Voltz Date: Sun Feb 28 21:26:27 2016 +0100 enable pixel averaging whne bleow 600 for all models commit d784dec60b096b8e8fe18f5f7b5c1921249d6ed2 Author: Stéphane Voltz Date: Sun Feb 28 12:26:12 2016 +0100 motor table fixes - add target speed for 600 dpi gray - add slope table for 4800/2400 dpi, gray and color commit 759729331cc60a86d884518064b2dc92736f7abd Author: Stéphane Voltz Date: Sun Feb 28 12:18:56 2016 +0100 fix maximum speed compute in gray mode commit e1b1ba8aeecf2eefa2855ec8c77604a8070027ab Author: Stéphane Voltz Date: Fri Feb 26 05:57:35 2016 +0100 fix expiration time option reading commit 61d6f5c2140e6e659db20916937cc95c5c7256f3 Author: Stéphane Voltz Date: Thu Feb 25 21:37:55 2016 +0100 mode set fixes commit fa2c9dc9b216fa7b7f1baf013b7cbe8eb3df8597 Author: Stéphane Voltz Date: Thu Feb 25 21:37:00 2016 +0100 fix GPIO during scan commit c5117ed0f1b522eab10fd2248f140b2acad2a708 Author: Stéphane Voltz Date: Wed Feb 24 21:43:29 2016 +0100 doc and version update commit 747275a00f03e4ab643461448985ce20879e1d12 Author: Stéphane Voltz Date: Wed Feb 24 21:15:26 2016 +0100 add 1200 and 2400 dpi mode for LiDE 120 commit 2a18600792c00f9ca37ff5b52d2cc1c8202d8b4b Author: Stéphane Voltz Date: Wed Feb 24 06:35:46 2016 +0100 make 1200 dpi scan mode work for LiDE 120 commit b11a69d27572aa938cedff303ba7560ca9793943 Author: Stéphane Voltz Date: Wed Feb 24 06:17:50 2016 +0100 make 600 dpi mode work for LiDE 120 - add override for registers 0x16 and 0x70 since 120's sensor is set differently according to resolution commit 15e203de89abe53f732aa431548645c5c9838237 Author: m. allan noah Date: Tue Feb 23 21:11:00 2016 -0500 Various copyright comment updates commit 1465543cc0dd9e4fb4b3706ca6793e90a35ce389 Author: m. allan noah Date: Tue Feb 23 21:07:06 2016 -0500 fujitsu backend v130 run init_model before init_ms so some scanners can override set all M309x and M409x scanners s->broken_diag_serial = 1 commit 963de58dfc4498693aeeec35a9ff23363af6ac67 Author: m. allan noah Date: Tue Feb 23 20:42:52 2016 -0500 Enable padded read for DR-3080CII commit 1207ce5a40664c04b934bd0a6babbc1575361356 Author: m. allan noah Date: Tue Feb 23 20:36:32 2016 -0500 Support SANE_USB_WORKAROUND env var Here, we add a new env var (SANE_USB_WORKAROUND) to sanei_usb.c. This allows end users to conditionally enable the workaround added in commit 014b45d920f1fb630e1a31bb01f1da02ea2a6a87. The default is to not enable the workaround, because more recent Linux kernels no longer seem to need it. Some users have even reported failure with the workaround enabled. commit 219198838be069d7e3d48b53762727f1bbfb93e5 Author: Stéphane Voltz Date: Tue Feb 23 21:39:22 2016 +0100 LiDE 120 working [75-300] dpi - fix sensor pixel number - enable calibration - default to 16 pixel DUMMY commit 4fd1d10228047a740f28b1cd25579b7c40c93b1f Author: Stéphane Voltz Date: Mon Feb 22 21:45:02 2016 +0100 tune scanarea geometry commit a74ebe551daf8750821b1ab57324e54141a84461 Author: Stéphane Voltz Date: Sun Feb 21 22:14:48 2016 +0100 first almost correct scan at 300 dpi commit 8f938f2d00d27070e826f88a77264ee36d0bbedf Author: Stéphane Voltz Date: Sun Feb 21 09:48:26 2016 +0100 GL124 DAC and SENSOR setup changes commit f56ffa63b99db4767b35d294fef96476b228f993 Author: Stéphane Voltz Date: Sun Feb 21 09:47:47 2016 +0100 doxygne fix commit 2e1102dc3ab1ee4d7bfec3e7cbf6e3a1527f5264 Author: Stéphane Voltz Date: Thu Feb 18 21:41:38 2016 +0100 add dedicated reference slope tables for LiDE 120 commit 214dfad1d5aa841b597187004747ec88c507cf06 Author: Stéphane Voltz Date: Wed Feb 17 21:43:05 2016 +0100 use dedicated LiDE120 GPIO commit 387cea7d6ce75af9441c5841221267bef7b7924c Author: Stéphane Voltz Date: Wed Feb 17 21:04:55 2016 +0100 define dedicated motor/sensor/gpio for LiDE 120 commit e90f8cb8a1e62f6865d9e237fd1f0e7f773e5094 Author: Stéphane Voltz Date: Fri Feb 12 08:11:20 2016 +0100 latin1 -> utf8 commit d74d3bcd887d2a3d59ee96e04eb68f15c0a3b882 Author: Rolf Bensch Date: Thu Feb 18 22:34:16 2016 +0100 README.linux: add some hints for individual SANE installations commit 926a7e67b6f81ffdb1b4f67a55bf84862efcf6b9 Author: Rolf Bensch Date: Wed Feb 17 21:24:18 2016 +0100 pixma: fix scanner names commit 235dc80b5f3faaf195eef1e177a1f38284ca3bee Author: Rolf Bensch Date: Wed Feb 17 21:10:44 2016 +0100 pixma: Canon i-SENSYS MF6100 Series is working commit 6d89f7ef25266cc9a53440bbf68ff2e1a37d4b86 Author: Rolf Bensch Date: Wed Feb 17 21:06:04 2016 +0100 pixma: backend version 0.17.26 commit 7a227dcaf2771b31feb852e6a83336976966a0ab Author: Rolf Bensch Date: Wed Feb 17 21:03:18 2016 +0100 pixma_imageclass: wait for 8sec to throw last page out of ADF feeder @ ADFDUP commit 23efb9f55f466179df86848912acbed1a94c10ff Author: Rolf Bensch Date: Wed Feb 17 21:01:48 2016 +0100 pixma_imageclass: PIXMA_ENO_PAPER check also for ADFDUP scans commit 29ceb0e377009cd6829d8f68c58a2197ac19a20d Author: Rolf Bensch Date: Wed Feb 17 20:59:32 2016 +0100 pixma_imageclass: fix for failed first usb command (timeout) Sometimes the first usb command to the scanner fails after a previous scan. A workaround was to reconnect the usb cable. This fix simply resends the failed command. commit 8f1202d6537568e56b4886ebe5d41d0210ffacd9 Author: Rolf Bensch Date: Wed Feb 17 20:55:49 2016 +0100 pixma_imageclass: fixes for MF6100 Series - special ADF settings - the MF6100 Series is a Generation 2+ scanner, but uses the old read image command commit 02855737ee84e3c72bceff9ba06fddc5a5d99860 Author: Rolf Bensch Date: Wed Feb 17 20:32:00 2016 +0100 pixma: use usb timeout instead of sleep timer while waiting for usb response commit 4771fab9c16b477dc376bd2e5fdd8d0dc7f2c478 Author: Rolf Bensch Date: Wed Feb 17 20:30:47 2016 +0100 pixma: reduce global usb read and write timeouts to 1 sec commit 99f7e7872f2619c3ebec2590b91de3fb0ca28a1a Author: Olaf Meeuwissen Date: Sat Feb 13 17:37:34 2016 +0900 Disable use of pthreads if pthread.h cannot be found commit 04d5e4a0cf775f6483873a3f1e70a173587546b6 Author: Olaf Meeuwissen Date: Sat Feb 13 17:34:46 2016 +0900 Move #include to sanei_thread.h The sanei header file may need pthread_t. If it does, make sure it is available. commit af35e9ba749cce6e735d685ec4495e8c8d85778c Author: Rolf Bensch Date: Thu Feb 11 12:06:34 2016 +0100 pixma: Canon Pixma MG3600 Series is working Reported by Rajib Bandopadhyay commit 7bd773ade5ff1bc4170d2a1773428efe759aaa75 Author: Stéphane Voltz Date: Tue Feb 9 09:55:26 2016 +0100 LiDE 120 support wip commit 056f590f2d147099554d97a89dd5e0ddfa8d6dda Author: Alessandro Zummo Date: Sat Jan 23 00:55:31 2016 +0100 epsonds: fixed comment commit cf2dfea0008d16cb70f8baeaae5a414e9bdafda3 Author: Alessandro Zummo Date: Fri Jan 22 20:44:36 2016 +0100 epsonds: extend the bug fix to all depths commit 8fd6151acd1a1b313b1c9fabb5e2691ba45de9d6 Author: Alessandro Zummo Date: Fri Jan 22 17:38:00 2016 +0100 epsonds: fix stripes on DS-60000 at 1bpp/300dpi commit 4fa7f4f6f8b69f41fd5d03abc12d16e0f2e876b3 Author: Alessandro Zummo Date: Fri Jan 22 17:01:57 2016 +0100 epsonds: clear endpoints on startup in order to fix some strange scanner / xhci combo commit f78e85cad666492fadd5612af77fa7c84e270a12 Author: Rolf Bensch Date: Fri Jan 8 18:35:20 2016 +0100 pixma: backend version 0.17.25 commit b08c324223732407d736a79ab8c59f01b3774736 Author: Rolf Bensch Date: Fri Jan 8 18:34:27 2016 +0100 pixma: Canon PIXMA MG5700 Series is working Reported by Andrew Reginato, bug #315244 commit 0f47b47b759908e7b11800404d269087d60d87ad Author: Rolf Bensch Date: Fri Jan 8 17:32:36 2016 +0100 pixma_mp[150|810]: disable send_time() The function send_time() makes trouble with a lot of scanners. We send a warning to the debug output instead of sending the time. fix for [#315248] Canon MP250 with pixma backend is not working commit b040b150a08b0b5394ad3bc91a45966d97f58152 Author: Rolf Bensch Date: Fri Jan 8 16:54:30 2016 +0100 pixma: fix for [#315244] Add support for Canon PIXMA MG5700, MG6800, MG6900 and MG7700 These scanners are new and need further testing! commit 81c429082c3c139f8616de4a73733953cd5aa33f Author: Rolf Bensch Date: Fri Jan 8 16:43:46 2016 +0100 pixma: update copyright commit 9aecb00947e6bf7ef1cf412aff2ab41202617b30 Author: Olaf Meeuwissen Date: Fri Jan 8 21:26:31 2016 +0900 md5: Avoid the need for casting This also modifies the code slightly to follow the original array access more closely. commit cdad5961f3888f0a3c0c525d0efab33174c11a24 Author: Volker Diels-Grabsch Date: Sun Dec 6 01:23:51 2015 +0100 Introduce md5_set_uint32 This fixes the following GCC warning: warning: dereferencing type-punned pointer will break strict-aliasing rules commit f3471c2ca6ea22846dd6619aff7913610722a6c0 Author: Olaf Meeuwissen Date: Sat Jan 2 17:50:34 2016 +0900 saned: Use system header IPv6 test macros if available This should fix [-Wstrict-aliasing] compiler warnings on those systems where the IN6_IS_ADDR_LOOPBACK and IN6_IS_ADDR_V4MAPPED macros exist. POSIX.1-2001 states that they shall be defined in netinit/in.h so most systems will probably have them. commit 0de5416a9bafa1ade52722c509817276bbf87d8a Author: Olaf Meeuwissen Date: Sat Jan 2 16:06:34 2016 +0900 umax_pp: fix memory leak Found courtesy of [-Wunused-but-set-variable] compiler warning. commit 9d78ace3b7e60afa2b3cb829ac23e5f8b4ccdc07 Author: Olaf Meeuwissen Date: Sat Jan 2 16:06:00 2016 +0900 umax_pp: fix [-Wunused-but-set-variable] compiler warnings commit 3f0c3df2fcde8d0cf30ab68c70cb5cad984dda6f Author: Olaf Meeuwissen Date: Thu Dec 31 17:51:00 2015 +0900 kvs40xx: fix [-Wstrict-aliasing] compiler warnings commit b1f886a2e36555fb0b01c8eb22a0041aebe25795 Author: Olaf Meeuwissen Date: Thu Dec 31 17:47:40 2015 +0900 kvs20xx: fix [-Wstrict-aliasing] compiler warnings commit 0e3a5c4197fe36eae739a6086b484ff16b83d663 Author: Olaf Meeuwissen Date: Thu Dec 31 17:43:25 2015 +0900 kodakaio: fix [-Wformat=] compiler warnings This uses the ANSI C approach that is used in a lot of existing code rather than what ISO C99 allows for consistency. commit cadb4b0fff00540159625320416e5601c4704627 Author: Olaf Meeuwissen Date: Sat Dec 26 17:45:56 2015 +0900 saned: fix [-Wmaybe-uninitialized] compiler warning commit 572e61d39a10ac7299d95005fa7543afe4957d80 Author: Olaf Meeuwissen Date: Sat Dec 26 14:56:12 2015 +0900 p5: fix [-Wunused-but-set-variable] compiler warnings commit f9e44963801be2940c71e49d7c76a4e59b28dfc7 Author: Olaf Meeuwissen Date: Sat Dec 26 14:51:21 2015 +0900 xerox_mfp: fix [-Wunused-but-set-variable] compiler warning commit f276e3e05503c5f44890df5a8105959ea07dbb6d Author: Olaf Meeuwissen Date: Sat Dec 26 14:49:25 2015 +0900 umax1220: fix [-Wunused-but-set-variable] compiler warning commit e28bdadae98f203188253c5b0a8825a284c8c066 Author: Olaf Meeuwissen Date: Sat Dec 26 13:27:47 2015 +0900 u12: fix [-Wunused-but-set-variable] compiler warning commit 70c9e1d13ce705249ddbbee2dad5e6307fe77ffa Author: Olaf Meeuwissen Date: Sat Dec 26 13:25:18 2015 +0900 sm3840: fix [-Wunused-but-set-variable] compiler warnings commit 9d4f2a72098436e4a65d2047a151ba3c0af82907 Author: Olaf Meeuwissen Date: Sat Dec 26 13:18:13 2015 +0900 sm3600: fix [-Wunused-but-set-variable] compiler warning commit 82720a2023d8e75480036a9e86f8a57d0bfe6a10 Author: Olaf Meeuwissen Date: Thu Dec 24 19:01:09 2015 +0900 sharp: fix [-Wunused-but-set-variable] compiler warning commit da010d6088a75ed85472c46e9a29ace18cd7eda9 Author: Olaf Meeuwissen Date: Thu Dec 24 17:44:04 2015 +0900 niash: fix [-Wunused-but-set-variable] compiler warning commit 86c5d6d7bd52dcb4208c7d5a1ba8844e8c8011e5 Author: Olaf Meeuwissen Date: Thu Dec 24 17:38:41 2015 +0900 nec: fix [-Wunused-but-set-variable] compiler warning commit 220429ff9ebc78e9869e431125ffd9a235efa93d Author: Olaf Meeuwissen Date: Wed Dec 23 22:27:47 2015 +0900 mustek_usb2: fix [-Wunused-but-set-variable] compiler warnings commit 7efb05627273266a8171d3f9244bbd7a433d6e44 Author: Olaf Meeuwissen Date: Wed Dec 23 22:19:01 2015 +0900 mustek_pp: fix [-Wunused-but-set-variable] compiler warning commit 664398cc311b85647a804bee0f8f230a0e3a3f49 Author: Olaf Meeuwissen Date: Wed Dec 23 22:12:07 2015 +0900 mustek: fix [-Wunused-but-sed-variable] compiler warnings commit 8b75c6d45002ffafae6cfbf2edd64b3de35d3b04 Author: Olaf Meeuwissen Date: Wed Dec 23 22:17:40 2015 +0900 microtek2: fix another [-Wunused-but-set-variable] compiler warning This allows for the fact that the backend may be compiled with and without support for authorization. commit c1458770955b5476eedc89755bb424744b05b055 Author: Olaf Meeuwissen Date: Wed Dec 23 22:11:31 2015 +0900 microtek2: fix [-Wunused-but-set-variable] compiler warnings commit 26aa8b52f60adf7553b2872f54a85cfd7b20dd98 Author: Olaf Meeuwissen Date: Sat Dec 26 17:41:09 2015 +0900 magicolor: fix [-Wunused-function] compiler warning This function is only used when SNMP support is activated. commit 292dd42bb6585e2801623d1f33497581626d9d72 Author: Olaf Meeuwissen Date: Wed Dec 23 21:50:42 2015 +0900 magicolor: fix [-Wunused-but-set-variable] compiler warning commit d0e85e9d5e775f143f3db98e762d72861f60a82b Author: Olaf Meeuwissen Date: Wed Dec 23 21:48:09 2015 +0900 ma1509: fix [-Wunused-but-set-variable] compiler warning commit 7c0f5ec66c7fd673d27876b538e52440a897cc1f Author: Olaf Meeuwissen Date: Sat Dec 26 17:36:57 2015 +0900 lexmark: fix [-Wmaybe-uninitialized] compiler warning This adds a default handler to switch statement so low_get_start_loc() bails before the start_600 variable is used. commit 068c3bb75d3972dd2218caa84a6de761c5ca0db8 Author: Olaf Meeuwissen Date: Sat Dec 26 17:28:34 2015 +0900 kodakaio: fix [-Wunused-function] compiler warning The function is only used when Avahi support is enabled and has been put in a suitable compilation scope. commit 610dc9ceb4d9eb061209d935e2b1966dfca5a74c Author: Olaf Meeuwissen Date: Wed Dec 23 21:38:08 2015 +0900 kodak: fix [-Wunused-but-set-variable] compiler warning commit 2724f85552def3fa0c92d88389854c283eac38d3 Author: Olaf Meeuwissen Date: Wed Dec 23 21:36:54 2015 +0900 hpsj5s: fix [-Wunused-but-set-variable] compiler warning commit aabb63dbbfdfea9f444019a19171bdcace08b0dd Author: Olaf Meeuwissen Date: Wed Dec 23 21:35:39 2015 +0900 hp4200: fix [-Wunused-but-set-variable] compiler warnings commit a82798d5e1d8352daa1d519d77a7a22771c8439e Author: Olaf Meeuwissen Date: Wed Dec 23 21:33:40 2015 +0900 hp3500: fix [-Wunused-but-set-variable] compiler warning commit 51277aec4a6959f88d46d7ca14cfb94166c328eb Author: Olaf Meeuwissen Date: Wed Dec 23 21:24:10 2015 +0900 hp: fix [-Wunused-but-set-variable] compiler warnings commit a97b1738dfcc16cd0a7fd68f95df8b013f3cb206 Author: Olaf Meeuwissen Date: Wed Dec 23 21:19:46 2015 +0900 gphoto2: fix [-Wunused-but-set-variable] compiler warning commit cbeb98daeceb262b3a868c1b2ea2102b98760e61 Author: Olaf Meeuwissen Date: Wed Dec 23 21:10:29 2015 +0900 epson: fix [-Wunused-but-set-variable] compiler warning commit cbc72a017123b81a21c6b69ffcb6f828cc810f03 Author: Olaf Meeuwissen Date: Wed Dec 23 21:08:46 2015 +0900 dmc: fix [-Wunused-but-set-variable] compiler warning commit fb4147c4f13f7f39c00a807ecc327b5824df21f5 Author: Olaf Meeuwissen Date: Wed Dec 23 20:58:07 2015 +0900 dc240: fix [-Wunused-but-set-variable] compiler warning commit bcfa3f6591744e43a0aa7be228505423b25f7731 Author: Olaf Meeuwissen Date: Wed Dec 23 20:56:49 2015 +0900 dc210: fix [-Wunused-but-set-variable] compiler warning commit c31cf621062ae4ef69a80d51879d242978853859 Author: Olaf Meeuwissen Date: Wed Dec 23 20:55:36 2015 +0900 dc25: fix [-Wunused-but-set-variable] compiler warnings commit 43b296471bc5a902de470f57df681d0c04964b91 Author: Olaf Meeuwissen Date: Wed Dec 23 20:51:28 2015 +0900 coolscan: fix [-Wunused-but-set-variable] compiler warnings commit 50ca4bc97670fed1083a5677ddfa71f74bd495dc Author: Olaf Meeuwissen Date: Wed Dec 23 20:49:17 2015 +0900 cardscan: fix [-Wunused-but-set-variable] compiler warning commit c2b7b1af748527dd8ba0fcabc4310fcac1bdf491 Author: Olaf Meeuwissen Date: Wed Dec 23 20:46:13 2015 +0900 canon636u: fix [-Wunused-but-set-variable] compiler warning commit e8818437456f36c721f12d311bdb65f3d45606c7 Author: Olaf Meeuwissen Date: Wed Dec 23 20:39:15 2015 +0900 canon: fix [-Wunused-but-set-variable] compiler warnings commit 592430016c97b4362314c63a1ac7c96f23d71e4d Author: Olaf Meeuwissen Date: Wed Dec 23 20:30:02 2015 +0900 avision: fix [-Wunused-but-set-variable] compiler warning The variable seems to have been superseded by conv_out_size in the else branch of set_calib_data(). commit 5b8fdd317f1bb4076b8fe661db78c230af21004b Author: Olaf Meeuwissen Date: Wed Dec 23 20:27:20 2015 +0900 artec_eplus48u: fix [-Wunused-but-set-variable] compiler warning This leaves the sane_close() implementation just as broken as it has been from the initial commit sometime in 2002. commit ec1936713e67b192d057b2f552a25622f88844a1 Author: Olaf Meeuwissen Date: Wed Dec 23 20:26:21 2015 +0900 artec_eplus48u: fix [-Wunused-but-set-variable] compiler warning The variable was only used to silence a [-Wunused-parameter] warning. commit 5b21a24312f2cf2ced5d5c70b0f7d2c1f0c58f35 Author: Olaf Meeuwissen Date: Wed Dec 23 19:57:13 2015 +0900 artec: fix [-Wunused-but-set-variable] compiler warning The variable is used to assign return values but is not referenced by anything itself. commit 57ae115eafa5b52b84b8e2878982cdad7c1a9f13 Author: Olaf Meeuwissen Date: Sat Dec 26 17:12:41 2015 +0900 sanei_thread: fix [-Wmaybe-uninitialized] compiler warning commit cd3453948dd812aaa77d921b198351b340f8c748 Author: Olaf Meeuwissen Date: Wed Dec 23 18:53:06 2015 +0900 sanei_usb: const_cast data buffer The libusb_bulk_transfer() API caters to both reads and writes and as a result of that will not take a const pointer. commit be084e0d7bb7933e1826e6e48b42f43bc3cb077a Author: Olaf Meeuwissen Date: Sat Dec 26 17:05:17 2015 +0900 sanei_usb: Move variable declarations to scope of usage Fixes an [-Wunused-variable] when compiling without libusb. commit 0d7882e34b5f5625261258a3a341a58a04beb304 Author: Olaf Meeuwissen Date: Sat Dec 26 16:51:44 2015 +0900 Change compile time warning policy The -Wall flag is now always enabled (when using gcc). The -Wextra flag (previously known as -W) and -pedantic flags are, by default, enabled during development but disabled for releases. All other flags have been removed. commit 5136e664b8608604f54a2cc1d466019922b311e6 Author: Olaf Meeuwissen Date: Sun Dec 20 21:58:45 2015 +0900 Document ChangeLog policy change commit 674b75fc913187415b4f151a52e4bc7004c5d5b0 Author: Olaf Meeuwissen Date: Sun Dec 20 17:33:55 2015 +0900 Improve readability of condition This also fixes the following GCC warning: warning: logical not is only applied to the left hand side of comparison commit 58052a7ce6b205e25a2fc85f31158595cad00258 Author: Volker Diels-Grabsch Date: Sat Dec 5 21:33:48 2015 +0100 Change GCC mode from ISO C90 to ISO C99 Add GCC flag "-std=c99". Also remove GCC flag "-ansi" which is an alias for "-std=c90" and would make the flag "-std=c99" ineffective. This fixes all occurrences of the following GCC warning: warning: ISO C90 does not support '__func__' predefined identifier commit baec5e039504de390cae41557b0b8323343721c3 Author: Volker Diels-Grabsch Date: Sat Dec 5 10:48:59 2015 +0100 Use consistently __func__ instead of __FUNCTION__ Some parts of SANE used __FUNCTION__ while other parts used __func__. Now, __func__ is used consistently throughout the SANE sources. This fixes all occurrences of the following GCC warning: warning: ISO C does not support '__FUNCTION__' predefined identifier commit 93298674d02b1127efdf4e726e92e797a0081c9e Author: Volker Diels-Grabsch Date: Sat Dec 5 20:44:14 2015 +0100 Merge all compatibility macros around __func__ and __FUNCTION__ Various parts of SANE introduced their own compatibility macros for old compilers that don't support __func__. Most of these definitions are identical or have minor differences. This patch replaces them with a single instance in the central header file for backends. commit 7c8c8e29beed2c4e6f96db08031c12c9001ca784 Author: Volker Diels-Grabsch Date: Sun Dec 6 03:32:51 2015 +0100 Remove dead code due to unused variables This fixes some occurrences of the following GCC warning: warning: variable '...' set but not used commit aba87a4582d594cf953b4bda5b5d42e37e13f21c Author: Volker Diels-Grabsch Date: Sun Dec 6 01:30:30 2015 +0100 Mark internal function toupper_ascii as static This fixes the following GCC warning: warning: no previous prototype for 'toupper_ascii' commit 13b6faee2a0696eb02a61f22121b7f4854987f2e Author: Volker Diels-Grabsch Date: Sun Dec 6 03:03:06 2015 +0100 Fix interface of helper function write_many This fixes two occurrences of the following GCC warning: warning: cast discards 'const' qualifier from pointer target type commit badd7025b21b2207cfb95001aeb324597e24b301 Author: Volker Diels-Grabsch Date: Sun Dec 6 02:37:10 2015 +0100 Bugfix: On error, return the actual error code in sanei_magic_rotate Up to now, on failure the sanei_magic_rotate function returned a success status. This fixes the following GCC warning: warning: variable 'ret' set but not used commit 6aced758f4a95fd858906f3e898ee967a9718641 Author: Volker Diels-Grabsch Date: Sun Nov 29 16:02:01 2015 +0100 Fix typos in comments While reading through the SANE sources I noticed some annoying typos in the comments. This patch is my contribution to make the SANE sources slightly more pleasant to read. commit 6d8b8d5aa6e8da2b24e1caa42b9ea75e9624b45d Author: Alessandro Zummo Date: Tue Dec 15 16:17:53 2015 +0100 epsonds: fix duplex w/ double feed detection commit e9b52639e8dca938b5569b1697c36796ab92174a Author: m. allan noah Date: Tue Dec 15 07:23:42 2015 -0500 Add note about changelogs commit 06d876f74e5d07cb82d02ca1222926a61a3e458b Author: Stéphane Voltz Date: Tue Dec 15 06:05:07 2015 +0100 fix for #315050 - handle case where linesel is rounded to 0 when scan y resolution is below minimal scan resolution but higher than half of the minimum commit 753d123f36d08cdb8047adac7c89a9fe015c4b25 Author: m. allan noah Date: Sat Nov 28 08:34:58 2015 -0500 canon_dr desc update add note about mode switch on P-208 commit f1593204c72124f3077b0b29f3c128d30be415b5 Author: Olaf Meeuwissen Date: Fri Nov 27 21:26:46 2015 +0900 Drop execute permission Source code, description files and configuration templates should never need to be executed. commit e094c5b43b6d8d8bec84bd5b1ab2c6009f38e14b Author: Olaf Meeuwissen Date: Fri Nov 13 22:06:30 2015 +0900 Invert sense of sanei_thread validity check Double negatives suck. commit fe12d31e6873f5c3de330f1de4c4fbc851df1e9f Author: Olaf Meeuwissen Date: Fri Nov 13 21:41:56 2015 +0900 Fix SANE_Pid related -Wsign-compare warnings This may fix threading related issues on WIN32 platforms, BTW. commit ed59056d40a143b3cf9243ea0068448a88ce3108 Author: m. allan noah Date: Mon Nov 23 21:26:09 2015 -0500 canon_dr backend v54 - br_x and br_y locked to page_width/height until changed commit d0ea697ab83360bf0ccddcd02565f85ea0f96b50 Author: m. allan noah Date: Mon Nov 23 21:08:30 2015 -0500 fujitsu backend v129 - br_x and br_y locked to page_width/height until changed - add USB ID's for fi-6xxxLA and fi-6xxxZLA scanners - add USB ID's for unsupported SP11xx scanners (genesys based) commit e6a249e0424f6854b7ed12f8272633a0edecfa90 Author: m. allan noah Date: Thu Nov 12 21:10:49 2015 -0500 revert mustek_usb2 backend upgrade Instead of 100+ revert commits, I've lumped everything into a single commit. This removes all of dedf0ac30 through db7f038f1, plus the parts of 497d59180 which were specific to mustek_usb2 commit 21c5f4d814f93a363377798635c7f1cbc1c79342 Author: Olaf Meeuwissen Date: Wed Nov 11 22:38:56 2015 +0900 Add missing #include for malloc() commit 7dc416b7ae3f0db7c5ce97b5bce0f05f869d877f Author: Olaf Meeuwissen Date: Wed Nov 11 22:38:32 2015 +0900 Remove unnecessary cast commit fff1c5962a94ab410dba4fed541312554c8edf8d Author: Olaf Meeuwissen Date: Wed Nov 11 22:35:34 2015 +0900 Fix "discards 'const' qualifier from pointer target type" warnings The line variable is not (and cannot be) declared 'const'. The string variable points to a location in line, hence it is safe to cast away 'const'ness of the sanei_config_skip_whitespace() return value. commit 38153b33e1657137e6956e63a9fcb76d665f86f2 Author: Olaf Meeuwissen Date: Wed Nov 11 22:33:34 2015 +0900 Fix "discards 'const' qualifier from pointer target type" warning The device2 variable is not modified so let's make that clear. commit d2576bbb948dd9d8e06f66dc4cede774c5518751 Author: Olaf Meeuwissen Date: Wed Nov 11 22:30:10 2015 +0900 Fix "discards 'const' qualifier from pointer target type" warnings The cs3_xfree() functions is really just a checked call to free() so its signature has been changed to match that. The warnings that causes have been fixed in the same way and on the same grounds as the previous commit. commit e65fd1b4cb5e9463d16a6fb4cd8eeb129ba58e63 Author: Olaf Meeuwissen Date: Wed Nov 11 22:28:17 2015 +0900 Fix "discards 'const' qualifier from pointer target type" warnings The resources pointed to have been acquired by the backend. It is safe to cast away the 'const' qualifier when releasing these resources. commit 497d59180649a831691220aefcc8ec81d5f90960 Author: m. allan noah Date: Sun Nov 8 17:17:37 2015 -0500 automake for recent changes updates to mustek_usb2, canon_dr and umax_pp require automake run commit db7f038f108ca12966b947dd80f3772e2133495e Author: Jan Hauffa Date: Sat Jul 14 23:15:02 2012 +0200 Fix a bug introduced during refactoring that caused discolored stripes to appear at the left and right sides of the scan area. commit a64477bf1a381458e0500ef7c62da521d6c4d97f Author: Jan Hauffa Date: Sat Jul 14 16:44:28 2012 +0200 Remove USB 2.0 mode, as it causes horrible backtracking for resolutions > 300 dpi. commit 98248f6088850045579a1e46f2e8aa16302f9dd9 Author: Jan Hauffa Date: Sat Jun 30 22:37:21 2012 +0200 properly add new handle to linked list commit 3b48a6d10560e855cef815ca5c1ecbb50fd02d00 Author: Jan Hauffa Date: Sat Jun 30 00:04:06 2012 +0200 fix integer overflow bug in image data conversion commit d0ea79f00059a4a8c3a2ac710fd0443c8bbb3d3a Author: Jan Hauffa Date: Sun May 27 12:23:53 2012 +0200 Add model-specific functions for computing the number of motor steps. commit 15fbbf60a6d8c9956a6b6a874f2d0b734ab1b935 Author: Jan Hauffa Date: Sun May 15 22:42:17 2011 +0200 Split SetMotorSteps into a function that computes the number of steps for the various motor states and and a function that writes the step counts to the controller's registers. commit 70dcfa4cedf3619575d413126d3530b28e490fd3 Author: Jan Hauffa Date: Sun May 15 21:16:00 2011 +0200 Simplify SetMotorStepTable*. commit 27b636d294876c7aac0b53922bacac627ba873c9 Author: Jan Hauffa Date: Sun May 15 19:58:09 2011 +0200 Provide model-specific function for computing the motor current. commit 8f405f5a937fd05a67a7554138c047fb5abe5e2c Author: Jan Hauffa Date: Sun May 15 18:13:44 2011 +0200 Update motor table generation according to new dumps. commit 2fa054456e723d7741be4eeb09bb879b802fad9d Author: Jan Hauffa Date: Sun May 15 15:09:21 2011 +0200 Detect USB controller type. commit d8a203a69373bb6f207de9ddc9c30a60da4a2cc9 Author: Jan Hauffa Date: Sun May 15 14:35:06 2011 +0200 Add function to compute scan motor table for 4800H48U, rearrange code in Asic_SetWindow. commit ceb7d29690f2ce8f32576caa4b7197fc91b024c1 Author: Jan Hauffa Date: Sun May 8 17:39:31 2011 +0200 Fix some misuse of SENSOR_DPI constant. commit 30e39071560412b362e03a105e20996093074d81 Author: Jan Hauffa Date: Sun May 8 16:44:15 2011 +0200 Allow for model-specific parameters in mustek_usb2_high.c. commit 47c56e3f19b38c97db4f2d14f780343adca9024f Author: Jan Hauffa Date: Sun May 8 14:55:42 2011 +0200 Add some motor-related code for the Microtek 4800H48U. commit 7b26e0e3fa48742b66bd4632772d70d140058c70 Author: Jan Hauffa Date: Sun May 8 13:56:17 2011 +0200 Simplify SimpleMotorMove. commit 0a1125895b3f1ed0058729fcc29d6858ac6d5e56 Author: Jan Hauffa Date: Sat May 7 13:58:24 2011 +0200 Add some information about the values retrieved by GetChipStatus. commit c691b0224130763239966c1d7856e96810289238 Author: Jan Hauffa Date: Sat May 7 13:28:52 2011 +0200 Remove restriction to 8-bit color in negative mode. The only reason for that restriction was that the histogram stretching code, which has been removed earlier, could only handle 8-bit color. commit 4ced7a900a6463c460121eaed7583f4249ef74c2 Author: Jan Hauffa Date: Sat May 7 12:45:50 2011 +0200 Improve debug logging and fix a bug in TestDRAM. commit e1c00bd9ab9d3f4b568d5bb6d09e0812cbef7b7f Author: Jan Hauffa Date: Wed May 4 23:30:14 2011 +0200 Introduce SetMotorCurrentAndPhase for Microtek scanner, fix old bug in simplification of Mustek variant. commit 96b4950499d0cf44369fc8e50099925de2ac3c4f Author: Jan Hauffa Date: Mon Apr 25 20:25:02 2011 +0200 Register related fixes. commit 5d556cd5e65ba9d1df30e3a3beb0322549d040ff Author: Jan Hauffa Date: Mon Apr 25 19:26:32 2011 +0200 Introduce structure for specifying model-specific parameters on the ASIC level. commit 529b6a1d6dc3ff52945f8bf3323bf571596e8088 Author: Jan Hauffa Date: Sun Apr 24 21:01:10 2011 +0200 Fix bug in device list handling. commit 877f250b5c32f8403ab321d14fd76afd7e2c2d1d Author: Jan Hauffa Date: Sun Apr 24 20:54:19 2011 +0200 Resolve issue with debug logging. commit 272c1d6fdeb8af9d6d4b61f85b4a77ca2ebbb645 Author: Jan Hauffa Date: Sun Apr 24 20:30:19 2011 +0200 Add preliminary model entry for the Microtek 4800H48U. commit 7fda9bbf93f4565e1334ebafd0b6caf13d462de4 Author: Jan Hauffa Date: Sun Apr 24 20:21:41 2011 +0200 Introduce support for multiple scanners. Keep all state local and ensure that all resources are freed by sane_exit. Ensure that each function returns only those error codes that are valid according to the SANE standard. commit 6865eaf6edef0cc5ea30bcc0d72b52189132f4d6 Author: Jan Hauffa Date: Sun Apr 24 14:49:06 2011 +0200 Simplify sane_read, other fixes to mustek_usb2.c. commit 63793907e2c2120511603a504396f7053fdc5149 Author: Jan Hauffa Date: Sun Apr 24 14:15:59 2011 +0200 Minor fixes to image processing. commit bc203e8aa125f276ce84498091185482a22d3527 Author: Jan Hauffa Date: Sun Apr 24 13:55:35 2011 +0200 Sanitize option handling and add support for scanner buttons. commit b2b3cf767a9a91677b0ac13a6645ed918ca71d55 Author: Jan Hauffa Date: Sun Apr 24 00:59:19 2011 +0200 Use standard macros for byte swapping. commit 281f53aa1829a61286232efed7a9d6253cec32d4 Author: Jan Hauffa Date: Sun Apr 24 00:39:59 2011 +0200 Remaining endian safety fixes. commit 80b7249ebf9c57b60cbc0a25288cc04ba2302b56 Author: Jan Hauffa Date: Sat Apr 23 22:42:45 2011 +0200 Resolve minor thread safety problem. commit de84f51270f05ead6758d2811a2d36160c412cb1 Author: Jan Hauffa Date: Sat Apr 23 19:31:50 2011 +0200 Simplify row stride calculation in Asic_SetWindow(). commit 7cd88d41222c85bd262fbf681401ae8c2dab1bce Author: Jan Hauffa Date: Sat Apr 23 19:21:52 2011 +0200 Remove Scanner_ScanSuggest. commit 3f5592ef8e7eedc0a9ff52b8091f9b41b9c2d56f Author: Jan Hauffa Date: Sat Apr 23 19:04:31 2011 +0200 Move global state variables of mustek_usb2_high.c into scanner structure. commit 60a244ed1e1a4e4f8c4dbd83f12141c0c35202ab Author: Jan Hauffa Date: Sat Apr 23 18:08:28 2011 +0200 Store size of shading table in ASIC structure. commit ed1997b22f5f11ccc96262ed841f03b705982737 Author: Jan Hauffa Date: Sat Apr 23 17:22:15 2011 +0200 Do not test for NULL before calling free(). commit 35c6a52834271e41960030b0c24f8cda2245230d Author: Jan Hauffa Date: Sat Apr 23 15:28:26 2011 +0200 Fix error propagation in mustek_usb2_high.c and a layering violation. commit babee5168909c8c3b8d01c36ab509ea4f7092c4f Author: Jan Hauffa Date: Thu Apr 21 23:25:34 2011 +0200 Fix indentation of debug macros. commit c0e44738a41c2cd772125d0774772a541dbac7c5 Author: Jan Hauffa Date: Thu Apr 21 23:23:18 2011 +0200 Simplify debug output in mustek_usb2.c. commit c377a0245332df3f5e07c3cbd5ead889f18e0549 Author: Jan Hauffa Date: Thu Apr 21 23:10:08 2011 +0200 Simplify debug output in mustek_usb2_high.c. commit eebbe92c4e73922f1fa1368852a77697c23a1ad1 Author: Jan Hauffa Date: Thu Apr 21 22:45:21 2011 +0200 Simplify debug logging in mustek_usb2_asic.c. commit 2c712f27c90109e2106d7e8d2f5eeb5af6314260 Author: Jan Hauffa Date: Thu Apr 21 00:12:26 2011 +0200 Remove uninformative function name prefixes, move gamma table creation into separate function. commit c1dc16d709459e054f50604f86f1ee41c0e7177f Author: Jan Hauffa Date: Wed Apr 20 23:10:53 2011 +0200 Extensive changes to reduce the amount of global variables in mustek_usb2_high.c. Might have made MustScanner_SetupScan less readable, though. commit 9444bf1156f0ab52937d101ba6120ae8685b645b Author: Jan Hauffa Date: Sun Apr 17 22:54:14 2011 +0200 Reorganize some MustScanner_* functions. commit bd7107ca057b1f45313d96114c6376bb5ee7c200 Author: Jan Hauffa Date: Sun Apr 17 22:29:32 2011 +0200 Remove some unneeded global variables from mustek_usb2_high.c. commit 589d6e15eee356121582eae90d7a938ff094c1e6 Author: Jan Hauffa Date: Sun Apr 17 21:57:18 2011 +0200 Endian-safe macros; moved remaining ASIC state into structure. commit f89a7962deafc3b015700469bc2976ac1b931165 Author: Jan Hauffa Date: Sun Apr 17 21:00:26 2011 +0200 Fix indentation. commit df045634cb6a9667c625fb88ecb36bcb58310cda Author: Jan Hauffa Date: Sun Apr 17 19:14:53 2011 +0200 Misc fixes. commit 86f399bd21d7794ba07265b503fea39baa1bb859 Author: Jan Hauffa Date: Sun Apr 17 19:00:30 2011 +0200 Code in mustek_usb2.c should not use global state of mustek_usb2_high.c. commit 74effd61fd8c9663b994459e8f5a738cc95c4932 Author: Jan Hauffa Date: Sun Apr 17 18:25:00 2011 +0200 Remove histogram stretching for negative images. commit 4962b35abd7426b7b51a00d907a538a2a38dc859 Author: Jan Hauffa Date: Sun Apr 17 15:56:40 2011 +0200 Use prefix 'p' instead of 'lp', fix other style issues. commit 9e2aabc97690baae4dd5a7d79d5e7d18df2cf697 Author: Jan Hauffa Date: Sun Apr 17 15:27:14 2011 +0200 If g_isCanceled is true, the thread has already been canceled. commit a75bd3e8f789435ac5d86ef100dd04e8bd155f76 Author: Jan Hauffa Date: Sun Apr 17 15:18:58 2011 +0200 Improve error handling in mustek_usb2_high.c. commit 1d0f3ca42ee9d84bd4afc2f379e46bc6a376de96 Author: Jan Hauffa Date: Sun Apr 17 14:51:01 2011 +0200 Fix remaining comments. commit 9226162537706c982405a7469e7003c4d61808e0 Author: Jan Hauffa Date: Sun Apr 17 14:23:46 2011 +0200 Normalize naming of constants, structures, and enums. commit d7ebb1553b8e28a9291493aa94003737f0c87298 Author: Jan Hauffa Date: Sun Apr 17 13:48:45 2011 +0200 Remove USB host type enum. commit 41ac627e5f4dbd84c082d1756414ef9922c294e7 Author: Jan Hauffa Date: Sun Apr 17 13:45:42 2011 +0200 Get rid of unnecessary forward declarations. commit da64a1fc1efd8a2e8b8245d6101deb103eea1dc4 Author: Jan Hauffa Date: Sat Apr 16 21:37:20 2011 +0200 First hack to build mustek_usb2* source files separately. commit 3479acf538335e1290ca00a5e5fef3097a835579 Author: Jan Hauffa Date: Sat Apr 16 20:24:26 2011 +0200 Merge mustek_usb2_reflective/transparent.c into mustek_usb2_high.c. commit a45931dd11e5fd270d963c5d4e1b882fa3755c90 Author: Jan Hauffa Date: Fri Apr 15 20:12:28 2011 +0200 Remove MustScanner_GetScannerState. commit c9516d53656ed5a7e45dc63b1f2202c96269a7ef Author: Jan Hauffa Date: Wed Apr 13 00:22:06 2011 +0200 Merge Reflective_Reset, Transparent_Reset, and MustScanner_Prepare into new function MustScanner_Reset. commit b2f52afa321331bf5214cdfe00d15ef479b88651 Author: Jan Hauffa Date: Sun Apr 10 18:53:37 2011 +0200 Further cleanup of mustek_usb2.c. commit ccce2d4a9a9e2762f8802af051db3f9ed2922ac8 Author: Jan Hauffa Date: Sun Apr 10 18:42:05 2011 +0200 Further cleanup of mustek_usb2.c. commit 39141a4c0265d97fe4d77084a5a63eaaafd8b8c4 Author: Jan Hauffa Date: Wed Mar 30 20:57:54 2011 +0200 Return SANE_STATUS_UNSUPPORTED unconditionally in sane_set_io_mode and sane_get_select_fd. commit d9c1df0bb84bffb23ee54be2fbd977e2a18ff4ed Author: Jan Hauffa Date: Wed Mar 30 19:41:05 2011 +0200 Remove vestigial support for custom gamma tables. commit acf84e0c9474382d78ae85120c2671b5525bd079 Author: Jan Hauffa Date: Tue Mar 29 18:25:19 2011 +0200 Clean up function StopScan. commit 9158d10df92b7d96bda66d9e601f248c5474259f Author: Jan Hauffa Date: Sat Mar 19 14:55:33 2011 +0100 Further simplification of MustScanner_Get*Line functions. commit 1f6b405451fda5fe349df1653e3423e8fc360e3b Author: Jan Hauffa Date: Sat Mar 19 14:14:30 2011 +0100 First attempt at simplifying the Get*Line functions. commit a6b15f18ccc430db08c638510bcd603d569723ee Author: Jan Hauffa Date: Mon Mar 14 00:50:30 2011 +0100 Break remaining long lines. commit 25242ff9c85f06275ca190896fe37b6d8902e122 Author: Jan Hauffa Date: Mon Mar 14 00:21:44 2011 +0100 Clean up mustek_usb2_high.c. commit c8982a99392cb7c982f12201a978fb4ae5e9e15a Author: Jan Hauffa Date: Sun Mar 13 21:13:26 2011 +0100 Do not use prefix "by" for byte variable names. commit d7b4e02780acd916ebbdd1cf8a9cc99945ea1acd Author: Jan Hauffa Date: Sun Mar 13 21:07:55 2011 +0100 Use SANE_Status and SANE_TRUE/SANE_FALSE consistently. commit 8b3c78838ae099d0099b54fbd640c0db1bb3b88c Author: Jan Hauffa Date: Sun Mar 13 20:06:24 2011 +0100 Create common helper function for Asic_CarriageHome and Asic_MotorMove, remove MotorBackHome. commit ed5dc8a7cdfb7c32faff37e7ea23446b5de9fc41 Author: Jan Hauffa Date: Sun Mar 13 19:41:40 2011 +0100 Further refactoring of Asic_SetWindow. commit 82a40d5dca84990f41c15998ae89425eaa576ff6 Author: Jan Hauffa Date: Sun Mar 13 19:24:17 2011 +0100 Refactoring of Asic_SetWindow. commit 93a79af5d3322fd06369c59a7e72f6773f9bed52 Author: Jan Hauffa Date: Sun Mar 13 15:54:02 2011 +0100 Fix indentation. commit b43f0688dbb309b7841e89074aab00d4aa61c3a2 Author: Jan Hauffa Date: Sun Mar 13 15:15:47 2011 +0100 Use symbolic constants in more places. commit 3c87b646b5831b24e6d9d13f26f2a08ec83b6cff Author: Jan Hauffa Date: Sun Mar 13 14:48:40 2011 +0100 First attempt at merging Asic_SetCalibrate into Asic_SetWindow. commit 033ebe6d9b6db266fb8146a4ac17d82043b5636a Author: Jan Hauffa Date: Sat Mar 12 19:25:59 2011 +0100 Made error handling in mustek_usb2_asic.c more consistent. commit 96c6ee1dae3dffe2eae9cf3466a0d246d9e3317d Author: Jan Hauffa Date: Sat Mar 12 16:20:36 2011 +0100 Cleaned up firmware state handling. commit c1f22ef9a9a3be1db26fc03721156a72156870b5 Author: Jan Hauffa Date: Sat Mar 12 14:18:48 2011 +0100 Clean up Asic_SetCalibrate, make Asic_SetCalibrate and Asic_SetWindow more similar. commit 3cd05daccad6bb1e50cc4030c0b471ed00897367 Author: Jan Hauffa Date: Sat Mar 12 02:13:34 2011 +0100 Refactoring the smaller high level ASIC functions. commit de5b647c4a47938f186b4661615dfbbd3315636d Author: Jan Hauffa Date: Fri Mar 11 23:48:21 2011 +0100 Refactored medium level ASIC functions. commit 693da258ce3bbcaf5c8ea31b9a08b77af615c0f2 Author: Jan Hauffa Date: Fri Mar 11 18:36:07 2011 +0100 Move some definitions from mustek_usb2_asic.h to more appropriate headers. commit 2776b336d15b0e8094271c69dfda7055cd1d896b Author: Jan Hauffa Date: Fri Mar 11 18:17:54 2011 +0100 Simplify LLFSetMotorCurrentAndPhase. commit dea59ee824157d33c64df719869ee937749f5428 Author: Jan Hauffa Date: Fri Mar 11 17:44:11 2011 +0100 Refactored all low-level motor functions except LLFSetMotorCurrentAndPhase. commit e47fee8dcc88ef4fc3e68ed65def29aacb56d17d Author: Jan Hauffa Date: Fri Mar 11 16:27:03 2011 +0100 Simplified computation of motor current, removed a redundant register assignment. commit 5688a78ace501c9a0ca36cee5f67a5929d652e81 Author: Jan Hauffa Date: Fri Mar 11 16:08:35 2011 +0100 Simplify low-level ASIC functions, add missing error checks. commit 1d8a008856d049df910b1d68599a622986ce85c4 Author: Jan Hauffa Date: Fri Mar 11 14:25:09 2011 +0100 Simplify SetRWSize, use symbolic constants for registers whenever possible. commit 794b15ff9e1daf87b80898aade0dc401e1f597d8 Author: Jan Hauffa Date: Fri Mar 11 13:38:40 2011 +0100 Simplyfied Asic_SetShadingTable. commit 6d5a5123ea3c41ada76e984670b988f847de2145 Author: Jan Hauffa Date: Fri Mar 11 13:12:31 2011 +0100 Remove whitespace at the end of debug output lines. commit d418094b64ad7ae2558860568c3e1e28a5a6cbc7 Author: Jan Hauffa Date: Fri Mar 11 13:08:03 2011 +0100 Some motor table related fixes. commit 3d1b409a1b526025c52c314f143cedd4d2d5d05f Author: Jan Hauffa Date: Fri Mar 11 02:28:14 2011 +0100 Fix a few comments. commit 88cac5b4ade1ad4ace0da5be843c879e9256c71c Author: Jan Hauffa Date: Fri Mar 11 02:25:43 2011 +0100 Begin simplifying LLFSetMotorCurrentAndPhase, ensure all fields of LLF_MOTOR_CURRENT_AND_PHASE are initialized. commit fb55a9260404049e00f13e627d7e3c8e06b397b8 Author: Jan Hauffa Date: Fri Mar 11 02:08:46 2011 +0100 Remove even more unused code from mustek_usb2_asic.c. commit 77ea9b01c374833e061ecee271d81a37f38dad77 Author: Jan Hauffa Date: Fri Mar 11 00:07:43 2011 +0100 Improved readability of functions in mustek_usb2_high.c. commit ca1e0db16f6aeb5c92e2ddf08700981f6799fc4e Author: Jan Hauffa Date: Thu Mar 10 01:39:01 2011 +0100 Remove unused code and fix indentation in mustek_usb2_high.c. commit 3f7cf8a65f48447fbc70808229ef6d2f50c3e412 Author: Jan Hauffa Date: Wed Mar 9 01:56:04 2011 +0100 Remove DISABLE bit flag constants. commit 073fe96611477986de970ab0c444f73024ecea33 Author: Jan Hauffa Date: Wed Mar 9 01:26:09 2011 +0100 LLF_MOTOR_CURRENT_AND_PHASE: only first byte of arrays MotorCurrentTableA/B is ever used commit 4b242a71394221a2155379b8e89340610a8ed725 Author: Jan Hauffa Date: Wed Mar 9 01:18:10 2011 +0100 Remove unused parameter isOrderInvert from MustScanner_GetMono*Line. commit 78863d13deacf657ef15b6078d0926fadbd9991a Author: Jan Hauffa Date: Wed Mar 9 01:05:41 2011 +0100 Remove redundant typecasts. commit cf6c88bfd1debd288ca563b54120e8ff3903f634 Author: Jan Hauffa Date: Wed Mar 9 00:41:21 2011 +0100 Try to reduce differences between mustek_usb2_reflective.c and mustek_usb2_transparent.c, part 1. commit 972fc54793d767a6cd18c722ae36feb408f45f9f Author: Jan Hauffa Date: Wed Mar 9 00:02:06 2011 +0100 Move some code that was duplicated in mustek_usb2_transparent.c and mustek_usb2_reflective.c to mustek_usb2_high.c. commit db37c13bb337c153ddd83902b8c9ad0b4a445c2a Author: Jan Hauffa Date: Tue Mar 8 23:10:57 2011 +0100 Remove information-less comments, break long lines, fix indentation. commit fa8101e05e0432a385e782acd663ce56e0c00367 Author: Jan Hauffa Date: Tue Mar 8 18:37:55 2011 +0100 Remove unused enum FS_NULL. commit ccde6b063555892ae55ac6c7bfeb8a7d44e02a4e Author: Jan Hauffa Date: Tue Mar 8 18:29:13 2011 +0100 Remove unused fields of struct GETPARAMETERS. commit 2be2be76aec39dbef8bbe0501eabaaf0838b3cbc Author: Jan Hauffa Date: Tue Mar 8 18:26:32 2011 +0100 Unified style of struct and enum definitions. commit ce6d7010d3fc0bfc5a54cd3411660db43e382bac Author: Jan Hauffa Date: Tue Mar 8 18:15:30 2011 +0100 Pixel flavor is never PF_WhiteIs0, so the associated code can be removed. commit 76a23c3bc4c80f91f223f29ae8cc5c91a1a8e4f8 Author: Jan Hauffa Date: Sun Mar 6 20:31:48 2011 +0100 Remove dead "auto level" code, sanitize key handling. commit e7c44fe6799e5c1d4bce272b539927337b7a2aca Author: Jan Hauffa Date: Sun Mar 6 20:19:27 2011 +0100 Cleanup of Asic_SetWindow commit 16485d47da8b2d0a829e378afa1443c1ef4839f8 Author: Jan Hauffa Date: Sun Mar 6 19:37:25 2011 +0100 Optimize motor table calculation. commit 8821c2882f51d309a7832b362407c46ff11ccd4a Author: Jan Hauffa Date: Sun Mar 6 19:16:16 2011 +0100 First attempt at cleaning up mustek_usb2_asic.c. commit 30087b3f43f4e6f2dd83373145dbe0a533b27419 Author: Jan Hauffa Date: Sun Mar 6 17:06:14 2011 +0100 Avoid some unorthodox language constructs. commit 030c7fa122dccca2f47c949ca46a5972efca20b8 Author: Jan Hauffa Date: Sun Mar 6 16:55:39 2011 +0100 Remove redundant code from mustek_usb2_high.c. commit a554d61c17206e6b1585bacdfd41fe4aacea1a95 Author: Jan Hauffa Date: Sun Mar 6 16:18:18 2011 +0100 Remove redundant code from mustek_usb2_asic.c, add a missing error check. commit a49bff1a60386c88168d9aa8a94cdc0ccecac7fd Author: Jan Hauffa Date: Sun Mar 6 15:39:23 2011 +0100 Simplify DRAM test. commit bc9252c09464b7ed460bf726dcca3d67f97cd74d Author: Jan Hauffa Date: Sun Mar 6 15:27:19 2011 +0100 Remove bogus automatic warmup and power saving functions. commit 0f63d16121ea84f99f75331582c3bdd0cd0d4e1f Author: Jan Hauffa Date: Sun Mar 6 15:13:46 2011 +0100 Remove redundant code from mustek_usb2.c. commit 694a69dcab0dddf2ab12eebba49c66c7ac20fdad Author: Jan Hauffa Date: Sun Mar 6 14:48:40 2011 +0100 Remove unused definitions from mustek_usb2.h. commit 21be236e840be4f8ca4bead69844f7cd691a8353 Author: Jan Hauffa Date: Sun Mar 6 13:57:10 2011 +0100 Remove unused definitions from mustek_usb2_asic.h. commit 2404326ddeaf7552e094062b1ed57521e9a21cb4 Author: Jan Hauffa Date: Sun Mar 6 02:41:42 2011 +0100 Remove unused definitions from mustek_usb2_high.h and ensure that the remaining ones are used consistently. commit d1851a6512a113d1dc4f20beb86a8be29310b627 Author: Jan Hauffa Date: Sun Mar 6 01:50:53 2011 +0100 Remove some particularly pointless comments, reduce size of block comments. commit 047631050c262142a0f52ed4e1ecc053b03869ad Author: Jan Hauffa Date: Sun Mar 6 01:15:12 2011 +0100 Remove pointless indirection. commit dedf0ac30d341b9bcbab7fb32050ff953cc73eff Author: Jan Hauffa Date: Sun Mar 6 01:03:14 2011 +0100 Remove unused global variable g_pDeviceFile and associated logic. commit 3b73e1e8a3b0085ad5db38837f0bf44f5a5b8919 Author: m. allan noah Date: Sun Nov 8 09:24:37 2015 -0500 fujitsu backend v128 do not ask fi-4340 for serial number commit 72ecee97ce9db13f148aedf52eb46911212d58e4 Author: Thomas Klausner Date: Tue Oct 27 20:06:00 2015 +0900 Add DragonFly BSD support (fixes 315205) commit a4cc05f677f110c9361f3274fc5d15087a2f8906 Author: Thomas Klausner Date: Tue Oct 27 20:09:00 2015 +0900 Add DragonFly BSD support to sane-find-scanner (fixes 315206) commit 1baab222e418275ec6fd14afad91b64d0110fdbd Author: Olaf Meeuwissen Date: Sun Nov 8 18:49:58 2015 +0900 Add missing include (fixes 315207) Both Linux and NetBSD mention this header for use of setsocketopt(). DragonFly BSD needs it for the SOL_SOCKET symbol. commit b0a99cb48938cae5a88c5f37a9a91b60589bad4e Author: Olaf Meeuwissen Date: Sun Nov 8 18:36:57 2015 +0900 Fix non-portable endian.h include issue (315209) commit d7516a11ebd6a8d96380c5ee256b171be1cb5e35 Author: Olaf Meeuwissen Date: Sun Nov 8 18:16:17 2015 +0900 Fix sane-desc testsuite logic This fixes test failures for release tarballs (pointed out by Mike Frysinger), clamps down on wildcards and prints a failure message when a test does not succeed. commit 358cbd7f319c64055cd76fedf62a92500b0c5cf5 Author: m. allan noah Date: Fri Nov 6 21:39:35 2015 -0500 canon_dr v53 continued reorder geometry group options use bg_color to fill missing image data commit 398610336b6aadf1a0c37390a0a5e2bd926bdfdf Author: m. allan noah Date: Fri Nov 6 12:19:20 2015 -0500 canon_dr backend v53 add swskip option commit b4bc0eb518ce74ffbfdbe0ce1a14bb404804cd57 Author: m. allan noah Date: Fri Nov 6 11:46:17 2015 -0500 canon_dr backend v53 replace image processing methods with sanei_magic commit 666c9a74ff26fd530b40db28f03b447209cf419e Author: m. allan noah Date: Thu Nov 5 21:42:29 2015 -0500 canon_dr backend v52 improve dropout option handling add software dropout implementation for downsampled modes commit 9dc79245291f6d4312c5656fff4232b07f70b673 Author: m. allan noah Date: Wed Nov 4 13:49:02 2015 -0500 canon_dr backend v52 add must_downsample and must_fully_buffer commit 01063a769d5431ca83069a9cf240894f893d01f0 Author: m. allan noah Date: Wed Nov 4 13:05:05 2015 -0500 canon_dr backend v52 set can_color=1 by default (recent models dont have 'C' in name) enable jpeg for DR-6080 commit 0b822359b3e1798294e30a7ea9cfd6fd9a1e3e85 Author: m. allan noah Date: Wed Nov 4 13:00:10 2015 -0500 cardscan backend v3 add USB IDs for newer model 800c commit 33495ef9b42a783c8f5f2c056ac5699481d3cc7e Author: Luiz Angelo Daros de Luca Date: Thu Oct 15 12:35:00 2015 +0900 Add missing includes commit 4f803bff0872460433dae1ac2a2954ad1016b678 Author: Olaf Meeuwissen Date: Thu Oct 22 22:23:47 2015 +0900 Escape [] for configure help strings commit 471453d2b825a569d467d60160b0eaaf6746bf67 Author: Olaf Meeuwissen Date: Mon Oct 19 20:51:04 2015 +0900 Drop unused INCLUDES substitution variable This addresses the following autoreconf output: configure.ac:85: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS') The INCLUDES variable is not referenced anywhere in configure.ac or configure. In addition, none of the Makefile.am files use it. commit 32c25b8b8235762d9feb5dbd0e81496a56e15569 Author: Olaf Meeuwissen Date: Mon Oct 19 21:11:53 2015 +0900 Fix duplicate automake file variable initialization issue This was introduced in 74c00494. commit f8d35b8d2fdcacc9b664594d141102c2c80ac076 Author: m. allan noah Date: Mon Oct 26 08:34:17 2015 -0400 Update canon_dr.desc We had a few scanners that were reported by email or in tracker tickets, which had not been updated in the desc file. commit 716340e7320e7f946329ad7a3cd911d676c92f6d Author: Olaf Meeuwissen Date: Sat Oct 17 13:55:17 2015 +0900 Include sys/types.h for u_long. Fixes compile on OS X commit 03d90ac2edf287bb0358044d7abdd9f6008dffc5 Author: Alessandro Zummo Date: Wed Oct 14 21:55:31 2015 +0200 epsonds: do not enable double feed detection by default commit a90d7c91b36b06bd002af890863c1d608dcdd7d4 Author: Rolf Bensch Date: Wed Oct 14 19:05:03 2015 +0200 changelog for recent work commit 4a83d9c8a4f4c396f5261d62bf7d2f9b8684eba9 Author: Rolf Bensch Date: Wed Oct 14 19:04:27 2015 +0200 Pixma backend version 0.17.24 commit 3095ab46c45e004163f5fb36efa00ce378770a9e Author: Rolf Bensch Date: Wed Oct 14 19:02:43 2015 +0200 new scanners Canon PIXUS MP5/SmartBase MPC190/imageCLASS MPC190 and Canon MP10/SmartBase MPC200/imageCLASS MPC200 commit 06b865cfd24f1e6c71506684d73ef79b43edc3cf Author: Olaf Meeuwissen Date: Wed Oct 14 20:39:39 2015 +0900 Prevent possible buffer overflows [-Wstrncat-size]. Fixes 315198 commit 18e4c4a08622e2ee4536dcb423d4548a4bc7a7e3 Author: Olaf Meeuwissen Date: Tue Oct 13 23:32:40 2015 +0900 Revert "Prevent use of uninitialized variable" This change introduces a variable that shadows the file scope one. This reverts commit 45e66aee952dcdada88293901580a111262fc1e9. commit 36876a83663832cf89fa945737d004ce9b46fb01 Author: Olaf Meeuwissen Date: Mon Oct 12 20:55:19 2015 +0900 saned: minor improvement of help message wording commit 32986192bd9ce14276e1ae144d71d42461e591b9 Author: Olaf Meeuwissen Date: Mon Oct 12 20:42:50 2015 +0900 fix: declaration-after-statement warning commit 42aa01e4e558e0019df00702579c928f9fd126e6 Author: Olaf Meeuwissen Date: Mon Oct 12 20:42:01 2015 +0900 fix: missing-field-initializers warning commit fa001c2193045844dd3318f9538b309e11089c9c Author: Olaf Meeuwissen Date: Mon Oct 12 20:49:07 2015 +0900 Follow getopt_long usage in scanimage.c This is on the off chance that getopt_long is not in the system's standard library. commit 45e66aee952dcdada88293901580a111262fc1e9 Author: Olaf Meeuwissen Date: Mon Oct 12 20:47:43 2015 +0900 Prevent use of uninitialized variable commit eab8fd457d2b8f38f9425f87258cf4fe42dac15c Author: Matteo Croce Date: Sun Oct 11 19:50:04 2015 +0200 saned: add '-b' option to bind to a specific address commit fed2a2cf60511d87e413148f1b9063f9ea4e6917 Author: Matteo Croce Date: Sun Oct 11 19:50:03 2015 +0200 saned: use getopt_long() for option parsing The help message has been adjusted to match getopt_long conventions. commit 418d1ecea7571d10acd08df2edc7967a91e14b0d Author: Matteo Croce Date: Sun Sep 20 19:55:37 2015 +0200 saned: move help message to usage() function commit a79cd0abe7daed1a749c8ad2cd7e2a89cc6153e4 Author: Matteo Croce Date: Sun Sep 20 19:55:36 2015 +0200 saned: parse inetd args in main() move argument parsing logic from run_inetd() to main() commit 2c3cb206ce55a7ac9ff9b479de452a332ba2aa1a Author: Matteo Croce Date: Sun Sep 20 19:55:35 2015 +0200 saned: parse standalone args in main() move argument parsing logic from run_standalone() to main() commit 2239d2aaff16964a5d67293f5e4220d235e2c84d Author: Alexander Hofmann Date: Tue Oct 6 17:42:05 2015 +0200 Replace obsolete interface with standard include files commit 56e69f0998005db432b4f7dd38693a870f663520 Author: m. allan noah Date: Mon Oct 5 08:21:39 2015 -0400 added kvs1025.conf.in and utsushi.desc commit 69a9a3116eb18f8d0c618217e033a1c134215954 Author: m. allan noah Date: Sun Oct 4 21:25:08 2015 -0400 minor release doc update commit 5e1d45cad7d7933b7120646ae5174ccdc8a9b49f Author: m. allan noah Date: Sun Oct 4 21:13:39 2015 -0400 reopen sane-backends 1.0.26git sane-backends-1.0.27/missing0000775000175000017500000001533012775312262012632 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sane-backends-1.0.27/Makefile.in0000664000175000017500000010073713110564732013301 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(top_srcdir)/include/sane/config.h.in mkinstalldirs ABOUT-NLS \ $(dist_doc_DATA) COPYING ar-lib compile config.guess \ config.rpath config.sub depcomp install-sh missing ltmain.sh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(docdir)" DATA = $(dist_doc_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = include lib sanei backend frontend tools doc po testsuite DIST_SUBDIRS = include lib sanei backend frontend tools doc po japi testsuite dist_doc_DATA = AUTHORS ChangeLog COPYING LICENSE NEWS PROBLEMS PROJECTS \ README README.aix README.beos README.darwin README.djpeg README.freebsd \ README.hp-ux README.linux README.netbsd README.openbsd README.os2 \ README.solaris README.unixware2 README.unixware7 README.windows \ README.zeta EXTRA_DIST = $(PACKAGE).lsm # # Keep the .gitignore files sorted, and use this target to do it. # Note that git's negated ignore patterns introduce order dependency # and should therefor be sorted with much more care than we do here. # Until that has been taken care of, such files are best left alone. # PERL = perl ACLOCAL_AMFLAGS = -I m4 all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): include/sane/config.h: include/sane/stamp-h1 @test -f $@ || rm -f include/sane/stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) include/sane/stamp-h1 include/sane/stamp-h1: $(top_srcdir)/include/sane/config.h.in $(top_builddir)/config.status @rm -f include/sane/stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status include/sane/config.h $(top_srcdir)/include/sane/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f include/sane/stamp-h1 touch $@ distclean-hdr: -rm -f include/sane/config.h include/sane/stamp-h1 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-dist_docDATA: $(dist_doc_DATA) @$(NORMAL_INSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-dist_docDATA: @$(NORMAL_UNINSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(docdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-local distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dist_docDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: installcheck-local maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-dist_docDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool clean-local cscope cscopelist-am ctags ctags-am \ dist dist-all dist-bzip2 dist-gzip dist-lzip dist-shar \ dist-tarZ dist-xz dist-zip distcheck distclean \ distclean-generic distclean-hdr distclean-libtool \ distclean-local distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-dist_docDATA install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installcheck-local installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-dist_docDATA sort-gitignore: for f in `find . -name .gitignore`; do \ if test -n "`sed -n '/^\!/p' $$f`"; then \ echo "$$f: skipping file with negated pattern" >&2; \ fi; \ $(PERL) -e 'print sort <>;' < $$f > $$f.tmptmp; \ mv $$f.tmptmp $$f; \ done # # Check to make sure only sane_ and sanei_ symbols are exported from # the libraries # libcheck: @echo "Libraries exporting 'illegal' symbols:" @for lib in backend/.libs/*.so backend/.libs/*.a; do \ lines=`nm -g $$lib|grep '\( T \)\|\( D \)'|egrep -v ' _fini| _init'|egrep -v ' sane_| sanei_'`; \ if test -n "$$lines" ; then \ echo -e "*** $$lib:\n$$lines"; \ found_errors="yes"; \ fi \ done; \ echo; \ echo "Libraries exporting 'non-standard sane_*' symbols:"; \ for lib in backend/.libs/*.so backend/.libs/*.a; do \ lines=`nm -g $$lib|grep '\( T \)\|\( D \)'|egrep ' sane_' | egrep -v 'sane_.*init|sane_.*exit|sane_.*get_devices|sane_.*open|sane_.*close|sane_.*get_option_descriptor|sane_.*control_option|sane_.*get_parameters|sane_.*start|sane_.*read|sane_.*cancel|sane_.*set_io_mode|sane_.*get_select_fd|sane_strstatus'` ; \ if test -n "$$lines" ; then \ echo -e "*** $$lib:\n$$lines"; \ found_errors="yes"; \ fi \ done; if test ! -z $$found_errors ; then \ exit 1; \ fi # Verify that backends do not contain any unwanted public symbols # anytime check or distcheck is ran. # TODO: Currently this doesn't pass. Uncomment once symbols have # been cleaned up. #check-am: libcheck # Run testsuite any time installcheck or distcheck is ran. # Must run testsuite after install or else shared library backends # will not be found (including test backend). installcheck-local: cd testsuite && $(MAKE) test.local $(distdir).lsm: dist $(PACKAGE).lsm ( cat $(PACKAGE).lsm | \ sed -e "s|_DATE_|`date +%d%b%y`|g" |\ sed -e "s|_VERSION_|$(VERSION)|g" | \ sed -e "s|_T_S_|`find $(distdir).tar.gz -printf "%4k"`|g" |\ sed -e "s|_L_S_|`find $(PACKAGE).lsm -printf "%4k"`|g" >\ $(distdir).lsm \ ) lsm: $(distdir).lsm md5: dist md5sum $(distdir).tar.gz > $(distdir).tar.gz.md5 sane-backends: lsm md5 # Clean files created by custom targets in this file. clean-local: rm -f sane-backends-*.lsm rm -f $(distdir).tar.gz.md5 # Clean files created by configure distclean-local: rm -f include/_stdint.h rm -f include/byteorder.h # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/README.zeta0000664000175000017500000000144412112021330013030 00000000000000SANE and Zeta ------------- The Zeta port is based on existing BeOS port, with some changes to accomodate yellowTAB's internal build procedure, and some new conventions brought up by Zeta. Cf. README.beos for more historical stuff. SANE 1.0.9 was updated for Zeta by Ithamar Adema for yellowTAB. SANE 1.0.15 was updated for BeOS and Zeta by François Revol for yellowTAB. Zeta uses a modified version of Philippe Houdoin's Sanity GUI frontend. http://philippe.houdoin.free.fr/phil/beos/sanity/index-en.html SANE was reported to work with the following configuration and features: Platform: Zeta R1 (== BeOS R6.x) ix86 Latest SANE version tested: 1.0.15 Compiler: gcc 2.95.3 User-level SCSI support: yes USB support: yes Shared library support: yes Dynamic loading support: yes X11 clients: no sane-backends-1.0.27/INSTALL0000664000175000017500000003661012775312260012266 00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command `./configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. sane-backends-1.0.27/README.darwin0000664000175000017500000000406012112021330013346 00000000000000SANE and Darwin (Mac OS X) -------------------------- Building: --------- You may get the message: "gcc: Internal compiler error: program cc1obj got fatal signal 11". That's not a bug in SANE. Probably a compiler or hardware problem. The error usually occurs in canon.c because that's the most complex backend (at least concerning compilation). If you can't update your compiler, try to reduce optimization (e.g. CFLAGS="-O1" ./configure). Another work-around: Disable the canon backend in backend/Makefile.in (look at PRELOADABLE_BACKENDS) and rerun configure. General: -------- If scanimage -L (or any other frontend) stops with a segmentation fault in the sm3600 backend, disable sm3600 in dll.conf if you don't need it. Backends that use the function "fork" may not work at least with USB scanners. That's a limitation of MacOS X (doesn't use file descriptors for USB access). Most backends have been modified to use threads on MacOS X and should work. Others don't use fork at all. Both types of backends should work with MacOS X. Changing the backends to use threads is an ongoing effort. SCSI-scanners and Firewire scanners: ------------------------------------ There is support for SCSI and Firewire scanners but hasn't had much testing. Please send failure and success reports to the sane-devel mailing list. At least the Epson Perfection 1640SU and the CANON IX-06015C (CanoScan 600) are reported to work. USB-scanners: ------------- Work with libusb. Try "sane-find-scanner -v -v" and report success or failure to the SANE mailing list. At least the following scanners are known to work: UMAX Astra 1220U and 2000U, Epson Perfection 1640SU and 2450 Photo. Use libusb version 0.1.11 or later (or a cvs checkout from 2005-09-01 or later). If you use earlier versions the libusb code needs to be patched. Parport-scanners: ----------------- I don't have any information about these. Please contact me or the SANE mailing list if you succeeded in using one of these. 2003-12-26 Henning Meier-Geinitz 2005-05-07 Mattias Ellert sane-backends-1.0.27/sanei/0000775000175000017500000000000013110600530012366 500000000000000sane-backends-1.0.27/sanei/sanei_config.c0000664000175000017500000002655112617742237015135 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Jeffrey S. Freedman This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file provides generic configuration support. */ #include "../include/sane/config.h" #include #include #include #include #include #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #define BACKEND_NAME sanei_config #include "../include/sane/sanei_debug.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #if defined(_WIN32) || defined(HAVE_OS2_H) # define DIR_SEP ";" # define PATH_SEP '\\' #else # define DIR_SEP ":" # define PATH_SEP '/' #endif #define DEFAULT_DIRS "." DIR_SEP STRINGIFY(PATH_SANE_CONFIG_DIR) #ifdef __BEOS__ #include #endif static char *dir_list; const char * sanei_config_get_paths () { #ifdef __BEOS__ char result[PATH_MAX]; #endif void *mem; char *dlist; size_t len; if (!dir_list) { DBG_INIT(); dlist = getenv ("SANE_CONFIG_DIR"); if (dlist) dir_list = strdup (dlist); #ifdef __BEOS__ /* ~/config/settings/SANE takes precedence over /etc/sane.d/ */ if (!dir_list) { if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, true, result, PATH_MAX) == B_OK) { strcat(result,"/SANE"); strcat(result,DIR_SEP); /* do append the default ones */ dir_list = strdup (result); } } #endif if (dir_list) { len = strlen (dir_list); if ((len > 0) && (dir_list[len - 1] == DIR_SEP[0])) { /* append default search directories: */ mem = malloc (len + sizeof (DEFAULT_DIRS)); memcpy (mem, dir_list, len); memcpy ((char *) mem + len, DEFAULT_DIRS, sizeof (DEFAULT_DIRS)); free (dir_list); dir_list = mem; } } else { /* Create a copy, since we might call free on it */ dir_list = strdup (DEFAULT_DIRS); } } DBG (5, "sanei_config_get_paths: using config directories %s\n", dir_list); return dir_list; } FILE * sanei_config_open (const char *filename) { char *next, *dir, result[PATH_MAX]; const char *cfg_dir_list; FILE *fp; char *copy; cfg_dir_list = sanei_config_get_paths (); if (!cfg_dir_list) { DBG(2, "sanei_config_open: could not find config file `%s'\n", filename); return NULL; } copy = strdup (cfg_dir_list); for (next = copy; (dir = strsep (&next, DIR_SEP)) != 0; ) { snprintf (result, sizeof (result), "%s%c%s", dir, PATH_SEP, filename); DBG(4, "sanei_config_open: attempting to open `%s'\n", result); fp = fopen (result, "r"); if (fp) { DBG(3, "sanei_config_open: using file `%s'\n", result); break; } } free (copy); if (!fp) DBG(2, "sanei_config_open: could not find config file `%s'\n", filename); return fp; } const char * sanei_config_skip_whitespace (const char *str) { while (str && *str && isspace (*str)) ++str; return str; } const char * sanei_config_get_string (const char *str, char **string_const) { const char *start; size_t len; str = sanei_config_skip_whitespace (str); if (*str == '"') { start = ++str; while (*str && *str != '"') ++str; len = str - start; if (*str == '"') ++str; else start = 0; /* final double quote is missing */ } else { start = str; while (*str && !isspace (*str)) ++str; len = str - start; } if (start) *string_const = strndup (start, len); else *string_const = 0; return str; } char * sanei_config_read (char *str, int n, FILE *stream) { char* rc; char* start; int len; /* read line from stream */ rc = fgets( str, n, stream); if (rc == NULL) return NULL; /* remove ending whitespaces */ len = strlen( str); while( (0 < len) && (isspace( str[--len])) ) str[len] = '\0'; /* remove starting whitespaces */ start = str; while( isspace( *start)) start++; if (start != str) do { *str++ = *start++; } while( *str); return rc; } SANE_Status sanei_configure_attach (const char *config_file, SANEI_Config * config, SANE_Status (*attach) (SANEI_Config * config, const char *devname)) { SANE_Char line[PATH_MAX]; SANE_Char *token, *string; SANE_Int len; const char *lp, *lp2; FILE *fp; SANE_Status status = SANE_STATUS_GOOD; int i, j, count; void *value = NULL; int size=0; SANE_Bool found; SANE_Word *wa; SANE_Bool *ba; DBG (3, "sanei_configure_attach: start\n"); /* open configuration file */ fp = sanei_config_open (config_file); if (!fp) { DBG (2, "sanei_configure_attach: couldn't access %s\n", config_file); DBG (3, "sanei_configure_attach: exit\n"); return SANE_STATUS_ACCESS_DENIED; } /* loop reading the configuration file, all line beginning by "option " are * parsed for value to store in configuration structure, other line are * used are device to try to attach */ while (sanei_config_read (line, PATH_MAX, fp) && status == SANE_STATUS_GOOD) { /* skip white spaces at beginning of line */ lp = sanei_config_skip_whitespace (line); /* skip empty lines */ if (*lp == 0) continue; /* skip comment line */ if (line[0] == '#') continue; len = strlen (line); /* delete newline characters at end */ if (line[len - 1] == '\n') line[--len] = '\0'; lp2 = lp; /* to ensure maximum compatibility, we accept line like: * option "option_name" "option_value" * "option_name" "option_value" * So we parse the line 2 time to find an option */ /* check if it is an option */ lp = sanei_config_get_string (lp, &token); if (strncmp (token, "option", 6) == 0) { /* skip the "option" token */ free (token); lp = sanei_config_get_string (lp, &token); } /* search for a matching descriptor */ i = 0; found = SANE_FALSE; while (config!=NULL && i < config->count && !found) { if (strcmp (config->descriptors[i]->name, token) == 0) { found = SANE_TRUE; switch (config->descriptors[i]->type) { case SANE_TYPE_INT: size=config->descriptors[i]->size; value = malloc (size); wa = (SANE_Word *) value; count = config->descriptors[i]->size / sizeof (SANE_Word); for (j = 0; j < count; j++) { lp = sanei_config_get_string (lp, &string); if (string == NULL) { DBG (2, "sanei_configure_attach: couldn't find a string to parse"); return SANE_STATUS_INVAL; } wa[j] = strtol (string, NULL, 0); free (string); } break; case SANE_TYPE_BOOL: size=config->descriptors[i]->size; value = malloc (size); ba = (SANE_Bool *) value; count = config->descriptors[i]->size / sizeof (SANE_Bool); for (j = 0; j < count; j++) { lp = sanei_config_get_string (lp, &string); if (string == NULL) { DBG (2, "sanei_configure_attach: couldn't find a string to parse"); return SANE_STATUS_INVAL; } if ((strcmp (string, "1") == 0) || (strcmp (string, "true") == 0)) { ba[j] = SANE_TRUE; } else { if ((strcmp (string, "0") == 0) || (strcmp (string, "false") == 0)) ba[j] = SANE_FALSE; else { DBG (2, "sanei_configure_attach: couldn't find a valid boolean value"); return SANE_STATUS_INVAL; } } free (string); } break; case SANE_TYPE_FIXED: size=config->descriptors[i]->size; value = malloc (size); wa = (SANE_Word *) value; count = config->descriptors[i]->size / sizeof (SANE_Word); for (j = 0; j < count; j++) { lp = sanei_config_get_string (lp, &string); if (string == NULL) { DBG (2, "sanei_configure_attach: couldn't find a string to parse"); return SANE_STATUS_INVAL; } wa[j] = SANE_FIX(strtod (string, NULL)); free (string); } break; case SANE_TYPE_STRING: sanei_config_get_string (lp, &string); if (string == NULL) { DBG (2, "sanei_configure_attach: couldn't find a string value to parse"); return SANE_STATUS_INVAL; } value = string; size=strlen(string)+1; if(size>config->descriptors[i]->size) { size=config->descriptors[i]->size-1; string[size]=0; } break; default: DBG (1, "sanei_configure_attach: incorrect type %d for option %s, skipping option ...\n", config->descriptors[i]->type, config->descriptors[i]->name); } /* check decoded value */ status = sanei_check_value (config->descriptors[i], value); /* if value OK, copy it in configuration struct */ if (status == SANE_STATUS_GOOD) { memcpy (config->values[i], value, size); } if (value != NULL) { free (value); value = NULL; } } if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_configure_attach: failed to parse option '%s', line '%s'\n", token, line); } i++; } free (token); /* not detected as an option, so we call the attach function * with it */ if (!found && status == SANE_STATUS_GOOD) { /* if not an option, try to attach */ /* to avoid every backend to depend on scsi and usb functions * we call back the backend for attach. In turn it will call * sanei_usb_attach_matching_devices, sanei_config_attach_matching_devices * or other. This means 2 callback functions per backend using this * function. */ DBG (3, "sanei_configure_attach: trying to attach with '%s'\n", lp2); if(attach!=NULL) attach (config, lp2); } } fclose (fp); DBG (3, "sanei_configure_attach: exit\n"); return status; } sane-backends-1.0.27/sanei/sanei_codec_bin.c0000664000175000017500000000715512206524362015563 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei_wire.h" #include "../include/sane/sanei_codec_bin.h" static void bin_w_byte (Wire *w, void *v) { SANE_Byte *b = v; sanei_w_space (w, 1); if (w->status) return; switch (w->direction) { case WIRE_ENCODE: *w->buffer.curr++ = *b; break; case WIRE_DECODE: *b = *w->buffer.curr++; break; case WIRE_FREE: break; } } static void bin_w_string (Wire *w, void *v) { SANE_Word len; SANE_String *s = v; if (w->direction != WIRE_DECODE) { len = 0; if (*s) len = strlen (*s) + 1; } sanei_w_array (w, &len, v, w->codec.w_byte, 1); if (w->direction == WIRE_DECODE) { if (len == 0) *s = 0; else if (w->status == 0) *(*s + len - 1) = '\0'; } } static void bin_w_word (Wire *w, void *v) { SANE_Word val, *word = v; sanei_w_space (w, 4); if (w->status) return; switch (w->direction) { case WIRE_ENCODE: val = *word; /* store in bigendian byte-order: */ w->buffer.curr[0] = (val >> 24) & 0xff; w->buffer.curr[1] = (val >> 16) & 0xff; w->buffer.curr[2] = (val >> 8) & 0xff; w->buffer.curr[3] = (val >> 0) & 0xff; w->buffer.curr += 4; break; case WIRE_DECODE: val = ( ((w->buffer.curr[0] & 0xff) << 24) | ((w->buffer.curr[1] & 0xff) << 16) | ((w->buffer.curr[2] & 0xff) << 8) | ((w->buffer.curr[3] & 0xff) << 0)); *word = val; w->buffer.curr += 4; break; case WIRE_FREE: break; } } void sanei_codec_bin_init (Wire *w) { w->codec.w_byte = bin_w_byte; w->codec.w_char = bin_w_byte; w->codec.w_word = bin_w_word; w->codec.w_string = bin_w_string; } sane-backends-1.0.27/sanei/sanei_pp.c0000664000175000017500000007750613106201017014271 00000000000000/* sane - Scanner Access Now Easy. * Copyright (C) 2003-2005 Gerhard Jaeger * based on work done by Jochen Eisinger * also parts from libieee1284 by Tim Waugh * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. * * This file implements an interface for accessing the parallelport */ /* debug levels: * 0 - nothing * 1 - errors * 2 - warnings * 3 - things nice to know * 4 - code flow * 5 - detailed flow * 6 - everything * * These debug levels can be set using the environment variable * SANE_DEBUG_SANEI_PP */ #include "../include/sane/config.h" #define BACKEND_NAME sanei_pp #define _TEST_LOOPS 1000 #define _MAX_PORTS 20 #ifndef _VAR_NOT_USED # define _VAR_NOT_USED(x) ((x)=(x)) #endif /* uncomment this to have some parameter checks on in/out functions, * note: that this will slow down the calls */ #if 0 # define _PARANOIA #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_LIMITS_H # include #else # ifndef ULONG_MAX # define ULONG_MAX 4294967295UL # endif #endif #if defined (ENABLE_PARPORT_DIRECTIO) # undef HAVE_LIBIEEE1284 # if defined(HAVE_SYS_IO_H) # if defined (__ICC) && __ICC >= 700 # define __GNUC__ 2 # endif # include # ifndef SANE_HAVE_SYS_IO_H_WITH_INB_OUTB # define IO_SUPPORT_MISSING # endif # if defined (__ICC) && __ICC >= 700 # undef __GNUC__ # elif defined(__ICC) && defined(HAVE_ASM_IO_H) # include # endif # elif defined(HAVE_ASM_IO_H) # include # elif defined(HAVE_SYS_HW_H) # include # elif defined(__i386__) && ( defined (__GNUC__) || defined (__ICC) ) static __inline__ void outb( u_char value, u_long port ) { __asm__ __volatile__ ("outb %0,%1"::"a" (value), "d" ((u_short) port)); } static __inline__ u_char inb( u_long port ) { u_char value; __asm__ __volatile__ ("inb %1,%0":"=a" (value):"d" ((u_short) port)); return value; } # endif #elif defined(HAVE_LIBIEEE1284) # include #else # pragma message "No I/O support for this architecture!" # define IO_SUPPORT_MISSING #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_pp.h" #if defined(STDC_HEADERS) # include # include # include #endif #if defined(HAVE_STRING_H) # include #elif defined(HAVE_STRINGS_H) # include #endif #if defined(HAVE_SYS_TYPES_H) # include #endif /** our global init flag... */ static int first_time = SANE_TRUE; static unsigned long pp_thresh = 0; #if (defined (HAVE_IOPERM) || defined (HAVE_LIBIEEE1284)) && !defined (IO_SUPPORT_MISSING) typedef struct { #ifndef HAVE_LIBIEEE1284 const char name[6]; u_long base; /**< i/o base address */ u_char ctrl; /**< for restoring CTRL register */ u_char ecp_ctrl; /**< for restoring ECP-CTRL register */ #endif u_int in_use; /**< port in use? */ u_int claimed; /**< port claimed? */ int caps; /**< port capabilities */ } PortRec, *Port; #if defined (HAVE_LIBIEEE1284) static struct parport_list pplist; static PortRec port[_MAX_PORTS]; #else /** redefine the CAPability flags */ enum ieee1284_capabilities { CAP1284_RAW = (1<<0), CAP1284_NIBBLE = (1<<1), /* SPP mode */ CAP1284_BYTE = (1<<2), /* PS/2 bidirectional */ CAP1284_COMPAT = (1<<3), CAP1284_BECP = (1<<4), CAP1284_ECP = (1<<5), /* ECP */ CAP1284_ECPRLE = (1<<6), /* ECP with RLE support */ CAP1284_ECPSWE = (1<<7), CAP1284_EPP = (1<<8), /* EPP hardware support */ CAP1284_EPPSL = (1<<9), /* EPP 1.7 */ CAP1284_EPPSWE = (1<<10) /* EPP software support */ }; static PortRec port[] = { { "0x378", 0x378, 0, 0, SANE_FALSE, SANE_FALSE, 0 }, { "0x278", 0x278, 0, 0, SANE_FALSE, SANE_FALSE, 0 }, { "0x3BC", 0x3BC, 0, 0, SANE_FALSE, SANE_FALSE, 0 } }; #endif /** depending on the interface we use, define the port macros */ #if defined(HAVE_LIBIEEE1284) #define inb_data(fd) ieee1284_read_data(pplist.portv[fd]); #define inb_stat(fd) (ieee1284_read_status(pplist.portv[fd]) ^ S1284_INVERTED) #define inb_ctrl(fd) (ieee1284_read_control(pplist.portv[fd]) ^ C1284_INVERTED) static inline u_char inb_eppdata(int fd) { u_char val; ieee1284_epp_read_data(pplist.portv[fd], 0, (char *)&val, 1); return val; } static inline void outb_eppdata(int fd, u_char val) { ieee1284_epp_write_data(pplist.portv[fd], 0, (const char *)&val, 1); } #define outb_data(fd,val) ieee1284_write_data(pplist.portv[fd], val) #define outb_ctrl(fd,val) ieee1284_write_control(pplist.portv[fd], \ (val) ^ C1284_INVERTED) static inline void outb_addr(int fd, u_char val) { ieee1284_epp_write_addr (pplist.portv[fd], 0, (char *)&val, 1); } #else #define inb_data(fd) inb(port[fd].base) #define inb_stat(fd) inb(port[fd].base + 1) #define inb_ctrl(fd) inb(port[fd].base + 2) #define inb_eppdata(fd) inb(port[fd].base + 4) #define outb_data(fd,val) outb(val, port[fd].base) #define outb_stat(fd,val) outb(val, port[fd].base + 1) #define outb_ctrl(fd,val) outb(val, port[fd].base + 2) #define outb_addr(fd,val) outb(val, port[fd].base + 3) #define outb_eppdata(fd,val) outb(val, port[fd].base + 4) #ifdef HAVE_IOPL # define _SET_IOPL() iopl(3) # define inbyte400(fd) inb(port[fd].base + 0x400) # define inbyte402(fd) inb(port[fd].base + 0x402) # define outbyte400(fd,val) outb(val, port[fd].base + 0x400) # define outbyte402(fd,val) outb(val, port[fd].base + 0x402) #else # define _SET_IOPL() # define inbyte400(fd) # define inbyte402(fd,val) # define outbyte400(fd,val) # define outbyte402(fd,val) #endif #endif /* should also be in unistd.h */ extern int setuid (uid_t); #if defined (HAVE_LIBIEEE1284) static const char *pp_libieee1284_errorstr( int error ) { switch (error) { case E1284_OK: return "Everything went fine"; case E1284_NOTIMPL: return "Not implemented in libieee1284"; case E1284_NOTAVAIL: return "Not available on this system"; case E1284_TIMEDOUT: return "Operation timed out"; case E1284_REJECTED: return "IEEE 1284 negotiation rejected"; case E1284_NEGFAILED: return "Negotiation went wrong"; case E1284_NOMEM: return "No memory left"; case E1284_INIT: return "Error initializing port"; case E1284_SYS: return "Error interfacing system"; case E1284_NOID: return "No IEEE 1284 ID available"; case E1284_INVALIDPORT: return "Invalid port"; default: return "Unknown error"; } } #endif /** show the caps */ static int pp_showcaps( int caps ) { int mode = 0; char ct[1024]; ct[0] = '\0'; if( caps & CAP1284_NIBBLE ) { strcat( ct, "SPP " ); mode |= SANEI_PP_MODE_SPP; } if( caps & CAP1284_BYTE ) { strcat( ct, "PS/2 " ); mode |= SANEI_PP_MODE_BIDI; } if( caps & CAP1284_EPP ) { strcat( ct, "EPP " ); mode |= SANEI_PP_MODE_EPP; } if( caps & CAP1284_EPPSWE ) { strcat( ct, "EPPSWE " ); mode |= SANEI_PP_MODE_EPP; } if( caps & CAP1284_ECP ) { strcat( ct, "ECP " ); mode |= SANEI_PP_MODE_ECP; } if( caps & CAP1284_ECPRLE ) { strcat( ct, "ECPRLE " ); mode |= SANEI_PP_MODE_ECP; } DBG( 4, "Supported Modes: %s\n", ct ); return mode; } #ifndef HAVE_LIBIEEE1284 /** probe the parallel port */ static int pp_probe( int fd ) { #ifdef HAVE_IOPL SANE_Byte c; int i, j; #endif SANE_Byte a, b; int retv = 0; DBG( 4, "pp_probe: port 0x%04lx\n", port[fd].base ); /* SPP check */ outbyte402( fd, 0x0c ); outb_ctrl ( fd, 0x0c ); outb_data ( fd, 0x55 ); a = inb_data( fd ); if( a != 0x55 ) { DBG( 4, "pp_probe: nothing supported :-(\n" ); return retv; } DBG( 4, "pp_probe: SPP port present\n" ); retv += CAP1284_NIBBLE; /* check for ECP */ #ifdef HAVE_IOPL /* clear at most 1k of data from FIFO */ for( i = 1024; i > 0; i-- ) { a = inbyte402( fd ); if ((a & 0x03) == 0x03) goto no_ecp; if (a & 0x01) break; inbyte400( fd ); /* Remove byte from FIFO */ } if (i <= 0) goto no_ecp; b = a ^ 3; outbyte402( fd, b ); c = inbyte402( fd ); if (a == c) { outbyte402( fd, 0xc0 ); /* FIFO test */ j = 0; while (!(inbyte402( fd ) & 0x01) && (j < 1024)) { inbyte402( fd ); j++; } if (j >= 1024) goto no_ecp; i = 0; j = 0; while (!(inbyte402( fd ) & 0x02) && (j < 1024)) { outbyte400( fd, 0x00 ); i++; j++; } if (j >= 1024) goto no_ecp; j = 0; while (!(inbyte402( fd ) & 0x01) && (j < 1024)) { inbyte400( fd ); j++; } if (j >= 1024) goto no_ecp; DBG( 4, "pp_probe: ECP with a %i byte FIFO present\n", i ); retv += CAP1284_ECP; } no_ecp: #endif /* check for PS/2 compatible port */ if( retv & CAP1284_ECP ) { outbyte402( fd, 0x20 ); } outb_data( fd, 0x55 ); outb_ctrl( fd, 0x0c ); a = inb_data( fd ); outb_data( fd, 0x55 ); outb_ctrl( fd, 0x2c ); b = inb_data( fd ); if( a != b ) { DBG( 4, "pp_probe: PS/2 bidirectional port present\n"); retv += CAP1284_BYTE; } /* check for EPP support */ if( port[fd].base & 0x007 ) { DBG( 4, "pp_probe: EPP not supported at this address\n" ); return retv; } #ifdef HAVE_IOPL if( retv & CAP1284_ECP ) { for( i = 0x00; i < 0x80; i += 0x20 ) { outbyte402( fd, i ); a = inb_stat( fd ); outb_stat( fd, a ); outb_stat( fd, (a & 0xfe)); a = inb_stat( fd ); if (!(a & 0x01)) { DBG( 2, "pp_probe: " "Failed Intel bug check. (Phony EPP in ECP)\n" ); return retv; } } DBG( 4, "pp_probe: Passed Intel bug check.\n" ); outbyte402( fd, 0x80 ); } #endif a = inb_stat( fd ); outb_stat( fd, a ); outb_stat( fd, (a & 0xfe)); a = inb_stat( fd ); if (a & 0x01) { outbyte402( fd, 0x0c ); outb_ctrl ( fd, 0x0c ); return retv; } outb_ctrl( fd, 0x04 ); inb_eppdata ( fd ); a = inb_stat( fd ); outb_stat( fd, a ); outb_stat( fd, (a & 0xfe)); if( a & 0x01 ) { DBG( 4, "pp_probe: EPP 1.9 with hardware direction protocol\n"); retv += CAP1284_EPP; } else { /* The EPP timeout bit was not set, this could either be: * EPP 1.7 * EPP 1.9 with software direction */ outb_ctrl( fd, 0x24 ); inb_eppdata ( fd ); a = inb_stat( fd ); outb_stat( fd, a ); outb_stat( fd, (a & 0xfe)); if( a & 0x01 ) { DBG( 4, "pp_probe: EPP 1.9 with software direction protocol\n" ); retv += CAP1284_EPPSWE; } else { DBG( 4, "pp_probe: EPP 1.7\n" ); retv += CAP1284_EPPSL; } } outbyte402( fd, 0x0c ); outb_ctrl ( fd, 0x0c ); return retv; } /** */ static int pp_set_scpmode( int fd ) { SANE_Byte tmp; DBG( 4, "pp_set_scpmode\n" ); #ifdef HAVE_IOPL tmp = inbyte402( fd ); tmp &= 0x1f; outbyte402( fd, tmp ); #endif tmp = inb_ctrl( fd ); tmp &= 0x0f; outb_ctrl ( fd, tmp ); return SANE_STATUS_GOOD; } static int pp_set_bidimode( int fd ) { SANE_Byte tmp; DBG( 4, "pp_set_bidimode\n" ); #ifdef HAVE_IOPL tmp = inbyte402( fd ); tmp = (tmp & 0x1f) | 0x20; outbyte402( fd, tmp ); #endif tmp = inb_ctrl( fd ); tmp = (tmp & 0x0f) | 0x20; outb_ctrl ( fd, tmp ); return SANE_STATUS_GOOD; } static int pp_set_eppmode( int fd ) { SANE_Byte tmp; DBG( 4, "pp_set_eppmode\n" ); #ifdef HAVE_IOPL tmp = inbyte402( fd ); tmp = (tmp & 0x1f) | 0x80; outbyte402( fd, tmp ); #endif tmp = inb_ctrl( fd ); tmp = (tmp & 0xf0) | 0x40; outb_ctrl ( fd, tmp ); return SANE_STATUS_GOOD; } static int pp_set_ecpmode( int fd ) { #ifdef HAVE_IOPL SANE_Byte tmp; #endif DBG( 4, "pp_set_ecpmode\n" ); #ifdef HAVE_IOPL tmp = inbyte402( fd ); tmp = (tmp & 0x1f) | 0x60; outbyte402( fd, tmp ); return SANE_STATUS_GOOD; #endif return SANE_STATUS_UNSUPPORTED; } /** set the parallel port mode */ static int pp_setmode( int fd, int mode ) { int ret; if( 0 == (mode & port[fd].caps)) { DBG( 2, "pp_setmode: mode not supported %d\n", mode ); return SANE_STATUS_UNSUPPORTED; } switch( mode ) { case SANEI_PP_MODE_SPP: ret = pp_set_scpmode( fd ); break; case SANEI_PP_MODE_BIDI: ret = pp_set_bidimode( fd ); break; case SANEI_PP_MODE_EPP: ret = pp_set_eppmode( fd ); break; case SANEI_PP_MODE_ECP: ret = pp_set_ecpmode( fd ); break; default: DBG( 2, "pp_setmode: invalid mode %d\n", mode ); return SANE_STATUS_INVAL; } return ret; } #endif static unsigned long pp_time_diff( struct timeval *start, struct timeval *end ) { double s, e, r; s = (double)start->tv_sec * 1000000.0 + (double)start->tv_usec; e = (double)end->tv_sec * 1000000.0 + (double)end->tv_usec; if( e > s ) r = (e - s); else r = (s - e); if( r <= (double)ULONG_MAX ) return (unsigned long)r; return 0; } /** */ static unsigned long pp_calculate_thresh( void ) { unsigned long i, r, ret; struct timeval start, end, deadline; gettimeofday( &start, NULL); for( i = _TEST_LOOPS; i; i-- ) { gettimeofday( &deadline, NULL ); deadline.tv_usec += 10; deadline.tv_sec += deadline.tv_usec / 1000000; deadline.tv_usec %= 1000000; } gettimeofday( &end, NULL); r = pp_time_diff( &start, &end ); ret = r/_TEST_LOOPS; return ret; } /** */ static void pp_calibrate_delay( void ) { unsigned long r, i; struct timeval start, end; for( i = 0; i < 5; i++ ) { pp_thresh = pp_calculate_thresh(); gettimeofday( &start, NULL); for( i = _TEST_LOOPS; i; i-- ) { sanei_pp_udelay( 1 ); } gettimeofday( &end, NULL); r = pp_time_diff( &start, &end ); DBG( 4, "pp_calibrate_delay: Delay expected: " "%u, real %lu, pp_thresh=%lu\n", _TEST_LOOPS, r, pp_thresh ); if( r >= _TEST_LOOPS ) { return; } } DBG( 4, "pp_calibrate_delay: pp_thresh set to 0\n" ); pp_thresh = 0; } static SANE_Status pp_init( void ) { #if defined (HAVE_LIBIEEE1284) int result, i; #endif if( first_time == SANE_FALSE ) { DBG( 5, "pp_init: already initialized\n" ); return SANE_STATUS_GOOD; } DBG( 5, "pp_init: called for the first time\n"); first_time = SANE_FALSE; #if defined (HAVE_LIBIEEE1284) DBG( 4, "pp_init: initializing libieee1284\n"); result = ieee1284_find_ports( &pplist, 0 ); if (result) { DBG (1, "pp_init: initializing IEEE 1284 failed (%s)\n", pp_libieee1284_errorstr( result )); first_time = SANE_TRUE; return SANE_STATUS_INVAL; } DBG( 3, "pp_init: %d ports reported by IEEE 1284 library\n", pplist.portc); for( i = 0; i < pplist.portc; i++ ) DBG( 6, "pp_init: port %d is `%s`\n", i, pplist.portv[i]->name); /* we support only up to _MAX_PORTS... */ if( pplist.portc > _MAX_PORTS ) { DBG (1, "pp_init: Lib IEEE 1284 reports too much ports: %d\n", pplist.portc ); ieee1284_free_ports( &pplist ); first_time = SANE_TRUE; return SANE_STATUS_UNSUPPORTED; } memset( port, 0, sizeof(port)); #else DBG( 4, "pp_init: trying to setuid root\n"); if( 0 > setuid( 0 )) { DBG( 1, "pp_init: setuid failed: errno = %d\n", errno ); DBG( 5, "pp_init: returning SANE_STATUS_INVAL\n" ); first_time = SANE_TRUE; return SANE_STATUS_INVAL; } DBG( 3, "pp_init: the application is now root\n" ); #endif DBG( 5, "pp_init: initialized successfully\n" ); return SANE_STATUS_GOOD; } static int pp_open( const char *dev, SANE_Status * status ) { int i; #if !defined (HAVE_LIBIEEE1284) u_long base; #else int result; #endif DBG( 4, "pp_open: trying to attach dev `%s`\n", dev ); #if !defined (HAVE_LIBIEEE1284) { char *end; DBG( 5, "pp_open: reading port number\n" ); base = strtol( dev, &end, 0 ); if ((end == dev) || (*end != '\0')) { DBG( 1, "pp_open: `%s` is not a valid port number\n", dev); DBG( 6, "pp_open: the part I did not understand was ...`%s`\n", end); *status = SANE_STATUS_INVAL; return -1; } } DBG( 6, "pp_open: read port number 0x%03lx\n", base ); if( base == 0 ) { DBG( 1, "pp_open: 0x%03lx is not a valid base address\n", base ); *status = SANE_STATUS_INVAL; return -1; } #endif DBG( 5, "pp_open: looking up port in list\n" ); #if defined (HAVE_LIBIEEE1284) for( i = 0; i < pplist.portc; i++ ) { DBG( 5, "pp_open: checking >%s<\n", pplist.portv[i]->name ); if( !strcmp(pplist.portv[i]->name, dev)) break; } if( pplist.portc <= i ) { DBG( 1, "pp_open: `%s` is not a valid device name\n", dev ); *status = SANE_STATUS_INVAL; return -1; } #else for( i = 0; i < NELEMS(port); i++ ) { if( port[i].base == base ) break; } if (NELEMS (port) <= i) { DBG( 1, "pp_open: 0x%03lx is not a valid base address\n", base ); *status = SANE_STATUS_INVAL; return -1; } #endif DBG( 6, "pp_open: port is in list at port[%d]\n", i); if( port[i].in_use == SANE_TRUE) { #if defined (HAVE_LIBIEEE1284) DBG( 1, "pp_open: device `%s` is already in use\n", dev ); #else DBG( 1, "pp_open: port 0x%03lx is already in use\n", base ); #endif *status = SANE_STATUS_DEVICE_BUSY; return -1; } port[i].in_use = SANE_TRUE; port[i].claimed = SANE_FALSE; #if defined (HAVE_LIBIEEE1284) DBG( 5, "pp_open: opening device\n" ); result = ieee1284_open( pplist.portv[i], 0, &port[i].caps ); if (result) { DBG( 1, "pp_open: could not open device `%s` (%s)\n", dev, pp_libieee1284_errorstr (result)); port[i].in_use = SANE_FALSE; *status = SANE_STATUS_ACCESS_DENIED; return -1; } #else DBG( 5, "pp_open: getting io permissions\n" ); /* TODO: insert FreeBSD compatible code here */ if( ioperm( port[i].base, 5, 1 )) { DBG( 1, "pp_open: cannot get io privilege for port 0x%03lx\n", port[i].base); port[i].in_use = SANE_FALSE; *status = SANE_STATUS_IO_ERROR; return -1; } /* save the CTRL register settings */ #ifdef HAVE_IOPL _SET_IOPL(); port[i].ecp_ctrl = inbyte402(i); port[i].ctrl = inb_ctrl(i); #endif /* check the capabilities of this port */ port[i].caps = pp_probe( i ); #endif port[i].caps = pp_showcaps( port[i].caps ); DBG( 3, "pp_open: device `%s` opened...\n", dev ); *status = SANE_STATUS_GOOD; return i; } static int pp_close( int fd, SANE_Status *status ) { #if defined(HAVE_LIBIEEE1284) int result; #endif DBG( 4, "pp_close: fd=%d\n", fd ); #if defined(HAVE_LIBIEEE1284) DBG( 6, "pp_close: this is port '%s'\n", pplist.portv[fd]->name ); #else DBG( 6, "pp_close: this is port 0x%03lx\n", port[fd].base ); DBG( 6, "pp_close: restoring the CTRL registers\n" ); outb_ctrl( fd, port[fd].ctrl ); #ifdef HAVE_IOPL outbyte402( fd, port[fd].ecp_ctrl ); #endif #endif if( port[fd].claimed == SANE_TRUE ) { sanei_pp_release( fd ); } DBG( 5, "pp_close: trying to free io port\n" ); #if defined(HAVE_LIBIEEE1284) if((result = ieee1284_close(pplist.portv[fd])) < 0) { #else if( ioperm( port[fd].base, 5, 0 )) { #endif #if defined(HAVE_LIBIEEE1284) DBG( 1, "pp_close: can't free port '%s' (%s)\n", pplist.portv[fd]->name, pp_libieee1284_errorstr(result)); #else DBG( 1, "pp_close: can't free port 0x%03lx\n", port[fd].base ); #endif *status = SANE_STATUS_IO_ERROR; return -1; } DBG( 5, "pp_close: marking port as unused\n" ); port[fd].in_use = SANE_FALSE; *status = SANE_STATUS_GOOD; return 0; } /** exported functions **/ SANE_Status sanei_pp_init( void ) { SANE_Status result; DBG_INIT(); result = pp_init(); if( result != SANE_STATUS_GOOD ) { return result; } pp_calibrate_delay(); return SANE_STATUS_GOOD; } SANE_Status sanei_pp_open( const char *dev, int *fd ) { SANE_Status status; DBG( 4, "sanei_pp_open: called for device '%s'\n", dev); *fd = pp_open( dev, &status ); if( *fd == -1 ) { DBG( 5, "sanei_pp_open: connection failed\n" ); return status; } DBG( 6, "sanei_pp_open: connected to device using fd %u\n", *fd ); return SANE_STATUS_GOOD; } void sanei_pp_close( int fd ) { SANE_Status status; DBG( 4, "sanei_pp_close: fd = %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if((fd < 0) || (fd >= pplist.portc)) { #else if((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_close: fd %d is invalid\n", fd ); return; } if( port[fd].in_use == SANE_FALSE ) { DBG( 2, "sanei_pp_close: port is not in use\n" ); #if defined(HAVE_LIBIEEE1284) DBG( 6, "sanei_pp_close: port is '%s'\n", pplist.portv[fd]->name ); #else DBG( 6, "sanei_pp_close: port is 0x%03lx\n", port[fd].base ); #endif return; } DBG( 5, "sanei_pp_close: freeing resources\n" ); if( pp_close (fd, &status) == -1 ) { DBG( 5, "sanei_pp_close: failed\n" ); return; } DBG( 5, "sanei_pp_close: finished\n" ); } SANE_Status sanei_pp_claim( int fd ) { #if defined (HAVE_LIBIEEE1284) int result; #endif DBG( 4, "sanei_pp_claim: fd = %d\n", fd ); #if defined (HAVE_LIBIEEE1284) if((fd < 0) || (fd >= pplist.portc)) { DBG( 2, "sanei_pp_claim: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } result = ieee1284_claim (pplist.portv[fd]); if (result) { DBG (1, "sanei_pp_claim: failed (%s)\n", pp_libieee1284_errorstr(result)); return -1; } #endif port[fd].claimed = SANE_TRUE; return SANE_STATUS_GOOD; } SANE_Status sanei_pp_release( int fd ) { DBG( 4, "sanei_pp_release: fd = %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if((fd < 0) || (fd >= pplist.portc)) { DBG( 2, "sanei_pp_release: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } ieee1284_release( pplist.portv[fd] ); #endif port[fd].claimed = SANE_FALSE; return SANE_STATUS_GOOD; } SANE_Status sanei_pp_outb_data( int fd, SANE_Byte val ) { #ifdef _PARANOIA DBG( 4, "sanei_pp_outb_data: called for fd %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_outb_data: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #endif outb_data( fd, val ); return SANE_STATUS_GOOD; } SANE_Status sanei_pp_outb_ctrl( int fd, SANE_Byte val ) { #ifdef _PARANOIA DBG( 4, "sanei_pp_outb_ctrl: called for fd %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_outb_ctrl: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #endif outb_ctrl( fd, val ); return SANE_STATUS_GOOD; } SANE_Status sanei_pp_outb_addr( int fd, SANE_Byte val ) { #ifdef _PARANOIA DBG( 4, "sanei_pp_outb_addr: called for fd %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_outb_addr: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #endif outb_addr( fd, val ); return SANE_STATUS_GOOD; } SANE_Status sanei_pp_outb_epp( int fd, SANE_Byte val ) { #ifdef _PARANOIA DBG( 4, "sanei_pp_outb_epp: called for fd %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_outb_epp: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #endif outb_eppdata( fd, val ); return SANE_STATUS_GOOD; } SANE_Byte sanei_pp_inb_data( int fd ) { #ifdef _PARANOIA DBG( 4, "sanei_pp_inb_data: called for fd %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_inb_data: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #endif return inb_data( fd ); } SANE_Byte sanei_pp_inb_stat( int fd ) { #ifdef _PARANOIA DBG( 4, "sanei_pp_inb_stat: called for fd %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_outb_stat: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #endif return inb_stat( fd ); } SANE_Byte sanei_pp_inb_ctrl( int fd ) { #ifdef _PARANOIA DBG( 4, "sanei_pp_inb_ctrl: called for fd %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_inb_ctrl: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #endif return inb_ctrl( fd ); } SANE_Byte sanei_pp_inb_epp( int fd ) { #ifdef _PARANOIA DBG( 4, "sanei_pp_inb_epp: called for fd %d\n", fd ); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_inb_epp: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #endif return inb_eppdata( fd ); } SANE_Status sanei_pp_getmodes( int fd, int *mode ) { #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_getmodes: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } if( mode ) *mode = port[fd].caps; return SANE_STATUS_GOOD; } SANE_Status sanei_pp_setmode( int fd, int mode ) { #if defined(HAVE_LIBIEEE1284) int result; if ((fd < 0) || (fd >= pplist.portc)) { #else if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_setmode: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } if((mode != SANEI_PP_MODE_SPP) && (mode != SANEI_PP_MODE_BIDI) && (mode != SANEI_PP_MODE_EPP) && (mode != SANEI_PP_MODE_ECP)) { DBG( 2, "sanei_pp_setmode: invalid mode %d\n", mode ); return SANE_STATUS_INVAL; } #if defined(HAVE_LIBIEEE1284) switch( mode ) { case SANEI_PP_MODE_SPP: mode = M1284_NIBBLE; break; case SANEI_PP_MODE_BIDI: mode = M1284_BYTE; break; case SANEI_PP_MODE_EPP: mode = M1284_EPP; break; case SANEI_PP_MODE_ECP: mode = M1284_ECP; break; default: DBG( 2, "sanei_pp_setmode: invalid mode %d\n", mode ); return SANE_STATUS_INVAL; } result = ieee1284_negotiate( pplist.portv[fd], mode ); /* negotiation might fails, but the port-mode should be set... */ if((E1284_OK != result) && (E1284_NEGFAILED != result)) { DBG( 2, "sanei_pp_setmode failed: %s\n", pp_libieee1284_errorstr( result )); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; #else return pp_setmode( fd, mode ); #endif } void sanei_pp_udelay( unsigned long usec ) { struct timeval now, deadline; if( usec == 0 ) return; gettimeofday( &deadline, NULL ); deadline.tv_usec += usec; deadline.tv_sec += deadline.tv_usec / 1000000; deadline.tv_usec %= 1000000; if( usec < pp_thresh ) return; do { gettimeofday( &now, NULL ); } while ((now.tv_sec < deadline.tv_sec) || (now.tv_sec == deadline.tv_sec && now.tv_usec < deadline.tv_usec)); } SANE_Status sanei_pp_set_datadir( int fd, int rev ) { #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) { #else SANE_Byte tmp; if ((fd < 0) || (fd >= NELEMS (port))) { #endif DBG( 2, "sanei_pp_setdir: invalid fd %d\n", fd ); return SANE_STATUS_INVAL; } #if defined(HAVE_LIBIEEE1284) ieee1284_data_dir( pplist.portv[fd], rev ); #else tmp = inb_ctrl( fd ); if( SANEI_PP_DATAIN == rev ) tmp |= SANEI_PP_CTRL_DIRECTION; else tmp &= ~SANEI_PP_CTRL_DIRECTION; outb_ctrl( fd, tmp ); #endif return SANE_STATUS_GOOD; } SANE_Bool sanei_pp_uses_directio( void ) { #if defined(HAVE_LIBIEEE1284) return SANE_FALSE; #else return SANE_TRUE; #endif } #else /* !HAVE_IOPERM */ SANE_Status sanei_pp_init( void ) { DBG_INIT(); _VAR_NOT_USED( first_time ); return SANE_STATUS_GOOD; } SANE_Status sanei_pp_open( const char *dev, int *fd ) { if (fd) *fd = -1; DBG( 4, "sanei_pp_open: called for device `%s`\n", dev ); DBG( 3, "sanei_pp_open: support not compiled\n" ); DBG( 6, "sanei_pp_open: basically, this backend does only compile\n" ); DBG( 6, "sanei_pp_open: on x86 architectures. Furthermore it\n" ); DBG( 6, "sanei_pp_open: needs ioperm() and inb()/outb() calls.\n" ); DBG( 6, "sanei_pp_open: alternativly it makes use of libieee1284\n" ); DBG( 6, "sanei_pp_open: (which isn't present either)\n"); return SANE_STATUS_INVAL; } void sanei_pp_close( int fd ) { DBG( 4, "sanei_pp_close: called for fd %d\n", fd ); DBG( 2, "sanei_pp_close: fd %d is invalid\n", fd ); return; } SANE_Status sanei_pp_claim( int fd ) { DBG( 4, "sanei_pp_claim: called for fd %d\n", fd ); DBG( 2, "sanei_pp_claim: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Status sanei_pp_release( int fd ) { DBG( 4, "sanei_pp_release: called for fd %d\n", fd ); DBG( 2, "sanei_pp_release: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Status sanei_pp_outb_data( int fd, SANE_Byte val ) { _VAR_NOT_USED( val ); DBG( 4, "sanei_pp_outb_data: called for fd %d\n", fd ); DBG( 2, "sanei_pp_outb_data: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Status sanei_pp_outb_ctrl( int fd, SANE_Byte val ) { _VAR_NOT_USED( val ); DBG( 4, "sanei_pp_outb_ctrl: called for fd %d\n", fd ); DBG( 2, "sanei_pp_outb_ctrl: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Status sanei_pp_outb_addr( int fd, SANE_Byte val ) { _VAR_NOT_USED( val ); DBG( 4, "sanei_pp_outb_addr: called for fd %d\n", fd ); DBG( 2, "sanei_pp_outb_addr: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Byte sanei_pp_inb_data( int fd ) { DBG( 4, "sanei_pp_inb_data: called for fd %d\n", fd ); DBG( 2, "sanei_pp_inb_data: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Byte sanei_pp_inb_stat( int fd ) { DBG( 4, "sanei_pp_inb_stat: called for fd %d\n", fd ); DBG( 2, "sanei_pp_inb_stat: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Byte sanei_pp_inb_ctrl( int fd ) { DBG( 4, "sanei_pp_inb_ctrl: called for fd %d\n", fd ); DBG( 2, "sanei_pp_inb_ctrl: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Byte sanei_pp_inb_epp ( int fd ) { DBG( 4, "sanei_pp_inb_epp: called for fd %d\n", fd ); DBG( 2, "sanei_pp_inb_epp: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Status sanei_pp_getmodes( int fd, int *mode ) { _VAR_NOT_USED( mode ); DBG( 4, "sanei_pp_getmodes: called for fd %d\n", fd ); DBG( 1, "sanei_pp_getmodes: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Status sanei_pp_setmode( int fd, int mode ) { _VAR_NOT_USED( mode ); DBG( 4, "sanei_pp_setmode: called for fd %d\n", fd ); DBG( 1, "sanei_pp_setmode: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } void sanei_pp_udelay( unsigned long usec ) { _VAR_NOT_USED( usec ); _VAR_NOT_USED( pp_thresh ); DBG( 2, "sanei_pp_udelay: not supported\n" ); } SANE_Status sanei_pp_set_datadir( int fd, int rev ) { _VAR_NOT_USED( rev ); DBG( 4, "sanei_pp_setdir: called for fd %d\n", fd ); DBG( 1, "sanei_pp_setdir: fd %d is invalid\n", fd ); return SANE_STATUS_INVAL; } SANE_Bool sanei_pp_uses_directio( void ) { DBG( 1, "sanei_pp_uses_directio: not supported\n" ); return SANE_FALSE; } #endif /* !HAVE_IOPERM */ sane-backends-1.0.27/sanei/os2_srb.h0000664000175000017500000001635212206524362014054 00000000000000/*************************************************************************** * * * ASPI Router Library * * * * This is a sample library which shows how to send SRB's to the * * ASPI Router device driver. USE AT YOUR OWN RISK!! * * * * Version 1.01 - June 1997 * * Daniel Dorau (woodst@cs.tu-berlin.de) * * * * Changes since 1.00: * * abort(), AbortSRB added * * * ***************************************************************************/ #pragma pack(1) /* SRB command */ #define SRB_Inquiry 0x00 #define SRB_Device 0x01 #define SRB_Command 0x02 #define SRB_Abort 0x03 #define SRB_Reset 0x04 #define SRB_Param 0x05 /* SRB status */ #define SRB_Busy 0x00 /* SCSI request in progress */ #define SRB_Done 0x01 /* SCSI request completed without error */ #define SRB_Aborted 0x02 /* SCSI aborted by host */ #define SRB_BadAbort 0x03 /* Unable to abort SCSI request */ #define SRB_Error 0x04 /* SCSI request completed with error */ #define SRB_BusyPost 0x10 /* SCSI request in progress with POST - Nokia */ #define SRB_InvalidCmd 0x80 /* Invalid SCSI request */ #define SRB_InvalidHA 0x81 /* Invalid Hhost adapter number */ #define SRB_BadDevice 0x82 /* SCSI device not installed */ /* SRB flags */ #define SRB_Post 0x01 /* Post vector valid */ #define SRB_Link 0x02 /* Link vector valid */ #define SRB_SG 0x04 /* Nokia: scatter/gather */ /* S/G: n * (4 bytes length, 4 bytes addr) */ /* No of s/g items not limited by HA spec. */ #define SRB_NoCheck 0x00 /* determined by command, not checked */ #define SRB_Read 0x08 /* target to host, length checked */ #define SRB_Write 0x10 /* host to target, length checked */ #define SRB_NoTransfer 0x18 /* no data transfer */ #define SRB_DirMask 0x18 /* bit mask */ /* SRB host adapter status */ #define SRB_NoError 0x00 /* No host adapter detected error */ #define SRB_Timeout 0x11 /* Selection timeout */ #define SRB_DataLength 0x12 /* Data over/underrun */ #define SRB_BusFree 0x13 /* Unexpected bus free */ #define SRB_BusSequence 0x14 /* Target bus sequence failure */ /* SRB target status field */ #define SRB_NoStatus 0x00 /* No target status */ #define SRB_CheckStatus 0x02 /* Check status (sense data valid) */ #define SRB_LUN_Busy 0x08 /* Specified LUN is busy */ #define SRB_Reserved 0x18 /* Reservation conflict */ #define MaxCDBStatus 64 /* max size of CDB + status */ typedef struct SRB SRB; struct SRB { unsigned char cmd, /* 00 */ status, /* 01 */ ha_num, /* 02 */ flags; /* 03 */ unsigned long res_04_07; /* 04..07 */ union { /* 08 */ /* SRB_Inquiry */ struct { unsigned char num_ha, /* 08 */ ha_target, /* 09 */ aspimgr_id[16], /* 0A..19 */ host_id[16], /* 1A..29 */ unique_id[16]; /* 2A..39 */ } inq; /* SRB_Device */ struct { unsigned char target, /* 08 */ lun, /* 09 */ devtype; /* 0A */ } dev; /* SRB_Command */ struct { unsigned char target, /* 08 */ lun; /* 09 */ unsigned long data_len; /* 0A..0D */ unsigned char sense_len; /* 0E */ void * _Seg16 data_ptr; /* 0F..12 */ void * _Seg16 link_ptr; /* 13..16 */ unsigned char cdb_len, /* 17 */ ha_status, /* 18 */ target_status; /* 19 */ void (* _Seg16 post) (SRB *); /* 1A..1D */ unsigned char res_1E_29[12]; /* 1E..29 */ unsigned char res_2A_3F[22]; /* 2A..3F */ unsigned char cdb_st[64]; /* 40..7F CDB+status */ unsigned char res_80_BF[64]; /* 80..BF */ } cmd; /* SRB_Abort */ struct { void * _Seg16 srb; /* 08..0B */ } abt; /* SRB_Reset */ struct { unsigned char target, /* 08 */ lun, /* 09 */ res_0A_17[14], /* 0A..17 */ ha_status, /* 18 */ target_status; /* 19 */ } res; /* SRB_Param - unused by ASPI4OS2 */ struct { unsigned char unique[16]; /* 08..17 */ } par; } u; }; /* SCSI sense codes */ /* Note! This list may not be complete. I did this compilation for use with tape drives.*/ #define Sense_Current 0x70; /* Current Error */ #define Sense_Deferred 0x71; /* Deferred Error */ #define Sense_Filemark 0x80; /* Filemark detected */ #define Sense_EOM 0x40; /* End of medium detected */ #define Sense_ILI 0x20; /* Incorrect length indicator */ /* Sense Keys */ #define SK_NoSense 0x00; /* No Sense */ #define SK_RcvrdErr 0x01; /* Recovered Error */ #define SK_NotReady 0x02; /* Not ready */ #define SK_MedErr 0x03; /* Medium Error */ #define SK_HWErr 0x04; /* Hardware Error */ #define SK_IllReq 0x05; /* Illegal Request */ #define SK_UnitAtt 0x06; /* Unit attention */ #define SK_DataProt 0x07: /* Data Protect */ #define SK_BlankChk 0x08: /* Blank Check */ #define SK_VndSpec 0x09; /* Vendor Specific */ #define SK_CopyAbort 0x0A; /* Copy Aborted */ #define SK_AbtdCmd 0x0B; /* Aborted Command */ #define SK_Equal 0x0C; /* Equal */ #define SK_VolOvfl 0x0D; /* Volume Overflow */ #define SK_MisComp 0x0E; /* Miscompare */ #define SK_Reserved 0x0F; /* Reserved */ sane-backends-1.0.27/sanei/linux_sg3_err.h0000664000175000017500000001213312206524362015257 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef SG_ERR_H #define SG_ERR_H /* Linux sg error codes taken from Doug Gilbert's sg_utils: http://www.torque.net/sg/ */ /* Some of the following error/status codes are exchanged between the various layers of the SCSI sub-system in Linux and should never reach the user. They are placed here for completeness. What appears here is copied from drivers/scsi/scsi.h which is not visible in the user space. */ /* The following are 'host_status' codes */ #ifndef DID_OK #define DID_OK 0x00 #endif #ifndef DID_NO_CONNECT #define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */ #define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */ #define DID_TIME_OUT 0x03 /* Timed out for some other reason */ #define DID_BAD_TARGET 0x04 /* Bad target (id?) */ #define DID_ABORT 0x05 /* Told to abort for some other reason */ #define DID_PARITY 0x06 /* Parity error (on SCSI bus) */ #define DID_ERROR 0x07 /* Internal error */ #define DID_RESET 0x08 /* Reset by somebody */ #define DID_BAD_INTR 0x09 /* Received an unexpected interrupt */ #define DID_PASSTHROUGH 0x0a /* Force command past mid-level */ #define DID_SOFT_ERROR 0x0b /* The low-level driver wants a retry */ #endif /* These defines are to isolate applictaions from kernel define changes */ #define SG_ERR_DID_OK DID_OK #define SG_ERR_DID_NO_CONNECT DID_NO_CONNECT #define SG_ERR_DID_BUS_BUSY DID_BUS_BUSY #define SG_ERR_DID_TIME_OUT DID_TIME_OUT #define SG_ERR_DID_BAD_TARGET DID_BAD_TARGET #define SG_ERR_DID_ABORT DID_ABORT #define SG_ERR_DID_PARITY DID_PARITY #define SG_ERR_DID_ERROR DID_ERROR #define SG_ERR_DID_RESET DID_RESET #define SG_ERR_DID_BAD_INTR DID_BAD_INTR #define SG_ERR_DID_PASSTHROUGH DID_PASSTHROUGH #define SG_ERR_DID_SOFT_ERROR DID_SOFT_ERROR /* The following are 'driver_status' codes */ #ifndef DRIVER_OK #define DRIVER_OK 0x00 #endif #ifndef DRIVER_BUSY #define DRIVER_BUSY 0x01 #define DRIVER_SOFT 0x02 #define DRIVER_MEDIA 0x03 #define DRIVER_ERROR 0x04 #define DRIVER_INVALID 0x05 #define DRIVER_TIMEOUT 0x06 #define DRIVER_HARD 0x07 #define DRIVER_SENSE 0x08 /* Sense_buffer has been set */ /* Following "suggests" are "or-ed" with one of previous 8 entries */ #define SUGGEST_RETRY 0x10 #define SUGGEST_ABORT 0x20 #define SUGGEST_REMAP 0x30 #define SUGGEST_DIE 0x40 #define SUGGEST_SENSE 0x80 #define SUGGEST_IS_OK 0xff #endif #ifndef DRIVER_MASK #define DRIVER_MASK 0x0f #endif #ifndef SUGGEST_MASK #define SUGGEST_MASK 0xf0 #endif /* These defines are to isolate applictaions from kernel define changes */ #define SG_ERR_DRIVER_OK DRIVER_OK #define SG_ERR_DRIVER_BUSY DRIVER_BUSY #define SG_ERR_DRIVER_SOFT DRIVER_SOFT #define SG_ERR_DRIVER_MEDIA DRIVER_MEDIA #define SG_ERR_DRIVER_ERROR DRIVER_ERROR #define SG_ERR_DRIVER_INVALID DRIVER_INVALID #define SG_ERR_DRIVER_TIMEOUT DRIVER_TIMEOUT #define SG_ERR_DRIVER_HARD DRIVER_HARD #define SG_ERR_DRIVER_SENSE DRIVER_SENSE #define SG_ERR_SUGGEST_RETRY SUGGEST_RETRY #define SG_ERR_SUGGEST_ABORT SUGGEST_ABORT #define SG_ERR_SUGGEST_REMAP SUGGEST_REMAP #define SG_ERR_SUGGEST_DIE SUGGEST_DIE #define SG_ERR_SUGGEST_SENSE SUGGEST_SENSE #define SG_ERR_SUGGEST_IS_OK SUGGEST_IS_OK #define SG_ERR_DRIVER_MASK DRIVER_MASK #define SG_ERR_SUGGEST_MASK SUGGEST_MASK #endif sane-backends-1.0.27/sanei/sanei_pa4s2.c0000664000175000017500000014345313106201017014576 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2003 Jochen Eisinger Copyright (C) 2003 James Perry (scsi_pp functions) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements an interface for the Mustek PP chipset A4S2 */ /* debug levels: 0 - nothing 1 - errors 2 - warnings 3 - things nice to know 4 - code flow 5 - detailed flow 6 - everything These debug levels can be set using the environment variable SANE_DEBUG_SANEI_PA4S2 */ #include "../include/sane/config.h" #define BACKEND_NAME sanei_pa4s2 #include "../include/sane/sanei_backend.h" /* pick up compatibility defs */ #ifdef HAVE_UNISTD_H #include #endif #if defined(HAVE_LIBIEEE1284) # include #elif defined(ENABLE_PARPORT_DIRECTIO) # if defined(HAVE_SYS_IO_H) # if defined (__ICC) && __ICC >= 700 # define __GNUC__ 2 # endif # include # ifndef SANE_HAVE_SYS_IO_H_WITH_INB_OUTB # define IO_SUPPORT_MISSING # endif # if defined (__ICC) && __ICC >= 700 # undef __GNUC__ # elif defined(__ICC) && defined(HAVE_ASM_IO_H) # include # endif # elif defined(HAVE_ASM_IO_H) # include /* ugly, but backwards compatible */ # elif defined(HAVE_SYS_HW_H) # include # elif defined(__i386__) && ( defined (__GNUC__) || defined (__ICC) ) static __inline__ void outb (u_char value, u_long port) { __asm__ __volatile__ ("outb %0,%1"::"a" (value), "d" ((u_short) port)); } static __inline__ u_char inb (u_long port) { u_char value; __asm__ __volatile__ ("inb %1,%0":"=a" (value):"d" ((u_short) port)); return value; } # else # define IO_SUPPORT_MISSING # endif #else # define IO_SUPPORT_MISSING #endif /* HAVE_LIBIEEE1284 */ #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_pa4s2.h" #ifdef NDEBUG #define DBG_INIT() /* basically, this is already done in sanei_debug.h... */ #define TEST_DBG_INIT() #else /* !NDEBUG */ static int sanei_pa4s2_dbg_init_called = SANE_FALSE; #if (!defined __GNUC__ || __GNUC__ < 2 || \ __GNUC_MINOR__ < (defined __cplusplus ? 6 : 4)) #define TEST_DBG_INIT() if (sanei_pa4s2_dbg_init_called == SANE_FALSE) \ { \ DBG_INIT(); \ DBG(6, "sanei_pa4s2: interface called for" \ " the first time\n"); \ sanei_pa4s2_dbg_init_called = SANE_TRUE; \ } #else #define TEST_DBG_INIT() if (sanei_pa4s2_dbg_init_called == SANE_FALSE) \ { \ DBG_INIT(); \ DBG(6, "%s: interface called for" \ " the first time\n", __func__); \ sanei_pa4s2_dbg_init_called = SANE_TRUE; \ } #endif #endif /* NDEBUG */ #if defined(STDC_HEADERS) # include # include # include #endif #if defined(HAVE_STRING_H) # include #elif defined(HAVE_STRINGS_H) # include #endif #if defined(HAVE_SYS_TYPES_H) # include #endif #include "../include/sane/saneopts.h" #if (defined (HAVE_IOPERM) || defined (HAVE_LIBIEEE1284)) && !defined (IO_SUPPORT_MISSING) #if defined(STDC_HEADERS) # include # include # include #endif #if defined(HAVE_STRING_H) # include #elif defined(HAVE_STRINGS_H) # include #endif #if defined(HAVE_SYS_TYPES_H) # include #endif #include "../include/sane/saneopts.h" #define PA4S2_MODE_NIB 0 #define PA4S2_MODE_UNI 1 #define PA4S2_MODE_EPP 2 #define PA4S2_ASIC_ID_1013 0xA8 #define PA4S2_ASIC_ID_1015 0xA5 #define PA4S2_ASIC_ID_1505 0xA2 typedef struct { #ifndef HAVE_LIBIEEE1284 const char name[6]; u_long base; /* i/o base address */ #endif u_int in_use; /* port in use? */ u_int enabled; /* port enabled? */ u_int mode; /* protocoll */ u_char prelock[3]; /* state of port */ #ifdef HAVE_LIBIEEE1284 int caps; #endif } PortRec, *Port; #if defined (HAVE_LIBIEEE1284) static struct parport_list pplist; static PortRec *port; #else static PortRec port[] = { {"0x378", 0x378, SANE_FALSE, SANE_FALSE, PA4S2_MODE_NIB, {0, 0, 0}}, {"0x278", 0x278, SANE_FALSE, SANE_FALSE, PA4S2_MODE_NIB, {0, 0, 0}}, {"0x3BC", 0x3BC, SANE_FALSE, SANE_FALSE, PA4S2_MODE_NIB, {0, 0, 0}} }; #endif static u_int sanei_pa4s2_interface_options = SANEI_PA4S2_OPT_DEFAULT; extern int setuid (uid_t); /* should also be in unistd.h */ static int pa4s2_open (const char *dev, SANE_Status * status); static void pa4s2_readbegin_epp (int fd, u_char reg); static u_char pa4s2_readbyte_epp (int fd); static void pa4s2_readend_epp (int fd); static void pa4s2_readbegin_uni (int fd, u_char reg); static u_char pa4s2_readbyte_uni (int fd); static void pa4s2_readend_uni (int fd); static void pa4s2_readbegin_nib (int fd, u_char reg); static u_char pa4s2_readbyte_nib (int fd); static void pa4s2_readend_nib (int fd); static void pa4s2_writebyte_any (int fd, u_char reg, u_char val); static int pa4s2_enable (int fd, u_char * prelock); static int pa4s2_disable (int fd, u_char * prelock); static int pa4s2_close (int fd, SANE_Status * status); #if defined (HAVE_LIBIEEE1284) static const char * pa4s2_libieee1284_errorstr(int error) { switch (error) { case E1284_OK: return "Everything went fine"; case E1284_NOTIMPL: return "Not implemented in libieee1284"; case E1284_NOTAVAIL: return "Not available on this system"; case E1284_TIMEDOUT: return "Operation timed out"; case E1284_REJECTED: return "IEEE 1284 negotiation rejected"; case E1284_NEGFAILED: return "Negotiation went wrong"; case E1284_NOMEM: return "No memory left"; case E1284_INIT: return "Error initializing port"; case E1284_SYS: return "Error interfacing system"; case E1284_NOID: return "No IEEE 1284 ID available"; case E1284_INVALIDPORT: return "Invalid port"; default: return "Unknown error"; } } #endif static int pa4s2_init (SANE_Status *status) { static int first_time = SANE_TRUE; #if defined (HAVE_LIBIEEE1284) int result, n; #endif DBG (6, "pa4s2_init: static int first_time = %u\n", first_time); if (first_time == SANE_FALSE) { DBG (5, "pa4s2_init: sanei already initialized\n"); status = SANE_STATUS_GOOD; return 0; } DBG (5, "pa4s2_init: called for the first time\n"); first_time = SANE_FALSE; #if defined (HAVE_LIBIEEE1284) DBG (4, "pa4s2_init: initializing libieee1284\n"); result = ieee1284_find_ports (&pplist, 0); if (result) { DBG (1, "pa4s2_init: initializing IEEE 1284 failed (%s)\n", pa4s2_libieee1284_errorstr (result)); first_time = SANE_TRUE; *status = SANE_STATUS_INVAL; return -1; } DBG (3, "pa4s2_init: %d ports reported by IEEE 1284 library\n", pplist.portc); for (n=0; nname); DBG (6, "pa4s2_init: allocating port list\n"); if ((port = calloc(pplist.portc, sizeof(PortRec))) == NULL) { DBG (1, "pa4s2_init: not enough free memory\n"); ieee1284_free_ports(&pplist); first_time = SANE_TRUE; *status = SANE_STATUS_NO_MEM; return -1; } #else DBG (4, "pa4s2_init: trying to setuid root\n"); if (0 > setuid (0)) { DBG (1, "pa4s2_init: setuid failed: errno = %d\n", errno); DBG (5, "pa4s2_init: returning SANE_STATUS_INVAL\n"); *status = SANE_STATUS_INVAL; first_time = SANE_TRUE; return -1; } DBG (3, "pa4s2_init: the application is now root\n"); DBG (3, "pa4s2_init: this is a high security risk...\n"); DBG (6, "pa4s2_init: ... you'd better start praying\n"); /* PS: no, i don't trust myself either */ /* PPS: i'd try rsbac or similar if i were you */ #endif DBG (5, "pa4s2_init: initialized successfully\n"); *status = SANE_STATUS_GOOD; return 0; } static int pa4s2_open (const char *dev, SANE_Status * status) { int n, result; #if !defined (HAVE_LIBIEEE1284) u_long base; #endif DBG (4, "pa4s2_open: trying to attach dev `%s`\n", dev); if ((result = pa4s2_init(status)) != 0) { DBG (1, "pa4s2_open: failed to initialize\n"); return result; } #if !defined (HAVE_LIBIEEE1284) { char *end; DBG (5, "pa4s2_open: reading port number\n"); base = strtol (dev, &end, 0); if ((end == dev) || (*end != '\0')) { DBG (1, "pa4s2_open: `%s` is not a valid port number\n", dev); DBG (6, "pa4s2_open: the part I did not understand was ...`%s`\n", end); DBG (5, "pa4s2_open: returning SANE_STATUS_INVAL\n"); *status = SANE_STATUS_INVAL; return -1; } } DBG (6, "pa4s2_open: read port number 0x%03lx\n", base); if (base == 0) { DBG (1, "pa4s2_open: 0x%03lx is not a valid base address\n", base); DBG (5, "pa4s2_open: returning SANE_STATUS_INVAL\n"); *status = SANE_STATUS_INVAL; return -1; } #endif DBG (5, "pa4s2_open: looking up port in list\n"); #if defined (HAVE_LIBIEEE1284) for (n = 0; n < pplist.portc; n++) if (!strcmp(pplist.portv[n]->name, dev)) break; if (pplist.portc <= n) { DBG (1, "pa4s2_open: `%s` is not a valid device name\n", dev); DBG (5, "pa4s2_open: returning SANE_STATUS_INVAL\n"); *status = SANE_STATUS_INVAL; return -1; } #else for (n = 0; n < NELEMS (port); n++) if (port[n].base == base) break; if (NELEMS (port) <= n) { DBG (1, "pa4s2_open: 0x%03lx is not a valid base address\n", base); DBG (5, "pa4s2_open: returning SANE_STATUS_INVAL\n"); *status = SANE_STATUS_INVAL; return -1; } #endif DBG (6, "pa4s2_open: port is in list at port[%d]\n", n); if (port[n].in_use == SANE_TRUE) { #if defined (HAVE_LIBIEEE1284) DBG (1, "pa4s2_open: device `%s` is already in use\n", dev); #else DBG (1, "pa4s2_open: port 0x%03lx is already in use\n", base); #endif DBG (5, "pa4s2_open: returning SANE_STATUS_DEVICE_BUSY\n"); *status = SANE_STATUS_DEVICE_BUSY; return -1; } DBG (5, "pa4s2_open: setting up port data\n"); #if defined (HAVE_LIBIEEE1284) DBG (6, "pa4s2_open: name=%s in_use=SANE_TRUE\n", dev); #else DBG (6, "pa4s2_open: base=0x%03lx in_use=SANE_TRUE\n", base); #endif DBG (6, "pa4s2_open: enabled=SANE_FALSE mode=PA4S2_MODE_NIB\n"); port[n].in_use = SANE_TRUE; port[n].enabled = SANE_FALSE; port[n].mode = PA4S2_MODE_NIB; #if defined (HAVE_LIBIEEE1284) DBG (5, "pa4s2_open: opening device\n"); result = ieee1284_open (pplist.portv[n], 0, &port[n].caps); if (result) { DBG (1, "pa4s2_open: could not open device `%s` (%s)\n", dev, pa4s2_libieee1284_errorstr (result)); port[n].in_use = SANE_FALSE; DBG (6, "pa4s2_open: marking port %d as unused\n", n); *status = SANE_STATUS_ACCESS_DENIED; return -1; } #else DBG (5, "pa4s2_open: getting io permissions\n"); /* TODO: insert FreeBSD compatible code here */ if (ioperm (port[n].base, 5, 1)) { DBG (1, "pa4s2_open: cannot get io privilege for port 0x%03lx\n", port[n].base); DBG (5, "pa4s2_open: marking port[%d] as unused\n", n); port[n].in_use = SANE_FALSE; DBG (5, "pa4s2_open: returning SANE_STATUS_IO_ERROR\n"); *status = SANE_STATUS_IO_ERROR; return -1; } #endif DBG (3, "pa4s2_open: device `%s` opened...\n", dev); DBG (5, "pa4s2_open: returning SANE_STATUS_GOOD\n"); *status = SANE_STATUS_GOOD; DBG (4, "pa4s2_open: open dev `%s` as fd %u\n", dev, n); return n; } #if defined(HAVE_LIBIEEE1284) #define inbyte0(fd) ieee1284_read_data(pplist.portv[fd]); #define inbyte1(fd) (ieee1284_read_status(pplist.portv[fd]) ^ S1284_INVERTED) #define inbyte2(fd) (ieee1284_read_control(pplist.portv[fd]) ^ C1284_INVERTED) static u_char inbyte4(int fd) { char val; ieee1284_epp_read_data(pplist.portv[fd], 0, &val, 1); return (u_char)val; } #define outbyte0(fd,val) ieee1284_write_data(pplist.portv[fd], val) #define outbyte1(fd,val) /* ieee1284_write_status(pplist.portv[fd], (val) ^ S1284_INVERTED) */ #define outbyte2(fd,val) ieee1284_write_control(pplist.portv[fd], (val) ^ C1284_INVERTED) static void outbyte3(int fd, u_char val) { ieee1284_epp_write_addr (pplist.portv[fd], 0, (char *)&val, 1); } #else #define inbyte0(fd) inb(port[fd].base) #define inbyte1(fd) inb(port[fd].base + 1) #define inbyte2(fd) inb(port[fd].base + 2) #define inbyte4(fd) inb(port[fd].base + 4) #define outbyte0(fd,val) outb(val, port[fd].base) #define outbyte1(fd,val) outb(val, port[fd].base + 1) #define outbyte2(fd,val) outb(val, port[fd].base + 2) #define outbyte3(fd,val) outb(val, port[fd].base + 3) #endif static void pa4s2_readbegin_epp (int fd, u_char reg) { #if defined(HAVE_LIBIEEE1284) DBG (6, "pa4s2_readbegin_epp: selecting register %u at '%s'\n", (int) reg, pplist.portv[fd]->name); #else DBG (6, "pa4s2_readbegin_epp: selecting register %u at 0x%03lx\n", (int) reg, port[fd].base); #endif outbyte0 (fd, 0x20); outbyte2 (fd, 0x04); outbyte2 (fd, 0x06); outbyte2 (fd, 0x04); outbyte3 (fd, reg + 0x18); } static u_char pa4s2_readbyte_epp (int fd) { u_char val = inbyte4 (fd); #if defined(HAVE_LIBIEEE1284) DBG (6, "pa4s2_readbyte_epp: reading value 0x%02x from '%s'\n", (int) val, pplist.portv[fd]->name); #else DBG (6, "pa4s2_readbyte_epp: reading value 0x%02x at 0x%03lx\n", (int) val, port[fd].base); #endif return val; } static void pa4s2_readend_epp (int fd) { DBG (6, "pa4s2_readend_epp: end of reading sequence\n"); outbyte2 (fd, 0x04); outbyte2 (fd, 0x00); outbyte2 (fd, 0x04); } static void pa4s2_readbegin_uni (int fd, u_char reg) { #if defined(HAVE_LIBIEEE1284) DBG (6, "pa4s2_readbegin_uni: selecting register %u for '%s'\n", (int) reg, pplist.portv[fd]->name); #else DBG (6, "pa4s2_readbegin_uni: selecting register %u at 0x%03lx\n", (int) reg, port[fd].base); #endif outbyte0 (fd, reg | 0x58); outbyte2 (fd, 0x04); outbyte2 (fd, 0x06); outbyte2 (fd, 0x04); outbyte2 (fd, 0x04); } static u_char pa4s2_readbyte_uni (int fd) { u_char val; outbyte2 (fd, 0x05); val = inbyte2(fd); val <<= 4; val &= 0xE0; val |= (inbyte1(fd) >> 3); outbyte2 (fd, 0x04); #if defined(HAVE_LIBIEEE1284) DBG (6, "pa4s2_readbyte_uni: reading value 0x%02x from '%s'\n", (int) val, pplist.portv[fd]->name); #else DBG (6, "pa4s2_readbyte_uni: reading value 0x%02x at 0x%03lx\n", (int) val, port[fd].base); #endif return val; } static void pa4s2_readend_uni (int fd) { DBG (6, "pa4s2_readend_uni: end of reading sequence for fd %d\n", fd); } static void pa4s2_readbegin_nib (int fd, u_char reg) { #if defined(HAVE_LIBIEEE1284) DBG (6, "pa4s2_readbegin_nib: selecting register %u at '%s'\n", (int) reg, pplist.portv[fd]->name); #else DBG (6, "pa4s2_readbegin_nib: selecting register %u at 0x%03lx\n", (int) reg, port[fd].base); #endif outbyte0 (fd, reg | 0x18); outbyte2 (fd, 0x04); outbyte2 (fd, 0x06); outbyte2 (fd, 0x04); outbyte2 (fd, 0x04); } static u_char pa4s2_readbyte_nib (int fd) { u_char val; outbyte2 (fd, 0x05); val = inbyte1(fd); val >>= 4; outbyte0 (fd, 0x58); val |= inbyte1(fd) & 0xF0; val ^= 0x88; outbyte0 (fd, 0x00); outbyte2 (fd, 0x04); #if defined(HAVE_LIBIEEE1284) DBG (6, "pa4s2_readbyte_nib: reading value 0x%02x from '%s'\n", (int) val, pplist.portv[fd]->name); #else DBG (6, "pa4s2_readbyte_nib: reading value 0x%02x at 0x%03lx\n", (int) val, port[fd].base); #endif return val; } static void pa4s2_readend_nib (int fd) { DBG (6, "pa4s2_readend_nib: end of reading sequence for fd %d\n", fd); } static void pa4s2_writebyte_any (int fd, u_char reg, u_char val) { /* somebody from Mustek asked me once, why I was writing the same value repeatedly to a port. Well, actually I don't know, it just works. Maybe the repeated writes could be replaced by appropriate delays or even left out completly. */ #if defined(HAVE_LIBIEEE1284) DBG (6, "pa4s2_writebyte_any: writing value 0x%02x" " in reg %u to '%s'\n", (int) val, (int) reg, pplist.portv[fd]->name); #else DBG (6, "pa4s2_writebyte_any: writing value 0x%02x" " in reg %u at 0x%03lx\n", (int) val, (int) reg, port[fd].base); #endif outbyte0 (fd, reg | 0x10); outbyte2 (fd, 0x04); outbyte2 (fd, 0x06); outbyte2 (fd, 0x06); outbyte2 (fd, 0x06); outbyte2 (fd, 0x06); outbyte2 (fd, 0x04); outbyte2 (fd, 0x04); outbyte0 (fd, val); outbyte2 (fd, 0x05); outbyte2 (fd, 0x05); outbyte2 (fd, 0x05); outbyte2 (fd, 0x04); outbyte2 (fd, 0x04); outbyte2 (fd, 0x04); outbyte2 (fd, 0x04); } static int pa4s2_enable (int fd, u_char * prelock) { #if defined (HAVE_LIBIEEE1284) int result; result = ieee1284_claim (pplist.portv[fd]); if (result) { DBG (1, "pa4s2_enable: failed to claim the port (%s)\n", pa4s2_libieee1284_errorstr(result)); return -1; } #endif prelock[0] = inbyte0 (fd); prelock[1] = inbyte1 (fd); prelock[2] = inbyte2 (fd); outbyte2 (fd, (prelock[2] & 0x0F) | 0x04); DBG (6, "pa4s2_enable: prelock[] = {0x%02x, 0x%02x, 0x%02x}\n", (int) prelock[0], (int) prelock[1], (int) prelock[2]); outbyte0 (fd, 0x15); outbyte0 (fd, 0x95); outbyte0 (fd, 0x35); outbyte0 (fd, 0xB5); outbyte0 (fd, 0x55); outbyte0 (fd, 0xD5); outbyte0 (fd, 0x75); outbyte0 (fd, 0xF5); outbyte0 (fd, 0x01); outbyte0 (fd, 0x81); return 0; } static int pa4s2_disable (int fd, u_char * prelock) { if ((sanei_pa4s2_interface_options & SANEI_PA4S2_OPT_ALT_LOCK) != 0) { DBG (6, "pa4s2_disable: using alternative command set\n"); outbyte0 (fd, 0x00); outbyte2 (fd, 0x04); outbyte2 (fd, 0x06); outbyte2 (fd, 0x04); } outbyte2 (fd, prelock[2] & 0x0F); outbyte0 (fd, 0x15); outbyte0 (fd, 0x95); outbyte0 (fd, 0x35); outbyte0 (fd, 0xB5); outbyte0 (fd, 0x55); outbyte0 (fd, 0xD5); outbyte0 (fd, 0x75); outbyte0 (fd, 0xF5); outbyte0 (fd, 0x00); outbyte0 (fd, 0x80); outbyte0 (fd, prelock[0]); outbyte1 (fd, prelock[1]); outbyte2 (fd, prelock[2]); #if defined(HAVE_LIBIEEE1284) ieee1284_release (pplist.portv[fd]); #endif DBG (6, "pa4s2_disable: state restored\n"); return 0; } static int pa4s2_close (int fd, SANE_Status * status) { #if defined(HAVE_LIBIEEE1284) int result; #endif DBG (4, "pa4s2_close: fd=%d\n", fd); #if defined(HAVE_LIBIEEE1284) DBG (6, "pa4s2_close: this is port '%s'\n", pplist.portv[fd]->name); #else DBG (6, "pa4s2_close: this is port 0x%03lx\n", port[fd].base); #endif DBG (5, "pa4s2_close: checking whether port is enabled\n"); if (port[fd].enabled == SANE_TRUE) { DBG (6, "pa4s2_close: disabling port\n"); pa4s2_disable (fd, port[fd].prelock); } DBG (5, "pa4s2_close: trying to free io port\n"); #if defined(HAVE_LIBIEEE1284) if ((result = ieee1284_close(pplist.portv[fd])) < 0) #else if (ioperm (port[fd].base, 5, 0)) #endif { #if defined(HAVE_LIBIEEE1284) DBG (1, "pa4s2_close: can't free port '%s' (%s)\n", pplist.portv[fd]->name, pa4s2_libieee1284_errorstr(result)); #else DBG (1, "pa4s2_close: can't free port 0x%03lx\n", port[fd].base); #endif DBG (5, "pa4s2_close: returning SANE_STATUS_IO_ERROR\n"); *status = SANE_STATUS_IO_ERROR; return -1; } DBG (5, "pa4s2_close: marking port as unused\n"); port[fd].in_use = SANE_FALSE; DBG (5, "pa4s2_close: returning SANE_STATUS_GOOD\n"); *status = SANE_STATUS_GOOD; return 0; } const char ** sanei_pa4s2_devices() { SANE_Status status; int n; const char **devices; TEST_DBG_INIT(); DBG (4, "sanei_pa4s2_devices: invoked\n"); if ((n = pa4s2_init(&status)) != 0) { DBG (1, "sanei_pa4s2_devices: failed to initialize (%s)\n", sane_strstatus(status)); return calloc(1, sizeof(char *)); } #if defined(HAVE_LIBIEEE1284) if ((devices = calloc((pplist.portc + 1), sizeof(char *))) == NULL) { DBG (2, "sanei_pa4s2_devices: not enough free memory\n"); return calloc(1, sizeof(char *)); } for (n=0; nname; #else if ((devices = calloc((NELEMS (port) + 1), sizeof(char *))) == NULL) { DBG (2, "sanei_pa4s2_devices: not enough free memory\n"); return calloc(1, sizeof(char *)); } for (n=0 ; n= pplist.portc)) #else if ((fd < 0) || (fd >= NELEMS (port))) #endif { DBG (2, "sanei_pa4s2_scsi_pp_get_status: invalid fd %d\n", fd); DBG (6, "sanei_pa4s2_scsi_pp_get_status: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].in_use == SANE_FALSE) { DBG (2, "sanei_pa4s2_scsi_pp_get_status: port is not in use\n"); #if defined(HAVE_LIBIEEE1284) DBG (4, "sanei_pa4s2_scsi_pp_get_status: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_scsi_pp_get_status: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_scsi_pp_get_status: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].enabled == SANE_FALSE) { DBG (2, "sanei_pa4s2_scsi_pp_get_status: port is not enabled\n"); #if defined(HAVE_LIBIEEE1284) DBG (4, "sanei_pa4s2_scsi_pp_get_status: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_scsi_pp_get_status: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_scsi_pp_get_status: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } outbyte2 (fd, 0x4); stat = inbyte1 (fd)^0x80; *status = (stat&0x2f)|((stat&0x10)<<2)|((stat&0x40)<<1)|((stat&0x80)>>3); DBG (5, "sanei_pa4s2_scsi_pp_get_status: status=0x%02X\n", *status); DBG (6, "sanei_pa4s2_scsi_pp_get_status: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } /* * SCSI-over-parallel scanners need this done when a register is * selected */ SANE_Status sanei_pa4s2_scsi_pp_reg_select (int fd, int reg) { TEST_DBG_INIT (); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) #else if ((fd < 0) || (fd >= NELEMS (port))) #endif { DBG (2, "sanei_pa4s2_scsi_pp_reg_select: invalid fd %d\n", fd); DBG (6, "sanei_pa4s2_scsi_pp_reg_select: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].in_use == SANE_FALSE) { DBG (2, "sanei_pa4s2_scsi_pp_reg_select: port is not in use\n"); #if defined(HAVE_LIBIEEE1284) DBG (4, "sanei_pa4s2_scsi_pp_get_status: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_scsi_pp_get_status: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_scsi_pp_reg_select: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].enabled == SANE_FALSE) { DBG (2, "sanei_pa4s2_scsi_pp_reg_select: port is not enabled\n"); #if defined(HAVE_LIBIEEE1284) DBG (4, "sanei_pa4s2_scsi_pp_get_status: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_scsi_pp_get_status: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_scsi_pp_reg_select: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_scsi_pp_reg_select: selecting register %u at port '%s'\n", (int) reg, pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_scsi_pp_reg_select: selecting register %u at 0x%03lx\n", (int) reg, (u_long)port[fd].base); #endif outbyte0 (fd, reg | 0x58); outbyte2 (fd, 0x04); outbyte2 (fd, 0x06); outbyte2 (fd, 0x04); outbyte2 (fd, 0x04); return SANE_STATUS_GOOD; } /* * The SCSI-over-parallel scanners need to be handled a bit differently * when opened, as they don't return a valid ASIC ID, so this can't be * used for detecting valid read modes */ SANE_Status sanei_pa4s2_scsi_pp_open (const char *dev, int *fd) { u_char val; SANE_Status status; TEST_DBG_INIT (); DBG(4, "sanei_pa4s2_scsi_pp_open: called for device '%s'\n", dev); DBG(5, "sanei_pa4s2_scsi_pp_open: trying to connect to port\n"); if ((*fd = pa4s2_open (dev, &status)) == -1) { DBG (5, "sanei_pa4s2_scsi_pp_open: connection failed\n"); return status; } DBG (6, "sanei_pa4s2_scsi_pp_open: connected to device using fd %u\n", *fd); DBG (5, "sanei_pa4s2_scsi_pp_open: checking for scanner\n"); if (sanei_pa4s2_enable (*fd, SANE_TRUE)!=SANE_STATUS_GOOD) { DBG (3, "sanei_pa4s2_scsi_pp_open: error enabling device\n"); return SANE_STATUS_IO_ERROR; } /* * Instead of checking ASIC ID, check device status */ if (sanei_pa4s2_scsi_pp_get_status(*fd, &val)!=SANE_STATUS_GOOD) { DBG (3, "sanei_pa4s2_scsi_pp_open: error getting device status\n"); sanei_pa4s2_enable (*fd, SANE_FALSE); return SANE_STATUS_IO_ERROR; } val&=0xf0; if ((val==0xf0)||(val&0x40)||(!(val&0x20))) { DBG (3, "sanei_pa4s2_scsi_pp_open: device returned status 0x%02X\n", val); sanei_pa4s2_enable (*fd, SANE_FALSE); return SANE_STATUS_DEVICE_BUSY; } if (sanei_pa4s2_enable (*fd, SANE_FALSE)!=SANE_STATUS_GOOD) { DBG (3, "sanei_pa4s2_scsi_pp_open: error disabling device\n"); return SANE_STATUS_IO_ERROR; } /* FIXME: it would be nice to try to use a better mode here, but how to * know if it's going to work? */ DBG (4, "sanei_pa4s2_scsi_pp_open: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } SANE_Status sanei_pa4s2_open (const char *dev, int *fd) { u_char asic, val; SANE_Status status; TEST_DBG_INIT (); DBG(4, "sanei_pa4s2_open: called for device '%s'\n", dev); DBG(5, "sanei_pa4s2_open: trying to connect to port\n"); if ((*fd = pa4s2_open (dev, &status)) == -1) { DBG (5, "sanei_pa4s2_open: connection failed\n"); return status; } DBG (6, "sanei_pa4s2_open: connected to device using fd %u\n", *fd); DBG (5, "sanei_pa4s2_open: checking for scanner\n"); sanei_pa4s2_enable (*fd, SANE_TRUE); DBG (6, "sanei_pa4s2_open: reading ASIC id\n"); sanei_pa4s2_readbegin (*fd, 0); sanei_pa4s2_readbyte (*fd, &asic); sanei_pa4s2_readend (*fd); switch (asic) { case PA4S2_ASIC_ID_1013: DBG (3, "sanei_pa4s2_open: detected ASIC id 1013\n"); break; case PA4S2_ASIC_ID_1015: DBG (3, "sanei_pa4s2_open: detected ASIC id 1015\n"); break; case PA4S2_ASIC_ID_1505: DBG (3, "sanei_pa4s2_open: detected ASIC id 1505\n"); break; default: DBG (1, "sanei_pa4s2_open: could not find scanner\n"); DBG (3, "sanei_pa4s2_open: reported ASIC id 0x%02x\n", asic); sanei_pa4s2_enable (*fd, SANE_FALSE); DBG (5, "sanei_pa4s2_open: closing port\n"); sanei_pa4s2_close (*fd); DBG (5, "sanei_pa4s2_open: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } sanei_pa4s2_enable (*fd, SANE_FALSE); DBG (4, "sanei_pa4s2_open: trying better modes\n"); while (port[*fd].mode <= PA4S2_MODE_EPP) { if ((port[*fd].mode == PA4S2_MODE_UNI) && ((sanei_pa4s2_interface_options & SANEI_PA4S2_OPT_TRY_MODE_UNI) == 0)) { DBG (3, "sanei_pa4s2_open: skipping mode UNI\n"); port[*fd].mode++; continue; } if ((port[*fd].mode == PA4S2_MODE_EPP) && ((sanei_pa4s2_interface_options & SANEI_PA4S2_OPT_NO_EPP) != 0)) { DBG (3, "sanei_pa4s2_open: skipping mode EPP\n"); break; } DBG (5, "sanei_pa4s2_open: trying mode %u\n", port[*fd].mode); sanei_pa4s2_enable (*fd, SANE_TRUE); sanei_pa4s2_readbegin (*fd, 0); sanei_pa4s2_readbyte (*fd, &val); if (val != asic) { sanei_pa4s2_readend (*fd); sanei_pa4s2_enable (*fd, SANE_FALSE); DBG (5, "sanei_pa4s2_open: mode failed\n"); DBG (6, "sanei_pa4s2_open: returned ASIC-ID 0x%02x\n", (int) val); break; } sanei_pa4s2_readend (*fd); sanei_pa4s2_enable (*fd, SANE_FALSE); DBG (5, "sanei_pa4s2_open: mode works\n"); port[*fd].mode++; } port[*fd].mode--; if ((port[*fd].mode == PA4S2_MODE_UNI) && ((sanei_pa4s2_interface_options & SANEI_PA4S2_OPT_TRY_MODE_UNI) == 0)) { port[*fd].mode--; } DBG (5, "sanei_pa4s2_open: using mode %u\n", port[*fd].mode); DBG (4, "sanei_pa4s2_open: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } void sanei_pa4s2_close (int fd) { SANE_Status status; TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_close: fd = %d\n", fd); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) #else if ((fd < 0) || (fd >= NELEMS (port))) #endif { DBG (2, "sanei_pa4s2_close: fd %d is invalid\n", fd); DBG (5, "sanei_pa4s2_close: failed\n"); return; } if (port[fd].in_use == SANE_FALSE) { DBG (2, "sanei_pa4s2_close: port is not in use\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_close: failed\n"); return; } DBG (5, "sanei_pa4s2_close: freeing resources\n"); if (pa4s2_close (fd, &status) == -1) { DBG (2, "sanei_pa4s2_close: could not close scanner\n"); DBG (5, "sanei_pa4s2_close: failed\n"); return; } DBG (5, "sanei_pa4s2_close: finished\n"); } SANE_Status sanei_pa4s2_enable (int fd, int enable) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_enable: called for fd %d with value %d\n", fd, enable); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) #else if ((fd < 0) || (fd >= NELEMS (port))) #endif { DBG (2, "sanei_pa4s2_enable: fd %d is invalid\n", fd); DBG (5, "sanei_pa4s2_enable: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].in_use == SANE_FALSE) { DBG (2, "sanei_pa4s2_enable: port is not in use\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_enable: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if ((enable != SANE_TRUE) && (enable != SANE_FALSE)) { DBG (2, "sanei_pa4s2_enable: invalid value %d\n", enable); DBG (5, "sanei_pa4s2_enable: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if ((unsigned int) enable == port[fd].enabled) { DBG (3, "sanei_pa4s2_enable: senseless call...\n"); DBG (4, "sanei_pa4s2_enable: aborting\n"); DBG (5, "sanei_pa4s2_enable: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } if (enable == SANE_TRUE) { #if defined(HAVE_LIBIEEE1284) DBG (4, "sanei_pa4s2_enable: enable port '%s'\n", pplist.portv[fd]->name); #else DBG (4, "sanei_pa4s2_enable: enable port 0x%03lx\n", port[fd].base); /* io-permissions are not inherited after fork (at least not on linux 2.2, although they seem to be inherited on linux 2.4), so we should make sure we get the permission */ if (ioperm (port[fd].base, 5, 1)) { DBG (1, "sanei_pa4s2_enable: cannot get io privilege for port" " 0x%03lx\n", port[fd].base); DBG (5, "sanei_pa4s2_enable:: marking port[%d] as unused\n", fd); port[fd].in_use = SANE_FALSE; DBG (5, "sanei_pa4s2_enable:: returning SANE_STATUS_IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } #endif if (pa4s2_enable (fd, port[fd].prelock) != 0) { DBG (1, "sanei_pa4s2_enable: failed to enable port\n"); DBG (5, "sanei_pa4s2_enable: returning SANE_STATUS_IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } } else { #if defined(HAVE_LIBIEEE1284) DBG (4, "sanei_pa4s2_enable: disable port '%s'\n", pplist.portv[fd]->name); #else DBG (4, "sanei_pa4s2_enable: disable port 0x%03lx\n", port[fd].base); #endif pa4s2_disable (fd, port[fd].prelock); } port[fd].enabled = enable; DBG (5, "sanei_pa4s2_enable: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } SANE_Status sanei_pa4s2_readbegin (int fd, u_char reg) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_readbegin: called for fd %d and register %u\n", fd, (int) reg); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) #else if ((fd < 0) || (fd >= NELEMS (port))) #endif { DBG (2, "sanei_pa4s2_readbegin: invalid fd %d\n", fd); DBG (5, "sanei_pa4s2_readbegin: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].in_use == SANE_FALSE) { DBG (2, "sanei_pa4s2_readbegin: port is not in use\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_readbegin: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].enabled == SANE_FALSE) { DBG (2, "sanei_pa4s2_readbegin: port is not enabled\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_readbegin: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } switch (port[fd].mode) { case PA4S2_MODE_EPP: DBG (5, "sanei_pa4s2_readbegin: EPP readbegin\n"); pa4s2_readbegin_epp (fd, reg); break; case PA4S2_MODE_UNI: DBG (5, "sanei_pa4s2_readbegin: UNI readbegin\n"); pa4s2_readbegin_uni (fd, reg); break; case PA4S2_MODE_NIB: DBG (5, "sanei_pa4s2_readbegin: NIB readbegin\n"); pa4s2_readbegin_nib (fd, reg); break; default: DBG (1, "sanei_pa4s2_readbegin: port info broken\n"); DBG (3, "sanei_pa4s2_readbegin: invalid port mode\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_readbegin: return SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } DBG (5, "sanei_pa4s2_readbegin: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } SANE_Status sanei_pa4s2_readbyte (int fd, u_char * val) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_readbyte: called with fd %d\n", fd); if (val == NULL) { DBG (1, "sanei_pa4s2_readbyte: got NULL pointer as result buffer\n"); return SANE_STATUS_INVAL; } #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) #else if ((fd < 0) || (fd >= NELEMS (port))) #endif { DBG (2, "sanei_pa4s2_readbyte: invalid fd %d\n", fd); DBG (5, "sanei_pa4s2_readbyte: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].in_use == SANE_FALSE) { DBG (2, "sanei_pa4s2_readbyte: port is not in use\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_readbyte: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].enabled == SANE_FALSE) { DBG (2, "sanei_pa4s2_readbyte: port is not enabled\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_readbyte: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } DBG (4, "sanei_pa4s2_readbyte: we hope, the backend called\n"); DBG (4, "sanei_pa4s2_readbyte: readbegin, so the port is ok...\n"); DBG (6, "sanei_pa4s2_readbyte: this means, I did not check it - it's\n"); DBG (6, "sanei_pa4s2_readbyte: not my fault, if your PC burns down.\n"); switch (port[fd].mode) { case PA4S2_MODE_EPP: DBG (5, "sanei_pa4s2_readbyte: read in EPP mode\n"); *val = pa4s2_readbyte_epp (fd); break; case PA4S2_MODE_UNI: DBG (5, "sanei_pa4s2_readbyte: read in UNI mode\n"); *val = pa4s2_readbyte_uni (fd); break; case PA4S2_MODE_NIB: DBG (5, "sanei_pa4s2_readbyte: read in NIB mode\n"); *val = pa4s2_readbyte_nib (fd); break; default: DBG (1, "sanei_pa4s2_readbyte: port info broken\n"); DBG (2, "sanei_pa4s2_readbyte: probably the port wasn't" " correct configured...\n"); DBG (3, "sanei_pa4s2_readbyte: invalid port mode\n"); DBG (6, "sanei_pa4s2_readbyte: port mode %u\n", port[fd].mode); DBG (6, "sanei_pa4s2_readbyte: I told you!!!\n"); DBG (5, "sanei_pa4s2_readbyte: return" " SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } DBG (5, "sanei_pa4s2_readbyte: read finished\n"); DBG (6, "sanei_pa4s2_readbyte: got value 0x%02x\n", (int) *val); DBG (5, "sanei_pa4s2_readbyte: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } SANE_Status sanei_pa4s2_readend (int fd) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_readend: called for fd %d\n", fd); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) #else if ((fd < 0) || (fd >= NELEMS (port))) #endif { DBG (2, "sanei_pa4s2_readend: invalid fd %d\n", fd); DBG (5, "sanei_pa4s2_readend: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].in_use == SANE_FALSE) { DBG (2, "sanei_pa4s2_readend: port is not in use\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_readend: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].enabled == SANE_FALSE) { DBG (2, "sanei_pa4s2_readend: port is not enabled\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_readend: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } DBG (4, "sanei_pa4s2_readend: we hope, the backend called\n"); DBG (4, "sanei_pa4s2_readend: readbegin, so the port is ok...\n"); DBG (6, "sanei_pa4s2_readend: this means, I did not check it - it's\n"); DBG (6, "sanei_pa4s2_readend: not my fault, if your PC burns down.\n"); switch (port[fd].mode) { case PA4S2_MODE_EPP: DBG (5, "sanei_pa4s2_readend: EPP mode readend\n"); pa4s2_readend_epp (fd); break; case PA4S2_MODE_UNI: DBG (5, "sanei_pa4s2_readend: UNI mode readend\n"); pa4s2_readend_uni (fd); break; case PA4S2_MODE_NIB: DBG (5, "sanei_pa4s2_readend: NIB mode readend\n"); pa4s2_readend_nib (fd); break; default: DBG (1, "sanei_pa4s2_readend: port info broken\n"); DBG (2, "sanei_pa4s2_readend: probably the port wasn't" " correct configured...\n"); DBG (3, "sanei_pa4s2_readend: invalid port mode\n"); DBG (6, "sanei_pa4s2_readend: port mode %u\n", port[fd].mode); DBG (6, "sanei_pa4s2_readend: I told you!!!\n"); DBG (5, "sanei_pa4s2_readend: return" " SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } DBG (5, "sanei_pa4s2_readend: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } SANE_Status sanei_pa4s2_writebyte (int fd, u_char reg, u_char val) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_writebyte: called for fd %d, reg %u and val %u\n", fd, (int) reg, (int) val); #if defined(HAVE_LIBIEEE1284) if ((fd < 0) || (fd >= pplist.portc)) #else if ((fd < 0) || (fd >= NELEMS (port))) #endif { DBG (2, "sanei_pa4s2_writebyte: invalid fd %d\n", fd); DBG (5, "sanei_pa4s2_writebyte: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].in_use == SANE_FALSE) { DBG (2, "sanei_pa4s2_writebyte: port is not in use\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_writebyte: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } if (port[fd].enabled == SANE_FALSE) { DBG (2, "sanei_pa4s2_writebyte: port is not enabled\n"); #if defined(HAVE_LIBIEEE1284) DBG (6, "sanei_pa4s2_close: port is '%s'\n", pplist.portv[fd]->name); #else DBG (6, "sanei_pa4s2_close: port is 0x%03lx\n", port[fd].base); #endif DBG (5, "sanei_pa4s2_readbegin: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } switch (port[fd].mode) { case PA4S2_MODE_EPP: case PA4S2_MODE_UNI: case PA4S2_MODE_NIB: DBG (5, "sanei_pa4s2_writebyte: NIB/UNI/EPP write\n"); pa4s2_writebyte_any (fd, reg, val); break; default: DBG (1, "sanei_pa4s2_writebyte: port info broken\n"); DBG (3, "sanei_pa4s2_writebyte: invalid port mode\n"); DBG (6, "sanei_pa4s2_writebyte: port mode %u\n", port[fd].mode); DBG (5, "sanei_pa4s2_writebyte: return" " SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } DBG (5, "sanei_pa4s2_writebyte: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } SANE_Status sanei_pa4s2_options (u_int * options, int set) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_options: called with options %u and set = %d\n", *options, set); if ((set != SANE_TRUE) && (set != SANE_FALSE)) DBG (2, "sanei_pa4s2_options: value of set is invalid\n"); if ((set == SANE_TRUE) && (*options > 7)) DBG (2, "sanei_pa4s2_options: value of *options is invalid\n"); if (set == SANE_TRUE) { DBG (5, "sanei_pa4s2_options: setting options to %u\n", *options); sanei_pa4s2_interface_options = *options; } else { DBG (5, "sanei_pa4s2_options: options are set to %u\n", sanei_pa4s2_interface_options); *options = sanei_pa4s2_interface_options; } DBG (5, "sanei_pa4s2_options: returning SANE_STATUS_GOOD\n"); return SANE_STATUS_GOOD; } #else /* !HAVE_IOPERM */ SANE_Status sanei_pa4s2_open (const char *dev, int *fd) { TEST_DBG_INIT (); if (fd) *fd = -1; DBG (4, "sanei_pa4s2_open: called for device `%s`\n", dev); DBG (3, "sanei_pa4s2_open: A4S2 support not compiled\n"); DBG (6, "sanei_pa4s2_open: basically, this backend does only compile\n"); DBG (6, "sanei_pa4s2_open: on x86 architectures. Furthermore it\n"); DBG (6, "sanei_pa4s2_open: needs ioperm() and inb()/outb() calls.\n"); DBG (6, "sanei_pa4s2_open: alternativly it makes use of libieee1284\n"); DBG (6, "sanei_pa4s2_open: (which isn't present either)\n"); DBG (5, "sanei_pa4s2_open: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } void sanei_pa4s2_close (int fd) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_close: called for fd %d\n", fd); DBG (2, "sanei_pa4s2_close: fd %d is invalid\n", fd); DBG (3, "sanei_pa4s2_close: A4S2 support not compiled\n"); DBG (6, "sanei_pa4s2_close: so I wonder, why this function is called" " anyway.\n"); DBG (6, "sanei_pa4s2_close: maybe this is a bug in the backend.\n"); DBG (5, "sanei_pa4s2_close: returning\n"); return; } SANE_Status sanei_pa4s2_enable (int fd, int enable) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_enable: called for fd %d with value=%d\n", fd, enable); DBG (2, "sanei_pa4s2_enable: fd %d is invalid\n", fd); if ((enable != SANE_TRUE) && (enable != SANE_FALSE)) DBG (2, "sanei_pa4s2_enable: value %d is invalid\n", enable); DBG (3, "sanei_pa4s2_enable: A4S2 support not compiled\n"); DBG (6, "sanei_pa4s2_enable: oops, I think there's someone going to\n"); DBG (6, "sanei_pa4s2_enable: produce a lot of garbage...\n"); DBG (5, "sanei_pa4s2_enable: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } SANE_Status sanei_pa4s2_readbegin (int fd, u_char reg) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_readbegin: called for fd %d and register %d\n", fd, (int) reg); DBG (2, "sanei_pa4s2_readbegin: fd %d is invalid\n", fd); DBG (3, "sanei_pa4s2_readbegin: A4S2 support not compiled\n"); DBG (6, "sanei_pa4s2_readbegin: don't look - this is going to be\n"); DBG (6, "sanei_pa4s2_readbegin: worse then you'd expect...\n"); DBG (5, "sanei_pa4s2_readbegin: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } SANE_Status sanei_pa4s2_readbyte (int fd, u_char * val) { TEST_DBG_INIT (); if (val) *val = 0; DBG (4, "sanei_pa4s2_readbyte: called for fd %d\n", fd); DBG (2, "sanei_pa4s2_readbyte: fd %d is invalid\n", fd); DBG (3, "sanei_pa4s2_readbyte: A4S2 support not compiled\n"); DBG (6, "sanei_pa4s2_readbyte: shit happens\n"); DBG (5, "sanei_pa4s2_readbyte: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } SANE_Status sanei_pa4s2_readend (int fd) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_readend: called for fd %d\n", fd); DBG (2, "sanei_pa4s2_readend: fd %d is invalid\n", fd); DBG (3, "sanei_pa4s2_readend: A4S2 support not compiled\n"); DBG (6, "sanei_pa4s2_readend: it's too late anyway\n"); DBG (5, "sanei_pa4s2_readend: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } SANE_Status sanei_pa4s2_writebyte (int fd, u_char reg, u_char val) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_writebyte: called for fd %d and register %d, " "value = %u\n", fd, (int) reg, (int) val); DBG (2, "sanei_pa4s2_writebyte: fd %d is invalid\n", fd); DBG (3, "sanei_pa4s2_writebyte: A4S2 support not compiled\n"); DBG (6, "sanei_pa4s2_writebyte: whatever backend you're using, tell\n"); DBG (6, "sanei_pa4s2_writebyte: the maintainer his code has bugs...\n"); DBG (5, "sanei_pa4s2_writebyte: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } SANE_Status sanei_pa4s2_options (u_int * options, int set) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_options: called with options %u and set = %d\n", *options, set); if ((set != SANE_TRUE) && (set != SANE_FALSE)) DBG (2, "sanei_pa4s2_options: value of set is invalid\n"); if ((set == SANE_TRUE) && (*options > 3)) DBG (2, "sanei_pa4s2_options: value of *options is invalid\n"); DBG (3, "sanei_pa4s2_options: A4S2 support not compiled\n"); DBG (5, "sanei_pa4s2_options: returning SANE_STATUS_INVAL\n"); return SANE_STATUS_INVAL; } const char ** sanei_pa4s2_devices() { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_devices: invoked\n"); DBG (3, "sanei_pa4s2_devices: A4S2 support not compiled\n"); DBG (5, "sanei_pa4s2_devices: returning empty list\n"); return calloc(1, sizeof(char *)); } SANE_Status sanei_pa4s2_scsi_pp_get_status(int fd, u_char *status) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_scsi_pp_get_status: fd=%d, status=%p\n", fd, (void *) status); DBG (3, "sanei_pa4s2_scsi_pp_get_status: A4S2 support not compiled\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sanei_pa4s2_scsi_pp_reg_select (int fd, int reg) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_scsi_pp_reg_select: fd=%d, reg=%d\n", fd, reg); DBG (3, "sanei_pa4s2_devices: A4S2 support not compiled\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sanei_pa4s2_scsi_pp_open (const char *dev, int *fd) { TEST_DBG_INIT (); DBG (4, "sanei_pa4s2_scsi_pp_open: dev=%s, fd=%p\n", dev, (void *) fd); DBG (3, "sanei_pa4s2_scsi_pp_open: A4S2 support not compiled\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* !HAVE_IOPERM */ sane-backends-1.0.27/sanei/sanei_ab306.c0000664000175000017500000003324412775312262014474 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Andreas Czechanowski and David Mosberger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements the Mustek-proprietary SCSI-over-parallel-port interface. */ #include "../include/sane/config.h" #ifdef HAVE_UNISTD_H # include #endif #include #ifdef HAVE_SYS_IO_H # include /* use where available (glibc 2.x, for example) */ # ifndef SANE_HAVE_SYS_IO_H_WITH_INB_OUTB # define IO_SUPPORT_MISSING # endif #elif HAVE_ASM_IO_H # include /* ugly, but backwards compatible */ #elif defined (__i386__) && defined (__GNUC__) static __inline__ void outb (u_char value, u_long port) { __asm__ __volatile__ ("outb %0,%1" : : "a" (value), "d" ((u_short) port)); } static __inline__ u_char inb (u_long port) { u_char value; __asm__ __volatile__ ("inb %1,%0" : "=a" (value) : "d" ((u_short)port)); return value; } #else # define IO_SUPPORT_MISSING #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_ab306.h" #if (defined(HAVE_IOPERM) || defined(__FreeBSD__) || defined(__DragonFly__)) && !defined(IO_SUPPORT_MISSING) #include #include #include #include #include #include #include #include #include #include #include "../include/sane/saneopts.h" #define BACKEND_NAME sanei_ab306 #include "../include/sane/sanei_debug.h" #define PORT_DEV "/dev/port" #define AB306_CIO 0x379 /* control i/o port */ #if defined(__FreeBSD__) || defined(__DragonFly__) static int dev_io_fd = 0; #endif typedef struct port { u_long base; /* i/o base address */ int port_fd; /* >= 0 when using /dev/port */ u_int lstat; u_int in_use : 1, /* port in use? */ active : 1; /* port was active at some point */ } Port; static Port port[] = { {0x26b, -1, 0, 0, 0}, {0x2ab, -1, 0, 0, 0}, {0x2eb, -1, 0, 0, 0}, {0x22b, -1, 0, 0, 0}, {0x32b, -1, 0, 0, 0}, {0x36b, -1, 0, 0, 0}, {0x3ab, -1, 0, 0, 0}, {0x3eb, -1, 0, 0, 0} }; static const SANE_Byte wakeup[] = { 0x47, 0x55, 0x54, 0x53, 0x02, 0x01, 0x80 }; static u_char cdb_sizes[8] = { 6, 10, 10, 12, 12, 12, 10, 10 }; #define CDB_SIZE(opcode) cdb_sizes[(((opcode) >> 5) & 7)] static void ab306_outb (Port *p, u_long addr, u_char val) { if (p->port_fd >= 0) { if ((u_long) lseek (p->port_fd, addr, SEEK_SET) != addr) return; if (write (p->port_fd, &val, 1) != 1) return; } else outb (val, addr); } static int ab306_inb (Port *p, u_long addr) { u_char ch; if (p->port_fd >= 0) { if ((u_long) lseek (p->port_fd, addr, SEEK_SET) != addr) return -1; if (read (p->port_fd, &ch, 1) != 1) return -1; return ch; } else return inb (addr); } /* Send a single command-byte over the AB306N-interface. */ static void ab306_cout (Port *p, int val) { u_long base = p->base; while ((ab306_inb (p, base + 1) & 0x80)); /* wait for dir flag */ ab306_outb (p, base, val); ab306_outb (p, base + 1, 0xe0); while ((ab306_inb (p, base + 1) & 0x80) == 0); /* wait for ack */ ab306_outb (p, base + 1, 0x60); } /* Read a single response-byte from the SANEI_AB306N-interface. */ static int ab306_cin (Port *p) { u_long base = p->base; u_char val; while ((ab306_inb (p, base + 1) & 0x80) == 0); /* wait for dir flag */ val = ab306_inb (p, base); ab306_outb (p, base + 1, 0xe0); /* ack received byte */ while (ab306_inb (p, base + 1) & 0x80); ab306_outb (p, base + 1, 0x60); /* reset ack */ return val; } static SANE_Status ab306_write (Port *p, const void *buf, size_t len) { u_long base = p->base; u_int i; int cksum = 0; DBG(3, "ab306_write: waiting for scanner to be ready %02x\n", ab306_inb (p, base + 1)); while ((ab306_inb (p, base + 1) & 0x20) == 0); usleep (10000); DBG(4, "ab306_write: writing data\n"); for (i = 0; i < len; ++i) { ab306_cout (p, ((const u_char *) buf)[i]); cksum += ((const u_char *) buf)[i]; } DBG(4, "ab306_write: writing checksum\n"); ab306_cout (p, -cksum & 0xff); DBG(3, "ab306_write: waiting for scanner to be NOT ready %02x\n", ab306_inb (p, base + 1)); while ((ab306_inb (p, base + 1) & 0x20) != 0); usleep (10000); DBG(4, "ab306_write: reading ack\n"); cksum = ab306_cin (p); if (cksum != 0xa5) { DBG(0, "ab306_write: checksum error (%02x!=a5) when sending command!\n", cksum); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* Abort a running scan by pulling C6 low for a while. */ static void ab306_abort (Port *p) { ab306_outb (p, p->base + 1, 0x20); while ((ab306_inb (p, p->base + 1) & 0x80)); ab306_outb (p, p->base + 1, 0x60); } /* Open the device, must contain a valid port number (as string) returns port number and I/O method in <*fdp> (not a file descriptor) turns the scanner on setting C5 and C6. */ SANE_Status sanei_ab306_open (const char *dev, int *fdp) { static int first_time = 1; SANE_Status status; u_char byte; u_long base; char *end; int i, j; if (first_time) { first_time = 0; DBG_INIT(); } base = strtol (dev, &end, 0); if (end == dev || *end) { DBG(1, "sanei_ab306_open: `%s' is not a valid port number\n", dev); return SANE_STATUS_INVAL; } for (i = 0; i < NELEMS(port); ++i) if (port[i].base == base) break; if (i >= NELEMS(port)) { DBG(1, "sanei_ab306_open: %lx is not a valid base address\n", base); return SANE_STATUS_INVAL; } if (port[i].in_use) { DBG(1, "sanei_ab306_open: port %lx is already in use\n", base); return SANE_STATUS_DEVICE_BUSY; } status = sanei_ab306_get_io_privilege (i); #if defined(__FreeBSD__) || defined(__DragonFly__) status = sanei_ab306_get_io_privilege (i); if (status != SANE_STATUS_GOOD) return status; DBG(1, "sanei_ab306_ioport: using inb/outb access\n"); for (j = 0; j < NELEMS(wakeup); ++j) { byte = wakeup[j]; if (j == NELEMS(wakeup) - 1) byte |= i; outb (byte, AB306_CIO); } #else /* !defined(__FreeBSD__) */ if (ioperm (AB306_CIO, 1, 1) != 0) { DBG(1, "sanei_ab306_ioport: using /dev/port access\n"); if (port[i].port_fd < 0) port[i].port_fd = open (PORT_DEV, O_RDWR); if (port[i].port_fd < 0) return SANE_STATUS_IO_ERROR; for (j = 0; j < NELEMS(wakeup); ++j) { if (lseek (port[i].port_fd, AB306_CIO, SEEK_SET) != AB306_CIO) return SANE_STATUS_IO_ERROR; byte = wakeup[j]; if (j == NELEMS(wakeup) - 1) byte |= i; if (write (port[i].port_fd, &byte, 1) != 1) return SANE_STATUS_IO_ERROR; } } else { DBG(1, "sanei_ab306_ioport: using inb/outb access\n"); for (j = 0; j < NELEMS(wakeup); ++j) { byte = wakeup[j]; if (j == NELEMS(wakeup) - 1) byte |= i; outb (byte, AB306_CIO); } status = sanei_ab306_get_io_privilege (i); if (status != SANE_STATUS_GOOD) return status; } #endif /* !defined(__FreeBSD__) */ ab306_outb (port + i, port[i].base + 1, 0x60); port[i].in_use = 1; port[i].active = 1; *fdp = i; return SANE_STATUS_GOOD; } void sanei_ab306_close (int fd) { Port *p = port + fd; if (p->in_use) { if (p->port_fd >= 0) { close (p->port_fd); p->port_fd = -1; } p->in_use = 0; } } /* Get I/O permission to the configuration port and the desired operating ports. */ SANE_Status sanei_ab306_get_io_privilege (int fd) { if (port[fd].port_fd < 0) { #if defined(__FreeBSD__) || defined(__DragonFly__) if (dev_io_fd == 0) dev_io_fd = open ("/dev/io", O_RDONLY); if (dev_io_fd < 0) return SANE_STATUS_IO_ERROR; #else /* !defined(__FreeBSD__) */ if (ioperm (port[fd].base, 3, 1) != 0) return SANE_STATUS_IO_ERROR; #endif /* !defined(__FreeBSD__) */ } return SANE_STATUS_GOOD; } /* Send a command via the SANEI_AB306N-interface, get response when is > 0. */ SANE_Status sanei_ab306_cmd (int fd, const void *src, size_t src_size, void *dst, size_t * dst_size) { Port *p = port + fd; const u_char *cp = src; size_t cdb_size = CDB_SIZE(cp[0]); SANE_Status status; u_char byte; /* If this is a READ_SCANNED_DATA command, reset lstat: */ switch (cp[0]) { case 0x08: /* scsi READ_SCANNED_DATA command */ /* Initialize lstat to the current status, because we need bit 4 (0x10) as toggle bit for reading lines. */ p->lstat = 0x34; break; case 0x1b: /* scsi START_STOP command */ if (!cp[4]) { /* it's a STOP */ ab306_abort (p); return SANE_STATUS_GOOD; } break; default: break; } status = ab306_write (p, src, 6); if (status != SANE_STATUS_GOOD) return status; if (src_size > cdb_size) { status = ab306_write (p, cp + cdb_size, src_size - cdb_size); if (status != SANE_STATUS_GOOD) return status; } if (dst && *dst_size > 0) { u_int i, cksum = 0; DBG(3, "sanei_ab306_cmd: waiting for scanner to be NOT ready %02x\n", ab306_inb (p, p->base + 1)); while ((ab306_inb (p, p->base + 1) & 0x20) != 0); for (i = 0; i < *dst_size; i++) { byte = ab306_cin (p); cksum += byte; ((u_char *) dst)[i] = byte; } cksum += ab306_cin (p); /* add in checksum */ if ((cksum & 0xff) != 0) { DBG(0, "sanei_ab306_cmd: checksum error (%2x!=0) when receiving " "after command!\n", cksum); return SANE_STATUS_IO_ERROR; } ab306_cout (p, 0); /* dummy byte (will be discarded) */ } return SANE_STATUS_GOOD; } /* Read scan-data from the AB306N-device. Read lines, of which every one has bytes. */ SANE_Status sanei_ab306_rdata (int fd, int planes, SANE_Byte * buf, int lines, int bpl) { Port *p = port + fd; int lcnt, pcnt, bcnt, xmax; int nstat; DBG(2, "sanei_ab306_rdata: start\n"); /* lstat should be set by a call to sanei_ab306_init_toggle before ! */ while ((ab306_inb (p, p->base + 1) & 0x80) == 0); /* the lines-loop: */ for (lcnt = 0; lcnt < lines; ++lcnt) { /* the planes-loop: */ for (pcnt = 0; pcnt < planes; ++pcnt) { xmax = bpl / planes; do nstat = ab306_inb (p, p->base + 1); while (((p->lstat ^ nstat) & 0x10) == 0); if (p->port_fd >= 0) { /* the pixel-loop: */ for (bcnt = 0; bcnt < xmax; bcnt++) { if ((u_long) lseek (p->port_fd, p->base, SEEK_SET) != p->base) return SANE_STATUS_IO_ERROR; if (read (p->port_fd, buf, 1) != 1) return SANE_STATUS_IO_ERROR; ++buf; } } else { /* the pixel-loop: */ for (bcnt = 0; bcnt < xmax; bcnt++) { *(u_char *) buf = inb (p->base); ++buf; } } p->lstat = nstat; } } DBG(2, "sanei_ab306_rdata: done\n"); return SANE_STATUS_GOOD; } void sanei_ab306_exit (void) { int i; for (i = 0; i < NELEMS(port); ++i) if (port[i].active) { port[i].active = 0; /* power off the scanner: */ ab306_outb (port + i, port[i].base + 1, 0x00); } #if defined(__FreeBSD) || defined(__DragonFly__) if (dev_io_fd >0) close (dev_io_fd); #endif /* defined(__FreeBSD__) */ } SANE_Status sanei_ab306_test_ready (int fd) { Port *p = port + fd; u_char byte; byte = ab306_inb (p, p->base + 1); if (byte & 0x20) return SANE_STATUS_GOOD; return SANE_STATUS_DEVICE_BUSY; } #else /* !HAVE_IOPERM */ SANE_Status sanei_ab306_open (const char *devname, int *fdp) { *fdp = -1; return SANE_STATUS_INVAL; } void sanei_ab306_close (int fd) { } void sanei_ab306_exit (void) { } SANE_Status sanei_ab306_get_io_privilege (int fd) { return SANE_STATUS_INVAL; } SANE_Status sanei_ab306_test_ready (int fd) { return SANE_STATUS_GOOD; /* non-existent device is always ready... */ } SANE_Status sanei_ab306_cmd (int fd, const void *src, size_t src_size, void *dst, size_t *dst_size) { return SANE_STATUS_INVAL; } SANE_Status sanei_ab306_rdata (int fd, int planes, SANE_Byte *buf, int lines, int bpl) { return SANE_STATUS_INVAL; } #endif /* !HAVE_IOPERM */ sane-backends-1.0.27/sanei/sanei_scsi.c0000664000175000017500000050632612775312262014630 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang Copyright (C) 2003 Frank Zago This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file provides a generic SCSI interface. */ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include "../include/lassert.h" #include #include #include #include #include #include #ifdef HAVE_SYS_IOCTL_H #include #endif #include #include #if defined (HAVE_WINDOWS_H) # include #endif #define STUBBED_INTERFACE 0 #define LINUX_INTERFACE 1 #define BSD_INTERFACE 2 #define HPUX_INTERFACE 3 #define OPENSTEP_INTERFACE 4 #define DECUNIX_INTERFACE 5 #define SCO_OS5_INTERFACE 6 #define IRIX_INTERFACE 7 #define SOLARIS_INTERFACE 8 #define SOLARIS_SG_INTERFACE 9 #define OS2_INTERFACE 10 #define AIX_GSC_INTERFACE 11 #define DOMAINOS_INTERFACE 12 #define FREEBSD_CAM_INTERFACE 13 #define SYSVR4_INTERFACE 14 #define SCO_UW71_INTERFACE 15 #define SOLARIS_USCSI_INTERFACE 16 #define MACOSX_INTERFACE 17 #define WIN32_INTERFACE 18 #ifdef HAVE_RESMGR # include #endif #if defined (HAVE_SCSI_SG_H) # define USE LINUX_INTERFACE # include #elif defined (HAVE__USR_SRC_LINUX_INCLUDE_SCSI_SG_H) # define USE LINUX_INTERFACE # include "/usr/src/linux/include/scsi/sg.h" #elif defined (HAVE_SYS_SCSICMD_H) # define USE SCSO_OS5_INTERFACE # include # include #elif defined (HAVE_CAMLIB_H) # define USE FREEBSD_CAM_INTERFACE # include /* there is a bug in scsi_all.h */ # include # include # include # include # include #elif defined (HAVE_SYS_SCSIIO_H) # define USE BSD_INTERFACE # include # ifdef HAVE_SCSI_H # include # endif #elif defined (HAVE_BSD_DEV_SCSIREG_H) # define USE OPENSTEP_INTERFACE # include #elif defined (HAVE_IO_CAM_CAM_H) # define USE DECUNIX_INTERFACE # include # include # include # include # include #elif defined (HAVE_SYS_DSREQ_H) # define USE IRIX_INTERFACE # include # include #elif defined (HAVE_SYS_SCSI_H) # include # ifdef HAVE_SYS_SDI_COMM_H # ifdef HAVE_SYS_PASSTHRUDEF_H # define USE SCO_UW71_INTERFACE # include # include # include # include # else # define USE SYSVR4_INTERFACE /* Unixware 2.x tested */ # define HAVE_SYSV_DRIVER # include # include # endif # else # ifdef SCTL_READ # define USE HPUX_INTERFACE # else # ifdef HAVE_GSCDDS_H # define USE AIX_GSC_INTERFACE # include # else /* This happens for AIX without gsc and possibly other platforms... */ # endif # endif # endif #elif defined (HAVE_OS2_H) # define USE OS2_INTERFACE # define INCL_DOSFILEMGR # define INCL_DOS # define INCL_DOSDEVICES # define INCL_DOSDEVIOCTL # define INCL_DOSMEMMGR # include # include "os2_srb.h" #elif defined (HAVE_SYS_SCSI_SGDEFS_H) # define USE SOLARIS_SG_INTERFACE # include #elif defined (HAVE_SYS_SCSI_TARGETS_SCGIO_H) # define USE SOLARIS_INTERFACE # define SOL2 # include #elif defined (HAVE_SYS_SCSI_SCSI_H) /* * the "offical" solaris uscsi(7I) interface; comes last, so that users * installing the SCG/SG driver can still use these generic scsi interfaces */ # define USE SOLARIS_USCSI_INTERFACE # define SOL2 # include #elif defined (HAVE_APOLLO_SCSI_H) # define USE DOMAINOS_INTERFACE # include /* Only used for signal name for KillDomainServer */ # include # include # include # include # include # include # include # include "sanei_DomainOS.h" #elif defined (HAVE_IOKIT_CDB_IOSCSILIB_H) || \ defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) # define USE MACOSX_INTERFACE # include # include # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H # include # include # endif # ifdef HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H /* The def of VERSION causes problems in the following include files */ # undef VERSION # include # include # include # else # ifdef HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H /* The def of VERSION causes problems in the following include files */ # undef VERSION # include # include # include # endif # endif #elif defined (HAVE_DDK_NTDDSCSI_H) # define USE WIN32_INTERFACE # include # include #elif defined (HAVE_NTDDSCSI_H) # define USE WIN32_INTERFACE # include #endif #ifndef USE # define USE STUBBED_INTERFACE #endif #if USE == LINUX_INTERFACE # include #endif #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_scsi.h" #define BACKEND_NAME sanei_scsi #include "../include/sane/sanei_debug.h" #if USE == DECUNIX_INTERFACE static int cam_fd = -1; /* used for SCSI CAM based interfaces */ #endif #if USE == SOLARIS_INTERFACE || USE == SOLARIS_USCSI_INTERFACE static int unit_ready (int fd); #endif #ifdef SG_BIG_BUFF # define MAX_DATA SG_BIG_BUFF #endif #if USE == SYSVR4_INTERFACE # define MAX_DATA 56*1024 /* don't increase or kernel will dump * tested with adsl, adsa and umax backend * it depends on the lowend scsi * drivers . But the most restriction * is in the UNIXWARE KERNEL witch do * not allow more then 64kB DMA transfers */ static char lastrcmd[16]; /* hold command block of last read command */ #endif #if USE == OPENSTEP_INTERFACE # define MAX_DATA (120*1024) #endif #if USE == IRIX_INTERFACE # define MAX_DATA (256*1024) #endif #if USE == FREEBSD_CAM_INTERFACE # define MAX_DATA (DFLTPHYS - PAGE_SIZE) #endif #if USE == SOLARIS_INTERFACE # define MAX_DATA (128*1024) #endif #if USE == SOLARIS_SG_INTERFACE # define MAX_DATA (128*1024) #endif #if USE == SOLARIS_USCSI_INTERFACE # define MAX_DATA (64*1024) #endif #if USE == OS2_INTERFACE # define MAX_DATA (64*1024) #endif #if USE == MACOSX_INTERFACE # define MAX_DATA (128*1024) #endif #ifndef MAX_DATA # define MAX_DATA (32*1024) #endif #ifdef SG_SET_TIMEOUT # ifdef _SC_CLK_TCK # define GNU_HZ sysconf(_SC_CLK_TCK) # else # ifdef HZ # define GNU_HZ HZ # else # ifdef CLOCKS_PER_SEC # define GNU_HZ CLOCKS_PER_SEC # endif # endif # endif #endif /* default timeout value: 120 seconds */ static int sane_scsicmd_timeout = 120; int sanei_scsi_max_request_size = MAX_DATA; #if USE == LINUX_INTERFACE /* the following #defines follow Douglas Gilbert's sample code to maintain run time compatibility with the old and the new SG driver for Linux */ #include "linux_sg3_err.h" /* contains several definitions of error codes */ #ifndef SG_SET_COMMAND_Q #define SG_SET_COMMAND_Q 0x2271 #endif #ifndef SG_SET_RESERVED_SIZE #define SG_SET_RESERVED_SIZE 0x2275 #endif #ifndef SG_GET_RESERVED_SIZE #define SG_GET_RESERVED_SIZE 0x2272 #endif #ifndef SG_GET_SCSI_ID #define SG_GET_SCSI_ID 0x2276 #else #define SG_GET_SCSI_ID_FOUND #endif #ifndef SG_GET_VERSION_NUM #define SG_GET_VERSION_NUM 0x2282 #endif #ifndef SG_NEXT_CMD_LEN #define SG_NEXT_CMD_LEN 0x2283 #endif #ifndef SCSIBUFFERSIZE #define SCSIBUFFERSIZE (128 * 1024) #endif /* the struct returned by the SG ioctl call SG_GET_SCSI_ID changed from version 2.1.34 to 2.1.35, and we need the informations from the field s_queue_depth, which was introduced in 2.1.35. To get this file compiling also with older versions of sg.h, the struct is re-defined here. */ typedef struct xsg_scsi_id { int host_no; /* as in "scsi" where 'n' is one of 0, 1, 2 etc */ int channel; int scsi_id; /* scsi id of target device */ int lun; int scsi_type; /* TYPE_... defined in scsi/scsi.h */ short h_cmd_per_lun; /* host (adapter) maximum commands per lun */ short d_queue_depth; /* device (or adapter) maximum queue length */ int unused1; /* probably find a good use, set 0 for now */ int unused2; /* ditto */ } SG_scsi_id; typedef struct req { struct req *next; int fd; u_int running:1, done:1; SANE_Status status; size_t *dst_len; void *dst; /* take the definition of the ioctl parameter SG_IO as a compiler flag if the new SG driver is available */ union { struct { struct sg_header hdr; /* Make sure this is the last element, the real size is SG_BIG_BUFF and machine dependant */ u_int8_t data[1]; } cdb; #ifdef SG_IO /* at present, Linux's SCSI system limits the sense buffer to 16 bytes which is definitely too small. Hoping that this will change at some time, let's set the sense buffer size to 64. */ #define SENSE_MAX 64 #define MAX_CDB 12 struct { struct sg_io_hdr hdr; u_char sense_buffer[SENSE_MAX]; u_int8_t data[1]; } sg3; #endif } sgdata; } req; typedef struct Fdparms { int sg_queue_used, sg_queue_max; size_t buffersize; req *sane_qhead, *sane_qtail, *sane_free_list; } fdparms; #endif #if USE == FREEBSD_CAM_INTERFACE # define CAM_MAXDEVS 128 struct cam_device *cam_devices[CAM_MAXDEVS] = { NULL }; #endif static struct { u_int in_use:1; /* is this fd_info in use? */ u_int fake_fd:1; /* is this a fake file descriptor? */ u_int bus, target, lun; /* nexus info; used for some interfaces only */ SANEI_SCSI_Sense_Handler sense_handler; void *sense_handler_arg; void *pdata; /* platform-specific data */ } *fd_info; static u_char cdb_sizes[8] = { 6, 10, 10, 12, 12, 12, 10, 10 }; #define CDB_SIZE(opcode) cdb_sizes[(((opcode) >> 5) & 7)] #if USE == DOMAINOS_INTERFACE /* This includes the server code. Most of these routines are private to the actual server. The only public ones are: sanei_DomainOS_init Used to initialize the server DomainErrorCheck A common error handling routine */ #include "sanei_DomainOS.c" int ServerInitialized = 0; pid_t ServerPID; struct DomainServerCommon *com; long CommandTriggerValue[2]; ec2_$ptr_t CommandAcceptedPtr[2]; long ResultTriggerValue[2]; ec2_$ptr_t ResultReadyPtr[2]; time_$clock_t Wait16S = { 64, 0 }; /* Delay of about 16 Seconds */ /* This function is registered as an exit function. It's purpose is to make sure that the Domain SANE Server is stopped. It tries to send an Exit command, and if that fails, it will send SIGQUIT to the server. It will also unmap the common area before it returns. */ static void KillDomainServer (void) { static boolean GotTheLock; static status_$t status; static pinteger index; DBG (1, "Asking Domain SANE Server to exit\n"); /* First, try to send a command to exit */ if (GotTheLock = mutex_$lock (&com->CommandLock, Wait16S)) { /* Set the wait time to 16 Seconds (units are 4uS) */ com->opcode = Exit; CommandTriggerValue[0] = ec2_$read (com->CommandAccepted) + 1; ec2_$advance (&com->CommandAvailable, &status); DomainErrorCheck (status, "Can't advance CommandAvailable EC"); /* For this wait, we want to allow a timeout as well */ CommandTriggerValue[1] = (ec2_$read (*CommandAcceptedPtr[1]) + DomainECWaitConstant); index = ec2_$wait_svc (CommandAcceptedPtr, CommandTriggerValue, 2, &status); DomainErrorCheck (status, "Error waiting on Exit command acceptance EC"); /* Release the lock */ mutex_$unlock (&com->CommandLock); if (index == 1) DBG (1, "Domain SANE Server responded to exit request\n"); else DBG (1, "Domain SANE Server did not respond to exit request\n"); } else DBG (0, "Could not get mutex lock for killing server\n"); if ((!GotTheLock) || (index != 1)) { /* If we get here, then we never got the mutex lock, or we timed out waiting for an Exit command ack. */ /* It's now time to be brutal with the server */ DBG (1, "Sending QUIT signal to Domain SANE Server\n"); kill (ServerPID, SIGQUIT); } /* unmap the common area */ ms_$unmap (com, sizeof (struct DomainServerCommon), &status); DomainErrorCheck (status, "Error unmapping common area"); } #endif /* USE == DOMAINOS_INTERFACE */ #if USE == OS2_INTERFACE /* Driver info: */ static HFILE driver_handle = 0; /* file handle for device driver */ static PVOID aspi_buf = 0; /* Big data buffer locked by driver. */ static int aspi_ref_count = 0; /* # of fds using ASPI */ static SRB *PSRBlock = 0; /* SCSI Request Block */ static char tmpAspi[MAXPATHLEN]; /* scsi chain scan */ #define INQUIRY 0x12 #define set_inquiry_return_size(icb,val) icb[0x04]=val #define IN_periph_devtype_cpu 0x03 #define IN_periph_devtype_scanner 0x06 #define get_inquiry_vendor(in, buf) strncpy(buf, in + 0x08, 0x08) #define get_inquiry_product(in, buf) strncpy(buf, in + 0x10, 0x010) #define get_inquiry_version(in, buf) strncpy(buf, in + 0x20, 0x04) #define get_inquiry_periph_devtype(in) (in[0] & 0x1f) #define get_inquiry_additional_length(in) in[0x04] #define set_inquiry_length(out,n) out[0x04]=n-5 /* Open OS2 ASPI driver. Output: 0 if error, which is reported. */ static int open_aspi (void) { ULONG rc; ULONG ActionTaken; USHORT lockSegmentReturn; unsigned long cbreturn = 0; unsigned long cbParam = 0; int i, num_adapters; /* no. of scsi adapters installed */ char *devtypes[] = { "disk", "tape", "printer", "processor", "CD-writer", "CD-drive", "scanner", "optical-drive", "jukebox", "communicator" }; FILE *tmp; if (driver_handle) { aspi_ref_count++; /* increment internal usage counter */ return 1; /* Already open. */ } aspi_buf = _tcalloc (sanei_scsi_max_request_size, 1); if (aspi_buf == NULL) { DBG (1, "sanei_scsi_open_aspi: _tcalloc aspi_buf failed"); return 0; } PSRBlock = _tcalloc (sizeof (SRB), 1); if (PSRBlock == NULL) { DBG (1, "sanei_scsi_open_aspi: _tcalloc PSRBlock failed"); return 0; } rc = DosOpen ((PSZ) "aspirou$", /* open driver */ &driver_handle, &ActionTaken, 0, 0, FILE_OPEN, OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, NULL); if (rc) { /* opening failed -> return false */ DBG (1, "open_aspi: opening failed.\n"); return 0; } /* Lock aspi_buf. */ rc = DosDevIOCtl (driver_handle, 0x92, 0x04, /* pass aspi_buf pointer */ (void *) aspi_buf, sizeof (PVOID), /* to driver */ &cbParam, (void *) &lockSegmentReturn, sizeof (USHORT), &cbreturn); if (rc || lockSegmentReturn) { /* DosDevIOCtl failed */ DBG (1, "sanei_scsi_open_aspi: Can't lock buffer. rc= %lu \n", rc); return 0; } /* query number of installed adapters */ memset (PSRBlock, 0, sizeof (SRB)); PSRBlock->cmd = SRB_Inquiry; /* host adapter inquiry */ PSRBlock->ha_num = 0; /* host adapter number */ PSRBlock->flags = 0; /* no flags set */ rc = DosDevIOCtl (driver_handle, 0x92, 0x02, (void *) PSRBlock, sizeof (SRB), &cbParam, (void *) PSRBlock, sizeof (SRB), &cbreturn); num_adapters = PSRBlock->u.inq.num_ha; DBG (1, "OS/2: installed adapters %d\n", num_adapters); DBG (1, "OS/2: ASPI manager is '%s'\n", PSRBlock->u.inq.aspimgr_id); DBG (1, "OS/2: host adapter is '%s'\n", PSRBlock->u.inq.host_id); DBG (1, "OS/2: unique id is '%s'\n", PSRBlock->u.inq.unique_id); strcpy (tmpAspi, "asXXXXXX"); mktemp (tmpAspi); DBG (2, "open_aspi: open temporary file '%s'\n", tmpAspi); tmp = fopen (tmpAspi, "w"); if (!tmp) { /* can't open tmp file */ DBG (1, "open_aspi: Can't open temporary file.\n"); return 0; } /* scan all installed adapters */ for (i = 0; i < num_adapters; i++) { int id; /* query adapter name */ memset (PSRBlock, 0, sizeof (SRB)); PSRBlock->cmd = SRB_Inquiry; /* host adapter inquiry */ PSRBlock->ha_num = i; /* host adapter number */ PSRBlock->flags = 0; /* no flags set */ rc = DosDevIOCtl (driver_handle, 0x92, 0x02, (void *) PSRBlock, sizeof (SRB), &cbParam, (void *) PSRBlock, sizeof (SRB), &cbreturn); DBG (1, "OS/2: adapter#%02d '%s'\n", i, PSRBlock->u.inq.host_id); /* scan scsi chain (need 15 for wide?) */ for (id = 0; id < 7; id++) { unsigned char len; char vendor[9]; char product[17]; char version[5]; char *pp; memset (PSRBlock, 0, sizeof (SRB)); PSRBlock->cmd = SRB_Device; /* get device type */ PSRBlock->ha_num = i; /* host adapter number */ PSRBlock->flags = 0; /* no flags set */ PSRBlock->u.dev.target = id; /* target id */ PSRBlock->u.dev.lun = 0; /* target LUN */ rc = DosDevIOCtl (driver_handle, 0x92, 0x02, (void *) PSRBlock, sizeof (SRB), &cbParam, (void *) PSRBlock, sizeof (SRB), &cbreturn); DBG (1, "OS/2: id#%02d status=%02xh\n", id, PSRBlock->status); /* skip if device not connected */ if (PSRBlock->status == SRB_BadDevice) continue; DBG (1, "OS/2: type is '%s'\n", PSRBlock->u.dev.devtype < sizeof (devtypes) / sizeof (char *)? devtypes[PSRBlock->u.dev.devtype] : "unknown device"); /* query adapter string id */ memset (PSRBlock, 0, sizeof (SRB)); PSRBlock->cmd = SRB_Command; /* execute SCSI command */ PSRBlock->ha_num = i; /* host adapter number */ PSRBlock->flags = SRB_Read | SRB_Post; /* data transfer, posting */ PSRBlock->u.cmd.target = id; /* Target SCSI ID */ PSRBlock->u.cmd.lun = 0; /* Target SCSI LUN */ PSRBlock->u.cmd.data_len = 5; /* # of bytes transferred */ PSRBlock->u.cmd.sense_len = 32; /* length of sense buffer */ PSRBlock->u.cmd.data_ptr = NULL; /* pointer to data buffer */ PSRBlock->u.cmd.link_ptr = NULL; /* pointer to next SRB */ PSRBlock->u.cmd.cdb_len = 6; /* SCSI command length */ PSRBlock->u.cmd.cdb_st[0] = INQUIRY; /* inquiry command */ PSRBlock->u.cmd.cdb_st[1] = 0; /* ?? length */ PSRBlock->u.cmd.cdb_st[2] = 0; /* transfer length MSB */ PSRBlock->u.cmd.cdb_st[3] = 0; /* transfer length */ PSRBlock->u.cmd.cdb_st[4] = 5; /* transfer length LSB */ PSRBlock->u.cmd.cdb_st[5] = 0; rc = DosDevIOCtl (driver_handle, 0x92, 0x02, (void *) PSRBlock, sizeof (SRB), &cbParam, (void *) PSRBlock, sizeof (SRB), &cbreturn); len = ((char *) aspi_buf)[4]; /* additional length */ /* query id string */ memset (PSRBlock, 0, sizeof (SRB)); PSRBlock->cmd = SRB_Command; /* execute SCSI command */ PSRBlock->ha_num = i; /* host adapter number */ PSRBlock->flags = SRB_Read | SRB_Post; /* data transfer, posting */ PSRBlock->u.cmd.target = id; /* Target SCSI ID */ PSRBlock->u.cmd.lun = 0; /* Target SCSI LUN */ PSRBlock->u.cmd.data_len = 5 + len; /* # of bytes transferred */ PSRBlock->u.cmd.sense_len = 32; /* length of sense buffer */ PSRBlock->u.cmd.data_ptr = NULL; /* pointer to data buffer */ PSRBlock->u.cmd.link_ptr = NULL; /* pointer to next SRB */ PSRBlock->u.cmd.cdb_len = 6; /* SCSI command length */ PSRBlock->u.cmd.cdb_st[0] = 0x12; /* inquiry command */ PSRBlock->u.cmd.cdb_st[1] = 0; /* ?? length */ PSRBlock->u.cmd.cdb_st[2] = 0; /* transfer length MSB */ PSRBlock->u.cmd.cdb_st[3] = 0; /* transfer length */ PSRBlock->u.cmd.cdb_st[4] = 5 + len; /* transfer length LSB */ PSRBlock->u.cmd.cdb_st[5] = 0; rc = DosDevIOCtl (driver_handle, 0x92, 0x02, (void *) PSRBlock, sizeof (SRB), &cbParam, (void *) PSRBlock, sizeof (SRB), &cbreturn); DBG (1, "OS/2 '%s'\n", (char *) aspi_buf + 8); /* write data */ get_inquiry_vendor ((char *) aspi_buf, vendor); get_inquiry_product ((char *) aspi_buf, product); get_inquiry_version ((char *) aspi_buf, version); pp = &vendor[7]; vendor[8] = '\0'; while (pp >= vendor && (*pp == ' ' || *pp >= 127)) *pp-- = '\0'; pp = &product[15]; product[16] = '\0'; while (pp >= product && (*pp == ' ' || *pp >= 127)) *pp-- = '\0'; pp = product; do { if (isspace ((int) *pp)) *pp = '_'; } while (*++pp); pp = &version[3]; version[4] = '\0'; while (pp >= version && (*pp == ' ' || *(pp - 1) >= 127)) *pp-- = '\0'; fprintf (tmp, "Vendor: %s ", vendor); fprintf (tmp, "Model: %s ", product); fprintf (tmp, "Rev: %s ", version); fprintf (tmp, "scsi %d Channel: 0 Id: %d Lun: 0\n", i, id); } } DBG (2, "open_aspi: close temporary file '%s'\n", tmpAspi); fclose (tmp); aspi_ref_count++; /* increment internal usage counter */ return 1; } /* Close driver and free everything. */ static void close_aspi (void) { aspi_ref_count--; /* decrement internal usage counter */ if (aspi_ref_count) return; /* wait for usage==0 */ if (driver_handle) /* Close driver. */ DosClose (driver_handle); driver_handle = 0; if (aspi_buf) /* Free buffer. */ _tfree (aspi_buf); aspi_buf = 0; if (PSRBlock) _tfree (PSRBlock); PSRBlock = 0; errno = 0; if (unlink (tmpAspi)) /* remove scsi descriptions */ DBG (2, "OS/2: error#%d while removing temporary '%s'\n", errno, tmpAspi); strcpy (tmpAspi, ""); DBG (1, "OS/2: ASPI closed\n"); } #endif /* USE_OS2_INTERFACE */ static int num_alloced = 0; #if USE == LINUX_INTERFACE static int sg_version = 0; static SANE_Status get_max_buffer_size (const char *file) { int fd = -1; int buffersize = SCSIBUFFERSIZE, i; size_t len; char *cc, *cc1, buf[32]; #ifdef HAVE_RESMGR fd = rsm_open_device(file, O_RDWR); #endif if (fd == -1) fd = open (file, O_RDWR); if (fd > 0) { cc = getenv ("SANE_SG_BUFFERSIZE"); if (cc) { i = strtol (cc, &cc1, 10); if (cc != cc1 && i >= 32768) buffersize = i; } ioctl (fd, SG_SET_RESERVED_SIZE, &buffersize); if (0 == ioctl (fd, SG_GET_RESERVED_SIZE, &buffersize)) { if (buffersize < sanei_scsi_max_request_size) sanei_scsi_max_request_size = buffersize; close (fd); DBG (4, "get_max_buffer_size for %s: %i\n", file, sanei_scsi_max_request_size); return SANE_STATUS_GOOD; } else { close (fd); /* ioctl not available: we have the old SG driver */ fd = open ("/proc/sys/kernel/sg-big-buff", O_RDONLY); if (fd > 0 && (len = read (fd, buf, sizeof (buf) - 1)) > 0) { buf[len] = '\0'; sanei_scsi_max_request_size = atoi (buf); close (fd); } else sanei_scsi_max_request_size = buffersize < SG_BIG_BUFF ? buffersize : SG_BIG_BUFF; return SANE_STATUS_IO_ERROR; } } else return SANE_STATUS_GOOD; } SANE_Status sanei_scsi_open_extended (const char *dev, int *fdp, SANEI_SCSI_Sense_Handler handler, void *handler_arg, int *buffersize) #else SANE_Status sanei_scsi_open (const char *dev, int *fdp, SANEI_SCSI_Sense_Handler handler, void *handler_arg) #endif { u_int bus = 0, target = 0, lun = 0, fake_fd = 0; char *real_dev = 0; void *pdata = 0; char *cc, *cc1; int fd, i; #if USE == LINUX_INTERFACE static int first_time = 1; #elif USE == MACOSX_INTERFACE UInt8 *guid; int len; u_int d; #endif cc = getenv ("SANE_SCSICMD_TIMEOUT"); if (cc) { i = strtol (cc, &cc1, 10); /* 20 minutes are hopefully enough as a timeout value ;) */ if (cc != cc1 && i > 0 && i <= 1200) { sane_scsicmd_timeout = i; } else { DBG (1, "sanei_scsi_open: timeout value must be between 1 and 1200 seconds\n"); } } DBG_INIT (); #if USE == LINUX_INTERFACE if (first_time) { first_time = 0; /* Try to determine a reliable value for sanei_scsi_max_request_size: With newer versions of the SG driver, check the available buffer size by opening all SG device files belonging to a scanner, issue the ioctl calls for setting and reading the reserved buffer size, and take the smallest value. For older version of the SG driver, which don't support variable buffer size, try to read /proc/sys/kernel/sg-big-biff ; if this fails (SG driver too old, or loaded as a module), use SG_BIG_BUFF */ sanei_scsi_max_request_size = SCSIBUFFERSIZE; cc = getenv ("SANE_SG_BUFFERSIZE"); if (cc) { i = strtol (cc, &cc1, 10); if (cc != cc1 && i >= 32768) sanei_scsi_max_request_size = i; } sanei_scsi_find_devices (0, 0, "Scanner", -1, -1, -1, -1, get_max_buffer_size); sanei_scsi_find_devices (0, 0, "Processor", -1, -1, -1, -1, get_max_buffer_size); DBG (4, "sanei_scsi_open: sanei_scsi_max_request_size=%d bytes\n", sanei_scsi_max_request_size); } #endif #if USE == OS2_INTERFACE if (sscanf (dev, "b%ut%ul%u", &bus, &target, &lun) != 3) { DBG (1, "sanei_scsi_open: device name %s is not valid\n", dev); return SANE_STATUS_INVAL; } if (!open_aspi ()) { /* Open driver if necessary. */ close_aspi (); return SANE_STATUS_INVAL; } /* Find fake fd. */ for (fd = 0; fd < num_alloced; ++fd) if (!fd_info[fd].in_use) break; fake_fd = 1; #elif USE == DECUNIX_INTERFACE { UAGT_CAM_SCAN cam_scan; if (sscanf (dev, "b%dt%dl%d", &bus, &target, &lun) != 3) { DBG (1, "sanei_scsi_open: device name `%s´ is not valid: %s\n", dev, strerror (errno)); return SANE_STATUS_INVAL; } if (cam_fd < 0) { cam_fd = open ("/dev/cam", O_RDWR); if (cam_fd < 0) { DBG (1, "sanei_scsi_open: open(/dev/cam) failed: %s\n", strerror (errno)); return SANE_STATUS_INVAL; } } cam_scan.ucs_bus = bus; cam_scan.ucs_target = target; cam_scan.ucs_lun = lun; if (ioctl (cam_fd, UAGT_CAM_SINGLE_SCAN, &cam_scan) < 0) { DBG (1, "sanei_scsi_open: ioctl(UAGT_CAM_SINGLE_SCAN) failed: %s\n", strerror (errno)); return SANE_STATUS_INVAL; } for (fd = 0; fd < num_alloced; ++fd) if (!fd_info[fd].in_use) break; fake_fd = 1; } #elif USE == DOMAINOS_INTERFACE { static int index; static status_$t status; static unsigned long length_mapped; DBG (1, "sanei_scsi_open: (dev='%s', int * fdp=%p, " "SANEI_SCSI_Sense_Handler handler=%p)\n", dev, fdp, handler); /* See if the server process has started yet */ if (!ServerInitialized) { static char *CommonAreaPath; /* Initialize the server */ DBG (2, "Initializing Domain Server\n"); /* Map the area */ CommonAreaPath = tmpnam (NULL); DBG (2, "Domain Server Common area name is '%s'\n", CommonAreaPath); com = ms_$crmapl (CommonAreaPath, strlen (CommonAreaPath), 0, sizeof (struct DomainServerCommon), ms_$cowriters, &status); DomainErrorCheck (status, "Can't open common area"); DBG (2, "Domain Server common area mapped\n"); /* Initialize the eventcounts */ ec2_$init (&com->CommandAvailable); ec2_$init (&com->CommandAccepted); ec2_$init (&com->ResultReady); ec2_$init (&com->ResultAccepted); DBG (2, "Domain Server EC's initialized\n"); /* Initialize the mutex locks */ mutex_$init (&com->CommandLock); mutex_$init (&com->ResultLock); DBG (2, "Domain Server MutexLock's initialized\n"); /* Initialize pointers to ECs */ CommandAcceptedPtr[0] = &com->CommandAccepted; ResultReadyPtr[0] = &com->ResultReady; time_$get_ec (time_$clockh_key, &CommandAcceptedPtr[1], &status); DomainErrorCheck (status, "Can't get time EC"); ResultReadyPtr[1] = CommandAcceptedPtr[1]; /* Read the ResultReady EC value, to avoid race with the server */ ResultTriggerValue[0] = ec2_$read (com->ResultReady) + 1; /* Now invoke the server */ ServerPID = fork (); if (!ServerPID) { /* I am the child, call the initialization routine */ sanei_DomainOS_init (CommonAreaPath); /* We get here when the server is done, so we just exit. */ exit (EXIT_SUCCESS); } /* The communication area is open, wait for the initial response */ ResultTriggerValue[1] = (ec2_$read (*ResultReadyPtr[1]) + DomainECWaitConstant); index = ec2_$wait_svc (ResultReadyPtr, ResultTriggerValue, 2, &status); DomainErrorCheck (status, "Error waiting on initial open EC"); if (index != 1) { DBG (0, "Domain SANE Server never responded on startup\n"); /* Send a quit signal to the server */ kill (ServerPID, SIGQUIT); return SANE_STATUS_INVAL; } /* Register a function to kill the server when we are done */ assert (!atexit (KillDomainServer)); ServerInitialized = 1; } /* Find fake fd. */ for (fd = 0; fd < num_alloced; ++fd) if (!fd_info[fd].in_use) break; fake_fd = 1; /* Send the command open to the server */ if (!mutex_$lock (&com->CommandLock, Wait16S)) { DBG (0, "Could not obtain mutex lock for Open\n"); return SANE_STATUS_INVAL; } com->opcode = Open; strcpy (com->open_path, dev); CommandTriggerValue[0] = ec2_$read (com->CommandAccepted) + 1; ec2_$advance (&com->CommandAvailable, &status); DomainErrorCheck (status, "Can't advance CommandAvailable EC"); CommandTriggerValue[1] = (ec2_$read (*CommandAcceptedPtr[1]) + DomainECWaitConstant); index = ec2_$wait_svc (CommandAcceptedPtr, CommandTriggerValue, 2, &status); DomainErrorCheck (status, "Error waiting on Open command acceptance EC"); if (index != 1) { DBG (0, "Domain SANE Server never accepted Open Command\n"); return SANE_STATUS_INVAL; } /* Read the result */ status = com->CommandStatus; DomainErrorCheck (status, "Opening device in server"); /* Now map the data area, and make it temporary */ DBG (2, "Mapping server's data block, name is '%s'\n", com->open_path); pdata = ms_$mapl (com->open_path, strlen (com->open_path), 0, DomainMaxDataSize + DomainSenseSize, ms_$cowriters, ms_$wr, true, &length_mapped, &status); DomainErrorCheck (status, "Mapping Server Data block"); assert (length_mapped >= DomainMaxDataSize + DomainSenseSize); ms_$mk_temporary (pdata, &status); DomainErrorCheck (status, "Can't make data block temporary"); /* Release the lock */ mutex_$unlock (&com->CommandLock); if (status.all != status_$ok) { /* we have a failure, return an error code, and generate debug output */ DBG (1, "sanei_scsi_open: acquire failed, Domain/OS status is %08x\n", status.all); error_$print (status); return SANE_STATUS_INVAL; } else { /* device acquired, what else to do? */ fd = com->fd; } } #elif USE == FREEBSD_CAM_INTERFACE if (1) { /* 'if(1) {' makes my emacs c-mode indent better than just '{' unfortunately, this only works if all of the '{' are that way. */ struct cam_device *curdev; fake_fd = 1; fd = -1; if ((curdev = cam_open_pass (dev, O_RDWR, NULL)) != NULL) { for (fd = 0; fd < CAM_MAXDEVS && cam_devices[fd] != NULL; fd++) ; if (fd == CAM_MAXDEVS) { DBG (1, "sanei_scsi_open: too many CAM devices (%d)\n", fd); cam_close_device (curdev); return SANE_STATUS_INVAL; } cam_devices[fd] = curdev; } else { DBG (1, "sanei_scsi_open: can't open device `%s´: %s\n", dev, strerror (errno)); return SANE_STATUS_INVAL; } } #elif USE == SCO_UW71_INTERFACE { pt_scsi_address_t dev_addr; pt_handle_t pt_handle; int bus, cnt, id, lun; if (4 != sscanf (dev, "/dev/passthru0:%d,%d,%d,%d", &bus, &cnt, &id, &lun)) { DBG (1, "sanei_scsi_open: device name `%s´ is not valid: %s\n", dev, strerror (errno)); return SANE_STATUS_INVAL; } dev_addr.psa_bus = bus; dev_addr.psa_controller = cnt; dev_addr.psa_target = id; dev_addr.psa_lun = lun; if (0 != pt_open (PASSTHRU_SCSI_ADDRESS, &dev_addr, PT_EXCLUSIVE, &pt_handle)) { DBG (1, "sanei_scsi_open: pt_open failed: %s!\n", strerror (errno)); return SANE_STATUS_INVAL; } else fd = (int) pt_handle; } #elif USE == MACOSX_INTERFACE { # if defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) len = strlen (dev); if (len > 2 && len % 2 == 0 && dev [0] == '<' && dev [len - 1] == '>') { len = (len - 2) / 2; guid = (UInt8 *) malloc (len); for (i = 0; i < len; i++) { if (sscanf (&dev [2 * i + 1], "%02x", &d) != 1) break; guid [i] = d; } if (i == len) pdata = (void *) CFDataCreate (kCFAllocatorDefault, guid, len); free (guid); } # endif # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H if ((pdata == NULL) && (sscanf (dev, "u%ut%ul%u", &bus, &target, &lun) != 3)) # else if (pdata == NULL) # endif { DBG (1, "sanei_scsi_open: device name %s is not valid\n", dev); return SANE_STATUS_INVAL; } /* Find fake fd. */ for (fd = 0; fd < num_alloced; ++fd) if (!fd_info[fd].in_use) break; fake_fd = 1; } #elif USE == WIN32_INTERFACE { char scsi_hca_name[20]; u_int hca = 0; if (sscanf (dev, "h%ub%ut%ul%u", &hca, &bus, &target, &lun) != 4) { DBG (1, "sanei_scsi_open: device name %s is not valid\n", dev); return SANE_STATUS_INVAL; } snprintf(scsi_hca_name, 19, "\\\\.\\Scsi%d:", hca); scsi_hca_name[19] = 0; fd = CreateFile(scsi_hca_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL ); if (fd == INVALID_HANDLE_VALUE) fd = -1; } #else #if defined(SGIOCSTL) || (USE == SOLARIS_INTERFACE) { size_t len; /* OpenStep and the Solaris SCG driver are a bit broken in that the device name refers to a scsi _bus_, not an individual scsi device. Hence, SANE has to fudge with the device name so we know which target to connect to. For this purpose, we use the last character in the device name as the target index. 'a' is target 0, 'b', target 1, and so on... */ len = strlen (dev); if (len <= 1) { DBG (1, "sanei_scsi_open: devicename `%s' too short\n", dev); return SANE_STATUS_INVAL; } real_dev = strdup (dev); real_dev[len - 1] = '\0'; target = dev[len - 1] - 'a'; if (target > 7) { DBG (1, "sanei_scsi_open: `%c' is not a valid target id\n", dev[len - 1]); return SANE_STATUS_INVAL; } dev = real_dev; } #endif /* defined(SGIOCSTL) || (USE == SOLARIS_INTERFACE) */ fd = -1; #ifdef HAVE_RESMGR fd = rsm_open_device(dev, O_RDWR | O_EXCL | O_NONBLOCK); #endif if (fd == -1) fd = open (dev, O_RDWR | O_EXCL #if USE == LINUX_INTERFACE | O_NONBLOCK #endif ); if (fd < 0) { SANE_Status status = SANE_STATUS_INVAL; if (errno == EACCES) status = SANE_STATUS_ACCESS_DENIED; else if (errno == EBUSY) status = SANE_STATUS_DEVICE_BUSY; DBG (1, "sanei_scsi_open: open of `%s' failed: %s\n", dev, strerror (errno)); return status; } if (real_dev) free (real_dev); #ifdef SG_SET_TIMEOUT /* Set large timeout since some scanners are slow but do not disconnect... ;-( */ { int timeout; timeout = sane_scsicmd_timeout * GNU_HZ; ioctl (fd, SG_SET_TIMEOUT, &timeout); } #endif #ifdef SGIOCSTL { struct scsi_adr sa; sa.sa_target = target; sa.sa_lun = 0; if (ioctl (fd, SGIOCSTL, &sa) == -1) { DBG (1, "sanei_scsi_open: failed to attach to target: %u (%s)\n", sa.sa_target, strerror (errno)); return SANE_STATUS_INVAL; } } #endif /* SGIOCSTL */ #if USE == LINUX_INTERFACE { SG_scsi_id sid; int ioctl_val; int real_buffersize; fdparms *fdpa = 0; SG_scsi_id devinfo; pdata = fdpa = malloc (sizeof (fdparms)); if (!pdata) { close (fd); return SANE_STATUS_NO_MEM; } memset (fdpa, 0, sizeof (fdparms)); /* default: allow only one command to be sent to the SG driver */ fdpa->sg_queue_max = 1; /* Try to read the SG version. If the ioctl call is successful, we have the new SG driver, and we can increase the buffer size using another ioctl call. If we have SG version 2.1.35 or above, we can additionally enable command queueing. */ if (0 == ioctl (fd, SG_GET_VERSION_NUM, &sg_version)) { DBG (1, "sanei_scsi_open: SG driver version: %i\n", sg_version); ioctl_val = ioctl (fd, SG_GET_SCSI_ID, &devinfo); if (ioctl_val == EINVAL || ioctl_val == ENOTTY) { DBG (1, "sanei_scsi_open: The file %s is not an SG device file\n", dev); close (fd); return SANE_STATUS_INVAL; } if (devinfo.scsi_type != 6 && devinfo.scsi_type != 3) { DBG (1, "sanei_scsi_open: The device found for %s does not look like a scanner\n", dev); close (fd); return SANE_STATUS_INVAL; } /* try to reserve a SG buffer of the size specified by *buffersize */ ioctl (fd, SG_SET_RESERVED_SIZE, buffersize); /* the set call may not be able to allocate as much memory as requested, thus we read the actual buffer size. */ if (0 == ioctl (fd, SG_GET_RESERVED_SIZE, &real_buffersize)) { /* if we got more memory than requested, we stick with with the requested value, in order to allow sanei_scsi_open to check the buffer size exactly. */ if (real_buffersize < *buffersize) *buffersize = real_buffersize; fdpa->buffersize = *buffersize; } else { DBG (1, "sanei_scsi_open: cannot read SG buffer size - %s\n", strerror (errno)); close (fd); return SANE_STATUS_NO_MEM; } DBG (1, "sanei_scsi_open_extended: using %i bytes as SCSI buffer\n", *buffersize); if (sg_version >= 20135) { DBG (1, "trying to enable low level command queueing\n"); if (0 == ioctl (fd, SG_GET_SCSI_ID, &sid)) { DBG (1, "sanei_scsi_open: Host adapter queue depth: %i\n", sid.d_queue_depth); ioctl_val = 1; if (0 == ioctl (fd, SG_SET_COMMAND_Q, &ioctl_val)) { fdpa->sg_queue_max = sid.d_queue_depth; if (fdpa->sg_queue_max <= 0) fdpa->sg_queue_max = 1; } } } } else { /* we have a really old SG driver version, or we're not opening an SG device file */ if (ioctl (fd, SG_GET_TIMEOUT, &ioctl_val) < 0) { DBG (1, "sanei_scsi_open: The file %s is not an SG device file\n", dev); close (fd); return SANE_STATUS_INVAL; } if (sanei_scsi_max_request_size < *buffersize) *buffersize = sanei_scsi_max_request_size; fdpa->buffersize = *buffersize; } if (sg_version == 0) { DBG (1, "sanei_scsi_open: using old SG driver logic\n"); } else { DBG (1, "sanei_scsi_open: SG driver can change buffer size at run time\n"); if (fdpa->sg_queue_max > 1) DBG (1, "sanei_scsi_open: low level command queueing enabled\n"); #ifdef SG_IO if (sg_version >= 30000) { DBG (1, "sanei_scsi_open: using new SG header structure\n"); } #endif } } #endif /* LINUX_INTERFACE */ #endif /* !DECUNIX_INTERFACE */ /* Note: this really relies on fd to start small. Windows starts a little higher than 3. */ if (fd >= num_alloced) { size_t new_size, old_size; old_size = num_alloced * sizeof (fd_info[0]); num_alloced = fd + 8; new_size = num_alloced * sizeof (fd_info[0]); if (fd_info) fd_info = realloc (fd_info, new_size); else fd_info = malloc (new_size); memset ((char *) fd_info + old_size, 0, new_size - old_size); if (!fd_info) { if (!fake_fd) close (fd); return SANE_STATUS_NO_MEM; } } fd_info[fd].in_use = 1; fd_info[fd].sense_handler = handler; fd_info[fd].sense_handler_arg = handler_arg; fd_info[fd].fake_fd = fake_fd; fd_info[fd].bus = bus; fd_info[fd].target = target; fd_info[fd].lun = lun; fd_info[fd].pdata = pdata; #if USE == SOLARIS_INTERFACE || USE == SOLARIS_USCSI_INTERFACE /* verify that the device really exists: */ if (!unit_ready (fd)) { sanei_scsi_close (fd); return SANE_STATUS_INVAL; } #endif #if USE == SYSVR4_INTERFACE memset (lastrcmd, 0, 16); /* reinitialize last read command block */ #endif if (fdp) *fdp = fd; return SANE_STATUS_GOOD; } #if USE == LINUX_INTERFACE /* The "wrapper" for the old open call */ SANE_Status sanei_scsi_open (const char *dev, int *fdp, SANEI_SCSI_Sense_Handler handler, void *handler_arg) { int i = 0; int wanted_buffersize = SCSIBUFFERSIZE, real_buffersize; SANE_Status res; char *cc, *cc1; static int first_time = 1; if (first_time) { cc = getenv ("SANE_SG_BUFFERSIZE"); if (cc) { i = strtol (cc, &cc1, 10); if (cc != cc1 && i >= 32768) wanted_buffersize = i; } } else wanted_buffersize = sanei_scsi_max_request_size; real_buffersize = wanted_buffersize; res = sanei_scsi_open_extended (dev, fdp, handler, handler_arg, &real_buffersize); /* make sure that we got as much memory as we wanted, otherwise the backend might be confused */ if (!first_time && real_buffersize != wanted_buffersize) { DBG (1, "sanei_scsi_open: could not allocate SG buffer memory " "wanted: %i got: %i\n", wanted_buffersize, real_buffersize); sanei_scsi_close (*fdp); return SANE_STATUS_NO_MEM; } first_time = 0; return res; } #else /* dummy for the proposed new open call */ SANE_Status sanei_scsi_open_extended (const char *dev, int *fdp, SANEI_SCSI_Sense_Handler handler, void *handler_arg, int *buffersize) { SANE_Status res; res = sanei_scsi_open (dev, fdp, handler, handler_arg); if (sanei_scsi_max_request_size < *buffersize) *buffersize = sanei_scsi_max_request_size; return res; } #endif void sanei_scsi_close (int fd) { #if USE == LINUX_INTERFACE if (fd_info[fd].pdata) { req *req, *next_req; /* make sure that there are no pending SCSI calls */ sanei_scsi_req_flush_all_extended (fd); req = ((fdparms *) fd_info[fd].pdata)->sane_free_list; while (req) { next_req = req->next; free (req); req = next_req; } free (fd_info[fd].pdata); } #endif fd_info[fd].in_use = 0; fd_info[fd].sense_handler = 0; fd_info[fd].sense_handler_arg = 0; #ifdef WIN32 CloseHandle(fd); #else if (!fd_info[fd].fake_fd) close (fd); #endif #if USE == FREEBSD_CAM_INTERFACE cam_close_device (cam_devices[fd]); cam_devices[fd] = NULL; #elif USE == DOMAINOS_INTERFACE { static int index; static status_$t status; DBG (1, "sanei_scsi_close: fd=%d\n", fd); /* Send the command to the server */ if (!mutex_$lock (&com->CommandLock, Wait16S)) { DBG (0, "Could not obtain mutex lock for Close command\n"); } else { com->opcode = Close; com->fd = fd; CommandTriggerValue[0] = ec2_$read (com->CommandAccepted) + 1; ec2_$advance (&com->CommandAvailable, &status); DomainErrorCheck (status, "Can't advance CommandAvailable EC"); CommandTriggerValue[1] = (ec2_$read (*CommandAcceptedPtr[1]) + DomainECWaitConstant); index = ec2_$wait_svc (CommandAcceptedPtr, CommandTriggerValue, 2, &status); DomainErrorCheck (status, "Error waiting on Close command acceptance EC"); if (index != 1) { DBG (0, "Domain SANE Server never accepted Close Command\n"); } /* Read the result */ status = com->CommandStatus; /* Release the lock */ mutex_$unlock (&com->CommandLock); } /* Unmap the data area */ ms_$unmap (fd_info[com->fd].pdata, DomainMaxDataSize + DomainSenseSize, &status); DomainErrorCheck (status, "Error unmapping device data area"); } #endif /* USE == DOMAINOS_INTERFACE */ #if USE == OS2_INTERFACE close_aspi (); #endif /* USE == OS2_INTERFACE */ #if USE == MACOSX_INTERFACE if (fd_info[fd].pdata) CFRelease (fd_info[fd].pdata); #endif /* USE == MACOSX_INTERFACE */ } #if USE == DOMAINOS_INTERFACE # define WE_HAVE_ASYNC_SCSI void sanei_scsi_req_flush_all (void) { status_$t status; DBG (1, "sanei_scsi_req_flush_all: ()\n"); /* I have never seen this called, and I'm not sure what to do with it, so I guarantee that it will generate a fault, and I can add support for it. */ assert (1 == 0); } SANE_Status sanei_scsi_req_enter2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size, void **idp) { SANEI_SCSI_Sense_Handler handler; static int index; static SANE_Status sane_status; static status_$t status; static scsi_$status_t SCSIStatus; static void *buf_ptr; if (dst_size) DBG (1, "sanei_scsi_req_enter2: (fd=%x, cmd=%p, cmd_size=%x, " "src=%p, src_size=%x, dst=%p, dst_size=%x, *idp=%p)\n", fd, cmd, cmd_size, src, src_size, dst, *dst_size, idp); else DBG (1, "sanei_scsi_req_enter2: (fd=%x, cmd=%p, cmd_size=%x, " "src=%p, src_size=%x, dst=%p, dst_size=NULL, *idp=%p)\n", fd, src, src_size, dst, idp); /* Lock the command structure */ if (!mutex_$lock (&com->CommandLock, mutex_$wait_forever)) { DBG (0, "Could not obtain mutex lock for Enter Command\n"); return SANE_STATUS_INVAL; } /* Fill in the command structure */ com->opcode = Enter; com->fd = fd; com->cdb_size = cmd_size; if (dst_size) com->dst_size = *dst_size; memcpy (&com->cdb, cmd, com->cdb_size); /* figure out if this is a read or a write */ if (dst_size && *dst_size) { /* dest buffer specified, must be a read */ /* assert (com->cdb_size == src_size); */ com->direction = scsi_read; buf_ptr = dst; com->buf_size = *dst_size; } else { /* no dest buffer, must be a write */ /* assert (com->cdb_size <= src_size); */ com->direction = scsi_write; buf_ptr = (char *) src; com->buf_size = src_size; if (com->buf_size) memcpy (fd_info[fd].pdata, buf_ptr, com->buf_size); } CommandTriggerValue[0] = ec2_$read (com->CommandAccepted) + 1; ec2_$advance (&com->CommandAvailable, &status); DomainErrorCheck (status, "Can't advance CommandAvailable EC"); CommandTriggerValue[1] = (ec2_$read (*CommandAcceptedPtr[1]) + DomainECWaitConstant); index = ec2_$wait_svc (CommandAcceptedPtr, CommandTriggerValue, 2, &status); DomainErrorCheck (status, "Error waiting on Enter command acceptance EC"); if (index != 1) { DBG (0, "Domain SANE Server never accepted Enter Command\n"); return SANE_STATUS_INVAL; } /* Read the result */ status = com->CommandStatus; SCSIStatus = com->SCSIStatus; /* Release the lock */ mutex_$unlock (&com->CommandLock); /* Now decode the return status */ if (status.all) DBG (1, "Server returned status %08x from Enter command\n", status.all); switch (status.all) { case status_$ok: sane_status = SANE_STATUS_GOOD; break; case scsi_$dma_underrun: sane_status = SANE_STATUS_IO_ERROR; /* This error is generated by the HP and UMAX backends. They ask for too much data. For now, the error is ignored :-( */ sane_status = SANE_STATUS_GOOD; break; case scsi_$operation_timeout: sane_status = SANE_STATUS_DEVICE_BUSY; break; case scsi_$hdwr_failure: /* received when both scanners were active */ sane_status = SANE_STATUS_IO_ERROR; break; case (status_$ok | 0x80000000): /* Special - no Domain/OS error, but fail bit set means to check SCSI operation status. */ DBG (1, "Server returned SCSI status of %08x\n", SCSIStatus); switch (SCSIStatus) { case scsi_check_condition: /* Call the sense handler, if defined */ handler = fd_info[com->fd].sense_handler; if (handler) (*handler) (fd, ((u_char *) fd_info[fd].pdata + DomainMaxDataSize), fd_info[com->fd].sense_handler_arg); sane_status = SANE_STATUS_IO_ERROR; break; case scsi_busy: sane_status = SANE_STATUS_DEVICE_BUSY; break; default: DBG (0, "Error - Unrecognized SCSI status %08x returned from " "Enter command\n", SCSIStatus); sane_status = SANE_STATUS_IO_ERROR; exit (EXIT_FAILURE); } break; default: DBG (0, "Unmapped status (%08x) returned from Domain SANE Server\n", status.all); sane_status = SANE_STATUS_IO_ERROR; } /* If a read, copy the data into the destination buffer */ if ((com->direction == scsi_read) && com->dst_size) memcpy (buf_ptr, fd_info[fd].pdata, com->dst_size); return sane_status; } SANE_Status sanei_scsi_req_wait (void *id) { SANE_Status status; DBG (1, "sanei_scsi_req_wait: (id=%p)\n", id); status = SANE_STATUS_GOOD; return status; } SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { SANE_Status status; void *id; DBG (1, "sanei_scsi_cmd2: (fd=%d)\n", fd); status = sanei_scsi_req_enter2 (fd, cmd, cmd_size, src, src_size, dst, dst_size, &id); if (status != SANE_STATUS_GOOD) return status; return sanei_scsi_req_wait (id); } #endif /* USE == DOMAINOS_INTERFACE */ #if USE == LINUX_INTERFACE #include #include #include #define WE_HAVE_ASYNC_SCSI #define WE_HAVE_FIND_DEVICES static int pack_id = 0; static int need_init = 1; static sigset_t all_signals; #define ATOMIC(s) \ do \ { \ sigset_t old_mask; \ \ if (need_init) \ { \ need_init = 0; \ sigfillset (&all_signals); \ } \ sigprocmask (SIG_BLOCK, &all_signals, &old_mask); \ {s;} \ sigprocmask (SIG_SETMASK, &old_mask, 0); \ } \ while (0) static void issue (struct req *req) { ssize_t nwritten; fdparms *fdp; struct req *rp; int retries; int ret; if (!req) return; fdp = (fdparms *) fd_info[req->fd].pdata; DBG (4, "sanei_scsi.issue: %p\n", (void *) req); rp = fdp->sane_qhead; while (rp && rp->running) rp = rp->next; while (rp && fdp->sg_queue_used < fdp->sg_queue_max) { retries = 20; while (retries) { errno = 0; #ifdef SG_IO if (sg_version < 30000) { #endif ATOMIC (rp->running = 1; nwritten = write (rp->fd, &rp->sgdata.cdb, rp->sgdata.cdb.hdr.pack_len); ret = 0; if (nwritten != rp->sgdata.cdb.hdr.pack_len) { /* ENOMEM can easily happen, if both command queueing inside the SG driver and large buffers are used. Therefore, if ENOMEM does not occur for the first command in the queue, we simply try to issue it later again. */ if (errno == EAGAIN || (errno == ENOMEM && rp != fdp->sane_qhead)) { /* don't try to send the data again, but wait for the next call to issue() */ rp->running = 0;} } ); #ifdef SG_IO } else { ATOMIC (rp->running = 1; ret = ioctl(rp->fd, SG_IO, &rp->sgdata.sg3.hdr); nwritten = 0; if (ret < 0) { /* ENOMEM can easily happen, if both command queuein inside the SG driver and large buffers are used. Therefore, if ENOMEM does not occur for the first command in the queue, we simply try to issue it later again. */ if (errno == EAGAIN || (errno == ENOMEM && rp != fdp->sane_qhead)) { /* don't try to send the data again, but wait for the next call to issue() */ rp->running = 0; } else /* game over */ { rp->running = 0; rp->done = 1; rp->status = SANE_STATUS_IO_ERROR; } } ); IF_DBG (if (DBG_LEVEL >= 255) system ("cat /proc/scsi/sg/debug 1>&2");) } #endif if (rp == fdp->sane_qhead && errno == EAGAIN) { retries--; usleep (10000); } else retries = 0; } #ifndef SG_IO if (nwritten != rp->sgdata.cdb.hdr.pack_len) #else if ((sg_version < 30000 && nwritten != rp->sgdata.cdb.hdr.pack_len) || (sg_version >= 30000 && ret < 0)) #endif { if (rp->running) { #ifdef SG_IO if (sg_version < 30000) #endif DBG (1, "sanei_scsi.issue: bad write (errno=%i) %s %li\n", errno, strerror (errno), (long)nwritten); #ifdef SG_IO else if (sg_version > 30000) DBG (1, "sanei_scsi.issue: SG_IO ioctl error (errno=%i, ret=%d) %s\n", errno, ret, strerror (errno)); #endif rp->done = 1; if (errno == ENOMEM) { DBG (1, "sanei_scsi.issue: SG_BIG_BUF inconsistency? " "Check file PROBLEMS.\n"); rp->status = SANE_STATUS_NO_MEM; } else rp->status = SANE_STATUS_IO_ERROR; } else { if (errno == ENOMEM) DBG (1, "issue: ENOMEM - cannot queue SCSI command. " "Trying again later.\n"); else DBG (1, "issue: EAGAIN - cannot queue SCSI command. " "Trying again later.\n"); } break; /* in case of an error don't try to queue more commands */ } else { #ifdef SG_IO if (sg_version < 30000) #endif req->status = SANE_STATUS_IO_ERROR; #ifdef SG_IO else if (sg_version > 30000) /* SG_IO is synchronous, we're all set */ req->status = SANE_STATUS_GOOD; #endif } fdp->sg_queue_used++; rp = rp->next; } } void sanei_scsi_req_flush_all_extended (int fd) { fdparms *fdp; struct req *req, *next_req; int len, count; fdp = (fdparms *) fd_info[fd].pdata; for (req = fdp->sane_qhead; req; req = next_req) { if (req->running && !req->done) { count = sane_scsicmd_timeout * 10; while (count) { errno = 0; #ifdef SG_IO if (sg_version < 30000) #endif len = read (fd, &req->sgdata.cdb, req->sgdata.cdb.hdr.reply_len); #ifdef SG_IO else len = read (fd, &req->sgdata.sg3.hdr, sizeof (Sg_io_hdr)); #endif if (len >= 0 || (len < 0 && errno != EAGAIN)) break; usleep (100000); count--; } ((fdparms *) fd_info[req->fd].pdata)->sg_queue_used--; } next_req = req->next; req->next = fdp->sane_free_list; fdp->sane_free_list = req; } fdp->sane_qhead = fdp->sane_qtail = 0; } void sanei_scsi_req_flush_all () { int fd, i, j = 0; /* sanei_scsi_open allows only one open file handle, so we can simply look for the first entry where in_use is set */ fd = num_alloced; for (i = 0; i < num_alloced; i++) if (fd_info[i].in_use) { j++; fd = i; } assert (j < 2); if (fd < num_alloced) sanei_scsi_req_flush_all_extended (fd); } SANE_Status sanei_scsi_req_enter2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size, void **idp) { struct req *req; size_t size; fdparms *fdp; fdp = (fdparms *) fd_info[fd].pdata; if (fdp->sane_free_list) { req = fdp->sane_free_list; fdp->sane_free_list = req->next; req->next = 0; } else { #ifdef SG_IO if (sg_version < 30000) #endif size = (sizeof (*req) - sizeof (req->sgdata.cdb.data) + fdp->buffersize); #ifdef SG_IO else size = sizeof (*req) + MAX_CDB + fdp->buffersize - sizeof (req->sgdata.sg3.data); #endif req = malloc (size); if (!req) { DBG (1, "sanei_scsi_req_enter: failed to malloc %lu bytes\n", (u_long) size); return SANE_STATUS_NO_MEM; } } req->fd = fd; req->running = 0; req->done = 0; req->status = SANE_STATUS_GOOD; req->dst = dst; req->dst_len = dst_size; #ifdef SG_IO if (sg_version < 30000) { #endif memset (&req->sgdata.cdb.hdr, 0, sizeof (req->sgdata.cdb.hdr)); req->sgdata.cdb.hdr.pack_id = pack_id++; req->sgdata.cdb.hdr.pack_len = cmd_size + src_size + sizeof (req->sgdata.cdb.hdr); req->sgdata.cdb.hdr.reply_len = (dst_size ? *dst_size : 0) + sizeof (req->sgdata.cdb.hdr); memcpy (&req->sgdata.cdb.data, cmd, cmd_size); memcpy (&req->sgdata.cdb.data[cmd_size], src, src_size); if (CDB_SIZE (*(const u_char *) cmd) != cmd_size) { if (ioctl (fd, SG_NEXT_CMD_LEN, &cmd_size)) { DBG (1, "sanei_scsi_req_enter2: ioctl to set command length failed\n"); } } #ifdef SG_IO } else { memset (&req->sgdata.sg3.hdr, 0, sizeof (req->sgdata.sg3.hdr)); req->sgdata.sg3.hdr.interface_id = 'S'; req->sgdata.sg3.hdr.cmd_len = cmd_size; req->sgdata.sg3.hdr.iovec_count = 0; req->sgdata.sg3.hdr.mx_sb_len = SENSE_MAX; /* read or write? */ if (dst_size && *dst_size) { req->sgdata.sg3.hdr.dxfer_direction = SG_DXFER_FROM_DEV; req->sgdata.sg3.hdr.dxfer_len = *dst_size; req->sgdata.sg3.hdr.dxferp = dst; } else if (src_size) { req->sgdata.sg3.hdr.dxfer_direction = SG_DXFER_TO_DEV; if (src_size > fdp->buffersize) { DBG (1, "sanei_scsi_req_enter2 warning: truncating write data " "from requested %li bytes to allowed %li bytes\n", (long)src_size, (long)fdp->buffersize); src_size = fdp->buffersize; } req->sgdata.sg3.hdr.dxfer_len = src_size; memcpy (&req->sgdata.sg3.data[MAX_CDB], src, src_size); req->sgdata.sg3.hdr.dxferp = &req->sgdata.sg3.data[MAX_CDB]; } else { req->sgdata.sg3.hdr.dxfer_direction = SG_DXFER_NONE; } if (cmd_size > MAX_CDB) { DBG (1, "sanei_scsi_req_enter2 warning: truncating write data " "from requested %li bytes to allowed %i bytes\n", (long)cmd_size, MAX_CDB); cmd_size = MAX_CDB; } memcpy (req->sgdata.sg3.data, cmd, cmd_size); req->sgdata.sg3.hdr.cmdp = req->sgdata.sg3.data; req->sgdata.sg3.hdr.sbp = &(req->sgdata.sg3.sense_buffer[0]); req->sgdata.sg3.hdr.timeout = 1000 * sane_scsicmd_timeout; #ifdef ENABLE_SCSI_DIRECTIO /* for the adventurous: If direct IO is used, the kernel locks the buffer. This can lead to conflicts, if a backend uses shared memory. OTOH, direct IO may be faster, and it reduces memory usage */ req->sgdata.sg3.hdr.flags = SG_FLAG_DIRECT_IO; #else req->sgdata.sg3.hdr.flags = 0; #endif req->sgdata.sg3.hdr.pack_id = pack_id++; req->sgdata.sg3.hdr.usr_ptr = 0; } #endif req->next = 0; ATOMIC (if (fdp->sane_qtail) { fdp->sane_qtail->next = req; fdp->sane_qtail = req;} else fdp->sane_qhead = fdp->sane_qtail = req); DBG (4, "scsi_req_enter: entered %p\n", (void *) req); *idp = req; issue (req); DBG (10, "scsi_req_enter: queue_used: %i, queue_max: %i\n", ((fdparms *) fd_info[fd].pdata)->sg_queue_used, ((fdparms *) fd_info[fd].pdata)->sg_queue_max); return SANE_STATUS_GOOD; } SANE_Status sanei_scsi_req_wait (void *id) { SANE_Status status = SANE_STATUS_GOOD; struct req *req = id; ssize_t nread = 0; /* we don't support out-of-order completion */ assert (req == ((fdparms *) fd_info[req->fd].pdata)->sane_qhead); DBG (4, "sanei_scsi_req_wait: waiting for %p\n", (void *) req); issue (req); /* ensure the command is running */ if (req->done) { issue (req->next); /* issue next command, if any */ status = req->status; } else { #ifdef SG_IO if (sg_version < 30000) { #endif fd_set readable; /* wait for command completion: */ FD_ZERO (&readable); FD_SET (req->fd, &readable); select (req->fd + 1, &readable, 0, 0, 0); /* now atomically read result and set DONE: */ ATOMIC (nread = read (req->fd, &req->sgdata.cdb, req->sgdata.cdb.hdr.reply_len); req->done = 1); #ifdef SG_IO } else { IF_DBG (if (DBG_LEVEL >= 255) system ("cat /proc/scsi/sg/debug 1>&2");) /* set DONE: */ nread = 0; /* unused in this code path */ req->done = 1; } #endif if (fd_info[req->fd].pdata) ((fdparms *) fd_info[req->fd].pdata)->sg_queue_used--; /* Now issue next command asap, if any. We can't do this earlier since the Linux kernel has space for just one big buffer. */ issue (req->next); DBG (4, "sanei_scsi_req_wait: read %ld bytes\n", (long) nread); if (nread < 0) { DBG (1, "sanei_scsi_req_wait: read returned %ld (errno=%d)\n", (long) nread, errno); status = SANE_STATUS_IO_ERROR; } else { #ifdef SG_IO if (sg_version < 30000) { #endif nread -= sizeof (req->sgdata.cdb.hdr); /* check for errors, but let the sense_handler decide.... */ if ((req->sgdata.cdb.hdr.result != 0) || (((req->sgdata.cdb.hdr.sense_buffer[0] & 0x7f) != 0) #ifdef HAVE_SG_TARGET_STATUS /* this is messy... Sometimes it happens that we have a valid looking sense buffer, but the DRIVER_SENSE bit is not set. Moreover, we can check this only for not tooo old SG drivers */ && (req->sgdata.cdb.hdr.driver_status & DRIVER_SENSE) #endif )) { SANEI_SCSI_Sense_Handler handler = fd_info[req->fd].sense_handler; void *arg = fd_info[req->fd].sense_handler_arg; DBG (1, "sanei_scsi_req_wait: SCSI command complained: %s\n", strerror (req->sgdata.cdb.hdr.result)); DBG (10, "sense buffer: %02x %02x %02x %02x %02x %02x %02x %02x" " %02x %02x %02x %02x %02x %02x %02x %02x\n", req->sgdata.cdb.hdr.sense_buffer[0], req->sgdata.cdb.hdr.sense_buffer[1], req->sgdata.cdb.hdr.sense_buffer[2], req->sgdata.cdb.hdr.sense_buffer[3], req->sgdata.cdb.hdr.sense_buffer[4], req->sgdata.cdb.hdr.sense_buffer[5], req->sgdata.cdb.hdr.sense_buffer[6], req->sgdata.cdb.hdr.sense_buffer[7], req->sgdata.cdb.hdr.sense_buffer[8], req->sgdata.cdb.hdr.sense_buffer[9], req->sgdata.cdb.hdr.sense_buffer[10], req->sgdata.cdb.hdr.sense_buffer[11], req->sgdata.cdb.hdr.sense_buffer[12], req->sgdata.cdb.hdr.sense_buffer[13], req->sgdata.cdb.hdr.sense_buffer[14], req->sgdata.cdb.hdr.sense_buffer[15]); #ifdef HAVE_SG_TARGET_STATUS /* really old SG header do not define target_status, host_status and driver_status */ DBG (10, "target status: %02x host status: %02x" " driver status: %02x\n", req->sgdata.cdb.hdr.target_status, req->sgdata.cdb.hdr.host_status, req->sgdata.cdb.hdr.driver_status); if (req->sgdata.cdb.hdr.host_status == DID_NO_CONNECT || req->sgdata.cdb.hdr.host_status == DID_BUS_BUSY || req->sgdata.cdb.hdr.host_status == DID_TIME_OUT || req->sgdata.cdb.hdr.driver_status == DRIVER_BUSY || req->sgdata.cdb.hdr.target_status == 0x04) /* BUSY */ #else if (req->sgdata.cdb.hdr.result == EBUSY) #endif status = SANE_STATUS_DEVICE_BUSY; else if (handler) /* sense handler should return SANE_STATUS_GOOD if it decided all was ok afterall */ status = (*handler) (req->fd, req->sgdata.cdb.hdr.sense_buffer, arg); else status = SANE_STATUS_IO_ERROR; } /* if we are ok so far, copy over the return data */ if (status == SANE_STATUS_GOOD) { if (req->dst) memcpy (req->dst, req->sgdata.cdb.data, nread); if (req->dst_len) *req->dst_len = nread; } #ifdef SG_IO } else { /* check for errors, but let the sense_handler decide.... */ if (((req->sgdata.sg3.hdr.info & SG_INFO_CHECK) != 0) || ((req->sgdata.sg3.hdr.sb_len_wr > 0) && ((req->sgdata.sg3.sense_buffer[0] & 0x7f) != 0) && (req->sgdata.sg3.hdr. driver_status & DRIVER_SENSE))) { SANEI_SCSI_Sense_Handler handler = fd_info[req->fd].sense_handler; void *arg = fd_info[req->fd].sense_handler_arg; DBG (1, "sanei_scsi_req_wait: SCSI command complained: %s\n", strerror (errno)); DBG (10, "sense buffer: %02x %02x %02x %02x %02x %02x %02x %02x" " %02x %02x %02x %02x %02x %02x %02x %02x\n", req->sgdata.sg3.sense_buffer[0], req->sgdata.sg3.sense_buffer[1], req->sgdata.sg3.sense_buffer[2], req->sgdata.sg3.sense_buffer[3], req->sgdata.sg3.sense_buffer[4], req->sgdata.sg3.sense_buffer[5], req->sgdata.sg3.sense_buffer[6], req->sgdata.sg3.sense_buffer[7], req->sgdata.sg3.sense_buffer[8], req->sgdata.sg3.sense_buffer[9], req->sgdata.sg3.sense_buffer[10], req->sgdata.sg3.sense_buffer[11], req->sgdata.sg3.sense_buffer[12], req->sgdata.sg3.sense_buffer[13], req->sgdata.sg3.sense_buffer[14], req->sgdata.sg3.sense_buffer[15]); DBG (10, "target status: %02x host status: %04x" " driver status: %04x\n", req->sgdata.sg3.hdr.status, req->sgdata.sg3.hdr.host_status, req->sgdata.sg3.hdr.driver_status); /* the first three tests below are an replacement of the error "classification" as it was with the old SG driver, the fourth test is new. */ if (req->sgdata.sg3.hdr.host_status == SG_ERR_DID_NO_CONNECT || req->sgdata.sg3.hdr.host_status == SG_ERR_DID_BUS_BUSY || req->sgdata.sg3.hdr.host_status == SG_ERR_DID_TIME_OUT || req->sgdata.sg3.hdr.driver_status == DRIVER_BUSY || req->sgdata.sg3.hdr.masked_status == 0x04) /* BUSY */ status = SANE_STATUS_DEVICE_BUSY; else if (handler && req->sgdata.sg3.hdr.sb_len_wr) /* sense handler should return SANE_STATUS_GOOD if it decided all was ok afterall */ status = (*handler) (req->fd, req->sgdata.sg3.sense_buffer, arg); /* status bits INTERMEDIATE and CONDITION MET should not result in an error; neither should reserved bits */ else if (((req->sgdata.sg3.hdr.status & 0x2a) == 0) && (req->sgdata.sg3.hdr.host_status == SG_ERR_DID_OK) && ((req->sgdata.sg3.hdr. driver_status & ~SG_ERR_DRIVER_SENSE) == SG_ERR_DRIVER_OK)) status = SANE_STATUS_GOOD; else status = SANE_STATUS_IO_ERROR; } #if 0 /* Sometimes the Linux SCSI system reports bogus resid values. Observed with lk 2.4.5, 2.4.13, aic7xxx and sym53c8xx drivers, if command queueing is used. So we better issue only a warning */ if (status == SANE_STATUS_GOOD) { if (req->dst_len) { *req->dst_len -= req->sgdata.sg3.hdr.resid; } } #endif if (req->sgdata.sg3.hdr.resid) { DBG (1, "sanei_scsi_req_wait: SG driver returned resid %i\n", req->sgdata.sg3.hdr.resid); DBG (1, " NOTE: This value may be bogus\n"); } } #endif } } /* dequeue and release processed request: */ ATOMIC (((fdparms *) fd_info[req->fd].pdata)->sane_qhead = ((fdparms *) fd_info[req->fd].pdata)->sane_qhead->next; if (!((fdparms *) fd_info[req->fd].pdata)->sane_qhead) ((fdparms *) fd_info[req->fd].pdata)->sane_qtail = 0; req->next = ((fdparms *) fd_info[req->fd].pdata)->sane_free_list; ((fdparms *) fd_info[req->fd].pdata)->sane_free_list = req); return status; } SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { SANE_Status status; void *id; status = sanei_scsi_req_enter2 (fd, cmd, cmd_size, src, src_size, dst, dst_size, &id); if (status != SANE_STATUS_GOOD) return status; return sanei_scsi_req_wait (id); } /* The following code (up to and including sanei_scsi_find_devices() ) is trying to match device/manufacturer names and/or SCSI addressing numbers (i.e. ) with a sg device file name (e.g. /dev/sg3). */ #define PROCFILE "/proc/scsi/scsi" #define DEVFS_MSK "/dev/scsi/host%d/bus%d/target%d/lun%d/generic" #define SCAN_MISSES 5 /* Some headers don't have the following define */ #ifndef SCSI_IOCTL_GET_IDLUN #define SCSI_IOCTL_GET_IDLUN 0x5382 #endif static int lx_sg_dev_base = -1; static int lx_devfs = -1; static const struct lx_device_name_list_tag { const char *prefix; char base; } lx_dnl[] = { { "/dev/sg", 0} , { "/dev/sg", 'a'} , { "/dev/uk", 0} , { "/dev/gsc", 0} }; static int /* Returns open sg file descriptor, or -1 for no access, or -2 for not found (or other error) */ lx_mk_devicename (int guess_devnum, char *name, size_t name_len) { int dev_fd, k, dnl_len; const struct lx_device_name_list_tag *dnp; dnl_len = NELEMS (lx_dnl); k = ((-1 == lx_sg_dev_base) ? 0 : lx_sg_dev_base); for (; k < dnl_len; ++k) { dnp = &lx_dnl[k]; if (dnp->base) snprintf (name, name_len, "%s%c", dnp->prefix, dnp->base + guess_devnum); else snprintf (name, name_len, "%s%d", dnp->prefix, guess_devnum); dev_fd = -1; #ifdef HAVE_RESMGR dev_fd = rsm_open_device (name, O_RDWR | O_NONBLOCK); #endif if (dev_fd == -1) dev_fd = open (name, O_RDWR | O_NONBLOCK); if (dev_fd >= 0) { lx_sg_dev_base = k; return dev_fd; } else if ((EACCES == errno) || (EBUSY == errno)) { lx_sg_dev_base = k; return -1; } if (-1 != lx_sg_dev_base) return -2; } return -2; } static int /* Returns 1 for match, else 0 */ lx_chk_id (int dev_fd, int host, int channel, int id, int lun) { #ifdef SG_GET_SCSI_ID_FOUND struct sg_scsi_id ssid; if ((ioctl (dev_fd, SG_GET_SCSI_ID, &ssid) >= 0)) { DBG (2, "lx_chk_id: %d,%d %d,%d %d,%d %d,%d\n", host, ssid.host_no, channel, ssid.channel, id, ssid.scsi_id, lun, ssid.lun); if ((host == ssid.host_no) && (channel == ssid.channel) && (id == ssid.scsi_id) && (lun == ssid.lun)) return 1; else return 0; } #endif { struct my_scsi_idlun { int dev_id; int host_unique_id; } my_idlun; if (ioctl (dev_fd, SCSI_IOCTL_GET_IDLUN, &my_idlun) >= 0) { if (((my_idlun.dev_id & 0xff) == id) && (((my_idlun.dev_id >> 8) & 0xff) == lun) && (((my_idlun.dev_id >> 16) & 0xff) == channel)) return 1; /* cheating, assume 'host' number matches */ } } return 0; } static int /* Returns 1 if match with 'name' set, else 0 */ lx_scan_sg (int exclude_devnum, char *name, size_t name_len, int host, int channel, int id, int lun) { int dev_fd, k, missed; if (-1 == lx_sg_dev_base) return 0; for (k = 0, missed = 0; (missed < SCAN_MISSES) && (k < 255); ++k, ++missed) { DBG (2, "lx_scan_sg: k=%d, exclude=%d, missed=%d\n", k, exclude_devnum, missed); if (k == exclude_devnum) { missed = 0; continue; /* assumed this one has been checked already */ } if ((dev_fd = lx_mk_devicename (k, name, name_len)) >= 0) { missed = 0; if (lx_chk_id (dev_fd, host, channel, id, lun)) { close (dev_fd); return 1; } close (dev_fd); } else if (-1 == dev_fd) missed = 0; /* no permissions but something found */ } return 0; } static int /* Returns 1 if match, else 0 */ lx_chk_devicename (int guess_devnum, char *name, size_t name_len, int host, int channel, int id, int lun) { int dev_fd; if (host < 0) return 0; if (0 != lx_devfs) { /* simple mapping if we have devfs */ if (-1 == lx_devfs) { if ((dev_fd = lx_mk_devicename (guess_devnum, name, name_len)) >= 0) close (dev_fd); /* hack to load sg driver module */ } snprintf (name, name_len, DEVFS_MSK, host, channel, id, lun); dev_fd = open (name, O_RDWR | O_NONBLOCK); if (dev_fd >= 0) { close (dev_fd); lx_devfs = 1; DBG (1, "lx_chk_devicename: matched device(devfs): %s\n", name); return 1; } else if (ENOENT == errno) lx_devfs = 0; } if ((dev_fd = lx_mk_devicename (guess_devnum, name, name_len)) < -1) { /* no candidate sg device file name found, try /dev/sg0,1 */ if ((dev_fd = lx_mk_devicename (0, name, name_len)) < -1) { if ((dev_fd = lx_mk_devicename (1, name, name_len)) < -1) return 0; /* no luck finding sg fd to open */ } } if (dev_fd >= 0) { /* now check this fd for match on */ if (lx_chk_id (dev_fd, host, channel, id, lun)) { close (dev_fd); DBG (1, "lx_chk_devicename: matched device(direct): %s\n", name); return 1; } close (dev_fd); } /* if mismatch then call scan algorithm */ if (lx_scan_sg (guess_devnum, name, name_len, host, channel, id, lun)) { DBG (1, "lx_chk_devicename: matched device(scan): %s\n", name); return 1; } return 0; } /* Legacy /proc/scsi/scsi */ static void /* calls 'attach' function pointer with sg device file name iff match */ sanei_proc_scsi_find_devices (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { #define FOUND_VENDOR 1 #define FOUND_MODEL 2 #define FOUND_TYPE 4 #define FOUND_REV 8 #define FOUND_HOST 16 #define FOUND_CHANNEL 32 #define FOUND_ID 64 #define FOUND_LUN 128 #define FOUND_ALL 255 char *me = "sanei_proc_scsi_find_devices"; size_t findvendor_len = 0, findmodel_len = 0, findtype_len = 0; char vendor[32], model[32], type[32], revision[32]; int bus, channel, id, lun; int number, i, j, definedd; char line[256], dev_name[128], *c1, *c2, ctmp; char *string; FILE *proc_fp; char *end; struct { const char *name; size_t name_len; int is_int; /* integer valued? (not a string) */ union { void *v; /* avoids compiler warnings... */ char *str; int *i; } u; } param[] = { { "Vendor:", 7, 0, { 0} } , { "Model:", 6, 0, { 0} } , { "Type:", 5, 0, { 0} } , { "Rev:", 4, 0, { 0} } , { "scsi", 4, 1, { 0} } , { "Channel:", 8, 1, { 0} } , { "Id:", 3, 1, { 0} } , { "Lun:", 4, 1, { 0} } }; param[0].u.str = vendor; param[1].u.str = model; param[2].u.str = type; param[3].u.str = revision; param[4].u.i = &bus; param[5].u.i = &channel; param[6].u.i = &id; param[7].u.i = &lun; DBG_INIT (); proc_fp = fopen (PROCFILE, "r"); if (!proc_fp) { DBG (1, "%s: could not open %s for reading\n", me, PROCFILE); return; } number = bus = channel = id = lun = -1; vendor[0] = model[0] = type[0] = '\0'; if (findvendor) findvendor_len = strlen (findvendor); if (findmodel) findmodel_len = strlen (findmodel); if (findtype) findtype_len = strlen (findtype); definedd = 0; while (!feof (proc_fp)) { fgets (line, sizeof (line), proc_fp); string = (char *) sanei_config_skip_whitespace (line); while (*string) { for (i = 0; i < NELEMS (param); ++i) { if (strncmp (string, param[i].name, param[i].name_len) == 0) { string += param[i].name_len; /* Make sure that we don't read the next parameter name as a value, if the real value consists only of spaces */ c2 = string + strlen (string); for (j = 0; j < NELEMS (param); ++j) { c1 = strstr (string, param[j].name); if ((j != i) && c1 && (c1 < c2)) c2 = c1; } ctmp = *c2; *c2 = 0; string = (char *) sanei_config_skip_whitespace (string); if (param[i].is_int) { if (*string) { *param[i].u.i = strtol (string, &end, 10); string = (char *) end; } else *param[i].u.i = 0; } else { strncpy (param[i].u.str, string, 32); param[i].u.str[31] = '\0'; /* while (*string && !isspace (*string)) ++string; */ } /* string = sanei_config_skip_whitespace (string); */ *c2 = ctmp; string = c2; definedd |= 1 << i; if (param[i].u.v == &bus) { ++number; definedd = FOUND_HOST; } break; } } if (i >= NELEMS (param)) ++string; /* no match */ } if (FOUND_ALL != definedd) /* some info is still missing */ continue; definedd = 0; if ((!findvendor || strncmp (vendor, findvendor, findvendor_len) == 0) && (!findmodel || strncmp (model, findmodel, findmodel_len) == 0) && (!findtype || strncmp (type, findtype, findtype_len) == 0) && (findbus == -1 || bus == findbus) && (findchannel == -1 || channel == findchannel) && (findid == -1 || id == findid) && (findlun == -1 || lun == findlun)) { DBG (2, "%s: found: vendor=%s model=%s type=%s\n\t" "bus=%d chan=%d id=%d lun=%d num=%d\n", me, findvendor, findmodel, findtype, bus, channel, id, lun, number); if (lx_chk_devicename (number, dev_name, sizeof (dev_name), bus, channel, id, lun) && ((*attach) (dev_name) != SANE_STATUS_GOOD)) { DBG(1,"sanei_scsi_find_devices: bad attach\n"); } } else { DBG (2, "%s: no match\n", me); } vendor[0] = model[0] = type[0] = 0; bus = channel = id = lun = -1; } fclose (proc_fp); } #define SYSFS_SCSI_DEVICES "/sys/bus/scsi/devices" /* From linux/drivers/scsi/scsi.c */ static char *lnxscsi_device_types[] = { "Direct-Access ", "Sequential-Access", "Printer ", "Processor ", "WORM ", "CD-ROM ", "Scanner ", "Optical Device ", "Medium Changer ", "Communications ", "ASC IT8 ", "ASC IT8 ", "RAID ", "Enclosure ", "Direct-Access-RBC", "Optical card ", "Bridge controller", "Object storage ", "Automation/Drive " }; void /* calls 'attach' function pointer with sg device file name iff match */ sanei_scsi_find_devices (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { char *me = "sanei_scsi_find_devices"; char path[PATH_MAX]; char dev_name[128]; struct dirent buf; struct dirent *de; DIR *scsidevs; FILE *fp; char *ptr; char *end; int bcil[4]; /* bus, channel, id, lun */ char vmt[3][33]; /* vendor, model, type */ int vmt_len[3]; char *vmtfiles[3] = { "vendor", "model", "type" }; int lastbus; int number; int i; long val; int ret; DBG_INIT (); DBG (2, "%s: looking for: v=%s m=%s t=%s b=%d c=%d i=%d l=%d\n", me, findvendor, findmodel, findtype, findbus, findchannel, findid, findlun); scsidevs = opendir (SYSFS_SCSI_DEVICES); if (!scsidevs) { DBG (1, "%s: could not open %s; falling back to /proc\n", me, SYSFS_SCSI_DEVICES); sanei_proc_scsi_find_devices (findvendor, findmodel, findtype, findbus, findchannel, findid, findlun, attach); return; } vmt_len[0] = (findvendor) ? strlen(findvendor) : 0; vmt_len[1] = (findmodel) ? strlen(findmodel) : 0; vmt_len[2] = (findtype) ? strlen(findtype) : 0; lastbus = -1; number = -1; for (;;) { ret = readdir_r(scsidevs, &buf, &de); if (ret != 0) { DBG (1, "%s: could not read directory %s: %s\n", me, SYSFS_SCSI_DEVICES, strerror(errno)); break; } if (de == NULL) break; if (buf.d_name[0] == '.') continue; /* Extract bus, channel, id, lun from directory name b:c:i:l */ ptr = buf.d_name; for (i = 0; i < 4; i++) { errno = 0; val = strtol (ptr, &end, 10); if (((errno == ERANGE) && ((val == LONG_MAX) || (val == LONG_MIN))) || ((errno != 0) && (val == 0))) { DBG (1, "%s: invalid integer in string (%s): %s\n", me, ptr, strerror(errno)); i = 12; /* Skip */ break; } if (end == ptr) { DBG (1, "%s: no integer found in string: %s (%d)\n", me, ptr, i); i = 12; /* Skip */ break; } if (*end && (*end != ':')) { DBG (1, "%s: parse error on string %s (%d)\n", me, buf.d_name, i); i = 12; /* Skip */ break; } if (val > INT_MAX) { DBG (1, "%s: integer value too large (%s)\n", me, buf.d_name); i = 12; /* Skip */ break; } bcil[i] = (int) val; ptr = end + 1; } /* Skip this one */ if (i == 12) continue; if (bcil[0] != lastbus) { lastbus = bcil[0]; number++; } for (i = 0; i < 3; i++) { ret = snprintf (path, PATH_MAX, "%s/%s/%s", SYSFS_SCSI_DEVICES, buf.d_name, vmtfiles[i]); if ((ret < 0) || (ret >= PATH_MAX)) { DBG (1, "%s: skipping %s/%s, PATH_MAX exceeded on %s\n", me, SYSFS_SCSI_DEVICES, buf.d_name, vmtfiles[i]); i = 12; /* Skip */ break; } memset (vmt[i], 0, sizeof(vmt[i])); fp = fopen(path, "r"); if (!fp) { DBG (1, "%s: could not open %s: %s\n", me, path, strerror(errno)); i = 12; /* Skip */ break; } ret = fread (vmt[i], 1, sizeof(vmt[i]) - 1, fp); if (ret <= 0) { if (ferror(fp)) { DBG (1, "%s: error reading %s\n", me, path); i = 12; /* Skip */ break; } } if (vmt[i][ret - 1] == '\n') vmt[i][ret - 1] = '\0'; fclose (fp); } /* Skip this one */ if (i == 12) continue; /* Type is a numeric string and must be converted back to a well-known string */ errno = 0; val = strtol (vmt[2], &end, 10); if (((errno == ERANGE) && ((val == LONG_MAX) || (val == LONG_MIN))) || ((errno != 0) && (val == 0))) { DBG (1, "%s: invalid integer in type string (%s): %s\n", me, vmt[2], strerror(errno)); continue; } if (end == vmt[2]) { DBG (1, "%s: no integer found in type string: %s\n", me, vmt[2]); continue; } if ((val < 0) || (val >= (int)(sizeof(lnxscsi_device_types) / sizeof(lnxscsi_device_types[0])))) { DBG (1, "%s: invalid type %ld\n", me, val); continue; } strncpy(vmt[2], lnxscsi_device_types[val], sizeof(vmt[2]) - 1); if ((!findvendor || strncmp (vmt[0], findvendor, vmt_len[0]) == 0) && (!findmodel || strncmp (vmt[1], findmodel, vmt_len[1]) == 0) && (!findtype || strncmp (vmt[2], findtype, vmt_len[2]) == 0) && (findbus == -1 || bcil[0] == findbus) && (findchannel == -1 || bcil[1] == findchannel) && (findid == -1 || bcil[2] == findid) && (findlun == -1 || bcil[3] == findlun)) { DBG (2, "%s: found: vendor=%s model=%s type=%s\n\t" "bus=%d chan=%d id=%d lun=%d num=%d\n", me, vmt[0], vmt[1], vmt[2], bcil[0], bcil[1], bcil[2], bcil[3], number); if (lx_chk_devicename (number, dev_name, sizeof (dev_name), bcil[0], bcil[1], bcil[2], bcil[3]) && ((*attach) (dev_name) != SANE_STATUS_GOOD)) { DBG (1, "%s: bad attach\n", me); } } else { DBG (2, "%s: no match\n", me); } } closedir(scsidevs); } #endif /* USE == LINUX_INTERFACE */ #if USE == BSD_INTERFACE #ifndef HAVE_SCSIREQ_ENTER static int scsireq_enter (int fd, scsireq_t * hdr) { return ioctl (fd, SCIOCCOMMAND, hdr); } #endif /* !HAVE_SCSIREQ_ENTER */ SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { /* xxx obsolete: size_t cdb_size; */ scsireq_t hdr; int result; /* xxx obsolete: cdb_size = CDB_SIZE (*(u_char *) src); */ memset (&hdr, 0, sizeof (hdr)); memcpy (hdr.cmd, cmd, cmd_size); if (dst_size && *dst_size) { /* xxx obsolete: assert (cdb_size == src_size); */ hdr.flags = SCCMD_READ; hdr.databuf = dst; hdr.datalen = *dst_size; } else { /* xxx obsolete: assert (cdb_size <= src_size); */ hdr.flags = SCCMD_WRITE; /* The old variant: hdr.databuf = (char *) src + cdb_size; hdr.datalen = src_size; xxxxxx huh? Shouldn´t the above line have been src_size - cdb_size) */ hdr.databuf = (char *) src; hdr.datalen = src_size; } hdr.timeout = sane_scsicmd_timeout * 1000; hdr.cmdlen = cmd_size; hdr.senselen = sizeof (hdr.sense); result = scsireq_enter (fd, &hdr); if (result < 0) { DBG (1, "sanei_scsi_cmd: scsi_reqenter() failed: %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if (hdr.retsts != SCCMD_OK) { SANEI_SCSI_Sense_Handler handler; DBG (1, "sanei_scsi_cmd: scsi returned with status %d\n", hdr.retsts); switch (hdr.retsts) { case SCCMD_TIMEOUT: case SCCMD_BUSY: return SANE_STATUS_DEVICE_BUSY; case SCCMD_SENSE: handler = fd_info[fd].sense_handler; if (handler) return (*handler) (fd, &hdr.sense[0], fd_info[fd].sense_handler_arg); /* fall through */ default: return SANE_STATUS_IO_ERROR; } } if (dst_size) *dst_size = hdr.datalen_used; return SANE_STATUS_GOOD; } #endif /* USE == BSD_INTERFACE */ #if USE == FREEBSD_CAM_INTERFACE SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { struct cam_device *dev; union ccb *ccb; int rv; u_int32_t ccb_flags; char *data_buf; size_t data_len; SANE_Status status; if (fd < 0 || fd > CAM_MAXDEVS || cam_devices[fd] == NULL) { fprintf (stderr, "attempt to reference invalid unit %d\n", fd); return SANE_STATUS_INVAL; } dev = cam_devices[fd]; ccb = cam_getccb (dev); /* Build the CCB */ bzero (&(&ccb->ccb_h)[1], sizeof (struct ccb_scsiio)); bcopy (cmd, &ccb->csio.cdb_io.cdb_bytes, cmd_size); /* * Set the data direction flags. */ if (dst_size && *dst_size) { /* xxx obsolete: assert (cdb_size == src_size); */ ccb_flags = CAM_DIR_IN; data_buf = ((char *) (dst)); data_len = *dst_size; } else if (src_size > 0) { ccb_flags = CAM_DIR_OUT; data_buf = ((char *) (src)); data_len = src_size; } else { ccb_flags = CAM_DIR_NONE; data_buf = NULL; data_len = 0; } cam_fill_csio (&ccb->csio, /* retries */ 1, /* cbfncp */ NULL, /* flags */ ccb_flags, /* tag_action */ MSG_SIMPLE_Q_TAG, /* data_ptr */ (u_int8_t *) data_buf, /* dxfer_len */ data_len, /* sense_len */ SSD_FULL_SIZE, /* cdb_len */ cmd_size, /* timeout */ sane_scsicmd_timeout * 1000); /* Run the command */ errno = 0; if ((rv = cam_send_ccb (dev, ccb)) == -1) { cam_freeccb (ccb); return (SANE_STATUS_IO_ERROR); } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { SANEI_SCSI_Sense_Handler handler; DBG (1, "sanei_scsi_cmd: scsi returned with status %d\n", (ccb->ccb_h.status & CAM_STATUS_MASK)); switch (ccb->ccb_h.status & CAM_STATUS_MASK) { case CAM_BUSY: case CAM_SEL_TIMEOUT: case CAM_SCSI_BUSY: status = SANE_STATUS_DEVICE_BUSY; break; default: status = SANE_STATUS_IO_ERROR; } handler = fd_info[fd].sense_handler; if (handler && (ccb->ccb_h.status & CAM_AUTOSNS_VALID)) { SANE_Status st = (*handler) (fd, ((u_char *) (&ccb->csio.sense_data)), fd_info[fd].sense_handler_arg); cam_freeccb (ccb); return st; } else { cam_freeccb (ccb); return status; } } cam_freeccb (ccb); return SANE_STATUS_GOOD; } #define WE_HAVE_FIND_DEVICES int cam_compare_inquiry (int fd, path_id_t path_id, target_id_t target_id, lun_id_t target_lun, const char *vendor, const char *product, const char *type) { struct ccb_dev_match cdm; struct device_match_pattern *pattern; struct scsi_inquiry_data *inq; int retval = 0; /* build ccb for device match */ bzero (&cdm, sizeof (cdm)); cdm.ccb_h.func_code = XPT_DEV_MATCH; /* result buffer */ cdm.match_buf_len = sizeof (struct dev_match_result); cdm.matches = (struct dev_match_result *) malloc (cdm.match_buf_len); cdm.num_matches = 0; /* pattern buffer */ cdm.num_patterns = 1; cdm.pattern_buf_len = sizeof (struct dev_match_pattern); cdm.patterns = (struct dev_match_pattern *) malloc (cdm.pattern_buf_len); /* assemble conditions */ cdm.patterns[0].type = DEV_MATCH_DEVICE; pattern = &cdm.patterns[0].pattern.device_pattern; pattern->flags = DEV_MATCH_PATH | DEV_MATCH_TARGET | DEV_MATCH_LUN; pattern->path_id = path_id; pattern->target_id = target_id; pattern->target_lun = target_lun; if (ioctl (fd, CAMIOCOMMAND, &cdm) == -1) { DBG (1, "error sending CAMIOCOMMAND ioctl"); retval = -1; goto ret; } if ((cdm.ccb_h.status != CAM_REQ_CMP) || ((cdm.status != CAM_DEV_MATCH_LAST) && (cdm.status != CAM_DEV_MATCH_MORE))) { DBG (1, "got CAM error %#x, CDM error %d\n", cdm.ccb_h.status, cdm.status); retval = -1; goto ret; } if (cdm.num_matches == 0) { DBG (1, "not found\n"); retval = -1; goto ret; } if (cdm.matches[0].type != DEV_MATCH_DEVICE) { DBG (1, "no device match\n"); retval = -1; goto ret; } inq = &cdm.matches[0].result.device_result.inq_data; if ((vendor && cam_strmatch (inq->vendor, vendor, SID_VENDOR_SIZE)) || (product && cam_strmatch (inq->product, product, SID_PRODUCT_SIZE))) retval = 1; ret: free (cdm.patterns); free (cdm.matches); return (retval); } void sanei_scsi_find_devices (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { int fd; struct ccb_dev_match cdm; struct periph_match_pattern *pattern; struct periph_match_result *result; int i; char devname[16]; DBG_INIT (); if ((fd = open (XPT_DEVICE, O_RDWR)) == -1) { DBG (1, "could not open %s\n", XPT_DEVICE); return; } /* build ccb for device match */ bzero (&cdm, sizeof (cdm)); cdm.ccb_h.func_code = XPT_DEV_MATCH; /* result buffer */ cdm.match_buf_len = sizeof (struct dev_match_result) * 100; cdm.matches = (struct dev_match_result *) malloc (cdm.match_buf_len); cdm.num_matches = 0; /* pattern buffer */ cdm.num_patterns = 1; cdm.pattern_buf_len = sizeof (struct dev_match_pattern); cdm.patterns = (struct dev_match_pattern *) malloc (cdm.pattern_buf_len); /* assemble conditions ... findchannel is ignored */ cdm.patterns[0].type = DEV_MATCH_PERIPH; pattern = &cdm.patterns[0].pattern.periph_pattern; pattern->flags = PERIPH_MATCH_NAME; strcpy (pattern->periph_name, "pass"); if (findbus != -1) { pattern->path_id = findbus; pattern->flags |= PERIPH_MATCH_PATH; } if (findid != -1) { pattern->target_id = findid; pattern->flags |= PERIPH_MATCH_TARGET; } if (findlun != -1) { pattern->target_lun = findlun; pattern->flags |= PERIPH_MATCH_LUN; } /* result loop */ do { if (ioctl (fd, CAMIOCOMMAND, &cdm) == -1) { DBG (1, "error sending CAMIOCOMMAND ioctl"); break; } if ((cdm.ccb_h.status != CAM_REQ_CMP) || ((cdm.status != CAM_DEV_MATCH_LAST) && (cdm.status != CAM_DEV_MATCH_MORE))) { DBG (1, "got CAM error %#x, CDM error %d\n", cdm.ccb_h.status, cdm.status); break; } for (i = 0; i < cdm.num_matches; i++) { if (cdm.matches[i].type != DEV_MATCH_PERIPH) continue; result = &cdm.matches[i].result.periph_result; DBG (4, "%s%d on scbus%d %d:%d\n", result->periph_name, result->unit_number, result->path_id, result->target_id, result->target_lun); if (cam_compare_inquiry (fd, result->path_id, result->target_id, result->target_lun, findvendor, findmodel, findtype) == 0) { sprintf (devname, "/dev/%s%d", result->periph_name, result->unit_number); (*attach) (devname); } } } while ((cdm.ccb_h.status == CAM_REQ_CMP) && (cdm.status == CAM_DEV_MATCH_MORE)); free (cdm.patterns); free (cdm.matches); close (fd); return; } #endif #if USE == HPUX_INTERFACE /* XXX untested code! */ SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { struct sctl_io hdr; /* xxx obsolete size_t cdb_size; cdb_size = CDB_SIZE (*(u_char *) src); */ memset (&hdr, 0, sizeof (hdr)); memcpy (hdr.cdb, cmd, cmd_size); if (dst_size && *dst_size) { /* xxx obsolete assert (cdb_size == src_size); */ hdr.flags = SCTL_READ; hdr.data = dst; hdr.data_length = *dst_size; } else { /* xxx obsolete assert (cdb_size <= src_size); */ hdr.data = (char *) src; hdr.data_length = src_size; } hdr.cdb_length = cmd_size; hdr.max_msecs = sane_scsicmd_timeout * 1000; if (ioctl (fd, SIOC_IO, &hdr) < 0) { DBG (1, "sanei_scsi_cmd: ioctl(SIOC_IO) failed: %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if (hdr.cdb_status) DBG (1, "sanei_scsi_cmd: SCSI completed with cdb_status=%d\n", hdr.cdb_status); if (dst_size) *dst_size = hdr.data_xfer; if (hdr.sense_xfer > 0 && (hdr.sense[0] & 0x80) && fd_info[fd].sense_handler) return (*fd_info[fd].sense_handler) (fd, hdr.sense, fd_info[fd].sense_handler_arg); return SANE_STATUS_GOOD; } #endif /* USE == HPUX_INTERFACE */ #if USE == OPENSTEP_INTERFACE SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { struct scsi_req hdr; /* xxx obsolete size_t cdb_size; cdb_size = CDB_SIZE (*(u_char *) src); */ memset (&hdr, 0, sizeof (hdr)); memcpy (&hdr.sr_cdb, cmd, cmd_size); hdr.sr_cdb_length = cmd_size; if (dst_size && *dst_size) { /* xxx obsolete assert (cdb_size == src_size); */ hdr.sr_dma_dir = SR_DMA_RD; hdr.sr_addr = dst; hdr.sr_dma_max = *dst_size; } else { /* xxx obsolete assert (cdb_size <= src_size); */ hdr.sr_dma_dir = SR_DMA_WR; hdr.sr_addr = (char *) src; hdr.sr_dma_max = src_size; } hdr.sr_ioto = sane_scsicmd_timeout; if (ioctl (fd, SGIOCREQ, &hdr) == -1) { DBG (1, "sanei_scsi_cmd: ioctl(SGIOCREQ) failed: %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if (hdr.sr_io_status != 1) DBG (1, "sanei_scsi_cmd: SGIOCREQ completed with sr_io_status=%d\n", hdr.sr_io_status); if (hdr.sr_io_status == SR_IOST_CHKSNV) { struct scsi_req sr; struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6; struct esense_reply sense_reply; int i; char *p; /* clear struct */ p = (char *) cdbp; for (i = 0; i < sizeof (union cdb); i++) *p++ = 0; memset (&sr, 0, sizeof (struct scsi_req)); cdbp->c6_opcode = C6OP_REQSENSE; cdbp->c6_lun = 0; /* where do I get the lun from? */ cdbp->c6_len = 0x20; cdbp->c6_ctrl = 0; sr.sr_dma_dir = SR_DMA_RD; sr.sr_addr = (char *) &sense_reply; sr.sr_dma_max = sizeof (struct esense_reply); sr.sr_ioto = sane_scsicmd_timeout; sr.sr_cdb_length = 6; ioctl (fd, SGIOCREQ, &sr); if (sense_reply.er_ibvalid) { sr.sr_esense = sense_reply; if (fd_info[fd].sense_handler) return (*fd_info[fd].sense_handler) (fd, (u_char *) & sr.sr_esense, fd_info[fd].sense_handler_arg); } /* sense reply is invalid */ return SANE_STATUS_INVAL; } if (hdr.sr_scsi_status == SR_IOST_CHKSV && fd_info[fd].sense_handler) return (*fd_info[fd].sense_handler) (fd, (u_char *) & hdr.sr_esense, fd_info[fd].sense_handler_arg); if (dst_size) *dst_size = hdr.sr_dma_xfr; return SANE_STATUS_GOOD; } #endif /* USE == OPENSTEP_INTERFACE */ #if USE == DECUNIX_INTERFACE SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { u_char sense[64]; UAGT_CAM_CCB hdr; CCB_SCSIIO ccb; /* xxx obsolete size_t cdb_size; cdb_size = CDB_SIZE (*(u_char *) src); */ memset (&ccb, 0, sizeof (ccb)); ccb.cam_ch.my_addr = (CCB_HEADER *) & ccb; ccb.cam_ch.cam_ccb_len = sizeof (ccb); ccb.cam_ch.cam_func_code = XPT_SCSI_IO; ccb.cam_ch.cam_path_id = fd_info[fd].bus; ccb.cam_ch.cam_target_id = fd_info[fd].target; ccb.cam_ch.cam_target_lun = fd_info[fd].lun; ccb.cam_ch.cam_flags = 0; if (dst_size && *dst_size) { /* xxx obsolete assert (cdb_size == src_size); */ ccb.cam_ch.cam_flags |= CAM_DIR_IN; ccb.cam_data_ptr = (u_char *) dst; ccb.cam_dxfer_len = *dst_size; } else { /* xxx obsolete assert (cdb_size <= src_size); */ if (0 == src_size) ccb.cam_ch.cam_flags |= CAM_DIR_NONE; else ccb.cam_ch.cam_flags |= CAM_DIR_OUT; ccb.cam_data_ptr = (u_char *) src; ccb.cam_dxfer_len = src_size; } ccb.cam_timeout = sane_scsicmd_timeout; ccb.cam_cdb_len = cmd_size; memcpy (&ccb.cam_cdb_io.cam_cdb_bytes[0], cmd, cmd_size); memset (&hdr, 0, sizeof (hdr)); hdr.uagt_ccb = (CCB_HEADER *) & ccb; hdr.uagt_ccblen = sizeof (ccb); hdr.uagt_buffer = ccb.cam_data_ptr; hdr.uagt_buflen = ccb.cam_dxfer_len; hdr.uagt_snsbuf = sense; hdr.uagt_snslen = sizeof (sense); hdr.uagt_cdb = 0; /* indicate that CDB is in CCB */ hdr.uagt_cdblen = 0; if (ioctl (cam_fd, UAGT_CAM_IO, &hdr) < 0) { DBG (1, "sanei_scsi_cmd: ioctl(UAGT_CAM_IO) failed: %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if (ccb.cam_ch.cam_status != CAM_REQ_CMP) { DBG (1, "sanei_scsi_cmd: UAGT_CAM_IO completed with cam_status=%d\n", ccb.cam_ch.cam_status); if (ccb.cam_ch.cam_status == CAM_AUTOSNS_VALID && fd_info[fd].sense_handler) return (*fd_info[fd].sense_handler) (fd, sense, fd_info[fd].sense_handler_arg); else return SANE_STATUS_INVAL; } if (dst_size) *dst_size = ccb.cam_dxfer_len; return SANE_STATUS_GOOD; } #endif /* USE == DECUNIX_INTERFACE */ #if USE == SCO_OS5_INTERFACE SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { static u_char sense_buffer[256]; struct scsicmd2 sc2; struct scsicmd *sc; /* xxx obsolete int cdb_size; */ int opcode; int i; if (fd < 0) return SANE_STATUS_IO_ERROR; memset (&sc2, 0, sizeof (sc2)); sc = &sc2.cmd; sc2.sense_len = sizeof (sense_buffer); sc2.sense_ptr = sense_buffer; /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src); */ if (dst_size && *dst_size) { sc->is_write = 0; sc->data_ptr = dst; sc->data_len = *dst_size; } else { sc->data_len = src_size; sc->data_ptr = (char *) src; sc->is_write = 1; } memcpy (sc->cdb, cmd, cmd_size); sc->cdb_len = cmd_size; /* Send the command down via the "pass-through" interface */ if (ioctl (fd, SCSIUSERCMD2, &sc2) < 0) { DBG (1, "sanei_scsi_cmd: ioctl(SCSIUSERCMD2) failed: %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if (sc->host_sts || sc->target_sts) { DBG (1, "sanei_scsi_cmd: SCSIUSERCMD2 completed with " "host_sts=%x, target_sts=%x\n", sc->host_sts, sc->target_sts); if (fd_info[fd].sense_handler) return (*fd_info[fd].sense_handler) (fd, sense_buffer, fd_info[fd].sense_handler_arg); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } #endif /* USE == SCO_OS5_INTERFACE */ #if USE == SYSVR4_INTERFACE /* * UNIXWARE 2.x interface * (c) R=I+S Rapp Informatik System Germany * Email: wolfgang@rapp-informatik.de * * The driver version should run with other scsi componets like disk * attached to the same controller at the same time. * * Attention : This port needs a sane kernel driver for Unixware 2.x * The driver is available in binary pkgadd format * Plese mail me. * */ SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { struct sb sb, *sb_ptr; /* Command block and pointer */ struct scs *scs; /* group 6 command pointer */ struct scm *scm; /* group 10 command pointer */ struct scv *scv; /* group 12 command pointer */ char sense[32]; /* for call of sens req */ char cmd[16]; /* global for right alignment */ char *cp; /* xxx obsolete size_t cdb_size; cdb_size = CDB_SIZE (*(u_char *) src); */ memset (&cmd, 0, 16); sb_ptr = &sb; sb_ptr->sb_type = ISCB_TYPE; cp = (char *) cmd; DBG (1, "cdb_size = %d src = {0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x ...}\n", cmd_size, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7], cp[8], cp[9]); switch (cmd_size) { default: return SANE_STATUS_IO_ERROR; case 6: scs = (struct scs *) cmd; memcpy (SCS_AD (scs), cmd, SCS_SZ); scs->ss_lun = 0; sb_ptr->SCB.sc_cmdpt = SCS_AD (scs); sb_ptr->SCB.sc_cmdsz = SCS_SZ; break; case 10: scm = (struct scm *) cmd; memcpy (SCM_AD (scm), cmd, SCM_SZ); scm->sm_lun = 0; sb_ptr->SCB.sc_cmdpt = SCM_AD (scm); sb_ptr->SCB.sc_cmdsz = SCM_SZ; break; case 12: scv = (struct scv *) cmd; memcpy (SCV_AD (scv), cmd, SCV_SZ); scv->sv_lun = 0; sb_ptr->SCB.sc_cmdpt = SCV_AD (scv); sb_ptr->SCB.sc_cmdsz = SCV_SZ; break; } if (dst_size && *dst_size) { assert (0 == src_size); sb_ptr->SCB.sc_mode = SCB_READ; sb_ptr->SCB.sc_datapt = dst; sb_ptr->SCB.sc_datasz = *dst_size; } else { assert (0 <= src_size); sb_ptr->SCB.sc_mode = SCB_WRITE; sb_ptr->SCB.sc_datapt = (char *) src; if ((sb_ptr->SCB.sc_datasz = src_size) > 0) { sb_ptr->SCB.sc_mode = SCB_WRITE; } else { /* also use READ mode if the backends have write with length 0 */ sb_ptr->SCB.sc_mode = SCB_READ; } } sb_ptr->SCB.sc_time = sane_scsicmd_timeout * 1000; DBG (1, "sanei_scsi_cmd: sc_mode = %d, sc_cmdsz = %d, sc_datasz = %d\n", sb_ptr->SCB.sc_mode, sb_ptr->SCB.sc_cmdsz, sb_ptr->SCB.sc_datasz); { /* do read write by normal read or write system calls */ /* the driver will lock process in momory and do optimized transfer */ cp = (char *) cmd; switch (*cp) { case 0x0: /* test unit ready */ if (ioctl (fd, SS_TEST, NULL) < 0) { return SANE_STATUS_DEVICE_BUSY; } break; case SS_READ: case SM_READ: if (*dst_size > 0x2048) { sb_ptr->SCB.sc_datapt = NULL; sb_ptr->SCB.sc_datasz = 0; if (memcmp (sb_ptr->SCB.sc_cmdpt, lastrcmd, sb_ptr->SCB.sc_cmdsz)) { /* set the command block for the next read or write */ memcpy (lastrcmd, sb_ptr->SCB.sc_cmdpt, sb_ptr->SCB.sc_cmdsz); if (!ioctl (fd, SDI_SEND, sb_ptr)) { *dst_size = read (fd, dst, *dst_size); if (*dst_size == -1) { perror ("sanei-scsi:UW-driver read "); return SANE_STATUS_IO_ERROR; } break; } } else { *dst_size = read (fd, dst, *dst_size); if (*dst_size == -1) { perror ("sanei-scsi:UW-driver read "); return SANE_STATUS_IO_ERROR; } break; } return SANE_STATUS_IO_ERROR; } /* fall through for small read */ default: if (ioctl (fd, SDI_SEND, sb_ptr) < 0) { DBG (1, "sanei_scsi_cmd: ioctl(SDI_SEND) FAILED: %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if (dst_size) *dst_size = sb_ptr->SCB.sc_datasz; #ifdef UWSUPPORTED /* at this time not supported by driver */ if (sb_ptr->SCB.sc_comp_code != SDI_ASW) { DBG (1, "sanei_scsi_cmd: scsi_cmd failture %x\n", sb_ptr->SCB.sc_comp_code); if (sb_ptr->SCB.sc_comp_code == SDI_CKSTAT && sb_ptr->SCB.sc_status == S_CKCON) if (fd_info[fd].sense_handler) { void *arg = fd_info[fd].sense_handler_arg; return (*fd_info[fd].sense_handler) (fd, (u_char *) & sb_ptr-> SCB.sc_link, arg); } return SANE_STATUS_IO_ERROR; } #endif break; } return SANE_STATUS_GOOD; } } #endif /* USE == SYSVR4_INTERFACE */ #if USE == SCO_UW71_INTERFACE SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { static u_char sense_buffer[24]; struct scb cmdblk; time_t elapsed; uint_t compcode, status; /* xxx obsolete int cdb_size, mode; */ int mode; int i; if (fd < 0) return SANE_STATUS_IO_ERROR; cmdblk.sc_cmdpt = (caddr_t) cmd; /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src); */ cmdblk.sc_cmdsz = cmd_size; cmdblk.sc_time = 60000; /* 60 secs */ if (dst_size && *dst_size) { /* xxx obsolete assert (cdb_size == src_size); */ cmdblk.sc_datapt = (caddr_t) dst; cmdblk.sc_datasz = *dst_size; mode = SCB_READ; } else { /* xxx obsolete assert (cdb_size <= src_size); */ cmdblk.sc_datapt = (char *) src; cmdblk.sc_datasz = src_size; mode = SCB_WRITE; } if (pt_send (fd, cmdblk.sc_cmdpt, cmdblk.sc_cmdsz, cmdblk.sc_datapt, cmdblk.sc_datasz, mode, cmdblk.sc_time, &elapsed, &compcode, &status, sense_buffer, sizeof (sense_buffer)) != 0) { DBG (1, "sanei_scsi_cmd: pt_send failed: %s!\n", strerror (errno)); } else { DBG (2, "sanei_scsi_cmd completed with: compcode = %x, status = %x\n", compcode, status); switch (compcode) { case SDI_ASW: /* All seems well */ return SANE_STATUS_GOOD; case SDI_CKSTAT: DBG (2, "Sense Data:\n"); for (i = 0; i < sizeof (sense_buffer); i++) DBG (2, "%.2X ", sense_buffer[i]); DBG (2, "\n"); if (fd_info[fd].sense_handler) return (*fd_info[fd].sense_handler) (fd, sense_buffer, fd_info[fd]. sense_handler_arg); /* fall through */ default: return SANE_STATUS_IO_ERROR; } } } #endif /* USE == SCO_UW71_INTERFACE */ #if USE == OS2_INTERFACE #define WE_HAVE_FIND_DEVICES static int get_devicename (int bus, int target, int lun, char *name, size_t name_len) { snprintf (name, name_len, "b%dt%dl%d", bus, target, lun); DBG (1, "OS/2 searched device is %s\n", name); return 0; } void sanei_scsi_find_devices (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { size_t findvendor_len = 0, findmodel_len = 0, findtype_len = 0; char vendor[32], model[32], type[32], revision[32]; int bus, channel, id, lun, number, i; char line[256], dev_name[128]; const char *string; FILE *proc_fp; char *end; struct { const char *name; size_t name_len; int is_int; /* integer valued? (not a string) */ union { void *v; /* avoids compiler warnings... */ char *str; int *i; } u; } param[] = { { "Vendor:", 7, 0, { 0} } , { "Model:", 6, 0, { 0} } , { "Type:", 5, 0, { 0} } , { "Rev:", 4, 0, { 0} } , { "scsi", 4, 1, { 0} } , { "Channel:", 8, 1, { 0} } , { "Id:", 3, 1, { 0} } , { "Lun:", 4, 1, { 0} } }; param[0].u.str = vendor; param[1].u.str = model; param[2].u.str = type; param[3].u.str = revision; param[4].u.i = &bus; param[5].u.i = &channel; param[6].u.i = &id; param[7].u.i = &lun; DBG_INIT (); open_aspi (); /* open aspi manager if not already done */ DBG (2, "find_devices: open temporary file '%s'\n", tmpAspi); proc_fp = fopen (tmpAspi, "r"); if (!proc_fp) { DBG (1, "could not open %s for reading\n", tmpAspi); return; } number = bus = channel = id = lun = -1; vendor[0] = model[0] = type[0] = '\0'; if (findvendor) findvendor_len = strlen (findvendor); if (findmodel) findmodel_len = strlen (findmodel); if (findtype) findtype_len = strlen (findtype); while (!feof (proc_fp)) { if (!fgets (line, sizeof (line), proc_fp)) break; /* at eof exit */ string = sanei_config_skip_whitespace (line); while (*string) { for (i = 0; i < NELEMS (param); ++i) { if (strncmp (string, param[i].name, param[i].name_len) == 0) { string += param[i].name_len; string = sanei_config_skip_whitespace (string); if (param[i].is_int) { *param[i].u.i = strtol (string, &end, 10); string = (char *) end; } else { strncpy (param[i].u.str, string, 32); param[i].u.str[31] = '\0'; while (*string && !isspace ((int) *string)) ++string; } string = sanei_config_skip_whitespace (string); if (param[i].u.v == &bus) ++number; break; } } if (i >= NELEMS (param)) ++string; /* no match */ } if ((findvendor && !vendor[0]) || (findmodel && !model[0]) || (findtype && !type[0]) || (findbus >= 0 && bus == -1) || (findchannel >= 0 && channel == -1) || (findlun >= 0 && lun == -1)) /* some info is still missing */ continue; if ((!findvendor || strncmp (vendor, findvendor, findvendor_len) == 0) && (!findmodel || strncmp (model, findmodel, findmodel_len) == 0) && (!findtype || strncmp (type, findtype, findtype_len) == 0) && (findbus == -1 || bus == findbus) && (findchannel == -1 || channel == findchannel) && (findid == -1 || id == findid) && (findlun == -1 || lun == findlun) && get_devicename (bus, id, lun, dev_name, sizeof (dev_name)) >= 0 && (*attach) (dev_name) != SANE_STATUS_GOOD) return; vendor[0] = model[0] = type[0] = 0; bus = channel = id = lun = -1; } DBG (2, "find_devices: close temporary file '%s'\n", tmpAspi); fclose (proc_fp); close_aspi (); /* close aspi manager */ } /* XXX untested code! */ SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { ULONG rc; /* Returns. */ unsigned long cbreturn; unsigned long cbParam; if (aspi_buf == NULL) /* avoid SIGSEGV in memcpy() when calling sanei_scsi_cmd2() while aspi-driver is closed */ { DBG (1, "sanei_scsi_cmd: Error no device (aspi_buf == NULL)\n"); return SANE_STATUS_INVAL; } if (PSRBlock == NULL) /* avoid SIGSEGV in memcpy() when calling sanei_scsi_cmd2() while aspi-driver is closed */ { DBG (1, "sanei_scsi_cmd: Error no device (PSRBlock == NULL)\n"); return SANE_STATUS_INVAL; } memset (PSRBlock, 0, sizeof (SRB)); /* Okay, I'm paranoid. */ PSRBlock->cmd = SRB_Command; /* execute SCSI cmd */ PSRBlock->ha_num = fd_info[fd].bus; /* host adapter number */ PSRBlock->u.cmd.target = fd_info[fd].target; /* Target SCSI ID */ PSRBlock->u.cmd.lun = fd_info[fd].lun; /* Target SCSI LUN */ PSRBlock->flags = SRB_Post; /* posting enabled */ if (dst_size && *dst_size) { /* Reading. */ assert (*dst_size <= (size_t) sanei_scsi_max_request_size); PSRBlock->u.cmd.data_len = *dst_size; DBG (1, "sanei_scsi_cmd: Reading PSRBlock->u.cmd.data_len= %lu\n", PSRBlock->u.cmd.data_len); PSRBlock->flags |= SRB_Read; } else { /* Writing. */ PSRBlock->u.cmd.data_len = src_size; DBG (1, "sanei_scsi_cmd: Writing PSRBlock->u.cmd.data_len= %lu\n", PSRBlock->u.cmd.data_len); assert (PSRBlock->u.cmd.data_len <= (unsigned long) sanei_scsi_max_request_size); if (PSRBlock->u.cmd.data_len) PSRBlock->flags |= SRB_Write; else PSRBlock->flags |= SRB_NoTransfer; memcpy (aspi_buf, src, PSRBlock->u.cmd.data_len); } PSRBlock->u.cmd.sense_len = 32; /* length of sense buffer */ PSRBlock->u.cmd.data_ptr = NULL; /* pointer to data buffer already registered */ PSRBlock->u.cmd.link_ptr = NULL; /* pointer to next SRB */ PSRBlock->u.cmd.cdb_len = cmd_size; /* SCSI command length */ memcpy (PSRBlock->u.cmd.cdb_st, cmd, cmd_size); /* Do the command. */ rc = DosDevIOCtl (driver_handle, 0x92, 0x02, (void *) PSRBlock, sizeof (SRB), &cbParam, (void *) PSRBlock, sizeof (SRB), &cbreturn); if (rc) { DBG (1, "sanei_scsi_cmd: DosDevIOCtl failed. rc= %lu \n", rc); return SANE_STATUS_IO_ERROR; } /* Get sense data if available. */ if ((PSRBlock->status == SRB_Aborted || PSRBlock->status == SRB_Error) && PSRBlock->u.cmd.target_status == SRB_CheckStatus && fd_info[fd].sense_handler != 0) { SANEI_SCSI_Sense_Handler s_handler = fd_info[fd].sense_handler; return (*s_handler) (fd, &PSRBlock->u.cmd.cdb_st[cmd_size], fd_info[fd].sense_handler_arg); } if (PSRBlock->status != SRB_Done || PSRBlock->u.cmd.ha_status != SRB_NoError || PSRBlock->u.cmd.target_status != SRB_NoStatus) { DBG (1, "sanei_scsi_cmd: command 0x%02x failed.\n" "PSRBlock->status= 0x%02x\n" "PSRBlock->u.chm.ha_status= 0x%02x\n" "PSRBlock->u.cmd.target_status= 0x%02x\n", PSRBlock->u.cmd.cdb_st[0], PSRBlock->status, PSRBlock->u.cmd.ha_status, PSRBlock->u.cmd.target_status); return SANE_STATUS_IO_ERROR; } if (dst_size && *dst_size) /* Reading? */ memcpy ((char *) dst, aspi_buf, *dst_size); return SANE_STATUS_GOOD; } #endif /* USE == OS2_INTERFACE */ #if USE == STUBBED_INTERFACE SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { return SANE_STATUS_UNSUPPORTED; } #endif /* USE == STUBBED_INTERFACE */ #if USE == IRIX_INTERFACE #define WE_HAVE_FIND_DEVICES SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { dsreq_t scsi_req; /* SCSI request */ /* xxx obsolete size_t cdb_size; *//* Size of SCSI command */ static u_char *cmdbuf = NULL, /* Command buffer */ *sensebuf = NULL, /* Request sense buffer */ *databuf = NULL; /* Data buffer */ /* * Allocate the sense and command data buffers as necessary; we have * to do this to avoid buffer alignment problems, since some * hardware requires these buffers to be 32-bit aligned. */ if (cmdbuf == NULL) { cmdbuf = malloc (64); sensebuf = malloc (1024); /* may be can reduced to 128 */ databuf = malloc (MAX_DATA); if (cmdbuf == NULL || sensebuf == NULL || databuf == NULL) return SANE_STATUS_NO_MEM; } /* * Build the SCSI request... */ /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src); */ DBG (1, "sanei_scsi_cmd: cmd_size = %d\n", cmd_size); if (dst != NULL) { /* * SCSI command returning/reading data... */ scsi_req.ds_flags = DSRQ_READ | DSRQ_SENSE; scsi_req.ds_time = 120 * 1000; scsi_req.ds_cmdbuf = (caddr_t) cmdbuf; scsi_req.ds_cmdlen = cmd_size; scsi_req.ds_databuf = (caddr_t) databuf; scsi_req.ds_datalen = *dst_size; scsi_req.ds_sensebuf = (caddr_t) sensebuf; scsi_req.ds_senselen = 128; /* 1024 does not work, 128 is tested (O.Rauch) */ /* * Copy command to cmdbuf to assure 32-bit alignment. */ memcpy (cmdbuf, cmd, cmd_size); } else { /* * SCSI command sending/writing data... */ scsi_req.ds_flags = DSRQ_WRITE | DSRQ_SENSE; scsi_req.ds_time = 120 * 1000; scsi_req.ds_cmdbuf = (caddr_t) cmdbuf; scsi_req.ds_cmdlen = cmd_size; scsi_req.ds_databuf = (caddr_t) databuf; scsi_req.ds_datalen = src_size; scsi_req.ds_sensebuf = (caddr_t) sensebuf; scsi_req.ds_senselen = 128; /* * Copy command and data to local buffers to ensure 32-bit alignment... */ memcpy (cmdbuf, (u_char *) cmd, cmd_size); memcpy (databuf, (u_char *) src, src_size); } bzero (sensebuf, 128); /* * Do SCSI request... */ if (ioctl (fd, DS_ENTER, &scsi_req) < 0) { DBG (1, "sanei_scsi_cmd: ioctl failed - %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } DBG (1, "sanei_scsi_cmd: status = %d\n", scsi_req.ds_status); /* * Set the incoming data size and copy the destination data as needed... */ if (dst != NULL) { *dst_size = scsi_req.ds_datasent; DBG (1, "sanei_scsi_cmd: read %d bytes\n", scsi_req.ds_datasent); if (scsi_req.ds_datasent > 0) memcpy (dst, databuf, scsi_req.ds_datasent); } /* * Return the appropriate status code... */ if (scsi_req.ds_status != 0) { if (scsi_req.ds_status == STA_BUSY) return SANE_STATUS_DEVICE_BUSY; else if (fd_info[fd].sense_handler) return (*fd_info[fd].sense_handler) (fd, sensebuf, fd_info[fd].sense_handler_arg); else return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } void sanei_scsi_find_devices (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { size_t findvendor_len = 0, findmodel_len = 0; /* Lengths of search strings */ inventory_t *inv; /* Current hardware inventory entry */ int bus, id, lun; /* Current Bus, ID, and LUN */ char dev_name[128]; /* SCSI device name */ int fd; /* SCSI file */ size_t inqsize; /* Size of returned inquiry data */ char vendor[9], /* Vendor name */ model[17]; /* Model/product name */ u_char inqdata[128], /* Inquiry data buffer */ inqcommand[6]; /* Inquiry command (0x12) buffer */ DBG_INIT (); vendor[0] = model[0] = '\0'; if (findvendor) findvendor_len = strlen (findvendor); if (findmodel) findmodel_len = strlen (findmodel); if (findvendor != NULL) DBG (1, "sanei_scsi_find_devices: looking for vendors starting " "with \"%s\".\n", findvendor); if (findmodel != NULL) DBG (1, "sanei_scsi_find_devices: looking for models starting " "with \"%s\".\n", findmodel); setinvent (); while ((inv = getinvent ()) != NULL) { if (inv->inv_class != INV_SCSI || (inv->inv_type != INV_SCANNER && inv->inv_type != INV_CPU)) continue; bus = inv->inv_controller; id = inv->inv_unit; lun = inv->inv_state >> 8; DBG (1, "sanei_scsi_find_devices: found %s on controller %d, " "ID %d, LUN %d.\n", inv->inv_type == INV_SCANNER ? "scanner" : "processor", bus, id, lun); if ((findbus >= 0 && bus != findbus) || (findid >= 0 && id != findid) || (findlun >= 0 && lun != findlun)) { DBG (1, "sanei_scsi_find_devices: ignoring this device.\n"); continue; } sprintf (dev_name, "/dev/scsi/sc%dd%dl%d", bus, id, lun); DBG (1, "sanei_scsi_find_devices: device name is \"%s\".\n", dev_name); /* * Open the SCSI device and get the inquiry data... */ if (sanei_scsi_open (dev_name, &fd, NULL, NULL) != SANE_STATUS_GOOD) { DBG (1, "sanei_scsi_find_devices: unable to open device file - %s.\n", strerror (errno)); continue; } DBG (1, "sanei_scsi_find_devices: device fd = %d.\n", fd); inqsize = sizeof (inqdata); inqcommand[0] = 0x12; inqcommand[1] = 0; inqcommand[2] = 0; inqcommand[3] = sizeof (inqdata) >> 8; inqcommand[4] = sizeof (inqdata); inqcommand[5] = 0; if (sanei_scsi_cmd (fd, inqcommand, sizeof (inqcommand), inqdata, &inqsize) != SANE_STATUS_GOOD) { DBG (1, "sanei_scsi_find_devices: unable to get inquiry data - %s.\n", strerror (errno)); continue; } sanei_scsi_close (fd); strncpy (vendor, (char *) inqdata + 8, 8); vendor[8] = '\0'; strncpy (model, (char *) inqdata + 16, 16); model[16] = '\0'; DBG (1, "sanei_scsi_find_devices: vendor = \'%s\', model = \'%s'.\n", vendor, model); /* * Compare as necessary... */ if ((findvendor != NULL && strncmp (findvendor, vendor, findvendor_len)) || (findmodel != NULL && strncmp (findmodel, model, findmodel_len))) { DBG (1, "sanei_scsi_find_devices: ignoring this device.\n"); continue; } /* * OK, this one matches, so use it! */ DBG (1, "sanei_scsi_find_devices: attaching this device.\n"); (*attach) (dev_name); } } #endif /* USE == IRIX_INTERFACE */ #if USE == AIX_GSC_INTERFACE SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { scmd_t scmd; /* xxx obsolete size_t cdb_size; */ char sense_buf[32]; char status; /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src); */ memset (&scmd, 0, sizeof (scmd)); if (dst_size && *dst_size) { /* xxx obsolete assert (cdb_size == src_size); */ scmd.rw = 1; scmd.data_buf = dst; scmd.datalen = *dst_size; } else { /* assert (cdb_size <= src_size); */ scmd.data_buf = (char *) src; scmd.datalen = src_size; } scmd.cdb = (char *) cmd; scmd.cdblen = cmd_size; scmd.timeval = sane_scsicmd_timeout; scmd.sense_buf = sense_buf; scmd.senselen = sizeof (sense_buf); scmd.statusp = &status; DBG (1, "sanei_scsi_cmd: scmd.rw = %d, scmd.cdblen = %d, ", scmd.rw, scmd.cdblen); DBG (1, "scmd.cdb = {0x%x,0x%x,0x%x,0x%x,0x%x,0x%x, ...}\n", scmd.cdb[0], scmd.cdb[1], scmd.cdb[2], scmd.cdb[3], scmd.cdb[4], scmd.cdb[5]); if (ioctl (fd, GSC_CMD, &scmd) < 0) { DBG (1, "sanei_scsi_cmd: ioctl(SIOC_IO) failed: %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if (*scmd.statusp) DBG (1, "sanei_scsi_cmd: SCSI completed with status=%d\n", *scmd.statusp); DBG (1, "sanei_scsi_cmd: dst = {0x%x,0x%x,0x%x,0x%x,0x%x,0x%x, ...}\n", *((char *) dst + 0), *((char *) dst + 1), *((char *) dst + 2), *((char *) dst + 3), *((char *) dst + 4), *((char *) dst + 5)); if (dst_size) *dst_size = scmd.datalen; if (scmd.senselen > 0 && (scmd.sense_buf[0] & 0x80) && fd_info[fd].sense_handler) return (*fd_info[fd].sense_handler) (fd, (u_char *) scmd.sense_buf, fd_info[fd].sense_handler_arg); return SANE_STATUS_GOOD; } #endif /* USE == AIX_GSC_INTERFACE */ #if USE == SOLARIS_SG_INTERFACE #ifndef CCS_SENSE_LEN # define CCS_SENSE_LEN 18 #endif SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { struct user_scsi us; /* xxx obsolete size_t cdb_size; */ char sensebf[CCS_SENSE_LEN]; /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src); */ /* first put the user scsi structure together. */ memset (&us, 0, sizeof (us)); us.us_cdbp = (caddr_t) cmd; us.us_cdblen = cmd_size; us.us_sensep = sensebf; us.us_senselen = CCS_SENSE_LEN; if (dst && dst_size && *dst_size) { us.us_bufp = (caddr_t) dst; us.us_buflen = *dst_size; us.us_flags = USER_SCSI_READ; } else { us.us_bufp = (caddr_t) src; us.us_buflen = src_size; us.us_flags = USER_SCSI_WRITE; } /* now run it */ if (ioctl (fd, USER_SCSI, &us) < 0) return SANE_STATUS_IO_ERROR; if (dst_size) *dst_size -= us.us_resid; return SANE_STATUS_GOOD; } #endif /* USE == SOLARIS_SG_INTERFACE */ #if USE == SOLARIS_INTERFACE #ifndef SC_NOT_READ # define SC_NOT_READY 0x02 #endif #ifndef SC_BUSY # define SC_BUSY 0x08 #endif #define DEF_TIMEOUT sane_scsicmd_timeout; /* Choosing one of the following DEF_SCG_FLG's SCG_DISRE_ENA allows the SCSI driver to disconnect/reconnect. SCG_CMD_RETRY allows a retry if a retryable error occurs. Disallowing SCG_DISRE_ENA slows down the operation of the SCSI bus while the scanner is working. If you have severe problems try to set it to 0. SCG_CMD_RETRY allows the driver to retry some commands. It should normally be set. For some kinds of odd problems, it may cause the machine to hang for some time. */ #define DEF_SCG_FLG SCG_DISRE_ENA /* #define DEF_SCG_FLG 0 */ /* #define DEF_SCG_FLG SCG_DISRE_ENA | SCG_CMD_RETRY */ /* #define DEF_SCG_FLG SCG_CMD_RETRY */ static int d_errs = 100; static SANE_Status scsi_cmd (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size, int probing) { struct scg_cmd scmd; /* xxx obsolete size_t cdb_size; */ SANEI_SCSI_Sense_Handler handler; /* xxx obsolete cdb_size = CDB_SIZE (*(u_char *) src); */ memset (&scmd, 0, sizeof (scmd)); scmd.flags = DEF_SCG_FLG | (probing ? SCG_SILENT : 0); if (dst && dst_size && *dst_size) { /* xxx obsolete assert (cdb_size == src_size); */ scmd.flags |= SCG_RECV_DATA; scmd.addr = dst; scmd.size = *dst_size; } else { /* xxx obsolete assert (cdb_size <= src_size); */ scmd.addr = (caddr_t) src; scmd.size = src_size; } scmd.cdb_len = cmd_size; scmd.sense_len = CCS_SENSE_LEN; scmd.target = fd_info[fd].target; /* use 2 second timeout when probing, 60 seconds otherwise: */ scmd.timeout = probing ? 2 : DEF_TIMEOUT; memcpy (&scmd.cdb.g0_cdb.cmd, cmd, cmd_size); scmd.cdb.cmd_cdb[1] |= fd_info[fd].lun << 5; if (ioctl (fd, SCGIO_CMD, &scmd) < 0) return SANE_STATUS_IO_ERROR; if (dst_size) *dst_size = scmd.size - scmd.resid; if (scmd.error == 0 && scmd.errno == 0 && *(u_char *) & scmd.scb == 0) return SANE_STATUS_GOOD; if (scmd.error == SCG_TIMEOUT) DBG (0, "sanei_scsi_cmd %x: timeout\n", scmd.cdb.g0_cdb.cmd); else if (probing) { struct scsi_ext_sense *ext_sense = (struct scsi_ext_sense *) &scmd.sense; if (scmd.error < SCG_FATAL && ((scmd.sense.code < 0x70 && scmd.sense.code != 0x04) || (scmd.sense.code >= 0x70 && ext_sense->key != SC_NOT_READY))) return SANE_STATUS_GOOD; } else { char errbf[128]; int i, rv, lifes; handler = fd_info[fd].sense_handler; DBG (3, "cmd=%x, error=%d:%s, bsiz=%d, stat=%x,%x,%x, slen=%d\n", scmd.cdb.g0_cdb.cmd, scmd.error, strerror (scmd.errno), ((dst_size != NULL) ? (*dst_size) : 0), scmd.u_scb.cmd_scb[0], scmd.u_scb.cmd_scb[1], scmd.u_scb.cmd_scb[2], scmd.sense_count); *errbf = '\0'; for (i = 0; i < scmd.sense_count; i++) sprintf (errbf + strlen (errbf), "%x,", scmd.u_sense.cmd_sense[i]); DBG (3, "sense=%s\n", errbf); /* test_unit_ready on a busy unit returns error = 0 or 2 with errno=EIO. I've seen 0 on a CDrom without a CD, and 2 on a scanner just busy. If (SANE_DEBUG_SANEI_SCSI > 100) lifes = SANE_DEBUG_SANEI_SCSI - 100 use up one life for every scmd.error abort and dump core when no lifes left test_unit_ready commands are not counted. */ if (scmd.error) { if (sanei_debug_sanei_scsi > 100 && scmd.cdb.g0_cdb.cmd != SC_TEST_UNIT_READY) { lifes = sanei_debug_sanei_scsi - ++d_errs; DBG (1, "sanei_scsi_cmd: %d lifes left\n", lifes); assert (lifes > 0); } return SANE_STATUS_IO_ERROR; } if (scmd.u_scb.cmd_scb[0] == SC_BUSY) return SANE_STATUS_DEVICE_BUSY; if (*(u_char *) & scmd.sense && handler) { rv = (*handler) (fd, scmd.u_sense.cmd_sense, fd_info[fd].sense_handler_arg); DBG (2, "sanei_scsi_cmd: sense-handler returns %d\n", rv); return rv; } } return SANE_STATUS_IO_ERROR; } SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { return scsi_cmd (fd, cmd, cmd_size, src, src_size, dst, dst_size, 0); } static int unit_ready (int fd) { static const u_char test_unit_ready[] = { 0, 0, 0, 0, 0, 0 }; int status; status = scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0, 0, 0, 1); return (status == SANE_STATUS_GOOD); } #endif /* USE == SOLARIS_INTERFACE */ #if USE == SOLARIS_USCSI_INTERFACE #define DEF_TIMEOUT sane_scsicmd_timeout; static int d_errs = 100; typedef struct scsi_extended_sense extended_sense_t; typedef struct scsi_inquiry scsi_inquiry_t; static SANE_Status scsi_cmd (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size, int probing) { struct uscsi_cmd us; scsi_inquiry_t inquiry, *iq = &inquiry; extended_sense_t sense, *sp = &sense; SANEI_SCSI_Sense_Handler handler; memset (&us, 0, sizeof (us)); memset (sp, 0, sizeof (*sp)); us.uscsi_flags = USCSI_SILENT | USCSI_RQENABLE | USCSI_DIAGNOSE; us.uscsi_timeout = probing ? 2 : DEF_TIMEOUT; us.uscsi_rqbuf = (caddr_t) sp; /* sense data address */ us.uscsi_rqlen = sizeof (extended_sense_t); /* length of sense data */ if (dst && dst_size && *dst_size) { us.uscsi_flags |= USCSI_READ; us.uscsi_bufaddr = (caddr_t) dst; us.uscsi_buflen = *dst_size; } else { us.uscsi_flags |= USCSI_WRITE; us.uscsi_bufaddr = (caddr_t) src; us.uscsi_buflen = src_size; } us.uscsi_cdblen = cmd_size; us.uscsi_cdb = (caddr_t) cmd; if (ioctl (fd, USCSICMD, &us) < 0) return SANE_STATUS_IO_ERROR; if (dst_size) *dst_size = us.uscsi_buflen - us.uscsi_resid; if ((us.uscsi_status & STATUS_MASK) == STATUS_GOOD) return SANE_STATUS_GOOD; if (sp->es_key == SUN_KEY_TIMEOUT) DBG (0, "sanei_scsi_cmd %x: timeout\n", *(char *) cmd); else { char errbf[128]; int i, rv, lifes; handler = fd_info[fd].sense_handler; DBG (3, "cmd=%x, scsi_status=%x\n", *(char *) cmd, us.uscsi_status); *errbf = '\0'; for (i = 0; i < us.uscsi_rqlen; i++) sprintf (errbf + strlen (errbf), "%x,", *(sp + i)); DBG (3, "sense=%s\n", errbf); #if 0 if (us.error) { if (sanei_debug_sanei_scsi > 100 && scmd.cdb.g0_cdb.cmd != SC_TEST_UNIT_READY) { lifes = sanei_debug_sanei_scsi - ++d_errs; DBG (1, "sanei_scsi_cmd: %d lifes left\n", lifes); assert (lifes > 0); } return SANE_STATUS_IO_ERROR; } if (scmd.u_scb.cmd_scb[0] == SC_BUSY) return SANE_STATUS_DEVICE_BUSY; #endif if (handler) { rv = (*handler) (fd, (unsigned char *) sp, fd_info[fd].sense_handler_arg); DBG (2, "sanei_scsi_cmd: sense-handler returns %d\n", rv); return rv; } } return SANE_STATUS_IO_ERROR; } SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { return scsi_cmd (fd, cmd, cmd_size, src, src_size, dst, dst_size, 0); } static int unit_ready (int fd) { static const u_char test_unit_ready[] = { 0, 0, 0, 0, 0, 0 }; int status; status = scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0, 0, 0, 1); return (status == SANE_STATUS_GOOD); } #endif /* USE == SOLARIS_USCSI_INTERFACE */ #if USE == WIN32_INTERFACE SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { struct pkt { SCSI_PASS_THROUGH_DIRECT sptd; unsigned char sense[255]; } pkt; DWORD BytesReturned; BOOL ret; memset(&pkt, 0, sizeof( pkt )); pkt.sptd.Length = sizeof( SCSI_PASS_THROUGH_DIRECT ); pkt.sptd.PathId = fd_info[fd].bus; pkt.sptd.TargetId = fd_info[fd].target; pkt.sptd.Lun = fd_info[fd].lun; assert(cmd_size == 6 || cmd_size == 10 || cmd_size == 12 || cmd_size == 16); memcpy(pkt.sptd.Cdb, cmd, cmd_size); pkt.sptd.CdbLength = cmd_size; if (dst_size && *dst_size) { pkt.sptd.DataIn = SCSI_IOCTL_DATA_IN; pkt.sptd.DataTransferLength = *dst_size; pkt.sptd.DataBuffer = dst; } else if (src_size) { pkt.sptd.DataIn = SCSI_IOCTL_DATA_OUT; pkt.sptd.DataTransferLength = src_size; pkt.sptd.DataBuffer = src; } else { pkt.sptd.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; } pkt.sptd.TimeOutValue = sane_scsicmd_timeout; pkt.sptd.SenseInfoOffset = (void *)pkt.sense - (void *)&pkt; pkt.sptd.SenseInfoLength = sizeof(pkt.sense); ret = DeviceIoControl(fd, IOCTL_SCSI_PASS_THROUGH_DIRECT, &pkt.sptd, sizeof( pkt ), &pkt.sptd, sizeof( pkt ), &BytesReturned, NULL ); if (ret == 0) { DBG (1, "sanei_scsi_cmd2: DeviceIoControl() failed: %ld\n", GetLastError()); return SANE_STATUS_IO_ERROR; } if (pkt.sptd.ScsiStatus == 2){ /* Check condition. */ SANEI_SCSI_Sense_Handler handler; handler = fd_info[fd].sense_handler; if (handler) { return handler(fd, pkt.sense, fd_info[fd].sense_handler_arg); } else { return SANE_STATUS_IO_ERROR; } } else if (pkt.sptd.ScsiStatus != 0) { DBG (1, "sanei_scsi_cmd2: ScsiStatus is %d\n", pkt.sptd.ScsiStatus); return SANE_STATUS_IO_ERROR; } if (dst_size) { *dst_size = pkt.sptd.DataTransferLength; } return SANE_STATUS_GOOD; } #define WE_HAVE_FIND_DEVICES /* This is almost the same algorithm used in sane-find-scanner. */ void sanei_scsi_find_devices (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { int hca; HANDLE fd; char scsi_hca_name[20]; char buffer[4096]; DWORD BytesReturned; BOOL ret; PSCSI_ADAPTER_BUS_INFO adapter; PSCSI_INQUIRY_DATA inquiry; int i; DBG_INIT(); hca = 0; for(hca = 0; ; hca++) { /* Open the adapter */ snprintf(scsi_hca_name, 20, "\\\\.\\Scsi%d:", hca); fd = CreateFile(scsi_hca_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL ); if (fd == INVALID_HANDLE_VALUE) { /* Assume there is no more adapter. This is wrong in the case * of hot-plug stuff, but I have yet to see it on a user * machine. */ break; } /* Get the inquiry info for the devices on that hca. */ ret = DeviceIoControl(fd, IOCTL_SCSI_GET_INQUIRY_DATA, NULL, 0, buffer, sizeof(buffer), &BytesReturned, FALSE); if(ret == 0) { CloseHandle(fd); continue; } adapter = (PSCSI_ADAPTER_BUS_INFO)buffer; for(i = 0; i < adapter->NumberOfBuses; i++) { if (adapter->BusData[i].InquiryDataOffset == 0) { /* No device here */ continue; } inquiry = (PSCSI_INQUIRY_DATA) (buffer + adapter->BusData[i].InquiryDataOffset); while(1) { if ((findvendor == NULL || strncmp(findvendor, (char *)&inquiry->InquiryData[8], 8) == 0)) { DBG(1, "OK1\n"); } else { DBG(1, "failed for [%s] and [%s]\n",findvendor, (char *)&inquiry->InquiryData[8] ); } /* Check if this device fits the criteria. */ if ((findvendor == NULL || strncmp(findvendor, (char *)&inquiry->InquiryData[8], strlen(findvendor)) == 0) && (findmodel == NULL || strncmp(findmodel, (char *)&inquiry->InquiryData[16], strlen(findmodel)) == 0) && (findbus == -1 || findbus == hca) && (findchannel == -1 || findchannel == inquiry->PathId) && (findid == -1 || findid == inquiry->TargetId) && (findlun == -1 || findlun == inquiry->Lun)) { char device_name[20]; sprintf(device_name, "h%db%dt%dl%d", hca, inquiry->PathId, inquiry->TargetId, inquiry->Lun); attach(device_name); } if (inquiry->NextInquiryDataOffset == 0) { /* No device here */ break; } else { inquiry = (PSCSI_INQUIRY_DATA) (buffer + inquiry->NextInquiryDataOffset); } } } CloseHandle(fd); } } #endif /* USE == WIN32_INTERFACE */ #if USE == MACOSX_INTERFACE # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H static SANE_Status sanei_scsi_cmd2_old_api (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { mach_port_t masterPort; IOReturn ioReturnValue; io_object_t scsiDevice; int i; CFMutableDictionaryRef scsiMatchDictionary; int deviceTypeNumber; CFNumberRef deviceTypeRef; io_iterator_t scsiObjectIterator; io_object_t device; CFNumberRef IOUnitRef; int iounit; CFNumberRef scsiTargetRef; int scsitarget; CFNumberRef scsiLunRef; int scsilun; IOCFPlugInInterface **plugInInterface; SInt32 score; HRESULT plugInResult; IOSCSIDeviceInterface **scsiDeviceInterface; IOCDBCommandInterface **cdbCommandInterface; CDBInfo cdb; IOVirtualRange range; UInt32 transferCount; Boolean isWrite; SCSIResults results; UInt32 seqNumber; masterPort = 0; ioReturnValue = IOMasterPort (MACH_PORT_NULL, &masterPort); if (ioReturnValue != kIOReturnSuccess || masterPort == 0) { DBG (5, "Could not get I/O master port (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } scsiDevice = 0; for (i = 0; !scsiDevice && i < 2; i++) { scsiMatchDictionary = IOServiceMatching (kIOSCSIDeviceClassName); if (scsiMatchDictionary == NULL) { DBG (5, "Could not create SCSI matching dictionary\n"); return SANE_STATUS_NO_MEM; } deviceTypeNumber = (i == 0 ? kSCSIDevTypeScanner : kSCSIDevTypeProcessor); deviceTypeRef = CFNumberCreate (NULL, kCFNumberIntType, &deviceTypeNumber); CFDictionarySetValue (scsiMatchDictionary, CFSTR (kSCSIPropertyDeviceTypeID), deviceTypeRef); CFRelease (deviceTypeRef); scsiObjectIterator = 0; ioReturnValue = IOServiceGetMatchingServices (masterPort, scsiMatchDictionary, &scsiObjectIterator); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Could not match services (0x%08x)\n", ioReturnValue); return SANE_STATUS_NO_MEM; } while ((device = IOIteratorNext (scsiObjectIterator))) { IOUnitRef = IORegistryEntryCreateCFProperty (device, CFSTR (kSCSIPropertyIOUnit), NULL, 0); CFNumberGetValue (IOUnitRef, kCFNumberIntType, &iounit); CFRelease (IOUnitRef); scsiTargetRef = IORegistryEntryCreateCFProperty (device, CFSTR (kSCSIPropertyTarget), NULL, 0); CFNumberGetValue (scsiTargetRef, kCFNumberIntType, &scsitarget); CFRelease (scsiTargetRef); scsiLunRef = IORegistryEntryCreateCFProperty (device, CFSTR (kSCSIPropertyLun), NULL, 0); CFNumberGetValue (scsiLunRef, kCFNumberIntType, &scsilun); CFRelease (scsiLunRef); if (fd_info[fd].bus == iounit && fd_info[fd].target == scsitarget && fd_info[fd].lun == scsilun) scsiDevice = device; else IOObjectRelease (device); } IOObjectRelease (scsiObjectIterator); } if (!scsiDevice) { DBG (5, "Device not found (unit %i, target %i, lun %i)\n", fd_info[fd].bus, fd_info[fd].target, fd_info[fd].lun); return SANE_STATUS_INVAL; } plugInInterface = NULL; score = 0; ioReturnValue = IOCreatePlugInInterfaceForService (scsiDevice, kIOSCSIUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if (ioReturnValue != kIOReturnSuccess || plugInInterface == NULL) { DBG (5, "Error creating plugin interface (0x%08x)\n", ioReturnValue); return SANE_STATUS_NO_MEM; } scsiDeviceInterface = NULL; plugInResult = (*plugInInterface)-> QueryInterface (plugInInterface, CFUUIDGetUUIDBytes (kIOSCSIDeviceInterfaceID), (LPVOID) & scsiDeviceInterface); if (plugInResult != S_OK || scsiDeviceInterface == NULL) { DBG (5, "Couldn't create SCSI device interface (%ld)\n", plugInResult); return SANE_STATUS_NO_MEM; } (*plugInInterface)->Release (plugInInterface); IOObjectRelease (scsiDevice); ioReturnValue = (*scsiDeviceInterface)->open (scsiDeviceInterface); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Error opening SCSI interface (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } cdbCommandInterface = NULL; plugInResult = (*scsiDeviceInterface)-> QueryInterface (scsiDeviceInterface, CFUUIDGetUUIDBytes (kIOCDBCommandInterfaceID), (LPVOID) & cdbCommandInterface); if (plugInResult != S_OK || cdbCommandInterface == NULL) { DBG (5, "Error creating CDB interface (%ld)\n", plugInResult); return SANE_STATUS_NO_MEM; } cdb.cdbLength = cmd_size; memcpy (&cdb.cdb, cmd, cmd_size); if (dst && dst_size) { bzero (dst, *dst_size); range.address = (IOVirtualAddress) dst; range.length = *dst_size; transferCount = *dst_size; isWrite = false; } else { range.address = (IOVirtualAddress) src; range.length = src_size; transferCount = src_size; isWrite = true; } seqNumber = 0; ioReturnValue = (*cdbCommandInterface)-> setAndExecuteCommand (cdbCommandInterface, &cdb, transferCount, &range, 1, isWrite, sane_scsicmd_timeout * 1000, 0, 0, 0, &seqNumber); if (ioReturnValue != kIOReturnSuccess && ioReturnValue != kIOReturnUnderrun) { DBG (5, "Error executing CDB command (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } ioReturnValue = (*cdbCommandInterface)->getResults (cdbCommandInterface, &results); if (ioReturnValue != kIOReturnSuccess && ioReturnValue != kIOReturnUnderrun) { DBG (5, "Error getting results from CDB Interface (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } if (dst && dst_size) *dst_size = results.bytesTransferred; (*cdbCommandInterface)->Release (cdbCommandInterface); (*scsiDeviceInterface)->close (scsiDeviceInterface); (*scsiDeviceInterface)->Release (scsiDeviceInterface); return SANE_STATUS_GOOD; } static void sanei_scsi_find_devices_old_api (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { mach_port_t masterPort; IOReturn ioReturnValue; int i; CFMutableDictionaryRef scsiMatchDictionary; int deviceTypeNumber; CFNumberRef deviceTypeRef; io_iterator_t scsiObjectIterator; io_object_t scsiDevice; CFNumberRef IOUnitRef; int iounit; CFNumberRef scsiTargetRef; int scsitarget; CFNumberRef scsiLunRef; int scsilun; IOCFPlugInInterface **plugInInterface; SInt32 score; HRESULT plugInResult; IOSCSIDeviceInterface **scsiDeviceInterface; SCSIInquiry inquiry; UInt32 inquirySize; char devname[16]; masterPort = 0; ioReturnValue = IOMasterPort (MACH_PORT_NULL, &masterPort); if (ioReturnValue != kIOReturnSuccess || masterPort == 0) { DBG (5, "Could not get I/O master port (0x%08x)\n", ioReturnValue); return; } for (i = 0; i < 2; i++) { scsiMatchDictionary = IOServiceMatching (kIOSCSIDeviceClassName); if (scsiMatchDictionary == NULL) { DBG (5, "Could not create SCSI matching dictionary\n"); return; } deviceTypeNumber = (i == 0 ? kSCSIDevTypeScanner : kSCSIDevTypeProcessor); deviceTypeRef = CFNumberCreate (NULL, kCFNumberIntType, &deviceTypeNumber); CFDictionarySetValue (scsiMatchDictionary, CFSTR (kSCSIPropertyDeviceTypeID), deviceTypeRef); CFRelease (deviceTypeRef); scsiObjectIterator = 0; ioReturnValue = IOServiceGetMatchingServices (masterPort, scsiMatchDictionary, &scsiObjectIterator); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Could not match services (0x%08x)\n", ioReturnValue); return; } while ((scsiDevice = IOIteratorNext (scsiObjectIterator))) { IOUnitRef = IORegistryEntryCreateCFProperty (scsiDevice, CFSTR (kSCSIPropertyIOUnit), NULL, 0); CFNumberGetValue (IOUnitRef, kCFNumberIntType, &iounit); CFRelease (IOUnitRef); scsiTargetRef = IORegistryEntryCreateCFProperty (scsiDevice, CFSTR (kSCSIPropertyTarget), NULL, 0); CFNumberGetValue (scsiTargetRef, kCFNumberIntType, &scsitarget); CFRelease (scsiTargetRef); scsiLunRef = IORegistryEntryCreateCFProperty (scsiDevice, CFSTR (kSCSIPropertyLun), NULL, 0); CFNumberGetValue (scsiLunRef, kCFNumberIntType, &scsilun); CFRelease (scsiLunRef); plugInInterface = NULL; score = 0; ioReturnValue = IOCreatePlugInInterfaceForService (scsiDevice, kIOSCSIUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if (ioReturnValue != kIOReturnSuccess || plugInInterface == NULL) { DBG (5, "Error creating plugin interface (0x%08x)\n", ioReturnValue); return; } scsiDeviceInterface = NULL; plugInResult = (*plugInInterface)-> QueryInterface (plugInInterface, CFUUIDGetUUIDBytes (kIOSCSIDeviceInterfaceID), (LPVOID) & scsiDeviceInterface); if (plugInResult != S_OK || scsiDeviceInterface == NULL) { DBG (5, "Couldn't create SCSI device interface (%ld)\n", plugInResult); return; } (*plugInInterface)->Release (plugInInterface); IOObjectRelease (scsiDevice); ioReturnValue = (*scsiDeviceInterface)-> getInquiryData (scsiDeviceInterface, &inquiry, sizeof (SCSIInquiry), &inquirySize); (*scsiDeviceInterface)->Release (scsiDeviceInterface); if ((findlun < 0 || findlun == scsilun) && (findvendor == NULL || strncmp (findvendor, inquiry.vendorName, strlen (findvendor)) == 0) && (findmodel == NULL || strncmp (findmodel, inquiry.productName, strlen (findmodel)) == 0)) { sprintf (devname, "u%dt%dl%d", iounit, scsitarget, scsilun); (*attach) (devname); } } IOObjectRelease (scsiObjectIterator); } } # endif /* ifdef HAVE_IOKIT_CDB_IOSCSILIB_H */ # if defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) static void CreateMatchingDictionaryForSTUC (SInt32 peripheralDeviceType, const char *findvendor, const char *findmodel, const CFDataRef scsiguid, CFMutableDictionaryRef * matchingDict) { CFMutableDictionaryRef subDict; CFNumberRef deviceTypeRef; CFStringRef str; /* Create the dictionaries */ *matchingDict = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (*matchingDict == NULL) { return; } subDict = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (subDict == NULL) { CFRelease (*matchingDict); *matchingDict = NULL; return; } /* Create a dictionary with the "SCSITaskDeviceCategory" key with the appropriate value for the device type we're interested in.*/ CFDictionarySetValue (subDict, CFSTR (kIOPropertySCSITaskDeviceCategory), CFSTR (kIOPropertySCSITaskUserClientDevice)); deviceTypeRef = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &peripheralDeviceType); CFDictionarySetValue (subDict, CFSTR (kIOPropertySCSIPeripheralDeviceType), deviceTypeRef); CFRelease (deviceTypeRef); /* Add search for a vendor or model */ if (findvendor) { str = CFStringCreateWithCString (kCFAllocatorDefault, findvendor, kCFStringEncodingUTF8); CFDictionarySetValue (subDict, CFSTR (kIOPropertySCSIVendorIdentification), str); CFRelease (str); } if (findmodel) { str = CFStringCreateWithCString (kCFAllocatorDefault, findmodel, kCFStringEncodingUTF8); CFDictionarySetValue (subDict, CFSTR (kIOPropertySCSIProductIdentification), str); CFRelease (str); } if (scsiguid) { CFDictionarySetValue (subDict, CFSTR (kIOPropertySCSITaskUserClientInstanceGUID), scsiguid); } /* Add the dictionary to the main dictionary with the key "IOPropertyMatch" to narrow the search to the above dictionary. */ CFDictionarySetValue (*matchingDict, CFSTR (kIOPropertyMatchKey), subDict); CFRelease (subDict); } static void CreateDeviceInterfaceUsingSTUC (io_object_t scsiDevice, IOCFPlugInInterface *** thePlugInInterface, SCSITaskDeviceInterface *** theInterface) { IOReturn ioReturnValue; IOCFPlugInInterface **plugInInterface = NULL; SInt32 score = 0; HRESULT plugInResult; SCSITaskDeviceInterface **interface = NULL; /* Create the base interface of type IOCFPlugInInterface. This object will be used to create the SCSI device interface object. */ ioReturnValue = IOCreatePlugInInterfaceForService (scsiDevice, kIOSCSITaskDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Error creating plugin interface (0x%08x)\n", ioReturnValue); return; } /* Query the base plugin interface for an instance of the specific SCSI device interface object. */ plugInResult = (*plugInInterface)->QueryInterface (plugInInterface, CFUUIDGetUUIDBytes (kIOSCSITaskDeviceInterfaceID), (LPVOID) & interface); if (plugInResult != S_OK) { DBG (5, "Couldn't create SCSI device interface (%ld)\n", (long) plugInResult); return; } /* Set the return values. */ *thePlugInInterface = plugInInterface; *theInterface = interface; } static SANE_Status ExecuteSCSITask (SCSITaskInterface ** task, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { SCSITaskStatus taskStatus; SCSI_Sense_Data senseData; SCSICommandDescriptorBlock cdb; IOReturn ioReturnValue; #ifdef HAVE_SCSITASKSGELEMENT SCSITaskSGElement range; #else IOVirtualRange range; #endif UInt64 transferCount = 0; UInt64 data_length = 0; UInt8 transferType = 0; if (dst && dst_size) /* isRead */ { DBG (6, "isRead dst_size:%ld\n", *dst_size); /* Zero the buffer. */ bzero (dst, *dst_size); /* Configure the virtual range for the buffer. */ range.address = (long) dst; range.length = *dst_size; data_length = *dst_size; transferType = kSCSIDataTransfer_FromTargetToInitiator; } else { DBG (6, "isWrite src_size:%ld\n", src_size); /* Configure the virtual range for the buffer. */ range.address = (long) src; range.length = src_size; data_length = src_size; transferType = kSCSIDataTransfer_FromInitiatorToTarget; } /* zero the senseData and CDB */ bzero (&senseData, sizeof (senseData)); bzero (cdb, sizeof (cdb)); /* copy the command data */ memcpy (cdb, cmd, cmd_size); /* Set the actual cdb in the task */ ioReturnValue = (*task)->SetCommandDescriptorBlock (task, cdb, cmd_size); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Error setting CDB (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } /* Set the scatter-gather entry in the task */ ioReturnValue = (*task)->SetScatterGatherEntries (task, &range, 1, data_length, transferType); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Error setting scatter-gather entries (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } /* Set the timeout in the task */ ioReturnValue = (*task)->SetTimeoutDuration (task, sane_scsicmd_timeout * 1000); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Error setting timeout (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } DBG (5, "Executing command\n"); /* Send it! */ ioReturnValue = (*task)->ExecuteTaskSync (task, &senseData, &taskStatus, &transferCount); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Error executing task (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } DBG (5, "ExecuteTaskSync OK Transferred %lld bytes\n", transferCount); if (taskStatus != kSCSITaskStatus_GOOD) { DBG (5, "taskStatus = 0x%08x\n", taskStatus); return SANE_STATUS_IO_ERROR; } /* Task worked correctly */ if (dst && dst_size) *dst_size = transferCount; return SANE_STATUS_GOOD; } static SANE_Status ExecuteCommandUsingSTUC (SCSITaskDeviceInterface ** interface, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { SCSITaskInterface **task; IOReturn ioReturnValue; SANE_Status returnValue; /* Get exclusive access for the device if we can. This must be done before any SCSITasks can be created and sent to the device. */ ioReturnValue = (*interface)->ObtainExclusiveAccess (interface); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "ObtainExclusiveAccess failed (0x%08x)\n", ioReturnValue); return SANE_STATUS_NO_MEM; } /* Create a task now that we have exclusive access */ task = (*interface)->CreateSCSITask (interface); if (task == NULL) { DBG (5, "CreateSCSITask returned NULL\n"); (*interface)->ReleaseExclusiveAccess (interface); return SANE_STATUS_NO_MEM; } returnValue = ExecuteSCSITask (task, cmd, cmd_size, src, src_size, dst, dst_size); /* Release the task interface */ (*task)->Release (task); /* Release exclusive access */ (*interface)->ReleaseExclusiveAccess (interface); return returnValue; } static SANE_Status sanei_scsi_cmd2_stuc_api (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { CFDataRef guid; mach_port_t masterPort; int i; io_object_t scsiDevice; SInt32 peripheralDeviceType; CFMutableDictionaryRef matchingDict; io_iterator_t iokIterator; IOReturn ioReturnValue; IOCFPlugInInterface **plugInInterface = NULL; SCSITaskDeviceInterface **interface = NULL; io_object_t nextDevice; SANE_Status returnValue; guid = fd_info[fd].pdata; if (!guid) { DBG (5, "No GUID\n"); return SANE_STATUS_INVAL; } DBG (2, "cmd2: cmd_size:%ld src_size:%ld dst_size:%ld isWrite:%d\n", cmd_size, src_size, (!dst_size) ? 0 : *dst_size, (!dst_size) ? 1 : 0); /* Use default master port */ masterPort = 0; ioReturnValue = IOMasterPort (MACH_PORT_NULL, &masterPort); if (ioReturnValue != kIOReturnSuccess || masterPort == 0) { DBG (5, "Could not get I/O master port (0x%08x)\n", ioReturnValue); return SANE_STATUS_IO_ERROR; } /* Search for both Scanner type and Processor type devices */ /* GB TDB This should only be needed for find */ scsiDevice = 0; for (i = 0; !scsiDevice && i < 2; i++) { peripheralDeviceType = (i == 0 ? kINQUIRY_PERIPHERAL_TYPE_ScannerSCSI2Device : kINQUIRY_PERIPHERAL_TYPE_ProcessorSPCDevice); /* Set up a matching dictionary to search the I/O Registry for the SCSI device */ /* we are interested in, specifying the SCSITaskUserClient GUID. */ matchingDict = NULL; CreateMatchingDictionaryForSTUC (peripheralDeviceType, NULL, NULL, guid, &matchingDict); if (matchingDict == NULL) { DBG (5, "CreateMatchingDictionaryForSTUC Failed\n"); return SANE_STATUS_NO_MEM; } /* Now search I/O Registry for the matching device */ iokIterator = 0; ioReturnValue = IOServiceGetMatchingServices (masterPort, matchingDict, &iokIterator); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "IOServiceGetMatchingServices Failed\n"); return SANE_STATUS_NO_MEM; } scsiDevice = IOIteratorNext (iokIterator); while ((nextDevice = IOIteratorNext (iokIterator))) { IOObjectRelease (nextDevice); } IOObjectRelease (iokIterator); } if (!scsiDevice) { DBG (5, "Device not found\n"); return SANE_STATUS_INVAL; } /* Found Device */ /* Create interface */ CreateDeviceInterfaceUsingSTUC (scsiDevice, &plugInInterface, &interface); /* Done with SCSI object from I/O Registry. */ ioReturnValue = IOObjectRelease (scsiDevice); returnValue = SANE_STATUS_IO_ERROR; if (ioReturnValue != kIOReturnSuccess) { DBG (5, "Error releasing SCSI device. (0x%08x)\n", ioReturnValue); } else if (interface != NULL) { /* Execute the command */ returnValue = ExecuteCommandUsingSTUC (interface, cmd, cmd_size, src, src_size, dst, dst_size); } if (interface != NULL) { (*interface)->Release (interface); } if (plugInInterface != NULL) { IODestroyPlugInInterface (plugInInterface); } return returnValue; } static void sanei_scsi_find_devices_stuc_api (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { mach_port_t masterPort; IOReturn ioReturnValue; int i; SInt32 peripheralDeviceType; CFMutableDictionaryRef matchingDict; io_iterator_t iokIterator; io_object_t scsiDevice; CFDataRef GUIDRef; char *devname; int len; const unsigned char *p; CFDictionaryRef protocolCharacteristics; CFNumberRef scsiLunRef; int scsilun; masterPort = 0; ioReturnValue = IOMasterPort (MACH_PORT_NULL, &masterPort); if (ioReturnValue != kIOReturnSuccess || masterPort == 0) return; DBG (5, "Search for Vendor: %s Model: %s\n", (findvendor) ? findvendor : "(none)", (findmodel) ? findmodel : "(none)"); /* Search for both Scanner type and Processor type devices */ for (i = 0; i < 2; i++) { peripheralDeviceType = (i == 0 ? kINQUIRY_PERIPHERAL_TYPE_ScannerSCSI2Device : kINQUIRY_PERIPHERAL_TYPE_ProcessorSPCDevice); /* Set up a matching dictionary to search the I/O Registry for SCSI devices we are interested in. */ matchingDict = NULL; CreateMatchingDictionaryForSTUC (peripheralDeviceType, findvendor, findmodel, NULL, &matchingDict); if (matchingDict == NULL) { DBG (5, "CreateMatchingDictionaryForSTUC Failed\n"); return; } /* Now search I/O Registry for matching devices. */ iokIterator = 0; ioReturnValue = IOServiceGetMatchingServices (masterPort, matchingDict, &iokIterator); if (ioReturnValue != kIOReturnSuccess) { DBG (5, "IOServiceGetMatchingServices Failed\n"); return; } /* Check devices */ while ((scsiDevice = IOIteratorNext (iokIterator))) { scsilun = 0; protocolCharacteristics = IORegistryEntryCreateCFProperty (scsiDevice, CFSTR ("Protocol Characteristics"), NULL, 0); if (protocolCharacteristics) { scsiLunRef = CFDictionaryGetValue (protocolCharacteristics, CFSTR ("SCSI Logical Unit Number")); if (scsiLunRef) CFNumberGetValue (scsiLunRef, kCFNumberIntType, &scsilun); CFRelease (protocolCharacteristics); } if (findlun < 0 || findlun == scsilun) { /* Create device name from the SCSITaskUserClient GUID */ GUIDRef = IORegistryEntryCreateCFProperty (scsiDevice, CFSTR (kIOPropertySCSITaskUserClientInstanceGUID), NULL, 0); if (GUIDRef) { len = CFDataGetLength (GUIDRef); p = CFDataGetBytePtr (GUIDRef); devname = (char *) malloc (2 * len + 3); devname [0] = '<'; for (i = 0; i < len; i++) sprintf (&devname [2 * i + 1], "%02x", p [i]); devname [2 * len + 1] = '>'; devname [2 * len + 2] = '\0'; CFRelease (GUIDRef); DBG (1, "Found: %s\n", devname); /* Attach to the device */ (*attach) (devname); free (devname); } else DBG (1, "Can't find SCSITaskUserClient GUID\n"); } } IOObjectRelease (iokIterator); } } # endif /* HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H */ SANE_Status sanei_scsi_cmd2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size) { if (fd_info[fd].pdata) # if defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) return sanei_scsi_cmd2_stuc_api (fd, cmd, cmd_size, src, src_size, dst, dst_size); # else return SANE_STATUS_INVAL; # endif else # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H return sanei_scsi_cmd2_old_api (fd, cmd, cmd_size, src, src_size, dst, dst_size); # else return SANE_STATUS_INVAL; # endif } void sanei_scsi_find_devices (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { # if defined (HAVE_IOKIT_SCSI_SCSICOMMANDOPERATIONCODES_H) || \ defined (HAVE_IOKIT_SCSI_COMMANDS_SCSICOMMANDOPERATIONCODES_H) sanei_scsi_find_devices_stuc_api (findvendor, findmodel, findtype, findbus, findchannel, findid, findlun, attach); # endif # ifdef HAVE_IOKIT_CDB_IOSCSILIB_H sanei_scsi_find_devices_old_api (findvendor, findmodel, findtype, findbus, findchannel, findid, findlun, attach); # endif } #define WE_HAVE_FIND_DEVICES #endif /* USE == MACOSX_INTERFACE */ #ifndef WE_HAVE_ASYNC_SCSI SANE_Status sanei_scsi_req_enter2 (int fd, const void *cmd, size_t cmd_size, const void *src, size_t src_size, void *dst, size_t * dst_size, void **idp) { return sanei_scsi_cmd2 (fd, cmd, cmd_size, src, src_size, dst, dst_size); } SANE_Status sanei_scsi_req_wait (void *id) { return SANE_STATUS_GOOD; } void sanei_scsi_req_flush_all (void) { } void sanei_scsi_req_flush_all_extended (int fd) { } #endif /* WE_HAVE_ASYNC_SCSI */ SANE_Status sanei_scsi_req_enter (int fd, const void *src, size_t src_size, void *dst, size_t * dst_size, void **idp) { size_t cmd_size = CDB_SIZE (*(const char *) src); if (dst_size && *dst_size) assert (src_size == cmd_size); else assert (src_size >= cmd_size); return sanei_scsi_req_enter2 (fd, src, cmd_size, (const char *) src + cmd_size, src_size - cmd_size, dst, dst_size, idp); } SANE_Status sanei_scsi_cmd (int fd, const void *src, size_t src_size, void *dst, size_t * dst_size) { size_t cmd_size = CDB_SIZE (*(const char *) src); if (dst_size && *dst_size) assert (src_size == cmd_size); else assert (src_size >= cmd_size); return sanei_scsi_cmd2 (fd, src, cmd_size, (const char *) src + cmd_size, src_size - cmd_size, dst, dst_size); } #ifndef WE_HAVE_FIND_DEVICES void sanei_scsi_find_devices (const char *findvendor, const char *findmodel, const char *findtype, int findbus, int findchannel, int findid, int findlun, SANE_Status (*attach) (const char *dev)) { DBG_INIT (); DBG (1, "sanei_scsi_find_devices: not implemented for this platform\n"); } #endif /* WE_HAVE_FIND_DEVICES */ sane-backends-1.0.27/sanei/sanei_DomainOS.h0000664000175000017500000000455012775312262015335 00000000000000/* This file defines the structure of the communication area used by the SANE Domain/OS server. This area must be initialized before the server is invoked with a path to the area. To send an open command to the server, follow these steps: 1) Obtain a mutex lock on CommandLock. 2) Fill in opcode and open_path variables. 3) Advance the CommandAvailable EC. 4) Wait for the CommandAccepted EC to advance. 5) Get the CommandStatus, which has the Domain/OS completion status. Get the fd value, which will be used for subsequent commands. Use the open_path variable to map the data section for the device. 6) Release the CommandLock mutex lock. To send a close command to the server, follow these steps: 1) Obtain a mutex lock on CommandLock. 2) Fill in appropriate Command Data Areas. 3) Advance the CommandAvailable EC. 4) Wait for the CommandAccepted EC to advance. 5) Get the CommandStatus, which has the Domain/OS completion status. 6) Release the CommandLock mutex lock. To send an enter command to the server, follow these steps: 1) Obtain a mutex lock on CommandLock. 2) Fill in the fd field. 3) Advance the CommandAvailable EC. 4) Wait for the CommandAccepted EC to advance. 5) Get the handle for the command. 5) Release the CommandLock mutex lock. */ #ifndef DomainSenseSize /* Amount of data in a sense request */ #define DomainSenseSize 18 /* Maximum amound of data in a transfer, per Domain/OS SCSI spec */ #define DomainMaxDataSize (32 * 1024) /* Timeout for ec2_$wait calls, in 1/4 second intervals */ #define DomainECWaitConstant 120 typedef enum {Open, Close, Enter, Exit} DomainOSOpCode; struct DomainServerCommon { /* Basic communication/synchronization items */ ec2_$eventcount_t CommandAvailable; ec2_$eventcount_t CommandAccepted; ec2_$eventcount_t ResultReady; ec2_$eventcount_t ResultAccepted; mutex_$lock_rec_t CommandLock; mutex_$lock_rec_t ResultLock; /* Command Data Areas - locked by CommandLock */ DomainOSOpCode opcode; int fd; name_$long_pname_t open_path; status_$t CommandStatus; scsi_$status_t SCSIStatus; unsigned long CommandHandle; linteger cdb_size; scsi_$cdb_t cdb; scsi_$direction_t direction; size_t dst_size; size_t buf_size; /* Result data areas */ status_$t status; }; #endif /*DomainSenseSize*/ sane-backends-1.0.27/sanei/sanei_magic.c0000644000175000017500000013614313072433473014740 00000000000000/* * sanei_magic - Image processing functions for despeckle, deskew, and autocrop Copyright (C) 2009 m. allan noah This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include #define BACKEND_NAME sanei_magic /* name of this module for debugging */ #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_magic.h" /* prototypes for utility functions defined at bottom of file */ int * sanei_magic_getTransY ( SANE_Parameters * params, int dpi, SANE_Byte * buffer, int top); int * sanei_magic_getTransX ( SANE_Parameters * params, int dpi, SANE_Byte * buffer, int left); static SANE_Status getTopEdge (int width, int height, int resolution, int * buff, double * finSlope, int * finXInter, int * finYInter); static SANE_Status getLeftEdge (int width, int height, int * top, int * bot, double slope, int * finXInter, int * finYInter); static SANE_Status getLine (int height, int width, int * buff, int slopes, double minSlope, double maxSlope, int offsets, int minOffset, int maxOffset, double * finSlope, int * finOffset, int * finDensity); void sanei_magic_init( void ) { DBG_INIT(); } /* find small spots and replace them with image background color */ SANE_Status sanei_magic_despeck (SANE_Parameters * params, SANE_Byte * buffer, SANE_Int diam) { SANE_Status ret = SANE_STATUS_GOOD; int pw = params->pixels_per_line; int bw = params->bytes_per_line; int h = params->lines; int bt = bw*h; int i,j,k,l,n; DBG (10, "sanei_magic_despeck: start\n"); if(params->format == SANE_FRAME_RGB){ for(i=bw; iformat == SANE_FRAME_GRAY && params->depth == 8){ for(i=bw; iformat == SANE_FRAME_GRAY && params->depth == 1){ for(i=bw; i> (7-(j+l)%8) & 1; } } if(!curr) continue; /*loop over rows and columns around window */ for(k=-1; k> (7-(j+l)%8) & 1; if(hits) break; } } /*no hits, overwrite with white*/ if(!hits){ for(k=0; kpixels_per_line; int height = params->lines; int * topBuf = NULL, * botBuf = NULL; int * leftBuf = NULL, * rightBuf = NULL; int topCount = 0, botCount = 0; int leftCount = 0, rightCount = 0; int i; DBG (10, "sanei_magic_findEdges: start\n"); /* get buffers to find sides and bottom */ topBuf = sanei_magic_getTransY(params,dpiY,buffer,1); if(!topBuf){ DBG (5, "sanei_magic_findEdges: no topBuf\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } botBuf = sanei_magic_getTransY(params,dpiY,buffer,0); if(!botBuf){ DBG (5, "sanei_magic_findEdges: no botBuf\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } leftBuf = sanei_magic_getTransX(params,dpiX,buffer,1); if(!leftBuf){ DBG (5, "sanei_magic_findEdges: no leftBuf\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } rightBuf = sanei_magic_getTransX(params,dpiX,buffer,0); if(!rightBuf){ DBG (5, "sanei_magic_findEdges: no rightBuf\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } /* loop thru left and right lists, look for top and bottom extremes */ *top = height; for(i=0; i leftBuf[i]){ if(*top > i){ *top = i; } topCount++; if(topCount > 3){ break; } } else{ topCount = 0; *top = height; } } *bot = -1; for(i=height-1; i>=0; i--){ if(rightBuf[i] > leftBuf[i]){ if(*bot < i){ *bot = i; } botCount++; if(botCount > 3){ break; } } else{ botCount = 0; *bot = -1; } } /* could not find top/bot edges */ if(*top > *bot){ DBG (5, "sanei_magic_findEdges: bad t/b edges\n"); ret = SANE_STATUS_UNSUPPORTED; goto cleanup; } /* loop thru top and bottom lists, look for l and r extremes * NOTE: We dont look above the top or below the bottom found previously. * This prevents issues with adf scanners that pad the image after the * paper runs out (usually with white) */ DBG (5, "sanei_magic_findEdges: bb0:%d tb0:%d b:%d t:%d\n", botBuf[0], topBuf[0], *bot, *top); *left = width; for(i=0; i topBuf[i] && (botBuf[i]-10 < *bot || topBuf[i]+10 > *top)){ if(*left > i){ *left = i; } leftCount++; if(leftCount > 3){ break; } } else{ leftCount = 0; *left = width; } } *right = -1; for(i=width-1; i>=0; i--){ if(botBuf[i] > topBuf[i] && (botBuf[i]-10 < *bot || topBuf[i]+10 > *top)){ if(*right < i){ *right = i; } rightCount++; if(rightCount > 3){ break; } } else{ rightCount = 0; *right = -1; } } /* could not find left/right edges */ if(*left > *right){ DBG (5, "sanei_magic_findEdges: bad l/r edges\n"); ret = SANE_STATUS_UNSUPPORTED; goto cleanup; } DBG (15, "sanei_magic_findEdges: t:%d b:%d l:%d r:%d\n", *top,*bot,*left,*right); cleanup: if(topBuf) free(topBuf); if(botBuf) free(botBuf); if(leftBuf) free(leftBuf); if(rightBuf) free(rightBuf); DBG (10, "sanei_magic_findEdges: finish\n"); return ret; } /* crop image to given size. updates params with new dimensions */ SANE_Status sanei_magic_crop(SANE_Parameters * params, SANE_Byte * buffer, int top, int bot, int left, int right) { SANE_Status ret = SANE_STATUS_GOOD; int bwidth = params->bytes_per_line; int pixels = 0; int bytes = 0; unsigned char * line = NULL; int pos = 0, i; DBG (10, "sanei_magic_crop: start\n"); /*convert left and right to bytes, figure new byte and pixel width */ if(params->format == SANE_FRAME_RGB){ pixels = right-left; bytes = pixels * 3; left *= 3; right *= 3; } else if(params->format == SANE_FRAME_GRAY && params->depth == 8){ pixels = right-left; bytes = right-left; } else if(params->format == SANE_FRAME_GRAY && params->depth == 1){ left /= 8; right = (right+7)/8; bytes = right-left; pixels = bytes * 8; } else{ DBG (5, "sanei_magic_crop: unsupported format/depth\n"); ret = SANE_STATUS_INVAL; goto cleanup; } DBG (15, "sanei_magic_crop: l:%d r:%d p:%d b:%d\n",left,right,pixels,bytes); line = malloc(bytes); if(!line){ DBG (5, "sanei_magic_crop: no line\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } for(i=top; ilines = bot-top; params->pixels_per_line = pixels; params->bytes_per_line = bytes; cleanup: if(line) free(line); DBG (10, "sanei_magic_crop: finish\n"); return ret; } /* find angle of media rotation against image background */ SANE_Status sanei_magic_findSkew(SANE_Parameters * params, SANE_Byte * buffer, int dpiX, int dpiY, int * centerX, int * centerY, double * finSlope) { SANE_Status ret = SANE_STATUS_GOOD; int pwidth = params->pixels_per_line; int height = params->lines; double TSlope = 0; int TXInter = 0; int TYInter = 0; double TSlopeHalf = 0; int TOffsetHalf = 0; double LSlope = 0; int LXInter = 0; int LYInter = 0; double LSlopeHalf = 0; int LOffsetHalf = 0; int rotateX = 0; int rotateY = 0; int * topBuf = NULL, * botBuf = NULL; DBG (10, "sanei_magic_findSkew: start\n"); dpiX=dpiX; /* get buffers for edge detection */ topBuf = sanei_magic_getTransY(params,dpiY,buffer,1); if(!topBuf){ DBG (5, "sanei_magic_findSkew: cant gTY\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } botBuf = sanei_magic_getTransY(params,dpiY,buffer,0); if(!botBuf){ DBG (5, "sanei_magic_findSkew: cant gTY\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } /* find best top line */ ret = getTopEdge (pwidth, height, dpiY, topBuf, &TSlope, &TXInter, &TYInter); if(ret){ DBG(5,"sanei_magic_findSkew: gTE error: %d",ret); goto cleanup; } DBG(15,"top: %04.04f %d %d\n",TSlope,TXInter,TYInter); /* slope is too shallow, don't want to divide by 0 */ if(fabs(TSlope) < 0.0001){ DBG(15,"sanei_magic_findSkew: slope too shallow: %0.08f\n",TSlope); ret = SANE_STATUS_UNSUPPORTED; goto cleanup; } /* find best left line, perpendicular to top line */ LSlope = (double)-1/TSlope; ret = getLeftEdge (pwidth, height, topBuf, botBuf, LSlope, &LXInter, &LYInter); if(ret){ DBG(5,"sanei_magic_findSkew: gLE error: %d",ret); goto cleanup; } DBG(15,"sanei_magic_findSkew: left: %04.04f %d %d\n",LSlope,LXInter,LYInter); /* find point about which to rotate */ TSlopeHalf = tan(atan(TSlope)/2); TOffsetHalf = LYInter; DBG(15,"sanei_magic_findSkew: top half: %04.04f %d\n",TSlopeHalf,TOffsetHalf); LSlopeHalf = tan((atan(LSlope) + ((LSlope < 0)?-M_PI_2:M_PI_2))/2); LOffsetHalf = - LSlopeHalf * TXInter; DBG(15,"sanei_magic_findSkew: left half: %04.04f %d\n",LSlopeHalf,LOffsetHalf); rotateX = (LOffsetHalf-TOffsetHalf) / (TSlopeHalf-LSlopeHalf); rotateY = TSlopeHalf * rotateX + TOffsetHalf; DBG(15,"sanei_magic_findSkew: rotate: %d %d\n",rotateX,rotateY); *centerX = rotateX; *centerY = rotateY; *finSlope = TSlope; cleanup: if(topBuf) free(topBuf); if(botBuf) free(botBuf); DBG (10, "sanei_magic_findSkew: finish\n"); return ret; } /* function to do a simple rotation by a given slope, around * a given point. The point can be outside of image to get * proper edge alignment. Unused areas filled with bg color * FIXME: Do in-place rotation to save memory */ SANE_Status sanei_magic_rotate (SANE_Parameters * params, SANE_Byte * buffer, int centerX, int centerY, double slope, int bg_color) { SANE_Status ret = SANE_STATUS_GOOD; double slopeRad = -atan(slope); double slopeSin = sin(slopeRad); double slopeCos = cos(slopeRad); int pwidth = params->pixels_per_line; int bwidth = params->bytes_per_line; int height = params->lines; int depth = 1; unsigned char * outbuf; int i, j, k; DBG(10,"sanei_magic_rotate: start: %d %d\n",centerX,centerY); outbuf = malloc(bwidth*height); if(!outbuf){ DBG(15,"sanei_magic_rotate: no outbuf\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } if(params->format == SANE_FRAME_RGB || (params->format == SANE_FRAME_GRAY && params->depth == 8) ){ if(params->format == SANE_FRAME_RGB) depth = 3; memset(outbuf,bg_color,bwidth*height); for (i=0; i= pwidth) continue; sourceY = centerY + (int)(-shiftY * slopeCos + shiftX * slopeSin); if (sourceY < 0 || sourceY >= height) continue; for (k=0; kformat == SANE_FRAME_GRAY && params->depth == 1){ if(bg_color) bg_color = 0xff; memset(outbuf,bg_color,bwidth*height); for (i=0; i= pwidth) continue; sourceY = centerY + (int)(-shiftY * slopeCos + shiftX * slopeSin); if (sourceY < 0 || sourceY >= height) continue; /* wipe out old bit */ outbuf[i*bwidth + j/8] &= ~(1 << (7-(j%8))); /* fill in new bit */ outbuf[i*bwidth + j/8] |= ((buffer[sourceY*bwidth + sourceX/8] >> (7-(sourceX%8))) & 1) << (7-(j%8)); } } } else{ DBG (5, "sanei_magic_rotate: unsupported format/depth\n"); ret = SANE_STATUS_INVAL; goto cleanup; } memcpy(buffer,outbuf,bwidth*height); cleanup: if(outbuf) free(outbuf); DBG(10,"sanei_magic_rotate: finish\n"); return ret; } SANE_Status sanei_magic_isBlank (SANE_Parameters * params, SANE_Byte * buffer, double thresh) { SANE_Status ret = SANE_STATUS_GOOD; double imagesum = 0; int i, j; DBG(10,"sanei_magic_isBlank: start: %f\n",thresh); /*convert thresh from percent (0-100) to 0-1 range*/ thresh /= 100; if(params->format == SANE_FRAME_RGB || (params->format == SANE_FRAME_GRAY && params->depth == 8) ){ /* loop over all rows, find density of each */ for(i=0; ilines; i++){ int rowsum = 0; SANE_Byte * ptr = buffer + params->bytes_per_line*i; /* loop over all columns, sum the 'darkness' of the pixels */ for(j=0; jbytes_per_line; j++){ rowsum += 255 - ptr[j]; } imagesum += (double)rowsum/params->bytes_per_line/255; } } else if(params->format == SANE_FRAME_GRAY && params->depth == 1){ /* loop over all rows, find density of each */ for(i=0; ilines; i++){ int rowsum = 0; SANE_Byte * ptr = buffer + params->bytes_per_line*i; /* loop over all columns, sum the pixels */ for(j=0; jpixels_per_line; j++){ rowsum += ptr[j/8] >> (7-(j%8)) & 1; } imagesum += (double)rowsum/params->pixels_per_line; } } else{ DBG (5, "sanei_magic_isBlank: unsupported format/depth\n"); ret = SANE_STATUS_INVAL; goto cleanup; } DBG (5, "sanei_magic_isBlank: sum:%f lines:%d thresh:%f density:%f\n", imagesum,params->lines,thresh,imagesum/params->lines); if(imagesum/params->lines <= thresh){ DBG (5, "sanei_magic_isBlank: blank!\n"); ret = SANE_STATUS_NO_DOCS; } cleanup: DBG(10,"sanei_magic_isBlank: finish\n"); return ret; } /* Divide the image into 1/2 inch squares, skipping a 1/4 inch * margin on all sides. If all squares are under the user's density, * signal our caller to skip the image entirely, by returning * SANE_STATUS_NO_DOCS */ SANE_Status sanei_magic_isBlank2 (SANE_Parameters * params, SANE_Byte * buffer, int dpiX, int dpiY, double thresh) { int xb,yb,x,y; /* .25 inch, rounded down to 8 pixel */ int xquarter = dpiX/4/8*8; int yquarter = dpiY/4/8*8; int xhalf = xquarter*2; int yhalf = yquarter*2; int blockpix = xhalf*yhalf; int xblocks = (params->pixels_per_line-xhalf)/xhalf; int yblocks = (params->lines-yhalf)/yhalf; /*convert thresh from percent (0-100) to 0-1 range*/ thresh /= 100; DBG (10, "sanei_magic_isBlank2: start %d %d %f %d\n",xhalf,yhalf,thresh,blockpix); if(params->depth == 8 && (params->format == SANE_FRAME_RGB || params->format == SANE_FRAME_GRAY) ){ int Bpp = params->format == SANE_FRAME_RGB ? 3 : 1; for(yb=0; ybbytes_per_line + (xquarter + xb*xhalf) * Bpp; SANE_Byte * ptr = buffer + offset; /*count darkness of pix in this row*/ int rowsum = 0; for(x=0; x thresh){ DBG (15, "sanei_magic_isBlank2: not blank %f %d %d\n", blocksum/yhalf, yb, xb); return SANE_STATUS_GOOD; } DBG (20, "sanei_magic_isBlank2: block blank %f %d %d\n", blocksum/yhalf, yb, xb); } } } else if(params->format == SANE_FRAME_GRAY && params->depth == 1){ for(yb=0; ybbytes_per_line + (xquarter + xb*xhalf) / 8; SANE_Byte * ptr = buffer + offset; /*count darkness of pix in this row*/ int rowsum = 0; for(x=0; x> (7-(x%8)) & 1; } blocksum += (double)rowsum/xhalf; } /* block was darker than thresh, keep image */ if(blocksum/yhalf > thresh){ DBG (15, "sanei_magic_isBlank2: not blank %f %d %d\n", blocksum/yhalf, yb, xb); return SANE_STATUS_GOOD; } DBG (20, "sanei_magic_isBlank2: block blank %f %d %d\n", blocksum/yhalf, yb, xb); } } } else{ DBG (5, "sanei_magic_isBlank2: unsupported format/depth\n"); return SANE_STATUS_INVAL; } DBG (10, "sanei_magic_isBlank2: returning blank\n"); return SANE_STATUS_NO_DOCS; } SANE_Status sanei_magic_findTurn(SANE_Parameters * params, SANE_Byte * buffer, int dpiX, int dpiY, int * angle) { SANE_Status ret = SANE_STATUS_GOOD; int i, j, k; int depth = 1; int htrans=0, vtrans=0; int htot=0, vtot=0; DBG(10,"sanei_magic_findTurn: start\n"); if(params->format == SANE_FRAME_RGB || (params->format == SANE_FRAME_GRAY && params->depth == 8) ){ if(params->format == SANE_FRAME_RGB) depth = 3; /* loop over some rows, count segment lengths */ for(i=0; ilines; i+=dpiY/20){ SANE_Byte * ptr = buffer + params->bytes_per_line*i; int color = 0; int len = 0; int sum = 0; /* loop over all columns */ for(j=0; jpixels_per_line; j++){ int curr = 0; /*convert color to gray*/ for (k=0; k 156)?0:color; /*count segment length*/ if(curr != color || j==params->pixels_per_line-1){ sum += len * len/5; len = 0; color = curr; } else{ len++; } } htot++; htrans += (double)sum/params->pixels_per_line; } /* loop over some cols, count dark vs light transitions */ for(i=0; ipixels_per_line; i+=dpiX/20){ SANE_Byte * ptr = buffer + i*depth; int color = 0; int len = 0; int sum = 0; /* loop over all rows */ for(j=0; jlines; j++){ int curr = 0; /*convert color to gray*/ for (k=0; kbytes_per_line+k]; } curr /= depth; /*convert gray to binary (with hysteresis) */ curr = (curr < 100)?1: (curr > 156)?0:color; /*count segment length*/ if(curr != color || j==params->lines-1){ sum += len * len/5; len = 0; color = curr; } else{ len++; } } vtot++; vtrans += (double)sum/params->lines; } } else if(params->format == SANE_FRAME_GRAY && params->depth == 1){ /* loop over some rows, count segment lengths */ for(i=0; ilines; i+=dpiY/30){ SANE_Byte * ptr = buffer + params->bytes_per_line*i; int color = 0; int len = 0; int sum = 0; /* loop over all columns */ for(j=0; jpixels_per_line; j++){ int curr = ptr[j/8] >> (7-(j%8)) & 1; /*count segment length*/ if(curr != color || j==params->pixels_per_line-1){ sum += len * len/5; len = 0; color = curr; } else{ len++; } } htot++; htrans += (double)sum/params->pixels_per_line; } /* loop over some cols, count dark vs light transitions */ for(i=0; ipixels_per_line; i+=dpiX/30){ SANE_Byte * ptr = buffer; int color = 0; int len = 0; int sum = 0; /* loop over all rows */ for(j=0; jlines; j++){ int curr = ptr[j*params->bytes_per_line + i/8] >> (7-(i%8)) & 1; /*count segment length*/ if(curr != color || j==params->lines-1){ sum += len * len/5; len = 0; color = curr; } else{ len++; } } vtot++; vtrans += (double)sum/params->lines; } } else{ DBG (5, "sanei_magic_findTurn: unsupported format/depth\n"); ret = SANE_STATUS_INVAL; goto cleanup; } DBG (10, "sanei_magic_findTurn: vtrans=%d vtot=%d vfrac=%f htrans=%d htot=%d hfrac=%f\n", vtrans, vtot, (double)vtrans/vtot, htrans, htot, (double)htrans/htot ); if((double)vtrans/vtot > (double)htrans/htot){ DBG (10, "sanei_magic_findTurn: suggest turning 90\n"); *angle = 90; } cleanup: DBG(10,"sanei_magic_findTurn: finish\n"); return ret; } /* FIXME: Do in-place rotation to save memory */ SANE_Status sanei_magic_turn(SANE_Parameters * params, SANE_Byte * buffer, int angle) { SANE_Status ret = SANE_STATUS_GOOD; int opwidth, ipwidth = params->pixels_per_line; int obwidth, ibwidth = params->bytes_per_line; int oheight, iheight = params->lines; int depth = 1; unsigned char * outbuf = NULL; int i, j, k; DBG(10,"sanei_magic_turn: start %d\n",angle); if(params->format == SANE_FRAME_RGB) depth = 3; /*clean angle and convert to 0-3*/ angle = (angle % 360) / 90; /*figure size of output image*/ switch(angle){ case 1: case 3: opwidth = iheight; oheight = ipwidth; /*gray and color, 1 or 3 bytes per pixel*/ if ( params->format == SANE_FRAME_RGB || (params->format == SANE_FRAME_GRAY && params->depth == 8) ){ obwidth = opwidth*depth; } /*clamp binary to byte width. must be <= input image*/ else if(params->format == SANE_FRAME_GRAY && params->depth == 1){ obwidth = opwidth/8; opwidth = obwidth*8; } else{ DBG(10,"sanei_magic_turn: bad params\n"); ret = SANE_STATUS_INVAL; goto cleanup; } break; case 2: opwidth = ipwidth; obwidth = ibwidth; oheight = iheight; break; default: DBG(10,"sanei_magic_turn: no turn\n"); goto cleanup; } /*get output image buffer*/ outbuf = malloc(obwidth*oheight); if(!outbuf){ DBG(15,"sanei_magic_turn: no outbuf\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } /*turn color & gray image*/ if(params->format == SANE_FRAME_RGB || (params->format == SANE_FRAME_GRAY && params->depth == 8) ){ switch (angle) { /*rotate 90 clockwise*/ case 1: for (i=0; iformat == SANE_FRAME_GRAY && params->depth == 1){ switch (angle) { /*rotate 90 clockwise*/ case 1: for (i=0; i> (7-(i%8)) & 1; unsigned char mask = 1 << (7-(j%8)); if(curr){ outbuf[i*obwidth + j/8] |= mask; } else{ outbuf[i*obwidth + j/8] &= (~mask); } } } break; /*rotate 180 clockwise*/ case 2: for (i=0; i> (j%8) & 1; unsigned char mask = 1 << (7-(j%8)); if(curr){ outbuf[i*obwidth + j/8] |= mask; } else{ outbuf[i*obwidth + j/8] &= (~mask); } } } break; /*rotate 270 clockwise*/ case 3: for (i=0; i> (i%8) & 1; unsigned char mask = 1 << (7-(j%8)); if(curr){ outbuf[i*obwidth + j/8] |= mask; } else{ outbuf[i*obwidth + j/8] &= (~mask); } } } break; } /*end switch*/ } else{ DBG (5, "sanei_magic_turn: unsupported format/depth\n"); ret = SANE_STATUS_INVAL; goto cleanup; } /*copy output back into input buffer*/ memcpy(buffer,outbuf,obwidth*oheight); /*update input params*/ params->pixels_per_line = opwidth; params->bytes_per_line = obwidth; params->lines = oheight; cleanup: if(outbuf) free(outbuf); DBG(10,"sanei_magic_turn: finish\n"); return ret; } /* Utility functions, not used outside this file */ /* Repeatedly call getLine to find the best range of slope and offset. * Shift the ranges thru 4 different positions to avoid splitting data * across multiple bins (false positive). Home-in on the most likely upper * line of the paper inside the image. Return the 'best' edge. */ static SANE_Status getTopEdge(int width, int height, int resolution, int * buff, double * finSlope, int * finXInter, int * finYInter) { SANE_Status ret = SANE_STATUS_GOOD; int slopes = 31; int offsets = 31; double maxSlope = 1; double minSlope = -1; int maxOffset = resolution; int minOffset = -resolution; double topSlope = 0; int topOffset = 0; int topDensity = 0; int i,j; int pass = 0; DBG(10,"getTopEdge: start\n"); while(pass++ < 7){ double sStep = (maxSlope-minSlope)/slopes; int oStep = (maxOffset-minOffset)/offsets; double slope = 0; int offset = 0; int density = 0; int go = 0; topSlope = 0; topOffset = 0; topDensity = 0; /* find lines 4 times with slightly moved params, * to bypass binning errors, highest density wins */ for(i=0;i<2;i++){ double sStep2 = sStep*i/2; for(j=0;j<2;j++){ int oStep2 = oStep*j/2; ret = getLine(height,width,buff,slopes,minSlope+sStep2,maxSlope+sStep2,offsets,minOffset+oStep2,maxOffset+oStep2,&slope,&offset,&density); if(ret){ DBG(5,"getTopEdge: getLine error %d\n",ret); return ret; } DBG(15,"getTopEdge: %d %d %+0.4f %d %d\n",i,j,slope,offset,density); if(density > topDensity){ topSlope = slope; topOffset = offset; topDensity = density; } } } DBG(15,"getTopEdge: ok %+0.4f %d %d\n",topSlope,topOffset,topDensity); /* did not find anything promising on first pass, * give up instead of fixating on some small, pointless feature */ if(pass == 1 && topDensity < width/5){ DBG(5,"getTopEdge: density too small %d %d\n",topDensity,width); topOffset = 0; topSlope = 0; break; } /* if slope can zoom in some more, do so. */ if(sStep >= 0.0001){ minSlope = topSlope - sStep; maxSlope = topSlope + sStep; go = 1; } /* if offset can zoom in some more, do so. */ if(oStep){ minOffset = topOffset - oStep; maxOffset = topOffset + oStep; go = 1; } /* cannot zoom in more, bail out */ if(!go){ break; } DBG(15,"getTopEdge: zoom: %+0.4f %+0.4f %d %d\n", minSlope,maxSlope,minOffset,maxOffset); } /* topOffset is in the center of the image, * convert to x and y intercept */ if(topSlope != 0){ *finYInter = topOffset - topSlope * width/2; *finXInter = *finYInter / -topSlope; *finSlope = topSlope; } else{ *finYInter = 0; *finXInter = 0; *finSlope = 0; } DBG(10,"getTopEdge: finish\n"); return 0; } /* Loop thru a transition array, and use a simplified Hough transform * to divide likely edges into a 2-d array of bins. Then weight each * bin based on its angle and offset. Return the 'best' bin. */ static SANE_Status getLine (int height, int width, int * buff, int slopes, double minSlope, double maxSlope, int offsets, int minOffset, int maxOffset, double * finSlope, int * finOffset, int * finDensity) { SANE_Status ret = 0; int ** lines = NULL; int i, j; int rise, run; double slope; int offset; int sIndex, oIndex; int hWidth = width/2; double * slopeCenter = NULL; int * slopeScale = NULL; double * offsetCenter = NULL; int * offsetScale = NULL; int maxDensity = 1; double absMaxSlope = fabs(maxSlope); double absMinSlope = fabs(minSlope); int absMaxOffset = abs(maxOffset); int absMinOffset = abs(minOffset); DBG(10,"getLine: start %+0.4f %+0.4f %d %d\n", minSlope,maxSlope,minOffset,maxOffset); /*silence compiler*/ height = height; if(absMaxSlope < absMinSlope) absMaxSlope = absMinSlope; if(absMaxOffset < absMinOffset) absMaxOffset = absMinOffset; /* build an array of pretty-print values for slope */ slopeCenter = calloc(slopes,sizeof(double)); if(!slopeCenter){ DBG(5,"getLine: cant load slopeCenter\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } /* build an array of scaling factors for slope */ slopeScale = calloc(slopes,sizeof(int)); if(!slopeScale){ DBG(5,"getLine: cant load slopeScale\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } for(j=0;j= maxSlope || slope < minSlope) continue; /* offset in center of width, not y intercept! */ offset = slope * hWidth + buff[i] - slope * i; if(offset >= maxOffset || offset < minOffset) continue; sIndex = (slope - minSlope) * slopes/(maxSlope-minSlope); if(sIndex >= slopes) continue; oIndex = (offset - minOffset) * offsets/(maxOffset-minOffset); if(oIndex >= offsets) continue; lines[sIndex][oIndex]++; } } /* go thru array, and find most dense line (highest number) */ for(i=0;i maxDensity) maxDensity = lines[i][j]; } } DBG(15,"getLine: maxDensity %d\n",maxDensity); *finSlope = 0; *finOffset = 0; *finDensity = 0; /* go thru array, and scale densities to % of maximum, plus adjust for * prefered (smaller absolute value) slope and offset */ for(i=0;i *finDensity){ *finDensity = lines[i][j]; *finSlope = slopeCenter[i]; *finOffset = offsetCenter[j]; } } } if(0){ fprintf(stderr,"offsetCenter: "); for(j=0;j txi){ topXInter = txi; topYInter = tyi; } leftCount++; if(leftCount > 5){ break; } } else{ topXInter = width; topYInter = 0; leftCount = 0; } } botXInter = width; botYInter = 0; leftCount = 0; for(i=0;i -1){ int byi = bot[i] - (slope * i); int bxi = byi/-slope; if(botXInter > bxi){ botXInter = bxi; botYInter = byi; } leftCount++; if(leftCount > 5){ break; } } else{ botXInter = width; botYInter = 0; leftCount = 0; } } if(botXInter < topXInter){ *finXInter = botXInter; *finYInter = botYInter; } else{ *finXInter = topXInter; *finYInter = topYInter; } DBG(10,"getEdgeSlope: finish\n"); return 0; } /* Loop thru the image and look for first color change in each column. * Return a malloc'd array. Caller is responsible for freeing. */ int * sanei_magic_getTransY ( SANE_Parameters * params, int dpi, SANE_Byte * buffer, int top) { int * buff; int i, j, k; int winLen = 9; int width = params->pixels_per_line; int height = params->lines; int depth = 1; /* defaults for bottom-up */ int firstLine = height-1; int lastLine = -1; int direction = -1; DBG (10, "sanei_magic_getTransY: start\n"); /* override for top-down */ if(top){ firstLine = 0; lastLine = height; direction = 1; } /* build output and preload with impossible value */ buff = calloc(width,sizeof(int)); if(!buff){ DBG (5, "sanei_magic_getTransY: no buff\n"); return NULL; } for(i=0; iformat == SANE_FRAME_RGB || (params->format == SANE_FRAME_GRAY && params->depth == 8) ){ if(params->format == SANE_FRAME_RGB) depth = 3; /* loop over all columns, find first transition */ for(i=0; i= height){ farLine = firstLine; } if(nearLine < 0 || nearLine >= height){ nearLine = firstLine; } for(k=0; k 50*winLen*depth - near*40/255){ buff[i] = j; break; } } } } else if(params->format == SANE_FRAME_GRAY && params->depth == 1){ int near = 0; for(i=0; i> (7-(i%8)) & 1; /* move */ for(j=firstLine+direction; j!=lastLine; j+=direction){ if((buffer[(j*width+i)/8] >> (7-(i%8)) & 1) != near){ buff[i] = j; break; } } } } /* some other format? */ else{ DBG (5, "sanei_magic_getTransY: unsupported format/depth\n"); free(buff); return NULL; } /* ignore transitions with few neighbors within .5 inch */ for(i=0;ibytes_per_line; int width = params->pixels_per_line; int height = params->lines; int depth = 1; /* defaults for right-first */ int firstCol = width-1; int lastCol = -1; int direction = -1; DBG (10, "sanei_magic_getTransX: start\n"); /* override for left-first*/ if(left){ firstCol = 0; lastCol = width; direction = 1; } /* build output and preload with impossible value */ buff = calloc(height,sizeof(int)); if(!buff){ DBG (5, "sanei_magic_getTransX: no buff\n"); return NULL; } for(i=0; iformat == SANE_FRAME_RGB || (params->format == SANE_FRAME_GRAY && params->depth == 8) ){ if(params->format == SANE_FRAME_RGB) depth = 3; /* loop over all columns, find first transition */ for(i=0; i= width){ farCol = firstCol; } if(nearCol < 0 || nearCol >= width){ nearCol = firstCol; } for(k=0; k 50*winLen*depth - near*40/255){ buff[i] = j; break; } } } } else if (params->format == SANE_FRAME_GRAY && params->depth == 1){ int near = 0; for(i=0; i> (7-(firstCol%8)) & 1; /* move */ for(j=firstCol+direction; j!=lastCol; j+=direction){ if((buffer[i*bwidth + j/8] >> (7-(j%8)) & 1) != near){ buff[i] = j; break; } } } } /* some other format? */ else{ DBG (5, "sanei_magic_getTransX: unsupported format/depth\n"); free(buff); return NULL; } /* ignore transitions with few neighbors within .5 inch */ for(i=0;i #include #include #include #ifdef __BEOS__ #include #include #include #endif #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_scsi.h" /* This logically belongs to sanei_config.c but not every backend that uses sanei_config() wants to depend on this function. */ void sanei_config_attach_matching_devices (const char *name, SANE_Status (*attach) (const char *dev)) { int bus = -1, channel = -1, id = -1, lun = -1; char *vendor = 0, *model = 0, *type = 0, *end; if (strncmp (name, "scsi", 4) == 0) { name += 4; name = sanei_config_skip_whitespace (name); if (*name) { name = sanei_config_get_string (name, &vendor); if (vendor && strcmp (vendor, "*") == 0) { free (vendor); vendor = 0; } name = sanei_config_skip_whitespace (name); } name = sanei_config_skip_whitespace (name); if (*name) { name = sanei_config_get_string (name, &model); if (model && strcmp (model, "*") == 0) { free (model); model = 0; } name = sanei_config_skip_whitespace (name); } name = sanei_config_skip_whitespace (name); if (*name) { name = sanei_config_get_string (name, &type); if (type && strcmp (type, "*") == 0) { free (type); type = 0; } name = sanei_config_skip_whitespace (name); } if (isdigit (*name)) { bus = strtol (name, &end, 10); name = sanei_config_skip_whitespace (end); } else if (*name == '*') name = sanei_config_skip_whitespace (++name); if (isdigit (*name)) { channel = strtol (name, &end, 10); name = sanei_config_skip_whitespace (end); } else if (*name == '*') name = sanei_config_skip_whitespace (++name); if (isdigit (*name)) { id = strtol (name, &end, 10); name = sanei_config_skip_whitespace (end); } else if (*name == '*') name = sanei_config_skip_whitespace (++name); if (isdigit (*name)) { lun = strtol (name, &end, 10); name = sanei_config_skip_whitespace (end); } else if (*name == '*') name = sanei_config_skip_whitespace (++name); sanei_scsi_find_devices (vendor, model, type, bus, channel, id, lun, attach); if (vendor) free (vendor); if (model) free (model); if (type) free (type); } else (*attach) (name); } sane-backends-1.0.27/sanei/sanei_pv8630.c0000664000175000017500000001406612206524362014623 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Adrian Perez Jorge Copyright (C) 2001 Frank Zago Copyright (C) 2001 Marcio Teixeira This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Interface files for the PowerVision 8630 chip, a USB to parallel converter used in many scanners. */ #include "../include/sane/config.h" #include #include #define BACKEND_NAME sanei_pv8630 #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_pv8630.h" #define DBG_error 1 #define DBG_info 5 void sanei_pv8630_init (void) { DBG_INIT(); } /* Write one control byte */ SANE_Status sanei_pv8630_write_byte (int fd, SANEI_PV_Index index, SANE_Byte byte) { SANE_Status status; DBG(DBG_info, "sanei_pv8630_write_byte - index=%d, byte=%d\n", index, byte); status = sanei_usb_control_msg (fd, 0x40, PV8630_REQ_WRITEBYTE, byte, index, 0, NULL); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "sanei_pv8630_write_byte error\n"); return status; } /* Read one control byte */ SANE_Status sanei_pv8630_read_byte (int fd, SANEI_PV_Index index, SANE_Byte * byte) { SANE_Status status; DBG(DBG_info, "sanei_pv8630_read_byte - index=%d, byte=%p\n", index, byte); status = sanei_usb_control_msg (fd, 0xc0, PV8630_REQ_READBYTE, 0, index, 1, byte); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "sanei_pv8630_read_byte error\n"); return status; } /* Prepare a bulk read. len is the size of the data going to be * read by pv8630_bulkread(). */ SANE_Status sanei_pv8630_prep_bulkread (int fd, int len) { SANE_Status status; status = sanei_usb_control_msg (fd, 0x40, PV8630_REQ_EPPBULKREAD, len & 0xffff, len >> 16, 0, NULL); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "sanei_pv8630_prep_bulkread error\n"); return status; } /* Prepare a bulk write. len is the size of the data going to be * written by pv8630_bulkwrite(). */ SANE_Status sanei_pv8630_prep_bulkwrite (int fd, int len) { SANE_Status status; status = sanei_usb_control_msg (fd, 0x40, PV8630_REQ_EPPBULKWRITE, len & 0xffff, len >> 16, 0, NULL); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "sanei_pv8630_prep_bulkwrite error\n"); return status; } /* Flush the buffer. */ SANE_Status sanei_pv8630_flush_buffer (int fd) { SANE_Status status; status = sanei_usb_control_msg (fd, 0x40, PV8630_REQ_FLUSHBUFFER, 0, 0, 0, NULL); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "sanei_pv8630_flush_buffer error\n"); return status; } /* Do a bulk write. The length must have previously been sent via * pv8630_prep_bulkwrite(). */ SANE_Status sanei_pv8630_bulkwrite (int fd, const void *data, size_t * len) { SANE_Status status; status = sanei_usb_write_bulk (fd, (const SANE_Byte *) data, len); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "sanei_pv8630_bulkwrite error\n"); return status; } /* Do a bulk read. The length must have previously been sent via * pv8630_prep_bulkread(). */ SANE_Status sanei_pv8630_bulkread (int fd, void *data, size_t * len) { SANE_Status status; status = sanei_usb_read_bulk (fd, data, len); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "sanei_pv8630_bulkread error\n"); return status; } /* Expects a specific byte in a register */ SANE_Status sanei_pv8630_xpect_byte (int fd, SANEI_PV_Index index, SANE_Byte value, SANE_Byte mask) { SANE_Status status; SANE_Byte s; status = sanei_pv8630_read_byte (fd, index, &s); if (status != SANE_STATUS_GOOD) return status; if ((s & mask) != value) { DBG (DBG_error, "sanei_pv8630_xpect_byte: expected %x, got %x\n", value, s); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* Wait for the status register to present a given status. A timeout value is given in tenths of a second. */ SANE_Status sanei_pv8630_wait_byte (int fd, SANEI_PV_Index index, SANE_Byte value, SANE_Byte mask, int timeout) { SANE_Status status; SANE_Byte s; int n; for (n = 0; n < timeout; n++) { status = sanei_pv8630_read_byte (fd, index, &s); if (status != SANE_STATUS_GOOD) return status; if ((s & mask) == value) return SANE_STATUS_GOOD; usleep (100000); } DBG (DBG_error, "sanei_pv8630_wait_byte: timeout waiting for %x (got %x)\n", value, s); return SANE_STATUS_IO_ERROR; } sane-backends-1.0.27/sanei/sanei_lm983x.c0000664000175000017500000001770012206524362014717 00000000000000/* sane - Scanner Access Now Easy. based on sources acquired from Plustek Inc. Copyright (C) 2002-2004 Gerhard Jaeger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Interface files for the LM9831/2/3 chip, a chip used in many USB scanners. */ #include "../include/sane/config.h" #include #include #include #include #include #define BACKEND_NAME sanei_lm983x /**< the name of this module for dbg */ #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_lm983x.h" /***************************** some definitions ******************************/ #define _MIN(a,b) ((a) < (b) ? (a) : (b)) #define _MAX(a,b) ((a) > (b) ? (a) : (b)) #define _CMD_BYTE_CNT 4 /**< header for LM983x transfers */ #define _MAX_RETRY 20 /**< number of tries for reset */ #define _LM9831_MAX_REG 0x7f /**< number of LM983x bytes */ #define _MAX_TRANSFER_SIZE 60 /**< max. number of bytes to transfer */ /******************************* the functions *******************************/ void sanei_lm983x_init( void ) { DBG_INIT(); } SANE_Status sanei_lm983x_write_byte( SANE_Int fd, SANE_Byte reg, SANE_Byte value ) { return sanei_lm983x_write( fd, reg, &value, 1, SANE_FALSE ); } SANE_Status sanei_lm983x_write( SANE_Int fd, SANE_Byte reg, SANE_Byte *buffer, SANE_Word len, SANE_Bool increment ) { size_t size; SANE_Byte command_buffer[_MAX_TRANSFER_SIZE + _CMD_BYTE_CNT]; SANE_Status result; SANE_Word bytes, max_len; DBG( 15, "sanei_lm983x_write: fd=%d, reg=%d, len=%d, increment=%d\n", fd, reg, len, increment); if( reg > _LM9831_MAX_REG ) { DBG( 1, "sanei_lm983x_write: register out of range (%u>%u)\n", reg, _LM9831_MAX_REG ); return SANE_STATUS_INVAL; } for( bytes = 0; len > 0; ) { max_len = _MIN( len, _MAX_TRANSFER_SIZE ); command_buffer[0] = 0; /* write */ command_buffer[1] = reg; /* LM983x register */ if( increment == SANE_TRUE ) { command_buffer[0] += 0x02; /* increase reg? */ command_buffer[1] += bytes; } command_buffer[2] = (max_len >> 8) & 0xff; /* bytes to write MSB */ command_buffer[3] = max_len & 0xff; /* bytes to write LSB */ memcpy( command_buffer + _CMD_BYTE_CNT, buffer + bytes, max_len ); size = (max_len + _CMD_BYTE_CNT); result = sanei_usb_write_bulk( fd, command_buffer, &size ); if( SANE_STATUS_GOOD != result ) return result; if( size != (size_t)(max_len + _CMD_BYTE_CNT)) { DBG( 2, "sanei_lm983x_write: short write (%d/%d)\n", result, max_len + _CMD_BYTE_CNT); if( size < _CMD_BYTE_CNT ) { DBG( 1, "sanei_lm983x_write: couldn't even send command\n" ); return SANE_STATUS_IO_ERROR; } DBG( 1, "sanei_lm983x_write: trying again\n" ); } len -= (size - _CMD_BYTE_CNT); bytes += (size - _CMD_BYTE_CNT); } DBG( 15, "sanei_lm983x_write: succeeded\n" ); return SANE_STATUS_GOOD; } SANE_Status sanei_lm983x_read( SANE_Int fd, SANE_Byte reg, SANE_Byte *buffer, SANE_Word len, SANE_Bool increment ) { size_t size; SANE_Byte command_buffer[_CMD_BYTE_CNT]; SANE_Status result; SANE_Word bytes, max_len, read_bytes; DBG( 15, "sanei_lm983x_read: fd=%d, reg=%d, len=%d, increment=%d\n", fd, reg, len, increment ); if( reg > _LM9831_MAX_REG ) { DBG( 1, "sanei_lm983x_read: register out of range (%u>%u)\n", reg, _LM9831_MAX_REG ); return SANE_STATUS_INVAL; } for( bytes = 0; len > 0; ) { max_len = _MIN(len, 0xFFFF ); command_buffer[0] = 1; /* read */ command_buffer[1] = reg; /* LM9831 register */ if( increment ) { command_buffer[0] += 0x02; command_buffer[1] += bytes; } command_buffer[2] = (max_len >> 8) & 0xff; /* bytes to read MSB */ command_buffer[3] = max_len & 0xff; /* bytes to read LSB */ DBG( 15, "sanei_lm983x_read: writing command: " "%02x %02x %02x %02x\n", command_buffer[0], command_buffer[1], command_buffer[2], command_buffer[3]); size = _CMD_BYTE_CNT; result = sanei_usb_write_bulk( fd, command_buffer, &size ); if( SANE_STATUS_GOOD != result ) return result; if( size != _CMD_BYTE_CNT) { DBG( 1, "sanei_lm983x_read: short write while writing command " "(%d/_CMD_BYTE_CNT)\n", result); return SANE_STATUS_IO_ERROR; } read_bytes = 0; do { size = (max_len - read_bytes); result = sanei_usb_read_bulk( fd, (buffer + bytes + read_bytes), &size ); if( SANE_STATUS_GOOD != result ) return result; read_bytes += size; DBG( 15, "sanei_lm983x_read: read %lu bytes\n", (u_long) size ); if( read_bytes != max_len ) { DBG( 2, "sanei_lm983x_read: short read (%d/%d)\n", result, max_len ); /* wait a little bit before retrying */ usleep( 10000 ); DBG( 2, "sanei_lm983x_read: trying again\n" ); } } while( read_bytes < max_len ); bytes += (max_len); len -= (max_len); } DBG( 15, "sanei_lm983x_read: succeeded\n" ); return SANE_STATUS_GOOD; } SANE_Bool sanei_lm983x_reset( SANE_Int fd ) { SANE_Status res; SANE_Byte tmp; SANE_Int i; DBG( 15, "sanei_lm983x_reset()\n" ); for( i = 0; i < _MAX_RETRY; i++ ) { /* Read the command register and check that the reset bit is not set * If it is set, clear it and return false to indicate that * the bit has only now been cleared * * Write the command bytes for a register read * without increment */ if( SANE_STATUS_GOOD != sanei_lm983x_read_byte( fd, 0x07, &tmp )) continue; if( tmp & 0x20 ) { res = sanei_lm983x_write_byte( fd, 0x07, 0 ); /* We will attempt to reset it but we really don't do * anything if this fails */ if( res == SANE_STATUS_GOOD ) { DBG( 15, "Resetting the LM983x already done\n" ); return SANE_TRUE; } } else { res = sanei_lm983x_write_byte( fd, 0x07, 0x20 ); if( res == SANE_STATUS_GOOD ) { DBG( 15, "Resetting the LM983x done\n" ); return SANE_TRUE; } } } return SANE_FALSE; } /* END sanei_lm983x.c .......................................................*/ sane-backends-1.0.27/sanei/Makefile.in0000664000175000017500000005522413110564734014402 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @HAVE_JPEG_TRUE@am__append_1 = sanei_jpeg.c subdir = sanei DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libsanei_la_LIBADD = am__libsanei_la_SOURCES_DIST = sanei_ab306.c sanei_constrain_value.c \ sanei_init_debug.c sanei_net.c sanei_wire.c \ sanei_codec_ascii.c sanei_codec_bin.c sanei_scsi.c \ sanei_config.c sanei_config2.c sanei_pio.c sanei_pa4s2.c \ sanei_auth.c sanei_usb.c sanei_thread.c sanei_pv8630.c \ sanei_pp.c sanei_lm983x.c sanei_access.c sanei_tcp.c \ sanei_udp.c sanei_magic.c sanei_ir.c sanei_jpeg.c @HAVE_JPEG_TRUE@am__objects_1 = sanei_jpeg.lo am_libsanei_la_OBJECTS = sanei_ab306.lo sanei_constrain_value.lo \ sanei_init_debug.lo sanei_net.lo sanei_wire.lo \ sanei_codec_ascii.lo sanei_codec_bin.lo sanei_scsi.lo \ sanei_config.lo sanei_config2.lo sanei_pio.lo sanei_pa4s2.lo \ sanei_auth.lo sanei_usb.lo sanei_thread.lo sanei_pv8630.lo \ sanei_pp.lo sanei_lm983x.lo sanei_access.lo sanei_tcp.lo \ sanei_udp.lo sanei_magic.lo sanei_ir.lo $(am__objects_1) libsanei_la_OBJECTS = $(am_libsanei_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libsanei_la_SOURCES) DIST_SOURCES = $(am__libsanei_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include $(USB_CFLAGS) AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libsanei.la libsanei_la_SOURCES = sanei_ab306.c sanei_constrain_value.c \ sanei_init_debug.c sanei_net.c sanei_wire.c \ sanei_codec_ascii.c sanei_codec_bin.c sanei_scsi.c \ sanei_config.c sanei_config2.c sanei_pio.c sanei_pa4s2.c \ sanei_auth.c sanei_usb.c sanei_thread.c sanei_pv8630.c \ sanei_pp.c sanei_lm983x.c sanei_access.c sanei_tcp.c \ sanei_udp.c sanei_magic.c sanei_ir.c $(am__append_1) EXTRA_DIST = linux_sg3_err.h os2_srb.h sanei_DomainOS.c sanei_DomainOS.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu sanei/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu sanei/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libsanei.la: $(libsanei_la_OBJECTS) $(libsanei_la_DEPENDENCIES) $(EXTRA_libsanei_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsanei_la_OBJECTS) $(libsanei_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_ab306.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_access.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_auth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_codec_ascii.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_codec_bin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_config.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_config2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_constrain_value.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_init_debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_ir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_jpeg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_lm983x.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_magic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_net.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_pa4s2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_pio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_pp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_pv8630.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_scsi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_tcp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_udp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_wire.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/sanei/sanei_pio.c0000664000175000017500000003354012775312262014447 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998 Christian Bucher Copyright (C) 1998 Kling & Hautzinger GmbH This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements the bi-directional parallel-port interface. */ /* RESTRICTIONS: - This interface is very timing sensitive, be carefull with setting debug levels. */ #include "../include/sane/config.h" #define BACKEND_NAME sanei_pio #include "../include/sane/sanei_backend.h" /* pick up compatibility defs */ #ifdef HAVE_UNISTD_H # include #endif #include #ifdef HAVE_SYS_IO_H # include /* use where available (glibc 2.x, for example) */ # ifndef SANE_HAVE_SYS_IO_H_WITH_INB_OUTB # define IO_SUPPORT_MISSING # endif #elif HAVE_ASM_IO_H # include /* ugly, but backwards compatible */ #elif HAVE_SYS_HW_H # include #elif defined(__i386__) && defined (__GNUC__) static __inline__ void outb (u_char value, u_long port) { __asm__ __volatile__ ("outb %0,%1"::"a" (value), "d" ((u_short) port)); } static __inline__ u_char inb (u_long port) { u_char value; __asm__ __volatile__ ("inb %1,%0":"=a" (value):"d" ((u_short) port)); return value; } #else # define IO_SUPPORT_MISSING #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_pio.h" #if defined (HAVE_IOPERM) && !defined (IO_SUPPORT_MISSING) #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/saneopts.h" #define PORT_DEV "/dev/port" /* base 278 (lpt2) ioport stat ctrl offs 0 1 2 len 1 1 1 */ /* Port definitions (`N' at end begin of label means negated signal) */ #define PIO_IOPORT 0 /* rel. addr io port */ #define PIO_STAT 1 /* rel. addr status port */ #define PIO_STAT_BUSY (1<<7) /* BUSY Pin */ #define PIO_STAT_NACKNLG (1<<6) /* ~ACKNLG Pin */ #define PIO_CTRL 2 /* rel. addr control port */ #define PIO_CTRL_IE (1<<5) /* Input enable */ #define PIO_CTRL_IRQE (1<<4) /* enable IRQ */ #define PIO_CTRL_DIR (1<<3) /* DIR pin, DIR=1 => out */ #define PIO_CTRL_NINIT (1<<2) /* reset output */ #define PIO_CTRL_FDXT (1<<1) /* Paper FEED (unused) */ #define PIO_CTRL_NSTROBE (1<<0) /* strobe pin */ #define PIO_APPLYRESET 2000 /* reset in 10us at init time */ #define DL40 6 #define DL50 7 #define DL60 8 #define DL61 9 #define DL70 10 #define DL71 11 #ifdef NDEBUG # define DBG_INIT() #endif typedef struct { u_long base; /* i/o base address */ int fd; /* >= 0 when using /dev/port */ int max_time_seconds;/* forever if <= 0 */ u_int in_use; /* port in use? */ } PortRec, *Port; static PortRec port[] = { {0x378, -1, 0, 0}, {0x278, -1, 0, 0} }; extern int setuid (uid_t); static inline int pio_outb (const Port port, u_char val, u_long addr); static inline int pio_inb (const Port port, u_char * val, u_long addr); static inline int pio_wait (const Port port, u_char val, u_char mask); static inline void pio_ctrl (const Port port, u_char val); static inline void pio_delay (const Port port); static inline void pio_init (const Port port); static void pio_reset (const Port port); static int pio_write (const Port port, const u_char * buf, int n); static int pio_read (const Port port, u_char * buf, int n); static int pio_open (const char *dev, SANE_Status * status); static inline int pio_outb (const Port port, u_char val, u_long addr) { if (-1 == port->fd) outb (val, addr); else { if (addr != (u_long)lseek (port->fd, addr, SEEK_SET)) return -1; if (1 != write (port->fd, &val, 1)) return -1; } return 0; } static inline int pio_inb (const Port port, u_char * val, u_long addr) { if (-1 == port->fd) *val = inb (addr); else { if (addr != (u_long)lseek (port->fd, addr, SEEK_SET)) return -1; if (1 != read (port->fd, val, 1)) return -1; } return 0; } static inline int pio_wait (const Port port, u_char val, u_char mask) { int stat = 0; long poll_count = 0; time_t start = time(NULL); DBG (DL60, "wait on port 0x%03lx for %02x mask %02x\n", port->base, (int) val, (int) mask); DBG (DL61, " BUSY %s\n", (mask & PIO_STAT_BUSY) ? (val & PIO_STAT_BUSY ? "on" : "off") : "-"); DBG (DL61, " NACKNLG %s\n", (mask & PIO_STAT_NACKNLG) ? (val & PIO_STAT_NACKNLG ? "on" : "off") : "-"); for (;;) { ++poll_count; stat = inb (port->base + PIO_STAT); if ((stat & mask) == (val & mask)) { DBG (DL60, "got %02x after %ld tries\n", stat, poll_count); DBG (DL61, " BUSY %s\n", stat & PIO_STAT_BUSY ? "on" : "off"); DBG (DL61, " NACKNLG %s\n", stat & PIO_STAT_NACKNLG ? "on" : "off"); return stat; } if(poll_count>1000) { if ((port->max_time_seconds>0) && (time(NULL)-start >= port->max_time_seconds)) break; usleep(1); } } DBG (DL60, "got %02x aborting after %ld\n", stat, poll_count); DBG (DL61, " BUSY %s\n", stat & PIO_STAT_BUSY ? "on" : "off"); DBG (DL61, " NACKNLG %s\n", stat & PIO_STAT_NACKNLG ? "on" : "off"); DBG (1, "polling time out, abort\n"); exit (-1); } static inline void pio_ctrl (const Port port, u_char val) { DBG (DL60, "ctrl on port 0x%03lx %02x %02x\n", port->base, (int) val, (int) val ^ PIO_CTRL_NINIT); val ^= PIO_CTRL_NINIT; DBG (DL61, " IE %s\n", val & PIO_CTRL_IE ? "on" : "off"); DBG (DL61, " IRQE %s\n", val & PIO_CTRL_IRQE ? "on" : "off"); DBG (DL61, " DIR %s\n", val & PIO_CTRL_DIR ? "on" : "off"); DBG (DL61, " NINIT %s\n", val & PIO_CTRL_NINIT ? "on" : "off"); DBG (DL61, " FDXT %s\n", val & PIO_CTRL_FDXT ? "on" : "off"); DBG (DL61, " NSTROBE %s\n", val & PIO_CTRL_NSTROBE ? "on" : "off"); outb (val, port->base + PIO_CTRL); return; } static inline void pio_delay (const Port port) { inb (port->base + PIO_STAT); /* delay */ return; } static inline void pio_init (const Port port) { pio_ctrl (port, PIO_CTRL_IE); return; } static void pio_reset (const Port port) { int n; DBG (DL40, "reset\n"); for (n = PIO_APPLYRESET; --n >= 0;) { outb ((PIO_CTRL_IE | PIO_CTRL_NINIT) ^ PIO_CTRL_NINIT, port->base + PIO_CTRL); } pio_init (port); DBG (DL40, "end reset\n"); return; } static int pio_write (const Port port, const u_char * buf, int n) { int k; DBG (DL40, "write\n"); pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY); /* busy */ pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_IE); /* praeoutput */ pio_wait (port, PIO_STAT_NACKNLG, PIO_STAT_NACKNLG); /* acknlg */ pio_ctrl (port, PIO_CTRL_DIR); /* output */ for (k = 0; k < n; k++, buf++) { DBG (DL40, "write byte\n"); #ifdef HANDSHAKE_BUSY pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY); /* busy */ #else pio_wait (port, PIO_STAT_BUSY | PIO_STAT_NACKNLG, PIO_STAT_BUSY | PIO_STAT_NACKNLG); /* busyack */ #endif DBG (DL60, "out %02x\n", (int) *buf); outb (*buf, port->base + PIO_IOPORT); pio_delay (port); pio_delay (port); pio_delay (port); pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_NSTROBE); /* outputstrobe */ pio_delay (port); pio_delay (port); pio_delay (port); pio_ctrl (port, PIO_CTRL_DIR); /* output */ pio_delay (port); pio_delay (port); pio_delay (port); DBG (DL40, "end write byte\n"); } #ifdef HANDSHAKE_BUSY pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY); /* busy */ #else pio_wait (port, PIO_STAT_BUSY | PIO_STAT_NACKNLG, PIO_STAT_BUSY | PIO_STAT_NACKNLG); /* busyack */ #endif pio_ctrl (port, PIO_CTRL_DIR | PIO_CTRL_IE); /* praeoutput */ DBG (DL40, "end write\n"); return k; } static int pio_read (const Port port, u_char * buf, int n) { int k; DBG (DL40, "read\n"); pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY); /* busy */ pio_ctrl (port, PIO_CTRL_IE); /* input */ for (k = 0; k < n; k++, buf++) { DBG (DL40, "read byte\n"); #ifdef HANDSHAKE_BUSY pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY); /* busy */ #else pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY | PIO_STAT_NACKNLG); /* busynack */ #endif pio_ctrl (port, PIO_CTRL_IE | PIO_CTRL_NSTROBE); /* inputstrobe */ pio_delay (port); pio_delay (port); pio_delay (port); pio_ctrl (port, PIO_CTRL_IE); /* input */ #ifdef HANDSHAKE_BUSY pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY); /* busy */ #else pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY | PIO_STAT_NACKNLG); /* busynack */ #endif *buf = inb (port->base + PIO_IOPORT); DBG (DL60, "in %02x\n", (int) *buf); DBG (DL40, "end read byte\n"); } pio_wait (port, PIO_STAT_BUSY, PIO_STAT_BUSY); /* busy */ pio_ctrl (port, PIO_CTRL_IE); /* input */ DBG (DL40, "end read\n"); return k; } /* Open the device, must contain a valid port number (as string). */ static int pio_open (const char *dev, SANE_Status * status) { static int first_time = 1; u_long base; int n; if (first_time) { first_time = 0; DBG_INIT (); /* set root uid */ if (0 > setuid (0)) { DBG (1, "sanei_pio_open: setuid failed: errno = %d\n", errno); *status = SANE_STATUS_INVAL; return -1; } } /* read port number */ { char *end; base = strtol (dev, &end, 0); if ((end == dev) || *end) { DBG (1, "sanei_pio_open: `%s' is not a valid port number\n", dev); *status = SANE_STATUS_INVAL; return -1; } } if (0 == base) { DBG (1, "sanei_pio_open: 0x%03lx is not a valid base address\n", base); *status = SANE_STATUS_INVAL; return -1; } for (n = 0; n < NELEMS (port); n++) if (port[n].base == base) break; if (NELEMS (port) <= n) { DBG (1, "sanei_pio_open: 0x%03lx is not a valid base address\n", base); *status = SANE_STATUS_INVAL; return -1; } if (port[n].in_use) { DBG (1, "sanei_pio_open: port 0x%03lx is already in use\n", base); *status = SANE_STATUS_DEVICE_BUSY; return -1; } port[n].base = base; port[n].fd = -1; port[n].max_time_seconds = 10; port[n].in_use = 1; if (ioperm (port[n].base, 3, 1)) { DBG (1, "sanei_pio_open: cannot get io privilege for port 0x%03lx\n", port[n].base); *status = SANE_STATUS_IO_ERROR; return -1; } pio_reset (&port[n]); *status = SANE_STATUS_GOOD; return n; } SANE_Status sanei_pio_open (const char *dev, int *fdp) { SANE_Status status; *fdp = pio_open (dev, &status); return status; } void sanei_pio_close (int fd) { Port p = port + fd; if ((0 > fd) && (NELEMS (port) <= fd)) return; if (!p->in_use) return; if (-1 != p->fd) { close (p->fd); p->fd = -1; } p->in_use = 0; return; } int sanei_pio_read (int fd, u_char * buf, int n) { if ((0 > fd) && (NELEMS (port) <= fd)) return -1; if (!port[fd].in_use) return -1; return pio_read (&port[fd], buf, n); } int sanei_pio_write (int fd, const u_char * buf, int n) { if ((0 > fd) && (NELEMS (port) <= fd)) return -1; if (!port[fd].in_use) return -1; return pio_write (&port[fd], buf, n); } #else /* !HAVE_IOPERM */ #ifdef __BEOS__ #include SANE_Status sanei_pio_open (const char *dev, int *fdp) { int fp; /* open internal parallel port */ fp=open("/dev/parallel/parallel1",O_RDWR); *fdp=fp; if(fp<0) return SANE_STATUS_INVAL; return(SANE_STATUS_GOOD); } void sanei_pio_close (int fd) { close(fd); return; } int sanei_pio_read (int fd, u_char * buf, int n) { return(read(fd,buf,n)); } int sanei_pio_write (int fd, const u_char * buf, int n) { return(write(fd,buf,n)); } #else /* !__BEOS__ */ SANE_Status sanei_pio_open (const char *dev, int *fdp) { *fdp = -1; return SANE_STATUS_INVAL; } void sanei_pio_close (int fd) { return; } int sanei_pio_read (int fd, u_char * buf, int n) { return -1; } int sanei_pio_write (int fd, const u_char * buf, int n) { return -1; } #endif /* __BEOS__ */ #endif /* !HAVE_IOPERM */ sane-backends-1.0.27/sanei/sanei_jpeg.c0000664000175000017500000001534612206524362014604 00000000000000/* Code for JPEG decompression by the Independent JPEG Group. Please see README.jpeg in the top level directory. */ #include "../include/sane/config.h" #ifdef HAVE_LIBJPEG #include "../include/sane/sanei_jpeg.h" typedef struct { struct djpeg_dest_struct pub; /* public fields */ /* Usually these two pointers point to the same place: */ char *iobuffer; /* fwrite's I/O buffer */ JSAMPROW pixrow; /* decompressor output buffer */ size_t buffer_width; /* width of I/O buffer */ JDIMENSION samples_per_row; /* JSAMPLEs per output row */ } ppm_dest_struct; typedef ppm_dest_struct *ppm_dest_ptr; /* * For 12-bit JPEG data, we either downscale the values to 8 bits * (to write standard byte-per-sample PPM/PGM files), or output * nonstandard word-per-sample PPM/PGM files. Downscaling is done * if PPM_NORAWWORD is defined (this can be done in the Makefile * or in jconfig.h). * (When the core library supports data precision reduction, a cleaner * implementation will be to ask for that instead.) */ #if BITS_IN_JSAMPLE==8 #define PUTPPMSAMPLE(ptr,v) *ptr++=(char) (v) #define BYTESPERSAMPLE 1 #define PPM_MAXVAL 255 #else #ifdef PPM_NORAWWORD #define PUTPPMSAMPLE(ptr,v) *ptr++=(char) ((v) >> (BITS_IN_JSAMPLE-8)) #define BYTESPERSAMPLE 1 #define PPM_MAXVAL 255 #else /* The word-per-sample format always puts the LSB first. */ #define PUTPPMSAMPLE(ptr,v) \ { register int val_=v; \ *ptr++=(char) (val_ & 0xFF); \ *ptr++=(char) ((val_ >> 8) & 0xFF); \ } #define BYTESPERSAMPLE 2 #define PPM_MAXVAL ((1<iobuffer, dest->buffer_width); } /* * This code is used when we have to copy the data and apply a pixel * format translation. Typically this only happens in 12-bit mode. */ METHODDEF (void) sanei_jpeg_copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied, char *data) { ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; register char *bufferptr; register JSAMPROW ptr; register JDIMENSION col; cinfo = cinfo; dinfo = dinfo; rows_supplied = rows_supplied; ptr = dest->pub.buffer[0]; bufferptr = dest->iobuffer; for (col = dest->samples_per_row; col > 0; col--) { PUTPPMSAMPLE (bufferptr, GETJSAMPLE (*ptr++)); } memcpy (data, dest->iobuffer, dest->buffer_width); } /* * Write some pixel data when color quantization is in effect. * We have to demap the color index values to straight data. */ METHODDEF (void) sanei_jpeg_put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied, char *data) { ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; register char *bufferptr; register int pixval; register JSAMPROW ptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register JSAMPROW color_map1 = cinfo->colormap[1]; register JSAMPROW color_map2 = cinfo->colormap[2]; register JDIMENSION col; rows_supplied = rows_supplied; ptr = dest->pub.buffer[0]; bufferptr = dest->iobuffer; for (col = cinfo->output_width; col > 0; col--) { pixval = GETJSAMPLE (*ptr++); PUTPPMSAMPLE (bufferptr, GETJSAMPLE (color_map0[pixval])); PUTPPMSAMPLE (bufferptr, GETJSAMPLE (color_map1[pixval])); PUTPPMSAMPLE (bufferptr, GETJSAMPLE (color_map2[pixval])); } memcpy (data, dest->iobuffer, dest->buffer_width); } METHODDEF (void) sanei_jpeg_put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied, char *data) { ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; register char *bufferptr; register JSAMPROW ptr; register JSAMPROW color_map = cinfo->colormap[0]; register JDIMENSION col; rows_supplied = rows_supplied; ptr = dest->pub.buffer[0]; bufferptr = dest->iobuffer; for (col = cinfo->output_width; col > 0; col--) { PUTPPMSAMPLE (bufferptr, GETJSAMPLE (color_map[GETJSAMPLE (*ptr++)])); } memcpy (data, dest->iobuffer, dest->buffer_width); } GLOBAL (djpeg_dest_ptr) sanei_jpeg_jinit_write_ppm (j_decompress_ptr cinfo) { ppm_dest_ptr dest; /* Create module interface object, fill in method pointers */ dest = (ppm_dest_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF (ppm_dest_struct)); dest->pub.start_output = sanei_jpeg_start_output_ppm; dest->pub.finish_output = sanei_jpeg_finish_output_ppm; /* Calculate output image dimensions so we can allocate space */ jpeg_calc_output_dimensions (cinfo); /* Create physical I/O buffer. Note we make this near on a PC. */ dest->samples_per_row = cinfo->output_width * cinfo->out_color_components; dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * SIZEOF (char)); dest->iobuffer = (char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width); if (cinfo->quantize_colors || BITS_IN_JSAMPLE != 8 || SIZEOF (JSAMPLE) != SIZEOF (char)) { /* When quantizing, we need an output buffer for clrmap indexes * that's separate from the physical I/O buffer. We also need a * separate buffer if pixel format translation must take place. */ dest->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->output_components, (JDIMENSION) 1); dest->pub.buffer_height = 1; if (!cinfo->quantize_colors) dest->pub.put_pixel_rows = sanei_jpeg_copy_pixel_rows; else if (cinfo->out_color_space == JCS_GRAYSCALE) dest->pub.put_pixel_rows = sanei_jpeg_put_demapped_gray; else dest->pub.put_pixel_rows = sanei_jpeg_put_demapped_rgb; } else { /* We will fwrite() directly from decompressor output buffer. */ /* Synthesize a JSAMPARRAY pointer structure */ /* Cast here implies near->far pointer conversion on PCs */ dest->pixrow = (JSAMPROW) dest->iobuffer; dest->pub.buffer = &dest->pixrow; dest->pub.buffer_height = 1; dest->pub.put_pixel_rows = sanei_jpeg_put_pixel_rows; } return (djpeg_dest_ptr) dest; } #endif sane-backends-1.0.27/sanei/sanei_ir.c0000664000175000017500000007372212775312262014300 00000000000000/** @file sanei_ir.c * * sanei_ir - functions for utilizing the infrared plane * * Copyright (C) 2012 Michael Rickmann * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * The threshold yen, otsu and max_entropy routines have been * adapted from the FOURIER 0.8 library by M. Emre Celebi, * http://sourceforge.net/projects/fourier-ipal/ which is * licensed under the GNU General Public License version 2 or later. */ #include #include #include #include #include #define BACKEND_NAME sanei_ir /* name of this module for debugging */ #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_ir.h" #include "../include/sane/sanei_magic.h" double * sanei_ir_create_norm_histo (const SANE_Parameters * params, const SANE_Uint *img_data); double * sanei_ir_accumulate_norm_histo (double * histo_data); /* Initialize sanei_ir */ void sanei_ir_init (void) { DBG_INIT (); } /* Create a normalized histogram of a grayscale image, internal */ double * sanei_ir_create_norm_histo (const SANE_Parameters * params, const SANE_Uint *img_data) { int is, i; int num_pixels; int *histo_data; double *histo; double term; DBG (10, "sanei_ir_create_norm_histo\n"); if ((params->format != SANE_FRAME_GRAY) && (params->format != SANE_FRAME_RED) && (params->format != SANE_FRAME_GREEN) && (params->format != SANE_FRAME_BLUE)) { DBG (5, "sanei_ir_create_norm_histo: invalid format\n"); return NULL; } /* Allocate storage for the histogram */ histo_data = calloc (HISTOGRAM_SIZE, sizeof (int)); histo = malloc (HISTOGRAM_SIZE * sizeof (double)); if ((histo == NULL) || (histo_data == NULL)) { DBG (5, "sanei_ir_create_norm_histo: no buffers\n"); if (histo) free (histo); if (histo_data) free (histo_data); return NULL; } num_pixels = params->pixels_per_line * params->lines; DBG (1, "sanei_ir_create_norm_histo: %d pixels_per_line, %d lines => %d num_pixels\n", params->pixels_per_line, params->lines, num_pixels); DBG (1, "sanei_ir_create_norm_histo: histo_data[] with %d x %ld bytes\n", HISTOGRAM_SIZE, sizeof(int)); /* Populate the histogram */ is = 16 - HISTOGRAM_SHIFT; /* Number of data bits to ignore */ DBG (1, "sanei_ir_create_norm_histo: depth %d, HISTOGRAM_SHIFT %d => ignore %d bits\n", params->depth, HISTOGRAM_SHIFT, is); for (i = num_pixels; i > 0; i--) { histo_data[*img_data++ >> is]++; } /* Calculate the normalized histogram */ term = 1.0 / (double) num_pixels; for (i = 0; i < HISTOGRAM_SIZE; i++) histo[i] = term * (double) histo_data[i]; free (histo_data); return histo; } /* Create the normalized histogram of a grayscale image */ SANE_Status sanei_ir_create_norm_histogram (const SANE_Parameters * params, const SANE_Uint *img_data, double ** histogram) { double *histo; DBG (10, "sanei_ir_create_norm_histogram\n"); histo = sanei_ir_create_norm_histo (params, img_data); if (!histo) return SANE_STATUS_NO_MEM; *histogram = histo; return SANE_STATUS_GOOD; } /* Accumulate a normalized histogram, internal */ double * sanei_ir_accumulate_norm_histo (double * histo_data) { int i; double *accum_data; accum_data = malloc (HISTOGRAM_SIZE * sizeof (double)); if (accum_data == NULL) { DBG (5, "sanei_ir_accumulate_norm_histo: Insufficient memory !\n"); return NULL; } accum_data[0] = histo_data[0]; for (i = 1; i < HISTOGRAM_SIZE; i++) accum_data[i] = accum_data[i - 1] + histo_data[i]; return accum_data; } /* Implements Yen's thresholding method */ SANE_Status sanei_ir_threshold_yen (const SANE_Parameters * params, double * norm_histo, int *thresh) { double *P1 = NULL; /* cumulative normalized histogram */ double *P1_sq = NULL; /* cumulative normalized histogram */ double *P2_sq = NULL; double crit, max_crit; int threshold, i; SANE_Status ret = SANE_STATUS_NO_MEM; DBG (10, "sanei_ir_threshold_yen\n"); P1 = sanei_ir_accumulate_norm_histo (norm_histo); P1_sq = malloc (HISTOGRAM_SIZE * sizeof (double)); P2_sq = malloc (HISTOGRAM_SIZE * sizeof (double)); if (!P1 || !P1_sq || !P2_sq) { DBG (5, "sanei_ir_threshold_yen: no buffers\n"); goto cleanup; } /* calculate cumulative squares */ P1_sq[0] = norm_histo[0] * norm_histo[0]; for (i = 1; i < HISTOGRAM_SIZE; i++) P1_sq[i] = P1_sq[i - 1] + norm_histo[i] * norm_histo[i]; P2_sq[HISTOGRAM_SIZE - 1] = 0.0; for (i = HISTOGRAM_SIZE - 2; i >= 0; i--) P2_sq[i] = P2_sq[i + 1] + norm_histo[i + 1] * norm_histo[i + 1]; /* Find the threshold that maximizes the criterion */ threshold = INT_MIN; max_crit = DBL_MIN; for (i = 0; i < HISTOGRAM_SIZE; i++) { crit = -1.0 * SAFE_LOG (P1_sq[i] * P2_sq[i]) + 2 * SAFE_LOG (P1[i] * (1.0 - P1[i])); if (crit > max_crit) { max_crit = crit; threshold = i; } } if (threshold == INT_MIN) { DBG (5, "sanei_ir_threshold_yen: no threshold found\n"); ret = SANE_STATUS_INVAL; } else { ret = SANE_STATUS_GOOD; if (params->depth > 8) { i = 1 << (params->depth - HISTOGRAM_SHIFT); *thresh = threshold * i + i / 2; } else *thresh = threshold; DBG (10, "sanei_ir_threshold_yen: threshold %d\n", *thresh); } cleanup: if (P1) free (P1); if (P1_sq) free (P1_sq); if (P2_sq) free (P2_sq); return ret; } /* Implements Otsu's thresholding method */ SANE_Status sanei_ir_threshold_otsu (const SANE_Parameters * params, double * norm_histo, int *thresh) { double *cnh = NULL; double *mean = NULL; double total_mean; double bcv, max_bcv; int first_bin, last_bin; int threshold, i; SANE_Status ret = SANE_STATUS_NO_MEM; DBG (10, "sanei_ir_threshold_otsu\n"); cnh = sanei_ir_accumulate_norm_histo (norm_histo); mean = malloc (HISTOGRAM_SIZE * sizeof (double)); if (!cnh || !mean) { DBG (5, "sanei_ir_threshold_otsu: no buffers\n"); goto cleanup; } mean[0] = 0.0; for (i = 1; i < HISTOGRAM_SIZE; i++) mean[i] = mean[i - 1] + i * norm_histo[i]; total_mean = mean[HISTOGRAM_SIZE - 1]; first_bin = 0; for (i = 0; i < HISTOGRAM_SIZE; i++) if (cnh[i] != 0) { first_bin = i; break; } last_bin = HISTOGRAM_SIZE - 1; for (i = HISTOGRAM_SIZE - 1; i >= first_bin; i--) if (1.0 - cnh[i] != 0) { last_bin = i; break; } threshold = INT_MIN; max_bcv = 0.0; for (i = first_bin; i <= last_bin; i++) { bcv = total_mean * cnh[i] - mean[i]; bcv *= bcv / (cnh[i] * (1.0 - cnh[i])); if (max_bcv < bcv) { max_bcv = bcv; threshold = i; } } if (threshold == INT_MIN) { DBG (5, "sanei_ir_threshold_otsu: no threshold found\n"); ret = SANE_STATUS_INVAL; } else { ret = SANE_STATUS_GOOD; if (params->depth > 8) { i = 1 << (params->depth - HISTOGRAM_SHIFT); *thresh = threshold * i + i / 2; } else *thresh = threshold; DBG (10, "sanei_ir_threshold_otsu: threshold %d\n", *thresh); } cleanup: if (cnh) free (cnh); if (mean) free (mean); return ret; } /* Implements a Maximum Entropy thresholding method */ SANE_Status sanei_ir_threshold_maxentropy (const SANE_Parameters * params, double * norm_histo, int *thresh) { int ih, it; int threshold; int first_bin; int last_bin; double tot_ent, max_ent; /* entropies */ double ent_back, ent_obj; double *P1; /* cumulative normalized histogram */ double *P2; SANE_Status ret = SANE_STATUS_NO_MEM; DBG (10, "sanei_ir_threshold_maxentropy\n"); /* Calculate the cumulative normalized histogram */ P1 = sanei_ir_accumulate_norm_histo (norm_histo); P2 = malloc (HISTOGRAM_SIZE * sizeof (double)); if (!P1 || !P2) { DBG (5, "sanei_ir_threshold_maxentropy: no buffers\n"); goto cleanup; } for ( ih = 0; ih < HISTOGRAM_SIZE; ih++ ) P2[ih] = 1.0 - P1[ih]; first_bin = 0; for ( ih = 0; ih < HISTOGRAM_SIZE; ih++ ) if (P1[ih] != 0) { first_bin = ih; break; } last_bin = HISTOGRAM_SIZE - 1; for ( ih = HISTOGRAM_SIZE - 1; ih >= first_bin; ih-- ) if (P2[ih] != 0) { last_bin = ih; break; } /* Calculate the total entropy each gray-level * and find the threshold that maximizes it */ threshold = INT_MIN; max_ent = DBL_MIN; for ( it = first_bin; it <= last_bin; it++ ) { /* Entropy of the background pixels */ ent_back = 0.0; for ( ih = 0; ih <= it; ih++ ) if (norm_histo[ih] != 0) ent_back -= ( norm_histo[ih] / P1[it] ) * log ( norm_histo[ih] / P1[it] ); /* Entropy of the object pixels */ ent_obj = 0.0; for ( ih = it + 1; ih < HISTOGRAM_SIZE; ih++ ) if (norm_histo[ih] != 0) ent_obj -= ( norm_histo[ih] / P2[it] ) * log ( norm_histo[ih] / P2[it] ); /* Total entropy */ tot_ent = ent_back + ent_obj; if ( max_ent < tot_ent ) { max_ent = tot_ent; threshold = it; } } if (threshold == INT_MIN) { DBG (5, "sanei_ir_threshold_maxentropy: no threshold found\n"); ret = SANE_STATUS_INVAL; } else { ret = SANE_STATUS_GOOD; if (params->depth > 8) { it = 1 << (params->depth - HISTOGRAM_SHIFT); *thresh = threshold * it + it / 2; } else *thresh = threshold; DBG (10, "sanei_ir_threshold_maxentropy: threshold %d\n", *thresh); } cleanup: if (P1) free (P1); if (P2) free (P2); return ret; } /* Generate gray scale luminance image from separate R, G, B images */ SANE_Status sanei_ir_RGB_luminance (SANE_Parameters * params, const SANE_Uint **in_img, SANE_Uint **out_img) { SANE_Uint *outi; int itop, i; if ((params->depth < 8) || (params->depth > 16) || (params->format != SANE_FRAME_GRAY)) { DBG (5, "sanei_ir_RGB_luminance: invalid format\n"); return SANE_STATUS_UNSUPPORTED; } itop = params->pixels_per_line * params->lines; outi = malloc (itop * sizeof(SANE_Uint)); if (!outi) { DBG (5, "sanei_ir_RGB_luminance: can not allocate out_img\n"); return SANE_STATUS_NO_MEM; } for (i = itop; i > 0; i--) *(outi++) = (218 * (int) *(in_img[0]++) + 732 * (int) *(in_img[1]++) + 74 * (int) *(in_img[2]++)) >> 10; *out_img = outi; return SANE_STATUS_GOOD; } /* Convert image from >8 bit depth to an 8 bit image */ SANE_Status sanei_ir_to_8bit (SANE_Parameters * params, const SANE_Uint *in_img, SANE_Parameters * out_params, SANE_Uint **out_img) { SANE_Uint *outi; size_t ssize; int i, is; if ((params->depth < 8) || (params->depth > 16)) { DBG (5, "sanei_ir_to_8bit: invalid format\n"); return SANE_STATUS_UNSUPPORTED; } ssize = params->pixels_per_line * params->lines; if (params->format == SANE_FRAME_RGB) ssize *= 3; outi = malloc (ssize * sizeof(SANE_Uint)); if (!outi) { DBG (5, "sanei_ir_to_8bit: can not allocate out_img\n"); return SANE_STATUS_NO_MEM; } if (out_params) { memmove (out_params, params, sizeof(SANE_Parameters)); out_params->bytes_per_line = out_params->pixels_per_line; if (params->format == SANE_FRAME_RGB) out_params->bytes_per_line *= 3; out_params->depth = 8; } memmove (outi, in_img, ssize * sizeof(SANE_Uint)); is = params->depth - 8; for (i = ssize; i > 0; i--) { *outi = *outi >> is, outi += 2; } *out_img = outi; return SANE_STATUS_GOOD; } /* allocate and initialize logarithmic lookup table */ SANE_Status sanei_ir_ln_table (int len, double **lut_ln) { double *llut; int i; DBG (10, "sanei_ir_ln_table\n"); llut = malloc (len * sizeof (double)); if (!llut) { DBG (5, "sanei_ir_ln_table: no table\n"); return SANE_STATUS_NO_MEM; } llut[0] = 0; llut[1] = 0; for (i = 2; i < len; i++) llut[i] = log ((double) i); *lut_ln = llut; return SANE_STATUS_GOOD; } /* Reduce red spectral overlap from an infrared image plane */ SANE_Status sanei_ir_spectral_clean (const SANE_Parameters * params, double *lut_ln, const SANE_Uint *red_data, SANE_Uint *ir_data) { const SANE_Uint *rptr; SANE_Uint *iptr; SANE_Int depth; double *llut; double rval, rsum, rrsum; double risum, rfac, radd; double *norm_histo; int64_t isum; int *calc_buf, *calc_ptr; int ival, imin, imax; int itop, len, ssize; int thresh_low, thresh; int irand, i; SANE_Status status; DBG (10, "sanei_ir_spectral_clean\n"); itop = params->pixels_per_line * params->lines; calc_buf = malloc (itop * sizeof (int)); /* could save this */ if (!calc_buf) { DBG (5, "sanei_ir_spectral_clean: no buffer\n"); return SANE_STATUS_NO_MEM; } depth = params->depth; len = 1 << depth; if (lut_ln) llut = lut_ln; else { status = sanei_ir_ln_table (len, &llut); if (status != SANE_STATUS_GOOD) { free (calc_buf); return status; } } /* determine not transparent areas to exclude them later * TODO: this has not been tested for negatives */ thresh_low = INT_MAX; status = sanei_ir_create_norm_histogram (params, ir_data, &norm_histo); if (status != SANE_STATUS_GOOD) { DBG (5, "sanei_ir_spectral_clean: no buffer\n"); free (calc_buf); return SANE_STATUS_NO_MEM; } /* TODO: remember only needed if cropping is not ok */ status = sanei_ir_threshold_maxentropy (params, norm_histo, &thresh); if (status == SANE_STATUS_GOOD) thresh_low = thresh; status = sanei_ir_threshold_otsu (params, norm_histo, &thresh); if ((status == SANE_STATUS_GOOD) && (thresh < thresh_low)) thresh_low = thresh; status = sanei_ir_threshold_yen (params, norm_histo, &thresh); if ((status == SANE_STATUS_GOOD) && (thresh < thresh_low)) thresh_low = thresh; if (thresh_low == INT_MAX) thresh_low = 0; else thresh_low /= 2; DBG (10, "sanei_ir_spectral_clean: low threshold %d\n", thresh_low); /* calculate linear regression ired (red) from randomly chosen points */ ssize = itop / 2; if (SAMPLE_SIZE < ssize) ssize = SAMPLE_SIZE; isum = 0; rsum = rrsum = risum = 0.0; i = ssize; while (i > 0) { irand = rand () % itop; rval = llut[red_data[irand]]; ival = ir_data[irand]; if (ival > thresh_low) { isum += ival; rsum += rval; rrsum += rval * rval; risum += rval * (double) ival; i--; } } /* "a" in ired = b + a * ln (red) */ rfac = ((double) ssize * risum - rsum * (double) isum) / ((double) ssize * rrsum - rsum * rsum); radd = ((double) isum - rfac * rsum) / (double) ssize; /* "b" unused */ DBG (10, "sanei_ir_spectral_clean: n = %d, ired(red) = %f * ln(red) + %f\n", ssize, rfac, radd); /* now calculate ired' = ired - a * ln (red) */ imin = INT_MAX; imax = INT_MIN; rptr = red_data; iptr = ir_data; calc_ptr = calc_buf; for (i = itop; i > 0; i--) { ival = *iptr++ - (int) (rfac * llut[*rptr++] + 0.5); if (ival > imax) imax = ival; if (ival < imin) imin = ival; *calc_ptr++ = ival; } /* scale the result back into the ired image */ calc_ptr = calc_buf; iptr = ir_data; rfac = (double) (len - 1) / (double) (imax - imin); for (i = itop; i > 0; i--) *iptr++ = (double) (*calc_ptr++ - imin) * rfac; if (!lut_ln) free (llut); free (calc_buf); free (norm_histo); return SANE_STATUS_GOOD; } /* Hopefully fast mean filter * JV: what does this do? Remove local mean? */ SANE_Status sanei_ir_filter_mean (const SANE_Parameters * params, const SANE_Uint *in_img, SANE_Uint *out_img, int win_rows, int win_cols) { const SANE_Uint *src; SANE_Uint *dest; int num_cols, num_rows; int itop, iadd, isub; int ndiv, the_sum; int nrow, ncol; int hwr, hwc; int *sum; int i, j; DBG (10, "sanei_ir_filter_mean, window: %d x%d\n", win_rows, win_cols); if (((win_rows & 1) == 0) || ((win_cols & 1) == 0)) { DBG (5, "sanei_ir_filter_mean: window even sized\n"); return SANE_STATUS_INVAL; } num_cols = params->pixels_per_line; num_rows = params->lines; sum = malloc (num_cols * sizeof (int)); if (!sum) { DBG (5, "sanei_ir_filter_mean: no buffer for sums\n"); return SANE_STATUS_NO_MEM; } dest = out_img; hwr = win_rows / 2; /* half window sizes */ hwc = win_cols / 2; /* pre-pre calculation */ for (j = 0; j < num_cols; j++) { sum[j] = 0; src = in_img + j; for (i = 0; i < hwr; i++) { sum[j] += *src; src += num_cols; } } itop = num_rows * num_cols; iadd = hwr * num_cols; isub = (hwr - win_rows) * num_cols; nrow = hwr; for (i = 0; i < num_rows; i++) { /* update row sums if possible */ if (isub >= 0) /* subtract old row */ { nrow--; src = in_img + isub; for (j = 0; j < num_cols; j++) sum[j] -= *src++; } isub += num_cols; if (iadd < itop) /* add new row */ { nrow++; src = in_img + iadd; for (j = 0; j < num_cols; j++) sum[j] += *src++; } iadd += num_cols; /* now we do the image columns using only the precalculated sums */ the_sum = 0; /* precalculation */ for (j = 0; j < hwc; j++) the_sum += sum[j]; ncol = hwc; /* at the left margin, real index hwc lower */ for (j = hwc; j < win_cols; j++) { ncol++; the_sum += sum[j]; *dest++ = the_sum / (ncol * nrow); } ndiv = ncol * nrow; /* in the middle, real index hwc + 1 higher */ for (j = 0; j < num_cols - win_cols; j++) { the_sum -= sum[j]; the_sum += sum[j + win_cols]; *dest++ = the_sum / ndiv; } /* at the right margin, real index hwc + 1 higher */ for (j = num_cols - win_cols; j < num_cols - hwc - 1; j++) { ncol--; the_sum -= sum[j]; /* j - hwc - 1 */ *dest++ = the_sum / (ncol * nrow); } } free (sum); return SANE_STATUS_GOOD; } /* Find noise by adaptive thresholding */ SANE_Status sanei_ir_filter_madmean (const SANE_Parameters * params, const SANE_Uint *in_img, SANE_Uint ** out_img, int win_size, int a_val, int b_val) { SANE_Uint *delta_ij, *delta_ptr; SANE_Uint *mad_ij; const SANE_Uint *mad_ptr; SANE_Uint *out_ij, *dest8; double ab_term; int num_rows, num_cols; int threshold, itop; size_t size; int ival, i; int depth; SANE_Status ret = SANE_STATUS_NO_MEM; DBG (10, "sanei_ir_filter_madmean\n"); depth = params->depth; if (depth != 8) { a_val = a_val << (depth - 8); b_val = b_val << (depth - 8); } num_cols = params->pixels_per_line; num_rows = params->lines; itop = num_rows * num_cols; size = itop * sizeof (SANE_Uint); out_ij = malloc (size); delta_ij = malloc (size); mad_ij = malloc (size); if (out_ij && delta_ij && mad_ij) { /* get the differences to the local mean */ mad_ptr = in_img; if (sanei_ir_filter_mean (params, mad_ptr, delta_ij, win_size, win_size) == SANE_STATUS_GOOD) { delta_ptr = delta_ij; for (i = 0; i < itop; i++) { ival = *mad_ptr++ - *delta_ptr; *delta_ptr++ = abs (ival); } /* make the second filtering window a bit larger */ win_size = MAD_WIN2_SIZE(win_size); /* and get the local mean differences */ if (sanei_ir_filter_mean (params, delta_ij, mad_ij, win_size, win_size) == SANE_STATUS_GOOD) { mad_ptr = mad_ij; delta_ptr = delta_ij; dest8 = out_ij; /* construct the noise map */ ab_term = (b_val - a_val) / (double) b_val; for (i = 0; i < itop; i++) { /* by calculating the threshold */ ival = *mad_ptr++; if (ival >= b_val) /* outlier */ threshold = a_val; else threshold = a_val + (double) ival *ab_term; /* above threshold is noise, indicated by 0 */ if (*delta_ptr++ >= threshold) *dest8++ = 0; else *dest8++ = 255; } *out_img = out_ij; ret = SANE_STATUS_GOOD; } } } else DBG (5, "sanei_ir_filter_madmean: Cannot allocate buffers\n"); free (mad_ij); free (delta_ij); return ret; } /* Add dark pixels to mask from static threshold */ void sanei_ir_add_threshold (const SANE_Parameters * params, const SANE_Uint *in_img, SANE_Uint * mask_img, int threshold) { const SANE_Uint *in_ptr; SANE_Uint *mask_ptr; int itop, i; DBG (10, "sanei_ir_add_threshold\n"); itop = params->pixels_per_line * params->lines; in_ptr = in_img; mask_ptr = mask_img; for (i = itop; i > 0; i--) { if (*in_ptr++ <= threshold) *mask_ptr = 0; mask_ptr++; } } /* Calculate minimal Manhattan distances for an image mask */ void sanei_ir_manhattan_dist (const SANE_Parameters * params, const SANE_Uint * mask_img, unsigned int *dist_map, unsigned int *idx_map, unsigned int erode) { const SANE_Uint *mask; unsigned int *index, *manhattan; int rows, cols, itop; int i, j; DBG (10, "sanei_ir_manhattan_dist\n"); if (erode != 0) erode = 255; /* initialize maps */ cols = params->pixels_per_line; rows = params->lines; itop = rows * cols; mask = mask_img; manhattan = dist_map; index = idx_map; for (i = 0; i < itop; i++) { *manhattan++ = *mask++; *index++ = i; } /* traverse from top left to bottom right */ manhattan = dist_map; index = idx_map; for (i = 0; i < rows; i++) for (j = 0; j < cols; j++) { if (*manhattan == erode) { /* take original, distance = 0, index stays the same */ *manhattan = 0; } else { /* assume maximal distance to clean pixel */ *manhattan = cols + rows; /* or one further away than pixel to the top */ if (i > 0) if (manhattan[-cols] + 1 < *manhattan) { *manhattan = manhattan[-cols] + 1; *index = index[-cols]; /* index follows */ } /* or one further away than pixel to the left */ if (j > 0) { if (manhattan[-1] + 1 < *manhattan) { *manhattan = manhattan[-1] + 1; *index = index[-1]; /* index follows */ } if (manhattan[-1] + 1 == *manhattan) if (rand () % 2 == 0) /* chose index */ *index = index[-1]; } } manhattan++; index++; } /* traverse from bottom right to top left */ manhattan = dist_map + itop - 1; index = idx_map + itop - 1; for (i = rows - 1; i >= 0; i--) for (j = cols - 1; j >= 0; j--) { if (i < rows - 1) { /* either what we had on the first pass or one more than the pixel to the bottm */ if (manhattan[+cols] + 1 < *manhattan) { *manhattan = manhattan[+cols] + 1; *index = index[+cols]; /* index follows */ } if (manhattan[+cols] + 1 == *manhattan) if (rand () % 2 == 0) /* chose index */ *index = index[+cols]; } if (j < cols - 1) { /* or one more than pixel to the right */ if (manhattan[1] + 1 < *manhattan) { *manhattan = manhattan[1] + 1; *index = index[1]; /* index follows */ } if (manhattan[1] + 1 == *manhattan) if (rand () % 2 == 0) /* chose index */ *index = index[1]; } manhattan--; index--; } } /* dilate or erode a mask image */ void sanei_ir_dilate (const SANE_Parameters *params, SANE_Uint *mask_img, unsigned int *dist_map, unsigned int *idx_map, int by) { SANE_Uint *mask; unsigned int *manhattan; unsigned int erode; unsigned int thresh; int i, itop; DBG (10, "sanei_ir_dilate\n"); if (by == 0) return; if (by > 0) { erode = 0; thresh = by; } else { erode = 1; thresh = -by; } itop = params->pixels_per_line * params->lines; mask = mask_img; sanei_ir_manhattan_dist (params, mask_img, dist_map, idx_map, erode); manhattan = dist_map; for (i = 0; i < itop; i++) { if (*manhattan++ <= thresh) *mask++ = 0; else *mask++ = 255; } return; } /* Suggest cropping for dark margins of positive film */ void sanei_ir_find_crop (const SANE_Parameters * params, unsigned int * dist_map, int inner, int * edges) { int width = params->pixels_per_line; int height = params->lines; uint64_t sum_x, sum_y, n; int64_t sum_xx, sum_xy; double a, b, mami; unsigned int *src; int off1, off2, inc, wh, i, j; DBG (10, "sanei_ir_find_crop\n"); /* loop through top, bottom, left, right */ for (j = 0; j < 4; j++) { if (j < 2) /* top, bottom */ { off1 = width / 8; /* only middle 3/4 */ off2 = width - off1; n = width - 2 * off1; src = dist_map + off1; /* first row */ inc = 1; wh = width; if (j == 1) /* last row */ src += (height - 1) * width; } else /* left, right */ { off1 = height / 8; /* only middle 3/4 */ off2 = height - off1; n = height - 2 * off1; src = dist_map + (off1 * width); /* first column */ inc = width; wh = height; if (j == 3) src += width - 1; /* last column */ } /* calculate linear regression */ sum_x = 0; sum_y = 0; sum_xx = 0; sum_xy = 0; for (i = off1; i < off2; i++) { sum_x += i; sum_y += *src; sum_xx += i * i; sum_xy += i * (*src); src += inc; } b = ((double) n * (double) sum_xy - (double) sum_x * (double) sum_y) / ((double) n * (double) sum_xx - (double) sum_x * (double) sum_x); a = ((double) sum_y - b * (double) sum_x) / (double) n; DBG (10, "sanei_ir_find_crop: y = %f + %f * x\n", a, b); /* take maximal/minimal value from either side */ mami = a + b * (wh - 1); if (inner) { if (a > mami) mami = a; } else { if (a < mami) mami = a; } edges[j] = mami + 0.5; } edges[1] = height - edges[1]; edges[3] = width - edges[3]; DBG (10, "sanei_ir_find_crop: would crop at top: %d, bot: %d, left %d, right %d\n", edges[0], edges[1], edges[2], edges[3]); return; } /* Dilate clean image parts into dirty ones and smooth */ SANE_Status sanei_ir_dilate_mean (const SANE_Parameters * params, SANE_Uint **in_img, SANE_Uint * mask_img, int dist_max, int expand, int win_size, SANE_Bool smooth, int inner, int *crop) { SANE_Uint *color; SANE_Uint *plane; unsigned int *dist_map, *manhattan; unsigned int *idx_map, *index; int dist; int rows, cols; int k, i, itop; SANE_Status ret = SANE_STATUS_NO_MEM; DBG (10, "sanei_ir_dilate_mean(): dist max = %d, expand = %d, win size = %d, smooth = %d, inner = %d\n", dist_max, expand, win_size, smooth, inner); cols = params->pixels_per_line; rows = params->lines; itop = rows * cols; idx_map = malloc (itop * sizeof (unsigned int)); dist_map = malloc (itop * sizeof (unsigned int)); plane = malloc (itop * sizeof (SANE_Uint)); if (!idx_map || !dist_map || !plane) DBG (5, "sanei_ir_dilate_mean: Cannot allocate buffers\n"); else { /* expand dirty regions into their half dirty surround*/ if (expand > 0) sanei_ir_dilate (params, mask_img, dist_map, idx_map, expand); /* for dirty pixels determine the closest clean ones */ sanei_ir_manhattan_dist (params, mask_img, dist_map, idx_map, 1); /* use the distance map to find how to crop dark edges */ if (crop) sanei_ir_find_crop (params, dist_map, inner, crop); /* replace dirty pixels */ for (k = 0; k < 3; k++) { manhattan = dist_map; index = idx_map; color = in_img[k]; /* first replacement */ for (i = 0; i < itop; i++) { dist = *manhattan++; if ((dist != 0) && (dist <= dist_max)) color[i] = color[index[i]]; } /* adapt pixels to their new surround and * smooth the whole image or the replaced pixels only */ ret = sanei_ir_filter_mean (params, color, plane, win_size, win_size); if (ret != SANE_STATUS_GOOD) break; else if (smooth) { /* a second mean results in triangular blur */ DBG (10, "sanei_ir_dilate_mean(): smoothing whole image\n"); ret = sanei_ir_filter_mean (params, plane, color, win_size, win_size); if (ret != SANE_STATUS_GOOD) break; } else { /* replace with smoothened pixels only */ DBG (10, "sanei_ir_dilate_mean(): smoothing replaced pixels only\n"); manhattan = dist_map; for (i = 0; i < itop; i++) { dist = *manhattan++; if ((dist != 0) && (dist <= dist_max)) color[i] = plane[i]; } } } } free (plane); free (dist_map); free (idx_map); return ret; } sane-backends-1.0.27/sanei/sanei_wire.c0000664000175000017500000004401112206524362014614 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei_wire.h" #define BACKEND_NAME sanei_wire #include "../include/sane/sanei_backend.h" void sanei_w_space (Wire * w, size_t howmuch) { size_t nbytes, left_over; int fd = w->io.fd; ssize_t nread, nwritten; DBG (3, "sanei_w_space: %lu bytes for wire %d\n", (u_long) howmuch, fd); if (howmuch > w->buffer.size) DBG (2, "sanei_w_space: bigger than buffer (%lu bytes), " "may be flush()\n", (u_long) w->buffer.size); if (w->status != 0) { DBG (1, "sanei_w_space: wire is in invalid state %d\n", w->status); return; } if (w->buffer.curr + howmuch > w->buffer.end) { DBG (4, "sanei_w_space: free buffer size is %lu\n", (u_long) (w->buffer.end - w->buffer.curr)); switch (w->direction) { case WIRE_ENCODE: nbytes = w->buffer.curr - w->buffer.start; w->buffer.curr = w->buffer.start; DBG (4, "sanei_w_space: ENCODE: sending %lu bytes\n", (u_long) nbytes); while (nbytes > 0) { nwritten = (*w->io.write) (fd, w->buffer.curr, nbytes); if (nwritten < 0) { DBG (1, "sanei_w_space: ENCODE: write failed (%d)\n", errno); w->status = errno; return; } w->buffer.curr += nwritten; nbytes -= nwritten; } w->buffer.curr = w->buffer.start; w->buffer.end = w->buffer.start + w->buffer.size; DBG (4, "sanei_w_space: ENCODE: free buffer is now %lu\n", (u_long) w->buffer.size); break; case WIRE_DECODE: left_over = w->buffer.end - w->buffer.curr; if ((signed) left_over < 0) { DBG (1, "sanei_w_space: DECODE: buffer underflow\n"); return; } if (left_over) { DBG (4, "sanei_w_space: DECODE: %lu bytes left in buffer\n", (u_long) left_over); memmove (w->buffer.start, w->buffer.curr, left_over); } w->buffer.curr = w->buffer.start; w->buffer.end = w->buffer.start + left_over; DBG (4, "sanei_w_space: DECODE: receiving data\n"); do { nread = (*w->io.read) (fd, w->buffer.end, w->buffer.size - left_over); if (nread <= 0) { DBG (2, "sanei_w_space: DECODE: no data received (%d)\n", errno); if (nread == 0) errno = EINVAL; w->status = errno; return; } left_over += nread; w->buffer.end += nread; } while (left_over < howmuch); DBG (4, "sanei_w_space: DECODE: %lu bytes read\n", (u_long) (w->buffer.end - w->buffer.start)); break; case WIRE_FREE: DBG (4, "sanei_w_space: FREE: doing nothing for free operation\n"); break; } } DBG (4, "sanei_w_space: done\n"); } void sanei_w_void (Wire * w) { DBG (3, "sanei_w_void: wire %d (void debug output)\n", w->io.fd); } void sanei_w_array (Wire * w, SANE_Word * len_ptr, void **v, WireCodecFunc w_element, size_t element_size) { SANE_Word len; char *val; int i; DBG (3, "sanei_w_array: wire %d, elements of size %lu\n", w->io.fd, (u_long) element_size); if (w->direction == WIRE_FREE) { if (*len_ptr && *v) { DBG (4, "sanei_w_array: FREE: freeing array (%d elements)\n", *len_ptr); val = *v; for (i = 0; i < *len_ptr; ++i) { (*w_element) (w, val); val += element_size; } free (*v); w->allocated_memory -= (*len_ptr * element_size); } else DBG (1, "sanei_w_array: FREE: tried to free array but *len_ptr or *v " "was NULL\n"); DBG (4, "sanei_w_array: FREE: done\n"); return; } if (w->direction == WIRE_ENCODE) len = *len_ptr; DBG (4, "sanei_w_array: send/receive array length\n"); sanei_w_word (w, &len); if (w->status) { DBG (1, "sanei_w_array: bad status: %d\n", w->status); return; } DBG (4, "sanei_w_array: array has %d elements\n", len); if (w->direction == WIRE_DECODE) { *len_ptr = len; if (len) { if (((unsigned int) len) > MAX_MEM || ((unsigned int) len * element_size) > MAX_MEM || (w->allocated_memory + len * element_size) > MAX_MEM) { DBG (0, "sanei_w_array: DECODE: maximum amount of allocated memory " "exceeded (limit: %u, new allocation: %lu, total: %lu bytes)\n", MAX_MEM, (unsigned long)(len * element_size), (unsigned long)(MAX_MEM + len * element_size)); w->status = ENOMEM; return; } *v = malloc (len * element_size); if (*v == 0) { /* Malloc failed, so return an error. */ DBG (1, "sanei_w_array: DECODE: not enough free memory\n"); w->status = ENOMEM; return; } memset (*v, 0, len * element_size); w->allocated_memory += (len * element_size); } else *v = 0; } val = *v; DBG (4, "sanei_w_array: transferring array elements\n"); for (i = 0; i < len; ++i) { (*w_element) (w, val); val += element_size; if (w->status) { DBG (1, "sanei_w_array: bad status: %d\n", w->status); return; } } DBG (4, "sanei_w_array: done\n"); } void sanei_w_ptr (Wire * w, void **v, WireCodecFunc w_value, size_t value_size) { SANE_Word is_null; DBG (3, "sanei_w_ptr: wire %d, value pointer at is %lu bytes\n", w->io.fd, (u_long) value_size); if (w->direction == WIRE_FREE) { if (*v && value_size) { DBG (4, "sanei_w_ptr: FREE: freeing value\n"); (*w_value) (w, *v); free (*v); w->allocated_memory -= value_size; } else DBG (1, "sanei_w_ptr: FREE: tried to free value but *v or value_size " "was NULL\n"); DBG (4, "sanei_w_ptr: FREE: done\n"); return; } if (w->direction == WIRE_ENCODE) is_null = (*v == 0); DBG (4, "sanei_w_ptr: send/receive is_null\n"); sanei_w_word (w, &is_null); if (w->status) { DBG (1, "sanei_w_ptr: bad status: %d\n", w->status); return; } if (!is_null) { if (w->direction == WIRE_DECODE) { DBG (4, "sanei_w_ptr: DECODE: receive data pointed at\n"); if (value_size > MAX_MEM) { DBG (0, "sanei_w_ptr: DECODE: maximum amount of allocated memory " "exceeded (limit: %u, new allocation: %lu, total: %lu bytes)\n", MAX_MEM, (unsigned long)value_size, (unsigned long)(w->allocated_memory + value_size)); w->status = ENOMEM; return; } *v = malloc (value_size); if (*v == 0) { /* Malloc failed, so return an error. */ DBG (1, "sanei_w_ptr: DECODE: not enough free memory\n"); w->status = ENOMEM; return; } w->allocated_memory += value_size; memset (*v, 0, value_size); } (*w_value) (w, *v); } else if (w->direction == WIRE_DECODE) *v = 0; DBG (4, "sanei_w_ptr: done\n"); } void sanei_w_byte (Wire * w, SANE_Byte * v) { DBG (3, "sanei_w_byte: wire %d\n", w->io.fd); (*w->codec.w_byte) (w, v); if (w->direction != WIRE_FREE) DBG (4, "sanei_w_byte: value = %d\n", *v); } void sanei_w_char (Wire * w, SANE_Char * v) { DBG (3, "sanei_w_char: wire %d\n", w->io.fd); (*w->codec.w_char) (w, v); if (w->direction != WIRE_FREE) DBG (4, "sanei_w_char: value = %d\n", *v); } void sanei_w_word (Wire * w, SANE_Word * v) { DBG (3, "sanei_w_word: wire %d\n", w->io.fd); (*w->codec.w_word) (w, v); if (w->direction != WIRE_FREE) DBG (4, "sanei_w_word: value = %d\n", *v); } void sanei_w_string (Wire * w, SANE_String * v) { DBG (3, "sanei_w_string: wire %d\n", w->io.fd); (*w->codec.w_string) (w, v); if (w->direction != WIRE_FREE && w->status == 0) DBG (4, "sanei_w_string: value = %s\n", *v); } void sanei_w_status (Wire * w, SANE_Status * v) { SANE_Word word = *v; DBG (3, "sanei_w_status: wire %d\n", w->io.fd); sanei_w_word (w, &word); if (w->direction == WIRE_DECODE) *v = word; if (w->direction != WIRE_FREE) DBG (4, "sanei_w_status: value = %d\n", word); } void sanei_w_bool (Wire * w, SANE_Bool * v) { SANE_Word word = *v; DBG (3, "sanei_w_bool: wire %d\n", w->io.fd); sanei_w_word (w, &word); if (w->direction == WIRE_DECODE) *v = word; if (w->direction != WIRE_FREE) DBG (4, "sanei_w_bool: value = %s\n", ((word == SANE_TRUE) ? ("true") : ("false"))); } void sanei_w_constraint_type (Wire * w, SANE_Constraint_Type * v) { SANE_Word word = *v; DBG (3, "sanei_w_constraint_type: wire %d\n", w->io.fd); sanei_w_word (w, &word); if (w->direction == WIRE_DECODE) *v = word; if (w->direction != WIRE_FREE) DBG (4, "sanei_w_constraint_type: value = %d\n", word); } void sanei_w_value_type (Wire * w, SANE_Value_Type * v) { SANE_Word word = *v; DBG (3, "sanei_w_value_type: wire %d\n", w->io.fd); sanei_w_word (w, &word); if (w->direction == WIRE_DECODE) *v = word; if (w->direction != WIRE_FREE) DBG (4, "sanei_w_value_type: value = %d\n", word); } void sanei_w_unit (Wire * w, SANE_Unit * v) { SANE_Word word = *v; DBG (3, "sanei_w_unit: wire %d\n", w->io.fd); sanei_w_word (w, &word); if (w->direction == WIRE_DECODE) *v = word; if (w->direction != WIRE_FREE) DBG (4, "sanei_w_unit: value = %d\n", word); /* gosh... all the sane_w_something should be a macro or something */ } void sanei_w_action (Wire * w, SANE_Action * v) { SANE_Word word = *v; DBG (3, "sanei_w_action: wire %d\n", w->io.fd); sanei_w_word (w, &word); if (w->direction == WIRE_DECODE) *v = word; if (w->direction != WIRE_FREE) DBG (4, "sanei_w_action: value = %d\n", word); } void sanei_w_frame (Wire * w, SANE_Frame * v) { SANE_Word word = *v; DBG (3, "sanei_w_frame: wire %d\n", w->io.fd); sanei_w_word (w, &word); if (w->direction == WIRE_DECODE) *v = word; if (w->direction != WIRE_FREE) DBG (4, "sanei_w_frame: value = %d\n", word); } void sanei_w_range (Wire * w, SANE_Range * v) { DBG (3, "sanei_w_range: wire %d\n", w->io.fd); sanei_w_word (w, &v->min); sanei_w_word (w, &v->max); sanei_w_word (w, &v->quant); if (w->direction != WIRE_FREE) DBG (4, "sanei_w_range: min/max/step = %f/%f/%f\n", SANE_UNFIX (v->min), SANE_UNFIX (v->max), SANE_UNFIX (v->quant)); } void sanei_w_device (Wire * w, SANE_Device * v) { DBG (3, "sanei_w_device: wire %d\n", w->io.fd); sanei_w_string (w, (SANE_String *) & v->name); sanei_w_string (w, (SANE_String *) & v->vendor); sanei_w_string (w, (SANE_String *) & v->model); sanei_w_string (w, (SANE_String *) & v->type); if (w->direction != WIRE_FREE) DBG (4, "sanei_w_device: %s %s from %s (%s)\n", v->name, v->model, v->vendor, v->type); } void sanei_w_device_ptr (Wire * w, SANE_Device ** v) { DBG (3, "sanei_w_device_ptr: wire %d\n", w->io.fd); sanei_w_ptr (w, (void **) v, (WireCodecFunc) sanei_w_device, sizeof (**v)); if (w->direction != WIRE_FREE) DBG (4, "sanei_w_device_ptr: device struct at %p\n", (void*) *v); } void sanei_w_option_descriptor (Wire * w, SANE_Option_Descriptor * v) { SANE_Word len; DBG (3, "sanei_w_option_descriptor: wire %d\n", w->io.fd); sanei_w_string (w, (SANE_String *) & v->name); sanei_w_string (w, (SANE_String *) & v->title); sanei_w_string (w, (SANE_String *) & v->desc); sanei_w_value_type (w, &v->type); sanei_w_unit (w, &v->unit); sanei_w_word (w, &v->size); sanei_w_word (w, &v->cap); sanei_w_constraint_type (w, &v->constraint_type); if (w->direction != WIRE_FREE) DBG (4, "sanei_w_option_descriptor: option %s\n", v->name); switch (v->constraint_type) { case SANE_CONSTRAINT_NONE: break; case SANE_CONSTRAINT_RANGE: sanei_w_ptr (w, (void **) &v->constraint.range, (WireCodecFunc) sanei_w_range, sizeof (SANE_Range)); break; case SANE_CONSTRAINT_WORD_LIST: if (w->direction != WIRE_DECODE) len = v->constraint.word_list[0] + 1; sanei_w_array (w, &len, (void **) &v->constraint.word_list, w->codec.w_word, sizeof (SANE_Word)); break; case SANE_CONSTRAINT_STRING_LIST: if (w->direction != WIRE_DECODE) { for (len = 0; v->constraint.string_list[len]; ++len); ++len; /* send NULL string, too */ } sanei_w_array (w, &len, (void **) &v->constraint.string_list, w->codec.w_string, sizeof (SANE_String)); break; } DBG (4, "sanei_w_option_descriptor: done\n"); } void sanei_w_option_descriptor_ptr (Wire * w, SANE_Option_Descriptor ** v) { DBG (3, "sanei_w_option_descriptor_ptr: wire %d\n", w->io.fd); sanei_w_ptr (w, (void **) v, (WireCodecFunc) sanei_w_option_descriptor, sizeof (**v)); DBG (4, "sanei_w_option_descriptor_ptr: done\n"); } void sanei_w_parameters (Wire * w, SANE_Parameters * v) { DBG (3, "sanei_w_parameters: wire %d\n", w->io.fd); sanei_w_frame (w, &v->format); sanei_w_bool (w, &v->last_frame); sanei_w_word (w, &v->bytes_per_line); sanei_w_word (w, &v->pixels_per_line); sanei_w_word (w, &v->lines); sanei_w_word (w, &v->depth); if (w->direction != WIRE_FREE) DBG (4, "sanei_w_parameters: format/last/bpl/ppl/lines/depth = " "%d/%d/%d/%d/%d/%d\n", v->format, v->last_frame, v->bytes_per_line, v->pixels_per_line, v->lines, v->depth); } static void flush (Wire * w) { DBG (3, "flush: wire %d\n", w->io.fd); if (w->direction == WIRE_ENCODE) sanei_w_space (w, w->buffer.size + 1); else if (w->direction == WIRE_DECODE) w->buffer.curr = w->buffer.end = w->buffer.start; if (w->status != 0) DBG (2, "flush: error status %d\n", w->status); DBG (4, "flush: wire flushed\n"); } void sanei_w_set_dir (Wire * w, WireDirection dir) { DBG (3, "sanei_w_set_dir: wire %d, old direction WIRE_%s\n", w->io.fd, w->direction == WIRE_ENCODE ? "ENCODE" : (w->direction == WIRE_DECODE ? "DECODE" : "FREE")); if (w->direction == WIRE_DECODE && w->buffer.curr != w->buffer.end) DBG (1, "sanei_w_set_dir: WARNING: will delete %lu bytes from buffer\n", (u_long) (w->buffer.end - w->buffer.curr)); flush (w); w->direction = dir; DBG (4, "sanei_w_set_dir: direction changed\n"); flush (w); DBG (3, "sanei_w_set_dir: wire %d, new direction WIRE_%s\n", w->io.fd, dir == WIRE_ENCODE ? "ENCODE" : (dir == WIRE_DECODE ? "DECODE" : "FREE")); } void sanei_w_call (Wire * w, SANE_Word procnum, WireCodecFunc w_arg, void *arg, WireCodecFunc w_reply, void *reply) { DBG (3, "sanei_w_call: wire %d (old status %d)\n", w->io.fd, w->status); w->status = 0; sanei_w_set_dir (w, WIRE_ENCODE); DBG (4, "sanei_w_call: sending request (procedure number: %d)\n", procnum); sanei_w_word (w, &procnum); (*w_arg) (w, arg); if (w->status == 0) { DBG (4, "sanei_w_call: receiving reply\n"); sanei_w_set_dir (w, WIRE_DECODE); (*w_reply) (w, reply); } if (w->status != 0) DBG (2, "sanei_w_call: error status %d\n", w->status); DBG (4, "sanei_w_call: done\n"); } void sanei_w_reply (Wire * w, WireCodecFunc w_reply, void *reply) { DBG (3, "sanei_w_reply: wire %d (old status %d)\n", w->io.fd, w->status); w->status = 0; sanei_w_set_dir (w, WIRE_ENCODE); (*w_reply) (w, reply); flush (w); if (w->status != 0) DBG (2, "sanei_w_reply: error status %d\n", w->status); DBG (4, "sanei_w_reply: done\n"); } void sanei_w_free (Wire * w, WireCodecFunc w_reply, void *reply) { WireDirection saved_dir = w->direction; DBG (3, "sanei_w_free: wire %d\n", w->io.fd); w->direction = WIRE_FREE; (*w_reply) (w, reply); w->direction = saved_dir; if (w->status != 0) DBG (2, "sanei_w_free: error status %d\n", w->status); DBG (4, "sanei_w_free: done\n"); } void sanei_w_init (Wire * w, void (*codec_init_func) (Wire *)) { DBG_INIT (); DBG (3, "sanei_w_init: initializing\n"); w->status = 0; w->direction = WIRE_ENCODE; w->buffer.size = 8192; w->buffer.start = malloc (w->buffer.size); if (w->buffer.start == 0) { /* Malloc failed, so return an error. */ w->status = ENOMEM; DBG (1, "sanei_w_init: not enough free memory\n"); } w->buffer.curr = w->buffer.start; w->buffer.end = w->buffer.start + w->buffer.size; if (codec_init_func != 0) { DBG (4, "sanei_w_init: initializing codec\n"); (*codec_init_func) (w); } w->allocated_memory = 0; DBG (4, "sanei_w_init: done\n"); } void sanei_w_exit (Wire * w) { DBG (3, "sanei_w_exit: wire %d\n", w->io.fd); if (w->buffer.start) { DBG (4, "sanei_w_exit: freeing buffer\n"); free (w->buffer.start); } w->buffer.start = 0; w->buffer.size = 0; DBG (4, "sanei_w_exit: done\n"); } sane-backends-1.0.27/sanei/sanei_udp.c0000664000175000017500000001225612617742237014455 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2006 Tower Technologies Author: Alessandro Zummo This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include #ifdef HAVE_WINSOCK2_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #include #include #include #endif #define BACKEND_NAME sanei_udp #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_udp.h" static SANE_Status sanei_udp_socket(int *fdp, int broadcast) { int fd; if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) return SANE_STATUS_INVAL; if (broadcast) { int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &opt, sizeof(opt)) < 0) { close(fd); return SANE_STATUS_INVAL; } } *fdp = fd; return SANE_STATUS_GOOD; } static SANE_Status sanei_udp_connect(int fd, const char *host, int port) { int err; struct sockaddr_in saddr; struct hostent *h; h = gethostbyname(host); if (h == NULL || h->h_addr_list[0] == NULL || h->h_addrtype != AF_INET) return SANE_STATUS_INVAL; memset(&saddr, 0x00, sizeof(struct sockaddr_in)); saddr.sin_family = AF_INET; saddr.sin_port = htons(port); memcpy(&saddr.sin_addr, h->h_addr_list[0], h->h_length); if ((err = connect(fd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in))) != 0) { return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } SANE_Status sanei_udp_open(const char *host, int port, int *fdp) { int status; #ifdef HAVE_WINSOCK2_H WSADATA wsaData; #endif DBG_INIT(); DBG(1, "%s\n", __func__); #ifdef HAVE_WINSOCK2_H status = WSAStartup(MAKEWORD(2, 2), &wsaData); if (status != 0) return SANE_STATUS_INVAL; #endif status = sanei_udp_socket(fdp, 0); if (status != SANE_STATUS_GOOD) return status; status = sanei_udp_connect(*fdp, host, port); if (status != SANE_STATUS_GOOD) { close(*fdp); return status; } return status; } SANE_Status sanei_udp_open_broadcast(int *fdp) { int status; DBG_INIT(); DBG(1, "%s\n", __func__); status = sanei_udp_socket(fdp, 1); if (status != SANE_STATUS_GOOD) return status; return status; } void sanei_udp_close(int fd) { close(fd); #ifdef HAVE_WINSOCK2_H WSACleanup(); #endif } ssize_t sanei_udp_write(int fd, const u_char * buf, int count) { return send(fd, buf, count, 0); } ssize_t sanei_udp_write_broadcast(int fd, int port, const u_char * buf, int count) { struct sockaddr_in saddr; memset(&saddr, 0x00, sizeof(struct sockaddr_in)); saddr.sin_family = AF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); return sendto(fd, buf, count, 0, (struct sockaddr *)&saddr, sizeof(saddr)); } void sanei_udp_set_nonblock(int fd, SANE_Bool nonblock) { #ifdef HAVE_WINSOCK2_H u_long mode=nonblock; ioctlsocket(fd, FIONBIO, &mode); #else long flags; flags = fcntl(fd, F_GETFL, 0L); if (nonblock) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; fcntl(fd, F_SETFL, flags); #endif } ssize_t sanei_udp_read(int fd, u_char * buf, int count) { return recv(fd, buf, count, 0); } ssize_t sanei_udp_recvfrom(int fd, u_char * buf, int count, char **fromp) { ssize_t l; socklen_t fl; struct sockaddr_in from; fl = sizeof(from); l = recvfrom(fd, buf, count, 0, (struct sockaddr *) &from, &fl); if (l > 0 && fromp) { *fromp = inet_ntoa(from.sin_addr); } return l; } sane-backends-1.0.27/sanei/sanei_net.c0000664000175000017500000001241712206524362014441 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei_net.h" void sanei_w_init_req (Wire *w, SANE_Init_Req *req) { sanei_w_word (w, &req->version_code); sanei_w_string (w, &req->username); } void sanei_w_init_reply (Wire *w, SANE_Init_Reply *reply) { sanei_w_status (w, &reply->status); sanei_w_word (w, &reply->version_code); } void sanei_w_get_devices_reply (Wire *w, SANE_Get_Devices_Reply *reply) { SANE_Word len; if (w->direction != WIRE_DECODE) { if (reply->device_list) { for (len = 0; reply->device_list[len]; ++len); ++len; } else len = 0; } sanei_w_status (w, &reply->status); sanei_w_array (w, &len, (void *) &reply->device_list, (WireCodecFunc) sanei_w_device_ptr, sizeof (reply->device_list[0])); } void sanei_w_open_reply (Wire *w, SANE_Open_Reply *reply) { sanei_w_status (w, &reply->status); sanei_w_word (w, &reply->handle); sanei_w_string (w, &reply->resource_to_authorize); } static void w_option_value (Wire *w, SANE_Word type, SANE_Word size, void **value) { SANE_Word len, element_size; WireCodecFunc w_value; switch (type) { case SANE_TYPE_BOOL: case SANE_TYPE_INT: case SANE_TYPE_FIXED: w_value = (WireCodecFunc) sanei_w_word; element_size = sizeof (SANE_Word); len = size / element_size; break; case SANE_TYPE_STRING: w_value = (WireCodecFunc) sanei_w_char; element_size = sizeof (SANE_Char); len = size; break; case SANE_TYPE_BUTTON: case SANE_TYPE_GROUP: w_value = (WireCodecFunc) sanei_w_void; len = 0; element_size = 0; break; default: w->status = EINVAL; return; } sanei_w_array (w, &len, value, w_value, element_size); } void sanei_w_option_descriptor_array (Wire *w, SANE_Option_Descriptor_Array *a) { sanei_w_array (w, &a->num_options, (void **) &a->desc, (WireCodecFunc) sanei_w_option_descriptor_ptr, sizeof (a->desc[0])); } void sanei_w_control_option_req (Wire *w, SANE_Control_Option_Req *req) { sanei_w_word (w, &req->handle); sanei_w_word (w, &req->option); sanei_w_word (w, &req->action); /* Up to and including version 2, we incorrectly attempted to encode the option value even the action was SANE_ACTION_SET_AUTO. */ if (w->version < 3 || req->action != SANE_ACTION_SET_AUTO) { sanei_w_word (w, &req->value_type); sanei_w_word (w, &req->value_size); w_option_value (w, req->value_type, req->value_size, &req->value); } } void sanei_w_control_option_reply (Wire *w, SANE_Control_Option_Reply *reply) { sanei_w_status (w, &reply->status); sanei_w_word (w, &reply->info); sanei_w_word (w, &reply->value_type); sanei_w_word (w, &reply->value_size); w_option_value (w, reply->value_type, reply->value_size, &reply->value); sanei_w_string (w, &reply->resource_to_authorize); } void sanei_w_get_parameters_reply (Wire *w, SANE_Get_Parameters_Reply *reply) { sanei_w_status (w, &reply->status); sanei_w_parameters (w, &reply->params); } void sanei_w_start_reply (Wire *w, SANE_Start_Reply *reply) { sanei_w_status (w, &reply->status); sanei_w_word (w, &reply->port); sanei_w_word (w, &reply->byte_order); sanei_w_string (w, &reply->resource_to_authorize); } void sanei_w_authorization_req (Wire *w, SANE_Authorization_Req *req) { sanei_w_string (w, &req->resource); sanei_w_string (w, &req->username); sanei_w_string (w, &req->password); } sane-backends-1.0.27/sanei/sanei_tcp.c0000664000175000017500000000712612775312262014447 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2006 Tower Technologies Author: Alessandro Zummo This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #ifdef HAVE_WINSOCK2_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #define BACKEND_NAME sanei_tcp #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_tcp.h" SANE_Status sanei_tcp_open(const char *host, int port, int *fdp) { int fd, err; struct sockaddr_in saddr; struct hostent *h; #ifdef HAVE_WINSOCK2_H WSADATA wsaData; #endif DBG_INIT(); DBG(1, "%s: host = %s, port = %d\n", __func__, host, port); #ifdef HAVE_WINSOCK2_H err = WSAStartup(MAKEWORD(2, 2), &wsaData); if (err != 0) return SANE_STATUS_INVAL; #endif h = gethostbyname(host); if (h == NULL || h->h_addr_list[0] == NULL || h->h_addrtype != AF_INET) return SANE_STATUS_INVAL; if ((fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) return SANE_STATUS_INVAL; memset(&saddr, 0x00, sizeof(struct sockaddr_in)); saddr.sin_family = AF_INET; saddr.sin_port = htons(port); memcpy(&saddr.sin_addr, h->h_addr_list[0], h->h_length); if ((err = connect(fd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in))) != 0) { close(fd); return SANE_STATUS_INVAL; } *fdp = fd; return SANE_STATUS_GOOD; } void sanei_tcp_close(int fd) { close(fd); #ifdef HAVE_WINSOCK2_H WSACleanup(); #endif } ssize_t sanei_tcp_write(int fd, const u_char * buf, int count) { return send(fd, buf, count, 0); } ssize_t sanei_tcp_read(int fd, u_char * buf, int count) { ssize_t bytes_recv = 0, rc = 1; while (bytes_recv < count && rc > 0) { rc = recv(fd, buf+bytes_recv, count-bytes_recv, 0); if (rc > 0) bytes_recv += rc; } return bytes_recv; } sane-backends-1.0.27/sanei/sanei_constrain_value.c0000664000175000017500000001735712775312262017064 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang and Andreas Beck This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" SANE_Status sanei_check_value (const SANE_Option_Descriptor * opt, void *value) { const SANE_String_Const *string_list; const SANE_Word *word_list; int i, count; const SANE_Range *range; SANE_Word w, v, *array; SANE_Bool *barray; size_t len; switch (opt->constraint_type) { case SANE_CONSTRAINT_RANGE: /* single values are treated as arrays of length 1 */ array = (SANE_Word *) value; /* compute number of elements */ if (opt->size > 0) { count = opt->size / sizeof (SANE_Word); } else { count = 1; } range = opt->constraint.range; /* for each element of the array, we check according to the constraint */ for (i = 0; i < count; i++) { /* test for min and max */ if (array[i] < range->min || array[i] > range->max) return SANE_STATUS_INVAL; /* check quantization */ if (range->quant) { v = (unsigned int) (array[i] - range->min + range->quant / 2) / range->quant; v = v * range->quant + range->min; if (v != array[i]) return SANE_STATUS_INVAL; } } break; case SANE_CONSTRAINT_WORD_LIST: w = *(SANE_Word *) value; word_list = opt->constraint.word_list; for (i = 1; w != word_list[i]; ++i) if (i >= word_list[0]) return SANE_STATUS_INVAL; break; case SANE_CONSTRAINT_STRING_LIST: string_list = opt->constraint.string_list; len = strlen (value); for (i = 0; string_list[i]; ++i) if (strncmp (value, string_list[i], len) == 0 && len == strlen (string_list[i])) return SANE_STATUS_GOOD; return SANE_STATUS_INVAL; case SANE_CONSTRAINT_NONE: switch (opt->type) { case SANE_TYPE_BOOL: /* single values are treated as arrays of length 1 */ array = (SANE_Word *) value; /* compute number of elements */ if (opt->size > 0) { count = opt->size / sizeof (SANE_Bool); } else { count = 1; } barray = (SANE_Bool *) value; /* test each boolean value in the array */ for (i = 0; i < count; i++) { if (barray[i] != SANE_TRUE && barray[i] != SANE_FALSE) return SANE_STATUS_INVAL; } break; default: break; } default: break; } return SANE_STATUS_GOOD; } /** * This function apply the constraint defined by the option descriptor * to the given value, and update the info flags holder if needed. It * return SANE_STATUS_INVAL if the constraint cannot be applied, else * it returns SANE_STATUS_GOOD. */ SANE_Status sanei_constrain_value (const SANE_Option_Descriptor * opt, void *value, SANE_Word * info) { const SANE_String_Const *string_list; const SANE_Word *word_list; int i, k, num_matches, match; const SANE_Range *range; SANE_Word w, v, *array; SANE_Bool b; size_t len; switch (opt->constraint_type) { case SANE_CONSTRAINT_RANGE: /* single values are treated as arrays of length 1 */ array = (SANE_Word *) value; /* compute number of elements */ if (opt->size > 0) { k = opt->size / sizeof (SANE_Word); } else { k = 1; } range = opt->constraint.range; /* for each element of the array, we apply the constraint */ for (i = 0; i < k; i++) { /* constrain min */ if (array[i] < range->min) { array[i] = range->min; if (info) { *info |= SANE_INFO_INEXACT; } } /* constrain max */ if (array[i] > range->max) { array[i] = range->max; if (info) { *info |= SANE_INFO_INEXACT; } } /* quantization */ if (range->quant) { v = (unsigned int) (array[i] - range->min + range->quant / 2) / range->quant; v = v * range->quant + range->min; /* due to rounding issues with sane 'fixed' values, * the computed value may exceed max */ if (v > range->max) { v = range->max; } if (v != array[i]) { array[i] = v; if (info) *info |= SANE_INFO_INEXACT; } } } break; case SANE_CONSTRAINT_WORD_LIST: /* If there is no exact match in the list, use the nearest value */ w = *(SANE_Word *) value; word_list = opt->constraint.word_list; for (i = 1, k = 1, v = abs (w - word_list[1]); i <= word_list[0]; i++) { SANE_Word vh; if ((vh = abs (w - word_list[i])) < v) { v = vh; k = i; } } if (w != word_list[k]) { *(SANE_Word *) value = word_list[k]; if (info) *info |= SANE_INFO_INEXACT; } break; case SANE_CONSTRAINT_STRING_LIST: /* Matching algorithm: take the longest unique match ignoring case. If there is an exact match, it is admissible even if the same string is a prefix of a longer option name. */ string_list = opt->constraint.string_list; len = strlen (value); /* count how many matches of length LEN characters we have: */ num_matches = 0; match = -1; for (i = 0; string_list[i]; ++i) if (strncasecmp (value, string_list[i], len) == 0 && len <= strlen (string_list[i])) { match = i; if (len == strlen (string_list[i])) { /* exact match... */ if (strcmp (value, string_list[i]) != 0) /* ...but case differs */ strcpy (value, string_list[match]); return SANE_STATUS_GOOD; } ++num_matches; } if (num_matches > 1) return SANE_STATUS_INVAL; else if (num_matches == 1) { strcpy (value, string_list[match]); return SANE_STATUS_GOOD; } return SANE_STATUS_INVAL; case SANE_CONSTRAINT_NONE: switch (opt->type) { case SANE_TYPE_BOOL: b = *(SANE_Bool *) value; if (b != SANE_TRUE && b != SANE_FALSE) return SANE_STATUS_INVAL; break; default: break; } default: break; } return SANE_STATUS_GOOD; } sane-backends-1.0.27/sanei/Makefile.am0000664000175000017500000000155412775312262014371 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include $(USB_CFLAGS) noinst_LTLIBRARIES = libsanei.la libsanei_la_SOURCES = sanei_ab306.c sanei_constrain_value.c \ sanei_init_debug.c sanei_net.c sanei_wire.c sanei_codec_ascii.c \ sanei_codec_bin.c sanei_scsi.c sanei_config.c sanei_config2.c \ sanei_pio.c sanei_pa4s2.c sanei_auth.c sanei_usb.c sanei_thread.c \ sanei_pv8630.c sanei_pp.c sanei_lm983x.c sanei_access.c sanei_tcp.c \ sanei_udp.c sanei_magic.c sanei_ir.c if HAVE_JPEG libsanei_la_SOURCES += sanei_jpeg.c endif EXTRA_DIST = linux_sg3_err.h os2_srb.h sanei_DomainOS.c sanei_DomainOS.h sane-backends-1.0.27/sanei/sanei_codec_ascii.c0000664000175000017500000001563712206524362016107 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei_wire.h" #include "../include/sane/sanei_codec_ascii.h" static const char *hexdigit = "0123456789abcdef"; static void skip_ws (Wire *w) { while (1) { sanei_w_space (w, 1); if (w->status != 0) return; if (!isspace (*w->buffer.curr)) return; ++w->buffer.curr; } } static unsigned get_digit (Wire *w) { unsigned digit; sanei_w_space (w, 1); digit = tolower(*w->buffer.curr++) - '0'; if (digit > 9) digit -= 'a' - ('9' + 1); if (digit > 0xf) { w->status = EINVAL; return 0; } return digit; } static SANE_Byte get_byte (Wire *w) { return get_digit (w) << 4 | get_digit (w); } static void ascii_w_byte (Wire *w, void *v) { SANE_Byte *b = v; switch (w->direction) { case WIRE_ENCODE: sanei_w_space (w, 3); *w->buffer.curr++ = hexdigit[(*b >> 4) & 0x0f]; *w->buffer.curr++ = hexdigit[(*b >> 0) & 0x0f]; *w->buffer.curr++ = '\n'; break; case WIRE_DECODE: skip_ws (w); *b = get_byte (w); break; case WIRE_FREE: break; } } static void ascii_w_char (Wire *w, void *v) { SANE_Char *c = v; switch (w->direction) { case WIRE_ENCODE: sanei_w_space (w, 5); *w->buffer.curr++ = '\''; if (*c == '\'' || *c == '\\') *w->buffer.curr++ = '\\'; *w->buffer.curr++ = *c; *w->buffer.curr++ = '\''; *w->buffer.curr++ = '\n'; break; case WIRE_DECODE: sanei_w_space (w, 4); if (*w->buffer.curr++ != '\'') { w->status = EINVAL; return; } *c = *w->buffer.curr++; if (*c == '\\') { sanei_w_space (w, 2); *c = *w->buffer.curr++; } if (*w->buffer.curr++ != '\'') { w->status = EINVAL; return; } break; case WIRE_FREE: break; } } static void ascii_w_string (Wire *w, void *v) { size_t len, alloced_len; SANE_String *s = v; char * str, ch; int done; switch (w->direction) { case WIRE_ENCODE: if (*s) { sanei_w_space (w, 1); *w->buffer.curr++ = '"'; str = *s; while ((ch = *str++)) { sanei_w_space (w, 2); if (ch == '"' || ch == '\\') *w->buffer.curr++ = '\\'; *w->buffer.curr++ = ch; } *w->buffer.curr++ = '"'; } else { sanei_w_space (w, 5); *w->buffer.curr++ = '('; *w->buffer.curr++ = 'n'; *w->buffer.curr++ = 'i'; *w->buffer.curr++ = 'l'; *w->buffer.curr++ = ')'; } sanei_w_space (w, 1); *w->buffer.curr++ = '\n'; break; case WIRE_DECODE: skip_ws (w); sanei_w_space (w, 1); ch = *w->buffer.curr++; if (ch == '"') { alloced_len = len = 0; str = 0; done = 0; do { sanei_w_space (w, 1); if (w->status != 0) return; ch = *w->buffer.curr++; if (ch == '"') done = 1; if (ch == '\\') { sanei_w_space (w, 1); ch = *w->buffer.curr++; } if (len >= alloced_len) { alloced_len += 1024; if (!str) str = malloc (alloced_len); else str = realloc (str, alloced_len); if (str == 0) { /* Malloc failed, so return an error. */ w->status = ENOMEM; return; } } str[len++] = ch; } while (!done); str[len - 1] = '\0'; *s = realloc (str, len); if (*s == 0) { /* Malloc failed, so return an error. */ w->status = ENOMEM; return; } } else if (ch == '(') { sanei_w_space (w, 4); if ( *w->buffer.curr++ != 'n' || *w->buffer.curr++ != 'i' || *w->buffer.curr++ != 'l' || *w->buffer.curr++ != ')') { w->status = EINVAL; return; } *s = 0; } else { w->status = EINVAL; return; } break; case WIRE_FREE: if (*s) free (*s); break; } } static void ascii_w_word (Wire *w, void *v) { SANE_Word val, *word = v; int i, is_negative = 0; char buf[16]; switch (w->direction) { case WIRE_ENCODE: val = *word; i = sizeof (buf) - 1; if (val < 0) { is_negative = 1; val = -val; } do { buf[i--] = '0' + (val % 10); val /= 10; } while (val); if (is_negative) buf[i--] = '-'; sanei_w_space (w, sizeof (buf) - i); memcpy (w->buffer.curr, buf + i + 1, sizeof (buf) - i - 1); w->buffer.curr += sizeof (buf) - i - 1; *w->buffer.curr++ = '\n'; break; case WIRE_DECODE: skip_ws (w); val = 0; sanei_w_space (w, 1); if (*w->buffer.curr == '-') { is_negative = 1; ++w->buffer.curr; } while (1) { sanei_w_space (w, 1); if (w->status != 0) return; if (!isdigit (*w->buffer.curr)) break; val = 10*val + (*w->buffer.curr++ - '0'); } *word = is_negative ? -val : val; break; case WIRE_FREE: break; } } void sanei_codec_ascii_init (Wire *w) { w->codec.w_byte = ascii_w_byte; w->codec.w_char = ascii_w_char; w->codec.w_word = ascii_w_word; w->codec.w_string = ascii_w_string; } sane-backends-1.0.27/sanei/sanei_thread.c0000664000175000017500000002727212775312262015134 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998-2001 Yuri Dario Copyright (C) 2003-2004 Gerhard Jaeger (pthread/process support) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. OS/2 Helper functions for the OS/2 port (using threads instead of forked processes). Don't use them in the backends, they are used automatically by macros. Other OS: use this lib, if you intend to let run your reader function within its own task (thread or process). Depending on the OS and/or the configure settings pthread or fork is used to achieve this goal. */ #include "../include/sane/config.h" #include #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_OS2_H # define INCL_DOSPROCESS # include #endif #ifdef __BEOS__ # undef USE_PTHREAD /* force */ # include #endif #if !defined USE_PTHREAD && !defined HAVE_OS2_H && !defined __BEOS__ # include #endif #define BACKEND_NAME sanei_thread /**< name of this module for debugging */ #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_thread.h" #ifndef _VAR_NOT_USED # define _VAR_NOT_USED(x) ((x)=(x)) #endif typedef struct { int (*func)( void* ); SANE_Status status; void *func_data; } ThreadDataDef, *pThreadDataDef; static ThreadDataDef td; /** for init issues - here only for the debug output */ void sanei_thread_init( void ) { DBG_INIT(); memset( &td, 0, sizeof(ThreadDataDef)); td.status = SANE_STATUS_GOOD; } SANE_Bool sanei_thread_is_forked( void ) { #if defined USE_PTHREAD || defined HAVE_OS2_H || defined __BEOS__ return SANE_FALSE; #else return SANE_TRUE; #endif } /* Use this to mark a SANE_Pid as invaild instead of marking with -1. */ static void sanei_thread_set_invalid( SANE_Pid *pid ) { #ifdef WIN32 #ifdef WINPTHREAD_API *pid = 0; #else pid->p = 0; #endif #else *pid = -1; #endif } /* Return if PID is a valid PID or not. */ SANE_Bool sanei_thread_is_valid( SANE_Pid pid ) { SANE_Bool rc = SANE_TRUE; #ifdef WIN32 #ifdef WINPTHREAD_API if (pid == 0) #else if (pid.p == 0) #endif rc = SANE_FALSE; #else if (pid == (SANE_Pid) -1) rc = SANE_FALSE; #endif return rc; } /* pthread_t is not an integer on all platform. Do our best to return * a PID-like value from structure. On platforms were it is an integer, * return that. */ static long sanei_thread_pid_to_long( SANE_Pid pid ) { int rc; #ifdef WIN32 #ifdef WINPTHREAD_API rc = pid; #else rc = pid.p; #endif #else rc = pid; #endif return rc; } int sanei_thread_kill( SANE_Pid pid ) { DBG(2, "sanei_thread_kill() will kill %ld\n", sanei_thread_pid_to_long(pid)); #ifdef USE_PTHREAD #if defined (__APPLE__) && defined (__MACH__) return pthread_kill((pthread_t)pid, SIGUSR2); #else return pthread_cancel((pthread_t)pid); #endif #elif defined HAVE_OS2_H return DosKillThread(pid); #else return kill( pid, SIGTERM ); #endif } #ifdef HAVE_OS2_H static void local_thread( void *arg ) { pThreadDataDef ltd = (pThreadDataDef)arg; DBG( 2, "thread started, calling func() now...\n" ); ltd->status = ltd->func( ltd->func_data ); DBG( 2, "func() done - status = %d\n", ltd->status ); _endthread(); } /* * starts a new thread or process * parameters: * star address of reader function * args pointer to scanner data structure * */ SANE_Pid sanei_thread_begin( int (*func)(void *args), void* args ) { SANE_Pid pid; td.func = func; td.func_data = args; pid = _beginthread( local_thread, NULL, 1024*1024, (void*)&td ); if ( pid == -1 ) { DBG( 1, "_beginthread() failed\n" ); return -1; } DBG( 2, "_beginthread() created thread %d\n", pid ); return pid; } SANE_Pid sanei_thread_waitpid( SANE_Pid pid, int *status ) { if (status) *status = 0; return pid; /* DosWaitThread( (TID*) &pid, DCWW_WAIT);*/ } int sanei_thread_sendsig( SANE_Pid pid, int sig ) { return 0; } #elif defined __BEOS__ static int32 local_thread( void *arg ) { pThreadDataDef ltd = (pThreadDataDef)arg; DBG( 2, "thread started, calling func() now...\n" ); ltd->status = ltd->func( ltd->func_data ); DBG( 2, "func() done - status = %d\n", ltd->status ); return ltd->status; } /* * starts a new thread or process * parameters: * star address of reader function * args pointer to scanner data structure * */ SANE_Pid sanei_thread_begin( int (*func)(void *args), void* args ) { SANE_Pid pid; td.func = func; td.func_data = args; pid = spawn_thread( local_thread, "sane thread (yes they can be)", B_NORMAL_PRIORITY, (void*)&td ); if ( pid < B_OK ) { DBG( 1, "spawn_thread() failed\n" ); return -1; } if ( resume_thread(pid) < B_OK ) { DBG( 1, "resume_thread() failed\n" ); return -1; } DBG( 2, "spawn_thread() created thread %d\n", pid ); return pid; } SANE_Pid sanei_thread_waitpid( SANE_Pid pid, int *status ) { int32 st; if ( wait_for_thread(pid, &st) < B_OK ) return -1; if ( status ) *status = (int)st; return pid; } int sanei_thread_sendsig( SANE_Pid pid, int sig ) { if (sig == SIGKILL) sig = SIGKILLTHR; return kill(pid, sig); } #else /* HAVE_OS2_H, __BEOS__ */ #ifdef USE_PTHREAD /* seems to be undefined in MacOS X */ #ifndef PTHREAD_CANCELED # define PTHREAD_CANCELED ((void *) -1) #endif /** */ #if defined (__APPLE__) && defined (__MACH__) static void thread_exit_handler( int signo ) { DBG( 2, "signal(%i) caught, calling pthread_exit now...\n", signo ); pthread_exit( PTHREAD_CANCELED ); } #endif static void* local_thread( void *arg ) { static int status; pThreadDataDef ltd = (pThreadDataDef)arg; #if defined (__APPLE__) && defined (__MACH__) struct sigaction act; sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = thread_exit_handler; sigaction( SIGUSR2, &act, 0 ); #else int old; pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &old ); pthread_setcanceltype ( PTHREAD_CANCEL_ASYNCHRONOUS, &old ); #endif DBG( 2, "thread started, calling func() now...\n" ); status = ltd->func( ltd->func_data ); /* so sanei_thread_get_status() will work correctly... */ ltd->status = status; DBG( 2, "func() done - status = %d\n", status ); /* return the status, so pthread_join is able to get it*/ pthread_exit((void*)&status ); } /** */ static void restore_sigpipe( void ) { #ifdef SIGPIPE struct sigaction act; if( sigaction( SIGPIPE, NULL, &act ) == 0 ) { if( act.sa_handler == SIG_IGN ) { sigemptyset( &act.sa_mask ); act.sa_flags = 0; act.sa_handler = SIG_DFL; DBG( 2, "restoring SIGPIPE to SIG_DFL\n" ); sigaction( SIGPIPE, &act, NULL ); } } #endif } #else /* the process stuff */ static int eval_wp_result( SANE_Pid pid, int wpres, int pf ) { int retval = SANE_STATUS_IO_ERROR; if( wpres == pid ) { if( WIFEXITED(pf)) { retval = WEXITSTATUS(pf); } else { if( !WIFSIGNALED(pf)) { retval = SANE_STATUS_GOOD; } else { DBG( 1, "Child terminated by signal %d\n", WTERMSIG(pf)); if( WTERMSIG(pf) == SIGTERM ) retval = SANE_STATUS_GOOD; } } } return retval; } #endif SANE_Pid sanei_thread_begin( int (func)(void *args), void* args ) { #ifdef USE_PTHREAD int result; pthread_t thread; #ifdef SIGPIPE struct sigaction act; /* if signal handler for SIGPIPE is SIG_DFL, replace by SIG_IGN */ if( sigaction( SIGPIPE, NULL, &act ) == 0 ) { if( act.sa_handler == SIG_DFL ) { sigemptyset( &act.sa_mask ); act.sa_flags = 0; act.sa_handler = SIG_IGN; DBG( 2, "setting SIGPIPE to SIG_IGN\n" ); sigaction( SIGPIPE, &act, NULL ); } } #endif td.func = func; td.func_data = args; result = pthread_create( &thread, NULL, local_thread, &td ); usleep( 1 ); if ( result != 0 ) { DBG( 1, "pthread_create() failed with %d\n", result ); sanei_thread_set_invalid(&thread); } else DBG( 2, "pthread_create() created thread %ld\n", (SANE_Pid)thread ); return (SANE_Pid)thread; #else SANE_Pid pid; pid = fork(); if( pid < 0 ) { DBG( 1, "fork() failed\n" ); return -1; } if( pid == 0 ) { /* run in child context... */ int status = func( args ); /* don't use exit() since that would run the atexit() handlers */ _exit( status ); } /* parents return */ return pid; #endif } int sanei_thread_sendsig( SANE_Pid pid, int sig ) { DBG(2, "sanei_thread_sendsig() %d to thread (id=%ld)\n", sig, sanei_thread_pid_to_long(pid)); #ifdef USE_PTHREAD return pthread_kill( (pthread_t)pid, sig ); #else return kill( pid, sig ); #endif } SANE_Pid sanei_thread_waitpid( SANE_Pid pid, int *status ) { #ifdef USE_PTHREAD int *ls; #else int ls; #endif SANE_Pid result = pid; int stat; stat = 0; DBG(2, "sanei_thread_waitpid() - %ld\n", sanei_thread_pid_to_long(pid)); #ifdef USE_PTHREAD int rc; rc = pthread_join( (pthread_t)pid, (void*)&ls ); if( 0 == rc ) { if( PTHREAD_CANCELED == ls ) { DBG(2, "* thread has been canceled!\n" ); stat = SANE_STATUS_GOOD; } else { stat = *ls; } DBG(2, "* result = %d (%p)\n", stat, (void*)status ); result = pid; } if ( EDEADLK == rc ) { if ( (pthread_t)pid != pthread_self() ) { /* call detach in any case to make sure that the thread resources * will be freed, when the thread has terminated */ DBG(2, "* detaching thread(%ld)\n", pid ); pthread_detach((pthread_t)pid); } } if (status) *status = stat; restore_sigpipe(); #else result = waitpid( pid, &ls, 0 ); if((result < 0) && (errno == ECHILD)) { stat = SANE_STATUS_GOOD; result = pid; } else { stat = eval_wp_result( pid, result, ls ); DBG(2, "* result = %d (%p)\n", stat, (void*)status ); } if( status ) *status = stat; #endif return result; } #endif /* HAVE_OS2_H */ SANE_Status sanei_thread_get_status( SANE_Pid pid ) { #if defined USE_PTHREAD || defined HAVE_OS2_H || defined __BEOS__ _VAR_NOT_USED( pid ); return td.status; #else int ls, stat, result; stat = SANE_STATUS_IO_ERROR; if( pid > 0 ) { result = waitpid( pid, &ls, WNOHANG ); stat = eval_wp_result( pid, result, ls ); } return stat; #endif } /* END sanei_thread.c .......................................................*/ sane-backends-1.0.27/sanei/sanei_access.c0000664000175000017500000001404312617742237015122 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005 Gerhard Jaeger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #define BACKEND_NAME sanei_access /**< name of this module for debugging */ #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_access.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #if defined(_WIN32) || defined(HAVE_OS2_H) # define PATH_SEP '\\' #else # define PATH_SEP '/' #endif #define REPLACEMENT_CHAR '_' #define PID_BUFSIZE 50 #define PROCESS_SELF 0 #define PROCESS_DEAD -1 #define PROCESS_OTHER 1 #ifdef ENABLE_LOCKING /** get the status/owner of a lock file * * The function tries to open an existing lockfile. On success, it reads out * the pid which is stored inside and tries to find out more about the status * of the process with the corresponding PID. * * @param fn - the complete filename of the lockfile to check * @return * - PROCESS_SELF - the calling process is owner of the lockfile * - PROCESS_DEAD - the process who created the lockfile is already dead * - PROCESS_OTHER - the process who created the lockfile is still alive */ static int get_lock_status( char *fn ) { char pid_buf[PID_BUFSIZE]; int fd, status; pid_t pid; fd = open( fn, O_RDONLY ); if( fd < 0 ) { DBG( 2, "does_process_exist: open >%s< failed: %s\n", fn, strerror(errno)); return PROCESS_OTHER; } read( fd, pid_buf, (PID_BUFSIZE-1)); pid_buf[PID_BUFSIZE-1] = '\0'; close( fd ); pid_buf[24] = '\0'; pid = strtol( pid_buf, NULL, 10 ); DBG( 2, "does_process_exist: PID %i\n", pid ); status = kill( pid, 0 ); if( status == -1 ) { if( errno == ESRCH ) { DBG( 2, "does_process_exist: process %i does not exist!\n", pid ); return PROCESS_DEAD; } DBG( 1, "does_process_exist: kill failed: %s\n", strerror(errno)); } else { DBG( 2, "does_process_exist: process %i does exist!\n", pid ); if( pid == getpid()){ DBG( 2, "does_process_exist: it's me!!!\n" ); return PROCESS_SELF; } } return PROCESS_OTHER; } static void create_lock_filename( char *fn, const char *devname ) { char *p; strcpy( fn, STRINGIFY(PATH_SANE_LOCK_DIR)"/LCK.." ); p = &fn[strlen(fn)]; strcat( fn, devname ); while( *p != '\0' ) { if( *p == PATH_SEP ) *p = REPLACEMENT_CHAR; p++; } DBG( 2, "sanei_access: lockfile name >%s<\n", fn ); } #endif void sanei_access_init( const char *backend ) { DBG_INIT(); DBG( 2, "sanei_access_init: >%s<\n", backend); } SANE_Status sanei_access_lock( const char *devicename, SANE_Word timeout ) { #ifdef ENABLE_LOCKING char fn[PATH_MAX]; char pid_buf[PID_BUFSIZE]; int fd, to, i; #endif DBG( 2, "sanei_access_lock: devname >%s<, timeout: %u\n", devicename, timeout ); #ifndef ENABLE_LOCKING return SANE_STATUS_GOOD; #else to = timeout; if (to <= 0) to = 1; create_lock_filename( fn, devicename ); for (i = 0; i < to; i++) { fd = open( fn, O_CREAT | O_EXCL | O_WRONLY, 0644 ); if (fd < 0) { if (errno == EEXIST) { switch( get_lock_status( fn )) { case PROCESS_DEAD: DBG( 2, "sanei_access_lock: " "deleting old lock file, retrying...\n" ); unlink( fn ); continue; break; case PROCESS_SELF: DBG( 2, "sanei_access_lock: success\n" ); return SANE_STATUS_GOOD; break; default: break; } DBG( 2, "sanei_access_lock: lock exists, waiting...\n" ); sleep(1); } else { DBG( 1, "sanei_access_lock: open >%s< failed: %s\n", fn, strerror(errno)); return SANE_STATUS_ACCESS_DENIED; } } else { DBG( 2, "sanei_access_lock: success\n" ); sprintf( pid_buf, "% 11i sane\n", getpid()); write(fd, pid_buf, strlen(pid_buf)); close( fd ); return SANE_STATUS_GOOD; } } DBG( 1, "sanei_access_lock: timeout!\n"); return SANE_STATUS_ACCESS_DENIED; #endif } SANE_Status sanei_access_unlock( const char *devicename ) { #ifdef ENABLE_LOCKING char fn[PATH_MAX]; #endif DBG( 2, "sanei_access_unlock: devname >%s<\n", devicename ); #ifdef ENABLE_LOCKING create_lock_filename( fn, devicename ); unlink( fn ); #endif return SANE_STATUS_GOOD; } /* END sanei_access.c .......................................................*/ sane-backends-1.0.27/sanei/sanei_init_debug.c0000664000175000017500000000755412775312262015777 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang and Andreas Beck This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #ifdef HAVE_VSYSLOG #include #endif #ifdef HAVE_OS2_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #include #ifdef HAVE_OS2_H # define INCL_DOS # include #endif #define BACKEND_NAME sanei_debug #include "../include/sane/sanei_debug.h" /* If a frontend enables translations, the system toupper() * call will use the LANG env var. We need to use ascii * instead, so the debugging env var name matches the docs. * This is a particular problem in Turkish, where 'i' does * not capitalize to 'I' */ static char toupper_ascii (int c) { if(c > 0x60 && c < 0x7b) return c - 0x20; return c; } void sanei_init_debug (const char * backend, int * var) { char ch, buf[256] = "SANE_DEBUG_"; const char * val; unsigned int i; *var = 0; for (i = 11; (ch = backend[i - 11]) != 0; ++i) { if (i >= sizeof (buf) - 1) break; buf[i] = toupper_ascii(ch); } buf[i] = '\0'; val = getenv (buf); if (!val) return; *var = atoi (val); DBG (0, "Setting debug level of %s to %d.\n", backend, *var); } void sanei_debug_msg (int level, int max_level, const char *be, const char *fmt, va_list ap) { char *msg; if (max_level >= level) { #ifdef S_IFSOCK if ( 1 == isfdtype(fileno(stderr), S_IFSOCK) ) { msg = (char *)malloc (sizeof(char) * (strlen(be) + strlen(fmt) + 4)); if (msg == NULL) { syslog (LOG_DEBUG, "[sanei_debug] malloc() failed\n"); vsyslog (LOG_DEBUG, fmt, ap); } else { sprintf (msg, "[%s] %s", be, fmt); vsyslog(LOG_DEBUG, msg, ap); free (msg); } } else #endif { fprintf (stderr, "[%s] ", be); vfprintf (stderr, fmt, ap); } } } #ifdef NDEBUG void sanei_debug_ndebug (int level, const char *fmt, ...) { /* this function is never called */ } #endif sane-backends-1.0.27/sanei/sanei_DomainOS.c0000664000175000017500000005625212775312262015336 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file defines a server for Apollo Domain/OS systems. It does all of the scsi_$ calls that are needed for SANE. This is necessary because Domain/OS will not allow a child process to access a parent's SCSI device. The interface is through a common, mapped area. Mutex locks are used to prevent concurrency problems, and eventcounts are used to notify a waiting process that its request has completed. This program is intended to support only one device at a time, although multiple instances of this program may run concurrently. It is intended that this program be forked/execd by a SANE application, and that it will exit when the application exits. Upon startup, the program is invoked with the path to an object that needs to be mapped for communication. The parent process will have already initialized the 'public' eventcounts and locks, and will be waiting for the ResultReady eventcount to be incremented. After initialization, the server will increment this eventcount, and wait for an incoming request, which is signified by the CommandAvailable eventcount. This EC will be incremented after another process has filled in the parameter area. DBG levels: 0 Error - always printed. 1 Basic monitor - print entry to main functions, or errors that are normally suppressed because they are reported at a higher level. 2 Medium monitor - show intermediate steps in functions 3 Detailed monitor - if its there, print it */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/config.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "sanei_DomainOS.h" /* Timeout period for SCSI wait, in milliseconds. We are using 100 seconds here. */ #define DomainScsiTimeout 100000 /* Communication Area pointer */ struct DomainServerCommon *com; /* Handle for fault handler */ pfm_$fh_handle_t FaultHandle; static struct { void *DomainSCSIPtr; /* Pointer to the data block for this device */ void *DomainSensePtr; /* Pointer to the sense area for this device */ u_int in_use : 1; /* is this DomainFdInfo in use? */ u_int fake_fd : 1; /* is this a fake file descriptor? */ scsi_$handle_t scsi_handle; /* SCSI handle */ scsi_$operation_id_t op_id; /* op_id of current request */ } *DomainFdInfo; /* This function is called error might have occured, but it would be one that I don't know how to handle, or never expect to happen. */ static void DomainErrorCheck(status_$t status, const char *message) { char *subsystem, *module, *code; short subsystem_length, module_length, code_length; if (status.all) { DBG(0, "Unrecoverable Domain/OS Error 0x%08x: %s\n", status.all, message); error_$find_text(status, &subsystem, &subsystem_length, &module, &module_length, &code, &code_length); if (subsystem_length && module_length && code_length) DBG(0, "%.*s (%.*s/%.*s)\n", code_length, code, subsystem_length, subsystem, module_length, module); exit(EXIT_FAILURE); } } /* This function is the fault handler for the server. Currently, it only handles asynchronous faults. It always returns to the faulting code, but it disables the handler, so that the server can be killed if the parent is unable to do so. */ pfm_$fh_func_val_t FaultHandler(pfm_$fault_rec_t *FaultStatusPtr) { status_$t status; DBG(1, "In fault handler, status is %08x\n", FaultStatusPtr->status.all); switch (FaultStatusPtr->status.all) { case fault_$quit: pfm_$release_fault_handler(FaultHandle, &status); DomainErrorCheck(status, "Can't release fault handler"); return pfm_$return_to_faulting_code; default: DBG(0, "Unrecognized fault type %08x, exiting\n", FaultStatusPtr->status.all); exit(EXIT_FAILURE); } } static void DomainSCSIOpen(void) { static int num_alloced = 0; int fd; scsi_$handle_t scsi_handle; pinteger len; void *DataBasePtr; /* Find fake fd. */ for (fd = 0; fd < num_alloced; ++fd) if (!DomainFdInfo[fd].in_use) break; /* Acquire the device */ DBG(1, "DomainSCSIOpen: dev='%s', fd=%d\n", com->open_path, fd); len = strlen(com->open_path); scsi_$acquire((char *)com->open_path, len, &scsi_handle, &com->CommandStatus); if (com->CommandStatus.all != status_$ok) { /* we have a failure, return an error code, and generate debug output */ DBG(1, "DomainSCSIOpen: acquire failed, Domain/OS status is %08x\n", com->CommandStatus.all); error_$print(com->CommandStatus); return; } else { /* device acquired, setup buffers and buffer pointers */ DBG(2, "DomainSCSIOpen: acquire OK, handle is %x\n", scsi_handle); /* Create/map the data area */ tmpnam(com->open_path); DBG(2, "DomainSCSIOpen: Data block name will be '%s'\n", com->open_path); DataBasePtr = ms_$crmapl(com->open_path, strlen(com->open_path), 0, DomainMaxDataSize + DomainSenseSize, ms_$cowriters, &com->CommandStatus); DomainErrorCheck(com->CommandStatus, "Creating Data Area"); assert((((int)DataBasePtr) & 0x3ff) == 0); /* Relies on Domain/OS mapping new objects on page boundary */ DBG(2, "Data Buffer block created at %p, length = 0x%lx\n", DataBasePtr, DomainMaxDataSize + DomainSenseSize); /* Wire the buffer */ scsi_$wire(scsi_handle, (void *)DataBasePtr, DomainMaxDataSize + DomainSenseSize, &com->CommandStatus); if (com->CommandStatus.all == status_$ok) { /* success, indicate status */ DBG(2, "Buffer wire was successful\n"); } else { /* failure, print detail and return code */ DBG(1, "Buffer wire failed, Domain/OS status is %08x\n", com->CommandStatus.all); error_$print(com->CommandStatus); return; } } if (fd >= num_alloced) { size_t new_size, old_size; old_size = num_alloced * sizeof (DomainFdInfo[0]); num_alloced = fd + 8; new_size = num_alloced * sizeof (DomainFdInfo[0]); if (DomainFdInfo) DomainFdInfo = realloc (DomainFdInfo, new_size); else DomainFdInfo = malloc (new_size); memset ((char *) DomainFdInfo + old_size, 0, new_size - old_size); assert(DomainFdInfo); } DomainFdInfo[fd].in_use = 1; DomainFdInfo[fd].scsi_handle = scsi_handle; DomainFdInfo[fd].DomainSCSIPtr = DataBasePtr; DomainFdInfo[fd].DomainSensePtr = ((char *)DataBasePtr) + DomainMaxDataSize; com->fd = fd; } static void DomainSCSIClose(void) { DomainFdInfo[com->fd].in_use = 0; DBG(1, "sanei_scsi_close: fd=%d\n", com->fd); /* Unwire the buffer */ scsi_$unwire(DomainFdInfo[com->fd].scsi_handle, DomainFdInfo[com->fd].DomainSCSIPtr, DomainMaxDataSize + DomainSenseSize, true, &com->CommandStatus); DomainErrorCheck(com->CommandStatus, "Unwiring SCSI buffers"); /* Release the device */ scsi_$release(DomainFdInfo[com->fd].scsi_handle, &com->CommandStatus); DomainErrorCheck(com->CommandStatus, "Releasing device"); /* Unmap the buffer area */ ms_$unmap(DomainFdInfo[com->fd].DomainSCSIPtr, DomainMaxDataSize + DomainSenseSize, &com->CommandStatus); DomainErrorCheck(com->CommandStatus, "Unmapping device data area"); } /* I have never seen this called, and I'm not sure what to do with it, so I guarantee that it will generate a fault, and I can add support for it. */ static void DomainSCSIFlushAll(void) { status_$t status; DBG(1, "DomainSCSIFlushAll: ()\n"); DBG(0, "Error - unimplemented feature in module" "BACKEND_NAME"); assert(1==0); } /* This function must only be called from DomainSCSIEnter. The current server architecture requires that the Wait immediately follow the Enter command. */ static void DomainSCSIWait(void) { int count; char *ascii_wait_status, *ascii_op_status; pinteger return_count; scsi_$op_status_t status_list[1]; scsi_$wait_index_t wait_index; /* wait for the command completion */ wait_index = scsi_$wait(DomainFdInfo[com->fd].scsi_handle, DomainScsiTimeout, true, DomainFdInfo[com->fd].op_id, 1, status_list, &return_count, &com->CommandStatus); DBG(2, " scsi_$wait returned status = %08x\n", com->CommandStatus.all); if (com->CommandStatus.all == status_$ok) { switch (wait_index) { case scsi_device_advance: ascii_wait_status = "scsi_device_advance"; break; case scsi_timeout: ascii_wait_status = "scsi_timeout"; break; case scsi_async_fault: ascii_wait_status = "scsi_async_fault"; break; default: ascii_wait_status = "unknown"; break; } DBG(2, " scsi_$wait status is %s, return_count is %d\n", ascii_wait_status, return_count); if (wait_index != scsi_device_advance) { DBG(1, "Error - SCSI timeout, or async fault\n"); com->CommandStatus.all = scsi_$operation_timeout; } else for (count = 0; count < return_count; count++) { switch (status_list[count].op_status) { case scsi_good_status: ascii_op_status = "scsi_good_status"; break; case scsi_check_condition: ascii_op_status = "scsi_check_condition"; break; case scsi_condition_met: ascii_op_status = "scsi_condition_met"; break; case scsi_rsv1: ascii_op_status = "scsi_rsv1"; break; case scsi_busy: ascii_op_status = "scsi_busy"; break; case scsi_rsv2: ascii_op_status = "scsi_rsv2"; break; case scsi_rsv3: ascii_op_status = "scsi_rsv3"; break; case scsi_rsv4: ascii_op_status = "scsi_rsv4"; break; case scsi_intermediate_good: ascii_op_status = "scsi_intermediate_good"; break; case scsi_rsv5: ascii_op_status = "scsi_rsv5"; break; case scsi_intermediate_condition_met: ascii_op_status = "scsi_intermediate_condition_met"; break; case scsi_rsv6: ascii_op_status = "scsi_rsv6"; break; case scsi_reservation_conflict: ascii_op_status = "scsi_reservation_conflict"; break; case scsi_rsv7: ascii_op_status = "scsi_rsv7"; break; case scsi_rsv8: ascii_op_status = "scsi_rsv8"; break; case scsi_rsv9: ascii_op_status = "scsi_rsv9"; break; case scsi_undefined_status: ascii_op_status = "scsi_undefined_status"; break; default: ascii_op_status = "unknown"; break; } DBG(2, " list[%d]: op=%x cmd_status=%08x, status=%s\n", count, status_list[count].op, status_list[count].cmd_status.all, ascii_op_status); switch (status_list[count].cmd_status.all) { case status_$ok: switch (status_list[count].op_status) { case scsi_good_status: break; case scsi_busy: com->CommandStatus.all = status_$ok | 0x80000000; com->SCSIStatus = scsi_busy; break; case scsi_check_condition: { static unsigned char scanner_sense_cdb[] = {3, 0, 0, 0, DomainSenseSize, 0}; static scsi_$cdb_t sense_cdb; static linteger sense_cdb_size; static scsi_$operation_id_t sense_op_id; static status_$t sense_status; static pinteger sense_return_count; static int temp; /* Issue the sense command (wire, issue, wait, unwire */ sense_cdb_size = sizeof(scanner_sense_cdb); memcpy(&sense_cdb, scanner_sense_cdb, sense_cdb_size); scsi_$do_command_2(DomainFdInfo[com->fd].scsi_handle, sense_cdb, sense_cdb_size, DomainFdInfo[com->fd].DomainSensePtr, DomainSenseSize, scsi_read, &sense_op_id, &sense_status); DomainErrorCheck(sense_status, "Executing sense command"); scsi_$wait(DomainFdInfo[com->fd].scsi_handle, DomainScsiTimeout, true, sense_op_id, 1, status_list, &sense_return_count, &sense_status); /* The following debug output is scanner specific */ DBG(2, "Sense information: Error code=%02x, ASC=%02x, ASCQ=%02x\n", ((u_char *)DomainFdInfo[com->fd].DomainSensePtr)[0], ((char *)DomainFdInfo[com->fd].DomainSensePtr)[0xc], ((char *)DomainFdInfo[com->fd].DomainSensePtr)[0xd]); DBG(2, " Sense dump:\n"); for (temp = 0; temp < DomainSenseSize; temp++) DBG(2, " %02x", ((u_char *)DomainFdInfo[com->fd].DomainSensePtr)[temp]); DBG(2, "\n"); /* see if buffer underrun - ILI/Valid are set, and command was a read */ /* Warning - this might be UMAX specific */ if ((((char *)DomainFdInfo[com->fd].DomainSensePtr)[0] == 0xf0) && (((char *)DomainFdInfo[com->fd].DomainSensePtr)[2] & 0x20) && (com->cdb.g0.cmd == 0x28)) { /* Warning - the following code is specific to endianness and int size */ /* Its also very ugly */ DBG(2, "Shortening destination length by %x bytes\n", *(int *)(((char *)DomainFdInfo[com->fd].DomainSensePtr)+3)); com->dst_size -= *(int *)(((char *)DomainFdInfo[com->fd].DomainSensePtr)+3); DBG(2, "Final dest size is %x\n", com->dst_size); } else { /* Set this status so that the sense handler can be called */ com->CommandStatus.all = status_$ok | 0x80000000; com->SCSIStatus = scsi_check_condition; } } break; default: /* I fault out in this case because I want to know about this error, and this guarantees that it will get attention. */ DBG(0, "Unrecoverable Domain/OS scsi handler error: status=%08x\n", status_list[count].op_status); exit(EXIT_FAILURE); } break; /* Handle recognized error conditions by copying the error code over */ case scsi_$operation_timeout: case scsi_$dma_underrun: /* received by some backend code */ case scsi_$hdwr_failure: /* received when both scanners were active */ com->CommandStatus = status_list[count].cmd_status; break; default: DBG(0, "Unrecoverable DomainOS scsi handler error: status=%08x\n", status_list[count].cmd_status.all); error_$print(status_list[count].cmd_status); exit(EXIT_FAILURE); } } /* Dump the buffer contents */ if (com->direction == scsi_read) { DBG(3, "first words of buffer are:\n"); for (return_count = 0; return_count < com->dst_size; return_count++) DBG(3, "%02X%c", ((unsigned char *)DomainFdInfo[com->fd].DomainSCSIPtr)[return_count], (return_count % 16) == 15 ? '\n' : ' '); DBG(3, "\n"); } } else { /* scsi_$wait failed */ DBG(1, "scsi_$wait failed, status is %08x\n", com->CommandStatus.all); } } static void DomainSCSIEnter(void) { static int count; /* Give some debug info */ DBG(1, "Entering DomainSCSIEnter, fd=%d, opcode=%02X\n", com->fd, com->cdb.all[0]); DBG(2, " CDB Contents: "); for (count = 0; count < com->cdb_size; count++) DBG(2, " %02X", com->cdb.all[count]); DBG(2, "\n"); DBG(2, "Buffer address is 0x%08x\n", DomainFdInfo[com->fd].DomainSCSIPtr); DBG(2, "Buffer size is %x\n", com->buf_size); DBG(2, "Direction is %s\n", (com->direction == scsi_read) ? "READ" : "WRITE"); /* now queue the command */ scsi_$do_command_2(DomainFdInfo[com->fd].scsi_handle, com->cdb, com->cdb_size, DomainFdInfo[com->fd].DomainSCSIPtr, com->buf_size, com->direction, &DomainFdInfo[com->fd].op_id, &com->CommandStatus); if (com->CommandStatus.all == status_$ok) { /* success, indicate status */ DBG(2, " scsi_$do_command_2 was successful, op_id is %x\n", DomainFdInfo[com->fd].op_id); /* If we supported multiple outstanding requests for one device, this would be a good breakpoint. We would store the op_id in a private place, and construct a queue for each device. This complicates things, and SANE doesn't seem to need it, so it won't be implemented. The current server architecture does the wait automatically, and status for the entire operation is returned. This means that the sanei_scsi_req_enter and sanei_scsi_req_wait calls don't make sense, and should generate an error. */ DomainSCSIWait(); } else { /* failure, print detail and return code */ DBG(1, " scsi_$do_command_2 failed, status is %08x\n", com->CommandStatus.all); } } /* This function is not currently used. */ static void DomainSCSIReqWait(void) { DBG(1, "sanei_scsi_req_wait: (id=%p)\n", NULL); return; } /* Startup the server */ static void sanei_DomainOS_init(char *path) { int done, index; long CommandTriggerValue; ec2_$ptr_t CommandAvailablePtr[1]; status_$t status; unsigned long length_mapped; DBG(1, "Starting Domain SANE Server, common area path = '%s'\n", path); com = ms_$mapl(path, strlen(path), 0, sizeof(struct DomainServerCommon), ms_$cowriters, ms_$wr, true, &length_mapped, &status); DomainErrorCheck(status, "Can't open common area"); if (length_mapped < sizeof(struct DomainServerCommon)) { DBG(0, "Error - can't open common area '%s' to required length\n", path); DBG(0, " Required length = %lx, returned length = %lx\n", sizeof(struct DomainServerCommon), length_mapped); exit(EXIT_FAILURE); } /* Make the file temporary, so it will disappear when it is closed */ ms_$mk_temporary(com, &status); DomainErrorCheck(status, "Can't make common file temporary"); DBG(2, "Domain Server common area mapped, length is %lx\n", length_mapped); /* The communication area is open, give the initial response */ ec2_$advance(&com->ResultReady, &status); DomainErrorCheck(status, "Can't advance ResultReady EC after startup"); /* Enter the command loop */ CommandAvailablePtr[0] = &com->CommandAvailable; CommandTriggerValue = ec2_$read(com->CommandAvailable) + 1; /* Inhibit asynchronous faults */ /* pfm_$inhibit();*/ /* Establish the fault handler */ FaultHandle = pfm_$establish_fault_handler(pfm_$all_faults, 0, FaultHandler, &status); DomainErrorCheck(status, "Can't establish fault handler"); done = 0; do { /* Wait for the command */ DBG(2, "Waiting for incoming command\n"); do { index = ec2_$wait_svc(CommandAvailablePtr, &CommandTriggerValue, 1, &status); } while (status.all == ec2_$wait_quit); DomainErrorCheck(status, "Error waiting on CommandAvailable EC"); assert (index == 1); /* Get the trigger value for next time - this avoids a race/deadlock */ CommandTriggerValue = ec2_$read(com->CommandAvailable) + 1; /* decode/execute the command */ DBG(2, "Received a command - opcode is %x\n", com->opcode); switch(com->opcode) { case Open: DomainSCSIOpen(); ec2_$advance(&com->CommandAccepted, &status); DomainErrorCheck(status, "Can't advance CommandAccepted EC on open"); break; case Close: DomainSCSIClose(); ec2_$advance(&com->CommandAccepted, &status); DomainErrorCheck(status, "Can't advance CommandAccepted EC on close"); break; case Enter: DomainSCSIEnter(); ec2_$advance(&com->CommandAccepted, &status); DomainErrorCheck(status, "Can't advance CommandAccepted EC on enter"); break; case Exit: done = 1; /* This lets the parent know that the command was accepted. It can be used to avoid sending a signal. */ ec2_$advance(&com->CommandAccepted, &status); DomainErrorCheck(status, "Can't advance CommandAccepted EC on exit"); break; default: DBG(1, "Invalid command %x received\n", com->opcode); } DBG(2, "Command processing complete\n"); } while (!done); /* This would be a good place to close all devices, but for now we'll assume they have already been closed by a well-behaved program */ /* Unmap the common area */ ms_$unmap(com, sizeof(struct DomainServerCommon), &status); DomainErrorCheck(status, "Error unmapping common area"); DBG(1, "Exiting Domain SANE Server\n"); /* pfm_$enable();*/ exit(EXIT_SUCCESS); } sane-backends-1.0.27/sanei/sanei_usb.c0000664000175000017500000026156613106201017014444 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001 - 2005 Henning Meier-Geinitz Copyright (C) 2001 Frank Zago (sanei_usb_control_msg) Copyright (C) 2003 Rene Rebe (sanei_read_int,sanei_set_timeout) Copyright (C) 2005 Paul Smedley (OS/2 usbcalls) Copyright (C) 2008 m. allan noah (bus rescan support, sanei_usb_clear_halt) Copyright (C) 2009 Julien BLACHE (libusb-1.0) Copyright (C) 2011 Reinhold Kainhofer (sanei_usb_set_endpoint) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file provides a generic USB interface. */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #ifdef HAVE_SYS_IOCTL_H #include #endif #include #include #include #ifdef HAVE_RESMGR #include #endif #ifdef HAVE_LIBUSB_LEGACY #ifdef HAVE_LUSB0_USB_H #include #else #include #endif #endif /* HAVE_LIBUSB_LEGACY */ #ifdef HAVE_LIBUSB #include #endif /* HAVE_LIBUSB */ #ifdef HAVE_USBCALLS #include #include #include #define MAX_RW 64000 static int usbcalls_timeout = 30 * 1000; /* 30 seconds */ USBHANDLE dh; PHEV pUsbIrqStartHev=NULL; static struct usb_descriptor_header * GetNextDescriptor( struct usb_descriptor_header *currHead, UCHAR *lastBytePtr) { UCHAR *currBytePtr, *nextBytePtr; if (!currHead->bLength) return (NULL); currBytePtr=(UCHAR *)currHead; nextBytePtr=currBytePtr+currHead->bLength; if (nextBytePtr>=lastBytePtr) return (NULL); return ((struct usb_descriptor_header*)nextBytePtr); } #endif /* HAVE_USBCALLS */ #if (defined (__FreeBSD__) && (__FreeBSD_version < 800064)) #include #include #endif /* __FreeBSD__ */ #if defined (__DragonFly__) #include #endif #define BACKEND_NAME sanei_usb #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_config.h" typedef enum { sanei_usb_method_scanner_driver = 0, /* kernel scanner driver (Linux, BSD) */ sanei_usb_method_libusb, sanei_usb_method_usbcalls } sanei_usb_access_method_type; typedef struct { SANE_Bool open; sanei_usb_access_method_type method; int fd; SANE_String devname; SANE_Int vendor; SANE_Int product; SANE_Int bulk_in_ep; SANE_Int bulk_out_ep; SANE_Int iso_in_ep; SANE_Int iso_out_ep; SANE_Int int_in_ep; SANE_Int int_out_ep; SANE_Int control_in_ep; SANE_Int control_out_ep; SANE_Int interface_nr; SANE_Int alt_setting; SANE_Int missing; #ifdef HAVE_LIBUSB_LEGACY usb_dev_handle *libusb_handle; struct usb_device *libusb_device; #endif /* HAVE_LIBUSB_LEGACY */ #ifdef HAVE_LIBUSB libusb_device *lu_device; libusb_device_handle *lu_handle; #endif /* HAVE_LIBUSB */ } device_list_type; /** * total number of devices that can be found at the same time */ #define MAX_DEVICES 100 /** * per-device information, using the functions' parameters dn as index */ static device_list_type devices[MAX_DEVICES]; /** * total number of detected devices in devices array */ static int device_number=0; /** * count number of time sanei_usb has been initialized */ static int initialized=0; #if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) static int libusb_timeout = 30 * 1000; /* 30 seconds */ #endif /* HAVE_LIBUSB_LEGACY */ #ifdef HAVE_LIBUSB static libusb_context *sanei_usb_ctx; #endif /* HAVE_LIBUSB */ #if defined (__linux__) /* From /usr/src/linux/driver/usb/scanner.h */ #define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int) #define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int) #define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, devrequest) /* Older (unofficial) IOCTL numbers for Linux < v2.4.13 */ #define SCANNER_IOCTL_VENDOR_OLD _IOR('u', 0xa0, int) #define SCANNER_IOCTL_PRODUCT_OLD _IOR('u', 0xa1, int) /* From /usr/src/linux/include/linux/usb.h */ typedef struct { unsigned char requesttype; unsigned char request; unsigned short value; unsigned short index; unsigned short length; } devrequest; /* From /usr/src/linux/driver/usb/scanner.h */ struct ctrlmsg_ioctl { devrequest req; void *data; } cmsg; #elif defined(__BEOS__) #include #include #endif /* __linux__ */ /* Debug level from sanei_init_debug */ static SANE_Int debug_level; static void print_buffer (const SANE_Byte * buffer, SANE_Int size) { #define NUM_COLUMNS 16 #define PRINT_BUFFER_SIZE (4 + NUM_COLUMNS * (3 + 1) + 1 + 1) char line_str[PRINT_BUFFER_SIZE]; char *pp; int column; int line; memset (line_str, 0, PRINT_BUFFER_SIZE); for (line = 0; line < ((size + NUM_COLUMNS - 1) / NUM_COLUMNS); line++) { pp = line_str; sprintf (pp, "%03X ", line * NUM_COLUMNS); pp += 4; for (column = 0; column < NUM_COLUMNS; column++) { if ((line * NUM_COLUMNS + column) < size) sprintf (pp, "%02X ", buffer[line * NUM_COLUMNS + column]); else sprintf (pp, " "); pp += 3; } for (column = 0; column < NUM_COLUMNS; column++) { if ((line * NUM_COLUMNS + column) < size) sprintf (pp, "%c", (buffer[line * NUM_COLUMNS + column] < 127) && (buffer[line * NUM_COLUMNS + column] > 31) ? buffer[line * NUM_COLUMNS + column] : '.'); else sprintf (pp, " "); pp += 1; } DBG (11, "%s\n", line_str); } } #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) static void kernel_get_vendor_product (int fd, const char *name, int *vendorID, int *productID) { #if defined (__linux__) /* read the vendor and product IDs via the IOCTLs */ if (ioctl (fd, SCANNER_IOCTL_VENDOR, vendorID) == -1) { if (ioctl (fd, SCANNER_IOCTL_VENDOR_OLD, vendorID) == -1) DBG (3, "kernel_get_vendor_product: ioctl (vendor) " "of device %s failed: %s\n", name, strerror (errno)); } if (ioctl (fd, SCANNER_IOCTL_PRODUCT, productID) == -1) { if (ioctl (fd, SCANNER_IOCTL_PRODUCT_OLD, productID) == -1) DBG (3, "sanei_usb_get_vendor_product: ioctl (product) " "of device %s failed: %s\n", name, strerror (errno)); } #elif defined(__BEOS__) { uint16 vendor, product; if (ioctl (fd, B_SCANNER_IOCTL_VENDOR, &vendor) != B_OK) DBG (3, "kernel_get_vendor_product: ioctl (vendor) " "of device %d failed: %s\n", fd, strerror (errno)); if (ioctl (fd, B_SCANNER_IOCTL_PRODUCT, &product) != B_OK) DBG (3, "sanei_usb_get_vendor_product: ioctl (product) " "of device %d failed: %s\n", fd, strerror (errno)); /* copy from 16 to 32 bit value */ *vendorID = vendor; *productID = product; } #elif (defined (__FreeBSD__) && __FreeBSD_version < 800064) || defined (__DragonFly__) { int controller; int ctrl_fd; char buf[40]; int dev; for (controller = 0; ; controller++ ) { snprintf (buf, sizeof (buf) - 1, "/dev/usb%d", controller); ctrl_fd = open (buf, O_RDWR); /* If we can not open the usb controller device, treat it as the end of controller devices */ if (ctrl_fd < 0) break; /* Search for the scanner device on this bus */ for (dev = 1; dev < USB_MAX_DEVICES; dev++) { struct usb_device_info devInfo; devInfo.udi_addr = dev; if (ioctl (ctrl_fd, USB_DEVICEINFO, &devInfo) == -1) break; /* Treat this as the end of devices for this controller */ snprintf (buf, sizeof (buf), "/dev/%s", devInfo.udi_devnames[0]); if (strncmp (buf, name, sizeof (buf)) == 0) { *vendorID = (int) devInfo.udi_vendorNo; *productID = (int) devInfo.udi_productNo; close (ctrl_fd); return; } } close (ctrl_fd); } DBG (3, "kernel_get_vendor_product: Could not retrieve " "vendor/product ID from device %s\n", name); } #endif /* defined (__linux__), defined(__BEOS__), ... */ /* put more os-dependant stuff ... */ } #endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) */ /** * store the given device in device list if it isn't already * in it * @param device device to store if new */ static void store_device (device_list_type device) { int i = 0; int pos = -1; /* if there are already some devices present, check against * them and leave if an equal one is found */ for (i = 0; i < device_number; i++) { if (devices[i].method == device.method && !strcmp (devices[i].devname, device.devname) && devices[i].vendor == device.vendor && devices[i].product == device.product) { /* * Need to update the LibUSB device pointer, since it might * have changed after the latest USB scan. */ #ifdef HAVE_LIBUSB_LEGACY devices[i].libusb_device = device.libusb_device; #endif #ifdef HAVE_LIBUSB devices[i].lu_device = device.lu_device; #endif devices[i].missing=0; DBG (3, "store_device: not storing device %s\n", device.devname); /* since devname has been created by strdup() * we have to free it to avoid leaking memory */ free(device.devname); return; } if (devices[i].missing >= 2) pos = i; } /* reuse slot of a device now missing */ if(pos > -1){ DBG (3, "store_device: overwrite dn %d with %s\n", pos, device.devname); /* we reuse the slot used by a now missing device * so we free the allocated memory for the missing one */ if (devices[pos].devname) { free(devices[pos].devname); devices[pos].devname = NULL; } } else{ if(device_number >= MAX_DEVICES){ DBG (3, "store_device: no room for %s\n", device.devname); return; } pos = device_number; device_number++; DBG (3, "store_device: add dn %d with %s\n", pos, device.devname); } memcpy (&(devices[pos]), &device, sizeof (device)); devices[pos].open = SANE_FALSE; } #ifdef HAVE_LIBUSB static char * sanei_libusb_strerror (int errcode) { /* Error codes & descriptions from the libusb-1.0 documentation */ switch (errcode) { case LIBUSB_SUCCESS: return "Success (no error)"; case LIBUSB_ERROR_IO: return "Input/output error"; case LIBUSB_ERROR_INVALID_PARAM: return "Invalid parameter"; case LIBUSB_ERROR_ACCESS: return "Access denied (insufficient permissions)"; case LIBUSB_ERROR_NO_DEVICE: return "No such device (it may have been disconnected)"; case LIBUSB_ERROR_NOT_FOUND: return "Entity not found"; case LIBUSB_ERROR_BUSY: return "Resource busy"; case LIBUSB_ERROR_TIMEOUT: return "Operation timed out"; case LIBUSB_ERROR_OVERFLOW: return "Overflow"; case LIBUSB_ERROR_PIPE: return "Pipe error"; case LIBUSB_ERROR_INTERRUPTED: return "System call interrupted (perhaps due to signal)"; case LIBUSB_ERROR_NO_MEM: return "Insufficient memory"; case LIBUSB_ERROR_NOT_SUPPORTED: return "Operation not supported or unimplemented on this platform"; case LIBUSB_ERROR_OTHER: return "Other error"; default: return "Unknown libusb-1.0 error code"; } } #endif /* HAVE_LIBUSB */ void sanei_usb_init (void) { #ifdef HAVE_LIBUSB int ret; #endif /* HAVE_LIBUSB */ DBG_INIT (); #ifdef DBG_LEVEL debug_level = DBG_LEVEL; #else debug_level = 0; #endif /* if no device yet, clean up memory */ if(device_number==0) memset (devices, 0, sizeof (devices)); /* initialize USB with old libusb library */ #ifdef HAVE_LIBUSB_LEGACY DBG (4, "%s: Looking for libusb devices\n", __func__); usb_init (); #ifdef DBG_LEVEL if (DBG_LEVEL > 4) usb_set_debug (255); #endif /* DBG_LEVEL */ #endif /* HAVE_LIBUSB_LEGACY */ /* initialize USB using libusb-1.0 */ #ifdef HAVE_LIBUSB if (!sanei_usb_ctx) { DBG (4, "%s: initializing libusb-1.0\n", __func__); ret = libusb_init (&sanei_usb_ctx); if (ret < 0) { DBG (1, "%s: failed to initialize libusb-1.0, error %d\n", __func__, ret); return; } #ifdef DBG_LEVEL if (DBG_LEVEL > 4) libusb_set_debug (sanei_usb_ctx, 3); #endif /* DBG_LEVEL */ } #endif /* HAVE_LIBUSB */ #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) DBG (4, "%s: SANE is built without support for libusb\n", __func__); #endif /* sanei_usb is now initialized */ initialized++; /* do a first scan of USB busses to fill device list */ sanei_usb_scan_devices(); } void sanei_usb_exit (void) { int i; /* check we have really some work to do */ if(initialized==0) { DBG (1, "%s: sanei_usb in not initialized!\n", __func__); return; } /* decrement the use count */ initialized--; /* if we reach 0, free allocated resources */ if(initialized==0) { /* free allocated resources */ DBG (4, "%s: freeing resources\n", __func__); for (i = 0; i < device_number; i++) { if (devices[i].devname != NULL) { DBG (5, "%s: freeing device %02d\n", __func__, i); free(devices[i].devname); devices[i].devname=NULL; } } #ifdef HAVE_LIBUSB if (sanei_usb_ctx) { libusb_exit (sanei_usb_ctx); /* reset libusb-1.0 context */ sanei_usb_ctx=NULL; } #endif /* reset device_number */ device_number=0; } else { DBG (4, "%s: not freeing resources since use count is %d\n", __func__, initialized); } return; } #ifdef HAVE_USBCALLS /** scan for devices through usbcall method * Check for devices using OS/2 USBCALLS Interface */ static void usbcall_scan_devices(void) { SANE_Char devname[1024]; device_list_type device; CHAR ucData[2048]; struct usb_device_descriptor *pDevDesc; struct usb_config_descriptor *pCfgDesc; APIRET rc; ULONG ulNumDev, ulDev, ulBufLen; ulBufLen = sizeof(ucData); memset(&ucData,0,sizeof(ucData)); rc = UsbQueryNumberDevices( &ulNumDev); if(rc==0 && ulNumDev) { for (ulDev=1; ulDev<=ulNumDev; ulDev++) { UsbQueryDeviceReport(ulDev, &ulBufLen, ucData); pDevDesc = (struct usb_device_descriptor*) ucData; pCfgDesc = (struct usb_config_descriptor*) (ucData+sizeof(struct usb_device_descriptor)); int interface=0; SANE_Bool found; if (!pCfgDesc->bConfigurationValue) { DBG (1, "%s: device 0x%04x/0x%04x is not configured\n", __func__, pDevDesc->idVendor, pDevDesc->idProduct); continue; } if (pDevDesc->idVendor == 0 || pDevDesc->idProduct == 0) { DBG (5, "%s: device 0x%04x/0x%04x looks like a root hub\n", __func__, pDevDesc->idVendor, pDevDesc->idProduct); continue; } found = SANE_FALSE; if (pDevDesc->bDeviceClass == USB_CLASS_VENDOR_SPEC) { found = SANE_TRUE; } if (!found) { DBG (5, "%s: device 0x%04x/0x%04x: no suitable interfaces\n", __func__, pDevDesc->idVendor, pDevDesc->idProduct); continue; } snprintf (devname, sizeof (devname), "usbcalls:%d", ulDev); memset (&device, 0, sizeof (device)); device.devname = strdup (devname); device.fd = ulDev; /* store usbcalls device number */ device.vendor = pDevDesc->idVendor; device.product = pDevDesc->idProduct; device.method = sanei_usb_method_usbcalls; device.interface_nr = interface; device.alt_setting = 0; DBG (4, "%s: found usbcalls device (0x%04x/0x%04x) as device number %s\n", __func__, pDevDesc->idVendor, pDevDesc->idProduct,device.devname); store_device(device); } } } #endif /* HAVE_USBCALLS */ #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) /** scan for devices using kernel device. * Check for devices using kernel device */ static void kernel_scan_devices(void) { SANE_String *prefix; SANE_String prefixlist[] = { #if defined(__linux__) "/dev/", "usbscanner", "/dev/usb/", "scanner", #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined (__DragonFly__) "/dev/", "uscanner", #elif defined(__BEOS__) "/dev/scanner/usb/", "", #endif 0, 0 }; SANE_Int vendor, product; SANE_Char devname[1024]; int fd; device_list_type device; DBG (4, "%s: Looking for kernel scanner devices\n", __func__); /* Check for devices using the kernel scanner driver */ for (prefix = prefixlist; *prefix; prefix += 2) { SANE_String dir_name = *prefix; SANE_String base_name = *(prefix + 1); struct stat stat_buf; DIR *dir; struct dirent *dir_entry; if (stat (dir_name, &stat_buf) < 0) { DBG (5, "%s: can't stat %s: %s\n", __func__, dir_name, strerror (errno)); continue; } if (!S_ISDIR (stat_buf.st_mode)) { DBG (5, "%s: %s is not a directory\n", __func__, dir_name); continue; } if ((dir = opendir (dir_name)) == 0) { DBG (5, "%s: cannot read directory %s: %s\n", __func__, dir_name, strerror (errno)); continue; } while ((dir_entry = readdir (dir)) != 0) { /* skip standard dir entries */ if (strcmp (dir_entry->d_name, ".") == 0 || strcmp (dir_entry->d_name, "..") == 0) continue; if (strncmp (base_name, dir_entry->d_name, strlen (base_name)) == 0) { if (strlen (dir_name) + strlen (dir_entry->d_name) + 1 > sizeof (devname)) continue; sprintf (devname, "%s%s", dir_name, dir_entry->d_name); fd = -1; #ifdef HAVE_RESMGR fd = rsm_open_device (devname, O_RDWR); #endif if (fd == -1) fd = open (devname, O_RDWR); if (fd < 0) { DBG (5, "%s: couldn't open %s: %s\n", __func__, devname, strerror (errno)); continue; } vendor = -1; product = -1; kernel_get_vendor_product (fd, devname, &vendor, &product); close (fd); memset (&device, 0, sizeof (device)); device.devname = strdup (devname); if (!device.devname) { closedir (dir); return; } device.vendor = vendor; device.product = product; device.method = sanei_usb_method_scanner_driver; DBG (4, "%s: found kernel scanner device (0x%04x/0x%04x) at %s\n", __func__, vendor, product, devname); store_device(device); } } closedir (dir); } } #endif /* !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) */ #ifdef HAVE_LIBUSB_LEGACY /** scan for devices using old libusb * Check for devices using 0.1.x libusb */ static void libusb_scan_devices(void) { struct usb_bus *bus; struct usb_device *dev; SANE_Char devname[1024]; device_list_type device; DBG (4, "%s: Looking for libusb devices\n", __func__); usb_find_busses (); usb_find_devices (); /* Check for the matching device */ for (bus = usb_get_busses (); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { int interface; SANE_Bool found = SANE_FALSE; if (!dev->config) { DBG (1, "%s: device 0x%04x/0x%04x is not configured\n", __func__, dev->descriptor.idVendor, dev->descriptor.idProduct); continue; } if (dev->descriptor.idVendor == 0 || dev->descriptor.idProduct == 0) { DBG (5, "%s: device 0x%04x/0x%04x looks like a root hub\n", __func__, dev->descriptor.idVendor, dev->descriptor.idProduct); continue; } for (interface = 0; interface < dev->config[0].bNumInterfaces && !found; interface++) { switch (dev->descriptor.bDeviceClass) { case USB_CLASS_VENDOR_SPEC: found = SANE_TRUE; break; case USB_CLASS_PER_INTERFACE: if (dev->config[0].interface[interface].num_altsetting == 0 || !dev->config[0].interface[interface].altsetting) { DBG (1, "%s: device 0x%04x/0x%04x doesn't " "have an altsetting for interface %d\n", __func__, dev->descriptor.idVendor, dev->descriptor.idProduct, interface); continue; } switch (dev->config[0].interface[interface].altsetting[0]. bInterfaceClass) { case USB_CLASS_VENDOR_SPEC: case USB_CLASS_PER_INTERFACE: case 6: /* imaging? */ case 16: /* data? */ found = SANE_TRUE; break; } break; } if (!found) DBG (5, "%s: device 0x%04x/0x%04x, interface %d " "doesn't look like a " "scanner (%d/%d)\n", __func__, dev->descriptor.idVendor, dev->descriptor.idProduct, interface, dev->descriptor.bDeviceClass, dev->config[0].interface[interface].num_altsetting != 0 ? dev->config[0].interface[interface].altsetting[0]. bInterfaceClass : -1); } interface--; if (!found) { DBG (5, "%s: device 0x%04x/0x%04x: no suitable interfaces\n", __func__, dev->descriptor.idVendor, dev->descriptor.idProduct); continue; } memset (&device, 0, sizeof (device)); device.libusb_device = dev; snprintf (devname, sizeof (devname), "libusb:%s:%s", dev->bus->dirname, dev->filename); device.devname = strdup (devname); if (!device.devname) return; device.vendor = dev->descriptor.idVendor; device.product = dev->descriptor.idProduct; device.method = sanei_usb_method_libusb; device.interface_nr = interface; device.alt_setting = 0; DBG (4, "%s: found libusb device (0x%04x/0x%04x) interface " "%d at %s\n", __func__, dev->descriptor.idVendor, dev->descriptor.idProduct, interface, devname); store_device(device); } } } #endif /* HAVE_LIBUSB_LEGACY */ #ifdef HAVE_LIBUSB /** scan for devices using libusb * Check for devices using libusb-1.0 */ static void libusb_scan_devices(void) { device_list_type device; SANE_Char devname[1024]; libusb_device **devlist; ssize_t ndev; libusb_device *dev; libusb_device_handle *hdl; struct libusb_device_descriptor desc; struct libusb_config_descriptor *config0; unsigned short vid, pid; unsigned char busno, address; int config; int interface; int ret; int i; DBG (4, "%s: Looking for libusb-1.0 devices\n", __func__); ndev = libusb_get_device_list (sanei_usb_ctx, &devlist); if (ndev < 0) { DBG (1, "%s: failed to get libusb-1.0 device list, error %d\n", __func__, (int) ndev); return; } for (i = 0; i < ndev; i++) { SANE_Bool found = SANE_FALSE; dev = devlist[i]; busno = libusb_get_bus_number (dev); address = libusb_get_device_address (dev); ret = libusb_get_device_descriptor (dev, &desc); if (ret < 0) { DBG (1, "%s: could not get device descriptor for device at %03d:%03d (err %d)\n", __func__, busno, address, ret); continue; } vid = desc.idVendor; pid = desc.idProduct; if ((vid == 0) || (pid == 0)) { DBG (5, "%s: device 0x%04x/0x%04x at %03d:%03d looks like a root hub\n", __func__, vid, pid, busno, address); continue; } ret = libusb_open (dev, &hdl); if (ret < 0) { DBG (1, "%s: skipping device 0x%04x/0x%04x at %03d:%03d: cannot open: %s\n", __func__, vid, pid, busno, address, sanei_libusb_strerror (ret)); continue; } ret = libusb_get_configuration (hdl, &config); libusb_close (hdl); if (ret < 0) { DBG (1, "%s: could not get configuration for device 0x%04x/0x%04x at %03d:%03d (err %d)\n", __func__, vid, pid, busno, address, ret); continue; } if (config == 0) { DBG (1, "%s: device 0x%04x/0x%04x at %03d:%03d is not configured\n", __func__, vid, pid, busno, address); continue; } ret = libusb_get_config_descriptor (dev, 0, &config0); if (ret < 0) { DBG (1, "%s: could not get config[0] descriptor for device 0x%04x/0x%04x at %03d:%03d (err %d)\n", __func__, vid, pid, busno, address, ret); continue; } for (interface = 0; (interface < config0->bNumInterfaces) && !found; interface++) { switch (desc.bDeviceClass) { case LIBUSB_CLASS_VENDOR_SPEC: found = SANE_TRUE; break; case LIBUSB_CLASS_PER_INTERFACE: if ((config0->interface[interface].num_altsetting == 0) || !config0->interface[interface].altsetting) { DBG (1, "%s: device 0x%04x/0x%04x doesn't " "have an altsetting for interface %d\n", __func__, vid, pid, interface); continue; } switch (config0->interface[interface].altsetting[0].bInterfaceClass) { case LIBUSB_CLASS_VENDOR_SPEC: case LIBUSB_CLASS_PER_INTERFACE: case LIBUSB_CLASS_PTP: case 16: /* data? */ found = SANE_TRUE; break; } break; } if (!found) DBG (5, "%s: device 0x%04x/0x%04x, interface %d " "doesn't look like a scanner (%d/%d)\n", __func__, vid, pid, interface, desc.bDeviceClass, (config0->interface[interface].num_altsetting != 0) ? config0->interface[interface].altsetting[0].bInterfaceClass : -1); } libusb_free_config_descriptor (config0); interface--; if (!found) { DBG (5, "%s: device 0x%04x/0x%04x at %03d:%03d: no suitable interfaces\n", __func__, vid, pid, busno, address); continue; } memset (&device, 0, sizeof (device)); device.lu_device = libusb_ref_device(dev); snprintf (devname, sizeof (devname), "libusb:%03d:%03d", busno, address); device.devname = strdup (devname); if (!device.devname) return; device.vendor = vid; device.product = pid; device.method = sanei_usb_method_libusb; device.interface_nr = interface; device.alt_setting = 0; DBG (4, "%s: found libusb-1.0 device (0x%04x/0x%04x) interface " "%d at %s\n", __func__, vid, pid, interface, devname); store_device (device); } libusb_free_device_list (devlist, 1); } #endif /* HAVE_LIBUSB */ void sanei_usb_scan_devices (void) { int count; int i; /* check USB has been initialized first */ if(initialized==0) { DBG (1, "%s: sanei_usb is not initialized!\n", __func__); return; } /* we mark all already detected devices as missing */ /* each scan method will reset this value to 0 (not missing) * when storing the device */ DBG (4, "%s: marking existing devices\n", __func__); for (i = 0; i < device_number; i++) { devices[i].missing++; } /* Check for devices using the kernel scanner driver */ #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) kernel_scan_devices(); #endif #if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) /* Check for devices using libusb (old or new)*/ libusb_scan_devices(); #endif #ifdef HAVE_USBCALLS /* Check for devices using OS/2 USBCALLS Interface */ usbcall_scan_devices(); #endif /* display found devices */ if (debug_level > 5) { count=0; for (i = 0; i < device_number; i++) { if(!devices[i].missing) { count++; DBG (6, "%s: device %02d is %s\n", __func__, i, devices[i].devname); } } DBG (5, "%s: found %d devices\n", __func__, count); } } /* This logically belongs to sanei_config.c but not every backend that uses sanei_config() wants to depend on sanei_usb. */ void sanei_usb_attach_matching_devices (const char *name, SANE_Status (*attach) (const char *dev)) { char *vendor, *product; if (strncmp (name, "usb", 3) == 0) { SANE_Word vendorID = 0, productID = 0; name += 3; name = sanei_config_skip_whitespace (name); if (*name) { name = sanei_config_get_string (name, &vendor); if (vendor) { vendorID = strtol (vendor, 0, 0); free (vendor); } name = sanei_config_skip_whitespace (name); } name = sanei_config_skip_whitespace (name); if (*name) { name = sanei_config_get_string (name, &product); if (product) { productID = strtol (product, 0, 0); free (product); } } sanei_usb_find_devices (vendorID, productID, attach); } else (*attach) (name); } SANE_Status sanei_usb_get_vendor_product_byname (SANE_String_Const devname, SANE_Word * vendor, SANE_Word * product) { int i; SANE_Bool found = SANE_FALSE; for (i = 0; i < device_number && devices[i].devname; i++) { if (!devices[i].missing && strcmp (devices[i].devname, devname) == 0) { found = SANE_TRUE; break; } } if (!found) { DBG (1, "sanei_usb_get_vendor_product_byname: can't find device `%s' in list\n", devname); return SANE_STATUS_INVAL; } if ((devices[i].vendor == 0) && (devices[i].product == 0)) { DBG (1, "sanei_usb_get_vendor_product_byname: not support for this method\n"); return SANE_STATUS_UNSUPPORTED; } if (vendor) *vendor = devices[i].vendor; if (product) *product = devices[i].product; return SANE_STATUS_GOOD; } SANE_Status sanei_usb_get_vendor_product (SANE_Int dn, SANE_Word * vendor, SANE_Word * product) { SANE_Word vendorID = 0; SANE_Word productID = 0; if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_get_vendor_product: dn >= device number || dn < 0\n"); return SANE_STATUS_INVAL; } if (devices[dn].missing >= 1) { DBG (1, "sanei_usb_get_vendor_product: dn=%d is missing!\n",dn); return SANE_STATUS_INVAL; } /* kernel, usbcal and libusb methods store these when device scanning * is done, so we can use them directly */ vendorID = devices[dn].vendor; productID = devices[dn].product; if (vendor) *vendor = vendorID; if (product) *product = productID; if (!vendorID || !productID) { DBG (3, "sanei_usb_get_vendor_product: device %d: Your OS doesn't " "seem to support detection of vendor+product ids\n", dn); return SANE_STATUS_UNSUPPORTED; } else { DBG (3, "sanei_usb_get_vendor_product: device %d: vendorID: 0x%04x, " "productID: 0x%04x\n", dn, vendorID, productID); return SANE_STATUS_GOOD; } } SANE_Status sanei_usb_find_devices (SANE_Int vendor, SANE_Int product, SANE_Status (*attach) (SANE_String_Const dev)) { SANE_Int dn = 0; DBG (3, "sanei_usb_find_devices: vendor=0x%04x, product=0x%04x\n", vendor, product); while (devices[dn].devname && dn < device_number) { if (devices[dn].vendor == vendor && devices[dn].product == product && !devices[dn].missing && attach) attach (devices[dn].devname); dn++; } return SANE_STATUS_GOOD; } void sanei_usb_set_endpoint (SANE_Int dn, SANE_Int ep_type, SANE_Int ep) { if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_set_endpoint: dn >= device number || dn < 0\n"); return; } DBG (5, "sanei_usb_set_endpoint: Setting endpoint of type 0x%02x to 0x%02x\n", ep_type, ep); switch (ep_type) { case USB_DIR_IN|USB_ENDPOINT_TYPE_BULK: devices[dn].bulk_in_ep = ep; break; case USB_DIR_OUT|USB_ENDPOINT_TYPE_BULK: devices[dn].bulk_out_ep = ep; break; case USB_DIR_IN|USB_ENDPOINT_TYPE_ISOCHRONOUS: devices[dn].iso_in_ep = ep; break; case USB_DIR_OUT|USB_ENDPOINT_TYPE_ISOCHRONOUS: devices[dn].iso_out_ep = ep; break; case USB_DIR_IN|USB_ENDPOINT_TYPE_INTERRUPT: devices[dn].int_in_ep = ep; break; case USB_DIR_OUT|USB_ENDPOINT_TYPE_INTERRUPT: devices[dn].int_out_ep = ep; break; case USB_DIR_IN|USB_ENDPOINT_TYPE_CONTROL: devices[dn].control_in_ep = ep; break; case USB_DIR_OUT|USB_ENDPOINT_TYPE_CONTROL: devices[dn].control_out_ep = ep; break; } } SANE_Int sanei_usb_get_endpoint (SANE_Int dn, SANE_Int ep_type) { if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_get_endpoint: dn >= device number || dn < 0\n"); return 0; } switch (ep_type) { case USB_DIR_IN|USB_ENDPOINT_TYPE_BULK: return devices[dn].bulk_in_ep; case USB_DIR_OUT|USB_ENDPOINT_TYPE_BULK: return devices[dn].bulk_out_ep; case USB_DIR_IN|USB_ENDPOINT_TYPE_ISOCHRONOUS: return devices[dn].iso_in_ep; case USB_DIR_OUT|USB_ENDPOINT_TYPE_ISOCHRONOUS: return devices[dn].iso_out_ep; case USB_DIR_IN|USB_ENDPOINT_TYPE_INTERRUPT: return devices[dn].int_in_ep; case USB_DIR_OUT|USB_ENDPOINT_TYPE_INTERRUPT: return devices[dn].int_out_ep; case USB_DIR_IN|USB_ENDPOINT_TYPE_CONTROL: return devices[dn].control_in_ep; case USB_DIR_OUT|USB_ENDPOINT_TYPE_CONTROL: return devices[dn].control_out_ep; default: return 0; } } SANE_Status sanei_usb_open (SANE_String_Const devname, SANE_Int * dn) { int devcount; SANE_Bool found = SANE_FALSE; DBG (5, "sanei_usb_open: trying to open device `%s'\n", devname); if (!dn) { DBG (1, "sanei_usb_open: can't open `%s': dn == NULL\n", devname); return SANE_STATUS_INVAL; } for (devcount = 0; devcount < device_number && devices[devcount].devname != 0; devcount++) { if (!devices[devcount].missing && strcmp (devices[devcount].devname, devname) == 0) { if (devices[devcount].open) { DBG (1, "sanei_usb_open: device `%s' already open\n", devname); return SANE_STATUS_INVAL; } found = SANE_TRUE; break; } } if (!found) { DBG (1, "sanei_usb_open: can't find device `%s' in list\n", devname); return SANE_STATUS_INVAL; } if (devices[devcount].method == sanei_usb_method_libusb) { #ifdef HAVE_LIBUSB_LEGACY struct usb_device *dev; struct usb_interface_descriptor *interface; int result, num; int c, i, a; devices[devcount].libusb_handle = usb_open (devices[devcount].libusb_device); if (!devices[devcount].libusb_handle) { SANE_Status status = SANE_STATUS_INVAL; DBG (1, "sanei_usb_open: can't open device `%s': %s\n", devname, strerror (errno)); if (errno == EPERM || errno == EACCES) { DBG (1, "Make sure you run as root or set appropriate " "permissions\n"); status = SANE_STATUS_ACCESS_DENIED; } else if (errno == EBUSY) { DBG (1, "Maybe the kernel scanner driver claims the " "scanner's interface?\n"); status = SANE_STATUS_DEVICE_BUSY; } return status; } dev = usb_device (devices[devcount].libusb_handle); /* Set the configuration */ if (!dev->config) { DBG (1, "sanei_usb_open: device `%s' not configured?\n", devname); return SANE_STATUS_INVAL; } if (dev->descriptor.bNumConfigurations > 1) { DBG (3, "sanei_usb_open: more than one " "configuration (%d), choosing first config (%d)\n", dev->descriptor.bNumConfigurations, dev->config[0].bConfigurationValue); result = usb_set_configuration (devices[devcount].libusb_handle, dev->config[0].bConfigurationValue); if (result < 0) { SANE_Status status = SANE_STATUS_INVAL; DBG (1, "sanei_usb_open: libusb complained: %s\n", usb_strerror ()); if (errno == EPERM || errno == EACCES) { DBG (1, "Make sure you run as root or set appropriate " "permissions\n"); status = SANE_STATUS_ACCESS_DENIED; } else if (errno == EBUSY) { DBG (3, "Maybe the kernel scanner driver or usblp claims the " "interface? Ignoring this error...\n"); status = SANE_STATUS_GOOD; } if (status != SANE_STATUS_GOOD) { usb_close (devices[devcount].libusb_handle); return status; } } } /* Claim the interface */ result = usb_claim_interface (devices[devcount].libusb_handle, devices[devcount].interface_nr); if (result < 0) { SANE_Status status = SANE_STATUS_INVAL; DBG (1, "sanei_usb_open: libusb complained: %s\n", usb_strerror ()); if (errno == EPERM || errno == EACCES) { DBG (1, "Make sure you run as root or set appropriate " "permissions\n"); status = SANE_STATUS_ACCESS_DENIED; } else if (errno == EBUSY) { DBG (1, "Maybe the kernel scanner driver claims the " "scanner's interface?\n"); status = SANE_STATUS_DEVICE_BUSY; } usb_close (devices[devcount].libusb_handle); return status; } /* Loop through all of the configurations */ for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { /* Loop through all of the interfaces */ for (i = 0; i < dev->config[c].bNumInterfaces; i++) { /* Loop through all of the alternate settings */ for (a = 0; a < dev->config[c].interface[i].num_altsetting; a++) { DBG (5, "sanei_usb_open: configuration nr: %d\n", c); DBG (5, "sanei_usb_open: interface nr: %d\n", i); DBG (5, "sanei_usb_open: alt_setting nr: %d\n", a); /* Start by interfaces found in sanei_usb_init */ if (c == 0 && i != devices[devcount].interface_nr) { DBG (5, "sanei_usb_open: interface %d not detected as " "a scanner by sanei_usb_init, ignoring.\n", i); continue; } interface = &dev->config[c].interface[i].altsetting[a]; /* Now we look for usable endpoints */ for (num = 0; num < interface->bNumEndpoints; num++) { struct usb_endpoint_descriptor *endpoint; int address, direction, transfer_type; endpoint = &interface->endpoint[num]; DBG (5, "sanei_usb_open: endpoint nr: %d\n", num); transfer_type = endpoint->bmAttributes & USB_ENDPOINT_TYPE_MASK; address = endpoint-> bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK; direction = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK; DBG (5, "sanei_usb_open: direction: %d\n", direction); DBG (5, "sanei_usb_open: address: %d transfertype: %d\n", address, transfer_type); /* save the endpoints we need later */ if (transfer_type == USB_ENDPOINT_TYPE_INTERRUPT) { DBG (5, "sanei_usb_open: found interrupt-%s endpoint (address 0x%02x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].int_in_ep) DBG (3, "sanei_usb_open: we already have a int-in endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].int_in_ep); else devices[devcount].int_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].int_out_ep) DBG (3, "sanei_usb_open: we already have a int-out endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].int_out_ep); else devices[devcount].int_out_ep = endpoint->bEndpointAddress; } } else if (transfer_type == USB_ENDPOINT_TYPE_BULK) { DBG (5, "sanei_usb_open: found bulk-%s endpoint (address 0x%02x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].bulk_in_ep) DBG (3, "sanei_usb_open: we already have a bulk-in endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].bulk_in_ep); else devices[devcount].bulk_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].bulk_out_ep) DBG (3, "sanei_usb_open: we already have a bulk-out endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].bulk_out_ep); else devices[devcount].bulk_out_ep = endpoint->bEndpointAddress; } } else if (transfer_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) { DBG (5, "sanei_usb_open: found isochronous-%s endpoint (address 0x%02x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].iso_in_ep) DBG (3, "sanei_usb_open: we already have a isochronous-in endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].iso_in_ep); else devices[devcount].iso_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].iso_out_ep) DBG (3, "sanei_usb_open: we already have a isochronous-out endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].iso_out_ep); else devices[devcount].iso_out_ep = endpoint->bEndpointAddress; } } else if (transfer_type == USB_ENDPOINT_TYPE_CONTROL) { DBG (5, "sanei_usb_open: found control-%s endpoint (address 0x%02x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].control_in_ep) DBG (3, "sanei_usb_open: we already have a control-in endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].control_in_ep); else devices[devcount].control_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].control_out_ep) DBG (3, "sanei_usb_open: we already have a control-out endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].control_out_ep); else devices[devcount].control_out_ep = endpoint->bEndpointAddress; } } } } } } #elif defined(HAVE_LIBUSB) /* libusb-1.0 */ int config; libusb_device *dev; struct libusb_device_descriptor desc; struct libusb_config_descriptor *config0; int result, num; int c, i, a; dev = devices[devcount].lu_device; result = libusb_open (dev, &devices[devcount].lu_handle); if (result < 0) { SANE_Status status = SANE_STATUS_INVAL; DBG (1, "sanei_usb_open: can't open device `%s': %s\n", devname, sanei_libusb_strerror (result)); if (result == LIBUSB_ERROR_ACCESS) { DBG (1, "Make sure you run as root or set appropriate " "permissions\n"); status = SANE_STATUS_ACCESS_DENIED; } else if (result == LIBUSB_ERROR_BUSY) { DBG (1, "Maybe the kernel scanner driver claims the " "scanner's interface?\n"); status = SANE_STATUS_DEVICE_BUSY; } else if (result == LIBUSB_ERROR_NO_MEM) { status = SANE_STATUS_NO_MEM; } return status; } result = libusb_get_configuration (devices[devcount].lu_handle, &config); if (result < 0) { DBG (1, "sanei_usb_open: could not get configuration for device `%s' (err %d)\n", devname, result); return SANE_STATUS_INVAL; } if (config == 0) { DBG (1, "sanei_usb_open: device `%s' not configured?\n", devname); return SANE_STATUS_INVAL; } result = libusb_get_device_descriptor (dev, &desc); if (result < 0) { DBG (1, "sanei_usb_open: could not get device descriptor for device `%s' (err %d)\n", devname, result); return SANE_STATUS_INVAL; } result = libusb_get_config_descriptor (dev, 0, &config0); if (result < 0) { DBG (1, "sanei_usb_open: could not get config[0] descriptor for device `%s' (err %d)\n", devname, result); return SANE_STATUS_INVAL; } /* Set the configuration */ if (desc.bNumConfigurations > 1) { DBG (3, "sanei_usb_open: more than one " "configuration (%d), choosing first config (%d)\n", desc.bNumConfigurations, config0->bConfigurationValue); result = 0; if (config != config0->bConfigurationValue) result = libusb_set_configuration (devices[devcount].lu_handle, config0->bConfigurationValue); if (result < 0) { SANE_Status status = SANE_STATUS_INVAL; DBG (1, "sanei_usb_open: libusb complained: %s\n", sanei_libusb_strerror (result)); if (result == LIBUSB_ERROR_ACCESS) { DBG (1, "Make sure you run as root or set appropriate " "permissions\n"); status = SANE_STATUS_ACCESS_DENIED; } else if (result == LIBUSB_ERROR_BUSY) { DBG (3, "Maybe the kernel scanner driver or usblp claims " "the interface? Ignoring this error...\n"); status = SANE_STATUS_GOOD; } if (status != SANE_STATUS_GOOD) { libusb_close (devices[devcount].lu_handle); libusb_free_config_descriptor (config0); return status; } } } libusb_free_config_descriptor (config0); /* Claim the interface */ result = libusb_claim_interface (devices[devcount].lu_handle, devices[devcount].interface_nr); if (result < 0) { SANE_Status status = SANE_STATUS_INVAL; DBG (1, "sanei_usb_open: libusb complained: %s\n", sanei_libusb_strerror (result)); if (result == LIBUSB_ERROR_ACCESS) { DBG (1, "Make sure you run as root or set appropriate " "permissions\n"); status = SANE_STATUS_ACCESS_DENIED; } else if (result == LIBUSB_ERROR_BUSY) { DBG (1, "Maybe the kernel scanner driver claims the " "scanner's interface?\n"); status = SANE_STATUS_DEVICE_BUSY; } libusb_close (devices[devcount].lu_handle); return status; } /* Loop through all of the configurations */ for (c = 0; c < desc.bNumConfigurations; c++) { struct libusb_config_descriptor *config; result = libusb_get_config_descriptor (dev, c, &config); if (result < 0) { DBG (1, "sanei_usb_open: could not get config[%d] descriptor for device `%s' (err %d)\n", c, devname, result); continue; } /* Loop through all of the interfaces */ for (i = 0; i < config->bNumInterfaces; i++) { /* Loop through all of the alternate settings */ for (a = 0; a < config->interface[i].num_altsetting; a++) { const struct libusb_interface_descriptor *interface; DBG (5, "sanei_usb_open: configuration nr: %d\n", c); DBG (5, "sanei_usb_open: interface nr: %d\n", i); DBG (5, "sanei_usb_open: alt_setting nr: %d\n", a); /* Start by interfaces found in sanei_usb_init */ if (c == 0 && i != devices[devcount].interface_nr) { DBG (5, "sanei_usb_open: interface %d not detected as " "a scanner by sanei_usb_init, ignoring.\n", i); continue; } interface = &config->interface[i].altsetting[a]; /* Now we look for usable endpoints */ for (num = 0; num < interface->bNumEndpoints; num++) { const struct libusb_endpoint_descriptor *endpoint; int address, direction, transfer_type; endpoint = &interface->endpoint[num]; DBG (5, "sanei_usb_open: endpoint nr: %d\n", num); transfer_type = endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK; address = endpoint->bEndpointAddress & LIBUSB_ENDPOINT_ADDRESS_MASK; direction = endpoint->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK; DBG (5, "sanei_usb_open: direction: %d\n", direction); DBG (5, "sanei_usb_open: address: %d transfertype: %d\n", address, transfer_type); /* save the endpoints we need later */ if (transfer_type == LIBUSB_TRANSFER_TYPE_INTERRUPT) { DBG (5, "sanei_usb_open: found interrupt-%s endpoint (address 0x%02x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].int_in_ep) DBG (3, "sanei_usb_open: we already have a int-in endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].int_in_ep); else devices[devcount].int_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].int_out_ep) DBG (3, "sanei_usb_open: we already have a int-out endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].int_out_ep); else devices[devcount].int_out_ep = endpoint->bEndpointAddress; } } else if (transfer_type == LIBUSB_TRANSFER_TYPE_BULK) { DBG (5, "sanei_usb_open: found bulk-%s endpoint (address 0x%02x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].bulk_in_ep) DBG (3, "sanei_usb_open: we already have a bulk-in endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].bulk_in_ep); else devices[devcount].bulk_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].bulk_out_ep) DBG (3, "sanei_usb_open: we already have a bulk-out endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].bulk_out_ep); else devices[devcount].bulk_out_ep = endpoint->bEndpointAddress; } } else if (transfer_type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) { DBG (5, "sanei_usb_open: found isochronous-%s endpoint (address 0x%02x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].iso_in_ep) DBG (3, "sanei_usb_open: we already have a isochronous-in endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].iso_in_ep); else devices[devcount].iso_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].iso_out_ep) DBG (3, "sanei_usb_open: we already have a isochronous-out endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].iso_out_ep); else devices[devcount].iso_out_ep = endpoint->bEndpointAddress; } } else if (transfer_type == LIBUSB_TRANSFER_TYPE_CONTROL) { DBG (5, "sanei_usb_open: found control-%s endpoint (address 0x%02x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].control_in_ep) DBG (3, "sanei_usb_open: we already have a control-in endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].control_in_ep); else devices[devcount].control_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].control_out_ep) DBG (3, "sanei_usb_open: we already have a control-out endpoint " "(address: 0x%02x), ignoring the new one\n", devices[devcount].control_out_ep); else devices[devcount].control_out_ep = endpoint->bEndpointAddress; } } } } } libusb_free_config_descriptor (config); } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ DBG (1, "sanei_usb_open: can't open device `%s': " "libusb support missing\n", devname); return SANE_STATUS_UNSUPPORTED; #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ } else if (devices[devcount].method == sanei_usb_method_scanner_driver) { #ifdef FD_CLOEXEC long int flag; #endif /* Using kernel scanner driver */ devices[devcount].fd = -1; #ifdef HAVE_RESMGR devices[devcount].fd = rsm_open_device (devname, O_RDWR); #endif if (devices[devcount].fd == -1) devices[devcount].fd = open (devname, O_RDWR); if (devices[devcount].fd < 0) { SANE_Status status = SANE_STATUS_INVAL; if (errno == EACCES) status = SANE_STATUS_ACCESS_DENIED; else if (errno == ENOENT) { DBG (5, "sanei_usb_open: open of `%s' failed: %s\n", devname, strerror (errno)); return status; } DBG (1, "sanei_usb_open: open of `%s' failed: %s\n", devname, strerror (errno)); return status; } #ifdef FD_CLOEXEC flag = fcntl (devices[devcount].fd, F_GETFD); if (flag >= 0) { if (fcntl (devices[devcount].fd, F_SETFD, flag | FD_CLOEXEC) < 0) DBG (1, "sanei_usb_open: fcntl of `%s' failed: %s\n", devname, strerror (errno)); } #endif } else if (devices[devcount].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS CHAR ucData[2048]; struct usb_device_descriptor *pDevDesc; struct usb_config_descriptor *pCfgDesc; struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_descriptor_header *pDescHead; ULONG ulBufLen; ulBufLen = sizeof(ucData); memset(&ucData,0,sizeof(ucData)); int result, rc; int address, direction, transfer_type; DBG (5, "devname = %s, devcount = %d\n",devices[devcount].devname,devcount); DBG (5, "USBCalls device number to open = %d\n",devices[devcount].fd); DBG (5, "USBCalls Vendor/Product to open = 0x%04x/0x%04x\n", devices[devcount].vendor,devices[devcount].product); rc = UsbOpen (&dh, devices[devcount].vendor, devices[devcount].product, USB_ANY_PRODUCTVERSION, USB_OPEN_FIRST_UNUSED); DBG (1, "sanei_usb_open: UsbOpen rc = %d\n",rc); if (rc!=0) { SANE_Status status = SANE_STATUS_INVAL; DBG (1, "sanei_usb_open: can't open device `%s': %s\n", devname, strerror (rc)); return status; } rc = UsbQueryDeviceReport( devices[devcount].fd, &ulBufLen, ucData); DBG (1, "sanei_usb_open: UsbQueryDeviceReport rc = %d\n",rc); pDevDesc = (struct usb_device_descriptor*)ucData; pCfgDesc = (struct usb_config_descriptor*) (ucData+sizeof(struct usb_device_descriptor)); UCHAR *pCurPtr = (UCHAR*) pCfgDesc; UCHAR *pEndPtr = pCurPtr+ pCfgDesc->wTotalLength; pDescHead = (struct usb_descriptor_header *) (pCurPtr+pCfgDesc->bLength); /* Set the configuration */ if (pDevDesc->bNumConfigurations > 1) { DBG (3, "sanei_usb_open: more than one " "configuration (%d), choosing first config (%d)\n", pDevDesc->bNumConfigurations, pCfgDesc->bConfigurationValue); } DBG (5, "UsbDeviceSetConfiguration parameters: dh = %p, bConfigurationValue = %d\n", dh,pCfgDesc->bConfigurationValue); result = UsbDeviceSetConfiguration (dh, pCfgDesc->bConfigurationValue); DBG (1, "sanei_usb_open: UsbDeviceSetConfiguration rc = %d\n",result); if (result) { DBG (1, "sanei_usb_open: usbcalls complained on UsbDeviceSetConfiguration, rc= %d\n", result); UsbClose (dh); return SANE_STATUS_ACCESS_DENIED; } /* Now we look for usable endpoints */ for (pDescHead = (struct usb_descriptor_header *) (pCurPtr+pCfgDesc->bLength); pDescHead;pDescHead = GetNextDescriptor(pDescHead,pEndPtr) ) { switch(pDescHead->bDescriptorType) { case USB_DT_INTERFACE: interface = (struct usb_interface_descriptor *) pDescHead; DBG (5, "Found %d endpoints\n",interface->bNumEndpoints); DBG (5, "bAlternateSetting = %d\n",interface->bAlternateSetting); break; case USB_DT_ENDPOINT: endpoint = (struct usb_endpoint_descriptor*)pDescHead; address = endpoint->bEndpointAddress; direction = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK; transfer_type = endpoint->bmAttributes & USB_ENDPOINT_TYPE_MASK; /* save the endpoints we need later */ if (transfer_type == USB_ENDPOINT_TYPE_INTERRUPT) { DBG (5, "sanei_usb_open: found interupt-%s endpoint (address %2x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].int_in_ep) DBG (3, "sanei_usb_open: we already have a int-in endpoint " "(address: %d), ignoring the new one\n", devices[devcount].int_in_ep); else devices[devcount].int_in_ep = endpoint->bEndpointAddress; } else if (devices[devcount].int_out_ep) DBG (3, "sanei_usb_open: we already have a int-out endpoint " "(address: %d), ignoring the new one\n", devices[devcount].int_out_ep); else devices[devcount].int_out_ep = endpoint->bEndpointAddress; } else if (transfer_type == USB_ENDPOINT_TYPE_BULK) { DBG (5, "sanei_usb_open: found bulk-%s endpoint (address %2x)\n", direction ? "in" : "out", address); if (direction) /* in */ { if (devices[devcount].bulk_in_ep) DBG (3, "sanei_usb_open: we already have a bulk-in endpoint " "(address: %d), ignoring the new one\n", devices[devcount].bulk_in_ep); else devices[devcount].bulk_in_ep = endpoint->bEndpointAddress; } else { if (devices[devcount].bulk_out_ep) DBG (3, "sanei_usb_open: we already have a bulk-out endpoint " "(address: %d), ignoring the new one\n", devices[devcount].bulk_out_ep); else devices[devcount].bulk_out_ep = endpoint->bEndpointAddress; } } /* ignore currently unsupported endpoints */ else { DBG (5, "sanei_usb_open: ignoring %s-%s endpoint " "(address: %d)\n", transfer_type == USB_ENDPOINT_TYPE_CONTROL ? "control" : transfer_type == USB_ENDPOINT_TYPE_ISOCHRONOUS ? "isochronous" : "interrupt", direction ? "in" : "out", address); continue; } break; } } #else DBG (1, "sanei_usb_open: can't open device `%s': " "usbcalls support missing\n", devname); return SANE_STATUS_UNSUPPORTED; #endif /* HAVE_USBCALLS */ } else { DBG (1, "sanei_usb_open: access method %d not implemented\n", devices[devcount].method); return SANE_STATUS_INVAL; } devices[devcount].open = SANE_TRUE; *dn = devcount; DBG (3, "sanei_usb_open: opened usb device `%s' (*dn=%d)\n", devname, devcount); return SANE_STATUS_GOOD; } void sanei_usb_close (SANE_Int dn) { char *env; int workaround = 0; DBG (5, "sanei_usb_close: evaluating environment variable SANE_USB_WORKAROUND\n"); env = getenv ("SANE_USB_WORKAROUND"); if (env) { workaround = atoi(env); DBG (5, "sanei_usb_close: workaround: %d\n", workaround); } DBG (5, "sanei_usb_close: closing device %d\n", dn); if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_close: dn >= device number || dn < 0\n"); return; } if (!devices[dn].open) { DBG (1, "sanei_usb_close: device %d already closed or never opened\n", dn); return; } if (devices[dn].method == sanei_usb_method_scanner_driver) close (devices[dn].fd); else if (devices[dn].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS int rc; rc=UsbClose (dh); DBG (5,"rc of UsbClose = %d\n",rc); #else DBG (1, "sanei_usb_close: usbcalls support missing\n"); #endif } else #ifdef HAVE_LIBUSB_LEGACY { /* This call seems to be required by Linux xhci driver * even though it should be a no-op. Without it, the * host or driver does not reset it's data toggle bit. * We intentionally ignore the return val */ if (workaround) { sanei_usb_set_altinterface (dn, devices[dn].alt_setting); } usb_release_interface (devices[dn].libusb_handle, devices[dn].interface_nr); usb_close (devices[dn].libusb_handle); } #elif defined(HAVE_LIBUSB) { /* This call seems to be required by Linux xhci driver * even though it should be a no-op. Without it, the * host or driver does not reset it's data toggle bit. * We intentionally ignore the return val */ if (workaround) { sanei_usb_set_altinterface (dn, devices[dn].alt_setting); } libusb_release_interface (devices[dn].lu_handle, devices[dn].interface_nr); libusb_close (devices[dn].lu_handle); } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ DBG (1, "sanei_usb_close: libusb support missing\n"); #endif devices[dn].open = SANE_FALSE; return; } void sanei_usb_set_timeout (SANE_Int __sane_unused__ timeout) { #if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) libusb_timeout = timeout; #else DBG (1, "sanei_usb_set_timeout: libusb support missing\n"); #endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ } SANE_Status sanei_usb_clear_halt (SANE_Int dn) { char *env; int workaround = 0; DBG (5, "sanei_usb_clear_halt: evaluating environment variable SANE_USB_WORKAROUND\n"); env = getenv ("SANE_USB_WORKAROUND"); if (env) { workaround = atoi(env); DBG (5, "sanei_usb_clear_halt: workaround: %d\n", workaround); } if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_clear_halt: dn >= device number || dn < 0\n"); return SANE_STATUS_INVAL; } #ifdef HAVE_LIBUSB_LEGACY int ret; /* This call seems to be required by Linux xhci driver * even though it should be a no-op. Without it, the * host or driver does not send the clear to the device. * We intentionally ignore the return val */ if (workaround) { sanei_usb_set_altinterface (dn, devices[dn].alt_setting); } ret = usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_in_ep); if (ret){ DBG (1, "sanei_usb_clear_halt: BULK_IN ret=%d\n", ret); return SANE_STATUS_INVAL; } ret = usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_out_ep); if (ret){ DBG (1, "sanei_usb_clear_halt: BULK_OUT ret=%d\n", ret); return SANE_STATUS_INVAL; } #elif defined(HAVE_LIBUSB) int ret; /* This call seems to be required by Linux xhci driver * even though it should be a no-op. Without it, the * host or driver does not send the clear to the device. * We intentionally ignore the return val */ if (workaround) { sanei_usb_set_altinterface (dn, devices[dn].alt_setting); } ret = libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_in_ep); if (ret){ DBG (1, "sanei_usb_clear_halt: BULK_IN ret=%d\n", ret); return SANE_STATUS_INVAL; } ret = libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_out_ep); if (ret){ DBG (1, "sanei_usb_clear_halt: BULK_OUT ret=%d\n", ret); return SANE_STATUS_INVAL; } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ DBG (1, "sanei_usb_clear_halt: libusb support missing\n"); #endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ return SANE_STATUS_GOOD; } SANE_Status sanei_usb_reset (SANE_Int __sane_unused__ dn) { #ifdef HAVE_LIBUSB_LEGACY int ret; ret = usb_reset (devices[dn].libusb_handle); if (ret){ DBG (1, "sanei_usb_reset: ret=%d\n", ret); return SANE_STATUS_INVAL; } #elif defined(HAVE_LIBUSB) int ret; ret = libusb_reset_device (devices[dn].lu_handle); if (ret){ DBG (1, "sanei_usb_reset: ret=%d\n", ret); return SANE_STATUS_INVAL; } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ DBG (1, "sanei_usb_reset: libusb support missing\n"); #endif /* HAVE_LIBUSB_LEGACY || HAVE_LIBUSB */ return SANE_STATUS_GOOD; } SANE_Status sanei_usb_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) { ssize_t read_size = 0; if (!size) { DBG (1, "sanei_usb_read_bulk: size == NULL\n"); return SANE_STATUS_INVAL; } if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_read_bulk: dn >= device number || dn < 0\n"); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_read_bulk: trying to read %lu bytes\n", (unsigned long) *size); if (devices[dn].method == sanei_usb_method_scanner_driver) { read_size = read (devices[dn].fd, buffer, *size); if (read_size < 0) DBG (1, "sanei_usb_read_bulk: read failed: %s\n", strerror (errno)); } else if (devices[dn].method == sanei_usb_method_libusb) #ifdef HAVE_LIBUSB_LEGACY { if (devices[dn].bulk_in_ep) { read_size = usb_bulk_read (devices[dn].libusb_handle, devices[dn].bulk_in_ep, (char *) buffer, (int) *size, libusb_timeout); if (read_size < 0) DBG (1, "sanei_usb_read_bulk: read failed: %s\n", strerror (errno)); } else { DBG (1, "sanei_usb_read_bulk: can't read without a bulk-in " "endpoint\n"); return SANE_STATUS_INVAL; } } #elif defined(HAVE_LIBUSB) { if (devices[dn].bulk_in_ep) { int ret, rsize; ret = libusb_bulk_transfer (devices[dn].lu_handle, devices[dn].bulk_in_ep, buffer, (int) *size, &rsize, libusb_timeout); if (ret < 0) { DBG (1, "sanei_usb_read_bulk: read failed: %s\n", sanei_libusb_strerror (ret)); read_size = -1; } else { read_size = rsize; } } else { DBG (1, "sanei_usb_read_bulk: can't read without a bulk-in " "endpoint\n"); return SANE_STATUS_INVAL; } } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ { DBG (1, "sanei_usb_read_bulk: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY */ else if (devices[dn].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS int rc; char* buffer_ptr = (char*) buffer; while (*size) { ULONG ulToRead = (*size>MAX_RW)?MAX_RW:*size; ULONG ulNum = ulToRead; DBG (5, "Entered usbcalls UsbBulkRead with dn = %d\n",dn); DBG (5, "Entered usbcalls UsbBulkRead with dh = %p\n",dh); DBG (5, "Entered usbcalls UsbBulkRead with bulk_in_ep = 0x%02x\n",devices[dn].bulk_in_ep); DBG (5, "Entered usbcalls UsbBulkRead with interface_nr = %d\n",devices[dn].interface_nr); DBG (5, "Entered usbcalls UsbBulkRead with usbcalls_timeout = %d\n",usbcalls_timeout); if (devices[dn].bulk_in_ep){ rc = UsbBulkRead (dh, devices[dn].bulk_in_ep, devices[dn].interface_nr, &ulToRead, buffer_ptr, usbcalls_timeout); DBG (1, "sanei_usb_read_bulk: rc = %d\n",rc);} else { DBG (1, "sanei_usb_read_bulk: can't read without a bulk-in endpoint\n"); return SANE_STATUS_INVAL; } if (rc || (ulNum!=ulToRead)) return SANE_STATUS_INVAL; *size -=ulToRead; buffer_ptr += ulToRead; read_size += ulToRead; } #else /* not HAVE_USBCALLS */ { DBG (1, "sanei_usb_read_bulk: usbcalls support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_USBCALLS */ } else { DBG (1, "sanei_usb_read_bulk: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_INVAL; } if (read_size < 0) { #ifdef HAVE_LIBUSB_LEGACY if (devices[dn].method == sanei_usb_method_libusb) usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_in_ep); #elif defined(HAVE_LIBUSB) if (devices[dn].method == sanei_usb_method_libusb) libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_in_ep); #endif *size = 0; return SANE_STATUS_IO_ERROR; } if (read_size == 0) { DBG (3, "sanei_usb_read_bulk: read returned EOF\n"); *size = 0; return SANE_STATUS_EOF; } if (debug_level > 10) print_buffer (buffer, read_size); DBG (5, "sanei_usb_read_bulk: wanted %lu bytes, got %ld bytes\n", (unsigned long) *size, (unsigned long) read_size); *size = read_size; return SANE_STATUS_GOOD; } SANE_Status sanei_usb_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) { ssize_t write_size = 0; if (!size) { DBG (1, "sanei_usb_write_bulk: size == NULL\n"); return SANE_STATUS_INVAL; } if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_write_bulk: dn >= device number || dn < 0\n"); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_write_bulk: trying to write %lu bytes\n", (unsigned long) *size); if (debug_level > 10) print_buffer (buffer, *size); if (devices[dn].method == sanei_usb_method_scanner_driver) { write_size = write (devices[dn].fd, buffer, *size); if (write_size < 0) DBG (1, "sanei_usb_write_bulk: write failed: %s\n", strerror (errno)); } else if (devices[dn].method == sanei_usb_method_libusb) #ifdef HAVE_LIBUSB_LEGACY { if (devices[dn].bulk_out_ep) { write_size = usb_bulk_write (devices[dn].libusb_handle, devices[dn].bulk_out_ep, (const char *) buffer, (int) *size, libusb_timeout); if (write_size < 0) DBG (1, "sanei_usb_write_bulk: write failed: %s\n", strerror (errno)); } else { DBG (1, "sanei_usb_write_bulk: can't write without a bulk-out " "endpoint\n"); return SANE_STATUS_INVAL; } } #elif defined(HAVE_LIBUSB) { if (devices[dn].bulk_out_ep) { int ret; int trans_bytes; ret = libusb_bulk_transfer (devices[dn].lu_handle, devices[dn].bulk_out_ep, (unsigned char *) buffer, (int) *size, &trans_bytes, libusb_timeout); if (ret < 0) { DBG (1, "sanei_usb_write_bulk: write failed: %s\n", sanei_libusb_strerror (ret)); write_size = -1; } else write_size = trans_bytes; } else { DBG (1, "sanei_usb_write_bulk: can't write without a bulk-out " "endpoint\n"); return SANE_STATUS_INVAL; } } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ { DBG (1, "sanei_usb_write_bulk: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ else if (devices[dn].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS int rc; DBG (5, "Entered usbcalls UsbBulkWrite with dn = %d\n",dn); DBG (5, "Entered usbcalls UsbBulkWrite with dh = %p\n",dh); DBG (5, "Entered usbcalls UsbBulkWrite with bulk_out_ep = 0x%02x\n",devices[dn].bulk_out_ep); DBG (5, "Entered usbcalls UsbBulkWrite with interface_nr = %d\n",devices[dn].interface_nr); DBG (5, "Entered usbcalls UsbBulkWrite with usbcalls_timeout = %d\n",usbcalls_timeout); while (*size) { ULONG ulToWrite = (*size>MAX_RW)?MAX_RW:*size; DBG (5, "size requested to write = %lu, ulToWrite = %lu\n",(unsigned long) *size,ulToWrite); if (devices[dn].bulk_out_ep){ rc = UsbBulkWrite (dh, devices[dn].bulk_out_ep, devices[dn].interface_nr, ulToWrite, (char*) buffer, usbcalls_timeout); DBG (1, "sanei_usb_write_bulk: rc = %d\n",rc); } else { DBG (1, "sanei_usb_write_bulk: can't read without a bulk-out endpoint\n"); return SANE_STATUS_INVAL; } if (rc) return SANE_STATUS_INVAL; *size -=ulToWrite; buffer += ulToWrite; write_size += ulToWrite; DBG (5, "size = %d, write_size = %d\n",*size, write_size); } #else /* not HAVE_USBCALLS */ { DBG (1, "sanei_usb_write_bulk: usbcalls support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_USBCALLS */ } else { DBG (1, "sanei_usb_write_bulk: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_INVAL; } if (write_size < 0) { *size = 0; #ifdef HAVE_LIBUSB_LEGACY if (devices[dn].method == sanei_usb_method_libusb) usb_clear_halt (devices[dn].libusb_handle, devices[dn].bulk_out_ep); #elif defined(HAVE_LIBUSB) if (devices[dn].method == sanei_usb_method_libusb) libusb_clear_halt (devices[dn].lu_handle, devices[dn].bulk_out_ep); #endif return SANE_STATUS_IO_ERROR; } DBG (5, "sanei_usb_write_bulk: wanted %lu bytes, wrote %ld bytes\n", (unsigned long) *size, (unsigned long) write_size); *size = write_size; return SANE_STATUS_GOOD; } SANE_Status sanei_usb_control_msg (SANE_Int dn, SANE_Int rtype, SANE_Int req, SANE_Int value, SANE_Int index, SANE_Int len, SANE_Byte * data) { if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_control_msg: dn >= device number || dn < 0, dn=%d\n", dn); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_control_msg: rtype = 0x%02x, req = %d, value = %d, " "index = %d, len = %d\n", rtype, req, value, index, len); if (!(rtype & 0x80) && debug_level > 10) print_buffer (data, len); if (devices[dn].method == sanei_usb_method_scanner_driver) { #if defined(__linux__) struct ctrlmsg_ioctl c; c.req.requesttype = rtype; c.req.request = req; c.req.value = value; c.req.index = index; c.req.length = len; c.data = data; if (ioctl (devices[dn].fd, SCANNER_IOCTL_CTRLMSG, &c) < 0) { DBG (5, "sanei_usb_control_msg: SCANNER_IOCTL_CTRLMSG error - %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if ((rtype & 0x80) && debug_level > 10) print_buffer (data, len); return SANE_STATUS_GOOD; #elif defined(__BEOS__) struct usb_scanner_ioctl_ctrlmsg c; c.req.request_type = rtype; c.req.request = req; c.req.value = value; c.req.index = index; c.req.length = len; c.data = data; if (ioctl (devices[dn].fd, B_SCANNER_IOCTL_CTRLMSG, &c) < 0) { DBG (5, "sanei_usb_control_msg: SCANNER_IOCTL_CTRLMSG error - %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if ((rtype & 0x80) && debug_level > 10) print_buffer (data, len); return SANE_STATUS_GOOD; #else /* not __linux__ */ DBG (5, "sanei_usb_control_msg: not supported on this OS\n"); return SANE_STATUS_UNSUPPORTED; #endif /* not __linux__ */ } else if (devices[dn].method == sanei_usb_method_libusb) #ifdef HAVE_LIBUSB_LEGACY { int result; result = usb_control_msg (devices[dn].libusb_handle, rtype, req, value, index, (char *) data, len, libusb_timeout); if (result < 0) { DBG (1, "sanei_usb_control_msg: libusb complained: %s\n", usb_strerror ()); return SANE_STATUS_INVAL; } if ((rtype & 0x80) && debug_level > 10) print_buffer (data, len); return SANE_STATUS_GOOD; } #elif defined(HAVE_LIBUSB) { int result; result = libusb_control_transfer (devices[dn].lu_handle, rtype, req, value, index, data, len, libusb_timeout); if (result < 0) { DBG (1, "sanei_usb_control_msg: libusb complained: %s\n", sanei_libusb_strerror (result)); return SANE_STATUS_INVAL; } if ((rtype & 0x80) && debug_level > 10) print_buffer (data, len); return SANE_STATUS_GOOD; } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB*/ { DBG (1, "sanei_usb_control_msg: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ else if (devices[dn].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS int result; result = UsbCtrlMessage (dh, rtype, req, value, index, len, (char *) data, usbcalls_timeout); DBG (5, "rc of usb_control_msg = %d\n",result); if (result < 0) { DBG (1, "sanei_usb_control_msg: usbcalls complained: %d\n",result); return SANE_STATUS_INVAL; } if ((rtype & 0x80) && debug_level > 10) print_buffer (data, len); return SANE_STATUS_GOOD; #else /* not HAVE_USBCALLS */ { DBG (1, "sanei_usb_control_msg: usbcalls support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_USBCALLS */ } else { DBG (1, "sanei_usb_control_msg: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_UNSUPPORTED; } } SANE_Status sanei_usb_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) { ssize_t read_size = 0; #if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) SANE_Bool stalled = SANE_FALSE; #endif if (!size) { DBG (1, "sanei_usb_read_int: size == NULL\n"); return SANE_STATUS_INVAL; } if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_read_int: dn >= device number || dn < 0\n"); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_read_int: trying to read %lu bytes\n", (unsigned long) *size); if (devices[dn].method == sanei_usb_method_scanner_driver) { DBG (1, "sanei_usb_read_int: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_INVAL; } else if (devices[dn].method == sanei_usb_method_libusb) #ifdef HAVE_LIBUSB_LEGACY { if (devices[dn].int_in_ep) { read_size = usb_interrupt_read (devices[dn].libusb_handle, devices[dn].int_in_ep, (char *) buffer, (int) *size, libusb_timeout); if (read_size < 0) DBG (1, "sanei_usb_read_int: read failed: %s\n", strerror (errno)); stalled = (read_size == -EPIPE); } else { DBG (1, "sanei_usb_read_int: can't read without an int " "endpoint\n"); return SANE_STATUS_INVAL; } } #elif defined(HAVE_LIBUSB) { if (devices[dn].int_in_ep) { int ret; int trans_bytes; ret = libusb_interrupt_transfer (devices[dn].lu_handle, devices[dn].int_in_ep, buffer, (int) *size, &trans_bytes, libusb_timeout); if (ret < 0) read_size = -1; else read_size = trans_bytes; stalled = (ret == LIBUSB_ERROR_PIPE); } else { DBG (1, "sanei_usb_read_int: can't read without an int " "endpoint\n"); return SANE_STATUS_INVAL; } } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ { DBG (1, "sanei_usb_read_int: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ else if (devices[dn].method == sanei_usb_method_usbcalls) { #ifdef HAVE_USBCALLS int rc; USHORT usNumBytes=*size; DBG (5, "Entered usbcalls UsbIrqStart with dn = %d\n",dn); DBG (5, "Entered usbcalls UsbIrqStart with dh = %p\n",dh); DBG (5, "Entered usbcalls UsbIrqStart with int_in_ep = 0x%02x\n",devices[dn].int_in_ep); DBG (5, "Entered usbcalls UsbIrqStart with interface_nr = %d\n",devices[dn].interface_nr); DBG (5, "Entered usbcalls UsbIrqStart with bytes to read = %u\n",usNumBytes); if (devices[dn].int_in_ep){ rc = UsbIrqStart (dh,devices[dn].int_in_ep,devices[dn].interface_nr, usNumBytes, (char *) buffer, pUsbIrqStartHev); DBG (5, "rc of UsbIrqStart = %d\n",rc); } else { DBG (1, "sanei_usb_read_int: can't read without an int " "endpoint\n"); return SANE_STATUS_INVAL; } if (rc) return SANE_STATUS_INVAL; read_size += usNumBytes; #else DBG (1, "sanei_usb_read_int: usbcalls support missing\n"); return SANE_STATUS_UNSUPPORTED; #endif /* HAVE_USBCALLS */ } else { DBG (1, "sanei_usb_read_int: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_INVAL; } if (read_size < 0) { #ifdef HAVE_LIBUSB_LEGACY if (devices[dn].method == sanei_usb_method_libusb) if (stalled) usb_clear_halt (devices[dn].libusb_handle, devices[dn].int_in_ep); #elif defined(HAVE_LIBUSB) if (devices[dn].method == sanei_usb_method_libusb) if (stalled) libusb_clear_halt (devices[dn].lu_handle, devices[dn].int_in_ep); #endif *size = 0; return SANE_STATUS_IO_ERROR; } if (read_size == 0) { DBG (3, "sanei_usb_read_int: read returned EOF\n"); *size = 0; return SANE_STATUS_EOF; } DBG (5, "sanei_usb_read_int: wanted %lu bytes, got %ld bytes\n", (unsigned long) *size, (unsigned long) read_size); *size = read_size; if (debug_level > 10) print_buffer (buffer, read_size); return SANE_STATUS_GOOD; } SANE_Status sanei_usb_set_configuration (SANE_Int dn, SANE_Int configuration) { if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_set_configuration: dn >= device number || dn < 0, dn=%d\n", dn); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_set_configuration: configuration = %d\n", configuration); if (devices[dn].method == sanei_usb_method_scanner_driver) { #if defined(__linux__) return SANE_STATUS_GOOD; #else /* not __linux__ */ DBG (5, "sanei_usb_set_configuration: not supported on this OS\n"); return SANE_STATUS_UNSUPPORTED; #endif /* not __linux__ */ } else if (devices[dn].method == sanei_usb_method_libusb) #ifdef HAVE_LIBUSB_LEGACY { int result; result = usb_set_configuration (devices[dn].libusb_handle, configuration); if (result < 0) { DBG (1, "sanei_usb_set_configuration: libusb complained: %s\n", usb_strerror ()); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #elif defined(HAVE_LIBUSB) { int result; result = libusb_set_configuration (devices[dn].lu_handle, configuration); if (result < 0) { DBG (1, "sanei_usb_set_configuration: libusb complained: %s\n", sanei_libusb_strerror (result)); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ { DBG (1, "sanei_usb_set_configuration: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ else { DBG (1, "sanei_usb_set_configuration: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_UNSUPPORTED; } } SANE_Status sanei_usb_claim_interface (SANE_Int dn, SANE_Int interface_number) { if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_claim_interface: dn >= device number || dn < 0, dn=%d\n", dn); return SANE_STATUS_INVAL; } if (devices[dn].missing) { DBG (1, "sanei_usb_claim_interface: device dn=%d is missing\n", dn); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_claim_interface: interface_number = %d\n", interface_number); if (devices[dn].method == sanei_usb_method_scanner_driver) { #if defined(__linux__) return SANE_STATUS_GOOD; #else /* not __linux__ */ DBG (5, "sanei_usb_claim_interface: not supported on this OS\n"); return SANE_STATUS_UNSUPPORTED; #endif /* not __linux__ */ } else if (devices[dn].method == sanei_usb_method_libusb) #ifdef HAVE_LIBUSB_LEGACY { int result; result = usb_claim_interface (devices[dn].libusb_handle, interface_number); if (result < 0) { DBG (1, "sanei_usb_claim_interface: libusb complained: %s\n", usb_strerror ()); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #elif defined(HAVE_LIBUSB) { int result; result = libusb_claim_interface (devices[dn].lu_handle, interface_number); if (result < 0) { DBG (1, "sanei_usb_claim_interface: libusb complained: %s\n", sanei_libusb_strerror (result)); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ { DBG (1, "sanei_usb_claim_interface: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ else { DBG (1, "sanei_usb_claim_interface: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_UNSUPPORTED; } } SANE_Status sanei_usb_release_interface (SANE_Int dn, SANE_Int interface_number) { if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_release_interface: dn >= device number || dn < 0, dn=%d\n", dn); return SANE_STATUS_INVAL; } if (devices[dn].missing) { DBG (1, "sanei_usb_release_interface: device dn=%d is missing\n", dn); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_release_interface: interface_number = %d\n", interface_number); if (devices[dn].method == sanei_usb_method_scanner_driver) { #if defined(__linux__) return SANE_STATUS_GOOD; #else /* not __linux__ */ DBG (5, "sanei_usb_release_interface: not supported on this OS\n"); return SANE_STATUS_UNSUPPORTED; #endif /* not __linux__ */ } else if (devices[dn].method == sanei_usb_method_libusb) #ifdef HAVE_LIBUSB_LEGACY { int result; result = usb_release_interface (devices[dn].libusb_handle, interface_number); if (result < 0) { DBG (1, "sanei_usb_release_interface: libusb complained: %s\n", usb_strerror ()); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #elif defined(HAVE_LIBUSB) { int result; result = libusb_release_interface (devices[dn].lu_handle, interface_number); if (result < 0) { DBG (1, "sanei_usb_release_interface: libusb complained: %s\n", sanei_libusb_strerror (result)); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ { DBG (1, "sanei_usb_release_interface: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ else { DBG (1, "sanei_usb_release_interface: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_UNSUPPORTED; } } SANE_Status sanei_usb_set_altinterface (SANE_Int dn, SANE_Int alternate) { if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_set_altinterface: dn >= device number || dn < 0, dn=%d\n", dn); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_set_altinterface: alternate = %d\n", alternate); devices[dn].alt_setting = alternate; if (devices[dn].method == sanei_usb_method_scanner_driver) { #if defined(__linux__) return SANE_STATUS_GOOD; #else /* not __linux__ */ DBG (5, "sanei_usb_set_altinterface: not supported on this OS\n"); return SANE_STATUS_UNSUPPORTED; #endif /* not __linux__ */ } else if (devices[dn].method == sanei_usb_method_libusb) #ifdef HAVE_LIBUSB_LEGACY { int result; result = usb_set_altinterface (devices[dn].libusb_handle, alternate); if (result < 0) { DBG (1, "sanei_usb_set_altinterface: libusb complained: %s\n", usb_strerror ()); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #elif defined(HAVE_LIBUSB) { int result; result = libusb_set_interface_alt_setting (devices[dn].lu_handle, devices[dn].interface_nr, alternate); if (result < 0) { DBG (1, "sanei_usb_set_altinterface: libusb complained: %s\n", sanei_libusb_strerror (result)); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ { DBG (1, "sanei_set_altinterface: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ else { DBG (1, "sanei_usb_set_altinterface: access method %d not implemented\n", devices[dn].method); return SANE_STATUS_UNSUPPORTED; } } extern SANE_Status sanei_usb_get_descriptor( SANE_Int dn, struct sanei_usb_dev_descriptor __sane_unused__ *desc ) { if (dn >= device_number || dn < 0) { DBG (1, "sanei_usb_get_descriptor: dn >= device number || dn < 0, dn=%d\n", dn); return SANE_STATUS_INVAL; } DBG (5, "sanei_usb_get_descriptor\n"); #ifdef HAVE_LIBUSB_LEGACY { struct usb_device_descriptor *usb_descr; usb_descr = &(devices[dn].libusb_device->descriptor); desc->desc_type = usb_descr->bDescriptorType; desc->bcd_usb = usb_descr->bcdUSB; desc->bcd_dev = usb_descr->bcdDevice; desc->dev_class = usb_descr->bDeviceClass; desc->dev_sub_class = usb_descr->bDeviceSubClass; desc->dev_protocol = usb_descr->bDeviceProtocol; desc->max_packet_size = usb_descr->bMaxPacketSize0; return SANE_STATUS_GOOD; } #elif defined(HAVE_LIBUSB) { struct libusb_device_descriptor lu_desc; int ret; ret = libusb_get_device_descriptor (devices[dn].lu_device, &lu_desc); if (ret < 0) { DBG (1, "sanei_usb_get_descriptor: libusb error: %s\n", sanei_libusb_strerror (ret)); return SANE_STATUS_INVAL; } desc->desc_type = lu_desc.bDescriptorType; desc->bcd_usb = lu_desc.bcdUSB; desc->bcd_dev = lu_desc.bcdDevice; desc->dev_class = lu_desc.bDeviceClass; desc->dev_sub_class = lu_desc.bDeviceSubClass; desc->dev_protocol = lu_desc.bDeviceProtocol; desc->max_packet_size = lu_desc.bMaxPacketSize0; return SANE_STATUS_GOOD; } #else /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ { DBG (1, "sanei_usb_get_descriptor: libusb support missing\n"); return SANE_STATUS_UNSUPPORTED; } #endif /* not HAVE_LIBUSB_LEGACY && not HAVE_LIBUSB */ } sane-backends-1.0.27/sanei/sanei_auth.c0000664000175000017500000001511612206524362014613 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements an interface for user authorization using MD5 digest */ #include "../include/sane/config.h" #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #define BACKEND_NAME sanei_auth #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_auth.h" #include "../include/sane/sanei_config.h" #include "../include/md5.h" static int random_seeded = 0; #define INIT_RND() do { \ if (random_seeded == 0) { \ random_seeded = 1; \ srand(time(NULL)); \ DBG_INIT(); \ } \ } while (0) #ifdef HAVE_DEV_URANDOM static unsigned long randombits (void) { FILE *dev_urandom; unsigned long result = 0; char buffer[4]; if ((dev_urandom = fopen ("/dev/urandom", "r")) == NULL) { DBG (2, "randombits: could not open /dev/urandom...\n"); return rand (); } fread (buffer, 1, 4, dev_urandom); fclose (dev_urandom); result = buffer[0]; result <<= 8; result += buffer[1]; result <<= 8; result += buffer[2]; result <<= 8; result += buffer[3]; return result; } #else #define randombits rand #endif static int check_passwd (const char *upassword, const char *password, const char *randomstring, const char *username) { unsigned char md5digest[16]; char tmpstr[512]; if (strncmp (upassword, "$MD5$", 5) == 0) { sprintf (tmpstr, "%s%.128s", strstr (randomstring, "$MD5$") + 5, password); md5_buffer (tmpstr, strlen (tmpstr), md5digest); sprintf (tmpstr, "$MD5$%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x", md5digest[0], md5digest[1], md5digest[2], md5digest[3], md5digest[4], md5digest[5], md5digest[6], md5digest[7], md5digest[8], md5digest[9], md5digest[10], md5digest[11], md5digest[12], md5digest[13], md5digest[14], md5digest[15]); return (strcmp (upassword, tmpstr) == 0); } else { DBG (1, "check_passwd: received plain-text reply from user ``%s''\n", username); return (strcmp (upassword, password) == 0); } } SANE_Status sanei_authorize (const char *resource, const char *backend, SANE_Auth_Callback authorize) { FILE *passwd_file; char passwd_filename[256]; char line[1024], *linep; SANE_Bool entry_found = SANE_FALSE; char md5resource[256]; char username[SANE_MAX_USERNAME_LEN]; char password[SANE_MAX_PASSWORD_LEN]; INIT_RND (); DBG (4, "called for ``%s'' by %s\n", resource, backend); if (strlen (resource) > 127) DBG (1, "resource is longer than 127 chars...\n"); sprintf (passwd_filename, "%s.users", backend); passwd_file = sanei_config_open (passwd_filename); if (passwd_file == NULL) { DBG (3, "could not open ``%s''...\n", passwd_filename); return SANE_STATUS_GOOD; } while (sanei_config_read (line, 1024, passwd_file)) { if (strchr (line, ':') != NULL) { if (strchr (strchr (line, ':') + 1, ':') != NULL) { if (strcmp (strchr (strchr (line, ':') + 1, ':') + 1, resource) == 0) { entry_found = SANE_TRUE; break; } } } } if (entry_found == SANE_FALSE) { fclose (passwd_file); DBG (3, "could not find resource ``%s''...\n", resource); return SANE_STATUS_GOOD; } if (authorize == NULL) { DBG (2, "no authorization callback supplied by frontend\n"); return SANE_STATUS_ACCESS_DENIED; } sprintf (md5resource, "%.128s$MD5$%x%lx%08lx", resource, getpid (), (long int) time (NULL), randombits ()); DBG(0, "resource=%s\n", md5resource); memset (username, 0, SANE_MAX_USERNAME_LEN); memset (password, 0, SANE_MAX_PASSWORD_LEN); (*authorize) (md5resource, username, password); fseek (passwd_file, 0L, SEEK_SET); while (sanei_config_read (line, 1024, passwd_file)) { if ((strlen (line) > 0) && (line[strlen (line) - 1] == '\n')) line[strlen (line) - 1] = '\n'; if ((strlen (line) > 0) && (line[strlen (line) - 1] == '\r')) line[strlen (line) - 1] = '\r'; if ((strncmp (line, username, strlen (username)) == 0) && (((strchr (line, ':')) - line) == (signed) strlen (username))) { linep = strchr (line, ':') + 1; if ((strchr (linep, ':') != NULL) && (strcmp (strchr (linep, ':') + 1, resource) == 0)) { *(strchr (linep, ':')) = 0; if (check_passwd (password, linep, md5resource, username)) { fclose (passwd_file); DBG (2, "authorization succeeded\n"); return SANE_STATUS_GOOD; } } } } fclose (passwd_file); DBG (1, "authorization failed\n"); return SANE_STATUS_ACCESS_DENIED; } sane-backends-1.0.27/lib/0000775000175000017500000000000013110600530012035 500000000000000sane-backends-1.0.27/lib/inet_ntop.c0000664000175000017500000000126612617742237014153 00000000000000#include "../include/sane/config.h" #ifndef HAVE_INET_NTOP #include #include #ifdef HAVE_WINSOCK2_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #include #include #endif const char * inet_ntop (int af, const void *src, char *dst, size_t cnt) { struct in_addr in; char *text_addr; #ifdef HAVE_INET_NTOA if (af == AF_INET) { memcpy (&in.s_addr, src, sizeof (in.s_addr)); text_addr = inet_ntoa (in); if (text_addr && dst) { strncpy (dst, text_addr, cnt); return dst; } else return 0; } #endif /* HAVE_INET_NTOA */ return 0; } #endif /* !HAVE_INET_NTOP */ sane-backends-1.0.27/lib/syslog.c0000664000175000017500000000031512617742237013466 00000000000000#include "../include/sane/config.h" #ifndef HAVE_SYSLOG #include void syslog(int priority, const char *format, va_list args) { printf("%d ", priority); printf(format, args); } #endif sane-backends-1.0.27/lib/sigprocmask.c0000664000175000017500000000273712617742237014502 00000000000000/* Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../include/sane/config.h" #include #ifndef HAVE_SIGPROCMASK #define sigprocmask SOMETHINGELSE #include #undef sigprocmask int sigprocmask (int how, int *new, int *old) { int o, n = *new; /* FIXME: Get this working on Windows. Probably should move to * POSIX sigaction API and emulate it before emulating this one. */ #ifndef WIN32 switch (how) { case 1: o = sigblock (n); break; case 2: o = sigsetmask (sigblock (0) & ~n); break; case 3: o = sigsetmask (n); break; default: errno = EINVAL; return -1; } if (old) *old = o; #endif return 0; } #endif /* !HAVE_SIGPROCMASK */ sane-backends-1.0.27/lib/getopt1.c0000664000175000017500000001124712112021330013505 00000000000000/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #if !defined(HAVE_GETOPT_H) || !defined(HAVE_GETOPT_LONG) #ifdef HAVE_CONFIG_H #include #endif #ifdef _LIBC # include #else # include "../include/lgetopt.h" #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } # ifdef _LIBC libc_hidden_def (getopt_long) libc_hidden_def (getopt_long_only) # endif #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ #endif /* HAVE_GETOPT_LONG */ sane-backends-1.0.27/lib/getenv.c0000664000175000017500000000046412112021330013411 00000000000000#include "../include/sane/config.h" #ifndef HAVE_GETENV char * getenv(const char *name) { char *retval = 0; #ifdef HAVE_OS2_H if (0 != DosScanEnv (buf, &retval)) retval = 0; #else # error "Missing getenv() on this platform. Please implement." #endif return retval; } #endif /* !HAVE_GETENV */ sane-backends-1.0.27/lib/snprintf.c0000664000175000017500000010557712775312262014025 00000000000000#include "../include/sane/config.h" #ifndef HAVE_SNPRINTF /************************************************************************** * Copyright 1994-2003 Patrick Powell, San Diego, CA **************************************************************************/ /* Overview: snprintf( char *buffer, int len, const char *format,...) plp_unsafe_snprintf( char *buffer, int len, const char *format,...) its horribly unsafe companion that does NOT protect you from the printing of evil control characters, but may be necessary See the man page documentation below This version of snprintf was developed originally for printing on a motley collection of specialized hardware that had NO IO library. Due to contractual restrictions, a clean room implementation of the printf() code had to be developed. The method chosen for printf was to be as paranoid as possible, as these platforms had NO memory protection, and very small address spaces. This made it possible to try to print very long strings, i.e. - all of memory, very easily. To guard against this, all printing was done via a buffer, generous enough to hold strings, but small enough to protect against overruns, etc. Strangely enough, this proved to be of immense importance when SPRINTFing to a buffer on a stack... The rest, of course, is well known, as buffer overruns in the stack are a common way to do horrible things to operating systems, security, etc etc. This version of snprintf is VERY limited by modern standards. Revision History: First Released Version - 1994. This version had NO comments. First Released Version - 1994. This version had NO comments. Second Major Released Version - Tue May 23 10:43:44 PDT 2000 Configuration and other items changed. Read this doc. Treat this as a new version. Minor Revision - Mon Apr 1 09:41:28 PST 2002 - fixed up some constants and casts COPYRIGHT AND TERMS OF USE: You may use, copy, distribute, or otherwise incorporate this software and documentation into any product or other item, provided that the copyright in the documentation and source code as well as the source code generated constant strings in the object, executable or other code remain in place and are present in executable modules or objects. You may modify this code as appropriate to your usage; however the modified version must be identified by changing the various source and object code identification strings as is appropriately noted in the source code. You can use this with the GNU CONFIGURE utility. This should define the following macros appropriately: HAVE_STDARG_H - if the include file is available HAVE_VARARG_H - if the include file is available HAVE_STRERROR - if the strerror() routine is available. If it is not available, then examine the lines containing the tests below. HAVE_SYS_ERRLIST - have sys_errlist available HAVE_DECL_SYS_ERRLIST - sys_errlist declaration in include files HAVE_SYS_NERR - have sys_nerr available HAVE_DECL_SYS_NERR - sys_nerr declaration in include files HAVE_QUAD_T - if the quad_t type is defined HAVE_LONG_LONG - if the long long type is defined HAVE_LONG_DOUBLE - if the long double type is defined If you are using the GNU configure (autoconf) facility, add the following line to the configure.in file, to force checking for the quad_t and long long data types: AC_CHECK_HEADERS(stdlib.h,stdio.h,unistd.h,errno.h) AC_CHECK_FUNCS(strerror) AC_CACHE_CHECK(for errno, ac_cv_errno, [ AC_TRY_LINK(,[extern int errno; return (errno);], ac_cv_errno=yes, ac_cv_errno=no) ]) if test "$ac_cv_errno" = yes; then AC_DEFINE(HAVE_ERRNO) AC_CACHE_CHECK(for errno declaration, ac_cv_decl_errno, [ AC_TRY_COMPILE([ #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_ERRNO_H #include ],[return(sys_nerr);], ac_cv_decl_errno=yes, ac_cv_decl_errno=no) ]) if test "$ac_cv_decl_errno" = yes; then AC_DEFINE(HAVE_DECL_ERRNO) fi; fi AC_CACHE_CHECK(for sys_nerr, ac_cv_sys_nerr, [ AC_TRY_LINK(,[extern int sys_nerr; return (sys_nerr);], ac_cv_sys_nerr=yes, ac_cv_sys_nerr=no) ]) if test "$ac_cv_sys_nerr" = yes; then AC_DEFINE(HAVE_SYS_NERR) AC_CACHE_CHECK(for sys_nerr declaration, ac_cv_decl_sys_nerr, [ AC_TRY_COMPILE([ #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_UNISTD_H #include #endif],[return(sys_nerr);], ac_cv_decl_sys_nerr_def=yes, ac_cv_decl_sys_nerr_def=no) ]) if test "$ac_cv_decl_sys_nerr" = yes; then AC_DEFINE(HAVE_DECL_SYS_NERR) fi fi AC_CACHE_CHECK(for sys_errlist array, ac_cv_sys_errlist, [AC_TRY_LINK(,[extern char *sys_errlist[]; sys_errlist[0];], ac_cv_sys_errlist=yes, ac_cv_sys_errlist=no) ]) if test "$ac_cv_sys_errlist" = yes; then AC_DEFINE(HAVE_SYS_ERRLIST) AC_CACHE_CHECK(for sys_errlist declaration, ac_cv_sys_errlist_def, [AC_TRY_COMPILE([ #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_UNISTD_H #include #endif],[char *s = sys_errlist[0]; return(*s);], ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no) ]) if test "$ac_cv_decl_sys_errlist" = yes; then AC_DEFINE(HAVE_DECL_SYS_ERRLIST) fi fi AC_CACHE_CHECK(checking for long long, ac_cv_long_long, [ AC_TRY_COMPILE([ #include #include ], [printf("%d",sizeof(long long));], ac_cv_long_long=yes, ac_cv_long_long=no) ]) if test $ac_cv_long_long = yes; then AC_DEFINE(HAVE_LONG_LONG) fi AC_CACHE_CHECK(checking for long double, ac_cv_long_double, [ AC_TRY_COMPILE([ #include #include ], [printf("%d",sizeof(long double));], ac_cv_long_double=yes, ac_cv_long_double=no) ]) if test $ac_cv_long_double = yes; then AC_DEFINE(HAVE_LONG_DOUBLE) fi AC_CACHE_CHECK(checking for quad_t, ac_cv_quad_t, [ AC_TRY_COMPILE([ #include #include ], [printf("%d",sizeof(quad_t));], ac_cv_quad_t=yes, ac_cv_quad_t=no) ]) if test $ac_cv_quad_t = yes; then AC_DEFINE(HAVE_QUAD_T) fi NAME snprintf, plp_vsnprintf - formatted output conversion SYNOPSIS #include #include int snprintf(const char *format, size_t size, va_list ap); int plp_unsafe_snprintf(const char *format, size_t size, va_list ap); AKA snprintf and unsafe_snprintf in the documentation below int vsnprintf(char *str, size_t size, const char *format, va_list ap); int unsafe_vsnprintf(char *str, size_t size, const char *format, va_list ap); AKA vsnprintf and unsafe_vsnprintf in the documentation below (Multithreaded Safe) DESCRIPTION The printf() family of functions produces output according to a format as described below. Snprintf(), and vsnprintf() write to the character string str. These functions write the output under the control of a format string that specifies how subsequent arguments (or arguments accessed via the variable-length argument facilities of stdarg(3)) are converted for output. These functions return the number of characters printed (not including the trailing `\0' used to end output to strings). Snprintf() and vsnprintf() will write at most size-1 of the characters printed into the output string (the size'th character then gets the terminating `\0'); if the return value is greater than or equal to the size argument, the string was too short and some of the printed characters were discarded. The size or str may be given as zero to find out how many characters are needed; in this case, the str argument is ignored. By default, the snprintf function will not format control characters (except new line and tab) in strings. This is a safety feature that has proven to be extremely critical when using snprintf for secure applications and when debugging. If you MUST have control characters formatted or printed, then use the unsafe_snprintf() and unsafe_vsnprintf() and on your own head be the consequences. You have been warned. There is one exception to the comments above, and that is the "%c" (character) format. It brutally assumes that the user will have performed the necessary 'isprint()' or other checks and uses the integer value as a character. The format string is composed of zero or more directives: ordinary characters (not %), which are copied unchanged to the output stream; and conversion specifications, each of which results in fetching zero or more subsequent arguments. Each conversion specification is introduced by the character %. The arguments must correspond properly (after type promotion) with the conversion specifier. After the %, the following appear in sequence: o Zero or more of the following flags: - A zero `0' character specifying zero padding. For all conversions except n, the converted value is padded on the left with zeros rather than blanks. If a precision is given with a numeric conversion (d, i, o, u, i, x, and X), the `0' flag is ignored. - A negative field width flag `-' indicates the converted value is to be left adjusted on the field boundary. Except for n conversions, the converted value is padded on the right with blanks, rather than on the left with blanks or zeros. A `-' overrides a `0' if both are given. - A space, specifying that a blank should be left before a positive number produced by a signed conversion (d, e, E, f, g, G, or i). - A `+' character specifying that a sign always be placed before a number produced by a signed conversion. A `+' overrides a space if both are used. o An optional decimal digit string specifying a minimum field width. If the converted value has fewer characters than the field width, it will be padded with spaces on the left (or right, if the left-adjustment flag has been given) to fill out the field width. o An optional precision, in the form of a period `.' followed by an optional digit string. If the digit string is omitted, the precision is taken as zero. This gives the minimum number of digits to appear for d, i, o, u, x, and X conversions, the number of digits to appear after the decimal-point for e, E, and f conversions, the maximum number of significant digits for g and G conversions, or the maximum number of characters to be printed from a string for s conversions. o The optional character h, specifying that a following d, i, o, u, x, or X conversion corresponds to a short int or unsigned short int argument, or that a following n conversion corresponds to a pointer to a short int argument. o The optional character l (ell) specifying that a following d, i, o, u, x, or X conversion applies to a pointer to a long int or unsigned long int argument, or that a following n conversion corresponds to a pointer to a long int argument. o The optional character q, specifying that a following d, i, o, u, x, or X conversion corresponds to a quad_t or u_quad_t argument, or that a following n conversion corresponds to a quad_t argument. This value is always printed in HEX notation. Tough. quad_t's are an OS system implementation, and should not be allowed. o The character L specifying that a following e, E, f, g, or G conversion corresponds to a long double argument. o A character that specifies the type of conversion to be applied. A field width or precision, or both, may be indicated by an asterisk `*' instead of a digit string. In this case, an int argument supplies the field width or precision. A negative field width is treated as a left adjustment flag followed by a positive field width; a negative precision is treated as though it were missing. The conversion specifiers and their meanings are: diouxX The int (or appropriate variant) argument is converted to signed decimal (d and i), unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal (x and X) notation. The letters abcdef are used for x conversions; the letters ABCDEF are used for X conversions. The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with zeros. eE The double argument is rounded and converted in the style [-]d.ddde+-dd where there is one digit before the decimal-point character and the number of digits after it is equal to the precision; if the precision is missing, it is taken as 6; if the precision is zero, no decimal-point character appears. An E conversion uses the letter E (rather than e) to introduce the exponent. The exponent always contains at least two digits; if the value is zero, the exponent is 00. f The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it. g The double argument is converted in style f or e (or E for G conversions). The precision specifies the number of significant digits. If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1. Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit. c The int argument is converted to an unsigned char, and the resulting character is written. s The ``char *'' argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating NUL character; if a precision is specified, no more than the number specified are written. If a precision is given, no null character need be present; if the precision is not specified, or is greater than the size of the array, the array must contain a terminating NUL character. % A `%' is written. No argument is converted. The complete conversion specification is `%%'. In no case does a non-existent or small field width cause truncation of a field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result. EXAMPLES To print a date and time in the form `Sunday, July 3, 10:02', where weekday and month are pointers to strings: #include fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min); To print pi to five decimal places: #include #include fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0)); To allocate a 128 byte string and print into it: #include #include #include char *newfmt(const char *fmt, ...) { char *p; va_list ap; if ((p = malloc(128)) == NULL) return (NULL); va_start(ap, fmt); (void) vsnprintf(p, 128, fmt, ap); va_end(ap); return (p); } SEE ALSO printf(1), scanf(3) STANDARDS Turkey C Standardization and wimpy POSIX folks did not define snprintf or vsnprintf(). BUGS The conversion formats %D, %O, and %U are not standard and are provided only for backward compatibility. The effect of padding the %p format with zeros (either by the `0' flag or by specifying a precision), and the benign effect (i.e., none) of the `#' flag on %n and %p conversions, as well as other nonsensical combinations such as %Ld, are not standard; such combinations should be avoided. The typedef names quad_t and u_quad_t are infelicitous. */ #include #include #include #include #if defined(HAVE_STRING_H) # include #endif #if defined(HAVE_STRINGS_H) # include #endif #if defined(HAVE_ERRNO_H) #include #endif /* * For testing, define these values */ #if 0 #define HAVE_STDARG_H 1 #define TEST 1 #define HAVE_QUAD_T 1 #endif /**** ENDINCLUDE ****/ /************************************************* * KEEP THIS STRING - MODIFY AT THE END WITH YOUR REVISIONS * i.e. - the LOCAL REVISIONS part is for your use *************************************************/ static char *const _id = "plp_snprintf V2000.08.18 Copyright Patrick Powell 1988-2000 " "$Id: plp_snprintf.c,v 1.4 2005/04/14 20:05:19 papowell Exp $" " LOCAL REVISIONS: renamed plp_snprintf to snprintf, conditionalized everything on HAVE_SNPRINTF"; /* varargs declarations: */ # undef HAVE_STDARGS /* let's hope that works everywhere (mj) */ # undef VA_LOCAL_DECL # undef VA_START # undef VA_SHIFT # undef VA_END #if defined(HAVE_STDARG_H) # include # define HAVE_STDARGS /* let's hope that works everywhere (mj) */ # define VA_LOCAL_DECL va_list ap; # define VA_START(f) va_start(ap, f) # define VA_SHIFT(v,t) ; /* no-op for ANSI */ # define VA_END va_end(ap) #else # if defined(HAVE_VARARGS_H) # include # undef HAVE_STDARGS # define VA_LOCAL_DECL va_list ap; # define VA_START(f) va_start(ap) /* f is ignored! */ # define VA_SHIFT(v,t) v = va_arg(ap,t) # define VA_END va_end(ap) # else XX ** NO VARARGS ** XX # endif #endif union value { #if defined(HAVE_QUAD_T) quad_t qvalue; #endif #if defined(HAVE_LONG_LONG) long long value; #else long value; #endif double dvalue; }; #undef CVAL #define CVAL(s) (*((unsigned char *)s)) #define safestrlen(s) ((s)?strlen(s):0) static char * plp_Errormsg ( int err, char *buffer ); static void dopr( int visible_control, char **buffer, int *left, const char *format, va_list args ); static void fmtstr( int visible_control, char **buffer, int *left, char *value, int ljust, int len, int zpad, int precision ); static void fmtnum( char **buffer, int *left, union value *value, int base, int dosign, int ljust, int len, int zpad, int precision ); #if defined(HAVE_QUAD_T) static void fmtquad( char **buffer, int *left, union value *value, int base, int dosign, int ljust, int len, int zpad, int precision ); #endif static void fmtdouble( char **bufer, int *left, int fmt, double value, int ljust, int len, int zpad, int precision ); static void dostr( char **buffer, int *left, char *str ); static void dopr_outch( char **buffer, int *left, int c ); /* VARARGS3 */ #ifdef HAVE_STDARGS int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args) #else int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args) #endif { int left; char *buffer; if( (int)count < 0 ) count = 0; left = count; if( count == 0 ) str = 0; buffer = str; dopr( 1, &buffer, &left, fmt, args ); /* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n", (int)str, (int)buffer, count, left ); */ if( str && count > 0 ){ if( left > 0 ){ str[count-left] = 0; } else { str[count-1] = 0; } } return(count - left); } /* VARARGS3 */ #ifdef HAVE_STDARGS int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args) #else int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args) #endif { int left; char *buffer; if( (int)count < 0 ) count = 0; left = count; if( count == 0 ) str = 0; buffer = str; dopr( 0, &buffer, &left, fmt, args ); /* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n", (int)str, (int)buffer, count, left ); */ if( str && count > 0 ){ if( left > 0 ){ str[count-left] = 0; } else { str[count-1] = 0; } } return(count - left); } /* VARARGS3 */ #ifdef HAVE_STDARGS int snprintf (char *str,size_t count,const char *fmt,...) #else int snprintf (va_alist) va_dcl #endif { #ifndef HAVE_STDARGS char *str; size_t count; char *fmt; #endif int n = 0; VA_LOCAL_DECL VA_START (fmt); VA_SHIFT (str, char *); VA_SHIFT (count, size_t ); VA_SHIFT (fmt, char *); n = plp_vsnprintf ( str, count, fmt, ap); VA_END; return( n ); } /* VARARGS3 */ #ifdef HAVE_STDARGS int plp_unsafe_snprintf (char *str,size_t count,const char *fmt,...) #else int plp_unsafe_snprintf (va_alist) va_dcl #endif { #ifndef HAVE_STDARGS char *str; size_t count; char *fmt; #endif int n = 0; VA_LOCAL_DECL VA_START (fmt); VA_SHIFT (str, char *); VA_SHIFT (count, size_t ); VA_SHIFT (fmt, char *); n = plp_unsafe_vsnprintf ( str, count, fmt, ap); VA_END; return( n ); } static void dopr( int visible_control, char **buffer, int *left, const char *format, va_list args ) { int ch; union value value; int longflag = 0; int quadflag = 0; char *strvalue; int ljust; int len; int zpad; int precision; int set_precision; double dval; int err = errno; int base = 0; int signed_val = 0; while( (ch = *format++) ){ switch( ch ){ case '%': longflag = quadflag = ljust = len = zpad = base = signed_val = 0; precision = -1; set_precision = 0; nextch: ch = *format++; switch( ch ){ case 0: dostr( buffer, left, "**end of format**" ); return; case '-': ljust = 1; goto nextch; case '.': set_precision = 1; precision = 0; goto nextch; case '*': if( set_precision ){ precision = va_arg( args, int ); } else { len = va_arg( args, int ); } goto nextch; case '0': /* set zero padding if len not set */ if(len==0 && set_precision == 0 ) zpad = '0'; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if( set_precision ){ precision = precision*10 + ch - '0'; } else { len = len*10 + ch - '0'; } goto nextch; case 'l': ++longflag; goto nextch; case 'q': #if !defined( HAVE_QUAD_T ) dostr( buffer, left, "*no quad_t support *"); return; #endif quadflag = 1; goto nextch; case 'u': case 'U': if( base == 0 ){ base = 10; signed_val = 0; } case 'o': case 'O': if( base == 0 ){ base = 8; signed_val = 0; } case 'd': case 'D': if( base == 0 ){ base = 10; signed_val = 1; } case 'x': if( base == 0 ){ base = 16; signed_val = 0; } case 'X': if( base == 0 ){ base = -16; signed_val = 0; } #if defined( HAVE_QUAD_T ) if( quadflag ){ value.qvalue = va_arg( args, quad_t ); fmtquad( buffer, left, &value,base,signed_val, ljust, len, zpad, precision ); break; } else #endif if( longflag > 1 ){ #if defined(HAVE_LONG_LONG) if( signed_val ){ value.value = va_arg( args, long long ); } else { value.value = va_arg( args, unsigned long long ); } #else if( signed_val ){ value.value = va_arg( args, long ); } else { value.value = va_arg( args, unsigned long ); } #endif } else if( longflag ){ if( signed_val ){ value.value = va_arg( args, long ); } else { value.value = va_arg( args, unsigned long ); } } else { if( signed_val ){ value.value = va_arg( args, int ); } else { value.value = va_arg( args, unsigned int ); } } fmtnum( buffer, left, &value,base,signed_val, ljust, len, zpad, precision ); break; case 's': strvalue = va_arg( args, char *); fmtstr( visible_control, buffer, left, strvalue,ljust,len, zpad, precision ); break; case 'c': ch = va_arg( args, int ); { char b[2]; b[0] = ch; b[1] = 0; fmtstr( 0, buffer, left, b,ljust,len, zpad, precision ); } break; case 'f': case 'g': case 'e': dval = va_arg( args, double ); fmtdouble( buffer, left, ch, dval,ljust,len, zpad, precision ); break; case 'm': { char shortbuffer[32]; fmtstr( visible_control, buffer, left, plp_Errormsg(err, shortbuffer),ljust,len, zpad, precision ); } break; case '%': dopr_outch( buffer, left, ch ); continue; default: dostr( buffer, left, "???????" ); } longflag = 0; break; default: dopr_outch( buffer, left, ch ); break; } } } /* * Format '%[-]len[.precision]s' * - = left justify (ljust) * len = minimum length * precision = numbers of chars in string to use */ static void fmtstr( int visible_control, char **buffer, int *left, char *value, int ljust, int len, int zpad, int precision ) { int padlen, strlenv, i, c; /* amount to pad */ if( value == 0 ){ value = ""; } /* cheap strlen so you do not have library call */ for( strlenv = i = 0; (c=CVAL(value+i)); ++i ){ if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){ ++strlenv; } ++strlenv; } if( precision > 0 && strlenv > precision ){ strlenv = precision; } padlen = len - strlenv; if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; while( padlen > 0 ) { dopr_outch( buffer, left, ' ' ); --padlen; } /* output characters */ for( i = 0; i < strlenv && (c = CVAL(value+i)); ++i ){ if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){ dopr_outch(buffer, left, '^'); c = ('@' | (c & 0x1F)); } dopr_outch(buffer, left, c); } while( padlen < 0 ) { dopr_outch( buffer, left, ' ' ); ++padlen; } } static void fmtnum( char **buffer, int *left, union value *value, int base, int dosign, int ljust, int len, int zpad, int precision ) { int signvalue = 0; #if defined(HAVE_LONG_LONG) unsigned long long uvalue; #else unsigned long uvalue; #endif char convert[sizeof( union value) * 8 + 16]; int place = 0; int padlen = 0; /* amount to pad */ int caps = 0; /* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", value, base, dosign, ljust, len, zpad );/ **/ uvalue = value->value; if( dosign ){ if( value->value < 0 ) { signvalue = '-'; uvalue = -value->value; } } if( base < 0 ){ caps = 1; base = -base; } do{ convert[place++] = (caps? "0123456789ABCDEF":"0123456789abcdef") [uvalue % (unsigned)base ]; uvalue = (uvalue / (unsigned)base ); }while(uvalue); convert[place] = 0; padlen = len - place; if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n", convert,place,signvalue,padlen); / **/ if( zpad && padlen > 0 ){ if( signvalue ){ dopr_outch( buffer, left, signvalue ); --padlen; signvalue = 0; } while( padlen > 0 ){ dopr_outch( buffer, left, zpad ); --padlen; } } while( padlen > 0 ) { dopr_outch( buffer, left, ' ' ); --padlen; } if( signvalue ) dopr_outch( buffer, left, signvalue ); while( place > 0 ) dopr_outch( buffer, left, convert[--place] ); while( padlen < 0 ){ dopr_outch( buffer, left, ' ' ); ++padlen; } } #if defined(HAVE_QUAD_T) static void fmtquad( char **buffer, int *left, union value *value, int base, int dosign, int ljust, int len, int zpad, int precision ) { int signvalue = 0; int place = 0; int padlen = 0; /* amount to pad */ int caps = 0; int i, c; union { quad_t qvalue; unsigned char qconvert[sizeof(quad_t)]; } vvalue; char convert[2*sizeof(quad_t)+1]; /* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", value, base, dosign, ljust, len, zpad );/ **/ vvalue.qvalue = value->qvalue; if( base < 0 ){ caps = 1; } for( i = 0; i < (int)sizeof(quad_t); ++i ){ c = vvalue.qconvert[i]; convert[2*i] = (caps? "0123456789ABCDEF":"0123456789abcdef")[ (c >> 4) & 0xF]; convert[2*i+1] = (caps? "0123456789ABCDEF":"0123456789abcdef")[ c & 0xF]; } convert[2*i] = 0; place = strlen(convert); padlen = len - place; if( padlen < 0 ) padlen = 0; if( ljust ) padlen = -padlen; /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n", convert,place,signvalue,padlen); / **/ if( zpad && padlen > 0 ){ if( signvalue ){ dopr_outch( buffer, left, signvalue ); --padlen; signvalue = 0; } while( padlen > 0 ){ dopr_outch( buffer, left, zpad ); --padlen; } } while( padlen > 0 ) { dopr_outch( buffer, left, ' ' ); --padlen; } if( signvalue ) dopr_outch( buffer, left, signvalue ); while( place > 0 ) dopr_outch( buffer, left, convert[--place] ); while( padlen < 0 ){ dopr_outch( buffer, left, ' ' ); ++padlen; } } #endif static void mystrcat(char *dest, char *src ) { if( dest && src ){ dest += safestrlen(dest); strcpy(dest,src); } } static void fmtdouble( char **buffer, int *left, int fmt, double value, int ljust, int len, int zpad, int precision ) { char convert[sizeof( union value) * 8 + 512]; char formatstr[128]; /* fprintf(stderr,"len %d, precision %d\n", len, precision ); */ if( len > 255 ){ len = 255; } if( precision > 255 ){ precision = 255; } if( precision >= 0 && len > 0 && precision > len ) precision = len; strcpy( formatstr, "%" ); /* 1 */ if( ljust ) mystrcat(formatstr, "-" ); /* 1 */ if( zpad ) mystrcat(formatstr, "0" ); /* 1 */ if( len >= 0 ){ sprintf( formatstr+strlen(formatstr), "%d", len ); /* 3 */ } if( precision >= 0 ){ sprintf( formatstr+strlen(formatstr), ".%d", precision ); /* 3 */ } /* format string will be at most 10 chars long ... */ sprintf( formatstr+strlen(formatstr), "%c", fmt ); /* this is easier than trying to do the portable dtostr */ /* fprintf(stderr,"format string '%s'\n", formatstr); */ sprintf( convert, formatstr, value ); dostr( buffer, left, convert ); } static void dostr( char **buffer, int *left, char *str ) { if(str)while(*str) dopr_outch( buffer, left, *str++ ); } static void dopr_outch( char **buffer, int *left, int c ) { if( *left > 0 ){ *(*buffer)++ = c; } *left -= 1; } /**************************************************************************** * static char *plp_errormsg( int err ) * returns a printable form of the * errormessage corresponding to the valie of err. * This is the poor man's version of sperror(), not available on all systems * Patrick Powell Tue Apr 11 08:05:05 PDT 1995 ****************************************************************************/ /****************************************************************************/ #if !defined(HAVE_STRERROR) # undef num_errors # if defined(HAVE_SYS_ERRLIST) # if !defined(HAVE_DECL_SYS_ERRLIST) extern const char *const sys_errlist[]; # endif # if defined(HAVE_SYS_NERR) # if !defined(HAVE_DECL_SYS_NERR) extern int sys_nerr; # endif # define num_errors (sys_nerr) # endif # endif # if !defined(num_errors) # define num_errors (-1) /* always use "errno=%d" */ # endif #endif static char * plp_Errormsg ( int err, char *buffer /* int maxlen = 32 */) { char *cp; #if defined(HAVE_STRERROR) cp = (void *)strerror(err); #else # if defined(HAVE_SYS_ERRLIST) if (err >= 0 && err < num_errors) { cp = (void *)sys_errlist[err]; } else # endif { (void) sprintf (buffer, "errno=%d", err); cp = buffer; } #endif return (cp); } #if defined(TEST) #include int main( void ) { char buffer[128]; char *t; char *test1 = "01234"; int n; errno = 1; buffer[0] = 0; n = snprintf( buffer, 0, (t="test")); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t="errno '%m'")); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%-12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%-12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%g"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%12g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%12.1g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%12.2g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%12.3g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%0*d"), 6, 1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); #if defined(HAVE_LONG_LONG) n = snprintf( buffer, sizeof(buffer), (t = "%llx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%llx"), (long long)1, (long long)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%qx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%qx"), (quad_t)1, (quad_t)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); #endif n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0x89ABCDEF, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), t, 0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%12f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%12.2f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%0.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%1.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%1.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); n = snprintf( buffer, sizeof(buffer), (t = "%5.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); return(0); } #endif #endif /* HAVE_SNPRINTF */ sane-backends-1.0.27/lib/strsep.c0000664000175000017500000000260312112021330013436 00000000000000/* Copyright (C) 1992, 1993, 1996 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../include/sane/config.h" #include #ifndef HAVE_STRSEP char * strsep (char **stringp, const char *delim) { char *begin, *end; begin = *stringp; if (! begin || *begin == '\0') return NULL; /* Find the end of the token. */ end = strpbrk (begin, delim); if (end) { /* Terminate the token and set *STRINGP past NUL character. */ *end++ = '\0'; *stringp = end; } else /* No more delimiters; this is the last token. */ *stringp = NULL; return begin; } #endif /* !HAVE_STRSEP */ sane-backends-1.0.27/lib/inet_pton.c0000664000175000017500000000163312617742237014151 00000000000000#include "../include/sane/config.h" #ifndef HAVE_INET_PTON #include #include #ifdef HAVE_WINSOCK2_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #include #include #endif int inet_pton (int af, const char *src, void *dst) { if (af == AF_INET) { #if defined(HAVE_INET_ATON) int result; struct in_addr in; result = inet_aton (src, &in); if (result) { memcpy (dst, &in.s_addr, sizeof (in.s_addr)); return 1; } else return 0; #elif defined(HAVE_INET_ADDR) # if !defined(INADDR_NONE) # define INADDR_NONE -1 # endif /* !defined(INADDR_NONE) */ u_int32_t in; in = inet_addr (src); if (in != INADDR_NONE) { memcpy (dst, &in, sizeof (in)); return 1; } else return 0; #endif /* defined(HAVE_INET_ATON) */ } return -1; } #endif /* !HAVE_INET_PTON */ sane-backends-1.0.27/lib/Makefile.in0000664000175000017500000005402013110564734014042 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs alloca.c getenv.c isfdtype.c \ getopt1.c sleep.c strdup.c strsep.c syslog.c usleep.c getopt.c \ inet_pton.c sigprocmask.c inet_ntop.c vsyslog.c strcasestr.c \ snprintf.c strndup.c $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) liblib_la_DEPENDENCIES = $(LTALLOCA) $(LTLIBOBJS) am_liblib_la_OBJECTS = liblib_la-md5.lo liblib_la_OBJECTS = $(am_liblib_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(liblib_la_SOURCES) DIST_SOURCES = $(liblib_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(top_builddir)/include \ -I$(top_srcdir)/include AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = liblib.la liblib_la_SOURCES = md5.c liblib_la_CPPFLAGS = -I$(top_srcdir)/include liblib_la_LIBADD = $(LTALLOCA) $(LTLIBOBJS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } liblib.la: $(liblib_la_OBJECTS) $(liblib_la_DEPENDENCIES) $(EXTRA_liblib_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(liblib_la_OBJECTS) $(liblib_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/alloca.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getenv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getopt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getopt1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/inet_ntop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/inet_pton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/isfdtype.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/sigprocmask.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/sleep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/snprintf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strcasestr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strdup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strndup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strsep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/syslog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/usleep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/vsyslog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblib_la-md5.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< liblib_la-md5.lo: md5.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblib_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblib_la-md5.lo -MD -MP -MF $(DEPDIR)/liblib_la-md5.Tpo -c -o liblib_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liblib_la-md5.Tpo $(DEPDIR)/liblib_la-md5.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='md5.c' object='liblib_la-md5.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblib_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblib_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf $(DEPDIR) ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf $(DEPDIR) ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/lib/isfdtype.c0000664000175000017500000000075412112021330013752 00000000000000#include "../include/sane/config.h" #ifndef HAVE_ISFDTYPE #include int isfdtype(int fd, int fdtype) { struct stat st; if (fstat(fd, &st) == -1) return 0; /* couldn't stat fd */ if (st.st_mode == 0) return 1; /* At least Irix doesn't seem to know socket type */ #if defined(S_ISSOCK) return S_ISSOCK(st.st_mode) != 0; #elif defined(S_IFSOCK) && defined(S_IFMT) return (st.st_mode & S_IFMT) == S_IFSOCK; #else return 0; #endif } #endif /* !HAVE_ISFDTYPE */ sane-backends-1.0.27/lib/md5.c0000664000175000017500000003343212775312262012635 00000000000000/* Functions to compute MD5 message digest of files or memory blocks. according to the definition of MD5 in RFC 1321 from April 1992. Copyright (C) 1995,1996,1997,1999,2000,2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ /* Written by Ulrich Drepper , 1995. */ #ifdef HAVE_CONFIG_H # include #endif #include #if STDC_HEADERS || defined _LIBC # include # include #else # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # endif #endif #include "md5.h" #ifdef _LIBC # include # if __BYTE_ORDER == __BIG_ENDIAN # define WORDS_BIGENDIAN 1 # endif /* We need to keep the namespace clean so define the MD5 function protected using leading __ . */ # define md5_init_ctx __md5_init_ctx # define md5_process_block __md5_process_block # define md5_process_bytes __md5_process_bytes # define md5_finish_ctx __md5_finish_ctx # define md5_read_ctx __md5_read_ctx # define md5_stream __md5_stream # define md5_buffer __md5_buffer #endif #ifdef WORDS_BIGENDIAN # define SWAP(n) \ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) #else # define SWAP(n) (n) #endif /* This array contains the bytes used to pad the buffer to the next 64-byte boundary. (RFC 1321, 3.1: Step 1) */ static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; void md5_init_ctx (struct md5_ctx *ctx); void * md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); void * md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); int md5_stream (FILE *stream, void *resblock); void * md5_buffer (const char *buffer, size_t len, void *resblock); void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx); void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx); /* Initialize structure containing state of computation. (RFC 1321, 3.3: Step 3) */ void md5_init_ctx (struct md5_ctx *ctx) { ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->total[0] = ctx->total[1] = 0; ctx->buflen = 0; } /* Put result from CTX in first 16 bytes following RESBUF. The result must be in little endian byte order. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ void * md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) { ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); return resbuf; } /* Process the remaining bytes in the internal buffer and the usual prolog according to the standard and write the result to RESBUF. IMPORTANT: On some systems it is required that RESBUF is correctly aligned for a 32 bits value. */ void * md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) { /* Take yet unprocessed bytes into account. */ md5_uint32 bytes = ctx->buflen; size_t pad; /* Now count remaining bytes. */ ctx->total[0] += bytes; if (ctx->total[0] < bytes) ++ctx->total[1]; pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; memcpy (&ctx->buffer[bytes], fillbuf, pad); /* Put the 64-bit file length in *bits* at the end of the buffer. */ ((md5_uint32 *) ctx->buffer)[bytes + pad] = SWAP (ctx->total[0] << 3); ((md5_uint32 *) ctx->buffer)[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); /* Process last bytes. */ md5_process_block (ctx->buffer, bytes + pad + 8, ctx); return md5_read_ctx (ctx, resbuf); } /* Compute MD5 message digest for bytes read from STREAM. The resulting message digest number will be written into the 16 bytes beginning at RESBLOCK. */ int md5_stream (FILE *stream, void *resblock) { /* Important: BLOCKSIZE must be a multiple of 64. */ #define BLOCKSIZE 4096 struct md5_ctx ctx; char buffer[BLOCKSIZE + 72]; size_t sum; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Iterate over full file contents. */ while (1) { /* We read the file in blocks of BLOCKSIZE bytes. One call of the computation function processes the whole buffer so that with the next round of the loop another block can be read. */ size_t n; sum = 0; /* Read block. Take care for partial reads. */ do { n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); sum += n; } while (sum < BLOCKSIZE && n != 0); if (n == 0 && ferror (stream)) return 1; /* If end of file is reached, end the loop. */ if (n == 0) break; /* Process buffer with BLOCKSIZE bytes. Note that BLOCKSIZE % 64 == 0 */ md5_process_block (buffer, BLOCKSIZE, &ctx); } /* Add the last bytes if necessary. */ if (sum > 0) md5_process_bytes (buffer, sum, &ctx); /* Construct result in desired memory. */ md5_finish_ctx (&ctx, resblock); return 0; } /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The result is always in little endian byte order, so that a byte-wise output yields to the wanted ASCII representation of the message digest. */ void * md5_buffer (const char *buffer, size_t len, void *resblock) { struct md5_ctx ctx; /* Initialize the computation context. */ md5_init_ctx (&ctx); /* Process whole buffer but last len % 64 bytes. */ md5_process_bytes (buffer, len, &ctx); /* Put result in desired memory area. */ return md5_finish_ctx (&ctx, resblock); } void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) { /* When we already have some bits in our internal buffer concatenate both inputs first. */ if (ctx->buflen != 0) { size_t left_over = ctx->buflen; size_t add = 128 - left_over > len ? len : 128 - left_over; memcpy (&ctx->buffer[left_over], buffer, add); ctx->buflen += add; if (ctx->buflen > 64) { md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); ctx->buflen &= 63; /* The regions in the following copy operation cannot overlap. */ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], ctx->buflen); } buffer = (const char *) buffer + add; len -= add; } /* Process available complete blocks. */ if (len >= 64) { #if !_STRING_ARCH_unaligned /* To check alignment gcc has an appropriate operator. Other compilers don't. */ # if __GNUC__ >= 2 # define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0) # else # define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0) # endif if (UNALIGNED_P (buffer)) while (len > 64) { md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); buffer = (const char *) buffer + 64; len -= 64; } else #endif { md5_process_block (buffer, len & ~63, ctx); buffer = (const char *) buffer + (len & ~63); len &= 63; } } /* Move remaining bytes in internal buffer. */ if (len > 0) { size_t left_over = ctx->buflen; memcpy (&ctx->buffer[left_over], buffer, len); left_over += len; if (left_over >= 64) { md5_process_block (ctx->buffer, 64, ctx); left_over -= 64; memcpy (ctx->buffer, &ctx->buffer[64], left_over); } ctx->buflen = left_over; } } /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /* Process LEN bytes of BUFFER, accumulating context into CTX. It is assumed that LEN % 64 == 0. */ void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) { md5_uint32 correct_words[16]; const md5_uint32 *words = buffer; size_t nwords = len / sizeof (md5_uint32); const md5_uint32 *endp = words + nwords; md5_uint32 A = ctx->A; md5_uint32 B = ctx->B; md5_uint32 C = ctx->C; md5_uint32 D = ctx->D; /* First increment the byte count. RFC 1321 specifies the possible length of the file up to 2^64 bits. Here we only compute the number of bytes. Do a double word increment. */ ctx->total[0] += len; if (ctx->total[0] < len) ++ctx->total[1]; /* Process all bytes in the buffer with 64 bytes in each round of the loop. */ while (words < endp) { md5_uint32 *cwp = correct_words; md5_uint32 A_save = A; md5_uint32 B_save = B; md5_uint32 C_save = C; md5_uint32 D_save = D; /* First round: using the given function, the context and a constant the next context is computed. Because the algorithms processing unit is a 32-bit word and it is determined to work on words in little endian byte order we perhaps have to change the byte order before the computation. To reduce the work for the next steps we store the swapped words in the array CORRECT_WORDS. */ #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ ++words; \ CYCLIC (a, s); \ a += b; \ } \ while (0) /* It is unfortunate that C does not provide an operator for cyclic rotation. Hope the C compiler is smart enough. */ #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) /* Before we start, one word to the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 */ /* Round 1. */ OP (A, B, C, D, 7, 0xd76aa478); OP (D, A, B, C, 12, 0xe8c7b756); OP (C, D, A, B, 17, 0x242070db); OP (B, C, D, A, 22, 0xc1bdceee); OP (A, B, C, D, 7, 0xf57c0faf); OP (D, A, B, C, 12, 0x4787c62a); OP (C, D, A, B, 17, 0xa8304613); OP (B, C, D, A, 22, 0xfd469501); OP (A, B, C, D, 7, 0x698098d8); OP (D, A, B, C, 12, 0x8b44f7af); OP (C, D, A, B, 17, 0xffff5bb1); OP (B, C, D, A, 22, 0x895cd7be); OP (A, B, C, D, 7, 0x6b901122); OP (D, A, B, C, 12, 0xfd987193); OP (C, D, A, B, 17, 0xa679438e); OP (B, C, D, A, 22, 0x49b40821); /* For the second to fourth round we have the possibly swapped words in CORRECT_WORDS. Redefine the macro to take an additional first argument specifying the function to use. */ #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ CYCLIC (a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP (FG, A, B, C, D, 1, 5, 0xf61e2562); OP (FG, D, A, B, C, 6, 9, 0xc040b340); OP (FG, C, D, A, B, 11, 14, 0x265e5a51); OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP (FG, A, B, C, D, 5, 5, 0xd62f105d); OP (FG, D, A, B, C, 10, 9, 0x02441453); OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); OP (FG, D, A, B, C, 14, 9, 0xc33707d6); OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); OP (FG, B, C, D, A, 8, 20, 0x455a14ed); OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP (FG, C, D, A, B, 7, 14, 0x676f02d9); OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP (FH, A, B, C, D, 5, 4, 0xfffa3942); OP (FH, D, A, B, C, 8, 11, 0x8771f681); OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); OP (FH, B, C, D, A, 14, 23, 0xfde5380c); OP (FH, A, B, C, D, 1, 4, 0xa4beea44); OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); OP (FH, B, C, D, A, 6, 23, 0x04881d05); OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP (FI, A, B, C, D, 0, 6, 0xf4292244); OP (FI, D, A, B, C, 7, 10, 0x432aff97); OP (FI, C, D, A, B, 14, 15, 0xab9423a7); OP (FI, B, C, D, A, 5, 21, 0xfc93a039); OP (FI, A, B, C, D, 12, 6, 0x655b59c3); OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP (FI, C, D, A, B, 10, 15, 0xffeff47d); OP (FI, B, C, D, A, 1, 21, 0x85845dd1); OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP (FI, C, D, A, B, 6, 15, 0xa3014314); OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); OP (FI, A, B, C, D, 4, 6, 0xf7537e82); OP (FI, D, A, B, C, 11, 10, 0xbd3af235); OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP (FI, B, C, D, A, 9, 21, 0xeb86d391); /* Add the starting values of the context. */ A += A_save; B += B_save; C += C_save; D += D_save; } /* Put checksum in context given as argument. */ ctx->A = A; ctx->B = B; ctx->C = C; ctx->D = D; } sane-backends-1.0.27/lib/alloca.c0000664000175000017500000003345312112021330013360 00000000000000/* alloca.c -- allocate automatically reclaimed memory (Mostly) portable public-domain implementation -- D A Gwyn This implementation of the PWB library alloca function, which is used to allocate space off the run-time stack so that it is automatically reclaimed upon procedure exit, was inspired by discussions with J. Q. Johnson of Cornell. J.Otto Tennant contributed the Cray support. There are some preprocessor constants that can be defined when compiling for your specific system, for improved efficiency; however, the defaults should be okay. The general concept of this implementation is to keep track of all alloca-allocated blocks, and reclaim any that are found to be deeper in the stack than the current invocation. This heuristic does not reclaim storage as soon as it becomes invalid, but it will do so eventually. As a special case, alloca(0) reclaims storage without allocating any. It is a good idea to use alloca(0) in your main control loop, etc. to force garbage collection. */ #ifdef HAVE_CONFIG_H #include "../include/sane/config.h" #endif #ifndef HAVE_ALLOCA #include "lalloca.h" #ifdef emacs #include "blockinput.h" #endif /* If compiling with GCC 2, this file's not needed. */ #if !defined (__GNUC__) || __GNUC__ < 2 /* If someone has defined alloca as a macro, there must be some other way alloca is supposed to work. */ #ifndef alloca #ifdef emacs #ifdef static /* actually, only want this if static is defined as "" -- this is for usg, in which emacs must undefine static in order to make unexec workable */ #ifndef STACK_DIRECTION you lose -- must know STACK_DIRECTION at compile-time #endif /* STACK_DIRECTION undefined */ #endif /* static */ #endif /* emacs */ /* If your stack is a linked list of frames, you have to provide an "address metric" ADDRESS_FUNCTION macro. */ #if defined (CRAY) && defined (CRAY_STACKSEG_END) long i00afunc (); #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) #else #define ADDRESS_FUNCTION(arg) &(arg) #endif #if __STDC__ typedef void *pointer; #else typedef char *pointer; #endif #define NULL 0 /* Different portions of Emacs need to call different versions of malloc. The Emacs executable needs alloca to call xmalloc, because ordinary malloc isn't protected from input signals. On the other hand, the utilities in lib-src need alloca to call malloc; some of them are very simple, and don't have an xmalloc routine. Non-Emacs programs expect this to call xmalloc. Callers below should use malloc. */ extern pointer malloc (); /* Define STACK_DIRECTION if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #ifndef STACK_DIRECTION #define STACK_DIRECTION 0 /* Direction unknown. */ #endif #if STACK_DIRECTION != 0 #define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ #else /* STACK_DIRECTION == 0; need run-time code. */ static int stack_dir; /* 1 or -1 once known. */ #define STACK_DIR stack_dir static void find_stack_direction () { static char *addr = NULL; /* Address of first `dummy', once known. */ auto char dummy; /* To get stack address. */ if (addr == NULL) { /* Initial entry. */ addr = ADDRESS_FUNCTION (dummy); find_stack_direction (); /* Recurse once. */ } else { /* Second entry. */ if (ADDRESS_FUNCTION (dummy) > addr) stack_dir = 1; /* Stack grew upward. */ else stack_dir = -1; /* Stack grew downward. */ } } #endif /* STACK_DIRECTION == 0 */ /* An "alloca header" is used to: (a) chain together all alloca'ed blocks; (b) keep track of stack depth. It is very important that sizeof(header) agree with malloc alignment chunk size. The following default should work okay. */ #ifndef ALIGN_SIZE #define ALIGN_SIZE sizeof(double) #endif typedef union hdr { char align[ALIGN_SIZE]; /* To force sizeof(header). */ struct { union hdr *next; /* For chaining headers. */ char *deep; /* For stack depth measure. */ } h; } header; static header *last_alloca_header = NULL; /* -> last alloca header. */ /* Return a pointer to at least SIZE bytes of storage, which will be automatically reclaimed upon exit from the procedure that called alloca. Originally, this space was supposed to be taken from the current stack frame of the caller, but that method cannot be made to work for some implementations of C, for example under Gould's UTX/32. */ pointer alloca (size) unsigned size; { auto char probe; /* Probes stack depth: */ register char *depth = ADDRESS_FUNCTION (probe); #if STACK_DIRECTION == 0 if (STACK_DIR == 0) /* Unknown growth direction. */ find_stack_direction (); #endif /* Reclaim garbage, defined as all alloca'd storage that was allocated from deeper in the stack than currently. */ { register header *hp; /* Traverses linked list. */ #ifdef emacs BLOCK_INPUT; #endif for (hp = last_alloca_header; hp != NULL;) if ((STACK_DIR > 0 && hp->h.deep > depth) || (STACK_DIR < 0 && hp->h.deep < depth)) { register header *np = hp->h.next; free ((pointer) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ last_alloca_header = hp; /* -> last valid storage. */ #ifdef emacs UNBLOCK_INPUT; #endif } if (size == 0) return NULL; /* No allocation required. */ /* Allocate combined header + user data storage. */ { register pointer new = malloc (sizeof (header) + size); /* Address of header. */ ((header *) new)->h.next = last_alloca_header; ((header *) new)->h.deep = depth; last_alloca_header = (header *) new; /* User storage begins just after header. */ return (pointer) ((char *) new + sizeof (header)); } } #if defined (CRAY) && defined (CRAY_STACKSEG_END) #ifdef DEBUG_I00AFUNC #include #endif #ifndef CRAY_STACK #define CRAY_STACK #ifndef CRAY2 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ struct stack_control_header { long shgrow:32; /* Number of times stack has grown. */ long shaseg:32; /* Size of increments to stack. */ long shhwm:32; /* High water mark of stack. */ long shsize:32; /* Current size of stack (all segments). */ }; /* The stack segment linkage control information occurs at the high-address end of a stack segment. (The stack grows from low addresses to high addresses.) The initial part of the stack segment linkage control information is 0200 (octal) words. This provides for register storage for the routine which overflows the stack. */ struct stack_segment_linkage { long ss[0200]; /* 0200 overflow words. */ long sssize:32; /* Number of words in this segment. */ long ssbase:32; /* Offset to stack base. */ long:32; long sspseg:32; /* Offset to linkage control of previous segment of stack. */ long:32; long sstcpt:32; /* Pointer to task common address block. */ long sscsnm; /* Private control structure number for microtasking. */ long ssusr1; /* Reserved for user. */ long ssusr2; /* Reserved for user. */ long sstpid; /* Process ID for pid based multi-tasking. */ long ssgvup; /* Pointer to multitasking thread giveup. */ long sscray[7]; /* Reserved for Cray Research. */ long ssa0; long ssa1; long ssa2; long ssa3; long ssa4; long ssa5; long ssa6; long ssa7; long sss0; long sss1; long sss2; long sss3; long sss4; long sss5; long sss6; long sss7; }; #else /* CRAY2 */ /* The following structure defines the vector of words returned by the STKSTAT library routine. */ struct stk_stat { long now; /* Current total stack size. */ long maxc; /* Amount of contiguous space which would be required to satisfy the maximum stack demand to date. */ long high_water; /* Stack high-water mark. */ long overflows; /* Number of stack overflow ($STKOFEN) calls. */ long hits; /* Number of internal buffer hits. */ long extends; /* Number of block extensions. */ long stko_mallocs; /* Block allocations by $STKOFEN. */ long underflows; /* Number of stack underflow calls ($STKRETN). */ long stko_free; /* Number of deallocations by $STKRETN. */ long stkm_free; /* Number of deallocations by $STKMRET. */ long segments; /* Current number of stack segments. */ long maxs; /* Maximum number of stack segments so far. */ long pad_size; /* Stack pad size. */ long current_address; /* Current stack segment address. */ long current_size; /* Current stack segment size. This number is actually corrupted by STKSTAT to include the fifteen word trailer area. */ long initial_address; /* Address of initial segment. */ long initial_size; /* Size of initial segment. */ }; /* The following structure describes the data structure which trails any stack segment. I think that the description in 'asdef' is out of date. I only describe the parts that I am sure about. */ struct stk_trailer { long this_address; /* Address of this block. */ long this_size; /* Size of this block (does not include this trailer). */ long unknown2; long unknown3; long link; /* Address of trailer block of previous segment. */ long unknown5; long unknown6; long unknown7; long unknown8; long unknown9; long unknown10; long unknown11; long unknown12; long unknown13; long unknown14; }; #endif /* CRAY2 */ #endif /* not CRAY_STACK */ #ifdef CRAY2 /* Determine a "stack measure" for an arbitrary ADDRESS. I doubt that "lint" will like this much. */ static long i00afunc (long *address) { struct stk_stat status; struct stk_trailer *trailer; long *block, size; long result = 0; /* We want to iterate through all of the segments. The first step is to get the stack status structure. We could do this more quickly and more directly, perhaps, by referencing the $LM00 common block, but I know that this works. */ STKSTAT (&status); /* Set up the iteration. */ trailer = (struct stk_trailer *) (status.current_address + status.current_size - 15); /* There must be at least one stack segment. Therefore it is a fatal error if "trailer" is null. */ if (trailer == 0) abort (); /* Discard segments that do not contain our argument address. */ while (trailer != 0) { block = (long *) trailer->this_address; size = trailer->this_size; if (block == 0 || size == 0) abort (); trailer = (struct stk_trailer *) trailer->link; if ((block <= address) && (address < (block + size))) break; } /* Set the result to the offset in this segment and add the sizes of all predecessor segments. */ result = address - block; if (trailer == 0) { return result; } do { if (trailer->this_size <= 0) abort (); result += trailer->this_size; trailer = (struct stk_trailer *) trailer->link; } while (trailer != 0); /* We are done. Note that if you present a bogus address (one not in any segment), you will get a different number back, formed from subtracting the address of the first block. This is probably not what you want. */ return (result); } #else /* not CRAY2 */ /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. Determine the number of the cell within the stack, given the address of the cell. The purpose of this routine is to linearize, in some sense, stack addresses for alloca. */ static long i00afunc (long address) { long stkl = 0; long size, pseg, this_segment, stack; long result = 0; struct stack_segment_linkage *ssptr; /* Register B67 contains the address of the end of the current stack segment. If you (as a subprogram) store your registers on the stack and find that you are past the contents of B67, you have overflowed the segment. B67 also points to the stack segment linkage control area, which is what we are really interested in. */ stkl = CRAY_STACKSEG_END (); ssptr = (struct stack_segment_linkage *) stkl; /* If one subtracts 'size' from the end of the segment, one has the address of the first word of the segment. If this is not the first segment, 'pseg' will be nonzero. */ pseg = ssptr->sspseg; size = ssptr->sssize; this_segment = stkl - size; /* It is possible that calling this routine itself caused a stack overflow. Discard stack segments which do not contain the target address. */ while (!(this_segment <= address && address <= stkl)) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); #endif if (pseg == 0) break; stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; this_segment = stkl - size; } result = address - this_segment; /* If you subtract pseg from the current end of the stack, you get the address of the previous stack segment's end. This seems a little convoluted to me, but I'll bet you save a cycle somewhere. */ while (pseg != 0) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o\n", pseg, size); #endif stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; result += size; } return (result); } #endif /* not CRAY2 */ #endif /* CRAY */ #endif /* no alloca */ #endif /* not GCC version 2 */ #endif /* !HAVE_ALLOCA */ sane-backends-1.0.27/lib/strdup.c0000664000175000017500000000214712112021330013442 00000000000000/* Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../include/sane/config.h" #include #include #ifndef HAVE_STRDUP char * strdup (const char * s) { char *clone; size_t size; size = strlen (s) + 1; clone = malloc (size); memcpy (clone, s, size); return clone; } #endif /* !HAVE_STRDUP */ sane-backends-1.0.27/lib/strndup.c0000664000175000017500000000216612112021330013621 00000000000000/* Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../include/sane/config.h" #ifndef HAVE_STRNDUP #include #include #include char * strndup (const char * s, size_t n) { char *clone; clone = malloc (n + 1); strncpy (clone, s, n); clone[n] = '\0'; return clone; } #endif /* !HAVE_STRNDUP */ sane-backends-1.0.27/lib/usleep.c0000664000175000017500000000320712112021330013414 00000000000000/* Copyright (C) 1992 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "../include/sane/config.h" #ifndef HAVE_USLEEP #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef apollo # include # include static time_$clock_t DomainTime100mS = { 0, 100000/4 }; static status_$t DomainStatus; #endif /* Sleep USECONDS microseconds, or until a previously set timer goes off. */ unsigned int usleep (unsigned int useconds) { #ifdef apollo /* The usleep function does not work under the SYS5.3 environment. Use the Domain/OS time_$wait call instead. */ time_$wait (time_$relative, DomainTime100mS, &DomainStatus); #else struct timeval delay; delay.tv_sec = 0; delay.tv_usec = useconds; select (0, 0, 0, 0, &delay); return 0; #endif } #endif /* !HAVE_USLEEP */ sane-backends-1.0.27/lib/sleep.c0000664000175000017500000000117712617742237013265 00000000000000#include "../include/sane/config.h" #ifndef HAVE_SLEEP #ifdef HAVE_WINDOWS_H #include #endif unsigned int sleep(unsigned int seconds) { #ifdef HAVE_WINDOWS_H Sleep(seconds*1000); return 0; #else int rc = 0; /* WARNING: Not all platforms support usleep() for more than 1 * second. Assuming if they do not have POSIX sleep then they * do not have POSIX usleep() either and are using our internal * version which can support it. If it fails, need to add an OS * specific replacement like Sleep for Windows. */ if (usleep(seconds*1000000)) rc = 1; return rc; #endif } #endif sane-backends-1.0.27/lib/Makefile.am0000664000175000017500000000071112775312262014032 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. AM_CPPFLAGS += -I. -I$(top_builddir)/include -I$(top_srcdir)/include noinst_LTLIBRARIES = liblib.la liblib_la_SOURCES = md5.c liblib_la_CPPFLAGS = -I$(top_srcdir)/include liblib_la_LIBADD = $(LTALLOCA) $(LTLIBOBJS) sane-backends-1.0.27/lib/vsyslog.c0000664000175000017500000000043612617742237013660 00000000000000#include "../include/sane/config.h" #ifndef HAVE_VSYSLOG #include #include void vsyslog(int priority, const char *format, va_list args) { char buf[1024]; vsnprintf(buf, sizeof(buf), format, args); syslog(priority, "%s", buf); } #endif /* !HAVE_VSYSLOG */ sane-backends-1.0.27/lib/strcasestr.c0000664000175000017500000000566212775312262014351 00000000000000/* Return the offset of one string within another. Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * My personal strstr() implementation that beats most other algorithms. * Until someone tells me otherwise, I assume that this is the * fastest implementation of strstr() in C. * I deliberately chose not to comment it. You should have at least * as much fun trying to understand it, as I had to write it :-). * * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */ /* added strcasestr support, davidm@lineo.com */ #include "../include/sane/config.h" #ifndef HAVE_STRCASESTR #if defined HAVE_STRING_H # include #endif typedef unsigned chartype; #include #define VAL(x) tolower(x) char * strcasestr ( const char *phaystack, const char *pneedle) { register const unsigned char *haystack, *needle; register chartype b, c; haystack = (const unsigned char *) phaystack; needle = (const unsigned char *) pneedle; b = *needle; if (b != '\0') { haystack--; /* possible ANSI violation */ do { c = *++haystack; if (c == '\0') goto ret0; } while (VAL(c) != VAL(b)); c = *++needle; if (c == '\0') goto foundneedle; ++needle; goto jin; for (;;) { register chartype a; register const unsigned char *rhaystack, *rneedle; do { a = *++haystack; if (a == '\0') goto ret0; if (VAL(a) == VAL(b)) break; a = *++haystack; if (a == '\0') goto ret0; shloop:;} while (VAL(a) != VAL(b)); jin:a = *++haystack; if (a == '\0') goto ret0; if (VAL(a) != VAL(c)) goto shloop; rhaystack = haystack-- + 1; rneedle = needle; a = *rneedle; if (VAL(*rhaystack) == VAL(a)) do { if (a == '\0') goto foundneedle; ++rhaystack; a = *++needle; if (VAL(*rhaystack) != VAL(a)) break; if (a == '\0') goto foundneedle; ++rhaystack; a = *++needle; } while (VAL(*rhaystack) == VAL(a)); needle = rneedle; /* took the register-poor approach */ if (a == '\0') break; } } foundneedle: return (char *) haystack; ret0: return 0; } #endif sane-backends-1.0.27/lib/getopt.c0000664000175000017500000010351712112021330013426 00000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ # include #if !defined(HAVE_GETOPT_H) || !defined(HAVE_GETOPT_LONG) /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #if 0 #ifdef HAVE_CONFIG_H # include #endif #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. */ # if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC # include # ifndef _ # define _(msgid) gettext (msgid) # endif # else # define _(msgid) (msgid) # endif # if defined _LIBC && defined USE_IN_LIBIO # include # endif #endif #ifndef attribute_hidden # define attribute_hidden #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "../include/lgetopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized attribute_hidden; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #else # if HAVE_STRING_H # include # else # include # endif /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Stored original parameters. XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ extern int __libc_argc; extern char **__libc_argv; /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ # ifdef USE_NONOPTION_FLAGS /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; # endif # ifdef USE_NONOPTION_FLAGS # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } # else # define SWAP_FLAGS(ch1, ch2) # endif #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #if defined _LIBC && defined USE_NONOPTION_FLAGS if (posixly_correct == NULL && argc == __libc_argc && argv == __libc_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { int print_errors = opterr; if (optstring[0] == ':') print_errors = 0; if (argc < 1) return -1; optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); #endif } nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (argv[optind - 1][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("\ %s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #else fprintf (stderr, _("\ %s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #endif } else { /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("\ %s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); #else fprintf (stderr, _("\ %s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #endif } nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); #endif } nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (argv[optind][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); #else fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); #endif } else { /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); #else fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #endif } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; int n; #endif if (posixly_correct) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: illegal option -- %c\n"), argv[0], c); #else fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); #endif } else { #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: invalid option -- %c\n"), argv[0], c); #else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); #endif } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #endif } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option requires an argument -- %c\n"), argv[0], c) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); #endif } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); #endif } nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); #endif } nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); #endif } nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (print_errors) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO char *buf; if (__asprintf (&buf, _("\ %s: option requires an argument -- %c\n"), argv[0], c) >= 0) { if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); free (buf); } #else fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); #endif } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ #endif /* !HAVE_GETOPT_LONG */ sane-backends-1.0.27/AUTHORS0000664000175000017500000002275313072310420012273 00000000000000Authors of the SANE standard: Andreas Beck and David Mosberger Backends: abaton: David Huggins-Daines agfafocus: Karl Anders Øygard apple: Milon Firikis artec: Chris Pinkham artec_eplus48u:Sergey Vlasov, Andreas Nowack, David Stevenson, and Michael Herder as6e: Eugene S. Weiss avision: Meino Christian Cramer, René Rebe (*) bh: Tom Martone canon: Helmut Koeberle, Manuel Panea, and Markus Mertinat Mitsuru Okaniwa, Ulrich Deiters (*) canon630u: Nathan Rutman canon_dr: m. allan noah (*) canon_pp: Matthew Duggan, Simon Krix cardscan: m. allan noah (*) coolscan: Didier Carlier, Andreas Rick coolscan2: Andras Major coolscan3: Alessandro Zummo dc25: Peter Fales dc210: Brian J. Murrell dc240: Peter Fales dell1600n_net: Jon Chambers dll: David Mosberger dmc: David F. Skoll epjitsu: m. allan noah (*) epson: Karl Heinz Kremer epson2: Alessandro Zummo epsonds: Alessandro Zummo fujitsu: Randolph Bentson, Frederik Ramm, Oliver Schirrmeister, m. allan noah (*) genesys: Henning Geinitz, Gerhard Jaeger (*), Stéphane Voltz, Pierre Willenbrock gphoto2: Peter Fales gt68xx: Sergey Vlasov, Andreas Nowack, David Stevenson, and Henning Geinitz hp: Peter Kirchgessner (*) Geoffrey Dairiki hp3500: Troy Rollo (*) hp3900: Jonathan Bravo Lopez hp4200: Adrian Perez Jorge, Andrew John Lewis, Arnar Mar Hrafnkelsson, Frank Zago, Henning Geinitz hp5400: Martijn van Oosterhout, Thomas Soumarmon hp5590: Ilia Sotnikov (*) hpljm1005: Philippe Rétornaz hpsj5s: Max Vorobiev hs2p: Jeremy Johnson (*) ibm: M.F., Henning Geinitz kodak: m. allan noah (*) kodakaio: Paul Newall (*) kvs1025: Tao Zhang, m. allan noah (*) kvs20xx: unknown, m. allan noah (*) kvs40xx: unknown, m. allan noah (*) leo: Frank Zago lexmark: Fred Odendaal, Stéphane Voltz ma1509: Henning Geinitz magicolor: Reinhold Kainhofer(based on epson2 backend) matsushita: Frank Zago microtek: Matthew Marjanovic microtek2: Bernd Schroeder, Karsten Festag mustek: Andreas Bolsch, David Mosberger, Andreas Czechanowski, Henning Geinitz, and James Perry. mustek_pp: Jochen Eisinger, Eddy De Greef mustek_usb: Tom Wang and Henning Geinitz mustek_usb2: Roy Zhou, Jack Xu, Vinci Cen, and Henning Geinitz nec: Kazuya Fukuda net: Andreas Beck, David Mosberger, Julien Blache niash: Ullrich Sigwanz, Bertrik Sikken p5: Stéphane Voltz pie: Simon Munton pieusb: Jan Vleeshouwers, Michael Rickmann, Klaus Kämpf pint: Gordon Matzigkeit pixma: Wittawat Yamwong Nicolas Martin Louis Lagendijk (*) Dennis Lou Rolf Bensch (*) plustek: Gerhard Jaeger (*) plustek_pp: Rick Bronson (former pp driver-code), Gerhard Jaeger (*) pnm: Andreas Beck, Gordon Matzigkeit, David Mosberger, Michael Herder, and Henning Geinitz qcam: Scott Laird (original driver), David Mosberger (SANE backend), despeckling filter by Patrick Reynolds, B&W fixes by Andrew Kuchling ricoh: Feico W. Dillema rts8891: Stéphane Voltz s9036: Ingo Schneider sceptre: Frank Zago sharp: Kazuya Fukuda and Abel Deuring sm3600: Marian Eichholz and Glenn Ramsey sm3840: Earle F. Philhower III snapscan: Kevin Charter, Franck Schneider, Michel Roelofs, Sebastien Sable, Henrik Johansson, Chris Bagwell, and Oliver Schwartz (*) sp15c: Randolph Bentson st400: Ingo Wilken stv680: Gerard Klaver tamarack: Rogier Wolff teco1: Frank Zago teco2: Frank Zago, Gerard Klaver teco3: Frank Zago test: Henning Geinitz u12: Gerhard Jaeger (*) umax: Oliver Rauch and Michael K. Johnson umax1220u: Marcio L. Teixeira, Patrick Lessard umax_pp: Stéphane Voltz v4l: Juergen G. Schimmer, and Henning Geinitz xerox_mfp: Alex Belkin (*) Frontends: jscanimage: Jeff Freedman and Guido Muesch saned: Andreas Beck, David Mosberger, Julien Blache scanimage: Andreas Beck, David Mosberger, Gordon Matzigkeit, m. allan noah (*), Julien Blache, Stéphane Voltz tstbackend: Frank Zago Sanei internal code: Adrian Perez Jorge, Andreas Beck, Andreas Czechanowski, Christian Bucher, David Mosberger-Tang, Frank Zago, Henning Geinitz, Jeff Freedman, Jochen Eisinger, Marcio Teixeira, Yuri Dario, Gerhard Jaeger (*), m. allan noah (*) Java API: Jeff Freedman Miscellaneous coding: Julien Blache, Mattias Ellert, Petter Reinholdtsen, Chris Bagwell, Olaf Meeuwissen (*) Translators: Giuseppe Sacco (*) (*) Maintainer with Git repository write access Please also read the file PROJECTS for projects that are planned or not yet included into the SANE distribution. Email addresses: Abel Deuring Alessandro Zummo Alex Belkin Andras Major Andreas Beck Andreas Bolsch Andreas Czechanowski Andreas Nowack Andreas Rick Andrew Kuchling Bernd Schroeder Bertrik Sikken Brian J. Murrell Chris Bagwell Chris Pinkham Christian Bucher David Etherton David F. Skoll David Huggins-Daines David Mosberger David Stevenson Didier Carlier Earle F. Philhower III Eddy De Greef Eugene S. Weiss Feico W. Dillema Franck Schneider Frank Zago Fred Odendaal Frederik Ramm Gerard Klaver Gerhard Jaeger Giuseppe Sacco Glenn Ramsey Gordon Matzigkeit Guido Muesch Helmut Koeberle Henning Geinitz Henrik Johansson Ilia Sotnikov Ingo Schneider Ingo Wilken James Perry Jeff Freedman Jochen Eisinger Jon Chambers Jonathan Bravo Lopez Juergen G. Schimmer Julien Blache Jan Vleeshouwers Karl Anders Øygard Karl Heinz Kremer Karsten Festag Kazuhiro Sasayama Kazuya Fukuda Kevin Charter Klaus Kämpf Louis Lagendijk M.F. Manuel Panea Marcio Teixeira Marian Eichholz Markus Mertinat Martijn van Oosterhout Matthew Duggan Matthew Marjanovic Mattias Ellert Max Vorobiev Meino Christian Cramer Michael Herder Michael K. Johnson Michael Rickmann Michel Roelofs Milon Firikis Mitsuru Okaniwa Nathan Rutman Nicolas Martin Olaf Meeuwissen Oliver Rauch Oliver Schirrmeister Oliver Schwartz Patrick Lessard Patrick Reynolds Paul Newall Peter Fales Peter Kirchgessner Petter Reinholdtsen Pierre Willenbrock Randolph Bentson Reinhold Kainhofer Rene Rebe Roger Wolff Rolf Bensch Roy Zhou Sebastien Sable Sergey Vlasov Simon Krix Simon Munton Stéphane Voltz Thomas Soumarmon Tom Martone Tom Wang Tristan Tarrant Troy Rollo Ullrich Sigwanz Ulrich Deiters Wittawat Yamwong m. allan noah sane-backends-1.0.27/README.hp-ux0000664000175000017500000000771112112021330013131 00000000000000Building and Installing SANE on HP-UX ------------------------------------- This file contains some notes on building and installing SANE on HP-UX. It tells you which compiler switches to use, how to find out to which controller card your scanner is connected, and how to create a device file for it. Building SANE ------------- On HP-UX, SANE can be built using either the HP ANSI C compiler or GCC. For GCC, no special arguments to configure are necessary. For the HP compiler, invoke configure like this: CC=cc CFLAGS="-Ae -O" ./configure Higher optimization levels than -O (equivalent to +O2) may fail to compile correctly. If you're using the HP compiler on 64-bit HP-UX 11, you must build 64-bit executables: CC=cc CFLAGS="-Ae +DA2.0W -O" ./configure Some of the make files use GNU extensions, so you have to use gmake (GNU make). Gmake binaries are available from the HP-UX Porting and Archive Centre and its mirror sites. Installing SANE --------------- The SCSI pass-through driver (sctl) must be enabled in your kernel, but it is by default. Naturally, the scanner must have a non-conflicting SCSI address and it must be connected to the right SCSI bus to work. You'll probably need to create a device file for your scanner. To do this, you'll need to know its SCSI address, and, if your machine has multiple SCSI controllers, the number of the one it's connected to. As root, you can use ioscan -f to find this information. For example, here's the partial ioscan output for a C200: Class I H/W Path Driver S/W State H/W Type Description ============================================================================== [...] ext_bus 0 8/0/19/0 c720 CLAIMED INTERFACE Ultra Wide SCSI target 0 8/0/19/0.6 tgt CLAIMED DEVICE disk 0 8/0/19/0.6.0 sdisk CLAIMED DEVICE IBM DDYS-T09170N target 1 8/0/19/0.7 tgt CLAIMED DEVICE ctl 0 8/0/19/0.7.0 sctl CLAIMED DEVICE Initiator [...] ext_bus 1 8/16/5 c720 CLAIMED INTERFACE Built-in SCSI target 4 8/16/5.1 tgt CLAIMED DEVICE unknown -1 8/16/5.1.0 UNCLAIMED UNKNOWN EPSON Perfection1640 target 2 8/16/5.2 tgt CLAIMED DEVICE disk 1 8/16/5.2.0 sdisk CLAIMED DEVICE TOSHIBA CD-ROM XM-5401TA target 3 8/16/5.7 tgt CLAIMED DEVICE ctl 1 8/16/5.7.0 sctl CLAIMED DEVICE Initiator [...] You can see that there are two SCSI controllers, Ultra Wide SCSI and Built-in SCSI (narrow single-ended). The I column shows the number of the controller card. Our scanner, an Epson Perfection 1640, is connected to controller 1, and has SCSI address 1 (that's the 1 in the H/W Path number). You can now create the device file using mknod(1M). In this example, the command would be: mknod /dev/rscsi/c1t1d0 c 203 0x011000 In the filename, c1 specifies controller 1, t1 is target 1 (i.e., the SCSI address), d0 (device 0) because it's the only device at that address. 203 is the major number of the sctl driver. In the minor number (0x011000), 01 again means controller 1, and the second one means SCSI address 1. See scsi_ctl(7) for details. For ease of use with SANE, I'd recommend to create a link to /dev/scanner, e.g., ln -s /dev/rscsi/c1t1d0 /dev/scanner To allow normal users to access the scanner, the best approach is probably to create a new group, say, "scanner", and make the scanner device file readable and writable for the group, e.g., chown bin:scanner /dev/rscsi/c1t1d0 chmod g+rw /dev/rscsi/c1t1d0 You would then add all users that are allowed to use the scanner to that group. If you haven't already done so, you should do ln -s /etc/group /etc/logingroup so that users are automatically in all groups to which they belong (and don't have to use newgrp(1)). sane-backends-1.0.27/COPYING0000664000175000017500000004312712112021330012245 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. sane-backends-1.0.27/README.aix0000664000175000017500000000067412112021330012652 00000000000000Under AIX, you'll need the generic SCSI device driver gsc written by Matthew Jacob (nice piece of work!). When you install this driver, copy the header file gscdds.h to /usr/include, as we look for it there. Find this driver under: ftp://ftp.feral.com/pub/aix/gsc.tar.gz ftp://ftp.thp.Uni-Duisburg.DE/pub/source/gsc.tar.gz A version for AIX 4.3.3 and AIX 5.1 is also available. http://www.zago.net/aix/gsc-1.1.tar.gz sane-backends-1.0.27/README.netbsd0000664000175000017500000000410512112021330013341 00000000000000SANE and NetBSD ---------------- Building: --------- Don't forget to use GNU make (gmake). E.g. "MAKE=gmake ./configure". SANE should compile and install out-of-the-box. SCSI-scanners: -------------- SANE only supports the generic /dev/uk? devices. /dev/ss? won't work. If your scanner is detected by the ss driver, disable the driver with the "config" utility or compile a new kernel without ss. Set a link /dev/scanner to /dev/uk0 (or whatever you use) and/or edit your backend's config file appropriately. Don't forget to set up permissions to the device file correctly for access by a non-root user (read/write). Auto-configuration using the "scsi *" lines in the config files doesn't work. Scanners with higher resolutions need bigger SCSI buffers. Therefore, edit sanei/sanei_scsi.c and look for these lines: #ifndef MAX_DATA # define MAX_DATA (32*1024) #endif Increase the buffer size to e.g. 128 * 1024. Recompile. USB-scanners: ------------- USB-Scanners are supported in principle. Using libusb is recommended. Problems when using libusb: Older kernels may need to be compiled WITHOUT DIAGNOSTIC. Disable it in the config file or use a GENERIC kernel without DIAGNOSTIC. If it is, you will get errors like "ugenioctl: USB_SET_TIMEOUT, no pipe". When using libusb, make sure, that /dev/ugen* and /dev/usb* devices are available. Use /dev/MAKEDEV to create them, if necessary. If you want to use libusb, disable the uscanner driver. Problems with uscanner driver: The uscanner driver also works (tested with the plustek backend). As the uscanner driver can't detect the vendor and product ids automatically, it's necessary to add the name of the device file to the backends's configuration file. Some backends also need the vendor and product id of the scanner. Some backends won't work with the uscanner driver becasue they need USB control messages. Use libusb instead. Parport-scanners: ----------------- I don't have any information about these. Please contact me or the SANE mailing list if you succeded in using one of these. 2003-04-24 Henning Meier-Geinitz sane-backends-1.0.27/sane-backends.lsm0000664000175000017500000000264612112021330014426 00000000000000Begin4 Title: sane-backends Version: _VERSION_ Entered-date: _DATE_ Description: SANE (Scanner Access Now Easy) is a universal scanner interface. SANE-BACKENDS comes complete with documentation, many backends, scanimage command line frontend, and networking support. For other/graphical frontends take a look at sane-frontends and XSane. Keywords: scanner, camera, flatbed, automatic document feeder (ADF), slides, diapositive, negative, film, transparency, CIS, CCD, network server & client, Java API & client Author: The SANE development team (sane-devel@lists.alioth.debian.org) (see AUTHORS for complete list) Maintained-by: kitno455@gmail.com (m. allan noah) Primary-site: ftp.sane-project.org /pub/sane/sane-backends-_VERSION_ _T_S_ kB sane-backends-_VERSION_.tar.gz _L_S_ kB sane-backends-_VERSION_.lsm Alternate-site: sunsite.unc.edu /pub/Linux/apps/graphics/capture Platforms: AIX, Digital Unix, HP Apollo Domain/OS, FreeBSD, HP-UX, IRIX, Linux (Alpha, m68k, SPARC, x86), NetBSD, OpenBSD, OpenStep (x86), SCO OpenServer 5.x (x86), OS/2, Solaris (SPARC, x86), SunOS. GNU make is needed. Copying-policy: GPL (programs), relaxed GPL (libraries), and public domain (SANE standard) End sane-backends-1.0.27/PROJECTS0000664000175000017500000000177712112021330012373 00000000000000PROJECTS (2005-10-03) Here is a list of projects that various people have expressed interest in. Before starting working on one of these projects, it may be a good idea to get in touch with the relevant people. Please also read the files AUTHORS and README for projects that are included into the SANE-package. For frontends, look at the sane-frontends package. For backends or stand-alone drivers, add a .desc file or add an entry to unsupported.desc. Status description --------- ---------------------------------------------------------------- wanted Somebody would like to have this feature but can't do it himself. planned Only plans but no code yet. wip Work in progress. There is (more or less) working code. For details, look at the web page or contact the author. SANE on non-Unix platforms: ---------------------------- OS/2 support (wip) http://home.tiscalinet.de/fbakan/sane-os2.htm Misc: ----- TWAIN interface for xsane-win32 (planned) Oliver Rauch sane-backends-1.0.27/README.openbsd0000664000175000017500000000476112112021330013524 00000000000000SANE and OpenBSD ---------------- Building: --------- Don't forget to use GNU make (gmake). E.g. "MAKE=gmake ./configure". SANE should compile and install out-of-the-box. If some libraries and headers (like libjpeg) are installed in /usr/local/, adding "-I/usr/local/include/ -L/usr/local/lib/" to the CPPFLAGS environment variable before running configure may be necessary to get them detected. Since release 3.9, SANE is available from OpenBSD ports. SCSI-scanners: -------------- SANE only supports the generic /dev/uk? devices. /dev/ss? won't work. If your scanner is detected by the ss driver, disable the driver with the "config" utility or compile a new kernel without ss. Set a link /dev/scanner to /dev/uk0 (or whatever you use) and/or edit your backend's config file appropriately. Don't forget to set up permissions to the device file correctly for access by a non-root user (read/write). USB-scanners: ------------- USB-Scanners are supported in principle since OpenBSD 2.9. The USB scanner driver "uscanner" and access over libusb is supported. To get your scanner detected by the uscanner driver, it may be necessary to add its vendor and device ids to the kernel and recompile (sys/devs/usb/uscanner.c). With OpenBSD 3.0 there is also a bug concerning uscanner that prevents accessing the /dev/uscanner devices. Get a newer kernel in this case. If your MAKEDEV won't make /dev/uscanner0 do it manually: "mknod /dev/uscanner0 c 77 0" for the first scanner. Edit your backend's configuration file appropriately. If you want to use libusb, your scanner should *not* be claimed by the uscanner driver. Also make sure that the ugen driver is NOT compiled with DIAGNOSTIC. If it is, you will get errors like "ugenioctl: USB_SET_TIMEOUT, no pipe". Make sure, that /dev/ugen* and /dev/usb* devices are available. Use /dev/MAKEDEV to create them, if necessary. For some backends you must use libusb. The uscanner driver won't work because automatic detection, control messages, or interrupt endpoints are needed. When using libusb, you need read/write permissions to ugen(4) (/dev/ugen*.*) and the usb(4) controller (/dev/usb*) your scanner is connected to. Consider adding a group usb and setting the device permissions using the hotplugd(8) attach and detach scripts. See tools/openbsd for an example. Parport-scanners: ----------------- I don't have any information about these. Please contact me or the SANE mailing list if you succeded in using one of these. 2005-12-23 Henning Meier-Geinitz sane-backends-1.0.27/NEWS0000664000175000017500000013363413110600265011725 00000000000000-*-Mode: outline-*- New with 1.0.27 (see Note 1), released 2017-05-22: * Significant enhancements to canon_dr, epjitsu, epsonds, fujitsu, genesys, hp3500, pixma and xerox-mfp backends. * Minor updates, bugfixes or scanners added in several backends. * 30+ new scanner models supported. * Made libusb-1.0 the default for USB support (see Note 2). * Switched code from C90 to C99 (Thanks to Volker Diels-Grabsch). * Updated Linux USB3 workaround (see Note 3). * Documentation and translation updates. * Bugfixes (Avahi, threading, USB, ICC/PNG/JPEG, etc). * Reduced compiler warnings, improved code (see Note 4). Note 1: There is no 1.0.26 release of sane-backends. That number was skipped so that our development version numbers would more clearly be an extension of the prior release. This should make packaging a little easier for our downstream users. Note 2: On all systems, the --enable-libusb* flags are now ignored. Instead, the --with-usb and --without-usb flags now control support. When neither is given, USB support will be enabled if possible and disabled otherwise. If --with-usb is requested but not possible, ./configure will fail. There is no support to prefer libusb-0.1 over libusb-1.0. When libusb-1.0 is not found, libusb-0.1 will be tried. Note 3: The Linux USB3 workaround which was added in version 1.0.25 is now disabled by default. If you have difficulty using a scanner which previously worked, or intermittent scanner availability, try setting the new environment variable SANE_USB_WORKAROUND=1 before starting your frontend. Note 4: A special thanks goes to Olaf Meeuwissen for picking up the janitorial duties in sane-backends. He has found and fixed a large number of long-standing bugs, curated our bug tracker, improved our build scripts and docs, and provided user support. Thank you Olaf! New with 1.0.25, released 2015-10-03: * New backends: epsonds (Epson DS, PX and WF series), pieusb (PIE and Reflecta film/slide scanners). * Support for JPG and PNG output format in scanimage. * Significant enhancements to avision, canon_dr, epjitsu, fujitsu, genesys, kodakaio and pixma backends. * Minor updates, bugfixes or scanners added in several backends. * 300 new scanner models supported. * Workaround for USB3 problems in Linux kernel. * Added code for IR functionality. * Documentation and translation updates. * Bugfixes (threading, networking, udev rules). New with 1.0.24, released 2013-09-30: * Significant enhancements to pixma, genesys, kodakaio, fujitsu, canon_dr. * Minor updates, bugfixes or scanners added in several backends. * Added new testsuite * 51 new scanner models supported. * USB support improvements. * Improved build system (mingw64, bug fixes, default pthread on Linux). * Documentation updates. * Bugfixes. New with 1.0.23, released 2012-08-19: * New backends: kvs40xx (Panasonic KV-S40xx), kodakaio (Kodak AiO ESP and Hero) * Significant enhancements to several backends. * 30 new scanner models supported. * V4L support improvements. * Improvements for builds on multiple platforms. * Improved udev rules. * Updated software deskew algorithm. * Documentation updates. * Bugfixes. New with 1.0.22, released 2011-02-13: * New backends: kvs20xx (Panasonic KV-S20xx), magicolor (Konica-Minolta ) * Significant enhancements to several backends. * More than 80 new scanner models supported. * Support many more networked scanners. * Added -A option to scanimage * Improved build system. * Improved USB support. * Improved udev rules. * Documentation updates. * Bugfixes. New with 1.0.21, released 2010-04-25: * New backends: kodak (Kodak i18xx), kvs1025 (Panasonic KV-S10xx), p5 (Primax PagePartner) * 224 more scanner models supported. * Many backends updated. * Improved compilation on uncommon platforms. * More consistent option naming. * Scanimage no longer writes image to tty. * Modern translation infrastructure. * Improved saned network daemon. * Internal SCSI, USB, threading, TCP & UDP code updates. * Updated HAL and udev support. * New sanei_magic image processing library. * Documentation updates. * Bugfixes. New with 1.0.20, released 2009-05-03: * New backends: canon_dr (Canon DR-series), coolscan3 (Nikon LS & Coolscan), rts8891 (Umax & HP 44xx), xerox_mfp (Samsung/Xerox/Dell MFPs) * Many backends updated. * 75 more scanner models supported. * New build system (thanks Chris and Olaf). * Avahi support (thanks Julien). * More network scanners supported * Epson backend deprecated, use epson2 * Coolscan2 backend deprecated, use coolscan3 * Internal SCSI, USB, threading, TCP & UDP code updates. * Updated HAL and udev support. * Improved saned configuration. * Scanimage updates. * Updated translations. * Documentation updates. * Bugfixes. New with 1.0.19, released 2008-02-10: * New backends: cardscan (Corex Cardscan 800c), epjitsu (Epson-based Fujitsu), epson2 (various Epson scanners), hp3900 (HP ScanJet 3970 and more), hp5590 (HP ScanJet 5590 and more), hpljm1005 (HP LaserJet M1005 and more), hs2p (Ricoh IS400 series) * Updated backends: abaton, agfafocus, apple, artec, artec_eplus48u, as6e, avision, canon, coolscan, coolscan2, dc25, dell1600n_net, dll, epson, fujitsu, genesys, gt68xx, hp3500, ibm, lexmark, microtek, microtek2, mustek, nec, net, pie, pint, pixma, plustek, plustek_pp, ricoh, s9036, sm3600, sm3840, snapscan, sp15c, st400, tamarack, teco2, test, u12, umax, umax1220u, umax_pp * Scanimage detects more chipsets. * Internal scsi, usb, tcp and udp code updates. * Basic HAL .fdi creation support * Build system updates. * Updated translations. * Documentation updates. * Bugfixes. New with 1.0.18, released 2006-07-02: * New backends: dell1600n_net (Dell 1600n), hp3500 (HP ScanJet 3500 series), pixma (Canon Pixma series), stv680 (Aiptek Pencam and similar). * Updated backends: avision, canon, dll, epson, fujitsu, genesys, gt68xx, microtek2, mustek_pp, niash, plustek, snapscan, sp15c, test, u12, umax1220u. * Scanimage batch mode fixes. * Scanner lists contain USB vendor/product ids and some statistics now. * Udev/hotplug lists are generated autmatically from the .desc files now. * Portability fixes (especially for DragonFlyBSD and HP/UX). * Build system updates. * Updated translations. * Documentation updates. * Bugfixes. New with 1.0.17, released 2005-12-18: * New backends: hp4200 (HP ScanJet 4200), lexmark (Lexmark X1100 series), mustek_usb2 (Mustek BearPaw 2448 TA Pro) * Updated backends: artec_eplus48u, avision, canon, epson, fujitsu, genesys, gt68xx, microtek2, mustek_pp, plustek, plustek_pp, sm3600, snapscan, umax_pp. * Hotplug/udev updates. * scanimage fixes. * sane-find-scanner finds more chipsets. * Build system fixes/updates. make now calls makedepend. * Several fixes in SANE internal functions (sanei). * Portability fixes (especially for MacOSX, FreeBSD, OpenBSD, OS/2). * Updated translations. * Documentation updates. * Bugfixes. New with 1.0.16, released 2005-08-07: * New backends: genesys, sm3840 * Updated backends: avision, canon, coolscan, epson, gphoto2, gt68xx, mustek, mustek_pp, niash, plustek, plustek_pp, qcam, sm3600, snapscan, teco2, umax_pp, v4l. * More functionality/fixes for sanei_usb and sanei_pp. * Added sanei_access to allow locking of SANE devices. * Hotplug updates. * scanimage updates. * Portability fixes (especially for OS/2, 64bit platforms, BeOS+ZETA). * Added Polish translation. Updated other translations. Fixed format strings. * Documentation updates. * Bugfixes. New with 1.0.15, released 2004-11-07: * New backends: niash. * Updated backends: agfafocus, artec_eplus48u.c, avision, canon, canon_pp, coolscan, dll, epson, fujitsu, gt68xx, hp, hp5400, leo, microtek2, mustek, mustek_pp, net, pie, plustek, plustek_pp, snapscan, sp15c, tamarack, teco2, umax, umax_pp, u12, v4l. * Portability fixes (especially for MacOS X, NetBSD, OS/2, 64 bit platforms). * sane-find-scanner detects more chipsets now. * Added Finnish translation. Updated other translations. * Several saned fixes. * Build system updates. * Documentation updates. * Bugfixes. New with 1.0.14, released 2004-05-01: * New backends: u12 * Updated backends: artec, artec_eplus48u, as6e, avision, canon630u, canon_pp, epson, fujitsu, gphoto2, gt68xx, hp, matsushita, mustek, mustek_pp, mustek_usb, plustek, plustek_pp, sm3600, snapscan, teco1, teco2, u12, umax, umax_pp, v4l. * Added scripts for USB hotplugging (Linux) * Added Danish translation. Updated other translations. * sane-find-scanner knows about more chipsets now. * Portability fixes (especially for MacOS X, NetBSD, OpenBSD, and OS/2). * Build system fixes. * Documentation updates. * Bugfixes. New with 1.0.13, released 2003-11-22: * New backends: mustek_pp_ccd (for Mustek parport CCD scanners), plustek_pp (for Plustek parport scanners, splitted from the plustek backend). * Updated backends: avision, canon630u, coolscan, epson, fujitsu, gphoto2, gt68xx, hp, hp5400, mustek, mustek_pp, pie, plustek, snapscan, teco2, test, umax, umax_pp. * New internal interface for parport scanners. * Networking (IPv6 + subnet support) fixes + updates. * sane-find-scanner can detect some USB scanner chipsets now. * Better support for threading. * Port to MS Windows (Cygwin). * Portability fixes (especially for FreeBSD, MacOS X, OS/2). * Build system improvements. * Added new (Bulgarian, Czech and Italian) and updated existing translations. * The level of support for scanners is now: unsupported, minimal, basic, good, complete or untested (instead of alpha, beta, stable). * Documentation updates. * Bugfixes. New with 1.0.12, released 2003-05-25: * New backends: hp5400 (Hewlett Packard 54XX series), ibm (IBM 2456, Ricoh IS-410, IS-420, and IS-430), and ma1509 (Mustek BearPaw 1200F). * Updated backends: apple, artec_eplus48u, as6e, avision, canon (FB1200S), canon630u, dc210, dc240, dll, epson, fujitsu (fi4220), gphoto2, gt68xx, hp, mustek, mustek_pp, mustek_usb, net, pie, plustek, snapscan (Agfa Arcus 1200, Epson Perfection 660), teco2 (Relisys AVEC II S3, Relisys APOLLO Express 3 and Primax Jewel 4800), test, umax, umax_pp. * Added IPv6 support for saned and net backend. * Added SCSI support for MacOS X. * Build system improvements. * USB access improvements. * Portability fixes (especially for Irix, MacOS X, OS/2 and Linux/m68k). * Added new (nl, no) and updated existing translations. * Documentation updates. * Bugfixes. New with 1.0.11, released 2003-02-09: * Security fixes for saned. New with 1.0.10, released 2003-02-01: * New backends: artec_eplus48u (Artec E+ 48U, Tevion/Medion MD 9693, Medion MD 9705, Trust Easy Webscan 19200), gt68xx (Artec Ultima 2000, some Mustek BearPaws and other GT6801/GT6816 based scanners). * Updated backends: avision, canon, coolscan2, canon_pp, dc210, dc240, dc25, dll, epson, gphoto2, hp, hpsj5s, microtek2, mustek, mustek_pp, plustek, sharp, snapscan, test, umax, umax_pp. * Improved SCSI and USB handling. * Portability fixes (especially for Linux/sparc64, MacOS X, OS/2, Tru64). * New translation system. All backends have translations for the standard options now. Added translations for Portuguese, Russian and Swedish. * Build system updates. * Various documentation updates. * Bugfixes. New with 1.0.9, released 2002-10-24: * New backends: hpsj5s (Hewlett-Packard ScanJet 5S parport scanner), teco2 (some Relisys/Primax SCSI flatbed scanners, models VM3575, VM6565, VM6586 and VM6575), teco3 (some Relisys/Piotech/Trust/Plustek SCSI flatbed scanners, model VM3552). * Updated backends: avision, canon_pp, coolscan2, dc240, dc25, epson, fujitsu, hp, leo, microtek, mustek, mustek_usb, pie, plustek, snapscan, teco1, test, umax, umax_pp, v4l. * sane-find-scanner finds more scanners and has more verbosity options now. * New tool to create gamma tables (gamma4scanimage). * Support for ICC profiles for scanimage. * USB scanner should work on all systems supported by libusb now. * Portability fixes (especially for big-endian sytems, Irix, OpenStep, OS/2, Solaris). * New and updated translations for various backends. * New system for generating lists of manufacturers/backends. * Various documentation updates. * Bugfixes. New with 1.0.8, released 2002-05-27: * New backends: canon_pp (Canon parport scanners), canon630u (CanoScan 630u + 636u), coolscan2 (Nikon Coolscan LS-30, LS-40 ED, LS-4000 ED, and LS-8000 ED), fujitsu (M3091, M3093, M3096 and similar scanners), leo (Leo/Across FS-1130 scanner), matsushita (Panasonic KV-SS scanners), sceptre (Sceptre VividScan S1200), teco1 (some Teco/Relisys flatbed scanners), test (test frontends and SANE installation). * Updated backends: avision, canon, dc240, dll, epson, gphoto2, mustek, mustek_pp, mustek_usb, nec, net, plustek, pnm, sharp, sm3600, snapscan, umax, umax_pp, v4l. * New translations for several backends (de, es, fr). * Networking supports hosts without working DNS now. * SCSI system ignores USB files and doesn't block (Linux). * New test frontend and backend for testing SANE. * Several build system improvements (e.g., new libtool, better make distclean, build only shared libs by default). * Portability fixes (especially for AIX, Linux (2.2, hppa, sparc), HP-UX, NetBSD, OPENSTEP, OS/2). * Better documentation of internal functions (sanei). * Various Documentation updates. * Bugfixes. New with 1.0.7, released 2002-02-04: * New backend: umax1220u (for UMAX Astra 1220U and 2000U scanners). * Updated backends: avision (v 1.0.15), dc240 (v 0.0), dc25 (v 1.2), dll (v 1.0.5), epson (v 1.0.219), gphoto2 (v 0.0), microtek2 (v 0.95), mustek (1.0.118), mustek_usb (v 1.0.10), plustek (v 0.41), pnm (v 1.0.4), sharp (v 0.32), snapscan (v 1.4.7), st400 (v 1.6), umax (v 1.0-32), umax_pp (v 1.0.6). * Added support for translating backend options. * Added support for USB control messages and lm983x and pv6830 chipsets. * Better documentation of internal functions (sanei). * Fixed several security issues with temporary files. * Fixed several issues in the networking code. * Portability fixes (especially for OS/2, FreeBSD, and OpenBSD). * Scanimage fixes concerning TIFF output and signal handling. * Documentation updates. * Bugfixes. New with 1.0.6, released 2001-11-05: * New backends: gphoto2 (backend for gphoto2 supported cameras), mustek_usb (for Mustek USB scanners 600CU, 1200CU(+), 1200UB). * Updated backends: dc240 (v 0.0), epson (v 0.2.12), hp (0.95), m3096g (v 1.11), microtek2 (v 0.95), mustek (v1.0-113), net (v 1.0.5), pie (1.0-7), pnm (1.0-2), snapscan (v 1.4.0), umax (1.0-31), umax_pp (1). * Added generic support for USB devices. * Added USB support to sane-find-scanner. * Code and documentation updates for HP UX compatibility. * Documentation updates. * Bugfixes. New with 1.0.5, released 2001-07-01: * New backends: bh (Bell+Howell Copiscan II series), dc240 (Kodak DC240 Digital Camera), sm3600 (Microtek ScanMaker 3600), umax_pp (Umax paralell port scanners). * Updated backends: artec (v0.5.16), dc25 (v1.2), dll (v1.0.3), epson (v0.2.08), hp (v0.94), microtek (v0.12.3), microtek2(v0.9), mustek (v1.0-107), nec (v0.12), net (v1.0.3), plustek (v0.39), pnm (v1.0.1), snapscan (v1.2), tamarack (v0.5), umax (v1.0-28). * Fixed security bug in saned.c that allowed access to scanner without password. * pnm isn't installed by default anymore due to security risks * Linux-part of sanei_scsi.c was updated concerning buffersizes, devfs, and kernel 2.4. More debug output. * sanei_scsi_find_devices works on FreeBSD now. * Added support for Solaris sgen SCSI driver. * find-scanner was renamed to sane-find-scanner and is installed now. Further more it has a man page now. * There is a testsuite for sane, but only one test is implemented yet. * Better output about versions of backends and frontends. * There is a man page for SANE now (sane(7)). * Install all available documentation. * Bugfixes. New with 1.0.4, released 2000-12-21: * New backends: as6e, nec, pie. * Updated backends: artec (v0.5.15), avision (v0.2.1), epson (v0.1.39), hp (v0.93), mustek (v1.0-102), mustek_pp (v0.9-devel), plustek (v0.38), sharp (v0.32), umax (v1.0-21). * Moved frontends xscanimage and xcam to a new package (sane-frontends). * Added authentification with encrypted passwords. * Installation of shared libraries on AIX is supported now. * Fixed compilation bugs on Irix and FreeBSD. * Better debug output on platforms not supporting vararg macros. * Better documentation about SANE devicenames. * Bugfixes. New with 1.0.3, released 2000-08-12: * New backends: mustek_pp, plustek, st400, v4l. * Updated backends: Artec (v0.5.14), Coolscan (v0.4.3), Epson (v0.1.33), HP (v0.88), Mustek (v1.0-96), Sharp (v0.31), UMAX (v1.0-21). * Removed backend info sagitta.desc due to lack of interest. * Installing no longer depends on 'rev'. * Added and structured documentation. * Every backend has a man page now. * Debug messages are now sent to syslog if stderr is a socket. * New 16 bit support to scanimage. * Bugfixes. New with 1.0.2, released 2000-03-06: * Aliased and hidden backend support. * Port to UnixWare 2.x and UnixWare 7. * New script 'sane-config' to help frontend developers. * Added Ricoh IS50 support. * Updated backends: Artec (v0.5.13), CANON (v991108), DC-25 (1.2), HP (v0.86), Microtek (0.12.0), Microtek2 (v0.8), UMAX (v1.0-build-18), Epson (v0.1.15), Sharp (v0.30), sp15c (1.12) and m3096g (1.11). * Automatic document feeder support for scanimage. * New backend for Avision AV 630 CS. * New Linux SCSI Generic driver. * Upgraded to libtool 1.3.4 * GIMP compatibility patch. * OS/2 patches. * Bugfixes. New with 1.01: * Miscellaneous o configure --disable-shared works again o scanimage -T testing option added (by Nick Lamb) o in dll.conf, the pnm, dc25, and dc210 backends are now disabled (commented out) by default. The net backend is now enabled by default. The pnm backend has been disabled as it often proved confusing to novice users. The dc25 and dc210 backends were disabled because they initialize very slowly if no camera is attached. o Downgraded PNM backend to the version shipped with SANE 0.74. The scan area options as implemented in SANE 1.00 were incorrectly implemented which made the backend unreliable. * New tool to turn off Mustek 600 II N scanner (by Andreas Czechanowski) o the new binary tools/mustk600iin-off allows to turn off a Mustek 600 II N scanner (note: you'll need to install this tool manually if you want it) * New backend for Sharp scanners (by FUKUDA Kazuya & Abel Deuring) o supports the Sharp JX-610, JX-250, and JX-330 SCSI scanner o preview/lineart/haftone/threshold are untested * Updated Kodak DC25 backend (by Peter Fales). * Updated HP backend (by Peter Kirchgessner) o New features: - Option 'unload after scan' for PhotoScanner - Manual page sane-hp updated - hp.desc updated o Bugfixes: - Adjustable scan size for scan from ADF - No blanks in command line options - Segmentation fault for starting scanimage -d hp:/dev/sg0 without /dev/sgo in hp.conf Scanning from the ADF therefore should work now. * Updated Microtek backend (by Matto Marjanovic) o Fixed off-by-1 error in revision-number parsing. o dump_inquiry() now prints the "Vendor Specific String". o Added model code/vendor name for the other 600ZS. o Made get_scan_status() retry delay increase with each try (will this help the poor 600ZS?). o Corrected base resolution for Agfa StudioScan II/IIsi (400dpi). o Disabled backend's clever aspect-ratio correction code for expanded-mode scans with StudioScan II/IIsi (scanner handles it internally - smart scanner.) o Fixed gamma LUT code parsing stupidity: now correctly determines maximum allowed LUT size, and uses it. (Especially necessary for StudioScan II/IIsi.) o The E6 claims to only support 256-byte LUT's, but the backend now ignores that misinformation (and uses 1024). o Now ignores denial of expanded-mode by older E6's (model code 0x63), in addition to newer E6's. * Updated Microtek2 backend (by Bernd Schroeder) o Added support for non-blocking I/O. o Preliminary support for a strip and a slide mode. o For people, who are annoyed, if the the scanhead moves back and fourth during a scan (backtracking): There is a new option 'disable backtracking'. At present this option must be activated by uncommenting the respective entry in the included microtek2.conf file. This is an advanced option. o The X6EL should no longer produce pixel junk after one successful scan. * Updated Mustek backend (by Andreas Bolsch) o larger buffer acquired (speeds up scanning slightly) o for SE models minimal resolution increased from 60 dpi to 75 dpi o for SE models 75 dpi in color mode is no longer used as the newer firware version seems to be even more buggy o bug in calculation of gamma table corrected (applies only to SE models, NOT related to the overflow problem which was corrected via CLIP( ) ) o default resolution is now set according to the minimal resolution (firmware dependent) o for SE models all unsupported options (speed, ... ) explicitly disabled * Updated Nikon Coolscan backend (by Didier Carlier) o Reverse the pixel order for the LS-1000. * Updated snapscan backend to v0.6 (by Kevin Charter and Petter Reinholdtsen) o Fixes the versioning problem. o Add support for SnapScan 1236s (should also work for SnapScan 600). * Updated UMAX backend (by Oliver Rauch) o Added support for Linotype Hell Saphir 2 o Changed bug in gray gamma data conversion o Added support for Nikon AX-210 o Added "Vista S-6E" as supported o Added PowerLook-II (PL-II) as supported o Added Astra 600S as supported New with 1.00: * Upgraded to libtool-1.2. This reportedly gets SANE to build on Solaris versions with a broken printf. * saned Matching of hostnames is no longer case-sensitive. * New Abaton backend (by David Huggins-Daines) Supports "Scan 300/GS" and may work with "Scan 300/S" but the latter is untested. * New Agfa Focus backend (by Karl Anders Øygard) Supports: o AGFA Focus GS (6 bit gray scale) (untested) o AGFA Focus Lineart (lineart) (untested) o AGFA Focus II (8 bit gray scale) (untested) o Siemens S9036 (8 bit gray scale) (untested) o AGFA Focus Color (24 bit color 3-pass) o AGFA Focus Color Plus (24 bit color 3-pass) * New Kodak DC210 still camera backend (by Brian J. Murrell) * New Ricoh backend (by Feico Dillema). * New HP backend. The backend formerly known as "xhp" is now the default HP backend. This backend should support HP scanners much better and was contributed by Geoffrey Dairiki and Peter Kirchgessner. - Added support for HP 6200C - Suppress halftone mode on photosmart (it is not supported) - Show calibrate button on photoscanner only for print media - Add media selection for photoscanner - Cleanup hp_scsi_s structure * Updated apple backend (by Milon Firikis). Now you should be able to scan from ColorOneScanners (in non color modes) and maybe from OneScanners (untested). * Updated Artec backend (by Chris Pinkham). * Updated Kodak DC25 backend (by Peter Fales). * Updated Microtek backend (by Matto Marjanovic). - Fix segfault on exit due to unnecessary free() in sane_close(). - Fix to red channel shift bug (which crept in during rewrite of color-handling code). - Addition of "patch level" to version codes. * Updated Microtek2 backend - Added support for ScanMaker 330, ScanMaker 636, ScanMaker E3plus, ScanMaker X6 and Phantom 636. - Other improvements (this includes support for automatic document feeders and transparency adapters, missing option descriptions were added). - Updated the manual page. * Updated Mustek backend (patches by Andreas Bolsch and Heiko Schroeder) - Heiko's patch should make resolutions >300dpi work for MFS-6000CX. Andreas's patches: - Should work with ScanExpress 6000SP, 12000SP as well as older models - Bug with MFS-12000SP corrected (poined out by Daniel Deckers) - Bug which caused xscanimage to crash after color preview corrected - Improvement(?) in high resolution Important Notes for ScanExpress models: - Resolutions below 60 dpi don't work (firmware problem). - Resolutions >300 dpi (6000 SP) or >600 dpi (12000 SP) result in different x/y-resolution as 6000 SP and 12000 SP have in fact only 300 dpi and 600 dpi CCD sensors, respectively. - Resolutions >300dpi in color mode sometimes result in corrupted images (parts duplicated/shifted *HORIZONTALLY*) depending on hardware configuration. Killing all other applications and disabling swap (if sufficient physical memory available) may help. I added some code which writes to every page of the buffer prior to scanning to fool the memory management and scanned a full page color scan with 600dpi * 1200dpi. Very slow but image seemed ok after pnmscale. - Max. scan area: 0-216mm (hor.), 2.5-294.5mm (ver.) The scanners can't scan the first 2.5mm (ver.), so you *MUST* specify the scan area according to this restriction! - The scanners support only lineart (1 bpp), gray (8 bpp), color (24 bpp). Although the scanners have 10 bit (6000 SP) or 12 bit (12000 SP) A/D-converters, they can send only 8 bit values to the host. The higher resolution may only be used via gamma table. - For compatibility only 256 entry gamma tables may be specified, the actual gamma table sent to the scanner is linearly interpolated from it. - In lineart mode only brightness may be adjusted. - Cover open/closed reported only via debug output and ignored otherwise. - Use of SCSI card supplied with scanner is *NOT* recommended. (Don't forget termination!) * Updated UMAX backend (by Oliver Rauch) - added output of umax-backend-version in sane_init - added Linotype Hell Jade2 (Vobis ScanBoostar Premium) SCSI-ID "LinoHell","Office2" as supported scanner - changed base of calculation of scanwidth and scanlegth from pixel to resolutionbase (1/300, 1/600 or 1/1200 inch) - changed calculation for width in pixels for lineart mode - changed selection for calibration mode - added inquiry for UMUX UC1200SE - corrected 12/36-bit-mode in send_gamma_data and array in umax.h * Updated SnapScan backend to v0.5 (by Kevin Charter) - bug fixes (Wolfgang, David) - addition of threshold control for lineart mode (Mikko) - Vuego 310S support (Wolfgang) - default scan area now maximal (Kevin) New with 0.74: * GIMP auto-detection should work again. * Service name for remote scanning changed from "saned" to "sane". Be sure to update your /etc/services and /etc/inetd.conf if you use remote scanning! We generally try to avoid such incompatible changes, but the name "saned" was definitely wrong, so it seemed better to change it now. * Thanks to Matto Marjanovic work, each backend now comes with a .desc file that describes exactly what devices it supports. These description files can be automatically translated into various other formats, such as HTML. See: http://www.mostang.com/sane/sane-backends.html for an example as to what this can do for you. * New backend for Kodak DC25 digital cameras (by Peter Fales). * Updated Artec backend (by Chris Pinkham). * Updated Microtek backend (by Matthew Marjanovic) o Complete rewrite of bit-shuffling, buffering, and color-handling code. o Improved rescaling algorithm for expanded resolution scans. o Support for 600GS (and maybe ZS, too) (thanks to Oliver Neukum). o Support for document autofeeder and IIG (thanks to Ross Crawford). o Fixed sane_cancel. o sane_get_parameters size estimates are now accurate to the last bit. o get_scan_status timeout increased (for 600GS), status code fixed. o Fixed parsing of 3-pass bit in INQUIRY data. o Stopped sending gamma tables to scanners that don't want them. o Made precalibration a bit more robust (always attempt at least one scan line now). o Much, much code clean-up. o Tested & working with saned. (Atrocious hack so sane_read handles buffers smaller than one scanline.) o Auto-expand pre/post hold buffers as necessary (fixes some problems with single-pass color scans). o Added configuration file option to disable precalibration logic. o Fixed document size calculations. o Added more informative scsi-II note. o Remove misnomer "Highscan" from manpage. o Updated man-page. * Updated Microtek2 backend (by Bernd Schroeder) o changed the code for gamma calculation and added a custom gamma table to the options. In some cases this requires an additional memcpy(), but the code is now leaner and cleaner. o fixed the bugs that the backend didn't compile with non gcc compilers. o added an option to control exposure times. o rewrote the code that processes the data that is received from the scanner and transfers it into the frontend buffer. The smallest unit of data that can be copied into the frontend buffer is now a pixel, no longer a complete line. o added (a yet) undocumented option "strip-height" that allows to control the number of lines that is read from the scanner with one "read image". o fixed a bug that caused scanimage to sigsegv when calling sane_exit() without having written all data into the output file. o added code to support scanners with more than 8 bit output per color. Due to the lack of such a scanner this functionality is COMPLETELY UNTESTED and there are some potential sources of bugs, but at least one could give it try. o added sanei_config_attach_matching_devices() o improved the code for the check if it really is Microtek SCSI-II scanner o fixed the "lineart inverted" bug o The threshold option in lineart mode is now in the enhancement group o changed the default for the resolution o The values for the SANE_Params struct are calculated more precisely o dito the number of scan lines that fit into the frontend buffer o changed some return stati ( replaced SANE_STATUS_INVAL with SANE_STATUS_IO_ERROR where the first one is not allowed) o completely rewrote the end of scan and cancel scan handling o fixed another bug that caused xscanimage to crash with sigsegv under some circumstances (check of the inquiry result was wrong) o added model code for a Vobis Highscan o support for new format of configuration file (including "option ") * Updated Nikon Coolscan backend (by Didier Carlier). * Updated UMAX backend (by Oliver Rauch): o Cancelling a scan now works, cancelling a preview still makes problems! o Preview fix is activated for Astra 600S, Astra 610S and Vista S6E scanners. (calibration by driver still does not work for these scanners). - removed button for preview patch o Quality calibration / calibration by driver now works for same scanners. - added selection for type of shading data calculation o Solved problem with black area at top of the image (happend only with some SCSI-adapters). o Added gamma download format type 0 and type 1 for older scanners. o Added Astra 1220S as supported scanner: - added 36 gamma input bits support for Astra 1220S - added 36 output bits support, but there is no frontend that can handle it! o Added inquiry for Escom Image Scanner 256 (UMAX UG80). * OS/2 (by Yuri Dario): o Updated SCSI support so sanei_scsi_find_devices is supported now. o Epson parallel support added (by Rocco Caputo ) New with 0.73: * In xscanimage, the selection box now gets updated again when changing the geometry option sliders---really! * On Linux, it is now possible to specify SCSI device names by entering their SCSI ids. For example, instead of "/dev/scanner", one can now specify "scsi MUSTEK" to get all scanners manufactured by Mustek. This feature is currently supported by the all SCSI backends except microtek2. This feature is courtesy of Oliver Rauch. * Backend libraries are now installed in $(libdir)/sane (/usr/local/lib/sane/, by default). * Updated Microtek backend (Matto Marjanovic): - ScanMaker 600ZS, Agfa Arcus II, StudioScan, and StudioScan II now supported (or recognized, at least ;-). - Fixed 3-pass scanning. - Various bug-fixes (see ChangeLog for details). * New Microtek2 backend (Bernd Schroeder) This backend supports the ScanMaker 630 and possibly other newer scanners that are not supported by the "old" Microtek backend. Additional info by Bernd: This is the very first release of this backend, so consider this software to be in alpha state. The backend was developed on a Pentium (60 Mhz) with Linux 2.0.29 and a ScanMaker 630 attached to the Adaptec AHA1505E that shipped with the scanner. As frontend xscanimage was used. It is intended to work with other models, too, but there are no experiences yet. The following options are supported: - 8-bit color, 8-bit grayscale, halftone and lineart scans. - brightness, contrast, shadow, midtone and highlight control - scalar gamma correction. Options that are not yet supported include: - 3-pass scanners - more than 8 bit per color output data. Provisions are made here and there in the code, to support more than 8 bit, but that's uncomplete. * configure --disable-static should now work as expected. New with 0.72: * New backend for Artec scanners. This backend is known to work with Artec AT3, but others may work too (A6000C should work). * Updated DMC and Microtek backend. * Updated UMAX backend: ** added exposure time adjustment (for high-end scanners) ** added lamp density control (for high-end scanners) ** UMAX Astra 6X0S works in color-mode now, you have to enable preview_patch! ** added support for UMAX UC1200S and UC1260, but it will not work fine! ** enabled x-resolution greater than 600 dpi if supported by scanner (e.g. UMAX S12) but it sometimes still does not work right! * Updated SnapScan backend: There is now support for the SnapScan 310 and 600 scanner models. * OS/2 and FreeBSD support should be working again. * New backend writer's guide to SANE File backend/GUIDE outlines a few rules that should help in writing a new backend. New with 0.71: * Polaroid Digital Microscope Camera (DMC) backend Written by David Skoll . * Apple scanner backend Written by Milon Firikis . This backend supports AppleScanner and has preliminary support for OneScanner and ColorOneScanner. * Nikon CoolScan backend Written by Didier Carlier . * Apollo Domain/OS support Contributed by Paul Walker . New with 0.70: * Preliminary version of AGFA SnapScan backend is now included. This backend is know to work with AGFA SnapScan scanners but is unlikely to work with any other AGFA See scanner.http://www.cs.ualberta.ca/~charter/snapscan.html for details. * Various minor bug fixes that prevented SANE from building on non-Linux platforms. * xscanimage now honors WM_DELETE message. * Updated UMAX backend. New between 0.6 and 0.69: * Mustek backend now supports the Transparency Adapter on the Paragon 1200SP (MFS-12000SP). * New backend for Canon scanners. This backend was written by Helmut Koeberle . It is known to work with the CanonScan 600 though not all features are supported yet. * Solaris SCSI support now exists. Thanks to Martin Huber , the SCSI backends are now usable under Solaris, too. See README.solaris for details. * AIX SCSI support now exists. Thanks to Fred Hucht & Michael Staats, the SCSI backends are now usable under AIX, too. * New backend for Tamarack and ESCOM scanners. This backend was written by Roger Wolff of BitWizard. * New backend for Siemens S9036 scanner. This backend was written by Ingo Schneider . * find-scanner (by Oliver Rauch) SANE now comes with a program called find-scanner (in the tools subdirectory) that can be used to find the device name of attaches SCSI scanners. Note that this program is not normally installed as part of the normal SANE installation as this program is not something an end-user should ever have to use. * The Mustek backend has preliminary support for the Paragon 600 II N scanner. This scanner attaches directly to a Mustek-supplied ISA card which implements a funky parallel port. For details, see the section entitled PARALLEL PORT SCANNERS in sane-mustek(5). Use at your own risk! * The location of the configuration files can now be overridden with environment variable SANE_CONFIG_DIR (see also man-pages for the backends and programs). * When preloading backends into dll, they now appear in the same order as if they had been loaded dynamically (i.e., in reverse order in which they're listed in dll.conf). * Java frontend (by Jeff Freedman) SANE now includes a Java frontend for SANE. However, the Java files are not built by default. See japi/README.JAVA for details. * There is a Java API for SANE now. See japi/README.JAVA for details. This code is courtesy of Jeff Freedman . * UMAX updates (by Oliver Rauch): - the umax backend is now fully runtime configuable---there are no longer any build-time configuration options. - Umax T630, Astra 610S, and Linotype Hell Office scanners are now supported - gamma-data now works on Astra 1200 S with 30 bits/pixel Note: None of the SANE frontends presently support 30 bits/pixel. If you're interested in fixing this, send mail to sane-devel@mostang.com. * The Mustek backend is now fully runtime configurable---there are no longer any build-time configuration options. To this end, the mustek.conf configuration file now supports options linedistance-fix, lineart-fix, and strip-height (see sane-mustek(5) for details). * New backend for Epson scanners An alpha-quality backend for Epson scanners is now included with SANE thanks to the efforts of Kazuhiro Sasayama . * OS/2 Support Thanks to Jeff Freedman SANE now supports OS/2. * New backend for Microtek scanners Thanks to the excellent work of Matthew Marjanovic , the Microtek is now taking shape. * Irix SCSI support Thanks to the work of Michael Sweet , there is now SCSI support for Irix! * Improvements to the UMAX backend (by Oliver Rauch): ** workaround for preview-bit-problem in RGB-mode (UMAX S6E ...) ** unsupported options are disabled ** now three_pass_scan should work ** new supported scanners: *** UC840 *** Astra 1200S * The Mustek configuration file (mustek.conf) now supports a configuration option to limit the height of the strip that is scanned with a single SCSI read command. The syntax is: option strip-height HEIGHT where HEIGHT is a floating point number that gives the maximum strip height in inches. This option should be set to a small value (e.g., 1 inch) when the scanner is connected to a SCSI bus shared with other devices or when using a broken SCSI driver whose timeouts expire prematurely. For best scan performance, the strip-height should be set to a large value or the option should be removed completely. See the sane-scsi(5) man-page for details on how drivers with premature timeouts can be fixed (the Linux ncr810 driver is the only known driver with this problem at this point). * The preview window now properly draws the initial window-selection. * Mustek backend now uses a SCSI command queue to avoid performance problems with three pass scanners. This can reduce scantimes from 15 minutes down to 3 minutes! * Mustek backend will now wait for up to 1 minute for a scanner to become ready if the scanner name is specified explicitly. E.g., "scanimage -d mustek" will timeout almost right away (since the Mustek device name is not specified explicitly) whereas "scanimage -d mustek:/dev/scanner" will wait for up to a minute. * HP backend now uses pixel-unit commands to accommodate ScanJet 5P. * Platform-specific SCSI setup info is now in sanei-scsi(5). * xscanimage(1) now has a section on how to run it under GIMP. * B&W qcam support should now work (reports on how well it works are welcome). * Exiting xscanimage with preview window open should no longer cause an error. * Support for OpenStep/NeXTStep added (xscanimage and xcam require an X server and the GTK+ libraries, though). User-level SCSI is supported. * SCSI support for NetBSD and FreeBSD should work now. Thanks to NOGAYA Shigeki and Amancio Hasty for relevant patches. * New man-page sane-scsi(5) with platform-specific SCSI tips and tricks. * SANE now builds on HP-UX (SCSI support untested) and IRIX (no SCSI support), too. New in 0.6: * UMAX scanners are now supported! Kudos to Oliver Rauch and Michael K. Johnson . * scan got renamed to scanimage to avoid a nameclash with an MH program by the same name. For consistency, xscan also got renamed to xscanimage. * Man-pages! There finally are at least a few man-pages. At present, the following is covered: saned.1 scanimage.1 xscanimage.1 sane-dll.5 sane-hp.5 sane-mustek.5 sane-net.5 sane-pint.5 sane-pnm.5 sane-qcam.5 sane-umax.5 * SANE no longer insists on using GCC. GCC works best, but other ANSI C compilers will now also produce usable executables. * xscanimage now supports vector options (such as gamma-tables which are also known as intensity or tonemaps). * The gamma-table (intensity/tone-map) handling changed in the Mustek backend. As a result, when using scanimage it is now necessary to specify option --custom-gamma before gamma-tables can be specified. Also, the handling of the intensity table is now handled better in color mode (it no longer overrides the color tables; instead the composition of the intensity and the color channel table is used). * The SANE header files are now isolated in the include/sane directory and those files get now installed as part of "make install". Thanks to Michael K. Johnson for this patch! * xscanimage now displays the options' documentation strings as tooltips (can be disabled via the "Preferences" menu). * scanimage now supports three-pass scanning and scanning of images whose height is not known a priori (e.g., hand-held scanners). * The Mustek backend now supports an option to force preview scans to be monochrome (good to save time on three-pass scanners). * configure can now be run from any directory, as it's supposed to (makes it easier to build SANE for multiple platforms from the same source tree). * xcam and xscanimage should now build on Solaris, too (thanks to Tristan Tarrant). * copyright info in various files have been adjusted. See LICENSE for the general idea behind SANE licensing. * Many, many bugfixes. New in 0.5: * The same xscan binary can now function as a standalone frontend or as a gimp extension. If installed as a GIMP extension, xscan will attach itself as Extensions->Acquire Image. * The pnm backend now has an option to simulate a three-pass scanner. Good for testing. * xscan now supports previewing and (persistent) preferences. * The build process should be much more robust now. It requires GNU make and gcc but should be completely unproblematic otherwise. A simple "configure" should result in a working SANE environment even on systems where dynamic loading is unavailable. Various options are available to tailor the SANE setup. See README for details. * A first implementation of the HP backend now exists (for ScanJet scanners). * A first implementation of the net backend and saned (network daemon) now exists. So it is now possible to scan across the network! See backend/net.README and frontend/saned.README for details. * xcam, a camera frontend is now included. See frontend/xcam.README for details. * Renamed metadl to dll. New in 0.4: * A first implementation of the Connectix quickcam backend now exists. At present, only color cameras are known to work, though it shouldn't be too hard to get the b&w versions to work as well. * Improvements for the command-line frontend scan: ** Option settings are now applied _before_ the help info is printed. This allows to see what the available options are with certain options in effect. ** It can now deal with SANE_INFO_RELOAD_OPTIONS. ** It now prints the current option values in the help message (except for vectors). New in 0.33: * sane_get_devices() now takes a second argument of boolean type. If it's SANE_TRUE, then the backend must return local (non-remote) devices only. * scan now uses the default-unit of `mm' (millimeters) again for lengths. Using `cm' (centimeter) proved confusing since the help messages print length values in millimeters. * Debugging can now be controlled on a per-backend basis. The debug-level of backend is set by environment variable SANE_DEBUG_. For example, to see all debug messages of the metadl backend, set SANE_DEBUG_METADL to a large value (say 128). The sanei.h file provides three macros to assist in using this debug facility: DBG_DECL to declare the integer variable that holds the debug level, DBG_INIT to initialize debugging, and DBG to print a debug message. See backend/sanei.h and backend/metadl.c for details and examples. * scan now supports setting options to "auto" mode (e.g., --brightness=auto would ask the backend to select brightness automatically if that option supports automatic mode * scan now allows abbreviating the values of a string-lists. Case is ignored and the best matches is used (either longest unique match or exact match when ignoring case) New in 0.32: * xscan improved much. See frontend/xscan.README and frontend/xscan.BUGS for details. New in 0.31: * xscan has improved much. See frontend/xscan.CHANGES for details. New in 0.3: * The location of the SANE configuration files moved from /etc/saneconf to ${prefix}/etc/sane.d. This normally expands into /usr/local/etc/sane.d. * Real build environment. It's GNU autoconf based so all you should have to say is: ./configure make make install sane-backends-1.0.27/m4/0000775000175000017500000000000013110600530011607 500000000000000sane-backends-1.0.27/m4/gettext.m40000664000175000017500000003513212775312262013503 00000000000000# gettext.m4 serial 63 (gettext-0.18) dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2006, 2008-2010. dnl Macro to add for using GNU gettext. dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The dnl default (if it is not specified or empty) is 'no-libtool'. dnl INTLSYMBOL should be 'external' for packages with no intl directory, dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. dnl If INTLSYMBOL is 'use-libtool', then a libtool library dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, dnl depending on --{enable,disable}-{shared,static} and on the presence of dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library dnl $(top_builddir)/intl/libintl.a will be created. dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext dnl implementations (in libc or libintl) without the ngettext() function dnl will be ignored. If NEEDSYMBOL is specified and is dnl 'need-formatstring-macros', then GNU gettext implementations that don't dnl support the ISO C 99 formatstring macros will be ignored. dnl INTLDIR is used to find the intl libraries. If empty, dnl the value `$(top_builddir)/intl/' is used. dnl dnl The result of the configuration is one of three cases: dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled dnl and used. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 2) GNU gettext has been found in the system's C library. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 3) No internationalization, always use English msgid. dnl Catalog format: none dnl Catalog extension: none dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. dnl The use of .gmo is historical (it was needed to avoid overwriting the dnl GNU format catalogs when building on a platform with an X/Open gettext), dnl but we keep it in order not to force irrelevant filename changes on the dnl maintainers. dnl AC_DEFUN([AM_GNU_GETTEXT], [ dnl Argument checking. ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT ])])])])]) ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT ])])])]) define([gt_included_intl], ifelse([$1], [external], ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), [yes])) define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) gt_NEEDS_INIT AM_GNU_GETTEXT_NEED([$2]) AC_REQUIRE([AM_PO_SUBDIRS])dnl ifelse(gt_included_intl, yes, [ AC_REQUIRE([AM_INTL_SUBDIR])dnl ]) dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Sometimes libintl requires libiconv, so first search for libiconv. dnl Ideally we would do this search only after the dnl if test "$USE_NLS" = "yes"; then dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT dnl the configure script would need to contain the same shell code dnl again, outside any 'if'. There are two solutions: dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not dnl documented, we avoid it. ifelse(gt_included_intl, yes, , [ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) ]) dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. gt_INTL_MACOSX dnl Set USE_NLS. AC_REQUIRE([AM_NLS]) ifelse(gt_included_intl, yes, [ BUILD_INCLUDED_LIBINTL=no USE_INCLUDED_LIBINTL=no ]) LIBINTL= LTLIBINTL= POSUB= dnl Add a version number to the cache macros. case " $gt_needs " in *" need-formatstring-macros "*) gt_api_version=3 ;; *" need-ngettext "*) gt_api_version=2 ;; *) gt_api_version=1 ;; esac gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" dnl If we use NLS figure out what method if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no ifelse(gt_included_intl, yes, [ AC_MSG_CHECKING([whether included gettext is requested]) AC_ARG_WITH([included-gettext], [ --with-included-gettext use the GNU gettext library included here], nls_cv_force_use_gnu_gettext=$withval, nls_cv_force_use_gnu_gettext=no) AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" if test "$nls_cv_force_use_gnu_gettext" != "yes"; then ]) dnl User does not insist on using GNU NLS library. Figure out what dnl to use. If GNU gettext is available we use this. Else we have dnl to fall back to GNU NLS library. if test $gt_api_version -ge 3; then gt_revision_test_code=' #ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif changequote(,)dnl typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; changequote([,])dnl ' else gt_revision_test_code= fi if test $gt_api_version -ge 2; then gt_expression_test_code=' + * ngettext ("", "", 0)' else gt_expression_test_code= fi AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], [AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings;], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings], [eval "$gt_func_gnugettext_libc=yes"], [eval "$gt_func_gnugettext_libc=no"])]) if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl Sometimes libintl requires libiconv, so first search for libiconv. ifelse(gt_included_intl, yes, , [ AM_ICONV_LINK ]) dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) dnl because that would add "-liconv" to LIBINTL and LTLIBINTL dnl even if libiconv doesn't exist. AC_LIB_LINKFLAGS_BODY([intl]) AC_CACHE_CHECK([for GNU gettext in libintl], [$gt_func_gnugettext_libintl], [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" dnl Now see whether libintl exists and does not depend on libiconv. AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [eval "$gt_func_gnugettext_libintl=yes"], [eval "$gt_func_gnugettext_libintl=no"]) dnl Now see whether libintl exists and depends on libiconv. if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" eval "$gt_func_gnugettext_libintl=yes" ]) fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) fi dnl If an already present or preinstalled GNU gettext() is found, dnl use it. But if this macro is used in GNU gettext, and GNU dnl gettext is already preinstalled in libintl, we update this dnl libintl. (Cf. the install rule in intl/Makefile.in.) if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else dnl Reset the values set by searching for libintl. LIBINTL= LTLIBINTL= INCINTL= fi ifelse(gt_included_intl, yes, [ if test "$gt_use_preinstalled_gnugettext" != "yes"; then dnl GNU gettext is not found in the C library. dnl Fall back on included GNU gettext library. nls_cv_use_gnu_gettext=yes fi fi if test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions used to generate GNU NLS library. BUILD_INCLUDED_LIBINTL=yes USE_INCLUDED_LIBINTL=yes LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` fi CATOBJEXT= if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions to use GNU gettext tools. CATOBJEXT=.gmo fi ]) if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Some extra flags are needed during linking. LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then AC_DEFINE([ENABLE_NLS], [1], [Define to 1 if translation of program messages to the user's native language is requested.]) else USE_NLS=no fi fi AC_MSG_CHECKING([whether to use NLS]) AC_MSG_RESULT([$USE_NLS]) if test "$USE_NLS" = "yes"; then AC_MSG_CHECKING([where the gettext function comes from]) if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi AC_MSG_RESULT([$gt_source]) fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then AC_MSG_CHECKING([how to link with libintl]) AC_MSG_RESULT([$LIBINTL]) AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) fi dnl For backward compatibility. Some packages may be using this. AC_DEFINE([HAVE_GETTEXT], [1], [Define if the GNU gettext() function is already present or preinstalled.]) AC_DEFINE([HAVE_DCGETTEXT], [1], [Define if the GNU dcgettext() function is already present or preinstalled.]) fi dnl We need to process the po/ directory. POSUB=po fi ifelse(gt_included_intl, yes, [ dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL dnl to 'yes' because some of the testsuite requires it. if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then BUILD_INCLUDED_LIBINTL=yes fi dnl Make all variables we use known to autoconf. AC_SUBST([BUILD_INCLUDED_LIBINTL]) AC_SUBST([USE_INCLUDED_LIBINTL]) AC_SUBST([CATOBJEXT]) dnl For backward compatibility. Some configure.ins may be using this. nls_cv_header_intl= nls_cv_header_libgt= dnl For backward compatibility. Some Makefiles may be using this. DATADIRNAME=share AC_SUBST([DATADIRNAME]) dnl For backward compatibility. Some Makefiles may be using this. INSTOBJEXT=.mo AC_SUBST([INSTOBJEXT]) dnl For backward compatibility. Some Makefiles may be using this. GENCAT=gencat AC_SUBST([GENCAT]) dnl For backward compatibility. Some Makefiles may be using this. INTLOBJS= if test "$USE_INCLUDED_LIBINTL" = yes; then INTLOBJS="\$(GETTOBJS)" fi AC_SUBST([INTLOBJS]) dnl Enable libtool support if the surrounding package wishes it. INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) ]) dnl For backward compatibility. Some Makefiles may be using this. INTLLIBS="$LIBINTL" AC_SUBST([INTLLIBS]) dnl Make all documented variables known to autoconf. AC_SUBST([LIBINTL]) AC_SUBST([LTLIBINTL]) AC_SUBST([POSUB]) ]) dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. m4_define([gt_NEEDS_INIT], [ m4_divert_text([DEFAULTS], [gt_needs=]) m4_define([gt_NEEDS_INIT], []) ]) dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) AC_DEFUN([AM_GNU_GETTEXT_NEED], [ m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) ]) dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) sane-backends-1.0.27/m4/byteorder.m40000664000175000017500000002776612112021330014006 00000000000000dnl AC_NEED_BYTEORDER_H ( HEADER-TO-GENERATE ) dnl Copyright 2001-2002 by Dan Fandrich dnl This file may be copied and used freely without restrictions. No warranty dnl is expressed or implied. dnl dnl Create a header file that guarantees that byte swapping macros of the dnl ntohl variety as well as the extended types included in OpenBSD and dnl NetBSD such as le32toh are defined. If possible, the standard ntohl dnl are overloaded as they are optimized for the given platform, but when dnl this is not possible (e.g. on a big-endian machine) they are defined dnl in this file. dnl Look for a symbol in a header file dnl AC_HAVE_SYMBOL ( IDENTIFIER, HEADER-FILE, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND ) AC_DEFUN([AC_HAVE_SYMBOL], [ AC_MSG_CHECKING(for $1 in $2) AC_EGREP_CPP([symbol is present|\<$1\>],[ #include <$2> #ifdef $1 symbol is present #endif ], [AC_MSG_RESULT(yes) $3 ], [AC_MSG_RESULT(no) $4 ])]) dnl Create a header file that defines extended byte swapping macros AC_DEFUN([AC_NEED_BYTEORDER_H], [ ac_byteorder_h=`echo ifelse($1, , _byteorder.h, $1)` changequote(, )dnl ac_dir=`echo $ac_byteorder_h|sed 's%/[^/][^/]*$%%'` changequote([, ])dnl if test "$ac_dir" != "$ac_byteorder" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" fi # We're only interested in the target CPU, but it's not always set effective_target="$target" if test "x$effective_target" = xNONE -o "x$effective_target" = x ; then effective_target="$host" fi AC_SUBST(effective_target) ac_byteorder=_byteorder.tmp cat > "$ac_byteorder" << EOF /* This file is generated automatically by configure */ /* It is valid only for the system type ${effective_target} */ #ifndef __BYTEORDER_H #define __BYTEORDER_H EOF dnl First, do an endian check AC_C_BIGENDIAN dnl Look for NetBSD-style extended byte swapping macros AC_HAVE_SYMBOL(le32toh,machine/endian.h, [HAVE_LE32TOH=1 cat >> "$ac_byteorder" << EOF /* extended byte swapping macros are already available */ #include EOF], [ dnl Look for standard byte swapping macros AC_HAVE_SYMBOL(ntohl,arpa/inet.h, [cat >> "$ac_byteorder" << EOF /* ntohl and relatives live here */ #include EOF], [AC_HAVE_SYMBOL(ntohl,netinet/in.h, [cat >> "$ac_byteorder" << EOF /* ntohl and relatives live here */ #include EOF],true)]) ]) dnl Look for generic byte swapping macros dnl OpenBSD AC_HAVE_SYMBOL(swap32,machine/endian.h, [cat >> "$ac_byteorder" << EOF /* swap32 and swap16 are defined in machine/endian.h */ EOF], [ dnl Linux GLIBC AC_HAVE_SYMBOL(bswap_32,byteswap.h, [cat >> "$ac_byteorder" << EOF /* Define generic byte swapping functions */ #include #define swap16(x) bswap_16(x) #define swap32(x) bswap_32(x) #define swap64(x) bswap_64(x) EOF], [ dnl NetBSD AC_HAVE_SYMBOL(bswap32,machine/endian.h, dnl We're already including machine/endian.h if this test succeeds [cat >> "$ac_byteorder" << EOF /* Define generic byte swapping functions */ EOF if test "$HAVE_LE32TOH" != "1"; then echo '#include '>> "$ac_byteorder" fi cat >> "$ac_byteorder" << EOF #define swap16(x) bswap16(x) #define swap32(x) bswap32(x) #define swap64(x) bswap64(x) EOF], [ dnl FreeBSD AC_HAVE_SYMBOL(__byte_swap_long,sys/types.h, [cat >> "$ac_byteorder" << EOF /* Define generic byte swapping functions */ #include #define swap16(x) __byte_swap_word(x) #define swap32(x) __byte_swap_long(x) /* No optimized 64 bit byte swapping macro is available */ #define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ ((x) >> 8) & 0x00000000ff000000ULL | \\ ((x) >> 24) & 0x0000000000ff0000ULL | \\ ((x) >> 40) & 0x000000000000ff00ULL | \\ ((x) >> 56) & 0x00000000000000ffULL)) EOF], [ dnl OS X AC_HAVE_SYMBOL(NXSwapLong,machine/byte_order.h, [cat >> "$ac_byteorder" << EOF /* Define generic byte swapping functions */ #include #define swap16(x) NXSwapShort(x) #define swap32(x) NXSwapLong(x) #define swap64(x) NXSwapLongLong(x) EOF], [ if test $ac_cv_c_bigendian = yes; then cat >> "$ac_byteorder" << EOF /* No other byte swapping functions are available on this big-endian system */ #define swap16(x) ((uint16_t)(((x) << 8) | ((uint16_t)(x) >> 8))) #define swap32(x) ((uint32_t)(((uint32_t)(x) << 24) & 0xff000000UL | \\ ((uint32_t)(x) << 8) & 0x00ff0000UL | \\ ((x) >> 8) & 0x0000ff00UL | \\ ((x) >> 24) & 0x000000ffUL)) #define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ ((x) >> 8) & 0x00000000ff000000ULL | \\ ((x) >> 24) & 0x0000000000ff0000ULL | \\ ((x) >> 40) & 0x000000000000ff00ULL | \\ ((x) >> 56) & 0x00000000000000ffULL)) EOF else cat >> "$ac_byteorder" << EOF /* Use these as generic byteswapping macros on this little endian system */ #define swap16(x) ntohs(x) #define swap32(x) ntohl(x) /* No optimized 64 bit byte swapping macro is available */ #define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ ((x) >> 8) & 0x00000000ff000000ULL | \\ ((x) >> 24) & 0x0000000000ff0000ULL | \\ ((x) >> 40) & 0x000000000000ff00ULL | \\ ((x) >> 56) & 0x00000000000000ffULL)) EOF fi ]) ]) ]) ]) ]) [ if test "$HAVE_LE32TOH" != "1"; then cat >> "$ac_byteorder" << EOF /* The byte swapping macros have the form: */ /* EENN[a]toh or htoEENN[a] where EE is be (big endian) or */ /* le (little-endian), NN is 16 or 32 (number of bits) and a, */ /* if present, indicates that the endian side is a pointer to an */ /* array of uint8_t bytes instead of an integer of the specified length. */ /* h refers to the host's ordering method. */ /* So, to convert a 32-bit integer stored in a buffer in little-endian */ /* format into a uint32_t usable on this machine, you could use: */ /* uint32_t value = le32atoh(&buf[3]); */ /* To put that value back into the buffer, you could use: */ /* htole32a(&buf[3], value); */ /* Define aliases for the standard byte swapping macros */ /* Arguments to these macros must be properly aligned on natural word */ /* boundaries in order to work properly on all architectures */ #ifndef htobe16 #define htobe16(x) htons(x) #endif #ifndef htobe32 #define htobe32(x) htonl(x) #endif #ifndef be16toh #define be16toh(x) ntohs(x) #endif #ifndef be32toh #define be32toh(x) ntohl(x) #endif #define HTOBE16(x) (x) = htobe16(x) #define HTOBE32(x) (x) = htobe32(x) #define BE32TOH(x) (x) = be32toh(x) #define BE16TOH(x) (x) = be16toh(x) EOF if test $ac_cv_c_bigendian = yes; then cat >> "$ac_byteorder" << EOF /* Define our own extended byte swapping macros for big-endian machines */ #ifndef htole16 #define htole16(x) swap16(x) #endif #ifndef htole32 #define htole32(x) swap32(x) #endif #ifndef le16toh #define le16toh(x) swap16(x) #endif #ifndef le32toh #define le32toh(x) swap32(x) #endif #ifndef htobe64 #define htobe64(x) (x) #endif #ifndef be64toh #define be64toh(x) (x) #endif #define HTOLE16(x) (x) = htole16(x) #define HTOLE32(x) (x) = htole32(x) #define LE16TOH(x) (x) = le16toh(x) #define LE32TOH(x) (x) = le32toh(x) #define HTOBE64(x) (void) (x) #define BE64TOH(x) (void) (x) EOF else cat >> "$ac_byteorder" << EOF /* On little endian machines, these macros are null */ #ifndef htole16 #define htole16(x) (x) #endif #ifndef htole32 #define htole32(x) (x) #endif #ifndef htole64 #define htole64(x) (x) #endif #ifndef le16toh #define le16toh(x) (x) #endif #ifndef le32toh #define le32toh(x) (x) #endif #ifndef le64toh #define le64toh(x) (x) #endif #define HTOLE16(x) (void) (x) #define HTOLE32(x) (void) (x) #define HTOLE64(x) (void) (x) #define LE16TOH(x) (void) (x) #define LE32TOH(x) (void) (x) #define LE64TOH(x) (void) (x) /* These don't have standard aliases */ #ifndef htobe64 #define htobe64(x) swap64(x) #endif #ifndef be64toh #define be64toh(x) swap64(x) #endif #define HTOBE64(x) (x) = htobe64(x) #define BE64TOH(x) (x) = be64toh(x) EOF fi fi cat >> "$ac_byteorder" << EOF /* Define the C99 standard length-specific integer types */ #include <_stdint.h> EOF case "${effective_target}" in i[3456]86-*) cat >> "$ac_byteorder" << EOF /* Here are some macros to create integers from a byte array */ /* These are used to get and put integers from/into a uint8_t array */ /* with a specific endianness. This is the most portable way to generate */ /* and read messages to a network or serial device. Each member of a */ /* packet structure must be handled separately. */ /* The i386 and compatibles can handle unaligned memory access, */ /* so use the optimized macros above to do this job */ #define be16atoh(x) be16toh(*(uint16_t*)(x)) #define be32atoh(x) be32toh(*(uint32_t*)(x)) #define be64atoh(x) be64toh(*(uint64_t*)(x)) #define le16atoh(x) le16toh(*(uint16_t*)(x)) #define le32atoh(x) le32toh(*(uint32_t*)(x)) #define le64atoh(x) le64toh(*(uint64_t*)(x)) #define htobe16a(a,x) *(uint16_t*)(a) = htobe16(x) #define htobe32a(a,x) *(uint32_t*)(a) = htobe32(x) #define htobe64a(a,x) *(uint64_t*)(a) = htobe64(x) #define htole16a(a,x) *(uint16_t*)(a) = htole16(x) #define htole32a(a,x) *(uint32_t*)(a) = htole32(x) #define htole64a(a,x) *(uint64_t*)(a) = htole64(x) EOF ;; *) cat >> "$ac_byteorder" << EOF /* Here are some macros to create integers from a byte array */ /* These are used to get and put integers from/into a uint8_t array */ /* with a specific endianness. This is the most portable way to generate */ /* and read messages to a network or serial device. Each member of a */ /* packet structure must be handled separately. */ /* Non-optimized but portable macros */ #define be16atoh(x) ((uint16_t)(((x)[0]<<8)|(x)[1])) #define be32atoh(x) ((uint32_t)(((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])) #define be64atoh(x) ((uint64_t)(((x)[0]<<56)|((x)[1]<<48)|((x)[2]<<40)| \\ ((x)[3]<<32)|((x)[4]<<24)|((x)[5]<<16)|((x)[6]<<8)|(x)[7])) #define le16atoh(x) ((uint16_t)(((x)[1]<<8)|(x)[0])) #define le32atoh(x) ((uint32_t)(((x)[3]<<24)|((x)[2]<<16)|((x)[1]<<8)|(x)[0])) #define le64atoh(x) ((uint64_t)(((x)[7]<<56)|((x)[6]<<48)|((x)[5]<<40)| \\ ((x)[4]<<32)|((x)[3]<<24)|((x)[2]<<16)|((x)[1]<<8)|(x)[0])) #define htobe16a(a,x) (a)[0]=(uint8_t)((x)>>8), (a)[1]=(uint8_t)(x) #define htobe32a(a,x) (a)[0]=(uint8_t)((x)>>24), (a)[1]=(uint8_t)((x)>>16), \\ (a)[2]=(uint8_t)((x)>>8), (a)[3]=(uint8_t)(x) #define htobe64a(a,x) (a)[0]=(uint8_t)((x)>>56), (a)[1]=(uint8_t)((x)>>48), \\ (a)[2]=(uint8_t)((x)>>40), (a)[3]=(uint8_t)((x)>>32), \\ (a)[4]=(uint8_t)((x)>>24), (a)[5]=(uint8_t)((x)>>16), \\ (a)[6]=(uint8_t)((x)>>8), (a)[7]=(uint8_t)(x) #define htole16a(a,x) (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) #define htole32a(a,x) (a)[3]=(uint8_t)((x)>>24), (a)[2]=(uint8_t)((x)>>16), \\ (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) #define htole64a(a,x) (a)[7]=(uint8_t)((x)>>56), (a)[6]=(uint8_t)((x)>>48), \\ (a)[5]=(uint8_t)((x)>>40), (a)[4]=(uint8_t)((x)>>32), \\ (a)[3]=(uint8_t)((x)>>24), (a)[2]=(uint8_t)((x)>>16), \\ (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) EOF ;; esac ] cat >> "$ac_byteorder" << EOF #endif /*__BYTEORDER_H*/ EOF if cmp -s $ac_byteorder_h $ac_byteorder 2>/dev/null; then AC_MSG_NOTICE([$ac_byteorder_h is unchanged]) rm $ac_byteorder else rm -f $ac_byteorder_h mv $ac_byteorder $ac_byteorder_h fi ]) sane-backends-1.0.27/m4/lib-link.m40000664000175000017500000010020212775312262013507 00000000000000# lib-link.m4 serial 21 (gettext-0.18) dnl Copyright (C) 2001-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_PREREQ([2.54]) dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and dnl augments the CPPFLAGS variable. dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) pushdef([Name],[translit([$1],[./-], [___])]) pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" ac_cv_lib[]Name[]_cppflags="$INC[]NAME" ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" ]) LIB[]NAME="$ac_cv_lib[]Name[]_libs" LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" INC[]NAME="$ac_cv_lib[]Name[]_cppflags" LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) AC_SUBST([LIB]NAME[_PREFIX]) dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the dnl results of this search when this library appears as a dependency. HAVE_LIB[]NAME=yes popdef([NAME]) popdef([Name]) ]) dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message]) dnl searches for libname and the libraries corresponding to explicit and dnl implicit dependencies, together with the specified include files and dnl the ability to compile and link the specified testcode. The missing-message dnl defaults to 'no' and may contain additional hints for the user. dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) pushdef([Name],[translit([$1],[./-], [___])]) pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. AC_LIB_LINKFLAGS_BODY([$1], [$2]) dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, dnl because if the user has installed lib[]Name and not disabled its use dnl via --without-lib[]Name-prefix, he wants to use it. ac_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS, dnl because these -l options might require -L options that are present in dnl LIBS. -l options benefit only from the -L options listed before it. dnl Otherwise, add it to the front of LIBS, because it may be a static dnl library that depends on another static library that is present in LIBS. dnl Static libraries benefit only from the static libraries listed after dnl it. case " $LIB[]NAME" in *" -l"*) LIBS="$LIBS $LIB[]NAME" ;; *) LIBS="$LIB[]NAME $LIBS" ;; esac AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])']) LIBS="$ac_save_LIBS" ]) if test "$ac_cv_lib[]Name" = yes; then HAVE_LIB[]NAME=yes AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.]) AC_MSG_CHECKING([how to link with lib[]$1]) AC_MSG_RESULT([$LIB[]NAME]) else HAVE_LIB[]NAME=no dnl If $LIB[]NAME didn't lead to a usable library, we don't need dnl $INC[]NAME either. CPPFLAGS="$ac_save_CPPFLAGS" LIB[]NAME= LTLIB[]NAME= LIB[]NAME[]_PREFIX= fi AC_SUBST([HAVE_LIB]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) AC_SUBST([LIB]NAME[_PREFIX]) popdef([NAME]) popdef([Name]) ]) dnl Determine the platform dependent parameters needed to use rpath: dnl acl_libext, dnl acl_shlibext, dnl acl_hardcode_libdir_flag_spec, dnl acl_hardcode_libdir_separator, dnl acl_hardcode_direct, dnl acl_hardcode_minus_L. AC_DEFUN([AC_LIB_RPATH], [ dnl Tell automake >= 1.10 to complain if config.rpath is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" acl_libext="$acl_cv_libext" acl_shlibext="$acl_cv_shlibext" acl_libname_spec="$acl_cv_libname_spec" acl_library_names_spec="$acl_cv_library_names_spec" acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" acl_hardcode_direct="$acl_cv_hardcode_direct" acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" dnl Determine whether the user wants rpath handling at all. AC_ARG_ENABLE([rpath], [ --disable-rpath do not hardcode runtime library paths], :, enable_rpath=yes) ]) dnl AC_LIB_FROMPACKAGE(name, package) dnl declares that libname comes from the given package. The configure file dnl will then not have a --with-libname-prefix option but a dnl --with-package-prefix option. Several libraries can come from the same dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar dnl macro call that searches for libname. AC_DEFUN([AC_LIB_FROMPACKAGE], [ pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) define([acl_frompackage_]NAME, [$2]) popdef([NAME]) pushdef([PACK],[$2]) pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) define([acl_libsinpackage_]PACKUP, m4_ifdef([acl_libsinpackage_]PACKUP, [acl_libsinpackage_]PACKUP[[, ]],)[lib$1]) popdef([PACKUP]) popdef([PACK]) ]) dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) dnl Autoconf >= 2.61 supports dots in --with options. pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit(PACK,[.],[_])],PACK)]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_ARG_WITH(P_A_C_K[-prefix], [[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" if test "$acl_libdirstem2" != "$acl_libdirstem" \ && ! test -d "$withval/$acl_libdirstem"; then additional_libdir="$withval/$acl_libdirstem2" fi fi fi ]) dnl Search the library and its dependencies in $additional_libdir and dnl $LDFLAGS. Using breadth-first-seach. LIB[]NAME= LTLIB[]NAME= INC[]NAME= LIB[]NAME[]_PREFIX= dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been dnl computed. So it has to be reset here. HAVE_LIB[]NAME= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='$1 $2' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" else dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined dnl that this library doesn't exist. So just drop it. : fi else dnl Search the library lib$name in $additional_libdir and $LDFLAGS dnl and the already constructed $LIBNAME/$LTLIBNAME. found_dir= found_la= found_so= found_a= eval libname=\"$acl_libname_spec\" # typically: libname=lib$name if test -n "$acl_shlibext"; then shrext=".$acl_shlibext" # typically: shrext=.so else shrext= fi if test $use_additional = yes; then dir="$additional_libdir" dnl The same code as in the loop below: dnl First look for a shared library. if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi dnl Then look for a static library. if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` dnl First look for a shared library. if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi dnl Then look for a static library. if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then dnl Found the library. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. if test "$enable_rpath" = no \ || test "X$found_dir" = "X/usr/$acl_libdirstem" \ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. if test "$acl_hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else dnl Rely on "-L$found_dir". dnl But don't add it if it's already contained in the LDFLAGS dnl or the already constructed $LIBNAME haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi if test "$acl_hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then dnl Linking with a static library. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" else dnl We shouldn't come here, but anyway it's good to have a dnl fallback. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" fi fi dnl Assume the include files are nearby. additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` if test "$name" = '$1'; then LIB[]NAME[]_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; */$acl_libdirstem2 | */$acl_libdirstem2/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` if test "$name" = '$1'; then LIB[]NAME[]_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then dnl Potentially add $additional_includedir to $INCNAME. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's /usr/local/include and we are using GCC on Linux, dnl 3. if it's already present in $CPPFLAGS or the already dnl constructed $INCNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else dnl The -rpath options are cumulative. for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then dnl When using libtool, the option that works for both libraries and dnl executables is -R. The -R options are cumulative. for found_dir in $ltrpathdirs; do LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi popdef([P_A_C_K]) popdef([PACKLIBS]) popdef([PACKUP]) popdef([PACK]) popdef([NAME]) ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, dnl unless already present in VAR. dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes dnl contains two or three consecutive elements that belong together. AC_DEFUN([AC_LIB_APPENDTOVAR], [ for element in [$2]; do haveit= for x in $[$1]; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then [$1]="${[$1]}${[$1]:+ }$element" fi done ]) dnl For those cases where a variable contains several -L and -l options dnl referring to unknown libraries and directories, this macro determines the dnl necessary additional linker options for the runtime path. dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) dnl sets LDADDVAR to linker options needed together with LIBSVALUE. dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, dnl otherwise linking without libtool is assumed. AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], [ AC_REQUIRE([AC_LIB_RPATH]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) $1= if test "$enable_rpath" != no; then if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then dnl Use an explicit option to hardcode directories into the resulting dnl binary. rpathdirs= next= for opt in $2; do if test -n "$next"; then dir="$next" dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem" \ && test "X$dir" != "X/usr/$acl_libdirstem2"; then rpathdirs="$rpathdirs $dir" fi next= else case $opt in -L) next=yes ;; -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem" \ && test "X$dir" != "X/usr/$acl_libdirstem2"; then rpathdirs="$rpathdirs $dir" fi next= ;; *) next= ;; esac fi done if test "X$rpathdirs" != "X"; then if test -n ""$3""; then dnl libtool is used for linking. Use -R options. for dir in $rpathdirs; do $1="${$1}${$1:+ }-R$dir" done else dnl The linker is used for linking directly. if test -n "$acl_hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user dnl must pass all path elements in one option. alldirs= for dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="$flag" else dnl The -rpath options are cumulative. for dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="${$1}${$1:+ }$flag" done fi fi fi fi fi AC_SUBST([$1]) ]) sane-backends-1.0.27/m4/lib-prefix.m40000664000175000017500000002042212775312262014054 00000000000000# lib-prefix.m4 serial 7 (gettext-0.18) dnl Copyright (C) 2001-2005, 2008-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], [AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib-prefix], [ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib --without-lib-prefix don't search for libraries in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi ]) if test $use_additional = yes; then dnl Potentially add $additional_includedir to $CPPFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's already present in $CPPFLAGS, dnl 3. if it's /usr/local/include and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= for x in $CPPFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= for x in $LDFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LDFLAGS. LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" fi fi fi fi fi ]) dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, dnl acl_final_exec_prefix, containing the values to which $prefix and dnl $exec_prefix will expand at the end of the configure script. AC_DEFUN([AC_LIB_PREPARE_PREFIX], [ dnl Unfortunately, prefix and exec_prefix get only finally determined dnl at the end of configure. if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" ]) dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the dnl variables prefix and exec_prefix bound to the values they will have dnl at the end of the configure script. AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], [ acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" $1 exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" ]) dnl AC_LIB_PREPARE_MULTILIB creates dnl - a variable acl_libdirstem, containing the basename of the libdir, either dnl "lib" or "lib64" or "lib/64", dnl - a variable acl_libdirstem2, as a secondary possible value for dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or dnl "lib/amd64". AC_DEFUN([AC_LIB_PREPARE_MULTILIB], [ dnl There is no formal standard regarding lib and lib64. dnl On glibc systems, the current practice is that on a system supporting dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine dnl the compiler's default mode by looking at the compiler's library search dnl path. If at least one of its elements ends in /lib64 or points to a dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. dnl Otherwise we use the default, namely "lib". dnl On Solaris systems, the current practice is that on a system supporting dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. AC_REQUIRE([AC_CANONICAL_HOST]) acl_libdirstem=lib acl_libdirstem2= case "$host_os" in solaris*) dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment dnl . dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the dnl symlink is missing, so we set acl_libdirstem2 too. AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], [AC_EGREP_CPP([sixtyfour bits], [ #ifdef _LP64 sixtyfour bits #endif ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) ]) if test $gl_cv_solaris_64bit = yes; then acl_libdirstem=lib/64 case "$host_cpu" in sparc*) acl_libdirstem2=lib/sparcv9 ;; i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; esac fi ;; *) searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test -n "$searchpath"; then acl_save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; */../ | */.. ) # Better ignore directories of this form. They are misleading. ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) acl_libdirstem=lib64 ;; esac ;; esac fi done IFS="$acl_save_IFS" fi ;; esac test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" ]) sane-backends-1.0.27/m4/ltsugar.m40000664000175000017500000001042412112021330013447 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) sane-backends-1.0.27/m4/nls.m40000664000175000017500000000231512775312262012610 00000000000000# nls.m4 serial 5 (gettext-0.18) dnl Copyright (C) 1995-2003, 2005-2006, 2008-2010 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ([2.50]) AC_DEFUN([AM_NLS], [ AC_MSG_CHECKING([whether NLS is requested]) dnl Default is enabled NLS AC_ARG_ENABLE([nls], [ --disable-nls do not use Native Language Support], USE_NLS=$enableval, USE_NLS=yes) AC_MSG_RESULT([$USE_NLS]) AC_SUBST([USE_NLS]) ]) sane-backends-1.0.27/m4/po.m40000664000175000017500000004461612775312262012444 00000000000000# po.m4 serial 17 (gettext-0.18) dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ([2.50]) dnl Checks for all prerequisites of the po subdirectory. AC_DEFUN([AM_PO_SUBDIRS], [ AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake AC_REQUIRE([AM_NLS])dnl dnl Release version of the gettext macros. This is used to ensure that dnl the gettext macros and po/Makefile.in.in are in sync. AC_SUBST([GETTEXT_MACRO_VERSION], [0.18]) dnl Perform the following tests also if --disable-nls has been given, dnl because they are needed for "make dist" to work. dnl Search for GNU msgfmt in the PATH. dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. dnl The second test excludes FreeBSD msgfmt. AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) dnl Test whether it is GNU msgfmt >= 0.15. changequote(,)dnl case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; *) MSGFMT_015=$MSGFMT ;; esac changequote([,])dnl AC_SUBST([MSGFMT_015]) changequote(,)dnl case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; *) GMSGFMT_015=$GMSGFMT ;; esac changequote([,])dnl AC_SUBST([GMSGFMT_015]) dnl Search for GNU xgettext 0.12 or newer in the PATH. dnl The first test excludes Solaris xgettext and early GNU xgettext versions. dnl The second test excludes FreeBSD xgettext. AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) dnl Remove leftover from FreeBSD xgettext call. rm -f messages.po dnl Test whether it is GNU xgettext >= 0.15. changequote(,)dnl case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; *) XGETTEXT_015=$XGETTEXT ;; esac changequote([,])dnl AC_SUBST([XGETTEXT_015]) dnl Search for GNU msgmerge 0.11 or newer in the PATH. AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) dnl Installation directories. dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we dnl have to define it here, so that it can be used in po/Makefile. test -n "$localedir" || localedir='${datadir}/locale' AC_SUBST([localedir]) dnl Support for AM_XGETTEXT_OPTION. test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) AC_CONFIG_COMMANDS([po-directories], [[ for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) # Compute UPDATEPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) # Compute DUMMYPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) # Compute GMOFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= UPDATEPOFILES= DUMMYPOFILES= GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done]], [# Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake < 1.5. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" ]) ]) dnl Postprocesses a Makefile in a directory containing PO files. AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], [ # When this code is run, in config.status, two variables have already been # set: # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, # - LINGUAS is the value of the environment variable LINGUAS at configure # time. changequote(,)dnl # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Find a way to echo strings without interpreting backslash. if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then gt_echo='echo' else if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then gt_echo='printf %s\n' else echo_func () { cat < "$ac_file.tmp" if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` cat >> "$ac_file.tmp" < /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` cat >> "$ac_file.tmp" <> "$ac_file.tmp" <], [CFPreferencesCopyAppValue(NULL, NULL)], [gt_cv_func_CFPreferencesCopyAppValue=yes], [gt_cv_func_CFPreferencesCopyAppValue=no]) LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) fi dnl Check for API introduced in MacOS X 10.3. AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], [gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], [gt_cv_func_CFLocaleCopyCurrent=yes], [gt_cv_func_CFLocaleCopyCurrent=no]) LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFLocaleCopyCurrent = yes; then AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi AC_SUBST([INTL_MACOSX_LIBS]) ]) sane-backends-1.0.27/m4/iconv.m40000664000175000017500000001653712775312262013145 00000000000000# iconv.m4 serial 11 (gettext-0.18.1) dnl Copyright (C) 2000-2002, 2007-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], [ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_LIB_LINKFLAGS_BODY([iconv]) ]) AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) dnl Add $INCICONV to CPPFLAGS before performing the following checks, dnl because if the user has installed libiconv and not disabled its use dnl via --without-libiconv-prefix, he wants to use it. The first dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], [am_cv_func_iconv=yes]) if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], [am_cv_lib_iconv=yes] [am_cv_func_iconv=yes]) LIBS="$am_save_LIBS" fi ]) if test "$am_cv_func_iconv" = yes; then AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ dnl This tests against bugs in AIX 5.1, HP-UX 11.11, Solaris 10. am_save_LIBS="$LIBS" if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi AC_TRY_RUN([ #include #include int main () { /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { static const char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } /* Test against Solaris 10 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); if (cd_ascii_to_88591 != (iconv_t)(-1)) { static const char input[] = "\263"; char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_ascii_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } #if 0 /* This bug could be worked around by the caller. */ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ { iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) return 1; } } #endif /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is provided. */ if (/* Try standardized names. */ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) /* Try IRIX, OSF/1 names. */ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) /* Try AIX names. */ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) /* Try HP-UX names. */ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) return 1; return 0; }], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no], [case "$host_os" in aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; *) am_cv_func_iconv_works="guessing yes" ;; esac]) LIBS="$am_save_LIBS" ]) case "$am_cv_func_iconv_works" in *no) am_func_iconv=no am_cv_lib_iconv=no ;; *) am_func_iconv=yes ;; esac else am_func_iconv=no am_cv_lib_iconv=no fi if test "$am_func_iconv" = yes; then AC_DEFINE([HAVE_ICONV], [1], [Define if you have the iconv() function and it works.]) fi if test "$am_cv_lib_iconv" = yes; then AC_MSG_CHECKING([how to link with libiconv]) AC_MSG_RESULT([$LIBICONV]) else dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV dnl either. CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi AC_SUBST([LIBICONV]) AC_SUBST([LTLIBICONV]) ]) dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to dnl avoid warnings like dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". dnl This is tricky because of the way 'aclocal' is implemented: dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. dnl Otherwise aclocal's initial scan pass would miss the macro definition. dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. dnl Otherwise aclocal would emit many "Use of uninitialized value $1" dnl warnings. m4_define([gl_iconv_AC_DEFUN], m4_version_prereq([2.64], [[AC_DEFUN_ONCE( [$1], [$2])]], [[AC_DEFUN( [$1], [$2])]])) gl_iconv_AC_DEFUN([AM_ICONV], [ AM_ICONV_LINK if test "$am_cv_func_iconv" = yes; then AC_MSG_CHECKING([for iconv declaration]) AC_CACHE_VAL([am_cv_proto_iconv], [ AC_TRY_COMPILE([ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif ], [], [am_cv_proto_iconv_arg1=""], [am_cv_proto_iconv_arg1="const"]) am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` AC_MSG_RESULT([ $am_cv_proto_iconv]) AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], [Define as const if the declaration of iconv() needs const.]) fi ]) sane-backends-1.0.27/m4/libtool.m40000664000175000017500000106011113106201017013437 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS sane-backends-1.0.27/m4/ltversion.m40000664000175000017500000000126212775312262014041 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) sane-backends-1.0.27/m4/progtest.m40000664000175000017500000000557312775312262013674 00000000000000# progtest.m4 serial 6 (gettext-0.18) dnl Copyright (C) 1996-2003, 2005, 2008-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1996. AC_PREREQ([2.50]) # Search path for a program which passes the given test. dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) AC_DEFUN([AM_PATH_PROG_WITH_TEST], [ # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL([ac_cv_path_$1], [case "[$]$1" in [[\\/]]* | ?:[[\\/]]*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in ifelse([$5], , $PATH, [$5]); do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$][$1]) else AC_MSG_RESULT([no]) fi AC_SUBST([$1])dnl ]) sane-backends-1.0.27/m4/lt~obsolete.m40000664000175000017500000001375612112021330014353 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) sane-backends-1.0.27/m4/ltoptions.m40000664000175000017500000003007312775312262014051 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) sane-backends-1.0.27/m4/stdint.m40000664000175000017500000005640012112021330013277 00000000000000dnl @synopsis AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])] dnl dnl the "ISO C9X: 7.18 Integer types " section requires the dnl existence of an include file that defines a set of dnl typedefs, especially uint8_t,int32_t,uintptr_t. Many older dnl installations will not provide this file, but some will have the dnl very same definitions in . In other enviroments we can dnl use the inet-types in which would define the typedefs dnl int8_t and u_int8_t respectivly. dnl dnl This macros will create a local "_stdint.h" or the headerfile given dnl as an argument. In many cases that file will just "#include dnl " or "#include ", while in other environments dnl it will provide the set of basic 'stdint's definitions/typedefs: dnl dnl int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t dnl int_least32_t.. int_fast32_t.. intmax_t dnl dnl which may or may not rely on the definitions of other files, or dnl using the AC_CHECK_SIZEOF macro to determine the actual sizeof each dnl type. dnl dnl if your header files require the stdint-types you will want to dnl create an installable file mylib-int.h that all your other dnl installable header may include. So if you have a library package dnl named "mylib", just use dnl dnl AX_CREATE_STDINT_H(mylib-int.h) dnl dnl in configure.ac and go to install that very header file in dnl Makefile.am along with the other headers (mylib.h) - and the dnl mylib-specific headers can simply use "#include " to dnl obtain the stdint-types. dnl dnl Remember, if the system already had a valid , the dnl generated file will include it directly. No need for fuzzy dnl HAVE_STDINT_H things... (oops, GCC 4.2.x has deliberatly disabled dnl its stdint.h for non-c99 compilation and the c99-mode is not the dnl default. Therefore this macro will not use the compiler's stdint.h dnl - please complain to the GCC developers). dnl dnl @category C dnl @author Guido U. Draheim dnl @version 2006-10-13 dnl @license GPLWithACException AC_DEFUN([AX_CHECK_DATA_MODEL],[ AC_CHECK_SIZEOF(char) AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(void*) ac_cv_char_data_model="" ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char" ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short" ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int" ac_cv_long_data_model="" ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int" ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long" ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp" AC_MSG_CHECKING([data model]) case "$ac_cv_char_data_model/$ac_cv_long_data_model" in 122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;; 122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;; 122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;; 124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;; 124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;; 124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;; 124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;; 128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;; 128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;; 222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;; 333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;; 444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;; 666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;; 888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;; 222/*|333/*|444/*|666/*|888/*) : ac_cv_data_model="iDSP" ; n="unusual dsptype" ;; *) ac_cv_data_model="none" ; n="very unusual model" ;; esac AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)]) ]) dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF]) AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[ AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[ ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) AC_MSG_RESULT([(..)]) for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h]) do unset ac_cv_type_uintptr_t unset ac_cv_type_uint64_t AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>]) AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) m4_ifvaln([$1],[$1]) break done AC_MSG_CHECKING([for stdint uintptr_t]) ]) ]) AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[ AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[ ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) AC_MSG_RESULT([(..)]) for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h]) do unset ac_cv_type_uint32_t unset ac_cv_type_uint64_t AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>]) AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) m4_ifvaln([$1],[$1]) break break; done AC_MSG_CHECKING([for stdint uint32_t]) ]) ]) AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[ AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[ ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) AC_MSG_RESULT([(..)]) for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do unset ac_cv_type_u_int32_t unset ac_cv_type_u_int64_t AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>]) AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>]) m4_ifvaln([$1],[$1]) break break; done AC_MSG_CHECKING([for stdint u_int32_t]) ]) ]) AC_DEFUN([AX_CREATE_STDINT_H], [# ------ AX CREATE STDINT H ------------------------------------- AC_MSG_CHECKING([for stdint types]) ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` # try to shortcircuit - if the default include path of the compiler # can find a "stdint.h" header then we assume that all compilers can. AC_CACHE_VAL([ac_cv_header_stdint_t],[ old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" old_CFLAGS="$CFLAGS" ; CFLAGS="" AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], [ac_cv_stdint_result="(assuming C99 compatible system)" ac_cv_header_stdint_t="stdint.h"; ], [ac_cv_header_stdint_t=""]) if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then CFLAGS="-std=c99" AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], [AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)]) fi CXXFLAGS="$old_CXXFLAGS" CPPFLAGS="$old_CPPFLAGS" CFLAGS="$old_CFLAGS" ]) v="... $ac_cv_header_stdint_h" if test "$ac_stdint_h" = "stdint.h" ; then AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)]) elif test "$ac_stdint_h" = "inttypes.h" ; then AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)]) elif test "_$ac_cv_header_stdint_t" = "_" ; then AC_MSG_RESULT([(putting them into $ac_stdint_h)$v]) else ac_cv_header_stdint="$ac_cv_header_stdint_t" AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)]) fi if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. dnl .....intro message done, now do a few system checks..... dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type, dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW dnl instead that is triggered with 3 or more arguments (see types.m4) inttype_headers=`echo $2 | sed -e 's/,/ /g'` ac_cv_stdint_result="(no helpful system typedefs seen)" AX_CHECK_HEADER_STDINT_X(dnl stdint.h inttypes.h sys/inttypes.h $inttype_headers, ac_cv_stdint_result="(seen uintptr_t$and64 in $i)") if test "_$ac_cv_header_stdint_x" = "_" ; then AX_CHECK_HEADER_STDINT_O(dnl, inttypes.h sys/inttypes.h stdint.h $inttype_headers, ac_cv_stdint_result="(seen uint32_t$and64 in $i)") fi if test "_$ac_cv_header_stdint_x" = "_" ; then if test "_$ac_cv_header_stdint_o" = "_" ; then AX_CHECK_HEADER_STDINT_U(dnl, sys/types.h inttypes.h sys/inttypes.h $inttype_headers, ac_cv_stdint_result="(seen u_int32_t$and64 in $i)") fi fi dnl if there was no good C99 header file, do some typedef checks... if test "_$ac_cv_header_stdint_x" = "_" ; then AC_MSG_CHECKING([for stdint datatype model]) AC_MSG_RESULT([(..)]) AX_CHECK_DATA_MODEL fi if test "_$ac_cv_header_stdint_x" != "_" ; then ac_cv_header_stdint="$ac_cv_header_stdint_x" elif test "_$ac_cv_header_stdint_o" != "_" ; then ac_cv_header_stdint="$ac_cv_header_stdint_o" elif test "_$ac_cv_header_stdint_u" != "_" ; then ac_cv_header_stdint="$ac_cv_header_stdint_u" else ac_cv_header_stdint="stddef.h" fi AC_MSG_CHECKING([for extra inttypes in chosen header]) AC_MSG_RESULT([($ac_cv_header_stdint)]) dnl see if int_least and int_fast types are present in _this_ header. unset ac_cv_type_int_least32_t unset ac_cv_type_int_fast32_t AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>]) fi # shortcircut to system "stdint.h" # ------------------ PREPARE VARIABLES ------------------------------ if test "$GCC" = "yes" ; then ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1` else ac_cv_stdint_message="using $CC" fi AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl $ac_cv_stdint_result]) dnl ----------------------------------------------------------------- # ----------------- DONE inttypes.h checks START header ------------- AC_CONFIG_COMMANDS([$ac_stdint_h],[ AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h) ac_stdint=$tmp/_stdint.h echo "#ifndef" $_ac_stdint_h >$ac_stdint echo "#define" $_ac_stdint_h "1" >>$ac_stdint echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint if test "_$ac_cv_header_stdint_t" != "_" ; then echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint echo "#include " >>$ac_stdint echo "#endif" >>$ac_stdint echo "#endif" >>$ac_stdint else cat >>$ac_stdint < #else #include /* .................... configured part ............................ */ STDINT_EOF echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint if test "_$ac_cv_header_stdint_x" != "_" ; then ac_header="$ac_cv_header_stdint_x" echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint else echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint fi echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint if test "_$ac_cv_header_stdint_o" != "_" ; then ac_header="$ac_cv_header_stdint_o" echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint else echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint fi echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint if test "_$ac_cv_header_stdint_u" != "_" ; then ac_header="$ac_cv_header_stdint_u" echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint else echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint fi echo "" >>$ac_stdint if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then echo "#include <$ac_header>" >>$ac_stdint echo "" >>$ac_stdint fi fi echo "/* which 64bit typedef has been found */" >>$ac_stdint if test "$ac_cv_type_uint64_t" = "yes" ; then echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint fi if test "$ac_cv_type_u_int64_t" = "yes" ; then echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint fi echo "" >>$ac_stdint echo "/* which type model has been detected */" >>$ac_stdint if test "_$ac_cv_char_data_model" != "_" ; then echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint else echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint fi echo "" >>$ac_stdint echo "/* whether int_least types were detected */" >>$ac_stdint if test "$ac_cv_type_int_least32_t" = "yes"; then echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint fi echo "/* whether int_fast types were detected */" >>$ac_stdint if test "$ac_cv_type_int_fast32_t" = "yes"; then echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint fi echo "/* whether intmax_t type was detected */" >>$ac_stdint if test "$ac_cv_type_intmax_t" = "yes"; then echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint fi echo "" >>$ac_stdint cat >>$ac_stdint <= 199901L #define _HAVE_UINT64_T #define _HAVE_LONGLONG_UINT64_T typedef long long int64_t; typedef unsigned long long uint64_t; #elif !defined __STRICT_ANSI__ #if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ #define _HAVE_UINT64_T typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ /* note: all ELF-systems seem to have loff-support which needs 64-bit */ #if !defined _NO_LONGLONG #define _HAVE_UINT64_T #define _HAVE_LONGLONG_UINT64_T typedef long long int64_t; typedef unsigned long long uint64_t; #endif #elif defined __alpha || (defined __mips && defined _ABIN32) #if !defined _NO_LONGLONG typedef long int64_t; typedef unsigned long uint64_t; #endif /* compiler/cpu type to define int64_t */ #endif #endif #endif #if defined _STDINT_HAVE_U_INT_TYPES /* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */ typedef u_int8_t uint8_t; typedef u_int16_t uint16_t; typedef u_int32_t uint32_t; /* glibc compatibility */ #ifndef __int8_t_defined #define __int8_t_defined #endif #endif #ifdef _STDINT_NEED_INT_MODEL_T /* we must guess all the basic types. Apart from byte-adressable system, */ /* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */ /* (btw, those nibble-addressable systems are way off, or so we assume) */ dnl /* have a look at "64bit and data size neutrality" at */ dnl /* http://unix.org/version2/whatsnew/login_64bit.html */ dnl /* (the shorthand "ILP" types always have a "P" part) */ #if defined _STDINT_BYTE_MODEL #if _STDINT_LONG_MODEL+0 == 242 /* 2:4:2 = IP16 = a normal 16-bit system */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; #ifndef __int8_t_defined #define __int8_t_defined typedef char int8_t; typedef short int16_t; typedef long int32_t; #endif #elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444 /* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */ /* 4:4:4 = ILP32 = a normal 32-bit system */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #ifndef __int8_t_defined #define __int8_t_defined typedef char int8_t; typedef short int16_t; typedef int int32_t; #endif #elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488 /* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */ /* 4:8:8 = LP64 = a normal 64-bit system */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #ifndef __int8_t_defined #define __int8_t_defined typedef char int8_t; typedef short int16_t; typedef int int32_t; #endif /* this system has a "long" of 64bit */ #ifndef _HAVE_UINT64_T #define _HAVE_UINT64_T typedef unsigned long uint64_t; typedef long int64_t; #endif #elif _STDINT_LONG_MODEL+0 == 448 /* LLP64 a 64-bit system derived from a 32-bit system */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #ifndef __int8_t_defined #define __int8_t_defined typedef char int8_t; typedef short int16_t; typedef int int32_t; #endif /* assuming the system has a "long long" */ #ifndef _HAVE_UINT64_T #define _HAVE_UINT64_T #define _HAVE_LONGLONG_UINT64_T typedef unsigned long long uint64_t; typedef long long int64_t; #endif #else #define _STDINT_NO_INT32_T #endif #else #define _STDINT_NO_INT8_T #define _STDINT_NO_INT32_T #endif #endif /* * quote from SunOS-5.8 sys/inttypes.h: * Use at your own risk. As of February 1996, the committee is squarely * behind the fixed sized types; the "least" and "fast" types are still being * discussed. The probability that the "fast" types may be removed before * the standard is finalized is high enough that they are not currently * implemented. */ #if defined _STDINT_NEED_INT_LEAST_T typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; #ifdef _HAVE_UINT64_T typedef int64_t int_least64_t; #endif typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; #ifdef _HAVE_UINT64_T typedef uint64_t uint_least64_t; #endif /* least types */ #endif #if defined _STDINT_NEED_INT_FAST_T typedef int8_t int_fast8_t; typedef int int_fast16_t; typedef int32_t int_fast32_t; #ifdef _HAVE_UINT64_T typedef int64_t int_fast64_t; #endif typedef uint8_t uint_fast8_t; typedef unsigned uint_fast16_t; typedef uint32_t uint_fast32_t; #ifdef _HAVE_UINT64_T typedef uint64_t uint_fast64_t; #endif /* fast types */ #endif #ifdef _STDINT_NEED_INTMAX_T #ifdef _HAVE_UINT64_T typedef int64_t intmax_t; typedef uint64_t uintmax_t; #else typedef long intmax_t; typedef unsigned long uintmax_t; #endif #endif #ifdef _STDINT_NEED_INTPTR_T #ifndef __intptr_t_defined #define __intptr_t_defined /* we encourage using "long" to store pointer values, never use "int" ! */ #if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484 typedef unsigned int uintptr_t; typedef int intptr_t; #elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444 typedef unsigned long uintptr_t; typedef long intptr_t; #elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T typedef uint64_t uintptr_t; typedef int64_t intptr_t; #else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */ typedef unsigned long uintptr_t; typedef long intptr_t; #endif #endif #endif /* The ISO C99 standard specifies that in C++ implementations these should only be defined if explicitly requested. */ #if !defined __cplusplus || defined __STDC_CONSTANT_MACROS #ifndef UINT32_C /* Signed. */ # define INT8_C(c) c # define INT16_C(c) c # define INT32_C(c) c # ifdef _HAVE_LONGLONG_UINT64_T # define INT64_C(c) c ## L # else # define INT64_C(c) c ## LL # endif /* Unsigned. */ # define UINT8_C(c) c ## U # define UINT16_C(c) c ## U # define UINT32_C(c) c ## U # ifdef _HAVE_LONGLONG_UINT64_T # define UINT64_C(c) c ## UL # else # define UINT64_C(c) c ## ULL # endif /* Maximal type. */ # ifdef _HAVE_LONGLONG_UINT64_T # define INTMAX_C(c) c ## L # define UINTMAX_C(c) c ## UL # else # define INTMAX_C(c) c ## LL # define UINTMAX_C(c) c ## ULL # endif /* literalnumbers */ #endif #endif /* These limits are merily those of a two complement byte-oriented system */ /* Minimum of signed integral types. */ # define INT8_MIN (-128) # define INT16_MIN (-32767-1) # define INT32_MIN (-2147483647-1) # define INT64_MIN (-__INT64_C(9223372036854775807)-1) /* Maximum of signed integral types. */ # define INT8_MAX (127) # define INT16_MAX (32767) # define INT32_MAX (2147483647) # define INT64_MAX (__INT64_C(9223372036854775807)) /* Maximum of unsigned integral types. */ # define UINT8_MAX (255) # define UINT16_MAX (65535) # define UINT32_MAX (4294967295U) # define UINT64_MAX (__UINT64_C(18446744073709551615)) /* Minimum of signed integral types having a minimum size. */ # define INT_LEAST8_MIN INT8_MIN # define INT_LEAST16_MIN INT16_MIN # define INT_LEAST32_MIN INT32_MIN # define INT_LEAST64_MIN INT64_MIN /* Maximum of signed integral types having a minimum size. */ # define INT_LEAST8_MAX INT8_MAX # define INT_LEAST16_MAX INT16_MAX # define INT_LEAST32_MAX INT32_MAX # define INT_LEAST64_MAX INT64_MAX /* Maximum of unsigned integral types having a minimum size. */ # define UINT_LEAST8_MAX UINT8_MAX # define UINT_LEAST16_MAX UINT16_MAX # define UINT_LEAST32_MAX UINT32_MAX # define UINT_LEAST64_MAX UINT64_MAX /* shortcircuit*/ #endif /* once */ #endif #endif STDINT_EOF fi if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then AC_MSG_NOTICE([$ac_stdint_h is unchanged]) else ac_dir=`AS_DIRNAME(["$ac_stdint_h"])` AS_MKDIR_P(["$ac_dir"]) rm -f $ac_stdint_h mv $ac_stdint $ac_stdint_h fi ],[# variables for create stdint.h replacement PACKAGE="$PACKAGE" VERSION="$VERSION" ac_stdint_h="$ac_stdint_h" _ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h) ac_cv_stdint_message="$ac_cv_stdint_message" ac_cv_header_stdint_t="$ac_cv_header_stdint_t" ac_cv_header_stdint_x="$ac_cv_header_stdint_x" ac_cv_header_stdint_o="$ac_cv_header_stdint_o" ac_cv_header_stdint_u="$ac_cv_header_stdint_u" ac_cv_type_uint64_t="$ac_cv_type_uint64_t" ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" ac_cv_char_data_model="$ac_cv_char_data_model" ac_cv_long_data_model="$ac_cv_long_data_model" ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" ac_cv_type_intmax_t="$ac_cv_type_intmax_t" ]) ]) sane-backends-1.0.27/m4/lib-ld.m40000664000175000017500000000660312775312262013163 00000000000000# lib-ld.m4 serial 4 (gettext-0.18) dnl Copyright (C) 1996-2003, 2009-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], [# I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]* | [A-Za-z]:[\\/]*)] [re_direlt='/[^/][^/]*/\.\./'] # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL([acl_cv_path_LD], [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT([$LD]) else AC_MSG_RESULT([no]) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) sane-backends-1.0.27/mkinstalldirs0000775000175000017500000000672212775312262014046 00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy scriptversion=2009-04-28.21; # UTC # Original author: Noah Friedman # Created: 1993-05-16 # Public domain. # # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' IFS=" "" $nl" errstatus=0 dirmode= usage="\ Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... Create each directory DIR (with mode MODE, if specified), including all leading file name components. Report bugs to ." # process command line arguments while test $# -gt 0 ; do case $1 in -h | --help | --h*) # -h for help echo "$usage" exit $? ;; -m) # -m PERM arg shift test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } dirmode=$1 shift ;; --version) echo "$0 $scriptversion" exit $? ;; --) # stop option processing shift break ;; -*) # unknown option echo "$usage" 1>&2 exit 1 ;; *) # first non-opt arg break ;; esac done for file do if test -d "$file"; then shift else break fi done case $# in 0) exit 0 ;; esac # Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and # mkdir -p a/c at the same time, both will detect that a is missing, # one will create a, then the other will try to create a and die with # a "File exists" error. This is a problem when calling mkinstalldirs # from a parallel make. We use --version in the probe to restrict # ourselves to GNU mkdir, which is thread-safe. case $dirmode in '') if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "mkdir -p -- $*" exec mkdir -p -- "$@" else # On NextStep and OpenStep, the 'mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because '.' already # exists. test -d ./-p && rmdir ./-p test -d ./--version && rmdir ./--version fi ;; *) if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "mkdir -m $dirmode -p -- $*" exec mkdir -m "$dirmode" -p -- "$@" else # Clean up after NextStep and OpenStep mkdir. for d in ./-m ./-p ./--version "./$dirmode"; do test -d $d && rmdir $d done fi ;; esac for file do case $file in /*) pathcomp=/ ;; *) pathcomp= ;; esac oIFS=$IFS IFS=/ set fnord $file shift IFS=$oIFS for d do test "x$d" = x && continue pathcomp=$pathcomp$d case $pathcomp in -*) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr else if test ! -z "$dirmode"; then echo "chmod $dirmode $pathcomp" lasterr= chmod "$dirmode" "$pathcomp" || lasterr=$? if test ! -z "$lasterr"; then errstatus=$lasterr fi fi fi fi pathcomp=$pathcomp/ done done exit $errstatus # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: sane-backends-1.0.27/Makefile.am0000664000175000017500000000642713110564566013276 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. SUBDIRS = include lib sanei backend frontend tools doc po testsuite DIST_SUBDIRS = include lib sanei backend frontend tools doc po japi testsuite dist_doc_DATA = AUTHORS ChangeLog COPYING LICENSE NEWS PROBLEMS PROJECTS \ README README.aix README.beos README.darwin README.djpeg README.freebsd \ README.hp-ux README.linux README.netbsd README.openbsd README.os2 \ README.solaris README.unixware2 README.unixware7 README.windows \ README.zeta EXTRA_DIST = $(PACKAGE).lsm # # Keep the .gitignore files sorted, and use this target to do it. # Note that git's negated ignore patterns introduce order dependency # and should therefor be sorted with much more care than we do here. # Until that has been taken care of, such files are best left alone. # PERL=perl sort-gitignore: for f in `find . -name .gitignore`; do \ if test -n "`sed -n '/^\!/p' $$f`"; then \ echo "$$f: skipping file with negated pattern" >&2; \ fi; \ $(PERL) -e 'print sort <>;' < $$f > $$f.tmptmp; \ mv $$f.tmptmp $$f; \ done # # Check to make sure only sane_ and sanei_ symbols are exported from # the libraries # libcheck: @echo "Libraries exporting 'illegal' symbols:" @for lib in backend/.libs/*.so backend/.libs/*.a; do \ lines=`nm -g $$lib|grep '\( T \)\|\( D \)'|egrep -v ' _fini| _init'|egrep -v ' sane_| sanei_'`; \ if test -n "$$lines" ; then \ echo -e "*** $$lib:\n$$lines"; \ found_errors="yes"; \ fi \ done; \ echo; \ echo "Libraries exporting 'non-standard sane_*' symbols:"; \ for lib in backend/.libs/*.so backend/.libs/*.a; do \ lines=`nm -g $$lib|grep '\( T \)\|\( D \)'|egrep ' sane_' | egrep -v 'sane_.*init|sane_.*exit|sane_.*get_devices|sane_.*open|sane_.*close|sane_.*get_option_descriptor|sane_.*control_option|sane_.*get_parameters|sane_.*start|sane_.*read|sane_.*cancel|sane_.*set_io_mode|sane_.*get_select_fd|sane_strstatus'` ; \ if test -n "$$lines" ; then \ echo -e "*** $$lib:\n$$lines"; \ found_errors="yes"; \ fi \ done; if test ! -z $$found_errors ; then \ exit 1; \ fi # Verify that backends do not contain any unwanted public symbols # anytime check or distcheck is ran. # TODO: Currently this doesn't pass. Uncomment once symbols have # been cleaned up. #check-am: libcheck # Run testsuite any time installcheck or distcheck is ran. # Must run testsuite after install or else shared library backends # will not be found (including test backend). installcheck-local: cd testsuite && $(MAKE) test.local $(distdir).lsm: dist $(PACKAGE).lsm ( cat $(PACKAGE).lsm | \ sed -e "s|_DATE_|`date +%d%b%y`|g" |\ sed -e "s|_VERSION_|$(VERSION)|g" | \ sed -e "s|_T_S_|`find $(distdir).tar.gz -printf "%4k"`|g" |\ sed -e "s|_L_S_|`find $(PACKAGE).lsm -printf "%4k"`|g" >\ $(distdir).lsm \ ) lsm: $(distdir).lsm md5: dist md5sum $(distdir).tar.gz > $(distdir).tar.gz.md5 sane-backends: lsm md5 # Clean files created by custom targets in this file. clean-local: rm -f sane-backends-*.lsm rm -f $(distdir).tar.gz.md5 # Clean files created by configure distclean-local: rm -f include/_stdint.h rm -f include/byteorder.h ACLOCAL_AMFLAGS = -I m4 sane-backends-1.0.27/testsuite/0000775000175000017500000000000013110600540013321 500000000000000sane-backends-1.0.27/testsuite/tools/0000775000175000017500000000000013110600540014461 500000000000000sane-backends-1.0.27/testsuite/tools/README0000664000175000017500000000045212775312262015303 00000000000000TOOLS test suite ================ This directory contains test for tools programs. They are run by 'make check'. sane-desc --------- sane-desc is ran for all known modes, using a test 'desc' file. The output is compared to a reference file for the same mode. Test fails if they are different. sane-backends-1.0.27/testsuite/tools/Makefile.in0000664000175000017500000003644313110564734016476 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = testsuite/tools DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SANEDESC = ../../tools/sane-desc$(EXEEXT) TESTFILE = $(srcdir)/data/testfile.desc OUTFILES = *.res DEVICE = test EXTRA_DIST = data/testfile.desc data/ascii.ref data/db.ref data/hal-new.ref \ data/hal.ref data/html-backends-split.ref data/html-mfgs.ref \ data/hwdb.ref data/plist.ref data/statistics.ref \ data/udev+acl.ref data/udev+hwdb.ref data/udev.ref \ data/usermap.ref data/xml.ref CLEANFILES = $(OUTFILES) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu testsuite/tools/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu testsuite/tools/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am all: @echo "run 'make check' to run tests" all: help help: @echo "Use 'make check' to run the tests." check: check.local check.local: @echo "**** Testing $(SANEDESC) with $(TESTFILE)" @for mode in ascii html-backends-split html-mfgs xml statistics usermap db udev udev+acl udev+hwdb hwdb plist hal hal-new; \ do \ $(SANEDESC) -m $$mode -s $(srcdir)/data >$$mode.res ;\ if diff -I "[ 012][0-9]:[0-5][0-9]:[0-6][0-9] 20[0-9][0-9]" \ -I "sane-backends 1\.0\.[0-9]\+\(git\)\?$$" \ $(srcdir)/data/$$mode.ref $$mode.res ; \ then \ echo "PASS: sane-desc -m $$mode -s $(srcdir)/data"; \ else \ echo "FAIL: sane-desc -m $$mode -s $(srcdir)/data"; \ exit 1 ;\ fi; \ done ;\ echo "================" ;\ echo "All tests passed" ;\ echo "================" # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/testsuite/tools/data/0000775000175000017500000000000013110600540015372 500000000000000sane-backends-1.0.27/testsuite/tools/data/db.ref0000664000175000017500000013065312775312262016426 00000000000000# This file was automatically created based on description files (*.desc) # by sane-desc 3.5 from sane-backends 1.0.24git on Wed Jul 31 07:52:48 2013 # # The entries below are used to detect a USB device when it's plugged in # and then run a script to change the ownership and # permissions on the "device node" used by libusb. # Sample entry (replace 0xVVVV and 0xPPPP with vendor ID and product ID # respectively): # # 0xVVVV0xPPPProot:scanner0664[/usr/local/bin/foo.sh] # Fields: # vendor ID # product ID # ownership (user:group) # permissions # path of an optional script to run (it can be omitted) # # If your scanner isn't listed below, you can add it as explained above. # # If your scanner is supported by some external backend (brother, epkowa, # hpaio, etc) please ask the author of the backend to provide proper # device detection support for your OS # # If the scanner is supported by sane-backends, please mail the entry to # the sane-devel mailing list (sane-devel@lists.alioth.debian.org). # # Hewlett-Packard ScanJet 4100C 0x03f0 0x0101 root:scanner 0664 # Hewlett-Packard ScanJet 4200C | Hewlett-Packard ScanJet 4200Cxi | Hewlett-Packard ScanJet 4200Cse 0x03f0 0x0105 root:scanner 0664 # Hewlett-Packard ScanJet 6200C | Hewlett-Packard ScanJet 6250C 0x03f0 0x0201 root:scanner 0664 # Hewlett-Packard ScanJet 3300c 0x03f0 0x0205 root:scanner 0664 # Hewlett-Packard ScanJet 4300c 0x03f0 0x0305 root:scanner 0664 # Hewlett-Packard ScanJet 5200C 0x03f0 0x0401 root:scanner 0664 # Hewlett-Packard ScanJet 3400c 0x03f0 0x0405 root:scanner 0664 # Hewlett-Packard ScanJet 2100C 0x03f0 0x0505 root:scanner 0664 # Hewlett-Packard ScanJet 6300C | Hewlett-Packard ScanJet 6350C | Hewlett-Packard ScanJet 6390C 0x03f0 0x0601 root:scanner 0664 # Hewlett-Packard ScanJet 2200C 0x03f0 0x0605 root:scanner 0664 # Hewlett-Packard ScanJet 5300C | Hewlett-Packard ScanJet 5370C 0x03f0 0x0701 root:scanner 0664 # Hewlett-Packard scanjet 4400c 0x03f0 0x0705 root:scanner 0664 # Hewlett-Packard ScanJet 7400c | Hewlett-Packard ScanJet 7450c | Hewlett-Packard ScanJet 7490c 0x03f0 0x0801 root:scanner 0664 # Hewlett-Packard scanjet 4470c 0x03f0 0x0805 root:scanner 0664 # Hewlett-Packard ScanJet 2300C 0x03f0 0x0901 root:scanner 0664 # Hewlett-Packard ScanJet 2400C | Hewlett-Packard ScanJet G2410 0x03f0 0x0a01 root:scanner 0664 # Hewlett-Packard ScanJet 8200 | Hewlett-Packard ScanJet 8250 | Hewlett-Packard ScanJet 8290 0x03f0 0x0b01 root:scanner 0664 # Hewlett-Packard ScanJet 5400c 0x03f0 0x1005 root:scanner 0664 # Hewlett-Packard ScanJet 5470c 0x03f0 0x1105 root:scanner 0664 # Hewlett-Packard ScanJet 4500C | Hewlett-Packard ScanJet 5550C 0x03f0 0x1205 root:scanner 0664 # Hewlett-Packard ScanJet 4570C | Hewlett-Packard ScanJet 5500C 0x03f0 0x1305 root:scanner 0664 # Hewlett-Packard ScanJet 3670C | Hewlett-Packard ScanJet 3690C 0x03f0 0x1405 root:scanner 0664 # Hewlett-Packard ScanJet 5590 0x03f0 0x1705 root:scanner 0664 # Hewlett-Packard ScanJet 7650 0x03f0 0x1805 root:scanner 0664 # Hewlett-Packard ScanJet 4850C 0x03f0 0x1b05 root:scanner 0664 # Hewlett-Packard ScanJet 3530C | Hewlett-Packard ScanJet 3570C 0x03f0 0x2005 root:scanner 0664 # Hewlett-Packard ScanJet 3500C 0x03f0 0x2205 root:scanner 0664 # Hewlett-Packard ScanJet 3970c 0x03f0 0x2305 root:scanner 0664 # Hewlett-Packard ScanJet 4070 Photosmart 0x03f0 0x2405 root:scanner 0664 # Hewlett-Packard ScanJet 3800 0x03f0 0x2605 root:scanner 0664 # Hewlett-Packard ScanJet G2710 0x03f0 0x2805 root:scanner 0664 # Hewlett-Packard ScanJet 8300 | Hewlett-Packard ScanJet 8350 | Hewlett-Packard ScanJet 8390 0x03f0 0x3805 root:scanner 0664 # Hewlett-Packard ScanJet 8270 0x03f0 0x3905 root:scanner 0664 # Hewlett-Packard LaserJet M1005 MFP 0x03f0 0x3b17 root:scanner 0664 # Hewlett-Packard ScanJet 4370 0x03f0 0x4105 root:scanner 0664 # Hewlett-Packard ScanJet G3010 0x03f0 0x4205 root:scanner 0664 # Hewlett-Packard ScanJet G3110 0x03f0 0x4305 root:scanner 0664 # Hewlett-Packard ScanJet G4010 0x03f0 0x4505 root:scanner 0664 # Hewlett-Packard ScanJet G4050 0x03f0 0x4605 root:scanner 0664 # Hewlett-Packard ScanJet N6310 0x03f0 0x4705 root:scanner 0664 # Hewlett-Packard LaserJet M1120 MFP 0x03f0 0x5617 root:scanner 0664 # Hewlett-Packard LaserJet M1120n MFP 0x03f0 0x5717 root:scanner 0664 # Mustek BearPaw 1200 0x0400 0x1000 root:scanner 0664 # Mustek BearPaw 1200 | Mustek BearPaw 2400 0x0400 0x1001 root:scanner 0664 # Kodak ESP 5100 0x040a 0x4025 root:scanner 0664 # Kodak ESP 5300 0x040a 0x4026 root:scanner 0664 # Kodak ESP 5500 0x040a 0x4027 root:scanner 0664 # Kodak ESP 5000 0x040a 0x4028 root:scanner 0664 # Kodak ESP 3300 0x040a 0x4031 root:scanner 0664 # Kodak ESP 5 0x040a 0x4032 root:scanner 0664 # Kodak ESP 7 0x040a 0x403e root:scanner 0664 # Kodak ESP 9 0x040a 0x403f root:scanner 0664 # Kodak ESP 5200 0x040a 0x4041 root:scanner 0664 # Kodak ESP 3200 0x040a 0x4043 root:scanner 0664 # Kodak ESP 4100 0x040a 0x4053 root:scanner 0664 # Kodak ESP 6100 0x040a 0x4054 root:scanner 0664 # Kodak ESP 7200 0x040a 0x4056 root:scanner 0664 # Kodak ESP C110 0x040a 0x4057 root:scanner 0664 # Kodak ESP C115 0x040a 0x4058 root:scanner 0664 # Kodak ESP 2150 0x040a 0x4059 root:scanner 0664 # Kodak ESP C310 0x040a 0x405d root:scanner 0664 # Kodak ESP C315 0x040a 0x405e root:scanner 0664 # Advent AW10 0x040a 0x4060 root:scanner 0664 # Kodak Hero Office 6.1 0x040a 0x4062 root:scanner 0664 # Kodak Hero 7.1 0x040a 0x4063 root:scanner 0664 # Kodak Hero 5.1 0x040a 0x4064 root:scanner 0664 # Kodak ESP 9200 0x040a 0x4065 root:scanner 0664 # Kodak ESP 2170 0x040a 0x4066 root:scanner 0664 # Kodak Hero 9.1 0x040a 0x4067 root:scanner 0664 # Kodak Hero 3.1 0x040a 0x406d root:scanner 0664 # Kodak i30 0x040a 0x6001 root:scanner 0664 # Kodak i40 0x040a 0x6002 root:scanner 0664 # Kodak i50 | Kodak i55 0x040a 0x6003 root:scanner 0664 # Kodak i60 | Kodak i65 0x040a 0x6004 root:scanner 0664 # Kodak i80 0x040a 0x6005 root:scanner 0664 # Creative WebCam Go Mini 0x041e 0x4007 root:scanner 0664 # Lexmark X70 | Lexmark X73 0x043d 0x002d root:scanner 0664 # Lexmark X74 0x043d 0x0060 root:scanner 0664 # Lexmark X1110 | Lexmark X1130 | Lexmark X1140 | Lexmark X1150 | Lexmark X1170 | Lexmark X1180 | Lexmark X1185 | Lexmark X1195 0x043d 0x007c root:scanner 0664 # Lexmark X12xx 0x043d 0x007d root:scanner 0664 # Genius ColorPage HR6 V1 0x0458 0x2004 root:scanner 0664 # Genius Colorpage HR6 V2 0x0458 0x2007 root:scanner 0664 # Genius Colorpage HR6 V2 0x0458 0x2008 root:scanner 0664 # Genius Colorpage HR6A 0x0458 0x2009 root:scanner 0664 # Genius Colorpage Vivid3x | Genius Colorpage Vivid3 V2 0x0458 0x2011 root:scanner 0664 # Genius Colorpage HR7 0x0458 0x2013 root:scanner 0664 # Genius Colorpage Vivid4 0x0458 0x2014 root:scanner 0664 # Genius Colorpage HR7LE 0x0458 0x2015 root:scanner 0664 # Genius Colorpage HR6X 0x0458 0x2016 root:scanner 0664 # Genius Colorpage Vivid3xe 0x0458 0x2017 root:scanner 0664 # Genius Colorpage Vivid4xe 0x0458 0x201a root:scanner 0664 # Genius Colorpage Vivid4x 0x0458 0x201b root:scanner 0664 # Genius Colorpage Vivid 1200 X 0x0458 0x201d root:scanner 0664 # Genius ColorPage Slim 1200 0x0458 0x201e root:scanner 0664 # Genius Colorpage Vivid 1200 XE 0x0458 0x201f root:scanner 0664 # Genius Colorpage SF600 0x0458 0x2021 root:scanner 0664 # Medion/Lifetec/Tevion/Cytron MD5345 | Medion/Lifetec/Tevion/Cytron MD6228 | Medion/Lifetec/Tevion/Cytron MD6471 0x0461 0x0377 root:scanner 0664 # Xerox 2400 Onetouch 0x0461 0x038b root:scanner 0664 # Trust Office Scan USB 19200 0x047b 0x1000 root:scanner 0664 # Hewlett-Packard ScanJet 4300c/Silitek 0x047b 0x1002 root:scanner 0664 # Kyocera FS-1016MFP 0x0482 0x0335 root:scanner 0664 # Compaq S4-100 0x049f 0x001a root:scanner 0664 # Benq (Acer) 310U 0x04a5 0x1a20 root:scanner 0664 # Benq (Acer) 620U 0x04a5 0x1a2a root:scanner 0664 # Benq (Acer) 320U | Benq (Acer) 340U | Mitsubishi Diamondview 648UT 0x04a5 0x2022 root:scanner 0664 # Benq (Acer) 620UT 0x04a5 0x2040 root:scanner 0664 # Benq (Acer) 640U | Guillemot / Hercules Maxi Scan A4 USB 640U | Guillemot / Hercules Maxi A4 36 bit 0x04a5 0x2060 root:scanner 0664 # Benq (Acer) 640bu 0x04a5 0x207e root:scanner 0664 # Benq (Acer) 3300 | Benq (Acer) 4300 | Mitsubishi Diamondview 650U 0x04a5 0x20b0 root:scanner 0664 # Benq (Acer) 640BT 0x04a5 0x20be root:scanner 0664 # Benq (Acer) 1240 0x04a5 0x20c0 root:scanner 0664 # Benq (Acer) 3300 | Benq (Acer) 4300 | Guillemot / Hercules Scan@home Touch 1248 (USB) 0x04a5 0x20de root:scanner 0664 # Benq (Acer) 5000 0x04a5 0x20f8 root:scanner 0664 # Benq (Acer) 5000E | Benq (Acer) 5000U 0x04a5 0x20fc root:scanner 0664 # Benq (Acer) 5300 0x04a5 0x20fe root:scanner 0664 # Benq (Acer) 5150 | Benq (Acer) 5250 0x04a5 0x2137 root:scanner 0664 # BenQ 5550 0x04a5 0x2211 root:scanner 0664 # Visioneer Visioneer OneTouch 7100 0x04a7 0x0229 root:scanner 0664 # Visioneer 9650 0x04a7 0x0390 root:scanner 0664 # Visioneer 9320 0x04a7 0x0420 root:scanner 0664 # Visioneer 9450 0x04a7 0x0421 root:scanner 0664 # Visioneer 9550 0x04a7 0x0422 root:scanner 0664 # Visioneer 9750 0x04a7 0x0423 root:scanner 0664 # Visioneer Strobe XP 450 0x04a7 0x0424 root:scanner 0664 # Visioneer Strobe XP 200 0x04a7 0x0426 root:scanner 0664 # Visioneer Strobe XP 100 0x04a7 0x0427 root:scanner 0664 # Visioneer OneTouch 7300 0x04a7 0x0444 root:scanner 0664 # Xerox DocuMate510 0x04a7 0x0446 root:scanner 0664 # Xerox DocuMate520 0x04a7 0x0447 root:scanner 0664 # Xerox DocuMate250 0x04a7 0x0448 root:scanner 0664 # Xerox DocuMate252 0x04a7 0x0449 root:scanner 0664 # Xerox DocuMate262 0x04a7 0x044c root:scanner 0664 # Visioneer Strobe XP 300 0x04a7 0x0474 root:scanner 0664 # Xerox DocuMate272 0x04a7 0x0475 root:scanner 0664 # Xerox DocuMate232 0x04a7 0x0476 root:scanner 0664 # Xerox DocuMate152 0x04a7 0x0477 root:scanner 0664 # Xerox DocuMate752 0x04a7 0x0478 root:scanner 0664 # Visioneer Strobe XP 470 0x04a7 0x0479 root:scanner 0664 # Visioneer 9450-G 0x04a7 0x047a root:scanner 0664 # Visioneer 9650-G 0x04a7 0x047b root:scanner 0664 # Xerox DocuMate510-G 0x04a7 0x047c root:scanner 0664 # Xerox DocuMate252-G 0x04a7 0x048c root:scanner 0664 # Xerox DocuMate262-G 0x04a7 0x048d root:scanner 0664 # Xerox DocuMate272-G 0x04a7 0x048e root:scanner 0664 # Visioneer Strobe XP 470-G | Visioneer Patriot 470 0x04a7 0x048f root:scanner 0664 # Xerox DocuMate250-G 0x04a7 0x0490 root:scanner 0664 # Visioneer Strobe XP 450-G 0x04a7 0x0491 root:scanner 0664 # Xerox DocuMate520-G 0x04a7 0x0492 root:scanner 0664 # Visioneer 9750-G 0x04a7 0x0493 root:scanner 0664 # Visioneer Roadwarrior 0x04a7 0x0494 root:scanner 0664 # Xerox DocuMate512 0x04a7 0x0495 root:scanner 0664 # Visioneer Patriot 430 0x04a7 0x0497 root:scanner 0664 # Visioneer Patriot 680 | Xerox DocuMate632 0x04a7 0x0498 root:scanner 0664 # Visioneer Patriot 780 0x04a7 0x0499 root:scanner 0664 # Xerox DocuMate752 0x04a7 0x049a root:scanner 0664 # Visioneer Strobe XP 100,r3 0x04a7 0x049b root:scanner 0664 # Xerox DocuMate150 0x04a7 0x049c root:scanner 0664 # Xerox DocuMate162 0x04a7 0x049d root:scanner 0664 # Xerox DocuMate262i 0x04a7 0x04a7 root:scanner 0664 # Xerox Travel Scanner 100 0x04a7 0x04ac root:scanner 0664 # Canon DR-2080C 0x04a9 0x1601 root:scanner 0664 # Canon CR-180 | Canon CR-180II 0x04a9 0x1602 root:scanner 0664 # Canon DR-9080C 0x04a9 0x1603 root:scanner 0664 # Canon DR-7080C 0x04a9 0x1604 root:scanner 0664 # Canon DR-5010C 0x04a9 0x1606 root:scanner 0664 # Canon DR-6080 0x04a9 0x1607 root:scanner 0664 # Canon DR-2580C 0x04a9 0x1608 root:scanner 0664 # Canon DR-3080CII 0x04a9 0x1609 root:scanner 0664 # Canon DR-2050C | Canon DR-2050SP 0x04a9 0x160a root:scanner 0664 # Canon DR-7580 0x04a9 0x160b root:scanner 0664 # Canon PIXMA MP750 0x04a9 0x1706 root:scanner 0664 # Canon PIXMA MP780 | Canon PIXMA MP790 0x04a9 0x1707 root:scanner 0664 # Canon PIXMA MP760 | Canon PIXMA MP770 0x04a9 0x1708 root:scanner 0664 # Canon PIXMA MP150 0x04a9 0x1709 root:scanner 0664 # Canon PIXMA MP170 0x04a9 0x170a root:scanner 0664 # Canon PIXMA MP450 0x04a9 0x170b root:scanner 0664 # Canon PIXMA MP500 0x04a9 0x170c root:scanner 0664 # Canon PIXMA MP800 0x04a9 0x170d root:scanner 0664 # Canon PIXMA MP800R 0x04a9 0x170e root:scanner 0664 # Canon PIXMA MP530 0x04a9 0x1712 root:scanner 0664 # Canon PIXMA MP830 0x04a9 0x1713 root:scanner 0664 # Canon PIXMA MP160 0x04a9 0x1714 root:scanner 0664 # Canon PIXMA MP180 0x04a9 0x1715 root:scanner 0664 # Canon PIXMA MP460 0x04a9 0x1716 root:scanner 0664 # Canon PIXMA MP510 0x04a9 0x1717 root:scanner 0664 # Canon PIXMA MP600 0x04a9 0x1718 root:scanner 0664 # Canon PIXMA MP600R 0x04a9 0x1719 root:scanner 0664 # Canon PIXMA MP810 0x04a9 0x171a root:scanner 0664 # Canon PIXMA MP960 0x04a9 0x171b root:scanner 0664 # Canon PIXMA MX7600 0x04a9 0x171c root:scanner 0664 # Canon PIXMA MP210 0x04a9 0x1721 root:scanner 0664 # Canon PIXMA MP220 0x04a9 0x1722 root:scanner 0664 # Canon PIXMA MP470 0x04a9 0x1723 root:scanner 0664 # Canon PIXMA MP520 0x04a9 0x1724 root:scanner 0664 # Canon PIXMA MP610 0x04a9 0x1725 root:scanner 0664 # Canon PIXMA MP970 0x04a9 0x1726 root:scanner 0664 # Canon PIXMA MX300 0x04a9 0x1727 root:scanner 0664 # Canon PIXMA MX310 0x04a9 0x1728 root:scanner 0664 # Canon PIXMA MX700 0x04a9 0x1729 root:scanner 0664 # Canon PIXMA MP140 0x04a9 0x172b root:scanner 0664 # Canon PIXMA MX850 0x04a9 0x172c root:scanner 0664 # Canon PIXMA MP980 0x04a9 0x172d root:scanner 0664 # Canon PIXMA MP630 0x04a9 0x172e root:scanner 0664 # Canon PIXMA MP620 0x04a9 0x172f root:scanner 0664 # Canon PIXMA MP540 0x04a9 0x1730 root:scanner 0664 # Canon PIXMA MP480 0x04a9 0x1731 root:scanner 0664 # Canon PIXMA MP240 0x04a9 0x1732 root:scanner 0664 # Canon PIXMA MP260 0x04a9 0x1733 root:scanner 0664 # Canon PIXMA MP190 0x04a9 0x1734 root:scanner 0664 # Canon PIXMA MX860 0x04a9 0x1735 root:scanner 0664 # Canon PIXMA MX320 0x04a9 0x1736 root:scanner 0664 # Canon PIXMA MX330 0x04a9 0x1737 root:scanner 0664 # Canon PIXMA MP250 0x04a9 0x173a root:scanner 0664 # Canon PIXMA MP270 0x04a9 0x173b root:scanner 0664 # Canon PIXMA MP490 0x04a9 0x173c root:scanner 0664 # Canon PIXMA MP550 0x04a9 0x173d root:scanner 0664 # Canon PIXMA MP560 0x04a9 0x173e root:scanner 0664 # Canon PIXMA MP640 0x04a9 0x173f root:scanner 0664 # Canon PIXMA MP990 0x04a9 0x1740 root:scanner 0664 # Canon PIXMA MX340 0x04a9 0x1741 root:scanner 0664 # Canon PIXMA MX350 0x04a9 0x1742 root:scanner 0664 # Canon PIXMA MX870 0x04a9 0x1743 root:scanner 0664 # Canon PIXMA MP280 0x04a9 0x1746 root:scanner 0664 # Canon PIXMA MP495 0x04a9 0x1747 root:scanner 0664 # Canon PIXMA MG5100 Series 0x04a9 0x1748 root:scanner 0664 # Canon PIXMA MG5200 Series 0x04a9 0x1749 root:scanner 0664 # Canon PIXMA MG6100 Series 0x04a9 0x174a root:scanner 0664 # Canon PIXMA MG8100 Series 0x04a9 0x174b root:scanner 0664 # Canon PIXMA MX360 0x04a9 0x174d root:scanner 0664 # Canon PIXMA MX410 0x04a9 0x174e root:scanner 0664 # Canon PIXMA MX420 0x04a9 0x174f root:scanner 0664 # Canon PIXMA MX880 Series | Canon PIXMA MX882 | Canon PIXMA MX885 0x04a9 0x1750 root:scanner 0664 # Canon PIXMA MG2100 Series 0x04a9 0x1751 root:scanner 0664 # Canon PIXMA MG3100 Series 0x04a9 0x1752 root:scanner 0664 # Canon PIXMA MG4100 Series 0x04a9 0x1753 root:scanner 0664 # Canon PIXMA MG5300 Series 0x04a9 0x1754 root:scanner 0664 # Canon PIXMA MG6200 Series 0x04a9 0x1755 root:scanner 0664 # Canon PIXMA MG8200 Series 0x04a9 0x1756 root:scanner 0664 # Canon PIXMA MP493 0x04a9 0x1757 root:scanner 0664 # Canon PIXMA E500 0x04a9 0x1758 root:scanner 0664 # Canon PIXMA MX370 Series 0x04a9 0x1759 root:scanner 0664 # Canon PIXMA E600 0x04a9 0x175a root:scanner 0664 # Canon PIXMA MX430 Series 0x04a9 0x175b root:scanner 0664 # Canon PIXMA MX510 Series 0x04a9 0x175c root:scanner 0664 # Canon PIXMA MX710 Series 0x04a9 0x175d root:scanner 0664 # Canon PIXMA MX890 Series 0x04a9 0x175e root:scanner 0664 # Canon PIXMA MP230 0x04a9 0x175f root:scanner 0664 # Canon PIXMA MG2200 Series 0x04a9 0x1760 root:scanner 0664 # Canon PIXMA E510 0x04a9 0x1761 root:scanner 0664 # Canon PIXMA MG3200 Series 0x04a9 0x1762 root:scanner 0664 # Canon PIXMA MG4200 Series 0x04a9 0x1763 root:scanner 0664 # Canon PIXMA MG5400 Series 0x04a9 0x1764 root:scanner 0664 # Canon PIXMA MG6300 Series 0x04a9 0x1765 root:scanner 0664 # Canon PIXMA MX390 Series 0x04a9 0x1766 root:scanner 0664 # Canon PIXMA E610 0x04a9 0x1767 root:scanner 0664 # Canon PIXMA MX450 Series 0x04a9 0x1768 root:scanner 0664 # Canon PIXMA MX520 Series 0x04a9 0x1769 root:scanner 0664 # Canon PIXMA MX720 Series 0x04a9 0x176a root:scanner 0664 # Canon PIXMA MX920 Series 0x04a9 0x176b root:scanner 0664 # Canon CanoScan 8800F 0x04a9 0x1901 root:scanner 0664 # Canon CanoScan LiDE 100 0x04a9 0x1904 root:scanner 0664 # Canon CanoScan LiDE 200 0x04a9 0x1905 root:scanner 0664 # Canon CanoScan 700F 0x04a9 0x1907 root:scanner 0664 # Canon CanoScan 9000F 0x04a9 0x1908 root:scanner 0664 # Canon CanoScan LiDE 110 0x04a9 0x1909 root:scanner 0664 # Canon CanoScan LiDE 210 0x04a9 0x190a root:scanner 0664 # Canon CanoScan 9000F Mark II 0x04a9 0x190d root:scanner 0664 # Canon CanoScan fb630u | Canon CanoScan fb636u 0x04a9 0x2204 root:scanner 0664 # Canon CanoScan N650U/N656U 0x04a9 0x2206 root:scanner 0664 # Canon CanoScan N1220U 0x04a9 0x2207 root:scanner 0664 # Canon CanoScan D660U 0x04a9 0x2208 root:scanner 0664 # Canon CanoScan N670U/N676U/LiDE20 0x04a9 0x220d root:scanner 0664 # Canon CanoScan N1240U/LiDE30 0x04a9 0x220e root:scanner 0664 # Canon CanoScan LiDE 35 | Canon CanoScan LiDE 40 | Canon CanoScan LiDE 50 0x04a9 0x2213 root:scanner 0664 # Canon CanoScan LiDE 60 0x04a9 0x221c root:scanner 0664 # Canon CanoScan LiDE25 0x04a9 0x2220 root:scanner 0664 # Canon DR-1210C 0x04a9 0x2222 root:scanner 0664 # Canon PIXMA MP730 0x04a9 0x262f root:scanner 0664 # Canon PIXMA MP700 0x04a9 0x2630 root:scanner 0664 # Canon PIXMA MP360 0x04a9 0x263c root:scanner 0664 # Canon PIXMA MP370 0x04a9 0x263d root:scanner 0664 # Canon PIXMA MP390 0x04a9 0x263e root:scanner 0664 # Canon PIXMA MP375R 0x04a9 0x263f root:scanner 0664 # Canon PIXMA MP740 0x04a9 0x264c root:scanner 0664 # Canon PIXMA MP710 0x04a9 0x264d root:scanner 0664 # Canon imageCLASS MF5630 0x04a9 0x264e root:scanner 0664 # Canon laserBase MF5650 0x04a9 0x264f root:scanner 0664 # Canon imageCLASS MF8170c 0x04a9 0x2659 root:scanner 0664 # Canon imageCLASS MF5730 0x04a9 0x265d root:scanner 0664 # Canon imageCLASS MF5750 0x04a9 0x265e root:scanner 0664 # Canon imageCLASS MF5770 0x04a9 0x265f root:scanner 0664 # Canon imageCLASS MF3110 0x04a9 0x2660 root:scanner 0664 # Canon imageCLASS MF3240 0x04a9 0x2684 root:scanner 0664 # Canon imageCLASS MF6500 series | Canon imageCLASS MF6550 0x04a9 0x2686 root:scanner 0664 # Canon imageCLASS MF4120 | Canon imageCLASS MF4122 | Canon imageCLASS MF4140 | Canon imageCLASS MF4150 0x04a9 0x26a3 root:scanner 0664 # Canon imageCLASS MF4660 | Canon imageCLASS MF4690 0x04a9 0x26b0 root:scanner 0664 # Canon imageCLASS MF4010 | Canon imageCLASS MF4018 0x04a9 0x26b4 root:scanner 0664 # Canon imageCLASS MF4270 0x04a9 0x26b5 root:scanner 0664 # Canon imageRUNNER 1020/1024/1025 0x04a9 0x26e6 root:scanner 0664 # Canon imageCLASS MF4370dn | Canon imageCLASS MF4380dn 0x04a9 0x26ec root:scanner 0664 # Canon imageCLASS D480 0x04a9 0x26ed root:scanner 0664 # Canon I-SENSYS MF4320d | Canon I-SENSYS MF4330d | Canon imageCLASS MF4350d 0x04a9 0x26ee root:scanner 0664 # Canon imageCLASS D420 0x04a9 0x26ef root:scanner 0664 # Canon i-SENSYS MF5880dn 0x04a9 0x26f9 root:scanner 0664 # Canon i-SENSYS MF6680dn 0x04a9 0x26fa root:scanner 0664 # Canon imageCLASS MF8030 0x04a9 0x2707 root:scanner 0664 # Canon i-SENSYS MF4550d 0x04a9 0x2736 root:scanner 0664 # Canon imageCLASS MF4410 | Canon imageCLASS MF4430 0x04a9 0x2737 root:scanner 0664 # Canon i-SENSYS MF3010 0x04a9 0x2759 root:scanner 0664 # Nikon LS 40 ED | Nikon LS 40 ED | Nikon Coolspan IV 0x04b0 0x4000 root:scanner 0664 # Nikon LS 50 ED | Nikon Coolscan V ED | Nikon LS 50 ED | Nikon Coolscan V ED 0x04b0 0x4001 root:scanner 0664 # Nikon Super Coolscan LS-5000 ED | Nikon Super Coolscan LS-5000 ED 0x04b0 0x4002 root:scanner 0664 # Epson Perfection 636U | Epson GT-7000U | Epson Perfection 636U 0x04b8 0x0101 root:scanner 0664 # Epson Perfection 610 | Epson GT-6600U | Epson Perfection 610 0x04b8 0x0103 root:scanner 0664 # Epson Perfection 1200U | Epson Perfection 1200Photo | Epson GT-7600U | Epson GT-7600UF | Epson Perfection 1200U | Epson Perfection 1200U PHOTO 0x04b8 0x0104 root:scanner 0664 # Epson Stylus Scan 2000 0x04b8 0x0105 root:scanner 0664 # Epson Stylus Scan 2500 0x04b8 0x0106 root:scanner 0664 # Epson Expression 1600 | Epson ES-2000 | Epson Expression 1600 0x04b8 0x0107 root:scanner 0664 # Epson ES-8500 | Epson Expression 1640XL 0x04b8 0x0109 root:scanner 0664 # Epson Perfection 1640 | Epson GT-8700 | Epson GT-8700F | Epson Perfection 1640SU | Epson Perfection 1640SU PHOTO 0x04b8 0x010a root:scanner 0664 # Epson Perfection 1240 | Epson GT-7700U | Epson Perfection 1240U 0x04b8 0x010b root:scanner 0664 # Epson Perfection 640 | Epson GT-6700U | Epson Perfection 640U 0x04b8 0x010c root:scanner 0664 # Epson Expression 1680 | Epson ES-2200 | Epson Expression 1680 0x04b8 0x010e root:scanner 0664 # Epson Perfection 1250 | Epson Perfection 1250Photo 0x04b8 0x010f root:scanner 0664 # Epson Perfection 1650 | Epson GT-8200U | Epson GT-8200UF | Epson Perfection 1650 | Epson Perfection 1650 PHOTO 0x04b8 0x0110 root:scanner 0664 # Epson Perfection 2450 | Epson GT-9700F | Epson Perfection 2450 PHOTO 0x04b8 0x0112 root:scanner 0664 # Epson Perfection 660 0x04b8 0x0114 root:scanner 0664 # Epson Perfection 2400 | Epson GT-9300UF | Epson Perfection 2400 PHOTO 0x04b8 0x011b root:scanner 0664 # Epson Perfection 3200 | Epson GT-9800F | Epson Perfection 3200 PHOTO 0x04b8 0x011c root:scanner 0664 # Epson Perfection 1260 | Epson Perfection 1260Photo 0x04b8 0x011d root:scanner 0664 # Epson Perfection 1660 | Epson GT-8300UF | Epson Perfection 1660 PHOTO 0x04b8 0x011e root:scanner 0664 # Epson Perfection 1670 0x04b8 0x011f root:scanner 0664 # Epson Perfection 1270 0x04b8 0x0120 root:scanner 0664 # Epson Perfection 2480 | Epson Perfection 2580 0x04b8 0x0121 root:scanner 0664 # Epson Perfection 3490 | Epson Perfection 3590 0x04b8 0x0122 root:scanner 0664 # Epson ES-7000H | Epson GT-15000 0x04b8 0x0126 root:scanner 0664 # Epson Perfection 4870 | Epson GT-X700 | Epson Perfection 4870 PHOTO 0x04b8 0x0128 root:scanner 0664 # Epson ES-10000G | Epson Expression 10000XL 0x04b8 0x0129 root:scanner 0664 # Epson Perfection 4990 | Epson GT-X800 | Epson Perfection 4990 PHOTO 0x04b8 0x012a root:scanner 0664 # Epson ES-H300 | Epson GT-2500 0x04b8 0x012b root:scanner 0664 # Epson V700 | Epson V750 | Epson GT-X900 | Epson Perfection V700 Photo | Epson Perfection V750 Photo 0x04b8 0x012c root:scanner 0664 # Epson GT-X970 0x04b8 0x0135 root:scanner 0664 # Epson CX-5200 | Epson CX-5400 | Epson CC-600PX | Epson Stylus CX5100 | Epson Stylus CX5200 0x04b8 0x0801 root:scanner 0664 # Epson CX-3200 | Epson CC-570L | Epson Stylus CX3100 | Epson Stylus CX3200 0x04b8 0x0802 root:scanner 0664 # Epson CX-6300 | Epson CX-6400 | Epson Stylus CX6300 | Epson Stylus CX6400 0x04b8 0x0805 root:scanner 0664 # Epson RX-600 | Epson PM-A850 | Epson Stylus Photo RX600 0x04b8 0x0806 root:scanner 0664 # Epson RX-500 | Epson Stylus Photo RX500 | Epson Stylus Photo RX510 0x04b8 0x0807 root:scanner 0664 # Epson CX-5400 | Epson Stylus CX5300 | Epson Stylus CX5400 0x04b8 0x0808 root:scanner 0664 # Epson Stylus CX-1500 0x04b8 0x080c root:scanner 0664 # Epson CX-4600 | Epson Stylus CX4500 | Epson Stylus CX4600 0x04b8 0x080d root:scanner 0664 # Epson CX-3600 | Epson CX-3650 | Epson PX-A550 | Epson Stylus CX3500 | Epson Stylus CX3600 | Epson Stylus CX3650 0x04b8 0x080e root:scanner 0664 # Epson RX-425 | Epson Stylus Photo RX420 | Epson Stylus Photo RX425 | Epson Stylus Photo RX430 0x04b8 0x080f root:scanner 0664 # Epson RX-700 | Epson PM-A900 | Epson Stylus Photo RX700 0x04b8 0x0810 root:scanner 0664 # Epson RX-620 | Epson PM-A870 | Epson Stylus Photo RX620 | Epson Stylus Photo RX630 0x04b8 0x0811 root:scanner 0664 # Epson CX-6500 | Epson CX-6600 | Epson Stylus CX6500 | Epson Stylus CX6600 0x04b8 0x0813 root:scanner 0664 # Epson PM-A700 0x04b8 0x0814 root:scanner 0664 # Epson AcuLaser CX11 | Epson AcuLaser CX11NF | Epson AcuLaser CX11 | Epson AcuLaser CX11NF | Epson LP-A500 0x04b8 0x0815 root:scanner 0664 # Epson LP-M5500 | Epson LP-M5500F 0x04b8 0x0817 root:scanner 0664 # Epson DX-3850 | Epson CX-3700 | Epson CX-3800 | Epson DX-3800 | Epson Stylus CX3700 | Epson Stylus CX3800 | Epson Stylus DX3800 0x04b8 0x0818 root:scanner 0664 # Epson CX-4800 | Epson PX-A650 | Epson Stylus CX4700 | Epson Stylus CX4800 | Epson Stylus DX4800 | Epson Stylus DX4850 0x04b8 0x0819 root:scanner 0664 # Epson PM-A750 | Epson Stylus Photo RX520 | Epson Stylus Photo RX530 0x04b8 0x081a root:scanner 0664 # Epson PM-A890 | Epson Stylus Photo RX640 | Epson Stylus Photo RX650 0x04b8 0x081c root:scanner 0664 # Epson PM-A950 0x04b8 0x081d root:scanner 0664 # Epson Stylus CX7700 | Epson Stylus CX7800 0x04b8 0x081f root:scanner 0664 # Epson CX-4200 | Epson Stylus CX4100 | Epson Stylus CX4200 | Epson Stylus DX4200 0x04b8 0x0820 root:scanner 0664 # Epson PM-A820 | Epson Stylus Photo RX560 | Epson Stylus Photo RX580 | Epson Stylus Photo RX590 0x04b8 0x0827 root:scanner 0664 # Epson PM-A970 0x04b8 0x0828 root:scanner 0664 # Epson PM-T990 0x04b8 0x0829 root:scanner 0664 # Epson PM-A920 0x04b8 0x082a root:scanner 0664 # Epson CX-5000 | Epson DX-5000 | Epson DX-5050 | Epson Stylus CX4900 | Epson Stylus CX5000 | Epson Stylus DX5000 0x04b8 0x082b root:scanner 0664 # Epson DX-6000 | Epson PX-A720 | Epson Stylus CX5900 | Epson Stylus CX6000 | Epson Stylus DX6000 0x04b8 0x082e root:scanner 0664 # Epson DX-4050 | Epson PX-A620 | Epson Stylus CX3900 | Epson Stylus DX4000 0x04b8 0x082f root:scanner 0664 # Epson ME 200 | Epson Stylus CX2800 | Epson Stylus CX2900 0x04b8 0x0830 root:scanner 0664 # Epson LP-M5600 0x04b8 0x0833 root:scanner 0664 # Epson LP-M6000 0x04b8 0x0834 root:scanner 0664 # Epson AcuLaser CX21 0x04b8 0x0835 root:scanner 0664 # Epson PM-T960 0x04b8 0x0836 root:scanner 0664 # Epson PM-A940 | Epson Stylus Photo RX680 | Epson Stylus Photo RX685 | Epson Stylus Photo RX690 0x04b8 0x0837 root:scanner 0664 # Epson DX-7400 | Epson PX-A640 | Epson Stylus CX7300 | Epson Stylus CX7400 | Epson Stylus DX7400 0x04b8 0x0838 root:scanner 0664 # Epson PX-A740 | Epson Stylus CX8300 | Epson Stylus CX8400 | Epson Stylus DX8400 0x04b8 0x0839 root:scanner 0664 # Epson PX-FA700 | Epson Stylus CX9300F | Epson Stylus CX9400Fax | Epson Stylus DX9400F 0x04b8 0x083a root:scanner 0664 # Epson PM-A840 | Epson PM-A840S | Epson Stylus Photo RX585 | Epson Stylus Photo RX595 | Epson Stylus Photo RX610 0x04b8 0x083c root:scanner 0664 # Epson ME 300 | Epson PX-401A | Epson Stylus NX100 | Epson Stylus SX100 | Epson Stylus TX100 0x04b8 0x0841 root:scanner 0664 # Epson LP-M5000 0x04b8 0x0843 root:scanner 0664 # Epson Artisan 800 | Epson EP-901A | Epson EP-901F | Epson Stylus Photo PX800FW | Epson Stylus Photo TX800FW 0x04b8 0x0844 root:scanner 0664 # Epson Artisan 700 | Epson EP-801A | Epson Stylus Photo PX700W | Epson Stylus Photo TX700W 0x04b8 0x0846 root:scanner 0664 # Epson ME Office 700FW | Epson PX-601F | Epson Stylus Office BX600FW | Epson Stylus Office TX600FW | Epson Stylus SX600FW | Epson WorkForce 600 0x04b8 0x0847 root:scanner 0664 # Epson ME Office 600F | Epson Stylus Office BX300F | Epson Stylus Office TX300F | Epson Stylus NX300 0x04b8 0x0848 root:scanner 0664 # Epson Stylus NX200 | Epson Stylus SX200 | Epson Stylus SX205 | Epson Stylus TX200 | Epson Stylus TX203 | Epson Stylus TX209 0x04b8 0x0849 root:scanner 0664 # Epson PX-501A | Epson Stylus NX400 | Epson Stylus SX400 | Epson Stylus SX405 | Epson Stylus TX400 0x04b8 0x084a root:scanner 0664 # Epson WorkForce 500 0x04b8 0x084c root:scanner 0664 # Epson PX-402A | Epson Stylus NX110 Series | Epson Stylus SX110 Series | Epson Stylus TX110 Series 0x04b8 0x084d root:scanner 0664 # Epson ME OFFICE 510 | Epson Stylus NX210 Series | Epson Stylus SX210 Series | Epson Stylus TX210 Series 0x04b8 0x084f root:scanner 0664 # Epson Stylus NX410 Series | Epson Stylus SX410 Series | Epson Stylus TX410 Series 0x04b8 0x0851 root:scanner 0664 # Epson ME OFFICE 650FN Series | Epson Stylus Office BX310FN Series | Epson Stylus Office TX510FN Series | Epson WorkForce 310 Series 0x04b8 0x0854 root:scanner 0664 # Epson PX-502A | Epson Stylus NX510 Series | Epson Stylus SX510W Series | Epson Stylus TX550W Series 0x04b8 0x0856 root:scanner 0664 # Epson Stylus SX125 0x04b8 0x085c root:scanner 0664 # Fujitsu fi-4010CU 0x04c5 0x1029 root:scanner 0664 # Fujitsu fi-4120C 0x04c5 0x1041 root:scanner 0664 # Fujitsu fi-4220C 0x04c5 0x1042 root:scanner 0664 # Fujitsu fi-4530C 0x04c5 0x1078 root:scanner 0664 # Fujitsu fi-5750C 0x04c5 0x1095 root:scanner 0664 # Fujitsu fi-5110EOX/2 0x04c5 0x1096 root:scanner 0664 # Fujitsu fi-5110C 0x04c5 0x1097 root:scanner 0664 # Fujitsu fi-5650C 0x04c5 0x10ad root:scanner 0664 # Fujitsu fi-4120C2 0x04c5 0x10ae root:scanner 0664 # Fujitsu fi-4220C2 0x04c5 0x10af root:scanner 0664 # Fujitsu fi-60F 0x04c5 0x10c7 root:scanner 0664 # Fujitsu fi-4340C 0x04c5 0x10cf root:scanner 0664 # Fujitsu fi-5120C 0x04c5 0x10e0 root:scanner 0664 # Fujitsu fi-5220C 0x04c5 0x10e1 root:scanner 0664 # Fujitsu fi-5530C 0x04c5 0x10e2 root:scanner 0664 # Fujitsu fi-5110EOX3 0x04c5 0x10e6 root:scanner 0664 # Fujitsu fi-5900C 0x04c5 0x10e7 root:scanner 0664 # Fujitsu fi-5015C 0x04c5 0x10ef root:scanner 0664 # Fujitsu fi-5110EOXM 0x04c5 0x10f2 root:scanner 0664 # Fujitsu ScanSnap S500 0x04c5 0x10fe root:scanner 0664 # Fujitsu ScanSnap S500M 0x04c5 0x1135 root:scanner 0664 # Fujitsu fi-5530C2 0x04c5 0x114a root:scanner 0664 # Fujitsu fi-6140 0x04c5 0x114d root:scanner 0664 # Fujitsu fi-6240 0x04c5 0x114e root:scanner 0664 # Fujitsu fi-6130 0x04c5 0x114f root:scanner 0664 # Fujitsu fi-6230 0x04c5 0x1150 root:scanner 0664 # Fujitsu ScanSnap S510 0x04c5 0x1155 root:scanner 0664 # Fujitsu ScanSnap S300 0x04c5 0x1156 root:scanner 0664 # Fujitsu ScanSnap S510M 0x04c5 0x116f root:scanner 0664 # Fujitsu fi-6770 0x04c5 0x1174 root:scanner 0664 # Fujitsu fi-6770A 0x04c5 0x1175 root:scanner 0664 # Fujitsu fi-6670 0x04c5 0x1176 root:scanner 0664 # Fujitsu fi-6670A 0x04c5 0x1177 root:scanner 0664 # Fujitsu fi-6750S 0x04c5 0x1178 root:scanner 0664 # Fujitsu ScanSnap S300M 0x04c5 0x117f root:scanner 0664 # Fujitsu fi-6800 0x04c5 0x119d root:scanner 0664 # Fujitsu fi-6800-CGA 0x04c5 0x119e root:scanner 0664 # Fujitsu ScanSnap S1500 | Fujitsu ScanSnap S1500M 0x04c5 0x11a2 root:scanner 0664 # Fujitsu ScanSnap S1300 0x04c5 0x11ed root:scanner 0664 # Fujitsu fi-6140Z 0x04c5 0x11f1 root:scanner 0664 # Fujitsu fi-6240Z 0x04c5 0x11f2 root:scanner 0664 # Fujitsu fi-6130Z 0x04c5 0x11f3 root:scanner 0664 # Fujitsu fi-6230Z 0x04c5 0x11f4 root:scanner 0664 # Fujitsu fi-6110 0x04c5 0x11fc root:scanner 0664 # Fujitsu fi-5950 0x04c5 0x1213 root:scanner 0664 # Fujitsu ScanSnap iX500 0x04c5 0x132b root:scanner 0664 # Konica e-mini 0x04c8 0x0722 root:scanner 0664 # Panasonic KV-S2026C 0x04da 0x1000 root:scanner 0664 # Panasonic KV-S2046C 0x04da 0x1001 root:scanner 0664 # Panasonic KV-S1025C 0x04da 0x1006 root:scanner 0664 # Panasonic KV-S1020C 0x04da 0x1007 root:scanner 0664 # Panasonic KV-S2048C 0x04da 0x1009 root:scanner 0664 # Panasonic KV-S2028C 0x04da 0x100a root:scanner 0664 # Panasonic KV-S4085C 0x04da 0x100c root:scanner 0664 # Panasonic KV-S4065C 0x04da 0x100d root:scanner 0664 # Panasonic KV-S7075C 0x04da 0x100e root:scanner 0664 # Panasonic KV-SS080 0x04da 0x100f root:scanner 0664 # Panasonic KV-S1045C 0x04da 0x1010 root:scanner 0664 # Samsung SCX-4x16 0x04e8 0x3409 root:scanner 0664 # Samsung SCX-6x20 0x04e8 0x340d root:scanner 0664 # Samsung MFP-560 0x04e8 0x340e root:scanner 0664 # Samsung MFP-750 0x04e8 0x340f root:scanner 0664 # Samsung SCX-4x20 0x04e8 0x3412 root:scanner 0664 # Samsung SCX-4100 0x04e8 0x3413 root:scanner 0664 # Samsung SCX-4x21 0x04e8 0x3419 root:scanner 0664 # Samsung SCX-5x30 0x04e8 0x341a root:scanner 0664 # Samsung SCX-4200 0x04e8 0x341b root:scanner 0664 # Samsung CLX-3160 0x04e8 0x341c root:scanner 0664 # Samsung SCX-6x22 0x04e8 0x341d root:scanner 0664 # Samsung SCX4725 | Samsung SCX4725-FN 0x04e8 0x341f root:scanner 0664 # Samsung SCX-6x45 0x04e8 0x3420 root:scanner 0664 # Samsung CLX-8380 0x04e8 0x3421 root:scanner 0664 # Samsung CLX-2160 0x04e8 0x3425 root:scanner 0664 # Samsung SCX-4500 0x04e8 0x3426 root:scanner 0664 # Samsung CLX-6200 0x04e8 0x3427 root:scanner 0664 # Samsung CLX-6240 0x04e8 0x3428 root:scanner 0664 # Samsung SCX-6x55 0x04e8 0x3429 root:scanner 0664 # Samsung CLX-3170fn (CLX-3170 Series) | Samsung CLX-3175FW 0x04e8 0x342a root:scanner 0664 # Samsung SCX-4500W 0x04e8 0x342b root:scanner 0664 # Samsung SCX-4824 (SCX-4x24 Series) 0x04e8 0x342c root:scanner 0664 # Samsung SCX-4828FN (SCX-4x28 Series) 0x04e8 0x342d root:scanner 0664 # Samsung SCX-4300 0x04e8 0x342e root:scanner 0664 # Samsung SCX-5835_5935 0x04e8 0x342f root:scanner 0664 # Samsung SCX-5635 0x04e8 0x3430 root:scanner 0664 # Samsung SCX-4x26 0x04e8 0x3432 root:scanner 0664 # Samsung SCX-4600 0x04e8 0x3433 root:scanner 0664 # Samsung SCX-4623 0x04e8 0x3434 root:scanner 0664 # Samsung MFP-65x 0x04e8 0x3435 root:scanner 0664 # Samsung SCX-6545 0x04e8 0x3437 root:scanner 0664 # Samsung CLX-8385 0x04e8 0x3439 root:scanner 0664 # Samsung CLX-6220 0x04e8 0x343a root:scanner 0664 # Samsung CLX-6250 0x04e8 0x343b root:scanner 0664 # Samsung SCX-4825FN (SCX-4x25 Series) 0x04e8 0x343c root:scanner 0664 # Samsung CLX-3185 0x04e8 0x343d root:scanner 0664 # Samsung CLX-8540 0x04e8 0x343f root:scanner 0664 # Samsung SCX-4623FW 0x04e8 0x3440 root:scanner 0664 # Samsung SCX-3205W (SCX-3200 Series) 0x04e8 0x3441 root:scanner 0664 # Samsung SCX-6545X 0x04e8 0x3442 root:scanner 0664 # Samsung SCX-6x55X 0x04e8 0x3443 root:scanner 0664 # Samsung CLX-8385X 0x04e8 0x3444 root:scanner 0664 # Samsung SCX-5835_5935X 0x04e8 0x3446 root:scanner 0664 # Samsung SCX-4833FD | Samsung SCX-4835FD 0x04e8 0x344b root:scanner 0664 # Samsung SCX-3400 0x04e8 0x344f root:scanner 0664 # Samsung SF-760 0x04e8 0x3450 root:scanner 0664 # Samsung SCX-4729FD 0x04e8 0x3453 root:scanner 0664 # Samsung CLX-6260 0x04e8 0x3455 root:scanner 0664 # Samsung CLX-3300 Series 0x04e8 0x3456 root:scanner 0664 # Samsung SCX-470x 0x04e8 0x3457 root:scanner 0664 # Samsung CLX-4190 0x04e8 0x345a root:scanner 0664 # Samsung SCX-4650 4x21S Series 0x04e8 0x345b root:scanner 0664 # Samsung M337x 387x 407x Series 0x04e8 0x3460 root:scanner 0664 # Samsung M267x 287x Series 0x04e8 0x3461 root:scanner 0664 # Samsung SCX-681x 0x04e8 0x3466 root:scanner 0664 # Samsung C460 0x04e8 0x3468 root:scanner 0664 # Pentax DSmobile 600 0x04f9 0x2038 root:scanner 0664 # Aiptek Aiptek Pencam 0x0553 0x0202 root:scanner 0664 # Mustek ScanExpress 1200 CU 0x055f 0x0001 root:scanner 0664 # Mustek ScanExpress 600 CU 0x055f 0x0002 root:scanner 0664 # Mustek ScanExpress 1200 UB | Trust Compact Scan USB 19200 0x055f 0x0006 root:scanner 0664 # Mustek ScanExpress 1200 CU Plus 0x055f 0x0008 root:scanner 0664 # Mustek BearPaw 1200 F 0x055f 0x0010 root:scanner 0664 # Mustek ScanExpress A3 USB 0x055f 0x0210 root:scanner 0664 # Mustek BearPaw 2400 CS | Mustek BearPaw 2400 TA | Trust 240TH Easy Webscan Gold 0x055f 0x0218 root:scanner 0664 # Mustek BearPaw 2400 CS Plus | Mustek BearPaw 2400 TA Plus | Mustek Plug-n-Scan 2400 MT | Mustek Plug-n-Scan 2400 M | Packard Bell Diamond 2450 0x055f 0x0219 root:scanner 0664 # Mustek BearPaw 2448 CS Plus | Mustek BearPaw 2448 TA Plus 0x055f 0x021a root:scanner 0664 # Mustek BearPaw 1200 CU Plus | Packard Bell Diamond 1200 Plus 0x055f 0x021b root:scanner 0664 # Mustek BearPaw 1200 CU Plus | Mustek BearPaw 1248 CU | Packard Bell Diamond 1200 Plus | Trust Direct WebScan 19200 0x055f 0x021c root:scanner 0664 # Mustek BearPaw 2400 CU Plus 0x055f 0x021d root:scanner 0664 # Mustek BearPaw 1200 CS | Mustek BearPaw 1200 TA 0x055f 0x021e root:scanner 0664 # Mustek ScanExpress 1248 UB 0x055f 0x021f root:scanner 0664 # Mustek BearPaw 2448TA Pro 0x055f 0x0409 root:scanner 0664 # Artec/Ultima Ultima 2000 | Artec/Ultima Ultima 2000 e+ | Boeder Sm@rtScan Slim Edition | Fujitsu 1200CUS | Googlegear 2000 | Medion/Lifetec/Tevion/Cytron MD 4394 | Medion/Lifetec/Tevion/Cytron MD/LT 9375 | Medion/Lifetec/Tevion/Cytron MD/LT 9385 | Medion/Lifetec/Tevion/Cytron LT 9452 | Medion/Lifetec/Tevion/Cytron MD 9458 | Mustek BearPaw 1200 CU | Mustek BearPaw 2400 CU | Mustek ScanExpress 1200 UB Plus | Mustek ScanExpress 2400 USB | Mustek ScanMagic 1200 UB Plus | Packard Bell Diamond 1200 | Trust Compact Scan USB 19200 | Trust Flat Scan USB 19200 0x05d8 0x4002 root:scanner 0664 # Artec/Ultima E+ 48U | Medion/Lifetec/Tevion/Cytron MD9693 | Medion/Lifetec/Tevion/Cytron MD9705 | Medion/Lifetec/Tevion/Cytron MD4394 | Microstar MR 9791 0x05d8 0x4003 root:scanner 0664 # Artec/Ultima E+ Pro 0x05d8 0x4004 root:scanner 0664 # Memorex MEM 48U 0x05d8 0x4005 root:scanner 0664 # Trust Easy Webscan 19200 0x05d8 0x4006 root:scanner 0664 # Trust 240H Easy Webscan Gold 0x05d8 0x4007 root:scanner 0664 # UMAX AstraSlim SE 0x05d8 0x4009 root:scanner 0664 # UMAX AstraSlim 1200 SE 0x05d8 0x4010 root:scanner 0664 # Yakumo Scan50 0x05d8 0x4011 root:scanner 0664 # Microtek ScanMaker X6USB 0x05da 0x0099 root:scanner 0664 # Microtek SlimScan C6 0x05da 0x009a root:scanner 0664 # Microtek ScanMaker V6USL 0x05da 0x00a3 root:scanner 0664 # Microtek ScanMaker V6UPL 0x05da 0x00b6 root:scanner 0664 # Microtek ScanMaker 4800 0x05da 0x30cf root:scanner 0664 # Microtek ScanMaker 3840 0x05da 0x30d4 root:scanner 0664 # Microtek ScanMaker 3600 0x05da 0x40b3 root:scanner 0664 # Microtek ScanMaker 3700 0x05da 0x40b8 root:scanner 0664 # Microtek ScanMaker 3600 0x05da 0x40ca root:scanner 0664 # Microtek ScanMaker 3700 0x05da 0x40cb root:scanner 0664 # Microtek ScanMaker 3750 0x05da 0x40dd root:scanner 0664 # Microtek ScanMaker 3600 0x05da 0x40ff root:scanner 0664 # Microtek ScanMaker V6USL 0x05da 0x80a3 root:scanner 0664 # iVina 1200U 0x0638 0x0268 root:scanner 0664 # Minolta Dimage Scan Dual II 0x0638 0x026a root:scanner 0664 # Avision AV600U 0x0638 0x0a13 root:scanner 0664 # Minolta-QMS SC-110 0x0638 0x0a15 root:scanner 0664 # Avision DS610CU Scancopier | Minolta-QMS SC-215 | OKI S700 Scancopier 0x0638 0x0a16 root:scanner 0664 # Avision AV610 | Avision AV600U Plus 0x0638 0x0a18 root:scanner 0664 # Avision AV220 0x0638 0x0a23 root:scanner 0664 # Avision AV210 0x0638 0x0a24 root:scanner 0664 # Avision AV210 0x0638 0x0a25 root:scanner 0664 # Avision AV120 0x0638 0x0a27 root:scanner 0664 # Avision AV220C2 0x0638 0x0a2a root:scanner 0664 # Avision AV220D2 0x0638 0x0a2b root:scanner 0664 # Avision AV220+ 0x0638 0x0a2c root:scanner 0664 # Avision AV220C2-G 0x0638 0x0a2d root:scanner 0664 # Avision AV220C2-B 0x0638 0x0a2e root:scanner 0664 # Avision AV210C2-G 0x0638 0x0a2f root:scanner 0664 # Avision AV122 0x0638 0x0a33 root:scanner 0664 # Avision AV210C2 0x0638 0x0a3a root:scanner 0664 # Avision AV121 0x0638 0x0a3c root:scanner 0664 # Avision AV8300 0x0638 0x0a40 root:scanner 0664 # Avision AM3000 Series 0x0638 0x0a41 root:scanner 0664 # Avision @V5100 0x0638 0x0a45 root:scanner 0664 # Avision AV8050U 0x0638 0x0a4d root:scanner 0664 # Avision AV3200SU 0x0638 0x0a4e root:scanner 0664 # Avision AV3730SU 0x0638 0x0a4f root:scanner 0664 # Avision AV610C2 0x0638 0x0a5e root:scanner 0664 # Avision IT8300 0x0638 0x0a61 root:scanner 0664 # Avision AV3750SU 0x0638 0x0a65 root:scanner 0664 # Avision AV3850SU 0x0638 0x0a66 root:scanner 0664 # Avision AV8350 0x0638 0x0a68 root:scanner 0664 # Avision FB6080E 0x0638 0x0a82 root:scanner 0664 # Avision FB2080E 0x0638 0x0a84 root:scanner 0664 # Avision AV122 C2 0x0638 0x0a93 root:scanner 0664 # Avision AV220-G 0x0638 0x0a94 root:scanner 0664 # Avision @V2500 0x0638 0x0aa1 root:scanner 0664 # Avision AV210D2+ 0x0638 0x1a35 root:scanner 0664 # Minolta Elite II 0x0686 0x4004 root:scanner 0664 # Minolta Dimage Scan Dual III 0x0686 0x400d root:scanner 0664 # Minolta Dimage Scan Elite 5400 0x0686 0x400e root:scanner 0664 # AGFA SnapScan 1212U 0x06bd 0x0001 root:scanner 0664 # AGFA SnapScan 1236u 0x06bd 0x0002 root:scanner 0664 # Agfa Snapscan Touch 0x06bd 0x0100 root:scanner 0664 # AGFA SnapScan 1212U_2 0x06bd 0x2061 root:scanner 0664 # AGFA SnapScan e40 0x06bd 0x208d root:scanner 0664 # AGFA SnapScan e50 0x06bd 0x208f root:scanner 0664 # AGFA SnapScan e20 0x06bd 0x2091 root:scanner 0664 # AGFA SnapScan e10 0x06bd 0x2093 root:scanner 0664 # AGFA SnapScan e25 0x06bd 0x2095 root:scanner 0664 # AGFA SnapScan e26 0x06bd 0x2097 root:scanner 0664 # AGFA SnapScan e52 0x06bd 0x20fd root:scanner 0664 # AGFA SnapScan e42 0x06bd 0x20ff root:scanner 0664 # UMAX Astra 4900 0x06dc 0x0020 root:scanner 0664 # Plustek OpticPro U12 | Plustek OpticPro UT12 | Plustek OpticPro 1212U | RevScan RevScan Orange R48Ti | Genius ColorPage Vivid III USB 0x07b3 0x0001 root:scanner 0664 # Plustek OpticPro U12 0x07b3 0x0010 root:scanner 0664 # Plustek OpticPro U24 0x07b3 0x0011 root:scanner 0664 # Plustek OpticPro UT12 0x07b3 0x0013 root:scanner 0664 # Plustek OpticPro U24 0x07b3 0x0015 root:scanner 0664 # Plustek OpticPro UT12 | Plustek OpticPro UT16 | Plustek OpticPro UT24 0x07b3 0x0017 root:scanner 0664 # Plustek OpticPro 1248U | RevScan 19200i 0x07b3 0x0400 root:scanner 0664 # Plustek OpticPro 1248U 0x07b3 0x0401 root:scanner 0664 # Plustek OpticPro U16B 0x07b3 0x0402 root:scanner 0664 # Plustek OpticPro U16B+ | Plustek OpticPro UT16B 0x07b3 0x0403 root:scanner 0664 # Nortek MyScan 1200 | Plustek OpticPro S12 | Plustek OpticPro ST12 0x07b3 0x040b root:scanner 0664 # Plustek OpticPro S24 0x07b3 0x040e root:scanner 0664 # NeatReceipts Scanalizer Professional 2.5 | Plustek OpticSlim M12 0x07b3 0x0412 root:scanner 0664 # Plustek OpticSlim 1200 0x07b3 0x0413 root:scanner 0664 # Plustek OpticSlim 2400 0x07b3 0x0422 root:scanner 0664 # Plustek OpticSlim 2400 plus 0x07b3 0x0454 root:scanner 0664 # Plustek Iriscan Express 2 0x07b3 0x045f root:scanner 0664 # NeatReceipts Mobile Scanner 0x07b3 0x0462 root:scanner 0664 # Plustek OpticBook 3600 0x07b3 0x0900 root:scanner 0664 # Corex 600c 0x08f0 0x0002 root:scanner 0664 # Corex 800c 0x08f0 0x0005 root:scanner 0664 # Xerox Phaser 6110MFP 0x0924 0x3d5d root:scanner 0664 # Xerox Phaser 3200MFP 0x0924 0x3da4 root:scanner 0664 # Xerox WorkCentre 4118 Series 0x0924 0x420c root:scanner 0664 # Xerox WorkCentre 3119 Series 0x0924 0x4265 root:scanner 0664 # Xerox WorkCentre 3210 0x0924 0x4293 root:scanner 0664 # Xerox WorkCentre 3220 0x0924 0x4294 root:scanner 0664 # Pentax DSmobile 600 0x0a17 0x3210 root:scanner 0664 # Portable Peripheral Co., Ltd. Q-Scan USB001 (A4 portable scanner) 0x0a53 0x1000 root:scanner 0664 # Portable Peripheral Co., Ltd. Q-Scan USB201 (A6 portable scanner) 0x0a53 0x2000 root:scanner 0664 # Syscan TravelScan 460/464 | Ambir Visigo A4 0x0a82 0x4600 root:scanner 0664 # Syscan DocketPort 465 0x0a82 0x4802 root:scanner 0664 # Syscan DocketPort 665 0x0a82 0x4803 root:scanner 0664 # Syscan DocketPort 685/ Ambir DS685 0x0a82 0x480c root:scanner 0664 # Syscan DocketPort 485 0x0a82 0x4810 root:scanner 0664 # Syscan TravelScan 662 0x0a82 0x6620 root:scanner 0664 # Canon CR-55 0x1083 0x160c root:scanner 0664 # Canon DR-1210C 0x1083 0x160f root:scanner 0664 # Canon DR-4010C 0x1083 0x1614 root:scanner 0664 # Canon DR-2510C 0x1083 0x1617 root:scanner 0664 # Canon DR-X10C 0x1083 0x1618 root:scanner 0664 # Canon CR-25 0x1083 0x161a root:scanner 0664 # Canon DR-2010C 0x1083 0x161b root:scanner 0664 # Canon DR-3010C 0x1083 0x161d root:scanner 0664 # Canon DR-7090C 0x1083 0x1620 root:scanner 0664 # Canon DR-9050C 0x1083 0x1622 root:scanner 0664 # Canon DR-7550C 0x1083 0x1623 root:scanner 0664 # Canon DR-6050C 0x1083 0x1624 root:scanner 0664 # Canon DR-6010C 0x1083 0x1626 root:scanner 0664 # Canon CR-190i 0x1083 0x162b root:scanner 0664 # Canon DR-6030C 0x1083 0x1638 root:scanner 0664 # Canon CR-135i 0x1083 0x1639 root:scanner 0664 # Digital Dream l' espion XS 0x1183 0x0001 root:scanner 0664 # KONICA MINOLTA magicolor 1690MF 0x132b 0x2089 root:scanner 0664 # UMAX Astra 1220U 0x1606 0x0010 root:scanner 0664 # UMAX Astra 1600U | UMAX Astra 2000U 0x1606 0x0030 root:scanner 0664 # Umax UMAX 3400 0x1606 0x0050 root:scanner 0664 # Umax UMAX 3400 | Umax UMAX Astranet ia101 | Umax UMAX 3450 0x1606 0x0060 root:scanner 0664 # UMAX Astra 4400 | UMAX Astra 4450 0x1606 0x0070 root:scanner 0664 # UMAX Astra 2100U 0x1606 0x0130 root:scanner 0664 # Umax UMAX 5400 0x1606 0x0160 root:scanner 0664 # UMAX Astra 2200 (SU) 0x1606 0x0230 root:scanner 0664 # DCT DocketPort 487 0x1dcc 0x4810 root:scanner 0664 # Dell A920 0x413c 0x5105 root:scanner 0664 # Dell Dell MFP Laser Printer 1815dn 0x413c 0x5124 root:scanner 0664 # Dell 1600n 0x413c 0x5250 root:scanner 0664 sane-backends-1.0.27/testsuite/tools/data/testfile.desc0000664000175000017500000123545412775312262020030 00000000000000:backend "abaton" :version "unmaintained" :manpage "sane-abaton" ;:url "http://aix2.uottawa.ca/~s1204672/sane/" :devicetype :scanner :mfg "Abaton" ;:url "http://www.everex.com/" ;dead? :model "Scan 300/GS" :interface "SCSI" :status :complete :comment "All known modes and functions supported" :model "Scan 300/S" :interface "SCSI" :status :untested :comment "Untested, use with caution" :backend "agfafocus" :version "unmaintained" :manpage "sane-agfafocus" :devicetype :scanner :mfg "AGFA" :url "http://www.agfa.com/" :model "Focus GS Scanner" :interface "SCSI" :status :untested :comment "6 bit gray" :model "Focus Lineart Scanner" :interface "SCSI" :status :untested :comment "Lineart only? Untested." :model "Focus II" :interface "SCSI" :status :untested :comment "gray only" :model "Focus Color" :interface "SCSI" :status :good :comment "3-pass" :model "Focus Color Plus" :interface "SCSI" :status :good :comment "3-pass" :mfg "Siemens" :model "S9036" :interface "SCSI" :status :untested :comment "gray only" ;Apple backend .desc file by Milon Firikis. :backend "apple" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-apple" ; name of manpage (if it exists) ;:url "http://no.www.page.yet/" ; backend's web page :devicetype :scanner ; start of a list of devices.... :mfg "Apple" :url "http://developer.apple.com/" :model "Apple Scanner" :interface "SCSI" :status :good ; :alpha, :beta, :stable, :new :comment "4bit, 16 shades of gray" :model "OneScanner" :interface "SCSI" :comment "8bit, 256 shades of gray. The backend needs work especially in the quantization code but it may work." :status :basic ; :alpha, :beta, :stable, :new :model "Color OneScanner" :interface "SCSI" :status :minimal ; :alpha, :beta, :stable, :new :comment "truecolor (needs much work) but it scans in non color modes." ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "artec" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-artec" ; name of manpage (if it exists) :url "http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Artec/Ultima" ; name a manufacturer :url "http://www.artecusa.com/" ;; name models for above-specified mfg. :model "AT3" :interface "SCSI" :status :complete :comment "all modes working" :model "A6000C" :interface "SCSI" :status :complete :comment "all modes working" :model "A6000C PLUS" :interface "SCSI" :status :complete :comment "f/w <= v1.92 basic, f/w >= v1.93 OK" :model "AT6" :status :good :interface "SCSI" :comment "Scan head needs to return home before another scan can be started." :model "AT12" :interface "SCSI" :status :complete :comment "all modes working" :model "AM12S" :interface "SCSI" :status :complete :comment "all modes working" :mfg "BlackWidow" :url "http://www.blackwidow.co.uk/" :model "BW4800SP" :interface "SCSI" :status :complete :comment "rebadged Artec AT3" :mfg "Plustek" :url "http://www.plustek.com/" :model "OpticPro 19200S" :interface "SCSI" :status :complete :comment "rebadged Artec AM12S" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; :backend "artec_eplus48u" :version "unmaintained" :manpage "sane-artec_eplus48u" ;:url "http://www.angelfire.com/linux/crapsite/" :devicetype :scanner :mfg "Artec/Ultima" :url "http://www.artecusa.com/" :model "E+ 48U" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :comment "CIS scanner based on the GT6816 chip. Apparently all other devices are re-badged Artec scanners." :model "E+ Pro" :status :minimal :interface "USB" :usbid "0x05d8" "0x4004" :comment "Works up to 600dpi, but not 1200. Needs better calibration. See bug #310490" :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.com" :comment "Sold by Aldi and Tchibo." :model "MD9693" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :model "MD9705" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :model "MD4394" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :comment "Only scanners with product id 0x4003 will work; try the gt68xx backend, if your scanner has product id 0x4002 " :mfg "Trust" :url "http://www.trust-site.com" :model "Easy Webscan 19200" :status :good :interface "USB" :usbid "0x05d8" "0x4006" :model "240H Easy Webscan Gold" :status :basic :interface "USB" :usbid "0x05d8" "0x4007" :comment "Works up to 600 dpi" :mfg "Memorex" :url "http://www.artecusa.com/" :model "MEM 48U" :status :good :interface "USB" :usbid "0x05d8" "0x4005" :mfg "Microstar" :url "http://www.microstar.de/" :model "MR 9791" :status :good :interface "USB" :usbid "0x05d8" "0x4003" :mfg "UMAX" :url "http://www.umax.com/" :url "http://www.umax.com.tw/" :url "http://www.umax.de/en" :url "http://www.umax-europe.com" :url "http://www.umaxjapan.co.jp" :url "http://www.umax.com.cn" :model "AstraSlim SE" :status :good :interface "USB" :usbid "0x05d8" "0x4009" :model "AstraSlim 1200 SE" :status :good :interface "USB" :usbid "0x05d8" "0x4010" :mfg "Yakumo" :url "http://www.yakumo.com/" :model "Scan50" :status :good :interface "USB" :usbid "0x05d8" "0x4011" ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "as6e" ; name of backend :version "0.5" ; version of backend :manpage "sane-as6e" ; name of manpage (if it exists) :url "http://as6edriver.sourceforge.net/" :devicetype :scanner :mfg "Artec/Ultima" ; name a manufacturer :url "http://www.artecusa.com/" :model "AS6E" :interface "Parport" :status :basic :comment "Requires the program 'as6edriver' to run." :mfg "Trust" ; name a manufacturer :url "http://www.trust-site.com" :comment "Carefully check the model names. Trust uses similar names for completely different hardware." :model "Easy Scan 9600 Plus" :interface "Parport" :status :basic :comment "Requires the program 'as6edriver' to run." :mfg "Dexxa" ; name a manufacturer :url "http://www.dexxa.com" :model "4800" :interface "Parport" :status :basic :comment "Requires the program 'as6edriver' to run." ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; SANE Backend specification file ; ; THIS FILE IS GENERATED FROM THE "avision.c" FILE AUTOMATICALLY - DO NOT EDIT ; THIS FILE MANUALLY !!! ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; name of backend :backend "avision" ; version of backend :version "Build: 296" ;status: alpha, beta, stable, new ;:status :stable ; backend's web page :url "http://skull.piratehaven.org/~mike/sane/avision.html" ; name of manpage (if it exists) :manpage "sane-avision" :devicetype :scanner :mfg "Avision" :url "http://www.avision.com" :model "AV100CS" :interface "SCSI" :status :untested :model "AV100IIICS" :interface "SCSI" :status :untested :model "AV100S" :interface "SCSI" :status :untested :model "AV120" :interface "USB" :usbid "0x0638" "0x0a27" :comment "sheetfed scanner" :status :complete :model "AV121" :interface "USB" :usbid "0x0638" "0x0a3c" :comment "sheetfed scanner" :status :good :model "AV122" :interface "USB" :usbid "0x0638" "0x0a33" :comment "sheetfed duplex scanner" :status :good :model "AV122 C2" :interface "USB" :usbid "0x0638" "0x0a93" :comment "sheetfed duplex scanner" :status :good :model "AV210" :interface "USB" :usbid "0x0638" "0x0a24" :comment "sheetfed scanner" :status :complete :model "AV210" :interface "USB" :usbid "0x0638" "0x0a25" :comment "sheetfed scanner" :status :complete :model "AV210C2" :interface "USB" :usbid "0x0638" "0x0a3a" :comment "sheetfed scanner" :status :complete :model "AV210C2-G" :interface "USB" :usbid "0x0638" "0x0a2f" :comment "sheetfed scanner" :status :complete :model "AV210D2+" :interface "USB" :usbid "0x0638" "0x1a35" :comment "sheetfed scanner" :status :complete :model "AV220" :interface "USB" :usbid "0x0638" "0x0a23" :comment "duplex! sheetfed scanner" :status :complete :model "AV220C2" :interface "USB" :usbid "0x0638" "0x0a2a" :comment "duplex! sheetfed scanner" :status :complete :model "AV220D2" :interface "USB" :usbid "0x0638" "0x0a2b" :comment "duplex! sheetfed scanner" :status :complete :model "AV220+" :interface "USB" :usbid "0x0638" "0x0a2c" :comment "duplex! sheetfed scanner" :status :complete :model "AV220C2-G" :interface "USB" :usbid "0x0638" "0x0a2d" :comment "duplex! sheetfed scanner" :status :complete :model "AV220C2-B" :interface "USB" :usbid "0x0638" "0x0a2e" :comment "duplex! sheetfed scanner" :status :complete :model "AV220-G" :interface "USB" :usbid "0x0638" "0x0a94" :comment "duplex! sheetfed scanner" :status :complete :model "AV240SC" :interface "SCSI" :status :untested :model "AV260CS" :interface "SCSI" :status :untested :model "AV360CS" :interface "SCSI" :status :untested :model "AV363CS" :interface "SCSI" :status :untested :model "AV420CS" :interface "SCSI" :status :untested :model "AV6120" :interface "SCSI" :status :untested :model "AV610" :interface "USB" :usbid "0x0638" "0x0a18" :status :good :model "AV600U Plus" :interface "USB" :usbid "0x0638" "0x0a18" :status :good :model "AV610C2" :interface "USB" :usbid "0x0638" "0x0a5e" :status :good :model "AM3000 Series" :interface "USB" :usbid "0x0638" "0x0a41" :comment "MFD" :status :basic :model "DS610CU Scancopier" :interface "USB" :usbid "0x0638" "0x0a16" :comment "1 pass, 600 dpi, A4" :status :good :model "AV620CS" :interface "SCSI" :comment "1 pass, 600 dpi" :status :complete :model "AV620CS Plus" :interface "SCSI" :comment "1 pass, 1200 dpi" :status :complete :model "AV630CS" :interface "SCSI" :comment "1 pass, 1200 dpi" :status :complete :model "AV630CSL" :interface "SCSI" :comment "1 pass, 1200 dpi" :status :untested :model "AV6240" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV600U" :interface "USB" :usbid "0x0638" "0x0a13" :comment "1 pass, 600 dpi" :status :good :model "AV660S" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV680S" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV690U" :interface "SCSI" :comment "1 pass, 2400 dpi" :status :untested :model "AV800S" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV810C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV820" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV820C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV820C Plus" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV830C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV830C Plus" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV880" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV880C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :untested :model "AV3200C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV3200SU" :interface "USB" :usbid "0x0638" "0x0a4e" :comment "1 pass, ??? dpi" :status :complete :model "AV3730SU" :interface "USB" :usbid "0x0638" "0x0a4f" :comment "1 pass, ??? dpi" :status :complete :model "AV3750SU" :interface "USB" :usbid "0x0638" "0x0a65" :comment "1 pass, ??? dpi" :status :complete :model "AV3800C" :interface "SCSI" :comment "1 pass, ??? dpi" :status :complete :model "AV3850SU" :interface "USB" :usbid "0x0638" "0x0a66" :comment "1 pass, ??? dpi" :status :complete :model "FB6000E" :interface "SCSI" :comment "1 pass, 1200 dpi, A3 - duplex! - zero edge!" :status :complete :model "FB6080E" :interface "USB" :usbid "0x0638" "0x0a82" :comment "1 pass, 1200 dpi, A3 - duplex! - zero edge!" :status :complete :model "FB2080E" :interface "USB" :usbid "0x0638" "0x0a84" :comment "1 pass, 600 dpi, zero-edge" ASIC 7 :status :basic :model "AV8000S" :interface "SCSI" :comment "1 pass, 1200 dpi, A3" :status :complete :model "AV8050U" :interface "USB" :usbid "0x0638" "0x0a4d" :comment "1 pass, 1200 dpi, A3 - duplex!" :status :complete :model "AV8300" :interface "USB" :usbid "0x0638" "0x0a40" :comment "1 pass, 1200 dpi, A3 - duplex!" :status :complete :model "AV8350" :interface "USB" :usbid "0x0638" "0x0a68" :comment "1 pass, 1200 dpi, A3 - duplex!" :status :complete :model "IT8300" :interface "USB" :usbid "0x0638" "0x0a61" :comment "1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" :status :good :model "@V2500" :interface "USB" :usbid "0x0638" "0x0aa1" :status :untested :model "@V5100" :interface "USB" :usbid "0x0638" "0x0a45" :comment "1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" :status :good :model "AVA3" :interface "SCSI" :comment "1 pass, 600 dpi, A3" :status :basic :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "ScanJet 5300C" :interface "USB" :usbid "0x03f0" "0x0701" :comment "1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" :status :complete :model "ScanJet 5370C" :interface "USB" :usbid "0x03f0" "0x0701" :comment "1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" :status :good :model "ScanJet 7400c" :interface "USB" :usbid "0x03f0" "0x0801" :comment "1 pass, 2400 dpi - dual USB/SCSI interface" :status :good :model "ScanJet 7450c" :interface "USB" :usbid "0x03f0" "0x0801" :comment "1 pass, 2400 dpi - dual USB/SCSI interface" :status :good :model "ScanJet 7490c" :interface "USB" :usbid "0x03f0" "0x0801" :comment "1 pass, 1200 dpi - dual USB/SCSI interface" :status :good :model "ScanJet 8200" :interface "USB" :usbid "0x03f0" "0x0b01" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8250" :interface "USB" :usbid "0x03f0" "0x0b01" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8270" :interface "USB" :usbid "0x03f0" "0x3905" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8290" :interface "USB" :usbid "0x03f0" "0x0b01" :comment "1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far" :status :good :model "ScanJet 8300" :interface "USB" :usbid "0x03f0" "0x3805" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8350" :interface "USB" :usbid "0x03f0" "0x3805" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :model "ScanJet 8390" :interface "USB" :usbid "0x03f0" "0x3805" :comment "1 pass, 4800 (?) dpi - USB 2.0" :status :good :mfg "Minolta" :url "http://www.minolta.com" :model "Dimage Scan Dual I" :interface "SCSI" :status :basic :model "Scan Multi Pro" :interface "SCSI" :status :untested :model "Dimage Scan Dual II" :interface "USB" :usbid "0x0638" "0x026a" :comment "1 pass, film-scanner" :status :good :model "Elite II" :interface "USB" :usbid "0x0686" "0x4004" :comment "1 pass, film-scanner" :status :untested :model "Dimage Scan Dual III" :interface "USB" :usbid "0x0686" "0x400d" :comment "1 pass, film-scanner" :status :good :model "Dimage Scan Elite 5400" :interface "USB" :usbid "0x0686" "0x400e" :comment "1 pass, film-scanner" :status :good :mfg "Minolta-QMS" :model "SC-110" :interface "USB" :usbid "0x0638" "0x0a15" :status :untested :model "SC-215" :interface "USB" :usbid "0x0638" "0x0a16" :status :good :mfg "Mitsubishi" :model "MCA-ADFC" :interface "SCSI" :status :untested :model "S1200C" :interface "SCSI" :status :untested :model "S600C" :interface "SCSI" :status :untested :model "SS600" :interface "SCSI" :status :good :mfg "Fujitsu" :url "http://www.fujitsu.com" :model "ScanPartner" :interface "SCSI" :status :untested :model "ScanPartner 10" :interface "SCSI" :status :untested :model "ScanPartner 10C" :interface "SCSI" :status :untested :model "ScanPartner 15C" :interface "SCSI" :status :untested :model "ScanPartner 300C" :interface "SCSI" :status :untested :model "ScanPartner 600C" :interface "SCSI" :status :untested :model "ScanPartner 620C" :interface "SCSI" :status :good :model "ScanPartner Jr" :interface "SCSI" :status :untested :model "ScanStation" :interface "SCSI" :status :untested :model "fi-4010CU" :interface "USB" :usbid "0x04c5" "0x1029" :status :untested :model "fi-5015C" :interface "USB" :usbid "0x04c5" "0x10ef" :status :good :mfg "Kodak" :url "http://www.kodak.com" :model "i30" :interface "USB" :usbid "0x040a" "0x6001" :status :untested :model "i40" :interface "USB" :usbid "0x040a" "0x6002" :status :basic :model "i50" :interface "USB" :usbid "0x040a" "0x6003" :status :untested :model "i55" :interface "USB" :usbid "0x040a" "0x6003" :status :untested :model "i60" :interface "USB" :usbid "0x040a" "0x6004" :status :untested :model "i65" :interface "USB" :usbid "0x040a" "0x6004" :status :untested :model "i80" :interface "USB" :usbid "0x040a" "0x6005" :status :good :mfg "iVina" :model "1200U" :interface "USB" :usbid "0x0638" "0x0268" :status :untested :mfg "Visioneer" :model "Strobe XP 450" :interface "USB" :usbid "0x04a7" "0x0424" :comment "sheetfed scanner" :status :complete :model "Strobe XP 450-G" :interface "USB" :usbid "0x04a7" "0x0491" :comment "sheetfed scanner" :status :complete :model "Strobe XP 470" :interface "USB" :usbid "0x04a7" "0x0479" :comment "sheetfed scanner" :status :complete :model "Strobe XP 470-G" :interface "USB" :usbid "0x04a7" "0x048f" :comment "sheetfed scanner" :status :complete :model "9320" :interface "USB" :usbid "0x04a7" "0x0420" :comment "sheetfed scanner" :status :complete :model "9450" :interface "USB" :usbid "0x04a7" "0x0421" :comment "sheetfed scanner" :status :complete :model "9450-G" :interface "USB" :usbid "0x04a7" "0x047a" :comment "sheetfed scanner" :status :complete :model "9550" :interface "USB" :usbid "0x04a7" "0x0422" :comment "sheetfed scanner" :status :complete :model "9650" :interface "USB" :usbid "0x04a7" "0x0390" :comment "sheetfed scanner" :status :complete :model "9650-G" :interface "USB" :usbid "0x04a7" "0x047b" :comment "sheetfed scanner" :status :complete :model "9750" :interface "USB" :usbid "0x04a7" "0x0423" :comment "sheetfed scanner" :status :complete :model "9750-G" :interface "USB" :usbid "0x04a7" "0x0493" :comment "sheetfed scanner" :status :complete :model "Patriot 430" :interface "USB" :usbid "0x04a7" "0x0497" :comment "sheetfed scanner" :status :complete :model "Patriot 470" :interface "USB" :usbid "0x04a7" "0x048f" :comment "sheetfed scanner" :status :complete :model "Patriot 680" :interface "USB" :usbid "0x04a7" "0x0498" :comment "sheetfed scanner" :status :complete :model "Patriot 780" :interface "USB" :usbid "0x04a7" "0x0499" :comment "sheetfed scanner" :status :complete :mfg "Xerox" :model "DocuMate150" :interface "USB" :usbid "0x04a7" "0x049c" :status :good :model "DocuMate152" :interface "USB" :usbid "0x04a7" "0x0477" :status :good :model "DocuMate162" :interface "USB" :usbid "0x04a7" "0x049d" :status :good :model "DocuMate250" :interface "USB" :usbid "0x04a7" "0x0448" :status :good :model "DocuMate250-G" :interface "USB" :usbid "0x04a7" "0x0490" :status :good :model "DocuMate252" :interface "USB" :usbid "0x04a7" "0x0449" :status :good :model "DocuMate252-G" :interface "USB" :usbid "0x04a7" "0x048c" :status :good :model "DocuMate232" :interface "USB" :usbid "0x04a7" "0x0476" :status :good :model "DocuMate262" :interface "USB" :usbid "0x04a7" "0x044c" :status :good :model "DocuMate262-G" :interface "USB" :usbid "0x04a7" "0x048d" :status :good :model "DocuMate262i" :interface "USB" :usbid "0x04a7" "0x04a7" :status :good :model "DocuMate272" :interface "USB" :usbid "0x04a7" "0x0475" :status :untested :model "DocuMate272-G" :interface "USB" :usbid "0x04a7" "0x048e" :status :untested :model "DocuMate510" :interface "USB" :usbid "0x04a7" "0x0446" :status :untested :model "DocuMate512" :interface "USB" :usbid "0x04a7" "0x0495" :status :untested :model "DocuMate510-G" :interface "USB" :usbid "0x04a7" "0x047c" :status :untested :model "DocuMate520" :interface "USB" :usbid "0x04a7" "0x0447" :status :untested :model "DocuMate520-G" :interface "USB" :usbid "0x04a7" "0x0492" :status :untested :model "DocuMate632" :interface "USB" :usbid "0x04a7" "0x0498" :status :untested :model "DocuMate752" :interface "USB" :usbid "0x04a7" "0x0478" :status :untested :model "DocuMate752" :interface "USB" :usbid "0x04a7" "0x049a" :status :untested :mfg "OKI" :model "S700 Scancopier" :interface "USB" :usbid "0x0638" "0x0a16" :comment "1 pass, 600 dpi, A4" :status :good :mfg "Bell+Howell" :model "2000F" :interface "SCSI" :comment "1 pass, ??? dpi, A4" :status :basic :mfg "Kyocera" :model "FS-1016MFP" :interface "USB" :usbid "0x0482" "0x0335" :comment "1 pass, ??? dpi, A4" :status :untested ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "bh" ; name of backend :version "1.0-4" ; version of backend :manpage "sane-bh" ; name of manpage (if it exists) :url "http://www.martoneconsulting.com/sane-bh.html" ; backend's web page :comment "Supports Copiscan II scanners with Remote SCSI Controller (RSC) interface" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Bell and Howell" ; name a manufacturer :url "http://www.bhscanners.com/" :model "COPISCAN II 6338" :interface "SCSI" :status :good :comment "Duplex Scanner with ACE - development model" :model "COPISCAN II 2135" :status :untested :interface "SCSI" :comment "Simplex Scanner" :model "COPISCAN II 2137(A)" :interface "SCSI" :status :good :comment "Simplex Scanner (with ACE) - limited testing" :model "COPISCAN II 2138A" :status :untested :interface "SCSI" :comment "Simplex Scanner with ACE" :model "COPISCAN II 3238" :status :untested :interface "SCSI" :comment "Simplex Scanner" :model "COPISCAN II 3338(A)" :status :untested :interface "SCSI" :comment "Simplex Scanner (with ACE)" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "canon630u" ; name of backend :manpage "sane-canon630u" :version "0.1" ; version of backend ;:status :beta :url "http://canon-fb630u.sourceforge.net/" ; backend home page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" :model "CanoScan fb630u" ; name models for above-specified mfg. :interface "USB" :usbid "0x04a9" "0x2204" :comment "OK" :status :good :model "CanoScan fb636u" ; name models for above-specified mfg. :interface "USB" :usbid "0x04a9" "0x2204" :status :good :comment "OK" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "canon" ; name of backend :manpage "sane-canon" :version "1.12" ; version of backend ;:status :good ; :alpha, :beta, :stable, :new :url "http://www.rzg.mpg.de/~mpd/sane/" ; backend home page :devicetype :scanner :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" :model "CanoScan 300" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :model "CanoScan 600" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :model "CanoScan 620S" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :model "CanoScan 1200S" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :model "CanoScan 2700F" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; film scanner" :status :good :model "CanoScan 2710S" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; 36bit film scanner" :status :good :model "IX-4015" ; name models for above-specified mfg. :interface "SCSI" :comment "1 pass; flatbed scanner" :status :good :mfg "Apple" ; name a manufacturer :url "http://www.apple.com/" :model "Color OneScanner 600/27" ; name models for above-specified mfg. :interface "SCSI" :comment "Rebadged CanoScan 300" :status :good ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "canon_dr" ; name of backend :url "http://www.thebility.com/canon/" :version "38" ; version of backend :manpage "sane-canon_dr" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.23, see sane-canon_dr manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" ;================================================== :model "CR-25" :interface "USB" :usbid "0x1083" "0x161a" :status :untested :comment "Please test!" :model "CR-55" :interface "USB" :usbid "0x1083" "0x160c" :status :untested :comment "Please test!" :model "CR-135i" :interface "USB SCSI" :usbid "0x1083" "0x1639" :status :untested :comment "Please test!" :model "CR-180" :interface "USB SCSI" :usbid "0x04a9" "0x1602" :status :untested :comment "Please test!" :model "CR-180II" :interface "USB SCSI" :usbid "0x04a9" "0x1602" :status :untested :comment "Same as CR-180? Please test!" :model "CR-190i" :interface "USB SCSI" :usbid "0x1083" "0x162b" :status :untested :comment "Please test!" :model "DR-1210C" :interface "USB" :usbid "0x04a9" "0x2222" :status :untested :comment "Older version? Please test!" :model "DR-1210C" :interface "USB" :usbid "0x1083" "0x160f" :status :untested :comment "Later version? Please test!" :model "DR-2010C" :interface "USB" :usbid "0x1083" "0x161b" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions." :model "DR-2010M" :interface "USB" :status :untested :comment "Mac version of DR-2010C? Please test!" :model "DR-2050C" :interface "USB" :usbid "0x04a9" "0x160a" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration." :model "DR-2050SP" :interface "USB" :usbid "0x04a9" "0x160a" :status :untested :comment "Same as DR-2050C? Please test!" :model "DR-2080C" :interface "USB SCSI" :usbid "0x04a9" "0x1601" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration" :model "DR-2510C" :interface "USB" :usbid "0x1083" "0x1617" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions" :model "DR-2510M" :interface "USB" :status :untested :comment "Mac version of DR-2510C? Please test!" :model "DR-2580C" :interface "USB SCSI" :usbid "0x04a9" "0x1608" :status :complete :comment "Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration" :model "DR-3010C" :interface "USB" :usbid "0x1083" "0x161d" :status :good :comment "Minimal testing, settings copied from DR-2510C" :model "DR3020" :interface "SCSI" :status :untested :comment "Please test!" :model "DR-3020C" :interface "SCSI" :status :untested :comment "Please test!" :model "DR-3060" :interface "SCSI" :status :untested :comment "Please test!" :model "DR-3080C" :interface "SCSI" :status :untested :comment "Almost works, need to investigate traces from windows driver" :model "DR-3080CII" :interface "USB SCSI" :usbid "0x04a9" "0x1609" :status :untested :comment "Almost works, need to investigate traces from windows driver" :model "DR-4010C" :interface "USB" :usbid "0x1083" "0x1614" :status :good :comment "Binary/HT/Gray/Color, Simplex/Duplex working. Multistream unsupported." :model "DR4080U" :interface "USB" ;:usbid "0x1083" "0x1614" :status :untested :comment "Please test!" :model "DR-4580U" :interface "USB" ;:usbid "0x1083" "0x1614" :status :untested :comment "Please test!" :model "DR-5010C" :interface "USB" :usbid "0x04a9" "0x1606" :status :untested :comment "Please test!" :model "DR-5020" :interface "SCSI" :status :good :comment "LineArt, Duplex working, cannot read buttons or screen?" :model "DR-5060F" :interface "SCSI" :status :basic :comment "Grayscale works, LineArt might" :model "DR-5080C" :interface "SCSI" :status :untested :comment "Please test!" :model "DR-6010C" :interface "USB SCSI" :usbid "0x1083" "0x1626" :status :untested :comment "Please test!" :model "DR-6030C" :interface "USB SCSI" :usbid "0x1083" "0x1638" :status :untested :comment "Please test!" :model "DR-6050C" :interface "USB SCSI" :usbid "0x1083" "0x1624" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode" :model "DR-6080" :interface "USB SCSI" :usbid "0x04a9" "0x1607" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported" :model "DR-7080C" :interface "USB SCSI" :usbid "0x04a9" "0x1604" :status :untested :comment "Please test!" :model "DR-7090C" :interface "USB SCSI" :usbid "0x1083" "0x1620" :status :good :comment "ADF and flatbed work" :model "DR-7550C" :interface "USB SCSI" :usbid "0x1083" "0x1623" :status :untested :comment "Assumed compatible with DR-6050C" :model "DR-7580" :interface "USB SCSI" :usbid "0x04a9" "0x160b" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported" :model "DR-9050C" :interface "USB SCSI" :usbid "0x1083" "0x1622" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode" :model "DR-9080C" :interface "USB SCSI" :usbid "0x04a9" "0x1603" :status :good :comment "Simplex, duplex, all resolutions, binary/ht/gray/color, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported" :model "DR-X10C" :interface "USB SCSI" :usbid "0x1083" "0x1618" :status :untested :comment "Please test!" ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "canon_pp" ; name of backend :manpage "sane-canon_pp" :version "0.33" ; version of backend :url "http://canon-fb330p.sourceforge.net" ; backend home page :devicetype :scanner :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" :model "CanoScan FB310P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :unsupported :comment "Rebadged Avision, different command set" :model "CanoScan FB610P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :unsupported :comment "Rebadged Avision, different command set" :model "CanoScan FB320P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :basic :comment "Newly added support" :model "CanoScan FB620P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :basic :comment "Newly added support" :model "CanoScan FB330P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :model "CanoScan FB630P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :model "CanoScan N340P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :model "CanoScan N640P" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :model "CanoScan N640P ex" ; name models for above-specified mfg. :interface "Parport (ECP)" :status :good :comment "Just an N640P in a different box?" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "cardscan" ; name of backend :url "http://www.thebility.com/cardscan/" :version "2" ; version of backend :manpage "sane-cardscan" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.21, see sane-cardscan manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Corex" ; name a manufacturer :url "http://www.cardscan.com/" :model "800c" :interface "USB" :usbid "0x08f0" "0x0005" :status :good :comment "4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner" :model "600c" :interface "USB" :usbid "0x08f0" "0x0002" :status :basic :comment "4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner" ; ; SANE Backend specification file for coolscan2 ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "coolscan2" :version "0.1.8" :manpage "sane-coolscan2" :url "http://coolscan2.sourceforge.net/" :devicetype :scanner :mfg "Nikon" :url "http://www.nikon.com/" :model "LS 30" :interface "SCSI" :comment "working -- model available to developer" :status :complete :model "LS 2000" :interface "SCSI" :status :good :model "LS 40 ED" :interface "USB" :usbid "0x04b0" "0x4000" :status :complete :model "LS 4000 ED" :interface "IEEE-1394" :status :good :comment "needs linux kernel 2.4.19 or later" :model "LS 50 ED" ;:url "/unsupported/nikon-ls50-ed.html" :interface "USB" :usbid "0x04b0" "0x4001" :status :minimal :model "Coolscan V ED" :url "/unsupported/nikon-ls50-ed.html" :interface "USB" :usbid "0x04b0" "0x4001" :status :minimal :model "Super Coolscan LS-5000 ED" :url "/unsupported/nikon-ls5000-ed.html" :interface "USB" :usbid "0x04b0" "0x4002" :status :untested :comment "May work, similar to LS 50 ED, but untested. Please tell us if it works." :model "LS 8000 ED" :interface "IEEE-1394" :status :good :comment "needs linux kernel 2.4.19 or later" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file for coolscan2 ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "coolscan3" :version "1.0.0" :manpage "sane-coolscan3" :devicetype :scanner :mfg "Nikon" :url "http://www.nikon.com/" :model "LS 30" :interface "SCSI" :status :complete :model "Coolscan III" :interface "SCSI" :status :complete :comment "Rebadged LS 30?" :model "LS 40 ED" :interface "USB" :usbid "0x04b0" "0x4000" :status :complete :model "Coolspan IV" :interface "USB" :usbid "0x04b0" "0x4000" :status :complete :comment "Rebadged LS 40?" :model "LS 50 ED" :url "/unsupported/nikon-ls50-ed.html" :interface "USB" :usbid "0x04b0" "0x4001" :status :minimal :model "Coolscan V ED" :url "/unsupported/nikon-ls50-ed.html" :interface "USB" :usbid "0x04b0" "0x4001" :status :minimal :comment "Rebadged LS 50?" :model "LS 2000" :interface "SCSI" :status :good :model "LS 4000 ED" :interface "IEEE-1394" :status :good :comment "needs linux kernel 2.4.19 or later" :model "Super Coolscan LS-5000 ED" :url "/unsupported/nikon-ls5000-ed.html" :interface "USB" :usbid "0x04b0" "0x4002" :status :untested :comment "May work, similar to LS 50 ED, but untested. Please tell us if it works." :model "LS 8000 ED" :interface "IEEE-1394" :status :good :comment "needs linux kernel 2.4.19 or later" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "coolscan" ; name of backend :version "0.4.3" ; version of backend :url "http://andreas.rick.free.fr/sane/" ; backend's web page :manpage "sane-coolscan" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Nikon" ; name a manufacturer :url "http://www.nikon.com/" :model "LS-20" ; name models for above-specified mfg. :interface "SCSI" :comment "The LS-20 has been replaced by the LS-30" :status :basic :model "LS-30" ; name models for above-specified mfg. :interface "SCSI" :comment "alpha: only 24/30 bit RGB + 32/40 bit RGBI" :status :basic :model "LS-2000" ; name models for above-specified mfg. :interface "SCSI" :comment "alpha: only 24/36 bit + RGB 32/48 bit RGBI" :status :basic :model "LS-1000" :interface "SCSI" :comment "Doesn't support gamma correction" :status :basic ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ;Kodak DC210 backend .desc file by Brian J. Murrell :backend "dc210" ; name of backend :version "0.0" ; version of backend :manpage "sane-dc210" ; name of manpage (if it exists) :url "mailto:peter@fales-lorenz.net" ; backend's web page :devicetype :stillcam ; start of a list of devices.... :mfg "Kodak" :url "http://www.kodak.com/global/en/service/digCam/dc210/dc210.shtml" :model "DC210" :interface "Serial port" :status :basic ;Kodak DC240 backend .desc file by Peter S. Fales :backend "dc240" ; name of backend :version "0.0" ; version of backend :manpage "sane-dc240" ; name of manpage (if it exists) :url "mailto:peter@fales-lorenz.net" ; backend's web page :devicetype :stillcam ; start of a list of devices.... :mfg "Kodak" :url "http://www.kodak.com/global/en/service/products/ekn006568.jhtml" :model "DC240" :status :good ; minimal, basic, good, complete :interface "Serial port" :comment "Use gphoto2 backend to get USB support" ;Kodak DC25 backend .desc file by Peter Fales :backend "dc25" ; name of backend :version "1.2" ; version of backend :manpage "sane-dc25" ; name of manpage (if it exists) :url "mailto:peter@fales-lorenz.net"; :devicetype :stillcam ; start of a list of devices.... :mfg "Kodak" ; Manufacturer :url "http://www.kodak.com/global/en/service/digCam/dc25/dc25.shtml"; :model "DC25" ; :status :complete ; untested, minimal, basic, complete :interface "Serial port" :model "DC20" ; :status :basic ; untested, minimal, basic, complete :interface "Serial port" :comment "DC-20 untested by author but reported to work" ; ; dell1600n_net backend ; Jon Chambers , 2006-05-29 ; :backend "dell1600n_net" :devicetype :scanner :mfg "Dell" :url "http://www.dell.com/" :model "1600n" :interface "Ethernet USB" :usbid "0x413c" "0x5250" :status :basic :comment "Supports colour and monochrome scans over ethernet (USB not supported)" :backend "dll" ; name of backend :version "1.0.13" :manpage "sane-dll" :url "mailto:henning@meier-geinitz.de" :devicetype :meta :desc "Dynamic loading of shared-library backends." ; $Id$ ; ; SANE Backend specification file (Matto Marjanovic's format) ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "dmc" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-dmc" ; name of manpage (if it exists) :devicetype :stillcam ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Polaroid" ; name a manufacturer :url "http://www.polaroid.com/" :model "DMC" ; name models for above-specified mfg. :interface "SCSI" ;:url "http://digitalimage.polaroid.com/products/digital_imaging/digital_cameras/dmcsuite/dmc/" :status :good ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "epjitsu" ; name of backend :url "http://www.thebility.com/epjitsu/" :version "20" ; version of backend :manpage "sane-epjitsu" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.21, see sane-epjitsu manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Fujitsu" ; name a manufacturer :url "http://www.fujitsu.com/" ;================================================== :model "fi-60F" :interface "USB" :status :basic :usbid "0x04c5" "0x10c7" :comment "A6-size flatbed, 300/600 dpi, color/gray/binary" :model "ScanSnap S300" :interface "USB" :status :good :usbid "0x04c5" "0x1156" :comment "Duplex, 150/225/300/600 dpi, color/gray/binary, AC/USB power, buttons/sensors all supported. Scanner always scans in _triplex_ color, fast USB required." :model "ScanSnap S300M" :interface "USB" :status :good :usbid "0x04c5" "0x117f" :comment "Same as S300, with different usb id" :model "ScanSnap S1100" :interface "USB" :status :unsupported :usbid "0x04c5" "0x1200" :comment "Beta version of backend source available, which works well, but breaks support for other epjitsu scanners. See http://ubuntuforums.org/showthread.php?t=1678335" :model "ScanSnap S1300" :interface "USB" :status :good :usbid "0x04c5" "0x11ed" :comment "Same as S300, with different usb id" ; ; SANE Backend specification file for the epson2 backend ; ; Copyright (C) 2009-10 Alessandro Zummo ; Released under GPLv2 ; ; This file is derived from epkowa.desc, Copyright (C) Olaf Meeuwissen, ; distributed with "Image Scan!" and released under GPL. ; ; DO NOT EDIT - It's automatically generated. :backend "epson2" :version "1.0.124" :new :no :manpage "sane-epson2" :devicetype :scanner :mfg "Epson" :url "http://www.epson.com/" :model "Actionscanner II" :interface "parallel SCSI" :status :good :comment "overseas version of the GT-5000" :url "http://www.epson.com/" :model "AcuLaser CX11" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :comment "overseas version of the LP-A500" :model "AcuLaser CX11NF" :interface "USB Network" :usbid "0x04b8" "0x0815" :status :good :comment "network interface supported
AcuLaser CX11 with network interface and fax" :model "AcuLaser CX21" :interface "USB" :usbid "0x04b8" "0x0835" :status :good :comment "network interface probably supported" :model "Artisan 700" :interface "USB Network" :usbid "0x04b8" "0x0846" :status :good :comment "network interface supported
all-in-one
overseas version of the EP-801A" :model "Artisan 710 Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Artisan 800" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-901A" :model "Artisan 810 Series" :interface "USB" :usbid "0x04b8" "0x0853" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "CC-500L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010d" :status :unsupported :comment "all-in-one" :model "CC-550L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011a" :status :unsupported :comment "all-in-one" :model "CC-570L" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one" :model "CC-600PX" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one" :model "CC-700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0108" :status :unsupported :comment "all-in-one" :model "EP-702A" :interface "USB" :usbid "0x04b8" "0x0850" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "EP-801A" :interface "USB Network" :usbid "0x04b8" "0x0846" :status :good :comment "network interface supported
all-in-one" :model "EP-802A" :interface "USB" :usbid "0x04b8" "0x0852" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "EP-901A" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one" :model "EP-901F" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one" :model "EP-902A" :interface "USB" :usbid "0x04b8" "0x0853" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "ES-300C" :interface "SCSI parallel" :status :good :comment "overseas version of the GT-6000" :model "ES-300GS" :interface "SCSI" :status :good :model "ES-600C" :interface "parallel" :status :good :comment "overseas version of the GT-5400" :model "ES-800C" :interface "SCSI" :status :good :comment "overseas version of the GT-8000" :model "ES-1000C" :status :unsupported :comment "overseas version of the GT-8500" :model "ES-1200C" :interface "parallel" :status :good :comment "overseas version of the GT-9000" :model "ES-2000" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0107" :status :complete :comment "IEEE1394 untested" :model "ES-2200" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010e" :status :complete :comment "IEEE1394 untested" :model "ES-6000" ; product spec (JP) :interface "SCSI" :status :good :model "ES-6000H" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-6000HS" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-7000H" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0126" :status :good :comment "network interface unsupported
IEEE1394 untested" :model "ES-8000" :interface "SCSI" :status :untested :model "ES-8500" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x0109" :status :good :comment "IEEE1394 untested" :model "ES-9000H" ; product spec (JP) :interface "SCSI" :status :good :comment "IEEE1394 untested" :model "ES-10000G" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0129" :status :good :comment "network interface unsupported
IEEE1394 untested" :model "ES-D400" :interface "USB" :usbid "0x04b8" "0x0136" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "ES-H300" :interface "USB" :usbid "0x04b8" "0x012b" :status :good :comment "network interface probably supported" :model "ES-H7200" :interface "USB Ethernet" :usbid "0x04b8" "0x0138" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Expression 636" :interface "SCSI" :status :complete :comment "overseas version of the GT-9500" :model "Expression 800" ; command spec :interface "SCSI" :status :complete :comment "overseas version of the GT-9600" :model "Expression 836XL" ; command spec :interface "SCSI" :status :untested :comment "overseas version of the ES-8000" :model "Expression 1600" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0107" :status :complete :comment "IEEE1394 untested
overseas version of the ES-2000" :model "Expression 1640XL" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0109" :status :good :comment "IEEE1394 untested
overseas version of the ES-8500" :model "Expression 1680" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x010e" :status :complete :comment "IEEE1394 untested
overseas version of the ES-2200" :model "Expression 1680 Pro" :interface "SCSI USB" :status :untested :comment "IEEE1394 option" :model "Expression 1680XL Pro" :interface "SCSI USB" :status :untested :model "Expression 10000XL" ; command spec :interface "USB" :usbid "0x04b8" "0x0129" :status :good :comment "network interface probably supported
IEEE1394 untested
overseas version of the ES-10000G" :model "Expression 10000XL Graphic Arts" :interface "USB IEEE1394" :status :untested :comment "network interface probably supported" :model "Expression 10000XL Photo" :interface "USB IEEE1394" :status :untested :comment "network interface probably supported" :model "F-3200" ; product spec (JP) :interface "USB IEEE1394" :usbid "0x04b8" "0x080a" :status :unsupported :comment "Film scanner" :model "F-3200 Photo" :interface "USB IEEE1394" :status :unsupported :model "FilmScan 200" :interface "SCSI" :status :minimal :comment "will be supported" :model "GT-1500" :interface "USB" :usbid "0x04b8" "0x0133" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-2200" :interface "USB" :usbid "0x04b8" "0x0102" :status :unsupported :model "GT-2500" :interface "USB" :usbid "0x04b8" "0x012b" :status :good :comment "network interface probably supported
overseas version of the ES-H300" :model "GT-4000" :status :untested :model "GT-5000" :interface "parallel SCSI" :status :good :model "GT-5400" :interface "parallel" :status :good :model "GT-5500" :interface "SCSI" :status :good :model "GT-6000" :interface "SCSI Parport" :status :good :model "GT-6500" :interface "parallel" :status :good :comment "overseas version of the GT-5400" :model "GT-6600U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0103" :status :complete :model "GT-6700U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010c" :status :complete :model "GT-7000S" :interface "SCSI" :status :complete :model "GT-7000U" :interface "USB" :usbid "0x04b8" "0x0101" :status :complete :model "GT-7200U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-7300U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-7400U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0120" :status :unsupported :comment "supported by the snapscan backend" :model "GT-7600S" ; product spec (JP) :interface "SCSI" :status :complete :comment "SCSI version of the GT-7600U" :model "GT-7600U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "USB version of the GT-7600S" :model "GT-7600UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "GT-7600U with TPU option bundled" :model "GT-7700U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x010b" :status :complete :model "GT-8000" :interface "SCSI" :status :good :model "GT-8200U" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0110" :status :complete :model "GT-8200UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0110" :status :good :model "GT-8300UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011e" :status :complete :model "GT-8400UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :model "GT-8500" :status :untested :model "GT-8700" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :complete :model "GT-8700F" ; product spec (JP) :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :good :comment "GT-8700U with TPU option bundled" :model "GT-9000" :interface "parallel" :status :good :model "GT-9300UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011b" :status :complete :model "GT-9400UF" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0116" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-9500" :interface "SCSI" :status :complete :model "GT-9600" :interface "SCSI" :status :complete :model "GT-9700F" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0112" :status :complete :comment "IEEE1394 untested" :model "GT-9800F" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x011c" :status :complete :comment "IEEE1394 untested" :model "GT-10000" :interface "SCSI" :status :good :comment "overseas version of the ES-6000" :model "GT-10000+" ; command spec :interface "SCSI" :scsi "EPSON" "SCANNER GT-10000" "processor" :status :good :comment "IEEE1394 untested
overseas version of the ES-6000H" :model "GT-12000" :interface "SCSI" :status :untested :comment "overseas version of the ES-8000" :model "GT-15000" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x0126" :status :good :comment "IEEE1394 untested
overseas version of the ES-7000H" :model "GT-20000" :interface "USB Ethernet" :usbid "0x04b8" "0x0138" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "GT-30000" ; command spec :interface "SCSI" :status :good :comment "IEEE1394 untested
overseas version of the ES-9000H" :model "GT-D1000" :interface "USB" :usbid "0x04b8" "0x0133" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F500" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F520" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F550" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F570" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F600" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0118" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F650" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F670" :interface "USB" :usbid "0x04b8" "0x012e" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F700" :interface "USB" :usbid "0x04b8" "0x012f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-F720" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-S50" :interface "USB" :usbid "0x04b8" "0x0137" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "GT-S80" :interface "USB" :usbid "0x04b8" "0x0136" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "GT-S600" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-S620" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-X700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0128" :status :complete :comment "IEEE1394 untested" :model "GT-X750" :interface "USB" :usbid "0x04b8" "0x0119" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-X770" :interface "USB" :usbid "0x04b8" "0x0130" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-X800" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x012a" :status :complete :comment "film area guide mode not supported
IEEE1394 untested" :model "GT-X820" :interface "USB" :usbid "0x04b8" "0x013a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux/scan/DL1.do" :model "GT-X900" :interface "USB" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested" :model "GT-X970" :interface "USB" :usbid "0x04b8" "0x0135" :status :good :comment "IEEE1394 untested" :model "LP-7900CS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9000CCH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9000CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9000CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9500CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9500CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9500CH2" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9800CCH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-9800CCS" :status :untested :comment "business all-in-one; scanner is a ES-7000H" :model "LP-9800CFH" :status :untested :comment "business all-in-one; scanner is a ES-9000H" :model "LP-A500" :interface "USB Network" :usbid "0x04b8" "0x0815" :status :good :comment "network interface supported
business all-in-one" :model "LP-M5000" :interface "USB" :usbid "0x04b8" "0x0843" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M5500" :interface "USB" :usbid "0x04b8" "0x0817" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M5500F" :interface "USB" :usbid "0x04b8" "0x0817" :status :good :comment "network interface probably supported
business all-in-one
LP-M5500 with the fax option bundled" :model "LP-M5600" :interface "USB" :usbid "0x04b8" "0x0833" :status :good :comment "network interface probably supported
business all-in-one" :model "LP-M6000" :interface "USB" :usbid "0x04b8" "0x0834" :status :good :comment "network interface probably supported
business all-in-one" :model "ME 200" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "ME 300" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "ME OFFICE 510" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "ME Office 600F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "all-in-one" :model "ME OFFICE 650FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "ME Office 700FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "PM-A700" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0814" :status :good :comment "all-in-one" :model "PM-A750" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one" :model "PM-A820" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one" :model "PM-A840" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one" :model "PM-A840S" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "network interface probably supported
all-in-one" :model "PM-A850" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0806" :status :good :comment "all-in-one" :model "PM-A870" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one" :model "PM-A890" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one" :model "PM-A900" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x0810" :status :good :comment "all-in-one" :model "PM-A920" :interface "USB" :usbid "0x04b8" "0x082a" :status :good :comment "all-in-one" :model "PM-A940" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one" :model "PM-A950" :interface "USB" :usbid "0x04b8" "0x081d" :status :good :comment "all-in-one" :model "PM-A970" :interface "USB" :usbid "0x04b8" "0x0828" :status :good :comment "all-in-one" :model "PM-T960" :interface "USB" :usbid "0x04b8" "0x0836" :status :good :comment "all-in-one" :model "PM-T990" :interface "USB" :usbid "0x04b8" "0x0829" :status :good :comment "all-in-one
PM-A970 with network interface" :model "PX-401A" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one" :model "PX-402A" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one" :model "PX-501A" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface probably supported
all-in-one" :model "PX-502A" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one" :model "PX-601F" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported" :model "PX-A550" ; product spec (JP) :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one" :model "PX-A620" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one" :model "PX-A640" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one" :model "PX-A650" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one" :model "PX-A720" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one" :model "PX-A740" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one" :model "PX-FA700" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one" :model "Perfection 600" :interface "SCSI" :status :unsupported :comment "supported by the umax backend
rebadged UMAX Astra 1200S" :model "Perfection 610" ; command spec :interface "USB" :usbid "0x04b8" "0x0103" :status :complete :comment "overseas version of the GT-6600U" :model "Perfection 636S" :interface "SCSI" :status :complete :comment "overseas version of the GT-7000S" :model "Perfection 636U" ; command spec :interface "USB" :usbid "0x04b8" "0x0101" :status :complete :comment "overseas version of the GT-7000U" :model "Perfection 640U" ; command spec :interface "USB" :usbid "0x04b8" "0x010c" :status :complete :comment "overseas version of the GT-6700U" :model "Perfection 660" :interface "USB" :usbid "0x04b8" "0x0114" :status :unsupported :comment "supported by the snapscan backend" :model "Perfection 1200S" ; command spec :interface "SCSI" :status :complete :comment "overseas version of the GT-7600S" :model "Perfection 1200U" ; command spec :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "overseas version of the GT-7600U" :model "Perfection 1200U PHOTO" :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :comment "Perfection 1200U with TPU option bundled
overseas version of the GT-7600UF" :model "Perfection 1240U" ; command spec :interface "USB" :usbid "0x04b8" "0x010b" :status :complete :comment "overseas version of the GT-7700U" :model "Perfection 1250" :interface "USB" :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 1250 PHOTO" :interface "USB" :usbid "0x04b8" "0x010f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 1260" :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 1260 PHOTO" :interface "USB" :usbid "0x04b8" "0x011d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 1270" :interface "USB" :usbid "0x04b8" "0x0120" :status :unsupported :comment "supported by the snapscan backend
overseas version of the GT-7400" :model "Perfection 1600" :interface "SCSI" :status :unsupported :model "Perfection 1640SU" ; command spec :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :complete :comment "overseas version of the GT-8700" :model "Perfection 1640SU PHOTO" :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :good :comment "overseas version of the GT-8700F" :model "Perfection 1650" ; command spec :interface "USB" :usbid "0x04b8" "0x0110" :status :complete :comment "overseas version of the GT-8200U" :model "Perfection 1650 PHOTO" :interface "USB" :usbid "0x04b8" "0x0110" :status :good :comment "overseas version of the GT-8200UF" :model "Perfection 1660 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x011e" :status :complete :comment "overseas version of the GT-8300UF" :model "Perfection 1670" :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :comment "supported by the snapscan backend" :model "Perfection 1670 PHOTO" :interface "USB" :usbid "0x04b8" "0x011f" :status :unsupported :comment "supported by the snapscan backend
overseas version of the GT-8400UF" :model "Perfection 2400 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x011b" :status :complete :comment "overseas version of the GT-9300UF" :model "Perfection 2450 PHOTO" ; command spec :interface "USB IEEE-1394" :usbid "0x04b8" "0x0112" :scsi "EPSON" "GT-9700" "processor" :status :complete :comment "overseas version of the GT-9700F" :model "Perfection 2480 PHOTO" :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 2580 PHOTO" :interface "USB" :usbid "0x04b8" "0x0121" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 3170 PHOTO" :interface "USB" :usbid "0x04b8" "0x0116" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 3200 PHOTO" ; command spec :interface "USB IEEE-1394" :usbid "0x04b8" "0x011c" :scsi "EPSON" "GT-9800" "processor" :status :complete :comment "overseas version of the GT-9800F" :model "Perfection 3490 PHOTO" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 3590 PHOTO" :interface "USB" :usbid "0x04b8" "0x0122" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 4180 PHOTO" :interface "USB" :usbid "0x04b8" "0x0118" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 4490 PHOTO" :interface "USB" :usbid "0x04b8" "0x0119" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection 4870 PHOTO" ; command spec :interface "USB" :usbid "0x04b8" "0x0128" :status :complete :comment "IEEE1394 untested
overseas version of the GT-X700" :model "Perfection 4990 PHOTO" :interface "USB" :usbid "0x04b8" "0x012a" :status :good :comment "film area guide mode not supported
IEEE1394 untested
overseas version of the GT-X800" :model "Perfection 4990 Pro" :interface "USB IEEE1394" :status :untested :comment "seems to be a 4990 PHOTO with additional software" :model "Perfection V10" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection V30" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection V100 Photo" :interface "USB" :usbid "0x04b8" "0x012d" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection V200 Photo" :interface "USB" :usbid "0x04b8" "0x012e" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection V300 Photo" :interface "USB" :usbid "0x04b8" "0x0131" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection V350 Photo" :interface "USB" :usbid "0x04b8" "0x012f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection V500 Photo" :interface "USB" :usbid "0x04b8" "0x0130" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection V600 Photo" :interface "USB" :usbid "0x04b8" "0x013a" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do" :model "Perfection V700 Photo" :interface "USB" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested
overseas version of the GT-X900" :model "Perfection V750 Photo" :interface "USB" :usbid "0x04b8" "0x012c" :status :good :comment "IEEE1394 untested
overseas version of the GT-X900" :model "Stylus CX1500" ; Australia :interface "USB" :usbid "0x04b8" "0x080c" :status :unsupported :comment "supported by the snapscan backend
all-in-one" :model "Stylus CX2800" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "Stylus CX2900" :interface "USB" :usbid "0x04b8" "0x0830" :status :good :comment "all-in-one" :model "Stylus CX3100" :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one
overseas version of the CC-570L" :model "Stylus CX3200" :interface "USB" :usbid "0x04b8" "0x0802" :status :good :comment "all-in-one
overseas version of the CC-570L" :model "Stylus CX3500" ; Australia :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one
overseas version of the PX-A550" :model "Stylus CX3600" ; UK :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one
overseas version of the PX-A550" :model "Stylus CX3650" ; France :interface "USB" :usbid "0x04b8" "0x080e" :status :good :comment "all-in-one" :model "Stylus CX3700" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus CX3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus CX3810" :interface "USB" :status :untested :comment "all-in-one" :model "Stylus CX3900" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one
overseas version of the PX-A620" :model "Stylus CX4100" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus CX4200" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus CX4300" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do" :model "Stylus CX4400" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do" :model "Stylus CX4500" :interface "USB" :usbid "0x04b8" "0x080d" :status :good :comment "all-in-one" :model "Stylus CX4600" :interface "USB" :usbid "0x04b8" "0x080d" :status :good :comment "all-in-one" :model "Stylus CX4700" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus CX4800" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus CX4900" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus CX5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus CX5100" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one
overseas version of the CC-600PX" :model "Stylus CX5200" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :comment "all-in-one
overseas version of the CC-600PX" :model "Stylus CX5300" :interface "USB" :usbid "0x04b8" "0x0808" :status :good :comment "all-in-one" :model "Stylus CX5400" :interface "USB" :usbid "0x04b8" "0x0808" :status :good :comment "all-in-one" :model "Stylus CX5500" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do" :model "Stylus CX5600" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do" :model "Stylus CX5700F" :interface "USB" :usbid "0x04b8" "0x0821" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX5800F" :interface "USB" :usbid "0x04b8" "0x0821" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX5900" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus CX6000" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus CX6300" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :comment "all-in-one
mistakenly thinks its a PX-A650" :model "Stylus CX6400" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :comment "all-in-one
mistakenly thinks its a PX-A650" :model "Stylus CX6500" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :comment "all-in-one" :model "Stylus CX6600" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :comment "all-in-one" :model "Stylus CX6900F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX7000F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus CX7300" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus CX7400" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus CX7700" :interface "USB" :usbid "0x04b8" "0x081f" :status :good :comment "all-in-one" :model "Stylus CX7800" :interface "USB" :usbid "0x04b8" "0x081f" :status :good :comment "all-in-one" :model "Stylus CX8300" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus CX8400" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus CX9300F" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus CX9400Fax" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus DX3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :comment "all-in-one" :model "Stylus DX3850" :interface "USB" :status :good :comment "all-in-one" :model "Stylus DX4000" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :comment "all-in-one
overseas version of the PX-A620" :model "Stylus DX4200" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :comment "all-in-one" :model "Stylus DX4400" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :url "http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do" :model "Stylus DX4800" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
overseas version of the PX-A650" :model "Stylus DX4850" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :comment "all-in-one
DX4800 + card reader" :model "Stylus DX5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :comment "all-in-one" :model "Stylus DX6000" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :comment "all-in-one
overseas version of the PX-A720" :model "Stylus DX7000F" :interface "USB" :usbid "0x04b8" "0x0831" :status :unsupported :comment "may work with the snapscan backend
all-in-one with FAX" :model "Stylus DX7400" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :comment "all-in-one
overseas version of the PX-A640" :model "Stylus DX8400" :interface "USB" :usbid "0x04b8" "0x0839" :status :good :comment "all-in-one
overseas version of the PX-A740" :model "Stylus DX9400F" :interface "USB" :usbid "0x04b8" "0x083a" :status :good :comment "all-in-one
overseas version of the PX-FA700" :model "Stylus Office BX300F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "all-in-one" :model "Stylus Office BX310FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "Stylus Office BX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "Stylus Office BX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus Office TX300F" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "all-in-one" :model "Stylus Office TX510FN Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "Stylus Office TX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "Stylus Office TX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus Photo PX650 Series" :interface "USB" :usbid "0x04b8" "0x0850" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus Photo PX700W" :interface "USB Network" :usbid "0x04b8" "0x0846" :status :good :comment "network interface supported
all-in-one
overseas version of the EP-801A" :model "Stylus Photo PX710W Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus Photo PX800FW" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-901A" :model "Stylus Photo PX810FW Series" :interface "USB" :usbid "0x04b8" "0x0853" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus Photo RX420" :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX425" ; France :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX430" ; Australia :interface "USB" :usbid "0x04b8" "0x080f" :status :good :comment "all-in-one" :model "Stylus Photo RX500" :interface "USB" :usbid "0x04b8" "0x0807" :status :good :comment "all-in-one" :model "Stylus Photo RX510" :interface "USB" :usbid "0x04b8" "0x0807" :status :good :comment "all-in-one" :model "Stylus Photo RX520" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one
overseas version of the PM-A750" :model "Stylus Photo RX530" :interface "USB" :usbid "0x04b8" "0x081a" :status :good :comment "all-in-one
overseas version of the PM-A750" :model "Stylus Photo RX560" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX585" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX580" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX595" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX590" :interface "USB" :usbid "0x04b8" "0x0827" :status :good :comment "all-in-one
overseas version of the PM-A820" :model "Stylus Photo RX600" :interface "USB" :usbid "0x04b8" "0x0806" :status :good :comment "all-in-one
overseas version of the PM-A850" :model "Stylus Photo RX610" :interface "USB" :usbid "0x04b8" "0x083c" :status :good :comment "all-in-one
overseas version of the PM-A840" :model "Stylus Photo RX620" :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one
overseas version of the PM-A870" :model "Stylus Photo RX630" :interface "USB" :usbid "0x04b8" "0x0811" :status :good :comment "all-in-one
overseas version of the PM-A870" :model "Stylus Photo RX640" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one
overseas version of the PM-A890" :model "Stylus Photo RX650" :interface "USB" :usbid "0x04b8" "0x081c" :status :good :comment "all-in-one
overseas version of the PM-A890" :model "Stylus Photo RX680" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX685" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX690" :interface "USB" :usbid "0x04b8" "0x0837" :status :good :comment "all-in-one
overseas version of the PM-A940" :model "Stylus Photo RX700" :interface "USB" :usbid "0x04b8" "0x0810" :status :good :comment "all-in-one
overseas version of the PM-A900" :model "Stylus Photo TX650 Series" :interface "USB" :usbid "0x04b8" "0x0850" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus Photo TX700W" :interface "USB" :usbid "0x04b8" "0x0846" :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-801A" :model "Stylus Photo TX710W Series" :interface "USB" :usbid "0x04b8" "0x0852" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus Photo TX800FW" :interface "USB" :usbid "0x04b8" "0x0844" :status :good :comment "network interface probably supported
all-in-one
overseas version of the EP-901A" :model "Stylus NX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus NX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus NX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus NX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus NX300" :interface "USB" :usbid "0x04b8" "0x0848" :status :good :comment "all-in-one" :model "Stylus NX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-501A" :model "Stylus NX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface probably supported
all-in-one" :model "Stylus NX510 Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "Stylus SX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus SX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus SX125" :interface "USB" :usbid "0x04b8" "0x085c" :status :untested :comment "all-in-one" :model "Stylus SX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus SX205" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus SX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus SX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-501A" :model "Stylus SX405" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "all-in-one" :model "Stylus SX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface probably supported
all-in-one" :model "Stylus SX510W Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "Stylus SX600FW" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "Stylus SX610FW Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" :model "Stylus Scan 2000" :interface "USB" :usbid "0x04b8" "0x0105" :status :untested :comment "apparently mostly the same as the Stylus Scan 2500" :model "Stylus Scan 2500" :interface "USB" :usbid "0x04b8" "0x0106" :status :untested :comment "scanner is apparently a GT-7000" :model "Stylus TX100" :interface "USB" :usbid "0x04b8" "0x0841" :status :good :comment "all-in-one
overseas version of the PX-401A" :model "Stylus TX110 Series" :interface "USB" :usbid "0x04b8" "0x084d" :status :good :comment "all-in-one
overseas version of the PX-402A" :model "Stylus TX200" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX203" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX209" :interface "USB" :usbid "0x04b8" "0x0849" :status :good :comment "all-in-one" :model "Stylus TX210 Series" :interface "USB" :usbid "0x04b8" "0x084f" :status :good :comment "all-in-one" :model "Stylus TX400" :interface "USB" :usbid "0x04b8" "0x084a" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-501A" :model "Stylus TX410 Series" :interface "USB" :usbid "0x04b8" "0x0851" :status :good :comment "network interface probably supported
all-in-one" :model "Stylus TX550W Series" :interface "USB" :usbid "0x04b8" "0x0856" :status :good :comment "all-in-one
overseas version of the PX-502A" :model "WorkForce 310 Series" :interface "USB" :usbid "0x04b8" "0x0854" :status :good :comment "all-in-one" :model "WorkForce 500" :interface "USB" :usbid "0x04b8" "0x084c" :status :good :comment "all-in-one" :model "WorkForce 600" :interface "USB" :usbid "0x04b8" "0x0847" :status :good :comment "network interface probably supported
all-in-one
overseas version of the PX-601F" :model "WorkForce 610 Series" :interface "USB" :usbid "0x04b8" "0x0855" :status :unsupported :comment "supported by the epkowa backend plus non-free interpreter" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "epson" ; name of backend ;:version "0.2.42" ; version of backend :version "unmaintained" ; version of backend :new :no :manpage "sane-epson" ; name of manpage (if it exists) :url "http://www.khk.net/sane" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Epson" ; name a manufacturer :url "http://www.epson.com/" :model "GT-5000" ; name models for above-specified mfg. :interface "SCSI Parport" :status :good :model "Actionscanner II" :comment "US version of GT-5000" :interface "SCSI Parport" :status :good :model "GT-6000" :interface "SCSI Parport" :status :good :model "ES-300C" :comment "US version of GT-6000" :interface "SCSI Parport" :status :good :model "ES-300GS" :interface "SCSI" :status :good :model "GT-5500" :interface "SCSI" :status :good :model "GT-6500" :interface "Parport" :status :good :model "ES-600C" :comment "US version of GT-6500" :interface "Parport" :status :good :model "ES-1200C" :comment "US version of GT-9000" :interface "Parport" :status :good :model "GT-7000" :interface "SCSI" :scsi "EPSON" "SCANNER GT-7000" "processor" :status :good :model "GT-8000" :interface "SCSI" :status :good :model "ES-8500" :interface "SCSI" :status :good :model "Perfection 636S" :comment "US version of GT-7000" :interface "SCSI" :scsi "EPSON" "Perfection1200" "processor" :status :complete :model "Perfection 636" :interface "SCSI" :scsi "EPSON" "Perfection636" "processor" :status :complete :model "Perfection 636U" :interface "USB" :usbid "0x04b8" "0x0101" :status :complete :model "Perfection 610" :interface "USB" :usbid "0x04b8" "0x0103" :status :complete :model "Perfection 640" :interface "USB" :usbid "0x04b8" "0x010c" :status :complete :model "Perfection 1200S" :interface "SCSI" :scsi "EPSON" "Perfection1200" "processor" :status :complete :model "Perfection 1200U" :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :model "Perfection 1200Photo" :comment "with TPU" :interface "USB" :usbid "0x04b8" "0x0104" :status :complete :model "Perfection 1240" :interface "SCSI USB" :usbid "0x04b8" "0x010b" :status :complete :model "Perfection 1640" :interface "SCSI USB" :usbid "0x04b8" "0x010a" :status :complete :model "Perfection 1650" :interface "USB" :usbid "0x04b8" "0x0110" :status :complete :model "Perfection 1660" :interface "USB" :usbid "0x04b8" "0x011e" :status :complete :model "Perfection 2400" :interface "USB" :usbid "0x04b8" "0x011b" :status :complete :model "Perfection 2450" :interface "USB IEEE-1394" :usbid "0x04b8" "0x0112" :scsi "EPSON" "GT-9700" "processor" :status :complete :model "Perfection 3200" :comment "US version of the GT-9800" :interface "USB IEEE-1394" :usbid "0x04b8" "0x011c" :scsi "EPSON" "GT-9800" "processor" :status :complete :model "Perfection 4870" :comment "US version of the GT-X700" :interface "USB" :usbid "0x04b8" "0x0128" :status :complete :model "Perfection 4990" :comment "US version of the GT-X800" :interface "USB" :usbid "0x04b8" "0x012a" :status :complete :model "Expression 636" :comment "US version of GT-9500" :interface "SCSI" :status :complete :model "Expression 800" :interface "SCSI" :status :complete :model "Expression 1600" :interface "SCSI USB IEEE-1394" :usbid "0x04b8" "0x0107" :status :complete :model "Expression 1680" :interface "SCSI USB IEEE-1394" :usbid "0x04b8" "0x010e" :status :complete :model "FilmScan 200" :interface "SCSI" :comment "A better backend for the FilmScan 200 can be found at http://www.vjet.demon.co.uk/scanner/" :status :unsupported :url "http://www.vjet.demon.co.uk/scanner/" :model "CX-3200" :interface "USB" :usbid "0x04b8" "0x0802" :status :good :model "CX-3600" :interface "USB" :usbid "0x04b8" "0x080e" :status :good :model "CX-3650" :interface "USB" :usbid "0x04b8" "0x080e" :status :good :model "CX-4600" :interface "USB" :usbid "0x04b8" "0x080d" :status :good :model "CX-4800" :interface "USB" :usbid "0x04b8" "0x0819" :status :good :model "CX-5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :model "CX-5200" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :model "CX-5400" :interface "USB" :usbid "0x04b8" "0x0801" :status :good :model "CX-5400" :interface "USB" :usbid "0x04b8" "0x0808" :status :good :model "CX-6300" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :model "CX-6400" :interface "USB" :usbid "0x04b8" "0x0805" :status :good :model "CX-6500" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :model "CX-6600" :interface "USB" :usbid "0x04b8" "0x0813" :status :good :model "RX-500" :interface "USB" :usbid "0x04b8" "0x0807" :status :good :model "RX-600" :interface "USB" :usbid "0x04b8" "0x0806" :status :good :model "RX-425" :interface "USB" :usbid "0x04b8" "0x080f" :status :good :model "RX-700" :interface "USB" :usbid "0x04b8" "0x0810" :status :good :model "RX-620" :interface "USB" :usbid "0x04b8" "0x0811" :status :good :model "DX-3850" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :model "CX-3700" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :model "CX-3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :model "CX-4200" :interface "USB" :usbid "0x04b8" "0x0820" :status :good :model "DX-3800" :interface "USB" :usbid "0x04b8" "0x0818" :status :good :model "DX-5000" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :model "DX-5050" :interface "USB" :usbid "0x04b8" "0x082b" :status :good :model "DX-6000" :interface "USB" :usbid "0x04b8" "0x082e" :status :good :model "DX-7400" :interface "USB" :usbid "0x04b8" "0x0838" :status :good :model "DX-4050" :interface "USB" :usbid "0x04b8" "0x082f" :status :good :model "AcuLaser CX11" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :model "AcuLaser CX11NF" :interface "USB" :usbid "0x04b8" "0x0815" :status :good :model "V700" :interface "USB IEEE-1394" :usbid "0x04b8" "0x012c" :status :good :model "V750" :interface "USB IEEE-1394" :usbid "0x04b8" "0x012c" :status :good ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "fujitsu" ; name of backend :url "http://www.thebility.com/fujitsu/" :version "117" ; version of backend :manpage "sane-fujitsu" ; name of manpage (if it exists) :comment "Backend updated for SANE release 1.0.23, see sane-fujitsu manpage" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Fujitsu" ; name a manufacturer :url "http://www.fujitsu.com/" ;================================================== ; DISCONTINUED OLDER MODELS, SMALL :model "M3091DC" :interface "SCSI" :url "http://www.remote.org/frederik/projects/software/sane/" :status :complete :comment "small, old, discontinued" :model "M3092DC" :interface "SCSI" :status :complete :comment "small, old, discontinued" ;================================================== ; DISCONTINUED NEWER MODELS, SMALL :model "fi-4120C" :interface "SCSI USB" :usbid "0x04c5" "0x1041" :status :complete :comment "small, recent, discontinued, usb 1.1" :model "fi-4120C2" :interface "SCSI USB" :usbid "0x04c5" "0x10ae" :status :complete :comment "small, recent, discontinued, usb 2.0" :model "fi-4220C" :interface "SCSI USB" :usbid "0x04c5" "0x1042" :status :complete :comment "small, recent, discontinued, usb 1.1" :model "fi-4220C2" :interface "SCSI USB" :usbid "0x04c5" "0x10af" :status :complete :comment "small, recent, discontinued, usb 2.0" :model "fi-5110C" :interface "USB" :status :complete :usbid "0x04c5" "0x1097" :comment "small, recent, discontinued" :model "fi-5110EOX/2" :interface "USB" :status :complete :usbid "0x04c5" "0x1096" :comment "small, recent, discontinued" :model "fi-5110EOX3" :interface "USB" :status :complete :usbid "0x04c5" "0x10e6" :comment "small, recent, discontinued" :model "fi-5110EOXM" :interface "USB" :usbid "0x04c5" "0x10f2" :status :complete :comment "small, recent, discontinued" :model "fi-5120C" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x10e0" :comment "small, recent, discontinued" :model "fi-5220C" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x10e1" :comment "small, recent, discontinued" :model "fi-5000N" :interface "Ethernet" :status :untested :comment "Not a scanner, rather a scanner to ethernet interface" :model "fi-6000NS" :interface "Ethernet" :status :untested :comment "small, recent, discontinued, integrated touchscreen and keyboard" :model "ScanSnap S500" :interface "USB" :status :complete :usbid "0x04c5" "0x10fe" :comment "small, recent, discontinued" :model "ScanSnap S500M" :interface "USB" :status :complete :usbid "0x04c5" "0x1135" :comment "small, recent, discontinued" :model "ScanSnap S510" :interface "USB" :status :complete :usbid "0x04c5" "0x1155" :comment "small, recent, discontinued" :model "ScanSnap S510M" :interface "USB" :status :complete :usbid "0x04c5" "0x116f" :comment "small, recent, discontinued" :model "fi-6130" :interface "USB" :status :complete :usbid "0x04c5" "0x114f" :comment "small, recent, discontinued" :model "fi-6230" :interface "USB" :status :complete :usbid "0x04c5" "0x1150" :comment "small, recent, discontinued" :model "ScanSnap S1500" :interface "USB" :status :complete :usbid "0x04c5" "0x11a2" :comment "small, discontinued" :model "ScanSnap S1500M" :interface "USB" :status :complete :usbid "0x04c5" "0x11a2" :comment "small, discontinued, same as S1500" ;================================================== ; CURRENT MODELS, SMALL :model "ScanSnap N1800" :interface "Ethernet" :status :untested :comment "small, current, integrated touchscreen and keyboard" :model "ScanSnap fi-6010N" :interface "Ethernet" :status :untested :comment "small, current, integrated touchscreen and keyboard" :model "fi-6110" :interface "USB" :status :complete :usbid "0x04c5" "0x11fc" :comment "small, current" :model "fi-6130Z" :interface "USB" :status :complete :usbid "0x04c5" "0x11f3" :comment "small, current" :model "fi-6230Z" :interface "USB" :status :complete :usbid "0x04c5" "0x11f4" :comment "small, current" :model "ScanSnap iX500" :interface "USB WiFi" :status :good :usbid "0x04c5" "0x132b" :comment "small, current, WiFi not supported. Hardware only scans in color. Backend generates binary and grayscale modes." ;================================================== ; DISCONTINUED OLDER MODELS, MEDIUM :model "M3093E" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3093DE" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3093DG" :interface "SCSI" :status :complete :comment "medium, old, discontinued" :model "M3093EX" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3093GX" :interface "SCSI" :status :complete :comment "medium, old, discontinued" :model "M3096EX" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3096GX" :interface "SCSI" :status :complete :comment "medium, old, discontinued" :model "M3097E+" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3097G+" :interface "SCSI" :status :complete :comment "medium, old, discontinued" :model "M3097DE" :interface "RS232C/Video" :status :unsupported :comment "medium, old, discontinued" :model "M3097DG" :interface "SCSI" :status :complete :comment "medium, old, discontinued" ;================================================== ; DISCONTINUED NEWER MODELS, MEDIUM :model "fi-4340C" :interface "SCSI USB" :usbid "0x04c5" "0x10cf" :status :complete :comment "medium, current" :model "fi-4530C" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x1078" :comment "medium, recent, discontinued" :model "fi-4640S" :interface "SCSI" :status :complete :comment "medium, recent, discontinued" :model "fi-4750C" :interface "SCSI" :status :complete :comment "medium, recent, discontinued" :model "fi-5530C" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x10e2" :comment "medium, recent, discontinued" :model "fi-6140" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x114d" :comment "medium, recent, discontinued" :model "fi-6240" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x114e" :comment "medium, recent, discontinued" ;================================================== ; CURRENT MODELS, MEDIUM :model "fi-5530C2" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x114a" :comment "medium, current" :model "fi-6140Z" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x11f1" :comment "medium, current" :model "fi-6240Z" :interface "SCSI USB" :status :complete :usbid "0x04c5" "0x11f2" :comment "medium, current" ;================================================== ; DISCONTINUED OLDER MODELS, BIG :model "M3099A" :interface "RS232C/Video" :status :unsupported :comment "big, old, discontinued" :model "M3099G" :interface "SCSI" :status :complete :comment "big, old, discontinued" :model "M3099EH" :interface "RS232C/Video" :status :unsupported :comment "big, old, discontinued" :model "M3099GH" :interface "SCSI" :status :complete :comment "big, old, discontinued" :model "M3099EX" :interface "RS232C/Video" :status :unsupported :comment "big, old, discontinued" :model "M3099GX" :interface "SCSI" :status :complete :comment "big, old, discontinued" :model "M4097D" :interface "SCSI" :status :complete :comment "big, old, discontinued" :model "M4099D" :interface "SCSI" :status :complete :comment "big, old, discontinued" ;================================================== ; DISCONTINUED NEWER MODELS, BIG :model "fi-4750L" :interface "SCSI" :status :complete :comment "big, recent, discontinued" :model "fi-4860C" :interface "SCSI" :status :complete :comment "big, recent, discontinued" :model "fi-4860C2" :interface "SCSI" :status :complete :comment "big, recent, discontinued" :model "fi-4990C" :interface "SCSI" :status :complete :comment "big, recent, discontinued" :model "fi-5650C" :interface "SCSI USB" :usbid "0x04c5" "0x10ad" :status :complete :comment "big, recent, discontinued" :model "fi-5750C" :interface "SCSI USB" :usbid "0x04c5" "0x1095" :status :complete :comment "big, recent, discontinued" :model "fi-5900C" :interface "SCSI USB" :usbid "0x04c5" "0x10e7" :status :good :comment "big, recent, discontinued. Independent ultrasonic control and multistream unsupported" :model "fi-6750S" :interface "USB" :status :untested :usbid "0x04c5" "0x1178" :comment "Simplex, USB only version of fi-6770, won't wakeup via software, discontinued" ;================================================== ; CURRENT MODELS, BIG :model "fi-5950" :interface "SCSI USB" :usbid "0x04c5" "0x1213" :status :untested :comment "big, current. Faster version of fi-5900?" :model "fi-6670" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x1176" :comment "big, current, won't wakeup via software" :model "fi-6670A" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x1177" :comment "big, current, VRS CGA board unsupported, won't wakeup via software" :model "fi-6770" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x1174" :comment "big, current, won't wakeup via software" :model "fi-6770A" :interface "SCSI USB" :status :good :usbid "0x04c5" "0x1175" :comment "big, current, VRS CGA board unsupported, won't wakeup via software" :model "fi-6800" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x119d" :comment "big, current. Independent ultrasonic control and multistream unsupported" :model "fi-6800-CGA" :interface "SCSI USB" :status :untested :usbid "0x04c5" "0x119e" :comment "big, current. VRS CGA board unsupported, Independent ultrasonic control and multistream unsupported" :backend "genesys" :version "1.0-63" :manpage "sane-genesys" :comment "Only the USB scanners mentioned below are currently supported." :url "http://www.meier-geinitz.de/sane/genesys-backend/" :devicetype :scanner ; ----------------------------------------------------------------------------- :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticBook 3600" :interface "USB" :usbid "0x07b3" "0x0900" :status :basic :comment "Has a Primax USB ID" ; ----------------------------------------------------------------------------- :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.com/" :url "http://www.medion.de/" :model "MD5345" :interface "USB" :usbid "0x0461" "0x0377" :status :good :comment "Has a Primax USB ID" :model "MD6228" :interface "USB" :usbid "0x0461" "0x0377" :status :good :comment "Has a Primax USB ID. Same as MD5345" :model "MD6471" :interface "USB" :usbid "0x0461" "0x0377" :status :complete :comment "Has a Primax USB ID. Same as MD5345" ; ----------------------------------------------------------------------------- :mfg "Hewlett-Packard" :url "http://www.hp.com/" :model "ScanJet 2300C" :interface "USB" :usbid "0x03f0" "0x0901" :status :complete :comment "600x1200 dpi max" :model "ScanJet 2400C" :interface "USB" :usbid "0x03f0" "0x0a01" :status :complete :comment "1200x1200 dpi max" :model "ScanJet G2410" :interface "USB" :usbid "0x03f0" "0x0a01" :status :basic :comment "clone of the HP 2400C" :model "ScanJet 3670C" :interface "USB" :usbid "0x03f0" "0x1405" :status :complete :comment "1200x1200 dpi max, complete transparency adaptor support" :model "ScanJet 3690C" :interface "USB" :usbid "0x03f0" "0x1405" :status :complete :comment "1200x1200 dpi max, same as HP 3670C" :model "ScanJet 4850C" :interface "USB" :usbid "0x03f0" "0x1b05" :status :untested :comment "resolution from 100 to 2400 supported, UTA not supported yet" :model "ScanJet G4010" :interface "USB" :usbid "0x03f0" "0x4505" :status :good :comment "resolution from 100 to 2400 supported, UTA not supported yet" :model "ScanJet G4050" :interface "USB" :usbid "0x03f0" "0x4605" :status :good :comment "resolution from 100 to 2400 supported, UTA not supported yet" :model "ScanJet N6310" :interface "USB" :usbid "0x03f0" "0x4705" :status :untested :comment "Not supported yet" ; ----------------------------------------------------------------------------- :mfg "Canon" :url "http://www.canon.com/" :model "CanoScan LiDE 35" :interface "USB" :usbid "0x04a9" "0x2213" :status :good :comment "Same ids as LiDE 50." :model "CanoScan LiDE 40" :interface "USB" :usbid "0x04a9" "0x2213" :status :good :comment "Same ids as LiDE 50." :model "CanoScan LiDE 50" :interface "USB" :usbid "0x04a9" "0x2213" :status :good :model "CanoScan LiDE 60" :interface "USB" :usbid "0x04a9" "0x221c" :status :good :model "CanoScan LiDE 100" :interface "USB" :usbid "0x04a9" "0x1904" :status :complete :comment "GL847 based, resolution from 75 to 2400 dpi" :model "CanoScan LiDE 110" :interface "USB" :usbid "0x04a9" "0x1909" :status :complete :comment "GL124 based, resolution from 75 to 2400 dpi" :model "CanoScan LiDE 200" :interface "USB" :usbid "0x04a9" "0x1905" :status :complete :comment "GL847 based, resolution from 75 to 4800 dpi" :model "CanoScan LiDE 210" :interface "USB" :usbid "0x04a9" "0x190a" :status :complete :comment "GL124 based, resolution from 75 to 2400 dpi" :model "CanoScan 4400f" :interface "USB" :usbid "0x04a9" "0x2228" :status :unsupported :comment "GL843 based, to be added to the genesys backend" :model "CanoScan 5600F" :interface "USB" :usbid "0x04a9" "0x1906" :status :unsupported :comment "GL847 based, to be added to the genesys backend" :model "CanoScan 700F" :interface "USB" :usbid "0x04a9" "0x1907" :status :good :comment "GL847 based, resolution from 75 to 4800 dpi" :model "Canon Image Formula 101" :interface "USB" :usbid "0x1083" "0x162e" :status :unsupported :comment "GL846 based, work in progress" ; ----------------------------------------------------------------------------- :mfg "Visioneer" :url "http://www.visioneer.com/" :model "Strobe XP 100,r3" :interface "USB" :usbid "0x04a7" "0x049b" :status :good :comment "All resolution and mode supported, calibration is available" :model "Strobe XP 200" :interface "USB" :usbid "0x04a7" "0x0426" :status :good :comment "All resolution and mode supported, calibration is available" :model "Strobe XP 300" :interface "USB" :usbid "0x04a7" "0x0474" :status :good :comment "All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally." :model "Roadwarrior" :interface "USB" :usbid "0x04a7" "0x0494" :status :basic :comment "All resolution and mode supported, calibration is available" :model "Visioneer OneTouch 7100" :interface "USB" :usbid "0x04a7" "0x0229" :status :complete :comment "Same as MD5345" ; ----------------------------------------------------------------------------- :mfg "Pentax" :url "http://www.pentaxtech.com/" :url "http://mobilesolutions.brother-usa.com/" :model "DSmobile 600" :interface "USB" :usbid "0x0a17" "0x3210" :status :good :comment "All resolution and mode supported, calibration is available" :model "DSmobile 600" :interface "USB" :usbid "0x04f9" "0x2038" :status :good :comment "All resolution and mode supported, calibration is available" ; ----------------------------------------------------------------------------- :mfg "DCT" :url "http://www.docucap.com/" :comment "Successor of Syscan in the USA" :model "DocketPort 487" :interface "USB" :usbid "0x1dcc" "0x4810" :status :basic :comment "All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally." ; ----------------------------------------------------------------------------- :mfg "Syscan" :model "DocketPort 485" :interface "USB" :usbid "0x0a82" "0x4810" :status :basic :comment "All resolution and mode supported, front- and backside side-by-side, with backside mirrored horizontally." :model "DocketPort 465" :interface "USB" :usbid "0x0a82" "0x4802" :status :untested :comment "All resolution and mode should be supported, but uncorrected scans" :model "DocketPort 665" :interface "USB" :usbid "0x0a82" "0x4803" :status :basic :comment "All resolution and mode supported, calibration is available" :model "DocketPort 685/ Ambir DS685" :interface "USB" :usbid "0x0a82" "0x480c" :status :good :comment "All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally." :mfg "Xerox" :url "http://www.xerox.com/" :model "Travel Scanner 100" :interface "USB" :usbid "0x04a7" "0x04ac" :status :good :comment "All resolution and mode supported, calibration is available" :model "2400 Onetouch" :interface "USB" :usbid "0x0461" "0x038b" :status :complete :comment "GL646 based, resolution from 75 to 2400 dpi" ; ----------------------------------------------------------------------------- :mfg "Panasonic" :model "KV-SS080" :interface "USB" :usbid "0x04da" "0x100f" :status :complete :comment "All resolution and mode supported, calibration is available. Support sponsored by cncsolutions (http://www.cncsolutions.com.br)" ;gphoto2 backend .desc file by Peter S. Fales :backend "gphoto2" ; name of backend :version "0.0" ; version of backend :manpage "sane-gphoto2" ; name of manpage (if it exists) :url "mailto:peter@fales-lorenz.net" ; backend's web page :devicetype :api ; start of a list of devices.... :desc "Multiple cameras supported by the gphoto2 libraries" :url "http://www.gphoto.org" ;:interface "USB, serial port" :comment "The long-term plan is to support all the cameras supported by the gphoto2 libraries (currently over 140 models). However, at this stage, only a handful of cameras are definitely known to work with SANE. Other cameras will probably work if the native file format is EXIF or JPEG. Testers welcome!" :backend "gt68xx" :version "1.0-84" :manpage "sane-gt68xx" :url "http://www.meier-geinitz.de/sane/gt68xx-backend/" :comment "Only the USB scanners mentioned below are supported. For other Mustek BearPaws, look at the Plustek and the MA-1509 backend." :devicetype :scanner ; ----------------------------------------------------------------------------- :mfg "Artec/Ultima" :url "http://www.artecusa.com/" :model "Ultima 2000" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Works, only product id 0x4002 is supported" :model "Ultima 2000 e+" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Works, however 12 bit mode doesn't seem to be supported" ; ----------------------------------------------------------------------------- :mfg "Boeder" :model "Sm@rtScan Slim Edition" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Artec Ultima 2000" ; ----------------------------------------------------------------------------- :mfg "Fujitsu" :url "http://www.fujitsu.com/" :model "1200CUS" :interface "USB" :usbid "0x05d8" "0x4002" :status :basic :comment "Works, but is slow. Probably a Mustek BearPaw 2400 CU clone." ; ----------------------------------------------------------------------------- :mfg "Genius" :url "http://www.genius-kye.com/" :model "ColorPage Slim 1200" ;:url "/unsupported/genius-colorpage-slim-1200.html" :interface "USB" :usbid "0x0458" "0x201e" :status :untested :comment "Untested but should work." :model "Colorpage SF600" :interface "USB" :usbid "0x0458" "0x2021" :status :basic :model "Colorpage Vivid3x" :interface "USB" :usbid "0x0458" "0x2011" :status :good :model "Colorpage Vivid3 V2" :interface "USB" :usbid "0x0458" "0x2011" :status :good :comment "Same as Colorpage Vivid3x" :model "Colorpage Vivid3xe" :interface "USB" :usbid "0x0458" "0x2017" :status :good :model "Colorpage Vivid4" :usbid "0x0458" "0x2014" :interface "USB" :status :good :model "Colorpage Vivid4x" :usbid "0x0458" "0x201b" :interface "USB" :status :good :model "Colorpage Vivid4xe" :usbid "0x0458" "0x201a" :interface "USB" :status :good :model "Colorpage Vivid 1200 X" :interface "USB" :usbid "0x0458" "0x201d" :status :good :model "Colorpage Vivid 1200 XE" :interface "USB" :usbid "0x0458" "0x201f" :status :good ; ----------------------------------------------------------------------------- :mfg "Googlegear" :model "2000" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Same as Artec Ultima 2000." ; ----------------------------------------------------------------------------- :mfg "Lexmark" :url "http://www.lexmark.com/" :model "X70" :interface "USB" :usbid "0x043d" "0x002d" :status :good :comment "Works, some resolutions fail at 16 bit" :model "X73" :interface "USB" :usbid "0x043d" "0x002d" :status :good :comment "Works, some resolutions fail at 16 bit, same as X70" ; ----------------------------------------------------------------------------- :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.com" :comment "Sold by Aldi and Tchibo." :model "MD 4394" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Product id 0x4002. If you have 0x4003, use artec_eplus48u backend." :model "MD/LT 9375" :interface "USB" :usbid "0x05d8" "0x4002" :status :untested :comment "Untested, but is reported to have the same ids as the Artec Ultima 2000. Please test." :model "MD/LT 9385" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Artec Ultima 2000" :model "LT 9452" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Mustek ScanExpress 1200 UB Plus" :model "MD 9458" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Artec Ultima 2000 (e+?)" ; ----------------------------------------------------------------------------- :mfg "Mustek" :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "BearPaw 1200 CS" :interface "USB" :usbid "0x055f" "0x021e" :status :good :model "BearPaw 1200 CU" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :model "BearPaw 1200 CU Plus" :interface "USB" :usbid "0x055f" "0x021b" :status :good :model "BearPaw 1200 CU Plus" :interface "USB" :usbid "0x055f" "0x021c" :status :good :model "BearPaw 1200 TA" :interface "USB" :usbid "0x055f" "0x021e" :status :good :comment "Transparency adapter supported" :model "BearPaw 1248 CU" :interface "USB" :usbid "0x055f" "0x021c" :status :good :comment "Seems to use the same ids as BearPaw 1200 CU Plus." :model "BearPaw 2400 CS" :interface "USB" :usbid "0x055f" "0x0218" :status :untested :comment "Probably works, reports are welcome" :model "BearPaw 2400 CS Plus" :interface "USB" :usbid "0x055f" "0x0219" :status :good :comment "Works, problems with 12/16 bit modes?" :model "BearPaw 2400 CU" :interface "USB" :usbid "0x05d8" "0x4002" :status :basic :comment "Works, but is slow" :model "BearPaw 2400 CU Plus" :interface "USB" :usbid "0x055f" "0x021d" :status :good :model "BearPaw 2400 TA" :interface "USB" :usbid "0x055f" "0x0218" :status :good :comment "Transparency adapter supported" :model "BearPaw 2400 TA Plus" :interface "USB" :usbid "0x055f" "0x0219" :status :good :comment "Transparency adapter supported" :model "BearPaw 2448 CS Plus" :interface "USB" :usbid "0x055f" "0x021a" :status :basic :comment "Slow. Same as 2448 TA Plus, but without TA." :model "BearPaw 2448 TA Plus" :interface "USB" :usbid "0x055f" "0x021a" :status :basic :comment "Slow. Transparency adapter supported. Slow. Brightness depends on resolution?" :model "Plug-n-Scan 2400 MT" :interface "USB" :usbid "0x055f" "0x0219" :status :good :comment "Works but is slow in high resolutions. Same as BearPaw 2400 TA Plus." :model "Plug-n-Scan 2400 M" :interface "USB" :usbid "0x055f" "0x0219" :status :good :comment "Works but is slow in high resolutions. Same as BearPaw 2400 CS Plus." :model "ScanExpress 1200 UB Plus" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :model "ScanExpress 1248 UB" :interface "USB" :usbid "0x055f" "0x021f" :status :complete :model "ScanExpress 2400 USB" :interface "USB" :usbid "0x05d8" "0x4002" :status :minimal :comment "Should be detected but may need some more work in the code. Testers welcome. Please contact me if you own this scanner." :model "ScanExpress A3 USB" :interface "USB" :usbid "0x055f" "0x0210" :status :basic :comment "Still some vertical stripes." :model "ScanMagic 1200 UB Plus" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Same as ScanExpress 1200 UB Plus" ; ----------------------------------------------------------------------------- :mfg "NeatReceipts" :model "Scanalizer Professional 2.5" :interface "USB" :usbid "0x07b3" "0x0412" :status :untested :comment "Similar to Plustek OpticSlim M12. Please tell us if this scanner works." :model "Mobile Scanner" :interface "USB" :usbid "0x07b3" "0x0462" :status :basic :comment "Similar to Plustek OpticSlim M12." ; ----------------------------------------------------------------------------- :mfg "Nortek" :model "MyScan 1200" :interface "USB" :usbid "0x07b3" "0x040b" :status :untested :comment "Untested. Please test. Similar to Plustek OpticPro S12?" ; ----------------------------------------------------------------------------- :mfg "Packard Bell" :model "Diamond 1200" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Mustek BearPaw 1200 (Plus)" :model "Diamond 1200 Plus" :interface "USB" :usbid "0x055f" "0x021c" :status :good :comment "Similar to Mustek BearPaw 1200 Plus" :model "Diamond 1200 Plus" :interface "USB" :usbid "0x055f" "0x021b" :status :good :comment "Similar to Mustek BearPaw 1200 Plus" :model "Diamond 2450" :interface "USB" :usbid "0x055f" "0x0219" :status :good ; ----------------------------------------------------------------------------- :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticPro 1248U" :interface "USB" :usbid "0x07b3" "0x0400" :status :good :model "OpticPro 1248U" :interface "USB" :usbid "0x07b3" "0x0401" :status :good :model "OpticPro U16B" :interface "USB" :usbid "0x07b3" "0x0402" :status :good :model "OpticPro U16B+" :interface "USB" :usbid "0x07b3" "0x0403" :status :good :model "OpticPro UT16B" :interface "USB" :usbid "0x07b3" "0x0403" :status :untested :comment "Probably works. Transparency adapter not supported yet. Please contact me if you own such a device. " :model "OpticPro S12" :interface "USB" :usbid "0x07b3" "0x040b" :status :good :comment "Product ID 0x040b only." :model "OpticPro S24" :interface "USB" :usbid "0x07b3" "0x040e" :status :good :comment "Product ID 0x040e only. Is reported to work." :model "OpticPro ST12" :interface "USB" :usbid "0x07b3" "0x040b" :status :untested :comment "Product ID 0x040b only. Needs testing. Transparency adapter completely untested. Please contact me if you own such a scanner." :model "OpticSlim 1200" :interface "USB" :usbid "0x07b3" "0x0413" :status :good :model "OpticSlim 2400" :interface "USB" :usbid "0x07b3" "0x0422" :status :good :comment "Works up to 1200 dpi." :model "OpticSlim 2400 plus" :interface "USB" :usbid "0x07b3" "0x0454" :status :good :comment "Same as OpticSlim 2400." :model "Iriscan Express 2" :interface "USB" :usbid "0x07b3" "0x045f" :status :complete :comment "Works up to 1200 dpi. Calibration with external calibration sheet supported" ; ----------------------------------------------------------------------------- :model "OpticSlim M12" :interface "USB" :usbid "0x07b3" "0x0412" :status :complete :comment "Works up to 1200 dpi. Calibration with external calibration sheet supported" ; ----------------------------------------------------------------------------- :mfg "RevScan" ;:url "" :model "19200i" :interface "USB" :usbid "0x07b3" "0x0400" :status :good :comment "Similar to Plustek OpticPro 1248U" ; ----------------------------------------------------------------------------- :mfg "Trust" :url "http://www.trust-site.com" :model "240TH Easy Webscan Gold" :interface "USB" :usbid "0x055f" "0x0218" :status :good :comment "Same as Mustek Bearpaw 2400 TA plus." :model "Compact Scan USB 19200" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Works, if you have vendor id 0x055f and product id 0x0006, use the mustek_usb backend instead, similar to Mustek ScanExpress 1200 UB (Plus)" :model "Direct WebScan 19200" :interface "USB" :usbid "0x055f" "0x021c" :status :good :comment "Same as Mustek BearPaw 1200 CU Plus (0x021c)." :model "Flat Scan USB 19200" :interface "USB" :usbid "0x05d8" "0x4002" :status :good :comment "Similar to Artec Ultima 2000" ; ----------------------------------------------------------------------------- :mfg "Visioneer" :url "http://www.visioneer.com/" :model "OneTouch 7300" :interface "USB" :usbid "0x04a7" "0x0444" :status :good :comment "Works upto 1200 dpi and 12 bits/color." ; ----------------------------------------------------------------------------- ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hp3500" ; name of backend :version "1.1" ; version of backend :manpage "sane-hp3500" ; name of manpage (if it exists) :url "http://projects.troy.rollo.name/rt-scanners/" ; backend's web page :comment "HP3500 series scanners." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com" :model "ScanJet 3500C" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port" or "Propretiary". :usbid "0x03f0" "0x2205" :status :good :model "ScanJet 3530C" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: :usbid "0x03f0" "0x2005" :status :good :model "ScanJet 3570C" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: :usbid "0x03f0" "0x2005" :status :good ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "hp3900" :version "0.12" :manpage "sane-hp3900" :url "http://sourceforge.net/projects/hp3900-series/" :comment "Still Beta" :devicetype :scanner ; ----------------------------------------------------- :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "ScanJet 3800" :interface "USB" :status :basic :usbid "0x03f0" "0x2605" :comment "Works with resolutions equal and less than 600dpi" :model "ScanJet 3970c" :interface "USB" :status :good :usbid "0x03f0" "0x2305" :model "ScanJet 4070 Photosmart" :interface "USB" :status :good :usbid "0x03f0" "0x2405" :model "ScanJet 4370" :interface "USB" :usbid "0x03f0" "0x4105" :status :basic :comment "Works with resolutions lower than 1200dpi" :model "ScanJet G2710" :interface "USB" :usbid "0x03f0" "0x2805" :status :basic :comment "Similar to hp scanjet 3800" :model "ScanJet G3010" :interface "USB" :usbid "0x03f0" "0x4205" :status :basic :comment "Similar to hp scanjet 4370" :model "ScanJet G3110" :interface "USB" :usbid "0x03f0" "0x4305" :status :basic :comment "Similar to hp scanjet 4370" ; ----------------------------------------------------- :mfg "UMAX" :url "http://www.umax.com" :model "Astra 4900" :interface "USB" :usbid "0x06dc" "0x0020" :status :minimal :comment "developing yet" ; ----------------------------------------------------- :mfg "BenQ" :url "http://www.benq.com/" :model "5550" :interface "USB" :usbid "0x04a5" "0x2211" :status :minimal :comment "developing yet" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "hp4200" ; name of backend :version "1.0-2" ; version of backend :manpage "sane-hp4200" ; name of manpage (if it exists) :url "http://hp4200-backend.sourceforge.net" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "ScanJet 4200C" ; name models for above-specified mfg. :interface "USB" :usbid "0x03f0" "0x0105" :status :basic :comment "8bpp color, 75/150/300/600 dpi only" :model "ScanJet 4200Cxi" ; name models for above-specified mfg. :interface "USB" :usbid "0x03f0" "0x0105" :status :basic :comment "8bpp color, 75/150/300/600 dpi only" :model "ScanJet 4200Cse" ; name models for above-specified mfg. :interface "USB" :usbid "0x03f0" "0x0105" :status :basic :comment "8bpp color, 75/150/300/600 dpi only" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; Copied from hp3300 testtools - Martijn van Oosterhout 22/02/2003 ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hp5400" ; name of backend :version "1.0-2" ; version of backend :manpage "sane-hp5400" ; name of manpage (if it exists) :url "http://sourceforge.net/projects/hp5400backend" ; backend's web page :comment "HP5400 and HP5470 scanners. Prototype backend available" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com" :model "ScanJet 5400c" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port" or "Propretiary". :usbid "0x03f0" "0x1005"" :status :basic :model "ScanJet 5470c" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: :usbid "0x03f0" "0x1105" :status :basic :model "ScanJet 5490c" ; name models for above-specified mfg. :interface "USB" ; interface type of the device: :status :basic ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "hp5590" :version "1.0.5" :manpage "sane-hp5590" :devicetype :scanner :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "ScanJet 4500C" :interface "USB" :usbid "0x03f0" "0x1205" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives" :model "ScanJet 4570C" :interface "USB" :usbid "0x03f0" "0x1305" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives" :model "ScanJet 5500C" :interface "USB" :usbid "0x03f0" "0x1305" :status :untested :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives" :model "ScanJet 5550C" :interface "USB" :usbid "0x03f0" "0x1205" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives" :model "ScanJet 5590" :interface "USB" :usbid "0x03f0" "0x1705" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives" :model "ScanJet 7650" :interface "USB" :usbid "0x03f0" "0x1805" :status :complete :comment "Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hp" ; name of backend :version "1.06" ; version of backend :manpage "sane-hp" ; name of manpage (if it exists) :url "http://www.kirchgessner.net/" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "ScanJet Plus" ; name models for above-specified mfg. :interface "Propietary" :status :complete :comment "Driver for HP parallel interface card required" :model "ScanJet IIc" :interface "SCSI" :status :complete :scsi "HP" "C1750A" "processor" :model "ScanJet IIp" :interface "SCSI" :status :complete :scsi "HP" "C1790A" "processor" :model "ScanJet IIcx" :interface "SCSI" :status :complete :scsi "HP" "C2500A" "processor" :model "ScanJet 3c" :interface "SCSI" :status :complete :model "ScanJet 3p" :interface "SCSI" :status :complete :model "ScanJet 4c" :interface "SCSI" :status :complete :scsi "HP" "C2520A" "processor" :model "ScanJet 4p" :interface "SCSI" :status :complete :scsi "HP" "C1130A" "processor" :model "ScanJet 4100C" :interface "USB" :usbid "0x03f0" "0x0101" :status :complete :model "ScanJet 5p" :interface "SCSI" :status :complete :scsi "HP" "C5110A" "processor" :model "ScanJet 5100C" :interface "Parport" :status :complete :comment "Requires ppscsi driver and epst module" :model "ScanJet 5200C" :interface "Parport USB" :usbid "0x03f0" "0x0401" :status :complete :comment "Parallel interface requires ppscsi driver and epst module" :model "ScanJet 6100C" :interface "SCSI" :status :complete :model "ScanJet 6200C" :interface "SCSI USB" :scsi "HP" "C6270A" "processor" :usbid "0x03f0" "0x0201" :status :complete :model "ScanJet 6250C" :interface "SCSI USB" :usbid "0x03f0" "0x0201" :status :complete :model "ScanJet 6300C" :interface "SCSI USB" :scsi "HP" "C7670A" "processor" :usbid "0x03f0" "0x0601" :status :complete :model "ScanJet 6350C" :interface "SCSI USB" :usbid "0x03f0" "0x0601" :status :complete :model "ScanJet 6390C" :interface "SCSI USB" :usbid "0x03f0" "0x0601" :status :complete :model "PhotoSmart PhotoScanner" :interface "SCSI" :status :complete ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "hpljm1005" :version "0" :manpage "sane-hpljm1005" :devicetype :scanner :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "LaserJet M1005 MFP" :interface "USB" :usbid "0x03f0" "0x3b17" :status :good :comment "grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI" :model "LaserJet M1120 MFP" :interface "USB" :usbid "0x03f0" "0x5617" :status :good :comment "grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI" :model "LaserJet M1120n MFP" :interface "USB" :usbid "0x03f0" "0x5717" :status :good :comment "grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hpsj5s" ; name of backend :version "0.03" ; version of backend ;:status :alpha ; :alpha, :beta, :stable, :new :manpage "sane-hpsj5s" ; name of manpage (if it exists) :url "http://hpsj5s.sourceforge.net/" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "ScanJet 5s" ; name models for above-specified mfg. :interface "Parport (EPP)" :comment "Requires libieee1284 library. Only gray mode." :status :minimal ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "hs2p" ; name of backend :url "http://www.acjlaw.net:8080/~jeremy/Ricoh/" :version "1.00" ; version of backend ; :manpage "sane-hs2p" ; name of manpage (if it exists) :comment "This backend has been tested with the IS450DE (Duplex/Endorser). All major functions necessary for scanning are supported. This backend should work with all Ricoh scanners in the IS450 family as well as the IS420 series, but the IS420 has not yet been tested. Features provided by the optional Image Processing Unit (IPU) are not yet integrated into the backend, as my scanner lacks the IPU." :devicetype :scanner :mfg "Ricoh" ; name a manufacturer :url "http://www.ricoh.com/" :model "IS450" ; name models for above-specified mfg. :interface "SCSI" :status :complete :comment "All major scanning-related features are supported (except for IPU). Certain non-scanning features, such as those related to scanner maintenance, are not supported. Such features would be better implemented in a separate stand-alone tool. For instance, if you replace the ADF Unit, you must recalibrate the scanner optics using a Ricoh Test Sheet and reset the E^2PROM registers. Reports are welcome." :model "IS-410" :interface "SCSI" :status :untested :comment "Untested, please report!" :model "IS-420" :interface "SCSI" :status :untested :comment "Untested, please report!" :model "IS-430" :interface "SCSI" :status :untested :comment "Untested, please report!" ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "ibm" ; name of backend :url "http://www.meier-geinitz.de/sane/ibm-backend/" :version "1.0-4" ; version of backend ; :manpage "sane-ibm" ; name of manpage (if it exists) :comment "This backend has had only limited testing. It needs more work especially for the Ricoh scanners. Patches are welcome." :devicetype :scanner :mfg "IBM" ; name a manufacturer :url "http://www.ibm.com/" :model "2456" ; name models for above-specified mfg. :interface "SCSI" :status :basic :comment "Was reported to work long time ago. Reports are welcome." :mfg "Ricoh" ; name a manufacturer :model "IS-410" :interface "SCSI" :status :untested :comment "Untested, please report!" :model "IS-420" :interface "SCSI" :status :basic :comment "Works at least in flatbed mode." :model "IS-430" :interface "SCSI" :status :untested :comment "Untested, please report!" :backend "kodakaio" :url "http://sourceforge.net/projects/cupsdriverkodak/" :version "2.4.6" :manpage "sane-kodakaio" :comment "Backend for Kodak AiO ESP and Hero printers. Also possibly Advent AWL10" :devicetype :scanner :new :no :mfg "Kodak" :url "http://www.kodak.com/" ;====================================== ; ESP series :model "ESP 2150" :interface "USB" :usbid "0x040a" "0x4059" :status :untested :comment "Please test!" :model "ESP 2170" :interface "USB" :usbid "0x040a" "0x4066" :status :untested :comment "Please test!" :model "ESP 3200" :interface "USB" :usbid "0x040a" "0x4043" :status :untested :comment "Please test!" :model "ESP 3300" :interface "USB" :usbid "0x040a" "0x4031" :status :untested :comment "Please test!" :model "ESP 4100" :interface "USB" :usbid "0x040a" "0x4053" :status :untested :comment "Please test!" :model "ESP 5000" :interface "USB" :usbid "0x040a" "0x4028" :status :untested :comment "Please test!" :model "ESP 5100" :interface "USB" :usbid "0x040a" "0x4025" :status :untested :comment "Please test!" :model "ESP 5200" :interface "USB Ethernet" :usbid "0x040a" "0x4041" :status :basic :comment "USB good, Network good" :model "ESP 5300" :interface "USB" :usbid "0x040a" "0x4026" :status :untested :comment "Please test!" :model "ESP 5500" :interface "USB" :usbid "0x040a" "0x4027" :status :untested :comment "Please test!" :model "ESP 6100" :interface "USB" :usbid "0x040a" "0x4054" :status :untested :comment "Please test!" :model "ESP 7200" :interface "USB" :usbid "0x040a" "0x4056" :status :untested :comment "Please test!" :model "ESP 9200" :interface "USB" :usbid "0x040a" "0x4065" :status :untested :comment "Please test!" :model "ESP 5" :interface "USB" :usbid "0x040a" "0x4032" :status :untested :comment "Please test!" :model "ESP 7" :interface "USB" :usbid "0x040a" "0x403e" :status :untested :comment "Please test!" :model "ESP 9" :interface "USB" :usbid "0x040a" "0x403f" :status :untested :comment "Please test!" :model "ESP C110" :interface "USB" :usbid "0x040a" "0x4057" :status :untested :comment "Please test!" :model "ESP C115" :interface "USB" :usbid "0x040a" "0x4058" :status :untested :comment "Please test!" :model "ESP C310" :interface "USB" :usbid "0x040a" "0x405d" :status :untested :comment "Please test!" :model "ESP C315" :interface "USB" :usbid "0x040a" "0x405e" :status :untested :comment "Please test!" ;====================================== ; Hero series :model "Hero 3.1" :interface "USB" :usbid "0x040a" "0x406d" :status :untested :comment "Please test!" :model "Hero 5.1" :interface "USB" :usbid "0x040a" "0x4064" :status :untested :comment "Please test!" :model "Hero Office 6.1" :interface "USB" :usbid "0x040a" "0x4062" :status :untested :comment "Please test!" :model "Hero 7.1" :interface "USB" :usbid "0x040a" "0x4063" :status :untested :comment "Please test!" :model "Hero 9.1" :interface "USB Ethernet" :usbid "0x040a" "0x4067" :status :basic :comment "USB good, Network good" ;=================================== :mfg "Advent" :url "http://www.adventcomputers.co.uk" :model "AW10" :interface "USB" :usbid "0x040a" "0x4060" :status :untested :comment "Please test!" :backend "kodak" :url "http://www.thebility.com/kodak/" :version "7" :manpage "sane-kodak" :comment "New backend for SANE release 1.0.21, see sane-kodak manpage" :devicetype :scanner :mfg "Kodak" :url "http://www.kodak.com/" ;====================================== ; workgroup machines, old :model "Scanner 1500" :interface "SCSI" :status :untested :comment "Please test!" ;====================================== ; departmental machines, old :model "Scanner 2500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 3500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 3510" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 3520" :interface "SCSI" :status :untested :comment "Please test!" :model "Color Scanner 3590C" :interface "SCSI" :status :untested :comment "Please test!" :model "Color Scanner 4500" :interface "SCSI" :status :untested :comment "Please test!" ;====================================== ; departmental machines, recent :model "i150 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i160 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i250 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i260 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i280 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" ;====================================== ; production machines, old :model "Scanner 900" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 923" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 5500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 7500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 7520" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 9500" :interface "SCSI" :status :untested :comment "Please test!" :model "Scanner 9520" :interface "SCSI" :status :untested :comment "Please test!" ;====================================== ; production machines, recent :model "i610 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i620 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i640 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i660 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i730 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i750 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i780 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i810 Scanner" :interface "SCSI" :status :untested :comment "Please test!" :model "i820 Scanner" :interface "SCSI" :status :untested :comment "Please test!" :model "i830 Scanner" :interface "SCSI" :status :untested :comment "Please test!" :model "i840 Scanner" :interface "SCSI" :status :untested :comment "Please test!" :model "i1840 Scanner" :interface "IEEE-1394" :status :untested :comment "Please test!" :model "i1860 Scanner" :interface "IEEE-1394" :status :basic :comment "Uncompressed B&W, Gray and Color, some automatic features supported" :model "s1740" :interface "SCSI" :status :untested :comment "Please test!" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "kvs1025" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-kvs1025" ; name of manpage (if it exists) :comment "New backend for SANE release 1.0.21, see sane-kvs1025 manpage" :devicetype :scanner ; start of a list of devices.... :mfg "Panasonic" ; name a manufacturer :url "http://www.panasonic.com/" :model "KV-S1020C" :interface "USB" :usbid "0x04da" "0x1007" :status :good :model "KV-S1025C" :interface "USB" :usbid "0x04da" "0x1006" :status :good :model "KV-S1045C" :interface "USB" :usbid "0x04da" "0x1010" :status :good ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "kvs20xx" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-kvs20xx" ; name of manpage (if it exists) :comment "New backend for SANE release 1.0.22, see sane-kvs20xx manpage" :devicetype :scanner ; start of a list of devices.... :mfg "Panasonic" ; name a manufacturer :url "http://www.panasonic.com/" :model "KV-S2025C" :interface "SCSI" :status :untested :model "KV-S2026C" :interface "USB SCSI" :usbid "0x04da" "0x1000" :status :untested :model "KV-S2028C" :interface "USB" :usbid "0x04da" "0x100a" :status :untested :model "KV-S2045C" :interface "SCSI" :status :untested :model "KV-S2046C" :interface "USB SCSI" :usbid "0x04da" "0x1001" :status :untested :model "KV-S2048C" :interface "USB" :usbid "0x04da" "0x1009" :status :untested ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "kvs40xx" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-kvs40xx" ; name of manpage (if it exists) :comment "New backend for SANE release 1.0.23, see sane-kvs40xx manpage" :devicetype :scanner ; start of a list of devices.... :new :no :mfg "Panasonic" ; name a manufacturer :url "http://www.panasonic.com/" :model "KV-S4065C" :interface "USB" :usbid "0x04da" "0x100d" :status :untested :model "KV-S4085C" :interface "USB" :usbid "0x04da" "0x100c" :status :untested :model "KV-S7075C" :interface "USB" :usbid "0x04da" "0x100e" :status :untested ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "leo" ; name of backend :version "1.0-10" ; version of backend :manpage "sane-leo" ; name of manpage (if it exists) :url "http://www.zago.net/sane/#leo" ; backend's web page :devicetype :scanner ; start of a list of devices.... :mfg "LEO" :model "LEOScan S3" :interface "SCSI" :comment "FCC ID LUZFS1130" :status :good :mfg "Across Technologies" :model "FS-1130" :interface "SCSI" :comment "FCC ID LUZFS1130" :status :good :mfg "Genius" :model "FS-1130 Colorpage Scanner" :interface "SCSI" :status :good ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "lexmark" ; name of backend :version "1.0-0" ; version of backend (or "unmaintained") :manpage "sane-lexmark" ; name of manpage (if it exists) :url "http://stef.dev.free.fr/sane/lexmark" ; backend's web page :comment "This backend supports lexmark x1100 series scanners." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Lexmark" ; name a manufacturer :url "http://www.lexmark.com/" ; manufacturer's URL :model "X1110" :interface "USB" :usbid "0x043d" "0x007c" :status :untested :model "X1130" :interface "USB" :usbid "0x043d" "0x007c" :status :good :comment "Supports 75, 150, 300, 600 dpi" :model "X1140" :interface "USB" :usbid "0x043d" "0x007c" :status :untested :model "X1150" :interface "USB" :usbid "0x043d" "0x007c" :status :good :comment "Supports 75, 150, 300, 600 dpi" :model "X1170" :interface "USB" :usbid "0x043d" "0x007c" :status :good :comment "Supports 75, 150, 300, 600 dpi" :model "X1180" :interface "USB" :usbid "0x043d" "0x007c" :status :good :model "X1185" :interface "USB" :usbid "0x043d" "0x007c" :status :good :comment "Tested with xscanimage. Supports 75, 150, 300, 600, 1200(600x1200) dpi resolutions. Does grayscale or colour scans in the following sizes: wallet, 3x5, 4x6, 5x7, 8x10, letter." :model "X1195" :interface "USB" :usbid "0x043d" "0x007c" :status :untested :model "X74" :interface "USB" :usbid "0x043d" "0x0060" :status :good :comment "Supports 75, 150, 300, 600 dpi" :model "X12xx" :interface "USB" :usbid "0x043d" "0x007d" :status :good :comment "USB1.1 is OK, USB2.0 needs testing" :mfg "Dell" ; name a manufacturer :model "A920" :interface "USB" :usbid "0x413c" "0x5105" :status :good :comment "Relabelled X11xx model" ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "ma1509" ; name of backend :version "1.0-3" ; version of backend :manpage "sane-ma1509" ; name of manpage (if it exists) :url "http://www.meier-geinitz.de/sane/ma1509-backend/" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Mustek" ; name a manufacturer :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "BearPaw 1200 F" :interface "USB" :usbid "0x055f" "0x0010" :status :good :comment "Works upto 600 dpi. No support for TA and ADF yet." :mfg "Fujitsu" ; name a manufacturer :url "http://www.fujitsu.com/" :model "fi-4110EOX/2/3" :interface "USB" :usbid "0x04c5" "0x1040" :status :unsupported :comment "Uses ma1509 chip, but very different from other scanners supported by the ma1509 backend" ; ; SANE Backend specification file for the magicolor backend ; ; Copyright (C) 2010-11 Reinhold Kainhofer ; Released under GPLv2 ; :backend "magicolor" :version "1.0.0" :manpage "sane-magicolor" :url "http://wiki.kainhofer.com/hardware/magicolor_scan" :devicetype :scanner :mfg "KONICA MINOLTA" :url "http://www.konicaminolta.com/" :model "magicolor 1690MF" :interface "USB Network" :usbid "0x132b" "0x2089" :status :good :comment "Multi-function color laser printer with fax, scanner and network interface" :url "http://www.konicaminolta.eu/business-solutions/products/laser-printers/all-in-one/magicolor-1690mf/key-features.html" :model "BizHub 162/132" :interface "USB Network" :usbid "ignore" :status :unsupported :comment "Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov." :model "DiMage 1611" :interface "USB Network" :usbid "ignore" :status :unsupported :comment "Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov." ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "matsushita" ; name of backend :version "1.0-7" ; version of backend :manpage "sane-matsushita" ; name of manpage :url "http://www.zago.net/sane" ; backend's web page :devicetype :scanner ; start of a list of devices.... :mfg "Panasonic" ; name a manufacturer :url "http://www.panasonic.com/" :model "KV-SS25" :interface "SCSI" :status :complete :model "KV-SS25D" :interface "SCSI" :status :complete :model "KV-SS50" :interface "SCSI" :status :untested :model "KV-SS55" :interface "SCSI" :status :untested :model "KV-SS50EX" :interface "SCSI" :status :untested :model "KV-SS55EX" :interface "SCSI" :status :minimal :comment "no color, no high resolution, no automatic cropping" :model "KV-SS850" :interface "SCSI" :status :untested :model "KV-SS855" :interface "SCSI" :status :untested :model "KV-S2025C" :interface "SCSI" :status :minimal :comment "no color, no high resolution, no automatic cropping" :model "KV-S2045C" :interface "SCSI" :status :minimal :comment "no color, no high resolution, no automatic cropping" :model "KV-S2065L" :interface "SCSI" :status :minimal :comment "no color, no high resolution, no automatic cropping" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "microtek2" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-microtek2" ; name of manpage (if it exists) :url "http://karstenfestag.gmxhome.de/linux.html" :devicetype :scanner ; start of a list of devices.... :mfg "Microtek" ; name a manufacturer :url "http://www.microtek.com/" :model "ScanMaker E3plus" :interface "Parport" :status :complete :model "ScanMaker E3plus" ; name models for above-specified mfg. :interface "SCSI" :status :complete :model "ScanMaker X6" :interface "SCSI" :status :complete :model "ScanMaker X6EL" :interface "SCSI" :status :basic :model "ScanMaker X6USB" :interface "USB" :usbid "0x05da" "0x0099" :status :good :model "ScanMaker V300" :interface "SCSI" :status :good :model "ScanMaker V300" :interface "Parport" :status :good :model "ScanMaker V310" :interface "SCSI" :status :basic :model "ScanMaker V310" :interface "Parport" :status :basic :model "ScanMaker V600" :interface "SCSI" :status :basic :model "ScanMaker V600" :interface "Parport" :status :basic :model "ScanMaker 330" :interface "SCSI" :status :basic :model "ScanMaker 630" :interface "SCSI" :status :basic :model "ScanMaker 636" :interface "SCSI" :status :complete :model "ScanMaker 6400XL" :interface "SCSI" :status :complete :model "ScanMaker 9600XL" :interface "SCSI" :comment "only flatbed mode ?" :status :good :model "ScanMaker 9800XL" :url "/unsupported/microtek-scanmaker-9800.html" :interface "IEEE-1394" :status :minimal :comment "IEEE-1394 seems to work. See link. More reports welcome." :model "Phantom 330CX" :interface "Parport" :status :complete :model "SlimScan C3" :interface "Parport" :status :complete :model "Phantom 636" :interface "SCSI" :status :complete :model "Phantom 636CX" :interface "Parport" :status :complete :model "SlimScan C6" :interface "USB" :usbid "0x05da" "0x009a" :status :complete :model "ScanMaker V6UPL" :interface "USB" :usbid "0x05da" "0x00b6" :status :basic :comment "Sometimes scan speed goes to fast and results look badly smudged." :model "ScanMaker V6USL" :interface "SCSI" :status :complete :model "ScanMaker V6USL" :interface "USB" :usbid "0x05da" "0x00a3" :status :complete :model "ScanMaker V6USL" :interface "USB" :usbid "0x05da" "0x80a3" :status :complete :model "ScanMaker X12USL" :interface "SCSI" :comment "only Flatbed mode ?" :status :good :mfg "Vobis" :url "http://www.vobis.de/" :model "HighScan" ; name models for above-specified mfg. :interface "SCSI" :comment "only E3plus based models" :status :complete :mfg "Scanport" :url "http://www.scanport.com/" :model "SQ300" :interface "Parport?" :status :basic :model "SQ2030" :interface "Parport" :status :basic :model "SQ4836" :interface "SCSI" :status :basic :mfg "Genius" :url "http://www.geniusmouse.co.uk/" :model "ColorPage-EP" :interface "Parport" :status :good :backend "microtek" :version "0.13.1" :manpage "sane-microtek" :url "http://www.mir.com/mtek/" :devicetype :scanner :mfg "Microtek" :url "http://www.microtek.com/" :model "Scanmaker E6" :interface "SCSI" :status :good :model "Scanmaker E3" :interface "SCSI" :status :good :model "Scanmaker E2" :interface "SCSI" :comment "3-pass" :status :good :model "Scanmaker 35t+" :interface "SCSI" :comment "slide-scanner" :status :good :model "Scanmaker 45t" :interface "SCSI" :comment "slide-scanner" :status :good :model "Scanmaker 35" :interface "SCSI" :comment "slide-scanner" :status :good :model "Scanmaker III" :interface "SCSI" :status :good :model "Scanmaker IISP" :interface "SCSI" :status :good :model "Scanmaker IIHR" :interface "SCSI" :comment "3-pass" :status :good :model "Scanmaker IIG" :interface "SCSI" :comment "gray only" :status :good :model "Scanmaker II" :interface "SCSI" :comment "3-pass" :status :good :model "Scanmaker 600Z(S)" :interface "SCSI" :status :untested :model "Scanmaker 600G(S)" :interface "SCSI" :comment "gray only (see manpage)" :status :basic :model "Color PageWiz" :interface "SCSI (Parport)" :comment "sheet-fed (preliminary, see mapage)" :status :basic :mfg "Agfa" :url "http://www.agfa.com/" :model "Arcus II" :interface "SCSI" :comment "Arcus *II*, not Arcus!" :status :good :model "StudioScan" :interface "SCSI" :status :good :model "StudioScan II" :interface "SCSI" :status :good :model "StudioScan IIsi" :interface "SCSI" :status :good :model "Studiostar" :interface "SCSI" :status :minimal :comment "Is detected but scans are very dark" :model "DuoScan" :interface "SCSI" :status :basic :mfg "Vobis" :url "http://www.vobis.de/" :model "Highscreen Realscan" :interface "SCSI" :status :good :mfg "Genius" :url "http://www.genius-kye.com/" :model "Colorpage-SP2" :interface "SCSI" :comment "Same as Microtek Scanmaker E3" :status :good ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "mustek" ; name of backend :version "1.0-138" ; version of backend :manpage "sane-mustek" ; name of manpage (if it exists) :url "http://www.meier-geinitz.de/sane/mustek-backend/" :comment "Most Mustek SCSI scanners are supported by this backend. For USB scanners, look at the mustek_usb backend." :devicetype :scanner :mfg "Mustek" ; name a manufacturer :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "Paragon MFS-6000CX" :interface "SCSI" :comment "3-pass" :status :good :model "Paragon MFS-12000CX" :interface "SCSI" :comment "3-pass" :status :good :model "Paragon MFC-600S" :interface "SCSI" :status :complete :model "Paragon 600 II CD" :interface "SCSI" :status :complete :model "Paragon 600 II ED" :interface "Parport" :status :untested :comment "Completely untested. If it's the same as the 600 II EP, it may work. Please contact me if you own such a device." :model "Paragon 600 II EP" :interface "Parport" :status :minimal :comment "Works, however only low resolutions and quality in color mode is bad." :model "ScanMagic 600 II SP" :interface "SCSI" :status :complete :model "TwainScan II SP" :interface "SCSI" :status :complete :model "Paragon MFC-800S" :interface "SCSI" :status :complete :model "Paragon 800 II SP" :interface "SCSI" :status :complete :model "Paragon MFS-6000SP" :interface "SCSI" :status :complete :model "Paragon MFS-8000SP" :interface "SCSI" :status :complete :model "Paragon MFS-1200SP" :interface "SCSI" :status :complete :model "Paragon MFS-12000SP" :interface "SCSI" :status :complete :model "ScanExpress 6000SP" :interface "SCSI" :status :complete :model "ScanExpress 12000SP" :interface "SCSI" :status :complete :model "ScanExpress 1200 FS" :interface "SCSI" :status :untested :comment "One report that it crashes the computer. SCSI driver issue? Please contact me if you own such a device." :model "ScanExpress 12000SP Plus" :interface "SCSI" :status :complete :model "Paragon 1200 III SP" :interface "SCSI" :status :complete :model "Paragon 1200 LS" :interface "SCSI" :status :complete :model "ScanMagic 9636S" :interface "SCSI" :status :complete :model "ScanMagic 9636S Plus" :interface "SCSI" :status :complete :model "ScanExpress A3 SP" :interface "SCSI" :comment "Please test!" :status :basic :model "Paragon 1200 SP Pro" :interface "SCSI" :status :good :model "Paragon 1200 A3 Pro" :interface "SCSI" :status :complete :comment "ADF and TA untested. Please contact me if you own such equipment." :model "Paragon 600 II N" :interface "Proprietary" :status :basic :comment "Resolutions above 300 dpi may cause trouble." :mfg "Trust" ; name a manufacturer :url "http://www.trust-site.com" :comment "Carefully check the model names. Trust uses similar names for completely different hardware." :model "Imagery 1200" :interface "SCSI" :status :good :comment "3-pass, Mustek Paragon MFS-6000CX compatible" :model "Imagery 1200 SP" :interface "SCSI" :status :complete :comment "Mustek Paragon MFS-6000SP compatible" :model "Imagery 4800 SP" :interface "SCSI" :status :complete :comment "Mustek Paragon 600 II CD compatible" :model "SCSI Connect 19200" :interface "SCSI" :status :complete :comment "Mustek ScanExpress 12000SP compatible" :model "SCSI excellence series 19200" :interface "SCSI" :status :complete :comment "Mustek ScanExpress 12000SP compatible" :mfg "Primax" ; name a manufacturer :url "http://www.primax.nl/" :model "Compact 4800 SCSI" :interface "SCSI" :status :complete :comment "Mustek 600 II CD compatible" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "mustek_pp" ; name of backend :version "13" ; version of backend :manpage "sane-mustek_pp" ; name of manpage (if it exists) ; backend's web page :url "http://penguin-breeder.org/sane/mustek_pp/" :comment "Supports CIS and CCD type parallel port scanners from Mustek." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Mustek" ; name a manufacturer :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "ScanExpress 6000 P" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "ScanExpress 600 SEP" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "ScanMagic 4800 P" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "600 III EP Plus" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "96 CP" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :model "ScanExpress 600 CP" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :model "ScanMagic 600 CP" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :model "ScanExpress 1200 CP" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :model "ScanExpress 1200 CP+" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.de/" :comment "Those scanners are also known as \"Aldi Scanner\" or \"Tchibo Scanners\"" :model "MD 9848" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "MD 9806" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :model "MD/LT 935x" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :model "MD/LT 985x" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :model "MD/LT 9890" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :mfg "Targa" :model "Funline TS12 EP" :interface "Parport (EPP)" :status :good :comment "600x1200 dpi CIS scanner" :model "Funline TS6 EP" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :mfg "Trust" :url "http://www.trust-site.com/home/" :model "Easy Connect 9600+" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :model "Easy Connect 19200+" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" :mfg "Viviscan" :model "Compact II" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :mfg "Cybercom" :model "9352" :interface "Parport (EPP)" :status :good :comment "CIS scanner" :mfg "Gallery" :model "4800" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :mfg "Network" :model "Easy Plus 30 Bit" :interface "Parport (EPP)" :status :good :comment "300 dpi CCD scanner" :mfg "Micromaxx" :model "MM-9851" :interface "Parport (EPP)" :status :good :comment "300x600 dpi CIS scanner" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. :backend "mustek_usb2" :version "1.0-10" :manpage "sane-mustek_usb2" :url "http://www.meier-geinitz.de/sane/mustek_usb2-backend/" :comment "Only BearPaw 2448TA Pro is supported at the moment" :devicetype :scanner :mfg "Mustek" :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "BearPaw 2448TA Pro" :interface "USB" :usbid "0x055f" "0x0409" :status :good :backend "mustek_usb" :version "1.0-18" :manpage "sane-mustek_usb" :url "http://www.meier-geinitz.de/sane/mustek_usb-backend/" :comment "Only the USB scanners mentioned below are supported. For BearPaws, look at the Plustek, MA-1509, and gt68xx backends." :devicetype :scanner :mfg "Mustek" :url "http://www.mustek.com/" :url "http://www.mustek.com.tw/" :url "http://www.mustek.de/" :model "ScanExpress 600 CU" :interface "USB" :usbid "0x055f" "0x0002" :status :complete :model "ScanExpress 1200 CU" :interface "USB" :usbid "0x055f" "0x0001" :status :complete :model "ScanExpress 1200 CU Plus" :interface "USB" :usbid "0x055f" "0x0008" :status :complete :model "ScanExpress 1200 UB" :interface "USB" :usbid "0x055f" "0x0006" :status :complete :comment "For the UB Plus, see gt68xx backend" :mfg "Trust" :url "http://www.trust-site.com" :model "Compact Scan USB 19200" :interface "USB" :usbid "0x055f" "0x0006" :status :complete :comment "Mustek 1200 UB compatible" :backend "nec" ; name of backend :version "0.12" ; version of backend :url "http://www5a.biglobe.ne.jp/~saetaka/" ; backend's homepage :manpage "sane-nec" :devicetype :scanner :mfg "NEC" ; name a manufacturer :url "http://www.nevt.co.jp/" :model "PC-IN500/4C" ; name models for above-specified mfg. :interface "SCSI" :comment "PC-IN500/4C was sold only in JAPAN" :status :good :backend "net" ; name of backend :version "1.0.14" :manpage "sane-net" :url "http://www.penguin-breeder.org/?page=sane-net" :devicetype :meta :desc "Network access to saned servers" :comment "Can be used to access any scanner supported by SANE over the net. Supports IPv4 and IPv6." ; $Id$ ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "niash" :version "0.3" :manpage "sane-niash" :url "http://sourceforge.net/projects/hp3300backend" :devicetype :scanner :mfg "Hewlett-Packard" :url "http://www.hp.com" :model "ScanJet 3300c" :interface "USB" :usbid "0x03f0" "0x0205" :status :complete :model "ScanJet 3400c" :interface "USB" :usbid "0x03f0" "0x0405" :comment "If you use Linux 2.6, version 2.6.8 or newer is necessary." :status :complete :model "ScanJet 4300c" :interface "USB" :usbid "0x03f0" "0x0305" :comment "If you use Linux 2.6, version 2.6.8 or newer is necessary." :status :complete :model "ScanJet 4300c/Silitek" :interface "USB" :usbid "0x047b" "0x1002" :comment "If you use Linux 2.6, version 2.6.8 or newer is necessary." :status :complete :mfg "Agfa" :url "http://www.agfa.com" :model "Snapscan Touch" :interface "USB" :usbid "0x06bd" "0x0100" :status :complete :mfg "Trust" :url "http://www.trust.com" :model "Office Scan USB 19200" :interface "USB" :usbid "0x047b" "0x1000" :status :complete ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "p5" ; name of backend :version "1" ; version of backend :manpage "sane-p5" ; name of manpage (if it exists) :comment "New backend for SANE release 1.0.21, see sane-p5 manpage" :url "http://www.sane-project.org/" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "PRIMAX" ; name a manufacturer :url "http://www.primax.com.tw" :model "PagePartner" :interface "Parport (EPP/ECP)" :status :basic :comment "Sheetfed scanner, work in gray and color, but uncalibrated scans" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "pie" ; name of backend :version "1.0" ; version of backend :manpage "sane-pie" ; name of manpage (if it exists) :url "http://www.munton.demon.co.uk/sane" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Devcom" :url "http://www.blackwidow.co.uk/" :model "9636PRO" :interface "SCSI" :status :good :model "9636S" :interface "SCSI" :status :untested :model "9630S" :interface "SCSI" :status :untested :mfg "PIE" ; name a manufacturer :url "http://www.scanace.com/" :model "ScanAce 1236S" :interface "SCSI" :status :good :model "ScanAce 1230S" :interface "SCSI" :status :good :model "ScanAce II" :interface "SCSI" :status :untested :model "ScanAce III" :interface "SCSI" :status :good :model "ScanAce Plus" :interface "SCSI" :status :untested :model "ScanAce II Plus" :interface "SCSI" :status :untested :model "ScanAce III Plus" :interface "SCSI" :status :untested :model "ScanAce V" :interface "SCSI" :status :untested :model "ScanAce ScanMedia" :interface "SCSI" :status :untested :model "ScanAce ScanMedia II" :interface "SCSI" :status :untested :model "ScanAce 630S" :interface "SCSI" :status :untested :model "ScanAce 636S" :interface "SCSI" :status :untested :mfg "Adlib" :model "JetScan630" :interface "SCSI" :status :good :model "JetScan636PRO" :interface "SCSI" :status :untested ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. :backend "pint" ; name of backend :version "unmaintained" ; version of backend ; :url "" ; backend's homepage :manpage "sane-pint" :devicetype :api ; name models for above-specified mfg. :desc "Scanners with the machine-independent PINT interface" :comment "Haven't been tested for a long time. Handle with care." ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "pixma" ; name of backend :version "0.17.3" ; version of backend (or "unmaintained") :manpage "sane-pixma" ; name of manpage (if it exists) :url "http://home.arcor.de/wittawat/pixma/" ; 0.13.2 backend's web page :url "http://mp610.blogspot.com/" ; the pixma backend blog ;:comment "Devices marked as experimantal are disabled by default. See the manual page for how to enable them." :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Canon" ; name a manufacturer :url "http://www.canon.com/" :model "PIXMA E500" :interface "USB" :usbid "0x04a9" "0x1758" :status :untested :comment "Testers needed!" :model "PIXMA E510" :interface "USB" :usbid "0x04a9" "0x1761" :status :untested :comment "Testers needed!" :model "PIXMA E600" :interface "USB" :usbid "0x04a9" "0x175a" :status :untested :comment "Testers needed!" :model "PIXMA E610" :interface "USB" :usbid "0x04a9" "0x1767" :status :untested :comment "Testers needed!" :model "PIXMA MG2100 Series" :interface "USB" :usbid "0x04a9" "0x1751" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG2200 Series" :interface "USB" :usbid "0x04a9" "0x1760" :status :untested :comment "Testers needed!" :model "PIXMA MG3100 Series" :interface "USB WLAN" :usbid "0x04a9" "0x1752" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG3200 Series" :interface "USB" :usbid "0x04a9" "0x1762" :status :untested :comment "Testers needed!" :model "PIXMA MG4100 Series" :interface "USB" :usbid "0x04a9" "0x1753" :status :untested :comment "Testers needed!" :model "PIXMA MG4200 Series" :interface "USB" :usbid "0x04a9" "0x1763" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG5100 Series" :interface "USB" :usbid "0x04a9" "0x1748" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG5200 Series" :interface "USB" :usbid "0x04a9" "0x1749" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MG5300 Series" :interface "USB" :usbid "0x04a9" "0x1754" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG5400 Series" :interface "USB" :usbid "0x04a9" "0x1764" :status :untested :comment "Testers needed!" :model "PIXMA MG6100 Series" :interface "USB" :usbid "0x04a9" "0x174a" :status :complete :comment "All resolutions supported (up to 2400 DPI)" :model "PIXMA MG6200 Series" :interface "USB" :usbid "0x04a9" "0x1755" :status :complete :comment "All resolutions supported (up to 4800 DPI)" :model "PIXMA MG6300 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1765" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MG8100 Series" :interface "USB" :usbid "0x04a9" "0x174b" :status :untested :comment "Testers needed!" :model "PIXMA MG8200 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1756" :status :complete :comment "All resolutions supported (up to 4800DPI)." :model "PIXMA MP140" :interface "USB" :usbid "0x04a9" "0x172b" :status :complete :comment "All resolutions supported (up to 600 DPI)" :model "PIXMA MP150" :interface "USB" :usbid "0x04a9" "0x1709" :status :good :model "PIXMA MP160" :interface "USB" :usbid "0x04a9" "0x1714" :status :basic :model "PIXMA MP170" :interface "USB" :usbid "0x04a9" "0x170a" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP180" :interface "USB" :usbid "0x04a9" "0x1715" :status :basic :model "PIXMA MP190" :interface "USB" :usbid "0x04a9" "0x1734" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "PIXMA MP210" :interface "USB" :usbid "0x04a9" "0x1721" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "PIXMA MP220" :interface "USB" :usbid "0x04a9" "0x1722" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP230" :interface "USB" :usbid "0x04a9" "0x175f" :status :complete :comment "All resolutions supported (up to 600DPI)." :model "PIXMA MP240" :interface "USB" :usbid "0x04a9" "0x1732" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP250" :interface "USB" :usbid "0x04a9" "0x173a" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "PIXMA MP260" :interface "USB" :usbid "0x04a9" "0x1733" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP270" :interface "USB" :usbid "0x04a9" "0x173b" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP280" :interface "USB" :usbid "0x04a9" "0x1746" :status :good :comment "All resolutions supported (up to 600DPI)." :model "PIXMA MP360" :interface "USB" :usbid "0x04a9" "0x263c" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP370" :interface "USB" :usbid "0x04a9" "0x263d" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP375R" :interface "USB" :usbid "0x04a9" "0x263f" :status :untested :comment "Same protocol as Pixma MP360/370/390? Testers needed!" :model "PIXMA MP390" :interface "USB" :usbid "0x04a9" "0x263e" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP450" :interface "USB" :usbid "0x04a9" "0x170b" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP460" :interface "USB" :usbid "0x04a9" "0x1716" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP470" :interface "USB" :usbid "0x04a9" "0x1723" :status :complete :comment "All resolutions supported (up to 2400DPI)." :model "PIXMA MP480" :interface "USB" :usbid "0x04a9" "0x1731" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP490" :interface "USB" :usbid "0x04a9" "0x173c" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP493" :interface "USB" :usbid "0x04a9" "0x1757" :status :untested :comment "Testers needed!" :model "PIXMA MP495" :interface "USB" :usbid "0x04a9" "0x1747" :status :untested :comment "Same protocol as Pixma MP280? Testers needed!" :model "PIXMA MP500" :interface "USB" :usbid "0x04a9" "0x170c" :status :good :model "PIXMA MP510" :interface "USB" :usbid "0x04a9" "0x1717" :status :complete :comment "All resolutions supported (up to 1200DPI)." :model "PIXMA MP520" :interface "USB" :usbid "0x04a9" "0x1724" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP530" :interface "USB" :usbid "0x04a9" "0x1712" :status :good :model "PIXMA MP540" :interface "USB" :usbid "0x04a9" "0x1730" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP550" :interface "USB" :usbid "0x04a9" "0x173d" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP560" :interface "USB" :usbid "0x04a9" "0x173e" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP600" :interface "USB" :usbid "0x04a9" "0x1718" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP600R" :interface "USB Ethernet" :usbid "0x04a9" "0x1719" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP610" :interface "USB" :usbid "0x04a9" "0x1725" :status :complete :comment "All resolutions supported (up to 4800DPI)" :model "PIXMA MP620" :interface "USB Ethernet" :usbid "0x04a9" "0x172f" :status :complete :comment "All resolutions supported (up to 2400DPI)" :model "PIXMA MP630" :interface "USB" :usbid "0x04a9" "0x172e" :status :complete :comment "All resolutions supported (up to 4800DPI)" :model "PIXMA MP640" :interface "USB Ethernet" :usbid "0x04a9" "0x173f" :status :complete :comment "All resolutions supported (up to 4800DPI)" :model "PIXMA MP700" :interface "USB" :usbid "0x04a9" "0x2630" :status :complete :comment "All resolutions supported (flatbed color up to 1200DPI, grayscale up to 600DPI)." :model "PIXMA MP710" :interface "USB" :usbid "0x04a9" "0x264d" :status :complete :comment "All resolutions supported (up to 1200DPI)" :model "PIXMA MP730" :interface "USB" :usbid "0x04a9" "0x262f" :status :good :comment "Flatbed color up to 1200DPI, grayscale up to 600DPI. ADF scan to be confirmed." :model "PIXMA MP740" :interface "USB" :usbid "0x04a9" "0x264c" :status :untested :comment "Same protocol as Pixma MP710? Testers needed!" :model "PIXMA MP750" :interface "USB" :usbid "0x04a9" "0x1706" :status :minimal :comment "No grayscale. Canceling scan in ADF mode doesn't eject the paper!" :model "PIXMA MP760" :interface "USB" :usbid "0x04a9" "0x1708" :status :minimal :comment "No grayscale. The scanner sometimes hangs!" :model "PIXMA MP770" :interface "USB" :usbid "0x04a9" "0x1708" :status :minimal :comment "No grayscale. The scanner sometimes hangs!" :model "PIXMA MP780" :interface "USB" :usbid "0x04a9" "0x1707" :status :minimal :comment "No grayscale. The scanner sometimes hangs!" :model "PIXMA MP790" :interface "USB" :usbid "0x04a9" "0x1707" :status :minimal :comment "No grayscale. The scanner sometimes hangs!" :model "PIXMA MP800" :interface "USB" :usbid "0x04a9" "0x170d" :status :complete :comment "All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI." :model "PIXMA MP800R" :interface "USB" :usbid "0x04a9" "0x170e" :status :complete :comment "All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI." :model "PIXMA MP810" :interface "USB" :usbid "0x04a9" "0x171a" :status :complete :comment "All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI." :model "PIXMA MP830" :interface "USB" :usbid "0x04a9" "0x1713" :status :complete :comment "All resolutions supported up to 2400DPI. Flatbed, ADF simplex and Duplex supported." :model "PIXMA MP960" :interface "USB" :usbid "0x04a9" "0x171b" :status :complete :comment "All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI." :model "PIXMA MP970" :interface "USB Ethernet" :usbid "0x04a9" "0x1726" :status :complete :comment "All resolutions supported (up to 4800DPI). Full TPU support (negative and slides) at 24 or 48 bits." :model "PIXMA MP980" :interface "USB Ethernet" :usbid "0x04a9" "0x172d" :status :complete :comment "Working fine at all resolutions." :model "PIXMA MP990" :interface "USB Ethernet" :usbid "0x04a9" "0x1740" :status :complete :comment "Working fine at all resolutions." :model "PIXMA MX300" :interface "USB" :usbid "0x04a9" "0x1727" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "PIXMA MX310" :interface "USB" :usbid "0x04a9" "0x1728" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)" :model "PIXMA MX320" :interface "USB" :usbid "0x04a9" "0x1736" :status :untested :comment "Same protocol as Pixma Generation 3? Testers needed!" :model "PIXMA MX330" :interface "USB" :usbid "0x04a9" "0x1737" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)" :model "PIXMA MX340" :interface "USB" :usbid "0x04a9" "0x1741" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)" :model "PIXMA MX350" :interface "USB Ethernet" :usbid "0x04a9" "0x1742" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)" :model "PIXMA MX360" :interface "USB" :usbid "0x04a9" "0x174d" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy." :model "PIXMA MX370 Series" :interface "USB" :usbid "0x04a9" "0x1759" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "PIXMA MX390 Series" :interface "USB" :usbid "0x04a9" "0x1766" :status :untested :comment "Testers needed!" :model "PIXMA MX410" :interface "USB Ethernet" :usbid "0x04a9" "0x174e" :status :untested :comment "Same protocol as Pixma MX420? Testers needed!" :model "PIXMA MX420" :interface "USB Ethernet" :usbid "0x04a9" "0x174f" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy." :model "PIXMA MX430 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175b" :status :untested :comment "Testers needed!" :model "PIXMA MX450 Series" :interface "USB" :usbid "0x04a9" "0x1768" :status :untested :comment "Testers needed!" :model "PIXMA MX510 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175c" :status :untested :comment "Testers needed!" :model "PIXMA MX520 Series" :interface "USB" :usbid "0x04a9" "0x1769" :status :untested :comment "Testers needed!" :model "PIXMA MX700" :interface "USB Ethernet" :usbid "0x04a9" "0x1729" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 2400DPI)" :model "PIXMA MX710 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175d" :status :untested :comment "Testers needed!" :model "PIXMA MX720 Series" :interface "USB" :usbid "0x04a9" "0x176a" :status :untested :comment "Testers needed!" :model "PIXMA MX850" :interface "USB Ethernet" :usbid "0x04a9" "0x172c" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX860" :interface "USB Ethernet" :usbid "0x04a9" "0x1735" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported." :model "PIXMA MX870" :interface "USB Ethernet" :usbid "0x04a9" "0x1743" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." :model "PIXMA MX880 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." :model "PIXMA MX882" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." :model "PIXMA MX885" :interface "USB Ethernet" :usbid "0x04a9" "0x1750" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." :model "PIXMA MX890 Series" :interface "USB Ethernet" :usbid "0x04a9" "0x175e" :status :complete :comment "All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy." :model "PIXMA MX920 Series" :interface "USB" :usbid "0x04a9" "0x176b" :status :untested :comment "Testers needed!" :model "PIXMA MX7600" :interface "USB Ethernet" :usbid "0x04a9" "0x171c" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 4800DPI)" :model "imageCLASS D420" :interface "USB" :usbid "0x04a9" "0x26ef" :status :complete :comment "All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported." :model "imageCLASS D480" :interface "USB" :usbid "0x04a9" "0x26ed" :status :complete :comment "All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported." :model "i-SENSYS MF3010" :interface "USB Ethernet" :usbid "0x04a9" "0x2759" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF3110" :interface "USB" :usbid "0x04a9" "0x2660" :status :complete :comment "All resolutions supported (up to 600DPI)." :model "imageCLASS MF3240" :interface "USB" :usbid "0x04a9" "0x2684" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4010" :interface "USB" :usbid "0x04a9" "0x26b4" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4018" :interface "USB" :usbid "0x04a9" "0x26b4" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4120" :interface "USB" :usbid "0x04a9" "0x26a3" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4122" :interface "USB" :usbid "0x04a9" "0x26a3" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4140" :interface "USB" :usbid "0x04a9" "0x26a3" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4150" :interface "USB" :usbid "0x04a9" "0x26a3" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF4270" :interface "USB" :usbid "0x04a9" "0x26b5" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "I-SENSYS MF4320d" :interface "USB" :usbid "0x04a9" "0x26ee" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "I-SENSYS MF4330d" :interface "USB" :usbid "0x04a9" "0x26ee" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF4350d" :interface "USB" :usbid "0x04a9" "0x26ee" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF4370dn" :interface "USB" :usbid "0x04a9" "0x26ec" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported" :model "imageCLASS MF4380dn" :interface "USB" :usbid "0x04a9" "0x26ec" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported" :model "imageCLASS MF4410" :interface "USB" :usbid "0x04a9" "0x2737" :status :complete :comment "All resolutions supported (up to 600DPI)" :model "imageCLASS MF4430" :interface "USB" :usbid "0x04a9" "0x2737" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI). ADF empty buggy." :model "i-SENSYS MF4550d" :interface "USB" :usbid "0x04a9" "0x2736" :status :good :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)." :model "imageCLASS MF4660" :interface "USB" :usbid "0x04a9" "0x26b0" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF4690" :interface "USB" :usbid "0x04a9" "0x26b0" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF5630" :interface "USB" :usbid "0x04a9" "0x264e" :status :untested :comment "Testers needed!" :model "laserBase MF5650" :interface "USB" :usbid "0x04a9" "0x264f" :status :untested :comment "Testers needed!" :model "imageCLASS MF5730" :interface "USB" :usbid "0x04a9" "0x265d" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 1200DPI)." :model "imageCLASS MF5750" :interface "USB" :usbid "0x04a9" "0x265e" :status :untested :comment "Testers needed!" :model "imageCLASS MF5770" :interface "USB" :usbid "0x04a9" "0x265f" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)." :model "i-SENSYS MF5880dn" :interface "USB" :usbid "0x04a9" "0x26f9" :status :untested :comment "Testers needed!" :model "imageCLASS MF6500 series" :interface "USB" :usbid "0x04a9" "0x2686" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "imageCLASS MF6550" :interface "USB" :usbid "0x04a9" "0x2686" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "i-SENSYS MF6680dn" :interface "USB" :usbid "0x04a9" "0x26fa" :status :untested :comment "Testers needed!" :model "imageCLASS MF8030" :interface "USB" :usbid "0x04a9" "0x2707" :status :untested :comment "Testers needed!" :model "imageCLASS MF8170c" :interface "USB" :usbid "0x04a9" "0x2659" :status :untested :comment "Testers needed!" :model "imageRUNNER 1020/1024/1025" :interface "USB" :usbid "0x04a9" "0x26e6" :status :complete :comment "Flatbed and ADF scan. All resolutions supported (up to 600DPI)" :model "CanoScan 8800F" :interface "USB" :usbid "0x04a9" "0x1901" :status :complete :comment "Flatbed scan. TPU for negatives and slides. All resolutions supported (up to 4800DPI)." :model "CanoScan 9000F" :interface "USB" :usbid "0x04a9" "0x1908" :status :complete :comment "Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI." :model "CanoScan 9000F Mark II" :interface "USB" :usbid "0x04a9" "0x190d" :status :complete :comment "Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI." ; ; SANE Backend description file for Plustek backend (USB only) ; :backend "plustek" :version "0.52" :manpage "sane-plustek" ; backend's web page :url "http://www.gjaeger.de/scanner/plustek/" :devicetype :scanner ;* Plustek ********************************************************************************** :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticPro U12" :interface "USB" :usbid "0x07b3" "0x0010" :status :complete :comment "NOTE: Devices with product ID 0x0001 are not supported!" :model "OpticPro UT12" :interface "USB" :usbid "0x07b3" "0x0013" :status :complete :model "OpticPro UT12" :interface "USB" :usbid "0x07b3" "0x0017" :status :complete :comment "Note: Devices with product ID 0x0001 are not supported!" :model "OpticPro UT16" :interface "USB" :usbid "0x07b3" "0x0017" :status :complete :model "OpticPro U24" :interface "USB" :usbid "0x07b3" "0x0011" :status :complete :model "OpticPro U24" :interface "USB" :usbid "0x07b3" "0x0015" :status :complete :model "OpticPro UT24" :interface "USB" :usbid "0x07b3" "0x0017" :status :complete ;* Genius/KYE ******************************************************************************************* :mfg "Genius" :url "http://www.geniusnet.com.tw/" :model "Colorpage HR6 V2" :interface "USB" :usbid "0x0458" "0x2007" :status :complete :model "Colorpage HR6 V2" :interface "USB" :usbid "0x0458" "0x2008" :status :complete :model "Colorpage HR7" :interface "USB" :usbid "0x0458" "0x2013" :status :complete :model "Colorpage HR6A" :interface "USB" :usbid "0x0458" "0x2009" :status :untested :model "Colorpage HR7LE" :interface "USB" :usbid "0x0458" "0x2015" :status :untested :model "Colorpage HR6X" :interface "USB" :usbid "0x0458" "0x2016" :status :untested ;* MUSTEK *********************************************************************************** :mfg "Mustek" :url "http://www.mustek.com/" :model "BearPaw 1200" :interface "USB" :usbid "0x0400" "0x1000" :status :complete :comment "both product versions are supported, see backends' man-page" :model "BearPaw 1200" :interface "USB" :usbid "0x0400" "0x1001" :status :complete :comment "both product versions are supported, see backends' man-page" :model "BearPaw 2400" :interface "USB" :usbid "0x0400" "0x1001" :status :complete ;* Hewlett-Packard ************************************************************************** :mfg "Hewlett-Packard" :url "http://www.hp.com/" :model "ScanJet 2100C" :interface "USB" :usbid "0x03f0" "0x0505" :status :complete :model "ScanJet 2200C" :interface "USB" :usbid "0x03f0" "0x0605" :status :complete ;* EPSON ******************************************************************************************* :mfg "Epson" :url "http://www.epson.com/" :model "Perfection 1250" :interface "USB" :usbid "0x04b8" "0x010f" :status :complete :model "Perfection 1250Photo" :interface "USB" :usbid "0x04b8" "0x010f" :status :good :comment "TPA scans not perfect" :model "Perfection 1260" :interface "USB" :usbid "0x04b8" "0x011d" :status :complete :model "Perfection 1260Photo" :interface "USB" :usbid "0x04b8" "0x011d" :status :good :comment "TPA scans not perfect" ;* UMAX ************************************************************************************* :mfg "Umax" :url "http://www.umax.com/" :model "UMAX 3400" :interface "USB" :usbid "0x1606" "0x0050" :status :complete :comment "there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x" :model "UMAX 3400" :interface "USB" :usbid "0x1606" "0x0060" :status :complete :comment "there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x" :model "UMAX Astranet ia101" :interface "USB" :usbid "0x1606" "0x0060" :status :complete :comment "seems to be a renamed UMAX 3400" :model "UMAX 3450" :interface "USB" :usbid "0x1606" "0x0060" :status :complete :model "UMAX 5400" :interface "USB" :usbid "0x1606" "0x0160" :status :complete ;* COMPAQ ****************************************************************************************** :mfg "Compaq" :url "http://www.compaq.com/" :model "S4-100" :interface "USB" :usbid "0x049f" "0x001a" :status :complete :comment "Identical to UMAX 3400" ;* CANON ******************************************************************************************* :mfg "Canon" :url "http://www.canon.com/" :model "CanoScan N650U/N656U" :interface "USB" :usbid "0x04a9" "0x2206" :status :complete :model "CanoScan N1220U" :interface "USB" :usbid "0x04a9" "0x2207" :status :complete :model "CanoScan N670U/N676U/LiDE20" :interface "USB" :usbid "0x04a9" "0x220d" :status :complete :model "CanoScan N1240U/LiDE30" :interface "USB" :usbid "0x04a9" "0x220e" :status :complete :model "CanoScan LiDE25" :interface "USB" :usbid "0x04a9" "0x2220" :status :good :model "CanoScan D660U" :interface "USB" :usbid "0x04a9" "0x2208" :status :good :comment "TPA scans not perfect" ;* SYSCAN ******************************************************************************************* :mfg "Syscan" :url "http://www.syscaninc.com/" :model "TravelScan 460/464" :interface "USB" :usbid "0x0a82" "0x4600" :status :complete :model "TravelScan 662" :interface "USB" :usbid "0x0a82" "0x6620" :status :complete ;* SYSCAN ******************************************************************************************* :mfg "Ambir" :model "Visigo A4" :interface "USB" :usbid "0x0a82" "0x4600" :status :complete :comment "Rebaged Travelscan 464" ;* Portable Peripheral Co., Ltd. ******************************************************************** :mfg "Portable Peripheral Co., Ltd." :url "http://www.pandp.com.tw/" :model "Q-Scan USB001 (A4 portable scanner)" :interface "USB" :usbid "0x0a53" "0x1000" :status :complete :model "Q-Scan USB201 (A6 portable scanner)" :interface "USB" :usbid "0x0a53" "0x2000" :status :good ;* Visioneer **************************************************************************************** :mfg "Visioneer" :url "http://www.visioneer.com/" :model "Strobe XP 100" :interface "USB" :usbid "0x04a7" "0x0427" :status :basic ; ; SANE Backend description file for Plustek_pp backend ; :backend "plustek_pp" :version "0.43" :manpage "sane-plustek_pp" ; backend's web page :url "http://www.gjaeger.de/scanner/plustek_pp/" :devicetype :scanner ;* Plustek ********************************************************************************** :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" ;name models for above-specified mfg. :model "OpticPro 4800P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 4830P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 600P/6000P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 4831P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 9630P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 9630PL" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=1" :model "OpticPro 9600P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 1236P" :interface "Parport (SPP, EPP)" :status :complete :comment "reported as OpticPro 12000P/96000P" :model "OpticPro 12000P/96000P" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 9636P" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=4" :model "OpticPro 9636P+/Turbo" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=3" :model "OpticPro 9636T" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro 12000T" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro AI3" :interface "Parport (SPP, EPP)" :status :basic :comment "use driver-switch mov=5, poor picture quality" :model "OpticPro P8" :interface "Parport" :status :untested :model "OpticPro P12" :interface "Parport (SPP, EPP)" :status :complete :model "OpticPro PT12" :interface "Parport (SPP, EPP)" :status :complete ;* Primax *********************************************************************************** :mfg "Primax" ; name of manufacturer :url "http://www.primax.nl/" ;name models for above-specified mfg. :model "Colorado 4800" :interface "Parport (SPP, EPP)" :status :untested :comment "same as OpticPro 4800P" :model "Compact 4800 Direct" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=2" :model "Compact 4800 Direct-30" :interface "Parport (SPP, EPP)" :status :complete :comment "same as OpticPro 4830P, use driver-switch mov=7" :model "Compact 9600 Direct-30" :interface "Parport (SPP, EPP)" :status :complete :comment "same as OpticPro 9630P" ;* Genius/KYE ******************************************************************************************* :mfg "Genius" :url "http://www.geniusnet.com.tw/" :model "Colorpage Vivid III V2" :interface "Parport (SPP, EPP)" :status :complete :comment "Reported as PT12" :model "Colorpage Vivid Pro II Film" :interface "Parport (SPP, EPP)" :status :complete :comment "Reported as OP9636T/12000T" :model "Colorpage HR6X EPP" :interface "Parport (SPP, EPP)" :status :good :comment "Negative scanning does not work correctly" ;******************************************************************************************** :mfg "Aries" :model "Scan-It Pro 4800" :interface "Parport (SPP, EPP)" :status :complete :comment "use driver-switch mov=2" ;******************************************************************************************** :mfg "BrightScan" :model "BrighScan OpticPro" :interface "Parport (SPP, EPP)" :status :complete :comment "Reported as P12" :backend "pnm" :version "1.0.8" :manpage "sane-pnm" :url "mailto:henning@meier-geinitz.de" :devicetype :api :desc "Reads PNM files" :comment "Used for debugging frontends. Obsolete, use test backend instead." :backend "qcam" ; name of backend :version "unmaintained" ; version of backend ; :url "" ; backend's homepage :manpage "sane-qcam" :devicetype :vidcam :mfg "Connectix" ; name a manufacturer ;:url "http://www.connectix.com/" ; doesn't exist any longer? :model "Color QuickCam" ; name models for above-specified mfg. :interface "Parport" :status :good :comment "Requires root privileges." :model "Greyscale QuickCam" ; name models for above-specified mfg. :interface "Parport" :status :minimal :comment "Requires root privileges. Partly working." ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "ricoh" ; name of backend :version "unmaintained" ; version of backend ; :manpage "sane-ricoh" ; name of manpage (if it exists) :devicetype :scanner :mfg "Ricoh" ; name a manufacturer :url "http://www.ricoh.com/" :model "Ricoh IS50" ; name models for above-specified mfg. :interface "SCSI" :status :basic ;:comment "?" :model "Ricoh IS60" ; name models for above-specified mfg. :interface "SCSI" :status :basic ;:comment "?" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). :backend "rts8891" ; name of backend :version "1.0-0" ; version of backend (or "unmaintained") :manpage "sane-rts8891" ; name of manpage (if it exists) :url "http://stef.dev.free.fr/sane/rts8891/index.html" ; backend's web page :comment "This backend supports Realtek RTS8891 ASIC bases scanners." ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com.tw/" ; manufacturer's URL :model "Astra 4400" :interface "USB" :usbid "0x1606" "0x0070" :status :good :comment "Supports 75, 150, 300, 600 and 1200 dpi" :model "Astra 4450" :interface "USB" :usbid "0x1606" "0x0070" :status :untested :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "scanjet 4470c" :interface "USB" :usbid "0x03f0" "0x0805" :status :good :comment "re-branded Astra 4400" :model "scanjet 4400c" :interface "USB" :usbid "0x03f0" "0x0705" :status :good :comment "exists with 2 different sensors of which only one works" :backend "s9036" ; name of backend :version "unmaintained" ; version of backend ; :url "" ; backend's homepage :manpage "sane-s9036" :devicetype :scanner :mfg "Siemens" ; name a manufacturer :url "http://www.siemens.com/" :model "9036 Flatbed scanner" ; name models for above-specified mfg. :interface "SCSI" :status :basic ; :comment "" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "sceptre" :version "1.0-10" ; version of backend :manpage "sane-sceptre" ; name of manpage :url "http://www.zago.net/sane/" ; backend's web page :devicetype :scanner :mfg "Sceptre" :url "http://www.sceptre.com/" :model "Vividscan S1200" :interface "SCSI" :status :basic :mfg "Komodo" :url "http://www.komodo.com/" :model "S1200" :interface "SCSI" :status :untested :comment "rebadged Sceptre S1200" :backend "sharp" ; name of backend :version "0.32" ; version of backend ;:status :beta ; :alpha, :beta, :stable, :new :url "http://www.satzbau-gmbh.de/staff/abel/sane-sharp.html" ; backend's homepage :manpage "sane-sharp" :devicetype :scanner :mfg "Sharp" ; name a manufacturer :url "http://sharp-world.com/" :model "JX-610" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" :model "JX-250" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" :model "JX-320" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" :model "JX-325" ; name models for above-specified mfg. :interface "SCSI" :status :untested :comment "" :model "JX-330" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" :model "JX-350" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "" ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "sm3600" ; name of backend :version "0.1" ; version of backend :manpage "sane-sm3600" ; name of manpage (if it exists) :url "http://sm3600.sourceforge.net/" ; backend's web page :devicetype :scanner ; start of a list of devices.... :mfg "Microtek" :url "http://www.microtek.com/" :model "ScanMaker 3600" :interface "USB" :usbid "0x05da" "0x40b3" :comment "works" :status :basic :model "ScanMaker 3600" :interface "USB" :usbid "0x05da" "0x40ca" :comment "works" :status :basic :model "ScanMaker 3600" :interface "USB" :usbid "0x05da" "0x40ff" :comment "works" :status :basic :model "ScanMaker 3700" :interface "USB" :usbid "0x05da" "0x40b8" :comment "works" :status :basic :model "ScanMaker 3700" :interface "USB" :usbid "0x05da" "0x40cb" :comment "works" :status :basic :model "ScanMaker 3750" :interface "USB" :usbid "0x05da" "0x40dd" :comment "works (told)" :status :basic ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; ; See doc/descriptions.txt for details. :backend "sm3840" ; name of backend :version "1.1" ; version of backend (or "unmaintained") :manpage "sane-sm3840" ; name of manpage (if it exists) :url "http://www.ziplabel.com/sm3840/" ; backend's web page :comment "This reverse-engineered backend supports the USB ScanMaker 3840 model" ; comment about the backend :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Microtek" ; name a manufacturer :url "http://www.microtek.com/" ; manufacturer's URL :comment "Microtek makes a wide variety of devices." ; comment about the manufacturer :model "ScanMaker 3840" ; name models for above-specified mfg. :status :good ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :usbid "0x05da" "0x30d4" :comment "8 and 16 bit, color and grayscale" ; comment about the model :model "ScanMaker 4800" ; name models for above-specified mfg. :status :good ; :minimal, :basic, :good, :complete ; :untested, or :unsupported :interface "USB" ; interface type of the device: ; "SCSI", "USB", "Parport (EPP)", ; "Parport (SPP)", "Parport (ECP)", ; "Serial port", "IEEE-1394", "JetDirect", ; or "Proprietary". :usbid "0x05da" "0x30cf" :comment "Same hardware as SM3840, different color box" ; comment ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; :status specifier is optional after :model and at the top-level ; $Id$ ; ; SANE Backend specification file (Matto Marjanovic's format) ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "SnapScan" ; name of backend :version "1.4" ; version of backend :manpage "sane-snapscan" ; name of manpage (if it exists) :url "http://snapscan.sourceforge.net/" ; backend's web page :comment "Supported bit depths: 24 bit (color), 48 bit (color, Epson) 8 bit (gray)" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api ;----------------------------------------------------------------------------- :mfg "AGFA" ; name a manufacturer :url "http://www.agfa.com/" :model "SnapScan" ; name models for above-specified mfg. :interface "SCSI" :status :good :model "SnapScan 300" :interface "SCSI" :status :good :model "SnapScan 310" :interface "SCSI" :status :good :model "SnapScan 600" :interface "SCSI" :status :good :comment "Optional ADF supported." :model "Arcus 1200" :interface "SCSI" :status :good :comment "Optional transparency unit supported." :model "SnapScan 1236s" :interface "SCSI" :status :good :comment "Optional ADF and transparency unit supported." :model "SnapScan 1236u" :interface "USB" :status :good :usbid "0x06bd" "0x0002" :comment "Optional ADF and transparency unit supported." :model "SnapScan 1212U" :interface "USB" :usbid "0x06bd" "0x0001" :status :good :model "SnapScan 1212U_2" :interface "USB" :usbid "0x06bd" "0x2061" :status :good :model "SnapScan e10" :interface "USB" :usbid "0x06bd" "0x2093" :status :good :model "SnapScan e20" :interface "USB" :usbid "0x06bd" "0x2091" :status :good :model "SnapScan e25" :interface "USB" :usbid "0x06bd" "0x2095" :status :good :model "SnapScan e26" :interface "USB" :usbid "0x06bd" "0x2097" :status :good :model "SnapScan e40" :interface "USB" :usbid "0x06bd" "0x208d" :status :good :model "SnapScan e42" :interface "USB" :usbid "0x06bd" "0x20ff" :status :good :model "SnapScan e50" :interface "USB" :status :good :usbid "0x06bd" "0x208f" :comment "Optional tranparency unit supported" :model "SnapScan e52" :interface "USB" :status :good :usbid "0x06bd" "0x20fd" :comment "Optional tranparency unit supported" :model "SnapScan e60" :interface "USB" :status :untested ;------------------------------------------------------------------------------ :mfg "Acer Peripherals" :comment "Company was renamed to Benq." :mfg "Vuego" :comment "Company was renamed to Benq." :mfg "Benq (Acer)" :url "http://www.benq.com" :comment "Formerly Acer Peripherals" :model "300f" :interface "SCSI" :status :good :model "310s" :interface "SCSI" :status :good :model "610s" :interface "SCSI" :status :good :model "610plus" :interface "SCSI" :status :good :model "620s" :interface "SCSI" :status :good :model "ScanWit 2720s" :interface "SCSI" :status :good :model "310U" :interface "USB" :usbid "0x04a5" "0x1a20" :status :good :model "320U" :interface "USB" :usbid "0x04a5" "0x2022" :status :good :model "340U" :interface "USB" :usbid "0x04a5" "0x2022" :status :good :model "620U" :interface "USB" :usbid "0x04a5" "0x1a2a" :status :good :comment "Optional tranparency unit supported" :model "620UT" :interface "USB" :usbid "0x04a5" "0x2040" :status :good :comment "Optional tranparency unit supported" :model "640U" :interface "USB" :usbid "0x04a5" "0x2060" :status :good :comment "Optional tranparency unit supported" :model "640bu" :interface "USB" :usbid "0x04a5" "0x207e" :status :good :model "640BT" :interface "USB" :usbid "0x04a5" "0x20be" :status :good :comment "Optional tranparency unit supported" :model "1240" :interface "USB" :usbid "0x04a5" "0x20c0" :status :good :comment "Optional tranparency unit supported" :model "3300" :interface "USB" :usbid "0x04a5" "0x20b0" :status :good :model "3300" :interface "USB" :usbid "0x04a5" "0x20de" :status :good :model "4300" :interface "USB" :usbid "0x04a5" "0x20b0" :status :good :model "4300" :interface "USB" :usbid "0x04a5" "0x20de" :status :good :model "5000E" :interface "USB" :usbid "0x04a5" "0x20fc" :status :basic :comment "Same as 5000U, working up to 600 DPI" :model "5000U" :interface "USB" :usbid "0x04a5" "0x20fc" :status :basic :comment "Same as 5000E, working up to 600 DPI" :model "5000" :interface "USB" :usbid "0x04a5" "0x20f8" :status :good :comment "USB ID 0x04a5,0x20f8: Color / grayscale scans working up to 1200 DPI" :model "5150" :interface "USB" :usbid "0x04a5" "0x2137" :status :basic :comment "Calibration algorithm unknown" :model "5250" :interface "USB" :usbid "0x04a5" "0x2137" :status :basic :comment "Same hardware as 5150 (?), Calibration algorithm unknown" :model "5300" :interface "USB" :usbid "0x04a5" "0x20fe" :status :basic :comment "Problems with firmware upload reported" ;------------------------------------------------------------------------------ :mfg "Guillemot / Hercules" :url "http://www.guillemot.com" :model "Maxi Scan A4 Deluxe (SCSI)" :interface "SCSI" :status :good :comment "Rebadged SnapScan 310s." :model "Scan@home Touch 1248 (USB)" :interface "USB" :usbid "0x04a5" "0x20de" :status :good :comment "Rebadged Benq 3300." :model "Maxi Scan A4 USB 640U" :interface "USB" :usbid "0x04a5" "0x2060" :status :good :comment "Rebadged Benq 640U." :model "Maxi A4 36 bit" :interface "USB" :usbid "0x04a5" "0x2060" :status :good :comment "Rebadged Benq 620U, needs Benq firmware file u96v???.bin" ;------------------------------------------------------------------------------ :mfg "Mitsubishi" :url "http://www.mitsubishi.com" :model "Diamondview 648UT" :interface "USB" :usbid "0x04a5" "0x2022" :status :good :comment "Rebadged Benq 320u." :model "Diamondview 650U" :interface "USB" :usbid "0x04a5" "0x20b0" :status :good :comment "Rebadged Benq 4300." ;------------------------------------------------------------------------------ :mfg "Epson" :url "http://www.epson.com" :model "Perfection 660" :interface "USB" :usbid "0x04b8" "0x0114" :status :good :model "Perfection 1270" :interface "USB" :usbid "0x04b8" "0x0120" :status :good :model "Perfection 1670" :interface "USB" :usbid "0x04b8" "0x011f" :status :good :model "Perfection 2480" :interface "USB" :usbid "0x04b8" "0x0121" :status :good :model "Perfection 2580" :interface "USB" :status :basic :usbid "0x04b8" "0x0121" :comment "Film scanning unit unsupported" :model "Perfection 3490" :interface "USB" :usbid "0x04b8" "0x0122" :status :good :model "Perfection 3590" :interface "USB" :usbid "0x04b8" "0x0122" :status :basic :comment "Film scanning unit unsupported" :model "Stylus CX-1500" :interface "USB" :usbid "0x04b8" "0x080c" :status :good ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "sp15c" ; name of backend :version "unmaintained" ; version of backend :manpage "sane-sp15c" ; name of manpage (if it exists) ;:url "http://www.aa.net/~bentson/sane.html" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Fujitsu" ; name a manufacturer :url "http://www.fcpa.fujitsu.com/products/scanners/" :url "http://www.fujitsu.com/" :model "ScanPartner 15C" ; name models for above-specified mfg. :interface "SCSI" :status :good :model "ScanPartner 600C" ; name models for above-specified mfg. :interface "SCSI" :status :good ; ST400 backend .desc by Ingo Wilken :backend "st400" ; name of backend :version "1.6" ; version number :manpage "sane-st400" ; name of manpage (if it exists) :url "http://www.informatik.uni-oldenburg.de/~ingo/sane/" ; backend's web page :devicetype :scanner ; start of a list of devices :mfg "Siemens" :url "http://www.siemens.de/" :model "ST400" :interface "SCSI" :comment "6 bit gray" :status :basic :model "ST800" :interface "SCSI" :comment "6 bit gray" :status :basic ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "stv680" ; name of backend :version "1.0-1" ; version of backend :manpage "sane-stv680" :url "http://gkall.hobby.nl/stv680-aiptek.html" ; backend's web page :comment "This vidcam backend is for the stv0680 chipset, See the website for more info." :devicetype :vidcam ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Aiptek" ; name a manufacturer :url "http://www.aiptek.com.tw" ; name models for above-specified mfg. :model "Aiptek Pencam" :interface "USB" :usbid "0x0553" "0x0202" :status :minimal :comment "image is OK for CIF and QCIF, VGA and QVGA untested, streaming video is a problem" :mfg "Konica" ; name a manufacturer :url "http://www.konicaminolta.com" ; name models for above-specified mfg. :model "e-mini" :interface "USB" :usbid "0x04c8" "0x0722" :status :untested :comment " " :mfg "Digital Dream" ; name a manufacturer :url "http://www.digitaldreamco.com/en/index.shtml" ; name models for above-specified mfg. :model "l' espion XS" :interface "USB" :usbid "0x1183" "0x0001" :status :untested :comment " " :mfg "Creative" ; name a manufacturer :url "http://www.creative.com/" ; name models for above-specified mfg. :model "WebCam Go Mini" :interface "USB" :usbid "0x041e" "0x4007" :status :untested :comment " " ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "tamarack" ; name of backend :version "unmaintained" ; version of backend ; :manpage "sane-tamarack" ; name of manpage (if it exists) :devicetype :scanner :mfg "Tamarack" ; name a manufacturer ;:url "http://www.tamarack.net/" ; doesn't exist anymore? :model "Artiscan 6000C" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "3 pass, 300 DPI" :model "Artiscan 8000C" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "3 pass, 400 DPI" :model "Artiscan 12000C" ; name models for above-specified mfg. :interface "SCSI" :status :good :comment "3 pass, 600 DPI" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "teco1" ; name of backend :version "1.0-10" ; version of backend :manpage "sane-teco1" ; name of manpage (if it exists) :url "http://www.zago.net/sane/#teco" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Relisys" :url "http://www.relisys.com/" :url "http://www.tecoimage.com.tw/" :model "RELI 2412" :interface "SCSI" :comment "sub model VM3530+" :status :complete :model "AVEC 2400" :interface "SCSI" :comment "sub model VM3520" :status :complete :model "RELI 4830" :interface "SCSI" :comment "sub model VM4542" :status :good :model "AVEC 2412" :comment "sub model VM3520+" :interface "SCSI" :status :complete :model "AVEC 4800" :comment "sub model VM4530" :interface "SCSI" :status :untested :model "AVEC 4816" :comment "sub model VM4530+" :interface "SCSI" :status :untested :model "RELI DS6" :comment "sub model VM3420" :interface "SCSI" :status :untested :model "RELI DS15" :comment "sub model VM3440" :interface "SCSI" :status :untested :model "RELI 2400" :comment "sub model VM3530" :interface "SCSI" :status :untested :model "RELI 4816" :comment "sub model VM4540" :interface "SCSI" :status :complete :model "RELI 9600" :comment "sub model VM6530" :interface "SCSI" :status :untested :model "RELI 9612" :comment "sub model VM6530*" :interface "SCSI" :status :untested :model "RELI 9624" :comment "sub model VM6530+" :interface "SCSI" :status :untested :model "RELI 9630" :comment "sub model VM6540" :interface "SCSI" :status :untested :mfg "Actown" :model "ACT Scan I 30" :comment "sub model VM3520A" :interface "SCSI" :status :untested :mfg "Dextra" :model "DF-600P" :comment "sub model VM3510" :interface "SCSI" :status :good :model "DF-1200T+" :comment "sub model VM3530+" :interface "SCSI" :status :untested :model "DF-4830T" :comment "sub model VM4542" :interface "SCSI" :status :untested :model "DF-9624" :comment "sub model VM6530+" :interface "SCSI" :status :untested ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "teco2" ; name of backend :version "1.0-9" ; version of backend :manpage "sane-teco2" :url "http://gkall.hobby.nl/teco2.html" ; backend's web page :devicetype :scanner :mfg "Relisys" :url "http://www.relisys.com/" :model "AVEC Super 3" :interface "SCSI" :comment "sub model VM3575" :status :untested :model "AVEC II S3" :interface "SCSI" :comment "sub model VM3564" :status :good :model "SCORPIO Super 3" :comment "sub model VM3575" :interface "SCSI" :status :good :model "APOLLO Express 3" :comment "sub model VM356A" :interface "SCSI" :status :basic :model "APOLLO Express 6" :comment "sub model VM6565" ; aka VM656A :interface "SCSI" :status :good :model "SCORPIO Pro" :comment "sub model VM6575" :interface "SCSI" :status :good :model "SCORPIO Pro-S" :comment "sub model VM6586" :interface "SCSI" :status :untested :mfg "Primax" :url "http://www.primax.nl/" :model "Jewel 4800" :comment "sub model VM356A" :interface "SCSI" :status :good :model "Profi 9600" :comment "sub model VM6575" :interface "SCSI" :status :basic :model "Profi 19200" :comment "sub model VM6586" :interface "SCSI" :status :good :mfg "Mustek" :url "http://www.mustek.com/" :model "ScanMagic 4830S" :comment "sub model VM3575" :interface "SCSI" :status :untested ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "teco3" ; name of backend :version "1.0-1" ; version of backend :manpage "sane-teco3" ; name of manpage (if it exists) :url "http://www.zago.net/sane/#teco3" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "Relisys" :url "http://www.tecoimage.com.tw/" :model "Infinity Scorpio" :comment "sub model VM3552" :interface "SCSI" :status :good :mfg "Plustek" :model "OpticPro 2400SP" :comment "sub model VM3552" :interface "SCSI" :status :untested :mfg "PIOTECH" :url "http://www.image-land.com/" :model "Splendeur 3024" :comment "sub model VM3552" :interface "SCSI" :status :good :mfg "Trust" :model "Imagery 2400 SP" :comment "sub model VM3552" :interface "SCSI" :status :good :model "Imagery 4800 SP+" :comment "sub model VM3552" :interface "SCSI" :status :good :model "Imagery 9600 SP" :comment "sub model VM3552" :interface "SCSI" :status :untested ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "test" ; name of backend :version "1.0-28" ; version of backend :manpage "sane-test" ; name of manpage (if it exists) :url "http://www.meier-geinitz.de/sane/test-backend/" ; backend's web page :devicetype :api ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :desc "Frontend-tester" :comment "Backend for testing frontends. Also serves as example for SANE backend options." ; ; SANE Backend description file for U12 backend ; :backend "u12" :version "0.02" :manpage "sane-u12" :new :no ; backend's web page :url "http://www.gjaeger.de/scanner/u12/" :devicetype :scanner ;* Plustek ********************************************************************************** :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticPro U12" :interface "USB" :usbid "0x07b3" "0x0001" :status :basic :comment "Note: Only devices with product ID 0x0001 are supported!" :model "OpticPro UT12" :interface "USB" :usbid "0x07b3" "0x0001" :status :basic :comment "Note: Only devices with product ID 0x0001 are supported!" :model "OpticPro 1212U" :interface "USB" :usbid "0x07b3" "0x0001" :status :basic ;* RevScan ********************************************************************************** :mfg "RevScan" :model "RevScan Orange R48Ti" :interface "USB" :usbid "0x07b3" "0x0001" :status :basic :comment "Rebadged Plustek OpticPro UT12" ;* Genius/KYE ******************************************************************************************* :mfg "Genius" :url "http://www.geniusnet.com.tw/" :model "ColorPage HR6 V1" :interface "USB" :usbid "0x0458" "0x2004" :status :basic :model "ColorPage Vivid III USB" :interface "USB" :usbid "0x07b3" "0x0001" :status :untested :comment "Note: Device has Plustek vendor and product ID (0x07b3/0x0001)" ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "umax1220u" ; name of backend :version "unmaintained" ; version of backend ;:status :stable ; :alpha, :beta, :stable, :new :manpage "sane-umax1220u" ; name of manpage (if it exists) :url "http://sourceforge.net/projects/umax1220u-sane" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com/" :model "Astra 1220U" ; name models for above-specified mfg. :interface "USB" :usbid "0x1606" "0x0010" :status :good :model "Astra 1600U" :interface "USB" :usbid "0x1606" "0x0030" :status :good :model "Astra 2000U" :interface "USB" :usbid "0x1606" "0x0030" :status :good :model "Astra 2100U" :interface "USB" :usbid "0x1606" "0x0130" :status :good ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "umax" ; name of backend :version "1.0-41" ; version of backend :manpage "sane-umax" ; name of manpage (if it exists) :url "http://www.rauch-domain.de/sane-umax/index.html" ; backend's web page :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com/" :url "http://www.umax.com.tw/" :url "http://www.umax.de/en" :url "http://www.umax-europe.com" :url "http://www.umaxjapan.co.jp" :url "http://www.umax.com.cn" :model "Vista S6" :interface "SCSI" :status :good :comment "OK" :model "Vista S6E" :interface "SCSI" :status :good :comment "OK" :model "UMAX S-6E" :interface "SCSI" :status :good :comment "OK" :model "UMAX S-6EG" :interface "SCSI" :status :good :comment "OK" :model "Vista-S8" :interface "SCSI" :status :good :comment "OK" :model "Supervista S-12" :interface "SCSI" :status :good :comment "OK" :model "UMAX S-12" :interface "SCSI" :status :good :comment "OK" :model "UMAX S-12G" :interface "SCSI" :status :good :comment "OK" :model "Astra 600S" :interface "SCSI" :status :good :comment "OK" :model "Astra 610S" :interface "SCSI" :status :good :comment "OK" :model "Astra 1200S" :interface "SCSI" :status :good :comment "OK" :model "Astra 1220S" :interface "SCSI" :status :good :comment "OK" :model "Astra 2100S" :interface "SCSI" :status :good :comment "OK" :model "Astra 2200 (SU)" :interface "SCSI" :status :good :comment "OK" :model "Astra 2200 (SU)" :interface "USB" :usbid "0x1606" "0x0230" :status :good :comment "OK, needs USB control messages" :model "Astra 2400S" :interface "SCSI" :status :good :comment "OK" :model "Astra 6400" :interface "IEEE-1394" :status :unsupported :comment "will probably work one day" :model "Astra 6450" :interface "IEEE-1394" :status :unsupported :comment "will probably work one day" :model "Astra MX3" :interface "SCSI" :status :good :comment "OK" :model "Astra MX3" :interface "USB" :status :good :comment "OK, needs USB control messages" :model "Mirage D-16L" :interface "SCSI" :status :good :comment "OK" :model "Mirage II" :interface "SCSI" :status :good :comment "OK" :model "Mirage IIse" :interface "SCSI" :status :good :comment "OK" :model "PSD" :interface "SCSI" :status :good :comment "OK" :model "PowerLook" :interface "SCSI" :status :good :comment "OK, SCSI-ID=PS-2400X" :model "PL-II" :interface "SCSI" :status :good :comment "OK" :model "PowerLook III" :interface "SCSI" :status :good :comment "OK" :model "PowerLook 270" :interface "SCSI" :status :unsupported :comment "incompatible" :model "PowerLook 270plus" :interface "SCSI" :status :unsupported :comment "incompatible" :model "PowerLook 1100" :interface "IEEE-1394" :status :unsupported :comment "will probably work one day" :model "PowerLook 2000" :interface "SCSI" :status :good :comment "OK" :model "PowerLook 2100XL" :interface "SCSI" :status :good :comment "OK" :model "PowerLook 3000" :interface "SCSI" :status :good :comment "OK" :model "Gemini D-16" :interface "SCSI" :status :good :comment "OK" :model "UMAX VT600" :interface "SCSI" :status :untested :comment "may work, please test and give feedback" :model "Vista-T630" :interface "SCSI" :status :good :comment "OK for some firmwareversions, on others only lineart OK" :model "UC 630" :interface "SCSI" :status :good :comment "Version 2.8 OK, others only lineart OK" :model "UG 630" :interface "SCSI" :status :good :comment "OK" :model "UG 80" :interface "SCSI" :status :good :comment "OK" :model "UC 840" :interface "SCSI" :status :good :comment "Version 1.6 OK, others only lineart OK" :model "UC 1200S" :interface "SCSI" :status :untested :comment "may work, please test and give feedback" :model "UC 1200SE" :interface "SCSI" :status :good :comment "Version 3.0 OK, others unknown" :model "UC 1260" :interface "SCSI" :status :good :comment "Version 1.6 OK, others unknown" :mfg "Linotype Hell" ; another manufacturer... :url "http://www.heidelberg.com/" :model "Jade" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell Office" :model "Jade" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell JADE" :model "Jade2" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell Office2" :model "Saphir" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Saphir2" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell SAPHIR2" :model "Saphir3" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell SAPHIR3" :model "Saphir Ultra" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Saphir Ultra II" :interface "SCSI" :status :good :comment "OK, SCSI-ID=Linotype SAPHIR4" :model "Saphir HiRes" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Opal" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Opal2" :interface "SCSI" :status :good :comment "OK; SCSI-ID=LinoHell OPAL2" :model "Opal Ultra" :interface "SCSI" :status :untested :comment "support disabled until tested - please contact author" :model "Linoscan 1400" :interface "SCSI" :status :good :comment "OK, SCSI-ID=HDM LS4H1S" :mfg "Vobis" :url "http://www.vobis.de/" :model "Highscreen Scanboostar Premium" :interface "SCSI" :status :good :comment "OK, SCSI-ID=LinoHell Office2" :mfg "EDGE" ; another manufacturer... ; :url "http://???/" :model "KTX-9600US" :interface "SCSI" :status :untested :comment "no feedback" :mfg "Epson" ; another manufacturer... :url "http://www.epson.com/" :model "Perfection 600" :interface "SCSI" :status :good :comment "OK, SCSI-ID=EPSON Perfection600" :mfg "Escom" ; another manufacturer... :model "Image Scanner 256" :interface "SCSI" :status :good :comment "OK, SCSI-ID=UMAX UG 80" :mfg "Escort" ; another manufacturer... :model "Galleria 600" :interface "SCSI" :status :untested :comment "untested, SCSI-ID=ESCORT Galleria 600S" :mfg "Genius" ; another manufacturer... ;:url "http://www.genius.kye.de/" :model "ColorPage-HR5 (Pro)" :interface "SCSI" :status :good :comment "OK, SCSI-ID=KYE ColorPage-HR5" :mfg "Nikon" ; another manufacturer... :url "http://www.nikon.com/" :model "AX-110 / Scantouch 110" :interface "SCSI" :status :untested :comment "may work, please test and give feedback" :model "AX-210" :interface "SCSI" :status :good :comment "OK" :mfg "TriGem" ; another manufacturer... :url "http://www.nikon.com/" :model "PowerScanII" :interface "SCSI" :status :good :comment "OK" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "umax_pp" ; name of backend :version "1" ; version of backend :manpage "sane-umax_pp" ; name of manpage (if it exists) ; backend's web page :url "http://umax1220p.sourceforge.net/" :devicetype :scanner ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :mfg "UMAX" ; name a manufacturer :url "http://www.umax.com.tw/" ; These scanners are known to have the same ASIC family. :model "Astra 1220P" :interface "Parport (EPP/ECP)" :status :good :model "Astra 2000P" :interface "Parport (EPP/ECP)" :status :good :model "Astra 1600P" :interface "Parport (EPP/ECP)" :status :good :model "Astra 600P" :interface "Parport (SPP/ECP)" :status :unsupported :comment "untested, but should be close to 610P" :model "Astra 610P" :interface "Parport (SPP/ECP)" :status :good :mfg "Hewlett-Packard" :model "Scanjet 3200C" :interface "Parport (EPP/ECP)" :status :good :comment "works (relabelled 1220P and 2000P)" :mfg "Genius" :model "ColorPage-Life Pro" :interface "Parport (EPP/ECP)" :status :good :comment "works (relabelled 1220P and 2000P)" ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "unsupported" ; name of backend :version "2010-06-09" ; version of backend :url "/contrib.html" ;:manpage "sane-mustek" ; name of manpage (if it exists) :comment "The devices mentioned here are not supported by any SANE backend. However, there may be links to information about them or stand-alone programs." :devicetype :scanner ;******************************************************************************************** :mfg "Agfa" :model "DuoScan f40" :url "/unsupported/agfa-duoscan-f40.html" :interface "USB IEEE-1394" :usbid "0x06bd" "0x02bf" :status :unsupported :comment "Unsupported. See link for details." :model "DuoScan T2000XL" :url "/unsupported/agfa-duoscan-t2000xl.html" :interface "SCSI" :status :unsupported :comment "Unsupported. Same as Microtek ArtixScan 2020?" :model "DuoScan T2500" :interface "SCSI IEEE-1384" :status :unsupported :comment "Unsupported. Same as Microtek Artixscan 2500f" :model "SnapScan 310P" :url "/unsupported/acer-parport.html" :interface "Parport" :status :unsupported :comment "Unsupported, see link for details." :model "SnapScan EZ" :url "/unsupported/acer-parport.html" :interface "Parport" :status :unsupported :comment "Unsupported, see link for details." :model "SnapScan 1200P" :url "/unsupported/acer-parport.html" :interface "Parport" :status :unsupported :comment "Unsupported, see link for details." :model "SnapScan 1212P" :url "/unsupported/acer-parport.html" :interface "Parport" :status :unsupported :comment "Unsupported, see link for details." ;******************************************************************************************** :mfg "Artec/Ultima" :url "http://www.artecusa.com/" :model "1236 USB" :url "/unsupported/artec_1236usb.html" :interface "USB" :usbid "0x05d8" "0x4001" :status :unsupported :comment "Unsupported. See link for details." :model "AM12e+" :status :unsupported :interface "Parport" :comment "Unsupported. Chips found inside: AT015, AD9816JS. Maybe similar to SCSI version or as6e?" :model "Ultima 2000 (0x4001)" :url "/unsupported/artec-ultima-2000-2.html" :interface "USB" :usbid "0x05d8" "0x4001" :status :unsupported :comment "Same name, but different ids: This scanner is not supported. The scanner with product id 0x4002 is supported by the gt68xx backend, however." ;******************************************************************************************** :mfg "Avigramm" :model "Minidoc" :url "/unsupported/trust-combiscan-19200.html" :interface "USB Parport" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** :mfg "Avision" :url "http://www.avision.com/" :model "DS310F" :interface "Parport" :status :unsupported :comment "Probably not supported. Scanner/printer/copier combination." :model "iVina FB2400" :interface "USB" :status :unsupported :comment "Not supported. No chipset information available. Same as UMAX Astra 6700." :model "iVina 1600" :url "/unsupported/umax-astra-4500.html" :interface "USB" :usbid "0x0638" "0x0a10" :status :unsupported :comment "GL646 based, to be added to genesys backend. Same as UMAX Astra 4500." :model "iVina FB1800" :url "/unsupported/umax-astra-4700.html" :interface "USB" :usbid "0x0638" "0x0a20" :status :unsupported :comment "GL646/GL660 based. Same as UMAX Astra 4700." ;******************************************************************************************** :mfg "Benq (Acer)" :url "http://www.benq.com" :comment "Formerly Acer Peripherals" :model "310P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "320P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "340P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "610P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "610PT" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "620P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "620PT" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "640P" :url "/unsupported/acer-parport.html" :status :unsupported :interface "Parport" :comment "Unsupported, see link for details." :model "5450" :interface "USB" :usbid "0x04a5" "0x211e" :status :unsupported :comment "Unsupported." :model "5550" :url "/unsupported/benq-5550.html" :interface "USB" :usbid "0x04a5" "0x2211" :status :unsupported :comment "Unsupported, see link for details." :model "5560" :interface "USB" :usbid "0x04a5" "0x2311" :status :unsupported :url "http://lists.alioth.debian.org/pipermail/sane-devel/2009-January/023447.html" :model "7400UT" :url "/unsupported/benq-7400ut.html" :interface "USB" :usbid "0x04a5" "0x2202" :status :unsupported ;******************************************************************************************** :mfg "Boeder" :model "Sm@rtScan Office" :url "/unsupported/trust-combiscan-19200.html" :interface "Parport USB" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Brother" :url "http://www.brother.com/" :model "MFC 2500" :url "/unsupported/brother-mfc-2500.html" :interface "USB" :usbid "0x04f9" "0x000a" :status :unsupported :comment "Not supported. See link for details." :model "MFC 4600" :status :unsupported :url "http://sourceforge.net/projects/brother-mfc" :interface "Parport" :comment "The parport 200x400dpi grayscale version of this scanner is unsupported. Dmitri Katchalov did some investigations on this scanner. If you want to write a backend, contact him (see link)." :model "MFC 7300c" :url "/unsupported/brother-mfc-7300.html" :interface "Parport USB" :usbid "0x04f9" "0x0106" :status :unsupported :model "MFC 9600" :url "/unsupported/brother-mfc-9600.html" :interface "USB" :usbid "0x04f9" "0x0101" :status :unsupported ;******************************************************************************************** :mfg "C-Channel" :url "http://www.c-channel.ch/" :model "MyPen Pro" :url "/unsupported/c-channel-mypen-pro.html" :interface "USB" ;:usbid "" "" :status :unsupported :comment "Probably unsupported. See link for details." :model "MyPen Light" :interface "USB" :usbid "0x0a93" "0x0005" :status :unsupported :comment "See bug #306792 for details." :model "MoneyPen II" ;:url "/unsupported/c-channel-mypen-pro.html" :interface "USB" ;:usbid "" "" :status :unsupported :comment "Probably unsupported." ;******************************************************************************************** :mfg "Canon" :url "http://www.canon.com/" :model "CanoScan 3000" :url "/unsupported/canon-3000.html" :interface "USB" :usbid "0x04a9" "0x2215" :status :unsupported :comment "GL660+GL646 based." :model "CanoScan 3000ex" :url "/unsupported/canon-3000.html" :interface "USB" :usbid "0x04a9" "0x2215" :status :unsupported :comment "GL660+GL646 based." :model "CanoScan 3000F" :url "/unsupported/canon-3000.html" :interface "USB" :usbid "0x04a9" "0x2215" :status :unsupported :comment "GL660+GL646 based, to be added to genesys backend" :model "CanoScan 4200F" :url "/unsupported/canon-4200f.html" :interface "USB" :usbid "0x04a9" "0x221b" :status :unsupported :comment "Probably unsupported. See link." :model "CanoScan 4400F" :url "/unsupported/canon-4400.html" :interface "USB" :usbid "0x04a9" "0x2228" :status :unsupported :comment "GL843 based, to be added to genesys backend" :model "CanoScan 5000F" :url "/unsupported/canon-5000f.html" :interface "USB" :usbid "0x04a9" "0x2212" :status :unsupported :comment "Unsupported. See link for details." :model "CanoScan 5200F" :url "/unsupported/canon-5200f.html" :interface "USB" :usbid "0x04a9" "0x2217" :status :unsupported :comment "Probably unsupported. See link for details." :model "CanoScan 8000F" :url "/unsupported/canon-8000f.html" :interface "USB" :usbid "0x04a9" "0x220f" :status :unsupported :comment "Not supported. See link for more information. With transparency adapter." :model "CanoScan 8400F" :url "/unsupported/canon-8400f.html" :interface "USB" :usbid "0x04a9" "0x221e" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "CanoScan 8600F" :url "/unsupported/canon-8600.html" :interface "USB" :usbid "0x04a9" "0x2229" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "CanoScan 9900F" :url "/unsupported/canon-9900f.html" :interface "USB" :usbid "0x04a9" "0x2210" :status :unsupported :comment "Probably unsupported, similar to 8000F. 3200x6400 dpi USB2. With transparency adapter." :model "CanoScan 9950F" :url "/unsupported/canon-9950f.html" :interface "USB" :usbid "0x04a9" "0x2219" :status :unsupported :comment "Probably unsupported." :model "CanoScan D646U" :url "/unsupported/canon-d646u.html" :interface "USB" :usbid "0x04a9" "0x220b" :status :unsupported :comment "Probably not supported. See link for more information and test program." :model "CanoScan D646U ex" :url "/unsupported/canon-d646u.html" :interface "USB" :usbid "0x04a9" "0x220b" :status :unsupported :comment "Probably not supported. See D646." :model "CanoScan D1230U" :url "/unsupported/canon-d1230u.html" :interface "USB" :usbid "0x04a9" "0x2209" :status :unsupported :comment "Probably not supported. " :model "CanoScan D1250U2" :url "/unsupported/canon-d1250u2.html" :interface "USB" :usbid "0x04a9" "0x220c" :status :unsupported :comment "Not supported. However, someone started working on this scanner and some information is available (see link)." :model "CanoScan D2400UF" :url "/unsupported/canon-d2400uf.html" :interface "USB" :usbid "0x04a9" "0x220a" :status :unsupported :comment "Not supported. See link." :model "CanoScan FB320U" :interface "USB" :usbid "0x04a9" "0x2201" :status :unsupported :comment "Probably not supported. No details known." :model "CanoScan FB620U" :url "/unsupported/canon-fb620u.html" :interface "USB" :usbid "0x04a9" "0x2202" :status :unsupported :comment "Probably not supported. Some information is available." :model "CanoScan FB1210U" :url "http://sourceforge.net/projects/canonscanner/" :interface "USB" :usbid "0x04a9" "0x2205" :status :unsupported :comment "Not supported. However, a stand-alone program for FreeBSD is available." :model "CanoScan LiDE 70" :url "http://www.juergen-ernst.de/info_sane.html" :interface "USB" :usbid "0x04a9" "0x2225" :status :unsupported :comment "Philips chip. Backend started, see link" :model "CanoScan LiDE 80" :url "/unsupported/canon-lide-80.html" :interface "USB" :usbid "0x04a9" "0x2214" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "CanoScan LiDE 90" :url "/unsupported/canon-lide-90.html" :interface "USB" :usbid "0x04a9" "0x1900" :status :unsupported :comment "Unsupported. See link for details." :model "CanoScan LiDE 500F" :url "/unsupported/canon-canoscan-lide-500f.html" :interface "USB" :usbid "0x04a9" "0x221f" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "CanoScan LiDE 600" :interface "USB" :url "http://www.juergen-ernst.de/info_sane.html" :usbid "0x04a9" "0x2224" :status :unsupported :comment "Philips chip. Backend started, see link" :model "CanoScan LiDE 600F" :interface "USB" :url "http://www.juergen-ernst.de/info_sane.html" :usbid "0x04a9" "0x2224" :status :unsupported :comment "Philips chip. Backend started, see link" :model "FS4000" :url "/unsupported/canon-fs4000.html" :interface "USB SCSI" :usbid "0x04a9" "0x3042" :status :unsupported :comment "Not supported. See link for more details." :model "IS 12" :url "/unsupported/canon-is-12.html" :interface "USB" :status :unsupported :comment "Probably not supported. Scanner cardridge for Canon inkjet printers." :model "IS 22" :url "/unsupported/canon-is-22.html" :interface "Parport" :status :unsupported :comment "Probably not supported. Scanner cardridge for Canon inkjet printers." :model "IS 32" :url "/unsupported/canon-is-32.html" :interface "USB" :usbid "0x04a9" "0x105d" :status :unsupported :comment "Probably not supported. Scanner cardridge for Canon inkjet printers." :model "IS 52" :url "/unsupported/canon-is-52.html" :interface "USB" :status :unsupported :comment "Probably not supported. Scanner cardridge for Canon inkjet printers." :model "ImageRunner iR1018" :url "/unsupported/canon-imagerunner.html" :interface "USB" :usbid "0x04a9" "0x269d" :status :unsupported :comment "Probably not supported. See link for details." :model "ImageRunner iR1022" :url "/unsupported/canon-imagerunner.html" :interface "USB" :usbid "0x04a9" "0x269d" :status :unsupported :comment "Probably not supported. See link for details." :model "ImageRunner iR1023" :url "/unsupported/canon-imagerunner.html" :interface "USB" :usbid "0x04a9" "0x269d" :status :unsupported :comment "Probably not supported. See link for details." :model "PIXMA MP110" :url "/unsupported/canon-pixma-mp110.html" :interface "USB" :usbid "0x04a9" "0x1700" :status :unsupported :comment "Probably not supported. See link for details." :model "PIXMA MP130" :url "/unsupported/canon-pixma-mp130.html" :interface "USB" :usbid "0x04a9" "0x1701" :status :unsupported :comment "Probably not supported. See link for details." :model "DR-2020U" :interface "USB" :status :unsupported :comment "GL84x?" ;******************************************************************************************** :mfg "Chinon" :model "DS-3000" :url "/unsupported/chinon-ds3000.html" :interface "Parport Serial Port" :status :unsupported :comment "Unsupported at the moment, but a backend is in preparation. See link." ;******************************************************************************************** :mfg "Compaq" :url "http://www.compaq.com/" :model "S200" :interface "USB" :usbid "0x049f" "0x0021" :status :unsupported :comment "Not supported. 2400x1200 dpi. One bulk-in, one bulk-out and one interrupt endpoint. Type-number: U0001-HB21, another type nr on the inside: 75100512-00" ;******************************************************************************************** :mfg "Compeye" :model "Simplex 1236C" :url "/unsupported/trust-combiscan-19200.html" :interface "Parport USB" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Corex" :url "http://www.cardscan.com/" :model "Cardscan 500" :url "/unsupported/corex-cardscan-500.html" :interface "USB" :usbid "0x08f0" "0x0001" :status :unsupported :comment "Probably not supported. Businesscard reader." :model "Cardscan 700 C" :url "/unsupported/corex-cardscan-700.html" :interface "USB" :usbid "0x08f0" "0x0004" :status :unsupported :comment "Probably not supported." ;******************************************************************************************** :mfg "Dell" :url "http://www.dell.com/" :model "A940" :interface "USB" :usbid "0x413c" "0x5106" :status :unsupported :comment "Probably rebadged Lexmark X5150. May work with sane-lexmark? See bug #312130" :model "A960" :url "/unsupported/dell-a960.html" :interface "USB" :usbid "0x413c" "0x5107" :status :unsupported :comment "Probably not supported. See link for details." :model "922" :url "/unsupported/dell-922.html" :interface "USB" :usbid "0x413c" "0x5109" :status :unsupported :comment "Probably not supported. See link for details." ;******************************************************************************************** :mfg "Epson" :url "http://www.epson.com/" :model "GT-2200" :interface "USB" :usbid "0x04b8" "0x0102" :status :unsupported :comment "Probably unsupported. No details known." :model "StylusScan 2000" :interface "USB" :usbid "0x04b8" "0x0105" :status :unsupported :comment "Probably unsupported. No details known." :model "Stylus DX4450" :url "/unsupported/epson-stylus-dx4450.html" :interface "USB" :usbid "0x04b8" "0x083f" :status :unsupported :comment "Probably unsupported. See link for details." :model "Stylus CX-5800" :interface "USB" :status :unsupported :comment "Probably unsupported at the moment. Not compatible to snapscan backend. It's not known if it may work with epson or epkowa backend." ;******************************************************************************************** :mfg "EDT (Electronic Document Technology)" :url "http://www.bizcardreader.com/" :model "BizCardReader 900C" :url "/unsupported/edt-900c.html" :interface "USB" :usbid "0x0a53" "0x5001" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "E-Lux" :comment "E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX" :model "j-6121" :interface "Parport" :status :unsupported :comment "Probably unsupported. Sold 1998. Same as E-Lux j-6121." ;******************************************************************************************** :mfg "Enhans" :comment "E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX" :model "j-6121" :interface "Parport" :status :unsupported :comment "Probably unsupported. Sold 1998. Same as E-Lux j-6121." :model "M-3630 A" :interface "Parport" :status :unsupported :comment "Probably unsupported. " ;******************************************************************************************** :mfg "Genius" :url "http://www.geniusnet.com.tw/" :url "http://www.genius-kye.com/" :model "ColorPage CS" :url "/unsupported/genius-colorpage-cs.html" :interface "SCSI" :status :unsupported :comment "Probably unsupported, see link for details." :model "ColorPage-Slim 1200 USB2" :url "/unsupported/genius-colorpage-slim-1200-usb2.html" :interface "USB" :usbid "0x0458" "0x2020" :status :unsupported :comment "GL841 based, to be added to genesys backend." :model "ColorPage HR6X Slim" :url "/unsupported/genius-colorpage-hr6x.html" :interface "USB" :usbid "0x0458" "0x2019" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "ColorPage HR7X" :url "/unsupported/genius-colorpage-hr7x.html" :interface "USB" :usbid "0x0458" "0x2018" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "ColorPage HR7XE" :url "/unsupported/genius-colorpage-hr7xe.html" :interface "USB" :usbid "0x06dc" "0x0012" :status :unsupported :comment "Unsuported. See link for details." :model "ColorPage HR8" :url "/unsupported/genius-colorpage-hr8.html" :interface "USB" :usbid "0x0458" "0x201c" :status :unsupported :comment "GL841 based, to be added to genesys backend" ;******************************************************************************************** :mfg "Guillemot" ; name a manufacturer :model "SCAN@HOME 48 USB" :url "/unsupported/teco-vm6509.html" :interface "USB" :usbid "0x080d" "0x0102" :status :unsupported :comment "Probably unsupported. See link for details." :model "Maxi Scan A4 Parallel 36 bit" :interface "Parport" :status :unsupported :comment "Probably unsupported. Identical to the Benq Prisa 620P." ;******************************************************************************************** :mfg "Hercules" ; name a manufacturer :model "SCAN@HOME 48 USB" :url "/unsupported/teco-vm6509.html" :interface "USB" :usbid "0x080d" "0x0102" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Hewlett-Packard" ; name a manufacturer :url "http://www.hp.com/" :model "Photo Scanner 1000" :url "/unsupported/hp-photo-1000.html" :interface "USB" :usbid "0x03f0" "0x1001" :status :unsupported :comment "Not supported by SANE. However, it's detected as mass storage device so just mounting it is reported to work. See link for device data." :model "Photosmart 1200 Photo" :interface "USB" :status :unsupported :comment "Probably not supported by SANE. No details known. 10x15 cm. Maybe similar to Photo Scanner 1000?" :model "Photosmart S20 (C5101A)" :url "/unsupported/hp-photosmart-s20xi.html" :interface "USB" :usbid "0x03f0" "0x0102" :status :unsupported :comment "Not supported yet by SANE. See link for details." :model "Photosmart S20xi (C7150A)" :url "/unsupported/hp-photosmart-s20xi.html" :interface "USB" :usbid "0x03f0" "0x0102" :status :unsupported :comment "Not supported yet by SANE. See link for details." :model "Photosmart C5100 series" :url "/unsupported/hp-photosmart-5100.html" :interface "USB" :usbid "0x03f0" "0x5811" :status :unsupported :comment "Not supported yet by SANE. See link for details." :model "ScanJet 2400c" :url "/unsupported/hp-scanjet-2400c.html" :interface "USB" :usbid "0x03f0" "0x0a01" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "Photosmart C3180" :url "/unsupported/hp-photosmart-3180.html" :interface "USB" :usbid "0x03f0" "0x5611" :status :unsupported :comment "Not supported yet by SANE. See link for details." :model "ScanJet 3770" :status :unsupported :interface "USB" :usbid "0x03f0" "0x2505" :comment "While an external binary-only backend exists, it works only on Linux i386. Therefore the scanner is unsupported on other platforms." :model "ScanJet 4600" :url "/unsupported/hp-scanjet-4600.html" :interface "USB" :usbid "0x03f0" "0x3005" :comment "Not supported. See link for details, or http://www.chmil.org/hp4600linux/ for code" :status :unsupported :model "ScanJet 4670" :interface "USB" :usbid "0x03f0" "0x3005" :comment "Not supported. See ScanJet 4600 entry." :status :unsupported :model "ScanJet 4850C" :url "/unsupported/hp-scanjet-4850.html" :interface "USB" :usbid "0x03f0" "0x1b05" :comment "GL841, maybe can be added to genesys backend " :status :unsupported :model "ScanJet 4890C" :url "/unsupported/hp-scanjet-4850.html" :interface "USB" :usbid "0x03f0" "0x1b05" :comment "GL843, maybe can be added to genesys backend " :status :unsupported :model "ScanJet 5530C Photosmart" :url "/unsupported/hp-scanjet-5530.html" :interface "USB" :usbid "0x03f0" "0x1605" :comment "Maybe GL841_HP, but not confirmed, maybe can be added to genesys backend" :status :unsupported :model "ScanJet 8390" :url "/unsupported/hp-scanjet-8390.html" :interface "USB" :usbid "0x03f0" "0x3805" :comment "Probably not supported. See link for details." :status :unsupported :model "ScanJet G4000" :url "/unsupported/hp-g4000.html" :interface "USB" :usbid "0x03f0" "0x4505" :comment "Probably not supported. See link for details." :status :unsupported ;******************************************************************************************** :mfg "IBM" :url "http://www.ibm.com" :model "ADF Color Scanner" :interface "Proprietary" :status :unsupported :comment "Unsupported. Uses proprietary ISA card. Maybe the same as the Plustek Spectra ADF?" ;******************************************************************************************** :mfg "IOMagic" :url "http://www.iomagic.com/" :model "MobileScan USB" :url "/unsupported/trust-combiscan-19200.html" :interface "USB Parport" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Iris" :url "http://irislink.com/" :model "IriScan" :url "/unsupported/iris-iriscan.html" :interface "USB" :usbid "0x0a53" "0x1000" :status :unsupported :comment "Unsupported. LM9832/3. See link for details." :model "IRISPen Translator Executive" :url "/unsupported/iris-irispen-translator.html" :interface "USB" :usbid "0x0f43" "0x015a" :status :unsupported :comment "Unsupported. See link for details." :model "IRISCard Pro (IBCR II)" :url "/unsupported/iris-business.html" :interface "USB" :usbid "0x0a38" "0x0301" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Kodak" :url "http://www.kodak.com" :model "Snapshot Photo Scanner 1" :interface "Parport" :status :unsupported :comment "Unsupported. FCC ID HWF96PHS" ;******************************************************************************************** :mfg "Lexmark" :url "http://www.lexmark.com/" :model "P6250" :url "/unsupported/lexmark-p6250.html" :interface "USB" :usbid "0x043d" "0x0097" :status :unsupported :comment "Unsupported. See link for details." :model "Photo 3150" :url "/unsupported/lexmark-3150.html" :interface "USB" :usbid "0x043d" "0x007d" :status :unsupported :comment "Unsupported. See link for details." :model "X74" :url "/unsupported/lexmark-x75.html" :interface "USB" :usbid "0x043d" "0x0060" :status :unsupported :comment "Unsupported. See link for details." :model "X75" :url "/unsupported/lexmark-x75.html" :interface "USB" :usbid "0x043d" "0x0060" :status :unsupported :comment "Unsupported. See link for details." :model "X75 PrinTrio" :url "/unsupported/lexmark-x75.html" :interface "USB" :usbid "0x043d" "0x0060" :status :unsupported :comment "Unsupported. See link for details." :model "X83" :url "/unsupported/lexmark-x83.html" :interface "USB" :usbid "0x043d" "0x003d" :status :unsupported :comment "Unsupported. GL640." :model "X2330" :url "/unsupported/lexmark-x2330.html" :interface "USB" :usbid "0x043d" "0x00bb" :status :unsupported :comment "Unsupported. See link for details." :model "X3450" :url "/unsupported/lexmark-x3450.html" :interface "USB" :usbid "0x043d" "0x00f6" :status :unsupported :comment "Unsupported. See link for details." :model "X5130" :url "/unsupported/lexmark-x5130.html" :interface "USB" :usbid "0x043d" "0x0065" :status :unsupported :comment "Unsupported." :model "X5150" :url "/unsupported/lexmark-x5130.html" :interface "USB" :usbid "0x043d" "0x0065" :status :unsupported :comment "Probably unsupported. See link for details." :model "X5250" :url "/unsupported/lexmark-x5250.html" :interface "USB" :usbid "0x043d" "0x0093" :status :unsupported :comment "Unsupported." :model "X6170" :url "/unsupported/lexmark-x6170.html" :interface "USB" :usbid "0x043d" "0x0072" :status :unsupported :comment "Unsupported. See link for details." :model "X7170" :interface "USB" :usbid "0x043d" "0x0098" :status :unsupported :comment "Unsupported. See bug #310889 for details." :model "X7350" :url "/unsupported/lexmark-x7350.html" :interface "USB" :usbid "0x043d" "0x00b8" :status :unsupported :comment "Unsupported. See link for details." :model "X8350" :url "/unsupported/lexmark-x8350.html" :interface "USB" :usbid "0x043d" "0x00b9" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Logitech" :model "PageScan Color" :interface "Parport" :status :unsupported :comment "Most probably unsupported." :model "PageScan USB" :url "/unsupported/logitech-pagescan-usb.html" :interface "USB" :usbid "0x046d" "0x040f" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Medion/Lifetec/Tevion/Cytron" :url "http://www.medion.com/" :url "http://www.medion.de/" :model "MD 6190" :url "/unsupported/medion-md6190.html" :interface "USB" :usbid "0x0461" "0x0392" :status :unsupported :comment "Probably unsupported. There seem to exist two different scanners with that name. See link for details." :model "MD 6190" :url "/unsupported/medion-md6190.html" :interface "USB" :usbid "0x0461" "0x037b" :status :unsupported :comment "Probably unsupported. There seem to exist two different scanners with that name. See link for details." :model "MD 40420" :url "/unsupported/tevion-md40420.html" :interface "USB" :usbid "0x05da" "0x3008" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 41260" :url "/unsupported/medion-md6190.html" :interface "USB" :usbid "0x0461" "0x037b" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 41985" :url "/unsupported/medion-md6190.html" :interface "USB" :usbid "0x0461" "0x037b" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 42666" :url "/unsupported/tevion-md40420.html" :interface "USB" :usbid "0x05da" "0x3008" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 85264" :url "http://gkall.hobby.nl/authentec.html" :interface "USB" :usbid "0x08ff" "0x2580" :status :unsupported :comment "Fingerprint sensor. See link for details." :model "MD 90009" :url "/unsupported/tevion-md90009.html" :interface "USB" :usbid "0x05da" "0x30e5" :status :unsupported :comment "Probably unsupported. See link for details." :model "MD 90070" :url "/unsupported/tevion-md90070.html" :interface "USB" :usbid "0x05da" "0x3022" :status :unsupported :comment "Unsupported. See link for details." :model "MD 90090" :url "/unsupported/tevion-md90070.html" :interface "USB" :usbid "0x05da" "0x3022" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Memorex" :url "http://www.memorex.com/" :model "6136u" :url "/unsupported/memorex-maxx-6136u.html" :interface "USB" :usbid "0x0461" "0x0346" :status :unsupported :comment "Probably unsupported." :model "6142u" :url "/unsupported/visioneer-onetouch4400.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Probably unsupported. Same as Visioneer Onetouch 4400. See link for details." :model "MaxxScan 6122" :url "/unsupported/trust-combiscan-19200.html" :interface "USB Parport" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." :model "SCF 9612P" :url "/unsupported/memorex-scf-9612p.html" :interface "Parport" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Microtek" :url "http://www.microtek.com/" :model "ArtixScan 2020" :interface "SCSI" :status :unsupported :comment "Unsupported. Same as Agfa DuoScan T2000XL?" :model "ArtixScanDI 2020" :url "/unsupported/microtek-artixscan-2020.html" :interface "USB" :usbid "0x05da" "0x202e" :status :unsupported :comment "Unsupported. See link for details." :model "Artixscan 2500f" :interface "SCSI IEEE-1384" :status :unsupported :comment "Unsupported. Same as Agfa DuoScan T2500?" :model "ArtixScan 4000tf" :interface "USB" :status :unsupported :comment "Unsupported. Uses ALI M5611B." :model "FilmScan 35" :url "/unsupported/microtek-filmscan-35.html" :interface "USB" :usbid "0x05e3" "0x0120" :status :unsupported :comment "Probably unsupported. See link for details." :model "ScanMaker 336 CX" :interface "SCSI" :status :unsupported :comment "Probably unsupported. Seems to be similar to the Microtek 330 CX and is detected by the microtek2 backend. Scanning doesn't seem to work however." :model "Scanmaker 1850S" :url "/unsupported/microtek-scanmaker-1850s.html" :interface "SCSI" :status :unsupported :comment "Unsupported. See link for details." :model "ScanMaker 3630" :url "/unsupported/microtek-scanmaker-3630.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Unsupported. Doesn't seem to be compatible to 3600 series, see link." :model "ScanMaker 3800" :url "/unsupported/microtek-scanmaker-3800.html" :interface "USB" :usbid "0x05da" "0x30ce" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 3830" :url "/unsupported/microtek-scanmaker-3830.html" :interface "USB" :usbid "0x05da" "0x30ce" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 3860" :url "/unsupported/microtek-scanmaker-3880.html" :interface "USB" :usbid "0x05da" "0x3023" :status :unsupported :comment "Unsupported. See link for more details. Appears to be similar to ScanMaker 3880." :model "ScanMaker 3880" :url "/unsupported/microtek-scanmaker-3880.html" :interface "USB" :usbid "0x05da" "0x3021" :status :unsupported :comment "Unsupported. SQ113 chip. See link for more details." :model "ScanMaker 4600" :url "/unsupported/microtek-scanmaker-4600.html" :interface "USB" :usbid "0x05da" "0x40c7" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 4700" :url "/unsupported/microtek-scanmaker-4700.html" :interface "USB" :usbid "0x05da" "0x20b4" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 4850" :url "/unsupported/microtek-scanmaker-4900.html" :interface "USB" :usbid "0x05da" "0x30d9" :status :unsupported :comment "Probably unsupported. See link for details." :model "ScanMaker 4850 II" :url "/unsupported/microtek-scanmaker-4850-2.html" :interface "USB" :usbid "0x05da" "0x3008" :status :unsupported :comment "Probably unsupported. See link for details." :model "ScanMaker 4900" :url "/unsupported/microtek-scanmaker-4900.html" :interface "USB" :usbid "0x05da" "0x30b9" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 5" :url "/unsupported/microtek-scanmaker-5600.html" :interface "SCSI" :status :unsupported :comment "Probably unsupported. See link for more details." :model "ScanMaker 5600" :url "/unsupported/microtek-scanmaker-5600.html" :interface "USB" :usbid "0x05da" "0x20a7" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 5700" :interface "USB" :usbid "0x05da" "0x20bd" :status :unsupported :comment "Unsupported. Uses ALI M5615 like the ScanMaker 4700." :model "ScanMaker 5800" :url "/unsupported/microtek-scanmaker-5800.html" :interface "USB" :usbid "0x05da" "0x3008" :status :unsupported :comment "Unsupported. See link for details." :model "ScanMaker 5800" :url "/unsupported/microtek-scanmaker-5800.html" :interface "USB" :usbid "0x05da" "0x30d8" :status :unsupported :comment "Unsupported. See link for details." :model "ScanMaker 5900" :url "/unsupported/microtek-scanmaker-5900.html" :interface "USB" :usbid "0x05da" "0x30d8" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 5950" :url "/unsupported/microtek-scanmaker-5950.html" :interface "USB" :usbid "0x05da" "0x30d8" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 6000" :url "/unsupported/microtek-scanmaker-6000.html" :interface "USB" :usbid "0x05da" "0x30e5" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 6100" :url "/unsupported/microtek-scanmaker-6100.html" :interface "USB" :usbid "0x05da" "0x30e5" :status :unsupported :comment "Unsupported. See link for more details." :model "ScanMaker 6700" :url "/unsupported/microtek-scanmaker-6700.html" :interface "USB IEEE-1394" :usbid "0x05da" "0x20c9" :status :unsupported :comment "Unsupported. See link." :model "ScanMaker 8700" :status :unsupported :url "/unsupported/microtek-scanmaker-8700.html" :interface "USB IEEE-1394" :usbid "0x05da" "0x20b1" :comment "Unsupported. See link for details. USB vendor and product ids to be checked." :model "ScanMaker 9600XL" :interface "USB IEEE-1394" :usbid "0x05da" "0x20de" :status :unsupported :comment "Probably unsupported. SCSI seems to work with microtek2 backend." :model "ScanMaker 9800XL" :url "/unsupported/microtek-scanmaker-9800.html" :interface "USB SCSI" :usbid "0x05da" "0x20de" :status :unsupported :comment "Partly unsupported. IEEE-1394 works with microtek2 backend. See link." :model "ScanMaker i320" :url "/unsupported/microtek-scanmaker-i320.html" :interface "USB" :usbid "0x05da" "0x30e6" :status :unsupported :comment "Unsupported. See link." :model "ScanMaker s400" :url "/unsupported/microtek-scanmaker-s400.html" :interface "USB" :usbid "0x05da" "0x201c" :status :unsupported :comment "Unsupported. See link." :model "ScanMaker S400" :url "/unsupported/microtek-scanmaker-s400.html" :interface "USB" :usbid "0x05da" "0x300b" :status :unsupported :comment "Unsupported. See link." :model "ScanPort 3000" :url "/unsupported/microtek-scanport-3000.html" :interface "USB" :usbid "0x04a7" "0x0224" :status :unsupported :comment "Unsupported. Vendor/Product ids: 0x04a7/0x0224. Realtek RTS8801B?. See link for details." ;******************************************************************************************** :mfg "Konica Minolta" :url "http://www.konicaminolta.com/" :model "Dual Scan III" :url "/unsupported/minolta-dual-scan-III.html" :interface "USB" :usbid "0x0686" "0x400d" :status :unsupported :comment "Unsupported. May work with vuescan. See link for details." :model "Dual Scan IV" :url "/unsupported/minolta-dual-scan-IV.html" :interface "USB" :usbid "0x132b" "0x000a" :status :unsupported :comment "Unsupported. Works with vuescan. See link for details." :model "DiMAGE Scan Elite 5400" :url "/unsupported/minolta-dse-5400.html" :interface "USB IEEE-1394" :usbid "0x0686" "0x400e" :status :unsupported :comment "Probably unsupported. May work with vuescan. See link for details." :model "DiMAGE Scan Elite 5400 2" :url "/unsupported/minolta-dse-5400-2.html" :interface "USB" :usbid "0x132b" "0x0012" :status :unsupported :comment "Probably unsupported. See link for details." :model "DiMAGE Scan Multi Pro" :url "/unsupported/minolta-dimage-scan-multi-pro.html" :interface "IEEE-1394" :status :unsupported :comment "Probably unsupported. See link for details." :model "magicolor 2480MF" :interface "USB Network" :status :unsupported :comment "Uses a different scanning protocol than the magicolor 1690MF" ;******************************************************************************************** :mfg "Mustek" ; name a manufacturer :url "http://www.mustek.com/" :url "http://www.mustek.de/" :url "http://www.mustek.com.tw/" :model "1200 III EP" :interface "Parport" :status :unsupported :comment "Probably not supported. quarlewm at jmu dot edu offers to temporarily loan such a scanner to anyone who is interested in writing a driver." :model "2400 M" :interface "USB" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :status :unsupported :comment "Probably unsupported. No details known." :model "BearPaw 2400 TA Pro" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x0400" :comment "Not supported. May be supported by mustek_usb2 backend later. See link for some information." :status :unsupported :model "BearPaw 2448 CU Pro" :url "/unsupported/mustek-bearpaw-2448-cu-pro.html" :usbid "0x055f" "0x0408" :interface "USB" :comment "Not supported. May be supported by mustek_usb2 backend later. See link for some information." :status :unsupported :model "BearPaw 4800 TA Pro" :url "/unsupported/mustek-bearpaw-4800ta-pro.html" :interface "USB" :usbid "0x055f" "0x1000" :comment "Not supported. See link for some information." :status :unsupported :model "BearPaw 4800 TA Pro II" :url "/unsupported/mustek-bearpaw-4800ta-pro-ii.html" :interface "USB" :usbid "0x055f" "0x040a" :comment "Not supported. May be supported by mustek_usb2 backend later. See link for some information." :status :unsupported :model "BearPaw 6400 TA Pro" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x040b" :comment "Not supported. May be supported by mustek_usb2 backend later. See link for some information." :status :unsupported :model "Paragon 800 II EP" :interface "Parport" :status :unsupported :comment "Not supported. Maybe similar to 600 II EP (SCSI_over-parport)? In this case it could be supported by the mustek SCSI backend." :model "ScanExpress 600 USB" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x0873" :status :unsupported :comment "Unsupported. Programming information is available." :model "ScanExpress 1200 USB" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x0003" :status :unsupported :comment "Unsupported. Programming information is available." :model "ScanExpress 1200 USB Plus" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :usbid "0x055f" "0x0007" :status :unsupported :comment "Unsupported." :model "ScanExpress 12000 P" :url "http://penguin-breeder.org/?page=mustek_pp" :interface "Parport" :status :unsupported :comment "Not supported. Asic 1505/05." :model "ScanExpress A3 EP" :interface "Parport" :status :unsupported :comment "Not supported. Maybe it will be supported by the mustek_pp backend in future." :model "ScanExpress CardSmart" :url "http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED" :interface "USB" :status :unsupported :comment "Probably unsupported. USB business card scanner. Maybe works as USB storage device?" :model "ScanMagic 9636P" :url "http://lists.alioth.debian.org/pipermail/sane-devel/2003-May/007682.html" :interface "Parport" :status :unsupported :comment "Probably not supported. Same as Mustek 12000 P?. ASIC 1505." ;******************************************************************************************** :mfg "NEC" :url "http://www.nevt.co.jp/" :model "Petiscan" :url "/unsupported/nec-petiscan.html" :interface "USB" :usbid "0x0475" "0x0100" :status :unsupported :comment "Most probably unsupported. See link for details. Vendor ID is Relisys/Teco. Not known if it is similar to other Relisys/Teco USB scanners." ;******************************************************************************************** :mfg "Nikon" :url "http://www.nikon.com/" :model "LS-9000 ED" :url "/unsupported/nikon-ls9000-ed.html" :interface "IEEE-1394" :status :unsupported :comment "Probably not supported. See link for details. Possibly similar to LS-8000 ED." ;******************************************************************************************** :mfg "Olivetti" :url "http://www.olivetti.com" :model "Job-Jet M400" :url "/unsupported/olivetti-job-jet-m400.html" :interface "USB" :usbid "0x0b3c" "0xa880" :status :unsupported :comment "Probably not supported. See link for details." ;******************************************************************************************** :mfg "Olympus" :url "http://www.olympus.com" :model "ES-10P" :url "http://lists.alioth.debian.org/pipermail/sane-devel/2008-December/023326.html" :interface "Parport" :status :unsupported :model "ES-10S" :url "/unsupported/olympus-es10s.html" :interface "SCSI" :status :unsupported :comment "Probably not supported. See link for details." ;******************************************************************************************** :mfg "Optoelectronics" :model "Barcode scanner" :interface "USB" :usbid "0x065a" "0x0001" :status :unsupported :comment "Probably not supported." ;******************************************************************************************** :mfg "Optrox" :model "PhotoMaker 3C" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Parport" :status :unsupported :model "PhotoMaker 3E" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Parport" :status :unsupported :model "PhotoMaker 3F" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Proprietary" :status :unsupported :comment "Special ISA card" :model "PhotoMaker 3S" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Parport" :status :unsupported :model "PhotoMaker 6E" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Parport" :status :unsupported :model "PhotoMaker 6F" :url "http://www.df.lth.se/~triad/krad/optrox/" :interface "Proprietary" :status :unsupported :comment "Special ISA card" ;******************************************************************************************** :mfg "Panasonic" :model "KV-SS905C" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool." :model "KV-S2055W" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S2055L" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S2065W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S3065CW" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S3065CL" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S3085" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S3105C" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool." :model "KV-S6040W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S6045W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S6050W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S6055W" :interface "SCSI" :status :unsupported :comment "might be supported by matsushita backend." :model "KV-S7065C" :interface "USB SCSI" :status :unsupported :comment "might be supported by matsushita backend." ;******************************************************************************************** :mfg "Pentax" :model "DSmobile USB" :url "/unsupported/syscan-travelscan-pro.html" :interface "USB" :usbid "0x0a82" "0x2000" :status :unsupported :comment "Probably not supported. Some information is available." ;******************************************************************************************** :mfg "PIE" :url "http://www.scanace.com/" :comment "Pacific Image Electronics" :model "Primefilm 1800u" :url "/unsupported/pie-1800u.html" :interface "USB" :usbid "0x05e3" "0x0120" :status :unsupported :comment "Not supported. See link for details." :model "Primefilm 2700" :interface "USB" :status :unsupported :url "http://lists.alioth.debian.org/pipermail/sane-devel/2009-January/023442.html" :model "Primefilm 3600PRO" :interface "USB IEEE-1394" :status :unsupported :comment "Probably not supported. " :model "Powerslide 3600" :url "/unsupported/reflecta-digitdia-3600.html" :interface "USB IEEE-1394" :usbid "0x05e3" "0x0142" :status :unsupported :comment "Probably unsupported. Film scanner that can scan directly from the magazine." :model "PF3650 Pro3 Film Scanner" :url "/unsupported/pie-pf3650.html" :interface "USB IEEE-1394" :usbid "0x05e3" "0x0143" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** ;:mfg "Packard Bell" ;******************************************************************************************** :mfg "Plustek" :url "http://www.plustek.de/" :url "http://www.plustek.com/" :model "OpticFilm 7200" :url "/unsupported/plustek-opticfilm-7200.html" :interface "USB" :usbid "0x07b3" "0x0807" :status :unsupported :comment "GL842 based, maybe to be added to genesys backend" :model "OpticFilm 7200i" :interface "USB" :usbid "0x07b3" "0x0c04" :status :unsupported :comment "GL843 based, maybe to be added to genesys backend" :model "OpticPro A3U" :interface "USB" :status :unsupported :comment "Uses Plustek ASIC P99002" :model "OpticPro S6" :interface "USB" :status :unsupported :comment "Uses RealTek chipset (RTL8801D)" :model "OpticPro S12" :url "/unsupported/plustek-opticpro-st12.html" :interface "USB" :usbid "0x07b3" "0x0600" :status :unsupported :comment "Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend." :model "OpticPro ST12" :url "/unsupported/plustek-opticpro-st12.html" :interface "USB" :usbid "0x07b3" "0x0600" :status :unsupported :comment "Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend." :model "OpticPro ST16" :url "/unsupported/plustek-opticpro-st16.html" :interface "USB" :usbid "0x07b3" "0x0600" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "OpticPro UA18" :interface "USB" :status :unsupported :comment "Probably LM983x based." :model "OpticPro S24" :url "/unsupported/plustek-opticpro-st24.html" :interface "USB" :usbid "0x07b3" "0x0601" :status :unsupported :comment "Product id 0x0601 is unsupported but may be supported by the genesys backend in future /GL646). Product id 0x040e is supported by the gt68xx backend." :model "OpticPro ST24" :url "/unsupported/plustek-opticpro-st24.html" :interface "USB" :usbid "0x07b3" "0x0601" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "OpticPro S28" :interface "USB" :url "/unsupported/plustek-opticpro-s28.html" :usbid "0x07b3" "0x0801" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticPro ST28" :url "/unsupported/plustek-opticpro-s28.html" :interface "USB" :usbid "0x07b3" "0x0801" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticPro ST28" :url "/unsupported/plustek-opticpro-st28.html" :interface "USB" :usbid "0x07b3" "0x0802" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "Umax AstraScan 4750" :url "/unsupported/umax-astrscan-4750.html" :interface "USB" :usbid "0x07b3" "0x0802" :status :unsupported :comment "GL841 based, to be added to genesys backend, rebadged Plustek ST28" :model "OpticPro ST48" :url "/unsupported/plustek-opticpro-st48.html" :interface "USB" :usbid "0x07b3" "0x0800" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticPro ST64" :url "/unsupported/plustek-opticpro-st64.html" :interface "USB" :usbid "0x07b3" "0x0c00" :status :unsupported :comment "GL843 based, maybe to be added to genesys backend" :model "OpticPro ST64+" :url "/unsupported/plustek-opticpro-st64plus.html" :interface "USB" :usbid "0x07b3" "0x0c03" :status :unsupported :comment "GL843 based. See link for more details." :model "PL 806" :url "/unsupported/plustek-pl806.html" :interface "USB" :usbid "0x07b3" "0x0c0c" :status :unsupported :comment "Unsupported. See link for more details." :model "SmartOffice PL 812" :url "/unsupported/plustek-pl812.html" :interface "USB" :usbid "0x07b3" "0x0c0d" :status :unsupported :comment "Unsupported. See link for more details." :model "OpticSlim 500" :url "/unsupported/plustek-opticslim-500.html" :interface "USB" :usbid "0x07b3" "0x0458" :status :unsupported :comment "Unsupported. See link for more details." :model "OpticSlim 2420" :url "/unsupported/plustek-opticslim-2420.html" :interface "USB" :usbid "0x07b3" "0x0806" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticSlim 2420+" :url "/unsupported/plustek-opticslim-2420plus.html" :interface "USB" :usbid "0x07b3" "0x0914" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "OpticWorks 2000" :interface "Parport" :status :unsupported :comment "Multifunction device. No further information available." :model "OptiCard 600+" :interface "USB" :status :unsupported :comment "Business card reader. No further information available." :model "ScanCopy 115" :url "/unsupported/plustek-scancopy-115.html" :interface "USB" :usbid "0x07b3" "0x081c" :status :unsupported :comment "GL841 based, to be added to genesys backend" :model "Spectra ADF" :interface "Proprietary" :status :unsupported :comment "Unsupported. Uses proprietary ISA card that also provides power and is labelled GPS-1 PAGE-A from Taiwan. Other labels on the scanner include ADF Color Scanner and SF600AS. Maybe the same as the IBM ADF Color Scanner?" :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0005" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0007" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x000f" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0012" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0014" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." :model "Unknown Plustek Device" :interface "USB" :usbid "0x07b3" "0x0016" :status :unsupported :comment "Probably unsupported. Scanner name not known yet." ;******************************************************************************************** :mfg "PLANon" :url "http://www.planon.com/" :model "DocuPen RC800" :interface "USB" :status :unsupported :comment "Probably not supported. No details known." :model "DocuPen R700" :url "/unsupported/planon-docupen-r700.html" :interface "USB" :usbid "0x10c4" "0xea60" :status :unsupported :comment "Probably not supported. See link for details." :model "DocuPen (DPEN-BW)" :interface "USB" :status :unsupported :comment "Probably not supported. No details known." ;******************************************************************************************** :mfg "Primax" :url "http://www.primax.nl/" :model "Colorado 600U" :url "/unsupported/primax-colorado-600u.html" :interface "USB" :usbid "0x0461" "0x0341" :status :unsupported :comment "Not supported. Some information is available." :model "Colorado 1200p" :interface "Parport" :url "http://home2.swipnet.se/~w-25069/pxscan.html" :status :unsupported :comment "Unsupported by SANE. But is reported to partly work with pxscan. See link." :model "Colorado 1200u" :interface "USB" :usbid "0x0461" "0x0361" :status :unsupported :comment "Probably unsupported. No details known." :model "Primascan Colorado 2600u" :url "/unsupported/visioneer-onetouch4400.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Unsupported. Same as Visioneer Onetouch 4400. See link for details." :model "Colorado Direct 600" :url "http://home2.swipnet.se/~w-25069/pxscan.html" :interface "Parport" :status :unsupported :comment "Not supported. However, a stand-alone program is available." :model "Colorado Direct 9600" :url "http://home2.swipnet.se/~w-25069/pxscan.html" :interface "Parport" :status :unsupported :comment "Not supported. However, a stand-alone program is available." :model "Colorado USB 9600" :url "/unsupported/primax-colorado-usb-9600.html" :interface "USB" :usbid "0x0461" "0x0340" :status :unsupported :comment "Not supported. See link for details." :model "G2-300" :interface "USB" :usbid "0x0461" "0x0300" :status :unsupported :comment "Probably unsupported. No details known." :model "G2-300 #2" :interface "USB" :usbid "0x0461" "0x0302" :status :unsupported :comment "Probably unsupported. No details known." :model "G2E-300" :interface "USB" :usbid "0x0461" "0x0301" :status :unsupported :comment "Probably unsupported. No details known." :model "G2E-300 #2" :usbid "0x0461" "0x0303" :interface "USB" :status :unsupported :comment "Probably unsupported. No details known." :model "G2-600" :usbid "0x0461" "0x0380" :interface "USB" :status :unsupported :comment "Probably unsupported. No details known." :model "G2-600 #2" :interface "USB" :usbid "0x0461" "0x0382" :status :unsupported :comment "Probably unsupported. No details known." :model "G2E-600" :usbid "0x0461" "0x0383" :interface "USB" :status :unsupported :comment "Probably unsupported. No details known." :model "OneTouch 5300" :interface "Parport" :status :unsupported :comment "Not supported." :model "ReadyScan 636i" :usbid "0x0461" "0x0381" :interface "USB" :status :unsupported :comment "Probably unsupported. No details known." :model "Slim-Line 1200" :interface "USB" :status :unsupported :comment "Maybe GL646. Maybe similar to Medion MD 6228?" :model "Onetouch 8920" :url "/unsupported/visioneer-onetouch8920.html" :interface "USB" :usbid "0x0461" "0x0371" :status :unsupported :comment "Not supported. Look similar to Visioneer Onetouch 8920 (same USB product id)." ;******************************************************************************************** :mfg "Prolink" :url "http://www.fida.com/" :model "Winscan Pro 2448U" :url "/unsupported/prolink-2448u.html" :interface "USB" :usbid "0x06dc" "0x0014" :status :unsupported :comment "Not supported. Some information is available. RealTek RTS8801." :model "Winscan Pro 2000" :interface "USB Parport" :status :unsupported :comment "Not supported. No further information available." ;******************************************************************************************** :mfg "Quato" :url "http://www.quato.de/" :model "X-Finity" :interface "SCSI" :status :unsupported :comment "Probably not supported. No details yet. Originally manufactured by PFU?" :model "X-Finity Ultra" :interface "USB IEEE-1394" :status :unsupported :comment "Probably not supported. No details yet." ;******************************************************************************************** :mfg "Reflecta" :model "DigitDia 3600" :url "/unsupported/reflecta-digitdia-3600.html" :interface "USB IEEE-1394" :usbid "0x05e3" "0x0142" :status :unsupported :comment "Film scanner that can scan directly from the magazine." :model "iScan 1800" :url "/unsupported/reflecta-iscan-1800.html" :interface "USB" :usbid "0x05e3" "0x0120" :status :unsupported :comment "Probably unsupported. See link for details." :model "ProScan 4000" :url "/unsupported/reflecta-proscan-4000.html" :interface "USB IEEE-1394" :usbid "0x05e3" "0x0143" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Relisys" :model "Eclipse 1200U" :url "/unsupported/relisys-eclipse-1200u.html" :interface "USB" :usbid "0x0475" "0x0103" :status :unsupported :comment "Probably unsupported. See link for details." :model "Scorpio Ultra 3" :url "/unsupported/relisys-scorpio-ultra3.html" :interface "USB" :usbid "0x0475" "0x0210" :status :unsupported :comment "Probably unsupported. See link for details." :model "Episode" :url "/unsupported/relisys-episode.html" :interface "USB" :usbid "0x0475" "0x0103" :status :unsupported :comment "Probably unsupported. See link for details." :model "AVEC II E3" :interface "Parport" :status :unsupported :comment "Parport version of AVEC II S3?. See bug #304992 for details" ;******************************************************************************************** :mfg "Samsung" :model "SCX-4725FN" :url "/unsupported/samsung-scx-4725.html" :interface "USB" :usbid "0x04e8" "0x341f" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** :mfg "Scanshell" :model "800N" :url "/unsupported/scanshell-800n.html" :interface "USB" :usbid "0x0a82" "0x6605" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** :mfg "Sicos" :model "DMS 2000" :url "mailto:ehaase@inf.fu-berlin.de" :interface "proprietary" :status :unsupported :comment "Not supported until now. Work on a backend has started, contact the author for details (see link)" ;******************************************************************************************** :mfg "Siemens" ; name a manufacturer :url "http://www.siemens.com/" :model "ID Mouse Professional" :interface "USB" :usbid "0x0681" "0x0005" :status :unsupported :comment "Not supported." :model "Cherry FingerTIP ID Board - Sensor" :interface "USB" :usbid "0x0681" "0x0010" :status :unsupported :comment "Not supported." ;******************************************************************************************** :mfg "SmartDisk" :model "SmartScan 3600" :interface "USB IEEE-1394" :status :unsupported :comment "Probably not supported. Same as PIE Primefilm 2600 PRO." ;******************************************************************************************** :mfg "Spot Technology" :comment "Spot seems have gone out of business." :model "Maxiscan A4" :url "http://www.el-profesor.net/spoonset/" :interface "proprietary" :status :unsupported :comment "Not supported until now. Work on a backend has started, see link for more information." :model "ScanTak 2c" :url "http://www.el-profesor.net/spoonset" :interface "proprietary" :status :unsupported :comment "Not supported. Work on a backend has started, see link for more information." :model "ScanTak 3c" :url "http://www.el-profesor.net/spoonset" :interface "proprietary" :status :unsupported :comment "Not supported. Work on a backend has started, see link for more information." ;******************************************************************************************** :mfg "Syscan" :model "TravelScan FS-531" :url "/unsupported/syscan-travelscan-fs531.html" :interface "USB" :usbid "0x0a82" "0x0530" :status :unsupported :comment "Not supported. May work with the Plustek backend in future. See link for details." :model "TravelScan Pro" :url "/unsupported/syscan-travelscan-pro.html" :interface "USB" :usbid "0x0a82" "0x2000" :status :unsupported :comment "Probably not supported. Some information is available." ;******************************************************************************************** :mfg "Tamarack" :model "Artiscan 9600" ; name models for above-specified mfg. :interface "Parport" :status :unsupported :url "http://www.autistici.org/tamarhack/" :comment "Unsupported at the moment. See link for a project for that scanner taht may support it in future." :model "Artiscan 9600 pro 36" ; name models for above-specified mfg. :interface "Parport" :status :unsupported :url "http://www.autistici.org/tamarhack/" :comment "Unsupported at the moment. See link for a project for that scanner." :model "Artiscan 2400FS" :url "/unsupported/tamarack-artiscan-2400.html" :interface "USB" :usbid "0x05e3" "0x0100" :status :unsupported :comment "Unsupported. See link for more information." ;******************************************************************************************** :mfg "TCE" :comment "Brasilian vendor." :url "http://www.tce.com.br/" :model "MK600U" :url "/unsupported/memorex-maxx-6136u.html" :interface "USB" :usbid "0x0461" "0x0346" :status :unsupported :comment "Not supported. Some information is available." :model "S450" :url "http://home2.swipnet.se/~w-25069/pxscan.html" :interface "Parport" :status :unsupported :comment "Not supported by SANE but is reported to work with pxscan (see link)." ;******************************************************************************************** :mfg "Teco" :url "http://www.tecoimage.com.tw/" :model "VM6509F" :url "/unsupported/teco-vm6509.html" :interface "USB" :usbid "0x080d" "0x0102" :status :unsupported :comment "Probably unsupported. See link for details." ;******************************************************************************************** :mfg "Tiny" :model "FU661E" :url "/unsupported/visioneer-onetouch4400.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "Trust" :url "http://www.trust-site.com" :model "CombiScan 19200" :url "/unsupported/trust-combiscan-19200.html" :interface "Parport USB" :usbid "0x05cb" "0x1483" :status :unsupported :comment "Unsupported. See link for details." :model "EasyScan 19200" :url "http://lists.alioth.debian.org/pipermail/sane-devel/2008-October/022955.html" :interface "Parport" :status :unsupported :model "SCSI Scan 19200 -Excellence Series-" :url "/unsupported/trust-scsi-scan-19200.html" :interface "SCSI" :status :unsupported :comment "Unsupported. See link for details." ;******************************************************************************************** :mfg "UMAX" :url "http://www.umax.com/" :model "Astra 2500" :url "/unsupported/umax-astra-2500.html" :interface "USB" :usbid "0x0461" "0x0374" :status :unsupported :comment "Probably not supported. See link for details." :model "Astra 2850" :url "/unsupported/plustek-opticpro-st24.html" :interface "USB" :usbid "0x07b3" "0x0601" :status :unsupported :comment "Probably not supported. Same IDs as Plustek OpticPro ST24. See link for details." :model "Astra 3000" :url "/unsupported/umax-astra-3000.html" :interface "USB" :usbid "0x0461" "0x038a" :status :unsupported :comment "Probably not supported. See link for details." :model "Astra 3600" :url "/unsupported/umax-astra-3600.html" :interface "USB" :usbid "0x0461" "0x038a" :status :unsupported :comment "Probably not supported. See link for details." :model "Astra 4000" :url "/unsupported/umax-astra-4000.html" :interface "USB" :usbid "0x1606" "0x1030" :status :unsupported :comment "Not supported. See link for details." :model "Astra 4100" :url "/unsupported/umax-astra-4100.html" :interface "USB" :usbid "0x0461" "0x038c" :status :unsupported :comment "Not supported, to be added to genesys backend." :model "Astra 4500" :url "/unsupported/umax-astra-4500.html" :interface "USB" :usbid "0x0638" "0x0a10" :status :unsupported :comment "GL646 based, to be added to genesys backend. Avision iVina FB1600 clone" :model "Astra 4600" :interface "USB" :status :unsupported :comment "Probably not supported, no details known." :model "Astra 4700" :url "/unsupported/umax-astra-4700.html" :interface "USB" :usbid "0x0638" "0x0a20" :status :unsupported :comment "GL646/GL660 based. Avision iVina FB1800 clone." :model "Astra 6700" :interface "USB" :status :unsupported :comment "Not supported. No chipset information available. Same as Avision iVina FB2400." :model "AstraSlim" :url "/unsupported/umax-astraslim.html" :usbid "0x080d" "0x0104" :interface "USB" :status :unsupported :comment "Probably not supported currently. See link for more details." :model "AstraSlim 1200" :url "/unsupported/umax-astraslim-1200.html" :interface "USB" :usbid "0x080d" "0x0110" :status :unsupported :comment "See link for more details." :model "AstraSlim 6000" :url "/unsupported/umax-astraslim-6000.html" :interface "USB" :usbid "0x080d" "0x0104" :status :unsupported :comment "Probably not supported currently. See link for more details." :model "Nete3470'" :interface "Parport" :status :unsupported :comment "Probably not supported. No details known.." :model "Powerlook 180" :url "/unsupported/umax-powerlook-180.html" :interface "USB" ;:usbid "0x3902" "0xc470" #correct? :status :unsupported :comment "Probably not supported. See link for details." :model "Powerlook 1000 USB" :interface "USB" :status :unsupported :comment "Probably not supported. No further information available." ;******************************************************************************************** :mfg "Vantas" :model "3000" :url "/unsupported/visioneer-onetouch4800.html" :interface "USB" :usbid "0x04a7" "0x0224" :status :unsupported :comment "Not supported. See link for more details." ;******************************************************************************************** :mfg "Visioneer" :url "http://www.visioneer.com/" :model "6200" :interface "USB" :usbid "0x0461" "0x0345" :status :unsupported :comment "Not supported. Is reported to use the E5 chipset. Uses a Primax ID. Looks similar to Primascan Colorado 2600u." :model "6200 EPP/USB" :interface "USB" :usbid "0x04a7" "0x0311" :status :unsupported :comment "Not supported. Id is from Primax? Yet another scanner with the same name?" :model "9420" :url "/unsupported/visioneer-9420.html" :interface "USB" :usbid "0x0461" "0x03a8" :status :unsupported :comment "Unsupported. See link for details." :model "9450 USB" :url "/unsupported/visioneer-9450-usb.html" :interface "USB" :usbid "0x04a7" "0x0421" :status :unsupported :comment "Unsupported. See link for details." :model "Onetouch 4400" :url "/unsupported/visioneer-onetouch4400.html" :interface "USB" :usbid "0x0461" "0x0347" :status :unsupported :comment "Not supported. E5 chipset? See link for more details." :model "OneTouch 4800 USB" :url "/unsupported/visioneer-onetouch4800.html" :interface "USB" :usbid "0x04a7" "0x0224" :status :unsupported :comment "Unsupported. Seems to use Realtek RTS8801B. Same as Microtek Scanport 3000. See link for details." :model "OneTouch 5300 USB" :url "/unsupported/visioneer-onetouch5300.html" :interface "USB" :usbid "0x04a7" "0x0226" :status :unsupported :comment "Not supported. Chipset is RTS8801B(?). See link for output of /proc/bus/usb/devices." :model "OneTouch 5300" :interface "USB" :usbid "0x04a7" "0x0221" :status :unsupported :comment "Not supported. Yet another scanner with this name?" :model "OneTouch 5800 USB" :url "/unsupported/visioneer-onetouch5800.html" :interface "USB" :usbid "0x04a7" "0x0226" :status :unsupported :comment "Unsupported. 48 bit scanner, doesn't work with viceo backend. RTS8801C." :model "OneTouch 6600" :url "/unsupported/visioneer-onetouch6600.html" :interface "USB" :usbid "0x04a7" "0x022a" :status :unsupported :comment "Unsupported. See link for details." :model "Onetouch 7100" :url "/unsupported/visioneer-onetouch7100.html" :interface "USB" :usbid "0x04a7" "0x0229" :status :unsupported :comment "GL646 based, to be added to genesys backend" :model "Onetouch 7700" :url "/unsupported/visioneer-onetouch7700.html" :interface "USB" :usbid "0x04a7" "0x0380" :status :unsupported :comment "LM9832/3 based, to be added to plustek backend" :model "OneTouch 8100" :url "/unsupported/visioneer-onetouch8100.html" :interface "USB" :usbid "0x04a7" "0x0321" :status :unsupported :comment "Unsupported. See link for details." :model "Onetouch 8700" :url "/unsupported/visioneer-onetouch8920.html" :interface "USB" :usbid "0x04a7" "0x0371" :status :unsupported :comment "Not supported. See link for details." :model "Onetouch 8900" :url "/unsupported/visioneer-onetouch8920.html" :interface "USB" :usbid "0x04a7" "0x0371" :status :unsupported :comment "Not supported. Same as 8920 but without TA?" :model "Onetouch 8920" :url "/unsupported/visioneer-onetouch8920.html" :interface "USB" :usbid "0x04a7" "0x0371" :status :unsupported :comment "Not supported. Same as 8700 and 8900 but includes a TA. Uses a Primax ID. Chipset is RTS8801C. See link for output of /proc/bus/usb/devices." :model "Onetouch 9000" :url "/unsupported/visioneer-onetouch9020.html" :interface "USB" :usbid "0x04a7" "0x022c" :status :unsupported :comment "Not supported. See link for details." :model "Onetouch 9020" :url "/unsupported/visioneer-onetouch9020.html" :interface "USB" :usbid "0x04a7" "0x022c" :status :unsupported :comment "Not supported. See link for details." :model "Onetouch 9320" :url "/unsupported/visioneer-onetouch9320.html" :interface "USB" :usbid "0x04a7" "0x0362" :status :unsupported :comment "Probably not supported. See link for details." :model "Onetouch Pro 8800" :url "/unsupported/visioneer-onetouch8820.html" :interface "USB" :usbid "0x04a7" "0x0410" :status :unsupported :comment "Probably not supported. See link for details." :model "Onetouch Pro 8820" :url "/unsupported/visioneer-onetouch8820.html" :interface "USB" :usbid "0x04a7" "0x0410" :status :unsupported :comment "Probably not supported. See link for details." :model "PaperPort 3100b" :url "/unsupported/visioneer-paperport-3100b.html" :interface "Parport" :status :unsupported :comment "Most probably not supported. See link for details." :model "PaperPort 6100" :interface "Parport" :status :unsupported :comment "Most probably not supported. More details would be appreciated." :model "PaperPort OneTouch" :url "/unsupported/visioneer-paperport-onetouch.html" :interface "Parport" :status :unsupported :comment "Most probably not supported. See link for details." :model "Strobe Pro USB" :url "/unsupported/visioneer-strobe-pro-usb.html" :interface "USB" :usbid "0x04a7" "0x0102" :status :unsupported :comment "Not supported. See link for details." ;******************************************************************************************** :model "4800 One Touch" :url "/unsupported/xerox-4800-onetouch.html" :interface "USB" :usbid "0x04a7" "0x03a0" :status :unsupported :comment "Unsupported. See link for details. Different id compared to One Touch 4800?" :model "DocuImage 620S" :url "/unsupported/xerox-docuimage-620s.html" :interface "SCSI" :status :unsupported :comment "Not supported. See link for more details." :model "DocuMate 510" :url "/unsupported/xerox-documate-510.html" :interface "USB" :status :unsupported :usbid "0x04a7" "0x0446" :comment "Not supported. See link for more details." :model "DocuMate 510" :url "/unsupported/xerox-documate-510.html" :interface "USB" :status :unsupported :usbid "0x04a7" "0x047c" :comment "Not supported. See link for more details. Yet another USB id." :model "One Touch 4800" :url "/unsupported/visioneer-onetouch4800.html" :interface "USB" :usbid "0x04a7" "0x0224" :status :unsupported :comment "Unsupported. See link for details. Different id compared to 4800 One Touch?" :model "WorkCentre 470cx" :url "/unsupported/xerox-workcentre-470cx.html" :interface "Parport" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre M15i" :url "/unsupported/xerox-workcentre-m15i.html" :interface "USB" :usbid "0x0924" "0xffef" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre XK35c" :url "/unsupported/xerox-workcentre-xk35c.html" :interface "USB Parport" :usbid "0x043d" "0x0020" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre XK50cx" :url "/unsupported/xerox-workcentre-xk50cx.html" :interface "USB" :usbid "0x04e8" "0x3903" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre Pro 412" :url "/unsupported/xerox-workcentre-pro412.html" :interface "USB Parport" :usbid "0x043d" "0x4303" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre PE16" :url "/unsupported/xerox-workcentre-pe16.html" :interface "USB Parport" :usbid "0x0924" "0x4220" :status :unsupported :comment "Not supported. See link for more details." :model "WorkCentre PE120i" :url "/unsupported/xerox-workcentre-pe120i.html" :interface "USB" :usbid "0x0924" "0x4237" :status :unsupported :comment "Not supported. See link for more details." ;******************************************************************************************** ;******************************************************************************************** ;******************************************************************************************** :devicetype :vidcam :mfg "Biolux" :model "654 (micrOcular)" :url "/unsupported/biolux-654.html" :interface "USB" :usbid "0x0923" "0x010f" :status :unsupported :comment "Not supported yet. See link for more details." ;******************************************************************************************** :mfg "Grandtek Scopecam" :model "8x30 Binocular & Digital Camera" :url "/unsupported/grandtech-scopecam.html" :interface "USB" :usbid "0x0797" "0x801c" :status :unsupported :comment "Not Supported yet. See link for more details." ;******************************************************************************************** ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. ; ; SANE Backend specification file ; ; It's basically emacs-lisp --- so ";" indicates comment to end of line. ; All syntactic elements are keyword tokens, followed by a string or ; keyword argument, as specified. ; ; ":backend" *must* be specified. ; All other information is optional (but what good is the file without it?). ; :backend "v4l" ; name of backend :version "1.0-3" ; version of backend :manpage "sane-v4l" ; name of manpage (if it exists) :url "mailto:henning@meier-geinitz.de" ; backend's web page :devicetype :api ; start of a list of devices.... ; other types: :stillcam, :vidcam, ; :meta, :api :desc "Interface to Video For Linux API" ; describe a non-hardware device :comment "Supports video cameras and other devices accessed by the v4l kernel API, e.g. bttv devices. Quite a lot of known bugs." ; :comment and :url specifiers are optional after :mfg, :model, :desc, ; and at the top-level. :backend "xerox_mfp" :version "1.0-13" :manpage "sane-xerox_mfp" :devicetype :scanner :mfg "Xerox" :url "http://www.office.xerox.com/" :model "Phaser 6110MFP" :interface "USB" :usbid "0x0924" "0x3d5d" :status :good :model "Phaser 3200MFP" :interface "USB" :usbid "0x0924" "0x3da4" :status :complete :url "http://www.office.xerox.com/multifunction-printer/multifunction-under-30ppm/phaser-3200mfp/spec-enus.html" :model "WorkCentre 3119 Series" :interface "USB" :usbid "0x0924" "0x4265" :status :good :model "WorkCentre 4118 Series" :interface "USB" :usbid "0x0924" "0x420c" :status :good :model "WorkCentre 3210" :interface "USB" :usbid "0x0924" "0x4293" :status :good :model "WorkCentre 3220" :interface "USB" :usbid "0x0924" "0x4294" :status :good :mfg "Dell" :url "http://www.dell.com/" :model "Dell MFP Laser Printer 1815dn" :interface "USB" :usbid "0x413c" "0x5124" :status :good :mfg "Samsung" :url "http://www.samsung.com" :model "SCX-4x16" :interface "USB" :usbid "0x04e8" "0x3409" :status :untested :model "SCX-6x20" :interface "USB" :usbid "0x04e8" "0x340d" :status :untested :model "MFP-560" :interface "USB" :usbid "0x04e8" "0x340e" :status :untested :model "MFP-750" :interface "USB" :usbid "0x04e8" "0x340f" :status :untested :model "SCX-4x20" :interface "USB" :usbid "0x04e8" "0x3412" :status :untested :model "SCX-4100" :interface "USB" :usbid "0x04e8" "0x3413" :status :good :model "SCX-4x21" :interface "USB" :usbid "0x04e8" "0x3419" :status :untested :model "SCX-5x30" :interface "USB" :usbid "0x04e8" "0x341a" :status :untested :model "SCX-4200" :interface "USB" :usbid "0x04e8" "0x341b" :status :good :model "CLX-3160" :interface "USB" :usbid "0x04e8" "0x341c" :status :untested :model "SCX-6x22" :interface "USB" :usbid "0x04e8" "0x341d" :status :untested :model "SCX4725" :interface "USB" :usbid "0x04e8" "0x341f" :status :untested :model "SCX4725-FN" :interface "USB" :usbid "0x04e8" "0x341f" :status :good :model "SCX-6x45" :interface "USB" :usbid "0x04e8" "0x3420" :status :untested :model "CLX-8380" :interface "USB" :usbid "0x04e8" "0x3421" :status :untested :model "CLX-2160" :interface "USB" :usbid "0x04e8" "0x3425" :status :good :model "SCX-4500" :interface "USB" :usbid "0x04e8" "0x3426" :status :good :model "CLX-6200" :interface "USB" :usbid "0x04e8" "0x3427" :status :untested :model "CLX-6240" :interface "USB" :usbid "0x04e8" "0x3428" :status :untested :model "SCX-6x55" :interface "USB" :usbid "0x04e8" "0x3429" :status :untested :model "CLX-3170fn (CLX-3170 Series)" :interface "USB" :usbid "0x04e8" "0x342a" :status :good :model "CLX-3175FW" :interface "USB" :usbid "0x04e8" "0x342a" :status :good :model "SCX-4500W" :interface "USB Ethernet" :usbid "0x04e8" "0x342b" :status :basic :model "SCX-4824 (SCX-4x24 Series)" :interface "USB" :usbid "0x04e8" "0x342c" :status :good :model "SCX-4828FN (SCX-4x28 Series)" :interface "USB" :usbid "0x04e8" "0x342d" :status :good :model "SCX-4300" :interface "USB" :usbid "0x04e8" "0x342e" :status :good :model "SCX-5835_5935" :interface "USB" :usbid "0x04e8" "0x342f" :status :good :model "SCX-5635" :interface "USB" :usbid "0x04e8" "0x3430" :status :untested :model "SCX-4x26" :interface "USB" :usbid "0x04e8" "0x3432" :status :untested :model "SCX-4600" :interface "USB" :usbid "0x04e8" "0x3433" :status :good :model "SCX-4623" :interface "USB" :usbid "0x04e8" "0x3434" :status :good :model "MFP-65x" :interface "USB" :usbid "0x04e8" "0x3435" :status :untested :model "SCX-6545" :interface "USB" :usbid "0x04e8" "0x3437" :status :untested :model "CLX-8385" :interface "USB" :usbid "0x04e8" "0x3439" :status :untested :model "CLX-6220" :interface "USB" :usbid "0x04e8" "0x343a" :status :good :model "CLX-6250" :interface "USB" :usbid "0x04e8" "0x343b" :status :untested :model "SCX-4825FN (SCX-4x25 Series)" :interface "USB" :usbid "0x04e8" "0x343c" :status :good :model "CLX-3185" :interface "USB" :usbid "0x04e8" "0x343d" :status :good :model "CLX-8540" :interface "USB" :usbid "0x04e8" "0x343f" :status :untested :model "SCX-4623FW" :interface "USB" :usbid "0x04e8" "0x3440" :status :good :model "SCX-3205W (SCX-3200 Series)" :interface "USB Ethernet" :usbid "0x04e8" "0x3441" :status :good :model "SCX-6545X" :interface "USB" :usbid "0x04e8" "0x3442" :status :untested :model "SCX-6x55X" :interface "USB" :usbid "0x04e8" "0x3443" :status :untested :model "CLX-8385X" :interface "USB" :usbid "0x04e8" "0x3444" :status :untested :model "SCX-5835_5935X" :interface "USB" :usbid "0x04e8" "0x3446" :status :good :model "SCX-4833FD" :interface "USB" :usbid "0x04e8" "0x344b" :status :good :model "SCX-4835FD" :interface "Ethernet" :usbid "0x04e8" "0x344b" :status :good :model "SCX-3405W" :interface "Ethernet" :status :basic :model "SCX-3400" :interface "USB" :usbid "0x04e8" "0x344f" :status :untested :model "SF-760" :interface "USB" :usbid "0x04e8" "0x3450" :status :untested :model "SCX-4729FD" :interface "USB" :usbid "0x04e8" "0x3453" :status :basic :model "CLX-6260" :interface "USB" :usbid "0x04e8" "0x3455" :status :minimal :model "CLX-3300 Series" :interface "USB" :usbid "0x04e8" "0x3456" :status :basic :model "SCX-470x" :interface "USB" :usbid "0x04e8" "0x3457" :status :untested :model "CLX-4190" :interface "USB" :usbid "0x04e8" "0x345a" :status :minimal :model "SCX-4650 4x21S Series" :interface "USB" :usbid "0x04e8" "0x345b" :status :untested :model "M337x 387x 407x Series" :interface "USB" :usbid "0x04e8" "0x3460" :status :untested :model "M267x 287x Series" :interface "USB" :usbid "0x04e8" "0x3461" :status :untested :model "SCX-681x" :interface "USB" :usbid "0x04e8" "0x3466" :status :untested :model "C460" :interface "USB" :usbid "0x04e8" "0x3468" :status :untested sane-backends-1.0.27/testsuite/tools/data/hal-new.ref0000664000175000017500000055345312775312262017403 00000000000000 scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary sane-backends-1.0.27/testsuite/tools/data/hwdb.ref0000664000175000017500000013642612775312262016771 00000000000000# This file was automatically created based on description files (*.desc) # by sane-desc 3.5 from sane-backends 1.0.25git on Tue Dec 3 15:24:46 2013 # # hwdb file for supported USB devices # # If your scanner isn't listed below, you can add it to a new hwdb file # under /etc/udev/hwdb.d/. # # If your scanner is supported by some external backend (brother, epkowa, # hpaio, etc) please ask the author of the backend to provide proper # device detection support for your OS # # If the scanner is supported by sane-backends, please mail the entry to # the sane-devel mailing list (sane-devel@lists.alioth.debian.org). # # Hewlett-Packard ScanJet 4100C usb:v03F0p0101* libsane_matched=yes # Hewlett-Packard ScanJet 4200C | Hewlett-Packard ScanJet 4200Cxi | Hewlett-Packard ScanJet 4200Cse usb:v03F0p0105* libsane_matched=yes # Hewlett-Packard ScanJet 6200C | Hewlett-Packard ScanJet 6250C usb:v03F0p0201* libsane_matched=yes # Hewlett-Packard ScanJet 3300c usb:v03F0p0205* libsane_matched=yes # Hewlett-Packard ScanJet 4300c usb:v03F0p0305* libsane_matched=yes # Hewlett-Packard ScanJet 5200C usb:v03F0p0401* libsane_matched=yes # Hewlett-Packard ScanJet 3400c usb:v03F0p0405* libsane_matched=yes # Hewlett-Packard ScanJet 2100C usb:v03F0p0505* libsane_matched=yes # Hewlett-Packard ScanJet 6300C | Hewlett-Packard ScanJet 6350C | Hewlett-Packard ScanJet 6390C usb:v03F0p0601* libsane_matched=yes # Hewlett-Packard ScanJet 2200C usb:v03F0p0605* libsane_matched=yes # Hewlett-Packard ScanJet 5300C | Hewlett-Packard ScanJet 5370C usb:v03F0p0701* libsane_matched=yes # Hewlett-Packard scanjet 4400c usb:v03F0p0705* libsane_matched=yes # Hewlett-Packard ScanJet 7400c | Hewlett-Packard ScanJet 7450c | Hewlett-Packard ScanJet 7490c usb:v03F0p0801* libsane_matched=yes # Hewlett-Packard scanjet 4470c usb:v03F0p0805* libsane_matched=yes # Hewlett-Packard ScanJet 2300C usb:v03F0p0901* libsane_matched=yes # Hewlett-Packard ScanJet 2400C | Hewlett-Packard ScanJet G2410 usb:v03F0p0A01* libsane_matched=yes # Hewlett-Packard ScanJet 8200 | Hewlett-Packard ScanJet 8250 | Hewlett-Packard ScanJet 8290 usb:v03F0p0B01* libsane_matched=yes # Hewlett-Packard ScanJet 5400c usb:v03F0p1005* libsane_matched=yes # Hewlett-Packard ScanJet 5470c usb:v03F0p1105* libsane_matched=yes # Hewlett-Packard ScanJet 4500C | Hewlett-Packard ScanJet 5550C usb:v03F0p1205* libsane_matched=yes # Hewlett-Packard ScanJet 4570C | Hewlett-Packard ScanJet 5500C usb:v03F0p1305* libsane_matched=yes # Hewlett-Packard ScanJet 3670C | Hewlett-Packard ScanJet 3690C usb:v03F0p1405* libsane_matched=yes # Hewlett-Packard ScanJet 5590 usb:v03F0p1705* libsane_matched=yes # Hewlett-Packard ScanJet 7650 usb:v03F0p1805* libsane_matched=yes # Hewlett-Packard ScanJet 4850C usb:v03F0p1B05* libsane_matched=yes # Hewlett-Packard ScanJet 3530C | Hewlett-Packard ScanJet 3570C usb:v03F0p2005* libsane_matched=yes # Hewlett-Packard ScanJet 3500C usb:v03F0p2205* libsane_matched=yes # Hewlett-Packard ScanJet 3970c usb:v03F0p2305* libsane_matched=yes # Hewlett-Packard ScanJet 4070 Photosmart usb:v03F0p2405* libsane_matched=yes # Hewlett-Packard ScanJet 3800 usb:v03F0p2605* libsane_matched=yes # Hewlett-Packard ScanJet G2710 usb:v03F0p2805* libsane_matched=yes # Hewlett-Packard ScanJet 8300 | Hewlett-Packard ScanJet 8350 | Hewlett-Packard ScanJet 8390 usb:v03F0p3805* libsane_matched=yes # Hewlett-Packard ScanJet 8270 usb:v03F0p3905* libsane_matched=yes # Hewlett-Packard LaserJet M1005 MFP usb:v03F0p3B17* libsane_matched=yes # Hewlett-Packard ScanJet 4370 usb:v03F0p4105* libsane_matched=yes # Hewlett-Packard ScanJet G3010 usb:v03F0p4205* libsane_matched=yes # Hewlett-Packard ScanJet G3110 usb:v03F0p4305* libsane_matched=yes # Hewlett-Packard ScanJet G4010 usb:v03F0p4505* libsane_matched=yes # Hewlett-Packard ScanJet G4050 usb:v03F0p4605* libsane_matched=yes # Hewlett-Packard ScanJet N6310 usb:v03F0p4705* libsane_matched=yes # Hewlett-Packard LaserJet M1120 MFP usb:v03F0p5617* libsane_matched=yes # Hewlett-Packard LaserJet M1120n MFP usb:v03F0p5717* libsane_matched=yes # Mustek BearPaw 1200 usb:v0400p1000* libsane_matched=yes # Mustek BearPaw 1200 | Mustek BearPaw 2400 usb:v0400p1001* libsane_matched=yes # Kodak ESP 5100 usb:v040Ap4025* libsane_matched=yes # Kodak ESP 5300 usb:v040Ap4026* libsane_matched=yes # Kodak ESP 5500 usb:v040Ap4027* libsane_matched=yes # Kodak ESP 5000 usb:v040Ap4028* libsane_matched=yes # Kodak ESP 3300 usb:v040Ap4031* libsane_matched=yes # Kodak ESP 5 usb:v040Ap4032* libsane_matched=yes # Kodak ESP 7 usb:v040Ap403E* libsane_matched=yes # Kodak ESP 9 usb:v040Ap403F* libsane_matched=yes # Kodak ESP 5200 usb:v040Ap4041* libsane_matched=yes # Kodak ESP 3200 usb:v040Ap4043* libsane_matched=yes # Kodak ESP 4100 usb:v040Ap4053* libsane_matched=yes # Kodak ESP 6100 usb:v040Ap4054* libsane_matched=yes # Kodak ESP 7200 usb:v040Ap4056* libsane_matched=yes # Kodak ESP C110 usb:v040Ap4057* libsane_matched=yes # Kodak ESP C115 usb:v040Ap4058* libsane_matched=yes # Kodak ESP 2150 usb:v040Ap4059* libsane_matched=yes # Kodak ESP C310 usb:v040Ap405D* libsane_matched=yes # Kodak ESP C315 usb:v040Ap405E* libsane_matched=yes # Advent AW10 usb:v040Ap4060* libsane_matched=yes # Kodak Hero Office 6.1 usb:v040Ap4062* libsane_matched=yes # Kodak Hero 7.1 usb:v040Ap4063* libsane_matched=yes # Kodak Hero 5.1 usb:v040Ap4064* libsane_matched=yes # Kodak ESP 9200 usb:v040Ap4065* libsane_matched=yes # Kodak ESP 2170 usb:v040Ap4066* libsane_matched=yes # Kodak Hero 9.1 usb:v040Ap4067* libsane_matched=yes # Kodak Hero 3.1 usb:v040Ap406D* libsane_matched=yes # Kodak i30 usb:v040Ap6001* libsane_matched=yes # Kodak i40 usb:v040Ap6002* libsane_matched=yes # Kodak i50 | Kodak i55 usb:v040Ap6003* libsane_matched=yes # Kodak i60 | Kodak i65 usb:v040Ap6004* libsane_matched=yes # Kodak i80 usb:v040Ap6005* libsane_matched=yes # Creative WebCam Go Mini usb:v041Ep4007* libsane_matched=yes # Lexmark X70 | Lexmark X73 usb:v043Dp002D* libsane_matched=yes # Lexmark X74 usb:v043Dp0060* libsane_matched=yes # Lexmark X1110 | Lexmark X1130 | Lexmark X1140 # Lexmark X1150 | Lexmark X1170 | Lexmark X1180 # Lexmark X1185 | Lexmark X1195 usb:v043Dp007C* libsane_matched=yes # Lexmark X12xx usb:v043Dp007D* libsane_matched=yes # Genius ColorPage HR6 V1 usb:v0458p2004* libsane_matched=yes # Genius Colorpage HR6 V2 usb:v0458p2007* libsane_matched=yes # Genius Colorpage HR6 V2 usb:v0458p2008* libsane_matched=yes # Genius Colorpage HR6A usb:v0458p2009* libsane_matched=yes # Genius Colorpage Vivid3x | Genius Colorpage Vivid3 V2 usb:v0458p2011* libsane_matched=yes # Genius Colorpage HR7 usb:v0458p2013* libsane_matched=yes # Genius Colorpage Vivid4 usb:v0458p2014* libsane_matched=yes # Genius Colorpage HR7LE usb:v0458p2015* libsane_matched=yes # Genius Colorpage HR6X usb:v0458p2016* libsane_matched=yes # Genius Colorpage Vivid3xe usb:v0458p2017* libsane_matched=yes # Genius Colorpage Vivid4xe usb:v0458p201A* libsane_matched=yes # Genius Colorpage Vivid4x usb:v0458p201B* libsane_matched=yes # Genius Colorpage Vivid 1200 X usb:v0458p201D* libsane_matched=yes # Genius ColorPage Slim 1200 usb:v0458p201E* libsane_matched=yes # Genius Colorpage Vivid 1200 XE usb:v0458p201F* libsane_matched=yes # Genius Colorpage SF600 usb:v0458p2021* libsane_matched=yes # Medion/Lifetec/Tevion/Cytron MD5345 | Medion/Lifetec/Tevion/Cytron MD6228 | Medion/Lifetec/Tevion/Cytron MD6471 usb:v0461p0377* libsane_matched=yes # Xerox 2400 Onetouch usb:v0461p038B* libsane_matched=yes # Trust Office Scan USB 19200 usb:v047Bp1000* libsane_matched=yes # Hewlett-Packard ScanJet 4300c/Silitek usb:v047Bp1002* libsane_matched=yes # Kyocera FS-1016MFP usb:v0482p0335* libsane_matched=yes # Compaq S4-100 usb:v049Fp001A* libsane_matched=yes # Benq (Acer) 310U usb:v04A5p1A20* libsane_matched=yes # Benq (Acer) 620U usb:v04A5p1A2A* libsane_matched=yes # Benq (Acer) 320U | Benq (Acer) 340U | Mitsubishi Diamondview 648UT usb:v04A5p2022* libsane_matched=yes # Benq (Acer) 620UT usb:v04A5p2040* libsane_matched=yes # Benq (Acer) 640U | Guillemot / Hercules Maxi Scan A4 USB 640U | Guillemot / Hercules Maxi A4 36 bit usb:v04A5p2060* libsane_matched=yes # Benq (Acer) 640bu usb:v04A5p207E* libsane_matched=yes # Benq (Acer) 3300 | Benq (Acer) 4300 | Mitsubishi Diamondview 650U usb:v04A5p20B0* libsane_matched=yes # Benq (Acer) 640BT usb:v04A5p20BE* libsane_matched=yes # Benq (Acer) 1240 usb:v04A5p20C0* libsane_matched=yes # Benq (Acer) 3300 | Benq (Acer) 4300 | Guillemot / Hercules Scan@home Touch 1248 (USB) usb:v04A5p20DE* libsane_matched=yes # Benq (Acer) 5000 usb:v04A5p20F8* libsane_matched=yes # Benq (Acer) 5000E | Benq (Acer) 5000U usb:v04A5p20FC* libsane_matched=yes # Benq (Acer) 5300 usb:v04A5p20FE* libsane_matched=yes # Benq (Acer) 5150 | Benq (Acer) 5250 usb:v04A5p2137* libsane_matched=yes # BenQ 5550 usb:v04A5p2211* libsane_matched=yes # Visioneer Visioneer OneTouch 7100 usb:v04A7p0229* libsane_matched=yes # Visioneer 9650 usb:v04A7p0390* libsane_matched=yes # Visioneer 9320 usb:v04A7p0420* libsane_matched=yes # Visioneer 9450 usb:v04A7p0421* libsane_matched=yes # Visioneer 9550 usb:v04A7p0422* libsane_matched=yes # Visioneer 9750 usb:v04A7p0423* libsane_matched=yes # Visioneer Strobe XP 450 usb:v04A7p0424* libsane_matched=yes # Visioneer Strobe XP 200 usb:v04A7p0426* libsane_matched=yes # Visioneer Strobe XP 100 usb:v04A7p0427* libsane_matched=yes # Visioneer OneTouch 7300 usb:v04A7p0444* libsane_matched=yes # Xerox DocuMate510 usb:v04A7p0446* libsane_matched=yes # Xerox DocuMate520 usb:v04A7p0447* libsane_matched=yes # Xerox DocuMate250 usb:v04A7p0448* libsane_matched=yes # Xerox DocuMate252 usb:v04A7p0449* libsane_matched=yes # Xerox DocuMate262 usb:v04A7p044C* libsane_matched=yes # Visioneer Strobe XP 300 usb:v04A7p0474* libsane_matched=yes # Xerox DocuMate272 usb:v04A7p0475* libsane_matched=yes # Xerox DocuMate232 usb:v04A7p0476* libsane_matched=yes # Xerox DocuMate152 usb:v04A7p0477* libsane_matched=yes # Xerox DocuMate752 usb:v04A7p0478* libsane_matched=yes # Visioneer Strobe XP 470 usb:v04A7p0479* libsane_matched=yes # Visioneer 9450-G usb:v04A7p047A* libsane_matched=yes # Visioneer 9650-G usb:v04A7p047B* libsane_matched=yes # Xerox DocuMate510-G usb:v04A7p047C* libsane_matched=yes # Xerox DocuMate252-G usb:v04A7p048C* libsane_matched=yes # Xerox DocuMate262-G usb:v04A7p048D* libsane_matched=yes # Xerox DocuMate272-G usb:v04A7p048E* libsane_matched=yes # Visioneer Strobe XP 470-G | Visioneer Patriot 470 usb:v04A7p048F* libsane_matched=yes # Xerox DocuMate250-G usb:v04A7p0490* libsane_matched=yes # Visioneer Strobe XP 450-G usb:v04A7p0491* libsane_matched=yes # Xerox DocuMate520-G usb:v04A7p0492* libsane_matched=yes # Visioneer 9750-G usb:v04A7p0493* libsane_matched=yes # Visioneer Roadwarrior usb:v04A7p0494* libsane_matched=yes # Xerox DocuMate512 usb:v04A7p0495* libsane_matched=yes # Visioneer Patriot 430 usb:v04A7p0497* libsane_matched=yes # Visioneer Patriot 680 | Xerox DocuMate632 usb:v04A7p0498* libsane_matched=yes # Visioneer Patriot 780 usb:v04A7p0499* libsane_matched=yes # Xerox DocuMate752 usb:v04A7p049A* libsane_matched=yes # Visioneer Strobe XP 100,r3 usb:v04A7p049B* libsane_matched=yes # Xerox DocuMate150 usb:v04A7p049C* libsane_matched=yes # Xerox DocuMate162 usb:v04A7p049D* libsane_matched=yes # Xerox DocuMate262i usb:v04A7p04A7* libsane_matched=yes # Xerox Travel Scanner 100 usb:v04A7p04AC* libsane_matched=yes # Canon DR-2080C usb:v04A9p1601* libsane_matched=yes # Canon CR-180 | Canon CR-180II usb:v04A9p1602* libsane_matched=yes # Canon DR-9080C usb:v04A9p1603* libsane_matched=yes # Canon DR-7080C usb:v04A9p1604* libsane_matched=yes # Canon DR-5010C usb:v04A9p1606* libsane_matched=yes # Canon DR-6080 usb:v04A9p1607* libsane_matched=yes # Canon DR-2580C usb:v04A9p1608* libsane_matched=yes # Canon DR-3080CII usb:v04A9p1609* libsane_matched=yes # Canon DR-2050C | Canon DR-2050SP usb:v04A9p160A* libsane_matched=yes # Canon DR-7580 usb:v04A9p160B* libsane_matched=yes # Canon PIXMA MP750 usb:v04A9p1706* libsane_matched=yes # Canon PIXMA MP780 | Canon PIXMA MP790 usb:v04A9p1707* libsane_matched=yes # Canon PIXMA MP760 | Canon PIXMA MP770 usb:v04A9p1708* libsane_matched=yes # Canon PIXMA MP150 usb:v04A9p1709* libsane_matched=yes # Canon PIXMA MP170 usb:v04A9p170A* libsane_matched=yes # Canon PIXMA MP450 usb:v04A9p170B* libsane_matched=yes # Canon PIXMA MP500 usb:v04A9p170C* libsane_matched=yes # Canon PIXMA MP800 usb:v04A9p170D* libsane_matched=yes # Canon PIXMA MP800R usb:v04A9p170E* libsane_matched=yes # Canon PIXMA MP530 usb:v04A9p1712* libsane_matched=yes # Canon PIXMA MP830 usb:v04A9p1713* libsane_matched=yes # Canon PIXMA MP160 usb:v04A9p1714* libsane_matched=yes # Canon PIXMA MP180 usb:v04A9p1715* libsane_matched=yes # Canon PIXMA MP460 usb:v04A9p1716* libsane_matched=yes # Canon PIXMA MP510 usb:v04A9p1717* libsane_matched=yes # Canon PIXMA MP600 usb:v04A9p1718* libsane_matched=yes # Canon PIXMA MP600R usb:v04A9p1719* libsane_matched=yes # Canon PIXMA MP810 usb:v04A9p171A* libsane_matched=yes # Canon PIXMA MP960 usb:v04A9p171B* libsane_matched=yes # Canon PIXMA MX7600 usb:v04A9p171C* libsane_matched=yes # Canon PIXMA MP210 usb:v04A9p1721* libsane_matched=yes # Canon PIXMA MP220 usb:v04A9p1722* libsane_matched=yes # Canon PIXMA MP470 usb:v04A9p1723* libsane_matched=yes # Canon PIXMA MP520 usb:v04A9p1724* libsane_matched=yes # Canon PIXMA MP610 usb:v04A9p1725* libsane_matched=yes # Canon PIXMA MP970 usb:v04A9p1726* libsane_matched=yes # Canon PIXMA MX300 usb:v04A9p1727* libsane_matched=yes # Canon PIXMA MX310 usb:v04A9p1728* libsane_matched=yes # Canon PIXMA MX700 usb:v04A9p1729* libsane_matched=yes # Canon PIXMA MP140 usb:v04A9p172B* libsane_matched=yes # Canon PIXMA MX850 usb:v04A9p172C* libsane_matched=yes # Canon PIXMA MP980 usb:v04A9p172D* libsane_matched=yes # Canon PIXMA MP630 usb:v04A9p172E* libsane_matched=yes # Canon PIXMA MP620 usb:v04A9p172F* libsane_matched=yes # Canon PIXMA MP540 usb:v04A9p1730* libsane_matched=yes # Canon PIXMA MP480 usb:v04A9p1731* libsane_matched=yes # Canon PIXMA MP240 usb:v04A9p1732* libsane_matched=yes # Canon PIXMA MP260 usb:v04A9p1733* libsane_matched=yes # Canon PIXMA MP190 usb:v04A9p1734* libsane_matched=yes # Canon PIXMA MX860 usb:v04A9p1735* libsane_matched=yes # Canon PIXMA MX320 usb:v04A9p1736* libsane_matched=yes # Canon PIXMA MX330 usb:v04A9p1737* libsane_matched=yes # Canon PIXMA MP250 usb:v04A9p173A* libsane_matched=yes # Canon PIXMA MP270 usb:v04A9p173B* libsane_matched=yes # Canon PIXMA MP490 usb:v04A9p173C* libsane_matched=yes # Canon PIXMA MP550 usb:v04A9p173D* libsane_matched=yes # Canon PIXMA MP560 usb:v04A9p173E* libsane_matched=yes # Canon PIXMA MP640 usb:v04A9p173F* libsane_matched=yes # Canon PIXMA MP990 usb:v04A9p1740* libsane_matched=yes # Canon PIXMA MX340 usb:v04A9p1741* libsane_matched=yes # Canon PIXMA MX350 usb:v04A9p1742* libsane_matched=yes # Canon PIXMA MX870 usb:v04A9p1743* libsane_matched=yes # Canon PIXMA MP280 usb:v04A9p1746* libsane_matched=yes # Canon PIXMA MP495 usb:v04A9p1747* libsane_matched=yes # Canon PIXMA MG5100 Series usb:v04A9p1748* libsane_matched=yes # Canon PIXMA MG5200 Series usb:v04A9p1749* libsane_matched=yes # Canon PIXMA MG6100 Series usb:v04A9p174A* libsane_matched=yes # Canon PIXMA MG8100 Series usb:v04A9p174B* libsane_matched=yes # Canon PIXMA MX360 usb:v04A9p174D* libsane_matched=yes # Canon PIXMA MX410 usb:v04A9p174E* libsane_matched=yes # Canon PIXMA MX420 usb:v04A9p174F* libsane_matched=yes # Canon PIXMA MX880 Series | Canon PIXMA MX882 | Canon PIXMA MX885 usb:v04A9p1750* libsane_matched=yes # Canon PIXMA MG2100 Series usb:v04A9p1751* libsane_matched=yes # Canon PIXMA MG3100 Series usb:v04A9p1752* libsane_matched=yes # Canon PIXMA MG4100 Series usb:v04A9p1753* libsane_matched=yes # Canon PIXMA MG5300 Series usb:v04A9p1754* libsane_matched=yes # Canon PIXMA MG6200 Series usb:v04A9p1755* libsane_matched=yes # Canon PIXMA MG8200 Series usb:v04A9p1756* libsane_matched=yes # Canon PIXMA MP493 usb:v04A9p1757* libsane_matched=yes # Canon PIXMA E500 usb:v04A9p1758* libsane_matched=yes # Canon PIXMA MX370 Series usb:v04A9p1759* libsane_matched=yes # Canon PIXMA E600 usb:v04A9p175A* libsane_matched=yes # Canon PIXMA MX430 Series usb:v04A9p175B* libsane_matched=yes # Canon PIXMA MX510 Series usb:v04A9p175C* libsane_matched=yes # Canon PIXMA MX710 Series usb:v04A9p175D* libsane_matched=yes # Canon PIXMA MX890 Series usb:v04A9p175E* libsane_matched=yes # Canon PIXMA MP230 usb:v04A9p175F* libsane_matched=yes # Canon PIXMA MG2200 Series usb:v04A9p1760* libsane_matched=yes # Canon PIXMA E510 usb:v04A9p1761* libsane_matched=yes # Canon PIXMA MG3200 Series usb:v04A9p1762* libsane_matched=yes # Canon PIXMA MG4200 Series usb:v04A9p1763* libsane_matched=yes # Canon PIXMA MG5400 Series usb:v04A9p1764* libsane_matched=yes # Canon PIXMA MG6300 Series usb:v04A9p1765* libsane_matched=yes # Canon PIXMA MX390 Series usb:v04A9p1766* libsane_matched=yes # Canon PIXMA E610 usb:v04A9p1767* libsane_matched=yes # Canon PIXMA MX450 Series usb:v04A9p1768* libsane_matched=yes # Canon PIXMA MX520 Series usb:v04A9p1769* libsane_matched=yes # Canon PIXMA MX720 Series usb:v04A9p176A* libsane_matched=yes # Canon PIXMA MX920 Series usb:v04A9p176B* libsane_matched=yes # Canon CanoScan 8800F usb:v04A9p1901* libsane_matched=yes # Canon CanoScan LiDE 100 usb:v04A9p1904* libsane_matched=yes # Canon CanoScan LiDE 200 usb:v04A9p1905* libsane_matched=yes # Canon CanoScan 700F usb:v04A9p1907* libsane_matched=yes # Canon CanoScan 9000F usb:v04A9p1908* libsane_matched=yes # Canon CanoScan LiDE 110 usb:v04A9p1909* libsane_matched=yes # Canon CanoScan LiDE 210 usb:v04A9p190A* libsane_matched=yes # Canon CanoScan 9000F Mark II usb:v04A9p190D* libsane_matched=yes # Canon CanoScan fb630u | Canon CanoScan fb636u usb:v04A9p2204* libsane_matched=yes # Canon CanoScan N650U/N656U usb:v04A9p2206* libsane_matched=yes # Canon CanoScan N1220U usb:v04A9p2207* libsane_matched=yes # Canon CanoScan D660U usb:v04A9p2208* libsane_matched=yes # Canon CanoScan N670U/N676U/LiDE20 usb:v04A9p220D* libsane_matched=yes # Canon CanoScan N1240U/LiDE30 usb:v04A9p220E* libsane_matched=yes # Canon CanoScan LiDE 35 | Canon CanoScan LiDE 40 | Canon CanoScan LiDE 50 usb:v04A9p2213* libsane_matched=yes # Canon CanoScan LiDE 60 usb:v04A9p221C* libsane_matched=yes # Canon CanoScan LiDE25 usb:v04A9p2220* libsane_matched=yes # Canon DR-1210C usb:v04A9p2222* libsane_matched=yes # Canon PIXMA MP730 usb:v04A9p262F* libsane_matched=yes # Canon PIXMA MP700 usb:v04A9p2630* libsane_matched=yes # Canon PIXMA MP360 usb:v04A9p263C* libsane_matched=yes # Canon PIXMA MP370 usb:v04A9p263D* libsane_matched=yes # Canon PIXMA MP390 usb:v04A9p263E* libsane_matched=yes # Canon PIXMA MP375R usb:v04A9p263F* libsane_matched=yes # Canon PIXMA MP740 usb:v04A9p264C* libsane_matched=yes # Canon PIXMA MP710 usb:v04A9p264D* libsane_matched=yes # Canon imageCLASS MF5630 usb:v04A9p264E* libsane_matched=yes # Canon laserBase MF5650 usb:v04A9p264F* libsane_matched=yes # Canon imageCLASS MF8170c usb:v04A9p2659* libsane_matched=yes # Canon imageCLASS MF5730 usb:v04A9p265D* libsane_matched=yes # Canon imageCLASS MF5750 usb:v04A9p265E* libsane_matched=yes # Canon imageCLASS MF5770 usb:v04A9p265F* libsane_matched=yes # Canon imageCLASS MF3110 usb:v04A9p2660* libsane_matched=yes # Canon imageCLASS MF3240 usb:v04A9p2684* libsane_matched=yes # Canon imageCLASS MF6500 series | Canon imageCLASS MF6550 usb:v04A9p2686* libsane_matched=yes # Canon imageCLASS MF4120 | Canon imageCLASS MF4122 | Canon imageCLASS MF4140 # Canon imageCLASS MF4150 usb:v04A9p26A3* libsane_matched=yes # Canon imageCLASS MF4660 | Canon imageCLASS MF4690 usb:v04A9p26B0* libsane_matched=yes # Canon imageCLASS MF4010 | Canon imageCLASS MF4018 usb:v04A9p26B4* libsane_matched=yes # Canon imageCLASS MF4270 usb:v04A9p26B5* libsane_matched=yes # Canon imageRUNNER 1020/1024/1025 usb:v04A9p26E6* libsane_matched=yes # Canon imageCLASS MF4370dn | Canon imageCLASS MF4380dn usb:v04A9p26EC* libsane_matched=yes # Canon imageCLASS D480 usb:v04A9p26ED* libsane_matched=yes # Canon I-SENSYS MF4320d | Canon I-SENSYS MF4330d | Canon imageCLASS MF4350d usb:v04A9p26EE* libsane_matched=yes # Canon imageCLASS D420 usb:v04A9p26EF* libsane_matched=yes # Canon i-SENSYS MF5880dn usb:v04A9p26F9* libsane_matched=yes # Canon i-SENSYS MF6680dn usb:v04A9p26FA* libsane_matched=yes # Canon imageCLASS MF8030 usb:v04A9p2707* libsane_matched=yes # Canon i-SENSYS MF4550d usb:v04A9p2736* libsane_matched=yes # Canon imageCLASS MF4410 | Canon imageCLASS MF4430 usb:v04A9p2737* libsane_matched=yes # Canon i-SENSYS MF3010 usb:v04A9p2759* libsane_matched=yes # Nikon LS 40 ED | Nikon LS 40 ED | Nikon Coolspan IV usb:v04B0p4000* libsane_matched=yes # Nikon LS 50 ED | Nikon Coolscan V ED | Nikon LS 50 ED # Nikon Coolscan V ED usb:v04B0p4001* libsane_matched=yes # Nikon Super Coolscan LS-5000 ED | Nikon Super Coolscan LS-5000 ED usb:v04B0p4002* libsane_matched=yes # Epson Perfection 636U | Epson GT-7000U | Epson Perfection 636U usb:v04B8p0101* libsane_matched=yes # Epson Perfection 610 | Epson GT-6600U | Epson Perfection 610 usb:v04B8p0103* libsane_matched=yes # Epson Perfection 1200U | Epson Perfection 1200Photo | Epson GT-7600U # Epson GT-7600UF | Epson Perfection 1200U | Epson Perfection 1200U PHOTO usb:v04B8p0104* libsane_matched=yes # Epson Stylus Scan 2000 usb:v04B8p0105* libsane_matched=yes # Epson Stylus Scan 2500 usb:v04B8p0106* libsane_matched=yes # Epson Expression 1600 | Epson ES-2000 | Epson Expression 1600 usb:v04B8p0107* libsane_matched=yes # Epson ES-8500 | Epson Expression 1640XL usb:v04B8p0109* libsane_matched=yes # Epson Perfection 1640 | Epson GT-8700 | Epson GT-8700F # Epson Perfection 1640SU | Epson Perfection 1640SU PHOTO usb:v04B8p010A* libsane_matched=yes # Epson Perfection 1240 | Epson GT-7700U | Epson Perfection 1240U usb:v04B8p010B* libsane_matched=yes # Epson Perfection 640 | Epson GT-6700U | Epson Perfection 640U usb:v04B8p010C* libsane_matched=yes # Epson Expression 1680 | Epson ES-2200 | Epson Expression 1680 usb:v04B8p010E* libsane_matched=yes # Epson Perfection 1250 | Epson Perfection 1250Photo usb:v04B8p010F* libsane_matched=yes # Epson Perfection 1650 | Epson GT-8200U | Epson GT-8200UF # Epson Perfection 1650 | Epson Perfection 1650 PHOTO usb:v04B8p0110* libsane_matched=yes # Epson Perfection 2450 | Epson GT-9700F | Epson Perfection 2450 PHOTO usb:v04B8p0112* libsane_matched=yes # Epson Perfection 660 usb:v04B8p0114* libsane_matched=yes # Epson Perfection 2400 | Epson GT-9300UF | Epson Perfection 2400 PHOTO usb:v04B8p011B* libsane_matched=yes # Epson Perfection 3200 | Epson GT-9800F | Epson Perfection 3200 PHOTO usb:v04B8p011C* libsane_matched=yes # Epson Perfection 1260 | Epson Perfection 1260Photo usb:v04B8p011D* libsane_matched=yes # Epson Perfection 1660 | Epson GT-8300UF | Epson Perfection 1660 PHOTO usb:v04B8p011E* libsane_matched=yes # Epson Perfection 1670 usb:v04B8p011F* libsane_matched=yes # Epson Perfection 1270 usb:v04B8p0120* libsane_matched=yes # Epson Perfection 2480 | Epson Perfection 2580 usb:v04B8p0121* libsane_matched=yes # Epson Perfection 3490 | Epson Perfection 3590 usb:v04B8p0122* libsane_matched=yes # Epson ES-7000H | Epson GT-15000 usb:v04B8p0126* libsane_matched=yes # Epson Perfection 4870 | Epson GT-X700 | Epson Perfection 4870 PHOTO usb:v04B8p0128* libsane_matched=yes # Epson ES-10000G | Epson Expression 10000XL usb:v04B8p0129* libsane_matched=yes # Epson Perfection 4990 | Epson GT-X800 | Epson Perfection 4990 PHOTO usb:v04B8p012A* libsane_matched=yes # Epson ES-H300 | Epson GT-2500 usb:v04B8p012B* libsane_matched=yes # Epson V700 | Epson V750 | Epson GT-X900 # Epson Perfection V700 Photo | Epson Perfection V750 Photo usb:v04B8p012C* libsane_matched=yes # Epson GT-X970 usb:v04B8p0135* libsane_matched=yes # Epson CX-5200 | Epson CX-5400 | Epson CC-600PX # Epson Stylus CX5100 | Epson Stylus CX5200 usb:v04B8p0801* libsane_matched=yes # Epson CX-3200 | Epson CC-570L | Epson Stylus CX3100 # Epson Stylus CX3200 usb:v04B8p0802* libsane_matched=yes # Epson CX-6300 | Epson CX-6400 | Epson Stylus CX6300 # Epson Stylus CX6400 usb:v04B8p0805* libsane_matched=yes # Epson RX-600 | Epson PM-A850 | Epson Stylus Photo RX600 usb:v04B8p0806* libsane_matched=yes # Epson RX-500 | Epson Stylus Photo RX500 | Epson Stylus Photo RX510 usb:v04B8p0807* libsane_matched=yes # Epson CX-5400 | Epson Stylus CX5300 | Epson Stylus CX5400 usb:v04B8p0808* libsane_matched=yes # Epson Stylus CX-1500 usb:v04B8p080C* libsane_matched=yes # Epson CX-4600 | Epson Stylus CX4500 | Epson Stylus CX4600 usb:v04B8p080D* libsane_matched=yes # Epson CX-3600 | Epson CX-3650 | Epson PX-A550 # Epson Stylus CX3500 | Epson Stylus CX3600 | Epson Stylus CX3650 usb:v04B8p080E* libsane_matched=yes # Epson RX-425 | Epson Stylus Photo RX420 | Epson Stylus Photo RX425 # Epson Stylus Photo RX430 usb:v04B8p080F* libsane_matched=yes # Epson RX-700 | Epson PM-A900 | Epson Stylus Photo RX700 usb:v04B8p0810* libsane_matched=yes # Epson RX-620 | Epson PM-A870 | Epson Stylus Photo RX620 # Epson Stylus Photo RX630 usb:v04B8p0811* libsane_matched=yes # Epson CX-6500 | Epson CX-6600 | Epson Stylus CX6500 # Epson Stylus CX6600 usb:v04B8p0813* libsane_matched=yes # Epson PM-A700 usb:v04B8p0814* libsane_matched=yes # Epson AcuLaser CX11 | Epson AcuLaser CX11NF | Epson AcuLaser CX11 # Epson AcuLaser CX11NF | Epson LP-A500 usb:v04B8p0815* libsane_matched=yes # Epson LP-M5500 | Epson LP-M5500F usb:v04B8p0817* libsane_matched=yes # Epson DX-3850 | Epson CX-3700 | Epson CX-3800 # Epson DX-3800 | Epson Stylus CX3700 | Epson Stylus CX3800 # Epson Stylus DX3800 usb:v04B8p0818* libsane_matched=yes # Epson CX-4800 | Epson PX-A650 | Epson Stylus CX4700 # Epson Stylus CX4800 | Epson Stylus DX4800 | Epson Stylus DX4850 usb:v04B8p0819* libsane_matched=yes # Epson PM-A750 | Epson Stylus Photo RX520 | Epson Stylus Photo RX530 usb:v04B8p081A* libsane_matched=yes # Epson PM-A890 | Epson Stylus Photo RX640 | Epson Stylus Photo RX650 usb:v04B8p081C* libsane_matched=yes # Epson PM-A950 usb:v04B8p081D* libsane_matched=yes # Epson Stylus CX7700 | Epson Stylus CX7800 usb:v04B8p081F* libsane_matched=yes # Epson CX-4200 | Epson Stylus CX4100 | Epson Stylus CX4200 # Epson Stylus DX4200 usb:v04B8p0820* libsane_matched=yes # Epson PM-A820 | Epson Stylus Photo RX560 | Epson Stylus Photo RX580 # Epson Stylus Photo RX590 usb:v04B8p0827* libsane_matched=yes # Epson PM-A970 usb:v04B8p0828* libsane_matched=yes # Epson PM-T990 usb:v04B8p0829* libsane_matched=yes # Epson PM-A920 usb:v04B8p082A* libsane_matched=yes # Epson CX-5000 | Epson DX-5000 | Epson DX-5050 # Epson Stylus CX4900 | Epson Stylus CX5000 | Epson Stylus DX5000 usb:v04B8p082B* libsane_matched=yes # Epson DX-6000 | Epson PX-A720 | Epson Stylus CX5900 # Epson Stylus CX6000 | Epson Stylus DX6000 usb:v04B8p082E* libsane_matched=yes # Epson DX-4050 | Epson PX-A620 | Epson Stylus CX3900 # Epson Stylus DX4000 usb:v04B8p082F* libsane_matched=yes # Epson ME 200 | Epson Stylus CX2800 | Epson Stylus CX2900 usb:v04B8p0830* libsane_matched=yes # Epson LP-M5600 usb:v04B8p0833* libsane_matched=yes # Epson LP-M6000 usb:v04B8p0834* libsane_matched=yes # Epson AcuLaser CX21 usb:v04B8p0835* libsane_matched=yes # Epson PM-T960 usb:v04B8p0836* libsane_matched=yes # Epson PM-A940 | Epson Stylus Photo RX680 | Epson Stylus Photo RX685 # Epson Stylus Photo RX690 usb:v04B8p0837* libsane_matched=yes # Epson DX-7400 | Epson PX-A640 | Epson Stylus CX7300 # Epson Stylus CX7400 | Epson Stylus DX7400 usb:v04B8p0838* libsane_matched=yes # Epson PX-A740 | Epson Stylus CX8300 | Epson Stylus CX8400 # Epson Stylus DX8400 usb:v04B8p0839* libsane_matched=yes # Epson PX-FA700 | Epson Stylus CX9300F | Epson Stylus CX9400Fax # Epson Stylus DX9400F usb:v04B8p083A* libsane_matched=yes # Epson PM-A840 | Epson PM-A840S | Epson Stylus Photo RX585 # Epson Stylus Photo RX595 | Epson Stylus Photo RX610 usb:v04B8p083C* libsane_matched=yes # Epson ME 300 | Epson PX-401A | Epson Stylus NX100 # Epson Stylus SX100 | Epson Stylus TX100 usb:v04B8p0841* libsane_matched=yes # Epson LP-M5000 usb:v04B8p0843* libsane_matched=yes # Epson Artisan 800 | Epson EP-901A | Epson EP-901F # Epson Stylus Photo PX800FW | Epson Stylus Photo TX800FW usb:v04B8p0844* libsane_matched=yes # Epson Artisan 700 | Epson EP-801A | Epson Stylus Photo PX700W # Epson Stylus Photo TX700W usb:v04B8p0846* libsane_matched=yes # Epson ME Office 700FW | Epson PX-601F | Epson Stylus Office BX600FW # Epson Stylus Office TX600FW | Epson Stylus SX600FW | Epson WorkForce 600 usb:v04B8p0847* libsane_matched=yes # Epson ME Office 600F | Epson Stylus Office BX300F | Epson Stylus Office TX300F # Epson Stylus NX300 usb:v04B8p0848* libsane_matched=yes # Epson Stylus NX200 | Epson Stylus SX200 | Epson Stylus SX205 # Epson Stylus TX200 | Epson Stylus TX203 | Epson Stylus TX209 usb:v04B8p0849* libsane_matched=yes # Epson PX-501A | Epson Stylus NX400 | Epson Stylus SX400 # Epson Stylus SX405 | Epson Stylus TX400 usb:v04B8p084A* libsane_matched=yes # Epson WorkForce 500 usb:v04B8p084C* libsane_matched=yes # Epson PX-402A | Epson Stylus NX110 Series | Epson Stylus SX110 Series # Epson Stylus TX110 Series usb:v04B8p084D* libsane_matched=yes # Epson ME OFFICE 510 | Epson Stylus NX210 Series | Epson Stylus SX210 Series # Epson Stylus TX210 Series usb:v04B8p084F* libsane_matched=yes # Epson Stylus NX410 Series | Epson Stylus SX410 Series | Epson Stylus TX410 Series usb:v04B8p0851* libsane_matched=yes # Epson ME OFFICE 650FN Series | Epson Stylus Office BX310FN Series | Epson Stylus Office TX510FN Series # Epson WorkForce 310 Series usb:v04B8p0854* libsane_matched=yes # Epson PX-502A | Epson Stylus NX510 Series | Epson Stylus SX510W Series # Epson Stylus TX550W Series usb:v04B8p0856* libsane_matched=yes # Epson Stylus SX125 usb:v04B8p085C* libsane_matched=yes # Fujitsu fi-4010CU usb:v04C5p1029* libsane_matched=yes # Fujitsu fi-4120C usb:v04C5p1041* libsane_matched=yes # Fujitsu fi-4220C usb:v04C5p1042* libsane_matched=yes # Fujitsu fi-4530C usb:v04C5p1078* libsane_matched=yes # Fujitsu fi-5750C usb:v04C5p1095* libsane_matched=yes # Fujitsu fi-5110EOX/2 usb:v04C5p1096* libsane_matched=yes # Fujitsu fi-5110C usb:v04C5p1097* libsane_matched=yes # Fujitsu fi-5650C usb:v04C5p10AD* libsane_matched=yes # Fujitsu fi-4120C2 usb:v04C5p10AE* libsane_matched=yes # Fujitsu fi-4220C2 usb:v04C5p10AF* libsane_matched=yes # Fujitsu fi-60F usb:v04C5p10C7* libsane_matched=yes # Fujitsu fi-4340C usb:v04C5p10CF* libsane_matched=yes # Fujitsu fi-5120C usb:v04C5p10E0* libsane_matched=yes # Fujitsu fi-5220C usb:v04C5p10E1* libsane_matched=yes # Fujitsu fi-5530C usb:v04C5p10E2* libsane_matched=yes # Fujitsu fi-5110EOX3 usb:v04C5p10E6* libsane_matched=yes # Fujitsu fi-5900C usb:v04C5p10E7* libsane_matched=yes # Fujitsu fi-5015C usb:v04C5p10EF* libsane_matched=yes # Fujitsu fi-5110EOXM usb:v04C5p10F2* libsane_matched=yes # Fujitsu ScanSnap S500 usb:v04C5p10FE* libsane_matched=yes # Fujitsu ScanSnap S500M usb:v04C5p1135* libsane_matched=yes # Fujitsu fi-5530C2 usb:v04C5p114A* libsane_matched=yes # Fujitsu fi-6140 usb:v04C5p114D* libsane_matched=yes # Fujitsu fi-6240 usb:v04C5p114E* libsane_matched=yes # Fujitsu fi-6130 usb:v04C5p114F* libsane_matched=yes # Fujitsu fi-6230 usb:v04C5p1150* libsane_matched=yes # Fujitsu ScanSnap S510 usb:v04C5p1155* libsane_matched=yes # Fujitsu ScanSnap S300 usb:v04C5p1156* libsane_matched=yes # Fujitsu ScanSnap S510M usb:v04C5p116F* libsane_matched=yes # Fujitsu fi-6770 usb:v04C5p1174* libsane_matched=yes # Fujitsu fi-6770A usb:v04C5p1175* libsane_matched=yes # Fujitsu fi-6670 usb:v04C5p1176* libsane_matched=yes # Fujitsu fi-6670A usb:v04C5p1177* libsane_matched=yes # Fujitsu fi-6750S usb:v04C5p1178* libsane_matched=yes # Fujitsu ScanSnap S300M usb:v04C5p117F* libsane_matched=yes # Fujitsu fi-6800 usb:v04C5p119D* libsane_matched=yes # Fujitsu fi-6800-CGA usb:v04C5p119E* libsane_matched=yes # Fujitsu ScanSnap S1500 | Fujitsu ScanSnap S1500M usb:v04C5p11A2* libsane_matched=yes # Fujitsu ScanSnap S1300 usb:v04C5p11ED* libsane_matched=yes # Fujitsu fi-6140Z usb:v04C5p11F1* libsane_matched=yes # Fujitsu fi-6240Z usb:v04C5p11F2* libsane_matched=yes # Fujitsu fi-6130Z usb:v04C5p11F3* libsane_matched=yes # Fujitsu fi-6230Z usb:v04C5p11F4* libsane_matched=yes # Fujitsu fi-6110 usb:v04C5p11FC* libsane_matched=yes # Fujitsu fi-5950 usb:v04C5p1213* libsane_matched=yes # Fujitsu ScanSnap iX500 usb:v04C5p132B* libsane_matched=yes # Konica e-mini usb:v04C8p0722* libsane_matched=yes # Panasonic KV-S2026C usb:v04DAp1000* libsane_matched=yes # Panasonic KV-S2046C usb:v04DAp1001* libsane_matched=yes # Panasonic KV-S1025C usb:v04DAp1006* libsane_matched=yes # Panasonic KV-S1020C usb:v04DAp1007* libsane_matched=yes # Panasonic KV-S2048C usb:v04DAp1009* libsane_matched=yes # Panasonic KV-S2028C usb:v04DAp100A* libsane_matched=yes # Panasonic KV-S4085C usb:v04DAp100C* libsane_matched=yes # Panasonic KV-S4065C usb:v04DAp100D* libsane_matched=yes # Panasonic KV-S7075C usb:v04DAp100E* libsane_matched=yes # Panasonic KV-SS080 usb:v04DAp100F* libsane_matched=yes # Panasonic KV-S1045C usb:v04DAp1010* libsane_matched=yes # Samsung SCX-4x16 usb:v04E8p3409* libsane_matched=yes # Samsung SCX-6x20 usb:v04E8p340D* libsane_matched=yes # Samsung MFP-560 usb:v04E8p340E* libsane_matched=yes # Samsung MFP-750 usb:v04E8p340F* libsane_matched=yes # Samsung SCX-4x20 usb:v04E8p3412* libsane_matched=yes # Samsung SCX-4100 usb:v04E8p3413* libsane_matched=yes # Samsung SCX-4x21 usb:v04E8p3419* libsane_matched=yes # Samsung SCX-5x30 usb:v04E8p341A* libsane_matched=yes # Samsung SCX-4200 usb:v04E8p341B* libsane_matched=yes # Samsung CLX-3160 usb:v04E8p341C* libsane_matched=yes # Samsung SCX-6x22 usb:v04E8p341D* libsane_matched=yes # Samsung SCX4725 | Samsung SCX4725-FN usb:v04E8p341F* libsane_matched=yes # Samsung SCX-6x45 usb:v04E8p3420* libsane_matched=yes # Samsung CLX-8380 usb:v04E8p3421* libsane_matched=yes # Samsung CLX-2160 usb:v04E8p3425* libsane_matched=yes # Samsung SCX-4500 usb:v04E8p3426* libsane_matched=yes # Samsung CLX-6200 usb:v04E8p3427* libsane_matched=yes # Samsung CLX-6240 usb:v04E8p3428* libsane_matched=yes # Samsung SCX-6x55 usb:v04E8p3429* libsane_matched=yes # Samsung CLX-3170fn (CLX-3170 Series) | Samsung CLX-3175FW usb:v04E8p342A* libsane_matched=yes # Samsung SCX-4500W usb:v04E8p342B* libsane_matched=yes # Samsung SCX-4824 (SCX-4x24 Series) usb:v04E8p342C* libsane_matched=yes # Samsung SCX-4828FN (SCX-4x28 Series) usb:v04E8p342D* libsane_matched=yes # Samsung SCX-4300 usb:v04E8p342E* libsane_matched=yes # Samsung SCX-5835_5935 usb:v04E8p342F* libsane_matched=yes # Samsung SCX-5635 usb:v04E8p3430* libsane_matched=yes # Samsung SCX-4x26 usb:v04E8p3432* libsane_matched=yes # Samsung SCX-4600 usb:v04E8p3433* libsane_matched=yes # Samsung SCX-4623 usb:v04E8p3434* libsane_matched=yes # Samsung MFP-65x usb:v04E8p3435* libsane_matched=yes # Samsung SCX-6545 usb:v04E8p3437* libsane_matched=yes # Samsung CLX-8385 usb:v04E8p3439* libsane_matched=yes # Samsung CLX-6220 usb:v04E8p343A* libsane_matched=yes # Samsung CLX-6250 usb:v04E8p343B* libsane_matched=yes # Samsung SCX-4825FN (SCX-4x25 Series) usb:v04E8p343C* libsane_matched=yes # Samsung CLX-3185 usb:v04E8p343D* libsane_matched=yes # Samsung CLX-8540 usb:v04E8p343F* libsane_matched=yes # Samsung SCX-4623FW usb:v04E8p3440* libsane_matched=yes # Samsung SCX-3205W (SCX-3200 Series) usb:v04E8p3441* libsane_matched=yes # Samsung SCX-6545X usb:v04E8p3442* libsane_matched=yes # Samsung SCX-6x55X usb:v04E8p3443* libsane_matched=yes # Samsung CLX-8385X usb:v04E8p3444* libsane_matched=yes # Samsung SCX-5835_5935X usb:v04E8p3446* libsane_matched=yes # Samsung SCX-4833FD | Samsung SCX-4835FD usb:v04E8p344B* libsane_matched=yes # Samsung SCX-3400 usb:v04E8p344F* libsane_matched=yes # Samsung SF-760 usb:v04E8p3450* libsane_matched=yes # Samsung SCX-4729FD usb:v04E8p3453* libsane_matched=yes # Samsung CLX-6260 usb:v04E8p3455* libsane_matched=yes # Samsung CLX-3300 Series usb:v04E8p3456* libsane_matched=yes # Samsung SCX-470x usb:v04E8p3457* libsane_matched=yes # Samsung CLX-4190 usb:v04E8p345A* libsane_matched=yes # Samsung SCX-4650 4x21S Series usb:v04E8p345B* libsane_matched=yes # Samsung M337x 387x 407x Series usb:v04E8p3460* libsane_matched=yes # Samsung M267x 287x Series usb:v04E8p3461* libsane_matched=yes # Samsung SCX-681x usb:v04E8p3466* libsane_matched=yes # Samsung C460 usb:v04E8p3468* libsane_matched=yes # Pentax DSmobile 600 usb:v04F9p2038* libsane_matched=yes # Aiptek Aiptek Pencam usb:v0553p0202* libsane_matched=yes # Mustek ScanExpress 1200 CU usb:v055Fp0001* libsane_matched=yes # Mustek ScanExpress 600 CU usb:v055Fp0002* libsane_matched=yes # Mustek ScanExpress 1200 UB | Trust Compact Scan USB 19200 usb:v055Fp0006* libsane_matched=yes # Mustek ScanExpress 1200 CU Plus usb:v055Fp0008* libsane_matched=yes # Mustek BearPaw 1200 F usb:v055Fp0010* libsane_matched=yes # Mustek ScanExpress A3 USB usb:v055Fp0210* libsane_matched=yes # Mustek BearPaw 2400 CS | Mustek BearPaw 2400 TA | Trust 240TH Easy Webscan Gold usb:v055Fp0218* libsane_matched=yes # Mustek BearPaw 2400 CS Plus | Mustek BearPaw 2400 TA Plus | Mustek Plug-n-Scan 2400 MT # Mustek Plug-n-Scan 2400 M | Packard Bell Diamond 2450 usb:v055Fp0219* libsane_matched=yes # Mustek BearPaw 2448 CS Plus | Mustek BearPaw 2448 TA Plus usb:v055Fp021A* libsane_matched=yes # Mustek BearPaw 1200 CU Plus | Packard Bell Diamond 1200 Plus usb:v055Fp021B* libsane_matched=yes # Mustek BearPaw 1200 CU Plus | Mustek BearPaw 1248 CU | Packard Bell Diamond 1200 Plus # Trust Direct WebScan 19200 usb:v055Fp021C* libsane_matched=yes # Mustek BearPaw 2400 CU Plus usb:v055Fp021D* libsane_matched=yes # Mustek BearPaw 1200 CS | Mustek BearPaw 1200 TA usb:v055Fp021E* libsane_matched=yes # Mustek ScanExpress 1248 UB usb:v055Fp021F* libsane_matched=yes # Mustek BearPaw 2448TA Pro usb:v055Fp0409* libsane_matched=yes # Artec/Ultima Ultima 2000 | Artec/Ultima Ultima 2000 e+ | Boeder Sm@rtScan Slim Edition # Fujitsu 1200CUS | Googlegear 2000 | Medion/Lifetec/Tevion/Cytron MD 4394 # Medion/Lifetec/Tevion/Cytron MD/LT 9375 | Medion/Lifetec/Tevion/Cytron MD/LT 9385 | Medion/Lifetec/Tevion/Cytron LT 9452 # Medion/Lifetec/Tevion/Cytron MD 9458 | Mustek BearPaw 1200 CU | Mustek BearPaw 2400 CU # Mustek ScanExpress 1200 UB Plus | Mustek ScanExpress 2400 USB | Mustek ScanMagic 1200 UB Plus # Packard Bell Diamond 1200 | Trust Compact Scan USB 19200 | Trust Flat Scan USB 19200 usb:v05D8p4002* libsane_matched=yes # Artec/Ultima E+ 48U | Medion/Lifetec/Tevion/Cytron MD9693 | Medion/Lifetec/Tevion/Cytron MD9705 # Medion/Lifetec/Tevion/Cytron MD4394 | Microstar MR 9791 usb:v05D8p4003* libsane_matched=yes # Artec/Ultima E+ Pro usb:v05D8p4004* libsane_matched=yes # Memorex MEM 48U usb:v05D8p4005* libsane_matched=yes # Trust Easy Webscan 19200 usb:v05D8p4006* libsane_matched=yes # Trust 240H Easy Webscan Gold usb:v05D8p4007* libsane_matched=yes # UMAX AstraSlim SE usb:v05D8p4009* libsane_matched=yes # UMAX AstraSlim 1200 SE usb:v05D8p4010* libsane_matched=yes # Yakumo Scan50 usb:v05D8p4011* libsane_matched=yes # Microtek ScanMaker X6USB usb:v05DAp0099* libsane_matched=yes # Microtek SlimScan C6 usb:v05DAp009A* libsane_matched=yes # Microtek ScanMaker V6USL usb:v05DAp00A3* libsane_matched=yes # Microtek ScanMaker V6UPL usb:v05DAp00B6* libsane_matched=yes # Microtek ScanMaker 4800 usb:v05DAp30CF* libsane_matched=yes # Microtek ScanMaker 3840 usb:v05DAp30D4* libsane_matched=yes # Microtek ScanMaker 3600 usb:v05DAp40B3* libsane_matched=yes # Microtek ScanMaker 3700 usb:v05DAp40B8* libsane_matched=yes # Microtek ScanMaker 3600 usb:v05DAp40CA* libsane_matched=yes # Microtek ScanMaker 3700 usb:v05DAp40CB* libsane_matched=yes # Microtek ScanMaker 3750 usb:v05DAp40DD* libsane_matched=yes # Microtek ScanMaker 3600 usb:v05DAp40FF* libsane_matched=yes # Microtek ScanMaker V6USL usb:v05DAp80A3* libsane_matched=yes # iVina 1200U usb:v0638p0268* libsane_matched=yes # Minolta Dimage Scan Dual II usb:v0638p026A* libsane_matched=yes # Avision AV600U usb:v0638p0A13* libsane_matched=yes # Minolta-QMS SC-110 usb:v0638p0A15* libsane_matched=yes # Avision DS610CU Scancopier | Minolta-QMS SC-215 | OKI S700 Scancopier usb:v0638p0A16* libsane_matched=yes # Avision AV610 | Avision AV600U Plus usb:v0638p0A18* libsane_matched=yes # Avision AV220 usb:v0638p0A23* libsane_matched=yes # Avision AV210 usb:v0638p0A24* libsane_matched=yes # Avision AV210 usb:v0638p0A25* libsane_matched=yes # Avision AV120 usb:v0638p0A27* libsane_matched=yes # Avision AV220C2 usb:v0638p0A2A* libsane_matched=yes # Avision AV220D2 usb:v0638p0A2B* libsane_matched=yes # Avision AV220+ usb:v0638p0A2C* libsane_matched=yes # Avision AV220C2-G usb:v0638p0A2D* libsane_matched=yes # Avision AV220C2-B usb:v0638p0A2E* libsane_matched=yes # Avision AV210C2-G usb:v0638p0A2F* libsane_matched=yes # Avision AV122 usb:v0638p0A33* libsane_matched=yes # Avision AV210C2 usb:v0638p0A3A* libsane_matched=yes # Avision AV121 usb:v0638p0A3C* libsane_matched=yes # Avision AV8300 usb:v0638p0A40* libsane_matched=yes # Avision AM3000 Series usb:v0638p0A41* libsane_matched=yes # Avision @V5100 usb:v0638p0A45* libsane_matched=yes # Avision AV8050U usb:v0638p0A4D* libsane_matched=yes # Avision AV3200SU usb:v0638p0A4E* libsane_matched=yes # Avision AV3730SU usb:v0638p0A4F* libsane_matched=yes # Avision AV610C2 usb:v0638p0A5E* libsane_matched=yes # Avision IT8300 usb:v0638p0A61* libsane_matched=yes # Avision AV3750SU usb:v0638p0A65* libsane_matched=yes # Avision AV3850SU usb:v0638p0A66* libsane_matched=yes # Avision AV8350 usb:v0638p0A68* libsane_matched=yes # Avision FB6080E usb:v0638p0A82* libsane_matched=yes # Avision FB2080E usb:v0638p0A84* libsane_matched=yes # Avision AV122 C2 usb:v0638p0A93* libsane_matched=yes # Avision AV220-G usb:v0638p0A94* libsane_matched=yes # Avision @V2500 usb:v0638p0AA1* libsane_matched=yes # Avision AV210D2+ usb:v0638p1A35* libsane_matched=yes # Minolta Elite II usb:v0686p4004* libsane_matched=yes # Minolta Dimage Scan Dual III usb:v0686p400D* libsane_matched=yes # Minolta Dimage Scan Elite 5400 usb:v0686p400E* libsane_matched=yes # AGFA SnapScan 1212U usb:v06BDp0001* libsane_matched=yes # AGFA SnapScan 1236u usb:v06BDp0002* libsane_matched=yes # Agfa Snapscan Touch usb:v06BDp0100* libsane_matched=yes # AGFA SnapScan 1212U_2 usb:v06BDp2061* libsane_matched=yes # AGFA SnapScan e40 usb:v06BDp208D* libsane_matched=yes # AGFA SnapScan e50 usb:v06BDp208F* libsane_matched=yes # AGFA SnapScan e20 usb:v06BDp2091* libsane_matched=yes # AGFA SnapScan e10 usb:v06BDp2093* libsane_matched=yes # AGFA SnapScan e25 usb:v06BDp2095* libsane_matched=yes # AGFA SnapScan e26 usb:v06BDp2097* libsane_matched=yes # AGFA SnapScan e52 usb:v06BDp20FD* libsane_matched=yes # AGFA SnapScan e42 usb:v06BDp20FF* libsane_matched=yes # UMAX Astra 4900 usb:v06DCp0020* libsane_matched=yes # Plustek OpticPro U12 | Plustek OpticPro UT12 | Plustek OpticPro 1212U # RevScan RevScan Orange R48Ti | Genius ColorPage Vivid III USB usb:v07B3p0001* libsane_matched=yes # Plustek OpticPro U12 usb:v07B3p0010* libsane_matched=yes # Plustek OpticPro U24 usb:v07B3p0011* libsane_matched=yes # Plustek OpticPro UT12 usb:v07B3p0013* libsane_matched=yes # Plustek OpticPro U24 usb:v07B3p0015* libsane_matched=yes # Plustek OpticPro UT12 | Plustek OpticPro UT16 | Plustek OpticPro UT24 usb:v07B3p0017* libsane_matched=yes # Plustek OpticPro 1248U | RevScan 19200i usb:v07B3p0400* libsane_matched=yes # Plustek OpticPro 1248U usb:v07B3p0401* libsane_matched=yes # Plustek OpticPro U16B usb:v07B3p0402* libsane_matched=yes # Plustek OpticPro U16B+ | Plustek OpticPro UT16B usb:v07B3p0403* libsane_matched=yes # Nortek MyScan 1200 | Plustek OpticPro S12 | Plustek OpticPro ST12 usb:v07B3p040B* libsane_matched=yes # Plustek OpticPro S24 usb:v07B3p040E* libsane_matched=yes # NeatReceipts Scanalizer Professional 2.5 | Plustek OpticSlim M12 usb:v07B3p0412* libsane_matched=yes # Plustek OpticSlim 1200 usb:v07B3p0413* libsane_matched=yes # Plustek OpticSlim 2400 usb:v07B3p0422* libsane_matched=yes # Plustek OpticSlim 2400 plus usb:v07B3p0454* libsane_matched=yes # Plustek Iriscan Express 2 usb:v07B3p045F* libsane_matched=yes # NeatReceipts Mobile Scanner usb:v07B3p0462* libsane_matched=yes # Plustek OpticBook 3600 usb:v07B3p0900* libsane_matched=yes # Corex 600c usb:v08F0p0002* libsane_matched=yes # Corex 800c usb:v08F0p0005* libsane_matched=yes # Xerox Phaser 6110MFP usb:v0924p3D5D* libsane_matched=yes # Xerox Phaser 3200MFP usb:v0924p3DA4* libsane_matched=yes # Xerox WorkCentre 4118 Series usb:v0924p420C* libsane_matched=yes # Xerox WorkCentre 3119 Series usb:v0924p4265* libsane_matched=yes # Xerox WorkCentre 3210 usb:v0924p4293* libsane_matched=yes # Xerox WorkCentre 3220 usb:v0924p4294* libsane_matched=yes # Pentax DSmobile 600 usb:v0A17p3210* libsane_matched=yes # Portable Peripheral Co., Ltd. Q-Scan USB001 (A4 portable scanner) usb:v0A53p1000* libsane_matched=yes # Portable Peripheral Co., Ltd. Q-Scan USB201 (A6 portable scanner) usb:v0A53p2000* libsane_matched=yes # Syscan TravelScan 460/464 | Ambir Visigo A4 usb:v0A82p4600* libsane_matched=yes # Syscan DocketPort 465 usb:v0A82p4802* libsane_matched=yes # Syscan DocketPort 665 usb:v0A82p4803* libsane_matched=yes # Syscan DocketPort 685/ Ambir DS685 usb:v0A82p480C* libsane_matched=yes # Syscan DocketPort 485 usb:v0A82p4810* libsane_matched=yes # Syscan TravelScan 662 usb:v0A82p6620* libsane_matched=yes # Canon CR-55 usb:v1083p160C* libsane_matched=yes # Canon DR-1210C usb:v1083p160F* libsane_matched=yes # Canon DR-4010C usb:v1083p1614* libsane_matched=yes # Canon DR-2510C usb:v1083p1617* libsane_matched=yes # Canon DR-X10C usb:v1083p1618* libsane_matched=yes # Canon CR-25 usb:v1083p161A* libsane_matched=yes # Canon DR-2010C usb:v1083p161B* libsane_matched=yes # Canon DR-3010C usb:v1083p161D* libsane_matched=yes # Canon DR-7090C usb:v1083p1620* libsane_matched=yes # Canon DR-9050C usb:v1083p1622* libsane_matched=yes # Canon DR-7550C usb:v1083p1623* libsane_matched=yes # Canon DR-6050C usb:v1083p1624* libsane_matched=yes # Canon DR-6010C usb:v1083p1626* libsane_matched=yes # Canon CR-190i usb:v1083p162B* libsane_matched=yes # Canon DR-6030C usb:v1083p1638* libsane_matched=yes # Canon CR-135i usb:v1083p1639* libsane_matched=yes # Digital Dream l' espion XS usb:v1183p0001* libsane_matched=yes # KONICA MINOLTA magicolor 1690MF usb:v132Bp2089* libsane_matched=yes # UMAX Astra 1220U usb:v1606p0010* libsane_matched=yes # UMAX Astra 1600U | UMAX Astra 2000U usb:v1606p0030* libsane_matched=yes # Umax UMAX 3400 usb:v1606p0050* libsane_matched=yes # Umax UMAX 3400 | Umax UMAX Astranet ia101 | Umax UMAX 3450 usb:v1606p0060* libsane_matched=yes # UMAX Astra 4400 | UMAX Astra 4450 usb:v1606p0070* libsane_matched=yes # UMAX Astra 2100U usb:v1606p0130* libsane_matched=yes # Umax UMAX 5400 usb:v1606p0160* libsane_matched=yes # UMAX Astra 2200 (SU) usb:v1606p0230* libsane_matched=yes # DCT DocketPort 487 usb:v1DCCp4810* libsane_matched=yes # Dell A920 usb:v413Cp5105* libsane_matched=yes # Dell Dell MFP Laser Printer 1815dn usb:v413Cp5124* libsane_matched=yes # Dell 1600n usb:v413Cp5250* libsane_matched=yes sane-backends-1.0.27/testsuite/tools/data/xml.ref0000664000175000017500000220005712775312262016637 00000000000000 unmaintained sane-abaton *none* *none* *none* *none* SCSI *none* *none* complete *none* All known modes and functions supported SCSI *none* *none* untested *none* Untested, use with caution unmaintained sane-agfafocus *none* *none* `http://www.agfa.com/' *none* SCSI *none* *none* untested *none* 6 bit gray SCSI *none* *none* untested *none* Lineart only? Untested. SCSI *none* *none* untested *none* gray only SCSI *none* *none* good *none* 3-pass SCSI *none* *none* good *none* 3-pass *none* *none* SCSI *none* *none* untested *none* gray only unmaintained sane-apple *none* *none* `http://developer.apple.com/' *none* SCSI *none* *none* good *none* 4bit, 16 shades of gray SCSI *none* *none* basic *none* 8bit, 256 shades of gray. The backend needs work especially in the quantization code but it may work. SCSI *none* *none* minimal *none* truecolor (needs much work) but it scans in non color modes. unmaintained sane-artec http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html *none* `http://www.artecusa.com/' *none* SCSI *none* *none* complete *none* all modes working SCSI *none* *none* complete *none* all modes working SCSI *none* *none* complete *none* f/w <= v1.92 basic, f/w >= v1.93 OK SCSI *none* *none* good *none* Scan head needs to return home before another scan can be started. SCSI *none* *none* complete *none* all modes working SCSI *none* *none* complete *none* all modes working `http://www.blackwidow.co.uk/' *none* SCSI *none* *none* complete *none* rebadged Artec AT3 `http://www.plustek.com/' *none* SCSI *none* *none* complete *none* rebadged Artec AM12S unmaintained sane-artec_eplus48u *none* *none* `http://www.artecusa.com/' *none* USB 0x05d8 0x4003 good *none* CIS scanner based on the GT6816 chip. Apparently all other devices are re-badged Artec scanners. USB 0x05d8 0x4004 minimal *none* Works up to 600dpi, but not 1200. Needs better calibration. See bug #310490 `http://www.medion.com' Sold by Aldi and Tchibo. USB 0x05d8 0x4003 good *none* *none* USB 0x05d8 0x4003 good *none* *none* USB 0x05d8 0x4003 good *none* Only scanners with product id 0x4003 will work; try the gt68xx backend, if your scanner has product id 0x4002 `http://www.trust-site.com' *none* USB 0x05d8 0x4006 good *none* *none* USB 0x05d8 0x4007 basic *none* Works up to 600 dpi `http://www.artecusa.com/' *none* USB 0x05d8 0x4005 good *none* *none* `http://www.microstar.de/' *none* USB 0x05d8 0x4003 good *none* *none* `http://www.umax.com/' `http://www.umax.com.tw/' `http://www.umax.de/en' `http://www.umax-europe.com' `http://www.umaxjapan.co.jp' `http://www.umax.com.cn' *none* USB 0x05d8 0x4009 good *none* *none* USB 0x05d8 0x4010 good *none* *none* `http://www.yakumo.com/' *none* USB 0x05d8 0x4011 good *none* *none* 0.5 sane-as6e http://as6edriver.sourceforge.net/ *none* `http://www.artecusa.com/' *none* Parport *none* *none* basic *none* Requires the program 'as6edriver' to run. `http://www.trust-site.com' Carefully check the model names. Trust uses similar names for completely different hardware. Parport *none* *none* basic *none* Requires the program 'as6edriver' to run. `http://www.dexxa.com' *none* Parport *none* *none* basic *none* Requires the program 'as6edriver' to run. Build: 296 sane-avision http://skull.piratehaven.org/~mike/sane/avision.html *none* `http://www.avision.com' *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* USB 0x0638 0x0a27 complete *none* sheetfed scanner USB 0x0638 0x0a3c good *none* sheetfed scanner USB 0x0638 0x0a33 good *none* sheetfed duplex scanner USB 0x0638 0x0a93 good *none* sheetfed duplex scanner USB 0x0638 0x0a24 complete *none* sheetfed scanner USB 0x0638 0x0a25 complete *none* sheetfed scanner USB 0x0638 0x0a3a complete *none* sheetfed scanner USB 0x0638 0x0a2f complete *none* sheetfed scanner USB 0x0638 0x1a35 complete *none* sheetfed scanner USB 0x0638 0x0a23 complete *none* duplex! sheetfed scanner USB 0x0638 0x0a2a complete *none* duplex! sheetfed scanner USB 0x0638 0x0a2b complete *none* duplex! sheetfed scanner USB 0x0638 0x0a2c complete *none* duplex! sheetfed scanner USB 0x0638 0x0a2d complete *none* duplex! sheetfed scanner USB 0x0638 0x0a2e complete *none* duplex! sheetfed scanner USB 0x0638 0x0a94 complete *none* duplex! sheetfed scanner SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* USB 0x0638 0x0a18 good *none* *none* USB 0x0638 0x0a18 good *none* *none* USB 0x0638 0x0a5e good *none* *none* USB 0x0638 0x0a41 basic *none* MFD USB 0x0638 0x0a16 good *none* 1 pass, 600 dpi, A4 SCSI *none* *none* complete *none* 1 pass, 600 dpi SCSI *none* *none* complete *none* 1 pass, 1200 dpi SCSI *none* *none* complete *none* 1 pass, 1200 dpi SCSI *none* *none* untested *none* 1 pass, 1200 dpi SCSI *none* *none* complete *none* 1 pass, ??? dpi USB 0x0638 0x0a13 good *none* 1 pass, 600 dpi SCSI *none* *none* untested *none* 1 pass, ??? dpi SCSI *none* *none* untested *none* 1 pass, ??? dpi SCSI *none* *none* untested *none* 1 pass, 2400 dpi SCSI *none* *none* untested *none* 1 pass, ??? dpi SCSI *none* *none* untested *none* 1 pass, ??? dpi SCSI *none* *none* untested *none* 1 pass, ??? dpi SCSI *none* *none* complete *none* 1 pass, ??? dpi SCSI *none* *none* complete *none* 1 pass, ??? dpi SCSI *none* *none* complete *none* 1 pass, ??? dpi SCSI *none* *none* untested *none* 1 pass, ??? dpi SCSI *none* *none* untested *none* 1 pass, ??? dpi SCSI *none* *none* untested *none* 1 pass, ??? dpi SCSI *none* *none* complete *none* 1 pass, ??? dpi USB 0x0638 0x0a4e complete *none* 1 pass, ??? dpi USB 0x0638 0x0a4f complete *none* 1 pass, ??? dpi USB 0x0638 0x0a65 complete *none* 1 pass, ??? dpi SCSI *none* *none* complete *none* 1 pass, ??? dpi USB 0x0638 0x0a66 complete *none* 1 pass, ??? dpi SCSI *none* *none* complete *none* 1 pass, 1200 dpi, A3 - duplex! - zero edge! USB 0x0638 0x0a82 complete *none* 1 pass, 1200 dpi, A3 - duplex! - zero edge! USB 0x0638 0x0a84 basic *none* 1 pass, 600 dpi, zero-edge SCSI *none* *none* complete *none* 1 pass, 1200 dpi, A3 USB 0x0638 0x0a4d complete *none* 1 pass, 1200 dpi, A3 - duplex! USB 0x0638 0x0a40 complete *none* 1 pass, 1200 dpi, A3 - duplex! USB 0x0638 0x0a68 complete *none* 1 pass, 1200 dpi, A3 - duplex! USB 0x0638 0x0a61 good *none* 1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors USB 0x0638 0x0aa1 untested *none* *none* USB 0x0638 0x0a45 good *none* 1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors SCSI *none* *none* basic *none* 1 pass, 600 dpi, A3 `http://www.hp.com' *none* USB 0x03f0 0x0701 complete *none* 1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi USB 0x03f0 0x0701 good *none* 1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi USB 0x03f0 0x0801 good *none* 1 pass, 2400 dpi - dual USB/SCSI interface USB 0x03f0 0x0801 good *none* 1 pass, 2400 dpi - dual USB/SCSI interface USB 0x03f0 0x0801 good *none* 1 pass, 1200 dpi - dual USB/SCSI interface USB 0x03f0 0x0b01 good *none* 1 pass, 4800 (?) dpi - USB 2.0 USB 0x03f0 0x0b01 good *none* 1 pass, 4800 (?) dpi - USB 2.0 USB 0x03f0 0x3905 good *none* 1 pass, 4800 (?) dpi - USB 2.0 USB 0x03f0 0x0b01 good *none* 1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far USB 0x03f0 0x3805 good *none* 1 pass, 4800 (?) dpi - USB 2.0 USB 0x03f0 0x3805 good *none* 1 pass, 4800 (?) dpi - USB 2.0 USB 0x03f0 0x3805 good *none* 1 pass, 4800 (?) dpi - USB 2.0 `http://www.minolta.com' *none* SCSI *none* *none* basic *none* *none* SCSI *none* *none* untested *none* *none* USB 0x0638 0x026a good *none* 1 pass, film-scanner USB 0x0686 0x4004 untested *none* 1 pass, film-scanner USB 0x0686 0x400d good *none* 1 pass, film-scanner USB 0x0686 0x400e good *none* 1 pass, film-scanner *none* *none* USB 0x0638 0x0a15 untested *none* *none* USB 0x0638 0x0a16 good *none* *none* *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* good *none* *none* `http://www.fujitsu.com' *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* USB 0x04c5 0x1029 untested *none* *none* USB 0x04c5 0x10ef good *none* *none* `http://www.kodak.com' *none* USB 0x040a 0x6001 untested *none* *none* USB 0x040a 0x6002 basic *none* *none* USB 0x040a 0x6003 untested *none* *none* USB 0x040a 0x6003 untested *none* *none* USB 0x040a 0x6004 untested *none* *none* USB 0x040a 0x6004 untested *none* *none* USB 0x040a 0x6005 good *none* *none* *none* *none* USB 0x0638 0x0268 untested *none* *none* *none* *none* USB 0x04a7 0x0424 complete *none* sheetfed scanner USB 0x04a7 0x0491 complete *none* sheetfed scanner USB 0x04a7 0x0479 complete *none* sheetfed scanner USB 0x04a7 0x048f complete *none* sheetfed scanner USB 0x04a7 0x0420 complete *none* sheetfed scanner USB 0x04a7 0x0421 complete *none* sheetfed scanner USB 0x04a7 0x047a complete *none* sheetfed scanner USB 0x04a7 0x0422 complete *none* sheetfed scanner USB 0x04a7 0x0390 complete *none* sheetfed scanner USB 0x04a7 0x047b complete *none* sheetfed scanner USB 0x04a7 0x0423 complete *none* sheetfed scanner USB 0x04a7 0x0493 complete *none* sheetfed scanner USB 0x04a7 0x0497 complete *none* sheetfed scanner USB 0x04a7 0x048f complete *none* sheetfed scanner USB 0x04a7 0x0498 complete *none* sheetfed scanner USB 0x04a7 0x0499 complete *none* sheetfed scanner *none* *none* USB 0x04a7 0x049c good *none* *none* USB 0x04a7 0x0477 good *none* *none* USB 0x04a7 0x049d good *none* *none* USB 0x04a7 0x0448 good *none* *none* USB 0x04a7 0x0490 good *none* *none* USB 0x04a7 0x0449 good *none* *none* USB 0x04a7 0x048c good *none* *none* USB 0x04a7 0x0476 good *none* *none* USB 0x04a7 0x044c good *none* *none* USB 0x04a7 0x048d good *none* *none* USB 0x04a7 0x04a7 good *none* *none* USB 0x04a7 0x0475 untested *none* *none* USB 0x04a7 0x048e untested *none* *none* USB 0x04a7 0x0446 untested *none* *none* USB 0x04a7 0x0495 untested *none* *none* USB 0x04a7 0x047c untested *none* *none* USB 0x04a7 0x0447 untested *none* *none* USB 0x04a7 0x0492 untested *none* *none* USB 0x04a7 0x0498 untested *none* *none* USB 0x04a7 0x0478 untested *none* *none* USB 0x04a7 0x049a untested *none* *none* *none* *none* USB 0x0638 0x0a16 good *none* 1 pass, 600 dpi, A4 *none* *none* SCSI *none* *none* basic *none* 1 pass, ??? dpi, A4 *none* *none* USB 0x0482 0x0335 untested *none* 1 pass, ??? dpi, A4 1.0-4 sane-bh http://www.martoneconsulting.com/sane-bh.html Supports Copiscan II scanners with Remote SCSI Controller (RSC) interface `http://www.bhscanners.com/' *none* SCSI *none* *none* good *none* Duplex Scanner with ACE - development model SCSI *none* *none* untested *none* Simplex Scanner SCSI *none* *none* good *none* Simplex Scanner (with ACE) - limited testing SCSI *none* *none* untested *none* Simplex Scanner with ACE SCSI *none* *none* untested *none* Simplex Scanner SCSI *none* *none* untested *none* Simplex Scanner (with ACE) 1.12 sane-canon http://www.rzg.mpg.de/~mpd/sane/ *none* `http://www.canon.com/' *none* SCSI *none* *none* good *none* 1 pass; flatbed scanner SCSI *none* *none* good *none* 1 pass; flatbed scanner SCSI *none* *none* good *none* 1 pass; flatbed scanner SCSI *none* *none* good *none* 1 pass; flatbed scanner SCSI *none* *none* good *none* 1 pass; film scanner SCSI *none* *none* good *none* 1 pass; 36bit film scanner SCSI *none* *none* good *none* 1 pass; flatbed scanner `http://www.apple.com/' *none* SCSI *none* *none* good *none* Rebadged CanoScan 300 0.1 sane-canon630u http://canon-fb630u.sourceforge.net/ *none* `http://www.canon.com/' *none* USB 0x04a9 0x2204 good *none* OK USB 0x04a9 0x2204 good *none* OK 38 sane-canon_dr http://www.thebility.com/canon/ Backend updated for SANE release 1.0.23, see sane-canon_dr manpage `http://www.canon.com/' *none* USB 0x1083 0x161a untested *none* Please test! USB 0x1083 0x160c untested *none* Please test! USB SCSI 0x1083 0x1639 untested *none* Please test! USB SCSI 0x04a9 0x1602 untested *none* Please test! USB SCSI 0x04a9 0x1602 untested *none* Same as CR-180? Please test! USB SCSI 0x1083 0x162b untested *none* Please test! USB 0x04a9 0x2222 untested *none* Older version? Please test! USB 0x1083 0x160f untested *none* Later version? Please test! USB 0x1083 0x161b complete *none* Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions. USB *none* *none* untested *none* Mac version of DR-2010C? Please test! USB 0x04a9 0x160a complete *none* Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration. USB 0x04a9 0x160a untested *none* Same as DR-2050C? Please test! USB SCSI 0x04a9 0x1601 complete *none* Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration USB 0x1083 0x1617 complete *none* Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions USB *none* *none* untested *none* Mac version of DR-2510C? Please test! USB SCSI 0x04a9 0x1608 complete *none* Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration USB 0x1083 0x161d good *none* Minimal testing, settings copied from DR-2510C SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Almost works, need to investigate traces from windows driver USB SCSI 0x04a9 0x1609 untested *none* Almost works, need to investigate traces from windows driver USB 0x1083 0x1614 good *none* Binary/HT/Gray/Color, Simplex/Duplex working. Multistream unsupported. USB *none* *none* untested *none* Please test! USB *none* *none* untested *none* Please test! USB 0x04a9 0x1606 untested *none* Please test! SCSI *none* *none* good *none* LineArt, Duplex working, cannot read buttons or screen? SCSI *none* *none* basic *none* Grayscale works, LineArt might SCSI *none* *none* untested *none* Please test! USB SCSI 0x1083 0x1626 untested *none* Please test! USB SCSI 0x1083 0x1638 untested *none* Please test! USB SCSI 0x1083 0x1624 good *none* Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode USB SCSI 0x04a9 0x1607 good *none* Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported USB SCSI 0x04a9 0x1604 untested *none* Please test! USB SCSI 0x1083 0x1620 good *none* ADF and flatbed work USB SCSI 0x1083 0x1623 untested *none* Assumed compatible with DR-6050C USB SCSI 0x04a9 0x160b good *none* Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported USB SCSI 0x1083 0x1622 good *none* Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode USB SCSI 0x04a9 0x1603 good *none* Simplex, duplex, all resolutions, binary/ht/gray/color, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported USB SCSI 0x1083 0x1618 untested *none* Please test! 0.33 sane-canon_pp http://canon-fb330p.sourceforge.net *none* `http://www.canon.com/' *none* Parport (ECP) *none* *none* unsupported *none* Rebadged Avision, different command set Parport (ECP) *none* *none* unsupported *none* Rebadged Avision, different command set Parport (ECP) *none* *none* basic *none* Newly added support Parport (ECP) *none* *none* basic *none* Newly added support Parport (ECP) *none* *none* good *none* *none* Parport (ECP) *none* *none* good *none* *none* Parport (ECP) *none* *none* good *none* *none* Parport (ECP) *none* *none* good *none* *none* Parport (ECP) *none* *none* good *none* Just an N640P in a different box? 2 sane-cardscan http://www.thebility.com/cardscan/ Backend updated for SANE release 1.0.21, see sane-cardscan manpage `http://www.cardscan.com/' *none* USB 0x08f0 0x0005 good *none* 4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner USB 0x08f0 0x0002 basic *none* 4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner 0.4.3 sane-coolscan http://andreas.rick.free.fr/sane/ *none* `http://www.nikon.com/' *none* SCSI *none* *none* basic *none* The LS-20 has been replaced by the LS-30 SCSI *none* *none* basic *none* alpha: only 24/30 bit RGB + 32/40 bit RGBI SCSI *none* *none* basic *none* alpha: only 24/36 bit + RGB 32/48 bit RGBI SCSI *none* *none* basic *none* Doesn't support gamma correction 0.1.8 sane-coolscan2 http://coolscan2.sourceforge.net/ *none* `http://www.nikon.com/' *none* SCSI *none* *none* complete *none* working -- model available to developer SCSI *none* *none* good *none* *none* USB 0x04b0 0x4000 complete *none* *none* IEEE-1394 *none* *none* good *none* needs linux kernel 2.4.19 or later USB 0x04b0 0x4001 minimal *none* *none* USB 0x04b0 0x4001 minimal /unsupported/nikon-ls50-ed.html *none* USB 0x04b0 0x4002 untested /unsupported/nikon-ls5000-ed.html May work, similar to LS 50 ED, but untested. Please tell us if it works. IEEE-1394 *none* *none* good *none* needs linux kernel 2.4.19 or later 1.0.0 sane-coolscan3 *none* *none* `http://www.nikon.com/' *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* Rebadged LS 30? USB 0x04b0 0x4000 complete *none* *none* USB 0x04b0 0x4000 complete *none* Rebadged LS 40? USB 0x04b0 0x4001 minimal /unsupported/nikon-ls50-ed.html *none* USB 0x04b0 0x4001 minimal /unsupported/nikon-ls50-ed.html Rebadged LS 50? SCSI *none* *none* good *none* *none* IEEE-1394 *none* *none* good *none* needs linux kernel 2.4.19 or later USB 0x04b0 0x4002 untested /unsupported/nikon-ls5000-ed.html May work, similar to LS 50 ED, but untested. Please tell us if it works. IEEE-1394 *none* *none* good *none* needs linux kernel 2.4.19 or later 1.2 sane-dc25 mailto:peter@fales-lorenz.net *none* `http://www.kodak.com/global/en/service/digCam/dc25/dc25.shtml' *none* Serial port *none* *none* complete *none* *none* Serial port *none* *none* basic *none* DC-20 untested by author but reported to work 0.0 sane-dc210 mailto:peter@fales-lorenz.net *none* `http://www.kodak.com/global/en/service/digCam/dc210/dc210.shtml' *none* Serial port *none* *none* basic *none* *none* 0.0 sane-dc240 mailto:peter@fales-lorenz.net *none* `http://www.kodak.com/global/en/service/products/ekn006568.jhtml' *none* Serial port *none* *none* good *none* Use gphoto2 backend to get USB support *none* *none* *none* *none* `http://www.dell.com/' *none* Ethernet USB 0x413c 0x5250 basic *none* Supports colour and monochrome scans over ethernet (USB not supported) 1.0.13 sane-dll mailto:henning@meier-geinitz.de *none* Dynamic loading of shared-library backends. *none* *none* unmaintained sane-dmc *none* *none* `http://www.polaroid.com/' *none* SCSI *none* *none* good *none* *none* 20 sane-epjitsu http://www.thebility.com/epjitsu/ Backend updated for SANE release 1.0.21, see sane-epjitsu manpage `http://www.fujitsu.com/' *none* USB 0x04c5 0x10c7 basic *none* A6-size flatbed, 300/600 dpi, color/gray/binary USB 0x04c5 0x1156 good *none* Duplex, 150/225/300/600 dpi, color/gray/binary, AC/USB power, buttons/sensors all supported. Scanner always scans in _triplex_ color, fast USB required. USB 0x04c5 0x117f good *none* Same as S300, with different usb id USB 0x04c5 0x1200 unsupported *none* Beta version of backend source available, which works well, but breaks support for other epjitsu scanners. See http://ubuntuforums.org/showthread.php?t=1678335 USB 0x04c5 0x11ed good *none* Same as S300, with different usb id unmaintained sane-epson http://www.khk.net/sane *none* `http://www.epson.com/' *none* SCSI Parport *none* *none* good *none* *none* SCSI Parport *none* *none* good *none* US version of GT-5000 SCSI Parport *none* *none* good *none* *none* SCSI Parport *none* *none* good *none* US version of GT-6000 SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* Parport *none* *none* good *none* *none* Parport *none* *none* good *none* US version of GT-6500 Parport *none* *none* good *none* US version of GT-9000 SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* complete *none* US version of GT-7000 SCSI *none* *none* complete *none* *none* USB 0x04b8 0x0101 complete *none* *none* USB 0x04b8 0x0103 complete *none* *none* USB 0x04b8 0x010c complete *none* *none* SCSI *none* *none* complete *none* *none* USB 0x04b8 0x0104 complete *none* *none* USB 0x04b8 0x0104 complete *none* with TPU SCSI USB 0x04b8 0x010b complete *none* *none* SCSI USB 0x04b8 0x010a complete *none* *none* USB 0x04b8 0x0110 complete *none* *none* USB 0x04b8 0x011e complete *none* *none* USB 0x04b8 0x011b complete *none* *none* USB IEEE-1394 0x04b8 0x0112 complete *none* *none* USB IEEE-1394 0x04b8 0x011c complete *none* US version of the GT-9800 USB 0x04b8 0x0128 complete *none* US version of the GT-X700 USB 0x04b8 0x012a complete *none* US version of the GT-X800 SCSI *none* *none* complete *none* US version of GT-9500 SCSI *none* *none* complete *none* *none* SCSI USB IEEE-1394 0x04b8 0x0107 complete *none* *none* SCSI USB IEEE-1394 0x04b8 0x010e complete *none* *none* SCSI *none* *none* unsupported http://www.vjet.demon.co.uk/scanner/ A better backend for the FilmScan 200 can be found at <A HREF= "http://www.vjet.demon.co.uk/scanner/ ">http://www.vjet.demon.co.uk/scanner/</A> USB 0x04b8 0x0802 good *none* *none* USB 0x04b8 0x080e good *none* *none* USB 0x04b8 0x080e good *none* *none* USB 0x04b8 0x080d good *none* *none* USB 0x04b8 0x0819 good *none* *none* USB 0x04b8 0x082b good *none* *none* USB 0x04b8 0x0801 good *none* *none* USB 0x04b8 0x0801 good *none* *none* USB 0x04b8 0x0808 good *none* *none* USB 0x04b8 0x0805 good *none* *none* USB 0x04b8 0x0805 good *none* *none* USB 0x04b8 0x0813 good *none* *none* USB 0x04b8 0x0813 good *none* *none* USB 0x04b8 0x0807 good *none* *none* USB 0x04b8 0x0806 good *none* *none* USB 0x04b8 0x080f good *none* *none* USB 0x04b8 0x0810 good *none* *none* USB 0x04b8 0x0811 good *none* *none* USB 0x04b8 0x0818 good *none* *none* USB 0x04b8 0x0818 good *none* *none* USB 0x04b8 0x0818 good *none* *none* USB 0x04b8 0x0820 good *none* *none* USB 0x04b8 0x0818 good *none* *none* USB 0x04b8 0x082b good *none* *none* USB 0x04b8 0x082b good *none* *none* USB 0x04b8 0x082e good *none* *none* USB 0x04b8 0x0838 good *none* *none* USB 0x04b8 0x082f good *none* *none* USB 0x04b8 0x0815 good *none* *none* USB 0x04b8 0x0815 good *none* *none* USB IEEE-1394 0x04b8 0x012c good *none* *none* USB IEEE-1394 0x04b8 0x012c good *none* *none* 1.0.124 sane-epson2 *none* *none* `http://www.epson.com/' *none* parallel SCSI *none* *none* good http://www.epson.com/ overseas version of the GT-5000 USB 0x04b8 0x0815 good *none* overseas version of the LP-A500 USB Network 0x04b8 0x0815 good *none* network interface supported<br>AcuLaser CX11 with network interface and fax USB 0x04b8 0x0835 good *none* network interface probably supported USB Network 0x04b8 0x0846 good *none* network interface supported<br>all-in-one<br>overseas version of the EP-801A USB 0x04b8 0x0852 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0844 good *none* network interface probably supported<br>all-in-one<br>overseas version of the EP-901A USB 0x04b8 0x0853 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x010d unsupported *none* all-in-one USB 0x04b8 0x011a unsupported *none* all-in-one USB 0x04b8 0x0802 good *none* all-in-one USB 0x04b8 0x0801 good *none* all-in-one USB 0x04b8 0x0108 unsupported *none* all-in-one USB 0x04b8 0x0850 unsupported *none* supported by the epkowa backend plus non-free interpreter USB Network 0x04b8 0x0846 good *none* network interface supported<br>all-in-one USB 0x04b8 0x0852 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0844 good *none* network interface probably supported<br>all-in-one USB 0x04b8 0x0844 good *none* network interface probably supported<br>all-in-one USB 0x04b8 0x0853 unsupported *none* supported by the epkowa backend plus non-free interpreter SCSI parallel *none* *none* good *none* overseas version of the GT-6000 SCSI *none* *none* good *none* *none* parallel *none* *none* good *none* overseas version of the GT-5400 SCSI *none* *none* good *none* overseas version of the GT-8000 *none* *none* *none* unsupported *none* overseas version of the GT-8500 parallel *none* *none* good *none* overseas version of the GT-9000 SCSI USB 0x04b8 0x0107 complete *none* IEEE1394 untested SCSI USB 0x04b8 0x010e complete *none* IEEE1394 untested SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* IEEE1394 untested SCSI *none* *none* good *none* IEEE1394 untested SCSI USB 0x04b8 0x0126 good *none* network interface unsupported<br>IEEE1394 untested SCSI *none* *none* untested *none* *none* SCSI USB 0x04b8 0x0109 good *none* IEEE1394 untested SCSI *none* *none* good *none* IEEE1394 untested USB 0x04b8 0x0129 good *none* network interface unsupported<br>IEEE1394 untested USB 0x04b8 0x0136 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012b good *none* network interface probably supported USB Ethernet 0x04b8 0x0138 unsupported *none* supported by the epkowa backend plus non-free interpreter SCSI *none* *none* complete *none* overseas version of the GT-9500 SCSI *none* *none* complete *none* overseas version of the GT-9600 SCSI *none* *none* untested *none* overseas version of the ES-8000 SCSI USB 0x04b8 0x0107 complete *none* IEEE1394 untested<br>overseas version of the ES-2000 SCSI USB 0x04b8 0x0109 good *none* IEEE1394 untested<br>overseas version of the ES-8500 SCSI USB 0x04b8 0x010e complete *none* IEEE1394 untested<br>overseas version of the ES-2200 SCSI USB *none* *none* untested *none* IEEE1394 option SCSI USB *none* *none* untested *none* *none* USB 0x04b8 0x0129 good *none* network interface probably supported<br>IEEE1394 untested<br>overseas version of the ES-10000G USB IEEE1394 *none* *none* untested *none* network interface probably supported USB IEEE1394 *none* *none* untested *none* network interface probably supported USB IEEE1394 0x04b8 0x080a unsupported *none* Film scanner USB IEEE1394 *none* *none* unsupported *none* *none* SCSI *none* *none* minimal *none* will be supported USB 0x04b8 0x0133 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0102 unsupported *none* *none* USB 0x04b8 0x012b good *none* network interface probably supported<br>overseas version of the ES-H300 *none* *none* *none* untested *none* *none* parallel SCSI *none* *none* good *none* *none* parallel *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI Parport *none* *none* good *none* *none* parallel *none* *none* good *none* overseas version of the GT-5400 USB 0x04b8 0x0103 complete *none* *none* USB 0x04b8 0x010c complete *none* *none* SCSI *none* *none* complete *none* *none* USB 0x04b8 0x0101 complete *none* *none* USB 0x04b8 0x010f unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x011d unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0120 unsupported *none* supported by the snapscan backend SCSI *none* *none* complete *none* SCSI version of the GT-7600U USB 0x04b8 0x0104 complete *none* USB version of the GT-7600S USB 0x04b8 0x0104 complete *none* GT-7600U with TPU option bundled USB 0x04b8 0x010b complete *none* *none* SCSI *none* *none* good *none* *none* USB 0x04b8 0x0110 complete *none* *none* USB 0x04b8 0x0110 good *none* *none* USB 0x04b8 0x011e complete *none* *none* USB 0x04b8 0x011f unsupported *none* *none* *none* *none* *none* untested *none* *none* SCSI USB 0x04b8 0x010a complete *none* *none* SCSI USB 0x04b8 0x010a good *none* GT-8700U with TPU option bundled parallel *none* *none* good *none* *none* USB 0x04b8 0x011b complete *none* *none* USB 0x04b8 0x0116 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* USB 0x04b8 0x0112 complete *none* IEEE1394 untested USB 0x04b8 0x011c complete *none* IEEE1394 untested SCSI *none* *none* good *none* overseas version of the ES-6000 SCSI *none* *none* good *none* IEEE1394 untested<br>overseas version of the ES-6000H SCSI *none* *none* untested *none* overseas version of the ES-8000 SCSI USB 0x04b8 0x0126 good *none* IEEE1394 untested<br>overseas version of the ES-7000H USB Ethernet 0x04b8 0x0138 unsupported *none* supported by the epkowa backend plus non-free interpreter SCSI *none* *none* good *none* IEEE1394 untested<br>overseas version of the ES-9000H USB 0x04b8 0x0133 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0121 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0122 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0121 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0122 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0118 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012d unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012e unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012f unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0131 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0137 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0136 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012d unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0131 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0128 complete *none* IEEE1394 untested USB 0x04b8 0x0119 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0130 unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012a complete *none* film area guide mode not supported<br>IEEE1394 untested USB 0x04b8 0x013a unsupported http://www.avasys.jp/lx-bin2/linux/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012c good *none* IEEE1394 untested USB 0x04b8 0x0135 good *none* IEEE1394 untested *none* *none* *none* untested *none* business all-in-one; scanner is a ES-7000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-9000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-7000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-9000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-7000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-9000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-9000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-9000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-7000H *none* *none* *none* untested *none* business all-in-one; scanner is a ES-9000H USB Network 0x04b8 0x0815 good *none* network interface supported<br>business all-in-one USB 0x04b8 0x0843 good *none* network interface probably supported<br>business all-in-one USB 0x04b8 0x0817 good *none* network interface probably supported<br>business all-in-one USB 0x04b8 0x0817 good *none* network interface probably supported<br>business all-in-one<br>LP-M5500 with the fax option bundled USB 0x04b8 0x0833 good *none* network interface probably supported<br>business all-in-one USB 0x04b8 0x0834 good *none* network interface probably supported<br>business all-in-one USB 0x04b8 0x0830 good *none* all-in-one USB 0x04b8 0x0841 good *none* all-in-one<br>overseas version of the PX-401A USB 0x04b8 0x084f good *none* all-in-one USB 0x04b8 0x0848 good *none* all-in-one USB 0x04b8 0x0854 good *none* all-in-one USB 0x04b8 0x0847 good *none* network interface probably supported<br>all-in-one<br>overseas version of the PX-601F USB 0x04b8 0x0814 good *none* all-in-one USB 0x04b8 0x081a good *none* all-in-one USB 0x04b8 0x0827 good *none* all-in-one USB 0x04b8 0x083c good *none* all-in-one USB 0x04b8 0x083c good *none* network interface probably supported<br>all-in-one USB 0x04b8 0x0806 good *none* all-in-one USB 0x04b8 0x0811 good *none* all-in-one USB 0x04b8 0x081c good *none* all-in-one USB 0x04b8 0x0810 good *none* all-in-one USB 0x04b8 0x082a good *none* all-in-one USB 0x04b8 0x0837 good *none* all-in-one USB 0x04b8 0x081d good *none* all-in-one USB 0x04b8 0x0828 good *none* all-in-one USB 0x04b8 0x0836 good *none* all-in-one USB 0x04b8 0x0829 good *none* all-in-one<br>PM-A970 with network interface USB 0x04b8 0x0841 good *none* all-in-one USB 0x04b8 0x084d good *none* all-in-one USB 0x04b8 0x084a good *none* network interface probably supported<br>all-in-one USB 0x04b8 0x0856 good *none* all-in-one USB 0x04b8 0x0847 good *none* network interface probably supported USB 0x04b8 0x080e good *none* all-in-one USB 0x04b8 0x082f good *none* all-in-one USB 0x04b8 0x0838 good *none* all-in-one USB 0x04b8 0x0819 good *none* all-in-one USB 0x04b8 0x082e good *none* all-in-one USB 0x04b8 0x0839 good *none* all-in-one USB 0x04b8 0x083a good *none* all-in-one SCSI *none* *none* unsupported *none* supported by the umax backend<br>rebadged UMAX Astra 1200S USB 0x04b8 0x0103 complete *none* overseas version of the GT-6600U SCSI *none* *none* complete *none* overseas version of the GT-7000S USB 0x04b8 0x0101 complete *none* overseas version of the GT-7000U USB 0x04b8 0x010c complete *none* overseas version of the GT-6700U USB 0x04b8 0x0114 unsupported *none* supported by the snapscan backend SCSI *none* *none* complete *none* overseas version of the GT-7600S USB 0x04b8 0x0104 complete *none* overseas version of the GT-7600U USB 0x04b8 0x0104 complete *none* Perfection 1200U with TPU option bundled<br>overseas version of the GT-7600UF USB 0x04b8 0x010b complete *none* overseas version of the GT-7700U USB 0x04b8 0x010f unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x010f unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x011d unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x011d unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0120 unsupported *none* supported by the snapscan backend<br>overseas version of the GT-7400 SCSI *none* *none* unsupported *none* *none* SCSI USB 0x04b8 0x010a complete *none* overseas version of the GT-8700 SCSI USB 0x04b8 0x010a good *none* overseas version of the GT-8700F USB 0x04b8 0x0110 complete *none* overseas version of the GT-8200U USB 0x04b8 0x0110 good *none* overseas version of the GT-8200UF USB 0x04b8 0x011e complete *none* overseas version of the GT-8300UF USB 0x04b8 0x011f unsupported *none* supported by the snapscan backend USB 0x04b8 0x011f unsupported *none* supported by the snapscan backend<br>overseas version of the GT-8400UF USB 0x04b8 0x011b complete *none* overseas version of the GT-9300UF USB IEEE-1394 0x04b8 0x0112 complete *none* overseas version of the GT-9700F USB 0x04b8 0x0121 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0121 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0116 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB IEEE-1394 0x04b8 0x011c complete *none* overseas version of the GT-9800F USB 0x04b8 0x0122 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0122 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0118 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0119 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0128 complete *none* IEEE1394 untested<br>overseas version of the GT-X700 USB 0x04b8 0x012a good *none* film area guide mode not supported<br>IEEE1394 untested<br>overseas version of the GT-X800 USB IEEE1394 *none* *none* untested *none* seems to be a 4990 PHOTO with additional software USB 0x04b8 0x012d unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0131 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012d unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012e unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0131 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012f unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0130 unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x013a unsupported http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x012c good *none* IEEE1394 untested<br>overseas version of the GT-X900 USB 0x04b8 0x012c good *none* IEEE1394 untested<br>overseas version of the GT-X900 USB 0x04b8 0x080c unsupported *none* supported by the snapscan backend<br>all-in-one USB 0x04b8 0x0830 good *none* all-in-one USB 0x04b8 0x0830 good *none* all-in-one USB 0x04b8 0x0802 good *none* all-in-one<br>overseas version of the CC-570L USB 0x04b8 0x0802 good *none* all-in-one<br>overseas version of the CC-570L USB 0x04b8 0x080e good *none* all-in-one<br>overseas version of the PX-A550 USB 0x04b8 0x080e good *none* all-in-one<br>overseas version of the PX-A550 USB 0x04b8 0x080e good *none* all-in-one USB 0x04b8 0x0818 good *none* all-in-one USB 0x04b8 0x0818 good *none* all-in-one USB *none* *none* untested *none* all-in-one USB 0x04b8 0x082f good *none* all-in-one<br>overseas version of the PX-A620 USB 0x04b8 0x0820 good *none* all-in-one USB 0x04b8 0x0820 good *none* all-in-one USB 0x04b8 0x083f unsupported http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x083f unsupported http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x080d good *none* all-in-one USB 0x04b8 0x080d good *none* all-in-one USB 0x04b8 0x0819 good *none* all-in-one<br>overseas version of the PX-A650 USB 0x04b8 0x0819 good *none* all-in-one<br>overseas version of the PX-A650 USB 0x04b8 0x082b good *none* all-in-one USB 0x04b8 0x082b good *none* all-in-one USB 0x04b8 0x0801 good *none* all-in-one<br>overseas version of the CC-600PX USB 0x04b8 0x0801 good *none* all-in-one<br>overseas version of the CC-600PX USB 0x04b8 0x0808 good *none* all-in-one USB 0x04b8 0x0808 good *none* all-in-one USB 0x04b8 0x083f unsupported http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x083f unsupported http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0821 unsupported *none* may work with the snapscan backend<br>all-in-one with FAX USB 0x04b8 0x0821 unsupported *none* may work with the snapscan backend<br>all-in-one with FAX USB 0x04b8 0x082e good *none* all-in-one<br>overseas version of the PX-A720 USB 0x04b8 0x082e good *none* all-in-one<br>overseas version of the PX-A720 USB 0x04b8 0x0805 good *none* all-in-one<br>mistakenly thinks its a PX-A650 USB 0x04b8 0x0805 good *none* all-in-one<br>mistakenly thinks its a PX-A650 USB 0x04b8 0x0813 good *none* all-in-one USB 0x04b8 0x0813 good *none* all-in-one USB 0x04b8 0x0831 unsupported *none* may work with the snapscan backend<br>all-in-one with FAX USB 0x04b8 0x0831 unsupported *none* may work with the snapscan backend<br>all-in-one with FAX USB 0x04b8 0x0838 good *none* all-in-one<br>overseas version of the PX-A640 USB 0x04b8 0x0838 good *none* all-in-one<br>overseas version of the PX-A640 USB 0x04b8 0x081f good *none* all-in-one USB 0x04b8 0x081f good *none* all-in-one USB 0x04b8 0x0839 good *none* all-in-one<br>overseas version of the PX-A740 USB 0x04b8 0x0839 good *none* all-in-one<br>overseas version of the PX-A740 USB 0x04b8 0x083a good *none* all-in-one<br>overseas version of the PX-FA700 USB 0x04b8 0x083a good *none* all-in-one<br>overseas version of the PX-FA700 USB 0x04b8 0x0818 good *none* all-in-one USB *none* *none* good *none* all-in-one USB 0x04b8 0x082f good *none* all-in-one<br>overseas version of the PX-A620 USB 0x04b8 0x0820 good *none* all-in-one USB 0x04b8 0x083f unsupported http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0819 good *none* all-in-one<br>overseas version of the PX-A650 USB 0x04b8 0x0819 good *none* all-in-one<br>DX4800 + card reader USB 0x04b8 0x082b good *none* all-in-one USB 0x04b8 0x082e good *none* all-in-one<br>overseas version of the PX-A720 USB 0x04b8 0x0831 unsupported *none* may work with the snapscan backend<br>all-in-one with FAX USB 0x04b8 0x0838 good *none* all-in-one<br>overseas version of the PX-A640 USB 0x04b8 0x0839 good *none* all-in-one<br>overseas version of the PX-A740 USB 0x04b8 0x083a good *none* all-in-one<br>overseas version of the PX-FA700 USB 0x04b8 0x0848 good *none* all-in-one USB 0x04b8 0x0854 good *none* all-in-one USB 0x04b8 0x0847 good *none* network interface probably supported<br>all-in-one<br>overseas version of the PX-601F USB 0x04b8 0x0855 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0848 good *none* all-in-one USB 0x04b8 0x0854 good *none* all-in-one USB 0x04b8 0x0847 good *none* network interface probably supported<br>all-in-one<br>overseas version of the PX-601F USB 0x04b8 0x0855 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0850 unsupported *none* supported by the epkowa backend plus non-free interpreter USB Network 0x04b8 0x0846 good *none* network interface supported<br>all-in-one<br>overseas version of the EP-801A USB 0x04b8 0x0852 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0844 good *none* network interface probably supported<br>all-in-one<br>overseas version of the EP-901A USB 0x04b8 0x0853 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x080f good *none* all-in-one USB 0x04b8 0x080f good *none* all-in-one USB 0x04b8 0x080f good *none* all-in-one USB 0x04b8 0x0807 good *none* all-in-one USB 0x04b8 0x0807 good *none* all-in-one USB 0x04b8 0x081a good *none* all-in-one<br>overseas version of the PM-A750 USB 0x04b8 0x081a good *none* all-in-one<br>overseas version of the PM-A750 USB 0x04b8 0x0827 good *none* all-in-one<br>overseas version of the PM-A820 USB 0x04b8 0x083c good *none* all-in-one<br>overseas version of the PM-A840 USB 0x04b8 0x0827 good *none* all-in-one<br>overseas version of the PM-A820 USB 0x04b8 0x083c good *none* all-in-one<br>overseas version of the PM-A840 USB 0x04b8 0x0827 good *none* all-in-one<br>overseas version of the PM-A820 USB 0x04b8 0x0806 good *none* all-in-one<br>overseas version of the PM-A850 USB 0x04b8 0x083c good *none* all-in-one<br>overseas version of the PM-A840 USB 0x04b8 0x0811 good *none* all-in-one<br>overseas version of the PM-A870 USB 0x04b8 0x0811 good *none* all-in-one<br>overseas version of the PM-A870 USB 0x04b8 0x081c good *none* all-in-one<br>overseas version of the PM-A890 USB 0x04b8 0x081c good *none* all-in-one<br>overseas version of the PM-A890 USB 0x04b8 0x0837 good *none* all-in-one<br>overseas version of the PM-A940 USB 0x04b8 0x0837 good *none* all-in-one<br>overseas version of the PM-A940 USB 0x04b8 0x0837 good *none* all-in-one<br>overseas version of the PM-A940 USB 0x04b8 0x0810 good *none* all-in-one<br>overseas version of the PM-A900 USB 0x04b8 0x0850 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0846 good *none* network interface probably supported<br>all-in-one<br>overseas version of the EP-801A USB 0x04b8 0x0852 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0844 good *none* network interface probably supported<br>all-in-one<br>overseas version of the EP-901A USB 0x04b8 0x0841 good *none* all-in-one<br>overseas version of the PX-401A USB 0x04b8 0x084d good *none* all-in-one<br>overseas version of the PX-402A USB 0x04b8 0x0849 good *none* all-in-one USB 0x04b8 0x084f good *none* all-in-one USB 0x04b8 0x0848 good *none* all-in-one USB 0x04b8 0x084a good *none* network interface probably supported<br>all-in-one<br>overseas version of the PX-501A USB 0x04b8 0x0851 good *none* network interface probably supported<br>all-in-one USB 0x04b8 0x0856 good *none* all-in-one<br>overseas version of the PX-502A USB 0x04b8 0x0841 good *none* all-in-one<br>overseas version of the PX-401A USB 0x04b8 0x084d good *none* all-in-one<br>overseas version of the PX-402A USB 0x04b8 0x085c untested *none* all-in-one USB 0x04b8 0x0849 good *none* all-in-one USB 0x04b8 0x0849 good *none* all-in-one USB 0x04b8 0x084f good *none* all-in-one USB 0x04b8 0x084a good *none* network interface probably supported<br>all-in-one<br>overseas version of the PX-501A USB 0x04b8 0x084a good *none* all-in-one USB 0x04b8 0x0851 good *none* network interface probably supported<br>all-in-one USB 0x04b8 0x0856 good *none* all-in-one<br>overseas version of the PX-502A USB 0x04b8 0x0847 good *none* network interface probably supported<br>all-in-one<br>overseas version of the PX-601F USB 0x04b8 0x0855 unsupported *none* supported by the epkowa backend plus non-free interpreter USB 0x04b8 0x0105 untested *none* apparently mostly the same as the Stylus Scan 2500 USB 0x04b8 0x0106 untested *none* scanner is apparently a GT-7000 USB 0x04b8 0x0841 good *none* all-in-one<br>overseas version of the PX-401A USB 0x04b8 0x084d good *none* all-in-one<br>overseas version of the PX-402A USB 0x04b8 0x0849 good *none* all-in-one USB 0x04b8 0x0849 good *none* all-in-one USB 0x04b8 0x0849 good *none* all-in-one USB 0x04b8 0x084f good *none* all-in-one USB 0x04b8 0x084a good *none* network interface probably supported<br>all-in-one<br>overseas version of the PX-501A USB 0x04b8 0x0851 good *none* network interface probably supported<br>all-in-one USB 0x04b8 0x0856 good *none* all-in-one<br>overseas version of the PX-502A USB 0x04b8 0x0854 good *none* all-in-one USB 0x04b8 0x084c good *none* all-in-one USB 0x04b8 0x0847 good *none* network interface probably supported<br>all-in-one<br>overseas version of the PX-601F USB 0x04b8 0x0855 unsupported *none* supported by the epkowa backend plus non-free interpreter 117 sane-fujitsu http://www.thebility.com/fujitsu/ Backend updated for SANE release 1.0.23, see sane-fujitsu manpage `http://www.fujitsu.com/' *none* SCSI *none* *none* complete http://www.remote.org/frederik/projects/software/sane/ small, old, discontinued SCSI *none* *none* complete *none* small, old, discontinued SCSI USB 0x04c5 0x1041 complete *none* small, recent, discontinued, usb 1.1 SCSI USB 0x04c5 0x10ae complete *none* small, recent, discontinued, usb 2.0 SCSI USB 0x04c5 0x1042 complete *none* small, recent, discontinued, usb 1.1 SCSI USB 0x04c5 0x10af complete *none* small, recent, discontinued, usb 2.0 USB 0x04c5 0x1097 complete *none* small, recent, discontinued USB 0x04c5 0x1096 complete *none* small, recent, discontinued USB 0x04c5 0x10e6 complete *none* small, recent, discontinued USB 0x04c5 0x10f2 complete *none* small, recent, discontinued SCSI USB 0x04c5 0x10e0 complete *none* small, recent, discontinued SCSI USB 0x04c5 0x10e1 complete *none* small, recent, discontinued Ethernet *none* *none* untested *none* Not a scanner, rather a scanner to ethernet interface Ethernet *none* *none* untested *none* small, recent, discontinued, integrated touchscreen and keyboard USB 0x04c5 0x10fe complete *none* small, recent, discontinued USB 0x04c5 0x1135 complete *none* small, recent, discontinued USB 0x04c5 0x1155 complete *none* small, recent, discontinued USB 0x04c5 0x116f complete *none* small, recent, discontinued USB 0x04c5 0x114f complete *none* small, recent, discontinued USB 0x04c5 0x1150 complete *none* small, recent, discontinued USB 0x04c5 0x11a2 complete *none* small, discontinued USB 0x04c5 0x11a2 complete *none* small, discontinued, same as S1500 Ethernet *none* *none* untested *none* small, current, integrated touchscreen and keyboard Ethernet *none* *none* untested *none* small, current, integrated touchscreen and keyboard USB 0x04c5 0x11fc complete *none* small, current USB 0x04c5 0x11f3 complete *none* small, current USB 0x04c5 0x11f4 complete *none* small, current USB WiFi 0x04c5 0x132b good *none* small, current, WiFi not supported. Hardware only scans in color. Backend generates binary and grayscale modes. RS232C/Video *none* *none* unsupported *none* medium, old, discontinued RS232C/Video *none* *none* unsupported *none* medium, old, discontinued SCSI *none* *none* complete *none* medium, old, discontinued RS232C/Video *none* *none* unsupported *none* medium, old, discontinued SCSI *none* *none* complete *none* medium, old, discontinued RS232C/Video *none* *none* unsupported *none* medium, old, discontinued SCSI *none* *none* complete *none* medium, old, discontinued RS232C/Video *none* *none* unsupported *none* medium, old, discontinued SCSI *none* *none* complete *none* medium, old, discontinued RS232C/Video *none* *none* unsupported *none* medium, old, discontinued SCSI *none* *none* complete *none* medium, old, discontinued SCSI USB 0x04c5 0x10cf complete *none* medium, current SCSI USB 0x04c5 0x1078 complete *none* medium, recent, discontinued SCSI *none* *none* complete *none* medium, recent, discontinued SCSI *none* *none* complete *none* medium, recent, discontinued SCSI USB 0x04c5 0x10e2 complete *none* medium, recent, discontinued SCSI USB 0x04c5 0x114d complete *none* medium, recent, discontinued SCSI USB 0x04c5 0x114e complete *none* medium, recent, discontinued SCSI USB 0x04c5 0x114a complete *none* medium, current SCSI USB 0x04c5 0x11f1 complete *none* medium, current SCSI USB 0x04c5 0x11f2 complete *none* medium, current RS232C/Video *none* *none* unsupported *none* big, old, discontinued SCSI *none* *none* complete *none* big, old, discontinued RS232C/Video *none* *none* unsupported *none* big, old, discontinued SCSI *none* *none* complete *none* big, old, discontinued RS232C/Video *none* *none* unsupported *none* big, old, discontinued SCSI *none* *none* complete *none* big, old, discontinued SCSI *none* *none* complete *none* big, old, discontinued SCSI *none* *none* complete *none* big, old, discontinued SCSI *none* *none* complete *none* big, recent, discontinued SCSI *none* *none* complete *none* big, recent, discontinued SCSI *none* *none* complete *none* big, recent, discontinued SCSI *none* *none* complete *none* big, recent, discontinued SCSI USB 0x04c5 0x10ad complete *none* big, recent, discontinued SCSI USB 0x04c5 0x1095 complete *none* big, recent, discontinued SCSI USB 0x04c5 0x10e7 good *none* big, recent, discontinued. Independent ultrasonic control and multistream unsupported USB 0x04c5 0x1178 untested *none* Simplex, USB only version of fi-6770, won't wakeup via software, discontinued SCSI USB 0x04c5 0x1213 untested *none* big, current. Faster version of fi-5900? SCSI USB 0x04c5 0x1176 good *none* big, current, won't wakeup via software SCSI USB 0x04c5 0x1177 good *none* big, current, VRS CGA board unsupported, won't wakeup via software SCSI USB 0x04c5 0x1174 good *none* big, current, won't wakeup via software SCSI USB 0x04c5 0x1175 good *none* big, current, VRS CGA board unsupported, won't wakeup via software SCSI USB 0x04c5 0x119d untested *none* big, current. Independent ultrasonic control and multistream unsupported SCSI USB 0x04c5 0x119e untested *none* big, current. VRS CGA board unsupported, Independent ultrasonic control and multistream unsupported 1.0-63 sane-genesys http://www.meier-geinitz.de/sane/genesys-backend/ Only the USB scanners mentioned below are currently supported. `http://www.plustek.de/' `http://www.plustek.com/' *none* USB 0x07b3 0x0900 basic *none* Has a Primax USB ID `http://www.medion.com/' `http://www.medion.de/' *none* USB 0x0461 0x0377 good *none* Has a Primax USB ID USB 0x0461 0x0377 good *none* Has a Primax USB ID. Same as MD5345 USB 0x0461 0x0377 complete *none* Has a Primax USB ID. Same as MD5345 `http://www.hp.com/' *none* USB 0x03f0 0x0901 complete *none* 600x1200 dpi max USB 0x03f0 0x0a01 complete *none* 1200x1200 dpi max USB 0x03f0 0x0a01 basic *none* clone of the HP 2400C USB 0x03f0 0x1405 complete *none* 1200x1200 dpi max, complete transparency adaptor support USB 0x03f0 0x1405 complete *none* 1200x1200 dpi max, same as HP 3670C USB 0x03f0 0x1b05 untested *none* resolution from 100 to 2400 supported, UTA not supported yet USB 0x03f0 0x4505 good *none* resolution from 100 to 2400 supported, UTA not supported yet USB 0x03f0 0x4605 good *none* resolution from 100 to 2400 supported, UTA not supported yet USB 0x03f0 0x4705 untested *none* Not supported yet `http://www.canon.com/' *none* USB 0x04a9 0x2213 good *none* Same ids as LiDE 50. USB 0x04a9 0x2213 good *none* Same ids as LiDE 50. USB 0x04a9 0x2213 good *none* *none* USB 0x04a9 0x221c good *none* *none* USB 0x04a9 0x1904 complete *none* GL847 based, resolution from 75 to 2400 dpi USB 0x04a9 0x1909 complete *none* GL124 based, resolution from 75 to 2400 dpi USB 0x04a9 0x1905 complete *none* GL847 based, resolution from 75 to 4800 dpi USB 0x04a9 0x190a complete *none* GL124 based, resolution from 75 to 2400 dpi USB 0x04a9 0x2228 unsupported *none* GL843 based, to be added to the genesys backend USB 0x04a9 0x1906 unsupported *none* GL847 based, to be added to the genesys backend USB 0x04a9 0x1907 good *none* GL847 based, resolution from 75 to 4800 dpi USB 0x1083 0x162e unsupported *none* GL846 based, work in progress `http://www.visioneer.com/' *none* USB 0x04a7 0x049b good *none* All resolution and mode supported, calibration is available USB 0x04a7 0x0426 good *none* All resolution and mode supported, calibration is available USB 0x04a7 0x0474 good *none* All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally. USB 0x04a7 0x0494 basic *none* All resolution and mode supported, calibration is available USB 0x04a7 0x0229 complete *none* Same as MD5345 `http://www.pentaxtech.com/' `http://mobilesolutions.brother-usa.com/' *none* USB 0x0a17 0x3210 good *none* All resolution and mode supported, calibration is available USB 0x04f9 0x2038 good *none* All resolution and mode supported, calibration is available `http://www.docucap.com/' Successor of Syscan in the USA USB 0x1dcc 0x4810 basic *none* All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally. *none* *none* USB 0x0a82 0x4810 basic *none* All resolution and mode supported, front- and backside side-by-side, with backside mirrored horizontally. USB 0x0a82 0x4802 untested *none* All resolution and mode should be supported, but uncorrected scans USB 0x0a82 0x4803 basic *none* All resolution and mode supported, calibration is available USB 0x0a82 0x480c good *none* All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally. `http://www.xerox.com/' *none* USB 0x04a7 0x04ac good *none* All resolution and mode supported, calibration is available USB 0x0461 0x038b complete *none* GL646 based, resolution from 75 to 2400 dpi *none* *none* USB 0x04da 0x100f complete *none* All resolution and mode supported, calibration is available. Support sponsored by cncsolutions (http://www.cncsolutions.com.br) 0.0 sane-gphoto2 mailto:peter@fales-lorenz.net *none* Multiple cameras supported by the gphoto2 libraries http://www.gphoto.org The long-term plan is to support all the cameras supported by the gphoto2 libraries (currently over 140 models). However, at this stage, only a handful of cameras are definitely known to work with SANE. Other cameras will probably work if the native file format is EXIF or JPEG. Testers welcome! 1.0-84 sane-gt68xx http://www.meier-geinitz.de/sane/gt68xx-backend/ Only the USB scanners mentioned below are supported. For other Mustek BearPaws, look at the Plustek and the MA-1509 backend. `http://www.artecusa.com/' *none* USB 0x05d8 0x4002 good *none* Works, only product id 0x4002 is supported USB 0x05d8 0x4002 good *none* Works, however 12 bit mode doesn't seem to be supported *none* *none* USB 0x05d8 0x4002 good *none* Similar to Artec Ultima 2000 `http://www.fujitsu.com/' *none* USB 0x05d8 0x4002 basic *none* Works, but is slow. Probably a Mustek BearPaw 2400 CU clone. `http://www.genius-kye.com/' *none* USB 0x0458 0x201e untested *none* Untested but should work. USB 0x0458 0x2021 basic *none* *none* USB 0x0458 0x2011 good *none* *none* USB 0x0458 0x2011 good *none* Same as Colorpage Vivid3x USB 0x0458 0x2017 good *none* *none* USB 0x0458 0x2014 good *none* *none* USB 0x0458 0x201b good *none* *none* USB 0x0458 0x201a good *none* *none* USB 0x0458 0x201d good *none* *none* USB 0x0458 0x201f good *none* *none* *none* *none* USB 0x05d8 0x4002 good *none* Same as Artec Ultima 2000. `http://www.lexmark.com/' *none* USB 0x043d 0x002d good *none* Works, some resolutions fail at 16 bit USB 0x043d 0x002d good *none* Works, some resolutions fail at 16 bit, same as X70 `http://www.medion.com' Sold by Aldi and Tchibo. USB 0x05d8 0x4002 good *none* Product id 0x4002. If you have 0x4003, use artec_eplus48u backend. USB 0x05d8 0x4002 untested *none* Untested, but is reported to have the same ids as the Artec Ultima 2000. Please test. USB 0x05d8 0x4002 good *none* Similar to Artec Ultima 2000 USB 0x05d8 0x4002 good *none* Similar to Mustek ScanExpress 1200 UB Plus USB 0x05d8 0x4002 good *none* Similar to Artec Ultima 2000 (e+?) `http://www.mustek.com/' `http://www.mustek.com.tw/' `http://www.mustek.de/' *none* USB 0x055f 0x021e good *none* *none* USB 0x05d8 0x4002 good *none* *none* USB 0x055f 0x021b good *none* *none* USB 0x055f 0x021c good *none* *none* USB 0x055f 0x021e good *none* Transparency adapter supported USB 0x055f 0x021c good *none* Seems to use the same ids as BearPaw 1200 CU Plus. USB 0x055f 0x0218 untested *none* Probably works, reports are welcome USB 0x055f 0x0219 good *none* Works, problems with 12/16 bit modes? USB 0x05d8 0x4002 basic *none* Works, but is slow USB 0x055f 0x021d good *none* *none* USB 0x055f 0x0218 good *none* Transparency adapter supported USB 0x055f 0x0219 good *none* Transparency adapter supported USB 0x055f 0x021a basic *none* Slow. Same as 2448 TA Plus, but without TA. USB 0x055f 0x021a basic *none* Slow. Transparency adapter supported. Slow. Brightness depends on resolution? USB 0x055f 0x0219 good *none* Works but is slow in high resolutions. Same as BearPaw 2400 TA Plus. USB 0x055f 0x0219 good *none* Works but is slow in high resolutions. Same as BearPaw 2400 CS Plus. USB 0x05d8 0x4002 good *none* *none* USB 0x055f 0x021f complete *none* *none* USB 0x05d8 0x4002 minimal *none* Should be detected but may need some more work in the code. Testers welcome. Please contact me if you own this scanner. USB 0x055f 0x0210 basic *none* Still some vertical stripes. USB 0x05d8 0x4002 good *none* Same as ScanExpress 1200 UB Plus *none* *none* USB 0x07b3 0x0412 untested *none* Similar to Plustek OpticSlim M12. Please tell us if this scanner works. USB 0x07b3 0x0462 basic *none* Similar to Plustek OpticSlim M12. *none* *none* USB 0x07b3 0x040b untested *none* Untested. Please test. Similar to Plustek OpticPro S12? *none* *none* USB 0x05d8 0x4002 good *none* Similar to Mustek BearPaw 1200 (Plus) USB 0x055f 0x021c good *none* Similar to Mustek BearPaw 1200 Plus USB 0x055f 0x021b good *none* Similar to Mustek BearPaw 1200 Plus USB 0x055f 0x0219 good *none* *none* `http://www.plustek.de/' `http://www.plustek.com/' *none* USB 0x07b3 0x0400 good *none* *none* USB 0x07b3 0x0401 good *none* *none* USB 0x07b3 0x0402 good *none* *none* USB 0x07b3 0x0403 good *none* *none* USB 0x07b3 0x0403 untested *none* Probably works. Transparency adapter not supported yet. Please contact me if you own such a device. USB 0x07b3 0x040b good *none* Product ID 0x040b only. USB 0x07b3 0x040e good *none* Product ID 0x040e only. Is reported to work. USB 0x07b3 0x040b untested *none* Product ID 0x040b only. Needs testing. Transparency adapter completely untested. Please contact me if you own such a scanner. USB 0x07b3 0x0413 good *none* *none* USB 0x07b3 0x0422 good *none* Works up to 1200 dpi. USB 0x07b3 0x0454 good *none* Same as OpticSlim 2400. USB 0x07b3 0x045f complete *none* Works up to 1200 dpi. Calibration with external calibration sheet supported USB 0x07b3 0x0412 complete *none* Works up to 1200 dpi. Calibration with external calibration sheet supported *none* *none* USB 0x07b3 0x0400 good *none* Similar to Plustek OpticPro 1248U `http://www.trust-site.com' *none* USB 0x055f 0x0218 good *none* Same as Mustek Bearpaw 2400 TA plus. USB 0x05d8 0x4002 good *none* Works, if you have vendor id 0x055f and product id 0x0006, use the mustek_usb backend instead, similar to Mustek ScanExpress 1200 UB (Plus) USB 0x055f 0x021c good *none* Same as Mustek BearPaw 1200 CU Plus (0x021c). USB 0x05d8 0x4002 good *none* Similar to Artec Ultima 2000 `http://www.visioneer.com/' *none* USB 0x04a7 0x0444 good *none* Works upto 1200 dpi and 12 bits/color. 1.06 sane-hp http://www.kirchgessner.net/ *none* `http://www.hp.com/' *none* Propietary *none* *none* complete *none* Driver for HP parallel interface card required SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* USB 0x03f0 0x0101 complete *none* *none* SCSI *none* *none* complete *none* *none* Parport *none* *none* complete *none* Requires ppscsi driver and epst module Parport USB 0x03f0 0x0401 complete *none* Parallel interface requires ppscsi driver and epst module SCSI *none* *none* complete *none* *none* SCSI USB 0x03f0 0x0201 complete *none* *none* SCSI USB 0x03f0 0x0201 complete *none* *none* SCSI USB 0x03f0 0x0601 complete *none* *none* SCSI USB 0x03f0 0x0601 complete *none* *none* SCSI USB 0x03f0 0x0601 complete *none* *none* SCSI *none* *none* complete *none* *none* 1.1 sane-hp3500 http://projects.troy.rollo.name/rt-scanners/ HP3500 series scanners. `http://www.hp.com' *none* USB 0x03f0 0x2205 good *none* *none* USB 0x03f0 0x2005 good *none* *none* USB 0x03f0 0x2005 good *none* *none* 0.12 sane-hp3900 http://sourceforge.net/projects/hp3900-series/ Still Beta `http://www.hp.com' *none* USB 0x03f0 0x2605 basic *none* Works with resolutions equal and less than 600dpi USB 0x03f0 0x2305 good *none* *none* USB 0x03f0 0x2405 good *none* *none* USB 0x03f0 0x4105 basic *none* Works with resolutions lower than 1200dpi USB 0x03f0 0x2805 basic *none* Similar to hp scanjet 3800 USB 0x03f0 0x4205 basic *none* Similar to hp scanjet 4370 USB 0x03f0 0x4305 basic *none* Similar to hp scanjet 4370 `http://www.umax.com' *none* USB 0x06dc 0x0020 minimal *none* developing yet `http://www.benq.com/' *none* USB 0x04a5 0x2211 minimal *none* developing yet 1.0-2 sane-hp4200 http://hp4200-backend.sourceforge.net *none* `http://www.hp.com/' *none* USB 0x03f0 0x0105 basic *none* 8bpp color, 75/150/300/600 dpi only USB 0x03f0 0x0105 basic *none* 8bpp color, 75/150/300/600 dpi only USB 0x03f0 0x0105 basic *none* 8bpp color, 75/150/300/600 dpi only 1.0-2 sane-hp5400 http://sourceforge.net/projects/hp5400backend HP5400 and HP5470 scanners. Prototype backend available `http://www.hp.com' *none* USB 0x03f0 0x1005 basic *none* *none* USB 0x03f0 0x1105 basic *none* *none* USB *none* *none* basic *none* *none* 1.0.5 sane-hp5590 *none* *none* `http://www.hp.com' *none* USB 0x03f0 0x1205 complete *none* Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives USB 0x03f0 0x1305 complete *none* Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives USB 0x03f0 0x1305 untested *none* Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives USB 0x03f0 0x1205 complete *none* Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives USB 0x03f0 0x1705 complete *none* Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives USB 0x03f0 0x1805 complete *none* Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives 0 sane-hpljm1005 *none* *none* `http://www.hp.com' *none* USB 0x03f0 0x3b17 good *none* grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI USB 0x03f0 0x5617 good *none* grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI USB 0x03f0 0x5717 good *none* grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI 0.03 sane-hpsj5s http://hpsj5s.sourceforge.net/ *none* `http://www.hp.com/' *none* Parport (EPP) *none* *none* minimal *none* Requires libieee1284 library. Only gray mode. 1.00 sane-hs2p http://www.acjlaw.net:8080/~jeremy/Ricoh/ This backend has been tested with the IS450DE (Duplex/Endorser). All major functions necessary for scanning are supported. This backend should work with all Ricoh scanners in the IS450 family as well as the IS420 series, but the IS420 has not yet been tested. Features provided by the optional Image Processing Unit (IPU) are not yet integrated into the backend, as my scanner lacks the IPU. `http://www.ricoh.com/' *none* SCSI *none* *none* complete *none* All major scanning-related features are supported (except for IPU). Certain non-scanning features, such as those related to scanner maintenance, are not supported. Such features would be better implemented in a separate stand-alone tool. For instance, if you replace the ADF Unit, you must recalibrate the scanner optics using a Ricoh Test Sheet and reset the E^2PROM registers. Reports are welcome. SCSI *none* *none* untested *none* Untested, please report! SCSI *none* *none* untested *none* Untested, please report! SCSI *none* *none* untested *none* Untested, please report! 1.0-4 sane-ibm http://www.meier-geinitz.de/sane/ibm-backend/ This backend has had only limited testing. It needs more work especially for the Ricoh scanners. Patches are welcome. `http://www.ibm.com/' *none* SCSI *none* *none* basic *none* Was reported to work long time ago. Reports are welcome. *none* *none* SCSI *none* *none* untested *none* Untested, please report! SCSI *none* *none* basic *none* Works at least in flatbed mode. SCSI *none* *none* untested *none* Untested, please report! 7 sane-kodak http://www.thebility.com/kodak/ New backend for SANE release 1.0.21, see sane-kodak manpage `http://www.kodak.com/' *none* SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! SCSI *none* *none* untested *none* Please test! IEEE-1394 *none* *none* untested *none* Please test! IEEE-1394 *none* *none* basic *none* Uncompressed B&W, Gray and Color, some automatic features supported SCSI *none* *none* untested *none* Please test! 2.4.6 sane-kodakaio http://sourceforge.net/projects/cupsdriverkodak/ Backend for Kodak AiO ESP and Hero printers. Also possibly Advent AWL10 `http://www.kodak.com/' *none* USB 0x040a 0x4059 untested *none* Please test! USB 0x040a 0x4066 untested *none* Please test! USB 0x040a 0x4043 untested *none* Please test! USB 0x040a 0x4031 untested *none* Please test! USB 0x040a 0x4053 untested *none* Please test! USB 0x040a 0x4028 untested *none* Please test! USB 0x040a 0x4025 untested *none* Please test! USB Ethernet 0x040a 0x4041 basic *none* USB good, Network good USB 0x040a 0x4026 untested *none* Please test! USB 0x040a 0x4027 untested *none* Please test! USB 0x040a 0x4054 untested *none* Please test! USB 0x040a 0x4056 untested *none* Please test! USB 0x040a 0x4065 untested *none* Please test! USB 0x040a 0x4032 untested *none* Please test! USB 0x040a 0x403e untested *none* Please test! USB 0x040a 0x403f untested *none* Please test! USB 0x040a 0x4057 untested *none* Please test! USB 0x040a 0x4058 untested *none* Please test! USB 0x040a 0x405d untested *none* Please test! USB 0x040a 0x405e untested *none* Please test! USB 0x040a 0x406d untested *none* Please test! USB 0x040a 0x4064 untested *none* Please test! USB 0x040a 0x4062 untested *none* Please test! USB 0x040a 0x4063 untested *none* Please test! USB Ethernet 0x040a 0x4067 basic *none* USB good, Network good `http://www.adventcomputers.co.uk' *none* USB 0x040a 0x4060 untested *none* Please test! unmaintained sane-kvs20xx *none* New backend for SANE release 1.0.22, see sane-kvs20xx manpage `http://www.panasonic.com/' *none* SCSI *none* *none* untested *none* *none* USB SCSI 0x04da 0x1000 untested *none* *none* USB 0x04da 0x100a untested *none* *none* SCSI *none* *none* untested *none* *none* USB SCSI 0x04da 0x1001 untested *none* *none* USB 0x04da 0x1009 untested *none* *none* unmaintained sane-kvs40xx *none* New backend for SANE release 1.0.23, see sane-kvs40xx manpage `http://www.panasonic.com/' *none* USB 0x04da 0x100d untested *none* *none* USB 0x04da 0x100c untested *none* *none* USB 0x04da 0x100e untested *none* *none* unmaintained sane-kvs1025 *none* New backend for SANE release 1.0.21, see sane-kvs1025 manpage `http://www.panasonic.com/' *none* USB 0x04da 0x1007 good *none* *none* USB 0x04da 0x1006 good *none* *none* USB 0x04da 0x1010 good *none* *none* 1.0-10 sane-leo http://www.zago.net/sane/#leo *none* *none* *none* SCSI *none* *none* good *none* FCC ID LUZFS1130 *none* *none* SCSI *none* *none* good *none* FCC ID LUZFS1130 *none* *none* SCSI *none* *none* good *none* *none* 1.0-0 sane-lexmark http://stef.dev.free.fr/sane/lexmark This backend supports lexmark x1100 series scanners. `http://www.lexmark.com/' *none* USB 0x043d 0x007c untested *none* *none* USB 0x043d 0x007c good *none* Supports 75, 150, 300, 600 dpi USB 0x043d 0x007c untested *none* *none* USB 0x043d 0x007c good *none* Supports 75, 150, 300, 600 dpi USB 0x043d 0x007c good *none* Supports 75, 150, 300, 600 dpi USB 0x043d 0x007c good *none* *none* USB 0x043d 0x007c good *none* Tested with xscanimage. Supports 75, 150, 300, 600, 1200(600x1200) dpi resolutions. Does grayscale or colour scans in the following sizes: wallet, 3x5, 4x6, 5x7, 8x10, letter. USB 0x043d 0x007c untested *none* *none* USB 0x043d 0x0060 good *none* Supports 75, 150, 300, 600 dpi USB 0x043d 0x007d good *none* USB1.1 is OK, USB2.0 needs testing *none* *none* USB 0x413c 0x5105 good *none* Relabelled X11xx model 1.0-3 sane-ma1509 http://www.meier-geinitz.de/sane/ma1509-backend/ *none* `http://www.mustek.com/' `http://www.mustek.com.tw/' `http://www.mustek.de/' *none* USB 0x055f 0x0010 good *none* Works upto 600 dpi. No support for TA and ADF yet. `http://www.fujitsu.com/' *none* USB 0x04c5 0x1040 unsupported *none* Uses ma1509 chip, but very different from other scanners supported by the ma1509 backend 1.0.0 sane-magicolor http://wiki.kainhofer.com/hardware/magicolor_scan *none* `http://www.konicaminolta.com/' *none* USB Network 0x132b 0x2089 good http://www.konicaminolta.eu/business-solutions/products/laser-printers/all-in-one/magicolor-1690mf/key-features.html Multi-function color laser printer with fax, scanner and network interface USB Network *none* *none* unsupported *none* Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov. USB Network *none* *none* unsupported *none* Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov. 1.0-7 sane-matsushita http://www.zago.net/sane *none* `http://www.panasonic.com/' *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* minimal *none* no color, no high resolution, no automatic cropping SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* minimal *none* no color, no high resolution, no automatic cropping SCSI *none* *none* minimal *none* no color, no high resolution, no automatic cropping SCSI *none* *none* minimal *none* no color, no high resolution, no automatic cropping 0.13.1 sane-microtek http://www.mir.com/mtek/ *none* `http://www.microtek.com/' *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* 3-pass SCSI *none* *none* good *none* slide-scanner SCSI *none* *none* good *none* slide-scanner SCSI *none* *none* good *none* slide-scanner SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* 3-pass SCSI *none* *none* good *none* gray only SCSI *none* *none* good *none* 3-pass SCSI *none* *none* untested *none* *none* SCSI *none* *none* basic *none* gray only (see manpage) SCSI (Parport) *none* *none* basic *none* sheet-fed (preliminary, see mapage) `http://www.agfa.com/' *none* SCSI *none* *none* good *none* Arcus *II*, not Arcus! SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* minimal *none* Is detected but scans are very dark SCSI *none* *none* basic *none* *none* `http://www.vobis.de/' *none* SCSI *none* *none* good *none* *none* `http://www.genius-kye.com/' *none* SCSI *none* *none* good *none* Same as Microtek Scanmaker E3 unmaintained sane-microtek2 http://karstenfestag.gmxhome.de/linux.html *none* `http://www.microtek.com/' *none* Parport *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* basic *none* *none* USB 0x05da 0x0099 good *none* *none* SCSI *none* *none* good *none* *none* Parport *none* *none* good *none* *none* SCSI *none* *none* basic *none* *none* Parport *none* *none* basic *none* *none* SCSI *none* *none* basic *none* *none* Parport *none* *none* basic *none* *none* SCSI *none* *none* basic *none* *none* SCSI *none* *none* basic *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* good *none* only flatbed mode ? IEEE-1394 *none* *none* minimal /unsupported/microtek-scanmaker-9800.html IEEE-1394 seems to work. See link. More reports welcome. Parport *none* *none* complete *none* *none* Parport *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* Parport *none* *none* complete *none* *none* USB 0x05da 0x009a complete *none* *none* USB 0x05da 0x00b6 basic *none* Sometimes scan speed goes to fast and results look badly smudged. SCSI *none* *none* complete *none* *none* USB 0x05da 0x00a3 complete *none* *none* USB 0x05da 0x80a3 complete *none* *none* SCSI *none* *none* good *none* only Flatbed mode ? `http://www.vobis.de/' *none* SCSI *none* *none* complete *none* only E3plus based models `http://www.scanport.com/' *none* Parport? *none* *none* basic *none* *none* Parport *none* *none* basic *none* *none* SCSI *none* *none* basic *none* *none* `http://www.geniusmouse.co.uk/' *none* Parport *none* *none* good *none* *none* 1.0-138 sane-mustek http://www.meier-geinitz.de/sane/mustek-backend/ Most Mustek SCSI scanners are supported by this backend. For USB scanners, look at the mustek_usb backend. `http://www.mustek.com/' `http://www.mustek.com.tw/' `http://www.mustek.de/' *none* SCSI *none* *none* good *none* 3-pass SCSI *none* *none* good *none* 3-pass SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* Parport *none* *none* untested *none* Completely untested. If it's the same as the 600 II EP, it may work. Please contact me if you own such a device. Parport *none* *none* minimal *none* Works, however only low resolutions and quality in color mode is bad. SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* untested *none* One report that it crashes the computer. SCSI driver issue? Please contact me if you own such a device. SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* complete *none* *none* SCSI *none* *none* basic *none* Please test! SCSI *none* *none* good *none* *none* SCSI *none* *none* complete *none* ADF and TA untested. Please contact me if you own such equipment. Proprietary *none* *none* basic *none* Resolutions above 300 dpi may cause trouble. `http://www.trust-site.com' Carefully check the model names. Trust uses similar names for completely different hardware. SCSI *none* *none* good *none* 3-pass, Mustek Paragon MFS-6000CX compatible SCSI *none* *none* complete *none* Mustek Paragon MFS-6000SP compatible SCSI *none* *none* complete *none* Mustek Paragon 600 II CD compatible SCSI *none* *none* complete *none* Mustek ScanExpress 12000SP compatible SCSI *none* *none* complete *none* Mustek ScanExpress 12000SP compatible `http://www.primax.nl/' *none* SCSI *none* *none* complete *none* Mustek 600 II CD compatible 13 sane-mustek_pp http://penguin-breeder.org/sane/mustek_pp/ Supports CIS and CCD type parallel port scanners from Mustek. `http://www.mustek.com/' `http://www.mustek.com.tw/' `http://www.mustek.de/' *none* Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner Parport (EPP) *none* *none* good *none* 300x600 dpi CIS scanner Parport (EPP) *none* *none* good *none* 300x600 dpi CIS scanner Parport (EPP) *none* *none* good *none* 300x600 dpi CIS scanner Parport (EPP) *none* *none* good *none* 600x1200 dpi CIS scanner Parport (EPP) *none* *none* good *none* 600x1200 dpi CIS scanner `http://www.medion.de/' Those scanners are also known as "Aldi Scanner " or "Tchibo Scanners " Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner Parport (EPP) *none* *none* good *none* 600x1200 dpi CIS scanner Parport (EPP) *none* *none* good *none* 600x1200 dpi CIS scanner Parport (EPP) *none* *none* good *none* 600x1200 dpi CIS scanner *none* *none* Parport (EPP) *none* *none* good *none* 600x1200 dpi CIS scanner Parport (EPP) *none* *none* good *none* 300x600 dpi CIS scanner `http://www.trust-site.com/home/' *none* Parport (EPP) *none* *none* good *none* 300x600 dpi CIS scanner Parport (EPP) *none* *none* good *none* 300x600 dpi CIS scanner *none* *none* Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner *none* *none* Parport (EPP) *none* *none* good *none* CIS scanner *none* *none* Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner *none* *none* Parport (EPP) *none* *none* good *none* 300 dpi CCD scanner *none* *none* Parport (EPP) *none* *none* good *none* 300x600 dpi CIS scanner 1.0-18 sane-mustek_usb http://www.meier-geinitz.de/sane/mustek_usb-backend/ Only the USB scanners mentioned below are supported. For BearPaws, look at the Plustek, MA-1509, and gt68xx backends. `http://www.mustek.com/' `http://www.mustek.com.tw/' `http://www.mustek.de/' *none* USB 0x055f 0x0002 complete *none* *none* USB 0x055f 0x0001 complete *none* *none* USB 0x055f 0x0008 complete *none* *none* USB 0x055f 0x0006 complete *none* For the UB Plus, see gt68xx backend `http://www.trust-site.com' *none* USB 0x055f 0x0006 complete *none* Mustek 1200 UB compatible 1.0-10 sane-mustek_usb2 http://www.meier-geinitz.de/sane/mustek_usb2-backend/ Only BearPaw 2448TA Pro is supported at the moment `http://www.mustek.com/' `http://www.mustek.com.tw/' `http://www.mustek.de/' *none* USB 0x055f 0x0409 good *none* *none* 0.12 sane-nec http://www5a.biglobe.ne.jp/~saetaka/ *none* `http://www.nevt.co.jp/' *none* SCSI *none* *none* good *none* PC-IN500/4C was sold only in JAPAN 1.0.14 sane-net http://www.penguin-breeder.org/?page=sane-net *none* Network access to saned servers *none* Can be used to access any scanner supported by SANE over the net. Supports IPv4 and IPv6. 0.3 sane-niash http://sourceforge.net/projects/hp3300backend *none* `http://www.hp.com' *none* USB 0x03f0 0x0205 complete *none* *none* USB 0x03f0 0x0405 complete *none* If you use Linux 2.6, version 2.6.8 or newer is necessary. USB 0x03f0 0x0305 complete *none* If you use Linux 2.6, version 2.6.8 or newer is necessary. USB 0x047b 0x1002 complete *none* If you use Linux 2.6, version 2.6.8 or newer is necessary. `http://www.agfa.com' *none* USB 0x06bd 0x0100 complete *none* *none* `http://www.trust.com' *none* USB 0x047b 0x1000 complete *none* *none* 1 sane-p5 http://www.sane-project.org/ New backend for SANE release 1.0.21, see sane-p5 manpage `http://www.primax.com.tw' *none* Parport (EPP/ECP) *none* *none* basic *none* Sheetfed scanner, work in gray and color, but uncalibrated scans 1.0 sane-pie http://www.munton.demon.co.uk/sane *none* `http://www.blackwidow.co.uk/' *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* `http://www.scanace.com/' *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* SCSI *none* *none* untested *none* *none* *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* untested *none* *none* unmaintained sane-pint *none* *none* Scanners with the machine-independent PINT interface *none* Haven't been tested for a long time. Handle with care. 0.17.3 sane-pixma http://home.arcor.de/wittawat/pixma/ http://mp610.blogspot.com/ *none* `http://www.canon.com/' *none* USB 0x04a9 0x1758 untested *none* Testers needed! USB 0x04a9 0x1761 untested *none* Testers needed! USB 0x04a9 0x175a untested *none* Testers needed! USB 0x04a9 0x1767 untested *none* Testers needed! USB 0x04a9 0x1751 complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1760 untested *none* Testers needed! USB WLAN 0x04a9 0x1752 complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1762 untested *none* Testers needed! USB 0x04a9 0x1753 untested *none* Testers needed! USB 0x04a9 0x1763 complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1748 complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1749 complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1754 complete *none* All resolutions supported (up to 2400DPI). USB 0x04a9 0x1764 untested *none* Testers needed! USB 0x04a9 0x174a complete *none* All resolutions supported (up to 2400 DPI) USB 0x04a9 0x1755 complete *none* All resolutions supported (up to 4800 DPI) USB Ethernet 0x04a9 0x1765 complete *none* All resolutions supported (up to 2400DPI). USB 0x04a9 0x174b untested *none* Testers needed! USB Ethernet 0x04a9 0x1756 complete *none* All resolutions supported (up to 4800DPI). USB 0x04a9 0x172b complete *none* All resolutions supported (up to 600 DPI) USB 0x04a9 0x1709 good *none* *none* USB 0x04a9 0x1714 basic *none* *none* USB 0x04a9 0x170a complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1715 basic *none* *none* USB 0x04a9 0x1734 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x1721 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x1722 complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x175f complete *none* All resolutions supported (up to 600DPI). USB 0x04a9 0x1732 complete *none* All resolutions supported (up to 1200DPI) USB 0x04a9 0x173a complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x1733 complete *none* All resolutions supported (up to 1200DPI) USB 0x04a9 0x173b complete *none* All resolutions supported (up to 1200DPI) USB 0x04a9 0x1746 good *none* All resolutions supported (up to 600DPI). USB 0x04a9 0x263c complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x263d complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x263f untested *none* Same protocol as Pixma MP360/370/390? Testers needed! USB 0x04a9 0x263e complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x170b complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1716 complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1723 complete *none* All resolutions supported (up to 2400DPI). USB 0x04a9 0x1731 complete *none* All resolutions supported (up to 2400DPI) USB 0x04a9 0x173c complete *none* All resolutions supported (up to 1200DPI) USB 0x04a9 0x1757 untested *none* Testers needed! USB 0x04a9 0x1747 untested *none* Same protocol as Pixma MP280? Testers needed! USB 0x04a9 0x170c good *none* *none* USB 0x04a9 0x1717 complete *none* All resolutions supported (up to 1200DPI). USB 0x04a9 0x1724 complete *none* All resolutions supported (up to 2400DPI) USB 0x04a9 0x1712 good *none* *none* USB 0x04a9 0x1730 complete *none* All resolutions supported (up to 2400DPI) USB 0x04a9 0x173d complete *none* All resolutions supported (up to 2400DPI) USB 0x04a9 0x173e complete *none* All resolutions supported (up to 2400DPI) USB 0x04a9 0x1718 complete *none* All resolutions supported (up to 2400DPI) USB Ethernet 0x04a9 0x1719 complete *none* All resolutions supported (up to 2400DPI) USB 0x04a9 0x1725 complete *none* All resolutions supported (up to 4800DPI) USB Ethernet 0x04a9 0x172f complete *none* All resolutions supported (up to 2400DPI) USB 0x04a9 0x172e complete *none* All resolutions supported (up to 4800DPI) USB Ethernet 0x04a9 0x173f complete *none* All resolutions supported (up to 4800DPI) USB 0x04a9 0x2630 complete *none* All resolutions supported (flatbed color up to 1200DPI, grayscale up to 600DPI). USB 0x04a9 0x264d complete *none* All resolutions supported (up to 1200DPI) USB 0x04a9 0x262f good *none* Flatbed color up to 1200DPI, grayscale up to 600DPI. ADF scan to be confirmed. USB 0x04a9 0x264c untested *none* Same protocol as Pixma MP710? Testers needed! USB 0x04a9 0x1706 minimal *none* No grayscale. Canceling scan in ADF mode doesn't eject the paper! USB 0x04a9 0x1708 minimal *none* No grayscale. The scanner sometimes hangs! USB 0x04a9 0x1708 minimal *none* No grayscale. The scanner sometimes hangs! USB 0x04a9 0x1707 minimal *none* No grayscale. The scanner sometimes hangs! USB 0x04a9 0x1707 minimal *none* No grayscale. The scanner sometimes hangs! USB 0x04a9 0x170d complete *none* All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI. USB 0x04a9 0x170e complete *none* All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI. USB 0x04a9 0x171a complete *none* All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI. USB 0x04a9 0x1713 complete *none* All resolutions supported up to 2400DPI. Flatbed, ADF simplex and Duplex supported. USB 0x04a9 0x171b complete *none* All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI. USB Ethernet 0x04a9 0x1726 complete *none* All resolutions supported (up to 4800DPI). Full TPU support (negative and slides) at 24 or 48 bits. USB Ethernet 0x04a9 0x172d complete *none* Working fine at all resolutions. USB Ethernet 0x04a9 0x1740 complete *none* Working fine at all resolutions. USB 0x04a9 0x1727 complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x1728 complete *none* Flatbed and ADF scan. All resolutions supported (up to 1200DPI) USB 0x04a9 0x1736 untested *none* Same protocol as Pixma Generation 3? Testers needed! USB 0x04a9 0x1737 complete *none* Flatbed and ADF scan. All resolutions supported (up to 1200DPI) USB 0x04a9 0x1741 complete *none* Flatbed and ADF scan. All resolutions supported (up to 1200DPI) USB Ethernet 0x04a9 0x1742 complete *none* Flatbed and ADF scan. All resolutions supported (up to 1200DPI) USB 0x04a9 0x174d complete *none* Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy. USB 0x04a9 0x1759 complete *none* Flatbed and ADF scan. All resolutions supported (up to 1200DPI). USB 0x04a9 0x1766 untested *none* Testers needed! USB Ethernet 0x04a9 0x174e untested *none* Same protocol as Pixma MX420? Testers needed! USB Ethernet 0x04a9 0x174f complete *none* Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy. USB Ethernet 0x04a9 0x175b untested *none* Testers needed! USB 0x04a9 0x1768 untested *none* Testers needed! USB Ethernet 0x04a9 0x175c untested *none* Testers needed! USB 0x04a9 0x1769 untested *none* Testers needed! USB Ethernet 0x04a9 0x1729 complete *none* Flatbed and ADF scan. All resolutions supported (up to 2400DPI) USB Ethernet 0x04a9 0x175d untested *none* Testers needed! USB 0x04a9 0x176a untested *none* Testers needed! USB Ethernet 0x04a9 0x172c complete *none* All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported. USB Ethernet 0x04a9 0x1735 complete *none* All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported. USB Ethernet 0x04a9 0x1743 complete *none* All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. USB Ethernet 0x04a9 0x1750 complete *none* All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. USB Ethernet 0x04a9 0x1750 complete *none* All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. USB Ethernet 0x04a9 0x1750 complete *none* All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. USB Ethernet 0x04a9 0x175e complete *none* All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. USB 0x04a9 0x176b untested *none* Testers needed! USB Ethernet 0x04a9 0x171c complete *none* Flatbed and ADF scan. All resolutions supported (up to 4800DPI) USB 0x04a9 0x26ef complete *none* All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported. USB 0x04a9 0x26ed complete *none* All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported. USB Ethernet 0x04a9 0x2759 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x2660 complete *none* All resolutions supported (up to 600DPI). USB 0x04a9 0x2684 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x26b4 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x26b4 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x26a3 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x26a3 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x26a3 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x26a3 complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x26b5 complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x26ee complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x26ee complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x26ee complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x26ec good *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported USB 0x04a9 0x26ec good *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported USB 0x04a9 0x2737 complete *none* All resolutions supported (up to 600DPI) USB 0x04a9 0x2737 good *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI). ADF empty buggy. USB 0x04a9 0x2736 good *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI). USB 0x04a9 0x26b0 complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x26b0 complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x264e untested *none* Testers needed! USB 0x04a9 0x264f untested *none* Testers needed! USB 0x04a9 0x265d complete *none* Flatbed and ADF scan. All resolutions supported (up to 1200DPI). USB 0x04a9 0x265e untested *none* Testers needed! USB 0x04a9 0x265f complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI). USB 0x04a9 0x26f9 untested *none* Testers needed! USB 0x04a9 0x2686 complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x2686 complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x26fa untested *none* Testers needed! USB 0x04a9 0x2707 untested *none* Testers needed! USB 0x04a9 0x2659 untested *none* Testers needed! USB 0x04a9 0x26e6 complete *none* Flatbed and ADF scan. All resolutions supported (up to 600DPI) USB 0x04a9 0x1901 complete *none* Flatbed scan. TPU for negatives and slides. All resolutions supported (up to 4800DPI). USB 0x04a9 0x1908 complete *none* Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI. USB 0x04a9 0x190d complete *none* Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI. 0.52 sane-plustek http://www.gjaeger.de/scanner/plustek/ *none* `http://www.plustek.de/' `http://www.plustek.com/' *none* USB 0x07b3 0x0010 complete *none* NOTE: Devices with product ID 0x0001 are not supported! USB 0x07b3 0x0013 complete *none* *none* USB 0x07b3 0x0017 complete *none* Note: Devices with product ID 0x0001 are not supported! USB 0x07b3 0x0017 complete *none* *none* USB 0x07b3 0x0011 complete *none* *none* USB 0x07b3 0x0015 complete *none* *none* USB 0x07b3 0x0017 complete *none* *none* `http://www.geniusnet.com.tw/' *none* USB 0x0458 0x2007 complete *none* *none* USB 0x0458 0x2008 complete *none* *none* USB 0x0458 0x2013 complete *none* *none* USB 0x0458 0x2009 untested *none* *none* USB 0x0458 0x2015 untested *none* *none* USB 0x0458 0x2016 untested *none* *none* `http://www.mustek.com/' *none* USB 0x0400 0x1000 complete *none* both product versions are supported, see backends' man-page USB 0x0400 0x1001 complete *none* both product versions are supported, see backends' man-page USB 0x0400 0x1001 complete *none* *none* `http://www.hp.com/' *none* USB 0x03f0 0x0505 complete *none* *none* USB 0x03f0 0x0605 complete *none* *none* `http://www.epson.com/' *none* USB 0x04b8 0x010f complete *none* *none* USB 0x04b8 0x010f good *none* TPA scans not perfect USB 0x04b8 0x011d complete *none* *none* USB 0x04b8 0x011d good *none* TPA scans not perfect `http://www.umax.com/' *none* USB 0x1606 0x0050 complete *none* there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x USB 0x1606 0x0060 complete *none* there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x USB 0x1606 0x0060 complete *none* seems to be a renamed UMAX 3400 USB 0x1606 0x0060 complete *none* *none* USB 0x1606 0x0160 complete *none* *none* `http://www.compaq.com/' *none* USB 0x049f 0x001a complete *none* Identical to UMAX 3400 `http://www.canon.com/' *none* USB 0x04a9 0x2206 complete *none* *none* USB 0x04a9 0x2207 complete *none* *none* USB 0x04a9 0x220d complete *none* *none* USB 0x04a9 0x220e complete *none* *none* USB 0x04a9 0x2220 good *none* *none* USB 0x04a9 0x2208 good *none* TPA scans not perfect `http://www.syscaninc.com/' *none* USB 0x0a82 0x4600 complete *none* *none* USB 0x0a82 0x6620 complete *none* *none* *none* *none* USB 0x0a82 0x4600 complete *none* Rebaged Travelscan 464 `http://www.pandp.com.tw/' *none* USB 0x0a53 0x1000 complete *none* *none* USB 0x0a53 0x2000 good *none* *none* `http://www.visioneer.com/' *none* USB 0x04a7 0x0427 basic *none* *none* 0.43 sane-plustek_pp http://www.gjaeger.de/scanner/plustek_pp/ *none* `http://www.plustek.de/' `http://www.plustek.com/' *none* Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* use driver-switch mov=1 Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* reported as OpticPro 12000P/96000P Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* use driver-switch mov=4 Parport (SPP, EPP) *none* *none* complete *none* use driver-switch mov=3 Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* basic *none* use driver-switch mov=5, poor picture quality Parport *none* *none* untested *none* *none* Parport (SPP, EPP) *none* *none* complete *none* *none* Parport (SPP, EPP) *none* *none* complete *none* *none* `http://www.primax.nl/' *none* Parport (SPP, EPP) *none* *none* untested *none* same as OpticPro 4800P Parport (SPP, EPP) *none* *none* complete *none* use driver-switch mov=2 Parport (SPP, EPP) *none* *none* complete *none* same as OpticPro 4830P, use driver-switch mov=7 Parport (SPP, EPP) *none* *none* complete *none* same as OpticPro 9630P `http://www.geniusnet.com.tw/' *none* Parport (SPP, EPP) *none* *none* complete *none* Reported as PT12 Parport (SPP, EPP) *none* *none* complete *none* Reported as OP9636T/12000T Parport (SPP, EPP) *none* *none* good *none* Negative scanning does not work correctly *none* *none* Parport (SPP, EPP) *none* *none* complete *none* use driver-switch mov=2 *none* *none* Parport (SPP, EPP) *none* *none* complete *none* Reported as P12 1.0.8 sane-pnm mailto:henning@meier-geinitz.de *none* Reads PNM files *none* Used for debugging frontends. Obsolete, use test backend instead. unmaintained sane-qcam *none* *none* *none* *none* Parport *none* *none* good *none* Requires root privileges. Parport *none* *none* minimal *none* Requires root privileges. Partly working. unmaintained sane-ricoh *none* *none* `http://www.ricoh.com/' *none* SCSI *none* *none* basic *none* *none* SCSI *none* *none* basic *none* *none* 1.0-0 sane-rts8891 http://stef.dev.free.fr/sane/rts8891/index.html This backend supports Realtek RTS8891 ASIC bases scanners. `http://www.umax.com.tw/' *none* USB 0x1606 0x0070 good *none* Supports 75, 150, 300, 600 and 1200 dpi USB 0x1606 0x0070 untested *none* *none* `http://www.hp.com/' *none* USB 0x03f0 0x0805 good *none* re-branded Astra 4400 USB 0x03f0 0x0705 good *none* exists with 2 different sensors of which only one works unmaintained sane-s9036 *none* *none* `http://www.siemens.com/' *none* SCSI *none* *none* basic *none* *none* 1.0-10 sane-sceptre http://www.zago.net/sane/ *none* `http://www.sceptre.com/' *none* SCSI *none* *none* basic *none* *none* `http://www.komodo.com/' *none* SCSI *none* *none* untested *none* rebadged Sceptre S1200 0.32 sane-sharp http://www.satzbau-gmbh.de/staff/abel/sane-sharp.html *none* `http://sharp-world.com/' *none* SCSI *none* *none* good *none* SCSI *none* *none* good *none* SCSI *none* *none* good *none* SCSI *none* *none* untested *none* SCSI *none* *none* good *none* SCSI *none* *none* good *none* 0.1 sane-sm3600 http://sm3600.sourceforge.net/ *none* `http://www.microtek.com/' *none* USB 0x05da 0x40b3 basic *none* works USB 0x05da 0x40ca basic *none* works USB 0x05da 0x40ff basic *none* works USB 0x05da 0x40b8 basic *none* works USB 0x05da 0x40cb basic *none* works USB 0x05da 0x40dd basic *none* works (told) 1.1 sane-sm3840 http://www.ziplabel.com/sm3840/ This reverse-engineered backend supports the USB ScanMaker 3840 model `http://www.microtek.com/' Microtek makes a wide variety of devices. USB 0x05da 0x30d4 good *none* 8 and 16 bit, color and grayscale USB 0x05da 0x30cf good *none* Same hardware as SM3840, different color box 1.4 sane-snapscan http://snapscan.sourceforge.net/ Supported bit depths: 24 bit (color), 48 bit (color, Epson) 8 bit (gray) `http://www.agfa.com/' *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* Optional ADF supported. SCSI *none* *none* good *none* Optional transparency unit supported. SCSI *none* *none* good *none* Optional ADF and transparency unit supported. USB 0x06bd 0x0002 good *none* Optional ADF and transparency unit supported. USB 0x06bd 0x0001 good *none* *none* USB 0x06bd 0x2061 good *none* *none* USB 0x06bd 0x2093 good *none* *none* USB 0x06bd 0x2091 good *none* *none* USB 0x06bd 0x2095 good *none* *none* USB 0x06bd 0x2097 good *none* *none* USB 0x06bd 0x208d good *none* *none* USB 0x06bd 0x20ff good *none* *none* USB 0x06bd 0x208f good *none* Optional tranparency unit supported USB 0x06bd 0x20fd good *none* Optional tranparency unit supported USB *none* *none* untested *none* *none* *none* Company was renamed to <a href= "#BENQ ">Benq</a>. *none* Company was renamed to <a href= "#BENQ ">Benq</a>. `http://www.benq.com' Formerly Acer Peripherals SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* USB 0x04a5 0x1a20 good *none* *none* USB 0x04a5 0x2022 good *none* *none* USB 0x04a5 0x2022 good *none* *none* USB 0x04a5 0x1a2a good *none* Optional tranparency unit supported USB 0x04a5 0x2040 good *none* Optional tranparency unit supported USB 0x04a5 0x2060 good *none* Optional tranparency unit supported USB 0x04a5 0x207e good *none* *none* USB 0x04a5 0x20be good *none* Optional tranparency unit supported USB 0x04a5 0x20c0 good *none* Optional tranparency unit supported USB 0x04a5 0x20b0 good *none* *none* USB 0x04a5 0x20de good *none* *none* USB 0x04a5 0x20b0 good *none* *none* USB 0x04a5 0x20de good *none* *none* USB 0x04a5 0x20fc basic *none* Same as 5000U, working up to 600 DPI USB 0x04a5 0x20fc basic *none* Same as 5000E, working up to 600 DPI USB 0x04a5 0x20f8 good *none* USB ID 0x04a5,0x20f8: Color / grayscale scans working up to 1200 DPI USB 0x04a5 0x2137 basic *none* Calibration algorithm unknown USB 0x04a5 0x2137 basic *none* Same hardware as 5150 (?), Calibration algorithm unknown USB 0x04a5 0x20fe basic *none* Problems with firmware upload reported `http://www.guillemot.com' *none* SCSI *none* *none* good *none* Rebadged SnapScan 310s. USB 0x04a5 0x20de good *none* Rebadged Benq 3300. USB 0x04a5 0x2060 good *none* Rebadged Benq 640U. USB 0x04a5 0x2060 good *none* Rebadged Benq 620U, needs Benq firmware file u96v???.bin `http://www.mitsubishi.com' *none* USB 0x04a5 0x2022 good *none* Rebadged Benq 320u. USB 0x04a5 0x20b0 good *none* Rebadged Benq 4300. `http://www.epson.com' *none* USB 0x04b8 0x0114 good *none* *none* USB 0x04b8 0x0120 good *none* *none* USB 0x04b8 0x011f good *none* *none* USB 0x04b8 0x0121 good *none* *none* USB 0x04b8 0x0121 basic *none* Film scanning unit unsupported USB 0x04b8 0x0122 good *none* *none* USB 0x04b8 0x0122 basic *none* Film scanning unit unsupported USB 0x04b8 0x080c good *none* *none* unmaintained sane-sp15c *none* *none* `http://www.fcpa.fujitsu.com/products/scanners/' `http://www.fujitsu.com/' *none* SCSI *none* *none* good *none* *none* SCSI *none* *none* good *none* *none* 1.6 sane-st400 http://www.informatik.uni-oldenburg.de/~ingo/sane/ *none* `http://www.siemens.de/' *none* SCSI *none* *none* basic *none* 6 bit gray SCSI *none* *none* basic *none* 6 bit gray 1.0-1 sane-stv680 http://gkall.hobby.nl/stv680-aiptek.html This vidcam backend is for the stv0680 chipset, See the website for more info. `http://www.aiptek.com.tw' *none* USB 0x0553 0x0202 minimal *none* image is OK for CIF and QCIF, VGA and QVGA untested, streaming video is a problem `http://www.konicaminolta.com' *none* USB 0x04c8 0x0722 untested *none* `http://www.digitaldreamco.com/en/index.shtml' *none* USB 0x1183 0x0001 untested *none* `http://www.creative.com/' *none* USB 0x041e 0x4007 untested *none* unmaintained sane-tamarack *none* *none* *none* *none* SCSI *none* *none* good *none* 3 pass, 300 DPI SCSI *none* *none* good *none* 3 pass, 400 DPI SCSI *none* *none* good *none* 3 pass, 600 DPI 1.0-10 sane-teco1 http://www.zago.net/sane/#teco *none* `http://www.relisys.com/' `http://www.tecoimage.com.tw/' *none* SCSI *none* *none* complete *none* sub model VM3530+ SCSI *none* *none* complete *none* sub model VM3520 SCSI *none* *none* good *none* sub model VM4542 SCSI *none* *none* complete *none* sub model VM3520+ SCSI *none* *none* untested *none* sub model VM4530 SCSI *none* *none* untested *none* sub model VM4530+ SCSI *none* *none* untested *none* sub model VM3420 SCSI *none* *none* untested *none* sub model VM3440 SCSI *none* *none* untested *none* sub model VM3530 SCSI *none* *none* complete *none* sub model VM4540 SCSI *none* *none* untested *none* sub model VM6530 SCSI *none* *none* untested *none* sub model VM6530* SCSI *none* *none* untested *none* sub model VM6530+ SCSI *none* *none* untested *none* sub model VM6540 *none* *none* SCSI *none* *none* untested *none* sub model VM3520A *none* *none* SCSI *none* *none* good *none* sub model VM3510 SCSI *none* *none* untested *none* sub model VM3530+ SCSI *none* *none* untested *none* sub model VM4542 SCSI *none* *none* untested *none* sub model VM6530+ 1.0-9 sane-teco2 http://gkall.hobby.nl/teco2.html *none* `http://www.relisys.com/' *none* SCSI *none* *none* untested *none* sub model VM3575 SCSI *none* *none* good *none* sub model VM3564 SCSI *none* *none* good *none* sub model VM3575 SCSI *none* *none* basic *none* sub model VM356A SCSI *none* *none* good *none* sub model VM6565 SCSI *none* *none* good *none* sub model VM6575 SCSI *none* *none* untested *none* sub model VM6586 `http://www.primax.nl/' *none* SCSI *none* *none* good *none* sub model VM356A SCSI *none* *none* basic *none* sub model VM6575 SCSI *none* *none* good *none* sub model VM6586 `http://www.mustek.com/' *none* SCSI *none* *none* untested *none* sub model VM3575 1.0-1 sane-teco3 http://www.zago.net/sane/#teco3 *none* `http://www.tecoimage.com.tw/' *none* SCSI *none* *none* good *none* sub model VM3552 *none* *none* SCSI *none* *none* untested *none* sub model VM3552 `http://www.image-land.com/' *none* SCSI *none* *none* good *none* sub model VM3552 *none* *none* SCSI *none* *none* good *none* sub model VM3552 SCSI *none* *none* good *none* sub model VM3552 SCSI *none* *none* untested *none* sub model VM3552 1.0-28 sane-test http://www.meier-geinitz.de/sane/test-backend/ *none* Frontend-tester *none* Backend for testing frontends. Also serves as example for SANE backend options. 0.02 sane-u12 http://www.gjaeger.de/scanner/u12/ *none* `http://www.plustek.de/' `http://www.plustek.com/' *none* USB 0x07b3 0x0001 basic *none* Note: Only devices with product ID 0x0001 are supported! USB 0x07b3 0x0001 basic *none* Note: Only devices with product ID 0x0001 are supported! USB 0x07b3 0x0001 basic *none* *none* *none* *none* USB 0x07b3 0x0001 basic *none* Rebadged Plustek OpticPro UT12 `http://www.geniusnet.com.tw/' *none* USB 0x0458 0x2004 basic *none* *none* USB 0x07b3 0x0001 untested *none* Note: Device has Plustek vendor and product ID (0x07b3/0x0001) 1.0-41 sane-umax http://www.rauch-domain.de/sane-umax/index.html *none* `http://www.umax.com/' `http://www.umax.com.tw/' `http://www.umax.de/en' `http://www.umax-europe.com' `http://www.umaxjapan.co.jp' `http://www.umax.com.cn' *none* SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK USB 0x1606 0x0230 good *none* OK, needs USB control messages SCSI *none* *none* good *none* OK IEEE-1394 *none* *none* unsupported *none* will probably work one day IEEE-1394 *none* *none* unsupported *none* will probably work one day SCSI *none* *none* good *none* OK USB *none* *none* good *none* OK, needs USB control messages SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK, SCSI-ID=PS-2400X SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* unsupported *none* incompatible SCSI *none* *none* unsupported *none* incompatible IEEE-1394 *none* *none* unsupported *none* will probably work one day SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* untested *none* may work, please test and give feedback SCSI *none* *none* good *none* OK for some firmwareversions, on others only lineart OK SCSI *none* *none* good *none* Version 2.8 OK, others only lineart OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* OK SCSI *none* *none* good *none* Version 1.6 OK, others only lineart OK SCSI *none* *none* untested *none* may work, please test and give feedback SCSI *none* *none* good *none* Version 3.0 OK, others unknown SCSI *none* *none* good *none* Version 1.6 OK, others unknown `http://www.heidelberg.com/' *none* SCSI *none* *none* good *none* OK, SCSI-ID=LinoHell Office SCSI *none* *none* good *none* OK, SCSI-ID=LinoHell JADE SCSI *none* *none* good *none* OK, SCSI-ID=LinoHell Office2 SCSI *none* *none* untested *none* support disabled until tested - please contact author SCSI *none* *none* good *none* OK, SCSI-ID=LinoHell SAPHIR2 SCSI *none* *none* good *none* OK, SCSI-ID=LinoHell SAPHIR3 SCSI *none* *none* untested *none* support disabled until tested - please contact author SCSI *none* *none* good *none* OK, SCSI-ID=Linotype SAPHIR4 SCSI *none* *none* untested *none* support disabled until tested - please contact author SCSI *none* *none* untested *none* support disabled until tested - please contact author SCSI *none* *none* good *none* OK; SCSI-ID=LinoHell OPAL2 SCSI *none* *none* untested *none* support disabled until tested - please contact author SCSI *none* *none* good *none* OK, SCSI-ID=HDM LS4H1S `http://www.vobis.de/' *none* SCSI *none* *none* good *none* OK, SCSI-ID=LinoHell Office2 *none* *none* SCSI *none* *none* untested *none* no feedback `http://www.epson.com/' *none* SCSI *none* *none* good *none* OK, SCSI-ID=EPSON Perfection600 *none* *none* SCSI *none* *none* good *none* OK, SCSI-ID=UMAX UG 80 *none* *none* SCSI *none* *none* untested *none* untested, SCSI-ID=ESCORT Galleria 600S *none* *none* SCSI *none* *none* good *none* OK, SCSI-ID=KYE ColorPage-HR5 `http://www.nikon.com/' *none* SCSI *none* *none* untested *none* may work, please test and give feedback SCSI *none* *none* good *none* OK `http://www.nikon.com/' *none* SCSI *none* *none* good *none* OK unmaintained sane-umax1220u http://sourceforge.net/projects/umax1220u-sane *none* `http://www.umax.com/' *none* USB 0x1606 0x0010 good *none* *none* USB 0x1606 0x0030 good *none* *none* USB 0x1606 0x0030 good *none* *none* USB 0x1606 0x0130 good *none* *none* 1 sane-umax_pp http://umax1220p.sourceforge.net/ *none* `http://www.umax.com.tw/' *none* Parport (EPP/ECP) *none* *none* good *none* *none* Parport (EPP/ECP) *none* *none* good *none* *none* Parport (EPP/ECP) *none* *none* good *none* *none* Parport (SPP/ECP) *none* *none* unsupported *none* untested, but should be close to 610P Parport (SPP/ECP) *none* *none* good *none* *none* *none* *none* Parport (EPP/ECP) *none* *none* good *none* works (relabelled 1220P and 2000P) *none* *none* Parport (EPP/ECP) *none* *none* good *none* works (relabelled 1220P and 2000P) 2010-06-09 *none* /contrib.html The devices mentioned here are not supported by any SANE backend. However, there may be links to information about them or stand-alone programs. *none* *none* USB IEEE-1394 0x06bd 0x02bf unsupported /unsupported/agfa-duoscan-f40.html Unsupported. See link for details. SCSI *none* *none* unsupported /unsupported/agfa-duoscan-t2000xl.html Unsupported. Same as Microtek ArtixScan 2020? SCSI IEEE-1384 *none* *none* unsupported *none* Unsupported. Same as Microtek Artixscan 2500f Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. `http://www.artecusa.com/' *none* USB 0x05d8 0x4001 unsupported /unsupported/artec_1236usb.html Unsupported. See link for details. Parport *none* *none* unsupported *none* Unsupported. Chips found inside: AT015, AD9816JS. Maybe similar to SCSI version or as6e? USB 0x05d8 0x4001 unsupported /unsupported/artec-ultima-2000-2.html Same name, but different ids: This scanner is not supported. The scanner with product id 0x4002 is supported by the gt68xx backend, however. *none* *none* USB Parport 0x05cb 0x1483 unsupported /unsupported/trust-combiscan-19200.html Not supported. See link for details. `http://www.avision.com/' *none* Parport *none* *none* unsupported *none* Probably not supported. Scanner/printer/copier combination. USB *none* *none* unsupported *none* Not supported. No chipset information available. Same as UMAX Astra 6700. USB 0x0638 0x0a10 unsupported /unsupported/umax-astra-4500.html GL646 based, to be added to genesys backend. Same as UMAX Astra 4500. USB 0x0638 0x0a20 unsupported /unsupported/umax-astra-4700.html GL646/GL660 based. Same as UMAX Astra 4700. `http://www.benq.com' Formerly Acer Peripherals Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. Parport *none* *none* unsupported /unsupported/acer-parport.html Unsupported, see link for details. USB 0x04a5 0x211e unsupported *none* Unsupported. USB 0x04a5 0x2211 unsupported /unsupported/benq-5550.html Unsupported, see link for details. USB 0x04a5 0x2311 unsupported http://lists.alioth.debian.org/pipermail/sane-devel/2009-January/023447.html *none* USB 0x04a5 0x2202 unsupported /unsupported/benq-7400ut.html *none* *none* *none* Parport USB 0x05cb 0x1483 unsupported /unsupported/trust-combiscan-19200.html Unsupported. See link for details. `http://www.brother.com/' *none* USB 0x04f9 0x000a unsupported /unsupported/brother-mfc-2500.html Not supported. See link for details. Parport *none* *none* unsupported http://sourceforge.net/projects/brother-mfc The parport 200x400dpi grayscale version of this scanner is unsupported. Dmitri Katchalov did some investigations on this scanner. If you want to write a backend, contact him (see link). Parport USB 0x04f9 0x0106 unsupported /unsupported/brother-mfc-7300.html *none* USB 0x04f9 0x0101 unsupported /unsupported/brother-mfc-9600.html *none* `http://www.c-channel.ch/' *none* USB *none* *none* unsupported /unsupported/c-channel-mypen-pro.html Probably unsupported. See link for details. USB 0x0a93 0x0005 unsupported *none* See bug #306792 for details. USB *none* *none* unsupported *none* Probably unsupported. `http://www.canon.com/' *none* USB 0x04a9 0x2215 unsupported /unsupported/canon-3000.html GL660+GL646 based. USB 0x04a9 0x2215 unsupported /unsupported/canon-3000.html GL660+GL646 based. USB 0x04a9 0x2215 unsupported /unsupported/canon-3000.html GL660+GL646 based, to be added to genesys backend USB 0x04a9 0x221b unsupported /unsupported/canon-4200f.html Probably unsupported. See link. USB 0x04a9 0x2228 unsupported /unsupported/canon-4400.html GL843 based, to be added to genesys backend USB 0x04a9 0x2212 unsupported /unsupported/canon-5000f.html Unsupported. See link for details. USB 0x04a9 0x2217 unsupported /unsupported/canon-5200f.html Probably unsupported. See link for details. USB 0x04a9 0x220f unsupported /unsupported/canon-8000f.html Not supported. See link for more information. With transparency adapter. USB 0x04a9 0x221e unsupported /unsupported/canon-8400f.html GL841 based, to be added to genesys backend USB 0x04a9 0x2229 unsupported /unsupported/canon-8600.html GL841 based, to be added to genesys backend USB 0x04a9 0x2210 unsupported /unsupported/canon-9900f.html Probably unsupported, similar to 8000F. 3200x6400 dpi USB2. With transparency adapter. USB 0x04a9 0x2219 unsupported /unsupported/canon-9950f.html Probably unsupported. USB 0x04a9 0x220b unsupported /unsupported/canon-d646u.html Probably not supported. See link for more information and test program. USB 0x04a9 0x220b unsupported /unsupported/canon-d646u.html Probably not supported. See D646. USB 0x04a9 0x2209 unsupported /unsupported/canon-d1230u.html Probably not supported. USB 0x04a9 0x220c unsupported /unsupported/canon-d1250u2.html Not supported. However, someone started working on this scanner and some information is available (see link). USB 0x04a9 0x220a unsupported /unsupported/canon-d2400uf.html Not supported. See link. USB 0x04a9 0x2201 unsupported *none* Probably not supported. No details known. USB 0x04a9 0x2202 unsupported /unsupported/canon-fb620u.html Probably not supported. Some information is available. USB 0x04a9 0x2205 unsupported http://sourceforge.net/projects/canonscanner/ Not supported. However, a stand-alone program for FreeBSD is available. USB 0x04a9 0x2225 unsupported http://www.juergen-ernst.de/info_sane.html Philips chip. Backend started, see link USB 0x04a9 0x2214 unsupported /unsupported/canon-lide-80.html GL841 based, to be added to genesys backend USB 0x04a9 0x1900 unsupported /unsupported/canon-lide-90.html Unsupported. See link for details. USB 0x04a9 0x221f unsupported /unsupported/canon-canoscan-lide-500f.html GL841 based, to be added to genesys backend USB 0x04a9 0x2224 unsupported http://www.juergen-ernst.de/info_sane.html Philips chip. Backend started, see link USB 0x04a9 0x2224 unsupported http://www.juergen-ernst.de/info_sane.html Philips chip. Backend started, see link USB SCSI 0x04a9 0x3042 unsupported /unsupported/canon-fs4000.html Not supported. See link for more details. USB *none* *none* unsupported /unsupported/canon-is-12.html Probably not supported. Scanner cardridge for Canon inkjet printers. Parport *none* *none* unsupported /unsupported/canon-is-22.html Probably not supported. Scanner cardridge for Canon inkjet printers. USB 0x04a9 0x105d unsupported /unsupported/canon-is-32.html Probably not supported. Scanner cardridge for Canon inkjet printers. USB *none* *none* unsupported /unsupported/canon-is-52.html Probably not supported. Scanner cardridge for Canon inkjet printers. USB 0x04a9 0x269d unsupported /unsupported/canon-imagerunner.html Probably not supported. See link for details. USB 0x04a9 0x269d unsupported /unsupported/canon-imagerunner.html Probably not supported. See link for details. USB 0x04a9 0x269d unsupported /unsupported/canon-imagerunner.html Probably not supported. See link for details. USB 0x04a9 0x1700 unsupported /unsupported/canon-pixma-mp110.html Probably not supported. See link for details. USB 0x04a9 0x1701 unsupported /unsupported/canon-pixma-mp130.html Probably not supported. See link for details. USB *none* *none* unsupported *none* GL84x? *none* *none* Parport Serial Port *none* *none* unsupported /unsupported/chinon-ds3000.html Unsupported at the moment, but a backend is in preparation. See link. `http://www.compaq.com/' *none* USB 0x049f 0x0021 unsupported *none* Not supported. 2400x1200 dpi. One bulk-in, one bulk-out and one interrupt endpoint. Type-number: U0001-HB21, another type nr on the inside: 75100512-00 *none* *none* Parport USB 0x05cb 0x1483 unsupported /unsupported/trust-combiscan-19200.html Unsupported. See link for details. `http://www.cardscan.com/' *none* USB 0x08f0 0x0001 unsupported /unsupported/corex-cardscan-500.html Probably not supported. Businesscard reader. USB 0x08f0 0x0004 unsupported /unsupported/corex-cardscan-700.html Probably not supported. `http://www.dell.com/' *none* USB 0x413c 0x5106 unsupported *none* Probably rebadged Lexmark X5150. May work with sane-lexmark? See bug #312130 USB 0x413c 0x5107 unsupported /unsupported/dell-a960.html Probably not supported. See link for details. USB 0x413c 0x5109 unsupported /unsupported/dell-922.html Probably not supported. See link for details. `http://www.epson.com/' *none* USB 0x04b8 0x0102 unsupported *none* Probably unsupported. No details known. USB 0x04b8 0x0105 unsupported *none* Probably unsupported. No details known. USB 0x04b8 0x083f unsupported /unsupported/epson-stylus-dx4450.html Probably unsupported. See link for details. USB *none* *none* unsupported *none* Probably unsupported at the moment. Not compatible to snapscan backend. It's not known if it may work with epson or epkowa backend. `http://www.bizcardreader.com/' *none* USB 0x0a53 0x5001 unsupported /unsupported/edt-900c.html Probably unsupported. See link for details. *none* E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX Parport *none* *none* unsupported *none* Probably unsupported. Sold 1998. Same as E-Lux j-6121. *none* E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX Parport *none* *none* unsupported *none* Probably unsupported. Sold 1998. Same as E-Lux j-6121. Parport *none* *none* unsupported *none* Probably unsupported. `http://www.geniusnet.com.tw/' `http://www.genius-kye.com/' *none* SCSI *none* *none* unsupported /unsupported/genius-colorpage-cs.html Probably unsupported, see link for details. USB 0x0458 0x2020 unsupported /unsupported/genius-colorpage-slim-1200-usb2.html GL841 based, to be added to genesys backend. USB 0x0458 0x2019 unsupported /unsupported/genius-colorpage-hr6x.html GL646 based, to be added to genesys backend USB 0x0458 0x2018 unsupported /unsupported/genius-colorpage-hr7x.html GL646 based, to be added to genesys backend USB 0x06dc 0x0012 unsupported /unsupported/genius-colorpage-hr7xe.html Unsuported. See link for details. USB 0x0458 0x201c unsupported /unsupported/genius-colorpage-hr8.html GL841 based, to be added to genesys backend *none* *none* USB 0x080d 0x0102 unsupported /unsupported/teco-vm6509.html Probably unsupported. See link for details. Parport *none* *none* unsupported *none* Probably unsupported. Identical to the Benq Prisa 620P. *none* *none* USB 0x080d 0x0102 unsupported /unsupported/teco-vm6509.html Probably unsupported. See link for details. `http://www.hp.com/' *none* USB 0x03f0 0x1001 unsupported /unsupported/hp-photo-1000.html Not supported by SANE. However, it's detected as mass storage device so just mounting it is reported to work. See link for device data. USB *none* *none* unsupported *none* Probably not supported by SANE. No details known. 10x15 cm. Maybe similar to Photo Scanner 1000? USB 0x03f0 0x0102 unsupported /unsupported/hp-photosmart-s20xi.html Not supported yet by SANE. See link for details. USB 0x03f0 0x0102 unsupported /unsupported/hp-photosmart-s20xi.html Not supported yet by SANE. See link for details. USB 0x03f0 0x5811 unsupported /unsupported/hp-photosmart-5100.html Not supported yet by SANE. See link for details. USB 0x03f0 0x0a01 unsupported /unsupported/hp-scanjet-2400c.html GL646 based, to be added to genesys backend USB 0x03f0 0x5611 unsupported /unsupported/hp-photosmart-3180.html Not supported yet by SANE. See link for details. USB 0x03f0 0x2505 unsupported *none* While an external binary-only backend exists, it works only on Linux i386. Therefore the scanner is unsupported on other platforms. USB 0x03f0 0x3005 unsupported /unsupported/hp-scanjet-4600.html Not supported. See link for details, or http://www.chmil.org/hp4600linux/ for code USB 0x03f0 0x3005 unsupported *none* Not supported. See ScanJet 4600 entry. USB 0x03f0 0x1b05 unsupported /unsupported/hp-scanjet-4850.html GL841, maybe can be added to genesys backend USB 0x03f0 0x1b05 unsupported /unsupported/hp-scanjet-4850.html GL843, maybe can be added to genesys backend USB 0x03f0 0x1605 unsupported /unsupported/hp-scanjet-5530.html Maybe GL841_HP, but not confirmed, maybe can be added to genesys backend USB 0x03f0 0x3805 unsupported /unsupported/hp-scanjet-8390.html Probably not supported. See link for details. USB 0x03f0 0x4505 unsupported /unsupported/hp-g4000.html Probably not supported. See link for details. `http://www.ibm.com' *none* Proprietary *none* *none* unsupported *none* Unsupported. Uses proprietary ISA card. Maybe the same as the Plustek Spectra ADF? `http://www.iomagic.com/' *none* USB Parport 0x05cb 0x1483 unsupported /unsupported/trust-combiscan-19200.html Unsupported. See link for details. `http://irislink.com/' *none* USB 0x0a53 0x1000 unsupported /unsupported/iris-iriscan.html Unsupported. LM9832/3. See link for details. USB 0x0f43 0x015a unsupported /unsupported/iris-irispen-translator.html Unsupported. See link for details. USB 0x0a38 0x0301 unsupported /unsupported/iris-business.html Unsupported. See link for details. `http://www.kodak.com' *none* Parport *none* *none* unsupported *none* Unsupported. FCC ID HWF96PHS `http://www.lexmark.com/' *none* USB 0x043d 0x0097 unsupported /unsupported/lexmark-p6250.html Unsupported. See link for details. USB 0x043d 0x007d unsupported /unsupported/lexmark-3150.html Unsupported. See link for details. USB 0x043d 0x0060 unsupported /unsupported/lexmark-x75.html Unsupported. See link for details. USB 0x043d 0x0060 unsupported /unsupported/lexmark-x75.html Unsupported. See link for details. USB 0x043d 0x0060 unsupported /unsupported/lexmark-x75.html Unsupported. See link for details. USB 0x043d 0x003d unsupported /unsupported/lexmark-x83.html Unsupported. GL640. USB 0x043d 0x00bb unsupported /unsupported/lexmark-x2330.html Unsupported. See link for details. USB 0x043d 0x00f6 unsupported /unsupported/lexmark-x3450.html Unsupported. See link for details. USB 0x043d 0x0065 unsupported /unsupported/lexmark-x5130.html Unsupported. USB 0x043d 0x0065 unsupported /unsupported/lexmark-x5130.html Probably unsupported. See link for details. USB 0x043d 0x0093 unsupported /unsupported/lexmark-x5250.html Unsupported. USB 0x043d 0x0072 unsupported /unsupported/lexmark-x6170.html Unsupported. See link for details. USB 0x043d 0x0098 unsupported *none* Unsupported. See bug #310889 for details. USB 0x043d 0x00b8 unsupported /unsupported/lexmark-x7350.html Unsupported. See link for details. USB 0x043d 0x00b9 unsupported /unsupported/lexmark-x8350.html Unsupported. See link for details. *none* *none* Parport *none* *none* unsupported *none* Most probably unsupported. USB 0x046d 0x040f unsupported /unsupported/logitech-pagescan-usb.html Probably unsupported. See link for details. `http://www.medion.com/' `http://www.medion.de/' *none* USB 0x0461 0x0392 unsupported /unsupported/medion-md6190.html Probably unsupported. There seem to exist two different scanners with that name. See link for details. USB 0x0461 0x037b unsupported /unsupported/medion-md6190.html Probably unsupported. There seem to exist two different scanners with that name. See link for details. USB 0x05da 0x3008 unsupported /unsupported/tevion-md40420.html Probably unsupported. See link for details. USB 0x0461 0x037b unsupported /unsupported/medion-md6190.html Probably unsupported. See link for details. USB 0x0461 0x037b unsupported /unsupported/medion-md6190.html Probably unsupported. See link for details. USB 0x05da 0x3008 unsupported /unsupported/tevion-md40420.html Probably unsupported. See link for details. USB 0x08ff 0x2580 unsupported http://gkall.hobby.nl/authentec.html Fingerprint sensor. See link for details. USB 0x05da 0x30e5 unsupported /unsupported/tevion-md90009.html Probably unsupported. See link for details. USB 0x05da 0x3022 unsupported /unsupported/tevion-md90070.html Unsupported. See link for details. USB 0x05da 0x3022 unsupported /unsupported/tevion-md90070.html Unsupported. See link for details. `http://www.memorex.com/' *none* USB 0x0461 0x0346 unsupported /unsupported/memorex-maxx-6136u.html Probably unsupported. USB 0x0461 0x0347 unsupported /unsupported/visioneer-onetouch4400.html Probably unsupported. Same as Visioneer Onetouch 4400. See link for details. USB Parport 0x05cb 0x1483 unsupported /unsupported/trust-combiscan-19200.html Unsupported. See link for details. Parport *none* *none* unsupported /unsupported/memorex-scf-9612p.html Probably unsupported. See link for details. `http://www.microtek.com/' *none* SCSI *none* *none* unsupported *none* Unsupported. Same as Agfa DuoScan T2000XL? USB 0x05da 0x202e unsupported /unsupported/microtek-artixscan-2020.html Unsupported. See link for details. SCSI IEEE-1384 *none* *none* unsupported *none* Unsupported. Same as Agfa DuoScan T2500? USB *none* *none* unsupported *none* Unsupported. Uses ALI M5611B. USB 0x05e3 0x0120 unsupported /unsupported/microtek-filmscan-35.html Probably unsupported. See link for details. SCSI *none* *none* unsupported *none* Probably unsupported. Seems to be similar to the Microtek 330 CX and is detected by the microtek2 backend. Scanning doesn't seem to work however. SCSI *none* *none* unsupported /unsupported/microtek-scanmaker-1850s.html Unsupported. See link for details. USB 0x0461 0x0347 unsupported /unsupported/microtek-scanmaker-3630.html Unsupported. Doesn't seem to be compatible to 3600 series, see link. USB 0x05da 0x30ce unsupported /unsupported/microtek-scanmaker-3800.html Unsupported. See link for more details. USB 0x05da 0x30ce unsupported /unsupported/microtek-scanmaker-3830.html Unsupported. See link for more details. USB 0x05da 0x3023 unsupported /unsupported/microtek-scanmaker-3880.html Unsupported. See link for more details. Appears to be similar to ScanMaker 3880. USB 0x05da 0x3021 unsupported /unsupported/microtek-scanmaker-3880.html Unsupported. SQ113 chip. See link for more details. USB 0x05da 0x40c7 unsupported /unsupported/microtek-scanmaker-4600.html Unsupported. See link for more details. USB 0x05da 0x20b4 unsupported /unsupported/microtek-scanmaker-4700.html Unsupported. See link for more details. USB 0x05da 0x30d9 unsupported /unsupported/microtek-scanmaker-4900.html Probably unsupported. See link for details. USB 0x05da 0x3008 unsupported /unsupported/microtek-scanmaker-4850-2.html Probably unsupported. See link for details. USB 0x05da 0x30b9 unsupported /unsupported/microtek-scanmaker-4900.html Unsupported. See link for more details. SCSI *none* *none* unsupported /unsupported/microtek-scanmaker-5600.html Probably unsupported. See link for more details. USB 0x05da 0x20a7 unsupported /unsupported/microtek-scanmaker-5600.html Unsupported. See link for more details. USB 0x05da 0x20bd unsupported *none* Unsupported. Uses ALI M5615 like the ScanMaker 4700. USB 0x05da 0x3008 unsupported /unsupported/microtek-scanmaker-5800.html Unsupported. See link for details. USB 0x05da 0x30d8 unsupported /unsupported/microtek-scanmaker-5800.html Unsupported. See link for details. USB 0x05da 0x30d8 unsupported /unsupported/microtek-scanmaker-5900.html Unsupported. See link for more details. USB 0x05da 0x30d8 unsupported /unsupported/microtek-scanmaker-5950.html Unsupported. See link for more details. USB 0x05da 0x30e5 unsupported /unsupported/microtek-scanmaker-6000.html Unsupported. See link for more details. USB 0x05da 0x30e5 unsupported /unsupported/microtek-scanmaker-6100.html Unsupported. See link for more details. USB IEEE-1394 0x05da 0x20c9 unsupported /unsupported/microtek-scanmaker-6700.html Unsupported. See link. USB IEEE-1394 0x05da 0x20b1 unsupported /unsupported/microtek-scanmaker-8700.html Unsupported. See link for details. USB vendor and product ids to be checked. USB IEEE-1394 0x05da 0x20de unsupported *none* Probably unsupported. SCSI seems to work with microtek2 backend. USB SCSI 0x05da 0x20de unsupported /unsupported/microtek-scanmaker-9800.html Partly unsupported. IEEE-1394 works with microtek2 backend. See link. USB 0x05da 0x30e6 unsupported /unsupported/microtek-scanmaker-i320.html Unsupported. See link. USB 0x05da 0x201c unsupported /unsupported/microtek-scanmaker-s400.html Unsupported. See link. USB 0x05da 0x300b unsupported /unsupported/microtek-scanmaker-s400.html Unsupported. See link. USB 0x04a7 0x0224 unsupported /unsupported/microtek-scanport-3000.html Unsupported. Vendor/Product ids: 0x04a7/0x0224. Realtek RTS8801B?. See link for details. `http://www.konicaminolta.com/' *none* USB 0x0686 0x400d unsupported /unsupported/minolta-dual-scan-III.html Unsupported. May work with vuescan. See link for details. USB 0x132b 0x000a unsupported /unsupported/minolta-dual-scan-IV.html Unsupported. Works with vuescan. See link for details. USB IEEE-1394 0x0686 0x400e unsupported /unsupported/minolta-dse-5400.html Probably unsupported. May work with vuescan. See link for details. USB 0x132b 0x0012 unsupported /unsupported/minolta-dse-5400-2.html Probably unsupported. See link for details. IEEE-1394 *none* *none* unsupported /unsupported/minolta-dimage-scan-multi-pro.html Probably unsupported. See link for details. USB Network *none* *none* unsupported *none* Uses a different scanning protocol than the magicolor 1690MF `http://www.mustek.com/' `http://www.mustek.de/' `http://www.mustek.com.tw/' *none* Parport *none* *none* unsupported *none* Probably not supported. quarlewm at jmu dot edu offers to temporarily loan such a scanner to anyone who is interested in writing a driver. USB *none* *none* unsupported http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED Probably unsupported. No details known. USB 0x055f 0x0400 unsupported http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED Not supported. May be supported by mustek_usb2 backend later. See link for some information. USB 0x055f 0x0408 unsupported /unsupported/mustek-bearpaw-2448-cu-pro.html Not supported. May be supported by mustek_usb2 backend later. See link for some information. USB 0x055f 0x1000 unsupported /unsupported/mustek-bearpaw-4800ta-pro.html Not supported. See link for some information. USB 0x055f 0x040a unsupported /unsupported/mustek-bearpaw-4800ta-pro-ii.html Not supported. May be supported by mustek_usb2 backend later. See link for some information. USB 0x055f 0x040b unsupported http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED Not supported. May be supported by mustek_usb2 backend later. See link for some information. Parport *none* *none* unsupported *none* Not supported. Maybe similar to 600 II EP (SCSI_over-parport)? In this case it could be supported by the mustek SCSI backend. USB 0x055f 0x0873 unsupported http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED Unsupported. Programming information is available. USB 0x055f 0x0003 unsupported http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED Unsupported. Programming information is available. USB 0x055f 0x0007 unsupported http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED Unsupported. Parport *none* *none* unsupported http://penguin-breeder.org/?page=mustek_pp Not supported. Asic 1505/05. Parport *none* *none* unsupported *none* Not supported. Maybe it will be supported by the mustek_pp backend in future. USB *none* *none* unsupported http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED Probably unsupported. USB business card scanner. Maybe works as USB storage device? Parport *none* *none* unsupported http://lists.alioth.debian.org/pipermail/sane-devel/2003-May/007682.html Probably not supported. Same as Mustek 12000 P?. ASIC 1505. `http://www.nevt.co.jp/' *none* USB 0x0475 0x0100 unsupported /unsupported/nec-petiscan.html Most probably unsupported. See link for details. Vendor ID is Relisys/Teco. Not known if it is similar to other Relisys/Teco USB scanners. `http://www.nikon.com/' *none* IEEE-1394 *none* *none* unsupported /unsupported/nikon-ls9000-ed.html Probably not supported. See link for details. Possibly similar to LS-8000 ED. `http://www.olivetti.com' *none* USB 0x0b3c 0xa880 unsupported /unsupported/olivetti-job-jet-m400.html Probably not supported. See link for details. `http://www.olympus.com' *none* Parport *none* *none* unsupported http://lists.alioth.debian.org/pipermail/sane-devel/2008-December/023326.html *none* SCSI *none* *none* unsupported /unsupported/olympus-es10s.html Probably not supported. See link for details. *none* *none* USB 0x065a 0x0001 unsupported *none* Probably not supported. *none* *none* Parport *none* *none* unsupported http://www.df.lth.se/~triad/krad/optrox/ *none* Parport *none* *none* unsupported http://www.df.lth.se/~triad/krad/optrox/ *none* Proprietary *none* *none* unsupported http://www.df.lth.se/~triad/krad/optrox/ Special ISA card Parport *none* *none* unsupported http://www.df.lth.se/~triad/krad/optrox/ *none* Parport *none* *none* unsupported http://www.df.lth.se/~triad/krad/optrox/ *none* Proprietary *none* *none* unsupported http://www.df.lth.se/~triad/krad/optrox/ Special ISA card *none* *none* SCSI *none* *none* unsupported *none* might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool. USB SCSI *none* *none* unsupported *none* might be supported by matsushita backend. SCSI *none* *none* unsupported *none* might be supported by matsushita backend. SCSI *none* *none* unsupported *none* might be supported by matsushita backend. USB SCSI *none* *none* unsupported *none* might be supported by matsushita backend. USB SCSI *none* *none* unsupported *none* might be supported by matsushita backend. USB SCSI *none* *none* unsupported *none* might be supported by matsushita backend. USB SCSI *none* *none* unsupported *none* might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool. SCSI *none* *none* unsupported *none* might be supported by matsushita backend. SCSI *none* *none* unsupported *none* might be supported by matsushita backend. SCSI *none* *none* unsupported *none* might be supported by matsushita backend. SCSI *none* *none* unsupported *none* might be supported by matsushita backend. USB SCSI *none* *none* unsupported *none* might be supported by matsushita backend. *none* *none* USB 0x0a82 0x2000 unsupported /unsupported/syscan-travelscan-pro.html Probably not supported. Some information is available. `http://www.scanace.com/' Pacific Image Electronics USB 0x05e3 0x0120 unsupported /unsupported/pie-1800u.html Not supported. See link for details. USB *none* *none* unsupported http://lists.alioth.debian.org/pipermail/sane-devel/2009-January/023442.html *none* USB IEEE-1394 *none* *none* unsupported *none* Probably not supported. USB IEEE-1394 0x05e3 0x0142 unsupported /unsupported/reflecta-digitdia-3600.html Probably unsupported. Film scanner that can scan directly from the magazine. USB IEEE-1394 0x05e3 0x0143 unsupported /unsupported/pie-pf3650.html Not supported. See link for details. `http://www.plustek.de/' `http://www.plustek.com/' *none* USB 0x07b3 0x0807 unsupported /unsupported/plustek-opticfilm-7200.html GL842 based, maybe to be added to genesys backend USB 0x07b3 0x0c04 unsupported *none* GL843 based, maybe to be added to genesys backend USB *none* *none* unsupported *none* Uses Plustek ASIC P99002 USB *none* *none* unsupported *none* Uses RealTek chipset (RTL8801D) USB 0x07b3 0x0600 unsupported /unsupported/plustek-opticpro-st12.html Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend. USB 0x07b3 0x0600 unsupported /unsupported/plustek-opticpro-st12.html Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend. USB 0x07b3 0x0600 unsupported /unsupported/plustek-opticpro-st16.html GL646 based, to be added to genesys backend USB *none* *none* unsupported *none* Probably LM983x based. USB 0x07b3 0x0601 unsupported /unsupported/plustek-opticpro-st24.html Product id 0x0601 is unsupported but may be supported by the genesys backend in future /GL646). Product id 0x040e is supported by the gt68xx backend. USB 0x07b3 0x0601 unsupported /unsupported/plustek-opticpro-st24.html GL646 based, to be added to genesys backend USB 0x07b3 0x0801 unsupported /unsupported/plustek-opticpro-s28.html GL841 based, to be added to genesys backend USB 0x07b3 0x0801 unsupported /unsupported/plustek-opticpro-s28.html GL841 based, to be added to genesys backend USB 0x07b3 0x0802 unsupported /unsupported/plustek-opticpro-st28.html GL841 based, to be added to genesys backend USB 0x07b3 0x0802 unsupported /unsupported/umax-astrscan-4750.html GL841 based, to be added to genesys backend, rebadged Plustek ST28 USB 0x07b3 0x0800 unsupported /unsupported/plustek-opticpro-st48.html GL841 based, to be added to genesys backend USB 0x07b3 0x0c00 unsupported /unsupported/plustek-opticpro-st64.html GL843 based, maybe to be added to genesys backend USB 0x07b3 0x0c03 unsupported /unsupported/plustek-opticpro-st64plus.html GL843 based. See link for more details. USB 0x07b3 0x0c0c unsupported /unsupported/plustek-pl806.html Unsupported. See link for more details. USB 0x07b3 0x0c0d unsupported /unsupported/plustek-pl812.html Unsupported. See link for more details. USB 0x07b3 0x0458 unsupported /unsupported/plustek-opticslim-500.html Unsupported. See link for more details. USB 0x07b3 0x0806 unsupported /unsupported/plustek-opticslim-2420.html GL841 based, to be added to genesys backend USB 0x07b3 0x0914 unsupported /unsupported/plustek-opticslim-2420plus.html GL841 based, to be added to genesys backend Parport *none* *none* unsupported *none* Multifunction device. No further information available. USB *none* *none* unsupported *none* Business card reader. No further information available. USB 0x07b3 0x081c unsupported /unsupported/plustek-scancopy-115.html GL841 based, to be added to genesys backend Proprietary *none* *none* unsupported *none* Unsupported. Uses proprietary ISA card that also provides power and is labelled GPS-1 PAGE-A from Taiwan. Other labels on the scanner include ADF Color Scanner and SF600AS. Maybe the same as the IBM ADF Color Scanner? USB 0x07b3 0x0005 unsupported *none* Probably unsupported. Scanner name not known yet. USB 0x07b3 0x0007 unsupported *none* Probably unsupported. Scanner name not known yet. USB 0x07b3 0x000f unsupported *none* Probably unsupported. Scanner name not known yet. USB 0x07b3 0x0012 unsupported *none* Probably unsupported. Scanner name not known yet. USB 0x07b3 0x0014 unsupported *none* Probably unsupported. Scanner name not known yet. USB 0x07b3 0x0016 unsupported *none* Probably unsupported. Scanner name not known yet. `http://www.planon.com/' *none* USB *none* *none* unsupported *none* Probably not supported. No details known. USB 0x10c4 0xea60 unsupported /unsupported/planon-docupen-r700.html Probably not supported. See link for details. USB *none* *none* unsupported *none* Probably not supported. No details known. `http://www.primax.nl/' *none* USB 0x0461 0x0341 unsupported /unsupported/primax-colorado-600u.html Not supported. Some information is available. Parport *none* *none* unsupported http://home2.swipnet.se/~w-25069/pxscan.html Unsupported by SANE. But is reported to partly work with pxscan. See link. USB 0x0461 0x0361 unsupported *none* Probably unsupported. No details known. USB 0x0461 0x0347 unsupported /unsupported/visioneer-onetouch4400.html Unsupported. Same as Visioneer Onetouch 4400. See link for details. Parport *none* *none* unsupported http://home2.swipnet.se/~w-25069/pxscan.html Not supported. However, a stand-alone program is available. Parport *none* *none* unsupported http://home2.swipnet.se/~w-25069/pxscan.html Not supported. However, a stand-alone program is available. USB 0x0461 0x0340 unsupported /unsupported/primax-colorado-usb-9600.html Not supported. See link for details. USB 0x0461 0x0300 unsupported *none* Probably unsupported. No details known. USB 0x0461 0x0302 unsupported *none* Probably unsupported. No details known. USB 0x0461 0x0301 unsupported *none* Probably unsupported. No details known. USB 0x0461 0x0303 unsupported *none* Probably unsupported. No details known. USB 0x0461 0x0380 unsupported *none* Probably unsupported. No details known. USB 0x0461 0x0382 unsupported *none* Probably unsupported. No details known. USB 0x0461 0x0383 unsupported *none* Probably unsupported. No details known. Parport *none* *none* unsupported *none* Not supported. USB 0x0461 0x0381 unsupported *none* Probably unsupported. No details known. USB *none* *none* unsupported *none* Maybe GL646. Maybe similar to Medion MD 6228? USB 0x0461 0x0371 unsupported /unsupported/visioneer-onetouch8920.html Not supported. Look similar to Visioneer Onetouch 8920 (same USB product id). `http://www.fida.com/' *none* USB 0x06dc 0x0014 unsupported /unsupported/prolink-2448u.html Not supported. Some information is available. RealTek RTS8801. USB Parport *none* *none* unsupported *none* Not supported. No further information available. `http://www.quato.de/' *none* SCSI *none* *none* unsupported *none* Probably not supported. No details yet. Originally manufactured by PFU? USB IEEE-1394 *none* *none* unsupported *none* Probably not supported. No details yet. *none* *none* USB IEEE-1394 0x05e3 0x0142 unsupported /unsupported/reflecta-digitdia-3600.html Film scanner that can scan directly from the magazine. USB 0x05e3 0x0120 unsupported /unsupported/reflecta-iscan-1800.html Probably unsupported. See link for details. USB IEEE-1394 0x05e3 0x0143 unsupported /unsupported/reflecta-proscan-4000.html Probably unsupported. See link for details. *none* *none* USB 0x0475 0x0103 unsupported /unsupported/relisys-eclipse-1200u.html Probably unsupported. See link for details. USB 0x0475 0x0210 unsupported /unsupported/relisys-scorpio-ultra3.html Probably unsupported. See link for details. USB 0x0475 0x0103 unsupported /unsupported/relisys-episode.html Probably unsupported. See link for details. Parport *none* *none* unsupported *none* Parport version of AVEC II S3?. See bug #304992 for details *none* *none* USB 0x04e8 0x341f unsupported /unsupported/samsung-scx-4725.html Not supported. See link for details. *none* *none* USB 0x0a82 0x6605 unsupported /unsupported/scanshell-800n.html Not supported. See link for details. *none* *none* proprietary *none* *none* unsupported mailto:ehaase@inf.fu-berlin.de Not supported until now. Work on a backend has started, contact the author for details (see link) `http://www.siemens.com/' *none* USB 0x0681 0x0005 unsupported *none* Not supported. USB 0x0681 0x0010 unsupported *none* Not supported. *none* *none* USB IEEE-1394 *none* *none* unsupported *none* Probably not supported. Same as PIE Primefilm 2600 PRO. *none* Spot seems have gone out of business. proprietary *none* *none* unsupported http://www.el-profesor.net/spoonset/ Not supported until now. Work on a backend has started, see link for more information. proprietary *none* *none* unsupported http://www.el-profesor.net/spoonset Not supported. Work on a backend has started, see link for more information. proprietary *none* *none* unsupported http://www.el-profesor.net/spoonset Not supported. Work on a backend has started, see link for more information. *none* *none* USB 0x0a82 0x0530 unsupported /unsupported/syscan-travelscan-fs531.html Not supported. May work with the Plustek backend in future. See link for details. USB 0x0a82 0x2000 unsupported /unsupported/syscan-travelscan-pro.html Probably not supported. Some information is available. *none* *none* Parport *none* *none* unsupported http://www.autistici.org/tamarhack/ Unsupported at the moment. See link for a project for that scanner taht may support it in future. Parport *none* *none* unsupported http://www.autistici.org/tamarhack/ Unsupported at the moment. See link for a project for that scanner. USB 0x05e3 0x0100 unsupported /unsupported/tamarack-artiscan-2400.html Unsupported. See link for more information. `http://www.tce.com.br/' Brasilian vendor. USB 0x0461 0x0346 unsupported /unsupported/memorex-maxx-6136u.html Not supported. Some information is available. Parport *none* *none* unsupported http://home2.swipnet.se/~w-25069/pxscan.html Not supported by SANE but is reported to work with pxscan (see link). `http://www.tecoimage.com.tw/' *none* USB 0x080d 0x0102 unsupported /unsupported/teco-vm6509.html Probably unsupported. See link for details. *none* *none* USB 0x0461 0x0347 unsupported /unsupported/visioneer-onetouch4400.html Unsupported. See link for details. `http://www.trust-site.com' *none* Parport USB 0x05cb 0x1483 unsupported /unsupported/trust-combiscan-19200.html Unsupported. See link for details. Parport *none* *none* unsupported http://lists.alioth.debian.org/pipermail/sane-devel/2008-October/022955.html *none* SCSI *none* *none* unsupported /unsupported/trust-scsi-scan-19200.html Unsupported. See link for details. `http://www.umax.com/' *none* USB 0x0461 0x0374 unsupported /unsupported/umax-astra-2500.html Probably not supported. See link for details. USB 0x07b3 0x0601 unsupported /unsupported/plustek-opticpro-st24.html Probably not supported. Same IDs as Plustek OpticPro ST24. See link for details. USB 0x0461 0x038a unsupported /unsupported/umax-astra-3000.html Probably not supported. See link for details. USB 0x0461 0x038a unsupported /unsupported/umax-astra-3600.html Probably not supported. See link for details. USB 0x1606 0x1030 unsupported /unsupported/umax-astra-4000.html Not supported. See link for details. USB 0x0461 0x038c unsupported /unsupported/umax-astra-4100.html Not supported, to be added to genesys backend. USB 0x0638 0x0a10 unsupported /unsupported/umax-astra-4500.html GL646 based, to be added to genesys backend. Avision iVina FB1600 clone USB *none* *none* unsupported *none* Probably not supported, no details known. USB 0x0638 0x0a20 unsupported /unsupported/umax-astra-4700.html GL646/GL660 based. Avision iVina FB1800 clone. USB *none* *none* unsupported *none* Not supported. No chipset information available. Same as Avision iVina FB2400. USB 0x080d 0x0104 unsupported /unsupported/umax-astraslim.html Probably not supported currently. See link for more details. USB 0x080d 0x0110 unsupported /unsupported/umax-astraslim-1200.html See link for more details. USB 0x080d 0x0104 unsupported /unsupported/umax-astraslim-6000.html Probably not supported currently. See link for more details. Parport *none* *none* unsupported *none* Probably not supported. No details known.. USB *none* *none* unsupported /unsupported/umax-powerlook-180.html Probably not supported. See link for details. USB *none* *none* unsupported *none* Probably not supported. No further information available. *none* *none* USB 0x04a7 0x0224 unsupported /unsupported/visioneer-onetouch4800.html Not supported. See link for more details. `http://www.visioneer.com/' *none* USB 0x0461 0x0345 unsupported *none* Not supported. Is reported to use the E5 chipset. Uses a Primax ID. Looks similar to Primascan Colorado 2600u. USB 0x04a7 0x0311 unsupported *none* Not supported. Id is from Primax? Yet another scanner with the same name? USB 0x0461 0x03a8 unsupported /unsupported/visioneer-9420.html Unsupported. See link for details. USB 0x04a7 0x0421 unsupported /unsupported/visioneer-9450-usb.html Unsupported. See link for details. USB 0x0461 0x0347 unsupported /unsupported/visioneer-onetouch4400.html Not supported. E5 chipset? See link for more details. USB 0x04a7 0x0224 unsupported /unsupported/visioneer-onetouch4800.html Unsupported. Seems to use Realtek RTS8801B. Same as Microtek Scanport 3000. See link for details. USB 0x04a7 0x0226 unsupported /unsupported/visioneer-onetouch5300.html Not supported. Chipset is RTS8801B(?). See link for output of /proc/bus/usb/devices. USB 0x04a7 0x0221 unsupported *none* Not supported. Yet another scanner with this name? USB 0x04a7 0x0226 unsupported /unsupported/visioneer-onetouch5800.html Unsupported. 48 bit scanner, doesn't work with viceo backend. RTS8801C. USB 0x04a7 0x022a unsupported /unsupported/visioneer-onetouch6600.html Unsupported. See link for details. USB 0x04a7 0x0229 unsupported /unsupported/visioneer-onetouch7100.html GL646 based, to be added to genesys backend USB 0x04a7 0x0380 unsupported /unsupported/visioneer-onetouch7700.html LM9832/3 based, to be added to plustek backend USB 0x04a7 0x0321 unsupported /unsupported/visioneer-onetouch8100.html Unsupported. See link for details. USB 0x04a7 0x0371 unsupported /unsupported/visioneer-onetouch8920.html Not supported. See link for details. USB 0x04a7 0x0371 unsupported /unsupported/visioneer-onetouch8920.html Not supported. Same as 8920 but without TA? USB 0x04a7 0x0371 unsupported /unsupported/visioneer-onetouch8920.html Not supported. Same as 8700 and 8900 but includes a TA. Uses a Primax ID. Chipset is RTS8801C. See link for output of /proc/bus/usb/devices. USB 0x04a7 0x022c unsupported /unsupported/visioneer-onetouch9020.html Not supported. See link for details. USB 0x04a7 0x022c unsupported /unsupported/visioneer-onetouch9020.html Not supported. See link for details. USB 0x04a7 0x0362 unsupported /unsupported/visioneer-onetouch9320.html Probably not supported. See link for details. USB 0x04a7 0x0410 unsupported /unsupported/visioneer-onetouch8820.html Probably not supported. See link for details. USB 0x04a7 0x0410 unsupported /unsupported/visioneer-onetouch8820.html Probably not supported. See link for details. Parport *none* *none* unsupported /unsupported/visioneer-paperport-3100b.html Most probably not supported. See link for details. Parport *none* *none* unsupported *none* Most probably not supported. More details would be appreciated. Parport *none* *none* unsupported /unsupported/visioneer-paperport-onetouch.html Most probably not supported. See link for details. USB 0x04a7 0x0102 unsupported /unsupported/visioneer-strobe-pro-usb.html Not supported. See link for details. USB 0x04a7 0x03a0 unsupported /unsupported/xerox-4800-onetouch.html Unsupported. See link for details. Different id compared to One Touch 4800? SCSI *none* *none* unsupported /unsupported/xerox-docuimage-620s.html Not supported. See link for more details. USB 0x04a7 0x0446 unsupported /unsupported/xerox-documate-510.html Not supported. See link for more details. USB 0x04a7 0x047c unsupported /unsupported/xerox-documate-510.html Not supported. See link for more details. Yet another USB id. USB 0x04a7 0x0224 unsupported /unsupported/visioneer-onetouch4800.html Unsupported. See link for details. Different id compared to 4800 One Touch? Parport *none* *none* unsupported /unsupported/xerox-workcentre-470cx.html Not supported. See link for more details. USB 0x0924 0xffef unsupported /unsupported/xerox-workcentre-m15i.html Not supported. See link for more details. USB Parport 0x043d 0x0020 unsupported /unsupported/xerox-workcentre-xk35c.html Not supported. See link for more details. USB 0x04e8 0x3903 unsupported /unsupported/xerox-workcentre-xk50cx.html Not supported. See link for more details. USB Parport 0x043d 0x4303 unsupported /unsupported/xerox-workcentre-pro412.html Not supported. See link for more details. USB Parport 0x0924 0x4220 unsupported /unsupported/xerox-workcentre-pe16.html Not supported. See link for more details. USB 0x0924 0x4237 unsupported /unsupported/xerox-workcentre-pe120i.html Not supported. See link for more details. *none* *none* USB 0x0923 0x010f unsupported /unsupported/biolux-654.html Not supported yet. See link for more details. *none* *none* USB 0x0797 0x801c unsupported /unsupported/grandtech-scopecam.html Not Supported yet. See link for more details. 1.0-3 sane-v4l mailto:henning@meier-geinitz.de *none* Interface to Video For Linux API *none* Supports video cameras and other devices accessed by the v4l kernel API, e.g. bttv devices. Quite a lot of known bugs. 1.0-13 sane-xerox_mfp *none* *none* `http://www.office.xerox.com/' *none* USB 0x0924 0x3d5d good *none* *none* USB 0x0924 0x3da4 complete http://www.office.xerox.com/multifunction-printer/multifunction-under-30ppm/phaser-3200mfp/spec-enus.html *none* USB 0x0924 0x4265 good *none* *none* USB 0x0924 0x420c good *none* *none* USB 0x0924 0x4293 good *none* *none* USB 0x0924 0x4294 good *none* *none* `http://www.dell.com/' *none* USB 0x413c 0x5124 good *none* *none* `http://www.samsung.com' *none* USB 0x04e8 0x3409 untested *none* *none* USB 0x04e8 0x340d untested *none* *none* USB 0x04e8 0x340e untested *none* *none* USB 0x04e8 0x340f untested *none* *none* USB 0x04e8 0x3412 untested *none* *none* USB 0x04e8 0x3413 good *none* *none* USB 0x04e8 0x3419 untested *none* *none* USB 0x04e8 0x341a untested *none* *none* USB 0x04e8 0x341b good *none* *none* USB 0x04e8 0x341c untested *none* *none* USB 0x04e8 0x341d untested *none* *none* USB 0x04e8 0x341f untested *none* *none* USB 0x04e8 0x341f good *none* *none* USB 0x04e8 0x3420 untested *none* *none* USB 0x04e8 0x3421 untested *none* *none* USB 0x04e8 0x3425 good *none* *none* USB 0x04e8 0x3426 good *none* *none* USB 0x04e8 0x3427 untested *none* *none* USB 0x04e8 0x3428 untested *none* *none* USB 0x04e8 0x3429 untested *none* *none* USB 0x04e8 0x342a good *none* *none* USB 0x04e8 0x342a good *none* *none* USB Ethernet 0x04e8 0x342b basic *none* *none* USB 0x04e8 0x342c good *none* *none* USB 0x04e8 0x342d good *none* *none* USB 0x04e8 0x342e good *none* *none* USB 0x04e8 0x342f good *none* *none* USB 0x04e8 0x3430 untested *none* *none* USB 0x04e8 0x3432 untested *none* *none* USB 0x04e8 0x3433 good *none* *none* USB 0x04e8 0x3434 good *none* *none* USB 0x04e8 0x3435 untested *none* *none* USB 0x04e8 0x3437 untested *none* *none* USB 0x04e8 0x3439 untested *none* *none* USB 0x04e8 0x343a good *none* *none* USB 0x04e8 0x343b untested *none* *none* USB 0x04e8 0x343c good *none* *none* USB 0x04e8 0x343d good *none* *none* USB 0x04e8 0x343f untested *none* *none* USB 0x04e8 0x3440 good *none* *none* USB Ethernet 0x04e8 0x3441 good *none* *none* USB 0x04e8 0x3442 untested *none* *none* USB 0x04e8 0x3443 untested *none* *none* USB 0x04e8 0x3444 untested *none* *none* USB 0x04e8 0x3446 good *none* *none* USB 0x04e8 0x344b good *none* *none* Ethernet 0x04e8 0x344b good *none* *none* Ethernet *none* *none* basic *none* *none* USB 0x04e8 0x344f untested *none* *none* USB 0x04e8 0x3450 untested *none* *none* USB 0x04e8 0x3453 basic *none* *none* USB 0x04e8 0x3455 minimal *none* *none* USB 0x04e8 0x3456 basic *none* *none* USB 0x04e8 0x3457 untested *none* *none* USB 0x04e8 0x345a minimal *none* *none* USB 0x04e8 0x345b untested *none* *none* USB 0x04e8 0x3460 untested *none* *none* USB 0x04e8 0x3461 untested *none* *none* USB 0x04e8 0x3466 untested *none* *none* USB 0x04e8 0x3468 untested *none* *none* sane-backends-1.0.27/testsuite/tools/data/statistics.ref0000664000175000017500000000076612775312262020234 00000000000000Number of known devices: Scanners: Total: 2337 Supported: 1205 (complete: 417, good: 662, basic: 101, minimal: 25) Untested: 325 Unsupported: 482 Still cameras: Total: 5 Supported: 5 (complete: 1, good: 2, basic: 2, minimal: 0) Untested: 0 Unsupported: 0 Video cameras: Total: 11 Supported: 3 (complete: 0, good: 1, basic: 0, minimal: 2) Untested: 3 Unsupported: 2 Meta backends: Total: 2 API backends: Total: 5 sane-backends-1.0.27/testsuite/tools/data/ascii.ref0000664000175000017500000143773312775312262017143 00000000000000backend `abaton' version `unmaintained' manpage `sane-abaton' url *none* comment *none* type scanner mfg `Abaton' url *none* comment *none* model `Scan 300/GS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `All known modes and functions supported' model `Scan 300/S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Untested, use with caution' backend `agfafocus' version `unmaintained' manpage `sane-agfafocus' url *none* comment *none* type scanner mfg `AGFA' url `http://www.agfa.com/' comment *none* model `Focus GS Scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `6 bit gray' model `Focus Lineart Scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Lineart only? Untested.' model `Focus II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `gray only' model `Focus Color' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3-pass' model `Focus Color Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3-pass' mfg `Siemens' url *none* comment *none* model `S9036' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `gray only' backend `apple' version `unmaintained' manpage `sane-apple' url *none* comment *none* type scanner mfg `Apple' url `http://developer.apple.com/' comment *none* model `Apple Scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `4bit, 16 shades of gray' model `OneScanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `8bit, 256 shades of gray. The backend needs work especially in the quantization code but it may work.' model `Color OneScanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `truecolor (needs much work) but it scans in non color modes.' backend `artec' version `unmaintained' manpage `sane-artec' url `http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html' comment *none* type scanner mfg `Artec/Ultima' url `http://www.artecusa.com/' comment *none* model `AT3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `all modes working' model `A6000C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `all modes working' model `A6000C PLUS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `f/w <= v1.92 basic, f/w >= v1.93 OK' model `AT6' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Scan head needs to return home before another scan can be started.' model `AT12' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `all modes working' model `AM12S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `all modes working' mfg `BlackWidow' url `http://www.blackwidow.co.uk/' comment *none* model `BW4800SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `rebadged Artec AT3' mfg `Plustek' url `http://www.plustek.com/' comment *none* model `OpticPro 19200S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `rebadged Artec AM12S' backend `artec_eplus48u' version `unmaintained' manpage `sane-artec_eplus48u' url *none* comment *none* type scanner mfg `Artec/Ultima' url `http://www.artecusa.com/' comment *none* model `E+ 48U' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4003' status good url *none* comment `CIS scanner based on the GT6816 chip. Apparently all other devices are re-badged Artec scanners.' model `E+ Pro' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4004' status minimal url *none* comment `Works up to 600dpi, but not 1200. Needs better calibration. See bug #310490' mfg `Medion/Lifetec/Tevion/Cytron' url `http://www.medion.com' comment `Sold by Aldi and Tchibo.' model `MD9693' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4003' status good url *none* comment *none* model `MD9705' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4003' status good url *none* comment *none* model `MD4394' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4003' status good url *none* comment `Only scanners with product id 0x4003 will work; try the gt68xx backend, if your scanner has product id 0x4002 ' mfg `Trust' url `http://www.trust-site.com' comment *none* model `Easy Webscan 19200' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4006' status good url *none* comment *none* model `240H Easy Webscan Gold' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4007' status basic url *none* comment `Works up to 600 dpi' mfg `Memorex' url `http://www.artecusa.com/' comment *none* model `MEM 48U' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4005' status good url *none* comment *none* mfg `Microstar' url `http://www.microstar.de/' comment *none* model `MR 9791' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4003' status good url *none* comment *none* mfg `UMAX' url `http://www.umax.com/' url `http://www.umax.com.tw/' url `http://www.umax.de/en' url `http://www.umax-europe.com' url `http://www.umaxjapan.co.jp' url `http://www.umax.com.cn' comment *none* model `AstraSlim SE' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4009' status good url *none* comment *none* model `AstraSlim 1200 SE' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4010' status good url *none* comment *none* mfg `Yakumo' url `http://www.yakumo.com/' comment *none* model `Scan50' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4011' status good url *none* comment *none* backend `as6e' version `0.5' manpage `sane-as6e' url `http://as6edriver.sourceforge.net/' comment *none* type scanner mfg `Artec/Ultima' url `http://www.artecusa.com/' comment *none* model `AS6E' interface `Parport' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Requires the program 'as6edriver' to run.' mfg `Trust' url `http://www.trust-site.com' comment `Carefully check the model names. Trust uses similar names for completely different hardware.' model `Easy Scan 9600 Plus' interface `Parport' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Requires the program 'as6edriver' to run.' mfg `Dexxa' url `http://www.dexxa.com' comment *none* model `4800' interface `Parport' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Requires the program 'as6edriver' to run.' backend `avision' version `Build: 296' manpage `sane-avision' url `http://skull.piratehaven.org/~mike/sane/avision.html' comment *none* type scanner mfg `Avision' url `http://www.avision.com' comment *none* model `AV100CS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV100IIICS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV100S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV120' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a27' status complete url *none* comment `sheetfed scanner' model `AV121' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a3c' status good url *none* comment `sheetfed scanner' model `AV122' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a33' status good url *none* comment `sheetfed duplex scanner' model `AV122 C2' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a93' status good url *none* comment `sheetfed duplex scanner' model `AV210' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a24' status complete url *none* comment `sheetfed scanner' model `AV210' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a25' status complete url *none* comment `sheetfed scanner' model `AV210C2' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a3a' status complete url *none* comment `sheetfed scanner' model `AV210C2-G' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a2f' status complete url *none* comment `sheetfed scanner' model `AV210D2+' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x1a35' status complete url *none* comment `sheetfed scanner' model `AV220' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a23' status complete url *none* comment `duplex! sheetfed scanner' model `AV220C2' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a2a' status complete url *none* comment `duplex! sheetfed scanner' model `AV220D2' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a2b' status complete url *none* comment `duplex! sheetfed scanner' model `AV220+' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a2c' status complete url *none* comment `duplex! sheetfed scanner' model `AV220C2-G' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a2d' status complete url *none* comment `duplex! sheetfed scanner' model `AV220C2-B' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a2e' status complete url *none* comment `duplex! sheetfed scanner' model `AV220-G' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a94' status complete url *none* comment `duplex! sheetfed scanner' model `AV240SC' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV260CS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV360CS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV363CS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV420CS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV6120' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `AV610' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a18' status good url *none* comment *none* model `AV600U Plus' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a18' status good url *none* comment *none* model `AV610C2' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a5e' status good url *none* comment *none* model `AM3000 Series' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a41' status basic url *none* comment `MFD' model `DS610CU Scancopier' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a16' status good url *none* comment `1 pass, 600 dpi, A4' model `AV620CS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, 600 dpi' model `AV620CS Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, 1200 dpi' model `AV630CS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, 1200 dpi' model `AV630CSL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, 1200 dpi' model `AV6240' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, ??? dpi' model `AV600U' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a13' status good url *none* comment `1 pass, 600 dpi' model `AV660S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, ??? dpi' model `AV680S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, ??? dpi' model `AV690U' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, 2400 dpi' model `AV800S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, ??? dpi' model `AV810C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, ??? dpi' model `AV820' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, ??? dpi' model `AV820C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, ??? dpi' model `AV820C Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, ??? dpi' model `AV830C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, ??? dpi' model `AV830C Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, ??? dpi' model `AV880' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, ??? dpi' model `AV880C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `1 pass, ??? dpi' model `AV3200C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, ??? dpi' model `AV3200SU' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a4e' status complete url *none* comment `1 pass, ??? dpi' model `AV3730SU' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a4f' status complete url *none* comment `1 pass, ??? dpi' model `AV3750SU' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a65' status complete url *none* comment `1 pass, ??? dpi' model `AV3800C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, ??? dpi' model `AV3850SU' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a66' status complete url *none* comment `1 pass, ??? dpi' model `FB6000E' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, 1200 dpi, A3 - duplex! - zero edge!' model `FB6080E' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a82' status complete url *none* comment `1 pass, 1200 dpi, A3 - duplex! - zero edge!' model `FB2080E' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a84' status basic url *none* comment `1 pass, 600 dpi, zero-edge' model `AV8000S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `1 pass, 1200 dpi, A3' model `AV8050U' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a4d' status complete url *none* comment `1 pass, 1200 dpi, A3 - duplex!' model `AV8300' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a40' status complete url *none* comment `1 pass, 1200 dpi, A3 - duplex!' model `AV8350' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a68' status complete url *none* comment `1 pass, 1200 dpi, A3 - duplex!' model `IT8300' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a61' status good url *none* comment `1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors' model `@V2500' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0aa1' status untested url *none* comment *none* model `@V5100' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a45' status good url *none* comment `1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors' model `AVA3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `1 pass, 600 dpi, A3' mfg `Hewlett-Packard' url `http://www.hp.com' comment *none* model `ScanJet 5300C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0701' status complete url *none* comment `1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi' model `ScanJet 5370C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0701' status good url *none* comment `1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi' model `ScanJet 7400c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0801' status good url *none* comment `1 pass, 2400 dpi - dual USB/SCSI interface' model `ScanJet 7450c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0801' status good url *none* comment `1 pass, 2400 dpi - dual USB/SCSI interface' model `ScanJet 7490c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0801' status good url *none* comment `1 pass, 1200 dpi - dual USB/SCSI interface' model `ScanJet 8200' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0b01' status good url *none* comment `1 pass, 4800 (?) dpi - USB 2.0' model `ScanJet 8250' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0b01' status good url *none* comment `1 pass, 4800 (?) dpi - USB 2.0' model `ScanJet 8270' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x3905' status good url *none* comment `1 pass, 4800 (?) dpi - USB 2.0' model `ScanJet 8290' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0b01' status good url *none* comment `1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far' model `ScanJet 8300' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x3805' status good url *none* comment `1 pass, 4800 (?) dpi - USB 2.0' model `ScanJet 8350' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x3805' status good url *none* comment `1 pass, 4800 (?) dpi - USB 2.0' model `ScanJet 8390' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x3805' status good url *none* comment `1 pass, 4800 (?) dpi - USB 2.0' mfg `Minolta' url `http://www.minolta.com' comment *none* model `Dimage Scan Dual I' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `Scan Multi Pro' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `Dimage Scan Dual II' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x026a' status good url *none* comment `1 pass, film-scanner' model `Elite II' interface `USB' usb-vendor-id `0x0686' usb-product-id `0x4004' status untested url *none* comment `1 pass, film-scanner' model `Dimage Scan Dual III' interface `USB' usb-vendor-id `0x0686' usb-product-id `0x400d' status good url *none* comment `1 pass, film-scanner' model `Dimage Scan Elite 5400' interface `USB' usb-vendor-id `0x0686' usb-product-id `0x400e' status good url *none* comment `1 pass, film-scanner' mfg `Minolta-QMS' url *none* comment *none* model `SC-110' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a15' status untested url *none* comment *none* model `SC-215' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a16' status good url *none* comment *none* mfg `Mitsubishi' url *none* comment *none* model `MCA-ADFC' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `S1200C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `S600C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `SS600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* mfg `Fujitsu' url `http://www.fujitsu.com' comment *none* model `ScanPartner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanPartner 10' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanPartner 10C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanPartner 15C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanPartner 300C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanPartner 600C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanPartner 620C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ScanPartner Jr' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanStation' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `fi-4010CU' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1029' status untested url *none* comment *none* model `fi-5015C' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x10ef' status good url *none* comment *none* mfg `Kodak' url `http://www.kodak.com' comment *none* model `i30' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x6001' status untested url *none* comment *none* model `i40' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x6002' status basic url *none* comment *none* model `i50' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x6003' status untested url *none* comment *none* model `i55' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x6003' status untested url *none* comment *none* model `i60' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x6004' status untested url *none* comment *none* model `i65' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x6004' status untested url *none* comment *none* model `i80' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x6005' status good url *none* comment *none* mfg `iVina' url *none* comment *none* model `1200U' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0268' status untested url *none* comment *none* mfg `Visioneer' url *none* comment *none* model `Strobe XP 450' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0424' status complete url *none* comment `sheetfed scanner' model `Strobe XP 450-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0491' status complete url *none* comment `sheetfed scanner' model `Strobe XP 470' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0479' status complete url *none* comment `sheetfed scanner' model `Strobe XP 470-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x048f' status complete url *none* comment `sheetfed scanner' model `9320' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0420' status complete url *none* comment `sheetfed scanner' model `9450' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0421' status complete url *none* comment `sheetfed scanner' model `9450-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x047a' status complete url *none* comment `sheetfed scanner' model `9550' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0422' status complete url *none* comment `sheetfed scanner' model `9650' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0390' status complete url *none* comment `sheetfed scanner' model `9650-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x047b' status complete url *none* comment `sheetfed scanner' model `9750' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0423' status complete url *none* comment `sheetfed scanner' model `9750-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0493' status complete url *none* comment `sheetfed scanner' model `Patriot 430' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0497' status complete url *none* comment `sheetfed scanner' model `Patriot 470' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x048f' status complete url *none* comment `sheetfed scanner' model `Patriot 680' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0498' status complete url *none* comment `sheetfed scanner' model `Patriot 780' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0499' status complete url *none* comment `sheetfed scanner' mfg `Xerox' url *none* comment *none* model `DocuMate150' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x049c' status good url *none* comment *none* model `DocuMate152' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0477' status good url *none* comment *none* model `DocuMate162' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x049d' status good url *none* comment *none* model `DocuMate250' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0448' status good url *none* comment *none* model `DocuMate250-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0490' status good url *none* comment *none* model `DocuMate252' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0449' status good url *none* comment *none* model `DocuMate252-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x048c' status good url *none* comment *none* model `DocuMate232' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0476' status good url *none* comment *none* model `DocuMate262' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x044c' status good url *none* comment *none* model `DocuMate262-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x048d' status good url *none* comment *none* model `DocuMate262i' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x04a7' status good url *none* comment *none* model `DocuMate272' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0475' status untested url *none* comment *none* model `DocuMate272-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x048e' status untested url *none* comment *none* model `DocuMate510' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0446' status untested url *none* comment *none* model `DocuMate512' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0495' status untested url *none* comment *none* model `DocuMate510-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x047c' status untested url *none* comment *none* model `DocuMate520' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0447' status untested url *none* comment *none* model `DocuMate520-G' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0492' status untested url *none* comment *none* model `DocuMate632' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0498' status untested url *none* comment *none* model `DocuMate752' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0478' status untested url *none* comment *none* model `DocuMate752' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x049a' status untested url *none* comment *none* mfg `OKI' url *none* comment *none* model `S700 Scancopier' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a16' status good url *none* comment `1 pass, 600 dpi, A4' mfg `Bell+Howell' url *none* comment *none* model `2000F' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `1 pass, ??? dpi, A4' mfg `Kyocera' url *none* comment *none* model `FS-1016MFP' interface `USB' usb-vendor-id `0x0482' usb-product-id `0x0335' status untested url *none* comment `1 pass, ??? dpi, A4' backend `bh' version `1.0-4' manpage `sane-bh' url `http://www.martoneconsulting.com/sane-bh.html' comment `Supports Copiscan II scanners with Remote SCSI Controller (RSC) interface' type scanner mfg `Bell and Howell' url `http://www.bhscanners.com/' comment *none* model `COPISCAN II 6338' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Duplex Scanner with ACE - development model' model `COPISCAN II 2135' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Simplex Scanner' model `COPISCAN II 2137(A)' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Simplex Scanner (with ACE) - limited testing' model `COPISCAN II 2138A' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Simplex Scanner with ACE' model `COPISCAN II 3238' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Simplex Scanner' model `COPISCAN II 3338(A)' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Simplex Scanner (with ACE)' backend `canon' version `1.12' manpage `sane-canon' url `http://www.rzg.mpg.de/~mpd/sane/' comment *none* type scanner mfg `Canon' url `http://www.canon.com/' comment *none* model `CanoScan 300' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `1 pass; flatbed scanner' model `CanoScan 600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `1 pass; flatbed scanner' model `CanoScan 620S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `1 pass; flatbed scanner' model `CanoScan 1200S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `1 pass; flatbed scanner' model `CanoScan 2700F' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `1 pass; film scanner' model `CanoScan 2710S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `1 pass; 36bit film scanner' model `IX-4015' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `1 pass; flatbed scanner' mfg `Apple' url `http://www.apple.com/' comment *none* model `Color OneScanner 600/27' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Rebadged CanoScan 300' backend `canon630u' version `0.1' manpage `sane-canon630u' url `http://canon-fb630u.sourceforge.net/' comment *none* type scanner mfg `Canon' url `http://www.canon.com/' comment *none* model `CanoScan fb630u' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2204' status good url *none* comment `OK' model `CanoScan fb636u' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2204' status good url *none* comment `OK' backend `canon_dr' version `38' manpage `sane-canon_dr' url `http://www.thebility.com/canon/' comment `Backend updated for SANE release 1.0.23, see sane-canon_dr manpage' type scanner mfg `Canon' url `http://www.canon.com/' comment *none* model `CR-25' interface `USB' usb-vendor-id `0x1083' usb-product-id `0x161a' status untested url *none* comment `Please test!' model `CR-55' interface `USB' usb-vendor-id `0x1083' usb-product-id `0x160c' status untested url *none* comment `Please test!' model `CR-135i' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x1639' status untested url *none* comment `Please test!' model `CR-180' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x1602' status untested url *none* comment `Please test!' model `CR-180II' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x1602' status untested url *none* comment `Same as CR-180? Please test!' model `CR-190i' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x162b' status untested url *none* comment `Please test!' model `DR-1210C' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2222' status untested url *none* comment `Older version? Please test!' model `DR-1210C' interface `USB' usb-vendor-id `0x1083' usb-product-id `0x160f' status untested url *none* comment `Later version? Please test!' model `DR-2010C' interface `USB' usb-vendor-id `0x1083' usb-product-id `0x161b' status complete url *none* comment `Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions.' model `DR-2010M' interface `USB' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Mac version of DR-2010C? Please test!' model `DR-2050C' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x160a' status complete url *none* comment `Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration.' model `DR-2050SP' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x160a' status untested url *none* comment `Same as DR-2050C? Please test!' model `DR-2080C' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x1601' status complete url *none* comment `Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration' model `DR-2510C' interface `USB' usb-vendor-id `0x1083' usb-product-id `0x1617' status complete url *none* comment `Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions' model `DR-2510M' interface `USB' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Mac version of DR-2510C? Please test!' model `DR-2580C' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x1608' status complete url *none* comment `Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration' model `DR-3010C' interface `USB' usb-vendor-id `0x1083' usb-product-id `0x161d' status good url *none* comment `Minimal testing, settings copied from DR-2510C' model `DR3020' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `DR-3020C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `DR-3060' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `DR-3080C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Almost works, need to investigate traces from windows driver' model `DR-3080CII' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x1609' status untested url *none* comment `Almost works, need to investigate traces from windows driver' model `DR-4010C' interface `USB' usb-vendor-id `0x1083' usb-product-id `0x1614' status good url *none* comment `Binary/HT/Gray/Color, Simplex/Duplex working. Multistream unsupported.' model `DR4080U' interface `USB' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `DR-4580U' interface `USB' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `DR-5010C' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1606' status untested url *none* comment `Please test!' model `DR-5020' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `LineArt, Duplex working, cannot read buttons or screen?' model `DR-5060F' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Grayscale works, LineArt might' model `DR-5080C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `DR-6010C' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x1626' status untested url *none* comment `Please test!' model `DR-6030C' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x1638' status untested url *none* comment `Please test!' model `DR-6050C' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x1624' status good url *none* comment `Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode' model `DR-6080' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x1607' status good url *none* comment `Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported' model `DR-7080C' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x1604' status untested url *none* comment `Please test!' model `DR-7090C' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x1620' status good url *none* comment `ADF and flatbed work' model `DR-7550C' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x1623' status untested url *none* comment `Assumed compatible with DR-6050C' model `DR-7580' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x160b' status good url *none* comment `Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported' model `DR-9050C' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x1622' status good url *none* comment `Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode' model `DR-9080C' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x1603' status good url *none* comment `Simplex, duplex, all resolutions, binary/ht/gray/color, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported' model `DR-X10C' interface `USB SCSI' usb-vendor-id `0x1083' usb-product-id `0x1618' status untested url *none* comment `Please test!' backend `canon_pp' version `0.33' manpage `sane-canon_pp' url `http://canon-fb330p.sourceforge.net' comment *none* type scanner mfg `Canon' url `http://www.canon.com/' comment *none* model `CanoScan FB310P' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Rebadged Avision, different command set' model `CanoScan FB610P' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Rebadged Avision, different command set' model `CanoScan FB320P' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Newly added support' model `CanoScan FB620P' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Newly added support' model `CanoScan FB330P' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `CanoScan FB630P' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `CanoScan N340P' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `CanoScan N640P' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `CanoScan N640P ex' interface `Parport (ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Just an N640P in a different box?' backend `cardscan' version `2' manpage `sane-cardscan' url `http://www.thebility.com/cardscan/' comment `Backend updated for SANE release 1.0.21, see sane-cardscan manpage' type scanner mfg `Corex' url `http://www.cardscan.com/' comment *none* model `800c' interface `USB' usb-vendor-id `0x08f0' usb-product-id `0x0005' status good url *none* comment `4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner' model `600c' interface `USB' usb-vendor-id `0x08f0' usb-product-id `0x0002' status basic url *none* comment `4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner' backend `coolscan' version `0.4.3' manpage `sane-coolscan' url `http://andreas.rick.free.fr/sane/' comment *none* type scanner mfg `Nikon' url `http://www.nikon.com/' comment *none* model `LS-20' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `The LS-20 has been replaced by the LS-30' model `LS-30' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `alpha: only 24/30 bit RGB + 32/40 bit RGBI' model `LS-2000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `alpha: only 24/36 bit + RGB 32/48 bit RGBI' model `LS-1000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Doesn't support gamma correction' backend `coolscan2' version `0.1.8' manpage `sane-coolscan2' url `http://coolscan2.sourceforge.net/' comment *none* type scanner mfg `Nikon' url `http://www.nikon.com/' comment *none* model `LS 30' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `working -- model available to developer' model `LS 2000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `LS 40 ED' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4000' status complete url *none* comment *none* model `LS 4000 ED' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `needs linux kernel 2.4.19 or later' model `LS 50 ED' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4001' status minimal url *none* comment *none* model `Coolscan V ED' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4001' status minimal url `/unsupported/nikon-ls50-ed.html' comment *none* model `Super Coolscan LS-5000 ED' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4002' status untested url `/unsupported/nikon-ls5000-ed.html' comment `May work, similar to LS 50 ED, but untested. Please tell us if it works.' model `LS 8000 ED' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `needs linux kernel 2.4.19 or later' backend `coolscan3' version `1.0.0' manpage `sane-coolscan3' url *none* comment *none* type scanner mfg `Nikon' url `http://www.nikon.com/' comment *none* model `LS 30' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Coolscan III' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Rebadged LS 30?' model `LS 40 ED' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4000' status complete url *none* comment *none* model `Coolspan IV' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4000' status complete url *none* comment `Rebadged LS 40?' model `LS 50 ED' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4001' status minimal url `/unsupported/nikon-ls50-ed.html' comment *none* model `Coolscan V ED' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4001' status minimal url `/unsupported/nikon-ls50-ed.html' comment `Rebadged LS 50?' model `LS 2000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `LS 4000 ED' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `needs linux kernel 2.4.19 or later' model `Super Coolscan LS-5000 ED' interface `USB' usb-vendor-id `0x04b0' usb-product-id `0x4002' status untested url `/unsupported/nikon-ls5000-ed.html' comment `May work, similar to LS 50 ED, but untested. Please tell us if it works.' model `LS 8000 ED' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `needs linux kernel 2.4.19 or later' backend `dc25' version `1.2' manpage `sane-dc25' url `mailto:peter@fales-lorenz.net' comment *none* type stillcam mfg `Kodak' url `http://www.kodak.com/global/en/service/digCam/dc25/dc25.shtml' comment *none* model `DC25' interface `Serial port' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `DC20' interface `Serial port' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `DC-20 untested by author but reported to work' backend `dc210' version `0.0' manpage `sane-dc210' url `mailto:peter@fales-lorenz.net' comment *none* type stillcam mfg `Kodak' url `http://www.kodak.com/global/en/service/digCam/dc210/dc210.shtml' comment *none* model `DC210' interface `Serial port' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* backend `dc240' version `0.0' manpage `sane-dc240' url `mailto:peter@fales-lorenz.net' comment *none* type stillcam mfg `Kodak' url `http://www.kodak.com/global/en/service/products/ekn006568.jhtml' comment *none* model `DC240' interface `Serial port' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Use gphoto2 backend to get USB support' backend `dell1600n_net' version *none* manpage *none* url *none* comment *none* type scanner mfg `Dell' url `http://www.dell.com/' comment *none* model `1600n' interface `Ethernet USB' usb-vendor-id `0x413c' usb-product-id `0x5250' status basic url *none* comment `Supports colour and monochrome scans over ethernet (USB not supported)' backend `dll' version `1.0.13' manpage `sane-dll' url `mailto:henning@meier-geinitz.de' comment *none* type meta desc `Dynamic loading of shared-library backends.' url *none* comment *none* backend `dmc' version `unmaintained' manpage `sane-dmc' url *none* comment *none* type stillcam mfg `Polaroid' url `http://www.polaroid.com/' comment *none* model `DMC' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* backend `epjitsu' version `20' manpage `sane-epjitsu' url `http://www.thebility.com/epjitsu/' comment `Backend updated for SANE release 1.0.21, see sane-epjitsu manpage' type scanner mfg `Fujitsu' url `http://www.fujitsu.com/' comment *none* model `fi-60F' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x10c7' status basic url *none* comment `A6-size flatbed, 300/600 dpi, color/gray/binary' model `ScanSnap S300' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1156' status good url *none* comment `Duplex, 150/225/300/600 dpi, color/gray/binary, AC/USB power, buttons/sensors all supported. Scanner always scans in _triplex_ color, fast USB required.' model `ScanSnap S300M' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x117f' status good url *none* comment `Same as S300, with different usb id' model `ScanSnap S1100' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1200' status unsupported url *none* comment `Beta version of backend source available, which works well, but breaks support for other epjitsu scanners. See http://ubuntuforums.org/showthread.php?t=1678335' model `ScanSnap S1300' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x11ed' status good url *none* comment `Same as S300, with different usb id' backend `epson' version `unmaintained' manpage `sane-epson' url `http://www.khk.net/sane' comment *none* type scanner mfg `Epson' url `http://www.epson.com/' comment *none* model `GT-5000' interface `SCSI Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Actionscanner II' interface `SCSI Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `US version of GT-5000' model `GT-6000' interface `SCSI Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ES-300C' interface `SCSI Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `US version of GT-6000' model `ES-300GS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-5500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-6500' interface `Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ES-600C' interface `Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `US version of GT-6500' model `ES-1200C' interface `Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `US version of GT-9000' model `GT-7000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-8000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ES-8500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Perfection 636S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `US version of GT-7000' model `Perfection 636' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Perfection 636U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0101' status complete url *none* comment *none* model `Perfection 610' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0103' status complete url *none* comment *none* model `Perfection 640' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010c' status complete url *none* comment *none* model `Perfection 1200S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Perfection 1200U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0104' status complete url *none* comment *none* model `Perfection 1200Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0104' status complete url *none* comment `with TPU' model `Perfection 1240' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x010b' status complete url *none* comment *none* model `Perfection 1640' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x010a' status complete url *none* comment *none* model `Perfection 1650' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0110' status complete url *none* comment *none* model `Perfection 1660' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011e' status complete url *none* comment *none* model `Perfection 2400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011b' status complete url *none* comment *none* model `Perfection 2450' interface `USB IEEE-1394' usb-vendor-id `0x04b8' usb-product-id `0x0112' status complete url *none* comment *none* model `Perfection 3200' interface `USB IEEE-1394' usb-vendor-id `0x04b8' usb-product-id `0x011c' status complete url *none* comment `US version of the GT-9800' model `Perfection 4870' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0128' status complete url *none* comment `US version of the GT-X700' model `Perfection 4990' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012a' status complete url *none* comment `US version of the GT-X800' model `Expression 636' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `US version of GT-9500' model `Expression 800' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Expression 1600' interface `SCSI USB IEEE-1394' usb-vendor-id `0x04b8' usb-product-id `0x0107' status complete url *none* comment *none* model `Expression 1680' interface `SCSI USB IEEE-1394' usb-vendor-id `0x04b8' usb-product-id `0x010e' status complete url *none* comment *none* model `FilmScan 200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.vjet.demon.co.uk/scanner/' comment `A better backend for the FilmScan 200 can be found at http://www.vjet.demon.co.uk/scanner/' model `CX-3200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0802' status good url *none* comment *none* model `CX-3600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080e' status good url *none* comment *none* model `CX-3650' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080e' status good url *none* comment *none* model `CX-4600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080d' status good url *none* comment *none* model `CX-4800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0819' status good url *none* comment *none* model `CX-5000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082b' status good url *none* comment *none* model `CX-5200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0801' status good url *none* comment *none* model `CX-5400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0801' status good url *none* comment *none* model `CX-5400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0808' status good url *none* comment *none* model `CX-6300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0805' status good url *none* comment *none* model `CX-6400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0805' status good url *none* comment *none* model `CX-6500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0813' status good url *none* comment *none* model `CX-6600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0813' status good url *none* comment *none* model `RX-500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0807' status good url *none* comment *none* model `RX-600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0806' status good url *none* comment *none* model `RX-425' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080f' status good url *none* comment *none* model `RX-700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0810' status good url *none* comment *none* model `RX-620' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0811' status good url *none* comment *none* model `DX-3850' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0818' status good url *none* comment *none* model `CX-3700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0818' status good url *none* comment *none* model `CX-3800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0818' status good url *none* comment *none* model `CX-4200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0820' status good url *none* comment *none* model `DX-3800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0818' status good url *none* comment *none* model `DX-5000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082b' status good url *none* comment *none* model `DX-5050' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082b' status good url *none* comment *none* model `DX-6000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082e' status good url *none* comment *none* model `DX-7400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0838' status good url *none* comment *none* model `DX-4050' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082f' status good url *none* comment *none* model `AcuLaser CX11' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0815' status good url *none* comment *none* model `AcuLaser CX11NF' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0815' status good url *none* comment *none* model `V700' interface `USB IEEE-1394' usb-vendor-id `0x04b8' usb-product-id `0x012c' status good url *none* comment *none* model `V750' interface `USB IEEE-1394' usb-vendor-id `0x04b8' usb-product-id `0x012c' status good url *none* comment *none* backend `epson2' version `1.0.124' manpage `sane-epson2' url *none* comment *none* type scanner mfg `Epson' url `http://www.epson.com/' comment *none* model `Actionscanner II' interface `parallel SCSI' usb-vendor-id *none* usb-product-id *none* status good url `http://www.epson.com/' comment `overseas version of the GT-5000' model `AcuLaser CX11' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0815' status good url *none* comment `overseas version of the LP-A500' model `AcuLaser CX11NF' interface `USB Network' usb-vendor-id `0x04b8' usb-product-id `0x0815' status good url *none* comment `network interface supported
AcuLaser CX11 with network interface and fax' model `AcuLaser CX21' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0835' status good url *none* comment `network interface probably supported' model `Artisan 700' interface `USB Network' usb-vendor-id `0x04b8' usb-product-id `0x0846' status good url *none* comment `network interface supported
all-in-one
overseas version of the EP-801A' model `Artisan 710 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0852' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Artisan 800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0844' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the EP-901A' model `Artisan 810 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0853' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `CC-500L' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010d' status unsupported url *none* comment `all-in-one' model `CC-550L' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011a' status unsupported url *none* comment `all-in-one' model `CC-570L' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0802' status good url *none* comment `all-in-one' model `CC-600PX' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0801' status good url *none* comment `all-in-one' model `CC-700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0108' status unsupported url *none* comment `all-in-one' model `EP-702A' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0850' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `EP-801A' interface `USB Network' usb-vendor-id `0x04b8' usb-product-id `0x0846' status good url *none* comment `network interface supported
all-in-one' model `EP-802A' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0852' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `EP-901A' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0844' status good url *none* comment `network interface probably supported
all-in-one' model `EP-901F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0844' status good url *none* comment `network interface probably supported
all-in-one' model `EP-902A' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0853' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `ES-300C' interface `SCSI parallel' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `overseas version of the GT-6000' model `ES-300GS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ES-600C' interface `parallel' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `overseas version of the GT-5400' model `ES-800C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `overseas version of the GT-8000' model `ES-1000C' interface *none* usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `overseas version of the GT-8500' model `ES-1200C' interface `parallel' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `overseas version of the GT-9000' model `ES-2000' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x0107' status complete url *none* comment `IEEE1394 untested' model `ES-2200' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x010e' status complete url *none* comment `IEEE1394 untested' model `ES-6000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ES-6000H' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `IEEE1394 untested' model `ES-6000HS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `IEEE1394 untested' model `ES-7000H' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x0126' status good url *none* comment `network interface unsupported
IEEE1394 untested' model `ES-8000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ES-8500' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x0109' status good url *none* comment `IEEE1394 untested' model `ES-9000H' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `IEEE1394 untested' model `ES-10000G' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0129' status good url *none* comment `network interface unsupported
IEEE1394 untested' model `ES-D400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0136' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `ES-H300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012b' status good url *none* comment `network interface probably supported' model `ES-H7200' interface `USB Ethernet' usb-vendor-id `0x04b8' usb-product-id `0x0138' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Expression 636' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `overseas version of the GT-9500' model `Expression 800' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `overseas version of the GT-9600' model `Expression 836XL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `overseas version of the ES-8000' model `Expression 1600' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x0107' status complete url *none* comment `IEEE1394 untested
overseas version of the ES-2000' model `Expression 1640XL' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x0109' status good url *none* comment `IEEE1394 untested
overseas version of the ES-8500' model `Expression 1680' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x010e' status complete url *none* comment `IEEE1394 untested
overseas version of the ES-2200' model `Expression 1680 Pro' interface `SCSI USB' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `IEEE1394 option' model `Expression 1680XL Pro' interface `SCSI USB' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `Expression 10000XL' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0129' status good url *none* comment `network interface probably supported
IEEE1394 untested
overseas version of the ES-10000G' model `Expression 10000XL Graphic Arts' interface `USB IEEE1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `network interface probably supported' model `Expression 10000XL Photo' interface `USB IEEE1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `network interface probably supported' model `F-3200' interface `USB IEEE1394' usb-vendor-id `0x04b8' usb-product-id `0x080a' status unsupported url *none* comment `Film scanner' model `F-3200 Photo' interface `USB IEEE1394' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment *none* model `FilmScan 200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `will be supported' model `GT-1500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0133' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-2200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0102' status unsupported url *none* comment *none* model `GT-2500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012b' status good url *none* comment `network interface probably supported
overseas version of the ES-H300' model `GT-4000' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `GT-5000' interface `parallel SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-5400' interface `parallel' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-5500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-6000' interface `SCSI Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-6500' interface `parallel' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `overseas version of the GT-5400' model `GT-6600U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0103' status complete url *none* comment *none* model `GT-6700U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010c' status complete url *none* comment *none* model `GT-7000S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `GT-7000U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0101' status complete url *none* comment *none* model `GT-7200U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010f' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-7300U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011d' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-7400U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0120' status unsupported url *none* comment `supported by the snapscan backend' model `GT-7600S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `SCSI version of the GT-7600U' model `GT-7600U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0104' status complete url *none* comment `USB version of the GT-7600S' model `GT-7600UF' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0104' status complete url *none* comment `GT-7600U with TPU option bundled' model `GT-7700U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010b' status complete url *none* comment *none* model `GT-8000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-8200U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0110' status complete url *none* comment *none* model `GT-8200UF' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0110' status good url *none* comment *none* model `GT-8300UF' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011e' status complete url *none* comment *none* model `GT-8400UF' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011f' status unsupported url *none* comment *none* model `GT-8500' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `GT-8700' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x010a' status complete url *none* comment *none* model `GT-8700F' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x010a' status good url *none* comment `GT-8700U with TPU option bundled' model `GT-9000' interface `parallel' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `GT-9300UF' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011b' status complete url *none* comment *none* model `GT-9400UF' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0116' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-9500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `GT-9600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `GT-9700F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0112' status complete url *none* comment `IEEE1394 untested' model `GT-9800F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011c' status complete url *none* comment `IEEE1394 untested' model `GT-10000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `overseas version of the ES-6000' model `GT-10000+' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `IEEE1394 untested
overseas version of the ES-6000H' model `GT-12000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `overseas version of the ES-8000' model `GT-15000' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x0126' status good url *none* comment `IEEE1394 untested
overseas version of the ES-7000H' model `GT-20000' interface `USB Ethernet' usb-vendor-id `0x04b8' usb-product-id `0x0138' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `GT-30000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `IEEE1394 untested
overseas version of the ES-9000H' model `GT-D1000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0133' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0121' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F520' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0122' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F550' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0121' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F570' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0122' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0118' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F650' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012d' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F670' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012e' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012f' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-F720' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0131' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-S50' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0137' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-S80' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0136' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-S600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012d' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-S620' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0131' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-X700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0128' status complete url *none* comment `IEEE1394 untested' model `GT-X750' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0119' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-X770' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0130' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-X800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012a' status complete url *none* comment `film area guide mode not supported
IEEE1394 untested' model `GT-X820' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x013a' status unsupported url `http://www.avasys.jp/lx-bin2/linux/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `GT-X900' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012c' status good url *none* comment `IEEE1394 untested' model `GT-X970' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0135' status good url *none* comment `IEEE1394 untested' model `LP-7900CS' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-7000H' model `LP-9000CCH' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-9000H' model `LP-9000CCS' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-7000H' model `LP-9000CFH' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-9000H' model `LP-9500CCS' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-7000H' model `LP-9500CFH' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-9000H' model `LP-9500CH2' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-9000H' model `LP-9800CCH' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-9000H' model `LP-9800CCS' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-7000H' model `LP-9800CFH' interface *none* usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `business all-in-one; scanner is a ES-9000H' model `LP-A500' interface `USB Network' usb-vendor-id `0x04b8' usb-product-id `0x0815' status good url *none* comment `network interface supported
business all-in-one' model `LP-M5000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0843' status good url *none* comment `network interface probably supported
business all-in-one' model `LP-M5500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0817' status good url *none* comment `network interface probably supported
business all-in-one' model `LP-M5500F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0817' status good url *none* comment `network interface probably supported
business all-in-one
LP-M5500 with the fax option bundled' model `LP-M5600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0833' status good url *none* comment `network interface probably supported
business all-in-one' model `LP-M6000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0834' status good url *none* comment `network interface probably supported
business all-in-one' model `ME 200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0830' status good url *none* comment `all-in-one' model `ME 300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0841' status good url *none* comment `all-in-one
overseas version of the PX-401A' model `ME OFFICE 510' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084f' status good url *none* comment `all-in-one' model `ME Office 600F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0848' status good url *none* comment `all-in-one' model `ME OFFICE 650FN Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0854' status good url *none* comment `all-in-one' model `ME Office 700FW' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0847' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the PX-601F' model `PM-A700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0814' status good url *none* comment `all-in-one' model `PM-A750' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081a' status good url *none* comment `all-in-one' model `PM-A820' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0827' status good url *none* comment `all-in-one' model `PM-A840' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083c' status good url *none* comment `all-in-one' model `PM-A840S' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083c' status good url *none* comment `network interface probably supported
all-in-one' model `PM-A850' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0806' status good url *none* comment `all-in-one' model `PM-A870' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0811' status good url *none* comment `all-in-one' model `PM-A890' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081c' status good url *none* comment `all-in-one' model `PM-A900' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0810' status good url *none* comment `all-in-one' model `PM-A920' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082a' status good url *none* comment `all-in-one' model `PM-A940' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0837' status good url *none* comment `all-in-one' model `PM-A950' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081d' status good url *none* comment `all-in-one' model `PM-A970' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0828' status good url *none* comment `all-in-one' model `PM-T960' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0836' status good url *none* comment `all-in-one' model `PM-T990' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0829' status good url *none* comment `all-in-one
PM-A970 with network interface' model `PX-401A' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0841' status good url *none* comment `all-in-one' model `PX-402A' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084d' status good url *none* comment `all-in-one' model `PX-501A' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084a' status good url *none* comment `network interface probably supported
all-in-one' model `PX-502A' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0856' status good url *none* comment `all-in-one' model `PX-601F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0847' status good url *none* comment `network interface probably supported' model `PX-A550' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080e' status good url *none* comment `all-in-one' model `PX-A620' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082f' status good url *none* comment `all-in-one' model `PX-A640' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0838' status good url *none* comment `all-in-one' model `PX-A650' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0819' status good url *none* comment `all-in-one' model `PX-A720' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082e' status good url *none* comment `all-in-one' model `PX-A740' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0839' status good url *none* comment `all-in-one' model `PX-FA700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083a' status good url *none* comment `all-in-one' model `Perfection 600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `supported by the umax backend
rebadged UMAX Astra 1200S' model `Perfection 610' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0103' status complete url *none* comment `overseas version of the GT-6600U' model `Perfection 636S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `overseas version of the GT-7000S' model `Perfection 636U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0101' status complete url *none* comment `overseas version of the GT-7000U' model `Perfection 640U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010c' status complete url *none* comment `overseas version of the GT-6700U' model `Perfection 660' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0114' status unsupported url *none* comment `supported by the snapscan backend' model `Perfection 1200S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `overseas version of the GT-7600S' model `Perfection 1200U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0104' status complete url *none* comment `overseas version of the GT-7600U' model `Perfection 1200U PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0104' status complete url *none* comment `Perfection 1200U with TPU option bundled
overseas version of the GT-7600UF' model `Perfection 1240U' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010b' status complete url *none* comment `overseas version of the GT-7700U' model `Perfection 1250' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010f' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 1250 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010f' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 1260' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011d' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 1260 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011d' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 1270' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0120' status unsupported url *none* comment `supported by the snapscan backend
overseas version of the GT-7400' model `Perfection 1600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment *none* model `Perfection 1640SU' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x010a' status complete url *none* comment `overseas version of the GT-8700' model `Perfection 1640SU PHOTO' interface `SCSI USB' usb-vendor-id `0x04b8' usb-product-id `0x010a' status good url *none* comment `overseas version of the GT-8700F' model `Perfection 1650' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0110' status complete url *none* comment `overseas version of the GT-8200U' model `Perfection 1650 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0110' status good url *none* comment `overseas version of the GT-8200UF' model `Perfection 1660 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011e' status complete url *none* comment `overseas version of the GT-8300UF' model `Perfection 1670' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011f' status unsupported url *none* comment `supported by the snapscan backend' model `Perfection 1670 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011f' status unsupported url *none* comment `supported by the snapscan backend
overseas version of the GT-8400UF' model `Perfection 2400 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011b' status complete url *none* comment `overseas version of the GT-9300UF' model `Perfection 2450 PHOTO' interface `USB IEEE-1394' usb-vendor-id `0x04b8' usb-product-id `0x0112' status complete url *none* comment `overseas version of the GT-9700F' model `Perfection 2480 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0121' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 2580 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0121' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 3170 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0116' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 3200 PHOTO' interface `USB IEEE-1394' usb-vendor-id `0x04b8' usb-product-id `0x011c' status complete url *none* comment `overseas version of the GT-9800F' model `Perfection 3490 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0122' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 3590 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0122' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 4180 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0118' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 4490 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0119' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection 4870 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0128' status complete url *none* comment `IEEE1394 untested
overseas version of the GT-X700' model `Perfection 4990 PHOTO' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012a' status good url *none* comment `film area guide mode not supported
IEEE1394 untested
overseas version of the GT-X800' model `Perfection 4990 Pro' interface `USB IEEE1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `seems to be a 4990 PHOTO with additional software' model `Perfection V10' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012d' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection V30' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0131' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection V100 Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012d' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection V200 Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012e' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection V300 Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0131' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection V350 Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012f' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection V500 Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0130' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection V600 Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x013a' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/scan/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Perfection V700 Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012c' status good url *none* comment `IEEE1394 untested
overseas version of the GT-X900' model `Perfection V750 Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x012c' status good url *none* comment `IEEE1394 untested
overseas version of the GT-X900' model `Stylus CX1500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080c' status unsupported url *none* comment `supported by the snapscan backend
all-in-one' model `Stylus CX2800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0830' status good url *none* comment `all-in-one' model `Stylus CX2900' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0830' status good url *none* comment `all-in-one' model `Stylus CX3100' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0802' status good url *none* comment `all-in-one
overseas version of the CC-570L' model `Stylus CX3200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0802' status good url *none* comment `all-in-one
overseas version of the CC-570L' model `Stylus CX3500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080e' status good url *none* comment `all-in-one
overseas version of the PX-A550' model `Stylus CX3600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080e' status good url *none* comment `all-in-one
overseas version of the PX-A550' model `Stylus CX3650' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080e' status good url *none* comment `all-in-one' model `Stylus CX3700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0818' status good url *none* comment `all-in-one' model `Stylus CX3800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0818' status good url *none* comment `all-in-one' model `Stylus CX3810' interface `USB' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `all-in-one' model `Stylus CX3900' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082f' status good url *none* comment `all-in-one
overseas version of the PX-A620' model `Stylus CX4100' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0820' status good url *none* comment `all-in-one' model `Stylus CX4200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0820' status good url *none* comment `all-in-one' model `Stylus CX4300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083f' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Stylus CX4400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083f' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Stylus CX4500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080d' status good url *none* comment `all-in-one' model `Stylus CX4600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080d' status good url *none* comment `all-in-one' model `Stylus CX4700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0819' status good url *none* comment `all-in-one
overseas version of the PX-A650' model `Stylus CX4800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0819' status good url *none* comment `all-in-one
overseas version of the PX-A650' model `Stylus CX4900' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082b' status good url *none* comment `all-in-one' model `Stylus CX5000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082b' status good url *none* comment `all-in-one' model `Stylus CX5100' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0801' status good url *none* comment `all-in-one
overseas version of the CC-600PX' model `Stylus CX5200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0801' status good url *none* comment `all-in-one
overseas version of the CC-600PX' model `Stylus CX5300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0808' status good url *none* comment `all-in-one' model `Stylus CX5400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0808' status good url *none* comment `all-in-one' model `Stylus CX5500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083f' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Stylus CX5600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083f' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Stylus CX5700F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0821' status unsupported url *none* comment `may work with the snapscan backend
all-in-one with FAX' model `Stylus CX5800F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0821' status unsupported url *none* comment `may work with the snapscan backend
all-in-one with FAX' model `Stylus CX5900' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082e' status good url *none* comment `all-in-one
overseas version of the PX-A720' model `Stylus CX6000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082e' status good url *none* comment `all-in-one
overseas version of the PX-A720' model `Stylus CX6300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0805' status good url *none* comment `all-in-one
mistakenly thinks its a PX-A650' model `Stylus CX6400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0805' status good url *none* comment `all-in-one
mistakenly thinks its a PX-A650' model `Stylus CX6500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0813' status good url *none* comment `all-in-one' model `Stylus CX6600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0813' status good url *none* comment `all-in-one' model `Stylus CX6900F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0831' status unsupported url *none* comment `may work with the snapscan backend
all-in-one with FAX' model `Stylus CX7000F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0831' status unsupported url *none* comment `may work with the snapscan backend
all-in-one with FAX' model `Stylus CX7300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0838' status good url *none* comment `all-in-one
overseas version of the PX-A640' model `Stylus CX7400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0838' status good url *none* comment `all-in-one
overseas version of the PX-A640' model `Stylus CX7700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081f' status good url *none* comment `all-in-one' model `Stylus CX7800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081f' status good url *none* comment `all-in-one' model `Stylus CX8300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0839' status good url *none* comment `all-in-one
overseas version of the PX-A740' model `Stylus CX8400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0839' status good url *none* comment `all-in-one
overseas version of the PX-A740' model `Stylus CX9300F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083a' status good url *none* comment `all-in-one
overseas version of the PX-FA700' model `Stylus CX9400Fax' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083a' status good url *none* comment `all-in-one
overseas version of the PX-FA700' model `Stylus DX3800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0818' status good url *none* comment `all-in-one' model `Stylus DX3850' interface `USB' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `all-in-one' model `Stylus DX4000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082f' status good url *none* comment `all-in-one
overseas version of the PX-A620' model `Stylus DX4200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0820' status good url *none* comment `all-in-one' model `Stylus DX4400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083f' status unsupported url `http://www.avasys.jp/lx-bin2/linux_e/spc/DL1.do' comment `supported by the epkowa backend plus non-free interpreter' model `Stylus DX4800' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0819' status good url *none* comment `all-in-one
overseas version of the PX-A650' model `Stylus DX4850' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0819' status good url *none* comment `all-in-one
DX4800 + card reader' model `Stylus DX5000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082b' status good url *none* comment `all-in-one' model `Stylus DX6000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x082e' status good url *none* comment `all-in-one
overseas version of the PX-A720' model `Stylus DX7000F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0831' status unsupported url *none* comment `may work with the snapscan backend
all-in-one with FAX' model `Stylus DX7400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0838' status good url *none* comment `all-in-one
overseas version of the PX-A640' model `Stylus DX8400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0839' status good url *none* comment `all-in-one
overseas version of the PX-A740' model `Stylus DX9400F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083a' status good url *none* comment `all-in-one
overseas version of the PX-FA700' model `Stylus Office BX300F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0848' status good url *none* comment `all-in-one' model `Stylus Office BX310FN Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0854' status good url *none* comment `all-in-one' model `Stylus Office BX600FW' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0847' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the PX-601F' model `Stylus Office BX610FW Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0855' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Stylus Office TX300F' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0848' status good url *none* comment `all-in-one' model `Stylus Office TX510FN Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0854' status good url *none* comment `all-in-one' model `Stylus Office TX600FW' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0847' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the PX-601F' model `Stylus Office TX610FW Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0855' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Stylus Photo PX650 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0850' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Stylus Photo PX700W' interface `USB Network' usb-vendor-id `0x04b8' usb-product-id `0x0846' status good url *none* comment `network interface supported
all-in-one
overseas version of the EP-801A' model `Stylus Photo PX710W Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0852' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Stylus Photo PX800FW' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0844' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the EP-901A' model `Stylus Photo PX810FW Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0853' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Stylus Photo RX420' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080f' status good url *none* comment `all-in-one' model `Stylus Photo RX425' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080f' status good url *none* comment `all-in-one' model `Stylus Photo RX430' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080f' status good url *none* comment `all-in-one' model `Stylus Photo RX500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0807' status good url *none* comment `all-in-one' model `Stylus Photo RX510' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0807' status good url *none* comment `all-in-one' model `Stylus Photo RX520' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081a' status good url *none* comment `all-in-one
overseas version of the PM-A750' model `Stylus Photo RX530' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081a' status good url *none* comment `all-in-one
overseas version of the PM-A750' model `Stylus Photo RX560' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0827' status good url *none* comment `all-in-one
overseas version of the PM-A820' model `Stylus Photo RX585' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083c' status good url *none* comment `all-in-one
overseas version of the PM-A840' model `Stylus Photo RX580' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0827' status good url *none* comment `all-in-one
overseas version of the PM-A820' model `Stylus Photo RX595' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083c' status good url *none* comment `all-in-one
overseas version of the PM-A840' model `Stylus Photo RX590' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0827' status good url *none* comment `all-in-one
overseas version of the PM-A820' model `Stylus Photo RX600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0806' status good url *none* comment `all-in-one
overseas version of the PM-A850' model `Stylus Photo RX610' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083c' status good url *none* comment `all-in-one
overseas version of the PM-A840' model `Stylus Photo RX620' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0811' status good url *none* comment `all-in-one
overseas version of the PM-A870' model `Stylus Photo RX630' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0811' status good url *none* comment `all-in-one
overseas version of the PM-A870' model `Stylus Photo RX640' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081c' status good url *none* comment `all-in-one
overseas version of the PM-A890' model `Stylus Photo RX650' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x081c' status good url *none* comment `all-in-one
overseas version of the PM-A890' model `Stylus Photo RX680' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0837' status good url *none* comment `all-in-one
overseas version of the PM-A940' model `Stylus Photo RX685' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0837' status good url *none* comment `all-in-one
overseas version of the PM-A940' model `Stylus Photo RX690' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0837' status good url *none* comment `all-in-one
overseas version of the PM-A940' model `Stylus Photo RX700' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0810' status good url *none* comment `all-in-one
overseas version of the PM-A900' model `Stylus Photo TX650 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0850' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Stylus Photo TX700W' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0846' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the EP-801A' model `Stylus Photo TX710W Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0852' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Stylus Photo TX800FW' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0844' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the EP-901A' model `Stylus NX100' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0841' status good url *none* comment `all-in-one
overseas version of the PX-401A' model `Stylus NX110 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084d' status good url *none* comment `all-in-one
overseas version of the PX-402A' model `Stylus NX200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0849' status good url *none* comment `all-in-one' model `Stylus NX210 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084f' status good url *none* comment `all-in-one' model `Stylus NX300' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0848' status good url *none* comment `all-in-one' model `Stylus NX400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084a' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the PX-501A' model `Stylus NX410 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0851' status good url *none* comment `network interface probably supported
all-in-one' model `Stylus NX510 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0856' status good url *none* comment `all-in-one
overseas version of the PX-502A' model `Stylus SX100' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0841' status good url *none* comment `all-in-one
overseas version of the PX-401A' model `Stylus SX110 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084d' status good url *none* comment `all-in-one
overseas version of the PX-402A' model `Stylus SX125' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x085c' status untested url *none* comment `all-in-one' model `Stylus SX200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0849' status good url *none* comment `all-in-one' model `Stylus SX205' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0849' status good url *none* comment `all-in-one' model `Stylus SX210 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084f' status good url *none* comment `all-in-one' model `Stylus SX400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084a' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the PX-501A' model `Stylus SX405' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084a' status good url *none* comment `all-in-one' model `Stylus SX410 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0851' status good url *none* comment `network interface probably supported
all-in-one' model `Stylus SX510W Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0856' status good url *none* comment `all-in-one
overseas version of the PX-502A' model `Stylus SX600FW' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0847' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the PX-601F' model `Stylus SX610FW Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0855' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' model `Stylus Scan 2000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0105' status untested url *none* comment `apparently mostly the same as the Stylus Scan 2500' model `Stylus Scan 2500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0106' status untested url *none* comment `scanner is apparently a GT-7000' model `Stylus TX100' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0841' status good url *none* comment `all-in-one
overseas version of the PX-401A' model `Stylus TX110 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084d' status good url *none* comment `all-in-one
overseas version of the PX-402A' model `Stylus TX200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0849' status good url *none* comment `all-in-one' model `Stylus TX203' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0849' status good url *none* comment `all-in-one' model `Stylus TX209' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0849' status good url *none* comment `all-in-one' model `Stylus TX210 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084f' status good url *none* comment `all-in-one' model `Stylus TX400' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084a' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the PX-501A' model `Stylus TX410 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0851' status good url *none* comment `network interface probably supported
all-in-one' model `Stylus TX550W Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0856' status good url *none* comment `all-in-one
overseas version of the PX-502A' model `WorkForce 310 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0854' status good url *none* comment `all-in-one' model `WorkForce 500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x084c' status good url *none* comment `all-in-one' model `WorkForce 600' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0847' status good url *none* comment `network interface probably supported
all-in-one
overseas version of the PX-601F' model `WorkForce 610 Series' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0855' status unsupported url *none* comment `supported by the epkowa backend plus non-free interpreter' backend `fujitsu' version `117' manpage `sane-fujitsu' url `http://www.thebility.com/fujitsu/' comment `Backend updated for SANE release 1.0.23, see sane-fujitsu manpage' type scanner mfg `Fujitsu' url `http://www.fujitsu.com/' comment *none* model `M3091DC' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url `http://www.remote.org/frederik/projects/software/sane/' comment `small, old, discontinued' model `M3092DC' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `small, old, discontinued' model `fi-4120C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1041' status complete url *none* comment `small, recent, discontinued, usb 1.1' model `fi-4120C2' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x10ae' status complete url *none* comment `small, recent, discontinued, usb 2.0' model `fi-4220C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1042' status complete url *none* comment `small, recent, discontinued, usb 1.1' model `fi-4220C2' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x10af' status complete url *none* comment `small, recent, discontinued, usb 2.0' model `fi-5110C' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1097' status complete url *none* comment `small, recent, discontinued' model `fi-5110EOX/2' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1096' status complete url *none* comment `small, recent, discontinued' model `fi-5110EOX3' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x10e6' status complete url *none* comment `small, recent, discontinued' model `fi-5110EOXM' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x10f2' status complete url *none* comment `small, recent, discontinued' model `fi-5120C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x10e0' status complete url *none* comment `small, recent, discontinued' model `fi-5220C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x10e1' status complete url *none* comment `small, recent, discontinued' model `fi-5000N' interface `Ethernet' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Not a scanner, rather a scanner to ethernet interface' model `fi-6000NS' interface `Ethernet' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `small, recent, discontinued, integrated touchscreen and keyboard' model `ScanSnap S500' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x10fe' status complete url *none* comment `small, recent, discontinued' model `ScanSnap S500M' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1135' status complete url *none* comment `small, recent, discontinued' model `ScanSnap S510' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1155' status complete url *none* comment `small, recent, discontinued' model `ScanSnap S510M' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x116f' status complete url *none* comment `small, recent, discontinued' model `fi-6130' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x114f' status complete url *none* comment `small, recent, discontinued' model `fi-6230' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1150' status complete url *none* comment `small, recent, discontinued' model `ScanSnap S1500' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x11a2' status complete url *none* comment `small, discontinued' model `ScanSnap S1500M' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x11a2' status complete url *none* comment `small, discontinued, same as S1500' model `ScanSnap N1800' interface `Ethernet' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `small, current, integrated touchscreen and keyboard' model `ScanSnap fi-6010N' interface `Ethernet' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `small, current, integrated touchscreen and keyboard' model `fi-6110' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x11fc' status complete url *none* comment `small, current' model `fi-6130Z' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x11f3' status complete url *none* comment `small, current' model `fi-6230Z' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x11f4' status complete url *none* comment `small, current' model `ScanSnap iX500' interface `USB WiFi' usb-vendor-id `0x04c5' usb-product-id `0x132b' status good url *none* comment `small, current, WiFi not supported. Hardware only scans in color. Backend generates binary and grayscale modes.' model `M3093E' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `medium, old, discontinued' model `M3093DE' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `medium, old, discontinued' model `M3093DG' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `medium, old, discontinued' model `M3093EX' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `medium, old, discontinued' model `M3093GX' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `medium, old, discontinued' model `M3096EX' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `medium, old, discontinued' model `M3096GX' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `medium, old, discontinued' model `M3097E+' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `medium, old, discontinued' model `M3097G+' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `medium, old, discontinued' model `M3097DE' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `medium, old, discontinued' model `M3097DG' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `medium, old, discontinued' model `fi-4340C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x10cf' status complete url *none* comment `medium, current' model `fi-4530C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1078' status complete url *none* comment `medium, recent, discontinued' model `fi-4640S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `medium, recent, discontinued' model `fi-4750C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `medium, recent, discontinued' model `fi-5530C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x10e2' status complete url *none* comment `medium, recent, discontinued' model `fi-6140' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x114d' status complete url *none* comment `medium, recent, discontinued' model `fi-6240' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x114e' status complete url *none* comment `medium, recent, discontinued' model `fi-5530C2' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x114a' status complete url *none* comment `medium, current' model `fi-6140Z' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x11f1' status complete url *none* comment `medium, current' model `fi-6240Z' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x11f2' status complete url *none* comment `medium, current' model `M3099A' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `big, old, discontinued' model `M3099G' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, old, discontinued' model `M3099EH' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `big, old, discontinued' model `M3099GH' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, old, discontinued' model `M3099EX' interface `RS232C/Video' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `big, old, discontinued' model `M3099GX' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, old, discontinued' model `M4097D' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, old, discontinued' model `M4099D' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, old, discontinued' model `fi-4750L' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, recent, discontinued' model `fi-4860C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, recent, discontinued' model `fi-4860C2' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, recent, discontinued' model `fi-4990C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `big, recent, discontinued' model `fi-5650C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x10ad' status complete url *none* comment `big, recent, discontinued' model `fi-5750C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1095' status complete url *none* comment `big, recent, discontinued' model `fi-5900C' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x10e7' status good url *none* comment `big, recent, discontinued. Independent ultrasonic control and multistream unsupported' model `fi-6750S' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1178' status untested url *none* comment `Simplex, USB only version of fi-6770, won't wakeup via software, discontinued' model `fi-5950' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1213' status untested url *none* comment `big, current. Faster version of fi-5900?' model `fi-6670' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1176' status good url *none* comment `big, current, won't wakeup via software' model `fi-6670A' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1177' status good url *none* comment `big, current, VRS CGA board unsupported, won't wakeup via software' model `fi-6770' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1174' status good url *none* comment `big, current, won't wakeup via software' model `fi-6770A' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x1175' status good url *none* comment `big, current, VRS CGA board unsupported, won't wakeup via software' model `fi-6800' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x119d' status untested url *none* comment `big, current. Independent ultrasonic control and multistream unsupported' model `fi-6800-CGA' interface `SCSI USB' usb-vendor-id `0x04c5' usb-product-id `0x119e' status untested url *none* comment `big, current. VRS CGA board unsupported, Independent ultrasonic control and multistream unsupported' backend `genesys' version `1.0-63' manpage `sane-genesys' url `http://www.meier-geinitz.de/sane/genesys-backend/' comment `Only the USB scanners mentioned below are currently supported.' type scanner mfg `Plustek' url `http://www.plustek.de/' url `http://www.plustek.com/' comment *none* model `OpticBook 3600' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0900' status basic url *none* comment `Has a Primax USB ID' mfg `Medion/Lifetec/Tevion/Cytron' url `http://www.medion.com/' url `http://www.medion.de/' comment *none* model `MD5345' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0377' status good url *none* comment `Has a Primax USB ID' model `MD6228' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0377' status good url *none* comment `Has a Primax USB ID. Same as MD5345' model `MD6471' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0377' status complete url *none* comment `Has a Primax USB ID. Same as MD5345' mfg `Hewlett-Packard' url `http://www.hp.com/' comment *none* model `ScanJet 2300C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0901' status complete url *none* comment `600x1200 dpi max' model `ScanJet 2400C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0a01' status complete url *none* comment `1200x1200 dpi max' model `ScanJet G2410' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0a01' status basic url *none* comment `clone of the HP 2400C' model `ScanJet 3670C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1405' status complete url *none* comment `1200x1200 dpi max, complete transparency adaptor support' model `ScanJet 3690C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1405' status complete url *none* comment `1200x1200 dpi max, same as HP 3670C' model `ScanJet 4850C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1b05' status untested url *none* comment `resolution from 100 to 2400 supported, UTA not supported yet' model `ScanJet G4010' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x4505' status good url *none* comment `resolution from 100 to 2400 supported, UTA not supported yet' model `ScanJet G4050' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x4605' status good url *none* comment `resolution from 100 to 2400 supported, UTA not supported yet' model `ScanJet N6310' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x4705' status untested url *none* comment `Not supported yet' mfg `Canon' url `http://www.canon.com/' comment *none* model `CanoScan LiDE 35' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2213' status good url *none* comment `Same ids as LiDE 50.' model `CanoScan LiDE 40' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2213' status good url *none* comment `Same ids as LiDE 50.' model `CanoScan LiDE 50' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2213' status good url *none* comment *none* model `CanoScan LiDE 60' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x221c' status good url *none* comment *none* model `CanoScan LiDE 100' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1904' status complete url *none* comment `GL847 based, resolution from 75 to 2400 dpi' model `CanoScan LiDE 110' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1909' status complete url *none* comment `GL124 based, resolution from 75 to 2400 dpi' model `CanoScan LiDE 200' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1905' status complete url *none* comment `GL847 based, resolution from 75 to 4800 dpi' model `CanoScan LiDE 210' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x190a' status complete url *none* comment `GL124 based, resolution from 75 to 2400 dpi' model `CanoScan 4400f' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2228' status unsupported url *none* comment `GL843 based, to be added to the genesys backend' model `CanoScan 5600F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1906' status unsupported url *none* comment `GL847 based, to be added to the genesys backend' model `CanoScan 700F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1907' status good url *none* comment `GL847 based, resolution from 75 to 4800 dpi' model `Canon Image Formula 101' interface `USB' usb-vendor-id `0x1083' usb-product-id `0x162e' status unsupported url *none* comment `GL846 based, work in progress' mfg `Visioneer' url `http://www.visioneer.com/' comment *none* model `Strobe XP 100,r3' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x049b' status good url *none* comment `All resolution and mode supported, calibration is available' model `Strobe XP 200' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0426' status good url *none* comment `All resolution and mode supported, calibration is available' model `Strobe XP 300' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0474' status good url *none* comment `All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally.' model `Roadwarrior' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0494' status basic url *none* comment `All resolution and mode supported, calibration is available' model `Visioneer OneTouch 7100' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0229' status complete url *none* comment `Same as MD5345' mfg `Pentax' url `http://www.pentaxtech.com/' url `http://mobilesolutions.brother-usa.com/' comment *none* model `DSmobile 600' interface `USB' usb-vendor-id `0x0a17' usb-product-id `0x3210' status good url *none* comment `All resolution and mode supported, calibration is available' model `DSmobile 600' interface `USB' usb-vendor-id `0x04f9' usb-product-id `0x2038' status good url *none* comment `All resolution and mode supported, calibration is available' mfg `DCT' url `http://www.docucap.com/' comment `Successor of Syscan in the USA' model `DocketPort 487' interface `USB' usb-vendor-id `0x1dcc' usb-product-id `0x4810' status basic url *none* comment `All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally.' mfg `Syscan' url *none* comment *none* model `DocketPort 485' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x4810' status basic url *none* comment `All resolution and mode supported, front- and backside side-by-side, with backside mirrored horizontally.' model `DocketPort 465' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x4802' status untested url *none* comment `All resolution and mode should be supported, but uncorrected scans' model `DocketPort 665' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x4803' status basic url *none* comment `All resolution and mode supported, calibration is available' model `DocketPort 685/ Ambir DS685' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x480c' status good url *none* comment `All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally.' mfg `Xerox' url `http://www.xerox.com/' comment *none* model `Travel Scanner 100' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x04ac' status good url *none* comment `All resolution and mode supported, calibration is available' model `2400 Onetouch' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x038b' status complete url *none* comment `GL646 based, resolution from 75 to 2400 dpi' mfg `Panasonic' url *none* comment *none* model `KV-SS080' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x100f' status complete url *none* comment `All resolution and mode supported, calibration is available. Support sponsored by cncsolutions (http://www.cncsolutions.com.br)' backend `gphoto2' version `0.0' manpage `sane-gphoto2' url `mailto:peter@fales-lorenz.net' comment *none* type api desc `Multiple cameras supported by the gphoto2 libraries' url `http://www.gphoto.org' comment `The long-term plan is to support all the cameras supported by the gphoto2 libraries (currently over 140 models). However, at this stage, only a handful of cameras are definitely known to work with SANE. Other cameras will probably work if the native file format is EXIF or JPEG. Testers welcome!' backend `gt68xx' version `1.0-84' manpage `sane-gt68xx' url `http://www.meier-geinitz.de/sane/gt68xx-backend/' comment `Only the USB scanners mentioned below are supported. For other Mustek BearPaws, look at the Plustek and the MA-1509 backend.' type scanner mfg `Artec/Ultima' url `http://www.artecusa.com/' comment *none* model `Ultima 2000' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Works, only product id 0x4002 is supported' model `Ultima 2000 e+' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Works, however 12 bit mode doesn't seem to be supported' mfg `Boeder' url *none* comment *none* model `Sm@rtScan Slim Edition' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Similar to Artec Ultima 2000' mfg `Fujitsu' url `http://www.fujitsu.com/' comment *none* model `1200CUS' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status basic url *none* comment `Works, but is slow. Probably a Mustek BearPaw 2400 CU clone.' mfg `Genius' url `http://www.genius-kye.com/' comment *none* model `ColorPage Slim 1200' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x201e' status untested url *none* comment `Untested but should work.' model `Colorpage SF600' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2021' status basic url *none* comment *none* model `Colorpage Vivid3x' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2011' status good url *none* comment *none* model `Colorpage Vivid3 V2' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2011' status good url *none* comment `Same as Colorpage Vivid3x' model `Colorpage Vivid3xe' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2017' status good url *none* comment *none* model `Colorpage Vivid4' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2014' status good url *none* comment *none* model `Colorpage Vivid4x' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x201b' status good url *none* comment *none* model `Colorpage Vivid4xe' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x201a' status good url *none* comment *none* model `Colorpage Vivid 1200 X' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x201d' status good url *none* comment *none* model `Colorpage Vivid 1200 XE' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x201f' status good url *none* comment *none* mfg `Googlegear' url *none* comment *none* model `2000' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Same as Artec Ultima 2000.' mfg `Lexmark' url `http://www.lexmark.com/' comment *none* model `X70' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x002d' status good url *none* comment `Works, some resolutions fail at 16 bit' model `X73' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x002d' status good url *none* comment `Works, some resolutions fail at 16 bit, same as X70' mfg `Medion/Lifetec/Tevion/Cytron' url `http://www.medion.com' comment `Sold by Aldi and Tchibo.' model `MD 4394' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Product id 0x4002. If you have 0x4003, use artec_eplus48u backend.' model `MD/LT 9375' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status untested url *none* comment `Untested, but is reported to have the same ids as the Artec Ultima 2000. Please test.' model `MD/LT 9385' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Similar to Artec Ultima 2000' model `LT 9452' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Similar to Mustek ScanExpress 1200 UB Plus' model `MD 9458' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Similar to Artec Ultima 2000 (e+?)' mfg `Mustek' url `http://www.mustek.com/' url `http://www.mustek.com.tw/' url `http://www.mustek.de/' comment *none* model `BearPaw 1200 CS' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021e' status good url *none* comment *none* model `BearPaw 1200 CU' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment *none* model `BearPaw 1200 CU Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021b' status good url *none* comment *none* model `BearPaw 1200 CU Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021c' status good url *none* comment *none* model `BearPaw 1200 TA' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021e' status good url *none* comment `Transparency adapter supported' model `BearPaw 1248 CU' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021c' status good url *none* comment `Seems to use the same ids as BearPaw 1200 CU Plus.' model `BearPaw 2400 CS' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0218' status untested url *none* comment `Probably works, reports are welcome' model `BearPaw 2400 CS Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0219' status good url *none* comment `Works, problems with 12/16 bit modes?' model `BearPaw 2400 CU' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status basic url *none* comment `Works, but is slow' model `BearPaw 2400 CU Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021d' status good url *none* comment *none* model `BearPaw 2400 TA' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0218' status good url *none* comment `Transparency adapter supported' model `BearPaw 2400 TA Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0219' status good url *none* comment `Transparency adapter supported' model `BearPaw 2448 CS Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021a' status basic url *none* comment `Slow. Same as 2448 TA Plus, but without TA.' model `BearPaw 2448 TA Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021a' status basic url *none* comment `Slow. Transparency adapter supported. Slow. Brightness depends on resolution?' model `Plug-n-Scan 2400 MT' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0219' status good url *none* comment `Works but is slow in high resolutions. Same as BearPaw 2400 TA Plus.' model `Plug-n-Scan 2400 M' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0219' status good url *none* comment `Works but is slow in high resolutions. Same as BearPaw 2400 CS Plus.' model `ScanExpress 1200 UB Plus' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment *none* model `ScanExpress 1248 UB' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021f' status complete url *none* comment *none* model `ScanExpress 2400 USB' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status minimal url *none* comment `Should be detected but may need some more work in the code. Testers welcome. Please contact me if you own this scanner.' model `ScanExpress A3 USB' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0210' status basic url *none* comment `Still some vertical stripes.' model `ScanMagic 1200 UB Plus' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Same as ScanExpress 1200 UB Plus' mfg `NeatReceipts' url *none* comment *none* model `Scanalizer Professional 2.5' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0412' status untested url *none* comment `Similar to Plustek OpticSlim M12. Please tell us if this scanner works.' model `Mobile Scanner' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0462' status basic url *none* comment `Similar to Plustek OpticSlim M12.' mfg `Nortek' url *none* comment *none* model `MyScan 1200' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x040b' status untested url *none* comment `Untested. Please test. Similar to Plustek OpticPro S12?' mfg `Packard Bell' url *none* comment *none* model `Diamond 1200' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Similar to Mustek BearPaw 1200 (Plus)' model `Diamond 1200 Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021c' status good url *none* comment `Similar to Mustek BearPaw 1200 Plus' model `Diamond 1200 Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021b' status good url *none* comment `Similar to Mustek BearPaw 1200 Plus' model `Diamond 2450' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0219' status good url *none* comment *none* mfg `Plustek' url `http://www.plustek.de/' url `http://www.plustek.com/' comment *none* model `OpticPro 1248U' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0400' status good url *none* comment *none* model `OpticPro 1248U' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0401' status good url *none* comment *none* model `OpticPro U16B' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0402' status good url *none* comment *none* model `OpticPro U16B+' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0403' status good url *none* comment *none* model `OpticPro UT16B' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0403' status untested url *none* comment `Probably works. Transparency adapter not supported yet. Please contact me if you own such a device. ' model `OpticPro S12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x040b' status good url *none* comment `Product ID 0x040b only.' model `OpticPro S24' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x040e' status good url *none* comment `Product ID 0x040e only. Is reported to work.' model `OpticPro ST12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x040b' status untested url *none* comment `Product ID 0x040b only. Needs testing. Transparency adapter completely untested. Please contact me if you own such a scanner.' model `OpticSlim 1200' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0413' status good url *none* comment *none* model `OpticSlim 2400' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0422' status good url *none* comment `Works up to 1200 dpi.' model `OpticSlim 2400 plus' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0454' status good url *none* comment `Same as OpticSlim 2400.' model `Iriscan Express 2' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x045f' status complete url *none* comment `Works up to 1200 dpi. Calibration with external calibration sheet supported' model `OpticSlim M12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0412' status complete url *none* comment `Works up to 1200 dpi. Calibration with external calibration sheet supported' mfg `RevScan' url *none* comment *none* model `19200i' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0400' status good url *none* comment `Similar to Plustek OpticPro 1248U' mfg `Trust' url `http://www.trust-site.com' comment *none* model `240TH Easy Webscan Gold' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0218' status good url *none* comment `Same as Mustek Bearpaw 2400 TA plus.' model `Compact Scan USB 19200' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Works, if you have vendor id 0x055f and product id 0x0006, use the mustek_usb backend instead, similar to Mustek ScanExpress 1200 UB (Plus)' model `Direct WebScan 19200' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x021c' status good url *none* comment `Same as Mustek BearPaw 1200 CU Plus (0x021c).' model `Flat Scan USB 19200' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4002' status good url *none* comment `Similar to Artec Ultima 2000' mfg `Visioneer' url `http://www.visioneer.com/' comment *none* model `OneTouch 7300' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0444' status good url *none* comment `Works upto 1200 dpi and 12 bits/color.' backend `hp' version `1.06' manpage `sane-hp' url `http://www.kirchgessner.net/' comment *none* type scanner mfg `Hewlett-Packard' url `http://www.hp.com/' comment *none* model `ScanJet Plus' interface `Propietary' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Driver for HP parallel interface card required' model `ScanJet IIc' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet IIp' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet IIcx' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet 3c' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet 3p' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet 4c' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet 4p' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet 4100C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0101' status complete url *none* comment *none* model `ScanJet 5p' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet 5100C' interface `Parport' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Requires ppscsi driver and epst module' model `ScanJet 5200C' interface `Parport USB' usb-vendor-id `0x03f0' usb-product-id `0x0401' status complete url *none* comment `Parallel interface requires ppscsi driver and epst module' model `ScanJet 6100C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanJet 6200C' interface `SCSI USB' usb-vendor-id `0x03f0' usb-product-id `0x0201' status complete url *none* comment *none* model `ScanJet 6250C' interface `SCSI USB' usb-vendor-id `0x03f0' usb-product-id `0x0201' status complete url *none* comment *none* model `ScanJet 6300C' interface `SCSI USB' usb-vendor-id `0x03f0' usb-product-id `0x0601' status complete url *none* comment *none* model `ScanJet 6350C' interface `SCSI USB' usb-vendor-id `0x03f0' usb-product-id `0x0601' status complete url *none* comment *none* model `ScanJet 6390C' interface `SCSI USB' usb-vendor-id `0x03f0' usb-product-id `0x0601' status complete url *none* comment *none* model `PhotoSmart PhotoScanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* backend `hp3500' version `1.1' manpage `sane-hp3500' url `http://projects.troy.rollo.name/rt-scanners/' comment `HP3500 series scanners.' type scanner mfg `Hewlett-Packard' url `http://www.hp.com' comment *none* model `ScanJet 3500C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x2205' status good url *none* comment *none* model `ScanJet 3530C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x2005' status good url *none* comment *none* model `ScanJet 3570C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x2005' status good url *none* comment *none* backend `hp3900' version `0.12' manpage `sane-hp3900' url `http://sourceforge.net/projects/hp3900-series/' comment `Still Beta' type scanner mfg `Hewlett-Packard' url `http://www.hp.com' comment *none* model `ScanJet 3800' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x2605' status basic url *none* comment `Works with resolutions equal and less than 600dpi' model `ScanJet 3970c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x2305' status good url *none* comment *none* model `ScanJet 4070 Photosmart' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x2405' status good url *none* comment *none* model `ScanJet 4370' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x4105' status basic url *none* comment `Works with resolutions lower than 1200dpi' model `ScanJet G2710' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x2805' status basic url *none* comment `Similar to hp scanjet 3800' model `ScanJet G3010' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x4205' status basic url *none* comment `Similar to hp scanjet 4370' model `ScanJet G3110' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x4305' status basic url *none* comment `Similar to hp scanjet 4370' mfg `UMAX' url `http://www.umax.com' comment *none* model `Astra 4900' interface `USB' usb-vendor-id `0x06dc' usb-product-id `0x0020' status minimal url *none* comment `developing yet' mfg `BenQ' url `http://www.benq.com/' comment *none* model `5550' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2211' status minimal url *none* comment `developing yet' backend `hp4200' version `1.0-2' manpage `sane-hp4200' url `http://hp4200-backend.sourceforge.net' comment *none* type scanner mfg `Hewlett-Packard' url `http://www.hp.com/' comment *none* model `ScanJet 4200C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0105' status basic url *none* comment `8bpp color, 75/150/300/600 dpi only' model `ScanJet 4200Cxi' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0105' status basic url *none* comment `8bpp color, 75/150/300/600 dpi only' model `ScanJet 4200Cse' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0105' status basic url *none* comment `8bpp color, 75/150/300/600 dpi only' backend `hp5400' version `1.0-2' manpage `sane-hp5400' url `http://sourceforge.net/projects/hp5400backend' comment `HP5400 and HP5470 scanners. Prototype backend available' type scanner mfg `Hewlett-Packard' url `http://www.hp.com' comment *none* model `ScanJet 5400c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1005' status basic url *none* comment *none* model `ScanJet 5470c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1105' status basic url *none* comment *none* model `ScanJet 5490c' interface `USB' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* backend `hp5590' version `1.0.5' manpage `sane-hp5590' url *none* comment *none* type scanner mfg `Hewlett-Packard' url `http://www.hp.com' comment *none* model `ScanJet 4500C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1205' status complete url *none* comment `Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives' model `ScanJet 4570C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1305' status complete url *none* comment `Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives' model `ScanJet 5500C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1305' status untested url *none* comment `Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives' model `ScanJet 5550C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1205' status complete url *none* comment `Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives' model `ScanJet 5590' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1705' status complete url *none* comment `Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives' model `ScanJet 7650' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1805' status complete url *none* comment `Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives' backend `hpljm1005' version `0' manpage `sane-hpljm1005' url *none* comment *none* type scanner mfg `Hewlett-Packard' url `http://www.hp.com' comment *none* model `LaserJet M1005 MFP' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x3b17' status good url *none* comment `grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI' model `LaserJet M1120 MFP' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x5617' status good url *none* comment `grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI' model `LaserJet M1120n MFP' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x5717' status good url *none* comment `grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI' backend `hpsj5s' version `0.03' manpage `sane-hpsj5s' url `http://hpsj5s.sourceforge.net/' comment *none* type scanner mfg `Hewlett-Packard' url `http://www.hp.com/' comment *none* model `ScanJet 5s' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `Requires libieee1284 library. Only gray mode.' backend `hs2p' version `1.00' manpage `sane-hs2p' url `http://www.acjlaw.net:8080/~jeremy/Ricoh/' comment `This backend has been tested with the IS450DE (Duplex/Endorser). All major functions necessary for scanning are supported. This backend should work with all Ricoh scanners in the IS450 family as well as the IS420 series, but the IS420 has not yet been tested. Features provided by the optional Image Processing Unit (IPU) are not yet integrated into the backend, as my scanner lacks the IPU.' type scanner mfg `Ricoh' url `http://www.ricoh.com/' comment *none* model `IS450' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `All major scanning-related features are supported (except for IPU). Certain non-scanning features, such as those related to scanner maintenance, are not supported. Such features would be better implemented in a separate stand-alone tool. For instance, if you replace the ADF Unit, you must recalibrate the scanner optics using a Ricoh Test Sheet and reset the E^2PROM registers. Reports are welcome.' model `IS-410' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Untested, please report!' model `IS-420' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Untested, please report!' model `IS-430' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Untested, please report!' backend `ibm' version `1.0-4' manpage `sane-ibm' url `http://www.meier-geinitz.de/sane/ibm-backend/' comment `This backend has had only limited testing. It needs more work especially for the Ricoh scanners. Patches are welcome.' type scanner mfg `IBM' url `http://www.ibm.com/' comment *none* model `2456' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Was reported to work long time ago. Reports are welcome.' mfg `Ricoh' url *none* comment *none* model `IS-410' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Untested, please report!' model `IS-420' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Works at least in flatbed mode.' model `IS-430' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Untested, please report!' backend `kodak' version `7' manpage `sane-kodak' url `http://www.thebility.com/kodak/' comment `New backend for SANE release 1.0.21, see sane-kodak manpage' type scanner mfg `Kodak' url `http://www.kodak.com/' comment *none* model `Scanner 1500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 2500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 3500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 3510' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 3520' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Color Scanner 3590C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Color Scanner 4500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i150 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i160 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i250 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i260 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i280 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 900' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 923' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 5500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 7500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 7520' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 9500' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `Scanner 9520' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i610 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i620 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i640 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i660 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i730 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i750 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i780 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i810 Scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i820 Scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i830 Scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i840 Scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i1840 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' model `i1860 Scanner' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Uncompressed B&W, Gray and Color, some automatic features supported' model `s1740' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Please test!' backend `kodakaio' version `2.4.6' manpage `sane-kodakaio' url `http://sourceforge.net/projects/cupsdriverkodak/' comment `Backend for Kodak AiO ESP and Hero printers. Also possibly Advent AWL10' type scanner mfg `Kodak' url `http://www.kodak.com/' comment *none* model `ESP 2150' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4059' status untested url *none* comment `Please test!' model `ESP 2170' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4066' status untested url *none* comment `Please test!' model `ESP 3200' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4043' status untested url *none* comment `Please test!' model `ESP 3300' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4031' status untested url *none* comment `Please test!' model `ESP 4100' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4053' status untested url *none* comment `Please test!' model `ESP 5000' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4028' status untested url *none* comment `Please test!' model `ESP 5100' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4025' status untested url *none* comment `Please test!' model `ESP 5200' interface `USB Ethernet' usb-vendor-id `0x040a' usb-product-id `0x4041' status basic url *none* comment `USB good, Network good' model `ESP 5300' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4026' status untested url *none* comment `Please test!' model `ESP 5500' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4027' status untested url *none* comment `Please test!' model `ESP 6100' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4054' status untested url *none* comment `Please test!' model `ESP 7200' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4056' status untested url *none* comment `Please test!' model `ESP 9200' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4065' status untested url *none* comment `Please test!' model `ESP 5' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4032' status untested url *none* comment `Please test!' model `ESP 7' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x403e' status untested url *none* comment `Please test!' model `ESP 9' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x403f' status untested url *none* comment `Please test!' model `ESP C110' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4057' status untested url *none* comment `Please test!' model `ESP C115' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4058' status untested url *none* comment `Please test!' model `ESP C310' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x405d' status untested url *none* comment `Please test!' model `ESP C315' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x405e' status untested url *none* comment `Please test!' model `Hero 3.1' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x406d' status untested url *none* comment `Please test!' model `Hero 5.1' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4064' status untested url *none* comment `Please test!' model `Hero Office 6.1' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4062' status untested url *none* comment `Please test!' model `Hero 7.1' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4063' status untested url *none* comment `Please test!' model `Hero 9.1' interface `USB Ethernet' usb-vendor-id `0x040a' usb-product-id `0x4067' status basic url *none* comment `USB good, Network good' mfg `Advent' url `http://www.adventcomputers.co.uk' comment *none* model `AW10' interface `USB' usb-vendor-id `0x040a' usb-product-id `0x4060' status untested url *none* comment `Please test!' backend `kvs20xx' version `unmaintained' manpage `sane-kvs20xx' url *none* comment `New backend for SANE release 1.0.22, see sane-kvs20xx manpage' type scanner mfg `Panasonic' url `http://www.panasonic.com/' comment *none* model `KV-S2025C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `KV-S2026C' interface `USB SCSI' usb-vendor-id `0x04da' usb-product-id `0x1000' status untested url *none* comment *none* model `KV-S2028C' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x100a' status untested url *none* comment *none* model `KV-S2045C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `KV-S2046C' interface `USB SCSI' usb-vendor-id `0x04da' usb-product-id `0x1001' status untested url *none* comment *none* model `KV-S2048C' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x1009' status untested url *none* comment *none* backend `kvs40xx' version `unmaintained' manpage `sane-kvs40xx' url *none* comment `New backend for SANE release 1.0.23, see sane-kvs40xx manpage' type scanner mfg `Panasonic' url `http://www.panasonic.com/' comment *none* model `KV-S4065C' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x100d' status untested url *none* comment *none* model `KV-S4085C' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x100c' status untested url *none* comment *none* model `KV-S7075C' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x100e' status untested url *none* comment *none* backend `kvs1025' version `unmaintained' manpage `sane-kvs1025' url *none* comment `New backend for SANE release 1.0.21, see sane-kvs1025 manpage' type scanner mfg `Panasonic' url `http://www.panasonic.com/' comment *none* model `KV-S1020C' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x1007' status good url *none* comment *none* model `KV-S1025C' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x1006' status good url *none* comment *none* model `KV-S1045C' interface `USB' usb-vendor-id `0x04da' usb-product-id `0x1010' status good url *none* comment *none* backend `leo' version `1.0-10' manpage `sane-leo' url `http://www.zago.net/sane/#leo' comment *none* type scanner mfg `LEO' url *none* comment *none* model `LEOScan S3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `FCC ID LUZFS1130' mfg `Across Technologies' url *none* comment *none* model `FS-1130' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `FCC ID LUZFS1130' mfg `Genius' url *none* comment *none* model `FS-1130 Colorpage Scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* backend `lexmark' version `1.0-0' manpage `sane-lexmark' url `http://stef.dev.free.fr/sane/lexmark' comment `This backend supports lexmark x1100 series scanners.' type scanner mfg `Lexmark' url `http://www.lexmark.com/' comment *none* model `X1110' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007c' status untested url *none* comment *none* model `X1130' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007c' status good url *none* comment `Supports 75, 150, 300, 600 dpi' model `X1140' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007c' status untested url *none* comment *none* model `X1150' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007c' status good url *none* comment `Supports 75, 150, 300, 600 dpi' model `X1170' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007c' status good url *none* comment `Supports 75, 150, 300, 600 dpi' model `X1180' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007c' status good url *none* comment *none* model `X1185' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007c' status good url *none* comment `Tested with xscanimage. Supports 75, 150, 300, 600, 1200(600x1200) dpi resolutions. Does grayscale or colour scans in the following sizes: wallet, 3x5, 4x6, 5x7, 8x10, letter.' model `X1195' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007c' status untested url *none* comment *none* model `X74' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0060' status good url *none* comment `Supports 75, 150, 300, 600 dpi' model `X12xx' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007d' status good url *none* comment `USB1.1 is OK, USB2.0 needs testing' mfg `Dell' url *none* comment *none* model `A920' interface `USB' usb-vendor-id `0x413c' usb-product-id `0x5105' status good url *none* comment `Relabelled X11xx model' backend `ma1509' version `1.0-3' manpage `sane-ma1509' url `http://www.meier-geinitz.de/sane/ma1509-backend/' comment *none* type scanner mfg `Mustek' url `http://www.mustek.com/' url `http://www.mustek.com.tw/' url `http://www.mustek.de/' comment *none* model `BearPaw 1200 F' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0010' status good url *none* comment `Works upto 600 dpi. No support for TA and ADF yet.' mfg `Fujitsu' url `http://www.fujitsu.com/' comment *none* model `fi-4110EOX/2/3' interface `USB' usb-vendor-id `0x04c5' usb-product-id `0x1040' status unsupported url *none* comment `Uses ma1509 chip, but very different from other scanners supported by the ma1509 backend' backend `magicolor' version `1.0.0' manpage `sane-magicolor' url `http://wiki.kainhofer.com/hardware/magicolor_scan' comment *none* type scanner mfg `KONICA MINOLTA' url `http://www.konicaminolta.com/' comment *none* model `magicolor 1690MF' interface `USB Network' usb-vendor-id `0x132b' usb-product-id `0x2089' status good url `http://www.konicaminolta.eu/business-solutions/products/laser-printers/all-in-one/magicolor-1690mf/key-features.html' comment `Multi-function color laser printer with fax, scanner and network interface' model `BizHub 162/132' interface `USB Network' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov.' model `DiMage 1611' interface `USB Network' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov.' backend `matsushita' version `1.0-7' manpage `sane-matsushita' url `http://www.zago.net/sane' comment *none* type scanner mfg `Panasonic' url `http://www.panasonic.com/' comment *none* model `KV-SS25' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `KV-SS25D' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `KV-SS50' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `KV-SS55' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `KV-SS50EX' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `KV-SS55EX' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `no color, no high resolution, no automatic cropping' model `KV-SS850' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `KV-SS855' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `KV-S2025C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `no color, no high resolution, no automatic cropping' model `KV-S2045C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `no color, no high resolution, no automatic cropping' model `KV-S2065L' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `no color, no high resolution, no automatic cropping' backend `microtek' version `0.13.1' manpage `sane-microtek' url `http://www.mir.com/mtek/' comment *none* type scanner mfg `Microtek' url `http://www.microtek.com/' comment *none* model `Scanmaker E6' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Scanmaker E3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Scanmaker E2' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3-pass' model `Scanmaker 35t+' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `slide-scanner' model `Scanmaker 45t' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `slide-scanner' model `Scanmaker 35' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `slide-scanner' model `Scanmaker III' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Scanmaker IISP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Scanmaker IIHR' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3-pass' model `Scanmaker IIG' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `gray only' model `Scanmaker II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3-pass' model `Scanmaker 600Z(S)' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `Scanmaker 600G(S)' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `gray only (see manpage)' model `Color PageWiz' interface `SCSI (Parport)' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `sheet-fed (preliminary, see mapage)' mfg `Agfa' url `http://www.agfa.com/' comment *none* model `Arcus II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Arcus *II*, not Arcus!' model `StudioScan' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `StudioScan II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `StudioScan IIsi' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Studiostar' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `Is detected but scans are very dark' model `DuoScan' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* mfg `Vobis' url `http://www.vobis.de/' comment *none* model `Highscreen Realscan' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* mfg `Genius' url `http://www.genius-kye.com/' comment *none* model `Colorpage-SP2' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Same as Microtek Scanmaker E3' backend `microtek2' version `unmaintained' manpage `sane-microtek2' url `http://karstenfestag.gmxhome.de/linux.html' comment *none* type scanner mfg `Microtek' url `http://www.microtek.com/' comment *none* model `ScanMaker E3plus' interface `Parport' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanMaker E3plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanMaker X6' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanMaker X6EL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `ScanMaker X6USB' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x0099' status good url *none* comment *none* model `ScanMaker V300' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ScanMaker V300' interface `Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ScanMaker V310' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `ScanMaker V310' interface `Parport' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `ScanMaker V600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `ScanMaker V600' interface `Parport' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `ScanMaker 330' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `ScanMaker 630' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `ScanMaker 636' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanMaker 6400XL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanMaker 9600XL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `only flatbed mode ?' model `ScanMaker 9800XL' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status minimal url `/unsupported/microtek-scanmaker-9800.html' comment `IEEE-1394 seems to work. See link. More reports welcome.' model `Phantom 330CX' interface `Parport' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `SlimScan C3' interface `Parport' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Phantom 636' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Phantom 636CX' interface `Parport' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `SlimScan C6' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x009a' status complete url *none* comment *none* model `ScanMaker V6UPL' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x00b6' status basic url *none* comment `Sometimes scan speed goes to fast and results look badly smudged.' model `ScanMaker V6USL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanMaker V6USL' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x00a3' status complete url *none* comment *none* model `ScanMaker V6USL' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x80a3' status complete url *none* comment *none* model `ScanMaker X12USL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `only Flatbed mode ?' mfg `Vobis' url `http://www.vobis.de/' comment *none* model `HighScan' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `only E3plus based models' mfg `Scanport' url `http://www.scanport.com/' comment *none* model `SQ300' interface `Parport?' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `SQ2030' interface `Parport' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `SQ4836' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* mfg `Genius' url `http://www.geniusmouse.co.uk/' comment *none* model `ColorPage-EP' interface `Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* backend `mustek' version `1.0-138' manpage `sane-mustek' url `http://www.meier-geinitz.de/sane/mustek-backend/' comment `Most Mustek SCSI scanners are supported by this backend. For USB scanners, look at the mustek_usb backend.' type scanner mfg `Mustek' url `http://www.mustek.com/' url `http://www.mustek.com.tw/' url `http://www.mustek.de/' comment *none* model `Paragon MFS-6000CX' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3-pass' model `Paragon MFS-12000CX' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3-pass' model `Paragon MFC-600S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon 600 II CD' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon 600 II ED' interface `Parport' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `Completely untested. If it's the same as the 600 II EP, it may work. Please contact me if you own such a device.' model `Paragon 600 II EP' interface `Parport' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `Works, however only low resolutions and quality in color mode is bad.' model `ScanMagic 600 II SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `TwainScan II SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon MFC-800S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon 800 II SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon MFS-6000SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon MFS-8000SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon MFS-1200SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon MFS-12000SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanExpress 6000SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanExpress 12000SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanExpress 1200 FS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `One report that it crashes the computer. SCSI driver issue? Please contact me if you own such a device.' model `ScanExpress 12000SP Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon 1200 III SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `Paragon 1200 LS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanMagic 9636S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanMagic 9636S Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `ScanExpress A3 SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Please test!' model `Paragon 1200 SP Pro' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Paragon 1200 A3 Pro' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `ADF and TA untested. Please contact me if you own such equipment.' model `Paragon 600 II N' interface `Proprietary' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Resolutions above 300 dpi may cause trouble.' mfg `Trust' url `http://www.trust-site.com' comment `Carefully check the model names. Trust uses similar names for completely different hardware.' model `Imagery 1200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3-pass, Mustek Paragon MFS-6000CX compatible' model `Imagery 1200 SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Mustek Paragon MFS-6000SP compatible' model `Imagery 4800 SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Mustek Paragon 600 II CD compatible' model `SCSI Connect 19200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Mustek ScanExpress 12000SP compatible' model `SCSI excellence series 19200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Mustek ScanExpress 12000SP compatible' mfg `Primax' url `http://www.primax.nl/' comment *none* model `Compact 4800 SCSI' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Mustek 600 II CD compatible' backend `mustek_pp' version `13' manpage `sane-mustek_pp' url `http://penguin-breeder.org/sane/mustek_pp/' comment `Supports CIS and CCD type parallel port scanners from Mustek.' type scanner mfg `Mustek' url `http://www.mustek.com/' url `http://www.mustek.com.tw/' url `http://www.mustek.de/' comment *none* model `ScanExpress 6000 P' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' model `ScanExpress 600 SEP' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' model `ScanMagic 4800 P' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' model `600 III EP Plus' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' model `96 CP' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300x600 dpi CIS scanner' model `ScanExpress 600 CP' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300x600 dpi CIS scanner' model `ScanMagic 600 CP' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300x600 dpi CIS scanner' model `ScanExpress 1200 CP' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `600x1200 dpi CIS scanner' model `ScanExpress 1200 CP+' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `600x1200 dpi CIS scanner' mfg `Medion/Lifetec/Tevion/Cytron' url `http://www.medion.de/' comment `Those scanners are also known as "Aldi Scanner " or "Tchibo Scanners "' model `MD 9848' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' model `MD 9806' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' model `MD/LT 935x' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `600x1200 dpi CIS scanner' model `MD/LT 985x' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `600x1200 dpi CIS scanner' model `MD/LT 9890' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `600x1200 dpi CIS scanner' mfg `Targa' url *none* comment *none* model `Funline TS12 EP' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `600x1200 dpi CIS scanner' model `Funline TS6 EP' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300x600 dpi CIS scanner' mfg `Trust' url `http://www.trust-site.com/home/' comment *none* model `Easy Connect 9600+' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300x600 dpi CIS scanner' model `Easy Connect 19200+' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300x600 dpi CIS scanner' mfg `Viviscan' url *none* comment *none* model `Compact II' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' mfg `Cybercom' url *none* comment *none* model `9352' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `CIS scanner' mfg `Gallery' url *none* comment *none* model `4800' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' mfg `Network' url *none* comment *none* model `Easy Plus 30 Bit' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300 dpi CCD scanner' mfg `Micromaxx' url *none* comment *none* model `MM-9851' interface `Parport (EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `300x600 dpi CIS scanner' backend `mustek_usb' version `1.0-18' manpage `sane-mustek_usb' url `http://www.meier-geinitz.de/sane/mustek_usb-backend/' comment `Only the USB scanners mentioned below are supported. For BearPaws, look at the Plustek, MA-1509, and gt68xx backends.' type scanner mfg `Mustek' url `http://www.mustek.com/' url `http://www.mustek.com.tw/' url `http://www.mustek.de/' comment *none* model `ScanExpress 600 CU' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0002' status complete url *none* comment *none* model `ScanExpress 1200 CU' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0001' status complete url *none* comment *none* model `ScanExpress 1200 CU Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0008' status complete url *none* comment *none* model `ScanExpress 1200 UB' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0006' status complete url *none* comment `For the UB Plus, see gt68xx backend' mfg `Trust' url `http://www.trust-site.com' comment *none* model `Compact Scan USB 19200' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0006' status complete url *none* comment `Mustek 1200 UB compatible' backend `mustek_usb2' version `1.0-10' manpage `sane-mustek_usb2' url `http://www.meier-geinitz.de/sane/mustek_usb2-backend/' comment `Only BearPaw 2448TA Pro is supported at the moment' type scanner mfg `Mustek' url `http://www.mustek.com/' url `http://www.mustek.com.tw/' url `http://www.mustek.de/' comment *none* model `BearPaw 2448TA Pro' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0409' status good url *none* comment *none* backend `nec' version `0.12' manpage `sane-nec' url `http://www5a.biglobe.ne.jp/~saetaka/' comment *none* type scanner mfg `NEC' url `http://www.nevt.co.jp/' comment *none* model `PC-IN500/4C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `PC-IN500/4C was sold only in JAPAN' backend `net' version `1.0.14' manpage `sane-net' url `http://www.penguin-breeder.org/?page=sane-net' comment *none* type meta desc `Network access to saned servers' url *none* comment `Can be used to access any scanner supported by SANE over the net. Supports IPv4 and IPv6.' backend `niash' version `0.3' manpage `sane-niash' url `http://sourceforge.net/projects/hp3300backend' comment *none* type scanner mfg `Hewlett-Packard' url `http://www.hp.com' comment *none* model `ScanJet 3300c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0205' status complete url *none* comment *none* model `ScanJet 3400c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0405' status complete url *none* comment `If you use Linux 2.6, version 2.6.8 or newer is necessary.' model `ScanJet 4300c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0305' status complete url *none* comment `If you use Linux 2.6, version 2.6.8 or newer is necessary.' model `ScanJet 4300c/Silitek' interface `USB' usb-vendor-id `0x047b' usb-product-id `0x1002' status complete url *none* comment `If you use Linux 2.6, version 2.6.8 or newer is necessary.' mfg `Agfa' url `http://www.agfa.com' comment *none* model `Snapscan Touch' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x0100' status complete url *none* comment *none* mfg `Trust' url `http://www.trust.com' comment *none* model `Office Scan USB 19200' interface `USB' usb-vendor-id `0x047b' usb-product-id `0x1000' status complete url *none* comment *none* backend `p5' version `1' manpage `sane-p5' url `http://www.sane-project.org/' comment `New backend for SANE release 1.0.21, see sane-p5 manpage' type scanner mfg `PRIMAX' url `http://www.primax.com.tw' comment *none* model `PagePartner' interface `Parport (EPP/ECP)' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `Sheetfed scanner, work in gray and color, but uncalibrated scans' backend `pie' version `1.0' manpage `sane-pie' url `http://www.munton.demon.co.uk/sane' comment *none* type scanner mfg `Devcom' url `http://www.blackwidow.co.uk/' comment *none* model `9636PRO' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `9636S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `9630S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* mfg `PIE' url `http://www.scanace.com/' comment *none* model `ScanAce 1236S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ScanAce 1230S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ScanAce II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanAce III' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ScanAce Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanAce II Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanAce III Plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanAce V' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanAce ScanMedia' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanAce ScanMedia II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanAce 630S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `ScanAce 636S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* mfg `Adlib' url *none* comment *none* model `JetScan630' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `JetScan636PRO' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* backend `pint' version `unmaintained' manpage `sane-pint' url *none* comment *none* type api desc `Scanners with the machine-independent PINT interface' url *none* comment `Haven't been tested for a long time. Handle with care.' backend `pixma' version `0.17.3' manpage `sane-pixma' url `http://home.arcor.de/wittawat/pixma/' url `http://mp610.blogspot.com/' comment *none* type scanner mfg `Canon' url `http://www.canon.com/' comment *none* model `PIXMA E500' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1758' status untested url *none* comment `Testers needed!' model `PIXMA E510' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1761' status untested url *none* comment `Testers needed!' model `PIXMA E600' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x175a' status untested url *none* comment `Testers needed!' model `PIXMA E610' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1767' status untested url *none* comment `Testers needed!' model `PIXMA MG2100 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1751' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MG2200 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1760' status untested url *none* comment `Testers needed!' model `PIXMA MG3100 Series' interface `USB WLAN' usb-vendor-id `0x04a9' usb-product-id `0x1752' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MG3200 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1762' status untested url *none* comment `Testers needed!' model `PIXMA MG4100 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1753' status untested url *none* comment `Testers needed!' model `PIXMA MG4200 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1763' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MG5100 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1748' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MG5200 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1749' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MG5300 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1754' status complete url *none* comment `All resolutions supported (up to 2400DPI).' model `PIXMA MG5400 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1764' status untested url *none* comment `Testers needed!' model `PIXMA MG6100 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x174a' status complete url *none* comment `All resolutions supported (up to 2400 DPI)' model `PIXMA MG6200 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1755' status complete url *none* comment `All resolutions supported (up to 4800 DPI)' model `PIXMA MG6300 Series' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1765' status complete url *none* comment `All resolutions supported (up to 2400DPI).' model `PIXMA MG8100 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x174b' status untested url *none* comment `Testers needed!' model `PIXMA MG8200 Series' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1756' status complete url *none* comment `All resolutions supported (up to 4800DPI).' model `PIXMA MP140' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x172b' status complete url *none* comment `All resolutions supported (up to 600 DPI)' model `PIXMA MP150' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1709' status good url *none* comment *none* model `PIXMA MP160' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1714' status basic url *none* comment *none* model `PIXMA MP170' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x170a' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MP180' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1715' status basic url *none* comment *none* model `PIXMA MP190' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1734' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `PIXMA MP210' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1721' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `PIXMA MP220' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1722' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MP230' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x175f' status complete url *none* comment `All resolutions supported (up to 600DPI).' model `PIXMA MP240' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1732' status complete url *none* comment `All resolutions supported (up to 1200DPI)' model `PIXMA MP250' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x173a' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `PIXMA MP260' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1733' status complete url *none* comment `All resolutions supported (up to 1200DPI)' model `PIXMA MP270' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x173b' status complete url *none* comment `All resolutions supported (up to 1200DPI)' model `PIXMA MP280' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1746' status good url *none* comment `All resolutions supported (up to 600DPI).' model `PIXMA MP360' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x263c' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MP370' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x263d' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MP375R' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x263f' status untested url *none* comment `Same protocol as Pixma MP360/370/390? Testers needed!' model `PIXMA MP390' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x263e' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MP450' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x170b' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MP460' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1716' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MP470' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1723' status complete url *none* comment `All resolutions supported (up to 2400DPI).' model `PIXMA MP480' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1731' status complete url *none* comment `All resolutions supported (up to 2400DPI)' model `PIXMA MP490' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x173c' status complete url *none* comment `All resolutions supported (up to 1200DPI)' model `PIXMA MP493' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1757' status untested url *none* comment `Testers needed!' model `PIXMA MP495' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1747' status untested url *none* comment `Same protocol as Pixma MP280? Testers needed!' model `PIXMA MP500' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x170c' status good url *none* comment *none* model `PIXMA MP510' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1717' status complete url *none* comment `All resolutions supported (up to 1200DPI).' model `PIXMA MP520' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1724' status complete url *none* comment `All resolutions supported (up to 2400DPI)' model `PIXMA MP530' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1712' status good url *none* comment *none* model `PIXMA MP540' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1730' status complete url *none* comment `All resolutions supported (up to 2400DPI)' model `PIXMA MP550' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x173d' status complete url *none* comment `All resolutions supported (up to 2400DPI)' model `PIXMA MP560' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x173e' status complete url *none* comment `All resolutions supported (up to 2400DPI)' model `PIXMA MP600' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1718' status complete url *none* comment `All resolutions supported (up to 2400DPI)' model `PIXMA MP600R' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1719' status complete url *none* comment `All resolutions supported (up to 2400DPI)' model `PIXMA MP610' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1725' status complete url *none* comment `All resolutions supported (up to 4800DPI)' model `PIXMA MP620' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x172f' status complete url *none* comment `All resolutions supported (up to 2400DPI)' model `PIXMA MP630' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x172e' status complete url *none* comment `All resolutions supported (up to 4800DPI)' model `PIXMA MP640' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x173f' status complete url *none* comment `All resolutions supported (up to 4800DPI)' model `PIXMA MP700' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2630' status complete url *none* comment `All resolutions supported (flatbed color up to 1200DPI, grayscale up to 600DPI).' model `PIXMA MP710' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x264d' status complete url *none* comment `All resolutions supported (up to 1200DPI)' model `PIXMA MP730' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x262f' status good url *none* comment `Flatbed color up to 1200DPI, grayscale up to 600DPI. ADF scan to be confirmed.' model `PIXMA MP740' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x264c' status untested url *none* comment `Same protocol as Pixma MP710? Testers needed!' model `PIXMA MP750' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1706' status minimal url *none* comment `No grayscale. Canceling scan in ADF mode doesn't eject the paper!' model `PIXMA MP760' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1708' status minimal url *none* comment `No grayscale. The scanner sometimes hangs!' model `PIXMA MP770' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1708' status minimal url *none* comment `No grayscale. The scanner sometimes hangs!' model `PIXMA MP780' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1707' status minimal url *none* comment `No grayscale. The scanner sometimes hangs!' model `PIXMA MP790' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1707' status minimal url *none* comment `No grayscale. The scanner sometimes hangs!' model `PIXMA MP800' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x170d' status complete url *none* comment `All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI.' model `PIXMA MP800R' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x170e' status complete url *none* comment `All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI.' model `PIXMA MP810' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x171a' status complete url *none* comment `All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI.' model `PIXMA MP830' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1713' status complete url *none* comment `All resolutions supported up to 2400DPI. Flatbed, ADF simplex and Duplex supported.' model `PIXMA MP960' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x171b' status complete url *none* comment `All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI.' model `PIXMA MP970' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1726' status complete url *none* comment `All resolutions supported (up to 4800DPI). Full TPU support (negative and slides) at 24 or 48 bits.' model `PIXMA MP980' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x172d' status complete url *none* comment `Working fine at all resolutions.' model `PIXMA MP990' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1740' status complete url *none* comment `Working fine at all resolutions.' model `PIXMA MX300' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1727' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `PIXMA MX310' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1728' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 1200DPI)' model `PIXMA MX320' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1736' status untested url *none* comment `Same protocol as Pixma Generation 3? Testers needed!' model `PIXMA MX330' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1737' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 1200DPI)' model `PIXMA MX340' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1741' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 1200DPI)' model `PIXMA MX350' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1742' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 1200DPI)' model `PIXMA MX360' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x174d' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy.' model `PIXMA MX370 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1759' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 1200DPI).' model `PIXMA MX390 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1766' status untested url *none* comment `Testers needed!' model `PIXMA MX410' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x174e' status untested url *none* comment `Same protocol as Pixma MX420? Testers needed!' model `PIXMA MX420' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x174f' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy.' model `PIXMA MX430 Series' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x175b' status untested url *none* comment `Testers needed!' model `PIXMA MX450 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1768' status untested url *none* comment `Testers needed!' model `PIXMA MX510 Series' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x175c' status untested url *none* comment `Testers needed!' model `PIXMA MX520 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1769' status untested url *none* comment `Testers needed!' model `PIXMA MX700' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1729' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 2400DPI)' model `PIXMA MX710 Series' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x175d' status untested url *none* comment `Testers needed!' model `PIXMA MX720 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x176a' status untested url *none* comment `Testers needed!' model `PIXMA MX850' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x172c' status complete url *none* comment `All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported.' model `PIXMA MX860' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1735' status complete url *none* comment `All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported.' model `PIXMA MX870' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1743' status complete url *none* comment `All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.' model `PIXMA MX880 Series' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1750' status complete url *none* comment `All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.' model `PIXMA MX882' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1750' status complete url *none* comment `All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.' model `PIXMA MX885' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x1750' status complete url *none* comment `All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.' model `PIXMA MX890 Series' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x175e' status complete url *none* comment `All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.' model `PIXMA MX920 Series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x176b' status untested url *none* comment `Testers needed!' model `PIXMA MX7600' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x171c' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 4800DPI)' model `imageCLASS D420' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26ef' status complete url *none* comment `All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported.' model `imageCLASS D480' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26ed' status complete url *none* comment `All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported.' model `i-SENSYS MF3010' interface `USB Ethernet' usb-vendor-id `0x04a9' usb-product-id `0x2759' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `imageCLASS MF3110' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2660' status complete url *none* comment `All resolutions supported (up to 600DPI).' model `imageCLASS MF3240' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2684' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `imageCLASS MF4010' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26b4' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `imageCLASS MF4018' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26b4' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `imageCLASS MF4120' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26a3' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `imageCLASS MF4122' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26a3' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `imageCLASS MF4140' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26a3' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `imageCLASS MF4150' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26a3' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `imageCLASS MF4270' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26b5' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `I-SENSYS MF4320d' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26ee' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `I-SENSYS MF4330d' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26ee' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `imageCLASS MF4350d' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26ee' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `imageCLASS MF4370dn' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26ec' status good url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported' model `imageCLASS MF4380dn' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26ec' status good url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported' model `imageCLASS MF4410' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2737' status complete url *none* comment `All resolutions supported (up to 600DPI)' model `imageCLASS MF4430' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2737' status good url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI). ADF empty buggy.' model `i-SENSYS MF4550d' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2736' status good url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI).' model `imageCLASS MF4660' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26b0' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `imageCLASS MF4690' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26b0' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `imageCLASS MF5630' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x264e' status untested url *none* comment `Testers needed!' model `laserBase MF5650' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x264f' status untested url *none* comment `Testers needed!' model `imageCLASS MF5730' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x265d' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 1200DPI).' model `imageCLASS MF5750' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x265e' status untested url *none* comment `Testers needed!' model `imageCLASS MF5770' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x265f' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI).' model `i-SENSYS MF5880dn' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26f9' status untested url *none* comment `Testers needed!' model `imageCLASS MF6500 series' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2686' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `imageCLASS MF6550' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2686' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `i-SENSYS MF6680dn' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26fa' status untested url *none* comment `Testers needed!' model `imageCLASS MF8030' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2707' status untested url *none* comment `Testers needed!' model `imageCLASS MF8170c' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2659' status untested url *none* comment `Testers needed!' model `imageRUNNER 1020/1024/1025' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x26e6' status complete url *none* comment `Flatbed and ADF scan. All resolutions supported (up to 600DPI)' model `CanoScan 8800F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1901' status complete url *none* comment `Flatbed scan. TPU for negatives and slides. All resolutions supported (up to 4800DPI).' model `CanoScan 9000F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1908' status complete url *none* comment `Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI.' model `CanoScan 9000F Mark II' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x190d' status complete url *none* comment `Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI.' backend `plustek' version `0.52' manpage `sane-plustek' url `http://www.gjaeger.de/scanner/plustek/' comment *none* type scanner mfg `Plustek' url `http://www.plustek.de/' url `http://www.plustek.com/' comment *none* model `OpticPro U12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0010' status complete url *none* comment `NOTE: Devices with product ID 0x0001 are not supported!' model `OpticPro UT12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0013' status complete url *none* comment *none* model `OpticPro UT12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0017' status complete url *none* comment `Note: Devices with product ID 0x0001 are not supported!' model `OpticPro UT16' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0017' status complete url *none* comment *none* model `OpticPro U24' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0011' status complete url *none* comment *none* model `OpticPro U24' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0015' status complete url *none* comment *none* model `OpticPro UT24' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0017' status complete url *none* comment *none* mfg `Genius' url `http://www.geniusnet.com.tw/' comment *none* model `Colorpage HR6 V2' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2007' status complete url *none* comment *none* model `Colorpage HR6 V2' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2008' status complete url *none* comment *none* model `Colorpage HR7' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2013' status complete url *none* comment *none* model `Colorpage HR6A' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2009' status untested url *none* comment *none* model `Colorpage HR7LE' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2015' status untested url *none* comment *none* model `Colorpage HR6X' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2016' status untested url *none* comment *none* mfg `Mustek' url `http://www.mustek.com/' comment *none* model `BearPaw 1200' interface `USB' usb-vendor-id `0x0400' usb-product-id `0x1000' status complete url *none* comment `both product versions are supported, see backends' man-page' model `BearPaw 1200' interface `USB' usb-vendor-id `0x0400' usb-product-id `0x1001' status complete url *none* comment `both product versions are supported, see backends' man-page' model `BearPaw 2400' interface `USB' usb-vendor-id `0x0400' usb-product-id `0x1001' status complete url *none* comment *none* mfg `Hewlett-Packard' url `http://www.hp.com/' comment *none* model `ScanJet 2100C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0505' status complete url *none* comment *none* model `ScanJet 2200C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0605' status complete url *none* comment *none* mfg `Epson' url `http://www.epson.com/' comment *none* model `Perfection 1250' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010f' status complete url *none* comment *none* model `Perfection 1250Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x010f' status good url *none* comment `TPA scans not perfect' model `Perfection 1260' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011d' status complete url *none* comment *none* model `Perfection 1260Photo' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011d' status good url *none* comment `TPA scans not perfect' mfg `Umax' url `http://www.umax.com/' comment *none* model `UMAX 3400' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0050' status complete url *none* comment `there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x' model `UMAX 3400' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0060' status complete url *none* comment `there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x' model `UMAX Astranet ia101' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0060' status complete url *none* comment `seems to be a renamed UMAX 3400' model `UMAX 3450' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0060' status complete url *none* comment *none* model `UMAX 5400' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0160' status complete url *none* comment *none* mfg `Compaq' url `http://www.compaq.com/' comment *none* model `S4-100' interface `USB' usb-vendor-id `0x049f' usb-product-id `0x001a' status complete url *none* comment `Identical to UMAX 3400' mfg `Canon' url `http://www.canon.com/' comment *none* model `CanoScan N650U/N656U' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2206' status complete url *none* comment *none* model `CanoScan N1220U' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2207' status complete url *none* comment *none* model `CanoScan N670U/N676U/LiDE20' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x220d' status complete url *none* comment *none* model `CanoScan N1240U/LiDE30' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x220e' status complete url *none* comment *none* model `CanoScan LiDE25' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2220' status good url *none* comment *none* model `CanoScan D660U' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2208' status good url *none* comment `TPA scans not perfect' mfg `Syscan' url `http://www.syscaninc.com/' comment *none* model `TravelScan 460/464' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x4600' status complete url *none* comment *none* model `TravelScan 662' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x6620' status complete url *none* comment *none* mfg `Ambir' url *none* comment *none* model `Visigo A4' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x4600' status complete url *none* comment `Rebaged Travelscan 464' mfg `Portable Peripheral Co., Ltd.' url `http://www.pandp.com.tw/' comment *none* model `Q-Scan USB001 (A4 portable scanner)' interface `USB' usb-vendor-id `0x0a53' usb-product-id `0x1000' status complete url *none* comment *none* model `Q-Scan USB201 (A6 portable scanner)' interface `USB' usb-vendor-id `0x0a53' usb-product-id `0x2000' status good url *none* comment *none* mfg `Visioneer' url `http://www.visioneer.com/' comment *none* model `Strobe XP 100' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0427' status basic url *none* comment *none* backend `plustek_pp' version `0.43' manpage `sane-plustek_pp' url `http://www.gjaeger.de/scanner/plustek_pp/' comment *none* type scanner mfg `Plustek' url `http://www.plustek.de/' url `http://www.plustek.com/' comment *none* model `OpticPro 4800P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro 4830P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro 600P/6000P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro 4831P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro 9630P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro 9630PL' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `use driver-switch mov=1' model `OpticPro 9600P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro 1236P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `reported as OpticPro 12000P/96000P' model `OpticPro 12000P/96000P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro 9636P' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `use driver-switch mov=4' model `OpticPro 9636P+/Turbo' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `use driver-switch mov=3' model `OpticPro 9636T' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro 12000T' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro AI3' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `use driver-switch mov=5, poor picture quality' model `OpticPro P8' interface `Parport' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* model `OpticPro P12' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* model `OpticPro PT12' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment *none* mfg `Primax' url `http://www.primax.nl/' comment *none* model `Colorado 4800' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `same as OpticPro 4800P' model `Compact 4800 Direct' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `use driver-switch mov=2' model `Compact 4800 Direct-30' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `same as OpticPro 4830P, use driver-switch mov=7' model `Compact 9600 Direct-30' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `same as OpticPro 9630P' mfg `Genius' url `http://www.geniusnet.com.tw/' comment *none* model `Colorpage Vivid III V2' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Reported as PT12' model `Colorpage Vivid Pro II Film' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Reported as OP9636T/12000T' model `Colorpage HR6X EPP' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Negative scanning does not work correctly' mfg `Aries' url *none* comment *none* model `Scan-It Pro 4800' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `use driver-switch mov=2' mfg `BrightScan' url *none* comment *none* model `BrighScan OpticPro' interface `Parport (SPP, EPP)' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `Reported as P12' backend `pnm' version `1.0.8' manpage `sane-pnm' url `mailto:henning@meier-geinitz.de' comment *none* type api desc `Reads PNM files' url *none* comment `Used for debugging frontends. Obsolete, use test backend instead.' backend `qcam' version `unmaintained' manpage `sane-qcam' url *none* comment *none* type vidcam mfg `Connectix' url *none* comment *none* model `Color QuickCam' interface `Parport' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Requires root privileges.' model `Greyscale QuickCam' interface `Parport' usb-vendor-id *none* usb-product-id *none* status minimal url *none* comment `Requires root privileges. Partly working.' backend `ricoh' version `unmaintained' manpage `sane-ricoh' url *none* comment *none* type scanner mfg `Ricoh' url `http://www.ricoh.com/' comment *none* model `Ricoh IS50' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `Ricoh IS60' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* backend `rts8891' version `1.0-0' manpage `sane-rts8891' url `http://stef.dev.free.fr/sane/rts8891/index.html' comment `This backend supports Realtek RTS8891 ASIC bases scanners.' type scanner mfg `UMAX' url `http://www.umax.com.tw/' comment *none* model `Astra 4400' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0070' status good url *none* comment `Supports 75, 150, 300, 600 and 1200 dpi' model `Astra 4450' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0070' status untested url *none* comment *none* mfg `Hewlett-Packard' url `http://www.hp.com/' comment *none* model `scanjet 4470c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0805' status good url *none* comment `re-branded Astra 4400' model `scanjet 4400c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0705' status good url *none* comment `exists with 2 different sensors of which only one works' backend `s9036' version `unmaintained' manpage `sane-s9036' url *none* comment *none* type scanner mfg `Siemens' url `http://www.siemens.com/' comment *none* model `9036 Flatbed scanner' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* backend `sceptre' version `1.0-10' manpage `sane-sceptre' url `http://www.zago.net/sane/' comment *none* type scanner mfg `Sceptre' url `http://www.sceptre.com/' comment *none* model `Vividscan S1200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* mfg `Komodo' url `http://www.komodo.com/' comment *none* model `S1200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `rebadged Sceptre S1200' backend `sharp' version `0.32' manpage `sane-sharp' url `http://www.satzbau-gmbh.de/staff/abel/sane-sharp.html' comment *none* type scanner mfg `Sharp' url `http://sharp-world.com/' comment *none* model `JX-610' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `' model `JX-250' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `' model `JX-320' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `' model `JX-325' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `' model `JX-330' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `' model `JX-350' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `' backend `sm3600' version `0.1' manpage `sane-sm3600' url `http://sm3600.sourceforge.net/' comment *none* type scanner mfg `Microtek' url `http://www.microtek.com/' comment *none* model `ScanMaker 3600' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x40b3' status basic url *none* comment `works' model `ScanMaker 3600' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x40ca' status basic url *none* comment `works' model `ScanMaker 3600' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x40ff' status basic url *none* comment `works' model `ScanMaker 3700' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x40b8' status basic url *none* comment `works' model `ScanMaker 3700' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x40cb' status basic url *none* comment `works' model `ScanMaker 3750' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x40dd' status basic url *none* comment `works (told)' backend `sm3840' version `1.1' manpage `sane-sm3840' url `http://www.ziplabel.com/sm3840/' comment `This reverse-engineered backend supports the USB ScanMaker 3840 model' type scanner mfg `Microtek' url `http://www.microtek.com/' comment `Microtek makes a wide variety of devices.' model `ScanMaker 3840' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30d4' status good url *none* comment `8 and 16 bit, color and grayscale' model `ScanMaker 4800' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30cf' status good url *none* comment `Same hardware as SM3840, different color box' backend `SnapScan' version `1.4' manpage `sane-snapscan' url `http://snapscan.sourceforge.net/' comment `Supported bit depths: 24 bit (color), 48 bit (color, Epson) 8 bit (gray)' type scanner mfg `AGFA' url `http://www.agfa.com/' comment *none* model `SnapScan' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `SnapScan 300' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `SnapScan 310' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `SnapScan 600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Optional ADF supported.' model `Arcus 1200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Optional transparency unit supported.' model `SnapScan 1236s' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Optional ADF and transparency unit supported.' model `SnapScan 1236u' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x0002' status good url *none* comment `Optional ADF and transparency unit supported.' model `SnapScan 1212U' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x0001' status good url *none* comment *none* model `SnapScan 1212U_2' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x2061' status good url *none* comment *none* model `SnapScan e10' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x2093' status good url *none* comment *none* model `SnapScan e20' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x2091' status good url *none* comment *none* model `SnapScan e25' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x2095' status good url *none* comment *none* model `SnapScan e26' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x2097' status good url *none* comment *none* model `SnapScan e40' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x208d' status good url *none* comment *none* model `SnapScan e42' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x20ff' status good url *none* comment *none* model `SnapScan e50' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x208f' status good url *none* comment `Optional tranparency unit supported' model `SnapScan e52' interface `USB' usb-vendor-id `0x06bd' usb-product-id `0x20fd' status good url *none* comment `Optional tranparency unit supported' model `SnapScan e60' interface `USB' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment *none* mfg `Acer Peripherals' url *none* comment `Company was renamed to Benq.' model *none* mfg `Vuego' url *none* comment `Company was renamed to Benq.' model *none* mfg `Benq (Acer)' url `http://www.benq.com' comment `Formerly Acer Peripherals' model `300f' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `310s' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `610s' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `610plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `620s' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ScanWit 2720s' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `310U' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x1a20' status good url *none* comment *none* model `320U' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2022' status good url *none* comment *none* model `340U' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2022' status good url *none* comment *none* model `620U' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x1a2a' status good url *none* comment `Optional tranparency unit supported' model `620UT' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2040' status good url *none* comment `Optional tranparency unit supported' model `640U' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2060' status good url *none* comment `Optional tranparency unit supported' model `640bu' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x207e' status good url *none* comment *none* model `640BT' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20be' status good url *none* comment `Optional tranparency unit supported' model `1240' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20c0' status good url *none* comment `Optional tranparency unit supported' model `3300' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20b0' status good url *none* comment *none* model `3300' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20de' status good url *none* comment *none* model `4300' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20b0' status good url *none* comment *none* model `4300' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20de' status good url *none* comment *none* model `5000E' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20fc' status basic url *none* comment `Same as 5000U, working up to 600 DPI' model `5000U' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20fc' status basic url *none* comment `Same as 5000E, working up to 600 DPI' model `5000' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20f8' status good url *none* comment `USB ID 0x04a5,0x20f8: Color / grayscale scans working up to 1200 DPI' model `5150' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2137' status basic url *none* comment `Calibration algorithm unknown' model `5250' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2137' status basic url *none* comment `Same hardware as 5150 (?), Calibration algorithm unknown' model `5300' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20fe' status basic url *none* comment `Problems with firmware upload reported' mfg `Guillemot / Hercules' url `http://www.guillemot.com' comment *none* model `Maxi Scan A4 Deluxe (SCSI)' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Rebadged SnapScan 310s.' model `Scan@home Touch 1248 (USB)' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20de' status good url *none* comment `Rebadged Benq 3300.' model `Maxi Scan A4 USB 640U' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2060' status good url *none* comment `Rebadged Benq 640U.' model `Maxi A4 36 bit' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2060' status good url *none* comment `Rebadged Benq 620U, needs Benq firmware file u96v???.bin' mfg `Mitsubishi' url `http://www.mitsubishi.com' comment *none* model `Diamondview 648UT' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2022' status good url *none* comment `Rebadged Benq 320u.' model `Diamondview 650U' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x20b0' status good url *none* comment `Rebadged Benq 4300.' mfg `Epson' url `http://www.epson.com' comment *none* model `Perfection 660' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0114' status good url *none* comment *none* model `Perfection 1270' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0120' status good url *none* comment *none* model `Perfection 1670' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x011f' status good url *none* comment *none* model `Perfection 2480' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0121' status good url *none* comment *none* model `Perfection 2580' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0121' status basic url *none* comment `Film scanning unit unsupported' model `Perfection 3490' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0122' status good url *none* comment *none* model `Perfection 3590' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0122' status basic url *none* comment `Film scanning unit unsupported' model `Stylus CX-1500' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x080c' status good url *none* comment *none* backend `sp15c' version `unmaintained' manpage `sane-sp15c' url *none* comment *none* type scanner mfg `Fujitsu' url `http://www.fcpa.fujitsu.com/products/scanners/' url `http://www.fujitsu.com/' comment *none* model `ScanPartner 15C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `ScanPartner 600C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* backend `st400' version `1.6' manpage `sane-st400' url `http://www.informatik.uni-oldenburg.de/~ingo/sane/' comment *none* type scanner mfg `Siemens' url `http://www.siemens.de/' comment *none* model `ST400' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `6 bit gray' model `ST800' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `6 bit gray' backend `stv680' version `1.0-1' manpage `sane-stv680' url `http://gkall.hobby.nl/stv680-aiptek.html' comment `This vidcam backend is for the stv0680 chipset, See the website for more info.' type vidcam mfg `Aiptek' url `http://www.aiptek.com.tw' comment *none* model `Aiptek Pencam' interface `USB' usb-vendor-id `0x0553' usb-product-id `0x0202' status minimal url *none* comment `image is OK for CIF and QCIF, VGA and QVGA untested, streaming video is a problem' mfg `Konica' url `http://www.konicaminolta.com' comment *none* model `e-mini' interface `USB' usb-vendor-id `0x04c8' usb-product-id `0x0722' status untested url *none* comment ` ' mfg `Digital Dream' url `http://www.digitaldreamco.com/en/index.shtml' comment *none* model `l' espion XS' interface `USB' usb-vendor-id `0x1183' usb-product-id `0x0001' status untested url *none* comment ` ' mfg `Creative' url `http://www.creative.com/' comment *none* model `WebCam Go Mini' interface `USB' usb-vendor-id `0x041e' usb-product-id `0x4007' status untested url *none* comment ` ' backend `tamarack' version `unmaintained' manpage `sane-tamarack' url *none* comment *none* type scanner mfg `Tamarack' url *none* comment *none* model `Artiscan 6000C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3 pass, 300 DPI' model `Artiscan 8000C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3 pass, 400 DPI' model `Artiscan 12000C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `3 pass, 600 DPI' backend `teco1' version `1.0-10' manpage `sane-teco1' url `http://www.zago.net/sane/#teco' comment *none* type scanner mfg `Relisys' url `http://www.relisys.com/' url `http://www.tecoimage.com.tw/' comment *none* model `RELI 2412' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `sub model VM3530+' model `AVEC 2400' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `sub model VM3520' model `RELI 4830' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM4542' model `AVEC 2412' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `sub model VM3520+' model `AVEC 4800' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM4530' model `AVEC 4816' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM4530+' model `RELI DS6' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3420' model `RELI DS15' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3440' model `RELI 2400' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3530' model `RELI 4816' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status complete url *none* comment `sub model VM4540' model `RELI 9600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM6530' model `RELI 9612' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM6530*' model `RELI 9624' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM6530+' model `RELI 9630' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM6540' mfg `Actown' url *none* comment *none* model `ACT Scan I 30' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3520A' mfg `Dextra' url *none* comment *none* model `DF-600P' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM3510' model `DF-1200T+' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3530+' model `DF-4830T' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM4542' model `DF-9624' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM6530+' backend `teco2' version `1.0-9' manpage `sane-teco2' url `http://gkall.hobby.nl/teco2.html' comment *none* type scanner mfg `Relisys' url `http://www.relisys.com/' comment *none* model `AVEC Super 3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3575' model `AVEC II S3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM3564' model `SCORPIO Super 3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM3575' model `APOLLO Express 3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `sub model VM356A' model `APOLLO Express 6' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM6565' model `SCORPIO Pro' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM6575' model `SCORPIO Pro-S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM6586' mfg `Primax' url `http://www.primax.nl/' comment *none* model `Jewel 4800' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM356A' model `Profi 9600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment `sub model VM6575' model `Profi 19200' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM6586' mfg `Mustek' url `http://www.mustek.com/' comment *none* model `ScanMagic 4830S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3575' backend `teco3' version `1.0-1' manpage `sane-teco3' url `http://www.zago.net/sane/#teco3' comment *none* type scanner mfg `Relisys' url `http://www.tecoimage.com.tw/' comment *none* model `Infinity Scorpio' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM3552' mfg `Plustek' url *none* comment *none* model `OpticPro 2400SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3552' mfg `PIOTECH' url `http://www.image-land.com/' comment *none* model `Splendeur 3024' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM3552' mfg `Trust' url *none* comment *none* model `Imagery 2400 SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM3552' model `Imagery 4800 SP+' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `sub model VM3552' model `Imagery 9600 SP' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `sub model VM3552' backend `test' version `1.0-28' manpage `sane-test' url `http://www.meier-geinitz.de/sane/test-backend/' comment *none* type api desc `Frontend-tester' url *none* comment `Backend for testing frontends. Also serves as example for SANE backend options.' backend `u12' version `0.02' manpage `sane-u12' url `http://www.gjaeger.de/scanner/u12/' comment *none* type scanner mfg `Plustek' url `http://www.plustek.de/' url `http://www.plustek.com/' comment *none* model `OpticPro U12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0001' status basic url *none* comment `Note: Only devices with product ID 0x0001 are supported!' model `OpticPro UT12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0001' status basic url *none* comment `Note: Only devices with product ID 0x0001 are supported!' model `OpticPro 1212U' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0001' status basic url *none* comment *none* mfg `RevScan' url *none* comment *none* model `RevScan Orange R48Ti' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0001' status basic url *none* comment `Rebadged Plustek OpticPro UT12' mfg `Genius' url `http://www.geniusnet.com.tw/' comment *none* model `ColorPage HR6 V1' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2004' status basic url *none* comment *none* model `ColorPage Vivid III USB' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0001' status untested url *none* comment `Note: Device has Plustek vendor and product ID (0x07b3/0x0001)' backend `umax' version `1.0-41' manpage `sane-umax' url `http://www.rauch-domain.de/sane-umax/index.html' comment *none* type scanner mfg `UMAX' url `http://www.umax.com/' url `http://www.umax.com.tw/' url `http://www.umax.de/en' url `http://www.umax-europe.com' url `http://www.umaxjapan.co.jp' url `http://www.umax.com.cn' comment *none* model `Vista S6' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Vista S6E' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `UMAX S-6E' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `UMAX S-6EG' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Vista-S8' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Supervista S-12' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `UMAX S-12' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `UMAX S-12G' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra 600S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra 610S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra 1200S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra 1220S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra 2100S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra 2200 (SU)' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra 2200 (SU)' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0230' status good url *none* comment `OK, needs USB control messages' model `Astra 2400S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra 6400' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `will probably work one day' model `Astra 6450' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `will probably work one day' model `Astra MX3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Astra MX3' interface `USB' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, needs USB control messages' model `Mirage D-16L' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Mirage II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Mirage IIse' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `PSD' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `PowerLook' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=PS-2400X' model `PL-II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `PowerLook III' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `PowerLook 270' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `incompatible' model `PowerLook 270plus' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `incompatible' model `PowerLook 1100' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `will probably work one day' model `PowerLook 2000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `PowerLook 2100XL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `PowerLook 3000' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `Gemini D-16' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `UMAX VT600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `may work, please test and give feedback' model `Vista-T630' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK for some firmwareversions, on others only lineart OK' model `UC 630' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Version 2.8 OK, others only lineart OK' model `UG 630' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `UG 80' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' model `UC 840' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Version 1.6 OK, others only lineart OK' model `UC 1200S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `may work, please test and give feedback' model `UC 1200SE' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Version 3.0 OK, others unknown' model `UC 1260' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `Version 1.6 OK, others unknown' mfg `Linotype Hell' url `http://www.heidelberg.com/' comment *none* model `Jade' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=LinoHell Office' model `Jade' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=LinoHell JADE' model `Jade2' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=LinoHell Office2' model `Saphir' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `support disabled until tested - please contact author' model `Saphir2' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=LinoHell SAPHIR2' model `Saphir3' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=LinoHell SAPHIR3' model `Saphir Ultra' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `support disabled until tested - please contact author' model `Saphir Ultra II' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=Linotype SAPHIR4' model `Saphir HiRes' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `support disabled until tested - please contact author' model `Opal' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `support disabled until tested - please contact author' model `Opal2' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK; SCSI-ID=LinoHell OPAL2' model `Opal Ultra' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `support disabled until tested - please contact author' model `Linoscan 1400' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=HDM LS4H1S' mfg `Vobis' url `http://www.vobis.de/' comment *none* model `Highscreen Scanboostar Premium' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=LinoHell Office2' mfg `EDGE' url *none* comment *none* model `KTX-9600US' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `no feedback' mfg `Epson' url `http://www.epson.com/' comment *none* model `Perfection 600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=EPSON Perfection600' mfg `Escom' url *none* comment *none* model `Image Scanner 256' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=UMAX UG 80' mfg `Escort' url *none* comment *none* model `Galleria 600' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `untested, SCSI-ID=ESCORT Galleria 600S' mfg `Genius' url *none* comment *none* model `ColorPage-HR5 (Pro)' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK, SCSI-ID=KYE ColorPage-HR5' mfg `Nikon' url `http://www.nikon.com/' comment *none* model `AX-110 / Scantouch 110' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status untested url *none* comment `may work, please test and give feedback' model `AX-210' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' mfg `TriGem' url `http://www.nikon.com/' comment *none* model `PowerScanII' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `OK' backend `umax1220u' version `unmaintained' manpage `sane-umax1220u' url `http://sourceforge.net/projects/umax1220u-sane' comment *none* type scanner mfg `UMAX' url `http://www.umax.com/' comment *none* model `Astra 1220U' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0010' status good url *none* comment *none* model `Astra 1600U' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0030' status good url *none* comment *none* model `Astra 2000U' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0030' status good url *none* comment *none* model `Astra 2100U' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x0130' status good url *none* comment *none* backend `umax_pp' version `1' manpage `sane-umax_pp' url `http://umax1220p.sourceforge.net/' comment *none* type scanner mfg `UMAX' url `http://www.umax.com.tw/' comment *none* model `Astra 1220P' interface `Parport (EPP/ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Astra 2000P' interface `Parport (EPP/ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Astra 1600P' interface `Parport (EPP/ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* model `Astra 600P' interface `Parport (SPP/ECP)' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `untested, but should be close to 610P' model `Astra 610P' interface `Parport (SPP/ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment *none* mfg `Hewlett-Packard' url *none* comment *none* model `Scanjet 3200C' interface `Parport (EPP/ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `works (relabelled 1220P and 2000P)' mfg `Genius' url *none* comment *none* model `ColorPage-Life Pro' interface `Parport (EPP/ECP)' usb-vendor-id *none* usb-product-id *none* status good url *none* comment `works (relabelled 1220P and 2000P)' backend `unsupported' version `2010-06-09' manpage *none* url `/contrib.html' comment `The devices mentioned here are not supported by any SANE backend. However, there may be links to information about them or stand-alone programs.' type scanner mfg `Agfa' url *none* comment *none* model `DuoScan f40' interface `USB IEEE-1394' usb-vendor-id `0x06bd' usb-product-id `0x02bf' status unsupported url `/unsupported/agfa-duoscan-f40.html' comment `Unsupported. See link for details.' model `DuoScan T2000XL' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/agfa-duoscan-t2000xl.html' comment `Unsupported. Same as Microtek ArtixScan 2020?' model `DuoScan T2500' interface `SCSI IEEE-1384' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Unsupported. Same as Microtek Artixscan 2500f' model `SnapScan 310P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `SnapScan EZ' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `SnapScan 1200P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `SnapScan 1212P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' mfg `Artec/Ultima' url `http://www.artecusa.com/' comment *none* model `1236 USB' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4001' status unsupported url `/unsupported/artec_1236usb.html' comment `Unsupported. See link for details.' model `AM12e+' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Unsupported. Chips found inside: AT015, AD9816JS. Maybe similar to SCSI version or as6e?' model `Ultima 2000 (0x4001)' interface `USB' usb-vendor-id `0x05d8' usb-product-id `0x4001' status unsupported url `/unsupported/artec-ultima-2000-2.html' comment `Same name, but different ids: This scanner is not supported. The scanner with product id 0x4002 is supported by the gt68xx backend, however.' mfg `Avigramm' url *none* comment *none* model `Minidoc' interface `USB Parport' usb-vendor-id `0x05cb' usb-product-id `0x1483' status unsupported url `/unsupported/trust-combiscan-19200.html' comment `Not supported. See link for details.' mfg `Avision' url `http://www.avision.com/' comment *none* model `DS310F' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. Scanner/printer/copier combination.' model `iVina FB2400' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Not supported. No chipset information available. Same as UMAX Astra 6700.' model `iVina 1600' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a10' status unsupported url `/unsupported/umax-astra-4500.html' comment `GL646 based, to be added to genesys backend. Same as UMAX Astra 4500.' model `iVina FB1800' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a20' status unsupported url `/unsupported/umax-astra-4700.html' comment `GL646/GL660 based. Same as UMAX Astra 4700.' mfg `Benq (Acer)' url `http://www.benq.com' comment `Formerly Acer Peripherals' model `310P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `320P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `340P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `610P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `610PT' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `620P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `620PT' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `640P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/acer-parport.html' comment `Unsupported, see link for details.' model `5450' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x211e' status unsupported url *none* comment `Unsupported.' model `5550' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2211' status unsupported url `/unsupported/benq-5550.html' comment `Unsupported, see link for details.' model `5560' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2311' status unsupported url `http://lists.alioth.debian.org/pipermail/sane-devel/2009-January/023447.html' comment *none* model `7400UT' interface `USB' usb-vendor-id `0x04a5' usb-product-id `0x2202' status unsupported url `/unsupported/benq-7400ut.html' comment *none* mfg `Boeder' url *none* comment *none* model `Sm@rtScan Office' interface `Parport USB' usb-vendor-id `0x05cb' usb-product-id `0x1483' status unsupported url `/unsupported/trust-combiscan-19200.html' comment `Unsupported. See link for details.' mfg `Brother' url `http://www.brother.com/' comment *none* model `MFC 2500' interface `USB' usb-vendor-id `0x04f9' usb-product-id `0x000a' status unsupported url `/unsupported/brother-mfc-2500.html' comment `Not supported. See link for details.' model `MFC 4600' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://sourceforge.net/projects/brother-mfc' comment `The parport 200x400dpi grayscale version of this scanner is unsupported. Dmitri Katchalov did some investigations on this scanner. If you want to write a backend, contact him (see link).' model `MFC 7300c' interface `Parport USB' usb-vendor-id `0x04f9' usb-product-id `0x0106' status unsupported url `/unsupported/brother-mfc-7300.html' comment *none* model `MFC 9600' interface `USB' usb-vendor-id `0x04f9' usb-product-id `0x0101' status unsupported url `/unsupported/brother-mfc-9600.html' comment *none* mfg `C-Channel' url `http://www.c-channel.ch/' comment *none* model `MyPen Pro' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/c-channel-mypen-pro.html' comment `Probably unsupported. See link for details.' model `MyPen Light' interface `USB' usb-vendor-id `0x0a93' usb-product-id `0x0005' status unsupported url *none* comment `See bug #306792 for details.' model `MoneyPen II' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably unsupported.' mfg `Canon' url `http://www.canon.com/' comment *none* model `CanoScan 3000' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2215' status unsupported url `/unsupported/canon-3000.html' comment `GL660+GL646 based.' model `CanoScan 3000ex' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2215' status unsupported url `/unsupported/canon-3000.html' comment `GL660+GL646 based.' model `CanoScan 3000F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2215' status unsupported url `/unsupported/canon-3000.html' comment `GL660+GL646 based, to be added to genesys backend' model `CanoScan 4200F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x221b' status unsupported url `/unsupported/canon-4200f.html' comment `Probably unsupported. See link.' model `CanoScan 4400F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2228' status unsupported url `/unsupported/canon-4400.html' comment `GL843 based, to be added to genesys backend' model `CanoScan 5000F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2212' status unsupported url `/unsupported/canon-5000f.html' comment `Unsupported. See link for details.' model `CanoScan 5200F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2217' status unsupported url `/unsupported/canon-5200f.html' comment `Probably unsupported. See link for details.' model `CanoScan 8000F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x220f' status unsupported url `/unsupported/canon-8000f.html' comment `Not supported. See link for more information. With transparency adapter.' model `CanoScan 8400F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x221e' status unsupported url `/unsupported/canon-8400f.html' comment `GL841 based, to be added to genesys backend' model `CanoScan 8600F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2229' status unsupported url `/unsupported/canon-8600.html' comment `GL841 based, to be added to genesys backend' model `CanoScan 9900F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2210' status unsupported url `/unsupported/canon-9900f.html' comment `Probably unsupported, similar to 8000F. 3200x6400 dpi USB2. With transparency adapter.' model `CanoScan 9950F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2219' status unsupported url `/unsupported/canon-9950f.html' comment `Probably unsupported.' model `CanoScan D646U' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x220b' status unsupported url `/unsupported/canon-d646u.html' comment `Probably not supported. See link for more information and test program.' model `CanoScan D646U ex' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x220b' status unsupported url `/unsupported/canon-d646u.html' comment `Probably not supported. See D646.' model `CanoScan D1230U' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2209' status unsupported url `/unsupported/canon-d1230u.html' comment `Probably not supported. ' model `CanoScan D1250U2' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x220c' status unsupported url `/unsupported/canon-d1250u2.html' comment `Not supported. However, someone started working on this scanner and some information is available (see link).' model `CanoScan D2400UF' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x220a' status unsupported url `/unsupported/canon-d2400uf.html' comment `Not supported. See link.' model `CanoScan FB320U' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2201' status unsupported url *none* comment `Probably not supported. No details known.' model `CanoScan FB620U' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2202' status unsupported url `/unsupported/canon-fb620u.html' comment `Probably not supported. Some information is available.' model `CanoScan FB1210U' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2205' status unsupported url `http://sourceforge.net/projects/canonscanner/' comment `Not supported. However, a stand-alone program for FreeBSD is available.' model `CanoScan LiDE 70' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2225' status unsupported url `http://www.juergen-ernst.de/info_sane.html' comment `Philips chip. Backend started, see link' model `CanoScan LiDE 80' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2214' status unsupported url `/unsupported/canon-lide-80.html' comment `GL841 based, to be added to genesys backend' model `CanoScan LiDE 90' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1900' status unsupported url `/unsupported/canon-lide-90.html' comment `Unsupported. See link for details.' model `CanoScan LiDE 500F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x221f' status unsupported url `/unsupported/canon-canoscan-lide-500f.html' comment `GL841 based, to be added to genesys backend' model `CanoScan LiDE 600' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2224' status unsupported url `http://www.juergen-ernst.de/info_sane.html' comment `Philips chip. Backend started, see link' model `CanoScan LiDE 600F' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x2224' status unsupported url `http://www.juergen-ernst.de/info_sane.html' comment `Philips chip. Backend started, see link' model `FS4000' interface `USB SCSI' usb-vendor-id `0x04a9' usb-product-id `0x3042' status unsupported url `/unsupported/canon-fs4000.html' comment `Not supported. See link for more details.' model `IS 12' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/canon-is-12.html' comment `Probably not supported. Scanner cardridge for Canon inkjet printers.' model `IS 22' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/canon-is-22.html' comment `Probably not supported. Scanner cardridge for Canon inkjet printers.' model `IS 32' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x105d' status unsupported url `/unsupported/canon-is-32.html' comment `Probably not supported. Scanner cardridge for Canon inkjet printers.' model `IS 52' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/canon-is-52.html' comment `Probably not supported. Scanner cardridge for Canon inkjet printers.' model `ImageRunner iR1018' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x269d' status unsupported url `/unsupported/canon-imagerunner.html' comment `Probably not supported. See link for details.' model `ImageRunner iR1022' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x269d' status unsupported url `/unsupported/canon-imagerunner.html' comment `Probably not supported. See link for details.' model `ImageRunner iR1023' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x269d' status unsupported url `/unsupported/canon-imagerunner.html' comment `Probably not supported. See link for details.' model `PIXMA MP110' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1700' status unsupported url `/unsupported/canon-pixma-mp110.html' comment `Probably not supported. See link for details.' model `PIXMA MP130' interface `USB' usb-vendor-id `0x04a9' usb-product-id `0x1701' status unsupported url `/unsupported/canon-pixma-mp130.html' comment `Probably not supported. See link for details.' model `DR-2020U' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `GL84x?' mfg `Chinon' url *none* comment *none* model `DS-3000' interface `Parport Serial Port' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/chinon-ds3000.html' comment `Unsupported at the moment, but a backend is in preparation. See link.' mfg `Compaq' url `http://www.compaq.com/' comment *none* model `S200' interface `USB' usb-vendor-id `0x049f' usb-product-id `0x0021' status unsupported url *none* comment `Not supported. 2400x1200 dpi. One bulk-in, one bulk-out and one interrupt endpoint. Type-number: U0001-HB21, another type nr on the inside: 75100512-00' mfg `Compeye' url *none* comment *none* model `Simplex 1236C' interface `Parport USB' usb-vendor-id `0x05cb' usb-product-id `0x1483' status unsupported url `/unsupported/trust-combiscan-19200.html' comment `Unsupported. See link for details.' mfg `Corex' url `http://www.cardscan.com/' comment *none* model `Cardscan 500' interface `USB' usb-vendor-id `0x08f0' usb-product-id `0x0001' status unsupported url `/unsupported/corex-cardscan-500.html' comment `Probably not supported. Businesscard reader.' model `Cardscan 700 C' interface `USB' usb-vendor-id `0x08f0' usb-product-id `0x0004' status unsupported url `/unsupported/corex-cardscan-700.html' comment `Probably not supported.' mfg `Dell' url `http://www.dell.com/' comment *none* model `A940' interface `USB' usb-vendor-id `0x413c' usb-product-id `0x5106' status unsupported url *none* comment `Probably rebadged Lexmark X5150. May work with sane-lexmark? See bug #312130' model `A960' interface `USB' usb-vendor-id `0x413c' usb-product-id `0x5107' status unsupported url `/unsupported/dell-a960.html' comment `Probably not supported. See link for details.' model `922' interface `USB' usb-vendor-id `0x413c' usb-product-id `0x5109' status unsupported url `/unsupported/dell-922.html' comment `Probably not supported. See link for details.' mfg `Epson' url `http://www.epson.com/' comment *none* model `GT-2200' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0102' status unsupported url *none* comment `Probably unsupported. No details known.' model `StylusScan 2000' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x0105' status unsupported url *none* comment `Probably unsupported. No details known.' model `Stylus DX4450' interface `USB' usb-vendor-id `0x04b8' usb-product-id `0x083f' status unsupported url `/unsupported/epson-stylus-dx4450.html' comment `Probably unsupported. See link for details.' model `Stylus CX-5800' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably unsupported at the moment. Not compatible to snapscan backend. It's not known if it may work with epson or epkowa backend.' mfg `EDT (Electronic Document Technology)' url `http://www.bizcardreader.com/' comment *none* model `BizCardReader 900C' interface `USB' usb-vendor-id `0x0a53' usb-product-id `0x5001' status unsupported url `/unsupported/edt-900c.html' comment `Probably unsupported. See link for details.' mfg `E-Lux' url *none* comment `E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX' model `j-6121' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably unsupported. Sold 1998. Same as E-Lux j-6121.' mfg `Enhans' url *none* comment `E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX' model `j-6121' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably unsupported. Sold 1998. Same as E-Lux j-6121.' model `M-3630 A' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably unsupported. ' mfg `Genius' url `http://www.geniusnet.com.tw/' url `http://www.genius-kye.com/' comment *none* model `ColorPage CS' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/genius-colorpage-cs.html' comment `Probably unsupported, see link for details.' model `ColorPage-Slim 1200 USB2' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2020' status unsupported url `/unsupported/genius-colorpage-slim-1200-usb2.html' comment `GL841 based, to be added to genesys backend.' model `ColorPage HR6X Slim' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2019' status unsupported url `/unsupported/genius-colorpage-hr6x.html' comment `GL646 based, to be added to genesys backend' model `ColorPage HR7X' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x2018' status unsupported url `/unsupported/genius-colorpage-hr7x.html' comment `GL646 based, to be added to genesys backend' model `ColorPage HR7XE' interface `USB' usb-vendor-id `0x06dc' usb-product-id `0x0012' status unsupported url `/unsupported/genius-colorpage-hr7xe.html' comment `Unsuported. See link for details.' model `ColorPage HR8' interface `USB' usb-vendor-id `0x0458' usb-product-id `0x201c' status unsupported url `/unsupported/genius-colorpage-hr8.html' comment `GL841 based, to be added to genesys backend' mfg `Guillemot' url *none* comment *none* model `SCAN@HOME 48 USB' interface `USB' usb-vendor-id `0x080d' usb-product-id `0x0102' status unsupported url `/unsupported/teco-vm6509.html' comment `Probably unsupported. See link for details.' model `Maxi Scan A4 Parallel 36 bit' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably unsupported. Identical to the Benq Prisa 620P.' mfg `Hercules' url *none* comment *none* model `SCAN@HOME 48 USB' interface `USB' usb-vendor-id `0x080d' usb-product-id `0x0102' status unsupported url `/unsupported/teco-vm6509.html' comment `Probably unsupported. See link for details.' mfg `Hewlett-Packard' url `http://www.hp.com/' comment *none* model `Photo Scanner 1000' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1001' status unsupported url `/unsupported/hp-photo-1000.html' comment `Not supported by SANE. However, it's detected as mass storage device so just mounting it is reported to work. See link for device data.' model `Photosmart 1200 Photo' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported by SANE. No details known. 10x15 cm. Maybe similar to Photo Scanner 1000?' model `Photosmart S20 (C5101A)' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0102' status unsupported url `/unsupported/hp-photosmart-s20xi.html' comment `Not supported yet by SANE. See link for details.' model `Photosmart S20xi (C7150A)' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0102' status unsupported url `/unsupported/hp-photosmart-s20xi.html' comment `Not supported yet by SANE. See link for details.' model `Photosmart C5100 series' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x5811' status unsupported url `/unsupported/hp-photosmart-5100.html' comment `Not supported yet by SANE. See link for details.' model `ScanJet 2400c' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x0a01' status unsupported url `/unsupported/hp-scanjet-2400c.html' comment `GL646 based, to be added to genesys backend' model `Photosmart C3180' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x5611' status unsupported url `/unsupported/hp-photosmart-3180.html' comment `Not supported yet by SANE. See link for details.' model `ScanJet 3770' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x2505' status unsupported url *none* comment `While an external binary-only backend exists, it works only on Linux i386. Therefore the scanner is unsupported on other platforms.' model `ScanJet 4600' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x3005' status unsupported url `/unsupported/hp-scanjet-4600.html' comment `Not supported. See link for details, or http://www.chmil.org/hp4600linux/ for code' model `ScanJet 4670' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x3005' status unsupported url *none* comment `Not supported. See ScanJet 4600 entry.' model `ScanJet 4850C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1b05' status unsupported url `/unsupported/hp-scanjet-4850.html' comment `GL841, maybe can be added to genesys backend ' model `ScanJet 4890C' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1b05' status unsupported url `/unsupported/hp-scanjet-4850.html' comment `GL843, maybe can be added to genesys backend ' model `ScanJet 5530C Photosmart' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x1605' status unsupported url `/unsupported/hp-scanjet-5530.html' comment `Maybe GL841_HP, but not confirmed, maybe can be added to genesys backend' model `ScanJet 8390' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x3805' status unsupported url `/unsupported/hp-scanjet-8390.html' comment `Probably not supported. See link for details.' model `ScanJet G4000' interface `USB' usb-vendor-id `0x03f0' usb-product-id `0x4505' status unsupported url `/unsupported/hp-g4000.html' comment `Probably not supported. See link for details.' mfg `IBM' url `http://www.ibm.com' comment *none* model `ADF Color Scanner' interface `Proprietary' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Unsupported. Uses proprietary ISA card. Maybe the same as the Plustek Spectra ADF?' mfg `IOMagic' url `http://www.iomagic.com/' comment *none* model `MobileScan USB' interface `USB Parport' usb-vendor-id `0x05cb' usb-product-id `0x1483' status unsupported url `/unsupported/trust-combiscan-19200.html' comment `Unsupported. See link for details.' mfg `Iris' url `http://irislink.com/' comment *none* model `IriScan' interface `USB' usb-vendor-id `0x0a53' usb-product-id `0x1000' status unsupported url `/unsupported/iris-iriscan.html' comment `Unsupported. LM9832/3. See link for details.' model `IRISPen Translator Executive' interface `USB' usb-vendor-id `0x0f43' usb-product-id `0x015a' status unsupported url `/unsupported/iris-irispen-translator.html' comment `Unsupported. See link for details.' model `IRISCard Pro (IBCR II)' interface `USB' usb-vendor-id `0x0a38' usb-product-id `0x0301' status unsupported url `/unsupported/iris-business.html' comment `Unsupported. See link for details.' mfg `Kodak' url `http://www.kodak.com' comment *none* model `Snapshot Photo Scanner 1' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Unsupported. FCC ID HWF96PHS' mfg `Lexmark' url `http://www.lexmark.com/' comment *none* model `P6250' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0097' status unsupported url `/unsupported/lexmark-p6250.html' comment `Unsupported. See link for details.' model `Photo 3150' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x007d' status unsupported url `/unsupported/lexmark-3150.html' comment `Unsupported. See link for details.' model `X74' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0060' status unsupported url `/unsupported/lexmark-x75.html' comment `Unsupported. See link for details.' model `X75' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0060' status unsupported url `/unsupported/lexmark-x75.html' comment `Unsupported. See link for details.' model `X75 PrinTrio' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0060' status unsupported url `/unsupported/lexmark-x75.html' comment `Unsupported. See link for details.' model `X83' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x003d' status unsupported url `/unsupported/lexmark-x83.html' comment `Unsupported. GL640.' model `X2330' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x00bb' status unsupported url `/unsupported/lexmark-x2330.html' comment `Unsupported. See link for details.' model `X3450' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x00f6' status unsupported url `/unsupported/lexmark-x3450.html' comment `Unsupported. See link for details.' model `X5130' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0065' status unsupported url `/unsupported/lexmark-x5130.html' comment `Unsupported.' model `X5150' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0065' status unsupported url `/unsupported/lexmark-x5130.html' comment `Probably unsupported. See link for details.' model `X5250' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0093' status unsupported url `/unsupported/lexmark-x5250.html' comment `Unsupported.' model `X6170' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0072' status unsupported url `/unsupported/lexmark-x6170.html' comment `Unsupported. See link for details.' model `X7170' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x0098' status unsupported url *none* comment `Unsupported. See bug #310889 for details.' model `X7350' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x00b8' status unsupported url `/unsupported/lexmark-x7350.html' comment `Unsupported. See link for details.' model `X8350' interface `USB' usb-vendor-id `0x043d' usb-product-id `0x00b9' status unsupported url `/unsupported/lexmark-x8350.html' comment `Unsupported. See link for details.' mfg `Logitech' url *none* comment *none* model `PageScan Color' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Most probably unsupported.' model `PageScan USB' interface `USB' usb-vendor-id `0x046d' usb-product-id `0x040f' status unsupported url `/unsupported/logitech-pagescan-usb.html' comment `Probably unsupported. See link for details.' mfg `Medion/Lifetec/Tevion/Cytron' url `http://www.medion.com/' url `http://www.medion.de/' comment *none* model `MD 6190' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0392' status unsupported url `/unsupported/medion-md6190.html' comment `Probably unsupported. There seem to exist two different scanners with that name. See link for details.' model `MD 6190' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x037b' status unsupported url `/unsupported/medion-md6190.html' comment `Probably unsupported. There seem to exist two different scanners with that name. See link for details.' model `MD 40420' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x3008' status unsupported url `/unsupported/tevion-md40420.html' comment `Probably unsupported. See link for details.' model `MD 41260' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x037b' status unsupported url `/unsupported/medion-md6190.html' comment `Probably unsupported. See link for details.' model `MD 41985' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x037b' status unsupported url `/unsupported/medion-md6190.html' comment `Probably unsupported. See link for details.' model `MD 42666' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x3008' status unsupported url `/unsupported/tevion-md40420.html' comment `Probably unsupported. See link for details.' model `MD 85264' interface `USB' usb-vendor-id `0x08ff' usb-product-id `0x2580' status unsupported url `http://gkall.hobby.nl/authentec.html' comment `Fingerprint sensor. See link for details.' model `MD 90009' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30e5' status unsupported url `/unsupported/tevion-md90009.html' comment `Probably unsupported. See link for details.' model `MD 90070' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x3022' status unsupported url `/unsupported/tevion-md90070.html' comment `Unsupported. See link for details.' model `MD 90090' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x3022' status unsupported url `/unsupported/tevion-md90070.html' comment `Unsupported. See link for details.' mfg `Memorex' url `http://www.memorex.com/' comment *none* model `6136u' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0346' status unsupported url `/unsupported/memorex-maxx-6136u.html' comment `Probably unsupported.' model `6142u' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0347' status unsupported url `/unsupported/visioneer-onetouch4400.html' comment `Probably unsupported. Same as Visioneer Onetouch 4400. See link for details.' model `MaxxScan 6122' interface `USB Parport' usb-vendor-id `0x05cb' usb-product-id `0x1483' status unsupported url `/unsupported/trust-combiscan-19200.html' comment `Unsupported. See link for details.' model `SCF 9612P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/memorex-scf-9612p.html' comment `Probably unsupported. See link for details.' mfg `Microtek' url `http://www.microtek.com/' comment *none* model `ArtixScan 2020' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Unsupported. Same as Agfa DuoScan T2000XL?' model `ArtixScanDI 2020' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x202e' status unsupported url `/unsupported/microtek-artixscan-2020.html' comment `Unsupported. See link for details.' model `Artixscan 2500f' interface `SCSI IEEE-1384' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Unsupported. Same as Agfa DuoScan T2500?' model `ArtixScan 4000tf' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Unsupported. Uses ALI M5611B.' model `FilmScan 35' interface `USB' usb-vendor-id `0x05e3' usb-product-id `0x0120' status unsupported url `/unsupported/microtek-filmscan-35.html' comment `Probably unsupported. See link for details.' model `ScanMaker 336 CX' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably unsupported. Seems to be similar to the Microtek 330 CX and is detected by the microtek2 backend. Scanning doesn't seem to work however.' model `Scanmaker 1850S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/microtek-scanmaker-1850s.html' comment `Unsupported. See link for details.' model `ScanMaker 3630' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0347' status unsupported url `/unsupported/microtek-scanmaker-3630.html' comment `Unsupported. Doesn't seem to be compatible to 3600 series, see link.' model `ScanMaker 3800' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30ce' status unsupported url `/unsupported/microtek-scanmaker-3800.html' comment `Unsupported. See link for more details.' model `ScanMaker 3830' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30ce' status unsupported url `/unsupported/microtek-scanmaker-3830.html' comment `Unsupported. See link for more details.' model `ScanMaker 3860' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x3023' status unsupported url `/unsupported/microtek-scanmaker-3880.html' comment `Unsupported. See link for more details. Appears to be similar to ScanMaker 3880.' model `ScanMaker 3880' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x3021' status unsupported url `/unsupported/microtek-scanmaker-3880.html' comment `Unsupported. SQ113 chip. See link for more details.' model `ScanMaker 4600' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x40c7' status unsupported url `/unsupported/microtek-scanmaker-4600.html' comment `Unsupported. See link for more details.' model `ScanMaker 4700' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x20b4' status unsupported url `/unsupported/microtek-scanmaker-4700.html' comment `Unsupported. See link for more details.' model `ScanMaker 4850' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30d9' status unsupported url `/unsupported/microtek-scanmaker-4900.html' comment `Probably unsupported. See link for details.' model `ScanMaker 4850 II' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x3008' status unsupported url `/unsupported/microtek-scanmaker-4850-2.html' comment `Probably unsupported. See link for details.' model `ScanMaker 4900' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30b9' status unsupported url `/unsupported/microtek-scanmaker-4900.html' comment `Unsupported. See link for more details.' model `ScanMaker 5' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/microtek-scanmaker-5600.html' comment `Probably unsupported. See link for more details.' model `ScanMaker 5600' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x20a7' status unsupported url `/unsupported/microtek-scanmaker-5600.html' comment `Unsupported. See link for more details.' model `ScanMaker 5700' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x20bd' status unsupported url *none* comment `Unsupported. Uses ALI M5615 like the ScanMaker 4700.' model `ScanMaker 5800' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x3008' status unsupported url `/unsupported/microtek-scanmaker-5800.html' comment `Unsupported. See link for details.' model `ScanMaker 5800' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30d8' status unsupported url `/unsupported/microtek-scanmaker-5800.html' comment `Unsupported. See link for details.' model `ScanMaker 5900' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30d8' status unsupported url `/unsupported/microtek-scanmaker-5900.html' comment `Unsupported. See link for more details.' model `ScanMaker 5950' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30d8' status unsupported url `/unsupported/microtek-scanmaker-5950.html' comment `Unsupported. See link for more details.' model `ScanMaker 6000' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30e5' status unsupported url `/unsupported/microtek-scanmaker-6000.html' comment `Unsupported. See link for more details.' model `ScanMaker 6100' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30e5' status unsupported url `/unsupported/microtek-scanmaker-6100.html' comment `Unsupported. See link for more details.' model `ScanMaker 6700' interface `USB IEEE-1394' usb-vendor-id `0x05da' usb-product-id `0x20c9' status unsupported url `/unsupported/microtek-scanmaker-6700.html' comment `Unsupported. See link.' model `ScanMaker 8700' interface `USB IEEE-1394' usb-vendor-id `0x05da' usb-product-id `0x20b1' status unsupported url `/unsupported/microtek-scanmaker-8700.html' comment `Unsupported. See link for details. USB vendor and product ids to be checked.' model `ScanMaker 9600XL' interface `USB IEEE-1394' usb-vendor-id `0x05da' usb-product-id `0x20de' status unsupported url *none* comment `Probably unsupported. SCSI seems to work with microtek2 backend.' model `ScanMaker 9800XL' interface `USB SCSI' usb-vendor-id `0x05da' usb-product-id `0x20de' status unsupported url `/unsupported/microtek-scanmaker-9800.html' comment `Partly unsupported. IEEE-1394 works with microtek2 backend. See link.' model `ScanMaker i320' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x30e6' status unsupported url `/unsupported/microtek-scanmaker-i320.html' comment `Unsupported. See link.' model `ScanMaker s400' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x201c' status unsupported url `/unsupported/microtek-scanmaker-s400.html' comment `Unsupported. See link.' model `ScanMaker S400' interface `USB' usb-vendor-id `0x05da' usb-product-id `0x300b' status unsupported url `/unsupported/microtek-scanmaker-s400.html' comment `Unsupported. See link.' model `ScanPort 3000' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0224' status unsupported url `/unsupported/microtek-scanport-3000.html' comment `Unsupported. Vendor/Product ids: 0x04a7/0x0224. Realtek RTS8801B?. See link for details.' mfg `Konica Minolta' url `http://www.konicaminolta.com/' comment *none* model `Dual Scan III' interface `USB' usb-vendor-id `0x0686' usb-product-id `0x400d' status unsupported url `/unsupported/minolta-dual-scan-III.html' comment `Unsupported. May work with vuescan. See link for details.' model `Dual Scan IV' interface `USB' usb-vendor-id `0x132b' usb-product-id `0x000a' status unsupported url `/unsupported/minolta-dual-scan-IV.html' comment `Unsupported. Works with vuescan. See link for details.' model `DiMAGE Scan Elite 5400' interface `USB IEEE-1394' usb-vendor-id `0x0686' usb-product-id `0x400e' status unsupported url `/unsupported/minolta-dse-5400.html' comment `Probably unsupported. May work with vuescan. See link for details.' model `DiMAGE Scan Elite 5400 2' interface `USB' usb-vendor-id `0x132b' usb-product-id `0x0012' status unsupported url `/unsupported/minolta-dse-5400-2.html' comment `Probably unsupported. See link for details.' model `DiMAGE Scan Multi Pro' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/minolta-dimage-scan-multi-pro.html' comment `Probably unsupported. See link for details.' model `magicolor 2480MF' interface `USB Network' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Uses a different scanning protocol than the magicolor 1690MF' mfg `Mustek' url `http://www.mustek.com/' url `http://www.mustek.de/' url `http://www.mustek.com.tw/' comment *none* model `1200 III EP' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. quarlewm at jmu dot edu offers to temporarily loan such a scanner to anyone who is interested in writing a driver.' model `2400 M' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED' comment `Probably unsupported. No details known.' model `BearPaw 2400 TA Pro' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0400' status unsupported url `http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED' comment `Not supported. May be supported by mustek_usb2 backend later. See link for some information.' model `BearPaw 2448 CU Pro' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0408' status unsupported url `/unsupported/mustek-bearpaw-2448-cu-pro.html' comment `Not supported. May be supported by mustek_usb2 backend later. See link for some information.' model `BearPaw 4800 TA Pro' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x1000' status unsupported url `/unsupported/mustek-bearpaw-4800ta-pro.html' comment `Not supported. See link for some information.' model `BearPaw 4800 TA Pro II' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x040a' status unsupported url `/unsupported/mustek-bearpaw-4800ta-pro-ii.html' comment `Not supported. May be supported by mustek_usb2 backend later. See link for some information.' model `BearPaw 6400 TA Pro' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x040b' status unsupported url `http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED' comment `Not supported. May be supported by mustek_usb2 backend later. See link for some information.' model `Paragon 800 II EP' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Not supported. Maybe similar to 600 II EP (SCSI_over-parport)? In this case it could be supported by the mustek SCSI backend.' model `ScanExpress 600 USB' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0873' status unsupported url `http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED' comment `Unsupported. Programming information is available.' model `ScanExpress 1200 USB' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0003' status unsupported url `http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED' comment `Unsupported. Programming information is available.' model `ScanExpress 1200 USB Plus' interface `USB' usb-vendor-id `0x055f' usb-product-id `0x0007' status unsupported url `http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED' comment `Unsupported.' model `ScanExpress 12000 P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://penguin-breeder.org/?page=mustek_pp' comment `Not supported. Asic 1505/05.' model `ScanExpress A3 EP' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Not supported. Maybe it will be supported by the mustek_pp backend in future.' model `ScanExpress CardSmart' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.meier-geinitz.de/sane/misc/mustek-scanners.html#UNSUPPORTED' comment `Probably unsupported. USB business card scanner. Maybe works as USB storage device?' model `ScanMagic 9636P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://lists.alioth.debian.org/pipermail/sane-devel/2003-May/007682.html' comment `Probably not supported. Same as Mustek 12000 P?. ASIC 1505.' mfg `NEC' url `http://www.nevt.co.jp/' comment *none* model `Petiscan' interface `USB' usb-vendor-id `0x0475' usb-product-id `0x0100' status unsupported url `/unsupported/nec-petiscan.html' comment `Most probably unsupported. See link for details. Vendor ID is Relisys/Teco. Not known if it is similar to other Relisys/Teco USB scanners.' mfg `Nikon' url `http://www.nikon.com/' comment *none* model `LS-9000 ED' interface `IEEE-1394' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/nikon-ls9000-ed.html' comment `Probably not supported. See link for details. Possibly similar to LS-8000 ED.' mfg `Olivetti' url `http://www.olivetti.com' comment *none* model `Job-Jet M400' interface `USB' usb-vendor-id `0x0b3c' usb-product-id `0xa880' status unsupported url `/unsupported/olivetti-job-jet-m400.html' comment `Probably not supported. See link for details.' mfg `Olympus' url `http://www.olympus.com' comment *none* model `ES-10P' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://lists.alioth.debian.org/pipermail/sane-devel/2008-December/023326.html' comment *none* model `ES-10S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/olympus-es10s.html' comment `Probably not supported. See link for details.' mfg `Optoelectronics' url *none* comment *none* model `Barcode scanner' interface `USB' usb-vendor-id `0x065a' usb-product-id `0x0001' status unsupported url *none* comment `Probably not supported.' mfg `Optrox' url *none* comment *none* model `PhotoMaker 3C' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.df.lth.se/~triad/krad/optrox/' comment *none* model `PhotoMaker 3E' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.df.lth.se/~triad/krad/optrox/' comment *none* model `PhotoMaker 3F' interface `Proprietary' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.df.lth.se/~triad/krad/optrox/' comment `Special ISA card' model `PhotoMaker 3S' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.df.lth.se/~triad/krad/optrox/' comment *none* model `PhotoMaker 6E' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.df.lth.se/~triad/krad/optrox/' comment *none* model `PhotoMaker 6F' interface `Proprietary' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.df.lth.se/~triad/krad/optrox/' comment `Special ISA card' mfg `Panasonic' url *none* comment *none* model `KV-SS905C' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool.' model `KV-S2055W' interface `USB SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S2055L' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S2065W' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S3065CW' interface `USB SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S3065CL' interface `USB SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S3085' interface `USB SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S3105C' interface `USB SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool.' model `KV-S6040W' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S6045W' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S6050W' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S6055W' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' model `KV-S7065C' interface `USB SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `might be supported by matsushita backend.' mfg `Pentax' url *none* comment *none* model `DSmobile USB' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x2000' status unsupported url `/unsupported/syscan-travelscan-pro.html' comment `Probably not supported. Some information is available.' mfg `PIE' url `http://www.scanace.com/' comment `Pacific Image Electronics' model `Primefilm 1800u' interface `USB' usb-vendor-id `0x05e3' usb-product-id `0x0120' status unsupported url `/unsupported/pie-1800u.html' comment `Not supported. See link for details.' model `Primefilm 2700' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://lists.alioth.debian.org/pipermail/sane-devel/2009-January/023442.html' comment *none* model `Primefilm 3600PRO' interface `USB IEEE-1394' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. ' model `Powerslide 3600' interface `USB IEEE-1394' usb-vendor-id `0x05e3' usb-product-id `0x0142' status unsupported url `/unsupported/reflecta-digitdia-3600.html' comment `Probably unsupported. Film scanner that can scan directly from the magazine.' model `PF3650 Pro3 Film Scanner' interface `USB IEEE-1394' usb-vendor-id `0x05e3' usb-product-id `0x0143' status unsupported url `/unsupported/pie-pf3650.html' comment `Not supported. See link for details.' mfg `Plustek' url `http://www.plustek.de/' url `http://www.plustek.com/' comment *none* model `OpticFilm 7200' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0807' status unsupported url `/unsupported/plustek-opticfilm-7200.html' comment `GL842 based, maybe to be added to genesys backend' model `OpticFilm 7200i' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0c04' status unsupported url *none* comment `GL843 based, maybe to be added to genesys backend' model `OpticPro A3U' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Uses Plustek ASIC P99002' model `OpticPro S6' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Uses RealTek chipset (RTL8801D)' model `OpticPro S12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0600' status unsupported url `/unsupported/plustek-opticpro-st12.html' comment `Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend.' model `OpticPro ST12' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0600' status unsupported url `/unsupported/plustek-opticpro-st12.html' comment `Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend.' model `OpticPro ST16' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0600' status unsupported url `/unsupported/plustek-opticpro-st16.html' comment `GL646 based, to be added to genesys backend' model `OpticPro UA18' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably LM983x based.' model `OpticPro S24' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0601' status unsupported url `/unsupported/plustek-opticpro-st24.html' comment `Product id 0x0601 is unsupported but may be supported by the genesys backend in future /GL646). Product id 0x040e is supported by the gt68xx backend.' model `OpticPro ST24' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0601' status unsupported url `/unsupported/plustek-opticpro-st24.html' comment `GL646 based, to be added to genesys backend' model `OpticPro S28' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0801' status unsupported url `/unsupported/plustek-opticpro-s28.html' comment `GL841 based, to be added to genesys backend' model `OpticPro ST28' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0801' status unsupported url `/unsupported/plustek-opticpro-s28.html' comment `GL841 based, to be added to genesys backend' model `OpticPro ST28' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0802' status unsupported url `/unsupported/plustek-opticpro-st28.html' comment `GL841 based, to be added to genesys backend' model `Umax AstraScan 4750' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0802' status unsupported url `/unsupported/umax-astrscan-4750.html' comment `GL841 based, to be added to genesys backend, rebadged Plustek ST28' model `OpticPro ST48' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0800' status unsupported url `/unsupported/plustek-opticpro-st48.html' comment `GL841 based, to be added to genesys backend' model `OpticPro ST64' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0c00' status unsupported url `/unsupported/plustek-opticpro-st64.html' comment `GL843 based, maybe to be added to genesys backend' model `OpticPro ST64+' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0c03' status unsupported url `/unsupported/plustek-opticpro-st64plus.html' comment `GL843 based. See link for more details.' model `PL 806' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0c0c' status unsupported url `/unsupported/plustek-pl806.html' comment `Unsupported. See link for more details.' model `SmartOffice PL 812' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0c0d' status unsupported url `/unsupported/plustek-pl812.html' comment `Unsupported. See link for more details.' model `OpticSlim 500' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0458' status unsupported url `/unsupported/plustek-opticslim-500.html' comment `Unsupported. See link for more details.' model `OpticSlim 2420' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0806' status unsupported url `/unsupported/plustek-opticslim-2420.html' comment `GL841 based, to be added to genesys backend' model `OpticSlim 2420+' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0914' status unsupported url `/unsupported/plustek-opticslim-2420plus.html' comment `GL841 based, to be added to genesys backend' model `OpticWorks 2000' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Multifunction device. No further information available.' model `OptiCard 600+' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Business card reader. No further information available.' model `ScanCopy 115' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x081c' status unsupported url `/unsupported/plustek-scancopy-115.html' comment `GL841 based, to be added to genesys backend' model `Spectra ADF' interface `Proprietary' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Unsupported. Uses proprietary ISA card that also provides power and is labelled GPS-1 PAGE-A from Taiwan. Other labels on the scanner include ADF Color Scanner and SF600AS. Maybe the same as the IBM ADF Color Scanner?' model `Unknown Plustek Device' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0005' status unsupported url *none* comment `Probably unsupported. Scanner name not known yet.' model `Unknown Plustek Device' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0007' status unsupported url *none* comment `Probably unsupported. Scanner name not known yet.' model `Unknown Plustek Device' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x000f' status unsupported url *none* comment `Probably unsupported. Scanner name not known yet.' model `Unknown Plustek Device' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0012' status unsupported url *none* comment `Probably unsupported. Scanner name not known yet.' model `Unknown Plustek Device' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0014' status unsupported url *none* comment `Probably unsupported. Scanner name not known yet.' model `Unknown Plustek Device' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0016' status unsupported url *none* comment `Probably unsupported. Scanner name not known yet.' mfg `PLANon' url `http://www.planon.com/' comment *none* model `DocuPen RC800' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. No details known.' model `DocuPen R700' interface `USB' usb-vendor-id `0x10c4' usb-product-id `0xea60' status unsupported url `/unsupported/planon-docupen-r700.html' comment `Probably not supported. See link for details.' model `DocuPen (DPEN-BW)' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. No details known.' mfg `Primax' url `http://www.primax.nl/' comment *none* model `Colorado 600U' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0341' status unsupported url `/unsupported/primax-colorado-600u.html' comment `Not supported. Some information is available.' model `Colorado 1200p' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://home2.swipnet.se/~w-25069/pxscan.html' comment `Unsupported by SANE. But is reported to partly work with pxscan. See link.' model `Colorado 1200u' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0361' status unsupported url *none* comment `Probably unsupported. No details known.' model `Primascan Colorado 2600u' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0347' status unsupported url `/unsupported/visioneer-onetouch4400.html' comment `Unsupported. Same as Visioneer Onetouch 4400. See link for details.' model `Colorado Direct 600' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://home2.swipnet.se/~w-25069/pxscan.html' comment `Not supported. However, a stand-alone program is available.' model `Colorado Direct 9600' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://home2.swipnet.se/~w-25069/pxscan.html' comment `Not supported. However, a stand-alone program is available.' model `Colorado USB 9600' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0340' status unsupported url `/unsupported/primax-colorado-usb-9600.html' comment `Not supported. See link for details.' model `G2-300' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0300' status unsupported url *none* comment `Probably unsupported. No details known.' model `G2-300 #2' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0302' status unsupported url *none* comment `Probably unsupported. No details known.' model `G2E-300' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0301' status unsupported url *none* comment `Probably unsupported. No details known.' model `G2E-300 #2' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0303' status unsupported url *none* comment `Probably unsupported. No details known.' model `G2-600' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0380' status unsupported url *none* comment `Probably unsupported. No details known.' model `G2-600 #2' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0382' status unsupported url *none* comment `Probably unsupported. No details known.' model `G2E-600' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0383' status unsupported url *none* comment `Probably unsupported. No details known.' model `OneTouch 5300' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Not supported.' model `ReadyScan 636i' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0381' status unsupported url *none* comment `Probably unsupported. No details known.' model `Slim-Line 1200' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Maybe GL646. Maybe similar to Medion MD 6228?' model `Onetouch 8920' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0371' status unsupported url `/unsupported/visioneer-onetouch8920.html' comment `Not supported. Look similar to Visioneer Onetouch 8920 (same USB product id).' mfg `Prolink' url `http://www.fida.com/' comment *none* model `Winscan Pro 2448U' interface `USB' usb-vendor-id `0x06dc' usb-product-id `0x0014' status unsupported url `/unsupported/prolink-2448u.html' comment `Not supported. Some information is available. RealTek RTS8801.' model `Winscan Pro 2000' interface `USB Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Not supported. No further information available.' mfg `Quato' url `http://www.quato.de/' comment *none* model `X-Finity' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. No details yet. Originally manufactured by PFU?' model `X-Finity Ultra' interface `USB IEEE-1394' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. No details yet.' mfg `Reflecta' url *none* comment *none* model `DigitDia 3600' interface `USB IEEE-1394' usb-vendor-id `0x05e3' usb-product-id `0x0142' status unsupported url `/unsupported/reflecta-digitdia-3600.html' comment `Film scanner that can scan directly from the magazine.' model `iScan 1800' interface `USB' usb-vendor-id `0x05e3' usb-product-id `0x0120' status unsupported url `/unsupported/reflecta-iscan-1800.html' comment `Probably unsupported. See link for details.' model `ProScan 4000' interface `USB IEEE-1394' usb-vendor-id `0x05e3' usb-product-id `0x0143' status unsupported url `/unsupported/reflecta-proscan-4000.html' comment `Probably unsupported. See link for details.' mfg `Relisys' url *none* comment *none* model `Eclipse 1200U' interface `USB' usb-vendor-id `0x0475' usb-product-id `0x0103' status unsupported url `/unsupported/relisys-eclipse-1200u.html' comment `Probably unsupported. See link for details.' model `Scorpio Ultra 3' interface `USB' usb-vendor-id `0x0475' usb-product-id `0x0210' status unsupported url `/unsupported/relisys-scorpio-ultra3.html' comment `Probably unsupported. See link for details.' model `Episode' interface `USB' usb-vendor-id `0x0475' usb-product-id `0x0103' status unsupported url `/unsupported/relisys-episode.html' comment `Probably unsupported. See link for details.' model `AVEC II E3' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Parport version of AVEC II S3?. See bug #304992 for details' mfg `Samsung' url *none* comment *none* model `SCX-4725FN' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x341f' status unsupported url `/unsupported/samsung-scx-4725.html' comment `Not supported. See link for details.' mfg `Scanshell' url *none* comment *none* model `800N' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x6605' status unsupported url `/unsupported/scanshell-800n.html' comment `Not supported. See link for details.' mfg `Sicos' url *none* comment *none* model `DMS 2000' interface `proprietary' usb-vendor-id *none* usb-product-id *none* status unsupported url `mailto:ehaase@inf.fu-berlin.de' comment `Not supported until now. Work on a backend has started, contact the author for details (see link)' mfg `Siemens' url `http://www.siemens.com/' comment *none* model `ID Mouse Professional' interface `USB' usb-vendor-id `0x0681' usb-product-id `0x0005' status unsupported url *none* comment `Not supported.' model `Cherry FingerTIP ID Board - Sensor' interface `USB' usb-vendor-id `0x0681' usb-product-id `0x0010' status unsupported url *none* comment `Not supported.' mfg `SmartDisk' url *none* comment *none* model `SmartScan 3600' interface `USB IEEE-1394' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. Same as PIE Primefilm 2600 PRO.' mfg `Spot Technology' url *none* comment `Spot seems have gone out of business.' model `Maxiscan A4' interface `proprietary' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.el-profesor.net/spoonset/' comment `Not supported until now. Work on a backend has started, see link for more information.' model `ScanTak 2c' interface `proprietary' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.el-profesor.net/spoonset' comment `Not supported. Work on a backend has started, see link for more information.' model `ScanTak 3c' interface `proprietary' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.el-profesor.net/spoonset' comment `Not supported. Work on a backend has started, see link for more information.' mfg `Syscan' url *none* comment *none* model `TravelScan FS-531' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x0530' status unsupported url `/unsupported/syscan-travelscan-fs531.html' comment `Not supported. May work with the Plustek backend in future. See link for details.' model `TravelScan Pro' interface `USB' usb-vendor-id `0x0a82' usb-product-id `0x2000' status unsupported url `/unsupported/syscan-travelscan-pro.html' comment `Probably not supported. Some information is available.' mfg `Tamarack' url *none* comment *none* model `Artiscan 9600' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.autistici.org/tamarhack/' comment `Unsupported at the moment. See link for a project for that scanner taht may support it in future.' model `Artiscan 9600 pro 36' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://www.autistici.org/tamarhack/' comment `Unsupported at the moment. See link for a project for that scanner.' model `Artiscan 2400FS' interface `USB' usb-vendor-id `0x05e3' usb-product-id `0x0100' status unsupported url `/unsupported/tamarack-artiscan-2400.html' comment `Unsupported. See link for more information.' mfg `TCE' url `http://www.tce.com.br/' comment `Brasilian vendor.' model `MK600U' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0346' status unsupported url `/unsupported/memorex-maxx-6136u.html' comment `Not supported. Some information is available.' model `S450' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://home2.swipnet.se/~w-25069/pxscan.html' comment `Not supported by SANE but is reported to work with pxscan (see link).' mfg `Teco' url `http://www.tecoimage.com.tw/' comment *none* model `VM6509F' interface `USB' usb-vendor-id `0x080d' usb-product-id `0x0102' status unsupported url `/unsupported/teco-vm6509.html' comment `Probably unsupported. See link for details.' mfg `Tiny' url *none* comment *none* model `FU661E' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0347' status unsupported url `/unsupported/visioneer-onetouch4400.html' comment `Unsupported. See link for details.' mfg `Trust' url `http://www.trust-site.com' comment *none* model `CombiScan 19200' interface `Parport USB' usb-vendor-id `0x05cb' usb-product-id `0x1483' status unsupported url `/unsupported/trust-combiscan-19200.html' comment `Unsupported. See link for details.' model `EasyScan 19200' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `http://lists.alioth.debian.org/pipermail/sane-devel/2008-October/022955.html' comment *none* model `SCSI Scan 19200 -Excellence Series-' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/trust-scsi-scan-19200.html' comment `Unsupported. See link for details.' mfg `UMAX' url `http://www.umax.com/' comment *none* model `Astra 2500' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0374' status unsupported url `/unsupported/umax-astra-2500.html' comment `Probably not supported. See link for details.' model `Astra 2850' interface `USB' usb-vendor-id `0x07b3' usb-product-id `0x0601' status unsupported url `/unsupported/plustek-opticpro-st24.html' comment `Probably not supported. Same IDs as Plustek OpticPro ST24. See link for details.' model `Astra 3000' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x038a' status unsupported url `/unsupported/umax-astra-3000.html' comment `Probably not supported. See link for details.' model `Astra 3600' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x038a' status unsupported url `/unsupported/umax-astra-3600.html' comment `Probably not supported. See link for details.' model `Astra 4000' interface `USB' usb-vendor-id `0x1606' usb-product-id `0x1030' status unsupported url `/unsupported/umax-astra-4000.html' comment `Not supported. See link for details.' model `Astra 4100' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x038c' status unsupported url `/unsupported/umax-astra-4100.html' comment `Not supported, to be added to genesys backend.' model `Astra 4500' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a10' status unsupported url `/unsupported/umax-astra-4500.html' comment `GL646 based, to be added to genesys backend. Avision iVina FB1600 clone' model `Astra 4600' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported, no details known.' model `Astra 4700' interface `USB' usb-vendor-id `0x0638' usb-product-id `0x0a20' status unsupported url `/unsupported/umax-astra-4700.html' comment `GL646/GL660 based. Avision iVina FB1800 clone.' model `Astra 6700' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Not supported. No chipset information available. Same as Avision iVina FB2400.' model `AstraSlim' interface `USB' usb-vendor-id `0x080d' usb-product-id `0x0104' status unsupported url `/unsupported/umax-astraslim.html' comment `Probably not supported currently. See link for more details.' model `AstraSlim 1200' interface `USB' usb-vendor-id `0x080d' usb-product-id `0x0110' status unsupported url `/unsupported/umax-astraslim-1200.html' comment `See link for more details.' model `AstraSlim 6000' interface `USB' usb-vendor-id `0x080d' usb-product-id `0x0104' status unsupported url `/unsupported/umax-astraslim-6000.html' comment `Probably not supported currently. See link for more details.' model `Nete3470'' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. No details known..' model `Powerlook 180' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/umax-powerlook-180.html' comment `Probably not supported. See link for details.' model `Powerlook 1000 USB' interface `USB' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Probably not supported. No further information available.' mfg `Vantas' url *none* comment *none* model `3000' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0224' status unsupported url `/unsupported/visioneer-onetouch4800.html' comment `Not supported. See link for more details.' mfg `Visioneer' url `http://www.visioneer.com/' comment *none* model `6200' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0345' status unsupported url *none* comment `Not supported. Is reported to use the E5 chipset. Uses a Primax ID. Looks similar to Primascan Colorado 2600u.' model `6200 EPP/USB' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0311' status unsupported url *none* comment `Not supported. Id is from Primax? Yet another scanner with the same name?' model `9420' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x03a8' status unsupported url `/unsupported/visioneer-9420.html' comment `Unsupported. See link for details.' model `9450 USB' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0421' status unsupported url `/unsupported/visioneer-9450-usb.html' comment `Unsupported. See link for details.' model `Onetouch 4400' interface `USB' usb-vendor-id `0x0461' usb-product-id `0x0347' status unsupported url `/unsupported/visioneer-onetouch4400.html' comment `Not supported. E5 chipset? See link for more details.' model `OneTouch 4800 USB' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0224' status unsupported url `/unsupported/visioneer-onetouch4800.html' comment `Unsupported. Seems to use Realtek RTS8801B. Same as Microtek Scanport 3000. See link for details.' model `OneTouch 5300 USB' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0226' status unsupported url `/unsupported/visioneer-onetouch5300.html' comment `Not supported. Chipset is RTS8801B(?). See link for output of /proc/bus/usb/devices.' model `OneTouch 5300' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0221' status unsupported url *none* comment `Not supported. Yet another scanner with this name?' model `OneTouch 5800 USB' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0226' status unsupported url `/unsupported/visioneer-onetouch5800.html' comment `Unsupported. 48 bit scanner, doesn't work with viceo backend. RTS8801C.' model `OneTouch 6600' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x022a' status unsupported url `/unsupported/visioneer-onetouch6600.html' comment `Unsupported. See link for details.' model `Onetouch 7100' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0229' status unsupported url `/unsupported/visioneer-onetouch7100.html' comment `GL646 based, to be added to genesys backend' model `Onetouch 7700' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0380' status unsupported url `/unsupported/visioneer-onetouch7700.html' comment `LM9832/3 based, to be added to plustek backend' model `OneTouch 8100' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0321' status unsupported url `/unsupported/visioneer-onetouch8100.html' comment `Unsupported. See link for details.' model `Onetouch 8700' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0371' status unsupported url `/unsupported/visioneer-onetouch8920.html' comment `Not supported. See link for details.' model `Onetouch 8900' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0371' status unsupported url `/unsupported/visioneer-onetouch8920.html' comment `Not supported. Same as 8920 but without TA?' model `Onetouch 8920' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0371' status unsupported url `/unsupported/visioneer-onetouch8920.html' comment `Not supported. Same as 8700 and 8900 but includes a TA. Uses a Primax ID. Chipset is RTS8801C. See link for output of /proc/bus/usb/devices.' model `Onetouch 9000' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x022c' status unsupported url `/unsupported/visioneer-onetouch9020.html' comment `Not supported. See link for details.' model `Onetouch 9020' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x022c' status unsupported url `/unsupported/visioneer-onetouch9020.html' comment `Not supported. See link for details.' model `Onetouch 9320' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0362' status unsupported url `/unsupported/visioneer-onetouch9320.html' comment `Probably not supported. See link for details.' model `Onetouch Pro 8800' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0410' status unsupported url `/unsupported/visioneer-onetouch8820.html' comment `Probably not supported. See link for details.' model `Onetouch Pro 8820' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0410' status unsupported url `/unsupported/visioneer-onetouch8820.html' comment `Probably not supported. See link for details.' model `PaperPort 3100b' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/visioneer-paperport-3100b.html' comment `Most probably not supported. See link for details.' model `PaperPort 6100' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url *none* comment `Most probably not supported. More details would be appreciated.' model `PaperPort OneTouch' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/visioneer-paperport-onetouch.html' comment `Most probably not supported. See link for details.' model `Strobe Pro USB' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0102' status unsupported url `/unsupported/visioneer-strobe-pro-usb.html' comment `Not supported. See link for details.' model `4800 One Touch' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x03a0' status unsupported url `/unsupported/xerox-4800-onetouch.html' comment `Unsupported. See link for details. Different id compared to One Touch 4800?' model `DocuImage 620S' interface `SCSI' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/xerox-docuimage-620s.html' comment `Not supported. See link for more details.' model `DocuMate 510' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0446' status unsupported url `/unsupported/xerox-documate-510.html' comment `Not supported. See link for more details.' model `DocuMate 510' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x047c' status unsupported url `/unsupported/xerox-documate-510.html' comment `Not supported. See link for more details. Yet another USB id.' model `One Touch 4800' interface `USB' usb-vendor-id `0x04a7' usb-product-id `0x0224' status unsupported url `/unsupported/visioneer-onetouch4800.html' comment `Unsupported. See link for details. Different id compared to 4800 One Touch?' model `WorkCentre 470cx' interface `Parport' usb-vendor-id *none* usb-product-id *none* status unsupported url `/unsupported/xerox-workcentre-470cx.html' comment `Not supported. See link for more details.' model `WorkCentre M15i' interface `USB' usb-vendor-id `0x0924' usb-product-id `0xffef' status unsupported url `/unsupported/xerox-workcentre-m15i.html' comment `Not supported. See link for more details.' model `WorkCentre XK35c' interface `USB Parport' usb-vendor-id `0x043d' usb-product-id `0x0020' status unsupported url `/unsupported/xerox-workcentre-xk35c.html' comment `Not supported. See link for more details.' model `WorkCentre XK50cx' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3903' status unsupported url `/unsupported/xerox-workcentre-xk50cx.html' comment `Not supported. See link for more details.' model `WorkCentre Pro 412' interface `USB Parport' usb-vendor-id `0x043d' usb-product-id `0x4303' status unsupported url `/unsupported/xerox-workcentre-pro412.html' comment `Not supported. See link for more details.' model `WorkCentre PE16' interface `USB Parport' usb-vendor-id `0x0924' usb-product-id `0x4220' status unsupported url `/unsupported/xerox-workcentre-pe16.html' comment `Not supported. See link for more details.' model `WorkCentre PE120i' interface `USB' usb-vendor-id `0x0924' usb-product-id `0x4237' status unsupported url `/unsupported/xerox-workcentre-pe120i.html' comment `Not supported. See link for more details.' type vidcam mfg `Biolux' url *none* comment *none* model `654 (micrOcular)' interface `USB' usb-vendor-id `0x0923' usb-product-id `0x010f' status unsupported url `/unsupported/biolux-654.html' comment `Not supported yet. See link for more details.' mfg `Grandtek Scopecam' url *none* comment *none* model `8x30 Binocular & Digital Camera' interface `USB' usb-vendor-id `0x0797' usb-product-id `0x801c' status unsupported url `/unsupported/grandtech-scopecam.html' comment `Not Supported yet. See link for more details.' backend `v4l' version `1.0-3' manpage `sane-v4l' url `mailto:henning@meier-geinitz.de' comment *none* type api desc `Interface to Video For Linux API' url *none* comment `Supports video cameras and other devices accessed by the v4l kernel API, e.g. bttv devices. Quite a lot of known bugs.' backend `xerox_mfp' version `1.0-13' manpage `sane-xerox_mfp' url *none* comment *none* type scanner mfg `Xerox' url `http://www.office.xerox.com/' comment *none* model `Phaser 6110MFP' interface `USB' usb-vendor-id `0x0924' usb-product-id `0x3d5d' status good url *none* comment *none* model `Phaser 3200MFP' interface `USB' usb-vendor-id `0x0924' usb-product-id `0x3da4' status complete url `http://www.office.xerox.com/multifunction-printer/multifunction-under-30ppm/phaser-3200mfp/spec-enus.html' comment *none* model `WorkCentre 3119 Series' interface `USB' usb-vendor-id `0x0924' usb-product-id `0x4265' status good url *none* comment *none* model `WorkCentre 4118 Series' interface `USB' usb-vendor-id `0x0924' usb-product-id `0x420c' status good url *none* comment *none* model `WorkCentre 3210' interface `USB' usb-vendor-id `0x0924' usb-product-id `0x4293' status good url *none* comment *none* model `WorkCentre 3220' interface `USB' usb-vendor-id `0x0924' usb-product-id `0x4294' status good url *none* comment *none* mfg `Dell' url `http://www.dell.com/' comment *none* model `Dell MFP Laser Printer 1815dn' interface `USB' usb-vendor-id `0x413c' usb-product-id `0x5124' status good url *none* comment *none* mfg `Samsung' url `http://www.samsung.com' comment *none* model `SCX-4x16' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3409' status untested url *none* comment *none* model `SCX-6x20' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x340d' status untested url *none* comment *none* model `MFP-560' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x340e' status untested url *none* comment *none* model `MFP-750' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x340f' status untested url *none* comment *none* model `SCX-4x20' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3412' status untested url *none* comment *none* model `SCX-4100' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3413' status good url *none* comment *none* model `SCX-4x21' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3419' status untested url *none* comment *none* model `SCX-5x30' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x341a' status untested url *none* comment *none* model `SCX-4200' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x341b' status good url *none* comment *none* model `CLX-3160' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x341c' status untested url *none* comment *none* model `SCX-6x22' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x341d' status untested url *none* comment *none* model `SCX4725' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x341f' status untested url *none* comment *none* model `SCX4725-FN' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x341f' status good url *none* comment *none* model `SCX-6x45' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3420' status untested url *none* comment *none* model `CLX-8380' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3421' status untested url *none* comment *none* model `CLX-2160' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3425' status good url *none* comment *none* model `SCX-4500' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3426' status good url *none* comment *none* model `CLX-6200' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3427' status untested url *none* comment *none* model `CLX-6240' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3428' status untested url *none* comment *none* model `SCX-6x55' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3429' status untested url *none* comment *none* model `CLX-3170fn (CLX-3170 Series)' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x342a' status good url *none* comment *none* model `CLX-3175FW' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x342a' status good url *none* comment *none* model `SCX-4500W' interface `USB Ethernet' usb-vendor-id `0x04e8' usb-product-id `0x342b' status basic url *none* comment *none* model `SCX-4824 (SCX-4x24 Series)' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x342c' status good url *none* comment *none* model `SCX-4828FN (SCX-4x28 Series)' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x342d' status good url *none* comment *none* model `SCX-4300' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x342e' status good url *none* comment *none* model `SCX-5835_5935' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x342f' status good url *none* comment *none* model `SCX-5635' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3430' status untested url *none* comment *none* model `SCX-4x26' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3432' status untested url *none* comment *none* model `SCX-4600' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3433' status good url *none* comment *none* model `SCX-4623' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3434' status good url *none* comment *none* model `MFP-65x' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3435' status untested url *none* comment *none* model `SCX-6545' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3437' status untested url *none* comment *none* model `CLX-8385' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3439' status untested url *none* comment *none* model `CLX-6220' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x343a' status good url *none* comment *none* model `CLX-6250' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x343b' status untested url *none* comment *none* model `SCX-4825FN (SCX-4x25 Series)' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x343c' status good url *none* comment *none* model `CLX-3185' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x343d' status good url *none* comment *none* model `CLX-8540' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x343f' status untested url *none* comment *none* model `SCX-4623FW' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3440' status good url *none* comment *none* model `SCX-3205W (SCX-3200 Series)' interface `USB Ethernet' usb-vendor-id `0x04e8' usb-product-id `0x3441' status good url *none* comment *none* model `SCX-6545X' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3442' status untested url *none* comment *none* model `SCX-6x55X' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3443' status untested url *none* comment *none* model `CLX-8385X' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3444' status untested url *none* comment *none* model `SCX-5835_5935X' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3446' status good url *none* comment *none* model `SCX-4833FD' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x344b' status good url *none* comment *none* model `SCX-4835FD' interface `Ethernet' usb-vendor-id `0x04e8' usb-product-id `0x344b' status good url *none* comment *none* model `SCX-3405W' interface `Ethernet' usb-vendor-id *none* usb-product-id *none* status basic url *none* comment *none* model `SCX-3400' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x344f' status untested url *none* comment *none* model `SF-760' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3450' status untested url *none* comment *none* model `SCX-4729FD' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3453' status basic url *none* comment *none* model `CLX-6260' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3455' status minimal url *none* comment *none* model `CLX-3300 Series' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3456' status basic url *none* comment *none* model `SCX-470x' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3457' status untested url *none* comment *none* model `CLX-4190' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x345a' status minimal url *none* comment *none* model `SCX-4650 4x21S Series' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x345b' status untested url *none* comment *none* model `M337x 387x 407x Series' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3460' status untested url *none* comment *none* model `M267x 287x Series' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3461' status untested url *none* comment *none* model `SCX-681x' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3466' status untested url *none* comment *none* model `C460' interface `USB' usb-vendor-id `0x04e8' usb-product-id `0x3468' status untested url *none* comment *none* sane-backends-1.0.27/testsuite/tools/data/udev+acl.ref0000664000175000017500000023200512775312262017531 00000000000000# This file was automatically created based on description files (*.desc) # by sane-desc 3.5 from sane-backends 1.0.24git on Wed Jul 31 07:52:49 2013 # # udev rules file for supported USB and SCSI devices # # The SCSI device support is very basic and includes only # scanners that mark themselves as type "scanner" or # SCSI-scanners from HP and other vendors that are entitled "processor" # but are treated accordingly. # # To add a USB device, add a rule to the list below between the # LABEL="libsane_usb_rules_begin" and LABEL="libsane_usb_rules_end" lines. # # To run a script when your device is plugged in, add RUN+="/path/to/script" # to the appropriate rule. # # If your scanner isn't listed below, you can add it as explained above. # # If your scanner is supported by some external backend (brother, epkowa, # hpaio, etc) please ask the author of the backend to provide proper # device detection support for your OS # # If the scanner is supported by sane-backends, please mail the entry to # the sane-devel mailing list (sane-devel@lists.alioth.debian.org). # ACTION!="add", GOTO="libsane_rules_end" ENV{DEVTYPE}=="usb_device", GOTO="libsane_create_usb_dev" SUBSYSTEMS=="scsi", GOTO="libsane_scsi_rules_begin" SUBSYSTEM=="usb_device", GOTO="libsane_usb_rules_begin" SUBSYSTEM!="usb_device", GOTO="libsane_usb_rules_end" # Kernel >= 2.6.22 jumps here LABEL="libsane_create_usb_dev" # For Linux >= 2.6.22 without CONFIG_USB_DEVICE_CLASS=y # If the following rule does not exist on your system yet, uncomment it # ENV{DEVTYPE}=="usb_device", MODE="0664", OWNER="root", GROUP="root" # Kernel < 2.6.22 jumps here LABEL="libsane_usb_rules_begin" # Hewlett-Packard ScanJet 4100C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0101", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4200C | Hewlett-Packard ScanJet 4200Cxi | Hewlett-Packard ScanJet 4200Cse ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0105", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6200C | Hewlett-Packard ScanJet 6250C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0201", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3300c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0205", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4300c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0305", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5200C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0401", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3400c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0405", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 2100C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0505", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6300C | Hewlett-Packard ScanJet 6350C | Hewlett-Packard ScanJet 6390C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0601", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 2200C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0605", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5300C | Hewlett-Packard ScanJet 5370C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0701", ENV{libsane_matched}="yes" # Hewlett-Packard scanjet 4400c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0705", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 7400c | Hewlett-Packard ScanJet 7450c | Hewlett-Packard ScanJet 7490c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0801", ENV{libsane_matched}="yes" # Hewlett-Packard scanjet 4470c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0805", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 2300C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0901", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 2400C | Hewlett-Packard ScanJet G2410 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0a01", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 8200 | Hewlett-Packard ScanJet 8250 | Hewlett-Packard ScanJet 8290 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0b01", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5400c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1005", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5470c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1105", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4500C | Hewlett-Packard ScanJet 5550C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1205", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4570C | Hewlett-Packard ScanJet 5500C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1305", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3670C | Hewlett-Packard ScanJet 3690C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1405", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5590 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1705", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 7650 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1805", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4850C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1b05", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3530C | Hewlett-Packard ScanJet 3570C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2005", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3500C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2205", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3970c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2305", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4070 Photosmart ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2405", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3800 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2605", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G2710 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2805", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 8300 | Hewlett-Packard ScanJet 8350 | Hewlett-Packard ScanJet 8390 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3805", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 8270 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3905", ENV{libsane_matched}="yes" # Hewlett-Packard LaserJet M1005 MFP ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3b17", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4370 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4105", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G3010 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4205", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G3110 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4305", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G4010 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4505", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G4050 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4605", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet N6310 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4705", ENV{libsane_matched}="yes" # Hewlett-Packard LaserJet M1120 MFP ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="5617", ENV{libsane_matched}="yes" # Hewlett-Packard LaserJet M1120n MFP ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="5717", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 ATTRS{idVendor}=="0400", ATTRS{idProduct}=="1000", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 | Mustek BearPaw 2400 ATTRS{idVendor}=="0400", ATTRS{idProduct}=="1001", ENV{libsane_matched}="yes" # Kodak ESP 5100 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4025", ENV{libsane_matched}="yes" # Kodak ESP 5300 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4026", ENV{libsane_matched}="yes" # Kodak ESP 5500 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4027", ENV{libsane_matched}="yes" # Kodak ESP 5000 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4028", ENV{libsane_matched}="yes" # Kodak ESP 3300 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4031", ENV{libsane_matched}="yes" # Kodak ESP 5 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4032", ENV{libsane_matched}="yes" # Kodak ESP 7 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="403e", ENV{libsane_matched}="yes" # Kodak ESP 9 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="403f", ENV{libsane_matched}="yes" # Kodak ESP 5200 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4041", ENV{libsane_matched}="yes" # Kodak ESP 3200 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4043", ENV{libsane_matched}="yes" # Kodak ESP 4100 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4053", ENV{libsane_matched}="yes" # Kodak ESP 6100 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4054", ENV{libsane_matched}="yes" # Kodak ESP 7200 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4056", ENV{libsane_matched}="yes" # Kodak ESP C110 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4057", ENV{libsane_matched}="yes" # Kodak ESP C115 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4058", ENV{libsane_matched}="yes" # Kodak ESP 2150 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4059", ENV{libsane_matched}="yes" # Kodak ESP C310 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="405d", ENV{libsane_matched}="yes" # Kodak ESP C315 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="405e", ENV{libsane_matched}="yes" # Advent AW10 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4060", ENV{libsane_matched}="yes" # Kodak Hero Office 6.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4062", ENV{libsane_matched}="yes" # Kodak Hero 7.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4063", ENV{libsane_matched}="yes" # Kodak Hero 5.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4064", ENV{libsane_matched}="yes" # Kodak ESP 9200 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4065", ENV{libsane_matched}="yes" # Kodak ESP 2170 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4066", ENV{libsane_matched}="yes" # Kodak Hero 9.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4067", ENV{libsane_matched}="yes" # Kodak Hero 3.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="406d", ENV{libsane_matched}="yes" # Kodak i30 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6001", ENV{libsane_matched}="yes" # Kodak i40 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6002", ENV{libsane_matched}="yes" # Kodak i50 | Kodak i55 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6003", ENV{libsane_matched}="yes" # Kodak i60 | Kodak i65 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6004", ENV{libsane_matched}="yes" # Kodak i80 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6005", ENV{libsane_matched}="yes" # Creative WebCam Go Mini ATTRS{idVendor}=="041e", ATTRS{idProduct}=="4007", ENV{libsane_matched}="yes" # Lexmark X70 | Lexmark X73 ATTRS{idVendor}=="043d", ATTRS{idProduct}=="002d", ENV{libsane_matched}="yes" # Lexmark X74 ATTRS{idVendor}=="043d", ATTRS{idProduct}=="0060", ENV{libsane_matched}="yes" # Lexmark X1110 | Lexmark X1130 | Lexmark X1140 # Lexmark X1150 | Lexmark X1170 | Lexmark X1180 # Lexmark X1185 | Lexmark X1195 ATTRS{idVendor}=="043d", ATTRS{idProduct}=="007c", ENV{libsane_matched}="yes" # Lexmark X12xx ATTRS{idVendor}=="043d", ATTRS{idProduct}=="007d", ENV{libsane_matched}="yes" # Genius ColorPage HR6 V1 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2004", ENV{libsane_matched}="yes" # Genius Colorpage HR6 V2 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2007", ENV{libsane_matched}="yes" # Genius Colorpage HR6 V2 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2008", ENV{libsane_matched}="yes" # Genius Colorpage HR6A ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2009", ENV{libsane_matched}="yes" # Genius Colorpage Vivid3x | Genius Colorpage Vivid3 V2 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2011", ENV{libsane_matched}="yes" # Genius Colorpage HR7 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2013", ENV{libsane_matched}="yes" # Genius Colorpage Vivid4 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2014", ENV{libsane_matched}="yes" # Genius Colorpage HR7LE ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2015", ENV{libsane_matched}="yes" # Genius Colorpage HR6X ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2016", ENV{libsane_matched}="yes" # Genius Colorpage Vivid3xe ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2017", ENV{libsane_matched}="yes" # Genius Colorpage Vivid4xe ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201a", ENV{libsane_matched}="yes" # Genius Colorpage Vivid4x ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201b", ENV{libsane_matched}="yes" # Genius Colorpage Vivid 1200 X ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201d", ENV{libsane_matched}="yes" # Genius ColorPage Slim 1200 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201e", ENV{libsane_matched}="yes" # Genius Colorpage Vivid 1200 XE ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201f", ENV{libsane_matched}="yes" # Genius Colorpage SF600 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2021", ENV{libsane_matched}="yes" # Medion/Lifetec/Tevion/Cytron MD5345 | Medion/Lifetec/Tevion/Cytron MD6228 | Medion/Lifetec/Tevion/Cytron MD6471 ATTRS{idVendor}=="0461", ATTRS{idProduct}=="0377", ENV{libsane_matched}="yes" # Xerox 2400 Onetouch ATTRS{idVendor}=="0461", ATTRS{idProduct}=="038b", ENV{libsane_matched}="yes" # Trust Office Scan USB 19200 ATTRS{idVendor}=="047b", ATTRS{idProduct}=="1000", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4300c/Silitek ATTRS{idVendor}=="047b", ATTRS{idProduct}=="1002", ENV{libsane_matched}="yes" # Kyocera FS-1016MFP ATTRS{idVendor}=="0482", ATTRS{idProduct}=="0335", ENV{libsane_matched}="yes" # Compaq S4-100 ATTRS{idVendor}=="049f", ATTRS{idProduct}=="001a", ENV{libsane_matched}="yes" # Benq (Acer) 310U ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="1a20", ENV{libsane_matched}="yes" # Benq (Acer) 620U ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="1a2a", ENV{libsane_matched}="yes" # Benq (Acer) 320U | Benq (Acer) 340U | Mitsubishi Diamondview 648UT ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2022", ENV{libsane_matched}="yes" # Benq (Acer) 620UT ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2040", ENV{libsane_matched}="yes" # Benq (Acer) 640U | Guillemot / Hercules Maxi Scan A4 USB 640U | Guillemot / Hercules Maxi A4 36 bit ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2060", ENV{libsane_matched}="yes" # Benq (Acer) 640bu ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="207e", ENV{libsane_matched}="yes" # Benq (Acer) 3300 | Benq (Acer) 4300 | Mitsubishi Diamondview 650U ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20b0", ENV{libsane_matched}="yes" # Benq (Acer) 640BT ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20be", ENV{libsane_matched}="yes" # Benq (Acer) 1240 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20c0", ENV{libsane_matched}="yes" # Benq (Acer) 3300 | Benq (Acer) 4300 | Guillemot / Hercules Scan@home Touch 1248 (USB) ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20de", ENV{libsane_matched}="yes" # Benq (Acer) 5000 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20f8", ENV{libsane_matched}="yes" # Benq (Acer) 5000E | Benq (Acer) 5000U ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20fc", ENV{libsane_matched}="yes" # Benq (Acer) 5300 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20fe", ENV{libsane_matched}="yes" # Benq (Acer) 5150 | Benq (Acer) 5250 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2137", ENV{libsane_matched}="yes" # BenQ 5550 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2211", ENV{libsane_matched}="yes" # Visioneer Visioneer OneTouch 7100 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0229", ENV{libsane_matched}="yes" # Visioneer 9650 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0390", ENV{libsane_matched}="yes" # Visioneer 9320 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0420", ENV{libsane_matched}="yes" # Visioneer 9450 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0421", ENV{libsane_matched}="yes" # Visioneer 9550 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0422", ENV{libsane_matched}="yes" # Visioneer 9750 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0423", ENV{libsane_matched}="yes" # Visioneer Strobe XP 450 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0424", ENV{libsane_matched}="yes" # Visioneer Strobe XP 200 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0426", ENV{libsane_matched}="yes" # Visioneer Strobe XP 100 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0427", ENV{libsane_matched}="yes" # Visioneer OneTouch 7300 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0444", ENV{libsane_matched}="yes" # Xerox DocuMate510 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0446", ENV{libsane_matched}="yes" # Xerox DocuMate520 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0447", ENV{libsane_matched}="yes" # Xerox DocuMate250 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0448", ENV{libsane_matched}="yes" # Xerox DocuMate252 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0449", ENV{libsane_matched}="yes" # Xerox DocuMate262 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="044c", ENV{libsane_matched}="yes" # Visioneer Strobe XP 300 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0474", ENV{libsane_matched}="yes" # Xerox DocuMate272 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0475", ENV{libsane_matched}="yes" # Xerox DocuMate232 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0476", ENV{libsane_matched}="yes" # Xerox DocuMate152 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0477", ENV{libsane_matched}="yes" # Xerox DocuMate752 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0478", ENV{libsane_matched}="yes" # Visioneer Strobe XP 470 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0479", ENV{libsane_matched}="yes" # Visioneer 9450-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="047a", ENV{libsane_matched}="yes" # Visioneer 9650-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="047b", ENV{libsane_matched}="yes" # Xerox DocuMate510-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="047c", ENV{libsane_matched}="yes" # Xerox DocuMate252-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="048c", ENV{libsane_matched}="yes" # Xerox DocuMate262-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="048d", ENV{libsane_matched}="yes" # Xerox DocuMate272-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="048e", ENV{libsane_matched}="yes" # Visioneer Strobe XP 470-G | Visioneer Patriot 470 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="048f", ENV{libsane_matched}="yes" # Xerox DocuMate250-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0490", ENV{libsane_matched}="yes" # Visioneer Strobe XP 450-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0491", ENV{libsane_matched}="yes" # Xerox DocuMate520-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0492", ENV{libsane_matched}="yes" # Visioneer 9750-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0493", ENV{libsane_matched}="yes" # Visioneer Roadwarrior ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0494", ENV{libsane_matched}="yes" # Xerox DocuMate512 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0495", ENV{libsane_matched}="yes" # Visioneer Patriot 430 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0497", ENV{libsane_matched}="yes" # Visioneer Patriot 680 | Xerox DocuMate632 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0498", ENV{libsane_matched}="yes" # Visioneer Patriot 780 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0499", ENV{libsane_matched}="yes" # Xerox DocuMate752 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="049a", ENV{libsane_matched}="yes" # Visioneer Strobe XP 100,r3 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="049b", ENV{libsane_matched}="yes" # Xerox DocuMate150 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="049c", ENV{libsane_matched}="yes" # Xerox DocuMate162 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="049d", ENV{libsane_matched}="yes" # Xerox DocuMate262i ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="04a7", ENV{libsane_matched}="yes" # Xerox Travel Scanner 100 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="04ac", ENV{libsane_matched}="yes" # Canon DR-2080C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1601", ENV{libsane_matched}="yes" # Canon CR-180 | Canon CR-180II ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1602", ENV{libsane_matched}="yes" # Canon DR-9080C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1603", ENV{libsane_matched}="yes" # Canon DR-7080C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1604", ENV{libsane_matched}="yes" # Canon DR-5010C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1606", ENV{libsane_matched}="yes" # Canon DR-6080 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1607", ENV{libsane_matched}="yes" # Canon DR-2580C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1608", ENV{libsane_matched}="yes" # Canon DR-3080CII ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1609", ENV{libsane_matched}="yes" # Canon DR-2050C | Canon DR-2050SP ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="160a", ENV{libsane_matched}="yes" # Canon DR-7580 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="160b", ENV{libsane_matched}="yes" # Canon PIXMA MP750 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1706", ENV{libsane_matched}="yes" # Canon PIXMA MP780 | Canon PIXMA MP790 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1707", ENV{libsane_matched}="yes" # Canon PIXMA MP760 | Canon PIXMA MP770 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1708", ENV{libsane_matched}="yes" # Canon PIXMA MP150 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1709", ENV{libsane_matched}="yes" # Canon PIXMA MP170 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170a", ENV{libsane_matched}="yes" # Canon PIXMA MP450 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170b", ENV{libsane_matched}="yes" # Canon PIXMA MP500 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170c", ENV{libsane_matched}="yes" # Canon PIXMA MP800 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170d", ENV{libsane_matched}="yes" # Canon PIXMA MP800R ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170e", ENV{libsane_matched}="yes" # Canon PIXMA MP530 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1712", ENV{libsane_matched}="yes" # Canon PIXMA MP830 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1713", ENV{libsane_matched}="yes" # Canon PIXMA MP160 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1714", ENV{libsane_matched}="yes" # Canon PIXMA MP180 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1715", ENV{libsane_matched}="yes" # Canon PIXMA MP460 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1716", ENV{libsane_matched}="yes" # Canon PIXMA MP510 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1717", ENV{libsane_matched}="yes" # Canon PIXMA MP600 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1718", ENV{libsane_matched}="yes" # Canon PIXMA MP600R ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1719", ENV{libsane_matched}="yes" # Canon PIXMA MP810 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="171a", ENV{libsane_matched}="yes" # Canon PIXMA MP960 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="171b", ENV{libsane_matched}="yes" # Canon PIXMA MX7600 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="171c", ENV{libsane_matched}="yes" # Canon PIXMA MP210 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1721", ENV{libsane_matched}="yes" # Canon PIXMA MP220 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1722", ENV{libsane_matched}="yes" # Canon PIXMA MP470 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1723", ENV{libsane_matched}="yes" # Canon PIXMA MP520 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1724", ENV{libsane_matched}="yes" # Canon PIXMA MP610 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1725", ENV{libsane_matched}="yes" # Canon PIXMA MP970 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1726", ENV{libsane_matched}="yes" # Canon PIXMA MX300 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1727", ENV{libsane_matched}="yes" # Canon PIXMA MX310 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1728", ENV{libsane_matched}="yes" # Canon PIXMA MX700 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1729", ENV{libsane_matched}="yes" # Canon PIXMA MP140 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172b", ENV{libsane_matched}="yes" # Canon PIXMA MX850 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172c", ENV{libsane_matched}="yes" # Canon PIXMA MP980 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172d", ENV{libsane_matched}="yes" # Canon PIXMA MP630 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172e", ENV{libsane_matched}="yes" # Canon PIXMA MP620 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172f", ENV{libsane_matched}="yes" # Canon PIXMA MP540 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1730", ENV{libsane_matched}="yes" # Canon PIXMA MP480 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1731", ENV{libsane_matched}="yes" # Canon PIXMA MP240 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1732", ENV{libsane_matched}="yes" # Canon PIXMA MP260 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1733", ENV{libsane_matched}="yes" # Canon PIXMA MP190 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1734", ENV{libsane_matched}="yes" # Canon PIXMA MX860 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1735", ENV{libsane_matched}="yes" # Canon PIXMA MX320 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1736", ENV{libsane_matched}="yes" # Canon PIXMA MX330 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1737", ENV{libsane_matched}="yes" # Canon PIXMA MP250 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173a", ENV{libsane_matched}="yes" # Canon PIXMA MP270 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173b", ENV{libsane_matched}="yes" # Canon PIXMA MP490 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173c", ENV{libsane_matched}="yes" # Canon PIXMA MP550 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173d", ENV{libsane_matched}="yes" # Canon PIXMA MP560 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173e", ENV{libsane_matched}="yes" # Canon PIXMA MP640 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173f", ENV{libsane_matched}="yes" # Canon PIXMA MP990 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1740", ENV{libsane_matched}="yes" # Canon PIXMA MX340 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1741", ENV{libsane_matched}="yes" # Canon PIXMA MX350 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1742", ENV{libsane_matched}="yes" # Canon PIXMA MX870 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1743", ENV{libsane_matched}="yes" # Canon PIXMA MP280 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1746", ENV{libsane_matched}="yes" # Canon PIXMA MP495 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1747", ENV{libsane_matched}="yes" # Canon PIXMA MG5100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1748", ENV{libsane_matched}="yes" # Canon PIXMA MG5200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1749", ENV{libsane_matched}="yes" # Canon PIXMA MG6100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174a", ENV{libsane_matched}="yes" # Canon PIXMA MG8100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174b", ENV{libsane_matched}="yes" # Canon PIXMA MX360 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174d", ENV{libsane_matched}="yes" # Canon PIXMA MX410 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174e", ENV{libsane_matched}="yes" # Canon PIXMA MX420 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174f", ENV{libsane_matched}="yes" # Canon PIXMA MX880 Series | Canon PIXMA MX882 | Canon PIXMA MX885 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1750", ENV{libsane_matched}="yes" # Canon PIXMA MG2100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1751", ENV{libsane_matched}="yes" # Canon PIXMA MG3100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1752", ENV{libsane_matched}="yes" # Canon PIXMA MG4100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1753", ENV{libsane_matched}="yes" # Canon PIXMA MG5300 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1754", ENV{libsane_matched}="yes" # Canon PIXMA MG6200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1755", ENV{libsane_matched}="yes" # Canon PIXMA MG8200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1756", ENV{libsane_matched}="yes" # Canon PIXMA MP493 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1757", ENV{libsane_matched}="yes" # Canon PIXMA E500 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1758", ENV{libsane_matched}="yes" # Canon PIXMA MX370 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1759", ENV{libsane_matched}="yes" # Canon PIXMA E600 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175a", ENV{libsane_matched}="yes" # Canon PIXMA MX430 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175b", ENV{libsane_matched}="yes" # Canon PIXMA MX510 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175c", ENV{libsane_matched}="yes" # Canon PIXMA MX710 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175d", ENV{libsane_matched}="yes" # Canon PIXMA MX890 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175e", ENV{libsane_matched}="yes" # Canon PIXMA MP230 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175f", ENV{libsane_matched}="yes" # Canon PIXMA MG2200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1760", ENV{libsane_matched}="yes" # Canon PIXMA E510 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1761", ENV{libsane_matched}="yes" # Canon PIXMA MG3200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1762", ENV{libsane_matched}="yes" # Canon PIXMA MG4200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1763", ENV{libsane_matched}="yes" # Canon PIXMA MG5400 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1764", ENV{libsane_matched}="yes" # Canon PIXMA MG6300 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1765", ENV{libsane_matched}="yes" # Canon PIXMA MX390 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1766", ENV{libsane_matched}="yes" # Canon PIXMA E610 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1767", ENV{libsane_matched}="yes" # Canon PIXMA MX450 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1768", ENV{libsane_matched}="yes" # Canon PIXMA MX520 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1769", ENV{libsane_matched}="yes" # Canon PIXMA MX720 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="176a", ENV{libsane_matched}="yes" # Canon PIXMA MX920 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="176b", ENV{libsane_matched}="yes" # Canon CanoScan 8800F ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1901", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 100 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1904", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 200 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1905", ENV{libsane_matched}="yes" # Canon CanoScan 700F ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1907", ENV{libsane_matched}="yes" # Canon CanoScan 9000F ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1908", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 110 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1909", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 210 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="190a", ENV{libsane_matched}="yes" # Canon CanoScan 9000F Mark II ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="190d", ENV{libsane_matched}="yes" # Canon CanoScan fb630u | Canon CanoScan fb636u ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2204", ENV{libsane_matched}="yes" # Canon CanoScan N650U/N656U ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2206", ENV{libsane_matched}="yes" # Canon CanoScan N1220U ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2207", ENV{libsane_matched}="yes" # Canon CanoScan D660U ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2208", ENV{libsane_matched}="yes" # Canon CanoScan N670U/N676U/LiDE20 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="220d", ENV{libsane_matched}="yes" # Canon CanoScan N1240U/LiDE30 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="220e", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 35 | Canon CanoScan LiDE 40 | Canon CanoScan LiDE 50 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2213", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 60 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="221c", ENV{libsane_matched}="yes" # Canon CanoScan LiDE25 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2220", ENV{libsane_matched}="yes" # Canon DR-1210C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2222", ENV{libsane_matched}="yes" # Canon PIXMA MP730 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="262f", ENV{libsane_matched}="yes" # Canon PIXMA MP700 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2630", ENV{libsane_matched}="yes" # Canon PIXMA MP360 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="263c", ENV{libsane_matched}="yes" # Canon PIXMA MP370 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="263d", ENV{libsane_matched}="yes" # Canon PIXMA MP390 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="263e", ENV{libsane_matched}="yes" # Canon PIXMA MP375R ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="263f", ENV{libsane_matched}="yes" # Canon PIXMA MP740 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="264c", ENV{libsane_matched}="yes" # Canon PIXMA MP710 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="264d", ENV{libsane_matched}="yes" # Canon imageCLASS MF5630 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="264e", ENV{libsane_matched}="yes" # Canon laserBase MF5650 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="264f", ENV{libsane_matched}="yes" # Canon imageCLASS MF8170c ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2659", ENV{libsane_matched}="yes" # Canon imageCLASS MF5730 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="265d", ENV{libsane_matched}="yes" # Canon imageCLASS MF5750 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="265e", ENV{libsane_matched}="yes" # Canon imageCLASS MF5770 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="265f", ENV{libsane_matched}="yes" # Canon imageCLASS MF3110 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2660", ENV{libsane_matched}="yes" # Canon imageCLASS MF3240 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2684", ENV{libsane_matched}="yes" # Canon imageCLASS MF6500 series | Canon imageCLASS MF6550 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2686", ENV{libsane_matched}="yes" # Canon imageCLASS MF4120 | Canon imageCLASS MF4122 | Canon imageCLASS MF4140 # Canon imageCLASS MF4150 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26a3", ENV{libsane_matched}="yes" # Canon imageCLASS MF4660 | Canon imageCLASS MF4690 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26b0", ENV{libsane_matched}="yes" # Canon imageCLASS MF4010 | Canon imageCLASS MF4018 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26b4", ENV{libsane_matched}="yes" # Canon imageCLASS MF4270 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26b5", ENV{libsane_matched}="yes" # Canon imageRUNNER 1020/1024/1025 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26e6", ENV{libsane_matched}="yes" # Canon imageCLASS MF4370dn | Canon imageCLASS MF4380dn ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26ec", ENV{libsane_matched}="yes" # Canon imageCLASS D480 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26ed", ENV{libsane_matched}="yes" # Canon I-SENSYS MF4320d | Canon I-SENSYS MF4330d | Canon imageCLASS MF4350d ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26ee", ENV{libsane_matched}="yes" # Canon imageCLASS D420 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26ef", ENV{libsane_matched}="yes" # Canon i-SENSYS MF5880dn ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26f9", ENV{libsane_matched}="yes" # Canon i-SENSYS MF6680dn ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26fa", ENV{libsane_matched}="yes" # Canon imageCLASS MF8030 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2707", ENV{libsane_matched}="yes" # Canon i-SENSYS MF4550d ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2736", ENV{libsane_matched}="yes" # Canon imageCLASS MF4410 | Canon imageCLASS MF4430 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2737", ENV{libsane_matched}="yes" # Canon i-SENSYS MF3010 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2759", ENV{libsane_matched}="yes" # Nikon LS 40 ED | Nikon LS 40 ED | Nikon Coolspan IV ATTRS{idVendor}=="04b0", ATTRS{idProduct}=="4000", ENV{libsane_matched}="yes" # Nikon LS 50 ED | Nikon Coolscan V ED | Nikon LS 50 ED # Nikon Coolscan V ED ATTRS{idVendor}=="04b0", ATTRS{idProduct}=="4001", ENV{libsane_matched}="yes" # Nikon Super Coolscan LS-5000 ED | Nikon Super Coolscan LS-5000 ED ATTRS{idVendor}=="04b0", ATTRS{idProduct}=="4002", ENV{libsane_matched}="yes" # Epson Perfection 636U | Epson GT-7000U | Epson Perfection 636U ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0101", ENV{libsane_matched}="yes" # Epson Perfection 610 | Epson GT-6600U | Epson Perfection 610 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0103", ENV{libsane_matched}="yes" # Epson Perfection 1200U | Epson Perfection 1200Photo | Epson GT-7600U # Epson GT-7600UF | Epson Perfection 1200U | Epson Perfection 1200U PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0104", ENV{libsane_matched}="yes" # Epson Stylus Scan 2000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0105", ENV{libsane_matched}="yes" # Epson Stylus Scan 2500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0106", ENV{libsane_matched}="yes" # Epson Expression 1600 | Epson ES-2000 | Epson Expression 1600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0107", ENV{libsane_matched}="yes" # Epson ES-8500 | Epson Expression 1640XL ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0109", ENV{libsane_matched}="yes" # Epson Perfection 1640 | Epson GT-8700 | Epson GT-8700F # Epson Perfection 1640SU | Epson Perfection 1640SU PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010a", ENV{libsane_matched}="yes" # Epson Perfection 1240 | Epson GT-7700U | Epson Perfection 1240U ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010b", ENV{libsane_matched}="yes" # Epson Perfection 640 | Epson GT-6700U | Epson Perfection 640U ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010c", ENV{libsane_matched}="yes" # Epson Expression 1680 | Epson ES-2200 | Epson Expression 1680 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010e", ENV{libsane_matched}="yes" # Epson Perfection 1250 | Epson Perfection 1250Photo ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010f", ENV{libsane_matched}="yes" # Epson Perfection 1650 | Epson GT-8200U | Epson GT-8200UF # Epson Perfection 1650 | Epson Perfection 1650 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0110", ENV{libsane_matched}="yes" # Epson Perfection 2450 | Epson GT-9700F | Epson Perfection 2450 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0112", ENV{libsane_matched}="yes" # Epson Perfection 660 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0114", ENV{libsane_matched}="yes" # Epson Perfection 2400 | Epson GT-9300UF | Epson Perfection 2400 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011b", ENV{libsane_matched}="yes" # Epson Perfection 3200 | Epson GT-9800F | Epson Perfection 3200 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011c", ENV{libsane_matched}="yes" # Epson Perfection 1260 | Epson Perfection 1260Photo ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011d", ENV{libsane_matched}="yes" # Epson Perfection 1660 | Epson GT-8300UF | Epson Perfection 1660 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011e", ENV{libsane_matched}="yes" # Epson Perfection 1670 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011f", ENV{libsane_matched}="yes" # Epson Perfection 1270 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0120", ENV{libsane_matched}="yes" # Epson Perfection 2480 | Epson Perfection 2580 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0121", ENV{libsane_matched}="yes" # Epson Perfection 3490 | Epson Perfection 3590 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0122", ENV{libsane_matched}="yes" # Epson ES-7000H | Epson GT-15000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0126", ENV{libsane_matched}="yes" # Epson Perfection 4870 | Epson GT-X700 | Epson Perfection 4870 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0128", ENV{libsane_matched}="yes" # Epson ES-10000G | Epson Expression 10000XL ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0129", ENV{libsane_matched}="yes" # Epson Perfection 4990 | Epson GT-X800 | Epson Perfection 4990 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="012a", ENV{libsane_matched}="yes" # Epson ES-H300 | Epson GT-2500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="012b", ENV{libsane_matched}="yes" # Epson V700 | Epson V750 | Epson GT-X900 # Epson Perfection V700 Photo | Epson Perfection V750 Photo ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="012c", ENV{libsane_matched}="yes" # Epson GT-X970 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0135", ENV{libsane_matched}="yes" # Epson CX-5200 | Epson CX-5400 | Epson CC-600PX # Epson Stylus CX5100 | Epson Stylus CX5200 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0801", ENV{libsane_matched}="yes" # Epson CX-3200 | Epson CC-570L | Epson Stylus CX3100 # Epson Stylus CX3200 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0802", ENV{libsane_matched}="yes" # Epson CX-6300 | Epson CX-6400 | Epson Stylus CX6300 # Epson Stylus CX6400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0805", ENV{libsane_matched}="yes" # Epson RX-600 | Epson PM-A850 | Epson Stylus Photo RX600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0806", ENV{libsane_matched}="yes" # Epson RX-500 | Epson Stylus Photo RX500 | Epson Stylus Photo RX510 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0807", ENV{libsane_matched}="yes" # Epson CX-5400 | Epson Stylus CX5300 | Epson Stylus CX5400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0808", ENV{libsane_matched}="yes" # Epson Stylus CX-1500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="080c", ENV{libsane_matched}="yes" # Epson CX-4600 | Epson Stylus CX4500 | Epson Stylus CX4600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="080d", ENV{libsane_matched}="yes" # Epson CX-3600 | Epson CX-3650 | Epson PX-A550 # Epson Stylus CX3500 | Epson Stylus CX3600 | Epson Stylus CX3650 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="080e", ENV{libsane_matched}="yes" # Epson RX-425 | Epson Stylus Photo RX420 | Epson Stylus Photo RX425 # Epson Stylus Photo RX430 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="080f", ENV{libsane_matched}="yes" # Epson RX-700 | Epson PM-A900 | Epson Stylus Photo RX700 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0810", ENV{libsane_matched}="yes" # Epson RX-620 | Epson PM-A870 | Epson Stylus Photo RX620 # Epson Stylus Photo RX630 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0811", ENV{libsane_matched}="yes" # Epson CX-6500 | Epson CX-6600 | Epson Stylus CX6500 # Epson Stylus CX6600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0813", ENV{libsane_matched}="yes" # Epson PM-A700 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0814", ENV{libsane_matched}="yes" # Epson AcuLaser CX11 | Epson AcuLaser CX11NF | Epson AcuLaser CX11 # Epson AcuLaser CX11NF | Epson LP-A500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0815", ENV{libsane_matched}="yes" # Epson LP-M5500 | Epson LP-M5500F ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0817", ENV{libsane_matched}="yes" # Epson DX-3850 | Epson CX-3700 | Epson CX-3800 # Epson DX-3800 | Epson Stylus CX3700 | Epson Stylus CX3800 # Epson Stylus DX3800 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0818", ENV{libsane_matched}="yes" # Epson CX-4800 | Epson PX-A650 | Epson Stylus CX4700 # Epson Stylus CX4800 | Epson Stylus DX4800 | Epson Stylus DX4850 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0819", ENV{libsane_matched}="yes" # Epson PM-A750 | Epson Stylus Photo RX520 | Epson Stylus Photo RX530 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="081a", ENV{libsane_matched}="yes" # Epson PM-A890 | Epson Stylus Photo RX640 | Epson Stylus Photo RX650 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="081c", ENV{libsane_matched}="yes" # Epson PM-A950 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="081d", ENV{libsane_matched}="yes" # Epson Stylus CX7700 | Epson Stylus CX7800 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="081f", ENV{libsane_matched}="yes" # Epson CX-4200 | Epson Stylus CX4100 | Epson Stylus CX4200 # Epson Stylus DX4200 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0820", ENV{libsane_matched}="yes" # Epson PM-A820 | Epson Stylus Photo RX560 | Epson Stylus Photo RX580 # Epson Stylus Photo RX590 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0827", ENV{libsane_matched}="yes" # Epson PM-A970 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0828", ENV{libsane_matched}="yes" # Epson PM-T990 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0829", ENV{libsane_matched}="yes" # Epson PM-A920 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="082a", ENV{libsane_matched}="yes" # Epson CX-5000 | Epson DX-5000 | Epson DX-5050 # Epson Stylus CX4900 | Epson Stylus CX5000 | Epson Stylus DX5000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="082b", ENV{libsane_matched}="yes" # Epson DX-6000 | Epson PX-A720 | Epson Stylus CX5900 # Epson Stylus CX6000 | Epson Stylus DX6000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="082e", ENV{libsane_matched}="yes" # Epson DX-4050 | Epson PX-A620 | Epson Stylus CX3900 # Epson Stylus DX4000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="082f", ENV{libsane_matched}="yes" # Epson ME 200 | Epson Stylus CX2800 | Epson Stylus CX2900 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0830", ENV{libsane_matched}="yes" # Epson LP-M5600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0833", ENV{libsane_matched}="yes" # Epson LP-M6000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0834", ENV{libsane_matched}="yes" # Epson AcuLaser CX21 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0835", ENV{libsane_matched}="yes" # Epson PM-T960 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0836", ENV{libsane_matched}="yes" # Epson PM-A940 | Epson Stylus Photo RX680 | Epson Stylus Photo RX685 # Epson Stylus Photo RX690 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0837", ENV{libsane_matched}="yes" # Epson DX-7400 | Epson PX-A640 | Epson Stylus CX7300 # Epson Stylus CX7400 | Epson Stylus DX7400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0838", ENV{libsane_matched}="yes" # Epson PX-A740 | Epson Stylus CX8300 | Epson Stylus CX8400 # Epson Stylus DX8400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0839", ENV{libsane_matched}="yes" # Epson PX-FA700 | Epson Stylus CX9300F | Epson Stylus CX9400Fax # Epson Stylus DX9400F ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="083a", ENV{libsane_matched}="yes" # Epson PM-A840 | Epson PM-A840S | Epson Stylus Photo RX585 # Epson Stylus Photo RX595 | Epson Stylus Photo RX610 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="083c", ENV{libsane_matched}="yes" # Epson ME 300 | Epson PX-401A | Epson Stylus NX100 # Epson Stylus SX100 | Epson Stylus TX100 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0841", ENV{libsane_matched}="yes" # Epson LP-M5000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0843", ENV{libsane_matched}="yes" # Epson Artisan 800 | Epson EP-901A | Epson EP-901F # Epson Stylus Photo PX800FW | Epson Stylus Photo TX800FW ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0844", ENV{libsane_matched}="yes" # Epson Artisan 700 | Epson EP-801A | Epson Stylus Photo PX700W # Epson Stylus Photo TX700W ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0846", ENV{libsane_matched}="yes" # Epson ME Office 700FW | Epson PX-601F | Epson Stylus Office BX600FW # Epson Stylus Office TX600FW | Epson Stylus SX600FW | Epson WorkForce 600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0847", ENV{libsane_matched}="yes" # Epson ME Office 600F | Epson Stylus Office BX300F | Epson Stylus Office TX300F # Epson Stylus NX300 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0848", ENV{libsane_matched}="yes" # Epson Stylus NX200 | Epson Stylus SX200 | Epson Stylus SX205 # Epson Stylus TX200 | Epson Stylus TX203 | Epson Stylus TX209 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0849", ENV{libsane_matched}="yes" # Epson PX-501A | Epson Stylus NX400 | Epson Stylus SX400 # Epson Stylus SX405 | Epson Stylus TX400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="084a", ENV{libsane_matched}="yes" # Epson WorkForce 500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="084c", ENV{libsane_matched}="yes" # Epson PX-402A | Epson Stylus NX110 Series | Epson Stylus SX110 Series # Epson Stylus TX110 Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="084d", ENV{libsane_matched}="yes" # Epson ME OFFICE 510 | Epson Stylus NX210 Series | Epson Stylus SX210 Series # Epson Stylus TX210 Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="084f", ENV{libsane_matched}="yes" # Epson Stylus NX410 Series | Epson Stylus SX410 Series | Epson Stylus TX410 Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0851", ENV{libsane_matched}="yes" # Epson ME OFFICE 650FN Series | Epson Stylus Office BX310FN Series | Epson Stylus Office TX510FN Series # Epson WorkForce 310 Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0854", ENV{libsane_matched}="yes" # Epson PX-502A | Epson Stylus NX510 Series | Epson Stylus SX510W Series # Epson Stylus TX550W Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0856", ENV{libsane_matched}="yes" # Epson Stylus SX125 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="085c", ENV{libsane_matched}="yes" # Fujitsu fi-4010CU ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1029", ENV{libsane_matched}="yes" # Fujitsu fi-4120C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1041", ENV{libsane_matched}="yes" # Fujitsu fi-4220C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1042", ENV{libsane_matched}="yes" # Fujitsu fi-4530C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1078", ENV{libsane_matched}="yes" # Fujitsu fi-5750C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1095", ENV{libsane_matched}="yes" # Fujitsu fi-5110EOX/2 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1096", ENV{libsane_matched}="yes" # Fujitsu fi-5110C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1097", ENV{libsane_matched}="yes" # Fujitsu fi-5650C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10ad", ENV{libsane_matched}="yes" # Fujitsu fi-4120C2 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10ae", ENV{libsane_matched}="yes" # Fujitsu fi-4220C2 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10af", ENV{libsane_matched}="yes" # Fujitsu fi-60F ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10c7", ENV{libsane_matched}="yes" # Fujitsu fi-4340C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10cf", ENV{libsane_matched}="yes" # Fujitsu fi-5120C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e0", ENV{libsane_matched}="yes" # Fujitsu fi-5220C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e1", ENV{libsane_matched}="yes" # Fujitsu fi-5530C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e2", ENV{libsane_matched}="yes" # Fujitsu fi-5110EOX3 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e6", ENV{libsane_matched}="yes" # Fujitsu fi-5900C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e7", ENV{libsane_matched}="yes" # Fujitsu fi-5015C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10ef", ENV{libsane_matched}="yes" # Fujitsu fi-5110EOXM ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10f2", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S500 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10fe", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S500M ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1135", ENV{libsane_matched}="yes" # Fujitsu fi-5530C2 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="114a", ENV{libsane_matched}="yes" # Fujitsu fi-6140 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="114d", ENV{libsane_matched}="yes" # Fujitsu fi-6240 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="114e", ENV{libsane_matched}="yes" # Fujitsu fi-6130 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="114f", ENV{libsane_matched}="yes" # Fujitsu fi-6230 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1150", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S510 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1155", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S300 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1156", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S510M ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="116f", ENV{libsane_matched}="yes" # Fujitsu fi-6770 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1174", ENV{libsane_matched}="yes" # Fujitsu fi-6770A ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1175", ENV{libsane_matched}="yes" # Fujitsu fi-6670 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1176", ENV{libsane_matched}="yes" # Fujitsu fi-6670A ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1177", ENV{libsane_matched}="yes" # Fujitsu fi-6750S ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1178", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S300M ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="117f", ENV{libsane_matched}="yes" # Fujitsu fi-6800 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="119d", ENV{libsane_matched}="yes" # Fujitsu fi-6800-CGA ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="119e", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S1500 | Fujitsu ScanSnap S1500M ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11a2", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S1300 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11ed", ENV{libsane_matched}="yes" # Fujitsu fi-6140Z ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11f1", ENV{libsane_matched}="yes" # Fujitsu fi-6240Z ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11f2", ENV{libsane_matched}="yes" # Fujitsu fi-6130Z ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11f3", ENV{libsane_matched}="yes" # Fujitsu fi-6230Z ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11f4", ENV{libsane_matched}="yes" # Fujitsu fi-6110 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11fc", ENV{libsane_matched}="yes" # Fujitsu fi-5950 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1213", ENV{libsane_matched}="yes" # Fujitsu ScanSnap iX500 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="132b", ENV{libsane_matched}="yes" # Konica e-mini ATTRS{idVendor}=="04c8", ATTRS{idProduct}=="0722", ENV{libsane_matched}="yes" # Panasonic KV-S2026C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1000", ENV{libsane_matched}="yes" # Panasonic KV-S2046C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1001", ENV{libsane_matched}="yes" # Panasonic KV-S1025C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1006", ENV{libsane_matched}="yes" # Panasonic KV-S1020C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1007", ENV{libsane_matched}="yes" # Panasonic KV-S2048C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1009", ENV{libsane_matched}="yes" # Panasonic KV-S2028C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100a", ENV{libsane_matched}="yes" # Panasonic KV-S4085C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100c", ENV{libsane_matched}="yes" # Panasonic KV-S4065C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100d", ENV{libsane_matched}="yes" # Panasonic KV-S7075C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100e", ENV{libsane_matched}="yes" # Panasonic KV-SS080 ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100f", ENV{libsane_matched}="yes" # Panasonic KV-S1045C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1010", ENV{libsane_matched}="yes" # Samsung SCX-4x16 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3409", ENV{libsane_matched}="yes" # Samsung SCX-6x20 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="340d", ENV{libsane_matched}="yes" # Samsung MFP-560 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="340e", ENV{libsane_matched}="yes" # Samsung MFP-750 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="340f", ENV{libsane_matched}="yes" # Samsung SCX-4x20 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3412", ENV{libsane_matched}="yes" # Samsung SCX-4100 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3413", ENV{libsane_matched}="yes" # Samsung SCX-4x21 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3419", ENV{libsane_matched}="yes" # Samsung SCX-5x30 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341a", ENV{libsane_matched}="yes" # Samsung SCX-4200 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341b", ENV{libsane_matched}="yes" # Samsung CLX-3160 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341c", ENV{libsane_matched}="yes" # Samsung SCX-6x22 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341d", ENV{libsane_matched}="yes" # Samsung SCX4725 | Samsung SCX4725-FN ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341f", ENV{libsane_matched}="yes" # Samsung SCX-6x45 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3420", ENV{libsane_matched}="yes" # Samsung CLX-8380 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3421", ENV{libsane_matched}="yes" # Samsung CLX-2160 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3425", ENV{libsane_matched}="yes" # Samsung SCX-4500 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3426", ENV{libsane_matched}="yes" # Samsung CLX-6200 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3427", ENV{libsane_matched}="yes" # Samsung CLX-6240 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3428", ENV{libsane_matched}="yes" # Samsung SCX-6x55 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3429", ENV{libsane_matched}="yes" # Samsung CLX-3170fn (CLX-3170 Series) | Samsung CLX-3175FW ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342a", ENV{libsane_matched}="yes" # Samsung SCX-4500W ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342b", ENV{libsane_matched}="yes" # Samsung SCX-4824 (SCX-4x24 Series) ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342c", ENV{libsane_matched}="yes" # Samsung SCX-4828FN (SCX-4x28 Series) ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342d", ENV{libsane_matched}="yes" # Samsung SCX-4300 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342e", ENV{libsane_matched}="yes" # Samsung SCX-5835_5935 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342f", ENV{libsane_matched}="yes" # Samsung SCX-5635 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3430", ENV{libsane_matched}="yes" # Samsung SCX-4x26 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3432", ENV{libsane_matched}="yes" # Samsung SCX-4600 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3433", ENV{libsane_matched}="yes" # Samsung SCX-4623 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3434", ENV{libsane_matched}="yes" # Samsung MFP-65x ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3435", ENV{libsane_matched}="yes" # Samsung SCX-6545 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3437", ENV{libsane_matched}="yes" # Samsung CLX-8385 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3439", ENV{libsane_matched}="yes" # Samsung CLX-6220 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343a", ENV{libsane_matched}="yes" # Samsung CLX-6250 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343b", ENV{libsane_matched}="yes" # Samsung SCX-4825FN (SCX-4x25 Series) ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343c", ENV{libsane_matched}="yes" # Samsung CLX-3185 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343d", ENV{libsane_matched}="yes" # Samsung CLX-8540 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343f", ENV{libsane_matched}="yes" # Samsung SCX-4623FW ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3440", ENV{libsane_matched}="yes" # Samsung SCX-3205W (SCX-3200 Series) ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3441", ENV{libsane_matched}="yes" # Samsung SCX-6545X ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3442", ENV{libsane_matched}="yes" # Samsung SCX-6x55X ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3443", ENV{libsane_matched}="yes" # Samsung CLX-8385X ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3444", ENV{libsane_matched}="yes" # Samsung SCX-5835_5935X ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3446", ENV{libsane_matched}="yes" # Samsung SCX-4833FD | Samsung SCX-4835FD ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="344b", ENV{libsane_matched}="yes" # Samsung SCX-3400 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="344f", ENV{libsane_matched}="yes" # Samsung SF-760 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3450", ENV{libsane_matched}="yes" # Samsung SCX-4729FD ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3453", ENV{libsane_matched}="yes" # Samsung CLX-6260 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3455", ENV{libsane_matched}="yes" # Samsung CLX-3300 Series ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3456", ENV{libsane_matched}="yes" # Samsung SCX-470x ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3457", ENV{libsane_matched}="yes" # Samsung CLX-4190 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="345a", ENV{libsane_matched}="yes" # Samsung SCX-4650 4x21S Series ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="345b", ENV{libsane_matched}="yes" # Samsung M337x 387x 407x Series ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3460", ENV{libsane_matched}="yes" # Samsung M267x 287x Series ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3461", ENV{libsane_matched}="yes" # Samsung SCX-681x ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3466", ENV{libsane_matched}="yes" # Samsung C460 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3468", ENV{libsane_matched}="yes" # Pentax DSmobile 600 ATTRS{idVendor}=="04f9", ATTRS{idProduct}=="2038", ENV{libsane_matched}="yes" # Aiptek Aiptek Pencam ATTRS{idVendor}=="0553", ATTRS{idProduct}=="0202", ENV{libsane_matched}="yes" # Mustek ScanExpress 1200 CU ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0001", ENV{libsane_matched}="yes" # Mustek ScanExpress 600 CU ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0002", ENV{libsane_matched}="yes" # Mustek ScanExpress 1200 UB | Trust Compact Scan USB 19200 ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0006", ENV{libsane_matched}="yes" # Mustek ScanExpress 1200 CU Plus ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0008", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 F ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0010", ENV{libsane_matched}="yes" # Mustek ScanExpress A3 USB ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0210", ENV{libsane_matched}="yes" # Mustek BearPaw 2400 CS | Mustek BearPaw 2400 TA | Trust 240TH Easy Webscan Gold ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0218", ENV{libsane_matched}="yes" # Mustek BearPaw 2400 CS Plus | Mustek BearPaw 2400 TA Plus | Mustek Plug-n-Scan 2400 MT # Mustek Plug-n-Scan 2400 M | Packard Bell Diamond 2450 ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0219", ENV{libsane_matched}="yes" # Mustek BearPaw 2448 CS Plus | Mustek BearPaw 2448 TA Plus ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021a", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 CU Plus | Packard Bell Diamond 1200 Plus ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021b", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 CU Plus | Mustek BearPaw 1248 CU | Packard Bell Diamond 1200 Plus # Trust Direct WebScan 19200 ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021c", ENV{libsane_matched}="yes" # Mustek BearPaw 2400 CU Plus ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021d", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 CS | Mustek BearPaw 1200 TA ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021e", ENV{libsane_matched}="yes" # Mustek ScanExpress 1248 UB ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021f", ENV{libsane_matched}="yes" # Mustek BearPaw 2448TA Pro ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0409", ENV{libsane_matched}="yes" # Artec/Ultima Ultima 2000 | Artec/Ultima Ultima 2000 e+ | Boeder Sm@rtScan Slim Edition # Fujitsu 1200CUS | Googlegear 2000 | Medion/Lifetec/Tevion/Cytron MD 4394 # Medion/Lifetec/Tevion/Cytron MD/LT 9375 | Medion/Lifetec/Tevion/Cytron MD/LT 9385 | Medion/Lifetec/Tevion/Cytron LT 9452 # Medion/Lifetec/Tevion/Cytron MD 9458 | Mustek BearPaw 1200 CU | Mustek BearPaw 2400 CU # Mustek ScanExpress 1200 UB Plus | Mustek ScanExpress 2400 USB | Mustek ScanMagic 1200 UB Plus # Packard Bell Diamond 1200 | Trust Compact Scan USB 19200 | Trust Flat Scan USB 19200 ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4002", ENV{libsane_matched}="yes" # Artec/Ultima E+ 48U | Medion/Lifetec/Tevion/Cytron MD9693 | Medion/Lifetec/Tevion/Cytron MD9705 # Medion/Lifetec/Tevion/Cytron MD4394 | Microstar MR 9791 ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4003", ENV{libsane_matched}="yes" # Artec/Ultima E+ Pro ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4004", ENV{libsane_matched}="yes" # Memorex MEM 48U ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4005", ENV{libsane_matched}="yes" # Trust Easy Webscan 19200 ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4006", ENV{libsane_matched}="yes" # Trust 240H Easy Webscan Gold ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4007", ENV{libsane_matched}="yes" # UMAX AstraSlim SE ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4009", ENV{libsane_matched}="yes" # UMAX AstraSlim 1200 SE ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4010", ENV{libsane_matched}="yes" # Yakumo Scan50 ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4011", ENV{libsane_matched}="yes" # Microtek ScanMaker X6USB ATTRS{idVendor}=="05da", ATTRS{idProduct}=="0099", ENV{libsane_matched}="yes" # Microtek SlimScan C6 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="009a", ENV{libsane_matched}="yes" # Microtek ScanMaker V6USL ATTRS{idVendor}=="05da", ATTRS{idProduct}=="00a3", ENV{libsane_matched}="yes" # Microtek ScanMaker V6UPL ATTRS{idVendor}=="05da", ATTRS{idProduct}=="00b6", ENV{libsane_matched}="yes" # Microtek ScanMaker 4800 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="30cf", ENV{libsane_matched}="yes" # Microtek ScanMaker 3840 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="30d4", ENV{libsane_matched}="yes" # Microtek ScanMaker 3600 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40b3", ENV{libsane_matched}="yes" # Microtek ScanMaker 3700 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40b8", ENV{libsane_matched}="yes" # Microtek ScanMaker 3600 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40ca", ENV{libsane_matched}="yes" # Microtek ScanMaker 3700 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40cb", ENV{libsane_matched}="yes" # Microtek ScanMaker 3750 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40dd", ENV{libsane_matched}="yes" # Microtek ScanMaker 3600 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40ff", ENV{libsane_matched}="yes" # Microtek ScanMaker V6USL ATTRS{idVendor}=="05da", ATTRS{idProduct}=="80a3", ENV{libsane_matched}="yes" # iVina 1200U ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0268", ENV{libsane_matched}="yes" # Minolta Dimage Scan Dual II ATTRS{idVendor}=="0638", ATTRS{idProduct}=="026a", ENV{libsane_matched}="yes" # Avision AV600U ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a13", ENV{libsane_matched}="yes" # Minolta-QMS SC-110 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a15", ENV{libsane_matched}="yes" # Avision DS610CU Scancopier | Minolta-QMS SC-215 | OKI S700 Scancopier ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a16", ENV{libsane_matched}="yes" # Avision AV610 | Avision AV600U Plus ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a18", ENV{libsane_matched}="yes" # Avision AV220 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a23", ENV{libsane_matched}="yes" # Avision AV210 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a24", ENV{libsane_matched}="yes" # Avision AV210 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a25", ENV{libsane_matched}="yes" # Avision AV120 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a27", ENV{libsane_matched}="yes" # Avision AV220C2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2a", ENV{libsane_matched}="yes" # Avision AV220D2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2b", ENV{libsane_matched}="yes" # Avision AV220+ ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2c", ENV{libsane_matched}="yes" # Avision AV220C2-G ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2d", ENV{libsane_matched}="yes" # Avision AV220C2-B ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2e", ENV{libsane_matched}="yes" # Avision AV210C2-G ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2f", ENV{libsane_matched}="yes" # Avision AV122 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a33", ENV{libsane_matched}="yes" # Avision AV210C2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a3a", ENV{libsane_matched}="yes" # Avision AV121 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a3c", ENV{libsane_matched}="yes" # Avision AV8300 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a40", ENV{libsane_matched}="yes" # Avision AM3000 Series ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a41", ENV{libsane_matched}="yes" # Avision @V5100 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a45", ENV{libsane_matched}="yes" # Avision AV8050U ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a4d", ENV{libsane_matched}="yes" # Avision AV3200SU ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a4e", ENV{libsane_matched}="yes" # Avision AV3730SU ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a4f", ENV{libsane_matched}="yes" # Avision AV610C2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a5e", ENV{libsane_matched}="yes" # Avision IT8300 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a61", ENV{libsane_matched}="yes" # Avision AV3750SU ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a65", ENV{libsane_matched}="yes" # Avision AV3850SU ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a66", ENV{libsane_matched}="yes" # Avision AV8350 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a68", ENV{libsane_matched}="yes" # Avision FB6080E ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a82", ENV{libsane_matched}="yes" # Avision FB2080E ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a84", ENV{libsane_matched}="yes" # Avision AV122 C2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a93", ENV{libsane_matched}="yes" # Avision AV220-G ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a94", ENV{libsane_matched}="yes" # Avision @V2500 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0aa1", ENV{libsane_matched}="yes" # Avision AV210D2+ ATTRS{idVendor}=="0638", ATTRS{idProduct}=="1a35", ENV{libsane_matched}="yes" # Minolta Elite II ATTRS{idVendor}=="0686", ATTRS{idProduct}=="4004", ENV{libsane_matched}="yes" # Minolta Dimage Scan Dual III ATTRS{idVendor}=="0686", ATTRS{idProduct}=="400d", ENV{libsane_matched}="yes" # Minolta Dimage Scan Elite 5400 ATTRS{idVendor}=="0686", ATTRS{idProduct}=="400e", ENV{libsane_matched}="yes" # AGFA SnapScan 1212U ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="0001", ENV{libsane_matched}="yes" # AGFA SnapScan 1236u ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="0002", ENV{libsane_matched}="yes" # Agfa Snapscan Touch ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="0100", ENV{libsane_matched}="yes" # AGFA SnapScan 1212U_2 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2061", ENV{libsane_matched}="yes" # AGFA SnapScan e40 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="208d", ENV{libsane_matched}="yes" # AGFA SnapScan e50 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="208f", ENV{libsane_matched}="yes" # AGFA SnapScan e20 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2091", ENV{libsane_matched}="yes" # AGFA SnapScan e10 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2093", ENV{libsane_matched}="yes" # AGFA SnapScan e25 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2095", ENV{libsane_matched}="yes" # AGFA SnapScan e26 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2097", ENV{libsane_matched}="yes" # AGFA SnapScan e52 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="20fd", ENV{libsane_matched}="yes" # AGFA SnapScan e42 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="20ff", ENV{libsane_matched}="yes" # UMAX Astra 4900 ATTRS{idVendor}=="06dc", ATTRS{idProduct}=="0020", ENV{libsane_matched}="yes" # Plustek OpticPro U12 | Plustek OpticPro UT12 | Plustek OpticPro 1212U # RevScan RevScan Orange R48Ti | Genius ColorPage Vivid III USB ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0001", ENV{libsane_matched}="yes" # Plustek OpticPro U12 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0010", ENV{libsane_matched}="yes" # Plustek OpticPro U24 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0011", ENV{libsane_matched}="yes" # Plustek OpticPro UT12 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0013", ENV{libsane_matched}="yes" # Plustek OpticPro U24 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0015", ENV{libsane_matched}="yes" # Plustek OpticPro UT12 | Plustek OpticPro UT16 | Plustek OpticPro UT24 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0017", ENV{libsane_matched}="yes" # Plustek OpticPro 1248U | RevScan 19200i ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0400", ENV{libsane_matched}="yes" # Plustek OpticPro 1248U ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0401", ENV{libsane_matched}="yes" # Plustek OpticPro U16B ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0402", ENV{libsane_matched}="yes" # Plustek OpticPro U16B+ | Plustek OpticPro UT16B ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0403", ENV{libsane_matched}="yes" # Nortek MyScan 1200 | Plustek OpticPro S12 | Plustek OpticPro ST12 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="040b", ENV{libsane_matched}="yes" # Plustek OpticPro S24 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="040e", ENV{libsane_matched}="yes" # NeatReceipts Scanalizer Professional 2.5 | Plustek OpticSlim M12 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0412", ENV{libsane_matched}="yes" # Plustek OpticSlim 1200 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0413", ENV{libsane_matched}="yes" # Plustek OpticSlim 2400 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0422", ENV{libsane_matched}="yes" # Plustek OpticSlim 2400 plus ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0454", ENV{libsane_matched}="yes" # Plustek Iriscan Express 2 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="045f", ENV{libsane_matched}="yes" # NeatReceipts Mobile Scanner ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0462", ENV{libsane_matched}="yes" # Plustek OpticBook 3600 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0900", ENV{libsane_matched}="yes" # Corex 600c ATTRS{idVendor}=="08f0", ATTRS{idProduct}=="0002", ENV{libsane_matched}="yes" # Corex 800c ATTRS{idVendor}=="08f0", ATTRS{idProduct}=="0005", ENV{libsane_matched}="yes" # Xerox Phaser 6110MFP ATTRS{idVendor}=="0924", ATTRS{idProduct}=="3d5d", ENV{libsane_matched}="yes" # Xerox Phaser 3200MFP ATTRS{idVendor}=="0924", ATTRS{idProduct}=="3da4", ENV{libsane_matched}="yes" # Xerox WorkCentre 4118 Series ATTRS{idVendor}=="0924", ATTRS{idProduct}=="420c", ENV{libsane_matched}="yes" # Xerox WorkCentre 3119 Series ATTRS{idVendor}=="0924", ATTRS{idProduct}=="4265", ENV{libsane_matched}="yes" # Xerox WorkCentre 3210 ATTRS{idVendor}=="0924", ATTRS{idProduct}=="4293", ENV{libsane_matched}="yes" # Xerox WorkCentre 3220 ATTRS{idVendor}=="0924", ATTRS{idProduct}=="4294", ENV{libsane_matched}="yes" # Pentax DSmobile 600 ATTRS{idVendor}=="0a17", ATTRS{idProduct}=="3210", ENV{libsane_matched}="yes" # Portable Peripheral Co., Ltd. Q-Scan USB001 (A4 portable scanner) ATTRS{idVendor}=="0a53", ATTRS{idProduct}=="1000", ENV{libsane_matched}="yes" # Portable Peripheral Co., Ltd. Q-Scan USB201 (A6 portable scanner) ATTRS{idVendor}=="0a53", ATTRS{idProduct}=="2000", ENV{libsane_matched}="yes" # Syscan TravelScan 460/464 | Ambir Visigo A4 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="4600", ENV{libsane_matched}="yes" # Syscan DocketPort 465 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="4802", ENV{libsane_matched}="yes" # Syscan DocketPort 665 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="4803", ENV{libsane_matched}="yes" # Syscan DocketPort 685/ Ambir DS685 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="480c", ENV{libsane_matched}="yes" # Syscan DocketPort 485 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="4810", ENV{libsane_matched}="yes" # Syscan TravelScan 662 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="6620", ENV{libsane_matched}="yes" # Canon CR-55 ATTRS{idVendor}=="1083", ATTRS{idProduct}=="160c", ENV{libsane_matched}="yes" # Canon DR-1210C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="160f", ENV{libsane_matched}="yes" # Canon DR-4010C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1614", ENV{libsane_matched}="yes" # Canon DR-2510C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1617", ENV{libsane_matched}="yes" # Canon DR-X10C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1618", ENV{libsane_matched}="yes" # Canon CR-25 ATTRS{idVendor}=="1083", ATTRS{idProduct}=="161a", ENV{libsane_matched}="yes" # Canon DR-2010C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="161b", ENV{libsane_matched}="yes" # Canon DR-3010C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="161d", ENV{libsane_matched}="yes" # Canon DR-7090C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1620", ENV{libsane_matched}="yes" # Canon DR-9050C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1622", ENV{libsane_matched}="yes" # Canon DR-7550C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1623", ENV{libsane_matched}="yes" # Canon DR-6050C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1624", ENV{libsane_matched}="yes" # Canon DR-6010C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1626", ENV{libsane_matched}="yes" # Canon CR-190i ATTRS{idVendor}=="1083", ATTRS{idProduct}=="162b", ENV{libsane_matched}="yes" # Canon DR-6030C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1638", ENV{libsane_matched}="yes" # Canon CR-135i ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1639", ENV{libsane_matched}="yes" # Digital Dream l' espion XS ATTRS{idVendor}=="1183", ATTRS{idProduct}=="0001", ENV{libsane_matched}="yes" # KONICA MINOLTA magicolor 1690MF ATTRS{idVendor}=="132b", ATTRS{idProduct}=="2089", ENV{libsane_matched}="yes" # UMAX Astra 1220U ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0010", ENV{libsane_matched}="yes" # UMAX Astra 1600U | UMAX Astra 2000U ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0030", ENV{libsane_matched}="yes" # Umax UMAX 3400 ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0050", ENV{libsane_matched}="yes" # Umax UMAX 3400 | Umax UMAX Astranet ia101 | Umax UMAX 3450 ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0060", ENV{libsane_matched}="yes" # UMAX Astra 4400 | UMAX Astra 4450 ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0070", ENV{libsane_matched}="yes" # UMAX Astra 2100U ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0130", ENV{libsane_matched}="yes" # Umax UMAX 5400 ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0160", ENV{libsane_matched}="yes" # UMAX Astra 2200 (SU) ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0230", ENV{libsane_matched}="yes" # DCT DocketPort 487 ATTRS{idVendor}=="1dcc", ATTRS{idProduct}=="4810", ENV{libsane_matched}="yes" # Dell A920 ATTRS{idVendor}=="413c", ATTRS{idProduct}=="5105", ENV{libsane_matched}="yes" # Dell Dell MFP Laser Printer 1815dn ATTRS{idVendor}=="413c", ATTRS{idProduct}=="5124", ENV{libsane_matched}="yes" # Dell 1600n ATTRS{idVendor}=="413c", ATTRS{idProduct}=="5250", ENV{libsane_matched}="yes" # The following rule will disable USB autosuspend for the device ENV{libsane_matched}=="yes", RUN+="/bin/sh -c 'if test -e /sys/$env{DEVPATH}/power/control; then echo on > /sys/$env{DEVPATH}/power/control; elif test -e /sys/$env{DEVPATH}/power/level; then echo on > /sys/$env{DEVPATH}/power/level; fi'" LABEL="libsane_usb_rules_end" SUBSYSTEMS=="scsi", GOTO="libsane_scsi_rules_begin" GOTO="libsane_scsi_rules_end" LABEL="libsane_scsi_rules_begin" # Generic: SCSI device type 6 indicates a scanner KERNEL=="sg[0-9]*", ATTRS{type}=="6", ENV{libsane_matched}="yes" # Some scanners advertise themselves as SCSI device type 3 # Wildcard: for some Epson SCSI scanners KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="SCANNER*", ENV{libsane_matched}="yes" # Epson Perfection 2450 | Epson Perfection 2450 PHOTO KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="GT-9700", ENV{libsane_matched}="yes" # Epson Perfection 3200 | Epson Perfection 3200 PHOTO KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="GT-9800", ENV{libsane_matched}="yes" # Epson Perfection 636S | Epson Perfection 1200S KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="Perfection1200", ENV{libsane_matched}="yes" # Epson Perfection 636 KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="Perfection636", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4p KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1130A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIc KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1750A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIp KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1790A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIcx KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C2500A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4c KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C2520A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5p KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C5110A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6200C KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C6270A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6300C KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C7670A", ENV{libsane_matched}="yes" LABEL="libsane_scsi_rules_end" ENV{libsane_matched}=="yes", RUN+="/bin/setfacl -m g:scanner:rw $env{DEVNAME}" LABEL="libsane_rules_end" sane-backends-1.0.27/testsuite/tools/data/usermap.ref0000664000175000017500000024330712775312262017516 00000000000000# This file was automatically created based on description files (*.desc) # by sane-desc 3.5 from sane-backends 1.0.24git on Wed Jul 31 07:52:48 2013 # # The entries below are used to detect a USB device and change owner # and permissions on the "device node" used by libusb. # # The 0x0003 match flag means the device is matched by its vendor and # product IDs. # # Sample entry (replace 0xVVVV and 0xPPPP with vendor ID and product ID # respectively): # # libusbscanner 0x0003 0xVVVV 0xPPPP 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # usb module match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info # # If your scanner isn't listed below, you can add it as explained above. # # If your scanner is supported by some external backend (brother, epkowa, # hpaio, etc) please ask the author of the backend to provide proper # device detection support for your OS # # If the scanner is supported by sane-backends, please mail the entry to # the sane-devel mailing list (sane-devel@lists.alioth.debian.org). # # Hewlett-Packard ScanJet 4100C libusbscanner 0x0003 0x03f0 0x0101 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 4200C | Hewlett-Packard ScanJet 4200Cxi | Hewlett-Packard ScanJet 4200Cse libusbscanner 0x0003 0x03f0 0x0105 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 6200C | Hewlett-Packard ScanJet 6250C libusbscanner 0x0003 0x03f0 0x0201 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 3300c libusbscanner 0x0003 0x03f0 0x0205 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 4300c libusbscanner 0x0003 0x03f0 0x0305 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 5200C libusbscanner 0x0003 0x03f0 0x0401 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 3400c libusbscanner 0x0003 0x03f0 0x0405 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 2100C libusbscanner 0x0003 0x03f0 0x0505 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 6300C | Hewlett-Packard ScanJet 6350C | Hewlett-Packard ScanJet 6390C libusbscanner 0x0003 0x03f0 0x0601 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 2200C libusbscanner 0x0003 0x03f0 0x0605 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 5300C | Hewlett-Packard ScanJet 5370C libusbscanner 0x0003 0x03f0 0x0701 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard scanjet 4400c libusbscanner 0x0003 0x03f0 0x0705 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 7400c | Hewlett-Packard ScanJet 7450c | Hewlett-Packard ScanJet 7490c libusbscanner 0x0003 0x03f0 0x0801 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard scanjet 4470c libusbscanner 0x0003 0x03f0 0x0805 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 2300C libusbscanner 0x0003 0x03f0 0x0901 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 2400C | Hewlett-Packard ScanJet G2410 libusbscanner 0x0003 0x03f0 0x0a01 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 8200 | Hewlett-Packard ScanJet 8250 | Hewlett-Packard ScanJet 8290 libusbscanner 0x0003 0x03f0 0x0b01 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 5400c libusbscanner 0x0003 0x03f0 0x1005 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 5470c libusbscanner 0x0003 0x03f0 0x1105 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 4500C | Hewlett-Packard ScanJet 5550C libusbscanner 0x0003 0x03f0 0x1205 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 4570C | Hewlett-Packard ScanJet 5500C libusbscanner 0x0003 0x03f0 0x1305 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 3670C | Hewlett-Packard ScanJet 3690C libusbscanner 0x0003 0x03f0 0x1405 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 5590 libusbscanner 0x0003 0x03f0 0x1705 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 7650 libusbscanner 0x0003 0x03f0 0x1805 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 4850C libusbscanner 0x0003 0x03f0 0x1b05 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 3530C | Hewlett-Packard ScanJet 3570C libusbscanner 0x0003 0x03f0 0x2005 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 3500C libusbscanner 0x0003 0x03f0 0x2205 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 3970c libusbscanner 0x0003 0x03f0 0x2305 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 4070 Photosmart libusbscanner 0x0003 0x03f0 0x2405 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 3800 libusbscanner 0x0003 0x03f0 0x2605 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet G2710 libusbscanner 0x0003 0x03f0 0x2805 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 8300 | Hewlett-Packard ScanJet 8350 | Hewlett-Packard ScanJet 8390 libusbscanner 0x0003 0x03f0 0x3805 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 8270 libusbscanner 0x0003 0x03f0 0x3905 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard LaserJet M1005 MFP libusbscanner 0x0003 0x03f0 0x3b17 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 4370 libusbscanner 0x0003 0x03f0 0x4105 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet G3010 libusbscanner 0x0003 0x03f0 0x4205 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet G3110 libusbscanner 0x0003 0x03f0 0x4305 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet G4010 libusbscanner 0x0003 0x03f0 0x4505 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet G4050 libusbscanner 0x0003 0x03f0 0x4605 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet N6310 libusbscanner 0x0003 0x03f0 0x4705 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard LaserJet M1120 MFP libusbscanner 0x0003 0x03f0 0x5617 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard LaserJet M1120n MFP libusbscanner 0x0003 0x03f0 0x5717 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 1200 libusbscanner 0x0003 0x0400 0x1000 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 1200 | Mustek BearPaw 2400 libusbscanner 0x0003 0x0400 0x1001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 5100 libusbscanner 0x0003 0x040a 0x4025 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 5300 libusbscanner 0x0003 0x040a 0x4026 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 5500 libusbscanner 0x0003 0x040a 0x4027 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 5000 libusbscanner 0x0003 0x040a 0x4028 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 3300 libusbscanner 0x0003 0x040a 0x4031 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 5 libusbscanner 0x0003 0x040a 0x4032 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 7 libusbscanner 0x0003 0x040a 0x403e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 9 libusbscanner 0x0003 0x040a 0x403f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 5200 libusbscanner 0x0003 0x040a 0x4041 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 3200 libusbscanner 0x0003 0x040a 0x4043 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 4100 libusbscanner 0x0003 0x040a 0x4053 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 6100 libusbscanner 0x0003 0x040a 0x4054 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 7200 libusbscanner 0x0003 0x040a 0x4056 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP C110 libusbscanner 0x0003 0x040a 0x4057 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP C115 libusbscanner 0x0003 0x040a 0x4058 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 2150 libusbscanner 0x0003 0x040a 0x4059 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP C310 libusbscanner 0x0003 0x040a 0x405d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP C315 libusbscanner 0x0003 0x040a 0x405e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Advent AW10 libusbscanner 0x0003 0x040a 0x4060 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak Hero Office 6.1 libusbscanner 0x0003 0x040a 0x4062 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak Hero 7.1 libusbscanner 0x0003 0x040a 0x4063 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak Hero 5.1 libusbscanner 0x0003 0x040a 0x4064 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 9200 libusbscanner 0x0003 0x040a 0x4065 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak ESP 2170 libusbscanner 0x0003 0x040a 0x4066 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak Hero 9.1 libusbscanner 0x0003 0x040a 0x4067 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak Hero 3.1 libusbscanner 0x0003 0x040a 0x406d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak i30 libusbscanner 0x0003 0x040a 0x6001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak i40 libusbscanner 0x0003 0x040a 0x6002 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak i50 | Kodak i55 libusbscanner 0x0003 0x040a 0x6003 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak i60 | Kodak i65 libusbscanner 0x0003 0x040a 0x6004 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kodak i80 libusbscanner 0x0003 0x040a 0x6005 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Creative WebCam Go Mini libusbscanner 0x0003 0x041e 0x4007 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Lexmark X70 | Lexmark X73 libusbscanner 0x0003 0x043d 0x002d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Lexmark X74 libusbscanner 0x0003 0x043d 0x0060 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Lexmark X1110 | Lexmark X1130 | Lexmark X1140 | Lexmark X1150 | Lexmark X1170 | Lexmark X1180 | Lexmark X1185 | Lexmark X1195 libusbscanner 0x0003 0x043d 0x007c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Lexmark X12xx libusbscanner 0x0003 0x043d 0x007d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius ColorPage HR6 V1 libusbscanner 0x0003 0x0458 0x2004 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage HR6 V2 libusbscanner 0x0003 0x0458 0x2007 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage HR6 V2 libusbscanner 0x0003 0x0458 0x2008 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage HR6A libusbscanner 0x0003 0x0458 0x2009 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage Vivid3x | Genius Colorpage Vivid3 V2 libusbscanner 0x0003 0x0458 0x2011 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage HR7 libusbscanner 0x0003 0x0458 0x2013 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage Vivid4 libusbscanner 0x0003 0x0458 0x2014 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage HR7LE libusbscanner 0x0003 0x0458 0x2015 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage HR6X libusbscanner 0x0003 0x0458 0x2016 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage Vivid3xe libusbscanner 0x0003 0x0458 0x2017 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage Vivid4xe libusbscanner 0x0003 0x0458 0x201a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage Vivid4x libusbscanner 0x0003 0x0458 0x201b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage Vivid 1200 X libusbscanner 0x0003 0x0458 0x201d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius ColorPage Slim 1200 libusbscanner 0x0003 0x0458 0x201e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage Vivid 1200 XE libusbscanner 0x0003 0x0458 0x201f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Genius Colorpage SF600 libusbscanner 0x0003 0x0458 0x2021 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Medion/Lifetec/Tevion/Cytron MD5345 | Medion/Lifetec/Tevion/Cytron MD6228 | Medion/Lifetec/Tevion/Cytron MD6471 libusbscanner 0x0003 0x0461 0x0377 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox 2400 Onetouch libusbscanner 0x0003 0x0461 0x038b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Trust Office Scan USB 19200 libusbscanner 0x0003 0x047b 0x1000 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Hewlett-Packard ScanJet 4300c/Silitek libusbscanner 0x0003 0x047b 0x1002 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Kyocera FS-1016MFP libusbscanner 0x0003 0x0482 0x0335 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Compaq S4-100 libusbscanner 0x0003 0x049f 0x001a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 310U libusbscanner 0x0003 0x04a5 0x1a20 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 620U libusbscanner 0x0003 0x04a5 0x1a2a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 320U | Benq (Acer) 340U | Mitsubishi Diamondview 648UT libusbscanner 0x0003 0x04a5 0x2022 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 620UT libusbscanner 0x0003 0x04a5 0x2040 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 640U | Guillemot / Hercules Maxi Scan A4 USB 640U | Guillemot / Hercules Maxi A4 36 bit libusbscanner 0x0003 0x04a5 0x2060 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 640bu libusbscanner 0x0003 0x04a5 0x207e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 3300 | Benq (Acer) 4300 | Mitsubishi Diamondview 650U libusbscanner 0x0003 0x04a5 0x20b0 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 640BT libusbscanner 0x0003 0x04a5 0x20be 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 1240 libusbscanner 0x0003 0x04a5 0x20c0 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 3300 | Benq (Acer) 4300 | Guillemot / Hercules Scan@home Touch 1248 (USB) libusbscanner 0x0003 0x04a5 0x20de 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 5000 libusbscanner 0x0003 0x04a5 0x20f8 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 5000E | Benq (Acer) 5000U libusbscanner 0x0003 0x04a5 0x20fc 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 5300 libusbscanner 0x0003 0x04a5 0x20fe 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Benq (Acer) 5150 | Benq (Acer) 5250 libusbscanner 0x0003 0x04a5 0x2137 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # BenQ 5550 libusbscanner 0x0003 0x04a5 0x2211 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Visioneer OneTouch 7100 libusbscanner 0x0003 0x04a7 0x0229 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer 9650 libusbscanner 0x0003 0x04a7 0x0390 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer 9320 libusbscanner 0x0003 0x04a7 0x0420 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer 9450 libusbscanner 0x0003 0x04a7 0x0421 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer 9550 libusbscanner 0x0003 0x04a7 0x0422 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer 9750 libusbscanner 0x0003 0x04a7 0x0423 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Strobe XP 450 libusbscanner 0x0003 0x04a7 0x0424 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Strobe XP 200 libusbscanner 0x0003 0x04a7 0x0426 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Strobe XP 100 libusbscanner 0x0003 0x04a7 0x0427 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer OneTouch 7300 libusbscanner 0x0003 0x04a7 0x0444 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate510 libusbscanner 0x0003 0x04a7 0x0446 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate520 libusbscanner 0x0003 0x04a7 0x0447 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate250 libusbscanner 0x0003 0x04a7 0x0448 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate252 libusbscanner 0x0003 0x04a7 0x0449 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate262 libusbscanner 0x0003 0x04a7 0x044c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Strobe XP 300 libusbscanner 0x0003 0x04a7 0x0474 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate272 libusbscanner 0x0003 0x04a7 0x0475 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate232 libusbscanner 0x0003 0x04a7 0x0476 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate152 libusbscanner 0x0003 0x04a7 0x0477 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate752 libusbscanner 0x0003 0x04a7 0x0478 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Strobe XP 470 libusbscanner 0x0003 0x04a7 0x0479 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer 9450-G libusbscanner 0x0003 0x04a7 0x047a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer 9650-G libusbscanner 0x0003 0x04a7 0x047b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate510-G libusbscanner 0x0003 0x04a7 0x047c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate252-G libusbscanner 0x0003 0x04a7 0x048c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate262-G libusbscanner 0x0003 0x04a7 0x048d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate272-G libusbscanner 0x0003 0x04a7 0x048e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Strobe XP 470-G | Visioneer Patriot 470 libusbscanner 0x0003 0x04a7 0x048f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate250-G libusbscanner 0x0003 0x04a7 0x0490 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Strobe XP 450-G libusbscanner 0x0003 0x04a7 0x0491 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate520-G libusbscanner 0x0003 0x04a7 0x0492 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer 9750-G libusbscanner 0x0003 0x04a7 0x0493 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Roadwarrior libusbscanner 0x0003 0x04a7 0x0494 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate512 libusbscanner 0x0003 0x04a7 0x0495 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Patriot 430 libusbscanner 0x0003 0x04a7 0x0497 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Patriot 680 | Xerox DocuMate632 libusbscanner 0x0003 0x04a7 0x0498 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Patriot 780 libusbscanner 0x0003 0x04a7 0x0499 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate752 libusbscanner 0x0003 0x04a7 0x049a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Visioneer Strobe XP 100,r3 libusbscanner 0x0003 0x04a7 0x049b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate150 libusbscanner 0x0003 0x04a7 0x049c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate162 libusbscanner 0x0003 0x04a7 0x049d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox DocuMate262i libusbscanner 0x0003 0x04a7 0x04a7 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox Travel Scanner 100 libusbscanner 0x0003 0x04a7 0x04ac 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-2080C libusbscanner 0x0003 0x04a9 0x1601 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CR-180 | Canon CR-180II libusbscanner 0x0003 0x04a9 0x1602 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-9080C libusbscanner 0x0003 0x04a9 0x1603 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-7080C libusbscanner 0x0003 0x04a9 0x1604 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-5010C libusbscanner 0x0003 0x04a9 0x1606 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-6080 libusbscanner 0x0003 0x04a9 0x1607 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-2580C libusbscanner 0x0003 0x04a9 0x1608 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-3080CII libusbscanner 0x0003 0x04a9 0x1609 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-2050C | Canon DR-2050SP libusbscanner 0x0003 0x04a9 0x160a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-7580 libusbscanner 0x0003 0x04a9 0x160b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP750 libusbscanner 0x0003 0x04a9 0x1706 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP780 | Canon PIXMA MP790 libusbscanner 0x0003 0x04a9 0x1707 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP760 | Canon PIXMA MP770 libusbscanner 0x0003 0x04a9 0x1708 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP150 libusbscanner 0x0003 0x04a9 0x1709 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP170 libusbscanner 0x0003 0x04a9 0x170a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP450 libusbscanner 0x0003 0x04a9 0x170b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP500 libusbscanner 0x0003 0x04a9 0x170c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP800 libusbscanner 0x0003 0x04a9 0x170d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP800R libusbscanner 0x0003 0x04a9 0x170e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP530 libusbscanner 0x0003 0x04a9 0x1712 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP830 libusbscanner 0x0003 0x04a9 0x1713 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP160 libusbscanner 0x0003 0x04a9 0x1714 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP180 libusbscanner 0x0003 0x04a9 0x1715 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP460 libusbscanner 0x0003 0x04a9 0x1716 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP510 libusbscanner 0x0003 0x04a9 0x1717 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP600 libusbscanner 0x0003 0x04a9 0x1718 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP600R libusbscanner 0x0003 0x04a9 0x1719 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP810 libusbscanner 0x0003 0x04a9 0x171a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP960 libusbscanner 0x0003 0x04a9 0x171b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX7600 libusbscanner 0x0003 0x04a9 0x171c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP210 libusbscanner 0x0003 0x04a9 0x1721 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP220 libusbscanner 0x0003 0x04a9 0x1722 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP470 libusbscanner 0x0003 0x04a9 0x1723 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP520 libusbscanner 0x0003 0x04a9 0x1724 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP610 libusbscanner 0x0003 0x04a9 0x1725 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP970 libusbscanner 0x0003 0x04a9 0x1726 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX300 libusbscanner 0x0003 0x04a9 0x1727 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX310 libusbscanner 0x0003 0x04a9 0x1728 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX700 libusbscanner 0x0003 0x04a9 0x1729 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP140 libusbscanner 0x0003 0x04a9 0x172b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX850 libusbscanner 0x0003 0x04a9 0x172c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP980 libusbscanner 0x0003 0x04a9 0x172d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP630 libusbscanner 0x0003 0x04a9 0x172e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP620 libusbscanner 0x0003 0x04a9 0x172f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP540 libusbscanner 0x0003 0x04a9 0x1730 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP480 libusbscanner 0x0003 0x04a9 0x1731 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP240 libusbscanner 0x0003 0x04a9 0x1732 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP260 libusbscanner 0x0003 0x04a9 0x1733 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP190 libusbscanner 0x0003 0x04a9 0x1734 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX860 libusbscanner 0x0003 0x04a9 0x1735 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX320 libusbscanner 0x0003 0x04a9 0x1736 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX330 libusbscanner 0x0003 0x04a9 0x1737 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP250 libusbscanner 0x0003 0x04a9 0x173a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP270 libusbscanner 0x0003 0x04a9 0x173b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP490 libusbscanner 0x0003 0x04a9 0x173c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP550 libusbscanner 0x0003 0x04a9 0x173d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP560 libusbscanner 0x0003 0x04a9 0x173e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP640 libusbscanner 0x0003 0x04a9 0x173f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP990 libusbscanner 0x0003 0x04a9 0x1740 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX340 libusbscanner 0x0003 0x04a9 0x1741 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX350 libusbscanner 0x0003 0x04a9 0x1742 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX870 libusbscanner 0x0003 0x04a9 0x1743 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP280 libusbscanner 0x0003 0x04a9 0x1746 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP495 libusbscanner 0x0003 0x04a9 0x1747 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG5100 Series libusbscanner 0x0003 0x04a9 0x1748 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG5200 Series libusbscanner 0x0003 0x04a9 0x1749 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG6100 Series libusbscanner 0x0003 0x04a9 0x174a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG8100 Series libusbscanner 0x0003 0x04a9 0x174b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX360 libusbscanner 0x0003 0x04a9 0x174d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX410 libusbscanner 0x0003 0x04a9 0x174e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX420 libusbscanner 0x0003 0x04a9 0x174f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX880 Series | Canon PIXMA MX882 | Canon PIXMA MX885 libusbscanner 0x0003 0x04a9 0x1750 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG2100 Series libusbscanner 0x0003 0x04a9 0x1751 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG3100 Series libusbscanner 0x0003 0x04a9 0x1752 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG4100 Series libusbscanner 0x0003 0x04a9 0x1753 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG5300 Series libusbscanner 0x0003 0x04a9 0x1754 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG6200 Series libusbscanner 0x0003 0x04a9 0x1755 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG8200 Series libusbscanner 0x0003 0x04a9 0x1756 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP493 libusbscanner 0x0003 0x04a9 0x1757 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA E500 libusbscanner 0x0003 0x04a9 0x1758 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX370 Series libusbscanner 0x0003 0x04a9 0x1759 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA E600 libusbscanner 0x0003 0x04a9 0x175a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX430 Series libusbscanner 0x0003 0x04a9 0x175b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX510 Series libusbscanner 0x0003 0x04a9 0x175c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX710 Series libusbscanner 0x0003 0x04a9 0x175d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX890 Series libusbscanner 0x0003 0x04a9 0x175e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP230 libusbscanner 0x0003 0x04a9 0x175f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG2200 Series libusbscanner 0x0003 0x04a9 0x1760 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA E510 libusbscanner 0x0003 0x04a9 0x1761 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG3200 Series libusbscanner 0x0003 0x04a9 0x1762 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG4200 Series libusbscanner 0x0003 0x04a9 0x1763 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG5400 Series libusbscanner 0x0003 0x04a9 0x1764 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MG6300 Series libusbscanner 0x0003 0x04a9 0x1765 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX390 Series libusbscanner 0x0003 0x04a9 0x1766 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA E610 libusbscanner 0x0003 0x04a9 0x1767 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX450 Series libusbscanner 0x0003 0x04a9 0x1768 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX520 Series libusbscanner 0x0003 0x04a9 0x1769 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX720 Series libusbscanner 0x0003 0x04a9 0x176a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MX920 Series libusbscanner 0x0003 0x04a9 0x176b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan 8800F libusbscanner 0x0003 0x04a9 0x1901 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan LiDE 100 libusbscanner 0x0003 0x04a9 0x1904 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan LiDE 200 libusbscanner 0x0003 0x04a9 0x1905 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan 700F libusbscanner 0x0003 0x04a9 0x1907 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan 9000F libusbscanner 0x0003 0x04a9 0x1908 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan LiDE 110 libusbscanner 0x0003 0x04a9 0x1909 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan LiDE 210 libusbscanner 0x0003 0x04a9 0x190a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan 9000F Mark II libusbscanner 0x0003 0x04a9 0x190d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan fb630u | Canon CanoScan fb636u libusbscanner 0x0003 0x04a9 0x2204 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan N650U/N656U libusbscanner 0x0003 0x04a9 0x2206 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan N1220U libusbscanner 0x0003 0x04a9 0x2207 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan D660U libusbscanner 0x0003 0x04a9 0x2208 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan N670U/N676U/LiDE20 libusbscanner 0x0003 0x04a9 0x220d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan N1240U/LiDE30 libusbscanner 0x0003 0x04a9 0x220e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan LiDE 35 | Canon CanoScan LiDE 40 | Canon CanoScan LiDE 50 libusbscanner 0x0003 0x04a9 0x2213 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan LiDE 60 libusbscanner 0x0003 0x04a9 0x221c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CanoScan LiDE25 libusbscanner 0x0003 0x04a9 0x2220 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-1210C libusbscanner 0x0003 0x04a9 0x2222 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP730 libusbscanner 0x0003 0x04a9 0x262f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP700 libusbscanner 0x0003 0x04a9 0x2630 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP360 libusbscanner 0x0003 0x04a9 0x263c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP370 libusbscanner 0x0003 0x04a9 0x263d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP390 libusbscanner 0x0003 0x04a9 0x263e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP375R libusbscanner 0x0003 0x04a9 0x263f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP740 libusbscanner 0x0003 0x04a9 0x264c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon PIXMA MP710 libusbscanner 0x0003 0x04a9 0x264d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF5630 libusbscanner 0x0003 0x04a9 0x264e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon laserBase MF5650 libusbscanner 0x0003 0x04a9 0x264f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF8170c libusbscanner 0x0003 0x04a9 0x2659 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF5730 libusbscanner 0x0003 0x04a9 0x265d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF5750 libusbscanner 0x0003 0x04a9 0x265e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF5770 libusbscanner 0x0003 0x04a9 0x265f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF3110 libusbscanner 0x0003 0x04a9 0x2660 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF3240 libusbscanner 0x0003 0x04a9 0x2684 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF6500 series | Canon imageCLASS MF6550 libusbscanner 0x0003 0x04a9 0x2686 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF4120 | Canon imageCLASS MF4122 | Canon imageCLASS MF4140 | Canon imageCLASS MF4150 libusbscanner 0x0003 0x04a9 0x26a3 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF4660 | Canon imageCLASS MF4690 libusbscanner 0x0003 0x04a9 0x26b0 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF4010 | Canon imageCLASS MF4018 libusbscanner 0x0003 0x04a9 0x26b4 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF4270 libusbscanner 0x0003 0x04a9 0x26b5 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageRUNNER 1020/1024/1025 libusbscanner 0x0003 0x04a9 0x26e6 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF4370dn | Canon imageCLASS MF4380dn libusbscanner 0x0003 0x04a9 0x26ec 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS D480 libusbscanner 0x0003 0x04a9 0x26ed 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon I-SENSYS MF4320d | Canon I-SENSYS MF4330d | Canon imageCLASS MF4350d libusbscanner 0x0003 0x04a9 0x26ee 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS D420 libusbscanner 0x0003 0x04a9 0x26ef 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon i-SENSYS MF5880dn libusbscanner 0x0003 0x04a9 0x26f9 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon i-SENSYS MF6680dn libusbscanner 0x0003 0x04a9 0x26fa 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF8030 libusbscanner 0x0003 0x04a9 0x2707 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon i-SENSYS MF4550d libusbscanner 0x0003 0x04a9 0x2736 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon imageCLASS MF4410 | Canon imageCLASS MF4430 libusbscanner 0x0003 0x04a9 0x2737 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon i-SENSYS MF3010 libusbscanner 0x0003 0x04a9 0x2759 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Nikon LS 40 ED | Nikon LS 40 ED | Nikon Coolspan IV libusbscanner 0x0003 0x04b0 0x4000 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Nikon LS 50 ED | Nikon Coolscan V ED | Nikon LS 50 ED | Nikon Coolscan V ED libusbscanner 0x0003 0x04b0 0x4001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Nikon Super Coolscan LS-5000 ED | Nikon Super Coolscan LS-5000 ED libusbscanner 0x0003 0x04b0 0x4002 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 636U | Epson GT-7000U | Epson Perfection 636U libusbscanner 0x0003 0x04b8 0x0101 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 610 | Epson GT-6600U | Epson Perfection 610 libusbscanner 0x0003 0x04b8 0x0103 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1200U | Epson Perfection 1200Photo | Epson GT-7600U | Epson GT-7600UF | Epson Perfection 1200U | Epson Perfection 1200U PHOTO libusbscanner 0x0003 0x04b8 0x0104 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Stylus Scan 2000 libusbscanner 0x0003 0x04b8 0x0105 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Stylus Scan 2500 libusbscanner 0x0003 0x04b8 0x0106 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Expression 1600 | Epson ES-2000 | Epson Expression 1600 libusbscanner 0x0003 0x04b8 0x0107 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ES-8500 | Epson Expression 1640XL libusbscanner 0x0003 0x04b8 0x0109 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1640 | Epson GT-8700 | Epson GT-8700F | Epson Perfection 1640SU | Epson Perfection 1640SU PHOTO libusbscanner 0x0003 0x04b8 0x010a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1240 | Epson GT-7700U | Epson Perfection 1240U libusbscanner 0x0003 0x04b8 0x010b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 640 | Epson GT-6700U | Epson Perfection 640U libusbscanner 0x0003 0x04b8 0x010c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Expression 1680 | Epson ES-2200 | Epson Expression 1680 libusbscanner 0x0003 0x04b8 0x010e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1250 | Epson Perfection 1250Photo libusbscanner 0x0003 0x04b8 0x010f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1650 | Epson GT-8200U | Epson GT-8200UF | Epson Perfection 1650 | Epson Perfection 1650 PHOTO libusbscanner 0x0003 0x04b8 0x0110 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 2450 | Epson GT-9700F | Epson Perfection 2450 PHOTO libusbscanner 0x0003 0x04b8 0x0112 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 660 libusbscanner 0x0003 0x04b8 0x0114 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 2400 | Epson GT-9300UF | Epson Perfection 2400 PHOTO libusbscanner 0x0003 0x04b8 0x011b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 3200 | Epson GT-9800F | Epson Perfection 3200 PHOTO libusbscanner 0x0003 0x04b8 0x011c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1260 | Epson Perfection 1260Photo libusbscanner 0x0003 0x04b8 0x011d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1660 | Epson GT-8300UF | Epson Perfection 1660 PHOTO libusbscanner 0x0003 0x04b8 0x011e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1670 libusbscanner 0x0003 0x04b8 0x011f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 1270 libusbscanner 0x0003 0x04b8 0x0120 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 2480 | Epson Perfection 2580 libusbscanner 0x0003 0x04b8 0x0121 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 3490 | Epson Perfection 3590 libusbscanner 0x0003 0x04b8 0x0122 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ES-7000H | Epson GT-15000 libusbscanner 0x0003 0x04b8 0x0126 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 4870 | Epson GT-X700 | Epson Perfection 4870 PHOTO libusbscanner 0x0003 0x04b8 0x0128 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ES-10000G | Epson Expression 10000XL libusbscanner 0x0003 0x04b8 0x0129 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Perfection 4990 | Epson GT-X800 | Epson Perfection 4990 PHOTO libusbscanner 0x0003 0x04b8 0x012a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ES-H300 | Epson GT-2500 libusbscanner 0x0003 0x04b8 0x012b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson V700 | Epson V750 | Epson GT-X900 | Epson Perfection V700 Photo | Epson Perfection V750 Photo libusbscanner 0x0003 0x04b8 0x012c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson GT-X970 libusbscanner 0x0003 0x04b8 0x0135 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-5200 | Epson CX-5400 | Epson CC-600PX | Epson Stylus CX5100 | Epson Stylus CX5200 libusbscanner 0x0003 0x04b8 0x0801 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-3200 | Epson CC-570L | Epson Stylus CX3100 | Epson Stylus CX3200 libusbscanner 0x0003 0x04b8 0x0802 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-6300 | Epson CX-6400 | Epson Stylus CX6300 | Epson Stylus CX6400 libusbscanner 0x0003 0x04b8 0x0805 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson RX-600 | Epson PM-A850 | Epson Stylus Photo RX600 libusbscanner 0x0003 0x04b8 0x0806 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson RX-500 | Epson Stylus Photo RX500 | Epson Stylus Photo RX510 libusbscanner 0x0003 0x04b8 0x0807 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-5400 | Epson Stylus CX5300 | Epson Stylus CX5400 libusbscanner 0x0003 0x04b8 0x0808 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Stylus CX-1500 libusbscanner 0x0003 0x04b8 0x080c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-4600 | Epson Stylus CX4500 | Epson Stylus CX4600 libusbscanner 0x0003 0x04b8 0x080d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-3600 | Epson CX-3650 | Epson PX-A550 | Epson Stylus CX3500 | Epson Stylus CX3600 | Epson Stylus CX3650 libusbscanner 0x0003 0x04b8 0x080e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson RX-425 | Epson Stylus Photo RX420 | Epson Stylus Photo RX425 | Epson Stylus Photo RX430 libusbscanner 0x0003 0x04b8 0x080f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson RX-700 | Epson PM-A900 | Epson Stylus Photo RX700 libusbscanner 0x0003 0x04b8 0x0810 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson RX-620 | Epson PM-A870 | Epson Stylus Photo RX620 | Epson Stylus Photo RX630 libusbscanner 0x0003 0x04b8 0x0811 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-6500 | Epson CX-6600 | Epson Stylus CX6500 | Epson Stylus CX6600 libusbscanner 0x0003 0x04b8 0x0813 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A700 libusbscanner 0x0003 0x04b8 0x0814 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson AcuLaser CX11 | Epson AcuLaser CX11NF | Epson AcuLaser CX11 | Epson AcuLaser CX11NF | Epson LP-A500 libusbscanner 0x0003 0x04b8 0x0815 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson LP-M5500 | Epson LP-M5500F libusbscanner 0x0003 0x04b8 0x0817 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson DX-3850 | Epson CX-3700 | Epson CX-3800 | Epson DX-3800 | Epson Stylus CX3700 | Epson Stylus CX3800 | Epson Stylus DX3800 libusbscanner 0x0003 0x04b8 0x0818 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-4800 | Epson PX-A650 | Epson Stylus CX4700 | Epson Stylus CX4800 | Epson Stylus DX4800 | Epson Stylus DX4850 libusbscanner 0x0003 0x04b8 0x0819 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A750 | Epson Stylus Photo RX520 | Epson Stylus Photo RX530 libusbscanner 0x0003 0x04b8 0x081a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A890 | Epson Stylus Photo RX640 | Epson Stylus Photo RX650 libusbscanner 0x0003 0x04b8 0x081c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A950 libusbscanner 0x0003 0x04b8 0x081d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Stylus CX7700 | Epson Stylus CX7800 libusbscanner 0x0003 0x04b8 0x081f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-4200 | Epson Stylus CX4100 | Epson Stylus CX4200 | Epson Stylus DX4200 libusbscanner 0x0003 0x04b8 0x0820 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A820 | Epson Stylus Photo RX560 | Epson Stylus Photo RX580 | Epson Stylus Photo RX590 libusbscanner 0x0003 0x04b8 0x0827 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A970 libusbscanner 0x0003 0x04b8 0x0828 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-T990 libusbscanner 0x0003 0x04b8 0x0829 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A920 libusbscanner 0x0003 0x04b8 0x082a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson CX-5000 | Epson DX-5000 | Epson DX-5050 | Epson Stylus CX4900 | Epson Stylus CX5000 | Epson Stylus DX5000 libusbscanner 0x0003 0x04b8 0x082b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson DX-6000 | Epson PX-A720 | Epson Stylus CX5900 | Epson Stylus CX6000 | Epson Stylus DX6000 libusbscanner 0x0003 0x04b8 0x082e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson DX-4050 | Epson PX-A620 | Epson Stylus CX3900 | Epson Stylus DX4000 libusbscanner 0x0003 0x04b8 0x082f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ME 200 | Epson Stylus CX2800 | Epson Stylus CX2900 libusbscanner 0x0003 0x04b8 0x0830 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson LP-M5600 libusbscanner 0x0003 0x04b8 0x0833 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson LP-M6000 libusbscanner 0x0003 0x04b8 0x0834 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson AcuLaser CX21 libusbscanner 0x0003 0x04b8 0x0835 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-T960 libusbscanner 0x0003 0x04b8 0x0836 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A940 | Epson Stylus Photo RX680 | Epson Stylus Photo RX685 | Epson Stylus Photo RX690 libusbscanner 0x0003 0x04b8 0x0837 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson DX-7400 | Epson PX-A640 | Epson Stylus CX7300 | Epson Stylus CX7400 | Epson Stylus DX7400 libusbscanner 0x0003 0x04b8 0x0838 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PX-A740 | Epson Stylus CX8300 | Epson Stylus CX8400 | Epson Stylus DX8400 libusbscanner 0x0003 0x04b8 0x0839 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PX-FA700 | Epson Stylus CX9300F | Epson Stylus CX9400Fax | Epson Stylus DX9400F libusbscanner 0x0003 0x04b8 0x083a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PM-A840 | Epson PM-A840S | Epson Stylus Photo RX585 | Epson Stylus Photo RX595 | Epson Stylus Photo RX610 libusbscanner 0x0003 0x04b8 0x083c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ME 300 | Epson PX-401A | Epson Stylus NX100 | Epson Stylus SX100 | Epson Stylus TX100 libusbscanner 0x0003 0x04b8 0x0841 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson LP-M5000 libusbscanner 0x0003 0x04b8 0x0843 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Artisan 800 | Epson EP-901A | Epson EP-901F | Epson Stylus Photo PX800FW | Epson Stylus Photo TX800FW libusbscanner 0x0003 0x04b8 0x0844 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Artisan 700 | Epson EP-801A | Epson Stylus Photo PX700W | Epson Stylus Photo TX700W libusbscanner 0x0003 0x04b8 0x0846 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ME Office 700FW | Epson PX-601F | Epson Stylus Office BX600FW | Epson Stylus Office TX600FW | Epson Stylus SX600FW | Epson WorkForce 600 libusbscanner 0x0003 0x04b8 0x0847 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ME Office 600F | Epson Stylus Office BX300F | Epson Stylus Office TX300F | Epson Stylus NX300 libusbscanner 0x0003 0x04b8 0x0848 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Stylus NX200 | Epson Stylus SX200 | Epson Stylus SX205 | Epson Stylus TX200 | Epson Stylus TX203 | Epson Stylus TX209 libusbscanner 0x0003 0x04b8 0x0849 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PX-501A | Epson Stylus NX400 | Epson Stylus SX400 | Epson Stylus SX405 | Epson Stylus TX400 libusbscanner 0x0003 0x04b8 0x084a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson WorkForce 500 libusbscanner 0x0003 0x04b8 0x084c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PX-402A | Epson Stylus NX110 Series | Epson Stylus SX110 Series | Epson Stylus TX110 Series libusbscanner 0x0003 0x04b8 0x084d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ME OFFICE 510 | Epson Stylus NX210 Series | Epson Stylus SX210 Series | Epson Stylus TX210 Series libusbscanner 0x0003 0x04b8 0x084f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Stylus NX410 Series | Epson Stylus SX410 Series | Epson Stylus TX410 Series libusbscanner 0x0003 0x04b8 0x0851 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson ME OFFICE 650FN Series | Epson Stylus Office BX310FN Series | Epson Stylus Office TX510FN Series | Epson WorkForce 310 Series libusbscanner 0x0003 0x04b8 0x0854 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson PX-502A | Epson Stylus NX510 Series | Epson Stylus SX510W Series | Epson Stylus TX550W Series libusbscanner 0x0003 0x04b8 0x0856 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Epson Stylus SX125 libusbscanner 0x0003 0x04b8 0x085c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-4010CU libusbscanner 0x0003 0x04c5 0x1029 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-4120C libusbscanner 0x0003 0x04c5 0x1041 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-4220C libusbscanner 0x0003 0x04c5 0x1042 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-4530C libusbscanner 0x0003 0x04c5 0x1078 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5750C libusbscanner 0x0003 0x04c5 0x1095 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5110EOX/2 libusbscanner 0x0003 0x04c5 0x1096 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5110C libusbscanner 0x0003 0x04c5 0x1097 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5650C libusbscanner 0x0003 0x04c5 0x10ad 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-4120C2 libusbscanner 0x0003 0x04c5 0x10ae 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-4220C2 libusbscanner 0x0003 0x04c5 0x10af 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-60F libusbscanner 0x0003 0x04c5 0x10c7 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-4340C libusbscanner 0x0003 0x04c5 0x10cf 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5120C libusbscanner 0x0003 0x04c5 0x10e0 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5220C libusbscanner 0x0003 0x04c5 0x10e1 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5530C libusbscanner 0x0003 0x04c5 0x10e2 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5110EOX3 libusbscanner 0x0003 0x04c5 0x10e6 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5900C libusbscanner 0x0003 0x04c5 0x10e7 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5015C libusbscanner 0x0003 0x04c5 0x10ef 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5110EOXM libusbscanner 0x0003 0x04c5 0x10f2 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap S500 libusbscanner 0x0003 0x04c5 0x10fe 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap S500M libusbscanner 0x0003 0x04c5 0x1135 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5530C2 libusbscanner 0x0003 0x04c5 0x114a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6140 libusbscanner 0x0003 0x04c5 0x114d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6240 libusbscanner 0x0003 0x04c5 0x114e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6130 libusbscanner 0x0003 0x04c5 0x114f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6230 libusbscanner 0x0003 0x04c5 0x1150 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap S510 libusbscanner 0x0003 0x04c5 0x1155 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap S300 libusbscanner 0x0003 0x04c5 0x1156 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap S510M libusbscanner 0x0003 0x04c5 0x116f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6770 libusbscanner 0x0003 0x04c5 0x1174 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6770A libusbscanner 0x0003 0x04c5 0x1175 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6670 libusbscanner 0x0003 0x04c5 0x1176 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6670A libusbscanner 0x0003 0x04c5 0x1177 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6750S libusbscanner 0x0003 0x04c5 0x1178 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap S300M libusbscanner 0x0003 0x04c5 0x117f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6800 libusbscanner 0x0003 0x04c5 0x119d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6800-CGA libusbscanner 0x0003 0x04c5 0x119e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap S1500 | Fujitsu ScanSnap S1500M libusbscanner 0x0003 0x04c5 0x11a2 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap S1300 libusbscanner 0x0003 0x04c5 0x11ed 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6140Z libusbscanner 0x0003 0x04c5 0x11f1 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6240Z libusbscanner 0x0003 0x04c5 0x11f2 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6130Z libusbscanner 0x0003 0x04c5 0x11f3 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6230Z libusbscanner 0x0003 0x04c5 0x11f4 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-6110 libusbscanner 0x0003 0x04c5 0x11fc 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu fi-5950 libusbscanner 0x0003 0x04c5 0x1213 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Fujitsu ScanSnap iX500 libusbscanner 0x0003 0x04c5 0x132b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Konica e-mini libusbscanner 0x0003 0x04c8 0x0722 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S2026C libusbscanner 0x0003 0x04da 0x1000 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S2046C libusbscanner 0x0003 0x04da 0x1001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S1025C libusbscanner 0x0003 0x04da 0x1006 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S1020C libusbscanner 0x0003 0x04da 0x1007 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S2048C libusbscanner 0x0003 0x04da 0x1009 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S2028C libusbscanner 0x0003 0x04da 0x100a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S4085C libusbscanner 0x0003 0x04da 0x100c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S4065C libusbscanner 0x0003 0x04da 0x100d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S7075C libusbscanner 0x0003 0x04da 0x100e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-SS080 libusbscanner 0x0003 0x04da 0x100f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Panasonic KV-S1045C libusbscanner 0x0003 0x04da 0x1010 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4x16 libusbscanner 0x0003 0x04e8 0x3409 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-6x20 libusbscanner 0x0003 0x04e8 0x340d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung MFP-560 libusbscanner 0x0003 0x04e8 0x340e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung MFP-750 libusbscanner 0x0003 0x04e8 0x340f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4x20 libusbscanner 0x0003 0x04e8 0x3412 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4100 libusbscanner 0x0003 0x04e8 0x3413 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4x21 libusbscanner 0x0003 0x04e8 0x3419 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-5x30 libusbscanner 0x0003 0x04e8 0x341a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4200 libusbscanner 0x0003 0x04e8 0x341b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-3160 libusbscanner 0x0003 0x04e8 0x341c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-6x22 libusbscanner 0x0003 0x04e8 0x341d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX4725 | Samsung SCX4725-FN libusbscanner 0x0003 0x04e8 0x341f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-6x45 libusbscanner 0x0003 0x04e8 0x3420 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-8380 libusbscanner 0x0003 0x04e8 0x3421 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-2160 libusbscanner 0x0003 0x04e8 0x3425 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4500 libusbscanner 0x0003 0x04e8 0x3426 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-6200 libusbscanner 0x0003 0x04e8 0x3427 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-6240 libusbscanner 0x0003 0x04e8 0x3428 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-6x55 libusbscanner 0x0003 0x04e8 0x3429 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-3170fn (CLX-3170 Series) | Samsung CLX-3175FW libusbscanner 0x0003 0x04e8 0x342a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4500W libusbscanner 0x0003 0x04e8 0x342b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4824 (SCX-4x24 Series) libusbscanner 0x0003 0x04e8 0x342c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4828FN (SCX-4x28 Series) libusbscanner 0x0003 0x04e8 0x342d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4300 libusbscanner 0x0003 0x04e8 0x342e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-5835_5935 libusbscanner 0x0003 0x04e8 0x342f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-5635 libusbscanner 0x0003 0x04e8 0x3430 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4x26 libusbscanner 0x0003 0x04e8 0x3432 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4600 libusbscanner 0x0003 0x04e8 0x3433 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4623 libusbscanner 0x0003 0x04e8 0x3434 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung MFP-65x libusbscanner 0x0003 0x04e8 0x3435 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-6545 libusbscanner 0x0003 0x04e8 0x3437 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-8385 libusbscanner 0x0003 0x04e8 0x3439 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-6220 libusbscanner 0x0003 0x04e8 0x343a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-6250 libusbscanner 0x0003 0x04e8 0x343b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4825FN (SCX-4x25 Series) libusbscanner 0x0003 0x04e8 0x343c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-3185 libusbscanner 0x0003 0x04e8 0x343d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-8540 libusbscanner 0x0003 0x04e8 0x343f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4623FW libusbscanner 0x0003 0x04e8 0x3440 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-3205W (SCX-3200 Series) libusbscanner 0x0003 0x04e8 0x3441 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-6545X libusbscanner 0x0003 0x04e8 0x3442 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-6x55X libusbscanner 0x0003 0x04e8 0x3443 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-8385X libusbscanner 0x0003 0x04e8 0x3444 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-5835_5935X libusbscanner 0x0003 0x04e8 0x3446 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4833FD | Samsung SCX-4835FD libusbscanner 0x0003 0x04e8 0x344b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-3400 libusbscanner 0x0003 0x04e8 0x344f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SF-760 libusbscanner 0x0003 0x04e8 0x3450 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4729FD libusbscanner 0x0003 0x04e8 0x3453 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-6260 libusbscanner 0x0003 0x04e8 0x3455 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-3300 Series libusbscanner 0x0003 0x04e8 0x3456 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-470x libusbscanner 0x0003 0x04e8 0x3457 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung CLX-4190 libusbscanner 0x0003 0x04e8 0x345a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-4650 4x21S Series libusbscanner 0x0003 0x04e8 0x345b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung M337x 387x 407x Series libusbscanner 0x0003 0x04e8 0x3460 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung M267x 287x Series libusbscanner 0x0003 0x04e8 0x3461 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung SCX-681x libusbscanner 0x0003 0x04e8 0x3466 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Samsung C460 libusbscanner 0x0003 0x04e8 0x3468 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Pentax DSmobile 600 libusbscanner 0x0003 0x04f9 0x2038 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Aiptek Aiptek Pencam libusbscanner 0x0003 0x0553 0x0202 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek ScanExpress 1200 CU libusbscanner 0x0003 0x055f 0x0001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek ScanExpress 600 CU libusbscanner 0x0003 0x055f 0x0002 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek ScanExpress 1200 UB | Trust Compact Scan USB 19200 libusbscanner 0x0003 0x055f 0x0006 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek ScanExpress 1200 CU Plus libusbscanner 0x0003 0x055f 0x0008 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 1200 F libusbscanner 0x0003 0x055f 0x0010 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek ScanExpress A3 USB libusbscanner 0x0003 0x055f 0x0210 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 2400 CS | Mustek BearPaw 2400 TA | Trust 240TH Easy Webscan Gold libusbscanner 0x0003 0x055f 0x0218 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 2400 CS Plus | Mustek BearPaw 2400 TA Plus | Mustek Plug-n-Scan 2400 MT | Mustek Plug-n-Scan 2400 M | Packard Bell Diamond 2450 libusbscanner 0x0003 0x055f 0x0219 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 2448 CS Plus | Mustek BearPaw 2448 TA Plus libusbscanner 0x0003 0x055f 0x021a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 1200 CU Plus | Packard Bell Diamond 1200 Plus libusbscanner 0x0003 0x055f 0x021b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 1200 CU Plus | Mustek BearPaw 1248 CU | Packard Bell Diamond 1200 Plus | Trust Direct WebScan 19200 libusbscanner 0x0003 0x055f 0x021c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 2400 CU Plus libusbscanner 0x0003 0x055f 0x021d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 1200 CS | Mustek BearPaw 1200 TA libusbscanner 0x0003 0x055f 0x021e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek ScanExpress 1248 UB libusbscanner 0x0003 0x055f 0x021f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Mustek BearPaw 2448TA Pro libusbscanner 0x0003 0x055f 0x0409 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Artec/Ultima Ultima 2000 | Artec/Ultima Ultima 2000 e+ | Boeder Sm@rtScan Slim Edition | Fujitsu 1200CUS | Googlegear 2000 | Medion/Lifetec/Tevion/Cytron MD 4394 | Medion/Lifetec/Tevion/Cytron MD/LT 9375 | Medion/Lifetec/Tevion/Cytron MD/LT 9385 | Medion/Lifetec/Tevion/Cytron LT 9452 | Medion/Lifetec/Tevion/Cytron MD 9458 | Mustek BearPaw 1200 CU | Mustek BearPaw 2400 CU | Mustek ScanExpress 1200 UB Plus | Mustek ScanExpress 2400 USB | Mustek ScanMagic 1200 UB Plus | Packard Bell Diamond 1200 | Trust Compact Scan USB 19200 | Trust Flat Scan USB 19200 libusbscanner 0x0003 0x05d8 0x4002 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Artec/Ultima E+ 48U | Medion/Lifetec/Tevion/Cytron MD9693 | Medion/Lifetec/Tevion/Cytron MD9705 | Medion/Lifetec/Tevion/Cytron MD4394 | Microstar MR 9791 libusbscanner 0x0003 0x05d8 0x4003 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Artec/Ultima E+ Pro libusbscanner 0x0003 0x05d8 0x4004 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Memorex MEM 48U libusbscanner 0x0003 0x05d8 0x4005 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Trust Easy Webscan 19200 libusbscanner 0x0003 0x05d8 0x4006 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Trust 240H Easy Webscan Gold libusbscanner 0x0003 0x05d8 0x4007 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # UMAX AstraSlim SE libusbscanner 0x0003 0x05d8 0x4009 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # UMAX AstraSlim 1200 SE libusbscanner 0x0003 0x05d8 0x4010 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Yakumo Scan50 libusbscanner 0x0003 0x05d8 0x4011 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker X6USB libusbscanner 0x0003 0x05da 0x0099 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek SlimScan C6 libusbscanner 0x0003 0x05da 0x009a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker V6USL libusbscanner 0x0003 0x05da 0x00a3 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker V6UPL libusbscanner 0x0003 0x05da 0x00b6 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker 4800 libusbscanner 0x0003 0x05da 0x30cf 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker 3840 libusbscanner 0x0003 0x05da 0x30d4 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker 3600 libusbscanner 0x0003 0x05da 0x40b3 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker 3700 libusbscanner 0x0003 0x05da 0x40b8 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker 3600 libusbscanner 0x0003 0x05da 0x40ca 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker 3700 libusbscanner 0x0003 0x05da 0x40cb 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker 3750 libusbscanner 0x0003 0x05da 0x40dd 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker 3600 libusbscanner 0x0003 0x05da 0x40ff 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Microtek ScanMaker V6USL libusbscanner 0x0003 0x05da 0x80a3 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # iVina 1200U libusbscanner 0x0003 0x0638 0x0268 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Minolta Dimage Scan Dual II libusbscanner 0x0003 0x0638 0x026a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV600U libusbscanner 0x0003 0x0638 0x0a13 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Minolta-QMS SC-110 libusbscanner 0x0003 0x0638 0x0a15 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision DS610CU Scancopier | Minolta-QMS SC-215 | OKI S700 Scancopier libusbscanner 0x0003 0x0638 0x0a16 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV610 | Avision AV600U Plus libusbscanner 0x0003 0x0638 0x0a18 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV220 libusbscanner 0x0003 0x0638 0x0a23 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV210 libusbscanner 0x0003 0x0638 0x0a24 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV210 libusbscanner 0x0003 0x0638 0x0a25 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV120 libusbscanner 0x0003 0x0638 0x0a27 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV220C2 libusbscanner 0x0003 0x0638 0x0a2a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV220D2 libusbscanner 0x0003 0x0638 0x0a2b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV220+ libusbscanner 0x0003 0x0638 0x0a2c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV220C2-G libusbscanner 0x0003 0x0638 0x0a2d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV220C2-B libusbscanner 0x0003 0x0638 0x0a2e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV210C2-G libusbscanner 0x0003 0x0638 0x0a2f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV122 libusbscanner 0x0003 0x0638 0x0a33 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV210C2 libusbscanner 0x0003 0x0638 0x0a3a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV121 libusbscanner 0x0003 0x0638 0x0a3c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV8300 libusbscanner 0x0003 0x0638 0x0a40 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AM3000 Series libusbscanner 0x0003 0x0638 0x0a41 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision @V5100 libusbscanner 0x0003 0x0638 0x0a45 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV8050U libusbscanner 0x0003 0x0638 0x0a4d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV3200SU libusbscanner 0x0003 0x0638 0x0a4e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV3730SU libusbscanner 0x0003 0x0638 0x0a4f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV610C2 libusbscanner 0x0003 0x0638 0x0a5e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision IT8300 libusbscanner 0x0003 0x0638 0x0a61 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV3750SU libusbscanner 0x0003 0x0638 0x0a65 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV3850SU libusbscanner 0x0003 0x0638 0x0a66 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV8350 libusbscanner 0x0003 0x0638 0x0a68 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision FB6080E libusbscanner 0x0003 0x0638 0x0a82 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision FB2080E libusbscanner 0x0003 0x0638 0x0a84 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV122 C2 libusbscanner 0x0003 0x0638 0x0a93 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV220-G libusbscanner 0x0003 0x0638 0x0a94 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision @V2500 libusbscanner 0x0003 0x0638 0x0aa1 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Avision AV210D2+ libusbscanner 0x0003 0x0638 0x1a35 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Minolta Elite II libusbscanner 0x0003 0x0686 0x4004 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Minolta Dimage Scan Dual III libusbscanner 0x0003 0x0686 0x400d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Minolta Dimage Scan Elite 5400 libusbscanner 0x0003 0x0686 0x400e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan 1212U libusbscanner 0x0003 0x06bd 0x0001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan 1236u libusbscanner 0x0003 0x06bd 0x0002 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Agfa Snapscan Touch libusbscanner 0x0003 0x06bd 0x0100 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan 1212U_2 libusbscanner 0x0003 0x06bd 0x2061 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan e40 libusbscanner 0x0003 0x06bd 0x208d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan e50 libusbscanner 0x0003 0x06bd 0x208f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan e20 libusbscanner 0x0003 0x06bd 0x2091 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan e10 libusbscanner 0x0003 0x06bd 0x2093 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan e25 libusbscanner 0x0003 0x06bd 0x2095 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan e26 libusbscanner 0x0003 0x06bd 0x2097 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan e52 libusbscanner 0x0003 0x06bd 0x20fd 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # AGFA SnapScan e42 libusbscanner 0x0003 0x06bd 0x20ff 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # UMAX Astra 4900 libusbscanner 0x0003 0x06dc 0x0020 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro U12 | Plustek OpticPro UT12 | Plustek OpticPro 1212U | RevScan RevScan Orange R48Ti | Genius ColorPage Vivid III USB libusbscanner 0x0003 0x07b3 0x0001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro U12 libusbscanner 0x0003 0x07b3 0x0010 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro U24 libusbscanner 0x0003 0x07b3 0x0011 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro UT12 libusbscanner 0x0003 0x07b3 0x0013 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro U24 libusbscanner 0x0003 0x07b3 0x0015 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro UT12 | Plustek OpticPro UT16 | Plustek OpticPro UT24 libusbscanner 0x0003 0x07b3 0x0017 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro 1248U | RevScan 19200i libusbscanner 0x0003 0x07b3 0x0400 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro 1248U libusbscanner 0x0003 0x07b3 0x0401 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro U16B libusbscanner 0x0003 0x07b3 0x0402 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro U16B+ | Plustek OpticPro UT16B libusbscanner 0x0003 0x07b3 0x0403 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Nortek MyScan 1200 | Plustek OpticPro S12 | Plustek OpticPro ST12 libusbscanner 0x0003 0x07b3 0x040b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticPro S24 libusbscanner 0x0003 0x07b3 0x040e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # NeatReceipts Scanalizer Professional 2.5 | Plustek OpticSlim M12 libusbscanner 0x0003 0x07b3 0x0412 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticSlim 1200 libusbscanner 0x0003 0x07b3 0x0413 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticSlim 2400 libusbscanner 0x0003 0x07b3 0x0422 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticSlim 2400 plus libusbscanner 0x0003 0x07b3 0x0454 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek Iriscan Express 2 libusbscanner 0x0003 0x07b3 0x045f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # NeatReceipts Mobile Scanner libusbscanner 0x0003 0x07b3 0x0462 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Plustek OpticBook 3600 libusbscanner 0x0003 0x07b3 0x0900 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Corex 600c libusbscanner 0x0003 0x08f0 0x0002 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Corex 800c libusbscanner 0x0003 0x08f0 0x0005 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox Phaser 6110MFP libusbscanner 0x0003 0x0924 0x3d5d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox Phaser 3200MFP libusbscanner 0x0003 0x0924 0x3da4 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox WorkCentre 4118 Series libusbscanner 0x0003 0x0924 0x420c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox WorkCentre 3119 Series libusbscanner 0x0003 0x0924 0x4265 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox WorkCentre 3210 libusbscanner 0x0003 0x0924 0x4293 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Xerox WorkCentre 3220 libusbscanner 0x0003 0x0924 0x4294 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Pentax DSmobile 600 libusbscanner 0x0003 0x0a17 0x3210 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Portable Peripheral Co., Ltd. Q-Scan USB001 (A4 portable scanner) libusbscanner 0x0003 0x0a53 0x1000 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Portable Peripheral Co., Ltd. Q-Scan USB201 (A6 portable scanner) libusbscanner 0x0003 0x0a53 0x2000 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Syscan TravelScan 460/464 | Ambir Visigo A4 libusbscanner 0x0003 0x0a82 0x4600 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Syscan DocketPort 465 libusbscanner 0x0003 0x0a82 0x4802 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Syscan DocketPort 665 libusbscanner 0x0003 0x0a82 0x4803 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Syscan DocketPort 685/ Ambir DS685 libusbscanner 0x0003 0x0a82 0x480c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Syscan DocketPort 485 libusbscanner 0x0003 0x0a82 0x4810 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Syscan TravelScan 662 libusbscanner 0x0003 0x0a82 0x6620 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CR-55 libusbscanner 0x0003 0x1083 0x160c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-1210C libusbscanner 0x0003 0x1083 0x160f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-4010C libusbscanner 0x0003 0x1083 0x1614 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-2510C libusbscanner 0x0003 0x1083 0x1617 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-X10C libusbscanner 0x0003 0x1083 0x1618 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CR-25 libusbscanner 0x0003 0x1083 0x161a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-2010C libusbscanner 0x0003 0x1083 0x161b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-3010C libusbscanner 0x0003 0x1083 0x161d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-7090C libusbscanner 0x0003 0x1083 0x1620 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-9050C libusbscanner 0x0003 0x1083 0x1622 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-7550C libusbscanner 0x0003 0x1083 0x1623 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-6050C libusbscanner 0x0003 0x1083 0x1624 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-6010C libusbscanner 0x0003 0x1083 0x1626 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CR-190i libusbscanner 0x0003 0x1083 0x162b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon DR-6030C libusbscanner 0x0003 0x1083 0x1638 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Canon CR-135i libusbscanner 0x0003 0x1083 0x1639 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Digital Dream l' espion XS libusbscanner 0x0003 0x1183 0x0001 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # KONICA MINOLTA magicolor 1690MF libusbscanner 0x0003 0x132b 0x2089 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # UMAX Astra 1220U libusbscanner 0x0003 0x1606 0x0010 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # UMAX Astra 1600U | UMAX Astra 2000U libusbscanner 0x0003 0x1606 0x0030 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Umax UMAX 3400 libusbscanner 0x0003 0x1606 0x0050 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Umax UMAX 3400 | Umax UMAX Astranet ia101 | Umax UMAX 3450 libusbscanner 0x0003 0x1606 0x0060 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # UMAX Astra 4400 | UMAX Astra 4450 libusbscanner 0x0003 0x1606 0x0070 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # UMAX Astra 2100U libusbscanner 0x0003 0x1606 0x0130 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Umax UMAX 5400 libusbscanner 0x0003 0x1606 0x0160 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # UMAX Astra 2200 (SU) libusbscanner 0x0003 0x1606 0x0230 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # DCT DocketPort 487 libusbscanner 0x0003 0x1dcc 0x4810 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Dell A920 libusbscanner 0x0003 0x413c 0x5105 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Dell Dell MFP Laser Printer 1815dn libusbscanner 0x0003 0x413c 0x5124 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 # Dell 1600n libusbscanner 0x0003 0x413c 0x5250 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 sane-backends-1.0.27/testsuite/tools/data/html-mfgs.ref0000664000175000017500000314436212775312262017744 00000000000000 SANE: Supported Devices
SANE

SANE: Supported Devices


The following table summarizes the devices supported by the latest version of sane-backends.

This is only a summary! Please consult the manpages and the author-supplied webpages for more detailed (and usually important) information concerning each backend.

If you have new information or corrections, please file a bug report with as many details as possible. Also please tell us if your scanner isn't mentioned in this list at all.

For an explanation of the tables, see the legend.

Summary

Device type Number of devices
Total Supported Untested Unsupported
Sum Complete Good Basic Minimal
Scanners 2012 1205 417 662 101 25 325 482
Still cameras 5 5 1 2 2 0 0 0
Video Cameras 8 3 0 1 0 2 3 2
Meta backends 2 n/a
APIs 5 n/a

Scanners

Manufacturers: Abaton, Acer Peripherals, Across Technologies, Actown, Adlib, Advent, AGFA, Ambir, Apple, Aries, Artec/Ultima, Avigramm, Avision, Bell and Howell, Bell+Howell, BenQ, Benq (Acer), BlackWidow, Boeder, BrightScan, Brother, C-Channel, Canon, Chinon, Compaq, Compeye, Corex, Cybercom, DCT, Dell, Devcom, Dextra, Dexxa, E-Lux, EDGE, EDT (Electronic Document Technology), Enhans, Epson, Escom, Escort, Fujitsu, Gallery, Genius, Googlegear, Guillemot, Guillemot / Hercules, Hercules, Hewlett-Packard, IBM, IOMagic, Iris, iVina, Kodak, Komodo, KONICA MINOLTA, Kyocera, LEO, Lexmark, Linotype Hell, Logitech, Medion/Lifetec/Tevion/Cytron, Memorex, Micromaxx, Microstar, Microtek, Minolta, Minolta-QMS, Mitsubishi, Mustek, NeatReceipts, NEC, Network, Nikon, Nortek, OKI, Olivetti, Olympus, Optoelectronics, Optrox, Packard Bell, Panasonic, Pentax, PIE, PIOTECH, PLANon, Plustek, Portable Peripheral Co., Ltd., Primax, Prolink, Quato, Reflecta, Relisys, RevScan, Ricoh, Samsung, Scanport, Scanshell, Sceptre, Sharp, Sicos, Siemens, SmartDisk, Spot Technology, Syscan, Tamarack, Targa, TCE, Teco, Tiny, TriGem, Trust, UMAX, Vantas, Visioneer, Viviscan, Vobis, Vuego, Xerox, Yakumo

Manufacturer: Abaton

Model Interface USB id Status Comment Backend Manpage
Scan 300/GS SCSI   Complete All known modes and functions supported abaton
(unmaintained)
sane-abaton
Scan 300/S SCSI   Untested Untested, use with caution abaton
(unmaintained)
sane-abaton

Manufacturer: Acer Peripherals

Comment: Company was renamed to Benq.

Manufacturer: Across Technologies

Model Interface USB id Status Comment Backend Manpage
FS-1130 SCSI   Good FCC ID LUZFS1130 leo
(1.0-10)
sane-leo

Manufacturer: Actown

Model Interface USB id Status Comment Backend Manpage
ACT Scan I 30 SCSI   Untested sub model VM3520A teco1
(1.0-10)
sane-teco1

Manufacturer: Adlib

Model Interface USB id Status Comment Backend Manpage
JetScan630 SCSI   Good   pie
(1.0)
sane-pie
JetScan636PRO SCSI   Untested   pie
(1.0)
sane-pie

Manufacturer: Advent

Link(s): http://www.adventcomputers.co.uk

Model Interface USB id Status Comment Backend Manpage
AW10 USB 0x040a/0x4060 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio

Manufacturer: AGFA

Link(s): http://www.agfa.com/, http://www.agfa.com

Model Interface USB id Status Comment Backend Manpage
Arcus 1200 SCSI   Good Optional transparency unit supported. SnapScan
(1.4)
sane-snapscan
Arcus II SCSI   Good Arcus *II*, not Arcus! microtek
(0.13.1)
sane-microtek
DuoScan SCSI   Basic   microtek
(0.13.1)
sane-microtek
DuoScan f40 USB IEEE-1394 0x06bd/0x02bf Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
DuoScan T2000XL SCSI   Unsupported Unsupported. Same as Microtek ArtixScan 2020? unsupported
(2010-06-09)
?
DuoScan T2500 SCSI IEEE-1384   Unsupported Unsupported. Same as Microtek Artixscan 2500f unsupported
(2010-06-09)
?
Focus Color SCSI   Good 3-pass agfafocus
(unmaintained)
sane-agfafocus
Focus Color Plus SCSI   Good 3-pass agfafocus
(unmaintained)
sane-agfafocus
Focus GS Scanner SCSI   Untested 6 bit gray agfafocus
(unmaintained)
sane-agfafocus
Focus II SCSI   Untested gray only agfafocus
(unmaintained)
sane-agfafocus
Focus Lineart Scanner SCSI   Untested Lineart only? Untested. agfafocus
(unmaintained)
sane-agfafocus
SnapScan SCSI   Good   SnapScan
(1.4)
sane-snapscan
SnapScan 300 SCSI   Good   SnapScan
(1.4)
sane-snapscan
SnapScan 310 SCSI   Good   SnapScan
(1.4)
sane-snapscan
SnapScan 310P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
SnapScan 600 SCSI   Good Optional ADF supported. SnapScan
(1.4)
sane-snapscan
SnapScan 1200P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
SnapScan 1212P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
SnapScan 1212U USB 0x06bd/0x0001 Good   SnapScan
(1.4)
sane-snapscan
SnapScan 1212U_2 USB 0x06bd/0x2061 Good   SnapScan
(1.4)
sane-snapscan
SnapScan 1236s SCSI   Good Optional ADF and transparency unit supported. SnapScan
(1.4)
sane-snapscan
SnapScan 1236u USB 0x06bd/0x0002 Good Optional ADF and transparency unit supported. SnapScan
(1.4)
sane-snapscan
SnapScan e10 USB 0x06bd/0x2093 Good   SnapScan
(1.4)
sane-snapscan
SnapScan e20 USB 0x06bd/0x2091 Good   SnapScan
(1.4)
sane-snapscan
SnapScan e25 USB 0x06bd/0x2095 Good   SnapScan
(1.4)
sane-snapscan
SnapScan e26 USB 0x06bd/0x2097 Good   SnapScan
(1.4)
sane-snapscan
SnapScan e40 USB 0x06bd/0x208d Good   SnapScan
(1.4)
sane-snapscan
SnapScan e42 USB 0x06bd/0x20ff Good   SnapScan
(1.4)
sane-snapscan
SnapScan e50 USB 0x06bd/0x208f Good Optional tranparency unit supported SnapScan
(1.4)
sane-snapscan
SnapScan e52 USB 0x06bd/0x20fd Good Optional tranparency unit supported SnapScan
(1.4)
sane-snapscan
SnapScan e60 USB   Untested   SnapScan
(1.4)
sane-snapscan
SnapScan EZ Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
Snapscan Touch USB 0x06bd/0x0100 Complete   niash
(0.3)
sane-niash
StudioScan SCSI   Good   microtek
(0.13.1)
sane-microtek
StudioScan II SCSI   Good   microtek
(0.13.1)
sane-microtek
StudioScan IIsi SCSI   Good   microtek
(0.13.1)
sane-microtek
Studiostar SCSI   Minimal Is detected but scans are very dark microtek
(0.13.1)
sane-microtek

Manufacturer: Ambir

Model Interface USB id Status Comment Backend Manpage
Visigo A4 USB 0x0a82/0x4600 Complete Rebaged Travelscan 464 plustek
(0.52)
sane-plustek

Manufacturer: Apple

Link(s): http://developer.apple.com/, http://www.apple.com/

Model Interface USB id Status Comment Backend Manpage
Apple Scanner SCSI   Good 4bit, 16 shades of gray apple
(unmaintained)
sane-apple
Color OneScanner SCSI   Minimal truecolor (needs much work) but it scans in non color modes. apple
(unmaintained)
sane-apple
Color OneScanner 600/27 SCSI   Good Rebadged CanoScan 300 canon
(1.12)
sane-canon
OneScanner SCSI   Basic 8bit, 256 shades of gray. The backend needs work especially in the quantization code but it may work. apple
(unmaintained)
sane-apple

Manufacturer: Aries

Model Interface USB id Status Comment Backend Manpage
Scan-It Pro 4800 Parport (SPP, EPP)   Complete use driver-switch mov=2 plustek_pp
(0.43)
sane-plustek_pp

Manufacturer: Artec/Ultima

Link(s): http://www.artecusa.com/

Model Interface USB id Status Comment Backend Manpage
1236 USB USB 0x05d8/0x4001 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
A6000C SCSI   Complete all modes working artec
(unmaintained)
sane-artec
A6000C PLUS SCSI   Complete f/w <= v1.92 basic, f/w >= v1.93 OK artec
(unmaintained)
sane-artec
AM12e+ Parport   Unsupported Unsupported. Chips found inside: AT015, AD9816JS. Maybe similar to SCSI version or as6e? unsupported
(2010-06-09)
?
AM12S SCSI   Complete all modes working artec
(unmaintained)
sane-artec
AS6E Parport   Basic Requires the program 'as6edriver' to run. as6e
(0.5)
sane-as6e
AT3 SCSI   Complete all modes working artec
(unmaintained)
sane-artec
AT6 SCSI   Good Scan head needs to return home before another scan can be started. artec
(unmaintained)
sane-artec
AT12 SCSI   Complete all modes working artec
(unmaintained)
sane-artec
E+ 48U USB 0x05d8/0x4003 Good CIS scanner based on the GT6816 chip. Apparently all other devices are re-badged Artec scanners. artec_eplus48u
(unmaintained)
sane-artec_eplus48u
E+ Pro USB 0x05d8/0x4004 Minimal Works up to 600dpi, but not 1200. Needs better calibration. See bug #310490 artec_eplus48u
(unmaintained)
sane-artec_eplus48u
Ultima 2000 USB 0x05d8/0x4002 Good Works, only product id 0x4002 is supported gt68xx
(1.0-84)
sane-gt68xx
Ultima 2000 (0x4001) USB 0x05d8/0x4001 Unsupported Same name, but different ids: This scanner is not supported. The scanner with product id 0x4002 is supported by the gt68xx backend, however. unsupported
(2010-06-09)
?
Ultima 2000 e+ USB 0x05d8/0x4002 Good Works, however 12 bit mode doesn't seem to be supported gt68xx
(1.0-84)
sane-gt68xx

Manufacturer: Avigramm

Model Interface USB id Status Comment Backend Manpage
Minidoc USB Parport 0x05cb/0x1483 Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Avision

Link(s): http://www.avision.com, http://www.avision.com/

Model Interface USB id Status Comment Backend Manpage
@V2500 USB 0x0638/0x0aa1 Untested   avision
(Build: 296)
sane-avision
@V5100 USB 0x0638/0x0a45 Good 1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors avision
(Build: 296)
sane-avision
AM3000 Series USB 0x0638/0x0a41 Basic MFD avision
(Build: 296)
sane-avision
AV100CS SCSI   Untested   avision
(Build: 296)
sane-avision
AV100IIICS SCSI   Untested   avision
(Build: 296)
sane-avision
AV100S SCSI   Untested   avision
(Build: 296)
sane-avision
AV120 USB 0x0638/0x0a27 Complete sheetfed scanner avision
(Build: 296)
sane-avision
AV121 USB 0x0638/0x0a3c Good sheetfed scanner avision
(Build: 296)
sane-avision
AV122 USB 0x0638/0x0a33 Good sheetfed duplex scanner avision
(Build: 296)
sane-avision
AV122 C2 USB 0x0638/0x0a93 Good sheetfed duplex scanner avision
(Build: 296)
sane-avision
AV210 USB 0x0638/0x0a25 Complete sheetfed scanner avision
(Build: 296)
sane-avision
AV210 USB 0x0638/0x0a24 Complete sheetfed scanner avision
(Build: 296)
sane-avision
AV210C2 USB 0x0638/0x0a3a Complete sheetfed scanner avision
(Build: 296)
sane-avision
AV210C2-G USB 0x0638/0x0a2f Complete sheetfed scanner avision
(Build: 296)
sane-avision
AV210D2+ USB 0x0638/0x1a35 Complete sheetfed scanner avision
(Build: 296)
sane-avision
AV220 USB 0x0638/0x0a23 Complete duplex! sheetfed scanner avision
(Build: 296)
sane-avision
AV220+ USB 0x0638/0x0a2c Complete duplex! sheetfed scanner avision
(Build: 296)
sane-avision
AV220-G USB 0x0638/0x0a94 Complete duplex! sheetfed scanner avision
(Build: 296)
sane-avision
AV220C2 USB 0x0638/0x0a2a Complete duplex! sheetfed scanner avision
(Build: 296)
sane-avision
AV220C2-B USB 0x0638/0x0a2e Complete duplex! sheetfed scanner avision
(Build: 296)
sane-avision
AV220C2-G USB 0x0638/0x0a2d Complete duplex! sheetfed scanner avision
(Build: 296)
sane-avision
AV220D2 USB 0x0638/0x0a2b Complete duplex! sheetfed scanner avision
(Build: 296)
sane-avision
AV240SC SCSI   Untested   avision
(Build: 296)
sane-avision
AV260CS SCSI   Untested   avision
(Build: 296)
sane-avision
AV360CS SCSI   Untested   avision
(Build: 296)
sane-avision
AV363CS SCSI   Untested   avision
(Build: 296)
sane-avision
AV420CS SCSI   Untested   avision
(Build: 296)
sane-avision
AV600U USB 0x0638/0x0a13 Good 1 pass, 600 dpi avision
(Build: 296)
sane-avision
AV600U Plus USB 0x0638/0x0a18 Good   avision
(Build: 296)
sane-avision
AV610 USB 0x0638/0x0a18 Good   avision
(Build: 296)
sane-avision
AV610C2 USB 0x0638/0x0a5e Good   avision
(Build: 296)
sane-avision
AV620CS SCSI   Complete 1 pass, 600 dpi avision
(Build: 296)
sane-avision
AV620CS Plus SCSI   Complete 1 pass, 1200 dpi avision
(Build: 296)
sane-avision
AV630CS SCSI   Complete 1 pass, 1200 dpi avision
(Build: 296)
sane-avision
AV630CSL SCSI   Untested 1 pass, 1200 dpi avision
(Build: 296)
sane-avision
AV660S SCSI   Untested 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV680S SCSI   Untested 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV690U SCSI   Untested 1 pass, 2400 dpi avision
(Build: 296)
sane-avision
AV800S SCSI   Untested 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV810C SCSI   Untested 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV820 SCSI   Untested 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV820C SCSI   Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV820C Plus SCSI   Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV830C SCSI   Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV830C Plus SCSI   Untested 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV880 SCSI   Untested 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV880C SCSI   Untested 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV3200C SCSI   Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV3200SU USB 0x0638/0x0a4e Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV3730SU USB 0x0638/0x0a4f Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV3750SU USB 0x0638/0x0a65 Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV3800C SCSI   Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV3850SU USB 0x0638/0x0a66 Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV6120 SCSI   Untested   avision
(Build: 296)
sane-avision
AV6240 SCSI   Complete 1 pass, ??? dpi avision
(Build: 296)
sane-avision
AV8000S SCSI   Complete 1 pass, 1200 dpi, A3 avision
(Build: 296)
sane-avision
AV8050U USB 0x0638/0x0a4d Complete 1 pass, 1200 dpi, A3 - duplex! avision
(Build: 296)
sane-avision
AV8300 USB 0x0638/0x0a40 Complete 1 pass, 1200 dpi, A3 - duplex! avision
(Build: 296)
sane-avision
AV8350 USB 0x0638/0x0a68 Complete 1 pass, 1200 dpi, A3 - duplex! avision
(Build: 296)
sane-avision
AVA3 SCSI   Basic 1 pass, 600 dpi, A3 avision
(Build: 296)
sane-avision
DS310F Parport   Unsupported Probably not supported. Scanner/printer/copier combination. unsupported
(2010-06-09)
?
DS610CU Scancopier USB 0x0638/0x0a16 Good 1 pass, 600 dpi, A4 avision
(Build: 296)
sane-avision
FB2080E USB 0x0638/0x0a84 Basic 1 pass, 600 dpi, zero-edge avision
(Build: 296)
sane-avision
FB6000E SCSI   Complete 1 pass, 1200 dpi, A3 - duplex! - zero edge! avision
(Build: 296)
sane-avision
FB6080E USB 0x0638/0x0a82 Complete 1 pass, 1200 dpi, A3 - duplex! - zero edge! avision
(Build: 296)
sane-avision
IT8300 USB 0x0638/0x0a61 Good 1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors avision
(Build: 296)
sane-avision
iVina 1600 USB 0x0638/0x0a10 Unsupported GL646 based, to be added to genesys backend. Same as UMAX Astra 4500. unsupported
(2010-06-09)
?
iVina FB1800 USB 0x0638/0x0a20 Unsupported GL646/GL660 based. Same as UMAX Astra 4700. unsupported
(2010-06-09)
?
iVina FB2400 USB   Unsupported Not supported. No chipset information available. Same as UMAX Astra 6700. unsupported
(2010-06-09)
?

Manufacturer: Bell and Howell

Link(s): http://www.bhscanners.com/

Model Interface USB id Status Comment Backend Manpage
COPISCAN II 2135 SCSI   Untested Simplex Scanner bh
(1.0-4)
sane-bh
COPISCAN II 2137(A) SCSI   Good Simplex Scanner (with ACE) - limited testing bh
(1.0-4)
sane-bh
COPISCAN II 2138A SCSI   Untested Simplex Scanner with ACE bh
(1.0-4)
sane-bh
COPISCAN II 3238 SCSI   Untested Simplex Scanner bh
(1.0-4)
sane-bh
COPISCAN II 3338(A) SCSI   Untested Simplex Scanner (with ACE) bh
(1.0-4)
sane-bh
COPISCAN II 6338 SCSI   Good Duplex Scanner with ACE - development model bh
(1.0-4)
sane-bh

Manufacturer: Bell+Howell

Model Interface USB id Status Comment Backend Manpage
2000F SCSI   Basic 1 pass, ??? dpi, A4 avision
(Build: 296)
sane-avision

Manufacturer: BenQ

Link(s): http://www.benq.com/

Model Interface USB id Status Comment Backend Manpage
5550 USB 0x04a5/0x2211 Minimal developing yet hp3900
(0.12)
sane-hp3900

Manufacturer: Benq (Acer)

Link(s): http://www.benq.com
Comment: Formerly Acer Peripherals

Model Interface USB id Status Comment Backend Manpage
300f SCSI   Good   SnapScan
(1.4)
sane-snapscan
310P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
310s SCSI   Good   SnapScan
(1.4)
sane-snapscan
310U USB 0x04a5/0x1a20 Good   SnapScan
(1.4)
sane-snapscan
320P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
320U USB 0x04a5/0x2022 Good   SnapScan
(1.4)
sane-snapscan
340P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
340U USB 0x04a5/0x2022 Good   SnapScan
(1.4)
sane-snapscan
610P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
610plus SCSI   Good   SnapScan
(1.4)
sane-snapscan
610PT Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
610s SCSI   Good   SnapScan
(1.4)
sane-snapscan
620P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
620PT Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
620s SCSI   Good   SnapScan
(1.4)
sane-snapscan
620U USB 0x04a5/0x1a2a Good Optional tranparency unit supported SnapScan
(1.4)
sane-snapscan
620UT USB 0x04a5/0x2040 Good Optional tranparency unit supported SnapScan
(1.4)
sane-snapscan
640BT USB 0x04a5/0x20be Good Optional tranparency unit supported SnapScan
(1.4)
sane-snapscan
640bu USB 0x04a5/0x207e Good   SnapScan
(1.4)
sane-snapscan
640P Parport   Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
640U USB 0x04a5/0x2060 Good Optional tranparency unit supported SnapScan
(1.4)
sane-snapscan
1240 USB 0x04a5/0x20c0 Good Optional tranparency unit supported SnapScan
(1.4)
sane-snapscan
3300 USB 0x04a5/0x20de Good   SnapScan
(1.4)
sane-snapscan
3300 USB 0x04a5/0x20b0 Good   SnapScan
(1.4)
sane-snapscan
4300 USB 0x04a5/0x20de Good   SnapScan
(1.4)
sane-snapscan
4300 USB 0x04a5/0x20b0 Good   SnapScan
(1.4)
sane-snapscan
5000 USB 0x04a5/0x20f8 Good USB ID 0x04a5,0x20f8: Color / grayscale scans working up to 1200 DPI SnapScan
(1.4)
sane-snapscan
5000E USB 0x04a5/0x20fc Basic Same as 5000U, working up to 600 DPI SnapScan
(1.4)
sane-snapscan
5000U USB 0x04a5/0x20fc Basic Same as 5000E, working up to 600 DPI SnapScan
(1.4)
sane-snapscan
5150 USB 0x04a5/0x2137 Basic Calibration algorithm unknown SnapScan
(1.4)
sane-snapscan
5250 USB 0x04a5/0x2137 Basic Same hardware as 5150 (?), Calibration algorithm unknown SnapScan
(1.4)
sane-snapscan
5300 USB 0x04a5/0x20fe Basic Problems with firmware upload reported SnapScan
(1.4)
sane-snapscan
5450 USB 0x04a5/0x211e Unsupported Unsupported. unsupported
(2010-06-09)
?
5550 USB 0x04a5/0x2211 Unsupported Unsupported, see link for details. unsupported
(2010-06-09)
?
5560 USB 0x04a5/0x2311 Unsupported   unsupported
(2010-06-09)
?
7400UT USB 0x04a5/0x2202 Unsupported   unsupported
(2010-06-09)
?
ScanWit 2720s SCSI   Good   SnapScan
(1.4)
sane-snapscan

Manufacturer: BlackWidow

Link(s): http://www.blackwidow.co.uk/

Model Interface USB id Status Comment Backend Manpage
BW4800SP SCSI   Complete rebadged Artec AT3 artec
(unmaintained)
sane-artec

Manufacturer: Boeder

Model Interface USB id Status Comment Backend Manpage
Sm@rtScan Office Parport USB 0x05cb/0x1483 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
Sm@rtScan Slim Edition USB 0x05d8/0x4002 Good Similar to Artec Ultima 2000 gt68xx
(1.0-84)
sane-gt68xx

Manufacturer: BrightScan

Model Interface USB id Status Comment Backend Manpage
BrighScan OpticPro Parport (SPP, EPP)   Complete Reported as P12 plustek_pp
(0.43)
sane-plustek_pp

Manufacturer: Brother

Link(s): http://www.brother.com/

Model Interface USB id Status Comment Backend Manpage
MFC 2500 USB 0x04f9/0x000a Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
MFC 4600 Parport   Unsupported The parport 200x400dpi grayscale version of this scanner is unsupported. Dmitri Katchalov did some investigations on this scanner. If you want to write a backend, contact him (see link). unsupported
(2010-06-09)
?
MFC 7300c Parport USB 0x04f9/0x0106 Unsupported   unsupported
(2010-06-09)
?
MFC 9600 USB 0x04f9/0x0101 Unsupported   unsupported
(2010-06-09)
?

Manufacturer: C-Channel

Link(s): http://www.c-channel.ch/

Model Interface USB id Status Comment Backend Manpage
MoneyPen II USB   Unsupported Probably unsupported. unsupported
(2010-06-09)
?
MyPen Light USB 0x0a93/0x0005 Unsupported See bug #306792 for details. unsupported
(2010-06-09)
?
MyPen Pro USB   Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Canon

Link(s): http://www.canon.com/

Model Interface USB id Status Comment Backend Manpage
Canon Image Formula 101 USB 0x1083/0x162e Unsupported GL846 based, work in progress genesys
(1.0-63)
sane-genesys
CanoScan 300 SCSI   Good 1 pass; flatbed scanner canon
(1.12)
sane-canon
CanoScan 600 SCSI   Good 1 pass; flatbed scanner canon
(1.12)
sane-canon
CanoScan 620S SCSI   Good 1 pass; flatbed scanner canon
(1.12)
sane-canon
CanoScan 700F USB 0x04a9/0x1907 Good GL847 based, resolution from 75 to 4800 dpi genesys
(1.0-63)
sane-genesys
CanoScan 1200S SCSI   Good 1 pass; flatbed scanner canon
(1.12)
sane-canon
CanoScan 2700F SCSI   Good 1 pass; film scanner canon
(1.12)
sane-canon
CanoScan 2710S SCSI   Good 1 pass; 36bit film scanner canon
(1.12)
sane-canon
CanoScan 3000 USB 0x04a9/0x2215 Unsupported GL660+GL646 based. unsupported
(2010-06-09)
?
CanoScan 3000ex USB 0x04a9/0x2215 Unsupported GL660+GL646 based. unsupported
(2010-06-09)
?
CanoScan 3000F USB 0x04a9/0x2215 Unsupported GL660+GL646 based, to be added to genesys backend unsupported
(2010-06-09)
?
CanoScan 4200F USB 0x04a9/0x221b Unsupported Probably unsupported. See link. unsupported
(2010-06-09)
?
CanoScan 4400F USB 0x04a9/0x2228 Unsupported GL843 based, to be added to genesys backend unsupported
(2010-06-09)
?
CanoScan 4400f USB 0x04a9/0x2228 Unsupported GL843 based, to be added to the genesys backend genesys
(1.0-63)
sane-genesys
CanoScan 5000F USB 0x04a9/0x2212 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
CanoScan 5200F USB 0x04a9/0x2217 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
CanoScan 5600F USB 0x04a9/0x1906 Unsupported GL847 based, to be added to the genesys backend genesys
(1.0-63)
sane-genesys
CanoScan 8000F USB 0x04a9/0x220f Unsupported Not supported. See link for more information. With transparency adapter. unsupported
(2010-06-09)
?
CanoScan 8400F USB 0x04a9/0x221e Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
CanoScan 8600F USB 0x04a9/0x2229 Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
CanoScan 8800F USB 0x04a9/0x1901 Complete Flatbed scan. TPU for negatives and slides. All resolutions supported (up to 4800DPI). pixma
(0.17.3)
sane-pixma
CanoScan 9000F USB 0x04a9/0x1908 Complete Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI. pixma
(0.17.3)
sane-pixma
CanoScan 9000F Mark II USB 0x04a9/0x190d Complete Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI. pixma
(0.17.3)
sane-pixma
CanoScan 9900F USB 0x04a9/0x2210 Unsupported Probably unsupported, similar to 8000F. 3200x6400 dpi USB2. With transparency adapter. unsupported
(2010-06-09)
?
CanoScan 9950F USB 0x04a9/0x2219 Unsupported Probably unsupported. unsupported
(2010-06-09)
?
CanoScan D646U USB 0x04a9/0x220b Unsupported Probably not supported. See link for more information and test program. unsupported
(2010-06-09)
?
CanoScan D646U ex USB 0x04a9/0x220b Unsupported Probably not supported. See D646. unsupported
(2010-06-09)
?
CanoScan D660U USB 0x04a9/0x2208 Good TPA scans not perfect plustek
(0.52)
sane-plustek
CanoScan D1230U USB 0x04a9/0x2209 Unsupported Probably not supported. unsupported
(2010-06-09)
?
CanoScan D1250U2 USB 0x04a9/0x220c Unsupported Not supported. However, someone started working on this scanner and some information is available (see link). unsupported
(2010-06-09)
?
CanoScan D2400UF USB 0x04a9/0x220a Unsupported Not supported. See link. unsupported
(2010-06-09)
?
CanoScan FB310P Parport (ECP)   Unsupported Rebadged Avision, different command set canon_pp
(0.33)
sane-canon_pp
CanoScan FB320P Parport (ECP)   Basic Newly added support canon_pp
(0.33)
sane-canon_pp
CanoScan FB320U USB 0x04a9/0x2201 Unsupported Probably not supported. No details known. unsupported
(2010-06-09)
?
CanoScan FB330P Parport (ECP)   Good   canon_pp
(0.33)
sane-canon_pp
CanoScan FB610P Parport (ECP)   Unsupported Rebadged Avision, different command set canon_pp
(0.33)
sane-canon_pp
CanoScan FB620P Parport (ECP)   Basic Newly added support canon_pp
(0.33)
sane-canon_pp
CanoScan FB620U USB 0x04a9/0x2202 Unsupported Probably not supported. Some information is available. unsupported
(2010-06-09)
?
CanoScan FB630P Parport (ECP)   Good   canon_pp
(0.33)
sane-canon_pp
CanoScan fb630u USB 0x04a9/0x2204 Good OK canon630u
(0.1)
sane-canon630u
CanoScan fb636u USB 0x04a9/0x2204 Good OK canon630u
(0.1)
sane-canon630u
CanoScan FB1210U USB 0x04a9/0x2205 Unsupported Not supported. However, a stand-alone program for FreeBSD is available. unsupported
(2010-06-09)
?
CanoScan LiDE 35 USB 0x04a9/0x2213 Good Same ids as LiDE 50. genesys
(1.0-63)
sane-genesys
CanoScan LiDE 40 USB 0x04a9/0x2213 Good Same ids as LiDE 50. genesys
(1.0-63)
sane-genesys
CanoScan LiDE 50 USB 0x04a9/0x2213 Good   genesys
(1.0-63)
sane-genesys
CanoScan LiDE 60 USB 0x04a9/0x221c Good   genesys
(1.0-63)
sane-genesys
CanoScan LiDE 70 USB 0x04a9/0x2225 Unsupported Philips chip. Backend started, see link unsupported
(2010-06-09)
?
CanoScan LiDE 80 USB 0x04a9/0x2214 Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
CanoScan LiDE 90 USB 0x04a9/0x1900 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
CanoScan LiDE 100 USB 0x04a9/0x1904 Complete GL847 based, resolution from 75 to 2400 dpi genesys
(1.0-63)
sane-genesys
CanoScan LiDE 110 USB 0x04a9/0x1909 Complete GL124 based, resolution from 75 to 2400 dpi genesys
(1.0-63)
sane-genesys
CanoScan LiDE 200 USB 0x04a9/0x1905 Complete GL847 based, resolution from 75 to 4800 dpi genesys
(1.0-63)
sane-genesys
CanoScan LiDE 210 USB 0x04a9/0x190a Complete GL124 based, resolution from 75 to 2400 dpi genesys
(1.0-63)
sane-genesys
CanoScan LiDE 500F USB 0x04a9/0x221f Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
CanoScan LiDE 600 USB 0x04a9/0x2224 Unsupported Philips chip. Backend started, see link unsupported
(2010-06-09)
?
CanoScan LiDE 600F USB 0x04a9/0x2224 Unsupported Philips chip. Backend started, see link unsupported
(2010-06-09)
?
CanoScan LiDE25 USB 0x04a9/0x2220 Good   plustek
(0.52)
sane-plustek
CanoScan N340P Parport (ECP)   Good   canon_pp
(0.33)
sane-canon_pp
CanoScan N640P Parport (ECP)   Good   canon_pp
(0.33)
sane-canon_pp
CanoScan N640P ex Parport (ECP)   Good Just an N640P in a different box? canon_pp
(0.33)
sane-canon_pp
CanoScan N650U/N656U USB 0x04a9/0x2206 Complete   plustek
(0.52)
sane-plustek
CanoScan N670U/N676U/LiDE20 USB 0x04a9/0x220d Complete   plustek
(0.52)
sane-plustek
CanoScan N1220U USB 0x04a9/0x2207 Complete   plustek
(0.52)
sane-plustek
CanoScan N1240U/LiDE30 USB 0x04a9/0x220e Complete   plustek
(0.52)
sane-plustek
CR-25 USB 0x1083/0x161a Untested Please test! canon_dr
(38)
sane-canon_dr
CR-55 USB 0x1083/0x160c Untested Please test! canon_dr
(38)
sane-canon_dr
CR-135i USB SCSI 0x1083/0x1639 Untested Please test! canon_dr
(38)
sane-canon_dr
CR-180 USB SCSI 0x04a9/0x1602 Untested Please test! canon_dr
(38)
sane-canon_dr
CR-180II USB SCSI 0x04a9/0x1602 Untested Same as CR-180? Please test! canon_dr
(38)
sane-canon_dr
CR-190i USB SCSI 0x1083/0x162b Untested Please test! canon_dr
(38)
sane-canon_dr
DR-1210C USB 0x1083/0x160f Untested Later version? Please test! canon_dr
(38)
sane-canon_dr
DR-1210C USB 0x04a9/0x2222 Untested Older version? Please test! canon_dr
(38)
sane-canon_dr
DR-2010C USB 0x1083/0x161b Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions. canon_dr
(38)
sane-canon_dr
DR-2010M USB   Untested Mac version of DR-2010C? Please test! canon_dr
(38)
sane-canon_dr
DR-2020U USB   Unsupported GL84x? unsupported
(2010-06-09)
?
DR-2050C USB 0x04a9/0x160a Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration. canon_dr
(38)
sane-canon_dr
DR-2050SP USB 0x04a9/0x160a Untested Same as DR-2050C? Please test! canon_dr
(38)
sane-canon_dr
DR-2080C USB SCSI 0x04a9/0x1601 Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration canon_dr
(38)
sane-canon_dr
DR-2510C USB 0x1083/0x1617 Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions canon_dr
(38)
sane-canon_dr
DR-2510M USB   Untested Mac version of DR-2510C? Please test! canon_dr
(38)
sane-canon_dr
DR-2580C USB SCSI 0x04a9/0x1608 Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration canon_dr
(38)
sane-canon_dr
DR-3010C USB 0x1083/0x161d Good Minimal testing, settings copied from DR-2510C canon_dr
(38)
sane-canon_dr
DR-3020C SCSI   Untested Please test! canon_dr
(38)
sane-canon_dr
DR-3060 SCSI   Untested Please test! canon_dr
(38)
sane-canon_dr
DR-3080C SCSI   Untested Almost works, need to investigate traces from windows driver canon_dr
(38)
sane-canon_dr
DR-3080CII USB SCSI 0x04a9/0x1609 Untested Almost works, need to investigate traces from windows driver canon_dr
(38)
sane-canon_dr
DR-4010C USB 0x1083/0x1614 Good Binary/HT/Gray/Color, Simplex/Duplex working. Multistream unsupported. canon_dr
(38)
sane-canon_dr
DR-4580U USB   Untested Please test! canon_dr
(38)
sane-canon_dr
DR-5010C USB 0x04a9/0x1606 Untested Please test! canon_dr
(38)
sane-canon_dr
DR-5020 SCSI   Good LineArt, Duplex working, cannot read buttons or screen? canon_dr
(38)
sane-canon_dr
DR-5060F SCSI   Basic Grayscale works, LineArt might canon_dr
(38)
sane-canon_dr
DR-5080C SCSI   Untested Please test! canon_dr
(38)
sane-canon_dr
DR-6010C USB SCSI 0x1083/0x1626 Untested Please test! canon_dr
(38)
sane-canon_dr
DR-6030C USB SCSI 0x1083/0x1638 Untested Please test! canon_dr
(38)
sane-canon_dr
DR-6050C USB SCSI 0x1083/0x1624 Good Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode canon_dr
(38)
sane-canon_dr
DR-6080 USB SCSI 0x04a9/0x1607 Good Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported canon_dr
(38)
sane-canon_dr
DR-7080C USB SCSI 0x04a9/0x1604 Untested Please test! canon_dr
(38)
sane-canon_dr
DR-7090C USB SCSI 0x1083/0x1620 Good ADF and flatbed work canon_dr
(38)
sane-canon_dr
DR-7550C USB SCSI 0x1083/0x1623 Untested Assumed compatible with DR-6050C canon_dr
(38)
sane-canon_dr
DR-7580 USB SCSI 0x04a9/0x160b Good Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported canon_dr
(38)
sane-canon_dr
DR-9050C USB SCSI 0x1083/0x1622 Good Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode canon_dr
(38)
sane-canon_dr
DR-9080C USB SCSI 0x04a9/0x1603 Good Simplex, duplex, all resolutions, binary/ht/gray/color, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported canon_dr
(38)
sane-canon_dr
DR-X10C USB SCSI 0x1083/0x1618 Untested Please test! canon_dr
(38)
sane-canon_dr
DR3020 SCSI   Untested Please test! canon_dr
(38)
sane-canon_dr
DR4080U USB   Untested Please test! canon_dr
(38)
sane-canon_dr
FS4000 USB SCSI 0x04a9/0x3042 Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
i-SENSYS MF3010 USB Ethernet 0x04a9/0x2759 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
I-SENSYS MF4320d USB 0x04a9/0x26ee Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
I-SENSYS MF4330d USB 0x04a9/0x26ee Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
i-SENSYS MF4550d USB 0x04a9/0x2736 Good Flatbed and ADF scan. All resolutions supported (up to 600DPI). pixma
(0.17.3)
sane-pixma
i-SENSYS MF5880dn USB 0x04a9/0x26f9 Untested Testers needed! pixma
(0.17.3)
sane-pixma
i-SENSYS MF6680dn USB 0x04a9/0x26fa Untested Testers needed! pixma
(0.17.3)
sane-pixma
imageCLASS D420 USB 0x04a9/0x26ef Complete All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported. pixma
(0.17.3)
sane-pixma
imageCLASS D480 USB 0x04a9/0x26ed Complete All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported. pixma
(0.17.3)
sane-pixma
imageCLASS MF3110 USB 0x04a9/0x2660 Complete All resolutions supported (up to 600DPI). pixma
(0.17.3)
sane-pixma
imageCLASS MF3240 USB 0x04a9/0x2684 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4010 USB 0x04a9/0x26b4 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4018 USB 0x04a9/0x26b4 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4120 USB 0x04a9/0x26a3 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4122 USB 0x04a9/0x26a3 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4140 USB 0x04a9/0x26a3 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4150 USB 0x04a9/0x26a3 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4270 USB 0x04a9/0x26b5 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4350d USB 0x04a9/0x26ee Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4370dn USB 0x04a9/0x26ec Good Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported pixma
(0.17.3)
sane-pixma
imageCLASS MF4380dn USB 0x04a9/0x26ec Good Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported pixma
(0.17.3)
sane-pixma
imageCLASS MF4410 USB 0x04a9/0x2737 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4430 USB 0x04a9/0x2737 Good Flatbed and ADF scan. All resolutions supported (up to 600DPI). ADF empty buggy. pixma
(0.17.3)
sane-pixma
imageCLASS MF4660 USB 0x04a9/0x26b0 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF4690 USB 0x04a9/0x26b0 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF5630 USB 0x04a9/0x264e Untested Testers needed! pixma
(0.17.3)
sane-pixma
imageCLASS MF5730 USB 0x04a9/0x265d Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
imageCLASS MF5750 USB 0x04a9/0x265e Untested Testers needed! pixma
(0.17.3)
sane-pixma
imageCLASS MF5770 USB 0x04a9/0x265f Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI). pixma
(0.17.3)
sane-pixma
imageCLASS MF6500 series USB 0x04a9/0x2686 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF6550 USB 0x04a9/0x2686 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
imageCLASS MF8030 USB 0x04a9/0x2707 Untested Testers needed! pixma
(0.17.3)
sane-pixma
imageCLASS MF8170c USB 0x04a9/0x2659 Untested Testers needed! pixma
(0.17.3)
sane-pixma
imageRUNNER 1020/1024/1025 USB 0x04a9/0x26e6 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
ImageRunner iR1018 USB 0x04a9/0x269d Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
ImageRunner iR1022 USB 0x04a9/0x269d Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
ImageRunner iR1023 USB 0x04a9/0x269d Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
IS 12 USB   Unsupported Probably not supported. Scanner cardridge for Canon inkjet printers. unsupported
(2010-06-09)
?
IS 22 Parport   Unsupported Probably not supported. Scanner cardridge for Canon inkjet printers. unsupported
(2010-06-09)
?
IS 32 USB 0x04a9/0x105d Unsupported Probably not supported. Scanner cardridge for Canon inkjet printers. unsupported
(2010-06-09)
?
IS 52 USB   Unsupported Probably not supported. Scanner cardridge for Canon inkjet printers. unsupported
(2010-06-09)
?
IX-4015 SCSI   Good 1 pass; flatbed scanner canon
(1.12)
sane-canon
laserBase MF5650 USB 0x04a9/0x264f Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA E500 USB 0x04a9/0x1758 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA E510 USB 0x04a9/0x1761 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA E600 USB 0x04a9/0x175a Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA E610 USB 0x04a9/0x1767 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MG2100 Series USB 0x04a9/0x1751 Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MG2200 Series USB 0x04a9/0x1760 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MG3100 Series USB WLAN 0x04a9/0x1752 Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MG3200 Series USB 0x04a9/0x1762 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MG4100 Series USB 0x04a9/0x1753 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MG4200 Series USB 0x04a9/0x1763 Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MG5100 Series USB 0x04a9/0x1748 Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MG5200 Series USB 0x04a9/0x1749 Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MG5300 Series USB 0x04a9/0x1754 Complete All resolutions supported (up to 2400DPI). pixma
(0.17.3)
sane-pixma
PIXMA MG5400 Series USB 0x04a9/0x1764 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MG6100 Series USB 0x04a9/0x174a Complete All resolutions supported (up to 2400 DPI) pixma
(0.17.3)
sane-pixma
PIXMA MG6200 Series USB 0x04a9/0x1755 Complete All resolutions supported (up to 4800 DPI) pixma
(0.17.3)
sane-pixma
PIXMA MG6300 Series USB Ethernet 0x04a9/0x1765 Complete All resolutions supported (up to 2400DPI). pixma
(0.17.3)
sane-pixma
PIXMA MG8100 Series USB 0x04a9/0x174b Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MG8200 Series USB Ethernet 0x04a9/0x1756 Complete All resolutions supported (up to 4800DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP110 USB 0x04a9/0x1700 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
PIXMA MP130 USB 0x04a9/0x1701 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
PIXMA MP140 USB 0x04a9/0x172b Complete All resolutions supported (up to 600 DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP150 USB 0x04a9/0x1709 Good   pixma
(0.17.3)
sane-pixma
PIXMA MP160 USB 0x04a9/0x1714 Basic   pixma
(0.17.3)
sane-pixma
PIXMA MP170 USB 0x04a9/0x170a Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP180 USB 0x04a9/0x1715 Basic   pixma
(0.17.3)
sane-pixma
PIXMA MP190 USB 0x04a9/0x1734 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP210 USB 0x04a9/0x1721 Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP220 USB 0x04a9/0x1722 Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP230 USB 0x04a9/0x175f Complete All resolutions supported (up to 600DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP240 USB 0x04a9/0x1732 Complete All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP250 USB 0x04a9/0x173a Complete All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP260 USB 0x04a9/0x1733 Complete All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP270 USB 0x04a9/0x173b Complete All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP280 USB 0x04a9/0x1746 Good All resolutions supported (up to 600DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP360 USB 0x04a9/0x263c Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP370 USB 0x04a9/0x263d Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP375R USB 0x04a9/0x263f Untested Same protocol as Pixma MP360/370/390? Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MP390 USB 0x04a9/0x263e Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP450 USB 0x04a9/0x170b Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP460 USB 0x04a9/0x1716 Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP470 USB 0x04a9/0x1723 Complete All resolutions supported (up to 2400DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP480 USB 0x04a9/0x1731 Complete All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP490 USB 0x04a9/0x173c Complete All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP493 USB 0x04a9/0x1757 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MP495 USB 0x04a9/0x1747 Untested Same protocol as Pixma MP280? Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MP500 USB 0x04a9/0x170c Good   pixma
(0.17.3)
sane-pixma
PIXMA MP510 USB 0x04a9/0x1717 Complete All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP520 USB 0x04a9/0x1724 Complete All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP530 USB 0x04a9/0x1712 Good   pixma
(0.17.3)
sane-pixma
PIXMA MP540 USB 0x04a9/0x1730 Complete All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP550 USB 0x04a9/0x173d Complete All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP560 USB 0x04a9/0x173e Complete All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP600 USB 0x04a9/0x1718 Complete All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP600R USB Ethernet 0x04a9/0x1719 Complete All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP610 USB 0x04a9/0x1725 Complete All resolutions supported (up to 4800DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP620 USB Ethernet 0x04a9/0x172f Complete All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP630 USB 0x04a9/0x172e Complete All resolutions supported (up to 4800DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP640 USB Ethernet 0x04a9/0x173f Complete All resolutions supported (up to 4800DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP700 USB 0x04a9/0x2630 Complete All resolutions supported (flatbed color up to 1200DPI, grayscale up to 600DPI). pixma
(0.17.3)
sane-pixma
PIXMA MP710 USB 0x04a9/0x264d Complete All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MP730 USB 0x04a9/0x262f Good Flatbed color up to 1200DPI, grayscale up to 600DPI. ADF scan to be confirmed. pixma
(0.17.3)
sane-pixma
PIXMA MP740 USB 0x04a9/0x264c Untested Same protocol as Pixma MP710? Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MP750 USB 0x04a9/0x1706 Minimal No grayscale. Canceling scan in ADF mode doesn't eject the paper! pixma
(0.17.3)
sane-pixma
PIXMA MP760 USB 0x04a9/0x1708 Minimal No grayscale. The scanner sometimes hangs! pixma
(0.17.3)
sane-pixma
PIXMA MP770 USB 0x04a9/0x1708 Minimal No grayscale. The scanner sometimes hangs! pixma
(0.17.3)
sane-pixma
PIXMA MP780 USB 0x04a9/0x1707 Minimal No grayscale. The scanner sometimes hangs! pixma
(0.17.3)
sane-pixma
PIXMA MP790 USB 0x04a9/0x1707 Minimal No grayscale. The scanner sometimes hangs! pixma
(0.17.3)
sane-pixma
PIXMA MP800 USB 0x04a9/0x170d Complete All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI. pixma
(0.17.3)
sane-pixma
PIXMA MP800R USB 0x04a9/0x170e Complete All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI. pixma
(0.17.3)
sane-pixma
PIXMA MP810 USB 0x04a9/0x171a Complete All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI. pixma
(0.17.3)
sane-pixma
PIXMA MP830 USB 0x04a9/0x1713 Complete All resolutions supported up to 2400DPI. Flatbed, ADF simplex and Duplex supported. pixma
(0.17.3)
sane-pixma
PIXMA MP960 USB 0x04a9/0x171b Complete All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI. pixma
(0.17.3)
sane-pixma
PIXMA MP970 USB Ethernet 0x04a9/0x1726 Complete All resolutions supported (up to 4800DPI). Full TPU support (negative and slides) at 24 or 48 bits. pixma
(0.17.3)
sane-pixma
PIXMA MP980 USB Ethernet 0x04a9/0x172d Complete Working fine at all resolutions. pixma
(0.17.3)
sane-pixma
PIXMA MP990 USB Ethernet 0x04a9/0x1740 Complete Working fine at all resolutions. pixma
(0.17.3)
sane-pixma
PIXMA MX300 USB 0x04a9/0x1727 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI) pixma
(0.17.3)
sane-pixma
PIXMA MX310 USB 0x04a9/0x1728 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MX320 USB 0x04a9/0x1736 Untested Same protocol as Pixma Generation 3? Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX330 USB 0x04a9/0x1737 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MX340 USB 0x04a9/0x1741 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MX350 USB Ethernet 0x04a9/0x1742 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI) pixma
(0.17.3)
sane-pixma
PIXMA MX360 USB 0x04a9/0x174d Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy. pixma
(0.17.3)
sane-pixma
PIXMA MX370 Series USB 0x04a9/0x1759 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI). pixma
(0.17.3)
sane-pixma
PIXMA MX390 Series USB 0x04a9/0x1766 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX410 USB Ethernet 0x04a9/0x174e Untested Same protocol as Pixma MX420? Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX420 USB Ethernet 0x04a9/0x174f Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy. pixma
(0.17.3)
sane-pixma
PIXMA MX430 Series USB Ethernet 0x04a9/0x175b Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX450 Series USB 0x04a9/0x1768 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX510 Series USB Ethernet 0x04a9/0x175c Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX520 Series USB 0x04a9/0x1769 Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX700 USB Ethernet 0x04a9/0x1729 Complete Flatbed and ADF scan. All resolutions supported (up to 2400DPI) pixma
(0.17.3)
sane-pixma
PIXMA MX710 Series USB Ethernet 0x04a9/0x175d Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX720 Series USB 0x04a9/0x176a Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX850 USB Ethernet 0x04a9/0x172c Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported. pixma
(0.17.3)
sane-pixma
PIXMA MX860 USB Ethernet 0x04a9/0x1735 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported. pixma
(0.17.3)
sane-pixma
PIXMA MX870 USB Ethernet 0x04a9/0x1743 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. pixma
(0.17.3)
sane-pixma
PIXMA MX880 Series USB Ethernet 0x04a9/0x1750 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. pixma
(0.17.3)
sane-pixma
PIXMA MX882 USB Ethernet 0x04a9/0x1750 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. pixma
(0.17.3)
sane-pixma
PIXMA MX885 USB Ethernet 0x04a9/0x1750 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. pixma
(0.17.3)
sane-pixma
PIXMA MX890 Series USB Ethernet 0x04a9/0x175e Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy. pixma
(0.17.3)
sane-pixma
PIXMA MX920 Series USB 0x04a9/0x176b Untested Testers needed! pixma
(0.17.3)
sane-pixma
PIXMA MX7600 USB Ethernet 0x04a9/0x171c Complete Flatbed and ADF scan. All resolutions supported (up to 4800DPI) pixma
(0.17.3)
sane-pixma

Manufacturer: Chinon

Model Interface USB id Status Comment Backend Manpage
DS-3000 Parport Serial Port   Unsupported Unsupported at the moment, but a backend is in preparation. See link. unsupported
(2010-06-09)
?

Manufacturer: Compaq

Link(s): http://www.compaq.com/

Model Interface USB id Status Comment Backend Manpage
S4-100 USB 0x049f/0x001a Complete Identical to UMAX 3400 plustek
(0.52)
sane-plustek
S200 USB 0x049f/0x0021 Unsupported Not supported. 2400x1200 dpi. One bulk-in, one bulk-out and one interrupt endpoint. Type-number: U0001-HB21, another type nr on the inside: 75100512-00 unsupported
(2010-06-09)
?

Manufacturer: Compeye

Model Interface USB id Status Comment Backend Manpage
Simplex 1236C Parport USB 0x05cb/0x1483 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Corex

Link(s): http://www.cardscan.com/

Model Interface USB id Status Comment Backend Manpage
600c USB 0x08f0/0x0002 Basic 4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner cardscan
(2)
sane-cardscan
800c USB 0x08f0/0x0005 Good 4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner cardscan
(2)
sane-cardscan
Cardscan 500 USB 0x08f0/0x0001 Unsupported Probably not supported. Businesscard reader. unsupported
(2010-06-09)
?
Cardscan 700 C USB 0x08f0/0x0004 Unsupported Probably not supported. unsupported
(2010-06-09)
?

Manufacturer: Cybercom

Model Interface USB id Status Comment Backend Manpage
9352 Parport (EPP)   Good CIS scanner mustek_pp
(13)
sane-mustek_pp

Manufacturer: DCT

Link(s): http://www.docucap.com/
Comment: Successor of Syscan in the USA

Model Interface USB id Status Comment Backend Manpage
DocketPort 487 USB 0x1dcc/0x4810 Basic All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally. genesys
(1.0-63)
sane-genesys

Manufacturer: Dell

Link(s): http://www.dell.com/

Model Interface USB id Status Comment Backend Manpage
922 USB 0x413c/0x5109 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
1600n Ethernet USB 0x413c/0x5250 Basic Supports colour and monochrome scans over ethernet (USB not supported) dell1600n_net ?
A920 USB 0x413c/0x5105 Good Relabelled X11xx model lexmark
(1.0-0)
sane-lexmark
A940 USB 0x413c/0x5106 Unsupported Probably rebadged Lexmark X5150. May work with sane-lexmark? See bug #312130 unsupported
(2010-06-09)
?
A960 USB 0x413c/0x5107 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
Dell MFP Laser Printer 1815dn USB 0x413c/0x5124 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp

Manufacturer: Devcom

Link(s): http://www.blackwidow.co.uk/

Model Interface USB id Status Comment Backend Manpage
9630S SCSI   Untested   pie
(1.0)
sane-pie
9636PRO SCSI   Good   pie
(1.0)
sane-pie
9636S SCSI   Untested   pie
(1.0)
sane-pie

Manufacturer: Dextra

Model Interface USB id Status Comment Backend Manpage
DF-600P SCSI   Good sub model VM3510 teco1
(1.0-10)
sane-teco1
DF-1200T+ SCSI   Untested sub model VM3530+ teco1
(1.0-10)
sane-teco1
DF-4830T SCSI   Untested sub model VM4542 teco1
(1.0-10)
sane-teco1
DF-9624 SCSI   Untested sub model VM6530+ teco1
(1.0-10)
sane-teco1

Manufacturer: Dexxa

Link(s): http://www.dexxa.com

Model Interface USB id Status Comment Backend Manpage
4800 Parport   Basic Requires the program 'as6edriver' to run. as6e
(0.5)
sane-as6e

Manufacturer: E-Lux

Comment: E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX

Model Interface USB id Status Comment Backend Manpage
j-6121 Parport   Unsupported Probably unsupported. Sold 1998. Same as E-Lux j-6121. unsupported
(2010-06-09)
?

Manufacturer: EDGE

Model Interface USB id Status Comment Backend Manpage
KTX-9600US SCSI   Untested no feedback umax
(1.0-41)
sane-umax

Manufacturer: EDT (Electronic Document Technology)

Link(s): http://www.bizcardreader.com/

Model Interface USB id Status Comment Backend Manpage
BizCardReader 900C USB 0x0a53/0x5001 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Enhans

Comment: E-Lux and Enhans seem to have been purchased by dysan, now known as MEMOREX

Model Interface USB id Status Comment Backend Manpage
j-6121 Parport   Unsupported Probably unsupported. Sold 1998. Same as E-Lux j-6121. unsupported
(2010-06-09)
?
M-3630 A Parport   Unsupported Probably unsupported. unsupported
(2010-06-09)
?

Manufacturer: Epson

Link(s): http://www.epson.com/, http://www.epson.com

Model Interface USB id Status Comment Backend Manpage
Actionscanner II parallel SCSI   Good overseas version of the GT-5000 epson2
(1.0.124)
sane-epson2
Actionscanner II SCSI Parport   Good US version of GT-5000 epson
(unmaintained)
sane-epson
AcuLaser CX11 USB 0x04b8/0x0815 Good overseas version of the LP-A500 epson2
(1.0.124)
sane-epson2
AcuLaser CX11 USB 0x04b8/0x0815 Good   epson
(unmaintained)
sane-epson
AcuLaser CX11NF USB Network 0x04b8/0x0815 Good network interface supported
AcuLaser CX11 with network interface and fax
epson2
(1.0.124)
sane-epson2
AcuLaser CX11NF USB 0x04b8/0x0815 Good   epson
(unmaintained)
sane-epson
AcuLaser CX21 USB 0x04b8/0x0835 Good network interface probably supported epson2
(1.0.124)
sane-epson2
Artisan 700 USB Network 0x04b8/0x0846 Good network interface supported
all-in-one
overseas version of the EP-801A
epson2
(1.0.124)
sane-epson2
Artisan 710 Series USB 0x04b8/0x0852 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Artisan 800 USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
overseas version of the EP-901A
epson2
(1.0.124)
sane-epson2
Artisan 810 Series USB 0x04b8/0x0853 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
CC-500L USB 0x04b8/0x010d Unsupported all-in-one epson2
(1.0.124)
sane-epson2
CC-550L USB 0x04b8/0x011a Unsupported all-in-one epson2
(1.0.124)
sane-epson2
CC-570L USB 0x04b8/0x0802 Good all-in-one epson2
(1.0.124)
sane-epson2
CC-600PX USB 0x04b8/0x0801 Good all-in-one epson2
(1.0.124)
sane-epson2
CC-700 USB 0x04b8/0x0108 Unsupported all-in-one epson2
(1.0.124)
sane-epson2
CX-3200 USB 0x04b8/0x0802 Good   epson
(unmaintained)
sane-epson
CX-3600 USB 0x04b8/0x080e Good   epson
(unmaintained)
sane-epson
CX-3650 USB 0x04b8/0x080e Good   epson
(unmaintained)
sane-epson
CX-3700 USB 0x04b8/0x0818 Good   epson
(unmaintained)
sane-epson
CX-3800 USB 0x04b8/0x0818 Good   epson
(unmaintained)
sane-epson
CX-4200 USB 0x04b8/0x0820 Good   epson
(unmaintained)
sane-epson
CX-4600 USB 0x04b8/0x080d Good   epson
(unmaintained)
sane-epson
CX-4800 USB 0x04b8/0x0819 Good   epson
(unmaintained)
sane-epson
CX-5000 USB 0x04b8/0x082b Good   epson
(unmaintained)
sane-epson
CX-5200 USB 0x04b8/0x0801 Good   epson
(unmaintained)
sane-epson
CX-5400 USB 0x04b8/0x0808 Good   epson
(unmaintained)
sane-epson
CX-5400 USB 0x04b8/0x0801 Good   epson
(unmaintained)
sane-epson
CX-6300 USB 0x04b8/0x0805 Good   epson
(unmaintained)
sane-epson
CX-6400 USB 0x04b8/0x0805 Good   epson
(unmaintained)
sane-epson
CX-6500 USB 0x04b8/0x0813 Good   epson
(unmaintained)
sane-epson
CX-6600 USB 0x04b8/0x0813 Good   epson
(unmaintained)
sane-epson
DX-3800 USB 0x04b8/0x0818 Good   epson
(unmaintained)
sane-epson
DX-3850 USB 0x04b8/0x0818 Good   epson
(unmaintained)
sane-epson
DX-4050 USB 0x04b8/0x082f Good   epson
(unmaintained)
sane-epson
DX-5000 USB 0x04b8/0x082b Good   epson
(unmaintained)
sane-epson
DX-5050 USB 0x04b8/0x082b Good   epson
(unmaintained)
sane-epson
DX-6000 USB 0x04b8/0x082e Good   epson
(unmaintained)
sane-epson
DX-7400 USB 0x04b8/0x0838 Good   epson
(unmaintained)
sane-epson
EP-702A USB 0x04b8/0x0850 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
EP-801A USB Network 0x04b8/0x0846 Good network interface supported
all-in-one
epson2
(1.0.124)
sane-epson2
EP-802A USB 0x04b8/0x0852 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
EP-901A USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
epson2
(1.0.124)
sane-epson2
EP-901F USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
epson2
(1.0.124)
sane-epson2
EP-902A USB 0x04b8/0x0853 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
ES-300C SCSI parallel   Good overseas version of the GT-6000 epson2
(1.0.124)
sane-epson2
ES-300C SCSI Parport   Good US version of GT-6000 epson
(unmaintained)
sane-epson
ES-300GS SCSI   Good   epson2
(1.0.124)
sane-epson2
ES-300GS SCSI   Good   epson
(unmaintained)
sane-epson
ES-600C parallel   Good overseas version of the GT-5400 epson2
(1.0.124)
sane-epson2
ES-600C Parport   Good US version of GT-6500 epson
(unmaintained)
sane-epson
ES-800C SCSI   Good overseas version of the GT-8000 epson2
(1.0.124)
sane-epson2
ES-1000C ?   Unsupported overseas version of the GT-8500 epson2
(1.0.124)
sane-epson2
ES-1200C parallel   Good overseas version of the GT-9000 epson2
(1.0.124)
sane-epson2
ES-1200C Parport   Good US version of GT-9000 epson
(unmaintained)
sane-epson
ES-2000 SCSI USB 0x04b8/0x0107 Complete IEEE1394 untested epson2
(1.0.124)
sane-epson2
ES-2200 SCSI USB 0x04b8/0x010e Complete IEEE1394 untested epson2
(1.0.124)
sane-epson2
ES-6000 SCSI   Good   epson2
(1.0.124)
sane-epson2
ES-6000H SCSI   Good IEEE1394 untested epson2
(1.0.124)
sane-epson2
ES-6000HS SCSI   Good IEEE1394 untested epson2
(1.0.124)
sane-epson2
ES-7000H SCSI USB 0x04b8/0x0126 Good network interface unsupported
IEEE1394 untested
epson2
(1.0.124)
sane-epson2
ES-8000 SCSI   Untested   epson2
(1.0.124)
sane-epson2
ES-8500 SCSI USB 0x04b8/0x0109 Good IEEE1394 untested epson2
(1.0.124)
sane-epson2
ES-8500 SCSI   Good   epson
(unmaintained)
sane-epson
ES-9000H SCSI   Good IEEE1394 untested epson2
(1.0.124)
sane-epson2
ES-10000G USB 0x04b8/0x0129 Good network interface unsupported
IEEE1394 untested
epson2
(1.0.124)
sane-epson2
ES-D400 USB 0x04b8/0x0136 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
ES-H300 USB 0x04b8/0x012b Good network interface probably supported epson2
(1.0.124)
sane-epson2
ES-H7200 USB Ethernet 0x04b8/0x0138 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Expression 636 SCSI   Complete overseas version of the GT-9500 epson2
(1.0.124)
sane-epson2
Expression 636 SCSI   Complete US version of GT-9500 epson
(unmaintained)
sane-epson
Expression 800 SCSI   Complete overseas version of the GT-9600 epson2
(1.0.124)
sane-epson2
Expression 800 SCSI   Complete   epson
(unmaintained)
sane-epson
Expression 836XL SCSI   Untested overseas version of the ES-8000 epson2
(1.0.124)
sane-epson2
Expression 1600 SCSI USB 0x04b8/0x0107 Complete IEEE1394 untested
overseas version of the ES-2000
epson2
(1.0.124)
sane-epson2
Expression 1600 SCSI USB IEEE-1394 0x04b8/0x0107 Complete   epson
(unmaintained)
sane-epson
Expression 1640XL SCSI USB 0x04b8/0x0109 Good IEEE1394 untested
overseas version of the ES-8500
epson2
(1.0.124)
sane-epson2
Expression 1680 SCSI USB 0x04b8/0x010e Complete IEEE1394 untested
overseas version of the ES-2200
epson2
(1.0.124)
sane-epson2
Expression 1680 SCSI USB IEEE-1394 0x04b8/0x010e Complete   epson
(unmaintained)
sane-epson
Expression 1680 Pro SCSI USB   Untested IEEE1394 option epson2
(1.0.124)
sane-epson2
Expression 1680XL Pro SCSI USB   Untested   epson2
(1.0.124)
sane-epson2
Expression 10000XL USB 0x04b8/0x0129 Good network interface probably supported
IEEE1394 untested
overseas version of the ES-10000G
epson2
(1.0.124)
sane-epson2
Expression 10000XL Graphic Arts USB IEEE1394   Untested network interface probably supported epson2
(1.0.124)
sane-epson2
Expression 10000XL Photo USB IEEE1394   Untested network interface probably supported epson2
(1.0.124)
sane-epson2
F-3200 USB IEEE1394 0x04b8/0x080a Unsupported Film scanner epson2
(1.0.124)
sane-epson2
F-3200 Photo USB IEEE1394   Unsupported   epson2
(1.0.124)
sane-epson2
FilmScan 200 SCSI   Minimal will be supported epson2
(1.0.124)
sane-epson2
GT-1500 USB 0x04b8/0x0133 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-2200 USB 0x04b8/0x0102 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
GT-2200 USB 0x04b8/0x0102 Unsupported   epson2
(1.0.124)
sane-epson2
GT-2500 USB 0x04b8/0x012b Good network interface probably supported
overseas version of the ES-H300
epson2
(1.0.124)
sane-epson2
GT-4000 ?   Untested   epson2
(1.0.124)
sane-epson2
GT-5000 parallel SCSI   Good   epson2
(1.0.124)
sane-epson2
GT-5000 SCSI Parport   Good   epson
(unmaintained)
sane-epson
GT-5400 parallel   Good   epson2
(1.0.124)
sane-epson2
GT-5500 SCSI   Good   epson2
(1.0.124)
sane-epson2
GT-5500 SCSI   Good   epson
(unmaintained)
sane-epson
GT-6000 SCSI Parport   Good   epson2
(1.0.124)
sane-epson2
GT-6000 SCSI Parport   Good   epson
(unmaintained)
sane-epson
GT-6500 parallel   Good overseas version of the GT-5400 epson2
(1.0.124)
sane-epson2
GT-6500 Parport   Good   epson
(unmaintained)
sane-epson
GT-6600U USB 0x04b8/0x0103 Complete   epson2
(1.0.124)
sane-epson2
GT-6700U USB 0x04b8/0x010c Complete   epson2
(1.0.124)
sane-epson2
GT-7000 SCSI   Good   epson
(unmaintained)
sane-epson
GT-7000S SCSI   Complete   epson2
(1.0.124)
sane-epson2
GT-7000U USB 0x04b8/0x0101 Complete   epson2
(1.0.124)
sane-epson2
GT-7200U USB 0x04b8/0x010f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-7300U USB 0x04b8/0x011d Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-7400U USB 0x04b8/0x0120 Unsupported supported by the snapscan backend epson2
(1.0.124)
sane-epson2
GT-7600S SCSI   Complete SCSI version of the GT-7600U epson2
(1.0.124)
sane-epson2
GT-7600U USB 0x04b8/0x0104 Complete USB version of the GT-7600S epson2
(1.0.124)
sane-epson2
GT-7600UF USB 0x04b8/0x0104 Complete GT-7600U with TPU option bundled epson2
(1.0.124)
sane-epson2
GT-7700U USB 0x04b8/0x010b Complete   epson2
(1.0.124)
sane-epson2
GT-8000 SCSI   Good   epson2
(1.0.124)
sane-epson2
GT-8000 SCSI   Good   epson
(unmaintained)
sane-epson
GT-8200U USB 0x04b8/0x0110 Complete   epson2
(1.0.124)
sane-epson2
GT-8200UF USB 0x04b8/0x0110 Good   epson2
(1.0.124)
sane-epson2
GT-8300UF USB 0x04b8/0x011e Complete   epson2
(1.0.124)
sane-epson2
GT-8400UF USB 0x04b8/0x011f Unsupported   epson2
(1.0.124)
sane-epson2
GT-8500 ?   Untested   epson2
(1.0.124)
sane-epson2
GT-8700 SCSI USB 0x04b8/0x010a Complete   epson2
(1.0.124)
sane-epson2
GT-8700F SCSI USB 0x04b8/0x010a Good GT-8700U with TPU option bundled epson2
(1.0.124)
sane-epson2
GT-9000 parallel   Good   epson2
(1.0.124)
sane-epson2
GT-9300UF USB 0x04b8/0x011b Complete   epson2
(1.0.124)
sane-epson2
GT-9400UF USB 0x04b8/0x0116 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-9500 SCSI   Complete   epson2
(1.0.124)
sane-epson2
GT-9600 SCSI   Complete   epson2
(1.0.124)
sane-epson2
GT-9700F USB 0x04b8/0x0112 Complete IEEE1394 untested epson2
(1.0.124)
sane-epson2
GT-9800F USB 0x04b8/0x011c Complete IEEE1394 untested epson2
(1.0.124)
sane-epson2
GT-10000 SCSI   Good overseas version of the ES-6000 epson2
(1.0.124)
sane-epson2
GT-10000+ SCSI   Good IEEE1394 untested
overseas version of the ES-6000H
epson2
(1.0.124)
sane-epson2
GT-12000 SCSI   Untested overseas version of the ES-8000 epson2
(1.0.124)
sane-epson2
GT-15000 SCSI USB 0x04b8/0x0126 Good IEEE1394 untested
overseas version of the ES-7000H
epson2
(1.0.124)
sane-epson2
GT-20000 USB Ethernet 0x04b8/0x0138 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-30000 SCSI   Good IEEE1394 untested
overseas version of the ES-9000H
epson2
(1.0.124)
sane-epson2
GT-D1000 USB 0x04b8/0x0133 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F500 USB 0x04b8/0x0121 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F520 USB 0x04b8/0x0122 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F550 USB 0x04b8/0x0121 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F570 USB 0x04b8/0x0122 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F600 USB 0x04b8/0x0118 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F650 USB 0x04b8/0x012d Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F670 USB 0x04b8/0x012e Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F700 USB 0x04b8/0x012f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-F720 USB 0x04b8/0x0131 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-S50 USB 0x04b8/0x0137 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-S80 USB 0x04b8/0x0136 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-S600 USB 0x04b8/0x012d Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-S620 USB 0x04b8/0x0131 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-X700 USB 0x04b8/0x0128 Complete IEEE1394 untested epson2
(1.0.124)
sane-epson2
GT-X750 USB 0x04b8/0x0119 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-X770 USB 0x04b8/0x0130 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-X800 USB 0x04b8/0x012a Complete film area guide mode not supported
IEEE1394 untested
epson2
(1.0.124)
sane-epson2
GT-X820 USB 0x04b8/0x013a Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
GT-X900 USB 0x04b8/0x012c Good IEEE1394 untested epson2
(1.0.124)
sane-epson2
GT-X970 USB 0x04b8/0x0135 Good IEEE1394 untested epson2
(1.0.124)
sane-epson2
LP-7900CS ?   Untested business all-in-one; scanner is a ES-7000H epson2
(1.0.124)
sane-epson2
LP-9000CCH ?   Untested business all-in-one; scanner is a ES-9000H epson2
(1.0.124)
sane-epson2
LP-9000CCS ?   Untested business all-in-one; scanner is a ES-7000H epson2
(1.0.124)
sane-epson2
LP-9000CFH ?   Untested business all-in-one; scanner is a ES-9000H epson2
(1.0.124)
sane-epson2
LP-9500CCS ?   Untested business all-in-one; scanner is a ES-7000H epson2
(1.0.124)
sane-epson2
LP-9500CFH ?   Untested business all-in-one; scanner is a ES-9000H epson2
(1.0.124)
sane-epson2
LP-9500CH2 ?   Untested business all-in-one; scanner is a ES-9000H epson2
(1.0.124)
sane-epson2
LP-9800CCH ?   Untested business all-in-one; scanner is a ES-9000H epson2
(1.0.124)
sane-epson2
LP-9800CCS ?   Untested business all-in-one; scanner is a ES-7000H epson2
(1.0.124)
sane-epson2
LP-9800CFH ?   Untested business all-in-one; scanner is a ES-9000H epson2
(1.0.124)
sane-epson2
LP-A500 USB Network 0x04b8/0x0815 Good network interface supported
business all-in-one
epson2
(1.0.124)
sane-epson2
LP-M5000 USB 0x04b8/0x0843 Good network interface probably supported
business all-in-one
epson2
(1.0.124)
sane-epson2
LP-M5500 USB 0x04b8/0x0817 Good network interface probably supported
business all-in-one
epson2
(1.0.124)
sane-epson2
LP-M5500F USB 0x04b8/0x0817 Good network interface probably supported
business all-in-one
LP-M5500 with the fax option bundled
epson2
(1.0.124)
sane-epson2
LP-M5600 USB 0x04b8/0x0833 Good network interface probably supported
business all-in-one
epson2
(1.0.124)
sane-epson2
LP-M6000 USB 0x04b8/0x0834 Good network interface probably supported
business all-in-one
epson2
(1.0.124)
sane-epson2
ME 200 USB 0x04b8/0x0830 Good all-in-one epson2
(1.0.124)
sane-epson2
ME 300 USB 0x04b8/0x0841 Good all-in-one
overseas version of the PX-401A
epson2
(1.0.124)
sane-epson2
ME OFFICE 510 USB 0x04b8/0x084f Good all-in-one epson2
(1.0.124)
sane-epson2
ME Office 600F USB 0x04b8/0x0848 Good all-in-one epson2
(1.0.124)
sane-epson2
ME OFFICE 650FN Series USB 0x04b8/0x0854 Good all-in-one epson2
(1.0.124)
sane-epson2
ME Office 700FW USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
epson2
(1.0.124)
sane-epson2
Perfection 600 SCSI   Good OK, SCSI-ID=EPSON Perfection600 umax
(1.0-41)
sane-umax
Perfection 610 USB 0x04b8/0x0103 Complete overseas version of the GT-6600U epson2
(1.0.124)
sane-epson2
Perfection 610 USB 0x04b8/0x0103 Complete   epson
(unmaintained)
sane-epson
Perfection 636 SCSI   Complete   epson
(unmaintained)
sane-epson
Perfection 636S SCSI   Complete overseas version of the GT-7000S epson2
(1.0.124)
sane-epson2
Perfection 636S SCSI   Complete US version of GT-7000 epson
(unmaintained)
sane-epson
Perfection 636U USB 0x04b8/0x0101 Complete overseas version of the GT-7000U epson2
(1.0.124)
sane-epson2
Perfection 636U USB 0x04b8/0x0101 Complete   epson
(unmaintained)
sane-epson
Perfection 640 USB 0x04b8/0x010c Complete   epson
(unmaintained)
sane-epson
Perfection 640U USB 0x04b8/0x010c Complete overseas version of the GT-6700U epson2
(1.0.124)
sane-epson2
Perfection 660 USB 0x04b8/0x0114 Good   SnapScan
(1.4)
sane-snapscan
Perfection 1200Photo USB 0x04b8/0x0104 Complete with TPU epson
(unmaintained)
sane-epson
Perfection 1200S SCSI   Complete overseas version of the GT-7600S epson2
(1.0.124)
sane-epson2
Perfection 1200S SCSI   Complete   epson
(unmaintained)
sane-epson
Perfection 1200U USB 0x04b8/0x0104 Complete overseas version of the GT-7600U epson2
(1.0.124)
sane-epson2
Perfection 1200U USB 0x04b8/0x0104 Complete   epson
(unmaintained)
sane-epson
Perfection 1200U PHOTO USB 0x04b8/0x0104 Complete Perfection 1200U with TPU option bundled
overseas version of the GT-7600UF
epson2
(1.0.124)
sane-epson2
Perfection 1240 SCSI USB 0x04b8/0x010b Complete   epson
(unmaintained)
sane-epson
Perfection 1240U USB 0x04b8/0x010b Complete overseas version of the GT-7700U epson2
(1.0.124)
sane-epson2
Perfection 1250 USB 0x04b8/0x010f Complete   plustek
(0.52)
sane-plustek
Perfection 1250 PHOTO USB 0x04b8/0x010f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 1250Photo USB 0x04b8/0x010f Good TPA scans not perfect plustek
(0.52)
sane-plustek
Perfection 1260 USB 0x04b8/0x011d Complete   plustek
(0.52)
sane-plustek
Perfection 1260 PHOTO USB 0x04b8/0x011d Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 1260Photo USB 0x04b8/0x011d Good TPA scans not perfect plustek
(0.52)
sane-plustek
Perfection 1270 USB 0x04b8/0x0120 Good   SnapScan
(1.4)
sane-snapscan
Perfection 1600 SCSI   Unsupported   epson2
(1.0.124)
sane-epson2
Perfection 1640 SCSI USB 0x04b8/0x010a Complete   epson
(unmaintained)
sane-epson
Perfection 1640SU SCSI USB 0x04b8/0x010a Complete overseas version of the GT-8700 epson2
(1.0.124)
sane-epson2
Perfection 1640SU PHOTO SCSI USB 0x04b8/0x010a Good overseas version of the GT-8700F epson2
(1.0.124)
sane-epson2
Perfection 1650 USB 0x04b8/0x0110 Complete overseas version of the GT-8200U epson2
(1.0.124)
sane-epson2
Perfection 1650 USB 0x04b8/0x0110 Complete   epson
(unmaintained)
sane-epson
Perfection 1650 PHOTO USB 0x04b8/0x0110 Good overseas version of the GT-8200UF epson2
(1.0.124)
sane-epson2
Perfection 1660 USB 0x04b8/0x011e Complete   epson
(unmaintained)
sane-epson
Perfection 1660 PHOTO USB 0x04b8/0x011e Complete overseas version of the GT-8300UF epson2
(1.0.124)
sane-epson2
Perfection 1670 USB 0x04b8/0x011f Good   SnapScan
(1.4)
sane-snapscan
Perfection 1670 PHOTO USB 0x04b8/0x011f Unsupported supported by the snapscan backend
overseas version of the GT-8400UF
epson2
(1.0.124)
sane-epson2
Perfection 2400 USB 0x04b8/0x011b Complete   epson
(unmaintained)
sane-epson
Perfection 2400 PHOTO USB 0x04b8/0x011b Complete overseas version of the GT-9300UF epson2
(1.0.124)
sane-epson2
Perfection 2450 USB IEEE-1394 0x04b8/0x0112 Complete   epson
(unmaintained)
sane-epson
Perfection 2450 PHOTO USB IEEE-1394 0x04b8/0x0112 Complete overseas version of the GT-9700F epson2
(1.0.124)
sane-epson2
Perfection 2480 USB 0x04b8/0x0121 Good   SnapScan
(1.4)
sane-snapscan
Perfection 2480 PHOTO USB 0x04b8/0x0121 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 2580 USB 0x04b8/0x0121 Basic Film scanning unit unsupported SnapScan
(1.4)
sane-snapscan
Perfection 2580 PHOTO USB 0x04b8/0x0121 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 3170 PHOTO USB 0x04b8/0x0116 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 3200 USB IEEE-1394 0x04b8/0x011c Complete US version of the GT-9800 epson
(unmaintained)
sane-epson
Perfection 3200 PHOTO USB IEEE-1394 0x04b8/0x011c Complete overseas version of the GT-9800F epson2
(1.0.124)
sane-epson2
Perfection 3490 USB 0x04b8/0x0122 Good   SnapScan
(1.4)
sane-snapscan
Perfection 3490 PHOTO USB 0x04b8/0x0122 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 3590 USB 0x04b8/0x0122 Basic Film scanning unit unsupported SnapScan
(1.4)
sane-snapscan
Perfection 3590 PHOTO USB 0x04b8/0x0122 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 4180 PHOTO USB 0x04b8/0x0118 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 4490 PHOTO USB 0x04b8/0x0119 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection 4870 USB 0x04b8/0x0128 Complete US version of the GT-X700 epson
(unmaintained)
sane-epson
Perfection 4870 PHOTO USB 0x04b8/0x0128 Complete IEEE1394 untested
overseas version of the GT-X700
epson2
(1.0.124)
sane-epson2
Perfection 4990 USB 0x04b8/0x012a Complete US version of the GT-X800 epson
(unmaintained)
sane-epson
Perfection 4990 PHOTO USB 0x04b8/0x012a Good film area guide mode not supported
IEEE1394 untested
overseas version of the GT-X800
epson2
(1.0.124)
sane-epson2
Perfection 4990 Pro USB IEEE1394   Untested seems to be a 4990 PHOTO with additional software epson2
(1.0.124)
sane-epson2
Perfection V10 USB 0x04b8/0x012d Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection V30 USB 0x04b8/0x0131 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection V100 Photo USB 0x04b8/0x012d Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection V200 Photo USB 0x04b8/0x012e Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection V300 Photo USB 0x04b8/0x0131 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection V350 Photo USB 0x04b8/0x012f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection V500 Photo USB 0x04b8/0x0130 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection V600 Photo USB 0x04b8/0x013a Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Perfection V700 Photo USB 0x04b8/0x012c Good IEEE1394 untested
overseas version of the GT-X900
epson2
(1.0.124)
sane-epson2
Perfection V750 Photo USB 0x04b8/0x012c Good IEEE1394 untested
overseas version of the GT-X900
epson2
(1.0.124)
sane-epson2
PM-A700 USB 0x04b8/0x0814 Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A750 USB 0x04b8/0x081a Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A820 USB 0x04b8/0x0827 Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A840 USB 0x04b8/0x083c Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A840S USB 0x04b8/0x083c Good network interface probably supported
all-in-one
epson2
(1.0.124)
sane-epson2
PM-A850 USB 0x04b8/0x0806 Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A870 USB 0x04b8/0x0811 Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A890 USB 0x04b8/0x081c Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A900 USB 0x04b8/0x0810 Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A920 USB 0x04b8/0x082a Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A940 USB 0x04b8/0x0837 Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A950 USB 0x04b8/0x081d Good all-in-one epson2
(1.0.124)
sane-epson2
PM-A970 USB 0x04b8/0x0828 Good all-in-one epson2
(1.0.124)
sane-epson2
PM-T960 USB 0x04b8/0x0836 Good all-in-one epson2
(1.0.124)
sane-epson2
PM-T990 USB 0x04b8/0x0829 Good all-in-one
PM-A970 with network interface
epson2
(1.0.124)
sane-epson2
PX-401A USB 0x04b8/0x0841 Good all-in-one epson2
(1.0.124)
sane-epson2
PX-402A USB 0x04b8/0x084d Good all-in-one epson2
(1.0.124)
sane-epson2
PX-501A USB 0x04b8/0x084a Good network interface probably supported
all-in-one
epson2
(1.0.124)
sane-epson2
PX-502A USB 0x04b8/0x0856 Good all-in-one epson2
(1.0.124)
sane-epson2
PX-601F USB 0x04b8/0x0847 Good network interface probably supported epson2
(1.0.124)
sane-epson2
PX-A550 USB 0x04b8/0x080e Good all-in-one epson2
(1.0.124)
sane-epson2
PX-A620 USB 0x04b8/0x082f Good all-in-one epson2
(1.0.124)
sane-epson2
PX-A640 USB 0x04b8/0x0838 Good all-in-one epson2
(1.0.124)
sane-epson2
PX-A650 USB 0x04b8/0x0819 Good all-in-one epson2
(1.0.124)
sane-epson2
PX-A720 USB 0x04b8/0x082e Good all-in-one epson2
(1.0.124)
sane-epson2
PX-A740 USB 0x04b8/0x0839 Good all-in-one epson2
(1.0.124)
sane-epson2
PX-FA700 USB 0x04b8/0x083a Good all-in-one epson2
(1.0.124)
sane-epson2
RX-425 USB 0x04b8/0x080f Good   epson
(unmaintained)
sane-epson
RX-500 USB 0x04b8/0x0807 Good   epson
(unmaintained)
sane-epson
RX-600 USB 0x04b8/0x0806 Good   epson
(unmaintained)
sane-epson
RX-620 USB 0x04b8/0x0811 Good   epson
(unmaintained)
sane-epson
RX-700 USB 0x04b8/0x0810 Good   epson
(unmaintained)
sane-epson
Stylus CX-1500 USB 0x04b8/0x080c Good   SnapScan
(1.4)
sane-snapscan
Stylus CX-5800 USB   Unsupported Probably unsupported at the moment. Not compatible to snapscan backend. It's not known if it may work with epson or epkowa backend. unsupported
(2010-06-09)
?
Stylus CX1500 USB 0x04b8/0x080c Unsupported supported by the snapscan backend
all-in-one
epson2
(1.0.124)
sane-epson2
Stylus CX2800 USB 0x04b8/0x0830 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX2900 USB 0x04b8/0x0830 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX3100 USB 0x04b8/0x0802 Good all-in-one
overseas version of the CC-570L
epson2
(1.0.124)
sane-epson2
Stylus CX3200 USB 0x04b8/0x0802 Good all-in-one
overseas version of the CC-570L
epson2
(1.0.124)
sane-epson2
Stylus CX3500 USB 0x04b8/0x080e Good all-in-one
overseas version of the PX-A550
epson2
(1.0.124)
sane-epson2
Stylus CX3600 USB 0x04b8/0x080e Good all-in-one
overseas version of the PX-A550
epson2
(1.0.124)
sane-epson2
Stylus CX3650 USB 0x04b8/0x080e Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX3700 USB 0x04b8/0x0818 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX3800 USB 0x04b8/0x0818 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX3810 USB   Untested all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX3900 USB 0x04b8/0x082f Good all-in-one
overseas version of the PX-A620
epson2
(1.0.124)
sane-epson2
Stylus CX4100 USB 0x04b8/0x0820 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX4200 USB 0x04b8/0x0820 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX4300 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus CX4400 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus CX4500 USB 0x04b8/0x080d Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX4600 USB 0x04b8/0x080d Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX4700 USB 0x04b8/0x0819 Good all-in-one
overseas version of the PX-A650
epson2
(1.0.124)
sane-epson2
Stylus CX4800 USB 0x04b8/0x0819 Good all-in-one
overseas version of the PX-A650
epson2
(1.0.124)
sane-epson2
Stylus CX4900 USB 0x04b8/0x082b Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX5000 USB 0x04b8/0x082b Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX5100 USB 0x04b8/0x0801 Good all-in-one
overseas version of the CC-600PX
epson2
(1.0.124)
sane-epson2
Stylus CX5200 USB 0x04b8/0x0801 Good all-in-one
overseas version of the CC-600PX
epson2
(1.0.124)
sane-epson2
Stylus CX5300 USB 0x04b8/0x0808 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX5400 USB 0x04b8/0x0808 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX5500 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus CX5600 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus CX5700F USB 0x04b8/0x0821 Unsupported may work with the snapscan backend
all-in-one with FAX
epson2
(1.0.124)
sane-epson2
Stylus CX5800F USB 0x04b8/0x0821 Unsupported may work with the snapscan backend
all-in-one with FAX
epson2
(1.0.124)
sane-epson2
Stylus CX5900 USB 0x04b8/0x082e Good all-in-one
overseas version of the PX-A720
epson2
(1.0.124)
sane-epson2
Stylus CX6000 USB 0x04b8/0x082e Good all-in-one
overseas version of the PX-A720
epson2
(1.0.124)
sane-epson2
Stylus CX6300 USB 0x04b8/0x0805 Good all-in-one
mistakenly thinks its a PX-A650
epson2
(1.0.124)
sane-epson2
Stylus CX6400 USB 0x04b8/0x0805 Good all-in-one
mistakenly thinks its a PX-A650
epson2
(1.0.124)
sane-epson2
Stylus CX6500 USB 0x04b8/0x0813 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX6600 USB 0x04b8/0x0813 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX6900F USB 0x04b8/0x0831 Unsupported may work with the snapscan backend
all-in-one with FAX
epson2
(1.0.124)
sane-epson2
Stylus CX7000F USB 0x04b8/0x0831 Unsupported may work with the snapscan backend
all-in-one with FAX
epson2
(1.0.124)
sane-epson2
Stylus CX7300 USB 0x04b8/0x0838 Good all-in-one
overseas version of the PX-A640
epson2
(1.0.124)
sane-epson2
Stylus CX7400 USB 0x04b8/0x0838 Good all-in-one
overseas version of the PX-A640
epson2
(1.0.124)
sane-epson2
Stylus CX7700 USB 0x04b8/0x081f Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX7800 USB 0x04b8/0x081f Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus CX8300 USB 0x04b8/0x0839 Good all-in-one
overseas version of the PX-A740
epson2
(1.0.124)
sane-epson2
Stylus CX8400 USB 0x04b8/0x0839 Good all-in-one
overseas version of the PX-A740
epson2
(1.0.124)
sane-epson2
Stylus CX9300F USB 0x04b8/0x083a Good all-in-one
overseas version of the PX-FA700
epson2
(1.0.124)
sane-epson2
Stylus CX9400Fax USB 0x04b8/0x083a Good all-in-one
overseas version of the PX-FA700
epson2
(1.0.124)
sane-epson2
Stylus DX3800 USB 0x04b8/0x0818 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus DX3850 USB   Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus DX4000 USB 0x04b8/0x082f Good all-in-one
overseas version of the PX-A620
epson2
(1.0.124)
sane-epson2
Stylus DX4200 USB 0x04b8/0x0820 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus DX4400 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus DX4450 USB 0x04b8/0x083f Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
Stylus DX4800 USB 0x04b8/0x0819 Good all-in-one
overseas version of the PX-A650
epson2
(1.0.124)
sane-epson2
Stylus DX4850 USB 0x04b8/0x0819 Good all-in-one
DX4800 + card reader
epson2
(1.0.124)
sane-epson2
Stylus DX5000 USB 0x04b8/0x082b Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus DX6000 USB 0x04b8/0x082e Good all-in-one
overseas version of the PX-A720
epson2
(1.0.124)
sane-epson2
Stylus DX7000F USB 0x04b8/0x0831 Unsupported may work with the snapscan backend
all-in-one with FAX
epson2
(1.0.124)
sane-epson2
Stylus DX7400 USB 0x04b8/0x0838 Good all-in-one
overseas version of the PX-A640
epson2
(1.0.124)
sane-epson2
Stylus DX8400 USB 0x04b8/0x0839 Good all-in-one
overseas version of the PX-A740
epson2
(1.0.124)
sane-epson2
Stylus DX9400F USB 0x04b8/0x083a Good all-in-one
overseas version of the PX-FA700
epson2
(1.0.124)
sane-epson2
Stylus NX100 USB 0x04b8/0x0841 Good all-in-one
overseas version of the PX-401A
epson2
(1.0.124)
sane-epson2
Stylus NX110 Series USB 0x04b8/0x084d Good all-in-one
overseas version of the PX-402A
epson2
(1.0.124)
sane-epson2
Stylus NX200 USB 0x04b8/0x0849 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus NX210 Series USB 0x04b8/0x084f Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus NX300 USB 0x04b8/0x0848 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus NX400 USB 0x04b8/0x084a Good network interface probably supported
all-in-one
overseas version of the PX-501A
epson2
(1.0.124)
sane-epson2
Stylus NX410 Series USB 0x04b8/0x0851 Good network interface probably supported
all-in-one
epson2
(1.0.124)
sane-epson2
Stylus NX510 Series USB 0x04b8/0x0856 Good all-in-one
overseas version of the PX-502A
epson2
(1.0.124)
sane-epson2
Stylus Office BX300F USB 0x04b8/0x0848 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Office BX310FN Series USB 0x04b8/0x0854 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Office BX600FW USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
epson2
(1.0.124)
sane-epson2
Stylus Office BX610FW Series USB 0x04b8/0x0855 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus Office TX300F USB 0x04b8/0x0848 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Office TX510FN Series USB 0x04b8/0x0854 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Office TX600FW USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
epson2
(1.0.124)
sane-epson2
Stylus Office TX610FW Series USB 0x04b8/0x0855 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus Photo PX650 Series USB 0x04b8/0x0850 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus Photo PX700W USB Network 0x04b8/0x0846 Good network interface supported
all-in-one
overseas version of the EP-801A
epson2
(1.0.124)
sane-epson2
Stylus Photo PX710W Series USB 0x04b8/0x0852 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus Photo PX800FW USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
overseas version of the EP-901A
epson2
(1.0.124)
sane-epson2
Stylus Photo PX810FW Series USB 0x04b8/0x0853 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus Photo RX420 USB 0x04b8/0x080f Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Photo RX425 USB 0x04b8/0x080f Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Photo RX430 USB 0x04b8/0x080f Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Photo RX500 USB 0x04b8/0x0807 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Photo RX510 USB 0x04b8/0x0807 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus Photo RX520 USB 0x04b8/0x081a Good all-in-one
overseas version of the PM-A750
epson2
(1.0.124)
sane-epson2
Stylus Photo RX530 USB 0x04b8/0x081a Good all-in-one
overseas version of the PM-A750
epson2
(1.0.124)
sane-epson2
Stylus Photo RX560 USB 0x04b8/0x0827 Good all-in-one
overseas version of the PM-A820
epson2
(1.0.124)
sane-epson2
Stylus Photo RX580 USB 0x04b8/0x0827 Good all-in-one
overseas version of the PM-A820
epson2
(1.0.124)
sane-epson2
Stylus Photo RX585 USB 0x04b8/0x083c Good all-in-one
overseas version of the PM-A840
epson2
(1.0.124)
sane-epson2
Stylus Photo RX590 USB 0x04b8/0x0827 Good all-in-one
overseas version of the PM-A820
epson2
(1.0.124)
sane-epson2
Stylus Photo RX595 USB 0x04b8/0x083c Good all-in-one
overseas version of the PM-A840
epson2
(1.0.124)
sane-epson2
Stylus Photo RX600 USB 0x04b8/0x0806 Good all-in-one
overseas version of the PM-A850
epson2
(1.0.124)
sane-epson2
Stylus Photo RX610 USB 0x04b8/0x083c Good all-in-one
overseas version of the PM-A840
epson2
(1.0.124)
sane-epson2
Stylus Photo RX620 USB 0x04b8/0x0811 Good all-in-one
overseas version of the PM-A870
epson2
(1.0.124)
sane-epson2
Stylus Photo RX630 USB 0x04b8/0x0811 Good all-in-one
overseas version of the PM-A870
epson2
(1.0.124)
sane-epson2
Stylus Photo RX640 USB 0x04b8/0x081c Good all-in-one
overseas version of the PM-A890
epson2
(1.0.124)
sane-epson2
Stylus Photo RX650 USB 0x04b8/0x081c Good all-in-one
overseas version of the PM-A890
epson2
(1.0.124)
sane-epson2
Stylus Photo RX680 USB 0x04b8/0x0837 Good all-in-one
overseas version of the PM-A940
epson2
(1.0.124)
sane-epson2
Stylus Photo RX685 USB 0x04b8/0x0837 Good all-in-one
overseas version of the PM-A940
epson2
(1.0.124)
sane-epson2
Stylus Photo RX690 USB 0x04b8/0x0837 Good all-in-one
overseas version of the PM-A940
epson2
(1.0.124)
sane-epson2
Stylus Photo RX700 USB 0x04b8/0x0810 Good all-in-one
overseas version of the PM-A900
epson2
(1.0.124)
sane-epson2
Stylus Photo TX650 Series USB 0x04b8/0x0850 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus Photo TX700W USB 0x04b8/0x0846 Good network interface probably supported
all-in-one
overseas version of the EP-801A
epson2
(1.0.124)
sane-epson2
Stylus Photo TX710W Series USB 0x04b8/0x0852 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus Photo TX800FW USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
overseas version of the EP-901A
epson2
(1.0.124)
sane-epson2
Stylus Scan 2000 USB 0x04b8/0x0105 Untested apparently mostly the same as the Stylus Scan 2500 epson2
(1.0.124)
sane-epson2
Stylus Scan 2500 USB 0x04b8/0x0106 Untested scanner is apparently a GT-7000 epson2
(1.0.124)
sane-epson2
Stylus SX100 USB 0x04b8/0x0841 Good all-in-one
overseas version of the PX-401A
epson2
(1.0.124)
sane-epson2
Stylus SX110 Series USB 0x04b8/0x084d Good all-in-one
overseas version of the PX-402A
epson2
(1.0.124)
sane-epson2
Stylus SX125 USB 0x04b8/0x085c Untested all-in-one epson2
(1.0.124)
sane-epson2
Stylus SX200 USB 0x04b8/0x0849 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus SX205 USB 0x04b8/0x0849 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus SX210 Series USB 0x04b8/0x084f Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus SX400 USB 0x04b8/0x084a Good network interface probably supported
all-in-one
overseas version of the PX-501A
epson2
(1.0.124)
sane-epson2
Stylus SX405 USB 0x04b8/0x084a Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus SX410 Series USB 0x04b8/0x0851 Good network interface probably supported
all-in-one
epson2
(1.0.124)
sane-epson2
Stylus SX510W Series USB 0x04b8/0x0856 Good all-in-one
overseas version of the PX-502A
epson2
(1.0.124)
sane-epson2
Stylus SX600FW USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
epson2
(1.0.124)
sane-epson2
Stylus SX610FW Series USB 0x04b8/0x0855 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2
Stylus TX100 USB 0x04b8/0x0841 Good all-in-one
overseas version of the PX-401A
epson2
(1.0.124)
sane-epson2
Stylus TX110 Series USB 0x04b8/0x084d Good all-in-one
overseas version of the PX-402A
epson2
(1.0.124)
sane-epson2
Stylus TX200 USB 0x04b8/0x0849 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus TX203 USB 0x04b8/0x0849 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus TX209 USB 0x04b8/0x0849 Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus TX210 Series USB 0x04b8/0x084f Good all-in-one epson2
(1.0.124)
sane-epson2
Stylus TX400 USB 0x04b8/0x084a Good network interface probably supported
all-in-one
overseas version of the PX-501A
epson2
(1.0.124)
sane-epson2
Stylus TX410 Series USB 0x04b8/0x0851 Good network interface probably supported
all-in-one
epson2
(1.0.124)
sane-epson2
Stylus TX550W Series USB 0x04b8/0x0856 Good all-in-one
overseas version of the PX-502A
epson2
(1.0.124)
sane-epson2
StylusScan 2000 USB 0x04b8/0x0105 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
V700 USB IEEE-1394 0x04b8/0x012c Good   epson
(unmaintained)
sane-epson
V750 USB IEEE-1394 0x04b8/0x012c Good   epson
(unmaintained)
sane-epson
WorkForce 310 Series USB 0x04b8/0x0854 Good all-in-one epson2
(1.0.124)
sane-epson2
WorkForce 500 USB 0x04b8/0x084c Good all-in-one epson2
(1.0.124)
sane-epson2
WorkForce 600 USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
epson2
(1.0.124)
sane-epson2
WorkForce 610 Series USB 0x04b8/0x0855 Unsupported supported by the epkowa backend plus non-free interpreter epson2
(1.0.124)
sane-epson2

Manufacturer: Escom

Model Interface USB id Status Comment Backend Manpage
Image Scanner 256 SCSI   Good OK, SCSI-ID=UMAX UG 80 umax
(1.0-41)
sane-umax

Manufacturer: Escort

Model Interface USB id Status Comment Backend Manpage
Galleria 600 SCSI   Untested untested, SCSI-ID=ESCORT Galleria 600S umax
(1.0-41)
sane-umax

Manufacturer: Fujitsu

Link(s): http://www.fujitsu.com, http://www.fujitsu.com/, http://www.fcpa.fujitsu.com/products/scanners/

Model Interface USB id Status Comment Backend Manpage
1200CUS USB 0x05d8/0x4002 Basic Works, but is slow. Probably a Mustek BearPaw 2400 CU clone. gt68xx
(1.0-84)
sane-gt68xx
fi-60F USB 0x04c5/0x10c7 Basic A6-size flatbed, 300/600 dpi, color/gray/binary epjitsu
(20)
sane-epjitsu
fi-4010CU USB 0x04c5/0x1029 Untested   avision
(Build: 296)
sane-avision
fi-4110EOX/2/3 USB 0x04c5/0x1040 Unsupported Uses ma1509 chip, but very different from other scanners supported by the ma1509 backend ma1509
(1.0-3)
sane-ma1509
fi-4120C SCSI USB 0x04c5/0x1041 Complete small, recent, discontinued, usb 1.1 fujitsu
(117)
sane-fujitsu
fi-4120C2 SCSI USB 0x04c5/0x10ae Complete small, recent, discontinued, usb 2.0 fujitsu
(117)
sane-fujitsu
fi-4220C SCSI USB 0x04c5/0x1042 Complete small, recent, discontinued, usb 1.1 fujitsu
(117)
sane-fujitsu
fi-4220C2 SCSI USB 0x04c5/0x10af Complete small, recent, discontinued, usb 2.0 fujitsu
(117)
sane-fujitsu
fi-4340C SCSI USB 0x04c5/0x10cf Complete medium, current fujitsu
(117)
sane-fujitsu
fi-4530C SCSI USB 0x04c5/0x1078 Complete medium, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-4640S SCSI   Complete medium, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-4750C SCSI   Complete medium, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-4750L SCSI   Complete big, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-4860C SCSI   Complete big, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-4860C2 SCSI   Complete big, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-4990C SCSI   Complete big, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5000N Ethernet   Untested Not a scanner, rather a scanner to ethernet interface fujitsu
(117)
sane-fujitsu
fi-5015C USB 0x04c5/0x10ef Good   avision
(Build: 296)
sane-avision
fi-5110C USB 0x04c5/0x1097 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5110EOX/2 USB 0x04c5/0x1096 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5110EOX3 USB 0x04c5/0x10e6 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5110EOXM USB 0x04c5/0x10f2 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5120C SCSI USB 0x04c5/0x10e0 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5220C SCSI USB 0x04c5/0x10e1 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5530C SCSI USB 0x04c5/0x10e2 Complete medium, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5530C2 SCSI USB 0x04c5/0x114a Complete medium, current fujitsu
(117)
sane-fujitsu
fi-5650C SCSI USB 0x04c5/0x10ad Complete big, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5750C SCSI USB 0x04c5/0x1095 Complete big, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-5900C SCSI USB 0x04c5/0x10e7 Good big, recent, discontinued. Independent ultrasonic control and multistream unsupported fujitsu
(117)
sane-fujitsu
fi-5950 SCSI USB 0x04c5/0x1213 Untested big, current. Faster version of fi-5900? fujitsu
(117)
sane-fujitsu
fi-6000NS Ethernet   Untested small, recent, discontinued, integrated touchscreen and keyboard fujitsu
(117)
sane-fujitsu
fi-6110 USB 0x04c5/0x11fc Complete small, current fujitsu
(117)
sane-fujitsu
fi-6130 USB 0x04c5/0x114f Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-6130Z USB 0x04c5/0x11f3 Complete small, current fujitsu
(117)
sane-fujitsu
fi-6140 SCSI USB 0x04c5/0x114d Complete medium, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-6140Z SCSI USB 0x04c5/0x11f1 Complete medium, current fujitsu
(117)
sane-fujitsu
fi-6230 USB 0x04c5/0x1150 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-6230Z USB 0x04c5/0x11f4 Complete small, current fujitsu
(117)
sane-fujitsu
fi-6240 SCSI USB 0x04c5/0x114e Complete medium, recent, discontinued fujitsu
(117)
sane-fujitsu
fi-6240Z SCSI USB 0x04c5/0x11f2 Complete medium, current fujitsu
(117)
sane-fujitsu
fi-6670 SCSI USB 0x04c5/0x1176 Good big, current, won't wakeup via software fujitsu
(117)
sane-fujitsu
fi-6670A SCSI USB 0x04c5/0x1177 Good big, current, VRS CGA board unsupported, won't wakeup via software fujitsu
(117)
sane-fujitsu
fi-6750S USB 0x04c5/0x1178 Untested Simplex, USB only version of fi-6770, won't wakeup via software, discontinued fujitsu
(117)
sane-fujitsu
fi-6770 SCSI USB 0x04c5/0x1174 Good big, current, won't wakeup via software fujitsu
(117)
sane-fujitsu
fi-6770A SCSI USB 0x04c5/0x1175 Good big, current, VRS CGA board unsupported, won't wakeup via software fujitsu
(117)
sane-fujitsu
fi-6800 SCSI USB 0x04c5/0x119d Untested big, current. Independent ultrasonic control and multistream unsupported fujitsu
(117)
sane-fujitsu
fi-6800-CGA SCSI USB 0x04c5/0x119e Untested big, current. VRS CGA board unsupported, Independent ultrasonic control and multistream unsupported fujitsu
(117)
sane-fujitsu
M3091DC SCSI   Complete small, old, discontinued fujitsu
(117)
sane-fujitsu
M3092DC SCSI   Complete small, old, discontinued fujitsu
(117)
sane-fujitsu
M3093DE RS232C/Video   Unsupported medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3093DG SCSI   Complete medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3093E RS232C/Video   Unsupported medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3093EX RS232C/Video   Unsupported medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3093GX SCSI   Complete medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3096EX RS232C/Video   Unsupported medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3096GX SCSI   Complete medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3097DE RS232C/Video   Unsupported medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3097DG SCSI   Complete medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3097E+ RS232C/Video   Unsupported medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3097G+ SCSI   Complete medium, old, discontinued fujitsu
(117)
sane-fujitsu
M3099A RS232C/Video   Unsupported big, old, discontinued fujitsu
(117)
sane-fujitsu
M3099EH RS232C/Video   Unsupported big, old, discontinued fujitsu
(117)
sane-fujitsu
M3099EX RS232C/Video   Unsupported big, old, discontinued fujitsu
(117)
sane-fujitsu
M3099G SCSI   Complete big, old, discontinued fujitsu
(117)
sane-fujitsu
M3099GH SCSI   Complete big, old, discontinued fujitsu
(117)
sane-fujitsu
M3099GX SCSI   Complete big, old, discontinued fujitsu
(117)
sane-fujitsu
M4097D SCSI   Complete big, old, discontinued fujitsu
(117)
sane-fujitsu
M4099D SCSI   Complete big, old, discontinued fujitsu
(117)
sane-fujitsu
ScanPartner SCSI   Untested   avision
(Build: 296)
sane-avision
ScanPartner 10 SCSI   Untested   avision
(Build: 296)
sane-avision
ScanPartner 10C SCSI   Untested   avision
(Build: 296)
sane-avision
ScanPartner 15C SCSI   Good   sp15c
(unmaintained)
sane-sp15c
ScanPartner 300C SCSI   Untested   avision
(Build: 296)
sane-avision
ScanPartner 600C SCSI   Good   sp15c
(unmaintained)
sane-sp15c
ScanPartner 620C SCSI   Good   avision
(Build: 296)
sane-avision
ScanPartner Jr SCSI   Untested   avision
(Build: 296)
sane-avision
ScanSnap fi-6010N Ethernet   Untested small, current, integrated touchscreen and keyboard fujitsu
(117)
sane-fujitsu
ScanSnap iX500 USB WiFi 0x04c5/0x132b Good small, current, WiFi not supported. Hardware only scans in color. Backend generates binary and grayscale modes. fujitsu
(117)
sane-fujitsu
ScanSnap N1800 Ethernet   Untested small, current, integrated touchscreen and keyboard fujitsu
(117)
sane-fujitsu
ScanSnap S300 USB 0x04c5/0x1156 Good Duplex, 150/225/300/600 dpi, color/gray/binary, AC/USB power, buttons/sensors all supported. Scanner always scans in _triplex_ color, fast USB required. epjitsu
(20)
sane-epjitsu
ScanSnap S300M USB 0x04c5/0x117f Good Same as S300, with different usb id epjitsu
(20)
sane-epjitsu
ScanSnap S500 USB 0x04c5/0x10fe Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
ScanSnap S500M USB 0x04c5/0x1135 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
ScanSnap S510 USB 0x04c5/0x1155 Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
ScanSnap S510M USB 0x04c5/0x116f Complete small, recent, discontinued fujitsu
(117)
sane-fujitsu
ScanSnap S1100 USB 0x04c5/0x1200 Unsupported Beta version of backend source available, which works well, but breaks support for other epjitsu scanners. See http://ubuntuforums.org/showthread.php?t=1678335 epjitsu
(20)
sane-epjitsu
ScanSnap S1300 USB 0x04c5/0x11ed Good Same as S300, with different usb id epjitsu
(20)
sane-epjitsu
ScanSnap S1500 USB 0x04c5/0x11a2 Complete small, discontinued fujitsu
(117)
sane-fujitsu
ScanSnap S1500M USB 0x04c5/0x11a2 Complete small, discontinued, same as S1500 fujitsu
(117)
sane-fujitsu
ScanStation SCSI   Untested   avision
(Build: 296)
sane-avision

Manufacturer: Gallery

Model Interface USB id Status Comment Backend Manpage
4800 Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp

Manufacturer: Genius

Link(s): http://www.genius-kye.com/, http://www.geniusmouse.co.uk/, http://www.geniusnet.com.tw/

Model Interface USB id Status Comment Backend Manpage
ColorPage CS SCSI   Unsupported Probably unsupported, see link for details. unsupported
(2010-06-09)
?
ColorPage HR6 V1 USB 0x0458/0x2004 Basic   u12
(0.02)
sane-u12
Colorpage HR6 V2 USB 0x0458/0x2008 Complete   plustek
(0.52)
sane-plustek
Colorpage HR6 V2 USB 0x0458/0x2007 Complete   plustek
(0.52)
sane-plustek
Colorpage HR6A USB 0x0458/0x2009 Untested   plustek
(0.52)
sane-plustek
Colorpage HR6X USB 0x0458/0x2016 Untested   plustek
(0.52)
sane-plustek
Colorpage HR6X EPP Parport (SPP, EPP)   Good Negative scanning does not work correctly plustek_pp
(0.43)
sane-plustek_pp
ColorPage HR6X Slim USB 0x0458/0x2019 Unsupported GL646 based, to be added to genesys backend unsupported
(2010-06-09)
?
Colorpage HR7 USB 0x0458/0x2013 Complete   plustek
(0.52)
sane-plustek
Colorpage HR7LE USB 0x0458/0x2015 Untested   plustek
(0.52)
sane-plustek
ColorPage HR7X USB 0x0458/0x2018 Unsupported GL646 based, to be added to genesys backend unsupported
(2010-06-09)
?
ColorPage HR7XE USB 0x06dc/0x0012 Unsupported Unsuported. See link for details. unsupported
(2010-06-09)
?
ColorPage HR8 USB 0x0458/0x201c Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
Colorpage SF600 USB 0x0458/0x2021 Basic   gt68xx
(1.0-84)
sane-gt68xx
ColorPage Slim 1200 USB 0x0458/0x201e Untested Untested but should work. gt68xx
(1.0-84)
sane-gt68xx
Colorpage Vivid 1200 X USB 0x0458/0x201d Good   gt68xx
(1.0-84)
sane-gt68xx
Colorpage Vivid 1200 XE USB 0x0458/0x201f Good   gt68xx
(1.0-84)
sane-gt68xx
ColorPage Vivid III USB USB 0x07b3/0x0001 Untested Note: Device has Plustek vendor and product ID (0x07b3/0x0001) u12
(0.02)
sane-u12
Colorpage Vivid III V2 Parport (SPP, EPP)   Complete Reported as PT12 plustek_pp
(0.43)
sane-plustek_pp
Colorpage Vivid Pro II Film Parport (SPP, EPP)   Complete Reported as OP9636T/12000T plustek_pp
(0.43)
sane-plustek_pp
Colorpage Vivid3 V2 USB 0x0458/0x2011 Good Same as Colorpage Vivid3x gt68xx
(1.0-84)
sane-gt68xx
Colorpage Vivid3x USB 0x0458/0x2011 Good   gt68xx
(1.0-84)
sane-gt68xx
Colorpage Vivid3xe USB 0x0458/0x2017 Good   gt68xx
(1.0-84)
sane-gt68xx
Colorpage Vivid4 USB 0x0458/0x2014 Good   gt68xx
(1.0-84)
sane-gt68xx
Colorpage Vivid4x USB 0x0458/0x201b Good   gt68xx
(1.0-84)
sane-gt68xx
Colorpage Vivid4xe USB 0x0458/0x201a Good   gt68xx
(1.0-84)
sane-gt68xx
ColorPage-EP Parport   Good   microtek2
(unmaintained)
sane-microtek2
ColorPage-HR5 (Pro) SCSI   Good OK, SCSI-ID=KYE ColorPage-HR5 umax
(1.0-41)
sane-umax
ColorPage-Life Pro Parport (EPP/ECP)   Good works (relabelled 1220P and 2000P) umax_pp
(1)
sane-umax_pp
ColorPage-Slim 1200 USB2 USB 0x0458/0x2020 Unsupported GL841 based, to be added to genesys backend. unsupported
(2010-06-09)
?
Colorpage-SP2 SCSI   Good Same as Microtek Scanmaker E3 microtek
(0.13.1)
sane-microtek
FS-1130 Colorpage Scanner SCSI   Good   leo
(1.0-10)
sane-leo

Manufacturer: Googlegear

Model Interface USB id Status Comment Backend Manpage
2000 USB 0x05d8/0x4002 Good Same as Artec Ultima 2000. gt68xx
(1.0-84)
sane-gt68xx

Manufacturer: Guillemot

Model Interface USB id Status Comment Backend Manpage
Maxi Scan A4 Parallel 36 bit Parport   Unsupported Probably unsupported. Identical to the Benq Prisa 620P. unsupported
(2010-06-09)
?
SCAN@HOME 48 USB USB 0x080d/0x0102 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Guillemot / Hercules

Link(s): http://www.guillemot.com

Model Interface USB id Status Comment Backend Manpage
Maxi A4 36 bit USB 0x04a5/0x2060 Good Rebadged Benq 620U, needs Benq firmware file u96v???.bin SnapScan
(1.4)
sane-snapscan
Maxi Scan A4 Deluxe (SCSI) SCSI   Good Rebadged SnapScan 310s. SnapScan
(1.4)
sane-snapscan
Maxi Scan A4 USB 640U USB 0x04a5/0x2060 Good Rebadged Benq 640U. SnapScan
(1.4)
sane-snapscan
Scan@home Touch 1248 (USB) USB 0x04a5/0x20de Good Rebadged Benq 3300. SnapScan
(1.4)
sane-snapscan

Manufacturer: Hercules

Model Interface USB id Status Comment Backend Manpage
SCAN@HOME 48 USB USB 0x080d/0x0102 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Hewlett-Packard

Link(s): http://www.hp.com, http://www.hp.com/

Model Interface USB id Status Comment Backend Manpage
LaserJet M1005 MFP USB 0x03f0/0x3b17 Good grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI hpljm1005
(0)
sane-hpljm1005
LaserJet M1120 MFP USB 0x03f0/0x5617 Good grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI hpljm1005
(0)
sane-hpljm1005
LaserJet M1120n MFP USB 0x03f0/0x5717 Good grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI hpljm1005
(0)
sane-hpljm1005
Photo Scanner 1000 USB 0x03f0/0x1001 Unsupported Not supported by SANE. However, it's detected as mass storage device so just mounting it is reported to work. See link for device data. unsupported
(2010-06-09)
?
Photosmart 1200 Photo USB   Unsupported Probably not supported by SANE. No details known. 10x15 cm. Maybe similar to Photo Scanner 1000? unsupported
(2010-06-09)
?
Photosmart C3180 USB 0x03f0/0x5611 Unsupported Not supported yet by SANE. See link for details. unsupported
(2010-06-09)
?
Photosmart C5100 series USB 0x03f0/0x5811 Unsupported Not supported yet by SANE. See link for details. unsupported
(2010-06-09)
?
PhotoSmart PhotoScanner SCSI   Complete   hp
(1.06)
sane-hp
Photosmart S20 (C5101A) USB 0x03f0/0x0102 Unsupported Not supported yet by SANE. See link for details. unsupported
(2010-06-09)
?
Photosmart S20xi (C7150A) USB 0x03f0/0x0102 Unsupported Not supported yet by SANE. See link for details. unsupported
(2010-06-09)
?
ScanJet 3c SCSI   Complete   hp
(1.06)
sane-hp
ScanJet 3p SCSI   Complete   hp
(1.06)
sane-hp
ScanJet 4c SCSI   Complete   hp
(1.06)
sane-hp
ScanJet 4p SCSI   Complete   hp
(1.06)
sane-hp
ScanJet 5p SCSI   Complete   hp
(1.06)
sane-hp
ScanJet 5s Parport (EPP)   Minimal Requires libieee1284 library. Only gray mode. hpsj5s
(0.03)
sane-hpsj5s
ScanJet 2100C USB 0x03f0/0x0505 Complete   plustek
(0.52)
sane-plustek
ScanJet 2200C USB 0x03f0/0x0605 Complete   plustek
(0.52)
sane-plustek
ScanJet 2300C USB 0x03f0/0x0901 Complete 600x1200 dpi max genesys
(1.0-63)
sane-genesys
ScanJet 2400C USB 0x03f0/0x0a01 Complete 1200x1200 dpi max genesys
(1.0-63)
sane-genesys
Scanjet 3200C Parport (EPP/ECP)   Good works (relabelled 1220P and 2000P) umax_pp
(1)
sane-umax_pp
ScanJet 3300c USB 0x03f0/0x0205 Complete   niash
(0.3)
sane-niash
ScanJet 3400c USB 0x03f0/0x0405 Complete If you use Linux 2.6, version 2.6.8 or newer is necessary. niash
(0.3)
sane-niash
ScanJet 3500C USB 0x03f0/0x2205 Good   hp3500
(1.1)
sane-hp3500
ScanJet 3530C USB 0x03f0/0x2005 Good   hp3500
(1.1)
sane-hp3500
ScanJet 3570C USB 0x03f0/0x2005 Good   hp3500
(1.1)
sane-hp3500
ScanJet 3670C USB 0x03f0/0x1405 Complete 1200x1200 dpi max, complete transparency adaptor support genesys
(1.0-63)
sane-genesys
ScanJet 3690C USB 0x03f0/0x1405 Complete 1200x1200 dpi max, same as HP 3670C genesys
(1.0-63)
sane-genesys
ScanJet 3770 USB 0x03f0/0x2505 Unsupported While an external binary-only backend exists, it works only on Linux i386. Therefore the scanner is unsupported on other platforms. unsupported
(2010-06-09)
?
ScanJet 3800 USB 0x03f0/0x2605 Basic Works with resolutions equal and less than 600dpi hp3900
(0.12)
sane-hp3900
ScanJet 3970c USB 0x03f0/0x2305 Good   hp3900
(0.12)
sane-hp3900
ScanJet 4070 Photosmart USB 0x03f0/0x2405 Good   hp3900
(0.12)
sane-hp3900
ScanJet 4100C USB 0x03f0/0x0101 Complete   hp
(1.06)
sane-hp
ScanJet 4200C USB 0x03f0/0x0105 Basic 8bpp color, 75/150/300/600 dpi only hp4200
(1.0-2)
sane-hp4200
ScanJet 4200Cse USB 0x03f0/0x0105 Basic 8bpp color, 75/150/300/600 dpi only hp4200
(1.0-2)
sane-hp4200
ScanJet 4200Cxi USB 0x03f0/0x0105 Basic 8bpp color, 75/150/300/600 dpi only hp4200
(1.0-2)
sane-hp4200
ScanJet 4300c USB 0x03f0/0x0305 Complete If you use Linux 2.6, version 2.6.8 or newer is necessary. niash
(0.3)
sane-niash
ScanJet 4300c/Silitek USB 0x047b/0x1002 Complete If you use Linux 2.6, version 2.6.8 or newer is necessary. niash
(0.3)
sane-niash
ScanJet 4370 USB 0x03f0/0x4105 Basic Works with resolutions lower than 1200dpi hp3900
(0.12)
sane-hp3900
scanjet 4400c USB 0x03f0/0x0705 Good exists with 2 different sensors of which only one works rts8891
(1.0-0)
sane-rts8891
scanjet 4470c USB 0x03f0/0x0805 Good re-branded Astra 4400 rts8891
(1.0-0)
sane-rts8891
ScanJet 4500C USB 0x03f0/0x1205 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives hp5590
(1.0.5)
sane-hp5590
ScanJet 4570C USB 0x03f0/0x1305 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives hp5590
(1.0.5)
sane-hp5590
ScanJet 4600 USB 0x03f0/0x3005 Unsupported Not supported. See link for details, or http://www.chmil.org/hp4600linux/ for code unsupported
(2010-06-09)
?
ScanJet 4670 USB 0x03f0/0x3005 Unsupported Not supported. See ScanJet 4600 entry. unsupported
(2010-06-09)
?
ScanJet 4850C USB 0x03f0/0x1b05 Untested resolution from 100 to 2400 supported, UTA not supported yet genesys
(1.0-63)
sane-genesys
ScanJet 4890C USB 0x03f0/0x1b05 Unsupported GL843, maybe can be added to genesys backend unsupported
(2010-06-09)
?
ScanJet 5100C Parport   Complete Requires ppscsi driver and epst module hp
(1.06)
sane-hp
ScanJet 5200C Parport USB 0x03f0/0x0401 Complete Parallel interface requires ppscsi driver and epst module hp
(1.06)
sane-hp
ScanJet 5300C USB 0x03f0/0x0701 Complete 1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi avision
(Build: 296)
sane-avision
ScanJet 5370C USB 0x03f0/0x0701 Good 1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi avision
(Build: 296)
sane-avision
ScanJet 5400c USB 0x03f0/0x1005 Basic   hp5400
(1.0-2)
sane-hp5400
ScanJet 5470c USB 0x03f0/0x1105 Basic   hp5400
(1.0-2)
sane-hp5400
ScanJet 5490c USB   Basic   hp5400
(1.0-2)
sane-hp5400
ScanJet 5500C USB 0x03f0/0x1305 Untested Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives hp5590
(1.0.5)
sane-hp5590
ScanJet 5530C Photosmart USB 0x03f0/0x1605 Unsupported Maybe GL841_HP, but not confirmed, maybe can be added to genesys backend unsupported
(2010-06-09)
?
ScanJet 5550C USB 0x03f0/0x1205 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives hp5590
(1.0.5)
sane-hp5590
ScanJet 5590 USB 0x03f0/0x1705 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives hp5590
(1.0.5)
sane-hp5590
ScanJet 6100C SCSI   Complete   hp
(1.06)
sane-hp
ScanJet 6200C SCSI USB 0x03f0/0x0201 Complete   hp
(1.06)
sane-hp
ScanJet 6250C SCSI USB 0x03f0/0x0201 Complete   hp
(1.06)
sane-hp
ScanJet 6300C SCSI USB 0x03f0/0x0601 Complete   hp
(1.06)
sane-hp
ScanJet 6350C SCSI USB 0x03f0/0x0601 Complete   hp
(1.06)
sane-hp
ScanJet 6390C SCSI USB 0x03f0/0x0601 Complete   hp
(1.06)
sane-hp
ScanJet 7400c USB 0x03f0/0x0801 Good 1 pass, 2400 dpi - dual USB/SCSI interface avision
(Build: 296)
sane-avision
ScanJet 7450c USB 0x03f0/0x0801 Good 1 pass, 2400 dpi - dual USB/SCSI interface avision
(Build: 296)
sane-avision
ScanJet 7490c USB 0x03f0/0x0801 Good 1 pass, 1200 dpi - dual USB/SCSI interface avision
(Build: 296)
sane-avision
ScanJet 7650 USB 0x03f0/0x1805 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives hp5590
(1.0.5)
sane-hp5590
ScanJet 8200 USB 0x03f0/0x0b01 Good 1 pass, 4800 (?) dpi - USB 2.0 avision
(Build: 296)
sane-avision
ScanJet 8250 USB 0x03f0/0x0b01 Good 1 pass, 4800 (?) dpi - USB 2.0 avision
(Build: 296)
sane-avision
ScanJet 8270 USB 0x03f0/0x3905 Good 1 pass, 4800 (?) dpi - USB 2.0 avision
(Build: 296)
sane-avision
ScanJet 8290 USB 0x03f0/0x0b01 Good 1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far avision
(Build: 296)
sane-avision
ScanJet 8300 USB 0x03f0/0x3805 Good 1 pass, 4800 (?) dpi - USB 2.0 avision
(Build: 296)
sane-avision
ScanJet 8350 USB 0x03f0/0x3805 Good 1 pass, 4800 (?) dpi - USB 2.0 avision
(Build: 296)
sane-avision
ScanJet 8390 USB 0x03f0/0x3805 Good 1 pass, 4800 (?) dpi - USB 2.0 avision
(Build: 296)
sane-avision
ScanJet G2410 USB 0x03f0/0x0a01 Basic clone of the HP 2400C genesys
(1.0-63)
sane-genesys
ScanJet G2710 USB 0x03f0/0x2805 Basic Similar to hp scanjet 3800 hp3900
(0.12)
sane-hp3900
ScanJet G3010 USB 0x03f0/0x4205 Basic Similar to hp scanjet 4370 hp3900
(0.12)
sane-hp3900
ScanJet G3110 USB 0x03f0/0x4305 Basic Similar to hp scanjet 4370 hp3900
(0.12)
sane-hp3900
ScanJet G4000 USB 0x03f0/0x4505 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
ScanJet G4010 USB 0x03f0/0x4505 Good resolution from 100 to 2400 supported, UTA not supported yet genesys
(1.0-63)
sane-genesys
ScanJet G4050 USB 0x03f0/0x4605 Good resolution from 100 to 2400 supported, UTA not supported yet genesys
(1.0-63)
sane-genesys
ScanJet IIc SCSI   Complete   hp
(1.06)
sane-hp
ScanJet IIcx SCSI   Complete   hp
(1.06)
sane-hp
ScanJet IIp SCSI   Complete   hp
(1.06)
sane-hp
ScanJet N6310 USB 0x03f0/0x4705 Untested Not supported yet genesys
(1.0-63)
sane-genesys
ScanJet Plus Propietary   Complete Driver for HP parallel interface card required hp
(1.06)
sane-hp

Manufacturer: IBM

Link(s): http://www.ibm.com/, http://www.ibm.com

Model Interface USB id Status Comment Backend Manpage
2456 SCSI   Basic Was reported to work long time ago. Reports are welcome. ibm
(1.0-4)
sane-ibm
ADF Color Scanner Proprietary   Unsupported Unsupported. Uses proprietary ISA card. Maybe the same as the Plustek Spectra ADF? unsupported
(2010-06-09)
?

Manufacturer: IOMagic

Link(s): http://www.iomagic.com/

Model Interface USB id Status Comment Backend Manpage
MobileScan USB USB Parport 0x05cb/0x1483 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Iris

Link(s): http://irislink.com/

Model Interface USB id Status Comment Backend Manpage
IriScan USB 0x0a53/0x1000 Unsupported Unsupported. LM9832/3. See link for details. unsupported
(2010-06-09)
?
IRISCard Pro (IBCR II) USB 0x0a38/0x0301 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
IRISPen Translator Executive USB 0x0f43/0x015a Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: iVina

Model Interface USB id Status Comment Backend Manpage
1200U USB 0x0638/0x0268 Untested   avision
(Build: 296)
sane-avision

Manufacturer: Kodak

Link(s): http://www.kodak.com, http://www.kodak.com/

Model Interface USB id Status Comment Backend Manpage
Color Scanner 3590C SCSI   Untested Please test! kodak
(7)
sane-kodak
Color Scanner 4500 SCSI   Untested Please test! kodak
(7)
sane-kodak
ESP 5 USB 0x040a/0x4032 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 7 USB 0x040a/0x403e Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 9 USB 0x040a/0x403f Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 2150 USB 0x040a/0x4059 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 2170 USB 0x040a/0x4066 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 3200 USB 0x040a/0x4043 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 3300 USB 0x040a/0x4031 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 4100 USB 0x040a/0x4053 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 5000 USB 0x040a/0x4028 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 5100 USB 0x040a/0x4025 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 5200 USB Ethernet 0x040a/0x4041 Basic USB good, Network good kodakaio
(2.4.6)
sane-kodakaio
ESP 5300 USB 0x040a/0x4026 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 5500 USB 0x040a/0x4027 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 6100 USB 0x040a/0x4054 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 7200 USB 0x040a/0x4056 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP 9200 USB 0x040a/0x4065 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP C110 USB 0x040a/0x4057 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP C115 USB 0x040a/0x4058 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP C310 USB 0x040a/0x405d Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
ESP C315 USB 0x040a/0x405e Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
Hero 3.1 USB 0x040a/0x406d Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
Hero 5.1 USB 0x040a/0x4064 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
Hero 7.1 USB 0x040a/0x4063 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
Hero 9.1 USB Ethernet 0x040a/0x4067 Basic USB good, Network good kodakaio
(2.4.6)
sane-kodakaio
Hero Office 6.1 USB 0x040a/0x4062 Untested Please test! kodakaio
(2.4.6)
sane-kodakaio
i30 USB 0x040a/0x6001 Untested   avision
(Build: 296)
sane-avision
i40 USB 0x040a/0x6002 Basic   avision
(Build: 296)
sane-avision
i50 USB 0x040a/0x6003 Untested   avision
(Build: 296)
sane-avision
i55 USB 0x040a/0x6003 Untested   avision
(Build: 296)
sane-avision
i60 USB 0x040a/0x6004 Untested   avision
(Build: 296)
sane-avision
i65 USB 0x040a/0x6004 Untested   avision
(Build: 296)
sane-avision
i80 USB 0x040a/0x6005 Good   avision
(Build: 296)
sane-avision
i150 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i160 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i250 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i260 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i280 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i610 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i620 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i640 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i660 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i730 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i750 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i780 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i810 Scanner SCSI   Untested Please test! kodak
(7)
sane-kodak
i820 Scanner SCSI   Untested Please test! kodak
(7)
sane-kodak
i830 Scanner SCSI   Untested Please test! kodak
(7)
sane-kodak
i840 Scanner SCSI   Untested Please test! kodak
(7)
sane-kodak
i1840 Scanner IEEE-1394   Untested Please test! kodak
(7)
sane-kodak
i1860 Scanner IEEE-1394   Basic Uncompressed B&W, Gray and Color, some automatic features supported kodak
(7)
sane-kodak
s1740 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 900 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 923 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 1500 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 2500 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 3500 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 3510 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 3520 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 5500 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 7500 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 7520 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 9500 SCSI   Untested Please test! kodak
(7)
sane-kodak
Scanner 9520 SCSI   Untested Please test! kodak
(7)
sane-kodak
Snapshot Photo Scanner 1 Parport   Unsupported Unsupported. FCC ID HWF96PHS unsupported
(2010-06-09)
?

Manufacturer: Komodo

Link(s): http://www.komodo.com/

Model Interface USB id Status Comment Backend Manpage
S1200 SCSI   Untested rebadged Sceptre S1200 sceptre
(1.0-10)
sane-sceptre

Manufacturer: KONICA MINOLTA

Link(s): http://www.konicaminolta.com/

Model Interface USB id Status Comment Backend Manpage
BizHub 162/132 USB Network   Unsupported Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov. magicolor
(1.0.0)
sane-magicolor
DiMage 1611 USB Network   Unsupported Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov. magicolor
(1.0.0)
sane-magicolor
DiMAGE Scan Elite 5400 USB IEEE-1394 0x0686/0x400e Unsupported Probably unsupported. May work with vuescan. See link for details. unsupported
(2010-06-09)
?
DiMAGE Scan Elite 5400 2 USB 0x132b/0x0012 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
DiMAGE Scan Multi Pro IEEE-1394   Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
Dual Scan III USB 0x0686/0x400d Unsupported Unsupported. May work with vuescan. See link for details. unsupported
(2010-06-09)
?
Dual Scan IV USB 0x132b/0x000a Unsupported Unsupported. Works with vuescan. See link for details. unsupported
(2010-06-09)
?
magicolor 1690MF USB Network 0x132b/0x2089 Good Multi-function color laser printer with fax, scanner and network interface magicolor
(1.0.0)
sane-magicolor
magicolor 2480MF USB Network   Unsupported Uses a different scanning protocol than the magicolor 1690MF unsupported
(2010-06-09)
?

Manufacturer: Kyocera

Model Interface USB id Status Comment Backend Manpage
FS-1016MFP USB 0x0482/0x0335 Untested 1 pass, ??? dpi, A4 avision
(Build: 296)
sane-avision

Manufacturer: LEO

Model Interface USB id Status Comment Backend Manpage
LEOScan S3 SCSI   Good FCC ID LUZFS1130 leo
(1.0-10)
sane-leo

Manufacturer: Lexmark

Link(s): http://www.lexmark.com/

Model Interface USB id Status Comment Backend Manpage
P6250 USB 0x043d/0x0097 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
Photo 3150 USB 0x043d/0x007d Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
X12xx USB 0x043d/0x007d Good USB1.1 is OK, USB2.0 needs testing lexmark
(1.0-0)
sane-lexmark
X70 USB 0x043d/0x002d Good Works, some resolutions fail at 16 bit gt68xx
(1.0-84)
sane-gt68xx
X73 USB 0x043d/0x002d Good Works, some resolutions fail at 16 bit, same as X70 gt68xx
(1.0-84)
sane-gt68xx
X74 USB 0x043d/0x0060 Good Supports 75, 150, 300, 600 dpi lexmark
(1.0-0)
sane-lexmark
X75 USB 0x043d/0x0060 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
X75 PrinTrio USB 0x043d/0x0060 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
X83 USB 0x043d/0x003d Unsupported Unsupported. GL640. unsupported
(2010-06-09)
?
X1110 USB 0x043d/0x007c Untested   lexmark
(1.0-0)
sane-lexmark
X1130 USB 0x043d/0x007c Good Supports 75, 150, 300, 600 dpi lexmark
(1.0-0)
sane-lexmark
X1140 USB 0x043d/0x007c Untested   lexmark
(1.0-0)
sane-lexmark
X1150 USB 0x043d/0x007c Good Supports 75, 150, 300, 600 dpi lexmark
(1.0-0)
sane-lexmark
X1170 USB 0x043d/0x007c Good Supports 75, 150, 300, 600 dpi lexmark
(1.0-0)
sane-lexmark
X1180 USB 0x043d/0x007c Good   lexmark
(1.0-0)
sane-lexmark
X1185 USB 0x043d/0x007c Good Tested with xscanimage. Supports 75, 150, 300, 600, 1200(600x1200) dpi resolutions. Does grayscale or colour scans in the following sizes: wallet, 3x5, 4x6, 5x7, 8x10, letter. lexmark
(1.0-0)
sane-lexmark
X1195 USB 0x043d/0x007c Untested   lexmark
(1.0-0)
sane-lexmark
X2330 USB 0x043d/0x00bb Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
X3450 USB 0x043d/0x00f6 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
X5130 USB 0x043d/0x0065 Unsupported Unsupported. unsupported
(2010-06-09)
?
X5150 USB 0x043d/0x0065 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
X5250 USB 0x043d/0x0093 Unsupported Unsupported. unsupported
(2010-06-09)
?
X6170 USB 0x043d/0x0072 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
X7170 USB 0x043d/0x0098 Unsupported Unsupported. See bug #310889 for details. unsupported
(2010-06-09)
?
X7350 USB 0x043d/0x00b8 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
X8350 USB 0x043d/0x00b9 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Linotype Hell

Link(s): http://www.heidelberg.com/

Model Interface USB id Status Comment Backend Manpage
Jade SCSI   Good OK, SCSI-ID=LinoHell JADE umax
(1.0-41)
sane-umax
Jade SCSI   Good OK, SCSI-ID=LinoHell Office umax
(1.0-41)
sane-umax
Jade2 SCSI   Good OK, SCSI-ID=LinoHell Office2 umax
(1.0-41)
sane-umax
Linoscan 1400 SCSI   Good OK, SCSI-ID=HDM LS4H1S umax
(1.0-41)
sane-umax
Opal SCSI   Untested support disabled until tested - please contact author umax
(1.0-41)
sane-umax
Opal Ultra SCSI   Untested support disabled until tested - please contact author umax
(1.0-41)
sane-umax
Opal2 SCSI   Good OK; SCSI-ID=LinoHell OPAL2 umax
(1.0-41)
sane-umax
Saphir SCSI   Untested support disabled until tested - please contact author umax
(1.0-41)
sane-umax
Saphir HiRes SCSI   Untested support disabled until tested - please contact author umax
(1.0-41)
sane-umax
Saphir Ultra SCSI   Untested support disabled until tested - please contact author umax
(1.0-41)
sane-umax
Saphir Ultra II SCSI   Good OK, SCSI-ID=Linotype SAPHIR4 umax
(1.0-41)
sane-umax
Saphir2 SCSI   Good OK, SCSI-ID=LinoHell SAPHIR2 umax
(1.0-41)
sane-umax
Saphir3 SCSI   Good OK, SCSI-ID=LinoHell SAPHIR3 umax
(1.0-41)
sane-umax

Manufacturer: Logitech

Model Interface USB id Status Comment Backend Manpage
PageScan Color Parport   Unsupported Most probably unsupported. unsupported
(2010-06-09)
?
PageScan USB USB 0x046d/0x040f Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Medion/Lifetec/Tevion/Cytron

Link(s): http://www.medion.com, http://www.medion.com/, http://www.medion.de/
Comment: Sold by Aldi and Tchibo.

Model Interface USB id Status Comment Backend Manpage
LT 9452 USB 0x05d8/0x4002 Good Similar to Mustek ScanExpress 1200 UB Plus gt68xx
(1.0-84)
sane-gt68xx
MD 4394 USB 0x05d8/0x4002 Good Product id 0x4002. If you have 0x4003, use artec_eplus48u backend. gt68xx
(1.0-84)
sane-gt68xx
MD 6190 USB 0x0461/0x037b Unsupported Probably unsupported. There seem to exist two different scanners with that name. See link for details. unsupported
(2010-06-09)
?
MD 6190 USB 0x0461/0x0392 Unsupported Probably unsupported. There seem to exist two different scanners with that name. See link for details. unsupported
(2010-06-09)
?
MD 9458 USB 0x05d8/0x4002 Good Similar to Artec Ultima 2000 (e+?) gt68xx
(1.0-84)
sane-gt68xx
MD 9806 Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp
MD 9848 Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp
MD 40420 USB 0x05da/0x3008 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
MD 41260 USB 0x0461/0x037b Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
MD 41985 USB 0x0461/0x037b Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
MD 42666 USB 0x05da/0x3008 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
MD 85264 USB 0x08ff/0x2580 Unsupported Fingerprint sensor. See link for details. unsupported
(2010-06-09)
?
MD 90009 USB 0x05da/0x30e5 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
MD 90070 USB 0x05da/0x3022 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
MD 90090 USB 0x05da/0x3022 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
MD/LT 935x Parport (EPP)   Good 600x1200 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
MD/LT 985x Parport (EPP)   Good 600x1200 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
MD/LT 9375 USB 0x05d8/0x4002 Untested Untested, but is reported to have the same ids as the Artec Ultima 2000. Please test. gt68xx
(1.0-84)
sane-gt68xx
MD/LT 9385 USB 0x05d8/0x4002 Good Similar to Artec Ultima 2000 gt68xx
(1.0-84)
sane-gt68xx
MD/LT 9890 Parport (EPP)   Good 600x1200 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
MD4394 USB 0x05d8/0x4003 Good Only scanners with product id 0x4003 will work; try the gt68xx backend, if your scanner has product id 0x4002 artec_eplus48u
(unmaintained)
sane-artec_eplus48u
MD5345 USB 0x0461/0x0377 Good Has a Primax USB ID genesys
(1.0-63)
sane-genesys
MD6228 USB 0x0461/0x0377 Good Has a Primax USB ID. Same as MD5345 genesys
(1.0-63)
sane-genesys
MD6471 USB 0x0461/0x0377 Complete Has a Primax USB ID. Same as MD5345 genesys
(1.0-63)
sane-genesys
MD9693 USB 0x05d8/0x4003 Good   artec_eplus48u
(unmaintained)
sane-artec_eplus48u
MD9705 USB 0x05d8/0x4003 Good   artec_eplus48u
(unmaintained)
sane-artec_eplus48u

Manufacturer: Memorex

Link(s): http://www.artecusa.com/, http://www.memorex.com/

Model Interface USB id Status Comment Backend Manpage
6136u USB 0x0461/0x0346 Unsupported Probably unsupported. unsupported
(2010-06-09)
?
6142u USB 0x0461/0x0347 Unsupported Probably unsupported. Same as Visioneer Onetouch 4400. See link for details. unsupported
(2010-06-09)
?
MaxxScan 6122 USB Parport 0x05cb/0x1483 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
MEM 48U USB 0x05d8/0x4005 Good   artec_eplus48u
(unmaintained)
sane-artec_eplus48u
SCF 9612P Parport   Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Micromaxx

Model Interface USB id Status Comment Backend Manpage
MM-9851 Parport (EPP)   Good 300x600 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp

Manufacturer: Microstar

Link(s): http://www.microstar.de/

Model Interface USB id Status Comment Backend Manpage
MR 9791 USB 0x05d8/0x4003 Good   artec_eplus48u
(unmaintained)
sane-artec_eplus48u

Manufacturer: Microtek

Link(s): http://www.microtek.com/
Comment: Microtek makes a wide variety of devices.

Model Interface USB id Status Comment Backend Manpage
ArtixScan 2020 SCSI   Unsupported Unsupported. Same as Agfa DuoScan T2000XL? unsupported
(2010-06-09)
?
Artixscan 2500f SCSI IEEE-1384   Unsupported Unsupported. Same as Agfa DuoScan T2500? unsupported
(2010-06-09)
?
ArtixScan 4000tf USB   Unsupported Unsupported. Uses ALI M5611B. unsupported
(2010-06-09)
?
ArtixScanDI 2020 USB 0x05da/0x202e Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
Color PageWiz SCSI (Parport)   Basic sheet-fed (preliminary, see mapage) microtek
(0.13.1)
sane-microtek
FilmScan 35 USB 0x05e3/0x0120 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
Phantom 330CX Parport   Complete   microtek2
(unmaintained)
sane-microtek2
Phantom 636 SCSI   Complete   microtek2
(unmaintained)
sane-microtek2
Phantom 636CX Parport   Complete   microtek2
(unmaintained)
sane-microtek2
ScanMaker 5 SCSI   Unsupported Probably unsupported. See link for more details. unsupported
(2010-06-09)
?
Scanmaker 35 SCSI   Good slide-scanner microtek
(0.13.1)
sane-microtek
Scanmaker 35t+ SCSI   Good slide-scanner microtek
(0.13.1)
sane-microtek
Scanmaker 45t SCSI   Good slide-scanner microtek
(0.13.1)
sane-microtek
ScanMaker 330 SCSI   Basic   microtek2
(unmaintained)
sane-microtek2
ScanMaker 336 CX SCSI   Unsupported Probably unsupported. Seems to be similar to the Microtek 330 CX and is detected by the microtek2 backend. Scanning doesn't seem to work however. unsupported
(2010-06-09)
?
Scanmaker 600G(S) SCSI   Basic gray only (see manpage) microtek
(0.13.1)
sane-microtek
Scanmaker 600Z(S) SCSI   Untested   microtek
(0.13.1)
sane-microtek
ScanMaker 630 SCSI   Basic   microtek2
(unmaintained)
sane-microtek2
ScanMaker 636 SCSI   Complete   microtek2
(unmaintained)
sane-microtek2
Scanmaker 1850S SCSI   Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
ScanMaker 3600 USB 0x05da/0x40ff Basic works sm3600
(0.1)
sane-sm3600
ScanMaker 3600 USB 0x05da/0x40ca Basic works sm3600
(0.1)
sane-sm3600
ScanMaker 3600 USB 0x05da/0x40b3 Basic works sm3600
(0.1)
sane-sm3600
ScanMaker 3630 USB 0x0461/0x0347 Unsupported Unsupported. Doesn't seem to be compatible to 3600 series, see link. unsupported
(2010-06-09)
?
ScanMaker 3700 USB 0x05da/0x40cb Basic works sm3600
(0.1)
sane-sm3600
ScanMaker 3700 USB 0x05da/0x40b8 Basic works sm3600
(0.1)
sane-sm3600
ScanMaker 3750 USB 0x05da/0x40dd Basic works (told) sm3600
(0.1)
sane-sm3600
ScanMaker 3800 USB 0x05da/0x30ce Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 3830 USB 0x05da/0x30ce Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 3840 USB 0x05da/0x30d4 Good 8 and 16 bit, color and grayscale sm3840
(1.1)
sane-sm3840
ScanMaker 3860 USB 0x05da/0x3023 Unsupported Unsupported. See link for more details. Appears to be similar to ScanMaker 3880. unsupported
(2010-06-09)
?
ScanMaker 3880 USB 0x05da/0x3021 Unsupported Unsupported. SQ113 chip. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 4600 USB 0x05da/0x40c7 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 4700 USB 0x05da/0x20b4 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 4800 USB 0x05da/0x30cf Good Same hardware as SM3840, different color box sm3840
(1.1)
sane-sm3840
ScanMaker 4850 USB 0x05da/0x30d9 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
ScanMaker 4850 II USB 0x05da/0x3008 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
ScanMaker 4900 USB 0x05da/0x30b9 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 5600 USB 0x05da/0x20a7 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 5700 USB 0x05da/0x20bd Unsupported Unsupported. Uses ALI M5615 like the ScanMaker 4700. unsupported
(2010-06-09)
?
ScanMaker 5800 USB 0x05da/0x30d8 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
ScanMaker 5800 USB 0x05da/0x3008 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
ScanMaker 5900 USB 0x05da/0x30d8 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 5950 USB 0x05da/0x30d8 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 6000 USB 0x05da/0x30e5 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 6100 USB 0x05da/0x30e5 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanMaker 6400XL SCSI   Complete   microtek2
(unmaintained)
sane-microtek2
ScanMaker 6700 USB IEEE-1394 0x05da/0x20c9 Unsupported Unsupported. See link. unsupported
(2010-06-09)
?
ScanMaker 8700 USB IEEE-1394 0x05da/0x20b1 Unsupported Unsupported. See link for details. USB vendor and product ids to be checked. unsupported
(2010-06-09)
?
ScanMaker 9600XL USB IEEE-1394 0x05da/0x20de Unsupported Probably unsupported. SCSI seems to work with microtek2 backend. unsupported
(2010-06-09)
?
ScanMaker 9600XL SCSI   Good only flatbed mode ? microtek2
(unmaintained)
sane-microtek2
ScanMaker 9800XL USB SCSI 0x05da/0x20de Unsupported Partly unsupported. IEEE-1394 works with microtek2 backend. See link. unsupported
(2010-06-09)
?
ScanMaker 9800XL IEEE-1394   Minimal IEEE-1394 seems to work. See link. More reports welcome. microtek2
(unmaintained)
sane-microtek2
Scanmaker E2 SCSI   Good 3-pass microtek
(0.13.1)
sane-microtek
Scanmaker E3 SCSI   Good   microtek
(0.13.1)
sane-microtek
ScanMaker E3plus SCSI   Complete   microtek2
(unmaintained)
sane-microtek2
ScanMaker E3plus Parport   Complete   microtek2
(unmaintained)
sane-microtek2
Scanmaker E6 SCSI   Good   microtek
(0.13.1)
sane-microtek
ScanMaker i320 USB 0x05da/0x30e6 Unsupported Unsupported. See link. unsupported
(2010-06-09)
?
Scanmaker II SCSI   Good 3-pass microtek
(0.13.1)
sane-microtek
Scanmaker IIG SCSI   Good gray only microtek
(0.13.1)
sane-microtek
Scanmaker IIHR SCSI   Good 3-pass microtek
(0.13.1)
sane-microtek
Scanmaker III SCSI   Good   microtek
(0.13.1)
sane-microtek
Scanmaker IISP SCSI   Good   microtek
(0.13.1)
sane-microtek
ScanMaker S400 USB 0x05da/0x300b Unsupported Unsupported. See link. unsupported
(2010-06-09)
?
ScanMaker s400 USB 0x05da/0x201c Unsupported Unsupported. See link. unsupported
(2010-06-09)
?
ScanMaker V6UPL USB 0x05da/0x00b6 Basic Sometimes scan speed goes to fast and results look badly smudged. microtek2
(unmaintained)
sane-microtek2
ScanMaker V6USL USB 0x05da/0x80a3 Complete   microtek2
(unmaintained)
sane-microtek2
ScanMaker V6USL USB 0x05da/0x00a3 Complete   microtek2
(unmaintained)
sane-microtek2
ScanMaker V6USL SCSI   Complete   microtek2
(unmaintained)
sane-microtek2
ScanMaker V300 Parport   Good   microtek2
(unmaintained)
sane-microtek2
ScanMaker V300 SCSI   Good   microtek2
(unmaintained)
sane-microtek2
ScanMaker V310 Parport   Basic   microtek2
(unmaintained)
sane-microtek2
ScanMaker V310 SCSI   Basic   microtek2
(unmaintained)
sane-microtek2
ScanMaker V600 Parport   Basic   microtek2
(unmaintained)
sane-microtek2
ScanMaker V600 SCSI   Basic   microtek2
(unmaintained)
sane-microtek2
ScanMaker X6 SCSI   Complete   microtek2
(unmaintained)
sane-microtek2
ScanMaker X6EL SCSI   Basic   microtek2
(unmaintained)
sane-microtek2
ScanMaker X6USB USB 0x05da/0x0099 Good   microtek2
(unmaintained)
sane-microtek2
ScanMaker X12USL SCSI   Good only Flatbed mode ? microtek2
(unmaintained)
sane-microtek2
ScanPort 3000 USB 0x04a7/0x0224 Unsupported Unsupported. Vendor/Product ids: 0x04a7/0x0224. Realtek RTS8801B?. See link for details. unsupported
(2010-06-09)
?
SlimScan C3 Parport   Complete   microtek2
(unmaintained)
sane-microtek2
SlimScan C6 USB 0x05da/0x009a Complete   microtek2
(unmaintained)
sane-microtek2

Manufacturer: Minolta

Link(s): http://www.minolta.com

Model Interface USB id Status Comment Backend Manpage
Dimage Scan Dual I SCSI   Basic   avision
(Build: 296)
sane-avision
Dimage Scan Dual II USB 0x0638/0x026a Good 1 pass, film-scanner avision
(Build: 296)
sane-avision
Dimage Scan Dual III USB 0x0686/0x400d Good 1 pass, film-scanner avision
(Build: 296)
sane-avision
Dimage Scan Elite 5400 USB 0x0686/0x400e Good 1 pass, film-scanner avision
(Build: 296)
sane-avision
Elite II USB 0x0686/0x4004 Untested 1 pass, film-scanner avision
(Build: 296)
sane-avision
Scan Multi Pro SCSI   Untested   avision
(Build: 296)
sane-avision

Manufacturer: Minolta-QMS

Model Interface USB id Status Comment Backend Manpage
SC-110 USB 0x0638/0x0a15 Untested   avision
(Build: 296)
sane-avision
SC-215 USB 0x0638/0x0a16 Good   avision
(Build: 296)
sane-avision

Manufacturer: Mitsubishi

Link(s): http://www.mitsubishi.com

Model Interface USB id Status Comment Backend Manpage
Diamondview 648UT USB 0x04a5/0x2022 Good Rebadged Benq 320u. SnapScan
(1.4)
sane-snapscan
Diamondview 650U USB 0x04a5/0x20b0 Good Rebadged Benq 4300. SnapScan
(1.4)
sane-snapscan
MCA-ADFC SCSI   Untested   avision
(Build: 296)
sane-avision
S600C SCSI   Untested   avision
(Build: 296)
sane-avision
S1200C SCSI   Untested   avision
(Build: 296)
sane-avision
SS600 SCSI   Good   avision
(Build: 296)
sane-avision

Manufacturer: Mustek

Link(s): http://www.mustek.com/, http://www.mustek.com.tw/, http://www.mustek.de/

Model Interface USB id Status Comment Backend Manpage
96 CP Parport (EPP)   Good 300x600 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
600 III EP Plus Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp
1200 III EP Parport   Unsupported Probably not supported. quarlewm at jmu dot edu offers to temporarily loan such a scanner to anyone who is interested in writing a driver. unsupported
(2010-06-09)
?
2400 M USB   Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
BearPaw 1200 USB 0x0400/0x1001 Complete both product versions are supported, see backends' man-page plustek
(0.52)
sane-plustek
BearPaw 1200 USB 0x0400/0x1000 Complete both product versions are supported, see backends' man-page plustek
(0.52)
sane-plustek
BearPaw 1200 CS USB 0x055f/0x021e Good   gt68xx
(1.0-84)
sane-gt68xx
BearPaw 1200 CU USB 0x05d8/0x4002 Good   gt68xx
(1.0-84)
sane-gt68xx
BearPaw 1200 CU Plus USB 0x055f/0x021c Good   gt68xx
(1.0-84)
sane-gt68xx
BearPaw 1200 CU Plus USB 0x055f/0x021b Good   gt68xx
(1.0-84)
sane-gt68xx
BearPaw 1200 F USB 0x055f/0x0010 Good Works upto 600 dpi. No support for TA and ADF yet. ma1509
(1.0-3)
sane-ma1509
BearPaw 1200 TA USB 0x055f/0x021e Good Transparency adapter supported gt68xx
(1.0-84)
sane-gt68xx
BearPaw 1248 CU USB 0x055f/0x021c Good Seems to use the same ids as BearPaw 1200 CU Plus. gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2400 USB 0x0400/0x1001 Complete   plustek
(0.52)
sane-plustek
BearPaw 2400 CS USB 0x055f/0x0218 Untested Probably works, reports are welcome gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2400 CS Plus USB 0x055f/0x0219 Good Works, problems with 12/16 bit modes? gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2400 CU USB 0x05d8/0x4002 Basic Works, but is slow gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2400 CU Plus USB 0x055f/0x021d Good   gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2400 TA USB 0x055f/0x0218 Good Transparency adapter supported gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2400 TA Plus USB 0x055f/0x0219 Good Transparency adapter supported gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2400 TA Pro USB 0x055f/0x0400 Unsupported Not supported. May be supported by mustek_usb2 backend later. See link for some information. unsupported
(2010-06-09)
?
BearPaw 2448 CS Plus USB 0x055f/0x021a Basic Slow. Same as 2448 TA Plus, but without TA. gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2448 CU Pro USB 0x055f/0x0408 Unsupported Not supported. May be supported by mustek_usb2 backend later. See link for some information. unsupported
(2010-06-09)
?
BearPaw 2448 TA Plus USB 0x055f/0x021a Basic Slow. Transparency adapter supported. Slow. Brightness depends on resolution? gt68xx
(1.0-84)
sane-gt68xx
BearPaw 2448TA Pro USB 0x055f/0x0409 Good   mustek_usb2
(1.0-10)
sane-mustek_usb2
BearPaw 4800 TA Pro USB 0x055f/0x1000 Unsupported Not supported. See link for some information. unsupported
(2010-06-09)
?
BearPaw 4800 TA Pro II USB 0x055f/0x040a Unsupported Not supported. May be supported by mustek_usb2 backend later. See link for some information. unsupported
(2010-06-09)
?
BearPaw 6400 TA Pro USB 0x055f/0x040b Unsupported Not supported. May be supported by mustek_usb2 backend later. See link for some information. unsupported
(2010-06-09)
?
Paragon 600 II CD SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon 600 II ED Parport   Untested Completely untested. If it's the same as the 600 II EP, it may work. Please contact me if you own such a device. mustek
(1.0-138)
sane-mustek
Paragon 600 II EP Parport   Minimal Works, however only low resolutions and quality in color mode is bad. mustek
(1.0-138)
sane-mustek
Paragon 600 II N Proprietary   Basic Resolutions above 300 dpi may cause trouble. mustek
(1.0-138)
sane-mustek
Paragon 800 II EP Parport   Unsupported Not supported. Maybe similar to 600 II EP (SCSI_over-parport)? In this case it could be supported by the mustek SCSI backend. unsupported
(2010-06-09)
?
Paragon 800 II SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon 1200 A3 Pro SCSI   Complete ADF and TA untested. Please contact me if you own such equipment. mustek
(1.0-138)
sane-mustek
Paragon 1200 III SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon 1200 LS SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon 1200 SP Pro SCSI   Good   mustek
(1.0-138)
sane-mustek
Paragon MFC-600S SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon MFC-800S SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon MFS-1200SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon MFS-6000CX SCSI   Good 3-pass mustek
(1.0-138)
sane-mustek
Paragon MFS-6000SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon MFS-8000SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
Paragon MFS-12000CX SCSI   Good 3-pass mustek
(1.0-138)
sane-mustek
Paragon MFS-12000SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
Plug-n-Scan 2400 M USB 0x055f/0x0219 Good Works but is slow in high resolutions. Same as BearPaw 2400 CS Plus. gt68xx
(1.0-84)
sane-gt68xx
Plug-n-Scan 2400 MT USB 0x055f/0x0219 Good Works but is slow in high resolutions. Same as BearPaw 2400 TA Plus. gt68xx
(1.0-84)
sane-gt68xx
ScanExpress 600 CP Parport (EPP)   Good 300x600 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
ScanExpress 600 CU USB 0x055f/0x0002 Complete   mustek_usb
(1.0-18)
sane-mustek_usb
ScanExpress 600 SEP Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp
ScanExpress 600 USB USB 0x055f/0x0873 Unsupported Unsupported. Programming information is available. unsupported
(2010-06-09)
?
ScanExpress 1200 CP Parport (EPP)   Good 600x1200 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
ScanExpress 1200 CP+ Parport (EPP)   Good 600x1200 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
ScanExpress 1200 CU USB 0x055f/0x0001 Complete   mustek_usb
(1.0-18)
sane-mustek_usb
ScanExpress 1200 CU Plus USB 0x055f/0x0008 Complete   mustek_usb
(1.0-18)
sane-mustek_usb
ScanExpress 1200 FS SCSI   Untested One report that it crashes the computer. SCSI driver issue? Please contact me if you own such a device. mustek
(1.0-138)
sane-mustek
ScanExpress 1200 UB USB 0x055f/0x0006 Complete For the UB Plus, see gt68xx backend mustek_usb
(1.0-18)
sane-mustek_usb
ScanExpress 1200 UB Plus USB 0x05d8/0x4002 Good   gt68xx
(1.0-84)
sane-gt68xx
ScanExpress 1200 USB USB 0x055f/0x0003 Unsupported Unsupported. Programming information is available. unsupported
(2010-06-09)
?
ScanExpress 1200 USB Plus USB 0x055f/0x0007 Unsupported Unsupported. unsupported
(2010-06-09)
?
ScanExpress 1248 UB USB 0x055f/0x021f Complete   gt68xx
(1.0-84)
sane-gt68xx
ScanExpress 2400 USB USB 0x05d8/0x4002 Minimal Should be detected but may need some more work in the code. Testers welcome. Please contact me if you own this scanner. gt68xx
(1.0-84)
sane-gt68xx
ScanExpress 6000 P Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp
ScanExpress 6000SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
ScanExpress 12000 P Parport   Unsupported Not supported. Asic 1505/05. unsupported
(2010-06-09)
?
ScanExpress 12000SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
ScanExpress 12000SP Plus SCSI   Complete   mustek
(1.0-138)
sane-mustek
ScanExpress A3 EP Parport   Unsupported Not supported. Maybe it will be supported by the mustek_pp backend in future. unsupported
(2010-06-09)
?
ScanExpress A3 SP SCSI   Basic Please test! mustek
(1.0-138)
sane-mustek
ScanExpress A3 USB USB 0x055f/0x0210 Basic Still some vertical stripes. gt68xx
(1.0-84)
sane-gt68xx
ScanExpress CardSmart USB   Unsupported Probably unsupported. USB business card scanner. Maybe works as USB storage device? unsupported
(2010-06-09)
?
ScanMagic 600 CP Parport (EPP)   Good 300x600 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
ScanMagic 600 II SP SCSI   Complete   mustek
(1.0-138)
sane-mustek
ScanMagic 1200 UB Plus USB 0x05d8/0x4002 Good Same as ScanExpress 1200 UB Plus gt68xx
(1.0-84)
sane-gt68xx
ScanMagic 4800 P Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp
ScanMagic 4830S SCSI   Untested sub model VM3575 teco2
(1.0-9)
sane-teco2
ScanMagic 9636P Parport   Unsupported Probably not supported. Same as Mustek 12000 P?. ASIC 1505. unsupported
(2010-06-09)
?
ScanMagic 9636S SCSI   Complete   mustek
(1.0-138)
sane-mustek
ScanMagic 9636S Plus SCSI   Complete   mustek
(1.0-138)
sane-mustek
TwainScan II SP SCSI   Complete   mustek
(1.0-138)
sane-mustek

Manufacturer: NeatReceipts

Model Interface USB id Status Comment Backend Manpage
Mobile Scanner USB 0x07b3/0x0462 Basic Similar to Plustek OpticSlim M12. gt68xx
(1.0-84)
sane-gt68xx
Scanalizer Professional 2.5 USB 0x07b3/0x0412 Untested Similar to Plustek OpticSlim M12. Please tell us if this scanner works. gt68xx
(1.0-84)
sane-gt68xx

Manufacturer: NEC

Link(s): http://www.nevt.co.jp/

Model Interface USB id Status Comment Backend Manpage
PC-IN500/4C SCSI   Good PC-IN500/4C was sold only in JAPAN nec
(0.12)
sane-nec
Petiscan USB 0x0475/0x0100 Unsupported Most probably unsupported. See link for details. Vendor ID is Relisys/Teco. Not known if it is similar to other Relisys/Teco USB scanners. unsupported
(2010-06-09)
?

Manufacturer: Network

Model Interface USB id Status Comment Backend Manpage
Easy Plus 30 Bit Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp

Manufacturer: Nikon

Link(s): http://www.nikon.com/

Model Interface USB id Status Comment Backend Manpage
AX-110 / Scantouch 110 SCSI   Untested may work, please test and give feedback umax
(1.0-41)
sane-umax
AX-210 SCSI   Good OK umax
(1.0-41)
sane-umax
Coolscan III SCSI   Complete Rebadged LS 30? coolscan3
(1.0.0)
sane-coolscan3
Coolscan V ED USB 0x04b0/0x4001 Minimal Rebadged LS 50? coolscan3
(1.0.0)
sane-coolscan3
Coolscan V ED USB 0x04b0/0x4001 Minimal   coolscan2
(0.1.8)
sane-coolscan2
Coolspan IV USB 0x04b0/0x4000 Complete Rebadged LS 40? coolscan3
(1.0.0)
sane-coolscan3
LS 30 SCSI   Complete   coolscan3
(1.0.0)
sane-coolscan3
LS 30 SCSI   Complete working -- model available to developer coolscan2
(0.1.8)
sane-coolscan2
LS 40 ED USB 0x04b0/0x4000 Complete   coolscan3
(1.0.0)
sane-coolscan3
LS 40 ED USB 0x04b0/0x4000 Complete   coolscan2
(0.1.8)
sane-coolscan2
LS 50 ED USB 0x04b0/0x4001 Minimal   coolscan3
(1.0.0)
sane-coolscan3
LS 50 ED USB 0x04b0/0x4001 Minimal   coolscan2
(0.1.8)
sane-coolscan2
LS 2000 SCSI   Good   coolscan3
(1.0.0)
sane-coolscan3
LS 2000 SCSI   Good   coolscan2
(0.1.8)
sane-coolscan2
LS 4000 ED IEEE-1394   Good needs linux kernel 2.4.19 or later coolscan3
(1.0.0)
sane-coolscan3
LS 4000 ED IEEE-1394   Good needs linux kernel 2.4.19 or later coolscan2
(0.1.8)
sane-coolscan2
LS 8000 ED IEEE-1394   Good needs linux kernel 2.4.19 or later coolscan3
(1.0.0)
sane-coolscan3
LS 8000 ED IEEE-1394   Good needs linux kernel 2.4.19 or later coolscan2
(0.1.8)
sane-coolscan2
LS-20 SCSI   Basic The LS-20 has been replaced by the LS-30 coolscan
(0.4.3)
sane-coolscan
LS-30 SCSI   Basic alpha: only 24/30 bit RGB + 32/40 bit RGBI coolscan
(0.4.3)
sane-coolscan
LS-1000 SCSI   Basic Doesn't support gamma correction coolscan
(0.4.3)
sane-coolscan
LS-2000 SCSI   Basic alpha: only 24/36 bit + RGB 32/48 bit RGBI coolscan
(0.4.3)
sane-coolscan
LS-9000 ED IEEE-1394   Unsupported Probably not supported. See link for details. Possibly similar to LS-8000 ED. unsupported
(2010-06-09)
?
Super Coolscan LS-5000 ED USB 0x04b0/0x4002 Untested May work, similar to LS 50 ED, but untested. Please tell us if it works. coolscan3
(1.0.0)
sane-coolscan3
Super Coolscan LS-5000 ED USB 0x04b0/0x4002 Untested May work, similar to LS 50 ED, but untested. Please tell us if it works. coolscan2
(0.1.8)
sane-coolscan2

Manufacturer: Nortek

Model Interface USB id Status Comment Backend Manpage
MyScan 1200 USB 0x07b3/0x040b Untested Untested. Please test. Similar to Plustek OpticPro S12? gt68xx
(1.0-84)
sane-gt68xx

Manufacturer: OKI

Model Interface USB id Status Comment Backend Manpage
S700 Scancopier USB 0x0638/0x0a16 Good 1 pass, 600 dpi, A4 avision
(Build: 296)
sane-avision

Manufacturer: Olivetti

Link(s): http://www.olivetti.com

Model Interface USB id Status Comment Backend Manpage
Job-Jet M400 USB 0x0b3c/0xa880 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Olympus

Link(s): http://www.olympus.com

Model Interface USB id Status Comment Backend Manpage
ES-10P Parport   Unsupported   unsupported
(2010-06-09)
?
ES-10S SCSI   Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Optoelectronics

Model Interface USB id Status Comment Backend Manpage
Barcode scanner USB 0x065a/0x0001 Unsupported Probably not supported. unsupported
(2010-06-09)
?

Manufacturer: Optrox

Model Interface USB id Status Comment Backend Manpage
PhotoMaker 3C Parport   Unsupported   unsupported
(2010-06-09)
?
PhotoMaker 3E Parport   Unsupported   unsupported
(2010-06-09)
?
PhotoMaker 3F Proprietary   Unsupported Special ISA card unsupported
(2010-06-09)
?
PhotoMaker 3S Parport   Unsupported   unsupported
(2010-06-09)
?
PhotoMaker 6E Parport   Unsupported   unsupported
(2010-06-09)
?
PhotoMaker 6F Proprietary   Unsupported Special ISA card unsupported
(2010-06-09)
?

Manufacturer: Packard Bell

Model Interface USB id Status Comment Backend Manpage
Diamond 1200 USB 0x05d8/0x4002 Good Similar to Mustek BearPaw 1200 (Plus) gt68xx
(1.0-84)
sane-gt68xx
Diamond 1200 Plus USB 0x055f/0x021b Good Similar to Mustek BearPaw 1200 Plus gt68xx
(1.0-84)
sane-gt68xx
Diamond 1200 Plus USB 0x055f/0x021c Good Similar to Mustek BearPaw 1200 Plus gt68xx
(1.0-84)
sane-gt68xx
Diamond 2450 USB 0x055f/0x0219 Good   gt68xx
(1.0-84)
sane-gt68xx

Manufacturer: Panasonic

Link(s): http://www.panasonic.com/

Model Interface USB id Status Comment Backend Manpage
KV-S1020C USB 0x04da/0x1007 Good   kvs1025
(unmaintained)
sane-kvs1025
KV-S1025C USB 0x04da/0x1006 Good   kvs1025
(unmaintained)
sane-kvs1025
KV-S1045C USB 0x04da/0x1010 Good   kvs1025
(unmaintained)
sane-kvs1025
KV-S2025C SCSI   Minimal no color, no high resolution, no automatic cropping matsushita
(1.0-7)
sane-matsushita
KV-S2026C USB SCSI 0x04da/0x1000 Untested   kvs20xx
(unmaintained)
sane-kvs20xx
KV-S2028C USB 0x04da/0x100a Untested   kvs20xx
(unmaintained)
sane-kvs20xx
KV-S2045C SCSI   Minimal no color, no high resolution, no automatic cropping matsushita
(1.0-7)
sane-matsushita
KV-S2046C USB SCSI 0x04da/0x1001 Untested   kvs20xx
(unmaintained)
sane-kvs20xx
KV-S2048C USB 0x04da/0x1009 Untested   kvs20xx
(unmaintained)
sane-kvs20xx
KV-S2055L SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S2055W USB SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S2065L SCSI   Minimal no color, no high resolution, no automatic cropping matsushita
(1.0-7)
sane-matsushita
KV-S2065W SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S3065CL USB SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S3065CW USB SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S3085 USB SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S3105C USB SCSI   Unsupported might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool. unsupported
(2010-06-09)
?
KV-S4065C USB 0x04da/0x100d Untested   kvs40xx
(unmaintained)
sane-kvs40xx
KV-S4085C USB 0x04da/0x100c Untested   kvs40xx
(unmaintained)
sane-kvs40xx
KV-S6040W SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S6045W SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S6050W SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S6055W SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S7065C USB SCSI   Unsupported might be supported by matsushita backend. unsupported
(2010-06-09)
?
KV-S7075C USB 0x04da/0x100e Untested   kvs40xx
(unmaintained)
sane-kvs40xx
KV-SS25 SCSI   Complete   matsushita
(1.0-7)
sane-matsushita
KV-SS25D SCSI   Complete   matsushita
(1.0-7)
sane-matsushita
KV-SS50 SCSI   Untested   matsushita
(1.0-7)
sane-matsushita
KV-SS50EX SCSI   Untested   matsushita
(1.0-7)
sane-matsushita
KV-SS55 SCSI   Untested   matsushita
(1.0-7)
sane-matsushita
KV-SS55EX SCSI   Minimal no color, no high resolution, no automatic cropping matsushita
(1.0-7)
sane-matsushita
KV-SS080 USB 0x04da/0x100f Complete All resolution and mode supported, calibration is available. Support sponsored by cncsolutions (http://www.cncsolutions.com.br) genesys
(1.0-63)
sane-genesys
KV-SS850 SCSI   Untested   matsushita
(1.0-7)
sane-matsushita
KV-SS855 SCSI   Untested   matsushita
(1.0-7)
sane-matsushita
KV-SS905C SCSI   Unsupported might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool. unsupported
(2010-06-09)
?

Manufacturer: Pentax

Link(s): http://www.pentaxtech.com/, http://mobilesolutions.brother-usa.com/

Model Interface USB id Status Comment Backend Manpage
DSmobile 600 USB 0x04f9/0x2038 Good All resolution and mode supported, calibration is available genesys
(1.0-63)
sane-genesys
DSmobile 600 USB 0x0a17/0x3210 Good All resolution and mode supported, calibration is available genesys
(1.0-63)
sane-genesys
DSmobile USB USB 0x0a82/0x2000 Unsupported Probably not supported. Some information is available. unsupported
(2010-06-09)
?

Manufacturer: PIE

Link(s): http://www.scanace.com/
Comment: Pacific Image Electronics

Model Interface USB id Status Comment Backend Manpage
PF3650 Pro3 Film Scanner USB IEEE-1394 0x05e3/0x0143 Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
Powerslide 3600 USB IEEE-1394 0x05e3/0x0142 Unsupported Probably unsupported. Film scanner that can scan directly from the magazine. unsupported
(2010-06-09)
?
Primefilm 1800u USB 0x05e3/0x0120 Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
Primefilm 2700 USB   Unsupported   unsupported
(2010-06-09)
?
Primefilm 3600PRO USB IEEE-1394   Unsupported Probably not supported. unsupported
(2010-06-09)
?
ScanAce 630S SCSI   Untested   pie
(1.0)
sane-pie
ScanAce 636S SCSI   Untested   pie
(1.0)
sane-pie
ScanAce 1230S SCSI   Good   pie
(1.0)
sane-pie
ScanAce 1236S SCSI   Good   pie
(1.0)
sane-pie
ScanAce II SCSI   Untested   pie
(1.0)
sane-pie
ScanAce II Plus SCSI   Untested   pie
(1.0)
sane-pie
ScanAce III SCSI   Good   pie
(1.0)
sane-pie
ScanAce III Plus SCSI   Untested   pie
(1.0)
sane-pie
ScanAce Plus SCSI   Untested   pie
(1.0)
sane-pie
ScanAce ScanMedia SCSI   Untested   pie
(1.0)
sane-pie
ScanAce ScanMedia II SCSI   Untested   pie
(1.0)
sane-pie
ScanAce V SCSI   Untested   pie
(1.0)
sane-pie

Manufacturer: PIOTECH

Link(s): http://www.image-land.com/

Model Interface USB id Status Comment Backend Manpage
Splendeur 3024 SCSI   Good sub model VM3552 teco3
(1.0-1)
sane-teco3

Manufacturer: PLANon

Link(s): http://www.planon.com/

Model Interface USB id Status Comment Backend Manpage
DocuPen (DPEN-BW) USB   Unsupported Probably not supported. No details known. unsupported
(2010-06-09)
?
DocuPen R700 USB 0x10c4/0xea60 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
DocuPen RC800 USB   Unsupported Probably not supported. No details known. unsupported
(2010-06-09)
?

Manufacturer: Plustek

Link(s): http://www.plustek.com/, http://www.plustek.de/

Model Interface USB id Status Comment Backend Manpage
Iriscan Express 2 USB 0x07b3/0x045f Complete Works up to 1200 dpi. Calibration with external calibration sheet supported gt68xx
(1.0-84)
sane-gt68xx
OptiCard 600+ USB   Unsupported Business card reader. No further information available. unsupported
(2010-06-09)
?
OpticBook 3600 USB 0x07b3/0x0900 Basic Has a Primax USB ID genesys
(1.0-63)
sane-genesys
OpticFilm 7200 USB 0x07b3/0x0807 Unsupported GL842 based, maybe to be added to genesys backend unsupported
(2010-06-09)
?
OpticFilm 7200i USB 0x07b3/0x0c04 Unsupported GL843 based, maybe to be added to genesys backend unsupported
(2010-06-09)
?
OpticPro 600P/6000P Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 1212U USB 0x07b3/0x0001 Basic   u12
(0.02)
sane-u12
OpticPro 1236P Parport (SPP, EPP)   Complete reported as OpticPro 12000P/96000P plustek_pp
(0.43)
sane-plustek_pp
OpticPro 1248U USB 0x07b3/0x0401 Good   gt68xx
(1.0-84)
sane-gt68xx
OpticPro 1248U USB 0x07b3/0x0400 Good   gt68xx
(1.0-84)
sane-gt68xx
OpticPro 2400SP SCSI   Untested sub model VM3552 teco3
(1.0-1)
sane-teco3
OpticPro 4800P Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 4830P Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 4831P Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 9600P Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 9630P Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 9630PL Parport (SPP, EPP)   Complete use driver-switch mov=1 plustek_pp
(0.43)
sane-plustek_pp
OpticPro 9636P Parport (SPP, EPP)   Complete use driver-switch mov=4 plustek_pp
(0.43)
sane-plustek_pp
OpticPro 9636P+/Turbo Parport (SPP, EPP)   Complete use driver-switch mov=3 plustek_pp
(0.43)
sane-plustek_pp
OpticPro 9636T Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 12000P/96000P Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 12000T Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro 19200S SCSI   Complete rebadged Artec AM12S artec
(unmaintained)
sane-artec
OpticPro A3U USB   Unsupported Uses Plustek ASIC P99002 unsupported
(2010-06-09)
?
OpticPro AI3 Parport (SPP, EPP)   Basic use driver-switch mov=5, poor picture quality plustek_pp
(0.43)
sane-plustek_pp
OpticPro P8 Parport   Untested   plustek_pp
(0.43)
sane-plustek_pp
OpticPro P12 Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro PT12 Parport (SPP, EPP)   Complete   plustek_pp
(0.43)
sane-plustek_pp
OpticPro S6 USB   Unsupported Uses RealTek chipset (RTL8801D) unsupported
(2010-06-09)
?
OpticPro S12 USB 0x07b3/0x0600 Unsupported Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend. unsupported
(2010-06-09)
?
OpticPro S12 USB 0x07b3/0x040b Good Product ID 0x040b only. gt68xx
(1.0-84)
sane-gt68xx
OpticPro S24 USB 0x07b3/0x0601 Unsupported Product id 0x0601 is unsupported but may be supported by the genesys backend in future /GL646). Product id 0x040e is supported by the gt68xx backend. unsupported
(2010-06-09)
?
OpticPro S24 USB 0x07b3/0x040e Good Product ID 0x040e only. Is reported to work. gt68xx
(1.0-84)
sane-gt68xx
OpticPro S28 USB 0x07b3/0x0801 Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
OpticPro ST12 USB 0x07b3/0x0600 Unsupported Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend. unsupported
(2010-06-09)
?
OpticPro ST12 USB 0x07b3/0x040b Untested Product ID 0x040b only. Needs testing. Transparency adapter completely untested. Please contact me if you own such a scanner. gt68xx
(1.0-84)
sane-gt68xx
OpticPro ST16 USB 0x07b3/0x0600 Unsupported GL646 based, to be added to genesys backend unsupported
(2010-06-09)
?
OpticPro ST24 USB 0x07b3/0x0601 Unsupported GL646 based, to be added to genesys backend unsupported
(2010-06-09)
?
OpticPro ST28 USB 0x07b3/0x0802 Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
OpticPro ST28 USB 0x07b3/0x0801 Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
OpticPro ST48 USB 0x07b3/0x0800 Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
OpticPro ST64 USB 0x07b3/0x0c00 Unsupported GL843 based, maybe to be added to genesys backend unsupported
(2010-06-09)
?
OpticPro ST64+ USB 0x07b3/0x0c03 Unsupported GL843 based. See link for more details. unsupported
(2010-06-09)
?
OpticPro U12 USB 0x07b3/0x0001 Basic Note: Only devices with product ID 0x0001 are supported! u12
(0.02)
sane-u12
OpticPro U12 USB 0x07b3/0x0010 Complete NOTE: Devices with product ID 0x0001 are not supported! plustek
(0.52)
sane-plustek
OpticPro U16B USB 0x07b3/0x0402 Good   gt68xx
(1.0-84)
sane-gt68xx
OpticPro U16B+ USB 0x07b3/0x0403 Good   gt68xx
(1.0-84)
sane-gt68xx
OpticPro U24 USB 0x07b3/0x0015 Complete   plustek
(0.52)
sane-plustek
OpticPro U24 USB 0x07b3/0x0011 Complete   plustek
(0.52)
sane-plustek
OpticPro UA18 USB   Unsupported Probably LM983x based. unsupported
(2010-06-09)
?
OpticPro UT12 USB 0x07b3/0x0001 Basic Note: Only devices with product ID 0x0001 are supported! u12
(0.02)
sane-u12
OpticPro UT12 USB 0x07b3/0x0017 Complete Note: Devices with product ID 0x0001 are not supported! plustek
(0.52)
sane-plustek
OpticPro UT12 USB 0x07b3/0x0013 Complete   plustek
(0.52)
sane-plustek
OpticPro UT16 USB 0x07b3/0x0017 Complete   plustek
(0.52)
sane-plustek
OpticPro UT16B USB 0x07b3/0x0403 Untested Probably works. Transparency adapter not supported yet. Please contact me if you own such a device. gt68xx
(1.0-84)
sane-gt68xx
OpticPro UT24 USB 0x07b3/0x0017 Complete   plustek
(0.52)
sane-plustek
OpticSlim 500 USB 0x07b3/0x0458 Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
OpticSlim 1200 USB 0x07b3/0x0413 Good   gt68xx
(1.0-84)
sane-gt68xx
OpticSlim 2400 USB 0x07b3/0x0422 Good Works up to 1200 dpi. gt68xx
(1.0-84)
sane-gt68xx
OpticSlim 2400 plus USB 0x07b3/0x0454 Good Same as OpticSlim 2400. gt68xx
(1.0-84)
sane-gt68xx
OpticSlim 2420 USB 0x07b3/0x0806 Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
OpticSlim 2420+ USB 0x07b3/0x0914 Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
OpticSlim M12 USB 0x07b3/0x0412 Complete Works up to 1200 dpi. Calibration with external calibration sheet supported gt68xx
(1.0-84)
sane-gt68xx
OpticWorks 2000 Parport   Unsupported Multifunction device. No further information available. unsupported
(2010-06-09)
?
PL 806 USB 0x07b3/0x0c0c Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
ScanCopy 115 USB 0x07b3/0x081c Unsupported GL841 based, to be added to genesys backend unsupported
(2010-06-09)
?
SmartOffice PL 812 USB 0x07b3/0x0c0d Unsupported Unsupported. See link for more details. unsupported
(2010-06-09)
?
Spectra ADF Proprietary   Unsupported Unsupported. Uses proprietary ISA card that also provides power and is labelled GPS-1 PAGE-A from Taiwan. Other labels on the scanner include ADF Color Scanner and SF600AS. Maybe the same as the IBM ADF Color Scanner? unsupported
(2010-06-09)
?
Umax AstraScan 4750 USB 0x07b3/0x0802 Unsupported GL841 based, to be added to genesys backend, rebadged Plustek ST28 unsupported
(2010-06-09)
?
Unknown Plustek Device USB 0x07b3/0x0016 Unsupported Probably unsupported. Scanner name not known yet. unsupported
(2010-06-09)
?
Unknown Plustek Device USB 0x07b3/0x0014 Unsupported Probably unsupported. Scanner name not known yet. unsupported
(2010-06-09)
?
Unknown Plustek Device USB 0x07b3/0x0012 Unsupported Probably unsupported. Scanner name not known yet. unsupported
(2010-06-09)
?
Unknown Plustek Device USB 0x07b3/0x000f Unsupported Probably unsupported. Scanner name not known yet. unsupported
(2010-06-09)
?
Unknown Plustek Device USB 0x07b3/0x0007 Unsupported Probably unsupported. Scanner name not known yet. unsupported
(2010-06-09)
?
Unknown Plustek Device USB 0x07b3/0x0005 Unsupported Probably unsupported. Scanner name not known yet. unsupported
(2010-06-09)
?

Manufacturer: Portable Peripheral Co., Ltd.

Link(s): http://www.pandp.com.tw/

Model Interface USB id Status Comment Backend Manpage
Q-Scan USB001 (A4 portable scanner) USB 0x0a53/0x1000 Complete   plustek
(0.52)
sane-plustek
Q-Scan USB201 (A6 portable scanner) USB 0x0a53/0x2000 Good   plustek
(0.52)
sane-plustek

Manufacturer: Primax

Link(s): http://www.primax.nl/, http://www.primax.com.tw

Model Interface USB id Status Comment Backend Manpage
Colorado 600U USB 0x0461/0x0341 Unsupported Not supported. Some information is available. unsupported
(2010-06-09)
?
Colorado 1200p Parport   Unsupported Unsupported by SANE. But is reported to partly work with pxscan. See link. unsupported
(2010-06-09)
?
Colorado 1200u USB 0x0461/0x0361 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
Colorado 4800 Parport (SPP, EPP)   Untested same as OpticPro 4800P plustek_pp
(0.43)
sane-plustek_pp
Colorado Direct 600 Parport   Unsupported Not supported. However, a stand-alone program is available. unsupported
(2010-06-09)
?
Colorado Direct 9600 Parport   Unsupported Not supported. However, a stand-alone program is available. unsupported
(2010-06-09)
?
Colorado USB 9600 USB 0x0461/0x0340 Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
Compact 4800 Direct Parport (SPP, EPP)   Complete use driver-switch mov=2 plustek_pp
(0.43)
sane-plustek_pp
Compact 4800 Direct-30 Parport (SPP, EPP)   Complete same as OpticPro 4830P, use driver-switch mov=7 plustek_pp
(0.43)
sane-plustek_pp
Compact 4800 SCSI SCSI   Complete Mustek 600 II CD compatible mustek
(1.0-138)
sane-mustek
Compact 9600 Direct-30 Parport (SPP, EPP)   Complete same as OpticPro 9630P plustek_pp
(0.43)
sane-plustek_pp
G2-300 USB 0x0461/0x0300 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
G2-300 #2 USB 0x0461/0x0302 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
G2-600 USB 0x0461/0x0380 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
G2-600 #2 USB 0x0461/0x0382 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
G2E-300 USB 0x0461/0x0301 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
G2E-300 #2 USB 0x0461/0x0303 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
G2E-600 USB 0x0461/0x0383 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
Jewel 4800 SCSI   Good sub model VM356A teco2
(1.0-9)
sane-teco2
OneTouch 5300 Parport   Unsupported Not supported. unsupported
(2010-06-09)
?
Onetouch 8920 USB 0x0461/0x0371 Unsupported Not supported. Look similar to Visioneer Onetouch 8920 (same USB product id). unsupported
(2010-06-09)
?
PagePartner Parport (EPP/ECP)   Basic Sheetfed scanner, work in gray and color, but uncalibrated scans p5
(1)
sane-p5
Primascan Colorado 2600u USB 0x0461/0x0347 Unsupported Unsupported. Same as Visioneer Onetouch 4400. See link for details. unsupported
(2010-06-09)
?
Profi 9600 SCSI   Basic sub model VM6575 teco2
(1.0-9)
sane-teco2
Profi 19200 SCSI   Good sub model VM6586 teco2
(1.0-9)
sane-teco2
ReadyScan 636i USB 0x0461/0x0381 Unsupported Probably unsupported. No details known. unsupported
(2010-06-09)
?
Slim-Line 1200 USB   Unsupported Maybe GL646. Maybe similar to Medion MD 6228? unsupported
(2010-06-09)
?

Manufacturer: Prolink

Link(s): http://www.fida.com/

Model Interface USB id Status Comment Backend Manpage
Winscan Pro 2000 USB Parport   Unsupported Not supported. No further information available. unsupported
(2010-06-09)
?
Winscan Pro 2448U USB 0x06dc/0x0014 Unsupported Not supported. Some information is available. RealTek RTS8801. unsupported
(2010-06-09)
?

Manufacturer: Quato

Link(s): http://www.quato.de/

Model Interface USB id Status Comment Backend Manpage
X-Finity SCSI   Unsupported Probably not supported. No details yet. Originally manufactured by PFU? unsupported
(2010-06-09)
?
X-Finity Ultra USB IEEE-1394   Unsupported Probably not supported. No details yet. unsupported
(2010-06-09)
?

Manufacturer: Reflecta

Model Interface USB id Status Comment Backend Manpage
DigitDia 3600 USB IEEE-1394 0x05e3/0x0142 Unsupported Film scanner that can scan directly from the magazine. unsupported
(2010-06-09)
?
iScan 1800 USB 0x05e3/0x0120 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
ProScan 4000 USB IEEE-1394 0x05e3/0x0143 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Relisys

Link(s): http://www.relisys.com/, http://www.tecoimage.com.tw/

Model Interface USB id Status Comment Backend Manpage
APOLLO Express 3 SCSI   Basic sub model VM356A teco2
(1.0-9)
sane-teco2
APOLLO Express 6 SCSI   Good sub model VM6565 teco2
(1.0-9)
sane-teco2
AVEC 2400 SCSI   Complete sub model VM3520 teco1
(1.0-10)
sane-teco1
AVEC 2412 SCSI   Complete sub model VM3520+ teco1
(1.0-10)
sane-teco1
AVEC 4800 SCSI   Untested sub model VM4530 teco1
(1.0-10)
sane-teco1
AVEC 4816 SCSI   Untested sub model VM4530+ teco1
(1.0-10)
sane-teco1
AVEC II E3 Parport   Unsupported Parport version of AVEC II S3?. See bug #304992 for details unsupported
(2010-06-09)
?
AVEC II S3 SCSI   Good sub model VM3564 teco2
(1.0-9)
sane-teco2
AVEC Super 3 SCSI   Untested sub model VM3575 teco2
(1.0-9)
sane-teco2
Eclipse 1200U USB 0x0475/0x0103 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
Episode USB 0x0475/0x0103 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?
Infinity Scorpio SCSI   Good sub model VM3552 teco3
(1.0-1)
sane-teco3
RELI 2400 SCSI   Untested sub model VM3530 teco1
(1.0-10)
sane-teco1
RELI 2412 SCSI   Complete sub model VM3530+ teco1
(1.0-10)
sane-teco1
RELI 4816 SCSI   Complete sub model VM4540 teco1
(1.0-10)
sane-teco1
RELI 4830 SCSI   Good sub model VM4542 teco1
(1.0-10)
sane-teco1
RELI 9600 SCSI   Untested sub model VM6530 teco1
(1.0-10)
sane-teco1
RELI 9612 SCSI   Untested sub model VM6530* teco1
(1.0-10)
sane-teco1
RELI 9624 SCSI   Untested sub model VM6530+ teco1
(1.0-10)
sane-teco1
RELI 9630 SCSI   Untested sub model VM6540 teco1
(1.0-10)
sane-teco1
RELI DS6 SCSI   Untested sub model VM3420 teco1
(1.0-10)
sane-teco1
RELI DS15 SCSI   Untested sub model VM3440 teco1
(1.0-10)
sane-teco1
SCORPIO Pro SCSI   Good sub model VM6575 teco2
(1.0-9)
sane-teco2
SCORPIO Pro-S SCSI   Untested sub model VM6586 teco2
(1.0-9)
sane-teco2
SCORPIO Super 3 SCSI   Good sub model VM3575 teco2
(1.0-9)
sane-teco2
Scorpio Ultra 3 USB 0x0475/0x0210 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: RevScan

Model Interface USB id Status Comment Backend Manpage
19200i USB 0x07b3/0x0400 Good Similar to Plustek OpticPro 1248U gt68xx
(1.0-84)
sane-gt68xx
RevScan Orange R48Ti USB 0x07b3/0x0001 Basic Rebadged Plustek OpticPro UT12 u12
(0.02)
sane-u12

Manufacturer: Ricoh

Link(s): http://www.ricoh.com/

Model Interface USB id Status Comment Backend Manpage
IS-410 SCSI   Untested Untested, please report! ibm
(1.0-4)
sane-ibm
IS-410 SCSI   Untested Untested, please report! hs2p
(1.00)
sane-hs2p
IS-420 SCSI   Basic Works at least in flatbed mode. ibm
(1.0-4)
sane-ibm
IS-430 SCSI   Untested Untested, please report! ibm
(1.0-4)
sane-ibm
IS-430 SCSI   Untested Untested, please report! hs2p
(1.00)
sane-hs2p
IS450 SCSI   Complete All major scanning-related features are supported (except for IPU). Certain non-scanning features, such as those related to scanner maintenance, are not supported. Such features would be better implemented in a separate stand-alone tool. For instance, if you replace the ADF Unit, you must recalibrate the scanner optics using a Ricoh Test Sheet and reset the E^2PROM registers. Reports are welcome. hs2p
(1.00)
sane-hs2p
Ricoh IS50 SCSI   Basic   ricoh
(unmaintained)
sane-ricoh
Ricoh IS60 SCSI   Basic   ricoh
(unmaintained)
sane-ricoh

Manufacturer: Samsung

Link(s): http://www.samsung.com

Model Interface USB id Status Comment Backend Manpage
C460 USB 0x04e8/0x3468 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-2160 USB 0x04e8/0x3425 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-3160 USB 0x04e8/0x341c Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-3170fn (CLX-3170 Series) USB 0x04e8/0x342a Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-3175FW USB 0x04e8/0x342a Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-3185 USB 0x04e8/0x343d Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-3300 Series USB 0x04e8/0x3456 Basic   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-4190 USB 0x04e8/0x345a Minimal   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-6200 USB 0x04e8/0x3427 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-6220 USB 0x04e8/0x343a Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-6240 USB 0x04e8/0x3428 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-6250 USB 0x04e8/0x343b Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-6260 USB 0x04e8/0x3455 Minimal   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-8380 USB 0x04e8/0x3421 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-8385 USB 0x04e8/0x3439 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-8385X USB 0x04e8/0x3444 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
CLX-8540 USB 0x04e8/0x343f Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
M267x 287x Series USB 0x04e8/0x3461 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
M337x 387x 407x Series USB 0x04e8/0x3460 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
MFP-65x USB 0x04e8/0x3435 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
MFP-560 USB 0x04e8/0x340e Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
MFP-750 USB 0x04e8/0x340f Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4x16 USB 0x04e8/0x3409 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4x20 USB 0x04e8/0x3412 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4x21 USB 0x04e8/0x3419 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4x26 USB 0x04e8/0x3432 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-5x30 USB 0x04e8/0x341a Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-6x20 USB 0x04e8/0x340d Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-6x22 USB 0x04e8/0x341d Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-6x45 USB 0x04e8/0x3420 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-6x55 USB 0x04e8/0x3429 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-6x55X USB 0x04e8/0x3443 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-470x USB 0x04e8/0x3457 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-681x USB 0x04e8/0x3466 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-3205W (SCX-3200 Series) USB Ethernet 0x04e8/0x3441 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-3400 USB 0x04e8/0x344f Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-3405W Ethernet   Basic   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4100 USB 0x04e8/0x3413 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4200 USB 0x04e8/0x341b Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4300 USB 0x04e8/0x342e Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4500 USB 0x04e8/0x3426 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4500W USB Ethernet 0x04e8/0x342b Basic   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4600 USB 0x04e8/0x3433 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4623 USB 0x04e8/0x3434 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4623FW USB 0x04e8/0x3440 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4650 4x21S Series USB 0x04e8/0x345b Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4725FN USB 0x04e8/0x341f Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
SCX-4729FD USB 0x04e8/0x3453 Basic   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4824 (SCX-4x24 Series) USB 0x04e8/0x342c Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4825FN (SCX-4x25 Series) USB 0x04e8/0x343c Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4828FN (SCX-4x28 Series) USB 0x04e8/0x342d Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4833FD USB 0x04e8/0x344b Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-4835FD Ethernet 0x04e8/0x344b Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-5635 USB 0x04e8/0x3430 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-5835_5935 USB 0x04e8/0x342f Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-5835_5935X USB 0x04e8/0x3446 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-6545 USB 0x04e8/0x3437 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX-6545X USB 0x04e8/0x3442 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX4725 USB 0x04e8/0x341f Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp
SCX4725-FN USB 0x04e8/0x341f Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
SF-760 USB 0x04e8/0x3450 Untested   xerox_mfp
(1.0-13)
sane-xerox_mfp

Manufacturer: Scanport

Link(s): http://www.scanport.com/

Model Interface USB id Status Comment Backend Manpage
SQ300 Parport?   Basic   microtek2
(unmaintained)
sane-microtek2
SQ2030 Parport   Basic   microtek2
(unmaintained)
sane-microtek2
SQ4836 SCSI   Basic   microtek2
(unmaintained)
sane-microtek2

Manufacturer: Scanshell

Model Interface USB id Status Comment Backend Manpage
800N USB 0x0a82/0x6605 Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Sceptre

Link(s): http://www.sceptre.com/

Model Interface USB id Status Comment Backend Manpage
Vividscan S1200 SCSI   Basic   sceptre
(1.0-10)
sane-sceptre

Manufacturer: Sharp

Link(s): http://sharp-world.com/

Model Interface USB id Status Comment Backend Manpage
JX-250 SCSI   Good   sharp
(0.32)
sane-sharp
JX-320 SCSI   Good   sharp
(0.32)
sane-sharp
JX-325 SCSI   Untested   sharp
(0.32)
sane-sharp
JX-330 SCSI   Good   sharp
(0.32)
sane-sharp
JX-350 SCSI   Good   sharp
(0.32)
sane-sharp
JX-610 SCSI   Good   sharp
(0.32)
sane-sharp

Manufacturer: Sicos

Model Interface USB id Status Comment Backend Manpage
DMS 2000 proprietary   Unsupported Not supported until now. Work on a backend has started, contact the author for details (see link) unsupported
(2010-06-09)
?

Manufacturer: Siemens

Link(s): http://www.siemens.com/, http://www.siemens.de/

Model Interface USB id Status Comment Backend Manpage
9036 Flatbed scanner SCSI   Basic   s9036
(unmaintained)
sane-s9036
Cherry FingerTIP ID Board - Sensor USB 0x0681/0x0010 Unsupported Not supported. unsupported
(2010-06-09)
?
ID Mouse Professional USB 0x0681/0x0005 Unsupported Not supported. unsupported
(2010-06-09)
?
S9036 SCSI   Untested gray only agfafocus
(unmaintained)
sane-agfafocus
ST400 SCSI   Basic 6 bit gray st400
(1.6)
sane-st400
ST800 SCSI   Basic 6 bit gray st400
(1.6)
sane-st400

Manufacturer: SmartDisk

Model Interface USB id Status Comment Backend Manpage
SmartScan 3600 USB IEEE-1394   Unsupported Probably not supported. Same as PIE Primefilm 2600 PRO. unsupported
(2010-06-09)
?

Manufacturer: Spot Technology

Comment: Spot seems have gone out of business.

Model Interface USB id Status Comment Backend Manpage
Maxiscan A4 proprietary   Unsupported Not supported until now. Work on a backend has started, see link for more information. unsupported
(2010-06-09)
?
ScanTak 2c proprietary   Unsupported Not supported. Work on a backend has started, see link for more information. unsupported
(2010-06-09)
?
ScanTak 3c proprietary   Unsupported Not supported. Work on a backend has started, see link for more information. unsupported
(2010-06-09)
?

Manufacturer: Syscan

Link(s): http://www.syscaninc.com/

Model Interface USB id Status Comment Backend Manpage
DocketPort 465 USB 0x0a82/0x4802 Untested All resolution and mode should be supported, but uncorrected scans genesys
(1.0-63)
sane-genesys
DocketPort 485 USB 0x0a82/0x4810 Basic All resolution and mode supported, front- and backside side-by-side, with backside mirrored horizontally. genesys
(1.0-63)
sane-genesys
DocketPort 665 USB 0x0a82/0x4803 Basic All resolution and mode supported, calibration is available genesys
(1.0-63)
sane-genesys
DocketPort 685/ Ambir DS685 USB 0x0a82/0x480c Good All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally. genesys
(1.0-63)
sane-genesys
TravelScan 460/464 USB 0x0a82/0x4600 Complete   plustek
(0.52)
sane-plustek
TravelScan 662 USB 0x0a82/0x6620 Complete   plustek
(0.52)
sane-plustek
TravelScan FS-531 USB 0x0a82/0x0530 Unsupported Not supported. May work with the Plustek backend in future. See link for details. unsupported
(2010-06-09)
?
TravelScan Pro USB 0x0a82/0x2000 Unsupported Probably not supported. Some information is available. unsupported
(2010-06-09)
?

Manufacturer: Tamarack

Model Interface USB id Status Comment Backend Manpage
Artiscan 2400FS USB 0x05e3/0x0100 Unsupported Unsupported. See link for more information. unsupported
(2010-06-09)
?
Artiscan 6000C SCSI   Good 3 pass, 300 DPI tamarack
(unmaintained)
sane-tamarack
Artiscan 8000C SCSI   Good 3 pass, 400 DPI tamarack
(unmaintained)
sane-tamarack
Artiscan 9600 Parport   Unsupported Unsupported at the moment. See link for a project for that scanner taht may support it in future. unsupported
(2010-06-09)
?
Artiscan 9600 pro 36 Parport   Unsupported Unsupported at the moment. See link for a project for that scanner. unsupported
(2010-06-09)
?
Artiscan 12000C SCSI   Good 3 pass, 600 DPI tamarack
(unmaintained)
sane-tamarack

Manufacturer: Targa

Model Interface USB id Status Comment Backend Manpage
Funline TS6 EP Parport (EPP)   Good 300x600 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
Funline TS12 EP Parport (EPP)   Good 600x1200 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp

Manufacturer: TCE

Link(s): http://www.tce.com.br/
Comment: Brasilian vendor.

Model Interface USB id Status Comment Backend Manpage
MK600U USB 0x0461/0x0346 Unsupported Not supported. Some information is available. unsupported
(2010-06-09)
?
S450 Parport   Unsupported Not supported by SANE but is reported to work with pxscan (see link). unsupported
(2010-06-09)
?

Manufacturer: Teco

Link(s): http://www.tecoimage.com.tw/

Model Interface USB id Status Comment Backend Manpage
VM6509F USB 0x080d/0x0102 Unsupported Probably unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: Tiny

Model Interface USB id Status Comment Backend Manpage
FU661E USB 0x0461/0x0347 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: TriGem

Link(s): http://www.nikon.com/

Model Interface USB id Status Comment Backend Manpage
PowerScanII SCSI   Good OK umax
(1.0-41)
sane-umax

Manufacturer: Trust

Link(s): http://www.trust-site.com, http://www.trust-site.com/home/, http://www.trust.com
Comment: Carefully check the model names. Trust uses similar names for completely different hardware.

Model Interface USB id Status Comment Backend Manpage
240H Easy Webscan Gold USB 0x05d8/0x4007 Basic Works up to 600 dpi artec_eplus48u
(unmaintained)
sane-artec_eplus48u
240TH Easy Webscan Gold USB 0x055f/0x0218 Good Same as Mustek Bearpaw 2400 TA plus. gt68xx
(1.0-84)
sane-gt68xx
CombiScan 19200 Parport USB 0x05cb/0x1483 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
Compact Scan USB 19200 USB 0x055f/0x0006 Complete Mustek 1200 UB compatible mustek_usb
(1.0-18)
sane-mustek_usb
Compact Scan USB 19200 USB 0x05d8/0x4002 Good Works, if you have vendor id 0x055f and product id 0x0006, use the mustek_usb backend instead, similar to Mustek ScanExpress 1200 UB (Plus) gt68xx
(1.0-84)
sane-gt68xx
Direct WebScan 19200 USB 0x055f/0x021c Good Same as Mustek BearPaw 1200 CU Plus (0x021c). gt68xx
(1.0-84)
sane-gt68xx
Easy Connect 9600+ Parport (EPP)   Good 300x600 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
Easy Connect 19200+ Parport (EPP)   Good 300x600 dpi CIS scanner mustek_pp
(13)
sane-mustek_pp
Easy Scan 9600 Plus Parport   Basic Requires the program 'as6edriver' to run. as6e
(0.5)
sane-as6e
Easy Webscan 19200 USB 0x05d8/0x4006 Good   artec_eplus48u
(unmaintained)
sane-artec_eplus48u
EasyScan 19200 Parport   Unsupported   unsupported
(2010-06-09)
?
Flat Scan USB 19200 USB 0x05d8/0x4002 Good Similar to Artec Ultima 2000 gt68xx
(1.0-84)
sane-gt68xx
Imagery 1200 SCSI   Good 3-pass, Mustek Paragon MFS-6000CX compatible mustek
(1.0-138)
sane-mustek
Imagery 1200 SP SCSI   Complete Mustek Paragon MFS-6000SP compatible mustek
(1.0-138)
sane-mustek
Imagery 2400 SP SCSI   Good sub model VM3552 teco3
(1.0-1)
sane-teco3
Imagery 4800 SP SCSI   Complete Mustek Paragon 600 II CD compatible mustek
(1.0-138)
sane-mustek
Imagery 4800 SP+ SCSI   Good sub model VM3552 teco3
(1.0-1)
sane-teco3
Imagery 9600 SP SCSI   Untested sub model VM3552 teco3
(1.0-1)
sane-teco3
Office Scan USB 19200 USB 0x047b/0x1000 Complete   niash
(0.3)
sane-niash
SCSI Connect 19200 SCSI   Complete Mustek ScanExpress 12000SP compatible mustek
(1.0-138)
sane-mustek
SCSI excellence series 19200 SCSI   Complete Mustek ScanExpress 12000SP compatible mustek
(1.0-138)
sane-mustek
SCSI Scan 19200 -Excellence Series- SCSI   Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?

Manufacturer: UMAX

Link(s): http://www.umax.com/, http://www.umax.com.tw/, http://www.umax.de/en, http://www.umax-europe.com, http://www.umaxjapan.co.jp, http://www.umax.com.cn, http://www.umax.com

Model Interface USB id Status Comment Backend Manpage
Astra 600P Parport (SPP/ECP)   Unsupported untested, but should be close to 610P umax_pp
(1)
sane-umax_pp
Astra 600S SCSI   Good OK umax
(1.0-41)
sane-umax
Astra 610P Parport (SPP/ECP)   Good   umax_pp
(1)
sane-umax_pp
Astra 610S SCSI   Good OK umax
(1.0-41)
sane-umax
Astra 1200S SCSI   Good OK umax
(1.0-41)
sane-umax
Astra 1220P Parport (EPP/ECP)   Good   umax_pp
(1)
sane-umax_pp
Astra 1220S SCSI   Good OK umax
(1.0-41)
sane-umax
Astra 1220U USB 0x1606/0x0010 Good   umax1220u
(unmaintained)
sane-umax1220u
Astra 1600P Parport (EPP/ECP)   Good   umax_pp
(1)
sane-umax_pp
Astra 1600U USB 0x1606/0x0030 Good   umax1220u
(unmaintained)
sane-umax1220u
Astra 2000P Parport (EPP/ECP)   Good   umax_pp
(1)
sane-umax_pp
Astra 2000U USB 0x1606/0x0030 Good   umax1220u
(unmaintained)
sane-umax1220u
Astra 2100S SCSI   Good OK umax
(1.0-41)
sane-umax
Astra 2100U USB 0x1606/0x0130 Good   umax1220u
(unmaintained)
sane-umax1220u
Astra 2200 (SU) USB 0x1606/0x0230 Good OK, needs USB control messages umax
(1.0-41)
sane-umax
Astra 2200 (SU) SCSI   Good OK umax
(1.0-41)
sane-umax
Astra 2400S SCSI   Good OK umax
(1.0-41)
sane-umax
Astra 2500 USB 0x0461/0x0374 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
Astra 2850 USB 0x07b3/0x0601 Unsupported Probably not supported. Same IDs as Plustek OpticPro ST24. See link for details. unsupported
(2010-06-09)
?
Astra 3000 USB 0x0461/0x038a Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
Astra 3600 USB 0x0461/0x038a Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
Astra 4000 USB 0x1606/0x1030 Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
Astra 4100 USB 0x0461/0x038c Unsupported Not supported, to be added to genesys backend. unsupported
(2010-06-09)
?
Astra 4400 USB 0x1606/0x0070 Good Supports 75, 150, 300, 600 and 1200 dpi rts8891
(1.0-0)
sane-rts8891
Astra 4450 USB 0x1606/0x0070 Untested   rts8891
(1.0-0)
sane-rts8891
Astra 4500 USB 0x0638/0x0a10 Unsupported GL646 based, to be added to genesys backend. Avision iVina FB1600 clone unsupported
(2010-06-09)
?
Astra 4600 USB   Unsupported Probably not supported, no details known. unsupported
(2010-06-09)
?
Astra 4700 USB 0x0638/0x0a20 Unsupported GL646/GL660 based. Avision iVina FB1800 clone. unsupported
(2010-06-09)
?
Astra 4900 USB 0x06dc/0x0020 Minimal developing yet hp3900
(0.12)
sane-hp3900
Astra 6400 IEEE-1394   Unsupported will probably work one day umax
(1.0-41)
sane-umax
Astra 6450 IEEE-1394   Unsupported will probably work one day umax
(1.0-41)
sane-umax
Astra 6700 USB   Unsupported Not supported. No chipset information available. Same as Avision iVina FB2400. unsupported
(2010-06-09)
?
Astra MX3 USB   Good OK, needs USB control messages umax
(1.0-41)
sane-umax
Astra MX3 SCSI   Good OK umax
(1.0-41)
sane-umax
AstraSlim USB 0x080d/0x0104 Unsupported Probably not supported currently. See link for more details. unsupported
(2010-06-09)
?
AstraSlim 1200 USB 0x080d/0x0110 Unsupported See link for more details. unsupported
(2010-06-09)
?
AstraSlim 1200 SE USB 0x05d8/0x4010 Good   artec_eplus48u
(unmaintained)
sane-artec_eplus48u
AstraSlim 6000 USB 0x080d/0x0104 Unsupported Probably not supported currently. See link for more details. unsupported
(2010-06-09)
?
AstraSlim SE USB 0x05d8/0x4009 Good   artec_eplus48u
(unmaintained)
sane-artec_eplus48u
Gemini D-16 SCSI   Good OK umax
(1.0-41)
sane-umax
Mirage D-16L SCSI   Good OK umax
(1.0-41)
sane-umax
Mirage II SCSI   Good OK umax
(1.0-41)
sane-umax
Mirage IIse SCSI   Good OK umax
(1.0-41)
sane-umax
Nete3470' Parport   Unsupported Probably not supported. No details known.. unsupported
(2010-06-09)
?
PL-II SCSI   Good OK umax
(1.0-41)
sane-umax
PowerLook SCSI   Good OK, SCSI-ID=PS-2400X umax
(1.0-41)
sane-umax
Powerlook 180 USB   Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
PowerLook 270 SCSI   Unsupported incompatible umax
(1.0-41)
sane-umax
PowerLook 270plus SCSI   Unsupported incompatible umax
(1.0-41)
sane-umax
Powerlook 1000 USB USB   Unsupported Probably not supported. No further information available. unsupported
(2010-06-09)
?
PowerLook 1100 IEEE-1394   Unsupported will probably work one day umax
(1.0-41)
sane-umax
PowerLook 2000 SCSI   Good OK umax
(1.0-41)
sane-umax
PowerLook 2100XL SCSI   Good OK umax
(1.0-41)
sane-umax
PowerLook 3000 SCSI   Good OK umax
(1.0-41)
sane-umax
PowerLook III SCSI   Good OK umax
(1.0-41)
sane-umax
PSD SCSI   Good OK umax
(1.0-41)
sane-umax
Supervista S-12 SCSI   Good OK umax
(1.0-41)
sane-umax
UC 630 SCSI   Good Version 2.8 OK, others only lineart OK umax
(1.0-41)
sane-umax
UC 840 SCSI   Good Version 1.6 OK, others only lineart OK umax
(1.0-41)
sane-umax
UC 1200S SCSI   Untested may work, please test and give feedback umax
(1.0-41)
sane-umax
UC 1200SE SCSI   Good Version 3.0 OK, others unknown umax
(1.0-41)
sane-umax
UC 1260 SCSI   Good Version 1.6 OK, others unknown umax
(1.0-41)
sane-umax
UG 80 SCSI   Good OK umax
(1.0-41)
sane-umax
UG 630 SCSI   Good OK umax
(1.0-41)
sane-umax
UMAX 3400 USB 0x1606/0x0060 Complete there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x plustek
(0.52)
sane-plustek
UMAX 3400 USB 0x1606/0x0050 Complete there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x plustek
(0.52)
sane-plustek
UMAX 3450 USB 0x1606/0x0060 Complete   plustek
(0.52)
sane-plustek
UMAX 5400 USB 0x1606/0x0160 Complete   plustek
(0.52)
sane-plustek
UMAX Astranet ia101 USB 0x1606/0x0060 Complete seems to be a renamed UMAX 3400 plustek
(0.52)
sane-plustek
UMAX S-6E SCSI   Good OK umax
(1.0-41)
sane-umax
UMAX S-6EG SCSI   Good OK umax
(1.0-41)
sane-umax
UMAX S-12 SCSI   Good OK umax
(1.0-41)
sane-umax
UMAX S-12G SCSI   Good OK umax
(1.0-41)
sane-umax
UMAX VT600 SCSI   Untested may work, please test and give feedback umax
(1.0-41)
sane-umax
Vista S6 SCSI   Good OK umax
(1.0-41)
sane-umax
Vista S6E SCSI   Good OK umax
(1.0-41)
sane-umax
Vista-S8 SCSI   Good OK umax
(1.0-41)
sane-umax
Vista-T630 SCSI   Good OK for some firmwareversions, on others only lineart OK umax
(1.0-41)
sane-umax

Manufacturer: Vantas

Model Interface USB id Status Comment Backend Manpage
3000 USB 0x04a7/0x0224 Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?

Manufacturer: Visioneer

Link(s): http://www.visioneer.com/

Model Interface USB id Status Comment Backend Manpage
4800 One Touch USB 0x04a7/0x03a0 Unsupported Unsupported. See link for details. Different id compared to One Touch 4800? unsupported
(2010-06-09)
?
6200 USB 0x0461/0x0345 Unsupported Not supported. Is reported to use the E5 chipset. Uses a Primax ID. Looks similar to Primascan Colorado 2600u. unsupported
(2010-06-09)
?
6200 EPP/USB USB 0x04a7/0x0311 Unsupported Not supported. Id is from Primax? Yet another scanner with the same name? unsupported
(2010-06-09)
?
9320 USB 0x04a7/0x0420 Complete sheetfed scanner avision
(Build: 296)
sane-avision
9420 USB 0x0461/0x03a8 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
9450 USB 0x04a7/0x0421 Complete sheetfed scanner avision
(Build: 296)
sane-avision
9450 USB USB 0x04a7/0x0421 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
9450-G USB 0x04a7/0x047a Complete sheetfed scanner avision
(Build: 296)
sane-avision
9550 USB 0x04a7/0x0422 Complete sheetfed scanner avision
(Build: 296)
sane-avision
9650 USB 0x04a7/0x0390 Complete sheetfed scanner avision
(Build: 296)
sane-avision
9650-G USB 0x04a7/0x047b Complete sheetfed scanner avision
(Build: 296)
sane-avision
9750 USB 0x04a7/0x0423 Complete sheetfed scanner avision
(Build: 296)
sane-avision
9750-G USB 0x04a7/0x0493 Complete sheetfed scanner avision
(Build: 296)
sane-avision
DocuImage 620S SCSI   Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
DocuMate 510 USB 0x04a7/0x047c Unsupported Not supported. See link for more details. Yet another USB id. unsupported
(2010-06-09)
?
DocuMate 510 USB 0x04a7/0x0446 Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
One Touch 4800 USB 0x04a7/0x0224 Unsupported Unsupported. See link for details. Different id compared to 4800 One Touch? unsupported
(2010-06-09)
?
Onetouch 4400 USB 0x0461/0x0347 Unsupported Not supported. E5 chipset? See link for more details. unsupported
(2010-06-09)
?
OneTouch 4800 USB USB 0x04a7/0x0224 Unsupported Unsupported. Seems to use Realtek RTS8801B. Same as Microtek Scanport 3000. See link for details. unsupported
(2010-06-09)
?
OneTouch 5300 USB 0x04a7/0x0221 Unsupported Not supported. Yet another scanner with this name? unsupported
(2010-06-09)
?
OneTouch 5300 USB USB 0x04a7/0x0226 Unsupported Not supported. Chipset is RTS8801B(?). See link for output of /proc/bus/usb/devices. unsupported
(2010-06-09)
?
OneTouch 5800 USB USB 0x04a7/0x0226 Unsupported Unsupported. 48 bit scanner, doesn't work with viceo backend. RTS8801C. unsupported
(2010-06-09)
?
OneTouch 6600 USB 0x04a7/0x022a Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
Onetouch 7100 USB 0x04a7/0x0229 Unsupported GL646 based, to be added to genesys backend unsupported
(2010-06-09)
?
OneTouch 7300 USB 0x04a7/0x0444 Good Works upto 1200 dpi and 12 bits/color. gt68xx
(1.0-84)
sane-gt68xx
Onetouch 7700 USB 0x04a7/0x0380 Unsupported LM9832/3 based, to be added to plustek backend unsupported
(2010-06-09)
?
OneTouch 8100 USB 0x04a7/0x0321 Unsupported Unsupported. See link for details. unsupported
(2010-06-09)
?
Onetouch 8700 USB 0x04a7/0x0371 Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
Onetouch 8900 USB 0x04a7/0x0371 Unsupported Not supported. Same as 8920 but without TA? unsupported
(2010-06-09)
?
Onetouch 8920 USB 0x04a7/0x0371 Unsupported Not supported. Same as 8700 and 8900 but includes a TA. Uses a Primax ID. Chipset is RTS8801C. See link for output of /proc/bus/usb/devices. unsupported
(2010-06-09)
?
Onetouch 9000 USB 0x04a7/0x022c Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
Onetouch 9020 USB 0x04a7/0x022c Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
Onetouch 9320 USB 0x04a7/0x0362 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
Onetouch Pro 8800 USB 0x04a7/0x0410 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
Onetouch Pro 8820 USB 0x04a7/0x0410 Unsupported Probably not supported. See link for details. unsupported
(2010-06-09)
?
PaperPort 3100b Parport   Unsupported Most probably not supported. See link for details. unsupported
(2010-06-09)
?
PaperPort 6100 Parport   Unsupported Most probably not supported. More details would be appreciated. unsupported
(2010-06-09)
?
PaperPort OneTouch Parport   Unsupported Most probably not supported. See link for details. unsupported
(2010-06-09)
?
Patriot 430 USB 0x04a7/0x0497 Complete sheetfed scanner avision
(Build: 296)
sane-avision
Patriot 470 USB 0x04a7/0x048f Complete sheetfed scanner avision
(Build: 296)
sane-avision
Patriot 680 USB 0x04a7/0x0498 Complete sheetfed scanner avision
(Build: 296)
sane-avision
Patriot 780 USB 0x04a7/0x0499 Complete sheetfed scanner avision
(Build: 296)
sane-avision
Roadwarrior USB 0x04a7/0x0494 Basic All resolution and mode supported, calibration is available genesys
(1.0-63)
sane-genesys
Strobe Pro USB USB 0x04a7/0x0102 Unsupported Not supported. See link for details. unsupported
(2010-06-09)
?
Strobe XP 100 USB 0x04a7/0x0427 Basic   plustek
(0.52)
sane-plustek
Strobe XP 100,r3 USB 0x04a7/0x049b Good All resolution and mode supported, calibration is available genesys
(1.0-63)
sane-genesys
Strobe XP 200 USB 0x04a7/0x0426 Good All resolution and mode supported, calibration is available genesys
(1.0-63)
sane-genesys
Strobe XP 300 USB 0x04a7/0x0474 Good All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally. genesys
(1.0-63)
sane-genesys
Strobe XP 450 USB 0x04a7/0x0424 Complete sheetfed scanner avision
(Build: 296)
sane-avision
Strobe XP 450-G USB 0x04a7/0x0491 Complete sheetfed scanner avision
(Build: 296)
sane-avision
Strobe XP 470 USB 0x04a7/0x0479 Complete sheetfed scanner avision
(Build: 296)
sane-avision
Strobe XP 470-G USB 0x04a7/0x048f Complete sheetfed scanner avision
(Build: 296)
sane-avision
Visioneer OneTouch 7100 USB 0x04a7/0x0229 Complete Same as MD5345 genesys
(1.0-63)
sane-genesys
WorkCentre 470cx Parport   Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
WorkCentre M15i USB 0x0924/0xffef Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
WorkCentre PE16 USB Parport 0x0924/0x4220 Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
WorkCentre PE120i USB 0x0924/0x4237 Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
WorkCentre Pro 412 USB Parport 0x043d/0x4303 Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
WorkCentre XK35c USB Parport 0x043d/0x0020 Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?
WorkCentre XK50cx USB 0x04e8/0x3903 Unsupported Not supported. See link for more details. unsupported
(2010-06-09)
?

Manufacturer: Viviscan

Model Interface USB id Status Comment Backend Manpage
Compact II Parport (EPP)   Good 300 dpi CCD scanner mustek_pp
(13)
sane-mustek_pp

Manufacturer: Vobis

Link(s): http://www.vobis.de/

Model Interface USB id Status Comment Backend Manpage
HighScan SCSI   Complete only E3plus based models microtek2
(unmaintained)
sane-microtek2
Highscreen Realscan SCSI   Good   microtek
(0.13.1)
sane-microtek
Highscreen Scanboostar Premium SCSI   Good OK, SCSI-ID=LinoHell Office2 umax
(1.0-41)
sane-umax

Manufacturer: Vuego

Comment: Company was renamed to Benq.

Manufacturer: Xerox

Link(s): http://www.xerox.com/, http://www.office.xerox.com/

Model Interface USB id Status Comment Backend Manpage
2400 Onetouch USB 0x0461/0x038b Complete GL646 based, resolution from 75 to 2400 dpi genesys
(1.0-63)
sane-genesys
DocuMate150 USB 0x04a7/0x049c Good   avision
(Build: 296)
sane-avision
DocuMate152 USB 0x04a7/0x0477 Good   avision
(Build: 296)
sane-avision
DocuMate162 USB 0x04a7/0x049d Good   avision
(Build: 296)
sane-avision
DocuMate232 USB 0x04a7/0x0476 Good   avision
(Build: 296)
sane-avision
DocuMate250 USB 0x04a7/0x0448 Good   avision
(Build: 296)
sane-avision
DocuMate250-G USB 0x04a7/0x0490 Good   avision
(Build: 296)
sane-avision
DocuMate252 USB 0x04a7/0x0449 Good   avision
(Build: 296)
sane-avision
DocuMate252-G USB 0x04a7/0x048c Good   avision
(Build: 296)
sane-avision
DocuMate262 USB 0x04a7/0x044c Good   avision
(Build: 296)
sane-avision
DocuMate262-G USB 0x04a7/0x048d Good   avision
(Build: 296)
sane-avision
DocuMate262i USB 0x04a7/0x04a7 Good   avision
(Build: 296)
sane-avision
DocuMate272 USB 0x04a7/0x0475 Untested   avision
(Build: 296)
sane-avision
DocuMate272-G USB 0x04a7/0x048e Untested   avision
(Build: 296)
sane-avision
DocuMate510 USB 0x04a7/0x0446 Untested   avision
(Build: 296)
sane-avision
DocuMate510-G USB 0x04a7/0x047c Untested   avision
(Build: 296)
sane-avision
DocuMate512 USB 0x04a7/0x0495 Untested   avision
(Build: 296)
sane-avision
DocuMate520 USB 0x04a7/0x0447 Untested   avision
(Build: 296)
sane-avision
DocuMate520-G USB 0x04a7/0x0492 Untested   avision
(Build: 296)
sane-avision
DocuMate632 USB 0x04a7/0x0498 Untested   avision
(Build: 296)
sane-avision
DocuMate752 USB 0x04a7/0x049a Untested   avision
(Build: 296)
sane-avision
DocuMate752 USB 0x04a7/0x0478 Untested   avision
(Build: 296)
sane-avision
Phaser 3200MFP USB 0x0924/0x3da4 Complete   xerox_mfp
(1.0-13)
sane-xerox_mfp
Phaser 6110MFP USB 0x0924/0x3d5d Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
Travel Scanner 100 USB 0x04a7/0x04ac Good All resolution and mode supported, calibration is available genesys
(1.0-63)
sane-genesys
WorkCentre 3119 Series USB 0x0924/0x4265 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
WorkCentre 3210 USB 0x0924/0x4293 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
WorkCentre 3220 USB 0x0924/0x4294 Good   xerox_mfp
(1.0-13)
sane-xerox_mfp
WorkCentre 4118 Series USB 0x0924/0x420c Good   xerox_mfp
(1.0-13)
sane-xerox_mfp

Manufacturer: Yakumo

Link(s): http://www.yakumo.com/

Model Interface USB id Status Comment Backend Manpage
Scan50 USB 0x05d8/0x4011 Good   artec_eplus48u
(unmaintained)
sane-artec_eplus48u

Still Cameras

Manufacturers: Kodak, Polaroid

Manufacturer: Kodak

Link(s): http://www.kodak.com/global/en/service/digCam/dc25/dc25.shtml, http://www.kodak.com/global/en/service/digCam/dc210/dc210.shtml, http://www.kodak.com/global/en/service/products/ekn006568.jhtml

Model Interface USB id Status Comment Backend Manpage
DC20 Serial port   Basic DC-20 untested by author but reported to work dc25
(1.2)
sane-dc25
DC25 Serial port   Complete   dc25
(1.2)
sane-dc25
DC210 Serial port   Basic   dc210
(0.0)
sane-dc210
DC240 Serial port   Good Use gphoto2 backend to get USB support dc240
(0.0)
sane-dc240

Manufacturer: Polaroid

Link(s): http://www.polaroid.com/

Model Interface USB id Status Comment Backend Manpage
DMC SCSI   Good   dmc
(unmaintained)
sane-dmc

Video Cameras

Manufacturers: Aiptek, Biolux, Connectix, Creative, Digital Dream, Grandtek Scopecam, Konica

Manufacturer: Aiptek

Link(s): http://www.aiptek.com.tw

Model Interface USB id Status Comment Backend Manpage
Aiptek Pencam USB 0x0553/0x0202 Minimal image is OK for CIF and QCIF, VGA and QVGA untested, streaming video is a problem stv680
(1.0-1)
sane-stv680

Manufacturer: Biolux

Model Interface USB id Status Comment Backend Manpage
654 (micrOcular) USB 0x0923/0x010f Unsupported Not supported yet. See link for more details. unsupported
(2010-06-09)
?

Manufacturer: Connectix

Model Interface USB id Status Comment Backend Manpage
Color QuickCam Parport   Good Requires root privileges. qcam
(unmaintained)
sane-qcam
Greyscale QuickCam Parport   Minimal Requires root privileges. Partly working. qcam
(unmaintained)
sane-qcam

Manufacturer: Creative

Link(s): http://www.creative.com/

Model Interface USB id Status Comment Backend Manpage
WebCam Go Mini USB 0x041e/0x4007 Untested stv680
(1.0-1)
sane-stv680

Manufacturer: Digital Dream

Link(s): http://www.digitaldreamco.com/en/index.shtml

Model Interface USB id Status Comment Backend Manpage
l' espion XS USB 0x1183/0x0001 Untested stv680
(1.0-1)
sane-stv680

Manufacturer: Grandtek Scopecam

Model Interface USB id Status Comment Backend Manpage
8x30 Binocular & Digital Camera USB 0x0797/0x801c Unsupported Not Supported yet. See link for more details. unsupported
(2010-06-09)
?

Manufacturer: Konica

Link(s): http://www.konicaminolta.com

Model Interface USB id Status Comment Backend Manpage
e-mini USB 0x04c8/0x0722 Untested stv680
(1.0-1)
sane-stv680

APIs

Backends: gphoto2, pint, pnm, test, v4l

Backend: gphoto2 (0.0)

Link(s): mailto:peter@fales-lorenz.net
Manual page: sane-gphoto2
Description: Multiple cameras supported by the gphoto2 libraries
Comment: The long-term plan is to support all the cameras supported by the gphoto2 libraries (currently over 140 models). However, at this stage, only a handful of cameras are definitely known to work with SANE. Other cameras will probably work if the native file format is EXIF or JPEG. Testers welcome!

Backend: pint (unmaintained)

Manual page: sane-pint
Description: Scanners with the machine-independent PINT interface
Comment: Haven't been tested for a long time. Handle with care.

Backend: pnm (1.0.8)

Link(s): mailto:henning@meier-geinitz.de
Manual page: sane-pnm
Description: Reads PNM files
Comment: Used for debugging frontends. Obsolete, use test backend instead.

Backend: test (1.0-28)

Link(s): http://www.meier-geinitz.de/sane/test-backend/
Manual page: sane-test
Description: Frontend-tester
Comment: Backend for testing frontends. Also serves as example for SANE backend options.

Backend: v4l (1.0-3)

Link(s): mailto:henning@meier-geinitz.de
Manual page: sane-v4l
Description: Interface to Video For Linux API
Comment: Supports video cameras and other devices accessed by the v4l kernel API, e.g. bttv devices. Quite a lot of known bugs.

Meta Backends

Backends: dll, net

Backend: dll (1.0.13)

Link(s): mailto:henning@meier-geinitz.de
Manual page: sane-dll
Description: Dynamic loading of shared-library backends.

Backend: net (1.0.14)

Link(s): http://www.penguin-breeder.org/?page=sane-net
Manual page: sane-net
Description: Network access to saned servers
Comment: Can be used to access any scanner supported by SANE over the net. Supports IPv4 and IPv6.

Legend:

Model:
Name of the device.
Interface:
How the device is connected to the computer.
USB id:
The USB vendor and product ids as printed by sane-find-scanner -q (only applicable for USB devices).
Status:
Indicates how many of the features the device provides are supported by SANE.
  • unsupported means the device is not supported at least by this backend. It may be supported by other backends, however.
  • untested means the device may be supported but couldn't be tested. Be very careful and report success/failure.
  • minimal means that the device is detected and scans at least in one mode. But the quality is bad or important features won't work.
  • basic means it works at least in the most important modes but quality is not perfect.
  • good means the device is usable for day-to-day work. Some rather exotic features may be missing.
  • complete means the backends supports everything the device can do.
Comment:
More information about the backend or model, e.g. the level of support and possible problems.
Backend:
Name of the backend, in parentheses if available: Version of backend/driver; newer versions may be available from their home sites.
NEW! means brand-new to the current release of SANE.
UNMAINTAINED means that nobody maintains that backend. Expect no new features or newly supported devices. You are welcome to take over maintainership.
Manual Page:
A link to the man-page online, if it exists.
Manufacturer:
Manufacturer, vendor or brand name of the device.
Description:
The scope of application of the backend.

SANE homepage
Contact
This page was last updated on Wed Jul 31 07:52:48 2013 by sane-desc 3.5 from sane-backends 1.0.24git sane-backends-1.0.27/testsuite/tools/data/udev.ref0000664000175000017500000030173312775312262017003 00000000000000# This file was automatically created based on description files (*.desc) # by sane-desc 3.5 from sane-backends 1.0.24git on Wed Jul 31 07:52:48 2013 # # udev rules file for supported USB and SCSI devices # # The SCSI device support is very basic and includes only # scanners that mark themselves as type "scanner" or # SCSI-scanners from HP and other vendors that are entitled "processor" # but are treated accordingly. # # To add a USB device, add a rule to the list below between the # LABEL="libsane_usb_rules_begin" and LABEL="libsane_usb_rules_end" lines. # # To run a script when your device is plugged in, add RUN+="/path/to/script" # to the appropriate rule. # # If your scanner isn't listed below, you can add it as explained above. # # If your scanner is supported by some external backend (brother, epkowa, # hpaio, etc) please ask the author of the backend to provide proper # device detection support for your OS # # If the scanner is supported by sane-backends, please mail the entry to # the sane-devel mailing list (sane-devel@lists.alioth.debian.org). # ACTION!="add", GOTO="libsane_rules_end" ENV{DEVTYPE}=="usb_device", GOTO="libsane_create_usb_dev" SUBSYSTEMS=="scsi", GOTO="libsane_scsi_rules_begin" SUBSYSTEM=="usb_device", GOTO="libsane_usb_rules_begin" SUBSYSTEM!="usb_device", GOTO="libsane_usb_rules_end" # Kernel >= 2.6.22 jumps here LABEL="libsane_create_usb_dev" # For Linux >= 2.6.22 without CONFIG_USB_DEVICE_CLASS=y # If the following rule does not exist on your system yet, uncomment it # ENV{DEVTYPE}=="usb_device", MODE="0664", OWNER="root", GROUP="root" # Kernel < 2.6.22 jumps here LABEL="libsane_usb_rules_begin" # Hewlett-Packard ScanJet 4100C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0101", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4200C | Hewlett-Packard ScanJet 4200Cxi | Hewlett-Packard ScanJet 4200Cse ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0105", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6200C | Hewlett-Packard ScanJet 6250C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0201", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3300c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0205", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4300c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0305", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5200C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0401", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3400c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0405", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 2100C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0505", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6300C | Hewlett-Packard ScanJet 6350C | Hewlett-Packard ScanJet 6390C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0601", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 2200C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0605", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5300C | Hewlett-Packard ScanJet 5370C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0701", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard scanjet 4400c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0705", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 7400c | Hewlett-Packard ScanJet 7450c | Hewlett-Packard ScanJet 7490c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0801", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard scanjet 4470c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0805", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 2300C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0901", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 2400C | Hewlett-Packard ScanJet G2410 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0a01", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 8200 | Hewlett-Packard ScanJet 8250 | Hewlett-Packard ScanJet 8290 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0b01", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5400c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1005", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5470c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1105", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4500C | Hewlett-Packard ScanJet 5550C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1205", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4570C | Hewlett-Packard ScanJet 5500C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1305", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3670C | Hewlett-Packard ScanJet 3690C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1405", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5590 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1705", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 7650 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1805", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4850C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="1b05", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3530C | Hewlett-Packard ScanJet 3570C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2005", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3500C ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2205", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3970c ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2305", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4070 Photosmart ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2405", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 3800 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2605", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G2710 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="2805", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 8300 | Hewlett-Packard ScanJet 8350 | Hewlett-Packard ScanJet 8390 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3805", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 8270 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3905", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard LaserJet M1005 MFP ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="3b17", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4370 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4105", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G3010 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4205", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G3110 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4305", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G4010 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4505", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet G4050 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4605", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet N6310 ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="4705", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard LaserJet M1120 MFP ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="5617", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard LaserJet M1120n MFP ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="5717", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 ATTRS{idVendor}=="0400", ATTRS{idProduct}=="1000", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 | Mustek BearPaw 2400 ATTRS{idVendor}=="0400", ATTRS{idProduct}=="1001", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 5100 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4025", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 5300 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4026", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 5500 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4027", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 5000 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4028", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 3300 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4031", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 5 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4032", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 7 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="403e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 9 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="403f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 5200 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4041", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 3200 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4043", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 4100 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4053", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 6100 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4054", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 7200 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4056", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP C110 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4057", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP C115 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4058", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 2150 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4059", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP C310 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="405d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP C315 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="405e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Advent AW10 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4060", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak Hero Office 6.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4062", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak Hero 7.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4063", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak Hero 5.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4064", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 9200 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4065", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak ESP 2170 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4066", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak Hero 9.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="4067", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak Hero 3.1 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="406d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak i30 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6001", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak i40 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6002", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak i50 | Kodak i55 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6003", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak i60 | Kodak i65 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6004", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kodak i80 ATTRS{idVendor}=="040a", ATTRS{idProduct}=="6005", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Creative WebCam Go Mini ATTRS{idVendor}=="041e", ATTRS{idProduct}=="4007", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Lexmark X70 | Lexmark X73 ATTRS{idVendor}=="043d", ATTRS{idProduct}=="002d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Lexmark X74 ATTRS{idVendor}=="043d", ATTRS{idProduct}=="0060", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Lexmark X1110 | Lexmark X1130 | Lexmark X1140 # Lexmark X1150 | Lexmark X1170 | Lexmark X1180 # Lexmark X1185 | Lexmark X1195 ATTRS{idVendor}=="043d", ATTRS{idProduct}=="007c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Lexmark X12xx ATTRS{idVendor}=="043d", ATTRS{idProduct}=="007d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius ColorPage HR6 V1 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2004", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage HR6 V2 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2007", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage HR6 V2 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2008", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage HR6A ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2009", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage Vivid3x | Genius Colorpage Vivid3 V2 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2011", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage HR7 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2013", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage Vivid4 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2014", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage HR7LE ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2015", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage HR6X ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2016", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage Vivid3xe ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2017", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage Vivid4xe ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage Vivid4x ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage Vivid 1200 X ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius ColorPage Slim 1200 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage Vivid 1200 XE ATTRS{idVendor}=="0458", ATTRS{idProduct}=="201f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Genius Colorpage SF600 ATTRS{idVendor}=="0458", ATTRS{idProduct}=="2021", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Medion/Lifetec/Tevion/Cytron MD5345 | Medion/Lifetec/Tevion/Cytron MD6228 | Medion/Lifetec/Tevion/Cytron MD6471 ATTRS{idVendor}=="0461", ATTRS{idProduct}=="0377", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox 2400 Onetouch ATTRS{idVendor}=="0461", ATTRS{idProduct}=="038b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Trust Office Scan USB 19200 ATTRS{idVendor}=="047b", ATTRS{idProduct}=="1000", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4300c/Silitek ATTRS{idVendor}=="047b", ATTRS{idProduct}=="1002", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Kyocera FS-1016MFP ATTRS{idVendor}=="0482", ATTRS{idProduct}=="0335", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Compaq S4-100 ATTRS{idVendor}=="049f", ATTRS{idProduct}=="001a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 310U ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="1a20", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 620U ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="1a2a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 320U | Benq (Acer) 340U | Mitsubishi Diamondview 648UT ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2022", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 620UT ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2040", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 640U | Guillemot / Hercules Maxi Scan A4 USB 640U | Guillemot / Hercules Maxi A4 36 bit ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2060", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 640bu ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="207e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 3300 | Benq (Acer) 4300 | Mitsubishi Diamondview 650U ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20b0", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 640BT ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20be", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 1240 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20c0", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 3300 | Benq (Acer) 4300 | Guillemot / Hercules Scan@home Touch 1248 (USB) ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20de", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 5000 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20f8", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 5000E | Benq (Acer) 5000U ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20fc", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 5300 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="20fe", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Benq (Acer) 5150 | Benq (Acer) 5250 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2137", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # BenQ 5550 ATTRS{idVendor}=="04a5", ATTRS{idProduct}=="2211", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Visioneer OneTouch 7100 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0229", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer 9650 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0390", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer 9320 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0420", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer 9450 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0421", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer 9550 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0422", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer 9750 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0423", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Strobe XP 450 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0424", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Strobe XP 200 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0426", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Strobe XP 100 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0427", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer OneTouch 7300 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0444", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate510 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0446", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate520 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0447", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate250 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0448", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate252 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0449", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate262 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="044c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Strobe XP 300 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0474", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate272 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0475", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate232 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0476", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate152 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0477", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate752 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0478", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Strobe XP 470 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0479", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer 9450-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="047a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer 9650-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="047b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate510-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="047c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate252-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="048c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate262-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="048d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate272-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="048e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Strobe XP 470-G | Visioneer Patriot 470 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="048f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate250-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0490", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Strobe XP 450-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0491", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate520-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0492", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer 9750-G ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0493", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Roadwarrior ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0494", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate512 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0495", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Patriot 430 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0497", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Patriot 680 | Xerox DocuMate632 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0498", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Patriot 780 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="0499", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate752 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="049a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Visioneer Strobe XP 100,r3 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="049b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate150 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="049c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate162 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="049d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox DocuMate262i ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="04a7", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox Travel Scanner 100 ATTRS{idVendor}=="04a7", ATTRS{idProduct}=="04ac", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-2080C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1601", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CR-180 | Canon CR-180II ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1602", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-9080C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1603", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-7080C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1604", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-5010C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1606", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-6080 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1607", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-2580C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1608", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-3080CII ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1609", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-2050C | Canon DR-2050SP ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="160a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-7580 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="160b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP750 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1706", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP780 | Canon PIXMA MP790 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1707", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP760 | Canon PIXMA MP770 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1708", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP150 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1709", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP170 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP450 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP500 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP800 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP800R ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="170e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP530 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1712", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP830 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1713", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP160 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1714", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP180 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1715", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP460 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1716", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP510 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1717", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP600 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1718", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP600R ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1719", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP810 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="171a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP960 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="171b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX7600 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="171c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP210 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1721", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP220 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1722", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP470 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1723", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP520 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1724", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP610 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1725", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP970 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1726", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX300 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1727", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX310 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1728", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX700 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1729", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP140 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX850 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP980 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP630 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP620 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="172f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP540 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1730", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP480 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1731", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP240 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1732", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP260 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1733", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP190 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1734", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX860 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1735", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX320 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1736", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX330 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1737", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP250 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP270 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP490 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP550 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP560 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP640 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP990 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1740", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX340 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1741", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX350 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1742", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX870 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1743", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP280 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1746", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP495 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1747", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG5100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1748", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG5200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1749", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG6100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG8100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX360 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX410 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX420 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="174f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX880 Series | Canon PIXMA MX882 | Canon PIXMA MX885 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1750", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG2100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1751", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG3100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1752", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG4100 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1753", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG5300 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1754", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG6200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1755", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG8200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1756", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP493 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1757", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA E500 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1758", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX370 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1759", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA E600 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX430 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX510 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX710 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX890 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP230 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="175f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG2200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1760", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA E510 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1761", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG3200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1762", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG4200 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1763", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG5400 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1764", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MG6300 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1765", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX390 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1766", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA E610 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1767", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX450 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1768", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX520 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1769", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX720 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="176a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MX920 Series ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="176b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan 8800F ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1901", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 100 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1904", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 200 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1905", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan 700F ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1907", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan 9000F ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1908", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 110 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="1909", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 210 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="190a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan 9000F Mark II ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="190d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan fb630u | Canon CanoScan fb636u ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2204", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan N650U/N656U ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2206", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan N1220U ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2207", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan D660U ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2208", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan N670U/N676U/LiDE20 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="220d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan N1240U/LiDE30 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="220e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 35 | Canon CanoScan LiDE 40 | Canon CanoScan LiDE 50 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2213", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan LiDE 60 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="221c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CanoScan LiDE25 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2220", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-1210C ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2222", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP730 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="262f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP700 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2630", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP360 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="263c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP370 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="263d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP390 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="263e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP375R ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="263f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP740 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="264c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon PIXMA MP710 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="264d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF5630 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="264e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon laserBase MF5650 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="264f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF8170c ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2659", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF5730 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="265d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF5750 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="265e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF5770 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="265f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF3110 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2660", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF3240 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2684", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF6500 series | Canon imageCLASS MF6550 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2686", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF4120 | Canon imageCLASS MF4122 | Canon imageCLASS MF4140 # Canon imageCLASS MF4150 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26a3", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF4660 | Canon imageCLASS MF4690 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26b0", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF4010 | Canon imageCLASS MF4018 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26b4", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF4270 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26b5", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageRUNNER 1020/1024/1025 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26e6", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF4370dn | Canon imageCLASS MF4380dn ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26ec", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS D480 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26ed", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon I-SENSYS MF4320d | Canon I-SENSYS MF4330d | Canon imageCLASS MF4350d ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26ee", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS D420 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26ef", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon i-SENSYS MF5880dn ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26f9", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon i-SENSYS MF6680dn ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="26fa", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF8030 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2707", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon i-SENSYS MF4550d ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2736", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon imageCLASS MF4410 | Canon imageCLASS MF4430 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2737", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon i-SENSYS MF3010 ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="2759", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Nikon LS 40 ED | Nikon LS 40 ED | Nikon Coolspan IV ATTRS{idVendor}=="04b0", ATTRS{idProduct}=="4000", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Nikon LS 50 ED | Nikon Coolscan V ED | Nikon LS 50 ED # Nikon Coolscan V ED ATTRS{idVendor}=="04b0", ATTRS{idProduct}=="4001", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Nikon Super Coolscan LS-5000 ED | Nikon Super Coolscan LS-5000 ED ATTRS{idVendor}=="04b0", ATTRS{idProduct}=="4002", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 636U | Epson GT-7000U | Epson Perfection 636U ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0101", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 610 | Epson GT-6600U | Epson Perfection 610 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0103", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1200U | Epson Perfection 1200Photo | Epson GT-7600U # Epson GT-7600UF | Epson Perfection 1200U | Epson Perfection 1200U PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0104", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Stylus Scan 2000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0105", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Stylus Scan 2500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0106", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Expression 1600 | Epson ES-2000 | Epson Expression 1600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0107", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ES-8500 | Epson Expression 1640XL ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0109", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1640 | Epson GT-8700 | Epson GT-8700F # Epson Perfection 1640SU | Epson Perfection 1640SU PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1240 | Epson GT-7700U | Epson Perfection 1240U ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 640 | Epson GT-6700U | Epson Perfection 640U ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Expression 1680 | Epson ES-2200 | Epson Expression 1680 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1250 | Epson Perfection 1250Photo ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="010f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1650 | Epson GT-8200U | Epson GT-8200UF # Epson Perfection 1650 | Epson Perfection 1650 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0110", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 2450 | Epson GT-9700F | Epson Perfection 2450 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0112", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 660 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0114", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 2400 | Epson GT-9300UF | Epson Perfection 2400 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 3200 | Epson GT-9800F | Epson Perfection 3200 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1260 | Epson Perfection 1260Photo ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1660 | Epson GT-8300UF | Epson Perfection 1660 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1670 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="011f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 1270 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0120", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 2480 | Epson Perfection 2580 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0121", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 3490 | Epson Perfection 3590 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0122", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ES-7000H | Epson GT-15000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0126", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 4870 | Epson GT-X700 | Epson Perfection 4870 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0128", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ES-10000G | Epson Expression 10000XL ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0129", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 4990 | Epson GT-X800 | Epson Perfection 4990 PHOTO ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="012a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ES-H300 | Epson GT-2500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="012b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson V700 | Epson V750 | Epson GT-X900 # Epson Perfection V700 Photo | Epson Perfection V750 Photo ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="012c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson GT-X970 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0135", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-5200 | Epson CX-5400 | Epson CC-600PX # Epson Stylus CX5100 | Epson Stylus CX5200 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0801", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-3200 | Epson CC-570L | Epson Stylus CX3100 # Epson Stylus CX3200 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0802", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-6300 | Epson CX-6400 | Epson Stylus CX6300 # Epson Stylus CX6400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0805", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson RX-600 | Epson PM-A850 | Epson Stylus Photo RX600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0806", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson RX-500 | Epson Stylus Photo RX500 | Epson Stylus Photo RX510 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0807", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-5400 | Epson Stylus CX5300 | Epson Stylus CX5400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0808", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Stylus CX-1500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="080c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-4600 | Epson Stylus CX4500 | Epson Stylus CX4600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="080d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-3600 | Epson CX-3650 | Epson PX-A550 # Epson Stylus CX3500 | Epson Stylus CX3600 | Epson Stylus CX3650 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="080e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson RX-425 | Epson Stylus Photo RX420 | Epson Stylus Photo RX425 # Epson Stylus Photo RX430 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="080f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson RX-700 | Epson PM-A900 | Epson Stylus Photo RX700 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0810", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson RX-620 | Epson PM-A870 | Epson Stylus Photo RX620 # Epson Stylus Photo RX630 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0811", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-6500 | Epson CX-6600 | Epson Stylus CX6500 # Epson Stylus CX6600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0813", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A700 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0814", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson AcuLaser CX11 | Epson AcuLaser CX11NF | Epson AcuLaser CX11 # Epson AcuLaser CX11NF | Epson LP-A500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0815", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson LP-M5500 | Epson LP-M5500F ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0817", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson DX-3850 | Epson CX-3700 | Epson CX-3800 # Epson DX-3800 | Epson Stylus CX3700 | Epson Stylus CX3800 # Epson Stylus DX3800 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0818", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-4800 | Epson PX-A650 | Epson Stylus CX4700 # Epson Stylus CX4800 | Epson Stylus DX4800 | Epson Stylus DX4850 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0819", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A750 | Epson Stylus Photo RX520 | Epson Stylus Photo RX530 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="081a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A890 | Epson Stylus Photo RX640 | Epson Stylus Photo RX650 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="081c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A950 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="081d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Stylus CX7700 | Epson Stylus CX7800 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="081f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-4200 | Epson Stylus CX4100 | Epson Stylus CX4200 # Epson Stylus DX4200 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0820", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A820 | Epson Stylus Photo RX560 | Epson Stylus Photo RX580 # Epson Stylus Photo RX590 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0827", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A970 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0828", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-T990 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0829", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A920 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="082a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson CX-5000 | Epson DX-5000 | Epson DX-5050 # Epson Stylus CX4900 | Epson Stylus CX5000 | Epson Stylus DX5000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="082b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson DX-6000 | Epson PX-A720 | Epson Stylus CX5900 # Epson Stylus CX6000 | Epson Stylus DX6000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="082e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson DX-4050 | Epson PX-A620 | Epson Stylus CX3900 # Epson Stylus DX4000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="082f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ME 200 | Epson Stylus CX2800 | Epson Stylus CX2900 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0830", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson LP-M5600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0833", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson LP-M6000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0834", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson AcuLaser CX21 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0835", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-T960 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0836", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A940 | Epson Stylus Photo RX680 | Epson Stylus Photo RX685 # Epson Stylus Photo RX690 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0837", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson DX-7400 | Epson PX-A640 | Epson Stylus CX7300 # Epson Stylus CX7400 | Epson Stylus DX7400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0838", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PX-A740 | Epson Stylus CX8300 | Epson Stylus CX8400 # Epson Stylus DX8400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0839", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PX-FA700 | Epson Stylus CX9300F | Epson Stylus CX9400Fax # Epson Stylus DX9400F ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="083a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PM-A840 | Epson PM-A840S | Epson Stylus Photo RX585 # Epson Stylus Photo RX595 | Epson Stylus Photo RX610 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="083c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ME 300 | Epson PX-401A | Epson Stylus NX100 # Epson Stylus SX100 | Epson Stylus TX100 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0841", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson LP-M5000 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0843", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Artisan 800 | Epson EP-901A | Epson EP-901F # Epson Stylus Photo PX800FW | Epson Stylus Photo TX800FW ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0844", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Artisan 700 | Epson EP-801A | Epson Stylus Photo PX700W # Epson Stylus Photo TX700W ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0846", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ME Office 700FW | Epson PX-601F | Epson Stylus Office BX600FW # Epson Stylus Office TX600FW | Epson Stylus SX600FW | Epson WorkForce 600 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0847", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ME Office 600F | Epson Stylus Office BX300F | Epson Stylus Office TX300F # Epson Stylus NX300 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0848", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Stylus NX200 | Epson Stylus SX200 | Epson Stylus SX205 # Epson Stylus TX200 | Epson Stylus TX203 | Epson Stylus TX209 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0849", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PX-501A | Epson Stylus NX400 | Epson Stylus SX400 # Epson Stylus SX405 | Epson Stylus TX400 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="084a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson WorkForce 500 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="084c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PX-402A | Epson Stylus NX110 Series | Epson Stylus SX110 Series # Epson Stylus TX110 Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="084d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ME OFFICE 510 | Epson Stylus NX210 Series | Epson Stylus SX210 Series # Epson Stylus TX210 Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="084f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Stylus NX410 Series | Epson Stylus SX410 Series | Epson Stylus TX410 Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0851", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson ME OFFICE 650FN Series | Epson Stylus Office BX310FN Series | Epson Stylus Office TX510FN Series # Epson WorkForce 310 Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0854", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson PX-502A | Epson Stylus NX510 Series | Epson Stylus SX510W Series # Epson Stylus TX550W Series ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="0856", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Stylus SX125 ATTRS{idVendor}=="04b8", ATTRS{idProduct}=="085c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-4010CU ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1029", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-4120C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1041", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-4220C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1042", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-4530C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1078", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5750C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1095", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5110EOX/2 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1096", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5110C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1097", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5650C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10ad", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-4120C2 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10ae", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-4220C2 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10af", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-60F ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10c7", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-4340C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10cf", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5120C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e0", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5220C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e1", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5530C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e2", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5110EOX3 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e6", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5900C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10e7", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5015C ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10ef", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5110EOXM ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10f2", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S500 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="10fe", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S500M ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1135", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5530C2 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="114a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6140 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="114d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6240 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="114e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6130 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="114f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6230 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1150", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S510 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1155", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S300 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1156", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S510M ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="116f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6770 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1174", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6770A ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1175", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6670 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1176", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6670A ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1177", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6750S ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1178", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S300M ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="117f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6800 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="119d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6800-CGA ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="119e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S1500 | Fujitsu ScanSnap S1500M ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11a2", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap S1300 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11ed", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6140Z ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11f1", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6240Z ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11f2", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6130Z ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11f3", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6230Z ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11f4", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-6110 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="11fc", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu fi-5950 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="1213", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Fujitsu ScanSnap iX500 ATTRS{idVendor}=="04c5", ATTRS{idProduct}=="132b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Konica e-mini ATTRS{idVendor}=="04c8", ATTRS{idProduct}=="0722", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S2026C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1000", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S2046C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1001", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S1025C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1006", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S1020C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1007", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S2048C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1009", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S2028C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S4085C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S4065C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S7075C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-SS080 ATTRS{idVendor}=="04da", ATTRS{idProduct}=="100f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Panasonic KV-S1045C ATTRS{idVendor}=="04da", ATTRS{idProduct}=="1010", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4x16 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3409", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-6x20 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="340d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung MFP-560 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="340e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung MFP-750 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="340f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4x20 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3412", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4100 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3413", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4x21 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3419", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-5x30 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4200 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-3160 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-6x22 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX4725 | Samsung SCX4725-FN ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="341f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-6x45 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3420", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-8380 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3421", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-2160 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3425", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4500 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3426", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-6200 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3427", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-6240 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3428", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-6x55 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3429", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-3170fn (CLX-3170 Series) | Samsung CLX-3175FW ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4500W ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4824 (SCX-4x24 Series) ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4828FN (SCX-4x28 Series) ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4300 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-5835_5935 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="342f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-5635 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3430", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4x26 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3432", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4600 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3433", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4623 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3434", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung MFP-65x ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3435", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-6545 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3437", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-8385 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3439", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-6220 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-6250 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4825FN (SCX-4x25 Series) ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-3185 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-8540 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="343f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4623FW ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3440", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-3205W (SCX-3200 Series) ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3441", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-6545X ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3442", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-6x55X ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3443", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-8385X ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3444", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-5835_5935X ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3446", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4833FD | Samsung SCX-4835FD ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="344b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-3400 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="344f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SF-760 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3450", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4729FD ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3453", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-6260 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3455", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-3300 Series ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3456", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-470x ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3457", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung CLX-4190 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="345a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-4650 4x21S Series ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="345b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung M337x 387x 407x Series ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3460", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung M267x 287x Series ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3461", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung SCX-681x ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3466", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Samsung C460 ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="3468", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Pentax DSmobile 600 ATTRS{idVendor}=="04f9", ATTRS{idProduct}=="2038", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Aiptek Aiptek Pencam ATTRS{idVendor}=="0553", ATTRS{idProduct}=="0202", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek ScanExpress 1200 CU ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0001", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek ScanExpress 600 CU ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0002", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek ScanExpress 1200 UB | Trust Compact Scan USB 19200 ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0006", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek ScanExpress 1200 CU Plus ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0008", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 F ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0010", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek ScanExpress A3 USB ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0210", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 2400 CS | Mustek BearPaw 2400 TA | Trust 240TH Easy Webscan Gold ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0218", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 2400 CS Plus | Mustek BearPaw 2400 TA Plus | Mustek Plug-n-Scan 2400 MT # Mustek Plug-n-Scan 2400 M | Packard Bell Diamond 2450 ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0219", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 2448 CS Plus | Mustek BearPaw 2448 TA Plus ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 CU Plus | Packard Bell Diamond 1200 Plus ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 CU Plus | Mustek BearPaw 1248 CU | Packard Bell Diamond 1200 Plus # Trust Direct WebScan 19200 ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 2400 CU Plus ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 1200 CS | Mustek BearPaw 1200 TA ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek ScanExpress 1248 UB ATTRS{idVendor}=="055f", ATTRS{idProduct}=="021f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Mustek BearPaw 2448TA Pro ATTRS{idVendor}=="055f", ATTRS{idProduct}=="0409", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Artec/Ultima Ultima 2000 | Artec/Ultima Ultima 2000 e+ | Boeder Sm@rtScan Slim Edition # Fujitsu 1200CUS | Googlegear 2000 | Medion/Lifetec/Tevion/Cytron MD 4394 # Medion/Lifetec/Tevion/Cytron MD/LT 9375 | Medion/Lifetec/Tevion/Cytron MD/LT 9385 | Medion/Lifetec/Tevion/Cytron LT 9452 # Medion/Lifetec/Tevion/Cytron MD 9458 | Mustek BearPaw 1200 CU | Mustek BearPaw 2400 CU # Mustek ScanExpress 1200 UB Plus | Mustek ScanExpress 2400 USB | Mustek ScanMagic 1200 UB Plus # Packard Bell Diamond 1200 | Trust Compact Scan USB 19200 | Trust Flat Scan USB 19200 ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4002", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Artec/Ultima E+ 48U | Medion/Lifetec/Tevion/Cytron MD9693 | Medion/Lifetec/Tevion/Cytron MD9705 # Medion/Lifetec/Tevion/Cytron MD4394 | Microstar MR 9791 ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4003", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Artec/Ultima E+ Pro ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4004", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Memorex MEM 48U ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4005", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Trust Easy Webscan 19200 ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4006", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Trust 240H Easy Webscan Gold ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4007", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # UMAX AstraSlim SE ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4009", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # UMAX AstraSlim 1200 SE ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4010", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Yakumo Scan50 ATTRS{idVendor}=="05d8", ATTRS{idProduct}=="4011", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker X6USB ATTRS{idVendor}=="05da", ATTRS{idProduct}=="0099", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek SlimScan C6 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="009a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker V6USL ATTRS{idVendor}=="05da", ATTRS{idProduct}=="00a3", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker V6UPL ATTRS{idVendor}=="05da", ATTRS{idProduct}=="00b6", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker 4800 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="30cf", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker 3840 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="30d4", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker 3600 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40b3", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker 3700 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40b8", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker 3600 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40ca", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker 3700 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40cb", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker 3750 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40dd", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker 3600 ATTRS{idVendor}=="05da", ATTRS{idProduct}=="40ff", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Microtek ScanMaker V6USL ATTRS{idVendor}=="05da", ATTRS{idProduct}=="80a3", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # iVina 1200U ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0268", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Minolta Dimage Scan Dual II ATTRS{idVendor}=="0638", ATTRS{idProduct}=="026a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV600U ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a13", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Minolta-QMS SC-110 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a15", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision DS610CU Scancopier | Minolta-QMS SC-215 | OKI S700 Scancopier ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a16", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV610 | Avision AV600U Plus ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a18", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV220 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a23", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV210 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a24", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV210 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a25", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV120 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a27", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV220C2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV220D2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV220+ ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV220C2-G ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV220C2-B ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV210C2-G ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a2f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV122 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a33", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV210C2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a3a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV121 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a3c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV8300 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a40", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AM3000 Series ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a41", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision @V5100 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a45", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV8050U ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a4d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV3200SU ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a4e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV3730SU ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a4f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV610C2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a5e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision IT8300 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a61", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV3750SU ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a65", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV3850SU ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a66", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV8350 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a68", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision FB6080E ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a82", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision FB2080E ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a84", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV122 C2 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a93", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV220-G ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0a94", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision @V2500 ATTRS{idVendor}=="0638", ATTRS{idProduct}=="0aa1", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Avision AV210D2+ ATTRS{idVendor}=="0638", ATTRS{idProduct}=="1a35", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Minolta Elite II ATTRS{idVendor}=="0686", ATTRS{idProduct}=="4004", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Minolta Dimage Scan Dual III ATTRS{idVendor}=="0686", ATTRS{idProduct}=="400d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Minolta Dimage Scan Elite 5400 ATTRS{idVendor}=="0686", ATTRS{idProduct}=="400e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan 1212U ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="0001", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan 1236u ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="0002", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Agfa Snapscan Touch ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="0100", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan 1212U_2 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2061", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan e40 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="208d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan e50 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="208f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan e20 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2091", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan e10 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2093", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan e25 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2095", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan e26 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="2097", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan e52 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="20fd", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # AGFA SnapScan e42 ATTRS{idVendor}=="06bd", ATTRS{idProduct}=="20ff", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # UMAX Astra 4900 ATTRS{idVendor}=="06dc", ATTRS{idProduct}=="0020", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro U12 | Plustek OpticPro UT12 | Plustek OpticPro 1212U # RevScan RevScan Orange R48Ti | Genius ColorPage Vivid III USB ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0001", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro U12 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0010", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro U24 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0011", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro UT12 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0013", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro U24 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0015", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro UT12 | Plustek OpticPro UT16 | Plustek OpticPro UT24 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0017", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro 1248U | RevScan 19200i ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0400", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro 1248U ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0401", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro U16B ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0402", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro U16B+ | Plustek OpticPro UT16B ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0403", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Nortek MyScan 1200 | Plustek OpticPro S12 | Plustek OpticPro ST12 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="040b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticPro S24 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="040e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # NeatReceipts Scanalizer Professional 2.5 | Plustek OpticSlim M12 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0412", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticSlim 1200 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0413", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticSlim 2400 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0422", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticSlim 2400 plus ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0454", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek Iriscan Express 2 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="045f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # NeatReceipts Mobile Scanner ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0462", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Plustek OpticBook 3600 ATTRS{idVendor}=="07b3", ATTRS{idProduct}=="0900", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Corex 600c ATTRS{idVendor}=="08f0", ATTRS{idProduct}=="0002", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Corex 800c ATTRS{idVendor}=="08f0", ATTRS{idProduct}=="0005", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox Phaser 6110MFP ATTRS{idVendor}=="0924", ATTRS{idProduct}=="3d5d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox Phaser 3200MFP ATTRS{idVendor}=="0924", ATTRS{idProduct}=="3da4", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox WorkCentre 4118 Series ATTRS{idVendor}=="0924", ATTRS{idProduct}=="420c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox WorkCentre 3119 Series ATTRS{idVendor}=="0924", ATTRS{idProduct}=="4265", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox WorkCentre 3210 ATTRS{idVendor}=="0924", ATTRS{idProduct}=="4293", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Xerox WorkCentre 3220 ATTRS{idVendor}=="0924", ATTRS{idProduct}=="4294", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Pentax DSmobile 600 ATTRS{idVendor}=="0a17", ATTRS{idProduct}=="3210", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Portable Peripheral Co., Ltd. Q-Scan USB001 (A4 portable scanner) ATTRS{idVendor}=="0a53", ATTRS{idProduct}=="1000", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Portable Peripheral Co., Ltd. Q-Scan USB201 (A6 portable scanner) ATTRS{idVendor}=="0a53", ATTRS{idProduct}=="2000", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Syscan TravelScan 460/464 | Ambir Visigo A4 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="4600", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Syscan DocketPort 465 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="4802", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Syscan DocketPort 665 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="4803", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Syscan DocketPort 685/ Ambir DS685 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="480c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Syscan DocketPort 485 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="4810", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Syscan TravelScan 662 ATTRS{idVendor}=="0a82", ATTRS{idProduct}=="6620", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CR-55 ATTRS{idVendor}=="1083", ATTRS{idProduct}=="160c", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-1210C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="160f", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-4010C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1614", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-2510C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1617", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-X10C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1618", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CR-25 ATTRS{idVendor}=="1083", ATTRS{idProduct}=="161a", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-2010C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="161b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-3010C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="161d", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-7090C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1620", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-9050C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1622", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-7550C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1623", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-6050C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1624", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-6010C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1626", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CR-190i ATTRS{idVendor}=="1083", ATTRS{idProduct}=="162b", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon DR-6030C ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1638", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Canon CR-135i ATTRS{idVendor}=="1083", ATTRS{idProduct}=="1639", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Digital Dream l' espion XS ATTRS{idVendor}=="1183", ATTRS{idProduct}=="0001", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # KONICA MINOLTA magicolor 1690MF ATTRS{idVendor}=="132b", ATTRS{idProduct}=="2089", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # UMAX Astra 1220U ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0010", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # UMAX Astra 1600U | UMAX Astra 2000U ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0030", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Umax UMAX 3400 ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0050", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Umax UMAX 3400 | Umax UMAX Astranet ia101 | Umax UMAX 3450 ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0060", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # UMAX Astra 4400 | UMAX Astra 4450 ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0070", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # UMAX Astra 2100U ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0130", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Umax UMAX 5400 ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0160", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # UMAX Astra 2200 (SU) ATTRS{idVendor}=="1606", ATTRS{idProduct}=="0230", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # DCT DocketPort 487 ATTRS{idVendor}=="1dcc", ATTRS{idProduct}=="4810", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Dell A920 ATTRS{idVendor}=="413c", ATTRS{idProduct}=="5105", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Dell Dell MFP Laser Printer 1815dn ATTRS{idVendor}=="413c", ATTRS{idProduct}=="5124", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Dell 1600n ATTRS{idVendor}=="413c", ATTRS{idProduct}=="5250", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # The following rule will disable USB autosuspend for the device ENV{libsane_matched}=="yes", RUN+="/bin/sh -c 'if test -e /sys/$env{DEVPATH}/power/control; then echo on > /sys/$env{DEVPATH}/power/control; elif test -e /sys/$env{DEVPATH}/power/level; then echo on > /sys/$env{DEVPATH}/power/level; fi'" LABEL="libsane_usb_rules_end" SUBSYSTEMS=="scsi", GOTO="libsane_scsi_rules_begin" GOTO="libsane_scsi_rules_end" LABEL="libsane_scsi_rules_begin" # Generic: SCSI device type 6 indicates a scanner KERNEL=="sg[0-9]*", ATTRS{type}=="6", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Some scanners advertise themselves as SCSI device type 3 # Wildcard: for some Epson SCSI scanners KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="SCANNER*", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 2450 | Epson Perfection 2450 PHOTO KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="GT-9700", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 3200 | Epson Perfection 3200 PHOTO KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="GT-9800", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 636S | Epson Perfection 1200S KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="Perfection1200", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Epson Perfection 636 KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="Perfection636", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4p KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1130A", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIc KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1750A", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIp KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1790A", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIcx KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C2500A", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4c KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C2520A", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5p KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C5110A", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6200C KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C6270A", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6300C KERNEL=="sg[0-9]*", ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C7670A", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes" LABEL="libsane_scsi_rules_end" ENV{libsane_matched}=="yes", MODE="664", GROUP="scanner" LABEL="libsane_rules_end" sane-backends-1.0.27/testsuite/tools/data/udev+hwdb.ref0000664000175000017500000000614212775312262017717 00000000000000# This file was automatically created based on description files (*.desc) # by sane-desc 3.5 from sane-backends 1.0.24git on Thu Aug 1 18:50:15 2013 # # udev rules file for supported USB and SCSI devices # # For the list of supported USB devices see /usr/lib/udev/hwdb.d/20-sane.hwdb # # The SCSI device support is very basic and includes only # scanners that mark themselves as type "scanner" or # SCSI-scanners from HP and other vendors that are entitled "processor" # but are treated accordingly. # # If your SCSI scanner isn't listed below, you can add it to a new rules # file under /etc/udev/rules.d/. # # If your scanner is supported by some external backend (brother, epkowa, # hpaio, etc) please ask the author of the backend to provide proper # device detection support for your OS # # If the scanner is supported by sane-backends, please mail the entry to # the sane-devel mailing list (sane-devel@lists.alioth.debian.org). # ACTION!="add", GOTO="libsane_rules_end" # The following rule will disable USB autosuspend for the device ENV{DEVTYPE}=="usb_device", ENV{libsane_matched}=="yes", TEST=="power/control", ATTR{power/control}="on" SUBSYSTEMS=="scsi", GOTO="libsane_scsi_rules_begin" GOTO="libsane_rules_end" LABEL="libsane_scsi_rules_begin" KERNEL!="sg[0-9]*", GOTO="libsane_rules_end" # Generic: SCSI device type 6 indicates a scanner ATTRS{type}=="6", ENV{libsane_matched}="yes" # Some scanners advertise themselves as SCSI device type 3 # Wildcard: for some Epson SCSI scanners ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="SCANNER*", ENV{libsane_matched}="yes" # Epson Perfection 2450 | Epson Perfection 2450 PHOTO ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="GT-9700", ENV{libsane_matched}="yes" # Epson Perfection 3200 | Epson Perfection 3200 PHOTO ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="GT-9800", ENV{libsane_matched}="yes" # Epson Perfection 636S | Epson Perfection 1200S ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="Perfection1200", ENV{libsane_matched}="yes" # Epson Perfection 636 ATTRS{type}=="3", ATTRS{vendor}=="EPSON", ATTRS{model}=="Perfection636", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4p ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1130A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIc ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1750A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIp ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C1790A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet IIcx ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C2500A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 4c ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C2520A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 5p ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C5110A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6200C ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C6270A", ENV{libsane_matched}="yes" # Hewlett-Packard ScanJet 6300C ATTRS{type}=="3", ATTRS{vendor}=="HP", ATTRS{model}=="C7670A", ENV{libsane_matched}="yes" LABEL="libsane_rules_end" sane-backends-1.0.27/testsuite/tools/data/plist.ref0000664000175000017500000035070212775312262017173 00000000000000 device info version 2.0 usb IOUSBDevice device type scanner product 0x0101 vendor 0x03f0 device type scanner product 0x0105 vendor 0x03f0 device type scanner product 0x0201 vendor 0x03f0 device type scanner product 0x0205 vendor 0x03f0 device type scanner product 0x0305 vendor 0x03f0 device type scanner product 0x0401 vendor 0x03f0 device type scanner product 0x0405 vendor 0x03f0 device type scanner product 0x0505 vendor 0x03f0 device type scanner product 0x0601 vendor 0x03f0 device type scanner product 0x0605 vendor 0x03f0 device type scanner product 0x0701 vendor 0x03f0 device type scanner product 0x0705 vendor 0x03f0 device type scanner product 0x0801 vendor 0x03f0 device type scanner product 0x0805 vendor 0x03f0 device type scanner product 0x0901 vendor 0x03f0 device type scanner product 0x0a01 vendor 0x03f0 device type scanner product 0x0b01 vendor 0x03f0 device type scanner product 0x1005 vendor 0x03f0 device type scanner product 0x1105 vendor 0x03f0 device type scanner product 0x1205 vendor 0x03f0 device type scanner product 0x1305 vendor 0x03f0 device type scanner product 0x1405 vendor 0x03f0 device type scanner product 0x1705 vendor 0x03f0 device type scanner product 0x1805 vendor 0x03f0 device type scanner product 0x1b05 vendor 0x03f0 device type scanner product 0x2005 vendor 0x03f0 device type scanner product 0x2205 vendor 0x03f0 device type scanner product 0x2305 vendor 0x03f0 device type scanner product 0x2405 vendor 0x03f0 device type scanner product 0x2605 vendor 0x03f0 device type scanner product 0x2805 vendor 0x03f0 device type scanner product 0x3805 vendor 0x03f0 device type scanner product 0x3905 vendor 0x03f0 device type scanner product 0x3b17 vendor 0x03f0 device type scanner product 0x4105 vendor 0x03f0 device type scanner product 0x4205 vendor 0x03f0 device type scanner product 0x4305 vendor 0x03f0 device type scanner product 0x4505 vendor 0x03f0 device type scanner product 0x4605 vendor 0x03f0 device type scanner product 0x4705 vendor 0x03f0 device type scanner product 0x5617 vendor 0x03f0 device type scanner product 0x5717 vendor 0x03f0 device type scanner product 0x1000 vendor 0x0400 device type scanner product 0x1001 vendor 0x0400 device type scanner product 0x4025 vendor 0x040a device type scanner product 0x4026 vendor 0x040a device type scanner product 0x4027 vendor 0x040a device type scanner product 0x4028 vendor 0x040a device type scanner product 0x4031 vendor 0x040a device type scanner product 0x4032 vendor 0x040a device type scanner product 0x403e vendor 0x040a device type scanner product 0x403f vendor 0x040a device type scanner product 0x4041 vendor 0x040a device type scanner product 0x4043 vendor 0x040a device type scanner product 0x4053 vendor 0x040a device type scanner product 0x4054 vendor 0x040a device type scanner product 0x4056 vendor 0x040a device type scanner product 0x4057 vendor 0x040a device type scanner product 0x4058 vendor 0x040a device type scanner product 0x4059 vendor 0x040a device type scanner product 0x405d vendor 0x040a device type scanner product 0x405e vendor 0x040a device type scanner product 0x4060 vendor 0x040a device type scanner product 0x4062 vendor 0x040a device type scanner product 0x4063 vendor 0x040a device type scanner product 0x4064 vendor 0x040a device type scanner product 0x4065 vendor 0x040a device type scanner product 0x4066 vendor 0x040a device type scanner product 0x4067 vendor 0x040a device type scanner product 0x406d vendor 0x040a device type scanner product 0x6001 vendor 0x040a device type scanner product 0x6002 vendor 0x040a device type scanner product 0x6003 vendor 0x040a device type scanner product 0x6004 vendor 0x040a device type scanner product 0x6005 vendor 0x040a device type scanner product 0x4007 vendor 0x041e device type scanner product 0x002d vendor 0x043d device type scanner product 0x0060 vendor 0x043d device type scanner product 0x007c vendor 0x043d device type scanner product 0x007d vendor 0x043d device type scanner product 0x2004 vendor 0x0458 device type scanner product 0x2007 vendor 0x0458 device type scanner product 0x2008 vendor 0x0458 device type scanner product 0x2009 vendor 0x0458 device type scanner product 0x2011 vendor 0x0458 device type scanner product 0x2013 vendor 0x0458 device type scanner product 0x2014 vendor 0x0458 device type scanner product 0x2015 vendor 0x0458 device type scanner product 0x2016 vendor 0x0458 device type scanner product 0x2017 vendor 0x0458 device type scanner product 0x201a vendor 0x0458 device type scanner product 0x201b vendor 0x0458 device type scanner product 0x201d vendor 0x0458 device type scanner product 0x201e vendor 0x0458 device type scanner product 0x201f vendor 0x0458 device type scanner product 0x2021 vendor 0x0458 device type scanner product 0x0377 vendor 0x0461 device type scanner product 0x038b vendor 0x0461 device type scanner product 0x1000 vendor 0x047b device type scanner product 0x1002 vendor 0x047b device type scanner product 0x0335 vendor 0x0482 device type scanner product 0x001a vendor 0x049f device type scanner product 0x1a20 vendor 0x04a5 device type scanner product 0x1a2a vendor 0x04a5 device type scanner product 0x2022 vendor 0x04a5 device type scanner product 0x2040 vendor 0x04a5 device type scanner product 0x2060 vendor 0x04a5 device type scanner product 0x207e vendor 0x04a5 device type scanner product 0x20b0 vendor 0x04a5 device type scanner product 0x20be vendor 0x04a5 device type scanner product 0x20c0 vendor 0x04a5 device type scanner product 0x20de vendor 0x04a5 device type scanner product 0x20f8 vendor 0x04a5 device type scanner product 0x20fc vendor 0x04a5 device type scanner product 0x20fe vendor 0x04a5 device type scanner product 0x2137 vendor 0x04a5 device type scanner product 0x2211 vendor 0x04a5 device type scanner product 0x0229 vendor 0x04a7 device type scanner product 0x0390 vendor 0x04a7 device type scanner product 0x0420 vendor 0x04a7 device type scanner product 0x0421 vendor 0x04a7 device type scanner product 0x0422 vendor 0x04a7 device type scanner product 0x0423 vendor 0x04a7 device type scanner product 0x0424 vendor 0x04a7 device type scanner product 0x0426 vendor 0x04a7 device type scanner product 0x0427 vendor 0x04a7 device type scanner product 0x0444 vendor 0x04a7 device type scanner product 0x0446 vendor 0x04a7 device type scanner product 0x0447 vendor 0x04a7 device type scanner product 0x0448 vendor 0x04a7 device type scanner product 0x0449 vendor 0x04a7 device type scanner product 0x044c vendor 0x04a7 device type scanner product 0x0474 vendor 0x04a7 device type scanner product 0x0475 vendor 0x04a7 device type scanner product 0x0476 vendor 0x04a7 device type scanner product 0x0477 vendor 0x04a7 device type scanner product 0x0478 vendor 0x04a7 device type scanner product 0x0479 vendor 0x04a7 device type scanner product 0x047a vendor 0x04a7 device type scanner product 0x047b vendor 0x04a7 device type scanner product 0x047c vendor 0x04a7 device type scanner product 0x048c vendor 0x04a7 device type scanner product 0x048d vendor 0x04a7 device type scanner product 0x048e vendor 0x04a7 device type scanner product 0x048f vendor 0x04a7 device type scanner product 0x0490 vendor 0x04a7 device type scanner product 0x0491 vendor 0x04a7 device type scanner product 0x0492 vendor 0x04a7 device type scanner product 0x0493 vendor 0x04a7 device type scanner product 0x0494 vendor 0x04a7 device type scanner product 0x0495 vendor 0x04a7 device type scanner product 0x0497 vendor 0x04a7 device type scanner product 0x0498 vendor 0x04a7 device type scanner product 0x0499 vendor 0x04a7 device type scanner product 0x049a vendor 0x04a7 device type scanner product 0x049b vendor 0x04a7 device type scanner product 0x049c vendor 0x04a7 device type scanner product 0x049d vendor 0x04a7 device type scanner product 0x04a7 vendor 0x04a7 device type scanner product 0x04ac vendor 0x04a7 device type scanner product 0x1601 vendor 0x04a9 device type scanner product 0x1602 vendor 0x04a9 device type scanner product 0x1603 vendor 0x04a9 device type scanner product 0x1604 vendor 0x04a9 device type scanner product 0x1606 vendor 0x04a9 device type scanner product 0x1607 vendor 0x04a9 device type scanner product 0x1608 vendor 0x04a9 device type scanner product 0x1609 vendor 0x04a9 device type scanner product 0x160a vendor 0x04a9 device type scanner product 0x160b vendor 0x04a9 device type scanner product 0x1706 vendor 0x04a9 device type scanner product 0x1707 vendor 0x04a9 device type scanner product 0x1708 vendor 0x04a9 device type scanner product 0x1709 vendor 0x04a9 device type scanner product 0x170a vendor 0x04a9 device type scanner product 0x170b vendor 0x04a9 device type scanner product 0x170c vendor 0x04a9 device type scanner product 0x170d vendor 0x04a9 device type scanner product 0x170e vendor 0x04a9 device type scanner product 0x1712 vendor 0x04a9 device type scanner product 0x1713 vendor 0x04a9 device type scanner product 0x1714 vendor 0x04a9 device type scanner product 0x1715 vendor 0x04a9 device type scanner product 0x1716 vendor 0x04a9 device type scanner product 0x1717 vendor 0x04a9 device type scanner product 0x1718 vendor 0x04a9 device type scanner product 0x1719 vendor 0x04a9 device type scanner product 0x171a vendor 0x04a9 device type scanner product 0x171b vendor 0x04a9 device type scanner product 0x171c vendor 0x04a9 device type scanner product 0x1721 vendor 0x04a9 device type scanner product 0x1722 vendor 0x04a9 device type scanner product 0x1723 vendor 0x04a9 device type scanner product 0x1724 vendor 0x04a9 device type scanner product 0x1725 vendor 0x04a9 device type scanner product 0x1726 vendor 0x04a9 device type scanner product 0x1727 vendor 0x04a9 device type scanner product 0x1728 vendor 0x04a9 device type scanner product 0x1729 vendor 0x04a9 device type scanner product 0x172b vendor 0x04a9 device type scanner product 0x172c vendor 0x04a9 device type scanner product 0x172d vendor 0x04a9 device type scanner product 0x172e vendor 0x04a9 device type scanner product 0x172f vendor 0x04a9 device type scanner product 0x1730 vendor 0x04a9 device type scanner product 0x1731 vendor 0x04a9 device type scanner product 0x1732 vendor 0x04a9 device type scanner product 0x1733 vendor 0x04a9 device type scanner product 0x1734 vendor 0x04a9 device type scanner product 0x1735 vendor 0x04a9 device type scanner product 0x1736 vendor 0x04a9 device type scanner product 0x1737 vendor 0x04a9 device type scanner product 0x173a vendor 0x04a9 device type scanner product 0x173b vendor 0x04a9 device type scanner product 0x173c vendor 0x04a9 device type scanner product 0x173d vendor 0x04a9 device type scanner product 0x173e vendor 0x04a9 device type scanner product 0x173f vendor 0x04a9 device type scanner product 0x1740 vendor 0x04a9 device type scanner product 0x1741 vendor 0x04a9 device type scanner product 0x1742 vendor 0x04a9 device type scanner product 0x1743 vendor 0x04a9 device type scanner product 0x1746 vendor 0x04a9 device type scanner product 0x1747 vendor 0x04a9 device type scanner product 0x1748 vendor 0x04a9 device type scanner product 0x1749 vendor 0x04a9 device type scanner product 0x174a vendor 0x04a9 device type scanner product 0x174b vendor 0x04a9 device type scanner product 0x174d vendor 0x04a9 device type scanner product 0x174e vendor 0x04a9 device type scanner product 0x174f vendor 0x04a9 device type scanner product 0x1750 vendor 0x04a9 device type scanner product 0x1751 vendor 0x04a9 device type scanner product 0x1752 vendor 0x04a9 device type scanner product 0x1753 vendor 0x04a9 device type scanner product 0x1754 vendor 0x04a9 device type scanner product 0x1755 vendor 0x04a9 device type scanner product 0x1756 vendor 0x04a9 device type scanner product 0x1757 vendor 0x04a9 device type scanner product 0x1758 vendor 0x04a9 device type scanner product 0x1759 vendor 0x04a9 device type scanner product 0x175a vendor 0x04a9 device type scanner product 0x175b vendor 0x04a9 device type scanner product 0x175c vendor 0x04a9 device type scanner product 0x175d vendor 0x04a9 device type scanner product 0x175e vendor 0x04a9 device type scanner product 0x175f vendor 0x04a9 device type scanner product 0x1760 vendor 0x04a9 device type scanner product 0x1761 vendor 0x04a9 device type scanner product 0x1762 vendor 0x04a9 device type scanner product 0x1763 vendor 0x04a9 device type scanner product 0x1764 vendor 0x04a9 device type scanner product 0x1765 vendor 0x04a9 device type scanner product 0x1766 vendor 0x04a9 device type scanner product 0x1767 vendor 0x04a9 device type scanner product 0x1768 vendor 0x04a9 device type scanner product 0x1769 vendor 0x04a9 device type scanner product 0x176a vendor 0x04a9 device type scanner product 0x176b vendor 0x04a9 device type scanner product 0x1901 vendor 0x04a9 device type scanner product 0x1904 vendor 0x04a9 device type scanner product 0x1905 vendor 0x04a9 device type scanner product 0x1907 vendor 0x04a9 device type scanner product 0x1908 vendor 0x04a9 device type scanner product 0x1909 vendor 0x04a9 device type scanner product 0x190a vendor 0x04a9 device type scanner product 0x190d vendor 0x04a9 device type scanner product 0x2204 vendor 0x04a9 device type scanner product 0x2206 vendor 0x04a9 device type scanner product 0x2207 vendor 0x04a9 device type scanner product 0x2208 vendor 0x04a9 device type scanner product 0x220d vendor 0x04a9 device type scanner product 0x220e vendor 0x04a9 device type scanner product 0x2213 vendor 0x04a9 device type scanner product 0x221c vendor 0x04a9 device type scanner product 0x2220 vendor 0x04a9 device type scanner product 0x2222 vendor 0x04a9 device type scanner product 0x262f vendor 0x04a9 device type scanner product 0x2630 vendor 0x04a9 device type scanner product 0x263c vendor 0x04a9 device type scanner product 0x263d vendor 0x04a9 device type scanner product 0x263e vendor 0x04a9 device type scanner product 0x263f vendor 0x04a9 device type scanner product 0x264c vendor 0x04a9 device type scanner product 0x264d vendor 0x04a9 device type scanner product 0x264e vendor 0x04a9 device type scanner product 0x264f vendor 0x04a9 device type scanner product 0x2659 vendor 0x04a9 device type scanner product 0x265d vendor 0x04a9 device type scanner product 0x265e vendor 0x04a9 device type scanner product 0x265f vendor 0x04a9 device type scanner product 0x2660 vendor 0x04a9 device type scanner product 0x2684 vendor 0x04a9 device type scanner product 0x2686 vendor 0x04a9 device type scanner product 0x26a3 vendor 0x04a9 device type scanner product 0x26b0 vendor 0x04a9 device type scanner product 0x26b4 vendor 0x04a9 device type scanner product 0x26b5 vendor 0x04a9 device type scanner product 0x26e6 vendor 0x04a9 device type scanner product 0x26ec vendor 0x04a9 device type scanner product 0x26ed vendor 0x04a9 device type scanner product 0x26ee vendor 0x04a9 device type scanner product 0x26ef vendor 0x04a9 device type scanner product 0x26f9 vendor 0x04a9 device type scanner product 0x26fa vendor 0x04a9 device type scanner product 0x2707 vendor 0x04a9 device type scanner product 0x2736 vendor 0x04a9 device type scanner product 0x2737 vendor 0x04a9 device type scanner product 0x2759 vendor 0x04a9 device type scanner product 0x4000 vendor 0x04b0 device type scanner product 0x4001 vendor 0x04b0 device type scanner product 0x4002 vendor 0x04b0 device type scanner product 0x0101 vendor 0x04b8 device type scanner product 0x0103 vendor 0x04b8 device type scanner product 0x0104 vendor 0x04b8 device type scanner product 0x0105 vendor 0x04b8 device type scanner product 0x0106 vendor 0x04b8 device type scanner product 0x0107 vendor 0x04b8 device type scanner product 0x0109 vendor 0x04b8 device type scanner product 0x010a vendor 0x04b8 device type scanner product 0x010b vendor 0x04b8 device type scanner product 0x010c vendor 0x04b8 device type scanner product 0x010e vendor 0x04b8 device type scanner product 0x010f vendor 0x04b8 device type scanner product 0x0110 vendor 0x04b8 device type scanner product 0x0112 vendor 0x04b8 device type scanner product 0x0114 vendor 0x04b8 device type scanner product 0x011b vendor 0x04b8 device type scanner product 0x011c vendor 0x04b8 device type scanner product 0x011d vendor 0x04b8 device type scanner product 0x011e vendor 0x04b8 device type scanner product 0x011f vendor 0x04b8 device type scanner product 0x0120 vendor 0x04b8 device type scanner product 0x0121 vendor 0x04b8 device type scanner product 0x0122 vendor 0x04b8 device type scanner product 0x0126 vendor 0x04b8 device type scanner product 0x0128 vendor 0x04b8 device type scanner product 0x0129 vendor 0x04b8 device type scanner product 0x012a vendor 0x04b8 device type scanner product 0x012b vendor 0x04b8 device type scanner product 0x012c vendor 0x04b8 device type scanner product 0x0135 vendor 0x04b8 device type scanner product 0x0801 vendor 0x04b8 device type scanner product 0x0802 vendor 0x04b8 device type scanner product 0x0805 vendor 0x04b8 device type scanner product 0x0806 vendor 0x04b8 device type scanner product 0x0807 vendor 0x04b8 device type scanner product 0x0808 vendor 0x04b8 device type scanner product 0x080c vendor 0x04b8 device type scanner product 0x080d vendor 0x04b8 device type scanner product 0x080e vendor 0x04b8 device type scanner product 0x080f vendor 0x04b8 device type scanner product 0x0810 vendor 0x04b8 device type scanner product 0x0811 vendor 0x04b8 device type scanner product 0x0813 vendor 0x04b8 device type scanner product 0x0814 vendor 0x04b8 device type scanner product 0x0815 vendor 0x04b8 device type scanner product 0x0817 vendor 0x04b8 device type scanner product 0x0818 vendor 0x04b8 device type scanner product 0x0819 vendor 0x04b8 device type scanner product 0x081a vendor 0x04b8 device type scanner product 0x081c vendor 0x04b8 device type scanner product 0x081d vendor 0x04b8 device type scanner product 0x081f vendor 0x04b8 device type scanner product 0x0820 vendor 0x04b8 device type scanner product 0x0827 vendor 0x04b8 device type scanner product 0x0828 vendor 0x04b8 device type scanner product 0x0829 vendor 0x04b8 device type scanner product 0x082a vendor 0x04b8 device type scanner product 0x082b vendor 0x04b8 device type scanner product 0x082e vendor 0x04b8 device type scanner product 0x082f vendor 0x04b8 device type scanner product 0x0830 vendor 0x04b8 device type scanner product 0x0833 vendor 0x04b8 device type scanner product 0x0834 vendor 0x04b8 device type scanner product 0x0835 vendor 0x04b8 device type scanner product 0x0836 vendor 0x04b8 device type scanner product 0x0837 vendor 0x04b8 device type scanner product 0x0838 vendor 0x04b8 device type scanner product 0x0839 vendor 0x04b8 device type scanner product 0x083a vendor 0x04b8 device type scanner product 0x083c vendor 0x04b8 device type scanner product 0x0841 vendor 0x04b8 device type scanner product 0x0843 vendor 0x04b8 device type scanner product 0x0844 vendor 0x04b8 device type scanner product 0x0846 vendor 0x04b8 device type scanner product 0x0847 vendor 0x04b8 device type scanner product 0x0848 vendor 0x04b8 device type scanner product 0x0849 vendor 0x04b8 device type scanner product 0x084a vendor 0x04b8 device type scanner product 0x084c vendor 0x04b8 device type scanner product 0x084d vendor 0x04b8 device type scanner product 0x084f vendor 0x04b8 device type scanner product 0x0851 vendor 0x04b8 device type scanner product 0x0854 vendor 0x04b8 device type scanner product 0x0856 vendor 0x04b8 device type scanner product 0x085c vendor 0x04b8 device type scanner product 0x1029 vendor 0x04c5 device type scanner product 0x1041 vendor 0x04c5 device type scanner product 0x1042 vendor 0x04c5 device type scanner product 0x1078 vendor 0x04c5 device type scanner product 0x1095 vendor 0x04c5 device type scanner product 0x1096 vendor 0x04c5 device type scanner product 0x1097 vendor 0x04c5 device type scanner product 0x10ad vendor 0x04c5 device type scanner product 0x10ae vendor 0x04c5 device type scanner product 0x10af vendor 0x04c5 device type scanner product 0x10c7 vendor 0x04c5 device type scanner product 0x10cf vendor 0x04c5 device type scanner product 0x10e0 vendor 0x04c5 device type scanner product 0x10e1 vendor 0x04c5 device type scanner product 0x10e2 vendor 0x04c5 device type scanner product 0x10e6 vendor 0x04c5 device type scanner product 0x10e7 vendor 0x04c5 device type scanner product 0x10ef vendor 0x04c5 device type scanner product 0x10f2 vendor 0x04c5 device type scanner product 0x10fe vendor 0x04c5 device type scanner product 0x1135 vendor 0x04c5 device type scanner product 0x114a vendor 0x04c5 device type scanner product 0x114d vendor 0x04c5 device type scanner product 0x114e vendor 0x04c5 device type scanner product 0x114f vendor 0x04c5 device type scanner product 0x1150 vendor 0x04c5 device type scanner product 0x1155 vendor 0x04c5 device type scanner product 0x1156 vendor 0x04c5 device type scanner product 0x116f vendor 0x04c5 device type scanner product 0x1174 vendor 0x04c5 device type scanner product 0x1175 vendor 0x04c5 device type scanner product 0x1176 vendor 0x04c5 device type scanner product 0x1177 vendor 0x04c5 device type scanner product 0x1178 vendor 0x04c5 device type scanner product 0x117f vendor 0x04c5 device type scanner product 0x119d vendor 0x04c5 device type scanner product 0x119e vendor 0x04c5 device type scanner product 0x11a2 vendor 0x04c5 device type scanner product 0x11ed vendor 0x04c5 device type scanner product 0x11f1 vendor 0x04c5 device type scanner product 0x11f2 vendor 0x04c5 device type scanner product 0x11f3 vendor 0x04c5 device type scanner product 0x11f4 vendor 0x04c5 device type scanner product 0x11fc vendor 0x04c5 device type scanner product 0x1213 vendor 0x04c5 device type scanner product 0x132b vendor 0x04c5 device type scanner product 0x0722 vendor 0x04c8 device type scanner product 0x1000 vendor 0x04da device type scanner product 0x1001 vendor 0x04da device type scanner product 0x1006 vendor 0x04da device type scanner product 0x1007 vendor 0x04da device type scanner product 0x1009 vendor 0x04da device type scanner product 0x100a vendor 0x04da device type scanner product 0x100c vendor 0x04da device type scanner product 0x100d vendor 0x04da device type scanner product 0x100e vendor 0x04da device type scanner product 0x100f vendor 0x04da device type scanner product 0x1010 vendor 0x04da device type scanner product 0x3409 vendor 0x04e8 device type scanner product 0x340d vendor 0x04e8 device type scanner product 0x340e vendor 0x04e8 device type scanner product 0x340f vendor 0x04e8 device type scanner product 0x3412 vendor 0x04e8 device type scanner product 0x3413 vendor 0x04e8 device type scanner product 0x3419 vendor 0x04e8 device type scanner product 0x341a vendor 0x04e8 device type scanner product 0x341b vendor 0x04e8 device type scanner product 0x341c vendor 0x04e8 device type scanner product 0x341d vendor 0x04e8 device type scanner product 0x341f vendor 0x04e8 device type scanner product 0x3420 vendor 0x04e8 device type scanner product 0x3421 vendor 0x04e8 device type scanner product 0x3425 vendor 0x04e8 device type scanner product 0x3426 vendor 0x04e8 device type scanner product 0x3427 vendor 0x04e8 device type scanner product 0x3428 vendor 0x04e8 device type scanner product 0x3429 vendor 0x04e8 device type scanner product 0x342a vendor 0x04e8 device type scanner product 0x342b vendor 0x04e8 device type scanner product 0x342c vendor 0x04e8 device type scanner product 0x342d vendor 0x04e8 device type scanner product 0x342e vendor 0x04e8 device type scanner product 0x342f vendor 0x04e8 device type scanner product 0x3430 vendor 0x04e8 device type scanner product 0x3432 vendor 0x04e8 device type scanner product 0x3433 vendor 0x04e8 device type scanner product 0x3434 vendor 0x04e8 device type scanner product 0x3435 vendor 0x04e8 device type scanner product 0x3437 vendor 0x04e8 device type scanner product 0x3439 vendor 0x04e8 device type scanner product 0x343a vendor 0x04e8 device type scanner product 0x343b vendor 0x04e8 device type scanner product 0x343c vendor 0x04e8 device type scanner product 0x343d vendor 0x04e8 device type scanner product 0x343f vendor 0x04e8 device type scanner product 0x3440 vendor 0x04e8 device type scanner product 0x3441 vendor 0x04e8 device type scanner product 0x3442 vendor 0x04e8 device type scanner product 0x3443 vendor 0x04e8 device type scanner product 0x3444 vendor 0x04e8 device type scanner product 0x3446 vendor 0x04e8 device type scanner product 0x344b vendor 0x04e8 device type scanner product 0x344f vendor 0x04e8 device type scanner product 0x3450 vendor 0x04e8 device type scanner product 0x3453 vendor 0x04e8 device type scanner product 0x3455 vendor 0x04e8 device type scanner product 0x3456 vendor 0x04e8 device type scanner product 0x3457 vendor 0x04e8 device type scanner product 0x345a vendor 0x04e8 device type scanner product 0x345b vendor 0x04e8 device type scanner product 0x3460 vendor 0x04e8 device type scanner product 0x3461 vendor 0x04e8 device type scanner product 0x3466 vendor 0x04e8 device type scanner product 0x3468 vendor 0x04e8 device type scanner product 0x2038 vendor 0x04f9 device type scanner product 0x0202 vendor 0x0553 device type scanner product 0x0001 vendor 0x055f device type scanner product 0x0002 vendor 0x055f device type scanner product 0x0006 vendor 0x055f device type scanner product 0x0008 vendor 0x055f device type scanner product 0x0010 vendor 0x055f device type scanner product 0x0210 vendor 0x055f device type scanner product 0x0218 vendor 0x055f device type scanner product 0x0219 vendor 0x055f device type scanner product 0x021a vendor 0x055f device type scanner product 0x021b vendor 0x055f device type scanner product 0x021c vendor 0x055f device type scanner product 0x021d vendor 0x055f device type scanner product 0x021e vendor 0x055f device type scanner product 0x021f vendor 0x055f device type scanner product 0x0409 vendor 0x055f device type scanner product 0x4002 vendor 0x05d8 device type scanner product 0x4003 vendor 0x05d8 device type scanner product 0x4004 vendor 0x05d8 device type scanner product 0x4005 vendor 0x05d8 device type scanner product 0x4006 vendor 0x05d8 device type scanner product 0x4007 vendor 0x05d8 device type scanner product 0x4009 vendor 0x05d8 device type scanner product 0x4010 vendor 0x05d8 device type scanner product 0x4011 vendor 0x05d8 device type scanner product 0x0099 vendor 0x05da device type scanner product 0x009a vendor 0x05da device type scanner product 0x00a3 vendor 0x05da device type scanner product 0x00b6 vendor 0x05da device type scanner product 0x30cf vendor 0x05da device type scanner product 0x30d4 vendor 0x05da device type scanner product 0x40b3 vendor 0x05da device type scanner product 0x40b8 vendor 0x05da device type scanner product 0x40ca vendor 0x05da device type scanner product 0x40cb vendor 0x05da device type scanner product 0x40dd vendor 0x05da device type scanner product 0x40ff vendor 0x05da device type scanner product 0x80a3 vendor 0x05da device type scanner product 0x0268 vendor 0x0638 device type scanner product 0x026a vendor 0x0638 device type scanner product 0x0a13 vendor 0x0638 device type scanner product 0x0a15 vendor 0x0638 device type scanner product 0x0a16 vendor 0x0638 device type scanner product 0x0a18 vendor 0x0638 device type scanner product 0x0a23 vendor 0x0638 device type scanner product 0x0a24 vendor 0x0638 device type scanner product 0x0a25 vendor 0x0638 device type scanner product 0x0a27 vendor 0x0638 device type scanner product 0x0a2a vendor 0x0638 device type scanner product 0x0a2b vendor 0x0638 device type scanner product 0x0a2c vendor 0x0638 device type scanner product 0x0a2d vendor 0x0638 device type scanner product 0x0a2e vendor 0x0638 device type scanner product 0x0a2f vendor 0x0638 device type scanner product 0x0a33 vendor 0x0638 device type scanner product 0x0a3a vendor 0x0638 device type scanner product 0x0a3c vendor 0x0638 device type scanner product 0x0a40 vendor 0x0638 device type scanner product 0x0a41 vendor 0x0638 device type scanner product 0x0a45 vendor 0x0638 device type scanner product 0x0a4d vendor 0x0638 device type scanner product 0x0a4e vendor 0x0638 device type scanner product 0x0a4f vendor 0x0638 device type scanner product 0x0a5e vendor 0x0638 device type scanner product 0x0a61 vendor 0x0638 device type scanner product 0x0a65 vendor 0x0638 device type scanner product 0x0a66 vendor 0x0638 device type scanner product 0x0a68 vendor 0x0638 device type scanner product 0x0a82 vendor 0x0638 device type scanner product 0x0a84 vendor 0x0638 device type scanner product 0x0a93 vendor 0x0638 device type scanner product 0x0a94 vendor 0x0638 device type scanner product 0x0aa1 vendor 0x0638 device type scanner product 0x1a35 vendor 0x0638 device type scanner product 0x4004 vendor 0x0686 device type scanner product 0x400d vendor 0x0686 device type scanner product 0x400e vendor 0x0686 device type scanner product 0x0001 vendor 0x06bd device type scanner product 0x0002 vendor 0x06bd device type scanner product 0x0100 vendor 0x06bd device type scanner product 0x2061 vendor 0x06bd device type scanner product 0x208d vendor 0x06bd device type scanner product 0x208f vendor 0x06bd device type scanner product 0x2091 vendor 0x06bd device type scanner product 0x2093 vendor 0x06bd device type scanner product 0x2095 vendor 0x06bd device type scanner product 0x2097 vendor 0x06bd device type scanner product 0x20fd vendor 0x06bd device type scanner product 0x20ff vendor 0x06bd device type scanner product 0x0020 vendor 0x06dc device type scanner product 0x0001 vendor 0x07b3 device type scanner product 0x0010 vendor 0x07b3 device type scanner product 0x0011 vendor 0x07b3 device type scanner product 0x0013 vendor 0x07b3 device type scanner product 0x0015 vendor 0x07b3 device type scanner product 0x0017 vendor 0x07b3 device type scanner product 0x0400 vendor 0x07b3 device type scanner product 0x0401 vendor 0x07b3 device type scanner product 0x0402 vendor 0x07b3 device type scanner product 0x0403 vendor 0x07b3 device type scanner product 0x040b vendor 0x07b3 device type scanner product 0x040e vendor 0x07b3 device type scanner product 0x0412 vendor 0x07b3 device type scanner product 0x0413 vendor 0x07b3 device type scanner product 0x0422 vendor 0x07b3 device type scanner product 0x0454 vendor 0x07b3 device type scanner product 0x045f vendor 0x07b3 device type scanner product 0x0462 vendor 0x07b3 device type scanner product 0x0900 vendor 0x07b3 device type scanner product 0x0002 vendor 0x08f0 device type scanner product 0x0005 vendor 0x08f0 device type scanner product 0x3d5d vendor 0x0924 device type scanner product 0x3da4 vendor 0x0924 device type scanner product 0x420c vendor 0x0924 device type scanner product 0x4265 vendor 0x0924 device type scanner product 0x4293 vendor 0x0924 device type scanner product 0x4294 vendor 0x0924 device type scanner product 0x3210 vendor 0x0a17 device type scanner product 0x1000 vendor 0x0a53 device type scanner product 0x2000 vendor 0x0a53 device type scanner product 0x4600 vendor 0x0a82 device type scanner product 0x4802 vendor 0x0a82 device type scanner product 0x4803 vendor 0x0a82 device type scanner product 0x480c vendor 0x0a82 device type scanner product 0x4810 vendor 0x0a82 device type scanner product 0x6620 vendor 0x0a82 device type scanner product 0x160c vendor 0x1083 device type scanner product 0x160f vendor 0x1083 device type scanner product 0x1614 vendor 0x1083 device type scanner product 0x1617 vendor 0x1083 device type scanner product 0x1618 vendor 0x1083 device type scanner product 0x161a vendor 0x1083 device type scanner product 0x161b vendor 0x1083 device type scanner product 0x161d vendor 0x1083 device type scanner product 0x1620 vendor 0x1083 device type scanner product 0x1622 vendor 0x1083 device type scanner product 0x1623 vendor 0x1083 device type scanner product 0x1624 vendor 0x1083 device type scanner product 0x1626 vendor 0x1083 device type scanner product 0x162b vendor 0x1083 device type scanner product 0x1638 vendor 0x1083 device type scanner product 0x1639 vendor 0x1083 device type scanner product 0x0001 vendor 0x1183 device type scanner product 0x2089 vendor 0x132b device type scanner product 0x0010 vendor 0x1606 device type scanner product 0x0030 vendor 0x1606 device type scanner product 0x0050 vendor 0x1606 device type scanner product 0x0060 vendor 0x1606 device type scanner product 0x0070 vendor 0x1606 device type scanner product 0x0130 vendor 0x1606 device type scanner product 0x0160 vendor 0x1606 device type scanner product 0x0230 vendor 0x1606 device type scanner product 0x4810 vendor 0x1dcc device type scanner product 0x5105 vendor 0x413c device type scanner product 0x5124 vendor 0x413c device type scanner product 0x5250 vendor 0x413c sane-backends-1.0.27/testsuite/tools/data/hal.ref0000664000175000017500000055344512775312262016615 00000000000000 scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary scanner proprietary sane-backends-1.0.27/testsuite/tools/data/html-backends-split.ref0000664000175000017500000175311012775312262021706 00000000000000 SANE: Backends (Drivers)
SANE

SANE: Backends (Drivers)


The following table summarizes the backends/drivers distributed with the latest version of sane-backends, and the hardware or software they support.

This is only a summary! Please consult the manpages and the author-supplied webpages for more detailed (and usually important) information concerning each backend.

If you have new information or corrections, please file a bug report with as many details as possible. Also please tell us if your scanner isn't mentioned in this list at all.

For an explanation of the tables, see the legend.

Summary

Device type Number of devices
Total Supported Untested Unsupported
Sum Complete Good Basic Minimal
Scanners 2012 1205 417 662 101 25 325 482
Still cameras 5 5 1 2 2 0 0 0
Video Cameras 8 3 0 1 0 2 3 2
Meta backends 2 n/a
APIs 5 n/a

Scanners

Backends: abaton, agfafocus, apple, artec, artec_eplus48u, as6e, avision, bh, canon, canon630u, canon_dr, canon_pp, cardscan, coolscan, coolscan2, coolscan3, dell1600n_net, epjitsu, epson, epson2, fujitsu, genesys, gt68xx, hp, hp3500, hp3900, hp4200, hp5400, hp5590, hpljm1005, hpsj5s, hs2p, ibm, kodak, kodakaio, kvs20xx, kvs40xx, kvs1025, leo, lexmark, ma1509, magicolor, matsushita, microtek, microtek2, mustek, mustek_pp, mustek_usb, mustek_usb2, nec, niash, p5, pie, pixma, plustek, plustek_pp, ricoh, rts8891, s9036, sceptre, sharp, sm3600, sm3840, SnapScan, sp15c, st400, tamarack, teco1, teco2, teco3, u12, umax, umax1220u, umax_pp, unsupported, xerox_mfp

Backend: abaton (unmaintained)

Manual page: sane-abaton

Manufacturer Model Interface USB id Status Comment
Abaton Scan 300/GS SCSI   Complete All known modes and functions supported
Scan 300/S SCSI   Untested Untested, use with caution

Backend: agfafocus (unmaintained)

Manual page: sane-agfafocus

Manufacturer Model Interface USB id Status Comment
AGFA Focus GS Scanner SCSI   Untested 6 bit gray
Focus Lineart Scanner SCSI   Untested Lineart only? Untested.
Focus II SCSI   Untested gray only
Focus Color SCSI   Good 3-pass
Focus Color Plus SCSI   Good 3-pass
Siemens S9036 SCSI   Untested gray only

Backend: apple (unmaintained)

Manual page: sane-apple

Manufacturer Model Interface USB id Status Comment
Apple Apple Scanner SCSI   Good 4bit, 16 shades of gray
OneScanner SCSI   Basic 8bit, 256 shades of gray. The backend needs work especially in the quantization code but it may work.
Color OneScanner SCSI   Minimal truecolor (needs much work) but it scans in non color modes.

Backend: artec (unmaintained)

Link(s): http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html
Manual page: sane-artec

Manufacturer Model Interface USB id Status Comment
Artec/Ultima AT3 SCSI   Complete all modes working
A6000C SCSI   Complete all modes working
A6000C PLUS SCSI   Complete f/w <= v1.92 basic, f/w >= v1.93 OK
AT6 SCSI   Good Scan head needs to return home before another scan can be started.
AT12 SCSI   Complete all modes working
AM12S SCSI   Complete all modes working
BlackWidow BW4800SP SCSI   Complete rebadged Artec AT3
Plustek OpticPro 19200S SCSI   Complete rebadged Artec AM12S

Backend: artec_eplus48u (unmaintained)

Manual page: sane-artec_eplus48u

Manufacturer Model Interface USB id Status Comment
Artec/Ultima E+ 48U USB 0x05d8/0x4003 Good CIS scanner based on the GT6816 chip. Apparently all other devices are re-badged Artec scanners.
E+ Pro USB 0x05d8/0x4004 Minimal Works up to 600dpi, but not 1200. Needs better calibration. See bug #310490
Medion/Lifetec/Tevion/Cytron MD9693 USB 0x05d8/0x4003 Good  
MD9705 USB 0x05d8/0x4003 Good  
MD4394 USB 0x05d8/0x4003 Good Only scanners with product id 0x4003 will work; try the gt68xx backend, if your scanner has product id 0x4002
Trust Easy Webscan 19200 USB 0x05d8/0x4006 Good  
240H Easy Webscan Gold USB 0x05d8/0x4007 Basic Works up to 600 dpi
Memorex MEM 48U USB 0x05d8/0x4005 Good  
Microstar MR 9791 USB 0x05d8/0x4003 Good  
UMAX AstraSlim SE USB 0x05d8/0x4009 Good  
AstraSlim 1200 SE USB 0x05d8/0x4010 Good  
Yakumo Scan50 USB 0x05d8/0x4011 Good  

Backend: as6e (0.5)

Link(s): http://as6edriver.sourceforge.net/
Manual page: sane-as6e

Manufacturer Model Interface USB id Status Comment
Artec/Ultima AS6E Parport   Basic Requires the program 'as6edriver' to run.
Trust Easy Scan 9600 Plus Parport   Basic Requires the program 'as6edriver' to run.
Dexxa 4800 Parport   Basic Requires the program 'as6edriver' to run.

Backend: avision (Build: 296)

Link(s): http://skull.piratehaven.org/~mike/sane/avision.html
Manual page: sane-avision

Manufacturer Model Interface USB id Status Comment
Avision AV100CS SCSI   Untested  
AV100IIICS SCSI   Untested  
AV100S SCSI   Untested  
AV120 USB 0x0638/0x0a27 Complete sheetfed scanner
AV121 USB 0x0638/0x0a3c Good sheetfed scanner
AV122 USB 0x0638/0x0a33 Good sheetfed duplex scanner
AV122 C2 USB 0x0638/0x0a93 Good sheetfed duplex scanner
AV210 USB 0x0638/0x0a24 Complete sheetfed scanner
AV210 USB 0x0638/0x0a25 Complete sheetfed scanner
AV210C2 USB 0x0638/0x0a3a Complete sheetfed scanner
AV210C2-G USB 0x0638/0x0a2f Complete sheetfed scanner
AV210D2+ USB 0x0638/0x1a35 Complete sheetfed scanner
AV220 USB 0x0638/0x0a23 Complete duplex! sheetfed scanner
AV220C2 USB 0x0638/0x0a2a Complete duplex! sheetfed scanner
AV220D2 USB 0x0638/0x0a2b Complete duplex! sheetfed scanner
AV220+ USB 0x0638/0x0a2c Complete duplex! sheetfed scanner
AV220C2-G USB 0x0638/0x0a2d Complete duplex! sheetfed scanner
AV220C2-B USB 0x0638/0x0a2e Complete duplex! sheetfed scanner
AV220-G USB 0x0638/0x0a94 Complete duplex! sheetfed scanner
AV240SC SCSI   Untested  
AV260CS SCSI   Untested  
AV360CS SCSI   Untested  
AV363CS SCSI   Untested  
AV420CS SCSI   Untested  
AV6120 SCSI   Untested  
AV610 USB 0x0638/0x0a18 Good  
AV600U Plus USB 0x0638/0x0a18 Good  
AV610C2 USB 0x0638/0x0a5e Good  
AM3000 Series USB 0x0638/0x0a41 Basic MFD
DS610CU Scancopier USB 0x0638/0x0a16 Good 1 pass, 600 dpi, A4
AV620CS SCSI   Complete 1 pass, 600 dpi
AV620CS Plus SCSI   Complete 1 pass, 1200 dpi
AV630CS SCSI   Complete 1 pass, 1200 dpi
AV630CSL SCSI   Untested 1 pass, 1200 dpi
AV6240 SCSI   Complete 1 pass, ??? dpi
AV600U USB 0x0638/0x0a13 Good 1 pass, 600 dpi
AV660S SCSI   Untested 1 pass, ??? dpi
AV680S SCSI   Untested 1 pass, ??? dpi
AV690U SCSI   Untested 1 pass, 2400 dpi
AV800S SCSI   Untested 1 pass, ??? dpi
AV810C SCSI   Untested 1 pass, ??? dpi
AV820 SCSI   Untested 1 pass, ??? dpi
AV820C SCSI   Complete 1 pass, ??? dpi
AV820C Plus SCSI   Complete 1 pass, ??? dpi
AV830C SCSI   Complete 1 pass, ??? dpi
AV830C Plus SCSI   Untested 1 pass, ??? dpi
AV880 SCSI   Untested 1 pass, ??? dpi
AV880C SCSI   Untested 1 pass, ??? dpi
AV3200C SCSI   Complete 1 pass, ??? dpi
AV3200SU USB 0x0638/0x0a4e Complete 1 pass, ??? dpi
AV3730SU USB 0x0638/0x0a4f Complete 1 pass, ??? dpi
AV3750SU USB 0x0638/0x0a65 Complete 1 pass, ??? dpi
AV3800C SCSI   Complete 1 pass, ??? dpi
AV3850SU USB 0x0638/0x0a66 Complete 1 pass, ??? dpi
FB6000E SCSI   Complete 1 pass, 1200 dpi, A3 - duplex! - zero edge!
FB6080E USB 0x0638/0x0a82 Complete 1 pass, 1200 dpi, A3 - duplex! - zero edge!
FB2080E USB 0x0638/0x0a84 Basic 1 pass, 600 dpi, zero-edge
AV8000S SCSI   Complete 1 pass, 1200 dpi, A3
AV8050U USB 0x0638/0x0a4d Complete 1 pass, 1200 dpi, A3 - duplex!
AV8300 USB 0x0638/0x0a40 Complete 1 pass, 1200 dpi, A3 - duplex!
AV8350 USB 0x0638/0x0a68 Complete 1 pass, 1200 dpi, A3 - duplex!
IT8300 USB 0x0638/0x0a61 Good 1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors
@V2500 USB 0x0638/0x0aa1 Untested  
@V5100 USB 0x0638/0x0a45 Good 1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors
AVA3 SCSI   Basic 1 pass, 600 dpi, A3
Hewlett-Packard ScanJet 5300C USB 0x03f0/0x0701 Complete 1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi
ScanJet 5370C USB 0x03f0/0x0701 Good 1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi
ScanJet 7400c USB 0x03f0/0x0801 Good 1 pass, 2400 dpi - dual USB/SCSI interface
ScanJet 7450c USB 0x03f0/0x0801 Good 1 pass, 2400 dpi - dual USB/SCSI interface
ScanJet 7490c USB 0x03f0/0x0801 Good 1 pass, 1200 dpi - dual USB/SCSI interface
ScanJet 8200 USB 0x03f0/0x0b01 Good 1 pass, 4800 (?) dpi - USB 2.0
ScanJet 8250 USB 0x03f0/0x0b01 Good 1 pass, 4800 (?) dpi - USB 2.0
ScanJet 8270 USB 0x03f0/0x3905 Good 1 pass, 4800 (?) dpi - USB 2.0
ScanJet 8290 USB 0x03f0/0x0b01 Good 1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far
ScanJet 8300 USB 0x03f0/0x3805 Good 1 pass, 4800 (?) dpi - USB 2.0
ScanJet 8350 USB 0x03f0/0x3805 Good 1 pass, 4800 (?) dpi - USB 2.0
ScanJet 8390 USB 0x03f0/0x3805 Good 1 pass, 4800 (?) dpi - USB 2.0
Minolta Dimage Scan Dual I SCSI   Basic  
Scan Multi Pro SCSI   Untested  
Dimage Scan Dual II USB 0x0638/0x026a Good 1 pass, film-scanner
Elite II USB 0x0686/0x4004 Untested 1 pass, film-scanner
Dimage Scan Dual III USB 0x0686/0x400d Good 1 pass, film-scanner
Dimage Scan Elite 5400 USB 0x0686/0x400e Good 1 pass, film-scanner
Minolta-QMS SC-110 USB 0x0638/0x0a15 Untested  
SC-215 USB 0x0638/0x0a16 Good  
Mitsubishi MCA-ADFC SCSI   Untested  
S1200C SCSI   Untested  
S600C SCSI   Untested  
SS600 SCSI   Good  
Fujitsu ScanPartner SCSI   Untested  
ScanPartner 10 SCSI   Untested  
ScanPartner 10C SCSI   Untested  
ScanPartner 15C SCSI   Untested  
ScanPartner 300C SCSI   Untested  
ScanPartner 600C SCSI   Untested  
ScanPartner 620C SCSI   Good  
ScanPartner Jr SCSI   Untested  
ScanStation SCSI   Untested  
fi-4010CU USB 0x04c5/0x1029 Untested  
fi-5015C USB 0x04c5/0x10ef Good  
Kodak i30 USB 0x040a/0x6001 Untested  
i40 USB 0x040a/0x6002 Basic  
i50 USB 0x040a/0x6003 Untested  
i55 USB 0x040a/0x6003 Untested  
i60 USB 0x040a/0x6004 Untested  
i65 USB 0x040a/0x6004 Untested  
i80 USB 0x040a/0x6005 Good  
iVina 1200U USB 0x0638/0x0268 Untested  
Visioneer Strobe XP 450 USB 0x04a7/0x0424 Complete sheetfed scanner
Strobe XP 450-G USB 0x04a7/0x0491 Complete sheetfed scanner
Strobe XP 470 USB 0x04a7/0x0479 Complete sheetfed scanner
Strobe XP 470-G USB 0x04a7/0x048f Complete sheetfed scanner
9320 USB 0x04a7/0x0420 Complete sheetfed scanner
9450 USB 0x04a7/0x0421 Complete sheetfed scanner
9450-G USB 0x04a7/0x047a Complete sheetfed scanner
9550 USB 0x04a7/0x0422 Complete sheetfed scanner
9650 USB 0x04a7/0x0390 Complete sheetfed scanner
9650-G USB 0x04a7/0x047b Complete sheetfed scanner
9750 USB 0x04a7/0x0423 Complete sheetfed scanner
9750-G USB 0x04a7/0x0493 Complete sheetfed scanner
Patriot 430 USB 0x04a7/0x0497 Complete sheetfed scanner
Patriot 470 USB 0x04a7/0x048f Complete sheetfed scanner
Patriot 680 USB 0x04a7/0x0498 Complete sheetfed scanner
Patriot 780 USB 0x04a7/0x0499 Complete sheetfed scanner
Xerox DocuMate150 USB 0x04a7/0x049c Good  
DocuMate152 USB 0x04a7/0x0477 Good  
DocuMate162 USB 0x04a7/0x049d Good  
DocuMate250 USB 0x04a7/0x0448 Good  
DocuMate250-G USB 0x04a7/0x0490 Good  
DocuMate252 USB 0x04a7/0x0449 Good  
DocuMate252-G USB 0x04a7/0x048c Good  
DocuMate232 USB 0x04a7/0x0476 Good  
DocuMate262 USB 0x04a7/0x044c Good  
DocuMate262-G USB 0x04a7/0x048d Good  
DocuMate262i USB 0x04a7/0x04a7 Good  
DocuMate272 USB 0x04a7/0x0475 Untested  
DocuMate272-G USB 0x04a7/0x048e Untested  
DocuMate510 USB 0x04a7/0x0446 Untested  
DocuMate512 USB 0x04a7/0x0495 Untested  
DocuMate510-G USB 0x04a7/0x047c Untested  
DocuMate520 USB 0x04a7/0x0447 Untested  
DocuMate520-G USB 0x04a7/0x0492 Untested  
DocuMate632 USB 0x04a7/0x0498 Untested  
DocuMate752 USB 0x04a7/0x0478 Untested  
DocuMate752 USB 0x04a7/0x049a Untested  
OKI S700 Scancopier USB 0x0638/0x0a16 Good 1 pass, 600 dpi, A4
Bell+Howell 2000F SCSI   Basic 1 pass, ??? dpi, A4
Kyocera FS-1016MFP USB 0x0482/0x0335 Untested 1 pass, ??? dpi, A4

Backend: bh (1.0-4)

Link(s): http://www.martoneconsulting.com/sane-bh.html
Manual page: sane-bh
Comment: Supports Copiscan II scanners with Remote SCSI Controller (RSC) interface

Manufacturer Model Interface USB id Status Comment
Bell and Howell COPISCAN II 6338 SCSI   Good Duplex Scanner with ACE - development model
COPISCAN II 2135 SCSI   Untested Simplex Scanner
COPISCAN II 2137(A) SCSI   Good Simplex Scanner (with ACE) - limited testing
COPISCAN II 2138A SCSI   Untested Simplex Scanner with ACE
COPISCAN II 3238 SCSI   Untested Simplex Scanner
COPISCAN II 3338(A) SCSI   Untested Simplex Scanner (with ACE)

Backend: canon (1.12)

Link(s): http://www.rzg.mpg.de/~mpd/sane/
Manual page: sane-canon

Manufacturer Model Interface USB id Status Comment
Canon CanoScan 300 SCSI   Good 1 pass; flatbed scanner
CanoScan 600 SCSI   Good 1 pass; flatbed scanner
CanoScan 620S SCSI   Good 1 pass; flatbed scanner
CanoScan 1200S SCSI   Good 1 pass; flatbed scanner
CanoScan 2700F SCSI   Good 1 pass; film scanner
CanoScan 2710S SCSI   Good 1 pass; 36bit film scanner
IX-4015 SCSI   Good 1 pass; flatbed scanner
Apple Color OneScanner 600/27 SCSI   Good Rebadged CanoScan 300

Backend: canon630u (0.1)

Link(s): http://canon-fb630u.sourceforge.net/
Manual page: sane-canon630u

Manufacturer Model Interface USB id Status Comment
Canon CanoScan fb630u USB 0x04a9/0x2204 Good OK
CanoScan fb636u USB 0x04a9/0x2204 Good OK

Backend: canon_dr (38)

Link(s): http://www.thebility.com/canon/
Manual page: sane-canon_dr
Comment: Backend updated for SANE release 1.0.23, see sane-canon_dr manpage

Manufacturer Model Interface USB id Status Comment
Canon CR-25 USB 0x1083/0x161a Untested Please test!
CR-55 USB 0x1083/0x160c Untested Please test!
CR-135i USB SCSI 0x1083/0x1639 Untested Please test!
CR-180 USB SCSI 0x04a9/0x1602 Untested Please test!
CR-180II USB SCSI 0x04a9/0x1602 Untested Same as CR-180? Please test!
CR-190i USB SCSI 0x1083/0x162b Untested Please test!
DR-1210C USB 0x04a9/0x2222 Untested Older version? Please test!
DR-1210C USB 0x1083/0x160f Untested Later version? Please test!
DR-2010C USB 0x1083/0x161b Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions.
DR-2010M USB   Untested Mac version of DR-2010C? Please test!
DR-2050C USB 0x04a9/0x160a Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration.
DR-2050SP USB 0x04a9/0x160a Untested Same as DR-2050C? Please test!
DR-2080C USB SCSI 0x04a9/0x1601 Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration
DR-2510C USB 0x1083/0x1617 Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width, 300/600dpi horizontal. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration, other resolutions
DR-2510M USB   Untested Mac version of DR-2510C? Please test!
DR-2580C USB SCSI 0x04a9/0x1608 Complete Hardware provides: Gray/Color, Simplex/Duplex, Full-width. Driver provides: Binary, Despeckle, Deskew, Cropping, Calibration
DR-3010C USB 0x1083/0x161d Good Minimal testing, settings copied from DR-2510C
DR3020 SCSI   Untested Please test!
DR-3020C SCSI   Untested Please test!
DR-3060 SCSI   Untested Please test!
DR-3080C SCSI   Untested Almost works, need to investigate traces from windows driver
DR-3080CII USB SCSI 0x04a9/0x1609 Untested Almost works, need to investigate traces from windows driver
DR-4010C USB 0x1083/0x1614 Good Binary/HT/Gray/Color, Simplex/Duplex working. Multistream unsupported.
DR4080U USB   Untested Please test!
DR-4580U USB   Untested Please test!
DR-5010C USB 0x04a9/0x1606 Untested Please test!
DR-5020 SCSI   Good LineArt, Duplex working, cannot read buttons or screen?
DR-5060F SCSI   Basic Grayscale works, LineArt might
DR-5080C SCSI   Untested Please test!
DR-6010C USB SCSI 0x1083/0x1626 Untested Please test!
DR-6030C USB SCSI 0x1083/0x1638 Untested Please test!
DR-6050C USB SCSI 0x1083/0x1624 Good Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode
DR-6080 USB SCSI 0x04a9/0x1607 Good Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported
DR-7080C USB SCSI 0x04a9/0x1604 Untested Please test!
DR-7090C USB SCSI 0x1083/0x1620 Good ADF and flatbed work
DR-7550C USB SCSI 0x1083/0x1623 Untested Assumed compatible with DR-6050C
DR-7580 USB SCSI 0x04a9/0x160b Good Simplex, duplex, all resolutions, binary/ht/gray, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported
DR-9050C USB SCSI 0x1083/0x1622 Good Simplex, duplex, all resolutions, binary/ht/gray working. Can't wake from stand-by mode
DR-9080C USB SCSI 0x04a9/0x1603 Good Simplex, duplex, all resolutions, binary/ht/gray/color, async mode, dropout-color, multifeed/staple detection, deskew, buttons and JPEG working. Imprinter, barcode, custom gamma and multistream unsupported
DR-X10C USB SCSI 0x1083/0x1618 Untested Please test!

Backend: canon_pp (0.33)

Link(s): http://canon-fb330p.sourceforge.net
Manual page: sane-canon_pp

Manufacturer Model Interface USB id Status Comment
Canon CanoScan FB310P Parport (ECP)   Unsupported Rebadged Avision, different command set
CanoScan FB610P Parport (ECP)   Unsupported Rebadged Avision, different command set
CanoScan FB320P Parport (ECP)   Basic Newly added support
CanoScan FB620P Parport (ECP)   Basic Newly added support
CanoScan FB330P Parport (ECP)   Good  
CanoScan FB630P Parport (ECP)   Good  
CanoScan N340P Parport (ECP)   Good  
CanoScan N640P Parport (ECP)   Good  
CanoScan N640P ex Parport (ECP)   Good Just an N640P in a different box?

Backend: cardscan (2)

Link(s): http://www.thebility.com/cardscan/
Manual page: sane-cardscan
Comment: Backend updated for SANE release 1.0.21, see sane-cardscan manpage

Manufacturer Model Interface USB id Status Comment
Corex 800c USB 0x08f0/0x0005 Good 4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner
600c USB 0x08f0/0x0002 Basic 4 inch wide 8bit Gray or 24bit Color simplex card/receipt scanner

Backend: coolscan (0.4.3)

Link(s): http://andreas.rick.free.fr/sane/
Manual page: sane-coolscan

Manufacturer Model Interface USB id Status Comment
Nikon LS-20 SCSI   Basic The LS-20 has been replaced by the LS-30
LS-30 SCSI   Basic alpha: only 24/30 bit RGB + 32/40 bit RGBI
LS-2000 SCSI   Basic alpha: only 24/36 bit + RGB 32/48 bit RGBI
LS-1000 SCSI   Basic Doesn't support gamma correction

Backend: coolscan2 (0.1.8)

Link(s): http://coolscan2.sourceforge.net/
Manual page: sane-coolscan2

Manufacturer Model Interface USB id Status Comment
Nikon LS 30 SCSI   Complete working -- model available to developer
LS 2000 SCSI   Good  
LS 40 ED USB 0x04b0/0x4000 Complete  
LS 4000 ED IEEE-1394   Good needs linux kernel 2.4.19 or later
LS 50 ED USB 0x04b0/0x4001 Minimal  
Coolscan V ED USB 0x04b0/0x4001 Minimal  
Super Coolscan LS-5000 ED USB 0x04b0/0x4002 Untested May work, similar to LS 50 ED, but untested. Please tell us if it works.
LS 8000 ED IEEE-1394   Good needs linux kernel 2.4.19 or later

Backend: coolscan3 (1.0.0)

Manual page: sane-coolscan3

Manufacturer Model Interface USB id Status Comment
Nikon LS 30 SCSI   Complete  
Coolscan III SCSI   Complete Rebadged LS 30?
LS 40 ED USB 0x04b0/0x4000 Complete  
Coolspan IV USB 0x04b0/0x4000 Complete Rebadged LS 40?
LS 50 ED USB 0x04b0/0x4001 Minimal  
Coolscan V ED USB 0x04b0/0x4001 Minimal Rebadged LS 50?
LS 2000 SCSI   Good  
LS 4000 ED IEEE-1394   Good needs linux kernel 2.4.19 or later
Super Coolscan LS-5000 ED USB 0x04b0/0x4002 Untested May work, similar to LS 50 ED, but untested. Please tell us if it works.
LS 8000 ED IEEE-1394   Good needs linux kernel 2.4.19 or later

Backend: dell1600n_net

Manufacturer Model Interface USB id Status Comment
Dell 1600n Ethernet USB 0x413c/0x5250 Basic Supports colour and monochrome scans over ethernet (USB not supported)

Backend: epjitsu (20)

Link(s): http://www.thebility.com/epjitsu/
Manual page: sane-epjitsu
Comment: Backend updated for SANE release 1.0.21, see sane-epjitsu manpage

Manufacturer Model Interface USB id Status Comment
Fujitsu fi-60F USB 0x04c5/0x10c7 Basic A6-size flatbed, 300/600 dpi, color/gray/binary
ScanSnap S300 USB 0x04c5/0x1156 Good Duplex, 150/225/300/600 dpi, color/gray/binary, AC/USB power, buttons/sensors all supported. Scanner always scans in _triplex_ color, fast USB required.
ScanSnap S300M USB 0x04c5/0x117f Good Same as S300, with different usb id
ScanSnap S1100 USB 0x04c5/0x1200 Unsupported Beta version of backend source available, which works well, but breaks support for other epjitsu scanners. See http://ubuntuforums.org/showthread.php?t=1678335
ScanSnap S1300 USB 0x04c5/0x11ed Good Same as S300, with different usb id

Backend: epson (unmaintained)

Link(s): http://www.khk.net/sane
Manual page: sane-epson

Manufacturer Model Interface USB id Status Comment
Epson GT-5000 SCSI Parport   Good  
Actionscanner II SCSI Parport   Good US version of GT-5000
GT-6000 SCSI Parport   Good  
ES-300C SCSI Parport   Good US version of GT-6000
ES-300GS SCSI   Good  
GT-5500 SCSI   Good  
GT-6500 Parport   Good  
ES-600C Parport   Good US version of GT-6500
ES-1200C Parport   Good US version of GT-9000
GT-7000 SCSI   Good  
GT-8000 SCSI   Good  
ES-8500 SCSI   Good  
Perfection 636S SCSI   Complete US version of GT-7000
Perfection 636 SCSI   Complete  
Perfection 636U USB 0x04b8/0x0101 Complete  
Perfection 610 USB 0x04b8/0x0103 Complete  
Perfection 640 USB 0x04b8/0x010c Complete  
Perfection 1200S SCSI   Complete  
Perfection 1200U USB 0x04b8/0x0104 Complete  
Perfection 1200Photo USB 0x04b8/0x0104 Complete with TPU
Perfection 1240 SCSI USB 0x04b8/0x010b Complete  
Perfection 1640 SCSI USB 0x04b8/0x010a Complete  
Perfection 1650 USB 0x04b8/0x0110 Complete  
Perfection 1660 USB 0x04b8/0x011e Complete  
Perfection 2400 USB 0x04b8/0x011b Complete  
Perfection 2450 USB IEEE-1394 0x04b8/0x0112 Complete  
Perfection 3200 USB IEEE-1394 0x04b8/0x011c Complete US version of the GT-9800
Perfection 4870 USB 0x04b8/0x0128 Complete US version of the GT-X700
Perfection 4990 USB 0x04b8/0x012a Complete US version of the GT-X800
Expression 636 SCSI   Complete US version of GT-9500
Expression 800 SCSI   Complete  
Expression 1600 SCSI USB IEEE-1394 0x04b8/0x0107 Complete  
Expression 1680 SCSI USB IEEE-1394 0x04b8/0x010e Complete  
FilmScan 200 SCSI   Unsupported A better backend for the FilmScan 200 can be found at http://www.vjet.demon.co.uk/scanner/
CX-3200 USB 0x04b8/0x0802 Good  
CX-3600 USB 0x04b8/0x080e Good  
CX-3650 USB 0x04b8/0x080e Good  
CX-4600 USB 0x04b8/0x080d Good  
CX-4800 USB 0x04b8/0x0819 Good  
CX-5000 USB 0x04b8/0x082b Good  
CX-5200 USB 0x04b8/0x0801 Good  
CX-5400 USB 0x04b8/0x0801 Good  
CX-5400 USB 0x04b8/0x0808 Good  
CX-6300 USB 0x04b8/0x0805 Good  
CX-6400 USB 0x04b8/0x0805 Good  
CX-6500 USB 0x04b8/0x0813 Good  
CX-6600 USB 0x04b8/0x0813 Good  
RX-500 USB 0x04b8/0x0807 Good  
RX-600 USB 0x04b8/0x0806 Good  
RX-425 USB 0x04b8/0x080f Good  
RX-700 USB 0x04b8/0x0810 Good  
RX-620 USB 0x04b8/0x0811 Good  
DX-3850 USB 0x04b8/0x0818 Good  
CX-3700 USB 0x04b8/0x0818 Good  
CX-3800 USB 0x04b8/0x0818 Good  
CX-4200 USB 0x04b8/0x0820 Good  
DX-3800 USB 0x04b8/0x0818 Good  
DX-5000 USB 0x04b8/0x082b Good  
DX-5050 USB 0x04b8/0x082b Good  
DX-6000 USB 0x04b8/0x082e Good  
DX-7400 USB 0x04b8/0x0838 Good  
DX-4050 USB 0x04b8/0x082f Good  
AcuLaser CX11 USB 0x04b8/0x0815 Good  
AcuLaser CX11NF USB 0x04b8/0x0815 Good  
V700 USB IEEE-1394 0x04b8/0x012c Good  
V750 USB IEEE-1394 0x04b8/0x012c Good  

Backend: epson2 (1.0.124)

Manual page: sane-epson2

Manufacturer Model Interface USB id Status Comment
Epson Actionscanner II parallel SCSI   Good overseas version of the GT-5000
AcuLaser CX11 USB 0x04b8/0x0815 Good overseas version of the LP-A500
AcuLaser CX11NF USB Network 0x04b8/0x0815 Good network interface supported
AcuLaser CX11 with network interface and fax
AcuLaser CX21 USB 0x04b8/0x0835 Good network interface probably supported
Artisan 700 USB Network 0x04b8/0x0846 Good network interface supported
all-in-one
overseas version of the EP-801A
Artisan 710 Series USB 0x04b8/0x0852 Unsupported supported by the epkowa backend plus non-free interpreter
Artisan 800 USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
overseas version of the EP-901A
Artisan 810 Series USB 0x04b8/0x0853 Unsupported supported by the epkowa backend plus non-free interpreter
CC-500L USB 0x04b8/0x010d Unsupported all-in-one
CC-550L USB 0x04b8/0x011a Unsupported all-in-one
CC-570L USB 0x04b8/0x0802 Good all-in-one
CC-600PX USB 0x04b8/0x0801 Good all-in-one
CC-700 USB 0x04b8/0x0108 Unsupported all-in-one
EP-702A USB 0x04b8/0x0850 Unsupported supported by the epkowa backend plus non-free interpreter
EP-801A USB Network 0x04b8/0x0846 Good network interface supported
all-in-one
EP-802A USB 0x04b8/0x0852 Unsupported supported by the epkowa backend plus non-free interpreter
EP-901A USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
EP-901F USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
EP-902A USB 0x04b8/0x0853 Unsupported supported by the epkowa backend plus non-free interpreter
ES-300C SCSI parallel   Good overseas version of the GT-6000
ES-300GS SCSI   Good  
ES-600C parallel   Good overseas version of the GT-5400
ES-800C SCSI   Good overseas version of the GT-8000
ES-1000C ?   Unsupported overseas version of the GT-8500
ES-1200C parallel   Good overseas version of the GT-9000
ES-2000 SCSI USB 0x04b8/0x0107 Complete IEEE1394 untested
ES-2200 SCSI USB 0x04b8/0x010e Complete IEEE1394 untested
ES-6000 SCSI   Good  
ES-6000H SCSI   Good IEEE1394 untested
ES-6000HS SCSI   Good IEEE1394 untested
ES-7000H SCSI USB 0x04b8/0x0126 Good network interface unsupported
IEEE1394 untested
ES-8000 SCSI   Untested  
ES-8500 SCSI USB 0x04b8/0x0109 Good IEEE1394 untested
ES-9000H SCSI   Good IEEE1394 untested
ES-10000G USB 0x04b8/0x0129 Good network interface unsupported
IEEE1394 untested
ES-D400 USB 0x04b8/0x0136 Unsupported supported by the epkowa backend plus non-free interpreter
ES-H300 USB 0x04b8/0x012b Good network interface probably supported
ES-H7200 USB Ethernet 0x04b8/0x0138 Unsupported supported by the epkowa backend plus non-free interpreter
Expression 636 SCSI   Complete overseas version of the GT-9500
Expression 800 SCSI   Complete overseas version of the GT-9600
Expression 836XL SCSI   Untested overseas version of the ES-8000
Expression 1600 SCSI USB 0x04b8/0x0107 Complete IEEE1394 untested
overseas version of the ES-2000
Expression 1640XL SCSI USB 0x04b8/0x0109 Good IEEE1394 untested
overseas version of the ES-8500
Expression 1680 SCSI USB 0x04b8/0x010e Complete IEEE1394 untested
overseas version of the ES-2200
Expression 1680 Pro SCSI USB   Untested IEEE1394 option
Expression 1680XL Pro SCSI USB   Untested  
Expression 10000XL USB 0x04b8/0x0129 Good network interface probably supported
IEEE1394 untested
overseas version of the ES-10000G
Expression 10000XL Graphic Arts USB IEEE1394   Untested network interface probably supported
Expression 10000XL Photo USB IEEE1394   Untested network interface probably supported
F-3200 USB IEEE1394 0x04b8/0x080a Unsupported Film scanner
F-3200 Photo USB IEEE1394   Unsupported  
FilmScan 200 SCSI   Minimal will be supported
GT-1500 USB 0x04b8/0x0133 Unsupported supported by the epkowa backend plus non-free interpreter
GT-2200 USB 0x04b8/0x0102 Unsupported  
GT-2500 USB 0x04b8/0x012b Good network interface probably supported
overseas version of the ES-H300
GT-4000 ?   Untested  
GT-5000 parallel SCSI   Good  
GT-5400 parallel   Good  
GT-5500 SCSI   Good  
GT-6000 SCSI Parport   Good  
GT-6500 parallel   Good overseas version of the GT-5400
GT-6600U USB 0x04b8/0x0103 Complete  
GT-6700U USB 0x04b8/0x010c Complete  
GT-7000S SCSI   Complete  
GT-7000U USB 0x04b8/0x0101 Complete  
GT-7200U USB 0x04b8/0x010f Unsupported supported by the epkowa backend plus non-free interpreter
GT-7300U USB 0x04b8/0x011d Unsupported supported by the epkowa backend plus non-free interpreter
GT-7400U USB 0x04b8/0x0120 Unsupported supported by the snapscan backend
GT-7600S SCSI   Complete SCSI version of the GT-7600U
GT-7600U USB 0x04b8/0x0104 Complete USB version of the GT-7600S
GT-7600UF USB 0x04b8/0x0104 Complete GT-7600U with TPU option bundled
GT-7700U USB 0x04b8/0x010b Complete  
GT-8000 SCSI   Good  
GT-8200U USB 0x04b8/0x0110 Complete  
GT-8200UF USB 0x04b8/0x0110 Good  
GT-8300UF USB 0x04b8/0x011e Complete  
GT-8400UF USB 0x04b8/0x011f Unsupported  
GT-8500 ?   Untested  
GT-8700 SCSI USB 0x04b8/0x010a Complete  
GT-8700F SCSI USB 0x04b8/0x010a Good GT-8700U with TPU option bundled
GT-9000 parallel   Good  
GT-9300UF USB 0x04b8/0x011b Complete  
GT-9400UF USB 0x04b8/0x0116 Unsupported supported by the epkowa backend plus non-free interpreter
GT-9500 SCSI   Complete  
GT-9600 SCSI   Complete  
GT-9700F USB 0x04b8/0x0112 Complete IEEE1394 untested
GT-9800F USB 0x04b8/0x011c Complete IEEE1394 untested
GT-10000 SCSI   Good overseas version of the ES-6000
GT-10000+ SCSI   Good IEEE1394 untested
overseas version of the ES-6000H
GT-12000 SCSI   Untested overseas version of the ES-8000
GT-15000 SCSI USB 0x04b8/0x0126 Good IEEE1394 untested
overseas version of the ES-7000H
GT-20000 USB Ethernet 0x04b8/0x0138 Unsupported supported by the epkowa backend plus non-free interpreter
GT-30000 SCSI   Good IEEE1394 untested
overseas version of the ES-9000H
GT-D1000 USB 0x04b8/0x0133 Unsupported supported by the epkowa backend plus non-free interpreter
GT-F500 USB 0x04b8/0x0121 Unsupported supported by the epkowa backend plus non-free interpreter
GT-F520 USB 0x04b8/0x0122 Unsupported supported by the epkowa backend plus non-free interpreter
GT-F550 USB 0x04b8/0x0121 Unsupported supported by the epkowa backend plus non-free interpreter
GT-F570 USB 0x04b8/0x0122 Unsupported supported by the epkowa backend plus non-free interpreter
GT-F600 USB 0x04b8/0x0118 Unsupported supported by the epkowa backend plus non-free interpreter
GT-F650 USB 0x04b8/0x012d Unsupported supported by the epkowa backend plus non-free interpreter
GT-F670 USB 0x04b8/0x012e Unsupported supported by the epkowa backend plus non-free interpreter
GT-F700 USB 0x04b8/0x012f Unsupported supported by the epkowa backend plus non-free interpreter
GT-F720 USB 0x04b8/0x0131 Unsupported supported by the epkowa backend plus non-free interpreter
GT-S50 USB 0x04b8/0x0137 Unsupported supported by the epkowa backend plus non-free interpreter
GT-S80 USB 0x04b8/0x0136 Unsupported supported by the epkowa backend plus non-free interpreter
GT-S600 USB 0x04b8/0x012d Unsupported supported by the epkowa backend plus non-free interpreter
GT-S620 USB 0x04b8/0x0131 Unsupported supported by the epkowa backend plus non-free interpreter
GT-X700 USB 0x04b8/0x0128 Complete IEEE1394 untested
GT-X750 USB 0x04b8/0x0119 Unsupported supported by the epkowa backend plus non-free interpreter
GT-X770 USB 0x04b8/0x0130 Unsupported supported by the epkowa backend plus non-free interpreter
GT-X800 USB 0x04b8/0x012a Complete film area guide mode not supported
IEEE1394 untested
GT-X820 USB 0x04b8/0x013a Unsupported supported by the epkowa backend plus non-free interpreter
GT-X900 USB 0x04b8/0x012c Good IEEE1394 untested
GT-X970 USB 0x04b8/0x0135 Good IEEE1394 untested
LP-7900CS ?   Untested business all-in-one; scanner is a ES-7000H
LP-9000CCH ?   Untested business all-in-one; scanner is a ES-9000H
LP-9000CCS ?   Untested business all-in-one; scanner is a ES-7000H
LP-9000CFH ?   Untested business all-in-one; scanner is a ES-9000H
LP-9500CCS ?   Untested business all-in-one; scanner is a ES-7000H
LP-9500CFH ?   Untested business all-in-one; scanner is a ES-9000H
LP-9500CH2 ?   Untested business all-in-one; scanner is a ES-9000H
LP-9800CCH ?   Untested business all-in-one; scanner is a ES-9000H
LP-9800CCS ?   Untested business all-in-one; scanner is a ES-7000H
LP-9800CFH ?   Untested business all-in-one; scanner is a ES-9000H
LP-A500 USB Network 0x04b8/0x0815 Good network interface supported
business all-in-one
LP-M5000 USB 0x04b8/0x0843 Good network interface probably supported
business all-in-one
LP-M5500 USB 0x04b8/0x0817 Good network interface probably supported
business all-in-one
LP-M5500F USB 0x04b8/0x0817 Good network interface probably supported
business all-in-one
LP-M5500 with the fax option bundled
LP-M5600 USB 0x04b8/0x0833 Good network interface probably supported
business all-in-one
LP-M6000 USB 0x04b8/0x0834 Good network interface probably supported
business all-in-one
ME 200 USB 0x04b8/0x0830 Good all-in-one
ME 300 USB 0x04b8/0x0841 Good all-in-one
overseas version of the PX-401A
ME OFFICE 510 USB 0x04b8/0x084f Good all-in-one
ME Office 600F USB 0x04b8/0x0848 Good all-in-one
ME OFFICE 650FN Series USB 0x04b8/0x0854 Good all-in-one
ME Office 700FW USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
PM-A700 USB 0x04b8/0x0814 Good all-in-one
PM-A750 USB 0x04b8/0x081a Good all-in-one
PM-A820 USB 0x04b8/0x0827 Good all-in-one
PM-A840 USB 0x04b8/0x083c Good all-in-one
PM-A840S USB 0x04b8/0x083c Good network interface probably supported
all-in-one
PM-A850 USB 0x04b8/0x0806 Good all-in-one
PM-A870 USB 0x04b8/0x0811 Good all-in-one
PM-A890 USB 0x04b8/0x081c Good all-in-one
PM-A900 USB 0x04b8/0x0810 Good all-in-one
PM-A920 USB 0x04b8/0x082a Good all-in-one
PM-A940 USB 0x04b8/0x0837 Good all-in-one
PM-A950 USB 0x04b8/0x081d Good all-in-one
PM-A970 USB 0x04b8/0x0828 Good all-in-one
PM-T960 USB 0x04b8/0x0836 Good all-in-one
PM-T990 USB 0x04b8/0x0829 Good all-in-one
PM-A970 with network interface
PX-401A USB 0x04b8/0x0841 Good all-in-one
PX-402A USB 0x04b8/0x084d Good all-in-one
PX-501A USB 0x04b8/0x084a Good network interface probably supported
all-in-one
PX-502A USB 0x04b8/0x0856 Good all-in-one
PX-601F USB 0x04b8/0x0847 Good network interface probably supported
PX-A550 USB 0x04b8/0x080e Good all-in-one
PX-A620 USB 0x04b8/0x082f Good all-in-one
PX-A640 USB 0x04b8/0x0838 Good all-in-one
PX-A650 USB 0x04b8/0x0819 Good all-in-one
PX-A720 USB 0x04b8/0x082e Good all-in-one
PX-A740 USB 0x04b8/0x0839 Good all-in-one
PX-FA700 USB 0x04b8/0x083a Good all-in-one
Perfection 600 SCSI   Unsupported supported by the umax backend
rebadged UMAX Astra 1200S
Perfection 610 USB 0x04b8/0x0103 Complete overseas version of the GT-6600U
Perfection 636S SCSI   Complete overseas version of the GT-7000S
Perfection 636U USB 0x04b8/0x0101 Complete overseas version of the GT-7000U
Perfection 640U USB 0x04b8/0x010c Complete overseas version of the GT-6700U
Perfection 660 USB 0x04b8/0x0114 Unsupported supported by the snapscan backend
Perfection 1200S SCSI   Complete overseas version of the GT-7600S
Perfection 1200U USB 0x04b8/0x0104 Complete overseas version of the GT-7600U
Perfection 1200U PHOTO USB 0x04b8/0x0104 Complete Perfection 1200U with TPU option bundled
overseas version of the GT-7600UF
Perfection 1240U USB 0x04b8/0x010b Complete overseas version of the GT-7700U
Perfection 1250 USB 0x04b8/0x010f Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 1250 PHOTO USB 0x04b8/0x010f Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 1260 USB 0x04b8/0x011d Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 1260 PHOTO USB 0x04b8/0x011d Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 1270 USB 0x04b8/0x0120 Unsupported supported by the snapscan backend
overseas version of the GT-7400
Perfection 1600 SCSI   Unsupported  
Perfection 1640SU SCSI USB 0x04b8/0x010a Complete overseas version of the GT-8700
Perfection 1640SU PHOTO SCSI USB 0x04b8/0x010a Good overseas version of the GT-8700F
Perfection 1650 USB 0x04b8/0x0110 Complete overseas version of the GT-8200U
Perfection 1650 PHOTO USB 0x04b8/0x0110 Good overseas version of the GT-8200UF
Perfection 1660 PHOTO USB 0x04b8/0x011e Complete overseas version of the GT-8300UF
Perfection 1670 USB 0x04b8/0x011f Unsupported supported by the snapscan backend
Perfection 1670 PHOTO USB 0x04b8/0x011f Unsupported supported by the snapscan backend
overseas version of the GT-8400UF
Perfection 2400 PHOTO USB 0x04b8/0x011b Complete overseas version of the GT-9300UF
Perfection 2450 PHOTO USB IEEE-1394 0x04b8/0x0112 Complete overseas version of the GT-9700F
Perfection 2480 PHOTO USB 0x04b8/0x0121 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 2580 PHOTO USB 0x04b8/0x0121 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 3170 PHOTO USB 0x04b8/0x0116 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 3200 PHOTO USB IEEE-1394 0x04b8/0x011c Complete overseas version of the GT-9800F
Perfection 3490 PHOTO USB 0x04b8/0x0122 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 3590 PHOTO USB 0x04b8/0x0122 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 4180 PHOTO USB 0x04b8/0x0118 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 4490 PHOTO USB 0x04b8/0x0119 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection 4870 PHOTO USB 0x04b8/0x0128 Complete IEEE1394 untested
overseas version of the GT-X700
Perfection 4990 PHOTO USB 0x04b8/0x012a Good film area guide mode not supported
IEEE1394 untested
overseas version of the GT-X800
Perfection 4990 Pro USB IEEE1394   Untested seems to be a 4990 PHOTO with additional software
Perfection V10 USB 0x04b8/0x012d Unsupported supported by the epkowa backend plus non-free interpreter
Perfection V30 USB 0x04b8/0x0131 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection V100 Photo USB 0x04b8/0x012d Unsupported supported by the epkowa backend plus non-free interpreter
Perfection V200 Photo USB 0x04b8/0x012e Unsupported supported by the epkowa backend plus non-free interpreter
Perfection V300 Photo USB 0x04b8/0x0131 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection V350 Photo USB 0x04b8/0x012f Unsupported supported by the epkowa backend plus non-free interpreter
Perfection V500 Photo USB 0x04b8/0x0130 Unsupported supported by the epkowa backend plus non-free interpreter
Perfection V600 Photo USB 0x04b8/0x013a Unsupported supported by the epkowa backend plus non-free interpreter
Perfection V700 Photo USB 0x04b8/0x012c Good IEEE1394 untested
overseas version of the GT-X900
Perfection V750 Photo USB 0x04b8/0x012c Good IEEE1394 untested
overseas version of the GT-X900
Stylus CX1500 USB 0x04b8/0x080c Unsupported supported by the snapscan backend
all-in-one
Stylus CX2800 USB 0x04b8/0x0830 Good all-in-one
Stylus CX2900 USB 0x04b8/0x0830 Good all-in-one
Stylus CX3100 USB 0x04b8/0x0802 Good all-in-one
overseas version of the CC-570L
Stylus CX3200 USB 0x04b8/0x0802 Good all-in-one
overseas version of the CC-570L
Stylus CX3500 USB 0x04b8/0x080e Good all-in-one
overseas version of the PX-A550
Stylus CX3600 USB 0x04b8/0x080e Good all-in-one
overseas version of the PX-A550
Stylus CX3650 USB 0x04b8/0x080e Good all-in-one
Stylus CX3700 USB 0x04b8/0x0818 Good all-in-one
Stylus CX3800 USB 0x04b8/0x0818 Good all-in-one
Stylus CX3810 USB   Untested all-in-one
Stylus CX3900 USB 0x04b8/0x082f Good all-in-one
overseas version of the PX-A620
Stylus CX4100 USB 0x04b8/0x0820 Good all-in-one
Stylus CX4200 USB 0x04b8/0x0820 Good all-in-one
Stylus CX4300 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter
Stylus CX4400 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter
Stylus CX4500 USB 0x04b8/0x080d Good all-in-one
Stylus CX4600 USB 0x04b8/0x080d Good all-in-one
Stylus CX4700 USB 0x04b8/0x0819 Good all-in-one
overseas version of the PX-A650
Stylus CX4800 USB 0x04b8/0x0819 Good all-in-one
overseas version of the PX-A650
Stylus CX4900 USB 0x04b8/0x082b Good all-in-one
Stylus CX5000 USB 0x04b8/0x082b Good all-in-one
Stylus CX5100 USB 0x04b8/0x0801 Good all-in-one
overseas version of the CC-600PX
Stylus CX5200 USB 0x04b8/0x0801 Good all-in-one
overseas version of the CC-600PX
Stylus CX5300 USB 0x04b8/0x0808 Good all-in-one
Stylus CX5400 USB 0x04b8/0x0808 Good all-in-one
Stylus CX5500 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter
Stylus CX5600 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter
Stylus CX5700F USB 0x04b8/0x0821 Unsupported may work with the snapscan backend
all-in-one with FAX
Stylus CX5800F USB 0x04b8/0x0821 Unsupported may work with the snapscan backend
all-in-one with FAX
Stylus CX5900 USB 0x04b8/0x082e Good all-in-one
overseas version of the PX-A720
Stylus CX6000 USB 0x04b8/0x082e Good all-in-one
overseas version of the PX-A720
Stylus CX6300 USB 0x04b8/0x0805 Good all-in-one
mistakenly thinks its a PX-A650
Stylus CX6400 USB 0x04b8/0x0805 Good all-in-one
mistakenly thinks its a PX-A650
Stylus CX6500 USB 0x04b8/0x0813 Good all-in-one
Stylus CX6600 USB 0x04b8/0x0813 Good all-in-one
Stylus CX6900F USB 0x04b8/0x0831 Unsupported may work with the snapscan backend
all-in-one with FAX
Stylus CX7000F USB 0x04b8/0x0831 Unsupported may work with the snapscan backend
all-in-one with FAX
Stylus CX7300 USB 0x04b8/0x0838 Good all-in-one
overseas version of the PX-A640
Stylus CX7400 USB 0x04b8/0x0838 Good all-in-one
overseas version of the PX-A640
Stylus CX7700 USB 0x04b8/0x081f Good all-in-one
Stylus CX7800 USB 0x04b8/0x081f Good all-in-one
Stylus CX8300 USB 0x04b8/0x0839 Good all-in-one
overseas version of the PX-A740
Stylus CX8400 USB 0x04b8/0x0839 Good all-in-one
overseas version of the PX-A740
Stylus CX9300F USB 0x04b8/0x083a Good all-in-one
overseas version of the PX-FA700
Stylus CX9400Fax USB 0x04b8/0x083a Good all-in-one
overseas version of the PX-FA700
Stylus DX3800 USB 0x04b8/0x0818 Good all-in-one
Stylus DX3850 USB   Good all-in-one
Stylus DX4000 USB 0x04b8/0x082f Good all-in-one
overseas version of the PX-A620
Stylus DX4200 USB 0x04b8/0x0820 Good all-in-one
Stylus DX4400 USB 0x04b8/0x083f Unsupported supported by the epkowa backend plus non-free interpreter
Stylus DX4800 USB 0x04b8/0x0819 Good all-in-one
overseas version of the PX-A650
Stylus DX4850 USB 0x04b8/0x0819 Good all-in-one
DX4800 + card reader
Stylus DX5000 USB 0x04b8/0x082b Good all-in-one
Stylus DX6000 USB 0x04b8/0x082e Good all-in-one
overseas version of the PX-A720
Stylus DX7000F USB 0x04b8/0x0831 Unsupported may work with the snapscan backend
all-in-one with FAX
Stylus DX7400 USB 0x04b8/0x0838 Good all-in-one
overseas version of the PX-A640
Stylus DX8400 USB 0x04b8/0x0839 Good all-in-one
overseas version of the PX-A740
Stylus DX9400F USB 0x04b8/0x083a Good all-in-one
overseas version of the PX-FA700
Stylus Office BX300F USB 0x04b8/0x0848 Good all-in-one
Stylus Office BX310FN Series USB 0x04b8/0x0854 Good all-in-one
Stylus Office BX600FW USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
Stylus Office BX610FW Series USB 0x04b8/0x0855 Unsupported supported by the epkowa backend plus non-free interpreter
Stylus Office TX300F USB 0x04b8/0x0848 Good all-in-one
Stylus Office TX510FN Series USB 0x04b8/0x0854 Good all-in-one
Stylus Office TX600FW USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
Stylus Office TX610FW Series USB 0x04b8/0x0855 Unsupported supported by the epkowa backend plus non-free interpreter
Stylus Photo PX650 Series USB 0x04b8/0x0850 Unsupported supported by the epkowa backend plus non-free interpreter
Stylus Photo PX700W USB Network 0x04b8/0x0846 Good network interface supported
all-in-one
overseas version of the EP-801A
Stylus Photo PX710W Series USB 0x04b8/0x0852 Unsupported supported by the epkowa backend plus non-free interpreter
Stylus Photo PX800FW USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
overseas version of the EP-901A
Stylus Photo PX810FW Series USB 0x04b8/0x0853 Unsupported supported by the epkowa backend plus non-free interpreter
Stylus Photo RX420 USB 0x04b8/0x080f Good all-in-one
Stylus Photo RX425 USB 0x04b8/0x080f Good all-in-one
Stylus Photo RX430 USB 0x04b8/0x080f Good all-in-one
Stylus Photo RX500 USB 0x04b8/0x0807 Good all-in-one
Stylus Photo RX510 USB 0x04b8/0x0807 Good all-in-one
Stylus Photo RX520 USB 0x04b8/0x081a Good all-in-one
overseas version of the PM-A750
Stylus Photo RX530 USB 0x04b8/0x081a Good all-in-one
overseas version of the PM-A750
Stylus Photo RX560 USB 0x04b8/0x0827 Good all-in-one
overseas version of the PM-A820
Stylus Photo RX585 USB 0x04b8/0x083c Good all-in-one
overseas version of the PM-A840
Stylus Photo RX580 USB 0x04b8/0x0827 Good all-in-one
overseas version of the PM-A820
Stylus Photo RX595 USB 0x04b8/0x083c Good all-in-one
overseas version of the PM-A840
Stylus Photo RX590 USB 0x04b8/0x0827 Good all-in-one
overseas version of the PM-A820
Stylus Photo RX600 USB 0x04b8/0x0806 Good all-in-one
overseas version of the PM-A850
Stylus Photo RX610 USB 0x04b8/0x083c Good all-in-one
overseas version of the PM-A840
Stylus Photo RX620 USB 0x04b8/0x0811 Good all-in-one
overseas version of the PM-A870
Stylus Photo RX630 USB 0x04b8/0x0811 Good all-in-one
overseas version of the PM-A870
Stylus Photo RX640 USB 0x04b8/0x081c Good all-in-one
overseas version of the PM-A890
Stylus Photo RX650 USB 0x04b8/0x081c Good all-in-one
overseas version of the PM-A890
Stylus Photo RX680 USB 0x04b8/0x0837 Good all-in-one
overseas version of the PM-A940
Stylus Photo RX685 USB 0x04b8/0x0837 Good all-in-one
overseas version of the PM-A940
Stylus Photo RX690 USB 0x04b8/0x0837 Good all-in-one
overseas version of the PM-A940
Stylus Photo RX700 USB 0x04b8/0x0810 Good all-in-one
overseas version of the PM-A900
Stylus Photo TX650 Series USB 0x04b8/0x0850 Unsupported supported by the epkowa backend plus non-free interpreter
Stylus Photo TX700W USB 0x04b8/0x0846 Good network interface probably supported
all-in-one
overseas version of the EP-801A
Stylus Photo TX710W Series USB 0x04b8/0x0852 Unsupported supported by the epkowa backend plus non-free interpreter
Stylus Photo TX800FW USB 0x04b8/0x0844 Good network interface probably supported
all-in-one
overseas version of the EP-901A
Stylus NX100 USB 0x04b8/0x0841 Good all-in-one
overseas version of the PX-401A
Stylus NX110 Series USB 0x04b8/0x084d Good all-in-one
overseas version of the PX-402A
Stylus NX200 USB 0x04b8/0x0849 Good all-in-one
Stylus NX210 Series USB 0x04b8/0x084f Good all-in-one
Stylus NX300 USB 0x04b8/0x0848 Good all-in-one
Stylus NX400 USB 0x04b8/0x084a Good network interface probably supported
all-in-one
overseas version of the PX-501A
Stylus NX410 Series USB 0x04b8/0x0851 Good network interface probably supported
all-in-one
Stylus NX510 Series USB 0x04b8/0x0856 Good all-in-one
overseas version of the PX-502A
Stylus SX100 USB 0x04b8/0x0841 Good all-in-one
overseas version of the PX-401A
Stylus SX110 Series USB 0x04b8/0x084d Good all-in-one
overseas version of the PX-402A
Stylus SX125 USB 0x04b8/0x085c Untested all-in-one
Stylus SX200 USB 0x04b8/0x0849 Good all-in-one
Stylus SX205 USB 0x04b8/0x0849 Good all-in-one
Stylus SX210 Series USB 0x04b8/0x084f Good all-in-one
Stylus SX400 USB 0x04b8/0x084a Good network interface probably supported
all-in-one
overseas version of the PX-501A
Stylus SX405 USB 0x04b8/0x084a Good all-in-one
Stylus SX410 Series USB 0x04b8/0x0851 Good network interface probably supported
all-in-one
Stylus SX510W Series USB 0x04b8/0x0856 Good all-in-one
overseas version of the PX-502A
Stylus SX600FW USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
Stylus SX610FW Series USB 0x04b8/0x0855 Unsupported supported by the epkowa backend plus non-free interpreter
Stylus Scan 2000 USB 0x04b8/0x0105 Untested apparently mostly the same as the Stylus Scan 2500
Stylus Scan 2500 USB 0x04b8/0x0106 Untested scanner is apparently a GT-7000
Stylus TX100 USB 0x04b8/0x0841 Good all-in-one
overseas version of the PX-401A
Stylus TX110 Series USB 0x04b8/0x084d Good all-in-one
overseas version of the PX-402A
Stylus TX200 USB 0x04b8/0x0849 Good all-in-one
Stylus TX203 USB 0x04b8/0x0849 Good all-in-one
Stylus TX209 USB 0x04b8/0x0849 Good all-in-one
Stylus TX210 Series USB 0x04b8/0x084f Good all-in-one
Stylus TX400 USB 0x04b8/0x084a Good network interface probably supported
all-in-one
overseas version of the PX-501A
Stylus TX410 Series USB 0x04b8/0x0851 Good network interface probably supported
all-in-one
Stylus TX550W Series USB 0x04b8/0x0856 Good all-in-one
overseas version of the PX-502A
WorkForce 310 Series USB 0x04b8/0x0854 Good all-in-one
WorkForce 500 USB 0x04b8/0x084c Good all-in-one
WorkForce 600 USB 0x04b8/0x0847 Good network interface probably supported
all-in-one
overseas version of the PX-601F
WorkForce 610 Series USB 0x04b8/0x0855 Unsupported supported by the epkowa backend plus non-free interpreter

Backend: fujitsu (117)

Link(s): http://www.thebility.com/fujitsu/
Manual page: sane-fujitsu
Comment: Backend updated for SANE release 1.0.23, see sane-fujitsu manpage

Manufacturer Model Interface USB id Status Comment
Fujitsu M3091DC SCSI   Complete small, old, discontinued
M3092DC SCSI   Complete small, old, discontinued
fi-4120C SCSI USB 0x04c5/0x1041 Complete small, recent, discontinued, usb 1.1
fi-4120C2 SCSI USB 0x04c5/0x10ae Complete small, recent, discontinued, usb 2.0
fi-4220C SCSI USB 0x04c5/0x1042 Complete small, recent, discontinued, usb 1.1
fi-4220C2 SCSI USB 0x04c5/0x10af Complete small, recent, discontinued, usb 2.0
fi-5110C USB 0x04c5/0x1097 Complete small, recent, discontinued
fi-5110EOX/2 USB 0x04c5/0x1096 Complete small, recent, discontinued
fi-5110EOX3 USB 0x04c5/0x10e6 Complete small, recent, discontinued
fi-5110EOXM USB 0x04c5/0x10f2 Complete small, recent, discontinued
fi-5120C SCSI USB 0x04c5/0x10e0 Complete small, recent, discontinued
fi-5220C SCSI USB 0x04c5/0x10e1 Complete small, recent, discontinued
fi-5000N Ethernet   Untested Not a scanner, rather a scanner to ethernet interface
fi-6000NS Ethernet   Untested small, recent, discontinued, integrated touchscreen and keyboard
ScanSnap S500 USB 0x04c5/0x10fe Complete small, recent, discontinued
ScanSnap S500M USB 0x04c5/0x1135 Complete small, recent, discontinued
ScanSnap S510 USB 0x04c5/0x1155 Complete small, recent, discontinued
ScanSnap S510M USB 0x04c5/0x116f Complete small, recent, discontinued
fi-6130 USB 0x04c5/0x114f Complete small, recent, discontinued
fi-6230 USB 0x04c5/0x1150 Complete small, recent, discontinued
ScanSnap S1500 USB 0x04c5/0x11a2 Complete small, discontinued
ScanSnap S1500M USB 0x04c5/0x11a2 Complete small, discontinued, same as S1500
ScanSnap N1800 Ethernet   Untested small, current, integrated touchscreen and keyboard
ScanSnap fi-6010N Ethernet   Untested small, current, integrated touchscreen and keyboard
fi-6110 USB 0x04c5/0x11fc Complete small, current
fi-6130Z USB 0x04c5/0x11f3 Complete small, current
fi-6230Z USB 0x04c5/0x11f4 Complete small, current
ScanSnap iX500 USB WiFi 0x04c5/0x132b Good small, current, WiFi not supported. Hardware only scans in color. Backend generates binary and grayscale modes.
M3093E RS232C/Video   Unsupported medium, old, discontinued
M3093DE RS232C/Video   Unsupported medium, old, discontinued
M3093DG SCSI   Complete medium, old, discontinued
M3093EX RS232C/Video   Unsupported medium, old, discontinued
M3093GX SCSI   Complete medium, old, discontinued
M3096EX RS232C/Video   Unsupported medium, old, discontinued
M3096GX SCSI   Complete medium, old, discontinued
M3097E+ RS232C/Video   Unsupported medium, old, discontinued
M3097G+ SCSI   Complete medium, old, discontinued
M3097DE RS232C/Video   Unsupported medium, old, discontinued
M3097DG SCSI   Complete medium, old, discontinued
fi-4340C SCSI USB 0x04c5/0x10cf Complete medium, current
fi-4530C SCSI USB 0x04c5/0x1078 Complete medium, recent, discontinued
fi-4640S SCSI   Complete medium, recent, discontinued
fi-4750C SCSI   Complete medium, recent, discontinued
fi-5530C SCSI USB 0x04c5/0x10e2 Complete medium, recent, discontinued
fi-6140 SCSI USB 0x04c5/0x114d Complete medium, recent, discontinued
fi-6240 SCSI USB 0x04c5/0x114e Complete medium, recent, discontinued
fi-5530C2 SCSI USB 0x04c5/0x114a Complete medium, current
fi-6140Z SCSI USB 0x04c5/0x11f1 Complete medium, current
fi-6240Z SCSI USB 0x04c5/0x11f2 Complete medium, current
M3099A RS232C/Video   Unsupported big, old, discontinued
M3099G SCSI   Complete big, old, discontinued
M3099EH RS232C/Video   Unsupported big, old, discontinued
M3099GH SCSI   Complete big, old, discontinued
M3099EX RS232C/Video   Unsupported big, old, discontinued
M3099GX SCSI   Complete big, old, discontinued
M4097D SCSI   Complete big, old, discontinued
M4099D SCSI   Complete big, old, discontinued
fi-4750L SCSI   Complete big, recent, discontinued
fi-4860C SCSI   Complete big, recent, discontinued
fi-4860C2 SCSI   Complete big, recent, discontinued
fi-4990C SCSI   Complete big, recent, discontinued
fi-5650C SCSI USB 0x04c5/0x10ad Complete big, recent, discontinued
fi-5750C SCSI USB 0x04c5/0x1095 Complete big, recent, discontinued
fi-5900C SCSI USB 0x04c5/0x10e7 Good big, recent, discontinued. Independent ultrasonic control and multistream unsupported
fi-6750S USB 0x04c5/0x1178 Untested Simplex, USB only version of fi-6770, won't wakeup via software, discontinued
fi-5950 SCSI USB 0x04c5/0x1213 Untested big, current. Faster version of fi-5900?
fi-6670 SCSI USB 0x04c5/0x1176 Good big, current, won't wakeup via software
fi-6670A SCSI USB 0x04c5/0x1177 Good big, current, VRS CGA board unsupported, won't wakeup via software
fi-6770 SCSI USB 0x04c5/0x1174 Good big, current, won't wakeup via software
fi-6770A SCSI USB 0x04c5/0x1175 Good big, current, VRS CGA board unsupported, won't wakeup via software
fi-6800 SCSI USB 0x04c5/0x119d Untested big, current. Independent ultrasonic control and multistream unsupported
fi-6800-CGA SCSI USB 0x04c5/0x119e Untested big, current. VRS CGA board unsupported, Independent ultrasonic control and multistream unsupported

Backend: genesys (1.0-63)

Link(s): http://www.meier-geinitz.de/sane/genesys-backend/
Manual page: sane-genesys
Comment: Only the USB scanners mentioned below are currently supported.

Manufacturer Model Interface USB id Status Comment
Plustek OpticBook 3600 USB 0x07b3/0x0900 Basic Has a Primax USB ID
Medion/Lifetec/Tevion/Cytron MD5345 USB 0x0461/0x0377 Good Has a Primax USB ID
MD6228 USB 0x0461/0x0377 Good Has a Primax USB ID. Same as MD5345
MD6471 USB 0x0461/0x0377 Complete Has a Primax USB ID. Same as MD5345
Hewlett-Packard ScanJet 2300C USB 0x03f0/0x0901 Complete 600x1200 dpi max
ScanJet 2400C USB 0x03f0/0x0a01 Complete 1200x1200 dpi max
ScanJet G2410 USB 0x03f0/0x0a01 Basic clone of the HP 2400C
ScanJet 3670C USB 0x03f0/0x1405 Complete 1200x1200 dpi max, complete transparency adaptor support
ScanJet 3690C USB 0x03f0/0x1405 Complete 1200x1200 dpi max, same as HP 3670C
ScanJet 4850C USB 0x03f0/0x1b05 Untested resolution from 100 to 2400 supported, UTA not supported yet
ScanJet G4010 USB 0x03f0/0x4505 Good resolution from 100 to 2400 supported, UTA not supported yet
ScanJet G4050 USB 0x03f0/0x4605 Good resolution from 100 to 2400 supported, UTA not supported yet
ScanJet N6310 USB 0x03f0/0x4705 Untested Not supported yet
Canon CanoScan LiDE 35 USB 0x04a9/0x2213 Good Same ids as LiDE 50.
CanoScan LiDE 40 USB 0x04a9/0x2213 Good Same ids as LiDE 50.
CanoScan LiDE 50 USB 0x04a9/0x2213 Good  
CanoScan LiDE 60 USB 0x04a9/0x221c Good  
CanoScan LiDE 100 USB 0x04a9/0x1904 Complete GL847 based, resolution from 75 to 2400 dpi
CanoScan LiDE 110 USB 0x04a9/0x1909 Complete GL124 based, resolution from 75 to 2400 dpi
CanoScan LiDE 200 USB 0x04a9/0x1905 Complete GL847 based, resolution from 75 to 4800 dpi
CanoScan LiDE 210 USB 0x04a9/0x190a Complete GL124 based, resolution from 75 to 2400 dpi
CanoScan 4400f USB 0x04a9/0x2228 Unsupported GL843 based, to be added to the genesys backend
CanoScan 5600F USB 0x04a9/0x1906 Unsupported GL847 based, to be added to the genesys backend
CanoScan 700F USB 0x04a9/0x1907 Good GL847 based, resolution from 75 to 4800 dpi
Canon Image Formula 101 USB 0x1083/0x162e Unsupported GL846 based, work in progress
Visioneer Strobe XP 100,r3 USB 0x04a7/0x049b Good All resolution and mode supported, calibration is available
Strobe XP 200 USB 0x04a7/0x0426 Good All resolution and mode supported, calibration is available
Strobe XP 300 USB 0x04a7/0x0474 Good All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally.
Roadwarrior USB 0x04a7/0x0494 Basic All resolution and mode supported, calibration is available
Visioneer OneTouch 7100 USB 0x04a7/0x0229 Complete Same as MD5345
Pentax DSmobile 600 USB 0x0a17/0x3210 Good All resolution and mode supported, calibration is available
DSmobile 600 USB 0x04f9/0x2038 Good All resolution and mode supported, calibration is available
DCT DocketPort 487 USB 0x1dcc/0x4810 Basic All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally.
Syscan DocketPort 485 USB 0x0a82/0x4810 Basic All resolution and mode supported, front- and backside side-by-side, with backside mirrored horizontally.
DocketPort 465 USB 0x0a82/0x4802 Untested All resolution and mode should be supported, but uncorrected scans
DocketPort 665 USB 0x0a82/0x4803 Basic All resolution and mode supported, calibration is available
DocketPort 685/ Ambir DS685 USB 0x0a82/0x480c Good All resolution and mode supported, calibration is available, front- and backside side-by-side, with backside mirrored horizontally.
Xerox Travel Scanner 100 USB 0x04a7/0x04ac Good All resolution and mode supported, calibration is available
2400 Onetouch USB 0x0461/0x038b Complete GL646 based, resolution from 75 to 2400 dpi
Panasonic KV-SS080 USB 0x04da/0x100f Complete All resolution and mode supported, calibration is available. Support sponsored by cncsolutions (http://www.cncsolutions.com.br)

Backend: gt68xx (1.0-84)

Link(s): http://www.meier-geinitz.de/sane/gt68xx-backend/
Manual page: sane-gt68xx
Comment: Only the USB scanners mentioned below are supported. For other Mustek BearPaws, look at the Plustek and the MA-1509 backend.

Manufacturer Model Interface USB id Status Comment
Artec/Ultima Ultima 2000 USB 0x05d8/0x4002 Good Works, only product id 0x4002 is supported
Ultima 2000 e+ USB 0x05d8/0x4002 Good Works, however 12 bit mode doesn't seem to be supported
Boeder Sm@rtScan Slim Edition USB 0x05d8/0x4002 Good Similar to Artec Ultima 2000
Fujitsu 1200CUS USB 0x05d8/0x4002 Basic Works, but is slow. Probably a Mustek BearPaw 2400 CU clone.
Genius ColorPage Slim 1200 USB 0x0458/0x201e Untested Untested but should work.
Colorpage SF600 USB 0x0458/0x2021 Basic  
Colorpage Vivid3x USB 0x0458/0x2011 Good  
Colorpage Vivid3 V2 USB 0x0458/0x2011 Good Same as Colorpage Vivid3x
Colorpage Vivid3xe USB 0x0458/0x2017 Good  
Colorpage Vivid4 USB 0x0458/0x2014 Good  
Colorpage Vivid4x USB 0x0458/0x201b Good  
Colorpage Vivid4xe USB 0x0458/0x201a Good  
Colorpage Vivid 1200 X USB 0x0458/0x201d Good  
Colorpage Vivid 1200 XE USB 0x0458/0x201f Good  
Googlegear 2000 USB 0x05d8/0x4002 Good Same as Artec Ultima 2000.
Lexmark X70 USB 0x043d/0x002d Good Works, some resolutions fail at 16 bit
X73 USB 0x043d/0x002d Good Works, some resolutions fail at 16 bit, same as X70
Medion/Lifetec/Tevion/Cytron MD 4394 USB 0x05d8/0x4002 Good Product id 0x4002. If you have 0x4003, use artec_eplus48u backend.
MD/LT 9375 USB 0x05d8/0x4002 Untested Untested, but is reported to have the same ids as the Artec Ultima 2000. Please test.
MD/LT 9385 USB 0x05d8/0x4002 Good Similar to Artec Ultima 2000
LT 9452 USB 0x05d8/0x4002 Good Similar to Mustek ScanExpress 1200 UB Plus
MD 9458 USB 0x05d8/0x4002 Good Similar to Artec Ultima 2000 (e+?)
Mustek BearPaw 1200 CS USB 0x055f/0x021e Good  
BearPaw 1200 CU USB 0x05d8/0x4002 Good  
BearPaw 1200 CU Plus USB 0x055f/0x021b Good  
BearPaw 1200 CU Plus USB 0x055f/0x021c Good  
BearPaw 1200 TA USB 0x055f/0x021e Good Transparency adapter supported
BearPaw 1248 CU USB 0x055f/0x021c Good Seems to use the same ids as BearPaw 1200 CU Plus.
BearPaw 2400 CS USB 0x055f/0x0218 Untested Probably works, reports are welcome
BearPaw 2400 CS Plus USB 0x055f/0x0219 Good Works, problems with 12/16 bit modes?
BearPaw 2400 CU USB 0x05d8/0x4002 Basic Works, but is slow
BearPaw 2400 CU Plus USB 0x055f/0x021d Good  
BearPaw 2400 TA USB 0x055f/0x0218 Good Transparency adapter supported
BearPaw 2400 TA Plus USB 0x055f/0x0219 Good Transparency adapter supported
BearPaw 2448 CS Plus USB 0x055f/0x021a Basic Slow. Same as 2448 TA Plus, but without TA.
BearPaw 2448 TA Plus USB 0x055f/0x021a Basic Slow. Transparency adapter supported. Slow. Brightness depends on resolution?
Plug-n-Scan 2400 MT USB 0x055f/0x0219 Good Works but is slow in high resolutions. Same as BearPaw 2400 TA Plus.
Plug-n-Scan 2400 M USB 0x055f/0x0219 Good Works but is slow in high resolutions. Same as BearPaw 2400 CS Plus.
ScanExpress 1200 UB Plus USB 0x05d8/0x4002 Good  
ScanExpress 1248 UB USB 0x055f/0x021f Complete  
ScanExpress 2400 USB USB 0x05d8/0x4002 Minimal Should be detected but may need some more work in the code. Testers welcome. Please contact me if you own this scanner.
ScanExpress A3 USB USB 0x055f/0x0210 Basic Still some vertical stripes.
ScanMagic 1200 UB Plus USB 0x05d8/0x4002 Good Same as ScanExpress 1200 UB Plus
NeatReceipts Scanalizer Professional 2.5 USB 0x07b3/0x0412 Untested Similar to Plustek OpticSlim M12. Please tell us if this scanner works.
Mobile Scanner USB 0x07b3/0x0462 Basic Similar to Plustek OpticSlim M12.
Nortek MyScan 1200 USB 0x07b3/0x040b Untested Untested. Please test. Similar to Plustek OpticPro S12?
Packard Bell Diamond 1200 USB 0x05d8/0x4002 Good Similar to Mustek BearPaw 1200 (Plus)
Diamond 1200 Plus USB 0x055f/0x021c Good Similar to Mustek BearPaw 1200 Plus
Diamond 1200 Plus USB 0x055f/0x021b Good Similar to Mustek BearPaw 1200 Plus
Diamond 2450 USB 0x055f/0x0219 Good  
Plustek OpticPro 1248U USB 0x07b3/0x0400 Good  
OpticPro 1248U USB 0x07b3/0x0401 Good  
OpticPro U16B USB 0x07b3/0x0402 Good  
OpticPro U16B+ USB 0x07b3/0x0403 Good  
OpticPro UT16B USB 0x07b3/0x0403 Untested Probably works. Transparency adapter not supported yet. Please contact me if you own such a device.
OpticPro S12 USB 0x07b3/0x040b Good Product ID 0x040b only.
OpticPro S24 USB 0x07b3/0x040e Good Product ID 0x040e only. Is reported to work.
OpticPro ST12 USB 0x07b3/0x040b Untested Product ID 0x040b only. Needs testing. Transparency adapter completely untested. Please contact me if you own such a scanner.
OpticSlim 1200 USB 0x07b3/0x0413 Good  
OpticSlim 2400 USB 0x07b3/0x0422 Good Works up to 1200 dpi.
OpticSlim 2400 plus USB 0x07b3/0x0454 Good Same as OpticSlim 2400.
Iriscan Express 2 USB 0x07b3/0x045f Complete Works up to 1200 dpi. Calibration with external calibration sheet supported
OpticSlim M12 USB 0x07b3/0x0412 Complete Works up to 1200 dpi. Calibration with external calibration sheet supported
RevScan 19200i USB 0x07b3/0x0400 Good Similar to Plustek OpticPro 1248U
Trust 240TH Easy Webscan Gold USB 0x055f/0x0218 Good Same as Mustek Bearpaw 2400 TA plus.
Compact Scan USB 19200 USB 0x05d8/0x4002 Good Works, if you have vendor id 0x055f and product id 0x0006, use the mustek_usb backend instead, similar to Mustek ScanExpress 1200 UB (Plus)
Direct WebScan 19200 USB 0x055f/0x021c Good Same as Mustek BearPaw 1200 CU Plus (0x021c).
Flat Scan USB 19200 USB 0x05d8/0x4002 Good Similar to Artec Ultima 2000
Visioneer OneTouch 7300 USB 0x04a7/0x0444 Good Works upto 1200 dpi and 12 bits/color.

Backend: hp (1.06)

Link(s): http://www.kirchgessner.net/
Manual page: sane-hp

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard ScanJet Plus Propietary   Complete Driver for HP parallel interface card required
ScanJet IIc SCSI   Complete  
ScanJet IIp SCSI   Complete  
ScanJet IIcx SCSI   Complete  
ScanJet 3c SCSI   Complete  
ScanJet 3p SCSI   Complete  
ScanJet 4c SCSI   Complete  
ScanJet 4p SCSI   Complete  
ScanJet 4100C USB 0x03f0/0x0101 Complete  
ScanJet 5p SCSI   Complete  
ScanJet 5100C Parport   Complete Requires ppscsi driver and epst module
ScanJet 5200C Parport USB 0x03f0/0x0401 Complete Parallel interface requires ppscsi driver and epst module
ScanJet 6100C SCSI   Complete  
ScanJet 6200C SCSI USB 0x03f0/0x0201 Complete  
ScanJet 6250C SCSI USB 0x03f0/0x0201 Complete  
ScanJet 6300C SCSI USB 0x03f0/0x0601 Complete  
ScanJet 6350C SCSI USB 0x03f0/0x0601 Complete  
ScanJet 6390C SCSI USB 0x03f0/0x0601 Complete  
PhotoSmart PhotoScanner SCSI   Complete  

Backend: hp3500 (1.1)

Link(s): http://projects.troy.rollo.name/rt-scanners/
Manual page: sane-hp3500
Comment: HP3500 series scanners.

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard ScanJet 3500C USB 0x03f0/0x2205 Good  
ScanJet 3530C USB 0x03f0/0x2005 Good  
ScanJet 3570C USB 0x03f0/0x2005 Good  

Backend: hp3900 (0.12)

Link(s): http://sourceforge.net/projects/hp3900-series/
Manual page: sane-hp3900
Comment: Still Beta

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard ScanJet 3800 USB 0x03f0/0x2605 Basic Works with resolutions equal and less than 600dpi
ScanJet 3970c USB 0x03f0/0x2305 Good  
ScanJet 4070 Photosmart USB 0x03f0/0x2405 Good  
ScanJet 4370 USB 0x03f0/0x4105 Basic Works with resolutions lower than 1200dpi
ScanJet G2710 USB 0x03f0/0x2805 Basic Similar to hp scanjet 3800
ScanJet G3010 USB 0x03f0/0x4205 Basic Similar to hp scanjet 4370
ScanJet G3110 USB 0x03f0/0x4305 Basic Similar to hp scanjet 4370
UMAX Astra 4900 USB 0x06dc/0x0020 Minimal developing yet
BenQ 5550 USB 0x04a5/0x2211 Minimal developing yet

Backend: hp4200 (1.0-2)

Link(s): http://hp4200-backend.sourceforge.net
Manual page: sane-hp4200

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard ScanJet 4200C USB 0x03f0/0x0105 Basic 8bpp color, 75/150/300/600 dpi only
ScanJet 4200Cxi USB 0x03f0/0x0105 Basic 8bpp color, 75/150/300/600 dpi only
ScanJet 4200Cse USB 0x03f0/0x0105 Basic 8bpp color, 75/150/300/600 dpi only

Backend: hp5400 (1.0-2)

Link(s): http://sourceforge.net/projects/hp5400backend
Manual page: sane-hp5400
Comment: HP5400 and HP5470 scanners. Prototype backend available

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard ScanJet 5400c USB 0x03f0/0x1005 Basic  
ScanJet 5470c USB 0x03f0/0x1105 Basic  
ScanJet 5490c USB   Basic  

Backend: hp5590 (1.0.5)

Manual page: sane-hp5590

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard ScanJet 4500C USB 0x03f0/0x1205 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives
ScanJet 4570C USB 0x03f0/0x1305 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives
ScanJet 5500C USB 0x03f0/0x1305 Untested Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/TMA slides/TMA negatives
ScanJet 5550C USB 0x03f0/0x1205 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives
ScanJet 5590 USB 0x03f0/0x1705 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives
ScanJet 7650 USB 0x03f0/0x1805 Complete Lineart/grayscale/color (24 bit), 100/200/300/600/1200/2400 DPI, flatbed/ADF/ADF duplex/TMA slides/TMA negatives

Backend: hpljm1005 (0)

Manual page: sane-hpljm1005

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard LaserJet M1005 MFP USB 0x03f0/0x3b17 Good grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI
LaserJet M1120 MFP USB 0x03f0/0x5617 Good grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI
LaserJet M1120n MFP USB 0x03f0/0x5717 Good grayscale/color (24 bit), 75/100/150/200/300/600/1200 DPI

Backend: hpsj5s (0.03)

Link(s): http://hpsj5s.sourceforge.net/
Manual page: sane-hpsj5s

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard ScanJet 5s Parport (EPP)   Minimal Requires libieee1284 library. Only gray mode.

Backend: hs2p (1.00)

Link(s): http://www.acjlaw.net:8080/~jeremy/Ricoh/
Manual page: sane-hs2p
Comment: This backend has been tested with the IS450DE (Duplex/Endorser). All major functions necessary for scanning are supported. This backend should work with all Ricoh scanners in the IS450 family as well as the IS420 series, but the IS420 has not yet been tested. Features provided by the optional Image Processing Unit (IPU) are not yet integrated into the backend, as my scanner lacks the IPU.

Manufacturer Model Interface USB id Status Comment
Ricoh IS450 SCSI   Complete All major scanning-related features are supported (except for IPU). Certain non-scanning features, such as those related to scanner maintenance, are not supported. Such features would be better implemented in a separate stand-alone tool. For instance, if you replace the ADF Unit, you must recalibrate the scanner optics using a Ricoh Test Sheet and reset the E^2PROM registers. Reports are welcome.
IS-410 SCSI   Untested Untested, please report!
IS-420 SCSI   Untested Untested, please report!
IS-430 SCSI   Untested Untested, please report!

Backend: ibm (1.0-4)

Link(s): http://www.meier-geinitz.de/sane/ibm-backend/
Manual page: sane-ibm
Comment: This backend has had only limited testing. It needs more work especially for the Ricoh scanners. Patches are welcome.

Manufacturer Model Interface USB id Status Comment
IBM 2456 SCSI   Basic Was reported to work long time ago. Reports are welcome.
Ricoh IS-410 SCSI   Untested Untested, please report!
IS-420 SCSI   Basic Works at least in flatbed mode.
IS-430 SCSI   Untested Untested, please report!

Backend: kodak (7)

Link(s): http://www.thebility.com/kodak/
Manual page: sane-kodak
Comment: New backend for SANE release 1.0.21, see sane-kodak manpage

Manufacturer Model Interface USB id Status Comment
Kodak Scanner 1500 SCSI   Untested Please test!
Scanner 2500 SCSI   Untested Please test!
Scanner 3500 SCSI   Untested Please test!
Scanner 3510 SCSI   Untested Please test!
Scanner 3520 SCSI   Untested Please test!
Color Scanner 3590C SCSI   Untested Please test!
Color Scanner 4500 SCSI   Untested Please test!
i150 Scanner IEEE-1394   Untested Please test!
i160 Scanner IEEE-1394   Untested Please test!
i250 Scanner IEEE-1394   Untested Please test!
i260 Scanner IEEE-1394   Untested Please test!
i280 Scanner IEEE-1394   Untested Please test!
Scanner 900 SCSI   Untested Please test!
Scanner 923 SCSI   Untested Please test!
Scanner 5500 SCSI   Untested Please test!
Scanner 7500 SCSI   Untested Please test!
Scanner 7520 SCSI   Untested Please test!
Scanner 9500 SCSI   Untested Please test!
Scanner 9520 SCSI   Untested Please test!
i610 Scanner IEEE-1394   Untested Please test!
i620 Scanner IEEE-1394   Untested Please test!
i640 Scanner IEEE-1394   Untested Please test!
i660 Scanner IEEE-1394   Untested Please test!
i730 Scanner IEEE-1394   Untested Please test!
i750 Scanner IEEE-1394   Untested Please test!
i780 Scanner IEEE-1394   Untested Please test!
i810 Scanner SCSI   Untested Please test!
i820 Scanner SCSI   Untested Please test!
i830 Scanner SCSI   Untested Please test!
i840 Scanner SCSI   Untested Please test!
i1840 Scanner IEEE-1394   Untested Please test!
i1860 Scanner IEEE-1394   Basic Uncompressed B&W, Gray and Color, some automatic features supported
s1740 SCSI   Untested Please test!

Backend: kodakaio (2.4.6)

Link(s): http://sourceforge.net/projects/cupsdriverkodak/
Manual page: sane-kodakaio
Comment: Backend for Kodak AiO ESP and Hero printers. Also possibly Advent AWL10

Manufacturer Model Interface USB id Status Comment
Kodak ESP 2150 USB 0x040a/0x4059 Untested Please test!
ESP 2170 USB 0x040a/0x4066 Untested Please test!
ESP 3200 USB 0x040a/0x4043 Untested Please test!
ESP 3300 USB 0x040a/0x4031 Untested Please test!
ESP 4100 USB 0x040a/0x4053 Untested Please test!
ESP 5000 USB 0x040a/0x4028 Untested Please test!
ESP 5100 USB 0x040a/0x4025 Untested Please test!
ESP 5200 USB Ethernet 0x040a/0x4041 Basic USB good, Network good
ESP 5300 USB 0x040a/0x4026 Untested Please test!
ESP 5500 USB 0x040a/0x4027 Untested Please test!
ESP 6100 USB 0x040a/0x4054 Untested Please test!
ESP 7200 USB 0x040a/0x4056 Untested Please test!
ESP 9200 USB 0x040a/0x4065 Untested Please test!
ESP 5 USB 0x040a/0x4032 Untested Please test!
ESP 7 USB 0x040a/0x403e Untested Please test!
ESP 9 USB 0x040a/0x403f Untested Please test!
ESP C110 USB 0x040a/0x4057 Untested Please test!
ESP C115 USB 0x040a/0x4058 Untested Please test!
ESP C310 USB 0x040a/0x405d Untested Please test!
ESP C315 USB 0x040a/0x405e Untested Please test!
Hero 3.1 USB 0x040a/0x406d Untested Please test!
Hero 5.1 USB 0x040a/0x4064 Untested Please test!
Hero Office 6.1 USB 0x040a/0x4062 Untested Please test!
Hero 7.1 USB 0x040a/0x4063 Untested Please test!
Hero 9.1 USB Ethernet 0x040a/0x4067 Basic USB good, Network good
Advent AW10 USB 0x040a/0x4060 Untested Please test!

Backend: kvs20xx (unmaintained)

Manual page: sane-kvs20xx
Comment: New backend for SANE release 1.0.22, see sane-kvs20xx manpage

Manufacturer Model Interface USB id Status Comment
Panasonic KV-S2025C SCSI   Untested  
KV-S2026C USB SCSI 0x04da/0x1000 Untested  
KV-S2028C USB 0x04da/0x100a Untested  
KV-S2045C SCSI   Untested  
KV-S2046C USB SCSI 0x04da/0x1001 Untested  
KV-S2048C USB 0x04da/0x1009 Untested  

Backend: kvs40xx (unmaintained)

Manual page: sane-kvs40xx
Comment: New backend for SANE release 1.0.23, see sane-kvs40xx manpage

Manufacturer Model Interface USB id Status Comment
Panasonic KV-S4065C USB 0x04da/0x100d Untested  
KV-S4085C USB 0x04da/0x100c Untested  
KV-S7075C USB 0x04da/0x100e Untested  

Backend: kvs1025 (unmaintained)

Manual page: sane-kvs1025
Comment: New backend for SANE release 1.0.21, see sane-kvs1025 manpage

Manufacturer Model Interface USB id Status Comment
Panasonic KV-S1020C USB 0x04da/0x1007 Good  
KV-S1025C USB 0x04da/0x1006 Good  
KV-S1045C USB 0x04da/0x1010 Good  

Backend: leo (1.0-10)

Link(s): http://www.zago.net/sane/#leo
Manual page: sane-leo

Manufacturer Model Interface USB id Status Comment
LEO LEOScan S3 SCSI   Good FCC ID LUZFS1130
Across Technologies FS-1130 SCSI   Good FCC ID LUZFS1130
Genius FS-1130 Colorpage Scanner SCSI   Good  

Backend: lexmark (1.0-0)

Link(s): http://stef.dev.free.fr/sane/lexmark
Manual page: sane-lexmark
Comment: This backend supports lexmark x1100 series scanners.

Manufacturer Model Interface USB id Status Comment
Lexmark X1110 USB 0x043d/0x007c Untested  
X1130 USB 0x043d/0x007c Good Supports 75, 150, 300, 600 dpi
X1140 USB 0x043d/0x007c Untested  
X1150 USB 0x043d/0x007c Good Supports 75, 150, 300, 600 dpi
X1170 USB 0x043d/0x007c Good Supports 75, 150, 300, 600 dpi
X1180 USB 0x043d/0x007c Good  
X1185 USB 0x043d/0x007c Good Tested with xscanimage. Supports 75, 150, 300, 600, 1200(600x1200) dpi resolutions. Does grayscale or colour scans in the following sizes: wallet, 3x5, 4x6, 5x7, 8x10, letter.
X1195 USB 0x043d/0x007c Untested  
X74 USB 0x043d/0x0060 Good Supports 75, 150, 300, 600 dpi
X12xx USB 0x043d/0x007d Good USB1.1 is OK, USB2.0 needs testing
Dell A920 USB 0x413c/0x5105 Good Relabelled X11xx model

Backend: ma1509 (1.0-3)

Link(s): http://www.meier-geinitz.de/sane/ma1509-backend/
Manual page: sane-ma1509

Manufacturer Model Interface USB id Status Comment
Mustek BearPaw 1200 F USB 0x055f/0x0010 Good Works upto 600 dpi. No support for TA and ADF yet.
Fujitsu fi-4110EOX/2/3 USB 0x04c5/0x1040 Unsupported Uses ma1509 chip, but very different from other scanners supported by the ma1509 backend

Backend: magicolor (1.0.0)

Link(s): http://wiki.kainhofer.com/hardware/magicolor_scan
Manual page: sane-magicolor

Manufacturer Model Interface USB id Status Comment
KONICA MINOLTA magicolor 1690MF USB Network 0x132b/0x2089 Good Multi-function color laser printer with fax, scanner and network interface
BizHub 162/132 USB Network   Unsupported Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov.
DiMage 1611 USB Network   Unsupported Uses a similar protocol as the magicolor 1690MF, according to Ilia Sotnikov.

Backend: matsushita (1.0-7)

Link(s): http://www.zago.net/sane
Manual page: sane-matsushita

Manufacturer Model Interface USB id Status Comment
Panasonic KV-SS25 SCSI   Complete  
KV-SS25D SCSI   Complete  
KV-SS50 SCSI   Untested  
KV-SS55 SCSI   Untested  
KV-SS50EX SCSI   Untested  
KV-SS55EX SCSI   Minimal no color, no high resolution, no automatic cropping
KV-SS850 SCSI   Untested  
KV-SS855 SCSI   Untested  
KV-S2025C SCSI   Minimal no color, no high resolution, no automatic cropping
KV-S2045C SCSI   Minimal no color, no high resolution, no automatic cropping
KV-S2065L SCSI   Minimal no color, no high resolution, no automatic cropping

Backend: microtek (0.13.1)

Link(s): http://www.mir.com/mtek/
Manual page: sane-microtek

Manufacturer Model Interface USB id Status Comment
Microtek Scanmaker E6 SCSI   Good  
Scanmaker E3 SCSI   Good  
Scanmaker E2 SCSI   Good 3-pass
Scanmaker 35t+ SCSI   Good slide-scanner
Scanmaker 45t SCSI   Good slide-scanner
Scanmaker 35 SCSI   Good slide-scanner
Scanmaker III SCSI   Good  
Scanmaker IISP SCSI   Good  
Scanmaker IIHR SCSI   Good 3-pass
Scanmaker IIG SCSI   Good gray only
Scanmaker II SCSI   Good 3-pass
Scanmaker 600Z(S) SCSI   Untested  
Scanmaker 600G(S) SCSI   Basic gray only (see manpage)
Color PageWiz SCSI (Parport)   Basic sheet-fed (preliminary, see mapage)
Agfa Arcus II SCSI   Good Arcus *II*, not Arcus!
StudioScan SCSI   Good  
StudioScan II SCSI   Good  
StudioScan IIsi SCSI   Good  
Studiostar SCSI   Minimal Is detected but scans are very dark
DuoScan SCSI   Basic  
Vobis Highscreen Realscan SCSI   Good  
Genius Colorpage-SP2 SCSI   Good Same as Microtek Scanmaker E3

Backend: microtek2 (unmaintained)

Link(s): http://karstenfestag.gmxhome.de/linux.html
Manual page: sane-microtek2

Manufacturer Model Interface USB id Status Comment
Microtek ScanMaker E3plus Parport   Complete  
ScanMaker E3plus SCSI   Complete  
ScanMaker X6 SCSI   Complete  
ScanMaker X6EL SCSI   Basic  
ScanMaker X6USB USB 0x05da/0x0099 Good  
ScanMaker V300 SCSI   Good  
ScanMaker V300 Parport   Good  
ScanMaker V310 SCSI   Basic  
ScanMaker V310 Parport   Basic  
ScanMaker V600 SCSI   Basic  
ScanMaker V600 Parport   Basic  
ScanMaker 330 SCSI   Basic  
ScanMaker 630 SCSI   Basic  
ScanMaker 636 SCSI   Complete  
ScanMaker 6400XL SCSI   Complete  
ScanMaker 9600XL SCSI   Good only flatbed mode ?
ScanMaker 9800XL IEEE-1394   Minimal IEEE-1394 seems to work. See link. More reports welcome.
Phantom 330CX Parport   Complete  
SlimScan C3 Parport   Complete  
Phantom 636 SCSI   Complete  
Phantom 636CX Parport   Complete  
SlimScan C6 USB 0x05da/0x009a Complete  
ScanMaker V6UPL USB 0x05da/0x00b6 Basic Sometimes scan speed goes to fast and results look badly smudged.
ScanMaker V6USL SCSI   Complete  
ScanMaker V6USL USB 0x05da/0x00a3 Complete  
ScanMaker V6USL USB 0x05da/0x80a3 Complete  
ScanMaker X12USL SCSI   Good only Flatbed mode ?
Vobis HighScan SCSI   Complete only E3plus based models
Scanport SQ300 Parport?   Basic  
SQ2030 Parport   Basic  
SQ4836 SCSI   Basic  
Genius ColorPage-EP Parport   Good  

Backend: mustek (1.0-138)

Link(s): http://www.meier-geinitz.de/sane/mustek-backend/
Manual page: sane-mustek
Comment: Most Mustek SCSI scanners are supported by this backend. For USB scanners, look at the mustek_usb backend.

Manufacturer Model Interface USB id Status Comment
Mustek Paragon MFS-6000CX SCSI   Good 3-pass
Paragon MFS-12000CX SCSI   Good 3-pass
Paragon MFC-600S SCSI   Complete  
Paragon 600 II CD SCSI   Complete  
Paragon 600 II ED Parport   Untested Completely untested. If it's the same as the 600 II EP, it may work. Please contact me if you own such a device.
Paragon 600 II EP Parport   Minimal Works, however only low resolutions and quality in color mode is bad.
ScanMagic 600 II SP SCSI   Complete  
TwainScan II SP SCSI   Complete  
Paragon MFC-800S SCSI   Complete  
Paragon 800 II SP SCSI   Complete  
Paragon MFS-6000SP SCSI   Complete  
Paragon MFS-8000SP SCSI   Complete  
Paragon MFS-1200SP SCSI   Complete  
Paragon MFS-12000SP SCSI   Complete  
ScanExpress 6000SP SCSI   Complete  
ScanExpress 12000SP SCSI   Complete  
ScanExpress 1200 FS SCSI   Untested One report that it crashes the computer. SCSI driver issue? Please contact me if you own such a device.
ScanExpress 12000SP Plus SCSI   Complete  
Paragon 1200 III SP SCSI   Complete  
Paragon 1200 LS SCSI   Complete  
ScanMagic 9636S SCSI   Complete  
ScanMagic 9636S Plus SCSI   Complete  
ScanExpress A3 SP SCSI   Basic Please test!
Paragon 1200 SP Pro SCSI   Good  
Paragon 1200 A3 Pro SCSI   Complete ADF and TA untested. Please contact me if you own such equipment.
Paragon 600 II N Proprietary   Basic Resolutions above 300 dpi may cause trouble.
Trust Imagery 1200 SCSI   Good 3-pass, Mustek Paragon MFS-6000CX compatible
Imagery 1200 SP SCSI   Complete Mustek Paragon MFS-6000SP compatible
Imagery 4800 SP SCSI   Complete Mustek Paragon 600 II CD compatible
SCSI Connect 19200 SCSI   Complete Mustek ScanExpress 12000SP compatible
SCSI excellence series 19200 SCSI   Complete Mustek ScanExpress 12000SP compatible
Primax Compact 4800 SCSI SCSI   Complete Mustek 600 II CD compatible

Backend: mustek_pp (13)

Link(s): http://penguin-breeder.org/sane/mustek_pp/
Manual page: sane-mustek_pp
Comment: Supports CIS and CCD type parallel port scanners from Mustek.

Manufacturer Model Interface USB id Status Comment
Mustek ScanExpress 6000 P Parport (EPP)   Good 300 dpi CCD scanner
ScanExpress 600 SEP Parport (EPP)   Good 300 dpi CCD scanner
ScanMagic 4800 P Parport (EPP)   Good 300 dpi CCD scanner
600 III EP Plus Parport (EPP)   Good 300 dpi CCD scanner
96 CP Parport (EPP)   Good 300x600 dpi CIS scanner
ScanExpress 600 CP Parport (EPP)   Good 300x600 dpi CIS scanner
ScanMagic 600 CP Parport (EPP)   Good 300x600 dpi CIS scanner
ScanExpress 1200 CP Parport (EPP)   Good 600x1200 dpi CIS scanner
ScanExpress 1200 CP+ Parport (EPP)   Good 600x1200 dpi CIS scanner
Medion/Lifetec/Tevion/Cytron MD 9848 Parport (EPP)   Good 300 dpi CCD scanner
MD 9806 Parport (EPP)   Good 300 dpi CCD scanner
MD/LT 935x Parport (EPP)   Good 600x1200 dpi CIS scanner
MD/LT 985x Parport (EPP)   Good 600x1200 dpi CIS scanner
MD/LT 9890 Parport (EPP)   Good 600x1200 dpi CIS scanner
Targa Funline TS12 EP Parport (EPP)   Good 600x1200 dpi CIS scanner
Funline TS6 EP Parport (EPP)   Good 300x600 dpi CIS scanner
Trust Easy Connect 9600+ Parport (EPP)   Good 300x600 dpi CIS scanner
Easy Connect 19200+ Parport (EPP)   Good 300x600 dpi CIS scanner
Viviscan Compact II Parport (EPP)   Good 300 dpi CCD scanner
Cybercom 9352 Parport (EPP)   Good CIS scanner
Gallery 4800 Parport (EPP)   Good 300 dpi CCD scanner
Network Easy Plus 30 Bit Parport (EPP)   Good 300 dpi CCD scanner
Micromaxx MM-9851 Parport (EPP)   Good 300x600 dpi CIS scanner

Backend: mustek_usb (1.0-18)

Link(s): http://www.meier-geinitz.de/sane/mustek_usb-backend/
Manual page: sane-mustek_usb
Comment: Only the USB scanners mentioned below are supported. For BearPaws, look at the Plustek, MA-1509, and gt68xx backends.

Manufacturer Model Interface USB id Status Comment
Mustek ScanExpress 600 CU USB 0x055f/0x0002 Complete  
ScanExpress 1200 CU USB 0x055f/0x0001 Complete  
ScanExpress 1200 CU Plus USB 0x055f/0x0008 Complete  
ScanExpress 1200 UB USB 0x055f/0x0006 Complete For the UB Plus, see gt68xx backend
Trust Compact Scan USB 19200 USB 0x055f/0x0006 Complete Mustek 1200 UB compatible

Backend: mustek_usb2 (1.0-10)

Link(s): http://www.meier-geinitz.de/sane/mustek_usb2-backend/
Manual page: sane-mustek_usb2
Comment: Only BearPaw 2448TA Pro is supported at the moment

Manufacturer Model Interface USB id Status Comment
Mustek BearPaw 2448TA Pro USB 0x055f/0x0409 Good  

Backend: nec (0.12)

Link(s): http://www5a.biglobe.ne.jp/~saetaka/
Manual page: sane-nec

Manufacturer Model Interface USB id Status Comment
NEC PC-IN500/4C SCSI   Good PC-IN500/4C was sold only in JAPAN

Backend: niash (0.3)

Link(s): http://sourceforge.net/projects/hp3300backend
Manual page: sane-niash

Manufacturer Model Interface USB id Status Comment
Hewlett-Packard ScanJet 3300c USB 0x03f0/0x0205 Complete  
ScanJet 3400c USB 0x03f0/0x0405 Complete If you use Linux 2.6, version 2.6.8 or newer is necessary.
ScanJet 4300c USB 0x03f0/0x0305 Complete If you use Linux 2.6, version 2.6.8 or newer is necessary.
ScanJet 4300c/Silitek USB 0x047b/0x1002 Complete If you use Linux 2.6, version 2.6.8 or newer is necessary.
Agfa Snapscan Touch USB 0x06bd/0x0100 Complete  
Trust Office Scan USB 19200 USB 0x047b/0x1000 Complete  

Backend: p5 (1)

Link(s): http://www.sane-project.org/
Manual page: sane-p5
Comment: New backend for SANE release 1.0.21, see sane-p5 manpage

Manufacturer Model Interface USB id Status Comment
PRIMAX PagePartner Parport (EPP/ECP)   Basic Sheetfed scanner, work in gray and color, but uncalibrated scans

Backend: pie (1.0)

Link(s): http://www.munton.demon.co.uk/sane
Manual page: sane-pie

Manufacturer Model Interface USB id Status Comment
Devcom 9636PRO SCSI   Good  
9636S SCSI   Untested  
9630S SCSI   Untested  
PIE ScanAce 1236S SCSI   Good  
ScanAce 1230S SCSI   Good  
ScanAce II SCSI   Untested  
ScanAce III SCSI   Good  
ScanAce Plus SCSI   Untested  
ScanAce II Plus SCSI   Untested  
ScanAce III Plus SCSI   Untested  
ScanAce V SCSI   Untested  
ScanAce ScanMedia SCSI   Untested  
ScanAce ScanMedia II SCSI   Untested  
ScanAce 630S SCSI   Untested  
ScanAce 636S SCSI   Untested  
Adlib JetScan630 SCSI   Good  
JetScan636PRO SCSI   Untested  

Backend: pixma (0.17.3)

Link(s): http://home.arcor.de/wittawat/pixma/, http://mp610.blogspot.com/
Manual page: sane-pixma

Manufacturer Model Interface USB id Status Comment
Canon PIXMA E500 USB 0x04a9/0x1758 Untested Testers needed!
PIXMA E510 USB 0x04a9/0x1761 Untested Testers needed!
PIXMA E600 USB 0x04a9/0x175a Untested Testers needed!
PIXMA E610 USB 0x04a9/0x1767 Untested Testers needed!
PIXMA MG2100 Series USB 0x04a9/0x1751 Complete All resolutions supported (up to 1200DPI).
PIXMA MG2200 Series USB 0x04a9/0x1760 Untested Testers needed!
PIXMA MG3100 Series USB WLAN 0x04a9/0x1752 Complete All resolutions supported (up to 1200DPI).
PIXMA MG3200 Series USB 0x04a9/0x1762 Untested Testers needed!
PIXMA MG4100 Series USB 0x04a9/0x1753 Untested Testers needed!
PIXMA MG4200 Series USB 0x04a9/0x1763 Complete All resolutions supported (up to 1200DPI).
PIXMA MG5100 Series USB 0x04a9/0x1748 Complete All resolutions supported (up to 1200DPI).
PIXMA MG5200 Series USB 0x04a9/0x1749 Complete All resolutions supported (up to 1200DPI).
PIXMA MG5300 Series USB 0x04a9/0x1754 Complete All resolutions supported (up to 2400DPI).
PIXMA MG5400 Series USB 0x04a9/0x1764 Untested Testers needed!
PIXMA MG6100 Series USB 0x04a9/0x174a Complete All resolutions supported (up to 2400 DPI)
PIXMA MG6200 Series USB 0x04a9/0x1755 Complete All resolutions supported (up to 4800 DPI)
PIXMA MG6300 Series USB Ethernet 0x04a9/0x1765 Complete All resolutions supported (up to 2400DPI).
PIXMA MG8100 Series USB 0x04a9/0x174b Untested Testers needed!
PIXMA MG8200 Series USB Ethernet 0x04a9/0x1756 Complete All resolutions supported (up to 4800DPI).
PIXMA MP140 USB 0x04a9/0x172b Complete All resolutions supported (up to 600 DPI)
PIXMA MP150 USB 0x04a9/0x1709 Good  
PIXMA MP160 USB 0x04a9/0x1714 Basic  
PIXMA MP170 USB 0x04a9/0x170a Complete All resolutions supported (up to 1200DPI).
PIXMA MP180 USB 0x04a9/0x1715 Basic  
PIXMA MP190 USB 0x04a9/0x1734 Complete All resolutions supported (up to 600DPI)
PIXMA MP210 USB 0x04a9/0x1721 Complete All resolutions supported (up to 600DPI)
PIXMA MP220 USB 0x04a9/0x1722 Complete All resolutions supported (up to 1200DPI).
PIXMA MP230 USB 0x04a9/0x175f Complete All resolutions supported (up to 600DPI).
PIXMA MP240 USB 0x04a9/0x1732 Complete All resolutions supported (up to 1200DPI)
PIXMA MP250 USB 0x04a9/0x173a Complete All resolutions supported (up to 600DPI)
PIXMA MP260 USB 0x04a9/0x1733 Complete All resolutions supported (up to 1200DPI)
PIXMA MP270 USB 0x04a9/0x173b Complete All resolutions supported (up to 1200DPI)
PIXMA MP280 USB 0x04a9/0x1746 Good All resolutions supported (up to 600DPI).
PIXMA MP360 USB 0x04a9/0x263c Complete All resolutions supported (up to 1200DPI).
PIXMA MP370 USB 0x04a9/0x263d Complete All resolutions supported (up to 1200DPI).
PIXMA MP375R USB 0x04a9/0x263f Untested Same protocol as Pixma MP360/370/390? Testers needed!
PIXMA MP390 USB 0x04a9/0x263e Complete All resolutions supported (up to 1200DPI).
PIXMA MP450 USB 0x04a9/0x170b Complete All resolutions supported (up to 1200DPI).
PIXMA MP460 USB 0x04a9/0x1716 Complete All resolutions supported (up to 1200DPI).
PIXMA MP470 USB 0x04a9/0x1723 Complete All resolutions supported (up to 2400DPI).
PIXMA MP480 USB 0x04a9/0x1731 Complete All resolutions supported (up to 2400DPI)
PIXMA MP490 USB 0x04a9/0x173c Complete All resolutions supported (up to 1200DPI)
PIXMA MP493 USB 0x04a9/0x1757 Untested Testers needed!
PIXMA MP495 USB 0x04a9/0x1747 Untested Same protocol as Pixma MP280? Testers needed!
PIXMA MP500 USB 0x04a9/0x170c Good  
PIXMA MP510 USB 0x04a9/0x1717 Complete All resolutions supported (up to 1200DPI).
PIXMA MP520 USB 0x04a9/0x1724 Complete All resolutions supported (up to 2400DPI)
PIXMA MP530 USB 0x04a9/0x1712 Good  
PIXMA MP540 USB 0x04a9/0x1730 Complete All resolutions supported (up to 2400DPI)
PIXMA MP550 USB 0x04a9/0x173d Complete All resolutions supported (up to 2400DPI)
PIXMA MP560 USB 0x04a9/0x173e Complete All resolutions supported (up to 2400DPI)
PIXMA MP600 USB 0x04a9/0x1718 Complete All resolutions supported (up to 2400DPI)
PIXMA MP600R USB Ethernet 0x04a9/0x1719 Complete All resolutions supported (up to 2400DPI)
PIXMA MP610 USB 0x04a9/0x1725 Complete All resolutions supported (up to 4800DPI)
PIXMA MP620 USB Ethernet 0x04a9/0x172f Complete All resolutions supported (up to 2400DPI)
PIXMA MP630 USB 0x04a9/0x172e Complete All resolutions supported (up to 4800DPI)
PIXMA MP640 USB Ethernet 0x04a9/0x173f Complete All resolutions supported (up to 4800DPI)
PIXMA MP700 USB 0x04a9/0x2630 Complete All resolutions supported (flatbed color up to 1200DPI, grayscale up to 600DPI).
PIXMA MP710 USB 0x04a9/0x264d Complete All resolutions supported (up to 1200DPI)
PIXMA MP730 USB 0x04a9/0x262f Good Flatbed color up to 1200DPI, grayscale up to 600DPI. ADF scan to be confirmed.
PIXMA MP740 USB 0x04a9/0x264c Untested Same protocol as Pixma MP710? Testers needed!
PIXMA MP750 USB 0x04a9/0x1706 Minimal No grayscale. Canceling scan in ADF mode doesn't eject the paper!
PIXMA MP760 USB 0x04a9/0x1708 Minimal No grayscale. The scanner sometimes hangs!
PIXMA MP770 USB 0x04a9/0x1708 Minimal No grayscale. The scanner sometimes hangs!
PIXMA MP780 USB 0x04a9/0x1707 Minimal No grayscale. The scanner sometimes hangs!
PIXMA MP790 USB 0x04a9/0x1707 Minimal No grayscale. The scanner sometimes hangs!
PIXMA MP800 USB 0x04a9/0x170d Complete All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI.
PIXMA MP800R USB 0x04a9/0x170e Complete All resolutions supported up to 2400DPI. Full TPU support up to 2400DPI.
PIXMA MP810 USB 0x04a9/0x171a Complete All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI.
PIXMA MP830 USB 0x04a9/0x1713 Complete All resolutions supported up to 2400DPI. Flatbed, ADF simplex and Duplex supported.
PIXMA MP960 USB 0x04a9/0x171b Complete All resolutions supported up to 4800DPI. Full TPU support (negative and slides) up to 4800DPI.
PIXMA MP970 USB Ethernet 0x04a9/0x1726 Complete All resolutions supported (up to 4800DPI). Full TPU support (negative and slides) at 24 or 48 bits.
PIXMA MP980 USB Ethernet 0x04a9/0x172d Complete Working fine at all resolutions.
PIXMA MP990 USB Ethernet 0x04a9/0x1740 Complete Working fine at all resolutions.
PIXMA MX300 USB 0x04a9/0x1727 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
PIXMA MX310 USB 0x04a9/0x1728 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI)
PIXMA MX320 USB 0x04a9/0x1736 Untested Same protocol as Pixma Generation 3? Testers needed!
PIXMA MX330 USB 0x04a9/0x1737 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI)
PIXMA MX340 USB 0x04a9/0x1741 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI)
PIXMA MX350 USB Ethernet 0x04a9/0x1742 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI)
PIXMA MX360 USB 0x04a9/0x174d Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy.
PIXMA MX370 Series USB 0x04a9/0x1759 Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI).
PIXMA MX390 Series USB 0x04a9/0x1766 Untested Testers needed!
PIXMA MX410 USB Ethernet 0x04a9/0x174e Untested Same protocol as Pixma MX420? Testers needed!
PIXMA MX420 USB Ethernet 0x04a9/0x174f Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI). ADF empty buggy.
PIXMA MX430 Series USB Ethernet 0x04a9/0x175b Untested Testers needed!
PIXMA MX450 Series USB 0x04a9/0x1768 Untested Testers needed!
PIXMA MX510 Series USB Ethernet 0x04a9/0x175c Untested Testers needed!
PIXMA MX520 Series USB 0x04a9/0x1769 Untested Testers needed!
PIXMA MX700 USB Ethernet 0x04a9/0x1729 Complete Flatbed and ADF scan. All resolutions supported (up to 2400DPI)
PIXMA MX710 Series USB Ethernet 0x04a9/0x175d Untested Testers needed!
PIXMA MX720 Series USB 0x04a9/0x176a Untested Testers needed!
PIXMA MX850 USB Ethernet 0x04a9/0x172c Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported.
PIXMA MX860 USB Ethernet 0x04a9/0x1735 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported.
PIXMA MX870 USB Ethernet 0x04a9/0x1743 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.
PIXMA MX880 Series USB Ethernet 0x04a9/0x1750 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.
PIXMA MX882 USB Ethernet 0x04a9/0x1750 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.
PIXMA MX885 USB Ethernet 0x04a9/0x1750 Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.
PIXMA MX890 Series USB Ethernet 0x04a9/0x175e Complete All resolutions supported (up to 2400DPI). Flatbed, ADF simplex and Duplex supported, ADF empty buggy.
PIXMA MX920 Series USB 0x04a9/0x176b Untested Testers needed!
PIXMA MX7600 USB Ethernet 0x04a9/0x171c Complete Flatbed and ADF scan. All resolutions supported (up to 4800DPI)
imageCLASS D420 USB 0x04a9/0x26ef Complete All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported.
imageCLASS D480 USB 0x04a9/0x26ed Complete All resolutions supported (up to 600DPI). Flatbed, ADF simplex and Duplex supported.
i-SENSYS MF3010 USB Ethernet 0x04a9/0x2759 Complete All resolutions supported (up to 600DPI)
imageCLASS MF3110 USB 0x04a9/0x2660 Complete All resolutions supported (up to 600DPI).
imageCLASS MF3240 USB 0x04a9/0x2684 Complete All resolutions supported (up to 600DPI)
imageCLASS MF4010 USB 0x04a9/0x26b4 Complete All resolutions supported (up to 600DPI)
imageCLASS MF4018 USB 0x04a9/0x26b4 Complete All resolutions supported (up to 600DPI)
imageCLASS MF4120 USB 0x04a9/0x26a3 Complete All resolutions supported (up to 600DPI)
imageCLASS MF4122 USB 0x04a9/0x26a3 Complete All resolutions supported (up to 600DPI)
imageCLASS MF4140 USB 0x04a9/0x26a3 Complete All resolutions supported (up to 600DPI)
imageCLASS MF4150 USB 0x04a9/0x26a3 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
imageCLASS MF4270 USB 0x04a9/0x26b5 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
I-SENSYS MF4320d USB 0x04a9/0x26ee Complete All resolutions supported (up to 600DPI)
I-SENSYS MF4330d USB 0x04a9/0x26ee Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
imageCLASS MF4350d USB 0x04a9/0x26ee Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
imageCLASS MF4370dn USB 0x04a9/0x26ec Good Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported
imageCLASS MF4380dn USB 0x04a9/0x26ec Good Flatbed and ADF scan. All resolutions supported (up to 600DPI). Network not supported
imageCLASS MF4410 USB 0x04a9/0x2737 Complete All resolutions supported (up to 600DPI)
imageCLASS MF4430 USB 0x04a9/0x2737 Good Flatbed and ADF scan. All resolutions supported (up to 600DPI). ADF empty buggy.
i-SENSYS MF4550d USB 0x04a9/0x2736 Good Flatbed and ADF scan. All resolutions supported (up to 600DPI).
imageCLASS MF4660 USB 0x04a9/0x26b0 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
imageCLASS MF4690 USB 0x04a9/0x26b0 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
imageCLASS MF5630 USB 0x04a9/0x264e Untested Testers needed!
laserBase MF5650 USB 0x04a9/0x264f Untested Testers needed!
imageCLASS MF5730 USB 0x04a9/0x265d Complete Flatbed and ADF scan. All resolutions supported (up to 1200DPI).
imageCLASS MF5750 USB 0x04a9/0x265e Untested Testers needed!
imageCLASS MF5770 USB 0x04a9/0x265f Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI).
i-SENSYS MF5880dn USB 0x04a9/0x26f9 Untested Testers needed!
imageCLASS MF6500 series USB 0x04a9/0x2686 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
imageCLASS MF6550 USB 0x04a9/0x2686 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
i-SENSYS MF6680dn USB 0x04a9/0x26fa Untested Testers needed!
imageCLASS MF8030 USB 0x04a9/0x2707 Untested Testers needed!
imageCLASS MF8170c USB 0x04a9/0x2659 Untested Testers needed!
imageRUNNER 1020/1024/1025 USB 0x04a9/0x26e6 Complete Flatbed and ADF scan. All resolutions supported (up to 600DPI)
CanoScan 8800F USB 0x04a9/0x1901 Complete Flatbed scan. TPU for negatives and slides. All resolutions supported (up to 4800DPI).
CanoScan 9000F USB 0x04a9/0x1908 Complete Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI.
CanoScan 9000F Mark II USB 0x04a9/0x190d Complete Full flatbed support up to 4800DPI (Note: flatbed does not have 9600DPI capability). Full TPU support (negatives, slides and infrared) up to 9600DPI.

Backend: plustek (0.52)

Link(s): http://www.gjaeger.de/scanner/plustek/
Manual page: sane-plustek

Manufacturer Model Interface USB id Status Comment
Plustek OpticPro U12 USB 0x07b3/0x0010 Complete NOTE: Devices with product ID 0x0001 are not supported!
OpticPro UT12 USB 0x07b3/0x0013 Complete  
OpticPro UT12 USB 0x07b3/0x0017 Complete Note: Devices with product ID 0x0001 are not supported!
OpticPro UT16 USB 0x07b3/0x0017 Complete  
OpticPro U24 USB 0x07b3/0x0011 Complete  
OpticPro U24 USB 0x07b3/0x0015 Complete  
OpticPro UT24 USB 0x07b3/0x0017 Complete  
Genius Colorpage HR6 V2 USB 0x0458/0x2007 Complete  
Colorpage HR6 V2 USB 0x0458/0x2008 Complete  
Colorpage HR7 USB 0x0458/0x2013 Complete  
Colorpage HR6A USB 0x0458/0x2009 Untested  
Colorpage HR7LE USB 0x0458/0x2015 Untested  
Colorpage HR6X USB 0x0458/0x2016 Untested  
Mustek BearPaw 1200 USB 0x0400/0x1000 Complete both product versions are supported, see backends' man-page
BearPaw 1200 USB 0x0400/0x1001 Complete both product versions are supported, see backends' man-page
BearPaw 2400 USB 0x0400/0x1001 Complete  
Hewlett-Packard ScanJet 2100C USB 0x03f0/0x0505 Complete  
ScanJet 2200C USB 0x03f0/0x0605 Complete  
Epson Perfection 1250 USB 0x04b8/0x010f Complete  
Perfection 1250Photo USB 0x04b8/0x010f Good TPA scans not perfect
Perfection 1260 USB 0x04b8/0x011d Complete  
Perfection 1260Photo USB 0x04b8/0x011d Good TPA scans not perfect
Umax UMAX 3400 USB 0x1606/0x0050 Complete there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x
UMAX 3400 USB 0x1606/0x0060 Complete there are some UMAX 3400 outside the U.S. which are not supported, as they use another chipset than the LM983x
UMAX Astranet ia101 USB 0x1606/0x0060 Complete seems to be a renamed UMAX 3400
UMAX 3450 USB 0x1606/0x0060 Complete  
UMAX 5400 USB 0x1606/0x0160 Complete  
Compaq S4-100 USB 0x049f/0x001a Complete Identical to UMAX 3400
Canon CanoScan N650U/N656U USB 0x04a9/0x2206 Complete  
CanoScan N1220U USB 0x04a9/0x2207 Complete  
CanoScan N670U/N676U/LiDE20 USB 0x04a9/0x220d Complete  
CanoScan N1240U/LiDE30 USB 0x04a9/0x220e Complete  
CanoScan LiDE25 USB 0x04a9/0x2220 Good  
CanoScan D660U USB 0x04a9/0x2208 Good TPA scans not perfect
Syscan TravelScan 460/464 USB 0x0a82/0x4600 Complete  
TravelScan 662 USB 0x0a82/0x6620 Complete  
Ambir Visigo A4 USB 0x0a82/0x4600 Complete Rebaged Travelscan 464
Portable Peripheral Co., Ltd. Q-Scan USB001 (A4 portable scanner) USB 0x0a53/0x1000 Complete  
Q-Scan USB201 (A6 portable scanner) USB 0x0a53/0x2000 Good  
Visioneer Strobe XP 100 USB 0x04a7/0x0427 Basic  

Backend: plustek_pp (0.43)

Link(s): http://www.gjaeger.de/scanner/plustek_pp/
Manual page: sane-plustek_pp

Manufacturer Model Interface USB id Status Comment
Plustek OpticPro 4800P Parport (SPP, EPP)   Complete  
OpticPro 4830P Parport (SPP, EPP)   Complete  
OpticPro 600P/6000P Parport (SPP, EPP)   Complete  
OpticPro 4831P Parport (SPP, EPP)   Complete  
OpticPro 9630P Parport (SPP, EPP)   Complete  
OpticPro 9630PL Parport (SPP, EPP)   Complete use driver-switch mov=1
OpticPro 9600P Parport (SPP, EPP)   Complete  
OpticPro 1236P Parport (SPP, EPP)   Complete reported as OpticPro 12000P/96000P
OpticPro 12000P/96000P Parport (SPP, EPP)   Complete  
OpticPro 9636P Parport (SPP, EPP)   Complete use driver-switch mov=4
OpticPro 9636P+/Turbo Parport (SPP, EPP)   Complete use driver-switch mov=3
OpticPro 9636T Parport (SPP, EPP)   Complete  
OpticPro 12000T Parport (SPP, EPP)   Complete  
OpticPro AI3 Parport (SPP, EPP)   Basic use driver-switch mov=5, poor picture quality
OpticPro P8 Parport   Untested  
OpticPro P12 Parport (SPP, EPP)   Complete  
OpticPro PT12 Parport (SPP, EPP)   Complete  
Primax Colorado 4800 Parport (SPP, EPP)   Untested same as OpticPro 4800P
Compact 4800 Direct Parport (SPP, EPP)   Complete use driver-switch mov=2
Compact 4800 Direct-30 Parport (SPP, EPP)   Complete same as OpticPro 4830P, use driver-switch mov=7
Compact 9600 Direct-30 Parport (SPP, EPP)   Complete same as OpticPro 9630P
Genius Colorpage Vivid III V2 Parport (SPP, EPP)   Complete Reported as PT12
Colorpage Vivid Pro II Film Parport (SPP, EPP)   Complete Reported as OP9636T/12000T
Colorpage HR6X EPP Parport (SPP, EPP)   Good Negative scanning does not work correctly
Aries Scan-It Pro 4800 Parport (SPP, EPP)   Complete use driver-switch mov=2
BrightScan BrighScan OpticPro Parport (SPP, EPP)   Complete Reported as P12

Backend: ricoh (unmaintained)

Manual page: sane-ricoh

Manufacturer Model Interface USB id Status Comment
Ricoh Ricoh IS50 SCSI   Basic  
Ricoh IS60 SCSI   Basic  

Backend: rts8891 (1.0-0)

Link(s): http://stef.dev.free.fr/sane/rts8891/index.html
Manual page: sane-rts8891
Comment: This backend supports Realtek RTS8891 ASIC bases scanners.

Manufacturer Model Interface USB id Status Comment
UMAX Astra 4400 USB 0x1606/0x0070 Good Supports 75, 150, 300, 600 and 1200 dpi
Astra 4450 USB 0x1606/0x0070 Untested  
Hewlett-Packard scanjet 4470c USB 0x03f0/0x0805 Good re-branded Astra 4400
scanjet 4400c USB 0x03f0/0x0705 Good exists with 2 different sensors of which only one works

Backend: s9036 (unmaintained)

Manual page: sane-s9036

Manufacturer Model Interface USB id Status Comment
Siemens 9036 Flatbed scanner SCSI   Basic  

Backend: sceptre (1.0-10)

Link(s): http://www.zago.net/sane/
Manual page: sane-sceptre

Manufacturer Model Interface USB id Status Comment
Sceptre Vividscan S1200 SCSI   Basic  
Komodo S1200 SCSI   Untested rebadged Sceptre S1200

Backend: sharp (0.32)

Link(s): http://www.satzbau-gmbh.de/staff/abel/sane-sharp.html
Manual page: sane-sharp

Manufacturer Model Interface USB id Status Comment
Sharp JX-610 SCSI   Good  
JX-250 SCSI   Good  
JX-320 SCSI   Good  
JX-325 SCSI   Untested  
JX-330 SCSI   Good  
JX-350 SCSI   Good  

Backend: sm3600 (0.1)

Link(s): http://sm3600.sourceforge.net/
Manual page: sane-sm3600

Manufacturer Model Interface USB id Status Comment
Microtek ScanMaker 3600 USB 0x05da/0x40b3 Basic works
ScanMaker 3600 USB 0x05da/0x40ca Basic works
ScanMaker 3600 USB 0x05da/0x40ff Basic works
ScanMaker 3700 USB 0x05da/0x40b8 Basic works
ScanMaker 3700 USB 0x05da/0x40cb Basic works
ScanMaker 3750 USB 0x05da/0x40dd Basic works (told)

Backend: sm3840 (1.1)

Link(s): http://www.ziplabel.com/sm3840/
Manual page: sane-sm3840
Comment: This reverse-engineered backend supports the USB ScanMaker 3840 model

Manufacturer Model Interface USB id Status Comment
Microtek ScanMaker 3840 USB 0x05da/0x30d4 Good 8 and 16 bit, color and grayscale
ScanMaker 4800 USB 0x05da/0x30cf Good Same hardware as SM3840, different color box

Backend: SnapScan (1.4)

Link(s): http://snapscan.sourceforge.net/
Manual page: sane-snapscan
Comment: Supported bit depths: 24 bit (color), 48 bit (color, Epson) 8 bit (gray)

Manufacturer Model Interface USB id Status Comment
AGFA SnapScan SCSI   Good  
SnapScan 300 SCSI   Good  
SnapScan 310 SCSI   Good  
SnapScan 600 SCSI   Good Optional ADF supported.
Arcus 1200 SCSI   Good Optional transparency unit supported.
SnapScan 1236s SCSI   Good Optional ADF and transparency unit supported.
SnapScan 1236u USB 0x06bd/0x0002 Good Optional ADF and transparency unit supported.
SnapScan 1212U USB 0x06bd/0x0001 Good  
SnapScan 1212U_2 USB 0x06bd/0x2061 Good  
SnapScan e10 USB 0x06bd/0x2093 Good  
SnapScan e20 USB 0x06bd/0x2091 Good  
SnapScan e25 USB 0x06bd/0x2095 Good  
SnapScan e26 USB 0x06bd/0x2097 Good  
SnapScan e40 USB 0x06bd/0x208d Good  
SnapScan e42 USB 0x06bd/0x20ff Good  
SnapScan e50 USB 0x06bd/0x208f Good Optional tranparency unit supported
SnapScan e52 USB 0x06bd/0x20fd Good Optional tranparency unit supported
SnapScan e60 USB   Untested  
Benq (Acer) 300f SCSI   Good  
310s SCSI   Good  
610s SCSI   Good  
610plus SCSI   Good  
620s SCSI   Good  
ScanWit 2720s SCSI   Good  
310U USB 0x04a5/0x1a20 Good  
320U USB 0x04a5/0x2022 Good  
340U USB 0x04a5/0x2022 Good  
620U USB 0x04a5/0x1a2a Good Optional tranparency unit supported
620UT USB 0x04a5/0x2040 Good Optional tranparency unit supported
640U USB 0x04a5/0x2060 Good Optional tranparency unit supported
640bu USB 0x04a5/0x207e Good  
640BT USB 0x04a5/0x20be Good Optional tranparency unit supported
1240 USB 0x04a5/0x20c0 Good Optional tranparency unit supported
3300 USB 0x04a5/0x20b0 Good  
3300 USB 0x04a5/0x20de Good  
4300 USB 0x04a5/0x20b0 Good  
4300 USB 0x04a5/0x20de Good  
5000E USB 0x04a5/0x20fc Basic Same as 5000U, working up to 600 DPI
5000U USB 0x04a5/0x20fc Basic Same as 5000E, working up to 600 DPI
5000 USB 0x04a5/0x20f8 Good USB ID 0x04a5,0x20f8: Color / grayscale scans working up to 1200 DPI
5150 USB 0x04a5/0x2137 Basic Calibration algorithm unknown
5250 USB 0x04a5/0x2137 Basic Same hardware as 5150 (?), Calibration algorithm unknown
5300 USB 0x04a5/0x20fe Basic Problems with firmware upload reported
Guillemot / Hercules Maxi Scan A4 Deluxe (SCSI) SCSI   Good Rebadged SnapScan 310s.
Scan@home Touch 1248 (USB) USB 0x04a5/0x20de Good Rebadged Benq 3300.
Maxi Scan A4 USB 640U USB 0x04a5/0x2060 Good Rebadged Benq 640U.
Maxi A4 36 bit USB 0x04a5/0x2060 Good Rebadged Benq 620U, needs Benq firmware file u96v???.bin
Mitsubishi Diamondview 648UT USB 0x04a5/0x2022 Good Rebadged Benq 320u.
Diamondview 650U USB 0x04a5/0x20b0 Good Rebadged Benq 4300.
Epson Perfection 660 USB 0x04b8/0x0114 Good  
Perfection 1270 USB 0x04b8/0x0120 Good  
Perfection 1670 USB 0x04b8/0x011f Good  
Perfection 2480 USB 0x04b8/0x0121 Good  
Perfection 2580 USB 0x04b8/0x0121 Basic Film scanning unit unsupported
Perfection 3490 USB 0x04b8/0x0122 Good  
Perfection 3590 USB 0x04b8/0x0122 Basic Film scanning unit unsupported
Stylus CX-1500 USB 0x04b8/0x080c Good  

Backend: sp15c (unmaintained)

Manual page: sane-sp15c

Manufacturer Model Interface USB id Status Comment
Fujitsu ScanPartner 15C SCSI   Good  
ScanPartner 600C SCSI   Good  

Backend: st400 (1.6)

Link(s): http://www.informatik.uni-oldenburg.de/~ingo/sane/
Manual page: sane-st400

Manufacturer Model Interface USB id Status Comment
Siemens ST400 SCSI   Basic 6 bit gray
ST800 SCSI   Basic 6 bit gray

Backend: tamarack (unmaintained)

Manual page: sane-tamarack

Manufacturer Model Interface USB id Status Comment
Tamarack Artiscan 6000C SCSI   Good 3 pass, 300 DPI
Artiscan 8000C SCSI   Good 3 pass, 400 DPI
Artiscan 12000C SCSI   Good 3 pass, 600 DPI

Backend: teco1 (1.0-10)

Link(s): http://www.zago.net/sane/#teco
Manual page: sane-teco1

Manufacturer Model Interface USB id Status Comment
Relisys RELI 2412 SCSI   Complete sub model VM3530+
AVEC 2400 SCSI   Complete sub model VM3520
RELI 4830 SCSI   Good sub model VM4542
AVEC 2412 SCSI   Complete sub model VM3520+
AVEC 4800 SCSI   Untested sub model VM4530
AVEC 4816 SCSI   Untested sub model VM4530+
RELI DS6 SCSI   Untested sub model VM3420
RELI DS15 SCSI   Untested sub model VM3440
RELI 2400 SCSI   Untested sub model VM3530
RELI 4816 SCSI   Complete sub model VM4540
RELI 9600 SCSI   Untested sub model VM6530
RELI 9612 SCSI   Untested sub model VM6530*
RELI 9624 SCSI   Untested sub model VM6530+
RELI 9630 SCSI   Untested sub model VM6540
Actown ACT Scan I 30 SCSI   Untested sub model VM3520A
Dextra DF-600P SCSI   Good sub model VM3510
DF-1200T+ SCSI   Untested sub model VM3530+
DF-4830T SCSI   Untested sub model VM4542
DF-9624 SCSI   Untested sub model VM6530+

Backend: teco2 (1.0-9)

Link(s): http://gkall.hobby.nl/teco2.html
Manual page: sane-teco2

Manufacturer Model Interface USB id Status Comment
Relisys AVEC Super 3 SCSI   Untested sub model VM3575
AVEC II S3 SCSI   Good sub model VM3564
SCORPIO Super 3 SCSI   Good sub model VM3575
APOLLO Express 3 SCSI   Basic sub model VM356A
APOLLO Express 6 SCSI   Good sub model VM6565
SCORPIO Pro SCSI   Good sub model VM6575
SCORPIO Pro-S SCSI   Untested sub model VM6586
Primax Jewel 4800 SCSI   Good sub model VM356A
Profi 9600 SCSI   Basic sub model VM6575
Profi 19200 SCSI   Good sub model VM6586
Mustek ScanMagic 4830S SCSI   Untested sub model VM3575

Backend: teco3 (1.0-1)

Link(s): http://www.zago.net/sane/#teco3
Manual page: sane-teco3

Manufacturer Model Interface USB id Status Comment
Relisys Infinity Scorpio SCSI   Good sub model VM3552
Plustek OpticPro 2400SP SCSI   Untested sub model VM3552
PIOTECH Splendeur 3024 SCSI   Good sub model VM3552
Trust Imagery 2400 SP SCSI   Good sub model VM3552
Imagery 4800 SP+ SCSI   Good sub model VM3552
Imagery 9600 SP SCSI   Untested sub model VM3552

Backend: u12 (0.02)

Link(s): http://www.gjaeger.de/scanner/u12/
Manual page: sane-u12

Manufacturer Model Interface USB id Status Comment
Plustek OpticPro U12 USB 0x07b3/0x0001 Basic Note: Only devices with product ID 0x0001 are supported!
OpticPro UT12 USB 0x07b3/0x0001 Basic Note: Only devices with product ID 0x0001 are supported!
OpticPro 1212U USB 0x07b3/0x0001 Basic  
RevScan RevScan Orange R48Ti USB 0x07b3/0x0001 Basic Rebadged Plustek OpticPro UT12
Genius ColorPage HR6 V1 USB 0x0458/0x2004 Basic  
ColorPage Vivid III USB USB 0x07b3/0x0001 Untested Note: Device has Plustek vendor and product ID (0x07b3/0x0001)

Backend: umax (1.0-41)

Link(s): http://www.rauch-domain.de/sane-umax/index.html
Manual page: sane-umax

Manufacturer Model Interface USB id Status Comment
UMAX Vista S6 SCSI   Good OK
Vista S6E SCSI   Good OK
UMAX S-6E SCSI   Good OK
UMAX S-6EG SCSI   Good OK
Vista-S8 SCSI   Good OK
Supervista S-12 SCSI   Good OK
UMAX S-12 SCSI   Good OK
UMAX S-12G SCSI   Good OK
Astra 600S SCSI   Good OK
Astra 610S SCSI   Good OK
Astra 1200S SCSI   Good OK
Astra 1220S SCSI   Good OK
Astra 2100S SCSI   Good OK
Astra 2200 (SU) SCSI   Good OK
Astra 2200 (SU) USB 0x1606/0x0230 Good OK, needs USB control messages
Astra 2400S SCSI   Good OK
Astra 6400 IEEE-1394   Unsupported will probably work one day
Astra 6450 IEEE-1394   Unsupported will probably work one day
Astra MX3 SCSI   Good OK
Astra MX3 USB   Good OK, needs USB control messages
Mirage D-16L SCSI   Good OK
Mirage II SCSI   Good OK
Mirage IIse SCSI   Good OK
PSD SCSI   Good OK
PowerLook SCSI   Good OK, SCSI-ID=PS-2400X
PL-II SCSI   Good OK
PowerLook III SCSI   Good OK
PowerLook 270 SCSI   Unsupported incompatible
PowerLook 270plus SCSI   Unsupported incompatible
PowerLook 1100 IEEE-1394   Unsupported will probably work one day
PowerLook 2000 SCSI   Good OK
PowerLook 2100XL SCSI   Good OK
PowerLook 3000 SCSI   Good OK
Gemini D-16 SCSI   Good OK
UMAX VT600 SCSI   Untested may work, please test and give feedback
Vista-T630 SCSI   Good OK for some firmwareversions, on others only lineart OK
UC 630 SCSI   Good Version 2.8 OK, others only lineart OK
UG 630 SCSI   Good OK
UG 80 SCSI   Good OK
UC 840 SCSI   Good Version 1.6 OK, others only lineart OK
UC 1200S SCSI   Untested may work, please test and give feedback
UC 1200SE SCSI   Good Version 3.0 OK, others unknown
UC 1260 SCSI   Good Version 1.6 OK, others unknown
Linotype Hell Jade SCSI   Good OK, SCSI-ID=LinoHell Office
Jade SCSI   Good OK, SCSI-ID=LinoHell JADE
Jade2 SCSI   Good OK, SCSI-ID=LinoHell Office2
Saphir SCSI   Untested support disabled until tested - please contact author
Saphir2 SCSI   Good OK, SCSI-ID=LinoHell SAPHIR2
Saphir3 SCSI   Good OK, SCSI-ID=LinoHell SAPHIR3
Saphir Ultra SCSI   Untested support disabled until tested - please contact author
Saphir Ultra II SCSI   Good OK, SCSI-ID=Linotype SAPHIR4
Saphir HiRes SCSI   Untested support disabled until tested - please contact author
Opal SCSI   Untested support disabled until tested - please contact author
Opal2 SCSI   Good OK; SCSI-ID=LinoHell OPAL2
Opal Ultra SCSI   Untested support disabled until tested - please contact author
Linoscan 1400 SCSI   Good OK, SCSI-ID=HDM LS4H1S
Vobis Highscreen Scanboostar Premium SCSI   Good OK, SCSI-ID=LinoHell Office2
EDGE KTX-9600US SCSI   Untested no feedback
Epson Perfection 600 SCSI   Good OK, SCSI-ID=EPSON Perfection600
Escom Image Scanner 256 SCSI   Good OK, SCSI-ID=UMAX UG 80
Escort Galleria 600 SCSI   Untested untested, SCSI-ID=ESCORT Galleria 600S
Genius ColorPage-HR5 (Pro) SCSI   Good OK, SCSI-ID=KYE ColorPage-HR5
Nikon AX-110 / Scantouch 110 SCSI   Untested may work, please test and give feedback
AX-210 SCSI   Good OK
TriGem PowerScanII SCSI   Good OK

Backend: umax1220u (unmaintained)

Link(s): http://sourceforge.net/projects/umax1220u-sane
Manual page: sane-umax1220u

Manufacturer Model Interface USB id Status Comment
UMAX Astra 1220U USB 0x1606/0x0010 Good  
Astra 1600U USB 0x1606/0x0030 Good  
Astra 2000U USB 0x1606/0x0030 Good  
Astra 2100U USB 0x1606/0x0130 Good  

Backend: umax_pp (1)

Link(s): http://umax1220p.sourceforge.net/
Manual page: sane-umax_pp

Manufacturer Model Interface USB id Status Comment
UMAX Astra 1220P Parport (EPP/ECP)   Good  
Astra 2000P Parport (EPP/ECP)   Good  
Astra 1600P Parport (EPP/ECP)   Good  
Astra 600P Parport (SPP/ECP)   Unsupported untested, but should be close to 610P
Astra 610P Parport (SPP/ECP)   Good  
Hewlett-Packard Scanjet 3200C Parport (EPP/ECP)   Good works (relabelled 1220P and 2000P)
Genius ColorPage-Life Pro Parport (EPP/ECP)   Good works (relabelled 1220P and 2000P)

Backend: unsupported (2010-06-09)

Link(s): /contrib.html
Comment: The devices mentioned here are not supported by any SANE backend. However, there may be links to information about them or stand-alone programs.

Manufacturer Model Interface USB id Status Comment
Agfa DuoScan f40 USB IEEE-1394 0x06bd/0x02bf Unsupported Unsupported. See link for details.
DuoScan T2000XL SCSI   Unsupported Unsupported. Same as Microtek ArtixScan 2020?
DuoScan T2500 SCSI IEEE-1384   Unsupported Unsupported. Same as Microtek Artixscan 2500f
SnapScan 310P Parport   Unsupported Unsupported, see link for details.
SnapScan EZ Parport   Unsupported Unsupported, see link for details.
SnapScan 1200P Parport   Unsupported Unsupported, see link for details.
SnapScan 1212P Parport   Unsupported Unsupported, see link for details.
Artec/Ultima 1236 USB USB 0x05d8/0x4001 Unsupported Unsupported. See link for details.
AM12e+ Parport   Unsupported Unsupported. Chips found inside: AT015, AD9816JS. Maybe similar to SCSI version or as6e?
Ultima 2000 (0x4001) USB 0x05d8/0x4001 Unsupported Same name, but different ids: This scanner is not supported. The scanner with product id 0x4002 is supported by the gt68xx backend, however.
Avigramm Minidoc USB Parport 0x05cb/0x1483 Unsupported Not supported. See link for details.
Avision DS310F Parport   Unsupported Probably not supported. Scanner/printer/copier combination.
iVina FB2400 USB   Unsupported Not supported. No chipset information available. Same as UMAX Astra 6700.
iVina 1600 USB 0x0638/0x0a10 Unsupported GL646 based, to be added to genesys backend. Same as UMAX Astra 4500.
iVina FB1800 USB 0x0638/0x0a20 Unsupported GL646/GL660 based. Same as UMAX Astra 4700.
Benq (Acer) 310P Parport   Unsupported Unsupported, see link for details.
320P Parport   Unsupported Unsupported, see link for details.
340P Parport   Unsupported Unsupported, see link for details.
610P Parport   Unsupported Unsupported, see link for details.
610PT Parport   Unsupported Unsupported, see link for details.
620P Parport   Unsupported Unsupported, see link for details.
620PT Parport   Unsupported Unsupported, see link for details.
640P Parport   Unsupported Unsupported, see link for details.
5450 USB 0x04a5/0x211e Unsupported Unsupported.
5550 USB 0x04a5/0x2211 Unsupported Unsupported, see link for details.
5560 USB 0x04a5/0x2311 Unsupported  
7400UT USB 0x04a5/0x2202 Unsupported  
Boeder Sm@rtScan Office Parport USB 0x05cb/0x1483 Unsupported Unsupported. See link for details.
Brother MFC 2500 USB 0x04f9/0x000a Unsupported Not supported. See link for details.
MFC 4600 Parport   Unsupported The parport 200x400dpi grayscale version of this scanner is unsupported. Dmitri Katchalov did some investigations on this scanner. If you want to write a backend, contact him (see link).
MFC 7300c Parport USB 0x04f9/0x0106 Unsupported  
MFC 9600 USB 0x04f9/0x0101 Unsupported  
C-Channel MyPen Pro USB   Unsupported Probably unsupported. See link for details.
MyPen Light USB 0x0a93/0x0005 Unsupported See bug #306792 for details.
MoneyPen II USB   Unsupported Probably unsupported.
Canon CanoScan 3000 USB 0x04a9/0x2215 Unsupported GL660+GL646 based.
CanoScan 3000ex USB 0x04a9/0x2215 Unsupported GL660+GL646 based.
CanoScan 3000F USB 0x04a9/0x2215 Unsupported GL660+GL646 based, to be added to genesys backend
CanoScan 4200F USB 0x04a9/0x221b Unsupported Probably unsupported. See link.
CanoScan 4400F USB 0x04a9/0x2228 Unsupported GL843 based, to be added to genesys backend
CanoScan 5000F USB 0x04a9/0x2212 Unsupported Unsupported. See link for details.
CanoScan 5200F USB 0x04a9/0x2217 Unsupported Probably unsupported. See link for details.
CanoScan 8000F USB 0x04a9/0x220f Unsupported Not supported. See link for more information. With transparency adapter.
CanoScan 8400F USB 0x04a9/0x221e Unsupported GL841 based, to be added to genesys backend
CanoScan 8600F USB 0x04a9/0x2229 Unsupported GL841 based, to be added to genesys backend
CanoScan 9900F USB 0x04a9/0x2210 Unsupported Probably unsupported, similar to 8000F. 3200x6400 dpi USB2. With transparency adapter.
CanoScan 9950F USB 0x04a9/0x2219 Unsupported Probably unsupported.
CanoScan D646U USB 0x04a9/0x220b Unsupported Probably not supported. See link for more information and test program.
CanoScan D646U ex USB 0x04a9/0x220b Unsupported Probably not supported. See D646.
CanoScan D1230U USB 0x04a9/0x2209 Unsupported Probably not supported.
CanoScan D1250U2 USB 0x04a9/0x220c Unsupported Not supported. However, someone started working on this scanner and some information is available (see link).
CanoScan D2400UF USB 0x04a9/0x220a Unsupported Not supported. See link.
CanoScan FB320U USB 0x04a9/0x2201 Unsupported Probably not supported. No details known.
CanoScan FB620U USB 0x04a9/0x2202 Unsupported Probably not supported. Some information is available.
CanoScan FB1210U USB 0x04a9/0x2205 Unsupported Not supported. However, a stand-alone program for FreeBSD is available.
CanoScan LiDE 70 USB 0x04a9/0x2225 Unsupported Philips chip. Backend started, see link
CanoScan LiDE 80 USB 0x04a9/0x2214 Unsupported GL841 based, to be added to genesys backend
CanoScan LiDE 90 USB 0x04a9/0x1900 Unsupported Unsupported. See link for details.
CanoScan LiDE 500F USB 0x04a9/0x221f Unsupported GL841 based, to be added to genesys backend
CanoScan LiDE 600 USB 0x04a9/0x2224 Unsupported Philips chip. Backend started, see link
CanoScan LiDE 600F USB 0x04a9/0x2224 Unsupported Philips chip. Backend started, see link
FS4000 USB SCSI 0x04a9/0x3042 Unsupported Not supported. See link for more details.
IS 12 USB   Unsupported Probably not supported. Scanner cardridge for Canon inkjet printers.
IS 22 Parport   Unsupported Probably not supported. Scanner cardridge for Canon inkjet printers.
IS 32 USB 0x04a9/0x105d Unsupported Probably not supported. Scanner cardridge for Canon inkjet printers.
IS 52 USB   Unsupported Probably not supported. Scanner cardridge for Canon inkjet printers.
ImageRunner iR1018 USB 0x04a9/0x269d Unsupported Probably not supported. See link for details.
ImageRunner iR1022 USB 0x04a9/0x269d Unsupported Probably not supported. See link for details.
ImageRunner iR1023 USB 0x04a9/0x269d Unsupported Probably not supported. See link for details.
PIXMA MP110 USB 0x04a9/0x1700 Unsupported Probably not supported. See link for details.
PIXMA MP130 USB 0x04a9/0x1701 Unsupported Probably not supported. See link for details.
DR-2020U USB   Unsupported GL84x?
Chinon DS-3000 Parport Serial Port   Unsupported Unsupported at the moment, but a backend is in preparation. See link.
Compaq S200 USB 0x049f/0x0021 Unsupported Not supported. 2400x1200 dpi. One bulk-in, one bulk-out and one interrupt endpoint. Type-number: U0001-HB21, another type nr on the inside: 75100512-00
Compeye Simplex 1236C Parport USB 0x05cb/0x1483 Unsupported Unsupported. See link for details.
Corex Cardscan 500 USB 0x08f0/0x0001 Unsupported Probably not supported. Businesscard reader.
Cardscan 700 C USB 0x08f0/0x0004 Unsupported Probably not supported.
Dell A940 USB 0x413c/0x5106 Unsupported Probably rebadged Lexmark X5150. May work with sane-lexmark? See bug #312130
A960 USB 0x413c/0x5107 Unsupported Probably not supported. See link for details.
922 USB 0x413c/0x5109 Unsupported Probably not supported. See link for details.
Epson GT-2200 USB 0x04b8/0x0102 Unsupported Probably unsupported. No details known.
StylusScan 2000 USB 0x04b8/0x0105 Unsupported Probably unsupported. No details known.
Stylus DX4450 USB 0x04b8/0x083f Unsupported Probably unsupported. See link for details.
Stylus CX-5800 USB   Unsupported Probably unsupported at the moment. Not compatible to snapscan backend. It's not known if it may work with epson or epkowa backend.
EDT (Electronic Document Technology) BizCardReader 900C USB 0x0a53/0x5001 Unsupported Probably unsupported. See link for details.
E-Lux j-6121 Parport   Unsupported Probably unsupported. Sold 1998. Same as E-Lux j-6121.
Enhans j-6121 Parport   Unsupported Probably unsupported. Sold 1998. Same as E-Lux j-6121.
M-3630 A Parport   Unsupported Probably unsupported.
Genius ColorPage CS SCSI   Unsupported Probably unsupported, see link for details.
ColorPage-Slim 1200 USB2 USB 0x0458/0x2020 Unsupported GL841 based, to be added to genesys backend.
ColorPage HR6X Slim USB 0x0458/0x2019 Unsupported GL646 based, to be added to genesys backend
ColorPage HR7X USB 0x0458/0x2018 Unsupported GL646 based, to be added to genesys backend
ColorPage HR7XE USB 0x06dc/0x0012 Unsupported Unsuported. See link for details.
ColorPage HR8 USB 0x0458/0x201c Unsupported GL841 based, to be added to genesys backend
Guillemot SCAN@HOME 48 USB USB 0x080d/0x0102 Unsupported Probably unsupported. See link for details.
Maxi Scan A4 Parallel 36 bit Parport   Unsupported Probably unsupported. Identical to the Benq Prisa 620P.
Hercules SCAN@HOME 48 USB USB 0x080d/0x0102 Unsupported Probably unsupported. See link for details.
Hewlett-Packard Photo Scanner 1000 USB 0x03f0/0x1001 Unsupported Not supported by SANE. However, it's detected as mass storage device so just mounting it is reported to work. See link for device data.
Photosmart 1200 Photo USB   Unsupported Probably not supported by SANE. No details known. 10x15 cm. Maybe similar to Photo Scanner 1000?
Photosmart S20 (C5101A) USB 0x03f0/0x0102 Unsupported Not supported yet by SANE. See link for details.
Photosmart S20xi (C7150A) USB 0x03f0/0x0102 Unsupported Not supported yet by SANE. See link for details.
Photosmart C5100 series USB 0x03f0/0x5811 Unsupported Not supported yet by SANE. See link for details.
ScanJet 2400c USB 0x03f0/0x0a01 Unsupported GL646 based, to be added to genesys backend
Photosmart C3180 USB 0x03f0/0x5611 Unsupported Not supported yet by SANE. See link for details.
ScanJet 3770 USB 0x03f0/0x2505 Unsupported While an external binary-only backend exists, it works only on Linux i386. Therefore the scanner is unsupported on other platforms.
ScanJet 4600 USB 0x03f0/0x3005 Unsupported Not supported. See link for details, or http://www.chmil.org/hp4600linux/ for code
ScanJet 4670 USB 0x03f0/0x3005 Unsupported Not supported. See ScanJet 4600 entry.
ScanJet 4850C USB 0x03f0/0x1b05 Unsupported GL841, maybe can be added to genesys backend
ScanJet 4890C USB 0x03f0/0x1b05 Unsupported GL843, maybe can be added to genesys backend
ScanJet 5530C Photosmart USB 0x03f0/0x1605 Unsupported Maybe GL841_HP, but not confirmed, maybe can be added to genesys backend
ScanJet 8390 USB 0x03f0/0x3805 Unsupported Probably not supported. See link for details.
ScanJet G4000 USB 0x03f0/0x4505 Unsupported Probably not supported. See link for details.
IBM ADF Color Scanner Proprietary   Unsupported Unsupported. Uses proprietary ISA card. Maybe the same as the Plustek Spectra ADF?
IOMagic MobileScan USB USB Parport 0x05cb/0x1483 Unsupported Unsupported. See link for details.
Iris IriScan USB 0x0a53/0x1000 Unsupported Unsupported. LM9832/3. See link for details.
IRISPen Translator Executive USB 0x0f43/0x015a Unsupported Unsupported. See link for details.
IRISCard Pro (IBCR II) USB 0x0a38/0x0301 Unsupported Unsupported. See link for details.
Kodak Snapshot Photo Scanner 1 Parport   Unsupported Unsupported. FCC ID HWF96PHS
Lexmark P6250 USB 0x043d/0x0097 Unsupported Unsupported. See link for details.
Photo 3150 USB 0x043d/0x007d Unsupported Unsupported. See link for details.
X74 USB 0x043d/0x0060 Unsupported Unsupported. See link for details.
X75 USB 0x043d/0x0060 Unsupported Unsupported. See link for details.
X75 PrinTrio USB 0x043d/0x0060 Unsupported Unsupported. See link for details.
X83 USB 0x043d/0x003d Unsupported Unsupported. GL640.
X2330 USB 0x043d/0x00bb Unsupported Unsupported. See link for details.
X3450 USB 0x043d/0x00f6 Unsupported Unsupported. See link for details.
X5130 USB 0x043d/0x0065 Unsupported Unsupported.
X5150 USB 0x043d/0x0065 Unsupported Probably unsupported. See link for details.
X5250 USB 0x043d/0x0093 Unsupported Unsupported.
X6170 USB 0x043d/0x0072 Unsupported Unsupported. See link for details.
X7170 USB 0x043d/0x0098 Unsupported Unsupported. See bug #310889 for details.
X7350 USB 0x043d/0x00b8 Unsupported Unsupported. See link for details.
X8350 USB 0x043d/0x00b9 Unsupported Unsupported. See link for details.
Logitech PageScan Color Parport   Unsupported Most probably unsupported.
PageScan USB USB 0x046d/0x040f Unsupported Probably unsupported. See link for details.
Medion/Lifetec/Tevion/Cytron MD 6190 USB 0x0461/0x0392 Unsupported Probably unsupported. There seem to exist two different scanners with that name. See link for details.
MD 6190 USB 0x0461/0x037b Unsupported Probably unsupported. There seem to exist two different scanners with that name. See link for details.
MD 40420 USB 0x05da/0x3008 Unsupported Probably unsupported. See link for details.
MD 41260 USB 0x0461/0x037b Unsupported Probably unsupported. See link for details.
MD 41985 USB 0x0461/0x037b Unsupported Probably unsupported. See link for details.
MD 42666 USB 0x05da/0x3008 Unsupported Probably unsupported. See link for details.
MD 85264 USB 0x08ff/0x2580 Unsupported Fingerprint sensor. See link for details.
MD 90009 USB 0x05da/0x30e5 Unsupported Probably unsupported. See link for details.
MD 90070 USB 0x05da/0x3022 Unsupported Unsupported. See link for details.
MD 90090 USB 0x05da/0x3022 Unsupported Unsupported. See link for details.
Memorex 6136u USB 0x0461/0x0346 Unsupported Probably unsupported.
6142u USB 0x0461/0x0347 Unsupported Probably unsupported. Same as Visioneer Onetouch 4400. See link for details.
MaxxScan 6122 USB Parport 0x05cb/0x1483 Unsupported Unsupported. See link for details.
SCF 9612P Parport   Unsupported Probably unsupported. See link for details.
Microtek ArtixScan 2020 SCSI   Unsupported Unsupported. Same as Agfa DuoScan T2000XL?
ArtixScanDI 2020 USB 0x05da/0x202e Unsupported Unsupported. See link for details.
Artixscan 2500f SCSI IEEE-1384   Unsupported Unsupported. Same as Agfa DuoScan T2500?
ArtixScan 4000tf USB   Unsupported Unsupported. Uses ALI M5611B.
FilmScan 35 USB 0x05e3/0x0120 Unsupported Probably unsupported. See link for details.
ScanMaker 336 CX SCSI   Unsupported Probably unsupported. Seems to be similar to the Microtek 330 CX and is detected by the microtek2 backend. Scanning doesn't seem to work however.
Scanmaker 1850S SCSI   Unsupported Unsupported. See link for details.
ScanMaker 3630 USB 0x0461/0x0347 Unsupported Unsupported. Doesn't seem to be compatible to 3600 series, see link.
ScanMaker 3800 USB 0x05da/0x30ce Unsupported Unsupported. See link for more details.
ScanMaker 3830 USB 0x05da/0x30ce Unsupported Unsupported. See link for more details.
ScanMaker 3860 USB 0x05da/0x3023 Unsupported Unsupported. See link for more details. Appears to be similar to ScanMaker 3880.
ScanMaker 3880 USB 0x05da/0x3021 Unsupported Unsupported. SQ113 chip. See link for more details.
ScanMaker 4600 USB 0x05da/0x40c7 Unsupported Unsupported. See link for more details.
ScanMaker 4700 USB 0x05da/0x20b4 Unsupported Unsupported. See link for more details.
ScanMaker 4850 USB 0x05da/0x30d9 Unsupported Probably unsupported. See link for details.
ScanMaker 4850 II USB 0x05da/0x3008 Unsupported Probably unsupported. See link for details.
ScanMaker 4900 USB 0x05da/0x30b9 Unsupported Unsupported. See link for more details.
ScanMaker 5 SCSI   Unsupported Probably unsupported. See link for more details.
ScanMaker 5600 USB 0x05da/0x20a7 Unsupported Unsupported. See link for more details.
ScanMaker 5700 USB 0x05da/0x20bd Unsupported Unsupported. Uses ALI M5615 like the ScanMaker 4700.
ScanMaker 5800 USB 0x05da/0x3008 Unsupported Unsupported. See link for details.
ScanMaker 5800 USB 0x05da/0x30d8 Unsupported Unsupported. See link for details.
ScanMaker 5900 USB 0x05da/0x30d8 Unsupported Unsupported. See link for more details.
ScanMaker 5950 USB 0x05da/0x30d8 Unsupported Unsupported. See link for more details.
ScanMaker 6000 USB 0x05da/0x30e5 Unsupported Unsupported. See link for more details.
ScanMaker 6100 USB 0x05da/0x30e5 Unsupported Unsupported. See link for more details.
ScanMaker 6700 USB IEEE-1394 0x05da/0x20c9 Unsupported Unsupported. See link.
ScanMaker 8700 USB IEEE-1394 0x05da/0x20b1 Unsupported Unsupported. See link for details. USB vendor and product ids to be checked.
ScanMaker 9600XL USB IEEE-1394 0x05da/0x20de Unsupported Probably unsupported. SCSI seems to work with microtek2 backend.
ScanMaker 9800XL USB SCSI 0x05da/0x20de Unsupported Partly unsupported. IEEE-1394 works with microtek2 backend. See link.
ScanMaker i320 USB 0x05da/0x30e6 Unsupported Unsupported. See link.
ScanMaker s400 USB 0x05da/0x201c Unsupported Unsupported. See link.
ScanMaker S400 USB 0x05da/0x300b Unsupported Unsupported. See link.
ScanPort 3000 USB 0x04a7/0x0224 Unsupported Unsupported. Vendor/Product ids: 0x04a7/0x0224. Realtek RTS8801B?. See link for details.
Konica Minolta Dual Scan III USB 0x0686/0x400d Unsupported Unsupported. May work with vuescan. See link for details.
Dual Scan IV USB 0x132b/0x000a Unsupported Unsupported. Works with vuescan. See link for details.
DiMAGE Scan Elite 5400 USB IEEE-1394 0x0686/0x400e Unsupported Probably unsupported. May work with vuescan. See link for details.
DiMAGE Scan Elite 5400 2 USB 0x132b/0x0012 Unsupported Probably unsupported. See link for details.
DiMAGE Scan Multi Pro IEEE-1394   Unsupported Probably unsupported. See link for details.
magicolor 2480MF USB Network   Unsupported Uses a different scanning protocol than the magicolor 1690MF
Mustek 1200 III EP Parport   Unsupported Probably not supported. quarlewm at jmu dot edu offers to temporarily loan such a scanner to anyone who is interested in writing a driver.
2400 M USB   Unsupported Probably unsupported. No details known.
BearPaw 2400 TA Pro USB 0x055f/0x0400 Unsupported Not supported. May be supported by mustek_usb2 backend later. See link for some information.
BearPaw 2448 CU Pro USB 0x055f/0x0408 Unsupported Not supported. May be supported by mustek_usb2 backend later. See link for some information.
BearPaw 4800 TA Pro USB 0x055f/0x1000 Unsupported Not supported. See link for some information.
BearPaw 4800 TA Pro II USB 0x055f/0x040a Unsupported Not supported. May be supported by mustek_usb2 backend later. See link for some information.
BearPaw 6400 TA Pro USB 0x055f/0x040b Unsupported Not supported. May be supported by mustek_usb2 backend later. See link for some information.
Paragon 800 II EP Parport   Unsupported Not supported. Maybe similar to 600 II EP (SCSI_over-parport)? In this case it could be supported by the mustek SCSI backend.
ScanExpress 600 USB USB 0x055f/0x0873 Unsupported Unsupported. Programming information is available.
ScanExpress 1200 USB USB 0x055f/0x0003 Unsupported Unsupported. Programming information is available.
ScanExpress 1200 USB Plus USB 0x055f/0x0007 Unsupported Unsupported.
ScanExpress 12000 P Parport   Unsupported Not supported. Asic 1505/05.
ScanExpress A3 EP Parport   Unsupported Not supported. Maybe it will be supported by the mustek_pp backend in future.
ScanExpress CardSmart USB   Unsupported Probably unsupported. USB business card scanner. Maybe works as USB storage device?
ScanMagic 9636P Parport   Unsupported Probably not supported. Same as Mustek 12000 P?. ASIC 1505.
NEC Petiscan USB 0x0475/0x0100 Unsupported Most probably unsupported. See link for details. Vendor ID is Relisys/Teco. Not known if it is similar to other Relisys/Teco USB scanners.
Nikon LS-9000 ED IEEE-1394   Unsupported Probably not supported. See link for details. Possibly similar to LS-8000 ED.
Olivetti Job-Jet M400 USB 0x0b3c/0xa880 Unsupported Probably not supported. See link for details.
Olympus ES-10P Parport   Unsupported  
ES-10S SCSI   Unsupported Probably not supported. See link for details.
Optoelectronics Barcode scanner USB 0x065a/0x0001 Unsupported Probably not supported.
Optrox PhotoMaker 3C Parport   Unsupported  
PhotoMaker 3E Parport   Unsupported  
PhotoMaker 3F Proprietary   Unsupported Special ISA card
PhotoMaker 3S Parport   Unsupported  
PhotoMaker 6E Parport   Unsupported  
PhotoMaker 6F Proprietary   Unsupported Special ISA card
Panasonic KV-SS905C SCSI   Unsupported might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool.
KV-S2055W USB SCSI   Unsupported might be supported by matsushita backend.
KV-S2055L SCSI   Unsupported might be supported by matsushita backend.
KV-S2065W SCSI   Unsupported might be supported by matsushita backend.
KV-S3065CW USB SCSI   Unsupported might be supported by matsushita backend.
KV-S3065CL USB SCSI   Unsupported might be supported by matsushita backend.
KV-S3085 USB SCSI   Unsupported might be supported by matsushita backend.
KV-S3105C USB SCSI   Unsupported might be supported by matsushita backend. See http://code.google.com/p/kvss905c/ for a standalone scanning tool.
KV-S6040W SCSI   Unsupported might be supported by matsushita backend.
KV-S6045W SCSI   Unsupported might be supported by matsushita backend.
KV-S6050W SCSI   Unsupported might be supported by matsushita backend.
KV-S6055W SCSI   Unsupported might be supported by matsushita backend.
KV-S7065C USB SCSI   Unsupported might be supported by matsushita backend.
Pentax DSmobile USB USB 0x0a82/0x2000 Unsupported Probably not supported. Some information is available.
PIE Primefilm 1800u USB 0x05e3/0x0120 Unsupported Not supported. See link for details.
Primefilm 2700 USB   Unsupported  
Primefilm 3600PRO USB IEEE-1394   Unsupported Probably not supported.
Powerslide 3600 USB IEEE-1394 0x05e3/0x0142 Unsupported Probably unsupported. Film scanner that can scan directly from the magazine.
PF3650 Pro3 Film Scanner USB IEEE-1394 0x05e3/0x0143 Unsupported Not supported. See link for details.
Plustek OpticFilm 7200 USB 0x07b3/0x0807 Unsupported GL842 based, maybe to be added to genesys backend
OpticFilm 7200i USB 0x07b3/0x0c04 Unsupported GL843 based, maybe to be added to genesys backend
OpticPro A3U USB   Unsupported Uses Plustek ASIC P99002
OpticPro S6 USB   Unsupported Uses RealTek chipset (RTL8801D)
OpticPro S12 USB 0x07b3/0x0600 Unsupported Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend.
OpticPro ST12 USB 0x07b3/0x0600 Unsupported Product id 0x0600 is unsupported but may be supported by the genesys backend in future. Product id 0x040b is supported by the gt68xx backend.
OpticPro ST16 USB 0x07b3/0x0600 Unsupported GL646 based, to be added to genesys backend
OpticPro UA18 USB   Unsupported Probably LM983x based.
OpticPro S24 USB 0x07b3/0x0601 Unsupported Product id 0x0601 is unsupported but may be supported by the genesys backend in future /GL646). Product id 0x040e is supported by the gt68xx backend.
OpticPro ST24 USB 0x07b3/0x0601 Unsupported GL646 based, to be added to genesys backend
OpticPro S28 USB 0x07b3/0x0801 Unsupported GL841 based, to be added to genesys backend
OpticPro ST28 USB 0x07b3/0x0801 Unsupported GL841 based, to be added to genesys backend
OpticPro ST28 USB 0x07b3/0x0802 Unsupported GL841 based, to be added to genesys backend
Umax AstraScan 4750 USB 0x07b3/0x0802 Unsupported GL841 based, to be added to genesys backend, rebadged Plustek ST28
OpticPro ST48 USB 0x07b3/0x0800 Unsupported GL841 based, to be added to genesys backend
OpticPro ST64 USB 0x07b3/0x0c00 Unsupported GL843 based, maybe to be added to genesys backend
OpticPro ST64+ USB 0x07b3/0x0c03 Unsupported GL843 based. See link for more details.
PL 806 USB 0x07b3/0x0c0c Unsupported Unsupported. See link for more details.
SmartOffice PL 812 USB 0x07b3/0x0c0d Unsupported Unsupported. See link for more details.
OpticSlim 500 USB 0x07b3/0x0458 Unsupported Unsupported. See link for more details.
OpticSlim 2420 USB 0x07b3/0x0806 Unsupported GL841 based, to be added to genesys backend
OpticSlim 2420+ USB 0x07b3/0x0914 Unsupported GL841 based, to be added to genesys backend
OpticWorks 2000 Parport   Unsupported Multifunction device. No further information available.
OptiCard 600+ USB   Unsupported Business card reader. No further information available.
ScanCopy 115 USB 0x07b3/0x081c Unsupported GL841 based, to be added to genesys backend
Spectra ADF Proprietary   Unsupported Unsupported. Uses proprietary ISA card that also provides power and is labelled GPS-1 PAGE-A from Taiwan. Other labels on the scanner include ADF Color Scanner and SF600AS. Maybe the same as the IBM ADF Color Scanner?
Unknown Plustek Device USB 0x07b3/0x0005 Unsupported Probably unsupported. Scanner name not known yet.
Unknown Plustek Device USB 0x07b3/0x0007 Unsupported Probably unsupported. Scanner name not known yet.
Unknown Plustek Device USB 0x07b3/0x000f Unsupported Probably unsupported. Scanner name not known yet.
Unknown Plustek Device USB 0x07b3/0x0012 Unsupported Probably unsupported. Scanner name not known yet.
Unknown Plustek Device USB 0x07b3/0x0014 Unsupported Probably unsupported. Scanner name not known yet.
Unknown Plustek Device USB 0x07b3/0x0016 Unsupported Probably unsupported. Scanner name not known yet.
PLANon DocuPen RC800 USB   Unsupported Probably not supported. No details known.
DocuPen R700 USB 0x10c4/0xea60 Unsupported Probably not supported. See link for details.
DocuPen (DPEN-BW) USB   Unsupported Probably not supported. No details known.
Primax Colorado 600U USB 0x0461/0x0341 Unsupported Not supported. Some information is available.
Colorado 1200p Parport   Unsupported Unsupported by SANE. But is reported to partly work with pxscan. See link.
Colorado 1200u USB 0x0461/0x0361 Unsupported Probably unsupported. No details known.
Primascan Colorado 2600u USB 0x0461/0x0347 Unsupported Unsupported. Same as Visioneer Onetouch 4400. See link for details.
Colorado Direct 600 Parport   Unsupported Not supported. However, a stand-alone program is available.
Colorado Direct 9600 Parport   Unsupported Not supported. However, a stand-alone program is available.
Colorado USB 9600 USB 0x0461/0x0340 Unsupported Not supported. See link for details.
G2-300 USB 0x0461/0x0300 Unsupported Probably unsupported. No details known.
G2-300 #2 USB 0x0461/0x0302 Unsupported Probably unsupported. No details known.
G2E-300 USB 0x0461/0x0301 Unsupported Probably unsupported. No details known.
G2E-300 #2 USB 0x0461/0x0303 Unsupported Probably unsupported. No details known.
G2-600 USB 0x0461/0x0380 Unsupported Probably unsupported. No details known.
G2-600 #2 USB 0x0461/0x0382 Unsupported Probably unsupported. No details known.
G2E-600 USB 0x0461/0x0383 Unsupported Probably unsupported. No details known.
OneTouch 5300 Parport   Unsupported Not supported.
ReadyScan 636i USB 0x0461/0x0381 Unsupported Probably unsupported. No details known.
Slim-Line 1200 USB   Unsupported Maybe GL646. Maybe similar to Medion MD 6228?
Onetouch 8920 USB 0x0461/0x0371 Unsupported Not supported. Look similar to Visioneer Onetouch 8920 (same USB product id).
Prolink Winscan Pro 2448U USB 0x06dc/0x0014 Unsupported Not supported. Some information is available. RealTek RTS8801.
Winscan Pro 2000 USB Parport   Unsupported Not supported. No further information available.
Quato X-Finity SCSI   Unsupported Probably not supported. No details yet. Originally manufactured by PFU?
X-Finity Ultra USB IEEE-1394   Unsupported Probably not supported. No details yet.
Reflecta DigitDia 3600 USB IEEE-1394 0x05e3/0x0142 Unsupported Film scanner that can scan directly from the magazine.
iScan 1800 USB 0x05e3/0x0120 Unsupported Probably unsupported. See link for details.
ProScan 4000 USB IEEE-1394 0x05e3/0x0143 Unsupported Probably unsupported. See link for details.
Relisys Eclipse 1200U USB 0x0475/0x0103 Unsupported Probably unsupported. See link for details.
Scorpio Ultra 3 USB 0x0475/0x0210 Unsupported Probably unsupported. See link for details.
Episode USB 0x0475/0x0103 Unsupported Probably unsupported. See link for details.
AVEC II E3 Parport   Unsupported Parport version of AVEC II S3?. See bug #304992 for details
Samsung SCX-4725FN USB 0x04e8/0x341f Unsupported Not supported. See link for details.
Scanshell 800N USB 0x0a82/0x6605 Unsupported Not supported. See link for details.
Sicos DMS 2000 proprietary   Unsupported Not supported until now. Work on a backend has started, contact the author for details (see link)
Siemens ID Mouse Professional USB 0x0681/0x0005 Unsupported Not supported.
Cherry FingerTIP ID Board - Sensor USB 0x0681/0x0010 Unsupported Not supported.
SmartDisk SmartScan 3600 USB IEEE-1394   Unsupported Probably not supported. Same as PIE Primefilm 2600 PRO.
Spot Technology Maxiscan A4 proprietary   Unsupported Not supported until now. Work on a backend has started, see link for more information.
ScanTak 2c proprietary   Unsupported Not supported. Work on a backend has started, see link for more information.
ScanTak 3c proprietary   Unsupported Not supported. Work on a backend has started, see link for more information.
Syscan TravelScan FS-531 USB 0x0a82/0x0530 Unsupported Not supported. May work with the Plustek backend in future. See link for details.
TravelScan Pro USB 0x0a82/0x2000 Unsupported Probably not supported. Some information is available.
Tamarack Artiscan 9600 Parport   Unsupported Unsupported at the moment. See link for a project for that scanner taht may support it in future.
Artiscan 9600 pro 36 Parport   Unsupported Unsupported at the moment. See link for a project for that scanner.
Artiscan 2400FS USB 0x05e3/0x0100 Unsupported Unsupported. See link for more information.
TCE MK600U USB 0x0461/0x0346 Unsupported Not supported. Some information is available.
S450 Parport   Unsupported Not supported by SANE but is reported to work with pxscan (see link).
Teco VM6509F USB 0x080d/0x0102 Unsupported Probably unsupported. See link for details.
Tiny FU661E USB 0x0461/0x0347 Unsupported Unsupported. See link for details.
Trust CombiScan 19200 Parport USB 0x05cb/0x1483 Unsupported Unsupported. See link for details.
EasyScan 19200 Parport   Unsupported  
SCSI Scan 19200 -Excellence Series- SCSI   Unsupported Unsupported. See link for details.
UMAX Astra 2500 USB 0x0461/0x0374 Unsupported Probably not supported. See link for details.
Astra 2850 USB 0x07b3/0x0601 Unsupported Probably not supported. Same IDs as Plustek OpticPro ST24. See link for details.
Astra 3000 USB 0x0461/0x038a Unsupported Probably not supported. See link for details.
Astra 3600 USB 0x0461/0x038a Unsupported Probably not supported. See link for details.
Astra 4000 USB 0x1606/0x1030 Unsupported Not supported. See link for details.
Astra 4100 USB 0x0461/0x038c Unsupported Not supported, to be added to genesys backend.
Astra 4500 USB 0x0638/0x0a10 Unsupported GL646 based, to be added to genesys backend. Avision iVina FB1600 clone
Astra 4600 USB   Unsupported Probably not supported, no details known.
Astra 4700 USB 0x0638/0x0a20 Unsupported GL646/GL660 based. Avision iVina FB1800 clone.
Astra 6700 USB   Unsupported Not supported. No chipset information available. Same as Avision iVina FB2400.
AstraSlim USB 0x080d/0x0104 Unsupported Probably not supported currently. See link for more details.
AstraSlim 1200 USB 0x080d/0x0110 Unsupported See link for more details.
AstraSlim 6000 USB 0x080d/0x0104 Unsupported Probably not supported currently. See link for more details.
Nete3470' Parport   Unsupported Probably not supported. No details known..
Powerlook 180 USB   Unsupported Probably not supported. See link for details.
Powerlook 1000 USB USB   Unsupported Probably not supported. No further information available.
Vantas 3000 USB 0x04a7/0x0224 Unsupported Not supported. See link for more details.
Visioneer 6200 USB 0x0461/0x0345 Unsupported Not supported. Is reported to use the E5 chipset. Uses a Primax ID. Looks similar to Primascan Colorado 2600u.
6200 EPP/USB USB 0x04a7/0x0311 Unsupported Not supported. Id is from Primax? Yet another scanner with the same name?
9420 USB 0x0461/0x03a8 Unsupported Unsupported. See link for details.
9450 USB USB 0x04a7/0x0421 Unsupported Unsupported. See link for details.
Onetouch 4400 USB 0x0461/0x0347 Unsupported Not supported. E5 chipset? See link for more details.
OneTouch 4800 USB USB 0x04a7/0x0224 Unsupported Unsupported. Seems to use Realtek RTS8801B. Same as Microtek Scanport 3000. See link for details.
OneTouch 5300 USB USB 0x04a7/0x0226 Unsupported Not supported. Chipset is RTS8801B(?). See link for output of /proc/bus/usb/devices.
OneTouch 5300 USB 0x04a7/0x0221 Unsupported Not supported. Yet another scanner with this name?
OneTouch 5800 USB USB 0x04a7/0x0226 Unsupported Unsupported. 48 bit scanner, doesn't work with viceo backend. RTS8801C.
OneTouch 6600 USB 0x04a7/0x022a Unsupported Unsupported. See link for details.
Onetouch 7100 USB 0x04a7/0x0229 Unsupported GL646 based, to be added to genesys backend
Onetouch 7700 USB 0x04a7/0x0380 Unsupported LM9832/3 based, to be added to plustek backend
OneTouch 8100 USB 0x04a7/0x0321 Unsupported Unsupported. See link for details.
Onetouch 8700 USB 0x04a7/0x0371 Unsupported Not supported. See link for details.
Onetouch 8900 USB 0x04a7/0x0371 Unsupported Not supported. Same as 8920 but without TA?
Onetouch 8920 USB 0x04a7/0x0371 Unsupported Not supported. Same as 8700 and 8900 but includes a TA. Uses a Primax ID. Chipset is RTS8801C. See link for output of /proc/bus/usb/devices.
Onetouch 9000 USB 0x04a7/0x022c Unsupported Not supported. See link for details.
Onetouch 9020 USB 0x04a7/0x022c Unsupported Not supported. See link for details.
Onetouch 9320 USB 0x04a7/0x0362 Unsupported Probably not supported. See link for details.
Onetouch Pro 8800 USB 0x04a7/0x0410 Unsupported Probably not supported. See link for details.
Onetouch Pro 8820 USB 0x04a7/0x0410 Unsupported Probably not supported. See link for details.
PaperPort 3100b Parport   Unsupported Most probably not supported. See link for details.
PaperPort 6100 Parport   Unsupported Most probably not supported. More details would be appreciated.
PaperPort OneTouch Parport   Unsupported Most probably not supported. See link for details.
Strobe Pro USB USB 0x04a7/0x0102 Unsupported Not supported. See link for details.
4800 One Touch USB 0x04a7/0x03a0 Unsupported Unsupported. See link for details. Different id compared to One Touch 4800?
DocuImage 620S SCSI   Unsupported Not supported. See link for more details.
DocuMate 510 USB 0x04a7/0x0446 Unsupported Not supported. See link for more details.
DocuMate 510 USB 0x04a7/0x047c Unsupported Not supported. See link for more details. Yet another USB id.
One Touch 4800 USB 0x04a7/0x0224 Unsupported Unsupported. See link for details. Different id compared to 4800 One Touch?
WorkCentre 470cx Parport   Unsupported Not supported. See link for more details.
WorkCentre M15i USB 0x0924/0xffef Unsupported Not supported. See link for more details.
WorkCentre XK35c USB Parport 0x043d/0x0020 Unsupported Not supported. See link for more details.
WorkCentre XK50cx USB 0x04e8/0x3903 Unsupported Not supported. See link for more details.
WorkCentre Pro 412 USB Parport 0x043d/0x4303 Unsupported Not supported. See link for more details.
WorkCentre PE16 USB Parport 0x0924/0x4220 Unsupported Not supported. See link for more details.
WorkCentre PE120i USB 0x0924/0x4237 Unsupported Not supported. See link for more details.

Backend: xerox_mfp (1.0-13)

Manual page: sane-xerox_mfp

Manufacturer Model Interface USB id Status Comment
Xerox Phaser 6110MFP USB 0x0924/0x3d5d Good  
Phaser 3200MFP USB 0x0924/0x3da4 Complete  
WorkCentre 3119 Series USB 0x0924/0x4265 Good  
WorkCentre 4118 Series USB 0x0924/0x420c Good  
WorkCentre 3210 USB 0x0924/0x4293 Good  
WorkCentre 3220 USB 0x0924/0x4294 Good  
Dell Dell MFP Laser Printer 1815dn USB 0x413c/0x5124 Good  
Samsung SCX-4x16 USB 0x04e8/0x3409 Untested  
SCX-6x20 USB 0x04e8/0x340d Untested  
MFP-560 USB 0x04e8/0x340e Untested  
MFP-750 USB 0x04e8/0x340f Untested  
SCX-4x20 USB 0x04e8/0x3412 Untested  
SCX-4100 USB 0x04e8/0x3413 Good  
SCX-4x21 USB 0x04e8/0x3419 Untested  
SCX-5x30 USB 0x04e8/0x341a Untested  
SCX-4200 USB 0x04e8/0x341b Good  
CLX-3160 USB 0x04e8/0x341c Untested  
SCX-6x22 USB 0x04e8/0x341d Untested  
SCX4725 USB 0x04e8/0x341f Untested  
SCX4725-FN USB 0x04e8/0x341f Good  
SCX-6x45 USB 0x04e8/0x3420 Untested  
CLX-8380 USB 0x04e8/0x3421 Untested  
CLX-2160 USB 0x04e8/0x3425 Good  
SCX-4500 USB 0x04e8/0x3426 Good  
CLX-6200 USB 0x04e8/0x3427 Untested  
CLX-6240 USB 0x04e8/0x3428 Untested  
SCX-6x55 USB 0x04e8/0x3429 Untested  
CLX-3170fn (CLX-3170 Series) USB 0x04e8/0x342a Good  
CLX-3175FW USB 0x04e8/0x342a Good  
SCX-4500W USB Ethernet 0x04e8/0x342b Basic  
SCX-4824 (SCX-4x24 Series) USB 0x04e8/0x342c Good  
SCX-4828FN (SCX-4x28 Series) USB 0x04e8/0x342d Good  
SCX-4300 USB 0x04e8/0x342e Good  
SCX-5835_5935 USB 0x04e8/0x342f Good  
SCX-5635 USB 0x04e8/0x3430 Untested  
SCX-4x26 USB 0x04e8/0x3432 Untested  
SCX-4600 USB 0x04e8/0x3433 Good  
SCX-4623 USB 0x04e8/0x3434 Good  
MFP-65x USB 0x04e8/0x3435 Untested  
SCX-6545 USB 0x04e8/0x3437 Untested  
CLX-8385 USB 0x04e8/0x3439 Untested  
CLX-6220 USB 0x04e8/0x343a Good  
CLX-6250 USB 0x04e8/0x343b Untested  
SCX-4825FN (SCX-4x25 Series) USB 0x04e8/0x343c Good  
CLX-3185 USB 0x04e8/0x343d Good  
CLX-8540 USB 0x04e8/0x343f Untested  
SCX-4623FW USB 0x04e8/0x3440 Good  
SCX-3205W (SCX-3200 Series) USB Ethernet 0x04e8/0x3441 Good  
SCX-6545X USB 0x04e8/0x3442 Untested  
SCX-6x55X USB 0x04e8/0x3443 Untested  
CLX-8385X USB 0x04e8/0x3444 Untested  
SCX-5835_5935X USB 0x04e8/0x3446 Good  
SCX-4833FD USB 0x04e8/0x344b Good  
SCX-4835FD Ethernet 0x04e8/0x344b Good  
SCX-3405W Ethernet   Basic  
SCX-3400 USB 0x04e8/0x344f Untested  
SF-760 USB 0x04e8/0x3450 Untested  
SCX-4729FD USB 0x04e8/0x3453 Basic  
CLX-6260 USB 0x04e8/0x3455 Minimal  
CLX-3300 Series USB 0x04e8/0x3456 Basic  
SCX-470x USB 0x04e8/0x3457 Untested  
CLX-4190 USB 0x04e8/0x345a Minimal  
SCX-4650 4x21S Series USB 0x04e8/0x345b Untested  
M337x 387x 407x Series USB 0x04e8/0x3460 Untested  
M267x 287x Series USB 0x04e8/0x3461 Untested  
SCX-681x USB 0x04e8/0x3466 Untested  
C460 USB 0x04e8/0x3468 Untested  

Still Cameras

Backends: dc25, dc210, dc240, dmc

Backend: dc25 (1.2)

Link(s): mailto:peter@fales-lorenz.net
Manual page: sane-dc25

Manufacturer Model Interface USB id Status Comment
Kodak DC25 Serial port   Complete  
DC20 Serial port   Basic DC-20 untested by author but reported to work

Backend: dc210 (0.0)

Link(s): mailto:peter@fales-lorenz.net
Manual page: sane-dc210

Manufacturer Model Interface USB id Status Comment
Kodak DC210 Serial port   Basic  

Backend: dc240 (0.0)

Link(s): mailto:peter@fales-lorenz.net
Manual page: sane-dc240

Manufacturer Model Interface USB id Status Comment
Kodak DC240 Serial port   Good Use gphoto2 backend to get USB support

Backend: dmc (unmaintained)

Manual page: sane-dmc

Manufacturer Model Interface USB id Status Comment
Polaroid DMC SCSI   Good  

Video Cameras

Backends: qcam, stv680, unsupported

Backend: qcam (unmaintained)

Manual page: sane-qcam

Manufacturer Model Interface USB id Status Comment
Connectix Color QuickCam Parport   Good Requires root privileges.
Greyscale QuickCam Parport   Minimal Requires root privileges. Partly working.

Backend: stv680 (1.0-1)

Link(s): http://gkall.hobby.nl/stv680-aiptek.html
Manual page: sane-stv680
Comment: This vidcam backend is for the stv0680 chipset, See the website for more info.

Manufacturer Model Interface USB id Status Comment
Aiptek Aiptek Pencam USB 0x0553/0x0202 Minimal image is OK for CIF and QCIF, VGA and QVGA untested, streaming video is a problem
Konica e-mini USB 0x04c8/0x0722 Untested
Digital Dream l' espion XS USB 0x1183/0x0001 Untested
Creative WebCam Go Mini USB 0x041e/0x4007 Untested

Backend: unsupported (2010-06-09)

Link(s): /contrib.html
Comment: The devices mentioned here are not supported by any SANE backend. However, there may be links to information about them or stand-alone programs.

Manufacturer Model Interface USB id Status Comment
Biolux 654 (micrOcular) USB 0x0923/0x010f Unsupported Not supported yet. See link for more details.
Grandtek Scopecam 8x30 Binocular & Digital Camera USB 0x0797/0x801c Unsupported Not Supported yet. See link for more details.

APIs

Backends: gphoto2, pint, pnm, test, v4l

Backend: gphoto2 (0.0)

Link(s): mailto:peter@fales-lorenz.net
Manual page: sane-gphoto2
Description: Multiple cameras supported by the gphoto2 libraries
Comment: The long-term plan is to support all the cameras supported by the gphoto2 libraries (currently over 140 models). However, at this stage, only a handful of cameras are definitely known to work with SANE. Other cameras will probably work if the native file format is EXIF or JPEG. Testers welcome!

Backend: pint (unmaintained)

Manual page: sane-pint
Description: Scanners with the machine-independent PINT interface
Comment: Haven't been tested for a long time. Handle with care.

Backend: pnm (1.0.8)

Link(s): mailto:henning@meier-geinitz.de
Manual page: sane-pnm
Description: Reads PNM files
Comment: Used for debugging frontends. Obsolete, use test backend instead.

Backend: test (1.0-28)

Link(s): http://www.meier-geinitz.de/sane/test-backend/
Manual page: sane-test
Description: Frontend-tester
Comment: Backend for testing frontends. Also serves as example for SANE backend options.

Backend: v4l (1.0-3)

Link(s): mailto:henning@meier-geinitz.de
Manual page: sane-v4l
Description: Interface to Video For Linux API
Comment: Supports video cameras and other devices accessed by the v4l kernel API, e.g. bttv devices. Quite a lot of known bugs.

Meta Backends

Backends: dll, net

Backend: dll (1.0.13)

Link(s): mailto:henning@meier-geinitz.de
Manual page: sane-dll
Description: Dynamic loading of shared-library backends.

Backend: net (1.0.14)

Link(s): http://www.penguin-breeder.org/?page=sane-net
Manual page: sane-net
Description: Network access to saned servers
Comment: Can be used to access any scanner supported by SANE over the net. Supports IPv4 and IPv6.

Legend:

Backend:
Name of the backend, in parentheses if available: Version of backend/driver; newer versions may be available from their home sites.
NEW! means brand-new to the current release of SANE.
UNMAINTAINED means that nobody maintains that backend. Expect no new features or newly supported devices. You are welcome to take over maintainership.
Link(s):
Link(s) to more extensive and detailed information, if it exists, or the email address of the author or maintainer.
Manual Page:
A link to the man-page online, if it exists.
Comment:
More information about the backend or model, e.g. the level of support and possible problems.
Manufacturer:
Manufacturer, vendor or brand name of the device.
Model:
Name of the device.
Interface:
How the device is connected to the computer.
USB id:
The USB vendor and product ids as printed by sane-find-scanner -q (only applicable for USB devices).
Status:
Indicates how many of the features the device provides are supported by SANE.
  • unsupported means the device is not supported at least by this backend. It may be supported by other backends, however.
  • untested means the device may be supported but couldn't be tested. Be very careful and report success/failure.
  • minimal means that the device is detected and scans at least in one mode. But the quality is bad or important features won't work.
  • basic means it works at least in the most important modes but quality is not perfect.
  • good means the device is usable for day-to-day work. Some rather exotic features may be missing.
  • complete means the backends supports everything the device can do.
Description:
The scope of application of the backend.

SANE homepage
Contact
This page was last updated on Wed Jul 31 07:52:48 2013 by sane-desc 3.5 from sane-backends 1.0.24git sane-backends-1.0.27/testsuite/tools/Makefile.am0000664000175000017500000000271012775312262016456 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2013 Stéphane Voltz and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. all: @echo "run 'make check' to run tests" SANEDESC = ../../tools/sane-desc$(EXEEXT) TESTFILE = $(srcdir)/data/testfile.desc OUTFILES = *.res DEVICE = test EXTRA_DIST = data/testfile.desc data/ascii.ref data/db.ref data/hal-new.ref \ data/hal.ref data/html-backends-split.ref data/html-mfgs.ref \ data/hwdb.ref data/plist.ref data/statistics.ref \ data/udev+acl.ref data/udev+hwdb.ref data/udev.ref \ data/usermap.ref data/xml.ref CLEANFILES = $(OUTFILES) all: help help: @echo "Use 'make check' to run the tests." check: check.local check.local: @echo "**** Testing $(SANEDESC) with $(TESTFILE)" @for mode in ascii html-backends-split html-mfgs xml statistics usermap db udev udev+acl udev+hwdb hwdb plist hal hal-new; \ do \ $(SANEDESC) -m $$mode -s $(srcdir)/data >$$mode.res ;\ if diff -I "[ 012][0-9]:[0-5][0-9]:[0-6][0-9] 20[0-9][0-9]" \ -I "sane-backends 1\.0\.[0-9]\+\(git\)\?$$" \ $(srcdir)/data/$$mode.ref $$mode.res ; \ then \ echo "PASS: sane-desc -m $$mode -s $(srcdir)/data"; \ else \ echo "FAIL: sane-desc -m $$mode -s $(srcdir)/data"; \ exit 1 ;\ fi; \ done ;\ echo "================" ;\ echo "All tests passed" ;\ echo "================" sane-backends-1.0.27/testsuite/README0000664000175000017500000000112512112021330014113 00000000000000SANE test suite =============== Petter Reinholdtsen This is a test framework for the Scanner Access Now Easy project (SANE). Please add more tests. This framework should be able to test everything without installing, to make sure a new distribution is function properly before the old one is replaced. If it isn't, please fix the bug. :-) The current tests use the test backend to scan in flatbed, hand scanner and three pass mode. Also a 16 bit color image is created and compared to the "right" one. This test should detect any little/big endian issues in scanimage. sane-backends-1.0.27/testsuite/Makefile.in0000664000175000017500000005301513110564734015330 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = testsuite DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = sanei tools SCANIMAGE = ../frontend/scanimage$(EXEEXT) TESTFILE = $(srcdir)/testfile.pnm OUTFILE = outfile.pnm DEVICE = test OPTIONS = --mode Color --depth 16 --test-picture "Color pattern" --resolution 50 -y 20 -x 20 > $(OUTFILE) EXTRA_DIST = README testfile.pnm CLEANFILES = $(OUTFILE) all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu testsuite/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu testsuite/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am all: help help: @echo "Use 'make test' to run the tests." test: test.local test.local: @echo "**** Testing $(SCANIMAGE) with device $(DEVICE)" @if echo "---> Trying flatbed scanner" && \ $(SCANIMAGE) -d $(DEVICE) -T && \ echo "<--- Flatbed scanner succeded" && \ echo "---> Trying three pass flatbed scanner" && \ $(SCANIMAGE) -d $(DEVICE) --mode Color --three-pass=yes -T && \ echo "<--- Three pass scanner succeded" && \ echo "---> Trying hand scanner" && \ $(SCANIMAGE) -d $(DEVICE) --hand-scanner=yes -T && \ echo "<--- Hand scanner succeded" && \ echo "---> Checking 16 bit color mode" && \ $(SCANIMAGE) -d $(DEVICE) $(OPTIONS) && \ cmp -s $(TESTFILE) $(OUTFILE) && \ echo "<--- 16 bit color mode succeded" && \ rm $(OUTFILE) ; \ then echo ; echo ; echo "**** All tests passed" ; \ else echo ; echo; \ echo "**** Something failed (maybe test backend not enabled by configure?)";\ exit 1; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/testsuite/sanei/0000775000175000017500000000000013110600540014420 500000000000000sane-backends-1.0.27/testsuite/sanei/sanei_config_test.c0000664000175000017500000005460212775312262020217 00000000000000#include "../../include/sane/config.h" #include #include #include #include #include #include #include /* sane includes for the sanei functions called */ #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #define XSTR(s) STR(s) #define STR(s) #s #define CONFIG_PATH XSTR(TESTSUITE_SANEI_SRCDIR) /* * variables and functions used by the tests below */ /* range for constraint */ static const SANE_Range model_range = { 1000, /* minimum */ 2000, /* maximum */ 2 /* quantization */ }; /* range for memory buffer size constraint */ static const SANE_Range buffer_range = { 1024, /* minimum bytes */ 2048 * 1024, /* maximum bytes */ 1024 /* quantization */ }; /* range for int value in [0-15] */ static const SANE_Range value16_range = { 0, /* minimum */ 15, /* maximum */ 1 /* quantization */ }; /* range for fixed height value */ static const SANE_Range height_range = { SANE_FIX (0), /* minimum */ SANE_FIX (29.7), /* maximum */ 0 /* no quantization : hard to do for float values ... */ }; /* list of astra models */ static const SANE_String_Const astra_models[] = { "610", "1220", "1600", "2000", NULL }; /* string list */ static const SANE_String_Const string_list[] = { "string1", "string2", "string3", "string4", NULL }; /* last device name used for attach callback */ static char *lastdevname = NULL; static SANE_Status check_config_attach (SANEI_Config * config, const char *devname) { /* silence compiler warning for now */ if (config == NULL) { return SANE_STATUS_INVAL; } fprintf (stdout, "attaching with devname '%s'\n", devname); if (lastdevname != NULL) { free (lastdevname); } lastdevname = strdup (devname); return SANE_STATUS_GOOD; } /******************************/ /* start of tests definitions */ /******************************/ /* * non-existent config file */ static void inexistent_config (void) { SANE_Status status; SANEI_Config config; config.count = 0; config.descriptors = NULL; config.values = NULL; status = sanei_configure_attach (CONFIG_PATH "/data/inexistent.conf", &config, NULL); /* check results */ assert (status != SANE_STATUS_GOOD); } /* * no config struct */ static void null_config (void) { SANE_Status status; status = sanei_configure_attach (CONFIG_PATH "/data/umax_pp.conf", NULL, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); } /* * no attach function */ static void null_attach (void) { SANE_Status status; status = sanei_configure_attach (CONFIG_PATH "/data/umax_pp.conf", NULL, NULL); /* check results */ assert (status == SANE_STATUS_GOOD); } /* * empty config : backend has no configuration option */ static void empty_config (void) { SANE_Status status; SANEI_Config config; config.count = 0; config.descriptors = NULL; config.values = NULL; status = sanei_configure_attach (CONFIG_PATH "/data/empty.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); } /* * string option */ static void string_option (void) { SANE_Status status; SANEI_Config config; SANE_Char modelname[128]; SANE_Char vendor[128]; SANE_Option_Descriptor *options[2]; void *values[2]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "modelname"; options[i]->title = "model name"; options[i]->desc = "user provided scanner's model name"; options[i]->type = SANE_TYPE_STRING; options[i]->unit = SANE_UNIT_NONE; options[i]->size = 128; options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = modelname; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "vendor"; options[i]->title = "vendor name"; options[i]->desc = "user provided scanner's vendor name"; options[i]->type = SANE_TYPE_STRING; options[i]->unit = SANE_UNIT_NONE; options[i]->size = 128; options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = vendor; i++; config.count = i; config.descriptors = options; config.values = values; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/string.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); assert (strcmp (modelname, "my model") == 0); assert (strcmp (vendor, "my vendor") == 0); } /* * int option */ static void int_option (void) { SANE_Status status; SANEI_Config config; SANE_Word modelnumber; SANE_Option_Descriptor *options[1]; void *values[1]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "modelnumber"; options[i]->title = "model number"; options[i]->desc = "user provided scanner's model number"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &model_range; values[i] = &modelnumber; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/int.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); assert (modelnumber == 1234); } /* * int option out of range */ static void wrong_range_int_option (void) { SANE_Status status; SANEI_Config config; SANE_Word modelnumber = -1; SANE_Option_Descriptor *options[1]; void *values[1]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "modelnumber"; options[i]->title = "model number"; options[i]->desc = "user provided scanner's model number"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &model_range; values[i] = &modelnumber; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/wrong-range.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_INVAL); assert (modelnumber == -1); } /* * word array */ static void word_array_option (void) { SANE_Status status; SANEI_Config config; SANE_Word numbers[7]; SANE_Option_Descriptor *options[1]; void *values[1]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "numbers"; options[i]->title = "some numbers"; options[i]->desc = "an array of numbers"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word) * 7; options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &model_range; values[i] = numbers; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/word-array.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); for (i = 0; i < 7; i++) { assert (numbers[i] == 1000 + 100 * i); } } /* * string option with string list constraint */ static void string_list_option (void) { SANE_Status status; SANEI_Config config; SANE_Char choice[128]; SANE_Option_Descriptor *options[1]; void *values[1]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "string-choice"; options[i]->title = "string choice"; options[i]->desc = "one string among a fixed list"; options[i]->type = SANE_TYPE_STRING; options[i]->unit = SANE_UNIT_NONE; options[i]->size = 128; options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_STRING_LIST; options[i]->constraint.string_list = string_list; values[i] = choice; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/string-list.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); assert (strcmp (choice, "string3") == 0); } /* * string option with string list constraint */ static void wrong_string_list_option (void) { SANE_Status status; SANEI_Config config; SANE_Char choice[128]; SANE_Option_Descriptor *options[1]; void *values[1]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "string-choice"; options[i]->title = "string choice"; options[i]->desc = "one string among a fixed list"; options[i]->type = SANE_TYPE_STRING; options[i]->unit = SANE_UNIT_NONE; options[i]->size = 128; options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_STRING_LIST; options[i]->constraint.string_list = string_list; values[i] = choice; i++; config.descriptors = options; config.values = values; config.count = i; choice[0] = 0; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/wrong-string-list.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_INVAL); assert (strcmp (choice, "") == 0); } /* * real umax_pp confiugration file parsing */ static void umax_pp (void) { SANE_Status status; SANEI_Config config; SANE_Option_Descriptor *options[9]; void *values[9]; int i = 0; /* placeholders for options */ SANE_Word buffersize = -1; SANE_Word redgain = -1; SANE_Word greengain = -1; SANE_Word bluegain = -1; SANE_Word redoffset = -1; SANE_Word greenoffset = -1; SANE_Word blueoffset = -1; SANE_Char model[128]; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "buffer"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &buffer_range; values[i] = &buffersize; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "red-gain"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &value16_range; values[i] = &redgain; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "green-gain"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &value16_range; values[i] = &greengain; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "blue-gain"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &value16_range; values[i] = &bluegain; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "red-offset"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &value16_range; values[i] = &redoffset; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "green-offset"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &value16_range; values[i] = &greenoffset; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "blue-offset"; options[i]->type = SANE_TYPE_INT; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &value16_range; values[i] = &blueoffset; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "astra"; options[i]->type = SANE_TYPE_STRING; options[i]->unit = SANE_UNIT_NONE; options[i]->size = 128; options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_STRING_LIST; options[i]->constraint.string_list = astra_models; values[i] = &model; i++; config.descriptors = options; config.values = values; config.count = i; model[0] = 0; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/umax_pp.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); assert (buffersize == 1048576); assert (redgain == 1); assert (greengain == 2); assert (bluegain == 3); assert (redoffset == 4); assert (greenoffset == 5); assert (blueoffset == 6); assert (strcmp (model, "1600") == 0); assert (strcmp (lastdevname, "port safe-auto") == 0); /* free memory */ while (i > 0) { i--; free (options[i]); } } /* * boolean option */ static void wrong_bool_option (void) { SANE_Status status; SANEI_Config config; SANE_Option_Descriptor *options[2]; void *values[2]; SANE_Bool booltrue, boolfalse; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "booltrue"; options[i]->title = "boolean true"; options[i]->type = SANE_TYPE_BOOL; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Bool); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = &booltrue; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "boolfalse"; options[i]->title = "boolean false"; options[i]->type = SANE_TYPE_BOOL; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Bool); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = &boolfalse; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/wrong-boolean.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_INVAL); assert (booltrue == SANE_TRUE); } /* * boolean option */ static void bool_option (void) { SANE_Status status; SANEI_Config config; SANE_Option_Descriptor *options[3]; void *values[3]; SANE_Bool booltrue, boolfalse, boolarray[3]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "booltrue"; options[i]->title = "boolean true"; options[i]->type = SANE_TYPE_BOOL; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Bool); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = &booltrue; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "boolfalse"; options[i]->title = "boolean false"; options[i]->type = SANE_TYPE_BOOL; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Bool); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = &boolfalse; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "boolarray"; options[i]->title = "boolean array"; options[i]->type = SANE_TYPE_BOOL; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (boolarray); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = boolarray; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/boolean.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); assert (booltrue == SANE_TRUE); assert (boolfalse == SANE_FALSE); for (i = 0; i < 3; i++) { assert (boolarray[i] == (SANE_Bool) i % 2); } } /* * fixed option */ static void fixed_option (void) { SANE_Status status; SANEI_Config config; SANE_Word width, height, fixedarray[7]; SANE_Option_Descriptor *options[3]; void *values[3]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "width"; options[i]->title = "width"; options[i]->type = SANE_TYPE_FIXED; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = &width; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "height"; options[i]->title = "height"; options[i]->type = SANE_TYPE_FIXED; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = &height; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "array-of-fixed"; options[i]->title = "array of fixed"; options[i]->type = SANE_TYPE_FIXED; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (fixedarray); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &height_range; values[i] = fixedarray; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/fixed.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); assert (width == SANE_FIX (21.0)); assert (height == SANE_FIX (29.7)); for (i = 0; i < 7; i++) { assert (fixedarray[i] == SANE_FIX (2.0 + 0.1 * ((float) i))); } } /* * fixed option with value out of range */ static void wrong_fixed_option (void) { SANE_Status status; SANEI_Config config; SANE_Word height; SANE_Option_Descriptor *options[1]; void *values[1]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "height"; options[i]->title = "height"; options[i]->type = SANE_TYPE_FIXED; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &height_range; values[i] = &height; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/wrong-fixed.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_INVAL); } static void snapscan (void) { SANE_Status status; SANEI_Config config; SANE_Char firmware[128]; SANE_Option_Descriptor *options[1]; void *values[1]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "firmware"; options[i]->title = "scanner's firmware path"; options[i]->desc = "user provided scanner's full path"; options[i]->type = SANE_TYPE_STRING; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (firmware); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = firmware; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/snapscan.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); assert (strcmp (firmware, "/usr/share/sane/snapscan/your-firmwarefile.bin") == 0); /* TODO must test attach() done */ } /** * create the test suite for sanei config related tests */ static void sanei_config_suite (void) { /* tests */ inexistent_config (); empty_config (); null_config (); null_attach (); string_option (); int_option (); string_list_option (); word_array_option (); bool_option (); fixed_option (); wrong_range_int_option (); wrong_string_list_option (); wrong_bool_option (); wrong_fixed_option (); /* backend real conf inspired cases */ umax_pp (); snapscan (); } /** * main function to run the test suites */ int main (void) { /* set up config dir for local conf files */ putenv("SANE_CONFIG_DIR=.:/"); /* run suites */ sanei_config_suite (); return 0; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/testsuite/sanei/sanei_check_test.c0000664000175000017500000002077012775312262020026 00000000000000#include "../../include/sane/config.h" #include #include #include #include #include #include #include /* sane includes for the sanei functions called */ #include "../../include/sane/sane.h" #include "../../include/sane/saneopts.h" #include "../../include/sane/sanei.h" /* range for constraint */ static const SANE_Range int_range = { 3, /* minimum */ 18, /* maximum */ 3 /* quantization */ }; static SANE_Option_Descriptor int_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Word), 0, SANE_CONSTRAINT_RANGE, {NULL} }; #define ARRAY_SIZE 7 static SANE_Option_Descriptor array_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Word) * ARRAY_SIZE, 0, SANE_CONSTRAINT_RANGE, {NULL} }; static SANE_Option_Descriptor bool_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_BOOL, SANE_UNIT_MM, sizeof (SANE_Bool), 0, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Option_Descriptor bool_array_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_BOOL, SANE_UNIT_MM, sizeof (SANE_Bool) * ARRAY_SIZE, 0, SANE_CONSTRAINT_NONE, {NULL} }; #define WORD_SIZE 9 static const SANE_Int dpi_list[] = { WORD_SIZE - 1, 100, 200, 300, 400, 500, 600, 700, 800 }; static SANE_Option_Descriptor word_array_opt = { SANE_NAME_SCAN_RESOLUTION, SANE_TITLE_SCAN_RESOLUTION, SANE_DESC_SCAN_RESOLUTION, SANE_TYPE_INT, SANE_UNIT_DPI, sizeof (SANE_Word) * WORD_SIZE, 100, SANE_CONSTRAINT_WORD_LIST, {NULL} }; /******************************/ /* start of tests definitions */ /******************************/ /* * constrained int */ static void min_int_value (void) { SANE_Int value = int_range.min; SANE_Status status; status = sanei_check_value (&int_opt, &value); /* check results */ assert (status == SANE_STATUS_GOOD); assert (value == int_range.min); } static void max_int_value (void) { SANE_Int value = int_range.max; SANE_Status status; status = sanei_check_value (&int_opt, &value); /* check results */ assert (status == SANE_STATUS_GOOD); assert (value == int_range.max); } static void below_min_int_value (void) { SANE_Int value = int_range.min - 1; SANE_Status status; status = sanei_check_value (&int_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } /* rounded to lower value */ static void quant1_int_value (void) { SANE_Int value = int_range.min + 1; SANE_Status status; status = sanei_check_value (&int_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } /* close to higher value */ static void quant2_int_value (void) { SANE_Int value = int_range.min + int_range.quant - 1; SANE_Status status; status = sanei_check_value (&int_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } static void in_range_int_value (void) { SANE_Int value = int_range.min + int_range.quant; SANE_Status status; status = sanei_check_value (&int_opt, &value); /* check results */ assert (status == SANE_STATUS_GOOD); assert (value == int_range.min + int_range.quant); } static void above_max_int_value (void) { SANE_Int value = int_range.max + 1; SANE_Status status; status = sanei_check_value (&int_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } /* * constrained int array */ static void min_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min; } status = sanei_check_value (&array_opt, value); /* check results */ assert (status == SANE_STATUS_GOOD); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.min); } } static void max_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.max; } status = sanei_check_value (&array_opt, value); /* check results */ assert (status == SANE_STATUS_GOOD); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.max); } } static void below_min_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min - 1; } status = sanei_check_value (&array_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } /* rounded to lower value */ static void quant1_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min + 1; } status = sanei_check_value (&array_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } /* rounded to higher value */ static void quant2_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min + int_range.quant - 1; } status = sanei_check_value (&array_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } static void in_range_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min + int_range.quant; } status = sanei_check_value (&array_opt, &value); /* check results */ assert (status == SANE_STATUS_GOOD); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.min + int_range.quant); } } static void above_max_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.max + 1; } status = sanei_check_value (&array_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } static void bool_true (void) { SANE_Bool value = SANE_TRUE; SANE_Status status; status = sanei_check_value (&bool_opt, &value); /* check results */ assert (status == SANE_STATUS_GOOD); } static void bool_false (void) { SANE_Bool value = SANE_FALSE; SANE_Status status; status = sanei_check_value (&bool_opt, &value); /* check results */ assert (status == SANE_STATUS_GOOD); } static void wrong_bool (void) { SANE_Bool value = 2; SANE_Status status; status = sanei_check_value (&bool_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } static void bool_array (void) { SANE_Bool value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) value[i] = i % 2; status = sanei_check_value (&bool_array_opt, &value); /* check results */ assert (status == SANE_STATUS_GOOD); } static void word_array_ok (void) { SANE_Word value = 400; SANE_Status status; status = sanei_check_value (&word_array_opt, &value); /* check results */ assert (status == SANE_STATUS_GOOD); } static void word_array_nok (void) { SANE_Word value = 444; SANE_Status status; status = sanei_check_value (&word_array_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } static void wrong_bool_array (void) { SANE_Bool value[ARRAY_SIZE]; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) value[i] = i % 2; value[3] = 4; status = sanei_check_value (&bool_array_opt, &value); /* check results */ assert (status == SANE_STATUS_INVAL); } /** * run the test suite for sanei_check_value related tests */ static void sanei_check_suite (void) { /* to be compatible with pre-C99 compilers */ int_opt.constraint.range = &int_range; array_opt.constraint.range = &int_range; word_array_opt.constraint.word_list = dpi_list; /* tests for constrained int value */ min_int_value (); max_int_value (); below_min_int_value (); above_max_int_value (); quant1_int_value (); quant2_int_value (); in_range_int_value (); /* tests for constrained int array */ min_int_array (); max_int_array (); below_min_int_array (); above_max_int_array (); quant1_int_array (); quant2_int_array (); in_range_int_array (); /* tests for boolean value */ bool_true (); bool_false (); wrong_bool (); bool_array (); wrong_bool_array (); /* word array test */ word_array_ok (); word_array_nok (); } int main (void) { sanei_check_suite (); return 0; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/testsuite/sanei/test_wire.c0000664000175000017500000001255413106201017016521 00000000000000#include "../include/sane/config.h" #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_wire.h" #include "../include/sane/sanei_codec_ascii.h" #include "../include/sane/sanei_codec_bin.h" static Wire w; static SANE_Word dpi_word_list[] = { 4, /* # of elements */ 3, 30, 300, -600 }; static SANE_String_Const mode_list[] = { "Lineart", "Grayscale", "Color", 0 }; static char *program_name; static char *default_codec = "bin"; static char *default_outfile = "test_wire.out"; static int usage (int code) { if (code == 0) { printf ("Usage: %s [OPTION]...\n\ \n\ Test the SANE wire manipulation library.\n\ \n\ --codec=CODEC set the codec [default=%s]\n\ --help display this message and exit\n\ -o, --output=FILE set the output file [default=%s]\n\ --readonly do not create FILE, just read it\n\ --version print version information\n\ \n\ Valid CODECs are: `ascii' `bin'\n", program_name, default_codec, default_outfile); } else { fprintf (stderr, "Type ``%s --help'' for more information.\n", program_name); } exit (code); } int main (int __sane_unused__ arg, char **argv) { SANE_Option_Descriptor desc[2], *desc_ptr; SANE_Word len; char *codec = default_codec; char *outfile = default_outfile; int readonly = 0; program_name = argv[0]; argv++; while (*argv != 0) { if (!strcmp (*argv, "--codec")) { if (argv[1] == 0) { fprintf (stderr, "%s: option `%s' requires an argument\n", program_name, *argv); usage (1); } argv++; codec = *argv; } else if (!strncmp (*argv, "--codec=", 8)) { codec = *argv + 8; } else if (!strcmp (*argv, "--help")) { usage (0); } else if (!strcmp (*argv, "-o") || !strcmp (*argv, "--output")) { if (argv[1] == 0) { fprintf (stderr, "%s: option `%s' requires an argument\n", program_name, *argv); usage (1); } argv++; outfile = *argv; } else if (!strncmp (*argv, "--output=", 9)) { outfile = *argv + 9; } else if (!strcmp (*argv, "--readonly")) { readonly = 1; } else if (!strcmp (*argv, "--version")) { printf ("test_wire (%s) %s\n", PACKAGE, VERSION); exit (0); } else if (**argv == '-') { fprintf (stderr, "%s: unrecognized option `%s'\n", program_name, *argv); usage (1); } else { fprintf (stderr, "%s: too many arguments\n", program_name); } argv++; } if (!strcmp (codec, "bin")) sanei_w_init (&w, sanei_codec_bin_init); else if (!strcmp (codec, "ascii")) sanei_w_init (&w, sanei_codec_ascii_init); else { fprintf (stderr, "%s: unknown codec type `%s'\n", program_name, codec); usage (1); } desc[0].name = "resolution"; desc[0].title = 0; desc[0].desc = "Determines scan resolution in dots/inch (\"DPI\")."; desc[0].type = SANE_TYPE_FIXED; desc[0].unit = SANE_UNIT_DPI; desc[0].size = sizeof (SANE_Word); desc[0].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; desc[0].constraint_type = SANE_CONSTRAINT_WORD_LIST; desc[0].constraint.word_list = dpi_word_list; desc[1].name = "mode"; desc[1].title = "Scan Mode"; desc[1].desc = "Determines scan mode."; desc[1].type = SANE_TYPE_STRING; desc[1].unit = SANE_UNIT_NONE; desc[1].size = 10; desc[1].cap = (SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC); desc[1].constraint_type = SANE_CONSTRAINT_STRING_LIST; desc[1].constraint.string_list = mode_list; { int flags; if (readonly) { printf ("reading %s output from %s\n", codec, outfile); flags = O_RDONLY; } else { printf ("creating %s\n", outfile); flags = O_RDWR | O_CREAT | O_TRUNC; } w.io.fd = open (outfile, flags, 0666); if (w.io.fd < 0) { perror (outfile); return -1; } } w.io.read = read; w.io.write = readonly ? 0 : write; if (!readonly) { sanei_w_set_dir (&w, WIRE_ENCODE); w.status = 0; len = NELEMS (desc); desc_ptr = desc; sanei_w_array (&w, &len, (void **) &desc_ptr, (WireCodecFunc) sanei_w_option_descriptor, sizeof (desc[0])); if (w.status == 0) printf ("%s encode successful\n", codec); else fprintf (stderr, "%s: %s encode error %d: %s\n", codec, program_name, w.status, strerror (w.status)); printf ("%s output written to %s\n", codec, outfile); } sanei_w_set_dir (&w, WIRE_DECODE); w.status = 0; if (!readonly) { printf ("reading %s output from %s\n", codec, outfile); lseek (w.io.fd, 0, SEEK_SET); } sanei_w_array (&w, &len, (void **) &desc_ptr, (WireCodecFunc) sanei_w_option_descriptor, sizeof (desc[0])); if (w.status == 0) printf ("%s decode successful\n", codec); else fprintf (stderr, "%s: %s decode error %d: %s\n", program_name, codec, w.status, strerror (w.status)); sanei_w_set_dir (&w, WIRE_FREE); w.status = 0; sanei_w_array (&w, &len, (void **) &desc_ptr, (WireCodecFunc) sanei_w_option_descriptor, sizeof (desc[0])); if (w.status == 0) printf ("free successful\n"); else fprintf (stderr, "%s: free error %d: %s\n", program_name, w.status, strerror (w.status)); close (w.io.fd); return 0; } sane-backends-1.0.27/testsuite/sanei/sanei_usb_test.c0000664000175000017500000005412713106201017017525 00000000000000#include "../../include/sane/config.h" #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_MKDIR #include #include #endif #include #define BACKEND_NAME sanei_usb #include "../../include/sane/sane.h" #include "../../include/sane/sanei.h" #include "../../include/sane/saneopts.h" #include "../../include/sane/sanei_backend.h" #include "../../include/sane/sanei_usb.h" #include "../../include/_stdint.h" /* * In order to avoid modifying sanei_usb.c to allow for unit tests * we include it so we can use its private variables and structures * and still test the code. */ #include "../../sanei/sanei_usb.c" /** test sanei_usb_init() * calls sanei_usb_init * @param expected expected use count * @return 1 on success, else 0 */ static int test_init (int expected) { /* initialize USB */ printf ("%s starting ...\n", __func__); sanei_usb_init (); if (initialized == 0) { printf ("ERROR: sanei_usb not initialized!\n"); return 0; } if (initialized != expected) { printf ("ERROR: incorrect use count, expected %d, got %d!\n", expected, initialized); return 0; } printf ("sanei_usb initialized, use count is %d ...\n", initialized); printf ("%s success\n\n", __func__); return 1; } /** test sanei_usb_exit() * calls sanei_usb_exit * @param expected use count after exit call * @return 1 on success, else 0 */ static int test_exit (int expected) { printf ("%s starting ...\n", __func__); /* end of USB use test */ sanei_usb_exit (); if (initialized != expected) { printf ("ERROR: incorrect use count, expected %d, got %d!\n", expected, initialized); return 0; } printf ("%s success\n\n", __func__); return 1; } /** count detected devices * count all detected devices and check it against expected value * @param expected detected count * @return 1 on success, else 0 */ static int count_detected (int expected) { int num = 0; int i; for (i = 0; i < device_number; i++) { if (devices[i].missing == 0 && devices[i].devname != NULL) { num++; } } if (num != expected) { printf ("ERROR: %d detected devices, expected %d!\n", num, expected); return 0; } printf ("%d devices still detected.\n", num); return 1; } /** create mock device * create a mock device entry * @param device device pointer to fill with mock data * @return nothing */ static void create_mock_device (char *devname, device_list_type * device) { memset (device, 0, sizeof (device_list_type)); device->devname = strdup (devname); device->vendor = 0xdead; device->product = 0xbeef; #if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) device->method = sanei_usb_method_libusb; #endif #ifdef HAVE_USBCALLS device->method = sanei_usb_method_usbcalls; #endif #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USBCALLS) device->method == sanei_usb_method_scanner_driver; #endif } /** test store_device * test store_device for corner cases not covered by the * other regular use by sanei_usb_scan_devices * the startiing situation is that the mock device has never * put into device list. * @return 1 on success, else 0 */ static int test_store_device (void) { int current_number; int expected; int i; int found; device_list_type mock; create_mock_device ("mock", &mock); /* first test store when there is no more room * to store device */ current_number = device_number; device_number = MAX_DEVICES; /* give unused devices a name so strcmp() won't crash. */ for (i = current_number; i < MAX_DEVICES; i++) devices[i].devname = ""; store_device (mock); /* there should be no more devices */ if (device_number > MAX_DEVICES) { printf ("ERROR: store past end of device list!\n"); return 0; } /* walk device list to be sure mock device hasn't been stored */ for (i = 0; i < MAX_DEVICES; i++) { if (devices[i].devname && !strcmp (devices[i].devname, mock.devname)) { printf ("ERROR: device stored although there were no place for it!\n"); return 0; } } /* restore device_number */ device_number = current_number; /* reset unused devnames to NULL */ for (i = current_number; i < MAX_DEVICES; i++) devices[i].devname = NULL; expected = device_number + 1; /* store mock device */ store_device (mock); found = 0; for (i = 0; i < MAX_DEVICES && !found; i++) { if (devices[i].devname && !strcmp (devices[i].devname, mock.devname)) { found = 1; } } if (device_number != expected || !found) { printf ("ERROR: mock device not stored !\n"); return 0; } /* scan devices should mark it as missing, and device_number should decrease */ sanei_usb_scan_devices (); found = 0; for (i = 0; i < MAX_DEVICES && !found; i++) { if (devices[i].devname && devices[i].missing == 1 && !strcmp (devices[i].devname, mock.devname)) { found = 1; } } if (device_number != expected || !found) { printf ("ERROR: mock device still present !\n"); return 0; } /* second scan devices should mark missing to 2 */ sanei_usb_scan_devices (); found = 0; for (i = 0; i < MAX_DEVICES && !found; i++) { if (devices[i].devname && devices[i].missing == 2 && !strcmp (devices[i].devname, mock.devname)) { found = 1; } } if (device_number != expected || !found) { printf ("ERROR: mock device slot not reusable !\n"); return 0; } /* store mock device again, slot in devices should be reused * and device_number shouldn't change */ create_mock_device ("mock2", &mock); store_device (mock); found = 0; for (i = 0; i < MAX_DEVICES && !found; i++) { if (devices[i].devname && !strcmp (devices[i].devname, mock.devname)) { found = 1; } } if (device_number != expected || !found) { printf ("ERROR: mock device not stored !\n"); return 0; } /* last rescan to wipe mock device out */ sanei_usb_scan_devices (); return 1; } /** return count of opened devices * @return count of opened devices */ static int get_opened (void) { int num = 0; int i; for (i = 0; i < device_number; i++) { if (devices[i].missing == 0 && devices[i].devname != NULL && devices[i].open == SANE_TRUE) { num++; } } return num; } /** count opened devices * count all opended devices and check it against expected value * @param expected use opened count * @return 1 on success, else 0 */ static int count_opened (int expected) { int num = get_opened(); if (num != expected) { printf ("ERROR: %d opened devices, expected %d!\n", num, expected); return 0; } printf ("%d devices still opened.\n", num); return 1; } /** open all devices * loop on all existing devices and open them * @param dn array to store opened device number * @param expected number of devices to be opened * @return 1 on success, else 0 */ static int test_open_all (SANE_Int * dn, int expected) { int opened = 0; int i; int last; SANE_Status status; /* loop on detected devices and open them */ last = -1; for (i = 0; i < device_number; i++) { if (devices[i].missing == 0 && devices[i].devname != NULL) { /* open device */ status = sanei_usb_open (devices[i].devname, dn + opened); if (status == SANE_STATUS_GOOD) { opened++; last = i; } else { if (status == SANE_STATUS_ACCESS_DENIED || status == SANE_STATUS_DEVICE_BUSY) { expected--; } else { printf ("ERROR: couldn't open device %s!\n", devices[i].devname); return 0; } } } } printf ("opened %d devices\n", opened); /* try to reopen an opened device when there is one */ if (last >= 0) { status = sanei_usb_open (devices[last].devname, dn + opened); if (status == SANE_STATUS_GOOD) { printf ("ERROR: unexpected success when opening %s twice!\n", devices[last].devname); return 0; } } /* there should be as many opened devices than detected devices */ return count_opened (expected); } /** test opening invalid device * try to open an non existing device * @return 1 on success, else 0 */ static int test_open_invalid (void) { SANE_Status status; SANE_Int dn; status = sanei_usb_open ("invalid device", &dn); if (status == SANE_STATUS_GOOD) { printf ("ERROR: unexpected success opening invalid device!\n"); return 0; } return 1; } /** close all devices * loop on all opened devices and close them * @param dn array of opened device number * @param expected number of devices to be closed * @return 1 on success, else 0 */ static int test_close_all (SANE_Int * dn, int expected) { int closed = 0; int i; /* loop on detected devices and open them */ for (i = 0; i < expected; i++) { /* close device */ sanei_usb_close (dn[i]); closed++; } printf ("closed %d devices\n", closed); /* there should be any more opened devices */ return count_opened (0); } /** claim all open devices * loop on all opened devices and claim interface 0 * @param dn array of opened device number * @param expected number of devices to be claimed * @return 1 on success, else 0 */ static int test_claim_all (SANE_Int * dn, int expected) { int claimed = 0; int i; SANE_Status status; device_list_type mock; claimed = 0; for (i = 0; i < expected; i++) { status = sanei_usb_claim_interface (dn[i], devices[dn[i]].interface_nr); if (status != SANE_STATUS_GOOD) { printf ("ERROR: couldn't claim interface 0 on device %d!\n", dn[i]); } else { claimed++; } } if (claimed != expected) { printf ("ERROR: expected %d claimed interfaces, got %d!\n", expected, claimed); return 0; } printf ("%d devices claimed...\n\n", claimed); /* try to claim invalid device entry */ status = sanei_usb_claim_interface (device_number, 0); if (status == SANE_STATUS_GOOD) { printf ("ERROR: could claim interface 0 on invalid device!\n"); return 0; } /* create a mock device and make it missing by rescanning */ create_mock_device ("mock", &mock); store_device (mock); sanei_usb_scan_devices (); /* try to claim interface on missing device */ status = sanei_usb_claim_interface (device_number - 1, 0); if (status == SANE_STATUS_GOOD) { printf ("ERROR: could claim interface 0 on invalid device!\n"); return 0; } /* remove mock device */ device_number--; free (devices[device_number].devname); devices[device_number].devname = NULL; return 1; } /** release all claimed devices * loop on all opened devices and claim interface 0 * @param dn array of opened device number * @param expected number of devices to be claimed * @return 1 on success, else 0 */ static int test_release_all (SANE_Int * dn, int expected) { int released = 0; int i; SANE_Status status; device_list_type mock; released = 0; for (i = 0; i < expected; i++) { status = sanei_usb_release_interface (dn[i], devices[dn[i]].interface_nr); if (status != SANE_STATUS_GOOD) { printf ("ERROR: couldn't release interface 0 on device %d!\n", dn[i]); } else { released++; } } if (released != expected) { printf ("ERROR: expected %d released interfaces, got %d!\n", expected, released); return 0; } printf ("%d devices released...\n\n", released); /* try to release invalid device entry */ status = sanei_usb_release_interface (device_number, 0); if (status == SANE_STATUS_GOOD) { printf ("ERROR: could release interface 0 on invalid device!\n"); return 0; } /* create a mock device and make it missing by rescanning */ create_mock_device ("mock", &mock); store_device (mock); sanei_usb_scan_devices (); /* try to claim interface on missing device */ status = sanei_usb_release_interface (device_number - 1, 0); if (status == SANE_STATUS_GOOD) { printf ("ERROR: could release interface 0 on invalid device!\n"); return 0; } /* remove mock device */ device_number--; free (devices[device_number].devname); devices[device_number].devname = NULL; return 1; } /** get id for all devices names * loop on all existing devices and get vendor * and product id by name. * @param expected count * @return 1 on success, else 0 */ static int test_vendor_by_devname (void) { int i; SANE_Status status; SANE_Word vendor, product; device_list_type mock; /* loop on detected devices and open them */ for (i = 0; i < device_number; i++) { if (devices[i].missing == 0 && devices[i].devname != NULL) { /* get device id */ status = sanei_usb_get_vendor_product_byname (devices[i].devname, &vendor, &product); if (status != SANE_STATUS_GOOD) { printf ("ERROR: couldn't query device %s!\n", devices[i].devname); return 0; } if (vendor == 0 || product == 0) { printf ("ERROR: incomplete device id for %s!\n", devices[i].devname); return 0; } printf ("%s is %04x:%04x\n", devices[i].devname, vendor, product); } } /* add mock device */ create_mock_device ("mock", &mock); store_device (mock); status = sanei_usb_get_vendor_product_byname ("mock", &vendor, &product); if (status != SANE_STATUS_GOOD) { printf ("ERROR: getting vendor for mock devname!\n"); return 0; } if (vendor != mock.vendor || product != mock.product) { printf ("ERROR: wrong vendor/product for mock devname!\n"); return 0; } /* remove mock device */ device_number--; free (devices[device_number].devname); devices[device_number].devname = NULL; /* try go get id for an invalid devname */ status = sanei_usb_get_vendor_product_byname ("invalid devname", &vendor, &product); if (status == SANE_STATUS_GOOD) { printf ("ERROR: unexpected success getting id for invalid devname!\n"); return 0; } printf ("\n"); return 1; } /** get vendor for all devices id * loop on all existing devices and get vendor * and product id. * @param expected count * @return 1 on success, else 0 */ static int test_vendor_by_id (void) { int i; SANE_Status status; SANE_Word vendor, product; device_list_type mock; /* loop on detected devices and open them */ for (i = 0; i < device_number; i++) { if (devices[i].missing == 0 && devices[i].devname != NULL) { /* get device id */ status = sanei_usb_get_vendor_product (i, &vendor, &product); if (status != SANE_STATUS_GOOD) { printf ("ERROR: couldn't query device %d!\n", i); return 0; } if (vendor == 0 || product == 0) { printf ("ERROR: incomplete device id for %d!\n", i); return 0; } printf ("%d is %04x:%04x\n", i, vendor, product); } } /* add mock device */ create_mock_device ("mock", &mock); store_device (mock); status = sanei_usb_get_vendor_product (device_number - 1, &vendor, &product); if (status != SANE_STATUS_GOOD) { printf ("ERROR: getting vendor for mock devname!\n"); return 0; } if (vendor != mock.vendor || product != mock.product) { printf ("ERROR: wrong vendor/product for mock devname!\n"); return 0; } /* remove mock device */ device_number--; free (devices[device_number].devname); devices[device_number].devname = NULL; /* try go get id for an invalid id */ status = sanei_usb_get_vendor_product (device_number + 1, &vendor, &product); if (status == SANE_STATUS_GOOD) { printf ("ERROR: unexpected success getting vendor for invalid devname!\n"); return 0; } printf ("\n"); return 1; } /** test timeout functions : libusb only * @return 1 on success, else 0 */ static int test_timeout (void) { #if defined(HAVE_LIBUSB_LEGACY) || defined(HAVE_LIBUSB) int timeout = libusb_timeout; sanei_usb_set_timeout (5000); if (libusb_timeout != 5000) { printf ("ERROR: failed to set timeout\n"); return 1; } sanei_usb_set_timeout (timeout); #endif return 1; } /** test device scanning * call sanei_usb_scan_devices, since it has no return code, no real * assert can be done, but at least we can test it doesn't break * other functions or don't leak memory * @return always 1 */ static int test_scan_devices (int detected, int opened) { int rc; printf ("rescanning for devices ...\n"); sanei_usb_scan_devices (); rc = count_detected (detected); if (!rc) { printf ("ERROR: scanning devices change detected count!\n"); return 0; } rc = count_opened (opened); if (!rc) { printf ("ERROR: scanning devices change opened count!\n"); return 0; } printf ("\n"); return 1; } /** * flag for dummy attach */ static int dummy_flag; /** * expected device name during attach */ static char *expected_device; /** dummy attach function * dummy attach function * @return resturn SANE_STATUS_GOOD */ static SANE_Status dummy_attach (const char *dev) { dummy_flag = (strcmp (expected_device, dev) == 0); if (dummy_flag) { printf ("success attaching to %s...\n", dev); } else { printf ("failed attaching to %s...\n", dev); } return SANE_STATUS_GOOD; } /** test attaching usb device * create a mock device and attach to it, checking * if it is ok * @return 1 on success, else 0 */ static int test_attach (void) { device_list_type mock; /* add mock device and try ot attach to it */ dummy_flag = 0; create_mock_device ("mock", &mock); expected_device = mock.devname; store_device (mock); sanei_usb_attach_matching_devices ("usb 0xdead 0xbeef", dummy_attach); /* flag must be set */ if (dummy_flag != 1) { printf ("ERROR: couldn't attach to 'usb xdead 0xbeef' device!\n"); return 0; } /* attach by devname */ dummy_flag = 0; sanei_usb_attach_matching_devices (mock.devname, dummy_attach); /* flag must be set */ if (dummy_flag != 1) { printf ("ERROR: couldn't attach to 'mock' device!\n"); return 0; } /* attach to bogus device */ dummy_flag = 0; sanei_usb_attach_matching_devices ("usb 0x0001 0x0001", dummy_attach); /* flag must not be set */ if (dummy_flag != 0) { printf ("ERROR: shouldn't be attached to bogus device!\n"); return 0; } /* attach by bogus devname */ sanei_usb_attach_matching_devices ("bogus", dummy_attach); /* flag must not be set */ if (dummy_flag != 0) { printf ("ERROR: shouldn't be attached to bogus device!\n"); return 0; } /* remove mock device */ device_number--; free (devices[device_number].devname); devices[device_number].devname = NULL; dummy_flag = 0; return 1; } int main (int __sane_unused__ argc, char **argv) { int detected, opened, i; SANE_Int dn[MAX_DEVICES]; #ifdef HAVE_LIBUSB_LEGACY printf ("\n%s built with old libusb\n\n", argv[0]); #endif #ifdef HAVE_LIBUSB printf ("\n%s built with libusb-1.0\n\n", argv[0]); #endif #ifdef HAVE_USBCALLS printf ("\n%s built with usbcalls\n\n", argv[0]); #endif #if !defined(HAVE_LIBUSB_LEGACY) && !defined(HAVE_LIBUSB) && !defined(HAVE_USBCALLS) printf ("\n%s relying on deprecated scanner kernel module\n", argv[0]); #endif /* start sanei_usb */ assert (test_init (1)); /* test timeout function */ assert (test_timeout ()); /* count available devices */ detected = 0; for (i = 0; i < device_number; i++) { if (devices[i].missing == 0 && devices[i].devname != NULL) { detected++; } } printf ("%d devices found.\n", detected); /* rescan devices : detected count shouldn't change */ assert (test_scan_devices (detected, 0)); /* test corner cases with mock device */ assert (test_store_device ()); /* get vendor/product id for all available devices devname */ assert (test_vendor_by_devname ()); /* get vendor/product id for all available devices id */ assert (test_vendor_by_id ()); /* open all available devices */ assert (test_open_all (dn, detected)); opened = get_opened(); /* rescan devices : detected and opened count shouldn't change */ assert (test_scan_devices (detected, opened)); /* try to open an inexisting device */ assert (test_open_invalid ()); /* increase sanei _sub use count */ assert (test_init (2)); /* there should be still as many detected devices */ assert (count_detected (detected)); /* there should be still as many opened devices */ assert (count_opened (opened)); assert (test_exit (1)); /* there should be still as many opened devices */ assert (count_opened (opened)); /* count devices again , sanei_usb_exit() shouldn't have * change the count */ assert (count_detected (detected)); /* claim all available devices */ assert (test_claim_all (dn, opened)); /* then release them all */ assert (test_release_all (dn, opened)); /* close all opened devices */ assert (test_close_all (dn, opened)); /* check there is no opened device */ assert (count_opened (0)); /* finally free resources */ assert (test_exit (0)); /* check there is no more devices */ assert (count_detected (0)); /* test attach matching device with a mock */ assert (test_attach ()); /* try to call sanei_usb_exit() when it not initialized */ assert (test_exit (0)); /* scan devices when sanei usb is not initialized */ assert (test_scan_devices (0, 0)); /* we re start use of sanei usb so we check we have left it * it he correct state after "closing" it. */ printf ("\n============================================================\n"); printf ("restart use of sanei usb after having freed all resources...\n\n"); assert (test_init (1)); /* we should have the same initial count of detected devices */ assert (count_detected (detected)); /* finally free resources */ assert (test_exit (0)); /* all the tests are OK ! */ return 0; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/testsuite/sanei/README0000664000175000017500000000200012775312262015231 00000000000000SANEI test suite ================ This directory contains test programs for sanei functions. They are compiled and run by 'make check'. sanei_usb_test --------------- Tests sanei_usb_* functions. No USB scanner needs to be plugged, but in this case less code is covered (open/close and claim/release of real devices). Function currently tested are: - sanei_usb_init() - sanei_usb_open(): valid, invalid devname, already opened - sanei_usb_get_vendor_product_byname(): valid and invalid devname - sanei_usb_get_vendor_product(): valid and invalid devname - sanei_usb_close() - sanei_usb_exit() - store_device() sanei_constrain_test -------------------- Tests for sanei_constrain_* functions Function currently tested are: - sanei_constrain_value() sanei_check_test ---------------- Tests for sanei_check_* functions Function currently tested are: - sanei_check_value() sanei_config_test ----------------- Tests for sanei_configure_* functions Function currently tested are: - sanei_configure_attach() sane-backends-1.0.27/testsuite/sanei/Makefile.in0000664000175000017500000012011313110564734016421 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = sanei_usb_test$(EXEEXT) test_wire$(EXEEXT) \ sanei_check_test$(EXEEXT) sanei_config_test$(EXEEXT) \ sanei_constrain_test$(EXEEXT) subdir = testsuite/sanei DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am_sanei_check_test_OBJECTS = sanei_check_test.$(OBJEXT) sanei_check_test_OBJECTS = $(am_sanei_check_test_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = ../../sanei/libsanei.la ../../lib/liblib.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) sanei_check_test_DEPENDENCIES = $(am__DEPENDENCIES_2) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_sanei_config_test_OBJECTS = \ sanei_config_test-sanei_config_test.$(OBJEXT) sanei_config_test_OBJECTS = $(am_sanei_config_test_OBJECTS) sanei_config_test_DEPENDENCIES = $(am__DEPENDENCIES_2) am_sanei_constrain_test_OBJECTS = sanei_constrain_test.$(OBJEXT) sanei_constrain_test_OBJECTS = $(am_sanei_constrain_test_OBJECTS) sanei_constrain_test_DEPENDENCIES = $(am__DEPENDENCIES_2) am_sanei_usb_test_OBJECTS = sanei_usb_test.$(OBJEXT) sanei_usb_test_OBJECTS = $(am_sanei_usb_test_OBJECTS) sanei_usb_test_DEPENDENCIES = $(am__DEPENDENCIES_2) am_test_wire_OBJECTS = test_wire.$(OBJEXT) test_wire_OBJECTS = $(am_test_wire_OBJECTS) test_wire_DEPENDENCIES = $(am__DEPENDENCIES_2) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(sanei_check_test_SOURCES) $(sanei_config_test_SOURCES) \ $(sanei_constrain_test_SOURCES) $(sanei_usb_test_SOURCES) \ $(test_wire_SOURCES) DIST_SOURCES = $(sanei_check_test_SOURCES) \ $(sanei_config_test_SOURCES) $(sanei_constrain_test_SOURCES) \ $(sanei_usb_test_SOURCES) $(test_wire_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include $(USB_CFLAGS) AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = data/boolean.conf data/empty.conf data/fixed.conf data/int.conf \ data/snapscan.conf data/string.conf data/string-list.conf \ data/umax_pp.conf data/word-array.conf data/wrong-boolean.conf \ data/wrong-fixed.conf data/wrong-range.conf \ data/wrong-string-list.conf TEST_LDADD = ../../sanei/libsanei.la ../../lib/liblib.la $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) TESTS = $(check_PROGRAMS) sanei_constrain_test_SOURCES = sanei_constrain_test.c sanei_constrain_test_LDADD = $(TEST_LDADD) sanei_config_test_SOURCES = sanei_config_test.c sanei_config_test_CPPFLAGS = $(AM_CPPFLAGS) -DTESTSUITE_SANEI_SRCDIR=$(srcdir) sanei_config_test_LDADD = $(TEST_LDADD) sanei_check_test_SOURCES = sanei_check_test.c sanei_check_test_LDADD = $(TEST_LDADD) sanei_usb_test_SOURCES = sanei_usb_test.c sanei_usb_test_LDADD = $(TEST_LDADD) test_wire_SOURCES = test_wire.c test_wire_LDADD = $(TEST_LDADD) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu testsuite/sanei/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu testsuite/sanei/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list sanei_check_test$(EXEEXT): $(sanei_check_test_OBJECTS) $(sanei_check_test_DEPENDENCIES) $(EXTRA_sanei_check_test_DEPENDENCIES) @rm -f sanei_check_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sanei_check_test_OBJECTS) $(sanei_check_test_LDADD) $(LIBS) sanei_config_test$(EXEEXT): $(sanei_config_test_OBJECTS) $(sanei_config_test_DEPENDENCIES) $(EXTRA_sanei_config_test_DEPENDENCIES) @rm -f sanei_config_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sanei_config_test_OBJECTS) $(sanei_config_test_LDADD) $(LIBS) sanei_constrain_test$(EXEEXT): $(sanei_constrain_test_OBJECTS) $(sanei_constrain_test_DEPENDENCIES) $(EXTRA_sanei_constrain_test_DEPENDENCIES) @rm -f sanei_constrain_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sanei_constrain_test_OBJECTS) $(sanei_constrain_test_LDADD) $(LIBS) sanei_usb_test$(EXEEXT): $(sanei_usb_test_OBJECTS) $(sanei_usb_test_DEPENDENCIES) $(EXTRA_sanei_usb_test_DEPENDENCIES) @rm -f sanei_usb_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sanei_usb_test_OBJECTS) $(sanei_usb_test_LDADD) $(LIBS) test_wire$(EXEEXT): $(test_wire_OBJECTS) $(test_wire_DEPENDENCIES) $(EXTRA_test_wire_DEPENDENCIES) @rm -f test_wire$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_wire_OBJECTS) $(test_wire_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_check_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_config_test-sanei_config_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_constrain_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanei_usb_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_wire.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< sanei_config_test-sanei_config_test.o: sanei_config_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sanei_config_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sanei_config_test-sanei_config_test.o -MD -MP -MF $(DEPDIR)/sanei_config_test-sanei_config_test.Tpo -c -o sanei_config_test-sanei_config_test.o `test -f 'sanei_config_test.c' || echo '$(srcdir)/'`sanei_config_test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sanei_config_test-sanei_config_test.Tpo $(DEPDIR)/sanei_config_test-sanei_config_test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sanei_config_test.c' object='sanei_config_test-sanei_config_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sanei_config_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sanei_config_test-sanei_config_test.o `test -f 'sanei_config_test.c' || echo '$(srcdir)/'`sanei_config_test.c sanei_config_test-sanei_config_test.obj: sanei_config_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sanei_config_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sanei_config_test-sanei_config_test.obj -MD -MP -MF $(DEPDIR)/sanei_config_test-sanei_config_test.Tpo -c -o sanei_config_test-sanei_config_test.obj `if test -f 'sanei_config_test.c'; then $(CYGPATH_W) 'sanei_config_test.c'; else $(CYGPATH_W) '$(srcdir)/sanei_config_test.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sanei_config_test-sanei_config_test.Tpo $(DEPDIR)/sanei_config_test-sanei_config_test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sanei_config_test.c' object='sanei_config_test-sanei_config_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sanei_config_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sanei_config_test-sanei_config_test.obj `if test -f 'sanei_config_test.c'; then $(CYGPATH_W) 'sanei_config_test.c'; else $(CYGPATH_W) '$(srcdir)/sanei_config_test.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? sanei_usb_test.log: sanei_usb_test$(EXEEXT) @p='sanei_usb_test$(EXEEXT)'; \ b='sanei_usb_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_wire.log: test_wire$(EXEEXT) @p='test_wire$(EXEEXT)'; \ b='test_wire'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) sanei_check_test.log: sanei_check_test$(EXEEXT) @p='sanei_check_test$(EXEEXT)'; \ b='sanei_check_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) sanei_config_test.log: sanei_config_test$(EXEEXT) @p='sanei_config_test$(EXEEXT)'; \ b='sanei_config_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) sanei_constrain_test.log: sanei_constrain_test$(EXEEXT) @p='sanei_constrain_test$(EXEEXT)'; \ b='sanei_constrain_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am clean-local: rm -f test_wire.out all: @echo "run 'make check' to run tests" # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/testsuite/sanei/data/0000775000175000017500000000000013110600540015331 500000000000000sane-backends-1.0.27/testsuite/sanei/data/word-array.conf0000664000175000017500000000010112775312262020220 00000000000000option numbers 1000 1100 1200 1300 1400 1500 1600 attach devname sane-backends-1.0.27/testsuite/sanei/data/empty.conf0000664000175000017500000000001712775312262017275 00000000000000attach devname sane-backends-1.0.27/testsuite/sanei/data/int.conf0000664000175000017500000000004712775312262016734 00000000000000option modelnumber 1234 attach devname sane-backends-1.0.27/testsuite/sanei/data/wrong-fixed.conf0000664000175000017500000000005012775312262020365 00000000000000# value out of range option height 59.7 sane-backends-1.0.27/testsuite/sanei/data/wrong-boolean.conf0000664000175000017500000000012012775312262020703 00000000000000# true boolean value option booltrue true # false boolean value boolfalse buggy sane-backends-1.0.27/testsuite/sanei/data/snapscan.conf0000664000175000017500000000427712775312262017761 00000000000000#------------------------------ General ----------------------------------- # Change to the fully qualified filename of your firmware file, if # firmware upload is needed by the scanner firmware /usr/share/sane/snapscan/your-firmwarefile.bin # If not automatically found you may manually specify a device name. # For USB scanners also specify bus=usb, e.g. # /dev/usb/scanner0 bus=usb # For SCSI scanners specify the generic device, e.g. /dev/sg0 on Linux. # /dev/sg0 #--------------------------------------------------------------------------- # No changes should be necessary below this line #--------------------------------------------------------------------------- #-------------------------- SCSI scanners ---------------------------------- # These SCSI devices will be probed automatically scsi AGFA * Scanner scsi COLOR * Scanner scsi Color * Scanner scsi ACERPERI * Scanner #--------------------------- USB scanners ----------------------------------- # These USB devices will be probed automatically # (This will currently work only on Linux) # Benq/Acer/Vuego 310U usb 0x04a5 0x1a20 usb 0x04a5 0x1a26 # Benq/Acer/Vuego 320U usb 0x04a5 0x2022 # Benq/Acer/Vuego 620U / 620UT usb 0x04a5 0x1a2a usb 0x04a5 0x2040 # Benq/Acer/Vuego 640U usb 0x04a5 0x2060 # Benq/Acer/Vuego 640BU usb 0x04a5 0x207e # Benq/Acer/Vuego 640BT usb 0x04a5 0x20be # Benq/Acer/Vuego 1240U usb 0x04a5 0x20c0 # Benq/Acer/Vuego 3300 / 4300 usb 0x04a5 0x20b0 # Benq/Acer/Vuego 4300 usb 0x04a5 0x20de # Benq 5000E / 5000U usb 0x04a5 0x20f8 # Benq 5000 usb 0x04a5 0x20fc # Benq/Acer 5300 usb 0x04a5 0x20fe # Benq 5250C usb 0x04a5 0x2137 # Agfa 1236U usb 0x06bd 0x0002 # Agfa 1212U usb 0x06bd 0x0001 usb 0x06bd 0x2061 # Agfa Snapscan e10 usb 0x06bd 0x2093 # Agfa Snapscan e20 usb 0x06bd 0x2091 # Agfa Snapscan e25 usb 0x06bd 0x2095 # Agfa Snapscan e26 usb 0x06bd 0x2097 # Agfa Snapscan e40 usb 0x06bd 0x208d # Agfa Snapscan e42 usb 0x06bd 0x20ff # Agfa Snapscan e50 usb 0x06bd 0x208f # Agfa Snapscan e52 usb 0x06bd 0x20fd # Epson Perfection 660 usb 0x04b8 0x0114 # Epson Perfection 1670 usb 0x04b8 0x011f # Epson Perfection 2480 usb 0x04b8 0x0121 # Epson Perfection 3490 usb 0x04b8 0x0122 # Epson Stylus CX-1500 usb 0x04b8 0x080c sane-backends-1.0.27/testsuite/sanei/data/string-list.conf0000664000175000017500000000014612775312262020421 00000000000000# one choice from string1, string2, string3 and string4 option string-choice "string3" attach devname sane-backends-1.0.27/testsuite/sanei/data/umax_pp.conf0000664000175000017500000000321512775312262017613 00000000000000# For documentation see sane-umax_pp(5) # GLOBAL # # size (in bytes) of scan buffer (default: 2 megabyte) option buffer 1048576 # DEVICES # # specify the port your scanner is connected to. # # the value 'auto' will make the backend find the correct value # by itself, it will scan ppdev, ppi device, then hardware address # 'safe-auto' will do the same but won't do direct hardware access # on linux systems, you may provide the device name of the ppdev character # device : /dev/parport0, /dev/parport1, ...... # # on *BSD, you may provide the device name of the ppi device: /dev/ppi0, # /dev/ppi1, ... # # Possible hardware addresses are 0x378 (lp0) # 0x278 (lp2) and 0x3c8 (lp1) # port safe-auto # the following options are local to this scanner # gain for red channel, if not given, will be automatically computed # must be between 0 and 15 option red-gain 1 # gain for green channel, if not given, will be automatically computed # must be between 0 and 15 option green-gain 2 # gain for blue channel, if not given, will be automatically computed # must be between 0 and 15 option blue-gain 3 # offset for red channel, if not given, will default to 0 # must be between 0 and 15 option red-offset 4 # offset for green channel, if not given, will default to 0 # must be between 0 and 15 option green-offset 5 # offset for blue channel, if not given, will default to 0 # must be between 0 and 15 option blue-offset 6 # # # model number # # valid values are 610, 1220, 1600 and 2000 # # by default, no model, we rely on autodetection # in case you have black or 'inverted' scans, # you may override detection by providing the # model number option astra 1600 sane-backends-1.0.27/testsuite/sanei/data/string.conf0000664000175000017500000000007612775312262017452 00000000000000option modelname "my model" vendor "my vendor" attach devname sane-backends-1.0.27/testsuite/sanei/data/fixed.conf0000664000175000017500000000020712775312262017237 00000000000000# FIXED type options option height 29.7 some device option array-of-fixed 2.0 2.1 2.2 2.3 2.4 2.5 2.6 another device option width 21.0 sane-backends-1.0.27/testsuite/sanei/data/wrong-string-list.conf0000664000175000017500000000014412775312262021551 00000000000000# one choice from string1, string2, string3 and string4 option string-choice "wrong" attach devname sane-backends-1.0.27/testsuite/sanei/data/wrong-range.conf0000664000175000017500000000004612775312262020367 00000000000000option modelnumber 234 attach devname sane-backends-1.0.27/testsuite/sanei/data/boolean.conf0000664000175000017500000000020212775312262017552 00000000000000# true boolean value option booltrue true # false boolean value boolfalse false # boolean array option boolarray false true false sane-backends-1.0.27/testsuite/sanei/Makefile.am0000664000175000017500000000263512775312262016423 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2013 Stéphane Voltz and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. EXTRA_DIST = data/boolean.conf data/empty.conf data/fixed.conf data/int.conf \ data/snapscan.conf data/string.conf data/string-list.conf \ data/umax_pp.conf data/word-array.conf data/wrong-boolean.conf \ data/wrong-fixed.conf data/wrong-range.conf \ data/wrong-string-list.conf TEST_LDADD = ../../sanei/libsanei.la ../../lib/liblib.la $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) check_PROGRAMS = sanei_usb_test test_wire sanei_check_test sanei_config_test sanei_constrain_test TESTS = $(check_PROGRAMS) AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include $(USB_CFLAGS) sanei_constrain_test_SOURCES = sanei_constrain_test.c sanei_constrain_test_LDADD = $(TEST_LDADD) sanei_config_test_SOURCES = sanei_config_test.c sanei_config_test_CPPFLAGS = $(AM_CPPFLAGS) -DTESTSUITE_SANEI_SRCDIR=$(srcdir) sanei_config_test_LDADD = $(TEST_LDADD) sanei_check_test_SOURCES = sanei_check_test.c sanei_check_test_LDADD = $(TEST_LDADD) sanei_usb_test_SOURCES = sanei_usb_test.c sanei_usb_test_LDADD = $(TEST_LDADD) test_wire_SOURCES = test_wire.c test_wire_LDADD = $(TEST_LDADD) clean-local: rm -f test_wire.out all: @echo "run 'make check' to run tests" sane-backends-1.0.27/testsuite/sanei/sanei_constrain_test.c0000664000175000017500000003726212775312262020755 00000000000000#include "../../include/sane/config.h" #include #include #include #include #include #include #include /* sane includes for the sanei functions called */ #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" static SANE_Option_Descriptor none_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word), 0, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Option_Descriptor none_bool_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), 0, SANE_CONSTRAINT_NONE, {NULL} }; /* range for int constraint */ static const SANE_Range int_range = { 3, /* minimum */ 18, /* maximum */ 3 /* quantization */ }; /* range for sane fixed constraint */ static const SANE_Range fixed_range = { SANE_FIX(1.0), /* minimum */ SANE_FIX(431.8), /* maximum */ SANE_FIX(0.01) /* quantization */ }; static SANE_Option_Descriptor int_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Word), 0, SANE_CONSTRAINT_RANGE, {NULL} }; static SANE_Option_Descriptor fixed_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Word), 0, SANE_CONSTRAINT_RANGE, {NULL} }; #define ARRAY_SIZE 7 static SANE_Option_Descriptor array_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Word) * ARRAY_SIZE, 0, SANE_CONSTRAINT_RANGE, {NULL} }; #define WORD_SIZE 9 static const SANE_Int dpi_list[] = { WORD_SIZE - 1, 100, 200, 300, 400, 500, 600, 700, 800 }; static SANE_Option_Descriptor word_array_opt = { SANE_NAME_SCAN_RESOLUTION, SANE_TITLE_SCAN_RESOLUTION, SANE_DESC_SCAN_RESOLUTION, SANE_TYPE_INT, SANE_UNIT_DPI, sizeof (SANE_Word) * WORD_SIZE, 100, SANE_CONSTRAINT_WORD_LIST, {NULL} }; static const SANE_String_Const string_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, "linelength", 0 }; static SANE_Option_Descriptor string_array_opt = { SANE_NAME_SCAN_MODE, SANE_TITLE_SCAN_MODE, SANE_DESC_SCAN_MODE, SANE_TYPE_STRING, SANE_UNIT_NONE, 8, 0, SANE_CONSTRAINT_STRING_LIST, {NULL} }; /******************************/ /* start of tests definitions */ /******************************/ /* * constrained int */ static void min_int_value (void) { SANE_Int value = int_range.min; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == int_range.min); } static void max_int_value (void) { SANE_Int value = int_range.max; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == int_range.max); } static void below_min_int_value (void) { SANE_Int value = int_range.min - 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == int_range.min); } /* rounded to lower value */ static void quant1_int_value (void) { SANE_Int value = int_range.min + 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == int_range.min); } /* rounded to higher value */ static void quant2_int_value (void) { SANE_Int value = int_range.min + int_range.quant - 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == int_range.min + int_range.quant); } static void in_range_int_value (void) { SANE_Int value = int_range.min + int_range.quant; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == int_range.min + int_range.quant); } static void above_max_int_value (void) { SANE_Int value = int_range.max + 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == int_range.max); } /* * constrained fixed value */ static void min_fixed_value (void) { SANE_Int value = fixed_range.min; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == fixed_range.min); } static void max_fixed_value (void) { SANE_Int value = fixed_range.max; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == fixed_range.max); } static void below_min_fixed_value (void) { SANE_Int value = fixed_range.min - 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == fixed_range.min); } /* rounded to lower value */ static void quant1_fixed_value (void) { SANE_Int value = fixed_range.min + fixed_range.quant/3; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == fixed_range.min); } /* rounded to higher value */ static void quant2_fixed_value (void) { SANE_Int value = fixed_range.min + fixed_range.quant - fixed_range.quant/3; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == fixed_range.min + fixed_range.quant); } static void in_range_fixed_value (void) { SANE_Int value = fixed_range.min + fixed_range.quant; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == fixed_range.min + fixed_range.quant); } static void above_max_fixed_value (void) { SANE_Int value = fixed_range.max + 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == fixed_range.max); } static void above_max_word (void) { SANE_Word value = 25000; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&word_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == 800); } static void below_max_word (void) { SANE_Word value = 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&word_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == 100); } static void closest_200_word (void) { SANE_Word value = 249; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&word_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == 200); } static void closest_300_word (void) { SANE_Word value = 251; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&word_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == 300); } static void exact_400_word (void) { SANE_Word value = 400; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&word_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == 400); } /* * constrained int array */ static void min_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min; } status = sanei_constrain_value (&array_opt, value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.min); } } static void max_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.max; } status = sanei_constrain_value (&array_opt, value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.max); } } static void below_min_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min - 1; } status = sanei_constrain_value (&array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.min); } } /* rounded to lower value */ static void quant1_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min + 1; } status = sanei_constrain_value (&array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.min); } } /* rounded to higher value */ static void quant2_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min + int_range.quant - 1; } status = sanei_constrain_value (&array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.min + int_range.quant); } } static void in_range_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min + int_range.quant; } status = sanei_constrain_value (&array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.min + int_range.quant); } } static void above_max_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.max + 1; } status = sanei_constrain_value (&array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.max); } } static void wrong_string_array (void) { SANE_Char value[9] = "wrong"; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&string_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_INVAL); assert (info == 0); } static void none_int (void) { SANE_Int value = 555; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&none_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); } static void none_bool_nok (void) { SANE_Bool value = 555; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&none_bool_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_INVAL); assert (info == 0); } static void none_bool_ok (void) { SANE_Bool value = SANE_FALSE; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&none_bool_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); } /** * several partial match */ static void string_array_several (void) { SANE_Char value[9] = "Line"; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&string_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_INVAL); assert (info == 0); } /** * unique partial match */ static void partial_string_array (void) { SANE_Char value[9] = "Linea"; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&string_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); } static void string_array_ignorecase (void) { SANE_Char value[9] = "lineart"; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&string_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); } static void string_array_ok (void) { SANE_Char value[9] = "Lineart"; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&string_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); } /** * run the test suite for sanei constrain related tests */ static void sanei_constrain_suite (void) { /* to be compatible with pre-C99 compilers */ int_opt.constraint.range = &int_range; fixed_opt.constraint.range = &fixed_range; array_opt.constraint.range = &int_range; word_array_opt.constraint.word_list = dpi_list; string_array_opt.constraint.string_list = string_list; /* tests for constrained int value */ min_int_value (); max_int_value (); below_min_int_value (); above_max_int_value (); quant1_int_value (); quant2_int_value (); in_range_int_value (); /* tests for sane fixed constrained value */ min_fixed_value (); max_fixed_value (); below_min_fixed_value (); above_max_fixed_value (); quant1_fixed_value (); quant2_fixed_value (); in_range_fixed_value (); /* tests for constrained int array */ min_int_array (); max_int_array (); below_min_int_array (); above_max_int_array (); quant1_int_array (); quant2_int_array (); in_range_int_array (); /* tests for word lists */ above_max_word (); below_max_word (); closest_200_word (); closest_300_word (); exact_400_word (); /* tests for string lists */ wrong_string_array (); partial_string_array (); string_array_ok (); string_array_ignorecase (); string_array_several (); /* constraint none tests */ none_int (); none_bool_nok (); none_bool_ok (); } /** * main function to run the test suites */ int main (void) { /* run suites */ sanei_constrain_suite (); return 0; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/testsuite/Makefile.am0000664000175000017500000000273212775312262015322 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. SUBDIRS = sanei tools SCANIMAGE = ../frontend/scanimage$(EXEEXT) TESTFILE = $(srcdir)/testfile.pnm OUTFILE = outfile.pnm DEVICE = test OPTIONS = --mode Color --depth 16 --test-picture "Color pattern" --resolution 50 -y 20 -x 20 > $(OUTFILE) EXTRA_DIST = README testfile.pnm CLEANFILES = $(OUTFILE) all: help help: @echo "Use 'make test' to run the tests." test: test.local test.local: @echo "**** Testing $(SCANIMAGE) with device $(DEVICE)" @if echo "---> Trying flatbed scanner" && \ $(SCANIMAGE) -d $(DEVICE) -T && \ echo "<--- Flatbed scanner succeded" && \ echo "---> Trying three pass flatbed scanner" && \ $(SCANIMAGE) -d $(DEVICE) --mode Color --three-pass=yes -T && \ echo "<--- Three pass scanner succeded" && \ echo "---> Trying hand scanner" && \ $(SCANIMAGE) -d $(DEVICE) --hand-scanner=yes -T && \ echo "<--- Hand scanner succeded" && \ echo "---> Checking 16 bit color mode" && \ $(SCANIMAGE) -d $(DEVICE) $(OPTIONS) && \ cmp -s $(TESTFILE) $(OUTFILE) && \ echo "<--- 16 bit color mode succeded" && \ rm $(OUTFILE) ; \ then echo ; echo ; echo "**** All tests passed" ; \ else echo ; echo; \ echo "**** Something failed (maybe test backend not enabled by configure?)";\ exit 1; \ fi sane-backends-1.0.27/testsuite/testfile.pnm0000664000175000017500000002171112112021330015571 00000000000000P6 # SANE data follows 39 39 65535 UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU  !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU                           ! " UUUUUUUUUUUUUUUUUUUUUUUU                           ! " UUUUUUUUUUUUUUUUUUUUUUUU                           ! " UUUUUUUUUUUUUUUUUUUUUUUU                           ! " UUUUUUUUUUUUUUUUUUUUUUUU                           ! " UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU      !"UUUUUUUUUUUUUUUUUUUUUUUU                           ! " UUUUUUUUUUUUUUUUUUUUUUUU!!!!!!!!! ! ! ! ! !!!!!!!!!!!!!!!!!!! !!!"!UUUUUUUUUUUUUUUUUUUUUUUU""""""""" " " " " """"""""""""""""""" "!"""sane-backends-1.0.27/frontend/0000775000175000017500000000000013110600532013110 500000000000000sane-backends-1.0.27/frontend/sicc.c0000664000175000017500000000344513106201017014123 00000000000000/* Load an ICC profile for embedding in an output file Copyright (C) 2017 Aaron Muir Hamilton This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "../include/sane/config.h" #include #include #include void * sanei_load_icc_profile (const char *path, size_t *size) { FILE *fd = NULL; size_t stated_size = 0; void *profile = NULL; struct stat s; fd = fopen(path, "r"); if (!fd) { fprintf(stderr, "Could not open ICC profile %s\n", path); } else { fstat(fileno(fd), &s); stated_size = 16777216 * fgetc(fd) + 65536 * fgetc(fd) + 256 * fgetc(fd) + fgetc(fd); rewind(fd); if (stated_size > (size_t) s.st_size) { fprintf(stderr, "Ignoring ICC profile because file %s is shorter than the profile\n", path); } else { profile = malloc(stated_size); if (fread(profile, stated_size, 1, fd) != 1) { fprintf(stderr, "Error reading ICC profile %s\n", path); free(profile); } else { fclose(fd); *size = stated_size; return profile; } } fclose(fd); } return NULL; } sane-backends-1.0.27/frontend/Makefile.in0000664000175000017500000006364013110564734015123 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ EXTRA_PROGRAMS = test$(EXEEXT) tstbackend$(EXEEXT) $(am__EXEEXT_1) bin_PROGRAMS = scanimage$(EXEEXT) @COMPILE_SANED_TRUE@sbin_PROGRAMS = saned$(EXEEXT) @COMPILE_SANED_FALSE@am__append_1 = saned subdir = frontend DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @COMPILE_SANED_FALSE@am__EXEEXT_1 = saned$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) am_saned_OBJECTS = saned.$(OBJEXT) saned_OBJECTS = $(am_saned_OBJECTS) am__DEPENDENCIES_1 = saned_DEPENDENCIES = ../backend/libsane.la ../sanei/libsanei.la \ ../lib/liblib.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_scanimage_OBJECTS = scanimage.$(OBJEXT) sicc.$(OBJEXT) \ stiff.$(OBJEXT) scanimage_OBJECTS = $(am_scanimage_OBJECTS) scanimage_DEPENDENCIES = ../backend/libsane.la ../sanei/libsanei.la \ ../lib/liblib.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_test_OBJECTS = test.$(OBJEXT) test_OBJECTS = $(am_test_OBJECTS) test_DEPENDENCIES = ../lib/liblib.la ../backend/libsane.la am_tstbackend_OBJECTS = tstbackend.$(OBJEXT) tstbackend_OBJECTS = $(am_tstbackend_OBJECTS) tstbackend_DEPENDENCIES = ../lib/liblib.la ../backend/libsane.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(saned_SOURCES) $(scanimage_SOURCES) $(test_SOURCES) \ $(tstbackend_SOURCES) DIST_SOURCES = $(saned_SOURCES) $(scanimage_SOURCES) $(test_SOURCES) \ $(tstbackend_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ scanimage_SOURCES = scanimage.c sicc.c sicc.h stiff.c stiff.h scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ $(PNG_LIBS) $(JPEG_LIBS) saned_SOURCES = saned.c saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ $(SYSLOG_LIBS) $(SYSTEMD_LIBS) $(AVAHI_LIBS) test_SOURCES = test.c test_LDADD = ../lib/liblib.la ../backend/libsane.la tstbackend_SOURCES = tstbackend.c tstbackend_LDADD = ../lib/liblib.la ../backend/libsane.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu frontend/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu frontend/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list saned$(EXEEXT): $(saned_OBJECTS) $(saned_DEPENDENCIES) $(EXTRA_saned_DEPENDENCIES) @rm -f saned$(EXEEXT) $(AM_V_CCLD)$(LINK) $(saned_OBJECTS) $(saned_LDADD) $(LIBS) scanimage$(EXEEXT): $(scanimage_OBJECTS) $(scanimage_DEPENDENCIES) $(EXTRA_scanimage_DEPENDENCIES) @rm -f scanimage$(EXEEXT) $(AM_V_CCLD)$(LINK) $(scanimage_OBJECTS) $(scanimage_LDADD) $(LIBS) test$(EXEEXT): $(test_OBJECTS) $(test_DEPENDENCIES) $(EXTRA_test_DEPENDENCIES) @rm -f test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_OBJECTS) $(test_LDADD) $(LIBS) tstbackend$(EXEEXT): $(tstbackend_OBJECTS) $(tstbackend_DEPENDENCIES) $(EXTRA_tstbackend_DEPENDENCIES) @rm -f tstbackend$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tstbackend_OBJECTS) $(tstbackend_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saned.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scanimage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sicc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stiff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tstbackend.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool clean-local \ clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-sbinPROGRAMS clean-local: rm -f test tstbackend # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/frontend/saned.c0000664000175000017500000024167513064344275014326 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Andreas Beck Copyright (C) 2001 - 2004 Henning Meier-Geinitz Copyright (C) 2003, 2008 Julien BLACHE AF-independent + IPv6 code, standalone mode This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The SANE network daemon. This is the counterpart to the NET backend. */ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include #if defined(HAVE_GETADDRINFO) && defined (HAVE_GETNAMEINFO) # define SANED_USES_AF_INDEP # ifdef HAS_SS_FAMILY # define SS_FAMILY(ss) ss.ss_family # elif defined(HAS___SS_FAMILY) # define SS_FAMILY(ss) ss.__ss_family # else /* fallback to the old, IPv4-only code */ # undef SANED_USES_AF_INDEP # undef ENABLE_IPV6 # endif #else # undef ENABLE_IPV6 #endif /* HAVE_GETADDRINFO && HAVE_GETNAMEINFO */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBC_H # include /* NeXTStep/OpenStep */ #endif #ifdef HAVE_SYS_SELECT_H # include #endif #include #include #include #include #include #include #include #include #include #include #include "lgetopt.h" #if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) # include #else /* * This replacement poll() using select() is only designed to cover * our needs in run_standalone(). It should probably be extended... */ struct pollfd { int fd; short events; short revents; }; #define POLLIN 0x0001 #define POLLERR 0x0002 int poll (struct pollfd *ufds, unsigned int nfds, int timeout); int poll (struct pollfd *ufds, unsigned int nfds, int timeout) { struct pollfd *fdp; fd_set rfds; fd_set efds; struct timeval tv; int maxfd = 0; unsigned int i; int ret; tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000; FD_ZERO (&rfds); FD_ZERO (&efds); for (i = 0, fdp = ufds; i < nfds; i++, fdp++) { fdp->revents = 0; if (fdp->events & POLLIN) FD_SET (fdp->fd, &rfds); FD_SET (fdp->fd, &efds); maxfd = (fdp->fd > maxfd) ? fdp->fd : maxfd; } maxfd++; ret = select (maxfd, &rfds, NULL, &efds, &tv); if (ret < 0) return ret; for (i = 0, fdp = ufds; i < nfds; i++, fdp++) { if (fdp->events & POLLIN) if (FD_ISSET (fdp->fd, &rfds)) fdp->revents |= POLLIN; if (FD_ISSET (fdp->fd, &efds)) fdp->revents |= POLLERR; } return ret; } #endif /* HAVE_SYS_POLL_H && HAVE_POLL */ #ifdef WITH_AVAHI # include # include # include # include # include # include # define SANED_SERVICE_DNS "_sane-port._tcp" # define SANED_NAME "saned" pid_t avahi_pid = -1; char *avahi_svc_name; static AvahiClient *avahi_client = NULL; static AvahiSimplePoll *avahi_poll = NULL; static AvahiEntryGroup *avahi_group = NULL; #endif /* WITH_AVAHI */ #ifdef HAVE_SYSTEMD #include #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_net.h" #include "../include/sane/sanei_codec_bin.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_auth.h" #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef IN_LOOPBACK # define IN_LOOPBACK(addr) (addr == 0x7f000001L) #endif #ifdef ENABLE_IPV6 # ifndef IN6_IS_ADDR_LOOPBACK # define IN6_IS_ADDR_LOOPBACK(a) \ (((const uint32_t *) (a))[0] == 0 \ && ((const uint32_t *) (a))[1] == 0 \ && ((const uint32_t *) (a))[2] == 0 \ && ((const uint32_t *) (a))[3] == htonl (1)) # endif # ifndef IN6_IS_ADDR_V4MAPPED # define IN6_IS_ADDR_V4MAPPED(a) \ ((((const uint32_t *) (a))[0] == 0) \ && (((const uint32_t *) (a))[1] == 0) \ && (((const uint32_t *) (a))[2] == htonl (0xffff))) # endif #endif /* ENABLE_IPV6 */ #ifndef MAXHOSTNAMELEN # define MAXHOSTNAMELEN 120 #endif #ifndef PATH_MAX # define PATH_MAX 1024 #endif struct saned_child { pid_t pid; struct saned_child *next; }; struct saned_child *children; int numchildren; #define SANED_CONFIG_FILE "saned.conf" #define SANED_PID_FILE "/var/run/saned.pid" #define SANED_SERVICE_NAME "sane-port" #define SANED_SERVICE_PORT 6566 #define SANED_SERVICE_PORT_S "6566" typedef struct { u_int inuse:1; /* is this handle in use? */ u_int scanning:1; /* are we scanning? */ u_int docancel:1; /* cancel the current scan */ SANE_Handle handle; /* backends handle */ } Handle; static SANE_Net_Procedure_Number current_request; static const char *prog_name; static int can_authorize; static Wire wire; static int num_handles; static int debug; static int run_mode; static Handle *handle; static char *bind_addr; static union { int w; u_char ch; } byte_order; /* The default-user name. This is not used to imply any rights. All it does is save a remote user some work by reducing the amount of text s/he has to type when authentication is requested. */ static const char *default_username = "saned-user"; static char *remote_ip; /* data port range */ static in_port_t data_port_lo; static in_port_t data_port_hi; #ifdef SANED_USES_AF_INDEP static union { struct sockaddr_storage ss; struct sockaddr sa; struct sockaddr_in sin; #ifdef ENABLE_IPV6 struct sockaddr_in6 sin6; #endif } remote_address; static int remote_address_len; #else static struct in_addr remote_address; #endif /* SANED_USES_AF_INDEP */ #ifndef _PATH_HEQUIV # define _PATH_HEQUIV "/etc/hosts.equiv" #endif static const char *config_file_names[] = { _PATH_HEQUIV, SANED_CONFIG_FILE }; static SANE_Bool log_to_syslog = SANE_TRUE; /* forward declarations: */ static int process_request (Wire * w); #define SANED_RUN_INETD 0 #define SANED_RUN_DEBUG 1 #define SANED_RUN_ALONE 2 #define DBG_ERR 1 #define DBG_WARN 2 #define DBG_MSG 3 #define DBG_INFO 4 #define DBG_DBG 5 #define DBG saned_debug_call static void saned_debug_call (int level, const char *fmt, ...) { #ifndef NDEBUG va_list ap; va_start (ap, fmt); if (debug >= level) { if (log_to_syslog) { /* print to syslog */ vsyslog (LOG_DEBUG, fmt, ap); } else { /* print to stderr */ fprintf (stderr, "[saned] "); vfprintf (stderr, fmt, ap); } } va_end (ap); #endif } static void reset_watchdog (void) { if (!debug) alarm (3600); } static void auth_callback (SANE_String_Const res, SANE_Char *username, SANE_Char *password) { SANE_Net_Procedure_Number procnum; SANE_Authorization_Req req; SANE_Word word, ack = 0; memset (username, 0, SANE_MAX_USERNAME_LEN); memset (password, 0, SANE_MAX_PASSWORD_LEN); if (!can_authorize) { DBG (DBG_WARN, "auth_callback: called during non-authorizable RPC (resource=%s)\n", res); return; } if (wire.status) { DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status); return; } switch (current_request) { case SANE_NET_OPEN: { SANE_Open_Reply reply; memset (&reply, 0, sizeof (reply)); reply.resource_to_authorize = (char *) res; sanei_w_reply (&wire, (WireCodecFunc) sanei_w_open_reply, &reply); } break; case SANE_NET_CONTROL_OPTION: { SANE_Control_Option_Reply reply; memset (&reply, 0, sizeof (reply)); reply.resource_to_authorize = (char *) res; sanei_w_reply (&wire, (WireCodecFunc) sanei_w_control_option_reply, &reply); } break; case SANE_NET_START: { SANE_Start_Reply reply; memset (&reply, 0, sizeof (reply)); reply.resource_to_authorize = (char *) res; sanei_w_reply (&wire, (WireCodecFunc) sanei_w_start_reply, &reply); } break; default: DBG (DBG_WARN, "auth_callback: called for unexpected request %d (resource=%s)\n", current_request, res); break; } if (wire.status) { DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status); return; } reset_watchdog (); sanei_w_set_dir (&wire, WIRE_DECODE); sanei_w_word (&wire, &word); if (wire.status) { DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status); return; } procnum = word; if (procnum != SANE_NET_AUTHORIZE) { DBG (DBG_WARN, "auth_callback: bad procedure number %d " "(expected: %d, resource=%s)\n", procnum, SANE_NET_AUTHORIZE, res); return; } sanei_w_authorization_req (&wire, &req); if (wire.status) { DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status); return; } if (req.username) strcpy (username, req.username); if (req.password) strcpy (password, req.password); if (!req.resource || strcmp (req.resource, res) != 0) { DBG (DBG_MSG, "auth_callback: got auth for resource %s (expected resource=%s)\n", res, req.resource); } sanei_w_free (&wire, (WireCodecFunc) sanei_w_authorization_req, &req); sanei_w_reply (&wire, (WireCodecFunc) sanei_w_word, &ack); } static void quit (int signum) { static int running = 0; int i; if (signum) DBG (DBG_ERR, "quit: received signal %d\n", signum); if (running) { DBG (DBG_ERR, "quit: already active, returning\n"); return; } running = 1; for (i = 0; i < num_handles; ++i) if (handle[i].inuse) sane_close (handle[i].handle); sane_exit (); sanei_w_exit (&wire); if (handle) free (handle); DBG (DBG_WARN, "quit: exiting\n"); if (log_to_syslog) closelog (); exit (EXIT_SUCCESS); /* This is a nowait-daemon. */ } static SANE_Word get_free_handle (void) { # define ALLOC_INCREMENT 16 static int h, last_handle_checked = -1; if (num_handles > 0) { h = last_handle_checked + 1; do { if (h >= num_handles) h = 0; if (!handle[h].inuse) { last_handle_checked = h; memset (handle + h, 0, sizeof (handle[0])); handle[h].inuse = 1; return h; } ++h; } while (h != last_handle_checked); } /* we're out of handles---alloc some more: */ last_handle_checked = num_handles - 1; num_handles += ALLOC_INCREMENT; if (handle) handle = realloc (handle, num_handles * sizeof (handle[0])); else handle = malloc (num_handles * sizeof (handle[0])); if (!handle) return -1; memset (handle + last_handle_checked + 1, 0, ALLOC_INCREMENT * sizeof (handle[0])); return get_free_handle (); # undef ALLOC_INCREMENT } static void close_handle (int h) { if (h >= 0 && handle[h].inuse) { sane_close (handle[h].handle); handle[h].inuse = 0; } } static SANE_Word decode_handle (Wire * w, const char *op) { SANE_Word h; sanei_w_word (w, &h); if (w->status || (unsigned) h >= (unsigned) num_handles || !handle[h].inuse) { DBG (DBG_ERR, "decode_handle: %s: error while decoding handle argument " "(h=%d, %s)\n", op, h, strerror (w->status)); return -1; } return h; } /* Convert a number of bits to an 8-bit bitmask */ static unsigned int cidrtomask[9] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF }; #ifdef SANED_USES_AF_INDEP static SANE_Bool check_v4_in_range (struct sockaddr_in *sin, char *base_ip, char *netmask) { int cidr; int i, err; char *end; uint32_t mask; struct sockaddr_in *base; struct addrinfo hints; struct addrinfo *res; SANE_Bool ret = SANE_FALSE; cidr = -1; cidr = strtol (netmask, &end, 10); /* Sanity check on the cidr value */ if ((cidr < 0) || (cidr > 32) || (end == netmask)) { DBG (DBG_ERR, "check_v4_in_range: invalid CIDR value (%s) !\n", netmask); return SANE_FALSE; } mask = 0; cidr -= 8; /* Build a bitmask out of the CIDR value */ for (i = 3; cidr >= 0; i--) { mask |= (0xff << (8 * i)); cidr -= 8; } if (cidr < 0) mask |= (cidrtomask[cidr + 8] << (8 * i)); mask = htonl (mask); /* get a sockaddr_in representing the base IP address */ memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = PF_INET; err = getaddrinfo (base_ip, NULL, &hints, &res); if (err) { DBG (DBG_DBG, "check_v4_in_range: getaddrinfo() failed: %s\n", gai_strerror (err)); return SANE_FALSE; } base = (struct sockaddr_in *) res->ai_addr; /* * Check that the address belongs to the specified subnet, using the bitmask. * The address is represented by a 32bit integer. */ if ((base->sin_addr.s_addr & mask) == (sin->sin_addr.s_addr & mask)) ret = SANE_TRUE; freeaddrinfo (res); return ret; } # ifdef ENABLE_IPV6 static SANE_Bool check_v6_in_range (struct sockaddr_in6 *sin6, char *base_ip, char *netmask) { int cidr; int i, err; unsigned int mask[16]; char *end; struct sockaddr_in6 *base; struct addrinfo hints; struct addrinfo *res; SANE_Bool ret = SANE_TRUE; cidr = -1; cidr = strtol (netmask, &end, 10); /* Sanity check on the cidr value */ if ((cidr < 0) || (cidr > 128) || (end == netmask)) { DBG (DBG_ERR, "check_v6_in_range: invalid CIDR value (%s) !\n", netmask); return SANE_FALSE; } memset (mask, 0, (16 * sizeof (unsigned int))); cidr -= 8; /* Build a bitmask out of the CIDR value */ for (i = 0; cidr >= 0; i++) { mask[i] = 0xff; cidr -= 8; } if (cidr < 0) mask[i] = cidrtomask[cidr + 8]; /* get a sockaddr_in6 representing the base IP address */ memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = PF_INET6; err = getaddrinfo (base_ip, NULL, &hints, &res); if (err) { DBG (DBG_DBG, "check_v6_in_range: getaddrinfo() failed: %s\n", gai_strerror (err)); return SANE_FALSE; } base = (struct sockaddr_in6 *) res->ai_addr; /* * Check that the address belongs to the specified subnet. * The address is reprensented by an array of 16 8bit integers. */ for (i = 0; i < 16; i++) { if ((base->sin6_addr.s6_addr[i] & mask[i]) != (sin6->sin6_addr.s6_addr[i] & mask[i])) { ret = SANE_FALSE; break; } } freeaddrinfo (res); return ret; } # endif /* ENABLE_IPV6 */ #else /* !SANED_USES_AF_INDEP */ static SANE_Bool check_v4_in_range (struct in_addr *inaddr, struct in_addr *base, char *netmask) { int cidr; int i; char *end; uint32_t mask; SANE_Bool ret = SANE_FALSE; cidr = -1; cidr = strtol (netmask, &end, 10); /* sanity check on the cidr value */ if ((cidr < 0) || (cidr > 32) || (end == netmask)) { DBG (DBG_ERR, "check_v4_in_range: invalid CIDR value (%s) !\n", netmask); return SANE_FALSE; } mask = 0; cidr -= 8; /* Build a bitmask out of the CIDR value */ for (i = 3; cidr >= 0; i--) { mask |= (0xff << (8 * i)); cidr -= 8; } if (cidr < 0) mask |= (cidrtomask[cidr + 8] << (8 * i)); mask = htonl (mask); /* * Check that the address belongs to the specified subnet, using the bitmask. * The address is represented by a 32bit integer. */ if ((base->s_addr & mask) == (inaddr->s_addr & mask)) ret = SANE_TRUE; return ret; } #endif /* SANED_USES_AF_INDEP */ /* Access control */ #ifdef SANED_USES_AF_INDEP static SANE_Status check_host (int fd) { struct sockaddr_in *sin = NULL; #ifdef ENABLE_IPV6 struct sockaddr_in6 *sin6; #endif /* ENABLE_IPV6 */ struct addrinfo hints; struct addrinfo *res; struct addrinfo *resp; int j, access_ok = 0; int err; char text_addr[64]; #ifdef ENABLE_IPV6 SANE_Bool IPv4map = SANE_FALSE; char *remote_ipv4 = NULL; /* in case we have an IPv4-mapped address (eg ::ffff:127.0.0.1) */ char *tmp; struct addrinfo *remote_ipv4_addr = NULL; #endif /* ENABLE_IPV6 */ char config_line_buf[1024]; char *config_line; char *netmask; char hostname[MAXHOSTNAMELEN]; int len; FILE *fp; /* Get address of remote host */ remote_address_len = sizeof (remote_address.ss); if (getpeername (fd, &remote_address.sa, (socklen_t *) &remote_address_len) < 0) { DBG (DBG_ERR, "check_host: getpeername failed: %s\n", strerror (errno)); remote_ip = strdup ("[error]"); return SANE_STATUS_INVAL; } err = getnameinfo (&remote_address.sa, remote_address_len, hostname, sizeof (hostname), NULL, 0, NI_NUMERICHOST); if (err) { DBG (DBG_DBG, "check_host: getnameinfo failed: %s\n", gai_strerror(err)); remote_ip = strdup ("[error]"); return SANE_STATUS_INVAL; } else remote_ip = strdup (hostname); #ifdef ENABLE_IPV6 sin6 = &remote_address.sin6; if (IN6_IS_ADDR_V4MAPPED ((struct in6_addr *)sin6->sin6_addr.s6_addr)) { DBG (DBG_DBG, "check_host: detected an IPv4-mapped address\n"); remote_ipv4 = remote_ip + 7; IPv4map = SANE_TRUE; memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = PF_INET; err = getaddrinfo (remote_ipv4, NULL, &hints, &res); if (err) { DBG (DBG_DBG, "check_host: getaddrinfo() failed: %s\n", gai_strerror (err)); IPv4map = SANE_FALSE; /* we failed, remote_ipv4_addr points to nothing */ } else { remote_ipv4_addr = res; sin = (struct sockaddr_in *)res->ai_addr; } } #endif /* ENABLE_IPV6 */ DBG (DBG_WARN, "check_host: access by remote host: %s\n", remote_ip); /* Always allow access from local host. Do it here to avoid DNS lookups and reading saned.conf. */ #ifdef ENABLE_IPV6 if (IPv4map == SANE_TRUE) { if (IN_LOOPBACK (ntohl (sin->sin_addr.s_addr))) { DBG (DBG_MSG, "check_host: remote host is IN_LOOPBACK: access granted\n"); freeaddrinfo (remote_ipv4_addr); return SANE_STATUS_GOOD; } freeaddrinfo (remote_ipv4_addr); } #endif /* ENABLE_IPV6 */ sin = &remote_address.sin; switch (SS_FAMILY(remote_address.ss)) { case AF_INET: if (IN_LOOPBACK (ntohl (sin->sin_addr.s_addr))) { DBG (DBG_MSG, "check_host: remote host is IN_LOOPBACK: access granted\n"); return SANE_STATUS_GOOD; } break; #ifdef ENABLE_IPV6 case AF_INET6: if (IN6_IS_ADDR_LOOPBACK ((struct in6_addr *)sin6->sin6_addr.s6_addr)) { DBG (DBG_MSG, "check_host: remote host is IN6_LOOPBACK: access granted\n"); return SANE_STATUS_GOOD; } break; #endif /* ENABLE_IPV6 */ default: break; } DBG (DBG_DBG, "check_host: remote host is not IN_LOOPBACK" #ifdef ENABLE_IPV6 " nor IN6_LOOPBACK" #endif /* ENABLE_IPV6 */ "\n"); /* Get name of local host */ if (gethostname (hostname, sizeof (hostname)) < 0) { DBG (DBG_ERR, "check_host: gethostname failed: %s\n", strerror (errno)); return SANE_STATUS_INVAL; } DBG (DBG_DBG, "check_host: local hostname: %s\n", hostname); /* Get local addresses */ memset (&hints, 0, sizeof (hints)); hints.ai_flags = AI_CANONNAME; #ifdef ENABLE_IPV6 hints.ai_family = PF_UNSPEC; #else hints.ai_family = PF_INET; #endif /* ENABLE_IPV6 */ err = getaddrinfo (hostname, NULL, &hints, &res); if (err) { DBG (DBG_ERR, "check_host: getaddrinfo for local hostname failed: %s\n", gai_strerror (err)); /* Proceed even if the local hostname does not resolve */ if (err != EAI_NONAME) return SANE_STATUS_INVAL; } else { for (resp = res; resp != NULL; resp = resp->ai_next) { DBG (DBG_DBG, "check_host: local hostname(s) (from DNS): %s\n", resp->ai_canonname); err = getnameinfo (resp->ai_addr, resp->ai_addrlen, text_addr, sizeof (text_addr), NULL, 0, NI_NUMERICHOST); if (err) strncpy (text_addr, "[error]", 8); #ifdef ENABLE_IPV6 if ((strcasecmp (text_addr, remote_ip) == 0) || ((IPv4map == SANE_TRUE) && (strcmp (text_addr, remote_ipv4) == 0))) #else if (strcmp (text_addr, remote_ip) == 0) #endif /* ENABLE_IPV6 */ { DBG (DBG_MSG, "check_host: remote host has same addr as local: access granted\n"); freeaddrinfo (res); res = NULL; return SANE_STATUS_GOOD; } } freeaddrinfo (res); res = NULL; DBG (DBG_DBG, "check_host: remote host doesn't have same addr as local\n"); } /* must be a remote host: check contents of PATH_NET_CONFIG or /etc/hosts.equiv if former doesn't exist: */ for (j = 0; j < NELEMS (config_file_names); ++j) { DBG (DBG_DBG, "check_host: opening config file: %s\n", config_file_names[j]); if (config_file_names[j][0] == '/') fp = fopen (config_file_names[j], "r"); else fp = sanei_config_open (config_file_names[j]); if (!fp) { DBG (DBG_MSG, "check_host: can't open config file: %s (%s)\n", config_file_names[j], strerror (errno)); continue; } while (!access_ok && sanei_config_read (config_line_buf, sizeof (config_line_buf), fp)) { config_line = config_line_buf; /* from now on, use a pointer */ DBG (DBG_DBG, "check_host: config file line: `%s'\n", config_line); if (config_line[0] == '#') continue; /* ignore comments */ if (strchr (config_line, '=')) continue; /* ignore lines with an = sign */ len = strlen (config_line); if (!len) continue; /* ignore empty lines */ /* look for a subnet specification */ netmask = strchr (config_line, '/'); if (netmask != NULL) { *netmask = '\0'; netmask++; DBG (DBG_DBG, "check_host: subnet with base IP = %s, CIDR netmask = %s\n", config_line, netmask); } #ifdef ENABLE_IPV6 /* IPv6 addresses are enclosed in [] */ if (*config_line == '[') { config_line++; tmp = strchr (config_line, ']'); if (tmp == NULL) { DBG (DBG_ERR, "check_host: malformed IPv6 address in config file, skipping: [%s\n", config_line); continue; } *tmp = '\0'; } #endif /* ENABLE_IPV6 */ if (strcmp (config_line, "+") == 0) { access_ok = 1; DBG (DBG_DBG, "check_host: access granted from any host (`+')\n"); } /* compare remote_ip (remote IP address) to the config_line */ else if (strcasecmp (config_line, remote_ip) == 0) { access_ok = 1; DBG (DBG_DBG, "check_host: access granted from IP address %s\n", remote_ip); } #ifdef ENABLE_IPV6 else if ((IPv4map == SANE_TRUE) && (strcmp (config_line, remote_ipv4) == 0)) { access_ok = 1; DBG (DBG_DBG, "check_host: access granted from IP address %s (IPv4-mapped)\n", remote_ip); } /* handle IP ranges, take care of the IPv4map stuff */ else if (netmask != NULL) { if (strchr (config_line, ':') != NULL) /* is a v6 address */ { if (SS_FAMILY(remote_address.ss) == AF_INET6) { if (check_v6_in_range (sin6, config_line, netmask)) { access_ok = 1; DBG (DBG_DBG, "check_host: access granted from IP address %s (in subnet [%s]/%s)\n", remote_ip, config_line, netmask); } } } else /* is a v4 address */ { if (IPv4map == SANE_TRUE) { /* get a sockaddr_in representing the v4-mapped IP address */ memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = PF_INET; err = getaddrinfo (remote_ipv4, NULL, &hints, &res); if (err) DBG (DBG_DBG, "check_host: getaddrinfo() failed: %s\n", gai_strerror (err)); else sin = (struct sockaddr_in *)res->ai_addr; } if ((SS_FAMILY(remote_address.ss) == AF_INET) || (IPv4map == SANE_TRUE)) { if (check_v4_in_range (sin, config_line, netmask)) { DBG (DBG_DBG, "check_host: access granted from IP address %s (in subnet %s/%s)\n", ((IPv4map == SANE_TRUE) ? remote_ipv4 : remote_ip), config_line, netmask); access_ok = 1; } else { /* restore the old sin pointer */ sin = &remote_address.sin; } if (res != NULL) { freeaddrinfo (res); res = NULL; } } } } #else /* !ENABLE_IPV6 */ /* handle IP ranges */ else if (netmask != NULL) { if (check_v4_in_range (sin, config_line, netmask)) { access_ok = 1; DBG (DBG_DBG, "check_host: access granted from IP address %s (in subnet %s/%s)\n", remote_ip, config_line, netmask); } } #endif /* ENABLE_IPV6 */ else { memset (&hints, 0, sizeof (hints)); hints.ai_flags = AI_CANONNAME; #ifdef ENABLE_IPV6 hints.ai_family = PF_UNSPEC; #else hints.ai_family = PF_INET; #endif /* ENABLE_IPV6 */ err = getaddrinfo (config_line, NULL, &hints, &res); if (err) { DBG (DBG_DBG, "check_host: getaddrinfo for `%s' failed: %s\n", config_line, gai_strerror (err)); DBG (DBG_MSG, "check_host: entry isn't an IP address " "and can't be found in DNS\n"); continue; } else { for (resp = res; resp != NULL; resp = resp->ai_next) { err = getnameinfo (resp->ai_addr, resp->ai_addrlen, text_addr, sizeof (text_addr), NULL, 0, NI_NUMERICHOST); if (err) strncpy (text_addr, "[error]", 8); DBG (DBG_MSG, "check_host: DNS lookup returns IP address: %s\n", text_addr); #ifdef ENABLE_IPV6 if ((strcasecmp (text_addr, remote_ip) == 0) || ((IPv4map == SANE_TRUE) && (strcmp (text_addr, remote_ipv4) == 0))) #else if (strcmp (text_addr, remote_ip) == 0) #endif /* ENABLE_IPV6 */ access_ok = 1; if (access_ok) break; } freeaddrinfo (res); res = NULL; } } } fclose (fp); } if (access_ok) return SANE_STATUS_GOOD; return SANE_STATUS_ACCESS_DENIED; } #else /* !SANED_USES_AF_INDEP */ static SANE_Status check_host (int fd) { struct sockaddr_in sin; int j, access_ok = 0; struct hostent *he; char text_addr[64]; char config_line_buf[1024]; char *config_line; char *netmask; char hostname[MAXHOSTNAMELEN]; char *r_hostname; static struct in_addr config_line_address; int len; FILE *fp; /* Get address of remote host */ len = sizeof (sin); if (getpeername (fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0) { DBG (DBG_ERR, "check_host: getpeername failed: %s\n", strerror (errno)); remote_ip = strdup ("[error]"); return SANE_STATUS_INVAL; } r_hostname = inet_ntoa (sin.sin_addr); remote_ip = strdup (r_hostname); DBG (DBG_WARN, "check_host: access by remote host: %s\n", remote_ip); /* Save remote address for check of control and data connections */ memcpy (&remote_address, &sin.sin_addr, sizeof (remote_address)); /* Always allow access from local host. Do it here to avoid DNS lookups and reading saned.conf. */ if (IN_LOOPBACK (ntohl (sin.sin_addr.s_addr))) { DBG (DBG_MSG, "check_host: remote host is IN_LOOPBACK: access accepted\n"); return SANE_STATUS_GOOD; } DBG (DBG_DBG, "check_host: remote host is not IN_LOOPBACK\n"); /* Get name of local host */ if (gethostname (hostname, sizeof (hostname)) < 0) { DBG (DBG_ERR, "check_host: gethostname failed: %s\n", strerror (errno)); return SANE_STATUS_INVAL; } DBG (DBG_DBG, "check_host: local hostname: %s\n", hostname); /* Get local address */ he = gethostbyname (hostname); if (!he) { DBG (DBG_ERR, "check_host: gethostbyname for local hostname failed: %s\n", hstrerror (h_errno)); /* Proceed even if the local hostname doesn't resolve */ if (h_errno != HOST_NOT_FOUND) return SANE_STATUS_INVAL; } else { DBG (DBG_DBG, "check_host: local hostname (from DNS): %s\n", he->h_name); if ((he->h_length == 4) || (he->h_addrtype == AF_INET)) { if (!inet_ntop (he->h_addrtype, he->h_addr_list[0], text_addr, sizeof (text_addr))) strcpy (text_addr, "[error]"); DBG (DBG_DBG, "check_host: local host address (from DNS): %s\n", text_addr); if (memcmp (he->h_addr_list[0], &remote_address.s_addr, 4) == 0) { DBG (DBG_MSG, "check_host: remote host has same addr as local: " "access accepted\n"); return SANE_STATUS_GOOD; } } else { DBG (DBG_ERR, "check_host: can't get local address " "(only IPv4 is supported)\n"); } DBG (DBG_DBG, "check_host: remote host doesn't have same addr as local\n"); } /* must be a remote host: check contents of PATH_NET_CONFIG or /etc/hosts.equiv if former doesn't exist: */ for (j = 0; j < NELEMS (config_file_names); ++j) { DBG (DBG_DBG, "check_host: opening config file: %s\n", config_file_names[j]); if (config_file_names[j][0] == '/') fp = fopen (config_file_names[j], "r"); else fp = sanei_config_open (config_file_names[j]); if (!fp) { DBG (DBG_MSG, "check_host: can't open config file: %s (%s)\n", config_file_names[j], strerror (errno)); continue; } while (!access_ok && sanei_config_read (config_line_buf, sizeof (config_line_buf), fp)) { config_line = config_line_buf; /* from now on, use a pointer */ DBG (DBG_DBG, "check_host: config file line: `%s'\n", config_line); if (config_line[0] == '#') continue; /* ignore comments */ if (strchr (config_line, '=')) continue; /* ignore lines with an = sign */ len = strlen (config_line); if (!len) continue; /* ignore empty lines */ /* look for a subnet specification */ netmask = strchr (config_line, '/'); if (netmask != NULL) { *netmask = '\0'; netmask++; DBG (DBG_DBG, "check_host: subnet with base IP = %s, CIDR netmask = %s\n", config_line, netmask); } if (strcmp (config_line, "+") == 0) { access_ok = 1; DBG (DBG_DBG, "check_host: access accepted from any host (`+')\n"); } else { if (inet_pton (AF_INET, config_line, &config_line_address) > 0) { if (memcmp (&remote_address.s_addr, &config_line_address.s_addr, 4) == 0) access_ok = 1; else if (netmask != NULL) { if (check_v4_in_range (&remote_address, &config_line_address, netmask)) { access_ok = 1; DBG (DBG_DBG, "check_host: access granted from IP address %s (in subnet %s/%s)\n", remote_ip, config_line, netmask); } } } else { DBG (DBG_DBG, "check_host: inet_pton for `%s' failed\n", config_line); he = gethostbyname (config_line); if (!he) { DBG (DBG_DBG, "check_host: gethostbyname for `%s' failed: %s\n", config_line, hstrerror (h_errno)); DBG (DBG_MSG, "check_host: entry isn't an IP address " "and can't be found in DNS\n"); continue; } if (!inet_ntop (he->h_addrtype, he->h_addr_list[0], text_addr, sizeof (text_addr))) strcpy (text_addr, "[error]"); DBG (DBG_MSG, "check_host: DNS lookup returns IP address: %s\n", text_addr); if (memcmp (&remote_address.s_addr, he->h_addr_list[0], 4) == 0) access_ok = 1; } } } fclose (fp); if (access_ok) return SANE_STATUS_GOOD; } return SANE_STATUS_ACCESS_DENIED; } #endif /* SANED_USES_AF_INDEP */ static int init (Wire * w) { SANE_Word word, be_version_code; SANE_Init_Reply reply; SANE_Status status; SANE_Init_Req req; reset_watchdog (); status = check_host (w->io.fd); if (status != SANE_STATUS_GOOD) { DBG (DBG_WARN, "init: access by host %s denied\n", remote_ip); return -1; } else DBG (DBG_MSG, "init: access granted\n"); sanei_w_set_dir (w, WIRE_DECODE); if (w->status) { DBG (DBG_ERR, "init: bad status after sanei_w_set_dir: %d\n", w->status); return -1; } sanei_w_word (w, &word); /* decode procedure number */ if (w->status || word != SANE_NET_INIT) { DBG (DBG_ERR, "init: bad status=%d or procnum=%d\n", w->status, word); return -1; } sanei_w_init_req (w, &req); if (w->status) { DBG (DBG_ERR, "init: bad status after sanei_w_init_req: %d\n", w->status); return -1; } w->version = SANEI_NET_PROTOCOL_VERSION; if (req.username) default_username = strdup (req.username); sanei_w_free (w, (WireCodecFunc) sanei_w_init_req, &req); if (w->status) { DBG (DBG_ERR, "init: bad status after sanei_w_free: %d\n", w->status); return -1; } reply.version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, SANEI_NET_PROTOCOL_VERSION); DBG (DBG_WARN, "init: access granted to %s@%s\n", default_username, remote_ip); if (status == SANE_STATUS_GOOD) { status = sane_init (&be_version_code, auth_callback); if (status != SANE_STATUS_GOOD) DBG (DBG_ERR, "init: failed to initialize backend (%s)\n", sane_strstatus (status)); if (SANE_VERSION_MAJOR (be_version_code) != V_MAJOR) { DBG (DBG_ERR, "init: unexpected backend major version %d (expected %d)\n", SANE_VERSION_MAJOR (be_version_code), V_MAJOR); status = SANE_STATUS_INVAL; } } reply.status = status; if (status != SANE_STATUS_GOOD) reply.version_code = 0; sanei_w_reply (w, (WireCodecFunc) sanei_w_init_reply, &reply); if (w->status || status != SANE_STATUS_GOOD) return -1; return 0; } #ifdef SANED_USES_AF_INDEP static int start_scan (Wire * w, int h, SANE_Start_Reply * reply) { union { struct sockaddr_storage ss; struct sockaddr sa; struct sockaddr_in sin; #ifdef ENABLE_IPV6 struct sockaddr_in6 sin6; #endif /* ENABLE_IPV6 */ } data_addr; struct sockaddr_in *sin; #ifdef ENABLE_IPV6 struct sockaddr_in6 *sin6; #endif /* ENABLE_IPV6 */ SANE_Handle be_handle; int fd, len; in_port_t data_port; int ret = -1; be_handle = handle[h].handle; len = sizeof (data_addr.ss); if (getsockname (w->io.fd, &data_addr.sa, (socklen_t *) &len) < 0) { DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } fd = socket (SS_FAMILY(data_addr.ss), SOCK_STREAM, 0); if (fd < 0) { DBG (DBG_ERR, "start_scan: failed to obtain data socket (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } switch (SS_FAMILY(data_addr.ss)) { case AF_INET: sin = &data_addr.sin; break; #ifdef ENABLE_IPV6 case AF_INET6: sin6 = &data_addr.sin6; break; #endif /* ENABLE_IPV6 */ default: break; } /* Try to bind a port between data_port_lo and data_port_hi for the data connection */ for (data_port = data_port_lo; data_port <= data_port_hi; data_port++) { switch (SS_FAMILY(data_addr.ss)) { case AF_INET: sin->sin_port = htons(data_port); break; #ifdef ENABLE_IPV6 case AF_INET6: sin6->sin6_port = htons(data_port); break; #endif /* ENABLE_IPV6 */ default: break; } DBG (DBG_INFO, "start_scan: trying to bind data port %d\n", data_port); ret = bind (fd, &data_addr.sa, len); if (ret == 0) break; } if (ret < 0) { DBG (DBG_ERR, "start_scan: failed to bind address (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } if (listen (fd, 1) < 0) { DBG (DBG_ERR, "start_scan: failed to make socket listen (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } if (getsockname (fd, &data_addr.sa, (socklen_t *) &len) < 0) { DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } switch (SS_FAMILY(data_addr.ss)) { case AF_INET: sin = &data_addr.sin; reply->port = ntohs (sin->sin_port); break; #ifdef ENABLE_IPV6 case AF_INET6: sin6 = &data_addr.sin6; reply->port = ntohs (sin6->sin6_port); break; #endif /* ENABLE_IPV6 */ default: break; } DBG (DBG_MSG, "start_scan: using port %d for data\n", reply->port); reply->status = sane_start (be_handle); if (reply->status == SANE_STATUS_GOOD) { handle[h].scanning = 1; handle[h].docancel = 0; } return fd; } #else /* !SANED_USES_AF_INDEP */ static int start_scan (Wire * w, int h, SANE_Start_Reply * reply) { struct sockaddr_in sin; SANE_Handle be_handle; int fd, len; in_port_t data_port; int ret; be_handle = handle[h].handle; len = sizeof (sin); if (getsockname (w->io.fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0) { DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } fd = socket (AF_INET, SOCK_STREAM, 0); if (fd < 0) { DBG (DBG_ERR, "start_scan: failed to obtain data socket (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } /* Try to bind a port between data_port_lo and data_port_hi for the data connection */ for (data_port = data_port_lo; data_port <= data_port_hi; data_port++) { sin.sin_port = htons(data_port); DBG(DBG_INFO, "start_scan: trying to bind data port %d\n", data_port); ret = bind (fd, (struct sockaddr *) &sin, len); if (ret == 0) break; } if (ret < 0) { DBG (DBG_ERR, "start_scan: failed to bind address (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } if (listen (fd, 1) < 0) { DBG (DBG_ERR, "start_scan: failed to make socket listen (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } if (getsockname (fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0) { DBG (DBG_ERR, "start_scan: failed to obtain socket address (%s)\n", strerror (errno)); reply->status = SANE_STATUS_IO_ERROR; return -1; } reply->port = ntohs (sin.sin_port); DBG (DBG_MSG, "start_scan: using port %d for data\n", reply->port); reply->status = sane_start (be_handle); if (reply->status == SANE_STATUS_GOOD) { handle[h].scanning = 1; handle[h].docancel = 0; } return fd; } #endif /* SANED_USES_AF_INDEP */ static int store_reclen (SANE_Byte * buf, size_t buf_size, int i, size_t reclen) { buf[i++] = (reclen >> 24) & 0xff; if (i >= (int) buf_size) i = 0; buf[i++] = (reclen >> 16) & 0xff; if (i >= (int) buf_size) i = 0; buf[i++] = (reclen >> 8) & 0xff; if (i >= (int) buf_size) i = 0; buf[i++] = (reclen >> 0) & 0xff; if (i >= (int) buf_size) i = 0; return i; } static void do_scan (Wire * w, int h, int data_fd) { int num_fds, be_fd = -1, reader, writer, bytes_in_buf, status_dirty = 0; SANE_Handle be_handle = handle[h].handle; struct timeval tv, *timeout = 0; fd_set rd_set, rd_mask, wr_set, wr_mask; SANE_Byte buf[8192]; SANE_Status status; long int nwritten; SANE_Int length; size_t nbytes; DBG (3, "do_scan: start\n"); FD_ZERO (&rd_mask); FD_SET (w->io.fd, &rd_mask); num_fds = w->io.fd + 1; FD_ZERO (&wr_mask); FD_SET (data_fd, &wr_mask); if (data_fd >= num_fds) num_fds = data_fd + 1; sane_set_io_mode (be_handle, SANE_TRUE); if (sane_get_select_fd (be_handle, &be_fd) == SANE_STATUS_GOOD) { FD_SET (be_fd, &rd_mask); if (be_fd >= num_fds) num_fds = be_fd + 1; } else { memset (&tv, 0, sizeof (tv)); timeout = &tv; } status = SANE_STATUS_GOOD; reader = writer = bytes_in_buf = 0; do { rd_set = rd_mask; wr_set = wr_mask; if (select (num_fds, &rd_set, &wr_set, 0, timeout) < 0) { if (be_fd >= 0 && errno == EBADF) { /* This normally happens when a backend closes a select filedescriptor when reaching the end of file. So pass back this status to the client: */ FD_CLR (be_fd, &rd_mask); be_fd = -1; /* only set status_dirty if EOF hasn't been already detected */ if (status == SANE_STATUS_GOOD) status_dirty = 1; status = SANE_STATUS_EOF; DBG (DBG_INFO, "do_scan: select_fd was closed --> EOF\n"); continue; } else { status = SANE_STATUS_IO_ERROR; DBG (DBG_ERR, "do_scan: select failed (%s)\n", strerror (errno)); break; } } if (bytes_in_buf) { if (FD_ISSET (data_fd, &wr_set)) { if (bytes_in_buf > 0) { /* write more input data */ nbytes = bytes_in_buf; if (writer + nbytes > sizeof (buf)) nbytes = sizeof (buf) - writer; DBG (DBG_INFO, "do_scan: trying to write %d bytes to client\n", nbytes); nwritten = write (data_fd, buf + writer, nbytes); DBG (DBG_INFO, "do_scan: wrote %ld bytes to client\n", nwritten); if (nwritten < 0) { DBG (DBG_ERR, "do_scan: write failed (%s)\n", strerror (errno)); status = SANE_STATUS_CANCELLED; break; } bytes_in_buf -= nwritten; writer += nwritten; if (writer == sizeof (buf)) writer = 0; } } } else if (status == SANE_STATUS_GOOD && (timeout || FD_ISSET (be_fd, &rd_set))) { int i; /* get more input data */ /* reserve 4 bytes to store the length of the data record: */ i = reader; reader += 4; if (reader >= (int) sizeof (buf)) reader -= sizeof(buf); assert (bytes_in_buf == 0); nbytes = sizeof (buf) - 4; if (reader + nbytes > sizeof (buf)) nbytes = sizeof (buf) - reader; DBG (DBG_INFO, "do_scan: trying to read %d bytes from scanner\n", nbytes); status = sane_read (be_handle, buf + reader, nbytes, &length); DBG (DBG_INFO, "do_scan: read %d bytes from scanner\n", length); reset_watchdog (); reader += length; if (reader >= (int) sizeof (buf)) reader = 0; bytes_in_buf += length + 4; if (status != SANE_STATUS_GOOD) { reader = i; /* restore reader index */ status_dirty = 1; DBG (DBG_MSG, "do_scan: status = `%s'\n", sane_strstatus(status)); } else store_reclen (buf, sizeof (buf), i, length); } if (status_dirty && sizeof (buf) - bytes_in_buf >= 5) { status_dirty = 0; reader = store_reclen (buf, sizeof (buf), reader, 0xffffffff); buf[reader] = status; bytes_in_buf += 5; DBG (DBG_MSG, "do_scan: statuscode `%s' was added to buffer\n", sane_strstatus(status)); } if (FD_ISSET (w->io.fd, &rd_set)) { DBG (DBG_MSG, "do_scan: processing RPC request on fd %d\n", w->io.fd); process_request (w); if (handle[h].docancel) break; } } while (status == SANE_STATUS_GOOD || bytes_in_buf > 0 || status_dirty); DBG (DBG_MSG, "do_scan: done, status=%s\n", sane_strstatus (status)); handle[h].docancel = 0; handle[h].scanning = 0; } static int process_request (Wire * w) { SANE_Handle be_handle; SANE_Word h, word; int i; DBG (DBG_DBG, "process_request: waiting for request\n"); sanei_w_set_dir (w, WIRE_DECODE); sanei_w_word (w, &word); /* decode procedure number */ if (w->status) { DBG (DBG_ERR, "process_request: bad status %d\n", w->status); return -1; } current_request = word; DBG (DBG_MSG, "process_request: got request %d\n", current_request); switch (current_request) { case SANE_NET_GET_DEVICES: { SANE_Get_Devices_Reply reply; reply.status = sane_get_devices ((const SANE_Device ***) &reply.device_list, SANE_TRUE); sanei_w_reply (w, (WireCodecFunc) sanei_w_get_devices_reply, &reply); } break; case SANE_NET_OPEN: { SANE_Open_Reply reply; SANE_Handle be_handle; SANE_String name, resource; sanei_w_string (w, &name); if (w->status) { DBG (DBG_ERR, "process_request: (open) error while decoding args (%s)\n", strerror (w->status)); return 1; } if (!name) { DBG (DBG_ERR, "process_request: (open) device_name == NULL\n"); reply.status = SANE_STATUS_INVAL; sanei_w_reply (w, (WireCodecFunc) sanei_w_open_reply, &reply); return 1; } can_authorize = 1; resource = strdup (name); if (strlen(resource) == 0) { const SANE_Device **device_list; DBG(DBG_DBG, "process_request: (open) strlen(resource) == 0\n"); free (resource); if ((i = sane_get_devices (&device_list, SANE_TRUE)) != SANE_STATUS_GOOD) { DBG(DBG_ERR, "process_request: (open) sane_get_devices failed\n"); memset (&reply, 0, sizeof (reply)); reply.status = i; sanei_w_reply (w, (WireCodecFunc) sanei_w_open_reply, &reply); break; } if ((device_list == NULL) || (device_list[0] == NULL)) { DBG(DBG_ERR, "process_request: (open) device_list[0] == 0\n"); memset (&reply, 0, sizeof (reply)); reply.status = SANE_STATUS_INVAL; sanei_w_reply (w, (WireCodecFunc) sanei_w_open_reply, &reply); break; } resource = strdup (device_list[0]->name); } if (strchr (resource, ':')) *(strchr (resource, ':')) = 0; if (sanei_authorize (resource, "saned", auth_callback) != SANE_STATUS_GOOD) { DBG (DBG_ERR, "process_request: access to resource `%s' denied\n", resource); free (resource); memset (&reply, 0, sizeof (reply)); /* avoid leaking bits */ reply.status = SANE_STATUS_ACCESS_DENIED; } else { DBG (DBG_MSG, "process_request: access to resource `%s' granted\n", resource); free (resource); memset (&reply, 0, sizeof (reply)); /* avoid leaking bits */ reply.status = sane_open (name, &be_handle); DBG (DBG_MSG, "process_request: sane_open returned: %s\n", sane_strstatus (reply.status)); } if (reply.status == SANE_STATUS_GOOD) { h = get_free_handle (); if (h < 0) reply.status = SANE_STATUS_NO_MEM; else { handle[h].handle = be_handle; reply.handle = h; } } can_authorize = 0; sanei_w_reply (w, (WireCodecFunc) sanei_w_open_reply, &reply); sanei_w_free (w, (WireCodecFunc) sanei_w_string, &name); } break; case SANE_NET_CLOSE: { SANE_Word ack = 0; h = decode_handle (w, "close"); close_handle (h); sanei_w_reply (w, (WireCodecFunc) sanei_w_word, &ack); } break; case SANE_NET_GET_OPTION_DESCRIPTORS: { SANE_Option_Descriptor_Array opt; h = decode_handle (w, "get_option_descriptors"); if (h < 0) return 1; be_handle = handle[h].handle; sane_control_option (be_handle, 0, SANE_ACTION_GET_VALUE, &opt.num_options, 0); opt.desc = malloc (opt.num_options * sizeof (opt.desc[0])); for (i = 0; i < opt.num_options; ++i) opt.desc[i] = (SANE_Option_Descriptor *) sane_get_option_descriptor (be_handle, i); sanei_w_reply (w,(WireCodecFunc) sanei_w_option_descriptor_array, &opt); free (opt.desc); } break; case SANE_NET_CONTROL_OPTION: { SANE_Control_Option_Req req; SANE_Control_Option_Reply reply; sanei_w_control_option_req (w, &req); if (w->status || (unsigned) req.handle >= (unsigned) num_handles || !handle[req.handle].inuse) { DBG (DBG_ERR, "process_request: (control_option) " "error while decoding args h=%d (%s)\n" , req.handle, strerror (w->status)); return 1; } /* Addresses CVE-2017-6318 (#315576, Debian BTS #853804) */ /* This is done here (rather than in sanei/sanei_wire.c where * it should be done) to minimize scope of impact and amount * of code change. */ if (w->direction == WIRE_DECODE && req.value_type == SANE_TYPE_STRING && req.action == SANE_ACTION_GET_VALUE) { if (req.value) { /* FIXME: If req.value contains embedded NUL * characters, this is wrong but we do not have * access to the amount of memory allocated in * sanei/sanei_wire.c at this point. */ w->allocated_memory -= (1 + strlen (req.value)); free (req.value); } req.value = malloc (req.value_size); if (!req.value) { w->status = ENOMEM; DBG (DBG_ERR, "process_request: (control_option) " "h=%d (%s)\n", req.handle, strerror (w->status)); return 1; } memset (req.value, 0, req.value_size); w->allocated_memory += req.value_size; } can_authorize = 1; memset (&reply, 0, sizeof (reply)); /* avoid leaking bits */ be_handle = handle[req.handle].handle; reply.status = sane_control_option (be_handle, req.option, req.action, req.value, &reply.info); reply.value_type = req.value_type; reply.value_size = req.value_size; reply.value = req.value; can_authorize = 0; sanei_w_reply (w, (WireCodecFunc) sanei_w_control_option_reply, &reply); sanei_w_free (w, (WireCodecFunc) sanei_w_control_option_req, &req); } break; case SANE_NET_GET_PARAMETERS: { SANE_Get_Parameters_Reply reply; h = decode_handle (w, "get_parameters"); if (h < 0) return 1; be_handle = handle[h].handle; reply.status = sane_get_parameters (be_handle, &reply.params); sanei_w_reply (w, (WireCodecFunc) sanei_w_get_parameters_reply, &reply); } break; case SANE_NET_START: { SANE_Start_Reply reply; int fd = -1, data_fd; h = decode_handle (w, "start"); if (h < 0) return 1; memset (&reply, 0, sizeof (reply)); /* avoid leaking bits */ reply.byte_order = SANE_NET_LITTLE_ENDIAN; if (byte_order.w != 1) reply.byte_order = SANE_NET_BIG_ENDIAN; if (handle[h].scanning) reply.status = SANE_STATUS_DEVICE_BUSY; else fd = start_scan (w, h, &reply); sanei_w_reply (w, (WireCodecFunc) sanei_w_start_reply, &reply); #ifdef SANED_USES_AF_INDEP if (reply.status == SANE_STATUS_GOOD) { struct sockaddr_storage ss; char text_addr[64]; int len; int error; DBG (DBG_MSG, "process_request: waiting for data connection\n"); data_fd = accept (fd, 0, 0); close (fd); /* Get address of remote host */ len = sizeof (ss); if (getpeername (data_fd, (struct sockaddr *) &ss, (socklen_t *) &len) < 0) { DBG (DBG_ERR, "process_request: getpeername failed: %s\n", strerror (errno)); return 1; } error = getnameinfo ((struct sockaddr *) &ss, len, text_addr, sizeof (text_addr), NULL, 0, NI_NUMERICHOST); if (error) { DBG (DBG_ERR, "process_request: getnameinfo failed: %s\n", gai_strerror (error)); return 1; } DBG (DBG_MSG, "process_request: access to data port from %s\n", text_addr); if (strcmp (text_addr, remote_ip) != 0) { DBG (DBG_ERR, "process_request: however, only %s is authorized\n", text_addr); DBG (DBG_ERR, "process_request: configuration problem or attack?\n"); close (data_fd); data_fd = -1; return -1; } #else /* !SANED_USES_AF_INDEP */ if (reply.status == SANE_STATUS_GOOD) { struct sockaddr_in sin; int len; DBG (DBG_MSG, "process_request: waiting for data connection\n"); data_fd = accept (fd, 0, 0); close (fd); /* Get address of remote host */ len = sizeof (sin); if (getpeername (data_fd, (struct sockaddr *) &sin, (socklen_t *) &len) < 0) { DBG (DBG_ERR, "process_request: getpeername failed: %s\n", strerror (errno)); return 1; } if (memcmp (&remote_address, &sin.sin_addr, sizeof (remote_address)) != 0) { DBG (DBG_ERR, "process_request: access to data port from %s\n", inet_ntoa (sin.sin_addr)); DBG (DBG_ERR, "process_request: however, only %s is authorized\n", inet_ntoa (remote_address)); DBG (DBG_ERR, "process_request: configuration problem or attack?\n"); close (data_fd); data_fd = -1; return -1; } else DBG (DBG_MSG, "process_request: access to data port from %s\n", inet_ntoa (sin.sin_addr)); #endif /* SANED_USES_AF_INDEP */ if (data_fd < 0) { sane_cancel (handle[h].handle); handle[h].scanning = 0; handle[h].docancel = 0; DBG (DBG_ERR, "process_request: accept failed! (%s)\n", strerror (errno)); return 1; } fcntl (data_fd, F_SETFL, 1); /* set non-blocking */ shutdown (data_fd, 0); do_scan (w, h, data_fd); close (data_fd); } } break; case SANE_NET_CANCEL: { SANE_Word ack = 0; h = decode_handle (w, "cancel"); if (h >= 0) { sane_cancel (handle[h].handle); handle[h].docancel = 1; } sanei_w_reply (w, (WireCodecFunc) sanei_w_word, &ack); } break; case SANE_NET_EXIT: return -1; break; case SANE_NET_INIT: case SANE_NET_AUTHORIZE: default: DBG (DBG_ERR, "process_request: received unexpected procedure number %d\n", current_request); return -1; } return 0; } static int wait_child (pid_t pid, int *status, int options) { struct saned_child *c; struct saned_child *p = NULL; int ret; ret = waitpid(pid, status, options); if (ret <= 0) return ret; #ifdef WITH_AVAHI if ((avahi_pid > 0) && (ret == avahi_pid)) { avahi_pid = -1; numchildren--; return ret; } #endif /* WITH_AVAHI */ for (c = children; (c != NULL) && (c->next != NULL); p = c, c = c->next) { if (c->pid == ret) { if (c == children) children = c->next; else if (p != NULL) p->next = c->next; free(c); numchildren--; break; } } return ret; } static int add_child (pid_t pid) { struct saned_child *c; c = (struct saned_child *) malloc (sizeof(struct saned_child)); if (c == NULL) { DBG (DBG_ERR, "add_child: out of memory\n"); return -1; } c->pid = pid; c->next = children; children = c; return 0; } static void handle_connection (int fd) { #ifdef TCP_NODELAY int on = 1; int level = -1; #endif DBG (DBG_DBG, "handle_connection: processing client connection\n"); wire.io.fd = fd; signal (SIGALRM, quit); signal (SIGPIPE, quit); #ifdef TCP_NODELAY # ifdef SOL_TCP level = SOL_TCP; # else /* !SOL_TCP */ /* Look up the protocol level in the protocols database. */ { struct protoent *p; p = getprotobyname ("tcp"); if (p == 0) { DBG (DBG_WARN, "handle_connection: cannot look up `tcp' protocol number"); } else level = p->p_proto; } # endif /* SOL_TCP */ if (level == -1 || setsockopt (wire.io.fd, level, TCP_NODELAY, &on, sizeof (on))) DBG (DBG_WARN, "handle_connection: failed to put socket in TCP_NODELAY mode (%s)", strerror (errno)); #endif /* !TCP_NODELAY */ if (init (&wire) < 0) return; while (1) { reset_watchdog (); if (process_request (&wire) < 0) break; } } static void handle_client (int fd) { pid_t pid; int i; DBG (DBG_DBG, "handle_client: spawning child process\n"); pid = fork (); if (pid == 0) { /* child */ if (log_to_syslog) closelog(); for (i = 3; i < fd; i++) close(i); if (log_to_syslog) openlog ("saned", LOG_PID | LOG_CONS, LOG_DAEMON); handle_connection (fd); quit (0); } else if (pid > 0) { /* parent */ add_child (pid); close(fd); } else { /* FAILED */ DBG (DBG_ERR, "handle_client: fork() failed: %s\n", strerror (errno)); close(fd); } } static void bail_out (int error) { DBG (DBG_ERR, "%sbailing out, waiting for children...\n", (error) ? "FATAL ERROR; " : ""); #ifdef WITH_AVAHI if (avahi_pid > 0) kill (avahi_pid, SIGTERM); #endif /* WITH_AVAHI */ while (numchildren > 0) wait_child (-1, NULL, 0); DBG (DBG_ERR, "bail_out: all children exited\n"); exit ((error) ? 1 : 0); } void sig_int_term_handler (int signum); void sig_int_term_handler (int signum) { /* unused */ signum = signum; signal (SIGINT, NULL); signal (SIGTERM, NULL); bail_out (0); } #ifdef WITH_AVAHI static void saned_avahi (struct pollfd *fds, int nfds); static void saned_create_avahi_services (AvahiClient *c); static void saned_avahi_callback (AvahiClient *c, AvahiClientState state, void *userdata); static void saned_avahi_group_callback (AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata); static void saned_avahi (struct pollfd *fds, int nfds) { struct pollfd *fdp = NULL; int error; avahi_pid = fork (); if (avahi_pid > 0) { numchildren++; return; } else if (avahi_pid < 0) { DBG (DBG_ERR, "saned_avahi: could not spawn Avahi process: %s\n", strerror (errno)); return; } signal (SIGINT, NULL); signal (SIGTERM, NULL); /* Close network fds */ for (fdp = fds; nfds > 0; nfds--, fdp++) close (fdp->fd); free(fds); avahi_svc_name = avahi_strdup(SANED_NAME); avahi_poll = avahi_simple_poll_new (); if (avahi_poll == NULL) { DBG (DBG_ERR, "saned_avahi: failed to create simple poll object\n"); goto fail; } avahi_client = avahi_client_new (avahi_simple_poll_get (avahi_poll), AVAHI_CLIENT_NO_FAIL, saned_avahi_callback, NULL, &error); if (avahi_client == NULL) { DBG (DBG_ERR, "saned_avahi: failed to create client: %s\n", avahi_strerror (error)); goto fail; } avahi_simple_poll_loop (avahi_poll); DBG (DBG_INFO, "saned_avahi: poll loop exited\n"); exit(EXIT_SUCCESS); /* NOT REACHED */ return; fail: if (avahi_client) avahi_client_free (avahi_client); if (avahi_poll) avahi_simple_poll_free (avahi_poll); avahi_free (avahi_svc_name); exit(EXIT_FAILURE); } static void saned_avahi_group_callback (AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { char *n; /* unused */ userdata = userdata; if ((!g) || (g != avahi_group)) return; switch (state) { case AVAHI_ENTRY_GROUP_ESTABLISHED: /* The entry group has been established successfully */ DBG (DBG_INFO, "saned_avahi_group_callback: service '%s' successfully established\n", avahi_svc_name); break; case AVAHI_ENTRY_GROUP_COLLISION: /* A service name collision with a remote service * happened. Let's pick a new name */ n = avahi_alternative_service_name (avahi_svc_name); avahi_free (avahi_svc_name); avahi_svc_name = n; DBG (DBG_WARN, "saned_avahi_group_callback: service name collision, renaming service to '%s'\n", avahi_svc_name); /* And recreate the services */ saned_create_avahi_services (avahi_entry_group_get_client (g)); break; case AVAHI_ENTRY_GROUP_FAILURE : DBG (DBG_ERR, "saned_avahi_group_callback: entry group failure: %s\n", avahi_strerror (avahi_client_errno (avahi_entry_group_get_client (g)))); /* Some kind of failure happened while we were registering our services */ avahi_simple_poll_quit (avahi_poll); break; case AVAHI_ENTRY_GROUP_UNCOMMITED: case AVAHI_ENTRY_GROUP_REGISTERING: break; } } static void saned_create_avahi_services (AvahiClient *c) { char *n; char txt[32]; AvahiProtocol proto; int ret; if (!c) return; if (!avahi_group) { avahi_group = avahi_entry_group_new (c, saned_avahi_group_callback, NULL); if (avahi_group == NULL) { DBG (DBG_ERR, "saned_create_avahi_services: avahi_entry_group_new() failed: %s\n", avahi_strerror (avahi_client_errno (c))); goto fail; } } if (avahi_entry_group_is_empty (avahi_group)) { DBG (DBG_INFO, "saned_create_avahi_services: adding service '%s'\n", avahi_svc_name); snprintf(txt, sizeof (txt), "protovers=%x", SANE_VERSION_CODE (V_MAJOR, V_MINOR, SANEI_NET_PROTOCOL_VERSION)); #ifdef ENABLE_IPV6 proto = AVAHI_PROTO_UNSPEC; #else proto = AVAHI_PROTO_INET; #endif /* ENABLE_IPV6 */ ret = avahi_entry_group_add_service (avahi_group, AVAHI_IF_UNSPEC, proto, 0, avahi_svc_name, SANED_SERVICE_DNS, NULL, NULL, SANED_SERVICE_PORT, txt, NULL); if (ret < 0) { if (ret == AVAHI_ERR_COLLISION) { n = avahi_alternative_service_name (avahi_svc_name); avahi_free (avahi_svc_name); avahi_svc_name = n; DBG (DBG_WARN, "saned_create_avahi_services: service name collision, renaming service to '%s'\n", avahi_svc_name); avahi_entry_group_reset (avahi_group); saned_create_avahi_services (c); return; } DBG (DBG_ERR, "saned_create_avahi_services: failed to add %s service: %s\n", SANED_SERVICE_DNS, avahi_strerror (ret)); goto fail; } /* Tell the server to register the service */ ret = avahi_entry_group_commit (avahi_group); if (ret < 0) { DBG (DBG_ERR, "saned_create_avahi_services: failed to commit entry group: %s\n", avahi_strerror (ret)); goto fail; } } return; fail: avahi_simple_poll_quit (avahi_poll); } static void saned_avahi_callback (AvahiClient *c, AvahiClientState state, void *userdata) { int error; /* unused */ userdata = userdata; if (!c) return; switch (state) { case AVAHI_CLIENT_CONNECTING: DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_CONNECTING\n"); break; case AVAHI_CLIENT_S_RUNNING: DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_S_RUNNING\n"); saned_create_avahi_services (c); break; case AVAHI_CLIENT_S_COLLISION: DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_S_COLLISION\n"); case AVAHI_CLIENT_S_REGISTERING: DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_S_REGISTERING\n"); if (avahi_group) avahi_entry_group_reset (avahi_group); break; case AVAHI_CLIENT_FAILURE: DBG (DBG_INFO, "saned_avahi_callback: AVAHI_CLIENT_FAILURE\n"); error = avahi_client_errno (c); if (error == AVAHI_ERR_DISCONNECTED) { DBG (DBG_INFO, "saned_avahi_callback: AVAHI_ERR_DISCONNECTED\n"); /* Server disappeared - try to reconnect */ avahi_client_free (avahi_client); avahi_client = NULL; avahi_group = NULL; avahi_client = avahi_client_new (avahi_simple_poll_get (avahi_poll), AVAHI_CLIENT_NO_FAIL, saned_avahi_callback, NULL, &error); if (avahi_client == NULL) { DBG (DBG_ERR, "saned_avahi_callback: failed to create client: %s\n", avahi_strerror (error)); avahi_simple_poll_quit (avahi_poll); } } else { /* Another error happened - game over */ DBG (DBG_ERR, "saned_avahi_callback: client failure: %s\n", avahi_strerror (error)); avahi_simple_poll_quit (avahi_poll); } break; } } #endif /* WITH_AVAHI */ static void read_config (void) { char config_line[PATH_MAX]; const char *optval; char *endval; long val; FILE *fp; int len; DBG (DBG_INFO, "read_config: searching for config file\n"); fp = sanei_config_open (SANED_CONFIG_FILE); if (fp) { while (sanei_config_read (config_line, sizeof (config_line), fp)) { if (config_line[0] == '#') continue; /* ignore line comments */ optval = strchr (config_line, '='); if (optval == NULL) continue; /* only interested in options, skip hosts */ len = strlen (config_line); if (!len) continue; /* ignore empty lines */ /* * Check for saned options. * Anything that isn't an option is a client. */ if (strstr(config_line, "data_portrange") != NULL) { optval = sanei_config_skip_whitespace (++optval); if ((optval != NULL) && (*optval != '\0')) { val = strtol (optval, &endval, 10); if (optval == endval) { DBG (DBG_ERR, "read_config: invalid value for data_portrange\n"); continue; } else if ((val < 0) || (val > 65535)) { DBG (DBG_ERR, "read_config: data_portrange start port is invalid\n"); continue; } optval = strchr (endval, '-'); if (optval == NULL) { DBG (DBG_ERR, "read_config: no end port value for data_portrange\n"); continue; } optval = sanei_config_skip_whitespace (++optval); data_port_lo = val; val = strtol (optval, &endval, 10); if (optval == endval) { DBG (DBG_ERR, "read_config: invalid value for data_portrange\n"); data_port_lo = 0; continue; } else if ((val < 0) || (val > 65535)) { DBG (DBG_ERR, "read_config: data_portrange end port is invalid\n"); data_port_lo = 0; continue; } else if (val < data_port_lo) { DBG (DBG_ERR, "read_config: data_portrange end port is less than start port\n"); data_port_lo = 0; continue; } data_port_hi = val; DBG (DBG_INFO, "read_config: data port range: %d - %d\n", data_port_lo, data_port_hi); } } } fclose (fp); DBG (DBG_INFO, "read_config: done reading config\n"); } else DBG (DBG_ERR, "read_config: could not open config file (%s): %s\n", SANED_CONFIG_FILE, strerror (errno)); } #ifdef SANED_USES_AF_INDEP static void do_bindings_family (int family, int *nfds, struct pollfd **fds, struct addrinfo *res) { struct addrinfo *resp; struct pollfd *fdp; short sane_port; int fd = -1; int on = 1; int i; fdp = *fds; for (resp = res, i = 0; resp != NULL; resp = resp->ai_next, i++) { /* We're not interested */ if (resp->ai_family != family) continue; if (resp->ai_family == AF_INET) { sane_port = ntohs (((struct sockaddr_in *) resp->ai_addr)->sin_port); } #ifdef ENABLE_IPV6 else if (resp->ai_family == AF_INET6) { sane_port = ntohs (((struct sockaddr_in6 *) resp->ai_addr)->sin6_port); } #endif /* ENABLE_IPV6 */ else continue; DBG (DBG_DBG, "do_bindings: [%d] socket () using IPv%d\n", i, (family == AF_INET) ? 4 : 6); if ((fd = socket (resp->ai_family, SOCK_STREAM, 0)) < 0) { DBG (DBG_ERR, "do_bindings: [%d] socket failed: %s\n", i, strerror (errno)); continue; } DBG (DBG_DBG, "do_bindings: [%d] setsockopt ()\n", i); if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))) DBG (DBG_ERR, "do_bindings: [%d] failed to put socket in SO_REUSEADDR mode (%s)\n", i, strerror (errno)); DBG (DBG_DBG, "do_bindings: [%d] bind () to port %d\n", i, sane_port); if (bind (fd, resp->ai_addr, resp->ai_addrlen) < 0) { /* * Binding a socket may fail with EADDRINUSE if we already bound * to an IPv6 addr returned by getaddrinfo (usually the first ones) * and we're trying to bind to an IPv4 addr now. * It can also fail because we're trying to bind an IPv6 socket and IPv6 * is not functional on this machine. * In any case, a bind() call returning an error is not necessarily fatal. */ DBG (DBG_WARN, "do_bindings: [%d] bind failed: %s\n", i, strerror (errno)); close (fd); continue; } DBG (DBG_DBG, "do_bindings: [%d] listen ()\n", i); if (listen (fd, 1) < 0) { DBG (DBG_ERR, "do_bindings: [%d] listen failed: %s\n", i, strerror (errno)); close (fd); continue; } fdp->fd = fd; fdp->events = POLLIN; (*nfds)++; fdp++; } *fds = fdp; } static void do_bindings (int *nfds, struct pollfd **fds) { struct addrinfo *res; struct addrinfo *resp; struct addrinfo hints; struct pollfd *fdp; int err; DBG (DBG_DBG, "do_bindings: trying to get port for service \"%s\" (getaddrinfo)\n", SANED_SERVICE_NAME); memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; err = getaddrinfo (bind_addr, SANED_SERVICE_NAME, &hints, &res); if (err) { DBG (DBG_WARN, "do_bindings: \" %s \" service unknown on your host; you should add\n", SANED_SERVICE_NAME); DBG (DBG_WARN, "do_bindings: %s %d/tcp saned # SANE network scanner daemon\n", SANED_SERVICE_NAME, SANED_SERVICE_PORT); DBG (DBG_WARN, "do_bindings: to your /etc/services file (or equivalent). Proceeding anyway.\n"); err = getaddrinfo (bind_addr, SANED_SERVICE_PORT_S, &hints, &res); if (err) { DBG (DBG_ERR, "do_bindings: getaddrinfo() failed even with numeric port: %s\n", gai_strerror (err)); bail_out (1); } } for (resp = res, *nfds = 0; resp != NULL; resp = resp->ai_next, (*nfds)++) ; *fds = malloc (*nfds * sizeof (struct pollfd)); if (fds == NULL) { DBG (DBG_ERR, "do_bindings: not enough memory for fds\n"); freeaddrinfo (res); bail_out (1); } fdp = *fds; *nfds = 0; /* bind IPv6 first, IPv4 second */ #ifdef ENABLE_IPV6 do_bindings_family (AF_INET6, nfds, &fdp, res); #endif do_bindings_family (AF_INET, nfds, &fdp, res); resp = NULL; freeaddrinfo (res); if (*nfds <= 0) { DBG (DBG_ERR, "do_bindings: couldn't bind an address. Exiting.\n"); bail_out (1); } } #else /* !SANED_USES_AF_INDEP */ static void do_bindings (int *nfds, struct pollfd **fds) { struct sockaddr_in sin; struct servent *serv; short port; int fd = -1; int on = 1; DBG (DBG_DBG, "do_bindings: trying to get port for service \"%s\" (getservbyname)\n", SANED_SERVICE_NAME); serv = getservbyname (SANED_SERVICE_NAME, "tcp"); if (serv) { port = serv->s_port; DBG (DBG_MSG, "do_bindings: port is %d\n", ntohs (port)); } else { port = htons (SANED_SERVICE_PORT); DBG (DBG_WARN, "do_bindings: \"%s\" service unknown on your host; you should add\n", SANED_SERVICE_NAME); DBG (DBG_WARN, "do_bindings: %s %d/tcp saned # SANE network scanner daemon\n", SANED_SERVICE_NAME, SANED_SERVICE_PORT); DBG (DBG_WARN, "do_bindings: to your /etc/services file (or equivalent). Proceeding anyway.\n"); } *nfds = 1; *fds = malloc (*nfds * sizeof (struct pollfd)); if (fds == NULL) { DBG (DBG_ERR, "do_bindings: not enough memory for fds\n"); bail_out (1); } memset (&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; if(bind_addr) sin.sin_addr.s_addr = inet_addr(bind_addr); else sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = port; DBG (DBG_DBG, "do_bindings: socket ()\n"); fd = socket (AF_INET, SOCK_STREAM, 0); DBG (DBG_DBG, "do_bindings: setsockopt ()\n"); if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))) DBG (DBG_ERR, "do_bindings: failed to put socket in SO_REUSEADDR mode (%s)", strerror (errno)); DBG (DBG_DBG, "do_bindings: bind ()\n"); if (bind (fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) { DBG (DBG_ERR, "do_bindings: bind failed: %s", strerror (errno)); bail_out (1); } DBG (DBG_DBG, "do_bindings: listen ()\n"); if (listen (fd, 1) < 0) { DBG (DBG_ERR, "do_bindings: listen failed: %s", strerror (errno)); bail_out (1); } (*fds)->fd = fd; (*fds)->events = POLLIN; } #endif /* SANED_USES_AF_INDEP */ static void run_standalone (char *user) { struct pollfd *fds = NULL; struct pollfd *fdp = NULL; int nfds; int fd = -1; int i; int ret; uid_t runas_uid = 0; gid_t runas_gid = 0; struct passwd *pwent; gid_t *grplist = NULL; struct group *grp; int ngroups = 0; FILE *pidfile; do_bindings (&nfds, &fds); if (run_mode != SANED_RUN_DEBUG) { if (user) { pwent = getpwnam(user); if (pwent == NULL) { DBG (DBG_ERR, "FATAL ERROR: user %s not found on system\n", user); bail_out (1); } runas_uid = pwent->pw_uid; runas_gid = pwent->pw_gid; /* Get group list for runas_uid */ grplist = (gid_t *)malloc(sizeof(gid_t)); if (grplist == NULL) { DBG (DBG_ERR, "FATAL ERROR: cannot allocate memory for group list\n"); exit (1); } ngroups = 1; grplist[0] = runas_gid; setgrent(); while ((grp = getgrent()) != NULL) { int i = 0; /* Already added current group */ if (grp->gr_gid == runas_gid) continue; while (grp->gr_mem[i]) { if (strcmp(grp->gr_mem[i], user) == 0) { int need_to_add = 1, j; /* Make sure its not already in list */ for (j = 0; j < ngroups; j++) { if (grp->gr_gid == grplist[i]) need_to_add = 0; } if (need_to_add) { grplist = (gid_t *)realloc(grplist, sizeof(gid_t)*ngroups+1); if (grplist == NULL) { DBG (DBG_ERR, "FATAL ERROR: cannot reallocate memory for group list\n"); exit (1); } grplist[ngroups++] = grp->gr_gid; } } i++; } } endgrent(); } DBG (DBG_MSG, "run_standalone: daemonizing now\n"); fd = open ("/dev/null", O_RDWR); if (fd < 0) { DBG (DBG_ERR, "FATAL ERROR: cannot open /dev/null: %s\n", strerror (errno)); exit (1); } ret = fork (); if (ret > 0) { _exit (0); } else if (ret < 0) { DBG (DBG_ERR, "FATAL ERROR: fork failed: %s\n", strerror (errno)); exit (1); } DBG (DBG_WARN, "Now daemonized\n"); /* Write out PID file */ pidfile = fopen (SANED_PID_FILE, "w"); if (pidfile) { fprintf (pidfile, "%d", getpid()); fclose (pidfile); } else DBG (DBG_ERR, "Could not write PID file: %s\n", strerror (errno)); chdir ("/"); dup2 (fd, STDIN_FILENO); dup2 (fd, STDOUT_FILENO); dup2 (fd, STDERR_FILENO); close (fd); setsid (); /* Drop privileges if requested */ if (runas_uid > 0) { ret = setgroups(ngroups, grplist); if (ret < 0) { DBG (DBG_ERR, "FATAL ERROR: could not set group list: %s\n", strerror(errno)); exit (1); } free(grplist); ret = setegid (runas_gid); if (ret < 0) { DBG (DBG_ERR, "FATAL ERROR: setegid to gid %d failed: %s\n", runas_gid, strerror (errno)); exit (1); } ret = seteuid (runas_uid); if (ret < 0) { DBG (DBG_ERR, "FATAL ERROR: seteuid to uid %d failed: %s\n", runas_uid, strerror (errno)); exit (1); } DBG (DBG_WARN, "Dropped privileges to uid %d gid %d\n", runas_uid, runas_gid); } signal(SIGINT, sig_int_term_handler); signal(SIGTERM, sig_int_term_handler); } #ifdef WITH_AVAHI DBG (DBG_INFO, "run_standalone: spawning Avahi process\n"); saned_avahi (fds, nfds); /* NOT REACHED (Avahi process) */ #endif /* WITH_AVAHI */ DBG (DBG_MSG, "run_standalone: waiting for control connection\n"); while (1) { ret = poll (fds, nfds, 500); if (ret < 0) { if (errno == EINTR) continue; else { DBG (DBG_ERR, "run_standalone: poll failed: %s\n", strerror (errno)); free (fds); bail_out (1); } } /* Wait for children */ while (wait_child (-1, NULL, WNOHANG) > 0) ; if (ret == 0) continue; for (i = 0, fdp = fds; i < nfds; i++, fdp++) { /* Error on an fd */ if (fdp->revents & (POLLERR | POLLHUP | POLLNVAL)) { for (i = 0, fdp = fds; i < nfds; i++, fdp++) close (fdp->fd); free (fds); DBG (DBG_WARN, "run_standalone: invalid fd in set, attempting to re-bind\n"); /* Reopen sockets */ do_bindings (&nfds, &fds); break; } else if (! (fdp->revents & POLLIN)) continue; fd = accept (fdp->fd, 0, 0); if (fd < 0) { DBG (DBG_ERR, "run_standalone: accept failed: %s", strerror (errno)); continue; } if (run_mode == SANED_RUN_DEBUG) break; /* We have the only connection we're going to handle */ else handle_client (fd); } if (run_mode == SANED_RUN_DEBUG) break; } for (i = 0, fdp = fds; i < nfds; i++, fdp++) close (fdp->fd); free (fds); if (run_mode == SANED_RUN_DEBUG) { if (fd > 0) handle_connection (fd); bail_out(0); } } static void run_inetd (char __sane_unused__ *sock) { int fd = -1; #ifdef HAVE_SYSTEMD int n; n = sd_listen_fds(0); if (n > 1) { DBG (DBG_ERR, "run_inetd: Too many file descriptors (sockets) received from systemd!\n"); return; } if (n == 1) { fd = SD_LISTEN_FDS_START + 0; DBG (DBG_INFO, "run_inetd: Using systemd socket %d!\n", fd); } #endif if (fd == -1) { int dave_null; /* Some backends really can't keep their dirty fingers off * stdin/stdout/stderr; we work around them here so they don't * mess up the network dialog and crash the remote net backend * by messing with the inetd socket. * For systemd this not an issue as systemd uses fd >= 3 for the * socket and can even redirect stdout and stderr to syslog. * We can even use this to get the debug logging */ do { /* get new fd for the inetd socket */ fd = dup (1); if (fd == -1) { DBG (DBG_ERR, "run_inetd: duplicating fd failed: %s", strerror (errno)); return; } } while (fd < 3); /* Our good'ole friend Dave Null to the rescue */ dave_null = open ("/dev/null", O_RDWR); if (dave_null < 0) { DBG (DBG_ERR, "run_inetd: could not open /dev/null: %s", strerror (errno)); return; } close (STDIN_FILENO); close (STDOUT_FILENO); close (STDERR_FILENO); dup2 (dave_null, STDIN_FILENO); dup2 (dave_null, STDOUT_FILENO); dup2 (dave_null, STDERR_FILENO); close (dave_null); } #ifdef HAVE_OS2_H /* under OS/2, the socket handle is passed as argument on the command line; the socket handle is relative to IBM TCP/IP, so a call to impsockethandle() is required to add it to the EMX runtime */ if (sock) { fd = _impsockhandle (atoi (sock), 0); if (fd == -1) perror ("impsockhandle"); } #endif /* HAVE_OS2_H */ handle_connection(fd); } static void usage(char *me, int err) { fprintf (stderr, "Usage: %s [OPTIONS]\n\n" " Options:\n\n" " -a, --alone[=user] run standalone and fork in background as `user'\n" " -d, --debug[=level] run foreground with output to stdout\n" " and debug level `level' (default is 2)\n" " -s, --syslog[=level] run foreground with output to syslog\n" " and debug level `level' (default is 2)\n" " -b, --bind=addr bind address `addr'\n" " -h, --help show this help message and exit\n", me); exit(err); } static int debug; static struct option long_options[] = { /* These options set a flag. */ {"help", no_argument, 0, 'h'}, {"alone", optional_argument, 0, 'a'}, {"debug", optional_argument, 0, 'd'}, {"syslog", optional_argument, 0, 's'}, {"bind", required_argument, 0, 'b'}, {0, 0, 0, 0 } }; int main (int argc, char *argv[]) { char options[64] = ""; char *user = NULL; char *sock = NULL; int c; int long_index = 0; debug = DBG_WARN; prog_name = strrchr (argv[0], '/'); if (prog_name) ++prog_name; else prog_name = argv[0]; numchildren = 0; run_mode = SANED_RUN_INETD; while((c = getopt_long(argc, argv,"ha::d::s::b:", long_options, &long_index )) != -1) { switch(c) { case 'a': run_mode = SANED_RUN_ALONE; user = optarg; break; case 'd': log_to_syslog = SANE_FALSE; case 's': run_mode = SANED_RUN_DEBUG; if(optarg) debug = atoi(optarg); break; case 'b': bind_addr = optarg; break; case 'h': usage(argv[0], EXIT_SUCCESS); break; default: usage(argv[0], EXIT_FAILURE); break; } } if (log_to_syslog) openlog ("saned", LOG_PID | LOG_CONS, LOG_DAEMON); read_config (); byte_order.w = 0; byte_order.ch = 1; sanei_w_init (&wire, sanei_codec_bin_init); wire.io.read = read; wire.io.write = write; #ifdef SANED_USES_AF_INDEP strcat(options, "AF-indep"); # ifdef ENABLE_IPV6 strcat(options, "+IPv6"); #endif #else strcat(options, "IPv4 only"); #endif #ifdef HAVE_SYSTEMD if (sd_listen_fds(0) > 0) { strcat(options, "+systemd"); } #endif if (strlen(options) > 0) { DBG (DBG_WARN, "saned (%s) from %s starting up\n", options, PACKAGE_STRING); } else { DBG (DBG_WARN, "saned from %s ready\n", PACKAGE_STRING); } if ((run_mode == SANED_RUN_ALONE) || (run_mode == SANED_RUN_DEBUG)) { run_standalone(user); } else { #ifdef HAVE_OS2_H if (argc == 2) sock = argv[1]; #endif run_inetd(sock); } DBG (DBG_WARN, "saned exiting\n"); return 0; } sane-backends-1.0.27/frontend/test.c0000664000175000017500000001203112112021330014142 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Andreas Beck This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. This file implements a simple SANE frontend (well it rather is a transport layer, but seen from libsane it is a frontend) which acts as a NETSANE server. The NETSANE specifications should have come with this package. Feel free to enhance this program ! It needs extension especially regarding crypto-support and authentication. */ #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" void auth_callback (SANE_String_Const domain, SANE_Char *username, SANE_Char *password) { printf ("Client '%s' requested authorization.\nUser:\n", domain); scanf ("%s", username); printf ("Password:\n"); scanf ("%s", password); return; } void testsane (const char *dev_name) { int hlp, x; SANE_Status bla; SANE_Int blubb; SANE_Handle hand; SANE_Parameters pars; const SANE_Option_Descriptor *sod; const SANE_Device **device_list; char buffer[2048]; bla = sane_init (&blubb, auth_callback); fprintf (stderr, "Init : stat=%d ver=%x\nPress Enter to continue...", bla, blubb); getchar (); if (bla != SANE_STATUS_GOOD) return; bla = sane_get_devices (&device_list, SANE_FALSE); fprintf (stderr, "GetDev : stat=%s\n", sane_strstatus (bla)); if (bla != SANE_STATUS_GOOD) return; bla = sane_open (dev_name, &hand); fprintf (stderr, "Open : stat=%s hand=%p\n", sane_strstatus (bla), hand); if (bla != SANE_STATUS_GOOD) return; bla = sane_set_io_mode (hand, 0); fprintf (stderr, "SetIoMode : stat=%s\n", sane_strstatus (bla)); for (hlp = 0; hlp < 9999; hlp++) { sod = sane_get_option_descriptor (hand, hlp); if (sod == NULL) break; fprintf (stderr, "Gopt(%d) : stat=%p\n", hlp, sod); fprintf (stderr, "name : %s\n", sod->name); fprintf (stderr, "title: %s\n", sod->title); fprintf (stderr, "desc : %s\n", sod->desc); fprintf (stderr, "type : %d\n", sod->type); fprintf (stderr, "unit : %d\n", sod->unit); fprintf (stderr, "size : %d\n", sod->size); fprintf (stderr, "cap : %d\n", sod->cap); fprintf (stderr, "ctyp : %d\n", sod->constraint_type); switch (sod->constraint_type) { case SANE_CONSTRAINT_NONE: break; case SANE_CONSTRAINT_STRING_LIST: fprintf (stderr, "stringlist:\n"); break; case SANE_CONSTRAINT_WORD_LIST: fprintf (stderr, "wordlist (%d) : ", sod->constraint.word_list[0]); for (x = 1; x <= sod->constraint.word_list[0]; x++) fprintf (stderr, " %d ", sod->constraint.word_list[x]); fprintf (stderr, "\n"); break; case SANE_CONSTRAINT_RANGE: fprintf (stderr, "range: %d-%d %d \n", sod->constraint.range->min, sod->constraint.range->max, sod->constraint.range->quant); break; } } bla = sane_get_parameters (hand, &pars); fprintf (stderr, "Parm : stat=%s form=%d,lf=%d,bpl=%d,pixpl=%d,lin=%d,dep=%d\n", sane_strstatus (bla), pars.format, pars.last_frame, pars.bytes_per_line, pars.pixels_per_line, pars.lines, pars.depth); if (bla != SANE_STATUS_GOOD) return; bla = sane_start (hand); fprintf (stderr, "Start : stat=%s\n", sane_strstatus (bla)); if (bla != SANE_STATUS_GOOD) return; do { bla = sane_read (hand, buffer, sizeof (buffer), &blubb); /*printf("Read : stat=%s len=%d\n",sane_strstatus (bla),blubb); */ if (bla != SANE_STATUS_GOOD) { if (bla == SANE_STATUS_EOF) break; return; } fwrite (buffer, 1, blubb, stdout); } while (1); sane_cancel (hand); fprintf (stderr, "Cancel.\n"); sane_close (hand); fprintf (stderr, "Close\n"); for (hlp = 0; hlp < 20; hlp++) fprintf (stderr, "STRS %d=%s\n", hlp, sane_strstatus (hlp)); fprintf (stderr, "Exit.\n"); } int main (int argc, char *argv[]) { if (argc != 2 && argc != 3) { fprintf (stderr, "Usage: %s devicename [hostname]\n", argv[0]); exit (0); } if (argc == 3) { char envbuf[1024]; sprintf (envbuf, "SANE_NET_HOST=%s", argv[2]); putenv (envbuf); } fprintf (stderr, "This is a SANE test application.\n" "Now connecting to device %s.\n", argv[1]); testsane (argv[1]); sane_exit (); return 0; } sane-backends-1.0.27/frontend/tstbackend.c0000664000175000017500000016204712775312262015350 00000000000000/* tstbackend -- backend test utility Uses the SANE library. Copyright (C) 2002 Frank Zago (sane at zago dot net) Copyright (C) 2013 Stéphane Voltz : sane_get_devices test This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define BUILD 19 /* 2013-03-29 */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" static struct option basic_options[] = { {"device-name", required_argument, NULL, 'd'}, {"level", required_argument, NULL, 'l'}, {"scan", NULL, NULL, 's'}, {"recursion", required_argument, NULL, 'r'}, {"get-devices", required_argument, NULL, 'g'}, {"help", 0, NULL, 'h'} }; static void test_options (SANE_Device * device, int can_do_recursive); enum message_level { MSG, /* info message */ INF, /* non-urgent warning */ WRN, /* warning */ ERR, /* error, test can continue */ FATAL, /* error, test can't/mustn't continue */ BUG /* bug in tstbackend */ }; int message_number_wrn = 0; int message_number_err = 0; #ifdef HAVE_LONG_LONG long long checks_done = 0; #else /* It may overflow, but it's no big deal. */ long int checks_done = 0; #endif int test_level; int verbose_level; /* Maybe add that to sane.h */ #define SANE_OPTION_IS_GETTABLE(cap) (((cap) & (SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE)) == SANE_CAP_SOFT_DETECT) /*--------------------------------------------------------------------------*/ /* Display the message error statistics. */ static void display_stats(void) { #ifdef HAVE_LONG_LONG printf("warnings: %d error: %d checks: %lld\n", message_number_wrn, message_number_err, checks_done); #else printf("warnings: %d error: %d checks: %ld\n", message_number_wrn, message_number_err, checks_done); #endif } /* * If the condition is false, display a message with some headers * depending on the level. * * Returns the condition. * */ #ifdef __GNUC__ static int check(enum message_level, int condition, const char *format, ...) __attribute__ ((format (printf, 3, 4))); #endif static int check(enum message_level level, int condition, const char *format, ...) { char str[1000]; va_list args; if (level != MSG && level != INF) checks_done ++; if (condition != 0) return condition; va_start(args, format); vsprintf(str, format, args); va_end(args); switch(level) { case MSG: printf(" %s\n", str); break; case INF: /* info */ printf("info : %s\n", str); break; case WRN: /* warning */ printf("warning : %s\n", str); message_number_wrn ++; break; case ERR: /* error */ printf("ERROR : %s\n", str); message_number_err ++; break; case FATAL: /* fatal error */ printf("FATAL ERROR : %s\n", str); message_number_err ++; break; case BUG: /* bug in tstbackend */ printf("tstbackend BUG : %s\n", str); break; } if (level == FATAL || level == BUG) { /* Fatal error. Generate a core dump. */ display_stats(); abort(); } fflush(stdout); return(0); } /*--------------------------------------------------------------------------*/ #define GUARDS_SIZE 4 /* 4 bytes */ #define GUARD1 ((SANE_Word)0x5abf8ea5) #define GUARD2 ((SANE_Word)0xa58ebf5a) /* Allocate the requested memory plus enough room to store some guard bytes. */ static void *guards_malloc(size_t size) { unsigned char *ptr; size += 2*GUARDS_SIZE; ptr = malloc(size); assert(ptr); ptr += GUARDS_SIZE; return(ptr); } /* Free some memory allocated by guards_malloc. */ static void guards_free(void *ptr) { unsigned char *p = ptr; p -= GUARDS_SIZE; free(p); } /* Set the guards */ static void guards_set(void *ptr, size_t size) { SANE_Word *p; p = (SANE_Word *)(((unsigned char *)ptr) - GUARDS_SIZE); *p = GUARD1; p = (SANE_Word *)(((unsigned char *)ptr) + size); *p = GUARD2; } /* Check that the guards have not been tampered with. */ static void guards_check(void *ptr, size_t size) { SANE_Word *p; p = (SANE_Word *)(((unsigned char *)ptr) - GUARDS_SIZE); check(FATAL, (*p == GUARD1), "guard before the block has been tampered"); p = (SANE_Word *)(((unsigned char *)ptr) + size); check(FATAL, (*p == GUARD2), "guard after the block has been tampered"); } /*--------------------------------------------------------------------------*/ static void test_parameters (SANE_Device * device, SANE_Parameters *params) { SANE_Status status; SANE_Parameters p; status = sane_get_parameters (device, &p); check(FATAL, (status == SANE_STATUS_GOOD), "cannot get the parameters (error %s)", sane_strstatus(status)); check(FATAL, ((p.format == SANE_FRAME_GRAY) || (p.format == SANE_FRAME_RGB) || (p.format == SANE_FRAME_RED) || (p.format == SANE_FRAME_GREEN) || (p.format == SANE_FRAME_BLUE)), "parameter format is not a known SANE_FRAME_* (%d)", p.format); check(FATAL, ((p.last_frame == SANE_FALSE) || (p.last_frame == SANE_TRUE)), "parameter last_frame is neither SANE_FALSE or SANE_TRUE (%d)", p.last_frame); check(FATAL, ((p.depth == 1) || (p.depth == 8) || (p.depth == 16)), "parameter depth is neither 1, 8 or 16 (%d)", p.depth); if (params) { *params = p; } } /* Try to set every option in a word list. */ static void test_options_word_list (SANE_Device * device, int option_num, const SANE_Option_Descriptor *opt, int can_do_recursive) { SANE_Status status; int i; SANE_Int val_int; SANE_Int info; check(FATAL, (opt->type == SANE_TYPE_INT || opt->type == SANE_TYPE_FIXED), "type must be SANE_TYPE_INT or SANE_TYPE_FIXED (%d)", opt->type); if (!SANE_OPTION_IS_SETTABLE(opt->cap)) return; for (i=1; iconstraint.word_list[0]; i++) { info = 0x1010; /* garbage */ val_int = opt->constraint.word_list[i]; status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int, &info); check(FATAL, (status == SANE_STATUS_GOOD), "cannot set a settable option (status=%s)", sane_strstatus(status)); check(WRN, ((info & ~(SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS)) == 0), "sane_control_option set an invalid info (%d)", info); if ((info & SANE_INFO_RELOAD_OPTIONS) && can_do_recursive) { test_options(device, can_do_recursive-1); } if (info & SANE_INFO_RELOAD_PARAMS) { test_parameters(device, NULL); } /* The option might have become inactive or unsettable. Skip it. */ if (!SANE_OPTION_IS_ACTIVE(opt->cap) || !SANE_OPTION_IS_SETTABLE(opt->cap)) return; } } /* Try to set every option in a string list. */ static void test_options_string_list (SANE_Device * device, int option_num, const SANE_Option_Descriptor *opt, int can_do_recursive) { SANE_Int info; SANE_Status status; SANE_String val_string; int i; check(FATAL, (opt->type == SANE_TYPE_STRING), "type must be SANE_TYPE_STRING (%d)", opt->type); if (!SANE_OPTION_IS_SETTABLE(opt->cap)) return; for (i=0; opt->constraint.string_list[i] != NULL; i++) { val_string = strdup(opt->constraint.string_list[i]); assert(val_string); check(WRN, (strlen(val_string) < (size_t)opt->size), "string [%s] is longer than the max size (%d)", val_string, opt->size); info = 0xE1000; /* garbage */ status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, val_string, &info); check(FATAL, (status == SANE_STATUS_GOOD), "cannot set a settable option (status=%s)", sane_strstatus(status)); check(WRN, ((info & ~(SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS)) == 0), "sane_control_option set an invalid info (%d)", info); free(val_string); if ((info & SANE_INFO_RELOAD_OPTIONS) && can_do_recursive) { test_options(device, can_do_recursive-1); } if (info & SANE_INFO_RELOAD_PARAMS) { test_parameters(device, NULL); } /* The option might have become inactive or unsettable. Skip it. */ if (!SANE_OPTION_IS_ACTIVE(opt->cap) || !SANE_OPTION_IS_SETTABLE(opt->cap)) return; } } /* Test the consistency of the options. */ static void test_options (SANE_Device * device, int can_do_recursive) { SANE_Word info; SANE_Int num_dev_options; SANE_Status status; const SANE_Option_Descriptor *opt; int option_num; void *optval; /* value for the option */ size_t optsize; /* size of the optval buffer */ /* * Test option 0 */ opt = sane_get_option_descriptor (device, 0); check(FATAL, (opt != NULL), "cannot get option descriptor for option 0 (it must exist)"); check(INF, (opt->cap == SANE_CAP_SOFT_DETECT), "invalid capabilities for option 0 (%d)", opt->cap); check(ERR, (opt->type == SANE_TYPE_INT), "option 0 type must be SANE_TYPE_INT"); /* Get the number of options. */ status = sane_control_option (device, 0, SANE_ACTION_GET_VALUE, &num_dev_options, 0); check(FATAL, (status == SANE_STATUS_GOOD), "cannot get option 0 value"); /* Try to change the number of options. */ status = sane_control_option (device, 0, SANE_ACTION_SET_VALUE, &num_dev_options, &info); check(WRN, (status != SANE_STATUS_GOOD), "the option 0 value can be set"); /* * Test all options */ option_num = 0; for (option_num = 0; option_num < num_dev_options; option_num++) { /* Get the option descriptor */ opt = sane_get_option_descriptor (device, option_num); check(FATAL, (opt != NULL), "cannot get option descriptor for option %d", option_num); check(WRN, ((opt->cap & ~(SANE_CAP_SOFT_SELECT | SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_EMULATED | SANE_CAP_AUTOMATIC | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED)) == 0), "invalid capabilities for option [%d, %s] (%x)", option_num, opt->name, opt->cap); check(WRN, (opt->title != NULL), "option [%d, %s] must have a title", option_num, opt->name); check(WRN, (opt->desc != NULL), "option [%d, %s] must have a description", option_num, opt->name); if (!SANE_OPTION_IS_ACTIVE (opt->cap)) { /* Option not active. Skip the remaining tests. */ continue; } if(verbose_level) { printf("checking option ""%s""\n",opt->title); } if (opt->type == SANE_TYPE_GROUP) { check(INF, (opt->name == NULL || *opt->name == 0), "option [%d, %s] has a name", option_num, opt->name); check(ERR, (!SANE_OPTION_IS_SETTABLE (opt->cap)), "option [%d, %s], group option is settable", option_num, opt->name); } else { if (option_num == 0) { check(ERR, (opt->name != NULL && *opt->name ==0), "option 0 must have an empty name (ie. \"\")"); } else { check(ERR, (opt->name != NULL && *opt->name !=0), "option %d must have a name", option_num); } } /* The option name must contain only "a".."z", "0".."9" and "-" and must start with "a".."z". */ if (opt->name && opt->name[0]) { const char *p = opt->name; check(ERR, (*p >= 'a' && *p <= 'z'), "name for option [%d, %s] must start with in letter in [a..z]", option_num, opt->name); p++; while(*p) { check(ERR, ((*p >= 'a' && *p <= 'z') || (*p == '-') || (*p >= '0' && *p <= '9')), "name for option [%d, %s] must only have the letters [-a..z0..9]", option_num, opt->name); p++; } } optval = NULL; optsize = 0; switch(opt->type) { case SANE_TYPE_BOOL: check(WRN, (opt->size == sizeof(SANE_Word)), "size of option %s is incorrect", opt->name); optval = guards_malloc(opt->size); optsize = opt->size; check(WRN, (opt->constraint_type == SANE_CONSTRAINT_NONE), "invalid constraint type for option [%d, %s] (%d)", option_num, opt->name, opt->constraint_type); break; case SANE_TYPE_INT: case SANE_TYPE_FIXED: check(WRN, (opt->size > 0 && (opt->size % sizeof(SANE_Word) == 0)), "invalid size for option %s", opt->name); optval = guards_malloc(opt->size); optsize = opt->size; check(WRN, (opt->constraint_type == SANE_CONSTRAINT_NONE || opt->constraint_type == SANE_CONSTRAINT_RANGE || opt->constraint_type == SANE_CONSTRAINT_WORD_LIST), "invalid constraint type for option [%d, %s] (%d)", option_num, opt->name, opt->constraint_type); break; case SANE_TYPE_STRING: check(WRN, (opt->size >= 1), "size of option [%d, %s] must be at least 1 for the NUL terminator", option_num, opt->name); check(INF, (opt->unit == SANE_UNIT_NONE), "unit of option [%d, %s] is not SANE_UNIT_NONE", option_num, opt->name); check(WRN, (opt->constraint_type == SANE_CONSTRAINT_STRING_LIST || opt->constraint_type == SANE_CONSTRAINT_NONE), "invalid constraint type for option [%d, %s] (%d)", option_num, opt->name, opt->constraint_type); optval = guards_malloc(opt->size); optsize = opt->size; break; case SANE_TYPE_BUTTON: case SANE_TYPE_GROUP: check(INF, (opt->unit == SANE_UNIT_NONE), "option [%d, %s], unit is not SANE_UNIT_NONE", option_num, opt->name); check(INF, (opt->size == 0), "option [%d, %s], size is not 0", option_num, opt->name); check(WRN, (opt->constraint_type == SANE_CONSTRAINT_NONE), "invalid constraint type for option [%d, %s] (%d)", option_num, opt->name, opt->constraint_type); break; default: check(ERR, 0, "invalid type %d for option %s", opt->type, opt->name); break; } if (optval) { /* This is an option with a value */ /* get with NULL info. * * The SANE standard is not explicit on that subject. I * consider that an inactive option shouldn't be read by a * frontend because its value is meaningless. I think * that, in that case, SANE_STATUS_INVAL is an appropriate * return. */ guards_set(optval, optsize); status = sane_control_option (device, option_num, SANE_ACTION_GET_VALUE, optval, NULL); guards_check(optval, optsize); if (SANE_OPTION_IS_GETTABLE (opt->cap)) { check(ERR, (status == SANE_STATUS_GOOD), "cannot get option [%d, %s] value, although it is active (%s)", option_num, opt->name, sane_strstatus(status)); } else { check(ERR, (status == SANE_STATUS_INVAL), "was able to get option [%d, %s] value, although it is not active", option_num, opt->name); } /* set with NULL info */ guards_set(optval, optsize); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, optval, NULL); guards_check(optval, optsize); if (SANE_OPTION_IS_SETTABLE (opt->cap) && SANE_OPTION_IS_ACTIVE (opt->cap)) { check(ERR, (status == SANE_STATUS_GOOD), "cannot set option [%d, %s] value, although it is active and settable (%s)", option_num, opt->name, sane_strstatus(status)); } else { check(ERR, (status == SANE_STATUS_INVAL), "was able to set option [%d, %s] value, although it is not active or settable", option_num, opt->name); } /* Get with invalid info. Since if is a get, info should be either * ignored or set to 0. */ info = 0xdeadbeef; guards_set(optval, optsize); status = sane_control_option (device, option_num, SANE_ACTION_GET_VALUE, optval, &info); guards_check(optval, optsize); if (SANE_OPTION_IS_GETTABLE (opt->cap)) { check(ERR, (status == SANE_STATUS_GOOD), "cannot get option [%d, %s] value, although it is active (%s)", option_num, opt->name, sane_strstatus(status)); } else { check(ERR, (status == SANE_STATUS_INVAL), "was able to get option [%d, %s] value, although it is not active", option_num, opt->name); } check(ERR, ((info == (SANE_Int)0xdeadbeef) || (info == 0)), "when getting option [%d, %s], info was set to %x", option_num, opt->name, info); /* Set with invalid info. Info should be reset by the backend. */ info = 0x10000; guards_set(optval, optsize); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, optval, &info); guards_check(optval, optsize); if (SANE_OPTION_IS_SETTABLE (opt->cap) && SANE_OPTION_IS_ACTIVE (opt->cap)) { check(ERR, (status == SANE_STATUS_GOOD), "cannot set option [%d, %s] value, although it is active and settable (%s)", option_num, opt->name, sane_strstatus(status)); check(ERR, ((info & ~(SANE_INFO_INEXACT | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS)) == 0), "sane_control_option set some wrong bit in info (%d)", info); if (info & SANE_INFO_RELOAD_PARAMS) { test_parameters(device, NULL); } } else { check(ERR, (status == SANE_STATUS_INVAL), "was able to set option [%d, %s] value, although it is not active or settable", option_num, opt->name); } /* Ask the backend to set the option automatically. */ guards_set(optval, optsize); status = sane_control_option (device, option_num, SANE_ACTION_SET_AUTO, optval, &info); guards_check(optval, optsize); if (SANE_OPTION_IS_SETTABLE (opt->cap) && SANE_OPTION_IS_ACTIVE (opt->cap) && (opt->cap & SANE_CAP_AUTOMATIC)) { check(ERR, (status == SANE_STATUS_GOOD), "cannot set the option [%d, %s] automatically.", option_num, opt->name); } else { check(ERR, (status != SANE_STATUS_GOOD), "was able to automatically set option [%d, %s], although it is not active or settable or automatically settable", option_num, opt->name); } if (info & SANE_INFO_RELOAD_PARAMS) { test_parameters(device, NULL); } } if (optval) { guards_free(optval); optval = NULL; } /* Some capabilities checks. */ check(ERR, ((opt->cap & (SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_SELECT)) != (SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_SELECT)), "option [%d, %s], SANE_CAP_HARD_SELECT and SANE_CAP_SOFT_SELECT are mutually exclusive", option_num, opt->name); if (opt->cap & SANE_CAP_SOFT_SELECT) { check(ERR, ((opt->cap & SANE_CAP_SOFT_DETECT) != 0), "option [%d, %s], SANE_CAP_SOFT_DETECT must be set if SANE_CAP_SOFT_SELECT is set", option_num, opt->name); } if ((opt->cap & (SANE_CAP_SOFT_SELECT | SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT)) == SANE_CAP_SOFT_DETECT) { check(ERR, (!SANE_OPTION_IS_SETTABLE (opt->cap)), "option [%d, %s], must not be settable", option_num, opt->name); } if (!SANE_OPTION_IS_SETTABLE (opt->cap)) { /* Unsettable option. Ignore the rest of the test. */ continue; } /* Check that will sane_control_option copy the string * parameter and not just store a pointer to it. */ if (opt->type == SANE_TYPE_STRING) { SANE_String val_string2; char *optstr; optstr = guards_malloc(opt->size); val_string2 = guards_malloc(opt->size); /* Poison the current value. */ strncpy(optstr, "-pOiSoN-", opt->size-1); optstr[opt->size-1] = 0; /* Get the value */ guards_set(optstr, opt->size); status = sane_control_option (device, option_num, SANE_ACTION_GET_VALUE, optstr, NULL); guards_check(optstr, opt->size); check(FATAL, (status == SANE_STATUS_GOOD), "cannot get option [%d, %s] value", option_num, opt->name); check(FATAL, (strcmp(optstr, "-pOiSoN-") != 0), "sane_control_option did not set a value"); /* Set the value */ guards_set(optstr, opt->size); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, optstr, NULL); guards_check(optstr, opt->size); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option [%d, %s] value", option_num, opt->name); /* Poison the returned value. */ strncpy(optstr, "-pOiSoN-", opt->size-1); optstr[opt->size-1] = 0; /* Read again the value and compare. */ guards_set(val_string2, opt->size); status = sane_control_option (device, option_num, SANE_ACTION_GET_VALUE, val_string2, NULL); guards_check(val_string2, opt->size); check(ERR, (status == SANE_STATUS_GOOD), "cannot get option [%d, %s] value", option_num, opt->name); check(FATAL, (strcmp(optstr, val_string2) != 0), "sane_control_option did not copy the string parameter for option [%d, %s]", option_num, opt->name); guards_free(optstr); guards_free(val_string2); } /* Try both boolean options. */ if (opt->type == SANE_TYPE_BOOL) { SANE_Bool org_v; SANE_Bool v; status = sane_control_option (device, option_num, SANE_ACTION_GET_VALUE, &org_v, &info); check(ERR, (status == SANE_STATUS_GOOD), "cannot get boolean option [%d, %s] value (%s)", option_num, opt->name, sane_strstatus(status)); /* Invert the condition. */ switch(org_v) { case SANE_FALSE: v = SANE_TRUE; break; case SANE_TRUE: v = SANE_FALSE; break; default: check(ERR, 0, "invalid boolean value %d for option [%d, %s]", org_v, option_num, opt->name); } /* Set the opposite of the current value. */ status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &v, &info); check(ERR, (status == SANE_STATUS_GOOD), "cannot set boolean option [%d, %s] value (%s)", option_num, opt->name, sane_strstatus(status)); check(ERR, (v != org_v), "boolean values should be different"); if (info & SANE_INFO_RELOAD_PARAMS) { test_parameters(device, NULL); } /* Set the initial value. */ v = org_v; status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &v, &info); check(ERR, (status == SANE_STATUS_GOOD), "cannot set boolean option [%d, %s] value (%s)", option_num, opt->name, sane_strstatus(status)); check(ERR, (v == org_v), "boolean values should be the same"); if (info & SANE_INFO_RELOAD_PARAMS) { test_parameters(device, NULL); } } /* Try to set an invalid option. */ switch(opt->type) { case SANE_TYPE_BOOL: { SANE_Word v; /* should be SANE_Bool instead */ v = -1; /* invalid value. must be SANE_FALSE or SANE_TRUE */ status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &v, NULL); check(ERR, (status != SANE_STATUS_GOOD), "was able to set an invalid value for boolean option [%d, %s]", option_num, opt->name); v = 2; /* invalid value. must be SANE_FALSE or SANE_TRUE */ status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &v, NULL); check(ERR, (status != SANE_STATUS_GOOD), "was able to set an invalid value for boolean option [%d, %s]", option_num, opt->name); } break; case SANE_TYPE_FIXED: case SANE_TYPE_INT: { SANE_Int *v; unsigned int i; v = guards_malloc(opt->size); /* I can only think of a test for * SANE_CONSTRAINT_RANGE. This tests the behaviour of * sanei_constrain_value(). */ if (opt->constraint_type == SANE_CONSTRAINT_RANGE) { for(i=0; isize / sizeof(SANE_Int); i++) v[i] = opt->constraint.range->min - 1; /* invalid range */ guards_set(v, opt->size); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, v, &info); guards_check(v, opt->size); check(ERR, (status == SANE_STATUS_GOOD && (info & SANE_INFO_INEXACT) ), "incorrect return when setting an invalid range value for option [%d, %s] (status %s, info %x)", option_num, opt->name, sane_strstatus(status), info); /* Set the corrected value. */ guards_set(v, opt->size); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, v, &info); guards_check(v, opt->size); check(ERR, (status == SANE_STATUS_GOOD && !(info & SANE_INFO_INEXACT) ), "incorrect return when setting an invalid range value for option [%d, %s] (status %s, info %x)", option_num, opt->name, sane_strstatus(status), info); for(i=0; isize / sizeof(SANE_Int); i++) v[i] = opt->constraint.range->max + 1; /* invalid range */ guards_set(v, opt->size); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, v, &info); guards_check(v, opt->size); check(ERR, (status == SANE_STATUS_GOOD && (info & SANE_INFO_INEXACT) ), "incorrect return when setting an invalid range value for option [%d, %s] (status %s, info %x)", option_num, opt->name, sane_strstatus(status), info); /* Set the corrected value. */ guards_set(v, opt->size); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, v, &info); guards_check(v, opt->size); check(ERR, (status == SANE_STATUS_GOOD && !(info & SANE_INFO_INEXACT) ), "incorrect return when setting a valid range value for option [%d, %s] (status %s, info %x)", option_num, opt->name, sane_strstatus(status), info); } guards_free(v); } break; default: break; } /* TODO: button */ /* * Here starts all the recursive stuff. After the test, it is * possible that the value is not settable nor active * anymore. */ /* Try to set every option in a list */ switch(opt->constraint_type) { case SANE_CONSTRAINT_WORD_LIST: check(FATAL, (opt->constraint.word_list != NULL), "no constraint list for option [%d, %s]", option_num, opt->name); test_options_word_list (device, option_num, opt, can_do_recursive); break; case SANE_CONSTRAINT_STRING_LIST: check(FATAL, (opt->constraint.string_list != NULL), "no constraint list for option [%d, %s]", option_num, opt->name); test_options_string_list (device, option_num, opt, can_do_recursive); break; case SANE_CONSTRAINT_RANGE: check(FATAL, (opt->constraint.range != NULL), "no constraint range for option [%d, %s]", option_num, opt->name); check(FATAL, (opt->constraint.range->max >= opt->constraint.range->min), "incorrect range for option [%d, %s] (min=%d > max=%d)", option_num, opt->name, opt->constraint.range->min, opt->constraint.range->max); /* Recurse. */ if (can_do_recursive) { test_options(device, can_do_recursive-1); } break; case SANE_CONSTRAINT_NONE: check(INF, (opt->constraint.range == NULL), "option [%d, %s] has some constraint value set", option_num, opt->name); /* Recurse. */ if (can_do_recursive) { test_options(device, can_do_recursive-1); } break; } /* End of the test for that option. */ } /* test random non-existing options. */ opt = sane_get_option_descriptor (device, -1); check(ERR, (opt == NULL), "was able to get option descriptor for option -1"); opt = sane_get_option_descriptor (device, num_dev_options+1); check(ERR, (opt == NULL), "was able to get option descriptor for option %d", num_dev_options+1); opt = sane_get_option_descriptor (device, num_dev_options+2); check(ERR, (opt == NULL), "was able to get option descriptor for option %d", num_dev_options+2); opt = sane_get_option_descriptor (device, num_dev_options+50); check(ERR, (opt == NULL), "was able to get option descriptor for option %d", num_dev_options+50); } /* Get an option descriptor by the name of the option. */ static const SANE_Option_Descriptor *get_optdesc_by_name(SANE_Handle device, const char *name, int *option_num) { const SANE_Option_Descriptor *opt; SANE_Int num_dev_options; SANE_Status status; /* Get the number of options. */ status = sane_control_option (device, 0, SANE_ACTION_GET_VALUE, &num_dev_options, 0); check(FATAL, (status == SANE_STATUS_GOOD), "cannot get option 0 value (%s)", sane_strstatus(status)); for (*option_num = 0; *option_num < num_dev_options; (*option_num)++) { /* Get the option descriptor */ opt = sane_get_option_descriptor (device, *option_num); check(FATAL, (opt != NULL), "cannot get option descriptor for option %d", *option_num); if (opt->name && strcmp(opt->name, name) == 0) { return(opt); } } return(NULL); } /* Set the first value for an option. That equates to the minimum for a * range or the first element in a list. */ static void set_min_value(SANE_Handle device, int option_num, const SANE_Option_Descriptor *opt) { SANE_Status status; SANE_String val_string; SANE_Int val_int; int rc; check(BUG, (SANE_OPTION_IS_SETTABLE(opt->cap)), "option is not settable"); switch(opt->constraint_type) { case SANE_CONSTRAINT_WORD_LIST: rc = check(ERR, (opt->constraint.word_list[0] > 0), "no value in the list for option %s", opt->name); if (!rc) return; val_int = opt->constraint.word_list[1]; status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to %d (%s)", opt->name, val_int, sane_strstatus(status)); break; case SANE_CONSTRAINT_STRING_LIST: rc = check(ERR, (opt->constraint.string_list[0] != NULL), "no value in the list for option %s", opt->name); if (!rc) return; val_string = strdup(opt->constraint.string_list[0]); assert(val_string); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, val_string, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to [%s] (%s)", opt->name, val_string, sane_strstatus(status)); free(val_string); break; case SANE_CONSTRAINT_RANGE: val_int = opt->constraint.range->min; status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to %d (%s)", opt->name, val_int, sane_strstatus(status)); break; default: abort(); } } /* Set the last value for an option. That equates to the maximum for a * range or the last element in a list. */ static void set_max_value(SANE_Handle device, int option_num, const SANE_Option_Descriptor *opt) { SANE_Status status; SANE_String val_string; SANE_Int val_int; int i; int rc; check(BUG, (SANE_OPTION_IS_SETTABLE(opt->cap)), "option is not settable"); switch(opt->constraint_type) { case SANE_CONSTRAINT_WORD_LIST: rc = check(ERR, (opt->constraint.word_list[0] > 0), "no value in the list for option %s", opt->name); if (!rc) return; val_int = opt->constraint.word_list[opt->constraint.word_list[0]]; status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to %d (%s)", opt->name, val_int, sane_strstatus(status)); break; case SANE_CONSTRAINT_STRING_LIST: rc = check(ERR, (opt->constraint.string_list[0] != NULL), "no value in the list for option %s", opt->name); if (!rc) return; for (i=1; opt->constraint.string_list[i] != NULL; i++); val_string = strdup(opt->constraint.string_list[i-1]); assert(val_string); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, val_string, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to [%s] (%s)", opt->name, val_string, sane_strstatus(status)); free(val_string); break; case SANE_CONSTRAINT_RANGE: val_int = opt->constraint.range->max; status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to %d (%s)", opt->name, val_int, sane_strstatus(status)); break; default: abort(); } } /* Set a random value for an option amongst the possible values. */ static void set_random_value(SANE_Handle device, int option_num, const SANE_Option_Descriptor *opt) { SANE_Status status; SANE_String val_string; SANE_Int val_int; int i; int rc; check(BUG, (SANE_OPTION_IS_SETTABLE(opt->cap)), "option is not settable"); switch(opt->constraint_type) { case SANE_CONSTRAINT_WORD_LIST: rc = check(ERR, (opt->constraint.word_list[0] > 0), "no value in the list for option %s", opt->name); if (!rc) return; i=1+(rand() % opt->constraint.word_list[0]); val_int = opt->constraint.word_list[i]; status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to %d (%s)", opt->name, val_int, sane_strstatus(status)); break; case SANE_CONSTRAINT_STRING_LIST: rc = check(ERR, (opt->constraint.string_list[0] != NULL), "no value in the list for option %s", opt->name); if (!rc) return; for (i=0; opt->constraint.string_list[i] != NULL; i++); i = rand() % i; val_string = strdup(opt->constraint.string_list[0]); assert(val_string); status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, val_string, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to [%s] (%s)", opt->name, val_string, sane_strstatus(status)); free(val_string); break; case SANE_CONSTRAINT_RANGE: i = opt->constraint.range->max - opt->constraint.range->min; i = rand() % i; val_int = opt->constraint.range->min + i; status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int, NULL); check(ERR, (status == SANE_STATUS_GOOD), "cannot set option %s to %d (%s)", opt->name, val_int, sane_strstatus(status)); break; default: abort(); } } /*--------------------------------------------------------------------------*/ /* Returns a string with the value of an option. */ static char *get_option_value(SANE_Handle device, const char *option_name) { const SANE_Option_Descriptor *opt; void *optval; /* value for the option */ int optnum; static char str[100]; SANE_Status status; opt = get_optdesc_by_name(device, option_name, &optnum); if (opt) { optval = guards_malloc(opt->size); status = sane_control_option (device, optnum, SANE_ACTION_GET_VALUE, optval, NULL); if (status == SANE_STATUS_GOOD) { switch(opt->type) { case SANE_TYPE_BOOL: if (*(SANE_Word*) optval == SANE_FALSE) { strcpy(str, "FALSE"); } else { strcpy(str, "TRUE"); } break; case SANE_TYPE_INT: sprintf(str, "%d", *(SANE_Word*) optval); break; case SANE_TYPE_FIXED: { int i; i = SANE_UNFIX(*(SANE_Word*) optval); sprintf(str, "%d", i); } break; case SANE_TYPE_STRING: strcpy(str, optval); break; default: str[0] = 0; } } else { /* Shouldn't happen. */ strcpy(str, "backend default"); } guards_free(optval); } else { /* The option does not exists. */ strcpy(str, "backend default"); } return(str); } /* Display the parameters that used for a scan. */ static char *display_scan_parameters(SANE_Handle device) { static char str[150]; char *p = str; *p = 0; p += sprintf(p, "scan mode=[%s] ", get_option_value(device, SANE_NAME_SCAN_MODE)); p += sprintf(p, "resolution=[%s] ", get_option_value(device, SANE_NAME_SCAN_RESOLUTION)); p += sprintf(p, "tl_x=[%s] ", get_option_value(device, SANE_NAME_SCAN_TL_X)); p += sprintf(p, "tl_y=[%s] ", get_option_value(device, SANE_NAME_SCAN_TL_Y)); p += sprintf(p, "br_x=[%s] ", get_option_value(device, SANE_NAME_SCAN_BR_X)); p += sprintf(p, "br_y=[%s] ", get_option_value(device, SANE_NAME_SCAN_BR_Y)); return(str); } /* Do a scan to test the correctness of the backend. */ static void test_scan(SANE_Handle device) { const SANE_Option_Descriptor *opt; SANE_Status status; int option_num; SANE_Int val_int; unsigned char *image = NULL; SANE_Parameters params; size_t to_read; SANE_Int len=0; int ask_len; int rc; int fd; /* Set the largest scan possible. * * For that test, the corner * position must exists and be SANE_CONSTRAINT_RANGE (this is not * a SANE requirement though). */ opt = get_optdesc_by_name(device, SANE_NAME_SCAN_TL_X, &option_num); if (opt) set_min_value(device, option_num, opt); opt = get_optdesc_by_name(device, SANE_NAME_SCAN_TL_Y, &option_num); if (opt) set_min_value(device, option_num, opt); opt = get_optdesc_by_name(device, SANE_NAME_SCAN_BR_X, &option_num); if (opt) set_max_value(device, option_num, opt); opt = get_optdesc_by_name(device, SANE_NAME_SCAN_BR_Y, &option_num); if (opt) set_max_value(device, option_num, opt); #define IMAGE_SIZE (512 * 1024) image = guards_malloc(IMAGE_SIZE); /* Try a read outside of a scan. */ status = sane_read (device, image, len, &len); check(ERR, (status != SANE_STATUS_GOOD), "it is possible to sane_read outside of a scan"); /* Try to set the I/O mode outside of a scan. */ status = sane_set_io_mode (device, SANE_FALSE); check(ERR, (status == SANE_STATUS_INVAL), "it is possible to sane_set_io_mode outside of a scan"); status = sane_set_io_mode (device, SANE_TRUE); check(ERR, (status == SANE_STATUS_INVAL || status == SANE_STATUS_UNSUPPORTED), "it is possible to sane_set_io_mode outside of a scan"); /* Test sane_get_select_fd outside of a scan. */ status = sane_get_select_fd(device, &fd); check(ERR, (status == SANE_STATUS_INVAL || status == SANE_STATUS_UNSUPPORTED), "sane_get_select_fd outside of a scan returned an invalid status (%s)", sane_strstatus (status)); if (test_level > 2) { /* Do a scan, reading byte per byte */ check(MSG, 0, "TEST: scan byte per byte - %s", display_scan_parameters(device)); test_parameters(device, ¶ms); status = sane_start (device); rc = check(ERR, (status == SANE_STATUS_GOOD), "cannot start the scan (%s)", sane_strstatus (status)); if (!rc) goto the_end; /* sane_set_io_mode with SANE_FALSE is always supported. */ status = sane_set_io_mode (device, SANE_FALSE); check(ERR, (status == SANE_STATUS_GOOD), "sane_set_io_mode with SANE_FALSE must return SANE_STATUS_GOOD"); /* test sane_set_io_mode with SANE_TRUE. */ status = sane_set_io_mode (device, SANE_TRUE); check(ERR, (status == SANE_STATUS_GOOD || status == SANE_STATUS_UNSUPPORTED), "sane_set_io_mode with SANE_TRUE returned an invalid status (%s)", sane_strstatus (status)); /* Put the backend back into blocking mode. */ status = sane_set_io_mode (device, SANE_FALSE); check(ERR, (status == SANE_STATUS_GOOD), "sane_set_io_mode with SANE_FALSE must return SANE_STATUS_GOOD"); /* Test sane_get_select_fd */ fd = 0x76575; /* won't exists */ status = sane_get_select_fd(device, &fd); check(ERR, (status == SANE_STATUS_GOOD || status == SANE_STATUS_UNSUPPORTED), "sane_get_select_fd returned an invalid status (%s)", sane_strstatus (status)); if (status == SANE_STATUS_GOOD) { check(ERR, (fd != 0x76575), "sane_get_select_fd didn't set the fd although it should have"); check(ERR, (fd >= 0), "sane_get_select_fd returned an invalid fd"); } /* Check that it is not possible to set an option. It is probably * a requirement stated indirectly in the section 4.4 on code * flow. */ status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int , NULL); check(WRN, (status != SANE_STATUS_GOOD), "it is possible to set a value during a scan"); test_parameters(device, ¶ms); if (params.bytes_per_line != 0 && params.lines != 0) { to_read = params.bytes_per_line * params.lines; while(SANE_TRUE) { len = 76457645; /* garbage */ guards_set(image, 1); status = sane_read (device, image, 1, &len); guards_check(image, 1); if (status == SANE_STATUS_EOF) { /* End of scan */ check(ERR, (len == 0), "the length returned is not 0"); break; } rc = check(ERR, (status == SANE_STATUS_GOOD), "scan stopped - status is %s", sane_strstatus (status)); if (!rc) { check(ERR, (len == 0), "the length returned is not 0"); break; } /* The scanner can only return 1. If it returns 0, we may * loop forever. */ rc = check(ERR, (len == 1), "backend returned 0 bytes - skipping test"); if (!rc) { break; } to_read -= len; } if (params.lines != -1) { check(ERR, (to_read == 0), "scan ended, but data was truncated"); } } sane_cancel(device); } /* Try a read outside a scan. */ ask_len = 1; guards_set(image, ask_len); status = sane_read (device, image, ask_len, &len); guards_check(image, ask_len); check(ERR, (status != SANE_STATUS_GOOD), "it is possible to sane_read outside a scan"); /* * Do a partial scan */ check(MSG, 0, "TEST: partial scan - %s", display_scan_parameters(device)); status = sane_start (device); rc = check(ERR, (status == SANE_STATUS_GOOD), "cannot start the scan (%s)", sane_strstatus (status)); if (!rc) goto the_end; test_parameters(device, ¶ms); if (params.bytes_per_line != 0 && params.lines != 0) { len = 10; guards_set(image, 1); status = sane_read (device, image, 1, &len); guards_check(image, 1); check(ERR, (len == 1), "sane_read() didn't return 1 byte as requested"); } sane_cancel(device); /* * Do a scan, reading random length. */ check(MSG, 0, "TEST: scan random length - %s", display_scan_parameters(device)); test_parameters(device, ¶ms); /* Try a read outside a scan. */ ask_len = 20; guards_set(image, ask_len); status = sane_read (device, image, ask_len, &len); guards_check(image, ask_len); check(ERR, (status != SANE_STATUS_GOOD), "it is possible to sane_read outside a scan"); status = sane_start (device); rc = check(ERR, (status == SANE_STATUS_GOOD), "cannot start the scan (%s)", sane_strstatus (status)); if (!rc) goto the_end; /* Check that it is not possible to set an option. */ status = sane_control_option (device, option_num, SANE_ACTION_SET_VALUE, &val_int , NULL); check(WRN, (status != SANE_STATUS_GOOD), "it is possible to set a value during a scan"); test_parameters(device, ¶ms); if (params.bytes_per_line != 0 && params.lines != 0) { to_read = params.bytes_per_line * params.lines; srandom(time(NULL)); while (SANE_TRUE) { ask_len = rand() & 0x7ffff; /* 0 to 512K-1 */ if (ask_len == 0) len = 1; len = ask_len + 4978; /* garbage */ guards_set(image, ask_len); status = sane_read (device, image, ask_len, &len); guards_check(image, ask_len); if (status == SANE_STATUS_EOF) { /* End of scan */ check(ERR, (len == 0), "the length returned is not 0"); break; } rc = check(ERR, (status == SANE_STATUS_GOOD), "scan stopped - status is %s", sane_strstatus (status)); if (!rc) { check(ERR, (len == 0), "the length returned is not 0"); break; } /* The scanner cannot return 0. If it returns 0, we may * loop forever. */ rc = check(ERR, (len > 0), "backend didn't return any data - skipping test"); if (!rc) { break; } rc = check(ERR, (len <= ask_len), "backend returned too much data (%d / %d) - skipping test", len, ask_len); if (!rc) { break; } to_read -= len; } if (params.lines != -1) { check(ERR, (to_read == 0), "scan ended, but data was truncated"); } } sane_cancel(device); /* Try a read outside a scan. */ ask_len = 30; guards_set(image, ask_len); status = sane_read (device, image, ask_len, &len); guards_check(image, ask_len); check(ERR, (status != SANE_STATUS_GOOD), "it is possible to sane_read outside a scan"); /* * Do a scan with a fixed size and a big buffer */ check(MSG, 0, "TEST: scan with a big max_len - %s", display_scan_parameters(device)); test_parameters(device, ¶ms); status = sane_start (device); rc = check(ERR, (status == SANE_STATUS_GOOD), "cannot start the scan (%s)", sane_strstatus (status)); if (!rc) goto the_end; test_parameters(device, ¶ms); if (params.bytes_per_line != 0 && params.lines != 0) { to_read = params.bytes_per_line * params.lines; while(SANE_TRUE) { ask_len = IMAGE_SIZE; len = rand(); /* garbage */ guards_set(image, ask_len); status = sane_read (device, image, ask_len, &len); guards_check(image, ask_len); if (status == SANE_STATUS_EOF) { /* End of scan */ check(ERR, (len == 0), "the length returned is not 0"); break; } rc = check(ERR, (status == SANE_STATUS_GOOD), "scan stopped - status is %s", sane_strstatus (status)); if (!rc) { check(ERR, (len == 0), "the length returned is not 0"); break; } /* If the scanner return 0, we may loop forever. */ rc = check(ERR, (len > 0), "backend didn't return any data - skipping test"); if (!rc) { break; } rc = check(ERR, (len <= ask_len), "backend returned too much data (%d / %d) - skipping test", len, ask_len); if (!rc) { break; } to_read -= len; } if (params.lines != -1) { check(ERR, (to_read == 0), "scan ended, but data was truncated"); } } sane_cancel(device); the_end: if (image) guards_free(image); } /* Do several scans at different scan mode and resolution. */ static void test_scans(SANE_Device * device) { const SANE_Option_Descriptor *scan_mode_opt; const SANE_Option_Descriptor *resolution_mode_opt; SANE_Status status; int scan_mode_optnum; int resolution_mode_optnum; SANE_String val_string; int i; int rc; /* For that test, the requirements are: * SANE_NAME_SCAN_MODE exists and is a SANE_CONSTRAINT_STRING_LIST * SANE_NAME_SCAN_RESOLUTION exists and is either a SANE_CONSTRAINT_WORD_LIST or a SANE_CONSTRAINT_RANGE. * * These are not a SANE requirement, though. */ scan_mode_opt = get_optdesc_by_name(device, SANE_NAME_SCAN_MODE, &scan_mode_optnum); if (scan_mode_opt) { rc = check(INF, (scan_mode_opt->type == SANE_TYPE_STRING), "option [%s] is not a SANE_TYPE_STRING - skipping test", SANE_NAME_SCAN_MODE); if (!rc) return; rc = check(INF, (scan_mode_opt->constraint_type == SANE_CONSTRAINT_STRING_LIST), "constraint for option [%s] is not SANE_CONSTRAINT_STRING_LIST - skipping test", SANE_NAME_SCAN_MODE); if (!rc) return; rc = check(INF, (SANE_OPTION_IS_SETTABLE(scan_mode_opt->cap)), "option [%s] is not settable - skipping test", SANE_NAME_SCAN_MODE); if (!rc) return; } resolution_mode_opt = get_optdesc_by_name(device, SANE_NAME_SCAN_RESOLUTION, &resolution_mode_optnum); if (resolution_mode_opt) { rc = check(INF, (SANE_OPTION_IS_SETTABLE(resolution_mode_opt->cap)), "option [%s] is not settable - skipping test", SANE_NAME_SCAN_RESOLUTION); if (!rc) return; } if (scan_mode_opt) { /* Do several scans, with several resolution. */ for (i=0; scan_mode_opt->constraint.string_list[i] != NULL; i++) { val_string = strdup(scan_mode_opt->constraint.string_list[i]); assert(val_string); status = sane_control_option (device, scan_mode_optnum, SANE_ACTION_SET_VALUE, val_string, NULL); check(FATAL, (status == SANE_STATUS_GOOD), "cannot set a settable option (status=%s)", sane_strstatus(status)); free(val_string); if (resolution_mode_opt) { set_min_value(device, resolution_mode_optnum, resolution_mode_opt); test_scan(device); set_max_value(device, resolution_mode_optnum, resolution_mode_opt); test_scan(device); set_random_value(device, resolution_mode_optnum, resolution_mode_opt); test_scan(device); } else { test_scan(device); } } } else { if (resolution_mode_opt) { set_min_value(device, resolution_mode_optnum, resolution_mode_opt); test_scan(device); set_max_value(device, resolution_mode_optnum, resolution_mode_opt); test_scan(device); set_random_value(device, resolution_mode_optnum, resolution_mode_opt); test_scan(device); } else { test_scan(device); } } } /** test sane_get_devices * test sane_get_device function, if time is greter than 0, * loop to let tester plug/unplug device to check for correct * hotplug detection * @param device_list device list to fill * @param time time to loop * @return 0 on success */ static int test_get_devices(const SANE_Device ***device_list, int time) { int loop=0; int i; const SANE_Device *dev; SANE_Status status; status = sane_get_devices (device_list, SANE_TRUE); check(FATAL, (status == SANE_STATUS_GOOD), "sane_get_devices() failed (%s)", sane_strstatus (status)); /* Verify that the SANE doc (or tstbackend) is up to date */ for (i=0; (*device_list)[i] != NULL; i++) { dev = (*device_list)[i]; check(FATAL, (dev->name != NULL), "device name is NULL"); check(FATAL, (dev->vendor != NULL), "device vendor is NULL"); check(FATAL, (dev->type != NULL), "device type is NULL"); check(FATAL, (dev->model != NULL), "device model is NULL"); check(INF, ((strcmp(dev->type, "flatbed scanner") == 0) || (strcmp(dev->type, "frame grabber") == 0) || (strcmp(dev->type, "handheld scanner") == 0) || (strcmp(dev->type, "still camera") == 0) || (strcmp(dev->type, "video camera") == 0) || (strcmp(dev->type, "virtual device") == 0) || (strcmp(dev->type, "film scanner") == 0) || (strcmp(dev->type, "multi-function peripheral") == 0) || (strcmp(dev->type, "sheetfed scanner") == 0)), "unknown device type [%s]. Update SANE doc section \"Type Strings\"", dev->type); check(INF, ( (strcmp(dev->vendor, "AGFA") == 0) || (strcmp(dev->vendor, "Abaton") == 0) || (strcmp(dev->vendor, "Acer") == 0) || (strcmp(dev->vendor, "Apple") == 0) || (strcmp(dev->vendor, "Artec") == 0) || (strcmp(dev->vendor, "Avision") == 0) || (strcmp(dev->vendor, "CANON") == 0) || (strcmp(dev->vendor, "Connectix") == 0) || (strcmp(dev->vendor, "Epson") == 0) || (strcmp(dev->vendor, "Fujitsu") == 0) || (strcmp(dev->vendor, "Gphoto2") == 0) || (strcmp(dev->vendor, "Hewlett-Packard") == 0) || (strcmp(dev->vendor, "IBM") == 0) || (strcmp(dev->vendor, "Kodak") == 0) || (strcmp(dev->vendor, "Lexmark") == 0) || (strcmp(dev->vendor, "Logitech") == 0) || (strcmp(dev->vendor, "Microtek") == 0) || (strcmp(dev->vendor, "Minolta") == 0) || (strcmp(dev->vendor, "Mitsubishi") == 0) || (strcmp(dev->vendor, "Mustek") == 0) || (strcmp(dev->vendor, "NEC") == 0) || (strcmp(dev->vendor, "Nikon") == 0) || (strcmp(dev->vendor, "Noname") == 0) || (strcmp(dev->vendor, "Plustek") == 0) || (strcmp(dev->vendor, "Polaroid") == 0) || (strcmp(dev->vendor, "Relisys") == 0) || (strcmp(dev->vendor, "Ricoh") == 0) || (strcmp(dev->vendor, "Sharp") == 0) || (strcmp(dev->vendor, "Siemens") == 0) || (strcmp(dev->vendor, "Tamarack") == 0) || (strcmp(dev->vendor, "UMAX") == 0)), "unknown device vendor [%s]. Update SANE doc section \"Vendor Strings\"", dev->vendor); } /* loop on detecting device to let time to plug/unplug scanners */ while(loopvendor, dev->name, dev->type, dev->model); } if(i==0) { check(MSG, 0, "\tnone..."); } sleep(1); (*device_list) = NULL; status = sane_get_devices (device_list, SANE_TRUE); check(FATAL, (status == SANE_STATUS_GOOD), "sane_get_devices() failed (%s)", sane_strstatus (status)); loop++; } return 0; } /** test test_default * test by scanning using default values * @param device device to use for the scan */ static void test_default(SANE_Device * device) { test_scan(device); } static void usage(const char *execname) { printf("Usage: %s [-d backend_name] [-l test_level] [-s] [-r recursion_level] [-g time (s)]\n", execname); printf("\t-v\tverbose level\n"); printf("\t-d\tbackend name\n"); printf("\t-l\tlevel of testing (0=some, 1=0+options, 2=1+scans, 3=longest tests)\n"); printf("\t-s\tdo a scan during open/close tests\n"); printf("\t-r\trecursion level for option testing (the higher, the longer)\n"); printf("\t-g\ttime to loop on sane_get_devices function to test scannet hotplug detection (time is in seconds).\n"); } int main (int argc, char **argv) { char *devname = NULL; SANE_Status status; SANE_Int version_code; SANE_Handle device; int ch; int index; int i; const SANE_Device **device_list; int rc; int recursion_level; int time; int default_scan; printf("tstbackend, Copyright (C) 2002 Frank Zago\n"); printf("tstbackend comes with ABSOLUTELY NO WARRANTY\n"); printf("This is free software, and you are welcome to redistribute it\n"); printf("under certain conditions. See COPYING file for details\n\n"); printf("This is tstbackend build %d\n\n", BUILD); /* Read the command line options. */ opterr = 0; recursion_level = 5; /* 5 levels or recursion should be enough */ test_level = 0; /* basic tests only */ time = 0; /* no get devices loop */ default_scan = 0; while ((ch = getopt_long (argc, argv, "-v:d:l:r:g:h:s", basic_options, &index)) != EOF) { switch(ch) { case 'v': verbose_level = atoi(optarg); break; case 'd': devname = strdup(optarg); break; case 'l': test_level = atoi(optarg); if (test_level < 0 || test_level > 4) { fprintf(stderr, "invalid test_level\n"); return(1); } break; case 's': default_scan = 1; break; case 'r': recursion_level = atoi(optarg); break; case 'g': time = atoi(optarg); break; case 'h': usage(argv[0]); return(0); case '?': fprintf(stderr, "invalid option\n"); return(1); default: fprintf(stderr, "bug in tstbackend\n"); return(1); } } /* First test */ check(MSG, 0, "TEST: init/exit"); for (i=0; i<10; i++) { /* Test 1. init/exit with a version code */ status = sane_init(&version_code, NULL); check(FATAL, (status == SANE_STATUS_GOOD), "sane_init failed with %s", sane_strstatus (status)); check(FATAL, (SANE_VERSION_MAJOR(version_code) == 1), "invalid SANE version linked"); sane_exit(); /* Test 2. init/exit without a version code */ status = sane_init(NULL, NULL); check(FATAL, (status == SANE_STATUS_GOOD), "sane_init failed with %s", sane_strstatus (status)); sane_exit(); /* Test 3. Init/get_devices/open invalid/exit */ status = sane_init(NULL, NULL); check(FATAL, (status == SANE_STATUS_GOOD), "sane_init failed with %s", sane_strstatus (status)); status = sane_get_devices (&device_list, SANE_TRUE); check(FATAL, (status == SANE_STATUS_GOOD), "sane_get_devices() failed (%s)", sane_strstatus (status)); status = sane_open ("opihndvses75bvt6fg", &device); check(WRN, (status == SANE_STATUS_INVAL), "sane_open() failed (%s)", sane_strstatus (status)); if (status == SANE_STATUS_GOOD) sane_close(device); sane_exit(); /* Test 4. Init/get_devices/open default/exit */ status = sane_init(NULL, NULL); check(FATAL, (status == SANE_STATUS_GOOD), "sane_init failed with %s", sane_strstatus (status)); status = sane_get_devices (&device_list, SANE_TRUE); check(FATAL, (status == SANE_STATUS_GOOD), "sane_get_devices() failed (%s)", sane_strstatus (status)); status = sane_open ("", &device); if (status == SANE_STATUS_GOOD) sane_close(device); sane_exit(); } status = sane_init (&version_code, NULL); check(FATAL, (status == SANE_STATUS_GOOD), "sane_init failed with %s", sane_strstatus (status)); /* Check the device list */ rc = test_get_devices(&device_list, time); if (rc) goto the_exit; if (!devname) { /* If no device name was specified explicitly, we look at the environment variable SANE_DEFAULT_DEVICE. If this variable is not set, we open the first device we find (if any): */ devname = getenv ("SANE_DEFAULT_DEVICE"); if (devname) devname = strdup(devname); } if (!devname) { if (device_list[0]) { devname = strdup(device_list[0]->name); } } rc = check(ERR, (devname != NULL), "no SANE devices found"); if (!rc) goto the_exit; check(MSG, 0, "using device %s", devname); /* Test open close */ check(MSG, 0, "TEST: open/close"); for (i=0; i<10; i++) { status = sane_open (devname, &device); rc = check(ERR, (status == SANE_STATUS_GOOD), "sane_open failed with %s for device %s", sane_strstatus (status), devname); if (!rc) goto the_exit; if (default_scan) { test_default (device); } sane_close (device); } if (test_level < 1) { sane_exit(); goto the_exit; } /* Test options */ check(MSG, 0, "TEST: options consistency"); status = sane_open (devname, &device); check(FATAL, (status == SANE_STATUS_GOOD), "sane_open failed with %s for device %s", sane_strstatus (status), devname); test_parameters(device, NULL); test_options(device, recursion_level); sane_close (device); sane_exit(); if (test_level < 2) { goto the_exit; } /* Test scans */ check(MSG, 0, "TEST: scan test"); status = sane_init (&version_code, NULL); check(FATAL, (status == SANE_STATUS_GOOD), "sane_init failed with %s", sane_strstatus (status)); status = sane_open (devname, &device); check(FATAL, (status == SANE_STATUS_GOOD), "sane_open failed with %s for device %s", sane_strstatus (status), devname); test_scans(device); sane_close (device); sane_exit(); the_exit: if (devname) free(devname); display_stats(); return(0); } sane-backends-1.0.27/frontend/Makefile.am0000664000175000017500000000175513106201017015074 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. EXTRA_PROGRAMS = test tstbackend bin_PROGRAMS = scanimage if COMPILE_SANED sbin_PROGRAMS = saned else EXTRA_PROGRAMS += saned endif AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include scanimage_SOURCES = scanimage.c sicc.c sicc.h stiff.c stiff.h scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ $(PNG_LIBS) $(JPEG_LIBS) saned_SOURCES = saned.c saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \ $(SYSLOG_LIBS) $(SYSTEMD_LIBS) $(AVAHI_LIBS) test_SOURCES = test.c test_LDADD = ../lib/liblib.la ../backend/libsane.la tstbackend_SOURCES = tstbackend.c tstbackend_LDADD = ../lib/liblib.la ../backend/libsane.la clean-local: rm -f test tstbackend sane-backends-1.0.27/frontend/stiff.c0000664000175000017500000003564613106201017014325 00000000000000/* Create SANE/tiff headers TIFF interfacing routines for SANE Copyright (C) 2000 Peter Kirchgessner Copyright (C) 2002 Oliver Rauch: added tiff ICC profile Copyright (C) 2017 Aaron Muir Hamilton This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Changes: 2000-11-19, PK: Color TIFF-header: write 3 values for bits per sample 2001-12-16, PK: Write fill order tag for b/w-images 2002-08-27, OR: Added tiff tag for ICC profile 2017-04-16, AMH: Separate ICC profile loading into a separate file */ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include #include #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "sicc.h" #include "stiff.h" typedef struct { int tag, typ, nvals, val; } IFD_ENTRY; typedef struct { int maxtags; int ntags; IFD_ENTRY *ifde; } IFD; #define IFDE_TYP_BYTE (1) #define IFDE_TYP_ASCII (2) #define IFDE_TYP_SHORT (3) #define IFDE_TYP_LONG (4) #define IFDE_TYP_RATIONAL (5) static IFD * create_ifd (void) { IFD *ifd; int maxtags = 10; ifd = (IFD *)malloc (sizeof (IFD)); if (ifd == NULL) return NULL; ifd->ifde = (IFD_ENTRY *)malloc (maxtags * sizeof (IFD_ENTRY)); if (ifd->ifde == NULL) { free (ifd); return NULL; } ifd->ntags = 0; ifd->maxtags = maxtags; return ifd; } static void free_ifd (IFD *ifd) { if (ifd == NULL) return; if (ifd->ifde != NULL) { free (ifd->ifde); ifd->ifde = NULL; } free (ifd); ifd = NULL; } static void add_ifd_entry (IFD *ifd, int tag, int typ, int nvals, int val) { IFD_ENTRY *ifde; int add_entries = 10; if (ifd == NULL) return; if (ifd->ntags == ifd->maxtags) { ifde = (IFD_ENTRY *)realloc (ifd->ifde, (ifd->maxtags+add_entries)*sizeof (IFD_ENTRY)); if (ifde == NULL) return; ifd->ifde = ifde; ifd->maxtags += add_entries; } ifde = &(ifd->ifde[ifd->ntags]); ifde->tag = tag; ifde->typ = typ; ifde->nvals = nvals; ifde->val = val; (ifd->ntags)++; } static void write_i2 (FILE *fptr, int val, int motorola) { if (motorola) { putc ((val >> 8) & 0xff, fptr); putc (val & 0xff, fptr); } else { putc (val & 0xff, fptr); putc ((val >> 8) & 0xff, fptr); } } static void write_i4 (FILE *fptr, int val, int motorola) { if (motorola) { putc ((val >> 24) & 0xff, fptr); putc ((val >> 16) & 0xff, fptr); putc ((val >> 8) & 0xff, fptr); putc (val & 0xff, fptr); } else { putc (val & 0xff, fptr); putc ((val >> 8) & 0xff, fptr); putc ((val >> 16) & 0xff, fptr); putc ((val >> 24) & 0xff, fptr); } } static void write_ifd (FILE *fptr, IFD *ifd, int motorola) {int k; IFD_ENTRY *ifde; if (!ifd) return; if (motorola) putc ('M', fptr), putc ('M', fptr); else putc ('I', fptr), putc ('I', fptr); write_i2 (fptr, 42, motorola); /* Magic */ write_i4 (fptr, 8, motorola); /* Offset to first IFD */ write_i2 (fptr, ifd->ntags, motorola); for (k = 0; k < ifd->ntags; k++) { ifde = &(ifd->ifde[k]); write_i2 (fptr, ifde->tag, motorola); write_i2 (fptr, ifde->typ, motorola); write_i4 (fptr, ifde->nvals, motorola); if ((ifde->typ == IFDE_TYP_SHORT) && (ifde->nvals == 1)) { write_i2 (fptr, ifde->val, motorola); write_i2 (fptr, 0, motorola); } else { write_i4 (fptr, ifde->val, motorola); } } write_i4 (fptr, 0, motorola); /* End of IFD chain */ } static void write_tiff_bw_header (FILE *fptr, int width, int height, int resolution) {IFD *ifd; int header_size = 8, ifd_size; int strip_offset, data_offset, data_size; int strip_bytecount; int ntags; int motorola; ifd = create_ifd (); strip_bytecount = ((width+7)/8) * height; /* the following values must be known in advance */ ntags = 12; data_size = 0; if (resolution > 0) { ntags += 3; data_size += 2*4 + 2*4; } ifd_size = 2 + ntags*12 + 4; data_offset = header_size + ifd_size; strip_offset = data_offset + data_size; /* New subfile type */ add_ifd_entry (ifd, 254, IFDE_TYP_LONG, 1, 0); /* image width */ add_ifd_entry (ifd, 256, (width > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT, 1, width); /* image length */ add_ifd_entry (ifd, 257, (height > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT, 1, height); /* bits per sample */ add_ifd_entry (ifd, 258, IFDE_TYP_SHORT, 1, 1); /* compression (uncompressed) */ add_ifd_entry (ifd, 259, IFDE_TYP_SHORT, 1, 1); /* photometric interpretation */ add_ifd_entry (ifd, 262, IFDE_TYP_SHORT, 1, 0); /* fill order */ add_ifd_entry (ifd, 266, IFDE_TYP_SHORT, 1, 1); /* strip offset */ add_ifd_entry (ifd, 273, IFDE_TYP_LONG, 1, strip_offset); /* orientation */ add_ifd_entry (ifd, 274, IFDE_TYP_SHORT, 1, 1); /* samples per pixel */ add_ifd_entry (ifd, 277, IFDE_TYP_SHORT, 1, 1); /* rows per strip */ add_ifd_entry (ifd, 278, IFDE_TYP_LONG, 1, height); /* strip bytecount */ add_ifd_entry (ifd, 279, IFDE_TYP_LONG, 1, strip_bytecount); if (resolution > 0) { /* x resolution */ add_ifd_entry (ifd, 282, IFDE_TYP_RATIONAL, 1, data_offset); data_offset += 2*4; /* y resolution */ add_ifd_entry (ifd, 283, IFDE_TYP_RATIONAL, 1, data_offset); data_offset += 2*4; } if (resolution > 0) { /* resolution unit (dpi) */ add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2); } /* I prefer motorola format. Its human readable. */ motorola = 1; write_ifd (fptr, ifd, motorola); /* Write x/y resolution */ if (resolution > 0) { write_i4 (fptr, resolution, motorola); write_i4 (fptr, 1, motorola); write_i4 (fptr, resolution, motorola); write_i4 (fptr, 1, motorola); } free_ifd (ifd); } static void write_tiff_grey_header (FILE *fptr, int width, int height, int depth, int resolution, const char *icc_profile) {IFD *ifd; int header_size = 8, ifd_size; int strip_offset, data_offset, data_size; int strip_bytecount; int ntags; int motorola, bps, maxsamplevalue; void *icc_buffer = NULL; size_t icc_size = 0; if (icc_profile) { icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size); } ifd = create_ifd (); bps = (depth <= 8) ? 1 : 2; /* Bytes per sample */ maxsamplevalue = (depth <= 8) ? 255 : 65535; strip_bytecount = width * height * bps; /* the following values must be known in advance */ ntags = 13; data_size = 0; if (resolution > 0) { ntags += 3; data_size += 2*4 + 2*4; } if (icc_size > 0) /* if icc profile exists add memory for tag */ { ntags += 1; data_size += icc_size; } ifd_size = 2 + ntags*12 + 4; data_offset = header_size + ifd_size; strip_offset = data_offset + data_size; /* New subfile type */ add_ifd_entry (ifd, 254, IFDE_TYP_LONG, 1, 0); /* image width */ add_ifd_entry (ifd, 256, (width > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT, 1, width); /* image length */ add_ifd_entry (ifd, 257, (height > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT, 1, height); /* bits per sample */ add_ifd_entry (ifd, 258, IFDE_TYP_SHORT, 1, depth); /* compression (uncompressed) */ add_ifd_entry (ifd, 259, IFDE_TYP_SHORT, 1, 1); /* photometric interpretation */ add_ifd_entry (ifd, 262, IFDE_TYP_SHORT, 1, 1); /* strip offset */ add_ifd_entry (ifd, 273, IFDE_TYP_LONG, 1, strip_offset); /* orientation */ add_ifd_entry (ifd, 274, IFDE_TYP_SHORT, 1, 1); /* samples per pixel */ add_ifd_entry (ifd, 277, IFDE_TYP_SHORT, 1, 1); /* rows per strip */ add_ifd_entry (ifd, 278, IFDE_TYP_LONG, 1, height); /* strip bytecount */ add_ifd_entry (ifd, 279, IFDE_TYP_LONG, 1, strip_bytecount); /* min sample value */ add_ifd_entry (ifd, 280, IFDE_TYP_SHORT, 1, 0); /* max sample value */ add_ifd_entry (ifd, 281, IFDE_TYP_SHORT, 1, maxsamplevalue); if (resolution > 0) { /* x resolution */ add_ifd_entry (ifd, 282, IFDE_TYP_RATIONAL, 1, data_offset); data_offset += 2*4; /* y resolution */ add_ifd_entry (ifd, 283, IFDE_TYP_RATIONAL, 1, data_offset); data_offset += 2*4; } if (resolution > 0) { /* resolution unit (dpi) */ add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2); } if (icc_size > 0) /* add ICC-profile TAG */ { add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset); data_offset += icc_size; } /* I prefer motorola format. Its human readable. But for 16 bit, */ /* the image format is defined by SANE to be the native byte order */ if (bps == 1) { motorola = 1; } else {int check = 1; motorola = ((*((char *)&check)) == 0); } write_ifd (fptr, ifd, motorola); /* Write x/y resolution */ if (resolution > 0) { write_i4 (fptr, resolution, motorola); write_i4 (fptr, 1, motorola); write_i4 (fptr, resolution, motorola); write_i4 (fptr, 1, motorola); } if (icc_size > 0) { fwrite(icc_buffer, icc_size, 1, fptr); } free(icc_buffer); free_ifd (ifd); } static void write_tiff_color_header (FILE *fptr, int width, int height, int depth, int resolution, const char *icc_profile) {IFD *ifd; int header_size = 8, ifd_size; int strip_offset, data_offset, data_size; int strip_bytecount; int ntags; int motorola, bps, maxsamplevalue; void *icc_buffer = NULL; size_t icc_size = 0; if (icc_profile) { icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size); } ifd = create_ifd (); bps = (depth <= 8) ? 1 : 2; /* Bytes per sample */ maxsamplevalue = (depth <= 8) ? 255 : 65535; strip_bytecount = width * height * 3 * bps; /* the following values must be known in advance */ ntags = 13; data_size = 3*2 + 3*2 + 3*2; if (resolution > 0) { ntags += 3; data_size += 2*4 + 2*4; } if (icc_size > 0) /* if icc profile exists add memory for tag */ { ntags += 1; data_size += icc_size; } ifd_size = 2 + ntags*12 + 4; data_offset = header_size + ifd_size; strip_offset = data_offset + data_size; /* New subfile type */ add_ifd_entry (ifd, 254, IFDE_TYP_LONG, 1, 0); /* image width */ add_ifd_entry (ifd, 256, (width > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT, 1, width); /* image length */ add_ifd_entry (ifd, 257, (height > 0xffff) ? IFDE_TYP_LONG : IFDE_TYP_SHORT, 1, height); /* bits per sample */ add_ifd_entry (ifd, 258, IFDE_TYP_SHORT, 3, data_offset); data_offset += 3*2; /* compression (uncompressed) */ add_ifd_entry (ifd, 259, IFDE_TYP_SHORT, 1, 1); /* photometric interpretation */ add_ifd_entry (ifd, 262, IFDE_TYP_SHORT, 1, 2); /* strip offset */ add_ifd_entry (ifd, 273, IFDE_TYP_LONG, 1, strip_offset); /* orientation */ add_ifd_entry (ifd, 274, IFDE_TYP_SHORT, 1, 1); /* samples per pixel */ add_ifd_entry (ifd, 277, IFDE_TYP_SHORT, 1, 3); /* rows per strip */ add_ifd_entry (ifd, 278, IFDE_TYP_LONG, 1, height); /* strip bytecount */ add_ifd_entry (ifd, 279, IFDE_TYP_LONG, 1, strip_bytecount); /* min sample value */ add_ifd_entry (ifd, 280, IFDE_TYP_SHORT, 3, data_offset); data_offset += 3*2; /* max sample value */ add_ifd_entry (ifd, 281, IFDE_TYP_SHORT, 3, data_offset); data_offset += 3*2; if (resolution > 0) { /* x resolution */ add_ifd_entry (ifd, 282, IFDE_TYP_RATIONAL, 1, data_offset); data_offset += 2*4; /* y resolution */ add_ifd_entry (ifd, 283, IFDE_TYP_RATIONAL, 1, data_offset); data_offset += 2*4; } if (resolution > 0) { /* resolution unit (dpi) */ add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2); } if (icc_size > 0) /* add ICC-profile TAG */ { add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset); data_offset += icc_size; } /* I prefer motorola format. Its human readable. But for 16 bit, */ /* the image format is defined by SANE to be the native byte order */ if (bps == 1) { motorola = 1; } else {int check = 1; motorola = ((*((char *)&check)) == 0); } write_ifd (fptr, ifd, motorola); /* Write bits per sample value values */ write_i2 (fptr, depth, motorola); write_i2 (fptr, depth, motorola); write_i2 (fptr, depth, motorola); /* Write min sample value values */ write_i2 (fptr, 0, motorola); write_i2 (fptr, 0, motorola); write_i2 (fptr, 0, motorola); /* Write max sample value values */ write_i2 (fptr, maxsamplevalue, motorola); write_i2 (fptr, maxsamplevalue, motorola); write_i2 (fptr, maxsamplevalue, motorola); /* Write x/y resolution */ if (resolution > 0) { write_i4 (fptr, resolution, motorola); write_i4 (fptr, 1, motorola); write_i4 (fptr, resolution, motorola); write_i4 (fptr, 1, motorola); } /* Write ICC profile */ if (icc_size > 0) { fwrite(icc_buffer, icc_size, 1, fptr); } free(icc_buffer); free_ifd (ifd); } void sanei_write_tiff_header (SANE_Frame format, int width, int height, int depth, int resolution, const char *icc_profile, FILE *ofp) { #ifdef __EMX__ /* OS2 - write in binary mode. */ _fsetmode(ofp, "b"); #endif switch (format) { case SANE_FRAME_RED: case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: case SANE_FRAME_RGB: write_tiff_color_header (ofp, width, height, depth, resolution, icc_profile); break; default: if (depth == 1) write_tiff_bw_header (ofp, width, height, resolution); else write_tiff_grey_header (ofp, width, height, depth, resolution, icc_profile); break; } } sane-backends-1.0.27/frontend/scanimage.c0000664000175000017500000020700713106201017015131 00000000000000/* scanimage -- command line scanning utility Uses the SANE library. Copyright (C) 2015 Rolf Bensch Copyright (C) 1996, 1997, 1998 Andreas Beck and David Mosberger Copyright (C) 1999 - 2009 by the SANE Project -- See AUTHORS and ChangeLog for details. For questions and comments contact the sane-devel mailinglist (see http://www.sane-project.org/mailing-lists.html). This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include #include "lgetopt.h" #include #include #include #include #include #include #include #include #ifdef HAVE_LIBPNG #include #endif #ifdef HAVE_LIBJPEG #include #endif #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "sicc.h" #include "stiff.h" #include "../include/md5.h" #ifndef PATH_MAX #define PATH_MAX 1024 #endif typedef struct { uint8_t *data; int width; /*WARNING: this is in bytes, get pixel width from param*/ int height; int x; int y; } Image; #define OPTION_FORMAT 1001 #define OPTION_MD5 1002 #define OPTION_BATCH_COUNT 1003 #define OPTION_BATCH_START_AT 1004 #define OPTION_BATCH_DOUBLE 1005 #define OPTION_BATCH_INCREMENT 1006 #define OPTION_BATCH_PROMPT 1007 #define OPTION_BATCH_PRINT 1008 #define BATCH_COUNT_UNLIMITED -1 static struct option basic_options[] = { {"device-name", required_argument, NULL, 'd'}, {"list-devices", no_argument, NULL, 'L'}, {"formatted-device-list", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"verbose", no_argument, NULL, 'v'}, {"progress", no_argument, NULL, 'p'}, {"test", no_argument, NULL, 'T'}, {"all-options", no_argument, NULL, 'A'}, {"version", no_argument, NULL, 'V'}, {"buffer-size", optional_argument, NULL, 'B'}, {"batch", optional_argument, NULL, 'b'}, {"batch-count", required_argument, NULL, OPTION_BATCH_COUNT}, {"batch-start", required_argument, NULL, OPTION_BATCH_START_AT}, {"batch-double", no_argument, NULL, OPTION_BATCH_DOUBLE}, {"batch-increment", required_argument, NULL, OPTION_BATCH_INCREMENT}, {"batch-print", no_argument, NULL, OPTION_BATCH_PRINT}, {"batch-prompt", no_argument, NULL, OPTION_BATCH_PROMPT}, {"format", required_argument, NULL, OPTION_FORMAT}, {"accept-md5-only", no_argument, NULL, OPTION_MD5}, {"icc-profile", required_argument, NULL, 'i'}, {"dont-scan", no_argument, NULL, 'n'}, {0, 0, NULL, 0} }; #define OUTPUT_PNM 0 #define OUTPUT_TIFF 1 #define OUTPUT_PNG 2 #define OUTPUT_JPEG 3 #define BASE_OPTSTRING "d:hi:Lf:B::nvVTAbp" #define STRIP_HEIGHT 256 /* # lines we increment image height */ static struct option *all_options; static int option_number_len; static int *option_number; static SANE_Handle device; static int verbose; static int progress = 0; static int test; static int all; static int output_format = OUTPUT_PNM; static int help; static int dont_scan = 0; static const char *prog_name; static int resolution_optind = -1, resolution_value = 0; /* window (area) related options */ static SANE_Option_Descriptor window_option[4]; /*updated descs for x,y,l,t*/ static int window[4]; /*index into backend options for x,y,l,t*/ static SANE_Word window_val[2]; /*the value for x,y options*/ static int window_val_user[2]; /* is x,y user-specified? */ static int accept_only_md5_auth = 0; static const char *icc_profile = NULL; static void fetch_options (SANE_Device * device); static void scanimage_exit (int); static SANE_Word tl_x = 0; static SANE_Word tl_y = 0; static SANE_Word br_x = 0; static SANE_Word br_y = 0; static SANE_Byte *buffer; static size_t buffer_size; static void auth_callback (SANE_String_Const resource, SANE_Char * username, SANE_Char * password) { char tmp[3 + 128 + SANE_MAX_USERNAME_LEN + SANE_MAX_PASSWORD_LEN], *wipe; unsigned char md5digest[16]; int md5mode = 0, len, query_user = 1; FILE *pass_file; struct stat stat_buf; char * uname = NULL; *tmp = 0; if (getenv ("HOME") != NULL) { if (strlen (getenv ("HOME")) < 500) { sprintf (tmp, "%s/.sane/pass", getenv ("HOME")); } } if ((strlen (tmp) > 0) && (stat (tmp, &stat_buf) == 0)) { if ((stat_buf.st_mode & 63) != 0) { fprintf (stderr, "%s has wrong permissions (use at least 0600)\n", tmp); } else { if ((pass_file = fopen (tmp, "r")) != NULL) { if (strstr (resource, "$MD5$") != NULL) len = (strstr (resource, "$MD5$") - resource); else len = strlen (resource); while (fgets (tmp, sizeof(tmp), pass_file)) { if ((strlen (tmp) > 0) && (tmp[strlen (tmp) - 1] == '\n')) tmp[strlen (tmp) - 1] = 0; if ((strlen (tmp) > 0) && (tmp[strlen (tmp) - 1] == '\r')) tmp[strlen (tmp) - 1] = 0; if (strchr (tmp, ':') != NULL) { if (strchr (strchr (tmp, ':') + 1, ':') != NULL) { if ((strncmp (strchr (strchr (tmp, ':') + 1, ':') + 1, resource, len) == 0) && ((int) strlen (strchr (strchr (tmp, ':') + 1, ':') + 1) == len)) { if ((strchr (tmp, ':') - tmp) < SANE_MAX_USERNAME_LEN) { if ((strchr (strchr (tmp, ':') + 1, ':') - (strchr (tmp, ':') + 1)) < SANE_MAX_PASSWORD_LEN) { strncpy (username, tmp, strchr (tmp, ':') - tmp); username[strchr (tmp, ':') - tmp] = 0; strncpy (password, strchr (tmp, ':') + 1, strchr (strchr (tmp, ':') + 1, ':') - (strchr (tmp, ':') + 1)); password[strchr (strchr (tmp, ':') + 1, ':') - (strchr (tmp, ':') + 1)] = 0; query_user = 0; break; } } } } } } fclose (pass_file); } } } if (strstr (resource, "$MD5$") != NULL) { md5mode = 1; len = (strstr (resource, "$MD5$") - resource); if (query_user == 1) fprintf (stderr, "Authentication required for resource %*.*s. " "Enter username: ", len, len, resource); } else { if (accept_only_md5_auth != 0) { fprintf (stderr, "ERROR: backend requested plain-text password\n"); return; } else { fprintf (stderr, "WARNING: backend requested plain-text password\n"); query_user = 1; } if (query_user == 1) fprintf (stderr, "Authentication required for resource %s. Enter username: ", resource); } if (query_user == 1) uname = fgets (username, SANE_MAX_USERNAME_LEN, stdin); if (uname != NULL && (strlen (username)) && (username[strlen (username) - 1] == '\n')) username[strlen (username) - 1] = 0; if (query_user == 1) { #ifdef HAVE_GETPASS strcpy (password, (wipe = getpass ("Enter password: "))); memset (wipe, 0, strlen (password)); #else printf("OS has no getpass(). User Queries will not work\n"); #endif } if (md5mode) { sprintf (tmp, "%.128s%.*s", (strstr (resource, "$MD5$")) + 5, SANE_MAX_PASSWORD_LEN - 1, password); md5_buffer (tmp, strlen (tmp), md5digest); memset (password, 0, SANE_MAX_PASSWORD_LEN); sprintf (password, "$MD5$%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x", md5digest[0], md5digest[1], md5digest[2], md5digest[3], md5digest[4], md5digest[5], md5digest[6], md5digest[7], md5digest[8], md5digest[9], md5digest[10], md5digest[11], md5digest[12], md5digest[13], md5digest[14], md5digest[15]); } } static void sighandler (int signum) { static SANE_Bool first_time = SANE_TRUE; if (device) { fprintf (stderr, "%s: received signal %d\n", prog_name, signum); if (first_time) { first_time = SANE_FALSE; fprintf (stderr, "%s: trying to stop scanner\n", prog_name); sane_cancel (device); } else { fprintf (stderr, "%s: aborting\n", prog_name); _exit (0); } } } static void print_unit (SANE_Unit unit) { switch (unit) { case SANE_UNIT_NONE: break; case SANE_UNIT_PIXEL: fputs ("pel", stdout); break; case SANE_UNIT_BIT: fputs ("bit", stdout); break; case SANE_UNIT_MM: fputs ("mm", stdout); break; case SANE_UNIT_DPI: fputs ("dpi", stdout); break; case SANE_UNIT_PERCENT: fputc ('%', stdout); break; case SANE_UNIT_MICROSECOND: fputs ("us", stdout); break; } } static void print_option (SANE_Device * device, int opt_num, const SANE_Option_Descriptor *opt) { const char *str, *last_break, *start; SANE_Bool not_first = SANE_FALSE; int i, column; if (opt->type == SANE_TYPE_GROUP){ printf (" %s:\n", opt->title); return; } /* if both of these are set, option is invalid */ if(opt->cap & SANE_CAP_SOFT_SELECT && opt->cap & SANE_CAP_HARD_SELECT){ fprintf (stderr, "%s: invalid option caps, SS+HS\n", prog_name); return; } /* invalid to select but not detect */ if(opt->cap & SANE_CAP_SOFT_SELECT && !(opt->cap & SANE_CAP_SOFT_DETECT)){ fprintf (stderr, "%s: invalid option caps, SS!SD\n", prog_name); return; } /* standard allows this, though it makes little sense if(opt->cap & SANE_CAP_HARD_SELECT && !(opt->cap & SANE_CAP_SOFT_DETECT)){ fprintf (stderr, "%s: invalid option caps, HS!SD\n", prog_name); return; }*/ /* if one of these three is not set, option is useless, skip it */ if(!(opt->cap & (SANE_CAP_SOFT_SELECT | SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT) )){ return; } /* print the option */ if ( !strcmp (opt->name, "x") || !strcmp (opt->name, "y") || !strcmp (opt->name, "t") || !strcmp (opt->name, "l")) printf (" -%s", opt->name); else printf (" --%s", opt->name); /* print the option choices */ if (opt->type == SANE_TYPE_BOOL) { fputs ("[=(", stdout); if (opt->cap & SANE_CAP_AUTOMATIC) fputs ("auto|", stdout); fputs ("yes|no)]", stdout); } else if (opt->type != SANE_TYPE_BUTTON) { fputc (' ', stdout); if (opt->cap & SANE_CAP_AUTOMATIC) { fputs ("auto|", stdout); not_first = SANE_TRUE; } switch (opt->constraint_type) { case SANE_CONSTRAINT_NONE: switch (opt->type) { case SANE_TYPE_INT: fputs ("", stdout); break; case SANE_TYPE_FIXED: fputs ("", stdout); break; case SANE_TYPE_STRING: fputs ("", stdout); break; default: break; } if (opt->type != SANE_TYPE_STRING && opt->size > (SANE_Int) sizeof (SANE_Word)) fputs (",...", stdout); break; case SANE_CONSTRAINT_RANGE: if (opt->type == SANE_TYPE_INT) { if (!strcmp (opt->name, "x")) { printf ("%d..%d", opt->constraint.range->min, opt->constraint.range->max - tl_x); } else if (!strcmp (opt->name, "y")) { printf ("%d..%d", opt->constraint.range->min, opt->constraint.range->max - tl_y); } else { printf ("%d..%d", opt->constraint.range->min, opt->constraint.range->max); } print_unit (opt->unit); if (opt->size > (SANE_Int) sizeof (SANE_Word)) fputs (",...", stdout); if (opt->constraint.range->quant) printf (" (in steps of %d)", opt->constraint.range->quant); } else { if (!strcmp (opt->name, "x")) { printf ("%g..%g", SANE_UNFIX (opt->constraint.range->min), SANE_UNFIX (opt->constraint.range->max - tl_x)); } else if (!strcmp (opt->name, "y")) { printf ("%g..%g", SANE_UNFIX (opt->constraint.range->min), SANE_UNFIX (opt->constraint.range->max - tl_y)); } else { printf ("%g..%g", SANE_UNFIX (opt->constraint.range->min), SANE_UNFIX (opt->constraint.range->max)); } print_unit (opt->unit); if (opt->size > (SANE_Int) sizeof (SANE_Word)) fputs (",...", stdout); if (opt->constraint.range->quant) printf (" (in steps of %g)", SANE_UNFIX (opt->constraint.range->quant)); } break; case SANE_CONSTRAINT_WORD_LIST: for (i = 0; i < opt->constraint.word_list[0]; ++i) { if (not_first) fputc ('|', stdout); not_first = SANE_TRUE; if (opt->type == SANE_TYPE_INT) printf ("%d", opt->constraint.word_list[i + 1]); else printf ("%g", SANE_UNFIX (opt->constraint.word_list[i + 1])); } print_unit (opt->unit); if (opt->size > (SANE_Int) sizeof (SANE_Word)) fputs (",...", stdout); break; case SANE_CONSTRAINT_STRING_LIST: for (i = 0; opt->constraint.string_list[i]; ++i) { if (i > 0) fputc ('|', stdout); fputs (opt->constraint.string_list[i], stdout); } break; } } /* print current option value */ if (opt->type == SANE_TYPE_STRING || opt->size == sizeof (SANE_Word)) { if (SANE_OPTION_IS_ACTIVE (opt->cap)) { void *val = alloca (opt->size); sane_control_option (device, opt_num, SANE_ACTION_GET_VALUE, val, 0); fputs (" [", stdout); switch (opt->type) { case SANE_TYPE_BOOL: fputs (*(SANE_Bool *) val ? "yes" : "no", stdout); break; case SANE_TYPE_INT: if (strcmp (opt->name, "l") == 0) { tl_x = (*(SANE_Fixed *) val); printf ("%d", tl_x); } else if (strcmp (opt->name, "t") == 0) { tl_y = (*(SANE_Fixed *) val); printf ("%d", tl_y); } else if (strcmp (opt->name, "x") == 0) { br_x = (*(SANE_Fixed *) val); printf ("%d", br_x - tl_x); } else if (strcmp (opt->name, "y") == 0) { br_y = (*(SANE_Fixed *) val); printf ("%d", br_y - tl_y); } else printf ("%d", *(SANE_Int *) val); break; case SANE_TYPE_FIXED: if (strcmp (opt->name, "l") == 0) { tl_x = (*(SANE_Fixed *) val); printf ("%g", SANE_UNFIX (tl_x)); } else if (strcmp (opt->name, "t") == 0) { tl_y = (*(SANE_Fixed *) val); printf ("%g", SANE_UNFIX (tl_y)); } else if (strcmp (opt->name, "x") == 0) { br_x = (*(SANE_Fixed *) val); printf ("%g", SANE_UNFIX (br_x - tl_x)); } else if (strcmp (opt->name, "y") == 0) { br_y = (*(SANE_Fixed *) val); printf ("%g", SANE_UNFIX (br_y - tl_y)); } else printf ("%g", SANE_UNFIX (*(SANE_Fixed *) val)); break; case SANE_TYPE_STRING: fputs ((char *) val, stdout); break; default: break; } fputc (']', stdout); } } if (!SANE_OPTION_IS_ACTIVE (opt->cap)) fputs (" [inactive]", stdout); else if(opt->cap & SANE_CAP_HARD_SELECT) fputs (" [hardware]", stdout); else if(!(opt->cap & SANE_CAP_SOFT_SELECT) && opt->cap & SANE_CAP_SOFT_DETECT) fputs (" [read-only]", stdout); fputs ("\n ", stdout); column = 8; last_break = 0; start = opt->desc; for (str = opt->desc; *str; ++str) { ++column; if (*str == ' ') last_break = str; else if (*str == '\n'){ column=80; last_break = str; } if (column >= 79 && last_break) { while (start < last_break) fputc (*start++, stdout); start = last_break + 1; /* skip blank */ fputs ("\n ", stdout); column = 8 + (str - start); } } while (*start) fputc (*start++, stdout); fputc ('\n', stdout); } /* A scalar has the following syntax: V [ U ] V is the value of the scalar. It is either an integer or a floating point number, depending on the option type. U is an optional unit. If not specified, the default unit is used. The following table lists which units are supported depending on what the option's default unit is: Option's unit: Allowed units: SANE_UNIT_NONE: SANE_UNIT_PIXEL: pel SANE_UNIT_BIT: b (bit), B (byte) SANE_UNIT_MM: mm (millimeter), cm (centimeter), in or " (inches), SANE_UNIT_DPI: dpi SANE_UNIT_PERCENT: % SANE_UNIT_PERCENT: us */ static const char * parse_scalar (const SANE_Option_Descriptor * opt, const char *str, SANE_Word * value) { char *end; double v; if (opt->type == SANE_TYPE_FIXED) v = strtod (str, &end) * (1 << SANE_FIXED_SCALE_SHIFT); else v = strtol (str, &end, 10); if (str == end) { fprintf (stderr, "%s: option --%s: bad option value (rest of option: %s)\n", prog_name, opt->name, str); scanimage_exit (1); } str = end; switch (opt->unit) { case SANE_UNIT_NONE: case SANE_UNIT_PIXEL: break; case SANE_UNIT_BIT: if (*str == 'b' || *str == 'B') { if (*str++ == 'B') v *= 8; } break; case SANE_UNIT_MM: if (str[0] == '\0') v *= 1.0; /* default to mm */ else if (strcmp (str, "mm") == 0) str += sizeof ("mm") - 1; else if (strcmp (str, "cm") == 0) { str += sizeof ("cm") - 1; v *= 10.0; } else if (strcmp (str, "in") == 0 || *str == '"') { if (*str++ != '"') ++str; v *= 25.4; /* 25.4 mm/inch */ } else { fprintf (stderr, "%s: option --%s: illegal unit (rest of option: %s)\n", prog_name, opt->name, str); return 0; } break; case SANE_UNIT_DPI: if (strcmp (str, "dpi") == 0) str += sizeof ("dpi") - 1; break; case SANE_UNIT_PERCENT: if (*str == '%') ++str; break; case SANE_UNIT_MICROSECOND: if (strcmp (str, "us") == 0) str += sizeof ("us") - 1; break; } if(v < 0){ *value = v - 0.5; } else{ *value = v + 0.5; } return str; } /* A vector has the following syntax: [ '[' I ']' ] S { [','|'-'] [ '[' I ']' S } The number in brackets (I), if present, determines the index of the vector element to be set next. If I is not present, the value of last index used plus 1 is used. The first index value used is 0 unless I is present. S is a scalar value as defined by parse_scalar(). If two consecutive value specs are separated by a comma (,) their values are set independently. If they are separated by a dash (-), they define the endpoints of a line and all vector values between the two endpoints are set according to the value of the interpolated line. For example, [0]15-[255]15 defines a vector of 256 elements whose value is 15. Similarly, [0]0-[255]255 defines a vector of 256 elements whose value starts at 0 and increases to 255. */ static void parse_vector (const SANE_Option_Descriptor * opt, const char *str, SANE_Word * vector, size_t vector_length) { SANE_Word value, prev_value = 0; int index = -1, prev_index = 0; char *end, separator = '\0'; /* initialize vector to all zeroes: */ memset (vector, 0, vector_length * sizeof (SANE_Word)); do { if (*str == '[') { /* read index */ index = strtol (++str, &end, 10); if (str == end || *end != ']') { fprintf (stderr, "%s: option --%s: closing bracket missing " "(rest of option: %s)\n", prog_name, opt->name, str); scanimage_exit (1); } str = end + 1; } else ++index; if (index < 0 || index >= (int) vector_length) { fprintf (stderr, "%s: option --%s: index %d out of range [0..%ld]\n", prog_name, opt->name, index, (long) vector_length - 1); scanimage_exit (1); } /* read value */ str = parse_scalar (opt, str, &value); if (!str) scanimage_exit (1); if (*str && *str != '-' && *str != ',') { fprintf (stderr, "%s: option --%s: illegal separator (rest of option: %s)\n", prog_name, opt->name, str); scanimage_exit (1); } /* store value: */ vector[index] = value; if (separator == '-') { /* interpolate */ double v, slope; int i; v = (double) prev_value; slope = ((double) value - v) / (index - prev_index); for (i = prev_index + 1; i < index; ++i) { v += slope; vector[i] = (SANE_Word) v; } } prev_index = index; prev_value = value; separator = *str++; } while (separator == ',' || separator == '-'); if (verbose > 2) { int i; fprintf (stderr, "%s: value for --%s is: ", prog_name, opt->name); for (i = 0; i < (int) vector_length; ++i) if (opt->type == SANE_TYPE_FIXED) fprintf (stderr, "%g ", SANE_UNFIX (vector[i])); else fprintf (stderr, "%d ", vector[i]); fputc ('\n', stderr); } } static void fetch_options (SANE_Device * device) { const SANE_Option_Descriptor *opt; SANE_Int num_dev_options; int i, option_count; SANE_Status status; opt = sane_get_option_descriptor (device, 0); if (opt == NULL) { fprintf (stderr, "Could not get option descriptor for option 0\n"); scanimage_exit (1); } status = sane_control_option (device, 0, SANE_ACTION_GET_VALUE, &num_dev_options, 0); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "Could not get value for option 0: %s\n", sane_strstatus (status)); scanimage_exit (1); } /* build the full table of long options */ option_count = 0; for (i = 1; i < num_dev_options; ++i) { opt = sane_get_option_descriptor (device, i); if (opt == NULL) { fprintf (stderr, "Could not get option descriptor for option %d\n",i); scanimage_exit (1); } /* create command line option only for settable options */ if (!SANE_OPTION_IS_SETTABLE (opt->cap) || opt->type == SANE_TYPE_GROUP) continue; option_number[option_count] = i; all_options[option_count].name = (const char *) opt->name; all_options[option_count].flag = 0; all_options[option_count].val = 0; if (opt->type == SANE_TYPE_BOOL) all_options[option_count].has_arg = optional_argument; else if (opt->type == SANE_TYPE_BUTTON) all_options[option_count].has_arg = no_argument; else all_options[option_count].has_arg = required_argument; /* Look for scan resolution */ if ((opt->type == SANE_TYPE_FIXED || opt->type == SANE_TYPE_INT) && opt->size == sizeof (SANE_Int) && (opt->unit == SANE_UNIT_DPI) && (strcmp (opt->name, SANE_NAME_SCAN_RESOLUTION) == 0)) resolution_optind = i; /* Keep track of top-left corner options (if they exist at all) and replace the bottom-right corner options by a width/height option (if they exist at all). */ if ((opt->type == SANE_TYPE_FIXED || opt->type == SANE_TYPE_INT) && opt->size == sizeof (SANE_Int) && (opt->unit == SANE_UNIT_MM || opt->unit == SANE_UNIT_PIXEL)) { if (strcmp (opt->name, SANE_NAME_SCAN_BR_X) == 0) { window[0] = i; all_options[option_count].name = "width"; all_options[option_count].val = 'x'; window_option[0] = *opt; window_option[0].title = "Scan width"; window_option[0].desc = "Width of scan-area."; window_option[0].name = "x"; } else if (strcmp (opt->name, SANE_NAME_SCAN_BR_Y) == 0) { window[1] = i; all_options[option_count].name = "height"; all_options[option_count].val = 'y'; window_option[1] = *opt; window_option[1].title = "Scan height"; window_option[1].desc = "Height of scan-area."; window_option[1].name = "y"; } else if (strcmp (opt->name, SANE_NAME_SCAN_TL_X) == 0) { window[2] = i; all_options[option_count].val = 'l'; window_option[2] = *opt; window_option[2].name = "l"; } else if (strcmp (opt->name, SANE_NAME_SCAN_TL_Y) == 0) { window[3] = i; all_options[option_count].val = 't'; window_option[3] = *opt; window_option[3].name = "t"; } } ++option_count; } memcpy (all_options + option_count, basic_options, sizeof (basic_options)); option_count += NELEMS (basic_options); memset (all_options + option_count, 0, sizeof (all_options[0])); /* Initialize width & height options based on backend default values for top-left x/y and bottom-right x/y: */ for (i = 0; i < 2; ++i) { if (window[i] && !window_val_user[i]) { sane_control_option (device, window[i], SANE_ACTION_GET_VALUE, &window_val[i], 0); if (window[i + 2]){ SANE_Word pos; sane_control_option (device, window[i + 2], SANE_ACTION_GET_VALUE, &pos, 0); window_val[i] -= pos; } } } } static void set_option (SANE_Handle device, int optnum, void *valuep) { const SANE_Option_Descriptor *opt; SANE_Status status; SANE_Word orig = 0; SANE_Int info = 0; opt = sane_get_option_descriptor (device, optnum); if (opt && (!SANE_OPTION_IS_ACTIVE (opt->cap))) { if (verbose > 0) fprintf (stderr, "%s: ignored request to set inactive option %s\n", prog_name, opt->name); return; } if (opt->size == sizeof (SANE_Word) && opt->type != SANE_TYPE_STRING) orig = *(SANE_Word *) valuep; status = sane_control_option (device, optnum, SANE_ACTION_SET_VALUE, valuep, &info); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: setting of option --%s failed (%s)\n", prog_name, opt->name, sane_strstatus (status)); scanimage_exit (1); } if ((info & SANE_INFO_INEXACT) && opt->size == sizeof (SANE_Word)) { if (opt->type == SANE_TYPE_INT) fprintf (stderr, "%s: rounded value of %s from %d to %d\n", prog_name, opt->name, orig, *(SANE_Word *) valuep); else if (opt->type == SANE_TYPE_FIXED) fprintf (stderr, "%s: rounded value of %s from %g to %g\n", prog_name, opt->name, SANE_UNFIX (orig), SANE_UNFIX (*(SANE_Word *) valuep)); } if (info & SANE_INFO_RELOAD_OPTIONS) fetch_options (device); } static void process_backend_option (SANE_Handle device, int optnum, const char *optarg) { static SANE_Word *vector = 0; static size_t vector_size = 0; const SANE_Option_Descriptor *opt; size_t vector_length; SANE_Status status; SANE_Word value; void *valuep; opt = sane_get_option_descriptor (device, optnum); if (!SANE_OPTION_IS_ACTIVE (opt->cap)) { fprintf (stderr, "%s: attempted to set inactive option %s\n", prog_name, opt->name); scanimage_exit (1); } if ((opt->cap & SANE_CAP_AUTOMATIC) && optarg && strncasecmp (optarg, "auto", 4) == 0) { status = sane_control_option (device, optnum, SANE_ACTION_SET_AUTO, 0, 0); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: failed to set option --%s to automatic (%s)\n", prog_name, opt->name, sane_strstatus (status)); scanimage_exit (1); } return; } valuep = &value; switch (opt->type) { case SANE_TYPE_BOOL: value = 1; /* no argument means option is set */ if (optarg) { if (strncasecmp (optarg, "yes", strlen (optarg)) == 0) value = 1; else if (strncasecmp (optarg, "no", strlen (optarg)) == 0) value = 0; else { fprintf (stderr, "%s: option --%s: bad option value `%s'\n", prog_name, opt->name, optarg); scanimage_exit (1); } } break; case SANE_TYPE_INT: case SANE_TYPE_FIXED: /* ensure vector is long enough: */ vector_length = opt->size / sizeof (SANE_Word); if (vector_size < vector_length) { vector_size = vector_length; vector = realloc (vector, vector_length * sizeof (SANE_Word)); if (!vector) { fprintf (stderr, "%s: out of memory\n", prog_name); scanimage_exit (1); } } parse_vector (opt, optarg, vector, vector_length); valuep = vector; break; case SANE_TYPE_STRING: valuep = malloc (opt->size); if (!valuep) { fprintf (stderr, "%s: out of memory\n", prog_name); scanimage_exit (1); } strncpy (valuep, optarg, opt->size); ((char *) valuep)[opt->size - 1] = 0; break; case SANE_TYPE_BUTTON: value = 0; /* value doesn't matter */ break; default: fprintf (stderr, "%s: duh, got unknown option type %d\n", prog_name, opt->type); return; } set_option (device, optnum, valuep); } static void write_pnm_header (SANE_Frame format, int width, int height, int depth, FILE *ofp) { /* The netpbm-package does not define raw image data with maxval > 255. */ /* But writing maxval 65535 for 16bit data gives at least a chance */ /* to read the image. */ switch (format) { case SANE_FRAME_RED: case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: case SANE_FRAME_RGB: fprintf (ofp, "P6\n# SANE data follows\n%d %d\n%d\n", width, height, (depth <= 8) ? 255 : 65535); break; default: if (depth == 1) fprintf (ofp, "P4\n# SANE data follows\n%d %d\n", width, height); else fprintf (ofp, "P5\n# SANE data follows\n%d %d\n%d\n", width, height, (depth <= 8) ? 255 : 65535); break; } #ifdef __EMX__ /* OS2 - write in binary mode. */ _fsetmode (ofp, "b"); #endif } #ifdef HAVE_LIBPNG static void write_png_header (SANE_Frame format, int width, int height, int depth, int dpi, const char * icc_profile, FILE *ofp, png_structp* png_ptr, png_infop* info_ptr) { int color_type; /* PNG does not have imperial reference units, so we must convert to metric. */ /* There are nominally 39.3700787401575 inches in a meter. */ const double pixels_per_meter = dpi * 39.3700787401575; size_t icc_size = 0; void *icc_buffer; *png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!*png_ptr) { fprintf(stderr, "png_create_write_struct failed\n"); exit(1); } *info_ptr = png_create_info_struct(*png_ptr); if (!*info_ptr) { fprintf(stderr, "png_create_info_struct failed\n"); exit(1); } png_init_io(*png_ptr, ofp); switch (format) { case SANE_FRAME_RED: case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: case SANE_FRAME_RGB: color_type = PNG_COLOR_TYPE_RGB; break; default: color_type = PNG_COLOR_TYPE_GRAY; break; } png_set_IHDR(*png_ptr, *info_ptr, width, height, depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_pHYs(*png_ptr, *info_ptr, pixels_per_meter, pixels_per_meter, PNG_RESOLUTION_METER); if (icc_profile) { icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size); if (icc_size > 0) { /* libpng will abort if the profile and image colour spaces do not match*/ /* The data colour space field is at bytes 16 to 20 in an ICC profile */ /* see: ICC.1:2010 § 7.2.6 */ int is_gray_profile = strncmp((char *) icc_buffer + 16, "GRAY", 4) == 0; int is_rgb_profile = strncmp((char *) icc_buffer + 16, "RGB ", 4) == 0; if ((is_gray_profile && color_type == PNG_COLOR_TYPE_GRAY) || (is_rgb_profile && color_type == PNG_COLOR_TYPE_RGB)) { png_set_iCCP(*png_ptr, *info_ptr, basename(icc_profile), PNG_COMPRESSION_TYPE_BASE, icc_buffer, icc_size); } else { if (is_gray_profile) { fprintf(stderr, "Ignoring 'GRAY' space ICC profile because the image is RGB.\n"); } if (is_rgb_profile) { fprintf(stderr, "Ignoring 'RGB ' space ICC profile because the image is Grayscale.\n"); } } free(icc_buffer); } } png_write_info(*png_ptr, *info_ptr); } #endif #ifdef HAVE_LIBJPEG static void write_jpeg_header (SANE_Frame format, int width, int height, int dpi, FILE *ofp, struct jpeg_compress_struct *cinfo, struct jpeg_error_mgr *jerr) { cinfo->err = jpeg_std_error(jerr); jpeg_create_compress(cinfo); jpeg_stdio_dest(cinfo, ofp); cinfo->image_width = width; cinfo->image_height = height; switch (format) { case SANE_FRAME_RED: case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: case SANE_FRAME_RGB: cinfo->in_color_space = JCS_RGB; cinfo->input_components = 3; break; default: cinfo->in_color_space = JCS_GRAYSCALE; cinfo->input_components = 1; break; } jpeg_set_defaults(cinfo); /* jpeg_set_defaults overrides density, be careful. */ cinfo->density_unit = 1; /* Inches */ cinfo->X_density = cinfo->Y_density = dpi; cinfo->write_JFIF_header = TRUE; jpeg_set_quality(cinfo, 75, TRUE); jpeg_start_compress(cinfo, TRUE); } #endif static void * advance (Image * image) { if (++image->x >= image->width) { image->x = 0; if (++image->y >= image->height || !image->data) { size_t old_size = 0, new_size; if (image->data) old_size = image->height * image->width; image->height += STRIP_HEIGHT; new_size = image->height * image->width; if (image->data) image->data = realloc (image->data, new_size); else image->data = malloc (new_size); if (image->data) memset (image->data + old_size, 0, new_size - old_size); } } if (!image->data) fprintf (stderr, "%s: can't allocate image buffer (%dx%d)\n", prog_name, image->width, image->height); return image->data; } static SANE_Status scan_it (FILE *ofp) { int i, len, first_frame = 1, offset = 0, must_buffer = 0, hundred_percent; SANE_Byte min = 0xff, max = 0; SANE_Parameters parm; SANE_Status status; Image image = { 0, 0, 0, 0, 0 }; static const char *format_name[] = { "gray", "RGB", "red", "green", "blue" }; SANE_Word total_bytes = 0, expected_bytes; SANE_Int hang_over = -1; #ifdef HAVE_LIBPNG int pngrow = 0; png_bytep pngbuf = NULL; png_structp png_ptr; png_infop info_ptr; #endif #ifdef HAVE_LIBJPEG int jpegrow = 0; JSAMPLE *jpegbuf = NULL; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; #endif do { if (!first_frame) { #ifdef SANE_STATUS_WARMING_UP do { status = sane_start (device); } while(status == SANE_STATUS_WARMING_UP); #else status = sane_start (device); #endif if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: sane_start: %s\n", prog_name, sane_strstatus (status)); goto cleanup; } } status = sane_get_parameters (device, &parm); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: sane_get_parameters: %s\n", prog_name, sane_strstatus (status)); goto cleanup; } if (verbose) { if (first_frame) { if (parm.lines >= 0) fprintf (stderr, "%s: scanning image of size %dx%d pixels at " "%d bits/pixel\n", prog_name, parm.pixels_per_line, parm.lines, parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1)); else fprintf (stderr, "%s: scanning image %d pixels wide and " "variable height at %d bits/pixel\n", prog_name, parm.pixels_per_line, parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1)); } fprintf (stderr, "%s: acquiring %s frame\n", prog_name, parm.format <= SANE_FRAME_BLUE ? format_name[parm.format]:"Unknown"); } if (first_frame) { switch (parm.format) { case SANE_FRAME_RED: case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: assert (parm.depth == 8); must_buffer = 1; offset = parm.format - SANE_FRAME_RED; break; case SANE_FRAME_RGB: assert ((parm.depth == 8) || (parm.depth == 16)); case SANE_FRAME_GRAY: assert ((parm.depth == 1) || (parm.depth == 8) || (parm.depth == 16)); if (parm.lines < 0) { must_buffer = 1; offset = 0; } else switch(output_format) { case OUTPUT_TIFF: sanei_write_tiff_header (parm.format, parm.pixels_per_line, parm.lines, parm.depth, resolution_value, icc_profile, ofp); break; case OUTPUT_PNM: write_pnm_header (parm.format, parm.pixels_per_line, parm.lines, parm.depth, ofp); break; #ifdef HAVE_LIBPNG case OUTPUT_PNG: write_png_header (parm.format, parm.pixels_per_line, parm.lines, parm.depth, resolution_value, icc_profile, ofp, &png_ptr, &info_ptr); break; #endif #ifdef HAVE_LIBJPEG case OUTPUT_JPEG: write_jpeg_header (parm.format, parm.pixels_per_line, parm.lines, resolution_value, ofp, &cinfo, &jerr); break; #endif } break; default: break; } #ifdef HAVE_LIBPNG if(output_format == OUTPUT_PNG) pngbuf = malloc(parm.bytes_per_line); #endif #ifdef HAVE_LIBJPEG if(output_format == OUTPUT_JPEG) jpegbuf = malloc(parm.bytes_per_line); #endif if (must_buffer) { /* We're either scanning a multi-frame image or the scanner doesn't know what the eventual image height will be (common for hand-held scanners). In either case, we need to buffer all data before we can write the image. */ image.width = parm.bytes_per_line; if (parm.lines >= 0) /* See advance(); we allocate one extra line so we don't end up realloc'ing in when the image has been filled in. */ image.height = parm.lines - STRIP_HEIGHT + 1; else image.height = 0; image.x = image.width - 1; image.y = -1; if (!advance (&image)) { status = SANE_STATUS_NO_MEM; goto cleanup; } } } else { assert (parm.format >= SANE_FRAME_RED && parm.format <= SANE_FRAME_BLUE); offset = parm.format - SANE_FRAME_RED; image.x = image.y = 0; } hundred_percent = parm.bytes_per_line * parm.lines * ((parm.format == SANE_FRAME_RGB || parm.format == SANE_FRAME_GRAY) ? 1:3); while (1) { double progr; status = sane_read (device, buffer, buffer_size, &len); total_bytes += (SANE_Word) len; progr = ((total_bytes * 100.) / (double) hundred_percent); if (progr > 100.) progr = 100.; if (progress) fprintf (stderr, "Progress: %3.1f%%\r", progr); if (status != SANE_STATUS_GOOD) { if (verbose && parm.depth == 8) fprintf (stderr, "%s: min/max graylevel value = %d/%d\n", prog_name, min, max); if (status != SANE_STATUS_EOF) { fprintf (stderr, "%s: sane_read: %s\n", prog_name, sane_strstatus (status)); return status; } break; } if (must_buffer) { switch (parm.format) { case SANE_FRAME_RED: case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: for (i = 0; i < len; ++i) { image.data[offset + 3 * i] = buffer[i]; if (!advance (&image)) { status = SANE_STATUS_NO_MEM; goto cleanup; } } offset += 3 * len; break; case SANE_FRAME_RGB: for (i = 0; i < len; ++i) { image.data[offset + i] = buffer[i]; if (!advance (&image)) { status = SANE_STATUS_NO_MEM; goto cleanup; } } offset += len; break; case SANE_FRAME_GRAY: for (i = 0; i < len; ++i) { image.data[offset + i] = buffer[i]; if (!advance (&image)) { status = SANE_STATUS_NO_MEM; goto cleanup; } } offset += len; break; default: break; } } else /* ! must_buffer */ { #ifdef HAVE_LIBPNG if (output_format == OUTPUT_PNG) { int i = 0; int left = len; while(pngrow + left >= parm.bytes_per_line) { memcpy(pngbuf + pngrow, buffer + i, parm.bytes_per_line - pngrow); if(parm.depth == 1) { int j; for(j = 0; j < parm.bytes_per_line; j++) pngbuf[j] = ~pngbuf[j]; } #ifndef WORDS_BIGENDIAN /* SANE is endian-native, PNG is big-endian, */ /* see: https://www.w3.org/TR/2003/REC-PNG-20031110/#7Integers-and-byte-order */ if (parm.depth == 16) { int j; for (j = 0; j < parm.bytes_per_line; j += 2) { SANE_Byte LSB; LSB = pngbuf[j]; pngbuf[j] = pngbuf[j + 1]; pngbuf[j + 1] = LSB; } } #endif png_write_row(png_ptr, pngbuf); i += parm.bytes_per_line - pngrow; left -= parm.bytes_per_line - pngrow; pngrow = 0; } memcpy(pngbuf + pngrow, buffer + i, left); pngrow += left; } else #endif #ifdef HAVE_LIBJPEG if (output_format == OUTPUT_JPEG) { int i = 0; int left = len; while(jpegrow + left >= parm.bytes_per_line) { memcpy(jpegbuf + jpegrow, buffer + i, parm.bytes_per_line - jpegrow); if(parm.depth == 1) { int col1, col8; JSAMPLE *buf8 = malloc(parm.bytes_per_line * 8); for(col1 = 0; col1 < parm.bytes_per_line; col1++) for(col8 = 0; col8 < 8; col8++) buf8[col1 * 8 + col8] = jpegbuf[col1] & (1 << (8 - col8 - 1)) ? 0 : 0xff; jpeg_write_scanlines(&cinfo, &buf8, 1); free(buf8); } else { jpeg_write_scanlines(&cinfo, &jpegbuf, 1); } i += parm.bytes_per_line - jpegrow; left -= parm.bytes_per_line - jpegrow; jpegrow = 0; } memcpy(jpegbuf + jpegrow, buffer + i, left); jpegrow += left; } else #endif if ((output_format == OUTPUT_TIFF) || (parm.depth != 16)) fwrite (buffer, 1, len, ofp); else { #if !defined(WORDS_BIGENDIAN) int i, start = 0; /* check if we have saved one byte from the last sane_read */ if (hang_over > -1) { if (len > 0) { fwrite (buffer, 1, 1, ofp); buffer[0] = (SANE_Byte) hang_over; hang_over = -1; start = 1; } } /* now do the byte-swapping */ for (i = start; i < (len - 1); i += 2) { unsigned char LSB; LSB = buffer[i]; buffer[i] = buffer[i + 1]; buffer[i + 1] = LSB; } /* check if we have an odd number of bytes */ if (((len - start) % 2) != 0) { hang_over = buffer[len - 1]; len--; } #endif fwrite (buffer, 1, len, ofp); } } if (verbose && parm.depth == 8) { for (i = 0; i < len; ++i) if (buffer[i] >= max) max = buffer[i]; else if (buffer[i] < min) min = buffer[i]; } } first_frame = 0; } while (!parm.last_frame); if (must_buffer) { image.height = image.y; switch(output_format) { case OUTPUT_TIFF: sanei_write_tiff_header (parm.format, parm.pixels_per_line, image.height, parm.depth, resolution_value, icc_profile, ofp); break; case OUTPUT_PNM: write_pnm_header (parm.format, parm.pixels_per_line, image.height, parm.depth, ofp); break; #ifdef HAVE_LIBPNG case OUTPUT_PNG: write_png_header (parm.format, parm.pixels_per_line, image.height, parm.depth, resolution_value, icc_profile, ofp, &png_ptr, &info_ptr); break; #endif #ifdef HAVE_LIBJPEG case OUTPUT_JPEG: write_jpeg_header (parm.format, parm.pixels_per_line, parm.lines, resolution_value, ofp, &cinfo, &jerr); break; #endif } #if !defined(WORDS_BIGENDIAN) /* multibyte pnm file may need byte swap to LE */ /* FIXME: other bit depths? */ if (output_format != OUTPUT_TIFF && parm.depth == 16) { int i; for (i = 0; i < image.height * image.width; i += 2) { unsigned char LSB; LSB = image.data[i]; image.data[i] = image.data[i + 1]; image.data[i + 1] = LSB; } } #endif fwrite (image.data, 1, image.height * image.width, ofp); } #ifdef HAVE_LIBPNG if(output_format == OUTPUT_PNG) png_write_end(png_ptr, info_ptr); #endif #ifdef HAVE_LIBJPEG if(output_format == OUTPUT_JPEG) jpeg_finish_compress(&cinfo); #endif /* flush the output buffer */ fflush( ofp ); cleanup: #ifdef HAVE_LIBPNG if(output_format == OUTPUT_PNG) { png_destroy_write_struct(&png_ptr, &info_ptr); free(pngbuf); } #endif #ifdef HAVE_LIBJPEG if(output_format == OUTPUT_JPEG) { jpeg_destroy_compress(&cinfo); free(jpegbuf); } #endif if (image.data) free (image.data); expected_bytes = parm.bytes_per_line * parm.lines * ((parm.format == SANE_FRAME_RGB || parm.format == SANE_FRAME_GRAY) ? 1 : 3); if (parm.lines < 0) expected_bytes = 0; if (total_bytes > expected_bytes && expected_bytes != 0) { fprintf (stderr, "%s: WARNING: read more data than announced by backend " "(%u/%u)\n", prog_name, total_bytes, expected_bytes); } else if (verbose) fprintf (stderr, "%s: read %u bytes in total\n", prog_name, total_bytes); return status; } #define clean_buffer(buf,size) memset ((buf), 0x23, size) static void pass_fail (int max, int len, SANE_Byte * buffer, SANE_Status status) { if (status != SANE_STATUS_GOOD) fprintf (stderr, "FAIL Error: %s\n", sane_strstatus (status)); else if (buffer[len] != 0x23) { while (len <= max && buffer[len] != 0x23) ++len; fprintf (stderr, "FAIL Cheat: %d bytes\n", len); } else if (len > max) fprintf (stderr, "FAIL Overflow: %d bytes\n", len); else if (len == 0) fprintf (stderr, "FAIL No data\n"); else fprintf (stderr, "PASS\n"); } static SANE_Status test_it (void) { int i, len; SANE_Parameters parm; SANE_Status status; Image image = { 0, 0, 0, 0, 0 }; static const char *format_name[] = { "gray", "RGB", "red", "green", "blue" }; #ifdef SANE_STATUS_WARMING_UP do { status = sane_start (device); } while(status == SANE_STATUS_WARMING_UP); #else status = sane_start (device); #endif if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: sane_start: %s\n", prog_name, sane_strstatus (status)); goto cleanup; } status = sane_get_parameters (device, &parm); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: sane_get_parameters: %s\n", prog_name, sane_strstatus (status)); goto cleanup; } if (parm.lines >= 0) fprintf (stderr, "%s: scanning image of size %dx%d pixels at " "%d bits/pixel\n", prog_name, parm.pixels_per_line, parm.lines, parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1)); else fprintf (stderr, "%s: scanning image %d pixels wide and " "variable height at %d bits/pixel\n", prog_name, parm.pixels_per_line, parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1)); fprintf (stderr, "%s: acquiring %s frame, %d bits/sample\n", prog_name, parm.format <= SANE_FRAME_BLUE ? format_name[parm.format]:"Unknown", parm.depth); image.data = malloc (parm.bytes_per_line * 2); clean_buffer (image.data, parm.bytes_per_line * 2); fprintf (stderr, "%s: reading one scanline, %d bytes...\t", prog_name, parm.bytes_per_line); status = sane_read (device, image.data, parm.bytes_per_line, &len); pass_fail (parm.bytes_per_line, len, image.data, status); if (status != SANE_STATUS_GOOD) goto cleanup; clean_buffer (image.data, parm.bytes_per_line * 2); fprintf (stderr, "%s: reading one byte...\t\t", prog_name); status = sane_read (device, image.data, 1, &len); pass_fail (1, len, image.data, status); if (status != SANE_STATUS_GOOD) goto cleanup; for (i = 2; i < parm.bytes_per_line * 2; i *= 2) { clean_buffer (image.data, parm.bytes_per_line * 2); fprintf (stderr, "%s: stepped read, %d bytes... \t", prog_name, i); status = sane_read (device, image.data, i, &len); pass_fail (i, len, image.data, status); if (status != SANE_STATUS_GOOD) goto cleanup; } for (i /= 2; i > 2; i /= 2) { clean_buffer (image.data, parm.bytes_per_line * 2); fprintf (stderr, "%s: stepped read, %d bytes... \t", prog_name, i - 1); status = sane_read (device, image.data, i - 1, &len); pass_fail (i - 1, len, image.data, status); if (status != SANE_STATUS_GOOD) goto cleanup; } cleanup: sane_cancel (device); if (image.data) free (image.data); return status; } static int get_resolution (void) { const SANE_Option_Descriptor *resopt; int resol = 0; void *val; if (resolution_optind < 0) return 0; resopt = sane_get_option_descriptor (device, resolution_optind); if (!resopt) return 0; val = alloca (resopt->size); if (!val) return 0; sane_control_option (device, resolution_optind, SANE_ACTION_GET_VALUE, val, 0); if (resopt->type == SANE_TYPE_INT) resol = *(SANE_Int *) val; else resol = (int) (SANE_UNFIX (*(SANE_Fixed *) val) + 0.5); return resol; } static void scanimage_exit (int status) { if (device) { if (verbose > 1) fprintf (stderr, "Closing device\n"); sane_close (device); } if (verbose > 1) fprintf (stderr, "Calling sane_exit\n"); sane_exit (); if (all_options) free (all_options); if (option_number) free (option_number); if (verbose > 1) fprintf (stderr, "scanimage: finished\n"); exit (status); } /** @brief print device options to stdout * * @param device struct of the opened device to describe * @param num_dev_options number of device options * @param ro SANE_TRUE to print read-only options */ static void print_options(SANE_Device * device, SANE_Int num_dev_options, SANE_Bool ro) { int i, j; const SANE_Option_Descriptor *opt; for (i = 1; i < num_dev_options; ++i) { opt = 0; /* scan area uses modified option struct */ for (j = 0; j < 4; ++j) if (i == window[j]) opt = window_option + j; if (!opt) opt = sane_get_option_descriptor (device, i); if (ro || SANE_OPTION_IS_SETTABLE (opt->cap) || opt->type == SANE_TYPE_GROUP) print_option (device, i, opt); } if (num_dev_options) fputc ('\n', stdout); } int main (int argc, char **argv) { int ch, i, index, all_options_len; const SANE_Device **device_list; SANE_Int num_dev_options = 0; const char *devname = 0; const char *defdevname = 0; const char *format = 0; char readbuf[2]; char *readbuf2; int batch = 0; int batch_print = 0; int batch_prompt = 0; int batch_count = BATCH_COUNT_UNLIMITED; int batch_start_at = 1; int batch_increment = 1; SANE_Status status; char *full_optstring; SANE_Int version_code; FILE *ofp = NULL; buffer_size = (32 * 1024); /* default size */ prog_name = strrchr (argv[0], '/'); if (prog_name) ++prog_name; else prog_name = argv[0]; defdevname = getenv ("SANE_DEFAULT_DEVICE"); sane_init (&version_code, auth_callback); /* make a first pass through the options with error printing and argument permutation disabled: */ opterr = 0; while ((ch = getopt_long (argc, argv, "-" BASE_OPTSTRING, basic_options, &index)) != EOF) { switch (ch) { case ':': case '?': break; /* may be an option that we'll parse later on */ case 'd': devname = optarg; break; case 'b': /* This may have already been set by the batch-count flag */ batch = 1; format = optarg; break; case 'h': help = 1; break; case 'i': /* icc profile */ icc_profile = optarg; break; case 'v': ++verbose; break; case 'p': progress = 1; break; case 'B': if (optarg) buffer_size = 1024 * atoi(optarg); else buffer_size = (1024 * 1024); break; case 'T': test = 1; break; case 'A': all = 1; break; case 'n': dont_scan = 1; break; case OPTION_BATCH_PRINT: batch_print = 1; break; case OPTION_BATCH_PROMPT: batch_prompt = 1; break; case OPTION_BATCH_INCREMENT: batch_increment = atoi (optarg); break; case OPTION_BATCH_START_AT: batch_start_at = atoi (optarg); break; case OPTION_BATCH_DOUBLE: batch_increment = 2; break; case OPTION_BATCH_COUNT: batch_count = atoi (optarg); batch = 1; break; case OPTION_FORMAT: if (strcmp (optarg, "tiff") == 0) output_format = OUTPUT_TIFF; else if (strcmp (optarg, "png") == 0) { #ifdef HAVE_LIBPNG output_format = OUTPUT_PNG; #else fprintf(stderr, "PNG support not compiled in\n"); exit(1); #endif } else if (strcmp (optarg, "jpeg") == 0) { #ifdef HAVE_LIBJPEG output_format = OUTPUT_JPEG; #else fprintf(stderr, "JPEG support not compiled in\n"); exit(1); #endif } else output_format = OUTPUT_PNM; break; case OPTION_MD5: accept_only_md5_auth = 1; break; case 'L': case 'f': { int i = 0; status = sane_get_devices (&device_list, SANE_FALSE); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: sane_get_devices() failed: %s\n", prog_name, sane_strstatus (status)); scanimage_exit (1); } if (ch == 'L') { for (i = 0; device_list[i]; ++i) { printf ("device `%s' is a %s %s %s\n", device_list[i]->name, device_list[i]->vendor, device_list[i]->model, device_list[i]->type); } } else { int i = 0, int_arg = 0; const char *percent, *start; const char *text_arg = 0; char ftype; for (i = 0; device_list[i]; ++i) { start = optarg; while (*start && (percent = strchr (start, '%'))) { int start_len = percent - start; percent++; if (*percent) { switch (*percent) { case 'd': text_arg = device_list[i]->name; ftype = 's'; break; case 'v': text_arg = device_list[i]->vendor; ftype = 's'; break; case 'm': text_arg = device_list[i]->model; ftype = 's'; break; case 't': text_arg = device_list[i]->type; ftype = 's'; break; case 'i': int_arg = i; ftype = 'i'; break; case 'n': text_arg = "\n"; ftype = 's'; break; case '%': text_arg = "%"; ftype = 's'; break; default: fprintf (stderr, "%s: unknown format specifier %%%c\n", prog_name, *percent); text_arg = "%"; ftype = 's'; } printf ("%.*s", start_len, start); switch (ftype) { case 's': printf ("%s", text_arg); break; case 'i': printf ("%i", int_arg); break; } start = percent + 1; } else { /* last char of the string is a '%', ignore it */ start++; break; } } if (*start) printf ("%s", start); } } if (i == 0 && ch != 'f') printf ("\nNo scanners were identified. If you were expecting " "something different,\ncheck that the scanner is plugged " "in, turned on and detected by the\nsane-find-scanner tool " "(if appropriate). Please read the documentation\nwhich came " "with this software (README, FAQ, manpages).\n"); if (defdevname) printf ("default device is `%s'\n", defdevname); scanimage_exit (0); } case 'V': printf ("scanimage (%s) %s; backend version %d.%d.%d\n", PACKAGE, VERSION, SANE_VERSION_MAJOR (version_code), SANE_VERSION_MINOR (version_code), SANE_VERSION_BUILD (version_code)); scanimage_exit (0); default: break; /* ignore device specific options for now */ } } if (help) { printf ("Usage: %s [OPTION]...\n\ \n\ Start image acquisition on a scanner device and write image data to\n\ standard output.\n\ \n\ Parameters are separated by a blank from single-character options (e.g.\n\ -d epson) and by a \"=\" from multi-character options (e.g. --device-name=epson).\n\ -d, --device-name=DEVICE use a given scanner device (e.g. hp:/dev/scanner)\n\ --format=pnm|tiff|png|jpeg file format of output file\n\ -i, --icc-profile=PROFILE include this ICC profile into TIFF file\n", prog_name); printf ("\ -L, --list-devices show available scanner devices\n\ -f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output\n\ can be specified: %%d (device name), %%v (vendor),\n\ %%m (model), %%t (type), %%i (index number), and\n\ %%n (newline)\n\ -b, --batch[=FORMAT] working in batch mode, FORMAT is `out%%d.pnm' `out%%d.tif'\n\ `out%%d.png' or `out%%d.jpg' by default depending on --format\n"); printf ("\ --batch-start=# page number to start naming files with\n\ --batch-count=# how many pages to scan in batch mode\n\ --batch-increment=# increase page number in filename by #\n\ --batch-double increment page number by two, same as\n\ --batch-increment=2\n\ --batch-print print image filenames to stdout\n\ --batch-prompt ask for pressing a key before scanning a page\n"); printf ("\ --accept-md5-only only accept authorization requests using md5\n\ -p, --progress print progress messages\n\ -n, --dont-scan only set options, don't actually scan\n\ -T, --test test backend thoroughly\n\ -A, --all-options list all available backend options\n\ -h, --help display this help message and exit\n\ -v, --verbose give even more status messages\n\ -B, --buffer-size=# change input buffer size (in kB, default 32)\n"); printf ("\ -V, --version print version information\n"); } if (!devname) { /* If no device name was specified explicitly, we look at the environment variable SANE_DEFAULT_DEVICE. If this variable is not set, we open the first device we find (if any): */ devname = defdevname; if (!devname) { status = sane_get_devices (&device_list, SANE_FALSE); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: sane_get_devices() failed: %s\n", prog_name, sane_strstatus (status)); scanimage_exit (1); } if (!device_list[0]) { fprintf (stderr, "%s: no SANE devices found\n", prog_name); scanimage_exit (1); } devname = device_list[0]->name; } } status = sane_open (devname, &device); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: open of device %s failed: %s\n", prog_name, devname, sane_strstatus (status)); if (devname[0] == '/') fprintf (stderr, "\nYou seem to have specified a UNIX device name, " "or filename instead of selecting\nthe SANE scanner or " "image acquisition device you want to use. As an example,\n" "you might want \"epson:/dev/sg0\" or " "\"hp:/dev/usbscanner0\". If any supported\ndevices are " "installed in your system, you should be able to see a " "list with\n\"scanimage --list-devices\".\n"); if (help) device = 0; else scanimage_exit (1); } if (device) { const SANE_Option_Descriptor * desc_ptr; /* Good form to always get the descriptor once before value */ desc_ptr = sane_get_option_descriptor(device, 0); if (!desc_ptr) { fprintf (stderr, "%s: unable to get option count descriptor\n", prog_name); scanimage_exit (1); } /* We got a device, find out how many options it has */ status = sane_control_option (device, 0, SANE_ACTION_GET_VALUE, &num_dev_options, 0); if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: unable to determine option count\n", prog_name); scanimage_exit (1); } /* malloc global option lists */ all_options_len = num_dev_options + NELEMS (basic_options) + 1; all_options = malloc (all_options_len * sizeof (all_options[0])); option_number_len = num_dev_options; option_number = malloc (option_number_len * sizeof (option_number[0])); if (!all_options || !option_number) { fprintf (stderr, "%s: out of memory in main()\n", prog_name); scanimage_exit (1); } /* load global option lists */ fetch_options (device); { char *larg, *targ, *xarg, *yarg; larg = targ = xarg = yarg = ""; /* Maybe accept t, l, x, and y options. */ if (window[0]) xarg = "x:"; if (window[1]) yarg = "y:"; if (window[2]) larg = "l:"; if (window[3]) targ = "t:"; /* Now allocate the full option list. */ full_optstring = malloc (strlen (BASE_OPTSTRING) + strlen (larg) + strlen (targ) + strlen (xarg) + strlen (yarg) + 1); if (!full_optstring) { fprintf (stderr, "%s: out of memory\n", prog_name); scanimage_exit (1); } strcpy (full_optstring, BASE_OPTSTRING); strcat (full_optstring, larg); strcat (full_optstring, targ); strcat (full_optstring, xarg); strcat (full_optstring, yarg); } /* re-run argument processing with backend-specific options included * this time, enable error printing and arg permutation */ optind = 0; opterr = 1; while ((ch = getopt_long (argc, argv, full_optstring, all_options, &index)) != EOF) { switch (ch) { case ':': case '?': scanimage_exit (1); /* error message is printed by getopt_long() */ case 'd': case 'h': case 'p': case 'v': case 'V': case 'T': case 'B': /* previously handled options */ break; case 'x': window_val_user[0] = 1; parse_vector (&window_option[0], optarg, &window_val[0], 1); break; case 'y': window_val_user[1] = 1; parse_vector (&window_option[1], optarg, &window_val[1], 1); break; case 'l': /* tl-x */ process_backend_option (device, window[2], optarg); break; case 't': /* tl-y */ process_backend_option (device, window[3], optarg); break; case 0: process_backend_option (device, option_number[index], optarg); break; } } if (optind < argc) { fprintf (stderr, "%s: argument without option: `%s'; ", prog_name, argv[argc - 1]); fprintf (stderr, "try %s --help\n", prog_name); scanimage_exit (1); } free (full_optstring); /* convert x/y to br_x/br_y */ for (index = 0; index < 2; ++index) if (window[index]) { SANE_Word pos = 0; SANE_Word val = window_val[index]; if (window[index + 2]) { sane_control_option (device, window[index + 2], SANE_ACTION_GET_VALUE, &pos, 0); val += pos; } set_option (device, window[index], &val); } /* output device-specific help */ if (help) { printf ("\nOptions specific to device `%s':\n", devname); print_options(device, num_dev_options, SANE_FALSE); } /* list all device-specific options */ if (all) { printf ("\nAll options specific to device `%s':\n", devname); print_options(device, num_dev_options, SANE_TRUE); scanimage_exit (0); } } /* output device list */ if (help) { printf ("\ Type ``%s --help -d DEVICE'' to get list of all options for DEVICE.\n\ \n\ List of available devices:", prog_name); status = sane_get_devices (&device_list, SANE_FALSE); if (status == SANE_STATUS_GOOD) { int column = 80; for (i = 0; device_list[i]; ++i) { if (column + strlen (device_list[i]->name) + 1 >= 80) { printf ("\n "); column = 4; } if (column > 4) { fputc (' ', stdout); column += 1; } fputs (device_list[i]->name, stdout); column += strlen (device_list[i]->name); } } fputc ('\n', stdout); scanimage_exit (0); } if (dont_scan) scanimage_exit (0); if (output_format != OUTPUT_PNM) resolution_value = get_resolution (); #ifdef SIGHUP signal (SIGHUP, sighandler); #endif #ifdef SIGPIPE signal (SIGPIPE, sighandler); #endif signal (SIGINT, sighandler); signal (SIGTERM, sighandler); if (test == 0) { int n = batch_start_at; if (batch && NULL == format) { switch(output_format) { case OUTPUT_TIFF: format = "out%d.tif"; break; case OUTPUT_PNM: format = "out%d.pnm"; break; #ifdef HAVE_LIBPNG case OUTPUT_PNG: format = "out%d.png"; break; #endif #ifdef HAVE_LIBJPEG case OUTPUT_JPEG: format = "out%d.jpg"; break; #endif } } if (!batch) ofp = stdout; if (batch) { fputs("Scanning ", stderr); if (batch_count == BATCH_COUNT_UNLIMITED) fputs("infinity", stderr); else fprintf(stderr, "%d", batch_count); fprintf (stderr, " page%s, incrementing by %d, numbering from %d\n", batch_count == 1 ? "" : "s", batch_increment, batch_start_at); } else if(isatty(fileno(ofp))){ fprintf (stderr,"%s: output is not a file, exiting\n", prog_name); scanimage_exit (1); } buffer = malloc (buffer_size); do { char path[PATH_MAX]; char part_path[PATH_MAX]; if (batch) /* format is NULL unless batch mode */ { sprintf (path, format, n); /* love --(C++) */ strcpy (part_path, path); strcat (part_path, ".part"); } if (batch) { if (batch_prompt) { fprintf (stderr, "Place document no. %d on the scanner.\n", n); fprintf (stderr, "Press to continue.\n"); fprintf (stderr, "Press Ctrl + D to terminate.\n"); readbuf2 = fgets (readbuf, 2, stdin); if (readbuf2 == NULL) { if (ofp) { fclose (ofp); ofp = NULL; } break; /* get out of this loop */ } } fprintf (stderr, "Scanning page %d\n", n); } #ifdef SANE_STATUS_WARMING_UP do { status = sane_start (device); } while(status == SANE_STATUS_WARMING_UP); #else status = sane_start (device); #endif if (status != SANE_STATUS_GOOD) { fprintf (stderr, "%s: sane_start: %s\n", prog_name, sane_strstatus (status)); if (ofp) { fclose (ofp); ofp = NULL; } break; } /* write to .part file while scanning is in progress */ if (batch) { if (NULL == (ofp = fopen (part_path, "w"))) { fprintf (stderr, "cannot open %s\n", part_path); sane_cancel (device); return SANE_STATUS_ACCESS_DENIED; } } status = scan_it (ofp); if (batch) { fprintf (stderr, "Scanned page %d.", n); fprintf (stderr, " (scanner status = %d)\n", status); } switch (status) { case SANE_STATUS_GOOD: case SANE_STATUS_EOF: status = SANE_STATUS_GOOD; if (batch) { if (!ofp || 0 != fclose(ofp)) { fprintf (stderr, "cannot close image file\n"); sane_cancel (device); return SANE_STATUS_ACCESS_DENIED; } else { ofp = NULL; /* let the fully scanned file show up */ if (rename (part_path, path)) { fprintf (stderr, "cannot rename %s to %s\n", part_path, path); sane_cancel (device); return SANE_STATUS_ACCESS_DENIED; } if (batch_print) { fprintf (stdout, "%s\n", path); fflush (stdout); } } } break; default: if (batch) { if (ofp) { fclose (ofp); ofp = NULL; } unlink (part_path); } break; } /* switch */ n += batch_increment; } while ((batch && (batch_count == BATCH_COUNT_UNLIMITED || --batch_count)) && SANE_STATUS_GOOD == status); if (batch) { int num_pgs = (n - batch_start_at) / batch_increment; fprintf (stderr, "Batch terminated, %d page%s scanned\n", num_pgs, num_pgs == 1 ? "" : "s"); } if (batch && SANE_STATUS_NO_DOCS == status && (batch_count == BATCH_COUNT_UNLIMITED) && n > batch_start_at) status = SANE_STATUS_GOOD; sane_cancel (device); } else status = test_it (); scanimage_exit (status); /* the line below avoids compiler warnings */ return status; } sane-backends-1.0.27/frontend/sicc.h0000664000175000017500000000156613106201017014132 00000000000000/* Load an ICC profile for embedding in an output file Copyright (C) 2017 Aaron Muir Hamilton This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ void * sanei_load_icc_profile (const char *path, size_t *size); sane-backends-1.0.27/frontend/stiff.h0000664000175000017500000000170412775312262014336 00000000000000/* Create SANE/tiff headers TIFF interfacing routines for SANE Copyright (C) 2000 Peter Kirchgessner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ void sanei_write_tiff_header (SANE_Frame format, int width, int height, int depth, int resolution, const char *icc_profile, FILE *ofp); sane-backends-1.0.27/README.freebsd0000664000175000017500000000341312112021330013475 00000000000000SANE and FreeBSD ---------------- Building: --------- Don't forget to use GNU make (gmake). E.g. "MAKE=gmake ./configure". SANE should compile and install out-of-the-box. If you've installed some of the optional libraries that sane-backends can make use of (see README for list) using Ports then you will need to let configure know about their locations: MAKE=gmake CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure SCSI-scanners: -------------- If the SCSI host adapter is supported, there are no known problems. USB-scanners: ------------- USB-Scanners are supported by FreeBSD. The USB scanner driver "uscanner" and access over libusb can be used. For some backends (e.g. gt68xx) you MUST use libusb. The uscanner driver won't work because it doesn't support control messages or interrupt endpoints. If you want to use libusb, your scanner should *not* be claimed by the uscanner driver. Make sure, that /dev/ugen* and /dev/usb* devices are available. Use /dev/MAKEDEV to create them, if necessary. Make sure that the user has write access to the appropriate device files. To get your scanner detected by the uscanner driver, it may be necessary to add its vendor and device ids to the kernel and recompile. Use MAKEDEV to generate the /dev/uscanner* files if they are not already there. Use sane-find-scanner to find your scanner. scanimage -L should find it automatically. Make sure that the user has read access to /dev/usb* and read and write access to /dev/uscanner*. Parport-scanners: ----------------- I don't have much information about these. The Mustek 600 II N scanner seems to work, others may or may not work. Please contact me or the SANE mailing list if you succeeded in using a parport scanner. 2005-11-01 Henning Meier-Geinitz sane-backends-1.0.27/README.linux0000664000175000017500000001544512775312260013256 00000000000000Information about USB scanners: ================================ With Linux 2.4.* you could either use the kernel scanner module or libusb to access USB scanners. In Linux 2.6.4 the kernel scanner module was removed. Therefore with this and later kernels libusb must be used. Permissions: ------------ While SANE automatically uses libusb when the library and its header file were present during the build of sane-backends, setting permissions will require some attention. So if scanimage -L lists your scanner as root but not as normal user read on this text. Most distributions support setting permissions without much manual configuration. Usually you must just add the users that are allowed to access the scanner to group "scanner". To make that change active, the user must login again. For more details, see your distribution's documentation e.g. for Debian: README.debian.gz. If this doesn't work you you want to know more, read on. The device files used by libusb are located in /proc/bus/usb/ (e.g. /proc/bus/usb/001/003) or in /dev/bus/usb/ (e.g. /dev/bus/usb/001/003), if you use udev. The exact file name can be found out by running sane-find-scanner which would print "libusb:001:003" in this case. While setting permissions with e.g. "chmod a+rw /proc/bus/usb/001/003" works, this change is not permanent. The permissions will be reset when the scanner is replugged or Linux is rebooted. One solution to set permissions on-the-fly is Linux udev which comes with current distributions. SANE comes with a udev rules file in the tools/udev directory which may be used by distributions or can be copied to /etc/udev/rules.d manually. The file format is explained on top of the file itself. Either you need libusb 0.1.12 or newer or USB_DEVFS_PATH=/dev/bus/usb must be exported as a system-wide environment variable. Older distributions may use the Linux hot-plug tools (or hotplug-ng). Your distribution should have set up the scripts to automatically change permissions correctly. Look for "libsane.usermap" and "libusbscanner" in /etc/hotplug/usb. If you build SANE from source you can use the hotplug script that comes with SANE. See the tools/hotplug/ directory in the source distribution. Please refer to the README in that directory for the details. Gentoo information: ------------------- Gentoo users: If your USB scanner is not detected at all check that USE=usb is set when emerging. Information about SCSI scanners: ================================ Under Linux, your kernel must have generic SCSI support (sg) as well as a driver for your SCSI adapter. You may want to increase the SCSI buffer size to increase scan speed. Details on all of the above can be found in sane-scsi(5). If your SCSI and sg driver are build as moduls you will need to load them with modprobe: # modprobe your-driver-name # modprobe sg You may find error messages in /var/log/messages. Look at the documentation for your SCSI driver. Maybe you need to add options like the io port. Now the SCSI adapter and your scanner should be visible at /proc/scsi/scsi. Example: # cat /proc/scsi/scsi Host: scsi0 Channel: 00 Id: 06 Lun: 00 Vendor: SCANNER Model: Rev: 2.02 Type: Scanner ANSI SCSI revision: 01 CCS In this case the real vendor and scanner name are not shown (Mustek Scannexpress 12000SP) but SANE will detect it nevertheless. If your scanner is supported by SANE, scanimage -L will list it now: # scanimage -L device mustek:/dev/scanner' is a Mustek ScanExpress 12000SP flatbed scanner If this doesn't work you may have to add the right SCSI generic device name to the configuration file. This should be documented in the man page for your backend. To find out about the right SCSI device use sane-find-scanner: # sane-find-scanner found SCSI scanner "SCANNER 2.02" at /dev/scanner found SCSI scanner "SCANNER 2.02" at /dev/sg0 found SCSI scanner "SCANNER 2.02" at /dev/sga It may help to set a symbolic link /dev/scanner to the respective device if automatic detection does not work. If you need more information on the Linux SCSI subsystem, look at http://www.torque.net/scsi/linux_scsi_24/index.html. Although this documentation is about the 2.4 kernels, large parts are also valid for older kernels. One important exception is the section on "Device Names in devfs". Adaptec 1542 SCSI adapter: Using buffer sizes of more than 32768 bytes with the aha1542 driver can lead to kernel panic with older kernels. To avoid this, run configure with the option --enable-scsibuffersize or set the environment variable SANE_SG_BUFFERSIZE to 32768 before running scanimage or another frontend, or download and install the SG driver 2.1.37 or newer from http://www.torque.net/sg. idescsi: The Linux kernel "Emulation of a SCSI host adapter for IDE ATAPI devices" (idescsi) is reported to cause problems in connection with SANE. If your scanner isn't found or you encounter segmentation faults try to disable idescsi. SCSI Direct IO: Recent versions of the Linux SG driver for the 2.4 kernels support direct IO, i.e., the SCSI adapter's DMA chip copies data directly to/from user memory. Direct IO reduces memory usage, but it can lead to access conflicts, if a backend uses shared memory. SANE does not use direct IO by default. If you want to use it, run configure --enable-scsi-directio=yes Very old Linux distributions are missing the /usr/include/scsi directory. In such a case, it is necessary to copy the relevant files from the kernel distribution. Normally, the command: cp -a /usr/src/linux/include/scsi /usr/include should fix this problem. Don't do this if you don't get compilation errors about missing SCSI headers. Other Information ================= ld.so.conf configuration: "/usr/local/lib/sane" or "/usr/lib/sane" MUST NOT be listed in /etc/ld.so.conf. If your scanner is not detected or only Video for Linux devices are found, check for one of the above lines in ld.so.conf. A line "/usr/local/lib" or "/usr/lib" in ld.so.conf is ok, however. Excessive warnings "pointer of type `void *' used in arithmetic": Some older versions of glibc generate these warnings not related to SANE source code. To suppress these warnings do export CFLAGS="-g -O2 -D__NO_STRING_INLINES" and rerun configure. If you use DEC cc on Linux Alpha, you may need to set LDFLAGS="-N" to be able to build sane-backends. The Intel C++ Compiler for IA32 and IA64 isn't supported yet. If you want to try nevertheless, you will experience undefined references to inb and outb functions. To avoid those replace #include with #if defined(__ICC) && __ICC >= 700 # define __GNUC__ 2 #endif #include #if defined(__ICC) && __ICC >= 700 # undef __GNUC__ #elif defined(__ICC) && defined(HAVE_ASM_IO_H) # include #endif Have a lot of fun with the latest SANE backend. sane-backends-1.0.27/README.djpeg0000664000175000017500000004730112112021330013160 00000000000000The JPEG decoder in SANE is taken mostly without change from The Independent JPEG Group's JPEG software, release 6a. Their "djpeg.README" file is included below. The only changes are to file names, e.g. djpeg.c -> sanei_jpeg.c, and function names, e.g. sanei_jpeg_start_output_ppm() The Independent JPEG Group's JPEG software ========================================== README for release 6a of 7-Feb-96 ================================= This distribution contains the sixth public release of the Independent JPEG Group's free JPEG software. You are welcome to redistribute this software and to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. Serious users of this software (particularly those incorporating it into larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to our electronic mailing list. Mailing list members are notified of updates and have a chance to participate in technical discussions, etc. This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Jim Boucher, Lee Crocker, Julian Minguillon, George Phillips, Davide Rossi, Ge' Weijers, and other members of the Independent JPEG Group. IJG is not affiliated with the official ISO JPEG standards committee. DOCUMENTATION ROADMAP ===================== This file contains the following sections: OVERVIEW General description of JPEG and the IJG software. LEGAL ISSUES Copyright, lack of warranty, terms of distribution. REFERENCES Where to learn more about JPEG. ARCHIVE LOCATIONS Where to find newer versions of this software. RELATED SOFTWARE Other stuff you should get. FILE FORMAT WARS Software *not* to get. TO DO Plans for future IJG releases. Other documentation files in the distribution are: User documentation: install.doc How to configure and install the IJG software. usage.doc Usage instructions for cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom. *.1 Unix-style man pages for programs (same info as usage.doc). wizard.doc Advanced usage instructions for JPEG wizards only. change.log Version-to-version change highlights. Programmer and internal documentation: libjpeg.doc How to use the JPEG library in your own programs. example.c Sample code for calling the JPEG library. structure.doc Overview of the JPEG library's internal structure. filelist.doc Road map of IJG files. coderules.doc Coding style rules --- please read if you contribute code. Please read at least the files install.doc and usage.doc. Useful information can also be found in the JPEG FAQ (Frequently Asked Questions) article. See ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. If you want to understand how the JPEG code works, we suggest reading one or more of the REFERENCES, then looking at the documentation files (in roughly the order listed) before diving into the code. OVERVIEW ======== This package contains C software to implement JPEG image compression and decompression. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and gray-scale images. JPEG is intended for compressing "real-world" scenes; line drawings, cartoons and other non-realistic images are not its strong suit. JPEG is lossy, meaning that the output image is not exactly identical to the input image. Hence you must not use JPEG if you have to have identical output bits. However, on typical photographic images, very good compression levels can be obtained with no visible change, and remarkably high compression levels are possible if you can tolerate a low-quality image. For more details, see the references, or just experiment with various compression settings. This software implements JPEG baseline, extended-sequential, and progressive compression processes. Provision is made for supporting all variants of these processes, although some uncommon parameter settings aren't implemented yet. For legal reasons, we are not distributing code for the arithmetic-coding variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting the hierarchical or lossless processes defined in the standard. We provide a set of library routines for reading and writing JPEG image files, plus two sample applications "cjpeg" and "djpeg", which use the library to perform conversion between JPEG and some other popular image file formats. The library is intended to be reused in other applications. In order to support file conversion and viewing software, we have included considerable functionality beyond the bare JPEG coding/decoding capability; for example, the color quantization modules are not strictly part of JPEG decoding, but they are essential for output to colormapped file formats or colormapped displays. These extra functions can be compiled out of the library if not required for a particular application. We have also included "jpegtran", a utility for lossless transcoding between different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple applications for inserting and extracting textual comments in JFIF files. The emphasis in designing this software has been on achieving portability and flexibility, while also making it fast enough to be useful. In particular, the software is not intended to be read as a tutorial on JPEG. (See the REFERENCES section for introductory material.) Rather, it is intended to be reliable, portable, industrial-strength code. We do not claim to have achieved that goal in every aspect of the software, but we strive for it. We welcome the use of this software as a component of commercial products. No royalty is required, but we do ask for an acknowledgement in product documentation, as described under LEGAL ISSUES. LEGAL ISSUES ============ In plain English: 1. We don't promise that this software works. (But if you find any bugs, please let us know!) 2. You can use this software for whatever you want. You don't have to pay us. 3. You may not pretend that you wrote this software. If you use it in a program, you must acknowledge somewhere in your documentation that you've used the IJG code. In legalese: The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. This software is copyright (C) 1991-1996, Thomas G. Lane. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this software (or portions thereof) for any purpose, without fee, subject to these conditions: (1) If any part of the source code for this software is distributed, then this README file must be included, with this copyright and no-warranty notice unaltered; and any additions, deletions, or changes to the original files must be clearly indicated in accompanying documentation. (2) If only executable code is distributed, then the accompanying documentation must state that "this software is based in part on the work of the Independent JPEG Group". (3) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. These conditions apply to any software derived from or based on the IJG code, not just to the unmodified library. If you use our work, you ought to acknowledge us. Permission is NOT granted for the use of any IJG author's name or company name in advertising or publicity relating to this software or products derived from it. This software may be referred to only as "the Independent JPEG Group's software". We specifically permit and encourage the use of this software as the basis of commercial products, provided that all warranty or liability claims are assumed by the product vendor. ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. ansi2knr.c is NOT covered by the above copyright and conditions, but instead by the usual distribution terms of the Free Software Foundation; principally, that you must include source code if you redistribute it. (See the file ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part of any program generated from the IJG code, this does not limit you more than the foregoing paragraphs do. The configuration script "configure" was produced with GNU Autoconf. It is copyright by the Free Software Foundation but is freely distributable. It appears that the arithmetic coding option of the JPEG spec is covered by patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot legally be used without obtaining one or more licenses. For this reason, support for arithmetic coding has been removed from the free JPEG software. (Since arithmetic coding provides only a marginal gain over the unpatented Huffman mode, it is unlikely that very many implementations will support it.) So far as we are aware, there are no patent restrictions on the remaining code. WARNING: Unisys has begun to enforce their patent on LZW compression against GIF encoders and decoders. You will need a license from Unisys to use the included rdgif.c or wrgif.c files in a commercial or shareware application. At this time, Unisys is not enforcing their patent against freeware, so distribution of this package remains legal. However, we intend to remove GIF support from the IJG package as soon as a suitable replacement format becomes reasonably popular. We are required to state that "The Graphics Interchange Format(c) is the Copyright property of CompuServe Incorporated. GIF(sm) is a Service Mark property of CompuServe Incorporated." REFERENCES ========== We highly recommend reading one or more of these references before trying to understand the innards of the JPEG software. The best short technical introduction to the JPEG compression algorithm is Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. (Adjacent articles in that issue discuss MPEG motion picture compression, applications of JPEG, and related topics.) If you don't have the CACM issue handy, a PostScript file containing a revised version of Wallace's article is available at ftp.uu.net, graphics/jpeg/wallace.ps.gz. The file (actually a preprint for an article that appeared in IEEE Trans. Consumer Electronics) omits the sample images that appeared in CACM, but it includes corrections and some added material. Note: the Wallace article is copyright ACM and IEEE, and it may not be used for commercial purposes. A somewhat less technical, more leisurely introduction to JPEG can be found in "The Data Compression Book" by Mark Nelson, published by M&T Books (Redwood City, CA), 1991, ISBN 1-55851-216-0. This book provides good explanations and example C code for a multitude of compression methods including JPEG. It is an excellent source if you are comfortable reading C code but don't know much about data compression in general. The book's JPEG sample code is far from industrial-strength, but when you are ready to look at a full implementation, you've got one here... The best full description of JPEG is the textbook "JPEG Still Image Data Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG standards (DIS 10918-1 and draft DIS 10918-2). This is by far the most complete exposition of JPEG in existence, and we highly recommend it. The JPEG standard itself is not available electronically; you must order a paper copy through ISO or ITU. (Unless you feel a need to own a certified official copy, we recommend buying the Pennebaker and Mitchell book instead; it's much cheaper and includes a great deal of useful explanatory material.) In the USA, copies of the standard may be ordered from ANSI Sales at (212) 642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI doesn't take credit card orders, but Global does.) It's not cheap: as of 1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% shipping/handling. The standard is divided into two parts, Part 1 being the actual specification, while Part 2 covers compliance testing methods. Part 1 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS 10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and has document numbers ISO/IEC IS 10918-2, ITU-T T.83. Extensions to the original JPEG standard are defined in JPEG Part 3, a new ISO document. Part 3 is undergoing ISO balloting and is expected to be approved by the end of 1995; it will have document numbers ISO/IEC IS 10918-3, ITU-T T.84. IJG currently does not support any Part 3 extensions. The JPEG standard does not specify all details of an interchangeable file format. For the omitted details we follow the "JFIF" conventions, revision 1.02. A copy of the JFIF spec is available from: Literature Department C-Cube Microsystems, Inc. 1778 McCarthy Blvd. Milpitas, CA 95035 phone (408) 944-6300, fax (408) 944-6314 A PostScript version of this document is available at ftp.uu.net, file graphics/jpeg/jfif.ps.gz. It can also be obtained by e-mail from the C-Cube mail server, netlib@c3.pla.ca.us. Send the message "send jfif_ps from jpeg" to the server to obtain the JFIF document; send the message "help" if you have trouble. The TIFF 6.0 file format specification can be obtained by FTP from sgi.com (192.48.153.1), file graphics/tiff/TIFF6.ps.Z; or you can order a printed copy from Aldus Corp. at (206) 628-6593. The JPEG incorporation scheme found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 (Compression tag 7). Copies of this Note can be obtained from sgi.com or from ftp.uu.net:/graphics/jpeg/. It is expected that the next revision of the TIFF spec will replace the 6.0 JPEG design with the Note's design. Although IJG's own code does not support TIFF/JPEG, the free libtiff library uses our library to implement TIFF/JPEG per the Note. libtiff is available from sgi.com:/graphics/tiff/. ARCHIVE LOCATIONS ================= The "official" archive site for this software is ftp.uu.net (Internet address 192.48.96.9). The most recent released version can always be found there in directory graphics/jpeg. This particular version will be archived as graphics/jpeg/jpegsrc.v6a.tar.gz. If you are on the Internet, you can retrieve files from ftp.uu.net by standard anonymous FTP. If you don't have FTP access, UUNET's archives are also available via UUCP; contact help@uunet.uu.net for information on retrieving files that way. Numerous Internet sites maintain copies of the UUNET files. However, only ftp.uu.net is guaranteed to have the latest official version. You can also obtain this software in DOS-compatible "zip" archive format from the SimTel archives (ftp.coast.net:/SimTel/msdos/graphics/), or on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 "JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net release. The JPEG FAQ (Frequently Asked Questions) article is a useful source of general information about JPEG. It is updated constantly and therefore is not included in this distribution. The FAQ is posted every two weeks to Usenet newsgroups comp.graphics.misc, news.answers, and other groups. You can always obtain the latest version from the news.answers archive at rtfm.mit.edu. By FTP, fetch /pub/usenet/news.answers/jpeg-faq/part1 and .../part2. If you don't have FTP, send e-mail to mail-server@rtfm.mit.edu with body send usenet/news.answers/jpeg-faq/part1 send usenet/news.answers/jpeg-faq/part2 RELATED SOFTWARE ================ Numerous viewing and image manipulation programs now support JPEG. (Quite a few of them use this library to do so.) The JPEG FAQ described above lists some of the more popular free and shareware viewers, and tells where to obtain them on Internet. If you are on a Unix machine, we highly recommend Jef Poskanzer's free PBMPLUS image software, which provides many useful operations on PPM-format image files. In particular, it can convert PPM images to and from a wide range of other formats. You can obtain this package by FTP from ftp.x.org (contrib/pbmplus*.tar.Z) or ftp.ee.lbl.gov (pbmplus*.tar.Z). There is also a newer update of this package called NETPBM, available from wuarchive.wustl.edu under directory /graphics/graphics/packages/NetPBM/. Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; you are likely to have difficulty making it work on any non-Unix machine. A different free JPEG implementation, written by the PVRG group at Stanford, is available from havefun.stanford.edu in directory pub/jpeg. This program is designed for research and experimentation rather than production use; it is slower, harder to use, and less portable than the IJG code, but it is easier to read and modify. Also, the PVRG code supports lossless JPEG, which we do not. FILE FORMAT WARS ================ Some JPEG programs produce files that are not compatible with our library. The root of the problem is that the ISO JPEG committee failed to specify a concrete file format. Some vendors "filled in the blanks" on their own, creating proprietary formats that no one else could read. (For example, none of the early commercial JPEG implementations for the Macintosh were able to exchange compressed files.) The file format we have adopted is called JFIF (see REFERENCES). This format has been agreed to by a number of major commercial JPEG vendors, and it has become the de facto standard. JFIF is a minimal or "low end" representation. We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF Technical Note #2) for "high end" applications that need to record a lot of additional data about an image. TIFF/JPEG is fairly new and not yet widely supported, unfortunately. The upcoming JPEG Part 3 standard defines a file format called SPIFF. SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should be able to read the most common variant of SPIFF. SPIFF has some technical advantages over JFIF, but its major claim to fame is simply that it is an official standard rather than an informal one. At this point it is unclear whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto standard. IJG intends to support SPIFF once the standard is frozen, but we have not decided whether it should become our default output format or not. (In any case, our decoder will remain capable of reading JFIF indefinitely.) Various proprietary file formats incorporating JPEG compression also exist. We have little or no sympathy for the existence of these formats. Indeed, one of the original reasons for developing this free software was to help force convergence on common, open format standards for JPEG files. Don't use a proprietary file format! TO DO ===== In future versions, we are considering supporting some of the upcoming JPEG Part 3 extensions --- principally, variable quantization and the SPIFF file format. Tuning the software for better behavior at low quality/high compression settings is also of interest. The current method for scaling the quantization tables is known not to be very good at low Q values. As always, speeding things up is high on our priority list. Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. sane-backends-1.0.27/acinclude.m40000664000175000017500000004655612775312260013440 00000000000000dnl dnl Contains the following macros dnl SANE_SET_AM_CFLAGS(is_release) dnl SANE_CHECK_MISSING_HEADERS dnl SANE_SET_AM_LDFLAGS dnl SANE_CHECK_DLL_LIB dnl SANE_EXTRACT_LDFLAGS(LIBS, LDFLAGS) dnl SANE_CHECK_JPEG dnl SANE_CHECK_IEEE1284 dnl SANE_CHECK_PTHREAD dnl SANE_CHECK_LOCKING dnl JAPHAR_GREP_AM_CFLAGS(flag, cmd_if_missing, cmd_if_present) dnl SANE_CHECK_U_TYPES dnl SANE_CHECK_GPHOTO2 dnl SANE_CHECK_IPV6 dnl SANE_CHECK_BACKENDS dnl SANE_PROTOTYPES dnl AC_PROG_LIBTOOL dnl # SANE_SET_AM_CFLAGS(is_release) # Set default AM_CFLAGS if gcc is used. Enable/disable additional # compilation warnings. The extra warnings are enabled by default # during the development cycle but disabled for official releases. # The argument is_release is either yes or no. AC_DEFUN([SANE_SET_AM_CFLAGS], [ if test "${ac_cv_c_compiler_gnu}" = "yes"; then DEFAULT_CFLAGS="\ -Wall" EXTRA_WARNINGS="\ -Wextra \ -pedantic" for flag in $DEFAULT_CFLAGS; do JAPHAR_GREP_AM_CFLAGS($flag, [ AM_CFLAGS="$AM_CFLAGS $flag" ]) done AC_ARG_ENABLE(warnings, AS_HELP_STRING([--enable-warnings], [turn on tons of compiler warnings (GCC only)]), [ if eval "test x$enable_warnings = xyes"; then for flag in $EXTRA_WARNINGS; do JAPHAR_GREP_AM_CFLAGS($flag, [ AM_CFLAGS="$AM_CFLAGS $flag" ]) done fi ], [if test x$1 = xno; then # Warnings enabled by default (development) for flag in $EXTRA_WARNINGS; do JAPHAR_GREP_AM_CFLAGS($flag, [ AM_CFLAGS="$AM_CFLAGS $flag" ]) done fi]) fi # ac_cv_c_compiler_gnu ]) dnl SANE_CHECK_MISSING_HEADERS dnl Do some sanity checks. It doesn't make sense to proceed if those headers dnl aren't present. AC_DEFUN([SANE_CHECK_MISSING_HEADERS], [ MISSING_HEADERS= if test "${ac_cv_header_fcntl_h}" != "yes" ; then MISSING_HEADERS="${MISSING_HEADERS}\"fcntl.h\" " fi if test "${ac_cv_header_sys_time_h}" != "yes" ; then MISSING_HEADERS="${MISSING_HEADERS}\"sys/time.h\" " fi if test "${ac_cv_header_unistd_h}" != "yes" ; then MISSING_HEADERS="${MISSING_HEADERS}\"unistd.h\" " fi if test "${ac_cv_header_stdc}" != "yes" ; then MISSING_HEADERS="${MISSING_HEADERS}\"ANSI C headers\" " fi if test "${MISSING_HEADERS}" != "" ; then echo "*** The following essential header files couldn't be found:" echo "*** ${MISSING_HEADERS}" echo "*** Maybe the compiler isn't ANSI C compliant or not properly installed?" echo "*** For details on what went wrong see config.log." AC_MSG_ERROR([Exiting now.]) fi ]) # SANE_SET_AM_LDFLAGS # Add special AM_LDFLAGS AC_DEFUN([SANE_SET_AM_LDFLAGS], [ # Define stricter linking policy on GNU systems. This is not # added to global LDFLAGS because we may want to create convenience # libraries that don't require such strick linking. if test "$GCC" = yes; then case ${host_os} in linux* | solaris*) STRICT_LDFLAGS="-Wl,-z,defs" ;; esac fi AC_SUBST(STRICT_LDFLAGS) case "${host_os}" in aix*) #enable .so libraries, disable archives AM_LDFLAGS="$AM_LDFLAGS -Wl,-brtl" ;; darwin*) #include frameworks LIBS="$LIBS -framework CoreFoundation -framework IOKit" ;; esac ]) # SANE_CHECK_DLL_LIB # Find dll library AC_DEFUN([SANE_CHECK_DLL_LIB], [ dnl Checks for dll libraries: dl DL_LIBS="" if test "${enable_dynamic}" = "auto"; then # default to disabled unless library found. enable_dynamic=no # dlopen AC_CHECK_HEADERS(dlfcn.h, [AC_CHECK_LIB(dl, dlopen, DL_LIBS=-ldl) saved_LIBS="${LIBS}" LIBS="${LIBS} ${DL_LIBS}" AC_CHECK_FUNCS(dlopen, enable_dynamic=yes,) LIBS="${saved_LIBS}" ],) # HP/UX DLL handling AC_CHECK_HEADERS(dl.h, [AC_CHECK_LIB(dld,shl_load, DL_LIBS=-ldld) saved_LIBS="${LIBS}" LIBS="${LIBS} ${DL_LIBS}" AC_CHECK_FUNCS(shl_load, enable_dynamic=yes,) LIBS="${saved_LIBS}" ],) if test -z "$DL_LIBS" ; then # old Mac OS X/Darwin (without dlopen) AC_CHECK_HEADERS(mach-o/dyld.h, [AC_CHECK_FUNCS(NSLinkModule, enable_dynamic=yes,) ],) fi fi AC_SUBST(DL_LIBS) DYNAMIC_FLAG= if test "${enable_dynamic}" = yes ; then DYNAMIC_FLAG=-module fi AC_SUBST(DYNAMIC_FLAG) ]) # # Separate LIBS from LDFLAGS to link correctly on HP/UX (and other # platforms who care about the order of params to ld. It removes all # non '-l..'-params from passed in $1(LIBS), and appends them to $2(LDFLAGS). # # Use like this: SANE_EXTRACT_LDFLAGS(PKGNAME_LIBS, PKGNAME_LDFLAGS) AC_DEFUN([SANE_EXTRACT_LDFLAGS], [ tmp_LIBS="" for param in ${$1}; do case "${param}" in -l*) tmp_LIBS="${tmp_LIBS} ${param}" ;; *) $2="${$2} ${param}" ;; esac done $1="${tmp_LIBS}" unset tmp_LIBS unset param ]) # # # Checks for ieee1284 library, needed for canon_pp backend. AC_DEFUN([SANE_CHECK_IEEE1284], [ AC_CHECK_HEADER(ieee1284.h, [ AC_CACHE_CHECK([for libieee1284 >= 0.1.5], sane_cv_use_libieee1284, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ struct parport p; char *buf; ieee1284_nibble_read(&p, 0, buf, 1); ]])], [sane_cv_use_libieee1284="yes"; IEEE1284_LIBS="-lieee1284" ],[sane_cv_use_libieee1284="no"]) ],) ],) if test "$sane_cv_use_libieee1284" = "yes" ; then AC_DEFINE(HAVE_LIBIEEE1284,1,[Define to 1 if you have the `ieee1284' library (-lcam).]) fi AC_SUBST(IEEE1284_LIBS) ]) # # Checks for pthread support AC_DEFUN([SANE_CHECK_PTHREAD], [ case "${host_os}" in linux* | darwin* | mingw*) # enabled by default on Linux, MacOS X and MINGW use_pthread=yes ;; *) use_pthread=no esac have_pthread=no # # now that we have the systems preferences, we check # the user AC_ARG_ENABLE([pthread], AS_HELP_STRING([--enable-pthread], [use pthread instead of fork (default=yes for Linux/MacOS X/MINGW, no for everything else)]), [ if test $enableval = yes ; then use_pthread=yes else use_pthread=no fi ]) if test $use_pthread = yes ; then AC_CHECK_HEADERS(pthread.h, [ AC_CHECK_LIB(pthread, pthread_create, PTHREAD_LIBS="-lpthread") have_pthread=yes save_LIBS="$LIBS" LIBS="$LIBS $PTHREAD_LIBS" AC_CHECK_FUNCS([pthread_create pthread_kill pthread_join pthread_detach pthread_cancel pthread_testcancel], ,[ have_pthread=no; use_pthread=no ]) LIBS="$save_LIBS" ],[ have_pthread=no; use_pthread=no ]) fi if test $use_pthread = yes ; then AC_DEFINE_UNQUOTED(USE_PTHREAD, "$use_pthread", [Define if pthreads should be used instead of forked processes.]) else dnl Reset library in case it was found but we are not going to use it. PTHREAD_LIBS="" fi if test "$have_pthread" = "yes" ; then AM_CPPFLAGS="${AM_CPPFLAGS} -D_REENTRANT" fi AC_SUBST(PTHREAD_LIBS) AC_MSG_CHECKING([whether to enable pthread support]) AC_MSG_RESULT([$have_pthread]) AC_MSG_CHECKING([whether to use pthread instead of fork]) AC_MSG_RESULT([$use_pthread]) ]) # # Checks for jpeg library >= v6B (61), needed for DC210, DC240, # GPHOTO2 and dell1600n_net backends. AC_DEFUN([SANE_CHECK_JPEG], [ AC_CHECK_LIB(jpeg,jpeg_start_decompress, [ AC_CHECK_HEADER(jconfig.h, [ AC_MSG_CHECKING([for jpeglib - version >= 61 (6a)]) AC_EGREP_CPP(sane_correct_jpeg_lib_version_found, [ #include #if JPEG_LIB_VERSION >= 61 sane_correct_jpeg_lib_version_found #endif ], [sane_cv_use_libjpeg="yes"; JPEG_LIBS="-ljpeg"; AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)]) ],) ],) if test "$sane_cv_use_libjpeg" = "yes" ; then AC_DEFINE(HAVE_LIBJPEG,1,[Define to 1 if you have the libjpeg library.]) fi AC_SUBST(JPEG_LIBS) ]) # Checks for tiff library dell1600n_net backend. AC_DEFUN([SANE_CHECK_TIFF], [ AC_CHECK_LIB(tiff,TIFFFdOpen, [ AC_CHECK_HEADER(tiffio.h, [sane_cv_use_libtiff="yes"; TIFF_LIBS="-ltiff"],) ],) AC_SUBST(TIFF_LIBS) ]) AC_DEFUN([SANE_CHECK_PNG], [ AC_CHECK_LIB(png,png_init_io, [ AC_CHECK_HEADER(png.h, [sane_cv_use_libpng="yes"; PNG_LIBS="-lpng"],) ],) if test "$sane_cv_use_libpng" = "yes" ; then AC_DEFINE(HAVE_LIBPNG,1,[Define to 1 if you have the libpng library.]) fi AC_SUBST(PNG_LIBS) ]) # # Checks for pthread support AC_DEFUN([SANE_CHECK_LOCKING], [ LOCKPATH_GROUP=uucp use_locking=yes case "${host_os}" in os2* ) use_locking=no ;; esac # # we check the user AC_ARG_ENABLE( [locking], AS_HELP_STRING([--enable-locking], [activate device locking (default=yes, but only used by some backends)]), [ if test $enableval = yes ; then use_locking=yes else use_locking=no fi ]) if test $use_locking = yes ; then AC_ARG_WITH([group], AS_HELP_STRING([--with-group], [use the specified group for lock dir @<:@default=uucp@:>@]), [LOCKPATH_GROUP="$withval"] ) # check if the group does exist lasterror="" touch sanetest.file chgrp $LOCKPATH_GROUP sanetest.file 2>/dev/null || lasterror=$? rm -f sanetest.file if test ! -z "$lasterror"; then AC_MSG_WARN([Group $LOCKPATH_GROUP does not exist on this system.]) AC_MSG_WARN([Locking feature will be disabled.]) use_locking=no fi fi if test $use_locking = yes ; then INSTALL_LOCKPATH=install-lockpath AC_DEFINE([ENABLE_LOCKING], 1, [Define to 1 if device locking should be enabled.]) else INSTALL_LOCKPATH= fi AC_MSG_CHECKING([whether to enable device locking]) AC_MSG_RESULT([$use_locking]) if test $use_locking = yes ; then AC_MSG_NOTICE([Setting lockdir group to $LOCKPATH_GROUP]) fi AC_SUBST(INSTALL_LOCKPATH) AC_SUBST(LOCKPATH_GROUP) ]) dnl dnl JAPHAR_GREP_AM_CFLAGS(flag, cmd_if_missing, cmd_if_present) dnl dnl From Japhar. Report changes to japhar@hungry.com dnl AC_DEFUN([JAPHAR_GREP_AM_CFLAGS], [case "$AM_CFLAGS" in "$1" | "$1 "* | *" $1" | *" $1 "* ) ifelse($#, 3, [$3], [:]) ;; *) $2 ;; esac ]) dnl dnl SANE_CHECK_U_TYPES dnl AC_DEFUN([SANE_CHECK_U_TYPES], [ dnl Use new style of check types that doesn't take default to use. dnl The old style would add an #undef of the type check on platforms dnl that defined that type... That is not portable to platform that dnl define it as a #define. AC_CHECK_TYPES([u_char, u_short, u_int, u_long],,,) ]) # # Checks for gphoto2 libs, needed by gphoto2 backend AC_DEFUN([SANE_CHECK_GPHOTO2], [ AC_ARG_WITH(gphoto2, AS_HELP_STRING([--with-gphoto2], [include the gphoto2 backend @<:@default=yes@:>@]), [# If --with-gphoto2=no or --without-gphoto2, disable backend # as "$with_gphoto2" will be set to "no"]) # If --with-gphoto2=yes (or not supplied), first check if # pkg-config exists, then use it to check if libgphoto2 is # present. If all that works, then see if we can actually link # a program. And, if that works, then add the -l flags to # GPHOTO2_LIBS and any other flags to GPHOTO2_LDFLAGS to pass to # sane-config. if test "$with_gphoto2" != "no" ; then AC_CHECK_TOOL(HAVE_GPHOTO2, pkg-config, false) if test ${HAVE_GPHOTO2} != "false" ; then if pkg-config --exists libgphoto2 ; then with_gphoto2="`pkg-config --modversion libgphoto2`" GPHOTO2_CPPFLAGS="`pkg-config --cflags libgphoto2`" GPHOTO2_LIBS="`pkg-config --libs libgphoto2`" saved_CPPFLAGS="${CPPFLAGS}" CPPFLAGS="${GPHOTO2_CPPFLAGS}" saved_LIBS="${LIBS}" LIBS="${LIBS} ${GPHOTO2_LIBS}" # Make sure we an really use the library AC_CHECK_FUNCS(gp_camera_init, HAVE_GPHOTO2=true, HAVE_GPHOTO2=false) if test "${HAVE_GPHOTO2}" = "true"; then AC_CHECK_FUNCS(gp_port_info_get_path) fi CPPFLAGS="${saved_CPPFLAGS}" LIBS="${saved_LIBS}" else HAVE_GPHOTO2=false fi if test "${HAVE_GPHOTO2}" = "false"; then GPHOTO2_CPPFLAGS="" GPHOTO2_LIBS="" else SANE_EXTRACT_LDFLAGS(GPHOTO2_LIBS, GPHOTO2_LDFLAGS) if pkg-config --atleast-version=2.5.0 libgphoto2; then AC_DEFINE([GPLOGFUNC_NO_VARGS], [1], [Define if GPLogFunc does not take a va_list.]) fi fi fi fi AC_SUBST(GPHOTO2_CPPFLAGS) AC_SUBST(GPHOTO2_LIBS) AC_SUBST(GPHOTO2_LDFLAGS) ]) # # Check for AF_INET6, determines whether or not to enable IPv6 support # Check for ss_family member in struct sockaddr_storage AC_DEFUN([SANE_CHECK_IPV6], [ AC_MSG_CHECKING([whether to enable IPv6]) AC_ARG_ENABLE(ipv6, AS_HELP_STRING([--disable-ipv6],[disable IPv6 support]), [ if test "$enableval" = "no" ; then AC_MSG_RESULT([no, manually disabled]) ipv6=no fi ]) if test "$ipv6" != "no" ; then AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define INET6 #include #include ]], [[ /* AF_INET6 available check */ if (socket(AF_INET6, SOCK_STREAM, 0) < 0) exit(1); else exit(0); ]])],[ AC_MSG_RESULT(yes) AC_DEFINE([ENABLE_IPV6], 1, [Define to 1 if the system supports IPv6]) ipv6=yes ],[ AC_MSG_RESULT([no (couldn't compile test program)]) ipv6=no ]) fi if test "$ipv6" != "no" ; then AC_MSG_CHECKING([whether struct sockaddr_storage has an ss_family member]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define INET6 #include #include ]], [[ /* test if the ss_family member exists in struct sockaddr_storage */ struct sockaddr_storage ss; ss.ss_family = AF_INET; exit (0); ]])], [ AC_MSG_RESULT(yes) AC_DEFINE([HAS_SS_FAMILY], 1, [Define to 1 if struct sockaddr_storage has an ss_family member]) ], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define INET6 #include #include ]], [[ /* test if the __ss_family member exists in struct sockaddr_storage */ struct sockaddr_storage ss; ss.__ss_family = AF_INET; exit (0); ]])], [ AC_MSG_RESULT([no, but __ss_family exists]) AC_DEFINE([HAS___SS_FAMILY], 1, [Define to 1 if struct sockaddr_storage has __ss_family instead of ss_family]) ], [ AC_MSG_RESULT([no]) ipv6=no ]) ]) fi ]) # # Verifies that values in $BACKENDS and updates FILTERED_BACKEND # with either backends that can be compiled or fails the script. AC_DEFUN([SANE_CHECK_BACKENDS], [ if test "${user_selected_backends}" = "yes"; then DISABLE_MSG="aborting" else DISABLE_MSG="disabling" fi FILTERED_BACKENDS="" for be in ${BACKENDS}; do backend_supported="yes" case $be in plustek_pp) case "$host_os" in gnu*) echo "*** $be backend not supported on GNU/Hurd - $DISABLE_MSG" backend_supported="no" ;; esac ;; dc210|dc240) if test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires JPEG library - $DISABLE_MSG" backend_supported="no" fi ;; canon_pp|hpsj5s) if test "${sane_cv_use_libieee1284}" != "yes"; then echo "*** $be backend requires libieee1284 library - $DISABLE_MSG" backend_supported="no" fi ;; mustek_pp) if test "${sane_cv_use_libieee1284}" != "yes" && test "${enable_parport_directio}" != "yes"; then echo "*** $be backend requires libieee1284 or parport-directio libraries - $DISABLE_MSG" backend_supported="no" fi ;; dell1600n_net) if test "${sane_cv_use_libjpeg}" != "yes" || test "${sane_cv_use_libtiff}" != "yes"; then echo "*** $be backend requires JPEG and TIFF library - $DISABLE_MSG" backend_supported="no" fi ;; epsonds) if test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires JPEG library - $DISABLE_MSG" backend_supported="no" fi ;; gphoto2) if test "${HAVE_GPHOTO2}" != "true" \ || test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires gphoto2 and JPEG libraries - $DISABLE_MSG" backend_supported="no" fi ;; pint) if test "${ac_cv_header_sys_scanio_h}" = "no"; then echo "*** $be backend requires sys/scanio.h - $DISABLE_MSG" backend_supported="no" fi ;; qcam) if ( test "${ac_cv_func_ioperm}" = "no" || test "${sane_cv_have_sys_io_h_with_inb_outb}" = "no" )\ && test "${ac_cv_func__portaccess}" = "no"; then echo "*** $be backend requires (ioperm, inb and outb) or portaccess functions - $DISABLE_MSG" backend_supported="no" fi ;; v4l) if test "${have_linux_ioctl_defines}" != "yes" \ || test "${have_libv4l1}" != "yes"; then echo "*** $be backend requires v4l libraries - $DISABLE_MSG" backend_supported="no" fi ;; net) if test "${ac_cv_header_sys_socket_h}" = "no"; then echo "*** $be backend requires sys/socket.h - $DISABLE_MSG" backend_supported="no" fi ;; mustek_usb2|kvs40xx) if test "${have_pthread}" != "yes"; then echo "*** $be backend requires pthread library - $DISABLE_MSG" backend_supported="no" fi ;; esac if test "${backend_supported}" = "no"; then if test "${user_selected_backends}" = "yes"; then exit 1 fi else FILTERED_BACKENDS="${FILTERED_BACKENDS} $be" fi done ]) # # Generate prototypes for functions not available on the system AC_DEFUN([SANE_PROTOTYPES], [ AH_BOTTOM([ #if defined(__MINGW32__) #define _BSDTYPES_DEFINED #endif #ifndef HAVE_U_CHAR #define u_char unsigned char #endif #ifndef HAVE_U_SHORT #define u_short unsigned short #endif #ifndef HAVE_U_INT #define u_int unsigned int #endif #ifndef HAVE_U_LONG #define u_long unsigned long #endif /* Prototype for getenv */ #ifndef HAVE_GETENV #define getenv sanei_getenv char * getenv(const char *name); #endif /* Prototype for inet_ntop */ #ifndef HAVE_INET_NTOP #define inet_ntop sanei_inet_ntop #include const char * inet_ntop (int af, const void *src, char *dst, size_t cnt); #endif /* Prototype for inet_pton */ #ifndef HAVE_INET_PTON #define inet_pton sanei_inet_pton int inet_pton (int af, const char *src, void *dst); #endif /* Prototype for isfdtype */ #ifndef HAVE_ISFDTYPE #define isfdtype sanei_isfdtype int isfdtype(int fd, int fdtype); #endif /* Prototype for sigprocmask */ #ifndef HAVE_SIGPROCMASK #define sigprocmask sanei_sigprocmask int sigprocmask (int how, int *new, int *old); #endif /* Prototype for snprintf */ #ifndef HAVE_SNPRINTF #define snprintf sanei_snprintf #include int snprintf (char *str,size_t count,const char *fmt,...); #endif /* Prototype for strcasestr */ #ifndef HAVE_STRCASESTR #define strcasestr sanei_strcasestr char * strcasestr (const char *phaystack, const char *pneedle); #endif /* Prototype for strdup */ #ifndef HAVE_STRDUP #define strdup sanei_strdup char *strdup (const char * s); #endif /* Prototype for strndup */ #ifndef HAVE_STRNDUP #define strndup sanei_strndup #include char *strndup(const char * s, size_t n); #endif /* Prototype for strsep */ #ifndef HAVE_STRSEP #define strsep sanei_strsep char *strsep(char **stringp, const char *delim); #endif /* Prototype for usleep */ #ifndef HAVE_USLEEP #define usleep sanei_usleep unsigned int usleep (unsigned int useconds); #endif /* Prototype for vsyslog */ #ifndef HAVE_VSYSLOG #include void vsyslog(int priority, const char *format, va_list args); #endif ]) ]) m4_include([m4/libtool.m4]) m4_include([m4/byteorder.m4]) m4_include([m4/stdint.m4]) sane-backends-1.0.27/backend/0000775000175000017500000000000013110600532012660 500000000000000sane-backends-1.0.27/backend/gt68xx_mid.h0000664000175000017500000001221012112021330014740 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GT68XX_MID_H #define GT68XX_MID_H /** @file * @brief Image data unpacking. */ #include "gt68xx_low.h" #include "../include/sane/sane.h" typedef struct GT68xx_Delay_Buffer GT68xx_Delay_Buffer; typedef struct GT68xx_Line_Reader GT68xx_Line_Reader; struct GT68xx_Delay_Buffer { SANE_Int line_count; SANE_Int read_index; SANE_Int write_index; unsigned int **lines; SANE_Byte *mem_block; }; /** * Object for reading image data line by line, with line distance correction. * * This object handles reading the image data from the scanner line by line and * converting it to internal format. Internally each image sample is * represented as unsigned int value, scaled to 16-bit range * (0-65535). For color images the data for each primary color is stored as * separate lines. */ struct GT68xx_Line_Reader { GT68xx_Device *dev; /**< Low-level interface object */ GT68xx_Scan_Parameters params; /**< Scan parameters */ #if 0 /** Number of bytes in the returned scanlines */ SANE_Int bytes_per_line; /** Number of bytes per pixel in the returned scanlines */ SANE_Int bytes_per_pixel; #endif /** Number of pixels in the returned scanlines */ SANE_Int pixels_per_line; SANE_Byte *pixel_buffer; GT68xx_Delay_Buffer r_delay; GT68xx_Delay_Buffer g_delay; GT68xx_Delay_Buffer b_delay; SANE_Bool delays_initialized; SANE_Status (*read) (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return); }; /** * Create a new GT68xx_Line_Reader object. * * @param dev The low-level scanner interface object. * @param params Scan parameters prepared by gt68xx_device_setup_scan(). * @param final_scan SANE_TRUE for the final scan, SANE_FALSE for * calibration scans. * @param reader_return Location for the returned object. * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_NO_MEM - cannot allocate memory for object or buffers * - other error values - failure of some internal functions */ static SANE_Status gt68xx_line_reader_new (GT68xx_Device * dev, GT68xx_Scan_Parameters * params, SANE_Bool final_scan, GT68xx_Line_Reader ** reader_return); /** * Destroy the GT68xx_Line_Reader object. * * @param reader The GT68xx_Line_Reader object to destroy. */ static SANE_Status gt68xx_line_reader_free (GT68xx_Line_Reader * reader); /** * Read a scanline from the GT68xx_Line_Reader object. * * @param reader The GT68xx_Line_Reader object. * @param buffer_pointers_return Array of pointers to image lines (1 or 3 * elements) * * This function reads a full scanline from the device, unpacks it to internal * buffers and returns pointer to these buffers in @a * buffer_pointers_return[i]. For monochrome scan, only @a * buffer_pointers_return[0] is filled; for color scan, elements 0, 1, 2 are * filled with pointers to red, green, and blue data. The returned pointers * are valid until the next call to gt68xx_line_reader_read(), or until @a * reader is destroyed. * * @return * - SANE_STATUS_GOOD - read completed successfully * - other error value - an error occured */ static SANE_Status gt68xx_line_reader_read (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return); #endif /* not GT68XX_MID_H */ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/kodakaio.conf.in0000664000175000017500000000504712775277260015674 00000000000000### kodakaio.conf ### ### here are some examples for how to configure the kodakaio backend ### Timeout settings: SNMP autodetection, Scan data read requests and other ### read requests. All values are given in milliseconds, ### i.e. 1000 is 1 second. # snmp-timeout controls auto-detection timeout in ms (1500=1.5s). snmp-timeout 2000 # scan-data-timeout controls the timeout for scan data # (scans may take several seconds to initialize, so we need to wait longer) scan-data-timeout 10000 # request-timeout controls all other data requests request-timeout 5000 ### Network: Format is "net IP_ADDRESS [USB_ID]" or "net autodiscovery" ### if USB_ID is left out, SNMP is used to detect the device type ### Currently autodiscovery seems to not work ### So always use "net IP_ADDRESS [USB_ID]" as shown below ### You can find the printer's IP address on its control panel ### There is a list of USB_IDs at the end of this file net autodiscovery ### The following is a kodak HERO 9.1 with explicit IP-Address #net 10.0.0.5 0x4067 # kodak ESP5250 is usb 0x040a 0x4041 #net 192.168.1.2 0x4041 # kodak HERO 9.1 is usb 0x040a 0x4067 #net 192.168.1.17 0x4067 ### USB: format is "usb" for automatic (libusb) discovery, based on USB IDs, ### or "usb to force the use of a particular ### device (the backend has some additional checks and will not use ### non-kodak devices, though) usb ### For libusb support for unknown scanners use the following command ### usb ### e.g.: # kodak ESP5250 is usb 0x040a 0x4041 #usb 0x040a 0x4041 # kodak HERO 9.1 is usb 0x040a 0x4067 #usb 0x040a 0x4067 ### List of USB device IDs # 0x4059, /* kodak ESP 2150 */ # 0x4066, /* kodak ESP 2170 */ # 0x4043, /* kodak ESP 3200 */ # 0x4031, /* kodak ESP 3300 */ # 0x4053, /* kodak ESP 4100 */ # 0x4028, /* kodak ESP 5000 */ # 0x4025, /* kodak ESP 5100 */ # 0x4041, /* kodak ESP 5200 */ # 0x4026, /* kodak ESP 5300 */ # 0x4027, /* kodak ESP 5500 */ # 0x4054, /* kodak ESP 6100 */ # 0x4056, /* kodak ESP 7200 */ # 0x4065, /* kodak ESP 9200 */ # 0x4032, /* kodak ESP 5 */ # 0x403E, /* kodak ESP 7 */ # 0x403F, /* kodak ESP 9 */ # 0x4057, /* kodak ESP C110 */ # 0x4058, /* kodak ESP C115 */ # 0x405D, /* kodak ESP C310 */ # 0x405E, /* kodak ESP C315 */ # 0x4060, /* ADVENT WiFi AIO AW10 */ # 0x406D, /* kodak Hero 3.1 */ # 0x4064, /* kodak Hero 5.1 */ # 0x4062, /* kodak Office Hero 6.1 */ # 0x4063, /* kodak Hero 7.1 */ # 0x4067, /* kodak Hero 9.1 */ sane-backends-1.0.27/backend/plustek-pp_sysdep.h0000664000175000017500000002661012775277260016501 00000000000000/* @file plustek-pp_sysdep.h * @brief a trial to centralize changes between the different * kernel-versions some stuff is maybe not relevant, but anyway... * * Copyright (C) 2000-2013 Gerhard Jaeger * * History: * 0.30 - initial version * 0.38 - added this header * 0.39 - added kernel 2.4 stuff * 0.40 - added slab.h/malloc.h stuff for kernel >= 2.4.17 * 0.41 - no changes * 0.42 - added _GET_TIME * - added LINUX_26 for new kernel * - added _MINOR * 0.43 - added class functions * 0.44 - added support for kernel >= 2.6.35 and 3.x * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef _SYSDEP_H_ #define _SYSDEP_H_ #ifndef LINUX_VERSION_CODE # include #endif #ifndef VERSION_CODE # define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) ) #endif /* only allow > 2.0.x */ #if LINUX_VERSION_CODE < VERSION_CODE(2,0,0) # error "This kernel is too old: not supported by this file" #endif #if LINUX_VERSION_CODE < VERSION_CODE(2,1,0) # define LINUX_20 #elif LINUX_VERSION_CODE < VERSION_CODE(2,4,0) # define LINUX_21 #elif LINUX_VERSION_CODE < VERSION_CODE(2,6,0) # define LINUX_24 #else # define LINUX_24 # define LINUX_26 # include # if LINUX_VERSION_CODE > VERSION_CODE(2,6,35) # define NOLOCK_IOCTL # define IOCTL unlocked_ioctl # else # define IOCTL ioctl # endif # if LINUX_VERSION_CODE > VERSION_CODE(3,0,0) # include # endif #endif #include /* used later in this header */ /* Modularization issues */ #if LINUX_VERSION_CODE < VERSION_CODE(2,1,18) # define __USE_OLD_SYMTAB__ # define EXPORT_NO_SYMBOLS register_symtab(NULL); # define REGISTER_SYMTAB(tab) register_symtab(tab) #else # define REGISTER_SYMTAB(tab) /* nothing */ #endif #ifdef __USE_OLD_SYMTAB__ # define __MODULE_STRING(s) /* nothing */ # define MODULE_PARM(v,t) /* nothing */ # define MODULE_PARM_DESC(v,t) /* nothing */ # define MODULE_AUTHOR(n) /* nothing */ # define MODULE_DESCRIPTION(d) /* nothing */ # define MODULE_SUPPORTED_DEVICE(n) /* nothing */ #endif #if LINUX_VERSION_CODE < VERSION_CODE(2,1,31) # define CLOSETYPE void # define CLOSERETURN(arg) #else # define CLOSETYPE int # define CLOSERETURN(arg) return arg #endif /* * "select" changed in 2.1.23. The implementation is twin, but this * header is new */ #if LINUX_VERSION_CODE > VERSION_CODE(2,1,22) # include #else # define __USE_OLD_SELECT__ #endif /* Other change in the fops are solved using pseudo-types */ #if defined(LINUX_21) || defined(LINUX_24) || defined(LINUX_26) # define lseek_t long long # define lseek_off_t long long #else # define lseek_t int # define lseek_off_t off_t #endif /* changed the prototype of read/write */ #if defined(LINUX_21) || defined (LINUX_24) || defined(LINUX_26) || defined(__alpha__) # define count_t unsigned long # define read_write_t long #else # define count_t int # define read_write_t int #endif #if LINUX_VERSION_CODE < VERSION_CODE(2,1,31) # define release_t void # define release_return(x) return #else # define release_t int # define release_return(x) return (x) #endif /* * access to user space: use the 2.1 functions, * and implement them as macros for 2.0 */ #ifdef LINUX_20 # include # define access_ok(t,a,sz) (verify_area((t),(a),(sz)) ? 0 : 1) # define verify_area_20 verify_area # define copy_to_user(t,f,n) (memcpy_tofs(t,f,n), 0) # define __copy_to_user(t,f,n) copy_to_user((t),(f),(n)) # define copy_to_user_ret(t,f,n,r) copy_to_user((t),(f),(n)) # define copy_from_user(t,f,n) (memcpy_fromfs((t),(f),(n)), 0) # define __copy_from_user(t,f,n) copy_from_user((t),(f),(n)) # define copy_from_user_ret(t,f,n,r) copy_from_user((t),(f),(n)) # define PUT_USER(val,add) (put_user((val),(add)), 0) # define __PUT_USER(val,add) PUT_USER((val),(add)) # define PUT_USER_RET(val,add,ret) PUT_USER((val),(add)) # define GET_USER(dest,add) ((dest)=get_user((add)), 0) # define __GET_USER(dest,add) GET_USER((dest),(add)) # define GET_USER_RET(dest,add,ret) GET_USER((dest),(add)) #else # include # include # define verify_area_20(t,a,sz) (0) /* == success */ # define PUT_USER put_user # define __PUT_USER __put_user # define PUT_USER_RET put_user_ret # define GET_USER get_user # define __GET_USER __get_user # define GET_USER_RET get_user_ret /* starting with 2.4.0-test8, they removed the put_user_ret and get_user_ret * macros, so we recode'em */ #if defined(LINUX_24) || defined(LINUX_26) #ifndef put_user_ret # define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; }) #endif #ifndef get_user_ret # define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; }) #endif #endif #endif /* ioremap */ #ifdef LINUX_20 # define ioremap vremap # define iounmap vfree #endif /* The use_count of exec_domain and binfmt changed in 2.1.23 */ #ifdef LINUX_20 # define INCRCOUNT(p) ((p)->module ? __MOD_INC_USE_COUNT((p)->module) : 0) # define CURRCOUNT(p) ((p)->module && (p)->module->usecount) # define DECRCOUNT(p) ((p)->module ? __MOD_DEC_USE_COUNT((p)->module) : 0) #else # define INCRCOUNT(p) ((p)->use_count++) # define CURRCOUNT(p) ((p)->use_count) # define DECRCOUNT(p) ((p)->use_count--) #endif /* register_dynamic no more existent -- just have 0 as inum */ #if LINUX_VERSION_CODE >= VERSION_CODE(2,1,29) # define proc_register_dynamic proc_register #endif #if LINUX_VERSION_CODE < VERSION_CODE(2,1,37) # define test_and_set_bit(nr,addr) test_bit((nr),(addr)) # define test_and_clear_bit(nr,addr) clear_bit((nr),(addr)) # define test_and_change_bit(nr,addr) change_bit((nr),(addr)) #endif /* 2.1.30 removed these functions. Let's define them, just in case */ #if LINUX_VERSION_CODE > VERSION_CODE(2,1,29) # define queue_task_irq queue_task # define queue_task_irq_off queue_task #endif /* 2.1.10 and 2.1.43 introduced new functions. They are worth using */ #if LINUX_VERSION_CODE < VERSION_CODE(2,1,10) # include # ifdef __LITTLE_ENDIAN # define cpu_to_le16(x) (x) # define cpu_to_le32(x) (x) # define cpu_to_be16(x) htons((x)) # define cpu_to_be32(x) htonl((x)) # else # define cpu_to_be16(x) (x) # define cpu_to_be32(x) (x) extern inline __u16 cpu_to_le16(__u16 x) { return (x<<8) | (x>>8);} extern inline __u32 cpu_to_le32(__u32 x) { return((x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | (x<<24));} # endif # define le16_to_cpu(x) cpu_to_le16(x) # define le32_to_cpu(x) cpu_to_le32(x) # define be16_to_cpu(x) cpu_to_be16(x) # define be32_to_cpu(x) cpu_to_be32(x) #endif #if LINUX_VERSION_CODE < VERSION_CODE(2,1,43) # define cpu_to_le16p(addr) (cpu_to_le16(*(addr))) # define cpu_to_le32p(addr) (cpu_to_le32(*(addr))) # define cpu_to_be16p(addr) (cpu_to_be16(*(addr))) # define cpu_to_be32p(addr) (cpu_to_be32(*(addr))) extern inline void cpu_to_le16s(__u16 *a) {*a = cpu_to_le16(*a);} extern inline void cpu_to_le32s(__u16 *a) {*a = cpu_to_le32(*a);} extern inline void cpu_to_be16s(__u16 *a) {*a = cpu_to_be16(*a);} extern inline void cpu_to_be32s(__u16 *a) {*a = cpu_to_be32(*a);} # define le16_to_cpup(x) cpu_to_le16p(x) # define le32_to_cpup(x) cpu_to_le32p(x) # define be16_to_cpup(x) cpu_to_be16p(x) # define be32_to_cpup(x) cpu_to_be32p(x) # define le16_to_cpus(x) cpu_to_le16s(x) # define le32_to_cpus(x) cpu_to_le32s(x) # define be16_to_cpus(x) cpu_to_be16s(x) # define be32_to_cpus(x) cpu_to_be32s(x) #endif #if LINUX_VERSION_CODE < VERSION_CODE(2,1,15) # define __USE_OLD_REBUILD_HEADER__ #endif #if LINUX_VERSION_CODE < VERSION_CODE(2,1,30) # define in_interrupt() (intr_count!=0) #endif /* * from 2.4.17 on, they decided to use slab.h instead of malloc.h... so what... * somewhere from 2.4.18-pre9 they skipped get_fast_time... */ #if LINUX_VERSION_CODE < VERSION_CODE(2,4,17) # include "linux/malloc.h" # define _GET_TIME get_fast_time #else # include "linux/slab.h" # define _GET_TIME do_gettimeofday #endif #ifdef LINUX_26 # define _MINOR(p) iminor(p) #else # define _MINOR(p) minor(p->i_rdev) #endif /* Basic class macros */ #ifdef LINUX_26 #if LINUX_VERSION_CODE >= VERSION_CODE(2,6,15) typedef struct class class_t; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) #define CLASS_DEV_CREATE(class, devt, device, name) \ device_create(class, device, devt, NULL, "%s", name) #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #define CLASS_DEV_CREATE(class, devt, device, name) \ device_create(class, device, devt, name) #else #define CLASS_DEV_CREATE(class, devt, device, name) \ class_device_create(class, NULL, devt, device, name) #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #define CLASS_DEV_DESTROY device_destroy #else #define CLASS_DEV_DESTROY class_device_destroy #endif #else /* LINUX 2.6.0 - 2.6.14 */ #if LINUX_VERSION_CODE >= VERSION_CODE(2,6,13) /* LINUX 2.6.13 - 2.6.14 */ typedef struct class class_t; #define CLASS_DEVICE_CREATE class_device_create #define CLASS_DEV_DESTROY(class, devt) class_device_destroy(class, devt) #else /* LINUX 2.6.0 - 2.6.12, class_simple */ typedef struct class_simple class_t; #define CLASS_DEVICE_CREATE class_simple_device_add #define CLASS_DEV_DESTROY(class, devt) class_simple_device_remove(class, devt) #define class_create class_simple_create #define class_destroy class_simple_destroy #define class_device_destroy(a, b) class_simple_device_remove(b) #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) */ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */ #endif #endif /* _SYSDEP_H_ */ /* END PLUSTEK-PP_SYSDEP.H ..................................................*/ sane-backends-1.0.27/backend/epsonds-usb.c0000664000175000017500000000175312775312261015233 00000000000000/* * epsonds-usb.c - Epson ESC/I-2 driver, USB device list. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #include "epsonds-usb.h" SANE_Word epsonds_usb_product_ids[] = { 0x0145, /* DS-5500, DS-6500, DS-7500 */ 0x0146, /* DS-50000, DS-60000, DS-70000 */ 0x014c, /* DS-510 */ 0x014d, /* DS-560 */ 0x0150, /* DS-40 */ 0x0152, /* DS-760, DS-860 */ 0x0154, /* DS-520 */ 0x08bc, /* PX-M7050 Series, WF-8510/8590 Series */ 0x08cc, /* PX-M7050FX Series, WF-R8590 Series */ 0 /* last entry - this is used for devices that are specified in the config file as "usb " */ }; int epsonds_get_number_of_ids(void) { return sizeof (epsonds_usb_product_ids) / sizeof (SANE_Word); } sane-backends-1.0.27/backend/rts8891_devices.c0000664000175000017500000002565712775277260015657 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007-2012 stef.dev@free.fr This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* here we have the various device settings... */ static Rts8891_Model hp4400c_model = { "HP4400c", /* Name */ "Hewlett-Packard", /* Device vendor string */ "4400c", /* Device model name */ "flatbed scanner", /* Device type */ {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 0}, /* possible y-resolutions */ 1200, /* max physical x dpi */ 600, /* max physical y dpi */ 150, /* min physical y dpi */ SANE_FIX (8.3), /* Start of scan area in mm (x) */ SANE_FIX (3.0), /* Start of scan area in mm (y) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (298.1), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ 24, 12, 0, /* R, G, and B CCD Line-distance correction in lines at max motor resolution */ /* default sensor */ SENSOR_TYPE_4400, /* default gamma table */ {0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x52, 0x53, 0x55, 0x57, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x62, 0x63, 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb1, 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb8, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xce, 0xce, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9, 0xda, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6, 0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea, 0xeb, 0xeb, 0xec, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xff}, /* number of buttons */ 5, /* button names */ { "copy", "mail", "image-copy", "scan", "power"}, /* button titles */ { "copy", "mail", "image copy", "scan", "power"}, /* flags */ RTS8891_FLAG_EMULATED_GRAY_MODE }; static Rts8891_Model hp4470c_model = { "HP4470c", /* Name */ "Hewlett-Packard", /* Device vendor string */ "4470c", /* Device model name */ "flatbed scanner", /* Device type */ {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 0}, /* possible y-resolutions */ 1200, /* max physical x dpi */ 600, /* max physical y dpi */ 150, /* min physical y dpi */ SANE_FIX (8.3), /* Start of scan area in mm (x) */ SANE_FIX (3.0), /* Start of scan area in mm (y) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (298.1), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ 24, 12, 0, /* R, G, and B CCD Line-distance correction in lines at max motor resolution */ /* default sensor */ SENSOR_TYPE_XPA, /* default gamma table */ {0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x52, 0x53, 0x55, 0x57, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x62, 0x63, 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb1, 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb8, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xce, 0xce, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9, 0xda, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6, 0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea, 0xeb, 0xeb, 0xec, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xff}, /* number of buttons */ 11, /* button names */ {"plus", "minus", "copy", "mail", "image-copy", "www", "scan", "power", "cancel", "options", "toggle-mode"}, /* button titles */ {"plus", "minus", "copy", "mail", "image copy", "www", "scan", "power", "cancel", "options", "toggle color/gray mode"}, /* flags */ RTS8891_FLAG_EMULATED_GRAY_MODE }; static Rts8891_Model astra4400_model = { "Astra 4400", /* Name */ "UMAX", /* Device vendor string */ "Astra 4400", /* Device model name */ "flatbed scanner", /* Device type */ {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 0}, /* possible y-resolutions */ 1200, /* max physical x dpi */ 600, /* max physical y dpi */ 150, /* min physical y dpi */ SANE_FIX (8.3), /* Start of scan area in mm (x) */ SANE_FIX (3.0), /* Start of scan area in mm (y) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (298.1), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ 24, 12, 0, /* R, G, and B CCD Line-distance correction in lines at max motor resolution */ /* default sensor */ SENSOR_TYPE_XPA, /* default gamma table */ {0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x50, 0x52, 0x53, 0x55, 0x57, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x62, 0x63, 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b, 0x6c, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb1, 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb8, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xce, 0xce, 0xcf, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8, 0xd9, 0xd9, 0xda, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, 0xe0, 0xe1, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6, 0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea, 0xeb, 0xeb, 0xec, 0xec, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xff}, /* number of buttons */ 11, /* button names */ {"plus", "minus", "copy", "mail", "image-copy", "www", "scan", "power", "cancel", "options", "toggle-mode"}, /* button titles */ {"plus", "minus", "copy", "mail", "image copy", "www", "scan", "power", "cancel", "options", "toggle color/gray mode"}, /* flags */ RTS8891_FLAG_EMULATED_GRAY_MODE }; /* full list of supported devices: vendor, product, description structure */ static Rts8891_USB_Device_Entry rts8891_usb_device_list[] = { {0x03f0, 0x0705, &hp4400c_model}, {0x03f0, 0x0805, &hp4470c_model}, {0x1606, 0x0070, &astra4400_model}, {0, 0, NULL} }; sane-backends-1.0.27/backend/sharp.h0000664000175000017500000002754512112021330014075 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998, 1999 Kazuya Fukuda, Abel Deuring This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef sharp_h #define sharp_h 1 #include /* default values for configurable options. Though these options are only meaningful if USE_FORK is defined, they are DEFAULT_BUFFERS: number of buffers allocated as shared memory for the data transfer from reader_process to read_data. The minimum value is 2 DEFAULT_BUFSIZE: default size of one buffer. Must be greater than zero. DEFAULT_QUEUED_READS: number of read requests queued by sanei_scsi_req_enter. Since queued read requests are currently only supported for Linux and DomainOS, this value should automatically be set dependent on the target OS... For Linux, 2 is the optimum; for DomainOS, I don't have any recommendation; other OS should use the value zero. The value for DEFAULT_BUFSIZE is probably too Linux-oriented... */ #define DEFAULT_BUFFERS 12 #define DEFAULT_BUFSIZE 128 * 1024 #define DEFAULT_QUEUED_READS 2 typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_HALFTONE, OPT_PAPER, OPT_SCANSOURCE, OPT_GAMMA, #ifdef USE_CUSTOM_GAMMA OPT_CUSTOM_GAMMA, #endif OPT_SPEED, OPT_RESOLUTION_GROUP, #ifdef USE_RESOLUTION_LIST OPT_RESOLUTION_LIST, #endif OPT_X_RESOLUTION, #ifdef USE_SEPARATE_Y_RESOLUTION OPT_Y_RESOLUTION, #endif OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_EDGE_EMPHASIS, OPT_THRESHOLD, #ifdef USE_COLOR_THRESHOLD OPT_THRESHOLD_R, OPT_THRESHOLD_G, OPT_THRESHOLD_B, #endif OPT_LIGHTCOLOR, OPT_PREVIEW, #ifdef USE_CUSTOM_GAMMA OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, #endif /* must come last: */ NUM_OPTIONS } SHARP_Option; #ifdef USE_FORK /* status defines for a buffer: buffer not used / read request queued / buffer contains data */ #define SHM_EMPTY 0 #define SHM_BUSY 1 #define SHM_FULL 2 typedef struct SHARP_shmem_ctl { int shm_status; /* can be SHM_EMPTY, SHM_BUSY, SHM_FULL */ size_t used; /* number of bytes successfully read from scanner */ size_t nreq; /* number of bytes requested from scanner */ size_t start; /* index of the begin of used area of the buffer */ void *qid; SANE_Byte *buffer; } SHARP_shmem_ctl; typedef struct SHARP_rdr_ctl { int cancel; /* 1 = flag for the reader process to cancel */ int running; /* 1 indicates that the reader process is alive */ SANE_Status status; /* return status of the reader process */ SHARP_shmem_ctl *buf_ctl; } SHARP_rdr_ctl; #endif /* USE_FORK */ typedef enum { /* JX250, JX330, JX350, JX610 are used as array indices, so the corresponding numbers should start at 0 */ unknown = -1, JX250, JX320, JX330, JX350, JX610 } SHARP_Model; typedef struct SHARP_Info { SANE_Range xres_range; SANE_Range yres_range; SANE_Range tl_x_ranges[3]; /* normal / FSU / ADF */ SANE_Range br_x_ranges[3]; /* normal / FSU / ADF */ SANE_Range tl_y_ranges[3]; /* normal / FSU / ADF */ SANE_Range br_y_ranges[3]; /* normal / FSU / ADF */ SANE_Range threshold_range; SANE_Int xres_default; SANE_Int yres_default; SANE_Int x_default; SANE_Int y_default; SANE_Int bmu; SANE_Int mud; SANE_Int adf_fsu_installed; SANE_String_Const scansources[5]; size_t buffers; size_t bufsize; int wanted_bufsize; size_t queued_reads; int complain_on_errors; /* default scan mode: -1 -> "automatic": Use the ADF, if installed, else use the FSU, if installed. or: SCAN_ADF, SCAN_FSU, SCAN_SIMPLE */ int default_scan_mode; } SHARP_Info; #define COMPLAIN_ON_FSU_ERROR 2 #define COMPLAIN_ON_ADF_ERROR 1 typedef struct SHARP_Sense_Data { SHARP_Model model; /* flag, if conditions like "paper jam" or "cover open" are considered as an error. Should be 0 for attach, else a frontend might refuse to start, if the scanner returns these errors. */ int complain_on_errors; /* Linux returns only 16 bytes of sense data... */ u_char sb[16]; } SHARP_Sense_Data; typedef struct SHARP_Device { struct SHARP_Device *next; SANE_Device sane; SHARP_Info info; /* xxx now part of sense data SHARP_Model model; */ SHARP_Sense_Data sensedat; } SHARP_Device; typedef struct SHARP_New_Device { struct SHARP_Device *dev; struct SHARP_New_Device *next; } SHARP_New_Device; typedef struct SHARP_Scanner { struct SHARP_Scanner *next; int fd; SHARP_Device *dev; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; int get_params_called; SANE_Byte *buffer; /* for color data re-ordering, required for JX 250 */ SANE_Int buf_used; SANE_Int buf_pos; SANE_Int modes; SANE_Int xres; SANE_Int yres; SANE_Int ulx; SANE_Int uly; SANE_Int width; SANE_Int length; SANE_Int threshold; SANE_Int image_composition; SANE_Int bpp; SANE_Int halftone; SANE_Bool reverse; SANE_Bool speed; SANE_Int gamma; SANE_Int edge; SANE_Int lightcolor; SANE_Int adf_fsu_mode; /* mode selected by user */ SANE_Int adf_scan; /* flag, if the actual scan is an ADF scan */ size_t bytes_to_read; size_t max_lines_to_read; size_t unscanned_lines; SANE_Bool scanning; SANE_Bool busy; SANE_Bool cancel; #ifdef USE_CUSTOM_GAMMA SANE_Int gamma_table[4][256]; #endif #ifdef USE_FORK pid_t reader_pid; SHARP_rdr_ctl *rdr_ctl; int shmid; size_t read_buff; /* index of the buffer actually used by read_data */ #endif /* USE_FORK */ } SHARP_Scanner; typedef struct SHARP_Send { SANE_Int dtc; SANE_Int dtq; SANE_Int length; SANE_Byte *data; } SHARP_Send; typedef struct WPDH { u_char wpdh[6]; u_char wdl[2]; } WPDH; typedef struct WDB { SANE_Byte wid; SANE_Byte autobit; SANE_Byte x_res[2]; SANE_Byte y_res[2]; SANE_Byte x_ul[4]; SANE_Byte y_ul[4]; SANE_Byte width[4]; SANE_Byte length[4]; SANE_Byte brightness; SANE_Byte threshold; SANE_Byte null_1; SANE_Byte image_composition; SANE_Byte bpp; SANE_Byte ht_pattern[2]; SANE_Byte rif_padding; SANE_Byte null_2[4]; SANE_Byte null_3[6]; SANE_Byte eletu; SANE_Byte zooming_x[2]; SANE_Byte zooming_y[2]; SANE_Byte lightness_r[2]; SANE_Byte lightness_g[2]; SANE_Byte lightness_b[2]; SANE_Byte lightness_bw[2]; } WDB; /* "extension" of the window descriptor block for the JX 330 */ typedef struct WDBX330 { SANE_Byte moire_reduction[2]; } WDBX330; /* "extension" of the window descriptor block for the JX 250 */ typedef struct XWDBX250 { SANE_Byte threshold_red; SANE_Byte threshold_green; SANE_Byte threshold_blue; SANE_Byte draft; SANE_Byte scanning_time[4]; SANE_Byte fixed_gamma; SANE_Byte x_axis_res_qualifier[2]; SANE_Byte y_axis_res_qualifier[2]; } WDBX250; typedef struct window_param { WPDH wpdh; WDB wdb; WDBX330 wdbx330; WDBX250 wdbx250; } window_param; typedef struct mode_sense_param { SANE_Byte mode_data_length; SANE_Byte mode_param_header2; SANE_Byte mode_param_header3; SANE_Byte mode_desciptor_length; SANE_Byte resereved[5]; SANE_Byte blocklength[3]; SANE_Byte page_code; SANE_Byte page_length; /* 6 */ SANE_Byte bmu; SANE_Byte res2; SANE_Byte mud[2]; SANE_Byte res3; SANE_Byte res4; } mode_sense_param; typedef struct mode_sense_subdevice { /* This definition reflects the JX250. The JX330 would need a slightly different definition, but the bytes used right now (for ADF and FSU) are identical. */ SANE_Byte mode_data_length; SANE_Byte mode_param_header2; SANE_Byte mode_param_header3; SANE_Byte mode_desciptor_length; SANE_Byte res1[5]; SANE_Byte blocklength[3]; SANE_Byte page_code; SANE_Byte page_length; /* 0x1a */ SANE_Byte a_mode_type; SANE_Byte f_mode_type; SANE_Byte res2; SANE_Byte max_x[4]; SANE_Byte max_y[4]; SANE_Byte res3[2]; SANE_Byte x_basic_resolution[2]; SANE_Byte y_basic_resolution[2]; SANE_Byte x_max_resolution[2]; SANE_Byte y_max_resolution[2]; SANE_Byte x_min_resolution[2]; SANE_Byte y_min_resolution[2]; SANE_Byte res4; } mode_sense_subdevice; typedef struct mode_select_param { SANE_Byte mode_param_header1; SANE_Byte mode_param_header2; SANE_Byte mode_param_header3; SANE_Byte mode_param_header4; SANE_Byte page_code; SANE_Byte page_length; /* 6 */ SANE_Byte res1; SANE_Byte res2; SANE_Byte mud[2]; SANE_Byte res3; SANE_Byte res4; } mode_select_param; typedef struct mode_select_subdevice { SANE_Byte mode_param_header1; SANE_Byte mode_param_header2; SANE_Byte mode_param_header3; SANE_Byte mode_param_header4; SANE_Byte page_code; SANE_Byte page_length; /* 0x1A */ SANE_Byte a_mode; SANE_Byte f_mode; SANE_Byte res[24]; } mode_select_subdevice; /* SCSI commands */ #define TEST_UNIT_READY 0x00 #define REQUEST_SENSE 0x03 #define INQUIRY 0x12 #define MODE_SELECT6 0x15 #define RESERVE_UNIT 0x16 #define RELEASE_UNIT 0x17 #define MODE_SENSE6 0x1a #define SCAN 0x1b #define SEND_DIAGNOSTIC 0x1d #define SET_WINDOW 0x24 #define GET_WINDOW 0x25 #define READ 0x28 #define SEND 0x2a #define OBJECT_POSITION 0x31 #define SENSE_LEN 18 #define INQUIRY_LEN 36 #define MODEPARAM_LEN 12 #define MODE_SUBDEV_LEN 32 #define WINDOW_LEN 76 #endif /* not sharp_h */ sane-backends-1.0.27/backend/dc210.h0000664000175000017500000001640112112021330013556 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. dc210.c 11/11/98 This file (C) 1998 Brian J. Murrell This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for the Kodak DC-210 digital camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! (feedback to: sane-dc210@interlinx.bc.ca This backend is based somewhat on the dc25 backend included in this package by Peter Fales ***************************************************************************/ #include #include #include #include #include #include #ifndef TRUE #define TRUE (1==1) #endif #ifndef FALSE #define FALSE (!TRUE) #endif #ifndef NULL #define NULL 0L #endif typedef struct picture_info { unsigned int low_res; unsigned int size; } PictureInfo; typedef struct DC210_s { int fd; /* file descriptor to talk to it */ char *tty_name; /* the tty port name it's on */ speed_t baud; /* current tty speed */ SANE_Bool scanning; /* currently scanning an image? */ unsigned char model; unsigned char ver_major; unsigned char ver_minor; int pic_taken; int pic_left; struct { unsigned int low_res:1; unsigned int low_batt:1; } flags; PictureInfo *Pictures; /* array of pictures */ unsigned int current_picture_number; /* picture being operated on */ } DC210; typedef struct dc210_info_s { unsigned char model; unsigned char ver_major; unsigned char ver_minor; int pic_taken; int pic_left; struct { unsigned int low_res:1; unsigned int low_batt:1; } flags; } Dc210Info, *Dc210InfoPtr; static int get_info (DC210 *); #define INIT_PCK {0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^^^^^^^ * Baud rate: (see pkt_speed structure) * 0x96 0x00 -> 9600 baud * 0x19 0x20 -> 19200 baud * 0x38 0x40 -> 38400 baud * 0x57 0x60 -> 57600 baud * 0x11 0x52 -> 115200 baud */ #define INFO_PCK {0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define SHOOT_PCK {0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define ERASE_PCK {0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define RES_PCK {0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * Resolution: 0x00 = high, 0x01 = low */ #define THUMBS_PCK {0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * Thumbnail number */ #define PICS_PCK {0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * Picture number */ #define PICS_INFO_PCK {0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * Picture number */ struct pkt_speed { speed_t baud; unsigned char pkt_code[2]; }; #if defined (B57600) && defined (B115200) # define SPEEDS { { B9600, { 0x96, 0x00 } }, \ { B19200, { 0x19, 0x20 } }, \ { B38400, { 0x38, 0x40 } }, \ { B57600, { 0x57, 0x60 } }, \ { B115200, { 0x11, 0x52 } } } #else # define SPEEDS { { B9600, { 0x96, 0x00 } }, \ { B19200, { 0x19, 0x20 } }, \ { B38400, { 0x38, 0x40 } } } #endif #define HIGH_RES 0 #define LOW_RES 1 /* * Image parameters */ #define LOW_CAMERA_HEADER 256 #define HIGH_CAMERA_HEADER 512 #define CAMERA_HEADER(r) ( (r) ? LOW_CAMERA_HEADER : HIGH_CAMERA_HEADER ) #define LOW_WIDTH 256 #define HIGH_WIDTH 512 #define WIDTH(r) ( (r) ? LOW_WIDTH : HIGH_WIDTH ) #define HEIGHT 243 #define LEFT_MARGIN 1 #define LOW_RIGHT_MARGIN 5 #define HIGH_RIGHT_MARGIN 10 #define RIGHT_MARGIN(r) ( (r) ? LOW_RIGHT_MARGIN : HIGH_RIGHT_MARGIN ) #define TOP_MARGIN 1 #define BOTTOM_MARGIN 1 #define BLOCK_SIZE 1024 #define LOW_BLOCKS 61 #define HIGH_BLOCKS 122 #define BLOCKS(r) ( (r) ? LOW_BLOCKS : HIGH_BLOCKS ) #define LOW_IMAGE_SIZE ( LOW_BLOCKS * BLOCK_SIZE ) #define HIGH_IMAGE_SIZE ( HIGH_BLOCKS * BLOCK_SIZE ) #define IMAGE_SIZE(r) ( (r) ? LOW_IMAGE_SIZE : HIGH_IMAGE_SIZE ) #define MAX_IMAGE_SIZE ( HIGH_IMAGE_SIZE ) /* * Comet file */ #define COMET_MAGIC "COMET" #define COMET_HEADER_SIZE 128 #define COMET_EXT "cmt" /* * Pixmap structure */ struct pixmap { int width; int height; int components; unsigned char *planes; }; /* * Rotations */ #define ROT_STRAIGHT 0x00 #define ROT_LEFT 0x01 #define ROT_RIGHT 0x02 #define ROT_HEADDOWN 0x03 #define ROT_MASK 0x03 /* * File formats */ #define SAVE_RAW 0x01 #define SAVE_GREYSCALE 0x02 #define SAVE_24BITS 0x04 #define SAVE_FILES 0x07 #define SAVE_FORMATS 0x38 #define SAVE_ADJASPECT 0x80 /* * External definitions */ extern char *__progname; /* Defined in /usr/lib/crt0.o */ #include FILE *sanei_config_open (const char *filename); static int init_dc210 (DC210 *); static void close_dc210 (int); static int read_data (int fd, unsigned char *buf, int sz); static int end_of_data (int fd); static PictureInfo *get_pictures_info (void); static int get_picture_info (PictureInfo * pic, int p); static SANE_Status snap_pic (int); char *sanei_config_read (char *str, int n, FILE * stream); sane-backends-1.0.27/backend/umax-uc1260.c0000664000175000017500000001050612112021330014630 00000000000000/* ------------------------------------------------------------------------- */ /* umax-uc1260.c: inquiry for UMAX scanner uc1260 (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------- */ #include "umax-scanner.h" /* ------------------------------------------------------------------------- */ static unsigned char UC1260_INQUIRY[] = { #define UC1260_INQUIRY_LEN 0x9d /* 24 F/W support function */ 0x03, /* 25 -27 exposure-times */ 0x00, 0x00, 0x00, /* 28 - 29 reserved */ 0x00, 0x00, /* 2a - 35 exposure times */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 37 reserved */ 0x00, 0x00, /* 38 - 5f scsi reserved */ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, /* 60 -62 scanner capability*/ 0x31, 0x0c, 0x07, /* 63 reserved */ 0x00, /* 64 gamma */ 0xa3, /* 65 reserved */ 0x00, /* 66 GIB */ 0x01, /* 67 reserved */ 0x00, /* 68 GOB */ 0x01, /* 69 - 6a halftone */ 0x0c, 0x2f, /* 6b - 6c reserved */ 0x00, 0x00, /* 6d color sequence */ 0x08, /* 6e - 71 video memory */ 0x00, 0x20, 0x00, 0x00, /* 72 reserved */ 0x00, /* 73 max optical res in 100 dpi */ 0x06, /* 74 max x_res in 100 dpi */ 0x06, /* 75 max y_res in 100 dpi */ 0x0c, /* 76-77 fb max scan width in 0.01 inch */ 0x03, 0x52, /* 78-79 fb max scan length in 0.01 inch */ 0x05, 0x78, /* UTA parameters empirically determined on Peter Missel's unit */ /* 7a-7b uta x original point */ 0x00, 0x77, /* 7c-7d uta y original point */ 0x00, 0x8f, /* 7e-7f uta max scan width in 0.01 inch */ 0x02, 0x63, /* 80-81 uta max scan length in 0.01 inch */ 0x03, 0x61, /* 82-85 reserved */ 00, 00, 00, 00, /* 86-87 dor x original point */ 0x00, 0x00, /* 88-89 dor x original point */ 0x00, 0x00, /* 8a-8b dor max scan width in 0.01 inch */ 0x00, 0x00, /* 8c-8d dor max scan length in 0.01 inch */ 0x00, 0x00, /* 8e reserved */ 0x00, /* 8f last calibration lamp density */ 0x00, /* 90 reserved */ 0x00, /* 91 lamp warmup max time */ 0x00, /* 92-93 window descriptor block length */ 0x00, 0x30, /* 94 optical resolution residue (1dpi) */ 0x00, /* 95 x_resolution residue (1dpi) */ 0x00, /* 96 y_resolution residue (1dpi) */ 0x00, /* 97 analog gamma table */ 0x00, /* 98-99 reserved */ 0x00, 0x00, /* 9a max calibration data lines */ 0x00, /* 9b fb/uta colour-sequnce-mode */ 0x01, /* 9c adf colour-sequnce-mode */ 0x01, /* 9d line-distance of ccd */ 0x08 }; static inquiry_blk inquiry_uc1260 = { "UC1260 ",UC1260_INQUIRY, UC1260_INQUIRY_LEN }; sane-backends-1.0.27/backend/leo.c0000664000175000017500000014252312112021330013524 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002-2003 Frank Zago (sane at zago dot net) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ Across FS-1130 */ /*--------------------------------------------------------------------------*/ #define BUILD 11 /* 2004/06/30 */ #define BACKEND_NAME leo #define LEO_CONFIG_FILE "leo.conf" /*--------------------------------------------------------------------------*/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "leo.h" /*--------------------------------------------------------------------------*/ /* Lists of possible scan modes. */ static SANE_String_Const scan_mode_list[] = { BLACK_WHITE_STR, GRAY_STR, COLOR_STR, NULL }; /*--------------------------------------------------------------------------*/ /* Minimum and maximum width and length supported. */ static SANE_Range x_range = { SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0 }; static SANE_Range y_range = { SANE_FIX (0), SANE_FIX (11.5 * MM_PER_INCH), 0 }; /*--------------------------------------------------------------------------*/ static const SANE_Range gamma_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ static SANE_String_Const halftone_pattern_list[] = { SANE_I18N ("None"), SANE_I18N ("Diamond"), SANE_I18N ("8x8 Coarse Fatting"), SANE_I18N ("8x8 Fine Fatting"), SANE_I18N ("8x8 Bayer"), SANE_I18N ("8x8 Vertical Line"), NULL }; static const halftone_pattern_t *const halftone_pattern_val[] = { NULL, &haltfone_pattern_diamond, &haltfone_pattern_8x8_Coarse_Fatting, &haltfone_pattern_8x8_Fine_Fatting, &haltfone_pattern_8x8_Bayer, &haltfone_pattern_8x8_Vertical_Line }; /*--------------------------------------------------------------------------*/ /* Define the supported scanners and their characteristics. */ static const struct scanners_supported scanners[] = { {6, "ACROSS ", " ", "Across", "FS-1130"}, {6, "LEO ", "LEOScan-S3 ", "Leo", "S3"}, {6, "LEO", "LEOScan-S3", "Leo", "S3"}, {6, "KYE CORP", "ColorPage-CS ", "Genius", "FS1130"} }; /*--------------------------------------------------------------------------*/ /* List of scanner attached. */ static Leo_Scanner *first_dev = NULL; static int num_devices = 0; static const SANE_Device **devlist = NULL; /* Local functions. */ /* Display a buffer in the log. */ static void hexdump (int level, const char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; char asc_buf[17]; char *asc_ptr; DBG (level, "%s\n", comment); ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { DBG (level, "%s %s\n", line, asc_buf); ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; } sprintf (ptr, "%3.3d:", i); ptr += 4; } ptr += sprintf (ptr, " %2.2x", *p); if (*p >= 32 && *p <= 127) { asc_ptr += sprintf (asc_ptr, "%c", *p); } else { asc_ptr += sprintf (asc_ptr, "."); } } *ptr = '\0'; DBG (level, "%s %s\n", line, asc_buf); } /* Returns the length of the longest string, including the terminating * character. */ static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* Lookup a string list from one array and return its index. */ static int get_string_list_index (SANE_String_Const list[], SANE_String_Const name) { int index; index = 0; while (list[index] != NULL) { if (strcmp (list[index], name) == 0) { return (index); } index++; } DBG (DBG_error, "name %s not found in list\n", name); assert (0 == 1); /* bug in backend, core dump */ return (-1); } /* Initialize a scanner entry. Return an allocated scanner with some * preset values. */ static Leo_Scanner * leo_init (void) { Leo_Scanner *dev; DBG (DBG_proc, "leo_init: enter\n"); /* Allocate a new scanner entry. */ dev = malloc (sizeof (Leo_Scanner)); if (dev == NULL) { return NULL; } memset (dev, 0, sizeof (Leo_Scanner)); /* Allocate the buffer used to transfer the SCSI data. */ dev->buffer_size = 64 * 1024; dev->buffer = malloc (dev->buffer_size); if (dev->buffer == NULL) { free (dev); return NULL; } /* Allocate a buffer to store the temporary image. */ dev->image_size = 64 * 1024; /* enough for 1 line at max res */ dev->image = malloc (dev->image_size); if (dev->image == NULL) { free (dev->buffer); free (dev); return NULL; } dev->sfd = -1; DBG (DBG_proc, "leo_init: exit\n"); return (dev); } /* Closes an open scanner. */ static void leo_close (Leo_Scanner * dev) { DBG (DBG_proc, "leo_close: enter\n"); if (dev->sfd != -1) { sanei_scsi_close (dev->sfd); dev->sfd = -1; } DBG (DBG_proc, "leo_close: exit\n"); } /* Frees the memory used by a scanner. */ static void leo_free (Leo_Scanner * dev) { int i; DBG (DBG_proc, "leo_free: enter\n"); if (dev == NULL) return; leo_close (dev); if (dev->devicename) { free (dev->devicename); } if (dev->buffer) { free (dev->buffer); } if (dev->image) { free (dev->image); } for (i = 1; i < OPT_NUM_OPTIONS; i++) { if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) { free (dev->val[i].s); } } free (dev); DBG (DBG_proc, "leo_free: exit\n"); } /* Inquiry a device and returns TRUE if is supported. */ static int leo_identify_scanner (Leo_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; int i; DBG (DBG_proc, "leo_identify_scanner: enter\n"); size = 5; MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "leo_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } size = dev->buffer[4] + 5; /* total length of the inquiry data */ if (size < 36) { DBG (DBG_error, "leo_identify_scanner: not enough data to identify device\n"); return (SANE_FALSE); } MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "leo_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } dev->scsi_type = dev->buffer[0] & 0x1f; memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); dev->scsi_vendor[0x08] = 0; memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); dev->scsi_product[0x10] = 0; memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); dev->scsi_version[0x04] = 0; DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\"\n", dev->scsi_vendor, dev->scsi_product, dev->scsi_version); /* Lookup through the supported scanners table to find if this * backend supports that one. */ for (i = 0; i < NELEMS (scanners); i++) { if (dev->scsi_type == scanners[i].scsi_type && strcmp (dev->scsi_vendor, scanners[i].scsi_vendor) == 0 && strcmp (dev->scsi_product, scanners[i].scsi_product) == 0) { DBG (DBG_error, "leo_identify_scanner: scanner supported\n"); /* Get the full inquiry, since that scanner does not fill the length correctly. */ size = 0x30; MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status != SANE_STATUS_GOOD) { return (SANE_FALSE); } hexdump (DBG_info2, "inquiry", dev->buffer, size); dev->def = &(scanners[i]); dev->res_range.min = 1; dev->res_range.max = B16TOI (&dev->buffer[42]); dev->x_resolution_max = B16TOI (&dev->buffer[40]); dev->y_resolution_max = B16TOI (&dev->buffer[42]); return (SANE_TRUE); } } DBG (DBG_proc, "leo_identify_scanner: exit, device not supported\n"); return (SANE_FALSE); } /* SCSI sense handler. Callback for SANE. */ static SANE_Status leo_sense_handler (int scsi_fd, unsigned char *result, void __sane_unused__ *arg) { int asc, ascq, sensekey; int len; DBG (DBG_proc, "leo_sense_handler (scsi_fd = %d)\n", scsi_fd); sensekey = get_RS_sense_key (result); len = 7 + get_RS_additional_length (result); hexdump (DBG_info2, "sense", result, len); if (get_RS_error_code (result) != 0x70) { DBG (DBG_error, "leo_sense_handler: invalid sense key error code (%d)\n", get_RS_error_code (result)); return SANE_STATUS_IO_ERROR; } if (get_RS_ILI (result) != 0) { DBG (DBG_sense, "leo_sense_handler: short read\n"); } if (len < 14) { DBG (DBG_error, "leo_sense_handler: sense too short, no ASC/ASCQ\n"); return SANE_STATUS_IO_ERROR; } asc = get_RS_ASC (result); ascq = get_RS_ASCQ (result); DBG (DBG_sense, "leo_sense_handler: sense=%d, ASC/ASCQ=%02x%02x\n", sensekey, asc, ascq); switch (sensekey) { case 0x00: /* no sense */ case 0x02: /* not ready */ case 0x03: /* medium error */ case 0x05: case 0x06: break; } DBG (DBG_sense, "leo_sense_handler: unknown error condition. Please report it to the backend maintainer\n"); return SANE_STATUS_IO_ERROR; } /* Set a window. */ static SANE_Status leo_set_window (Leo_Scanner * dev) { size_t size; CDB cdb; unsigned char window[48]; SANE_Status status; DBG (DBG_proc, "leo_set_window: enter\n"); size = sizeof (window); MKSCSI_SET_WINDOW (cdb, size); memset (window, 0, size); /* size of the windows descriptor block */ window[7] = sizeof (window) - 8; window[1] = sizeof (window) - 2; /* X and Y resolution */ Ito16 (dev->x_resolution, &window[10]); Ito16 (dev->y_resolution, &window[12]); /* Upper Left (X,Y) */ Ito32 (dev->x_tl, &window[14]); Ito32 (dev->y_tl, &window[18]); /* Width and length */ Ito32 (dev->width, &window[22]); Ito32 (dev->length, &window[26]); /* Image Composition */ switch (dev->scan_mode) { case LEO_BW: window[33] = 0x00; break; case LEO_HALFTONE: window[33] = 0x01; break; case LEO_GRAYSCALE: window[33] = 0x02; break; case LEO_COLOR: window[33] = 0x05; break; } /* Depth */ window[34] = dev->depth; /* Unknown - invariants */ window[31] = 0x80; window[43] = 0x01; hexdump (DBG_info2, "windows", window, sizeof (window)); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, window, sizeof (window), NULL, NULL); DBG (DBG_proc, "leo_set_window: exit, status=%d\n", status); return status; } /* Read the size of the scan. */ static SANE_Status leo_get_scan_size (Leo_Scanner * dev) { size_t size; CDB cdb; SANE_Status status; DBG (DBG_proc, "leo_get_scan_size: enter\n"); size = 0x10; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (size != 0x10) { DBG (DBG_error, "leo_get_scan_size: GET DATA BUFFER STATUS returned an invalid size (%ld)\n", (long) size); return SANE_STATUS_IO_ERROR; } hexdump (DBG_info2, "leo_get_scan_size return", dev->buffer, size); dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); /* The number of lines if the number of lines left plus the number * of lines already waiting in the buffer. */ dev->params.lines = B16TOI (&dev->buffer[12]) + (B24TOI (&dev->buffer[9]) / dev->params.bytes_per_line); switch (dev->scan_mode) { case LEO_BW: case LEO_HALFTONE: dev->params.pixels_per_line &= ~0x7; dev->params.bytes_per_line = dev->params.pixels_per_line / 8; break; case LEO_GRAYSCALE: dev->params.bytes_per_line = dev->params.pixels_per_line; break; case LEO_COLOR: dev->params.bytes_per_line = dev->params.pixels_per_line * 3; break; } DBG (DBG_proc, "leo_get_scan_size: exit, status=%d\n", status); DBG (DBG_proc, "lines=%d, bpl=%d\n", dev->params.lines, dev->params.bytes_per_line); return (status); } /* Return the number of byte that can be read. */ static SANE_Status get_filled_data_length (Leo_Scanner * dev, size_t * to_read) { size_t size; CDB cdb; SANE_Status status; DBG (DBG_proc, "get_filled_data_length: enter\n"); *to_read = 0; size = 0x10; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (size != 0x10) { DBG (DBG_error, "get_filled_data_length: GET DATA BUFFER STATUS returned an invalid size (%ld)\n", (long) size); return SANE_STATUS_IO_ERROR; } hexdump (DBG_info2, "get_filled_data_length return", dev->buffer, size); *to_read = B24TOI (&dev->buffer[9]); DBG (DBG_info, "get_filled_data_length: to read = %ld\n", (long) *to_read); DBG (DBG_proc, "get_filled_data_length: exit, status=%d\n", status); return (status); } /* Start a scan. */ static SANE_Status leo_scan (Leo_Scanner * dev) { CDB cdb; SANE_Status status; DBG (DBG_proc, "leo_scan: enter\n"); MKSCSI_SCAN (cdb); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "leo_scan: exit, status=%d\n", status); return status; } /* Attach a scanner to this backend. */ static SANE_Status attach_scanner (const char *devicename, Leo_Scanner ** devp) { Leo_Scanner *dev; int sfd; DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); if (devp) *devp = NULL; /* Check if we know this device name. */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (DBG_info, "device is already known\n"); return SANE_STATUS_GOOD; } } /* Allocate a new scanner entry. */ dev = leo_init (); if (dev == NULL) { DBG (DBG_error, "ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_scanner: opening %s\n", devicename); if (sanei_scsi_open (devicename, &sfd, leo_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: attach_scanner: open failed\n"); leo_free (dev); return SANE_STATUS_INVAL; } /* Fill some scanner specific values. */ dev->devicename = strdup (devicename); dev->sfd = sfd; /* Now, check that it is a scanner we support. */ if (leo_identify_scanner (dev) == SANE_FALSE) { DBG (DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); leo_free (dev); return SANE_STATUS_INVAL; } leo_close (dev); /* Set the default options for that scanner. */ dev->sane.name = dev->devicename; dev->sane.vendor = dev->def->real_vendor; dev->sane.model = dev->def->real_product; dev->sane.type = "flatbed scanner"; /* Link the scanner with the others. */ dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } num_devices++; DBG (DBG_proc, "attach_scanner: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach_scanner (dev, NULL); return SANE_STATUS_GOOD; } /* Reset the options for that scanner. */ static void leo_init_options (Leo_Scanner * dev) { int i; /* Pre-initialize the options. */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < OPT_NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options. */ dev->opt[OPT_NUM_OPTS].name = ""; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; /* Mode group */ dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan mode"); dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].cap = 0; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scanner supported modes */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = max_string_size (scan_mode_list); dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = scan_mode_list; dev->val[OPT_MODE].s = (SANE_Char *) strdup (""); /* will be set later */ /* X and Y resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RESOLUTION].constraint.range = &dev->res_range; dev->val[OPT_RESOLUTION].w = dev->res_range.max / 2; /* Halftone pattern */ dev->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; dev->opt[OPT_HALFTONE_PATTERN].size = max_string_size (halftone_pattern_list); dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_pattern_list; dev->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[0]); /* Geometry group */ dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_GEOMETRY_GROUP].cap = 0; dev->opt[OPT_GEOMETRY_GROUP].size = 0; dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Upper left X */ dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &x_range; dev->val[OPT_TL_X].w = x_range.min; /* Upper left Y */ dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &y_range; dev->val[OPT_TL_Y].w = y_range.min; /* Bottom-right x */ dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &x_range; dev->val[OPT_BR_X].w = x_range.max; /* Bottom-right y */ dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &y_range; dev->val[OPT_BR_Y].w = y_range.max; /* Enhancement group */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* custom-gamma table */ dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* red gamma vector */ dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_R].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_R].wa = dev->gamma_R; /* green gamma vector */ dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_G].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_G].wa = dev->gamma_G; /* blue gamma vector */ dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_B].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_B].wa = dev->gamma_B; /* grayscale gamma vector */ dev->opt[OPT_GAMMA_VECTOR_GRAY].name = SANE_NAME_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].title = SANE_TITLE_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].desc = SANE_DESC_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_GRAY].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_GRAY].wa = dev->gamma_GRAY; /* preview */ dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; dev->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; dev->val[OPT_PREVIEW].w = SANE_FALSE; /* Lastly, set the default scan mode. This might change some * values previously set here. */ sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, (SANE_String_Const *) scan_mode_list[0], NULL); } /* * Wait until the scanner is ready. */ static SANE_Status leo_wait_scanner (Leo_Scanner * dev) { SANE_Status status; int timeout; CDB cdb; DBG (DBG_proc, "leo_wait_scanner: enter\n"); MKSCSI_TEST_UNIT_READY (cdb); /* Set the timeout to 60 seconds. */ timeout = 60; while (timeout > 0) { /* test unit ready */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); if (status == SANE_STATUS_GOOD) { return SANE_STATUS_GOOD; } sleep (1); }; DBG (DBG_proc, "leo_wait_scanner: scanner not ready\n"); return (SANE_STATUS_IO_ERROR); } /* Read the image from the scanner and fill the temporary buffer with it. */ static SANE_Status leo_fill_image (Leo_Scanner * dev) { SANE_Status status; size_t size; CDB cdb; unsigned char *image; DBG (DBG_proc, "leo_fill_image: enter\n"); assert (dev->image_begin == dev->image_end); assert (dev->real_bytes_left > 0); dev->image_begin = 0; dev->image_end = 0; while (dev->real_bytes_left) { /* * Try to read the maximum number of bytes. */ size = 0; while (size == 0) { status = get_filled_data_length (dev, &size); if (status) return (status); if (size == 0) usleep (100000); /* sleep 1/10th of second */ } if (size > dev->real_bytes_left) size = dev->real_bytes_left; if (size > dev->image_size - dev->image_end) size = dev->image_size - dev->image_end; /* The scanner seems to hang if more than 32KB are read. */ if (size > 0x7fff) size = 0x7fff; /* Always read a multiple of a line. */ size = size - (size % dev->params.bytes_per_line); if (size == 0) { /* Probably reached the end of the buffer. * Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } DBG (DBG_info, "leo_fill_image: to read = %ld bytes (bpl=%d)\n", (long) size, dev->params.bytes_per_line); MKSCSI_READ_10 (cdb, 0, 0, size); hexdump (DBG_info2, "leo_fill_image: READ_10 CDB", cdb.data, 10); image = dev->image + dev->image_end; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, image, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "leo_fill_image: cannot read from the scanner\n"); return status; } /* Some format conversion. */ if (dev->scan_mode == LEO_COLOR) { /* Reorder the lines. The scanner gives color by color for * each line. */ unsigned char *src = image; int nb_lines = size / dev->params.bytes_per_line; int i, j; for (i = 0; i < nb_lines; i++) { unsigned char *dest = dev->buffer; for (j = 0; j < dev->params.pixels_per_line; j++) { *dest = src[j + 0 * dev->params.pixels_per_line]; dest++; *dest = src[j + 1 * dev->params.pixels_per_line]; dest++; *dest = src[j + 2 * dev->params.pixels_per_line]; dest++; } /* Copy the line back. */ memcpy (src, dev->buffer, dev->params.bytes_per_line); src += dev->params.bytes_per_line; } } dev->image_end += size; dev->real_bytes_left -= size; DBG (DBG_info, "leo_fill_image: real bytes left = %ld\n", (long) dev->real_bytes_left); } return (SANE_STATUS_GOOD); /* unreachable */ } /* Copy from the raw buffer to the buffer given by the backend. * * len in input is the maximum length available in buf, and, in * output, is the length written into buf. */ static void leo_copy_raw_to_frontend (Leo_Scanner * dev, SANE_Byte * buf, size_t * len) { size_t size; size = dev->image_end - dev->image_begin; if (size > *len) { size = *len; } *len = size; memcpy (buf, dev->image + dev->image_begin, size); dev->image_begin += size; } /* Stop a scan. */ static SANE_Status do_cancel (Leo_Scanner * dev) { DBG (DBG_sane_proc, "do_cancel enter\n"); if (dev->scanning == SANE_TRUE) { /* Reset the scanner */ dev->x_tl = 0; dev->x_tl = 0; dev->width = 0; dev->length = 0; leo_set_window (dev); leo_scan (dev); leo_close (dev); } dev->scanning = SANE_FALSE; DBG (DBG_sane_proc, "do_cancel exit\n"); return SANE_STATUS_CANCELLED; } /* A default gamma table. */ static const SANE_Word gamma_init[GAMMA_LENGTH] = { 0x00, 0x06, 0x0A, 0x0D, 0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, 0x25, 0x27, 0x28, 0x2A, 0x2C, 0x2D, 0x2F, 0x30, 0x32, 0x33, 0x35, 0x36, 0x38, 0x39, 0x3A, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC0, 0xC1, 0xC2, 0xC3, 0xC3, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCF, 0xCF, 0xD0, 0xD1, 0xD2, 0xD2, 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, 0xDE, 0xDF, 0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5, 0xE6, 0xE6, 0xE7, 0xE8, 0xE8, 0xE9, 0xEA, 0xEB, 0xEB, 0xEC, 0xED, 0xED, 0xEE, 0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF4, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFC, 0xFD, 0xFE, 0xFE, 0xFF }; /* Send the gamma */ static SANE_Status leo_send_gamma (Leo_Scanner * dev) { CDB cdb; SANE_Status status; struct { unsigned char gamma_R[GAMMA_LENGTH]; unsigned char gamma_G[GAMMA_LENGTH]; /* also gray */ unsigned char gamma_B[GAMMA_LENGTH]; } param; size_t i; size_t size; DBG (DBG_proc, "leo_send_gamma: enter\n"); size = sizeof (param); assert (size == 3 * GAMMA_LENGTH); MKSCSI_SEND_10 (cdb, 0x03, 0x01, size); if (dev->val[OPT_CUSTOM_GAMMA].w) { /* Use the custom gamma. */ if (dev->scan_mode == LEO_GRAYSCALE) { /* Gray */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = dev->gamma_GRAY[i]; param.gamma_G[i] = 0; param.gamma_B[i] = 0; } } else { /* Color */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = dev->gamma_R[i]; param.gamma_G[i] = dev->gamma_G[i]; param.gamma_B[i] = dev->gamma_B[i]; } } } else { for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = gamma_init[i]; param.gamma_G[i] = gamma_init[i]; param.gamma_B[i] = gamma_init[i]; } } hexdump (DBG_info2, "leo_send_gamma:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, ¶m, size, NULL, NULL); DBG (DBG_proc, "leo_send_gamma: exit, status=%d\n", status); return (status); } /* Send the halftone pattern */ static SANE_Status leo_send_halftone_pattern (Leo_Scanner * dev) { int i; const halftone_pattern_t *pattern; SANE_Status status; size_t size; CDB cdb; DBG (DBG_proc, "leo_send_halftone_pattern: enter\n"); if (dev->scan_mode == LEO_HALFTONE) { i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); pattern = halftone_pattern_val[i]; assert (pattern != NULL); size = sizeof (halftone_pattern_t); assert (size == 256); MKSCSI_SEND_10 (cdb, 0x02, 0x0F, size); hexdump (DBG_info2, "leo_send_gamma:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, pattern, size, NULL, NULL); } else { status = SANE_STATUS_GOOD; } DBG (DBG_proc, "leo_send_halftone_pattern: exit, status=%d\n", status); return status; } /*--------------------------------------------------------------------------*/ /* Sane entry points */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; char dev_name[PATH_MAX]; size_t len; DBG_INIT (); DBG (DBG_sane_init, "sane_init\n"); DBG (DBG_error, "This is sane-leo version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_error, "(C) 2002 by Frank Zago\n"); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); } fp = sanei_config_open (LEO_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach_scanner ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); DBG (DBG_proc, "sane_init: leave\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { Leo_Scanner *dev; int i; DBG (DBG_proc, "sane_get_devices: enter\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Leo_Scanner *dev; SANE_Status status; DBG (DBG_proc, "sane_open: enter\n"); /* search for devicename */ if (devicename[0]) { DBG (DBG_info, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); dev = first_dev; /* empty devicename -> use first device */ } if (!dev) { DBG (DBG_error, "No scanner found\n"); return SANE_STATUS_INVAL; } leo_init_options (dev); /* Initialize the gamma table. */ memcpy (dev->gamma_R, gamma_init, dev->opt[OPT_GAMMA_VECTOR_R].size); memcpy (dev->gamma_G, gamma_init, dev->opt[OPT_GAMMA_VECTOR_G].size); memcpy (dev->gamma_B, gamma_init, dev->opt[OPT_GAMMA_VECTOR_B].size); memcpy (dev->gamma_GRAY, gamma_init, dev->opt[OPT_GAMMA_VECTOR_GRAY].size); *handle = dev; DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Leo_Scanner *dev = handle; DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); if ((unsigned) option >= OPT_NUM_OPTIONS) { return NULL; } DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return dev->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Leo_Scanner *dev = handle; SANE_Status status; SANE_Word cap; int i; DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", option, action); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_CUSTOM_GAMMA: case OPT_PREVIEW: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_HALFTONE_PATTERN: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; /* Gamma */ case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (val, dev->val[option].wa, dev->opt[option].size); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Numeric side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* Numeric side-effect free options */ case OPT_PREVIEW: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* String side-effect options */ case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, BLACK_WHITE_STR) == 0) { i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); if (halftone_pattern_val[i] == NULL) { dev->scan_mode = LEO_BW; } else { dev->scan_mode = LEO_HALFTONE; } dev->depth = 1; dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, GRAY_STR) == 0) { dev->scan_mode = LEO_GRAYSCALE; dev->depth = 8; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } } else if (strcmp (dev->val[OPT_MODE].s, COLOR_STR) == 0) { dev->scan_mode = LEO_COLOR; dev->depth = 8; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_HALFTONE_PATTERN: free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); if (halftone_pattern_val[i] == NULL) { dev->scan_mode = LEO_BW; } else { dev->scan_mode = LEO_HALFTONE; } return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (dev->val[option].wa, val, dev->opt[option].size); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: dev->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; if (dev->val[OPT_CUSTOM_GAMMA].w) { /* use custom_gamma_table */ if (dev->scan_mode == LEO_GRAYSCALE) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } else { /* color mode */ dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Leo_Scanner *dev = handle; DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { /* Setup the parameters for the scan. These values will be re-used * in the SET WINDOWS command. */ if (dev->val[OPT_PREVIEW].w == SANE_TRUE) { dev->x_resolution = 28; dev->y_resolution = 28; dev->x_tl = 0; dev->y_tl = 0; dev->x_br = mmToIlu (SANE_UNFIX (x_range.max)); dev->y_br = mmToIlu (SANE_UNFIX (y_range.max)); } else { dev->x_resolution = dev->val[OPT_RESOLUTION].w; dev->y_resolution = dev->val[OPT_RESOLUTION].w; dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); } /* Check the corners are OK. */ if (dev->x_tl > dev->x_br) { int s; s = dev->x_tl; dev->x_tl = dev->x_br; dev->x_br = s; } if (dev->y_tl > dev->y_br) { int s; s = dev->y_tl; dev->y_tl = dev->y_br; dev->y_br = s; } dev->width = dev->x_br - dev->x_tl; dev->length = dev->y_br - dev->y_tl; /* Prepare the parameters for the caller. */ memset (&dev->params, 0, sizeof (SANE_Parameters)); dev->params.last_frame = SANE_TRUE; switch (dev->scan_mode) { case LEO_BW: case LEO_HALFTONE: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = dev->width & ~0x7; dev->params.bytes_per_line = dev->params.pixels_per_line / 8; dev->params.depth = 1; break; case LEO_GRAYSCALE: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = dev->width; dev->params.bytes_per_line = dev->params.pixels_per_line; dev->params.depth = 8; break; case LEO_COLOR: dev->params.format = SANE_FRAME_RGB; dev->params.pixels_per_line = dev->width; dev->params.bytes_per_line = dev->params.pixels_per_line * 3; dev->params.depth = 8; break; } dev->params.lines = dev->length; } /* Return the current values. */ if (params) { *params = (dev->params); } DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Leo_Scanner *dev = handle; SANE_Status status; DBG (DBG_proc, "sane_start: enter\n"); if (!(dev->scanning)) { sane_get_parameters (dev, NULL); /* Open again the scanner. */ if (sanei_scsi_open (dev->devicename, &(dev->sfd), leo_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: sane_start: open failed\n"); return SANE_STATUS_INVAL; } /* The scanner must be ready. */ status = leo_wait_scanner (dev); if (status) { leo_close (dev); return status; } status = leo_set_window (dev); if (status) { leo_close (dev); return status; } status = leo_send_gamma (dev); if (status) { leo_close (dev); return status; } status = leo_send_halftone_pattern (dev); if (status) { leo_close (dev); return status; } status = leo_scan (dev); if (status) { leo_close (dev); return status; } status = leo_wait_scanner (dev); if (status) { leo_close (dev); return status; } status = leo_get_scan_size (dev); if (status) { leo_close (dev); return status; } } dev->image_end = 0; dev->image_begin = 0; dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->real_bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->scanning = SANE_TRUE; DBG (DBG_proc, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status status; Leo_Scanner *dev = handle; size_t size; int buf_offset; /* offset into buf */ DBG (DBG_proc, "sane_read: enter\n"); *len = 0; if (!(dev->scanning)) { /* OOPS, not scanning */ return do_cancel (dev); } if (dev->bytes_left <= 0) { return (SANE_STATUS_EOF); } buf_offset = 0; do { if (dev->image_begin == dev->image_end) { /* Fill image */ status = leo_fill_image (dev); if (status != SANE_STATUS_GOOD) { return (status); } } /* Something must have been read */ if (dev->image_begin == dev->image_end) { DBG (DBG_info, "sane_read: nothing read\n"); return SANE_STATUS_IO_ERROR; } /* Copy the data to the frontend buffer. */ size = max_len - buf_offset; if (size > dev->bytes_left) { size = dev->bytes_left; } leo_copy_raw_to_frontend (dev, buf + buf_offset, &size); buf_offset += size; dev->bytes_left -= size; *len += size; } while ((buf_offset != max_len) && dev->bytes_left); DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", (long) dev->bytes_left); return SANE_STATUS_GOOD; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { SANE_Status status; Leo_Scanner *dev = handle; DBG (DBG_proc, "sane_set_io_mode: enter\n"); if (!dev->scanning) { return SANE_STATUS_INVAL; } if (non_blocking == SANE_FALSE) { status = SANE_STATUS_GOOD; } else { status = SANE_STATUS_UNSUPPORTED; } DBG (DBG_proc, "sane_set_io_mode: exit\n"); return status; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { DBG (DBG_proc, "sane_get_select_fd: enter\n"); DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } void sane_cancel (SANE_Handle handle) { Leo_Scanner *dev = handle; DBG (DBG_proc, "sane_cancel: enter\n"); do_cancel (dev); DBG (DBG_proc, "sane_cancel: exit\n"); } void sane_close (SANE_Handle handle) { Leo_Scanner *dev = handle; Leo_Scanner *dev_tmp; DBG (DBG_proc, "sane_close: enter\n"); do_cancel (dev); leo_close (dev); /* Unlink dev. */ if (first_dev == dev) { first_dev = dev->next; } else { dev_tmp = first_dev; while (dev_tmp->next && dev_tmp->next != dev) { dev_tmp = dev_tmp->next; } if (dev_tmp->next != NULL) { dev_tmp->next = dev_tmp->next->next; } } leo_free (dev); num_devices--; DBG (DBG_proc, "sane_close: exit\n"); } void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); while (first_dev) { sane_close (first_dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); } sane-backends-1.0.27/backend/magicolor.h0000664000175000017500000001223612775312261014750 00000000000000/* * magicolor.h - SANE library for Magicolor scanners. * * (C) 2010 Reinhold Kainhofer * * Based on the epson2 sane backend: * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for original copyrights. * Copyright (C) 2006 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #ifndef magicolor_h #define magicolor_h #undef BACKEND_NAME #define BACKEND_NAME magicolor #define DEBUG_NOT_STATIC #include #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" /* Silence the compiler for unused arguments */ #define NOT_USED(x) ( (void)(x) ) #define MAGICOLOR_CONFIG_FILE "magicolor.conf" #define NUM_OF_HEX_ELEMENTS (16) /* number of hex numbers per line for data dump */ #define DEVICE_NAME_LEN (16) /* length of device name in extended status */ /* misc constants */ #define NET 0x04 #define CMD 0x03 /* status values */ #define STATUS_READY 0x00 /* scanner is ready */ #define STATUS_ADF_JAM 0x01 /* ADF paper jam */ #define STATUS_OPEN 0x02 /* scanner is open */ #define STATUS_NOT_READY 0x03 /* scanner is in use on another interface */ #define ADF_LOADED 0x01 /* ADF is loaded */ #define MAGICOLOR_CAP_DEFAULT 0 #define MAGICOLOR_LEVEL_1690mf 0 #define MAGICOLOR_LEVEL_DEFAULT MAGICOLOR_LEVEL_1690mf #define MAGICOLOR_LEVEL_NET MAGICOLOR_LEVEL_1690mf /* Structure holding the command set for a device */ struct MagicolorCmd { const char *level; unsigned char scanner_cmd; unsigned char start_scanning; unsigned char request_error; unsigned char stop_scanning; unsigned char request_scan_parameters; unsigned char set_scan_parameters; unsigned char request_status; unsigned char request_data; unsigned char unknown1; unsigned char unknown2; unsigned char net_wrapper_cmd; unsigned char net_welcome; unsigned char net_lock; unsigned char net_lock_ack; unsigned char net_unlock; }; /* Structure holding the device capabilities */ struct MagicolorCap { unsigned int id; const char *cmds; const char *model; const char *OID; SANE_Int out_ep, in_ep; /* USB bulk out/in endpoints */ SANE_Int optical_res; /* optical resolution */ SANE_Range dpi_range; /* max/min resolutions */ SANE_Int *res_list; /* list of resolutions */ SANE_Int res_list_size; /* number of entries in this list */ SANE_Int maxDepth; /* max. color depth */ SANE_Word *depth_list; /* list of color depths */ SANE_Range brightness; /* brightness range */ SANE_Range fbf_x_range; /* flattbed x range */ SANE_Range fbf_y_range; /* flattbed y range */ SANE_Bool ADF; /* ADF is installed */ SANE_Bool adf_duplex; /* does the ADF handle duplex scanning */ SANE_Range adf_x_range; /* autom. document feeder x range */ SANE_Range adf_y_range; /* autom. document feeder y range */ }; enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_BIT_DEPTH, OPT_BRIGHTNESS, OPT_RESOLUTION, OPT_PREVIEW, OPT_SOURCE, OPT_ADF_MODE, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, NUM_OPTIONS }; typedef enum { /* hardware connection to the scanner */ SANE_MAGICOLOR_NODEV, /* default, no HW specified yet */ SANE_MAGICOLOR_USB, /* USB interface */ SANE_MAGICOLOR_NET /* network interface */ } Magicolor_Connection_Type; /* Structure holding the hardware description */ struct Magicolor_Device { struct Magicolor_Device *next; int missing; char *name; char *model; SANE_Device sane; SANE_Range *x_range; /* x range w/out extension */ SANE_Range *y_range; /* y range w/out extension */ Magicolor_Connection_Type connection; struct MagicolorCmd *cmd; struct MagicolorCap *cap; }; typedef struct Magicolor_Device Magicolor_Device; /* Structure holding an instance of a scanner (i.e. scanner has been opened) */ struct Magicolor_Scanner { struct Magicolor_Scanner *next; struct Magicolor_Device *hw; int fd; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; SANE_Bool eof; SANE_Byte *buf, *end, *ptr; SANE_Bool canceling; SANE_Int left, top; SANE_Int width, height; /* image block data */ SANE_Int data_len; SANE_Int block_len; SANE_Int last_len; SANE_Int blocks; SANE_Int counter; /* store how many bytes of the current pixel line we have already * read in previous read attempts. Since each line will be padded * to multiples of 512 bytes, this is needed to know which bytes * to ignore */ SANE_Int bytes_read_in_line; SANE_Byte *line_buffer; /* How many bytes are scanned per line (multiple of 512 bytes */ SANE_Int scan_bytes_per_line; }; typedef struct Magicolor_Scanner Magicolor_Scanner; struct mode_param { int flags; int colors; int depth; }; enum { MODE_BINARY, MODE_GRAY, MODE_COLOR }; #endif sane-backends-1.0.27/backend/niash_xfer.c0000664000175000017500000002131712112021330015070 00000000000000/* Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. $Id$ */ /* Provides a simple interface to read and write data from the scanner, without any knowledge whether it's a parallel or USB scanner */ #include /* printf */ #include /* better error reports */ #include /* better error reports */ #include "niash_xfer.h" #include "../include/sane/sanei_usb.h" /* list of supported models */ STATIC TScannerModel ScannerModels[] = { {"Hewlett-Packard", "ScanJet 3300C", 0x3F0, 0x205, eHp3300c} , {"Hewlett-Packard", "ScanJet 3400C", 0x3F0, 0x405, eHp3400c} , {"Hewlett-Packard", "ScanJet 4300C", 0x3F0, 0x305, eHp4300c} , {"Silitek Corp.", "HP ScanJet 4300c", 0x47b, 0x1002, eHp3400c} , {"Agfa", "Snapscan Touch", 0x6BD, 0x100, eAgfaTouch} , {"Trust", "Office Scanner USB 19200", 0x47b, 0x1000, eAgfaTouch} , /* last entry all zeros */ {0, 0, 0, 0, 0} }; static TFnReportDevice *_pfnReportDevice; static TScannerModel *_pModel; /* MatchUsbDevice ============== Matches a given USB vendor and product id against a list of supported scanners. IN iVendor USB vendor ID iProduct USB product ID OUT *ppModel Pointer to TScannerModel structure Returns TRUE if a matching USB scanner was found */ STATIC SANE_Bool MatchUsbDevice (int iVendor, int iProduct, TScannerModel ** ppModel) { TScannerModel *pModels = ScannerModels; DBG (DBG_MSG, "Matching USB device 0x%04X-0x%04X ... ", iVendor, iProduct); while (pModels->pszName != NULL) { if ((pModels->iVendor == iVendor) && (pModels->iProduct == iProduct)) { DBG (DBG_MSG, "found %s %s\n", pModels->pszVendor, pModels->pszName); *ppModel = pModels; return SANE_TRUE; } /* next model to match */ pModels++; } DBG (DBG_MSG, "nothing found\n"); return SANE_FALSE; } /************************************************************************ Public functions for the SANE compilation ************************************************************************/ /* callback for sanei_usb_attach_matching_devices */ static SANE_Status _AttachUsb (SANE_String_Const devname) { DBG (DBG_MSG, "_AttachUsb: found %s\n", devname); _pfnReportDevice (_pModel, (const char *) devname); return SANE_STATUS_GOOD; } /* NiashXferInit =============== Initialises all registered data transfer modules, which causes them to report any devices found through the pfnReport callback. IN pfnReport Function to call to report a transfer device */ static void NiashXferInit (TFnReportDevice * pfnReport) { TScannerModel *pModels = ScannerModels; sanei_usb_init (); _pfnReportDevice = pfnReport; /* loop over all scanner models */ while (pModels->pszName != NULL) { DBG (DBG_MSG, "Looking for %s...\n", pModels->pszName); _pModel = pModels; if (sanei_usb_find_devices ((SANE_Int) pModels->iVendor, (SANE_Int) pModels->iProduct, _AttachUsb) != SANE_STATUS_GOOD) { DBG (DBG_ERR, "Error invoking sanei_usb_find_devices"); break; } pModels++; } } static int NiashXferOpen (const char *pszName, EScannerModel * peModel) { SANE_Status status; SANE_Word vendor, product; int fd; TScannerModel *pModel = 0; DBG (DBG_MSG, "Trying to open %s...\n", pszName); status = sanei_usb_open (pszName, &fd); if (status != SANE_STATUS_GOOD) { return -1; } status = sanei_usb_get_vendor_product (fd, &vendor, &product); if (status == SANE_STATUS_GOOD) { MatchUsbDevice (vendor, product, &pModel); *peModel = pModel->eModel; } DBG (DBG_MSG, "handle = %d\n", (int) fd); return fd; } static void NiashXferClose (int iHandle) { /* close usb device */ if (iHandle != -1) { sanei_usb_close (iHandle); } } static void parusb_write_reg (int fd, unsigned char bReg, unsigned char bValue) { sanei_usb_control_msg (fd, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 0x0C, bReg, 0, 1, &bValue); } static void parusb_read_reg (int fd, unsigned char bReg, unsigned char *pbValue) { sanei_usb_control_msg (fd, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x0C, bReg, 0, 1, pbValue); } static void NiashWriteReg (int iHandle, unsigned char bReg, unsigned char bData) { if (iHandle < 0) { DBG (DBG_MSG, "Invalid handle %d\n", iHandle); return; } parusb_write_reg (iHandle, SPP_CONTROL, 0x14); parusb_write_reg (iHandle, EPP_ADDR, bReg); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); parusb_write_reg (iHandle, EPP_DATA_WRITE, bData); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); } static void NiashReadReg (int iHandle, unsigned char bReg, unsigned char *pbData) { if (iHandle < 0) { return; } parusb_write_reg (iHandle, SPP_CONTROL, 0x14); parusb_write_reg (iHandle, EPP_ADDR, bReg); parusb_write_reg (iHandle, SPP_CONTROL, 0x34); parusb_read_reg (iHandle, EPP_DATA_READ, pbData); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); } static void NiashWriteBulk (int iHandle, unsigned char *pabBuf, int iSize) { /* byte abSetup[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; HP3400 probably needs 0x01, 0x01 */ SANE_Byte abSetup[8] = { 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; size_t size; if (iHandle < 0) { return; } /* select scanner register 0x24 */ parusb_write_reg (iHandle, SPP_CONTROL, 0x14); parusb_write_reg (iHandle, EPP_ADDR, 0x24); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); /* tell scanner that a bulk transfer follows */ abSetup[4] = (iSize) & 0xFF; abSetup[5] = (iSize >> 8) & 0xFF; sanei_usb_control_msg (iHandle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 0x04, USB_SETUP, 0, 8, abSetup); /* do the bulk write */ size = iSize; if (sanei_usb_write_bulk (iHandle, pabBuf, &size) != SANE_STATUS_GOOD) { DBG (DBG_ERR, "ERROR: Bulk write failed\n"); } } static void NiashReadBulk (int iHandle, unsigned char *pabBuf, int iSize) { SANE_Byte abSetup[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; size_t size; if (iHandle < 0) { return; } /* select scanner register 0x24 */ parusb_write_reg (iHandle, SPP_CONTROL, 0x14); parusb_write_reg (iHandle, EPP_ADDR, 0x24); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); /* tell scanner that a bulk transfer follows */ abSetup[4] = (iSize) & 0xFF; abSetup[5] = (iSize >> 8) & 0xFF; sanei_usb_control_msg (iHandle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 0x04, USB_SETUP, 0, 8, abSetup); /* do the bulk read */ size = iSize; if (sanei_usb_read_bulk (iHandle, pabBuf, &size) != SANE_STATUS_GOOD) { DBG (DBG_ERR, "ERROR: Bulk read failed\n"); } } static void NiashWakeup (int iHandle) { unsigned char abMagic[] = { 0xA0, 0xA8, 0x50, 0x58, 0x90, 0x98, 0xC0, 0xC8, 0x90, 0x98, 0xE0, 0xE8 }; int i; if (iHandle < 0) { return; } /* write magic startup sequence */ parusb_write_reg (iHandle, SPP_CONTROL, 0x14); for (i = 0; i < (int) sizeof (abMagic); i++) { parusb_write_reg (iHandle, SPP_DATA, abMagic[i]); } /* write 0x04 to scanner register 0x00 the hard way */ parusb_write_reg (iHandle, SPP_DATA, 0x00); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); parusb_write_reg (iHandle, SPP_CONTROL, 0x15); parusb_write_reg (iHandle, SPP_CONTROL, 0x1D); parusb_write_reg (iHandle, SPP_CONTROL, 0x15); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); parusb_write_reg (iHandle, SPP_DATA, 0x04); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); parusb_write_reg (iHandle, SPP_CONTROL, 0x15); parusb_write_reg (iHandle, SPP_CONTROL, 0x17); parusb_write_reg (iHandle, SPP_CONTROL, 0x15); parusb_write_reg (iHandle, SPP_CONTROL, 0x14); } sane-backends-1.0.27/backend/ricoh.h0000664000175000017500000001777312112021330014066 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998, Feico W. Dillema This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ */ #ifndef ricoh_h #define ricoh_h 1 #include #include "../include/sane/config.h" /* defines for scan_image_mode field */ #define RICOH_BINARY_MONOCHROME 0 #define RICOH_DITHERED_MONOCHROME 1 #define RICOH_GRAYSCALE 2 /* sizes for mode parameter's base_measurement_unit */ #define INCHES 0 #define MILLIMETERS 1 #define POINTS 2 #define DEFAULT_MUD 1200 #define MEASUREMENTS_PAGE (SANE_Byte)(0x03) /* Mode Page Control */ #define PC_CURRENT 0x00 #define PC_CHANGE 0x40 #define PC_DEFAULT 0x80 #define PC_SAVED 0xc0 static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, 0 }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const SANE_Range is50_res_range = { 75, /* minimum */ 400, /* maximum */ 0 /* quantization */ }; static const SANE_Range is60_res_range = { 100, /* minimum */ 600, /* maximum */ 0 /* quantization */ }; static const SANE_Range default_x_range = { 0, /* minimum */ (SANE_Word) (8 * DEFAULT_MUD), /* maximum */ 2 /* quantization */ }; static const SANE_Range default_y_range = { 0, /* minimum */ (SANE_Word) (14 * DEFAULT_MUD), /* maximum */ 2 /* quantization */ }; static inline void _lto2b(SANE_Int val, SANE_Byte *bytes) { bytes[0] = (val >> 8) & 0xff; bytes[1] = val & 0xff; } static inline void _lto3b(SANE_Int val, SANE_Byte *bytes) { bytes[0] = (val >> 16) & 0xff; bytes[1] = (val >> 8) & 0xff; bytes[2] = val & 0xff; } static inline void _lto4b(SANE_Int val, SANE_Byte *bytes) { bytes[0] = (val >> 24) & 0xff; bytes[1] = (val >> 16) & 0xff; bytes[2] = (val >> 8) & 0xff; bytes[3] = val & 0xff; } static inline SANE_Int _2btol(SANE_Byte *bytes) { SANE_Int rv; rv = (bytes[0] << 8) | bytes[1]; return (rv); } static inline SANE_Int _3btol(SANE_Byte *bytes) { SANE_Int rv; rv = (bytes[0] << 16) | (bytes[1] << 8) | bytes[2]; return (rv); } static inline SANE_Int _4btol(SANE_Byte *bytes) { SANE_Int rv; rv = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; return (rv); } typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_X_RESOLUTION, OPT_Y_RESOLUTION, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, /* must come last: */ NUM_OPTIONS } Ricoh_Option; typedef struct Ricoh_Info { SANE_Range xres_range; SANE_Range yres_range; SANE_Range x_range; SANE_Range y_range; SANE_Range brightness_range; SANE_Range contrast_range; SANE_Int xres_default; SANE_Int yres_default; SANE_Int image_mode_default; SANE_Int brightness_default; SANE_Int contrast_default; SANE_Int bmu; SANE_Int mud; } Ricoh_Info; typedef struct Ricoh_Device { struct Ricoh_Device *next; SANE_Device sane; Ricoh_Info info; } Ricoh_Device; typedef struct Ricoh_Scanner { /* all the state needed to define a scan request: */ struct Ricoh_Scanner *next; int fd; /* SCSI filedescriptor */ SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; /* scanner dependent/low-level state: */ Ricoh_Device *hw; SANE_Int xres; SANE_Int yres; SANE_Int ulx; SANE_Int uly; SANE_Int width; SANE_Int length; SANE_Int brightness; SANE_Int contrast; SANE_Int image_composition; SANE_Int bpp; SANE_Bool reverse; size_t bytes_to_read; int scanning; } Ricoh_Scanner; struct inquiry_data { SANE_Byte devtype; SANE_Byte byte2; SANE_Byte byte3; SANE_Byte byte4; SANE_Byte byte5; SANE_Byte res1[2]; SANE_Byte flags; SANE_Byte vendor[8]; SANE_Byte product[8]; SANE_Byte revision[4]; SANE_Byte byte[60]; }; #define RICOH_WINDOW_DATA_SIZE 328 struct ricoh_window_data { /* header */ SANE_Byte reserved[6]; SANE_Byte len[2]; /* data */ SANE_Byte window_id; /* must be zero */ SANE_Byte auto_bit; SANE_Byte x_res[2]; SANE_Byte y_res[2]; SANE_Byte x_org[4]; SANE_Byte y_org[4]; SANE_Byte width[4]; SANE_Byte length[4]; SANE_Byte brightness; SANE_Byte threshold; SANE_Byte contrast; SANE_Byte image_comp; /* image composition (data type) */ SANE_Byte bits_per_pixel; SANE_Byte halftone_pattern[2]; SANE_Byte pad_type; SANE_Byte bit_ordering[2]; SANE_Byte compression_type; SANE_Byte compression_arg; SANE_Byte res3[6]; /* Vendor Specific parameter byte(s) */ /* Ricoh specific, follow the scsi2 standard ones */ SANE_Byte byte1; SANE_Byte byte2; SANE_Byte mrif_filtering_gamma_id; SANE_Byte byte3; SANE_Byte byte4; SANE_Byte binary_filter; SANE_Byte reserved2[18]; SANE_Byte reserved3[256]; }; struct measurements_units_page { SANE_Byte page_code; /* 0x03 */ SANE_Byte parameter_length; /* 0x06 */ SANE_Byte bmu; SANE_Byte res1; SANE_Byte mud[2]; SANE_Byte res2[2]; /* anybody know what `COH' may mean ??? */ #if 0 SANE_Byte more_pages[243]; /* maximum size 255 bytes (incl header) */ #endif }; struct mode_pages { SANE_Byte page_code; SANE_Byte parameter_length; SANE_Byte rest[6]; #if 0 SANE_Byte more_pages[243]; /* maximum size 255 bytes (incl header) */ #endif }; #endif /* ricoh_h */ sane-backends-1.0.27/backend/pixma.conf.in0000664000175000017500000000173113063340150015200 00000000000000# pixma.conf configuration for the sane pixma backend # # bjnp-timeout=5000 # Specify the timeout (in ms) to be used for all the folllowing # scanners. # May be specified multiple times. # The last value (if any) will be used for auto-detection # # define URI's of scanners (one per line) # This is only used for network scanners. # normally scanners will be detected by sending a broadcast # if this does not work under your OS, or if the scanners # are on a different subnet, configure your scanners URI here # # method must be bjnp # port number can normally be left out, port 8612 is used as default # The timeout parameter sets a timeout value for the scanner on # the same line # Example: # bjnp://myscanner.my.domain:8612 // uses the default 1000ms timeout # bjnp-timeout=5000 # bjnp://printer-1.pheasant.org // will use the 5000 ms timeout # bjnp://scanner.bad-network.org/timeout=1500 // timeout set to 1500 ms # bjnp-timeout=3000 // will be used for auto-detected scanners # sane-backends-1.0.27/backend/kvs20xx.h0000664000175000017500000001071412775312261014320 00000000000000#ifndef __KVS20XX_H #define __KVS20XX_H /* Copyright (C) 2008, Panasonic Russia Ltd. Copyright (C) 2010, m. allan noah */ /* Panasonic KV-S20xx USB-SCSI scanners. */ #include #undef BACKEND_NAME #define BACKEND_NAME kvs20xx #define DBG_ERR 1 #define DBG_WARN 2 #define DBG_MSG 3 #define DBG_INFO 4 #define DBG_DBG 5 #define PANASONIC_ID 0x04da #define KV_S2025C 0xdeadbeef #define KV_S2045C 0xdeadbeee #define KV_S2026C 0x1000 #define KV_S2046C 0x1001 #define KV_S2048C 0x1009 #define KV_S2028C 0x100a #define USB 1 #define SCSI 2 #define MAX_READ_DATA_SIZE 0x10000 #define BULK_HEADER_SIZE 12 typedef unsigned char u8; typedef unsigned u32; typedef unsigned short u16; #define SIDE_FRONT 0x00 #define SIDE_BACK 0x80 /* options */ typedef enum { NUM_OPTS = 0, /* General options */ MODE_GROUP, MODE, /* scanner modes */ RESOLUTION, /* X and Y resolution */ DUPLEX, /* Duplex mode */ FEEDER_MODE, /* Feeder mode, fixed to Continous */ LENGTHCTL, /* Length control mode */ MANUALFEED, /* Manual feed mode */ FEED_TIMEOUT, /* Feed timeout */ DBLFEED, /* Double feed detection mode */ FIT_TO_PAGE, /* Scanner shrinks image to fit scanned page */ /* Geometry group */ GEOMETRY_GROUP, PAPER_SIZE, /* Paper size */ LANDSCAPE, /* true if landscape */ TL_X, /* upper left X */ TL_Y, /* upper left Y */ BR_X, /* bottom right X */ BR_Y, /* bottom right Y */ ADVANCED_GROUP, BRIGHTNESS, /* Brightness */ CONTRAST, /* Contrast */ THRESHOLD, /* Binary threshold */ IMAGE_EMPHASIS, /* Image emphasis */ GAMMA_CORRECTION, /* Gamma correction */ LAMP, /* Lamp -- color drop out */ /* must come last: */ NUM_OPTIONS } KV_OPTION; #ifndef SANE_OPTION typedef union { SANE_Bool b; /**< bool */ SANE_Word w; /**< word */ SANE_Word *wa; /**< word array */ SANE_String s; /**< string */ } Option_Value; #define SANE_OPTION 1 #endif struct scanner { unsigned id; int scanning; int page; int side; int bus; SANE_Int file; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; u8 *buffer; u8 *data; unsigned side_size; unsigned read; unsigned dummy_size; unsigned saved_dummy_size; }; struct window { u8 reserved[6]; u16 window_descriptor_block_length; u8 window_identifier; u8 reserved2; u16 x_resolution; u16 y_resolution; u32 upper_left_x; u32 upper_left_y; u32 width; u32 length; u8 brightness; u8 threshold; u8 contrast; u8 image_composition; u8 bit_per_pixel; u16 halftone_pattern; u8 reserved3; u16 bit_ordering; u8 compression_type; u8 compression_argument; u8 reserved4[6]; u8 vendor_unique_identifier; u8 nobuf_fstspeed_dfstop; u8 mirror_image; u8 image_emphasis; u8 gamma_correction; u8 mcd_lamp_dfeed_sens; u8 reserved5; u8 document_size; u32 document_width; u32 document_length; u8 ahead_deskew_dfeed_scan_area_fspeed_rshad; u8 continuous_scanning_pages; u8 automatic_threshold_mode; u8 automatic_separation_mode; u8 standard_white_level_mode; u8 b_wnr_noise_reduction; u8 mfeed_toppos_btmpos_dsepa_hsepa_dcont_rstkr; u8 stop_mode; } __attribute__((__packed__)); void kvs20xx_init_options (struct scanner *); void kvs20xx_init_window (struct scanner *s, struct window *wnd, int wnd_id); static inline u16 swap_bytes16 (u16 x) { return x << 8 | x >> 8; } static inline u32 swap_bytes32 (u32 x) { return x << 24 | x >> 24 | (x & (u32) 0x0000ff00UL) << 8 | (x & (u32) 0x00ff0000UL) >> 8; } static inline void copy16 (u8 * p, u16 x) { memcpy (p, (u8 *) &x, sizeof (x)); } #if __BYTE_ORDER == __BIG_ENDIAN static inline void set24 (u8 * p, u32 x) { p[2] = x >> 16; p[1] = x >> 8; p[0] = x >> 0; } #define cpu2be16(x) (x) #define cpu2be32(x) (x) #define cpu2le16(x) swap_bytes16(x) #define cpu2le32(x) swap_bytes32(x) #define le2cpu16(x) swap_bytes16(x) #define le2cpu32(x) swap_bytes32(x) #define be2cpu16(x) (x) #define be2cpu32(x) (x) #define BIT_ORDERING 0 #elif __BYTE_ORDER == __LITTLE_ENDIAN static inline void set24 (u8 * p, u32 x) { p[0] = x >> 16; p[1] = x >> 8; p[2] = x >> 0; } #define cpu2le16(x) (x) #define cpu2le32(x) (x) #define cpu2be16(x) swap_bytes16(x) #define cpu2be32(x) swap_bytes32(x) #define le2cpu16(x) (x) #define le2cpu32(x) (x) #define be2cpu16(x) swap_bytes16(x) #define be2cpu32(x) swap_bytes32(x) #define BIT_ORDERING 1 #else #error __BYTE_ORDER not defined #endif #endif /*__KVS20XX_H*/ sane-backends-1.0.27/backend/pieusb.h0000664000175000017500000000741713106201017014251 00000000000000/* sane - Scanner Access Now Easy. pieusb.h Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIEUSB_H #define PIEUSB_H #include "../include/sane/config.h" #include #include #include #ifdef HAVE_UNISTD_H #include #endif #define BACKEND_NAME pieusb #include "../include/sane/sane.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_debug.h" #include "pieusb_scancmd.h" #include "pieusb_usb.h" /* -------------------------------------------------------------------------- * * SUPPORTED DEVICES SPECIFICS * * --------------------------------------------------------------------------*/ /* List of default supported scanners by vendor-id, product-id and model number. * A default list will be created in sane_init(), and entries in the config file * will be added to it. */ struct Pieusb_USB_Device_Entry { SANE_Word vendor; /* USB vendor identifier */ SANE_Word product; /* USB product identifier */ SANE_Word model; /* USB model number */ SANE_Int device_number; /* USB device number if the device is present */ SANE_Int flags; /* flags */ }; extern struct Pieusb_USB_Device_Entry* pieusb_supported_usb_device_list; extern struct Pieusb_USB_Device_Entry pieusb_supported_usb_device; /* for searching */ struct Pieusb_Device_Definition; extern struct Pieusb_Device_Definition *pieusb_definition_list_head; /* Debug error levels */ #define DBG_error 1 /* errors */ #define DBG_warning 3 /* warnings */ #define DBG_info 5 /* information */ #define DBG_info_sane 7 /* information sane interface level */ #define DBG_inquiry 8 /* inquiry data */ #define DBG_info_proc 9 /* information pieusb backend functions */ #define DBG_info_scan 11 /* information scanner commands */ #define DBG_info_usb 13 /* information usb level functions */ #define DBG_info_buffer 15 /* information buffer functions */ /* R G B I */ #define PLANES 4 #endif /* PIEUSB_H */ sane-backends-1.0.27/backend/pieusb_usb.h0000664000175000017500000001036512775312261015135 00000000000000/* sane - Scanner Access Now Easy. pieusb_usb.h Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIEUSB_USB_H #define PIEUSB_USB_H #define PIEUSB_WAIT_BUSY 1 /* seconds to wait on busy condition */ #define SCSI_COMMAND_LEN 6 SANE_Status sanei_pieusb_usb_reset(SANE_Int device_number); SANE_Status sanei_pieusb_convert_status(PIEUSB_Status status); SANE_String sanei_pieusb_decode_sense(struct Pieusb_Sense* sense, PIEUSB_Status *status); PIEUSB_Status sanei_pieusb_command(SANE_Int device_number, SANE_Byte command[], SANE_Byte data[], SANE_Int size); /* ========================================================================= * * Pieusb scanner commands * * ========================================================================= */ /* Standard SCSI command codes */ #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_REQUEST_SENSE 0x03 #define SCSI_READ 0x08 #define SCSI_WRITE 0x0A #define SCSI_PARAM 0x0F #define SCSI_INQUIRY 0x12 #define SCSI_MODE_SELECT 0x15 #define SCSI_COPY 0x18 #define SCSI_MODE_SENSE 0x1A #define SCSI_SCAN 0x1B /* Non-standard SCSI command codes */ #define SCSI_SLIDE 0xD1 #define SCSI_SET_SCAN_HEAD 0xD2 #define SCSI_READ_GAIN_OFFSET 0xD7 #define SCSI_WRITE_GAIN_OFFSET 0xDC #define SCSI_READ_STATE 0xDD /* Additional SCSI READ/WRITE codes, |0x80 for Read */ #define SCSI_POWER_SAVE_CONTROL 0x01 #define SCSI_GAMMA_TABLE 0x10 #define SCSI_HALFTONE_PATTERN 0x11 #define SCSI_SCAN_FRAME 0x12 #define SCSI_EXPOSURE 0x13 #define SCSI_HIGHLIGHT_SHADOW 0x14 #define SCSI_CALIBRATION_INFO 0x15 #define SCSI_CAL_DATA 0x16 #define SCSI_CMD_17 0x17 /* used by CyberView */ /* Standard SCSI Sense keys, see http://www.t10.org/lists/2sensekey.htm */ #define SCSI_SENSE_NO_SENSE 0x00 #define SCSI_SENSE_RECOVERED_ERROR 0x01 #define SCSI_SENSE_NOT_READY 0x02 #define SCSI_SENSE_MEDIUM_ERROR 0x03 #define SCSI_SENSE_HARDWARE_ERROR 0x04 #define SCSI_SENSE_ILLEGAL_REQUEST 0x05 #define SCSI_SENSE_UNIT_ATTENTION 0x06 #define SCSI_SENSE_DATA_PROTECT 0x07 #define SCSI_SENSE_BLANK_CHECK 0x08 #define SCSI_SENSE_VENDOR_SPECIFIC 0x09 #define SCSI_SENSE_COPY_ABORTED 0x0A #define SCSI_SENSE_ABORTED_COMMAND 0x0B #define SCSI_SENSE_EQUAL 0x0C #define SCSI_SENSE_VOLUME_OVERFLOW 0x0D #define SCSI_SENSE_MISCOMPARE 0x0E #define SCSI_SENSE_COMPLETED 0x0F #endif /* PIEUSB_USB_H */ sane-backends-1.0.27/backend/mustek_usb2_asic.h0000664000175000017500000013434512621242546016242 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005 Mustek. Originally maintained by Mustek Author:Roy 2005.5.24 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro and similar USB2 scanners. */ #ifndef MUSTEK_USB2_ASIC_H #define MUSTEK_USB2_ASIC_H #include "../include/sane/sanei_usb.h" /* ---------------------- low level asic defines -------------------------- */ #define TRUE 1 #define FALSE 0 #define _MAX(a,b) ((a)>(b)?(a):(b)) #define _MIN(a,b) ((a)<(b)?(a):(b)) #ifndef LOBYTE #define LOBYTE(w) (SANE_Byte)((unsigned short)(w) & 0x00ff) #endif #ifndef HIBYTE #define HIBYTE(w) (SANE_Byte)((unsigned short)(w)>>8 & 0x00ff) #endif typedef enum tagFIRMWARESTATE { FS_NULL = 0, FS_ATTACHED = 1, FS_OPENED = 2, FS_SCANNING = 3 } FIRMWARESTATE, *LPFIRMWARESTATE; typedef enum tagMOTORSTATE { MS_STILL = 0, MS_MOVED = 1 } MOTORSTATE, *LPMOTORSTATE; typedef enum tagUSBHOST { HT_USB10 = 0, HT_USB20 = 1 } USBHOST; typedef enum tagLIGHTSOURCE { LS_REFLECTIVE = 1, LS_POSITIVE = 2, LS_NEGATIVE = 4 } LIGHTSOURCE; typedef struct { unsigned int LongX; unsigned int PicWidth; unsigned int PicHeight; unsigned int Top; unsigned int Bottom; unsigned int Left; unsigned int Right; unsigned int ScanMode; unsigned int Dpi; unsigned int TotalMotorSteps; unsigned int CCD_Pixel_Length; SANE_Byte LineGap; SANE_Byte TG_Pulse_Width_Pixel; SANE_Byte TG_Wait_Width_Pixel; unsigned short Multi_TG_Dummy_Pixel; unsigned short CCD_Dummy_Pixel; SANE_Byte Dummy_Cycle; SANE_Byte TG_Times; double LineTime; unsigned short StartPixel; unsigned short StartLine; } ScanParam; typedef struct { unsigned int Shading_Table_Size; unsigned int Image_Buffer_Size; unsigned int Full_Bank; unsigned int Line_Pixel; double Line_Time; SANE_Byte LineGap; } Temps; typedef struct { /* AFE */ unsigned int AFE_ADCCLK_Timing; unsigned int AFE_ADCVS_Timing; unsigned int AFE_ADCRS_Timing; unsigned short AFE_ChannelA_LatchPos; unsigned short AFE_ChannelB_LatchPos; unsigned short AFE_ChannelC_LatchPos; unsigned short AFE_ChannelD_LatchPos; SANE_Byte AFE_Secondary_FF_LatchPos; /* Sensor */ unsigned int CCD_DummyCycleTiming; SANE_Byte PHTG_PluseWidth; SANE_Byte PHTG_WaitWidth; unsigned short ChannelR_StartPixel; unsigned short ChannelR_EndPixel; unsigned short ChannelG_StartPixel; unsigned short ChannelG_EndPixel; unsigned short ChannelB_StartPixel; unsigned short ChannelB_EndPixel; SANE_Byte PHTG_TimingAdj; SANE_Byte PHTG_TimingSetup; /*1200dpi */ unsigned int CCD_PHRS_Timing_1200; unsigned int CCD_PHCP_Timing_1200; unsigned int CCD_PH1_Timing_1200; unsigned int CCD_PH2_Timing_1200; SANE_Byte DE_CCD_SETUP_REGISTER_1200; unsigned short wCCDPixelNumber_1200; /*600dpi */ unsigned int CCD_PHRS_Timing_600; unsigned int CCD_PHCP_Timing_600; unsigned int CCD_PH1_Timing_600; unsigned int CCD_PH2_Timing_600; SANE_Byte DE_CCD_SETUP_REGISTER_600; unsigned short wCCDPixelNumber_600; } Timings; typedef struct tagADConverter { SANE_Byte GainR; SANE_Byte GainG; SANE_Byte GainB; SANE_Byte OffsetR; SANE_Byte OffsetG; SANE_Byte OffsetB; SANE_Bool DirectionR; SANE_Bool DirectionG; SANE_Bool DirectionB; } ADConverter, LPADConverter; typedef struct { unsigned int Shading; SANE_Byte Shading_0; SANE_Byte Shading_1; SANE_Byte Shading_2; unsigned int Motor; SANE_Byte Motor_0; SANE_Byte Motor_1; SANE_Byte Motor_2; SANE_Byte ImageEndAddr_0; SANE_Byte ImageEndAddr_1; SANE_Byte ImageEndAddr_2; SANE_Byte ImageFullBank_0; SANE_Byte ImageFullBank_1; } RamPosition; typedef enum tagTASSTATUS { TA_NOT_PLUGIN = 0, TA_PLUGIN = 1, TA_UNKNOW = 2 } TASTATUS; typedef struct { int fd; /* File Description of Scanner */ FIRMWARESTATE firmwarestate; /* record firmware state */ MOTORSTATE motorstate; /* record motor status */ SANE_Bool isFirstOpenChip; /* If first open chip, is TRUE */ USBHOST UsbHost; /* The type of USB port */ LIGHTSOURCE lsLightSource; /* light source of scanner */ ScanParam Scan; /* The parameters of Scan */ unsigned int dwBytesCountPerRow; unsigned int dwCalibrationBytesCountPerRow; Temps Temp; Timings Timing; ADConverter AD; SANE_Bool isHardwareShading; RamPosition RamPositions; unsigned short * lpGammaTable; SANE_Byte isMotorMove; unsigned int ibase1; unsigned int ibase2; unsigned short SWWidth; TASTATUS TA_Status; SANE_Byte isMotorGoToFirstLine; /*Roy add */ SANE_Byte * lpShadingTable; /*Roy add */ SANE_Byte isUniformSpeedToScan; } Asic, *PAsic; typedef enum { STATUS_GOOD = 0, STATUS_CANCELLED, STATUS_EOF, STATUS_DEVICE_BUSY, STATUS_INVAL, STATUS_MEM_ERROR, STATUS_IO_ERROR, STATUS_ACCESS_ERROR } STATUS; /* For ScanObj */ typedef struct Point { unsigned int x; unsigned int y; } Point; typedef struct Rect { unsigned int left; unsigned int right; unsigned int top; unsigned int bottom; } Rect; typedef struct RGBColor { unsigned short Red; unsigned short Green; unsigned short Blue; } RGBColor; /* debug levels */ #define DBG_CRIT 0 /* Critical errors thatshould be printed even if user hasn't enabled debugging -- use with care and only after sane_open has been called */ #define DBG_ERR 1 /* Other errors */ #define DBG_WARN 2 /* unusual conditions that may not be fatal */ #define DBG_INFO 3 /* information useful for the deucated user */ #define DBG_DET 4 /* more detailed information */ #define DBG_FUNC 5 /* start and exits of high level functions */ #define DBG_ASIC 6 /* starts and exits of low level functions */ #define DBG_DBG 10 /* usefull only for tracing bugs */ #define DPI_2400 0x8000 #define DPI_1200 0x8000 #define DPI_600 0x8000 #define DPI_300 0x4000 #define DPI_200 0x2aaa #define DPI_150 0x2000 #define DPI_100 0x1555 #define DPI_75 0x1000 #define DPI_50 0xaaa #define PIXEL_TIME 333 /*unit : ms */ #define DRAM_1Mx16_SIZE (1024*1024) /*unit : word */ #define PackAreaStartAddress ((DRAM_1Mx16_SIZE/4)*3) #define TEMP_MEMORY_SIZE_64K 64*1024 #define CALIBRATION_PIXEL_WIDTH 10240 /*need 512x */ #define CALIBRATE_WHITE_LINECOUNT 40 #define CALIBRATE_DARK_LINECOUNT 2 #define ACTION_MODE_ACCDEC_MOVE 0 #define ACTION_MODE_UNIFORM_SPEED_MOVE 1 #define ACTION_TYPE_BACKWARD 0 #define ACTION_TYPE_FORWARD 1 #define ACTION_TYPE_BACKTOHOME 2 #define ACTION_TYPE_TEST_MODE 3 #define SENSOR0_DETECTED 0x10 #define SENSOR1_DETECTED 0x20 #define SENSOR0AND1_DETECTED 0x30 #define READ_RAM 0 #define WRITE_RAM 1 #define EXTERNAL_RAM 0 #define ON_CHIP_PRE_GAMMA 1 #define ON_CHIP_FINAL_GAMMA 2 #define MOTOR_TABLE_SIZE 512*8 #define ValidPixelNumberFor600DPI 5100 + 50 + 250 #define ValidPixelNumberFor1200DPI 10200 + 100 + 500 #define OverLapPixelNumber600 0 #define OverLapPixelNumber1200 0 #define SegmentGap 0 #define BANK_SIZE (64) #define WaitBufferOneLineSize 11000*6 #define CCD_PIXEL_NUMBER 21600 #define CCD_Line_Spacing 24 #define CCD_EvneOdd_Spacing 2 #define ShadingTableSize(x) ( ((x + 10)*6) + ( ((x + 10)*6)/240)*16 ) #define ACC_DEC_STEP_TABLE_SIZE (512) /*unit : word */ #define TableBase(x) ((((x)+((1<>TABLE_OFFSET_BASE)< #include #include #include #endif #include "../include/sane/config.h" #include "lalloca.h" #include #include #include #include #include #if defined(HAVE_DLOPEN) && defined(HAVE_DLFCN_H) # include /* This works around a pedantic GCC compiler warning. The ISO C standard says that the behaviour of converting an object pointer like the void * returned by dlsym() to a function pointer like void *(*)() is implementation defined. POSIX though guarantees that this works fine. Workaround based on http://stackoverflow.com/a/36385690. Turns off pedantic warnings for the duration of the definition only. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpedantic" typedef void *(*func_ptr)(void); func_ptr posix_dlsym (void *handle, const char *func) { return dlsym (handle, func); } # pragma GCC diagnostic pop /* Older versions of dlopen() don't define RTLD_NOW and RTLD_LAZY. They all seem to use a mode of 1 to indicate RTLD_NOW and some do not support RTLD_LAZY at all. Hence, unless defined, we define both macros as 1 to play it safe. */ # ifndef RTLD_NOW # define RTLD_NOW 1 # endif # ifndef RTLD_LAZY # define RTLD_LAZY 1 # endif # define HAVE_DLL #endif /* HP/UX DLL support */ #if defined (HAVE_SHL_LOAD) && defined(HAVE_DL_H) # include # define HAVE_DLL #endif /* Mac OS X/Darwin support */ #if defined (HAVE_NSLINKMODULE) && defined(HAVE_MACH_O_DYLD_H) # include # define HAVE_DLL #endif #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #define BACKEND_NAME dll #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #if defined(_WIN32) || defined(HAVE_OS2_H) # define DIR_SEP ";" #else # define DIR_SEP ":" #endif #include "../include/sane/sanei_config.h" #define DLL_CONFIG_FILE "dll.conf" #define DLL_ALIASES_FILE "dll.aliases" enum SANE_Ops { OP_INIT = 0, OP_EXIT, OP_GET_DEVS, OP_OPEN, OP_CLOSE, OP_GET_OPTION_DESC, OP_CTL_OPTION, OP_GET_PARAMS, OP_START, OP_READ, OP_CANCEL, OP_SET_IO_MODE, OP_GET_SELECT_FD, NUM_OPS }; typedef SANE_Status (*op_init_t) (SANE_Int *, SANE_Auth_Callback); typedef void (*op_exit_t) (void); typedef SANE_Status (*op_get_devs_t) (const SANE_Device ***, SANE_Bool); typedef SANE_Status (*op_open_t) (SANE_String_Const, SANE_Handle *); typedef void (*op_close_t) (SANE_Handle); typedef const SANE_Option_Descriptor * (*op_get_option_desc_t) (SANE_Handle, SANE_Int); typedef SANE_Status (*op_ctl_option_t) (SANE_Handle, SANE_Int, SANE_Action, void *, SANE_Int *); typedef SANE_Status (*op_get_params_t) (SANE_Handle, SANE_Parameters *); typedef SANE_Status (*op_start_t) (SANE_Handle); typedef SANE_Status (*op_read_t) (SANE_Handle, SANE_Byte *, SANE_Int, SANE_Int *); typedef void (*op_cancel_t) (SANE_Handle); typedef SANE_Status (*op_set_io_mode_t) (SANE_Handle, SANE_Bool); typedef SANE_Status (*op_get_select_fd_t) (SANE_Handle, SANE_Int *); struct backend { struct backend *next; char *name; u_int permanent:1; /* is the backend preloaded? */ u_int loaded:1; /* are the functions available? */ u_int inited:1; /* has the backend been initialized? */ void *handle; /* handle returned by dlopen() */ void *(*op[NUM_OPS]) (void); }; #define BE_ENTRY(be,func) sane_##be##_##func #define PRELOAD_DECL(name) \ extern SANE_Status BE_ENTRY(name,init) (SANE_Int *, SANE_Auth_Callback); \ extern void BE_ENTRY(name,exit) (void); \ extern SANE_Status BE_ENTRY(name,get_devices) (const SANE_Device ***, SANE_Bool); \ extern SANE_Status BE_ENTRY(name,open) (SANE_String_Const, SANE_Handle *); \ extern void BE_ENTRY(name,close) (SANE_Handle); \ extern const SANE_Option_Descriptor *BE_ENTRY(name,get_option_descriptor) (SANE_Handle, SANE_Int); \ extern SANE_Status BE_ENTRY(name,control_option) (SANE_Handle, SANE_Int, SANE_Action, void *, SANE_Int *); \ extern SANE_Status BE_ENTRY(name,get_parameters) (SANE_Handle, SANE_Parameters *); \ extern SANE_Status BE_ENTRY(name,start) (SANE_Handle); \ extern SANE_Status BE_ENTRY(name,read) (SANE_Handle, SANE_Byte *, SANE_Int, SANE_Int *); \ extern void BE_ENTRY(name,cancel) (SANE_Handle); \ extern SANE_Status BE_ENTRY(name,set_io_mode) (SANE_Handle, SANE_Bool); \ extern SANE_Status BE_ENTRY(name,get_select_fd) (SANE_Handle, SANE_Int *); #define PRELOAD_DEFN(name) \ { \ 0 /* next */, #name, \ 1 /* permanent */, \ 1 /* loaded */, \ 0 /* inited */, \ 0 /* handle */, \ { \ BE_ENTRY(name,init), \ BE_ENTRY(name,exit), \ BE_ENTRY(name,get_devices), \ BE_ENTRY(name,open), \ BE_ENTRY(name,close), \ BE_ENTRY(name,get_option_descriptor), \ BE_ENTRY(name,control_option), \ BE_ENTRY(name,get_parameters), \ BE_ENTRY(name,start), \ BE_ENTRY(name,read), \ BE_ENTRY(name,cancel), \ BE_ENTRY(name,set_io_mode), \ BE_ENTRY(name,get_select_fd) \ } \ } #ifndef __BEOS__ #ifdef ENABLE_PRELOAD #include "dll-preload.h" #else static struct backend preloaded_backends[] = { { 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} }; #endif #endif struct meta_scanner { struct backend *be; SANE_Handle handle; }; struct alias { struct alias *next; char *oldname; char *newname; }; /* * List of available devices, allocated by sane_get_devices, released * by sane_exit() */ static SANE_Device **devlist = NULL; static int devlist_size = 0, devlist_len = 0; static struct alias *first_alias; static SANE_Auth_Callback auth_callback; static struct backend *first_backend; #ifndef __BEOS__ static const char *op_name[] = { "init", "exit", "get_devices", "open", "close", "get_option_descriptor", "control_option", "get_parameters", "start", "read", "cancel", "set_io_mode", "get_select_fd" }; #else static const char *op_name[] = { "sane_init", "sane_exit", "sane_get_devices", "sane_open", "sane_close", "sane_get_option_descriptor", "sane_control_option", "sane_get_parameters", "sane_start", "sane_read", "sane_cancel", "sane_set_io_mode", "sane_get_select_fd" }; #endif /* __BEOS__ */ static void * op_unsupported (void) { DBG (1, "op_unsupported: call to unsupported backend operation\n"); return (void *) (long) SANE_STATUS_UNSUPPORTED; } static SANE_Status add_backend (const char *name, struct backend **bep) { struct backend *be, *prev; DBG (3, "add_backend: adding backend `%s'\n", name); if (strcmp (name, "dll") == 0) { DBG (0, "add_backend: remove the dll-backend from your dll.conf!\n"); return SANE_STATUS_GOOD; } for (prev = 0, be = first_backend; be; prev = be, be = be->next) if (strcmp (be->name, name) == 0) { DBG (1, "add_backend: `%s' is already there\n", name); /* move to front so we preserve order that we'd get with dynamic loading: */ if (prev) { prev->next = be->next; be->next = first_backend; first_backend = be; } if (bep) *bep = be; return SANE_STATUS_GOOD; } be = calloc (1, sizeof (*be)); if (!be) return SANE_STATUS_NO_MEM; be->name = strdup (name); if (!be->name) return SANE_STATUS_NO_MEM; be->next = first_backend; first_backend = be; if (bep) *bep = be; return SANE_STATUS_GOOD; } #if defined(HAVE_NSLINKMODULE) static const char *dyld_get_error_str (); static const char * dyld_get_error_str () { NSLinkEditErrors c; int errorNumber; const char *fileName; const char *errorString; NSLinkEditError (&c, &errorNumber, &fileName, &errorString); return errorString; } #endif #ifdef __BEOS__ #include static SANE_Status load (struct backend *be) { /* use BeOS kernel function to load scanner addons from ~/config/add-ons/SANE */ char path[PATH_MAX]; image_id id = -1; int i, w; directory_which which[3] = { B_USER_ADDONS_DIRECTORY, B_COMMON_ADDONS_DIRECTORY, B_BEOS_ADDONS_DIRECTORY }; /* look for config files in SANE/conf */ for (w = 0; (w < 3) && (id < 0) && (find_directory(which[w],0,true,path,PATH_MAX) == 0); w++) { strcat(path,"/SANE/"); strcat(path,be->name); DBG(1, "loading backend %s\n", be->name); /* initialize all ops to "unsupported" so we can "use" the backend even if the stuff later in this function fails */ be->loaded = 1; be->handle = 0; for (i = 0; i < NUM_OPS; ++i) be->op[i] = op_unsupported; DBG(2, "dlopen()ing `%s'\n", path); id=load_add_on(path); if (id < 0) { continue; /* try next path */ } be->handle=(void *)id; for (i = 0; i < NUM_OPS; ++i) { void *(*op) (); op = NULL; /* Look for the symbol */ if ((get_image_symbol(id, op_name[i],B_SYMBOL_TYPE_TEXT,(void **)&op) < 0) || !op) DBG(2, "unable to find %s\n", op_name[i]); else be->op[i]=op; } } if (id < 0) { DBG(2, "load: couldn't find %s\n",path); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } #else static SANE_Status load (struct backend *be) { #ifdef HAVE_DLL int mode = 0; char *funcname, *src, *orig_src = 0, *dir, *path = 0; char libname[PATH_MAX]; int i; int src_len; FILE *fp = 0; #if defined(HAVE_DLOPEN) # define PREFIX "libsane-" # ifdef __hpux # define POSTFIX ".sl.%u" # define ALT_POSTFIX ".so.%u" # elif defined (HAVE_WINDOWS_H) # undef PREFIX # define PREFIX "cygsane-" # define POSTFIX "-%u.dll" # elif defined (HAVE_OS2_H) # undef PREFIX # define PREFIX "" # define POSTFIX ".dll" # elif defined (__APPLE__) && defined (__MACH__) # define POSTFIX ".%u.so" # else # define POSTFIX ".so.%u" # endif mode = getenv ("LD_BIND_NOW") ? RTLD_NOW : RTLD_LAZY; #elif defined(HAVE_SHL_LOAD) # define PREFIX "libsane-" # define POSTFIX ".sl.%u" mode = BIND_DEFERRED; #elif defined(HAVE_NSLINKMODULE) # define PREFIX "libsane-" # define POSTFIX ".%u.so" mode = NSLINKMODULE_OPTION_RETURN_ON_ERROR + NSLINKMODULE_OPTION_PRIVATE; #else # error "Tried to compile unsupported DLL." #endif /* HAVE_DLOPEN */ /* initialize all ops to "unsupported" so we can "use" the backend even if the stuff later in this function fails */ be->loaded = 1; be->handle = 0; for (i = 0; i < NUM_OPS; ++i) be->op[i] = op_unsupported; path = getenv ("LD_LIBRARY_PATH"); if (!path) path = getenv ("SHLIB_PATH"); /* for HP-UX */ if (!path) path = getenv ("LIBPATH"); /* for AIX */ if (path) { src_len = strlen (path) + strlen (DIR_SEP) + strlen(LIBDIR) + 1; src = malloc (src_len); if (!src) { DBG (1, "load: malloc failed: %s\n", strerror (errno)); return SANE_STATUS_NO_MEM; } if (orig_src) free (orig_src); orig_src = src; snprintf (src, src_len, "%s%s%s", path, DIR_SEP, LIBDIR); } else { src = LIBDIR; src = strdup (src); if (!src) { DBG (1, "load: strdup failed: %s\n", strerror (errno)); return SANE_STATUS_NO_MEM; } } DBG (3, "load: searching backend `%s' in `%s'\n", be->name, src); dir = strsep (&src, DIR_SEP); while (dir) { #ifdef HAVE_OS2_H /* only max 7.3 names work with dlopen() for DLLs on OS/2 */ snprintf (libname, sizeof (libname), "%s/" PREFIX "%.2s%.5s" POSTFIX, dir, be->name, strlen(be->name)>7 ? (be->name)+strlen(be->name)-5 : (be->name)+2, V_MAJOR); #else snprintf (libname, sizeof (libname), "%s/" PREFIX "%s" POSTFIX, dir, be->name, V_MAJOR); #endif DBG (4, "load: trying to load `%s'\n", libname); fp = fopen (libname, "r"); if (fp) break; DBG (4, "load: couldn't open `%s' (%s)\n", libname, strerror (errno)); #ifdef ALT_POSTFIX /* Some platforms have two ways of storing their libraries, try both postfixes */ snprintf (libname, sizeof (libname), "%s/" PREFIX "%s" ALT_POSTFIX, dir, be->name, V_MAJOR); DBG (4, "load: trying to load `%s'\n", libname); fp = fopen (libname, "r"); if (fp) break; DBG (4, "load: couldn't open `%s' (%s)\n", libname, strerror (errno)); #endif dir = strsep (&src, DIR_SEP); } if (orig_src) free (orig_src); if (!fp) { DBG (1, "load: couldn't find backend `%s' (%s)\n", be->name, strerror (errno)); return SANE_STATUS_INVAL; } fclose (fp); DBG (3, "load: dlopen()ing `%s'\n", libname); #ifdef HAVE_DLOPEN be->handle = dlopen (libname, mode); #elif defined(HAVE_SHL_LOAD) be->handle = (shl_t) shl_load (libname, mode, 0L); #elif defined(HAVE_NSLINKMODULE) { NSObjectFileImage objectfile_img = NULL; if (NSCreateObjectFileImageFromFile (libname, &objectfile_img) == NSObjectFileImageSuccess) { be->handle = NSLinkModule (objectfile_img, libname, mode); NSDestroyObjectFileImage (objectfile_img); } } #else # error "Tried to compile unsupported DLL." #endif /* HAVE_DLOPEN */ if (!be->handle) { #ifdef HAVE_DLOPEN DBG (1, "load: dlopen() failed (%s)\n", dlerror ()); #elif defined(HAVE_NSLINKMODULE) DBG (1, "load: dyld error (%s)\n", dyld_get_error_str ()); #else DBG (1, "load: dlopen() failed (%s)\n", strerror (errno)); #endif return SANE_STATUS_INVAL; } /* all is dandy---lookup and fill in backend ops: */ funcname = alloca (strlen (be->name) + 64); for (i = 0; i < NUM_OPS; ++i) { void *(*op) (void); sprintf (funcname, "_sane_%s_%s", be->name, op_name[i]); /* First try looking up the symbol without a leading underscore. */ #ifdef HAVE_DLOPEN op = posix_dlsym (be->handle, funcname + 1); #elif defined(HAVE_SHL_LOAD) shl_findsym ((shl_t *) & (be->handle), funcname + 1, TYPE_UNDEFINED, &op); #elif defined(HAVE_NSLINKMODULE) { NSSymbol *nssym = NSLookupSymbolInModule (be->handle, funcname); if (!nssym) { DBG (15, "dyld error: %s\n", dyld_get_error_str ()); } else { op = (void *(*)(void)) NSAddressOfSymbol (nssym); } } #else # error "Tried to compile unsupported DLL." #endif /* HAVE_DLOPEN */ if (op) be->op[i] = op; else { /* Try again, with an underscore prepended. */ #ifdef HAVE_DLOPEN op = posix_dlsym (be->handle, funcname); #elif defined(HAVE_SHL_LOAD) shl_findsym (be->handle, funcname, TYPE_UNDEFINED, &op); #elif defined(HAVE_NSLINKMODULE) { NSSymbol *nssym = NSLookupSymbolInModule (be->handle, funcname); if (!nssym) { DBG (15, "dyld error: %s\n", dyld_get_error_str ()); } else { op = (void *(*)(void)) NSAddressOfSymbol (nssym); } } #else # error "Tried to compile unsupported DLL." #endif /* HAVE_DLOPEN */ if (op) be->op[i] = op; } if (NULL == op) DBG (1, "load: unable to find %s\n", funcname); } return SANE_STATUS_GOOD; # undef PREFIX # undef POSTFIX #else /* HAVE_DLL */ DBG (1, "load: ignoring attempt to load `%s'; compiled without dl support\n", be->name); return SANE_STATUS_UNSUPPORTED; #endif /* HAVE_DLL */ } #endif /* __BEOS__ */ static SANE_Status init (struct backend *be) { SANE_Status status; SANE_Int version; if (!be->loaded) { status = load (be); if (status != SANE_STATUS_GOOD) return status; } DBG (3, "init: initializing backend `%s'\n", be->name); status = (*(op_init_t)be->op[OP_INIT]) (&version, auth_callback); if (status != SANE_STATUS_GOOD) return status; if (SANE_VERSION_MAJOR (version) != SANE_CURRENT_MAJOR) { DBG (1, "init: backend `%s' has a wrong major version (%d instead of %d)\n", be->name, SANE_VERSION_MAJOR (version), SANE_CURRENT_MAJOR); return SANE_STATUS_INVAL; } DBG (4, "init: backend `%s' is version %d.%d.%d\n", be->name, SANE_VERSION_MAJOR (version), SANE_VERSION_MINOR (version), SANE_VERSION_BUILD (version)); be->inited = 1; return SANE_STATUS_GOOD; } static void add_alias (const char *line_param) { #ifndef __BEOS__ const char *command; enum { CMD_ALIAS, CMD_HIDE } cmd; const char *oldname, *oldend, *newname; size_t oldlen, newlen; struct alias *alias; char *line; command = sanei_config_skip_whitespace (line_param); if (!*command) return; line = strchr (command, '#'); if (line) *line = '\0'; line = strpbrk (command, " \t"); if (!line) return; *line++ = '\0'; if (strcmp (command, "alias") == 0) cmd = CMD_ALIAS; else if (strcmp (command, "hide") == 0) cmd = CMD_HIDE; else return; newlen = 0; newname = NULL; if (cmd == CMD_ALIAS) { char *newend; newname = sanei_config_skip_whitespace (line); if (!*newname) return; if (*newname == '\"') { ++newname; newend = strchr (newname, '\"'); } else newend = strpbrk (newname, " \t"); if (!newend) return; newlen = newend - newname; line = (char *) (newend + 1); } oldname = sanei_config_skip_whitespace (line); if (!*oldname) return; oldend = oldname + strcspn (oldname, " \t"); oldlen = oldend - oldname; alias = malloc (sizeof (struct alias)); if (alias) { alias->oldname = malloc (oldlen + newlen + 2); if (alias->oldname) { strncpy (alias->oldname, oldname, oldlen); alias->oldname[oldlen] = '\0'; if (cmd == CMD_ALIAS) { alias->newname = alias->oldname + oldlen + 1; strncpy (alias->newname, newname, newlen); alias->newname[newlen] = '\0'; } else alias->newname = NULL; alias->next = first_alias; first_alias = alias; return; } free (alias); } return; #endif } static void read_config (const char *conffile) { FILE *fp; char config_line[PATH_MAX]; char *backend_name; fp = sanei_config_open (conffile); if (!fp) { DBG (1, "sane_init/read_config: Couldn't open config file (%s): %s\n", conffile, strerror (errno)); return; /* don't insist on config file */ } DBG (5, "sane_init/read_config: reading %s\n", conffile); while (sanei_config_read (config_line, sizeof (config_line), fp)) { char *comment; SANE_String_Const cp; cp = sanei_config_get_string (config_line, &backend_name); /* ignore empty lines */ if (!backend_name || cp == config_line) { if (backend_name) free (backend_name); continue; } /* ignore line comments */ if (backend_name[0] == '#') { free (backend_name); continue; } /* ignore comments after backend names */ comment = strchr (backend_name, '#'); if (comment) *comment = '\0'; add_backend (backend_name, 0); free (backend_name); } fclose (fp); } static void read_dlld (void) { DIR *dlld; struct dirent *dllconf; struct stat st; char conffile[PATH_MAX], dlldir[PATH_MAX]; size_t len, plen; const char *dir_list; char *copy, *next, *dir; dir_list = sanei_config_get_paths (); if (!dir_list) { DBG(2, "sane_init/read_dlld: Unable to detect configuration directories\n"); return; } copy = strdup (dir_list); for (next = copy; (dir = strsep (&next, DIR_SEP)) != NULL;) { snprintf (dlldir, sizeof (dlldir), "%s%s", dir, "/dll.d"); DBG(4, "sane_init/read_dlld: attempting to open directory `%s'\n", dlldir); dlld = opendir (dlldir); if (dlld) { /* length of path to parent dir of dll.d/ */ plen = strlen (dir) + 1; DBG(3, "sane_init/read_dlld: using config directory `%s'\n", dlldir); break; } } free (copy); if (dlld == NULL) { DBG (1, "sane_init/read_dlld: opendir failed: %s\n", strerror (errno)); return; } while ((dllconf = readdir (dlld)) != NULL) { /* dotfile (or directory) */ if (dllconf->d_name[0] == '.') continue; len = strlen (dllconf->d_name); /* backup files */ if ((dllconf->d_name[len-1] == '~') || (dllconf->d_name[len-1] == '#')) continue; snprintf (conffile, PATH_MAX, "%s/%s", dlldir, dllconf->d_name); DBG (5, "sane_init/read_dlld: considering %s\n", conffile); if (stat (conffile, &st) != 0) continue; if (!S_ISREG (st.st_mode)) continue; /* expects a path relative to PATH_SANE_CONFIG_DIR */ read_config (conffile+plen); } closedir (dlld); DBG (5, "sane_init/read_dlld: done.\n"); } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { #ifndef __BEOS__ char config_line[PATH_MAX]; size_t len; FILE *fp; int i; #else DIR *dir; struct dirent *dirent; char path[1024]; directory_which which[3] = { B_USER_ADDONS_DIRECTORY, B_COMMON_ADDONS_DIRECTORY, B_BEOS_ADDONS_DIRECTORY }; int i; #endif DBG_INIT (); auth_callback = authorize; DBG (1, "sane_init: SANE dll backend version %s from %s\n", DLL_VERSION, PACKAGE_STRING); #ifndef __BEOS__ /* chain preloaded backends together: */ for (i = 0; i < NELEMS (preloaded_backends); ++i) { if (!preloaded_backends[i].name) continue; DBG (3, "sane_init: adding backend `%s' (preloaded)\n", preloaded_backends[i].name); preloaded_backends[i].next = first_backend; first_backend = &preloaded_backends[i]; } /* Return the version number of the sane-backends package to allow the frontend to print them. This is done only for net and dll, because these backends are usually called by the frontend. */ if (version_code) *version_code = SANE_VERSION_CODE (SANE_DLL_V_MAJOR, SANE_DLL_V_MINOR, SANE_DLL_V_BUILD); /* * Read dll.conf & dll.d * Read dll.d first, so that the extras backends will be tried last */ read_dlld (); read_config (DLL_CONFIG_FILE); fp = sanei_config_open (DLL_ALIASES_FILE); if (!fp) return SANE_STATUS_GOOD; /* don't insist on aliases file */ DBG (5, "sane_init: reading %s\n", DLL_ALIASES_FILE); while (sanei_config_read (config_line, sizeof (config_line), fp)) { if (config_line[0] == '#') /* ignore line comments */ continue; len = strlen (config_line); if (!len) continue; /* ignore empty lines */ add_alias (config_line); } fclose (fp); #else /* no ugly config files, just get scanners from their ~/config/add-ons/SANE */ /* look for drivers */ for (i = 0; i < 3; i++) { if (find_directory(which[i],0,true,path,1024) < B_OK) continue; strcat(path,"/SANE/"); dir=opendir(path); if(!dir) continue; while((dirent=readdir(dir))) { if((strcmp(dirent->d_name,".")==0) || (strcmp(dirent->d_name,"..")==0)) continue; if((strcmp(dirent->d_name,"dll")==0)) continue; add_backend(dirent->d_name,0); } closedir(dir); } #endif /* __BEOS__ */ return SANE_STATUS_GOOD; } void sane_exit (void) { struct backend *be, *next; struct alias *alias; DBG (2, "sane_exit: exiting\n"); for (be = first_backend; be; be = next) { next = be->next; if (be->loaded) { if (be->inited) { DBG (3, "sane_exit: calling backend `%s's exit function\n", be->name); (*(op_exit_t)be->op[OP_EXIT]) (); } #ifdef __BEOS__ /* use BeOS kernel functions to unload add-ons */ if(be->handle) unload_add_on((image_id)be->handle); #else #ifdef HAVE_DLL #ifdef HAVE_DLOPEN if (be->handle) dlclose (be->handle); #elif defined(HAVE_SHL_LOAD) if (be->handle) shl_unload (be->handle); #elif defined(HAVE_NSLINKMODULE) if (be->handle) NSUnLinkModule (be->handle, NSUNLINKMODULE_OPTION_NONE # ifdef __ppc__ | NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES # endif ); #else # error "Tried to compile unsupported DLL." #endif /* HAVE_DLOPEN */ #endif /* HAVE_DLL */ #endif /* __BEOS__ */ } if (!be->permanent) { if (be->name) free ((void *) be->name); free (be); } else { be->inited = 0; } } first_backend = 0; while ((alias = first_alias) != NULL) { first_alias = first_alias->next; free (alias->oldname); free (alias); } if (NULL != devlist) { /* Release memory allocated by sane_get_devices(). */ int i = 0; while (devlist[i]) free (devlist[i++]); free (devlist); devlist = NULL; devlist_size = 0; devlist_len = 0; } DBG (3, "sane_exit: finished\n"); } /* Note that a call to get_devices() implies that we'll have to load all backends. To avoid this, you can call sane_open() directly (assuming you know the name of the backend/device). This is appropriate for the command-line interface of SANE, for example. */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { const SANE_Device **be_list; struct backend *be; SANE_Status status; char *full_name; int i, num_devs; size_t len; #define ASSERT_SPACE(n) \ { \ if (devlist_len + (n) > devlist_size) \ { \ devlist_size += (n) + 15; \ if (devlist) \ devlist = realloc (devlist, devlist_size * sizeof (devlist[0])); \ else \ devlist = malloc (devlist_size * sizeof (devlist[0])); \ if (!devlist) \ return SANE_STATUS_NO_MEM; \ } \ } DBG (3, "sane_get_devices\n"); if (devlist) for (i = 0; i < devlist_len; ++i) free ((void *) devlist[i]); devlist_len = 0; for (be = first_backend; be; be = be->next) { if (!be->inited) if (init (be) != SANE_STATUS_GOOD) continue; status = (*(op_get_devs_t)be->op[OP_GET_DEVS]) (&be_list, local_only); if (status != SANE_STATUS_GOOD || !be_list) continue; /* count the number of devices for this backend: */ for (num_devs = 0; be_list[num_devs]; ++num_devs); ASSERT_SPACE (num_devs); for (i = 0; i < num_devs; ++i) { SANE_Device *dev; char *mem; struct alias *alias; for (alias = first_alias; alias != NULL; alias = alias->next) { len = strlen (be->name); if (strlen (alias->oldname) <= len) continue; if (strncmp (alias->oldname, be->name, len) == 0 && alias->oldname[len] == ':' && strcmp (&alias->oldname[len + 1], be_list[i]->name) == 0) break; } if (alias) { if (!alias->newname) /* hidden device */ continue; len = strlen (alias->newname); mem = malloc (sizeof (*dev) + len + 1); if (!mem) return SANE_STATUS_NO_MEM; full_name = mem + sizeof (*dev); strcpy (full_name, alias->newname); } else { /* create a new device entry with a device name that is the sum of the backend name a colon and the backend's device name: */ len = strlen (be->name) + 1 + strlen (be_list[i]->name); mem = malloc (sizeof (*dev) + len + 1); if (!mem) return SANE_STATUS_NO_MEM; full_name = mem + sizeof (*dev); strcpy (full_name, be->name); strcat (full_name, ":"); strcat (full_name, be_list[i]->name); } dev = (SANE_Device *) mem; dev->name = full_name; dev->vendor = be_list[i]->vendor; dev->model = be_list[i]->model; dev->type = be_list[i]->type; devlist[devlist_len++] = dev; } } /* terminate device list with NULL entry: */ ASSERT_SPACE (1); devlist[devlist_len++] = 0; *device_list = (const SANE_Device **) devlist; DBG (3, "sane_get_devices: found %d devices\n", devlist_len - 1); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle) { const char *be_name, *dev_name; struct meta_scanner *s; SANE_Handle handle; struct backend *be; SANE_Status status; struct alias *alias; DBG (3, "sane_open: trying to open `%s'\n", full_name); for (alias = first_alias; alias != NULL; alias = alias->next) { if (!alias->newname) continue; if (strcmp (alias->newname, full_name) == 0) { full_name = alias->oldname; break; } } dev_name = strchr (full_name, ':'); if (dev_name) { #ifdef strndupa be_name = strndupa (full_name, dev_name - full_name); #else char *tmp; tmp = alloca (dev_name - full_name + 1); memcpy (tmp, full_name, dev_name - full_name); tmp[dev_name - full_name] = '\0'; be_name = tmp; #endif ++dev_name; /* skip colon */ } else { /* if no colon interpret full_name as the backend name; an empty backend device name will cause us to open the first device of that backend. */ be_name = full_name; dev_name = ""; } if (!be_name[0]) be = first_backend; else for (be = first_backend; be; be = be->next) if (strcmp (be->name, be_name) == 0) break; if (!be) { status = add_backend (be_name, &be); if (status != SANE_STATUS_GOOD) return status; } if (!be->inited) { status = init (be); if (status != SANE_STATUS_GOOD) return status; } status = (*(op_open_t)be->op[OP_OPEN]) (dev_name, &handle); if (status != SANE_STATUS_GOOD) return status; s = calloc (1, sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; s->be = be; s->handle = handle; *meta_handle = s; DBG (3, "sane_open: open successful\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { struct meta_scanner *s = handle; DBG (3, "sane_close(handle=%p)\n", handle); (*(op_close_t)s->be->op[OP_CLOSE]) (s->handle); free (s); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct meta_scanner *s = handle; DBG (3, "sane_get_option_descriptor(handle=%p,option=%d)\n", handle, option); return (*(op_get_option_desc_t)s->be->op[OP_GET_OPTION_DESC]) (s->handle, option); } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Word * info) { struct meta_scanner *s = handle; DBG (3, "sane_control_option(handle=%p,option=%d,action=%d,value=%p,info=%p)\n", handle, option, action, value, (void *) info); return (*(op_ctl_option_t)s->be->op[OP_CTL_OPTION]) (s->handle, option, action, value, info); } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { struct meta_scanner *s = handle; DBG (3, "sane_get_parameters(handle=%p,params=%p)\n", handle, (void *) params); return (*(op_get_params_t)s->be->op[OP_GET_PARAMS]) (s->handle, params); } SANE_Status sane_start (SANE_Handle handle) { struct meta_scanner *s = handle; DBG (3, "sane_start(handle=%p)\n", handle); return (*(op_start_t)s->be->op[OP_START]) (s->handle); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { struct meta_scanner *s = handle; DBG (3, "sane_read(handle=%p,data=%p,maxlen=%d,lenp=%p)\n", handle, data, max_length, (void *) length); return (*(op_read_t)s->be->op[OP_READ]) (s->handle, data, max_length, length); } void sane_cancel (SANE_Handle handle) { struct meta_scanner *s = handle; DBG (3, "sane_cancel(handle=%p)\n", handle); (*(op_cancel_t)s->be->op[OP_CANCEL]) (s->handle); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { struct meta_scanner *s = handle; DBG (3, "sane_set_io_mode(handle=%p,nonblocking=%d)\n", handle, non_blocking); return (*(op_set_io_mode_t)s->be->op[OP_SET_IO_MODE]) (s->handle, non_blocking); } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { struct meta_scanner *s = handle; DBG (3, "sane_get_select_fd(handle=%p,fdp=%p)\n", handle, (void *) fd); return (*(op_get_select_fd_t)s->be->op[OP_GET_SELECT_FD]) (s->handle, fd); } sane-backends-1.0.27/backend/canon.conf.in0000664000175000017500000000003212112021330015137 00000000000000#canon.conf scsi CANON IX sane-backends-1.0.27/backend/pieusb_usb.c0000664000175000017500000005323512775312261015133 00000000000000/* sane - Scanner Access Now Easy. pieusb_usb.c Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #define DEBUG_DECLARE_ONLY #include "pieusb.h" #include "pieusb_scancmd.h" #include "pieusb_usb.h" #include "../include/sane/sanei_usb.h" #include /* usleep */ #include /* time */ /* USB functions */ static SANE_Status _ctrl_out_byte(SANE_Int device_number, SANE_Int port, SANE_Byte b); static SANE_Status _bulk_size(SANE_Int device_number, unsigned int size); static SANE_Status _ctrl_in_byte(SANE_Int device_number, SANE_Byte* b); static SANE_Status _bulk_in(SANE_Int device_number, SANE_Byte* data, size_t *size); static SANE_Status _ieee_command(SANE_Int device_number, SANE_Byte command); /* Defines for use in USB functions */ #define REQUEST_TYPE_IN (USB_TYPE_VENDOR | USB_DIR_IN) #define REQUEST_TYPE_OUT (USB_TYPE_VENDOR | USB_DIR_OUT) #define REQUEST_REGISTER 0x0c #define REQUEST_BUFFER 0x04 #define ANYINDEX 0x00 /* wIndex value for USB control transfer - value is irrelevant */ /* from libieee1284 */ #define C1284_NSTROBE 0x01 #define C1284_NINIT 0x04 /* usb via ieee1284 */ #define IEEE1284_ADDR 0x00 #define IEEE1284_RESET 0x30 #define IEEE1284_SCSI 0xe0 #define PORT_SCSI_SIZE 0x0082 #define PORT_SCSI_STATUS 0x0084 #define PORT_SCSI_CMD 0x0085 #define PORT_PAR_CTRL 0x0087 /* IEEE1284 parallel control */ #define PORT_PAR_DATA 0x0088 /* IEEE1284 parallel data */ /* see also: SCSI Status Codes http://www.t10.org/lists/2status.htm */ typedef enum { USB_STATUS_OK = 0x00, /* ok */ USB_STATUS_READ = 0x01, /* read: send expected length, then read data */ USB_STATUS_CHECK = 0x02, /* check condition */ USB_STATUS_BUSY = 0x03, /* wait on usb */ USB_STATUS_AGAIN = 0x08, /* re-send scsi cmd */ USB_STATUS_FAIL = 0x88, /* ??? */ USB_STATUS_ERROR = 0xff /* usb i/o error */ } PIEUSB_USB_Status; static PIEUSB_USB_Status _pieusb_scsi_command(SANE_Int device_number, SANE_Byte command[], SANE_Byte data[], SANE_Int size); #define SENSE_CODE_WARMING_UP 4 /* Standard SCSI Sense codes*/ #define SCSI_NO_ADDITIONAL_SENSE_INFORMATION 0x00 struct code_text_t { int code; char *text; }; static struct code_text_t usb_code_text[] = { { 0x00, "Ok" }, { 0x01, "Read" }, { 0x02, "Check" }, { 0x03, "Busy" }, { 0x08, "Again" }, { 0xff, "Error" }, { -1, NULL } }; static struct code_text_t scsi_code_text[] = { { 0x00, "Test Unit Ready" } ,{ 0x01, "Calibrate" } ,{ 0x03, "Request Sense" } ,{ 0x04, "Format" } ,{ 0x08, "Read" } ,{ 0x0a, "Write" } ,{ 0x0f, "Get Param" } ,{ 0x10, "Mark" } ,{ 0x11, "Space" } ,{ 0x12, "Inquiry" } ,{ 0x15, "Mode Select" } ,{ 0x16, "Reserve Unit" } ,{ 0x18, "Copy" } ,{ 0x1a, "Mode Sense" } ,{ 0x1b, "Scan" } ,{ 0x1d, "Diagnose" } ,{ 0xa8, "Read Extended" } ,{ 0xd1, "Slide" } ,{ 0xd2, "Set Scan Head" } ,{ 0xd7, "Read Gain Offset" } ,{ 0xdc, "Write Gain Offset" } ,{ 0xdd, "Read State" } ,{ -1, NULL } }; static char * code_to_text(struct code_text_t *list, int code) { while (list && list->text) { if (list->code == code) return list->text; list++; } return "**unknown**"; } /** * Convert PIEUSB_Status to SANE_Status */ SANE_Status sanei_pieusb_convert_status(PIEUSB_Status status) { return (SANE_Status)status; } /** * hex dump 'size' bytes starting at 'ptr' */ static void _hexdump(char *msg, unsigned char *ptr, int size) { unsigned char *lptr = ptr; int count = 0; long start = 0; long clipped = 0; if (DBG_info_proc > DBG_LEVEL) return; if (size > 127) { clipped = size; size = 128; } while (size-- > 0) { if ((count % 16) == 0) fprintf (stderr, "%s\t%08lx:", msg?msg:"", start); msg = NULL; fprintf (stderr, " %02x", *ptr++); count++; start++; if (size == 0) { while ((count % 16) != 0) { fprintf (stderr, " "); count++; } } if ((count % 16) == 0) { fprintf (stderr, " "); while (lptr < ptr) { unsigned char c = *lptr & 0x7f; fprintf (stderr, "%c", ((c < 0x20)||(c == 0x7f)) ? '.' : c); lptr++; } fprintf (stderr, "\n"); } } if ((count % 16) != 0) fprintf (stderr, "\n"); if (clipped > 0) fprintf (stderr, "\t%08lx bytes clipped\n", clipped); fflush(stderr); return; } /* ========================================================================= * * USB functions * * ========================================================================= */ /** * Send a command to the device, retry 10 times if device is busy * and return SENSE data in the sense fields of status if there is a CHECK * CONDITION response from the command. * If the REQUEST SENSE command fails, the SANE status code is unequal to * PIEUSB_STATUS_GOOD and the sense fields are empty. * * @param device_number Device number * @param command Command array * @param data Input or output data buffer * @param size Size of the data buffer * @param status Pieusb_Command_Status */ PIEUSB_Status sanei_pieusb_command(SANE_Int device_number, SANE_Byte command[], SANE_Byte data[], SANE_Int size) { #define MAXTIME 60 /* max 60 seconds */ time_t start; SANE_Status sane_status; PIEUSB_Status ret = PIEUSB_STATUS_DEVICE_BUSY; SANE_Byte usbstat; PIEUSB_USB_Status usb_status = USB_STATUS_AGAIN; DBG (DBG_info_usb, "*** sanei_pieusb_command(%02x:%s): size 0x%02x\n", command[0], code_to_text (scsi_code_text, command[0]), size); start = time(NULL); while ((time(NULL)-start) < MAXTIME) { DBG (DBG_info_usb, "\tsanei_pieusb_command loop, status %d:%s\n", usb_status, code_to_text (usb_code_text, usb_status)); if (usb_status == USB_STATUS_AGAIN) { usb_status = _pieusb_scsi_command (device_number, command, data, size); DBG (DBG_info_usb, "\t_pieusb_scsi_command returned %d:%s\n", usb_status, code_to_text (usb_code_text, usb_status)); continue; } if (usb_status == USB_STATUS_OK) { ret = PIEUSB_STATUS_GOOD; break; } if (usb_status == USB_STATUS_READ) { DBG (DBG_error, "\tsanei_pieusb_command() 2nd STATUS_READ ?!\n"); ret = PIEUSB_STATUS_IO_ERROR; break; } if (usb_status == USB_STATUS_CHECK) { /* check condition */ struct Pieusb_Sense sense; struct Pieusb_Command_Status senseStatus; #define SCSI_REQUEST_SENSE 0x03 if (command[0] == SCSI_REQUEST_SENSE) { DBG (DBG_error, "\tsanei_pieusb_command() recursive SCSI_REQUEST_SENSE\n"); ret = PIEUSB_STATUS_INVAL; break; } /* A check sense may be a busy state in disguise * It is also practical to execute a request sense command by * default. The calling function should interpret * PIEUSB_STATUS_CHECK_SENSE as 'sense data available'. */ sanei_pieusb_cmd_get_sense (device_number, &sense, &senseStatus, &ret); if (senseStatus.pieusb_status != PIEUSB_STATUS_GOOD) { DBG (DBG_error, "\tsanei_pieusb_command(): CHECK CONDITION, but REQUEST SENSE fails\n"); ret = senseStatus.pieusb_status; } break; } if (usb_status == USB_STATUS_BUSY) { /* wait on usb */ sane_status = _ctrl_in_byte (device_number, &usbstat); if (sane_status != SANE_STATUS_GOOD) { DBG (DBG_error, "\tpieusb_scsi_command() fails status in: %d\n", sane_status); ret = PIEUSB_STATUS_IO_ERROR; break; } usb_status = usbstat; if (usb_status == USB_STATUS_AGAIN) { sleep(1); } continue; } if (usb_status == USB_STATUS_AGAIN) { /* re-send scsi cmd */ continue; } if (usb_status == USB_STATUS_FAIL) { DBG (DBG_error, "\tsanei_pieusb_command() usb status again2\n"); usb_status = USB_STATUS_ERROR; sanei_pieusb_usb_reset(device_number); ret = PIEUSB_STATUS_IO_ERROR; break; } if (usb_status == USB_STATUS_ERROR) { sanei_pieusb_usb_reset(device_number); ret = PIEUSB_STATUS_IO_ERROR; break; } DBG (DBG_error, "\tsanei_pieusb_command() unhandled usb status 0x%02x\n", usb_status); ret = PIEUSB_STATUS_IO_ERROR; break; } if ((time(NULL)-start) > MAXTIME) { DBG (DBG_info_usb, "\tsanei_pieusb_command() timeout !\n"); } DBG (DBG_info_usb, "\tsanei_pieusb_command() finished with state %d\n", ret); return ret; } /** * Reset IEEE1284 interface * * @param device_number Device number * @returns SANE_Status */ SANE_Status sanei_pieusb_usb_reset(SANE_Int device_number) { DBG (DBG_info_sane, "\tsanei_pieusb_usb_reset()\n"); return _ieee_command (device_number, IEEE1284_RESET); } /* http://www.t10.org/lists/2sensekey.htm */ static struct code_text_t sense_code_text[] = { { SCSI_SENSE_NO_SENSE, "No Sense" }, { SCSI_SENSE_RECOVERED_ERROR, "Recovered Error" }, { SCSI_SENSE_NOT_READY, "Not Ready" }, { SCSI_SENSE_MEDIUM_ERROR, "Medium Error" }, { SCSI_SENSE_HARDWARE_ERROR, "Hardware Error" }, { SCSI_SENSE_ILLEGAL_REQUEST, "Illegal Request" }, { SCSI_SENSE_UNIT_ATTENTION, "Unit Attention" }, { SCSI_SENSE_DATA_PROTECT, "Data Protect" }, { SCSI_SENSE_BLANK_CHECK, "Blank Check" }, { SCSI_SENSE_VENDOR_SPECIFIC, "Vendor Specific" }, { SCSI_SENSE_COPY_ABORTED, "Copy Aborted" }, { SCSI_SENSE_ABORTED_COMMAND, "Aborted Command" }, { SCSI_SENSE_EQUAL, "Equal" }, { SCSI_SENSE_VOLUME_OVERFLOW, "Volume Overflow" }, { SCSI_SENSE_MISCOMPARE, "Miscompare" }, { SCSI_SENSE_COMPLETED, "Completed" }, { -1, NULL } }; /** * Return a textual description of the given sense code. * * See http://www.t10.org/lists/asc-num.txt * * @param sense * @return description */ SANE_String sanei_pieusb_decode_sense(struct Pieusb_Sense* sense, PIEUSB_Status *status) { SANE_Char* desc = malloc(200); SANE_Char* ptr; strcpy (desc, code_to_text (sense_code_text, sense->senseKey)); ptr = desc + strlen(desc); switch (sense->senseKey) { case SCSI_SENSE_NOT_READY: if (sense->senseCode == SENSE_CODE_WARMING_UP && sense->senseQualifier == 1) { strcpy (ptr, ": Logical unit is in the process of becoming ready"); *status = PIEUSB_STATUS_WARMING_UP; } else { sprintf (ptr, ": senseCode 0x%02x, senseQualifier 0x%02x", sense->senseCode, sense->senseQualifier); *status = PIEUSB_STATUS_INVAL; } break; case SCSI_SENSE_UNIT_ATTENTION: if (sense->senseCode == 0x1a && sense->senseQualifier == 0) { strcpy (ptr, ": Invalid field in parameter list"); *status = PIEUSB_STATUS_INVAL; break; } else if (sense->senseCode == 0x20 && sense->senseQualifier == 0) { strcpy (ptr, ": Invalid command operation code"); *status = PIEUSB_STATUS_INVAL; break; } else if (sense->senseCode == 0x82 && sense->senseQualifier == 0) { strcpy (ptr, ": Calibration disable not granted"); *status = PIEUSB_STATUS_MUST_CALIBRATE; break; } else if (sense->senseCode == 0x00 && sense->senseQualifier == 6) { strcpy (ptr, ": I/O process terminated"); *status = PIEUSB_STATUS_IO_ERROR; break; } else if (sense->senseCode == 0x26 && sense->senseQualifier == 0x82) { strcpy (ptr, ": MODE SELECT value invalid: resolution too high (vs)"); *status = PIEUSB_STATUS_INVAL; break; } else if (sense->senseCode == 0x26 && sense->senseQualifier == 0x83) { strcpy (ptr, ": MODE SELECT value invalid: select only one color (vs)"); *status = PIEUSB_STATUS_INVAL; break; } else if (sense->senseCode == 0x26 && sense->senseQualifier == 0x83) { strcpy (ptr, ": MODE SELECT value invalid: unsupported bit depth (vs)"); *status = PIEUSB_STATUS_INVAL; break; } /*fallthru*/ case SCSI_SENSE_NO_SENSE: case SCSI_SENSE_RECOVERED_ERROR: case SCSI_SENSE_MEDIUM_ERROR: case SCSI_SENSE_HARDWARE_ERROR: case SCSI_SENSE_ILLEGAL_REQUEST: case SCSI_SENSE_DATA_PROTECT: case SCSI_SENSE_BLANK_CHECK: case SCSI_SENSE_VENDOR_SPECIFIC: case SCSI_SENSE_COPY_ABORTED: case SCSI_SENSE_ABORTED_COMMAND: case SCSI_SENSE_EQUAL: case SCSI_SENSE_VOLUME_OVERFLOW: case SCSI_SENSE_MISCOMPARE: case SCSI_SENSE_COMPLETED: default: sprintf (ptr, ": senseCode 0x%02x, senseQualifier 0x%02x", sense->senseCode, sense->senseQualifier); *status = PIEUSB_STATUS_INVAL; } return desc; } /** * Prepare IEEE1284 interface * Issue one of IEEE1284_ADDR, IEEE1284_RESET, or IEEE1284_SCSI * * @param device_number Device number * @param command - IEEE1284 command * @returns SANE_Status */ static SANE_Status _ieee_command(SANE_Int device_number, SANE_Byte command) { SANE_Status st; static int sequence[] = { 0xff, 0xaa, 0x55, 0x00, 0xff, 0x87, 0x78 }; #define SEQUENCE_LEN 7 unsigned int i; /* 2 x 4 + 3 bytes preceding command, then SCSI_COMMAND_LEN bytes command */ /* IEEE1284 command, see hpsj5s.c:cpp_daisy() */ for (i = 0; i < SEQUENCE_LEN; ++i) { st = _ctrl_out_byte (device_number, PORT_PAR_DATA, sequence[i]); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_ieee_command fails after %d bytes\n", i); return st; } } st = _ctrl_out_byte (device_number, PORT_PAR_DATA, command); if (st == SANE_STATUS_GOOD) { usleep(3000); /* 3.000 usec -> 3 msec */ st = _ctrl_out_byte (device_number, PORT_PAR_CTRL, C1284_NINIT|C1284_NSTROBE); /* CTRL_VAL_FINAL */ if (st == SANE_STATUS_GOOD) { st = _ctrl_out_byte (device_number, PORT_PAR_CTRL, C1284_NINIT); if (st == SANE_STATUS_GOOD) { st = _ctrl_out_byte (device_number, PORT_PAR_DATA, 0xff); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_ieee_command fails to write final data\n"); } } else { DBG (DBG_error, "\t\t_ieee_command fails to reset strobe\n"); } } else { DBG (DBG_error, "\t\t_ieee_command fails to set strobe\n"); } } return st; #undef SEQUENCE_LEN } /** * Send a command to the device. * The command is a SCSI_COMMAND_LEN-byte array. The data-array is used for input and output. * The sense-fields of Pieusb_Command_Status are cleared. * * @param device_number Device number * @param command Command array * @param data Input or output data buffer * @param size Size of the data buffer * @returns PIEUSB_SCSI_Status */ static PIEUSB_USB_Status _pieusb_scsi_command(SANE_Int device_number, SANE_Byte command[], SANE_Byte data[], SANE_Int size) { SANE_Status st; SANE_Byte usbstat; int i; DBG (DBG_info_usb, "\t\t_pieusb_scsi_command(): %02x:%s\n", command[0], code_to_text (scsi_code_text, command[0])); st = _ieee_command (device_number, IEEE1284_SCSI); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_pieusb_scsi_command can't prep scsi cmd: %d\n", st); return USB_STATUS_ERROR; } /* output command */ for (i = 0; i < SCSI_COMMAND_LEN; ++i) { SANE_Status st; st = _ctrl_out_byte (device_number, PORT_SCSI_CMD, command[i]); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_pieusb_scsi_command fails command out, after %d bytes: %d\n", i, st); return USB_STATUS_ERROR; } } _hexdump ("Cmd", command, SCSI_COMMAND_LEN); /* Verify this sequence */ st = _ctrl_in_byte (device_number, &usbstat); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_pieusb_scsi_command fails status after command out: %d\n", st); return USB_STATUS_ERROR; } /* Process rest of the data, if present; either input or output, possibly bulk */ DBG (DBG_info_usb, "\t\t_pieusb_scsi_command usbstat 0x%02x\n", usbstat); if (usbstat == USB_STATUS_OK && size > 0) { /* * send additional data to usb */ _hexdump ("Out", data, size); for (i = 0; i < size; ++i) { st = _ctrl_out_byte (device_number, PORT_SCSI_CMD, data[i]); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_pieusb_scsi_command fails data out after %d bytes: %d\n", i, st); return USB_STATUS_ERROR; } } /* Verify data out */ st = _ctrl_in_byte (device_number, &usbstat); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_pieusb_scsi_command fails status after data out: %d\n", st); return USB_STATUS_ERROR; } } else if (usbstat == USB_STATUS_READ) { /* Intermediate status OK, device has made data available for reading */ /* Read data */ size_t remsize; size_t partsize; remsize = (size_t)size; DBG (DBG_info_usb, "\t\t_pieusb_scsi_command data in\n"); while (remsize > 0) { partsize = remsize > 0x1000000 ? 0x1000000 : remsize; /* 0xc000 must be multiples of 0x4000, see _bulk_in() */ /* send expected length */ st = _bulk_size (device_number, partsize); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_pieusb_scsi_command prepare read data failed for size %u: %d\n", (unsigned int)partsize, st); return USB_STATUS_ERROR; } /* read expected length bytes */ st = _bulk_in (device_number, data + size - remsize, &partsize); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_pieusb_scsi_command read data failed for size %u: %d\n", (unsigned int)partsize, st); return USB_STATUS_ERROR; } remsize -= partsize; /* DBG (DBG_info, "\t\t_pieusb_scsi_command partsize %08x, remsize %08x\n", (unsigned int)partsize, (unsigned int)remsize); */ } /* Verify data in */ st = _ctrl_in_byte (device_number, &usbstat); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "\t\t_pieusb_scsi_command fails status after data in: %d\n", st); return USB_STATUS_ERROR; } _hexdump ("In", data, size); } return usbstat; } /** * Simplified control transfer: one byte to given port * * @param device_number device number * @param b byte to send to device * @return SANE status */ static SANE_Status _ctrl_out_byte(SANE_Int device_number, SANE_Int port, SANE_Byte b) { /* int r = libusb_control_transfer(scannerHandle, CTRL_OUT, 0x0C, 0x0088, ANYINDEX, &b, 1, TIMEOUT); */ return sanei_usb_control_msg(device_number, REQUEST_TYPE_OUT, REQUEST_REGISTER, port, ANYINDEX, 1, &b); } /** * Simplified control transfer for port/wValue = 0x82 - prepare bulk * * @param device_number device number * @param size Size of bulk transfer which follows (number of bytes) * @return SANE status */ static SANE_Status _bulk_size(SANE_Int device_number, unsigned int size) { SANE_Byte bulksize[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; bulksize[4] = size & 0xff; bulksize[5] = (size >> 8) & 0xff; bulksize[6] = (size >> 16) & 0xff; bulksize[7] = (size >> 24) & 0xff; return sanei_usb_control_msg(device_number, REQUEST_TYPE_OUT, REQUEST_BUFFER, PORT_SCSI_SIZE, ANYINDEX, 8, bulksize); } /* * Ctrl inbound, single byte */ /** * Inbound control transfer * * @param device_number device number * @param b byte received from device * @return SANE status */ static SANE_Status _ctrl_in_byte(SANE_Int device_number, SANE_Byte* b) { /* int r = libusb_control_transfer(scannerHandle, CTRL_IN, 0x0C, 0x0084, ANYINDEX, &b, 1, TIMEOUT); */ /* int r = libusb_control_transfer(scannerHandle, CTRL_IN, 0x0C, 0x0084, ANYINDEX, &b, 1, TIMEOUT); */ return sanei_usb_control_msg(device_number, REQUEST_TYPE_IN, REQUEST_REGISTER, PORT_SCSI_STATUS, ANYINDEX, 1, b); } /** * Bulk in transfer for data, in parts of 0x4000 bytes max * * @param device_number device number * @param data array holding or receiving data (must be preallocated) * @param size ptr to size of the data array / actual size on output * @return SANE status */ static SANE_Status _bulk_in(SANE_Int device_number, SANE_Byte *data, size_t *size) { size_t remaining = 0; SANE_Status r = SANE_STATUS_GOOD; size_t part; remaining = *size; while (remaining > 0) { /* Determine bulk size */ part = (remaining >= 0x4000) ? 0x4000 : remaining; /* max 16k per chunk */ /* DBG (DBG_info, "\t\t_bulk_in: %08x @ %p, %08x rem\n", (unsigned int)part, data, (unsigned int)remaining); */ r = sanei_usb_read_bulk(device_number, data, &part); if (r != SANE_STATUS_GOOD) { break; } /* DBG (DBG_info, "\t\t_bulk_in: -> %d : %08x\n", r, (unsigned int)part);*/ remaining -= part; data += part; } *size -= remaining; return r; } sane-backends-1.0.27/backend/sceptre.conf.in0000664000175000017500000000006012112021330015507 00000000000000scsi "KINPO " "Vividscan S120 " /dev/scanner sane-backends-1.0.27/backend/gt68xx_gt6801.c0000664000175000017500000001624612112021330015130 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov GT6801 support by Andreas Nowack Copyright (C) 2002-2007 Henning Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file * @brief Implementation of the GT6801 specific functions. */ #include "gt68xx_gt6801.h" /* doesn't work with plustek scanner */ SANE_Status gt6801_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x50; req[1] = 0x01; req[2] = 0x80; RIE (gt68xx_device_req (dev, req, req)); if (req[0] == 0x00 && req[1] == 0x50) *loaded = SANE_TRUE; else *loaded = SANE_FALSE; return SANE_STATUS_GOOD; } /* doesn't work with at least cytron scanner */ SANE_Status gt6801_check_plustek_firmware (GT68xx_Device * dev, SANE_Bool * loaded) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x73; req[1] = 0x01; status = gt68xx_device_small_req (dev, req, req); if (status != SANE_STATUS_GOOD) { /* Assume that firmware is not loaded */ *loaded = SANE_FALSE; return SANE_STATUS_GOOD; } /* check for correct answer */ if ((req[0] == 0) && (req[1] == 0x12) && (req[3] == 0x80)) /* req[3] is 0 if fw is not loaded, if loaded it's 0x80 * at least on my 1284u (gerhard@gjaeger.de) * * With the Genius scanners req[3] is 0x02/0x82. (hmg) */ *loaded = SANE_TRUE; else *loaded = SANE_FALSE; /* Until I find out if testing for req[3] & 0x80 is save, load the firmware everytime */ *loaded = SANE_FALSE; return SANE_STATUS_GOOD; } #define MAX_DOWNLOAD_BLOCK_SIZE 64 SANE_Status gt6801_download_firmware (GT68xx_Device * dev, SANE_Byte * data, SANE_Word size) { SANE_Status status; SANE_Byte download_buf[MAX_DOWNLOAD_BLOCK_SIZE]; SANE_Byte check_buf[MAX_DOWNLOAD_BLOCK_SIZE]; SANE_Byte *block; SANE_Word addr, bytes_left; GT68xx_Packet boot_req; SANE_Word block_size = MAX_DOWNLOAD_BLOCK_SIZE; CHECK_DEV_ACTIVE (dev, "gt6801_download_firmware"); for (addr = 0; addr < size; addr += block_size) { bytes_left = size - addr; if (bytes_left > block_size) block = data + addr; else { memset (download_buf, 0, block_size); memcpy (download_buf, data + addr, bytes_left); block = download_buf; } RIE (gt68xx_device_memory_write (dev, addr, block_size, block)); RIE (gt68xx_device_memory_read (dev, 0x3f00, block_size, check_buf)); /* * For GT6816 this was: * if (memcmp (block, check_buf, block_size) != 0) ... * Apparently the GT6801 does something different... * * hmg: For my BP 1200 CU the result is 00 09 so maybe only the 0 is * relevant? */ if ((check_buf[0] != 0) && (check_buf[1] != 0x40)) { DBG (3, "gt6801_download_firmware: mismatch at block 0x%0x\n", addr); return SANE_STATUS_IO_ERROR; } } memset (boot_req, 0, sizeof (boot_req)); boot_req[0] = 0x69; boot_req[1] = 0x01; boot_req[2] = 0xc0; boot_req[3] = 0x1c; RIE (gt68xx_device_req (dev, boot_req, boot_req)); #if 0 /* hmg: the following isn't in my log: */ memset (boot_req, 0, sizeof (boot_req)); /* I don't know if this is needed */ boot_req[0] = 0x01; boot_req[1] = 0x01; RIE (gt68xx_device_small_req (dev, boot_req, boot_req)); #endif return SANE_STATUS_GOOD; } SANE_Status gt6801_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x10; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); /* I don't know what power_ok = SANE_FALSE looks like... */ /* hmg: let's assume it's different from the usual 00 10 */ if (gt68xx_device_check_result (req, 0x10) == SANE_STATUS_GOOD) *power_ok = SANE_TRUE; else *power_ok = SANE_FALSE; return SANE_STATUS_GOOD; } SANE_Status gt6801_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp, SANE_Bool ta_lamp) { if (!dev->model->is_cis) { GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x25; req[1] = 0x01; req[2] = 0; if (fb_lamp) req[2] |= 0x01; if (ta_lamp) req[2] |= 0x02; return gt68xx_device_req (dev, req, req); } return SANE_STATUS_GOOD; } SANE_Status gt6801_is_moving (GT68xx_Device * dev, SANE_Bool * moving) { /* this seems not to be supported by the scanner */ (void) dev; *moving = SANE_FALSE; return SANE_STATUS_GOOD; } SANE_Status gt6801_carriage_home (GT68xx_Device * dev) { GT68xx_Packet req; SANE_Status status; memset (req, 0, sizeof (req)); if (dev->model->flags & GT68XX_FLAG_MOTOR_HOME) { req[0] = 0x34; req[1] = 0x01; status = gt68xx_device_req (dev, req, req); } else { req[0] = 0x12; req[1] = 0x01; if ((status = gt68xx_device_req (dev, req, req)) == SANE_STATUS_GOOD) { RIE (gt68xx_device_check_result (req, 0x12)); memset (req, 0, sizeof (req)); req[0] = 0x24; req[1] = 0x01; status = gt68xx_device_req (dev, req, req); RIE (gt68xx_device_check_result (req, 0x24)); } } return status; } SANE_Status gt6801_stop_scan (GT68xx_Device * dev) { GT68xx_Packet req; SANE_Status status; memset (req, 0, sizeof (req)); req[0] = 0x42; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); RIE (gt68xx_device_check_result (req, 0x42)); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/plustek-pp_procs.h0000664000175000017500000002114612112021330016261 00000000000000/** @file plustek-pp_procs.h * @brief here are the prototypes of all exported functions * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2004 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * 0.30 - initial version * 0.31 - no changes * 0.32 - no changes * 0.33 - no changes * 0.34 - added this history * 0.35 - added Kevins´ changes to MiscRestorePort * changed prototype of MiscReinitStruct * added prototype for function PtDrvLegalRequested() * 0.36 - added prototype for function MiscLongRand() * removed PtDrvLegalRequested() * changed prototype of function MiscInitPorts() * 0.37 - added io.c and procfs.c * added MiscGetModelName() * added ModelSetA3I() * 0.38 - added P12 stuff * removed prototype of IOScannerIdleMode() * removed prototype of IOSPPWrite() * 0.39 - moved prototypes for the user space stuff to plustek-share.h * 0.40 - no changes * 0.41 - no changes * 0.42 - added MapAdjust * 0.43 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __PROCS_H__ #define __PROCS_H__ #ifdef _BACKEND_ENABLED # define _LOC static #else # define _LOC #endif /* * implementation in plustek-pp_misc.c */ _LOC pScanData MiscAllocAndInitStruct( void ); _LOC int MiscReinitStruct ( pScanData ps ); _LOC int MiscInitPorts ( pScanData ps, int port ); _LOC void MiscRestorePort( pScanData ps ); _LOC void MiscStartTimer ( pTimerDef timer, unsigned long us ); _LOC int MiscCheckTimer ( pTimerDef timer ); _LOC int MiscRegisterPort ( pScanData ps, int portAddr ); _LOC void MiscUnregisterPort ( pScanData ps ); _LOC int MiscClaimPort ( pScanData ps ); _LOC void MiscReleasePort ( pScanData ps ); _LOC Long MiscLongRand ( void ); _LOC const char *MiscGetModelName( UShort id ); #ifdef DEBUG _LOC Bool MiscAllPointersSet( pScanData ps ); #endif /* * implementation in plustek-pp_detect.c */ _LOC int DetectScanner( pScanData ps, int mode ); /* * implementation in plustek-pp_p48xx.c */ _LOC int P48xxInitAsic( pScanData ps ); /* * implementation in plustek-pp_p9636.c */ _LOC int P9636InitAsic( pScanData ps ); /* * implementation in plustek-pp_p12.c */ _LOC int P12InitAsic ( pScanData ps ); _LOC void P12SetGeneralRegister( pScanData ps ); /* * implementation in plustek-pp_p12ccd.c */ _LOC void P12InitCCDandDAC( pScanData ps, Bool shading ); /* * implementation in plustek-pp_models.c */ _LOC void ModelSet4800 ( pScanData ps ); _LOC void ModelSet4830 ( pScanData ps ); _LOC void ModelSet600 ( pScanData ps ); _LOC void ModelSet12000( pScanData ps ); _LOC void ModelSetA3I ( pScanData ps ); _LOC void ModelSet9630 ( pScanData ps ); _LOC void ModelSet9636 ( pScanData ps ); _LOC void ModelSetP12 ( pScanData ps ); /* * implementation in plustek-pp_dac.c */ _LOC int DacInitialize( pScanData ps ); _LOC void DacP98AdjustDark ( pScanData ps ); _LOC void DacP98FillGainOutDirectPort ( pScanData ps ); _LOC void DacP98FillShadingDarkToShadingRegister( pScanData ps ); _LOC void DacP96WriteBackToGammaShadingRAM( pScanData ps ); _LOC void DacP98003FillToDAC (pScanData ps, pRGBByteDef regs, pColorByte data); _LOC void DacP98003AdjustGain(pScanData ps, ULong color, Byte hilight ); _LOC Byte DacP98003SumGains ( pUChar pb, ULong pixelsLine ); /* * implementation in plustek-pp_motor.c */ _LOC int MotorInitialize ( pScanData ps ); _LOC void MotorSetConstantMove( pScanData ps, Byte bMovePerStep ); _LOC void MotorToHomePosition ( pScanData ps ); _LOC void MotorP98GoFullStep ( pScanData ps, ULong dwStep ); _LOC void MotorP96SetSpeedToStopProc( pScanData ps ); _LOC void MotorP96ConstantMoveProc ( pScanData ps, ULong dwLines ); _LOC Bool MotorP96AheadToDarkArea ( pScanData ps ); _LOC void MotorP96AdjustCurrentSpeed( pScanData ps, Byte bSpeed ); _LOC void MotorP98003BackToHomeSensor ( pScanData ps ); _LOC void MotorP98003ModuleForwardBackward( pScanData ps ); _LOC void MotorP98003ForceToLeaveHomePos ( pScanData ps ); _LOC void MotorP98003PositionYProc ( pScanData ps, ULong steps); /* * implementation in plustek-pp_map.c */ _LOC void MapInitialize ( pScanData ps ); _LOC void MapSetupDither( pScanData ps ); _LOC void MapAdjust ( pScanData ps, int which ); /* * implementation in plustek-pp_image.c */ _LOC int ImageInitialize( pScanData ps ); /* * implementation in plustek-pp_genericio.c */ _LOC int IOFuncInitialize ( pScanData ps ); _LOC Byte IOSetToMotorRegister ( pScanData ps ); _LOC Byte IOGetScanState ( pScanData ps, Bool fOpenned ); _LOC Byte IOGetExtendedStatus ( pScanData ps ); _LOC void IOGetCurrentStateCount( pScanData, pScanState pScanStep); _LOC int IOIsReadyForScan ( pScanData ps ); _LOC void IOSetXStepLineScanTime( pScanData ps, Byte b ); _LOC void IOSetToMotorStepCount ( pScanData ps ); _LOC void IOSelectLampSource ( pScanData ps ); _LOC Bool IOReadOneShadingLine ( pScanData ps, pUChar pBuf, ULong len ); _LOC ULong IOReadFifoLength ( pScanData ps ); _LOC void IOPutOnAllRegisters ( pScanData ps ); _LOC void IOReadColorData ( pScanData ps, pUChar pBuf, ULong len ); /* * implementation in plustek-pp_io.c */ _LOC int IOInitialize ( pScanData ps ); _LOC void IOMoveDataToScanner ( pScanData ps, pUChar pBuffer, ULong size ); _LOC void IODownloadScanStates( pScanData ps ); _LOC void IODataToScanner ( pScanData, Byte bValue ); _LOC void IODataToRegister ( pScanData ps, Byte bReg, Byte bData ); _LOC Byte IODataFromRegister ( pScanData ps, Byte bReg ); _LOC void IORegisterToScanner ( pScanData ps, Byte bReg ); _LOC void IODataRegisterToDAC ( pScanData ps, Byte bReg, Byte bData ); _LOC Byte IODataRegisterFromScanner( pScanData ps, Byte bReg ); _LOC void IOCmdRegisterToScanner ( pScanData ps, Byte bReg, Byte bData ); _LOC void IORegisterDirectToScanner( pScanData, Byte bReg ); _LOC void IOSoftwareReset ( pScanData ps ); _LOC void IOReadScannerImageData ( pScanData ps, pUChar pBuf, ULong size ); #ifdef __KERNEL__ _LOC void IOOut ( Byte data, UShort port ); _LOC void IOOutDelayed( Byte data, UShort port ); _LOC Byte IOIn ( UShort port ); _LOC Byte IOInDelayed ( UShort port ); #endif /* * implementation in plustek-pp_tpa.c */ _LOC void TPAP98001AverageShadingData( pScanData ps ); _LOC void TPAP98003FindCenterPointer ( pScanData ps ); _LOC void TPAP98003Reshading ( pScanData ps ); /* * implementation in plustek-pp_scale.c */ _LOC void ScaleX( pScanData ps, pUChar inBuf, pUChar outBuf ); /* * implementation in plustek-pp_procfs.c (Kernel-mode only) */ #ifdef __KERNEL__ int ProcFsInitialize ( void ); void ProcFsShutdown ( void ); void ProcFsRegisterDevice ( pScanData ps ); void ProcFsUnregisterDevice( pScanData ps ); #endif #endif /* guard __PROCS_H__ */ /* END PLUSTEK-PP_PROCS.H ...................................................*/ sane-backends-1.0.27/backend/niash.c0000664000175000017500000011553112775312261014073 00000000000000/* Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. $Id$ */ /* Concept for a backend for scanners based on the NIASH chipset, such as HP3300C, HP3400C, HP4300C, Agfa Touch. Parts of this source were inspired by other backends. */ #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/saneopts.h" #include /* malloc, free */ #include /* memcpy */ #include #include #include /* definitions for debug */ #define BACKEND_NAME niash #define BUILD 1 #define DBG_ASSERT 1 #define DBG_ERR 16 #define DBG_MSG 32 /* Just to avoid conflicts between niash backend and testtool */ #define WITH_NIASH 1 /* (source) includes for data transfer methods */ #define STATIC static #include "niash_core.c" #include "niash_xfer.c" #define ASSERT(cond) (!(cond) ? DBG(DBG_ASSERT, "!!! ASSERT(%S) FAILED!!!\n",STRINGIFY(cond));) #define MM_TO_PIXEL(_mm_, _dpi_) ((_mm_) * (_dpi_) / 25.4 ) #define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_) ) /* options enumerator */ typedef enum { optCount = 0, optGroupGeometry, optTLX, optTLY, optBRX, optBRY, optDPI, optGroupImage, optGammaTable, /* gamma table */ optGroupMode, optMode, optGroupEnhancement, optThreshold, #ifdef EXPERIMENTAL optGroupMisc, optLamp, optCalibrate, optGamma, /* analog gamma = single number */ #endif optLast } EOptionIndex; typedef union { SANE_Word w; SANE_Word *wa; /* word array */ SANE_String s; } TOptionValue; #define HW_GAMMA_SIZE 4096 #define SANE_GAMMA_SIZE 4096 typedef struct { SANE_Option_Descriptor aOptions[optLast]; TOptionValue aValues[optLast]; TScanParams ScanParams; THWParams HWParams; TDataPipe DataPipe; int iLinesLeft; /* lines to scan */ int iBytesLeft; /* bytes to read */ int iPixelsPerLine; /* pixels in one scan line */ SANE_Int aGammaTable[SANE_GAMMA_SIZE]; /* a 12-to-8 bit color lookup table */ /* fCancelled needed to let sane issue the cancel message instead of an error message */ SANE_Bool fCancelled; /* SANE_TRUE if scanning cancelled */ SANE_Bool fScanning; /* SANE_TRUE if actively scanning */ int WarmUpTime; /* time to wait before a calibration starts */ unsigned char CalWhite[3]; /* values for the last calibration of white */ struct timeval WarmUpStarted; /* system type to trace the time elapsed */ } TScanner; /* linked list of SANE_Device structures */ typedef struct TDevListEntry { struct TDevListEntry *pNext; SANE_Device dev; } TDevListEntry; static TDevListEntry *_pFirstSaneDev = 0; static int iNumSaneDev = 0; static const SANE_Device **_pSaneDevList = 0; /* option constraints */ static const SANE_Range rangeGammaTable = { 0, 255, 1 }; /* available scanner resolutions */ static const SANE_Int setResolutions[] = { 4, 75, 150, 300, 600 }; #ifdef EXPERIMENTAL /* range of an analog gamma */ static const SANE_Range rangeGamma = { SANE_FIX (0.25), SANE_FIX (4.0), SANE_FIX (0.0) }; #endif /* interpolate a sane gamma table to a hardware appropriate one just in case the sane gamma table would be smaller */ static void _ConvertGammaTable (SANE_Word * saneGamma, unsigned char *hwGamma) { int i; int current = 0; for (i = 0; i < SANE_GAMMA_SIZE; ++i) { int j; int next; /* highest range of copy indices */ next = ((i + 1) * HW_GAMMA_SIZE) / SANE_GAMMA_SIZE; /* always copy the first */ hwGamma[current] = saneGamma[i]; /* the interpolation of the rest depends on the gap */ for (j = current + 1; j < HW_GAMMA_SIZE && j < next; ++j) { hwGamma[j] = (saneGamma[i] * (next - j) + saneGamma[i + 1] * (j - current)) / (next - current); } current = next; } } /* create a unity gamma table */ static void _UnityGammaTable (unsigned char *hwGamma) { int i; for (i = 0; i < HW_GAMMA_SIZE; ++i) { hwGamma[i] = (i * 256) / HW_GAMMA_SIZE; } } static const SANE_Range rangeXmm = { 0, 220, 1 }; static const SANE_Range rangeYmm = { 0, 296, 1 }; static const SANE_Int startUpGamma = SANE_FIX (1.6); static const char colorStr[] = { SANE_VALUE_SCAN_MODE_COLOR }; static const char grayStr[] = { SANE_VALUE_SCAN_MODE_GRAY }; static const char lineartStr[] = { SANE_VALUE_SCAN_MODE_LINEART }; #define DEPTH_LINEART 1 #define DEPTH_GRAY 8 #define DEPTH_COLOR 8 #define BYTES_PER_PIXEL_GRAY 1 #define BYTES_PER_PIXEL_COLOR 3 #define BITS_PER_PIXEL_LINEART 1 #define BITS_PER_PIXEL_GRAY DEPTH_GRAY #define BITS_PER_PIXEL_COLOR (DEPTH_COLOR*3) #define BITS_PER_BYTE 8 #define BITS_PADDING (BITS_PER_BYTE-1) #define MODE_COLOR 0 #define MODE_GRAY 1 #define MODE_LINEART 2 /* lineart treshold range */ static const SANE_Range rangeThreshold = { 0, 100, 1 }; /* scanning modes */ static SANE_String_Const modeList[] = { colorStr, grayStr, lineartStr, NULL }; static int _bytesPerLineLineart (int pixelsPerLine) { return (pixelsPerLine * BITS_PER_PIXEL_LINEART + BITS_PADDING) / BITS_PER_BYTE; } static int _bytesPerLineGray (int pixelsPerLine) { return (pixelsPerLine * BITS_PER_PIXEL_GRAY + BITS_PADDING) / BITS_PER_BYTE; } static int _bytesPerLineColor (int pixelsPerLine) { return (pixelsPerLine * BITS_PER_PIXEL_COLOR + BITS_PADDING) / BITS_PER_BYTE; } /* dummy*/ static void _rgb2rgb (unsigned char __sane_unused__ *buffer, int __sane_unused__ pixels, int __sane_unused__ threshold) { /* make the compiler content */ } /* convert 24bit RGB to 8bit GRAY */ static void _rgb2gray (unsigned char *buffer, int pixels, int __sane_unused__ threshold) { #define WEIGHT_R 27 #define WEIGHT_G 54 #define WEIGHT_B 19 #define WEIGHT_W (WEIGHT_R + WEIGHT_G + WEIGHT_B) static int aWeight[BYTES_PER_PIXEL_COLOR] = { WEIGHT_R, WEIGHT_G, WEIGHT_B }; int nbyte = pixels * BYTES_PER_PIXEL_COLOR; int acc = 0; int x; for (x = 0; x < nbyte; ++x) { acc += aWeight[x % BYTES_PER_PIXEL_COLOR] * buffer[x]; if ((x + 1) % BYTES_PER_PIXEL_COLOR == 0) { buffer[x / BYTES_PER_PIXEL_COLOR] = (unsigned char) (acc / WEIGHT_W); acc = 0; } } #undef WEIGHT_R #undef WEIGHT_G #undef WEIGHT_B #undef WEIGHT_W } /* convert 24bit RGB to 1bit B/W */ static void _rgb2lineart (unsigned char *buffer, int pixels, int threshold) { static const int aMask[BITS_PER_BYTE] = { 128, 64, 32, 16, 8, 4, 2, 1 }; int acc = 0; int nx; int x; int thresh; _rgb2gray (buffer, pixels, 0); nx = ((pixels + BITS_PADDING) / BITS_PER_BYTE) * BITS_PER_BYTE; thresh = 255 * threshold / rangeThreshold.max; for (x = 0; x < nx; ++x) { if (x < pixels && buffer[x] < thresh) { acc |= aMask[x % BITS_PER_BYTE]; } if ((x + 1) % BITS_PER_BYTE == 0) { buffer[x / BITS_PER_BYTE] = (unsigned char) (acc); acc = 0; } } } typedef struct tgModeParam { SANE_Int depth; SANE_Frame format; int (*bytesPerLine) (int pixelsPerLine); void (*adaptFormat) (unsigned char *rgbBuffer, int pixels, int threshold); } TModeParam; static const TModeParam modeParam[] = { {DEPTH_COLOR, SANE_FRAME_RGB, _bytesPerLineColor, _rgb2rgb}, {DEPTH_GRAY, SANE_FRAME_GRAY, _bytesPerLineGray, _rgb2gray}, {DEPTH_LINEART, SANE_FRAME_GRAY, _bytesPerLineLineart, _rgb2lineart} }; #define WARMUP_AFTERSTART 1 /* flag for 1st warm up */ #define WARMUP_INSESSION 0 #define WARMUP_TESTINTERVAL 15 /* test every 15sec */ #define WARMUP_TIME 30 /* first wait is 30sec minimum */ #define WARMUP_MAXTIME 90 /* after one and a half minute start latest */ #define CAL_DEV_MAX 15 /* maximum deviation of cal values in percent between 2 tests */ /* different warm up after start and after automatic off */ static const int aiWarmUpTime[] = { WARMUP_TESTINTERVAL, WARMUP_TIME }; /* returns 1, when the warm up time "iTime" has elasped */ static int _TimeElapsed (struct timeval *start, struct timeval *now, int iTime) { /* this is a bit strange, but can deal with overflows */ if (start->tv_sec > now->tv_sec) return (start->tv_sec / 2 - now->tv_sec / 2 > iTime / 2); else return (now->tv_sec - start->tv_sec >= iTime); } static void _WarmUpLamp (TScanner * s, int iMode) { SANE_Bool fLampOn; /* on startup don't care what was before assume lamp was off, and the previous cal values can never be reached */ if (iMode == WARMUP_AFTERSTART) { fLampOn = SANE_FALSE; s->CalWhite[0] = s->CalWhite[1] = s->CalWhite[2] = (unsigned char) (-1); } else GetLamp (&s->HWParams, &fLampOn); if (!fLampOn) { /* get the current system time */ gettimeofday (&s->WarmUpStarted, 0); /* determine the time to wait at least */ s->WarmUpTime = aiWarmUpTime[iMode]; /* switch on the lamp */ SetLamp (&s->HWParams, SANE_TRUE); } } static void _WaitForLamp (TScanner * s, unsigned char *pabCalibTable) { struct timeval now[2]; /* toggling time holder */ int i; /* rgb loop */ int iCal = 0; /* counter */ int iCurrent = 0; /* buffer and time-holder swap flag */ SANE_Bool fHasCal; unsigned char CalWhite[2][3]; /* toggling buffer */ int iDelay = 0; /* delay loop counter */ _WarmUpLamp (s, SANE_FALSE); /* get the time stamp for the wait loops */ if (s->WarmUpTime) gettimeofday (&now[iCurrent], 0); SimpleCalibExt (&s->HWParams, pabCalibTable, CalWhite[iCurrent]); fHasCal = SANE_TRUE; DBG (DBG_MSG, "_WaitForLamp: first calibration\n"); /* wait until time has elapsed or for values to stabilze */ while (s->WarmUpTime) { /* check if the last scan has lower calibration values than the current one would have */ if (s->WarmUpTime && fHasCal) { SANE_Bool fOver = SANE_TRUE; for (i = 0; fOver && i < 3; ++i) { if (!s->CalWhite[i]) fOver = SANE_FALSE; else if (CalWhite[iCurrent][i] < s->CalWhite[i]) fOver = SANE_FALSE; } /* warm up is not needed, when calibration data is above the calibration data of the last scan */ if (fOver) { s->WarmUpTime = 0; DBG (DBG_MSG, "_WaitForLamp: Values seem stable, skipping next calibration cycle\n"); } } /* break the loop, when the longest wait time has expired to prevent a hanging application, even if the values might not be good, yet */ if (s->WarmUpTime && fHasCal && iCal) { /* abort, when we have waited long enough */ if (_TimeElapsed (&s->WarmUpStarted, &now[iCurrent], WARMUP_MAXTIME)) { /* stop idling */ s->WarmUpTime = 0; DBG (DBG_MSG, "_WaitForLamp: WARMUP_MAXTIME=%ds elapsed!\n", WARMUP_MAXTIME); } } /* enter a delay loop, when there is still time to wait */ if (s->WarmUpTime) { /* if the (too low) calibration values have just been acquired we start waiting */ if (fHasCal) DBG (DBG_MSG, "_WaitForLamp: entering delay loop\r"); else DBG (DBG_MSG, "_WaitForLamp: delay loop %d \r", ++iDelay); sleep (1); fHasCal = SANE_FALSE; gettimeofday (&now[!iCurrent], 0); } /* look if we should check again */ if (s->WarmUpTime /* did we have to wait at all */ /* is the minimum time elapsed */ && _TimeElapsed (&s->WarmUpStarted, &now[!iCurrent], s->WarmUpTime) /* has the minimum time elapsed since the last calibration */ && _TimeElapsed (&now[iCurrent], &now[!iCurrent], WARMUP_TESTINTERVAL)) { int dev = 0; /* 0 percent deviation in cal value as default */ iDelay = 0; /* all delays processed */ /* new calibration */ ++iCal; iCurrent = !iCurrent; /* swap the test-buffer, and time-holder */ SimpleCalibExt (&s->HWParams, pabCalibTable, CalWhite[iCurrent]); fHasCal = SANE_TRUE; for (i = 0; i < 3; ++i) { /* copy for faster and clearer access */ int cwa; int cwb; int ldev; cwa = CalWhite[!iCurrent][i]; cwb = CalWhite[iCurrent][i]; /* find the biggest deviation of one color */ if (cwa > cwb) ldev = 0; else if (cwa && cwb) ldev = ((cwb - cwa) * 100) / cwb; else ldev = 100; dev = MAX (dev, ldev); } /* show the biggest deviation of the calibration values */ DBG (DBG_MSG, "_WaitForLamp: recalibration #%d, deviation = %d%%\n", iCal, dev); /* the deviation to the previous calibration is tolerable */ if (dev <= CAL_DEV_MAX) s->WarmUpTime = 0; } } /* remember the values of this calibration for the next time */ for (i = 0; i < 3; ++i) { s->CalWhite[i] = CalWhite[iCurrent][i]; } } /* used, when setting gamma as 1 value */ static void _SetScalarGamma (SANE_Int * aiGamma, SANE_Int sfGamma) { int j; double fGamma; fGamma = SANE_UNFIX (sfGamma); for (j = 0; j < SANE_GAMMA_SIZE; j++) { int iData; iData = floor (256.0 * pow (((double) j / (double) SANE_GAMMA_SIZE), 1.0 / fGamma)); if (iData > 255) iData = 255; aiGamma[j] = iData; } } /* return size of longest string in a string list */ static size_t _MaxStringSize (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /* change a sane cap and return true, when a change took place */ static int _ChangeCap (SANE_Word * pCap, SANE_Word cap, int isSet) { SANE_Word prevCap = *pCap; if (isSet) { *pCap |= cap; } else { *pCap &= ~cap; } return *pCap != prevCap; } static void _InitOptions (TScanner * s) { int i; SANE_Option_Descriptor *pDesc; TOptionValue *pVal; _SetScalarGamma (s->aGammaTable, startUpGamma); for (i = optCount; i < optLast; i++) { pDesc = &s->aOptions[i]; pVal = &s->aValues[i]; /* defaults */ pDesc->name = ""; pDesc->title = ""; pDesc->desc = ""; pDesc->type = SANE_TYPE_INT; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->cap = 0; switch (i) { case optCount: pDesc->title = SANE_TITLE_NUM_OPTIONS; pDesc->desc = SANE_DESC_NUM_OPTIONS; pDesc->cap = SANE_CAP_SOFT_DETECT; pVal->w = (SANE_Word) optLast; break; case optGroupGeometry: pDesc->title = "Geometry"; pDesc->type = SANE_TYPE_GROUP; pDesc->size = 0; break; case optTLX: pDesc->name = SANE_NAME_SCAN_TL_X; pDesc->title = SANE_TITLE_SCAN_TL_X; pDesc->desc = SANE_DESC_SCAN_TL_X; pDesc->unit = SANE_UNIT_MM; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &rangeXmm; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = rangeXmm.min; break; case optTLY: pDesc->name = SANE_NAME_SCAN_TL_Y; pDesc->title = SANE_TITLE_SCAN_TL_Y; pDesc->desc = SANE_DESC_SCAN_TL_Y; pDesc->unit = SANE_UNIT_MM; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &rangeYmm; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = rangeYmm.min; break; case optBRX: pDesc->name = SANE_NAME_SCAN_BR_X; pDesc->title = SANE_TITLE_SCAN_BR_X; pDesc->desc = SANE_DESC_SCAN_BR_X; pDesc->unit = SANE_UNIT_MM; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &rangeXmm; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = 210 /* A4 width instead of rangeXmm.max */ ; break; case optBRY: pDesc->name = SANE_NAME_SCAN_BR_Y; pDesc->title = SANE_TITLE_SCAN_BR_Y; pDesc->desc = SANE_DESC_SCAN_BR_Y; pDesc->unit = SANE_UNIT_MM; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &rangeYmm; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = 290 /* have a bit reserve instaed of rangeYmm.max */ ; break; case optDPI: pDesc->name = SANE_NAME_SCAN_RESOLUTION; pDesc->title = SANE_TITLE_SCAN_RESOLUTION; pDesc->desc = SANE_DESC_SCAN_RESOLUTION; pDesc->unit = SANE_UNIT_DPI; pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST; pDesc->constraint.word_list = setResolutions; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = setResolutions[2]; /* default to 150dpi */ break; case optGroupImage: pDesc->title = SANE_I18N ("Image"); pDesc->type = SANE_TYPE_GROUP; pDesc->size = 0; break; #ifdef EXPERIMENTAL case optGamma: pDesc->name = SANE_NAME_ANALOG_GAMMA; pDesc->title = SANE_TITLE_ANALOG_GAMMA; pDesc->desc = SANE_DESC_ANALOG_GAMMA; pDesc->type = SANE_TYPE_FIXED; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &rangeGamma; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = startUpGamma; break; #endif case optGammaTable: pDesc->name = SANE_NAME_GAMMA_VECTOR; pDesc->title = SANE_TITLE_GAMMA_VECTOR; pDesc->desc = SANE_DESC_GAMMA_VECTOR; pDesc->size = sizeof (s->aGammaTable); pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &rangeGammaTable; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->wa = s->aGammaTable; break; #ifdef EXPERIMENTAL case optGroupMisc: pDesc->title = SANE_I18N ("Miscellaneous"); pDesc->type = SANE_TYPE_GROUP; pDesc->size = 0; break; case optLamp: pDesc->name = "lamp"; pDesc->title = SANE_I18N ("Lamp status"); pDesc->desc = SANE_I18N ("Switches the lamp on or off."); pDesc->type = SANE_TYPE_BOOL; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* switch the lamp on when starting for first the time */ pVal->w = SANE_TRUE; break; case optCalibrate: pDesc->name = "calibrate"; pDesc->title = SANE_I18N ("Calibrate"); pDesc->desc = SANE_I18N ("Calibrates for black and white level."); pDesc->type = SANE_TYPE_BUTTON; pDesc->cap = SANE_CAP_SOFT_SELECT; pDesc->size = 0; break; #endif case optGroupMode: pDesc->title = SANE_I18N ("Scan Mode"); pDesc->desc = ""; pDesc->type = SANE_TYPE_GROUP; break; case optMode: /* scan mode */ pDesc->name = SANE_NAME_SCAN_MODE; pDesc->title = SANE_TITLE_SCAN_MODE; pDesc->desc = SANE_DESC_SCAN_MODE; pDesc->type = SANE_TYPE_STRING; pDesc->size = _MaxStringSize (modeList); pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; pDesc->constraint.string_list = modeList; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_EMULATED; pVal->w = MODE_COLOR; break; case optGroupEnhancement: pDesc->title = SANE_I18N ("Enhancement"); pDesc->desc = ""; pDesc->type = SANE_TYPE_GROUP; break; case optThreshold: pDesc->name = SANE_NAME_THRESHOLD; pDesc->title = SANE_TITLE_THRESHOLD; pDesc->desc = SANE_DESC_THRESHOLD; pDesc->type = SANE_TYPE_INT; pDesc->unit = SANE_UNIT_PERCENT; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &rangeThreshold; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_EMULATED; pVal->w = 50; default: DBG (DBG_ERR, "Uninitialised option %d\n", i); break; } } } static int _ReportDevice (TScannerModel * pModel, const char *pszDeviceName) { TDevListEntry *pNew, *pDev; DBG (DBG_MSG, "niash: _ReportDevice '%s'\n", pszDeviceName); pNew = malloc (sizeof (TDevListEntry)); if (!pNew) { DBG (DBG_ERR, "no mem\n"); return -1; } /* add new element to the end of the list */ if (_pFirstSaneDev == 0) { _pFirstSaneDev = pNew; } else { for (pDev = _pFirstSaneDev; pDev->pNext; pDev = pDev->pNext) { ; } pDev->pNext = pNew; } /* fill in new element */ pNew->pNext = 0; pNew->dev.name = strdup (pszDeviceName); pNew->dev.vendor = pModel->pszVendor; pNew->dev.model = pModel->pszName; pNew->dev.type = "flatbed scanner"; iNumSaneDev++; return 0; } /*****************************************************************************/ SANE_Status sane_init (SANE_Int * piVersion, SANE_Auth_Callback __sane_unused__ pfnAuth) { DBG_INIT (); DBG (DBG_MSG, "sane_init\n"); if (piVersion != NULL) { *piVersion = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); } /* initialise transfer methods */ iNumSaneDev = 0; NiashXferInit (_ReportDevice); return SANE_STATUS_GOOD; } void sane_exit (void) { TDevListEntry *pDev, *pNext; DBG (DBG_MSG, "sane_exit\n"); /* free device list memory */ if (_pSaneDevList) { for (pDev = _pFirstSaneDev; pDev; pDev = pNext) { pNext = pDev->pNext; free ((void *) pDev->dev.name); free (pDev); } _pFirstSaneDev = 0; free (_pSaneDevList); _pSaneDevList = 0; } } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { TDevListEntry *pDev; int i; DBG (DBG_MSG, "sane_get_devices\n"); if (_pSaneDevList) { free (_pSaneDevList); } _pSaneDevList = malloc (sizeof (*_pSaneDevList) * (iNumSaneDev + 1)); if (!_pSaneDevList) { DBG (DBG_MSG, "no mem\n"); return SANE_STATUS_NO_MEM; } i = 0; for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext) { _pSaneDevList[i++] = &pDev->dev; } _pSaneDevList[i++] = 0; /* last entry is 0 */ *device_list = _pSaneDevList; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h) { TScanner *s; DBG (DBG_MSG, "sane_open: %s\n", name); /* check the name */ if (strlen (name) == 0) { /* default to first available device */ name = _pFirstSaneDev->dev.name; } s = malloc (sizeof (TScanner)); if (!s) { DBG (DBG_MSG, "malloc failed\n"); return SANE_STATUS_NO_MEM; } if (NiashOpen (&s->HWParams, name) < 0) { /* is this OK ? */ DBG (DBG_ERR, "NiashOpen failed\n"); free ((void *) s); return SANE_STATUS_DEVICE_BUSY; } _InitOptions (s); s->fScanning = SANE_FALSE; s->fCancelled = SANE_FALSE; *h = s; /* Turn on lamp by default at startup */ _WarmUpLamp (s, WARMUP_AFTERSTART); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle h) { TScanner *s; DBG (DBG_MSG, "sane_close\n"); s = (TScanner *) h; /* turn off scanner lamp */ SetLamp (&s->HWParams, SANE_FALSE); /* close scanner */ NiashClose (&s->HWParams); /* free scanner object memory */ free ((void *) s); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int n) { TScanner *s; DBG (DBG_MSG, "sane_get_option_descriptor %d\n", n); if ((n < optCount) || (n >= optLast)) { return NULL; } s = (TScanner *) h; return &s->aOptions[n]; } SANE_Status sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, void *pVal, SANE_Int * pInfo) { TScanner *s; static char szTable[100]; int *pi; int i; SANE_Int info; SANE_Status status; #ifdef EXPERIMENTAL SANE_Bool fLampIsOn; SANE_Bool fVal; SANE_Bool fSame; #endif DBG (DBG_MSG, "sane_control_option: option %d, action %d\n", n, Action); if ((n < optCount) || (n >= optLast)) { return SANE_STATUS_UNSUPPORTED; } if (Action == SANE_ACTION_GET_VALUE || Action == SANE_ACTION_SET_VALUE) { if (pVal == NULL) { return SANE_STATUS_INVAL; } } s = (TScanner *) h; info = 0; switch (Action) { case SANE_ACTION_GET_VALUE: switch (n) { /* Get options of type SANE_Word */ case optCount: case optDPI: #ifdef EXPERIMENTAL case optGamma: #endif case optTLX: case optTLY: case optBRX: case optBRY: case optThreshold: DBG (DBG_MSG, "sane_control_option: SANE_ACTION_GET_VALUE %d = %d\n", n, (int) s->aValues[n].w); *(SANE_Word *) pVal = s->aValues[n].w; break; /* Get options of type SANE_Word array */ case optGammaTable: DBG (DBG_MSG, "Reading gamma table\n"); memcpy (pVal, s->aValues[n].wa, s->aOptions[n].size); break; case optMode: DBG (DBG_MSG, "Reading scan mode %s\n", modeList[s->aValues[optMode].w]); strcpy ((char *) pVal, modeList[s->aValues[optMode].w]); break; #ifdef EXPERIMENTAL /* Get options of type SANE_Bool */ case optLamp: GetLamp (&s->HWParams, &fLampIsOn); *(SANE_Bool *) pVal = fLampIsOn; break; case optCalibrate: /* although this option has nothing to read, it's added here to avoid a warning when running scanimage --help */ break; #endif default: DBG (DBG_MSG, "SANE_ACTION_GET_VALUE: Invalid option (%d)\n", n); } break; case SANE_ACTION_SET_VALUE: if (s->fScanning) { DBG (DBG_ERR, "sane_control_option: SANE_ACTION_SET_VALUE not allowed during scan\n"); return SANE_STATUS_INVAL; } switch (n) { case optCount: return SANE_STATUS_INVAL; #ifdef EXPERIMENTAL case optGamma: #endif case optThreshold: case optDPI: info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case optTLX: case optTLY: case optBRX: case optBRY: status = sanei_constrain_value (&s->aOptions[n], pVal, &info); if (status != SANE_STATUS_GOOD) { DBG (DBG_ERR, "Failed to constrain option %d (%s)\n", n, s->aOptions[n].title); return status; } #ifdef EXPERIMENTAL /* check values if they are equal */ fSame = s->aValues[n].w == *(SANE_Word *) pVal; #endif /* set the values */ s->aValues[n].w = *(SANE_Word *) pVal; DBG (DBG_MSG, "sane_control_option: SANE_ACTION_SET_VALUE %d = %d\n", n, (int) s->aValues[n].w); #ifdef EXPERIMENTAL if (n == optGamma) { if (!fSame && optLast > optGammaTable) { info |= SANE_INFO_RELOAD_OPTIONS; } _SetScalarGamma (s->aGammaTable, s->aValues[n].w); } #endif break; case optGammaTable: DBG (DBG_MSG, "Writing gamma table\n"); pi = (SANE_Int *) pVal; memcpy (s->aValues[n].wa, pVal, s->aOptions[n].size); /* prepare table for debug */ strcpy (szTable, "Gamma table summary:"); for (i = 0; i < SANE_GAMMA_SIZE; i++) { if ((SANE_GAMMA_SIZE / 16) && (i % (SANE_GAMMA_SIZE / 16)) == 0) { DBG (DBG_MSG, "%s\n", szTable); szTable[0] = '\0'; } /* test for number print */ if ((SANE_GAMMA_SIZE / 64) && (i % (SANE_GAMMA_SIZE / 64)) == 0) { sprintf (szTable + strlen(szTable), " %04X", pi[i]); } } if (strlen (szTable)) { DBG (DBG_MSG, "%s\n", szTable); } break; case optMode: { SANE_Word *pCap; int fCapChanged = 0; pCap = &s->aOptions[optThreshold].cap; if (strcmp ((char const *) pVal, colorStr) == 0) { s->aValues[optMode].w = MODE_COLOR; fCapChanged = _ChangeCap (pCap, SANE_CAP_INACTIVE, 1); } if (strcmp ((char const *) pVal, grayStr) == 0) { s->aValues[optMode].w = MODE_GRAY; fCapChanged = _ChangeCap (pCap, SANE_CAP_INACTIVE, 1); } if (strcmp ((char const *) pVal, lineartStr) == 0) { s->aValues[optMode].w = MODE_LINEART; fCapChanged = _ChangeCap (pCap, SANE_CAP_INACTIVE, 0); } info |= SANE_INFO_RELOAD_PARAMS; if (fCapChanged) { info |= SANE_INFO_RELOAD_OPTIONS; } DBG (DBG_MSG, "setting scan mode: %s\n", (char const *) pVal); } break; #ifdef EXPERIMENTAL case optLamp: fVal = *(SANE_Bool *) pVal; DBG (DBG_MSG, "lamp %s\n", fVal ? "on" : "off"); if (fVal) _WarmUpLamp (s, WARMUP_INSESSION); else SetLamp (&s->HWParams, SANE_FALSE); break; case optCalibrate: /* SimpleCalib(&s->HWParams); */ break; #endif default: DBG (DBG_ERR, "SANE_ACTION_SET_VALUE: Invalid option (%d)\n", n); } if (pInfo != NULL) { *pInfo |= info; } break; case SANE_ACTION_SET_AUTO: return SANE_STATUS_UNSUPPORTED; default: DBG (DBG_ERR, "Invalid action (%d)\n", Action); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p) { TScanner *s; TModeParam const *pMode; DBG (DBG_MSG, "sane_get_parameters\n"); s = (TScanner *) h; /* first do some checks */ if (s->aValues[optTLX].w >= s->aValues[optBRX].w) { DBG (DBG_ERR, "TLX should be smaller than BRX\n"); return SANE_STATUS_INVAL; /* proper error code? */ } if (s->aValues[optTLY].w >= s->aValues[optBRY].w) { DBG (DBG_ERR, "TLY should be smaller than BRY\n"); return SANE_STATUS_INVAL; /* proper error code? */ } pMode = &modeParam[s->aValues[optMode].w]; /* return the data */ p->format = pMode->format; p->last_frame = SANE_TRUE; p->lines = MM_TO_PIXEL (s->aValues[optBRY].w - s->aValues[optTLY].w, s->aValues[optDPI].w); p->depth = pMode->depth; p->pixels_per_line = MM_TO_PIXEL (s->aValues[optBRX].w - s->aValues[optTLX].w, s->aValues[optDPI].w); p->bytes_per_line = pMode->bytesPerLine (p->pixels_per_line); return SANE_STATUS_GOOD; } /* get the scale down factor for a resolution that is not supported by hardware */ static int _SaneEmulateScaling (int iDpi) { if (iDpi == 75) return 2; else return 1; } SANE_Status sane_start (SANE_Handle h) { TScanner *s; SANE_Parameters par; int iLineCorr; int iScaleDown; static unsigned char abGamma[HW_GAMMA_SIZE]; static unsigned char abCalibTable[HW_PIXELS * 6]; DBG (DBG_MSG, "sane_start\n"); s = (TScanner *) h; if (sane_get_parameters (h, &par) != SANE_STATUS_GOOD) { DBG (DBG_MSG, "Invalid scan parameters\n"); return SANE_STATUS_INVAL; } iScaleDown = _SaneEmulateScaling (s->aValues[optDPI].w); s->iLinesLeft = par.lines; /* fill in the scanparams using the option values */ s->ScanParams.iDpi = s->aValues[optDPI].w * iScaleDown; s->ScanParams.iLpi = s->aValues[optDPI].w * iScaleDown; /* calculate correction for filling of circular buffer */ iLineCorr = 3 * s->HWParams.iSensorSkew; /* usually 16 motor steps */ /* calculate correction for garbage lines */ iLineCorr += s->HWParams.iSkipLines * (HW_LPI / s->ScanParams.iLpi); s->ScanParams.iTop = MM_TO_PIXEL (s->aValues[optTLY].w + s->HWParams.iTopLeftY, HW_LPI) - iLineCorr; s->ScanParams.iLeft = MM_TO_PIXEL (s->aValues[optTLX].w + s->HWParams.iTopLeftX, HW_DPI); s->ScanParams.iWidth = par.pixels_per_line * iScaleDown; s->ScanParams.iHeight = par.lines * iScaleDown; s->ScanParams.iBottom = HP3300C_BOTTOM; s->ScanParams.fCalib = SANE_FALSE; /* perform a simple calibration just before scanning */ _WaitForLamp (s, abCalibTable); if (s->aValues[optMode].w == MODE_LINEART) { /* use a unity gamma table for lineart to be independent from Gamma settings */ _UnityGammaTable (abGamma); } else { /* copy gamma table */ _ConvertGammaTable (s->aGammaTable, abGamma); } WriteGammaCalibTable (abGamma, abGamma, abGamma, abCalibTable, 0, 0, &s->HWParams); /* prepare the actual scan */ if (!InitScan (&s->ScanParams, &s->HWParams)) { DBG (DBG_MSG, "Invalid scan parameters\n"); return SANE_STATUS_INVAL; } /* init data pipe */ s->DataPipe.iSkipLines = s->HWParams.iSkipLines; /* on the hp3400 and hp4300 we cannot set the top of the scan area (yet), so instead we just scan and throw away the data until the top */ if (s->HWParams.fReg07) { s->DataPipe.iSkipLines += MM_TO_PIXEL (s->aValues[optTLY].w + s->HWParams.iTopLeftY, s->aValues[optDPI].w * iScaleDown); } s->iBytesLeft = 0; s->iPixelsPerLine = par.pixels_per_line; /* hack */ s->DataPipe.pabLineBuf = (unsigned char *) malloc (HW_PIXELS * 3); CircBufferInit (s->HWParams.iXferHandle, &s->DataPipe, par.pixels_per_line, s->ScanParams.iHeight, s->ScanParams.iLpi * s->HWParams.iSensorSkew / HW_LPI, s->HWParams.iReversedHead, iScaleDown, iScaleDown); s->fScanning = SANE_TRUE; s->fCancelled = SANE_FALSE; return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) { TScanner *s; TDataPipe *p; TModeParam const *pMode; DBG (DBG_MSG, "sane_read: buf=%p, maxlen=%d, ", buf, maxlen); s = (TScanner *) h; pMode = &modeParam[s->aValues[optMode].w]; /* sane_read only allowed after sane_start */ if (!s->fScanning) { if (s->fCancelled) { DBG (DBG_MSG, "\n"); DBG (DBG_MSG, "sane_read: sane_read cancelled\n"); s->fCancelled = SANE_FALSE; return SANE_STATUS_CANCELLED; } else { DBG (DBG_ERR, "sane_read: sane_read only allowed after sane_start\n"); return SANE_STATUS_INVAL; } } p = &s->DataPipe; /* anything left to read? */ if ((s->iLinesLeft == 0) && (s->iBytesLeft == 0)) { CircBufferExit (p); free (p->pabLineBuf); p->pabLineBuf = NULL; FinishScan (&s->HWParams); *len = 0; DBG (DBG_MSG, "\n"); DBG (DBG_MSG, "sane_read: end of scan\n"); s->fCancelled = SANE_FALSE; s->fScanning = SANE_FALSE; return SANE_STATUS_EOF; } /* time to read the next line? */ if (s->iBytesLeft == 0) { /* read a line from the transfer buffer */ if (CircBufferGetLineEx (s->HWParams.iXferHandle, p, p->pabLineBuf, s->HWParams.iReversedHead, SANE_TRUE)) { pMode->adaptFormat (p->pabLineBuf, s->iPixelsPerLine, s->aValues[optThreshold].w); s->iBytesLeft = pMode->bytesPerLine (s->iPixelsPerLine); s->iLinesLeft--; } /* stop scanning further, when the read action fails because we try read after the end of the buffer */ else { FinishScan (&s->HWParams); CircBufferExit (p); free (p->pabLineBuf); p->pabLineBuf = NULL; *len = 0; DBG (DBG_MSG, "\n"); DBG (DBG_MSG, "sane_read: read after end of buffer\n"); s->fCancelled = SANE_FALSE; s->fScanning = SANE_FALSE; return SANE_STATUS_EOF; } } /* copy (part of) a line */ *len = MIN (maxlen, s->iBytesLeft); memcpy (buf, &p->pabLineBuf[pMode->bytesPerLine (s->iPixelsPerLine) - s->iBytesLeft], *len); s->iBytesLeft -= *len; DBG (DBG_MSG, " read=%d \n", *len); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle h) { TScanner *s; DBG (DBG_MSG, "sane_cancel\n"); s = (TScanner *) h; /* Make sure the scanner head returns home */ FinishScan (&s->HWParams); /* delete allocated data */ if (s->fScanning) { CircBufferExit (&s->DataPipe); free (s->DataPipe.pabLineBuf); s->DataPipe.pabLineBuf = NULL; DBG (DBG_MSG, "sane_cancel: freeing buffers\n"); } s->fCancelled = SANE_TRUE; s->fScanning = SANE_FALSE; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ h, SANE_Bool m) { DBG (DBG_MSG, "sane_set_io_mode %s\n", m ? "non-blocking" : "blocking"); if (m) { return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ * fd) { DBG (DBG_MSG, "sane_select_fd\n"); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/umax-uc1200s.c0000664000175000017500000001050612112021330015005 00000000000000 /* ------------------------------------------------------------------------- */ /* umax-uc1200s.c: inquiry for UMAX scanner uc1200s (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------- */ #include "umax-scanner.h" /* ------------------------------------------------------------------------- */ static unsigned char UC1200S_INQUIRY[] = { #define UC1200S_INQUIRY_LEN 0x9d /* 24 F/W support function */ 0x03, /* 25 -27 exposure-times */ 0x00, 0x00, 0x00, /* 28 - 29 reserved */ 0x00, 0x00, /* 2a - 35 exposure times */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 37 reserved */ 0x00, 0x00, /* 38 - 5f scsi reserved */ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, /* 60 -62 scanner capability*/ 0x2f, 0x0c, 0x07, /* 63 reserved */ 0x00, /* 64 gamma */ 0xa3, /* 65 reserved */ 0x00, /* 66 GIB */ 0x01, /* 67 reserved */ 0x00, /* 68 GOB */ 0x01, /* 69 - 6a halftone */ 0x0c, 0x2f, /* 6b - 6c reserved */ 0x00, 0x00, /* 6d color sequence */ 0xe8, /* 0xe9 or 0xe1 ? */ /* 6e - 71 video memory */ 0x00, 0x04, 0x00, 0x00, /* 72 reserved */ 0x00, /* 73 max optical res in 100 dpi */ 0x06, /* 74 max x_res in 100 dpi */ 0x0c, /* 75 max y_res in 100 dpi */ 0x0c, /* 76-77 fb max scan width in 0.01 inch */ 0x03, 0x20, /* 78-79 fb max scan length in 0.01 inch */ 0x04, 0x9c, /* 7a-7b uta x original point, may be 0x05, 0x89 */ 0x00, 0x76, /* 7c-7d uta y original point, may be 0x06, 0x75 */ 0x00, 0x89, /* 7e-7f uta max scan width in 0.01 inch */ 0x02, 0x4e, /* 80-81 uta max scan length in 0.01 inch */ 0x03, 0x65, /* 82-85 reserved */ 00, 00, 00, 00, /* 86-87 dor x original point */ 0x00, 0x00, /* 88-89 dor x original point */ 0x00, 0x00, /* 8a-8b dor max scan width in 0.01 inch */ 0x00, 0x00, /* 8c-8d dor max scan length in 0.01 inch */ 0x00, 0x00, /* 8e reserved */ 0x00, /* 8f last calibration lamp density */ 0x00, /* 90 reserved */ 0x00, /* 91 lamp warmup max time */ 0x00, /* 92-93 window descriptor block length */ 0x00, 0x30, /* 94 optical resolution residue (1dpi) */ 0x00, /* 95 x_resolution residue (1dpi) */ 0x00, /* 96 y_resolution residue (1dpi) */ 0x00, /* 97 analog gamma table */ 0x00, /* 98-99 reserved */ 0x00, 0x00, /* 9a max calibration data lines */ 0x00, /* 9b fb/uta colour-sequnce-mode */ 0x01, /* 9c adf colour-sequnce-mode */ 0x01, /* 9d line-distance of ccd */ 0x08 }; static inquiry_blk inquiry_uc1200s = { "UC1200S ",UC1200S_INQUIRY, UC1200S_INQUIRY_LEN }; sane-backends-1.0.27/backend/snapscan-mutex.c0000664000175000017500000001171012775312261015731 00000000000000/* Mutex implementation for SnapScan backend Copyright (C) 2000, 2004 Henrik Johansson, Oliver Schwartz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice.*/ #if defined __BEOS__ #include #define snapscan_mutex_t sem_id static int snapscani_mutex_open(snapscan_mutex_t* a_sem, const char* dev __sane_unused__) { *a_sem = create_sem(1, "snapscan_mutex"); return 1; } static void snapscani_mutex_close(snapscan_mutex_t* a_sem) { delete_sem(*a_sem); } static void snapscani_mutex_lock(snapscan_mutex_t* a_sem) { acquire_sem(*a_sem); } static void snapscani_mutex_unlock(snapscan_mutex_t* a_sem) { release_sem(*a_sem); } #elif defined USE_PTHREAD || defined HAVE_OS2_H #include #define snapscan_mutex_t pthread_mutex_t static int snapscani_mutex_open(snapscan_mutex_t* sem_id, const char* dev __sane_unused__) { pthread_mutex_init(sem_id, NULL); return 1; } static void snapscani_mutex_close(snapscan_mutex_t* sem_id) { pthread_mutex_destroy(sem_id); } static void snapscani_mutex_lock(snapscan_mutex_t* sem_id) { pthread_mutex_lock(sem_id); } static void snapscani_mutex_unlock(snapscan_mutex_t* sem_id) { pthread_mutex_unlock(sem_id); } #else /* defined USE_PTHREAD || defined HAVE_OS2_H */ #include #include #include #include #define snapscan_mutex_t int /* check for union semun */ #if defined(HAVE_UNION_SEMUN) /* union semun is defined by including */ #else /* according to X/OPEN we have to define it ourselves */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ unsigned short int *array; /* array for GETALL, SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; #endif /* defined HAVE_UNION_SEMUN */ static struct sembuf sem_wait = { 0, -1, 0 }; static struct sembuf sem_signal = { 0, 1, 0 }; static unsigned int snapscani_bernstein(const unsigned char* str) { unsigned int hash = 5381; /* some arbitrary number */ int c; while (*str) { c = *str++; hash = ((hash << 5) + hash) + c; } return hash; } static int snapscani_mutex_open(snapscan_mutex_t* sem_id, const char* dev) { static const char *me = "snapscani_mutex_open"; key_t ipc_key = -1; if (strstr(dev, "libusb:") == dev) { key_t ipc_key = (key_t) snapscani_bernstein((const unsigned char*) dev+7); DBG (DL_INFO, "%s: using IPC key 0x%08x for device %s\n", me, ipc_key, dev); } else { ipc_key = ftok(dev, 0x12); if (ipc_key == -1) { DBG (DL_MAJOR_ERROR, "%s: could not obtain IPC key for device %s: %s\n", me, dev, strerror(errno)); return 0; } } *sem_id = semget( ipc_key, 1, IPC_CREAT | 0660 ); if (*sem_id == -1) { DBG (DL_MAJOR_ERROR, "%s: semget failed: %s\n", me, strerror(errno)); return 0; } semop(*sem_id, &sem_signal, 1); return 1; } static void snapscani_mutex_close(snapscan_mutex_t* sem_id) { static union semun dummy_semun_arg; semctl(*sem_id, 0, IPC_RMID, dummy_semun_arg); } static void snapscani_mutex_lock(snapscan_mutex_t* sem_id) { semop(*sem_id, &sem_wait, 1); } static void snapscani_mutex_unlock(snapscan_mutex_t* sem_id) { semop(*sem_id, &sem_signal, 1); } #endif /* defined USE_PTHREAD || defined HAVE_OS2_H */ sane-backends-1.0.27/backend/umax.c0000664000175000017500000107634413106201017013735 00000000000000/* --------------------------------------------------------------------------------------------------------- */ /* sane - Scanner Access Now Easy. umax.c (C) 1997-2007 Oliver Rauch This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for UMAX flatbed scanners. */ /* --------------------------------------------------------------------------------------------------------- */ #define BUILD 45 /* --------------------------------------------------------------------------------------------------------- */ /* SANE-FLOW-DIAGRAMM - sane_init() : initialize backend, attach scanners(devicename,0) . - sane_get_devices() : query list of scanner-devices . - sane_open() : open a particular scanner-device and attach_scanner(devicename,&dev) . . - sane_set_io_mode : set blocking-mode . . - sane_get_select_fd : get scanner-fd . . - sane_get_option_descriptor() : get option information . . - sane_control_option() : change option values . . . . - sane_start() : start image aquisition . . - sane_get_parameters() : returns actual scan-parameters . . - sane_read() : read image-data (from pipe) in ADF mode this is done often: . . - sane_start() : start image aquisition . . - sane_get_parameters() : returns actual scan-parameters . . - sane_read() : read image-data (from pipe) . . - sane_cancel() : cancel operation, kill reader_process . - sane_close() : close opened scanner-device, do_cancel, free buffer and handle - sane_exit() : terminate use of backend, free devicename and device-struture */ /* ------------------------------------------------------------ DBG OUTPUT LEVELS -------------------------- */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /* ------------------------------------------------------------ SANE DEFINES ------------------------------- */ #define BACKEND_NAME umax #define UMAX_CONFIG_FILE "umax.conf" /* ------------------------------------------------------------ SANE INTERNATIONALISATION ------------------ */ #ifndef SANE_I18N #define SANE_I18N(text) text #endif /* ------------------------------------------------------------ INCLUDES ----------------------------------- */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_thread.h" #ifdef UMAX_ENABLE_USB # include "sane/sanei_usb.h" #endif #include #include #include "umax-scsidef.h" #include "umax-scanner.c" #ifdef UMAX_ENABLE_USB # include "umax-usb.c" #endif #include "umax.h" /* ------------------------------------------------------------ SANE DEFINES ------------------------------- */ #ifndef PATH_MAX #define PATH_MAX 1024 #endif /* ------------------------------------------------------------ OPTION DEFINITIONS ------------------------- */ #define SANE_NAME_BATCH_SCAN_START "batch-scan-start" #define SANE_TITLE_BATCH_SCAN_START "Batch scan start" #define SANE_DESC_BATCH_SCAN_START "set for first scan of batch" #define SANE_NAME_BATCH_SCAN_LOOP "batch-scan-loop" #define SANE_TITLE_BATCH_SCAN_LOOP "Batch scan loop" #define SANE_DESC_BATCH_SCAN_LOOP "set for middle scans of batch" #define SANE_NAME_BATCH_SCAN_END "batch-scan-end" #define SANE_TITLE_BATCH_SCAN_END "Batch scan end" #define SANE_DESC_BATCH_SCAN_END "set for last scan of batch" #define SANE_NAME_BATCH_NEXT_TL_Y "batch-scan-next-tl-y" #define SANE_TITLE_BATCH_NEXT_TL_Y "Batch scan next top left Y" #define SANE_DESC_BATCH_NEXT_TL_Y "Set top left Y position for next scan" #define SANE_UMAX_NAME_SELECT_CALIBRATON_EXPOSURE_TIME "select-calibration-exposure-time" #define SANE_UMAX_TITLE_SELECT_CALIBRATION_EXPOSURE_TIME "Set calibration exposure time" #define SANE_UMAX_DESC_SELECT_CALIBRATION_EXPOSURE_TIME "Allow different settings for calibration and scan exposure times" /* ------------------------------------------------------------ STRING DEFINITIONS ------------------------- */ #define FLB_STR SANE_I18N("Flatbed") #define UTA_STR SANE_I18N("Transparency Adapter") #define ADF_STR SANE_I18N("Automatic Document Feeder") #define LINEART_STR SANE_VALUE_SCAN_MODE_LINEART #define HALFTONE_STR SANE_VALUE_SCAN_MODE_HALFTONE #define GRAY_STR SANE_VALUE_SCAN_MODE_GRAY #define COLOR_LINEART_STR SANE_VALUE_SCAN_MODE_COLOR_LINEART #define COLOR_HALFTONE_STR SANE_VALUE_SCAN_MODE_COLOR_HALFTONE #define COLOR_STR SANE_VALUE_SCAN_MODE_COLOR /* ------------------------------------------------------------ DEFINITIONS -------------------------------- */ #define P_200_TO_255(per) ( (SANE_UNFIX(per) + 100) * 255/200 ) #define P_100_TO_255(per) SANE_UNFIX(per * 255/100 ) #define P_100_TO_254(per) 1+SANE_UNFIX(per * 254/100 ) /* ------------------------------------------------------------ GLOBAL VARIABLES --------------------------- */ static SANE_String scan_mode_list[7]; static SANE_String_Const source_list[4]; static SANE_Int bit_depth_list[9]; static SANE_Auth_Callback frontend_authorize_callback; static int umax_scsi_buffer_size_min = 32768; /* default: minimum scsi buffer size: 32 KB */ static int umax_scsi_buffer_size_max = 131072; /* default: maximum scsi buffer size: 128 KB */ /* number of lines that shall be scanned in one buffer for preview if possible */ /* this value should not be too large because it defines the step size in which */ /* the scanned parts are displayed while preview scan is in progress */ static int umax_preview_lines = 10; /* default: 10 preview lines */ /* number of lines that shall be scanned in one buffer for scan if possible */ static int umax_scan_lines = 40; /* default: 40 scan lines */ static int umax_scsi_maxqueue = 2; /* use command queueing depth 2 as default */ static int umax_handle_bad_sense_error = 0; /* default: handle bad sense error code as device busy */ static int umax_execute_request_sense = 0; /* default: do not use request sense in do_calibration */ static int umax_force_preview_bit_rgb = 0; /* default: do not force preview bit in real color scan */ static int umax_slow = -1; /* don`t use slow scanning speed */ static int umax_smear = -1; /* don`t care about image smearing problem */ static int umax_calibration_area = -1; /* -1=auto, 0=calibration on image, 1=calibration for full ccd */ static int umax_calibration_width_offset = -99999; /* -99999=auto */ static int umax_calibration_width_offset_batch = -99999; /* -99999=auto */ static int umax_calibration_bytespp = -1; /* -1=auto */ static int umax_exposure_time_rgb_bind = -1; /* -1=auto */ static int umax_invert_shading_data = -1; /* -1=auto */ static int umax_lamp_control_available = 0; /* 0=disabled */ static int umax_gamma_lsb_padded = -1; /* -1=auto */ static int umax_connection_type = 1; /* 1=scsi, 2=usb */ /* ------------------------------------------------------------ CALIBRATION MODE --------------------------- */ #ifdef UMAX_CALIBRATION_MODE_SELECTABLE #define CALIB_MODE_0000 SANE_I18N("Use Image Composition") #define CALIB_MODE_1111 SANE_I18N("Bi-level black and white (lineart mode)") #define CALIB_MODE_1110 SANE_I18N("Dithered/halftone black & white (halftone mode)") #define CALIB_MODE_1101 SANE_I18N("Multi-level black & white (grayscale mode)") #define CALIB_MODE_1010 SANE_I18N("Multi-level RGB color (one pass color)") #define CALIB_MODE_1001 SANE_I18N("Ignore calibration") static SANE_String_Const calibration_list[] = { CALIB_MODE_0000, CALIB_MODE_1111, CALIB_MODE_1110, CALIB_MODE_1101, CALIB_MODE_1010, CALIB_MODE_1001, 0 }; #endif /* --------------------------------------------------------------------------------------------------------- */ enum { UMAX_CALIBRATION_AREA_IMAGE = 0, UMAX_CALIBRATION_AREA_CCD }; static const SANE_Int pattern_dim_list[] = { 5, /* # of elements */ 2, 4, 6, 8, 12 }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 1 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static const SANE_Range percentage_range_100 = { 0 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 0 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static int num_devices = 0; static const SANE_Device **devlist = NULL; static Umax_Device *first_dev = NULL; static Umax_Scanner *first_handle = NULL; /* ------------------------------------------------------------ MATH-HELPERS ------------------------------- */ #define min(a, b) (((a)<(b))?(a):(b)) #define max(a, b) (((a)>(b))?(a):(b)) #define inrange(minimum, val, maximum) (min(maximum, max(val, minimum))) /* ------------------------------------------------------------ umax_test_little_endian -------------------- */ static SANE_Bool umax_test_little_endian(void) { SANE_Int testvalue = 255; unsigned char *firstbyte = (unsigned char *) &testvalue; if (*firstbyte == 255) { return SANE_TRUE; } return SANE_FALSE; } /* ------------------------------------------------------------ DBG_inq_nz --------------------------------- */ static void DBG_inq_nz(char *text, int flag) { if (flag != 0) { DBG(DBG_inquiry,"%s", text); } } /*------------------------------------------------------------- DBG_sense_nz ------------------------------- */ static void DBG_sense_nz(char *text, int flag) { if (flag != 0) { DBG(DBG_sense,"%s", text); } } /* ------------------------------------------------------------ UMAX PRINT INQUIRY ------------------------- */ static void umax_print_inquiry(Umax_Device *dev) { unsigned char *inquiry_block; int i; inquiry_block=dev->buffer[0]; DBG(DBG_inquiry,"INQUIRY:\n"); DBG(DBG_inquiry,"========\n"); DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"vendor........................: '%s'\n", dev->vendor); DBG(DBG_inquiry,"product.......................: '%s'\n", dev->product); DBG(DBG_inquiry,"version.......................: '%s'\n", dev->version); DBG(DBG_inquiry,"peripheral qualifier..........: %d\n", get_inquiry_periph_qual(inquiry_block)); DBG(DBG_inquiry,"peripheral device type........: %d\n", get_inquiry_periph_devtype(inquiry_block)); DBG_inq_nz("RMB bit set (reserved)\n", get_inquiry_rmb(inquiry_block)); DBG_inq_nz("0x01 bit 6\n", get_inquiry_0x01_bit6(inquiry_block)); DBG_inq_nz("0x01 bit 5\n", get_inquiry_0x01_bit5(inquiry_block)); DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"CBHS value range..............: %s\n", cbhs_str[dev->inquiry_cbhs]); DBG(DBG_inquiry,"scanmode......................: %s\n", scanmode_str[get_inquiry_scanmode(inquiry_block)]); if (dev->inquiry_transavail) { DBG(DBG_inquiry,"UTA (transparency)............: available\n"); if (get_inquiry_translamp(inquiry_block) == 0) { DBG(DBG_inquiry,"UTA lamp status ..............: off\n"); } else { DBG(DBG_inquiry,"UTA lamp status ..............: on\n"); } DBG(DBG_inquiry,"\n"); } DBG(DBG_inquiry,"inquiry block length..........: %d bytes\n", dev->inquiry_len); if (dev->inquiry_len<=0x8e) { DBG(DBG_inquiry, "Inquiry block is unexpected short, should be at least 147 bytes\n"); } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"ISO Version (reserved).......: %d\n", get_inquiry_iso_version(inquiry_block)); DBG(DBG_inquiry,"ECMA Version (reserved).......: %d\n", get_inquiry_ecma_version(inquiry_block)); DBG(DBG_inquiry,"ANSI Version .................: %d\n", get_inquiry_ansi_version(inquiry_block)); DBG(DBG_inquiry,"\n"); DBG_inq_nz("AENC bit set (reserved)\n", get_inquiry_aenc(inquiry_block)); DBG_inq_nz("TmIOP bit set (reserved)\n", get_inquiry_tmiop(inquiry_block)); DBG_inq_nz("0x03 bit 5\n", get_inquiry_0x03_bit5(inquiry_block)); DBG_inq_nz("0x03 bit 4\n", get_inquiry_0x03_bit4(inquiry_block)); DBG(DBG_inquiry,"reserved byte 0x05 = %d\n", get_inquiry_0x05(inquiry_block)); DBG(DBG_inquiry,"reserved byte 0x06 = %d\n", get_inquiry_0x06(inquiry_block)); DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"scsi features (%02x):\n", get_inquiry_scsi_byte(inquiry_block)); DBG(DBG_inquiry,"-------------------\n"); DBG_inq_nz(" - relative address\n", get_inquiry_scsi_reladr(inquiry_block)); DBG_inq_nz(" - wide bus 32 bit\n", get_inquiry_scsi_wbus32(inquiry_block)); DBG_inq_nz(" - wide bus 16 bit\n", get_inquiry_scsi_wbus16(inquiry_block)); DBG_inq_nz(" - synchronous neg.\n", get_inquiry_scsi_sync(inquiry_block)); DBG_inq_nz(" - linked commands\n", get_inquiry_scsi_linked(inquiry_block)); DBG_inq_nz(" - (reserved)\n", get_inquiry_scsi_R(inquiry_block)); DBG_inq_nz(" - command queueing\n", get_inquiry_scsi_cmdqueue(inquiry_block)); DBG_inq_nz(" - sftre\n", get_inquiry_scsi_sftre(inquiry_block)); /* 0x24 */ if (dev->inquiry_len<=0x24) { return; } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"f/w support function:\n"); DBG(DBG_inquiry,"---------------------\n"); DBG_inq_nz(" - quality calibration\n", dev->inquiry_quality_ctrl); DBG_inq_nz(" - fast preview function\n", dev->inquiry_preview); DBG_inq_nz(" - shadow compensation by f/w\n", get_inquiry_fw_shadow_comp(inquiry_block)); DBG_inq_nz(" - reselection phase\n", get_inquiry_fw_reselection(inquiry_block)); DBG_inq_nz(" - lamp intensity control\n", dev->inquiry_lamp_ctrl); DBG_inq_nz(" - batch scan function\n", get_inquiry_fw_batch_scan(inquiry_block)); DBG_inq_nz(" - calibration mode control by driver\n", get_inquiry_fw_calibration(inquiry_block)); /* 0x36, 0x37 */ DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"reserved byte 0x36 = %d\n", get_inquiry_0x36(inquiry_block)); DBG(DBG_inquiry,"reserved byte 0x37 = %d\n", get_inquiry_0x37(inquiry_block)); if (get_inquiry_fw_adjust_exposure_tf(inquiry_block)) { int unit; DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"adjust exposure time function\n"); unit=get_inquiry_exposure_time_step_unit(inquiry_block); DBG(DBG_inquiry,"exposure time step units......: %d micro-sec\n", unit); DBG(DBG_inquiry,"exposure time maximum.........: %d micro-sec\n", unit*get_inquiry_exposure_time_max(inquiry_block)); DBG(DBG_inquiry,"exposure time minimum (LHG)...: %d micro-sec\n", unit*get_inquiry_exposure_time_lhg_min(inquiry_block)); DBG(DBG_inquiry,"exposure time minimum color...: %d micro-sec\n", unit*get_inquiry_exposure_time_color_min(inquiry_block)); DBG(DBG_inquiry,"exposure time default FB (LH).: %d micro-sec\n", unit*get_inquiry_exposure_time_lh_def_fb(inquiry_block)); DBG(DBG_inquiry,"exposure time default UTA (LH): %d micro-sec\n", unit*get_inquiry_exposure_time_lh_def_uta(inquiry_block)); DBG(DBG_inquiry,"exposure time default FB gray.: %d micro-sec\n", unit*get_inquiry_exposure_time_gray_def_fb(inquiry_block)); DBG(DBG_inquiry,"exposure time default UTA gray: %d micro-sec\n", unit*get_inquiry_exposure_time_gray_def_uta(inquiry_block)); DBG(DBG_inquiry,"exposure time default FB red..: %d micro-sec\n", unit*get_inquiry_exposure_time_def_r_fb(inquiry_block)); DBG(DBG_inquiry,"exposure time default FB grn..: %d micro-sec\n", unit*get_inquiry_exposure_time_def_g_fb(inquiry_block)); DBG(DBG_inquiry,"exposure time default FB blue.: %d micro-sec\n", unit*get_inquiry_exposure_time_def_b_fb(inquiry_block)); DBG(DBG_inquiry,"exposure time default UTA red.: %d micro-sec\n", unit*get_inquiry_exposure_time_def_r_uta(inquiry_block)); DBG(DBG_inquiry,"exposure time default UTA grn.: %d micro-sec\n", unit*get_inquiry_exposure_time_def_g_uta(inquiry_block)); DBG(DBG_inquiry,"exposure time default UTA blue: %d micro-sec\n", unit*get_inquiry_exposure_time_def_b_uta(inquiry_block)); } /* 0x60 */ if (dev->inquiry_len<=0x60) { return; } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"scan modes (%02x):\n", get_inquiry_sc_feature_byte0(inquiry_block)); DBG(DBG_inquiry,"----------------\n"); DBG_inq_nz(" - three passes color mode\n", get_inquiry_sc_three_pass_color(inquiry_block)); DBG_inq_nz(" - single pass color mode\n", get_inquiry_sc_one_pass_color(inquiry_block)); DBG_inq_nz(" - lineart mode\n", dev->inquiry_lineart); DBG_inq_nz(" - halftone mode\n", dev->inquiry_halftone); DBG_inq_nz(" - gray mode\n", dev->inquiry_gray); DBG_inq_nz(" - color mode\n", dev->inquiry_color); DBG_inq_nz(" - transparency (UTA)\n", dev->inquiry_uta); DBG_inq_nz(" - automatic document feeder (ADF)\n", dev->inquiry_adf); /* 0x61 */ if (dev->inquiry_len<=0x61) { return; } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"scanner capability (%02x, %02x, %02x):\n", get_inquiry_sc_feature_byte1(inquiry_block), get_inquiry_sc_feature_byte2(inquiry_block), get_inquiry_sc_feature_byte3(inquiry_block)); DBG(DBG_inquiry,"--------------------------------\n"); DBG_inq_nz(" - double resolution\n", dev->inquiry_dor); DBG_inq_nz(" - send high byte first\n", get_inquiry_sc_high_byte_first(inquiry_block)); DBG_inq_nz(" - bi-level image reverse\n", dev->inquiry_reverse); DBG_inq_nz(" - multi-level image reverse\n", dev->inquiry_reverse_multi); DBG_inq_nz(" - support shadow function\n", dev->inquiry_shadow); DBG_inq_nz(" - support highlight function\n", dev->inquiry_highlight); DBG_inq_nz(" - f/w downloadable\n", get_inquiry_sc_downloadable_fw(inquiry_block)); DBG_inq_nz(" - paper length can reach to 14 inch\n", get_inquiry_sc_paper_length_14(inquiry_block)); /* 0x62 */ if (dev->inquiry_len<=0x62) { return; } DBG_inq_nz(" - shading data/gain uploadable\n", get_inquiry_sc_uploadable_shade(inquiry_block)); DBG_inq_nz(" - analog gamma correction\n", dev->inquiry_analog_gamma); DBG_inq_nz(" - x, y coordinate base\n", get_inquiry_xy_coordinate_base(inquiry_block)); DBG_inq_nz(" - lineart starts with LSB\n", get_inquiry_lineart_order(inquiry_block)); DBG_inq_nz(" - start density \n", get_inquiry_start_density(inquiry_block)); DBG_inq_nz(" - hardware x scaling\n", get_inquiry_hw_x_scaling(inquiry_block)); DBG_inq_nz(" - hardware y scaling\n", get_inquiry_hw_y_scaling(inquiry_block)); /* 0x63 */ if (dev->inquiry_len<=0x63) { return; } DBG_inq_nz(" + ADF: no paper\n", get_inquiry_ADF_no_paper(inquiry_block)); DBG_inq_nz(" + ADF: cover open\n", get_inquiry_ADF_cover_open(inquiry_block)); DBG_inq_nz(" + ADF: paper jam\n", get_inquiry_ADF_paper_jam(inquiry_block)); DBG_inq_nz(" - unknown flag; 0x63 bit 3\n", get_inquiry_0x63_bit3(inquiry_block)); DBG_inq_nz(" - unknown lfag: 0x63 bit 4\n", get_inquiry_0x63_bit4(inquiry_block)); DBG_inq_nz(" - lens calib in doc pos\n", get_inquiry_lens_cal_in_doc_pos(inquiry_block)); DBG_inq_nz(" - manual focus\n", get_inquiry_manual_focus(inquiry_block)); DBG_inq_nz(" - UTA lens calib pos selectable\n", get_inquiry_sel_uta_lens_cal_pos(inquiry_block)); /* 0x64 - 0x68*/ if (dev->inquiry_len<=0x68) { return; } if (dev->inquiry_gamma_dwload) { DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"gamma download available\n"); DBG_inq_nz("gamma download type 2\n", get_inquiry_gamma_type_2(inquiry_block)); DBG(DBG_inquiry,"lines of gamma curve: %s\n", gamma_lines_str[get_inquiry_gamma_lines(inquiry_block)]); /* 0x66 */ DBG_inq_nz("gamma input 8 bits/pixel support\n", get_inquiry_gib_8bpp(inquiry_block)); DBG_inq_nz("gamma input 9 bits/pixel support\n", get_inquiry_gib_9bpp(inquiry_block)); DBG_inq_nz("gamma input 10 bits/pixel support\n", get_inquiry_gib_10bpp(inquiry_block)); DBG_inq_nz("gamma input 12 bits/pixel support\n", get_inquiry_gib_12bpp(inquiry_block)); DBG_inq_nz("gamma input 14 bits/pixel support\n", get_inquiry_gib_14bpp(inquiry_block)); DBG_inq_nz("gamma input 16 bits/pixel support\n", get_inquiry_gib_16bpp(inquiry_block)); DBG_inq_nz("0x66 bit 6\n", get_inquiry_0x66_bit6(inquiry_block)); DBG_inq_nz("0x66 bit 7\n", get_inquiry_0x66_bit7(inquiry_block)); /* 0x68 */ DBG_inq_nz("gamma output 8 bits/pixel support\n", get_inquiry_gob_8bpp(inquiry_block)); DBG_inq_nz("gamma output 9 bits/pixel support\n", get_inquiry_gob_9bpp(inquiry_block)); DBG_inq_nz("gamma output 10 bits/pixel support\n", get_inquiry_gob_10bpp(inquiry_block)); DBG_inq_nz("gamma output 12 bits/pixel support\n", get_inquiry_gob_12bpp(inquiry_block)); DBG_inq_nz("gamma output 14 bits/pixel support\n", get_inquiry_gob_14bpp(inquiry_block)); DBG_inq_nz("gamma output 16 bits/pixel support\n", get_inquiry_gob_16bpp(inquiry_block)); DBG_inq_nz("0x68 bit 6\n", get_inquiry_0x68_bit6(inquiry_block)); DBG_inq_nz("0x68 bit 7\n", get_inquiry_0x68_bit7(inquiry_block)); } /* 0x64 - 0x68 reserved bits */ DBG_inq_nz("0x64 bit 2\n", get_inquiry_0x64_bit2(inquiry_block)); DBG_inq_nz("0x64 bit 3\n", get_inquiry_0x64_bit3(inquiry_block)); DBG_inq_nz("0x64 bit 4\n", get_inquiry_0x64_bit4(inquiry_block)); DBG_inq_nz("0x64 bit 6\n", get_inquiry_0x64_bit6(inquiry_block)); DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"reserved byte 0x65 = %d\n", get_inquiry_0x65(inquiry_block)); DBG(DBG_inquiry,"reserved byte 0x67 = %d\n", get_inquiry_0x67(inquiry_block)); /* 0x69 */ if (dev->inquiry_len<=0x69) { return; } DBG(DBG_inquiry,"\n"); if (get_inquiry_hda(inquiry_block)) { DBG(DBG_inquiry,"halftone download available\n"); DBG(DBG_inquiry,"halftone pattern download max matrix %dx%d\n", get_inquiry_max_halftone_matrix(inquiry_block), get_inquiry_max_halftone_matrix(inquiry_block)); } /* 0x6a */ if (dev->inquiry_len<=0x6a) { return; } DBG_inq_nz("built-in halftone patterns:\n", get_inquiry_halftones_supported(inquiry_block)); DBG_inq_nz("built-in halftone pattern size ............: 2x2\n", get_inquiry_halftones_2x2(inquiry_block)); DBG_inq_nz("built-in halftone pattern size ............: 4x4\n", get_inquiry_halftones_4x4(inquiry_block)); DBG_inq_nz("built-in halftone pattern size ............: 6x6\n", get_inquiry_halftones_6x6(inquiry_block)); DBG_inq_nz("built-in halftone pattern size ............: 8x8\n", get_inquiry_halftones_8x8(inquiry_block)); DBG_inq_nz("built-in halftone pattern size ............: 12x12\n", get_inquiry_halftones_12x12(inquiry_block)); /* 0x6b, 0x6c */ DBG(DBG_inquiry,"reserved byte 0x6b = %d\n", get_inquiry_0x6b(inquiry_block)); DBG(DBG_inquiry,"reserved byte 0x6c = %d\n", get_inquiry_0x6c(inquiry_block)); /* 0x6d */ if (dev->inquiry_len<=0x6d) { return; } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"color sequence............................: %s\n", color_sequence_str[get_inquiry_colorseq(inquiry_block)]); DBG_inq_nz("color ordering support....................: pixel\n", get_inquiry_color_order_pixel(inquiry_block)); DBG_inq_nz("color ordering support....................: line without CCD distance\n", get_inquiry_color_order_line_no_ccd(inquiry_block)); DBG_inq_nz("color ordering support....................: plane\n", get_inquiry_color_order_plane(inquiry_block)); DBG_inq_nz("color ordering support....................: line with CCD distance\n", get_inquiry_color_order_line_w_ccd(inquiry_block)); DBG_inq_nz("color ordering support....................: (reserved)\n", get_inquiry_color_order_reserved(inquiry_block)); /* 0x6e */ if (dev->inquiry_len<=0x71) { return; } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"maximum video memory......................: %d KB\n", dev->inquiry_vidmem/1024); /* 0x72 */ DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"reserved byte 0x72 = %d\n", get_inquiry_0x72(inquiry_block)); DBG(DBG_inquiry,"\n"); /* 0x73/0x94 - 0x75/0x96 */ if (dev->inquiry_len<=0x75) { return; } DBG(DBG_inquiry,"optical resolution........................: %d dpi\n", dev->inquiry_optical_res); DBG(DBG_inquiry,"maximum x-resolution......................: %d dpi\n", dev->inquiry_x_res); DBG(DBG_inquiry,"maximum y-resolution......................: %d dpi\n", dev->inquiry_y_res); /* ---------- */ /* 0x76 0x77 */ if (dev->inquiry_len<=0x77) { return; } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"FB (flatbed-mode):\n"); DBG(DBG_inquiry,"FB maximum scan width.....................: %2.2f inch\n", dev->inquiry_fb_width); DBG(DBG_inquiry,"FB maximum scan length....................: %2.2f inch\n", dev->inquiry_fb_length); /* ---------- */ /* 0x7a - 0x81 */ if (dev->inquiry_len<=0x81) { return; } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"UTA (transparency-mode):\n"); DBG(DBG_inquiry,"UTA x-original point......................: %2.2f inch\n", dev->inquiry_uta_x_off); DBG(DBG_inquiry,"UTA y-original point......................: %2.2f inch\n", dev->inquiry_uta_y_off); DBG(DBG_inquiry,"UTA maximum scan width....................: %2.2f inch\n", dev->inquiry_uta_width); DBG(DBG_inquiry,"UTA maximum scan length...................: %2.2f inch\n", dev->inquiry_uta_length); /* ---------- */ /* 0x82-0x85 */ DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"reserved byte 0x82 = %d\n", get_inquiry_0x82(inquiry_block)); /* ---------- */ /* 0x83/0xa0 - 0x85/0xa2 */ if (dev->inquiry_len<=0x85) { return; } DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"DOR (double optical resolution-mode):\n"); DBG(DBG_inquiry,"DOR optical resolution....................: %d dpi\n", dev->inquiry_dor_optical_res); DBG(DBG_inquiry,"DOR maximum x-resolution..................: %d dpi\n", dev->inquiry_dor_x_res); DBG(DBG_inquiry,"DOR maximum y-resolution..................: %d dpi\n", dev->inquiry_dor_y_res); /* 0x86 - 0x8d */ if (dev->inquiry_len<=0x8d) { return; } DBG(DBG_inquiry,"DOR x-original point......................: %2.2f inch\n", dev->inquiry_dor_x_off); DBG(DBG_inquiry,"DOR y-original point......................: %2.2f inch\n", dev->inquiry_dor_y_off); DBG(DBG_inquiry,"DOR maximum scan width....................: %2.2f inch\n", dev->inquiry_dor_width); DBG(DBG_inquiry,"DOR maximum scan length...................: %2.2f inch\n", dev->inquiry_dor_length); DBG(DBG_inquiry,"\n"); /* ---------- */ /* 0x8e */ DBG(DBG_inquiry,"reserved byte 0x8e = %d\n", get_inquiry_0x8e(inquiry_block)); DBG(DBG_inquiry,"\n"); /* ---------- */ /* 0x8f */ if (dev->inquiry_len<=0x8f) { return; } DBG(DBG_inquiry,"last calibration lamp density.............: %d\n", get_inquiry_last_calibration_lamp_density(inquiry_block)); /* 0x90 */ DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"reserved byte 0x90 = %d\n", get_inquiry_0x90(inquiry_block)); DBG(DBG_inquiry,"\n"); /* 0x91 */ if (dev->inquiry_len<=0x91) { return; } DBG(DBG_inquiry,"lamp warmup maximum time..................: %d sec\n", dev->inquiry_max_warmup_time); /* 0x92 0x93 */ if (dev->inquiry_len<=0x93) { return; } DBG(DBG_inquiry,"window descriptor block length............: %d bytes\n", get_inquiry_wdb_length(inquiry_block)); /* ----------------- */ /* 0x97 */ if (dev->inquiry_len<=0x97) { return; } if (get_inquiry_analog_gamma_table(inquiry_block) == 0) { DBG(DBG_inquiry,"no analog gamma function\n"); } else { DBG(DBG_inquiry,"mp 8832 analog gamma table\n"); } /* 0x98, 0x99 */ DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"reserved byte 0x98 = %d\n", get_inquiry_0x98(inquiry_block)); DBG(DBG_inquiry,"reserved byte 0x99 = %d\n", get_inquiry_0x99(inquiry_block)); DBG(DBG_inquiry,"\n"); /* 0x9a */ if (dev->inquiry_len<=0x9a) { return; } DBG(DBG_inquiry,"maximum calibration data lines for shading: %d\n", get_inquiry_max_calibration_data_lines(inquiry_block)); /* 0x9b */ if (dev->inquiry_len<=0x9b) { return; } DBG(DBG_inquiry,"fb/uta: color line arrangement mode.......: %d\n", get_inquiry_fb_uta_line_arrangement_mode(inquiry_block)); /* 0x9c */ if (dev->inquiry_len<=0x9c) { return; } DBG(DBG_inquiry,"adf: color line arrangement mode.......: %d\n", get_inquiry_adf_line_arrangement_mode(inquiry_block)); /* 0x9d */ if (dev->inquiry_len<=0x9d) { return; } DBG(DBG_inquiry,"CCD line distance.........................: %d\n", get_inquiry_CCD_line_distance(inquiry_block)); DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"reserved byte 0x9e = %d\n", get_inquiry_0x9e(inquiry_block)); /* 0xa2 following */ if (dev->inquiry_len<=0xa2) { return; } DBG(DBG_inquiry,"\n"); for(i=0xa3; iinquiry_len; i++) { DBG(DBG_inquiry,"unknown reserved byte 0x%x = %d\n", i, inquiry_block[i]); } } /* ------------------------------------------------------------ CBHS_CORRECT ------------------------------- */ static int umax_cbhs_correct(int minimum, int cbhs, int maximum) { int range = maximum - minimum + 1; if (range == 256) { return cbhs; } return (int)( (cbhs/256.0)*range + minimum ); } /* ------------------------------------------------------------ SENSE_HANDLER ------------------------------ */ static SANE_Status sense_handler(int scsi_fd, unsigned char *result, void *arg) /* is called by sanei_scsi */ { unsigned char asc, ascq, sensekey; int asc_ascq, len; Umax_Device *dev = arg; DBG(DBG_proc, "check condition sense handler (scsi_fd = %d)\n", scsi_fd); sensekey = get_RS_sense_key(result); asc = get_RS_ASC(result); ascq = get_RS_ASCQ(result); asc_ascq = (int)(256 * asc + ascq); len = 7 + get_RS_additional_length(result); if ( get_RS_error_code(result) != 0x70 ) { DBG(DBG_error, "invalid sense key error code (%d)\n", get_RS_error_code(result)); switch (dev->handle_bad_sense_error) { default: case 0: DBG(DBG_error, "=> handled as DEVICE BUSY!\n"); return SANE_STATUS_DEVICE_BUSY; case 1: DBG(DBG_error, "=> handled as ok!\n"); return SANE_STATUS_GOOD; case 2: DBG(DBG_error, "=> handled as i/o error!\n"); return SANE_STATUS_IO_ERROR; case 3: DBG(DBG_error, "=> ignored, sense handler does continue\n"); } } DBG(DBG_sense, "check condition sense: %s\n", sense_str[sensekey]); /* when we reach here then we have no valid data in buffer[0] */ /* but it may be helpful to have the result data in buffer[0] */ memset(dev->buffer[0], 0, rs_return_block_size); /* clear sense data buffer */ memcpy(dev->buffer[0], result, len+1); /* copy sense data to buffer */ if (len > 0x15) { int scanner_error = get_RS_scanner_error_code(result); if (scanner_error < 100) { DBG(DBG_sense, "-> %s (#%d)\n", scanner_error_str[scanner_error], scanner_error); } else { DBG(DBG_sense, "-> error %d\n", scanner_error); } } if (get_RS_ILI(result) != 0) { DBG(DBG_sense, "-> ILI-ERROR: requested data length is larger than actual length\n"); } switch(sensekey) { case 0x00: /* no sense */ return SANE_STATUS_GOOD; break; case 0x03: /* medium error */ if (asc_ascq == 0x1400) { DBG(DBG_sense, "-> misfeed, paper jam\n"); return SANE_STATUS_JAMMED; } else if (asc_ascq == 0x1401) { DBG(DBG_sense, "-> adf not ready\n"); return SANE_STATUS_NO_DOCS; } else { DBG(DBG_sense, "-> unknown medium error: asc=%d, ascq=%d\n", asc, ascq); } break; case 0x04: /* hardware error */ if (asc_ascq == 0x4000) { DBG(DBG_sense, "-> diagnostic error:\n"); if (len >= 0x13) { DBG_sense_nz(" dim light\n", get_RS_asb_dim_light(result)); DBG_sense_nz(" no light\n", get_RS_asb_no_light(result)); DBG_sense_nz(" sensor or motor error\n", get_RS_asb_sensor_motor(result)); DBG_sense_nz(" too light\n", get_RS_asb_too_light(result)); DBG_sense_nz(" calibration error\n", get_RS_asb_calibration(result)); DBG_sense_nz(" rom error\n", get_RS_asb_rom(result)); DBG_sense_nz(" ram error\n", get_RS_asb_ram(result)); DBG_sense_nz(" cpu error\n", get_RS_asb_cpu(result)); DBG_sense_nz(" scsi error\n", get_RS_asb_scsi(result)); DBG_sense_nz(" timer error\n", get_RS_asb_timer(result)); DBG_sense_nz(" filter motor error\n", get_RS_asb_filter_motor(result)); DBG_sense_nz(" dc adjust error\n", get_RS_asb_dc_adjust(result)); DBG_sense_nz(" uta home sensor or motor error\n", get_RS_asb_uta_sensor(result)); } } else { DBG(DBG_sense, "-> unknown hardware error: asc=%d, ascq=%d\n", asc, ascq); } return SANE_STATUS_IO_ERROR; break; case 0x05: /* illegal request */ if (asc_ascq == 0x2000) { DBG(DBG_sense, "-> invalid command operation code\n"); } else if (asc_ascq == 0x2400) { DBG(DBG_sense, "-> illegal field in CDB\n"); } else if (asc_ascq == 0x2500) { DBG(DBG_sense, "-> logical unit not supported\n"); } else if (asc_ascq == 0x2600) { DBG(DBG_sense, "-> invalid field in parameter list\n"); } else if (asc_ascq == 0x2c01) { DBG(DBG_sense, "-> too many windows specified\n"); } else if (asc_ascq == 0x2c02) { DBG(DBG_sense, "-> invalid combination of windows specified\n"); } else { DBG(DBG_sense, "-> illegal request: asc=%d, ascq=%d\n", asc, ascq); } if (len >= 0x11) { if (get_RS_SKSV(result) != 0) { if (get_RS_CD(result) == 0) { DBG(DBG_sense, "-> illegal parameter in CDB\n"); } else { DBG(DBG_sense, "-> illegal parameter is in the data parameters sent during data out phase\n"); } DBG(DBG_sense, "-> error detected in byte %d\n", get_RS_field_pointer(result)); } } return SANE_STATUS_IO_ERROR; break; case 0x06: /* unit attention */ if (asc_ascq == 0x2900) { DBG(DBG_sense, "-> power on, reset or bus device reset\n"); } else if (asc_ascq == 0x3f01) { DBG(DBG_sense, "-> microcode has been changed\n"); } else { DBG(DBG_sense, "-> unit attention: asc=%d, ascq=%d\n", asc, ascq); } break; case 0x09: /* vendor specific */ if (asc == 0x00) { DBG(DBG_sense, "-> button protocol\n"); if (ascq & 1) { dev->button0_pressed = 1; DBG(DBG_sense, "-> button 0 pressed\n"); } if (ascq & 2) { dev->button1_pressed = 1; DBG(DBG_sense, "-> button 1 pressed\n"); } if (ascq & 4) { dev->button2_pressed = 1; DBG(DBG_sense, "-> button 2 pressed\n"); } return SANE_STATUS_GOOD; } else if (asc_ascq == 0x8001) { DBG(DBG_sense, "-> lamp warmup\n"); return SANE_STATUS_DEVICE_BUSY; } else if (asc_ascq == 0x8002) { DBG(DBG_sense, "-> calibration by driver\n"); if (dev) { dev->do_calibration = 1; /* set flag for calibration by driver */ } return SANE_STATUS_GOOD; } else { DBG(DBG_sense, "-> vendor specific sense-code: asc=%d, ascq=%d\n", asc, ascq); } break; } return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ UMAX SET RGB BIND -------------------------- */ static void umax_set_rgb_bind(Umax_Scanner *scanner) { if ( (scanner->val[OPT_RGB_BIND].w == SANE_FALSE) && (strcmp(scanner->val[OPT_MODE].s, COLOR_STR) == 0) ) /* enable rgb options */ { if (scanner->device->inquiry_analog_gamma) { scanner->opt[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_B].cap &= ~SANE_CAP_INACTIVE; } if (scanner->device->inquiry_highlight) { scanner->opt[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_B].cap &= ~SANE_CAP_INACTIVE; } if (scanner->device->inquiry_shadow) { scanner->opt[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_B].cap &= ~SANE_CAP_INACTIVE; } } else /* only show gray options */ { if (scanner->device->inquiry_analog_gamma) { scanner->opt[OPT_ANALOG_GAMMA].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE; } if (scanner->device->inquiry_highlight) { scanner->opt[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; } if (scanner->device->inquiry_shadow) { scanner->opt[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; } } if ( (scanner->device->inquiry_exposure_adj) && (scanner->val[OPT_SELECT_EXPOSURE_TIME].w) ) { if ( (scanner->val[OPT_RGB_BIND].w == SANE_FALSE) && (!scanner->device->exposure_time_rgb_bind) && (strcmp(scanner->val[OPT_MODE].s, COLOR_STR) == 0) ) /* enable rgb exposure time options */ { if (scanner->val[OPT_SELECT_CAL_EXPOSURE_TIME].w) /* exposure time setting for calibration enabled */ { scanner->opt[OPT_CAL_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_B].cap &= ~SANE_CAP_INACTIVE; } else /* no separate settings for calibration exposure times */ { scanner->opt[OPT_CAL_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_SCAN_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_B].cap &= ~SANE_CAP_INACTIVE; } else /* enable gray exposure time options */ { if (scanner->val[OPT_SELECT_CAL_EXPOSURE_TIME].w) /* exposure time setting for calibration enabled */ { scanner->opt[OPT_CAL_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; } else /* no separate settings for calibration exposure times */ { scanner->opt[OPT_CAL_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_CAL_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; } } } /* ------------------------------------------------------------ UMAX CALCULATE PIXELS ---------------------- */ static int umax_calculate_pixels(int scansize_pixel, int resolution, int resolution_base, int coordinate_base) /* scansize_pixel = size in pixels at 1200 dpi */ /* resolution = scan resolution */ /* resolution_base = this is the optical resolution * 1 or * 2 */ /* coordinate_base = this is 1200 dpi */ { unsigned int intsize_inch, intsize_pixel, diffsize_pixel, missing_pixels, del_pixel_1, pix; int toomuch; intsize_inch = scansize_pixel / coordinate_base; /* full inches */ intsize_pixel = intsize_inch * resolution; /* pixels in full inches */ diffsize_pixel = scansize_pixel % coordinate_base; /* missing pixels in last inch at 1200 dpi */ missing_pixels = diffsize_pixel * resolution_base / coordinate_base; /* missing pixels at resolution_base dpi */ del_pixel_1 = resolution_base - resolution; /* pixels to erase in one inch */ toomuch = 0; /* number of pixels that must be deleted in last inch */ if (del_pixel_1 != 0) /* search the number of pixels that must deleted */ { pix = 0; while (pix <= missing_pixels) { toomuch++; pix = toomuch * resolution_base/del_pixel_1; } if (pix > missing_pixels) { toomuch--; } } return (intsize_pixel + missing_pixels - toomuch); } /* ------------------------------------------------------------ UMAX FORGET LINE --------------------------- */ static int umax_forget_line(Umax_Device *dev, int color) /* tests if line related to optical resolution has to be skipped for selected resolution */ /* returns 0 if line is ok, -1 if line has to be skipped */ { unsigned int opt_res = dev->relevant_optical_res * dev->scale_y; unsigned int forget; dev->pixelline_opt_res++; /* increment number of lines in optical res */ if (opt_res != dev->y_resolution) /* are there any lines to skip ? */ { forget = (dev->pixelline_del[color] * opt_res)/(opt_res - dev->y_resolution); if (dev->pixelline_optic[color]++ == forget) { dev->pixelline_del[color]++; /* inc pointer to next line to skip */ return(-1); /* skip line */ } } return(0); /* ok, order this line */ } /* ------------------------------------------------------------ UMAX ORDER LINE TO PIXEL ------------------- */ static void umax_order_line_to_pixel(Umax_Device *dev, unsigned char *source, int color) /* reads a one-color line and writes it into a pixel-ordered-buffer if line */ /* is not skipped */ /* color = 0:red, 1:green, 2:blue */ { unsigned int i; unsigned int line = dev->pixelline_next[color]; /* bufferlinenumber */ unsigned char *dest = dev->pixelbuffer; if (dest != NULL) { if (dev->bits_per_pixel_code == 1) /* 24 bpp */ { dest += line * dev->width_in_pixels * 3 + color; for (i=0; iwidth_in_pixels; i++) /* cp each pixel into pixelbuffer */ { *dest++ = *source++; dest++; dest++; } } else /* > 24 bpp */ { dest += line * dev->width_in_pixels * 6 + color * 2; for(i=0; iwidth_in_pixels; i++) /* cp each pixel into pixelbuffer */ { *dest++ = *source++; /* byte order correct ? , don't know ! */ *dest++ = *source++; dest++; dest++; dest++; dest++; } } line++; if (line >= dev->pixelline_max) { line = 0; } dev->pixelline_next[color] = line; /* next line of this color */ dev->pixelline_ready[color]++; /* number of ready lines for color */ DBG(DBG_read, "merged line as color %d to line %d\n", color, dev->pixelline_ready[color]); } } /* ------------------------------------------------------------ UMAX ORDER LINE ---------------------------- */ static void umax_order_line(Umax_Device *dev, unsigned char *source) { unsigned int CCD_distance = dev->CCD_distance * dev->scale_y; unsigned int length = (dev->scanlength * dev->scale_y * dev->relevant_optical_res) / dev->y_coordinate_base; unsigned int color; do /* search next valid line */ { if (dev->pixelline_opt_res < CCD_distance) { color = dev->CCD_color[0]; /* color 0 */ } else if (dev->pixelline_opt_res < CCD_distance * 3) { color = dev->CCD_color[1 + ((dev->pixelline_opt_res - CCD_distance) % 2)]; /* color 1,2 */ } else if (dev->pixelline_opt_res < length * 3 - CCD_distance * 3) { color = dev->CCD_color[3 + (dev->pixelline_opt_res % 3)]; /* color 3,4,5 */ } else if (dev->pixelline_opt_res < length * 3 - CCD_distance) { color = dev->CCD_color[6 + ((dev->pixelline_opt_res - length*3 + CCD_distance*3) % 2)]; /* color 6,7 */ } else { color = dev->CCD_color[8]; /* color 8 */ } } while(umax_forget_line(dev, color) != 0); /* until found correct line */ umax_order_line_to_pixel(dev, source, color); } /* ------------------------------------------------------------ UMAX GET PIXEL LINE ------------------------ */ static unsigned char * umax_get_pixel_line(Umax_Device *dev) { unsigned char *source = NULL; if (dev->pixelbuffer != NULL) { if ( (dev->pixelline_ready[0] > dev->pixelline_written) && (dev->pixelline_ready[1] > dev->pixelline_written) && (dev->pixelline_ready[2] > dev->pixelline_written) ) { source = dev->pixelbuffer + dev->pixelline_read * dev->width_in_pixels * 3; dev->pixelline_written++; dev->pixelline_read++; if (dev->pixelline_read >= dev->pixelline_max) { dev->pixelline_read = 0; } } } return source; } /* ============================================================ Switches between the SCSI and USB commands = */ /* ------------------------------------------------------------ UMAX SCSI CMD ------------------------------ */ static SANE_Status umax_scsi_cmd(Umax_Device *dev, const void *src, size_t src_size, void *dst, size_t * dst_size) { switch (dev->connection_type) { case SANE_UMAX_SCSI: return sanei_scsi_cmd(dev->sfd, src, src_size, dst, dst_size); break; #ifdef UMAX_ENABLE_USB case SANE_UMAX_USB: return sanei_umaxusb_cmd(dev->sfd, src, src_size, dst, dst_size); break; #endif default: return(SANE_STATUS_INVAL); } } /* ------------------------------------------------------------ UMAX SCSI OPEN EXTENDED -------------------- */ static SANE_Status umax_scsi_open_extended(const char *devicename, Umax_Device *dev, SANEI_SCSI_Sense_Handler handler, void *handler_arg, int *buffersize) { switch (dev->connection_type) { case SANE_UMAX_SCSI: return sanei_scsi_open_extended(devicename, &dev->sfd, handler, handler_arg, buffersize); break; #ifdef UMAX_ENABLE_USB case SANE_UMAX_USB: return sanei_umaxusb_open_extended(devicename, &dev->sfd, handler, handler_arg, buffersize); break; #endif default: return(SANE_STATUS_INVAL); } } /* ------------------------------------------------------------ UMAX SCSI OPEN ----------------------------- */ static SANE_Status umax_scsi_open(const char *devicename, Umax_Device *dev, SANEI_SCSI_Sense_Handler handler, void *handler_arg) { switch (dev->connection_type) { case SANE_UMAX_SCSI: return sanei_scsi_open(devicename, &dev->sfd, handler, handler_arg); break; #ifdef UMAX_ENABLE_USB case SANE_UMAX_USB: return sanei_umaxusb_open(devicename, &dev->sfd, handler, handler_arg); break; #endif default: return(SANE_STATUS_INVAL); } } /* ------------------------------------------------------------ UMAX SCSI CLOSE ---------------------------- */ static void umax_scsi_close(Umax_Device *dev) { switch (dev->connection_type) { case SANE_UMAX_SCSI: sanei_scsi_close(dev->sfd); dev->sfd=-1; break; #ifdef UMAX_ENABLE_USB case SANE_UMAX_USB: sanei_umaxusb_close(dev->sfd); dev->sfd=-1; break; #endif } } /* ------------------------------------------------------------ UMAX SCSI REQ ENTER ------------------------ */ static SANE_Status umax_scsi_req_enter(Umax_Device *dev, const void *src, size_t src_size, void *dst, size_t * dst_size, void **idp) { switch (dev->connection_type) { case SANE_UMAX_SCSI: return sanei_scsi_req_enter (dev->sfd, src, src_size, dst, dst_size, idp); break; #ifdef UMAX_ENABLE_USB case SANE_UMAX_USB: return sanei_umaxusb_req_enter (dev->sfd, src, src_size, dst, dst_size, idp); break; #endif default: return(SANE_STATUS_INVAL); } } /* ------------------------------------------------------------ UMAX SCSI REQ WAIT ------------------------- */ static SANE_Status umax_scsi_req_wait(Umax_Device *dev, void *id) { switch (dev->connection_type) { case SANE_UMAX_SCSI: return sanei_scsi_req_wait(id); break; #ifdef UMAX_ENABLE_USB case SANE_UMAX_USB: return sanei_umaxusb_req_wait(id); break; #endif default: return(SANE_STATUS_INVAL); } } /* ------------------------------------------------------------ UMAX SCSI GET LAMP STATUS ------------------ */ static SANE_Status umax_scsi_get_lamp_status(Umax_Device *dev, int *lamp_on) { SANE_Status status; size_t size = 1; DBG(DBG_proc, "umax_scsi_get_lamp_status\n"); status = umax_scsi_cmd(dev, get_lamp_status.cmd, get_lamp_status.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_scsi_get_lamp_status: command returned status %s\n", sane_strstatus(status)); return status; } *lamp_on = get_lamp_status_lamp_on(dev->buffer[0]); DBG(DBG_info, "lamp_status = %d\n", *lamp_on); return status; } /* ------------------------------------------------------------ UMAX SCSI SET LAMP STATUS ------------------ */ static SANE_Status umax_scsi_set_lamp_status(Umax_Device *dev, int lamp_on) { SANE_Status status; DBG(DBG_proc, "umax_scsi_set_lamp_status\n"); DBG(DBG_info, "lamp_status=%d\n", lamp_on); set_lamp_status_lamp_on(set_lamp_status.cmd, lamp_on); status = umax_scsi_cmd(dev, set_lamp_status.cmd, set_lamp_status.size, NULL, NULL); if (status) { DBG(DBG_error, "umax_scsi_set_lamp_status: command returned status %s\n", sane_strstatus(status)); } return status; } /* ------------------------------------------------------------ UMAX SET LAMP STATUS ----------------------- */ static SANE_Status umax_set_lamp_status(SANE_Handle handle, int lamp_on) { Umax_Scanner *scanner = handle; int lamp_status; SANE_Status status; DBG(DBG_proc, "umax_set_lamp_status\n"); if (umax_scsi_open(scanner->device->sane.name, scanner->device, sense_handler, scanner->device) != SANE_STATUS_GOOD ) { DBG(DBG_error, "ERROR: umax_set_lamp_status: open of %s failed:\n", scanner->device->sane.name); return SANE_STATUS_INVAL; } status = umax_scsi_get_lamp_status(scanner->device, &lamp_status); if (!status) { status = umax_scsi_set_lamp_status(scanner->device, lamp_on); } umax_scsi_close(scanner->device); return status; } /* ------------------------------------------------------------ UMAX GET DATA BUFFER STATUS ---------------- */ #ifndef UMAX_HIDE_UNUSED /* NOT USED */ static SANE_Status umax_get_data_buffer_status(Umax_Device *dev) { SANE_Status status; DBG(DBG_proc, "get_data_buffer_status\n"); set_GDBS_wait(get_data_buffer_status.cmd,1); /* wait for scanned data */ status = umax_scsi_cmd(dev, get_data_buffer_status.cmd, get_data_buffer_status.size, NULL, NULL); if (status) { DBG(DBG_error, "umax_get_data_buffer_status: command returned status %s\n", sane_strstatus(status)); } return status; } #endif /* ------------------------------------------------------------ UMAX DO REQUEST SENSE ---------------------- */ static void umax_do_request_sense(Umax_Device *dev) { size_t size = rs_return_block_size; SANE_Status status; DBG(DBG_proc, "do_request_sense\n"); set_RS_allocation_length(request_sense.cmd, rs_return_block_size); status = umax_scsi_cmd(dev, request_sense.cmd, request_sense.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_do_request_sense: command returned status %s\n", sane_strstatus(status)); } } /* ------------------------------------------------------------ UMAX WAIT SCANNER -------------------------- */ static SANE_Status umax_wait_scanner(Umax_Device *dev) { SANE_Status status; int cnt = 0; DBG(DBG_proc, "wait_scanner\n"); do { if (cnt > 100) /* maximal 100 * 0.5 sec = 50 sec */ { DBG(DBG_warning, "scanner does not get ready\n"); return -1; } /* test unit ready */ status = umax_scsi_cmd(dev, test_unit_ready.cmd, test_unit_ready.size, NULL, NULL); cnt++; if (status) { if (cnt == 1) { DBG(DBG_info2, "scanner reports %s, waiting ...\n", sane_strstatus(status)); } usleep(500000); /* wait 0.5 seconds */ } } while (status != SANE_STATUS_GOOD ); DBG(DBG_info, "scanner ready\n"); return status; } #define WAIT_SCANNER { int status = umax_wait_scanner(dev); if (status) return status; } /* ------------------------------------------------------------ UMAX GRAB SCANNER -------------------------- */ static int umax_grab_scanner(Umax_Device *dev) { int status; DBG(DBG_proc, "grab_scanner\n"); WAIT_SCANNER; /* wait for scanner ready */ status = umax_scsi_cmd(dev, reserve_unit.cmd, reserve_unit.size, NULL, NULL); if (status) { DBG(DBG_error, "umax_grab_scanner: command returned status %s\n", sane_strstatus(status)); } else { DBG(DBG_info, "scanner reserved\n"); } return status; } /* ------------------------------------------------------------ UMAX REPOSITION SCANNER -------------------- */ static int umax_reposition_scanner(Umax_Device *dev) { int status; int pause; pause = dev->pause_after_reposition + dev->pause_for_moving * (dev->upper_left_y + dev->scanlength) / ( (dev->inquiry_fb_length * dev->y_coordinate_base) ); DBG(DBG_info2, "trying to reposition scanner ...\n"); status = umax_scsi_cmd(dev, object_position.cmd, object_position.size, NULL, NULL); if (status) { DBG(DBG_error, "umax_reposition_scanner: command returned status %s\n", sane_strstatus(status)); return status; } if (pause > 0) /* predefined time to wait (Astra 2400S) */ { DBG(DBG_info2, "pause for repositioning %d msec ...\n", pause); usleep(((long) pause) * 1000); DBG(DBG_info, "repositioning pause done\n"); } else if (pause == 0) /* use TEST UNIT READY */ { WAIT_SCANNER; DBG(DBG_info, "scanner repositioned\n"); } else /* pause < 0 : return without any pause */ { DBG(DBG_info, "not waiting for finishing reposition scanner\n"); } return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ UMAX GIVE SCANNER -------------------------- */ static int umax_give_scanner(Umax_Device *dev) { int status; DBG(DBG_info2, "trying to release scanner ...\n"); status = umax_scsi_cmd(dev, release_unit.cmd, release_unit.size, NULL, NULL); if (status) { DBG(DBG_error, "umax_give_scanner: command returned status %s\n", sane_strstatus(status)); } else { DBG(DBG_info, "scanner released\n"); } if (!dev->batch_scan || dev->batch_end) { umax_reposition_scanner(dev); } else { usleep(200000); /* 200 ms pause to make sure program does not exit before scanner is ready */ } return status; } /* ------------------------------------------------------------ UMAX SEND GAMMA DATA ----------------------- */ static void umax_send_gamma_data(Umax_Device *dev, void *gamma_data, int color) { unsigned char *data = gamma_data; unsigned char *dest; int length; SANE_Status status; DBG(DBG_proc, "send_gamma_data\n"); if (dev->inquiry_gamma_dwload == 0) { DBG(DBG_error, "ERROR: gamma download not available\n"); return; } memcpy(dev->buffer[0], send.cmd, send.size); /* send */ set_S_datatype_code(dev->buffer[0], S_datatype_gamma); /* gamma curve */ dest = dev->buffer[0] + send.size; if (dev->inquiry_gamma_DCF == 0) /* gamma format type 0 */ { DBG(DBG_info, "using gamma download curve format type 0\n"); memcpy(dest, gamma_DCF0.cmd, gamma_DCF0.size); if (color == 1) /* one color */ { set_DCF0_gamma_lines(dest, DCF0_gamma_one_line); set_DCF0_gamma_color(dest, 0, DCF0_gamma_color_gray); /* grayscale */ if ( (dev->colormode == RGB) && (dev->three_pass != 0) ) /* 3 pass color */ { set_DCF0_gamma_color(dest, 0, dev->three_pass_color); /* set color */ } dest = dest + 2; memcpy(dest, data, 1024); /* copy data */ set_S_xfer_length(dev->buffer[0], 1026); /* set length */ status = umax_scsi_cmd(dev, dev->buffer[0], send.size + 1026, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_gamma_data(DCF=0, one color): command returned status %s\n", sane_strstatus(status)); } } else /* three colors */ { set_DCF0_gamma_lines(dest, DCF0_gamma_three_lines); set_DCF0_gamma_color(dest, 0, DCF0_gamma_color_red); /* red */ set_DCF0_gamma_color(dest, 1, DCF0_gamma_color_green); /* green */ set_DCF0_gamma_color(dest, 2, DCF0_gamma_color_blue); /* blue */ dest = dest + 2; memcpy(dest, data, 1024); /* copy red data */ dest = dest + 1025; data = data + 1024; memcpy(dest, data, 1024); /* copy green data */ dest = dest + 1025; data = data + 1024; memcpy(dest, data, 1024); /* copy blue data */ set_S_xfer_length(dev->buffer[0], 3076); /* set length */ status = umax_scsi_cmd(dev, dev->buffer[0], send.size + 3076, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_gamma_data(DCF=0, RGB): command returned status %s\n", sane_strstatus(status)); } } } else if (dev->inquiry_gamma_DCF == 1) /* gamma format type 1 */ { DBG(DBG_info, "using gamma download curve format type 1\n"); memcpy(dest, gamma_DCF1.cmd, gamma_DCF1.size); set_DCF1_gamma_color(dest, DCF1_gamma_color_gray); /* grayscale */ if ( (dev->colormode == RGB) && (dev->three_pass != 0) ) /* 3 pass color */ { set_DCF1_gamma_color(dest, dev->three_pass_color); /* set color */ } dest = dest + 2; memcpy(dest, data, 256); /* copy data */ set_S_xfer_length(dev->buffer[0], 258); /* set length */ status = umax_scsi_cmd(dev, dev->buffer[0], send.size + 258, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_gamma_data(DCF=1): command returned status %s\n", sane_strstatus(status)); } } else if (dev->inquiry_gamma_DCF == 2) /* gamma format type 2 */ { DBG(DBG_info, "using gamma download curve format type 2\n"); memcpy(dest, gamma_DCF2.cmd, gamma_DCF2.size); set_DCF2_gamma_color(dest, DCF2_gamma_color_gray); /* grayscale */ if ( (dev->colormode == RGB) && (dev->three_pass != 0) ) /* 3 pass color */ { set_DCF2_gamma_color(dest, dev->three_pass_color); } /* set color */ if (color == 1) { set_DCF2_gamma_lines(dest, DCF2_gamma_one_line); } else { set_DCF2_gamma_lines(dest, DCF2_gamma_three_lines); } set_DCF2_gamma_input_bits(dest, dev->gamma_input_bits_code); set_DCF2_gamma_output_bits(dest, dev->bits_per_pixel_code); dest = dev->buffer[0] + send.size + gamma_DCF2.size; /* write to dest */ if (dev->gamma_input_bits_code & 32) { length = 65536; /* 16 input bits */ } else if (dev->gamma_input_bits_code & 16) { length = 16384; /* 14 input bits */ } else if (dev->gamma_input_bits_code & 8) { length = 4096; /* 12 input bits */ } else if (dev->gamma_input_bits_code & 4) { length = 1024; /* 10 input bits */ } else if (dev->gamma_input_bits_code & 2) { length = 512; /* 9 input bits */ } else { length = 256; /* 8 input bits */ } if (dev->bits_per_pixel_code != 1) /* more than 8 output bits per pixel */ { length = length * 2; /* = 2 output bytes */ } if (dev->bufsize >= color*length+gamma_DCF2.size) { set_S_xfer_length(dev->buffer[0], color*length+gamma_DCF2.size); /* set length */ memcpy(dest, data, color*length); /* copy data */ status = umax_scsi_cmd(dev, dev->buffer[0], send.size+gamma_DCF2.size + length * color, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_gamma_data(DCF=2): command returned status %s\n", sane_strstatus(status)); } } else { DBG(DBG_error, "ERROR: too small scsi buffer (%d bytes) to send gamma data\n", dev->bufsize); } } else { DBG(DBG_error, "ERROR: unknown gamma download curve type for this scanner\n"); } } /* ------------------------------------------------------------ UMAX SEND DATA ---------------------------- */ static void umax_send_data(Umax_Device *dev, void *data, int size, int datatype) { unsigned char *dest; SANE_Status status; memcpy(dev->buffer[0], send.cmd, send.size); /* send */ set_S_datatype_code(dev->buffer[0], datatype); /* set datatype */ set_S_xfer_length(dev->buffer[0], size); /* bytes */ dest=dev->buffer[0] + send.size; memcpy(dest, data, size); /* copy data */ status = umax_scsi_cmd(dev, dev->buffer[0], send.size + size, NULL, NULL); if (status) { DBG(DBG_error, "umax_send_data: command returned status %s\n", sane_strstatus(status)); } } /* ------------------------------------------------------------ UMAX SEND HALFTONE PATTERN ----------------- */ #ifndef UMAX_HIDE_UNUSED static void umax_send_halftone_pattern(Umax_Device *dev, void *data, int size) { DBG(DBG_proc,"send_halftone_pattern\n"); umax_send_data(dev, data, size*size, S_datatype_halftone); } #endif /* ------------------------------------------------------------ UMAX SEND SHADING DATA -------------------- */ static void umax_send_shading_data(Umax_Device *dev, void *data, int size) { DBG(DBG_proc,"send_shading_data\n"); umax_send_data(dev, data, size, S_datatype_shading); } /* ------------------------------------------------------------ UMAX SEND GAIN DATA ----------------------- */ #ifndef UMAX_HIDE_UNUSED static void umax_send_gain_data(Umax_Device *dev, void *data, int size) { DBG(DBG_proc,"send_gain_data\n"); umax_send_data(dev, data, size, S_datatype_gain); } #endif /* ------------------------------------------------------------ UMAX QUEUE READ IMAGE DATA REQ ------------- */ static SANE_Status umax_queue_read_image_data_req(Umax_Device *dev, unsigned int length, int bufnr) { SANE_Status status; DBG(DBG_proc, "umax_queue_read_image_data_req for buffer[%d], length = %d\n", bufnr, length); set_R_xfer_length(sread.cmd, length); /* set length */ set_R_datatype_code(sread.cmd, R_datatype_imagedata); /* set datatype */ dev->length_queued[bufnr] = length; /* set length request */ dev->length_read[bufnr] = length; /* set length request, can be changed asyncronous by umax_scsi_req_enter */ status = umax_scsi_req_enter(dev, sread.cmd, sread.size, dev->buffer[bufnr], &(dev->length_read[bufnr]), &(dev->queue_id[bufnr])); if (status) { DBG(DBG_error, "umax_queue_read_image_data_req: command returned status %s\n", sane_strstatus(status)); return -1; } else { DBG(DBG_info2, "umax_queue_read_image_data_req: id for buffer[%d] is %p\n", bufnr, dev->queue_id[bufnr]); } return length; } /* ------------------------------------------------------------ UMAX WAIT QUEUED IMAGE DATA ---------------- */ static int umax_wait_queued_image_data(Umax_Device *dev, int bufnr) { SANE_Status status; DBG(DBG_proc, "umax_wait_queued_image_data for buffer[%d] (id=%p)\n", bufnr, dev->queue_id[bufnr]); status = umax_scsi_req_wait(dev, dev->queue_id[bufnr]); if (status) { DBG(DBG_error, "umax_wait_queued_image_data: wait returned status %s\n", sane_strstatus(status)); return -1; } return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ UMAX READ DATA ----------------------------- */ static int umax_read_data(Umax_Device *dev, size_t length, int datatype) { SANE_Status status; set_R_xfer_length(sread.cmd, length); /* set length */ set_R_datatype_code(sread.cmd, datatype); /* set datatype */ status = umax_scsi_cmd(dev, sread.cmd, sread.size, dev->buffer[0], &length); if (status) { DBG(DBG_error, "umax_read_data: command returned status %s\n", sane_strstatus(status)); return -1; } return length; } /* ------------------------------------------------------------ UMAX READ SHADING DATA -------------------- */ static int umax_read_shading_data(Umax_Device *dev, unsigned int length) { DBG(DBG_proc,"read_shading_data\n"); return umax_read_data(dev, length, R_datatype_shading); } /* ------------------------------------------------------------ UMAX READ GAIN DATA ----------------------- */ #ifndef UMAX_HIDE_UNUSED static int umax_read_gain_data(Umax_Device *dev, unsigned int length) { DBG(DBG_proc,"read_gain_data\n"); return umax_read_data(dev, length, R_datatype_gain); } #endif /* ------------------------------------------------------------ UMAX READ IMAGE DATA ---------------------- */ #ifndef UMAX_HIDE_UNUSED static int umax_read_image_data(Umax_Device *dev, unsigned int length) { DBG(DBG_proc,"read_image_data\n"); WAIT_SCANNER; return umax_read_data(dev, length, R_datatype_imagedata); } #endif /* ------------------------------------------------------------ UMAX CORRECT LIGHT ------------------------- */ static int umax_correct_light(int light, int analog_gamma_byte) /* correct highlight/shadow if analog gamma is set */ { double analog_gamma; analog_gamma=analog_gamma_table[analog_gamma_byte]; return( (int) 255 * pow( ((double) light)/255.0 , (1.0/analog_gamma) )+.5 ); } /* ------------------------------------------------------------ UMAX SET WINDOW PARAM ---------------------- */ /* set_window_param sets all the window parameters. This means building a */ /* fairly complicated SCSI command before sending it... */ static SANE_Status umax_set_window_param(Umax_Device *dev) { SANE_Status status; int num_dblocks = 1; /* number of window descriptor blocks, usually 1 or 3 */ unsigned char buffer_r[max_WDB_size], buffer_g[max_WDB_size], buffer_b[max_WDB_size]; DBG(DBG_proc, "set_window_param\n"); memset(buffer_r, '\0', max_WDB_size); /* clear buffer */ set_WDB_length(dev->wdb_len); /* length of win descriptor block */ memcpy(buffer_r, window_descriptor_block.cmd, window_descriptor_block.size); /* copy preset data */ set_WD_wid(buffer_r, 0); /* window identifier */ set_WD_auto(buffer_r, dev->set_auto); /* 0 or 1: don't know what it is */ /* geometry */ set_WD_Xres(buffer_r, dev->x_resolution); /* x resolution in dpi */ set_WD_Yres(buffer_r, dev->y_resolution); /* y resolution in dpi */ set_WD_ULX(buffer_r, dev->upper_left_x); /* left_edge x */ set_WD_ULY(buffer_r, dev->upper_left_y); /* upper_edge y */ set_WD_width(buffer_r, dev->scanwidth); /* width */ set_WD_length(buffer_r, dev->scanlength); /* length */ /* BTC */ set_WD_brightness(buffer_r, dev->brightness); /* brightness, only halftone */ set_WD_threshold(buffer_r, dev->threshold); /* threshold, only lineart */ set_WD_contrast(buffer_r, dev->contrast); /* contrast, only halftone */ /* scanmode, preset to LINEART */ set_WD_composition(buffer_r, WD_comp_lineart); /* image composition */ /* = (scan-mode) */ set_WD_bitsperpixel(buffer_r, WD_bits_1); /* bits/pixel (1,8,9,10,12,14,16) */ set_WD_halftone(buffer_r, dev->halftone); /* select halftone-pattern */ set_WD_RIF(buffer_r, dev->reverse); /* reverse, invert black and white */ set_WD_speed(buffer_r, dev->WD_speed); /* set speed */ set_WD_select_color(buffer_r, WD_color_gray); /* color for window-block */ /* set highlight and shadow in dependence of analog gamma */ set_WD_highlight(buffer_r, umax_correct_light(dev->highlight_r, dev->analog_gamma_r)); set_WD_shadow(buffer_r, umax_correct_light(dev->shadow_r, dev->analog_gamma_r)); /* scan options */ set_WD_gamma(buffer_r, dev->digital_gamma_r); /* set digital gamma */ set_WD_module(buffer_r, dev->module); /* flatbed or transparency */ set_WD_CBHS(buffer_r, dev->cbhs_range); /* 50 or 255 */ set_WD_FF(buffer_r, dev->fix_focus_position); /* fix focus position */ set_WD_RMIF(buffer_r, dev->reverse_multi); /* reverse color-values */ set_WD_FDC(buffer_r, dev->lens_cal_in_doc_pos); /* lens calibration in document position */ set_WD_PF(buffer_r, dev->disable_pre_focus); /* disable pre focus */ set_WD_LCL(buffer_r, dev->holder_focus_pos_0mm); /* 0.6mm <-> 0.0mm holder focus position */ set_WD_HBT(buffer_r, dev->low_byte_first); /* set byte order for 16 bit scanners */ set_WD_DOR(buffer_r, dev->dor); /* double-resolution-mode */ set_WD_scan_exposure_level(buffer_r, dev->exposure_time_scan_r); /* scan exposure time */ set_WD_calibration_exposure_level(buffer_r, dev->exposure_time_calibration_r);/* calibration exposure time */ set_WD_batch(buffer_r, dev->batch_scan); /* batch or normal scan */ set_WD_MF(buffer_r, dev->manual_focus); /* automatic <-> manual focus */ set_WD_line_arrangement(buffer_r, WD_line_arrengement_by_fw); /* line arrangement by scanner */ set_WD_warmup(buffer_r, dev->warmup); /* warmup */ set_WD_calibration(buffer_r, dev->calibration); /* image calibration */ set_WD_color_sequence(buffer_r, WD_color_sequence_RGB); /* sequence RGB */ set_WD_color_ordering(buffer_r, WD_color_ordering_pixel); /* set to pixel for pbm, pgm, pnm-file */ set_WD_analog_gamma(buffer_r, dev->analog_gamma_r ); /* analog gamma */ set_WD_lamp_c_density(buffer_r, dev->c_density); /* calibrat. lamp density */ set_WD_lamp_s_density(buffer_r, dev->s_density); /* scan lamp density */ set_WD_next_upper_left(buffer_r, dev->batch_next_tl_y); /* batch scan next top left y position */ set_WD_pixel_count(buffer_r, dev->width_in_pixels); /* pixel count */ set_WD_line_count(buffer_r, dev->length_in_pixels); /* line count */ set_WD_x_coordinate_base(buffer_r, dev->x_coordinate_base); /* dpi (1200) */ set_WD_y_coordinate_base(buffer_r, dev->y_coordinate_base); /* dpi (1200) */ set_WD_calibration_data_lines(buffer_r, dev->calib_lines); /* required lines for calibration by driver */ switch(dev->colormode) { case LINEART: /* LINEART */ set_WD_composition(buffer_r, WD_comp_lineart); set_WD_bitsperpixel(buffer_r, WD_bits_1); set_WD_select_color(buffer_r, WD_color_gray); break; case HALFTONE: /* HALFTONE */ set_WD_composition(buffer_r, WD_comp_dithered); set_WD_bitsperpixel(buffer_r, WD_bits_1); set_WD_select_color(buffer_r, WD_color_gray); break; case GRAYSCALE: /* GRAYSCALE */ set_WD_composition(buffer_r, WD_comp_gray); set_WD_bitsperpixel(buffer_r, dev->bits_per_pixel); set_WD_select_color(buffer_r, WD_color_gray); break; case RGB_LINEART: /* COLOR MODES */ case RGB_HALFTONE: case RGB: if (dev->colormode == RGB_LINEART ) { set_WD_composition(buffer_r, WD_comp_rgb_bilevel); set_WD_bitsperpixel(buffer_r, WD_bits_1); } else if (dev->colormode == RGB_HALFTONE ) { set_WD_composition(buffer_r, WD_comp_rgb_dithered); set_WD_bitsperpixel(buffer_r, WD_bits_1); } else /* RGB */ { set_WD_composition(buffer_r, WD_comp_rgb_full); set_WD_bitsperpixel(buffer_r, dev->bits_per_pixel); } if (dev->three_pass == 0) { /* singlepass */ num_dblocks = 3; if (dev->do_color_ordering != 0) { set_WD_line_arrangement(buffer_r, WD_line_arrengement_by_driver); if (dev->CCD_distance == 0) { set_WD_color_ordering(buffer_r, WD_color_ordering_line_no_ccd); } else { set_WD_color_ordering(buffer_r, WD_color_ordering_line_w_ccd); } } memcpy(buffer_g, buffer_r, max_WDB_size); /* copy WDB for green */ memcpy(buffer_b, buffer_r, max_WDB_size); /* copy WDB for blue */ set_WD_wid(buffer_r, WD_wid_red); /* window identifier red */ set_WD_wid(buffer_g, WD_wid_green); /* window identifier green */ set_WD_wid(buffer_b, WD_wid_blue); /* window identifier blue */ set_WD_select_color(buffer_r, WD_color_red); /* select red for this window */ set_WD_select_color(buffer_g, WD_color_green); /* select green for this window */ set_WD_select_color(buffer_b, WD_color_blue); /* select blue for this window */ set_WD_gamma(buffer_r, dev->digital_gamma_r); /* digital gamma */ set_WD_gamma(buffer_g, dev->digital_gamma_g); set_WD_gamma(buffer_b, dev->digital_gamma_b); set_WD_analog_gamma(buffer_r, dev->analog_gamma_r); /* analog gamma */ set_WD_analog_gamma(buffer_g, dev->analog_gamma_g); set_WD_analog_gamma(buffer_b, dev->analog_gamma_b); /* set highlight in dependence of analog gamma */ set_WD_highlight(buffer_r, umax_correct_light(dev->highlight_r, dev->analog_gamma_r)); set_WD_highlight(buffer_g, umax_correct_light(dev->highlight_g, dev->analog_gamma_g)); set_WD_highlight(buffer_b, umax_correct_light(dev->highlight_b, dev->analog_gamma_b)); /* set shadow in dependence of analog gamma */ set_WD_shadow(buffer_r, umax_correct_light(dev->shadow_r, dev->analog_gamma_r)); set_WD_shadow(buffer_g, umax_correct_light(dev->shadow_g, dev->analog_gamma_g)); set_WD_shadow(buffer_b, umax_correct_light(dev->shadow_b, dev->analog_gamma_b)); set_WD_scan_exposure_level(buffer_r, dev->exposure_time_scan_r); /* set scan exposure times */ set_WD_scan_exposure_level(buffer_g, dev->exposure_time_scan_g); set_WD_scan_exposure_level(buffer_b, dev->exposure_time_scan_b); set_WD_calibration_exposure_level(buffer_r, dev->exposure_time_calibration_r);/* set calib exp times */ set_WD_calibration_exposure_level(buffer_g, dev->exposure_time_calibration_g); set_WD_calibration_exposure_level(buffer_b, dev->exposure_time_calibration_b); } else { /* threepass */ set_WD_wid(buffer_r, 0); /* window identifier */ set_WD_color_ordering(buffer_r, WD_color_ordering_plane); /* ???? */ if (dev->colormode == RGB_LINEART ) { set_WD_composition(buffer_r, WD_comp_lineart); /* color-lineart-mode */ } else if (dev->colormode == RGB_HALFTONE ) { set_WD_composition(buffer_r, WD_comp_dithered); /* color-halftone-mode */ } else /* RGB */ { set_WD_composition(buffer_r, WD_comp_gray); /* color-mode */ } switch (dev->three_pass_color) { case WD_wid_red: set_WD_select_color(buffer_r, WD_color_red); /* color red */ set_WD_gamma(buffer_r, dev->digital_gamma_r); set_WD_analog_gamma(buffer_r, dev->analog_gamma_r); set_WD_highlight(buffer_r, umax_correct_light(dev->highlight_r, dev->analog_gamma_r)); set_WD_shadow(buffer_r, umax_correct_light(dev->shadow_r, dev->analog_gamma_r)); set_WD_scan_exposure_level(buffer_r, dev->exposure_time_scan_r); set_WD_calibration_exposure_level(buffer_r, dev->exposure_time_calibration_r); break; case WD_wid_green: set_WD_select_color(buffer_r, WD_color_green); /* color green */ set_WD_gamma(buffer_r, dev->digital_gamma_g); set_WD_analog_gamma(buffer_r, dev->analog_gamma_g); set_WD_highlight(buffer_r, umax_correct_light(dev->highlight_g, dev->analog_gamma_g)); set_WD_shadow(buffer_r, umax_correct_light(dev->shadow_g, dev->analog_gamma_g)); set_WD_scan_exposure_level(buffer_r, dev->exposure_time_scan_g); set_WD_calibration_exposure_level(buffer_r, dev->exposure_time_calibration_g); break; case WD_wid_blue: set_WD_select_color(buffer_r, WD_color_blue); /* color blue */ set_WD_gamma(buffer_r, dev->digital_gamma_b); set_WD_analog_gamma(buffer_r, dev->analog_gamma_b); set_WD_highlight(buffer_r, umax_correct_light(dev->highlight_b, dev->analog_gamma_b)); set_WD_shadow(buffer_r, umax_correct_light(dev->shadow_b, dev->analog_gamma_b)); set_WD_scan_exposure_level(buffer_r, dev->exposure_time_scan_b); set_WD_calibration_exposure_level(buffer_r, dev->exposure_time_calibration_b); break; } /* switch dev->three_pass_color */ } /* if (single_pass) else (three_pass) */ break; } /* switch dev->colormode, case RGB */ /* prepare SCSI-BUFFER */ memcpy(dev->buffer[0], set_window.cmd, set_window.size); /* SET-WINDOW cmd */ memcpy(WPDB_OFF(dev->buffer[0]), window_parameter_data_block.cmd, window_parameter_data_block.size); /* WPDB */ set_WPDB_wdbnum(WPDB_OFF(dev->buffer[0]), num_dblocks); /* set WD_len */ memcpy(WDB_OFF(dev->buffer[0],1), buffer_r, window_descriptor_block.size); /* add WD_block */ if ( num_dblocks == 3) /* if singelpass RGB */ { memcpy(WDB_OFF(dev->buffer[0],2), buffer_g, window_descriptor_block.size); /* add green */ memcpy(WDB_OFF(dev->buffer[0],3), buffer_b, window_descriptor_block.size); /* add blue */ } DBG(DBG_info2, "window descriptor block created with %d bytes\n", dev->wdb_len); set_SW_xferlen(dev->buffer[0], (window_parameter_data_block.size + (window_descriptor_block.size * num_dblocks))); status = umax_scsi_cmd(dev, dev->buffer[0], set_window.size + window_parameter_data_block.size + (window_descriptor_block.size * num_dblocks), NULL, NULL); if (status) { DBG(DBG_error, "umax_set_window_param: command returned status %s\n", sane_strstatus(status)); } else { DBG(DBG_info, "window(s) set\n"); } return status; } /* ------------------------------------------------------------ UMAX DO INQUIRY ---------------------------- */ static void umax_do_inquiry(Umax_Device *dev) { size_t size; SANE_Status status; DBG(DBG_proc,"do_inquiry\n"); memset(dev->buffer[0], '\0', 256); /* clear buffer */ size = 5; set_inquiry_return_size(inquiry.cmd, size); /* first get only 5 bytes to get size of inquiry_return_block */ status = umax_scsi_cmd(dev, inquiry.cmd, inquiry.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_do_inquiry: command returned status %s\n", sane_strstatus(status)); } size = get_inquiry_additional_length(dev->buffer[0]) + 5; set_inquiry_return_size(inquiry.cmd, size); /* then get inquiry with actual size */ status = umax_scsi_cmd(dev, inquiry.cmd, inquiry.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_do_inquiry: command returned status %s\n", sane_strstatus(status)); } } /* ------------------------------------------------------------ UMAX START SCAN ---------------------------- */ static SANE_Status umax_start_scan(Umax_Device *dev) { int size = 1; SANE_Status status; DBG(DBG_proc,"start_scan\n"); if (dev->adf) /* ADF selected: test for ADF errors */ { umax_do_inquiry(dev); /* get inquiry */ if (get_inquiry_ADF_paper_jam(dev->buffer[0])) /* test for ADF paper jam */ { DBG(DBG_error,"ERROR: umax_start_scan: ADF paper jam\n"); return SANE_STATUS_JAMMED; } else if (get_inquiry_ADF_cover_open(dev->buffer[0])) /* test for ADF cover open */ { DBG(DBG_error,"ERROR: umax_start_scan: ADF cover open\n"); return SANE_STATUS_COVER_OPEN; } else if (get_inquiry_ADF_no_paper(dev->buffer[0])) /* test for ADF no paper */ { DBG(DBG_error,"ERROR: umax_start_scan: ADF no paper\n"); return SANE_STATUS_NO_DOCS; } } set_SC_quality(scan.cmd, dev->quality); /* 1=qual, 0=fast */ set_SC_adf( scan.cmd, dev->adf); /* ADF, 0=off, 1=use */ set_SC_preview(scan.cmd, dev->preview); /* 1=preview */ set_SC_wid(scan.cmd, 1, 0); /* Window-Identifier */ set_SC_xfer_length(scan.cmd, size); /* following Bytes */ DBG(DBG_info,"starting scan\n"); status = umax_scsi_cmd(dev, scan.cmd, scan.size + size, NULL, NULL); if (status) { DBG(DBG_error, "umax_start_scan: command returned status %s\n", sane_strstatus(status)); } return status; } /* ------------------------------------------------------------ UMAX DO CALIBRATION ------------------------ */ static SANE_Status umax_do_calibration(Umax_Device *dev) { SANE_Status status; unsigned int width = 0; unsigned int lines = 0; unsigned int bytespp = 0; DBG(DBG_proc,"do_calibration\n"); status = umax_wait_scanner(dev); if ((status == SANE_STATUS_GOOD) && (dev->do_calibration != 0)) /* calibration by driver */ { unsigned char *shading_data = 0; unsigned int i, j; long *average; DBG(DBG_info,"driver is doing calibration\n"); if (umax_execute_request_sense) { DBG(DBG_info,"request sense call is enabled\n"); memset(dev->buffer[0], 0, rs_return_block_size); /* clear sense data buffer */ umax_do_request_sense(dev); /* new request-sense call to get all data */ } else { DBG(DBG_info,"request sense call is disabled\n"); } if (get_RS_SCC_condition_code(dev->buffer[0]) != 1) { DBG(DBG_warning,"WARNING: missing information about shading-data\n"); DBG(DBG_warning," driver tries to guess missing values!\n"); if ((dev->calibration_area != UMAX_CALIBRATION_AREA_CCD) && (!dev->batch_scan)) /* calibration is done with image geometry and depth */ { DBG(DBG_warning," Calibration is done with selected image geometry and depth!\n"); width = dev->scanwidth * dev->relevant_optical_res / dev->x_coordinate_base; if (dev->calibration_width_offset > -99999) /* driver or user (umax.conf) define an offset */ { width = width + dev->calibration_width_offset; DBG(DBG_warning," Using calibration width offset of %d\n", dev->calibration_width_offset); } if (dev->colormode == RGB) { width = width * 3; } lines = dev->calib_lines; if (dev->gamma_input_bits_code <= 1) { bytespp = 1; /* 8 bit mode */ } else { bytespp = 2; /* 16 bit mode */ } } else /* calibration is done with full scanarea and full depth */ { DBG(DBG_warning," Calibration is done for each CCD pixel with full depth!\n"); width = (int)(dev->inquiry_fb_width * dev->inquiry_optical_res); if (dev->batch_scan) { if (dev->calibration_width_offset_batch > -99999) /* driver or user (umax.conf) define an offset for batch scanning */ { width = width + dev->calibration_width_offset_batch; DBG(DBG_warning," Using calibration width offset for batch scanning of %d\n", dev->calibration_width_offset_batch); } } else /* normal scan */ { if (dev->calibration_width_offset > -99999) /* driver or user (umax.conf) define an offset */ { width = width + dev->calibration_width_offset; DBG(DBG_warning," Using calibration width offset of %d\n", dev->calibration_width_offset); } } if (dev->colormode == RGB) { width = width * 3; } lines = dev->calib_lines; if (dev->gamma_input_bits_code <= 1) { bytespp = 1; /* 8 bit mode */ } else { bytespp = 2; /* 16 bit mode */ } } } else { lines = get_RS_SCC_calibration_lines(dev->buffer[0]); bytespp = get_RS_SCC_calibration_bytespp(dev->buffer[0]); width = get_RS_SCC_calibration_bytesperline(dev->buffer[0]) / bytespp; } if (dev->calibration_bytespp > 0) /* correct bytespp if necessary and driver knows about it or user did select it */ { bytespp = dev->calibration_bytespp; } DBG(DBG_info,"scanner sends %d lines with %d pixels and %d bytes/pixel\n", lines, width, bytespp); if (width * bytespp > dev->bufsize) { DBG(DBG_error,"ERROR: scsi buffer is to small for one shading line, calibration aborted\n"); DBG(DBG_error,"=> change umax.conf options scsi-buffer-size-min and scsi-buffer-size-max\n"); return SANE_STATUS_NO_MEM; } /* UMAX S12 sends a kind of uncalibrated image data, bright -> 255, dark -> 0 */ /* (although 0 is not black) my scanner sends values around 220 */ /* for some scanners the data is simply sent back, other scanners want 255-value as awnswer */ average = calloc(width, sizeof(long)); if (average == 0) { DBG(DBG_error,"ERROR: could not allocate memory for averaging shading data: calibration aborted\n"); return SANE_STATUS_NO_MEM; } shading_data = calloc(width, bytespp); if (shading_data == 0) { DBG(DBG_error,"ERROR: could not allocate memory for shading data: calibration aborted\n"); return SANE_STATUS_NO_MEM; } if (bytespp == 1) /* 1 byte per pixel */ { DBG(DBG_info,"calculating average value for 8 bit shading data!\n"); for (i=0; ibuffer[0][j]; } DBG(DBG_read,"8 bit shading-line %d read\n", i+1); } for (j=0; jlow_byte_first) /* 2 bytes per pixel with low byte first */ { DBG(DBG_info,"calculating average value for 16 bit shading data (low byte first)!\n"); for (i=0; ibuffer[0][2*j+1] + dev->buffer[0][2*j] ; } DBG(DBG_read,"16 bit shading-line %d read\n", i+1); } for (j=0; jbuffer[0][2*j] + dev->buffer[0][2*j + 1] ; } DBG(DBG_read,"16 bit shading-line %d read\n", i+1); } for (j=0; jinvert_shading_data) ) /* invert data */ { if (bytespp == 1) { DBG(DBG_info,"inverting 8 bit shading data\n"); for (j=0; jdo_calibration = 0; } return status; } /* ------------------------------------------------------------ UMAX DO NEW INQUIRY ------------------------ */ static void umax_do_new_inquiry(Umax_Device *dev, size_t size) /* call inquiry again if wrong length */ { SANE_Status status; DBG(DBG_proc,"do_new_inquiry\n"); memset(dev->buffer[0], '\0', 256); /* clear buffer */ set_inquiry_return_size(inquiry.cmd, size); status = umax_scsi_cmd(dev, inquiry.cmd, inquiry.size, dev->buffer[0], &size); if (status) { DBG(DBG_error, "umax_do_new_inquiry: command returned status %s\n", sane_strstatus(status)); } } /* ------------------------------------------------------------ UMAX CORRECT INQUIRY ----------------------- */ static void umax_correct_inquiry(Umax_Device *dev, char *vendor, char *product, char *version) { DBG(DBG_info, "umax_correct_inquiry(\"%s %s %s\")\n", vendor, product, version); if (!strncmp(vendor, "UMAX ", 5)) { if (!strncmp(product, "Astra 600S ", 11)) { int add_len = get_inquiry_additional_length(dev->buffer[0]); DBG(DBG_warning,"setting up special options for %s\n", product); if (add_len == 0x8f) { DBG(DBG_warning," - correcting wrong inquiry data\n"); umax_do_new_inquiry(dev, 0x9b); /* get inquiry with correct length */ set_inquiry_length(dev->buffer[0], 0x9e); /* correct inquiry len */ /* correct color-ordering from pixel to line_with_ccd_distance */ set_inquiry_color_order(dev->buffer[0], IN_color_ordering_line_w_ccd); set_inquiry_fb_uta_line_arrangement_mode(dev->buffer[0], 32); set_inquiry_CCD_line_distance(dev->buffer[0], 8); /* we should reset ADF-bit here too */ if (dev->invert_shading_data == -1) /* nothing defined in umax.conf */ { DBG(DBG_warning," - activating inversion of shading data\n"); dev->invert_shading_data = 1; } } } else if (!strncmp(product, "Astra 610S ", 11)) { int add_len = get_inquiry_additional_length(dev->buffer[0]); DBG(DBG_warning,"setting up special options for %s\n", product); if (add_len == 0x8f) { DBG(DBG_warning," - correcting wrong inquiry data\n"); umax_do_new_inquiry(dev, 0x9b); /* get inquiry with correct length */ set_inquiry_length(dev->buffer[0], 0x9e); /* correct inquiry len */ /* correct color-ordering from pixel to line_with_ccd_distance */ set_inquiry_color_order(dev->buffer[0], IN_color_ordering_line_w_ccd); set_inquiry_fb_uta_line_arrangement_mode(dev->buffer[0], 33); set_inquiry_CCD_line_distance(dev->buffer[0], 8); if (dev->invert_shading_data == -1) /* nothing defined in umax.conf */ { DBG(DBG_warning," - activating inversion of shading data\n"); dev->invert_shading_data = 1; } } } else if ( (!strncmp(product, "Astra 1200S ", 12)) || (!strncmp(product, "Perfection600 ", 14)) ) { DBG(DBG_warning,"using standard options for %s\n", product); } else if (!strncmp(product, "Astra 1220S ", 12)) { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->gamma_lsb_padded == -1) /* nothing defined in umax.conf and not by backend */ { DBG(DBG_warning," - 16 bit gamma table is created lsb padded\n"); dev->gamma_lsb_padded = 1; } if (!strncmp(version, "V1.5 ", 4)) { DBG(DBG_warning," - lamp control enabled for version %s\n", version); dev->lamp_control_available = 1; } } else if (!strncmp(product, "Astra 2100S ", 12)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - lamp control enabled\n"); dev->lamp_control_available = 1; if (dev->calibration_bytespp == -1) /* no calibration-bytespp defined in umax.conf */ { DBG(DBG_warning," - setting calibration_bytespp = 1\n"); dev->calibration_bytespp = 1; /* scanner says 2 bytespp for calibration but 1 bytepp is correct */ } } else if (!strncmp(product, "Astra 2200 ", 11)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - lamp control enabled\n"); dev->lamp_control_available = 1; if (dev->calibration_area == -1) /* no calibration area defined in umax.conf */ { DBG(DBG_warning," - calibration by driver is done for each CCD pixel\n"); dev->calibration_area = UMAX_CALIBRATION_AREA_CCD; } if (dev->calibration_bytespp == -1) /* no calibration-bytespp defined in umax.conf */ { DBG(DBG_warning," - setting calibration_bytespp = 2\n"); dev->calibration_bytespp = 2; } DBG(DBG_warning," - common x and y resolution\n"); dev->common_xy_resolutions = 1; if (dev->connection_type == SANE_UMAX_USB) { DBG(DBG_warning," - disabling quality calibration for USB connection\n"); set_inquiry_fw_quality(dev->buffer[0], 0); } } else if (!strncmp(product, "Astra 2400S ", 12)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - defining pauses\n"); dev->pause_for_color_calibration = 7000; /* pause between start_scan and do_calibration in ms */ dev->pause_for_gray_calibration = 4000; /* pause between start_scan and do_calibration in ms */ dev->pause_after_calibration = 0000; /* pause between do_calibration and read data in ms */ dev->pause_after_reposition = 3000; /* pause after repostion scanner in ms */ dev->pause_for_moving = 3000; /* pause for moving scanhead over full area */ DBG(DBG_warning," - correcting ADF bit in inquiry\n"); set_inquiry_sc_adf(dev->buffer[0], 1); /* set second bit that indicates ADF is supported */ } else if (!strncmp(product, "Vista-T630 ", 11)) { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->slow == -1) /* option is not predefined in umax.conf */ { DBG(DBG_warning," - activating slow option\n"); dev->slow = 1; } } else if (!strncmp(product, "UC630 ", 6)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - reposition_scanner waits until move of scan head has finished\n"); dev->pause_after_reposition = 0; /* call wait_scanner */ } else if (!strncmp(product, "UC840 ", 6)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - reposition_scanner waits until move of scan head has finished\n"); dev->pause_after_reposition = 0; /* call wait_scanner */ } else if (!strncmp(product, "UC1260 ", 7)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - setting gamma download curve format to type 1\n"); dev->inquiry_gamma_DCF = 1; /* define gamma download curve format */ DBG(DBG_warning," - reposition_scanner waits until move of scan head has finished\n"); dev->pause_after_reposition = 0; /* call wait_scanner */ } else if (!strncmp(product, "UC1200S ", 8)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - setting gamma download curve format to type 1\n"); dev->inquiry_gamma_DCF = 1; /* define gamma download curve format */ } else if (!strncmp(product, "UC1200SE ", 9)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - setting gamma download curve format to type 0\n"); dev->inquiry_gamma_DCF = 0; /* define gamma download curve format */ } else if (!strncmp(product, "ARCUS PLUS ", 11)) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - setting gamma download curve format to type 0\n"); dev->inquiry_gamma_DCF = 0; /* define gamma download curve format */ } else if ( (!strncmp(product, "UMAX S-12G ", 11)) || (!strncmp(product, "UMAX S-12 ", 10)) || (!strncmp(product, "SuperVista S-12 ", 16)) ) { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - setting maximum calibration data lines to 66\n"); set_inquiry_max_calibration_data_lines(dev->buffer[0], 66); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = -1; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } if (dev->calibration_area == -1) /* no calibration area defined in umax.conf */ { DBG(DBG_warning," - calibration by driver is done for each CCD pixel\n"); dev->calibration_area = UMAX_CALIBRATION_AREA_CCD; } } else if (!strncmp(product, "Mirage D-16L ", 13)) { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->calibration_area == -1) /* no calibration area defined in umax.conf */ { DBG(DBG_warning," - calibration by driver is done for each CCD pixel\n"); dev->calibration_area = UMAX_CALIBRATION_AREA_CCD; } if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = 308; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } } else if (!strncmp(product, "PowerLook III ", 14)) { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = 28; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } /* calibration_area = image */ if (dev->calibration_width_offset_batch == -99999) /* no calibration-width-offset for batch scanning defined in umax.conf */ { dev->calibration_width_offset_batch = 828; DBG(DBG_warning," - adding calibration width offset for batch scanning of %d pixels\n", dev->calibration_width_offset_batch); } } else if (!strncmp(product, "Power Look 2000", 15)) { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = 22; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } /* calibration_area = image */ if (dev->calibration_width_offset_batch == -99999) /* no calibration-width-offset for batch scanning defined in umax.conf */ { dev->calibration_width_offset_batch = 24; DBG(DBG_warning," - adding calibration width offset for batch scanning of %d pixels\n", dev->calibration_width_offset_batch); } } else if (!strncmp(product, "PowerLook 2100XL", 16)) { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = 52; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } /* calibration_area = image */ if (dev->calibration_width_offset_batch == -99999) /* no calibration-width-offset for batch scanning defined in umax.conf */ { dev->calibration_width_offset_batch = 1052; DBG(DBG_warning," - adding calibration width offset for batch scanning of %d pixels\n", dev->calibration_width_offset_batch); } dev->force_quality_calibration = 1; DBG(DBG_warning," - always set quality calibration\n"); /* the scanner uses the same exposure times for red, green and blue exposure_time_rgb_bind = 1 */ } else if (!strncmp(product, "PowerLook 3000 ", 15)) { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = 52; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } /* calibration_area = image */ if (dev->calibration_width_offset_batch == -99999) /* no calibration-width-offset for batch scanning defined in umax.conf */ { /* not tested */ dev->calibration_width_offset_batch = 1052; DBG(DBG_warning," - adding calibration width offset for batch scanning of %d pixels\n", dev->calibration_width_offset_batch); } } else { DBG(DBG_warning,"using standard options for %s\n", product); } } else if (!strncmp(vendor, "LinoHell ", 9)) { if ( (!strncmp(product, "Office ", 7)) || (!strncmp(product, "JADE ", 5)) ) /* is a Supervista S-12 */ { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - setting maximum calibration data lines to 66\n"); set_inquiry_max_calibration_data_lines(dev->buffer[0], 66); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = -1; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } if (dev->calibration_area == -1) /* no calibration area defined in umax.conf */ { DBG(DBG_warning," - calibration by driver is done for each CCD pixel\n"); dev->calibration_area = UMAX_CALIBRATION_AREA_CCD; } } else if (!strncmp(product, "OPAL2 ", 6)) /* looks like a Mirage II */ { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->gamma_lsb_padded == -1) /* nothing defined in umax.conf and not by backend */ { DBG(DBG_warning," - 16 bit gamma table is created lsb padded\n"); dev->gamma_lsb_padded = 1; } } } else if (!strncmp(vendor, "Linotype ", 9)) { if (!strncmp(product, "SAPHIR4 ", 8)) /* is a Powerlook III */ { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = 28; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } /* calibration_area = image */ if (dev->calibration_width_offset_batch == -99999) /* no calibration-width-offset for batch scanning defined in umax.conf */ { dev->calibration_width_offset_batch = 828; DBG(DBG_warning," - adding calibration width offset for batch scanning of %d pixels\n", dev->calibration_width_offset_batch); } } } else if (!strncmp(vendor, "HDM ", 4)) { if (!strncmp(product, "LS4H1S ", 7)) /* is a Powerlook III */ { DBG(DBG_warning,"setting up special options for %s\n", product); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = 28; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } /* calibration_area = image */ if (dev->calibration_width_offset_batch == -99999) /* no calibration-width-offset for batch scanning defined in umax.conf */ { dev->calibration_width_offset_batch = 828; DBG(DBG_warning," - adding calibration width offset for batch scanning of %d pixels\n", dev->calibration_width_offset_batch); } } } else if (!strncmp(vendor, "ESCORT ", 7)) { if (!strncmp(product, "Galleria 600S ", 14)) /* this is an Astra 600S */ { int add_len = get_inquiry_additional_length(dev->buffer[0]); DBG(DBG_warning,"setting up special options for %s\n", product); if (add_len == 0x8f) { DBG(DBG_warning," - correcting wrong inquiry data\n"); umax_do_new_inquiry(dev, 0x9b); /* get inquiry with correct length */ set_inquiry_length(dev->buffer[0], 0x9e); /* correct inquiry len */ /* correct color-ordering from pixel to line_with_ccd_distance */ set_inquiry_color_order(dev->buffer[0], IN_color_ordering_line_w_ccd); set_inquiry_fb_uta_line_arrangement_mode(dev->buffer[0], 32); set_inquiry_CCD_line_distance(dev->buffer[0], 8); /* we should reset ADF-bit here too */ if (dev->invert_shading_data == -1) /* nothing defined in umax.conf */ { DBG(DBG_warning," - activating inversion of shading data\n"); dev->invert_shading_data = 1; } } } } else if (!strncmp(vendor, "TriGem ", 7)) { if (!strncmp(product, "PowerScanII ", 12)) /* is a Supervista S-12 */ { DBG(DBG_warning,"setting up special options for %s\n", product); DBG(DBG_warning," - setting maximum calibration data lines to 66\n"); set_inquiry_max_calibration_data_lines(dev->buffer[0], 66); if (dev->calibration_width_offset == -99999) /* no calibration-width-offset defined in umax.conf */ { dev->calibration_width_offset = -1; DBG(DBG_warning," - adding calibration width offset of %d pixels\n", dev->calibration_width_offset); } if (dev->calibration_area == -1) /* no calibration area defined in umax.conf */ { DBG(DBG_warning," - calibration by driver is done for each CCD pixel\n"); dev->calibration_area = UMAX_CALIBRATION_AREA_CCD; } } } } /* ------------------------------------------------------------ UMAX IDENTIFY SCANNER ---------------------- */ static int umax_identify_scanner(Umax_Device *dev) { char vendor[10]; char product[0x12]; char version[6]; char *pp; DBG(DBG_proc,"identify_scanner\n"); umax_do_inquiry(dev); /* get inquiry */ if (get_inquiry_periph_devtype(dev->buffer[0]) != IN_periph_devtype_scanner) { return 1; } /* no scanner */ get_inquiry_vendor( (char *)dev->buffer[0], vendor); vendor[8] = ' '; vendor[9] = '\0'; get_inquiry_product((char *)dev->buffer[0], product); product[16] = ' '; product[17] = '\0'; get_inquiry_version((char *)dev->buffer[0], version); version[4] = ' '; version[5] = '\0'; pp = &vendor[8]; while (*(pp-1) == ' ') { *pp-- = '\0'; } pp = &product[0x10]; while (*(pp-1) == ' ') { *pp-- = '\0'; } pp = &version[4]; while (*pp == ' ') { *pp-- = '\0'; } DBG(DBG_info, "Found %s scanner %sversion %s on device %s\n", vendor, product, version, dev->devicename); /* look for scanners that do not give all inquiry-information */ /* and if possible use driver-known inquiry-data */ if (get_inquiry_additional_length(dev->buffer[0])>=0x8f) { int i = 0; while (strncmp("END_OF_LIST", scanner_str[2*i], 11) != 0) /* Now identify full supported scanners */ { if (!strncmp(vendor, scanner_str[2*i], strlen(scanner_str[2*i])) ) { if (!strncmp(product, scanner_str[2*i+1], strlen(scanner_str[2*i+1])) ) { umax_correct_inquiry(dev, vendor, product, version); return 0; } } i++; } if (strncmp(vendor, "UMAX ", 5)) { return 1; } /* not UMAX then abort */ DBG(DBG_error0, "WARNING: %s scanner %s version %s on device %s\n" "is currently an unrecognized device for this backend version.\n" "Please make sure you use the most recent version of the umax backend.\n" "You can download new umax-backend versions from:\n" "http://www.rauch-domain.de/sane-umax\n", vendor, product, version, dev->devicename); DBG(DBG_error0, "Inquiry seems to be ok.\n" "******************************************************************\n" "*** !!!! CONTINUE AT YOUR OWN RISK !!!! ***\n" "******************************************************************\n" "If you already use the most recent umax-backend version\n" "then please contact me: Oliver.Rauch@rauch-domain.de\n"); return 0; } else /* inquiry-data not complete */ if (!strncmp(vendor, "UMAX ", 5)) /* test UMAX-scanners with short inquiry */ { inquiry_blk inq_data; int i; for(i=0; i < known_inquiry; i++) { inq_data = *inquiry_table[i]; if (!strncmp(product, inq_data.scanner, strlen(inq_data.scanner))) { DBG(DBG_warning, "inquiry-block-length: %d\n", get_inquiry_additional_length(dev->buffer[0])+5); DBG(DBG_warning, "using driver-internal inquiry-data for this scanner!\n"); /* copy driver-defined inquiry-data into inquiry-block */ memcpy(dev->buffer[0]+0x24, inq_data.inquiry, inq_data.inquiry_len-0x24); /* correct variables */ set_inquiry_sc_uta(dev->buffer[0], get_inquiry_transavail(dev->buffer[0])); /* transparancy available ? */ set_inquiry_sc_adf(dev->buffer[0], get_inquiry_scanmode(dev->buffer[0])); /* automatic document feeder available ? */ set_inquiry_length(dev->buffer[0], inq_data.inquiry_len); umax_correct_inquiry(dev, vendor, product, version); return 0; /* ok */ } } DBG(DBG_error0, "ERROR: %s scanner %s version %s on device %s\n" "is currently an unrecognized device, and inquiry is too short,\n" "so we are not able to continue!\n" "Please make sure you use the most recent version of the umax backend.\n" "You can download new umax-backend versions from:\n" "http://www.rauch-domain.de/sane-umax\n" "You already use the most recent umax-backend version:\n" "Please contact me: Oliver.Rauch@rauch-domain.de\n", vendor, product, version, dev->devicename); } return 1; /* NO SUPPORTED SCANNER: short inquiry-block and unknown scanner */ } /* ------------------------------------------------------------ UMAX TRIM BUFSIZE -------------------------- */ static void umax_trim_rowbufsize(Umax_Device *dev) { unsigned int lines=0; if (dev->row_bufsize > dev->row_len) { lines = dev->row_bufsize / dev->row_len; if (lines > dev->lines_max) /* reduce number of lines to scan if set up in config file */ { lines = dev->lines_max; } dev->row_bufsize = lines * dev->row_len; } DBG(DBG_proc,"trim_rowbufsize: row_bufsize = %d bytes = %d lines\n", dev->row_bufsize, lines); } /* ------------------------------------------------------------ UMAX CALCULATE EXPOSURE TIME --------------- */ static void umax_calculate_exposure_time(Umax_Device *dev, int def, int *value) { int level; DBG(DBG_proc,"calculate_exposure_time\n"); if ( (*value)) { if ( (*value) == -1 ) { (*value) = def; } else { level = (*value) / dev->inquiry_exposure_time_step_unit; (*value) = inrange(dev->use_exposure_time_min, level, dev->inquiry_exposure_time_max); } } } /* ------------------------------------------------------------ UMAX CHECK VALUES -------------------------- */ static int umax_check_values(Umax_Device *dev) { double inquiry_x_orig; double inquiry_y_orig; double inquiry_width; double inquiry_length; unsigned int maxwidth; unsigned int maxlength; DBG(DBG_proc,"check_values\n"); /* ------------------------------- flatbed ------------------------------- */ dev->module = WD_module_flatbed; /* reset scanmode to flatbed first */ /* --------------------------------- uta --------------------------------- */ if (dev->uta != 0) { dev->module = WD_module_transparency; if ( (dev->inquiry_uta == 0) || (dev->inquiry_transavail == 0) ) { DBG(DBG_error, "ERROR: transparency mode not supported by scanner\n"); return(1); } } /* --------------------------------- adf --------------------------------- */ if (dev->adf != 0) { if (dev->inquiry_adf == 0) { DBG(DBG_error,"ERROR: adf mode not supported by scanner\n"); return(1); } } /* --------------------------------- dor --------------------------------- */ if (dev->dor != 0) { if (dev->inquiry_dor == 0) { DBG(DBG_error, "ERROR: double optical resolution not supported by scanner\n"); return(1); } } /* ------------------------------- resolution ------------------------ */ if (dev->dor == 0) /* standard (FB) */ { dev->relevant_optical_res = dev->inquiry_optical_res; dev->relevant_max_x_res = dev->inquiry_x_res; dev->relevant_max_y_res = dev->inquiry_y_res; } else /* DOR mode */ { dev->relevant_optical_res = dev->inquiry_dor_optical_res; dev->relevant_max_x_res = dev->inquiry_dor_x_res; dev->relevant_max_y_res = dev->inquiry_dor_y_res; } if (dev->x_resolution <= 0) { DBG(DBG_error,"ERROR: no x-resolution given\n"); return(1); } if (dev->x_resolution > dev->relevant_max_x_res) { dev->x_resolution = dev->relevant_max_x_res; } if (dev->x_resolution > dev->relevant_optical_res) { dev->scale_x = 2; } else { dev->scale_x = 1; } if (dev->y_resolution <= 0) { DBG(DBG_error,"ERROR: no y-resolution given\n"); return(1); } if (dev->y_resolution > dev->relevant_max_y_res) { dev->y_resolution = dev->relevant_max_y_res; } if (dev->y_resolution > dev->relevant_optical_res) { dev->scale_y = 2; } else if (dev->y_resolution > dev->relevant_optical_res/2) { dev->scale_y = 1; } else { /* astra 600S and 610S need this in umax_forget_line */ dev->scale_y = 0.5; } /* ------------------------------- scanarea ------------------------ */ if (dev->module == WD_module_flatbed) /* flatbed mode */ { inquiry_x_orig = 0; /* flatbed origin */ inquiry_y_orig = 0; inquiry_width = dev->inquiry_fb_width; /* flatbed width */ inquiry_length = dev->inquiry_fb_length; } else /* transparency mode */ { inquiry_x_orig = dev->inquiry_uta_x_off; /* uta origin */ inquiry_y_orig = dev->inquiry_uta_y_off; inquiry_width = dev->inquiry_uta_x_off + dev->inquiry_uta_width; /* uta width */ inquiry_length = dev->inquiry_uta_y_off + dev->inquiry_uta_length; } if (dev->dor != 0) { inquiry_x_orig = dev->inquiry_dor_x_off; /* dor origin */ inquiry_y_orig = dev->inquiry_dor_y_off; inquiry_width = dev->inquiry_dor_x_off + dev->inquiry_dor_width; /* dor width */ inquiry_length = dev->inquiry_dor_y_off + dev->inquiry_dor_length; } /* limit the size to what the scanner can scan. */ /* this is particularly important because the scanners don't have */ /* built-in checks and will happily grind their gears if this is exceeded. */ maxwidth = inquiry_width * dev->x_coordinate_base - dev->upper_left_x - 1; if ( (dev->scanwidth <= 0) || (dev->scanwidth > maxwidth) ) { dev->scanwidth = maxwidth; } if (dev->upper_left_x < inquiry_x_orig) { dev->upper_left_x = inquiry_x_orig; } maxlength = inquiry_length * dev->y_coordinate_base - dev->upper_left_y - 1; if ( (dev->scanlength <= 0) || (dev->scanlength > maxlength) ) { dev->scanlength = maxlength; } if (dev->upper_left_y < inquiry_y_orig) { dev->upper_left_y = inquiry_y_orig; } /* Now calculate width and length in pixels */ dev->width_in_pixels = umax_calculate_pixels(dev->scanwidth, dev->x_resolution, dev->relevant_optical_res * dev->scale_x, dev->x_coordinate_base); dev->length_in_pixels = umax_calculate_pixels(dev->scanlength, dev->y_resolution, dev->relevant_optical_res * dev->scale_y, dev->y_coordinate_base); if ((dev->scanwidth <= 0) || (dev->scanlength <= 0)) { DBG(DBG_error,"ERROR: scanwidth or scanlength not given\n"); return(1); } if (dev->bits_per_pixel_code == 1) { dev->bytes_per_color = 1; } else { dev->bytes_per_color = 2; } switch(dev->colormode) { case LINEART: dev->width_in_pixels -= dev->width_in_pixels % 8; dev->row_len = (dev->width_in_pixels / 8); break; case HALFTONE: dev->width_in_pixels -= dev->width_in_pixels % 8; dev->row_len = (dev->width_in_pixels / 8); break; case GRAYSCALE: dev->row_len = dev->width_in_pixels * dev->bytes_per_color; break; case RGB_LINEART: case RGB_HALFTONE: if (dev->three_pass) { dev->row_len = dev->width_in_pixels / 8 ; } else { dev->row_len = (dev->width_in_pixels / 8 ) * 3; } break; case RGB: if (dev->three_pass) /* three (24bpp) or six (30bpp) bytes per pixel */ { dev->row_len = dev->width_in_pixels * dev->bytes_per_color; } else { dev->row_len = dev->width_in_pixels * 3 * dev->bytes_per_color; } break; } /* ------------------------------- wdb length ------------------------ */ if (dev->wdb_len <= 0) { dev->wdb_len = dev->inquiry_wdb_len; if (dev->wdb_len <= 0) { DBG(DBG_error,"ERROR: wdb-length not given\n"); return(1); } } if (dev->wdb_len > used_WDB_size) { DBG(DBG_warning,"WARNING:window descriptor block too long, will be shortned!\n"); dev->wdb_len = used_WDB_size; } /* ----------------------------- cbhs-range ----------------------------- */ dev->threshold = umax_cbhs_correct(dev->inquiry_threshold_min, dev->threshold , dev->inquiry_threshold_max); dev->contrast = umax_cbhs_correct(dev->inquiry_contrast_min, dev->contrast , dev->inquiry_contrast_max); dev->brightness = umax_cbhs_correct(dev->inquiry_brightness_min, dev->brightness, dev->inquiry_brightness_max); dev->highlight_r = umax_cbhs_correct(dev->inquiry_highlight_min, dev->highlight_r, dev->inquiry_highlight_max); dev->highlight_g = umax_cbhs_correct(dev->inquiry_highlight_min, dev->highlight_g, dev->inquiry_highlight_max); dev->highlight_b = umax_cbhs_correct(dev->inquiry_highlight_min, dev->highlight_b, dev->inquiry_highlight_max); dev->shadow_r = umax_cbhs_correct(dev->inquiry_shadow_min, dev->shadow_r, dev->inquiry_shadow_max-1); dev->shadow_g = umax_cbhs_correct(dev->inquiry_shadow_min, dev->shadow_g, dev->inquiry_shadow_max-1); dev->shadow_b = umax_cbhs_correct(dev->inquiry_shadow_min, dev->shadow_b, dev->inquiry_shadow_max-1); if (dev->shadow_r >= dev->highlight_r) { dev->shadow_r = dev->highlight_r-1; } if (dev->shadow_g >= dev->highlight_g) { dev->shadow_g = dev->highlight_g-1; } if (dev->shadow_b >= dev->highlight_b) { dev->shadow_b = dev->highlight_b-1; } /* ----------------------- quality calibration and preview -------------- */ if (dev->inquiry_preview == 0) { if (dev->preview) { DBG(DBG_warning, "WARNING: fast preview function not supported by scanner\n"); dev->preview = 0; } } /* always set calibration lines because we also need this value if the scanner requeires calibration by driver */ dev->calib_lines = dev->inquiry_max_calib_lines; if (dev->force_quality_calibration) { dev->quality = 1; /* always use quality calibration */ } else if (dev->inquiry_quality_ctrl == 0) { if (dev->quality) { DBG(DBG_warning, "WARNING: quality calibration not supported by scanner\n"); dev->quality = 0; } } else { if (dev->preview != 0) { DBG(DBG_info, "quality calibration disabled in preview mode\n"); dev->quality = 0; /* do not use quality calibration in preview mode */ } } /* --------------------------- lamp intensity control ------------------- */ if (dev->inquiry_lamp_ctrl == 0) { if (dev->c_density || dev->s_density) { DBG(DBG_warning, "WARNING: scanner doesn't support lamp intensity control\n"); } dev->c_density = dev->s_density = 0; } /* --------------------------- reverse (negative) ----------------------- */ if (dev->reverse != 0) { if ( (dev->colormode == LINEART) || (dev->colormode == HALFTONE) || (dev->colormode == RGB_LINEART) || (dev->colormode == RGB_HALFTONE) ) { if (dev->inquiry_reverse == 0) { DBG(DBG_error, "ERROR: reverse for bi-level-image not supported\n"); return(1); } } else { dev->reverse = 0; } } if (dev->reverse_multi != 0) { if ((dev->colormode == RGB) || (dev->colormode == GRAYSCALE) ) { if (dev->inquiry_reverse_multi == 0) { DBG(DBG_error, "ERROR: reverse for multi-level-image not supported\n"); return(1); } } else { dev->reverse_multi = 0; } } /* ----------------------------- analog gamma ---------------------------- */ if (dev->inquiry_analog_gamma == 0) { if (dev->analog_gamma_r + dev->analog_gamma_g + dev->analog_gamma_b != 0) { DBG(DBG_warning,"WARNING: analog gamma correction not supported by scanner!\n"); } dev->analog_gamma_r = dev->analog_gamma_g = dev->analog_gamma_b = 0; } /* ---------------------------- digital gamma ---------------------------- */ if ( (dev->digital_gamma_r == 0) || (dev->digital_gamma_g == 0) || (dev->digital_gamma_b == 0) ) { if (dev->inquiry_gamma_dwload == 0) { DBG(DBG_warning, "WARNING: gamma download not available\n"); dev->digital_gamma_r = dev->digital_gamma_g = dev->digital_gamma_b = 15; } } /* ---------------------------- speed and smear ------------------------- */ if (dev->slow == 1) { dev->WD_speed = WD_speed_slow; } else { dev->WD_speed = WD_speed_fast; } if (dev->smear == 1) { dev->WD_speed += WD_speed_smear; } /* ---------------------- test bits per pixel --------------------------- */ if ( ( (dev->inquiry_GIB | 1) & dev->gamma_input_bits_code) == 0 ) { DBG(DBG_warning,"WARNING: selected gamma input bits not supported, gamma ignored\n"); dev->gamma_input_bits_code = 1; dev->digital_gamma_r = dev->digital_gamma_g = dev->digital_gamma_b = 15; } if ( ( (dev->inquiry_GOB | 1) & dev->bits_per_pixel_code) == 0 ) { DBG(DBG_error,"ERROR: selected bits per pixel not supported\n"); return(1); } /* ----------------------- scan mode dependencies ------------------------ */ switch(dev->colormode) { case LINEART: /* ------------ LINEART ------------- */ case RGB_LINEART: /* ---------- RGB_LINEART ----------- */ dev->use_exposure_time_min = dev->inquiry_exposure_time_l_min; if (dev->module == WD_module_flatbed) { dev->use_exposure_time_def_r = dev->inquiry_exposure_time_l_fb_def; } else { dev->use_exposure_time_def_r = dev->inquiry_exposure_time_l_uta_def; } if (dev->inquiry_lineart == 0) { DBG(DBG_error,"ERROR: lineart mode not supported by scanner\n"); return(1); } break; case HALFTONE: /* ----------- HALFTONE------------ */ case RGB_HALFTONE: /* --------- RGB_HALFTONE---------- */ dev->use_exposure_time_min = dev->inquiry_exposure_time_h_min; if (dev->module == WD_module_flatbed) { dev->use_exposure_time_def_r = dev->inquiry_exposure_time_h_fb_def; } else { dev->use_exposure_time_def_r = dev->inquiry_exposure_time_h_uta_def; } if (dev->inquiry_halftone == 0) { DBG(DBG_error,"ERROR: halftone mode not supported by scanner\n"); return(1); } break; case GRAYSCALE: /* ---------- GRAYSCALE ------------- */ dev->use_exposure_time_min = dev->inquiry_exposure_time_g_min; if (dev->module == WD_module_flatbed) { dev->use_exposure_time_def_r = dev->inquiry_exposure_time_g_fb_def; } else { dev->use_exposure_time_def_r = dev->inquiry_exposure_time_g_uta_def; } if (dev->inquiry_gray == 0) { DBG(DBG_error, "ERROR: grayscale mode not supported by scanner\n"); return(1); } break; case RGB: /* ----------------- COLOR ---------- */ dev->use_exposure_time_min = dev->inquiry_exposure_time_c_min; if (dev->module == WD_module_flatbed) { dev->use_exposure_time_def_r = dev->inquiry_exposure_time_c_fb_def_r; dev->use_exposure_time_def_g = dev->inquiry_exposure_time_c_fb_def_g; dev->use_exposure_time_def_b = dev->inquiry_exposure_time_c_fb_def_b; } else { dev->use_exposure_time_def_r = dev->inquiry_exposure_time_c_uta_def_r; dev->use_exposure_time_def_g = dev->inquiry_exposure_time_c_uta_def_g; dev->use_exposure_time_def_b = dev->inquiry_exposure_time_c_uta_def_b; } if (dev->inquiry_color == 0) { DBG(DBG_error,"ERROR: color mode not supported by scanner\n"); return(1); } if (dev->inquiry_one_pass_color) { DBG(DBG_info,"using one pass scanning mode\n"); if (dev->inquiry_color_order & IN_color_ordering_pixel) { DBG(DBG_info,"scanner uses color-pixel-ordering\n"); } else if (dev->inquiry_color_order & IN_color_ordering_line_no_ccd) { dev->CCD_distance = 0; dev->do_color_ordering = 1; DBG(DBG_info,"scanner uses color-line-ordering without CCD-distance\n"); } else if (dev->inquiry_color_order & IN_color_ordering_line_w_ccd) { dev->CCD_distance = dev->inquiry_CCD_line_distance; dev->do_color_ordering = 1; switch (dev->inquiry_fb_uta_color_arrangement) /* define color order for line ordering */ { case 1: dev->CCD_color[0] = CCD_color_green; dev->CCD_color[1] = CCD_color_blue; dev->CCD_color[2] = CCD_color_green; dev->CCD_color[3] = CCD_color_blue; dev->CCD_color[4] = CCD_color_red; dev->CCD_color[5] = CCD_color_green; dev->CCD_color[6] = CCD_color_blue; dev->CCD_color[7] = CCD_color_red; dev->CCD_color[8] = CCD_color_red; break; case 2: dev->CCD_color[0] = CCD_color_blue; dev->CCD_color[1] = CCD_color_green; dev->CCD_color[2] = CCD_color_blue; dev->CCD_color[3] = CCD_color_green; dev->CCD_color[4] = CCD_color_red; dev->CCD_color[5] = CCD_color_blue; dev->CCD_color[6] = CCD_color_green; dev->CCD_color[7] = CCD_color_red; dev->CCD_color[8] = CCD_color_red; break; case 3: dev->CCD_color[0] = CCD_color_red; dev->CCD_color[1] = CCD_color_blue; dev->CCD_color[2] = CCD_color_red; dev->CCD_color[3] = CCD_color_blue; dev->CCD_color[4] = CCD_color_green; dev->CCD_color[5] = CCD_color_red; dev->CCD_color[6] = CCD_color_blue; dev->CCD_color[7] = CCD_color_green; dev->CCD_color[8] = CCD_color_green; break; case 4: /* may be wrong !!! */ dev->CCD_color[0] = CCD_color_red; dev->CCD_color[1] = CCD_color_green; dev->CCD_color[2] = CCD_color_red; dev->CCD_color[3] = CCD_color_green; dev->CCD_color[4] = CCD_color_red; dev->CCD_color[5] = CCD_color_blue; dev->CCD_color[6] = CCD_color_green; dev->CCD_color[7] = CCD_color_blue; dev->CCD_color[8] = CCD_color_blue; break; case 32: /* not defined from UMAX, for Astra 600S */ dev->CCD_color[0] = CCD_color_green; dev->CCD_color[1] = CCD_color_green; dev->CCD_color[2] = CCD_color_blue; dev->CCD_color[3] = CCD_color_green; dev->CCD_color[4] = CCD_color_red; dev->CCD_color[5] = CCD_color_blue; dev->CCD_color[6] = CCD_color_red; dev->CCD_color[7] = CCD_color_blue; dev->CCD_color[8] = CCD_color_red; break; case 33: /* not defined from UMAX, for Astra 610S */ dev->CCD_color[0] = CCD_color_red; dev->CCD_color[1] = CCD_color_red; dev->CCD_color[2] = CCD_color_blue; dev->CCD_color[3] = CCD_color_red; dev->CCD_color[4] = CCD_color_green; dev->CCD_color[5] = CCD_color_blue; dev->CCD_color[6] = CCD_color_green; dev->CCD_color[7] = CCD_color_blue; dev->CCD_color[8] = CCD_color_green; break; default: dev->CCD_color[0] = CCD_color_green; dev->CCD_color[1] = CCD_color_blue; dev->CCD_color[2] = CCD_color_green; dev->CCD_color[3] = CCD_color_blue; dev->CCD_color[4] = CCD_color_red; dev->CCD_color[5] = CCD_color_green; dev->CCD_color[6] = CCD_color_blue; dev->CCD_color[7] = CCD_color_red; dev->CCD_color[8] = CCD_color_red; } DBG(DBG_info,"scanner uses color-line-ordering with CCD-distance of %d lines\n", dev->CCD_distance); } else { DBG(DBG_error,"ERROR: color-ordering-type not supported \n"); return(1); } } else { DBG(DBG_info,"using three pass scanning mode\n"); dev->three_pass=1; } break; } /* switch */ /* ----------------------------- color ordering ------------------------ */ if (dev->do_color_ordering != 0) { if ( (dev->colormode != RGB) || (dev->three_pass != 0) ) { dev->do_color_ordering = 0; /* color ordering not necessery */ } } return(0); } /* ------------------------------------------------------------ UMAX GET INQUIRY VALUES -------------------- */ static void umax_get_inquiry_values(Umax_Device *dev) { unsigned char * inquiry_block; DBG(DBG_proc,"get_inquiry_values\n"); inquiry_block = dev->buffer[0]; dev->inquiry_len = get_inquiry_additional_length(dev->buffer[0])+5; dev->cbhs_range = dev->inquiry_cbhs = get_inquiry_CBHS(inquiry_block); if (dev->cbhs_range > IN_CBHS_255) { dev->cbhs_range = IN_CBHS_255; } if (dev->cbhs_range == IN_CBHS_50) { dev->inquiry_contrast_min = 103; /* minimum value for c */ dev->inquiry_contrast_max = 153; /* maximum value for c */ dev->inquiry_brightness_min = 78; /* minimum value for b */ dev->inquiry_brightness_max = 178; /* maximum value for b */ dev->inquiry_threshold_min = 78; /* minimum value for t */ dev->inquiry_threshold_max = 178; /* maximum value for t */ dev->inquiry_highlight_min = 1; /* minimum value for h */ dev->inquiry_highlight_max = 50; /* maximum value for h */ dev->inquiry_shadow_min = 0; /* minimum value for s */ dev->inquiry_shadow_max = 49; /* maximum value for s */ } get_inquiry_vendor( (char *)inquiry_block, dev->vendor); dev->vendor[8] ='\0'; get_inquiry_product((char *)inquiry_block, dev->product); dev->product[16]='\0'; get_inquiry_version((char *)inquiry_block, dev->version); dev->version[4] ='\0'; dev->inquiry_batch_scan = get_inquiry_fw_batch_scan(inquiry_block); dev->inquiry_quality_ctrl = get_inquiry_fw_quality(inquiry_block); dev->inquiry_preview = get_inquiry_fw_fast_preview(inquiry_block); dev->inquiry_lamp_ctrl = get_inquiry_fw_lamp_int_cont(inquiry_block); dev->inquiry_calibration = get_inquiry_fw_calibration(inquiry_block); dev->inquiry_transavail = get_inquiry_transavail(inquiry_block); dev->inquiry_adfmode = get_inquiry_scanmode(inquiry_block); if (dev->inquiry_len<=0x8f) { DBG(DBG_warning, "WARNING: inquiry return block is unexpected short.\n"); } dev->inquiry_uta = get_inquiry_sc_uta(inquiry_block); dev->inquiry_adf = get_inquiry_sc_adf(inquiry_block); dev->inquiry_one_pass_color = get_inquiry_sc_one_pass_color(inquiry_block); dev->inquiry_three_pass_color = get_inquiry_sc_three_pass_color(inquiry_block); dev->inquiry_color = get_inquiry_sc_color(inquiry_block); dev->inquiry_gray = get_inquiry_sc_gray(inquiry_block); dev->inquiry_halftone = get_inquiry_sc_halftone(inquiry_block); dev->inquiry_lineart = get_inquiry_sc_lineart(inquiry_block); dev->inquiry_exposure_adj = get_inquiry_fw_adjust_exposure_tf(inquiry_block); dev->inquiry_exposure_time_step_unit = get_inquiry_exposure_time_step_unit(inquiry_block); dev->inquiry_exposure_time_max = get_inquiry_exposure_time_max(inquiry_block); /* --- lineart --- */ dev->inquiry_exposure_time_l_min = get_inquiry_exposure_time_lhg_min(inquiry_block); dev->inquiry_exposure_time_l_fb_def = get_inquiry_exposure_time_lh_def_fb(inquiry_block); dev->inquiry_exposure_time_l_uta_def = get_inquiry_exposure_time_lh_def_uta(inquiry_block); /* --- halftone --- */ dev->inquiry_exposure_time_h_min = get_inquiry_exposure_time_lhg_min(inquiry_block); dev->inquiry_exposure_time_h_fb_def = get_inquiry_exposure_time_lh_def_fb(inquiry_block); dev->inquiry_exposure_time_h_uta_def = get_inquiry_exposure_time_lh_def_uta(inquiry_block); /* --- grayscale --- */ dev->inquiry_exposure_time_g_min = get_inquiry_exposure_time_lhg_min(inquiry_block); dev->inquiry_exposure_time_g_fb_def = get_inquiry_exposure_time_gray_def_fb(inquiry_block); dev->inquiry_exposure_time_g_uta_def = get_inquiry_exposure_time_gray_def_uta(inquiry_block); /* --- color --- */ dev->inquiry_exposure_time_c_min = get_inquiry_exposure_time_color_min(inquiry_block); dev->inquiry_exposure_time_c_fb_def_r = get_inquiry_exposure_time_def_r_fb(inquiry_block); dev->inquiry_exposure_time_c_fb_def_g = get_inquiry_exposure_time_def_g_fb(inquiry_block); dev->inquiry_exposure_time_c_fb_def_b = get_inquiry_exposure_time_def_g_fb(inquiry_block); dev->inquiry_exposure_time_c_uta_def_r = get_inquiry_exposure_time_def_r_uta(inquiry_block); dev->inquiry_exposure_time_c_uta_def_g = get_inquiry_exposure_time_def_g_uta(inquiry_block); dev->inquiry_exposure_time_c_uta_def_b = get_inquiry_exposure_time_def_b_uta(inquiry_block); dev->inquiry_dor = get_inquiry_sc_double_res(inquiry_block); dev->inquiry_reverse = get_inquiry_sc_bi_image_reverse(inquiry_block); dev->inquiry_reverse_multi = get_inquiry_sc_multi_image_reverse(inquiry_block); dev->inquiry_shadow = 1 - get_inquiry_sc_no_shadow(inquiry_block); dev->inquiry_highlight = 1 - get_inquiry_sc_no_highlight(inquiry_block); dev->inquiry_analog_gamma = get_inquiry_analog_gamma(inquiry_block); dev->inquiry_lineart_order = get_inquiry_lineart_order(inquiry_block); dev->inquiry_lens_cal_in_doc_pos = get_inquiry_manual_focus(inquiry_block); dev->inquiry_manual_focus = get_inquiry_manual_focus(inquiry_block); dev->inquiry_sel_uta_lens_cal_pos = get_inquiry_manual_focus(inquiry_block); dev->inquiry_gamma_dwload = get_inquiry_gamma_download_available(inquiry_block); if (get_inquiry_gamma_type_2(inquiry_block) != 0) { dev->inquiry_gamma_DCF = 2; } dev->inquiry_GIB = get_inquiry_gib(inquiry_block); dev->inquiry_GOB = get_inquiry_gob(inquiry_block); dev->inquiry_color_order = get_inquiry_color_order(inquiry_block); dev->inquiry_vidmem = get_inquiry_max_vidmem(inquiry_block); /* optical resolution = [0x73] * 100 + [0x94] , 0x94 is not always defined */ dev->inquiry_optical_res = 100 * get_inquiry_max_opt_res(inquiry_block); if (dev->inquiry_len > 0x94) { dev->inquiry_optical_res += get_inquiry_optical_resolution_residue(inquiry_block); } /* x resolution = [0x74] * 100 + [0x95] , 0x95 is not always defined */ dev->inquiry_x_res = 100 * get_inquiry_max_x_res(inquiry_block); if (dev->inquiry_len > 0x95) { dev->inquiry_x_res+= get_inquiry_x_resolution_residue(inquiry_block); }; /* y resolution = [0x75] * 100 + [0x96] , 0x96 is not always defined */ dev->inquiry_y_res = 100 * get_inquiry_max_y_res(inquiry_block); if (dev->inquiry_len > 0x96) { dev->inquiry_y_res+= get_inquiry_y_resolution_residue(inquiry_block); } /* optical resolution = [0x83] * 100 + [0xa0] , 0xa0 is not always defined */ dev->inquiry_dor_optical_res = 100 * get_inquiry_dor_max_opt_res(inquiry_block); if (dev->inquiry_len > 0xa0) { dev->inquiry_dor_optical_res += get_inquiry_dor_optical_resolution_residue(inquiry_block); } /* x resolution = [0x84] * 100 + [0xa1] , 0xa1 is not always defined */ dev->inquiry_dor_x_res = 100 * get_inquiry_dor_max_x_res(inquiry_block); if (dev->inquiry_len > 0xa1) { dev->inquiry_dor_x_res+= get_inquiry_dor_x_resolution_residue(inquiry_block); } /* y resolution = [0x85] * 100 + [0xa2] , 0xa2 is not always defined */ dev->inquiry_dor_y_res = 100 * get_inquiry_dor_max_y_res(inquiry_block); if (dev->inquiry_len > 0xa2) { dev->inquiry_dor_y_res+= get_inquiry_dor_y_resolution_residue(inquiry_block); } if (dev->inquiry_dor) /* DOR mode available ? */ { /* if DOR resolutions are not defined, use double of standard resolution */ if (dev->inquiry_dor_optical_res == 0) { dev->inquiry_dor_optical_res = dev->inquiry_optical_res * 2; } if (dev->inquiry_dor_x_res == 0) { dev->inquiry_dor_x_res = dev->inquiry_x_res * 2; } if (dev->inquiry_dor_y_res == 0) { dev->inquiry_dor_y_res = dev->inquiry_y_res * 2; } } dev->inquiry_fb_width = (double)get_inquiry_fb_max_scan_width(inquiry_block) * 0.01; dev->inquiry_fb_length = (double)get_inquiry_fb_max_scan_length(inquiry_block) * 0.01; dev->inquiry_uta_width = (double)get_inquiry_uta_max_scan_width(inquiry_block) * 0.01; dev->inquiry_uta_length = (double)get_inquiry_uta_max_scan_length(inquiry_block) * 0.01; dev->inquiry_uta_x_off = (double)get_inquiry_uta_x_original_point(inquiry_block) * 0.01; dev->inquiry_uta_y_off = (double)get_inquiry_uta_y_original_point(inquiry_block) * 0.01; dev->inquiry_dor_width = (double)get_inquiry_dor_max_scan_width(inquiry_block) * 0.01; dev->inquiry_dor_length = (double)get_inquiry_dor_max_scan_length(inquiry_block) * 0.01; dev->inquiry_dor_x_off = (double)get_inquiry_dor_x_original_point(inquiry_block) * 0.01; dev->inquiry_dor_y_off = (double)get_inquiry_dor_y_original_point(inquiry_block) * 0.01; dev->inquiry_max_warmup_time = get_inquiry_lamp_warmup_maximum_time(inquiry_block) * 2; dev->inquiry_wdb_len = get_inquiry_wdb_length(inquiry_block); /* it is not guaranteed that the following values are in the inquiry return block */ /* 0x9a */ if (dev->inquiry_len<=0x9a) { return; } dev->inquiry_max_calib_lines = get_inquiry_max_calibration_data_lines(inquiry_block); /* 0x9b */ if (dev->inquiry_len<=0x9b) { return; } dev->inquiry_fb_uta_color_arrangement = get_inquiry_fb_uta_line_arrangement_mode(inquiry_block); /* 0x9c */ if (dev->inquiry_len<=0x9c) { return; } dev->inquiry_adf_color_arrangement = get_inquiry_adf_line_arrangement_mode(inquiry_block); /* 0x9d */ if (dev->inquiry_len<=0x9d) { return; } dev->inquiry_CCD_line_distance = get_inquiry_CCD_line_distance(inquiry_block); return; } /* ------------------------------------------------------------ UMAX CALCULATE ANALOG GAMMA ---------------- */ static int umax_calculate_analog_gamma(double value) { int gamma; if (value < 1.0) { value=1.0; } if (value > 2.0) { value=2.0; } gamma=0; /* select gamma_value from analog_gamma_table */ while (value>analog_gamma_table[gamma]) { gamma++; } if (gamma) { if ((analog_gamma_table[gamma-1] + analog_gamma_table[gamma]) /2 > value) { gamma--; } } return(gamma); } /* ------------------------------------------------------------ UMAX OUTPUT IMAGE DATA -------------------- */ static void umax_output_image_data(Umax_Device *dev, FILE *fp, unsigned int data_to_read, int bufnr) { if (dev->do_color_ordering == 0) /* pixel ordering */ { if ((dev->inquiry_lineart_order) && (dev->colormode == LINEART)) /* lineart with LSB first */ { unsigned int i, j; int new, old; for (i=0; ibuffer[bufnr][i]; new = 0; for (j=0; j<8; j++) /* reverse bit order of 1 byte */ { new = (new << 1) + (old & 1); old = old >> 1; } dev->buffer[bufnr][i]=new; } } fwrite(dev->buffer[bufnr], 1, data_to_read, fp); } else /* line ordering */ { unsigned char *linesource = dev->buffer[bufnr]; unsigned char *pixelsource; int bytes = 1; int lines; int i; if (dev->bits_per_pixel_code != 1) /* >24 bpp */ { bytes = 2; } lines = data_to_read / (dev->width_in_pixels * bytes); for(i=0; iwidth_in_pixels * bytes; pixelsource = umax_get_pixel_line(dev); if (pixelsource != NULL) { fwrite(pixelsource, bytes, dev->width_in_pixels * 3, fp); } } } } /* ------------------------------------------------------------ UMAX READER PROCESS ------------------------ */ static int umax_reader_process(Umax_Device *dev, FILE *fp, unsigned int image_size) { int status; int bytes = 1; int queue_filled = 0; unsigned int bufnr_queue = 0; unsigned int bufnr_read = 0; unsigned int data_left_to_read = image_size; unsigned int data_left_to_queue = image_size; unsigned int data_to_read; unsigned int data_to_queue; dev->row_bufsize = dev->bufsize; umax_trim_rowbufsize(dev); /* trim bufsize */ if (dev->bits_per_pixel_code != 1) /* >24 bpp */ { bytes = 2; } DBG(DBG_read,"reading %u bytes in blocks of %u bytes\n", image_size, dev->row_bufsize); if (dev->pixelbuffer != NULL) /* buffer exists? */ { free(dev->pixelbuffer); dev->pixelbuffer = NULL; } if (dev->do_color_ordering != 0) { DBG(DBG_info,"ordering from line-order to pixel-order\n"); dev->pixelline_max = 3 * dev->CCD_distance * dev->scale_y + 2; dev->pixelbuffer = malloc(dev->width_in_pixels * dev->pixelline_max * bytes * 3); if (dev->pixelbuffer == NULL) /* NO MEMORY */ { return -1; } } WAIT_SCANNER; do { if (data_left_to_queue) { data_to_queue = (data_left_to_queue < dev->row_bufsize) ? data_left_to_queue : dev->row_bufsize; /* umax_get_data_buffer_status(dev); */ status = umax_queue_read_image_data_req(dev, data_to_queue, bufnr_queue); if (status == 0) /* no error but nothing queued */ { continue; } if (status == -1) /* error */ { DBG(DBG_error,"ERROR: umax_reader_process: unable to queue read image data request!\n"); free(dev->pixelbuffer); dev->pixelbuffer = NULL; return(-1); } data_left_to_queue -= data_to_queue; DBG(DBG_read, "umax_reader_process: read image data queued for buffer[%d] \n", bufnr_queue); bufnr_queue++; if (bufnr_queue >= dev->scsi_maxqueue) { bufnr_queue = 0; queue_filled = 1; /* ok, we can start to read the queued buffers - if not already started */ } if (!data_left_to_queue) { queue_filled = 1; /* ok, we can start to read the queued buffer(s) - all read requests are send */ } } if (queue_filled) /* queue filled, ok we can read data */ { status = umax_wait_queued_image_data(dev, bufnr_read); if (status == -1) { DBG(DBG_error,"ERROR: umax_reader_process: unable to get image data from scanner!\n"); free(dev->pixelbuffer); dev->pixelbuffer = NULL; return(-1); } data_to_read = dev->length_read[bufnr_read]; /* number of bytes in buffer */ umax_output_image_data(dev, fp, data_to_read, bufnr_read); data_left_to_read -= data_to_read; DBG(DBG_read, "umax_reader_process: buffer of %d bytes read; %d bytes to go\n", data_to_read, data_left_to_read); /* if we did not get all requested data increase data_left_to_queue so that we get all needed data */ if (dev->length_read[bufnr_read] != dev->length_queued[bufnr_read]) { data_left_to_queue += dev->length_queued[bufnr_read] - dev->length_read[bufnr_read]; } bufnr_read++; if (bufnr_read >= dev->scsi_maxqueue) { bufnr_read = 0; } } } while (data_left_to_read); free(dev->pixelbuffer); dev->pixelbuffer = NULL; return 0; } /* ------------------------------------------------------------ UMAX INITIALIZE VALUES --------------------- */ static void umax_initialize_values(Umax_Device *dev) /* called each time before setting scan-values */ { /* Initialize dev structure */ DBG(DBG_proc,"initialize_values\n"); dev->three_pass = 0; /* 1 if threepas_mode only */ dev->row_len = -1; dev->max_value = 255; /* maximum value */ dev->wdb_len = 0; dev->width_in_pixels = 0; /* scan width in pixels */ dev->length_in_pixels = 0; /* scan length in pixels */ dev->scanwidth = 0; /* width in inch at x_coordinate_base dpi */ dev->scanlength = 0; /* length in inch at y_coordinate_base dpi */ dev->x_resolution = 0; dev->y_resolution = 0; dev->upper_left_x = 0; /* at 1200pt/inch */ dev->upper_left_y = 0; /* at 1200pt/inch */ dev->bytes_per_color = 0; /* bytes for each color */ dev->bits_per_pixel = 8; /* number of bits per pixel */ dev->bits_per_pixel_code = 1; /* 1 = 8/24 bpp, 2 = 9/27 bpp, 4 = 10/30 bpp */ dev->gamma_input_bits_code = 1; /* 8 = 12/36 bpp, 16 = 14/42 bpp, 32 = 16/48 bpp */ dev->set_auto = 0; /* 0 or 1 */ dev->preview = 0; /* 1 for preview */ dev->quality = 0; /* quality calibration */ dev->warmup = 0; /* warmup-bit */ dev->fix_focus_position = 0; /* fix focus position */ dev->lens_cal_in_doc_pos = 0; /* lens calibration in document position */ dev->disable_pre_focus = 0; /* disable pre focus */ dev->holder_focus_pos_0mm = 0; /* 0.6mm <-> 0.0mm holder focus position */ dev->manual_focus = 0; /* automatic <-> manual focus */ dev->colormode = 0; /* LINEART, HALFTONE, GRAYSCALE or RGB */ dev->adf = 0; /* 1 if adf shall be used */ dev->uta = 0; /* 1 if uta shall be used */ dev->module = WD_module_flatbed; dev->cbhs_range = WD_CBHS_255; dev->dor = 0; dev->halftone = WD_halftone_8x8_1; dev->reverse = 0; dev->reverse_multi = 0; dev->calibration = 0; dev->exposure_time_calibration_r = 0; /* use this for calibration */ dev->exposure_time_calibration_g = 0; /* use this for calibration */ dev->exposure_time_calibration_b = 0; /* use this for calibration */ dev->exposure_time_scan_r = 0; /* use this for scan */ dev->exposure_time_scan_g = 0; /* use this for scan */ dev->exposure_time_scan_b = 0; /* use this for scan */ dev->c_density = WD_lamp_c_density_auto; /* calibration lamp density */ dev->s_density = WD_lamp_s_density_auto; /* next scan lamp density */ dev->threshold = 128; /* threshold for lineart mode */ dev->brightness = 128; /* brightness for halftone mode */ dev->contrast = 128; /* contrast for halftone mode */ dev->highlight_r = 255; /* highlight gray/red */ dev->highlight_g = 255; /* highlight green */ dev->highlight_b = 255; /* highlight blue */ dev->shadow_r = 0; /* shadow gray/red */ dev->shadow_g = 0; /* shadow green */ dev->shadow_b = 0; /* shadow blue */ dev->digital_gamma_r = WD_gamma_normal; dev->digital_gamma_g = WD_gamma_normal; dev->digital_gamma_b = WD_gamma_normal; dev->analog_gamma_r = 0; /* analog gamma for red and gray to 1.0 */ dev->analog_gamma_g = 0; /* analog gamma for green to 1.0 */ dev->analog_gamma_b = 0; /* analog gamma for blue to 1.0 */ dev->pixelline_ready[0] = 0; /* reset all values for color ordering */ dev->pixelline_ready[1] = 0; dev->pixelline_ready[2] = 0; dev->pixelline_next[0] = 0; dev->pixelline_next[1] = 0; dev->pixelline_next[2] = 0; dev->pixelline_del[0] = 1; dev->pixelline_del[1] = 1; dev->pixelline_del[2] = 1; dev->pixelline_optic[0] = 1; dev->pixelline_optic[1] = 1; dev->pixelline_optic[2] = 1; dev->pixelline_max = 0; dev->pixelline_opt_res = 0; dev->pixelline_read = 0; dev->pixelline_written = 0; dev->CCD_distance = 0; dev->calib_lines = 0; /* request calibration lines */ dev->do_calibration = 0; /* no calibration by driver */ dev->do_color_ordering = 0; /* no line- to pixel-mode ordering */ dev->button0_pressed = 0; /* reset button 0 pressed flag */ dev->button1_pressed = 0; /* reset button 1 pressed flag */ dev->button2_pressed = 0; /* reset button 2 pressed flag */ } /* ------------------------------------------------------------ UMAX INIT ---------------------------------- */ static void umax_init(Umax_Device *dev) /* umax_init is called once while driver-initialization */ { DBG(DBG_proc,"init\n"); dev->devicename = NULL; dev->pixelbuffer = NULL; /* config file or predefined settings */ if (dev->connection_type == SANE_UMAX_SCSI) { dev->request_scsi_maxqueue = umax_scsi_maxqueue; } else /* SANE_UMAX_USB, USB does not support command queueing */ { DBG(DBG_info2, "setting request_scsi_maxqueue = 1 for USB connection\n"); dev->request_scsi_maxqueue = 1; } dev->request_preview_lines = umax_preview_lines; dev->request_scan_lines = umax_scan_lines; dev->handle_bad_sense_error = umax_handle_bad_sense_error; dev->execute_request_sense = umax_execute_request_sense; dev->scsi_buffer_size_min = umax_scsi_buffer_size_min; dev->scsi_buffer_size_max = umax_scsi_buffer_size_max; dev->force_preview_bit_rgb = umax_force_preview_bit_rgb; dev->slow = umax_slow; dev->smear = umax_smear; dev->calibration_area = umax_calibration_area; dev->calibration_width_offset = umax_calibration_width_offset; dev->calibration_width_offset_batch = umax_calibration_width_offset_batch; dev->calibration_bytespp = umax_calibration_bytespp; dev->exposure_time_rgb_bind = umax_exposure_time_rgb_bind; dev->invert_shading_data = umax_invert_shading_data; dev->lamp_control_available = umax_lamp_control_available; dev->gamma_lsb_padded = umax_gamma_lsb_padded; DBG(DBG_info, "request_scsi_maxqueue = %d\n", dev->request_scsi_maxqueue); DBG(DBG_info, "request_preview_lines = %d\n", dev->request_preview_lines); DBG(DBG_info, "request_scan_lines = %d\n", dev->request_scan_lines); DBG(DBG_info, "handle_bad_sense_error = %d\n", dev->handle_bad_sense_error); DBG(DBG_info, "execute_request_sense = %d\n", dev->execute_request_sense); DBG(DBG_info, "scsi_buffer_size_min = %d\n", dev->scsi_buffer_size_min); DBG(DBG_info, "scsi_buffer_size_max = %d\n", dev->scsi_buffer_size_max); DBG(DBG_info, "force_preview_bit_rgb = %d\n", dev->force_preview_bit_rgb); DBG(DBG_info, "slow = %d\n", dev->slow); DBG(DBG_info, "smear = %d\n", dev->smear); DBG(DBG_info, "calibration_area = %d\n", dev->calibration_area); DBG(DBG_info, "calibration_width_offset = %d\n", dev->calibration_width_offset); DBG(DBG_info, "calibration_width_offset_batch = %d\n", dev->calibration_width_offset_batch); DBG(DBG_info, "calibration_bytespp = %d\n", dev->calibration_bytespp); DBG(DBG_info, "exposure_time_rgb_bind = %d\n", dev->exposure_time_rgb_bind); DBG(DBG_info, "invert_shading_data = %d\n", dev->invert_shading_data); DBG(DBG_info, "lamp_control_available = %d\n", dev->lamp_control_available); dev->inquiry_len = 0; dev->inquiry_wdb_len = -1; dev->inquiry_optical_res = -1; dev->inquiry_x_res = -1; dev->inquiry_y_res = -1; dev->inquiry_fb_width = -1; dev->inquiry_fb_length = -1; dev->inquiry_uta_width = -1; dev->inquiry_uta_length = -1; dev->inquiry_dor_width = -1; dev->inquiry_dor_length = -1; dev->inquiry_exposure_adj = 0; dev->inquiry_exposure_time_step_unit = -1; /* exposure time unit in micro sec */ dev->inquiry_exposure_time_max = -1; /* exposure time maximum */ dev->inquiry_exposure_time_l_min = -1; /* exposure time minimum for lineart */ dev->inquiry_exposure_time_l_fb_def = -1; /* exposure time default for lineart flatbed */ dev->inquiry_exposure_time_l_uta_def = -1; /* exposure time default for lineart uta */ dev->inquiry_exposure_time_h_min = -1; /* exposure time minimum for halftone */ dev->inquiry_exposure_time_h_fb_def = -1; /* exposure time default for halftone flatbed */ dev->inquiry_exposure_time_h_uta_def = -1; /* exposure time default for halftone uta */ dev->inquiry_exposure_time_g_min = -1; /* exposure time minimum for grayscale */ dev->inquiry_exposure_time_g_fb_def = -1; /* exposure time default for grayscale flatbed */ dev->inquiry_exposure_time_g_uta_def = -1; /* exposure time default for grayscale uta */ dev->inquiry_exposure_time_c_min = -1; /* exposure time minimum for color */ dev->inquiry_exposure_time_c_fb_def_r = -1; /* exposure time default for color flatbed red */ dev->inquiry_exposure_time_c_fb_def_g = -1; /* exposure time default for color flatbed green */ dev->inquiry_exposure_time_c_fb_def_b = -1; /* exposure time default for color flatbed blue */ dev->inquiry_exposure_time_c_uta_def_r = -1; /* exposure time default for color uta red */ dev->inquiry_exposure_time_c_uta_def_g = -1; /* exposure time default for color uta green */ dev->inquiry_exposure_time_c_uta_def_b = -1; /* exposure time default for color uta blue */ dev->inquiry_max_warmup_time = 0; /* maximum warmup time */ dev->inquiry_cbhs = WD_CBHS_255; dev->inquiry_contrast_min = 1; /* minimum value for c */ dev->inquiry_contrast_max = 255; /* maximum value for c */ dev->inquiry_brightness_min = 1; /* minimum value for b */ dev->inquiry_brightness_max = 255; /* maximum value for b */ dev->inquiry_threshold_min = 1; /* minimum value for t */ dev->inquiry_threshold_max = 255; /* maximum value for t */ dev->inquiry_highlight_min = 1; /* minimum value for h */ dev->inquiry_highlight_max = 255; /* maximum value for h */ dev->inquiry_shadow_min = 0; /* minimum value for s */ dev->inquiry_shadow_max = 254; /* maximum value for s */ dev->inquiry_quality_ctrl = 0; dev->inquiry_preview = 0; dev->inquiry_lamp_ctrl = 0; dev->inquiry_transavail = 0; dev->inquiry_uta = 0; dev->inquiry_adfmode = 0; dev->inquiry_adf = 0; dev->inquiry_dor = 0; dev->inquiry_reverse = 0; dev->inquiry_reverse_multi = 0; dev->inquiry_analog_gamma = 0; dev->inquiry_gamma_dwload = 0; dev->inquiry_one_pass_color = 0; dev->inquiry_three_pass_color = 0; dev->inquiry_color = 0; dev->inquiry_gray = 0; dev->inquiry_halftone = 0; dev->inquiry_lineart = 0; dev->inquiry_calibration = 1; dev->inquiry_shadow = 0; dev->inquiry_highlight = 0; dev->inquiry_gamma_DCF = -1; dev->inquiry_max_calib_lines = 66; /* most scanners use 66 lines, so lets define it as default */ dev->common_xy_resolutions = 0; dev->x_coordinate_base = 1200; /* these are the 1200pt/inch */ dev->y_coordinate_base = 1200; /* these are the 1200pt/inch */ dev->button0_pressed = 0; /* reset button 0 pressed flag */ dev->button1_pressed = 0; /* reset button 1 pressed flag */ dev->button2_pressed = 0; /* reset button 2 pressed flag */ dev->pause_for_color_calibration = 0; /* pause between start_scan and do_calibration in ms */ dev->pause_for_gray_calibration = 0; /* pause between start_scan and do_calibration in ms */ dev->pause_after_calibration = 0; /* pause between do_calibration and read data in ms */ dev->pause_after_reposition = -1; /* pause after repostion scanner in ms, -1 = do not wait */ dev->pause_for_moving = 0; /* pause for moving scanhead over full area */ if (umax_test_little_endian() == SANE_TRUE) { dev->low_byte_first = 1; /* in 2 byte mode send lowbyte first */ DBG(DBG_info, "backend runs on little endian machine\n"); } else { dev->low_byte_first = 0; /* in 2 byte mode send highbyte first */ DBG(DBG_info, "backend runs on big endian machine\n"); } #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED DBG(DBG_info,"variable scsi buffer size (usage of sanei_scsi_open_extended)\n"); #else DBG(DBG_info,"fixed scsi buffer size = %d bytes\n", sanei_scsi_max_request_size); #endif } /* ------------------------------------------------------------ MAX STRING SIZE ---------------------------- */ static size_t max_string_size(SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* ------------------------------------------------------------ DO CANCEL ---------------------------------- */ static SANE_Status do_cancel(Umax_Scanner *scanner) { SANE_Pid pid; int status; DBG(DBG_sane_proc,"do_cancel\n"); scanner->scanning = SANE_FALSE; if (sanei_thread_is_valid (scanner->reader_pid)) { DBG(DBG_sane_info,"killing reader_process\n"); sanei_thread_kill(scanner->reader_pid); pid = sanei_thread_waitpid(scanner->reader_pid, &status); if (!sanei_thread_is_valid (pid)) { DBG(DBG_sane_info, "do_cancel: sanei_thread_waitpid failed, already terminated ? (%s)\n", strerror(errno)); } else { DBG(DBG_sane_info, "do_cancel: reader_process terminated with status: %s\n", sane_strstatus(status)); } scanner->reader_pid = -1; if (scanner->device->pixelbuffer != NULL) /* pixelbuffer exists? */ { free(scanner->device->pixelbuffer); /* free pixelbuffer */ scanner->device->pixelbuffer = NULL; } } sanei_scsi_req_flush_all(); /* flush SCSI queue, when we do not do this then sanei_scsi crashes next time */ if (scanner->device->sfd != -1) /* make sure we have a working filedescriptor */ { umax_give_scanner(scanner->device); /* reposition and release scanner */ DBG(DBG_sane_info,"closing scannerdevice filedescriptor\n"); umax_scsi_close(scanner->device); } scanner->device->three_pass_color = 1; /* reset color in color scanning */ return SANE_STATUS_CANCELLED; } /* ------------------------------------------------------------ ATTACH SCANNER ----------------------------- */ static SANE_Status attach_scanner(const char *devicename, Umax_Device **devp, int connection_type) { Umax_Device *dev; int i; DBG(DBG_sane_proc,"attach_scanner: %s, connection_type %d\n", devicename, connection_type); for (dev = first_dev; dev; dev = dev->next) /* search is scanner already is listed in devicelist */ { if (strcmp(dev->sane.name, devicename) == 0) /* scanner is already listed */ { if (devp) { *devp = dev; /* return pointer to device */ } return SANE_STATUS_GOOD; } } /* scanner has not been attached yet */ dev = malloc( sizeof(*dev) ); if (!dev) { return SANE_STATUS_NO_MEM; } memset(dev, '\0', sizeof(Umax_Device)); /* clear structure */ /* If connection type is not known (==0) then try to open the device as an USB device. */ /* If it fails, try the SCSI method. */ #ifdef UMAX_ENABLE_USB dev->connection_type = connection_type; /* 0 = unknown, 1=scsi, 2=usb */ if (dev->connection_type != SANE_UMAX_SCSI) { dev->bufsize = 16384; /* 16KB */ DBG(DBG_info, "attach_scanner: opening usb device %s\n", devicename); if (sanei_umaxusb_open(devicename, &dev->sfd, sense_handler, dev) == SANE_STATUS_GOOD) { dev->connection_type = SANE_UMAX_USB; } else /* opening usb device failed */ { if (dev->connection_type == SANE_UMAX_USB) /* we know it is not a scsi device: error */ { DBG(DBG_error, "ERROR: attach_scanner: opening usb device %s failed\n", devicename); free(dev); return SANE_STATUS_INVAL; } DBG(DBG_info, "attach_scanner: failed to open %s as usb device\n", devicename); } } #else dev->connection_type = SANE_UMAX_SCSI; #endif if (dev->connection_type != SANE_UMAX_USB) /* not an USB device, then try as SCSI */ { #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED dev->bufsize = 16384; /* 16KB */ DBG(DBG_info, "attach_scanner: opening scsi device %s\n", devicename); if (sanei_scsi_open_extended(devicename, &dev->sfd, sense_handler, dev, (int *) &dev->bufsize) != 0) { DBG(DBG_error, "ERROR: attach_scanner: opening scsi device %s failed\n", devicename); free(dev); return SANE_STATUS_INVAL; } if (dev->bufsize < 4096) /* < 4KB */ { DBG(DBG_error, "ERROR: attach_scanner: sanei_scsi_open_extended returned too small scsi buffer\n"); umax_scsi_close(dev); free(dev); return SANE_STATUS_NO_MEM; } DBG(DBG_info, "attach_scanner: sanei_scsi_open_extended returned scsi buffer size = %d\n", dev->bufsize); #else dev->bufsize = sanei_scsi_max_request_size; if (sanei_scsi_open(devicename, dev, sense_handler, dev) != 0) { DBG(DBG_error, "ERROR: attach_scanner: opening scsi device %s failed\n", devicename); free(dev); return SANE_STATUS_INVAL; } #endif dev->connection_type = SANE_UMAX_SCSI; /* set connection type (may have been unknown == 0) */ } DBG(DBG_info, "attach_scanner: allocating SCSI buffer[0]\n"); dev->buffer[0] = malloc(dev->bufsize); /* allocate buffer */ for (i=1; ibuffer[i] = NULL; } if (!dev->buffer[0]) /* malloc failed */ { DBG(DBG_error, "ERROR: attach scanner: could not allocate buffer[0]\n"); umax_scsi_close(dev); free(dev); return SANE_STATUS_NO_MEM; } dev->scsi_maxqueue = 1; /* only one buffer outside the reader process */ umax_init(dev); /* preset values in structure dev */ umax_initialize_values(dev); /* reset values */ dev->devicename = strdup(devicename); if (umax_identify_scanner(dev) != 0) { DBG(DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); umax_scsi_close(dev); free(dev->buffer[0]); free(dev); return SANE_STATUS_INVAL; } if (dev->slow == -1) /* option is not predefined in umax.conf and not by backend */ { dev->slow = 0; } if (dev->smear == -1) /* option is not predefined in umax.conf and not by backend */ { dev->smear = 0; } if (dev->invert_shading_data == -1) /* nothing defined in umax.conf and not by backend */ { dev->invert_shading_data = 0; } if (dev->gamma_lsb_padded == -1) /* nothing defined in umax.conf and not by backend */ { dev->gamma_lsb_padded = 0; } umax_get_inquiry_values(dev); umax_print_inquiry(dev); DBG(DBG_inquiry,"\n"); DBG(DBG_inquiry,"==================== end of inquiry ====================\n"); DBG(DBG_inquiry,"\n"); umax_scsi_close(dev); dev->sane.name = dev->devicename; dev->sane.vendor = dev->vendor; dev->sane.model = dev->product; dev->sane.type = "flatbed scanner"; if (strcmp(dev->sane.model,"PSD ") == 0) { dev->sane.type = "page scanner"; } dev->x_range.min = SANE_FIX(0); dev->x_range.quant = SANE_FIX(0); dev->x_range.max = SANE_FIX(dev->inquiry_fb_width * MM_PER_INCH); dev->y_range.min = SANE_FIX(0); dev->y_range.quant = SANE_FIX(0); dev->y_range.max = SANE_FIX(dev->inquiry_fb_length * MM_PER_INCH); #if UMAX_RESOLUTION_PERCENT_STEP dev->x_dpi_range.min = SANE_FIX(dev->inquiry_optical_res/100); dev->x_dpi_range.quant = SANE_FIX(dev->inquiry_optical_res/100); #else dev->x_dpi_range.min = SANE_FIX(5); dev->x_dpi_range.quant = SANE_FIX(5); #endif dev->x_dpi_range.max = SANE_FIX(dev->inquiry_x_res); #if UMAX_RESOLUTION_PERCENT_STEP dev->y_dpi_range.min = SANE_FIX(dev->inquiry_optical_res/100); dev->y_dpi_range.quant = SANE_FIX(dev->inquiry_optical_res/100); #else dev->y_dpi_range.min = SANE_FIX(5); dev->y_dpi_range.quant = SANE_FIX(5); #endif dev->y_dpi_range.max = SANE_FIX(dev->inquiry_y_res); dev->analog_gamma_range.min = SANE_FIX(1.0); dev->analog_gamma_range.quant = SANE_FIX(0.01); dev->analog_gamma_range.max = SANE_FIX(2.0); DBG(DBG_info,"x_range.max = %f\n", SANE_UNFIX(dev->x_range.max)); DBG(DBG_info,"y_range.max = %f\n", SANE_UNFIX(dev->y_range.max)); DBG(DBG_info,"x_dpi_range.max = %f\n", SANE_UNFIX(dev->x_dpi_range.max)); DBG(DBG_info,"y_dpi_range.max = %f\n", SANE_UNFIX(dev->y_dpi_range.max)); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ READER PROCESS SIGTERM HANDLER ------------ */ static void reader_process_sigterm_handler(int signal) { DBG(DBG_sane_info,"reader_process: terminated by signal %d\n", signal); sanei_scsi_req_flush_all(); /* flush SCSI queue */ _exit (SANE_STATUS_GOOD); } /* ------------------------------------------------------------ READER PROCESS ----------------------------- */ static int reader_process(void *data) /* executed as a child process or as thread */ { Umax_Scanner *scanner = (Umax_Scanner *)data; FILE *fp; int status; unsigned int data_length; struct SIGACTION act; unsigned int i; if (sanei_thread_is_forked()) { DBG(DBG_sane_proc,"reader_process started (forked)\n"); close(scanner->pipe_read_fd); scanner->pipe_read_fd = -1; /* sanei_scsi crashes when the scsi commands are not flushed, done in reader_process_sigterm_handler */ memset(&act, 0, sizeof (act)); /* define SIGTERM-handler */ act.sa_handler = reader_process_sigterm_handler; sigaction(SIGTERM, &act, 0); } else { DBG(DBG_sane_proc,"reader_process started (as thread)\n"); } scanner->device->scsi_maxqueue = scanner->device->request_scsi_maxqueue; if (scanner->device->request_scsi_maxqueue > 1) { for (i = 1; idevice->buffer[i]) { DBG(DBG_info, "reader_process: freeing SCSI buffer[%d]\n", i); free(scanner->device->buffer[i]); /* free buffer */ scanner->device->buffer[i] = NULL; } } for (i = 1; idevice->request_scsi_maxqueue; i++) { DBG(DBG_info, "reader_process: allocating SCSI buffer[%d]\n", i); scanner->device->buffer[i] = malloc(scanner->device->bufsize); /* allocate buffer */ if (!scanner->device->buffer[i]) /* malloc failed */ { DBG(DBG_warning, "WARNING: reader_process: only allocated %d/%d scsi buffers\n", i, scanner->device->request_scsi_maxqueue); scanner->device->scsi_maxqueue = i; break; /* leave for loop */ } } } data_length = scanner->params.lines * scanner->params.bytes_per_line; fp = fdopen(scanner->pipe_write_fd, "w"); if (!fp) { return SANE_STATUS_IO_ERROR; } DBG(DBG_sane_info,"reader_process: starting to READ data\n"); status = umax_reader_process(scanner->device, fp, data_length); fclose(fp); /* close write end of pipe */ for (i = 1; idevice->request_scsi_maxqueue; i++) { if (scanner->device->buffer[i]) { DBG(DBG_info, "reader_process: freeing SCSI buffer[%d]\n", i); free(scanner->device->buffer[i]); /* free buffer */ scanner->device->buffer[i] = NULL; } } DBG(DBG_sane_info,"reader_process: finished reading data\n"); return status; } /* ------------------------------------------------------------ INIT OPTIONS ------------------------------- */ static SANE_Status init_options(Umax_Scanner *scanner) { int i; int scan_modes; int bit_depths; DBG(DBG_sane_proc,"init_options\n"); memset(scanner->opt, 0, sizeof (scanner->opt)); memset(scanner->val, 0, sizeof (scanner->val)); for (i = 0; i < NUM_OPTIONS; ++i) { scanner->opt[i].size = sizeof (SANE_Word); scanner->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } scanner->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; /* empty string */ scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; scanner->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ scanner->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); scanner->opt[OPT_MODE_GROUP].desc = ""; scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_MODE_GROUP].cap = 0; scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; scan_modes = -1; if (scanner->device->inquiry_lineart) { scan_mode_list[++scan_modes] = LINEART_STR; } if (scanner->device->inquiry_halftone) { scan_mode_list[++scan_modes]= HALFTONE_STR; } if (scanner->device->inquiry_gray) { scan_mode_list[++scan_modes]= GRAY_STR; } if (scanner->device->inquiry_color) { /* if (scanner->device->inquiry_lineart) { scan_mode_list[++scan_modes]= COLOR_LINEART_STR; } if (scanner->device->inquiry_halftone) { scan_mode_list[++scan_modes]= COLOR_HALFTONE_STR; } */ scan_mode_list[++scan_modes]= COLOR_STR; } scan_mode_list[scan_modes + 1] = 0; { int i=0; source_list[i++]= FLB_STR; if (scanner->device->inquiry_adfmode) { source_list[i++] = ADF_STR; } if (scanner->device->inquiry_transavail) { source_list[i++] = UTA_STR; } source_list[i] = 0; } /* scan mode */ scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; scanner->opt[OPT_MODE].type = SANE_TYPE_STRING; scanner->opt[OPT_MODE].size = max_string_size((SANE_String_Const *) scan_mode_list); scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_MODE].constraint.string_list = (SANE_String_Const *) scan_mode_list; scanner->val[OPT_MODE].s = (SANE_Char*)strdup(scan_mode_list[0]); /* source */ scanner->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; scanner->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; scanner->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; scanner->opt[OPT_SOURCE].type = SANE_TYPE_STRING; scanner->opt[OPT_SOURCE].size = max_string_size(source_list); scanner->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_SOURCE].constraint.string_list = source_list; scanner->val[OPT_SOURCE].s = (SANE_Char*)strdup(source_list[0]); /* x-resolution */ scanner->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; scanner->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; scanner->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; scanner->opt[OPT_X_RESOLUTION].type = SANE_TYPE_FIXED; scanner->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; scanner->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_X_RESOLUTION].constraint.range = &scanner->device->x_dpi_range; scanner->val[OPT_X_RESOLUTION].w = 100 << SANE_FIXED_SCALE_SHIFT; /* y-resolution */ scanner->opt[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION; scanner->opt[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION; scanner->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_Y_RESOLUTION; scanner->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_FIXED; scanner->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; scanner->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_Y_RESOLUTION].constraint.range = &scanner->device->y_dpi_range; scanner->val[OPT_Y_RESOLUTION].w = 100 << SANE_FIXED_SCALE_SHIFT; scanner->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; /* bind resolution */ scanner->opt[OPT_RESOLUTION_BIND].name = SANE_NAME_RESOLUTION_BIND; scanner->opt[OPT_RESOLUTION_BIND].title = SANE_TITLE_RESOLUTION_BIND; scanner->opt[OPT_RESOLUTION_BIND].desc = SANE_DESC_RESOLUTION_BIND; scanner->opt[OPT_RESOLUTION_BIND].type = SANE_TYPE_BOOL; scanner->val[OPT_RESOLUTION_BIND].w = SANE_TRUE; if (scanner->device->common_xy_resolutions) /* disable bind if x and y res have to be the same */ { scanner->opt[OPT_RESOLUTION_BIND].cap |= SANE_CAP_INACTIVE; } /* negative */ scanner->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; scanner->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; scanner->opt[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE; scanner->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL; scanner->val[OPT_NEGATIVE].w = SANE_FALSE; if (scanner->device->inquiry_reverse_multi == 0) { scanner->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; } /* ------------------------------ */ /* "Geometry" group: */ scanner->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); scanner->opt[OPT_GEOMETRY_GROUP].desc = ""; scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_X].constraint.range = &(scanner->device->x_range); scanner->val[OPT_TL_X].w = 0; /* top-left y */ scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_Y].constraint.range = &(scanner->device->y_range); scanner->val[OPT_TL_Y].w = 0; /* bottom-right x */ scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_X].constraint.range = &(scanner->device->x_range); scanner->val[OPT_BR_X].w = scanner->device->x_range.max; /* bottom-right y */ scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_Y].constraint.range = &(scanner->device->y_range); scanner->val[OPT_BR_Y].w = scanner->device->y_range.max; /* ------------------------------ */ /* "Enhancement" group: */ scanner->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement"); scanner->opt[OPT_ENHANCEMENT_GROUP].desc = ""; scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ENHANCEMENT_GROUP].cap = 0; scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* bit depth */ bit_depths = 0; if (scanner->device->inquiry_GOB & 1) { bit_depth_list[++bit_depths] = 8; } if (scanner->device->inquiry_GOB & 2) { bit_depth_list[++bit_depths] = 9; } if (scanner->device->inquiry_GOB & 4) { bit_depth_list[++bit_depths] = 10; } if (scanner->device->inquiry_GOB & 8) { bit_depth_list[++bit_depths] = 12; } if (scanner->device->inquiry_GOB & 16) { bit_depth_list[++bit_depths] = 14; } if (scanner->device->inquiry_GOB & 32) { bit_depth_list[++bit_depths] = 16; } bit_depth_list[0] = bit_depths; scanner->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; scanner->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT; scanner->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_BIT_DEPTH].constraint.word_list = bit_depth_list; scanner->val[OPT_BIT_DEPTH].w = bit_depth_list[1]; /* quality-calibration */ scanner->opt[OPT_QUALITY].name = SANE_NAME_QUALITY_CAL; scanner->opt[OPT_QUALITY].title = SANE_TITLE_QUALITY_CAL; scanner->opt[OPT_QUALITY].desc = SANE_DESC_QUALITY_CAL; scanner->opt[OPT_QUALITY].type = SANE_TYPE_BOOL; scanner->val[OPT_QUALITY].w = SANE_FALSE; if ((scanner->device->inquiry_quality_ctrl == 0) || (scanner->device->force_quality_calibration) ) { scanner->opt[OPT_QUALITY].cap |= SANE_CAP_INACTIVE; } else /* enable quality calibration when available */ { scanner->val[OPT_QUALITY].w = SANE_TRUE; } /* double optical resolution */ scanner->opt[OPT_DOR].name = SANE_NAME_DOR; scanner->opt[OPT_DOR].title = SANE_TITLE_DOR; scanner->opt[OPT_DOR].desc = SANE_DESC_DOR; scanner->opt[OPT_DOR].type = SANE_TYPE_BOOL; scanner->val[OPT_DOR].w = SANE_FALSE; if (scanner->device->inquiry_dor == 0) { scanner->opt[OPT_DOR].cap |= SANE_CAP_INACTIVE; } /* warmup */ scanner->opt[OPT_WARMUP].name = SANE_NAME_WARMUP; scanner->opt[OPT_WARMUP].title = SANE_TITLE_WARMUP; scanner->opt[OPT_WARMUP].desc = SANE_DESC_WARMUP; scanner->opt[OPT_WARMUP].type = SANE_TYPE_BOOL; scanner->val[OPT_WARMUP].w = SANE_FALSE; if (scanner->device->inquiry_max_warmup_time == 0) { scanner->opt[OPT_WARMUP].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_RGB_BIND].name = SANE_NAME_RGB_BIND; scanner->opt[OPT_RGB_BIND].title = SANE_TITLE_RGB_BIND; scanner->opt[OPT_RGB_BIND].desc = SANE_DESC_RGB_BIND; scanner->opt[OPT_RGB_BIND].type = SANE_TYPE_BOOL; scanner->val[OPT_RGB_BIND].w = SANE_FALSE; /* brightness */ scanner->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; scanner->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; scanner->val[OPT_BRIGHTNESS].w = 0; /* contrast */ scanner->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; scanner->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; scanner->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; scanner->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; scanner->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_CONTRAST].constraint.range = &percentage_range; scanner->val[OPT_CONTRAST].w = 0; /* threshold */ scanner->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; scanner->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; scanner->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; scanner->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; scanner->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_THRESHOLD].constraint.range = &percentage_range_100; scanner->val[OPT_THRESHOLD].w = SANE_FIX(50); /* ------------------------------ */ /* highlight, white level */ scanner->opt[OPT_HIGHLIGHT].name = SANE_NAME_HIGHLIGHT; scanner->opt[OPT_HIGHLIGHT].title = SANE_TITLE_HIGHLIGHT; scanner->opt[OPT_HIGHLIGHT].desc = SANE_DESC_HIGHLIGHT; scanner->opt[OPT_HIGHLIGHT].type = SANE_TYPE_FIXED; scanner->opt[OPT_HIGHLIGHT].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_HIGHLIGHT].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_HIGHLIGHT].constraint.range = &percentage_range_100; scanner->val[OPT_HIGHLIGHT].w = SANE_FIX(100); scanner->opt[OPT_HIGHLIGHT_R].name = SANE_NAME_HIGHLIGHT_R; scanner->opt[OPT_HIGHLIGHT_R].title = SANE_TITLE_HIGHLIGHT_R; scanner->opt[OPT_HIGHLIGHT_R].desc = SANE_DESC_HIGHLIGHT_R; scanner->opt[OPT_HIGHLIGHT_R].type = SANE_TYPE_FIXED; scanner->opt[OPT_HIGHLIGHT_R].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_HIGHLIGHT_R].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_HIGHLIGHT_R].constraint.range = &percentage_range_100; scanner->val[OPT_HIGHLIGHT_R].w = SANE_FIX(100); scanner->opt[OPT_HIGHLIGHT_G].name = SANE_NAME_HIGHLIGHT_G; scanner->opt[OPT_HIGHLIGHT_G].title = SANE_TITLE_HIGHLIGHT_G; scanner->opt[OPT_HIGHLIGHT_G].desc = SANE_DESC_HIGHLIGHT_G; scanner->opt[OPT_HIGHLIGHT_G].type = SANE_TYPE_FIXED; scanner->opt[OPT_HIGHLIGHT_G].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_HIGHLIGHT_G].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_HIGHLIGHT_G].constraint.range = &percentage_range_100; scanner->val[OPT_HIGHLIGHT_G].w = SANE_FIX(100); scanner->opt[OPT_HIGHLIGHT_B].name = SANE_NAME_HIGHLIGHT_B; scanner->opt[OPT_HIGHLIGHT_B].title = SANE_TITLE_HIGHLIGHT_B; scanner->opt[OPT_HIGHLIGHT_B].desc = SANE_DESC_HIGHLIGHT_B; scanner->opt[OPT_HIGHLIGHT_B].type = SANE_TYPE_FIXED; scanner->opt[OPT_HIGHLIGHT_B].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_HIGHLIGHT_B].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_HIGHLIGHT_B].constraint.range = &percentage_range_100; scanner->val[OPT_HIGHLIGHT_B].w = SANE_FIX(100); /* shadow, black level */ scanner->opt[OPT_SHADOW].name = SANE_NAME_SHADOW; scanner->opt[OPT_SHADOW].title = SANE_TITLE_SHADOW; scanner->opt[OPT_SHADOW].desc = SANE_DESC_SHADOW; scanner->opt[OPT_SHADOW].type = SANE_TYPE_FIXED; scanner->opt[OPT_SHADOW].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_SHADOW].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SHADOW].constraint.range = &percentage_range_100; scanner->val[OPT_SHADOW].w = 0; scanner->opt[OPT_SHADOW_R].name = SANE_NAME_SHADOW_R; scanner->opt[OPT_SHADOW_R].title = SANE_TITLE_SHADOW_R; scanner->opt[OPT_SHADOW_R].desc = SANE_DESC_SHADOW_R; scanner->opt[OPT_SHADOW_R].type = SANE_TYPE_FIXED; scanner->opt[OPT_SHADOW_R].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_SHADOW_R].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SHADOW_R].constraint.range = &percentage_range_100; scanner->val[OPT_SHADOW_R].w = 0; scanner->opt[OPT_SHADOW_G].name = SANE_NAME_SHADOW_G; scanner->opt[OPT_SHADOW_G].title = SANE_TITLE_SHADOW_G; scanner->opt[OPT_SHADOW_G].desc = SANE_DESC_SHADOW_G; scanner->opt[OPT_SHADOW_G].type = SANE_TYPE_FIXED; scanner->opt[OPT_SHADOW_G].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_SHADOW_G].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SHADOW_G].constraint.range = &percentage_range_100; scanner->val[OPT_SHADOW_G].w = 0; scanner->opt[OPT_SHADOW_B].name = SANE_NAME_SHADOW_B; scanner->opt[OPT_SHADOW_B].title = SANE_TITLE_SHADOW_B; scanner->opt[OPT_SHADOW_B].desc = SANE_DESC_SHADOW_B; scanner->opt[OPT_SHADOW_B].type = SANE_TYPE_FIXED; scanner->opt[OPT_SHADOW_B].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_SHADOW_B].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SHADOW_B].constraint.range = &percentage_range_100; scanner->val[OPT_SHADOW_B].w = 0; /* analog-gamma */ scanner->opt[OPT_ANALOG_GAMMA].name = SANE_NAME_ANALOG_GAMMA; scanner->opt[OPT_ANALOG_GAMMA].title = SANE_TITLE_ANALOG_GAMMA; scanner->opt[OPT_ANALOG_GAMMA].desc = SANE_DESC_ANALOG_GAMMA; scanner->opt[OPT_ANALOG_GAMMA].type = SANE_TYPE_FIXED; scanner->opt[OPT_ANALOG_GAMMA].unit = SANE_UNIT_NONE; scanner->opt[OPT_ANALOG_GAMMA].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_ANALOG_GAMMA].constraint.range = &(scanner->device->analog_gamma_range); scanner->val[OPT_ANALOG_GAMMA].w = 1 << SANE_FIXED_SCALE_SHIFT; scanner->opt[OPT_ANALOG_GAMMA_R].name = SANE_NAME_ANALOG_GAMMA_R; scanner->opt[OPT_ANALOG_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R; scanner->opt[OPT_ANALOG_GAMMA_R].desc = SANE_DESC_ANALOG_GAMMA_R; scanner->opt[OPT_ANALOG_GAMMA_R].type = SANE_TYPE_FIXED; scanner->opt[OPT_ANALOG_GAMMA_R].unit = SANE_UNIT_NONE; scanner->opt[OPT_ANALOG_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_ANALOG_GAMMA_R].constraint.range = &(scanner->device->analog_gamma_range); scanner->val[OPT_ANALOG_GAMMA_R].w = 1 << SANE_FIXED_SCALE_SHIFT; scanner->opt[OPT_ANALOG_GAMMA_G].name = SANE_NAME_ANALOG_GAMMA_G; scanner->opt[OPT_ANALOG_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G; scanner->opt[OPT_ANALOG_GAMMA_G].desc = SANE_DESC_ANALOG_GAMMA_G; scanner->opt[OPT_ANALOG_GAMMA_G].type = SANE_TYPE_FIXED; scanner->opt[OPT_ANALOG_GAMMA_G].unit = SANE_UNIT_NONE; scanner->opt[OPT_ANALOG_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_ANALOG_GAMMA_G].constraint.range = &(scanner->device->analog_gamma_range); scanner->val[OPT_ANALOG_GAMMA_G].w = 1 << SANE_FIXED_SCALE_SHIFT; scanner->opt[OPT_ANALOG_GAMMA_B].name = SANE_NAME_ANALOG_GAMMA_B; scanner->opt[OPT_ANALOG_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B; scanner->opt[OPT_ANALOG_GAMMA_B].desc = SANE_DESC_ANALOG_GAMMA_B; scanner->opt[OPT_ANALOG_GAMMA_B].type = SANE_TYPE_FIXED; scanner->opt[OPT_ANALOG_GAMMA_B].unit = SANE_UNIT_NONE; scanner->opt[OPT_ANALOG_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_ANALOG_GAMMA_B].constraint.range = &(scanner->device->analog_gamma_range); scanner->val[OPT_ANALOG_GAMMA_B].w = 1 << SANE_FIXED_SCALE_SHIFT; /* custom-gamma table */ scanner->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; scanner->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; scanner->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; scanner->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; scanner->val[OPT_CUSTOM_GAMMA].w = SANE_TRUE; /* grayscale gamma vector */ scanner->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; scanner->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; scanner->val[OPT_GAMMA_VECTOR].wa = scanner->gamma_table[0]; scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &scanner->output_range; scanner->opt[OPT_GAMMA_VECTOR].size = scanner->gamma_length * sizeof(SANE_Word); scanner->output_range.min = 0; if (bit_depth_list[1] == 8) { scanner->output_range.max = 255; /* 8 bits/pixel */ } else { scanner->output_range.max = 65535; /* 9-16 bits/pixel */ } scanner->output_range.quant = 0; /* red gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; scanner->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; scanner->val[OPT_GAMMA_VECTOR_R].wa = scanner->gamma_table[1]; scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(scanner->gamma_range); scanner->opt[OPT_GAMMA_VECTOR_R].size = scanner->gamma_length * sizeof(SANE_Word); /* green gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; scanner->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; scanner->val[OPT_GAMMA_VECTOR_G].wa = scanner->gamma_table[2]; scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(scanner->gamma_range); scanner->opt[OPT_GAMMA_VECTOR_G].size = scanner->gamma_length * sizeof(SANE_Word); /* blue gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; scanner->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; scanner->val[OPT_GAMMA_VECTOR_B].wa = scanner->gamma_table[3]; scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(scanner->gamma_range); scanner->opt[OPT_GAMMA_VECTOR_B].size = scanner->gamma_length * sizeof(SANE_Word); /* halftone dimension */ scanner->opt[OPT_HALFTONE_DIMENSION].name = SANE_NAME_HALFTONE_DIMENSION; scanner->opt[OPT_HALFTONE_DIMENSION].title = SANE_TITLE_HALFTONE_DIMENSION; scanner->opt[OPT_HALFTONE_DIMENSION].desc = SANE_DESC_HALFTONE_DIMENSION; scanner->opt[OPT_HALFTONE_DIMENSION].type = SANE_TYPE_INT; scanner->opt[OPT_HALFTONE_DIMENSION].unit = SANE_UNIT_PIXEL; scanner->opt[OPT_HALFTONE_DIMENSION].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_HALFTONE_DIMENSION].constraint.word_list = pattern_dim_list; scanner->val[OPT_HALFTONE_DIMENSION].w = pattern_dim_list[1]; /* halftone pattern */ scanner->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_INT; scanner->opt[OPT_HALFTONE_PATTERN].size = 0; scanner->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_HALFTONE_PATTERN].constraint.range = &u8_range; scanner->val[OPT_HALFTONE_PATTERN].wa = scanner->halftone_pattern; /* ------------------------------ */ /* "Advanced" group: */ scanner->opt[OPT_ADVANCED_GROUP].title = SANE_I18N("Advanced"); scanner->opt[OPT_ADVANCED_GROUP].desc = ""; scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* ------------------------------ */ /* select exposure time */ scanner->opt[OPT_SELECT_EXPOSURE_TIME].name = SANE_NAME_SELECT_EXPOSURE_TIME; scanner->opt[OPT_SELECT_EXPOSURE_TIME].title = SANE_TITLE_SELECT_EXPOSURE_TIME; scanner->opt[OPT_SELECT_EXPOSURE_TIME].desc = SANE_DESC_SELECT_EXPOSURE_TIME; scanner->opt[OPT_SELECT_EXPOSURE_TIME].type = SANE_TYPE_BOOL; scanner->val[OPT_SELECT_EXPOSURE_TIME].w = SANE_FALSE; /* select calibration exposure time */ scanner->opt[OPT_SELECT_CAL_EXPOSURE_TIME].name = SANE_UMAX_NAME_SELECT_CALIBRATON_EXPOSURE_TIME; scanner->opt[OPT_SELECT_CAL_EXPOSURE_TIME].title = SANE_UMAX_TITLE_SELECT_CALIBRATION_EXPOSURE_TIME; scanner->opt[OPT_SELECT_CAL_EXPOSURE_TIME].desc = SANE_UMAX_DESC_SELECT_CALIBRATION_EXPOSURE_TIME; scanner->opt[OPT_SELECT_CAL_EXPOSURE_TIME].type = SANE_TYPE_BOOL; scanner->val[OPT_SELECT_CAL_EXPOSURE_TIME].w = SANE_FALSE; scanner->opt[OPT_SELECT_CAL_EXPOSURE_TIME].cap |= SANE_CAP_INACTIVE; /* calibration exposure time */ scanner->opt[OPT_CAL_EXPOS_TIME].name = SANE_NAME_CAL_EXPOS_TIME; scanner->opt[OPT_CAL_EXPOS_TIME].title = SANE_TITLE_CAL_EXPOS_TIME; scanner->opt[OPT_CAL_EXPOS_TIME].desc = SANE_DESC_CAL_EXPOS_TIME; scanner->opt[OPT_CAL_EXPOS_TIME].type = SANE_TYPE_INT; scanner->opt[OPT_CAL_EXPOS_TIME].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_CAL_EXPOS_TIME].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_CAL_EXPOS_TIME].constraint.range = &(scanner->exposure_time_range); scanner->val[OPT_CAL_EXPOS_TIME].w = scanner->device->inquiry_exposure_time_g_fb_def * scanner->device->inquiry_exposure_time_step_unit; scanner->opt[OPT_CAL_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; /* calibration exposure time red */ scanner->opt[OPT_CAL_EXPOS_TIME_R].name = SANE_NAME_CAL_EXPOS_TIME_R; scanner->opt[OPT_CAL_EXPOS_TIME_R].title = SANE_TITLE_CAL_EXPOS_TIME_R; scanner->opt[OPT_CAL_EXPOS_TIME_R].desc = SANE_DESC_CAL_EXPOS_TIME_R; scanner->opt[OPT_CAL_EXPOS_TIME_R].type = SANE_TYPE_INT; scanner->opt[OPT_CAL_EXPOS_TIME_R].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_CAL_EXPOS_TIME_R].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_CAL_EXPOS_TIME_R].constraint.range = &(scanner->exposure_time_range); scanner->val[OPT_CAL_EXPOS_TIME_R].w = scanner->device->inquiry_exposure_time_c_fb_def_r * scanner->device->inquiry_exposure_time_step_unit; scanner->opt[OPT_CAL_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; /* calibration exposure time green */ scanner->opt[OPT_CAL_EXPOS_TIME_G].name = SANE_NAME_CAL_EXPOS_TIME_G; scanner->opt[OPT_CAL_EXPOS_TIME_G].title = SANE_TITLE_CAL_EXPOS_TIME_G; scanner->opt[OPT_CAL_EXPOS_TIME_G].desc = SANE_DESC_CAL_EXPOS_TIME_G; scanner->opt[OPT_CAL_EXPOS_TIME_G].type = SANE_TYPE_INT; scanner->opt[OPT_CAL_EXPOS_TIME_G].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_CAL_EXPOS_TIME_G].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_CAL_EXPOS_TIME_G].constraint.range = &(scanner->exposure_time_range); scanner->val[OPT_CAL_EXPOS_TIME_G].w = scanner->device->inquiry_exposure_time_c_fb_def_g * scanner->device->inquiry_exposure_time_step_unit; scanner->opt[OPT_CAL_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; /* calibration exposure time blue */ scanner->opt[OPT_CAL_EXPOS_TIME_B].name = SANE_NAME_CAL_EXPOS_TIME_B; scanner->opt[OPT_CAL_EXPOS_TIME_B].title = SANE_TITLE_CAL_EXPOS_TIME_B; scanner->opt[OPT_CAL_EXPOS_TIME_B].desc = SANE_DESC_CAL_EXPOS_TIME_B; scanner->opt[OPT_CAL_EXPOS_TIME_B].type = SANE_TYPE_INT; scanner->opt[OPT_CAL_EXPOS_TIME_B].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_CAL_EXPOS_TIME_B].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_CAL_EXPOS_TIME_B].constraint.range = &(scanner->exposure_time_range); scanner->val[OPT_CAL_EXPOS_TIME_B].w = scanner->device->inquiry_exposure_time_c_fb_def_b * scanner->device->inquiry_exposure_time_step_unit; scanner->opt[OPT_CAL_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; /* scan exposure time */ scanner->opt[OPT_SCAN_EXPOS_TIME].name = SANE_NAME_SCAN_EXPOS_TIME; scanner->opt[OPT_SCAN_EXPOS_TIME].title = SANE_TITLE_SCAN_EXPOS_TIME; scanner->opt[OPT_SCAN_EXPOS_TIME].desc = SANE_DESC_SCAN_EXPOS_TIME; scanner->opt[OPT_SCAN_EXPOS_TIME].type = SANE_TYPE_INT; scanner->opt[OPT_SCAN_EXPOS_TIME].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_SCAN_EXPOS_TIME].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SCAN_EXPOS_TIME].constraint.range = &(scanner->exposure_time_range); scanner->val[OPT_SCAN_EXPOS_TIME].w = scanner->device->inquiry_exposure_time_g_fb_def * scanner->device->inquiry_exposure_time_step_unit; scanner->opt[OPT_SCAN_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; /* scan exposure time red */ scanner->opt[OPT_SCAN_EXPOS_TIME_R].name = SANE_NAME_SCAN_EXPOS_TIME_R; scanner->opt[OPT_SCAN_EXPOS_TIME_R].title = SANE_TITLE_SCAN_EXPOS_TIME_R; scanner->opt[OPT_SCAN_EXPOS_TIME_R].desc = SANE_DESC_SCAN_EXPOS_TIME_R; scanner->opt[OPT_SCAN_EXPOS_TIME_R].type = SANE_TYPE_INT; scanner->opt[OPT_SCAN_EXPOS_TIME_R].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_SCAN_EXPOS_TIME_R].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SCAN_EXPOS_TIME_R].constraint.range = &(scanner->exposure_time_range); scanner->val[OPT_SCAN_EXPOS_TIME_R].w = scanner->device->inquiry_exposure_time_c_fb_def_r * scanner->device->inquiry_exposure_time_step_unit; scanner->opt[OPT_SCAN_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; /* scan exposure time green */ scanner->opt[OPT_SCAN_EXPOS_TIME_G].name = SANE_NAME_SCAN_EXPOS_TIME_G; scanner->opt[OPT_SCAN_EXPOS_TIME_G].title = SANE_TITLE_SCAN_EXPOS_TIME_G; scanner->opt[OPT_SCAN_EXPOS_TIME_G].desc = SANE_DESC_SCAN_EXPOS_TIME_G; scanner->opt[OPT_SCAN_EXPOS_TIME_G].type = SANE_TYPE_INT; scanner->opt[OPT_SCAN_EXPOS_TIME_G].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_SCAN_EXPOS_TIME_G].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SCAN_EXPOS_TIME_G].constraint.range = &(scanner->exposure_time_range); scanner->val[OPT_SCAN_EXPOS_TIME_G].w = scanner->device->inquiry_exposure_time_c_fb_def_g * scanner->device->inquiry_exposure_time_step_unit; scanner->opt[OPT_SCAN_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; /* scan exposure time blue */ scanner->opt[OPT_SCAN_EXPOS_TIME_B].name = SANE_NAME_SCAN_EXPOS_TIME_B; scanner->opt[OPT_SCAN_EXPOS_TIME_B].title = SANE_TITLE_SCAN_EXPOS_TIME_B; scanner->opt[OPT_SCAN_EXPOS_TIME_B].desc = SANE_DESC_SCAN_EXPOS_TIME_B; scanner->opt[OPT_SCAN_EXPOS_TIME_B].type = SANE_TYPE_INT; scanner->opt[OPT_SCAN_EXPOS_TIME_B].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_SCAN_EXPOS_TIME_B].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SCAN_EXPOS_TIME_B].constraint.range = &(scanner->exposure_time_range); scanner->val[OPT_SCAN_EXPOS_TIME_B].w = scanner->device->inquiry_exposure_time_c_fb_def_b * scanner->device->inquiry_exposure_time_step_unit; scanner->opt[OPT_SCAN_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; if (scanner->device->inquiry_exposure_adj == 0) { scanner->opt[OPT_SELECT_EXPOSURE_TIME].cap |= SANE_CAP_INACTIVE; } /* ------------------------------ */ /* select calibration lamp density */ scanner->opt[OPT_SELECT_LAMP_DENSITY].name = SANE_NAME_SELECT_LAMP_DENSITY; scanner->opt[OPT_SELECT_LAMP_DENSITY].title = SANE_TITLE_SELECT_LAMP_DENSITY; scanner->opt[OPT_SELECT_LAMP_DENSITY].desc = SANE_DESC_SELECT_LAMP_DENSITY; scanner->opt[OPT_SELECT_LAMP_DENSITY].type = SANE_TYPE_BOOL; scanner->val[OPT_SELECT_LAMP_DENSITY].w = SANE_FALSE; /* calibration lamp density */ scanner->opt[OPT_CAL_LAMP_DEN].name = SANE_NAME_CAL_LAMP_DEN; scanner->opt[OPT_CAL_LAMP_DEN].title = SANE_TITLE_CAL_LAMP_DEN; scanner->opt[OPT_CAL_LAMP_DEN].desc = SANE_DESC_CAL_LAMP_DEN; scanner->opt[OPT_CAL_LAMP_DEN].type = SANE_TYPE_FIXED; scanner->opt[OPT_CAL_LAMP_DEN].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_CAL_LAMP_DEN].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_CAL_LAMP_DEN].constraint.range = &percentage_range_100; scanner->val[OPT_CAL_LAMP_DEN].w = SANE_FIX(50); scanner->opt[OPT_CAL_LAMP_DEN].cap |= SANE_CAP_INACTIVE; /* scan lamp density */ scanner->opt[OPT_SCAN_LAMP_DEN].name = SANE_NAME_SCAN_LAMP_DEN; scanner->opt[OPT_SCAN_LAMP_DEN].title = SANE_TITLE_SCAN_LAMP_DEN; scanner->opt[OPT_SCAN_LAMP_DEN].desc = SANE_DESC_SCAN_LAMP_DEN; scanner->opt[OPT_SCAN_LAMP_DEN].type = SANE_TYPE_FIXED; scanner->opt[OPT_SCAN_LAMP_DEN].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_SCAN_LAMP_DEN].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_SCAN_LAMP_DEN].constraint.range = &percentage_range_100; scanner->val[OPT_SCAN_LAMP_DEN].w = SANE_FIX(50); scanner->opt[OPT_SCAN_LAMP_DEN].cap |= SANE_CAP_INACTIVE; if (scanner->device->inquiry_lamp_ctrl == 0) { scanner->opt[OPT_SELECT_LAMP_DENSITY].cap |= SANE_CAP_INACTIVE; } /* ------------------------------ */ /* disable pre focus */ scanner->opt[OPT_DISABLE_PRE_FOCUS].name = "disable-pre-focus"; scanner->opt[OPT_DISABLE_PRE_FOCUS].title = SANE_I18N("Disable pre focus"); scanner->opt[OPT_DISABLE_PRE_FOCUS].desc = SANE_I18N("Do not calibrate focus"); scanner->opt[OPT_DISABLE_PRE_FOCUS].type = SANE_TYPE_BOOL; scanner->val[OPT_DISABLE_PRE_FOCUS].w = SANE_FALSE; if (scanner->device->inquiry_manual_focus == 0) { scanner->opt[OPT_DISABLE_PRE_FOCUS].cap |= SANE_CAP_INACTIVE; } /* manual pre focus */ scanner->opt[OPT_MANUAL_PRE_FOCUS].name = "manual-pre-focus"; scanner->opt[OPT_MANUAL_PRE_FOCUS].title = SANE_I18N("Manual pre focus"); scanner->opt[OPT_MANUAL_PRE_FOCUS].desc = ""; scanner->opt[OPT_MANUAL_PRE_FOCUS].type = SANE_TYPE_BOOL; scanner->val[OPT_MANUAL_PRE_FOCUS].w = SANE_FALSE; if (scanner->device->inquiry_manual_focus == 0) { scanner->opt[OPT_MANUAL_PRE_FOCUS].cap |= SANE_CAP_INACTIVE; } /* fix focus position */ scanner->opt[OPT_FIX_FOCUS_POSITION].name = "fix-focus-position"; scanner->opt[OPT_FIX_FOCUS_POSITION].title = SANE_I18N("Fix focus position"); scanner->opt[OPT_FIX_FOCUS_POSITION].desc = ""; scanner->opt[OPT_FIX_FOCUS_POSITION].type = SANE_TYPE_BOOL; scanner->val[OPT_FIX_FOCUS_POSITION].w = SANE_FALSE; if (scanner->device->inquiry_manual_focus == 0) { scanner->opt[OPT_FIX_FOCUS_POSITION].cap |= SANE_CAP_INACTIVE; } /* lens calibration in doc position */ scanner->opt[OPT_LENS_CALIBRATION_DOC_POS].name = "lens-calibration-in-doc-position"; scanner->opt[OPT_LENS_CALIBRATION_DOC_POS].title = SANE_I18N("Lens calibration in doc position"); scanner->opt[OPT_LENS_CALIBRATION_DOC_POS].desc = SANE_I18N("Calibrate lens focus in document position"); scanner->opt[OPT_LENS_CALIBRATION_DOC_POS].type = SANE_TYPE_BOOL; scanner->val[OPT_LENS_CALIBRATION_DOC_POS].w = SANE_FALSE; if (scanner->device->inquiry_lens_cal_in_doc_pos == 0) { scanner->opt[OPT_LENS_CALIBRATION_DOC_POS].cap |= SANE_CAP_INACTIVE; } /* 0mm holder focus position */ scanner->opt[OPT_HOLDER_FOCUS_POS_0MM].name = "holder-focus-position-0mm"; scanner->opt[OPT_HOLDER_FOCUS_POS_0MM].title = SANE_I18N("Holder focus position 0mm"); scanner->opt[OPT_HOLDER_FOCUS_POS_0MM].desc = SANE_I18N("Use 0mm holder focus position instead of 0.6mm"); scanner->opt[OPT_HOLDER_FOCUS_POS_0MM].type = SANE_TYPE_BOOL; scanner->val[OPT_HOLDER_FOCUS_POS_0MM].w = SANE_FALSE; if (scanner->device->inquiry_sel_uta_lens_cal_pos == 0) { scanner->opt[OPT_HOLDER_FOCUS_POS_0MM].cap |= SANE_CAP_INACTIVE; } /* ------------------------------ */ /* lamp on */ scanner->opt[OPT_LAMP_ON].name = "lamp-on"; scanner->opt[OPT_LAMP_ON].title = SANE_I18N("Lamp on"); scanner->opt[OPT_LAMP_ON].desc = SANE_I18N("Turn on scanner lamp"); scanner->opt[OPT_LAMP_ON].type = SANE_TYPE_BUTTON; scanner->opt[OPT_LAMP_ON].unit = SANE_UNIT_NONE; scanner->opt[OPT_LAMP_ON].size = 0; scanner->opt[OPT_LAMP_ON].constraint_type = SANE_CONSTRAINT_NONE; scanner->val[OPT_LAMP_ON].w = 0; if (!scanner->device->lamp_control_available) /* lamp state can not be controlled by driver */ { scanner->opt[OPT_LAMP_ON].cap |= SANE_CAP_INACTIVE; } /* ------------------------------ */ /* lamp off */ scanner->opt[OPT_LAMP_OFF].name = "lamp-off"; scanner->opt[OPT_LAMP_OFF].title = SANE_I18N("Lamp off"); scanner->opt[OPT_LAMP_OFF].desc = SANE_I18N("Turn off scanner lamp"); scanner->opt[OPT_LAMP_OFF].type = SANE_TYPE_BUTTON; scanner->opt[OPT_LAMP_OFF].unit = SANE_UNIT_NONE; scanner->opt[OPT_LAMP_OFF].size = 0; scanner->opt[OPT_LAMP_OFF].constraint_type = SANE_CONSTRAINT_NONE; scanner->val[OPT_LAMP_OFF].w = 0; if (!scanner->device->lamp_control_available) /* lamp state can not be controlled by driver */ { scanner->opt[OPT_LAMP_OFF].cap |= SANE_CAP_INACTIVE; } /* ------------------------------ */ /* lamp off at exit */ scanner->opt[OPT_LAMP_OFF_AT_EXIT].name = "lamp-off-at-exit"; scanner->opt[OPT_LAMP_OFF_AT_EXIT].title = SANE_I18N("Lamp off at exit"); scanner->opt[OPT_LAMP_OFF_AT_EXIT].desc = SANE_I18N("Turn off lamp when program exits"); scanner->opt[OPT_LAMP_OFF_AT_EXIT].type = SANE_TYPE_BOOL; scanner->val[OPT_LAMP_OFF_AT_EXIT].w = SANE_FALSE; if (!scanner->device->lamp_control_available) /* lamp state can not be controlled by driver */ { scanner->opt[OPT_LAMP_OFF_AT_EXIT].cap |= SANE_CAP_INACTIVE; } /* ------------------------------ */ /* batch-scan-start */ scanner->opt[OPT_BATCH_SCAN_START].name = SANE_NAME_BATCH_SCAN_START; scanner->opt[OPT_BATCH_SCAN_START].title = SANE_TITLE_BATCH_SCAN_START; scanner->opt[OPT_BATCH_SCAN_START].desc = SANE_DESC_BATCH_SCAN_START; scanner->opt[OPT_BATCH_SCAN_START].type = SANE_TYPE_BOOL; scanner->val[OPT_BATCH_SCAN_START].w = SANE_FALSE; /* batch-scan-loop */ scanner->opt[OPT_BATCH_SCAN_LOOP].name = SANE_NAME_BATCH_SCAN_LOOP; scanner->opt[OPT_BATCH_SCAN_LOOP].title = SANE_TITLE_BATCH_SCAN_LOOP; scanner->opt[OPT_BATCH_SCAN_LOOP].desc = SANE_DESC_BATCH_SCAN_LOOP; scanner->opt[OPT_BATCH_SCAN_LOOP].type = SANE_TYPE_BOOL; scanner->val[OPT_BATCH_SCAN_LOOP].w = SANE_FALSE; /* batch-scan-end */ scanner->opt[OPT_BATCH_SCAN_END].name = SANE_NAME_BATCH_SCAN_END; scanner->opt[OPT_BATCH_SCAN_END].title = SANE_TITLE_BATCH_SCAN_END; scanner->opt[OPT_BATCH_SCAN_END].desc = SANE_DESC_BATCH_SCAN_END; scanner->opt[OPT_BATCH_SCAN_END].type = SANE_TYPE_BOOL; scanner->val[OPT_BATCH_SCAN_END].w = SANE_FALSE; /* batch-scan-next-y */ scanner->opt[OPT_BATCH_NEXT_TL_Y].name = SANE_NAME_BATCH_NEXT_TL_Y; scanner->opt[OPT_BATCH_NEXT_TL_Y].title = SANE_TITLE_BATCH_NEXT_TL_Y; scanner->opt[OPT_BATCH_NEXT_TL_Y].desc = SANE_DESC_BATCH_NEXT_TL_Y; scanner->opt[OPT_BATCH_NEXT_TL_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_BATCH_NEXT_TL_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_BATCH_NEXT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BATCH_NEXT_TL_Y].constraint.range = &(scanner->device->y_range); scanner->val[OPT_BATCH_NEXT_TL_Y].w = 0xFFFF; /* mark value as not touched */ if (scanner->device->inquiry_batch_scan == 0) { scanner->opt[OPT_BATCH_SCAN_START].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_BATCH_SCAN_LOOP].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_BATCH_SCAN_END].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_BATCH_NEXT_TL_Y].cap |= SANE_CAP_INACTIVE; } /* ------------------------------ */ #ifdef UMAX_CALIBRATION_MODE_SELECTABLE /* calibration mode */ scanner->opt[OPT_CALIB_MODE].name = "calibrationmode"; scanner->opt[OPT_CALIB_MODE].title = SANE_I18N("Calibration mode"); scanner->opt[OPT_CALIB_MODE].desc = SANE_I18N("Define calibration mode"); scanner->opt[OPT_CALIB_MODE].type = SANE_TYPE_STRING; scanner->opt[OPT_CALIB_MODE].size = max_string_size(calibration_list); scanner->opt[OPT_CALIB_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_CALIB_MODE].constraint.string_list = calibration_list; scanner->val[OPT_CALIB_MODE].s = (SANE_Char*)strdup(calibration_list[0]); if (scanner->device->inquiry_calibration == 0) { scanner->opt[OPT_CALIB_MODE].cap |= SANE_CAP_INACTIVE; } #endif /* preview */ scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; scanner->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; scanner->val[OPT_PREVIEW].w = SANE_FALSE; sane_control_option(scanner, OPT_MODE, SANE_ACTION_SET_VALUE, (SANE_String *) scan_mode_list[scan_modes], NULL ); return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ ATTACH ONE SCSI ----------------------------- */ /* callback function for sanei_config_attach_matching_devices(dev_name, attach_one_scsi) */ static SANE_Status attach_one_scsi(const char *name) { attach_scanner(name, 0, SANE_UMAX_SCSI); return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ ATTACH ONE USB ------------------------------ */ /* callback function for sanei_usb_attach_matching_devices(dev_name, attach_one_usb) */ static SANE_Status attach_one_usb(const char *name) { attach_scanner(name, 0, SANE_UMAX_USB); return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ UMAX TEST CONFIGURE OPTION ------------------ */ static SANE_Status umax_test_configure_option(const char *option_str, char *test_name, int *test_value, int test_min, int test_max) /* returns with 1 if option was found, 0 if option was not found */ { const char *value_str; char *end_ptr; int value; if (strncmp(option_str, test_name, strlen(test_name)) == 0) { value_str = sanei_config_skip_whitespace(option_str+strlen(test_name)); errno = 0; value = strtol(value_str, &end_ptr, 10); if (end_ptr == value_str || errno) { DBG(DBG_error, "ERROR: invalid value \"%s\" for option %s in %s\n", value_str, test_name, UMAX_CONFIG_FILE); } else { if (value < test_min) { DBG(DBG_error, "ERROR: value \"%d\" is too small for option %s in %s\n", value, test_name, UMAX_CONFIG_FILE); value = test_min; } else if (value > test_max) { DBG(DBG_error, "ERROR: value \"%d\" is too large for option %s in %s\n", value, test_name, UMAX_CONFIG_FILE); value = test_max; } *test_value = value; DBG(DBG_info, "option %s = %d\n", test_name, *test_value); } return 1; } return 0; } /* ------------------------------------------------------------ SANE INIT ---------------------------------- */ SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) { char config_line[PATH_MAX]; const char *option_str; size_t len; FILE *fp; /* we have to initialize these global variables here because sane_init can be called several times */ num_devices = 0; devlist = NULL; first_dev = NULL; first_handle = NULL; DBG_INIT(); DBG(DBG_sane_init,"sane_init\n"); DBG(DBG_error,"This is sane-umax version %d.%d build %d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); #ifdef UMAX_ENABLE_USB DBG(DBG_error,"compiled with USB support for Astra 2200\n"); #else DBG(DBG_error,"no USB support for Astra 2200\n"); #endif DBG(DBG_error,"(C) 1997-2002 by Oliver Rauch\n"); DBG(DBG_error,"EMAIL: Oliver.Rauch@rauch-domain.de\n"); if (version_code) { *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, BUILD); } frontend_authorize_callback = authorize; /* store frontend authorize callback */ sanei_thread_init(); /* must be called before any other sanei_thread call */ #ifdef UMAX_ENABLE_USB sanei_usb_init(); sanei_pv8630_init(); #endif fp = sanei_config_open(UMAX_CONFIG_FILE); if (!fp) { /* no config-file: try /dev/scanner and /dev/usbscanner. */ attach_scanner("/dev/scanner", 0, SANE_UMAX_SCSI); #ifdef UMAX_ENABLE_USB attach_scanner("/dev/usbscanner", 0, SANE_UMAX_USB); #endif return SANE_STATUS_GOOD; } DBG(DBG_info, "reading configure file %s\n", UMAX_CONFIG_FILE); while(sanei_config_read(config_line, sizeof(config_line), fp)) { if (config_line[0] == '#') { continue; /* ignore line comments */ } if (strncmp(config_line, "option", 6) == 0) { option_str = sanei_config_skip_whitespace(config_line+6); if (umax_test_configure_option(option_str, "scsi-maxqueue", &umax_scsi_maxqueue, 1, SANE_UMAX_SCSI_MAXQUEUE)); else if (umax_test_configure_option(option_str, "scsi-buffer-size-min", &umax_scsi_buffer_size_min, 4096, 1048576)); else if (umax_test_configure_option(option_str, "scsi-buffer-size-max", &umax_scsi_buffer_size_max, 4096, 1048576)); else if (umax_test_configure_option(option_str, "preview-lines", &umax_preview_lines, 1, 65535)); else if (umax_test_configure_option(option_str, "scan-lines", &umax_scan_lines, 1, 65535)); else if (umax_test_configure_option(option_str, "handle-bad-sense-error", &umax_handle_bad_sense_error, 0, 3)); else if (umax_test_configure_option(option_str, "execute-request-sense", &umax_execute_request_sense, 0, 1)); else if (umax_test_configure_option(option_str, "force-preview-bit-rgb", &umax_force_preview_bit_rgb, 0, 1)); else if (umax_test_configure_option(option_str, "slow-speed", &umax_slow, -1, 1)); else if (umax_test_configure_option(option_str, "care-about-smearing", &umax_smear, -1, 1)); else if (umax_test_configure_option(option_str, "calibration-full-ccd", &umax_calibration_area, -1, 1)); else if (umax_test_configure_option(option_str, "calibration-width-offset-batch", &umax_calibration_width_offset_batch, -99999, 65535)); else if (umax_test_configure_option(option_str, "calibration-width-offset", &umax_calibration_width_offset, -99999, 65535)); else if (umax_test_configure_option(option_str, "calibration-bytes-pixel", &umax_calibration_bytespp, -1, 2)); else if (umax_test_configure_option(option_str, "exposure-time-rgb-bind", &umax_exposure_time_rgb_bind, -1, 1)); else if (umax_test_configure_option(option_str, "invert-shading-data", &umax_invert_shading_data, -1, 1)); else if (umax_test_configure_option(option_str, "lamp-control-available", &umax_lamp_control_available, 0, 1)); else if (umax_test_configure_option(option_str, "gamma-lsb-padded", &umax_gamma_lsb_padded, -1, 1)); else if (umax_test_configure_option(option_str, "connection-type", &umax_connection_type, 1, 2)); else { DBG(DBG_error,"ERROR: unknown option \"%s\" in %s\n", option_str, UMAX_CONFIG_FILE); } continue; } else if (strncmp(config_line, "scsi", 4) == 0) { DBG(DBG_info,"sanei_config_attach_matching_devices(%s)\n", config_line); sanei_config_attach_matching_devices(config_line, attach_one_scsi); continue; } else if (strncmp(config_line, "usb", 3) == 0) { #ifdef UMAX_ENABLE_USB DBG(DBG_info,"sanei_usb_attach_matching_devices(%s)\n", config_line); sanei_usb_attach_matching_devices(config_line, attach_one_usb); #else DBG(DBG_info,"USB not supported, ignoring config line: %s\n", config_line); #endif continue; } len = strlen(config_line); if (!len) /* ignore empty lines */ { continue; } /* umax_connection_type is set by umax.conf: 1=scsi, 2=usb */ attach_scanner(config_line, 0, umax_connection_type); /* try to open as devicename */ } DBG(DBG_info, "finished reading configure file\n"); fclose(fp); return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ SANE EXIT ---------------------------------- */ void sane_exit(void) { Umax_Device *dev, *next; DBG(DBG_sane_init,"sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free(dev->devicename); free(dev); } if (devlist) { free(devlist); } } /* ------------------------------------------------------------ SANE GET DEVICES --------------------------- */ SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only) { Umax_Device *dev; int i; DBG(DBG_sane_init,"sane_get_devices(local_only = %d)\n", local_only); if (devlist) { free(devlist); } devlist = malloc((num_devices + 1) * sizeof (devlist[0])); if (!devlist) { return SANE_STATUS_NO_MEM; } i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) { devlist[i++] = &dev->sane; } devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ SANE OPEN ---------------------------------- */ SANE_Status sane_open(SANE_String_Const devicename, SANE_Handle *handle) { Umax_Device *dev; SANE_Status status; Umax_Scanner *scanner; unsigned int i, j; DBG(DBG_sane_init,"sane_open\n"); if (devicename[0]) /* search for devicename */ { DBG(DBG_sane_info,"sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, devicename) == 0) { break; /* device found, exit for loop */ } } if (!dev) /* no device found */ { status = attach_scanner(devicename, &dev, 0 /* connection-type not known */); /* try to open devicename and set dev */ if (status != SANE_STATUS_GOOD) { return status; } } } else { DBG(DBG_sane_info,"sane_open: no devicename, opening first device\n"); dev = first_dev; /* empty devicename -> use first device */ } if (!dev) /* no device found */ { return SANE_STATUS_INVAL; } scanner = malloc(sizeof (*scanner)); if (!scanner) { return SANE_STATUS_NO_MEM; } memset(scanner, 0, sizeof (*scanner)); scanner->device = dev; if (scanner->device->inquiry_GIB & 32) { scanner->gamma_length = 65536; /* 16 bits input */ DBG(DBG_sane_info, "Using 16 bits for gamma input\n"); } else if (scanner->device->inquiry_GIB & 16) { scanner->gamma_length = 16384; /* 14 bits input */ DBG(DBG_sane_info, "Using 14 bits for gamma input\n"); } else if (scanner->device->inquiry_GIB & 8) { scanner->gamma_length = 4096; /* 12 bits input */ DBG(DBG_sane_info, "Using 12 bits for gamma input\n"); } else if (scanner->device->inquiry_GIB & 4) { scanner->gamma_length = 1024; /* 10 bits input */ DBG(DBG_sane_info, "Using 10 bits for gamma input\n"); } else if (scanner->device->inquiry_GIB & 2) { scanner->gamma_length = 512; /* 9 bits input */ DBG(DBG_sane_info, "Using 9 bits for gamma input\n"); } else { scanner->gamma_length = 256; /* 8 bits input */ DBG(DBG_sane_info, "Using 8 bits for gamma input\n"); } scanner->output_bytes = 1; /* 8 bits output */ scanner->gamma_range.min = 0; scanner->gamma_range.max = scanner->gamma_length-1; scanner->gamma_range.quant = 0; scanner->gamma_table[0] = (SANE_Int *) malloc(scanner->gamma_length * sizeof(SANE_Int)); scanner->gamma_table[1] = (SANE_Int *) malloc(scanner->gamma_length * sizeof(SANE_Int)); scanner->gamma_table[2] = (SANE_Int *) malloc(scanner->gamma_length * sizeof(SANE_Int)); scanner->gamma_table[3] = (SANE_Int *) malloc(scanner->gamma_length * sizeof(SANE_Int)); for (j = 0; j < scanner->gamma_length; ++j) /* gamma_table[0] : converts GIB to GOB */ { scanner->gamma_table[0][j] = j * scanner->device->max_value / scanner->gamma_length; } for (i = 1; i < 4; ++i) /* gamma_table[1,2,3] : doesn't convert anything (GIB->GIB) */ { for (j = 0; j < scanner->gamma_length; ++j) { scanner->gamma_table[i][j] = j; } } scanner->exposure_time_range.min = scanner->device->inquiry_exposure_time_c_min * scanner->device->inquiry_exposure_time_step_unit; scanner->exposure_time_range.quant = scanner->device->inquiry_exposure_time_step_unit; scanner->exposure_time_range.max = scanner->device->inquiry_exposure_time_max * scanner->device->inquiry_exposure_time_step_unit; init_options(scanner); scanner->next = first_handle; /* insert newly opened handle into list of open handles: */ first_handle = scanner; *handle = scanner; return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ SANE CLOSE --------------------------------- */ void sane_close(SANE_Handle handle) { Umax_Scanner *prev, *scanner; DBG(DBG_sane_init,"sane_close\n"); if (!first_handle) { DBG(DBG_error, "ERROR: sane_close: no handles opened\n"); return; } /* remove handle from list of open handles: */ prev = 0; for (scanner = first_handle; scanner; scanner = scanner->next) { if (scanner == handle) { break; } prev = scanner; } if (!scanner) { DBG(DBG_error, "ERROR: sane_close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (scanner->scanning) /* stop scan if still scanning */ { do_cancel(handle); } if (scanner->device->lamp_control_available) /* lamp state can be controlled by driver */ { if (scanner->val[OPT_LAMP_OFF_AT_EXIT].w) /* turn off scanner lamp on sane_close */ { umax_set_lamp_status(handle, 0 /* lamp off */); } } if (prev) { prev->next = scanner->next; } else { first_handle = scanner->next; } free(scanner->gamma_table[0]); /* free custom gamma tables */ free(scanner->gamma_table[1]); free(scanner->gamma_table[2]); free(scanner->gamma_table[3]); free(scanner->device->buffer[0]); /* free buffer allocated by umax_initialize_values */ scanner->device->buffer[0] = NULL; scanner->device->bufsize = 0; free(scanner); /* free scanner */ } /* ------------------------------------------------------------ SANE GET OPTION DESCRIPTOR ----------------- */ const SANE_Option_Descriptor *sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) { Umax_Scanner *scanner = handle; DBG(DBG_sane_option,"sane_get_option_descriptor %d\n", option); if ((unsigned) option >= NUM_OPTIONS) { return 0; } return scanner->opt + option; } /* ------------------------------------------------------------ UMAX SET MAX GEOMETRY ---------------------- */ static void umax_set_max_geometry(Umax_Scanner *scanner) { if (scanner->val[OPT_DOR].w) { scanner->device->x_range.min = SANE_FIX(scanner->device->inquiry_dor_x_off * MM_PER_INCH); scanner->device->x_range.max = SANE_FIX( (scanner->device->inquiry_dor_x_off + scanner->device->inquiry_dor_width) * MM_PER_INCH); scanner->device->y_range.min = SANE_FIX(scanner->device->inquiry_dor_y_off * MM_PER_INCH); scanner->device->y_range.max = SANE_FIX( (scanner->device->inquiry_dor_y_off + scanner->device->inquiry_dor_length) * MM_PER_INCH); scanner->device->x_dpi_range.max = SANE_FIX(scanner->device->inquiry_dor_x_res); scanner->device->y_dpi_range.max = SANE_FIX(scanner->device->inquiry_dor_y_res); } else if ( (strcmp(scanner->val[OPT_SOURCE].s, FLB_STR) == 0) || (strcmp(scanner->val[OPT_SOURCE].s, ADF_STR) == 0) ) { scanner->device->x_range.min = 0; scanner->device->x_range.max = SANE_FIX(scanner->device->inquiry_fb_width * MM_PER_INCH); scanner->device->y_range.min = 0; scanner->device->y_range.max = SANE_FIX(scanner->device->inquiry_fb_length * MM_PER_INCH); scanner->device->x_dpi_range.max = SANE_FIX(scanner->device->inquiry_x_res); scanner->device->y_dpi_range.max = SANE_FIX(scanner->device->inquiry_y_res); } else if (strcmp(scanner->val[OPT_SOURCE].s, UTA_STR) == 0) { scanner->device->x_range.min = SANE_FIX(scanner->device->inquiry_uta_x_off * MM_PER_INCH); scanner->device->x_range.max = SANE_FIX( (scanner->device->inquiry_uta_x_off + scanner->device->inquiry_uta_width) * MM_PER_INCH); scanner->device->y_range.min = SANE_FIX(scanner->device->inquiry_uta_y_off * MM_PER_INCH); scanner->device->y_range.max = SANE_FIX( ( scanner->device->inquiry_uta_y_off + scanner->device->inquiry_uta_length) * MM_PER_INCH); scanner->device->x_dpi_range.max = SANE_FIX(scanner->device->inquiry_x_res); scanner->device->y_dpi_range.max = SANE_FIX(scanner->device->inquiry_y_res); } DBG(DBG_info,"x_range = [%f .. %f]\n", SANE_UNFIX(scanner->device->x_range.min), SANE_UNFIX(scanner->device->x_range.max)); DBG(DBG_info,"y_range = [%f .. %f]\n", SANE_UNFIX(scanner->device->y_range.min), SANE_UNFIX(scanner->device->y_range.max)); DBG(DBG_info,"x_dpi_range = [1 .. %f]\n", SANE_UNFIX(scanner->device->x_dpi_range.max)); DBG(DBG_info,"y_dpi_range = [1 .. %f]\n", SANE_UNFIX(scanner->device->y_dpi_range.max)); /* make sure geometry selection is in bounds */ if ( scanner->val[OPT_TL_X].w < scanner->device->x_range.min) { scanner->val[OPT_TL_X].w = scanner->device->x_range.min; } if (scanner->val[OPT_TL_Y].w < scanner->device->y_range.min) { scanner->val[OPT_TL_Y].w = scanner->device->y_range.min; } if ( scanner->val[OPT_BR_X].w > scanner->device->x_range.max) { scanner->val[OPT_BR_X].w = scanner->device->x_range.max; } if (scanner->val[OPT_BR_Y].w > scanner->device->y_range.max) { scanner->val[OPT_BR_Y].w = scanner->device->y_range.max; } } /* ------------------------------------------------------------ SANE CONTROL OPTION ------------------------ */ SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int *info) { Umax_Scanner *scanner = handle; SANE_Status status; SANE_Word w, cap; SANE_String_Const name; if (info) { *info = 0; } if (scanner->scanning) { return SANE_STATUS_DEVICE_BUSY; } if ((unsigned) option >= NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = scanner->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } name = scanner->opt[option].name; if (!name) { name = "(no name)"; } if (action == SANE_ACTION_GET_VALUE) { DBG(DBG_sane_option,"get %s [#%d]\n", name, option); switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION_BIND: case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_PREVIEW: case OPT_BIT_DEPTH: case OPT_NEGATIVE: case OPT_BATCH_SCAN_START: case OPT_BATCH_SCAN_LOOP: case OPT_BATCH_SCAN_END: case OPT_BATCH_NEXT_TL_Y: case OPT_QUALITY: case OPT_DOR: case OPT_WARMUP: case OPT_RGB_BIND: case OPT_ANALOG_GAMMA: case OPT_ANALOG_GAMMA_R: case OPT_ANALOG_GAMMA_G: case OPT_ANALOG_GAMMA_B: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_HIGHLIGHT: case OPT_HIGHLIGHT_R: case OPT_HIGHLIGHT_G: case OPT_HIGHLIGHT_B: case OPT_SHADOW: case OPT_SHADOW_R: case OPT_SHADOW_G: case OPT_SHADOW_B: case OPT_CUSTOM_GAMMA: case OPT_HALFTONE_DIMENSION: case OPT_SELECT_EXPOSURE_TIME: case OPT_SELECT_CAL_EXPOSURE_TIME: case OPT_CAL_EXPOS_TIME: case OPT_CAL_EXPOS_TIME_R: case OPT_CAL_EXPOS_TIME_G: case OPT_CAL_EXPOS_TIME_B: case OPT_SCAN_EXPOS_TIME: case OPT_SCAN_EXPOS_TIME_R: case OPT_SCAN_EXPOS_TIME_G: case OPT_SCAN_EXPOS_TIME_B: case OPT_CAL_LAMP_DEN: case OPT_SCAN_LAMP_DEN: case OPT_DISABLE_PRE_FOCUS: case OPT_MANUAL_PRE_FOCUS: case OPT_FIX_FOCUS_POSITION: case OPT_LENS_CALIBRATION_DOC_POS: case OPT_HOLDER_FOCUS_POS_0MM: case OPT_LAMP_OFF_AT_EXIT: case OPT_SELECT_LAMP_DENSITY: *(SANE_Word *) val = scanner->val[option].w; return SANE_STATUS_GOOD; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_HALFTONE_PATTERN: memcpy (val, scanner->val[option].wa, scanner->opt[option].size); return SANE_STATUS_GOOD; /* string options: */ case OPT_SOURCE: /* fall through */ case OPT_MODE: /* fall through */ #ifdef UMAX_CALIBRATION_MODE_SELECTABLE case OPT_CALIB_MODE: /* fall through */ #endif strcpy (val, scanner->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { switch (scanner->opt[option].type) { case SANE_TYPE_INT: DBG(DBG_sane_option, "set %s [#%d] to %d\n", name, option, *(SANE_Word *) val); break; case SANE_TYPE_FIXED: DBG(DBG_sane_option, "set %s [#%d] to %f\n", name, option, SANE_UNFIX(*(SANE_Word *) val)); break; case SANE_TYPE_STRING: DBG(DBG_sane_option, "set %s [#%d] to %s\n", name, option, (char *) val); break; case SANE_TYPE_BOOL: DBG(DBG_sane_option, "set %s [#%d] to %d\n", name, option, *(SANE_Word *) val); break; default: DBG(DBG_sane_option, "set %s [#%d]\n", name, option); } if (!SANE_OPTION_IS_SETTABLE(cap)) { DBG(DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value(scanner->opt+option, val, info); if (status != SANE_STATUS_GOOD) { DBG(DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } /* fall through */ case OPT_NUM_OPTS: case OPT_NEGATIVE: case OPT_BATCH_SCAN_START: case OPT_BATCH_SCAN_LOOP: case OPT_BATCH_SCAN_END: case OPT_BATCH_NEXT_TL_Y: case OPT_QUALITY: case OPT_WARMUP: case OPT_PREVIEW: case OPT_ANALOG_GAMMA: case OPT_ANALOG_GAMMA_R: case OPT_ANALOG_GAMMA_G: case OPT_ANALOG_GAMMA_B: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_HIGHLIGHT: case OPT_HIGHLIGHT_R: case OPT_HIGHLIGHT_G: case OPT_HIGHLIGHT_B: case OPT_SHADOW: case OPT_SHADOW_R: case OPT_SHADOW_G: case OPT_SHADOW_B: case OPT_CAL_EXPOS_TIME: case OPT_CAL_EXPOS_TIME_R: case OPT_CAL_EXPOS_TIME_G: case OPT_CAL_EXPOS_TIME_B: case OPT_SCAN_EXPOS_TIME: case OPT_SCAN_EXPOS_TIME_R: case OPT_SCAN_EXPOS_TIME_G: case OPT_SCAN_EXPOS_TIME_B: case OPT_CAL_LAMP_DEN: case OPT_SCAN_LAMP_DEN: case OPT_DISABLE_PRE_FOCUS: case OPT_MANUAL_PRE_FOCUS: case OPT_FIX_FOCUS_POSITION: case OPT_LENS_CALIBRATION_DOC_POS: case OPT_HOLDER_FOCUS_POS_0MM: case OPT_LAMP_OFF_AT_EXIT: scanner->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_DOR: { if (scanner->val[option].w != *(SANE_Word *) val) { scanner->val[option].w = *(SANE_Word *) val; /* update valure for umax_set_max_geometry */ if (info) { *info |= SANE_INFO_RELOAD_PARAMS; *info |= SANE_INFO_RELOAD_OPTIONS; } DBG(DBG_info,"sane_control_option: set DOR = %d\n", scanner->val[option].w); umax_set_max_geometry(scanner); } return SANE_STATUS_GOOD; } case OPT_BIT_DEPTH: { if (scanner->val[option].w != *(SANE_Word *) val) { scanner->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } scanner->output_range.min = 0; scanner->output_range.quant = 0; if (scanner->val[option].w == 8) /* 8 bit mode */ { scanner->output_bytes = 1; /* 1 bytes output */ scanner->output_range.max = 255; } else /* > 8 bit mode */ { scanner->output_bytes = 2; /* 2 bytes output */ if (scanner->device->gamma_lsb_padded) /* e.g. astra 1220s need lsb padded data */ { scanner->output_range.max = (int) pow(2, scanner->val[option].w) - 1; } else { scanner->output_range.max = 65535; /* define maxval for msb padded data */ } } if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } } return SANE_STATUS_GOOD; } case OPT_RGB_BIND: { if (scanner->val[option].w != *(SANE_Word *) val) { scanner->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } umax_set_rgb_bind(scanner); } return SANE_STATUS_GOOD; } case OPT_RESOLUTION_BIND: { if (scanner->val[option].w != *(SANE_Word *) val) { scanner->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } if (scanner->val[option].w == SANE_FALSE) { /* don't bind */ scanner->opt[OPT_Y_RESOLUTION].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_X_RESOLUTION; scanner->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; scanner->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_X_RESOLUTION; } else { /* bind */ scanner->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; scanner->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; scanner->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; } } return SANE_STATUS_GOOD; } case OPT_SELECT_EXPOSURE_TIME: case OPT_SELECT_CAL_EXPOSURE_TIME: { if (scanner->val[option].w != *(SANE_Word *) val) { scanner->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } if (scanner->val[OPT_SELECT_EXPOSURE_TIME].w == SANE_FALSE) { scanner->opt[OPT_SELECT_CAL_EXPOSURE_TIME].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; } else /* exposure time selection active */ { scanner->opt[OPT_SELECT_CAL_EXPOSURE_TIME].cap &= ~SANE_CAP_INACTIVE; if ( (strcmp(scanner->val[OPT_MODE].s, COLOR_STR) != 0) || (scanner->val[OPT_RGB_BIND].w == SANE_TRUE) || (scanner->device->exposure_time_rgb_bind) ) /* RGB bind */ { if (scanner->val[OPT_SELECT_CAL_EXPOSURE_TIME].w) { scanner->opt[OPT_CAL_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; } else { scanner->opt[OPT_CAL_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_SCAN_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; } else /* no RGB bind */ { if (scanner->val[OPT_SELECT_CAL_EXPOSURE_TIME].w) { scanner->opt[OPT_CAL_EXPOS_TIME_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_B].cap &= ~SANE_CAP_INACTIVE; } else { scanner->opt[OPT_CAL_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_SCAN_EXPOS_TIME_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_B].cap &= ~SANE_CAP_INACTIVE; } } } return SANE_STATUS_GOOD; } case OPT_SELECT_LAMP_DENSITY: { if (scanner->val[option].w != *(SANE_Word *) val) { scanner->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } if (scanner->val[option].w == SANE_FALSE) { scanner->opt[OPT_CAL_LAMP_DEN].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_LAMP_DEN].cap |= SANE_CAP_INACTIVE; } else { scanner->opt[OPT_CAL_LAMP_DEN].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_LAMP_DEN].cap &= ~SANE_CAP_INACTIVE; } } return SANE_STATUS_GOOD; } /* side-effect-free word-array options: */ case OPT_HALFTONE_PATTERN: case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (scanner->val[option].wa, val, scanner->opt[option].size); return SANE_STATUS_GOOD; /* single string-option with side-effect: */ case OPT_SOURCE: { if (scanner->val[option].s) { free(scanner->val[option].s); } scanner->val[option].s = (SANE_Char *) strdup(val); /* update string for umax_set_max_geometry */ DBG(DBG_info,"sane_control_option: set SOURCE = %s\n", (SANE_Char *) val); umax_set_max_geometry(scanner); if (info) { *info |= SANE_INFO_RELOAD_PARAMS; *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; } break; /* side-effect-free single-string options: */ #ifdef UMAX_CALIBRATION_MODE_SELECTABLE case OPT_CALIB_MODE: /* fall through */ #endif { if (scanner->val[option].s) { free (scanner->val[option].s); } scanner->val[option].s = (SANE_Char*)strdup(val); return SANE_STATUS_GOOD; } /* options with side-effects: */ case OPT_CUSTOM_GAMMA: { w = *(SANE_Word *) val; if (w == scanner->val[OPT_CUSTOM_GAMMA].w) { return SANE_STATUS_GOOD; } scanner->val[OPT_CUSTOM_GAMMA].w = w; if (w) /* use custom_gamma_table */ { const char *mode = scanner->val[OPT_MODE].s; if ( (strcmp(mode, LINEART_STR) == 0) || (strcmp(mode, HALFTONE_STR) == 0) || (strcmp(mode, GRAY_STR) == 0) ) { scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp(mode, COLOR_STR) == 0) { scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else /* don't use custom_gamma_table */ { scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; } case OPT_MODE: { int halftoning; if (scanner->val[option].s) { free (scanner->val[option].s); } scanner->val[option].s = (SANE_Char*)strdup(val); if (info) { *info |=SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } scanner->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_RGB_BIND].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CAL_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HALFTONE_DIMENSION].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; halftoning = (strcmp(val, HALFTONE_STR) == 0 || strcmp(val, COLOR_HALFTONE_STR) == 0); if (halftoning || strcmp(val, LINEART_STR) == 0 || strcmp(val, COLOR_LINEART_STR) == 0) { /* one bit modes */ if (scanner->device->inquiry_reverse) { scanner->opt[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE; } if (halftoning) { /* halftoning modes */ scanner->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; if (scanner->device->inquiry_highlight) { scanner->opt[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; } if (scanner->device->inquiry_shadow) { scanner->opt[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; } /* disable halftone pattern download options */ #if 0 scanner->opt[OPT_HALFTONE_DIMENSION].cap &= ~SANE_CAP_INACTIVE; if (scanner->val[OPT_HALFTONE_DIMENSION].w) { scanner->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } #endif if (scanner->val[OPT_SELECT_EXPOSURE_TIME].w == SANE_TRUE) { scanner->opt[OPT_CAL_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; } scanner->exposure_time_range.min = scanner->device->inquiry_exposure_time_h_min * scanner->device->inquiry_exposure_time_step_unit; } else { /* lineart modes */ scanner->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; if (scanner->val[OPT_SELECT_EXPOSURE_TIME].w == SANE_TRUE) { scanner->opt[OPT_CAL_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; } scanner->exposure_time_range.min = scanner->device->inquiry_exposure_time_l_min * scanner->device->inquiry_exposure_time_step_unit; } } else { /* multi-bit modes(gray or color) */ scanner->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; if (scanner->device->inquiry_highlight) { scanner->opt[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; } if (scanner->device->inquiry_shadow) { scanner->opt[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; } if (scanner->device->inquiry_reverse_multi) { scanner->opt[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE; } if (scanner->device->inquiry_gamma_dwload) { scanner->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; } else { scanner->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; } if (scanner->device->inquiry_analog_gamma) { scanner->opt[OPT_ANALOG_GAMMA].cap &= ~SANE_CAP_INACTIVE; } if (scanner->val[OPT_SELECT_EXPOSURE_TIME].w == SANE_TRUE) { scanner->opt[OPT_CAL_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_SCAN_EXPOS_TIME].cap &= ~SANE_CAP_INACTIVE; } if (strcmp(val, COLOR_STR) == 0) { if ( (scanner->device->inquiry_analog_gamma) || (scanner->device->inquiry_highlight) || (scanner->device->inquiry_shadow) || (scanner->device->inquiry_exposure_adj) ) { scanner->opt[OPT_RGB_BIND].cap &= ~SANE_CAP_INACTIVE; } scanner->exposure_time_range.min = scanner->device->inquiry_exposure_time_c_min * scanner->device->inquiry_exposure_time_step_unit; } else /* grayscale */ { scanner->exposure_time_range.min = scanner->device->inquiry_exposure_time_g_min * scanner->device->inquiry_exposure_time_step_unit; } } umax_set_rgb_bind(scanner); if (scanner->val[OPT_CUSTOM_GAMMA].w) { if (strcmp(val, GRAY_STR) == 0) { scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp(val, COLOR_STR) == 0) { scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } return SANE_STATUS_GOOD; } case OPT_HALFTONE_DIMENSION: /* halftone pattern dimension affects halftone pattern option: */ { unsigned dim = *(SANE_Word *) val; scanner->val[option].w = dim; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } scanner->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (dim > 0) { scanner->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_HALFTONE_PATTERN].size = dim * sizeof (SANE_Word); } return SANE_STATUS_GOOD; } case OPT_LAMP_ON: { if (!umax_set_lamp_status(handle, 1 /* lamp on */)) { return SANE_STATUS_GOOD; } else { return SANE_STATUS_UNSUPPORTED; } } case OPT_LAMP_OFF: { if (!umax_set_lamp_status(handle, 0 /* lamp off */)) { return SANE_STATUS_GOOD; } else { return SANE_STATUS_UNSUPPORTED; } } } } /* else */ return SANE_STATUS_INVAL; } /* ------------------------------------------------------------ SANE GET PARAMETERS ------------------------ */ SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters *params) { Umax_Scanner *scanner = handle; const char *mode; DBG(DBG_sane_info,"sane_get_parameters\n"); if (!scanner->scanning) { /* not scanning, so lets use recent values */ double width, length, x_dpi, y_dpi; memset(&scanner->params, 0, sizeof (scanner->params)); width = SANE_UNFIX(scanner->val[OPT_BR_X].w - scanner->val[OPT_TL_X].w); length = SANE_UNFIX(scanner->val[OPT_BR_Y].w - scanner->val[OPT_TL_Y].w); x_dpi = SANE_UNFIX(scanner->val[OPT_X_RESOLUTION].w); y_dpi = SANE_UNFIX(scanner->val[OPT_Y_RESOLUTION].w); if ( (scanner->val[OPT_RESOLUTION_BIND].w == SANE_TRUE) || (scanner->val[OPT_PREVIEW].w == SANE_TRUE) ) { y_dpi = x_dpi; } if (x_dpi > 0.0 && y_dpi > 0.0 && width > 0.0 && length > 0.0) { double x_dots_per_mm = x_dpi / MM_PER_INCH; double y_dots_per_mm = y_dpi / MM_PER_INCH; scanner->params.pixels_per_line = width * x_dots_per_mm; scanner->params.lines = length * y_dots_per_mm; } } mode = scanner->val[OPT_MODE].s; if (strcmp(mode, LINEART_STR) == 0 || strcmp(mode, HALFTONE_STR) == 0) { scanner->params.format = SANE_FRAME_GRAY; scanner->params.bytes_per_line = (scanner->params.pixels_per_line + 7) / 8; scanner->params.depth = 1; } else if (strcmp(mode, GRAY_STR) == 0) { scanner->params.format = SANE_FRAME_GRAY; scanner->params.bytes_per_line = scanner->params.pixels_per_line * scanner->output_bytes; scanner->params.depth = 8 * scanner->output_bytes; } else if (strcmp(mode, COLOR_LINEART_STR) == 0 || strcmp(mode, COLOR_HALFTONE_STR) == 0 ) { if (scanner->device->inquiry_one_pass_color) { scanner->device->three_pass = 0; scanner->params.format = SANE_FRAME_RGB; scanner->params.bytes_per_line = 3 * scanner->params.pixels_per_line; scanner->params.depth = 8; } else /* three pass color */ { scanner->device->three_pass = 1; scanner->params.format = SANE_FRAME_RED + scanner->device->three_pass_color - 1; scanner->params.bytes_per_line = scanner->params.pixels_per_line; scanner->params.depth = 8; } } else /* RGB */ { if (scanner->device->inquiry_one_pass_color) { scanner->device->three_pass = 0; scanner->params.format = SANE_FRAME_RGB; scanner->params.bytes_per_line = 3 * scanner->params.pixels_per_line * scanner->output_bytes; scanner->params.depth = 8 * scanner->output_bytes; } else /* three pass color */ { scanner->device->three_pass = 1; scanner->params.format = SANE_FRAME_RED + scanner->device->three_pass_color - 1; scanner->params.bytes_per_line = scanner->params.pixels_per_line * scanner->output_bytes; scanner->params.depth = 8 * scanner->output_bytes; } } scanner->params.last_frame = (scanner->params.format != SANE_FRAME_RED && scanner->params.format != SANE_FRAME_GREEN); if (params) { *params = scanner->params; } return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ SANE START --------------------------------- */ SANE_Status sane_start(SANE_Handle handle) { Umax_Scanner *scanner = handle; const char *mode; double xbasedots, ybasedots; const char *scan_source; int pause; int status; int fds[2]; DBG(DBG_sane_init,"sane_start\n"); /* Initialize reader_pid to invalid so a subsequent error and following call * to do_cancel() won't trip over it. */ scanner->reader_pid = -1; mode = scanner->val[OPT_MODE].s; if (scanner->device->sfd == -1) /* first call, don`t run this routine again on multi frame or multi image scan */ { umax_initialize_values(scanner->device); /* reset values */ scanner->device->three_pass_color = 1; /* test for adf and uta */ scan_source = scanner->val[OPT_SOURCE].s; if (strcmp(scan_source, UTA_STR) == 0) { if ( (scanner->device->inquiry_uta != 0) && (scanner->device->inquiry_transavail != 0) ) { scanner->device->uta = 1; } else { DBG(DBG_error,"ERROR: Transparency Adapter not available\n"); umax_scsi_close(scanner->device); return SANE_STATUS_INVAL; } } else /* Test if ADF is selected */ { scanner->device->uta = 0; if (strcmp(scan_source, ADF_STR) == 0) { if ( (scanner->device->inquiry_adf) && (scanner->device->inquiry_adfmode) ) { scanner->device->adf = 1; } else { DBG(DBG_error,"ERROR: Automatic Document Feeder not available\n"); umax_scsi_close(scanner->device); return SANE_STATUS_INVAL; } } else { scanner->device->adf = 0; } } if (scanner->device->inquiry_GIB & 32) /* 16 bit input mode */ { scanner->device->gamma_input_bits_code = 32; DBG(DBG_sane_info, "Using 16 bits for gamma input\n"); } else if (scanner->device->inquiry_GIB & 16) /* 14 bit input mode */ { scanner->device->gamma_input_bits_code = 16; DBG(DBG_sane_info, "Using 14 bits for gamma input\n"); } else if (scanner->device->inquiry_GIB & 8) /* 12 bit input mode */ { scanner->device->gamma_input_bits_code = 8; DBG(DBG_sane_info, "Using 12 bits for gamma input\n"); } else if (scanner->device->inquiry_GIB & 4) /* 10 bit input mode */ { scanner->device->gamma_input_bits_code = 4; DBG(DBG_sane_info, "Using 10 bits for gamma input\n"); } else if (scanner->device->inquiry_GIB & 2) /* 9 bit input mode */ { scanner->device->gamma_input_bits_code = 2; DBG(DBG_sane_info, "Using 9 bits for gamma input\n"); } else /* 8 bit input mode */ { scanner->device->gamma_input_bits_code = 1; DBG(DBG_sane_info, "Using 8 bits for gamma input\n"); } if (scanner->val[OPT_BIT_DEPTH].w == 16) /* 16 bit output mode */ { scanner->device->bits_per_pixel = 16; scanner->device->bits_per_pixel_code = 32; scanner->device->max_value = 65535; DBG(DBG_sane_info,"Using 16 bits for output\n"); } else if (scanner->val[OPT_BIT_DEPTH].w == 14) /* 14 bit output mode */ { scanner->device->bits_per_pixel = 14; scanner->device->bits_per_pixel_code = 16; scanner->device->max_value = 16383; DBG(DBG_sane_info,"Using 14 bits for output\n"); } else if (scanner->val[OPT_BIT_DEPTH].w == 12) /* 12 bit output mode */ { scanner->device->bits_per_pixel = 12; scanner->device->bits_per_pixel_code = 8; scanner->device->max_value = 4095; DBG(DBG_sane_info,"Using 12 bits for output\n"); } else if (scanner->val[OPT_BIT_DEPTH].w == 10) /* 10 bit output mode */ { scanner->device->bits_per_pixel = 10; scanner->device->bits_per_pixel_code = 4; scanner->device->max_value = 1023; DBG(DBG_sane_info,"Using 10 bits for output\n"); } else if (scanner->val[OPT_BIT_DEPTH].w == 9) /* 9 bit output mode */ { scanner->device->bits_per_pixel = 9; scanner->device->bits_per_pixel_code = 2; scanner->device->max_value = 511; DBG(DBG_sane_info,"Using 9 bits for output\n"); } else /* 8 bit output mode */ { scanner->device->bits_per_pixel = 8; scanner->device->bits_per_pixel_code = 1; scanner->device->max_value = 255; DBG(DBG_sane_info,"Using 8 bits for output\n"); } scanner->device->reverse = scanner->device->reverse_multi = scanner->val[OPT_NEGATIVE].w; scanner->device->threshold = P_100_TO_255(scanner->val[OPT_THRESHOLD].w); scanner->device->brightness = P_200_TO_255(scanner->val[OPT_BRIGHTNESS].w); scanner->device->contrast = P_200_TO_255(scanner->val[OPT_CONTRAST].w); scanner->device->batch_scan = ( scanner->val[OPT_BATCH_SCAN_START].w || scanner->val[OPT_BATCH_SCAN_LOOP].w || scanner->val[OPT_BATCH_SCAN_END].w ); scanner->device->batch_end = scanner->val[OPT_BATCH_SCAN_END].w; scanner->device->batch_next_tl_y = SANE_UNFIX(scanner->val[OPT_BATCH_NEXT_TL_Y].w) * scanner->device->y_coordinate_base / MM_PER_INCH; if (scanner->val[OPT_BATCH_NEXT_TL_Y].w == 0xFFFF) /* option not set: use br_y => scanhead stops at end of batch area */ { scanner->device->batch_next_tl_y = SANE_UNFIX(scanner->val[OPT_BR_Y].w) * scanner->device->y_coordinate_base / MM_PER_INCH; } if ((scanner->device->batch_scan) && !scanner->val[OPT_BATCH_SCAN_START].w) { scanner->device->calibration = 9; /* no calibration - otherwise the scanhead will go into calibration position */ } else { scanner->device->calibration = 0; /* calibration defined by image type */ } scanner->device->quality = scanner->val[OPT_QUALITY].w; scanner->device->dor = scanner->val[OPT_DOR].w; scanner->device->preview = scanner->val[OPT_PREVIEW].w; scanner->device->warmup = scanner->val[OPT_WARMUP].w; scanner->device->fix_focus_position = scanner->val[OPT_FIX_FOCUS_POSITION].w; scanner->device->lens_cal_in_doc_pos = scanner->val[OPT_LENS_CALIBRATION_DOC_POS].w; scanner->device->disable_pre_focus = scanner->val[OPT_DISABLE_PRE_FOCUS].w; scanner->device->holder_focus_pos_0mm = scanner->val[OPT_HOLDER_FOCUS_POS_0MM].w; scanner->device->manual_focus = scanner->val[OPT_MANUAL_PRE_FOCUS].w; scanner->device->analog_gamma_r = scanner->device->analog_gamma_g = scanner->device->analog_gamma_b = umax_calculate_analog_gamma(SANE_UNFIX(scanner->val[OPT_ANALOG_GAMMA].w)); scanner->device->highlight_r = scanner->device->highlight_g = scanner->device->highlight_b = P_100_TO_255(scanner->val[OPT_HIGHLIGHT].w); scanner->device->shadow_r = scanner->device->shadow_g = scanner->device->shadow_b = P_100_TO_255(scanner->val[OPT_SHADOW].w); if (scanner->val[OPT_SELECT_EXPOSURE_TIME].w == SANE_TRUE) { if (scanner->val[OPT_SELECT_CAL_EXPOSURE_TIME].w) /* separate calibration exposure time */ { scanner->device->exposure_time_calibration_r = scanner->device->exposure_time_calibration_g = scanner->device->exposure_time_calibration_b = scanner->val[OPT_CAL_EXPOS_TIME].w; } else /* same exposure times for calibration as for scanning */ { scanner->device->exposure_time_calibration_r = scanner->device->exposure_time_calibration_g = scanner->device->exposure_time_calibration_b = scanner->val[OPT_SCAN_EXPOS_TIME].w; } scanner->device->exposure_time_scan_r = scanner->device->exposure_time_scan_g = scanner->device->exposure_time_scan_b = scanner->val[OPT_SCAN_EXPOS_TIME].w; } if (scanner->val[OPT_SELECT_LAMP_DENSITY].w == SANE_TRUE) { scanner->device->c_density = P_100_TO_254(scanner->val[OPT_CAL_LAMP_DEN].w); scanner->device->s_density = P_100_TO_254(scanner->val[OPT_SCAN_LAMP_DEN].w); } if (strcmp(mode, LINEART_STR) == 0) { scanner->device->colormode = LINEART; } else if (strcmp(mode, HALFTONE_STR) == 0) { scanner->device->colormode = HALFTONE; } else if (strcmp(mode, GRAY_STR) == 0) { scanner->device->colormode = GRAYSCALE; } else if (strcmp(mode, COLOR_LINEART_STR) == 0) { scanner->device->colormode = RGB_LINEART; } else if (strcmp(mode, COLOR_HALFTONE_STR) == 0) { scanner->device->colormode = RGB_HALFTONE; } else if (strcmp(mode, COLOR_STR) == 0) { scanner->device->colormode = RGB; if (scanner->val[OPT_RGB_BIND].w == SANE_FALSE) { scanner->device->analog_gamma_r = umax_calculate_analog_gamma( SANE_UNFIX(scanner->val[OPT_ANALOG_GAMMA_R].w) ); scanner->device->analog_gamma_g = umax_calculate_analog_gamma( SANE_UNFIX(scanner->val[OPT_ANALOG_GAMMA_G].w) ); scanner->device->analog_gamma_b = umax_calculate_analog_gamma( SANE_UNFIX(scanner->val[OPT_ANALOG_GAMMA_B].w) ); scanner->device->highlight_r = P_100_TO_255(scanner->val[OPT_HIGHLIGHT_R].w); scanner->device->highlight_g = P_100_TO_255(scanner->val[OPT_HIGHLIGHT_G].w); scanner->device->highlight_b = P_100_TO_255(scanner->val[OPT_HIGHLIGHT_B].w); scanner->device->shadow_r = P_100_TO_255(scanner->val[OPT_SHADOW_R].w); scanner->device->shadow_g = P_100_TO_255(scanner->val[OPT_SHADOW_G].w); scanner->device->shadow_b = P_100_TO_255(scanner->val[OPT_SHADOW_B].w); if ((scanner->val[OPT_SELECT_EXPOSURE_TIME].w == SANE_TRUE) && (!scanner->device->exposure_time_rgb_bind)) { if (scanner->val[OPT_SELECT_CAL_EXPOSURE_TIME].w) /* separate calibration exposure time */ { scanner->device->exposure_time_calibration_r = scanner->val[OPT_CAL_EXPOS_TIME_R].w; scanner->device->exposure_time_calibration_g = scanner->val[OPT_CAL_EXPOS_TIME_G].w; scanner->device->exposure_time_calibration_b = scanner->val[OPT_CAL_EXPOS_TIME_B].w; } else /* same exposure times for calibration as for scanning */ { scanner->device->exposure_time_calibration_r = scanner->val[OPT_SCAN_EXPOS_TIME_R].w; scanner->device->exposure_time_calibration_g = scanner->val[OPT_SCAN_EXPOS_TIME_G].w; scanner->device->exposure_time_calibration_b = scanner->val[OPT_SCAN_EXPOS_TIME_B].w; } scanner->device->exposure_time_scan_r = scanner->val[OPT_SCAN_EXPOS_TIME_R].w; scanner->device->exposure_time_scan_g = scanner->val[OPT_SCAN_EXPOS_TIME_G].w; scanner->device->exposure_time_scan_b = scanner->val[OPT_SCAN_EXPOS_TIME_B].w; } } } if (scanner->device->force_preview_bit_rgb != 0) /* in RGB-mode set preview bit, eg. for UMAX S6E */ { if (scanner->device->colormode == RGB) { DBG(DBG_sane_info,"setting preview bit = 1 (option force-preview-bit-rgb)\n"); scanner->device->preview = SANE_TRUE; } } #ifdef UMAX_CALIBRATION_MODE_SELECTABLE if (strcmp(scanner->val[OPT_CALIB_MODE].s, CALIB_MODE_0000) == 0) { scanner->device->calibration = 0; } else if (strcmp(scanner->val[OPT_CALIB_MODE].s, CALIB_MODE_1111) == 0) { scanner->device->calibration = 15; } else if (strcmp(scanner->val[OPT_CALIB_MODE].s, CALIB_MODE_1110) == 0) { scanner->device->calibration = 14; } else if (strcmp(scanner->val[OPT_CALIB_MODE].s, CALIB_MODE_1101) == 0) { scanner->device->calibration = 13; } else if (strcmp(scanner->val[OPT_CALIB_MODE].s, CALIB_MODE_1010) == 0) { scanner->device->calibration = 10; } else if (strcmp(scanner->val[OPT_CALIB_MODE].s, CALIB_MODE_1001) == 0) { scanner->device->calibration = 9; } #endif /* get and set geometric values for scanning */ scanner->device->x_resolution = SANE_UNFIX(scanner->val[OPT_X_RESOLUTION].w); scanner->device->y_resolution = SANE_UNFIX(scanner->val[OPT_Y_RESOLUTION].w); if ( (scanner->val[OPT_RESOLUTION_BIND].w == SANE_TRUE) || (scanner->val[OPT_PREVIEW].w == SANE_TRUE) ) { scanner->device->y_resolution = scanner->device->x_resolution; } xbasedots = scanner->device->x_coordinate_base / MM_PER_INCH; ybasedots = scanner->device->y_coordinate_base / MM_PER_INCH; #if 0 scanner->device->upper_left_x = ((int) (SANE_UNFIX(scanner->val[OPT_TL_X].w) * xbasedots)) & 65534; scanner->device->upper_left_y = ((int) (SANE_UNFIX(scanner->val[OPT_TL_Y].w) * ybasedots)) & 65534; scanner->device->scanwidth = ((int)((SANE_UNFIX(scanner->val[OPT_BR_X].w - scanner->val[OPT_TL_X].w)) * xbasedots)) & 65534; scanner->device->scanlength = ((int)((SANE_UNFIX(scanner->val[OPT_BR_Y].w - scanner->val[OPT_TL_Y].w)) * ybasedots)) & 65534; #endif scanner->device->upper_left_x = (int) (SANE_UNFIX(scanner->val[OPT_TL_X].w) * xbasedots); scanner->device->upper_left_y = (int) (SANE_UNFIX(scanner->val[OPT_TL_Y].w) * ybasedots); scanner->device->scanwidth = (int)((SANE_UNFIX(scanner->val[OPT_BR_X].w - scanner->val[OPT_TL_X].w)) * xbasedots); scanner->device->scanlength = (int)((SANE_UNFIX(scanner->val[OPT_BR_Y].w - scanner->val[OPT_TL_Y].w)) * ybasedots); if (umax_check_values(scanner->device) != 0) { DBG(DBG_error,"ERROR: invalid scan-values\n"); scanner->scanning = SANE_FALSE; return SANE_STATUS_INVAL; } /* The scanner defines a x-origin-offset for DOR mode, this offset is used for the */ /* x range in this backend, so the frontend/user knows the correct positions related to */ /* scanner's surface. But the scanner wants x values from origin 0 instead */ /* of the x-origin defined by the scanner`s inquiry */ if (scanner->device->dor != 0) /* dor mode active */ { DBG(DBG_info,"subtracting DOR x-origin-offset from upper left x\n"); scanner->device->upper_left_x -= scanner->device->inquiry_dor_x_off * scanner->device->x_coordinate_base; /* correct DOR x-origin */ if (scanner->device->upper_left_x < 0) /* rounding errors may create a negative value */ { scanner->device->upper_left_x = 0; /* but negative values are not allowed */ } } scanner->params.bytes_per_line = scanner->device->row_len; scanner->params.pixels_per_line = scanner->device->width_in_pixels; scanner->params.lines = scanner->device->length_in_pixels; /* set exposure times */ if ( scanner->device->inquiry_exposure_adj ) { umax_calculate_exposure_time(scanner->device, scanner->device->use_exposure_time_def_r, &scanner->device->exposure_time_calibration_r); umax_calculate_exposure_time(scanner->device, scanner->device->use_exposure_time_def_g, &scanner->device->exposure_time_calibration_g); umax_calculate_exposure_time(scanner->device, scanner->device->use_exposure_time_def_b, &scanner->device->exposure_time_calibration_b); umax_calculate_exposure_time(scanner->device, scanner->device->use_exposure_time_def_r, &scanner->device->exposure_time_scan_r); umax_calculate_exposure_time(scanner->device, scanner->device->use_exposure_time_def_g, &scanner->device->exposure_time_scan_g); umax_calculate_exposure_time(scanner->device, scanner->device->use_exposure_time_def_b, &scanner->device->exposure_time_scan_b); } else { scanner->device->exposure_time_calibration_r = scanner->device->exposure_time_calibration_g = scanner->device->exposure_time_calibration_b = scanner->device->exposure_time_scan_r = scanner->device->exposure_time_scan_g = scanner->device->exposure_time_scan_b = 0; } scanner->scanning = SANE_TRUE; sane_get_parameters(scanner, 0); DBG(DBG_sane_info,"x_resolution (dpi) = %u\n", scanner->device->x_resolution); DBG(DBG_sane_info,"y_resolution (dpi) = %u\n", scanner->device->y_resolution); DBG(DBG_sane_info,"x_coordinate_base (dpi) = %u\n", scanner->device->x_coordinate_base); DBG(DBG_sane_info,"y_coordinate_base (dpi) = %u\n", scanner->device->y_coordinate_base); DBG(DBG_sane_info,"upper_left_x (xbase) = %d\n", scanner->device->upper_left_x); DBG(DBG_sane_info,"upper_left_y (ybase) = %d\n", scanner->device->upper_left_y); DBG(DBG_sane_info,"scanwidth (xbase) = %u\n", scanner->device->scanwidth); DBG(DBG_sane_info,"scanlength (ybase) = %u\n", scanner->device->scanlength); DBG(DBG_sane_info,"width in pixels = %u\n", scanner->device->width_in_pixels); DBG(DBG_sane_info,"length in pixels = %u\n", scanner->device->length_in_pixels); DBG(DBG_sane_info,"bits per pixel/color = %u\n", scanner->device->bits_per_pixel); DBG(DBG_sane_info,"bytes per line = %d\n", scanner->params.bytes_per_line); DBG(DBG_sane_info,"pixels_per_line = %d\n", scanner->params.pixels_per_line); DBG(DBG_sane_info,"lines = %d\n", scanner->params.lines); DBG(DBG_sane_info,"negative = %d\n", scanner->device->reverse); DBG(DBG_sane_info,"threshold (lineart) = %d\n", scanner->device->threshold); DBG(DBG_sane_info,"brightness (halftone) = %d\n", scanner->device->brightness); DBG(DBG_sane_info,"contrast (halftone) = %d\n", scanner->device->contrast); DBG(DBG_sane_info,"analog_gamma = %d %d %d\n", scanner->device->analog_gamma_r, scanner->device->analog_gamma_g, scanner->device->analog_gamma_b); DBG(DBG_sane_info,"highlight = %d %d %d\n", scanner->device->highlight_r, scanner->device->highlight_g, scanner->device->highlight_b); DBG(DBG_sane_info,"shadow = %d %d %d\n", scanner->device->shadow_r, scanner->device->shadow_g, scanner->device->shadow_b); DBG(DBG_sane_info,"calibrat. exposure time = %d %d %d\n", scanner->device->exposure_time_calibration_r, scanner->device->exposure_time_calibration_g, scanner->device->exposure_time_calibration_b); DBG(DBG_sane_info,"scan exposure time = %d %d %d\n", scanner->device->exposure_time_scan_r, scanner->device->exposure_time_scan_g, scanner->device->exposure_time_scan_b); #ifdef UMAX_CALIBRATION_MODE_SELECTABLE DBG(DBG_sane_info,"calibration = %s\n", scanner->val[OPT_CALIB_MODE].s); #endif DBG(DBG_sane_info,"calibration mode number = %d\n", scanner->device->calibration); DBG(DBG_sane_info,"batch scan = %d\n", scanner->device->batch_scan); DBG(DBG_sane_info,"batch end = %d\n", scanner->device->batch_end); DBG(DBG_sane_info,"batch next top left y = %d\n", scanner->device->batch_next_tl_y); DBG(DBG_sane_info,"quality calibration = %d\n", scanner->device->quality); DBG(DBG_sane_info,"warm up = %d\n", scanner->device->warmup); DBG(DBG_sane_info,"fast preview function = %d\n", scanner->device->preview); DBG(DBG_sane_info,"DOR = %d\n", scanner->device->dor); DBG(DBG_sane_info,"ADF = %d\n", scanner->device->adf); DBG(DBG_sane_info,"manual focus = %d\n", scanner->device->manual_focus); DBG(DBG_sane_info,"fix focus position = %d\n", scanner->device->fix_focus_position); DBG(DBG_sane_info,"disable pre focus = %d\n", scanner->device->disable_pre_focus); DBG(DBG_sane_info,"lens cal in doc pos = %d\n", scanner->device->lens_cal_in_doc_pos); DBG(DBG_sane_info,"holder focus pos 0mm = %d\n", scanner->device->holder_focus_pos_0mm); if (scanner->val[OPT_PREVIEW].w) /* preview mode */ { scanner->device->lines_max = scanner->device->request_preview_lines; } else /* scan mode */ { scanner->device->lines_max = scanner->device->request_scan_lines; } #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED { unsigned int scsi_bufsize = 0; scsi_bufsize = scanner->device->width_in_pixels * scanner->device->lines_max; if (scsi_bufsize == 0) /* no scsi buffer size, take scanner buffer size */ { scsi_bufsize = scanner->device->inquiry_vidmem; } if (scsi_bufsize < scanner->device->scsi_buffer_size_min) /* make sure buffer has at least minimum size */ { scsi_bufsize = scanner->device->scsi_buffer_size_min; } else if (scsi_bufsize > scanner->device->scsi_buffer_size_max) /* make sure buffer does not exceed maximum size */ { scsi_bufsize = scanner->device->scsi_buffer_size_max; } if (umax_scsi_open_extended(scanner->device->sane.name, scanner->device, sense_handler, scanner->device, (int *) &scsi_bufsize) != 0) { DBG(DBG_error, "ERROR: sane_start: open failed\n"); scanner->scanning = SANE_FALSE; return SANE_STATUS_INVAL; } if (scsi_bufsize < scanner->device->scsi_buffer_size_min) /* minimum size must be available */ { DBG(DBG_error, "ERROR: sane_start: umax_scsi_open_extended returned too small scsi buffer\n"); umax_scsi_close((scanner->device)); scanner->scanning = SANE_FALSE; return SANE_STATUS_NO_MEM; } DBG(DBG_info, "sane_start: umax_scsi_open_extended returned scsi buffer size = %d\n", scsi_bufsize); if (scsi_bufsize < scanner->device->width_in_pixels) /* print warning when buffer is smaller than one scanline */ { DBG(DBG_warning, "WARNING: sane_start: scsi buffer is smaller than one scanline\n"); } if (scsi_bufsize != scanner->device->bufsize) { DBG(DBG_info, "sane_start: buffer size has changed, reallocating buffer\n"); if (scanner->device->buffer[0]) { DBG(DBG_info, "sane_start: freeing SCSI buffer[0]\n"); free(scanner->device->buffer[0]); /* free buffer */ } scanner->device->bufsize = scsi_bufsize; DBG(DBG_info, "sane_start: allocating SCSI buffer[0]\n"); scanner->device->buffer[0] = malloc(scanner->device->bufsize); /* allocate buffer */ if (!scanner->device->buffer[0]) /* malloc failed */ { DBG(DBG_error, "ERROR: sane_start: could not allocate buffer[0]\n"); umax_scsi_close(scanner->device); scanner->device->bufsize = 0; scanner->scanning = SANE_FALSE; return SANE_STATUS_NO_MEM; } } } #else if ( umax_scsi_open(scanner->device->sane.name, scanner->device, sense_handler, scanner->device) != SANE_STATUS_GOOD ) { scanner->scanning = SANE_FALSE; DBG(DBG_error, "ERROR: sane_start: open of %s failed:\n", scanner->device->sane.name); return SANE_STATUS_INVAL; } /* there is no need to reallocate the buffer because the size is fixed */ #endif /* grab scanner */ if (umax_grab_scanner(scanner->device)) { umax_scsi_close(scanner->device); scanner->scanning = SANE_FALSE; DBG(DBG_warning,"WARNING: unable to reserve scanner: device busy\n"); return SANE_STATUS_DEVICE_BUSY; } /* halftone pattern download is not ready in this version */ #if 0 /* send halftonepattern */ if ( (strcmp(mode, HALFTONE_STR) == 0) || (strcmp(mode, COLOR_HALFTONE_STR) == 0) ) { umax_send_halftone_pattern(scanner->device, (char *) &(scanner->halftone_pattern[0]), scanner->val[OPT_HALFTONE_DIMENSION].w ); scanner->device->halftone = WD_halftone_download; } /* end of send halftonepattern */ #endif } /* ------------ end of first call -------------- */ /* send gammacurves */ if (scanner->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { if (strcmp(mode, COLOR_STR) == 0) { if (scanner->device->three_pass == 0) /* one pass color scan */ { unsigned int i, dest, color, value; char *gamma; gamma = malloc( (size_t) (3 * scanner->gamma_length * scanner->output_bytes) ); if (gamma == NULL) { DBG(DBG_warning,"WARNING: not able to allocate memory for gamma table, gamma ignored !!!\n"); } else { dest=0; for(color=1; color <= 3; color++) { for(i=0; i < scanner->gamma_length; i++) { value = scanner->gamma_table[color][i]; if (scanner->output_bytes == 2) { gamma[dest++] = scanner->gamma_table[0][value] / 256; } gamma[dest++] = (scanner->gamma_table[0][value] & 255); } } DBG(DBG_sane_info,"sending 3 * %d bytes of gamma data for RGB\n", scanner->gamma_length * scanner->output_bytes); umax_send_gamma_data(scanner->device, &gamma[0], 3); scanner->device->digital_gamma_r = scanner->device->digital_gamma_g = scanner->device->digital_gamma_b = WD_gamma_download; free(gamma); } } else /* three pass color scan */ { unsigned int i, dest, color, value; char *gamma; gamma = malloc( (size_t) (scanner->gamma_length * scanner->output_bytes) ); if (gamma == NULL) { DBG(DBG_warning,"not able to allocate memory for gamma table, gamma ignored !!!\n"); } else { dest = 0; color = scanner->device->three_pass_color; for(i = 0; i < scanner->gamma_length; i++) { value = scanner->gamma_table[color][i]; if (scanner->output_bytes == 2) { gamma[dest++] = scanner->gamma_table[0][value] / 256; } gamma[dest++] = (scanner->gamma_table[0][value] & 255); } DBG(DBG_sane_info,"sending %d bytes of gamma data for color %d\n", scanner->gamma_length * scanner->output_bytes, color); umax_send_gamma_data(scanner->device, &gamma[0], 1); scanner->device->digital_gamma_r = scanner->device->digital_gamma_g = scanner->device->digital_gamma_b = WD_gamma_download; free(gamma); } } } else if (strcmp(mode, GRAY_STR) == 0) /* grayscale scan */ { unsigned int i, dest; char *gamma; gamma = malloc( (size_t) (scanner->gamma_length * scanner->output_bytes) ); if (gamma == NULL) { DBG(DBG_warning,"WARNING: not able to allocate memory for gamma table, gamma ignored !!!\n"); } else { dest=0; for(i=0; i < scanner->gamma_length; i++) { if (scanner->output_bytes == 2) { gamma[dest++] = scanner->gamma_table[0][i] / 256; } gamma[dest++] = (scanner->gamma_table[0][i] & 255); } DBG(DBG_sane_info,"sending %d bytes of gamma data for gray\n", scanner->gamma_length * scanner->output_bytes); umax_send_gamma_data(scanner->device, &gamma[0], 1); scanner->device->digital_gamma_r = WD_gamma_download; free(gamma); } } } /* end of send gammacurves */ if ( scanner->device->three_pass_color > WD_wid_red) /* three pass scan, not first pass */ { umax_reposition_scanner(scanner->device); } umax_set_window_param(scanner->device); status = umax_start_scan(scanner->device); if (status) /* errror */ { umax_give_scanner(scanner->device); /* reposition and release scanner */ return status; } pause = scanner->device->pause_for_color_calibration; if (scanner->device->colormode != RGB) { pause = scanner->device->pause_for_gray_calibration; } if (pause) /* Astra 2400S needs this pause (7sec in color, 4sec in gray mode) */ { DBG(DBG_info2,"pause for calibration %d msec ...\n", pause); usleep(((long) pause) * 1000); /* time in ms */ DBG(DBG_info2,"pause done\n"); } status = umax_do_calibration(scanner->device); if (status) /* errror */ { umax_give_scanner(scanner->device); /* reposition and release scanner */ return status; } if (scanner->device->pause_after_calibration) /* may be usefull */ { DBG(DBG_info2,"pause after calibration %d msec ...\n", scanner->device->pause_after_calibration); usleep(((long) scanner->device->pause_after_calibration) * 1000); /* time in ms */ DBG(DBG_info2,"pause done\n"); } if (pipe(fds) < 0) { DBG(DBG_error,"ERROR: could not create pipe\n"); scanner->scanning = SANE_FALSE; umax_give_scanner(scanner->device); /* reposition and release scanner */ umax_scsi_close(scanner->device); return SANE_STATUS_IO_ERROR; } scanner->pipe_read_fd = fds[0]; scanner->pipe_write_fd = fds[1]; /* start reader_process, deponds on OS if fork() or threads are used */ scanner->reader_pid = sanei_thread_begin(reader_process, (void *) scanner); if (!sanei_thread_is_valid (scanner->reader_pid)) { DBG(DBG_error, "ERROR: sanei_thread_begin failed (%s)\n", strerror(errno)); scanner->scanning = SANE_FALSE; umax_give_scanner(scanner->device); /* reposition and release scanner */ umax_scsi_close(scanner->device); return SANE_STATUS_NO_MEM; /* any other reason than no memory possible ? */ } if (sanei_thread_is_forked()) { close(scanner->pipe_write_fd); scanner->pipe_write_fd = -1; } return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ SANE READ ---------------------------------- */ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { Umax_Scanner *scanner = handle; ssize_t nread; *len = 0; nread = read(scanner->pipe_read_fd, buf, max_len); DBG(DBG_sane_info, "sane_read: read %ld bytes\n", (long) nread); if (!(scanner->scanning)) /* OOPS, not scanning */ { return do_cancel(scanner); } if (nread < 0) { if (errno == EAGAIN) { DBG(DBG_sane_info, "sane_read: EAGAIN\n"); return SANE_STATUS_GOOD; } else { do_cancel(scanner); /* we had an error, stop scanner */ return SANE_STATUS_IO_ERROR; } } *len = nread; if (nread == 0) /* EOF */ { if ( (scanner->device->three_pass == 0) || (scanner->device->colormode <= RGB_LINEART) || (++(scanner->device->three_pass_color) > 3) ) { do_cancel(scanner); } DBG(DBG_sane_proc,"closing read end of pipe\n"); if (scanner->pipe_read_fd >= 0) { close(scanner->pipe_read_fd); scanner->pipe_read_fd = -1; } return SANE_STATUS_EOF; } return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ SANE CANCEL -------------------------------- */ void sane_cancel(SANE_Handle handle) { Umax_Scanner *scanner = handle; DBG(DBG_sane_init,"sane_cancel\n"); if (scanner->scanning) { do_cancel(scanner); } } /* ------------------------------------------------------------ SANE SET IO MODE --------------------------- */ SANE_Status sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking) { Umax_Scanner *scanner = handle; DBG(DBG_sane_init,"sane_set_io_mode: non_blocking=%d\n", non_blocking); if (!scanner->scanning) { return SANE_STATUS_INVAL; } if (fcntl(scanner->pipe_read_fd, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ SANE GET SELECT FD ------------------------- */ SANE_Status sane_get_select_fd(SANE_Handle handle, SANE_Int *fd) { Umax_Scanner *scanner = handle; DBG(DBG_sane_init,"sane_get_select_fd\n"); if (!scanner->scanning) { return SANE_STATUS_INVAL; } *fd = scanner->pipe_read_fd; return SANE_STATUS_GOOD; } /* ------------------------------------------------------------ EOF ---------------------------------------- */ sane-backends-1.0.27/backend/cardscan.c0000664000175000017500000013371512775312260014552 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package, and implements a SANE backend for various Corex Cardscan scanners. Copyright (C) 2007-2015 m. allan noah -------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. -------------------------------------------------------------------------- The source code is divided in sections which you can easily find by searching for the tag "@@". Section 1 - Init & static stuff Section 2 - sane_init, _get_devices, _open & friends Section 3 - sane_*_option functions Section 4 - sane_start, _get_param, _read & friends Section 5 - sane_close functions Section 6 - misc functions Changes: v0, 2007-05-09, MAN (SANE v1.0.19) - initial release v1, 2008-02-14, MAN - sanei_config_read has already cleaned string (#310597) v2, 2010-02-10, MAN - add lines_per_block config option - add has_cal_buffer config option - basic support for 600c - clean #include lines v3, 2015-11-04, MAN - add USB IDs for newer model 800c ################################################## DATA FROM TRACE OF WINDOWS DRIVER: cmd packet format: cmdcode cmdlenlow cmdlenhigh cmdpayloadbytes resp packet format: respcode paperfound resplenlow resplenhigh respayloadbytes ############ status read loop? ################## >> 01 01 00 00 << 81 00 07 00 00 09 0c 61 c2 7a 0a >> 34 00 00 << b4 00 00 00 >> 01 01 00 00 << 81 00 07 00 00 09 0c 61 c2 7a 0a >> 34 00 00 << b4 00 00 00 >> 01 01 00 00 << 81 00 07 00 00 09 0c 61 c2 7a 0a ############# scanner settings read? (0x04b8 is scan width) ############# >> 48 00 00 << c8 00 0c 00 b8 04 60 00 00 80 00 00 00 58 ca 7d ############## color and gray calibration data read ############ >> 45 00 00 << 0x2600 bytes, bbbBBBgggGGGrrrRRRxxxXXX ############ 34/b4 and 01/81 status loop til paper inserted ############## >> 35 01 00 00 << b5 01 01 00 00 always together? { >> 14 05 00 80 1b 28 00 0f << 94 01 05 00 80 1b 28 00 0f >> 22 01 00 00 << a2 01 01 00 00 } >> 1a 01 00 66 << 9a 01 01 00 66 >> 19 03 00 51 62 49 << 99 01 03 00 51 62 49 ############# heat up lamp? ################# ===========color=================== three times { >> 18 07 00 00 01 60 00 61 00 07 << 0x40 read and 0x03 read the 3 byte drops from f4 f4 f4 to 17 10 08 etc. } ===========gray=================== three times { >> 12 06 00 00 01 60 00 61 00 << 0x40 read and 0x01 read } the 1 byte drops from f4 to 02 ================================== >> 35 01 00 00 << b5 01 01 00 00 >> 13 01 00 28 << 93 01 01 00 28 ===========color=================== three times { >> 18 07 00 01 10 60 00 18 05 07 << 0xe2c0 read } 14/94 and 22/a2 many times { >> 18 07 00 01 10 60 00 18 05 07 << 0xe2c0 read } ===========gray=================== two times { >> 12 06 00 01 10 60 00 18 05 << 0x4bc0 read } 14/94 and 22/a2 many times { >> 12 06 00 01 10 60 00 18 05 << 0x4bc0 read } ================================== >> 35 01 00 ff << b5 00 01 00 ff 14/94 and 22/a2 ########### discarge capacitor? ########### four times { >> 21 02 00 0a 00 << a1 00 02 00 0a 00 } >> 01 01 00 00 << 81 00 07 00 00 09 0c 61 c2 7a 0a >> 35 01 00 ff << b5 00 01 00 ff >> 34 00 00 << b4 00 00 00 ############################################# SANE FLOW DIAGRAM - sane_init() : initialize backend . - sane_get_devices() : query list of scanner devices . - sane_open() : open a particular scanner device . . - sane_set_io_mode : set blocking mode . . - sane_get_select_fd : get scanner fd . . . . - sane_get_option_descriptor() : get option information . . - sane_control_option() : change option values . . - sane_get_parameters() : returns estimated scan parameters . . - (repeat previous 3 functions) . . . . - sane_start() : start image acquisition . . - sane_get_parameters() : returns actual scan parameters . . - sane_read() : read image data (from pipe) . . (sane_read called multiple times; after sane_read returns EOF, . . loop may continue with sane_start which may return a 2nd page . . when doing duplex scans, or load the next page from the ADF) . . . . - sane_cancel() : cancel operation . - sane_close() : close opened scanner device - sane_exit() : terminate use of backend */ /* * @@ Section 1 - Init */ #include "../include/sane/config.h" #include /*memcpy...*/ #include /*isspace*/ #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "cardscan.h" #define DEBUG 1 #define BUILD 3 /* values for SANE_DEBUG_CARDSCAN env var: - errors 5 - function trace 10 - function detail 15 - get/setopt cmds 20 - usb cmd trace 25 - usb cmd detail 30 - useless noise 35 */ int global_has_cal_buffer = 1; int global_lines_per_block = 16; /* ------------------------------------------------------------------------- */ #define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY #define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR /* * used by attach* and sane_get_devices * a ptr to a null term array of ptrs to SANE_Device structs * a ptr to a single-linked list of scanner structs */ static const SANE_Device **sane_devArray = NULL; static struct scanner *scanner_devList = NULL; /* * @@ Section 2 - SANE & scanner init code */ /* * Called by SANE initially. * * From the SANE spec: * This function must be called before any other SANE function can be * called. The behavior of a SANE backend is undefined if this * function is not called first. The version code of the backend is * returned in the value pointed to by version_code. If that pointer * is NULL, no version code is returned. Argument authorize is either * a pointer to a function that is invoked when the backend requires * authentication for a specific resource or NULL if the frontend does * not support authentication. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { authorize = authorize; /* get rid of compiler warning */ DBG_INIT (); DBG (10, "sane_init: start\n"); sanei_usb_init(); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (5, "sane_init: cardscan backend %d.%d.%d, from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); DBG (10, "sane_init: finish\n"); return SANE_STATUS_GOOD; } /* * Called by SANE to find out about supported devices. * * From the SANE spec: * This function can be used to query the list of devices that are * available. If the function executes successfully, it stores a * pointer to a NULL terminated array of pointers to SANE_Device * structures in *device_list. The returned list is guaranteed to * remain unchanged and valid until (a) another call to this function * is performed or (b) a call to sane_exit() is performed. This * function can be called repeatedly to detect when new devices become * available. If argument local_only is true, only local devices are * returned (devices directly attached to the machine that SANE is * running on). If it is false, the device list includes all remote * devices that are accessible to the SANE library. * * SANE does not require that this function is called before a * sane_open() call is performed. A device name may be specified * explicitly by a user which would make it unnecessary and * undesirable to call this function first. * * Read the config file, find scanners with help from sanei_* * store in global device structs */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { struct scanner *dev; char line[PATH_MAX]; const char *lp; FILE *fp; int num_devices=0; int i=0; local_only = local_only; /* get rid of compiler warning */ DBG (10, "sane_get_devices: start\n"); global_has_cal_buffer = 1; global_lines_per_block = 16; fp = sanei_config_open (CONFIG_FILE); if (fp) { DBG (15, "sane_get_devices: reading config file %s\n", CONFIG_FILE); while (sanei_config_read (line, PATH_MAX, fp)) { lp = line; /* ignore comments */ if (*lp == '#') continue; /* skip empty lines */ if (*lp == 0) continue; if ((strncmp ("usb", lp, 3) == 0) && isspace (lp[3])) { DBG (15, "sane_get_devices: looking for '%s'\n", lp); sanei_usb_attach_matching_devices(lp, attach_one); } else if (!strncmp(lp, "has_cal_buffer", 14) && isspace (lp[14])) { int buf; lp += 14; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); if(buf){ global_has_cal_buffer = 1; } else{ global_has_cal_buffer = 0; } DBG (15, "sane_get_devices: setting \"has_cal_buffer\" to %d\n", global_has_cal_buffer); } else if (!strncmp(lp, "lines_per_block", 15) && isspace (lp[15])) { int buf; lp += 15; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); if(buf < 1 || buf > 32){ DBG (15, "sane_get_devices: \"lines_per_block\"=%d\n out of range", buf ); continue; } DBG (15, "sane_get_devices: \"lines_per_block\" is %d\n", buf); global_lines_per_block = buf; } else{ DBG (5, "sane_get_devices: config line \"%s\" ignored.\n", lp); } } fclose (fp); } else { DBG (5, "sane_get_devices: no config file '%s', using defaults\n", CONFIG_FILE); DBG (15, "sane_get_devices: looking for 'usb 0x08F0 0x0005'\n"); sanei_usb_attach_matching_devices("usb 0x08F0 0x0005", attach_one); } for (dev = scanner_devList; dev; dev=dev->next) { DBG (15, "sane_get_devices: found scanner %s\n",dev->device_name); num_devices++; } DBG (15, "sane_get_devices: found %d scanner(s)\n",num_devices); sane_devArray = calloc (num_devices + 1, sizeof (SANE_Device*)); if (!sane_devArray) return SANE_STATUS_NO_MEM; for (dev = scanner_devList; dev; dev=dev->next) { sane_devArray[i++] = (SANE_Device *)&dev->sane; } sane_devArray[i] = 0; *device_list = sane_devArray; DBG (10, "sane_get_devices: finish\n"); return SANE_STATUS_GOOD; } /* callback used by sane_get_devices * build the scanner struct and link to global list * unless struct is already loaded, then pretend */ static SANE_Status attach_one (const char *device_name) { struct scanner *s; int ret, i; SANE_Word vid, pid; DBG (10, "attach_one: start '%s'\n", device_name); for (s = scanner_devList; s; s = s->next) { if (strcmp (s->sane.name, device_name) == 0) { DBG (10, "attach_one: already attached!\n"); return SANE_STATUS_GOOD; } } /* build a scanner struct to hold it */ DBG (15, "attach_one: init struct\n"); if ((s = calloc (sizeof (*s), 1)) == NULL) return SANE_STATUS_NO_MEM; /* copy the device name */ s->device_name = strdup (device_name); if (!s->device_name){ free (s); return SANE_STATUS_NO_MEM; } /* connect the fd */ DBG (15, "attach_one: connect fd\n"); s->fd = -1; ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ free (s->device_name); free (s); return ret; } /* clean up the scanner struct based on model */ /* this is the only piece of model specific code */ sanei_usb_get_vendor_product(s->fd,&vid,&pid); if(vid == 0x08f0){ s->vendor_name = "CardScan"; if(pid == 0x0005){ s->product_name = "800c"; } else if(pid == 0x0002){ s->product_name = "600c"; } else{ DBG (5, "Unknown product, using default settings\n"); s->product_name = "Unknown"; } } else if(vid == 0x0451){ s->vendor_name = "Sanford"; if(pid == 0x6250){ s->product_name = "800c"; } else{ DBG (5, "Unknown product, using default settings\n"); s->product_name = "Unknown"; } } else{ DBG (5, "Unknown vendor/product, using default settings\n"); s->vendor_name = "Unknown"; s->product_name = "Unknown"; } DBG (15, "attach_one: Found %s scanner %s at %s\n", s->vendor_name, s->product_name, s->device_name); /*copy config file settings*/ s->has_cal_buffer = global_has_cal_buffer; s->lines_per_block = global_lines_per_block; s->color_block_size = s->lines_per_block * PIXELS_PER_LINE * 3; s->gray_block_size = s->lines_per_block * PIXELS_PER_LINE; /* try to get calibration */ if(s->has_cal_buffer){ DBG (15, "attach_one: scanner calibration\n"); ret = load_calibration(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot calibrate, incompatible?\n"); free (s->device_name); free (s); return ret; } } else{ DBG (15, "attach_one: skipping calibration\n"); } /* set SANE option 'values' to good defaults */ DBG (15, "attach_one: init options\n"); /* go ahead and setup the first opt, because * frontend may call control_option on it * before calling get_option_descriptor */ memset (s->opt, 0, sizeof (s->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].name = "filler"; s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_INACTIVE; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; DBG (15, "attach_one: init settings\n"); /* we close the connection, so that another backend can talk to scanner */ disconnect_fd(s); /* load info into sane_device struct */ s->sane.name = s->device_name; s->sane.vendor = s->vendor_name; s->sane.model = s->product_name; s->sane.type = "scanner"; s->next = scanner_devList; scanner_devList = s; DBG (10, "attach_one: finish\n"); return SANE_STATUS_GOOD; } /* * connect the fd in the scanner struct */ static SANE_Status connect_fd (struct scanner *s) { SANE_Status ret; DBG (10, "connect_fd: start\n"); if(s->fd > -1){ DBG (5, "connect_fd: already open\n"); ret = SANE_STATUS_GOOD; } else { DBG (15, "connect_fd: opening USB device\n"); ret = sanei_usb_open (s->device_name, &(s->fd)); } if(ret != SANE_STATUS_GOOD){ DBG (5, "connect_fd: could not open device: %d\n", ret); } DBG (10, "connect_fd: finish\n"); return ret; } static SANE_Status load_calibration(struct scanner *s) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[] = {0x45, 0x00, 0x00}; unsigned char * buf; size_t bytes = HEADER_SIZE + CAL_COLOR_SIZE*2 + CAL_GRAY_SIZE*2; int j; DBG (10, "load_calibration: start\n"); buf = malloc(bytes); if(!buf){ DBG(5, "load_calibration: not enough mem for buffer: %ld\n",(long)bytes); return SANE_STATUS_NO_MEM; } ret = do_cmd( s, 0, cmd, sizeof(cmd), NULL, 0, buf, &bytes ); if (ret == SANE_STATUS_GOOD) { DBG(15, "load_calibration: got GOOD\n"); /* * color cal data comes from scaner like: * bbbbbbbBBBBBBBgggggggGGGGGGGrrrrrrrRRRRRRR * where b=darkblue, B=lightblue, etc * reorder the data into two buffers * bbbbbbbgggggggrrrrrrr and BBBBBBBGGGGGGGRRRRRRR */ /*dark/light blue*/ memcpy(s->cal_color_b, buf+HEADER_SIZE, PIXELS_PER_LINE); memcpy(s->cal_color_w, buf+HEADER_SIZE+PIXELS_PER_LINE, PIXELS_PER_LINE); /*dark/light green*/ memcpy(s->cal_color_b+PIXELS_PER_LINE, buf+HEADER_SIZE+(PIXELS_PER_LINE*2), PIXELS_PER_LINE); memcpy(s->cal_color_w+PIXELS_PER_LINE, buf+HEADER_SIZE+(PIXELS_PER_LINE*3), PIXELS_PER_LINE); /*dark/light red*/ memcpy(s->cal_color_b+(PIXELS_PER_LINE*2), buf+HEADER_SIZE+(PIXELS_PER_LINE*4), PIXELS_PER_LINE); memcpy(s->cal_color_w+(PIXELS_PER_LINE*2), buf+HEADER_SIZE+(PIXELS_PER_LINE*5), PIXELS_PER_LINE); /* then slide the light data down using the dark offset */ for(j=0;jcal_color_w[j] -= s->cal_color_b[j]; } /*dark/light gray*/ memcpy(s->cal_gray_b, buf+HEADER_SIZE+(CAL_COLOR_SIZE*2), PIXELS_PER_LINE); memcpy(s->cal_gray_w, buf+HEADER_SIZE+(CAL_COLOR_SIZE*2)+PIXELS_PER_LINE, PIXELS_PER_LINE); /* then slide the light data down using the dark offset */ for(j=0;jcal_gray_w[j] -= s->cal_gray_b[j]; } hexdump(35, "cal_color_b:", s->cal_color_b, CAL_COLOR_SIZE); hexdump(35, "cal_color_w:", s->cal_color_w, CAL_COLOR_SIZE); hexdump(35, "cal_gray_b:", s->cal_gray_b, CAL_GRAY_SIZE); hexdump(35, "cal_gray_w:", s->cal_gray_w, CAL_GRAY_SIZE); } else { DBG(5, "load_calibration: error reading data block status = %d\n", ret); } DBG (10, "load_calibration: finish\n"); return ret; } /* * From the SANE spec: * This function is used to establish a connection to a particular * device. The name of the device to be opened is passed in argument * name. If the call completes successfully, a handle for the device * is returned in *h. As a special case, specifying a zero-length * string as the device requests opening the first available device * (if there is such a device). */ SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle) { struct scanner *dev = NULL; struct scanner *s = NULL; SANE_Status ret; DBG (10, "sane_open: start\n"); if(name[0] == 0){ if(scanner_devList){ DBG (15, "sane_open: no device requested, using first\n"); s = scanner_devList; } else{ DBG (15, "sane_open: no device requested, none found\n"); } } else{ DBG (15, "sane_open: device %s requested, attaching\n", name); ret = attach_one(name); if(ret){ DBG (5, "sane_open: attach error %d\n",ret); return ret; } for (dev = scanner_devList; dev; dev = dev->next) { if (strcmp (dev->sane.name, name) == 0) { s = dev; break; } } } if (!s) { DBG (5, "sane_open: no device found\n"); return SANE_STATUS_INVAL; } DBG (15, "sane_open: device %s found\n", s->sane.name); *handle = s; /* connect the fd so we can talk to scanner */ ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ return ret; } DBG (10, "sane_open: finish\n"); return SANE_STATUS_GOOD; } /* * @@ Section 3 - SANE Options functions */ /* * Returns the options we know. * * From the SANE spec: * This function is used to access option descriptors. The function * returns the option descriptor for option number n of the device * represented by handle h. Option number 0 is guaranteed to be a * valid option. Its value is an integer that specifies the number of * options that are available for device handle h (the count includes * option 0). If n is not a valid option index, the function returns * NULL. The returned option descriptor is guaranteed to remain valid * (and at the returned address) until the device is closed. */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct scanner *s = handle; int i; SANE_Option_Descriptor *opt = &s->opt[option]; DBG (20, "sane_get_option_descriptor: %d\n", option); if ((unsigned) option >= NUM_OPTIONS) return NULL; /* "Mode" group -------------------------------------------------------- */ if(option==OPT_MODE_GROUP){ opt->title = "Scan Mode"; opt->desc = ""; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* scan mode */ else if(option==OPT_MODE){ i=0; s->mode_list[i++]=STRING_GRAYSCALE; s->mode_list[i++]=STRING_COLOR; s->mode_list[i]=NULL; opt->name = SANE_NAME_SCAN_MODE; opt->title = SANE_TITLE_SCAN_MODE; opt->desc = SANE_DESC_SCAN_MODE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->mode_list; opt->size = maxStringSize (opt->constraint.string_list); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } return opt; } /** * Gets or sets an option value. * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which * the option is controlled is specified by parameter action. The * possible values of this parameter are described in more detail * below. The value of the option is passed through argument val. It * is a pointer to the memory that holds the option value. The memory * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon * encountering the first NUL terminator in the string. If argument i * is not NULL, the value of *i will be set to provide details on how * well the request has been met. */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { struct scanner *s = (struct scanner *) handle; SANE_Int dummy = 0; /* Make sure that all those statements involving *info cannot break (better * than having to do "if (info) ..." everywhere!) */ if (info == 0) info = &dummy; if (option >= NUM_OPTIONS) { DBG (5, "sane_control_option: %d too big\n", option); return SANE_STATUS_INVAL; } if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) { DBG (5, "sane_control_option: %d inactive\n", option); return SANE_STATUS_INVAL; } /* * SANE_ACTION_GET_VALUE: We have to find out the current setting and * return it in a human-readable form (often, text). */ if (action == SANE_ACTION_GET_VALUE) { SANE_Word * val_p = (SANE_Word *) val; DBG (20, "sane_control_option: get value for '%s' (%d)\n", s->opt[option].name,option); switch (option) { case OPT_NUM_OPTS: *val_p = NUM_OPTIONS; return SANE_STATUS_GOOD; case OPT_MODE: if(s->mode == MODE_GRAYSCALE){ strcpy (val, STRING_GRAYSCALE); } else if(s->mode == MODE_COLOR){ strcpy (val, STRING_COLOR); } return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { int tmp; SANE_Status status; DBG (20, "sane_control_option: set value for '%s' (%d)\n", s->opt[option].name,option); if ( s->started ) { DBG (5, "sane_control_option: cant set, device busy\n"); return SANE_STATUS_DEVICE_BUSY; } if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) { DBG (5, "sane_control_option: not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (5, "sane_control_option: bad value\n"); return status; } /* * Note - for those options which can assume one of a list of * valid values, we can safely assume that they will have * exactly one of those values because that's what * sanei_constrain_value does. Hence no "else: invalid" branches * below. */ switch (option) { /* Mode Group */ case OPT_MODE: if (!strcmp (val, STRING_GRAYSCALE)) { tmp = MODE_GRAYSCALE; } else{ tmp = MODE_COLOR; } if (tmp == s->mode) return SANE_STATUS_GOOD; s->mode = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; } /* switch */ } /* else */ return SANE_STATUS_INVAL; } /* * @@ Section 4 - SANE scanning functions */ /* * Called by SANE to retrieve information about the type of data * that the current scan will return. * * From the SANE spec: * This function is used to obtain the current scan parameters. The * returned parameters are guaranteed to be accurate between the time * a scan has been started (sane_start() has been called) and the * completion of that request. Outside of that window, the returned * values are best-effort estimates of what the parameters will be * when sane_start() gets invoked. * * Calling this function before a scan has actually started allows, * for example, to get an estimate of how big the scanned image will * be. The parameters passed to this function are the handle h of the * device for which the parameters should be obtained and a pointer p * to a parameter structure. */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { struct scanner *s = (struct scanner *) handle; DBG (10, "sane_get_parameters: start\n"); params->pixels_per_line = PIXELS_PER_LINE; params->lines = -1; params->last_frame = 1; if (s->mode == MODE_COLOR) { params->format = SANE_FRAME_RGB; params->depth = 8; params->bytes_per_line = params->pixels_per_line * 3; } else if (s->mode == MODE_GRAYSCALE) { params->format = SANE_FRAME_GRAY; params->depth = 8; params->bytes_per_line = params->pixels_per_line; } DBG (15, "\tdepth %d\n", params->depth); DBG (15, "\tlines %d\n", params->lines); DBG (15, "\tpixels_per_line %d\n", params->pixels_per_line); DBG (15, "\tbytes_per_line %d\n", params->bytes_per_line); DBG (10, "sane_get_parameters: finish\n"); return SANE_STATUS_GOOD; } /* * Called by SANE when a page acquisition operation is to be started. */ SANE_Status sane_start (SANE_Handle handle) { struct scanner *s = handle; SANE_Status ret; DBG (10, "sane_start: start\n"); /* first page of batch */ if(s->started){ DBG(5,"sane_start: previous transfer not finished?"); sane_cancel((SANE_Handle)s); return SANE_STATUS_CANCELLED; } /* set clean defaults */ s->started=1; s->bytes_rx=0; s->bytes_tx=0; s->paperless_lines=0; /* heat up the lamp */ if(s->mode == MODE_COLOR){ ret = heat_lamp_color(s); } else{ ret = heat_lamp_gray(s); } if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to heat lamp\n"); sane_cancel((SANE_Handle)s); return ret; } DBG (10, "sane_start: finish\n"); return SANE_STATUS_GOOD; } static SANE_Status heat_lamp_gray(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; SANE_Status ret2 = SANE_STATUS_GOOD; unsigned char cmd[] = {0x12, 0x06, 0x00, 0x00, 0x01, 0x60, 0x00, 0x61, 0x00}; size_t bytes = HEADER_SIZE + 1; unsigned char * buf; int i; DBG (10, "heat_lamp_gray: start\n"); buf = malloc(bytes); if(!buf){ DBG(5, "heat_lamp_gray: not enough mem for buffer: %lu\n", (long unsigned)bytes); return SANE_STATUS_NO_MEM; } for(i=0;i<10;i++){ ret2 = do_cmd( s, 0, cmd, sizeof(cmd), NULL, 0, buf, &bytes ); if (ret2 != SANE_STATUS_GOOD) { DBG(5, "heat_lamp_gray: %d error\n",i); ret = ret2; break; } if(!buf[1]){ DBG(5, "heat_lamp_gray: %d got no docs\n",i); ret = SANE_STATUS_NO_DOCS; break; } DBG(15, "heat_lamp_gray: %d got: %d %d\n",i, buf[HEADER_SIZE],s->cal_gray_b[0]); if(buf[HEADER_SIZE] < 0x20){ DBG(15, "heat_lamp_gray: hot\n"); ret = SANE_STATUS_GOOD; break; } else{ DBG(15, "heat_lamp_gray: cold\n"); ret = SANE_STATUS_DEVICE_BUSY; } } free(buf); DBG (10, "heat_lamp_gray: finish %d\n",ret); return ret; } static SANE_Status heat_lamp_color(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; SANE_Status ret2 = SANE_STATUS_GOOD; unsigned char cmd[] = {0x18, 0x07, 0x00, 0x00, 0x01, 0x60, 0x00, 0x61, 0x00, 0x07}; size_t bytes = HEADER_SIZE + 3; unsigned char * buf; int i; DBG (10, "heat_lamp_color: start\n"); buf = malloc(bytes); if(!buf){ DBG(5, "heat_lamp_color: not enough mem for buffer: %lu\n", (long unsigned)bytes); return SANE_STATUS_NO_MEM; } for(i=0;i<10;i++){ ret2 = do_cmd( s, 0, cmd, sizeof(cmd), NULL, 0, buf, &bytes ); if (ret2 != SANE_STATUS_GOOD) { DBG(5, "heat_lamp_color: %d error\n",i); ret = ret2; break; } if(!buf[1]){ DBG(5, "heat_lamp_color: %d got no docs\n",i); ret = SANE_STATUS_NO_DOCS; break; } DBG(15, "heat_lamp_color: %d got: %d,%d,%d %d,%d,%d\n",i, buf[HEADER_SIZE],buf[HEADER_SIZE+1],buf[HEADER_SIZE+2], s->cal_color_b[0],s->cal_color_b[1],s->cal_color_b[2]); if(buf[HEADER_SIZE] < 0x20 && buf[HEADER_SIZE+1] < 0x20 && buf[HEADER_SIZE+2] < 0x20){ DBG(15, "heat_lamp_color: hot\n"); ret = SANE_STATUS_GOOD; break; } else{ DBG(15, "heat_lamp_color: cold\n"); ret = SANE_STATUS_DEVICE_BUSY; } } free(buf); DBG (10, "heat_lamp_color: finish %d\n",ret); return ret; } /* * Called by SANE to read data. * * From the SANE spec: * This function is used to read image data from the device * represented by handle h. Argument buf is a pointer to a memory * area that is at least maxlen bytes long. The number of bytes * returned is stored in *len. A backend must set this to zero when * the call fails (i.e., when a status other than SANE_STATUS_GOOD is * returned). * * When the call succeeds, the number of bytes returned can be * anywhere in the range from 0 to maxlen bytes. */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct scanner *s = (struct scanner *) handle; SANE_Status ret=SANE_STATUS_GOOD; DBG (10, "sane_read: start\n"); *len = 0; /* cancelled? */ if(!s->started){ DBG (5, "sane_read: call sane_start first\n"); return SANE_STATUS_CANCELLED; } /* have sent all of current buffer */ if(s->bytes_tx == s->bytes_rx){ /* at end of data, stop */ if(s->paperless_lines >= MAX_PAPERLESS_LINES){ DBG (15, "sane_read: returning eof\n"); power_down(s); return SANE_STATUS_EOF; } /* more to get, reset and go */ s->bytes_tx = 0; s->bytes_rx = 0; if(s->mode == MODE_COLOR){ ret = read_from_scanner_color(s); } else{ ret = read_from_scanner_gray(s); } if(ret){ DBG(5,"sane_read: returning %d\n",ret); return ret; } } /* data in current buffer, send some of it */ *len = s->bytes_rx - s->bytes_tx; if(*len > max_len){ *len = max_len; } memcpy(buf,s->buffer+s->bytes_tx,*len); s->bytes_tx += *len; DBG (10, "sane_read: %d,%d,%d finish\n", *len,s->bytes_rx,s->bytes_tx); return ret; } static SANE_Status read_from_scanner_gray(struct scanner *s) { SANE_Status ret=SANE_STATUS_GOOD; /*cmd len-le16 move lines ??? ??? ??? ???*/ unsigned char cmd[] = {0x12, 0x06, 0x00, 0x01, 0x01, 0x60, 0x00, 0x18, 0x05}; size_t bytes = HEADER_SIZE + s->gray_block_size; unsigned char * buf; int i,j; DBG (10, "read_from_scanner_gray: start\n"); cmd[4] = s->lines_per_block; buf = malloc(bytes); if(!buf){ DBG(5, "read_from_scanner_gray: not enough mem for buffer: %lu\n", (long unsigned)bytes); return SANE_STATUS_NO_MEM; } ret = do_cmd( s, 0, cmd, sizeof(cmd), NULL, 0, buf, &bytes ); if (ret == SANE_STATUS_GOOD) { DBG(15, "read_from_scanner_gray: got GOOD\n"); if(!buf[1]){ s->paperless_lines += s->lines_per_block; } s->bytes_rx = s->gray_block_size; /*memcpy(s->buffer,buf+HEADER_SIZE,s->gray_block_size);*/ /* reorder the gray data into the struct's buffer */ for(i=0;igray_block_size;i+=PIXELS_PER_LINE){ for(j=0;jcal_gray_b[j]; unsigned char wcal = s->cal_gray_w[j]; byte = (byte <= bcal)?0:(byte-bcal); byte = (byte >= wcal)?255:(byte*255/wcal); s->buffer[i+j] = byte; } } } else { DBG(5, "read_from_scanner_gray: error reading status = %d\n", ret); } free(buf); DBG (10, "read_from_scanner_gray: finish\n"); return ret; } static SANE_Status read_from_scanner_color(struct scanner *s) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[] = {0x18, 0x07, 0x00, 0x01, 0x01, 0x60, 0x00, 0x18, 0x05, 0x07}; size_t bytes = HEADER_SIZE + s->color_block_size; unsigned char * buf; int i,j,k; DBG (10, "read_from_scanner_color: start\n"); cmd[4] = s->lines_per_block; buf = malloc(bytes); if(!buf){ DBG(5, "read_from_scanner_color: not enough mem for buffer: %lu\n", (long unsigned)bytes); return SANE_STATUS_NO_MEM; } ret = do_cmd( s, 0, cmd, sizeof(cmd), NULL, 0, buf, &bytes ); if (ret == SANE_STATUS_GOOD) { DBG(15, "read_from_scanner_color: got GOOD\n"); if(!buf[1]){ s->paperless_lines += s->lines_per_block; } s->bytes_rx = s->color_block_size; /*memcpy(s->buffer,buf+HEADER_SIZE,s->color_block_size);*/ /* reorder the color data into the struct's buffer */ for(i=0;icolor_block_size;i+=PIXELS_PER_LINE*3){ for(j=0;jcal_color_b[offset]; unsigned char wcal = s->cal_color_w[offset]; byte = (byte <= bcal)?0:(byte-bcal); byte = (byte >= wcal)?255:(byte*255/wcal); s->buffer[i+j*3+k] = byte; } } } } else { DBG(5, "read_from_scanner_color: error reading status = %d\n", ret); } free(buf); DBG (10, "read_from_scanner_color: finish\n"); return ret; } /* * @@ Section 4 - SANE cleanup functions */ /* * Cancels a scan. * * From the SANE spec: * This function is used to immediately or as quickly as possible * cancel the currently pending operation of the device represented by * handle h. This function can be called at any time (as long as * handle h is a valid handle) but usually affects long-running * operations only (such as image is acquisition). It is safe to call * this function asynchronously (e.g., from within a signal handler). * It is important to note that completion of this operaton does not * imply that the currently pending operation has been cancelled. It * only guarantees that cancellation has been initiated. Cancellation * completes only when the cancelled call returns (typically with a * status value of SANE_STATUS_CANCELLED). Since the SANE API does * not require any other operations to be re-entrant, this implies * that a frontend must not call any other operation until the * cancelled operation has returned. */ void sane_cancel (SANE_Handle handle) { struct scanner * s = (struct scanner *) handle; DBG (10, "sane_cancel: start\n"); s->started = 0; DBG (10, "sane_cancel: finish\n"); } static SANE_Status power_down(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[] = {0x21, 0x02, 0x00, 0x0a, 0x00}; unsigned char buf[6]; size_t bytes = sizeof(buf); int i; DBG (10, "power_down: start\n"); for(i=0;i<5;i++){ ret = do_cmd( s, 0, cmd, sizeof(cmd), NULL, 0, buf, &bytes ); if(ret != SANE_STATUS_GOOD){ break; } } #if 0 unsigned char cmd[] = {0x35, 0x01, 0x00, 0xff}; unsigned char buf[5]; size_t bytes = sizeof(buf); DBG (10, "power_down: start\n"); ret = do_cmd( s, 0, cmd, sizeof(cmd), NULL, 0, buf, &bytes ); #endif DBG (10, "power_down: finish %d\n",ret); return ret; } /* * Ends use of the scanner. * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is * presently active, a call to sane_cancel() is performed first. After * this function returns, handle h must not be used anymore. */ void sane_close (SANE_Handle handle) { DBG (10, "sane_close: start\n"); sane_cancel(handle); disconnect_fd((struct scanner *) handle); DBG (10, "sane_close: finish\n"); } static SANE_Status disconnect_fd (struct scanner *s) { DBG (10, "disconnect_fd: start\n"); if(s->fd > -1){ DBG (15, "disconnecting usb device\n"); sanei_usb_close (s->fd); s->fd = -1; } DBG (10, "disconnect_fd: finish\n"); return SANE_STATUS_GOOD; } /* * Terminates the backend. * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be * open (it is recommended to close device handles explicitly through * a call to sane_close(), but backends are required to release all * resources upon a call to this function). After this function * returns, no function other than sane_init() may be called * (regardless of the status value returned by sane_exit(). Neglecting * to call this function may result in some resources not being * released properly. */ void sane_exit (void) { struct scanner *dev, *next; DBG (10, "sane_exit: start\n"); for (dev = scanner_devList; dev; dev = next) { disconnect_fd(dev); next = dev->next; free (dev->device_name); free (dev); } if (sane_devArray) free (sane_devArray); scanner_devList = NULL; sane_devArray = NULL; DBG (10, "sane_exit: finish\n"); } /* * @@ Section 5 - misc helper functions */ /* * take a bunch of pointers, send commands to scanner */ static SANE_Status do_cmd(struct scanner *s, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { /* sanei_usb overwrites the transfer size, so make some local copies */ size_t loc_cmdLen = cmdLen; size_t loc_outLen = outLen; size_t loc_inLen = *inLen; int cmdTime = USB_COMMAND_TIME; int outTime = USB_DATA_TIME; int inTime = USB_DATA_TIME; int ret = 0; DBG (10, "do_cmd: start\n"); if(shortTime){ cmdTime /= 20; outTime /= 20; inTime /= 20; } /* change timeout */ sanei_usb_set_timeout(cmdTime); /* write the command out */ DBG(25, "cmd: writing %ld bytes, timeout %d\n", (long)cmdLen, cmdTime); hexdump(30, "cmd: >>", cmdBuff, cmdLen); ret = sanei_usb_write_bulk(s->fd, cmdBuff, &cmdLen); DBG(25, "cmd: wrote %ld bytes, retVal %d\n", (long)cmdLen, ret); if(ret == SANE_STATUS_EOF){ DBG(5,"cmd: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"cmd: return error '%s'\n",sane_strstatus(ret)); return ret; } if(loc_cmdLen != cmdLen){ DBG(5,"cmd: wrong size %ld/%ld\n", (long)loc_cmdLen, (long)cmdLen); return SANE_STATUS_IO_ERROR; } /* this command has a write component, and a place to get it */ if(outBuff && outLen && outTime){ /* change timeout */ sanei_usb_set_timeout(outTime); DBG(25, "out: writing %ld bytes, timeout %d\n", (long)outLen, outTime); hexdump(30, "out: >>", outBuff, outLen); ret = sanei_usb_write_bulk(s->fd, outBuff, &outLen); DBG(25, "out: wrote %ld bytes, retVal %d\n", (long)outLen, ret); if(ret == SANE_STATUS_EOF){ DBG(5,"out: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"out: return error '%s'\n",sane_strstatus(ret)); return ret; } if(loc_outLen != outLen){ DBG(5,"out: wrong size %ld/%ld\n", (long)loc_outLen, (long)outLen); return SANE_STATUS_IO_ERROR; } } /* this command has a read component, and a place to put it */ if(inBuff && inLen && inTime){ memset(inBuff,0,*inLen); /* change timeout */ sanei_usb_set_timeout(inTime); DBG(25, "in: reading %ld bytes, timeout %d\n", (long)*inLen, inTime); ret = sanei_usb_read_bulk(s->fd, inBuff, inLen); DBG(25, "in: retVal %d\n", ret); if(ret == SANE_STATUS_EOF){ DBG(5,"in: got EOF, continuing\n"); } else if(ret != SANE_STATUS_GOOD){ DBG(5,"in: return error '%s'\n",sane_strstatus(ret)); return ret; } DBG(25, "in: read %ld bytes\n", (long)*inLen); if(*inLen){ hexdump(30, "in: <<", inBuff, *inLen); } if(loc_inLen != *inLen){ ret = SANE_STATUS_EOF; DBG(5,"in: short read %ld/%ld\n", (long)loc_inLen, (long)*inLen); } } DBG (10, "do_cmd: finish\n"); return ret; } /** * Convenience method to determine longest string size in a list. */ static size_t maxStringSize (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /** * Prints a hex dump of the given buffer onto the debug output stream. */ static void hexdump (int level, char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; if(DBG_LEVEL < level) return; DBG (level, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { *ptr = '\0'; DBG (level, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3x:", i); ptr += 4; } sprintf (ptr, " %2.2x", *p); ptr += 3; } *ptr = '\0'; DBG (level, "%s\n", line); } /** * An advanced method we don't support but have to define. */ SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) { DBG (10, "sane_set_io_mode\n"); DBG (15, "%d %p\n", non_blocking, h); return SANE_STATUS_UNSUPPORTED; } /** * An advanced method we don't support but have to define. */ SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) { DBG (10, "sane_get_select_fd\n"); DBG (15, "%p %d\n", h, *fdp); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/gt68xx_shm_channel.c0000664000175000017500000005005512112021330016452 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file * @brief Shared memory channel implementation. */ #include "gt68xx_shm_channel.h" #include #include #include #include #include #include #ifndef SHM_R #define SHM_R 0 #endif #ifndef SHM_W #define SHM_W 0 #endif /** Shared memory channel. * */ struct Shm_Channel { SANE_Int buf_size; /**< Size of each buffer */ SANE_Int buf_count; /**< Number of buffers */ void *shm_area; /**< Address of shared memory area */ SANE_Byte **buffers; /**< Array of pointers to buffers */ SANE_Int *buffer_bytes; /**< Array of buffer byte counts */ int writer_put_pipe[2]; /**< Notification pipe from writer */ int reader_put_pipe[2]; /**< Notification pipe from reader */ }; /** Dummy union to find out the needed alignment */ union Shm_Channel_Align { int i; long l; void *ptr; void (*func_ptr) (void); double d; }; /** Check if shm_channel is valid */ #define SHM_CHANNEL_CHECK(shm_channel, func_name) \ do { \ if ((shm_channel) == NULL) \ { \ DBG (3, "%s: BUG: shm_channel==NULL\n", (func_name)); \ return SANE_STATUS_INVAL; \ } \ } while (SANE_FALSE) /** Alignment for shared memory contents */ #define SHM_CHANNEL_ALIGNMENT (sizeof (union Shm_Channel_Align)) /** Align the given size up to a multiple of the given alignment */ #define SHM_CHANNEL_ROUND_UP(size, align) \ ( ((size) % (align)) ? ((size)/(align) + 1)*(align) : (size) ) /** Align the size using SHM_CHANNEL_ALIGNMENT */ #define SHM_CHANNEL_ALIGN(size) \ SHM_CHANNEL_ROUND_UP((size_t) (size), SHM_CHANNEL_ALIGNMENT) /** Close a file descriptor if it is currently open. * * This function checks if the file descriptor is not -1, and sets it to -1 * after close (so that it will not be closed twice). * * @param fd_var Pointer to a variable holding the file descriptor. */ static void shm_channel_fd_safe_close (int *fd_var) { if (*fd_var != -1) { close (*fd_var); *fd_var = -1; } } static SANE_Status shm_channel_fd_set_close_on_exec (int fd) { long value; value = fcntl (fd, F_GETFD, 0L); if (value == -1) return SANE_STATUS_IO_ERROR; if (fcntl (fd, F_SETFD, value | FD_CLOEXEC) == -1) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } #if 0 static SANE_Status shm_channel_fd_set_non_blocking (int fd, SANE_Bool non_blocking) { long value; value = fcntl (fd, F_GETFL, 0L); if (value == -1) return SANE_STATUS_IO_ERROR; if (non_blocking) value |= O_NONBLOCK; else value &= ~O_NONBLOCK; if (fcntl (fd, F_SETFL, value) == -1) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } #endif /** Create a new shared memory channel. * * This function should be called before the fork to set up the shared memory. * * @param buf_size Size of each shared memory buffer in bytes. * @param buf_count Number of shared memory buffers (up to 255). * @param shm_channel_return Returned shared memory channel object. */ SANE_Status shm_channel_new (SANE_Int buf_size, SANE_Int buf_count, Shm_Channel ** shm_channel_return) { Shm_Channel *shm_channel; void *shm_area; SANE_Byte *shm_data; int shm_buffer_bytes_size, shm_buffer_size; int shm_size; int shm_id; int i; if (buf_size <= 0) { DBG (3, "shm_channel_new: invalid buf_size=%d\n", buf_size); return SANE_STATUS_INVAL; } if (buf_count <= 0 || buf_count > 255) { DBG (3, "shm_channel_new: invalid buf_count=%d\n", buf_count); return SANE_STATUS_INVAL; } if (!shm_channel_return) { DBG (3, "shm_channel_new: BUG: shm_channel_return==NULL\n"); return SANE_STATUS_INVAL; } *shm_channel_return = NULL; shm_channel = (Shm_Channel *) malloc (sizeof (Shm_Channel)); if (!shm_channel) { DBG (3, "shm_channel_new: no memory for Shm_Channel\n"); return SANE_STATUS_NO_MEM; } shm_channel->buf_size = buf_size; shm_channel->buf_count = buf_count; shm_channel->shm_area = NULL; shm_channel->buffers = NULL; shm_channel->buffer_bytes = NULL; shm_channel->writer_put_pipe[0] = shm_channel->writer_put_pipe[1] = -1; shm_channel->reader_put_pipe[0] = shm_channel->reader_put_pipe[1] = -1; shm_channel->buffers = (SANE_Byte **) malloc (sizeof (SANE_Byte *) * buf_count); if (!shm_channel->buffers) { DBG (3, "shm_channel_new: no memory for buffer pointers\n"); shm_channel_free (shm_channel); return SANE_STATUS_NO_MEM; } if (pipe (shm_channel->writer_put_pipe) == -1) { DBG (3, "shm_channel_new: cannot create writer put pipe: %s\n", strerror (errno)); shm_channel_free (shm_channel); return SANE_STATUS_NO_MEM; } if (pipe (shm_channel->reader_put_pipe) == -1) { DBG (3, "shm_channel_new: cannot create reader put pipe: %s\n", strerror (errno)); shm_channel_free (shm_channel); return SANE_STATUS_NO_MEM; } shm_channel_fd_set_close_on_exec (shm_channel->reader_put_pipe[0]); shm_channel_fd_set_close_on_exec (shm_channel->reader_put_pipe[1]); shm_channel_fd_set_close_on_exec (shm_channel->writer_put_pipe[0]); shm_channel_fd_set_close_on_exec (shm_channel->writer_put_pipe[1]); shm_buffer_bytes_size = SHM_CHANNEL_ALIGN (sizeof (SANE_Int) * buf_count); shm_buffer_size = SHM_CHANNEL_ALIGN (buf_size); shm_size = shm_buffer_bytes_size + buf_count * shm_buffer_size; shm_id = shmget (IPC_PRIVATE, shm_size, IPC_CREAT | SHM_R | SHM_W); if (shm_id == -1) { DBG (3, "shm_channel_new: cannot create shared memory segment: %s\n", strerror (errno)); shm_channel_free (shm_channel); return SANE_STATUS_NO_MEM; } shm_area = shmat (shm_id, NULL, 0); if (shm_area == (void *) -1) { DBG (3, "shm_channel_new: cannot attach to shared memory segment: %s\n", strerror (errno)); shmctl (shm_id, IPC_RMID, NULL); shm_channel_free (shm_channel); return SANE_STATUS_NO_MEM; } if (shmctl (shm_id, IPC_RMID, NULL) == -1) { DBG (3, "shm_channel_new: cannot remove shared memory segment id: %s\n", strerror (errno)); shmdt (shm_area); shmctl (shm_id, IPC_RMID, NULL); shm_channel_free (shm_channel); return SANE_STATUS_NO_MEM; } shm_channel->shm_area = shm_area; shm_channel->buffer_bytes = (SANE_Int *) shm_area; shm_data = ((SANE_Byte *) shm_area) + shm_buffer_bytes_size; for (i = 0; i < shm_channel->buf_count; ++i) { shm_channel->buffers[i] = shm_data; shm_data += shm_buffer_size; } *shm_channel_return = shm_channel; return SANE_STATUS_GOOD; } /** Close the shared memory channel and release associated resources. * * @param shm_channel Shared memory channel object. */ SANE_Status shm_channel_free (Shm_Channel * shm_channel) { SHM_CHANNEL_CHECK (shm_channel, "shm_channel_free"); if (shm_channel->shm_area) { shmdt (shm_channel->shm_area); shm_channel->shm_area = NULL; } if (shm_channel->buffers) { free (shm_channel->buffers); shm_channel->buffers = NULL; } shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[0]); shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]); shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[0]); shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]); return SANE_STATUS_GOOD; } /** Initialize the shared memory channel in the writer process. * * This function should be called after the fork in the process which will * write data to the channel. * * @param shm_channel Shared memory channel object. */ SANE_Status shm_channel_writer_init (Shm_Channel * shm_channel) { SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_init"); shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[0]); shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]); return SANE_STATUS_GOOD; } /** Get a free shared memory buffer for writing. * * This function may block waiting for a free buffer (if the reader process * does not process the data fast enough). * * After successfull call to this function the writer process should fill the * buffer with the data and pass the buffer identifier from @a buffer_id_return * to shm_channel_writer_put_buffer() to give the buffer to the reader process. * * @param shm_channel Shared memory channel object. * @param buffer_id_return Returned buffer identifier. * @param buffer_addr_return Returned buffer address. * * @return * - SANE_STATUS_GOOD - a free buffer was available (or became available after * waiting for it); @a buffer_id_return and @a buffer_addr_return are filled * with valid values. * - SANE_STATUS_EOF - the reader process has closed its half of the channel. * - SANE_STATUS_IO_ERROR - an I/O error occured. */ SANE_Status shm_channel_writer_get_buffer (Shm_Channel * shm_channel, SANE_Int * buffer_id_return, SANE_Byte ** buffer_addr_return) { SANE_Byte buf_index; int bytes_read; SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_get_buffer"); do bytes_read = read (shm_channel->reader_put_pipe[0], &buf_index, 1); while (bytes_read == -1 && errno == EINTR); if (bytes_read == 1) { SANE_Int index = buf_index; if (index < shm_channel->buf_count) { *buffer_id_return = index; *buffer_addr_return = shm_channel->buffers[index]; return SANE_STATUS_GOOD; } } *buffer_id_return = -1; *buffer_addr_return = NULL; if (bytes_read == 0) return SANE_STATUS_EOF; else return SANE_STATUS_IO_ERROR; } /** Pass a filled shared memory buffer to the reader process. * * @param shm_channel Shared memory channel object. * @param buffer_id Buffer identifier from shm_channel_writer_put_buffer(). * @param buffer_bytes Number of data bytes in the buffer. * * @return * - SANE_STATUS_GOOD - the buffer was successfully queued. * - SANE_STATUS_IO_ERROR - the reader process has closed its half of the * channel, or another I/O error occured. */ SANE_Status shm_channel_writer_put_buffer (Shm_Channel * shm_channel, SANE_Int buffer_id, SANE_Int buffer_bytes) { SANE_Byte buf_index; int bytes_written; SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_put_buffer"); if (buffer_id < 0 || buffer_id >= shm_channel->buf_count) { DBG (3, "shm_channel_writer_put_buffer: BUG: buffer_id=%d\n", buffer_id); return SANE_STATUS_INVAL; } shm_channel->buffer_bytes[buffer_id] = buffer_bytes; buf_index = (SANE_Byte) buffer_id; do bytes_written = write (shm_channel->writer_put_pipe[1], &buf_index, 1); while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR)); if (bytes_written == 1) return SANE_STATUS_GOOD; else return SANE_STATUS_IO_ERROR; } /** Close the writing half of the shared memory channel. * * @param shm_channel Shared memory channel object. */ SANE_Status shm_channel_writer_close (Shm_Channel * shm_channel) { SHM_CHANNEL_CHECK (shm_channel, "shm_channel_writer_close"); shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]); return SANE_STATUS_GOOD; } /** Initialize the shared memory channel in the reader process. * * This function should be called after the fork in the process which will * read data from the channel. * * @param shm_channel Shared memory channel object. */ SANE_Status shm_channel_reader_init (Shm_Channel * shm_channel) { SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_init"); shm_channel_fd_safe_close (&shm_channel->writer_put_pipe[1]); /* Don't close reader_put_pipe[0] here. Otherwise, if the channel writer * process dies early, this process might get SIGPIPE - and I don't want to * mess with signals in the main process. */ /* shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[0]); */ return SANE_STATUS_GOOD; } #if 0 /** Set non-blocking or blocking mode for the reading half of the shared memory * channel. * * @param shm_channel Shared memory channel object. * @param non_blocking SANE_TRUE to make the channel non-blocking, SANE_FALSE * to set blocking mode. * * @return * - SANE_STATUS_GOOD - the requested mode was set successfully. * - SANE_STATUS_IO_ERROR - error setting the requested mode. */ SANE_Status shm_channel_reader_set_io_mode (Shm_Channel * shm_channel, SANE_Bool non_blocking) { SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_set_io_mode"); return shm_channel_fd_set_non_blocking (shm_channel->writer_put_pipe[0], non_blocking); } /** Get the file descriptor which will signal when some data is available in * the shared memory channel. * * The returned file descriptor can be used in select() or poll(). When one of * these functions signals that the file descriptor is ready for reading, * shm_channel_reader_get_buffer() should return some data without blocking. * * @param shm_channel Shared memory channel object. * @param fd_return The returned file descriptor. * * @return * - SANE_STATUS_GOOD - the file descriptor was returned. */ SANE_Status shm_channel_reader_get_select_fd (Shm_Channel * shm_channel, SANE_Int * fd_return) { SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_get_select_fd"); *fd_return = shm_channel->writer_put_pipe[0]; return SANE_STATUS_GOOD; } #endif /** Start reading from the shared memory channel. * * A newly initialized shared memory channel is stopped - the writer process * will block on shm_channel_writer_get_buffer(). This function will pass all * available buffers to the writer process, starting the transfer through the * channel. * * @param shm_channel Shared memory channel object. */ SANE_Status shm_channel_reader_start (Shm_Channel * shm_channel) { int i, bytes_written; SANE_Byte buffer_id; SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_start"); for (i = 0; i < shm_channel->buf_count; ++i) { buffer_id = i; do bytes_written = write (shm_channel->reader_put_pipe[1], &buffer_id, 1); while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR)); if (bytes_written == -1) { DBG (3, "shm_channel_reader_start: write error at buffer %d: %s\n", i, strerror (errno)); return SANE_STATUS_IO_ERROR; } } return SANE_STATUS_GOOD; } /** Get the next shared memory buffer passed from the writer process. * * If the channel was not set to non-blocking mode, this function will block * until the data buffer arrives from the writer process. In non-blocking mode * this function will place NULL in @a *buffer_addr_return and return * SANE_STATUS_GOOD if a buffer is not available immediately. * * After successful completion of this function (return value is * SANE_STATUS_GOOD and @a *buffer_addr_return is not NULL) the reader process * should process the data in the buffer and then call * shm_channel_reader_put_buffer() to release the buffer. * * @param shm_channel Shared memory channel object. * @param buffer_id_return Returned buffer identifier. * @param buffer_addr_return Returned buffer address. * @param buffer_bytes_return Returned number of data bytes in the buffer. * * @return * - SANE_STATUS_GOOD - no error. If the channel was in non-blocking mode, @a * *buffer_id_return may be NULL, indicating that no data was available. * Otherwise, @a *buffer_id_return, @a *buffer_addr_return and @a * *buffer_bytes return are filled with valid values. * - SANE_STATUS_EOF - the writer process has closed its half of the channel. * - SANE_STATUS_IO_ERROR - an I/O error occured. */ SANE_Status shm_channel_reader_get_buffer (Shm_Channel * shm_channel, SANE_Int * buffer_id_return, SANE_Byte ** buffer_addr_return, SANE_Int * buffer_bytes_return) { SANE_Byte buf_index; int bytes_read; SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_get_buffer"); do bytes_read = read (shm_channel->writer_put_pipe[0], &buf_index, 1); while (bytes_read == -1 && errno == EINTR); if (bytes_read == 1) { SANE_Int index = buf_index; if (index < shm_channel->buf_count) { *buffer_id_return = index; *buffer_addr_return = shm_channel->buffers[index]; *buffer_bytes_return = shm_channel->buffer_bytes[index]; return SANE_STATUS_GOOD; } } *buffer_id_return = -1; *buffer_addr_return = NULL; *buffer_bytes_return = 0; if (bytes_read == 0) return SANE_STATUS_EOF; else return SANE_STATUS_IO_ERROR; } /** Release a shared memory buffer received by the reader process. * * This function must be called after shm_channel_reader_get_buffer() to * release the buffer and make it available for transferring the next portion * of data. * * After calling this function the reader process must not access the buffer * contents; any data which may be needed later should be copied into some * other place beforehand. * * @param shm_channel Shared memory channel object. * @param buffer_id Buffer identifier from shm_channel_reader_get_buffer(). * * @return * - SANE_STATUS_GOOD - the buffer was successfully released. * - SANE_STATUS_IO_ERROR - the writer process has closed its half of the * channel, or an unexpected I/O error occured. */ SANE_Status shm_channel_reader_put_buffer (Shm_Channel * shm_channel, SANE_Int buffer_id) { SANE_Byte buf_index; int bytes_written; SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_put_buffer"); if (buffer_id < 0 || buffer_id >= shm_channel->buf_count) { DBG (3, "shm_channel_reader_put_buffer: BUG: buffer_id=%d\n", buffer_id); return SANE_STATUS_INVAL; } buf_index = (SANE_Byte) buffer_id; do bytes_written = write (shm_channel->reader_put_pipe[1], &buf_index, 1); while ((bytes_written == 0) || (bytes_written == -1 && errno == EINTR)); if (bytes_written == 1) return SANE_STATUS_GOOD; else return SANE_STATUS_IO_ERROR; } #if 0 /** Close the reading half of the shared memory channel. * * @param shm_channel Shared memory channel object. */ SANE_Status shm_channel_reader_close (Shm_Channel * shm_channel) { SHM_CHANNEL_CHECK (shm_channel, "shm_channel_reader_close"); shm_channel_fd_safe_close (&shm_channel->reader_put_pipe[1]); return SANE_STATUS_GOOD; } #endif /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/umax-ug630.c0000664000175000017500000001023412112021330014552 00000000000000/* ------------------------------------------------------------------------- */ /* umax-ug630.c: inquiry for UMAX scanner ug630 (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------- */ #include "umax-scanner.h" /* ------------------------------------------------------------------------- */ static unsigned char UG630_INQUIRY[] = { #define UG630_INQUIRY_LEN 0x94 /* 24 F/W support function */ 0x00, /* 25 -27 exposure-times */ 0x00, 0x00, 0x00, /* 28 - 29 reserved */ 0x00, 0x00, /* 2a - 35 exposure times */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 37 reserved */ 0x00, 0x00, /* 38 - 5f scsi reserved */ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, /* 60 -62 scanner capability */ 0xdc, 0xbc, /* 8e ? */ 0x03, /* ? */ /* 63 reserved */ 0x00, /* 64 gamma */ 0xa1, /* 65 reserved */ 0x00, /* 66 GIB */ 0x01, /* 67 reserved */ 0x00, /* 68 GOB */ 0x01, /* 69 - 6a halftone */ 0x88, 0x21, /* ? */ /* 6b - 6c reserved */ 0x00, 0x00, /* 6d color sequence */ 0x05, /* 6e - 71 video memory */ 0x00, 0x04, 0x00, 0x00, /* 72 reserved */ 0x00, /* 73 max optical res in 100 dpi */ 0x04, /* 74 max x_res in 100 dpi */ 0x04, /* 75 max y_res in 100 dpi */ 0x04, /* 76-77 fb max scan width in 0.01 inch */ 0x03, 0x52, /* 78-79 fb max scan length in 0.01 inch */ 0x04, 0x92, /* 7a-7b uta x original point */ 0x00, 0x76, /* 7c-7d uta y original point */ 0x00, 0x89, /* 7e-7f uta max scan width in 0.01 inch */ 0x02, 0x4e, /* 80-81 uta max scan length in 0.01 inch */ 0x03, 0x65, /* 82-85 reserved */ 00, 00, 00, 00, /* 86-87 dor x original point */ 0x00, 0x00, /* 88-89 dor x original point */ 0x00, 0x00, /* 8a-8b dor max scan width in 0.01 inch */ 0x00, 0x00, /* 8c-8d dor max scan length in 0.01 inch */ 0x00, 0x00, /* 8e reserved */ 0x00, /* 8f last calibration lamp density */ 0x00, /* 90 reserved */ 0x00, /* 91 lamp warmup max time */ 0x00, /* 92-93 window descriptor block length */ 0x00, 0x30, /* 94 optical resolution residue (1dpi) */ 0x00, /* 95 x_resolution residue (1dpi) */ 0x00, /* 96 y_resolution residue (1dpi) */ 0x00, /* 97 analog gamma table */ 0x00, /* 98-99 reserved */ 0x00, 0x00, /* 9a max calibration data lines */ 0x00 }; static inquiry_blk inquiry_ug630 = { "UG630 ", UG630_INQUIRY, UG630_INQUIRY_LEN }; sane-backends-1.0.27/backend/plustek-pp_genericio.c0000664000175000017500000012526012112021330017074 00000000000000/* @file plustek-pp_genericio.c * @brief all i/o functions * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2004 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - moved ioP96ReadScannerImageData and ioP98ReadScannerImageData * into this file * - added SPP-read functions * - 0.32 - changes in function ioControlLampOnOff() * - made IOReadingImage a local function -> ioP98ReadingImage() * - rewritten function ioP96ReadScannerImageData() * - moved function IOSetStartStopRegister to p9636.c * - 0.33 - added debug messages to IOPutOnAllRegisters * - fixed a bug in ioP96InitialSetCurrentSpeed * - 0.34 - no changes * - 0.35 - no changes * - 0.36 - removed some warning conditions * - 0.37 - moved functions IOSPPWrite(), IODataToScanner(), IODataToRegister(), * IODataFromRegister() to io.c * - moved the data read functions to io.c * - renamed IOInitialize to IOFuncInitialize * - 0.38 - moved some functions to io.c * - added P12 stuff * - 0.39 - no changes * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - fixed a problem in ioP96InitialSetCurrentSpeed(), for COLOR_BW * at least, used the setting for A3I * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** local vars **************************************/ /* WORK COMMENT THIS */ typedef void (*pFnSpeed_Set)(pScanData); static ModeTypeVar a_FilmSettings[18] = { /* SppNegFilmPos */ {0xa0, 1782, 96, _QuarterStep, 0, 0}, {0xb7, 1782, 96, _QuarterStep, 0, 0}, {0xb7, 1782, 96, _QuarterStep, 0, 0}, /* BppNegFilmPos */ {0xa9, 1782, 96, _QuarterStep, 0, 0}, {0xbf, 1782, 96, _QuarterStep, 0, 0}, {0xbf, 1782, 96, _QuarterStep, 0, 0}, /* EppNegFilmPos */ {0x95, 1782, 96, _QuarterStep, 0, 0}, {0xa6, 1782, 96, _QuarterStep, 0, 0}, {0xa6, 1782, 96, _QuarterStep, 0, 0}, /* SppPosFilmPos */ {0x50, 1782, 96, _QuarterStep, 0, 0}, {0x67, 1782, 96, _QuarterStep, 0, 0}, {0x67, 1782, 96, _QuarterStep, 0, 0}, /* BppPosFilmPos */ {0x59, 1782, 96, _QuarterStep, 0, 0}, {0x6f, 1782, 96, _QuarterStep, 0, 0}, {0x6f, 1782, 96, _QuarterStep, 0, 0}, /* EppPosFilmPos */ {0x45, 1782, 96, _QuarterStep, 0, 0}, {0x56, 1782, 96, _QuarterStep, 0, 0}, {0x56, 1782, 96, _QuarterStep, 0, 0} }; static ModeTypeVar a_BwSettings[12] = { {_Home_BE75, 890, 96, _HalfStep, 2, 1}, {_Home_BE150, 1780, 88, _QuarterStep, 2, 0}, {_Home_BE300, 3542, 96, _QuarterStep, 2, 0}, {_Home_BE600, 7070, 96, _QuarterStep, 2, 0}, {_Home_BB75, 890, 96, _HalfStep, 2, 1}, {_Home_BB150, 1780, 88, _QuarterStep, 2, 0}, {_Home_BB300, 3542, 96, _QuarterStep, 2, 0}, {_Home_BB600, 7070, 96, _QuarterStep, 2, 0}, {_Home_BS75, 890, 96, _HalfStep, 2, 1}, {_Home_BS150, 1780, 88, _QuarterStep, 2, 0}, {_Home_BS300, 3542, 96, _QuarterStep, 2, 0}, {_Home_BS600, 7070, 96, _QuarterStep, 2, 0} }; static ModeTypeVar a_GraySettings[12] = { {_Home_GE75, 890, 96, _HalfStep, 2, 0}, {_Home_GE150, 1780, 88, _QuarterStep, 2, 0}, {_Home_GE300, 3542, 88, _QuarterStep, 2, 0}, {_Home_GE600, 7070, 88, _QuarterStep, 2, 0}, {_Home_GB75, 890, 96, _HalfStep, 2, 0}, {_Home_GB150, 1780, 88, _QuarterStep, 2, 0}, {_Home_GB300, 3542, 88, _QuarterStep, 2, 0}, {_Home_GB600, 7070, 88, _QuarterStep, 2, 0}, {_Home_GS75, 890, 96, _HalfStep, 2, 0}, {_Home_GS150, 1782, 96, _QuarterStep, 2, 0}, {_Home_GS300, 3549, 88, _QuarterStep, 2, 0}, {_Home_GS600, 7070, 88, _QuarterStep, 2, 0} }; static ModeTypeVar a_ColorSettings[15] = { {_Home_CE50, 720, 60, _HalfStep, 1, 1}, {_Home_CE100, 1782, 48, _QuarterStep, 1, 0}, {_Home_CE150, 1782, 88, _QuarterStep, 0, 0}, {_Home_CE300, 3549, 96, _QuarterStep, 0, 0}, {_Home_CE600, 7082, 96, _QuarterStep, 0, 0}, {_Home_CB50, 720, 120, _QuarterStep, 0, 1}, {_Home_CB100, 1782, 96, _QuarterStep, 0, 0}, {_Home_CB150, 1782, 96, _QuarterStep, 0, 0}, {_Home_CB300, 3549, 96, _QuarterStep, 0, 0}, {_Home_CB600, 7082, 96, _QuarterStep, 0, 0}, {_Home_CS50, 720, 120, _QuarterStep, 0, 1}, {_Home_CS100, 1782, 96, _QuarterStep, 0, 0}, {_Home_CS150, 1782, 96, _QuarterStep, 0, 0}, {_Home_CS300, 3549, 96, _QuarterStep, 0, 0}, {_Home_CS600, 7082, 96, _QuarterStep, 0, 0} }; static DiffModeVar a_tabDiffParam[] ={ /* BPP/EPP B/W */ {0, 1, 11}, /* Bpp/Epp B/W, Dpi <= 150 ;(0) */ {0, 1, 24}, /* Bpp/Epp B/W, Dpi <= 300 ;(1) */ {0, 1, 48}, /* Bpp/Epp B/W, Dpi > 300 ;(2) */ /* SPP B/W */ {0, 1, 11}, /* Spp B/W, Dpi <= 150 ;(3) */ {0, 1, 24}, /* Spp B/W, Dpi <= 300 ;(4) */ {0, 1, 48}, /* Spp B/W, Dpi > 300 ;(5) */ /* EPP Gray */ /* The difference for this DPI: * if pixels <= | 3000 | Others * --------------------+------+------------- * VarFullStateSpeed | 0 | 1 * VarCurrentSpeed | 1 | 2 * VarStepSpeed | 44 | 88 */ {0, 1, 12}, /* Epp Gray, Dpi <= 150 ;(6) */ {1, 2, 80}, /* Epp Gray, Dpi <= 300 ;(7) */ {0, 1, 80}, /* Epp Gray, Dpi > 300, Px <= 3000 ;(8) */ {0, 1, 80}, /* Epp Gray, Dpi > 300, Px > 3000 ;(9) */ /* BPP Gray */ {0, 1, 11}, /* Bpp Gray, Dpi <= 150 ; 10 */ /* The difference for this DPI: * if pixels <= | 1600 | Others * --------------------+------+------------- * VarFullStateSpeed | 0 | 1 * VarCurrentSpeed | 1 | 2 * VarStepSpeed | 24 | 48 */ {0, 1, 24}, /* Bpp Gray, Dpi <= 300, Px <= 1600 ; 11 */ {1, 2, 48}, /* Bpp Gray, Dpi <= 300, Px > 1600 ; 12 */ /* The difference for this DPI: * if pixels <= | 1600 | 3200 | Others * --------------------+-----+-------+---------------------- * VarFullStateSpeed | 0 | 1 | 2 * VarCurrentSpeed | 1 | 2 | 4 * VarStepSpeed | 44 | 88 | 88 */ {0, 1, 44}, /* Bpp Gray, Dpi > 300, Px <= 1600 ; 13 */ {1, 2, 88}, /* Bpp Gray, Dpi > 300, Px <= 3200 ; 14 */ {2, 4, 88}, /* Bpp Gray, Dpi > 300, Px > 3200 ; 15 */ /* SPP Gray */ /* The difference for this DPI: * if pixels <= | 800 | Others * --------------------+-----+------------- * VarFullStateSpeed | 0 | 1 * VarCurrentSpeed | 1 | 2 * VarStepSpeed | 12 | 24 */ {0, 1, 12}, /* Spp Gray, Dpi <= 150, Px <= 800 ; 16 */ {1, 2, 24}, /* Spp Gray, Dpi <= 150, Px > 800 ; 17 */ /* The difference for this DPI: * if pixels <= | 800 | 1600 | Others * --------------------+-----+-------+---------------------- * VarFullStateSpeed | 0 | 1 | 1 * VarCurrentSpeed | 1 | 2 | 4 * VarStepSpeed | 22 | 88 | 88 */ {0, 1, 22}, /* Spp Gray, Dpi <= 300, Px <= 800 ; 18 */ {1, 2, 88}, /* Spp Gray, Dpi <= 300, Px <= 1600 ; 19 */ {1, 4, 88}, /* Spp Gray, Dpi <= 300, Px > 1600 ; 20 */ /* The difference for this DPI: * if pixels <= | 800 | 1600 | 3200 | Others * --------------------+-----+------+------+--------------- * VarFullStateSpeed | 0 | 1 | 2 | 3 * VarCurrentSpeed | 1 | 2 | 4 | 6 * VarStepSpeed | 44 | 88 | 88 | 88 */ {0, 1, 44}, /* Spp Gray, Dpi > 300, Px <= 800 ; 21 */ {1, 2, 88}, /* Spp Gray, Dpi > 300, Px <= 1600 ; 22 */ {2, 4, 88}, /* Spp Gray, Dpi > 300, Px <= 3200 ; 23 */ {3, 6, 88}, /* Spp Gray, Dpi > 300, Px > 3200 ; 24 */ /* EPP Color */ {0, 1, 6}, /* Epp Color, Dpi <= 60/100 ; 25 */ {0, 1, 11}, /* Epp Color, Dpi <= 150 ; 26 */ /* The difference for this DPI: * if pixels <= | 1200 | Others * --------------------+------+------------- * VarFullStateSpeed | 0 | 1 * VarCurrentSpeed | 1 | 2 * VarStepSpeed | 24 | 48 */ {0, 1, 24}, /* Epp Color, Dpi <= 300, Px <= 1400 ; 27 */ {1, 2, 48}, /* Epp Color, Dpi <= 300, Px > 1400 ; 28 */ /* The difference for this DPI: * if pixels <= | 1400 | 2800 | 4000 | Others * --------------------+------+------+------+--------------- * VarFullStateSpeed | 0 | 1 | 2 | 3 * VarCurrentSpeed | 1 | 2 | 4 | 6 * VarStepSpeed | 48 | 96 | 88 | 88 * VarExposureTime | 96 | 96 | 88 | 88 */ {0, 1, 48}, /* Epp Color, Dpi > 300, Px <= 1400 ; 29 */ {1, 2, 96}, /* Epp Color, Dpi > 300, Px <= 2800 ; 30 */ {2, 4, 88}, /* Epp Color, Dpi > 300, Px <= 4000 ; 31 */ {4, 8, 88}, /* Epp Color, Dpi > 300, Px > 4000 ; 32 */ /* BPP Color */ {0, 1, 6}, /* Bpp/Spp Color, Dpi <= 60 ; 33 */ {0, 1, 12}, /* Bpp/Spp Color, Dpi <= 100 ; 34 */ /* if pixels <= | 800 | Others * --------------------+-----+------------- * VarFullStateSpeed | 0 | 1 * VarCurrentSpeed | 1 | 2 * VarStepSpeed | 12 | 24 */ {0, 1, 12}, /* Bpp/Spp Color, Dpi <= 150, Px <= 800 ; 35 */ {1, 2, 24}, /* Bpp/Spp Color, Dpi <= 150, Px > 800 ; 36 */ /* The difference for this DPI: * if pixels <= | 800 | 1600 | Others * --------------------+-----+-------+---------------------- * VarFullStateSpeed | 0 | 1 | 1 * VarCurrentSpeed | 1 | 2 | 4 * VarStepSpeed | 24 | 48 | 96 */ {0, 1, 24}, /* Bpp Color, Dpi <= 300, Px <= 800 ; 37 */ {1, 2, 48}, /* Bpp Color, Dpi <= 300, Px <= 1600 ; 38 */ {1, 4, 96}, /* Bpp Color, Dpi <= 300, Px > 1600 ; 39 */ /* The difference for this DPI: * if pixels <= | 800 | 1600 | 3200 | Others * --------------------+-----+------+------+--------------- * VarFullStateSpeed | 0 | 1 | 2 | 4 * VarCurrentSpeed | 1 | 2 | 4 | 8 * VarStepSpeed | 48 | 96 | 96 | 96 */ {0, 1, 48}, /* Bpp Color, Dpi > 300, Px <= 800 ; 40 */ {1, 2, 48}, /* Bpp Color, Dpi > 300, Px <= 1600 ; 41 */ {2, 4, 96}, /* Bpp Color, Dpi > 300, Px <= 3200 ; 42 */ {4, 8, 96}, /* Bpp Color, Dpi > 300, Px > 3200 ; 43 */ /* SPP Color */ /* The difference for this DPI: * if pixels <= | 500 | 1000 | 2000 | Others * --------------------+-----+------+------+--------------- * VarFullStateSpeed | 0 | 1 | 1 | 2 * VarCurrentSpeed | 1 | 2 | 4 | 8 * VarStepSpeed | 24 | 48 | 96 | 96 */ {0, 1, 24}, /* Spp Color, Dpi <= 300, Px <= 500 ; 44 */ {1, 2, 48}, /* Spp Color, Dpi <= 300, Px <= 1000 ; 45 */ {1, 4, 96}, /* Spp Color, Dpi <= 300, Px <= 2000 ; 46 */ {2, 8, 96}, /* Spp Color, Dpi <= 300, Px > 2000 ; 47 */ /* The difference for this DPI: * if pixels <= | 500 | 1000 | 2000 | 4000 | Others * --------------------+-----+------+------+------+-------- * VarFullStateSpeed | 0 | 1 | 2 | 4 | 5 * VarCurrentSpeed | 1 | 2 | 4 | 8 | 10 * VarStepSpeed | 48 | 96 | 96 | 96 | 96 */ {0, 1, 48}, /* Spp Color, Dpi > 300, Px <= 500 ; 48 */ {1, 2, 96}, /* Spp Color, Dpi > 300, Px <= 1000 ; 49 */ {2, 4, 96}, /* Spp Color, Dpi > 300, Px <= 2000 ; 50 */ {4, 8, 96}, /* Spp Color, Dpi > 300, Px <= 4000 ; 51 */ {5, 10, 96}, /* Spp Color, Dpi > 300, Px > 4000 ; 52 */ /* Negative & Transparency */ /* EPP/SPP/BPP */ /* for exposure time = 96 */ {0, 1, 12}, /* Spp/EPP Color, Dpi <= 150 ; 60 */ {0, 1, 24}, /* Spp Color, Dpi <= 300 ; 61 */ {0, 1, 48}, /* Spp Color, Dpi > 300 ; 62 */ {0, 1, 12}, /* Bpp/Epp B/W, Dpi <= 75 ; 56 */ /* for exposure time = 144 */ {0, 1, 18}, /* Spp/EPP Color, Dpi <= 150 ; 57 */ {0, 1, 36}, /* Spp Color, Dpi <= 300 ; 58 */ {0, 1, 72}, /* Spp Color, Dpi > 300 ; 59 */ /* for exposure time = 192 */ {0, 1, 24}, /* Spp/EPP Color, Dpi <= 150 ; 53 */ {0, 1, 48}, /* Spp Color, Dpi <= 300 ; 54 */ {0, 1, 96}, /* Spp Color, Dpi > 300 ; 55 */ /* for 48 bits color */ {1, 2, 12}, /* Epp Color, Dpi <= 100, Px > 1400 ; 63 */ {1, 2, 22}, /* Epp Color, Dpi <= 150, Px > 1900 ; 64 */ {2, 4, 48}, /* Epp Color, Dpi <= 300, Px > 4000 ; 65 */ {5, 10, 88},/* Epp Color, Dpi > 300, Px > 9600 ; 66 */ {3, 12, 96} /* Spp Color, Dpi <= 300, Px > 3000 ; 67 */ }; static pModeTypeVar pModeType; static pDiffModeVar pModeDiff; /* * prototypes for the speed procs (ASIC 98001), EPP, SPP and BIDI */ static void fnLineArtSpeed( pScanData ps ); static void fnGraySpeed ( pScanData ps ); static void fnColorSpeed ( pScanData ps ); static void fnSppLineArtSpeed( pScanData ps ); static void fnSppGraySpeed ( pScanData ps ); static void fnSppColorSpeed ( pScanData ps ); static void fnBppLineArtSpeed( pScanData ps ); static void fnBppGraySpeed ( pScanData ps ); static void fnBppColorSpeed ( pScanData ps ); /* * some procedures for the different modes */ static pFnSpeed_Set a_fnSpeedProcs[5] = { fnLineArtSpeed, fnGraySpeed, fnGraySpeed, fnColorSpeed, fnColorSpeed }; static pFnSpeed_Set a_fnSppSpeedProcs[5] = { fnSppLineArtSpeed, fnSppGraySpeed, fnSppGraySpeed, fnSppColorSpeed, fnSppColorSpeed }; static pFnSpeed_Set a_fnBppSpeedProcs[5] = { fnBppLineArtSpeed, fnBppGraySpeed, fnBppGraySpeed, fnBppColorSpeed, fnBppColorSpeed }; /*************************** local functions *********************************/ /*............................................................................. * */ static void ioP96InitialSetCurrentSpeed( pScanData ps ) { DBG( DBG_LOW, "ioP96InitialSetCurrentSpeed()\n" ); switch ( ps->DataInf.wPhyDataType ) { case COLOR_BW: ps->bCurrentSpeed = (ps->DataInf.dwAsicPixelsPerPlane > _BUF_SIZE_BASE_CONST * 2) ? 2 : 1; break; case COLOR_256GRAY: if ( COLOR_256GRAY == ps->DataInf.wAppDataType ) { ps->bCurrentSpeed = (Byte)(ps->a_wGrayInitTime[ps->IO.portMode] / ps->wLinesPer64kTime); if (!ps->bCurrentSpeed) ps->bCurrentSpeed = 1; if ((ps->DataInf.dwAsicPixelsPerPlane>=1500) && (ps->bCurrentSpeed==1)) ps->bCurrentSpeed = 2; if ( ps->DataInf.xyAppDpi.x > 1200) { ps->bCurrentSpeed += 2; /* 1201-2400 */ if ( ps->DataInf.xyAppDpi.x > 2400 ) ps->bCurrentSpeed += 2; /* >= 2401 */ } MotorP96AdjustCurrentSpeed( ps, ps->bCurrentSpeed ); } else { if ( _PORT_SPP != ps->IO.portMode ) { if( ps->DataInf.dwAsicPixelsPerPlane <= 1280 ) ps->bCurrentSpeed = 1; /* <= 1280 pixels */ else if( ps->DataInf.dwAsicPixelsPerPlane <= 1720 ) ps->bCurrentSpeed = 2; /* 1281-1720 */ else if( ps->DataInf.dwAsicPixelsPerPlane <= 3780 ) ps->bCurrentSpeed = 4; /* 1721-3780 */ else ps->bCurrentSpeed = 6; /* >= 3780 */ } else { if( ps->DataInf.dwAsicPixelsPerPlane <= 400 ) ps->bCurrentSpeed = 1; /* <= 400 pixels */ else if( ps->DataInf.dwAsicPixelsPerPlane <= 853 ) ps->bCurrentSpeed = 2; /* 401-853 */ else if( ps->DataInf.dwAsicPixelsPerPlane <= 1280 ) ps->bCurrentSpeed = 4; /* 854-1280 */ else if( ps->DataInf.dwAsicPixelsPerPlane <= 1728 ) ps->bCurrentSpeed = 6; /* 1281-1728 */ else if( ps->DataInf.dwAsicPixelsPerPlane <= 3780 ) ps->bCurrentSpeed = 8; /* 1729-3780 */ else ps->bCurrentSpeed = 10; /* > 3780 */ } } break; case COLOR_TRUE24: ps->bCurrentSpeed = (Byte)(ps->a_wColorInitTime[ps->IO.portMode] / ps->wLinesPer64kTime); if( 0 == ps->bCurrentSpeed ) { DBG( DBG_LOW, "Initially set to 1\n" ); ps->bCurrentSpeed = 1; } if (ps->DataInf.xyAppDpi.x > 150) { if (ps->bCurrentSpeed < 4) ps->bCurrentSpeed = 4; } else { /* // HEINER:A3I // if (ps->DataInf.xyAppDpi.x > 100) */ if (ps->DataInf.xyAppDpi.x > 75) if (ps->bCurrentSpeed < 2) ps->bCurrentSpeed = 2; } if( 1 != ps->bCurrentSpeed ) ps->bCurrentSpeed += ps->bExtraAdd; if (ps->DataInf.xyAppDpi.x > ps->PhysicalDpi) { if (ps->DataInf.xyAppDpi.x <= 600) ps->bCurrentSpeed += 2; else if (ps->DataInf.xyAppDpi.x <= 1200) ps->bCurrentSpeed += 2; else if (ps->DataInf.xyAppDpi.x <= 2400) ps->bCurrentSpeed += 2; else ps->bCurrentSpeed += 2; } MotorP96AdjustCurrentSpeed( ps, ps->bCurrentSpeed ); } DBG( DBG_LOW, "Current Speed = %u\n", ps->bCurrentSpeed ); } /*............................................................................. * */ static void fnLineArtSpeed( pScanData ps ) { pModeType = a_BwSettings + _FixParamEppBw; pModeDiff = a_tabDiffParam + _BwEpp75; if (ps->DataInf.xyAppDpi.y > 75) { pModeType++; pModeDiff = a_tabDiffParam + _BwEpp150; } if (ps->DataInf.xyAppDpi.y > 150) { if (ps->DataInf.xyAppDpi.y <= 300) { pModeType++; pModeDiff = a_tabDiffParam + _BwEpp300; } else { pModeType += 2; pModeDiff = a_tabDiffParam + _BwEpp600; } } } /*............................................................................. * */ static void fnGraySpeed( pScanData ps ) { pModeType = a_GraySettings + _FixParamEppGray; pModeDiff = a_tabDiffParam + _GrayEpp75; if (ps->DataInf.xyAppDpi.y > 75) { pModeType++; pModeDiff = a_tabDiffParam + _GrayEpp150; } if ( ps->DataInf.xyAppDpi.y > 150) { if (ps->DataInf.xyAppDpi.y <= 300) { pModeType++; pModeDiff = a_tabDiffParam + _GrayEpp300; } else { pModeType += 2; pModeDiff = a_tabDiffParam + _GrayEpp600; if (ps->DataInf.dwAsicPixelsPerPlane > 3000) pModeDiff++; } } } /*............................................................................. * */ static void fnColorSpeed( pScanData ps ) { DBG( DBG_LOW, "fnColorSpeed();\n" ); pModeType = a_ColorSettings + _FixParamEppColor; if ( ps->DataInf.xyAppDpi.y <= ps->wMinCmpDpi ) { /* DPI <= 60 */ pModeDiff = a_tabDiffParam + _ColorEpp60; } else { if (ps->DataInf.xyAppDpi.y <= 100) { pModeType++; pModeDiff = a_tabDiffParam + _ColorEpp100; if (ps->DataInf.dwAsicBytesPerPlane > 1400) pModeDiff = a_tabDiffParam + _ColorEpp100_1400; } else { if (ps->DataInf.xyAppDpi.y <= 150) { pModeType += 2; pModeDiff = a_tabDiffParam + _ColorEpp150; if (ps->DataInf.dwAsicBytesPerPlane > 1900) pModeDiff = a_tabDiffParam + _ColorEpp150_1900; } else { if (ps->DataInf.xyAppDpi.y <= 300) { pModeType += 3; pModeDiff = a_tabDiffParam + _ColorEpp300_1200; if (ps->DataInf.dwAsicBytesPerPlane <= 1200) pModeDiff --; else { if (ps->DataInf.dwAsicBytesPerPlane > 4000) pModeDiff = a_tabDiffParam + _ColorEpp300_4000; } } else { pModeType += 4; pModeDiff = a_tabDiffParam + _ColorEpp600_4000; pModeType->bExposureTime = 88; if (ps->DataInf.dwAsicBytesPerPlane <= 4000) { pModeDiff--; if (ps->DataInf.dwAsicBytesPerPlane <= 2800) { pModeType->bExposureTime = 96; pModeDiff--; if (ps->DataInf.dwAsicBytesPerPlane <= 1200) pModeDiff--; } } else { if (ps->DataInf.dwAsicBytesPerPlane >= 9600) pModeDiff = a_tabDiffParam + _ColorEpp600_9600; } } } } } } /*............................................................................. * */ static void fnSppLineArtSpeed( pScanData ps ) { pModeType = a_BwSettings + _FixParamSppBw; pModeDiff = a_tabDiffParam + _BwSpp75; if (ps->DataInf.xyAppDpi.y > 75) { pModeType++; pModeDiff = a_tabDiffParam + _BwSpp150; } if (ps->DataInf.xyAppDpi.y > 150) { if (ps->DataInf.xyAppDpi.y <= 300) { pModeType++; pModeDiff = a_tabDiffParam + _BwSpp300; } else { pModeType += 2; pModeDiff = a_tabDiffParam + _BwSpp600; } } } /*............................................................................. * */ static void fnSppGraySpeed( pScanData ps ) { pModeType = a_GraySettings + _FixParamSppGray; pModeDiff = a_tabDiffParam + _GraySpp75; if (ps->DataInf.xyAppDpi.y > 75) { pModeType++; pModeDiff = a_tabDiffParam + _GraySpp150_800; if (ps->DataInf.xyAppDpi.y > 150) { if (ps->DataInf.xyAppDpi.y <= 300) { pModeType ++; pModeDiff = a_tabDiffParam + _GraySpp300_1600; } else { pModeType += 2; pModeDiff = a_tabDiffParam + _GraySpp600_3200; if (ps->DataInf.dwAsicPixelsPerPlane <= 3200) pModeDiff--; } if (ps->DataInf.dwAsicPixelsPerPlane <= 1600) pModeDiff--; } if (ps->DataInf.dwAsicPixelsPerPlane <= 800) pModeDiff--; } } /*............................................................................. * */ static void fnSppColorSpeed( pScanData ps ) { pModeType = a_ColorSettings + _FixParamSppColor; pModeDiff = a_tabDiffParam + _ColorSpp60; if (ps->DataInf.xyAppDpi.y > ps->wMinCmpDpi) { pModeType ++; pModeDiff = a_tabDiffParam + _ColorSpp100; if (ps->DataInf.xyAppDpi.y > 100) { pModeType ++; pModeDiff = a_tabDiffParam + _ColorSpp150_800; if (ps->DataInf.xyAppDpi.y > 150) { pModeType ++; pModeDiff = a_tabDiffParam + _ColorSpp300_2000; if (ps->DataInf.xyAppDpi.y > 300) { pModeType ++; pModeDiff = a_tabDiffParam + _ColorSpp600_4000; if (ps->DataInf.dwAsicBytesPerPlane > 4000) return; else pModeDiff--; } else { if (ps->DataInf.dwAsicBytesPerPlane > 3000) pModeDiff = a_tabDiffParam + _ColorSpp300_3000; return; } if (ps->DataInf.dwAsicBytesPerPlane <= 2000) { pModeDiff--; if (ps->DataInf.dwAsicBytesPerPlane <= 1000) { pModeDiff--; if (ps->DataInf.dwAsicBytesPerPlane <= 500) pModeDiff--; } } } else { if (ps->DataInf.dwAsicBytesPerPlane <= 800) pModeDiff--; } } } } /*............................................................................. * */ static void fnBppLineArtSpeed( pScanData ps ) { pModeType = a_BwSettings + _FixParamBppBw; /* (+) Micky, 7-14-1998 * pModeDiff = a_tabDiffParam + _BwBpp150; */ pModeDiff = a_tabDiffParam + _BwBpp75; if( ps->DataInf.xyAppDpi.y > 75 ) { pModeType++; pModeDiff = a_tabDiffParam + _BwBpp150; } /* (-) Micky, 7-14-1998 */ if( ps->DataInf.xyAppDpi.y > 150 ) { if( ps->DataInf.xyAppDpi.y <= 300 ) { pModeType++; pModeDiff = a_tabDiffParam + _BwBpp300; } else { pModeType += 2; pModeDiff = a_tabDiffParam + _BwBpp600; } } } /*............................................................................. * */ static void fnBppGraySpeed( pScanData ps ) { pModeType = a_GraySettings + _FixParamBppGray; /* (+) Micky, 7-14-1998 * pModeDiff = a_tabDiffParam + _GrayBpp150; */ pModeDiff = a_tabDiffParam + _GrayBpp75; if( ps->DataInf.xyAppDpi.y > 75 ) { pModeType++; pModeDiff = a_tabDiffParam + _GrayBpp150; } /* (-) Micky, 7-14-1998 */ if( ps->DataInf.xyAppDpi.y > 150 ) { pModeType ++; pModeDiff = a_tabDiffParam + _GrayBpp300_1600; if( ps->DataInf.xyAppDpi.y > 300 ) { pModeType ++; pModeDiff = a_tabDiffParam + _GrayBpp600_3200; if( ps->DataInf.dwAsicPixelsPerPlane <= 3200 ) pModeDiff --; } if( ps->DataInf.dwAsicPixelsPerPlane <= 1600 ) pModeDiff --; } } /*............................................................................. * */ static void fnBppColorSpeed( pScanData ps ) { pModeType = a_ColorSettings + _FixParamBppColor; pModeDiff = a_tabDiffParam + _ColorBpp60; if (ps->DataInf.xyAppDpi.y > ps->wMinCmpDpi ) { pModeType ++; pModeDiff = a_tabDiffParam + _ColorBpp100; if( ps->DataInf.xyAppDpi.y > 100 ) { pModeType ++; pModeDiff = a_tabDiffParam + _ColorBpp150_800; if( ps->DataInf.xyAppDpi.y > 150 ) { pModeType ++; pModeDiff = a_tabDiffParam + _ColorBpp300_1600; if( ps->DataInf.xyAppDpi.y > 300 ) { pModeType ++; pModeDiff = a_tabDiffParam + _ColorBpp600_3200; if( ps->DataInf.dwAsicBytesPerPlane <= 3200 ) return; else pModeDiff--; } if( ps->DataInf.dwAsicBytesPerPlane <= 1600 ) pModeDiff--; } if( ps->DataInf.dwAsicBytesPerPlane <= 800 ) pModeDiff--; } } } /*............................................................................. * */ static void ioP98SppNegativeProcs( pScanData ps ) { if ( ps->DataInf.dwScanFlag & SCANDEF_Negative ) pModeType = a_FilmSettings + _FixParamSppNegative; else pModeType = a_FilmSettings + _FixParamSppPositive; pModeDiff = a_tabDiffParam + _NegativeSpp150; if (ps->DataInf.xyAppDpi.y > 150) { if (ps->DataInf.xyAppDpi.y < 300) { pModeType ++; pModeDiff ++; } else { pModeType += 2; pModeDiff += 2; } } if (ps->DataInf.dwScanFlag & SCANDEF_Negative) { if (ps->AsicReg.RD_LineControl == 144) pModeDiff += 4; else if (ps->AsicReg.RD_LineControl == 192) pModeDiff += 7; } } /*............................................................................. * */ static void ioP98EppNegativeProcs( pScanData ps ) { if (ps->DataInf.dwScanFlag & SCANDEF_Negative) pModeType = a_FilmSettings + _FixParamEppNegative; else pModeType = a_FilmSettings + _FixParamEppPositive; pModeDiff = a_tabDiffParam + _NegativeEpp150; if (ps->DataInf.xyAppDpi.y > 150) { if (ps->DataInf.xyAppDpi.y < 300) { pModeType ++; pModeDiff ++; } else { pModeType += 2; pModeDiff += 2; } } if (ps->DataInf.dwScanFlag & SCANDEF_Negative) { if (ps->AsicReg.RD_LineControl == 144) pModeDiff += 4; else if (ps->AsicReg.RD_LineControl == 192) pModeDiff += 7; } } /*............................................................................. * */ static void ioP98BppNegativeProcs( pScanData ps ) { if( ps->DataInf.dwScanFlag & SCANDEF_Negative) { pModeType = a_FilmSettings + _FixParamBppNegative; } else { pModeType = a_FilmSettings + _FixParamBppPositive; } pModeDiff = a_tabDiffParam + _NegativeBpp150; if( ps->DataInf.xyAppDpi.y > 150 ) { if( ps->DataInf.xyAppDpi.y < 300 ) { pModeType ++; pModeDiff ++; } else { pModeType += 2; pModeDiff += 2; } } if ( ps->DataInf.dwScanFlag & SCANDEF_Negative ) { if( ps->AsicReg.RD_LineControl == 144 ) { pModeDiff += 4; } else { if( ps->AsicReg.RD_LineControl == 192 ) pModeDiff += 7; } } } /*............................................................................. * */ static void ioControlLampOnOff( pScanData ps ) { Byte lampStatus; ps->fWarmupNeeded = _TRUE; if( _IS_ASIC98(ps->sCaps.AsicID)) { lampStatus = ps->AsicReg.RD_ScanControl & _SCAN_LAMPS_ON; if (ps->bLastLampStatus != lampStatus) { DBG( DBG_LOW, "Using OTHER Lamp !\n" ); ps->bLastLampStatus = lampStatus; IOCmdRegisterToScanner( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); return; } } else { lampStatus = ps->AsicReg.RD_ScanControl & _SCAN_LAMP_ON; if (ps->DataInf.dwScanFlag&(SCANDEF_Transparency + SCANDEF_Negative)) { ps->bLampOn = 0; } else { ps->bLampOn = _SCAN_LAMP_ON; } if (ps->bLastLampStatus != lampStatus) { DBG( DBG_LOW, "Using OTHER Lamp !\n" ); ps->bLastLampStatus = lampStatus; return; } } ps->fWarmupNeeded = _FALSE; DBG( DBG_LOW, "Using SAME Lamp !\n" ); } /*............................................................................. * */ static void ioP98InitialSetCurrentSpeed( pScanData ps ) { DBG( DBG_LOW, "ioP98InitialSetCurrentSpeed()\n" ); if( ps->DataInf.dwScanFlag & SCANDEF_TPA) { switch (ps->IO.portMode) { case _PORT_SPP: ioP98SppNegativeProcs( ps ); break; case _PORT_BIDI: ioP98BppNegativeProcs( ps ); break; default: ioP98EppNegativeProcs( ps ); break; } } else { switch (ps->IO.portMode) { case _PORT_SPP: a_fnSppSpeedProcs[ps->DataInf.wAppDataType](ps); break; case _PORT_BIDI: a_fnBppSpeedProcs[ps->DataInf.wAppDataType](ps); break; default: a_fnSpeedProcs[ps->DataInf.wAppDataType](ps); break; } } ps->wInitialStep = pModeType->wHomePos; ps->wMaxMoveStep = pModeType->wMaxSteps; ps->AsicReg.RD_LineControl = pModeType->bExposureTime; if (ps->DataInf.dwScanFlag & SCANDEF_Negative) ps->AsicReg.RD_LineControl = 144; #ifdef DEBUG if( pModeType->bFlagScanMode != ps->Shade.bIntermediate ) DBG( DBG_HIGH, "bSetScanModeFlag != bIntermediate\n" ); #endif ps->bHpMotor = pModeType->bMotorStep; ps->bSetScanModeFlag = pModeType->bFlagScanMode; ps->bShadingTimeFlag = pModeType->bTimesShading; ps->dwFullStateSpeed = pModeDiff->dwFullSpeed; ps->bCurrentSpeed = pModeDiff->bCurrentSpeed; ps->bStepSpeed = pModeDiff->bStepSpeed; if( ps->DataInf.xyAppDpi.y > 600 ) { if( ps->dwFullStateSpeed ) ps->dwFullStateSpeed = 0; else ps->bStepSpeed <<= 1; ps->wMaxMoveStep <<= 1; } } /************************ exported functions *********************************/ /*............................................................................. * here we do some init work */ _LOC int IOFuncInitialize( pScanData ps ) { DBG( DBG_HIGH, "IOFuncInitialize()\n" ); if( NULL == ps ) return _E_NULLPTR; ps->lpEppColorHomePos = &a_ColorSettings[0]; ps->lpEppColorExposure = &a_ColorSettings[4]; ps->lpBppColorHomePos = &a_ColorSettings[5]; ps->lpSppColorHomePos = &a_ColorSettings[10]; ps->a_tabDiffParam = a_tabDiffParam; ps->a_ColorSettings = a_ColorSettings; /* * depending on the asic, we set some functions */ if( _IS_ASIC98(ps->sCaps.AsicID)) { ps->InitialSetCurrentSpeed = ioP98InitialSetCurrentSpeed; } else if( _IS_ASIC96(ps->sCaps.AsicID)) { ps->InitialSetCurrentSpeed = ioP96InitialSetCurrentSpeed; } else { DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); return _E_NOSUPP; } return _OK; } /*............................................................................. * 1) Fill scan states to asic. * 2) Refresh the scan states if necessary * 3) Wait for motor running within half-second period. */ _LOC Byte IOSetToMotorRegister( pScanData ps ) { ps->OpenScanPath( ps ); IORegisterToScanner( ps, ps->RegInitScanState ); IODownloadScanStates( ps ); ps->CloseScanPath( ps ); if( _ASIC_IS_98001 != ps->sCaps.AsicID ) { return 0; } ps->Scan.bOldScanState = IOGetScanState( ps, _FALSE ); return ps->Scan.bOldScanState; } /*............................................................................. * 1) If scanner path is not established, connect it * 2) Read the recent state count * 3) Disconnect the path if necessary */ _LOC Byte IOGetScanState( pScanData ps, Bool fOpenned ) { Byte bScanState, bScanStateNow; if( !fOpenned && (_ASIC_IS_98003 != ps->sCaps.AsicID)) ps->OpenScanPath( ps ); bScanState = IODataFromRegister( ps, ps->RegGetScanState ); bScanStateNow = IODataFromRegister( ps, ps->RegGetScanState ); if((bScanState != bScanStateNow) || ((ps->sCaps.AsicID == _ASIC_IS_98001 && bScanState & 0x40))) { bScanState = IODataFromRegister( ps, ps->RegGetScanState); } if( !fOpenned && (_ASIC_IS_98003 != ps->sCaps.AsicID)) ps->CloseScanPath( ps ); return bScanState; } /*............................................................................. * ASIC 98003 specific function to read status 2 regiser */ _LOC Byte IOGetExtendedStatus( pScanData ps ) { Byte b; b = IODataFromRegister( ps, ps->RegStatus2 ); if( b == 0xff ) return 0; return b; } /*............................................................................. * Read the scan state. Return the count with status bit, and count. */ _LOC void IOGetCurrentStateCount( pScanData ps, pScanState pScanStep ) { pScanStep->bStatus = IOGetScanState( ps, _FALSE ); pScanStep->bStep = pScanStep->bStatus & _SCANSTATE_MASK; } /*............................................................................. * 1) If scanner connection is not established, return error * 2) If paper not ready, return error * 3) If scanning environment is not prepared, return error * 4) Setup the buffers for reassembler the CCD incoming lines. * 5) Initiate the registers of asic. * [NOTE] * This routine combines from SetupAsicDependentVariables & IsReadyForScan * routines in assembly source. */ _LOC int IOIsReadyForScan( pScanData ps ) { ULong dw; pULong pdwTable; if((_NO_BASE != ps->sCaps.wIOBase) && (ps->DataInf.dwVxdFlag & _VF_ENVIRONMENT_READY)) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { IOSelectLampSource( ps ); ioControlLampOnOff( ps ); ps->AsicReg.RD_Motor0Control = 0; /* motor off */ ps->AsicReg.RD_Motor1Control = 0; /* motor off */ ps->AsicReg.RD_ModelControl = (_ModelDpi600 + _LED_ACTIVITY + _LED_CONTROL); ps->AsicReg.RD_Origin = 0; ps->AsicReg.RD_Pixels = 5110; } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->OpenScanPath( ps ); P12SetGeneralRegister( ps ); ps->CloseScanPath( ps ); ioControlLampOnOff( ps ); } else { ioControlLampOnOff( ps ); /* SetupAsicDependentVariables */ ps->pPutBufR = ps->pGetBufR = ps->pPrescan16; /* 1st color plane */ ps->pPutBufG = ps->pGetBufG = ps->pPrescan8; /* 2nd color plane */ ps->AsicReg.RD_ScanControl = ps->bLampOn; ps->Asic96Reg.RD_MotorControl = 0; ps->AsicReg.RD_Origin = 0; ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; ps->AsicReg.RD_Pixels = 5110; /* ps->RdPix; */ IOPutOnAllRegisters( ps ); } /* * MotorInitiate */ if( _ASIC_IS_98003 != ps->sCaps.AsicID ) { for (dw = _SCANSTATE_BYTES, pdwTable = (pULong)ps->a_wMoveStepTable; dw; dw--, pdwTable++) { *pdwTable = 0x10001; } memset( ps->a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS ); } return _OK; } return _E_SEQUENCE; } /*............................................................................. * */ _LOC void IOSetXStepLineScanTime( pScanData ps, Byte b ) { ps->AsicReg.RD_LineControl = b; ps->bSpeed1 = b; ps->bSpeed2 = b >> 1; ps->bSpeed4 = b >> 2; ps->bSpeed8 = b >> 3; ps->bSpeed16 = b >> 4; ps->bSpeed32 = b >> 5; ps->bSpeed24 = b / 24; ps->bSpeed12 = b / 12; ps->bSpeed6 = b / 6; ps->bSpeed3 = b / 3; } /*............................................................................. * 1) Reset and fill all new scan states (Mode = Scan) * 2) Refresh scan state * 3) Wait for motor running within half second. */ _LOC void IOSetToMotorStepCount( pScanData ps ) { ULong dw; pUChar pb; TimerDef timer; ps->OpenScanPath( ps ); if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { IORegisterToScanner( ps, ps->RegInitScanState ); } else { ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, _ModeScan ); } IORegisterToScanner( ps, ps->RegScanStateControl ); for (dw = _SCANSTATE_BYTES, pb = ps->a_nbNewAdrPointer; dw; dw--, pb++) IODataToScanner( ps, *pb ); IORegisterToScanner( ps, ps->RegRefreshScanState ); MiscStartTimer( &timer, (_SECOND/2)); do { if (!( IOGetScanState( ps, _TRUE) & _SCANSTATE_STOP)) break; } while( !MiscCheckTimer(&timer)); /* CHECK - this line has been added by Rick ? Why ? * return (pScanData->bOldTempScanState = GetScanState (pScanData, FALSE)); */ ps->Scan.bOldScanState = IOGetScanState( ps, _TRUE ); ps->CloseScanPath( ps ); } /*............................................................................. * */ _LOC void IOSelectLampSource( pScanData ps ) { ps->AsicReg.RD_ScanControl &= (~_SCAN_LAMPS_ON); if (ps->DataInf.dwScanFlag & (SCANDEF_TPA)) { ps->AsicReg.RD_ScanControl |= _SCAN_TPALAMP_ON; } else { ps->AsicReg.RD_ScanControl |= _SCAN_NORMALLAMP_ON; } } /*............................................................................. * */ _LOC Bool IOReadOneShadingLine( pScanData ps, pUChar pBuf, ULong len ) { TimerDef timer; MiscStartTimer( &timer, _SECOND ); if( _ASIC_IS_98003 == ps->sCaps.AsicID ) ps->Scan.bFifoSelect = ps->RegGFifoOffset; do { if( IOReadFifoLength( ps ) >= ps->AsicReg.RD_Pixels ) { IOReadColorData( ps, pBuf, len ); return _TRUE; } } while( _OK == MiscCheckTimer( &timer )); return _FALSE; } /*............................................................................. * */ _LOC ULong IOReadFifoLength( pScanData ps ) { DataType Data; Data.dwValue = 0; if( _ASIC_IS_98003 != ps->sCaps.AsicID ) ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegBitDepth, _BIT0_7 ); Data.dwOverlap.w1st.b1st = IODataFromRegister( ps, ps->Scan.bFifoSelect ); IODataToRegister( ps, ps->RegBitDepth, _BIT8_15 ); Data.dwOverlap.w1st.b2nd = IODataFromRegister( ps, ps->Scan.bFifoSelect ); IODataToRegister( ps, ps->RegBitDepth, _BIT16_20 ); Data.dwOverlap.w2nd.b1st = (IODataFromRegister( ps, ps->Scan.bFifoSelect) & 0x0f); if( _ASIC_IS_98003 != ps->sCaps.AsicID ) ps->CloseScanPath( ps ); return Data.dwValue; } /*............................................................................. * 1) Initiates the scan states * 2) Write the contents to corresponding registers (from ps->RegModeControl to * ps->RegGreenGainOutDirect (P9363) or from ps->RegModeControl to * ps->RegModeControl2 (48xx) */ _LOC void IOPutOnAllRegisters( pScanData ps ) { pUChar pValue; Byte bReg; /* setup scan states */ if( _ASIC_IS_98003 == ps->sCaps.AsicID ) IODownloadScanStates( ps ); else { IOSetToMotorRegister( ps ); ps->OpenScanPath( ps ); } if( _IS_ASIC98(ps->sCaps.AsicID)) { IODataToRegister(ps, ps->RegStepControl, ps->AsicReg.RD_StepControl); IODataToRegister(ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control); if( _ASIC_IS_98003 == ps->sCaps.AsicID ) IODataToRegister(ps,ps->RegLineControl,ps->AsicReg.RD_LineControl); IODataToRegister(ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime); IODataToRegister(ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl); /* the 1st register to write */ pValue = (pUChar)&ps->AsicReg.RD_Dpi; /* 0x21 - 0x28 */ for (bReg = ps->RegDpiLow; bReg <= ps->RegThresholdHigh; bReg++, pValue++) { IODataToRegister( ps, bReg, *pValue); } IORegisterToScanner( ps, ps->RegInitDataFifo ); IORegisterToScanner( ps, ps->RegRefreshScanState ); if( _ASIC_IS_98003 == ps->sCaps.AsicID ) IODataToRegister( ps, ps->RegModeControl, _ModeScan ); else IODataToRegister( ps, ps->RegModeControl, (_ModeScan + _ModeFifoRSel)); } else { /* * the original driver uses a loop, starting at RegModeControl * 0x18 - 0x26 * as we use the Asic96Reg structure only for the differences * to the AsicReg struct, we have to write to each register by hand */ IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl ); IODataToRegister( ps, ps->RegMemAccessControl, ps->Asic96Reg.RD_MemAccessControl ); #if 0 DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegModeControl, ps->AsicReg.RD_ModeControl ); DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegLineControl, ps->AsicReg.RD_LineControl ); DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegScanControl, ps->AsicReg.RD_ScanControl ); DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegModelControl, ps->AsicReg.RD_ModelControl ); DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegMemAccessControl, ps->Asic96Reg.RD_MemAccessControl ); #endif pValue = (pUChar)&ps->AsicReg.RD_Dpi; /* 0x21 - 0x26 */ for (bReg = ps->RegDpiLow; bReg <= ps->RegWidthPixelsHigh; bReg++, pValue++) { IODataToRegister( ps, bReg, *pValue ); #if 0 DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", bReg, *pValue ); #endif } /* the rest */ IODataToRegister( ps, ps->RegThresholdControl, (Byte)ps->AsicReg.RD_ThresholdControl ); IODataToRegister( ps, ps->RegWatchDogControl, (Byte)ps->Asic96Reg.RD_WatchDogControl ); IODataToRegister( ps, ps->RegModelControl2, ps->Asic96Reg.u26.RD_ModelControl2 ); #if 0 DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegThresholdControl, ps->AsicReg.RD_ThresholdControl ); DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegWatchDogControl, ps->Asic96Reg.RD_WatchDogControl ); DBG( DBG_LOW, "[0x%02x] = 0x%02x\n", ps->RegModelControl2, ps->Asic96Reg.u26.RD_ModelControl2 ); #endif IORegisterToScanner( ps, ps->RegInitDataFifo ); } if( _ASIC_IS_98003 != ps->sCaps.AsicID ) ps->CloseScanPath( ps ); } /*............................................................................. * */ _LOC void IOReadColorData( pScanData ps, pUChar pBuf, ULong len ) { ps->AsicReg.RD_ModeControl = _ModeFifoRSel; IOReadScannerImageData( ps, pBuf, len ); ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, pBuf + len, len ); ps->AsicReg.RD_ModeControl = _ModeFifoBSel; IOReadScannerImageData( ps, pBuf + len * 2, len ); } /* END PLUSTEK-PP_GENERICIO.C ...............................................*/ sane-backends-1.0.27/backend/hpsj5s.h0000664000175000017500000000526512112021330014167 00000000000000#ifndef __HPSJ5S_MIDDLE_LEVEL_API_HEADER__ #define __HPSJ5S_MIDDLE_LEVEL_API_HEADER__ #include /*Scanner hardware registers*/ #define REGISTER_FUNCTION_CODE 0x70 /*Here goes function code */ #define REGISTER_FUNCTION_PARAMETER 0x60 /*Here goes function param */ #define ADDRESS_RESULT 0x20 /*Here we get result */ /*Scanner functions (not all - some of them I cann't identify)*/ #define FUNCTION_SETUP_HARDWARE 0xA0 /*Scanner hardware control flags:*/ /*Set this flag and non-zero speed to start rotation*/ #define FLAGS_HW_MOTOR_READY 0x1 /*Set this flag to turn on lamp*/ #define FLAGS_HW_LAMP_ON 0x2 /*Set this flag to turn indicator lamp off*/ #define FLAGS_HW_INDICATOR_OFF 0x4 /* Types: */ /*Color modes we support: 1-bit Drawing, 2-bit Halftone, 8-bit Gray Scale, 24-bt True Color*/ typedef enum { Drawing, Halftone, GrayScale, TrueColor } enumColorDepth; /*Middle-level API:*/ static int OpenScanner (const char *scanner_path); static void CloseScanner (int handle); static int DetectScanner (void); static void StandByScanner (void); static void SwitchHardwareState (SANE_Byte mask, SANE_Byte invert_mask); static int CheckPaperPresent (void); static int ReleasePaper (void); static int PaperFeed (SANE_Word wLinesToFeed); static void TransferScanParameters (enumColorDepth enColor, SANE_Word wResolution, SANE_Word wCorrectedLength); static void TurnOnPaperPulling (enumColorDepth enColor, SANE_Word wResolution); static void TurnOffPaperPulling (void); static SANE_Byte GetCalibration (void); static void CalibrateScanElements (void); /*Internal-use functions:*/ static int OutputCheck (void); static int InputCheck (void); static int CallCheck (void); static void LoadingPaletteToScanner (void); /*Low level warappers:*/ static void WriteAddress (SANE_Byte Address); static void WriteData (SANE_Byte Data); static void WriteScannerRegister (SANE_Byte Address, SANE_Byte Data); static void CallFunctionWithParameter (SANE_Byte Function, SANE_Byte Parameter); static SANE_Byte CallFunctionWithRetVal (SANE_Byte Function); static SANE_Byte ReadDataByte (void); static void ReadDataBlock (SANE_Byte * Buffer, int lenght); /*Daisy chaining API: (should be moved to ieee1284 library in future)*/ /*Deselect all devices in chain on this port.*/ static void daisy_deselect_all (struct parport *port); /*Select device with number 'daisy' in 'mode'.*/ static int daisy_select (struct parport *port, int daisy, int mode); /*Setup address for device in chain on this port*/ static int assign_addr (struct parport *port, int daisy); /* Send a daisy-chain-style CPP command packet. */ static int cpp_daisy (struct parport *port, int cmd); #endif sane-backends-1.0.27/backend/mustek_pp_drivers.h0000664000175000017500000000231212112021330016506 00000000000000 #ifndef MUSTEK_PP_DRIVERS_H #define MUSTEK_PP_DRIVERS_H #include "mustek_pp.h" #include "mustek_pp_decl.h" static Mustek_pp_Functions Mustek_pp_Drivers[] = { { "debug", "Jochen Eisinger", "0.11-devel", debug_drv_init, debug_drv_capabilities, debug_drv_open, debug_drv_setup, debug_drv_config, debug_drv_close, debug_drv_start, debug_drv_read, debug_drv_stop }, { "cis600", "Eddy De Greef", "0.13-beta", cis600_drv_init, cis_drv_capabilities, cis_drv_open, cis_drv_setup, cis_drv_config, cis_drv_close, cis_drv_start, cis_drv_read, cis_drv_stop }, { "cis1200", "Eddy De Greef", "0.13-beta", cis1200_drv_init, cis_drv_capabilities, cis_drv_open, cis_drv_setup, cis_drv_config, cis_drv_close, cis_drv_start, cis_drv_read, cis_drv_stop }, { "cis1200+", "Eddy De Greef", "0.13-beta", cis1200p_drv_init, cis_drv_capabilities, cis_drv_open, cis_drv_setup, cis_drv_config, cis_drv_close, cis_drv_start, cis_drv_read, cis_drv_stop }, { "ccd300", "Jochen Eisinger", "0.11-devel", ccd300_init, ccd300_capabilities, ccd300_open, ccd300_setup, ccd300_config, ccd300_close, ccd300_start, ccd300_read, ccd300_stop } }; #endif sane-backends-1.0.27/backend/epjitsu.conf.in0000664000175000017500000000525013073301665015556 00000000000000# For scanners connected via USB on a known device (kernel driver): #usb /dev/usb/scanner0 # For scanners connected via USB using vendor and device ids (libusb): #usb VENDORID PRODUCTID # NOTE: if you have to add your device here- please send the id and model # to the author via email, so it can be included in next version. kitno455 at # gmail dot com - with epjitsu in the subject line # These devices require a firmware file in order to function, which must be # extracted from the Fujitsu Windows driver. Presumably the Mac versions # contain the firmware as well, but the author has no access such a machine. # Firmware is installed in several different locations by the fujitsu software, # using the windows 'search' feature to look for '*.nal' is the easiest way to # find them. They should be ~65K, and have the scanner's name as part of the # file name. They are often inside a .cab file. # To extract .nal files from cabinet files on Linux, use the following steps: # (you need the "unshield" tool, which is - in Debian - in the unshield package) # # 1) Mount the ScanSnap installation DVD # (mount point e.g. /media/dvd) # # 2) Extract the .nal files c$ from the cabinet files on the DVD # using the following shell script: # # # loop over all cabinet files found on the DVD # for cab in $(find /media/dvd/ -name \*.cab); do # # search for .nal files in the cabinet files # nalinfo=$(unshield l $cab | grep '\.nal$') # # # we found something # if [ -n "$nalinfo" ]; then # #echo -e "=== $cab ===\n$nalinfo" # # # loop over all fields in $nalinfo # for nal in $nalinfo; do # # if the element of $nalinfo is a .nal file name # if echo "$nal" | grep -q '\.nal$' - 2>/dev/null; then # # extract .nal file form the cabinet file # unshield x "$cab" "${nal##*\\}" # fi # done # fi # done # Copy the file someplace sane can reach it. Then update the line below. # NOTE: the firmware line must occur BEFORE the usb line for your scanner # Fujitsu fi-60F firmware @DATADIR@/sane/epjitsu/60f_0A00.nal usb 0x04c5 0x10c7 # Fujitsu S300 firmware @DATADIR@/sane/epjitsu/300_0C00.nal usb 0x04c5 0x1156 # Fujitsu S300M firmware @DATADIR@/sane/epjitsu/300M_0C00.nal usb 0x04c5 0x117f # Fujitsu fi-65F firmware @DATADIR@/sane/epjitsu/65f_0A01.nal usb 0x04c5 0x11bd # Fujitsu S1300 firmware @DATADIR@/sane/epjitsu/1300_0C26.nal usb 0x04c5 0x11ed # Fujitsu S1100 firmware @DATADIR@/sane/epjitsu/1100_0B00.nal usb 0x04c5 0x1200 # Fujitsu S1300i firmware @DATADIR@/sane/epjitsu/1300i_0D12.nal usb 0x04c5 0x128d # Fujitsu S1100i firmware @DATADIR@/sane/epjitsu/1100i_0A00.nal usb 0x04c5 0x1447 sane-backends-1.0.27/backend/artec.conf.in0000664000175000017500000000003212112021330015137 00000000000000scsi ULTIMA /dev/scanner sane-backends-1.0.27/backend/epson2.conf.in0000664000175000017500000000057012775312261015303 00000000000000# epson2.conf # # here are some examples for how to configure the EPSON2 backend # SCSI scsi EPSON # for the GT-6500: #scsi "EPSON SC" # Parallel port #pio 0x278 #pio 0x378 #pio 0x3BC # USB usb # For libusb support for unknown scanners use the following command # usb # e.g.: # usb 0x4b8 0x110 # Network # # net 192.168.1.123 net autodiscovery sane-backends-1.0.27/backend/snapscan.c0000664000175000017500000025046212775312261014602 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997-2005, 2013 Franck Schnefra, Michel Roelofs, Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, Simon Munton, Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson, Max Ushakov, Andrew Goodbody, Oliver Schwartz and Kevin Charter This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is a component of the implementation of a backend for many of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ SANE SnapScan backend */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_thread.h" #ifndef PATH_MAX #define PATH_MAX 1024 #endif #define MINOR_VERSION 4 #define BUILD 53 #define BACKEND_NAME snapscan #include "../include/sane/sanei_backend.h" #include "../include/sane/saneopts.h" #include "snapscan.h" #define MIN(x,y) ((x)<(y) ? (x) : (y)) #define MAX(x,y) ((x)>(y) ? (x) : (y)) #define LIMIT(x,min,max) MIN(MAX(x, min), max) #ifdef INOPERATIVE #define P_200_TO_255(per) SANE_UNFIX(255.0*((per + 100)/200.0)) #endif #include "../include/sane/sanei_config.h" /* debug levels */ #define DL_INFO 10 #define DL_MINOR_INFO 15 #define DL_MAJOR_ERROR 1 #define DL_MINOR_ERROR 2 #define DL_DATA_TRACE 50 #define DL_OPTION_TRACE 70 #define DL_CALL_TRACE 30 #define DL_VERBOSE 20 #define CHECK_STATUS(s,caller,cmd) \ if ((s) != SANE_STATUS_GOOD) { DBG(DL_MAJOR_ERROR, "%s: %s command failed: %s\n", caller, (cmd), sane_strstatus(s)); return s; } /*----- internal scanner operations -----*/ /* hardware configuration byte masks */ #define HCFG_ADC 0x80 /* AD converter 1 ==> 10bit, 0 ==> 8bit */ #define HCFG_ADF 0x40 /* automatic document feeder */ #define HCFG_TPO 0x20 /* transparency option */ #define HCFG_RB 0x10 /* ring buffer */ #define HCFG_HT16 0x08 /* 16x16 halftone matrices */ #define HCFG_HT8 0x04 /* 8x8 halftone matrices */ #define HCFG_SRA 0x02 /* scanline row average (high-speed colour) */ #define HCFG_CAL_ALLOWED 0x01 /* 1 ==> calibration allowed */ #define HCFG_HT 0x0C /* support halftone matrices at all */ #define MM_PER_IN 25.4 /* # millimetres per inch */ #define IN_PER_MM 0.03937 /* # inches per millimetre */ #define GAMMA_8BIT 0 #define GAMMA_16BIT 1 #define GAMMA_12_16BIT 2 #ifndef SANE_I18N #define SANE_I18N(text) text #endif /* authorization stuff */ static SANE_Auth_Callback auth = NULL; #if UNUSED static SANE_Char username[SANE_MAX_USERNAME_LEN]; static SANE_Char password[SANE_MAX_PASSWORD_LEN]; #endif /* function prototypes */ static void gamma_n (double gamma, int brightness, int contrast, u_char *buf, int length, int gamma_mode); static void gamma_to_sane (int length, u_char *in, SANE_Int *out); static size_t max_string_size(SANE_String_Const strings[]); /* inline functions */ static inline SnapScan_Mode actual_mode (SnapScan_Scanner *pss) { if (pss->preview == SANE_TRUE) return pss->preview_mode; return pss->mode; } static inline int is_colour_mode (SnapScan_Mode m) { return (m == MD_COLOUR) || (m == MD_BILEVELCOLOUR); } static inline int calibration_line_length(SnapScan_Scanner *pss) { int pos_factor; int pixel_length; switch (pss->pdev->model) { case STYLUS_CX1500: case PRISA5000E: case PRISA5000: case PRISA5150: case PERFECTION1270: case PERFECTION1670: case PERFECTION2480: case PERFECTION3490: pos_factor = pss->actual_res / 2; pixel_length = pos_factor * 8.5; break; case SCANWIT2720S: pixel_length = 2550; break; default: pos_factor = pss->actual_res; pixel_length = pos_factor * 8.5; break; } if(is_colour_mode(actual_mode(pss))) { return 3 * pixel_length; } else { return pixel_length; } } /*----- global data structures and access utilities -----*/ /* available device list */ static SnapScan_Device *first_device = NULL; /* device list head */ static SANE_Int n_devices = 0; /* the device count */ static SANE_Char *default_firmware_filename; static SANE_Bool cancelRead; /* list returned from sane_get_devices() */ static const SANE_Device **get_devices_list = NULL; /* external routines */ #include "snapscan-scsi.c" #include "snapscan-sources.c" #include "snapscan-usb.c" #include "snapscan-options.c" /* Initialize gamma tables */ static SANE_Status alloc_gamma_tables(SnapScan_Scanner * ps) { static const char me[] = "alloc_gamma_tables"; ps->gamma_length = 1 << ps->bpp; DBG (DL_MINOR_INFO, "%s: using 4*%d bytes for gamma table\n", me, ps->gamma_length); ps->gamma_tables = (SANE_Int *) malloc(4 * ps->gamma_length * sizeof(SANE_Int)); if (!ps->gamma_tables) { return SANE_STATUS_NO_MEM; } ps->gamma_table_gs = &ps->gamma_tables[0 * ps->gamma_length]; ps->gamma_table_r = &ps->gamma_tables[1 * ps->gamma_length]; ps->gamma_table_g = &ps->gamma_tables[2 * ps->gamma_length]; ps->gamma_table_b = &ps->gamma_tables[3 * ps->gamma_length]; return SANE_STATUS_GOOD; } static SANE_Status init_gamma(SnapScan_Scanner * ps) { u_char *gamma; gamma = (u_char*) malloc(ps->gamma_length * sizeof(u_char) * 2); if (!gamma) { return SANE_STATUS_NO_MEM; } /* Default tables */ gamma_n (SANE_UNFIX(ps->gamma_gs), ps->bright, ps->contrast, gamma, ps->bpp, 1); gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_gs); gamma_n (SANE_UNFIX(ps->gamma_r), ps->bright, ps->contrast, gamma, ps->bpp, 1); gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_r); gamma_n (SANE_UNFIX(ps->gamma_g), ps->bright, ps->contrast, gamma, ps->bpp, 1); gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_g); gamma_n (SANE_UNFIX(ps->gamma_b), ps->bright, ps->contrast, gamma, ps->bpp, 1); gamma_to_sane (ps->gamma_length, gamma, ps->gamma_table_b); free (gamma); return SANE_STATUS_GOOD; } /* Max string size */ static size_t max_string_size (SANE_String_Const strings[]) { size_t size; size_t max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /* gamma table computation */ static void gamma_n (double gamma, int brightness, int contrast, u_char *buf, int bpp, int gamma_mode) { int i; double i_gamma = 1.0/gamma; int length = 1 << bpp; int max = length - 1; double mid = max / 2.0; for (i = 0; i < length; i++) { int x; double val = (i - mid) * (1.0 + contrast / 100.0) + (1.0 + brightness / 100.0) * mid; val = LIMIT(val, 0, max); switch (gamma_mode) { case GAMMA_16BIT: x = LIMIT(65535*pow ((double) val/max, i_gamma) + 0.5, 0, 65535); buf[2*i] = (u_char) x; buf[2*i + 1] = (u_char) (x >> 8); break; case GAMMA_12_16BIT: buf[2*i] = (u_char) i; buf[2*i + 1] = (u_char) (i >> 8); break; case GAMMA_8BIT: buf[i] = (u_char) LIMIT(255*pow ((double) val/max, i_gamma) + 0.5, 0, 255); break; default: break; } } } static void gamma_from_sane (int length, SANE_Int *in, u_char *out, int gamma_mode) { int i; for (i = 0; i < length; i++) if (gamma_mode != GAMMA_8BIT) { out[2*i] = (u_char) LIMIT(in[i], 0, 65535); out[2*i + 1] = (u_char) (LIMIT(in[i], 0, 65535) >> 8); } else out[i] = (u_char) LIMIT(in[i] / 256, 0, 255); } static void gamma_to_sane (int length, u_char *in, SANE_Int *out) { int i; for (i = 0; i < length; i++) out[i] = in[2*i] + 256 * in[2*i + 1]; } /* dispersed-dot dither matrices; this is discussed in Foley, Van Dam, Feiner and Hughes: Computer Graphics: principles and practice, 2nd ed. (Addison-Wesley), pp 570-571. The function mfDn computes the nth dispersed-dot dither matrix Dn given D(n/2) and n; n is presumed to be a power of 2. D8 and D16 are the matrices of interest to us, since the SnapScan supports only 8x8 and 16x16 dither matrices. */ static u_char D2[] ={0, 2, 3, 1}; static u_char D4[16], D8[64], D16[256]; static void mkDn (u_char *Dn, u_char *Dn_half, unsigned n) { unsigned int x, y; for (y = 0; y < n; y++) { for (x = 0; x < n; x++) { /* Dn(x,y) = D2(2*x/n, 2*y/n) +4*Dn_half(x%(n/2), y%(n/2)) */ Dn[y*n + x] = D2[((int)(2*y/n))*2 + (int)(2*x/n)] + 4*Dn_half[(y%(n/2))*(n/2) + x%(n/2)]; } } } static SANE_Bool device_already_in_list (SnapScan_Device *current, SANE_String_Const name) { for ( ; NULL != current; current = current->pnext) { if (0 == strcmp (name, current->dev.name)) return SANE_TRUE; } return SANE_FALSE; } static SANE_Char* get_driver_name(SnapScan_Model model_num) { SANE_Int i; for (i=0; idev.name = strdup (name); if (strcmp(vendor, "Color") == 0) { (*pd)->dev.vendor = strdup ("Acer"); } else { (*pd)->dev.vendor = strdup (vendor); } (*pd)->dev.model = strdup (model); if (model_num == SCANWIT2720S) { (*pd)->dev.type = strdup (SNAPSCAN_FS_TYPE); } else { (*pd)->dev.type = strdup (SNAPSCAN_TYPE); } (*pd)->bus = bus_type; (*pd)->model = model_num; if (!(*pd)->dev.name || !(*pd)->dev.vendor || !(*pd)->dev.model || !(*pd)->dev.type) { DBG (DL_MAJOR_ERROR, "%s: out of memory allocating device descriptor strings.\n", me); free (*pd); return SANE_STATUS_NO_MEM; } (*pd)->x_range.min = x_range_fb.min; (*pd)->x_range.quant = x_range_fb.quant; (*pd)->x_range.max = x_range_fb.max; (*pd)->y_range.min = y_range_fb.min; (*pd)->y_range.quant = y_range_fb.quant; (*pd)->y_range.max = y_range_fb.max; (*pd)->firmware_filename = NULL; (*pd)->pnext = first_device; first_device = (*pd); n_devices++; return status; } static SANE_Status add_scsi_device (SANE_String_Const full_name) { int fd; static const char me[] = "add_scsi_device"; SANE_Status status = SANE_STATUS_GOOD; SnapScan_Device *pd; SnapScan_Model model_num = UNKNOWN; SnapScan_Bus bus_type = SCSI; char vendor[8]; char model[17]; SANE_Char *name = NULL; DBG (DL_CALL_TRACE, "%s(%s)\n", me, full_name); sanei_config_get_string(full_name, &name); if (!name) { return SANE_STATUS_INVAL; } /* Avoid adding the same device more then once */ if (device_already_in_list (first_device, name)) { free(name); name = 0; return SANE_STATUS_GOOD; } vendor[0] = model[0] = '\0'; DBG (DL_VERBOSE, "%s: Detected (kind of) a SCSI device\n", me); status = sanei_scsi_open (name, &fd, sense_handler, NULL); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: error opening device %s: %s\n", me, name, sane_strstatus (status)); } else { status = snapscani_check_device(fd, bus_type, vendor, model, &model_num); sanei_scsi_close(fd); } if (status == SANE_STATUS_GOOD) { status = snapscani_init_device_structure( &pd, bus_type, name, vendor, model, model_num ); } free(name); name = 0; return status; } static SANE_Status add_usb_device (SANE_String_Const full_name) { static const char me[] = "add_usb_device"; int fd; SnapScan_Device *pd; SnapScan_Model model_num = UNKNOWN; SANE_Word vendor_id, product_id; int supported_usb_vendor = 0; char vendor[8]; char model[17]; SANE_Status status = SANE_STATUS_GOOD; SnapScan_Bus bus_type = USB; int i; SANE_Char *name = NULL; DBG (DL_CALL_TRACE, "%s(%s)\n", me, full_name); sanei_config_get_string(full_name, &name); if (!name) { return SANE_STATUS_INVAL; } /* Avoid adding the same device more then once */ if (device_already_in_list (first_device, name)) { free(name); name = 0; return SANE_STATUS_GOOD; } vendor[0] = model[0] = '\0'; DBG (DL_VERBOSE, "%s: Detected (kind of) an USB device\n", me); bus_type = USB; status = snapscani_usb_shm_init(); if (status != SANE_STATUS_GOOD) { return status; } status = snapscani_usb_open (name, &fd, sense_handler, NULL); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: error opening device %s: %s\n", me, name, sane_strstatus (status)); } else { if (sanei_usb_get_vendor_product(fd, &vendor_id, &product_id) == SANE_STATUS_GOOD) { /* check for known USB vendors to avoid hanging scanners by inquiry-command. */ DBG(DL_INFO, "%s: Checking if 0x%04x is a supported USB vendor ID\n", me, vendor_id); for (i = 0; i < known_usb_vendor_ids; i++) { if (vendor_id == usb_vendor_ids[i]) { supported_usb_vendor = 1; } } if (!supported_usb_vendor) { DBG(DL_MINOR_ERROR, "%s: USB vendor ID 0x%04x is currently NOT supported by the snapscan backend.\n", me, vendor_id); status=SANE_STATUS_INVAL; snapscani_usb_close(fd); } } } if (status == SANE_STATUS_GOOD) { status = snapscani_check_device(fd, bus_type, vendor, model, &model_num); snapscani_usb_close(fd); } /* deinit shared memory, will be initialized again in open_scanner */ snapscani_usb_shm_exit(); if (status == SANE_STATUS_GOOD) { status = snapscani_init_device_structure( &pd, bus_type, name, vendor, model, model_num ); } free(name); name = 0; return status; } /* find_device: find a device in the available list by name ARG: the device name RET: a pointer to the corresponding device record, or NULL if there is no such device */ static SnapScan_Device *find_device (SANE_String_Const name) { static char me[] = "find_device"; SnapScan_Device *psd; DBG (DL_CALL_TRACE, "%s\n", me); for (psd = first_device; psd; psd = psd->pnext) { if (strcmp (psd->dev.name, name) == 0) return psd; } return NULL; } /*----- functions in the scanner interface -----*/ SANE_Status sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) { static const char me[] = "sane_snapscan_init"; char dev_name[PATH_MAX]; size_t len; FILE *fp; SANE_Status status; DBG_INIT (); DBG (DL_CALL_TRACE, "%s\n", me); DBG (DL_VERBOSE, "%s: Snapscan backend version %d.%d.%d\n", me, SANE_CURRENT_MAJOR, MINOR_VERSION, BUILD); if (version_code != NULL) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, MINOR_VERSION, BUILD); } auth = authorize; /* Initialize data structures */ default_firmware_filename = NULL; first_device = NULL; n_devices = 0; sanei_usb_init(); sanei_thread_init(); /* build a device structure */ fp = sanei_config_open (SNAPSCAN_CONFIG_FILE); if (!fp) { /* default to DEFAULT_DEVICE instead of insisting on config file */ DBG (DL_INFO, "%s: configuration file not found, defaulting to %s.\n", me, DEFAULT_DEVICE); status = add_scsi_device (DEFAULT_DEVICE); if (status != SANE_STATUS_GOOD) { DBG (DL_MINOR_ERROR, "%s: failed to add device \"%s\"\n", me, dev_name); } } else { while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ if (dev_name[0] == '#') /* ignore line comments */ continue; if (strncasecmp(dev_name, FIRMWARE_KW, strlen(FIRMWARE_KW)) == 0) { if (!default_firmware_filename) { sanei_config_get_string(dev_name + strlen(FIRMWARE_KW), &default_firmware_filename); if (default_firmware_filename == NULL) { DBG (0, "%s: Illegal firmware entry %s.\n", me, dev_name); } } } else if (strncasecmp(dev_name, OPTIONS_KW, strlen(OPTIONS_KW)) == 0) continue; /* ignore options lines */ else if (strncmp(dev_name, "usb", 3) == 0) { sanei_usb_attach_matching_devices (dev_name, add_usb_device); } else if (strncmp(dev_name, "scsi", 4) == 0) { sanei_config_attach_matching_devices (dev_name, add_scsi_device); } else if (strstr (dev_name, "usb")) { add_usb_device(dev_name); } else { add_scsi_device(dev_name); } } fclose (fp); } /* compute the dither matrices */ mkDn (D4, D2, 4); mkDn (D8, D4, 8); mkDn (D16, D8, 16); /* scale the D8 matrix from 0..63 to 0..255 */ { u_char i; for (i = 0; i < 64; i++) D8[i] = (u_char) (4 * D8[i] + 2); } return SANE_STATUS_GOOD; } static void free_device_list(SnapScan_Device *psd) { if (psd->pnext != NULL) { free_device_list(psd->pnext); } free(psd); } void sane_exit (void) { DBG (DL_CALL_TRACE, "sane_snapscan_exit\n"); if (get_devices_list) free (get_devices_list); get_devices_list = NULL; /* just for safety, reset things to known values */ auth = NULL; if (first_device) { free_device_list(first_device); first_device = NULL; } n_devices = 0; } SANE_Status sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) { static const char *me = "sane_snapscan_get_devices"; DBG (DL_CALL_TRACE, "%s (%p, %ld)\n", me, (const void *) device_list, (long) local_only); /* Waste the last list returned from this function */ if (NULL != get_devices_list) free (get_devices_list); *device_list = (const SANE_Device **) malloc ((n_devices + 1) * sizeof (SANE_Device *)); if (*device_list) { int i; SnapScan_Device *pdev; for (i = 0, pdev = first_device; pdev; i++, pdev = pdev->pnext) (*device_list)[i] = &(pdev->dev); (*device_list)[i] = 0x0000 /*NULL */; } else { DBG (DL_MAJOR_ERROR, "%s: out of memory\n", me); return SANE_STATUS_NO_MEM; } get_devices_list = *device_list; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h) { static const char *me = "sane_snapscan_open"; SnapScan_Device *psd; SANE_Status status; DBG (DL_CALL_TRACE, "%s (%s, %p)\n", me, name, (void *) h); /* possible authorization required */ /* no device name: use first device */ if ((strlen(name) == 0) && (first_device != NULL)) { name = first_device->dev.name; } /* device exists? */ psd = find_device (name); if (!psd) { DBG (DL_MINOR_ERROR, "%s: device \"%s\" not in current device list.\n", me, name); return SANE_STATUS_INVAL; } /* create and initialize the scanner structure */ *h = (SnapScan_Scanner *) calloc (sizeof (SnapScan_Scanner), 1); if (!*h) { DBG (DL_MAJOR_ERROR, "%s: out of memory creating scanner structure.\n", me); return SANE_STATUS_NO_MEM; } { SnapScan_Scanner *pss = *(SnapScan_Scanner **) h; { pss->devname = strdup (name); if (!pss->devname) { free (*h); DBG (DL_MAJOR_ERROR, "%s: out of memory copying device name.\n", me); return SANE_STATUS_NO_MEM; } pss->pdev = psd; pss->opens = 0; pss->sense_str = NULL; pss->as_str = NULL; pss->phys_buf_sz = DEFAULT_SCANNER_BUF_SZ; if ((pss->pdev->model == PERFECTION2480) || (pss->pdev->model == PERFECTION3490)) pss->phys_buf_sz *= 2; if (psd->bus == SCSI) { pss->phys_buf_sz = sanei_scsi_max_request_size; } DBG (DL_DATA_TRACE, "%s: Allocating %lu bytes as scanner buffer.\n", me, (u_long) pss->phys_buf_sz); pss->buf = (u_char *) malloc(pss->phys_buf_sz); if (!pss->buf) { DBG (DL_MAJOR_ERROR, "%s: out of memory creating scanner buffer.\n", me); return SANE_STATUS_NO_MEM; } DBG (DL_VERBOSE, "%s: allocated scanner structure at %p\n", me, (void *) pss); } status = snapscani_usb_shm_init(); if (status != SANE_STATUS_GOOD) { return status; } status = open_scanner (pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: open_scanner failed, status: %s\n", me, sane_strstatus (status)); free (pss); return SANE_STATUS_ACCESS_DENIED; } DBG (DL_MINOR_INFO, "%s: waiting for scanner to warm up.\n", me); status = wait_scanner_ready (pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: error waiting for scanner to warm up: %s\n", me, sane_strstatus(status)); free (pss); return status; } DBG (DL_MINOR_INFO, "%s: performing scanner self test.\n", me); status = send_diagnostic (pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MINOR_INFO, "%s: send_diagnostic reports %s\n", me, sane_strstatus (status)); free (pss); return status; } DBG (DL_MINOR_INFO, "%s: self test passed.\n", me); /* option initialization depends on getting the hardware configuration byte */ status = inquiry (pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: error in inquiry command: %s\n", me, sane_strstatus (status)); free (pss); return status; } if (pss->pdev->bus == USB) { if (sanei_usb_get_vendor_product(pss->fd, &pss->usb_vendor, &pss->usb_product) != SANE_STATUS_GOOD) { pss->usb_vendor = 0; pss->usb_product = 0; } /* Download Firmware for USB scanners */ if (pss->hwst & 0x02) { char vendor[8]; char model[17]; status = download_firmware(pss); CHECK_STATUS (status, me, "download_firmware"); /* send inquiry command again, wait for scanner to initialize */ status = wait_scanner_ready(pss); CHECK_STATUS (status, me, "wait_scanner_ready after firmware upload"); status = mini_inquiry (pss->pdev->bus, pss->fd, vendor, model); CHECK_STATUS (status, me, "mini_inquiry after firmware upload"); /* The model identifier may change after firmware upload */ DBG (DL_INFO, "%s (after firmware upload): Checking if \"%s\" is a supported scanner\n", me, model); /* Check if it is one of our supported models */ pss->pdev->model = snapscani_get_model_id(model, pss->fd, pss->pdev->bus); if (pss->pdev->model == UNKNOWN) { DBG (DL_MINOR_ERROR, "%s (after firmware upload): \"%s\" is not a supported scanner\n", me, model); } /* run "real" inquiry command once again for option initialization */ status = inquiry (pss); CHECK_STATUS (status, me, "inquiry after firmware upload"); } } close_scanner(pss); status = alloc_gamma_tables (pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: error in alloc_gamma_tables: %s\n", me, sane_strstatus (status)); free (pss); return status; } init_options (pss); status = init_gamma (pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: error in init_gamma: %s\n", me, sane_strstatus (status)); free (pss); return status; } pss->state = ST_IDLE; } return SANE_STATUS_GOOD; } void sane_close (SANE_Handle h) { SnapScan_Scanner *pss = (SnapScan_Scanner *) h; DBG (DL_CALL_TRACE, "sane_snapscan_close (%p)\n", (void *) h); switch (pss->state) { case ST_SCAN_INIT: case ST_SCANNING: release_unit (pss); break; default: break; } close_scanner (pss); snapscani_usb_shm_exit(); free (pss->gamma_tables); free (pss->buf); free (pss); } SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters *p) { static const char *me = "sane_snapscan_get_parameters"; SnapScan_Scanner *pss = (SnapScan_Scanner *) h; SANE_Status status = SANE_STATUS_GOOD; SnapScan_Mode mode = actual_mode(pss); DBG (DL_CALL_TRACE, "%s (%p, %p)\n", me, (void *) h, (void *) p); p->last_frame = SANE_TRUE; /* we always do only one frame */ if ((pss->state == ST_SCAN_INIT) || (pss->state == ST_SCANNING)) { /* we are in the middle of a scan, so we can use the data that the scanner has reported */ if (pss->psrc != NULL) { DBG(DL_DATA_TRACE, "%s: Using source chain data\n", me); /* use what the source chain says */ p->pixels_per_line = pss->psrc->pixelsPerLine(pss->psrc); p->bytes_per_line = pss->psrc->bytesPerLine(pss->psrc); /* p->lines = pss->psrc->remaining(pss->psrc)/p->bytes_per_line; */ p->lines = pss->lines; } else { DBG(DL_DATA_TRACE, "%s: Using current data\n", me); /* estimate based on current data */ p->pixels_per_line = pss->pixels_per_line; p->bytes_per_line = pss->bytes_per_line; p->lines = pss->lines; if (mode == MD_BILEVELCOLOUR) p->bytes_per_line = p->pixels_per_line*3; } } else { /* no scan in progress. The scanner data may not be up to date. we have to calculate an estimate. */ double width, height; int dpi; double dots_per_mm; DBG(DL_DATA_TRACE, "%s: Using estimated data\n", me); width = SANE_UNFIX (pss->brx - pss->tlx); height = SANE_UNFIX (pss->bry - pss->tly); dpi = pss->res; dots_per_mm = dpi / MM_PER_IN; p->pixels_per_line = width * dots_per_mm; p->lines = height * dots_per_mm; switch (mode) { case MD_COLOUR: case MD_BILEVELCOLOUR: p->bytes_per_line = 3 * p->pixels_per_line * ((pss->bpp_scan+7)/8); break; case MD_LINEART: p->bytes_per_line = (p->pixels_per_line + 7) / 8; break; default: /* greyscale */ p->bytes_per_line = p->pixels_per_line * ((pss->bpp_scan+7)/8); break; } } p->format = (is_colour_mode(mode)) ? SANE_FRAME_RGB : SANE_FRAME_GRAY; if (mode == MD_LINEART) p->depth = 1; else if (pss->pdev->model == SCANWIT2720S) p->depth = 16; else if (pss->preview) p->depth = 8; else p->depth = pss->val[OPT_BIT_DEPTH].w; DBG (DL_DATA_TRACE, "%s: depth = %ld\n", me, (long) p->depth); DBG (DL_DATA_TRACE, "%s: lines = %ld\n", me, (long) p->lines); DBG (DL_DATA_TRACE, "%s: pixels per line = %ld\n", me, (long) p->pixels_per_line); DBG (DL_DATA_TRACE, "%s: bytes per line = %ld\n", me, (long) p->bytes_per_line); return status; } /* scan data reader routine for child process */ #define READER_WRITE_SIZE 4096 static void reader (SnapScan_Scanner *pss) { static char me[] = "Child reader process"; SANE_Status status; SANE_Byte *wbuf = NULL; DBG (DL_CALL_TRACE, "%s\n", me); wbuf = (SANE_Byte*) malloc(READER_WRITE_SIZE); if (wbuf == NULL) { DBG (DL_MAJOR_ERROR, "%s: failed to allocate write buffer.\n", me); return; } while ((pss->preadersrc->remaining(pss->preadersrc) > 0) && !cancelRead) { SANE_Int ndata = READER_WRITE_SIZE; status = pss->preadersrc->get(pss->preadersrc, wbuf, &ndata); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: %s on read.\n", me, sane_strstatus (status)); return; } { SANE_Byte *buf = wbuf; DBG (DL_DATA_TRACE, "READ %d BYTES (%d)\n", ndata, cancelRead); while (ndata > 0) { int written = write (pss->rpipe[1], buf, ndata); DBG (DL_DATA_TRACE, "WROTE %d BYTES\n", written); if (written == -1) { DBG (DL_MAJOR_ERROR, "%s: error writing scan data on parent pipe.\n", me); perror ("pipe error: "); } else { ndata -= written; buf += written; } } } } } /** signal handler to kill the child process */ static void usb_reader_process_sigterm_handler( int signo ) { DBG( DL_INFO, "(SIG) reader_process: terminated by signal %d\n", signo ); cancelRead = SANE_TRUE; } static void sigalarm_handler( int signo __sane_unused__) { DBG( DL_INFO, "ALARM!!!\n" ); } /** executed as a child process * read the data from the driver and send them to the parent process */ static int reader_process( void *args ) { SANE_Status status; struct SIGACTION act; sigset_t ignore_set; SnapScan_Scanner *pss = (SnapScan_Scanner *) args; if( sanei_thread_is_forked()) { DBG( DL_MINOR_INFO, "reader_process started (forked)\n" ); /* child process - close read side, make stdout the write side of the pipe */ close( pss->rpipe[0] ); pss->rpipe[0] = -1; } else { DBG( DL_MINOR_INFO, "reader_process started (as thread)\n" ); } sigfillset ( &ignore_set ); sigdelset ( &ignore_set, SIGUSR1 ); sigprocmask( SIG_SETMASK, &ignore_set, 0 ); memset ( &act, 0, sizeof (act)); sigaction( SIGTERM, &act, 0 ); cancelRead = SANE_FALSE; /* install the signal handler */ sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = usb_reader_process_sigterm_handler; sigaction( SIGUSR1, &act, 0 ); status = create_base_source (pss, SCSI_SRC, &(pss->preadersrc)); if (status == SANE_STATUS_GOOD) { reader (pss); } else { DBG (DL_MAJOR_ERROR, "Reader process: failed to create SCSISource.\n"); } pss->preadersrc->done(pss->preadersrc); free(pss->preadersrc); pss->preadersrc = 0; close( pss->rpipe[1] ); pss->rpipe[1] = -1; DBG( DL_MINOR_INFO, "reader_process: finished reading data\n" ); return SANE_STATUS_GOOD; } static SANE_Status start_reader (SnapScan_Scanner *pss) { SANE_Status status = SANE_STATUS_GOOD; static char me[] = "start_reader"; DBG (DL_CALL_TRACE, "%s\n", me); pss->nonblocking = SANE_FALSE; pss->rpipe[0] = pss->rpipe[1] = -1; pss->child = -1; if (pipe (pss->rpipe) != -1) { pss->orig_rpipe_flags = fcntl (pss->rpipe[0], F_GETFL, 0); pss->child = sanei_thread_begin(reader_process, (void *) pss); cancelRead = SANE_FALSE; if (!sanei_thread_is_valid (pss->child)) { /* we'll have to read in blocking mode */ DBG (DL_MAJOR_ERROR, "%s: Error while calling sanei_thread_begin; must read in blocking mode.\n", me); close (pss->rpipe[0]); close (pss->rpipe[1]); status = SANE_STATUS_UNSUPPORTED; } if (sanei_thread_is_forked()) { /* parent; close write side */ close (pss->rpipe[1]); pss->rpipe[1] = -1; } pss->nonblocking = SANE_TRUE; } return status; } static SANE_Status send_gamma_table (SnapScan_Scanner *pss, u_char dtc, u_char dtcq) { static char me[] = "send_gamma_table"; SANE_Status status = SANE_STATUS_GOOD; status = send (pss, dtc, dtcq); CHECK_STATUS (status, me, "send"); switch (pss->pdev->model) { case PERFECTION1270: case PERFECTION1670: case PERFECTION2480: case PERFECTION3490: /* Some epson scanners need the gamma table twice */ status = send (pss, dtc, dtcq); CHECK_STATUS (status, me, "2nd send"); break; case PRISA5150: /* 5150 needs the gamma table twice, with dtc = 0x04 for the second one */ status = send (pss, DTC_GAMMA2, dtcq); CHECK_STATUS (status, me, "2nd send"); break; default: break; } return status; } static SANE_Status download_gamma_tables (SnapScan_Scanner *pss) { static char me[] = "download_gamma_tables"; SANE_Status status = SANE_STATUS_GOOD; double gamma_gs = SANE_UNFIX (pss->gamma_gs); double gamma_r = SANE_UNFIX (pss->gamma_r); double gamma_g = SANE_UNFIX (pss->gamma_g); double gamma_b = SANE_UNFIX (pss->gamma_b); SnapScan_Mode mode = actual_mode (pss); int dtcq_gamma_gray; int dtcq_gamma_red; int dtcq_gamma_green; int dtcq_gamma_blue; int gamma_mode = GAMMA_8BIT; DBG (DL_CALL_TRACE, "%s\n", me); switch (mode) { case MD_COLOUR: break; case MD_BILEVELCOLOUR: if (!pss->halftone) { gamma_r = gamma_g = gamma_b = 1.0; } break; case MD_LINEART: if (!pss->halftone) gamma_gs = 1.0; break; default: /* no further action for greyscale */ break; } switch (pss->bpp) { case 10: DBG (DL_DATA_TRACE, "%s: Sending 8bit gamma table for %d bpp\n", me, pss->bpp); dtcq_gamma_gray = DTCQ_GAMMA_GRAY10; dtcq_gamma_red = DTCQ_GAMMA_RED10; dtcq_gamma_green = DTCQ_GAMMA_GREEN10; dtcq_gamma_blue = DTCQ_GAMMA_BLUE10; break; case 12: if (pss->pdev->model == SCANWIT2720S) { DBG (DL_DATA_TRACE, "%s: Sending 16bit gamma table for %d bpp\n", me, pss->bpp); dtcq_gamma_gray = DTCQ_GAMMA_GRAY12_16BIT; dtcq_gamma_red = DTCQ_GAMMA_RED12_16BIT; dtcq_gamma_green = DTCQ_GAMMA_GREEN12_16BIT; dtcq_gamma_blue = DTCQ_GAMMA_BLUE12_16BIT; gamma_mode = GAMMA_12_16BIT; } else { DBG (DL_DATA_TRACE, "%s: Sending 8bit gamma table for %d bpp\n", me, pss->bpp); dtcq_gamma_gray = DTCQ_GAMMA_GRAY12; dtcq_gamma_red = DTCQ_GAMMA_RED12; dtcq_gamma_green = DTCQ_GAMMA_GREEN12; dtcq_gamma_blue = DTCQ_GAMMA_BLUE12; } break; case 14: if (pss->bpp_scan == 16) { DBG (DL_DATA_TRACE, "%s: Sending 16bit gamma table for %d bpp\n", me, pss->bpp); dtcq_gamma_gray = DTCQ_GAMMA_GRAY14_16BIT; dtcq_gamma_red = DTCQ_GAMMA_RED14_16BIT; dtcq_gamma_green = DTCQ_GAMMA_GREEN14_16BIT; dtcq_gamma_blue = DTCQ_GAMMA_BLUE14_16BIT; gamma_mode = GAMMA_16BIT; } else { DBG (DL_DATA_TRACE, "%s: Sending 8bit gamma table for %d bpp\n", me, pss->bpp); dtcq_gamma_gray = DTCQ_GAMMA_GRAY14; dtcq_gamma_red = DTCQ_GAMMA_RED14; dtcq_gamma_green = DTCQ_GAMMA_GREEN14; dtcq_gamma_blue = DTCQ_GAMMA_BLUE14; } break; default: DBG (DL_DATA_TRACE, "%s: Sending 8bit gamma table for %d bpp\n", me, pss->bpp); dtcq_gamma_gray = DTCQ_GAMMA_GRAY8; dtcq_gamma_red = DTCQ_GAMMA_RED8; dtcq_gamma_green = DTCQ_GAMMA_GREEN8; dtcq_gamma_blue = DTCQ_GAMMA_BLUE8; break; } if (is_colour_mode(mode)) { if (pss->val[OPT_CUSTOM_GAMMA].b) { if (pss->val[OPT_GAMMA_BIND].b) { /* Use greyscale gamma for all rgb channels */ gamma_from_sane (pss->gamma_length, pss->gamma_table_gs, pss->buf + SEND_LENGTH, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_red); CHECK_STATUS (status, me, "send"); gamma_from_sane (pss->gamma_length, pss->gamma_table_gs, pss->buf + SEND_LENGTH, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_green); CHECK_STATUS (status, me, "send"); gamma_from_sane (pss->gamma_length, pss->gamma_table_gs, pss->buf + SEND_LENGTH, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_blue); CHECK_STATUS (status, me, "send"); } else { gamma_from_sane (pss->gamma_length, pss->gamma_table_r, pss->buf + SEND_LENGTH, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_red); CHECK_STATUS (status, me, "send"); gamma_from_sane (pss->gamma_length, pss->gamma_table_g, pss->buf + SEND_LENGTH, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_green); CHECK_STATUS (status, me, "send"); gamma_from_sane (pss->gamma_length, pss->gamma_table_b, pss->buf + SEND_LENGTH, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_blue); CHECK_STATUS (status, me, "send"); } } else { if (pss->val[OPT_GAMMA_BIND].b) { /* Use greyscale gamma for all rgb channels */ gamma_n (gamma_gs, pss->bright, pss->contrast, pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_red); CHECK_STATUS (status, me, "send"); gamma_n (gamma_gs, pss->bright, pss->contrast, pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_green); CHECK_STATUS (status, me, "send"); gamma_n (gamma_gs, pss->bright, pss->contrast, pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_blue); CHECK_STATUS (status, me, "send"); } else { gamma_n (gamma_r, pss->bright, pss->contrast, pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_red); CHECK_STATUS (status, me, "send"); gamma_n (gamma_g, pss->bright, pss->contrast, pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_green); CHECK_STATUS (status, me, "send"); gamma_n (gamma_b, pss->bright, pss->contrast, pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_blue); CHECK_STATUS (status, me, "send"); } } } else { if(pss->val[OPT_CUSTOM_GAMMA].b) { gamma_from_sane (pss->gamma_length, pss->gamma_table_gs, pss->buf + SEND_LENGTH, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_gray); CHECK_STATUS (status, me, "send"); } else { gamma_n (gamma_gs, pss->bright, pss->contrast, pss->buf + SEND_LENGTH, pss->bpp, gamma_mode); status = send_gamma_table(pss, DTC_GAMMA, dtcq_gamma_gray); CHECK_STATUS (status, me, "send"); } } return status; } static SANE_Status download_halftone_matrices (SnapScan_Scanner *pss) { static char me[] = "download_halftone_matrices"; SANE_Status status = SANE_STATUS_GOOD; if ((pss->halftone) && ((actual_mode(pss) == MD_LINEART) || (actual_mode(pss) == MD_BILEVELCOLOUR))) { u_char *matrix; size_t matrix_sz; u_char dtcq; if (pss->dither_matrix == dm_dd8x8) { matrix = D8; matrix_sz = sizeof (D8); } else { matrix = D16; matrix_sz = sizeof (D16); } memcpy (pss->buf + SEND_LENGTH, matrix, matrix_sz); if (is_colour_mode(actual_mode(pss))) { if (matrix_sz == sizeof (D8)) dtcq = DTCQ_HALFTONE_COLOR8; else dtcq = DTCQ_HALFTONE_COLOR16; /* need copies for green and blue bands */ memcpy (pss->buf + SEND_LENGTH + matrix_sz, matrix, matrix_sz); memcpy (pss->buf + SEND_LENGTH + 2 * matrix_sz, matrix, matrix_sz); } else { if (matrix_sz == sizeof (D8)) dtcq = DTCQ_HALFTONE_BW8; else dtcq = DTCQ_HALFTONE_BW16; } status = send (pss, DTC_HALFTONE, dtcq); CHECK_STATUS (status, me, "send"); } return status; } static SANE_Status measure_transfer_rate (SnapScan_Scanner *pss) { static char me[] = "measure_transfer_rate"; SANE_Status status = SANE_STATUS_GOOD; if (pss->hconfig & HCFG_RB) { /* We have a ring buffer. We simulate one round of a read-store cycle on the size of buffer we will be using. For this read only, the buffer size must be rounded to a 128-byte boundary. */ DBG (DL_VERBOSE, "%s: have ring buffer\n", me); if ((pss->pdev->model == PERFECTION2480) || (pss->pdev->model == PERFECTION3490)) { /* Epson 2480: read a multiple of bytes per line, limit to less than 0xfff0 */ if (pss->bytes_per_line > 0xfff0) pss->expected_read_bytes = 0xfff0; else pss->expected_read_bytes = (0xfff0 / pss->bytes_per_line) * pss->bytes_per_line; } else pss->expected_read_bytes = (pss->buf_sz%128) ? (pss->buf_sz/128 + 1)*128 : pss->buf_sz; status = scsi_read (pss, READ_TRANSTIME); CHECK_STATUS (status, me, "scsi_read"); pss->expected_read_bytes = 0; status = scsi_read (pss, READ_TRANSTIME); CHECK_STATUS (status, me, "scsi_read"); } else { /* we don't have a ring buffer. The test requires transferring one scan line of data (rounded up to next 128 byte boundary). */ DBG (DL_VERBOSE, "%s: we don't have a ring buffer.\n", me); pss->expected_read_bytes = pss->bytes_per_line; if (pss->expected_read_bytes%128) { pss->expected_read_bytes = (pss->expected_read_bytes/128 + 1)*128; } status = scsi_read (pss, READ_TRANSTIME); CHECK_STATUS (status, me, "scsi_read"); DBG (DL_VERBOSE, "%s: read %ld bytes.\n", me, (long) pss->read_bytes); } pss->expected_read_bytes = 0; status = scsi_read (pss, READ_TRANSTIME); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: test read failed.\n", me); return status; } DBG (DL_VERBOSE, "%s: successfully calibrated transfer rate.\n", me); return status; } SANE_Status sane_start (SANE_Handle h) { static const char *me = "sane_snapscan_start"; SANE_Status status; SnapScan_Scanner *pss = (SnapScan_Scanner *) h; DBG (DL_CALL_TRACE, "%s (%p)\n", me, (void *) h); /* possible authorization required */ status = open_scanner (pss); CHECK_STATUS (status, me, "open_scanner"); status = wait_scanner_ready (pss); CHECK_STATUS (status, me, "wait_scanner_ready"); /* start scanning; reserve the unit first, because a release_unit is necessary to abort a scan in progress */ pss->state = ST_SCAN_INIT; if ((pss->pdev->model == SCANWIT2720S) && (pss->focus_mode == MD_AUTO)) { status = get_focus(pss); CHECK_STATUS (status, me, "get_focus"); } reserve_unit(pss); if (pss->pdev->model == SCANWIT2720S) { status = set_frame(pss, 0); CHECK_STATUS (status, me, "set_frame"); status = set_focus(pss, pss->focus); CHECK_STATUS (status, me, "set_focus"); } /* set up the window and fetch the resulting scanner parameters */ status = set_window(pss); CHECK_STATUS (status, me, "set_window"); status = inquiry(pss); CHECK_STATUS (status, me, "inquiry"); /* download the gamma and halftone tables */ status = download_gamma_tables(pss); CHECK_STATUS (status, me, "download_gamma_tables"); status = download_halftone_matrices(pss); CHECK_STATUS (status, me, "download_halftone_matrices"); if (pss->val[OPT_QUALITY_CAL].b && (pss->usb_vendor == USB_VENDOR_EPSON)) { status = calibrate(pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: calibration failed.\n", me); release_unit (pss); return status; } } /* we must measure the data transfer rate between the host and the scanner, and the method varies depending on whether there is a ring buffer or not. */ status = measure_transfer_rate(pss); CHECK_STATUS (status, me, "measure_transfer_rate"); /* now perform an inquiry again to retrieve the scan speed */ status = inquiry(pss); CHECK_STATUS (status, me, "inquiry"); DBG (DL_DATA_TRACE, "%s: after measuring speed:\n\t%lu bytes per scan line\n" "\t%f milliseconds per scan line.\n\t==>%f bytes per millisecond\n", me, (u_long) pss->bytes_per_line, pss->ms_per_line, pss->bytes_per_line/pss->ms_per_line); if (pss->val[OPT_QUALITY_CAL].b && (pss->usb_vendor != USB_VENDOR_EPSON)) { status = calibrate(pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: calibration failed.\n", me); release_unit (pss); return status; } } status = scan(pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: scan command failed: %s.\n", me, sane_strstatus(status)); release_unit (pss); return status; } if (pss->pdev->model == SCANWIT2720S) { status = set_frame(pss, pss->frame_no); CHECK_STATUS (status, me, "set_frame"); } if (pss->source == SRC_ADF) { /* Wait for scanner ready again (e.g. until paper is loaded from an ADF) */ /* Maybe replace with get_data_buffer_status()? */ status = wait_scanner_ready (pss); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: scan command failed while waiting for scanner: %s.\n", me, sane_strstatus(status)); release_unit (pss); return status; } } DBG (DL_MINOR_INFO, "%s: starting the reader process.\n", me); status = start_reader(pss); { BaseSourceType st = FD_SRC; if (status != SANE_STATUS_GOOD) st = SCSI_SRC; status = create_source_chain (pss, st, &(pss->psrc)); } return status; } SANE_Status sane_read (SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *plen) { static const char *me = "sane_snapscan_read"; SnapScan_Scanner *pss = (SnapScan_Scanner *) h; SANE_Status status = SANE_STATUS_GOOD; DBG (DL_CALL_TRACE, "%s (%p, %p, %ld, %p)\n", me, (void *) h, (void *) buf, (long) maxlen, (void *) plen); *plen = 0; if (pss->state == ST_CANCEL_INIT) { pss->state = ST_IDLE; return SANE_STATUS_CANCELLED; } if (pss->psrc == NULL || pss->psrc->remaining(pss->psrc) == 0) { if (sanei_thread_is_valid (pss->child)) { sanei_thread_waitpid (pss->child, 0); /* ensure no zombies */ pss->child = -1; } release_unit (pss); close_scanner (pss); if (pss->psrc != NULL) { pss->psrc->done(pss->psrc); free(pss->psrc); pss->psrc = NULL; } pss->state = ST_IDLE; return SANE_STATUS_EOF; } *plen = maxlen; status = pss->psrc->get(pss->psrc, buf, plen); switch (pss->state) { case ST_IDLE: DBG (DL_MAJOR_ERROR, "%s: weird error: scanner state should not be idle on call to " "sane_read.\n", me); break; case ST_SCAN_INIT: /* we've read some data */ pss->state = ST_SCANNING; break; case ST_CANCEL_INIT: /* stop scanning */ status = SANE_STATUS_CANCELLED; break; default: break; } return status; } void sane_cancel (SANE_Handle h) { char *me = "sane_snapscan_cancel"; SnapScan_Scanner *pss = (SnapScan_Scanner *) h; struct SIGACTION act; SANE_Pid res; DBG (DL_CALL_TRACE, "%s\n", me); switch (pss->state) { case ST_IDLE: break; case ST_SCAN_INIT: case ST_SCANNING: /* signal a cancellation has occurred */ pss->state = ST_CANCEL_INIT; /* signal the reader, if any */ if (sanei_thread_is_valid (pss->child)) { DBG( DL_INFO, ">>>>>>>> killing reader_process <<<<<<<<\n" ); sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = sigalarm_handler; sigaction( SIGALRM, &act, 0 ); if (sanei_thread_is_forked()) { /* use SIGUSR1 to set cancelRead in child process */ sanei_thread_sendsig( pss->child, SIGUSR1 ); } else { cancelRead = SANE_TRUE; } /* give'em 10 seconds 'til done...*/ alarm(10); res = sanei_thread_waitpid( pss->child, 0 ); alarm(0); if( res != pss->child ) { DBG( DL_MINOR_ERROR,"sanei_thread_waitpid() failed !\n"); /* do it the hard way...*/ #ifdef USE_PTHREAD sanei_thread_kill( pss->child ); #else sanei_thread_sendsig( pss->child, SIGKILL ); #endif } pss->child = -1; DBG( DL_INFO,"reader_process killed\n"); } release_unit (pss); close_scanner (pss); break; case ST_CANCEL_INIT: DBG (DL_INFO, "%s: cancellation already initiated.\n", me); break; default: DBG (DL_MAJOR_ERROR, "%s: weird error: invalid scanner state (%ld).\n", me, (long) pss->state); break; } } SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool m) { static char me[] = "sane_snapscan_set_io_mode"; SnapScan_Scanner *pss = (SnapScan_Scanner *) h; char *op; DBG (DL_CALL_TRACE, "%s\n", me); if (pss->state != ST_SCAN_INIT) return SANE_STATUS_INVAL; if (m) { if (!sanei_thread_is_valid (pss->child)) { DBG (DL_MINOR_INFO, "%s: no reader child; must use blocking mode.\n", me); return SANE_STATUS_UNSUPPORTED; } op = "ON"; fcntl (pss->rpipe[0], F_SETFL, O_NONBLOCK | pss->orig_rpipe_flags); } else { op = "OFF"; fcntl (pss->rpipe[0], F_SETFL, pss->orig_rpipe_flags); } DBG (DL_MINOR_INFO, "%s: turning nonblocking mode %s.\n", me, op); pss->nonblocking = m; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fd) { static char me[] = "sane_snapscan_get_select_fd"; SnapScan_Scanner *pss = (SnapScan_Scanner *) h; DBG (DL_CALL_TRACE, "%s\n", me); if (pss->state != ST_SCAN_INIT) return SANE_STATUS_INVAL; if (!sanei_thread_is_valid (pss->child)) { DBG (DL_MINOR_INFO, "%s: no reader child; cannot provide select file descriptor.\n", me); return SANE_STATUS_UNSUPPORTED; } *fd = pss->rpipe[0]; return SANE_STATUS_GOOD; } /* * $Log$ * Revision 1.73 2008/11/26 21:21:29 kitno-guest * * backend/ *.[ch]: nearly every backend used V_MAJOR * instead of SANE_CURRENT_MAJOR in sane_init() * * backend/snapscan.c: remove EXPECTED_VERSION check * since new SANE standard is forward compatible * * Revision 1.72 2008-05-15 12:50:24 ellert-guest * Fix for bug #306751: sanei-thread with pthreads on 64 bit * * Revision 1.71 2008-01-29 17:48:42 kitno-guest * fix snapscan bug, add LiDE 600F * * Revision 1.70 2007-11-18 10:59:18 ellert-guest * Fix handling of valid "negative" PIDs * * Revision 1.69 2007-11-16 08:04:02 ellert-guest * Correct the test of the return value from sanei_thread_begin * * Revision 1.68 2006-09-03 10:00:11 oliver-guest * Bugfix for firmware download by Paul Smedley * * Revision 1.67 2006/01/10 19:32:16 oliver-guest * Added 12 bit gamma tables for Epson Stylus CX-1500 * * Revision 1.66 2006/01/06 20:59:17 oliver-guest * Some fixes for the Epson Stylus CX 1500 * * Revision 1.65 2006/01/01 23:02:55 oliver-guest * Added snapscan-data.c to Makefile.in * * Revision 1.64 2005/12/05 20:38:23 oliver-guest * Small bugfix for Benq 5150 * * Revision 1.63 2005/12/04 15:03:00 oliver-guest * Some fixes for Benq 5150 * * Revision 1.62 2005/12/02 19:15:42 oliver-guest * Change SnapScan version number to 1.4.50 * * Revision 1.61 2005/11/15 20:11:19 oliver-guest * Enabled quality calibration for the Epson 3490 * * Revision 1.60 2005/11/10 19:42:02 oliver-guest * Added deinterlacing for Epson 3490 * * Revision 1.59 2005/11/02 22:12:54 oliver-guest * Correct cut'n'paste error * * Revision 1.58 2005/11/02 19:22:06 oliver-guest * Fixes for Benq 5000 * * Revision 1.57 2005/10/31 21:08:47 oliver-guest * Distinguish between Benq 5000/5000E/5000U * * Revision 1.56 2005/10/24 19:46:40 oliver-guest * Preview and range fix for Epson 2480/2580 * * Revision 1.55 2005/10/23 21:28:58 oliver-guest * Fix for buffer size in high res modes, fixes for delay code * * Revision 1.54 2005/10/13 22:43:30 oliver-guest * Fixes for 16 bit scan mode from Simon Munton * * Revision 1.53 2005/10/11 18:47:07 oliver-guest * Fixes for Epson 3490 and 16 bit scan mode * * Revision 1.52 2005/09/28 21:33:11 oliver-guest * Added 16 bit option for Epson scanners (untested) * * Revision 1.51 2005/08/15 18:56:55 oliver-guest * Added temporary debug code for 2480/2580 distinction * * Revision 1.50 2005/08/15 18:06:37 oliver-guest * Added support for Epson 3490/3590 (thanks to Matt Judge) * * Revision 1.49 2005/08/07 12:37:29 oliver-guest * Use first known device if no device is specified * * Revision 1.48 2004/12/09 23:21:48 oliver-guest * Added quality calibration for Epson 2480 (by Simon Munton) * * Revision 1.47 2004/12/01 22:49:14 oliver-guest * Fix for allocation of gamma tables by Simon Munton * * Revision 1.46 2004/12/01 22:12:03 oliver-guest * Added support for Epson 1270 * * Revision 1.45 2004/10/03 17:34:36 hmg-guest * 64 bit platform fixes (bug #300799). * * Revision 1.44 2004/09/02 20:59:12 oliver-guest * Added support for Epson 2480 * * Revision 1.43 2004/06/16 19:52:26 oliver-guest * Don't enforce even number of URB packages on 1212u_2. Fixes bug #300753. * * Revision 1.42 2004/06/15 12:17:37 hmg-guest * Only use __attribute__ if gcc is used for compilation. Some other compilers * don't know __attribute__ and therefore can't compile sane-backends without this * fix. See bug #300803. * * Revision 1.41 2004/05/26 22:37:01 oliver-guest * Use shared memory for urb counters in snapscan backend * * Revision 1.40 2004/04/09 11:59:02 oliver-guest * Fixes for pthread implementation * * Revision 1.39 2004/04/08 21:53:10 oliver-guest * Use sanei_thread in snapscan backend * * Revision 1.37 2003/11/27 23:11:32 oliver-guest * Send gamma table twice for Epson Perfection 1670 * * Revision 1.36 2003/11/09 21:43:45 oliver-guest * Disabled quality calibration for Epson Perfection 1670 * * Revision 1.35 2003/11/07 23:26:49 oliver-guest * Final bugfixes for bascic support of Epson 1670 * * Revision 1.34 2003/10/21 20:43:25 oliver-guest * Bugfixes for SnapScan backend * * Revision 1.33 2003/10/07 18:29:20 oliver-guest * Initial support for Epson 1670, minor bugfix * * Revision 1.32 2003/09/24 18:05:39 oliver-guest * Bug #300198: Check second argument of sanei_config_get_string * * Revision 1.31 2003/09/12 16:10:33 hmg-guest * Moved union Option_Value from backend header files to sanei_backend.h. No need * to copy it over and over again. Changed header inclusion order in backend * files to include backend.h after sanei_backend.h. Based on a patch from stef * . * * Revision 1.30 2003/08/19 21:05:08 oliverschwartz * Scanner ID cleanup * * Revision 1.29 2003/04/30 20:49:40 oliverschwartz * SnapScan backend 1.4.26 * * Revision 1.58 2003/04/30 20:43:07 oliverschwartz * Set backend version number to 1.4.26 * * Revision 1.57 2003/04/02 21:17:14 oliverschwartz * Fix for 1200 DPI with Acer 5000 * * Revision 1.56 2003/02/08 10:45:09 oliverschwartz * Use 600 DPI as optical resolution for Benq 5000 * * Revision 1.55 2003/01/08 21:16:17 oliverschwartz * Added support for Acer / Benq 310U * * Revision 1.54 2002/12/10 20:14:12 oliverschwartz * Enable color offset correction for SnapScan300 * * Revision 1.53 2002/10/31 19:29:41 oliverschwartz * Set version to 1.4.17 * * Revision 1.52 2002/10/12 10:40:48 oliverschwartz * Added support for Snapscan e10 * * Revision 1.51 2002/09/26 19:27:44 oliverschwartz * Version 1.4.16 * * Revision 1.50 2002/09/24 16:07:44 oliverschwartz * Added support for Benq 5000 * * Revision 1.49 2002/07/12 22:53:54 oliverschwartz * Version 1.4.15 * * Revision 1.48 2002/07/12 22:53:16 oliverschwartz * call sanei_usb_init() before sanei_usb_attach_matching_devices() * * Revision 1.47 2002/06/06 21:16:23 oliverschwartz * Set backend version to 1.4.14 * * Revision 1.46 2002/06/06 20:40:01 oliverschwartz * Changed default scan area for transparancy unit of SnapScan e50 * * Revision 1.45 2002/05/02 18:29:34 oliverschwartz * - Added ADF support * - Fixed status handling after cancel * * Revision 1.44 2002/04/27 14:42:30 oliverschwartz * Cleanup of debug logging * * Revision 1.43 2002/04/23 22:40:33 oliverschwartz * Improve config file reading * * Revision 1.42 2002/04/10 21:00:09 oliverschwartz * Check for NULL pointer before deleting device list * * Revision 1.41 2002/03/24 12:12:36 oliverschwartz * - Moved option functions to snapscan-options.c * - Autodetect USB scanners * - Cleanup * * Revision 1.40 2002/02/09 14:55:23 oliverschwartz * Added language translation support (SANE_I18N) * * Revision 1.39 2002/01/23 20:40:54 oliverschwartz * Don't use quantization for scan area parameter * Improve recognition of Acer 320U * Version 1.4.7 * * Revision 1.38 2002/01/14 21:11:56 oliverschwartz * Add workaround for bug semctl() call in libc for PPC * * Revision 1.37 2002/01/10 21:33:12 oliverschwartz * Set version number to 1.4.4 * * Revision 1.36 2002/01/06 18:34:02 oliverschwartz * Added support for Snapscan e42 thanks to Yari Ad� Petralanda * * Revision 1.35 2001/12/20 23:18:01 oliverschwartz * Remove tmpfname * * Revision 1.34 2001/12/18 18:28:35 oliverschwartz * Removed temporary file * * Revision 1.33 2001/12/12 19:43:30 oliverschwartz * - Set version number to 1.4.3 * - Clean up CVS Log * * Revision 1.32 2001/12/09 23:06:45 oliverschwartz * - use sense handler for USB if scanner reports CHECK_CONDITION * * Revision 1.31 2001/12/08 11:50:34 oliverschwartz * Fix dither matrix computation * * Revision 1.30 2001/11/29 22:50:14 oliverschwartz * Add support for SnapScan e52 * * Revision 1.29 2001/11/27 23:16:17 oliverschwartz * - Fix color alignment for SnapScan 600 * - Added documentation in snapscan-sources.c * - Guard against TL_X < BR_X and TL_Y < BR_Y * * Revision 1.28 2001/11/25 18:51:41 oliverschwartz * added support for SnapScan e52 thanks to Rui Lopes * * Revision 1.27 2001/11/16 20:28:35 oliverschwartz * add support for Snapscan e26 * * Revision 1.26 2001/11/16 20:23:16 oliverschwartz * Merge with sane-1.0.6 * - Check USB vendor IDs to avoid hanging scanners * - fix bug in dither matrix computation * * Revision 1.25 2001/10/25 11:06:22 oliverschwartz * Change snapscan backend version number to 1.4.0 * * Revision 1.24 2001/10/11 14:02:10 oliverschwartz * Distinguish between e20/e25 and e40/e50 * * Revision 1.23 2001/10/09 22:34:23 oliverschwartz * fix compiler warnings * * Revision 1.22 2001/10/08 19:26:01 oliverschwartz * - Disable quality calibration for scanners that do not support it * * Revision 1.21 2001/10/08 18:22:02 oliverschwartz * - Disable quality calibration for Acer Vuego 310F * - Use sanei_scsi_max_request_size as scanner buffer size * for SCSI devices * - Added new devices to snapscan.desc * * Revision 1.20 2001/09/18 15:01:07 oliverschwartz * - Read scanner id string again after firmware upload * to indentify correct model * - Make firmware upload work for AGFA scanners * - Change copyright notice * * Revision 1.19 2001/09/17 10:01:08 sable * Added model AGFA 1236U * * Revision 1.18 2001/09/10 10:16:32 oliverschwartz * better USB / SCSI recognition, correct max scan area for 1236+TPO * * Revision 1.17 2001/09/09 18:06:32 oliverschwartz * add changes from Acer (new models; automatic firmware upload for USB scanners); fix distorted colour scans after greyscale scans (call set_window only in sane_start); code cleanup * * Revision 1.16 2001/09/07 09:42:13 oliverschwartz * Sync with Sane-1.0.5 * * Revision 1.15 2001/05/15 20:51:14 oliverschwartz * check for pss->devname instead of name in sane_open() * * Revision 1.14 2001/04/10 13:33:06 sable * Transparency adapter bug and xsane crash corrections thanks to Oliver Schwartz * * Revision 1.13 2001/04/10 13:00:31 sable * Moving sanei_usb_* to snapscani_usb* * * Revision 1.12 2001/04/10 11:04:31 sable * Adding support for snapscan e40 an e50 thanks to Giuseppe Tanzilli * * Revision 1.11 2001/03/17 22:53:21 sable * Applying Mikael Magnusson patch concerning Gamma correction * Support for 1212U_2 * * Revision 1.4 2001/03/04 16:50:53 mikael * Added Scan Mode, Geometry, Enhancement and Advanced groups. Implemented brightness and contrast controls with gamma tables. Added Quality Calibration, Analog Gamma Bind, Custom Gamma and Gamma Vector GS,R,G,B options. * * Revision 1.3 2001/02/16 18:32:28 mikael * impl calibration, signed position, increased buffer size * * Revision 1.2 2001/02/10 18:18:29 mikael * Extended x and y ranges * * Revision 1.1.1.1 2001/02/10 17:09:29 mikael * Imported from snapscan-11282000.tar.gz * * Revision 1.10 2000/11/10 01:01:59 sable * USB (kind of) autodetection * * Revision 1.9 2000/11/01 01:26:43 sable * Support for 1212U * * Revision 1.8 2000/10/30 22:31:13 sable * Auto preview mode * * Revision 1.7 2000/10/28 14:16:10 sable * Bug correction for SnapScan310 * * Revision 1.6 2000/10/28 14:06:35 sable * Add support for Acer300f * * Revision 1.5 2000/10/15 19:52:06 cbagwell * Changed USB support to a 1 line modification instead of multi-file * changes. * * Revision 1.4 2000/10/13 03:50:27 cbagwell * Updating to source from SANE 1.0.3. Calling this versin 1.1 * * Revision 1.3 2000/08/12 15:09:35 pere * Merge devel (v1.0.3) into head branch. * * Revision 1.1.1.1.2.5 2000/07/29 16:04:33 hmg * 2000-07-29 Henning Meier-Geinitz * * * backend/GUIDE: Added some comments about portability and * documentation. * * backend/abaton.c backend/agfafocus.c backend/apple.c * backend/canon.c backend/coolscan.c backend/dc210.c backend/dc25.c * backend/dll.c backend/dmc.c backend/microtek.c backend/microtek2.c * backend/microtek2.c backend/mustek_pp.c backend/net.c backend/pint.c * backend/pnm.c backend/qcam.c backend/ricoh.c backend/s9036.c * backend/sane_strstatus.c backend/sharp.c backend/snapscan.c * backend/st400.c backend/stubs.c backend/tamarack.c backend/v4l.c: * Changed include statements from #include to * #include "sane...". * * backend/avision.c backend/dc25.c: Use DBG(0, ...) instead of * fprintf (stderr, ...) * * backend/avision.c backend/canon-sane.c backend/coolscan.c * backend/dc25.c backend/microtek.c backend/microtek2.c * backend/st400.c: Use sanei_config_read() instead of fgets(). * * backend/coolscan.desc backend/microtek.desc backend/microtek2.desc * backend/st400.desc: Added :interface and :manpage entries. * * backend/nec.desc: Status is beta now (was: new). Fixed typo. * * doc/canon.README: Removed, because the information is included in * the manpage now. * * doc/Makefile.in: Added sane-coolscan to list of mapages to install. * * README: Added Link to coolscan manpage. * * backend/mustek.*: Update to Mustek backend 1.0-94. Fixed the * #include bug. * * Revision 1.1.1.1.2.4 2000/07/25 21:47:43 hmg * 2000-07-25 Henning Meier-Geinitz * * * backend/snapscan.c: Use DBG(0, ...) instead of fprintf (stderr, ...). * * backend/abaton.c backend/agfafocus.c backend/apple.c backend/dc210.c * backend/dll.c backend/dmc.c backend/microtek2.c backend/pint.c * backend/qcam.c backend/ricoh.c backend/s9036.c backend/snapscan.c * backend/tamarack.c: Use sanei_config_read instead of fgets. * * backend/dc210.c backend/microtek.c backend/pnm.c: Added * #include "../include/sane/config.h". * * backend/dc25.c backend/m3096.c backend/sp15.c * backend/st400.c: Moved #include "../include/sane/config.h" to the beginning. * * AUTHORS: Changed agfa to agfafocus. * * Revision 1.1.1.1.2.3 2000/07/17 21:37:28 hmg * 2000-07-17 Henning Meier-Geinitz * * * backend/snapscan.c backend/snapscan-scsi.c: Replace C++ comment * with C comment. * * Revision 1.1.1.1.2.2 2000/07/13 04:47:46 pere * New snapscan backend version dated 20000514 from Steve Underwood. * * Revision 1.2 2000/05/14 13:30:20 coppice * R, G and B images now merge correctly. Still some outstanding issues, * but a lot more useful than before. * * Revision 1.2 2000/03/05 13:55:20 pere * Merged main branch with current DEVEL_1_9. * * Revision 1.1.1.1.2.1 1999/09/15 18:20:44 charter * Early version 1.0 snapscan.c * * Revision 2.2 1999/09/09 18:22:45 charter * Checkpoint. Now using Sources for scanner data, and have removed * references to the old snapscan-310.c stuff. This stuff must still * be incorporated into the RGBRouter to get trilinear CCD SnapScan * models working. * * Revision 2.1 1999/09/08 03:07:05 charter * Start of branch 2; same as 1.47. * * Revision 1.47 1999/09/08 03:03:53 charter * The actions for the scanner command options now use fprintf for * printing, rather than DGB. I want the output to come out no matter * what the value of the snapscan debug level. * * Revision 1.46 1999/09/07 20:53:41 charter * Changed expected_data_len to bytes_remaining. * * Revision 1.45 1999/09/06 23:32:37 charter * Split up sane_start() into sub-functions to improve readability (again). * Introduced actual_mode() and is_colour_mode() (again). * Fixed problems with cancellation. Works fine with my system now. * * Revision 1.44 1999/09/02 05:28:01 charter * Added Gary Plewa's name to the list of copyrighted contributors. * * Revision 1.43 1999/09/02 05:23:54 charter * Added Gary Plewa's patch for the Acer PRISA 620s. * * Revision 1.42 1999/09/02 02:05:34 charter * Check-in of revision 1.42 (release 0.7 of the backend). * This is part of the recovery from the great disk crash of Sept 1, 1999. * * Revision 1.42 1999/07/09 22:37:55 charter * Potential bugfix for problems with sane_get_parameters() and * the new generic scsi driver (suggested by Francois Desarmeni, * Douglas Gilbert, Abel Deuring). * * Revision 1.41 1999/07/09 20:58:07 charter * Changes to support SnapScan 1236s (Petter Reinholdsten). * * Revision 1.40 1998/12/16 18:43:06 charter * Fixed major version problem precipitated by release of SANE-1.00. * * Revision 1.39 1998/09/07 06:09:26 charter * Formatting (whitespace) changes. * * Revision 1.38 1998/09/07 06:06:01 charter * Merged in Wolfgang Goeller's changes (Vuego 310S, bugfixes). * * Revision 1.37 1998/08/06 06:16:39 charter * Now using sane_config_attach_matching_devices() in sane_snapscan_init(). * Change contributed by David Mosberger-Tang. * * Revision 1.36 1998/05/11 17:02:53 charter * Added Mikko's threshold stuff. * * Revision 1.35 1998/03/10 23:43:23 eblot * Bug correction * * Revision 0.72 1998/03/10 23:40:42 eblot * More support for 310/600 models: color preview, large window * * Revision 1.35 1998/03/10 21:32:07 eblot * Debugging * * Revision 1.34 1998/02/15 21:55:53 charter * From Emmanuel Blot: * First routines to support SnapScan 310 scanned data. * * Revision 1.33 1998/02/06 02:30:28 charter * Now using a mode enum (instead of the static string pointers directly). * Now check for the SnapScan 310 and 600 explicitly (start of support * for these models). * * Revision 1.32 1998/02/01 21:56:48 charter * Patches to fix compilation problems on Solaris supplied by * Jim McBeath. * * Revision 1.31 1998/02/01 03:36:40 charter * Now check for BRX < TLX and BRY < TLY and whether the area of the * scanning window is approaching zero in set_window. I'm setting a * minimum window size of 75x75 hardware pixels (0.25 inches a side). * If the area falls to zero, the scanner seems to hang in the middle * of the set_window command. * * Revision 1.30 1998/02/01 00:00:33 charter * TLX, TLY, BRX and BRY are now lengths expressed in mm. The frontends * can now allow changes in the units, and units that are more user- * friendly. * * Revision 1.29 1998/01/31 21:09:19 charter * Fixed another problem with add_device(): if mini_inquiry ends * up indirectly invoking the sense handler, there'll be a segfault * because the sense_handler isn't set. Had to fix sense_handler so * it can handle a NULL pss pointer and then use the sanei_scsi stuff * everywhere. This error is most likely to occur if the scanner is * turned off. * * Revision 1.28 1998/01/31 18:45:22 charter * Last fix botched, produced a compile error. Thought I'd already * compiled successfully. * * Revision 1.27 1998/01/31 18:32:42 charter * Fixed stupid bug in add_device that causes segfault when no snapscan * found: closing a scsi fd opened with open() using sanei_scsi_close(). * * Revision 1.26 1998/01/30 21:19:02 charter * sane_snapscan_init() handles failure of add_device() in the same * way when there is no snapscan.conf file available as when there is * one. * * Revision 1.25 1998/01/30 19:41:11 charter * Waiting for child process termination at regular end of scan (not * just on cancellation); before I was getting zombies. * * Revision 1.24 1998/01/30 19:19:27 charter * Changed from strncmp() to strncasecmp() to do vendor and model * comparisons in sane_snapscan_init. There are some snapcsan models * that use lower case. * Now have debug level defines instead of raw numbers, and better debug * information categories. * Don't complain at debug level 0 when a snapscan isn't found on a * requested device. * Changed CHECK_STATUS to take caller parameter instead of always * assuming an available string "me". * * Revision 1.23 1998/01/30 11:03:04 charter * Fixed * vs [] operator precedence screwup in sane_snapscan_get_devices() * that caused a segfault in scanimage -h. * Fixed problem with not closing the scsi fd between certain commands * that caused scanimage to hang; now using open_scanner() and close_scanner(). * * Revision 1.22 1998/01/28 09:02:55 charter * Fixed bug: zero allocation length in request sense command buffer * was preventing sense information from being received. The * backend now correctly waits for the scanner to warm up. * Now using the hardware configuration byte to check whether * both 8x8 and 16x16 halftoning should be made available. * * Revision 1.21 1998/01/25 09:57:57 charter * Added more SCSI command buttons (and a group for them). * Made the output of the Inquiry command a bit nicer. * * Revision 1.20 1998/01/25 08:53:14 charter * Have added bi-level colour mode, with halftones too. * Can now select preview mode (but it's an advanced option, since * you usually don't want to do it). * * Revision 1.19 1998/01/25 02:25:02 charter * Fixed bug: preview mode gives blank image at initial startup. * Fixed bug: lineart mode goes weird after a preview or gs image. * More changes to option relationships; * now using test_unit_ready and send_diagnostic in sane_snapscan_open(). * Added negative option. * * Revision 1.18 1998/01/24 05:15:32 charter * Now have RGB gamma correction and dispersed-dot dither halftoning * for BW images. Cleaned up some spots in the code and have set up * option interactions a bit better (e.g. halftoning and GS gamma * correction made inactive in colour mode, etc). TL_[XY] and BR_[XY] * now change in ten-pixel increments (I had problems with screwed-up * scan lines when the dimensions were weird at low res... could be the * problem). * * Revision 1.17 1998/01/23 13:03:17 charter * Several changes, all aimed at getting scanning performance working * correctly, and the progress/cancel window functioning. Cleaned up * a few nasty things as well. * * Revision 1.16 1998/01/23 07:40:23 charter * Reindented using GNU convention at David Mosberger-Tang's request. * Also applied David's patch fixing problems on 64-bit architectures. * Now using scanner's reported speed to guage amount of data to request * in a read on the scsi fd---nonblocking mode operates better now. * Fixed stupid bug I introduced in preview mode data transfer. * * Revision 1.15 1998/01/22 06:18:57 charter * Raised the priority of a couple of DBG messages in reserve_unit() * and release_unit(), and got rid of some unecessary ones. * * Revision 1.14 1998/01/22 05:15:35 charter * Have replaced the bit depth option with a mode option; various * changes associated with that. * Also, I again close the STDERR_FILENO in the reader child and * dup the STDOUT file descriptor onto it. This prevents an "X io" * error when the child exits, while still allowing the use of * DBG. * * Revision 1.13 1998/01/21 20:41:22 charter * Added copyright info. * Also now seem to have cancellation working. This requires using a * new scanner state variable and checking in all the right places * in the reader child and the sane_snapscan_read function. I've * tested it using both blocking and nonblocking I/O and it seems * to work both ways. * I've also switched to GTK+-0.99.2 and sane-0.69, and the * mysterious problems with the preview window have disappeared. * Problems with scanimage doing weird things to options have also * gone away and the frontends seem more stable. * * Revision 1.12 1998/01/21 11:05:53 charter * Inoperative code largely #defined out; I had the preview window * working correctly by having the window coordinates properly * constrained, but now the preview window bombs with a floating- * point error each time... I'm not sure yet what happened. * I've also figured out that we need to use reserve_unit and * release_unit in order to cancel scans in progress. This works * under scanimage, but I can't seem to find a way to fit cancellation * into xscanimage properly. * * Revision 1.11 1998/01/20 22:42:08 charter * Applied Franck's patch from Dec 17; preview mode is now grayscale. * * Revision 1.10 1997/12/10 23:33:12 charter * Slight change to some floating-point computations in the brightness * and contrast stuff. The controls don't seem to do anything to the * scanner though (I think these aren't actually supported in the * SnapScan). * * Revision 1.9 1997/11/26 15:40:50 charter * Brightness and contrast added by Michel. * * Revision 1.8 1997/11/12 12:55:40 charter * No longer exec after forking to do nonblocking scanning; found how * to fix the problems with SIGPIPEs from before. * Now support a config file like the other scanner drivers, and * can check whether a given device is an AGFA SnapScan (mini_inquiry()). * * Revision 1.7 1997/11/10 05:52:08 charter * Now have the child reader process and pipe stuff working, and * nonblocking mode. For large scans the nonblocking mode actually * seems to cut down on cpu hogging (though there is still a hit). * * Revision 1.6 1997/11/03 07:45:54 charter * Added the predef_window stuff. I've tried it with 6x4, and it seems * to work; I think something gets inconsistent if a preview is * performed though. * * Revision 1.5 1997/11/03 03:15:27 charter * Global static variables have now become part of the scanner structure; * the inquiry command automatically retrieves window parameters into * scanner structure members. Things are a bit cleaned up. * * Revision 1.4 1997/11/02 23:35:28 charter * After much grief.... I can finally scan reliably. Now it's a matter * of getting the band arrangement sorted out. * * Revision 1.3 1997/10/30 07:36:37 charter * Fixed a stupid bug in the #defines for the inquiry command, pointed out * by Franck. * * Revision 1.2 1997/10/14 06:00:11 charter * Option manipulation and some basic SCSI commands done; the basics * for scanning are written but there are bugs. A full scan always hangs * the SCSI driver, and preview mode scans complete but it isn't clear * whether any meaningful data is received. * * Revision 1.1 1997/10/13 02:25:54 charter * Initial revision * */ sane-backends-1.0.27/backend/plustek-pp.h0000664000175000017500000005151512775277260015114 00000000000000/** @file plustek-pp.h * @brief Definitions for the backend. * * Based on Kazuhiro Sasayama previous * Work on plustek.[ch] file from the SANE package.
* * original code taken from sane-0.71
* Copyright (C) 1997 Hypercore Software Design, Ltd.
* Copyright (C) 2001-2013 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.43 - bumped up version to reflect the former module code version * - removed Version from ScannerCaps * - added _E_FAULT * - 0.44 - fix UL issues, as Long types default to int32_t now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __PLUSTEKPP_H__ #define __PLUSTEKPP_H__ /*............................................................................. * the structures for driver communication */ typedef struct { unsigned short x; unsigned short y; } XY, *pXY; typedef struct { unsigned short x; unsigned short y; unsigned short cx; unsigned short cy; } CropRect, *pCropRect; typedef struct image { unsigned long dwFlag; CropRect crArea; XY xyDpi; unsigned short wDataType; } ImgDef, *pImgDef; typedef struct { unsigned long dwPixelsPerLine; unsigned long dwBytesPerLine; unsigned long dwLinesPerArea; struct image ImgDef; } CropInfo, *pCropInfo; /** definition of gamma maps */ typedef struct { int len; /**< gamma table len */ int depth; /**< entry bit depth */ int map_id; /**< what map */ void *map; /**< pointer for map */ } MapDef, *pMapDef; /** for offset stuff */ typedef struct { int x; int y; } OffsDef, *pOffsDef; /** useful for description tables */ typedef struct { int id; char *desc; } TabDef, *pTabDef; /** for defining the scanmodes */ typedef const struct mode_param { int color; int depth; int scanmode; } ModeParam, *pModeParam; /** */ #define SFLAG_ADF 0x00000010 /* Automatic document feeder */ #define SFLAG_MFP 0x00000020 /* MF-Keypad support */ #define SFLAG_SheetFed 0x00000040 /* Sheetfed support */ #define SFLAG_TPA 0x00000080 /* has transparency adapter */ #define SFLAG_CUSTOM_GAMMA 0x00000200 /* driver supports custom gamma */ /** */ #define SCANDEF_Inverse 0x00000001 #define SCANDEF_UnlimitLength 0x00000002 #define SCANDEF_StopWhenPaperOut 0x00000004 #define SCANDEF_BoundaryDWORD 0x00000008 #define SCANDEF_ColorBGROrder 0x00000010 #define SCANDEF_BmpStyle 0x00000020 #define SCANDEF_BoundaryWORD 0x00000040 #define SCANDEF_NoMap 0x00000080 /* specified this flag will */ /* cause system ignores the */ /* siBrightness & siContrast */ #define SCANDEF_Transparency 0x00000100 /* Scanning from transparency*/ #define SCANDEF_Negative 0x00000200 /* Scanning from negative */ #define SCANDEF_QualityScan 0x00000400 /* Scanning in quality mode */ #define SCANDEF_BuildBwMap 0x00000800 /* Set default map */ #define SCANDEF_ContinuousScan 0x00001000 #define SCANDEF_DontBackModule 0x00002000 /* module will not back to */ /* home after image scanned */ #define SCANDEF_RightAlign 0x00008000 /* 12-bit */ #define SCANDEF_TPA (SCANDEF_Transparency | SCANDEF_Negative) #define SCANDEF_Adf 0x00020000 /* Scan from ADF tray */ /* these values will be combined with ScannerInfo.dwFlag */ #define _SCANNER_SCANNING 0x8000000 #define _SCANNER_PAPEROUT 0x4000000 /* for GetLensInformation */ #if 0 #define SOURCE_Reflection 0 #define SOURCE_Transparency 1 #define SOURCE_Negative 2 #define SOURCE_ADF 3 #endif /****************************************************************************** * Section 6 - additional definitions */ /* scan modes */ #define COLOR_BW 0 #define COLOR_HALFTONE 1 #define COLOR_256GRAY 2 #define COLOR_TRUE24 3 #define COLOR_TRUE32 4 #define COLOR_TRUE48 4 /* not sure if this should be the same as 32 */ #define COLOR_TRUE36 5 /* We don't support halftone mode now --> Plustek statement for USB */ #define COLOR_GRAY16 6 #define _MEASURE_BASE 300UL /** transparency/negative mode set ranges */ #define _TPAPageWidth 500U /* org. was 450 = 38.1 mm */ #define _TPAPageHeight 510U /* org. was 460 = 38.9 mm */ #define _TPAModeSupportMin COLOR_TRUE24 #define _TPAModeSupportMax COLOR_TRUE48 #define _TPAModeSupportDef COLOR_TRUE24 #define _TPAMinDpi 150 #define _NegativePageWidth 460U /* 38.9 mm */ #define _NegativePageHeight 350U /* 29.6 mm */ #define _DEF_DPI 50 /* * additional shared stuff between user-world and kernel mode */ #define _VAR_NOT_USED(x) ((x)=(x)) /* * for Gamma tables */ #define _MAP_RED 0 #define _MAP_GREEN 1 #define _MAP_BLUE 2 #define _MAP_MASTER 3 /* * generic error codes... */ #define _OK 0 #define _FIRST_ERR -9000 #define _E_INIT (_FIRST_ERR-1) /* already initialized */ #define _E_NOT_INIT (_FIRST_ERR-2) /* not initialized */ #define _E_NULLPTR (_FIRST_ERR-3) /* internal NULL-PTR detected */ #define _E_ALLOC (_FIRST_ERR-4) /* error allocating memory */ #define _E_TIMEOUT (_FIRST_ERR-5) /* signals a timeout condition */ #define _E_INVALID (_FIRST_ERR-6) /* invalid parameter detected */ #define _E_INTERNAL (_FIRST_ERR-7) /* internal error */ #define _E_BUSY (_FIRST_ERR-8) /* device is already in use */ #define _E_ABORT (_FIRST_ERR-9) /* operation aborted */ #define _E_LOCK (_FIRST_ERR-10) /* can't lock resource */ #define _E_NOSUPP (_FIRST_ERR-11) /* feature or device not supported */ #define _E_NORESOURCE (_FIRST_ERR-12) /* out of memo, resource busy... */ #define _E_VERSION (_FIRST_ERR-19) /* version conflict */ #define _E_NO_DEV (_FIRST_ERR-20) /* device does not exist */ #define _E_NO_CONN (_FIRST_ERR-21) /* nothing connected */ #define _E_PORTSEARCH (_FIRST_ERR-22) /* parport_enumerate failed */ #define _E_NO_PORT (_FIRST_ERR-23) /* requested port does not exist */ #define _E_REGISTER (_FIRST_ERR-24) /* cannot register this device */ #define _E_SEQUENCE (_FIRST_ERR-30) /* caller sequence does not match */ #define _E_NO_ASIC (_FIRST_ERR-31) /* can't detect ASIC */ #ifdef __KERNEL__ # define _E_FAULT (-EFAULT) #else # define _E_FAULT (_E_INTERNAL) /* should never happen in userspace */ #endif #define _E_LAMP_NOT_IN_POS (_FIRST_ERR-40) #define _E_LAMP_NOT_STABLE (_FIRST_ERR-41) #define _E_NODATA (_FIRST_ERR-42) #define _E_BUFFER_TOO_SMALL (_FIRST_ERR-43) #define _E_DATAREAD (_FIRST_ERR-44) /************************ some definitions ***********************************/ /* NOTE: needs to be kept in sync with table below */ #define MODELSTR static char *ModelStr[] = { \ "unknown", \ "Primax 4800", \ "Primax 4800 Direct", \ "Primax 4800 Direct 30Bit", \ "Primax 9600 Direct 30Bit", \ "4800P", \ "4830P", \ "600P/6000P", \ "4831P", \ "9630P", \ "9630PL", \ "9636P", \ "A3I", \ "12000P/96000P", \ "9636P+/Turbo", \ "9636T/12000T", \ "P8", \ "P12", \ "PT12", \ "Genius Colorpage Vivid III V2", \ "USB-Device" \ } /* the models */ #define MODEL_OP_UNKNOWN 0 /* unknown */ #define MODEL_PMX_4800 1 /* Primax Colorado 4800 like OP 4800 */ #define MODEL_PMX_4800D 2 /* Primax Compact 4800 Direct, OP 600 R->G, G->R */ #define MODEL_PMX_4800D3 3 /* Primax Compact 4800 Direct 30 */ #define MODEL_PMX_9600D3 4 /* Primax Compact 9600 Direct 30 */ #define MODEL_OP_4800P 5 /* 32k, 96001 ASIC, 24 bit, 300x600, 8.5x11.69 */ #define MODEL_OP_4830P 6 /* 32k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */ #define MODEL_OP_600P 7 /* 32k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */ #define MODEL_OP_4831P 8 /* 128k, 96003 ASIC, 30 bit, 300x600, 8.5x11.69 */ #define MODEL_OP_9630P 9 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x11.69 */ #define MODEL_OP_9630PL 10 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x14 */ #define MODEL_OP_9636P 11 /* 512k, 98001 ASIC, 36 bit, 600x1200, 8.5x11.69 */ #define MODEL_OP_A3I 12 /* 128k, 96003 ASIC, 30 bit, 400x800, 11.69x17 */ #define MODEL_OP_12000P 13 /* 128k, 96003 ASIC, 30 bit, 600x1200, 8.5x11.69 */ #define MODEL_OP_9636PP 14 /* 512k, 98001 ASIC, 36 bit, 600x1200, 8.5x11.69 */ #define MODEL_OP_9636T 15 /* like OP_9636PP + transparency */ #define MODEL_OP_P8 16 /* 512k, 98003 ASIC, 36 bit, 300x600, 8.5x11.69 */ #define MODEL_OP_P12 17 /* 512k, 98003 ASIC, 36 bit, 600x1200, 8.5x11.69 */ #define MODEL_OP_PT12 18 /* like OP_P12 + transparency */ #define MODEL_GEN_CPV2 19 /* Genius Colorpage Vivid III V2, ASIC 98003 */ #define MODEL_UNKNOWN 20 /* not known/supported */ #define _NO_BASE 0xFFFF /******************** from former plustek-share.h ***************************/ /* * for other OS than Linux, we might have to define the _IO macros */ #ifndef _IOC #define _IOC(dir,type,nr,size) \ (((dir) << 30) | \ ((type) << 8) | \ ((nr) << 0) | \ ((size) << 16)) #endif #ifndef _IOC_DIR #define _IOC_DIR(cmd) (((cmd) >> 30) & 0x3) #endif #ifndef _IOC_SIZE #define _IOC_SIZE(cmd) (((cmd) >> 16) & 0x3FFF) #endif #ifndef _IOC_WRITE #define _IOC_WRITE 1U #endif #ifndef _IO #define _IO(type,nr) _IOC(0U,(type),(nr),0) #endif #ifndef _IOR #define _IOR(type,nr,size) _IOC(2U,(type),(nr),((UInt)sizeof(size))) #endif #ifndef _IOW #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),((UInt)sizeof(size))) #endif #ifndef _IOWR #define _IOWR(type,nr,size) _IOC(3U,(type),(nr),((UInt)sizeof(size))) #endif /*............................................................................. * the ioctl interface */ #define _PTDRV_OPEN_DEVICE _IOW('x', 1, unsigned short)/* open */ #define _PTDRV_GET_CAPABILITIES _IOR('x', 2, ScannerCaps) /* get caps */ #define _PTDRV_GET_LENSINFO _IOR('x', 3, LensInfo) /* get lenscaps */ #define _PTDRV_PUT_IMAGEINFO _IOW('x', 4, ImgDef) /* put image info*/ #define _PTDRV_GET_CROPINFO _IOR('x', 5, CropInfo) /* get crop */ #define _PTDRV_SET_ENV _IOWR('x',6, ScanInfo) /* set env. */ #define _PTDRV_START_SCAN _IOR('x', 7, StartScan) /* start scan */ #define _PTDRV_STOP_SCAN _IOWR('x', 8, short) /* stop scan */ #define _PTDRV_CLOSE_DEVICE _IO('x', 9) /* close */ #define _PTDRV_ACTION_BUTTON _IOR('x', 10, unsigned char)/* rd act. button*/ #define _PTDRV_ADJUST _IOR('x', 11, AdjDef) /* adjust driver */ #define _PTDRV_SETMAP _IOR('x', 12, MapDef) /* download gamma*/ /* * this version MUST match the one inside the driver to make sure, that * both sides use the same structures. This version changes each time * the ioctl interface changes */ #define _PTDRV_COMPAT_IOCTL_VERSION 0x0102 #define _PTDRV_IOCTL_VERSION 0x0104 /** for adjusting the parport stuff */ typedef struct { int lampOff; int lampOffOnEnd; int warmup; int enableTpa; OffsDef pos; /* for adjusting normal scan area */ OffsDef tpa; /* for adjusting transparency scan area */ OffsDef neg; /* for adjusting negative scan area */ /* for adjusting the default gamma settings */ double rgamma; double ggamma; double bgamma; double graygamma; } PPAdjDef, *pPPAdjDef; /** for adjusting the scanner settings */ typedef struct { int direct_io; int mov; int lampOff; int lampOffOnEnd; int warmup; OffsDef pos; /* for adjusting normal scan area */ OffsDef tpa; /* for adjusting transparency scan area */ OffsDef neg; /* for adjusting negative scan area */ /* for adjusting the default gamma settings */ double rgamma; double ggamma; double bgamma; double graygamma; } AdjDef, *pAdjDef; typedef struct { unsigned long dwFlag; /* refer to SECTION (1.2) */ unsigned long dwBytesPerLine; unsigned long dwLinesPerScan; } StartScan, *pStartScan; typedef struct { unsigned short wMin; /* minimum value */ unsigned short wDef; /* default value */ unsigned short wMax; /* software maximum value */ unsigned short wPhyMax; /* hardware maximum value (for DPI only)*/ } RANGE, *PRANGE; typedef struct { RANGE rDataType; /* available scan modes */ unsigned long dwFlag; /* refer to SECTION (1.2) */ unsigned short wIOBase; /* refer to SECTION (1.3) */ unsigned short wMaxExtentX; /* scanarea width */ unsigned short wMaxExtentY; /* scanarea height */ unsigned short AsicID; /* copy of RegAsicID */ unsigned short Model; /* model as best we can determine */ } ScannerCaps, *pScannerCaps; typedef struct { RANGE rDpiX; RANGE rDpiY; RANGE rExtentX; RANGE rExtentY; unsigned short wBeginX; /* offset from left */ unsigned short wBeginY; /* offset from top */ } LensInfo, *pLensInfo; typedef struct { unsigned char* pDither; void* pMap; ImgDef ImgDef; unsigned short wMapType; /* refer to SECTION (3.2) */ unsigned short wDither; /* refer to SECTION (3.3) */ short siBrightness; /* refer to SECTION (3.5) */ short siContrast; /* refer to SECTION (3.6) */ } ScanInfo, *pScanInfo; /* IDs the ASIC returns */ #define _ASIC_IS_96001 0x0f /* value for 96001 */ #define _ASIC_IS_96003 0x10 /* value for 96003 */ #define _ASIC_IS_98001 0x81 /* value for 98001 */ #define _ASIC_IS_98003 0x83 /* value for 98003 */ #define _Transparency48OriginOffsetX 375 #define _Transparency48OriginOffsetY 780 #define _Transparency96OriginOffsetX 0x03DB /* org. was 0x0430 */ #define _Negative96OriginOffsetX 0x03F3 /* org. was 0x0428 */ /** Scanmodes */ #define _ScanMode_Color 0 #define _ScanMode_AverageOut 1 /* CCD averaged 2 pixels value for output*/ #define _ScanMode_Mono 2 /* not color mode */ #ifndef __KERNEL__ #define PLUSTEK_CONFIG_FILE "plustek_pp.conf" #ifndef PATH_MAX # define PATH_MAX 1024 #endif /* * the default image size */ #define _DEFAULT_TLX 0 /* 0..216 mm */ #define _DEFAULT_TLY 0 /* 0..297 mm */ #define _DEFAULT_BRX 126 /* 0..216 mm*/ #define _DEFAULT_BRY 76.21 /* 0..297 mm */ #define _DEFAULT_TP_TLX 3.5 /* 0..42.3 mm */ #define _DEFAULT_TP_TLY 10.5 /* 0..43.1 mm */ #define _DEFAULT_TP_BRX 38.5 /* 0..42.3 mm */ #define _DEFAULT_TP_BRY 33.5 /* 0..43.1 mm */ #define _DEFAULT_NEG_TLX 1.5 /* 0..38.9 mm */ #define _DEFAULT_NEG_TLY 1.5 /* 0..29.6 mm */ #define _DEFAULT_NEG_BRX 37.5 /* 0..38.9 mm */ #define _DEFAULT_NEG_BRY 25.5 /* 0..29.6 mm */ /** image sizes for normal, transparent and negative modes */ #define _TP_X ((double)_TPAPageWidth/300.0 * MM_PER_INCH) #define _TP_Y ((double)_TPAPageHeight/300.0 * MM_PER_INCH) #define _NEG_X ((double)_NegativePageWidth/300.0 * MM_PER_INCH) #define _NEG_Y ((double)_NegativePageHeight/300.0 * MM_PER_INCH) /************************ some structures ************************************/ enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_EXT_MODE, OPT_RESOLUTION, OPT_PREVIEW, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_ENHANCEMENT_GROUP, OPT_HALFTONE, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_CUSTOM_GAMMA, OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, NUM_OPTIONS }; /** for compatiblity to version 0x0102 drivers */ typedef struct { int lampOff; int lampOffOnEnd; int warmup; OffsDef pos; /* for adjusting normal scan area */ OffsDef tpa; /* for adjusting transparency scan area */ OffsDef neg; /* for adjusting negative scan area */ } CompatAdjDef, *pCompatAdjDef; /** */ typedef struct Plustek_Device { SANE_Int initialized; /* device already initialized? */ struct Plustek_Device *next; /* pointer to next dev in list */ int fd; /* device handle */ char *name; /* (to avoid compiler warnings!)*/ SANE_Device sane; /* info struct */ SANE_Int max_x; /* max XY-extension of the scan-*/ SANE_Int max_y; /* area */ SANE_Range dpi_range; /* resolution range */ SANE_Range x_range; /* x-range of the scan-area */ SANE_Range y_range; /* y-range of the scan-area */ SANE_Int *res_list; /* to hold the available phys. */ SANE_Int res_list_size; /* resolution values */ ScannerCaps caps; /* caps reported by the driver */ AdjDef adj; /* for driver adjustment */ /* * each device we support may need other access functions... */ int (*open) ( const char*, void* ); int (*close) ( struct Plustek_Device* ); void (*shutdown) ( struct Plustek_Device* ); int (*getCaps) ( struct Plustek_Device* ); int (*getLensInfo)( struct Plustek_Device*, pLensInfo ); int (*getCropInfo)( struct Plustek_Device*, pCropInfo ); int (*putImgInfo) ( struct Plustek_Device*, pImgDef ); int (*setScanEnv) ( struct Plustek_Device*, pScanInfo ); int (*setMap) ( struct Plustek_Device*, SANE_Word*, SANE_Word, SANE_Word ); int (*startScan) ( struct Plustek_Device*, pStartScan ); int (*stopScan) ( struct Plustek_Device*, short* ); int (*readImage) ( struct Plustek_Device*, SANE_Byte*, unsigned long ); int (*prepare) ( struct Plustek_Device*, SANE_Byte* ); int (*readLine) ( struct Plustek_Device* ); } Plustek_Device, *pPlustek_Device; #ifndef SANE_OPTION /* for compatibility with older versions */ typedef union { SANE_Word w; SANE_Word *wa; /* word array */ SANE_String s; } Option_Value; #endif typedef struct Plustek_Scanner { struct Plustek_Scanner *next; SANE_Pid reader_pid; /* process id of reader */ SANE_Status exit_code; /* status of the reader process */ int r_pipe; /* pipe to reader process */ int w_pipe; /* pipe from reader process */ unsigned long bytes_read; /* number of bytes currently read*/ Plustek_Device *hw; /* pointer to current device */ Option_Value val[NUM_OPTIONS]; SANE_Byte *buf; /* the image buffer */ SANE_Bool scanning; /* TRUE during scan-process */ SANE_Parameters params; /* for keeping the parameter */ /************************** gamma tables *********************************/ SANE_Word gamma_table[4][4096]; SANE_Range gamma_range; int gamma_length; SANE_Option_Descriptor opt[NUM_OPTIONS]; } Plustek_Scanner, *pPlustek_Scanner; /** for collecting configuration info... */ typedef struct { char devName[PATH_MAX]; /* contains the stuff to adjust... */ AdjDef adj; } CnfDef, *pCnfDef; #endif /* guard __KERNEL__ */ #endif /* guard __PLUSTEKPP_H__ */ /* END PLUSTEK-PP.H .........................................................*/ sane-backends-1.0.27/backend/plustek-pp_scan.h0000664000175000017500000001532512775312261016106 00000000000000/* @file plustek-pp_scan.h * @brief the global header for the plustek driver * * Copyright (C) 2000-2013 Gerhard Jaeger * * History: * 0.30 - initial version * 0.31 - no changes * 0.32 - changed _DODELAY macro to work properly for delays > 5 ms * 0.33 - no changes * 0.34 - no changes * 0.35 - removed _PTDRV_PUT_SCANNER_MODEL from ioctl interface * 0.36 - now including plustek-share.h from the backend path * changed _INB/_OUTB to _INB_STATUS, _INB_CTRL, _INB_DATA ... * 0.37 - added _OUTB_ECTL/_INB_ECTL, _MAX_PTDEVS, _DRV_NAME and _MAX_BTNS * added _OUTB_STATUS * 0.38 - added _IS_ASIC96() and _IS_ASIC98() macros * 0.39 - no changes * 0.40 - no changes * 0.41 - no changes * 0.42 - changed include names * 0.43 - no changes * 0.44 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __PLUSTEK_SCAN_H__ #define __PLUSTEK_SCAN_H__ #ifndef __KERNEL__ # include # include # include # include # include # include # ifdef HAVE_SYS_SIGNAL_H # include # else # include # endif # include # ifdef HAVE_SYS_IO_H # include # endif #else # include # include # include # include "plustek-pp_sysdep.h" # include # include #ifdef LINUX_24 # include #endif /* LINUX_24 */ #endif /* __KERNEL__ */ /*............................................................................. * driver properties */ #define _DRV_NAME "pt_drv" /**< driver's name */ #define _MAX_PTDEVS 4 /**< support for 4 devices */ #define _MAX_BTNS 6 /**< support for 6 buttons */ #define _PTDRV_MAJOR 40 /**< our major number */ /*............................................................................. * for port operations */ # define _OPF ps->IO.fnOut # define _IPF ps->IO.fnIn #ifdef __KERNEL__ #define _OUTB_CTRL(pSD,port_value) _OPF(port_value,pSD->IO.pbControlPort) #define _OUTB_DATA(pSD,port_value) _OPF(port_value,pSD->IO.pbSppDataPort) #define _OUTB_ECTL(pSD,port_value) _OPF(port_value,(pSD->IO.portBase+0x402)) #define _INB_CTRL(pSD) _IPF(pSD->IO.pbControlPort) #define _INB_DATA(pSD) _IPF(pSD->IO.pbSppDataPort) #define _INB_EPPDATA(pSD) _IPF(pSD->IO.pbEppDataPort) #define _INB_STATUS(pSD) _IPF(pSD->IO.pbStatusPort) #define _INB_ECTL(pSD) _IPF((pSD->IO.portBase+0x402)) #else #define _OUTB_CTRL(pSD,port_value) sanei_pp_outb_ctrl(pSD->pardev, port_value) #define _OUTB_DATA(pSD,port_value) sanei_pp_outb_data(pSD->pardev, port_value) #define _OUTB_ECTL(pSD,port_value) #define _INB_CTRL(pSD) sanei_pp_inb_ctrl(pSD->pardev) #define _INB_DATA(pSD) sanei_pp_inb_data(pSD->pardev) #define _INB_EPPDATA(pSD) sanei_pp_inb_epp(pSD->pardev) #define _INB_STATUS(pSD) sanei_pp_inb_stat(pSD->pardev) #endif /*............................................................................. * for memory allocation */ #ifndef __KERNEL__ # define _KALLOC(x,y) malloc(x) # define _KFREE(x) free(x) # define _VMALLOC(x) malloc(x) # define _VFREE(x) free(x) #else # define _KALLOC(x,y) kmalloc(x,y) # define _KFREE(x) kfree(x) # define _VMALLOC(x) vmalloc(x) # define _VFREE(x) vfree(x) #endif /* * WARNING - never use the _SECOND define with the _DODELAY macro !! * they are for use the MiscStartTimer function and the _DO_UDELAY macro */ #ifndef __KERNEL__ typedef double TimerDef, *pTimerDef; #else typedef long long TimerDef, *pTimerDef; #endif #define _MSECOND 1000 /* based on 1 us */ #define _SECOND (1000*_MSECOND) /*............................................................................. * timer topics */ #ifndef __KERNEL__ # define _DO_UDELAY(usecs) sanei_pp_udelay(usecs) # define _DODELAY(msecs) { int i; for( i = msecs; i--; ) _DO_UDELAY(1000); } #else # define _DO_UDELAY(usecs) udelay(usecs) # define _DODELAY(msecs) mdelay(msecs) #endif /*............................................................................. * include the shared stuff right here, this concerns the ioctl interface * and the communication stuff */ #include "plustek-pp.h" /*............................................................................. * WARNING: don't move the following headers above the previous defines !!!!!!! * * the include files for user-mode and kernel-mode program */ #include "plustek-pp_types.h" #include "plustek-pp_hwdefs.h" #include "plustek-pp_scandata.h" #include "plustek-pp_procs.h" #include "plustek-pp_dbg.h" /*............................................................................. * some macros for convenience */ #define _IS_ASIC96(aid) ((_ASIC_IS_96001 == aid) || (_ASIC_IS_96003 == aid)) #define _IS_ASIC98(aid) ((_ASIC_IS_98001 == aid) || (_ASIC_IS_98003 == aid)) #endif /* guard __PLUSTEK_SCAN_H__ */ /* END PLUSTEK-PP_SCAN.H ....................................................*/ sane-backends-1.0.27/backend/niash_xfer.h0000664000175000017500000000515412112021330015076 00000000000000/* Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. $Id$ */ /* Provides a simple interface to read and write data from the scanner, without any knowledge whether it's a parallel or USB scanner */ #ifndef _NIASH_XFER_H_ #define _NIASH_XFER_H_ #include /* for FILE * */ /* register codes for the USB - IEEE1284 bridge */ #define USB_SETUP 0x82 #define EPP_ADDR 0x83 #define EPP_DATA_READ 0x84 #define EPP_DATA_WRITE 0x85 #define SPP_STATUS 0x86 #define SPP_CONTROL 0x87 #define SPP_DATA 0x88 typedef enum { eUnknownModel = 0, eHp3300c, eHp3400c, eHp4300c, eAgfaTouch } EScannerModel; typedef struct { char *pszVendor; char *pszName; int iVendor; int iProduct; EScannerModel eModel; } TScannerModel; typedef int (TFnReportDevice) (TScannerModel * pModel, const char *pszDeviceName); /* Creates our own DBG definitions, externs are define in main.c*/ #ifndef WITH_NIASH #define DBG fprintf extern FILE *DBG_MSG; extern FILE *DBG_ERR; extern FILE *BG_ASSERT; #endif /* NO WITH_NIASH */ /* we do not make data prototypes */ #ifndef WITH_NIASH /* list of supported models, the actual list is in niash_xfer.c */ extern TScannerModel ScannerModels[]; #endif /* NO WITH_NIASH */ STATIC void NiashXferInit (TFnReportDevice * pfnReport); STATIC int NiashXferOpen (const char *pszName, EScannerModel * peModel); STATIC void NiashXferClose (int iXferHandle); STATIC void NiashWriteReg (int iXferHandle, unsigned char bReg, unsigned char bData); STATIC void NiashReadReg (int iXferHandle, unsigned char bReg, unsigned char *pbData); STATIC void NiashWriteBulk (int iXferHandle, unsigned char *pabBuf, int iSize); STATIC void NiashReadBulk (int iXferHandle, unsigned char *pabBuf, int iSize); STATIC void NiashWakeup (int iXferHandle); STATIC SANE_Bool MatchUsbDevice (int iVendor, int iProduct, TScannerModel ** ppeModel); #endif /* _NIASH_XFER_H_ */ sane-backends-1.0.27/backend/net.conf.in0000664000175000017500000000107512112021330014637 00000000000000# This is the net backend config file. ## net backend options # Timeout for the initial connection to saned. This will prevent the backend # from blocking for several minutes trying to connect to an unresponsive # saned host (network outage, host down, ...). Value in seconds. # connect_timeout = 60 ## saned hosts # Each line names a host to attach to. # If you list "localhost" then your backends can be accessed either # directly or through the net backend. Going through the net backend # may be necessary to access devices that need special privileges. # localhost sane-backends-1.0.27/backend/hp.README0000664000175000017500000000467512112021330014074 00000000000000Fri Dec 5 18:10:52 PST 1997 Geoffrey T. Dairiki Here is a new HP backend. It's name is, appropriately, ``newhp''. It is still in the pre-alpha stages but mostly works on my ScanJet 5P. It is completely untested on other scanners, but might hopefully work on ScanJet models IIp, IIc, IIcx, 3p, 3c, 4c, 4p, and 5p. I've only really tested this with xscanimage. Some features included in this backend which aren't in the old HP driver are: Support for custom tonemaps (gamma-maps). For some reason I can't get the 10-bit tonemaps working with my 5p, so for you only get a single tonemap (it still works in color mode, but you don't get individual control over each R/G/B channel.) You can enable the scanjets "Auto Threshold" mode when scanning line-art. I can't notice that it does much though.... Added an option to control the scan speed. Added an option to select the dither pattern used in half-tone mode. I don't think that custom dither patterns are working correctly, and in any case, with the current front-ends, there is no convenient way to set a custom dither pattern.... Added an option to select the color correction matrixes. This also seems to be flaky. Again the current front-ends do not provide a decent way to adjust the custom color matrix. Tue Feb 24 20:00:00 UT+1 1998 Peter Kirchgessner Picked up the sources because they did not find their way to the SANE-package up to now. And because I want to have a better support for the HP Photosmart Photoscanner. Renamed the backend from newhp to xhp just to get a better acceptance. Added an option to perform calibration. Upload and download calibration data Added options for horizontal/vertical mirroring. Vertical mirroring is performed by loading image completely into memory before sending to frontend. Uses SCSI-flushing more often because otherwise the scanner did not accept all of the commands. Test support of commands to be independant from inquired model number. Wed Mar 28 10:00:00 UT+1 1998 Bring it on its way to the SANE-project. Geoffrey accepted to add licence informations to the files as long as noone has to pay for the code. Sun Jun 07 15:00:00 UT+1 1998 Added unload button Fixed problem with custom gamma table Sat Nov 14 14:00:00 UT+1 1998 Show calibrate button on Photosmart only for print media Add HP 6200 C Suppress halftone mode on photosmart (it is not supported) sane-backends-1.0.27/backend/epsonds-usb.h0000664000175000017500000000113612775312261015233 00000000000000/* * epsonds-usb.h - Epson ESC/I-2 driver, USB device list. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #include "sane/sane.h" #ifndef _EPSONDS_USB_H_ #define _EPSONDS_USB_H_ #define SANE_EPSONDS_VENDOR_ID (0x4b8) extern SANE_Word epsonds_usb_product_ids[]; extern int epsonds_get_number_of_ids(void); #endif sane-backends-1.0.27/backend/v4l.c0000664000175000017500000010036212775312261013472 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1999 Juergen G. Schimmer Updates and bugfixes (C) 2002 - 2004 Henning Meier-Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for v4l-Devices. */ #define BUILD 5 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include #include /* XXX glibc */ #define BACKEND_NAME v4l #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define V4L_CONFIG_FILE "v4l.conf" #include #include "v4l.h" static const SANE_Device **devlist = NULL; static int num_devices; static V4L_Device *first_dev; static V4L_Scanner *first_handle; static char *buffer; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static const SANE_Range u8_range = { /* min, max, quantization */ 0, 255, 0 }; static SANE_Range x_range = { 0, 338, 2 }; static SANE_Range odd_x_range = { 1, 339, 2 }; static SANE_Range y_range = { 0, 249, 1 }; static SANE_Range odd_y_range = { 1, 250, 1 }; static SANE_Parameters parms = { SANE_FRAME_RGB, 1, /* 1 = Last Frame , 0 = More Frames to come */ 0, /* Number of bytes returned per scan line: */ 0, /* Number of pixels per scan line. */ 0, /* Number of lines for the current scan. */ 8, /* Number of bits per sample. */ }; static SANE_Status attach (const char *devname, V4L_Device ** devp) { V4L_Device *dev; static int v4lfd; static struct video_capability capability; errno = 0; for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; DBG (5, "attach: device %s is already known\n", devname); return SANE_STATUS_GOOD; } DBG (3, "attach: trying to open %s\n", devname); v4lfd = v4l1_open (devname, O_RDWR); if (v4lfd != -1) { if (v4l1_ioctl (v4lfd, VIDIOCGCAP, &capability) == -1) { DBG (1, "attach: ioctl (%d, VIDIOCGCAP,..) failed on `%s': %s\n", v4lfd, devname, strerror (errno)); v4l1_close (v4lfd); return SANE_STATUS_INVAL; } if (!(VID_TYPE_CAPTURE & capability.type)) { DBG (1, "attach: device %s can't capture to memory -- exiting\n", devname); v4l1_close (v4lfd); return SANE_STATUS_UNSUPPORTED; } DBG (2, "attach: found videodev `%s' on `%s'\n", capability.name, devname); v4l1_close (v4lfd); } else { DBG (1, "attach: failed to open device `%s': %s\n", devname, strerror (errno)); return SANE_STATUS_INVAL; } dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devname); if (!dev->sane.name) return SANE_STATUS_NO_MEM; dev->sane.vendor = "Noname"; dev->sane.model = strdup (capability.name); if (!dev->sane.model) return SANE_STATUS_NO_MEM; dev->sane.type = "virtual device"; ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static void update_parameters (V4L_Scanner * s) { /* ??? should be per-device */ x_range.min = 0; x_range.max = s->capability.maxwidth - s->capability.minwidth; x_range.quant = 1; y_range.min = 0; y_range.max = s->capability.maxheight - s->capability.minheight; y_range.quant = 1; odd_x_range.min = s->capability.minwidth; odd_x_range.max = s->capability.maxwidth; if (odd_x_range.max > 767) { odd_x_range.max = 767; x_range.max = 767 - s->capability.minwidth; }; odd_x_range.quant = 1; odd_y_range.min = s->capability.minheight; odd_y_range.max = s->capability.maxheight; if (odd_y_range.max > 511) { odd_y_range.max = 511; y_range.max = 511 - s->capability.minheight; }; odd_y_range.quant = 1; parms.lines = s->window.height; parms.pixels_per_line = s->window.width; switch (s->pict.palette) { case VIDEO_PALETTE_GREY: /* Linear greyscale */ { parms.format = SANE_FRAME_GRAY; parms.depth = 8; parms.bytes_per_line = s->window.width; break; } case VIDEO_PALETTE_RGB24: /* 24bit RGB */ { parms.format = SANE_FRAME_RGB; parms.depth = 8; parms.bytes_per_line = s->window.width * 3; break; } default: { parms.format = SANE_FRAME_GRAY; parms.bytes_per_line = s->window.width; break; } } } static SANE_Status init_options (V4L_Scanner * s) { int i; memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = (SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT); } /* Number of options */ s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].unit = SANE_UNIT_NONE; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[0]); if (!s->val[OPT_MODE].s) return SANE_STATUS_NO_MEM; s->opt[OPT_MODE].size = 1; /* '\0' */ for (i = 0; mode_list[i] != 0; ++i) { int len = strlen(mode_list[i]) + 1; if (s->opt[OPT_MODE].size < len) s->opt[OPT_MODE].size = len; } /* channel */ s->opt[OPT_CHANNEL].name = "channel"; s->opt[OPT_CHANNEL].title = "Channel"; s->opt[OPT_CHANNEL].desc = "Selects the channel of the v4l device (e.g. television " "or video-in."; s->opt[OPT_CHANNEL].type = SANE_TYPE_STRING; s->opt[OPT_CHANNEL].unit = SANE_UNIT_NONE; s->opt[OPT_CHANNEL].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_CHANNEL].constraint.string_list = s->channel; s->val[OPT_CHANNEL].s = strdup (s->channel[0]); if (!s->val[OPT_CHANNEL].s) return SANE_STATUS_NO_MEM; if (s->channel[0] == 0 || s->channel[1] == 0) s->opt[OPT_CHANNEL].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CHANNEL].size = 1; /* '\0' */ for (i = 0; s->channel[i] != 0; ++i) { int len = strlen(s->channel[i]) + 1; if (s->opt[OPT_CHANNEL].size < len) s->opt[OPT_CHANNEL].size = len; } /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x *//* ??? first check if window is settable at all */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_INT; s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL; s->opt[OPT_TL_X].cap |= SANE_CAP_INACTIVE; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_INT; s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL; s->opt[OPT_TL_Y].cap |= SANE_CAP_INACTIVE; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_INT; s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL; s->opt[OPT_BR_X].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &odd_x_range; s->val[OPT_BR_X].w = s->capability.maxwidth; if (s->val[OPT_BR_X].w > 767) s->val[OPT_BR_X].w = 767; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_INT; s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL; s->opt[OPT_BR_Y].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &odd_y_range; s->val[OPT_BR_Y].w = s->capability.maxheight; if (s->val[OPT_BR_Y].w > 511) s->val[OPT_BR_Y].w = 511; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range; s->val[OPT_BRIGHTNESS].w = s->pict.brightness / 256; /* hue */ s->opt[OPT_HUE].name = SANE_NAME_HUE; s->opt[OPT_HUE].title = SANE_TITLE_HUE; s->opt[OPT_HUE].desc = SANE_DESC_HUE; s->opt[OPT_HUE].type = SANE_TYPE_INT; s->opt[OPT_HUE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_HUE].constraint.range = &u8_range; s->val[OPT_HUE].w = s->pict.hue / 256; /* colour */ s->opt[OPT_COLOR].name = "color"; s->opt[OPT_COLOR].title = "Picture color"; s->opt[OPT_COLOR].desc = "Sets the picture's color."; s->opt[OPT_COLOR].type = SANE_TYPE_INT; s->opt[OPT_COLOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_COLOR].constraint.range = &u8_range; s->val[OPT_COLOR].w = s->pict.colour / 256; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &u8_range; s->val[OPT_CONTRAST].w = s->pict.contrast / 256; /* whiteness */ s->opt[OPT_WHITE_LEVEL].name = SANE_NAME_WHITE_LEVEL; s->opt[OPT_WHITE_LEVEL].title = SANE_TITLE_WHITE_LEVEL; s->opt[OPT_WHITE_LEVEL].desc = SANE_DESC_WHITE_LEVEL; s->opt[OPT_WHITE_LEVEL].type = SANE_TYPE_INT; s->opt[OPT_WHITE_LEVEL].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_WHITE_LEVEL].constraint.range = &u8_range; s->val[OPT_WHITE_LEVEL].w = s->pict.whiteness / 256; return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX], *str; size_t len; FILE *fp; authorize = authorize; /* stop gcc from complaining */ DBG_INIT (); DBG (2, "SANE v4l backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); fp = sanei_config_open (V4L_CONFIG_FILE); if (!fp) { DBG (2, "sane_init: file `%s' not accessible (%s), trying /dev/video0\n", V4L_CONFIG_FILE, strerror (errno)); return attach ("/dev/video0", 0); } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ /* Remove trailing space and trailing comments */ for (str = dev_name; *str && !isspace (*str) && *str != '#'; ++str); attach (dev_name, 0); } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { V4L_Device *dev, *next; for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free (dev); } if (NULL != devlist) { free (devlist); devlist = NULL; } DBG (5, "sane_exit: all devices freed\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { V4L_Device *dev; int i; DBG (5, "sane_get_devices\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devname, SANE_Handle * handle) { V4L_Device *dev; V4L_Scanner *s; static int v4lfd; int i; struct video_channel channel; SANE_Status status; int max_channels = MAX_CHANNELS; if (!devname) { DBG (1, "sane_open: devname == 0\n"); return SANE_STATUS_INVAL; } for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { DBG (5, "sane_open: device %s found in devlist\n", devname); break; } if (!devname[0]) dev = first_dev; if (!dev) { DBG (1, "sane_open: device %s doesn't seem to be a v4l " "device\n", devname); return SANE_STATUS_INVAL; } v4lfd = v4l1_open (devname, O_RDWR); if (v4lfd == -1) { DBG (1, "sane_open: can't open %s (%s)\n", devname, strerror (errno)); return SANE_STATUS_INVAL; } s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->user_corner = 0; /* ??? */ s->devicename = devname; s->fd = v4lfd; if (v4l1_ioctl (s->fd, VIDIOCGCAP, &s->capability) == -1) { DBG (1, "sane_open: ioctl (%d, VIDIOCGCAP,..) failed on `%s': %s\n", s->fd, devname, strerror (errno)); v4l1_close (s->fd); return SANE_STATUS_INVAL; } DBG (5, "sane_open: %d channels, %d audio devices\n", s->capability.channels, s->capability.audios); DBG (5, "sane_open: minwidth=%d, minheight=%d, maxwidth=%d, " "maxheight=%d\n", s->capability.minwidth, s->capability.minheight, s->capability.maxwidth, s->capability.maxheight); if (VID_TYPE_CAPTURE & s->capability.type) DBG (5, "sane_open: V4L device can capture to memory\n"); if (VID_TYPE_TUNER & s->capability.type) DBG (5, "sane_open: V4L device has a tuner of some form\n"); if (VID_TYPE_TELETEXT & s->capability.type) DBG (5, "sane_open: V4L device supports teletext\n"); if (VID_TYPE_OVERLAY & s->capability.type) DBG (5, "sane_open: V4L device can overlay its image onto the frame " "buffer\n"); if (VID_TYPE_CHROMAKEY & s->capability.type) DBG (5, "sane_open: V4L device uses chromakey on overlay\n"); if (VID_TYPE_CLIPPING & s->capability.type) DBG (5, "sane_open: V4L device supports overlay clipping\n"); if (VID_TYPE_FRAMERAM & s->capability.type) DBG (5, "sane_open: V4L device overwrites frame buffer memory\n"); if (VID_TYPE_SCALES & s->capability.type) DBG (5, "sane_open: V4L device supports hardware scaling\n"); if (VID_TYPE_MONOCHROME & s->capability.type) DBG (5, "sane_open: V4L device is grey scale only\n"); if (VID_TYPE_SUBCAPTURE & s->capability.type) DBG (5, "sane_open: V4L device can capture parts of the image\n"); if (s->capability.channels < max_channels) max_channels = s->capability.channels; for (i = 0; i < max_channels; i++) { channel.channel = i; if (-1 == v4l1_ioctl (v4lfd, VIDIOCGCHAN, &channel)) { DBG (1, "sane_open: can't ioctl VIDIOCGCHAN %s: %s\n", devname, strerror (errno)); return SANE_STATUS_INVAL; } DBG (5, "sane_open: channel %d (%s), tuners=%d, flags=0x%x, " "type=%d, norm=%d\n", channel.channel, channel.name, channel.tuners, channel.flags, channel.type, channel.norm); if (VIDEO_VC_TUNER & channel.flags) DBG (5, "sane_open: channel has tuner(s)\n"); if (VIDEO_VC_AUDIO & channel.flags) DBG (5, "sane_open: channel has audio\n"); if (VIDEO_TYPE_TV == channel.type) DBG (5, "sane_open: input is TV input\n"); if (VIDEO_TYPE_CAMERA == channel.type) DBG (5, "sane_open: input is camera input\n"); s->channel[i] = strdup (channel.name); if (!s->channel[i]) return SANE_STATUS_NO_MEM; } s->channel[i] = 0; if (-1 == v4l1_ioctl (v4lfd, VIDIOCGPICT, &s->pict)) { DBG (1, "sane_open: can't ioctl VIDIOCGPICT %s: %s\n", devname, strerror (errno)); return SANE_STATUS_INVAL; } DBG (5, "sane_open: brightness=%d, hue=%d, colour=%d, contrast=%d\n", s->pict.brightness, s->pict.hue, s->pict.colour, s->pict.contrast); DBG (5, "sane_open: whiteness=%d, depth=%d, palette=%d\n", s->pict.whiteness, s->pict.depth, s->pict.palette); /* ??? */ s->pict.palette = VIDEO_PALETTE_GREY; if (-1 == v4l1_ioctl (s->fd, VIDIOCSPICT, &s->pict)) { DBG (1, "sane_open: ioctl VIDIOCSPICT failed (%s)\n", strerror (errno)); } if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window)) { DBG (1, "sane_open: can't ioctl VIDIOCGWIN %s: %s\n", devname, strerror (errno)); return SANE_STATUS_INVAL; } DBG (5, "sane_open: x=%d, y=%d, width=%d, height=%d\n", s->window.x, s->window.y, s->window.width, s->window.height); /* already done in sane_start if (-1 == v4l1_ioctl (v4lfd, VIDIOCGMBUF, &mbuf)) DBG (1, "sane_open: can't ioctl VIDIOCGMBUF (no Fbuffer?)\n"); */ status = init_options (s); if (status != SANE_STATUS_GOOD) return status; update_parameters (s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { V4L_Scanner *prev, *s; DBG (2, "sane_close: trying to close handle %p\n", (void *) handle); /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (1, "sane_close: bad handle %p\n", handle); return; /* oops, not a handle we know about */ } if (prev) prev->next = s->next; else first_handle = s->next; if (s->scanning) sane_cancel (handle); v4l1_close (s->fd); free (s); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { V4L_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS || option < 0) return 0; DBG (4, "sane_get_option_descriptor: option %d (%s)\n", option, s->opt[option].name ? s->opt[option].name : s->opt[option].title); return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { V4L_Scanner *s = handle; SANE_Status status; SANE_Word cap; if (info) *info = 0; if (option >= NUM_OPTIONS || option < 0) return SANE_STATUS_INVAL; DBG (4, "sane_control_option: %s option %d (%s)\n", action == SANE_ACTION_GET_VALUE ? "get" : action == SANE_ACTION_SET_VALUE ? "set" : action == SANE_ACTION_SET_AUTO ? "auto set" : "(unknow action with)", option, s->opt[option].name ? s->opt[option].name : s->opt[option].title); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (1, "sane_control option: option is inactive\n"); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_BRIGHTNESS: case OPT_HUE: case OPT_COLOR: case OPT_CONTRAST: case OPT_WHITE_LEVEL: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; case OPT_CHANNEL: /* string list options */ case OPT_MODE: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; default: DBG (1, "sane_control_option: option %d unknown\n", option); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (1, "sane_control_option: option is not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_control_option: sanei_constarin_value failed: %s\n", sane_strstatus (status)); return status; } if (option >= OPT_TL_X && option <= OPT_BR_Y) { s->user_corner |= 1 << (option - OPT_TL_X); if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window)) { DBG (1, "sane_control_option: ioctl VIDIOCGWIN failed " "(can not get window geometry)\n"); return SANE_STATUS_INVAL; } s->window.clipcount = 0; s->window.clips = 0; s->window.height = parms.lines; s->window.width = parms.pixels_per_line; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_TL_X: break; case OPT_TL_Y: break; case OPT_BR_X: s->window.width = *(SANE_Word *) val; parms.pixels_per_line = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BR_Y: s->window.height = *(SANE_Word *) val; parms.lines = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_MODE: if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->pict.palette = VIDEO_PALETTE_GREY; else s->pict.palette = VIDEO_PALETTE_RGB24; update_parameters (s); break; case OPT_BRIGHTNESS: s->pict.brightness = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_HUE: s->pict.hue = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_COLOR: s->pict.colour = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_CONTRAST: s->pict.contrast = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_WHITE_LEVEL: s->pict.whiteness = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_CHANNEL: { int i; struct video_channel channel; s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; for (i = 0; i < MAX_CHANNELS; i++) { if (strcmp (s->channel[i], val) == 0) { channel.channel = i; if (-1 == v4l1_ioctl (s->fd, VIDIOCGCHAN, &channel)) { DBG (1, "sane_open: can't ioctl VIDIOCGCHAN %s: %s\n", s->devicename, strerror (errno)); return SANE_STATUS_INVAL; } if (-1 == v4l1_ioctl (s->fd, VIDIOCSCHAN, &channel)) { DBG (1, "sane_open: can't ioctl VIDIOCSCHAN %s: %s\n", s->devicename, strerror (errno)); return SANE_STATUS_INVAL; } break; } } return SANE_STATUS_GOOD; break; } default: DBG (1, "sane_control_option: option %d unknown\n", option); return SANE_STATUS_INVAL; } if (option >= OPT_TL_X && option <= OPT_BR_Y) { if (-1 == v4l1_ioctl (s->fd, VIDIOCSWIN, &s->window)) { DBG (1, "sane_control_option: ioctl VIDIOCSWIN failed (%s)\n", strerror (errno)); /* return SANE_STATUS_INVAL; */ } if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window)) { DBG (1, "sane_control_option: ioctl VIDIOCGWIN failed (%s)\n", strerror (errno)); return SANE_STATUS_INVAL; } } if (option >= OPT_BRIGHTNESS && option <= OPT_WHITE_LEVEL) { if (-1 == v4l1_ioctl (s->fd, VIDIOCSPICT, &s->pict)) { DBG (1, "sane_control_option: ioctl VIDIOCSPICT failed (%s)\n", strerror (errno)); /* return SANE_STATUS_INVAL; */ } } return SANE_STATUS_GOOD; } else if (action == SANE_ACTION_SET_AUTO) { if (!(cap & SANE_CAP_AUTOMATIC)) { DBG (1, "sane_control_option: option can't be set automatically\n"); return SANE_STATUS_INVAL; } switch (option) { case OPT_BRIGHTNESS: /* not implemented yet */ return SANE_STATUS_GOOD; default: break; } } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { V4L_Scanner *s = handle; DBG (4, "sane_get_parameters\n"); update_parameters (s); if (params == 0) { DBG (1, "sane_get_parameters: params == 0\n"); return SANE_STATUS_INVAL; } if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window)) { DBG (1, "sane_control_option: ioctl VIDIOCGWIN failed " "(can not get window geometry)\n"); return SANE_STATUS_INVAL; } parms.pixels_per_line = s->window.width; parms.bytes_per_line = s->window.width; if (parms.format == SANE_FRAME_RGB) parms.bytes_per_line = s->window.width * 3; parms.lines = s->window.height; *params = parms; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { int len; V4L_Scanner *s; char data; DBG (2, "sane_start\n"); for (s = first_handle; s; s = s->next) { if (s == handle) break; } if (!s) { DBG (1, "sane_start: bad handle %p\n", handle); return SANE_STATUS_INVAL; /* oops, not a handle we know about */ } len = v4l1_ioctl (s->fd, VIDIOCGCAP, &s->capability); if (-1 == len) { DBG (1, "sane_start: can not get capabilities\n"); return SANE_STATUS_INVAL; } s->buffercount = 0; if (-1 == v4l1_ioctl (s->fd, VIDIOCGMBUF, &s->mbuf)) { s->is_mmap = SANE_FALSE; buffer = malloc (s->capability.maxwidth * s->capability.maxheight * s->pict.depth); if (0 == buffer) return SANE_STATUS_NO_MEM; DBG (3, "sane_start: V4L trying to read frame\n"); len = v4l1_read (s->fd, buffer, parms.bytes_per_line * parms.lines); DBG (3, "sane_start: %d bytes read\n", len); } else { int loop; s->is_mmap = SANE_TRUE; DBG (3, "sane_start: mmap frame, buffersize: %d bytes, buffers: %d, offset 0 %d\n", s->mbuf.size, s->mbuf.frames, s->mbuf.offsets[0]); buffer = v4l1_mmap (0, s->mbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, 0); if (buffer == (void *)-1) { DBG (1, "sane_start: mmap failed: %s\n", strerror (errno)); buffer = NULL; return SANE_STATUS_IO_ERROR; } DBG (3, "sane_start: mmapped frame, capture 1 pict into %p\n", buffer); s->mmap.frame = 0; s->mmap.width = s->window.width; /* s->mmap.width = parms.pixels_per_line; ??? huh? */ s->mmap.height = s->window.height; /* s->mmap.height = parms.lines; ??? huh? */ s->mmap.format = s->pict.palette; DBG (2, "sane_start: mmapped frame %d x %d with palette %d\n", s->mmap.width, s->mmap.height, s->mmap.format); /* We need to loop here to empty the read buffers, so we don't get a stale image */ for (loop = 0; loop <= s->mbuf.frames; loop++) { len = v4l1_ioctl (s->fd, VIDIOCMCAPTURE, &s->mmap); if (len == -1) { DBG (1, "sane_start: ioctl VIDIOCMCAPTURE failed: %s\n", strerror (errno)); return SANE_STATUS_INVAL; } DBG (3, "sane_start: waiting for frame %x, loop %d\n", s->mmap.frame, loop); len = v4l1_ioctl (s->fd, VIDIOCSYNC, &(s->mmap.frame)); if (-1 == len) { DBG (1, "sane_start: call to ioctl(%d, VIDIOCSYNC, ..) failed\n", s->fd); return SANE_STATUS_INVAL; } } DBG (3, "sane_start: frame %x done\n", s->mmap.frame); } /* v4l1 actually returns BGR when we ask for RGB, so convert it */ if (s->pict.palette == VIDEO_PALETTE_RGB24) { __u32 loop; DBG (3, "sane_start: converting from BGR to RGB\n"); for (loop = 0; loop < (s->window.width * s->window.height * 3); loop += 3) { data = *(buffer + loop); *(buffer + loop) = *(buffer + loop + 2); *(buffer + loop + 2) = data; } } DBG (3, "sane_start: done\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * lenp) { int i, min; V4L_Scanner *s = handle; DBG (4, "sane_read: max_len = %d\n", max_len); if (!lenp) { DBG (1, "sane_read: lenp == 0\n"); return SANE_STATUS_INVAL; } if ((s->buffercount + 1) > (parms.lines * parms.bytes_per_line)) { *lenp = 0; return SANE_STATUS_EOF; }; min = parms.lines * parms.bytes_per_line; if (min > (max_len + s->buffercount)) min = (max_len + s->buffercount); if (s->is_mmap == SANE_FALSE) { for (i = s->buffercount; i < (min + 0); i++) { *(buf + i - s->buffercount) = *(buffer + i); }; *lenp = (parms.lines * parms.bytes_per_line - s->buffercount); if (max_len < *lenp) *lenp = max_len; DBG (3, "sane_read: transferred %d bytes (from %d to %d)\n", *lenp, s->buffercount, i); s->buffercount = i; } else { for (i = s->buffercount; i < (min + 0); i++) { *(buf + i - s->buffercount) = *(buffer + i); }; *lenp = (parms.lines * parms.bytes_per_line - s->buffercount); if ((i - s->buffercount) < *lenp) *lenp = (i - s->buffercount); DBG (3, "sane_read: transferred %d bytes (from %d to %d)\n", *lenp, s->buffercount, i); s->buffercount = i; } return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { V4L_Scanner *s = handle; DBG (2, "sane_cancel\n"); /* ??? buffer isn't checked in sane_read? */ if (buffer) { if (s->is_mmap) v4l1_munmap(buffer, s->mbuf.size); else free (buffer); buffer = NULL; } } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool non_blocking) { if (non_blocking == SANE_FALSE) return SANE_STATUS_GOOD; return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/teco1.conf.in0000664000175000017500000000054312112021330015063 00000000000000# Relisys RELI 2412 # The scanner respond to all luns. Get only lun 0. scsi "RELISYS" "VM3530+" Scanner * * * 0 # Avec Color Office 2400, 2412 scsi "" "Image Scanner" Scanner # Relisys RELI 4816 scsi "RELISYS" "VM4540" Scanner * * * 0 # Relisys RELI 4830 scsi "RELISYS" "RELI 4830" Scanner # Dextra DF-600P scsi "Dextra DF-600P" Scanner /dev/scanner sane-backends-1.0.27/backend/mustek_usb.h0000664000175000017500000000463612112021330015135 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Mustek. Originally maintained by Tom Wang Copyright (C) 2001, 2002 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek 1200UB and similar USB flatbed scanners. */ #ifndef mustek_usb_h #define mustek_usb_h #include #include "mustek_usb_high.h" #define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE #define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE #define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) #define MUSTEK_USB_CONFIG_FILE "mustek_usb.conf" #define SCAN_BUFFER_SIZE (64 * 1024) #endif /* mustek_usb_h */ sane-backends-1.0.27/backend/u12-hwdef.h0000664000175000017500000003611012112021330014446 00000000000000/** @file u12-hwdef.h * @brief Definitions for the ASIC. * * Copyright (c) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - change _DEF_BW_THRESHOLD * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __U12_HWDEF_H__ #define __U12_HWDEF_H__ #define _LOWORD(x) ((u_short)(x & 0xffff)) #define _HIWORD(x) ((u_short)(x >> 16)) #define _LOBYTE(x) ((SANE_Byte)((x) & 0xFF)) #define _HIBYTE(x) ((SANE_Byte)((x) >> 8)) #define _SET_REG(b,c,r,v) {b[c*2]=r; b[(c*2)+1]=v;c++;} /** some magics for the ASIC */ #define _ID_TO_PRINTER 0x00 #define _ID1ST 0x69 #define _ID2ND 0x96 #define _ID3RD 0xa5 #define _ID4TH 0x5a /** some more for reset... */ #define _RESET1ST 0x69 #define _RESET2ND 0x96 #define _RESET3RD 0xaa #define _RESET4TH 0x55 /** Printer Control Port: Definitions */ #define _CTRL_STROBE 0x01 #define _CTRL_AUTOLF 0x02 #define _CTRL_NOT_INIT 0x04 #define _CTRL_SELECT_IN 0x08 #define _CTRL_ENABLE_IRQ 0x10 #define _CTRL_DIRECTION 0x20 #define _CTRL_RESERVED 0xc0 /** for Asic I/O signal control */ #define _CTRL_GENSIGNAL (_CTRL_RESERVED + _CTRL_NOT_INIT) /* 0xc4 */ #define _CTRL_SIGNAL_REGWRITE (_CTRL_GENSIGNAL + _CTRL_SELECT_IN) /* 0xcc */ #define _CTRL_END_REGWRITE (_CTRL_GENSIGNAL) /* 0xc4 */ #define _CTRL_SIGNAL_DATAWRITE (_CTRL_GENSIGNAL + _CTRL_AUTOLF) /* 0xc6 */ #define _CTRL_END_DATAWRITE (_CTRL_GENSIGNAL) /* 0xc4 */ #define ASIC_ID 0x83 /** the Register set */ #define REG_SWITCHBUS 0x00 #define REG_EPPENABLE 0x01 #define REG_READDATAMODE 0x03 #define REG_WRITEDATAMODE 0x04 #define REG_INITDATAFIFO 0x05 #define REG_FORCESTEP 0x06 #define REG_REFRESHSCANSTATE 0x08 #define REG_WAITSTATEINSERT 0x0a #define REG_RFIFOOFFSET 0x0a #define REG_GFIFOOFFSET 0x0b #define REG_BFIFOOFFSET 0x0c #define REG_STEPCONTROL 0x14 #define REG_MOTOR0CONTROL 0x15 #define REG_XSTEPTIME 0x16 #define REG_GETSCANSTATE 0x17 #define REG_ASICID 0x18 #define REG_MEMORYLO 0x19 #define REG_MEMORYHI 0x1a #define REG_MODECONTROL 0x1b #define REG_LINECONTROL 0x1c #define REG_SCANCONTROL 0x1d #define REG_CONFIG 0x1e #define REG_MODELCONTROL 0x1f #define REG_MODEL1CONTROL 0x20 #define REG_DPILO 0x21 #define REG_DPIHI 0x22 #define REG_SCANPOSLO 0x23 #define REG_SCANPOSHI 0x24 #define REG_WIDTHPIXELLO 0x25 #define REG_WIDTHPIXELHI 0x26 #define REG_THRESHOLDLO 0x27 #define REG_THRESHOLDHI 0x28 #define REG_ADCADDR 0x2a #define REG_ADCDATA 0x2b #define REG_ADCSERIALOUT 0x2d #define REG_RESETCONFIG 0x2e #define REG_STATUS 0x30 #define REG_SCANSTATECONTROL 0x31 #define REG_REDCHDARKOFFSETLO 0x33 #define REG_REDCHDARKOFFSETHI 0x34 #define REG_GREENCHDARKOFFSETLO 0x35 #define REG_GREENCHDARKOFFSETHI 0x36 #define REG_BLUECHDARKOFFSETLO 0x37 #define REG_BLUECHDARKOFFSETHI 0x38 #define REG_FIFOFULLEN0 0x54 #define REG_FIFOFULLEN1 0x55 #define REG_FIFOFULLEN2 0x56 #define REG_MOTORTOTALSTEP0 0x57 #define REG_MOTORTOTALSTEP1 0x58 #define REG_MOTORFREERUNCOUNT0 0x59 #define REG_MOTORFREERUNCOUNT1 0x5a #define REG_SCANCONTROL1 0x5b #define REG_MOTORFREERUNTRIGGER 0x5c #define REG_RESETMTSC 0x5d #define REG_MOTORDRVTYPE 0x64 #define REG_STATUS2 0x66 #define REG_EXTENDEDLINECONTROL 0x6d #define REG_EXTENDEDXSTEP 0x6e #define REG_PLLPREDIV 0x71 #define REG_PLLMAINDIV 0x72 #define REG_PLLPOSTDIV 0x73 #define REG_CLOCKSELECTOR 0x74 #define REG_TESTMODE 0xf0 /* Register RegStepControl (Addr: 0x14) */ #define _MOTOR0_ONESTEP 0x01 #define _MOTOR0_SCANSTATE 0x02 #define _MOTOR_FREERUN 0x40 #define _MOTOR_NOFREERUN 0x00 /* Register RegGetScanState (Addr: 0x17)*/ #define _SCANSTATE_MASK 0x3f /* bit 0-5 */ #define _SCANSTATE_STOP 0x80 /* Register RegMemoryLow/High (Addr: 0x19/0x1a)*/ #define _MAP_ADDR_RED 0x00 #define _MAP_ADDR_GREEN 0x40 #define _MAP_ADDR_BLUE 0x80 #define _MAP_ADDR_SIZE 0x40 /* Register RegModeControl (Addr: 0x1b)*/ #define _ModeScan 0x00 #define _ModeIdle 0x01 #define _ModeShadingMem 0x02 #define _ModeMappingMem 0x03 #define _ModeReadMappingMem 0x07 #define _ModeFifoRSel 0x00 #define _ModeFifoGSel 0x08 #define _ModeFifoBSel 0x10 #define _ModeFifoClose 0x18 /* Register RegLineControl (Addr: 0x1c) */ #define _LINE_SCANTIME_MASK 0x3f /* bit 0-6 */ #define _LINE_CDSINVERSE 0x80 /* Color Drive Signal */ /* Register RegScanControl (Addr: 0x1d) */ #define _SCAN_BITMODE 0x00 #define _SCAN_BYTEMODE 0x01 /* Gray/Color mode */ #define _SCAN_12BITMODE 0x02 #define _SCAN_1ST_AVERAGE 0x04 /* first pixel is averaged pixel */ #define _SCAN_BITDIRR2L 0x08 /* bit shift from right to left */ #define _SCAN_NORMALLAMP_ON 0x10 /* normal Lamp */ #define _SCAN_TPALAMP_ON 0x20 #define _SCAN_DATA_INVERT 0x40 #define _BITALIGN_LEFT 0x80 #define _SCAN_LAMPS_ON (_SCAN_NORMALLAMP_ON | _SCAN_TPALAMP_ON) #define _SCAN_LAMP_MASK _SCAN_LAMPS_ON /* Register RegMotor0Control (Addr: 0x15) */ #define _MotorDirForward 0x01 #define _MotorDirBackward 0x00 #define _MotorOn 0x02 #define _MotorHFullStepH 0x00 #define _MotorHHalfStep 0x04 #define _MotorHQuarterStep 0x08 #define _MotorPowerEnable 0x40 #define _MotorHHomeStop 0x80 #define _DIR_FW 1 #define _DIR_BW 2 #define _DIR_NONE 0 #define _FORWARD_MOTOR (_MotorDirForward + _MotorOn + \ _MotorHQuarterStep + _MotorPowerEnable) #define _BACKWARD_MOTOR (_MotorDirBackward + _MotorOn + _MotorHHomeStop + \ _MotorHQuarterStep + _MotorPowerEnable) /* Register RegConfiguration (Addr: 0x1e) */ #define _P98_CCD_TYPE_ID 0x07 #define _P98_NEC_MACHINE 0x08 #define _P98_PCBID 0xF0 #define _DEF_BW_THRESHOLD 128 /* default B/W mode threshold value */ #define _NUMBER_OF_SCANSTEPS 64 /* Asic spec.: up to 64 scan steps */ #define _SCANSTATE_BYTES (_NUMBER_OF_SCANSTEPS/2) #define _CCD_3797 0 #define _CCD_3799 1 #define _CCD_535 2 #define _CCD_2556 3 #define _CCD_518 4 #define _CCD_539 5 #define _CCD_3777 6 #define _CCD_548 7 /* PCB-IDs (from parport driver)... */ #define _OPTICWORKS2000 0x00 #define _PLUSTEK_SCANNER 0x10 #define _SCANNER_WITH_TPA 0x20 #define _SCANNER4Button 0x30 #define _SCANNER4ButtonTPA 0x40 #define _SCANNER5Button 0x50 #define _SCANNER5ButtonTPA 0x60 #define _SCANNER1Button 0x70 #define _SCANNER1ButtonTPA 0x80 #define _SCANNER2Button 0x90 #define _AGFA_SCANNER 0xf0 #define _AGFA_PCB 0x1f /* Register RegModelControl (Addr: 0x1f) */ #define _HOME_SENSOR_POLARITY 0x01 #define _LED_CONTROL 0x02 #define _LED_ACTIVITY 0x04 #define _MODEL_DPI200 0x00 #define _MODEL_DPI300 0x08 #define _MODEL_DPI400 0x10 #define _MODEL_DPI600 0x18 #define _MODEL_DPI800 0x20 #define _MODEL_DPI1200 0x28 #define _DUMMY_12BIT 0x40 /* Register RegModel1Control (Addr: 0x20) */ #define _SCAN_GRAYTYPE 0x01 #define _CCD_SHIFT_GATE 0x02 #define _CCD_SHIFT_PULSE 0x04 #define _BUTTON_MODE 0x08 #define _MOTOR_2003 0x00 #define _MOTOR_2916 0x10 #define _MOTOR_7042 0x20 /* Register RegThresholdGapControl (Addr: 0x29) */ #define _THRESHOLDGAP_MASK 0x0f /* Register RegResetConfig (Addr: 0x2e) */ #define _ADC_MASK 0x07 #define _DA_WOLFSON8143 0x00 #define _DA_ESIC 0x04 #define _DA_SAMSUNG8531 0x05 #define _DA_WOLFSON8141 0x06 #define _DA_SAMSUNG1224 0x07 #define _MOTOR0_MASK 0x18 #define _MOTOR0_2003 0x00 #define _MOTOR0_2916 0x08 #define _MOTOR0_7042 0x10 #define _MOTOR1_MASK 0x60 #define _MOTOR1_2003 0x00 #define _MOTOR1_2916 0x20 #define _MOTOR1_7042 0x40 /* Status Register (Addr: 0x30) */ #define _FLAG_PAPER 0x01 #define _FLAG_KEY 0x80 /* Register RegFifoFullLength (Addr: 0x54) */ #define _RED_FULLSIZE 0x00 #define _GREEN_FULLSIZE 0x08 #define _BLUE_FULLSIZE 0x10 /* Register RegScanControl1 (Addr: 0x5b) */ #define _MTSC_ENABLE 0x01 #define _SCANSTOPONBUFFULL 0x02 #define _MFRC_RUNSCANSTATE 0x04 #define _MFRC_BY_XSTEP 0x08 /* Register RegMotorDriverType (Addr: 0x64) */ #define _MOTORS_MASK 0x33 #define _MOTORR_MASK 0xf3 #define _MOTORR_WEAK 0x04 #define _MOTORR_MEDIUM 0x08 #define _MOTORR_STRONG 0x0c #define _MOTORT_WEAK 0x40 #define _MOTORT_MEDIUM 0x80 #define _MOTORT_STRONG 0xc0 #define _BUTTON_SELECT1 0x40 #define _BUTTON_SELECT2 0x80 #define _BUTTON_DISABLE 0xc0 /** Register RegStatus2 (Addr: 0x66) */ #define _REFLECTIONLAMP_ON 0x01 #define _TPALAMP_ON 0x02 #define _STILL_FREE_RUNNING 0x04 #define _BUFFER_IS_FULL 0x08 /** Register RegTestMode (Addr: 0xf0) */ #define _SW_TESTMODE 0x20 /** buffer sizes */ #define _BYTES_PER_CHANNEL 5500UL #define _SIZE_DATA_BUF (u_long)(_BYTES_PER_CHANNEL * 3 * 2) #define _SIZE_TPA_DATA_BUF (u_long)(_BYTES_PER_CHANNEL * 3 * 2) #define _SIZE_SHADING_SUM_BUF (u_long)(_BYTES_PER_CHANNEL * 3 * 4) #define _SIZE_TOTAL_BUF (u_long)(_SIZE_DATA_BUF + _SIZE_SHADING_SUM_BUF) #define _SIZE_TOTAL_BUF_TPA (u_long)(_SIZE_TOTAL_BUF + _SIZE_TPA_DATA_BUF) /** internal FIFO buffers */ #define _SIZE_REDFIFO 196608UL /* 192k */ #define _SIZE_GREENFIFO 147456UL /* 144k */ #define _SIZE_BLUEFIFO 114688UL /* 112k */ #define _SIZE_GRAYFIFO (_SIZE_REDFIFO + _SIZE_GREENFIFO + _SIZE_BLUEFIFO) /* Scan State Definitions */ #define _SS_STEP 0x08 #define _SS_RED 0x04 #define _SS_GREEN 0x02 #define _SS_BLUE 0x01 #define _SS_MONO _SS_GREEN #define _SS_COLOR (_SS_RED | _SS_GREEN | _SS_BLUE) /** some positioning stuff */ #define _RFT_SCANNING_ORG 380U #define _POS_SCANNING_ORG 2840U #define _NEG_SCANNING_ORG 3000U #define _TPA_SHADINGORG 2172U #define _DATA_ORIGIN_X 72 #define _YOFFSET 300 #define _POS_PAGEWIDTH 450U #define _POS_ORG_OFFSETX 0x41C #define _NEG_PAGEWIDTH 464U #define _NEG_PAGEWIDTH600 992U #define _NEG_ORG_OFFSETX 0x430 #define _NEG_EDGE_VALUE 0x800 #define _NEG_SHADING_OFFS 1500U #define _SHADING_BEGINX 4U #define _DEFAULT_LINESCANTIME 96 #define _LINE_TIMEOUT (_SECOND * 5 ) /** for mirroring parts of the 98003 ASIC register set */ typedef struct { SANE_Byte RD_Motor1Control; /* 0x0b */ SANE_Byte RD_StepControl; /* 0x14 */ SANE_Byte RD_Motor0Control; /* 0x15 */ SANE_Byte RD_XStepTime; /* 0x16 */ SANE_Byte RD_ModeControl; /* 0x1b */ SANE_Byte RD_LineControl; /* 0x1c */ SANE_Byte RD_ScanControl; /* 0x1d, init = 5 */ SANE_Byte RD_ModelControl; /* 0x1f */ SANE_Byte RD_Model1Control; /* 0x20 */ u_short RD_Dpi; /* 0x21 */ u_short RD_Origin; /* 0x23 */ u_short RD_Pixels; /* 0x25 */ u_short RD_ThresholdControl; /* 0x27 */ SANE_Byte RD_ThresholdGapCtrl; /* 0x29 */ u_short RD_RedDarkOff; /* 0x33 */ u_short RD_GreenDarkOff; /* 0x35 */ u_short RD_BlueDarkOff; /* 0x37 */ u_long RD_BufFullSize; /* 0x54 */ u_short RD_MotorTotalSteps; /* 0x57 */ SANE_Byte RD_ScanControl1; /* 0x5b */ SANE_Byte RD_MotorDriverType; /* 0x64 */ SANE_Byte RD_ExtLineControl; /* 0x6d */ SANE_Byte RD_ExtXStepTime; /* 0x6e */ } ShadowRegs; /** to hold all the shading stuff for calibrating a scanner */ typedef struct svd { ColorWord GainResize; ColorWord DarkCmpHi; ColorWord DarkCmpLo; ColorWord DarkOffSub; ColorByte DarkDAC; SANE_Byte Reserved; } ShadingVarDef; typedef struct { ShadingVarDef *pCcdDac; ColorByte DarkDAC; ColorWord DarkOffset; u_short wDarkLevels; SANE_Byte intermediate; u_long dwDiv; SANE_Byte skipShadow; SANE_Byte skipHilight; ColorByte Hilight; RGBUShortDef *pHilight; ColorByte Gain; SANE_Byte bGainDouble; SANE_Byte bUniGain; SANE_Byte bMinGain; SANE_Byte bMaxGain; SANE_Byte bGainHigh; SANE_Byte bGainLow; SANE_Bool fStop; u_short wExposure; u_short wXStep; } ShadingDef; #endif /* guard __U12_HWDEF_H__ */ /* END U12-HWDEF.H ..........................................................*/ sane-backends-1.0.27/backend/umax1220u-common.c0000664000175000017500000016554112112021330015704 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1999 Paul Mackerras Copyright (C) 2000 Adrian Perez Jorge Copyright (C) 2001 Frank Zago Copyright (C) 2001 Marcio Teixeira Parts copyright (C) 2006 Patrick Lessard This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Defines a driver and API for accessing the UMAX Astra 1220U USB scanner. Based on the original command line tool by Paul Mackerras. The UMAX Astra 1220U scanner uses the PowerVision PV8630 Parallel Port to USB bridge. This chip is also used by the HP4200C flatbed scanner. Adrian Perez Jorge wrote a nice interface file for that chip and Frank Zago adapted it to use the sanei_usb interface. Thanks, guys, for making my life easier! :) */ #include #include #include #include #include #include #include /* * The backend performs test scans in order to calibrate * the CCD and to find the zero location. If you would like * to look at those scans, define DEBUG_CALIBRATION to have * the backend save "find_zero.pgm" and "calibration.pgm" to * disk. */ /* #define DEBUG_CALIBRATION */ /* * Define DEBUG_BOUNDS to insert paranoid array bounds * overrun detection into the code. */ /* #define DEBUG_BOUNDS */ /* These values are empirically determined and are given * in 1/600 inch units. If UMAX_MAX_HEIGHT is too large, * the scanner may grind its gears. I assume there is a * physical limit to UMAX_MAX_WIDTH as well (based on the * sensor size) but I do not know what it is. The current * value can be increased beyond what it is now, but you * gain nothing in usuable scan area (you only scan more * of the underside of the scanner's plastic lid). */ #define UMAX_MAX_WIDTH 5400 #define UMAX_MAX_HEIGHT 7040 /* Buffer size. Specifies the size of the buffer that is * used to copy data from the scanner. The old command * line driver had this set at 0x80000 which is likely * the largest possible chunck of data that can be. * at once. This is probably most efficient, but using * a lower value for the SANE driver makes the driver * more responsive to interaction. */ #define BUFFER_SIZE 0x80000 /* Constants that can be used with set_lamp_state to * control the state of the scanner's lamp */ typedef enum { UMAX_LAMP_OFF = 0, UMAX_LAMP_ON = 1 } UMAX_Lamp_State; /* Constants that can be used with move to control * the rate of scanner head movement */ typedef enum { UMAX_NOT_FINE = 0, UMAX_FINE = 1 } UMAX_Speed; /* If anyone knows some descriptive names for these, * please update */ typedef enum { CMD_0 = 0x00, CMD_1 = 0x01, CMD_2 = 0x02, CMD_4 = 0x04, CMD_8 = 0x08, CMD_40 = 0x40, CMD_WRITE = 0x80, CMD_READ = 0xc0 } UMAX_Cmd; /* Product IDs for Astra scanners */ typedef enum { ASTRA_1220U = 0x0010, ASTRA_2000U = 0x0030, ASTRA_2100U = 0x0130 } UMAX_Model; /* The bytes UMAX_SYNC1 and UMAX_SYNC2 serve as a * synchronization signal. Unintentional sync bytes * in the data stream are escaped with UMAX_ESCAPE * character */ #define UMAX_SYNC1 0x55 #define UMAX_SYNC2 0xaa #define UMAX_ESCAPE 0x1b /* Status bits. These bits are active low. * In umax_pp, UMAX_REVERSE_BIT is called * MOTOR_BIT. */ #define UMAX_FORWARD_BIT 0x40 #define UMAX_ERROR_BIT 0x20 #define UMAX_MOTOR_OFF_BIT 0x08 #define UMAX_OK 0x48 /* Used to be 0xC8 */ #define UMAX_OK_WITH_MOTOR 0x40 /* Used to be 0xD0 */ #define UMAX_STATUS_MASK 0x68 /* This byte is used as a placeholder for bytes that are parameterized * in the opcode strings */ #define XXXX 0x00 /* This macro is used to check the return code of * functions */ #define CHK(A) {if( (res = A) != SANE_STATUS_GOOD ) { \ DBG( 1, "Failure on line of %s: %d\n", __FILE__, \ __LINE__ ); return A; }} /* Macros that are used for array overrun detection * (when DEBUG_BOUNDS is defined) */ #ifdef DEBUG_BOUNDS #define PAD 10 #define PAD_ARRAY( A, len ) {int i; \ for( i = 0; i < PAD; i++ ) {A[len+i]=0x55;}} #define CHK_ARRAY( A, len ) {int i;for( i = 0; i < PAD; i++ ) {\ if(A[len+i]!=0x55) { \ DBG( 1, "Array overrun detected on line %d\n", __LINE__ ); \ }}} #else #define PAD 0 #define PAD_ARRAY( A, len ) #define CHK_ARRAY( A, len ) #endif /* This data structure contains data related * to the scanning process. */ typedef struct { /* Constant data */ int color; int w; int h; int xo; int yo; int xdpi; /* Physical x dpi */ int ydpi; /* Physical y dpi */ int xsamp; int ysamp; int xskip; int yskip; int fd; /* Device file handle */ UMAX_Model model; /* Raw scan data buffer */ unsigned char *p; int bh; /* Size of buffer in lines */ int hexp; /* Scan lines yet to be read */ /* Decoding logic */ int x, y, maxh; int done; /* Boolean, all lines decoded */ /* Calibration data */ unsigned char caldata[16070 + PAD]; /* Scan head position */ int scanner_ypos; int scanner_yorg; } UMAX_Handle; typedef unsigned char UMAX_Status_Byte; #if 0 static void unused_operations () { /* These operations are unused anywhere in the driver */ unsigned char opb8[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x18, 0x10, 0x03, 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0x13, 0x1a }; unsigned char opb9[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x41, 0x20, 0x24, 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0x13, 0x1a }; unsigned char opb10[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0x41, 0x60, 0x4f, 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0x93, 0x1a }; unsigned char opc5[16] = { 0x05, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00, 0x00, 0x30, 0x0c, 0xc3, 0xa4, 0x00 }; unsigned char opc6[16] = { 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00, 0x88, 0x48, 0x0c, 0x83, 0xa4, 0x00 }; unsigned char opc7[16] = { 0x05, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x00, 0xec, 0x4e, 0x0c, 0xc3, 0xa4, 0x00 }; unsigned char opd2[8] = { 0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, 0x00, 0x30 }; } #endif #if 0 static SANE_Status calib (UMAX_Handle * scan) { unsigned char buf[65536]; opc5[11] = 0x30; opd2[7] = 0x30; CHK (get_pixels (scan, opc5, opb8, opd2, ope, 24, 0, buff)); opc5[11] = 0x40; opd2[7] = 0x40; CHK (get_pixels (scan, opc5, opb8, opd2, ope, 24, 0, buff)); opd2[6] = 8; opd2[7] = 0x30; CHK (get_pixels (scan, opc6, opb9, opd2, ope, 0x200, 1, buff)); opc7[10] = 0xec; opd2[6] = 0xc; opd2[7] = 0x40; CHK (get_pixels (scan, opc7, opb10, opd2, ope, 5300, 1, buff)); opc7[10] = 0xed; opd2[6] = 0xd; CHK (get_pixels (scan, opc7, opb10, opd2, ope, 5300, 0, buff)); return SANE_STATUS_GOOD; } #endif /* This seems to configure the pv8630 chip somehow. I wish * all the magic numbers were defined as self-descriptive * constants somewhere. I made some guesses based on what * I found in "pv8630.c", but alas there wasn't enough in * there. If you know what this does, please let me know! */ static SANE_Status xxxops (UMAX_Handle * scan) { SANE_Status res; DBG (9, "doing xxxops\n"); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RMODE, 0x02)); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x0E)); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RDATA, 0x40)); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x06)); CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0x38, 0xFF)); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x07)); CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0x38, 0xFF)); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x04)); CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_RSTATUS, 0xF8, 0xFF)); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x05)); CHK (sanei_pv8630_xpect_byte (scan->fd, PV8630_UNKNOWN, 0x05, 0xFF)); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_UNKNOWN, 0x04)); CHK (sanei_pv8630_write_byte (scan->fd, PV8630_RMODE, 0x1E)); return res; } /* Apparently sends the two syncronization characters followed by the command length, followed by the command number */ static SANE_Status usync (UMAX_Handle * scan, UMAX_Cmd cmd, int len) { UMAX_Status_Byte s0, s4; SANE_Status res; unsigned char buf[4]; size_t nb; DBG (80, "usync: len = %d, cmd = %d\n", len, cmd); buf[0] = UMAX_SYNC1; buf[1] = UMAX_SYNC2; nb = 2; CHK (sanei_pv8630_flush_buffer (scan->fd)); CHK (sanei_pv8630_prep_bulkwrite (scan->fd, nb)); CHK (sanei_pv8630_bulkwrite (scan->fd, buf, &nb)); CHK (sanei_pv8630_wait_byte (scan->fd, PV8630_RSTATUS, UMAX_OK, UMAX_STATUS_MASK, 20)); buf[0] = len >> 16; buf[1] = len >> 8; buf[2] = len; buf[3] = cmd; nb = 4; CHK (sanei_pv8630_flush_buffer (scan->fd)); CHK (sanei_pv8630_prep_bulkwrite (scan->fd, nb)); CHK (sanei_pv8630_bulkwrite (scan->fd, buf, &nb)); CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0)); CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4)); DBG (90, "usync: s0 = %#x s4 = %#x\n", s0, s4); return SANE_STATUS_GOOD; } /* This function escapes any syncronization sequence that may be in data, storing the result in buf. In the worst case where every character gets escaped buf must be at least twice as large as dlen. */ static int bescape (const unsigned char *data, int dlen, unsigned char *buf, int blen) { const unsigned char *p; unsigned char *q; int i, c; i = blen; /* Eliminate compiler warning about unused param */ p = data; q = buf; for (i = 0; i < dlen; ++i) { c = *p++; if (c == UMAX_ESCAPE || (c == UMAX_SYNC2 && i > 0 && p[-2] == UMAX_SYNC1)) *q++ = UMAX_ESCAPE; *q++ = c; } return q - buf; } /* Write */ static SANE_Status cwrite (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, const unsigned char *data, UMAX_Status_Byte * s) { SANE_Status res; UMAX_Status_Byte s0, s4; static unsigned char *escaped = NULL; static size_t escaped_size = 0; DBG (80, "cwrite: cmd = %d, len = %lu\n", cmd, (u_long) len); CHK (usync (scan, cmd | CMD_WRITE, len)); if (len <= 0) return SANE_STATUS_GOOD; if (escaped_size < len * 2) { escaped_size = len * 2; if (escaped) free (escaped); escaped = malloc (escaped_size); if (escaped == NULL) return SANE_STATUS_NO_MEM; } len = bescape (data, len, escaped, len * 2); CHK (sanei_pv8630_wait_byte (scan->fd, PV8630_RSTATUS, UMAX_OK, UMAX_STATUS_MASK, 20)); CHK (sanei_pv8630_flush_buffer (scan->fd)); CHK (sanei_pv8630_prep_bulkwrite (scan->fd, len)); CHK (sanei_pv8630_bulkwrite (scan->fd, escaped, &len)); CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4)); CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0)); DBG (90, "cwrite: s0 = %#x s4 = %#x\n", s0, s4); if (s) *s = s0; return SANE_STATUS_GOOD; } /* Read */ static SANE_Status cread (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, unsigned char *data, UMAX_Status_Byte * s) { SANE_Status res; UMAX_Status_Byte s0, s4; DBG (80, "cread: cmd = %d, len = %lu\n", cmd, (u_long) len); CHK (usync (scan, cmd | CMD_READ, len)); if (len > 0) { CHK (sanei_pv8630_wait_byte (scan->fd, PV8630_RSTATUS, UMAX_OK_WITH_MOTOR, UMAX_STATUS_MASK, 2000)); while (len > 0) { size_t req, n; req = n = (len > 0xf000) ? 0xf000 : len; CHK (sanei_pv8630_prep_bulkread (scan->fd, n)); CHK (sanei_pv8630_bulkread (scan->fd, data, &n)); if (n < req) { DBG (1, "qread: Expecting to read %lu, only got %lu\n", (u_long) req, (u_long) n); return SANE_STATUS_IO_ERROR; } data += n; len -= n; } } CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RSTATUS, &s4)); CHK (sanei_pv8630_read_byte (scan->fd, PV8630_RDATA, &s0)); DBG (90, "cwrite: s0 = %#x s4 = %#x\n", s0, s4); if (s) *s = s0; return SANE_STATUS_GOOD; } /* Seems to be like cwrite, with a verification option */ static SANE_Status cwritev (UMAX_Handle * scan, UMAX_Cmd cmd, size_t len, const unsigned char *data, UMAX_Status_Byte * s) { SANE_Status res; unsigned char buf[16384]; /* Write out the opcode */ CHK (cwrite (scan, cmd, len, data, s)); if (len <= 0) return SANE_STATUS_GOOD; /* Read the opcode back */ CHK (cread (scan, cmd, len, buf, NULL)); if (bcmp (buf, data, len)) { DBG (1, "cwritev: verification failed\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* Send command */ static SANE_Status csend (UMAX_Handle * scan, UMAX_Cmd cmd) { DBG (80, "csend: cmd = %d\n", cmd); return usync (scan, cmd, 0); } /* Lamp control */ static SANE_Status cwritev_opc1_lamp_ctrl (UMAX_Handle * scan, UMAX_Lamp_State state) { unsigned char opc1[16] = { 0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x13, 0x05, 0x00, 0x00, 0x00, 0x80, 0xf0, 0x00 }; DBG (9, "cwritev_opc1: set lamp state = %s\n", (state == UMAX_LAMP_OFF) ? "off" : "on"); opc1[14] = (state == UMAX_LAMP_OFF) ? 0x90 : 0xf0; return cwritev (scan, CMD_2, 16, opc1, NULL); } /* Restore Head 1220U */ static SANE_Status cwritev_opb3_restore (UMAX_Handle * scan) { unsigned char opb3[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 0xc1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0x1b, 0x1a, }; SANE_Status res; DBG (9, "cwritev_opb3_restore:\n"); CHK (cwritev (scan, CMD_8, 35, opb3, NULL)); CHK (csend (scan, CMD_40)); return SANE_STATUS_GOOD; } /* Restore Head 2100U */ static SANE_Status cwritev_opb3_restore_2100U (UMAX_Handle * scan) { unsigned char opb3[36] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 0xc1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 0xe9, 0x68, 0xdf, 0x0b, 0x1a, 0x00 }; SANE_Status res; DBG (9, "cwritev_opb3_restore:\n"); CHK (cwritev (scan, CMD_8, 36, opb3, NULL)); CHK (csend (scan, CMD_40)); return SANE_STATUS_GOOD; } /* Initialize and turn lamp on 1220U */ /* This function seems to perform various things. First, it loads a default gamma information (which is used for the calibration scan), returns the head to the park position, and turns the lamp on. This function used to be split up into two parts, umaxinit and umaxinit2. */ static SANE_Status umaxinit (UMAX_Handle * scan) { unsigned char opb[34] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 0xc1, 0x80, 0x60, 0x20, 0x00, 0x00, 0x16, 0x41, 0xe0, 0xac, 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 }; unsigned char opb1[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 0xc1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xe0, 0xac, 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1a }; unsigned char opb2[35] = { 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 0xc1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xe0, 0xac, 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1a }; unsigned char opb4[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x03, 0xc1, 0x80, 0x60, 0x20, 0x00, 0x00, 0x16, 0x41, 0xe0, 0xac, 0x03, 0x03, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0xf3, 0x1b }; unsigned char opbx[35]; unsigned char opc[16] = { 0x02, 0x80, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x07, 0x00, 0x00, 0x00, 0x80, 0xf0, 0x00 }; unsigned char opcx[16]; unsigned char opd[8] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }; SANE_Status res; UMAX_Status_Byte s; unsigned char ramp[800]; int i; unsigned char *p; DBG (3, "umaxinit called\n"); CHK (csend (scan, CMD_0)); CHK (xxxops (scan)); CHK (cwritev (scan, CMD_8, 34, opb, &s)); CHK (cread (scan, CMD_8, 35, opbx, &s)); CHK (cwritev (scan, CMD_8, 35, opb1, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "umaxinit: checkpoint 2:\n"); /* The following code appears to send three 256 entry, 8-bit gamma tables * to the scanner */ p = ramp; *p++ = 0; *p++ = 0; *p++ = 0; for (i = 0; i < 256; ++i) *p++ = i; for (i = 0; i < 256; ++i) *p++ = i; for (i = 0; i < 256; ++i) *p++ = i; *p++ = 0xaa; *p++ = 0xaa; res = cwritev (scan, CMD_4, p - ramp, ramp, &s); if (res != SANE_STATUS_GOOD) { DBG (4, "umaxinit: Writing ramp 1 failed (is this a 2000U?)\n"); } CHK (cwritev (scan, CMD_8, 35, opb1, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "umaxinit: checkpoint 3:\n"); /* The following code appears to send a 256 entry, 16-bit gamma table * to the scanner */ p = ramp; for (i = 0; i < 256; ++i) { *p++ = i; *p++ = 0; } res = cwrite (scan, CMD_4, p - ramp, ramp, &s); if (res != SANE_STATUS_GOOD) { DBG (4, "umaxinit: Writing ramp 2 failed (is this a 2000U?)\n"); } CHK (cwritev (scan, CMD_8, 35, opb2, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "umaxinit: checkpoint 4:\n"); /* The following code appears to send a 256 entry, 16-bit gamma table * to the scanner. */ p = ramp; for (i = 0; i < 256; ++i) { *p++ = i; *p++ = 4; } res = cwritev (scan, CMD_4, p - ramp, ramp, &s); if (res != SANE_STATUS_GOOD) { DBG (4, "umaxinit: Writing ramp 3 failed (is this a 2000U?)\n"); } CHK (cwritev (scan, CMD_8, 35, opb1, &s)); CHK (cwritev (scan, CMD_2, 16, opc, NULL)); CHK (cwritev (scan, CMD_1, 8, opd, NULL)); CHK (csend (scan, CMD_0)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "umaxinit: checkpoint 5: s = %#x\n", s); if ((s & 0x40) == 0) { DBG (4, "umaxinit: turning on lamp and restoring\n"); CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON)); CHK (cwritev_opb3_restore (scan)); for (i = 0; i < 60; ++i) { CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "umaxinit: s = %#x\n", s); if ((s & 0x40) != 0) break; DBG (4, "umaxinit: sleeping\n"); usleep (500000); } } DBG (4, "umaxinit: checkpoint 6\n"); CHK (csend (scan, CMD_0)); /* The following stuff used to be in umaxinit2() */ DBG (4, "umaxinit: checkpoint 7\n"); CHK (xxxops (scan)); CHK (csend (scan, CMD_0)); CHK (xxxops (scan)); CHK (cwritev (scan, CMD_8, 34, opb4, &s)); CHK (cread (scan, CMD_8, 35, opbx, &s)); CHK (cread (scan, CMD_2, 16, opcx, &s)); CHK (cwritev (scan, CMD_2, 16, opc, NULL)); CHK (cwritev (scan, CMD_1, 8, opd, NULL)); CHK (csend (scan, CMD_0)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "umaxinit: checkpoint 8: s = %d\n", s); return SANE_STATUS_GOOD; } /* Initialize and turn lamp on 2100U */ static SANE_Status umaxinit_2100U (UMAX_Handle * scan) { unsigned char opx[36]; unsigned char opy[16]; SANE_Status res; UMAX_Status_Byte s; DBG (3, "umaxinit called\n"); CHK (xxxops (scan)); CHK (csend (scan, CMD_0)); /* Turn lamp on */ cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON); CHK (cread (scan, CMD_8, 36, opx, &s)); CHK (cread (scan, CMD_2, 16, opy, &s)); CHK (csend (scan, CMD_0)); CHK (cread (scan, CMD_2, 0, NULL, &s)); CHK (csend (scan, CMD_0)); return SANE_STATUS_GOOD; } /* Move head 1220U */ static SANE_Status move (UMAX_Handle * scan, int distance, UMAX_Speed fine) { unsigned char opc4[16] = { 0x01, XXXX, XXXX, XXXX, 0x00, 0x00, 0x60, 0x2f, XXXX, XXXX, 0x00, 0x00, 0x00, 0x80, XXXX, 0x00 }; unsigned char opb5[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf, 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0x13, 0x1a }; unsigned char opb7[35] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0x13, 0x1a }; unsigned char ope[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }; unsigned char ope2[3] = { 0x00, 0xff, 0x8f }; unsigned char buf[512 + PAD]; SANE_Status res; UMAX_Status_Byte s; SANE_Bool rev = distance < 0; int skip = (rev ? -distance : distance) - 1; DBG (9, "move: distance = %d, scanner_ypos = %d\n", distance, scan->scanner_ypos); PAD_ARRAY (buf, 512); if (distance == 0) return SANE_STATUS_GOOD; opc4[1] = skip << 6; opc4[2] = skip >> 2; opc4[3] = (rev ? 0x20 : 0x70) + ((skip >> 10) & 0xf); opc4[9] = rev ? 0x01 : 0x05; if (fine == UMAX_FINE) { opc4[8] = 0x2f; opc4[14] = 0xa4; } else { opc4[8] = 0x17; opc4[14] = 0xac; } scan->scanner_ypos += (fine == UMAX_FINE ? distance : 2 * distance + (rev ? -1 : 1)); scan->scanner_ypos = (scan->scanner_ypos + (rev ? 0 : 3)) & ~3; CHK (cwrite (scan, CMD_2, 16, opc4, &s)); CHK (cwrite (scan, CMD_8, 35, rev ? opb7 : opb5, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (10, "move: checkpoint 1: s = %d\n", s); CHK (csend (scan, CMD_0)); if (rev) CHK (cwrite (scan, CMD_4, 3, ope2, &s)) else CHK (cwrite (scan, CMD_4, 8, ope, &s)); CHK (csend (scan, CMD_40)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (10, "move: checkpoint 2: s = %d\n", s); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (10, "move: checkpoint 3: s = %d\n", s); CHK (cread (scan, CMD_4, 512, buf, &s)); CHK_ARRAY (buf, 512); return res; } /* Move head 2100U */ static SANE_Status move_2100U (UMAX_Handle * scan, int distance, UMAX_Speed fine) { unsigned char opc4[16] = { 0x01, XXXX, XXXX, XXXX, 0x00, 0x00, 0x60, 0x2f, XXXX, XXXX, 0x00, 0x00, 0x00, 0x80, XXXX, 0x00 }; unsigned char opb5[36] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf, 0x06, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00 }; unsigned char opb7[36] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xf6, 0x79, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00 }; unsigned char ope[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }; unsigned char ope2[3] = { 0x00, 0xff, 0xff }; unsigned char buf[512]; SANE_Status res; UMAX_Status_Byte s; SANE_Bool rev = distance < 0; int skip = (rev ? -distance : distance) - 1; DBG (9, "move: distance = %d, scanner_ypos = %d\n", distance, scan->scanner_ypos); PAD_ARRAY (buf, 512); if (distance == 0) return SANE_STATUS_GOOD; opc4[1] = skip << 6; opc4[2] = skip >> 2; opc4[3] = (rev ? 0x20 : 0x70) + ((skip >> 10) & 0x0f); opc4[9] = rev ? 0x01 : 0x05; if (fine == UMAX_FINE) { opc4[8] = 0x2b; opc4[14] = 0xa4; } else { opc4[8] = 0x15; opc4[14] = 0xac; } scan->scanner_ypos += (fine == UMAX_FINE ? distance : 2 * distance + (rev ? -1 : 1)); scan->scanner_ypos = (scan->scanner_ypos + (rev ? 0 : 3)) & ~3; CHK (cwrite (scan, CMD_2, 16, opc4, &s)); CHK (cwrite (scan, CMD_8, 36, rev ? opb7 : opb5, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (10, "move: checkpoint 1: s = %d\n", s); CHK (csend (scan, CMD_0)); if (rev) CHK (cwrite (scan, CMD_4, 3, ope2, &s)) else CHK (cwrite (scan, CMD_4, 8, ope, &s)); CHK (csend (scan, CMD_40)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (10, "move: checkpoint 2: s = %d\n", s); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (10, "move: checkpoint 3: s = %d\n", s); CHK (cread (scan, CMD_4, 512, buf, &s)); CHK_ARRAY (buf, 512); return res; } /* Get pixel image 1220U */ static SANE_Status get_pixels (UMAX_Handle * scan, unsigned char *op2, unsigned char *op8, unsigned char *op1, unsigned char *op4, int len, int zpos, unsigned char *buf) { SANE_Status res; UMAX_Status_Byte s; DBG (9, "get_pixels: len = %d, zpos = %d\n", len, zpos); if (zpos == 0) CHK (csend (scan, CMD_0)); CHK (cwrite (scan, CMD_2, 16, op2, &s)); CHK (cwrite (scan, CMD_8, 35, op8, &s)); CHK (cwrite (scan, CMD_1, 8, op1, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); if (zpos == 1) CHK (csend (scan, CMD_0)); CHK (cwrite (scan, CMD_4, 8, op4, &s)); CHK (csend (scan, CMD_40)); CHK (cread (scan, CMD_2, 0, NULL, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); CHK (cread (scan, CMD_4, len, buf, &s)); return SANE_STATUS_GOOD; } /* Get pixel image 2100U */ static SANE_Status get_pixels_2100U (UMAX_Handle * scan, unsigned char *op2, unsigned char *op8, unsigned char *op1, unsigned char *op4, int len, int zpos, unsigned char *buf) { SANE_Status res; UMAX_Status_Byte s; DBG (9, "get_pixels: len = %d, zpos = %d\n", len, zpos); CHK (cwrite (scan, CMD_2, 16, op2, &s)); CHK (cwrite (scan, CMD_8, 36, op8, &s)); if (zpos == 1) CHK (cwritev (scan, CMD_1, 8, op1, &s)) else CHK (cwrite (scan, CMD_1, 8, op1, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); if (zpos == 1) CHK (csend (scan, CMD_0)); CHK (cwrite (scan, CMD_4, 8, op4, &s)); CHK (csend (scan, CMD_40)); CHK (cread (scan, CMD_2, 0, NULL, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); CHK (cread (scan, CMD_4, len, buf, &s)); return SANE_STATUS_GOOD; } /* This function locates the black stripe under scanner lid */ static int locate_black_stripe (unsigned char *img, int w, int h) { int epos, ecnt, x, y; unsigned char *p; epos = 0; ecnt = 0; p = img; for (x = 0; x < w; ++x, ++p) { int d, dmax = 0, dpos = 0; unsigned char *q = img + x; for (y = 1; y < h; ++y, q += w) { d = q[0] - q[w]; if (d > dmax) { dmax = d; dpos = y; } } if (dmax > 0) { epos += dpos; ++ecnt; } } if (ecnt == 0) epos = 70; else epos = (epos + ecnt / 2) / ecnt; return epos; } /* To find the lowest head position 1220U */ static SANE_Status find_zero (UMAX_Handle * scan) { unsigned char opc3[16] = { 0xb4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2f, 0x05, 0x00, 0x00, 0x00, 0x80, 0xa4, 0x00 }; unsigned char ope1[8] = { 0x00, 0x00, 0x00, 0xaa, 0xcc, 0xee, 0x80, 0xff }; unsigned char opb6[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xfb, 0xc4, 0xe5, 0x06, 0x00, 0x00, 0x60, 0x4d, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0x13, 0x1a }; unsigned char opd1[8] = { 0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, 0x08, 0x00 }; SANE_Status res; int s; unsigned char *img; DBG (9, "find_zero:\n"); img = malloc (54000); if (img == 0) { DBG (1, "out of memory (need 54000)\n"); return SANE_STATUS_NO_MEM; } CHK (csend (scan, CMD_0)); CHK (get_pixels (scan, opc3, opb6, opd1, ope1, 54000, 1, img)); #ifdef DEBUG_CALIBRATION { int w = 300, h = 180; FILE *f2 = fopen ("find_zero.pgm", "wb"); fprintf (f2, "P5\n%d %d\n255\n", w, h); fwrite (img, 1, w * h, f2); fclose (f2); } #endif s = locate_black_stripe (img, 300, 180); scan->scanner_yorg = scan->scanner_ypos + s + 64; scan->scanner_ypos += 180 + 3; scan->scanner_ypos &= ~3; free (img); return SANE_STATUS_GOOD; } /* To find the lowest head position 2100U */ static SANE_Status find_zero_2100U (UMAX_Handle * scan) { unsigned char opc3[16] = { 0xb4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2f, 0x2b, 0x05, 0x00, 0x00, 0x00, 0x80, 0xa4, 0x00 }; unsigned char ope1[8] = { 0x00, 0x00, 0x00, 0xaa, 0xcc, 0xee, 0x80, 0xff }; unsigned char opb6[36] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xfb, 0xc4, 0xe5, 0x06, 0x00, 0x00, 0x60, 0x4d, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 0xe9, 0x68, 0xdf, 0x03, 0x1a, 0x00 }; unsigned char opd1[8] = { 0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, 0x08, 0x00 }; SANE_Status res; int s; unsigned char *img; DBG (9, "find_zero:\n"); img = malloc (54000); if (img == 0) { DBG (1, "out of memory (need 54000)\n"); return SANE_STATUS_NO_MEM; } CHK (csend (scan, CMD_0)); CHK (get_pixels_2100U (scan, opc3, opb6, opd1, ope1, 54000, 1, img)); #ifdef DEBUG_CALIBRATION { int w = 300, h = 180; FILE *f2 = fopen ("find_zero.pgm", "wb"); fprintf (f2, "P5\n%d %d\n255\n", w, h); fwrite (img, 1, w * h, f2); fclose (f2); } #endif s = locate_black_stripe (img, 300, 180); scan->scanner_yorg = scan->scanner_ypos + s + 64; scan->scanner_ypos += 180 + 3; scan->scanner_ypos &= ~3; free (img); return SANE_STATUS_GOOD; } /* Calibration 1220U */ /* Format of caldata: 5100 bytes of CCD calibration values 5100 bytes of CCD calibration values 5100 bytes of CCD calibration values 256 bytes of gamma data for blue 256 bytes of gamma data for green 256 bytes of gamma data for red 2 bytes of extra information */ static SANE_Status get_caldata (UMAX_Handle * scan, int color) { unsigned char opc9[16] = { XXXX, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x17, 0x05, 0xec, 0x4e, 0x0c, XXXX, 0xac }; unsigned char opb11[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, 0xad, 0xa0, 0x49, 0x06, 0x00, 0x00, XXXX, XXXX, 0xa0, 0x00, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, 0x93, 0x1b }; unsigned char ope[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }; unsigned char opd4[8] = { 0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, XXXX, XXXX }; SANE_Status res; unsigned char *p; int h = 66; int w = color ? 3 * 5100 : 5100; int x0 = color ? 0 : 5100; int l = w * h; int i, x, y; PAD_ARRAY (scan->caldata, 16070); DBG (9, "get_caldata: color = %d\n", color); p = malloc (l); if (p == 0) { DBG (1, "out of memory (need %d)\n", l); return SANE_STATUS_NO_MEM; } memset (scan->caldata, 0, 3 * 5100); CHK (csend (scan, CMD_0)); opc9[0] = h + 4; if (color) { opc9[13] = 0x03; opb11[23] = 0xc4; opb11[24] = 0x5c; opd4[6] = 0x08; opd4[7] = 0x00; } else { opc9[13] = 0xc3; opb11[23] = 0xec; opb11[24] = 0x54; opd4[6] = 0x0c; opd4[7] = 0x40; } /* Do a test scan of the calibration strip (which is located * under the scanner's lid */ CHK (get_pixels (scan, opc9, opb11, opd4, ope, l, 0, p)); #ifdef DEBUG_CALIBRATION { FILE *f2 = fopen ("calibration.pgm", "wb"); fprintf (f2, "P5\n%d %d\n255\n", w, h); fwrite (p, 1, w * h, f2); fclose (f2); } #endif scan->scanner_ypos += (h + 4) * 2 + 3; scan->scanner_ypos &= ~3; /* The following loop computes the gain for each of the CCD pixel * elements. */ for (x = 0; x < w; ++x) { int t = 0, gn; double av, gain; for (y = 0; y < h; ++y) t += p[x + y * w]; av = (double) t / h; gain = 250 / av; gn = (int) ((gain - 0.984) * 102.547 + 0.5); if (gn < 0) gn = 0; else if (gn > 255) gn = 255; scan->caldata[x + x0] = gn; } /* Gamma table for blue */ for (i = 0; i < 256; ++i) scan->caldata[i + 3 * 5100 + 0] = i; /* Gamma table for green */ for (i = 0; i < 256; ++i) scan->caldata[i + 3 * 5100 + 256] = i; /* Gamma table for red */ for (i = 0; i < 256; ++i) scan->caldata[i + 3 * 5100 + 512] = i; free (p); CHK_ARRAY (scan->caldata, 16070); return SANE_STATUS_GOOD; } /* Calibration 2100U */ /* Format of caldata: 5100 bytes of CCD calibration values 5100 bytes of CCD calibration values 5100 bytes of CCD calibration values 256 bytes of gamma data for blue 256 bytes of gamma data for green 256 bytes of gamma data for red 2 bytes of extra information */ static SANE_Status get_caldata_2100U (UMAX_Handle * scan, int color) { unsigned char opc9[16] = { XXXX, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x15, 0x05, XXXX, XXXX, XXXX, XXXX, 0xac, 0x00 }; unsigned char opb11[36] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, 0x46, 0x06, 0x00, 0x00, XXXX, XXXX, 0xa0, 0x00, 0x8b, 0x49, 0x2a, 0xe9, 0x68, 0xdf, 0x83, XXXX, 0x00 }; unsigned char opd4[8] = { 0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, XXXX, XXXX }; unsigned char ope[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }; /* default gamma translation table */ unsigned char ggamma[256] = { 0x00, 0x06, 0x0A, 0x0D, 0x10, 0x12, 0x14, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, 0x24, 0x26, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x30, 0x31, 0x33, 0x34, 0x36, 0x37, 0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x40, 0x41, 0x42, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB8, 0xB9, 0xBA, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC8, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCD, 0xCE, 0xCE, 0xCF, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6, 0xD6, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE3, 0xE4, 0xE5, 0xE6, 0xE6, 0xE7, 0xE8, 0xE8, 0xE9, 0xEA, 0xEA, 0xEB, 0xEC, 0xEC, 0xED, 0xEE, 0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF3, 0xF4, 0xF5, 0xF5, 0xF6, 0xF7, 0xF7, 0xF8, 0xF9, 0xF9, 0xFA, 0xFB, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFF }; SANE_Status res; unsigned char *p; int h = 66; int w = color ? 3 * 5100 : 5100; int x0 = color ? 0 : 5100; int l = w * h; int i, x, y; int t, gn; double av, pct; PAD_ARRAY (scan->caldata, 16070); DBG (9, "get_caldata: color = %d\n", color); p = malloc (l); if (p == 0) { DBG (1, "out of memory (need %d)\n", l); return SANE_STATUS_NO_MEM; } memset (scan->caldata, 0, 3 * 5100); CHK (csend (scan, CMD_0)); CHK (csend (scan, CMD_0)); opc9[0] = h + 4; if (color) { opc9[10] = 0xb6; opc9[11] = 0x3b; opc9[12] = 0x0c; opc9[13] = 0x03; opb11[17] = 0x7e; opb11[18] = 0xb0; opb11[23] = 0xc4; opb11[24] = 0x5c; opb11[34] = 0x1b; opd4[6] = 0x0f; opd4[7] = 0x40; } else { opc9[10] = 0xa6; opc9[11] = 0x2a; opc9[12] = 0x08; opc9[13] = 0xc2; opb11[17] = 0x7f; opb11[18] = 0xc0; opb11[23] = 0xec; opb11[24] = 0x54; opb11[34] = 0x1a; opd4[6] = 0x06; opd4[7] = 0x20; } /* Do a test scan of the calibration strip (which is located * under the scanner's lid */ CHK (get_pixels_2100U (scan, opc9, opb11, opd4, ope, l, 0, p)); #ifdef DEBUG_CALIBRATION { FILE *f2 = fopen ("calibration.pgm", "wb"); fprintf (f2, "P5\n%d %d\n255\n", w, h); fwrite (p, 1, w * h, f2); fclose (f2); } #endif scan->scanner_ypos += (h + 4) * 2 + 3; scan->scanner_ypos &= ~3; /* The following loop computes the gain for each of the CCD pixel * elements. */ for (x = 0; x < w; x++) { t = 0; for (y = 0; y < h; y++) t += p[x + y * w]; av = (double) t / h; pct = 100.0 - (av * 100.0) / 250; gn = (int) (pct / 0.57); pct = gn; av = exp((-pct)/50)*2.5+0.9; gn = gn * av; if (gn < 0) gn = 0; else if (gn > 127) gn = 127; scan->caldata[x + x0] = gn; } /* Gamma table for blue */ for (i = 0; i < 256; i++) scan->caldata[i + 3 * 5100 + 0] = ggamma[i]; /* Gamma table for green */ for (i = 0; i < 256; i++) scan->caldata[i + 3 * 5100 + 256] = ggamma[i]; /* Gamma table for red */ for (i = 0; i < 256; i++) scan->caldata[i + 3 * 5100 + 512] = ggamma[i]; free (p); CHK_ARRAY (scan->caldata, 16070); return SANE_STATUS_GOOD; } /* Sends scan user parameters from frontend 1220U */ static SANE_Status send_scan_parameters (UMAX_Handle * scan) { SANE_Status res; UMAX_Status_Byte s; /* Appears to correspond to opscan in umax_pp_low.c */ unsigned char opbgo[35] = { 0x00, 0x00, 0xb0, 0x4f, 0xd8, 0xe7, 0xfa, 0x10, 0xef, 0xc4, 0x3c, 0x71, 0x0f, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, XXXX, 0xc4, 0x7e, 0x00, XXXX, XXXX, 0xa0, 0x0a, 0x8b, 0x49, 0x4a, 0xd0, 0x68, 0xdf, XXXX, 0x1a }; /* Appears to correspond to opsc53 in umax_pp_low.c */ unsigned char opcgo[16] = { XXXX, XXXX, XXXX, XXXX, 0xec, 0x03, XXXX, XXXX, XXXX, XXXX, 0xec, 0x4e, XXXX, XXXX, XXXX }; /* Appears to correspond to opsc04 in umax_pp_low.c */ unsigned char opdgo[8] = { 0x06, 0xf4, 0xff, 0x81, 0x3d, 0x00, XXXX, XXXX }; unsigned char subsamp[9] = { 0xff, 0xff, 0xaa, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x80 }; const int xend = scan->xskip + scan->w * scan->xsamp + (scan->xsamp + 1) / 2; const int ytot = scan->hexp * scan->ysamp + 12; opbgo[17] = scan->xskip % 256; opbgo[18] = ((scan->xskip >> 8) & 0xf) + (xend << 4); opbgo[19] = xend >> 4; opbgo[33] = 0x33 + ((xend & 0x1000) >> 5) + ((scan->xskip & 0x1000) >> 6); /* bytes per line */ opbgo[23] = scan->color ? 0xc6 : 0x77; opbgo[24] = scan->color ? 0x5b : 0x4a; /* Scan height */ opcgo[0] = ytot; opcgo[1] = ((ytot >> 8) & 0x3f) + (scan->yskip << 6); opcgo[2] = scan->yskip >> 2; opcgo[3] = 0x50 + ((scan->yskip >> 10) & 0xf); /* This is what used to be here: opcgo[6] = bh == h? 0: 0x60; // a guess I replaced it with what umax_pp_low.c uses, since it made more sense */ opcgo[6] = (scan->ydpi <= 300) ? 0x00 : 0x60; opcgo[8] = (scan->ydpi <= 300) ? 0x17 : 0x2F; opcgo[9] = (scan->ydpi >= 300) ? 0x05 : 0x07; opcgo[14] = (scan->ydpi == 600) ? 0xa4 : 0xac; opcgo[7] = scan->color ? 0x2F : 0x40; opcgo[12] = scan->color ? 0x10 : 0x0C; opcgo[13] = scan->color ? 0x04 : 0xc3; opdgo[6] = scan->color ? 0x88 : 0x8c; opdgo[7] = scan->color ? 0x00 : 0x40; DBG (3, "send_scan_parameters: xskip = %d, yskip = %d\n", scan->xskip, scan->yskip); CHK (csend (scan, CMD_0)); CHK (csend (scan, CMD_0)); CHK (cwritev (scan, CMD_2, 16, opcgo, &s)); CHK (cwritev (scan, CMD_8, 35, opbgo, &s)); CHK (cwritev (scan, CMD_1, 8, opdgo, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "send_scan_parameters: checkpoint 1: s = %d\n", s); /* Loads the new calibration data (that was computed by get_caldata) into the scanner */ scan->caldata[16068] = subsamp[scan->xsamp]; scan->caldata[16069] = subsamp[scan->ysamp]; CHK (cwrite (scan, CMD_4, 16070, scan->caldata, &s)); CHK (csend (scan, CMD_40)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "send_scan_parameters: checkpoint 2: s = %d\n", s); return SANE_STATUS_GOOD; } /* Sends scan user parameters from frontend 2100U */ static SANE_Status send_scan_parameters_2100U (UMAX_Handle * scan) { SANE_Status res; UMAX_Status_Byte s; int bpl; /* Appears to correspond to opscan in umax_pp_low.c */ unsigned char opbgo[36] = { 0x00, 0x00, 0xb0, 0x4f, 0xd8, 0xe7, 0xfa, 0x10, 0xef, 0xc4, 0x3c, 0x71, 0x0f, 0x00, 0x04, 0x00, 0x6e, XXXX, XXXX, XXXX, 0xc4, 0x7e, 0x00, XXXX, XXXX, 0xa0, 0x0a, 0x8b, 0x49, 0x2a, 0xe9, 0x68, 0xdf, XXXX, 0x1a, 0x00 }; /* Appears to correspond to opsc53 in umax_pp_low.c */ unsigned char opcgo[16] = { XXXX, XXXX, XXXX, XXXX, 0xec, 0x03, 0x60, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, XXXX, 0x00 }; /* Appears to correspond to opsc04 in umax_pp_low.c */ unsigned char opdgo[8] = { 0x06, 0xf4, 0xff, 0x81, 0x1b, 0x00, XXXX, XXXX }; unsigned char subsamp[9] = { 0xff, 0xff, 0xaa, 0xaa, 0x88, 0x88, 0x88, 0x88, 0x80 }; const int xend = scan->xskip + scan->w * scan->xsamp + (scan->xsamp + 1) / 2; const int ytot = scan->hexp * scan->ysamp + 12; opbgo[17] = scan->xskip % 256; opbgo[18] = ((scan->xskip >> 8) & 0x0f) + (xend << 4); opbgo[19] = xend >> 4; opbgo[33] = 0x23 + ((xend & 0x1000) >> 5) + ((scan->xskip & 0x1000) >> 6); /* bytes per line */ bpl = (scan->color ? 3 : 1) * scan->w * scan->xdpi; opbgo[23] = bpl % 256; opbgo[24] = 0x41 + ((bpl / 256) & 0x1f); /* Scan height */ opcgo[0] = ytot; opcgo[1] = ((ytot >> 8) & 0x3f) + (scan->yskip << 6); opcgo[2] = (scan->yskip >> 2); opcgo[3] = 0x50 + ((scan->yskip >> 10) & 0x0f); opcgo[6] = (scan->ydpi <= 300) ? 0x00 : 0x60; opcgo[8] = (scan->ydpi <= 300) ? 0x17 : 0x2F; opcgo[9] = (scan->ydpi >= 300) ? 0x05 : 0x07; opcgo[14] = (scan->ydpi == 600) ? 0xa4 : 0xac; opcgo[7] = scan->color ? 0x2f : 0x40; opcgo[10] = scan->color ? 0xb6 : 0xa6; opcgo[11] = scan->color ? 0x3b : 0x2a; opcgo[12] = scan->color ? 0x0c : 0x08; opcgo[13] = scan->color ? 0x03 : 0xc2; opdgo[6] = scan->color ? 0x8f : 0x86; opdgo[7] = scan->color ? 0x40 : 0x20; DBG (3, "send_scan_parameters: xskip = %d, yskip = %d\n", scan->xskip, scan->yskip); CHK (csend (scan, CMD_0)); CHK (csend (scan, CMD_0)); CHK (cwritev (scan, CMD_2, 16, opcgo, &s)); CHK (cwritev (scan, CMD_8, 36, opbgo, &s)); CHK (cwritev (scan, CMD_1, 8, opdgo, &s)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "send_scan_parameters: checkpoint 1: s = %d\n", s); /* Loads the new calibration data (that was computed by get_caldata) into the scanner */ scan->caldata[16068] = subsamp[scan->xsamp]; scan->caldata[16069] = subsamp[scan->ysamp]; CHK (cwrite (scan, CMD_4, 16070, scan->caldata, &s)); CHK (csend (scan, CMD_40)); CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "send_scan_parameters: checkpoint 2: s = %d\n", s); return SANE_STATUS_GOOD; } /* Read raw data */ static SANE_Status read_raw_data (UMAX_Handle * scan, unsigned char *data, int len) { SANE_Status res; UMAX_Status_Byte s; CHK (cread (scan, CMD_2, 0, NULL, &s)); CHK (cread (scan, CMD_4, len, data, &s)); return SANE_STATUS_GOOD; } /* Read raw strip color */ static SANE_Status read_raw_strip_color (UMAX_Handle * scan) { /** yres = 75 => ydpi = 150 => ysamp = 2 => yoff_scale = 8 yres = 150 => ydpi = 150 => ysamp = 1 => yoff_scale = 4 yres = 300 => ydpi = 300 => ysamp = 1 => yoff_scale = 2 yres = 600 => ydpi = 600 => ysamp = 1 => yoff_scale = 1 */ const int yoff_scale = 600 * scan->ysamp / scan->ydpi; const int linelen = 3 * scan->w; /* yoff_scale = 8 => roff = 5 * w, goff = 1 * w, boff = 0 * w, hextra = 1 yoff_scale = 4 => roff = 8 * w, goff = 4 * w, boff = 0 * w, hextra = 2 yoff_scale = 2 => roff = 14 * w, goff = 7 * w, boff = 0 * w, hextra = 4 yoff_scale = 1 => roff = 26 * w, goff = 13 * w, boff = 0 * w, hextra = 8 */ const int hextra = 8 / yoff_scale; SANE_Status res; int lines_to_read = scan->hexp; DBG (9, "read_raw_strip_color: hexp = %d, bh = %d\n", scan->hexp, scan->bh); if (scan->maxh == -1) { DBG (10, "read_raw_strip_color: filling buffer for the first time\n"); if (lines_to_read > scan->bh) lines_to_read = scan->bh; CHK (read_raw_data (scan, scan->p, lines_to_read * linelen)); scan->maxh = lines_to_read - hextra; } else { DBG (10, "read_raw_strip_color: reading new rows into buffer\n"); memmove (scan->p, scan->p + (scan->bh - hextra) * linelen, hextra * linelen); if (lines_to_read > (scan->bh - hextra)) lines_to_read = scan->bh - hextra; CHK (read_raw_data (scan, scan->p + hextra * linelen, lines_to_read * linelen)); scan->maxh = lines_to_read; } scan->hexp -= lines_to_read; scan->x = 0; scan->y = 0; return SANE_STATUS_GOOD; } /* Read raw strip grey */ static SANE_Status read_raw_strip_gray (UMAX_Handle * scan) { const int linelen = scan->w; SANE_Status res; int lines_to_read = scan->bh; DBG (9, "read_raw_strip_gray: hexp = %d\n", scan->hexp); if (lines_to_read > scan->hexp) lines_to_read = scan->hexp; scan->hexp -= lines_to_read; CHK (read_raw_data (scan, scan->p, lines_to_read * linelen)); scan->maxh = lines_to_read; scan->x = 0; scan->y = 0; return SANE_STATUS_GOOD; } /* Read raw strip */ static SANE_Status read_raw_strip (UMAX_Handle * scan) { if (scan->color) return read_raw_strip_color (scan); else return read_raw_strip_gray (scan); } /* Set scan user pamaters Frontend */ static SANE_Status UMAX_set_scan_parameters (UMAX_Handle * scan, const int color, const int xo, const int yo, const int w, const int h, const int xres, const int yres) { /* Validate the input parameters */ int left = xo; int top = yo; int right = xo + w * 600 / xres; int bottom = yo + h * 600 / yres; DBG (2, "UMAX_set_scan_parameters:\n"); DBG (2, "color = %d \n", color); DBG (2, "xo = %d, yo = %d\n", xo, yo); DBG (2, "w = %d, h = %d\n", w, h); DBG (2, "xres = %d, yres = %d\n", xres, yres); DBG (2, "left = %d, top = %d\n", left, top); DBG (2, "right = %d, bottom = %d\n", right, bottom); if ((left < 0) || (right > UMAX_MAX_WIDTH)) return SANE_STATUS_INVAL; if ((top < 0) || (bottom > UMAX_MAX_HEIGHT)) return SANE_STATUS_INVAL; if (((right - left) < 10) || ((bottom - top) < 10)) return SANE_STATUS_INVAL; if ((xres != 75) && (xres != 150) && (xres != 300) && (xres != 600)) return SANE_STATUS_INVAL; if ((yres != 75) && (yres != 150) && (yres != 300) && (yres != 600)) return SANE_STATUS_INVAL; /* If we get this far, begin initializing the data structure */ scan->color = color; scan->w = w; scan->h = h; scan->xo = xo; scan->yo = yo; /* The scanner has a fixed X resolution of 600 dpi, but supports three choices for the Y resolution. We must choose an appropriate physical resolution and the corresponding sampling value. It is not clear to me why the choice depends on whether we are scanning in color or not, but the original code did this and I didn't want to mess with it. Physical X resolution choice: xres = 75 => xdpi = 600 (xsamp = 8) xres = 150 => xdpi = 600 (xsamp = 4) xres = 300 => xdpi = 600 (xsamp = 2) xres = 600 => xdpi = 600 (xsamp = 1) Physical Y resolution choice (if color): yres = 75 => ydpi = 150 (ysamp = 2) yres = 150 => ydpi = 150 (ysamp = 1) yres = 300 => ydpi = 300 (ysamp = 1) yres = 600 => ydpi = 600 (ysamp = 1) Physical Y resolution choice (if not color): yres = 75 => ydpi = 300 (ysamp = 4) yres = 150 => ydpi = 300 (ysamp = 2) yres = 300 => ydpi = 300 (ysamp = 1) yres = 600 => ydpi = 600 (ysamp = 1) */ scan->xdpi = 600; if (yres <= 150 && color) scan->ydpi = 150; else if (yres > 300) scan->ydpi = 600; else scan->ydpi = 300; scan->xsamp = scan->xdpi / xres; scan->ysamp = scan->ydpi / yres; return SANE_STATUS_GOOD; } /* Start actual scan 1220U */ static SANE_Status UMAX_start_scan (UMAX_Handle * scan) { SANE_Status res; int linelen; int yd; DBG (3, "UMAX_start_scan called\n"); if (scan->color) { const int yoff_scale = 600 * scan->ysamp / scan->ydpi; const int hextra = 8 / yoff_scale; linelen = 3 * scan->w; scan->hexp = scan->h + hextra; } else { linelen = scan->w; scan->hexp = scan->h; } scan->bh = BUFFER_SIZE / linelen; scan->p = malloc (scan->bh * linelen); if (scan->p == 0) return SANE_STATUS_NO_MEM; DBG (4, "UMAX_start_scan: bh = %d, linelen = %d\n", scan->bh, linelen); scan->maxh = -1; scan->done = 0; /* Initialize the scanner and position the scan head */ CHK (umaxinit (scan)); /* This scans in the black and white calibration strip that * is located under the scanner's lid. The scan of that strip * is used to pick correct values for the CCD calibration * values */ scan->scanner_ypos = 0; CHK (move (scan, 196, UMAX_NOT_FINE)); CHK (find_zero (scan)); CHK (move (scan, scan->scanner_yorg - 232 - scan->scanner_ypos, UMAX_FINE)); CHK (get_caldata (scan, scan->color)); /* This moves the head back to the starting position */ yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos; if (yd < 0) CHK (move (scan, yd, UMAX_FINE)); if (yd > 300) CHK (move (scan, (yd - 20) / 2, UMAX_NOT_FINE)); yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos; scan->yskip = yd / (600 / scan->ydpi); scan->xskip = scan->xo / (600 / scan->xdpi); /* Read in the first chunk of raw data */ CHK (send_scan_parameters (scan)); CHK (read_raw_strip (scan)); DBG (4, "UMAX_start_scan successful\n"); return SANE_STATUS_GOOD; } /* Start actual scan 2100U */ static SANE_Status UMAX_start_scan_2100U (UMAX_Handle * scan) { SANE_Status res; int linelen; int yd; DBG (3, "UMAX_start_scan called\n"); if (scan->color) { const int yoff_scale = 600 * scan->ysamp / scan->ydpi; const int hextra = 8 / yoff_scale; linelen = 3 * scan->w; scan->hexp = scan->h + hextra; } else { linelen = scan->w; scan->hexp = scan->h; } scan->bh = BUFFER_SIZE / linelen; scan->p = malloc (scan->bh * linelen); if (scan->p == 0) return SANE_STATUS_NO_MEM; DBG (4, "UMAX_start_scan: bh = %d, linelen = %d\n", scan->bh, linelen); scan->maxh = -1; scan->done = 0; /* Initialize the scanner and position the scan head */ CHK (umaxinit_2100U (scan)); /* This scans in the black and white calibration strip that * is located under the scanner's lid. The scan of that strip * is used to pick correct values for the CCD calibration * values */ scan->scanner_ypos = 0; CHK (move_2100U (scan, 196, UMAX_NOT_FINE)); CHK (find_zero_2100U (scan)); CHK (move_2100U (scan, scan->scanner_yorg - 232 - scan->scanner_ypos, UMAX_FINE)); CHK (get_caldata_2100U (scan, scan->color)); /* This moves the head back to the starting position */ yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos; if (yd < 0) CHK (move_2100U (scan, yd, UMAX_FINE)); if (yd > 300) CHK (move_2100U (scan, (yd - 20) / 2, UMAX_NOT_FINE)); yd = scan->scanner_yorg + scan->yo - scan->scanner_ypos; scan->yskip = yd / (600 / scan->ydpi); scan->xskip = scan->xo / (600 / scan->xdpi); /* Read in the first chunk of raw data */ CHK (send_scan_parameters_2100U (scan)); CHK (read_raw_strip (scan)); DBG (4, "UMAX_start_scan successful\n"); return SANE_STATUS_GOOD; } /* Set lamp state */ static SANE_Status UMAX_set_lamp_state (UMAX_Handle * scan, UMAX_Lamp_State state) { SANE_Status res; DBG (3, "UMAX_set_lamp_state: state = %d\n", (int) state); CHK (csend (scan, CMD_0)); CHK (cwritev_opc1_lamp_ctrl (scan, state)); return SANE_STATUS_GOOD; } /* Park head 1220U */ static SANE_Status UMAX_park_head (UMAX_Handle * scan) { SANE_Status res; UMAX_Status_Byte s; int i; DBG (3, "UMAX_park_head called\n"); CHK (csend (scan, CMD_0)); /* WARNING: Must call cwritev_opc1_lamp_ctrl before cwritev_opb3_restore, * otherwise the head moves the wrong way and makes ugly grinding noises. */ CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON)); CHK (cwritev_opb3_restore (scan)); for (i = 0; i < 60; ++i) { CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "UMAX_park_head: s = %#x\n", s); if ((s & 0x40) != 0) break; DBG (4, "UMAX_park_head: sleeping\n"); usleep (500000); } scan->scanner_ypos = 0; return SANE_STATUS_GOOD; } /* Park head 2100U */ static SANE_Status UMAX_park_head_2100U (UMAX_Handle * scan) { SANE_Status res; UMAX_Status_Byte s; int i; DBG (3, "UMAX_park_head called\n"); CHK (csend (scan, CMD_0)); /* WARNING: Must call cwritev_opc1_lamp_ctrl before cwritev_opb3_restore, * otherwise the head moves the wrong way and makes ugly grinding noises. */ CHK (cwritev_opc1_lamp_ctrl (scan, UMAX_LAMP_ON)); CHK (cwritev_opb3_restore_2100U (scan)); for (i = 0; i < 60; ++i) { CHK (cread (scan, CMD_2, 0, NULL, &s)); DBG (4, "UMAX_park_head: s = %#x\n", s); if ((s & 0x40) != 0) break; DBG (4, "UMAX_park_head: sleeping\n"); usleep (500000); } /* CHK (csend (scan, CMD_0)); CHK (csend (scan, CMD_0)); */ scan->scanner_ypos = 0; return SANE_STATUS_GOOD; } /* Finish scan */ static SANE_Status UMAX_finish_scan (UMAX_Handle * scan) { DBG (3, "UMAX_finish_scan:\n"); if (scan->p) free (scan->p); scan->p = NULL; return SANE_STATUS_GOOD; } /* RGB decoding for a color scan */ static SANE_Status UMAX_get_rgb (UMAX_Handle * scan, unsigned char *rgb) { if (scan->color) { const int linelen = 3 * scan->w; const int yoff_scale = 600 * scan->ysamp / scan->ydpi; const int roff = (8 / yoff_scale * 3 + 2) * scan->w; const int goff = (4 / yoff_scale * 3 + 1) * scan->w; const int boff = 0; unsigned char *base = scan->p + (scan->y * linelen) + scan->x; rgb[0] = base[roff]; rgb[1] = base[goff]; rgb[2] = base[boff]; } else { const int linelen = scan->w; unsigned char *base = scan->p + (scan->y * linelen) + (scan->x); rgb[0] = base[0]; rgb[1] = base[0]; rgb[2] = base[0]; } if (!(((scan->x + 1) == scan->w) && ((scan->y + 1) == scan->maxh))) { ++scan->x; if (scan->x == scan->w) { ++scan->y; scan->x = 0; } return SANE_STATUS_GOOD; } if (scan->hexp <= 0) { DBG (4, "UMAX_get_rgb: setting done flag\n"); scan->done = 1; return SANE_STATUS_GOOD; } return read_raw_strip (scan); } /* Close device */ static SANE_Status UMAX_close_device (UMAX_Handle * scan) { DBG (3, "UMAX_close_device:\n"); sanei_usb_close (scan->fd); return SANE_STATUS_GOOD; } /* Open device */ static SANE_Status UMAX_open_device (UMAX_Handle * scan, const char *dev) { SANE_Word vendor; SANE_Word product; SANE_Status res; DBG (3, "UMAX_open_device: `%s'\n", dev); res = sanei_usb_open (dev, &scan->fd); if (res != SANE_STATUS_GOOD) { DBG (1, "UMAX_open_device: couldn't open device `%s': %s\n", dev, sane_strstatus (res)); return res; } #ifndef NO_AUTODETECT /* We have opened the device. Check that it is a USB scanner. */ if (sanei_usb_get_vendor_product (scan->fd, &vendor, &product) != SANE_STATUS_GOOD) { DBG (1, "UMAX_open_device: sanei_usb_get_vendor_product failed\n"); /* This is not a USB scanner, or SANE or the OS doesn't support it. */ sanei_usb_close (scan->fd); scan->fd = -1; return SANE_STATUS_UNSUPPORTED; } /* Make sure we have a UMAX scanner */ if (vendor != 0x1606) { DBG (1, "UMAX_open_device: incorrect vendor\n"); sanei_usb_close (scan->fd); scan->fd = -1; return SANE_STATUS_UNSUPPORTED; } /* Now check whether it is a scanner we know about */ switch (product) { case ASTRA_2000U: /* The UMAX Astra 2000U is only partially supported by this driver. Expect severe color problems! :) */ DBG (1, "UMAX_open_device: Scanner is a 2000U. Expect color problems :)\n"); scan->model = ASTRA_2000U; break; case ASTRA_2100U: scan->model = ASTRA_2100U; break; case ASTRA_1220U: scan->model = ASTRA_1220U; break; default: DBG (1, "UMAX_open_device: unknown product number\n"); sanei_usb_close (scan->fd); scan->fd = -1; return SANE_STATUS_UNSUPPORTED; } #endif res = csend (scan, CMD_0); if (res != SANE_STATUS_GOOD) UMAX_close_device (scan); CHK (res); res = xxxops (scan); if (res != SANE_STATUS_GOOD) UMAX_close_device (scan); CHK (res); return SANE_STATUS_GOOD; } /* Get scanner model name */ static const char * UMAX_get_device_name (UMAX_Handle * scan) { switch (scan->model) { case ASTRA_1220U: return "Astra 1220U"; case ASTRA_2000U: return "Astra 2000U"; case ASTRA_2100U: return "Astra 2100U"; } return "Unknown"; } /* End */ sane-backends-1.0.27/backend/umax_pp_mid.h0000664000175000017500000001245512775277260015312 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2012 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Umax PP flatbed scanners. */ #ifdef HAVE_LINUX_PPDEV_H #include #include #include #endif #include "umax_pp_low.h" #ifndef _UMAX1220P_ #define _UMAX1220P_ #define UMAX1220P_OK 0 #define UMAX1220P_NOSCANNER 1 #define UMAX1220P_TRANSPORT_FAILED 2 #define UMAX1220P_PROBE_FAILED 3 #define UMAX1220P_SCANNER_FAILED 4 #define UMAX1220P_PARK_FAILED 5 #define UMAX1220P_START_FAILED 6 #define UMAX1220P_READ_FAILED 7 #define UMAX1220P_BUSY 8 /* probes the port for an umax1220p scanner initialize transport layer probe scanner if name is null, direct I/O is attempted to address given in port else ppdev is tried using the given name as device on success returns UMAX1220P_OK, else one of the error above. */ extern int sanei_umax_pp_attach (int port, char *name); /* recognizes 1220P from 2000P on success returns UMAX1220P_OK, else one of the error above. */ extern int sanei_umax_pp_model (int port, int *model); /* if on=1 -> lights scanner lamp if on=0 -> lights off scanner lamp on success returns UMAX1220P_OK, else one of the error above. */ extern int sanei_umax_pp_lamp (int on); /* probes the port for an umax1220p scanner initialize transport layer initialize scanner on succes returns UMAX1220P_OK, else one of the error above. port: addr when doing direc I/O name: ppdev character device name */ extern int sanei_umax_pp_open (int port, char *name); /* release any ressource acquired during open since there may be only one scanner, no port parameter */ extern int sanei_umax_pp_close (void); /* stops any pending action, then parks the head */ extern int sanei_umax_pp_cancel (void); /* starts scanning: - find scanner origin - does channel gain calibration if needed - does calibration - initialize scan operation x, y, width and height are expressed in 600 dpi unit dpi must be 75, 150, 300, 600 or 1200 color is true for color scan, false for gray-levels gain value is 256*red_gain+16*green_gain+blue_gain if gain is given (ie <> 0), auto gain will not be performed returns UMAX1220P_OK on success, or one of the error above if successful, rbpp holds bytes/pixel, rth the height and rtw the width of scanned area expressed in pixels */ extern int sanei_umax_pp_start (int x, int y, int width, int height, int dpi, int color, int autoset, int gain, int offset, int *rbpp, int *rtw, int *rth); /* reads one block of data from scanner returns UMAX1220P_OK on success, or UMAX1220P_READ_FAILED on error it also sets internal cancel flag on error len if the length of the block needed window if the width in pixels of the scanned area dpi is the resolution, it is used to choose the best read method last is true if it is the last block of the scan buffer will hold the data read */ extern int sanei_umax_pp_read (long len, int window, int dpi, int last, unsigned char *buffer); /* get ASIC status from scanner returns UMAX1220P_OK if scanner idle, or UMAX1220P_BUSY if scanner's motor is on */ extern int sanei_umax_pp_status (void); /* set auto calibration 0: no, else yes */ extern void sanei_umax_pp_setauto (int mode); /* set umax astra model number */ extern void sanei_umax_pp_setastra (int val); /* set gamma tables */ extern void sanei_umax_pp_gamma (int *red, int *green, int *blue); /* sets coordinate of first usable left pixel */ extern int sanei_umax_pp_getLeft (void); #endif sane-backends-1.0.27/backend/kodak.h0000664000175000017500000001775212617742237014102 00000000000000#ifndef KODAK_H #define KODAK_H /* * Part of SANE - Scanner Access Now Easy. * Please see opening comment in kodak.c */ /* ------------------------------------------------------------------------- * This option list has to contain all options for all scanners supported by * this driver. If a certain scanner cannot handle a certain option, there's * still the possibility to say so, later. */ enum kodak_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_SOURCE, /*front/back/duplex*/ OPT_MODE, /*mono/ht/gray/color*/ OPT_RES, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_PAGE_WIDTH, OPT_PAGE_HEIGHT, OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_THRESHOLD, OPT_RIF, /* must come last: */ NUM_OPTIONS }; struct scanner { /* --------------------------------------------------------------------- */ /* immutable values which are set during init of scanner. */ struct scanner *next; char *device_name; /* The name of the scanner device for sane */ /* --------------------------------------------------------------------- */ /* immutable values which are set during reading of config file. */ int buffer_size; /* --------------------------------------------------------------------- */ /* immutable values which are set during inquiry probing of the scanner. */ /* members in order found in scsi data... */ SANE_Device sane; char vendor_name[9]; /* null-term data returned by SCSI inquiry.*/ char product_name[17]; /* null-term data returned by SCSI inquiry.*/ char version_name[5]; /* null-term data returned by SCSI inquiry.*/ char build_name[3]; /* null-term data returned by SCSI inquiry.*/ /* --------------------------------------------------------------------- */ /* immutable values which are set during INQUIRY probing of the scanner, */ /* or in the init_model cleanup routine... */ /* which modes scanner has */ int s_mode[4]; /* min and max resolution for each mode */ int s_res_min[4]; int s_res_max[4]; /* in 1/1200th inches, NOT sane units */ int s_width_min; int s_width_max; int s_length_min; int s_length_max; int s_brightness_steps; int s_contrast_steps; int s_threshold_steps; int s_rif; /* --------------------------------------------------------------------- */ /* changeable SANE_Option structs provide our interface to frontend. */ /* some options require lists of strings or numbers, we keep them here */ /* instead of in global vars so that they can differ for each scanner */ /* long array of option structs */ SANE_Option_Descriptor opt[NUM_OPTIONS]; /*mode group*/ SANE_String_Const o_source_list[4]; SANE_String_Const o_mode_list[5]; SANE_Int o_res_list[4][6]; /*geometry group*/ SANE_Range o_tl_x_range; SANE_Range o_tl_y_range; SANE_Range o_br_x_range; SANE_Range o_br_y_range; SANE_Range o_page_x_range; SANE_Range o_page_y_range; /*enhancement group*/ SANE_Range o_brightness_range; SANE_Range o_contrast_range; SANE_Range o_threshold_range; /* --------------------------------------------------------------------- */ /* changeable vars to hold user input. modified by SANE_Options above */ /*mode group*/ int u_mode; /* color,lineart,etc */ int u_source; /* adf front,adf duplex,etc */ int u_res; /* resolution in dpi */ /*geometry group*/ /* The desired size of the scan, all in 1/1200 inch */ int u_tl_x; int u_tl_y; int u_br_x; int u_br_y; int u_page_width; int u_page_height; /*enhancement group*/ int u_brightness; int u_contrast; int u_threshold; int u_rif; int u_compr; /* --------------------------------------------------------------------- */ /* values which are set by the scanner's post-scan image header */ int i_bytes; int i_id; int i_dpi; int i_tlx; int i_tly; int i_width; int i_length; int i_bpp; int i_compr; /* --------------------------------------------------------------------- */ /* values which are set by scanning functions to keep track of pages, etc */ int started; /* total to read/write */ int bytes_tot; /* how far we have read */ int bytes_rx; /* how far we have written */ int bytes_tx; /* size of buffer */ int bytes_buf; /* the buffer */ unsigned char * buffer; /* --------------------------------------------------------------------- */ /* values which used by the command and data sending functions (scsi/usb)*/ int fd; /* The scanner device file descriptor. */ size_t rs_info; }; #define DEFAULT_BUFFER_SIZE 32768 #define SIDE_FRONT 0 #define SIDE_BACK 1 #define SOURCE_ADF_FRONT 0 #define SOURCE_ADF_BACK 1 #define SOURCE_ADF_DUPLEX 2 #define MODE_LINEART 0 #define MODE_HALFTONE 1 #define MODE_GRAYSCALE 2 #define MODE_COLOR 3 /* ------------------------------------------------------------------------- */ #define MM_PER_INCH 25.4 #define MM_PER_UNIT_UNFIX SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0)) #define MM_PER_UNIT_FIX SANE_FIX(SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0))) #define SCANNER_UNIT_TO_FIXED_MM(number) SANE_FIX((number) * MM_PER_UNIT_UNFIX) #define FIXED_MM_TO_SCANNER_UNIT(number) SANE_UNFIX(number) / MM_PER_UNIT_UNFIX #define KODAK_CONFIG_FILE "kodak.conf" #ifndef PATH_MAX # define PATH_MAX 1024 #endif /* ------------------------------------------------------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle); SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking); SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp); const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info); SANE_Status sane_start (SANE_Handle handle); SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len); void sane_cancel (SANE_Handle h); void sane_close (SANE_Handle h); void sane_exit (void); /* ------------------------------------------------------------------------- */ static SANE_Status attach_one (const char *name); static SANE_Status connect_fd (struct scanner *s); static SANE_Status disconnect_fd (struct scanner *s); static SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg); static SANE_Status init_inquire (struct scanner *s); static SANE_Status init_model (struct scanner *s); static SANE_Status init_user (struct scanner *s); static SANE_Status init_options (struct scanner *s); static SANE_Status do_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ); #if 0 /* unused */ static SANE_Status wait_scanner (struct scanner *s); #endif static SANE_Status do_cancel (struct scanner *scanner); static SANE_Status set_window (struct scanner *s); static SANE_Status read_imageheader(struct scanner *s); static SANE_Status send_sc(struct scanner *s); static SANE_Status read_from_scanner(struct scanner *s); static SANE_Status copy_buffer(struct scanner *s, unsigned char * buf, int len); static SANE_Status read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len); static void hexdump (int level, char *comment, unsigned char *p, int l); static size_t maxStringSize (const SANE_String_Const strings[]); #endif /* KODAK_H */ sane-backends-1.0.27/backend/canon.c0000664000175000017500000017751612775277260014113 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 BYTEC GmbH Germany Written by Helmut Koeberle, Email: helmut.koeberle@bytec.de Modified by Manuel Panea and Markus Mertinat FB620 and FB1200 support by Mitsuru Okaniwa FS2710 support by Ulrich Deiters backend version: 1.13e This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* This file implements the sane-api */ /* SANE-FLOW-DIAGRAMM - sane_init() : initialize backend, attach scanners(devicename,0) . - sane_get_devices() : query list of scanner-devices . - sane_open() : open a particular scanner-device and attach_scanner(devicename,&dev) . . - sane_set_io_mode : set blocking-mode . . - sane_get_select_fd : get scanner-fd . . - sane_get_option_descriptor() : get option informations . . - sane_control_option() : change option values . . . . - sane_start() : start image aquisition . . - sane_get_parameters() : returns actual scan-parameters . . - sane_read() : read image-data (from pipe) . . - sane_cancel() : cancel operation, kill reader_process . - sane_close() : close opened scanner-device, do_cancel, free buffer and handle - sane_exit() : terminate use of backend, free devicename and device-struture */ /* This driver's flow: - sane_init . - attach_one . . - inquiry . . - test_unit_ready . . - medium_position . . - extended inquiry . . - mode sense . . - get_density_curve - sane_get_devices - sane_open . - init_options - sane_set_io_mode : set blocking-mode - sane_get_select_fd : get scanner-fd - sane_get_option_descriptor() : get option informations - sane_control_option() : change option values - sane_start() : start image aquisition - sane_get_parameters() : returns actual scan-parameters - sane_read() : read image-data (from pipe) - sane_cancel() : cancel operation, kill reader_process - sane_close() : close opened scanner-device, do_cancel, free buffer and handle - sane_exit() : terminate use of backend, free devicename and device-struture */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include /* for FB1200S */ #include /* for FB1200S */ #include /* for FB1200S */ #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #define BACKEND_NAME canon #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX #define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define CANON_CONFIG_FILE "canon.conf" #include #ifndef SANE_I18N #define SANE_I18N(text) text #endif static SANE_Byte primaryHigh[256], primaryLow[256], secondaryHigh[256], secondaryLow[256]; /* modification for FB1200S */ static int num_devices = 0; static CANON_Device *first_dev = NULL; static CANON_Scanner *first_handle = NULL; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; /* modification for FS2710 */ static const SANE_String_Const mode_list_fs2710[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_I18N("Raw"), 0 }; /* modification for FB620S */ static const SANE_String_Const mode_list_fb620[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, SANE_I18N("Fine color"), 0 }; /* modification for FB1200S */ static const SANE_String_Const mode_list_fb1200[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static const SANE_String_Const tpu_dc_mode_list[] = { SANE_I18N("No transparency correction"), SANE_I18N("Correction according to film type"), SANE_I18N("Correction according to transparency ratio"), 0 }; static const SANE_String_Const filmtype_list[] = { SANE_I18N("Negatives"), SANE_I18N("Slides"), 0 }; static const SANE_String_Const negative_filmtype_list[] = { "Kodak", "Fuji", "Agfa", "Konica", 0 }; static const SANE_String_Const scanning_speed_list[] = { SANE_I18N("Automatic"), SANE_I18N("Normal speed"), SANE_I18N("1/2 normal speed"), SANE_I18N("1/3 normal speed"), 0 }; static const SANE_String_Const tpu_filmtype_list[] = { "Film 0", "Film 1", "Film 2", "Film 3", 0 }; static const SANE_String_Const papersize_list[] = { "A4", "Letter", "B5", "Maximal", 0 }; /**************************************************/ static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; #include "canon-scsi.c" /**************************************************************************/ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; DBG (11, ">> max_string_size\n"); for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } DBG (11, "<< max_string_size\n"); return max_size; } /**************************************************************************/ static void get_tpu_stat (int fd, CANON_Device * dev) { unsigned char tbuf[12 + 5]; size_t buf_size, i; SANE_Status status; DBG (3, ">> get tpu stat\n"); memset (tbuf, 0, sizeof (tbuf)); buf_size = sizeof (tbuf); status = get_scan_mode (fd, TRANSPARENCY_UNIT, tbuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "get scan mode failed: %s\n", sane_strstatus (status)); return; } for (i = 0; i < buf_size; i++) DBG (3, "scan mode control byte[%d] = %d\n", (int) i, tbuf[i]); dev->tpu.Status = (tbuf[2 + 4 + 5] >> 7) ? TPU_STAT_INACTIVE : TPU_STAT_NONE; if (dev->tpu.Status != TPU_STAT_NONE) /* TPU available */ { dev->tpu.Status = (tbuf[2 + 4 + 5] & 0x04) ? TPU_STAT_INACTIVE : TPU_STAT_ACTIVE; } dev->tpu.ControlMode = tbuf[3 + 4 + 5] & 0x03; dev->tpu.Transparency = tbuf[4 + 4 + 5] * 256 + tbuf[5 + 4 + 5]; dev->tpu.PosNeg = tbuf[6 + 4 + 5] & 0x01; dev->tpu.FilmType = tbuf[7 + 4 + 5]; if(dev->tpu.FilmType > 3) dev->tpu.FilmType = 0; DBG (11, "TPU Status: %d\n", dev->tpu.Status); DBG (11, "TPU ControlMode: %d\n", dev->tpu.ControlMode); DBG (11, "TPU Transparency: %d\n", dev->tpu.Transparency); DBG (11, "TPU PosNeg: %d\n", dev->tpu.PosNeg); DBG (11, "TPU FilmType: %d\n", dev->tpu.FilmType); DBG (3, "<< get tpu stat\n"); return; } /**************************************************************************/ static void get_adf_stat (int fd, CANON_Device * dev) { size_t buf_size = 0x0C, i; unsigned char abuf[0x0C]; SANE_Status status; DBG (3, ">> get adf stat\n"); memset (abuf, 0, buf_size); status = get_scan_mode (fd, AUTO_DOC_FEEDER_UNIT, abuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "get scan mode failed: %s\n", sane_strstatus (status)); perror ("get scan mode failed"); return; } for (i = 0; i < buf_size; i++) DBG (3, "scan mode control byte[%d] = %d\n", (int) i, abuf[i]); dev->adf.Status = (abuf[ADF_Status] & ADF_NOT_PRESENT) ? ADF_STAT_NONE : ADF_STAT_INACTIVE; if (dev->adf.Status != ADF_STAT_NONE) /* ADF available / INACTIVE */ { dev->adf.Status = (abuf[ADF_Status] & ADF_PROBLEM) ? ADF_STAT_INACTIVE : ADF_STAT_ACTIVE; } dev->adf.Problem = (abuf[ADF_Status] & ADF_PROBLEM); dev->adf.Priority = (abuf[ADF_Settings] & ADF_PRIORITY); dev->adf.Feeder = (abuf[ADF_Settings] & ADF_FEEDER); DBG (11, "ADF Status: %d\n", dev->adf.Status); DBG (11, "ADF Priority: %d\n", dev->adf.Priority); DBG (11, "ADF Problem: %d\n", dev->adf.Problem); DBG (11, "ADF Feeder: %d\n", dev->adf.Feeder); DBG (3, "<< get adf stat\n"); return; } /**************************************************************************/ static SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg) { static char me[] = "canon_sense_handler"; u_char sense; int asc; char *sense_str = NULL; SANE_Status status; DBG (1, ">> sense_handler\n"); DBG (11, "%s(%ld, %p, %p)\n", me, (long) scsi_fd, (void *) result, (void *) arg); DBG (11, "sense buffer: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x\n", result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]); status = SANE_STATUS_GOOD; DBG(11, "sense data interpretation for SCSI-2 devices\n"); sense = result[2] & 0x0f; /* extract the sense key */ if (result[7] > 3) /* additional sense code available? */ { asc = (result[12] << 8) + result[13]; /* 12: additional sense code */ } /* 13: a.s.c. qualifier */ else asc = 0xffff; switch (sense) { case 0x00: DBG(11, "sense category: no error\n"); status = SANE_STATUS_GOOD; break; case 0x01: DBG(11, "sense category: recovered error\n"); switch (asc) { case 0x3700: sense_str = SANE_I18N("rounded parameter"); break; default: sense_str = SANE_I18N("unknown"); } status = SANE_STATUS_GOOD; break; case 0x03: DBG(11, "sense category: medium error\n"); switch (asc) { case 0x8000: sense_str = SANE_I18N("ADF jam"); break; case 0x8001: sense_str = SANE_I18N("ADF cover open"); break; default: sense_str = SANE_I18N("unknown"); } status = SANE_STATUS_IO_ERROR; break; case 0x04: DBG(11, "sense category: hardware error\n"); switch (asc) { case 0x6000: sense_str = SANE_I18N("lamp failure"); break; case 0x6200: sense_str = SANE_I18N("scan head positioning error"); break; case 0x8001: sense_str = SANE_I18N("CPU check error"); break; case 0x8002: sense_str = SANE_I18N("RAM check error"); break; case 0x8003: sense_str = SANE_I18N("ROM check error"); break; case 0x8004: sense_str = SANE_I18N("hardware check error"); break; case 0x8005: sense_str = SANE_I18N("transparency unit lamp failure"); break; case 0x8006: sense_str = SANE_I18N("transparency unit scan head " "positioning failure"); break; default: sense_str = SANE_I18N("unknown"); } status = SANE_STATUS_IO_ERROR; break; case 0x05: DBG(11, "sense category: illegal request\n"); switch (asc) { case 0x1a00: sense_str = SANE_I18N("parameter list length error"); status = SANE_STATUS_IO_ERROR; break; case 0x2000: sense_str = SANE_I18N("invalid command operation code"); status = SANE_STATUS_UNSUPPORTED; break; case 0x2400: sense_str = SANE_I18N("invalid field in CDB"); status = SANE_STATUS_IO_ERROR; break; case 0x2500: sense_str = SANE_I18N("unsupported LUN"); status = SANE_STATUS_UNSUPPORTED; break; case 0x2600: sense_str = SANE_I18N("invalid field in parameter list"); status = SANE_STATUS_UNSUPPORTED; break; case 0x2c00: sense_str = SANE_I18N("command sequence error"); status = SANE_STATUS_UNSUPPORTED; break; case 0x2c01: sense_str = SANE_I18N("too many windows specified"); status = SANE_STATUS_UNSUPPORTED; break; case 0x3a00: sense_str = SANE_I18N("medium not present"); status = SANE_STATUS_IO_ERROR; break; case 0x3d00: sense_str = SANE_I18N("invalid bit IDENTIFY message"); status = SANE_STATUS_UNSUPPORTED; break; case 0x8002: sense_str = SANE_I18N("option not connect"); status = SANE_STATUS_UNSUPPORTED; break; default: sense_str = SANE_I18N("unknown"); status = SANE_STATUS_UNSUPPORTED; } break; case 0x06: DBG(11, "sense category: unit attention\n"); switch (asc) { case 0x2900: sense_str = SANE_I18N("power on reset / bus device reset"); status = SANE_STATUS_GOOD; break; case 0x2a00: sense_str = SANE_I18N("parameter changed by another initiator"); status = SANE_STATUS_IO_ERROR; break; default: sense_str = SANE_I18N("unknown"); status = SANE_STATUS_IO_ERROR; } break; case 0x0b: DBG(11, "sense category: non-standard\n"); switch (asc) { case 0x0000: sense_str = SANE_I18N("no additional sense information"); status = SANE_STATUS_IO_ERROR; break; case 0x4500: sense_str = SANE_I18N("reselect failure"); status = SANE_STATUS_IO_ERROR; break; case 0x4700: sense_str = SANE_I18N("SCSI parity error"); status = SANE_STATUS_IO_ERROR; break; case 0x4800: sense_str = SANE_I18N("initiator detected error message " "received"); status = SANE_STATUS_IO_ERROR; break; case 0x4900: sense_str = SANE_I18N("invalid message error"); status = SANE_STATUS_UNSUPPORTED; break; case 0x8000: sense_str = SANE_I18N("timeout error"); status = SANE_STATUS_IO_ERROR; break; case 0x8001: sense_str = SANE_I18N("transparency unit shading error"); status = SANE_STATUS_IO_ERROR; break; case 0x8003: sense_str = SANE_I18N("lamp not stabilized"); status = SANE_STATUS_IO_ERROR; break; default: sense_str = SANE_I18N("unknown"); status = SANE_STATUS_IO_ERROR; } break; default: DBG(11, "sense category: else\n"); } DBG (11, "sense message: %s\n", sense_str); #if 0 /* superfluous? [U.D.] */ s->sense_str = sense_str; #endif DBG (1, "<< sense_handler\n"); return status; } /***************************************************************/ static SANE_Status do_gamma (CANON_Scanner * s) { SANE_Status status; u_char gbuf[256]; size_t buf_size; int i, j, neg, transfer_data_type, from; DBG (7, "sending SET_DENSITY_CURVE\n"); buf_size = 256 * sizeof (u_char); transfer_data_type = 0x03; neg = (s->hw->info.is_filmscanner) ? strcmp (filmtype_list[1], s->val[OPT_NEGATIVE].s) : s->val[OPT_HNEGATIVE].w; if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) { /* If scanning in gray mode, use the first curve for the scanner's monochrome gamma component */ for (j = 0; j < 256; j++) { if (!neg) { gbuf[j] = (u_char) s->gamma_table[0][j]; DBG (22, "set_density %d: gbuf[%d] = [%d]\n", 0, j, gbuf[j]); } else { gbuf[255 - j] = (u_char) (255 - s->gamma_table[0][j]); DBG (22, "set_density %d: gbuf[%d] = [%d]\n", 0, 255 - j, gbuf[255 - j]); } } if ((status = set_density_curve (s->fd, 0, gbuf, &buf_size, transfer_data_type)) != SANE_STATUS_GOOD) { DBG (7, "SET_DENSITY_CURVE\n"); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } } else { /* colour mode */ /* If in RGB mode but with gamma bind, use the first curve for all 3 colors red, green, blue */ for (i = 1; i < 4; i++) { from = (s->val[OPT_CUSTOM_GAMMA_BIND].w) ? 0 : i; for (j = 0; j < 256; j++) { if (!neg) { gbuf[j] = (u_char) s->gamma_table[from][j]; DBG (22, "set_density %d: gbuf[%d] = [%d]\n", i, j, gbuf[j]); } else { gbuf[255 - j] = (u_char) (255 - s->gamma_table[from][j]); DBG (22, "set_density %d: gbuf[%d] = [%d]\n", i, 255 - j, gbuf[255 - j]); } } if (s->hw->info.model == FS2710) status = set_density_curve_fs2710 (s, i, gbuf); else { if ((status = set_density_curve (s->fd, i, gbuf, &buf_size, transfer_data_type)) != SANE_STATUS_GOOD) { DBG (7, "SET_DENSITY_CURVE\n"); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } } } } return (SANE_STATUS_GOOD); } /**************************************************************************/ static SANE_Status attach (const char *devnam, CANON_Device ** devp) { SANE_Status status; CANON_Device *dev; int fd; u_char ibuf[36], ebuf[74], mbuf[12]; size_t buf_size, i; char *str; DBG (1, ">> attach\n"); for (dev = first_dev; dev; dev = dev->next) { if (!strcmp (dev->sane.name, devnam)) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } DBG (3, "attach: opening %s\n", devnam); status = sanei_scsi_open (devnam, &fd, sense_handler, dev); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } DBG (3, "attach: sending (standard) INQUIRY\n"); memset (ibuf, 0, sizeof (ibuf)); buf_size = sizeof (ibuf); status = inquiry (fd, 0, ibuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); fd = -1; return (status); } if (ibuf[0] != 6 || strncmp ((char *) (ibuf + 8), "CANON", 5) != 0 || strncmp ((char *) (ibuf + 16), "IX-", 3) != 0) { DBG (1, "attach: device doesn't look like a Canon scanner\n"); sanei_scsi_close (fd); fd = -1; return (SANE_STATUS_INVAL); } DBG (3, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); fd = -1; return (status); } #if 0 DBG (3, "attach: sending REQUEST SENSE\n"); memset (sbuf, 0, sizeof (sbuf)); buf_size = sizeof (sbuf); status = request_sense (fd, sbuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: REQUEST_SENSE failed\n"); sanei_scsi_close (fd); fd = -1; return (SANE_STATUS_INVAL); } DBG (3, "attach: sending MEDIUM POSITION\n"); status = medium_position (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MEDIUM POSITION failed\n"); sanei_scsi_close (fd); fd = -1; return (SANE_STATUS_INVAL); } /* s->val[OPT_AF_NOW].w == SANE_TRUE; */ #endif DBG (3, "attach: sending RESERVE UNIT\n"); status = reserve_unit (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: RESERVE UNIT failed\n"); sanei_scsi_close (fd); fd = -1; return (SANE_STATUS_INVAL); } #if 0 DBG (3, "attach: sending GET SCAN MODE for transparency unit\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = sizeof (ebuf); buf_size = 12; status = get_scan_mode (fd, TRANSPARENCY_UNIT, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET SCAN MODE for transparency unit failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } for (i = 0; i < buf_size; i++) DBG(3, "scan mode trans byte[%d] = %d\n", i, ebuf[i]); #endif DBG (3, "attach: sending GET SCAN MODE for scan control conditions\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = sizeof (ebuf); status = get_scan_mode (fd, SCAN_CONTROL_CONDITIONS, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET SCAN MODE for scan control conditions failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } for (i = 0; i < buf_size; i++) { DBG (3, "scan mode byte[%d] = %d\n", (int) i, ebuf[i]); } DBG (3, "attach: sending (extended) INQUIRY\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = sizeof (ebuf); status = inquiry (fd, 1, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: (extended) INQUIRY failed\n"); sanei_scsi_close (fd); fd = -1; return (SANE_STATUS_INVAL); } #if 0 DBG (3, "attach: sending GET SCAN MODE for transparency unit\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = 64; status = get_scan_mode (fd, ALL_SCAN_MODE_PAGES, /* transparency unit */ ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET SCAN MODE for scan control conditions failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } for (i = 0; i < buf_size; i++) DBG (3, "scan mode control byte[%d] = %d\n", i, ebuf[i]); #endif #if 0 DBG (3, "attach: sending GET SCAN MODE for all scan mode pages\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = 32; status = get_scan_mode (fd, (u_char)ALL_SCAN_MODE_PAGES, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET SCAN MODE for scan control conditions failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } for (i = 0; i < buf_size; i++) DBG(3, "scan mode control byte[%d] = %d\n", i, ebuf[i]); #endif DBG (3, "attach: sending MODE SENSE\n"); memset (mbuf, 0, sizeof (mbuf)); buf_size = sizeof (mbuf); status = mode_sense (fd, mbuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SENSE failed\n"); sanei_scsi_close (fd); fd = -1; return (SANE_STATUS_INVAL); } dev = malloc (sizeof (*dev)); if (!dev) { sanei_scsi_close (fd); fd = -1; return (SANE_STATUS_NO_MEM); } memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devnam); dev->sane.vendor = "CANON"; if ((str = calloc (16 + 1, 1)) == NULL) { sanei_scsi_close (fd); fd = -1; return (SANE_STATUS_NO_MEM); } strncpy (str, (char *) (ibuf + 16), 16); dev->sane.model = str; /* Register the fixed properties of the scanner below: - whether it is a film scanner or a flatbed scanner - whether it can have an automatic document feeder (ADF) - whether it can be equipped with a transparency unit (TPU) - whether it has got focus control - whether it can optimize image parameters (autoexposure) - whether it can calibrate itself - whether it can diagnose itself - whether it can eject the media - whether it can mirror the scanned data - whether it is a film scanner (or can be used as one) - whether it has fixed, hardware-set scan resolutions only */ if (!strncmp (str, "IX-27015", 8)) /* FS2700S */ { dev->info.model = CS2700; dev->sane.type = SANE_I18N("film scanner"); dev->adf.Status = ADF_STAT_NONE; dev->tpu.Status = TPU_STAT_NONE; dev->info.can_focus = SANE_TRUE; dev->info.can_autoexpose = SANE_TRUE; dev->info.can_calibrate = SANE_FALSE; dev->info.can_diagnose = SANE_FALSE; dev->info.can_eject = SANE_TRUE; dev->info.can_mirror = SANE_TRUE; dev->info.is_filmscanner = SANE_TRUE; dev->info.has_fixed_resolutions = SANE_TRUE; } else if (!strncmp (str, "IX-27025E", 9)) /* FS2710S */ { dev->info.model = FS2710; dev->sane.type = SANE_I18N("film scanner"); dev->adf.Status = ADF_STAT_NONE; dev->tpu.Status = TPU_STAT_NONE; dev->info.can_focus = SANE_TRUE; dev->info.can_autoexpose = SANE_TRUE; dev->info.can_calibrate = SANE_FALSE; dev->info.can_diagnose = SANE_FALSE; dev->info.can_eject = SANE_TRUE; dev->info.can_mirror = SANE_TRUE; dev->info.is_filmscanner = SANE_TRUE; dev->info.has_fixed_resolutions = SANE_TRUE; } else if (!strncmp (str, "IX-06035E", 9)) /* FB620S */ { dev->info.model = FB620; dev->sane.type = SANE_I18N("flatbed scanner"); dev->adf.Status = ADF_STAT_NONE; dev->tpu.Status = TPU_STAT_NONE; dev->info.can_focus = SANE_FALSE; dev->info.can_autoexpose = SANE_FALSE; dev->info.can_calibrate = SANE_TRUE; dev->info.can_diagnose = SANE_TRUE; dev->info.can_eject = SANE_FALSE; dev->info.can_mirror = SANE_FALSE; dev->info.is_filmscanner = SANE_FALSE; dev->info.has_fixed_resolutions = SANE_TRUE; } else if (!strncmp (str, "IX-12015E", 9)) /* FB1200S */ { dev->info.model = FB1200; dev->sane.type = SANE_I18N("flatbed scanner"); dev->adf.Status = ADF_STAT_INACTIVE; dev->tpu.Status = TPU_STAT_INACTIVE; dev->info.can_focus = SANE_FALSE; dev->info.can_autoexpose = SANE_FALSE; dev->info.can_calibrate = SANE_FALSE; dev->info.can_diagnose = SANE_FALSE; dev->info.can_eject = SANE_FALSE; dev->info.can_mirror = SANE_FALSE; dev->info.is_filmscanner = SANE_FALSE; dev->info.has_fixed_resolutions = SANE_TRUE; } else if (!strncmp (str, "IX-4015", 7)) /* IX-4015 */ { dev->info.model = IX4015; dev->sane.type = SANE_I18N("flatbed scanner"); dev->adf.Status = ADF_STAT_INACTIVE; dev->tpu.Status = TPU_STAT_INACTIVE; dev->info.can_focus = SANE_FALSE; dev->info.can_autoexpose = SANE_TRUE; dev->info.can_calibrate = SANE_FALSE; dev->info.can_diagnose = SANE_TRUE; dev->info.can_eject = SANE_FALSE; dev->info.can_mirror = SANE_TRUE; dev->info.is_filmscanner = SANE_FALSE; dev->info.has_fixed_resolutions = SANE_FALSE; } else /* CS300, CS600 */ { dev->info.model = CS3_600; dev->sane.type = SANE_I18N("flatbed scanner"); dev->adf.Status = ADF_STAT_INACTIVE; dev->tpu.Status = TPU_STAT_INACTIVE; dev->info.can_focus = SANE_FALSE; dev->info.can_autoexpose = SANE_FALSE; dev->info.can_calibrate = SANE_FALSE; dev->info.can_diagnose = SANE_FALSE; dev->info.can_eject = SANE_FALSE; dev->info.can_mirror = SANE_TRUE; dev->info.is_filmscanner = SANE_FALSE; dev->info.has_fixed_resolutions = SANE_FALSE; } DBG (5, "dev->sane.name = '%s'\n", dev->sane.name); DBG (5, "dev->sane.vendor = '%s'\n", dev->sane.vendor); DBG (5, "dev->sane.model = '%s'\n", dev->sane.model); DBG (5, "dev->sane.type = '%s'\n", dev->sane.type); if (dev->tpu.Status != TPU_STAT_NONE) get_tpu_stat (fd, dev); /* Query TPU */ if (dev->adf.Status != ADF_STAT_NONE) get_adf_stat (fd, dev); /* Query ADF */ dev->info.bmu = mbuf[6]; DBG (5, "bmu=%d\n", dev->info.bmu); dev->info.mud = (mbuf[8] << 8) + mbuf[9]; DBG (5, "mud=%d\n", dev->info.mud); dev->info.xres_default = (ebuf[5] << 8) + ebuf[6]; DBG (5, "xres_default=%d\n", dev->info.xres_default); dev->info.xres_range.max = (ebuf[10] << 8) + ebuf[11]; DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max); dev->info.xres_range.min = (ebuf[14] << 8) + ebuf[15]; DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min); dev->info.xres_range.quant = ebuf[9] >> 4; DBG (5, "xres_range.quant=%d\n", dev->info.xres_range.quant); dev->info.yres_default = (ebuf[7] << 8) + ebuf[8]; DBG (5, "yres_default=%d\n", dev->info.yres_default); dev->info.yres_range.max = (ebuf[12] << 8) + ebuf[13]; DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max); dev->info.yres_range.min = (ebuf[16] << 8) + ebuf[17]; DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min); dev->info.yres_range.quant = ebuf[9] & 0x0f; DBG (5, "xres_range.quant=%d\n", dev->info.xres_range.quant); dev->info.x_range.min = SANE_FIX (0.0); dev->info.x_range.max = (ebuf[20] << 24) + (ebuf[21] << 16) + (ebuf[22] << 8) + ebuf[23] - 1; dev->info.x_range.max = SANE_FIX (dev->info.x_range.max * MM_PER_INCH / dev->info.mud); DBG (5, "x_range.max=%d\n", dev->info.x_range.max); dev->info.x_range.quant = 0; dev->info.y_range.min = SANE_FIX (0.0); dev->info.y_range.max = (ebuf[24] << 24) + (ebuf[25] << 16) + (ebuf[26] << 8) + ebuf[27] - 1; dev->info.y_range.max = SANE_FIX (dev->info.y_range.max * MM_PER_INCH / dev->info.mud); DBG (5, "y_range.max=%d\n", dev->info.y_range.max); dev->info.y_range.quant = 0; dev->info.x_adf_range.max = (ebuf[30] << 24) + (ebuf[31] << 16) + (ebuf[32] << 8) + ebuf[33] - 1; DBG (5, "x_adf_range.max=%d\n", dev->info.x_adf_range.max); dev->info.y_adf_range.max = (ebuf[34] << 24) + (ebuf[35] << 16) + (ebuf[36] << 8) + ebuf[37] - 1; DBG (5, "y_adf_range.max=%d\n", dev->info.y_adf_range.max); dev->info.brightness_range.min = 0; dev->info.brightness_range.max = 255; dev->info.brightness_range.quant = 0; dev->info.contrast_range.min = 1; dev->info.contrast_range.max = 255; dev->info.contrast_range.quant = 0; dev->info.threshold_range.min = 1; dev->info.threshold_range.max = 255; dev->info.threshold_range.quant = 0; dev->info.HiliteR_range.min = 0; dev->info.HiliteR_range.max = 255; dev->info.HiliteR_range.quant = 0; dev->info.ShadowR_range.min = 0; dev->info.ShadowR_range.max = 254; dev->info.ShadowR_range.quant = 0; dev->info.HiliteG_range.min = 0; dev->info.HiliteG_range.max = 255; dev->info.HiliteG_range.quant = 0; dev->info.ShadowG_range.min = 0; dev->info.ShadowG_range.max = 254; dev->info.ShadowG_range.quant = 0; dev->info.HiliteB_range.min = 0; dev->info.HiliteB_range.max = 255; dev->info.HiliteB_range.quant = 0; dev->info.ShadowB_range.min = 0; dev->info.ShadowB_range.max = 254; dev->info.ShadowB_range.quant = 0; dev->info.focus_range.min = 0; dev->info.focus_range.max = 255; dev->info.focus_range.quant = 0; dev->info.TPU_Transparency_range.min = 0; dev->info.TPU_Transparency_range.max = 10000; dev->info.TPU_Transparency_range.quant = 100; sanei_scsi_close (fd); fd = -1; ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (1, "<< attach\n"); return (SANE_STATUS_GOOD); } /**************************************************************************/ static SANE_Status do_cancel (CANON_Scanner * s) { SANE_Status status; DBG (1, ">> do_cancel\n"); s->scanning = SANE_FALSE; if (s->fd >= 0) { if (s->val[OPT_EJECT_AFTERSCAN].w && !(s->val[OPT_PREVIEW].w && s->hw->info.is_filmscanner)) { DBG (3, "do_cancel: sending MEDIUM POSITION\n"); status = medium_position (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "do_cancel: MEDIUM POSITION failed\n"); return (SANE_STATUS_INVAL); } s->AF_NOW = SANE_TRUE; DBG (1, "do_cancel AF_NOW = '%d'\n", s->AF_NOW); } DBG (21, "do_cancel: reset_flag = %d\n", s->reset_flag); if ((s->reset_flag == 1) && (s->hw->info.model == FB620)) { status = reset_scanner (s->fd); if (status != SANE_STATUS_GOOD) { DBG (21, "RESET SCANNER failed\n"); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } DBG (21, "RESET SCANNER\n"); s->reset_flag = 0; DBG (21, "do_cancel: reset_flag = %d\n", s->reset_flag); s->time0 = -1; DBG (21, "time0 = %ld\n", s->time0); } if (s->hw->info.model == FB1200) { DBG (3, "CANCEL FB1200S\n"); status = cancel (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "CANCEL FB1200S failed\n"); return (SANE_STATUS_INVAL); } DBG (3, "CANCEL FB1200S OK\n"); } sanei_scsi_close (s->fd); s->fd = -1; } DBG (1, "<< do_cancel\n"); return (SANE_STATUS_CANCELLED); } /**************************************************************************/ static SANE_Status init_options (CANON_Scanner * s) { int i; DBG (1, ">> init_options\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); s->AF_NOW = SANE_TRUE; for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; switch (s->hw->info.model) { case FB620: s->opt[OPT_MODE].size = max_string_size (mode_list_fb620); s->opt[OPT_MODE].constraint.string_list = mode_list_fb620; s->val[OPT_MODE].s = strdup (mode_list_fb620[3]); break; case FB1200: s->opt[OPT_MODE].size = max_string_size (mode_list_fb1200); s->opt[OPT_MODE].constraint.string_list = mode_list_fb1200; s->val[OPT_MODE].s = strdup (mode_list_fb1200[2]); break; case FS2710: s->opt[OPT_MODE].size = max_string_size (mode_list_fs2710); s->opt[OPT_MODE].constraint.string_list = mode_list_fs2710; s->val[OPT_MODE].s = strdup (mode_list_fs2710[0]); break; default: s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[3]); } /* Slides or negatives */ s->opt[OPT_NEGATIVE].name = "film-type"; s->opt[OPT_NEGATIVE].title = SANE_I18N("Film type"); s->opt[OPT_NEGATIVE].desc = SANE_I18N("Selects the film type, i.e. " "negatives or slides"); s->opt[OPT_NEGATIVE].type = SANE_TYPE_STRING; s->opt[OPT_NEGATIVE].size = max_string_size (filmtype_list); s->opt[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_NEGATIVE].constraint.string_list = filmtype_list; s->opt[OPT_NEGATIVE].cap |= (s->hw->info.is_filmscanner)? 0 : SANE_CAP_INACTIVE; s->val[OPT_NEGATIVE].s = strdup (filmtype_list[1]); /* Negative film type */ s->opt[OPT_NEGATIVE_TYPE].name = "negative-film-type"; s->opt[OPT_NEGATIVE_TYPE].title = SANE_I18N("Negative film type"); s->opt[OPT_NEGATIVE_TYPE].desc = SANE_I18N("Selects the negative film type"); s->opt[OPT_NEGATIVE_TYPE].type = SANE_TYPE_STRING; s->opt[OPT_NEGATIVE_TYPE].size = max_string_size (negative_filmtype_list); s->opt[OPT_NEGATIVE_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_NEGATIVE_TYPE].constraint.string_list = negative_filmtype_list; s->opt[OPT_NEGATIVE_TYPE].cap |= SANE_CAP_INACTIVE; s->val[OPT_NEGATIVE_TYPE].s = strdup (negative_filmtype_list[0]); /* Scanning speed */ s->opt[OPT_SCANNING_SPEED].name = SANE_NAME_SCAN_SPEED; s->opt[OPT_SCANNING_SPEED].title = SANE_TITLE_SCAN_SPEED; s->opt[OPT_SCANNING_SPEED].desc = SANE_DESC_SCAN_SPEED; s->opt[OPT_SCANNING_SPEED].type = SANE_TYPE_STRING; s->opt[OPT_SCANNING_SPEED].size = max_string_size (scanning_speed_list); s->opt[OPT_SCANNING_SPEED].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SCANNING_SPEED].constraint.string_list = scanning_speed_list; s->opt[OPT_SCANNING_SPEED].cap |= (s->hw->info.model == CS2700) ? 0 : SANE_CAP_INACTIVE; if (s->hw->info.model != CS2700) s->opt[OPT_SCANNING_SPEED].cap &= ~SANE_CAP_SOFT_SELECT; s->val[OPT_SCANNING_SPEED].s = strdup (scanning_speed_list[0]); /* "Resolution" group: */ s->opt[OPT_RESOLUTION_GROUP].title = SANE_I18N("Scan resolution"); s->opt[OPT_RESOLUTION_GROUP].desc = ""; s->opt[OPT_RESOLUTION_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_RESOLUTION_GROUP].cap = 0; s->opt[OPT_RESOLUTION_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* bind resolution */ s->opt[OPT_RESOLUTION_BIND].name = SANE_NAME_RESOLUTION_BIND; s->opt[OPT_RESOLUTION_BIND].title = SANE_TITLE_RESOLUTION_BIND; s->opt[OPT_RESOLUTION_BIND].desc = SANE_DESC_RESOLUTION_BIND; s->opt[OPT_RESOLUTION_BIND].type = SANE_TYPE_BOOL; s->val[OPT_RESOLUTION_BIND].w = SANE_TRUE; /* hardware resolutions only */ s->opt[OPT_HW_RESOLUTION_ONLY].name = "hw-resolution-only"; s->opt[OPT_HW_RESOLUTION_ONLY].title = SANE_I18N("Hardware resolution"); s->opt[OPT_HW_RESOLUTION_ONLY].desc = SANE_I18N("Use only hardware " "resolutions"); s->opt[OPT_HW_RESOLUTION_ONLY].type = SANE_TYPE_BOOL; s->val[OPT_HW_RESOLUTION_ONLY].w = SANE_TRUE; s->opt[OPT_HW_RESOLUTION_ONLY].cap |= (s->hw->info.has_fixed_resolutions)? 0 : SANE_CAP_INACTIVE; /* x-resolution */ s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; if (s->hw->info.has_fixed_resolutions) { int iCnt; float iRes; /* modification for FB620S */ s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; iCnt = 0; iRes = s->hw->info.xres_range.max; DBG (5, "hw->info.xres_range.max=%d\n", s->hw->info.xres_range.max); s->opt[OPT_X_RESOLUTION].constraint.word_list = s->xres_word_list; /* go to minimum resolution by dividing by 2 */ while (iRes >= s->hw->info.xres_range.min) iRes /= 2; /* fill array up to maximum resolution */ while (iRes < s->hw->info.xres_range.max) { iRes *= 2; s->xres_word_list[++iCnt] = iRes; } s->xres_word_list[0] = iCnt; s->val[OPT_X_RESOLUTION].w = s->xres_word_list[2]; } else { s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_X_RESOLUTION].constraint.range = &s->hw->info.xres_range; s->val[OPT_X_RESOLUTION].w = 300; } /* y-resolution */ s->opt[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION; s->opt[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION; s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_Y_RESOLUTION; s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; if (s->hw->info.has_fixed_resolutions) { int iCnt; float iRes; /* modification for FB620S */ s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; iCnt = 0; iRes = s->hw->info.yres_range.max; DBG (5, "hw->info.yres_range.max=%d\n", s->hw->info.yres_range.max); s->opt[OPT_Y_RESOLUTION].constraint.word_list = s->yres_word_list; /* go to minimum resolution by dividing by 2 */ while (iRes >= s->hw->info.yres_range.min) iRes /= 2; /* fill array up to maximum resolution */ while (iRes < s->hw->info.yres_range.max) { iRes *= 2; s->yres_word_list[++iCnt] = iRes; } s->yres_word_list[0] = iCnt; s->val[OPT_Y_RESOLUTION].w = s->yres_word_list[2]; } else { s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_Y_RESOLUTION].constraint.range = &s->hw->info.yres_range; s->val[OPT_Y_RESOLUTION].w = 300; } /* Focus group: */ s->opt[OPT_FOCUS_GROUP].title = SANE_I18N("Focus"); s->opt[OPT_FOCUS_GROUP].desc = ""; s->opt[OPT_FOCUS_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_FOCUS_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_FOCUS_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_FOCUS_GROUP].cap |= (s->hw->info.can_focus) ? 0 : SANE_CAP_INACTIVE; /* Auto-Focus switch */ s->opt[OPT_AF].name = "af"; s->opt[OPT_AF].title = SANE_I18N("Auto focus"); s->opt[OPT_AF].desc = SANE_I18N("Enable/disable auto focus"); s->opt[OPT_AF].type = SANE_TYPE_BOOL; s->opt[OPT_AF].cap |= (s->hw->info.can_focus) ? 0 : SANE_CAP_INACTIVE; s->val[OPT_AF].w = s->hw->info.can_focus; /* Auto-Focus once switch */ s->opt[OPT_AF_ONCE].name = "afonce"; s->opt[OPT_AF_ONCE].title = SANE_I18N("Auto focus only once"); s->opt[OPT_AF_ONCE].desc = SANE_I18N("Do auto focus only once between " "ejects"); s->opt[OPT_AF_ONCE].type = SANE_TYPE_BOOL; s->opt[OPT_AF_ONCE].cap |= (s->hw->info.can_focus) ? 0 : SANE_CAP_INACTIVE; s->val[OPT_AF_ONCE].w = s->hw->info.can_focus; /* Manual focus */ s->opt[OPT_FOCUS].name = "focus"; s->opt[OPT_FOCUS].title = SANE_I18N("Manual focus position"); s->opt[OPT_FOCUS].desc = SANE_I18N("Set the optical system's focus " "position by hand (default: 128)."); s->opt[OPT_FOCUS].type = SANE_TYPE_INT; s->opt[OPT_FOCUS].unit = SANE_UNIT_NONE; s->opt[OPT_FOCUS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_FOCUS].constraint.range = &s->hw->info.focus_range; s->opt[OPT_FOCUS].cap |= (s->hw->info.can_focus) ? 0 : SANE_CAP_INACTIVE; s->val[OPT_FOCUS].w = (s->hw->info.can_focus) ? 128 : 0; /* Margins group: */ s->opt[OPT_MARGINS_GROUP].title = SANE_I18N("Scan margins"); s->opt[OPT_MARGINS_GROUP].desc = ""; s->opt[OPT_MARGINS_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MARGINS_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_MARGINS_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->info.x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->info.y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->info.x_range; s->val[OPT_BR_X].w = s->hw->info.x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->info.y_range; s->val[OPT_BR_Y].w = s->hw->info.y_range.max; /* Colors group: */ s->opt[OPT_COLORS_GROUP].title = SANE_I18N("Extra color adjustments"); s->opt[OPT_COLORS_GROUP].desc = ""; s->opt[OPT_COLORS_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_COLORS_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_COLORS_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Positive/Negative switch for the CanoScan 300/600 models */ s->opt[OPT_HNEGATIVE].name = SANE_NAME_NEGATIVE; s->opt[OPT_HNEGATIVE].title = SANE_TITLE_NEGATIVE; s->opt[OPT_HNEGATIVE].desc = SANE_DESC_NEGATIVE; s->opt[OPT_HNEGATIVE].type = SANE_TYPE_BOOL; s->opt[OPT_HNEGATIVE].cap |= (s->hw->info.model == CS2700 || s->hw->info.model == FS2710) ? SANE_CAP_INACTIVE : 0; s->val[OPT_HNEGATIVE].w = SANE_FALSE; /* Same values for highlight and shadow points for red, green, blue */ s->opt[OPT_BIND_HILO].name = "bind-highlight-shadow-points"; s->opt[OPT_BIND_HILO].title = SANE_TITLE_RGB_BIND; s->opt[OPT_BIND_HILO].desc = SANE_DESC_RGB_BIND; s->opt[OPT_BIND_HILO].type = SANE_TYPE_BOOL; s->opt[OPT_BIND_HILO].cap |= (s->hw->info.model == FB620 || s->hw->info.model == IX4015) ? SANE_CAP_INACTIVE : 0; s->val[OPT_BIND_HILO].w = SANE_TRUE; /* highlight point for red */ s->opt[OPT_HILITE_R].name = SANE_NAME_HIGHLIGHT_R; s->opt[OPT_HILITE_R].title = SANE_TITLE_HIGHLIGHT_R; s->opt[OPT_HILITE_R].desc = SANE_DESC_HIGHLIGHT_R; s->opt[OPT_HILITE_R].type = SANE_TYPE_INT; s->opt[OPT_HILITE_R].unit = SANE_UNIT_NONE; s->opt[OPT_HILITE_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_HILITE_R].constraint.range = &s->hw->info.HiliteR_range; s->opt[OPT_HILITE_R].cap |= SANE_CAP_INACTIVE; s->val[OPT_HILITE_R].w = 255; /* shadow point for red */ s->opt[OPT_SHADOW_R].name = SANE_NAME_SHADOW_R; s->opt[OPT_SHADOW_R].title = SANE_TITLE_SHADOW_R; s->opt[OPT_SHADOW_R].desc = SANE_DESC_SHADOW_R; s->opt[OPT_SHADOW_R].type = SANE_TYPE_INT; s->opt[OPT_SHADOW_R].unit = SANE_UNIT_NONE; s->opt[OPT_SHADOW_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_SHADOW_R].constraint.range = &s->hw->info.ShadowR_range; s->opt[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; s->val[OPT_SHADOW_R].w = 0; /* highlight point for green */ s->opt[OPT_HILITE_G].name = SANE_NAME_HIGHLIGHT; s->opt[OPT_HILITE_G].title = SANE_TITLE_HIGHLIGHT; s->opt[OPT_HILITE_G].desc = SANE_DESC_HIGHLIGHT; s->opt[OPT_HILITE_G].type = SANE_TYPE_INT; s->opt[OPT_HILITE_G].unit = SANE_UNIT_NONE; s->opt[OPT_HILITE_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_HILITE_G].constraint.range = &s->hw->info.HiliteG_range; s->opt[OPT_HILITE_G].cap |= (s->hw->info.model == IX4015) ? SANE_CAP_INACTIVE : 0; s->val[OPT_HILITE_G].w = 255; /* shadow point for green */ s->opt[OPT_SHADOW_G].name = SANE_NAME_SHADOW; s->opt[OPT_SHADOW_G].title = SANE_TITLE_SHADOW; s->opt[OPT_SHADOW_G].desc = SANE_DESC_SHADOW; s->opt[OPT_SHADOW_G].type = SANE_TYPE_INT; s->opt[OPT_SHADOW_G].unit = SANE_UNIT_NONE; s->opt[OPT_SHADOW_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_SHADOW_G].constraint.range = &s->hw->info.ShadowG_range; s->opt[OPT_SHADOW_G].cap |= (s->hw->info.model == IX4015) ? SANE_CAP_INACTIVE : 0; s->val[OPT_SHADOW_G].w = 0; /* highlight point for blue */ s->opt[OPT_HILITE_B].name = SANE_NAME_HIGHLIGHT_B; s->opt[OPT_HILITE_B].title = SANE_TITLE_HIGHLIGHT_B; s->opt[OPT_HILITE_B].desc = SANE_DESC_HIGHLIGHT_B; s->opt[OPT_HILITE_B].type = SANE_TYPE_INT; s->opt[OPT_HILITE_B].unit = SANE_UNIT_NONE; s->opt[OPT_HILITE_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_HILITE_B].constraint.range = &s->hw->info.HiliteB_range; s->opt[OPT_HILITE_B].cap |= SANE_CAP_INACTIVE; s->val[OPT_HILITE_B].w = 255; /* shadow point for blue */ s->opt[OPT_SHADOW_B].name = SANE_NAME_SHADOW_B; s->opt[OPT_SHADOW_B].title = SANE_TITLE_SHADOW_B; s->opt[OPT_SHADOW_B].desc = SANE_DESC_SHADOW_B; s->opt[OPT_SHADOW_B].type = SANE_TYPE_INT; s->opt[OPT_SHADOW_B].unit = SANE_UNIT_NONE; s->opt[OPT_SHADOW_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_SHADOW_B].constraint.range = &s->hw->info.ShadowB_range; s->opt[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; s->val[OPT_SHADOW_B].w = 0; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->info.brightness_range; s->opt[OPT_BRIGHTNESS].cap |= 0; s->val[OPT_BRIGHTNESS].w = 128; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &s->hw->info.contrast_range; s->opt[OPT_CONTRAST].cap |= 0; s->val[OPT_CONTRAST].w = 128; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &s->hw->info.threshold_range; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->val[OPT_THRESHOLD].w = 128; s->opt[OPT_MIRROR].name = "mirror"; s->opt[OPT_MIRROR].title = SANE_I18N("Mirror image"); s->opt[OPT_MIRROR].desc = SANE_I18N("Mirror the image horizontally"); s->opt[OPT_MIRROR].type = SANE_TYPE_BOOL; s->opt[OPT_MIRROR].cap |= (s->hw->info.can_mirror) ? 0: SANE_CAP_INACTIVE; s->val[OPT_MIRROR].w = SANE_FALSE; /* analog-gamma curve */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* bind analog-gamma */ s->opt[OPT_CUSTOM_GAMMA_BIND].name = "bind-custom-gamma"; s->opt[OPT_CUSTOM_GAMMA_BIND].title = SANE_TITLE_RGB_BIND; s->opt[OPT_CUSTOM_GAMMA_BIND].desc = SANE_DESC_RGB_BIND; s->opt[OPT_CUSTOM_GAMMA_BIND].type = SANE_TYPE_BOOL; s->opt[OPT_CUSTOM_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; s->val[OPT_CUSTOM_GAMMA_BIND].w = SANE_TRUE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; s->opt[OPT_AE].name = "ae"; s->opt[OPT_AE].title = SANE_I18N("Auto exposure"); s->opt[OPT_AE].desc = SANE_I18N("Enable/disable the auto exposure feature"); s->opt[OPT_AE].cap |= (s->hw->info.can_autoexpose) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_AE].type = SANE_TYPE_BOOL; s->val[OPT_AE].w = SANE_FALSE; /* "Calibration" group */ s->opt[OPT_CALIBRATION_GROUP].title = SANE_I18N("Calibration"); s->opt[OPT_CALIBRATION_GROUP].desc = ""; s->opt[OPT_CALIBRATION_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_CALIBRATION_GROUP].cap |= (s->hw->info.can_calibrate || s->hw->info.can_diagnose) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_CALIBRATION_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* calibration now */ s->opt[OPT_CALIBRATION_NOW].name = "calibration-now"; s->opt[OPT_CALIBRATION_NOW].title = SANE_I18N("Calibration now"); s->opt[OPT_CALIBRATION_NOW].desc = SANE_I18N("Execute calibration *now*"); s->opt[OPT_CALIBRATION_NOW].type = SANE_TYPE_BUTTON; s->opt[OPT_CALIBRATION_NOW].unit = SANE_UNIT_NONE; s->opt[OPT_CALIBRATION_NOW].cap |= (s->hw->info.can_calibrate) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_CALIBRATION_NOW].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_CALIBRATION_NOW].constraint.range = NULL; /* scanner self diagnostic */ s->opt[OPT_SCANNER_SELF_DIAGNOSTIC].name = "self-diagnostic"; s->opt[OPT_SCANNER_SELF_DIAGNOSTIC].title = SANE_I18N("Self diagnosis"); s->opt[OPT_SCANNER_SELF_DIAGNOSTIC].desc = SANE_I18N("Perform scanner " "self diagnosis"); s->opt[OPT_SCANNER_SELF_DIAGNOSTIC].type = SANE_TYPE_BUTTON; s->opt[OPT_SCANNER_SELF_DIAGNOSTIC].unit = SANE_UNIT_NONE; s->opt[OPT_SCANNER_SELF_DIAGNOSTIC].cap |= (s->hw->info.can_diagnose) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_SCANNER_SELF_DIAGNOSTIC].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_SCANNER_SELF_DIAGNOSTIC].constraint.range = NULL; /* reset scanner for FB620S */ s->opt[OPT_RESET_SCANNER].name = "reset-scanner"; s->opt[OPT_RESET_SCANNER].title = SANE_I18N("Reset scanner"); s->opt[OPT_RESET_SCANNER].desc = SANE_I18N("Reset the scanner"); s->opt[OPT_RESET_SCANNER].type = SANE_TYPE_BUTTON; s->opt[OPT_RESET_SCANNER].unit = SANE_UNIT_NONE; s->opt[OPT_RESET_SCANNER].cap |= (s->hw->info.model == FB620) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_RESET_SCANNER].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_RESET_SCANNER].constraint.range = NULL; /* "Eject" group (active only for film scanners) */ s->opt[OPT_EJECT_GROUP].title = SANE_I18N("Medium handling"); s->opt[OPT_EJECT_GROUP].desc = ""; s->opt[OPT_EJECT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_EJECT_GROUP].cap |= (s->hw->info.can_eject) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_EJECT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* eject after scan */ s->opt[OPT_EJECT_AFTERSCAN].name = "eject-after-scan"; s->opt[OPT_EJECT_AFTERSCAN].title = SANE_I18N("Eject film after each scan"); s->opt[OPT_EJECT_AFTERSCAN].desc = SANE_I18N("Automatically eject the " "film from the device after each scan"); s->opt[OPT_EJECT_AFTERSCAN].cap |= (s->hw->info.can_eject) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_EJECT_AFTERSCAN].type = SANE_TYPE_BOOL; /* IX-4015 requires medium_position command after cancel */ s->val[OPT_EJECT_AFTERSCAN].w = (s->hw->info.model == IX4015) ? SANE_TRUE : SANE_FALSE; /* eject before exit */ s->opt[OPT_EJECT_BEFOREEXIT].name = "eject-before-exit"; s->opt[OPT_EJECT_BEFOREEXIT].title = SANE_I18N("Eject film before exit"); s->opt[OPT_EJECT_BEFOREEXIT].desc = SANE_I18N("Automatically eject the " "film from the device before exiting the program"); s->opt[OPT_EJECT_BEFOREEXIT].cap |= (s->hw->info.can_eject) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_EJECT_BEFOREEXIT].type = SANE_TYPE_BOOL; s->val[OPT_EJECT_BEFOREEXIT].w = s->hw->info.can_eject; /* eject now */ s->opt[OPT_EJECT_NOW].name = "eject-now"; s->opt[OPT_EJECT_NOW].title = SANE_I18N("Eject film now"); s->opt[OPT_EJECT_NOW].desc = SANE_I18N("Eject the film *now*"); s->opt[OPT_EJECT_NOW].type = SANE_TYPE_BUTTON; s->opt[OPT_EJECT_NOW].unit = SANE_UNIT_NONE; s->opt[OPT_EJECT_NOW].cap |= (s->hw->info.can_eject) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_EJECT_NOW].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_EJECT_NOW].constraint.range = NULL; /* "NO-ADF" option: */ s->opt[OPT_ADF_GROUP].title = SANE_I18N("Document feeder extras"); s->opt[OPT_ADF_GROUP].desc = ""; s->opt[OPT_ADF_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ADF_GROUP].cap = 0; s->opt[OPT_ADF_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_FLATBED_ONLY].name = "noadf"; s->opt[OPT_FLATBED_ONLY].title = SANE_I18N("Flatbed only"); s->opt[OPT_FLATBED_ONLY].desc = SANE_I18N("Disable auto document feeder " "and use flatbed only"); s->opt[OPT_FLATBED_ONLY].type = SANE_TYPE_BOOL; s->opt[OPT_FLATBED_ONLY].unit = SANE_UNIT_NONE; s->opt[OPT_FLATBED_ONLY].size = sizeof (SANE_Word); s->opt[OPT_FLATBED_ONLY].cap |= (s->hw->adf.Status == ADF_STAT_NONE) ? SANE_CAP_INACTIVE : 0; s->val[OPT_FLATBED_ONLY].w = SANE_FALSE; /* "TPU" group: */ s->opt[OPT_TPU_GROUP].title = SANE_I18N("Transparency unit"); s->opt[OPT_TPU_GROUP].desc = ""; s->opt[OPT_TPU_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_TPU_GROUP].cap = 0; s->opt[OPT_TPU_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_TPU_GROUP].cap |= (s->hw->tpu.Status != TPU_STAT_NONE) ? 0 : SANE_CAP_INACTIVE; /* Transparency Unit (FAU, Film Adapter Unit) */ s->opt[OPT_TPU_ON].name = "transparency-unit-on-off"; s->opt[OPT_TPU_ON].title = SANE_I18N("Transparency unit"); s->opt[OPT_TPU_ON].desc = SANE_I18N("Switch on/off the transparency unit " "(FAU, film adapter unit)"); s->opt[OPT_TPU_ON].type = SANE_TYPE_BOOL; s->opt[OPT_TPU_ON].unit = SANE_UNIT_NONE; s->val[OPT_TPU_ON].w = (s->hw->tpu.Status == TPU_STAT_ACTIVE) ? SANE_TRUE : SANE_FALSE; s->opt[OPT_TPU_ON].cap |= (s->hw->tpu.Status != TPU_STAT_NONE) ? 0 : SANE_CAP_INACTIVE; s->opt[OPT_TPU_PN].name = "transparency-unit-negative-film"; s->opt[OPT_TPU_PN].title = SANE_I18N("Negative film"); s->opt[OPT_TPU_PN].desc = SANE_I18N("Positive or negative film"); s->opt[OPT_TPU_PN].type = SANE_TYPE_BOOL; s->opt[OPT_TPU_PN].unit = SANE_UNIT_NONE; s->val[OPT_TPU_PN].w = s->hw->tpu.PosNeg; s->opt[OPT_TPU_PN].cap |= (s->hw->tpu.Status == TPU_STAT_ACTIVE) ? 0 : SANE_CAP_INACTIVE; /* density control mode */ s->opt[OPT_TPU_DCM].name = "TPMDC"; s->opt[OPT_TPU_DCM].title = SANE_I18N("Density control"); s->opt[OPT_TPU_DCM].desc = SANE_I18N("Set density control mode"); s->opt[OPT_TPU_DCM].type = SANE_TYPE_STRING; s->opt[OPT_TPU_DCM].size = max_string_size (tpu_dc_mode_list); s->opt[OPT_TPU_DCM].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_TPU_DCM].constraint.string_list = tpu_dc_mode_list; s->val[OPT_TPU_DCM].s = strdup (tpu_dc_mode_list[s->hw->tpu.ControlMode]); s->opt[OPT_TPU_DCM].cap |= (s->hw->tpu.Status == TPU_STAT_ACTIVE) ? 0 : SANE_CAP_INACTIVE; /* Transparency Ratio */ s->opt[OPT_TPU_TRANSPARENCY].name = "Transparency-Ratio"; s->opt[OPT_TPU_TRANSPARENCY].title = SANE_I18N("Transparency ratio"); s->opt[OPT_TPU_TRANSPARENCY].desc = ""; s->opt[OPT_TPU_TRANSPARENCY].type = SANE_TYPE_INT; s->opt[OPT_TPU_TRANSPARENCY].unit = SANE_UNIT_NONE; s->opt[OPT_TPU_TRANSPARENCY].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TPU_TRANSPARENCY].constraint.range = &s->hw->info.TPU_Transparency_range; s->val[OPT_TPU_TRANSPARENCY].w = s->hw->tpu.Transparency; s->opt[OPT_TPU_TRANSPARENCY].cap |= (s->hw->tpu.Status == TPU_STAT_ACTIVE && s->hw->tpu.ControlMode == 3) ? 0 : SANE_CAP_INACTIVE; /* Select Film type */ s->opt[OPT_TPU_FILMTYPE].name = "Filmtype"; s->opt[OPT_TPU_FILMTYPE].title = SANE_I18N("Select film type"); s->opt[OPT_TPU_FILMTYPE].desc = SANE_I18N("Select the film type"); s->opt[OPT_TPU_FILMTYPE].type = SANE_TYPE_STRING; s->opt[OPT_TPU_FILMTYPE].size = max_string_size (tpu_filmtype_list); s->opt[OPT_TPU_FILMTYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_TPU_FILMTYPE].constraint.string_list = tpu_filmtype_list; s->val[OPT_TPU_FILMTYPE].s = strdup (tpu_filmtype_list[s->hw->tpu.FilmType]); s->opt[OPT_TPU_FILMTYPE].cap |= (s->hw->tpu.Status == TPU_STAT_ACTIVE && s->hw->tpu.ControlMode == 1) ? 0 : SANE_CAP_INACTIVE; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = SANE_FALSE; DBG (1, "<< init_options\n"); return SANE_STATUS_GOOD; } /**************************************************************************/ static SANE_Status attach_one (const char *dev) { DBG (1, ">> attach_one\n"); attach (dev, 0); DBG (1, "<< attach_one\n"); return SANE_STATUS_GOOD; } /**************************************************************************/ static SANE_Status do_focus (CANON_Scanner * s) { SANE_Status status; u_char ebuf[74]; size_t buf_size; DBG (3, "do_focus: sending GET FILM STATUS\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = 4; status = get_film_status (s->fd, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "do_focus: GET FILM STATUS failed\n"); if (status == SANE_STATUS_UNSUPPORTED) return (SANE_STATUS_GOOD); else { DBG (1, "do_focus: ... for unknown reasons\n"); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } } DBG (3, "focus point before autofocus : %d\n", ebuf[3]); status = execute_auto_focus (s->fd, s->val[OPT_AF].w, (s->scanning_speed == 0 && !s->RIF && s->hw->info.model == CS2700), (int) s->AE, s->val[OPT_FOCUS].w); if (status != SANE_STATUS_GOOD) { DBG (7, "execute_auto_focus failed\n"); if (status == SANE_STATUS_UNSUPPORTED) return (SANE_STATUS_GOOD); else { DBG (1, "do_focus: ... for unknown reasons\n"); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } } DBG (3, "do_focus: sending GET FILM STATUS\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = 4; status = get_film_status (s->fd, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "do_focus: GET FILM STATUS failed\n"); if (status == SANE_STATUS_UNSUPPORTED) return (SANE_STATUS_GOOD); else { DBG (1, "do_focus: ... for unknown reasons\n"); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } } else DBG (3, "focus point after autofocus : %d\n", ebuf[3]); return (SANE_STATUS_GOOD); } /**************************************************************************/ #include "canon-sane.c" sane-backends-1.0.27/backend/hpsj5s.c0000664000175000017500000011766512775312261014217 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Max Vorobiev This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #define BUILD 3 #define BACKEND_NAME hpsj5s #define HPSJ5S_CONFIG_FILE "hpsj5s.conf" #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" #include "hpsj5s.h" #include #include #include #include #define LINES_TO_FEED 480 /*Default feed length */ static int scanner_d = -1; /*This is handler to the only-supported. Will be fixed. */ static char scanner_path[PATH_MAX] = ""; /*String for device-file */ static SANE_Byte bLastCalibration; /*Here we store calibration result */ static SANE_Byte bCalibration; /*Here we store new calibration value */ static SANE_Byte bHardwareState; /*Here we store copy of hardware flags register */ /*Here we store Parameters:*/ static SANE_Word wWidth = 2570; /*Scan area width */ static SANE_Word wResolution = 300; /*Resolution in DPI */ static SANE_Frame wCurrentFormat = SANE_FRAME_GRAY; /*Type of colors in image */ static SANE_Int wCurrentDepth = 8; /*Bits per pixel in image */ /*Here we count lines of every new image...*/ static SANE_Word wVerticalResolution; /*Limits for resolution control*/ static const SANE_Range ImageWidthRange = { 0, /*minimal */ 2570, /*maximum */ 2 /*quant */ }; static const SANE_Word ImageResolutionsList[] = { 6, /*Number of resolutions */ 75, 100, 150, 200, 250, 300 }; static SANE_Option_Descriptor sod[] = { { /*Number of options */ SANE_NAME_NUM_OPTIONS, SANE_TITLE_NUM_OPTIONS, SANE_DESC_NUM_OPTIONS, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} /*No constraints required */ } , { /*Width of scaned area */ "width", "Width", "Width of area to scan", SANE_TYPE_INT, SANE_UNIT_PIXEL, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {NULL} /*Range constrain setted in sane_init */ } , { /*Resolution for scan */ "resolution", "Resolution", "Image resolution", SANE_TYPE_INT, SANE_UNIT_DPI, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_WORD_LIST, {NULL} /*Word list constrain setted in sane_init */ } }; static SANE_Parameters parms; /*Recalculate Lenght in dependace of resolution*/ static SANE_Word LengthForRes (SANE_Word Resolution, SANE_Word Length) { switch (Resolution) { case 75: return Length / 4; case 100: return Length / 3; case 150: return Length / 2; case 200: return Length * 2 / 3; case 250: return Length * 5 / 6; case 300: default: return Length; } } static struct parport_list pl; /*List of detected parallel ports. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char line[PATH_MAX]; /*Line from config file */ FILE *config_file; /*Handle to config file of this backend */ DBG_INIT (); DBG (1, ">>sane_init"); DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); DBG (1, "sane_init: SANE hpsj5s backend version %d.%d.%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); /*Inform about supported version */ if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); /*Open configuration file for this backend */ config_file = sanei_config_open (HPSJ5S_CONFIG_FILE); if (!config_file) /*Failed to open config file */ { DBG (1, "sane_init: no config file found."); return SANE_STATUS_GOOD; } /*Read line by line */ while (sanei_config_read (line, PATH_MAX, config_file)) { if ((line[0] == '#') || (line[0] == '\0')) /*comment line or empty line */ continue; strcpy (scanner_path, line); /*so, we choose last in file (uncommented) */ } fclose (config_file); /*We don't need config file any more */ /*sanei_config_attach_matching_devices(devname, attach_one); To do latter */ scanner_d = -1; /*scanner device not opened yet. */ DBG (1, "<= NELEMS (dev)) /*No such device */ return SANE_STATUS_INVAL; if (scanner_d != -1) /*scanner opened already! */ return SANE_STATUS_DEVICE_BUSY; DBG (1, "sane_open: scanner device path name is \'%s\'\n", scanner_path); scanner_d = OpenScanner (scanner_path); if (scanner_d == -1) return SANE_STATUS_DEVICE_BUSY; /*This should be done more carefully */ /*Check device. */ DBG (1, "sane_open: check scanner started."); if (DetectScanner () == 0) { /*Device malfunction! */ DBG (1, "sane_open: Device malfunction."); CloseScanner (scanner_d); scanner_d = -1; return SANE_STATUS_IO_ERROR; } DBG (1, "sane_open: Device found.All are green."); *handle = (SANE_Handle) (unsigned long)scanner_d; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { DBG (2, "sane_close\n"); /*We support only single device - so ignore handle (FIX IT LATER) */ if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1)) return; /* wrong device */ StandByScanner (); CloseScanner (scanner_d); scanner_d = -1; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { DBG (2, "sane_get_option_descriptor: option = %d\n", option); if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1)) return NULL; /* wrong device */ if (option < 0 || option >= NELEMS (sod)) /*No real options supported */ return NULL; return &sod[option]; /*Return demanded option */ } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1)) return SANE_STATUS_INVAL; /* wrong device */ if ((option >= NELEMS (sod)) || (option < 0)) /*Supported only this option */ return SANE_STATUS_INVAL; switch (option) { case 0: /*Number of options */ if (action != SANE_ACTION_GET_VALUE) /*It can be only read */ return SANE_STATUS_INVAL; *((SANE_Int *) value) = NELEMS (sod); return SANE_STATUS_GOOD; case 1: /*Scan area width */ switch (action) { case SANE_ACTION_GET_VALUE: *((SANE_Word *) value) = wWidth; return SANE_STATUS_GOOD; case SANE_ACTION_SET_VALUE: /*info should be setted */ wWidth = *((SANE_Word *) value); if (info != NULL) *info = SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } case 2: /*Resolution */ switch (action) { case SANE_ACTION_GET_VALUE: *((SANE_Word *) value) = wResolution; return SANE_STATUS_GOOD; case SANE_ACTION_SET_VALUE: /*info should be setted */ wResolution = *((SANE_Word *) value); if (info != NULL) *info = 0; return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; /*For now we have no options to control */ } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { DBG (2, "sane_get_parameters\n"); if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1)) return SANE_STATUS_INVAL; /* wrong device */ /*Ignore handle parameter for now. FIX it latter. */ /*These parameters are OK for gray scale mode. */ parms.depth = /*wCurrentDepth */ 8; parms.format = /*wCurrentFormat */ SANE_FRAME_GRAY; parms.last_frame = SANE_TRUE; /*For grayscale... */ parms.lines = -1; /*Unknown a priory */ parms.pixels_per_line = LengthForRes (wResolution, wWidth); /*For grayscale... */ parms.bytes_per_line = parms.pixels_per_line; /*For grayscale... */ *params = parms; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { int i; DBG (2, "sane_start\n"); if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1)) return SANE_STATUS_IO_ERROR; CallFunctionWithParameter (0x93, 2); bLastCalibration = CallFunctionWithRetVal (0xA9); if (bLastCalibration == 0) bLastCalibration = -1; /*Turn on the lamp: */ CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, FLAGS_HW_LAMP_ON); bHardwareState = FLAGS_HW_LAMP_ON; /*Get average white point */ bCalibration = GetCalibration (); if (bLastCalibration - bCalibration > 16) { /*Lamp is not warm enouth */ DBG (1, "sane_start: warming lamp for 30 sec.\n"); for (i = 0; i < 30; i++) sleep (1); } /*Check paper presents */ if (CheckPaperPresent () == 0) { DBG (1, "sane_start: no paper detected."); return SANE_STATUS_NO_DOCS; } CalibrateScanElements (); TransferScanParameters (GrayScale, wResolution, wWidth); /*Turn on indicator and prepare engine. */ SwitchHardwareState (FLAGS_HW_INDICATOR_OFF | FLAGS_HW_MOTOR_READY, 1); /*Feed paper */ if (PaperFeed (LINES_TO_FEED) == 0) /*Feed only for fixel lenght. Change it */ { DBG (1, "sane_start: paper feed failed."); SwitchHardwareState (FLAGS_HW_INDICATOR_OFF | FLAGS_HW_MOTOR_READY, 0); return SANE_STATUS_JAMMED; } /*Set paper moving speed */ TurnOnPaperPulling (GrayScale, wResolution); wVerticalResolution = 0; /*Reset counter */ return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { SANE_Byte bFuncResult, bTest; int timeout; if (!length) { DBG (1, "sane_read: length == NULL\n"); return SANE_STATUS_INVAL; } *length = 0; if (!data) { DBG (1, "sane_read: data == NULL\n"); return SANE_STATUS_INVAL; } if ((handle != (SANE_Handle) (unsigned long)scanner_d) || (scanner_d == -1)) { DBG (1, "sane_read: unknown handle\n"); return SANE_STATUS_INVAL; } /*While end of paper sheet was not reached */ /*Wait for scaned line ready */ timeout = 0; while (((bFuncResult = CallFunctionWithRetVal (0xB2)) & 0x20) == 0) { bTest = CallFunctionWithRetVal (0xB5); usleep (1); timeout++; if ((timeout < 1000) && (((bTest & 0x80) && ((bTest & 0x3F) <= 2)) || (((bTest & 0x80) == 0) && ((bTest & 0x3F) >= 5)))) continue; if (timeout >= 1000) continue; /*do it again! */ /*Data ready state! */ if ((bFuncResult & 0x20) != 0) /*End of paper reached! */ { *length = 0; return SANE_STATUS_EOF; } /*Data ready */ *length = LengthForRes (wResolution, wWidth); if (*length >= max_length) *length = max_length; CallFunctionWithParameter (0xCD, 0); CallFunctionWithRetVal (0xC8); WriteScannerRegister (REGISTER_FUNCTION_CODE, 0xC8); WriteAddress (ADDRESS_RESULT); /*Test if we need this line for current resolution (scanner doesn't control vertical resolution in hardware) */ wVerticalResolution -= wResolution; if (wVerticalResolution > 0) { timeout = 0; continue; } else wVerticalResolution = 300; /*Reset counter */ ReadDataBlock (data, *length); /*switch indicator */ bHardwareState ^= FLAGS_HW_INDICATOR_OFF; CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, bHardwareState); return SANE_STATUS_GOOD; } return SANE_STATUS_EOF; } void sane_cancel (SANE_Handle handle) { DBG (2, "sane_cancel: handle = %p\n", handle); /*Stop motor */ TurnOffPaperPulling (); /*Indicator turn off */ bHardwareState |= FLAGS_HW_INDICATOR_OFF; CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, bHardwareState); /*Get out of paper */ ReleasePaper (); /*Restore indicator */ bHardwareState &= ~FLAGS_HW_INDICATOR_OFF; CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, bHardwareState); bLastCalibration = CallFunctionWithRetVal (0xA9); CallFunctionWithParameter (0xA9, bLastCalibration); CallFunctionWithParameter (0x93, 4); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, non_blocking); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", handle, fd ? "!=" : "="); return SANE_STATUS_UNSUPPORTED; } /* Middle-level API: */ /* Detect if scanner present and works correctly. Ret Val: 0 = detection failed, 1 = detection OK. */ static int DetectScanner (void) { int Result1, Result2; int Successful, Total; Result1 = OutputCheck (); Result2 = InputCheck (); if (!(Result1 || Result2)) /*If all are 0 - it's error */ { return 0; } WriteScannerRegister (0x7C, 0x80); WriteScannerRegister (0x7F, 0x1); WriteScannerRegister (0x72, 0x10); WriteScannerRegister (0x72, 0x90); WriteScannerRegister (0x7C, 0x24); WriteScannerRegister (0x75, 0x0C); WriteScannerRegister (0x78, 0x0); WriteScannerRegister (0x79, 0x10); WriteScannerRegister (0x71, 0x10); WriteScannerRegister (0x71, 0x1); WriteScannerRegister (0x72, 0x1); for (Successful = 0, Total = 0; Total < 5; Total++) { if (CallCheck ()) Successful++; if (Successful >= 3) return 1; /*Correct and Stable */ } return 0; } static void StandByScanner () { WriteScannerRegister (0x74, 0x80); WriteScannerRegister (0x75, 0x0C); WriteScannerRegister (0x77, 0x0); WriteScannerRegister (0x78, 0x0); WriteScannerRegister (0x79, 0x0); WriteScannerRegister (0x7A, 0x0); WriteScannerRegister (0x7B, 0x0); WriteScannerRegister (0x7C, 0x4); WriteScannerRegister (0x70, 0x0); WriteScannerRegister (0x72, 0x90); WriteScannerRegister (0x70, 0x0); } static void SwitchHardwareState (SANE_Byte mask, SANE_Byte invert_mask) { if (!invert_mask) { bHardwareState &= ~mask; } else bHardwareState |= mask; CallFunctionWithParameter (FUNCTION_SETUP_HARDWARE, bHardwareState); } /*return value: 0 - no paper, 1 - paper loaded.*/ static int CheckPaperPresent () { if ((CallFunctionWithRetVal (0xB2) & 0x10) == 0) return 1; /*Ok - paper present. */ return 0; /*No paper present */ } static int ReleasePaper () { int i; if ((CallFunctionWithRetVal (0xB2) & 0x20) == 0) { /*End of paper was not reached */ CallFunctionWithParameter (0xA7, 0xF); CallFunctionWithParameter (0xA8, 0xFF); CallFunctionWithParameter (0xC2, 0); for (i = 0; i < 90000; i++) { if (CallFunctionWithRetVal (0xB2) & 0x80) break; usleep (1); } if (i >= 90000) return 0; /*Fail. */ for (i = 0; i < 90000; i++) { if ((CallFunctionWithRetVal (0xB2) & 0x20) == 0) break; else if ((CallFunctionWithRetVal (0xB2) & 0x80) == 0) { i = 90000; break; } usleep (1); } CallFunctionWithParameter (0xC5, 0); if (i >= 90000) return 0; /*Fail. */ while (CallFunctionWithRetVal (0xB2) & 0x80); /*Wait bit dismiss */ CallFunctionWithParameter (0xA7, 1); CallFunctionWithParameter (0xA8, 0x25); CallFunctionWithParameter (0xC2, 0); for (i = 0; i < 90000; i++) { if (CallFunctionWithRetVal (0xB2) & 0x80) break; usleep (1); } if (i >= 90000) return 0; /*Fail. */ for (i = 0; i < 90000; i++) { if ((CallFunctionWithRetVal (0xB2) & 0x80) == 0) break; usleep (1); } if (i >= 90000) return 0; /*Fail. */ } if (CallFunctionWithRetVal (0xB2) & 0x10) { CallFunctionWithParameter (0xA7, 1); CallFunctionWithParameter (0xA8, 0x40); } else { CallFunctionWithParameter (0xA7, 0); CallFunctionWithParameter (0xA8, 0xFA); } CallFunctionWithParameter (0xC2, 0); for (i = 0; i < 9000; i++) { if (CallFunctionWithRetVal (0xB2) & 0x80) break; usleep (1); } if (i >= 9000) return 0; /*Fail. */ while (CallFunctionWithRetVal (0xB2) & 0x80) usleep (1); return 1; } static void TransferScanParameters (enumColorDepth enColor, SANE_Word wResolution, SANE_Word wPixelsLength) { SANE_Word wRightBourder = (2570 + wPixelsLength) / 2 + 65; SANE_Word wLeftBourder = (2570 - wPixelsLength) / 2 + 65; switch (enColor) { case Drawing: CallFunctionWithParameter (0x90, 2); /*Not supported correctle. FIX ME!!! */ break; case Halftone: CallFunctionWithParameter (0x90, 0xE3); /*Not supported correctly. FIX ME!!! */ CallFunctionWithParameter (0x92, 3); break; case GrayScale: case TrueColor: CallFunctionWithParameter (0x90, 0); /*Not suppoted correctly. FIX ME!!! */ break; }; CallFunctionWithParameter (0xA1, 2); CallFunctionWithParameter (0xA2, 1); CallFunctionWithParameter (0xA3, 0x98); /*Resolution: */ CallFunctionWithParameter (0x9A, (SANE_Byte) (wResolution >> 8)); /*High byte */ CallFunctionWithParameter (0x9B, (SANE_Byte) wResolution); /*Low byte */ LoadingPaletteToScanner (); CallFunctionWithParameter (0xA4, 31); /*Some sort of constant parameter */ /*Left bourder */ CallFunctionWithParameter (0xA5, wLeftBourder / 256); CallFunctionWithParameter (0xA6, wLeftBourder % 256); /*Right bourder */ CallFunctionWithParameter (0xAA, wRightBourder / 256); CallFunctionWithParameter (0xAB, wRightBourder % 256); CallFunctionWithParameter (0xD0, 0); CallFunctionWithParameter (0xD1, 0); CallFunctionWithParameter (0xD2, 0); CallFunctionWithParameter (0xD3, 0); CallFunctionWithParameter (0xD4, 0); CallFunctionWithParameter (0xD5, 0); CallFunctionWithParameter (0x9D, 5); } static void TurnOnPaperPulling (enumColorDepth enColor, SANE_Word wResolution) { switch (enColor) { case Drawing: case Halftone: CallFunctionWithParameter (0x91, 0xF7); return; case GrayScale: switch (wResolution) { case 50: case 75: case 100: CallFunctionWithParameter (0x91, 0xB7); return; case 150: case 200: CallFunctionWithParameter (0x91, 0x77); return; case 250: case 300: CallFunctionWithParameter (0x91, 0x37); return; default: return; } case TrueColor: switch (wResolution) { case 75: case 100: CallFunctionWithParameter (0x91, 0xA3); return; case 150: case 200: CallFunctionWithParameter (0x91, 0x53); return; case 250: case 300: CallFunctionWithParameter (0x91, 0x3); return; default: return; } default: return; } } static void TurnOffPaperPulling () { CallFunctionWithParameter (0x91, 0); } /* Returns avarage value of scaned row. While paper not loaded this is base "white point". */ static SANE_Byte GetCalibration () { int i; int Result; SANE_Byte Buffer[2600]; SANE_Byte bTest; CallFunctionWithParameter (0xA1, 2); CallFunctionWithParameter (0xA2, 1); CallFunctionWithParameter (0xA3, 0x98); /*Resolution to 300 DPI */ CallFunctionWithParameter (0x9A, 1); CallFunctionWithParameter (0x9B, 0x2C); CallFunctionWithParameter (0x92, 0); CallFunctionWithParameter (0xC6, 0); CallFunctionWithParameter (0x92, 0x80); for (i = 1; i < 256; i++) CallFunctionWithParameter (0xC6, i); for (i = 0; i < 256; i++) CallFunctionWithParameter (0xC6, i); for (i = 0; i < 256; i++) CallFunctionWithParameter (0xC6, i); CallFunctionWithParameter (0xA4, 31); /*Some sort of constant */ /*Left bourder */ CallFunctionWithParameter (0xA5, 0); CallFunctionWithParameter (0xA6, 0x41); /*Right bourder */ CallFunctionWithParameter (0xAA, 0xA); CallFunctionWithParameter (0xAB, 0x39); CallFunctionWithParameter (0xD0, 0); CallFunctionWithParameter (0xD1, 0); CallFunctionWithParameter (0xD2, 0); CallFunctionWithParameter (0xD3, 0); CallFunctionWithParameter (0xD4, 0); CallFunctionWithParameter (0xD5, 0); CallFunctionWithParameter (0x9C, 0x1B); CallFunctionWithParameter (0x9D, 5); CallFunctionWithParameter (0x92, 0x10); CallFunctionWithParameter (0xC6, 0xFF); CallFunctionWithParameter (0x92, 0x90); for (i = 0; i < 2999; i++) CallFunctionWithParameter (0xC6, 0xFF); CallFunctionWithParameter (0x92, 0x50); CallFunctionWithParameter (0xC6, 0); CallFunctionWithParameter (0x92, 0xD0); for (i = 0; i < 2999; i++) CallFunctionWithParameter (0xC6, 0); CallFunctionWithParameter (0x98, 0xFF); /*Up limit */ CallFunctionWithParameter (0x95, 0); /*Low limit */ CallFunctionWithParameter (0x90, 0); /*Gray scale... */ CallFunctionWithParameter (0x91, 0x3B); /*Turn motor on. */ for (i = 0; i < 5; i++) { do { /*WARNING!!! Deadlock possible! */ bTest = CallFunctionWithRetVal (0xB5); } while ((((bTest & 0x80) == 1) && ((bTest & 0x3F) <= 2)) || (((bTest & 0x80) == 0) && ((bTest & 0x3F) >= 5))); CallFunctionWithParameter (0xCD, 0); /*Skip this line for ECP: */ CallFunctionWithRetVal (0xC8); WriteScannerRegister (REGISTER_FUNCTION_CODE, 0xC8); WriteAddress (0x20); ReadDataBlock (Buffer, 2552); }; CallFunctionWithParameter (0x91, 0); /*Turn off motor. */ usleep (10); for (Result = 0, i = 0; i < 2552; i++) Result += Buffer[i]; return Result / 2552; } static int PaperFeed (SANE_Word wLinesToFeed) { int i; CallFunctionWithParameter (0xA7, 0xF); CallFunctionWithParameter (0xA8, 0xFF); CallFunctionWithParameter (0xC2, 0); for (i = 0; i < 9000; i++) { if (CallFunctionWithRetVal (0xB2) & 0x80) break; usleep (1); } if (i >= 9000) return 0; /*Fail. */ for (i = 0; i < 9000; i += 5) { if ((CallFunctionWithRetVal (0xB2) & 0x20) == 0) break; else if ((CallFunctionWithRetVal (0xB2) & 0x80) == 0) { i = 9000; break; } usleep (5); } CallFunctionWithParameter (0xC5, 0); if (i >= 9000) return 0; /*Fail. */ /*Potential deadlock */ while (CallFunctionWithRetVal (0xB2) & 0x80); /*Wait bit dismiss */ CallFunctionWithParameter (0xA7, wLinesToFeed / 256); CallFunctionWithParameter (0xA8, wLinesToFeed % 256); CallFunctionWithParameter (0xC2, 0); for (i = 0; i < 9000; i++) { if (CallFunctionWithRetVal (0xB2) & 0x80) break; usleep (1); } if (i >= 9000) return 0; /*Fail. */ for (i = 0; i < 9000; i++) { if ((CallFunctionWithRetVal (0xB2) & 0x80) == 0) break; usleep (1); } if (i >= 9000) return 0; /*Fail. */ return 1; } /*For now we do no calibrate elements - just set maximum limits. FIX ME?*/ static void CalibrateScanElements () { /*Those arrays will be used in future for correct calibration. */ /*Then we need to transfer UP brightness border, we use these registers */ SANE_Byte arUpTransferBorders[] = { 0x10, 0x20, 0x30 }; /*Then we need to transfer LOW brightness border, we use these registers */ SANE_Byte arLowTransferBorders[] = { 0x50, 0x60, 0x70 }; /*Then we need to save UP brightness border, we use these registers */ SANE_Byte arUpSaveBorders[] = { 0x98, 0x97, 0x99 }; /*Then we need to save LOW brightness border, we use these registers */ SANE_Byte arLowSaveBorders[] = { 0x95, 0x94, 0x96 }; /*Speeds, used for calibration */ SANE_Byte arSpeeds[] = { 0x3B, 0x37, 0x3F }; int j, Average, Temp, Index, /* Line, */ timeout,Calibration; SANE_Byte bTest /*, Min, Max, Result */ ; /*For current color component: (values from arrays). Next two lines - starting and terminating. */ SANE_Byte CurrentUpTransferBorder; SANE_Byte CurrentLowTransferBorder; SANE_Byte CurrentUpSaveBorder; SANE_Byte CurrentLowSaveBorder; SANE_Byte CurrentSpeed1, CurrentSpeed2; SANE_Byte CorrectionValue; SANE_Byte FilteredBuffer[2570]; CallFunctionWithParameter (0xA1, 2); CallFunctionWithParameter (0xA2, 0); CallFunctionWithParameter (0xA3, 0x98); /*DPI = 300 */ CallFunctionWithParameter (0x9A, 1); /*High byte */ CallFunctionWithParameter (0x9B, 0x2C); /*Low byte */ /*Paletter settings. */ CallFunctionWithParameter (0x92, 0); CallFunctionWithParameter (0xC6, 0); CallFunctionWithParameter (0x92, 0x80); /*First color component */ for (j = 1; j < 256; j++) CallFunctionWithParameter (0xC6, j); /*Second color component */ for (j = 0; j < 256; j++) CallFunctionWithParameter (0xC6, j); /*Third color component */ for (j = 0; j < 256; j++) CallFunctionWithParameter (0xC6, j); CallFunctionWithParameter (0xA4, 31); /*Left border */ CallFunctionWithParameter (0xA5, 0); /*High byte */ CallFunctionWithParameter (0xA6, 0x41); /*Low byte */ /*Right border */ CallFunctionWithParameter (0xAA, 0xA); /*High byte */ CallFunctionWithParameter (0xAB, 0x4B); /*Low byte */ /*Zero these registers... */ CallFunctionWithParameter (0xD0, 0); CallFunctionWithParameter (0xD1, 0); CallFunctionWithParameter (0xD2, 0); CallFunctionWithParameter (0xD3, 0); CallFunctionWithParameter (0xD4, 0); CallFunctionWithParameter (0xD5, 0); CallFunctionWithParameter (0x9C, 0x1B); CallFunctionWithParameter (0x9D, 0x5); Average = 0; for (Index = 0; Index < 3; Index++) /*For theree color components */ { /*Up border = 0xFF */ CallFunctionWithParameter (0x92, arUpTransferBorders[Index]); CallFunctionWithParameter (0xC6, 0xFF); CallFunctionWithParameter (0x92, arUpTransferBorders[Index] | 0x80); for (j = 2999; j > 0; j--) CallFunctionWithParameter (0xC6, 0xFF); /*Low border = 0x0 */ CallFunctionWithParameter (0x92, arLowTransferBorders[Index]); CallFunctionWithParameter (0xC6, 0x0); CallFunctionWithParameter (0x92, arLowTransferBorders[Index] | 0x80); for (j = 2999; j > 0; j--) CallFunctionWithParameter (0xC6, 0x0); /*Save borders */ CallFunctionWithParameter (arUpSaveBorders[Index], 0xFF); CallFunctionWithParameter (arLowSaveBorders[Index], 0x0); CallFunctionWithParameter (0x90, 0); /*Gray Scale or True color sign :) */ CallFunctionWithParameter (0x91, arSpeeds[Index]); /*waiting for scaned line... */ timeout = 0; do { bTest = CallFunctionWithRetVal (0xB5); timeout++; usleep (1); } while ((timeout < 1000) && ((((bTest & 0x80) == 1) && ((bTest & 0x3F) <= 2)) || (((bTest & 0x80) == 0) && ((bTest & 0x3F) >= 5)))); /*Let's read it... */ if(timeout < 1000) { CallFunctionWithParameter (0xCD, 0); CallFunctionWithRetVal (0xC8); WriteScannerRegister (0x70, 0xC8); WriteAddress (0x20); ReadDataBlock (FilteredBuffer, 2570); } CallFunctionWithParameter (0x91, 0); /*Stop engine. */ /*Note: if first read failed, junk would be calculated, but if previous read was succeded, but last one failed, previous data'ld be used. */ for(Temp = 0, j = 0; j < 2570; j++) Temp += FilteredBuffer[j]; Temp /= 2570; if((Average == 0)||(Average > Temp)) Average = Temp; } for(Index = 0; Index < 3; Index++) /*Three color components*/ { CurrentUpTransferBorder = arUpTransferBorders[Index]; CallFunctionWithParameter (0xC6, 0xFF); CallFunctionWithParameter (0x92, CurrentUpTransferBorder|0x80); for(j=2999; j>0; j--) CallFunctionWithParameter (0xC6, 0xFF); CurrentLowTransferBorder = arLowTransferBorders[Index]; CallFunctionWithParameter (0xC6, 0x0); CallFunctionWithParameter (0x92, CurrentLowTransferBorder|0x80); for(j=2999; j>0; j--) CallFunctionWithParameter (0xC6, 0); CurrentUpSaveBorder = arUpSaveBorders[Index]; CallFunctionWithParameter (CurrentUpSaveBorder, 0xFF); CurrentLowSaveBorder = arLowSaveBorders[Index]; CallFunctionWithParameter (CurrentLowSaveBorder, 0x0); CallFunctionWithParameter (0x90,0); Calibration = 0x80; CallFunctionWithParameter (CurrentUpSaveBorder, 0x80); CurrentSpeed1 = CurrentSpeed2 = arSpeeds[Index]; for(CorrectionValue = 0x40; CorrectionValue != 0;CorrectionValue >>= 2) { CallFunctionWithParameter (0x91, CurrentSpeed2); usleep(10); /*waiting for scaned line... */ for(j = 0; j < 5; j++) { timeout = 0; do { bTest = CallFunctionWithRetVal (0xB5); timeout++; usleep (1); } while ((timeout < 1000) && ((((bTest & 0x80) == 1) && ((bTest & 0x3F) <= 2)) || (((bTest & 0x80) == 0) && ((bTest & 0x3F) >= 5)))); /*Let's read it... */ if(timeout < 1000) { CallFunctionWithParameter (0xCD, 0); CallFunctionWithRetVal (0xC8); WriteScannerRegister (0x70, 0xC8); WriteAddress (0x20); ReadDataBlock (FilteredBuffer, 2570); } }/*5 times we read. I don't understand what for, but so does HP's driver. Perhaps, we can optimize it in future.*/ WriteScannerRegister (0x91, 0); usleep(10); for(Temp = 0,j = 0; j < 16;j++) Temp += FilteredBuffer[509+j]; /*At this offset calcalates HP's driver.*/ Temp /= 16; if(Average > Temp) { Calibration += CorrectionValue; Calibration = 0xFF < Calibration ? 0xFF : Calibration; /*min*/ } else Calibration -= CorrectionValue; WriteScannerRegister (CurrentUpSaveBorder, Calibration); }/*By CorrectionValue we tune UpSaveBorder*/ WriteScannerRegister (0x90, 8); WriteScannerRegister (0x91, CurrentSpeed1); usleep(10); }/*By color components*/ return; } /* Internal use functions: */ /*Returns 0 in case of fail and 1 in success.*/ static int OutputCheck () { int i; WriteScannerRegister (0x7F, 0x1); WriteAddress (0x7E); for (i = 0; i < 256; i++) WriteData ((SANE_Byte) i); WriteAddress (0x3F); if (ReadDataByte () & 0x80) return 0; return 1; } static int InputCheck () { int i; SANE_Byte Buffer[256]; WriteAddress (0x3E); for (i = 0; i < 256; i++) { Buffer[i] = ReadDataByte (); } for (i = 0; i < 256; i++) { if (Buffer[i] != i) return 0; } return 1; } static int CallCheck () { int i; SANE_Byte Buffer[256]; CallFunctionWithParameter (0x92, 0x10); CallFunctionWithParameter (0xC6, 0x0); CallFunctionWithParameter (0x92, 0x90); WriteScannerRegister (REGISTER_FUNCTION_CODE, 0xC6); WriteAddress (0x60); for (i = 1; i < 256; i++) WriteData ((SANE_Byte) i); CallFunctionWithParameter (0x92, 0x10); CallFunctionWithRetVal (0xC6); CallFunctionWithParameter (0x92, 0x90); WriteScannerRegister (REGISTER_FUNCTION_CODE, 0xC6); WriteAddress (ADDRESS_RESULT); ReadDataBlock (Buffer, 256); for (i = 0; i < 255; i++) { if (Buffer[i + 1] != (SANE_Byte) i) return 0; } return 1; } static void LoadingPaletteToScanner () { /*For now we have statical gamma. */ SANE_Byte Gamma[256]; int i; for (i = 0; i < 256; i++) Gamma[i] = i; CallFunctionWithParameter (0x92, 0); CallFunctionWithParameter (0xC6, Gamma[0]); CallFunctionWithParameter (0x92, 0x80); for (i = 1; i < 256; i++) CallFunctionWithParameter (0xC6, Gamma[i]); for (i = 0; i < 256; i++) CallFunctionWithParameter (0xC6, Gamma[i]); for (i = 0; i < 256; i++) CallFunctionWithParameter (0xC6, Gamma[i]); } /* Low level warappers: */ static void WriteAddress (SANE_Byte Address) { ieee1284_data_dir (pl.portv[scanner_d], 0); /*Forward mode */ ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT); ieee1284_epp_write_addr (pl.portv[scanner_d], 0, (char *) &Address, 1); } static void WriteData (SANE_Byte Data) { ieee1284_data_dir (pl.portv[scanner_d], 0); /*Forward mode */ ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT); ieee1284_epp_write_data (pl.portv[scanner_d], 0, (char *) &Data, 1); } static void WriteScannerRegister (SANE_Byte Address, SANE_Byte Data) { WriteAddress (Address); WriteData (Data); } static void CallFunctionWithParameter (SANE_Byte Function, SANE_Byte Parameter) { WriteScannerRegister (REGISTER_FUNCTION_CODE, Function); WriteScannerRegister (REGISTER_FUNCTION_PARAMETER, Parameter); } static SANE_Byte CallFunctionWithRetVal (SANE_Byte Function) { WriteScannerRegister (REGISTER_FUNCTION_CODE, Function); WriteAddress (ADDRESS_RESULT); return ReadDataByte (); } static SANE_Byte ReadDataByte () { SANE_Byte Result; ieee1284_data_dir (pl.portv[scanner_d], 1); /*Reverse mode */ ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT); ieee1284_epp_read_data (pl.portv[scanner_d], 0, (char *) &Result, 1); return Result; } static void ReadDataBlock (SANE_Byte * Buffer, int length) { ieee1284_data_dir (pl.portv[scanner_d], 1); /*Reverse mode */ ieee1284_frob_control (pl.portv[scanner_d], C1284_NINIT, C1284_NINIT); ieee1284_epp_read_data (pl.portv[scanner_d], 0, (char *) Buffer, length); } /* Send a daisy-chain-style CPP command packet. */ int cpp_daisy (struct parport *port, int cmd) { unsigned char s; ieee1284_data_dir (port, 0); /*forward direction */ ieee1284_write_control (port, C1284_NINIT); ieee1284_write_data (port, 0xaa); usleep (2); ieee1284_write_data (port, 0x55); usleep (2); ieee1284_write_data (port, 0x00); usleep (2); ieee1284_write_data (port, 0xff); usleep (2); s = ieee1284_read_status (port) ^ S1284_INVERTED; /*Converted for PC-style */ s &= (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT); if (s != (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT)) { DBG (1, "%s: cpp_daisy: aa5500ff(%02x)\n", port->name, s); return -1; } ieee1284_write_data (port, 0x87); usleep (2); s = ieee1284_read_status (port) ^ S1284_INVERTED; /*Convert to PC-style */ s &= (S1284_BUSY | S1284_PERROR | S1284_SELECT | S1284_NFAULT); if (s != (S1284_SELECT | S1284_NFAULT)) { DBG (1, "%s: cpp_daisy: aa5500ff87(%02x)\n", port->name, s); return -1; } ieee1284_write_data (port, 0x78); usleep (2); ieee1284_write_control (port, C1284_NINIT); ieee1284_write_data (port, cmd); usleep (2); ieee1284_frob_control (port, C1284_NSTROBE, C1284_NSTROBE); usleep (1); ieee1284_frob_control (port, C1284_NSTROBE, 0); usleep (1); s = ieee1284_read_status (port); ieee1284_write_data (port, 0xff); usleep (2); return s; } /*Daisy chain deselect operation.*/ void daisy_deselect_all (struct parport *port) { cpp_daisy (port, 0x30); } /*Daisy chain select operation*/ int daisy_select (struct parport *port, int daisy, int mode) { switch (mode) { /*For these modes we should switch to EPP mode: */ case M1284_EPP: case M1284_EPPSL: case M1284_EPPSWE: return cpp_daisy (port, 0x20 + daisy) & S1284_NFAULT; /*For these modes we should switch to ECP mode: */ case M1284_ECP: case M1284_ECPRLE: case M1284_ECPSWE: return cpp_daisy (port, 0xd0 + daisy) & S1284_NFAULT; /*Nothing was told for BECP in Daisy chain specification. May be it's wise to use ECP? */ case M1284_BECP: /*Others use compat mode */ case M1284_NIBBLE: case M1284_BYTE: case M1284_COMPAT: default: return cpp_daisy (port, 0xe0 + daisy) & S1284_NFAULT; } } /*Daisy chain assign address operation.*/ int assign_addr (struct parport *port, int daisy) { return cpp_daisy (port, daisy); } static int OpenScanner (const char *scanner_path) { int handle; int caps; /*Scaner name was specified in config file?*/ if (strlen(scanner_path) == 0) return -1; for (handle = 0; handle < pl.portc; handle++) { if (strcmp (scanner_path, pl.portv[handle]->name) == 0) break; } if (handle == pl.portc) /*No match found */ return -1; /*Open port */ if (ieee1284_open (pl.portv[handle], 0, &caps) != E1284_OK) return -1; /*Claim port */ if (ieee1284_claim (pl.portv[handle]) != E1284_OK) return -1; /*Total chain reset. */ daisy_deselect_all (pl.portv[handle]); /*Assign addresses. */ assign_addr (pl.portv[handle], 0); /*Assume we have device first in chain. */ /*Select required device. For now - first in chain. */ daisy_select (pl.portv[handle], 0, M1284_EPP); return handle; } static void CloseScanner (int handle) { if (handle == -1) return; daisy_deselect_all (pl.portv[handle]); ieee1284_release (pl.portv[handle]); ieee1284_close (pl.portv[handle]); } sane-backends-1.0.27/backend/genesys_gl841.c0000664000175000017500000053364412775312261015376 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Oliver Rauch Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2004 Gerhard Jaeger Copyright (C) 2004-2013 Stéphane Voltz Copyright (C) 2005 Philipp Schmid Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2006 Laurent Charpentier Copyright (C) 2010 Chris Berry and Michael Rickmann for Plustek Opticbook 3600 support This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME #define BACKEND_NAME genesys_gl841 #include "genesys_gl841.h" /**************************************************************************** Low level function ****************************************************************************/ /* ------------------------------------------------------------------------ */ /* Read and write RAM, registers and AFE */ /* ------------------------------------------------------------------------ */ /* Write to many registers */ /* Note: There is no known bulk register write, this function is sending single registers instead */ static SANE_Status gl841_bulk_write_register (Genesys_Device * dev, Genesys_Register_Set * reg, size_t elems) { SANE_Status status = SANE_STATUS_GOOD; unsigned int i, c; uint8_t buffer[GENESYS_MAX_REGS * 2]; /* handle differently sized register sets, reg[0x00] is the last one */ i = 0; while ((i < elems) && (reg[i].address != 0)) i++; elems = i; DBG (DBG_io, "gl841_bulk_write_register (elems = %lu)\n", (u_long) elems); for (i = 0; i < elems; i++) { buffer[i * 2 + 0] = reg[i].address; buffer[i * 2 + 1] = reg[i].value; DBG (DBG_io2, "reg[0x%02x] = 0x%02x\n", buffer[i * 2 + 0], buffer[i * 2 + 1]); } for (i = 0; i < elems;) { c = elems - i; if (c > 32) /*32 is max. checked that.*/ c = 32; status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_SET_REGISTER, INDEX, c * 2, buffer + i * 2); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_bulk_write_register: failed while writing command: %s\n", sane_strstatus (status)); return status; } i += c; } DBG (DBG_io, "gl841_bulk_write_register: wrote %lu registers\n", (u_long) elems); return status; } /* Write bulk data (e.g. shading, gamma) */ static SANE_Status gl841_bulk_write_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size; uint8_t outdata[8]; DBG (DBG_io, "gl841_bulk_write_data writing %lu bytes\n", (u_long) len); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX, 1, &addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_bulk_write_data failed while setting register: %s\n", sane_strstatus (status)); return status; } while (len) { if (len > BULKOUT_MAXSIZE) size = BULKOUT_MAXSIZE; else size = len; outdata[0] = BULK_OUT; outdata[1] = BULK_RAM; outdata[2] = VALUE_BUFFER & 0xff; outdata[3] = (VALUE_BUFFER >> 8) & 0xff; outdata[4] = (size & 0xff); outdata[5] = ((size >> 8) & 0xff); outdata[6] = ((size >> 16) & 0xff); outdata[7] = ((size >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_bulk_write_data failed while writing command: %s\n", sane_strstatus (status)); return status; } status = sanei_usb_write_bulk (dev->dn, data, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_bulk_write_data failed while writing bulk data: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io2, "gl841_bulk_write_data wrote %lu bytes, %lu remaining\n", (u_long) size, (u_long) (len - size)); len -= size; data += size; } DBG (DBG_io, "gl841_bulk_write_data: completed\n"); return status; } /* for debugging transfer rate*/ /* #include static struct timeval start_time; static void starttime(){ gettimeofday(&start_time,NULL); } static void printtime(char *p) { struct timeval t; long long int dif; gettimeofday(&t,NULL); dif = t.tv_sec - start_time.tv_sec; dif = dif*1000000 + t.tv_usec - start_time.tv_usec; fprintf(stderr,"%s %lluµs\n",p,dif); } */ /* Read bulk data (e.g. scanned data) */ static SANE_Status gl841_bulk_read_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size, target; uint8_t outdata[8], *buffer; DBG (DBG_io, "gl841_bulk_read_data: requesting %lu bytes\n", (u_long) len); if (len == 0) return SANE_STATUS_GOOD; status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX, 1, &addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_bulk_read_data failed while setting register: %s\n", sane_strstatus (status)); return status; } outdata[0] = BULK_IN; outdata[1] = BULK_RAM; outdata[2] = VALUE_BUFFER & 0xff; outdata[3] = (VALUE_BUFFER >> 8) & 0xff; outdata[4] = (len & 0xff); outdata[5] = ((len >> 8) & 0xff); outdata[6] = ((len >> 16) & 0xff); outdata[7] = ((len >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_bulk_read_data failed while writing command: %s\n", sane_strstatus (status)); return status; } target = len; buffer = data; while (target) { if (target > BULKIN_MAXSIZE) size = BULKIN_MAXSIZE; else size = target; DBG (DBG_io2, "gl841_bulk_read_data: trying to read %lu bytes of data\n", (u_long) size); status = sanei_usb_read_bulk (dev->dn, data, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io2, "gl841_bulk_read_data read %lu bytes, %lu remaining\n", (u_long) size, (u_long) (target - size)); target -= size; data += size; } if (DBG_LEVEL >= DBG_data && dev->binary!=NULL) { fwrite(buffer, len, 1, dev->binary); } DBGCOMPLETED; return SANE_STATUS_GOOD; } /* Set address for writing data */ static SANE_Status gl841_set_buffer_address_gamma (Genesys_Device * dev, uint32_t addr) { SANE_Status status; DBG (DBG_io, "gl841_set_buffer_address_gamma: setting address to 0x%05x\n", addr & 0xfffffff0); addr = addr >> 4; status = sanei_genesys_write_register (dev, 0x5c, (addr & 0xff)); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_buffer_address_gamma: failed while writing low byte: %s\n", sane_strstatus (status)); return status; } addr = addr >> 8; status = sanei_genesys_write_register (dev, 0x5b, (addr & 0xff)); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_buffer_address_gamma: failed while writing high byte: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io, "gl841_set_buffer_address_gamma: completed\n"); return status; } /* Write bulk data (e.g. gamma) */ GENESYS_STATIC SANE_Status gl841_bulk_write_data_gamma (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size; uint8_t outdata[8]; DBG (DBG_io, "gl841_bulk_write_data_gamma writing %lu bytes\n", (u_long) len); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX, 1, &addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_bulk_write_data_gamma failed while setting register: %s\n", sane_strstatus (status)); return status; } while (len) { if (len > BULKOUT_MAXSIZE) size = BULKOUT_MAXSIZE; else size = len; outdata[0] = BULK_OUT; outdata[1] = BULK_RAM; outdata[2] = 0x00;/* 0x82 works, too */ outdata[3] = 0x00; outdata[4] = (size & 0xff); outdata[5] = ((size >> 8) & 0xff); outdata[6] = ((size >> 16) & 0xff); outdata[7] = ((size >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_bulk_write_data_gamma failed while writing command: %s\n", sane_strstatus (status)); return status; } status = sanei_usb_write_bulk (dev->dn, data, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_bulk_write_data_gamma failed while writing bulk data: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io2, "genesys_bulk_write_data:gamma wrote %lu bytes, %lu remaining\n", (u_long) size, (u_long) (len - size)); len -= size; data += size; } DBG (DBG_io, "genesys_bulk_write_data_gamma: completed\n"); return status; } /**************************************************************************** Mid level functions ****************************************************************************/ static SANE_Bool gl841_get_fast_feed_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x02); if (r && (r->value & REG02_FASTFED)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl841_get_filter_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x04); if (r && (r->value & REG04_FILTER)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl841_get_lineart_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x04); if (r && (r->value & REG04_LINEART)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl841_get_bitset_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x04); if (r && (r->value & REG04_BITSET)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl841_get_gain4_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x06); if (r && (r->value & REG06_GAIN4)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl841_test_buffer_empty_bit (SANE_Byte val) { if (val & REG41_BUFEMPTY) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl841_test_motor_flag_bit (SANE_Byte val) { if (val & REG41_MOTORENB) return SANE_TRUE; return SANE_FALSE; } /** copy sensor specific settings */ /* *dev : device infos *regs : registers to be set extended : do extended set up half_ccd: set up for half ccd resolution all registers 08-0B, 10-1D, 52-59 are set up. They shouldn't appear anywhere else but in register_ini Responsible for signals to CCD/CIS: CCD_CK1X (CK1INV(0x16),CKDIS(0x16),CKTOGGLE(0x18),CKDELAY(0x18),MANUAL1(0x1A),CK1MTGL(0x1C),CK1LOW(0x1D),CK1MAP(0x74,0x75,0x76),CK1NEG(0x7D)) CCD_CK2X (CK2INV(0x16),CKDIS(0x16),CKTOGGLE(0x18),CKDELAY(0x18),MANUAL1(0x1A),CK1LOW(0x1D),CK1NEG(0x7D)) CCD_CK3X (MANUAL3(0x1A),CK3INV(0x1A),CK3MTGL(0x1C),CK3LOW(0x1D),CK3MAP(0x77,0x78,0x79),CK3NEG(0x7D)) CCD_CK4X (MANUAL3(0x1A),CK4INV(0x1A),CK4MTGL(0x1C),CK4LOW(0x1D),CK4MAP(0x7A,0x7B,0x7C),CK4NEG(0x7D)) CCD_CPX (CTRLHI(0x16),CTRLINV(0x16),CTRLDIS(0x16),CPH(0x72),CPL(0x73),CPNEG(0x7D)) CCD_RSX (CTRLHI(0x16),CTRLINV(0x16),CTRLDIS(0x16),RSH(0x70),RSL(0x71),RSNEG(0x7D)) CCD_TGX (TGINV(0x16),TGMODE(0x17),TGW(0x17),EXPR(0x10,0x11),TGSHLD(0x1D)) CCD_TGG (TGINV(0x16),TGMODE(0x17),TGW(0x17),EXPG(0x12,0x13),TGSHLD(0x1D)) CCD_TGB (TGINV(0x16),TGMODE(0x17),TGW(0x17),EXPB(0x14,0x15),TGSHLD(0x1D)) LAMP_SW (EXPR(0x10,0x11),XPA_SEL(0x03),LAMP_PWR(0x03),LAMPTIM(0x03),MTLLAMP(0x04),LAMPPWM(0x29)) XPA_SW (EXPG(0x12,0x13),XPA_SEL(0x03),LAMP_PWR(0x03),LAMPTIM(0x03),MTLLAMP(0x04),LAMPPWM(0x29)) LAMP_B (EXPB(0x14,0x15),LAMP_PWR(0x03)) other registers: CISSET(0x01),CNSET(0x18),DCKSEL(0x18),SCANMOD(0x18),EXPDMY(0x19),LINECLP(0x1A),CKAREA(0x1C),TGTIME(0x1C),LINESEL(0x1E),DUMMY(0x34) Responsible for signals to AFE: VSMP (VSMP(0x58),VSMPW(0x58)) BSMP (BSMP(0x59),BSMPW(0x59)) other register settings depending on this: RHI(0x52),RLOW(0x53),GHI(0x54),GLOW(0x55),BHI(0x56),BLOW(0x57), */ static void sanei_gl841_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool extended, SANE_Bool half_ccd) { Genesys_Register_Set *r; int i; DBG (DBG_proc, "gl841_setup_sensor\n"); /* that one is tricky at least ....*/ r = sanei_genesys_get_address (regs, 0x70); for (i = 0; i < 4; i++, r++) r->value = dev->sensor.regs_0x08_0x0b[i]; r = sanei_genesys_get_address (regs, 0x16); for (i = 0x06; i < 0x0a; i++, r++) r->value = dev->sensor.regs_0x10_0x1d[i]; r = sanei_genesys_get_address (regs, 0x1a); for (i = 0x0a; i < 0x0e; i++, r++) r->value = dev->sensor.regs_0x10_0x1d[i]; r = sanei_genesys_get_address (regs, 0x52); for (i = 0; i < 9; i++, r++) r->value = dev->sensor.regs_0x52_0x5e[i]; /* don't go any further if no extended setup */ if (!extended) return; /* todo : add more CCD types if needed */ /* we might want to expand the Sensor struct to have these 2 kind of settings */ if (dev->model->ccd_type == CCD_5345) { if (half_ccd) { /* settings for CCD used at half is max resolution */ r = sanei_genesys_get_address (regs, 0x70); r->value = 0x00; r = sanei_genesys_get_address (regs, 0x71); r->value = 0x05; r = sanei_genesys_get_address (regs, 0x72); r->value = 0x06; r = sanei_genesys_get_address (regs, 0x73); r->value = 0x08; r = sanei_genesys_get_address (regs, 0x18); r->value = 0x28; r = sanei_genesys_get_address (regs, 0x58); r->value = 0x80 | (r->value & 0x03); /* VSMP=16 */ } else { /* swap latch times */ r = sanei_genesys_get_address (regs, 0x18); r->value = 0x30; r = sanei_genesys_get_address (regs, 0x52); for (i = 0; i < 6; i++, r++) r->value = dev->sensor.regs_0x52_0x5e[(i + 3) % 6]; r = sanei_genesys_get_address (regs, 0x58); r->value = 0x20 | (r->value & 0x03); /* VSMP=4 */ } return; } if (dev->model->ccd_type == CCD_HP2300) { /* settings for CCD used at half is max resolution */ if (half_ccd) { r = sanei_genesys_get_address (regs, 0x70); r->value = 0x16; r = sanei_genesys_get_address (regs, 0x71); r->value = 0x00; r = sanei_genesys_get_address (regs, 0x72); r->value = 0x01; r = sanei_genesys_get_address (regs, 0x73); r->value = 0x03; /* manual clock programming */ r = sanei_genesys_get_address (regs, 0x1d); r->value |= 0x80; } else { r = sanei_genesys_get_address (regs, 0x70); r->value = 1; r = sanei_genesys_get_address (regs, 0x71); r->value = 3; r = sanei_genesys_get_address (regs, 0x72); r->value = 4; r = sanei_genesys_get_address (regs, 0x73); r->value = 6; } r = sanei_genesys_get_address (regs, 0x58); r->value = 0x80 | (r->value & 0x03); /* VSMP=16 */ return; } } /** Test if the ASIC works */ /*TODO: make this functional*/ static SANE_Status sanei_gl841_asic_test (Genesys_Device * dev) { SANE_Status status; uint8_t val; uint8_t *data; uint8_t *verify_data; size_t size, verify_size; unsigned int i; DBG (DBG_proc, "sanei_gl841_asic_test\n"); return SANE_STATUS_INVAL; /* set and read exposure time, compare if it's the same */ status = sanei_genesys_write_register (dev, 0x38, 0xde); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_gl841_asic_test: failed to write register: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_write_register (dev, 0x39, 0xad); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_gl841_asic_test: failed to write register: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_read_register (dev, 0x38, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_gl841_asic_test: failed to read register: %s\n", sane_strstatus (status)); return status; } if (val != 0xde) /* value of register 0x38 */ { DBG (DBG_error, "sanei_gl841_asic_test: register contains invalid value\n"); return SANE_STATUS_IO_ERROR; } status = sanei_genesys_read_register (dev, 0x39, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_gl841_asic_test: failed to read register: %s\n", sane_strstatus (status)); return status; } if (val != 0xad) /* value of register 0x39 */ { DBG (DBG_error, "sanei_gl841_asic_test: register contains invalid value\n"); return SANE_STATUS_IO_ERROR; } /* ram test: */ size = 0x40000; verify_size = size + 0x80; /* todo: looks like the read size must be a multiple of 128? otherwise the read doesn't succeed the second time after the scanner has been plugged in. Very strange. */ data = (uint8_t *) malloc (size); if (!data) { DBG (DBG_error, "sanei_gl841_asic_test: could not allocate memory\n"); return SANE_STATUS_NO_MEM; } verify_data = (uint8_t *) malloc (verify_size); if (!verify_data) { free (data); DBG (DBG_error, "sanei_gl841_asic_test: could not allocate memory\n"); return SANE_STATUS_NO_MEM; } for (i = 0; i < (size - 1); i += 2) { data[i] = i / 512; data[i + 1] = (i / 2) % 256; } status = sanei_genesys_set_buffer_address (dev, 0x0000); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_gl841_asic_test: failed to set buffer address: %s\n", sane_strstatus (status)); free (data); free (verify_data); return status; } /* status = gl841_bulk_write_data (dev, 0x3c, data, size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_gl841_asic_test: failed to bulk write data: %s\n", sane_strstatus (status)); free (data); free (verify_data); return status; }*/ status = sanei_genesys_set_buffer_address (dev, 0x0000); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_gl841_asic_test: failed to set buffer address: %s\n", sane_strstatus (status)); free (data); free (verify_data); return status; } status = gl841_bulk_read_data (dev, 0x45, (uint8_t *) verify_data, verify_size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_gl841_asic_test: failed to bulk read data: %s\n", sane_strstatus (status)); free (data); free (verify_data); return status; } /* todo: why i + 2 ? */ for (i = 0; i < size; i++) { if (verify_data[i] != data[i]) { DBG (DBG_error, "sanei_gl841_asic_test: data verification error\n"); DBG (DBG_info, "0x%.8x: got %.2x %.2x %.2x %.2x, expected %.2x %.2x %.2x %.2x\n", i, verify_data[i], verify_data[i+1], verify_data[i+2], verify_data[i+3], data[i], data[i+1], data[i+2], data[i+3]); free (data); free (verify_data); return SANE_STATUS_IO_ERROR; } } free (data); free (verify_data); DBG (DBG_info, "sanei_gl841_asic_test: completed\n"); return SANE_STATUS_GOOD; } /* returns the max register bulk size */ static int gl841_bulk_full_size (void) { return GENESYS_GL841_MAX_REGS; } /* * Set all registers LiDE 80 to default values * (function called only once at the beginning) * we are doing a special case to ease development */ static void gl841_init_lide80 (Genesys_Device * dev) { uint8_t val; int index=0; INITREG (0x01, 0x82); /* 0x02 = SHDAREA and no CISSET ! */ INITREG (0x02, 0x10); INITREG (0x03, 0x50); INITREG (0x04, 0x02); INITREG (0x05, 0x4c); /* 1200 DPI */ INITREG (0x06, 0x38); /* 0x38 scanmod=1, pwrbit, GAIN4 */ INITREG (0x07, 0x00); INITREG (0x08, 0x00); INITREG (0x09, 0x11); INITREG (0x0a, 0x00); INITREG (0x10, 0x40); INITREG (0x11, 0x00); INITREG (0x12, 0x40); INITREG (0x13, 0x00); INITREG (0x14, 0x40); INITREG (0x15, 0x00); INITREG (0x16, 0x00); INITREG (0x17, 0x01); INITREG (0x18, 0x00); INITREG (0x19, 0x06); INITREG (0x1a, 0x00); INITREG (0x1b, 0x00); INITREG (0x1c, 0x00); INITREG (0x1d, 0x04); INITREG (0x1e, 0x10); INITREG (0x1f, 0x04); INITREG (0x20, 0x02); INITREG (0x21, 0x10); INITREG (0x22, 0x20); INITREG (0x23, 0x20); INITREG (0x24, 0x10); INITREG (0x25, 0x00); INITREG (0x26, 0x00); INITREG (0x27, 0x00); INITREG (0x29, 0xff); INITREG (0x2c, dev->sensor.optical_res>>8); INITREG (0x2d, dev->sensor.optical_res & 0xff); INITREG (0x2e, 0x80); INITREG (0x2f, 0x80); INITREG (0x30, 0x00); INITREG (0x31, 0x10); INITREG (0x32, 0x15); INITREG (0x33, 0x0e); INITREG (0x34, 0x40); INITREG (0x35, 0x00); INITREG (0x36, 0x2a); INITREG (0x37, 0x30); INITREG (0x38, 0x2a); INITREG (0x39, 0xf8); INITREG (0x3d, 0x00); INITREG (0x3e, 0x00); INITREG (0x3f, 0x00); INITREG (0x52, 0x03); INITREG (0x53, 0x07); INITREG (0x54, 0x00); INITREG (0x55, 0x00); INITREG (0x56, 0x00); INITREG (0x57, 0x00); INITREG (0x58, 0x29); INITREG (0x59, 0x69); INITREG (0x5a, 0x55); INITREG (0x5d, 0x20); INITREG (0x5e, 0x41); INITREG (0x5f, 0x40); INITREG (0x60, 0x00); INITREG (0x61, 0x00); INITREG (0x62, 0x00); INITREG (0x63, 0x00); INITREG (0x64, 0x00); INITREG (0x65, 0x00); INITREG (0x66, 0x00); INITREG (0x67, 0x40); INITREG (0x68, 0x40); INITREG (0x69, 0x20); INITREG (0x6a, 0x20); INITREG (0x6c, dev->gpo.value[0]); INITREG (0x6d, dev->gpo.value[1]); INITREG (0x6e, dev->gpo.enable[0]); INITREG (0x6f, dev->gpo.enable[1]); INITREG (0x70, 0x00); INITREG (0x71, 0x05); INITREG (0x72, 0x07); INITREG (0x73, 0x09); INITREG (0x74, 0x00); INITREG (0x75, 0x01); INITREG (0x76, 0xff); INITREG (0x77, 0x00); INITREG (0x78, 0x0f); INITREG (0x79, 0xf0); INITREG (0x7a, 0xf0); INITREG (0x7b, 0x00); INITREG (0x7c, 0x1e); INITREG (0x7d, 0x11); INITREG (0x7e, 0x00); INITREG (0x7f, 0x50); INITREG (0x80, 0x00); INITREG (0x81, 0x00); INITREG (0x82, 0x0f); INITREG (0x83, 0x00); INITREG (0x84, 0x0e); INITREG (0x85, 0x00); INITREG (0x86, 0x0d); INITREG (0x87, 0x02); INITREG (0x88, 0x00); INITREG (0x89, 0x00); /* specific scanner settings, clock and gpio first */ sanei_genesys_read_register (dev, REG6B, &val); sanei_genesys_write_register (dev, REG6B, 0x0c); sanei_genesys_write_register (dev, 0x06, 0x10); sanei_genesys_write_register (dev, REG6E, 0x6d); sanei_genesys_write_register (dev, REG6F, 0x80); sanei_genesys_write_register (dev, REG6B, 0x0e); sanei_genesys_read_register (dev, REG6C, &val); sanei_genesys_write_register (dev, REG6C, 0x00); sanei_genesys_read_register (dev, REG6D, &val); sanei_genesys_write_register (dev, REG6D, 0x8f); sanei_genesys_read_register (dev, REG6B, &val); sanei_genesys_write_register (dev, REG6B, 0x0e); sanei_genesys_read_register (dev, REG6B, &val); sanei_genesys_write_register (dev, REG6B, 0x0e); sanei_genesys_read_register (dev, REG6B, &val); sanei_genesys_write_register (dev, REG6B, 0x0a); sanei_genesys_read_register (dev, REG6B, &val); sanei_genesys_write_register (dev, REG6B, 0x02); sanei_genesys_read_register (dev, REG6B, &val); sanei_genesys_write_register (dev, REG6B, 0x06); sanei_genesys_write_0x8c (dev, 0x10, 0x94); sanei_genesys_write_register (dev, 0x09, 0x10); /* set up GPIO : no address, so no bulk write, doesn't written directly either ? */ /* dev->reg[reg_0x6c].value = dev->gpo.value[0]; dev->reg[reg_0x6d].value = dev->gpo.value[1]; dev->reg[reg_0x6e].value = dev->gpo.enable[0]; dev->reg[reg_0x6f].value = dev->gpo.enable[1]; */ dev->reg[reg_0x6b].value |= REG6B_GPO18; dev->reg[reg_0x6b].value &= ~REG6B_GPO17; sanei_gl841_setup_sensor (dev, dev->reg, 0, 0); } /* * Set all registers to default values * (function called only once at the beginning) */ static void gl841_init_registers (Genesys_Device * dev) { int nr, addr; DBG (DBG_proc, "gl841_init_registers\n"); nr = 0; memset (dev->reg, 0, GENESYS_MAX_REGS * sizeof (Genesys_Register_Set)); if (strcmp (dev->model->name, "canon-lide-80") == 0) { gl841_init_lide80(dev); return ; } for (addr = 1; addr <= 0x0a; addr++) dev->reg[nr++].address = addr; for (addr = 0x10; addr <= 0x27; addr++) dev->reg[nr++].address = addr; dev->reg[nr++].address = 0x29; for (addr = 0x2c; addr <= 0x39; addr++) dev->reg[nr++].address = addr; for (addr = 0x3d; addr <= 0x3f; addr++) dev->reg[nr++].address = addr; for (addr = 0x52; addr <= 0x5a; addr++) dev->reg[nr++].address = addr; for (addr = 0x5d; addr <= 0x87; addr++) dev->reg[nr++].address = addr; dev->reg[reg_0x01].value = 0x20; /* (enable shading), CCD, color, 1M */ if (dev->model->is_cis == SANE_TRUE) { dev->reg[reg_0x01].value |= REG01_CISSET; } else { dev->reg[reg_0x01].value &= ~REG01_CISSET; } dev->reg[reg_0x02].value = 0x30 /*0x38 */ ; /* auto home, one-table-move, full step */ dev->reg[reg_0x02].value |= REG02_AGOHOME; dev->reg[reg_0x02].value |= REG02_MTRPWR; dev->reg[reg_0x02].value |= REG02_FASTFED; dev->reg[reg_0x03].value = 0x1f /*0x17 */ ; /* lamp on */ dev->reg[reg_0x03].value |= REG03_AVEENB; if (dev->model->ccd_type == CCD_PLUSTEK_3600) /* AD front end */ { dev->reg[reg_0x04].value = (2 << REG04S_AFEMOD) | 0x02; } else /* Wolfson front end */ { dev->reg[reg_0x04].value |= 1 << REG04S_AFEMOD; } dev->reg[reg_0x05].value = 0x00; /* disable gamma, 24 clocks/pixel */ if (dev->sensor.sensor_pixels < 0x1500) dev->reg[reg_0x05].value |= REG05_DPIHW_600; else if (dev->sensor.sensor_pixels < 0x2a80) dev->reg[reg_0x05].value |= REG05_DPIHW_1200; else if (dev->sensor.sensor_pixels < 0x5400) dev->reg[reg_0x05].value |= REG05_DPIHW_2400; else { dev->reg[reg_0x05].value |= REG05_DPIHW_2400; DBG (DBG_warn, "gl841_init_registers: Cannot handle sensor pixel count %d\n", dev->sensor.sensor_pixels); } dev->reg[reg_0x06].value |= REG06_PWRBIT; dev->reg[reg_0x06].value |= REG06_GAIN4; /* XP300 CCD needs different clock and clock/pixels values */ if (dev->model->ccd_type != CCD_XP300 && dev->model->ccd_type != CCD_DP685 && dev->model->ccd_type != CCD_PLUSTEK_3600) { dev->reg[reg_0x06].value |= 0 << REG06S_SCANMOD; dev->reg[reg_0x09].value |= 1 << REG09S_CLKSET; } else { dev->reg[reg_0x06].value |= 0x05 << REG06S_SCANMOD; /* 15 clocks/pixel */ dev->reg[reg_0x09].value = 0; /* 24 MHz CLKSET */ } dev->reg[reg_0x1e].value = 0xf0; /* watch-dog time */ dev->reg[reg_0x17].value |= 1 << REG17S_TGW; dev->reg[reg_0x19].value = 0x50; dev->reg[reg_0x1d].value |= 1 << REG1DS_TGSHLD; dev->reg[reg_0x1e].value |= 1 << REG1ES_WDTIME; /*SCANFED*/ dev->reg[reg_0x1f].value = 0x01; /*BUFSEL*/ dev->reg[reg_0x20].value = 0x20; /*LAMPPWM*/ dev->reg[reg_0x29].value = 0xff; /*BWHI*/ dev->reg[reg_0x2e].value = 0x80; /*BWLOW*/ dev->reg[reg_0x2f].value = 0x80; /*LPERIOD*/ dev->reg[reg_0x38].value = 0x4f; dev->reg[reg_0x39].value = 0xc1; /*VSMPW*/ dev->reg[reg_0x58].value |= 3 << REG58S_VSMPW; /*BSMPW*/ dev->reg[reg_0x59].value |= 3 << REG59S_BSMPW; /*RLCSEL*/ dev->reg[reg_0x5a].value |= REG5A_RLCSEL; /*STOPTIM*/ dev->reg[reg_0x5e].value |= 0x2 << REG5ES_STOPTIM; sanei_gl841_setup_sensor (dev, dev->reg, 0, 0); /* set up GPIO */ dev->reg[reg_0x6c].value = dev->gpo.value[0]; dev->reg[reg_0x6d].value = dev->gpo.value[1]; dev->reg[reg_0x6e].value = dev->gpo.enable[0]; dev->reg[reg_0x6f].value = dev->gpo.enable[1]; /* TODO there is a switch calling to be written here */ if (dev->model->gpo_type == GPO_CANONLIDE35) { dev->reg[reg_0x6b].value |= REG6B_GPO18; dev->reg[reg_0x6b].value &= ~REG6B_GPO17; } if (dev->model->gpo_type == GPO_CANONLIDE80) { dev->reg[reg_0x6b].value |= REG6B_GPO18; dev->reg[reg_0x6b].value &= ~REG6B_GPO17; } if (dev->model->gpo_type == GPO_XP300) { dev->reg[reg_0x6b].value |= REG6B_GPO17; } if (dev->model->gpo_type == GPO_DP685) { /* REG6B_GPO18 lights on green led */ dev->reg[reg_0x6b].value |= REG6B_GPO17|REG6B_GPO18; } DBG (DBG_proc, "gl841_init_registers complete\n"); } /* Send slope table for motor movement slope_table in machine byte order */ GENESYS_STATIC SANE_Status gl841_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps) { int dpihw; int start_address; SANE_Status status; uint8_t *table; char msg[4000]; /*#ifdef WORDS_BIGENDIAN*/ int i; /*#endif*/ DBG (DBG_proc, "gl841_send_slope_table (table_nr = %d, steps = %d)\n", table_nr, steps); dpihw = dev->reg[reg_0x05].value >> 6; if (dpihw == 0) /* 600 dpi */ start_address = 0x08000; else if (dpihw == 1) /* 1200 dpi */ start_address = 0x10000; else if (dpihw == 2) /* 2400 dpi */ start_address = 0x20000; else /* reserved */ return SANE_STATUS_INVAL; /*#ifdef WORDS_BIGENDIAN*/ table = (uint8_t*)malloc(steps * 2); for(i = 0; i < steps; i++) { table[i * 2] = slope_table[i] & 0xff; table[i * 2 + 1] = slope_table[i] >> 8; } /*#else table = (uint8_t*)slope_table; #endif*/ if (DBG_LEVEL >= DBG_io) { sprintf (msg, "write slope %d (%d)=", table_nr, steps); for (i = 0; i < steps; i++) { sprintf (msg+strlen(msg), ",%d", slope_table[i]); } DBG (DBG_io, "%s: %s\n", __func__, msg); } status = sanei_genesys_set_buffer_address (dev, start_address + table_nr * 0x200); if (status != SANE_STATUS_GOOD) { /*#ifdef WORDS_BIGENDIAN*/ free(table); /*#endif*/ DBG (DBG_error, "gl841_send_slope_table: failed to set buffer address: %s\n", sane_strstatus (status)); return status; } status = gl841_bulk_write_data (dev, 0x3c, (uint8_t *) table, steps * 2); if (status != SANE_STATUS_GOOD) { /*#ifdef WORDS_BIGENDIAN*/ free(table); /*#endif*/ DBG (DBG_error, "gl841_send_slope_table: failed to send slope table: %s\n", sane_strstatus (status)); return status; } /*#ifdef WORDS_BIGENDIAN*/ free(table); /*#endif*/ DBG (DBG_proc, "gl841_send_slope_table: completed\n"); return status; } static SANE_Status gl841_set_lide80_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status = SANE_STATUS_GOOD; DBGSTART; if (set == AFE_INIT) { DBG (DBG_proc, "%s(): setting DAC %u\n", __func__, dev->model->dac_type); /* sets to default values */ sanei_genesys_init_fe (dev); /* write them to analog frontend */ status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: writing reg 0x00 failed: %s\n", __func__, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.reg[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: writing reg 0x03 failed: %s\n", __func__, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x06, dev->frontend.reg[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: writing reg 0x06 failed: %s\n", __func__, sane_strstatus (status)); return status; } } if (set == AFE_SET) { status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: writing reg 0x00 failed: %s\n", __func__, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x06, dev->frontend.offset[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: writing offset failed: %s\n", __func__, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.gain[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: writing gain failed: %s\n", __func__, sane_strstatus (status)); return status; } } return status; DBGCOMPLETED; } /* Set values of Analog Device type frontend */ static SANE_Status gl841_set_ad_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status = SANE_STATUS_GOOD; int i; /* special case for LiDE 80 analog frontend */ if(dev->model->dac_type==DAC_CANONLIDE80) { return gl841_set_lide80_fe(dev, set); } DBG (DBG_proc, "gl841_set_ad_fe(): start\n"); if (set == AFE_INIT) { DBG (DBG_proc, "gl841_set_ad_fe(): setting DAC %u\n", dev->model->dac_type); /* sets to default values */ sanei_genesys_init_fe (dev); /* write them to analog frontend */ status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: writing reg 0x00 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x01, dev->frontend.reg[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: writing reg 0x01 failed: %s\n", sane_strstatus (status)); return status; } for (i = 0; i < 6; i++) { status = sanei_genesys_fe_write_data (dev, 0x02 + i, 0x00); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: writing sign[%d] failed: %s\n", 0x02 + i, sane_strstatus (status)); return status; } } } if (set == AFE_SET) { /* write them to analog frontend */ status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: writing reg 0x00 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x01, dev->frontend.reg[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: writing reg 0x01 failed: %s\n", sane_strstatus (status)); return status; } /* Write fe 0x02 (red gain)*/ status = sanei_genesys_fe_write_data (dev, 0x02, dev->frontend.gain[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: writing fe 0x02 (gain r) fail: %s\n", sane_strstatus (status)); return status; } /* Write fe 0x03 (green gain)*/ status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.gain[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: writing fe 0x03 (gain g) fail: %s\n", sane_strstatus (status)); return status; } /* Write fe 0x04 (blue gain)*/ status = sanei_genesys_fe_write_data (dev, 0x04, dev->frontend.gain[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: writing fe 0x04 (gain b) fail: %s\n", sane_strstatus (status)); return status; } /* Write fe 0x05 (red offset)*/ status = sanei_genesys_fe_write_data (dev, 0x05, dev->frontend.offset[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: write fe 0x05 (offset r) fail: %s\n", sane_strstatus (status)); return status; } /* Write fe 0x06 (green offset)*/ status = sanei_genesys_fe_write_data (dev, 0x06, dev->frontend.offset[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: write fe 0x06 (offset g) fail: %s\n", sane_strstatus (status)); return status; } /* Write fe 0x07 (blue offset)*/ status = sanei_genesys_fe_write_data (dev, 0x07, dev->frontend.offset[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_ad_fe: write fe 0x07 (offset b) fail: %s\n", sane_strstatus (status)); return status; } } DBG (DBG_proc, "gl841_set_ad_fe(): end\n"); return status; } /* Set values of analog frontend */ static SANE_Status gl841_set_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status; int i; DBG (DBG_proc, "gl841_set_fe (%s)\n", set == AFE_INIT ? "init" : set == AFE_SET ? "set" : set == AFE_POWER_SAVE ? "powersave" : "huh?"); /* Analog Device type frontend */ if ((dev->reg[reg_0x04].value & REG04_FESET) == 0x02) { return gl841_set_ad_fe (dev, set); } if ((dev->reg[reg_0x04].value & REG04_FESET) != 0x00) { DBG (DBG_proc, "gl841_set_fe(): unsupported frontend type %d\n", dev->reg[reg_0x04].value & REG04_FESET); return SANE_STATUS_UNSUPPORTED; } if (set == AFE_INIT) { DBG (DBG_proc, "gl841_set_fe(): setting DAC %u\n", dev->model->dac_type); sanei_genesys_init_fe (dev); /* reset only done on init */ status = sanei_genesys_fe_write_data (dev, 0x04, 0x80); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: reset fe failed: %s\n", sane_strstatus (status)); return status; /* if (dev->model->ccd_type == CCD_HP2300 || dev->model->ccd_type == CCD_HP2400) { val = 0x07; status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, GPIO_OUTPUT_ENABLE, INDEX, 1, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe failed resetting frontend: %s\n", sane_strstatus (status)); return status; } }*/ } DBG (DBG_proc, "gl841_set_fe(): frontend reset complete\n"); } if (set == AFE_POWER_SAVE) { status = sanei_genesys_fe_write_data (dev, 0x01, 0x02); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "gl841_set_fe: writing data failed: %s\n", sane_strstatus (status)); return status; } /* todo : base this test on cfg reg3 or a CCD family flag to be created */ /*if (dev->model->ccd_type!=CCD_HP2300 && dev->model->ccd_type!=CCD_HP2400) */ { status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing reg0 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x02, dev->frontend.reg[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing reg2 failed: %s\n", sane_strstatus (status)); return status; } } status = sanei_genesys_fe_write_data (dev, 0x01, dev->frontend.reg[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing reg1 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.reg[3]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing reg3 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x06, dev->frontend.reg2[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing reg6 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x08, dev->frontend.reg2[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing reg8 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x09, dev->frontend.reg2[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing reg9 failed: %s\n", sane_strstatus (status)); return status; } for (i = 0; i < 3; i++) { status = sanei_genesys_fe_write_data (dev, 0x24 + i, dev->frontend.sign[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing sign[%d] failed: %s\n", i, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x28 + i, dev->frontend.gain[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing gain[%d] failed: %s\n", i, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x20 + i, dev->frontend.offset[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_set_fe: writing offset[%d] failed: %s\n", i, sane_strstatus (status)); return status; } } DBG (DBG_proc, "gl841_set_fe: completed\n"); return SANE_STATUS_GOOD; } #define MOTOR_ACTION_FEED 1 #define MOTOR_ACTION_GO_HOME 2 #define MOTOR_ACTION_HOME_FREE 3 /** @brief turn off motor * */ static SANE_Status gl841_init_motor_regs_off(Genesys_Register_Set * reg, unsigned int scan_lines) { unsigned int feedl; Genesys_Register_Set * r; DBG (DBG_proc, "gl841_init_motor_regs_off : scan_lines=%d\n", scan_lines); feedl = 2; r = sanei_genesys_get_address (reg, 0x3d); r->value = (feedl >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x3e); r->value = (feedl >> 8) & 0xff; r = sanei_genesys_get_address (reg, 0x3f); r->value = feedl & 0xff; r = sanei_genesys_get_address (reg, 0x5e); r->value &= ~0xe0; r = sanei_genesys_get_address (reg, 0x25); r->value = (scan_lines >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x26); r->value = (scan_lines >> 8) & 0xff; r = sanei_genesys_get_address (reg, 0x27); r->value = scan_lines & 0xff; r = sanei_genesys_get_address (reg, 0x02); r->value &= ~0x01; /*LONGCURV OFF*/ r->value &= ~0x80; /*NOT_HOME OFF*/ r->value &= ~0x10; r->value &= ~0x06; r->value &= ~0x08; r->value &= ~0x20; r->value &= ~0x40; r = sanei_genesys_get_address (reg, 0x67); r->value = 0x3f; r = sanei_genesys_get_address (reg, 0x68); r->value = 0x3f; r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = 0; r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = 0; r = sanei_genesys_get_address (reg, 0x69); r->value = 0; r = sanei_genesys_get_address (reg, 0x6a); r->value = 0; r = sanei_genesys_get_address (reg, 0x5f); r->value = 0; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief write motor table frequency * Write motor frequency data table. * @param dev device to set up motor * @param ydpi motor target resolution * @return SANE_STATUS_GOOD on success */ GENESYS_STATIC SANE_Status gl841_write_freq(Genesys_Device *dev, unsigned int ydpi) { SANE_Status status; /**< fast table */ uint8_t tdefault[] = {0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0x36,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xb6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0xf6,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76,0x18,0x76}; uint8_t t1200[] = {0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc7,0x31,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc0,0x11,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0xc7,0xb1,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0x07,0xe0,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc7,0xf1,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc0,0x51,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0xc7,0x71,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20,0x07,0x20}; uint8_t t300[] = {0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x08,0x32,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x08,0xb2,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x0c,0xa0,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x08,0xf2,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x00,0xd3,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x08,0x72,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60,0x0c,0x60}; uint8_t t150[] = {0x0c,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0xcf,0x33,0x40,0x14,0x80,0x15,0x80,0x15,0x80,0x15,0x80,0x15,0x80,0x15,0x80,0x15,0x80,0x15,0x0c,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0xcf,0xb3,0x11,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x16,0xa0,0x0c,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0x40,0xd4,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x80,0xd5,0x0c,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0xcf,0x73,0x11,0x60,0x16,0x60,0x16,0x60,0x16,0x60,0x16,0x60,0x16,0x60,0x16,0x60,0x16,0x60}; uint8_t *table; DBGSTART; if(dev->model->motor_type == MOTOR_CANONLIDE80) { switch(ydpi) { case 3600: case 1200: table=t1200; break; case 900: case 300: table=t300; break; case 450: case 150: table=t150; break; default: table=tdefault; } RIE(sanei_genesys_write_register(dev, 0x66, 0x00)); RIE(sanei_genesys_write_register(dev, 0x5b, 0x0c)); RIE(sanei_genesys_write_register(dev, 0x5c, 0x00)); RIE(gl841_bulk_write_data_gamma (dev, 0x28, table, 128)); RIE(sanei_genesys_write_register(dev, 0x5b, 0x00)); RIE(sanei_genesys_write_register(dev, 0x5c, 0x00)); } DBGCOMPLETED; return SANE_STATUS_GOOD; } #ifndef UNIT_TESTING static #endif SANE_Status gl841_init_motor_regs(Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int feed_steps,/*1/base_ydpi*/ /*maybe float for half/quarter step resolution?*/ unsigned int action, unsigned int flags) { SANE_Status status; unsigned int fast_exposure; int scan_power_mode; int use_fast_fed = 0; uint16_t fast_slope_table[256]; unsigned int fast_slope_steps = 0; unsigned int feedl; Genesys_Register_Set * r; /*number of scan lines to add in a scan_lines line*/ DBG (DBG_proc, "gl841_init_motor_regs : feed_steps=%d, action=%d, flags=%x\n", feed_steps, action, flags); memset(fast_slope_table,0xff,512); gl841_send_slope_table (dev, 0, fast_slope_table, 256); gl841_send_slope_table (dev, 1, fast_slope_table, 256); gl841_send_slope_table (dev, 2, fast_slope_table, 256); gl841_send_slope_table (dev, 3, fast_slope_table, 256); gl841_send_slope_table (dev, 4, fast_slope_table, 256); gl841_write_freq(dev, dev->motor.base_ydpi / 4); fast_slope_steps = 256; if (action == MOTOR_ACTION_FEED || action == MOTOR_ACTION_GO_HOME) { /* FEED and GO_HOME can use fastest slopes available */ fast_exposure = gl841_exposure_time(dev, dev->motor.base_ydpi / 4, 0, 0, 0, &scan_power_mode); DBG (DBG_info, "%s : fast_exposure=%d pixels\n", __func__, fast_exposure); } if (action == MOTOR_ACTION_HOME_FREE) { /* HOME_FREE must be able to stop in one step, so do not try to get faster */ fast_exposure = dev->motor.slopes[0][0].maximum_start_speed; } sanei_genesys_create_slope_table3 ( dev, fast_slope_table, 256, fast_slope_steps, 0, fast_exposure, dev->motor.base_ydpi / 4, &fast_slope_steps, &fast_exposure, 0); feedl = feed_steps - fast_slope_steps*2; use_fast_fed = 1; /* all needed slopes available. we did even decide which mode to use. what next? - transfer slopes SCAN: flags \ use_fast_fed ! 0 1 ------------------------\-------------------- 0 ! 0,1,2 0,1,2,3 MOTOR_FLAG_AUTO_GO_HOME ! 0,1,2,4 0,1,2,3,4 OFF: none FEED: 3 GO_HOME: 3 HOME_FREE: 3 - setup registers * slope specific registers (already done) * DECSEL for HOME_FREE/GO_HOME/SCAN * FEEDL * MTRREV * MTRPWR * FASTFED * STEPSEL * MTRPWM * FSTPSEL * FASTPWM * HOMENEG * BWDSTEP * FWDSTEP * Z1 * Z2 */ r = sanei_genesys_get_address (reg, 0x3d); r->value = (feedl >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x3e); r->value = (feedl >> 8) & 0xff; r = sanei_genesys_get_address (reg, 0x3f); r->value = feedl & 0xff; r = sanei_genesys_get_address (reg, 0x5e); r->value &= ~0xe0; r = sanei_genesys_get_address (reg, 0x25); r->value = 0; r = sanei_genesys_get_address (reg, 0x26); r->value = 0; r = sanei_genesys_get_address (reg, 0x27); r->value = 0; r = sanei_genesys_get_address (reg, 0x02); r->value &= ~0x01; /*LONGCURV OFF*/ r->value &= ~0x80; /*NOT_HOME OFF*/ r->value |= 0x10; if (action == MOTOR_ACTION_GO_HOME) r->value |= 0x06; else r->value &= ~0x06; if (use_fast_fed) r->value |= 0x08; else r->value &= ~0x08; if (flags & MOTOR_FLAG_AUTO_GO_HOME) r->value |= 0x20; else r->value &= ~0x20; r->value &= ~0x40; status = gl841_send_slope_table (dev, 3, fast_slope_table, 256); if (status != SANE_STATUS_GOOD) return status; r = sanei_genesys_get_address (reg, 0x67); r->value = 0x3f; r = sanei_genesys_get_address (reg, 0x68); r->value = 0x3f; r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = 0; r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = 0; r = sanei_genesys_get_address (reg, 0x69); r->value = 0; r = sanei_genesys_get_address (reg, 0x6a); r->value = (fast_slope_steps >> 1) + (fast_slope_steps & 1); r = sanei_genesys_get_address (reg, 0x5f); r->value = (fast_slope_steps >> 1) + (fast_slope_steps & 1); DBGCOMPLETED; return SANE_STATUS_GOOD; } #ifndef UNIT_TESTING static #endif SANE_Status gl841_init_motor_regs_scan(Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int scan_exposure_time,/*pixel*/ float scan_yres,/*dpi, motor resolution*/ int scan_step_type,/*0: full, 1: half, 2: quarter*/ unsigned int scan_lines,/*lines, scan resolution*/ unsigned int scan_dummy, /*number of scan lines to add in a scan_lines line*/ unsigned int feed_steps,/*1/base_ydpi*/ /*maybe float for half/quarter step resolution?*/ int scan_power_mode, unsigned int flags) { SANE_Status status; unsigned int fast_exposure; int use_fast_fed = 0; int dummy_power_mode; unsigned int fast_time; unsigned int slow_time; uint16_t slow_slope_table[256]; uint16_t fast_slope_table[256]; uint16_t back_slope_table[256]; unsigned int slow_slope_time; unsigned int fast_slope_time; unsigned int slow_slope_steps = 0; unsigned int fast_slope_steps = 0; unsigned int back_slope_steps = 0; unsigned int feedl; Genesys_Register_Set * r; unsigned int min_restep = 0x20; uint32_t z1, z2; DBG (DBG_proc, "gl841_init_motor_regs_scan : scan_exposure_time=%d, " "scan_yres=%g, scan_step_type=%d, scan_lines=%d, scan_dummy=%d, " "feed_steps=%d, scan_power_mode=%d, flags=%x\n", scan_exposure_time, scan_yres, scan_step_type, scan_lines, scan_dummy, feed_steps, scan_power_mode, flags); fast_exposure = gl841_exposure_time(dev, dev->motor.base_ydpi / 4, 0, 0, 0, &dummy_power_mode); DBG (DBG_info, "%s : fast_exposure=%d pixels\n", __func__, fast_exposure); memset(slow_slope_table,0xff,512); gl841_send_slope_table (dev, 0, slow_slope_table, 256); gl841_send_slope_table (dev, 1, slow_slope_table, 256); gl841_send_slope_table (dev, 2, slow_slope_table, 256); gl841_send_slope_table (dev, 3, slow_slope_table, 256); gl841_send_slope_table (dev, 4, slow_slope_table, 256); /* motor frequency table */ gl841_write_freq(dev, scan_yres); /* we calculate both tables for SCAN. the fast slope step count depends on how many steps we need for slow acceleration and how much steps we are allowed to use. */ slow_slope_time = sanei_genesys_create_slope_table3 ( dev, slow_slope_table, 256, 256, scan_step_type, scan_exposure_time, scan_yres, &slow_slope_steps, NULL, scan_power_mode); sanei_genesys_create_slope_table3 ( dev, back_slope_table, 256, 256, scan_step_type, 0, scan_yres, &back_slope_steps, NULL, scan_power_mode); if (feed_steps < (slow_slope_steps >> scan_step_type)) { /*TODO: what should we do here?? go back to exposure calculation?*/ feed_steps = slow_slope_steps >> scan_step_type; } if (feed_steps > fast_slope_steps*2 - (slow_slope_steps >> scan_step_type)) fast_slope_steps = 256; else /* we need to shorten fast_slope_steps here. */ fast_slope_steps = (feed_steps - (slow_slope_steps >> scan_step_type))/2; DBG(DBG_info,"gl841_init_motor_regs_scan: Maximum allowed slope steps for fast slope: %d\n",fast_slope_steps); fast_slope_time = sanei_genesys_create_slope_table3 ( dev, fast_slope_table, 256, fast_slope_steps, 0, fast_exposure, dev->motor.base_ydpi / 4, &fast_slope_steps, &fast_exposure, scan_power_mode); /* fast fed special cases handling */ if (dev->model->gpo_type == GPO_XP300 || dev->model->gpo_type == GPO_DP685) { /* quirk: looks like at least this scanner is unable to use 2-feed mode */ use_fast_fed = 0; } else if (feed_steps < fast_slope_steps*2 + (slow_slope_steps >> scan_step_type)) { use_fast_fed = 0; DBG(DBG_info,"gl841_init_motor_regs_scan: feed too short, slow move forced.\n"); } else { /* for deciding whether we should use fast mode we need to check how long we need for (fast)accelerating, moving, decelerating, (TODO: stopping?) (slow)accelerating again versus (slow)accelerating and moving. we need fast and slow tables here. */ /*NOTE: scan_exposure_time is per scan_yres*/ /*NOTE: fast_exposure is per base_ydpi/4*/ /*we use full steps as base unit here*/ fast_time = fast_exposure / 4 * (feed_steps - fast_slope_steps*2 - (slow_slope_steps >> scan_step_type)) + fast_slope_time*2 + slow_slope_time; slow_time = (scan_exposure_time * scan_yres) / dev->motor.base_ydpi * (feed_steps - (slow_slope_steps >> scan_step_type)) + slow_slope_time; DBG(DBG_info,"gl841_init_motor_regs_scan: Time for slow move: %d\n", slow_time); DBG(DBG_info,"gl841_init_motor_regs_scan: Time for fast move: %d\n", fast_time); use_fast_fed = fast_time < slow_time; } if (use_fast_fed) feedl = feed_steps - fast_slope_steps*2 - (slow_slope_steps >> scan_step_type); else if ((feed_steps << scan_step_type) < slow_slope_steps) feedl = 0; else feedl = (feed_steps << scan_step_type) - slow_slope_steps; DBG(DBG_info,"gl841_init_motor_regs_scan: Decided to use %s mode\n", use_fast_fed?"fast feed":"slow feed"); /* all needed slopes available. we did even decide which mode to use. what next? - transfer slopes SCAN: flags \ use_fast_fed ! 0 1 ------------------------\-------------------- 0 ! 0,1,2 0,1,2,3 MOTOR_FLAG_AUTO_GO_HOME ! 0,1,2,4 0,1,2,3,4 OFF: none FEED: 3 GO_HOME: 3 HOME_FREE: 3 - setup registers * slope specific registers (already done) * DECSEL for HOME_FREE/GO_HOME/SCAN * FEEDL * MTRREV * MTRPWR * FASTFED * STEPSEL * MTRPWM * FSTPSEL * FASTPWM * HOMENEG * BWDSTEP * FWDSTEP * Z1 * Z2 */ r = sanei_genesys_get_address (reg, 0x3d); r->value = (feedl >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x3e); r->value = (feedl >> 8) & 0xff; r = sanei_genesys_get_address (reg, 0x3f); r->value = feedl & 0xff; r = sanei_genesys_get_address (reg, 0x5e); r->value &= ~0xe0; r = sanei_genesys_get_address (reg, 0x25); r->value = (scan_lines >> 16) & 0xf; r = sanei_genesys_get_address (reg, 0x26); r->value = (scan_lines >> 8) & 0xff; r = sanei_genesys_get_address (reg, 0x27); r->value = scan_lines & 0xff; r = sanei_genesys_get_address (reg, 0x02); r->value &= ~0x01; /*LONGCURV OFF*/ r->value &= ~0x80; /*NOT_HOME OFF*/ r->value |= 0x10; r->value &= ~0x06; if (use_fast_fed) r->value |= 0x08; else r->value &= ~0x08; if (flags & MOTOR_FLAG_AUTO_GO_HOME) r->value |= 0x20; else r->value &= ~0x20; if (flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE) r->value |= 0x40; else r->value &= ~0x40; status = gl841_send_slope_table (dev, 0, slow_slope_table, 256); if (status != SANE_STATUS_GOOD) return status; status = gl841_send_slope_table (dev, 1, back_slope_table, 256); if (status != SANE_STATUS_GOOD) return status; status = gl841_send_slope_table (dev, 2, slow_slope_table, 256); if (status != SANE_STATUS_GOOD) return status; if (use_fast_fed) { status = gl841_send_slope_table (dev, 3, fast_slope_table, 256); if (status != SANE_STATUS_GOOD) return status; } if (flags & MOTOR_FLAG_AUTO_GO_HOME){ status = gl841_send_slope_table (dev, 4, fast_slope_table, 256); if (status != SANE_STATUS_GOOD) return status; } /* now reg 0x21 and 0x24 are available, we can calculate reg 0x22 and 0x23, reg 0x60-0x62 and reg 0x63-0x65 rule: 2*STEPNO+FWDSTEP=2*FASTNO+BWDSTEP */ /* steps of table 0*/ if (min_restep < slow_slope_steps*2+2) min_restep = slow_slope_steps*2+2; /* steps of table 1*/ if (min_restep < back_slope_steps*2+2) min_restep = back_slope_steps*2+2; /* steps of table 0*/ r = sanei_genesys_get_address (reg, REG_FWDSTEP); r->value = min_restep - slow_slope_steps*2; /* steps of table 1*/ r = sanei_genesys_get_address (reg, REG_BWDSTEP); r->value = min_restep - back_slope_steps*2; /* for z1/z2: in dokumentation mentioned variables a-d: a = time needed for acceleration, table 1 b = time needed for reg 0x1f... wouldn't that be reg0x1f*exposure_time? c = time needed for acceleration, table 1 d = time needed for reg 0x22... wouldn't that be reg0x22*exposure_time? z1 = (c+d-1) % exposure_time z2 = (a+b-1) % exposure_time */ /* i don't see any effect of this. i can only guess that this will enhance sub-pixel accuracy z1 = (slope_0_time-1) % exposure_time; z2 = (slope_0_time-1) % exposure_time; */ z1 = z2 = 0; DBG (DBG_info, "gl841_init_motor_regs_scan: z1 = %d\n", z1); DBG (DBG_info, "gl841_init_motor_regs_scan: z2 = %d\n", z2); r = sanei_genesys_get_address (reg, 0x60); r->value = ((z1 >> 16) & 0xff); r = sanei_genesys_get_address (reg, 0x61); r->value = ((z1 >> 8) & 0xff); r = sanei_genesys_get_address (reg, 0x62); r->value = (z1 & 0xff); r = sanei_genesys_get_address (reg, 0x63); r->value = ((z2 >> 16) & 0xff); r = sanei_genesys_get_address (reg, 0x64); r->value = ((z2 >> 8) & 0xff); r = sanei_genesys_get_address (reg, 0x65); r->value = (z2 & 0xff); r = sanei_genesys_get_address (reg, REG1E); r->value &= REG1E_WDTIME; r->value |= scan_dummy; r = sanei_genesys_get_address (reg, 0x67); r->value = 0x3f | (scan_step_type << 6); r = sanei_genesys_get_address (reg, 0x68); r->value = 0x3f; r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = (slow_slope_steps >> 1) + (slow_slope_steps & 1); r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = (back_slope_steps >> 1) + (back_slope_steps & 1); r = sanei_genesys_get_address (reg, 0x69); r->value = (slow_slope_steps >> 1) + (slow_slope_steps & 1); r = sanei_genesys_get_address (reg, 0x6a); r->value = (fast_slope_steps >> 1) + (fast_slope_steps & 1); r = sanei_genesys_get_address (reg, 0x5f); r->value = (fast_slope_steps >> 1) + (fast_slope_steps & 1); DBGCOMPLETED; return SANE_STATUS_GOOD; } static int gl841_get_dpihw(Genesys_Device * dev) { Genesys_Register_Set * r; r = sanei_genesys_get_address (dev->reg, 0x05); if ((r->value & REG05_DPIHW) == REG05_DPIHW_600) return 600; if ((r->value & REG05_DPIHW) == REG05_DPIHW_1200) return 1200; if ((r->value & REG05_DPIHW) == REG05_DPIHW_2400) return 2400; return 0; } static SANE_Status gl841_init_optical_regs_off(Genesys_Register_Set * reg) { Genesys_Register_Set * r; DBGSTART; r = sanei_genesys_get_address (reg, 0x01); r->value &= ~REG01_SCAN; DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl841_init_optical_regs_scan(Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int exposure_time, unsigned int used_res, unsigned int start, unsigned int pixels, int channels, int depth, SANE_Bool half_ccd, int color_filter, int flags ) { unsigned int words_per_line; unsigned int end; unsigned int dpiset; unsigned int i; Genesys_Register_Set * r; SANE_Status status; uint16_t expavg, expr, expb, expg; DBG (DBG_proc, "gl841_init_optical_regs_scan : exposure_time=%d, " "used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, " "half_ccd=%d, flags=%x\n", exposure_time, used_res, start, pixels, channels, depth, half_ccd, flags); end = start + pixels; status = gl841_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_init_optical_regs_scan: failed to set frontend: %s\n", sane_strstatus (status)); return status; } /* adjust used_res for chosen dpihw */ used_res = used_res * gl841_get_dpihw(dev) / dev->sensor.optical_res; /* with half_ccd the optical resolution of the ccd is halved. We don't apply this to dpihw, so we need to double dpiset. For the scanner only the ratio of dpiset and dpihw is of relevance to scale down properly. */ if (half_ccd) dpiset = used_res * 2; else dpiset = used_res; /* gpio part.*/ if (dev->model->gpo_type == GPO_CANONLIDE35) { r = sanei_genesys_get_address (reg, REG6C); if (half_ccd) r->value &= ~0x80; else r->value |= 0x80; } if (dev->model->gpo_type == GPO_CANONLIDE80) { r = sanei_genesys_get_address (reg, REG6C); if (half_ccd) { r->value &= ~0x40; r->value |= 0x20; } else { r->value &= ~0x20; r->value |= 0x40; } } /* enable shading */ r = sanei_genesys_get_address (reg, 0x01); r->value |= REG01_SCAN; if ((flags & OPTICAL_FLAG_DISABLE_SHADING) || (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) r->value &= ~REG01_DVDSET; else r->value |= REG01_DVDSET; /* average looks better than deletion, and we are already set up to use one of the average enabled resolutions */ r = sanei_genesys_get_address (reg, 0x03); r->value |= REG03_AVEENB; if (flags & OPTICAL_FLAG_DISABLE_LAMP) r->value &= ~REG03_LAMPPWR; else r->value |= REG03_LAMPPWR; /* exposure times */ r = sanei_genesys_get_address (reg, 0x10); for (i = 0; i < 6; i++, r++) { if (flags & OPTICAL_FLAG_DISABLE_LAMP) r->value = 0x01;/* 0x0101 is as off as possible */ else { /* EXP[R,G,B] only matter for CIS scanners */ if (dev->sensor.regs_0x10_0x1d[i] == 0x00) r->value = 0x01; /*0x00 will not be accepted*/ else r->value = dev->sensor.regs_0x10_0x1d[i]; } } r = sanei_genesys_get_address (reg, 0x19); if (flags & OPTICAL_FLAG_DISABLE_LAMP) r->value = 0xff; else r->value = 0x50; /* BW threshold */ r = sanei_genesys_get_address (reg, 0x2e); r->value = dev->settings.threshold; r = sanei_genesys_get_address (reg, 0x2f); r->value = dev->settings.threshold; /* monochrome / color scan */ r = sanei_genesys_get_address (reg, 0x04); switch (depth) { case 1: r->value &= ~REG04_BITSET; r->value |= REG04_LINEART; break; case 8: r->value &= ~(REG04_LINEART | REG04_BITSET); break; case 16: r->value &= ~REG04_LINEART; r->value |= REG04_BITSET; break; } /* AFEMOD should depend on FESET, and we should set these * bits separately */ r->value &= ~(REG04_FILTER | REG04_AFEMOD); if (flags & OPTICAL_FLAG_ENABLE_LEDADD) { r->value |= 0x10; /* no filter */ } else if (channels == 1) { switch (color_filter) { case 0: r->value |= 0x14; /* red filter */ break; case 1: r->value |= 0x18; /* green filter */ break; case 2: r->value |= 0x1c; /* blue filter */ break; default: r->value |= 0x10; /* no filter */ break; } } else { if (dev->model->ccd_type == CCD_PLUSTEK_3600) { r->value |= 0x22; /* slow color pixel by pixel */ } else { r->value |= 0x10; /* color pixel by pixel */ } } /* CIS scanners can do true gray by setting LEDADD */ r = sanei_genesys_get_address (reg, 0x87); r->value &= ~REG87_LEDADD; if (flags & OPTICAL_FLAG_ENABLE_LEDADD) { r->value |= REG87_LEDADD; sanei_genesys_get_double (reg, REG_EXPR, &expr); sanei_genesys_get_double (reg, REG_EXPG, &expg); sanei_genesys_get_double (reg, REG_EXPB, &expb); /* use minimal exposure for best image quality */ expavg = expg; if (expr < expg) expavg = expr; if (expb < expavg) expavg = expb; sanei_genesys_set_double (dev->reg, REG_EXPR, expavg); sanei_genesys_set_double (dev->reg, REG_EXPG, expavg); sanei_genesys_set_double (dev->reg, REG_EXPB, expavg); } /* enable gamma tables */ r = sanei_genesys_get_address (reg, 0x05); if (flags & OPTICAL_FLAG_DISABLE_GAMMA) r->value &= ~REG05_GMMENB; else r->value |= REG05_GMMENB; /* sensor parameters */ sanei_gl841_setup_sensor (dev, dev->reg, 1, half_ccd); r = sanei_genesys_get_address (reg, 0x29); r->value = 255; /*<<<"magic" number, only suitable for cis*/ sanei_genesys_set_double(reg, REG_DPISET, dpiset); sanei_genesys_set_double(reg, REG_STRPIXEL, start); sanei_genesys_set_double(reg, REG_ENDPIXEL, end); DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d\n",__func__,start,end); /* words(16bit) before gamma, conversion to 8 bit or lineart*/ words_per_line = (pixels * dpiset) / gl841_get_dpihw(dev); words_per_line *= channels; if (depth == 1) words_per_line = (words_per_line >> 3) + ((words_per_line & 7)?1:0); else words_per_line *= depth / 8; dev->wpl = words_per_line; dev->bpl = words_per_line; r = sanei_genesys_get_address (reg, 0x35); r->value = LOBYTE (HIWORD (words_per_line)); r = sanei_genesys_get_address (reg, 0x36); r->value = HIBYTE (LOWORD (words_per_line)); r = sanei_genesys_get_address (reg, 0x37); r->value = LOBYTE (LOWORD (words_per_line)); sanei_genesys_set_double(reg, REG_LPERIOD, exposure_time); r = sanei_genesys_get_address (reg, 0x34); r->value = dev->sensor.dummy_pixel; DBGCOMPLETED; return SANE_STATUS_GOOD; } static int gl841_get_led_exposure(Genesys_Device * dev) { int d,r,g,b,m; if (!dev->model->is_cis) return 0; d = dev->reg[reg_0x19].value; r = dev->sensor.regs_0x10_0x1d[1] | (dev->sensor.regs_0x10_0x1d[0] << 8); g = dev->sensor.regs_0x10_0x1d[3] | (dev->sensor.regs_0x10_0x1d[2] << 8); b = dev->sensor.regs_0x10_0x1d[5] | (dev->sensor.regs_0x10_0x1d[4] << 8); m = r; if (m < g) m = g; if (m < b) m = b; return m + d; } /** @brief compute exposure time * Compute exposure time for the device and the given scan resolution, * also compute scan_power_mode */ GENESYS_STATIC int gl841_exposure_time(Genesys_Device *dev, float slope_dpi, int scan_step_type, int start, int used_pixels, int *scan_power_mode) { int exposure_time = 0; int exposure_time2 = 0; int led_exposure; *scan_power_mode=0; led_exposure=gl841_get_led_exposure(dev); exposure_time = sanei_genesys_exposure_time2( dev, slope_dpi, scan_step_type, start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ led_exposure, *scan_power_mode); while(*scan_power_mode + 1 < dev->motor.power_mode_count) { exposure_time2 = sanei_genesys_exposure_time2( dev, slope_dpi, scan_step_type, start+used_pixels,/*+tgtime? currently done in sanei_genesys_exposure_time2 with tgtime = 32 pixel*/ led_exposure, *scan_power_mode + 1); if (exposure_time < exposure_time2) break; exposure_time = exposure_time2; (*scan_power_mode)++; } return exposure_time; } /**@brief compute scan_step_type * Try to do at least 4 steps per line. if that is impossible we will have to * live with that. * @param dev device * @param yres motor resolution */ GENESYS_STATIC int gl841_scan_step_type(Genesys_Device *dev, int yres) { int scan_step_type=0; /* TODO : check if there is a bug around the use of max_step_type */ /* should be <=1, need to chek all devices entry in genesys_devices */ if (yres*4 < dev->motor.base_ydpi || dev->motor.max_step_type <= 0) { scan_step_type = 0; } else if (yres*4 < dev->motor.base_ydpi*2 || dev->motor.max_step_type <= 1) { scan_step_type = 1; } else { scan_step_type = 2; } /* this motor behaves differently */ if (dev->model->motor_type==MOTOR_CANONLIDE80) { /* driven by 'frequency' tables ? */ scan_step_type = 0; } return scan_step_type; } /* set up registers for an actual scan * * this function sets up the scanner to scan in normal or single line mode */ GENESYS_STATIC SANE_Status gl841_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres,/*dpi*/ float yres,/*dpi*/ float startx,/*optical_res, from dummy_pixel+1*/ float starty,/*base_ydpi, from home!*/ float pixels, float lines, unsigned int depth, unsigned int channels, int color_filter, unsigned int flags ) { int used_res; int start, used_pixels; int bytes_per_line; int move; unsigned int lincnt; int exposure_time; int scan_power_mode; int i; int stagger; int avg; int slope_dpi = 0; int dummy = 0; int scan_step_type = 1; int max_shift; size_t requested_buffer_size, read_buffer_size; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; SANE_Status status; unsigned int oflags; /**> optical flags */ DBG (DBG_info, "gl841_init_scan_regs settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g/%g\n" "Depth/Channels: %u/%u\n" "Flags : %x\n\n", xres, yres, lines, pixels, startx, starty, depth, channels, flags); /* results: for scanner: half_ccd start end dpiset exposure_time dummy z1 z2 for ordered_read: dev->words_per_line dev->read_factor dev->requested_buffer_size dev->read_buffer_size dev->read_pos dev->read_bytes_in_buffer dev->read_bytes_left dev->max_shift dev->stagger independent of our calculated values: dev->total_bytes_read dev->bytes_to_read */ /* half_ccd */ /* we have 2 domains for ccd: xres below or above half ccd max dpi */ if (dev->sensor.optical_res < 2 * xres || !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)) { half_ccd = SANE_FALSE; } else { half_ccd = SANE_TRUE; } /* optical_res */ optical_res = dev->sensor.optical_res; if (half_ccd) optical_res /= 2; /* stagger */ if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "gl841_init_scan_regs : stagger=%d lines\n", stagger); /* used_res */ i = optical_res / xres; /* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */ if (i < 2 || (flags & SCAN_FLAG_USE_OPTICAL_RES)) /* optical_res >= xres > optical_res/2 */ used_res = optical_res; else if (i < 3) /* optical_res/2 >= xres > optical_res/3 */ used_res = optical_res/2; else if (i < 4) /* optical_res/3 >= xres > optical_res/4 */ used_res = optical_res/3; else if (i < 5) /* optical_res/4 >= xres > optical_res/5 */ used_res = optical_res/4; else if (i < 6) /* optical_res/5 >= xres > optical_res/6 */ used_res = optical_res/5; else if (i < 8) /* optical_res/6 >= xres > optical_res/8 */ used_res = optical_res/6; else if (i < 10) /* optical_res/8 >= xres > optical_res/10 */ used_res = optical_res/8; else if (i < 12) /* optical_res/10 >= xres > optical_res/12 */ used_res = optical_res/10; else if (i < 15) /* optical_res/12 >= xres > optical_res/15 */ used_res = optical_res/12; else used_res = optical_res/15; /* compute scan parameters values */ /* pixels are allways given at half or full CCD optical resolution */ /* use detected left margin and fixed value */ /* start */ /* add x coordinates */ start = ((dev->sensor.CCD_start_xoffset + startx) * used_res) / dev->sensor.optical_res; /* needs to be aligned for used_res */ start = (start * optical_res) / used_res; start += dev->sensor.dummy_pixel + 1; if (stagger > 0) start |= 1; /* in case of SHDAREA, we need to align start * on pixel average factor, startx is different of * 0 only when calling for function to setup for * scan, where shading data needs to be align */ if((dev->reg[reg_0x01].value & REG01_SHDAREA) != 0) { avg=optical_res/used_res; start=(start/avg)*avg; } /* compute correct pixels number */ /* pixels */ used_pixels = (pixels * optical_res) / xres; /* round up pixels number if needed */ if (used_pixels * xres < pixels * optical_res) used_pixels++; /* dummy */ /* dummy lines: may not be usefull, for instance 250 dpi works with 0 or 1 dummy line. Maybe the dummy line adds correctness since the motor runs slower (higher dpi) */ /* for cis this creates better aligned color lines: dummy \ scanned lines 0: R G B R ... 1: R G B - R ... 2: R G B - - R ... 3: R G B - - - R ... 4: R G B - - - - R ... 5: R G B - - - - - R ... 6: R G B - - - - - - R ... 7: R G B - - - - - - - R ... 8: R G B - - - - - - - - R ... 9: R G B - - - - - - - - - R ... 10: R G B - - - - - - - - - - R ... 11: R G B - - - - - - - - - - - R ... 12: R G B - - - - - - - - - - - - R ... 13: R G B - - - - - - - - - - - - - R ... 14: R G B - - - - - - - - - - - - - - R ... 15: R G B - - - - - - - - - - - - - - - R ... -- pierre */ dummy = 0; /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ if (dev->model->is_cis) slope_dpi = yres*channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); scan_step_type = gl841_scan_step_type(dev, yres); exposure_time = gl841_exposure_time(dev, slope_dpi, scan_step_type, start, used_pixels, &scan_power_mode); DBG (DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time); /*** optical parameters ***/ /* in case of dynamic lineart, we use an internal 8 bit gray scan * to generate 1 lineart data */ if(flags & SCAN_FLAG_DYNAMIC_LINEART) { depth=8; } oflags=0; if (flags & SCAN_FLAG_DISABLE_SHADING) { oflags |= OPTICAL_FLAG_DISABLE_SHADING; } if ((flags & SCAN_FLAG_DISABLE_GAMMA) || (depth==16)) { oflags |= OPTICAL_FLAG_DISABLE_GAMMA; } if (flags & SCAN_FLAG_DISABLE_LAMP) { oflags |= OPTICAL_FLAG_DISABLE_LAMP; } if (flags & SCAN_FLAG_ENABLE_LEDADD) { oflags |= OPTICAL_FLAG_ENABLE_LEDADD; } status = gl841_init_optical_regs_scan(dev, reg, exposure_time, used_res, start, used_pixels, channels, depth, half_ccd, color_filter, oflags); if (status != SANE_STATUS_GOOD) { return status; } /*** motor parameters ***/ /* scanned area must be enlarged by max color shift needed */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,flags); /* lincnt */ lincnt = lines + max_shift + stagger; /* add tl_y to base movement */ move = starty; DBG (DBG_info, "gl841_init_scan_regs: move=%d steps\n", move); /* subtract current head position */ move -= dev->scanhead_position_in_steps; DBG (DBG_info, "gl841_init_scan_regs: move=%d steps\n", move); if (move < 0) move = 0; /* round it */ /* the move is not affected by dummy -- pierre */ /* move = ((move + dummy) / (dummy + 1)) * (dummy + 1); DBG (DBG_info, "gl841_init_scan_regs: move=%d steps\n", move);*/ if (flags & SCAN_FLAG_SINGLE_LINE) status = gl841_init_motor_regs_off(reg, dev->model->is_cis?lincnt*channels:lincnt); else status = gl841_init_motor_regs_scan(dev, reg, exposure_time, slope_dpi, scan_step_type, dev->model->is_cis?lincnt*channels:lincnt, dummy, move, scan_power_mode, (flags & SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE)? MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE:0 ); if (status != SANE_STATUS_GOOD) return status; /*** prepares data reordering ***/ /* words_per_line */ bytes_per_line = (used_pixels * used_res) / optical_res; bytes_per_line = (bytes_per_line * channels * depth) / 8; requested_buffer_size = 8 * bytes_per_line; /* we must use a round number of bytes_per_line */ if (requested_buffer_size > BULKIN_MAXSIZE) requested_buffer_size = (BULKIN_MAXSIZE / bytes_per_line) * bytes_per_line; read_buffer_size = 2 * requested_buffer_size + ((max_shift + stagger) * used_pixels * channels * depth) / 8; RIE(sanei_genesys_buffer_free(&(dev->read_buffer))); RIE(sanei_genesys_buffer_alloc(&(dev->read_buffer), read_buffer_size)); RIE(sanei_genesys_buffer_free(&(dev->lines_buffer))); RIE(sanei_genesys_buffer_alloc(&(dev->lines_buffer), read_buffer_size)); RIE(sanei_genesys_buffer_free(&(dev->shrink_buffer))); RIE(sanei_genesys_buffer_alloc(&(dev->shrink_buffer), requested_buffer_size)); RIE(sanei_genesys_buffer_free(&(dev->out_buffer))); RIE(sanei_genesys_buffer_alloc(&(dev->out_buffer), (8 * dev->settings.pixels * channels * depth) / 8)); dev->read_bytes_left = bytes_per_line * lincnt; DBG (DBG_info, "gl841_init_scan_regs: physical bytes to read = %lu\n", (u_long) dev->read_bytes_left); dev->read_active = SANE_TRUE; dev->current_setup.pixels = (used_pixels * used_res)/optical_res; dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure_time; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; /* TODO: should this be done elsewhere? */ /* scan bytes to send to the frontend */ /* theory : target_size = (dev->settings.pixels * dev->settings.lines * channels * depth) / 8; but it suffers from integer overflow so we do the following: 1 bit color images store color data byte-wise, eg byte 0 contains 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains 8 bits of blue. This does not fix the overflow, though. 644mp*16 = 10gp, leading to an overflow -- pierre */ dev->total_bytes_read = 0; if (depth == 1) dev->total_bytes_to_read = ((dev->settings.pixels * dev->settings.lines) / 8 + (((dev->settings.pixels * dev->settings.lines)%8)?1:0) ) * channels; else dev->total_bytes_to_read = dev->settings.pixels * dev->settings.lines * channels * (depth / 8); DBG (DBG_info, "gl841_init_scan_regs: total bytes to send = %lu\n", (u_long) dev->total_bytes_to_read); /* END TODO */ DBG (DBG_proc, "gl841_init_scan_regs: completed\n"); return SANE_STATUS_GOOD; } static SANE_Status gl841_calculate_current_setup (Genesys_Device * dev) { int channels; int depth; int start; float xres;/*dpi*/ float yres;/*dpi*/ float startx;/*optical_res, from dummy_pixel+1*/ float pixels; float lines; int used_res; int used_pixels; unsigned int lincnt; int exposure_time; int scan_power_mode; int i; int stagger; int slope_dpi = 0; int dummy = 0; int scan_step_type = 1; int max_shift; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; DBG (DBG_info, "gl841_calculate_current_setup settings:\n" "Resolution: %uDPI\n" "Lines : %u\n" "PPL : %u\n" "Startpos : %.3f/%.3f\n" "Scan mode : %d\n\n", dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* channels */ if (dev->settings.scan_mode == 4) /* single pass color */ channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == 0) depth = 1; /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; xres = dev->settings.xres;/*dpi*/ yres = dev->settings.yres;/*dpi*/ startx = start;/*optical_res, from dummy_pixel+1*/ pixels = dev->settings.pixels; lines = dev->settings.lines; DBG (DBG_info, "gl841_calculate_current_setup settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g\n" "Depth/Channels: %u/%u\n\n", xres, yres, lines, pixels, startx, depth, channels); /* half_ccd */ /* we have 2 domains for ccd: xres below or above half ccd max dpi */ if ((dev->sensor.optical_res < 2 * xres) || !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)) { half_ccd = SANE_FALSE; } else { half_ccd = SANE_TRUE; } /* optical_res */ optical_res = dev->sensor.optical_res; if (half_ccd) optical_res /= 2; /* stagger */ if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "gl841_calculate_current_setup: stagger=%d lines\n", stagger); /* used_res */ i = optical_res / xres; /* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */ if (i < 2) /* optical_res >= xres > optical_res/2 */ used_res = optical_res; else if (i < 3) /* optical_res/2 >= xres > optical_res/3 */ used_res = optical_res/2; else if (i < 4) /* optical_res/3 >= xres > optical_res/4 */ used_res = optical_res/3; else if (i < 5) /* optical_res/4 >= xres > optical_res/5 */ used_res = optical_res/4; else if (i < 6) /* optical_res/5 >= xres > optical_res/6 */ used_res = optical_res/5; else if (i < 8) /* optical_res/6 >= xres > optical_res/8 */ used_res = optical_res/6; else if (i < 10) /* optical_res/8 >= xres > optical_res/10 */ used_res = optical_res/8; else if (i < 12) /* optical_res/10 >= xres > optical_res/12 */ used_res = optical_res/10; else if (i < 15) /* optical_res/12 >= xres > optical_res/15 */ used_res = optical_res/12; else used_res = optical_res/15; /* compute scan parameters values */ /* pixels are allways given at half or full CCD optical resolution */ /* use detected left margin and fixed value */ /* start */ /* add x coordinates */ start = ((dev->sensor.CCD_start_xoffset + startx) * used_res) / dev->sensor.optical_res; /* needs to be aligned for used_res */ start = (start * optical_res) / used_res; start += dev->sensor.dummy_pixel + 1; if (stagger > 0) start |= 1; /* compute correct pixels number */ /* pixels */ used_pixels = (pixels * optical_res) / xres; /* round up pixels number if needed */ if (used_pixels * xres < pixels * optical_res) used_pixels++; /* dummy */ /* dummy lines: may not be usefull, for instance 250 dpi works with 0 or 1 dummy line. Maybe the dummy line adds correctness since the motor runs slower (higher dpi) */ /* for cis this creates better aligned color lines: dummy \ scanned lines 0: R G B R ... 1: R G B - R ... 2: R G B - - R ... 3: R G B - - - R ... 4: R G B - - - - R ... 5: R G B - - - - - R ... 6: R G B - - - - - - R ... 7: R G B - - - - - - - R ... 8: R G B - - - - - - - - R ... 9: R G B - - - - - - - - - R ... 10: R G B - - - - - - - - - - R ... 11: R G B - - - - - - - - - - - R ... 12: R G B - - - - - - - - - - - - R ... 13: R G B - - - - - - - - - - - - - R ... 14: R G B - - - - - - - - - - - - - - R ... 15: R G B - - - - - - - - - - - - - - - R ... -- pierre */ dummy = 0; /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ if (dev->model->is_cis) slope_dpi = yres*channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); scan_step_type = gl841_scan_step_type(dev, yres); exposure_time = gl841_exposure_time(dev, slope_dpi, scan_step_type, start, used_pixels, &scan_power_mode); DBG (DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time); /* scanned area must be enlarged by max color shift needed */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0); /* lincnt */ lincnt = lines + max_shift + stagger; dev->current_setup.pixels = (used_pixels * used_res)/optical_res; dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure_time; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; DBGCOMPLETED; return SANE_STATUS_GOOD; } static void gl841_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set) { DBG (DBG_proc, "gl841_set_motor_power\n"); if (set) { sanei_genesys_set_reg_from_set (regs, 0x02, sanei_genesys_read_reg_from_set (regs, 0x02) | REG02_MTRPWR); } else { sanei_genesys_set_reg_from_set (regs, 0x02, sanei_genesys_read_reg_from_set (regs, 0x02) & ~REG02_MTRPWR); } } static void gl841_set_lamp_power (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool set) { Genesys_Register_Set * r; int i; if (set) { sanei_genesys_set_reg_from_set (regs, 0x03, sanei_genesys_read_reg_from_set (regs, 0x03) | REG03_LAMPPWR); r = sanei_genesys_get_address (regs, 0x10); for (i = 0; i < 6; i++, r++) { if (dev->sensor.regs_0x10_0x1d[i] == 0x00) r->value = 0x01;/*0x00 will not be accepted*/ else r->value = dev->sensor.regs_0x10_0x1d[i]; } r = sanei_genesys_get_address (regs, 0x19); r->value = 0x50; } else { sanei_genesys_set_reg_from_set (regs, 0x03, sanei_genesys_read_reg_from_set (regs, 0x03) & ~REG03_LAMPPWR); r = sanei_genesys_get_address (regs, 0x10); for (i = 0; i < 6; i++, r++) { r->value = 0x01;/* 0x0101 is as off as possible */ } r = sanei_genesys_get_address (regs, 0x19); r->value = 0xff; } } /*for fast power saving methods only, like disabling certain amplifiers*/ static SANE_Status gl841_save_power(Genesys_Device * dev, SANE_Bool enable) { uint8_t val; DBG(DBG_proc, "gl841_save_power: enable = %d\n", enable); if (enable) { if (dev->model->gpo_type == GPO_CANONLIDE35) { /* expect GPIO17 to be enabled, and GPIO9 to be disabled, while GPIO8 is disabled*/ /* final state: GPIO8 disabled, GPIO9 enabled, GPIO17 disabled, GPIO18 disabled*/ sanei_genesys_read_register(dev, REG6D, &val); sanei_genesys_write_register(dev, REG6D, val | 0x80); usleep(1000); /*enable GPIO9*/ sanei_genesys_read_register(dev, REG6C, &val); sanei_genesys_write_register(dev, REG6C, val | 0x01); /*disable GPO17*/ sanei_genesys_read_register(dev, REG6B, &val); sanei_genesys_write_register(dev, REG6B, val & ~REG6B_GPO17); /*disable GPO18*/ sanei_genesys_read_register(dev, REG6B, &val); sanei_genesys_write_register(dev, REG6B, val & ~REG6B_GPO18); usleep(1000); sanei_genesys_read_register(dev, REG6D, &val); sanei_genesys_write_register(dev, REG6D, val & ~0x80); } if (dev->model->gpo_type == GPO_DP685) { sanei_genesys_read_register(dev, REG6B, &val); sanei_genesys_write_register(dev, REG6B, val & ~REG6B_GPO17); dev->reg[reg_0x6b].value &= ~REG6B_GPO17; dev->calib_reg[reg_0x6b].value &= ~REG6B_GPO17; } gl841_set_fe (dev, AFE_POWER_SAVE); } else { if (dev->model->gpo_type == GPO_CANONLIDE35) { /* expect GPIO17 to be enabled, and GPIO9 to be disabled, while GPIO8 is disabled*/ /* final state: GPIO8 enabled, GPIO9 disabled, GPIO17 enabled, GPIO18 enabled*/ sanei_genesys_read_register(dev, REG6D, &val); sanei_genesys_write_register(dev, REG6D, val | 0x80); usleep(10000); /*disable GPIO9*/ sanei_genesys_read_register(dev, REG6C, &val); sanei_genesys_write_register(dev, REG6C, val & ~0x01); /*enable GPIO10*/ sanei_genesys_read_register(dev, REG6C, &val); sanei_genesys_write_register(dev, REG6C, val | 0x02); /*enable GPO17*/ sanei_genesys_read_register(dev, REG6B, &val); sanei_genesys_write_register(dev, REG6B, val | REG6B_GPO17); dev->reg[reg_0x6b].value |= REG6B_GPO17; dev->calib_reg[reg_0x6b].value |= REG6B_GPO17; /*enable GPO18*/ sanei_genesys_read_register(dev, REG6B, &val); sanei_genesys_write_register(dev, REG6B, val | REG6B_GPO18); dev->reg[reg_0x6b].value |= REG6B_GPO18; dev->calib_reg[reg_0x6b].value |= REG6B_GPO18; } if (dev->model->gpo_type == GPO_DP665 || dev->model->gpo_type == GPO_DP685) { sanei_genesys_read_register(dev, REG6B, &val); sanei_genesys_write_register(dev, REG6B, val | REG6B_GPO17); dev->reg[reg_0x6b].value |= REG6B_GPO17; dev->calib_reg[reg_0x6b].value |= REG6B_GPO17; } } return SANE_STATUS_GOOD; } static SANE_Status gl841_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ ) { SANE_Status status; Genesys_Register_Set local_reg[7]; int rate, exposure_time, tgtime, time; DBG (DBG_proc, "gl841_set_powersaving (delay = %d)\n", delay); local_reg[0].address = 0x01; local_reg[0].value = sanei_genesys_read_reg_from_set (dev->reg, 0x01); /* disable fastmode */ local_reg[1].address = 0x03; local_reg[1].value = sanei_genesys_read_reg_from_set (dev->reg, 0x03); /* Lamp power control */ local_reg[2].address = 0x05; local_reg[2].value = sanei_genesys_read_reg_from_set (dev->reg, 0x05) /*& ~REG05_BASESEL*/; /* 24 clocks/pixel */ local_reg[3].address = 0x18; /* Set CCD type */ local_reg[3].value = 0x00; local_reg[4].address = 0x38; /* line period low */ local_reg[4].value = 0x00; local_reg[5].address = 0x39; /* line period high */ local_reg[5].value = 0x00; local_reg[6].address = 0x1c; /* period times for LPeriod, expR,expG,expB, Z1MODE, Z2MODE */ local_reg[6].value = sanei_genesys_read_reg_from_set (dev->reg, 0x05) & ~REG1C_TGTIME; if (!delay) local_reg[1].value = local_reg[1].value & 0xf0; /* disable lampdog and set lamptime = 0 */ else if (delay < 20) local_reg[1].value = (local_reg[1].value & 0xf0) | 0x09; /* enable lampdog and set lamptime = 1 */ else local_reg[1].value = (local_reg[1].value & 0xf0) | 0x0f; /* enable lampdog and set lamptime = 7 */ time = delay * 1000 * 60; /* -> msec */ exposure_time = (uint32_t) (time * 32000.0 / (24.0 * 64.0 * (local_reg[1].value & REG03_LAMPTIM) * 1024.0) + 0.5); /* 32000 = system clock, 24 = clocks per pixel */ rate = (exposure_time + 65536) / 65536; if (rate > 4) { rate = 8; tgtime = 3; } else if (rate > 2) { rate = 4; tgtime = 2; } else if (rate > 1) { rate = 2; tgtime = 1; } else { rate = 1; tgtime = 0; } local_reg[6].value |= tgtime; exposure_time /= rate; if (exposure_time > 65535) exposure_time = 65535; local_reg[4].value = exposure_time >> 8; /* highbyte */ local_reg[5].value = exposure_time & 255; /* lowbyte */ status = gl841_bulk_write_register (dev, local_reg, sizeof (local_reg)/sizeof (local_reg[0])); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "gl841_set_powersaving: failed to bulk write registers: %s\n", sane_strstatus (status)); DBG (DBG_proc, "gl841_set_powersaving: completed\n"); return status; } #ifndef UNIT_TESTING static #endif SANE_Status gl841_start_action (Genesys_Device * dev) { return sanei_genesys_write_register (dev, 0x0f, 0x01); } #ifndef UNIT_TESTING static #endif SANE_Status gl841_stop_action (Genesys_Device * dev) { Genesys_Register_Set local_reg[GENESYS_GL841_MAX_REGS+1]; SANE_Status status; uint8_t val40, val; unsigned int loop; DBG (DBG_proc, "%s\n", __func__); status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } status = sanei_genesys_read_register(dev, 0x40, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n",__func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* only stop action if needed */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)) { DBG (DBG_info, "%s: already stopped\n", __func__); DBGCOMPLETED; return SANE_STATUS_GOOD; } memcpy (local_reg, dev->reg, (GENESYS_GL841_MAX_REGS+1) * sizeof (Genesys_Register_Set)); gl841_init_optical_regs_off(local_reg); gl841_init_motor_regs_off(local_reg,0); status = gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __func__, sane_strstatus (status)); return status; } /* looks like writing the right registers to zero is enough to get the chip out of scan mode into command mode, actually triggering(writing to register 0x0f) seems to be unnecessary */ loop = 10; while (loop > 0) { status = sanei_genesys_read_register(dev, 0x40, &val40); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n",__func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* if scanner is in command mode, we are done */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)) { DBGCOMPLETED; return SANE_STATUS_GOOD; } usleep(100*1000); loop--; } DBGCOMPLETED; return SANE_STATUS_IO_ERROR; } static SANE_Status gl841_get_paper_sensor(Genesys_Device * dev, SANE_Bool * paper_loaded) { SANE_Status status; uint8_t val; status = sanei_genesys_read_register(dev, REG6D, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_get_paper_sensor: failed to read gpio: %s\n", sane_strstatus (status)); return status; } *paper_loaded = (val & 0x1) == 0; return SANE_STATUS_GOOD; } static SANE_Status gl841_eject_document (Genesys_Device * dev) { Genesys_Register_Set local_reg[GENESYS_GL841_MAX_REGS+1]; SANE_Status status; uint8_t val; SANE_Bool paper_loaded; unsigned int init_steps; float feed_mm; int loop; DBG (DBG_proc, "gl841_eject_document\n"); if (dev->model->is_sheetfed == SANE_FALSE) { DBG (DBG_proc, "gl841_eject_document: there is no \"eject sheet\"-concept for non sheet fed\n"); DBG (DBG_proc, "gl841_eject_document: finished\n"); return SANE_STATUS_GOOD; } memset (local_reg, 0, sizeof (local_reg)); val = 0; status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_eject_document: failed to read status register: %s\n", sane_strstatus (status)); return status; } status = gl841_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_eject_document: failed to stop motor: %s\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } memcpy (local_reg, dev->reg, (GENESYS_GL841_MAX_REGS+1) * sizeof (Genesys_Register_Set)); gl841_init_optical_regs_off(local_reg); gl841_init_motor_regs(dev,local_reg, 65536,MOTOR_ACTION_FEED,0); status = gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_eject_document: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } status = gl841_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_eject_document: failed to start motor: %s\n", sane_strstatus (status)); gl841_stop_action (dev); /* send original registers */ gl841_bulk_write_register (dev, dev->reg, GENESYS_GL841_MAX_REGS); return status; } RIE(gl841_get_paper_sensor(dev, &paper_loaded)); if (paper_loaded) { DBG (DBG_info, "gl841_eject_document: paper still loaded\n"); /* force document TRUE, because it is definitely present */ dev->document = SANE_TRUE; dev->scanhead_position_in_steps = 0; loop = 300; while (loop > 0) /* do not wait longer then 30 seconds */ { RIE(gl841_get_paper_sensor(dev, &paper_loaded)); if (!paper_loaded) { DBG (DBG_info, "gl841_eject_document: reached home position\n"); DBG (DBG_proc, "gl841_eject_document: finished\n"); break; } usleep (100000); /* sleep 100 ms */ --loop; } if (loop == 0) { /* when we come here then the scanner needed too much time for this, so we better stop the motor */ gl841_stop_action (dev); DBG (DBG_error, "gl841_eject_document: timeout while waiting for scanhead to go home\n"); return SANE_STATUS_IO_ERROR; } } feed_mm = SANE_UNFIX(dev->model->eject_feed); if (dev->document) { feed_mm += SANE_UNFIX(dev->model->post_scan); } status = sanei_genesys_read_feed_steps(dev, &init_steps); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_eject_document: failed to read feed steps: %s\n", sane_strstatus (status)); return status; } /* now feed for extra steps */ loop = 0; while (loop < 300) /* do not wait longer then 30 seconds */ { unsigned int steps; status = sanei_genesys_read_feed_steps(dev, &steps); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_eject_document: failed to read feed steps: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl841_eject_document: init_steps: %d, steps: %d\n", init_steps, steps); if (steps > init_steps + (feed_mm * dev->motor.base_ydpi) / MM_PER_INCH) { break; } usleep (100000); /* sleep 100 ms */ ++loop; } status = gl841_stop_action(dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_eject_document: failed to stop motor: %s\n", sane_strstatus (status)); return status; } dev->document = SANE_FALSE; DBG (DBG_proc, "gl841_eject_document: finished\n"); return SANE_STATUS_GOOD; } static SANE_Status gl841_load_document (Genesys_Device * dev) { SANE_Status status; SANE_Bool paper_loaded; int loop = 300; DBG (DBG_proc, "gl841_load_document\n"); while (loop > 0) /* do not wait longer then 30 seconds */ { RIE(gl841_get_paper_sensor(dev, &paper_loaded)); if (paper_loaded) { DBG (DBG_info, "gl841_load_document: document inserted\n"); /* when loading OK, document is here */ dev->document = SANE_TRUE; usleep (1000000); /* give user 1000ms to place document correctly */ break; } usleep (100000); /* sleep 100 ms */ --loop; } if (loop == 0) { /* when we come here then the user needed to much time for this */ DBG (DBG_error, "gl841_load_document: timeout while waiting for document\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_proc, "gl841_load_document: finished\n"); return SANE_STATUS_GOOD; } /** * detects end of document and adjust current scan * to take it into account * used by sheetfed scanners */ static SANE_Status gl841_detect_document_end (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; SANE_Bool paper_loaded; unsigned int scancnt = 0, lincnt, postcnt; uint8_t val; size_t total_bytes_to_read; DBG (DBG_proc, "%s: begin\n", __func__); RIE (gl841_get_paper_sensor (dev, &paper_loaded)); /* sheetfed scanner uses home sensor as paper present */ if ((dev->document == SANE_TRUE) && !paper_loaded) { DBG (DBG_info, "%s: no more document\n", __func__); dev->document = SANE_FALSE; /* we can't rely on total_bytes_to_read since the frontend * might have been slow to read data, so we re-evaluate the * amount of data to scan form the hardware settings */ status=sanei_genesys_read_scancnt(dev,&scancnt); if(status!=SANE_STATUS_GOOD) { dev->total_bytes_to_read = dev->total_bytes_read; dev->read_bytes_left = 0; DBG (DBG_proc, "%s: finished\n", __func__); return SANE_STATUS_GOOD; } if (dev->settings.scan_mode == SCAN_MODE_COLOR && dev->model->is_cis) { scancnt/=3; } DBG (DBG_io, "%s: scancnt=%u lines\n",__func__, scancnt); RIE(sanei_genesys_read_register(dev, 0x25, &val)); lincnt=65536*val; RIE(sanei_genesys_read_register(dev, 0x26, &val)); lincnt+=256*val; RIE(sanei_genesys_read_register(dev, 0x27, &val)); lincnt+=val; DBG (DBG_io, "%s: lincnt=%u lines\n",__func__, lincnt); postcnt=(SANE_UNFIX(dev->model->post_scan)/MM_PER_INCH)*dev->settings.yres; DBG (DBG_io, "%s: postcnt=%u lines\n",__func__, postcnt); /* the current scancnt is also the final one, so we use it to * compute total bytes to read. We also add the line count to eject document */ total_bytes_to_read=(scancnt+postcnt)*dev->wpl; DBG (DBG_io, "%s: old total_bytes_to_read=%u\n",__func__,(unsigned int)dev->total_bytes_to_read); DBG (DBG_io, "%s: new total_bytes_to_read=%u\n",__func__,(unsigned int)total_bytes_to_read); /* assign new end value */ if(dev->total_bytes_to_read>total_bytes_to_read) { DBG (DBG_io, "%s: scan shorten\n",__func__); dev->total_bytes_to_read=total_bytes_to_read; } } DBG (DBG_proc, "%s: finished\n", __func__); return SANE_STATUS_GOOD; } /* Send the low-level scan command */ /* todo : is this that useful ? */ #ifndef UNIT_TESTING static #endif SANE_Status gl841_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor) { SANE_Status status; Genesys_Register_Set local_reg[4]; uint8_t val; DBG (DBG_proc, "gl841_begin_scan\n"); if (dev->model->gpo_type == GPO_CANONLIDE80) { RIE (sanei_genesys_read_register (dev, REG6B, &val)); val = REG6B_GPO18; RIE (sanei_genesys_write_register (dev, REG6B, val)); } local_reg[0].address = 0x03; if (dev->model->ccd_type != CCD_PLUSTEK_3600) { local_reg[0].value = sanei_genesys_read_reg_from_set (reg, 0x03) | REG03_LAMPPWR; } else { local_reg[0].value = sanei_genesys_read_reg_from_set (reg, 0x03); /* TODO PLUSTEK_3600: why ?? */ } local_reg[1].address = 0x01; local_reg[1].value = sanei_genesys_read_reg_from_set (reg, 0x01) | REG01_SCAN; /* set scan bit */ local_reg[2].address = 0x0d; local_reg[2].value = 0x01; local_reg[3].address = 0x0f; if (start_motor) local_reg[3].value = 0x01; else local_reg[3].value = 0x00; /* do not start motor yet */ status = gl841_bulk_write_register (dev, local_reg, sizeof (local_reg)/sizeof (local_reg[0])); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_begin_scan: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } DBG (DBG_proc, "gl841_begin_scan: completed\n"); return status; } /* Send the stop scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl841_end_scan (Genesys_Device * dev, Genesys_Register_Set __sane_unused__ * reg, SANE_Bool check_stop) { SANE_Status status; DBG (DBG_proc, "gl841_end_scan (check_stop = %d)\n", check_stop); if (dev->model->is_sheetfed == SANE_TRUE) { status = SANE_STATUS_GOOD; } else /* flat bed scanners */ { status = gl841_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_end_scan: failed to stop: %s\n", sane_strstatus (status)); return status; } } DBG (DBG_proc, "gl841_end_scan: completed\n"); return status; } /* Moves the slider to steps */ #ifndef UNIT_TESTING static #endif SANE_Status gl841_feed (Genesys_Device * dev, int steps) { Genesys_Register_Set local_reg[GENESYS_GL841_MAX_REGS+1]; SANE_Status status; uint8_t val; int loop; DBG (DBG_proc, "gl841_feed (steps = %d)\n", steps); status = gl841_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_feed: failed to stop action: %s\n", sane_strstatus (status)); return status; } memcpy (local_reg, dev->reg, (GENESYS_GL841_MAX_REGS+1) * sizeof (Genesys_Register_Set)); gl841_init_optical_regs_off(local_reg); gl841_init_motor_regs(dev,local_reg, steps,MOTOR_ACTION_FEED,0); status = gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_feed: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } status = gl841_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_feed: failed to start motor: %s\n", sane_strstatus (status)); gl841_stop_action (dev); /* send original registers */ gl841_bulk_write_register (dev, dev->reg, GENESYS_GL841_MAX_REGS); return status; } loop = 0; while (loop < 300) /* do not wait longer then 30 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_feed: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (!(val & REG41_MOTORENB)) /* motor enabled */ { DBG (DBG_proc, "gl841_feed: finished\n"); dev->scanhead_position_in_steps += steps; return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ ++loop; } /* when we come here then the scanner needed too much time for this, so we better stop the motor */ gl841_stop_action (dev); DBG (DBG_error, "gl841_feed: timeout while waiting for scanhead to go home\n"); return SANE_STATUS_IO_ERROR; } /* Moves the slider to the home (top) position slowly */ #ifndef UNIT_TESTING static #endif SANE_Status gl841_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) { Genesys_Register_Set local_reg[GENESYS_GL841_MAX_REGS+1]; SANE_Status status; Genesys_Register_Set *r; uint8_t val; int loop = 0; DBG (DBG_proc, "gl841_slow_back_home (wait_until_home = %d)\n", wait_until_home); if (dev->model->is_sheetfed == SANE_TRUE) { DBG (DBG_proc, "gl841_slow_back_home: there is no \"home\"-concept for sheet fed\n"); DBG (DBG_proc, "gl841_slow_back_home: finished\n"); return SANE_STATUS_GOOD; } /* reset gpio pin */ if (dev->model->gpo_type == GPO_CANONLIDE35) { RIE (sanei_genesys_read_register (dev, REG6C, &val)); val = dev->gpo.value[0]; RIE (sanei_genesys_write_register (dev, REG6C, val)); } if (dev->model->gpo_type == GPO_CANONLIDE80) { RIE (sanei_genesys_read_register (dev, REG6B, &val)); val = REG6B_GPO18 | REG6B_GPO17; RIE (sanei_genesys_write_register (dev, REG6B, val)); } gl841_save_power(dev, SANE_FALSE); /* first read gives HOME_SENSOR true */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } usleep (100000); /* sleep 100 ms */ /* second is reliable */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } dev->scanhead_position_in_steps = 0; if (val & REG41_HOMESNR) /* is sensor at home? */ { DBG (DBG_info, "gl841_slow_back_home: already at home, completed\n"); dev->scanhead_position_in_steps = 0; return SANE_STATUS_GOOD; } /* end previous scan if any */ r = sanei_genesys_get_address (dev->reg, REG01); r->value &= ~REG01_SCAN; status = sanei_genesys_write_register (dev, REG01, r->value); /* if motor is on, stop current action */ if (val & REG41_MOTORENB) { status = gl841_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_slow_back_home: failed to stop motor: %s\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } } memcpy (local_reg, dev->reg, (GENESYS_GL841_MAX_REGS+1) * sizeof (Genesys_Register_Set)); gl841_init_motor_regs(dev,local_reg, 65536,MOTOR_ACTION_GO_HOME,0); /* set up for reverse and no scan */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; RIE (gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS)); status = gl841_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_slow_back_home: failed to start motor: %s\n", sane_strstatus (status)); gl841_stop_action (dev); /* send original registers */ gl841_bulk_write_register (dev, dev->reg, GENESYS_GL841_MAX_REGS); return status; } if (wait_until_home) { while (loop < 300) /* do not wait longer then 30 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (val & REG41_HOMESNR) /* home sensor */ { DBG (DBG_info, "gl841_slow_back_home: reached home position\n"); DBG (DBG_proc, "gl841_slow_back_home: finished\n"); return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ ++loop; } /* when we come here then the scanner needed too much time for this, so we better stop the motor */ gl841_stop_action (dev); DBG (DBG_error, "gl841_slow_back_home: timeout while waiting for scanhead to go home\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_info, "gl841_slow_back_home: scanhead is still moving\n"); DBG (DBG_proc, "gl841_slow_back_home: finished\n"); return SANE_STATUS_GOOD; } /* Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi from very top of scanner */ static SANE_Status gl841_search_start_position (Genesys_Device * dev) { int size; SANE_Status status; uint8_t *data; Genesys_Register_Set local_reg[GENESYS_GL841_MAX_REGS+1]; int steps; int pixels = 600; int dpi = 300; DBGSTART; memcpy (local_reg, dev->reg, (GENESYS_GL841_MAX_REGS +1) * sizeof (Genesys_Register_Set)); /* sets for a 200 lines * 600 pixels */ /* normal scan with no shading */ status = gl841_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0,/*we should give a small offset here~60 steps*/ 600, dev->model->search_lines, 8, 1, 1,/*green*/ SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE); if(status!=SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to init scan registers: %s\n", __func__, sane_strstatus (status)); return status; } /* send to scanner */ status = gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __func__, sane_strstatus (status)); return status; } size = pixels * dev->model->search_lines; data = malloc (size); if (!data) { DBG (DBG_error, "gl841_search_start_position: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } status = gl841_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_start_position: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, pixels, dev->model->search_lines); status = gl841_end_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_start_position: failed to end scan: %s\n", sane_strstatus (status)); return status; } /* update regs to copy ASIC internal state */ memcpy (dev->reg, local_reg, (GENESYS_GL841_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); /*TODO: find out where sanei_genesys_search_reference_point stores information, and use that correctly*/ status = sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels, dev->model->search_lines); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_start_position: failed to set search reference point: %s\n", sane_strstatus (status)); return status; } free (data); return SANE_STATUS_GOOD; } /* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status gl841_init_regs_for_coarse_calibration (Genesys_Device * dev) { SANE_Status status; uint8_t channels; uint8_t cksel; DBGSTART; cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */ /* set line size */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; status = gl841_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, dev->sensor.optical_res / cksel, /* XXX STEF XXX !!! */ 20, 16, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE ); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_init_register_for_coarse_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl841_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n", dev->sensor.optical_res / cksel, dev->settings.xres); status = gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_init_register_for_coarse_calibration: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } /* if (DBG_LEVEL >= DBG_info) sanei_gl841_print_registers (dev->calib_reg);*/ DBGCOMPLETED; return SANE_STATUS_GOOD; } /* init registers for shading calibration */ static SANE_Status gl841_init_regs_for_shading (Genesys_Device * dev) { SANE_Status status; SANE_Int ydpi; float starty=0; DBGSTART; DBG (DBG_proc, "%s: lines = %d\n", __func__, (int)(dev->calib_lines)); /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL841_MAX_REGS * sizeof (Genesys_Register_Set)); ydpi = dev->motor.base_ydpi; if (dev->model->motor_type == MOTOR_PLUSTEK_3600) /* TODO PLUSTEK_3600: 1200dpi not yet working, produces dark bar */ { ydpi = 600; } if (dev->model->motor_type == MOTOR_CANONLIDE80) { ydpi = gl841_get_dpihw(dev); /* get over extra dark area for this model */ starty = 140; } dev->calib_channels = 3; dev->calib_lines = dev->model->shading_lines; status = gl841_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, ydpi, 0, starty, (dev->sensor.sensor_pixels * dev->settings.xres) / dev->sensor.optical_res, dev->calib_lines, 16, dev->calib_channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_USE_OPTICAL_RES | /*SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE |*/ SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } dev->calib_pixels = dev->current_setup.pixels; dev->scanhead_position_in_steps += dev->calib_lines + starty; status = gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __func__, sane_strstatus (status)); return status; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /* set up registers for the actual scan */ static SANE_Status gl841_init_regs_for_scan (Genesys_Device * dev) { int channels; int flags; int depth; float move; int move_dpi; float start; SANE_Status status; DBG (DBG_info, "gl841_init_regs_for_scan settings:\nResolution: %uDPI\n" "Lines : %u\nPPL : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n", dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); gl841_slow_back_home(dev,SANE_TRUE); /* channels */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == SCAN_MODE_LINEART) depth = 1; /* steps to move to reach scanning area: - first we move to physical start of scanning either by a fixed steps amount from the black strip or by a fixed amount from parking position, minus the steps done during shading calibration - then we move by the needed offset whitin physical scanning area assumption: steps are expressed at maximum motor resolution we need: SANE_Fixed y_offset; SANE_Fixed y_size; SANE_Fixed y_offset_calib; mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */ /* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is relative from origin, else, it is from parking position */ move_dpi = dev->motor.base_ydpi; move = 0; if (dev->model->flags & GENESYS_FLAG_SEARCH_START) { move += SANE_UNFIX (dev->model->y_offset_calib); } DBG (DBG_info, "gl841_init_regs_for_scan: move=%f steps\n", move); move += SANE_UNFIX (dev->model->y_offset); DBG (DBG_info, "gl841_init_regs_for_scan: move=%f steps\n", move); move += dev->settings.tl_y; DBG (DBG_info, "gl841_init_regs_for_scan: move=%f steps\n", move); move = (move * move_dpi) / MM_PER_INCH; /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; flags=0; /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ flags = 0; /* true gray (led add for cis scanners) */ if(dev->model->is_cis && dev->settings.true_gray && dev->settings.scan_mode != SCAN_MODE_COLOR) { DBG (DBG_io, "%s: activating LEDADD\n", __func__); flags |= SCAN_FLAG_ENABLE_LEDADD; } /* enable emulated lineart from gray data */ if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; } status = gl841_init_scan_regs (dev, dev->reg, dev->settings.xres, dev->settings.yres, start, move, dev->settings.pixels, dev->settings.lines, depth, channels, dev->settings.color_filter, flags); if (status != SANE_STATUS_GOOD) return status; DBG (DBG_proc, "gl841_init_register_for_scan: completed\n"); return SANE_STATUS_GOOD; } /* * this function sends generic gamma table (ie linear ones) * or the Sensor specific one if provided */ static SANE_Status gl841_send_gamma_table (Genesys_Device * dev) { int size; SANE_Status status; uint8_t *gamma; DBGSTART; size = 256; /* allocate temporary gamma tables: 16 bits words, 3 channels */ gamma = (uint8_t *) malloc (size * 2 * 3); if (gamma==NULL) { return SANE_STATUS_NO_MEM; } RIE(sanei_genesys_generate_gamma_buffer(dev, 16, 65535, size, gamma)); /* send address */ status = gl841_set_buffer_address_gamma (dev, 0x00000); if (status != SANE_STATUS_GOOD) { free (gamma); DBG (DBG_error, "gl841_send_gamma_table: failed to set buffer address: %s\n", sane_strstatus (status)); return status; } /* send data */ status = gl841_bulk_write_data_gamma (dev, 0x28, (uint8_t *) gamma, size * 2 * 3); if (status != SANE_STATUS_GOOD) { free (gamma); DBG (DBG_error, "gl841_send_gamma_table: failed to send gamma table: %s\n", sane_strstatus (status)); return status; } free (gamma); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* this function does the led calibration by scanning one line of the calibration area below scanner's top on white strip. -needs working coarse/gain */ GENESYS_STATIC SANE_Status gl841_led_calibration (Genesys_Device * dev) { int num_pixels; int total_size; uint8_t *line; int i, j; SANE_Status status = SANE_STATUS_GOOD; int val; int channels; int avg[3], avga, avge; int turn; char fn[20]; uint16_t exp[3], target; Genesys_Register_Set *r; int move; SANE_Bool acceptable = SANE_FALSE; /* these 2 boundaries should be per sensor */ uint16_t min_exposure=500; uint16_t max_exposure; DBGSTART; /* feed to white strip if needed */ if (dev->model->y_offset_calib>0) { move = SANE_UNFIX (dev->model->y_offset_calib); move = (move * (dev->motor.base_ydpi)) / MM_PER_INCH; DBG (DBG_io, "%s: move=%d lines\n", __func__, move); status = gl841_feed(dev, move); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to feed: %s\n", __func__, sane_strstatus (status)); return status; } } /* offset calibration is always done in color mode */ channels = 3; status = gl841_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, (dev->sensor.sensor_pixels*dev->settings.xres) / dev->sensor.optical_res, 1, 16, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_USE_OPTICAL_RES ); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } RIE (gl841_bulk_write_register(dev, dev->calib_reg, GENESYS_GL841_MAX_REGS)); num_pixels = dev->current_setup.pixels; total_size = num_pixels * channels * 2 * 1; /* colors * bytes_per_color * scan lines */ line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; /* we try to get equal bright leds here: loop: average per color adjust exposure times */ exp[0] = (dev->sensor.regs_0x10_0x1d[0] << 8) | dev->sensor.regs_0x10_0x1d[1]; exp[1] = (dev->sensor.regs_0x10_0x1d[2] << 8) | dev->sensor.regs_0x10_0x1d[3]; exp[2] = (dev->sensor.regs_0x10_0x1d[4] << 8) | dev->sensor.regs_0x10_0x1d[5]; turn = 0; /* max exposure is set to ~2 time initial average * exposure, or 2 time last calibration exposure */ max_exposure=((exp[0]+exp[1]+exp[2])/3)*2; target=dev->sensor.gain_white_ref*256; do { dev->sensor.regs_0x10_0x1d[0] = (exp[0] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[1] = exp[0] & 0xff; dev->sensor.regs_0x10_0x1d[2] = (exp[1] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[3] = exp[1] & 0xff; dev->sensor.regs_0x10_0x1d[4] = (exp[2] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[5] = exp[2] & 0xff; r = &(dev->calib_reg[reg_0x10]); for (i = 0; i < 6; i++, r++) { r->value = dev->sensor.regs_0x10_0x1d[i]; RIE (sanei_genesys_write_register (dev, 0x10+i, dev->sensor.regs_0x10_0x1d[i])); } RIE (gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS)); DBG (DBG_info, "%s: starting line reading\n", __func__); RIE (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE)); RIE (sanei_genesys_read_data_from_scanner (dev, line, total_size)); if (DBG_LEVEL >= DBG_data) { snprintf(fn,20,"led_%d.pnm",turn); sanei_genesys_write_pnm_file (fn, line, 16, channels, num_pixels, 1); } /* compute average */ for (j = 0; j < channels; j++) { avg[j] = 0; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * num_pixels + 1] * 256 + line[i * 2 + j * 2 * num_pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; avg[j] += val; } avg[j] /= num_pixels; } DBG(DBG_info,"%s: average: %d,%d,%d\n", __func__, avg[0], avg[1], avg[2]); acceptable = SANE_TRUE; /* exposure is acceptable if each color is in the %5 range * of other color channels */ if (avg[0] < avg[1] * 0.95 || avg[1] < avg[0] * 0.95 || avg[0] < avg[2] * 0.95 || avg[2] < avg[0] * 0.95 || avg[1] < avg[2] * 0.95 || avg[2] < avg[1] * 0.95) { acceptable = SANE_FALSE; } /* led exposure is not acceptable if white level is too low * ~80 hardcoded value for white level */ if(avg[0]<20000 || avg[1]<20000 || avg[2]<20000) { acceptable = SANE_FALSE; } /* for scanners using target value */ if(target>0) { acceptable = SANE_TRUE; for(i=0;i<3;i++) { /* we accept +- 2% delta from target */ if(abs(avg[i]-target)>target/50) { exp[i]=(exp[i]*target)/avg[i]; acceptable = SANE_FALSE; } } } else { if (!acceptable) { avga = (avg[0]+avg[1]+avg[2])/3; exp[0] = (exp[0] * avga) / avg[0]; exp[1] = (exp[1] * avga) / avg[1]; exp[2] = (exp[2] * avga) / avg[2]; /* keep the resulting exposures below this value. too long exposure drives the ccd into saturation. we may fix this by relying on the fact that we get a striped scan without shading, by means of statistical calculation */ avge = (exp[0] + exp[1] + exp[2]) / 3; if (avge > max_exposure) { exp[0] = (exp[0] * max_exposure) / avge; exp[1] = (exp[1] * max_exposure) / avge; exp[2] = (exp[2] * max_exposure) / avge; } if (avge < min_exposure) { exp[0] = (exp[0] * min_exposure) / avge; exp[1] = (exp[1] * min_exposure) / avge; exp[2] = (exp[2] * min_exposure) / avge; } } } RIE (gl841_stop_action (dev)); turn++; } while (!acceptable && turn < 100); DBG(DBG_info,"%s: acceptable exposure: %d,%d,%d\n", __func__, exp[0],exp[1],exp[2]); /* cleanup before return */ free (line); gl841_slow_back_home(dev, SANE_TRUE); DBGCOMPLETED; return status; } /** @brief calibration for AD frontend devices * offset calibration assumes that the scanning head is on a black area * For LiDE80 analog frontend * 0x0003 : is gain and belongs to [0..63] * 0x0006 : is offset * We scan a line with no gain until average offset reaches the target */ static SANE_Status ad_fe_offset_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; int num_pixels; int total_size; uint8_t *line; int i; int average; int turn; char fn[20]; int top; int bottom; int target; DBGSTART; /* don't impact 3600 behavior since we can't test it */ if (dev->model->ccd_type == CCD_PLUSTEK_3600) { DBGCOMPLETED; return status; } status = gl841_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, (dev->sensor.sensor_pixels*dev->settings.xres) / dev->sensor.optical_res, 1, 8, 3, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_USE_OPTICAL_RES); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_offset_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } num_pixels = dev->current_setup.pixels; total_size = num_pixels * 3 * 2 * 1; line = malloc (total_size); if (line==NULL) { DBGCOMPLETED; return SANE_STATUS_NO_MEM; } dev->frontend.gain[0] = 0x00; dev->frontend.gain[1] = 0x00; dev->frontend.gain[2] = 0x00; /* loop on scan until target offset is reached */ turn=0; target=24; bottom=0; top=255; do { /* set up offset mid range */ dev->frontend.offset[0] = (top+bottom)/2; dev->frontend.offset[1] = (top+bottom)/2; dev->frontend.offset[2] = (top+bottom)/2; /* scan line */ DBG (DBG_info, "%s: starting line reading\n",__func__); gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS); gl841_set_fe(dev, AFE_SET); gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE); sanei_genesys_read_data_from_scanner (dev, line, total_size); gl841_stop_action (dev); if (DBG_LEVEL >= DBG_data) { snprintf(fn,20,"offset_%02d.pnm",turn); sanei_genesys_write_pnm_file (fn, line, 8, 3, num_pixels, 1); } /* search for minimal value */ average=0; for(i=0;itarget) { top=(top+bottom)/2; } else { bottom=(top+bottom)/2; } turn++; } while ((top-bottom)>1 && turn < 100); dev->frontend.offset[0]=0; dev->frontend.offset[1]=0; dev->frontend.offset[2]=0; free(line); DBG (DBG_info, "%s: offset=(%d,%d,%d)\n", __func__, dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); DBGCOMPLETED; return status; } /* this function does the offset calibration by scanning one line of the calibration area below scanner's top. There is a black margin and the remaining is white. sanei_genesys_search_start() must have been called so that the offsets and margins are allready known. this function expects the slider to be where? */ GENESYS_STATIC SANE_Status gl841_offset_calibration (Genesys_Device * dev) { int num_pixels; int total_size; uint8_t *first_line, *second_line; int i, j; SANE_Status status = SANE_STATUS_GOOD; int val; int channels; int off[3],offh[3],offl[3],off1[3],off2[3]; int min1[3],min2[3]; int cmin[3],cmax[3]; int turn; char fn[20]; SANE_Bool acceptable = SANE_FALSE; int mintgt = 0x400; DBG (DBG_proc, "gl841_offset_calibration\n"); /* Analog Device fronted have a different calibration */ if ((dev->reg[reg_0x04].value & REG04_FESET) == 0x02) { return ad_fe_offset_calibration (dev); } /* offset calibration is always done in color mode */ channels = 3; status = gl841_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, (dev->sensor.sensor_pixels*dev->settings.xres) / dev->sensor.optical_res, 1, 16, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_USE_OPTICAL_RES | SCAN_FLAG_DISABLE_LAMP ); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_offset_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } num_pixels = dev->current_setup.pixels; total_size = num_pixels * channels * 2 * 1; /* colors * bytes_per_color * scan lines */ first_line = malloc (total_size); if (!first_line) return SANE_STATUS_NO_MEM; second_line = malloc (total_size); if (!second_line) { free (first_line); return SANE_STATUS_NO_MEM; } /* scan first line of data with no offset nor gain */ /*WM8199: gain=0.73; offset=-260mV*/ /*okay. the sensor black level is now at -260mV. we only get 0 from AFE...*/ /* we should probably do real calibration here: * -detect acceptable offset with binary search * -calculate offset from this last version * * acceptable offset means * - few completely black pixels(<10%?) * - few completely white pixels(<10%?) * * final offset should map the minimum not completely black * pixel to 0(16 bits) * * this does account for dummy pixels at the end of ccd * this assumes slider is at black strip(which is not quite as black as "no * signal"). * */ dev->frontend.gain[0] = 0x00; dev->frontend.gain[1] = 0x00; dev->frontend.gain[2] = 0x00; offh[0] = 0xff; offh[1] = 0xff; offh[2] = 0xff; offl[0] = 0x00; offl[1] = 0x00; offl[2] = 0x00; turn = 0; do { RIEF2 (gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS), first_line, second_line); for (j=0; j < channels; j++) { off[j] = (offh[j]+offl[j])/2; dev->frontend.offset[j] = off[j]; } status = gl841_set_fe(dev, AFE_SET); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_offset_calibration: failed to setup frontend: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl841_offset_calibration: starting first line reading\n"); RIEF2 (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size), first_line, second_line); if (DBG_LEVEL >= DBG_data) { snprintf(fn,20,"offset1_%02d.pnm",turn); sanei_genesys_write_pnm_file (fn, first_line, 16, channels, num_pixels, 1); } acceptable = SANE_TRUE; for (j = 0; j < channels; j++) { cmin[j] = 0; cmax[j] = 0; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = first_line[i * 2 + j * 2 * num_pixels + 1] * 256 + first_line[i * 2 + j * 2 * num_pixels]; else val = first_line[i * 2 * channels + 2 * j + 1] * 256 + first_line[i * 2 * channels + 2 * j]; if (val < 10) cmin[j]++; if (val > 65525) cmax[j]++; } /* TODO the DP685 has a black strip in the middle of the sensor * should be handled in a more elegant way , could be a bug */ if (dev->model->ccd_type == CCD_DP685) cmin[j] -= 20; if (cmin[j] > num_pixels/100) { acceptable = SANE_FALSE; if (dev->model->is_cis) offl[0] = off[0]; else offl[j] = off[j]; } if (cmax[j] > num_pixels/100) { acceptable = SANE_FALSE; if (dev->model->is_cis) offh[0] = off[0]; else offh[j] = off[j]; } } DBG(DBG_info,"gl841_offset_calibration: black/white pixels: " "%d/%d,%d/%d,%d/%d\n", cmin[0],cmax[0],cmin[1],cmax[1],cmin[2],cmax[2]); if (dev->model->is_cis) { offh[2] = offh[1] = offh[0]; offl[2] = offl[1] = offl[0]; } RIEF2 (gl841_stop_action (dev), first_line, second_line); turn++; } while (!acceptable && turn < 100); DBG(DBG_info,"gl841_offset_calibration: acceptable offsets: %d,%d,%d\n", off[0],off[1],off[2]); for (j = 0; j < channels; j++) { off1[j] = off[j]; min1[j] = 65536; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = first_line[i * 2 + j * 2 * num_pixels + 1] * 256 + first_line[i * 2 + j * 2 * num_pixels]; else val = first_line[i * 2 * channels + 2 * j + 1] * 256 + first_line[i * 2 * channels + 2 * j]; if (min1[j] > val && val >= 10) min1[j] = val; } } offl[0] = off[0]; offl[1] = off[0]; offl[2] = off[0]; turn = 0; do { for (j=0; j < channels; j++) { off[j] = (offh[j]+offl[j])/2; dev->frontend.offset[j] = off[j]; } status = gl841_set_fe(dev, AFE_SET); if (status != SANE_STATUS_GOOD) { free (first_line); free (second_line); DBG (DBG_error, "gl841_offset_calibration: failed to setup frontend: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl841_offset_calibration: starting second line reading\n"); RIEF2 (gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS), first_line, second_line); RIEF2 (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); if (DBG_LEVEL >= DBG_data) { snprintf(fn,20,"offset2_%02d.pnm",turn); sanei_genesys_write_pnm_file (fn, second_line, 16, channels, num_pixels, 1); } acceptable = SANE_TRUE; for (j = 0; j < channels; j++) { cmin[j] = 0; cmax[j] = 0; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = second_line[i * 2 + j * 2 * num_pixels + 1] * 256 + second_line[i * 2 + j * 2 * num_pixels]; else val = second_line[i * 2 * channels + 2 * j + 1] * 256 + second_line[i * 2 * channels + 2 * j]; if (val < 10) cmin[j]++; if (val > 65525) cmax[j]++; } if (cmin[j] > num_pixels/100) { acceptable = SANE_FALSE; if (dev->model->is_cis) offl[0] = off[0]; else offl[j] = off[j]; } if (cmax[j] > num_pixels/100) { acceptable = SANE_FALSE; if (dev->model->is_cis) offh[0] = off[0]; else offh[j] = off[j]; } } DBG(DBG_info,"gl841_offset_calibration: black/white pixels: " "%d/%d,%d/%d,%d/%d\n", cmin[0],cmax[0],cmin[1],cmax[1],cmin[2],cmax[2]); if (dev->model->is_cis) { offh[2] = offh[1] = offh[0]; offl[2] = offl[1] = offl[0]; } RIEF2 (gl841_stop_action (dev), first_line, second_line); turn++; } while (!acceptable && turn < 100); DBG(DBG_info,"gl841_offset_calibration: acceptable offsets: %d,%d,%d\n", off[0],off[1],off[2]); for (j = 0; j < channels; j++) { off2[j] = off[j]; min2[j] = 65536; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = second_line[i * 2 + j * 2 * num_pixels + 1] * 256 + second_line[i * 2 + j * 2 * num_pixels]; else val = second_line[i * 2 * channels + 2 * j + 1] * 256 + second_line[i * 2 * channels + 2 * j]; if (min2[j] > val && val != 0) min2[j] = val; } } DBG(DBG_info,"gl841_offset_calibration: first set: %d/%d,%d/%d,%d/%d\n", off1[0],min1[0],off1[1],min1[1],off1[2],min1[2]); DBG(DBG_info,"gl841_offset_calibration: second set: %d/%d,%d/%d,%d/%d\n", off2[0],min2[0],off2[1],min2[1],off2[2],min2[2]); /* calculate offset for each channel based on minimal pixel value min1 at offset off1 and minimal pixel value min2 at offset off2 to get min at off, values are linearly interpolated: min=real+off*fact min1=real+off1*fact min2=real+off2*fact fact=(min1-min2)/(off1-off2) real=min1-off1*(min1-min2)/(off1-off2) off=(min-min1+off1*(min1-min2)/(off1-off2))/((min1-min2)/(off1-off2)) off=(min*(off1-off2)+min1*off2-off1*min2)/(min1-min2) */ for (j = 0; j < channels; j++) { if (min2[j]-min1[j] == 0) { /*TODO: try to avoid this*/ DBG(DBG_warn,"gl841_offset_calibration: difference too small\n"); if (mintgt * (off1[j] - off2[j]) + min1[j] * off2[j] - min2[j] * off1[j] >= 0) off[j] = 0x0000; else off[j] = 0xffff; } else off[j] = (mintgt * (off1[j] - off2[j]) + min1[j] * off2[j] - min2[j] * off1[j])/(min1[j]-min2[j]); if (off[j] > 255) off[j] = 255; if (off[j] < 0) off[j] = 0; dev->frontend.offset[j] = off[j]; } DBG(DBG_info,"gl841_offset_calibration: final offsets: %d,%d,%d\n", off[0],off[1],off[2]); if (dev->model->is_cis) { if (off[0] < off[1]) off[0] = off[1]; if (off[0] < off[2]) off[0] = off[2]; dev->frontend.offset[0] = off[0]; dev->frontend.offset[1] = off[0]; dev->frontend.offset[2] = off[0]; } if (channels == 1) { dev->frontend.offset[1] = dev->frontend.offset[0]; dev->frontend.offset[2] = dev->frontend.offset[0]; } /* cleanup before return */ free (first_line); free (second_line); DBG (DBG_proc, "gl841_offset_calibration: completed\n"); return status; } /* alternative coarse gain calibration this on uses the settings from offset_calibration and uses only one scanline */ /* with offset and coarse calibration we only want to get our input range into a reasonable shape. the fine calibration of the upper and lower bounds will be done with shading. */ GENESYS_STATIC SANE_Status gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi) { int num_pixels; int total_size; uint8_t *line; int i, j, channels; SANE_Status status = SANE_STATUS_GOOD; int max[3]; float gain[3]; int val; int lines=1; int move; DBG (DBG_proc, "%s: dpi=%d\n", __func__, dpi); /* feed to white strip if needed */ if (dev->model->y_offset_calib>0) { move = SANE_UNFIX (dev->model->y_offset_calib); move = (move * (dev->motor.base_ydpi)) / MM_PER_INCH; DBG (DBG_io, "%s: move=%d lines\n", __func__, move); status = gl841_feed(dev, move); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to feed: %s\n", __func__, sane_strstatus (status)); return status; } } /* coarse gain calibration is allways done in color mode */ channels = 3; status = gl841_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, (dev->sensor.sensor_pixels*dev->settings.xres) / dev->sensor.optical_res, lines, 16, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_USE_OPTICAL_RES ); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } RIE (gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS)); num_pixels = dev->current_setup.pixels; total_size = num_pixels * channels * 2 * lines; /* colors * bytes_per_color * scan lines */ line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; RIEF (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("coarse.pnm", line, 16, channels, num_pixels, lines); /* average high level for each channel and compute gain to reach the target code we only use the central half of the CCD data */ for (j = 0; j < channels; j++) { max[j] = 0; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * num_pixels + 1] * 256 + line[i * 2 + j * 2 * num_pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; if (val > max[j]) max[j] = val; } gain[j] = 65535.0/max[j]; if (dev->model->dac_type == DAC_CANONLIDE35 || dev->model->dac_type == DAC_WOLFSON_XP300 || dev->model->dac_type == DAC_WOLFSON_DSM600) { gain[j] *= 0.69;/*seems we don't get the real maximum. empirically derived*/ if (283 - 208/gain[j] > 255) dev->frontend.gain[j] = 255; else if (283 - 208/gain[j] < 0) dev->frontend.gain[j] = 0; else dev->frontend.gain[j] = 283 - 208/gain[j]; } else if (dev->model->dac_type == DAC_CANONLIDE80) { dev->frontend.gain[j] = gain[j]*12; } DBG (DBG_proc, "%s: channel %d, max=%d, gain = %f, setting:%d\n", __func__, j, max[j], gain[j],dev->frontend.gain[j]); } for (j = 0; j < channels; j++) { if(gain[j] > 10) { DBG (DBG_error0, "**********************************************\n"); DBG (DBG_error0, "**********************************************\n"); DBG (DBG_error0, "**** ****\n"); DBG (DBG_error0, "**** Extremely low Brightness detected. ****\n"); DBG (DBG_error0, "**** Check the scanning head is ****\n"); DBG (DBG_error0, "**** unlocked and moving. ****\n"); DBG (DBG_error0, "**** ****\n"); DBG (DBG_error0, "**********************************************\n"); DBG (DBG_error0, "**********************************************\n"); #ifdef SANE_STATUS_HW_LOCKED return SANE_STATUS_HW_LOCKED; #else return SANE_STATUS_JAMMED; #endif } } if (dev->model->is_cis) { if (dev->frontend.gain[0] > dev->frontend.gain[1]) dev->frontend.gain[0] = dev->frontend.gain[1]; if (dev->frontend.gain[0] > dev->frontend.gain[2]) dev->frontend.gain[0] = dev->frontend.gain[2]; dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0]; } if (channels == 1) { dev->frontend.gain[0] = dev->frontend.gain[1]; dev->frontend.gain[2] = dev->frontend.gain[1]; } free (line); DBG (DBG_info, "%s: gain=(%d,%d,%d)\n", __func__, dev->frontend.gain[0], dev->frontend.gain[1], dev->frontend.gain[2]); RIE (gl841_stop_action (dev)); gl841_slow_back_home(dev, SANE_TRUE); DBGCOMPLETED; return status; } /* * wait for lamp warmup by scanning the same line until difference * between 2 scans is below a threshold */ static SANE_Status gl841_init_regs_for_warmup (Genesys_Device * dev, Genesys_Register_Set * local_reg, int *channels, int *total_size) { int num_pixels = (int) (4 * 300); SANE_Status status = SANE_STATUS_GOOD; DBG (DBG_proc, "sanei_gl841_warmup_lamp\n"); memcpy (local_reg, dev->reg, (GENESYS_GL841_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); /* okay.. these should be defaults stored somewhere */ dev->frontend.gain[0] = 0x00; dev->frontend.gain[1] = 0x00; dev->frontend.gain[2] = 0x00; dev->frontend.offset[0] = 0x80; dev->frontend.offset[1] = 0x80; dev->frontend.offset[2] = 0x80; status = gl841_init_scan_regs (dev, local_reg, dev->sensor.optical_res, dev->settings.yres, dev->sensor.dummy_pixel, 0, num_pixels, 1, 16, *channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_USE_OPTICAL_RES ); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_init_regs_for_warmup: failed to setup scan: %s\n", sane_strstatus (status)); return status; } num_pixels = dev->current_setup.pixels; *total_size = num_pixels * 3 * 2 * 1; /* colors * bytes_per_color * scan lines */ RIE (gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS)); return status; } /* * this function moves head without scanning, forward, then backward * so that the head goes to park position. * as a by-product, also check for lock */ #ifndef UNIT_TESTING static #endif SANE_Status sanei_gl841_repark_head (Genesys_Device * dev) { SANE_Status status; DBG (DBG_proc, "sanei_gl841_repark_head\n"); status = gl841_feed(dev,232); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_repark_head: failed to feed: %s\n", sane_strstatus (status)); return status; } /* toggle motor flag, put an huge step number and redo move backward */ status = gl841_slow_back_home (dev, SANE_TRUE); DBG (DBG_proc, "gl841_park_head: completed\n"); return status; } static SANE_Status gl841_is_compatible_calibration (Genesys_Device * dev, Genesys_Calibration_Cache *cache, int for_overwrite) { SANE_Status status; #ifdef HAVE_SYS_TIME_H struct timeval time; #endif DBGSTART; /* calibration cache not working yet for this model */ if (dev->model->ccd_type == CCD_PLUSTEK_3600) { return SANE_STATUS_UNSUPPORTED; } status = gl841_calculate_current_setup (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_is_compatible_calibration: failed to calculate current setup: %s\n", sane_strstatus (status)); return status; } DBG (DBG_proc, "gl841_is_compatible_calibration: checking\n"); if (dev->current_setup.half_ccd != cache->used_setup.half_ccd) return SANE_STATUS_UNSUPPORTED; /* a cache entry expires after 30 minutes for non sheetfed scanners */ /* this is not taken into account when overwriting cache entries */ #ifdef HAVE_SYS_TIME_H if(for_overwrite == SANE_FALSE) { gettimeofday (&time, NULL); if ((time.tv_sec - cache->last_calibration > 30 * 60) && (dev->model->is_sheetfed == SANE_FALSE)) { DBG (DBG_proc, "%s: expired entry, non compatible cache\n",__func__); return SANE_STATUS_UNSUPPORTED; } } #endif DBGCOMPLETED; return SANE_STATUS_GOOD; } /* * initialize ASIC : registers, motor tables, and gamma tables * then ensure scanner's head is at home */ static SANE_Status gl841_init (Genesys_Device * dev) { SANE_Status status; uint8_t val; size_t size; uint8_t *line; int i; DBG_INIT (); DBGSTART; dev->scanhead_position_in_steps = 0; /* Check if the device has already been initialized and powered up */ if (dev->already_initialized) { RIE (sanei_genesys_get_status (dev, &val)); if (val & REG41_PWRBIT) { DBG (DBG_info, "gl841_init: already initialized\n"); DBGCOMPLETED; return SANE_STATUS_GOOD; } } dev->dark_average_data = NULL; dev->white_average_data = NULL; dev->settings.color_filter = 0; /* ASIC reset */ RIE (sanei_genesys_write_register (dev, 0x0e, 0x01)); RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); /* Set default values for registers */ gl841_init_registers (dev); /* Write initial registers */ RIE (gl841_bulk_write_register (dev, dev->reg, GENESYS_GL841_MAX_REGS)); /* Test ASIC and RAM */ if (!(dev->model->flags & GENESYS_FLAG_LAZY_INIT)) { RIE (sanei_gl841_asic_test (dev)); } /* Set analog frontend */ RIE (gl841_set_fe (dev, AFE_INIT)); /* Move home */ RIE (gl841_slow_back_home (dev, SANE_TRUE)); /* Init shading data */ RIE (sanei_genesys_init_shading_data (dev, dev->sensor.sensor_pixels)); /* ensure head is correctly parked, and check lock */ if (dev->model->flags & GENESYS_FLAG_REPARK) { status = sanei_gl841_repark_head (dev); if (status != SANE_STATUS_GOOD) { if (status == SANE_STATUS_INVAL) DBG (DBG_error0, "Your scanner is locked. Please move the lock switch " "to the unlocked position\n"); else DBG (DBG_error, "gl841_init: sanei_gl841_repark_head failed: %s\n", sane_strstatus (status)); return status; } } /* initalize sensor gamma tables */ size = 256; for(i=0;i<3;i++) { if (dev->sensor.gamma_table[i] == NULL) { dev->sensor.gamma_table[i] = (uint16_t *) malloc (2 * size); if (dev->sensor.gamma_table[i] == NULL) { DBG (DBG_error, "gl841_init: could not allocate memory for gamma table %d\n",i); return SANE_STATUS_NO_MEM; } sanei_genesys_create_gamma_table (dev->sensor.gamma_table[i], size, 65535, 65535, dev->sensor.gamma[i]); } } /* send gamma tables */ status = gl841_send_gamma_table (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_init: failed to send initial gamma tables: %s\n", sane_strstatus (status)); return status; } /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, (GENESYS_GL841_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); status = gl841_init_scan_regs (dev, dev->calib_reg, 300, 300, 0, 0, (16 * 300) / dev->sensor.optical_res, 1, 16, 3, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_USE_OPTICAL_RES ); RIE (gl841_bulk_write_register (dev, dev->calib_reg, GENESYS_GL841_MAX_REGS)); size = dev->current_setup.pixels * 3 * 2 * 1; /* colors * bytes_per_color * scan lines */ line = malloc (size); if (!line) return SANE_STATUS_NO_MEM; DBG (DBG_info, "gl841_init: starting dummy data reading\n"); RIEF (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); sanei_usb_set_timeout(1000);/* 1 second*/ /*ignore errors. next read will succeed*/ sanei_genesys_read_data_from_scanner (dev, line, size); free(line); sanei_usb_set_timeout(30 * 1000);/* 30 seconds*/ RIE (gl841_end_scan (dev, dev->calib_reg, SANE_TRUE)); memcpy (dev->calib_reg, dev->reg, (GENESYS_GL841_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); /* Set powersaving (default = 15 minutes) */ RIE (gl841_set_powersaving (dev, 15)); dev->already_initialized = SANE_TRUE; DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl841_update_hardware_sensors (Genesys_Scanner * s) { /* do what is needed to get a new set of events, but try to not lose any of them. */ SANE_Status status = SANE_STATUS_GOOD; uint8_t val; if (s->dev->model->gpo_type == GPO_CANONLIDE35 || s->dev->model->gpo_type == GPO_CANONLIDE80) { RIE(sanei_genesys_read_register(s->dev, REG6D, &val)); if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b) s->val[OPT_SCAN_SW].b = (val & 0x01) == 0; if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b) s->val[OPT_FILE_SW].b = (val & 0x02) == 0; if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b) s->val[OPT_EMAIL_SW].b = (val & 0x04) == 0; if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b) s->val[OPT_COPY_SW].b = (val & 0x08) == 0; } if (s->dev->model->gpo_type == GPO_XP300 || s->dev->model->gpo_type == GPO_DP665 || s->dev->model->gpo_type == GPO_DP685) { RIE(sanei_genesys_read_register(s->dev, REG6D, &val)); if (s->val[OPT_PAGE_LOADED_SW].b == s->last_val[OPT_PAGE_LOADED_SW].b) s->val[OPT_PAGE_LOADED_SW].b = (val & 0x01) == 0; if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b) s->val[OPT_SCAN_SW].b = (val & 0x02) == 0; } return status; } /** @brief search for a full width black or white strip. * This function searches for a black or white stripe across the scanning area. * When searching backward, the searched area must completely be of the desired * color since this area will be used for calibration which scans forward. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward * @param black SANE_TRUE if searching for a black strip, SANE_FALSE for a white strip * @return SANE_STATUS_GOOD if a matching strip is found, SANE_STATUS_UNSUPPORTED if not */ static SANE_Status gl841_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black) { unsigned int pixels, lines, channels; SANE_Status status; Genesys_Register_Set local_reg[GENESYS_GL841_MAX_REGS + 1]; size_t size; uint8_t *data; int steps, depth, dpi; unsigned int pass, count, found, x, y, length; char title[80]; Genesys_Register_Set *r; uint8_t white_level=90; /**< default white level to detect white dots */ uint8_t black_level=60; /**< default black level to detect black dots */ DBG (DBG_proc, "gl841_search_strip %s %s\n", black ? "black" : "white", forward ? "forward" : "reverse"); /* use maximum gain when doing forward white strip detection * since we don't have calibrated the sensor yet */ if(!black && forward) { dev->frontend.gain[0] = 0xff; dev->frontend.gain[1] = 0xff; dev->frontend.gain[2] = 0xff; } gl841_set_fe (dev, AFE_SET); status = gl841_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_search_strip: failed to stop: %s\n", sane_strstatus (status)); return status; } /* set up for a gray scan at lowest dpi */ dpi = 9600; for (x = 0; x < MAX_RESOLUTIONS; x++) { if (dev->model->xdpi_values[x] > 0 && dev->model->xdpi_values[x] < dpi) dpi = dev->model->xdpi_values[x]; } channels = 1; /* shading calibation is done with dev->motor.base_ydpi */ /* lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi; */ lines = (10*dpi)/MM_PER_INCH; depth = 8; pixels = (dev->sensor.sensor_pixels * dpi) / dev->sensor.optical_res; size = pixels * channels * lines * (depth / 8); data = malloc (size); if (!data) { DBG (DBG_error, "gl841_search_strip: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } /* 20 cm max length for calibration sheet */ length = ((200 * dpi) / MM_PER_INCH)/lines; dev->scanhead_position_in_steps = 0; memcpy (local_reg, dev->reg, (GENESYS_GL841_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); status = gl841_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, pixels, lines, depth, channels, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "%s: failed to setup for scan: %s\n", __func__, sane_strstatus (status)); return status; } /* set up for reverse or forward */ r = sanei_genesys_get_address (local_reg, 0x02); if (forward) r->value &= ~4; else r->value |= 4; status = gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "gl841_search_strip: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } status = gl841_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_strip: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } status = gl841_stop_action (dev); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_strip: gl841_stop_action failed\n"); return status; } pass = 0; if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s_%s%02u.pnm", black ? "black" : "white", forward ? "fwd" : "bwd", pass); sanei_genesys_write_pnm_file (title, data, depth, channels, pixels, lines); } /* loop until strip is found or maximum pass number done */ found = 0; while (pass < length && !found) { status = gl841_bulk_write_register (dev, local_reg, GENESYS_GL841_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl841_search_strip: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } /* now start scan */ status = gl841_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_strip: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } status = gl841_stop_action (dev); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl841_search_strip: gl841_stop_action failed\n"); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s_%s%02u.pnm", black ? "black" : "white", forward ? "fwd" : "bwd", pass); sanei_genesys_write_pnm_file (title, data, depth, channels, pixels, lines); } /* search data to find black strip */ /* when searching forward, we only need one line of the searched color since we * will scan forward. But when doing backward search, we need all the area of the * same color */ if (forward) { for (y = 0; y < lines && !found; y++) { count = 0; /* count of white/black pixels depending on the color searched */ for (x = 0; x < pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * pixels + x] > white_level) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * pixels + x] < black_level) { count++; } } /* at end of line, if count >= 3%, line is not fully of the desired color * so we must go to next line of the buffer */ /* count*100/pixels < 3 */ if ((count * 100) / pixels < 3) { found = 1; DBG (DBG_data, "gl841_search_strip: strip found forward during pass %d at line %d\n", pass, y); } else { DBG (DBG_data, "gl841_search_strip: pixels=%d, count=%d (%d%%)\n", pixels, count, (100 * count) / pixels); } } } else /* since calibration scans are done forward, we need the whole area to be of the required color when searching backward */ { count = 0; for (y = 0; y < lines; y++) { /* count of white/black pixels depending on the color searched */ for (x = 0; x < pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * pixels + x] > white_level) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * pixels + x] < black_level) { count++; } } } /* at end of area, if count >= 3%, area is not fully of the desired color * so we must go to next buffer */ if ((count * 100) / (pixels * lines) < 3) { found = 1; DBG (DBG_data, "gl841_search_strip: strip found backward during pass %d \n", pass); } else { DBG (DBG_data, "gl841_search_strip: pixels=%d, count=%d (%d%%)\n", pixels, count, (100 * count) / pixels); } } pass++; } free (data); if (found) { status = SANE_STATUS_GOOD; DBG (DBG_info, "gl841_search_strip: %s strip found\n", black ? "black" : "white"); } else { status = SANE_STATUS_UNSUPPORTED; DBG (DBG_info, "gl841_search_strip: %s strip not found\n", black ? "black" : "white"); } DBG (DBG_proc, "gl841_search_strip: completed\n"); return status; } /** * Send shading calibration data. The buffer is considered to always hold values * for all the channels. */ GENESYS_STATIC SANE_Status gl841_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) { SANE_Status status = SANE_STATUS_GOOD; uint32_t length, x, factor, pixels, i; uint32_t half; uint32_t lines, channels; uint16_t dpiset, dpihw, strpixel ,endpixel, beginpixel; uint8_t *buffer,*ptr,*src; DBGSTART; DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__func__,size); /* old method if no SHDAREA */ if((dev->reg[reg_0x01].value & REG01_SHDAREA) == 0) { /* start address */ status = sanei_genesys_set_buffer_address (dev, 0x0000); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to set buffer address: %s\n", __func__, sane_strstatus (status)); return status; } /* shading data whole line */ status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to send shading table: %s\n", __func__, sane_strstatus (status)); return status; } DBGCOMPLETED; return status; } /* data is whole line, we extract only the part for the scanned area */ length = (uint32_t) (size / 3); sanei_genesys_get_double(dev->reg,REG_STRPIXEL,&strpixel); sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&endpixel); DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d, PIXELS=%d\n",__func__,strpixel,endpixel,endpixel-strpixel); /* compute deletion/average factor */ sanei_genesys_get_double(dev->reg,REG_DPISET,&dpiset); dpihw = gl841_get_dpihw(dev); half=dev->current_setup.half_ccd+1; factor=dpihw/dpiset; DBG( DBG_io2, "%s: dpihw=%d, dpiset=%d, half_ccd=%d, factor=%d\n",__func__,dpihw,dpiset,half-1,factor); /* binary data logging */ if(DBG_LEVEL>=DBG_data) { dev->binary=fopen("binary.pnm","wb"); sanei_genesys_get_triple(dev->reg, REG_LINCNT, &lines); channels=dev->current_setup.channels; if(dev->binary!=NULL) { fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255); } } /* turn pixel value into bytes 2x16 bits words */ strpixel*=2*2; /* 2 words of 2 bytes */ endpixel*=2*2; pixels=endpixel-strpixel; /* shading pixel begin is start pixel minus start pixel during shading * calibration. Currently only cases handled are full and half ccd resolution. */ beginpixel = dev->sensor.CCD_start_xoffset / half; beginpixel += dev->sensor.dummy_pixel + 1; DBG(DBG_io2, "%s: ORIGIN PIXEL=%d\n", __func__, beginpixel); beginpixel = (strpixel-beginpixel*2*2)/factor; DBG(DBG_io2, "%s: BEGIN PIXEL=%d\n",__func__,beginpixel/4); DBG(DBG_io2, "%s: using chunks of %d bytes (%d shading data pixels)\n",__func__,length, length/4); buffer=(uint8_t *)malloc(pixels); memset(buffer,0,pixels); /* write actual shading data contigously * channel by channel, starting at addr 0x0000 * */ for(i=0;i<3;i++) { /* copy data to work buffer and process it */ /* coefficent destination */ ptr=buffer; /* iterate on both sensor segment, data has been averaged, * so is in the right order and we only have to copy it */ for(x=0;xmodel->cmd_set->bulk_write_data (dev, 0x3c, buffer, pixels), buffer); } free(buffer); DBGCOMPLETED; return status; } /** the gl841 command set */ static Genesys_Command_Set gl841_cmd_set = { "gl841-generic", /* the name of this set */ gl841_init, gl841_init_regs_for_warmup, gl841_init_regs_for_coarse_calibration, gl841_init_regs_for_shading, gl841_init_regs_for_scan, gl841_get_filter_bit, gl841_get_lineart_bit, gl841_get_bitset_bit, gl841_get_gain4_bit, gl841_get_fast_feed_bit, gl841_test_buffer_empty_bit, gl841_test_motor_flag_bit, gl841_bulk_full_size, gl841_set_fe, gl841_set_powersaving, gl841_save_power, gl841_set_motor_power, gl841_set_lamp_power, gl841_begin_scan, gl841_end_scan, gl841_send_gamma_table, gl841_search_start_position, gl841_offset_calibration, gl841_coarse_gain_calibration, gl841_led_calibration, gl841_slow_back_home, NULL, gl841_bulk_write_register, gl841_bulk_write_data, gl841_bulk_read_data, gl841_update_hardware_sensors, gl841_load_document, gl841_detect_document_end, gl841_eject_document, gl841_search_strip, gl841_is_compatible_calibration, NULL, gl841_send_shading_data, gl841_calculate_current_setup, NULL, NULL }; SANE_Status sanei_gl841_init_cmd_set (Genesys_Device * dev) { dev->model->cmd_set = &gl841_cmd_set; return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/hp3900_usb.c0000664000175000017500000003237312112021330014542 00000000000000/* HP Scanjet 3900 series - USB layer Copyright (C) 2005-2008 Jonathan Bravo Lopez This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef USBLAYER #define USBLAYER #define TIMEOUT 1000 #define BLK_READ_EP 0x81 #define BLK_WRITE_EP 0x02 SANE_Int dataline_count = 0; /* USB layer commands */ static SANE_Int usb_ctl_write (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size, SANE_Int index); static SANE_Int usb_ctl_read (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size, SANE_Int index); /* Higher level commands*/ static SANE_Int IRead_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data, SANE_Int index); static SANE_Int IRead_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int * data, SANE_Int index); static SANE_Int IRead_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int * data, SANE_Int index); static SANE_Int IRead_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size, SANE_Int index); static SANE_Int IWrite_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data, SANE_Int index1, SANE_Int index2); static SANE_Int IWrite_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int data, SANE_Int index); static SANE_Int IWrite_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int data, SANE_Int index); static SANE_Int IWrite_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size, SANE_Int index); static SANE_Int Read_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data); static SANE_Int Read_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int * data); static SANE_Int Read_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int * data); static SANE_Int Read_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size); static SANE_Int Read_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, size_t size); static SANE_Int Write_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data); static SANE_Int Write_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int data); /*static SANE_Int Write_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int data);*/ static SANE_Int Write_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size); static SANE_Int Write_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, SANE_Int size); static SANE_Int show_buffer (SANE_Int level, SANE_Byte * buffer, SANE_Int size); /* Implementation */ static SANE_Int IWrite_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data, SANE_Int index1, SANE_Int index2) { SANE_Int rst = ERROR; SANE_Byte buffer[2] = { 0x00, 0x00 }; if (usb_ctl_read (usb_handle, address + 1, buffer, 0x02, index1) == 2) { buffer[1] = (buffer[0] & 0xff); buffer[0] = (data & 0xff); if (usb_ctl_write (usb_handle, address, buffer, 0x02, index2) == 2) rst = OK; } return rst; } static SANE_Int IWrite_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int data, SANE_Int index) { SANE_Int rst = ERROR; SANE_Byte buffer[2]; buffer[0] = (data & 0xff); buffer[1] = ((data >> 8) & 0xff); if (usb_ctl_write (usb_handle, address, buffer, 0x02, index) == 2) rst = OK; return rst; } static SANE_Int IWrite_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int data, SANE_Int index) { SANE_Int rst = ERROR; SANE_Byte buffer[4]; buffer[0] = (data & 0xff); buffer[1] = ((data >> 8) & 0xff); buffer[2] = ((data >> 16) & 0xff); buffer[3] = ((data >> 24) & 0xff); if (usb_ctl_write (usb_handle, address, buffer, 0x04, index) == 4) rst = OK; return rst; } static SANE_Int IWrite_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size, SANE_Int index) { SANE_Int ret = ERROR; if (!((buffer == NULL) && (size > 0))) if (usb_ctl_write (usb_handle, address, buffer, size, index) == size) ret = OK; return ret; } static SANE_Int IRead_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data, SANE_Int index) { SANE_Byte buffer[2] = { 0x00, 0x00 }; SANE_Int ret = ERROR; if (data != NULL) if (usb_ctl_read (usb_handle, address, buffer, 0x02, index) == 2) { *data = (SANE_Byte) (buffer[0] & 0xff); ret = OK; } return ret; } static SANE_Int IRead_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int * data, SANE_Int index) { SANE_Byte buffer[2] = { 0x00, 0x00 }; SANE_Int ret = ERROR; if (data != NULL) if (usb_ctl_read (usb_handle, address, buffer, 0x02, index) == 2) { *data = ((buffer[1] << 8) & 0xffff) + (buffer[0] & 0xff); ret = OK; } return ret; } static SANE_Int IRead_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int * data, SANE_Int index) { SANE_Byte buffer[4] = { 0x00, 0x00, 0x00, 0x00 }; SANE_Int ret = ERROR; if (data != NULL) { *data = 0; if (usb_ctl_read (usb_handle, address, buffer, 0x04, index) == 4) { SANE_Int C; for (C = 3; C >= 0; C--) *data = ((*data << 8) + (buffer[C] & 0xff)) & 0xffffffff; ret = OK; } } return ret; } static SANE_Int IRead_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size, SANE_Int index) { SANE_Int ret = ERROR; if (buffer != NULL) if (usb_ctl_read (usb_handle, address, buffer, size, index) == size) ret = OK; return ret; } static SANE_Int Write_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data) { return IWrite_Byte (usb_handle, address, data, 0x100, 0); } static SANE_Int Write_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int data) { return IWrite_Word (usb_handle, address, data, 0); } /*static SANE_Int Write_Integer(USB_Handle usb_handle, SANE_Int address, SANE_Int data) { return IWrite_Integer(usb_handle, address, data, 0); }*/ static SANE_Int Write_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size) { return IWrite_Buffer (usb_handle, address, buffer, size, 0); } static SANE_Int Read_Byte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data) { return IRead_Byte (usb_handle, address, data, 0x100); } static SANE_Int Read_Word (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) { return IRead_Word (usb_handle, address, data, 0x100); } static SANE_Int Read_Integer (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) { return IRead_Integer (usb_handle, address, data, 0x100); } static SANE_Int Read_Buffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size) { return IRead_Buffer (usb_handle, address, buffer, size, 0x100); } static SANE_Int Write_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, SANE_Int size) { SANE_Int rst = ERROR; if (buffer != NULL) { dataline_count++; DBG (DBG_CTL, "%06i BLK DO: %i. bytes\n", dataline_count, size); show_buffer (4, buffer, size); #ifdef STANDALONE if (usb_handle != NULL) if (usb_bulk_write (usb_handle, BLK_WRITE_EP, (char *) buffer, size, TIMEOUT) == size) rst = OK; #else if (usb_handle != -1) { size_t mysize = size; if (sanei_usb_write_bulk (usb_handle, buffer, &mysize) == SANE_STATUS_GOOD) rst = OK; } #endif } if (rst != OK) DBG (DBG_CTL, " : Write_Bulk error\n"); return rst; } static SANE_Int Read_Bulk (USB_Handle usb_handle, SANE_Byte * buffer, size_t size) { SANE_Int rst = ERROR; if (buffer != NULL) { dataline_count++; DBG (DBG_CTL, "%06i BLK DI: Buffer length = %lu. bytes\n", dataline_count, (u_long) size); #ifdef STANDALONE if (usb_handle != NULL) rst = usb_bulk_read (usb_handle, BLK_READ_EP, (char *) buffer, size, TIMEOUT); #else if (usb_handle != -1) if (sanei_usb_read_bulk (usb_handle, buffer, &size) == SANE_STATUS_GOOD) rst = size; #endif } if (rst < 0) DBG (DBG_CTL, " : Read_Bulk error\n"); else show_buffer (4, buffer, rst); return rst; } static SANE_Int usb_ctl_write (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size, SANE_Int index) { SANE_Int rst = ERROR; dataline_count++; DBG (DBG_CTL, "%06i CTL DO: 40 04 %04x %04x %04x\n", dataline_count, address & 0xffff, index, size); show_buffer (DBG_CTL, buffer, size); #ifdef STANDALONE if (usb_handle != NULL) rst = usb_control_msg (usb_handle, 0x40, /* Request type */ 0x04, /* Request */ address, /* Value */ index, /* Index */ (char *) buffer, /* Buffer */ size, /* Size */ TIMEOUT); #else if (usb_handle != -1) { if (sanei_usb_control_msg (usb_handle, 0x40, /* Request type */ 0x04, /* Request */ address, /* Value */ index, /* Index */ size, /* Size */ buffer) /* Buffer */ == SANE_STATUS_GOOD) rst = size; else rst = -1; } #endif if (rst < 0) DBG (DBG_CTL, " : Error, returned %i\n", rst); return rst; } static SANE_Int usb_ctl_read (USB_Handle usb_handle, SANE_Int address, SANE_Byte * buffer, SANE_Int size, SANE_Int index) { SANE_Int rst; rst = ERROR; dataline_count++; DBG (DBG_CTL, "%06i CTL DI: c0 04 %04x %04x %04x\n", dataline_count, address & 0xffff, index, size); #ifdef STANDALONE if (usb_handle != NULL) rst = usb_control_msg (usb_handle, 0xc0, /* Request type */ 0x04, /* Request */ address, /* Value */ index, /* Index */ (char *) buffer, /* Buffer */ size, /* Size */ TIMEOUT); #else if (usb_handle != -1) { if (sanei_usb_control_msg (usb_handle, 0xc0, /* Request type */ 0x04, /* Request */ address, /* Value */ index, /* Index */ size, /* Size */ buffer) /* Buffer */ == SANE_STATUS_GOOD) rst = size; else rst = -1; } #endif if (rst < 0) DBG (DBG_CTL, " : Error, returned %i\n", rst); else show_buffer (DBG_CTL, buffer, rst); return rst; } static SANE_Int show_buffer (SANE_Int level, SANE_Byte * buffer, SANE_Int size) { if (DBG_LEVEL >= level) { char *sline = NULL; char *sdata = NULL; SANE_Int cont, data, offset = 0, col = 0; if ((size > 0) && (buffer != NULL)) { sline = (char *) malloc (256); if (sline != NULL) { sdata = (char *) malloc (256); if (sdata != NULL) { bzero (sline, 256); for (cont = 0; cont < size; cont++) { if (col == 0) { if (cont == 0) snprintf (sline, 255, " BF: "); else snprintf (sline, 255, " "); } data = (buffer[cont] & 0xff); snprintf (sdata, 255, "%02x ", data); sline = strcat (sline, sdata); col++; offset++; if (col == 8) { col = 0; snprintf (sdata, 255, " : %i\n", offset - 8); sline = strcat (sline, sdata); DBG (level, "%s", sline); bzero (sline, 256); } } if (col > 0) { for (cont = col; cont < 8; cont++) { snprintf (sdata, 255, "-- "); sline = strcat (sline, sdata); offset++; } snprintf (sdata, 255, " : %i\n", offset - 8); sline = strcat (sline, sdata); DBG (level, "%s", sline); bzero (sline, 256); } free (sdata); } free (sline); } } else DBG (level, " BF: Empty buffer\n"); } return OK; } #endif /*USBLAYER*/ sane-backends-1.0.27/backend/ma1509.h0000664000175000017500000001175612112021330013671 00000000000000/* sane - Scanner Access Now Easy. (C) 2003 Henning Meier-Geinitz . Based on the mustek (SCSI) backend. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for scanners based on the Mustek MA-1509 chipset. Currently the Mustek BearPaw 1200F is known to work. */ #ifndef ma1509_h #define ma1509_h #include "../include/sane/config.h" #include /* Some constants */ #define INQ_LEN 0x60 /* Length of SCSI inquiry */ #define MA1509_COMMAND_LENGTH 8 #define MA1509_GAMMA_SIZE 1024 #define MA1509_BUFFER_SIZE (1024 * 128) #define MA1509_WARMUP_TIME 30 #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define MA1509_CONFIG_FILE "ma1509.conf" /* Convenience macros */ #if defined(MIN) #undef MIN #endif #if defined(MAX) #undef MAX #endif #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /* Copy values to memory ('L' = little endian, 'B' = big endian */ #define STORE16L(cp,v) \ do { \ int value = (v); \ \ *(cp)++ = (value >> 0) & 0xff; \ *(cp)++ = (value >> 8) & 0xff; \ } while (0) #define STORE16B(cp,v) \ do { \ int value = (v); \ \ *(cp)++ = (value >> 8) & 0xff; \ *(cp)++ = (value >> 0) & 0xff; \ } while (0) #define STORE32B(cp,v) \ do { \ long int value = (v); \ \ *(cp)++ = (value >> 24) & 0xff; \ *(cp)++ = (value >> 16) & 0xff; \ *(cp)++ = (value >> 8) & 0xff; \ *(cp)++ = (value >> 0) & 0xff; \ } while (0) /* declarations */ enum Ma1509_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_RESOLUTION, OPT_SOURCE, OPT_PREVIEW, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_THRESHOLD, OPT_CUSTOM_GAMMA, /* use custom gamma tables? */ OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, /* must come last: */ NUM_OPTIONS }; typedef struct Ma1509_Device { struct Ma1509_Device *next; SANE_String name; SANE_Device sane; SANE_Bool has_ta; SANE_Bool has_adf; SANE_Range x_range; SANE_Range y_range; /* scan area when transparency adapter is used: */ SANE_Range x_trans_range; SANE_Range y_trans_range; /* values actually used by scanner, not necessarily the desired! */ SANE_Int bpl, ppl, lines; } Ma1509_Device; typedef struct Ma1509_Scanner { /* all the state needed to define a scan request: */ struct Ma1509_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Bool scanning; SANE_Bool cancelled; SANE_Parameters params; /* Parsed option values and variables that are valid only during actual scanning: */ int fd; /* filedescriptor */ long start_time; /* at this time the scan started */ long lamp_time; /* at this time the lamp was turned on */ SANE_Word total_bytes; /* bytes read from scanner */ SANE_Word read_bytes; /* bytes transmitted by sane_read */ SANE_Int red_gamma_table[MA1509_GAMMA_SIZE]; SANE_Int green_gamma_table[MA1509_GAMMA_SIZE]; SANE_Int blue_gamma_table[MA1509_GAMMA_SIZE]; SANE_Byte *buffer, *buffer_start; SANE_Int buffer_bytes; /* scanner dependent/low-level state: */ Ma1509_Device *hw; } Ma1509_Scanner; #endif /* ma1509_h */ sane-backends-1.0.27/backend/leo.h0000664000175000017500000004613212112021330013530 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ */ /* Commands supported by the scanner. */ #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_INQUIRY 0x12 #define SCSI_SCAN 0x1b #define SCSI_SET_WINDOW 0x24 #define SCSI_READ_10 0x28 #define SCSI_SEND_10 0x2a #define SCSI_REQUEST_SENSE 0x03 #define SCSI_GET_DATA_BUFFER_STATUS 0x34 typedef struct { unsigned char data[16]; int len; } CDB; /* Set a specific bit depending on a boolean. * MKSCSI_BIT(TRUE, 3) will generate 0x08. */ #define MKSCSI_BIT(bit, pos) ((bit)? 1<<(pos): 0) /* Set a value in a range of bits. * MKSCSI_I2B(5, 3, 5) will generate 0x28 */ #define MKSCSI_I2B(bits, pos_b, pos_e) ((bits) << (pos_b) & ((1<<((pos_e)-(pos_b)+1))-1)) /* Store an integer in 2, 3 or 4 byte in an array. */ #define Ito16(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 0) & 0xff; \ } #define Ito24(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 0) & 0xff; \ } #define Ito32(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 24) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[3] = ((val) >> 0) & 0xff; \ } #define MKSCSI_GET_DATA_BUFFER_STATUS(cdb, wait, buflen) \ cdb.data[0] = SCSI_GET_DATA_BUFFER_STATUS; \ cdb.data[1] = MKSCSI_BIT(wait, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = 0; \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_INQUIRY(cdb, buflen) \ cdb.data[0] = SCSI_INQUIRY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SCAN(cdb) \ cdb.data[0] = SCSI_SCAN; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SEND_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_SEND_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_SET_WINDOW(cdb, buflen) \ cdb.data[0] = SCSI_SET_WINDOW; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_READ_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_READ_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_REQUEST_SENSE(cdb, buflen) \ cdb.data[0] = SCSI_REQUEST_SENSE; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = (buflen); \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_TEST_UNIT_READY(cdb) \ cdb.data[0] = SCSI_TEST_UNIT_READY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; /*--------------------------------------------------------------------------*/ static int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /*--------------------------------------------------------------------------*/ #define mmToIlu(mm) (((mm) * dev->x_resolution) / MM_PER_INCH) #define iluToMm(ilu) (((ilu) * MM_PER_INCH) / dev->x_resolution) /*--------------------------------------------------------------------------*/ #define GAMMA_LENGTH 0x100 /* number of value per color */ /*--------------------------------------------------------------------------*/ enum Leo_Option { /* Must come first */ OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* scanner modes */ OPT_RESOLUTION, /* X and Y resolution */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* upper left X */ OPT_TL_Y, /* upper left Y */ OPT_BR_X, /* bottom right X */ OPT_BR_Y, /* bottom right Y */ OPT_ENHANCEMENT_GROUP, OPT_CUSTOM_GAMMA, /* Use the custom gamma tables */ OPT_GAMMA_VECTOR_R, /* Custom Red gamma table */ OPT_GAMMA_VECTOR_G, /* Custom Green Gamma table */ OPT_GAMMA_VECTOR_B, /* Custom Blue Gamma table */ OPT_GAMMA_VECTOR_GRAY, /* Custom Gray Gamma table */ OPT_HALFTONE_PATTERN, /* Halftone pattern */ OPT_PREVIEW, /* preview mode */ /* must come last: */ OPT_NUM_OPTIONS }; /*--------------------------------------------------------------------------*/ /* * Scanner supported by this backend. */ struct scanners_supported { int scsi_type; char scsi_vendor[9]; char scsi_product[17]; const char *real_vendor; const char *real_product; }; /*--------------------------------------------------------------------------*/ #define BLACK_WHITE_STR SANE_VALUE_SCAN_MODE_LINEART #define GRAY_STR SANE_VALUE_SCAN_MODE_GRAY #define COLOR_STR SANE_VALUE_SCAN_MODE_COLOR /*--------------------------------------------------------------------------*/ /* Define a scanner occurence. */ typedef struct Leo_Scanner { struct Leo_Scanner *next; SANE_Device sane; char *devicename; int sfd; /* device handle */ /* Infos from inquiry. */ char scsi_type; char scsi_vendor[9]; char scsi_product[17]; char scsi_version[5]; SANE_Range res_range; int x_resolution_max; /* maximum X dpi */ int y_resolution_max; /* maximum Y dpi */ /* SCSI handling */ size_t buffer_size; /* size of the buffer */ SANE_Byte *buffer; /* for SCSI transfer. */ /* Scanner infos. */ const struct scanners_supported *def; /* default options for that scanner */ /* Scanning handling. */ int scanning; /* TRUE if a scan is running. */ int x_resolution; /* X resolution in DPI */ int y_resolution; /* Y resolution in DPI */ int x_tl; /* X top left */ int y_tl; /* Y top left */ int x_br; /* X bottom right */ int y_br; /* Y bottom right */ int width; /* width of the scan area in mm */ int length; /* length of the scan area in mm */ int pass; /* current pass number */ enum { LEO_BW, LEO_HALFTONE, LEO_GRAYSCALE, LEO_COLOR } scan_mode; int depth; /* depth per color */ size_t bytes_left; /* number of bytes left to give to the backend */ size_t real_bytes_left; /* number of bytes left the scanner will return. */ SANE_Byte *image; /* keep the raw image here */ size_t image_size; /* allocated size of image */ size_t image_begin; /* first significant byte in image */ size_t image_end; /* first free byte in image */ SANE_Parameters params; /* Options */ SANE_Option_Descriptor opt[OPT_NUM_OPTIONS]; Option_Value val[OPT_NUM_OPTIONS]; /* Gamma table. 1 array per colour. */ SANE_Word gamma_R[GAMMA_LENGTH]; SANE_Word gamma_G[GAMMA_LENGTH]; SANE_Word gamma_B[GAMMA_LENGTH]; SANE_Word gamma_GRAY[GAMMA_LENGTH]; } Leo_Scanner; /*--------------------------------------------------------------------------*/ /* Debug levels. * Should be common to all backends. */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /*--------------------------------------------------------------------------*/ /* 32 bits from an array to an integer (eg ntohl). */ #define B32TOI(buf) \ ((((unsigned char *)buf)[0] << 24) | \ (((unsigned char *)buf)[1] << 16) | \ (((unsigned char *)buf)[2] << 8) | \ (((unsigned char *)buf)[3] << 0)) #define B24TOI(buf) \ ((((unsigned char *)buf)[0] << 16) | \ (((unsigned char *)buf)[1] << 8) | \ (((unsigned char *)buf)[2] << 0)) #define B16TOI(buf) \ ((((unsigned char *)buf)[0] << 8) | \ (((unsigned char *)buf)[1] << 0)) /*--------------------------------------------------------------------------*/ /* Downloadable halftone patterns */ typedef unsigned char halftone_pattern_t[256]; static const halftone_pattern_t haltfone_pattern_diamond = { 0xF0, 0xE0, 0x60, 0x20, 0x00, 0x19, 0x61, 0xD8, 0xF0, 0xE0, 0x60, 0x20, 0x00, 0x19, 0x61, 0xD8, 0xC0, 0xA0, 0x88, 0x40, 0x38, 0x58, 0x80, 0xB8, 0xC0, 0xA0, 0x88, 0x40, 0x38, 0x58, 0x80, 0xB8, 0x30, 0x50, 0x98, 0xB0, 0xC8, 0xA8, 0x90, 0x48, 0x30, 0x50, 0x98, 0xB0, 0xC8, 0xA8, 0x90, 0x48, 0x08, 0x10, 0x70, 0xD0, 0xF8, 0xE8, 0x68, 0x28, 0x08, 0x10, 0x70, 0xD0, 0xF8, 0xE8, 0x68, 0x28, 0x00, 0x18, 0x78, 0xD8, 0xF0, 0xE0, 0x60, 0x20, 0x00, 0x18, 0x78, 0xD8, 0xF0, 0xE0, 0x60, 0x20, 0x38, 0x58, 0x80, 0xB8, 0xC0, 0xA0, 0x88, 0x40, 0x38, 0x58, 0x80, 0xB8, 0xC0, 0xA0, 0x88, 0x40, 0xC8, 0xA8, 0x90, 0x48, 0x30, 0x50, 0x9B, 0xB0, 0xC8, 0xA8, 0x90, 0x48, 0x30, 0x50, 0x9B, 0xB0, 0xF8, 0xE8, 0x68, 0x28, 0x08, 0x18, 0x70, 0xD0, 0xF8, 0xE8, 0x68, 0x28, 0x08, 0x18, 0x70, 0xD0, 0xF0, 0xE0, 0x60, 0x20, 0x00, 0x19, 0x61, 0xD8, 0xF0, 0xE0, 0x60, 0x20, 0x00, 0x19, 0x61, 0xD8, 0xC0, 0xA0, 0x88, 0x40, 0x38, 0x58, 0x80, 0xB8, 0xC0, 0xA0, 0x88, 0x40, 0x38, 0x58, 0x80, 0xB8, 0x30, 0x50, 0x98, 0xB0, 0xC8, 0xA8, 0x90, 0x48, 0x30, 0x50, 0x98, 0xB0, 0xC8, 0xA8, 0x90, 0x48, 0x08, 0x10, 0x70, 0xD0, 0xF8, 0xE8, 0x68, 0x28, 0x08, 0x10, 0x70, 0xD0, 0xF8, 0xE8, 0x68, 0x28, 0x00, 0x18, 0x78, 0xD8, 0xF0, 0xE0, 0x60, 0x20, 0x00, 0x18, 0x78, 0xD8, 0xF0, 0xE0, 0x60, 0x20, 0x38, 0x58, 0x80, 0xB8, 0xC0, 0xA0, 0x88, 0x40, 0x38, 0x58, 0x80, 0xB8, 0xC0, 0xA0, 0x88, 0x40, 0xC8, 0xA8, 0x90, 0x48, 0x30, 0x50, 0x9B, 0xB0, 0xC8, 0xA8, 0x90, 0x48, 0x30, 0x50, 0x9B, 0xB0, 0xF8, 0xE8, 0x68, 0x28, 0x08, 0x18, 0x70, 0xD0, 0xF8, 0xE8, 0x68, 0x28, 0x08, 0x18, 0x70, 0xD0 }; static const halftone_pattern_t haltfone_pattern_8x8_Coarse_Fatting = { 0x12, 0x3A, 0xD2, 0xEA, 0xE2, 0xB6, 0x52, 0x1A, 0x12, 0x3A, 0xD2, 0xEA, 0xE2, 0xB6, 0x52, 0x1A, 0x42, 0x6A, 0x9A, 0xCA, 0xC2, 0x92, 0x72, 0x4A, 0x42, 0x6A, 0x9A, 0xCA, 0xC2, 0x92, 0x72, 0x4A, 0xAE, 0x8E, 0x7E, 0x26, 0x2E, 0x66, 0x86, 0xA6, 0xAE, 0x8E, 0x7E, 0x26, 0x2E, 0x66, 0x86, 0xA6, 0xFA, 0xBA, 0x5E, 0x06, 0x0E, 0x36, 0xDE, 0xF6, 0xFA, 0xBA, 0x5E, 0x06, 0x0E, 0x36, 0xDE, 0xF6, 0xE6, 0xBE, 0x56, 0x1E, 0x16, 0x3E, 0xD6, 0xEE, 0xE6, 0xBE, 0x56, 0x1E, 0x16, 0x3E, 0xD6, 0xEE, 0xC6, 0x96, 0x76, 0x4E, 0x46, 0x6E, 0x9E, 0xCE, 0xC6, 0x96, 0x76, 0x4E, 0x46, 0x6E, 0x9E, 0xCE, 0x2A, 0x62, 0x82, 0xA2, 0xAA, 0x8A, 0x7A, 0x22, 0x2A, 0x62, 0x82, 0xA2, 0xAA, 0x8A, 0x7A, 0x22, 0x0A, 0x32, 0xDA, 0xF2, 0xFE, 0xB2, 0x5A, 0x02, 0x0A, 0x32, 0xDA, 0xF2, 0xFE, 0xB2, 0x5A, 0x02, 0x12, 0x3A, 0xD2, 0xEA, 0xE2, 0xB6, 0x52, 0x1A, 0x12, 0x3A, 0xD2, 0xEA, 0xE2, 0xB6, 0x52, 0x1A, 0x42, 0x6A, 0x9A, 0xCA, 0xC2, 0x92, 0x72, 0x4A, 0x42, 0x6A, 0x9A, 0xCA, 0xC2, 0x92, 0x72, 0x4A, 0xAE, 0x8E, 0x7E, 0x26, 0x2E, 0x66, 0x86, 0xA6, 0xAE, 0x8E, 0x7E, 0x26, 0x2E, 0x66, 0x86, 0xA6, 0xFA, 0xBA, 0x5E, 0x06, 0x0E, 0x36, 0xDE, 0xF6, 0xFA, 0xBA, 0x5E, 0x06, 0x0E, 0x36, 0xDE, 0xF6, 0xE6, 0xBE, 0x56, 0x1E, 0x16, 0x3E, 0xD6, 0xEE, 0xE6, 0xBE, 0x56, 0x1E, 0x16, 0x3E, 0xD6, 0xEE, 0xC6, 0x96, 0x76, 0x4E, 0x46, 0x6E, 0x9E, 0xCE, 0xC6, 0x96, 0x76, 0x4E, 0x46, 0x6E, 0x9E, 0xCE, 0x2A, 0x62, 0x82, 0xA2, 0xAA, 0x8A, 0x7A, 0x22, 0x2A, 0x62, 0x82, 0xA2, 0xAA, 0x8A, 0x7A, 0x22, 0x0A, 0x32, 0xDA, 0xF2, 0xFE, 0xB2, 0x5A, 0x02, 0x0A, 0x32, 0xDA, 0xF2, 0xFE, 0xB2, 0x5A, 0x02 }; static const halftone_pattern_t haltfone_pattern_8x8_Fine_Fatting = { 0x02, 0x22, 0x92, 0xB2, 0x0A, 0x2A, 0x9A, 0xBA, 0x02, 0x22, 0x92, 0xB2, 0x0A, 0x2A, 0x9A, 0xBA, 0x42, 0x62, 0xD2, 0xF2, 0x4A, 0x6A, 0xDA, 0xFA, 0x42, 0x62, 0xD2, 0xF2, 0x4A, 0x6A, 0xDA, 0xFA, 0x82, 0xA2, 0x12, 0x32, 0x8A, 0xAA, 0x1A, 0x3A, 0x82, 0xA2, 0x12, 0x32, 0x8A, 0xAA, 0x1A, 0x3A, 0xC2, 0xE2, 0x52, 0x72, 0xCA, 0xEA, 0x5A, 0x7A, 0xC2, 0xE2, 0x52, 0x72, 0xCA, 0xEA, 0x5A, 0x7A, 0x0E, 0x2E, 0x9E, 0xBE, 0x06, 0x26, 0x96, 0xB6, 0x0E, 0x2E, 0x9E, 0xBE, 0x06, 0x26, 0x96, 0xB6, 0x4C, 0x6E, 0xDE, 0xFE, 0x46, 0x66, 0xD6, 0xF6, 0x4C, 0x6E, 0xDE, 0xFE, 0x46, 0x66, 0xD6, 0xF6, 0x8E, 0xAE, 0x1E, 0x3E, 0x86, 0xA6, 0x16, 0x36, 0x8E, 0xAE, 0x1E, 0x3E, 0x86, 0xA6, 0x16, 0x36, 0xCE, 0xEE, 0x60, 0x7E, 0xC6, 0xE6, 0x56, 0x76, 0xCE, 0xEE, 0x60, 0x7E, 0xC6, 0xE6, 0x56, 0x76, 0x02, 0x22, 0x92, 0xB2, 0x0A, 0x2A, 0x9A, 0xBA, 0x02, 0x22, 0x92, 0xB2, 0x0A, 0x2A, 0x9A, 0xBA, 0x42, 0x62, 0xD2, 0xF2, 0x4A, 0x6A, 0xDA, 0xFA, 0x42, 0x62, 0xD2, 0xF2, 0x4A, 0x6A, 0xDA, 0xFA, 0x82, 0xA2, 0x12, 0x32, 0x8A, 0xAA, 0x1A, 0x3A, 0x82, 0xA2, 0x12, 0x32, 0x8A, 0xAA, 0x1A, 0x3A, 0xC2, 0xE2, 0x52, 0x72, 0xCA, 0xEA, 0x5A, 0x7A, 0xC2, 0xE2, 0x52, 0x72, 0xCA, 0xEA, 0x5A, 0x7A, 0x0E, 0x2E, 0x9E, 0xBE, 0x06, 0x26, 0x96, 0xB6, 0x0E, 0x2E, 0x9E, 0xBE, 0x06, 0x26, 0x96, 0xB6, 0x4C, 0x6E, 0xDE, 0xFE, 0x46, 0x66, 0xD6, 0xF6, 0x4C, 0x6E, 0xDE, 0xFE, 0x46, 0x66, 0xD6, 0xF6, 0x8E, 0xAE, 0x1E, 0x3E, 0x86, 0xA6, 0x16, 0x36, 0x8E, 0xAE, 0x1E, 0x3E, 0x86, 0xA6, 0x16, 0x36, 0xCE, 0xEE, 0x60, 0x7E, 0xC6, 0xE6, 0x56, 0x76, 0xCE, 0xEE, 0x60, 0x7E, 0xC6, 0xE6, 0x56, 0x76 }; static const halftone_pattern_t haltfone_pattern_8x8_Bayer = { 0xF2, 0x42, 0x82, 0xC2, 0xFA, 0x4A, 0x8A, 0xCA, 0xF2, 0x42, 0x82, 0xC2, 0xFA, 0x4A, 0x8A, 0xCA, 0xB2, 0x02, 0x12, 0x52, 0xBA, 0x0A, 0x1A, 0x5A, 0xB2, 0x02, 0x12, 0x52, 0xBA, 0x0A, 0x1A, 0x5A, 0x72, 0x32, 0x22, 0x92, 0x7A, 0x3A, 0x2A, 0x9A, 0x72, 0x32, 0x22, 0x92, 0x7A, 0x3A, 0x2A, 0x9A, 0xE2, 0xA2, 0x62, 0xD2, 0xEA, 0xAA, 0x6A, 0xDA, 0xE2, 0xA2, 0x62, 0xD2, 0xEA, 0xAA, 0x6A, 0xDA, 0xFE, 0x4E, 0x8E, 0xCE, 0xF6, 0x46, 0xD6, 0xC6, 0xFE, 0x4E, 0x8E, 0xCE, 0xF6, 0x46, 0xD6, 0xC6, 0xBE, 0x0E, 0x1E, 0x5E, 0xB6, 0x06, 0x16, 0x56, 0xBE, 0x0E, 0x1E, 0x5E, 0xB6, 0x06, 0x16, 0x56, 0x7E, 0x3E, 0x2E, 0x9E, 0x76, 0x36, 0x26, 0x96, 0x7E, 0x3E, 0x2E, 0x9E, 0x76, 0x36, 0x26, 0x96, 0xEE, 0xAE, 0x6E, 0xDE, 0xE6, 0xA6, 0x66, 0xD6, 0xEE, 0xAE, 0x6E, 0xDE, 0xE6, 0xA6, 0x66, 0xD6, 0xF2, 0x42, 0x82, 0xC2, 0xFA, 0x4A, 0x8A, 0xCA, 0xF2, 0x42, 0x82, 0xC2, 0xFA, 0x4A, 0x8A, 0xCA, 0xB2, 0x02, 0x12, 0x52, 0xBA, 0x0A, 0x1A, 0x5A, 0xB2, 0x02, 0x12, 0x52, 0xBA, 0x0A, 0x1A, 0x5A, 0x72, 0x32, 0x22, 0x92, 0x7A, 0x3A, 0x2A, 0x9A, 0x72, 0x32, 0x22, 0x92, 0x7A, 0x3A, 0x2A, 0x9A, 0xE2, 0xA2, 0x62, 0xD2, 0xEA, 0xAA, 0x6A, 0xDA, 0xE2, 0xA2, 0x62, 0xD2, 0xEA, 0xAA, 0x6A, 0xDA, 0xFE, 0x4E, 0x8E, 0xCE, 0xF6, 0x46, 0xD6, 0xC6, 0xFE, 0x4E, 0x8E, 0xCE, 0xF6, 0x46, 0xD6, 0xC6, 0xBE, 0x0E, 0x1E, 0x5E, 0xB6, 0x06, 0x16, 0x56, 0xBE, 0x0E, 0x1E, 0x5E, 0xB6, 0x06, 0x16, 0x56, 0x7E, 0x3E, 0x2E, 0x9E, 0x76, 0x36, 0x26, 0x96, 0x7E, 0x3E, 0x2E, 0x9E, 0x76, 0x36, 0x26, 0x96, 0xEE, 0xAE, 0x6E, 0xDE, 0xE6, 0xA6, 0x66, 0xD6, 0xEE, 0xAE, 0x6E, 0xDE, 0xE6, 0xA6, 0x66, 0xD6 }; static const halftone_pattern_t haltfone_pattern_8x8_Vertical_Line = { 0x02, 0x42, 0x82, 0xC4, 0x0A, 0x4C, 0x8A, 0xCA, 0x02, 0x42, 0x82, 0xC4, 0x0A, 0x4C, 0x8A, 0xCA, 0x12, 0x52, 0x92, 0xD2, 0x1A, 0x5A, 0x9A, 0xDA, 0x12, 0x52, 0x92, 0xD2, 0x1A, 0x5A, 0x9A, 0xDA, 0x22, 0x62, 0xA2, 0xE2, 0x2A, 0x6A, 0xAA, 0xEA, 0x22, 0x62, 0xA2, 0xE2, 0x2A, 0x6A, 0xAA, 0xEA, 0x32, 0x72, 0xB2, 0xF2, 0x3A, 0x7A, 0xBA, 0xFA, 0x32, 0x72, 0xB2, 0xF2, 0x3A, 0x7A, 0xBA, 0xFA, 0x0E, 0x4E, 0x8E, 0xCE, 0x06, 0x46, 0x86, 0xC6, 0x0E, 0x4E, 0x8E, 0xCE, 0x06, 0x46, 0x86, 0xC6, 0x1E, 0x5E, 0x9E, 0xDE, 0x16, 0x56, 0x96, 0xD6, 0x1E, 0x5E, 0x9E, 0xDE, 0x16, 0x56, 0x96, 0xD6, 0x2E, 0x6E, 0xAE, 0xEE, 0x26, 0x66, 0xA6, 0xE6, 0x2E, 0x6E, 0xAE, 0xEE, 0x26, 0x66, 0xA6, 0xE6, 0x3E, 0x7E, 0xBE, 0xFE, 0x36, 0x76, 0xB6, 0xF6, 0x3E, 0x7E, 0xBE, 0xFE, 0x36, 0x76, 0xB6, 0xF6, 0x02, 0x42, 0x82, 0xC4, 0x0A, 0x4C, 0x8A, 0xCA, 0x02, 0x42, 0x82, 0xC4, 0x0A, 0x4C, 0x8A, 0xCA, 0x12, 0x52, 0x92, 0xD2, 0x1A, 0x5A, 0x9A, 0xDA, 0x12, 0x52, 0x92, 0xD2, 0x1A, 0x5A, 0x9A, 0xDA, 0x22, 0x62, 0xA2, 0xE2, 0x2A, 0x6A, 0xAA, 0xEA, 0x22, 0x62, 0xA2, 0xE2, 0x2A, 0x6A, 0xAA, 0xEA, 0x32, 0x72, 0xB2, 0xF2, 0x3A, 0x7A, 0xBA, 0xFA, 0x32, 0x72, 0xB2, 0xF2, 0x3A, 0x7A, 0xBA, 0xFA, 0x0E, 0x4E, 0x8E, 0xCE, 0x06, 0x46, 0x86, 0xC6, 0x0E, 0x4E, 0x8E, 0xCE, 0x06, 0x46, 0x86, 0xC6, 0x1E, 0x5E, 0x9E, 0xDE, 0x16, 0x56, 0x96, 0xD6, 0x1E, 0x5E, 0x9E, 0xDE, 0x16, 0x56, 0x96, 0xD6, 0x2E, 0x6E, 0xAE, 0xEE, 0x26, 0x66, 0xA6, 0xE6, 0x2E, 0x6E, 0xAE, 0xEE, 0x26, 0x66, 0xA6, 0xE6, 0x3E, 0x7E, 0xBE, 0xFE, 0x36, 0x76, 0xB6, 0xF6, 0x3E, 0x7E, 0xBE, 0xFE, 0x36, 0x76, 0xB6, 0xF6 }; sane-backends-1.0.27/backend/epson2_scsi.h0000664000175000017500000000135112112021330015172 00000000000000#ifndef _EPSON2_SCSI_H_ #define _EPSON2_SCSI_H_ #include #include "../include/sane/sane.h" #define TEST_UNIT_READY_COMMAND (0x00) #define READ_6_COMMAND (0x08) #define WRITE_6_COMMAND (0x0a) #define INQUIRY_COMMAND (0x12) #define TYPE_PROCESSOR (0x03) #define INQUIRY_BUF_SIZE (36) SANE_Status sanei_epson2_scsi_sense_handler(int scsi_fd, unsigned char *result, void *arg); SANE_Status sanei_epson2_scsi_inquiry(int fd, void *buf, size_t *buf_size); int sanei_epson2_scsi_read(int fd, void *buf, size_t buf_size, SANE_Status *status); int sanei_epson2_scsi_write(int fd, const void *buf, size_t buf_size, SANE_Status *status); SANE_Status sanei_epson2_scsi_test_unit_ready(int fd); #endif sane-backends-1.0.27/backend/mustek_usb2_high.c0000664000175000017500000026044012775312261016233 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005 Mustek. Originally maintained by Mustek Author:Jack Roy 2005.5.24 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro and similar USB2 scanners. */ #include /* HOLD */ #include /* local header files */ #include "mustek_usb2_asic.c" #include "mustek_usb2_high.h" /* ******************++ spuicall_g.h ****************************/ /*global variable HOLD: these should go to scanner structure */ /*base type*/ static SANE_Bool g_bOpened; static SANE_Bool g_bPrepared; static SANE_Bool g_isCanceled; static SANE_Bool g_bSharpen; static SANE_Bool g_bFirstReadImage; static SANE_Bool g_isScanning; static SANE_Bool g_isSelfGamma; static SANE_Byte g_bScanBits; static SANE_Byte *g_lpReadImageHead; static unsigned short s_wOpticalYDpi[] = { 1200, 600, 300, 150, 75, 0 }; static unsigned short s_wOpticalXDpi[] = { 1200, 600, 300, 150, 75, 0 }; static unsigned short g_X; static unsigned short g_Y; static unsigned short g_Width; static unsigned short g_Height; static unsigned short g_XDpi; static unsigned short g_YDpi; static unsigned short g_SWWidth; static unsigned short g_SWHeight; static unsigned short g_wPixelDistance; /*even & odd sensor problem */ static unsigned short g_wLineDistance; static unsigned short g_wScanLinesPerBlock; static unsigned short g_wReadedLines; static unsigned short g_wReadImageLines; static unsigned short g_wReadyShadingLine; static unsigned short g_wStartShadingLinePos; static unsigned short g_wLineartThreshold; static unsigned int g_wtheReadyLines; static unsigned int g_wMaxScanLines; static unsigned int g_dwScannedTotalLines; static unsigned int g_dwImageBufferSize; static unsigned int g_BytesPerRow; static unsigned int g_SWBytesPerRow; static unsigned int g_dwCalibrationSize; static unsigned int g_dwBufferSize; static unsigned int g_dwTotalTotalXferLines; static unsigned short *g_pGammaTable; static unsigned char *g_pDeviceFile; static pthread_t g_threadid_readimage; /*user define type*/ static COLORMODE g_ScanMode; static TARGETIMAGE g_tiTarget; static SCANTYPE g_ScanType = ST_Reflective; static SCANSOURCE g_ssScanSource; static PIXELFLAVOR g_PixelFlavor; static SUGGESTSETTING g_ssSuggest; static Asic g_chip; static int g_nSecLength, g_nDarkSecLength; static int g_nSecNum, g_nDarkSecNum; static unsigned short g_wCalWidth; static unsigned short g_wDarkCalWidth; static int g_nPowerNum; static unsigned short g_wStartPosition; static pthread_mutex_t g_scannedLinesMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_readyLinesMutex = PTHREAD_MUTEX_INITIALIZER; /*for modify the last point*/ static SANE_Byte * g_lpBefLineImageData = NULL; static SANE_Bool g_bIsFirstReadBefData = TRUE; static unsigned int g_dwAlreadyGetLines = 0; /* forward declarations */ static SANE_Bool MustScanner_Init (void); static SANE_Bool MustScanner_GetScannerState (void); static SANE_Bool MustScanner_PowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn); static SANE_Bool MustScanner_BackHome (void); static SANE_Bool MustScanner_Prepare (SANE_Byte bScanSource); #ifdef SANE_UNUSED static SANE_Bool MustScanner_AdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset, SANE_Byte * bLastMin, SANE_Byte * bLastOffset, unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound, SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel, unsigned short wStdMaxLevel); static SANE_Bool MustScanner_SecondAdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset, SANE_Byte * bLastMin, SANE_Byte * bLastOffset, unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound, SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel, unsigned short wStdMaxLevel); #endif static unsigned short MustScanner_FiltLower (unsigned short * pSort, unsigned short TotalCount, unsigned short LowCount, unsigned short HighCount); static SANE_Bool MustScanner_GetRgb48BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetRgb48BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetRgb24BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetRgb24BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetMono16BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetMono16BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetMono8BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetMono8BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetMono1BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static SANE_Bool MustScanner_GetMono1BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount); static void *MustScanner_ReadDataFromScanner (void * dummy); static void MustScanner_PrepareCalculateMaxMin (unsigned short wResolution); static void MustScanner_CalculateMaxMin (SANE_Byte * pBuffer, unsigned short * lpMaxValue, unsigned short * lpMinValue, unsigned short wResolution); static SANE_Byte QBET4 (SANE_Byte A, SANE_Byte B); static unsigned int GetScannedLines (void); static unsigned int GetReadyLines (void); static void AddScannedLines (unsigned short wAddLines); static void AddReadyLines (void); static void ModifyLinePoint (SANE_Byte * lpImageData, SANE_Byte * lpImageDataBefore, unsigned int dwBytesPerLine, unsigned int dwLinesCount, unsigned short wPixDistance, unsigned short wModPtCount); #include "mustek_usb2_reflective.c" #include "mustek_usb2_transparent.c" /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: Parameters: none Return value: if initialize the scanner success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_Init () { DBG (DBG_FUNC, "MustScanner_Init: Call in\n"); g_chip.firmwarestate = FS_NULL; if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile)) { DBG (DBG_FUNC, "MustScanner_Init: Asic_Open return error\n"); return FALSE; } if (STATUS_GOOD != Asic_Initialize (&g_chip)) { DBG (DBG_FUNC, "MustScanner_Init: Asic_Initialize return error\n"); return FALSE; } g_dwImageBufferSize = 24L * 1024L * 1024L; g_dwBufferSize = 64L * 1024L; g_dwCalibrationSize = 64L * 1024L; g_lpReadImageHead = NULL; g_isCanceled = FALSE; g_bFirstReadImage = TRUE; g_bOpened = FALSE; g_bPrepared = FALSE; g_bSharpen = FALSE; g_isScanning = FALSE; g_isSelfGamma = FALSE; g_pGammaTable = NULL; if (NULL != g_pDeviceFile) { free (g_pDeviceFile); g_pDeviceFile = NULL; } g_ssScanSource = SS_Reflective; g_PixelFlavor = PF_BlackIs0; Asic_Close (&g_chip); DBG (DBG_FUNC, "MustScanner_Init: leave MustScanner_Init\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: check the scanner connect status Parameters: none Return value: if scanner's status is OK return TRUE else return FASLE ***********************************************************************/ static SANE_Bool MustScanner_GetScannerState () { if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile)) { DBG (DBG_FUNC, "MustScanner_GetScannerState: Asic_Open return error\n"); return FALSE; } else { Asic_Close (&g_chip); return TRUE; } } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: Turn the lamp on or off Parameters: isLampOn: turn the lamp on or off isTALampOn: turn the TA lamp on or off Return value: if operation success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_PowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn) { SANE_Bool hasTA; DBG (DBG_FUNC, "MustScanner_PowerControl: Call in\n"); if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile)) { DBG (DBG_FUNC, "MustScanner_PowerControl: Asic_Open return error\n"); return FALSE; } if (STATUS_GOOD != Asic_TurnLamp (&g_chip, isLampOn)) { DBG (DBG_FUNC, "MustScanner_PowerControl: Asic_TurnLamp return error\n"); return FALSE; } if (STATUS_GOOD != Asic_IsTAConnected (&g_chip, &hasTA)) { DBG (DBG_FUNC, "MustScanner_PowerControl: Asic_IsTAConnected return error\n"); return FALSE; } if (hasTA) { if (STATUS_GOOD != Asic_TurnTA (&g_chip, isTALampOn)) { DBG (DBG_FUNC, "MustScanner_PowerControl: Asic_TurnTA return error\n"); return FALSE; } } Asic_Close (&g_chip); DBG (DBG_FUNC, "MustScanner_PowerControl: leave MustScanner_PowerControl\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: Turn the carriage home Parameters: none Return value: if the operation success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_BackHome () { DBG (DBG_FUNC, "MustScanner_BackHome: call in \n"); if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile)) { DBG (DBG_FUNC, "MustScanner_BackHome: Asic_Open return error\n"); return FALSE; } if (STATUS_GOOD != Asic_CarriageHome (&g_chip, FALSE)) { DBG (DBG_FUNC, "MustScanner_BackHome: Asic_CarriageHome return error\n"); return FALSE; } if (STATUS_GOOD != Asic_WaitUnitReady (&g_chip)) { DBG (DBG_FUNC, "MustScanner_BackHome: Asic_WaitUnitReady return error\n"); return FALSE; } Asic_Close (&g_chip); DBG (DBG_FUNC, "MustScanner_BackHome: leave MustScanner_BackHome\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: prepare the scan image Parameters: bScanSource: the scan source Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_Prepare (SANE_Byte bScanSource) { DBG (DBG_FUNC, "MustScanner_Prepare: call in\n"); if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile)) { DBG (DBG_FUNC, "MustScanner_Prepare: Asic_Open return error\n"); return FALSE; } if (STATUS_GOOD != Asic_WaitUnitReady (&g_chip)) { DBG (DBG_FUNC, "MustScanner_Prepare: Asic_WaitUnitReady return error\n"); return FALSE; } if (SS_Reflective == bScanSource) { DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Reflective\n"); if (STATUS_GOOD != Asic_TurnLamp (&g_chip, TRUE)) { DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnLamp return error\n"); return FALSE; } if (STATUS_GOOD != Asic_SetSource (&g_chip, LS_REFLECTIVE)) { DBG (DBG_FUNC, "MustScanner_Prepare: Asic_SetSource return error\n"); return FALSE; } } else if (SS_Positive == bScanSource) { DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Positive\n"); if (STATUS_GOOD != Asic_TurnTA (&g_chip, TRUE)) { DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnTA return error\n"); return FALSE; } if (STATUS_GOOD != Asic_SetSource (&g_chip, LS_POSITIVE)) { DBG (DBG_FUNC, "MustScanner_Prepare: Asic_SetSource return error\n"); return FALSE; } } else if (SS_Negative == bScanSource) { DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Negative\n"); if (STATUS_GOOD != Asic_TurnTA (&g_chip, TRUE)) { DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnTA return error\n"); return FALSE; } if (STATUS_GOOD != Asic_SetSource (&g_chip, LS_NEGATIVE)) { DBG (DBG_FUNC, "MustScanner_Prepare: Asic_SetSource return error\n"); return FALSE; } DBG (DBG_FUNC, "MustScanner_Prepare: Asic_SetSource return good\n"); } Asic_Close (&g_chip); g_bPrepared = TRUE; DBG (DBG_FUNC, "MustScanner_Prepare: leave MustScanner_Prepare\n"); return TRUE; } #ifdef SANE_UNUSED /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Adjuest the offset Parameters: nTimes: Adjuest offset the times bDirection: whether direction bOffset: the data of offset bLastMin: the last min data bLastOffset: the last offset data wMinValue: the min value of offset bOffsetUpperBound: the upper bound of offset bOffsetLowerBound: the lower bound of offset wStdMinLevel: the min level of offset wStdMaxLevel: the max level of offset Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_AdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset, SANE_Byte * bLastMin, SANE_Byte * bLastOffset, unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound, SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel, unsigned short wStdMaxLevel) { if ((*wMinValue <= wStdMaxLevel) && (*wMinValue >= wStdMinLevel)) { return TRUE; } if (nTimes == 0) { *bLastMin = LOSANE_Byte (*wMinValue); *bLastOffset = *bOffset; if (*wMinValue == 255) { *bOffset = 0; } else { *bOffset = 255; } } if (nTimes == 1) { if (*wMinValue > *bLastMin) { if (*wMinValue > wStdMaxLevel && *bLastMin > wStdMaxLevel) { *bDirection = !(*bDirection); return TRUE; } if (*wMinValue < wStdMinLevel && *bLastMin < wStdMinLevel) return TRUE; } if (*wMinValue < *bLastMin) { if (*wMinValue < wStdMinLevel && *bLastMin < wStdMinLevel) *bDirection = !(*bDirection); if (*wMinValue > wStdMaxLevel && *bLastMin > wStdMaxLevel) return TRUE; } } if (nTimes > 1) { if (*wMinValue > *bLastMin) { SANE_Byte bTemp; bTemp = *bOffset; *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2; if (nTimes > 2) { if (*wMinValue > wStdMaxLevel) if (bDirection) *bOffsetLowerBound = bTemp; else *bOffsetUpperBound = bTemp; else if (bDirection) *bOffsetUpperBound = bTemp; else *bOffsetLowerBound = bTemp; } *bLastOffset = bTemp; *bLastMin = (SANE_Byte) * wMinValue; } else { SANE_Byte bTemp; bTemp = *bOffset; *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2; if (nTimes > 2) { if (*wMinValue == *bLastMin) { if (*wMinValue > wStdMaxLevel) { if (!bDirection) *bOffsetUpperBound = bTemp; else *bOffsetLowerBound = bTemp; } else { if (!bDirection) *bOffsetLowerBound = bTemp; else *bOffsetUpperBound = bTemp; } } else { if (*wMinValue > wStdMaxLevel) { if (bDirection) *bOffsetUpperBound = bTemp; else *bOffsetLowerBound = bTemp; } else { if (bDirection) *bOffsetLowerBound = bTemp; else *bOffsetUpperBound = bTemp; } } } *bLastOffset = bTemp; *bLastMin = (SANE_Byte) * wMinValue; } } /* end of if(nTimes > 1) */ return TRUE; } #endif #ifdef SANE_UNUSED /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Adjuest the offset second times Parameters: nTimes: Adjuest offset the times bDirection: whether direction bOffset: the data of offset bLastMin: the last min data bLastOffset: the last offset data wMinValue: the min value of offset bOffsetUpperBound: the upper bound of offset bOffsetLowerBound: the lower bound of offset wStdMinLevel: the min level of offset wStdMaxLevel: the max level of offset Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_SecondAdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset, SANE_Byte * bLastMin, SANE_Byte * bLastOffset, unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound, SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel, unsigned short wStdMaxLevel) { if ((*wMinValue <= wStdMaxLevel) && (*wMinValue >= wStdMinLevel)) { return TRUE; } if (nTimes == 0) { *bLastMin = LOSANE_Byte (*wMinValue); *bLastOffset = *bOffset; if (*bDirection == 0) { *bOffsetUpperBound = *bLastOffset; *bOffsetLowerBound = 0; *bOffset = 0; } else { *bOffsetUpperBound = 255; *bOffsetLowerBound = *bLastOffset; *bOffset = 255; } } if (nTimes >= 1) { if (*wMinValue > wStdMaxLevel) { if (*wMinValue > *bLastMin) { if (*bDirection == 0) { *bOffsetUpperBound = *bOffset; } else { *bOffsetLowerBound = *bOffset; } *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2; } else { if (*bDirection == 1) { *bOffsetUpperBound = *bOffset; *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2; } else { *bOffsetLowerBound = *bOffset; *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2; } } } /*end of if(*wMinValue > MAX_OFFSET) */ if (*wMinValue < wStdMinLevel) { if (*wMinValue > *bLastMin) { if (*bDirection == 0) { *bOffsetLowerBound = *bOffset; } else { *bOffsetUpperBound = *bOffset; } *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2; } else { if (*bDirection == 1) { *bOffsetUpperBound = *bOffset; *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2; } else { *bOffsetLowerBound = *bOffset; *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2; } } } /*end of if(*wMinValue > MIN_OFFSET) */ *bLastMin = (SANE_Byte) * wMinValue; } /*end of if(nTimes >= 1) */ /* HOLD: missing return value! Correct? */ return FALSE; } #endif /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Filter the data Parameters: pSort: the sort data TotalCount: the total count LowCount: the low count HighCount: the upper count Return value: the data of Filter ***********************************************************************/ static unsigned short MustScanner_FiltLower (unsigned short * pSort, unsigned short TotalCount, unsigned short LowCount, unsigned short HighCount) { unsigned short Bound = TotalCount - 1; unsigned short LeftCount = HighCount - LowCount; int Temp = 0; unsigned int Sum = 0; unsigned short i, j; for (i = 0; i < Bound; i++) { for (j = 0; j < Bound - i; j++) { if (pSort[j + 1] > pSort[j]) { Temp = pSort[j]; pSort[j] = pSort[j + 1]; pSort[j + 1] = Temp; } } } for (i = 0; i < LeftCount; i++) Sum += pSort[i + LowCount]; return (unsigned short) (Sum / LeftCount); } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when single CCD and color is 48bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetRgb48BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned short wRLinePos = 0; unsigned short wGLinePos = 0; unsigned short wBLinePos = 0; unsigned short wRTempData; unsigned short wGTempData; unsigned short wBTempData; unsigned short i; DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: call in \n"); g_isCanceled = FALSE; g_isScanning = TRUE; wWantedTotalLines = *wLinesCount; TotalXferLines = 0; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread create\n"); g_bFirstReadImage = FALSE; } if (!isOrderInvert) { for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { wRLinePos = g_wtheReadyLines % g_wMaxScanLines; wGLinePos = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePos = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; for (i = 0; i < g_SWWidth; i++) { wRTempData = *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 + 0); wRTempData += *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 + 1) << 8; wGTempData = *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 + 2); wGTempData += *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 + 3) << 8; wBTempData = *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 + 4); wBTempData += *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 + 5) << 8; *(lpLine + i * 6 + 0) = LOBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 1) = HIBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 2) = LOBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 3) = HIBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 4) = LOBYTE (g_pGammaTable[wBTempData + 131072]); *(lpLine + i * 6 + 5) = HIBYTE (g_pGammaTable[wBTempData + 131072]); } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n"); break; } } } else { for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { wRLinePos = g_wtheReadyLines % g_wMaxScanLines; wGLinePos = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePos = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; for (i = 0; i < g_SWWidth; i++) { wRTempData = *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 + 0); wRTempData += *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 + 1) << 8; wGTempData = *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 + 2); wGTempData += *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 + 3) << 8; wBTempData = *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 + 4); wBTempData += *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 + 5) << 8; *(lpLine + i * 6 + 4) = LOBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 5) = HIBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 2) = LOBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 3) = HIBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 0) = LOBYTE (g_pGammaTable[wBTempData + 131072]); *(lpLine + i * 6 + 1) = HIBYTE (g_pGammaTable[wBTempData + 131072]); } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n"); break; } } /*end for */ } *wLinesCount = TotalXferLines; g_isScanning = FALSE; DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: leave MustScanner_GetRgb48BitLine\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when double CCD and color is 48bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetRgb48BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned short wRLinePosOdd = 0; unsigned short wGLinePosOdd = 0; unsigned short wBLinePosOdd = 0; unsigned short wRLinePosEven = 0; unsigned short wGLinePosEven = 0; unsigned short wBLinePosEven = 0; unsigned int wRTempData; unsigned int wGTempData; unsigned int wBTempData; unsigned int wNextTempData; unsigned short i; DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: call in \n"); TotalXferLines = 0; wWantedTotalLines = *wLinesCount; g_isCanceled = FALSE; g_isScanning = TRUE; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: thread create\n"); g_bFirstReadImage = FALSE; } if (!isOrderInvert) { for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { if (ST_Reflective == g_ScanType) { wRLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wGLinePosOdd = (g_wtheReadyLines - g_wLineDistance - g_wPixelDistance) % g_wMaxScanLines; wBLinePosOdd = (g_wtheReadyLines - g_wLineDistance * 2 - g_wPixelDistance) % g_wMaxScanLines; wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; wGLinePosEven = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePosEven = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; } else { wRLinePosEven = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wGLinePosEven = (g_wtheReadyLines - g_wLineDistance - g_wPixelDistance) % g_wMaxScanLines; wBLinePosEven = (g_wtheReadyLines - g_wLineDistance * 2 - g_wPixelDistance) % g_wMaxScanLines; wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines; wGLinePosOdd = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePosOdd = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; } for (i = 0; i < g_SWWidth;) { if (i + 1 != g_SWWidth) { wRTempData = *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + i * 6 + 0); wRTempData += *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + i * 6 + 1) << 8; wNextTempData = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + (i + 1) * 6 + 0); wNextTempData += *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + (i + 1) * 6 + 1) << 8; wRTempData = (wRTempData + wNextTempData) >> 1; wGTempData = *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + i * 6 + 2); wGTempData += *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + i * 6 + 3) << 8; wNextTempData = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + (i + 1) * 6 + 2); wNextTempData += *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + (i + 1) * 6 + 3) << 8; wGTempData = (wGTempData + wNextTempData) >> 1; wBTempData = *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + i * 6 + 4); wBTempData += *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + i * 6 + 5) << 8; wNextTempData = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + (i + 1) * 6 + 4); wNextTempData += *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + (i + 1) * 6 + 5) << 8; wBTempData = (wBTempData + wNextTempData) >> 1; *(lpLine + i * 6 + 0) = LOBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 1) = HIBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 2) = LOBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 3) = HIBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 4) = LOBYTE (g_pGammaTable[wBTempData + 131072]); *(lpLine + i * 6 + 5) = HIBYTE (g_pGammaTable[wBTempData + 131072]); i++; if (i >= g_SWWidth) { break; } wRTempData = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + i * 6 + 0); wRTempData += *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + i * 6 + 1) << 8; wNextTempData = *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 0); wNextTempData += *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 1) << 8; wRTempData = (wRTempData + wNextTempData) >> 1; wGTempData = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + i * 6 + 2); wGTempData += *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + i * 6 + 3) << 8; wNextTempData = *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 2); wNextTempData += *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 3) << 8; wGTempData = (wGTempData + wNextTempData) >> 1; wBTempData = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + i * 6 + 4); wBTempData += *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + i * 6 + 5) << 8; wNextTempData = *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 4); wNextTempData += *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 5) << 8; wBTempData = (wBTempData + wNextTempData) >> 1; *(lpLine + i * 6 + 0) = LOBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 1) = HIBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 2) = LOBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 3) = HIBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 4) = LOBYTE (g_pGammaTable[wBTempData + 131072]); *(lpLine + i * 6 + 5) = HIBYTE (g_pGammaTable[wBTempData + 131072]); i++; } } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: thread exit\n"); break; } } } else { for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { if (ST_Reflective == g_ScanType) { wRLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wGLinePosOdd = (g_wtheReadyLines - g_wLineDistance - g_wPixelDistance) % g_wMaxScanLines; wBLinePosOdd = (g_wtheReadyLines - g_wLineDistance * 2 - g_wPixelDistance) % g_wMaxScanLines; wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; wGLinePosEven = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePosEven = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; } else { wRLinePosEven = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wGLinePosEven = (g_wtheReadyLines - g_wLineDistance - g_wPixelDistance) % g_wMaxScanLines; wBLinePosEven = (g_wtheReadyLines - g_wLineDistance * 2 - g_wPixelDistance) % g_wMaxScanLines; wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines; wGLinePosOdd = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePosOdd = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; } for (i = 0; i < g_SWWidth;) { if ((i + 1) != g_SWWidth) { wRTempData = *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + i * 6 + 0); wRTempData += *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + i * 6 + 1) << 8; wNextTempData = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + (i + 1) * 6 + 0); wNextTempData += *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + (i + 1) * 6 + 1) << 8; wRTempData = (wRTempData + wNextTempData) >> 1; wGTempData = *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + i * 6 + 2); wGTempData += *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + i * 6 + 3) << 8; wNextTempData = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + (i + 1) * 6 + 2); wNextTempData += *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + (i + 1) * 6 + 3) << 8; wGTempData = (wGTempData + wNextTempData) >> 1; wBTempData = *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + i * 6 + 4); wBTempData += *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + i * 6 + 5) << 8; wNextTempData = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + (i + 1) * 6 + 4); wNextTempData += *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + (i + 1) * 6 + 5) << 8; wBTempData = (wBTempData + wNextTempData) >> 1; *(lpLine + i * 6 + 4) = LOBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 5) = HIBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 2) = LOBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 3) = HIBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 0) = LOBYTE (g_pGammaTable[wBTempData + 131072]); *(lpLine + i * 6 + 1) = HIBYTE (g_pGammaTable[wBTempData + 131072]); i++; if (i >= g_SWWidth) { break; } wRTempData = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + i * 6 + 0); wRTempData += *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + i * 6 + 1) << 8; wNextTempData = *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 0); wNextTempData += *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 1) << 8; wRTempData = (wRTempData + wNextTempData) >> 1; wGTempData = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + i * 6 + 2); wGTempData += *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + i * 6 + 3) << 8; wNextTempData = *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 2); wNextTempData += *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 3) << 8; wGTempData = (wGTempData + wNextTempData) >> 1; wBTempData = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + i * 6 + 4); wBTempData += *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + i * 6 + 5) << 8; wNextTempData = *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 4); wNextTempData += *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + (i + 1) * 6 + 5) << 8; wBTempData = (wBTempData + wNextTempData) >> 1; *(lpLine + i * 6 + 4) = LOBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 5) = HIBYTE (g_pGammaTable[wRTempData]); *(lpLine + i * 6 + 2) = LOBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 3) = HIBYTE (g_pGammaTable[wGTempData + 65536]); *(lpLine + i * 6 + 0) = LOBYTE (g_pGammaTable[wBTempData + 131072]); *(lpLine + i * 6 + 1) = HIBYTE (g_pGammaTable[wBTempData + 131072]); i++; } } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: thread exit\n"); break; } } } *wLinesCount = TotalXferLines; g_isScanning = FALSE; DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: leave MustScanner_GetRgb48BitLine1200DPI\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when single CCD and color is 24bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetRgb24BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned short wRLinePos = 0; unsigned short wGLinePos = 0; unsigned short wBLinePos = 0; SANE_Byte byRed; SANE_Byte byGreen; SANE_Byte byBlue; SANE_Byte bNextPixel = 0; unsigned short i; unsigned short tempR, tempG, tempB; DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: call in\n"); g_isCanceled = FALSE; g_isScanning = TRUE; wWantedTotalLines = *wLinesCount; DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: get wWantedTotalLines= %d\n", wWantedTotalLines); TotalXferLines = 0; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread create\n"); g_bFirstReadImage = FALSE; } if (!isOrderInvert) { DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: !isOrderInvert\n"); for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { wRLinePos = g_wtheReadyLines % g_wMaxScanLines; wGLinePos = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePos = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; for (i = 0; i < g_SWWidth; i++) { byRed = *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 3 + 0); bNextPixel = *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + (i + 1) * 3 + 0); byRed = (byRed + bNextPixel) >> 1; byGreen = *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 3 + 1); bNextPixel = *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + (i + 1) * 3 + 1); byGreen = (byGreen + bNextPixel) >> 1; byBlue = *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 3 + 2); bNextPixel = *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + (i + 1) * 3 + 2); byBlue = (byBlue + bNextPixel) >> 1; #ifdef ENABLE_GAMMA tempR = (unsigned short) ((byRed << 4) | QBET4 (byBlue, byGreen)); tempG = (unsigned short) ((byGreen << 4) | QBET4 (byRed, byBlue)); tempB = (unsigned short) ((byBlue << 4) | QBET4 (byGreen, byRed)); *(lpLine + i * 3 + 0) = (unsigned char) (*(g_pGammaTable + tempR)); *(lpLine + i * 3 + 1) = (unsigned char) (*(g_pGammaTable + 4096 + tempG)); *(lpLine + i * 3 + 2) = (unsigned char) (*(g_pGammaTable + 8192 + tempB)); #else *(lpLine + i * 3 + 0) = (unsigned char) byRed; *(lpLine + i * 3 + 1) = (unsigned char) byGreen; *(lpLine + i * 3 + 2) = (unsigned char) byBlue; #endif } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: g_dwTotalTotalXferLines=%d,g_SWHeight=%d\n", g_dwTotalTotalXferLines, g_SWHeight); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: g_SWBytesPerRow=%d\n", g_SWBytesPerRow); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n"); break; } } } else { DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: isOrderInvert is TRUE\n"); for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { wRLinePos = g_wtheReadyLines % g_wMaxScanLines; wGLinePos = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePos = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; for (i = 0; i < g_SWWidth; i++) { DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: before byRed\n"); byRed = *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 3 + 0); bNextPixel = *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + (i + 1) * 3 + 0); /*R-channel */ byRed = (byRed + bNextPixel) >> 1; DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: before byGreen\n"); byGreen = *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 3 + 1); bNextPixel = *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + (i + 1) * 3 + 1); /*G-channel */ byGreen = (byGreen + bNextPixel) >> 1; DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: before byBlue\n"); byBlue = *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 3 + 2); bNextPixel = *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + (i + 1) * 3 + 2); /*B-channel */ byBlue = (byBlue + bNextPixel) >> 1; DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: before set lpLine\n"); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: i=%d\n", i); #ifdef ENABLE_GAMMA *(lpLine + i * 3 + 2) = (unsigned char) (*(g_pGammaTable + (unsigned short) ((byRed << 4) | QBET4 (byBlue, byGreen)))); *(lpLine + i * 3 + 1) = (unsigned char) (*(g_pGammaTable + 4096 + (unsigned short) ((byGreen << 4) | QBET4 (byRed, byBlue)))); *(lpLine + i * 3 + 0) = (unsigned char) (*(g_pGammaTable + 8192 + (unsigned short) ((byBlue << 4) | QBET4 (byGreen, byRed)))); #else *(lpLine + i * 3 + 2) = (unsigned char) byRed; *(lpLine + i * 3 + 1) = (unsigned char) byGreen; *(lpLine + i * 3 + 0) = (unsigned char) byBlue; #endif } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: g_dwTotalTotalXferLines=%d,g_SWHeight=%d\n", g_dwTotalTotalXferLines, g_SWHeight); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: g_SWBytesPerRow=%d\n", g_SWBytesPerRow); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n"); break; } } /*end for */ } *wLinesCount = TotalXferLines; g_isScanning = FALSE; DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: leave MustScanner_GetRgb24BitLine\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when double CCD and color is 24bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetRgb24BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned short wRLinePosOdd = 0; unsigned short wGLinePosOdd = 0; unsigned short wBLinePosOdd = 0; unsigned short wRLinePosEven = 0; unsigned short wGLinePosEven = 0; unsigned short wBLinePosEven = 0; SANE_Byte byRed; SANE_Byte byGreen; SANE_Byte byBlue; SANE_Byte bNextPixel = 0; unsigned short i; DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: call in\n"); g_isCanceled = FALSE; g_isScanning = TRUE; TotalXferLines = 0; wWantedTotalLines = *wLinesCount; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: thread create\n"); g_bFirstReadImage = FALSE; } if (!isOrderInvert) { for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n", g_dwTotalTotalXferLines); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n", g_Height); pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { if (ST_Reflective == g_ScanType) { wRLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wGLinePosOdd = (g_wtheReadyLines - g_wLineDistance - g_wPixelDistance) % g_wMaxScanLines; wBLinePosOdd = (g_wtheReadyLines - g_wLineDistance * 2 - g_wPixelDistance) % g_wMaxScanLines; wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; wGLinePosEven = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePosEven = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; } else { wRLinePosEven = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wGLinePosEven = (g_wtheReadyLines - g_wLineDistance - g_wPixelDistance) % g_wMaxScanLines; wBLinePosEven = (g_wtheReadyLines - g_wLineDistance * 2 - g_wPixelDistance) % g_wMaxScanLines; wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines; wGLinePosOdd = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePosOdd = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; } for (i = 0; i < g_SWWidth;) { if ((i + 1) != g_SWWidth) { byRed = *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + i * 3 + 0); bNextPixel = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + (i + 1) * 3 + 0); /*R-channel */ byRed = (byRed + bNextPixel) >> 1; byGreen = *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + i * 3 + 1); bNextPixel = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + (i + 1) * 3 + 1); /*G-channel */ byGreen = (byGreen + bNextPixel) >> 1; byBlue = *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + i * 3 + 2); bNextPixel = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + (i + 1) * 3 + 2); /*B-channel */ byBlue = (byBlue + bNextPixel) >> 1; #ifdef ENABLE_GAMMA *(lpLine + i * 3 + 0) = (unsigned char) (*(g_pGammaTable + (unsigned short) ((byRed << 4) | QBET4 (byBlue, byGreen)))); *(lpLine + i * 3 + 1) = (unsigned char) (*(g_pGammaTable + 4096 + (unsigned short) ((byGreen << 4) | QBET4 (byRed, byBlue)))); *(lpLine + i * 3 + 2) = (unsigned char) (*(g_pGammaTable + 8192 + (unsigned short) ((byBlue << 4) | QBET4 (byGreen, byRed)))); #else *(lpLine + i * 3 + 0) = (unsigned char) byRed; *(lpLine + i * 3 + 1) = (unsigned char) byGreen; *(lpLine + i * 3 + 2) = (unsigned char) byBlue; #endif i++; if (i >= g_SWWidth) { break; } byRed = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + i * 3 + 0); bNextPixel = *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + (i + 1) * 3 + 0); byRed = (byRed + bNextPixel) >> 1; byGreen = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + i * 3 + 1); bNextPixel = *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + (i + 1) * 3 + 1); byGreen = (byGreen + bNextPixel) >> 1; byBlue = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + i * 3 + 2); bNextPixel = *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + (i + 1) * 3 + 2); byBlue = (byBlue + bNextPixel) >> 1; #ifdef ENABLE_GAMMA *(lpLine + i * 3 + 0) = (unsigned char) (*(g_pGammaTable + (unsigned short) ((byRed << 4) | QBET4 (byBlue, byGreen)))); *(lpLine + i * 3 + 1) = (unsigned char) (*(g_pGammaTable + 4096 + (unsigned short) ((byGreen << 4) | QBET4 (byRed, byBlue)))); *(lpLine + i * 3 + 2) = (unsigned char) (*(g_pGammaTable + 8192 + (unsigned short) ((byBlue << 4) | QBET4 (byGreen, byRed)))); #else *(lpLine + i * 3 + 0) = (unsigned char) byRed; *(lpLine + i * 3 + 1) = (unsigned char) byGreen; *(lpLine + i * 3 + 2) = (unsigned char) byBlue; #endif i++; } } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n", g_dwTotalTotalXferLines); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n", g_Height); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: thread exit\n"); break; } } } else { for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n", g_dwTotalTotalXferLines); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n", g_Height); pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { if (ST_Reflective == g_ScanType) { wRLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wGLinePosOdd = (g_wtheReadyLines - g_wLineDistance - g_wPixelDistance) % g_wMaxScanLines; wBLinePosOdd = (g_wtheReadyLines - g_wLineDistance * 2 - g_wPixelDistance) % g_wMaxScanLines; wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; wGLinePosEven = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePosEven = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; } else { wRLinePosEven = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wGLinePosEven = (g_wtheReadyLines - g_wLineDistance - g_wPixelDistance) % g_wMaxScanLines; wBLinePosEven = (g_wtheReadyLines - g_wLineDistance * 2 - g_wPixelDistance) % g_wMaxScanLines; wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines; wGLinePosOdd = (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines; wBLinePosOdd = (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines; } for (i = 0; i < g_SWWidth;) { if ((i + 1) != g_SWWidth) { byRed = *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + i * 3 + 0); bNextPixel = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + (i + 1) * 3 + 0); byRed = (byRed + bNextPixel) >> 1; byGreen = *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + i * 3 + 1); bNextPixel = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + (i + 1) * 3 + 1); byGreen = (byGreen + bNextPixel) >> 1; byBlue = *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + i * 3 + 2); bNextPixel = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + (i + 1) * 3 + 2); byBlue = (byBlue + bNextPixel) >> 1; #ifdef ENABLE_GAMMA *(lpLine + i * 3 + 2) = (unsigned char) (*(g_pGammaTable + (unsigned short) ((byRed << 4) | QBET4 (byBlue, byGreen)))); *(lpLine + i * 3 + 1) = (unsigned char) (*(g_pGammaTable + 4096 + (unsigned short) ((byGreen << 4) | QBET4 (byRed, byBlue)))); *(lpLine + i * 3 + 0) = (unsigned char) (*(g_pGammaTable + 8192 + (unsigned short) ((byBlue << 4) | QBET4 (byGreen, byRed)))); #else *(lpLine + i * 3 + 2) = (unsigned char) byRed; *(lpLine + i * 3 + 1) = (unsigned char) byGreen; *(lpLine + i * 3 + 0) = (unsigned char) byBlue; #endif i++; if (i >= g_SWWidth) { break; } byRed = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + i * 3 + 0); bNextPixel = *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow + (i + 1) * 3 + 0); byRed = (byRed + bNextPixel) >> 1; byGreen = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + i * 3 + 1); bNextPixel = *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow + (i + 1) * 3 + 1); byGreen = (byGreen + bNextPixel) >> 1; byBlue = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + i * 3 + 2); bNextPixel = *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow + (i + 1) * 3 + 2); byBlue = (byBlue + bNextPixel) >> 1; #ifdef ENABLE_GAMMA *(lpLine + i * 3 + 2) = (unsigned char) (*(g_pGammaTable + (unsigned short) ((byRed << 4) | QBET4 (byBlue, byGreen)))); *(lpLine + i * 3 + 1) = (unsigned char) (*(g_pGammaTable + 4096 + (unsigned short) ((byGreen << 4) | QBET4 (byRed, byBlue)))); *(lpLine + i * 3 + 0) = (unsigned char) (*(g_pGammaTable + 8192 + (unsigned short) ((byBlue << 4) | QBET4 (byGreen, byRed)))); #else *(lpLine + i * 3 + 2) = (unsigned char) byRed; *(lpLine + i * 3 + 1) = (unsigned char) byGreen; *(lpLine + i * 3 + 0) = (unsigned char) byBlue; #endif i++; } } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n", g_dwTotalTotalXferLines); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n", g_Height); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: thread exit\n"); break; } } } *wLinesCount = TotalXferLines; g_isScanning = FALSE; DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: leave MustScanner_GetRgb24BitLine1200DPI\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when single CCD and color is 16bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetMono16BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned int wTempData; unsigned short wLinePos = 0; unsigned short i; isOrderInvert = isOrderInvert; DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: call in\n"); TotalXferLines = 0; g_isCanceled = FALSE; g_isScanning = TRUE; wWantedTotalLines = *wLinesCount; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread create\n"); g_bFirstReadImage = FALSE; } for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { wLinePos = g_wtheReadyLines % g_wMaxScanLines; for (i = 0; i < g_SWWidth; i++) { wTempData = *(g_lpReadImageHead + wLinePos * g_BytesPerRow + i * 2 + 0); wTempData += *(g_lpReadImageHead + wLinePos * g_BytesPerRow + i * 2 + 1) << 8; *(lpLine + i * 2 + 0) = LOBYTE (g_pGammaTable[wTempData]); *(lpLine + i * 2 + 1) = HIBYTE (g_pGammaTable[wTempData]); } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread exit\n"); break; } } *wLinesCount = TotalXferLines; g_isScanning = FALSE; DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: leave MustScanner_GetMono16BitLine\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when double CCD and color is 16bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetMono16BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned int dwTempData; unsigned short wLinePosOdd = 0; unsigned short wLinePosEven = 0; unsigned short i; SANE_Byte * lpTemp = lpLine; isOrderInvert = isOrderInvert; DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: call in\n"); TotalXferLines = 0; g_isCanceled = FALSE; g_isScanning = TRUE; wWantedTotalLines = *wLinesCount; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: thread create\n"); g_bFirstReadImage = FALSE; } for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { if (ST_Reflective == g_ScanType) { wLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; } else { wLinePosEven = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines; } for (i = 0; i < g_SWWidth;) { if ((i + 1) != g_SWWidth) { dwTempData = (unsigned int) (* (g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + i * 2 + 0)); dwTempData += (unsigned int) (* (g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + i * 2 + 1) << 8); dwTempData += (unsigned int) (* (g_lpReadImageHead + wLinePosEven * g_BytesPerRow + (i + 1) * 2 + 0)); dwTempData += (unsigned int) (* (g_lpReadImageHead + wLinePosEven * g_BytesPerRow + (i + 1) * 2 + 1) << 8); dwTempData = g_pGammaTable[dwTempData >> 1]; *(lpLine + i * 2 + 0) = LOBYTE ((unsigned short) dwTempData); *(lpLine + i * 2 + 1) = HIBYTE ((unsigned short) dwTempData); i++; if (i >= g_SWWidth) { break; } dwTempData = (unsigned int) (* (g_lpReadImageHead + wLinePosEven * g_BytesPerRow + i * 2 + 0)); dwTempData += (unsigned int) (* (g_lpReadImageHead + wLinePosEven * g_BytesPerRow + i * 2 + 1) << 8); dwTempData += (unsigned int) (* (g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + (i + 1) * 2 + 0)); dwTempData += (unsigned int) (* (g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + (i + 1) * 2 + 1) << 8); dwTempData = g_pGammaTable[dwTempData >> 1]; *(lpLine + i * 2 + 0) = LOBYTE ((unsigned short) dwTempData); *(lpLine + i * 2 + 1) = HIBYTE ((unsigned short) dwTempData); i++; } } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: thread exit\n"); break; } } *wLinesCount = TotalXferLines; g_isScanning = FALSE; /*for modify the last point */ if (g_bIsFirstReadBefData) { g_lpBefLineImageData = (SANE_Byte *) malloc (g_SWBytesPerRow); if (NULL == g_lpBefLineImageData) { return FALSE; } memset (g_lpBefLineImageData, 0, g_SWBytesPerRow); memcpy (g_lpBefLineImageData, lpTemp, g_SWBytesPerRow); g_bIsFirstReadBefData = FALSE; } ModifyLinePoint (lpTemp, g_lpBefLineImageData, g_SWBytesPerRow, wWantedTotalLines, 2, 4); memcpy (g_lpBefLineImageData, lpTemp + (wWantedTotalLines - 1) * g_SWBytesPerRow, g_SWBytesPerRow); g_dwAlreadyGetLines += wWantedTotalLines; if (g_dwAlreadyGetLines >= g_SWHeight) { DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: free before line data!\n"); free (g_lpBefLineImageData); g_lpBefLineImageData = NULL; g_dwAlreadyGetLines = 0; g_bIsFirstReadBefData = TRUE; } DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: leave MustScanner_GetMono16BitLine1200DPI\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when single CCD and color is 8bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetMono8BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned short i; unsigned short wLinePos = 0; isOrderInvert = isOrderInvert; DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: call in\n"); TotalXferLines = 0; g_isCanceled = FALSE; g_isScanning = TRUE; wWantedTotalLines = *wLinesCount; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread create\n"); g_bFirstReadImage = FALSE; } for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { wLinePos = g_wtheReadyLines % g_wMaxScanLines; for (i = 0; i < g_SWWidth; i++) { *(lpLine + i) = (SANE_Byte) * (g_pGammaTable + (unsigned short) ((* (g_lpReadImageHead + wLinePos * g_BytesPerRow + i) << 4) | (rand () & 0x0f))); } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread exit\n"); break; } } *wLinesCount = TotalXferLines; g_isScanning = FALSE; DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: leave MustScanner_GetMono8BitLine\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when double CCD and color is 8bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetMono8BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { SANE_Byte *lpTemp; unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned short wLinePosOdd = 0; unsigned short wLinePosEven = 0; SANE_Byte byGray; unsigned short i; SANE_Byte bNextPixel = 0; isOrderInvert = isOrderInvert; DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: call in\n"); TotalXferLines = 0; g_isCanceled = FALSE; g_isScanning = TRUE; wWantedTotalLines = *wLinesCount; lpTemp = lpLine; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread create\n"); g_bFirstReadImage = FALSE; } for (; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { if (ST_Reflective == g_ScanType) { wLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; } else { wLinePosEven = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines; } for (i = 0; i < g_SWWidth;) { if ((i + 1) != g_SWWidth) { byGray = *(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + i); bNextPixel = *(g_lpReadImageHead + wLinePosEven * g_BytesPerRow + (i + 1)); byGray = (byGray + bNextPixel) >> 1; *(lpLine + i) = (SANE_Byte) * (g_pGammaTable + (byGray << 4 | (rand () & 0x0f))); i++; if (i >= g_SWWidth) { break; } byGray = *(g_lpReadImageHead + wLinePosEven * g_BytesPerRow + i); bNextPixel = *(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + (i + 1)); byGray = (byGray + bNextPixel) >> 1; *(lpLine + i) = (SANE_Byte) * (g_pGammaTable + (byGray << 4 | (rand () & 0x0f))); i++; } } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread exit\n"); break; } } *wLinesCount = TotalXferLines; g_isScanning = FALSE; /*for modify the last point */ if (g_bIsFirstReadBefData) { g_lpBefLineImageData = (SANE_Byte *) malloc (g_SWBytesPerRow); if (NULL == g_lpBefLineImageData) { return FALSE; } memset (g_lpBefLineImageData, 0, g_SWBytesPerRow); memcpy (g_lpBefLineImageData, lpTemp, g_SWBytesPerRow); g_bIsFirstReadBefData = FALSE; } ModifyLinePoint (lpTemp, g_lpBefLineImageData, g_SWBytesPerRow, wWantedTotalLines, 1, 4); memcpy (g_lpBefLineImageData, lpTemp + (wWantedTotalLines - 1) * g_SWBytesPerRow, g_SWBytesPerRow); g_dwAlreadyGetLines += wWantedTotalLines; if (g_dwAlreadyGetLines >= g_SWHeight) { DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: free the before line data!\n"); free (g_lpBefLineImageData); g_lpBefLineImageData = NULL; g_dwAlreadyGetLines = 0; g_bIsFirstReadBefData = TRUE; } DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: leave MustScanner_GetMono8BitLine1200DPI\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when single CCD and color is 1bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetMono1BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned short wLinePos; unsigned short i; isOrderInvert = isOrderInvert; DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: call in\n"); g_isCanceled = FALSE; g_isScanning = TRUE; wWantedTotalLines = *wLinesCount; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread create\n"); g_bFirstReadImage = FALSE; } memset (lpLine, 0, wWantedTotalLines * g_SWWidth / 8); for (TotalXferLines = 0; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { wLinePos = g_wtheReadyLines % g_wMaxScanLines; for (i = 0; i < g_SWWidth; i++) { if (*(g_lpReadImageHead + wLinePos * g_BytesPerRow + i) > g_wLineartThreshold) { *(lpLine + i / 8) += (0x80 >> (i % 8)); } } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += (g_SWBytesPerRow / 8); AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread exit\n"); break; } } *wLinesCount = TotalXferLines; g_isScanning = FALSE; DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: leave MustScanner_GetMono1BitLine\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Repair line when double CCD and color is 1bit Parameters: lpLine: point to image be repaired isOrderInvert: RGB or BGR wLinesCount: how many line be repaired Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool MustScanner_GetMono1BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert, unsigned short * wLinesCount) { unsigned short wWantedTotalLines; unsigned short TotalXferLines; unsigned short i; unsigned short wLinePosOdd; unsigned short wLinePosEven; isOrderInvert = isOrderInvert; DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: call in\n"); g_isCanceled = FALSE; g_isScanning = TRUE; wWantedTotalLines = *wLinesCount; if (g_bFirstReadImage) { pthread_create (&g_threadid_readimage, NULL, MustScanner_ReadDataFromScanner, NULL); DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread create\n"); g_bFirstReadImage = FALSE; } memset (lpLine, 0, wWantedTotalLines * g_SWWidth / 8); for (TotalXferLines = 0; TotalXferLines < wWantedTotalLines;) { if (g_dwTotalTotalXferLines >= g_SWHeight) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread exit\n"); *wLinesCount = TotalXferLines; g_isScanning = FALSE; return TRUE; } if (GetScannedLines () > g_wtheReadyLines) { if (ST_Reflective == g_ScanType) { wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; wLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; } else { wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines; wLinePosEven = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; } for (i = 0; i < g_SWWidth;) { if ((i + 1) != g_SWWidth) { if (*(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + i) > g_wLineartThreshold) *(lpLine + i / 8) += (0x80 >> (i % 8)); i++; if (i >= g_SWWidth) { break; } if (*(g_lpReadImageHead + wLinePosEven * g_BytesPerRow + i) > g_wLineartThreshold) *(lpLine + i / 8) += (0x80 >> (i % 8)); i++; } } TotalXferLines++; g_dwTotalTotalXferLines++; lpLine += g_SWBytesPerRow / 8; AddReadyLines (); } if (g_isCanceled) { pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread exit\n"); break; } } /*end for */ *wLinesCount = TotalXferLines; g_isScanning = FALSE; DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: leave MustScanner_GetMono1BitLine1200DPI\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/21 Routine Description: prepare calculate Max and Min value Parameters: wResolution: the scan resolution Return value: none ***********************************************************************/ static void MustScanner_PrepareCalculateMaxMin (unsigned short wResolution) { g_wDarkCalWidth = 52; if (wResolution <= 600) { g_wCalWidth = ((5120 * wResolution / 600 + 511) >> 9) << 9; g_wDarkCalWidth = g_wDarkCalWidth / (1200 / wResolution); if (wResolution < 200) { g_nPowerNum = 3; g_nSecLength = 8; /* 2^nPowerNum */ g_nDarkSecLength = g_wDarkCalWidth / 2; /* Dark has at least 2 sections */ } else { g_nPowerNum = 6; g_nSecLength = 64; /* 2^nPowerNum */ g_nDarkSecLength = g_wDarkCalWidth / 3; } } else { g_nPowerNum = 6; g_nSecLength = 64; /*2^nPowerNum */ g_wCalWidth = 10240; g_nDarkSecLength = g_wDarkCalWidth / 5; } if (g_nDarkSecLength <= 0) { g_nDarkSecLength = 1; } g_wStartPosition = 13 * wResolution / 1200; g_wCalWidth -= g_wStartPosition; /* start of find Max value */ g_nSecNum = (int) (g_wCalWidth / g_nSecLength); /* start of fin min value */ g_nDarkSecNum = (int) (g_wDarkCalWidth / g_nDarkSecLength); } /********************************************************************** Author: Jack Date: 2005/05/21 Routine Description: calculate the Max and Min value Parameters: pBuffer: the image data lpMaxValue: the max value lpMinValue: the min value wResolution: the scan resolution Return value: none ***********************************************************************/ static void MustScanner_CalculateMaxMin (SANE_Byte * pBuffer, unsigned short * lpMaxValue, unsigned short * lpMinValue, unsigned short wResolution) { unsigned short *wSecData = NULL, *wDarkSecData = NULL; int i, j; wResolution = wResolution; wSecData = (unsigned short *) malloc (sizeof (unsigned short) * g_nSecNum); if (wSecData == NULL) { return; } else { memset (wSecData, 0, g_nSecNum * sizeof (unsigned short)); } for (i = 0; i < g_nSecNum; i++) { for (j = 0; j < g_nSecLength; j++) wSecData[i] += *(pBuffer + g_wStartPosition + i * g_nSecLength + j); wSecData[i] >>= g_nPowerNum; } *lpMaxValue = wSecData[0]; for (i = 0; i < g_nSecNum; i++) { if (*lpMaxValue < wSecData[i]) *lpMaxValue = wSecData[i]; } free (wSecData); wDarkSecData = (unsigned short *) malloc (sizeof (unsigned short) * g_nDarkSecNum); if (wDarkSecData == NULL) { return; } else { memset (wDarkSecData, 0, g_nDarkSecNum * sizeof (unsigned short)); } for (i = 0; i < g_nDarkSecNum; i++) { for (j = 0; j < g_nDarkSecLength; j++) wDarkSecData[i] += *(pBuffer + g_wStartPosition + i * g_nDarkSecLength + j); wDarkSecData[i] /= g_nDarkSecLength; } *lpMinValue = wDarkSecData[0]; for (i = 0; i < g_nDarkSecNum; i++) { if (*lpMinValue > wDarkSecData[i]) *lpMinValue = wDarkSecData[i]; } free (wDarkSecData); } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Read the data from scanner Parameters: none Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static void * MustScanner_ReadDataFromScanner (void * dummy) { unsigned short wTotalReadImageLines = 0; unsigned short wWantedLines = g_Height; SANE_Byte * lpReadImage = g_lpReadImageHead; SANE_Bool isWaitImageLineDiff = FALSE; unsigned int wMaxScanLines = g_wMaxScanLines; unsigned short wReadImageLines = 0; unsigned short wScanLinesThisBlock; unsigned short wBufferLines = g_wLineDistance * 2 + g_wPixelDistance; dummy = dummy; DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: call in, and in new thread\n"); while (wTotalReadImageLines < wWantedLines && g_lpReadImageHead) { if (!isWaitImageLineDiff) { wScanLinesThisBlock = (wWantedLines - wTotalReadImageLines) < g_wScanLinesPerBlock ? (wWantedLines - wTotalReadImageLines) : g_wScanLinesPerBlock; DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: wWantedLines=%d\n", wWantedLines); DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: wScanLinesThisBlock=%d\n", wScanLinesThisBlock); if (STATUS_GOOD != Asic_ReadImage (&g_chip, lpReadImage, wScanLinesThisBlock)) { DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner:Asic_ReadImage return error\n"); DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner:thread exit\n"); return NULL; } /*has read in memroy Buffer */ wReadImageLines += wScanLinesThisBlock; AddScannedLines (wScanLinesThisBlock); wTotalReadImageLines += wScanLinesThisBlock; lpReadImage += wScanLinesThisBlock * g_BytesPerRow; /*Buffer is full */ if (wReadImageLines >= wMaxScanLines) { lpReadImage = g_lpReadImageHead; wReadImageLines = 0; } if ((g_dwScannedTotalLines - GetReadyLines ()) >= (wMaxScanLines - (wBufferLines + g_wScanLinesPerBlock)) && g_dwScannedTotalLines > GetReadyLines ()) { isWaitImageLineDiff = TRUE; } } else if (g_dwScannedTotalLines <= GetReadyLines () + wBufferLines + g_wScanLinesPerBlock) { isWaitImageLineDiff = FALSE; } pthread_testcancel (); } DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: Read image ok\n"); DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: thread exit\n"); DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: leave MustScanner_ReadDataFromScanner\n"); return NULL; } /********************************************************************** Author: Jack Date: 2005/05/26 Routine Description: get the lines of scanned Parameters: none Return value: the lines of scanned ***********************************************************************/ static unsigned int GetScannedLines () { unsigned int dwScannedLines = 0; pthread_mutex_lock (&g_scannedLinesMutex); dwScannedLines = g_dwScannedTotalLines; pthread_mutex_unlock (&g_scannedLinesMutex); return dwScannedLines; } /********************************************************************** Author: Jack Date: 2005/05/26 Routine Description: get lines which pass to superstratum Parameters: none Return value: the lines which pass to superstratum ***********************************************************************/ static unsigned int GetReadyLines () { unsigned int dwReadyLines = 0; pthread_mutex_lock (&g_readyLinesMutex); dwReadyLines = g_wtheReadyLines; pthread_mutex_unlock (&g_readyLinesMutex); return dwReadyLines; } /********************************************************************** Author: Jack Date: 2005/05/26 Routine Description: add the scanned total lines Parameters: wAddLines: add the lines Return value: none ***********************************************************************/ static void AddScannedLines (unsigned short wAddLines) { pthread_mutex_lock (&g_scannedLinesMutex); g_dwScannedTotalLines += wAddLines; pthread_mutex_unlock (&g_scannedLinesMutex); } /********************************************************************** Author: Jack Date: 2005/05/26 Routine Description: add the ready lines Parameters: none Return value: none ***********************************************************************/ static void AddReadyLines () { pthread_mutex_lock (&g_readyLinesMutex); g_wtheReadyLines++; pthread_mutex_unlock (&g_readyLinesMutex); } /********************************************************************** Author: Jack Date: 2005/05/26 Routine Description: modify the point Parameters: lpImageData: the data of image lpImageDataBefore: the data of before line image dwBytesPerLine: the bytes of per line dwLinesCount: the line count wPixDistance: the pixel distance wModPtCount: the modify point count Return value: none ***********************************************************************/ static void ModifyLinePoint (SANE_Byte * lpImageData, SANE_Byte * lpImageDataBefore, unsigned int dwBytesPerLine, unsigned int dwLinesCount, unsigned short wPixDistance, unsigned short wModPtCount) { unsigned short i = 0; unsigned short j = 0; unsigned short wLines = 0; unsigned int dwWidth = dwBytesPerLine / wPixDistance; for (i = wModPtCount; i > 0; i--) { for (j = 0; j < wPixDistance; j++) { /*modify the first line */ *(lpImageData + (dwWidth - i) * wPixDistance + j) = (*(lpImageData + (dwWidth - i - 1) * wPixDistance + j) + *(lpImageDataBefore + (dwWidth - i) * wPixDistance + j)) / 2; /*modify other lines */ for (wLines = 1; wLines < dwLinesCount; wLines++) { unsigned int dwBytesBefor = (wLines - 1) * dwBytesPerLine; unsigned int dwBytes = wLines * dwBytesPerLine; *(lpImageData + dwBytes + (dwWidth - i) * wPixDistance + j) = (* (lpImageData + dwBytes + (dwWidth - i - 1) * wPixDistance + j) + *(lpImageData + dwBytesBefor + (dwWidth - i) * wPixDistance + j)) / 2; } } } } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Modifiy the image data Parameters: A: the input the image data B: the input the iamge data Return value: the modified data ***********************************************************************/ static SANE_Byte QBET4 (SANE_Byte A, SANE_Byte B) { SANE_Byte bQBET[16][16] = { {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9}, {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9}, {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9}, {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9}, {1, 1, 1, 1, 3, 3, 3, 3, 6, 6, 6, 6, 10, 10, 11, 11}, {1, 1, 1, 1, 3, 3, 3, 3, 6, 6, 6, 6, 10, 10, 11, 11}, {2, 2, 2, 2, 3, 3, 3, 3, 7, 7, 7, 7, 10, 10, 11, 11}, {2, 2, 2, 2, 3, 3, 3, 3, 7, 7, 7, 7, 10, 10, 11, 11}, {4, 4, 4, 4, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14}, {4, 4, 4, 4, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14}, {5, 5, 5, 5, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14}, {5, 5, 5, 5, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14}, {8, 8, 8, 8, 10, 10, 10, 10, 13, 13, 13, 13, 15, 15, 15, 15}, {8, 8, 8, 8, 10, 10, 10, 10, 13, 13, 13, 13, 15, 15, 15, 15}, {9, 9, 9, 9, 11, 11, 11, 11, 14, 14, 14, 14, 15, 15, 15, 15}, {9, 9, 9, 9, 11, 11, 11, 11, 14, 14, 14, 14, 15, 15, 15, 15} }; A = A & 0x0f; B = B & 0x0f; return bQBET[A][B]; } /* end of the file MustScanner.c */ sane-backends-1.0.27/backend/niash_core.c0000664000175000017500000010413612775312261015102 00000000000000/* Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. $Id$ */ /* Core NIASH chip functions. */ #include /* fopen, fread, fwrite, fclose etc */ #include /* va_list for vfprintf */ #include /* memcpy, memset */ #include /* unlink */ #include /* malloc, free */ #include /* exp, pow */ #include "niash_xfer.h" #include "niash_core.h" #ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #endif #define XFER_BUF_SIZE 0xF000 /* HP3400 firmware data */ static unsigned char abData0000[] = { 0xfe, 0x9f, 0x58, 0x1b, 0x00, 0x03, 0xa4, 0x02, 0x63, 0x02, 0x33, 0x02, 0x0d, 0x02, 0xf0, 0x01, 0xd8, 0x01, 0xc5, 0x01, 0xb5, 0x01, 0xa8, 0x01, 0x9d, 0x01, 0x93, 0x01, 0x8b, 0x01, 0x84, 0x01, 0x7e, 0x01, 0x79, 0x01, 0x74, 0x01, 0x70, 0x01, 0x6d, 0x01, 0x69, 0x01, 0x67, 0x01, 0x64, 0x01, 0x62, 0x01, 0x60, 0x01, 0x5f, 0x01, 0x5d, 0x01, 0x5c, 0x01, 0x5b, 0x01, 0x5a, 0x01, 0x59, 0x01, 0x58, 0x01, 0x57, 0x01, 0x57, 0x01, 0x56, 0x01, 0x56, 0x01, 0x55, 0x01, 0x55, 0x01, 0x54, 0x01, 0x54, 0x01, 0x54, 0x01, 0x54, 0x01, 0x53, 0x01, 0x53, 0x01, 0x53, 0x01, 0x53, 0x01, 0x52, 0x81 }; /* 1st word : 0x9ffe = 40958, strip 15th bit: 0x1ffe = 8190 2nd word : 0x1b58 = 7000 -> coincidence ? other words: formula: y = 676 / (2 - exp(0.113 * (1-x)) ), where x = 0 for first entry */ /* more HP3400 firmware data */ static unsigned char abData0400[] = { 0xa4, 0x82, 0x00, 0x80, 0xa4, 0x82, 0xaa, 0x02, 0xc0, 0x02, 0xe8, 0x02, 0x3e, 0x03, 0xc8, 0x03, 0x58, 0x1b, 0xfe, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static void _ConvertMotorTable (unsigned char *pabOld, unsigned char *pabNew, int iSize, int iLpi) { int iData, i, iBit15; for (i = 0; i < (iSize / 2); i++) { iData = pabOld[2 * i + 0] + (pabOld[2 * i + 1] << 8); iBit15 = (iData & 0x8000); iData = (iData & 0x7FFF); if (iData <= 0x400) { iData = iData * iLpi / 300; } if (iBit15 != 0) { iData |= 0x8000; } pabNew[2 * i + 0] = iData & 255; pabNew[2 * i + 1] = (iData >> 8) & 255; } } /************************************************************************* _ProbeRegisters =============== Tries to determine certain hardware properties. This is done by checking the writeability of some scanner registers. We cannot rely simply on the scanner model to contain a specific chip. The HP3300c for example uses one of at least three slightly different scanner ASICs (NIASH00012, NIASH00013 and NIASH00014). OUT pHWParams Hardware parameters, updated fields: fGamma16 TRUE if 16 bit gamma tables can be used fReg07 TRUE if reg07 is writeable iBufferSize Size of scanner's internal buffer Returns TRUE if a NIASH chipset was found. *************************************************************************/ static SANE_Bool _ProbeRegisters (THWParams * pHWParams) { unsigned char bData1, bData2; int iHandle; iHandle = pHWParams->iXferHandle; DBG (DBG_MSG, "Probing scanner...\n"); /* check register 0x04 */ NiashWriteReg (iHandle, 0x04, 0x55); NiashReadReg (iHandle, 0x04, &bData1); NiashWriteReg (iHandle, 0x04, 0xAA); NiashReadReg (iHandle, 0x04, &bData2); NiashWriteReg (iHandle, 0x04, 0x07); if ((bData1 != 0x55) || (bData2 != 0xAA)) { DBG (DBG_ERR, " No NIASH chipset found!\n"); return SANE_FALSE; } /* check writeability of register 3 bit 1 */ NiashReadReg (iHandle, 0x03, &bData1); NiashWriteReg (iHandle, 0x03, bData1 | 0x02); NiashReadReg (iHandle, 0x03, &bData2); NiashWriteReg (iHandle, 0x03, bData1); pHWParams->fGamma16 = ((bData2 & 0x02) != 0); DBG (DBG_MSG, " Gamma table entries are %d bit\n", pHWParams->fGamma16 ? 16 : 8); /* check register 0x07 */ NiashReadReg (iHandle, 0x07, &bData1); NiashWriteReg (iHandle, 0x07, 0x1C); NiashReadReg (iHandle, 0x07, &bData2); NiashWriteReg (iHandle, 0x07, bData1); pHWParams->fReg07 = (bData2 == 0x1C); if (!pHWParams->fGamma16) { /* internal scan buffer size is an educated guess, but seems to correlate well with the size calculated from several windows driver log files size = 128kB - 44088 unsigned chars (space required for gamma/calibration table) */ pHWParams->iBufferSize = 86984L; DBG (DBG_MSG, " NIASH version < 00014\n"); } else { pHWParams->iBufferSize = 0x60000L; if (!pHWParams->fReg07) { DBG (DBG_MSG, " NIASH version = 00014\n"); } else { DBG (DBG_MSG, " NIASH version > 00014\n"); } } return SANE_TRUE; } /* returns 0 on success, < 0 otherwise */ STATIC int NiashOpen (THWParams * pHWParams, const char *pszName) { int iXferHandle; iXferHandle = NiashXferOpen (pszName, &pHWParams->eModel); if (iXferHandle < 0) { DBG (DBG_ERR, "NiashXferOpen failed for '%s'\n", pszName); return -1; } pHWParams->iXferHandle = iXferHandle; NiashWakeup (pHWParams->iXferHandle); /* default HW params */ pHWParams->iSensorSkew = 8; pHWParams->iTopLeftX = 0; pHWParams->iTopLeftY = 3; pHWParams->fReg07 = SANE_FALSE; pHWParams->iSkipLines = 0; pHWParams->iExpTime = 5408; pHWParams->iReversedHead = SANE_TRUE; switch (pHWParams->eModel) { case eHp3300c: DBG (DBG_MSG, "Setting params for Hp3300\n"); pHWParams->iTopLeftX = 4; pHWParams->iTopLeftY = 11; pHWParams->iSkipLines = 14; break; case eHp3400c: case eHp4300c: DBG (DBG_MSG, "Setting params for Hp3400c/Hp4300c\n"); pHWParams->iTopLeftX = 3; pHWParams->iTopLeftY = 14; pHWParams->fReg07 = SANE_TRUE; break; case eAgfaTouch: DBG (DBG_MSG, "Setting params for AgfaTouch\n"); pHWParams->iReversedHead = SANE_FALSE; /* head not reversed on Agfa Touch */ pHWParams->iTopLeftX = 3; pHWParams->iTopLeftY = 10; pHWParams->iSkipLines = 7; break; case eUnknownModel: DBG (DBG_MSG, "Setting params for UnknownModel\n"); break; default: DBG (DBG_ERR, "ERROR: internal error! (%d)\n", (int) pHWParams->eModel); return -1; } /* autodetect some hardware properties */ if (!_ProbeRegisters (pHWParams)) { DBG (DBG_ERR, "_ProbeRegisters failed!\n"); return -1; } return 0; } STATIC void NiashClose (THWParams * pHWPar) { NiashXferClose (pHWPar->iXferHandle); pHWPar->iXferHandle = 0; } static void WriteRegWord (int iHandle, unsigned char bReg, SANE_Word wData) { NiashWriteReg (iHandle, bReg, wData & 0xFF); NiashWriteReg (iHandle, bReg + 1, (wData >> 8) & 0xFF); } /* calculate a 4096 unsigned char gamma table */ STATIC void CalcGamma (unsigned char *pabTable, double Gamma) { int i, iData; /* fill gamma table */ for (i = 0; i < 4096; i++) { iData = floor (256.0 * pow (((double) i / 4096.0), 1.0 / Gamma)); pabTable[i] = iData; } } /* Hp3400WriteFw ============= Writes data to scanners with a NIASH00019 chipset, e.g. gamma, calibration and motor control data. IN pabData pointer to firmware data iLen Size of firmware date (unsigned chars) iAddr Scanner address to write to */ static void Hp3400cWriteFW (int iXferHandle, unsigned char *pabData, int iLen, int iAddr) { iAddr--; NiashWriteReg (iXferHandle, 0x21, iAddr & 0xFF); NiashWriteReg (iXferHandle, 0x22, (iAddr >> 8) & 0xFF); NiashWriteReg (iXferHandle, 0x23, (iAddr >> 16) & 0xFF); NiashWriteBulk (iXferHandle, pabData, iLen); } /* Writes the gamma and offset/gain tables to the scanner. In case a calibration file exist, it will be used for offset/gain */ STATIC void WriteGammaCalibTable (unsigned char *pabGammaR, unsigned char *pabGammaG, unsigned char *pabGammaB, unsigned char *pabCalibTable, int iGain, int iOffset, THWParams * pHWPar) { int i, j, k; static unsigned char abGamma[60000]; int iData; int iHandle; iHandle = pHWPar->iXferHandle; j = 0; /* fill gamma table for red component */ /* pad entries with 0 for 16-bit gamma table */ for (i = 0; i < 4096; i++) { if (pHWPar->fGamma16) { abGamma[j++] = 0; } abGamma[j++] = pabGammaR[i]; } /* fill gamma table for green component */ for (i = 0; i < 4096; i++) { if (pHWPar->fGamma16) { abGamma[j++] = 0; } abGamma[j++] = pabGammaG[i]; } /* fill gamma table for blue component */ for (i = 0; i < 4096; i++) { if (pHWPar->fGamma16) { abGamma[j++] = 0; } abGamma[j++] = pabGammaB[i]; } if (pabCalibTable == NULL) { iData = (iGain << 6) + iOffset; for (i = 0; i < HW_PIXELS; i++) { for (k = 0; k < 3; k++) { abGamma[j++] = (iData) & 255; abGamma[j++] = (iData >> 8) & 255; } } } else { memcpy (&abGamma[j], pabCalibTable, HW_PIXELS * 6); j += HW_PIXELS * 6; } NiashWriteReg (iHandle, 0x02, 0x80); NiashWriteReg (iHandle, 0x03, 0x01); NiashWriteReg (iHandle, 0x03, 0x11); NiashWriteReg (iHandle, 0x02, 0x84); if (pHWPar->fReg07) { Hp3400cWriteFW (iHandle, abGamma, j, 0x2000); } else { NiashWriteBulk (iHandle, abGamma, j); } NiashWriteReg (iHandle, 0x02, 0x80); } static void WriteAFEReg (int iHandle, int iReg, int iData) { NiashWriteReg (iHandle, 0x25, iReg); NiashWriteReg (iHandle, 0x26, iData); } /* setup the analog front-end -> coarse calibration */ static void WriteAFE (int iHandle) { /* see WM8143 datasheet */ WriteAFEReg (iHandle, 0x04, 0x00); WriteAFEReg (iHandle, 0x03, 0x12); WriteAFEReg (iHandle, 0x02, 0x04); WriteAFEReg (iHandle, 0x05, 0x10); WriteAFEReg (iHandle, 0x01, 0x03); WriteAFEReg (iHandle, 0x20, 0xc0); /*c8 *//* red offset */ WriteAFEReg (iHandle, 0x21, 0xc0); /*c8 *//* green offset */ WriteAFEReg (iHandle, 0x22, 0xc0); /*d0 *//* blue offset */ WriteAFEReg (iHandle, 0x28, 0x05); /*5 *//* red gain */ WriteAFEReg (iHandle, 0x29, 0x03); /*3 *//* green gain */ WriteAFEReg (iHandle, 0x2A, 0x04); /*4 *//* blue gain */ } /* wait for the carriage to return */ static void WaitReadyBit (int iHandle) { unsigned char bData; do { NiashReadReg (iHandle, 0x03, &bData); } while ((bData & 8) == 0); } /* Initialisation specific for NIASH00014 and lower chips */ static void InitNiash00014 (TScanParams * pParams, THWParams * pHWParams) { int iHandle, iLpiCode; iHandle = pHWParams->iXferHandle; /* exposure time (in units 24/Fcrystal)? */ WriteRegWord (iHandle, 0x08, pHWParams->iExpTime - 1); /* width in pixels */ WriteRegWord (iHandle, 0x12, pParams->iWidth - 1); /* top */ WriteRegWord (iHandle, 0x17, pParams->iTop); WriteRegWord (iHandle, 0x19, pParams->iTop); /* time between stepper motor steps (in units of 24/Fcrystal)? */ iLpiCode = pParams->iLpi * pHWParams->iExpTime / 1200L; if (!pHWParams->fGamma16) { /* NIASH 00012 / 00013 init */ /* LPI specific settings */ if (pParams->iLpi < 600) { /* set halfres bit */ NiashWriteReg (iHandle, 0x06, 0x01); /* double lpi code because of halfres bit */ iLpiCode *= 2; } else { /* clear halfres bit */ NiashWriteReg (iHandle, 0x06, 0x00); /* add exptime to make it scan slower */ iLpiCode += pHWParams->iExpTime; } /* unknown setting */ WriteRegWord (iHandle, 0x27, 0x7FD2); WriteRegWord (iHandle, 0x29, 0x6421); } else { /* NIASH 00014 init */ /* halfres bit always cleared */ NiashWriteReg (iHandle, 0x06, 0x00); /* LPI specific settings */ if (pParams->iLpi >= 600) { /* add exptime to make it scan slower */ iLpiCode += pHWParams->iExpTime; } /* unknown setting */ WriteRegWord (iHandle, 0x27, 0xc862); /*c862 */ WriteRegWord (iHandle, 0x29, 0xb853); /*b853 */ } /* LPI code */ WriteRegWord (iHandle, 0x0A, iLpiCode - 1); /* backtrack reversing speed */ NiashWriteReg (iHandle, 0x1E, (iLpiCode - 1) / 32); } /* Initialisation specific for NIASH00019 chips */ static void InitNiash00019 (TScanParams * pParams, THWParams * pHWParams) { int iHandle, iLpiCode; static unsigned char abMotor[512]; iHandle = pHWParams->iXferHandle; /* exposure time (in units 24/Fcrystal)? */ WriteRegWord (iHandle, 0x08, pHWParams->iExpTime); /* width in pixels */ WriteRegWord (iHandle, 0x12, pParams->iWidth); /* ? */ WriteRegWord (iHandle, 0x27, 0xc862); /*c862 */ WriteRegWord (iHandle, 0x29, 0xb853); /*b853 */ /* specific handling of 150 dpi resolution */ if (pParams->iLpi == 150) { /* use 300 LPI but skip every other line */ pParams->iLpi = 300; NiashWriteReg (iHandle, 0x06, 0x01); } else { NiashWriteReg (iHandle, 0x06, 0x00); } /* DPI and position table */ NiashWriteReg (iHandle, 0x07, 0x02); _ConvertMotorTable (abData0000, abMotor, sizeof (abData0000), pParams->iLpi); Hp3400cWriteFW (iHandle, abMotor, sizeof (abData0000), 0x000); _ConvertMotorTable (abData0400, abMotor, sizeof (abData0400), pParams->iLpi); Hp3400cWriteFW (iHandle, abMotor, sizeof (abData0400), 0x400); /* backtrack reversing speed */ iLpiCode = pParams->iLpi * pHWParams->iExpTime / 1200L; NiashWriteReg (iHandle, 0x1E, (iLpiCode - 1) / 32); } /* Scanner initialisation common to all NIASH chips */ static void InitNiashCommon (TScanParams * pParams, THWParams * pHWParams) { int iWidthHW, iHandle, iMaxLevel; iHandle = pHWParams->iXferHandle; NiashWriteReg (iHandle, 0x02, 0x80); NiashWriteReg (iHandle, 0x03, 0x11); NiashWriteReg (iHandle, 0x01, 0x8B); NiashWriteReg (iHandle, 0x05, 0x01); /* dpi */ WriteRegWord (iHandle, 0x0C, pParams->iDpi); /* calculate width in units of HW resolution */ iWidthHW = pParams->iWidth * (HW_DPI / pParams->iDpi); /* set left and right limits */ if (pHWParams->iReversedHead) { /* head is reversed */ /* right */ WriteRegWord (iHandle, 0x0E, 3 * (HW_PIXELS - (pParams->iLeft + iWidthHW))); /* left */ WriteRegWord (iHandle, 0x10, 3 * (HW_PIXELS - pParams->iLeft) - 1); } else { /* head is not reversed */ /*left */ WriteRegWord (iHandle, 0x0E, 3 * pParams->iLeft); /* right */ WriteRegWord (iHandle, 0x10, 3 * (pParams->iLeft + iWidthHW) - 1); } /* bottom */ WriteRegWord (iHandle, 0x1B, pParams->iBottom); /* 0x393C); */ /* forward jogging speed */ NiashWriteReg (iHandle, 0x1D, 0x60); /* backtrack reversing speed? */ NiashWriteReg (iHandle, 0x2B, 0x15); /* backtrack distance */ if (pParams->iLpi < 600) { NiashWriteReg (iHandle, 0x1F, 0x30); } else { NiashWriteReg (iHandle, 0x1F, 0x18); } /* max buffer level before backtrace */ iMaxLevel = MIN (pHWParams->iBufferSize / pParams->iWidth, 250); NiashWriteReg (iHandle, 0x14, iMaxLevel - 1); /* lamp PWM, max = 0x1ff? */ WriteRegWord (iHandle, 0x2C, 0x01FF); /* not needed? */ NiashWriteReg (iHandle, 0x15, 0x90); /* 90 */ NiashWriteReg (iHandle, 0x16, 0x70); /* 70 */ WriteAFE (iHandle); WaitReadyBit (iHandle); NiashWriteReg (iHandle, 0x03, 0x05); NiashWriteReg (iHandle, 0x02, pParams->fCalib ? 0x88 : 0xA8); } /* write registers */ STATIC SANE_Bool InitScan (TScanParams * pParams, THWParams * pHWParams) { int iHeight; int iExpTime; TScanParams Params; /* check validity of scanparameters */ switch (pParams->iDpi) { case 150: case 300: case 600: break; default: DBG (DBG_ERR, "Invalid dpi (%d)\n", pParams->iDpi); return SANE_FALSE; } iHeight = (pParams->iBottom - pParams->iTop + 1); if (iHeight <= 0) { DBG (DBG_ERR, "Invalid height (%d)\n", iHeight); return SANE_FALSE; } if (pParams->iWidth <= 0) { DBG (DBG_ERR, "Invalid width (%d)\n", pParams->iWidth); return SANE_FALSE; } switch (pParams->iLpi) { case 150: case 300: case 600: break; default: DBG (DBG_ERR, "Invalid lpi (%d)\n", pParams->iLpi); return SANE_FALSE; } /* exposure time (in units of 24/Fcrystal?), must be divisible by 8 !!! */ iExpTime = 5408; if ((iExpTime % 8) != 0) { DBG (DBG_ERR, "Invalid exposure time (%d)\n", iExpTime); return SANE_FALSE; } /* *** Done checking scan parameters validity *** */ /* copy the parameters locally and make pParams point to the local copy */ memcpy (&Params, pParams, sizeof (Params)); pParams = &Params; if (!pHWParams->fReg07) { /* init NIASH00014 and lower */ InitNiash00014 (pParams, pHWParams); } else { /* init NIASH00019 */ InitNiash00019 (pParams, pHWParams); } /* common NIASH init */ InitNiashCommon (pParams, pHWParams); return SANE_TRUE; } /************************************************************************/ static SANE_Bool XferBufferGetLine (int iHandle, TDataPipe * p, unsigned char *pabLine, SANE_Bool fReturn) { unsigned char bData, bData2; SANE_Bool fJustDone = SANE_FALSE; /* all calculated transfers done ? */ if (p->iLinesLeft == 0) return SANE_FALSE; /* time for a fresh read? */ if (p->iCurLine == 0) { int iLines; iLines = p->iLinesPerXferBuf; /* read only as many lines as needed */ if (p->iLinesLeft > 0 && p->iLinesLeft <= iLines) { iLines = p->iLinesLeft; DBG (DBG_MSG, "\n"); DBG (DBG_MSG, "last bulk read\n"); if (iLines < p->iLinesPerXferBuf) { DBG (DBG_MSG, "reading reduced number of lines: %d instead of %d\n", iLines, p->iLinesPerXferBuf); } fJustDone = SANE_TRUE; } /* reading old buffer level */ NiashReadReg (iHandle, 0x20, &bData); NiashReadBulk (iHandle, p->pabXferBuf, iLines * p->iBytesPerLine); /* reding new buffer level */ NiashReadReg (iHandle, 0x20, &bData2); if (fJustDone && fReturn) { NiashWriteReg (iHandle, 0x02, 0x80); DBG (DBG_MSG, "returning scanner head\n"); } DBG (DBG_MSG, "buffer level = %3d, , buffer level = %3d\r", (int) bData, iLines * p->iBytesPerLine, (int) bData2); fflush (stdout); } /* copy one line */ if (pabLine != NULL) { memcpy (pabLine, &p->pabXferBuf[p->iCurLine * p->iBytesPerLine], p->iBytesPerLine); } /* advance pointer */ p->iCurLine = (p->iCurLine + 1) % p->iLinesPerXferBuf; /* one transfer line less to the XFerBuffer */ if (p->iLinesLeft > 0) --(p->iLinesLeft); return SANE_TRUE; } static void XferBufferInit (int iHandle, TDataPipe * p) { int i; p->pabXferBuf = (unsigned char *) malloc (XFER_BUF_SIZE); p->iCurLine = 0; /* skip garbage lines */ for (i = 0; i < p->iSkipLines; i++) { XferBufferGetLine (iHandle, p, NULL, SANE_FALSE); } } /* static procedure that fills the circular buffer in advance to any circular buffer data retrieval */ static void CircBufferFill (int iHandle, TDataPipe * p, SANE_Bool iReversedHead) { int i; for (i = 0; i < p->iLinesPerCircBuf; i++) { if (iReversedHead) { XferBufferGetLine (iHandle, p, &p->pabCircBuf[p->iRedLine * p->iBytesPerLine], SANE_FALSE); } else { XferBufferGetLine (iHandle, p, &p->pabCircBuf[p->iBluLine * p->iBytesPerLine], SANE_FALSE); } /* advance pointers */ p->iRedLine = (p->iRedLine + 1) % p->iLinesPerCircBuf; p->iGrnLine = (p->iGrnLine + 1) % p->iLinesPerCircBuf; p->iBluLine = (p->iBluLine + 1) % p->iLinesPerCircBuf; } } static void XferBufferExit (TDataPipe * p) { if (p->pabXferBuf != NULL) { free (p->pabXferBuf); p->pabXferBuf = NULL; } else { DBG (DBG_ERR, "XferBufExit: Xfer buffer not initialised!\n"); } } /* unscrambles a line: - combining the proper R, G and B lines and converting them to interpixel RGB - mirroring left to right */ static void _UnscrambleLine (unsigned char *pabLine, unsigned char *pabRed, unsigned char *pabGrn, unsigned char *pabBlu, int iWidth, SANE_Bool iReversedHead, int iScaleDownDpi, int iBufWeight) { /* never change an approved algorithm ... so take Bertriks original source for this special case */ if (iScaleDownDpi == 1 && iBufWeight == 0) { int i, j; if (iReversedHead) { /* reversed */ for (i = 0; i < iWidth; i++) { j = (iWidth - i) * 3; pabLine[j - 3] = pabRed[i]; pabLine[j - 2] = pabGrn[i + iWidth]; pabLine[j - 1] = pabBlu[i + iWidth * 2]; } } else { /* not reversed */ for (i = 0; i < iWidth; i++) { pabLine[3 * i] = pabRed[i]; pabLine[3 * i + 1] = pabGrn[i + iWidth]; pabLine[3 * i + 2] = pabBlu[i + iWidth * 2]; } } } else { int i, j; /* loop variables */ int c; /* color buffer accumulator for horizontal avarage */ /* initialize for incremental color buffer access */ int iInc = 1; int iStart = 0; /* set for "from the end to the front" of the circular color buffers */ if (iReversedHead) { iStart = iWidth - iScaleDownDpi; iInc = -1; } /* each pixel is the mean of iScaleDownDpi so set the skip width accordingly */ iInc *= iScaleDownDpi; for (i = iStart; i >= 0 && i < iWidth; i += iInc) { /* collect the red pixels */ for (c = j = 0; j < iScaleDownDpi; ++j) c += pabRed[i + j]; *pabLine = (*pabLine * iBufWeight + c / iScaleDownDpi) / (iBufWeight + 1); pabLine++; /* collect the green pixels */ for (c = j = 0; j < iScaleDownDpi; ++j) c += pabGrn[i + iWidth + j]; *pabLine = (*pabLine * iBufWeight + c / iScaleDownDpi) / (iBufWeight + 1); pabLine++; /* collect the blue pixels */ for (c = j = 0; j < iScaleDownDpi; ++j) c += pabBlu[i + 2 * iWidth + j]; *pabLine = (*pabLine * iBufWeight + c / iScaleDownDpi) / (iBufWeight + 1); pabLine++; } } } /* gets an unscrambled line from the circular buffer. the first couple of lines contain garbage, if fReturn==SANE_TRUE, the head will return automatically on an end of scan */ STATIC SANE_Bool CircBufferGetLineEx (int iHandle, TDataPipe * p, unsigned char *pabLine, SANE_Bool iReversedHead, SANE_Bool fReturn) { int iLineCount; for (iLineCount = 0; iLineCount < p->iScaleDownLpi; ++iLineCount) { if (iReversedHead) { if (!XferBufferGetLine (iHandle, p, &p->pabCircBuf[p->iRedLine * p->iBytesPerLine], fReturn)) return SANE_FALSE; } else { if (!XferBufferGetLine (iHandle, p, &p->pabCircBuf[p->iBluLine * p->iBytesPerLine], fReturn)) return SANE_FALSE; } if (pabLine != NULL) { _UnscrambleLine (pabLine, &p->pabCircBuf[p->iRedLine * p->iBytesPerLine], &p->pabCircBuf[p->iGrnLine * p->iBytesPerLine], &p->pabCircBuf[p->iBluLine * p->iBytesPerLine], p->iWidth * p->iScaleDownDpi, iReversedHead, p->iScaleDownDpi, iLineCount); } /* advance pointers */ p->iRedLine = (p->iRedLine + 1) % p->iLinesPerCircBuf; p->iGrnLine = (p->iGrnLine + 1) % p->iLinesPerCircBuf; p->iBluLine = (p->iBluLine + 1) % p->iLinesPerCircBuf; } return SANE_TRUE; } /* gets an unscrambled line from the circular buffer. the first couple of lines contain garbage */ STATIC SANE_Bool CircBufferGetLine (int iHandle, TDataPipe * p, unsigned char *pabLine, SANE_Bool iReversedHead) { return CircBufferGetLineEx (iHandle, p, pabLine, iReversedHead, SANE_FALSE); } /* try to keep the number of transfers the same, but make them all as good as possible the same size to avoid cranking in critical situations */ static int _OptimizeXferSize (int iLines, int iLinesPerXfer) { int iXfers; iXfers = (iLines + iLinesPerXfer - 1) / iLinesPerXfer; while (--iLinesPerXfer > 0 && (iLines + iLinesPerXfer - 1) / iLinesPerXfer == iXfers); return iLinesPerXfer + 1; } STATIC void CircBufferInit (int iHandle, TDataPipe * p, int iWidth, int iHeight, int iMisAlignment, SANE_Bool iReversedHead, int iScaleDownDpi, int iScaleDownLpi) { /* relevant for internal read and write functions */ p->iScaleDownLpi = iScaleDownLpi; p->iScaleDownDpi = iScaleDownDpi; p->iWidth = iWidth; p->iBytesPerLine = iWidth * iScaleDownDpi * BYTES_PER_PIXEL; p->iSaneBytesPerLine = iWidth * BYTES_PER_PIXEL; if (iMisAlignment == 0) { p->iLinesPerCircBuf = 1; } else { p->iLinesPerCircBuf = 3 * iMisAlignment; } DBG (DBG_MSG, "_iScaleDown (Dpi,Lpi) = (%d,%d)\n", p->iScaleDownDpi, p->iScaleDownLpi); DBG (DBG_MSG, "_iBytesPerLine = %d\n", p->iBytesPerLine); DBG (DBG_MSG, "_iLinesPerCircBuf = %d\n", p->iLinesPerCircBuf); p->pabCircBuf = (unsigned char *) malloc (p->iBytesPerLine * p->iLinesPerCircBuf); if (p->pabCircBuf == NULL) { DBG (DBG_ERR, "Unable to allocate %d unsigned chars for circular buffer\n", (int) (p->iBytesPerLine * p->iLinesPerCircBuf)); return; } DBG (DBG_MSG, "Allocated %d unsigned chars for circular buffer\n", p->iBytesPerLine * p->iLinesPerCircBuf); if (iReversedHead) { p->iBluLine = 0; p->iGrnLine = iMisAlignment; p->iRedLine = iMisAlignment * 2; } else { p->iRedLine = 0; p->iGrnLine = iMisAlignment; p->iBluLine = iMisAlignment * 2; } /* negative height is an indication for "no Check" */ if (iHeight < 0) { p->iLinesLeft = -1; p->iLinesPerXferBuf = XFER_BUF_SIZE / p->iBytesPerLine; DBG (DBG_MSG, "using unchecked XFER_BUF_SIZE\n"); DBG (DBG_MSG, "_iXFerSize = %d\n", p->iBytesPerLine * p->iLinesPerXferBuf); } else { #define SAFETY_LINES 0 #define MAX_LINES_PER_XFERBUF 800 /* estimate of number of unsigned chars to transfer at all via the USB */ /* add some lines for securtiy */ p->iLinesLeft = iHeight + p->iSkipLines + p->iLinesPerCircBuf + SAFETY_LINES; p->iLinesPerXferBuf = XFER_BUF_SIZE / p->iBytesPerLine; /* with more than 800 lines the timing is spoiled */ if (p->iLinesPerXferBuf > MAX_LINES_PER_XFERBUF) { p->iLinesPerXferBuf = MAX_LINES_PER_XFERBUF; } /* final optimization to keep critical scans smooth */ p->iLinesPerXferBuf = _OptimizeXferSize (p->iLinesLeft, p->iLinesPerXferBuf); DBG (DBG_MSG, "_iXFerSize = %d for %d transfer(s)\n", (int) p->iLinesPerXferBuf * p->iBytesPerLine, (p->iLinesLeft + p->iLinesPerXferBuf - 1) / p->iLinesPerXferBuf); } DBG (DBG_MSG, "_iLinesPerXferBuf = %d\n", p->iLinesPerXferBuf); /* init transfer buffer */ XferBufferInit (iHandle, p); /* fill circular buffer */ CircBufferFill (iHandle, p, iReversedHead); } STATIC void CircBufferExit (TDataPipe * p) { XferBufferExit (p); if (p->pabCircBuf != NULL) { DBG (DBG_MSG, "\n"); free (p->pabCircBuf); p->pabCircBuf = NULL; } else { DBG (DBG_ERR, "CircBufferExit: Circular buffer not initialised!\n"); } } /************************************************************************/ static int _CalcAvg (unsigned char *pabBuf, int n, int iStep) { int i, j, x; for (i = j = x = 0; i < n; i++) { x += pabBuf[j]; j += iStep; } return (x / n); } /* converts white line data and black point data into a calibration table */ static void CreateCalibTable (unsigned char *abWhite, unsigned char bBlackR, unsigned char bBlackG, unsigned char bBlackB, int iReversedHead, unsigned char *pabCalibTable) { int i, j, iGain, iOffset, iData; unsigned char *pabPixel; j = 0; for (i = 0; i < HW_PIXELS; i++) { if (iReversedHead) { pabPixel = &abWhite[(HW_PIXELS - i - 1) * 3]; } else { pabPixel = &abWhite[i * 3]; } /* red */ if (bBlackR > 16) bBlackR = 16; iGain = 65536 / MAX (1, pabPixel[0] - bBlackR); iOffset = bBlackR * 4; if (iOffset > 63) iOffset = 63; iData = (iGain << 6) + iOffset; pabCalibTable[j++] = (iData) & 255; pabCalibTable[j++] = (iData >> 8) & 255; /* green */ if (bBlackG > 16) bBlackG = 16; iGain = 65536 / MAX (1, pabPixel[1] - bBlackG); iOffset = bBlackG * 4; if (iOffset > 63) iOffset = 63; iData = (iGain << 6) + iOffset; pabCalibTable[j++] = (iData) & 255; pabCalibTable[j++] = (iData >> 8) & 255; /* blue */ if (bBlackB > 16) bBlackB = 16; iGain = 65536 / MAX (1, pabPixel[2] - bBlackB); iOffset = bBlackB * 4; if (iOffset > 63) iOffset = 63; iData = (iGain << 6) + iOffset; pabCalibTable[j++] = (iData) & 255; pabCalibTable[j++] = (iData >> 8) & 255; } } /************************************************************************* Lamp control functions *************************************************************************/ STATIC SANE_Bool GetLamp (THWParams * pHWParams, SANE_Bool * pfLampIsOn) { unsigned char bData; NiashReadReg (pHWParams->iXferHandle, 0x03, &bData); *pfLampIsOn = ((bData & 0x01) != 0); return SANE_TRUE; } STATIC SANE_Bool SetLamp (THWParams * pHWParams, SANE_Bool fLampOn) { unsigned char bData; int iHandle; iHandle = pHWParams->iXferHandle; NiashReadReg (iHandle, 0x03, &bData); if (fLampOn) { NiashWriteReg (iHandle, 0x03, bData | 0x01); } else { NiashWriteReg (iHandle, 0x03, bData & ~0x01); } return SANE_TRUE; } /************************************************************************* Experimental simple calibration, but also returning the white levels *************************************************************************/ STATIC SANE_Bool SimpleCalibExt (THWParams * pHWPar, unsigned char *pabCalibTable, unsigned char *pabCalWhite) { unsigned char bMinR, bMinG, bMinB; TDataPipe DataPipe; TScanParams Params; unsigned char abGamma[4096]; int i, j; static unsigned char abBuf[HW_PIXELS * 3 * 71]; /* Carefull : see startWhite and endWhite below */ static unsigned char abLine[HW_PIXELS * 3]; static unsigned char abWhite[HW_PIXELS * 3]; unsigned char *pabWhite; int iWhiteR, iWhiteG, iWhiteB; int iHandle; SANE_Bool iReversedHead; int startWhiteY, endWhiteY; int startBlackY, endBlackY; int endBlackX; iHandle = pHWPar->iXferHandle; iReversedHead = pHWPar->iReversedHead; DataPipe.iSkipLines = pHWPar->iSkipLines; Params.iDpi = HW_DPI; Params.iLpi = HW_DPI; if (iReversedHead) /* hp scanners */ Params.iTop = 60; else /* agfa scanners */ Params.iTop = 30; Params.iBottom = HP3300C_BOTTOM; Params.iLeft = 0; Params.iWidth = HW_PIXELS; Params.iHeight = 54; Params.fCalib = SANE_TRUE; /* write gamma table with neutral gain / offset */ CalcGamma (abGamma, 1.0); WriteGammaCalibTable (abGamma, abGamma, abGamma, NULL, 256, 0, pHWPar); if (!InitScan (&Params, pHWPar)) { if (pabCalWhite) pabCalWhite[0] = pabCalWhite[1] = pabCalWhite[2] = 0; return SANE_FALSE; } /* Definition of white and black areas */ if (iReversedHead) { /* hp scanners */ startWhiteY = 0; endWhiteY = 15; startBlackY = 16; endBlackY = 135; endBlackX = HW_PIXELS; } else { /* agfa scanners */ startWhiteY = 0; endWhiteY = 70; startBlackY = 86; endBlackY = 135; endBlackX = 3374; } CircBufferInit (iHandle, &DataPipe, HW_PIXELS, -1, Params.iLpi / 150, iReversedHead, 1, 1); /* white level */ /* skip some lines */ for (i = 0; i < startWhiteY; i++) { CircBufferGetLine (iHandle, &DataPipe, abLine, iReversedHead); } /* Get white lines */ for (i = 0; i < endWhiteY - startWhiteY + 1; i++) { CircBufferGetLine (iHandle, &DataPipe, &abBuf[i * HW_PIXELS * 3], iReversedHead); } /* black level */ bMinR = 255; bMinG = 255; bMinB = 255; /* Skip some lines */ for (i = 0; i < startBlackY; i++) { CircBufferGetLine (iHandle, &DataPipe, abLine, iReversedHead); } for (i = 0; i < endBlackY - startBlackY + 1; i++) { CircBufferGetLine (iHandle, &DataPipe, abLine, iReversedHead); for (j = 0; j < endBlackX; j++) { bMinR = MIN (abLine[j * 3 + 0], bMinR); bMinG = MIN (abLine[j * 3 + 1], bMinG); bMinB = MIN (abLine[j * 3 + 2], bMinB); } } CircBufferExit (&DataPipe); FinishScan (pHWPar); /* calc average white level */ pabWhite = abBuf; for (i = 0; i < HW_PIXELS; i++) { abWhite[i * 3 + 0] = _CalcAvg (&pabWhite[i * 3 + 0], endWhiteY - startWhiteY + 1, HW_PIXELS * 3); abWhite[i * 3 + 1] = _CalcAvg (&pabWhite[i * 3 + 1], endWhiteY - startWhiteY + 1, HW_PIXELS * 3); abWhite[i * 3 + 2] = _CalcAvg (&pabWhite[i * 3 + 2], endWhiteY - startWhiteY + 1, HW_PIXELS * 3); } iWhiteR = _CalcAvg (&abWhite[0], HW_PIXELS, 3); iWhiteG = _CalcAvg (&abWhite[1], HW_PIXELS, 3); iWhiteB = _CalcAvg (&abWhite[2], HW_PIXELS, 3); DBG (DBG_MSG, "Black level (%d,%d,%d), White level (%d,%d,%d)\n", (int) bMinR, (int) bMinG, (int) bMinB, iWhiteR, iWhiteG, iWhiteB); /* convert the white line and black point into a calibration table */ CreateCalibTable (abWhite, bMinR, bMinG, bMinB, iReversedHead, pabCalibTable); /* assign the White Levels */ if (pabCalWhite) { pabCalWhite[0] = iWhiteR; pabCalWhite[1] = iWhiteG; pabCalWhite[2] = iWhiteB; } return SANE_TRUE; } /************************************************************************* FinishScan ========== Finishes the scan. Makes the scanner head move back to the home position. *************************************************************************/ STATIC void FinishScan (THWParams * pHWParams) { NiashWriteReg (pHWParams->iXferHandle, 0x02, 0x80); } sane-backends-1.0.27/backend/genesys_conv_hlp.c0000664000175000017500000002114012775312261016326 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005 Pierre Willenbrock This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* * Conversion filters for genesys backend */ static SANE_Status FUNC_NAME(genesys_reorder_components_cis) ( uint8_t *src_data, uint8_t *dst_data, unsigned int lines, unsigned int pixels) { unsigned int x, y; uint8_t *src[3]; uint8_t *dst = dst_data; unsigned int rest = pixels * 2 * BYTES_PER_COMPONENT; src[0] = src_data + pixels * BYTES_PER_COMPONENT * 0; src[1] = src_data + pixels * BYTES_PER_COMPONENT * 1; src[2] = src_data + pixels * BYTES_PER_COMPONENT * 2; for(y = 0; y < lines; y++) { for(x = 0; x < pixels; x++) { #ifndef DOUBLE_BYTE *dst++ = *src[0]++; *dst++ = *src[1]++; *dst++ = *src[2]++; #else # ifndef WORDS_BIGENDIAN *dst++ = *src[0]++; *dst++ = *src[0]++; *dst++ = *src[1]++; *dst++ = *src[1]++; *dst++ = *src[2]++; *dst++ = *src[2]++; # else *dst++ = src[0][1]; *dst++ = src[0][0]; *dst++ = src[1][1]; *dst++ = src[1][0]; *dst++ = src[2][1]; *dst++ = src[2][0]; src[0] += 2; src[1] += 2; src[2] += 2; # endif #endif } src[0] += rest; src[1] += rest; src[2] += rest; } return SANE_STATUS_GOOD; } static SANE_Status FUNC_NAME(genesys_reorder_components_cis_bgr) ( uint8_t *src_data, uint8_t *dst_data, unsigned int lines, unsigned int pixels) { unsigned int x, y; uint8_t *src[3]; uint8_t *dst = dst_data; unsigned int rest = pixels * 2 * BYTES_PER_COMPONENT; src[0] = src_data + pixels * BYTES_PER_COMPONENT * 0; src[1] = src_data + pixels * BYTES_PER_COMPONENT * 1; src[2] = src_data + pixels * BYTES_PER_COMPONENT * 2; for(y = 0; y < lines; y++) { for(x = 0; x < pixels; x++) { #ifndef DOUBLE_BYTE *dst++ = *src[2]++; *dst++ = *src[1]++; *dst++ = *src[0]++; #else # ifndef WORDS_BIGENDIAN *dst++ = *src[2]++; *dst++ = *src[2]++; *dst++ = *src[1]++; *dst++ = *src[1]++; *dst++ = *src[0]++; *dst++ = *src[0]++; # else *dst++ = src[2][1]; *dst++ = src[2][0]; *dst++ = src[1][1]; *dst++ = src[1][0]; *dst++ = src[0][1]; *dst++ = src[0][0]; src[0] += 2; src[1] += 2; src[2] += 2; # endif #endif } src[0] += rest; src[1] += rest; src[2] += rest; } return SANE_STATUS_GOOD; } static SANE_Status FUNC_NAME(genesys_reorder_components_bgr) ( uint8_t *src_data, uint8_t *dst_data, unsigned int lines, unsigned int pixels) { unsigned int c; uint8_t *src = src_data; uint8_t *dst = dst_data; for(c = 0; c < lines * pixels; c++) { #ifndef DOUBLE_BYTE *dst++ = src[2]; *dst++ = src[1]; *dst++ = src[0]; src += 3; #else # ifndef WORDS_BIGENDIAN *dst++ = src[2 * 2 + 0]; *dst++ = src[2 * 2 + 1]; *dst++ = src[1 * 2 + 0]; *dst++ = src[1 * 2 + 1]; *dst++ = src[0 * 2 + 0]; *dst++ = src[0 * 2 + 1]; # else *dst++ = src[2 * 2 + 1]; *dst++ = src[2 * 2 + 0]; *dst++ = src[1 * 2 + 1]; *dst++ = src[1 * 2 + 0]; *dst++ = src[0 * 2 + 1]; *dst++ = src[0 * 2 + 0]; # endif src += 3 * 2; #endif } return SANE_STATUS_GOOD; } #if defined(DOUBLE_BYTE) && defined(WORDS_BIGENDIAN) static SANE_Status FUNC_NAME(genesys_reorder_components_endian) ( uint8_t *src_data, uint8_t *dst_data, unsigned int lines, unsigned int pixels, unsigned int channels) { unsigned int c; uint8_t *src = src_data; uint8_t *dst = dst_data; for(c = 0; c < lines * pixels * channels; c++) { *dst++ = src[1]; *dst++ = src[0]; src += 2; } return SANE_STATUS_GOOD; } #endif /*defined(DOUBLE_BYTE) && defined(WORDS_BIGENDIAN)*/ static SANE_Status FUNC_NAME(genesys_reverse_ccd) ( uint8_t *src_data, uint8_t *dst_data, unsigned int lines, unsigned int components_per_line, unsigned int *ccd_shift, unsigned int component_count) { unsigned int x, y, c; COMPONENT_TYPE *src = (COMPONENT_TYPE *)src_data; COMPONENT_TYPE *dst = (COMPONENT_TYPE *)dst_data; COMPONENT_TYPE *srcp; COMPONENT_TYPE *dstp; unsigned int pitch = components_per_line; unsigned int ccd_shift_pitch[12]; unsigned int *csp; for (c = 0; c < component_count; c++) ccd_shift_pitch[c] = ccd_shift[c] * pitch; /* * cache efficiency: we are processing a single line component_count times, so it should fit into the cpu cache for maximum efficiency. our lines take maximum 252kb(3 channels, 16bit, 2400dpi, full gl841 shading range) * instruction efficiency: the innermost loop runs long and consists of 3 adds, one compare, 2 derefences. */ /* for (y = 0; y < lines; y++) { csp = ccd_shift_pitch; for (c = 0; c < component_count; c++) { srcp = src + c + *csp++; dstp = dst + c; for (x = 0; x < pitch; x += component_count) { *dstp = *srcp; srcp += component_count; dstp += component_count; } } dst += pitch; src += pitch; } */ /* * cache efficency: here only line_dist_pitch needs to stay in cache. 12*4 = 48 bytes * instruction efficiency: we have a short running inner loop, consisting of 4 incs, 2 compare, 1 add, 2 dereference and 1 indexed dereference. the enclosing loop is long running, consisting of 1 add, 1 compare. */ srcp = src; dstp = dst; for (y = 0; y < lines; y++) { for (x = 0; x < pitch; x += component_count) { csp = ccd_shift_pitch; for (c = 0; c < component_count && c + x < pitch; c++) { *dstp = srcp[*csp++]; dstp++; srcp++; } } } return SANE_STATUS_GOOD; } static SANE_Status FUNC_NAME(genesys_shrink_lines) ( uint8_t *src_data, uint8_t *dst_data, unsigned int lines, unsigned int src_pixels, unsigned int dst_pixels, unsigned int channels) { unsigned int dst_x, src_x, y, c, cnt; unsigned int avg[3]; unsigned int count; COMPONENT_TYPE *src = (COMPONENT_TYPE *)src_data; COMPONENT_TYPE *dst = (COMPONENT_TYPE *)dst_data; if (src_pixels > dst_pixels) { /*average*/ for (c = 0; c < channels; c++) avg[c] = 0; for(y = 0; y < lines; y++) { cnt = src_pixels / 2; src_x = 0; for (dst_x = 0; dst_x < dst_pixels; dst_x++) { count = 0; while (cnt < src_pixels && src_x < src_pixels) { cnt += dst_pixels; for (c = 0; c < channels; c++) avg[c] += *src++; src_x++; count++; } cnt -= src_pixels; for (c = 0; c < channels; c++) { *dst++ = avg[c] / count; avg[c] = 0; } } } } else { /*interpolate. copy pixels*/ for(y = 0; y < lines; y++) { cnt = dst_pixels / 2; dst_x = 0; for (src_x = 0; src_x < src_pixels; src_x++) { for (c = 0; c < channels; c++) avg[c] = *src++; while ((cnt < dst_pixels || src_x + 1 == src_pixels) && dst_x < dst_pixels) { cnt += src_pixels; for (c = 0; c < channels; c++) *dst++ = avg[c]; dst_x++; } cnt -= dst_pixels; } } } return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/dll.aliases0000664000175000017500000000025512112021330014712 00000000000000# List of aliased or hiddend backends. See sane-dll(5) for details. # # Format: # alias SomeName SaneDeviceName # alias "Some Name" SaneDeviceName # hide SaneDeviceName sane-backends-1.0.27/backend/mustek_usb2_asic.c0000664000175000017500000046622313106201017016223 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005 Mustek. Originally maintained by Mustek Author:Roy 2005.5.24 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro and similar USB2 scanners. */ #include "mustek_usb2_asic.h" /* ---------------------- low level asic functions -------------------------- */ static SANE_Byte RegisterBankStatus = -1; static STATUS WriteIOControl (PAsic chip, unsigned short wValue, unsigned short wIndex, unsigned short wLength, SANE_Byte * lpbuf) { STATUS status = STATUS_GOOD; status = sanei_usb_control_msg (chip->fd, 0x40, 0x01, wValue, wIndex, wLength, lpbuf); if (status != STATUS_GOOD) { DBG (DBG_ERR, "WriteIOControl Error!\n"); return status; } return STATUS_GOOD; } static STATUS ReadIOControl (PAsic chip, unsigned short wValue, unsigned short wIndex, unsigned short wLength, SANE_Byte * lpbuf) { STATUS status = STATUS_GOOD; status = sanei_usb_control_msg (chip->fd, 0xc0, 0x01, wValue, wIndex, wLength, lpbuf); if (status != STATUS_GOOD) { DBG (DBG_ERR, "WriteIOControl Error!\n"); return status; } return status; } static STATUS Mustek_ClearFIFO (PAsic chip) { STATUS status = STATUS_GOOD; SANE_Byte buf[4]; DBG (DBG_ASIC, "Mustek_ClearFIFO:Enter\n"); buf[0] = 0; buf[1] = 0; buf[2] = 0; buf[3] = 0; status = WriteIOControl (chip, 0x05, 0, 4, (SANE_Byte *) (buf)); if (status != STATUS_GOOD) return status; status = WriteIOControl (chip, 0xc0, 0, 4, (SANE_Byte *) (buf)); if (status != STATUS_GOOD) return status; DBG (DBG_ASIC, "Mustek_ClearFIFO:Exit\n"); return STATUS_GOOD; } static STATUS Mustek_SendData (PAsic chip, unsigned short reg, SANE_Byte data) { SANE_Byte buf[4]; STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "Mustek_SendData: Enter. reg=%x,data=%x\n", reg, data); if (reg <= 0xFF) { if (RegisterBankStatus != 0) { DBG (DBG_ASIC, "RegisterBankStatus=%d\n", RegisterBankStatus); buf[0] = ES01_5F_REGISTER_BANK_SELECT; buf[1] = SELECT_REGISTER_BANK0; buf[2] = ES01_5F_REGISTER_BANK_SELECT; buf[3] = SELECT_REGISTER_BANK0; WriteIOControl (chip, 0xb0, 0, 4, buf); RegisterBankStatus = 0; DBG (DBG_ASIC, "RegisterBankStatus=%d\n", RegisterBankStatus); } } else if (reg <= 0x1FF) { if (RegisterBankStatus != 1) { DBG (DBG_ASIC, "RegisterBankStatus=%d\n", RegisterBankStatus); buf[0] = ES01_5F_REGISTER_BANK_SELECT; buf[1] = SELECT_REGISTER_BANK1; buf[2] = ES01_5F_REGISTER_BANK_SELECT; buf[3] = SELECT_REGISTER_BANK1; WriteIOControl (chip, 0xb0, 0, 4, buf); RegisterBankStatus = 1; } } else if (reg <= 0x2FF) { if (RegisterBankStatus != 2) { DBG (DBG_ASIC, "RegisterBankStatus=%d\n", RegisterBankStatus); buf[0] = ES01_5F_REGISTER_BANK_SELECT; buf[1] = SELECT_REGISTER_BANK2; buf[2] = ES01_5F_REGISTER_BANK_SELECT; buf[3] = SELECT_REGISTER_BANK2; WriteIOControl (chip, 0xb0, 0, 4, buf); RegisterBankStatus = 2; } } buf[0] = LOBYTE (reg); buf[1] = data; buf[2] = LOBYTE (reg); buf[3] = data; status = WriteIOControl (chip, 0xb0, 0, 4, buf); if (status != STATUS_GOOD) DBG (DBG_ERR, ("Mustek_SendData: write error\n")); return status; } static STATUS Mustek_ReceiveData (PAsic chip, SANE_Byte * reg) { STATUS status = STATUS_GOOD; SANE_Byte buf[4]; DBG (DBG_ASIC, "Mustek_ReceiveData\n"); status = ReadIOControl (chip, 0x07, 0, 4, buf); *reg = buf[0]; return status; } static STATUS Mustek_WriteAddressLineForRegister (PAsic chip, SANE_Byte x) { STATUS status = STATUS_GOOD; SANE_Byte buf[4]; DBG (DBG_ASIC, "Mustek_WriteAddressLineForRegister: Enter\n"); buf[0] = x; buf[1] = x; buf[2] = x; buf[3] = x; status = WriteIOControl (chip, 0x04, x, 4, buf); DBG (DBG_ASIC, "Mustek_WriteAddressLineForRegister: Exit\n"); return status; } static STATUS SetRWSize (PAsic chip, SANE_Byte ReadWrite, unsigned int size) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "SetRWSize: Enter\n"); if (ReadWrite == 0) { /*write */ status = Mustek_SendData (chip, 0x7C, (SANE_Byte) (size)); if (status != STATUS_GOOD) return status; status = Mustek_SendData (chip, 0x7D, (SANE_Byte) (size >> 8)); if (status != STATUS_GOOD) return status; status = Mustek_SendData (chip, 0x7E, (SANE_Byte) (size >> 16)); if (status != STATUS_GOOD) return status; status = Mustek_SendData (chip, 0x7F, (SANE_Byte) (size >> 24)); if (status != STATUS_GOOD) return status; } else { /* read */ status = Mustek_SendData (chip, 0x7C, (SANE_Byte) (size >> 1)); if (status != STATUS_GOOD) return status; status = Mustek_SendData (chip, 0x7D, (SANE_Byte) (size >> 9)); if (status != STATUS_GOOD) return status; status = Mustek_SendData (chip, 0x7E, (SANE_Byte) (size >> 17)); if (status != STATUS_GOOD) return status; status = Mustek_SendData (chip, 0x7F, (SANE_Byte) (size >> 25)); if (status != STATUS_GOOD) return status; } DBG (DBG_ASIC, "SetRWSize: Exit\n"); return STATUS_GOOD; } static STATUS Mustek_DMARead (PAsic chip, unsigned int size, SANE_Byte * lpdata) { STATUS status = STATUS_GOOD; unsigned int i, buf[1]; unsigned int read_size; DBG (DBG_ASIC, "Mustek_DMARead: Enter\n"); status = Mustek_ClearFIFO (chip); if (status != STATUS_GOOD) return status; buf[0] = read_size = 32 * 1024; for (i = 0; i < size / (read_size); i++) { SetRWSize (chip, 1, buf[0]); status = WriteIOControl (chip, 0x03, 0, 4, (SANE_Byte *) (buf)); status = sanei_usb_read_bulk (chip->fd, lpdata + i * read_size, (size_t *) buf); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Mustek_DMARead: read error\n"); return status; } } buf[0] = size - i * read_size; if (buf[0] > 0) { SetRWSize (chip, 1, buf[0]); status = WriteIOControl (chip, 0x03, 0, 4, (SANE_Byte *) (buf)); status = sanei_usb_read_bulk (chip->fd, lpdata + i * read_size, (size_t *) buf); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Mustek_DMARead: read error\n"); return status; } usleep (20000); } DBG (DBG_ASIC, "Mustek_DMARead: Exit\n"); return STATUS_GOOD; } static STATUS Mustek_DMAWrite (PAsic chip, unsigned int size, SANE_Byte * lpdata) { STATUS status = STATUS_GOOD; unsigned int buf[1]; unsigned int i; unsigned int write_size; DBG (DBG_ASIC, "Mustek_DMAWrite: Enter:size=%d\n", size); status = Mustek_ClearFIFO (chip); if (status != STATUS_GOOD) return status; buf[0] = write_size = 32 * 1024; for (i = 0; i < size / (write_size); i++) { SetRWSize (chip, 0, buf[0]); WriteIOControl (chip, 0x02, 0, 4, (SANE_Byte *) buf); status = sanei_usb_write_bulk (chip->fd, lpdata + i * write_size, (size_t *) buf); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Mustek_DMAWrite: write error\n"); return status; } } buf[0] = size - i * write_size; if (buf[0] > 0) { SetRWSize (chip, 0, buf[0]); WriteIOControl (chip, 0x02, 0, 4, (SANE_Byte *) buf); status = sanei_usb_write_bulk (chip->fd, lpdata + i * write_size, (size_t *) buf); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Mustek_DMAWrite: write error\n"); return status; } } Mustek_ClearFIFO (chip); DBG (DBG_ASIC, "Mustek_DMAWrite: Exit\n"); return STATUS_GOOD; } static STATUS Mustek_SendData2Byte (PAsic chip, unsigned short reg, SANE_Byte data) { static SANE_Bool isTransfer = FALSE; static SANE_Byte BankBuf[4]; static SANE_Byte DataBuf[4]; if (reg <= 0xFF) { if (RegisterBankStatus != 0) { DBG (DBG_ASIC, "RegisterBankStatus=%d\n", RegisterBankStatus); BankBuf[0] = ES01_5F_REGISTER_BANK_SELECT; BankBuf[1] = SELECT_REGISTER_BANK0; BankBuf[2] = ES01_5F_REGISTER_BANK_SELECT; BankBuf[3] = SELECT_REGISTER_BANK0; WriteIOControl (chip, 0xb0, 0, 4, BankBuf); RegisterBankStatus = 0; } } else if (reg <= 0x1FF) { if (RegisterBankStatus != 1) { DBG (DBG_ASIC, "RegisterBankStatus=%d\n", RegisterBankStatus); BankBuf[0] = ES01_5F_REGISTER_BANK_SELECT; BankBuf[1] = SELECT_REGISTER_BANK1; BankBuf[2] = ES01_5F_REGISTER_BANK_SELECT; BankBuf[3] = SELECT_REGISTER_BANK1; WriteIOControl (chip, 0xb0, 0, 4, BankBuf); RegisterBankStatus = 1; } } else if (reg <= 0x2FF) { if (RegisterBankStatus != 2) { DBG (DBG_ASIC, "RegisterBankStatus=%d\n", RegisterBankStatus); BankBuf[0] = ES01_5F_REGISTER_BANK_SELECT; BankBuf[1] = SELECT_REGISTER_BANK2; BankBuf[2] = ES01_5F_REGISTER_BANK_SELECT; BankBuf[3] = SELECT_REGISTER_BANK2; WriteIOControl (chip, 0xb0, 0, 4, BankBuf); RegisterBankStatus = 2; } } if (isTransfer == FALSE) { DataBuf[0] = LOBYTE (reg); DataBuf[1] = data; isTransfer = TRUE; } else { DataBuf[2] = LOBYTE (reg); DataBuf[3] = data; WriteIOControl (chip, 0xb0, 0, 4, DataBuf); isTransfer = FALSE; } return STATUS_GOOD; } /* ---------------------- asic motor functions ----------------------------- */ static STATUS LLFRamAccess (PAsic chip, LLF_RAMACCESS * RamAccess) { STATUS status = STATUS_GOOD; SANE_Byte a[2]; DBG (DBG_ASIC, "LLFRamAccess:Enter\n"); /*Set start address. Unit is a word. */ Mustek_SendData (chip, ES01_A0_HostStartAddr0_7, LOBYTE (RamAccess->LoStartAddress)); if (RamAccess->IsOnChipGamma == ON_CHIP_FINAL_GAMMA) { /* final gamma */ Mustek_SendData (chip, ES01_A1_HostStartAddr8_15, HIBYTE (RamAccess->LoStartAddress)); Mustek_SendData (chip, ES01_A2_HostStartAddr16_21, LOBYTE (RamAccess->HiStartAddress) | ACCESS_GAMMA_RAM); } else if (RamAccess->IsOnChipGamma == ON_CHIP_PRE_GAMMA) { /* pre gamma */ Mustek_SendData (chip, ES01_A1_HostStartAddr8_15, HIBYTE (RamAccess-> LoStartAddress) | ES01_ACCESS_PRE_GAMMA); Mustek_SendData (chip, ES01_A2_HostStartAddr16_21, LOBYTE (RamAccess->HiStartAddress) | ACCESS_GAMMA_RAM); } else { /* dram */ Mustek_SendData (chip, ES01_A1_HostStartAddr8_15, HIBYTE (RamAccess->LoStartAddress)); Mustek_SendData (chip, ES01_A2_HostStartAddr16_21, LOBYTE (RamAccess->HiStartAddress) | ACCESS_DRAM); } /* set SDRAM delay time */ Mustek_SendData (chip, ES01_79_AFEMCLK_SDRAMCLK_DELAY_CONTROL, SDRAMCLK_DELAY_12_ns); /*Set end address. Unit is a word. */ Mustek_SendData (chip, ES01_A3_HostEndAddr0_7, 0xff); Mustek_SendData (chip, ES01_A4_HostEndAddr8_15, 0xff); Mustek_SendData (chip, ES01_A5_HostEndAddr16_21, 0xff); Mustek_ClearFIFO (chip); if (RamAccess->ReadWrite == WRITE_RAM) { /*Write RAM */ Mustek_DMAWrite (chip, RamAccess->RwSize, RamAccess->BufferPtr); /* read-write size must be even */ /*steal read 2byte */ usleep (20000); RamAccess->RwSize = 2; RamAccess->BufferPtr = (SANE_Byte *) a; RamAccess->ReadWrite = READ_RAM; LLFRamAccess (chip, RamAccess); DBG (DBG_ASIC, "end steal 2 byte!\n"); } else { /* Read RAM */ Mustek_DMARead (chip, RamAccess->RwSize, RamAccess->BufferPtr); /* read-write size must be even */ } DBG (DBG_ASIC, "LLFRamAccess:Exit\n"); return status; } static STATUS LLFSetMotorCurrentAndPhase (PAsic chip, LLF_MOTOR_CURRENT_AND_PHASE * MotorCurrentAndPhase) { STATUS status = STATUS_GOOD; SANE_Byte MotorPhase; DBG (DBG_ASIC, "LLFSetMotorCurrentAndPhase:Enter\n"); if (MotorCurrentAndPhase->MotorDriverIs3967 == 1) { MotorPhase = 0xFE; } else { MotorPhase = 0xFF; } DBG (DBG_ASIC, "MotorPhase=0x%x\n", MotorPhase); Mustek_SendData (chip, ES02_50_MOTOR_CURRENT_CONTORL, 0x01); if (MotorCurrentAndPhase->FillPhase == 0) { Mustek_SendData (chip, ES01_AB_PWM_CURRENT_CONTROL, 0x00); Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*2 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*3 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*4 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); } else { if (MotorCurrentAndPhase->MoveType == _4_TABLE_SPACE_FOR_FULL_STEP) { /* Full Step */ Mustek_SendData (chip, ES01_AB_PWM_CURRENT_CONTROL, 0x00); /*1 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*2 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*3 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*4 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); } else if (MotorCurrentAndPhase->MoveType == _8_TABLE_SPACE_FOR_1_DIV_2_STEP) { /* Half Step */ Mustek_SendData (chip, ES01_AB_PWM_CURRENT_CONTROL, 0x01); /*1 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x25 & MotorPhase); /*2 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x07 & MotorPhase); /*3 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x24 & MotorPhase); /*4 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x30 & MotorPhase); /*5 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x2c & MotorPhase); /*6 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x0e & MotorPhase); /*7 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x2d & MotorPhase); /*8 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, MotorCurrentAndPhase->MotorCurrentTableA[0]); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, MotorCurrentAndPhase->MotorCurrentTableB[0]); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x39 & MotorPhase); } else if (MotorCurrentAndPhase->MoveType == _16_TABLE_SPACE_FOR_1_DIV_4_STEP) { /* 1/4 step */ Mustek_SendData (chip, ES01_AB_PWM_CURRENT_CONTROL, 0x02); /*1 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (0 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (0 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*2 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (1 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (1 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*3 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (2 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (2 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*4 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (3 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (3 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*5 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * cos (0 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * sin (0 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*6 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * cos (1 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * sin (1 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*7 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * cos (2 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * sin (2 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*8 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * cos (3 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * sin (3 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*9 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (0 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (0 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*10 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (1 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (1 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*11 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (2 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (2 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*12 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (3 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (3 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*13 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * cos (0 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * sin (0 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*14 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * cos (1 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * sin (1 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*15 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * cos (2 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * sin (2 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*16 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * cos (3 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * sin (3 * 3.141592654 * 90 / 4 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); } else if (MotorCurrentAndPhase->MoveType == _32_TABLE_SPACE_FOR_1_DIV_8_STEP) { Mustek_SendData (chip, ES01_AB_PWM_CURRENT_CONTROL, 0x03); /*1 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (0 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (0 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*2 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (1 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (1 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*3 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (2 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (2 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*4 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (3 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (3 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*5 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (4 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (4 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*6 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (5 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (5 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*7 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (6 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (6 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*8 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (7 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (7 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x00 & MotorPhase); /*9 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (0 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (0 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*10 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (1 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (1 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*11 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (2 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (2 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*12 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (3 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (3 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*13 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (4 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (4 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*14 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (5 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (5 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*15 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (6 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (6 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*16 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (7 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (7 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x08 & MotorPhase); /*17 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (0 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (0 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*18 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (1 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (1 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*19 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (2 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (2 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*20 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (3 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (3 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*21 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (4 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (4 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*22 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (5 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (5 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*23 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (6 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (6 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*24 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (7 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (7 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x09 & MotorPhase); /*25 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (0 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (0 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*26 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (1 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (1 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*27 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (2 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (2 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*28 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (3 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (3 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*29 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (4 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (4 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*30 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (5 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (5 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*31 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (6 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (6 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); /*32 */ Mustek_SendData2Byte (chip, ES02_52_MOTOR_CURRENT_TABLE_A, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableA[0] * sin (7 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_53_MOTOR_CURRENT_TABLE_B, (SANE_Byte) (MotorCurrentAndPhase-> MotorCurrentTableB[0] * cos (7 * 3.141592654 * 90 / 8 / 180))); Mustek_SendData2Byte (chip, ES02_51_MOTOR_PHASE_TABLE_1, 0x01 & MotorPhase); } } if (MotorCurrentAndPhase->FillPhase != 0) { Mustek_SendData (chip, ES02_50_MOTOR_CURRENT_CONTORL, 0x00 | MotorCurrentAndPhase->MoveType); } else { Mustek_SendData (chip, ES02_50_MOTOR_CURRENT_CONTORL, 0x00); } DBG (DBG_ASIC, "LLFSetMotorCurrentAndPhase:Exit\n"); return status; } #if SANE_UNUSED static STATUS LLFStopMotorMove (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "LLFStopMotorMove:Enter\n"); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); Asic_WaitUnitReady (chip); DBG (DBG_ASIC, "LLFStopMotorMove:Exit\n"); return status; } #endif static STATUS LLFSetMotorTable (PAsic chip, LLF_SETMOTORTABLE * LLF_SetMotorTable) { STATUS status = STATUS_GOOD; LLF_RAMACCESS RamAccess; DBG (DBG_ASIC, "LLFSetMotorTable:Enter\n"); if (LLF_SetMotorTable->MotorTablePtr != NULL) { RamAccess.ReadWrite = WRITE_RAM; RamAccess.IsOnChipGamma = EXTERNAL_RAM; RamAccess.DramDelayTime = SDRAMCLK_DELAY_12_ns; RamAccess.LoStartAddress = 0; RamAccess.LoStartAddress |= LLF_SetMotorTable->MotorTableAddress; RamAccess.LoStartAddress <<= TABLE_OFFSET_BASE; RamAccess.LoStartAddress |= 0x3000; RamAccess.HiStartAddress = 0; RamAccess.HiStartAddress |= LLF_SetMotorTable->MotorTableAddress; RamAccess.HiStartAddress >>= (16 - TABLE_OFFSET_BASE); RamAccess.RwSize = 512 * 2 * 8; /* BYTE */ RamAccess.BufferPtr = (SANE_Byte *) LLF_SetMotorTable->MotorTablePtr; LLFRamAccess (chip, &RamAccess); /* tell scan chip the motor table address, unit is 2^14 words */ Mustek_SendData (chip, ES01_9D_MotorTableAddrA14_A21, LLF_SetMotorTable->MotorTableAddress); } DBG (DBG_ASIC, "LLFSetMotorTable:Exit\n"); return status; } static STATUS LLFMotorMove (PAsic chip, LLF_MOTORMOVE * LLF_MotorMove) { STATUS status = STATUS_GOOD; unsigned int motor_steps; SANE_Byte temp_motor_action; DBG (DBG_ASIC, "LLFMotorMove:Enter\n"); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); status = Asic_WaitUnitReady (chip); DBG (DBG_ASIC, "Set start/end pixel\n"); Mustek_SendData (chip, ES01_B8_ChannelRedExpStartPixelLSB, LOBYTE (100)); Mustek_SendData (chip, ES01_B9_ChannelRedExpStartPixelMSB, HIBYTE (100)); Mustek_SendData (chip, ES01_BA_ChannelRedExpEndPixelLSB, LOBYTE (101)); Mustek_SendData (chip, ES01_BB_ChannelRedExpEndPixelMSB, HIBYTE (101)); Mustek_SendData (chip, ES01_BC_ChannelGreenExpStartPixelLSB, LOBYTE (100)); Mustek_SendData (chip, ES01_BD_ChannelGreenExpStartPixelMSB, HIBYTE (100)); Mustek_SendData (chip, ES01_BE_ChannelGreenExpEndPixelLSB, LOBYTE (101)); Mustek_SendData (chip, ES01_BF_ChannelGreenExpEndPixelMSB, HIBYTE (101)); Mustek_SendData (chip, ES01_C0_ChannelBlueExpStartPixelLSB, LOBYTE (100)); Mustek_SendData (chip, ES01_C1_ChannelBlueExpStartPixelMSB, HIBYTE (100)); Mustek_SendData (chip, ES01_C2_ChannelBlueExpEndPixelLSB, LOBYTE (101)); Mustek_SendData (chip, ES01_C3_ChannelBlueExpEndPixelMSB, HIBYTE (101)); /*set motor accelerate steps MAX 511 steps */ Mustek_SendData (chip, ES01_E0_MotorAccStep0_7, LOBYTE (LLF_MotorMove->AccStep)); Mustek_SendData (chip, ES01_E1_MotorAccStep8_8, HIBYTE (LLF_MotorMove->AccStep)); DBG (DBG_ASIC, "AccStep=%d\n", LLF_MotorMove->AccStep); Mustek_SendData (chip, ES01_E2_MotorStepOfMaxSpeed0_7, LOBYTE (LLF_MotorMove->FixMoveSteps)); Mustek_SendData (chip, ES01_E3_MotorStepOfMaxSpeed8_15, HIBYTE (LLF_MotorMove->FixMoveSteps)); Mustek_SendData (chip, ES01_E4_MotorStepOfMaxSpeed16_19, 0); DBG (DBG_ASIC, "FixMoveSteps=%d\n", LLF_MotorMove->FixMoveSteps); /*set motor decelerate steps MAX 255 steps */ Mustek_SendData (chip, ES01_E5_MotorDecStep, LLF_MotorMove->DecStep); DBG (DBG_ASIC, "DecStep=%d\n", LLF_MotorMove->DecStep); /*set motor uniform speed only for uniform speed //only used for UNIFORM_MOTOR_AND_SCAN_SPEED_ENABLE //If you use acc mode, this two reg are not used. */ Mustek_SendData (chip, ES01_FD_MotorFixedspeedLSB, LOBYTE (LLF_MotorMove->FixMoveSpeed)); Mustek_SendData (chip, ES01_FE_MotorFixedspeedMSB, HIBYTE (LLF_MotorMove->FixMoveSpeed)); DBG (DBG_ASIC, "FixMoveSpeed=%d\n", LLF_MotorMove->FixMoveSpeed); /*Set motor type */ Mustek_SendData (chip, ES01_A6_MotorOption, LLF_MotorMove->MotorSelect | LLF_MotorMove->HomeSensorSelect | LLF_MotorMove-> MotorMoveUnit); /*Set motor speed unit, for all motor mode, //inclue uniform, acc, motor speed of scan */ Mustek_SendData (chip, ES01_F6_MorotControl1, LLF_MotorMove->MotorSpeedUnit | LLF_MotorMove-> MotorSyncUnit); /* below is setting action register */ if (LLF_MotorMove->ActionType == ACTION_TYPE_BACKTOHOME) { DBG (DBG_ASIC, "ACTION_TYPE_BACKTOHOME\n"); temp_motor_action = MOTOR_BACK_HOME_AFTER_SCAN_ENABLE; motor_steps = 30000 * 2; } else { DBG (DBG_ASIC, "Forward or Backward\n"); temp_motor_action = MOTOR_MOVE_TO_FIRST_LINE_ENABLE; motor_steps = LLF_MotorMove->FixMoveSteps; if (LLF_MotorMove->ActionType == ACTION_TYPE_BACKWARD) { DBG (DBG_ASIC, "ACTION_TYPE_BACKWARD\n"); temp_motor_action = temp_motor_action | INVERT_MOTOR_DIRECTION_ENABLE; } } if (LLF_MotorMove->ActionType == ACTION_TYPE_TEST_MODE) { DBG (DBG_ASIC, "ACTION_TYPE_TEST_MODE\n"); temp_motor_action = temp_motor_action | MOTOR_MOVE_TO_FIRST_LINE_ENABLE | MOTOR_BACK_HOME_AFTER_SCAN_ENABLE | MOTOR_TEST_LOOP_ENABLE; } Mustek_SendData (chip, ES01_94_PowerSaveControl, 0x27 | LLF_MotorMove->Lamp0PwmFreq | LLF_MotorMove-> Lamp1PwmFreq); /* fix speed move steps */ Mustek_SendData (chip, ES01_E2_MotorStepOfMaxSpeed0_7, LOBYTE (motor_steps)); Mustek_SendData (chip, ES01_E3_MotorStepOfMaxSpeed8_15, HIBYTE (motor_steps)); Mustek_SendData (chip, ES01_E4_MotorStepOfMaxSpeed16_19, (SANE_Byte) ((motor_steps & 0x00ff0000) >> 16)); DBG (DBG_ASIC, "motor_steps=%d\n", motor_steps); DBG (DBG_ASIC, "LOBYTE(motor_steps)=%d\n", LOBYTE (motor_steps)); DBG (DBG_ASIC, "HIBYTE(motor_steps)=%d\n", HIBYTE (motor_steps)); DBG (DBG_ASIC, "(SANE_Byte)((motor_steps & 0x00ff0000) >> 16)=%d\n", (SANE_Byte) ((motor_steps & 0x00ff0000) >> 16)); if (LLF_MotorMove->ActionMode == ACTION_MODE_UNIFORM_SPEED_MOVE) { temp_motor_action = temp_motor_action | UNIFORM_MOTOR_AND_SCAN_SPEED_ENABLE; } Mustek_SendData (chip, ES01_F3_ActionOption, SCAN_DISABLE | SCAN_BACK_TRACKING_DISABLE | temp_motor_action); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_ENABLE); if (LLF_MotorMove->WaitOrNoWait == 1) { if (LLF_MotorMove->ActionType == ACTION_TYPE_BACKTOHOME) { DBG (DBG_ASIC, "ACTION_TYPE_BACKTOHOME\n"); Asic_WaitCarriageHome (chip, FALSE); } else { Asic_WaitUnitReady (chip); } } DBG (DBG_ASIC, "LLFMotorMove:Exit\n"); return status; } static STATUS SetMotorStepTable (PAsic chip, LLF_MOTORMOVE * MotorStepsTable, unsigned short wStartY, unsigned int dwScanImageSteps, unsigned short wYResolution) { STATUS status = STATUS_GOOD; unsigned short wAccSteps = 511; unsigned short wForwardSteps = 20; SANE_Byte bDecSteps = 255; unsigned short wMotorSycnPixelNumber = 0; unsigned short wScanAccSteps = 511; SANE_Byte bScanDecSteps = 255; unsigned short wFixScanSteps = 20; unsigned short wScanBackTrackingSteps = 40; unsigned short wScanRestartSteps = 40; unsigned short wScanBackHomeExtSteps = 100; unsigned int dwTotalMotorSteps; DBG (DBG_ASIC, "SetMotorStepTable:Enter\n"); dwTotalMotorSteps = dwScanImageSteps; switch (wYResolution) { case 2400: case 1200: wScanAccSteps = 100; bScanDecSteps = 10; wScanBackTrackingSteps = 10; wScanRestartSteps = 10; break; case 600: case 300: wScanAccSteps = 300; bScanDecSteps = 40; break; case 150: wScanAccSteps = 300; bScanDecSteps = 40; break; case 100: case 75: case 50: wScanAccSteps = 300; bScanDecSteps = 40; break; } if (wStartY < (wAccSteps + wForwardSteps + bDecSteps + wScanAccSteps)) /*not including T0,T1 steps */ { wAccSteps = 1; bDecSteps = 1; wFixScanSteps = (wStartY - wScanAccSteps) > 0 ? (wStartY - wScanAccSteps) : 0; wForwardSteps = 0; chip->isMotorGoToFirstLine = MOTOR_MOVE_TO_FIRST_LINE_DISABLE; } else { wForwardSteps = (wStartY - wAccSteps - (unsigned short) bDecSteps - wScanAccSteps - wFixScanSteps) > 0 ? (wStartY - wAccSteps - (unsigned short) bDecSteps - wScanAccSteps - wFixScanSteps) : 0; chip->isMotorGoToFirstLine = MOTOR_MOVE_TO_FIRST_LINE_ENABLE; } dwTotalMotorSteps += wAccSteps; dwTotalMotorSteps += wForwardSteps; dwTotalMotorSteps += bDecSteps; dwTotalMotorSteps += wScanAccSteps; dwTotalMotorSteps += wFixScanSteps; dwTotalMotorSteps += bScanDecSteps; dwTotalMotorSteps += 2; MotorStepsTable->AccStep = wAccSteps; MotorStepsTable->DecStep = bDecSteps; MotorStepsTable->wForwardSteps = wForwardSteps; MotorStepsTable->wScanAccSteps = wScanAccSteps; MotorStepsTable->bScanDecSteps = bScanDecSteps; MotorStepsTable->wFixScanSteps = wFixScanSteps; MotorStepsTable->MotorSyncUnit = (SANE_Byte) wMotorSycnPixelNumber; MotorStepsTable->wScanBackHomeExtSteps = wScanBackHomeExtSteps; MotorStepsTable->wScanRestartSteps = wScanRestartSteps; MotorStepsTable->wScanBackTrackingSteps = wScanBackTrackingSteps; /*state 1 */ Mustek_SendData (chip, ES01_E0_MotorAccStep0_7, LOBYTE (wAccSteps)); Mustek_SendData (chip, ES01_E1_MotorAccStep8_8, HIBYTE (wAccSteps)); /*state 2 */ Mustek_SendData (chip, ES01_E2_MotorStepOfMaxSpeed0_7, LOBYTE (wForwardSteps)); Mustek_SendData (chip, ES01_E3_MotorStepOfMaxSpeed8_15, HIBYTE (wForwardSteps)); Mustek_SendData (chip, ES01_E4_MotorStepOfMaxSpeed16_19, 0); /*state 3 */ Mustek_SendData (chip, ES01_E5_MotorDecStep, bDecSteps); /*state 4 */ Mustek_SendData (chip, ES01_AE_MotorSyncPixelNumberM16LSB, LOBYTE (wMotorSycnPixelNumber)); Mustek_SendData (chip, ES01_AF_MotorSyncPixelNumberM16MSB, HIBYTE (wMotorSycnPixelNumber)); /*state 5 */ Mustek_SendData (chip, ES01_EC_ScanAccStep0_7, LOBYTE (wScanAccSteps)); Mustek_SendData (chip, ES01_ED_ScanAccStep8_8, HIBYTE (wScanAccSteps)); /*state 6 */ Mustek_SendData (chip, ES01_EE_FixScanStepLSB, LOBYTE (wFixScanSteps)); Mustek_SendData (chip, ES01_8A_FixScanStepMSB, HIBYTE (wFixScanSteps)); /*state 8 */ Mustek_SendData (chip, ES01_EF_ScanDecStep, bScanDecSteps); /*state 10 */ Mustek_SendData (chip, ES01_E6_ScanBackTrackingStepLSB, LOBYTE (wScanBackTrackingSteps)); Mustek_SendData (chip, ES01_E7_ScanBackTrackingStepMSB, HIBYTE (wScanBackTrackingSteps)); /*state 15 */ Mustek_SendData (chip, ES01_E8_ScanRestartStepLSB, LOBYTE (wScanRestartSteps)); Mustek_SendData (chip, ES01_E9_ScanRestartStepMSB, HIBYTE (wScanRestartSteps)); /*state 19 */ Mustek_SendData (chip, ES01_EA_ScanBackHomeExtStepLSB, LOBYTE (wScanBackHomeExtSteps)); Mustek_SendData (chip, ES01_EB_ScanBackHomeExtStepMSB, HIBYTE (wScanBackHomeExtSteps)); /*total motor steps */ Mustek_SendData (chip, ES01_F0_ScanImageStep0_7, LOBYTE (dwTotalMotorSteps)); Mustek_SendData (chip, ES01_F1_ScanImageStep8_15, HIBYTE (dwTotalMotorSteps)); Mustek_SendData (chip, ES01_F2_ScanImageStep16_19, (SANE_Byte) ((dwTotalMotorSteps & 0x00ff0000) >> 16)); DBG (DBG_ASIC, "SetMotorStepTable:Exit\n"); return status; } static STATUS CalculateMotorTable (LLF_CALCULATEMOTORTABLE * lpCalculateMotorTable, unsigned short wYResolution) { STATUS status = STATUS_GOOD; unsigned short i; unsigned short wEndSpeed, wStartSpeed; unsigned short wScanAccSteps; SANE_Byte bScanDecSteps; double PI = 3.1415926; double x = PI / 2; long double y; unsigned short *lpMotorTable; DBG (DBG_ASIC, "CalculateMotorTable:Enter\n"); wStartSpeed = lpCalculateMotorTable->StartSpeed; wEndSpeed = lpCalculateMotorTable->EndSpeed; wScanAccSteps = lpCalculateMotorTable->AccStepBeforeScan; bScanDecSteps = lpCalculateMotorTable->DecStepAfterScan; lpMotorTable = lpCalculateMotorTable->lpMotorTable; /*Motor T0 & T6 Acc Table */ for (i = 0; i < 512; i++) { y = (6000 - 3500); y *= (pow (0.09, (x * i) / 512) - pow (0.09, (x * 511) / 512)); y += 4500; *((unsigned short *) lpMotorTable + i) = (unsigned short) y; /*T0 */ *((unsigned short *) lpMotorTable + i + 512 * 6) = (unsigned short) y; /*T6 */ } /*Motor T1 & T7 Dec Table */ for (i = 0; i < 256; i++) { y = (6000 - 3500); y *= pow (0.3, (x * i) / 256); y = 6000 - y; *((unsigned short *) lpMotorTable + i + 512) = (unsigned short) y; /*T1 */ *((unsigned short *) lpMotorTable + i + 512 * 7) = (unsigned short) y; /*T7 */ } switch (wYResolution) { case 2400: case 1200: case 600: case 300: case 150: case 100: case 75: case 50: for (i = 0; i < wScanAccSteps; i++) { y = (wStartSpeed - wEndSpeed); y *= (pow (0.09, (x * i) / wScanAccSteps) - pow (0.09, (x * (wScanAccSteps - 1)) / wScanAccSteps)); y += wEndSpeed; *((unsigned short *) lpMotorTable + i + 512 * 2) = (unsigned short) y; /*T2 */ *((unsigned short *) lpMotorTable + i + 512 * 4) = (unsigned short) y; /*T4 */ } for (i = wScanAccSteps; i < 512; i++) { *((unsigned short *) lpMotorTable + i + 512 * 2) = (unsigned short) wEndSpeed; /*T2 */ *((unsigned short *) lpMotorTable + i + 512 * 4) = (unsigned short) wEndSpeed; /*T4 */ } for (i = 0; i < (unsigned short) bScanDecSteps; i++) { y = (wStartSpeed - wEndSpeed); y *= pow (0.3, (x * i) / bScanDecSteps); y = wStartSpeed - y; *((unsigned short *) lpMotorTable + i + 512 * 3) = (unsigned short) (y); /*T3 */ *((unsigned short *) lpMotorTable + i + 512 * 5) = (unsigned short) (y); /*T5 */ } for (i = bScanDecSteps; i < 256; i++) { *((unsigned short *) lpMotorTable + i + 512 * 3) = (unsigned short) wStartSpeed; /*T3 */ *((unsigned short *) lpMotorTable + i + 512 * 5) = (unsigned short) wStartSpeed; /*T5 */ } break; } DBG (DBG_ASIC, "CalculateMotorTable:Exit\n"); return status; } static STATUS LLFCalculateMotorTable (LLF_CALCULATEMOTORTABLE * LLF_CalculateMotorTable) { STATUS status = STATUS_GOOD; unsigned short i; double PI = 3.1415926535; double x; DBG (DBG_ASIC, "LLF_CALCULATEMOTORTABLE:Enter\n"); x = PI / 2; for (i = 0; i < 512; i++) { /* befor scan acc table */ *(LLF_CalculateMotorTable->lpMotorTable + i) = (unsigned short) ((LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.09, (x * i) / 512) + LLF_CalculateMotorTable->EndSpeed); *(LLF_CalculateMotorTable->lpMotorTable + i + 512 * 2) = (unsigned short) ((LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.09, (x * i) / 512) + LLF_CalculateMotorTable->EndSpeed); *(LLF_CalculateMotorTable->lpMotorTable + i + 512 * 4) = (unsigned short) ((LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.09, (x * i) / 512) + LLF_CalculateMotorTable->EndSpeed); *(LLF_CalculateMotorTable->lpMotorTable + i + 512 * 6) = (unsigned short) ((LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.09, (x * i) / 512) + LLF_CalculateMotorTable->EndSpeed); } for (i = 0; i < 255; i++) { *(LLF_CalculateMotorTable->lpMotorTable + i + 512) = (unsigned short) (LLF_CalculateMotorTable->StartSpeed - (LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.3, (x * i) / 256)); *(LLF_CalculateMotorTable->lpMotorTable + i + 512 * 3) = (unsigned short) (LLF_CalculateMotorTable->StartSpeed - (LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.3, (x * i) / 256)); *(LLF_CalculateMotorTable->lpMotorTable + i + 512 * 5) = (unsigned short) (LLF_CalculateMotorTable->StartSpeed - (LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.3, (x * i) / 256)); *(LLF_CalculateMotorTable->lpMotorTable + i + 512 * 7) = (unsigned short) (LLF_CalculateMotorTable->StartSpeed - (LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.3, (x * i) / 256)); } for (i = 0; i < 512; i++) { /* back acc table */ *(LLF_CalculateMotorTable->lpMotorTable + i) = (unsigned short) ((LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.09, (x * i) / 512) + LLF_CalculateMotorTable->EndSpeed); *(LLF_CalculateMotorTable->lpMotorTable + i + 512 * 6) = (unsigned short) ((LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * pow (0.09, (x * i) / 512) + LLF_CalculateMotorTable->EndSpeed); } if (LLF_CalculateMotorTable->AccStepBeforeScan == 0) { } else { for (i = 0; i < LLF_CalculateMotorTable->AccStepBeforeScan; i++) { *(LLF_CalculateMotorTable->lpMotorTable + i + 512 * 2) = (unsigned short) ((LLF_CalculateMotorTable->StartSpeed - LLF_CalculateMotorTable->EndSpeed) * (pow (0.09, (x * i) / LLF_CalculateMotorTable-> AccStepBeforeScan) - pow (0.09, (x * (LLF_CalculateMotorTable-> AccStepBeforeScan - 1)) / LLF_CalculateMotorTable-> AccStepBeforeScan)) + LLF_CalculateMotorTable->EndSpeed); } } DBG (DBG_ASIC, "LLF_CALCULATEMOTORTABLE:Exit\n"); return status; } static STATUS SetMotorCurrent (PAsic chip, unsigned short dwMotorSpeed, LLF_MOTOR_CURRENT_AND_PHASE * CurrentPhase) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "SetMotorCurrent:Enter\n"); chip = chip; if (dwMotorSpeed < 2000) { CurrentPhase->MotorCurrentTableA[0] = 255; CurrentPhase->MotorCurrentTableB[0] = 255; } else if (dwMotorSpeed < 3500) { CurrentPhase->MotorCurrentTableA[0] = 200; CurrentPhase->MotorCurrentTableB[0] = 200; } else if (dwMotorSpeed < 5000) { CurrentPhase->MotorCurrentTableA[0] = 160; CurrentPhase->MotorCurrentTableB[0] = 160; } else if (dwMotorSpeed < 10000) { CurrentPhase->MotorCurrentTableA[0] = 70; CurrentPhase->MotorCurrentTableB[0] = 70; } else if (dwMotorSpeed < 17000) { CurrentPhase->MotorCurrentTableA[0] = 60; CurrentPhase->MotorCurrentTableB[0] = 60; } else if (dwMotorSpeed < 25000) { CurrentPhase->MotorCurrentTableA[0] = 50; CurrentPhase->MotorCurrentTableB[0] = 50; } else { CurrentPhase->MotorCurrentTableA[0] = 50; CurrentPhase->MotorCurrentTableB[0] = 50; } DBG (DBG_ASIC, "SetMotorCurrent:Exit\n"); return status; } static STATUS MotorBackHome (PAsic chip, SANE_Byte WaitOrNoWait) { STATUS status = STATUS_GOOD; unsigned short BackHomeMotorTable[512 * 8]; LLF_CALCULATEMOTORTABLE CalMotorTable; LLF_MOTOR_CURRENT_AND_PHASE CurrentPhase; LLF_SETMOTORTABLE LLF_SetMotorTable; LLF_MOTORMOVE MotorMove; DBG (DBG_ASIC, "MotorBackHome:Enter\n"); CalMotorTable.StartSpeed = 5000; CalMotorTable.EndSpeed = 1200; CalMotorTable.AccStepBeforeScan = 511; CalMotorTable.DecStepAfterScan = 255; CalMotorTable.lpMotorTable = BackHomeMotorTable; LLFCalculateMotorTable (&CalMotorTable); CurrentPhase.MotorCurrentTableA[0] = 220; CurrentPhase.MotorCurrentTableB[0] = 220; CurrentPhase.MoveType = _4_TABLE_SPACE_FOR_FULL_STEP; LLFSetMotorCurrentAndPhase (chip, &CurrentPhase); LLF_SetMotorTable.MotorTableAddress = 0; LLF_SetMotorTable.MotorTablePtr = BackHomeMotorTable; LLFSetMotorTable (chip, &LLF_SetMotorTable); MotorMove.MotorSelect = MOTOR_0_ENABLE | MOTOR_1_DISABLE; MotorMove.MotorMoveUnit = ES03_TABLE_DEFINE; MotorMove.MotorSpeedUnit = SPEED_UNIT_1_PIXEL_TIME; MotorMove.MotorSyncUnit = MOTOR_SYNC_UNIT_1_PIXEL_TIME; MotorMove.HomeSensorSelect = HOME_SENSOR_0_ENABLE; MotorMove.ActionMode = ACTION_MODE_ACCDEC_MOVE; MotorMove.ActionType = ACTION_TYPE_BACKTOHOME; MotorMove.AccStep = 511; MotorMove.DecStep = 255; MotorMove.FixMoveSteps = 0; MotorMove.FixMoveSpeed = 3000; MotorMove.WaitOrNoWait = WaitOrNoWait; LLFMotorMove (chip, &MotorMove); DBG (DBG_ASIC, "MotorBackHome:Exit\n"); return status; } static STATUS LLFSetRamAddress (PAsic chip, unsigned int dwStartAddr, unsigned int dwEndAddr, SANE_Byte byAccessTarget) { STATUS status = STATUS_GOOD; SANE_Byte * pStartAddr = (SANE_Byte *) & dwStartAddr; SANE_Byte * pEndAddr = (SANE_Byte *) & dwEndAddr; DBG (DBG_ASIC, "LLFSetRamAddress:Enter\n"); /*Set start address. */ Mustek_SendData (chip, ES01_A0_HostStartAddr0_7, *(pStartAddr)); Mustek_SendData (chip, ES01_A1_HostStartAddr8_15, *(pStartAddr + 1)); if (byAccessTarget == ACCESS_DRAM) Mustek_SendData (chip, ES01_A2_HostStartAddr16_21, *(pStartAddr + 2) | ACCESS_DRAM); else Mustek_SendData (chip, ES01_A2_HostStartAddr16_21, *(pStartAddr + 2) | ACCESS_GAMMA_RAM); /*Set end address. */ Mustek_SendData (chip, ES01_A3_HostEndAddr0_7, *(pEndAddr)); Mustek_SendData (chip, ES01_A4_HostEndAddr8_15, *(pEndAddr + 1)); Mustek_SendData (chip, ES01_A5_HostEndAddr16_21, *(pEndAddr + 2)); Mustek_ClearFIFO (chip); DBG (DBG_ASIC, "LLFSetRamAddress:Exit\n"); return status; } /* ---------------------- medium level asic functions ---------------------- */ static STATUS InitTiming (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "InitTiming:Enter\n"); chip->Timing.AFE_ADCCLK_Timing = 1010580480; chip->Timing.AFE_ADCVS_Timing = 12582912; chip->Timing.AFE_ADCRS_Timing = 3072; chip->Timing.AFE_ChannelA_LatchPos = 3080; chip->Timing.AFE_ChannelB_LatchPos = 3602; chip->Timing.AFE_ChannelC_LatchPos = 5634; chip->Timing.AFE_ChannelD_LatchPos = 1546; chip->Timing.AFE_Secondary_FF_LatchPos = 12; /* Sensor */ chip->Timing.CCD_DummyCycleTiming = 0; chip->Timing.PHTG_PluseWidth = 12; chip->Timing.PHTG_WaitWidth = 1; chip->Timing.PHTG_TimingAdj = 1; chip->Timing.PHTG_TimingSetup = 0; chip->Timing.ChannelR_StartPixel = 100; chip->Timing.ChannelR_EndPixel = 200; chip->Timing.ChannelG_StartPixel = 100; chip->Timing.ChannelG_EndPixel = 200; chip->Timing.ChannelB_StartPixel = 100; chip->Timing.ChannelB_EndPixel = 200; /*1200dpi Timing */ chip->Timing.CCD_PH2_Timing_1200 = 1048320; chip->Timing.CCD_PHRS_Timing_1200 = 983040; chip->Timing.CCD_PHCP_Timing_1200 = 61440; chip->Timing.CCD_PH1_Timing_1200 = 4293918720u; chip->Timing.DE_CCD_SETUP_REGISTER_1200 = 32; chip->Timing.wCCDPixelNumber_1200 = 11250; /*600dpi Timing */ chip->Timing.CCD_PH2_Timing_600 = 1048320; chip->Timing.CCD_PHRS_Timing_600 = 983040; chip->Timing.CCD_PHCP_Timing_600 = 61440; chip->Timing.CCD_PH1_Timing_600 = 4293918720u; chip->Timing.DE_CCD_SETUP_REGISTER_600 = 0; chip->Timing.wCCDPixelNumber_600 = 7500; DBG (DBG_ASIC, "InitTiming:Exit\n"); return status; } static STATUS OpenScanChip (PAsic chip) { STATUS status = STATUS_GOOD; SANE_Byte x[4]; DBG (DBG_ASIC, "OpenScanChip:Enter\n"); x[0] = 0x64; x[1] = 0x64; x[2] = 0x64; x[3] = 0x64; status = WriteIOControl (chip, 0x90, 0, 4, x); if (status != STATUS_GOOD) return status; x[0] = 0x65; x[1] = 0x65; x[2] = 0x65; x[3] = 0x65; status = WriteIOControl (chip, 0x90, 0, 4, x); if (status != STATUS_GOOD) return status; x[0] = 0x44; x[1] = 0x44; x[2] = 0x44; x[3] = 0x44; status = WriteIOControl (chip, 0x90, 0, 4, x); if (status != STATUS_GOOD) return status; x[0] = 0x45; x[1] = 0x45; x[2] = 0x45; x[3] = 0x45; status = WriteIOControl (chip, 0x90, 0, 4, x); DBG (DBG_ASIC, "OpenScanChip: Exit\n"); return status; } static STATUS CloseScanChip (PAsic chip) { STATUS status = STATUS_GOOD; SANE_Byte x[4]; DBG (DBG_ASIC, "CloseScanChip:Enter\n"); x[0] = 0x64; x[1] = 0x64; x[2] = 0x64; x[3] = 0x64; status = WriteIOControl (chip, 0x90, 0, 4, x); if (status != STATUS_GOOD) return status; x[0] = 0x65; x[1] = 0x65; x[2] = 0x65; x[3] = 0x65; status = WriteIOControl (chip, 0x90, 0, 4, x); if (status != STATUS_GOOD) return status; x[0] = 0x16; x[1] = 0x16; x[2] = 0x16; x[3] = 0x16; status = WriteIOControl (chip, 0x90, 0, 4, x); if (status != STATUS_GOOD) return status; x[0] = 0x17; x[1] = 0x17; x[2] = 0x17; x[3] = 0x17; status = WriteIOControl (chip, 0x90, 0, 4, x); DBG (DBG_ASIC, "CloseScanChip: Exit\n"); return status; } static STATUS SafeInitialChip (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "SafeInitialChip:Enter\n"); Mustek_SendData (chip, ES01_F3_ActionOption, 0); Mustek_SendData (chip, ES01_86_DisableAllClockWhenIdle, CLOSE_ALL_CLOCK_DISABLE); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); status = Asic_WaitUnitReady (chip); DBG (DBG_ASIC, "isFirstOpenChip=%d\n", chip->isFirstOpenChip); if (chip->isFirstOpenChip) { DBG (DBG_ASIC, "isFirstOpenChip=%d\n", chip->isFirstOpenChip); status = DRAM_Test (chip); if (status != STATUS_GOOD) { DBG (DBG_ASIC, "DRAM_Test: Error\n"); return status; } chip->isFirstOpenChip = FALSE; } DBG (DBG_ASIC, "SafeInitialChip: exit\n"); return status; } static STATUS DRAM_Test (PAsic chip) { STATUS status = STATUS_GOOD; unsigned char *temps; unsigned int i; DBG (DBG_ASIC, "DRAM_Test:Enter\n"); temps = (unsigned char *) malloc (64); for (i = 0; i < 64; i++) { *(temps + i) = i; } /*set start address */ status = Mustek_SendData (chip, ES01_A0_HostStartAddr0_7, 0x00); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_SendData (chip, ES01_A1_HostStartAddr8_15, 0x00); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_SendData (chip, ES01_A2_HostStartAddr16_21, 0x00 | ACCESS_DRAM); if (status != STATUS_GOOD) { free (temps); return status; } Mustek_SendData (chip, ES01_79_AFEMCLK_SDRAMCLK_DELAY_CONTROL, SDRAMCLK_DELAY_12_ns); status = Mustek_SendData (chip, ES01_A3_HostEndAddr0_7, 0xff); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_SendData (chip, ES01_A4_HostEndAddr8_15, 0xff); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_SendData (chip, ES01_A5_HostEndAddr16_21, 0xff); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_DMAWrite (chip, 64, (SANE_Byte *) (temps)); if (status != STATUS_GOOD) { DBG (DBG_ASIC, "Mustek_DMAWrite error\n"); free (temps); return status; } status = Mustek_SendData (chip, ES01_A0_HostStartAddr0_7, 0x00); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_SendData (chip, ES01_A1_HostStartAddr8_15, 0x00); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_SendData (chip, ES01_A2_HostStartAddr16_21, 0x00 | ACCESS_DRAM); if (status != STATUS_GOOD) { free (temps); return status; } /*set end address */ status = Mustek_SendData (chip, ES01_A3_HostEndAddr0_7, 0xff); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_SendData (chip, ES01_A4_HostEndAddr8_15, 0xff); if (status != STATUS_GOOD) { free (temps); return status; } status = Mustek_SendData (chip, ES01_A5_HostEndAddr16_21, 0xff); if (status != STATUS_GOOD) { free (temps); return status; } memset (temps, 0, 64); status = Mustek_DMARead (chip, 64, (SANE_Byte *) (temps)); if (status != STATUS_GOOD) { free (temps); return status; } for (i = 0; i < 60; i += 10) { DBG (DBG_ASIC, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", *(temps + i), *(temps + i + 1), *(temps + i + 2), *(temps + i + 3), *(temps + i + 4), *(temps + i + 5), *(temps + i + 6), *(temps + i + 7), *(temps + i + 8), *(temps + i + 9)); } for (i = 0; i < 64; i++) { if (*(temps + i) != i) { DBG (DBG_ERR, "DRAM Test error...(No.=%d)\n", i + 1); return STATUS_IO_ERROR; } } free (temps); DBG (DBG_ASIC, "DRAM_Text: Exit\n"); return status; } #if SANE_UNUSED static STATUS SetPowerSave (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "SetPowerSave:Enter\n"); if (chip->firmwarestate < FS_OPENED) OpenScanChip (chip); if (chip->firmwarestate > FS_OPENED) Asic_ScanStop (chip); Mustek_SendData (chip, ES01_94_PowerSaveControl, 0x10); chip->firmwarestate = FS_OPENED; DBG (DBG_ASIC, "SetPowerSave:Exit\n"); return status; } #endif static STATUS SetLineTimeAndExposure (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "SetLineTimeAndExposure:Enter\n"); if (chip->firmwarestate < FS_OPENED) OpenScanChip (chip); Mustek_SendData (chip, ES01_C4_MultiTGTimesRed, 0); Mustek_SendData (chip, ES01_C5_MultiTGTimesGreen, 0); Mustek_SendData (chip, ES01_C6_MultiTGTimesBlue, 0); Mustek_SendData (chip, ES01_C7_MultiTGDummyPixelNumberLSB, 0); Mustek_SendData (chip, ES01_C8_MultiTGDummyPixelNumberMSB, 0); Mustek_SendData (chip, ES01_C9_CCDDummyPixelNumberLSB, 0); Mustek_SendData (chip, ES01_CA_CCDDummyPixelNumberMSB, 0); Mustek_SendData (chip, ES01_CB_CCDDummyCycleNumber, 0); chip->firmwarestate = FS_OPENED; DBG (DBG_ASIC, "SetLineTimeAndExposure:Exit\n"); return status; } static STATUS CCDTiming (PAsic chip) { STATUS status = STATUS_GOOD; unsigned int dwPH1, dwPH2, dwPHRS, dwPHCP; DBG (DBG_ASIC, "CCDTiming:Enter\n"); DBG (DBG_ASIC, "Dpi=%d\n", chip->Scan.Dpi); if (chip->firmwarestate < FS_OPENED) OpenScanChip (chip); Mustek_SendData (chip, ES01_82_AFE_ADCCLK_TIMING_ADJ_BYTE0, (SANE_Byte) (chip->Timing.AFE_ADCCLK_Timing)); Mustek_SendData (chip, ES01_83_AFE_ADCCLK_TIMING_ADJ_BYTE1, (SANE_Byte) (chip->Timing.AFE_ADCCLK_Timing >> 8)); Mustek_SendData (chip, ES01_84_AFE_ADCCLK_TIMING_ADJ_BYTE2, (SANE_Byte) (chip->Timing.AFE_ADCCLK_Timing >> 16)); Mustek_SendData (chip, ES01_85_AFE_ADCCLK_TIMING_ADJ_BYTE3, (SANE_Byte) (chip->Timing.AFE_ADCCLK_Timing >> 24)); Mustek_SendData (chip, ES01_1F0_AFERS_TIMING_ADJ_B0, (SANE_Byte) (chip->Timing.AFE_ADCRS_Timing)); Mustek_SendData (chip, ES01_1F1_AFERS_TIMING_ADJ_B1, (SANE_Byte) (chip->Timing.AFE_ADCRS_Timing >> 8)); Mustek_SendData (chip, ES01_1F2_AFERS_TIMING_ADJ_B2, (SANE_Byte) (chip->Timing.AFE_ADCRS_Timing >> 16)); Mustek_SendData (chip, ES01_1F3_AFERS_TIMING_ADJ_B3, (SANE_Byte) (chip->Timing.AFE_ADCRS_Timing >> 24)); Mustek_SendData (chip, ES01_1EC_AFEVS_TIMING_ADJ_B0, (SANE_Byte) (chip->Timing.AFE_ADCVS_Timing)); Mustek_SendData (chip, ES01_1ED_AFEVS_TIMING_ADJ_B1, (SANE_Byte) (chip->Timing.AFE_ADCVS_Timing >> 8)); Mustek_SendData (chip, ES01_1EE_AFEVS_TIMING_ADJ_B2, (SANE_Byte) (chip->Timing.AFE_ADCVS_Timing >> 16)); Mustek_SendData (chip, ES01_1EF_AFEVS_TIMING_ADJ_B3, (SANE_Byte) (chip->Timing.AFE_ADCVS_Timing >> 24)); Mustek_SendData (chip, ES01_160_CHANNEL_A_LATCH_POSITION_HB, HIBYTE (chip->Timing.AFE_ChannelA_LatchPos)); Mustek_SendData (chip, ES01_161_CHANNEL_A_LATCH_POSITION_LB, LOBYTE (chip->Timing.AFE_ChannelA_LatchPos)); Mustek_SendData (chip, ES01_162_CHANNEL_B_LATCH_POSITION_HB, HIBYTE (chip->Timing.AFE_ChannelB_LatchPos)); Mustek_SendData (chip, ES01_163_CHANNEL_B_LATCH_POSITION_LB, LOBYTE (chip->Timing.AFE_ChannelB_LatchPos)); Mustek_SendData (chip, ES01_164_CHANNEL_C_LATCH_POSITION_HB, HIBYTE (chip->Timing.AFE_ChannelC_LatchPos)); Mustek_SendData (chip, ES01_165_CHANNEL_C_LATCH_POSITION_LB, LOBYTE (chip->Timing.AFE_ChannelC_LatchPos)); Mustek_SendData (chip, ES01_166_CHANNEL_D_LATCH_POSITION_HB, HIBYTE (chip->Timing.AFE_ChannelD_LatchPos)); Mustek_SendData (chip, ES01_167_CHANNEL_D_LATCH_POSITION_LB, LOBYTE (chip->Timing.AFE_ChannelD_LatchPos)); Mustek_SendData (chip, ES01_168_SECONDARY_FF_LATCH_POSITION, chip->Timing.AFE_Secondary_FF_LatchPos); Mustek_SendData (chip, ES01_1D0_DUMMY_CYCLE_TIMING_B0, (SANE_Byte) (chip->Timing.CCD_DummyCycleTiming)); Mustek_SendData (chip, ES01_1D1_DUMMY_CYCLE_TIMING_B1, (SANE_Byte) (chip->Timing.CCD_DummyCycleTiming >> 8)); Mustek_SendData (chip, ES01_1D2_DUMMY_CYCLE_TIMING_B2, (SANE_Byte) (chip->Timing.CCD_DummyCycleTiming >> 16)); Mustek_SendData (chip, ES01_1D3_DUMMY_CYCLE_TIMING_B3, (SANE_Byte) (chip->Timing.CCD_DummyCycleTiming >> 24)); if (chip->Scan.Dpi >= 1200) { dwPH1 = chip->Timing.CCD_PH1_Timing_1200; dwPH2 = chip->Timing.CCD_PH2_Timing_1200; dwPHRS = chip->Timing.CCD_PHRS_Timing_1200; dwPHCP = chip->Timing.CCD_PHCP_Timing_1200; } else { dwPH1 = chip->Timing.CCD_PH1_Timing_600; dwPH2 = chip->Timing.CCD_PH2_Timing_600; dwPHRS = chip->Timing.CCD_PHRS_Timing_600; dwPHCP = chip->Timing.CCD_PHCP_Timing_600; } Mustek_SendData (chip, ES01_1D4_PH1_TIMING_ADJ_B0, (SANE_Byte) (dwPH1)); Mustek_SendData (chip, ES01_1D5_PH1_TIMING_ADJ_B1, (SANE_Byte) (dwPH1 >> 8)); Mustek_SendData (chip, ES01_1D6_PH1_TIMING_ADJ_B2, (SANE_Byte) (dwPH1 >> 16)); Mustek_SendData (chip, ES01_1D7_PH1_TIMING_ADJ_B3, (SANE_Byte) (dwPH1 >> 24)); /* set ccd ph1 ph2 rs cp */ Mustek_SendData (chip, ES01_D0_PH1_0, 0); Mustek_SendData (chip, ES01_D1_PH2_0, 4); Mustek_SendData (chip, ES01_D4_PHRS_0, 0); Mustek_SendData (chip, ES01_D5_PHCP_0, 0); Mustek_SendData (chip, ES01_1D8_PH2_TIMING_ADJ_B0, (SANE_Byte) (dwPH2)); Mustek_SendData (chip, ES01_1D9_PH2_TIMING_ADJ_B1, (SANE_Byte) (dwPH2 >> 8)); Mustek_SendData (chip, ES01_1DA_PH2_TIMING_ADJ_B2, (SANE_Byte) (dwPH2 >> 16)); Mustek_SendData (chip, ES01_1DB_PH2_TIMING_ADJ_B3, (SANE_Byte) (dwPH2 >> 24)); Mustek_SendData (chip, ES01_1E4_PHRS_TIMING_ADJ_B0, (SANE_Byte) (dwPHRS)); Mustek_SendData (chip, ES01_1E5_PHRS_TIMING_ADJ_B1, (SANE_Byte) (dwPHRS >> 8)); Mustek_SendData (chip, ES01_1E6_PHRS_TIMING_ADJ_B2, (SANE_Byte) (dwPHRS >> 16)); Mustek_SendData (chip, ES01_1E7_PHRS_TIMING_ADJ_B3, (SANE_Byte) (dwPHRS >> 24)); Mustek_SendData (chip, ES01_1E8_PHCP_TIMING_ADJ_B0, (SANE_Byte) (dwPHCP)); Mustek_SendData (chip, ES01_1E9_PHCP_TIMING_ADJ_B1, (SANE_Byte) (dwPHCP >> 8)); Mustek_SendData (chip, ES01_1EA_PHCP_TIMING_ADJ_B2, (SANE_Byte) (dwPHCP >> 16)); Mustek_SendData (chip, ES01_1EB_PHCP_TIMING_ADJ_B3, (SANE_Byte) (dwPHCP >> 24)); chip->firmwarestate = FS_OPENED; DBG (DBG_ASIC, "CCDTiming:Exit\n"); return status; } static STATUS IsCarriageHome (PAsic chip, SANE_Bool * LampHome, SANE_Bool * TAHome) { STATUS status = STATUS_GOOD; SANE_Byte temp; DBG (DBG_ASIC, "IsCarriageHome:Enter\n"); status = GetChipStatus (chip, 0, &temp); if (status != STATUS_GOOD) { DBG (DBG_ASIC, "IsCarriageHome:Error!\n"); return status; } if ((temp & SENSOR0_DETECTED) == SENSOR0_DETECTED) *LampHome = TRUE; else { *LampHome = FALSE; } *TAHome = TRUE; DBG (DBG_ASIC, "LampHome=%d\n", *LampHome); DBG (DBG_ASIC, "IsCarriageHome:Exit\n"); return status; } static STATUS GetChipStatus (PAsic chip, SANE_Byte Selector, SANE_Byte * ChipStatus) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "GetChipStatus:Enter\n"); status = Mustek_SendData (chip, ES01_8B_Status, Selector); if (status != STATUS_GOOD) return status; status = Mustek_WriteAddressLineForRegister (chip, ES01_8B_Status); if (status != STATUS_GOOD) return status; *ChipStatus = ES01_8B_Status; status = Mustek_ReceiveData (chip, ChipStatus); if (status != STATUS_GOOD) return status; DBG (DBG_ASIC, "GetChipStatus:Exit\n"); return status; } static STATUS SetAFEGainOffset (PAsic chip) { STATUS status = STATUS_GOOD; int i = 0; DBG (DBG_ASIC, "SetAFEGainOffset:Enter\n"); if (chip->AD.DirectionR) { /* Negative */ Mustek_SendData (chip, ES01_60_AFE_AUTO_GAIN_OFFSET_RED_LB, (chip->AD.GainR << 1) | 0x01); Mustek_SendData (chip, ES01_61_AFE_AUTO_GAIN_OFFSET_RED_HB, chip->AD.OffsetR); } else { /* Postive */ Mustek_SendData (chip, ES01_60_AFE_AUTO_GAIN_OFFSET_RED_LB, (chip->AD.GainR << 1)); Mustek_SendData (chip, ES01_61_AFE_AUTO_GAIN_OFFSET_RED_HB, chip->AD.OffsetR); } if (chip->AD.DirectionG) { Mustek_SendData (chip, ES01_62_AFE_AUTO_GAIN_OFFSET_GREEN_LB, (chip->AD.GainG << 1) | 0x01); Mustek_SendData (chip, ES01_63_AFE_AUTO_GAIN_OFFSET_GREEN_HB, chip->AD.OffsetG); } else { Mustek_SendData (chip, ES01_62_AFE_AUTO_GAIN_OFFSET_GREEN_LB, (chip->AD.GainG << 1)); Mustek_SendData (chip, ES01_63_AFE_AUTO_GAIN_OFFSET_GREEN_HB, chip->AD.OffsetG); } if (chip->AD.DirectionB) { Mustek_SendData (chip, ES01_64_AFE_AUTO_GAIN_OFFSET_BLUE_LB, (chip->AD.GainB << 1) | 0x01); Mustek_SendData (chip, ES01_65_AFE_AUTO_GAIN_OFFSET_BLUE_HB, chip->AD.OffsetB); } else { Mustek_SendData (chip, ES01_64_AFE_AUTO_GAIN_OFFSET_BLUE_LB, (chip->AD.GainB << 1)); Mustek_SendData (chip, ES01_65_AFE_AUTO_GAIN_OFFSET_BLUE_HB, chip->AD.OffsetB); } Mustek_SendData (chip, ES01_2A0_AFE_GAIN_OFFSET_CONTROL, 0x01); for (i = 0; i < 4; i++) { if (chip->AD.DirectionR == 0) { Mustek_SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN, (SANE_Byte) (chip->AD.GainR << 1)); Mustek_SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET, (SANE_Byte) (chip->AD.OffsetR)); } else { Mustek_SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN, (SANE_Byte) (chip->AD.GainR << 1) | 0x01); Mustek_SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET, (SANE_Byte) (chip->AD.OffsetR)); } } for (i = 0; i < 4; i++) { if (chip->AD.DirectionG == 0) { Mustek_SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN, (SANE_Byte) (chip->AD.GainG << 1)); Mustek_SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET, (SANE_Byte) (chip->AD.OffsetG)); } else { Mustek_SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN, (SANE_Byte) (chip->AD.GainG << 1) | 0x01); Mustek_SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET, (SANE_Byte) (chip->AD.OffsetG)); } } for (i = 0; i < 4; i++) { if (chip->AD.DirectionB == 0) { Mustek_SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN, (SANE_Byte) (chip->AD.GainB << 1)); Mustek_SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET, (SANE_Byte) (chip->AD.OffsetB)); } else { Mustek_SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN, (SANE_Byte) (chip->AD.GainB << 1) | 0x01); Mustek_SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET, (SANE_Byte) (chip->AD.OffsetB)); } } for (i = 0; i < 36; i++) { Mustek_SendData (chip, ES01_2A1_AFE_AUTO_CONFIG_GAIN, 0); Mustek_SendData (chip, ES01_2A2_AFE_AUTO_CONFIG_OFFSET, 0); } Mustek_SendData (chip, ES01_2A0_AFE_GAIN_OFFSET_CONTROL, 0x00); /* Set to AFE */ Mustek_SendData (chip, ES01_04_ADAFEPGACH1, chip->AD.GainR); Mustek_SendData (chip, ES01_06_ADAFEPGACH2, chip->AD.GainG); Mustek_SendData (chip, ES01_08_ADAFEPGACH3, chip->AD.GainB); if (chip->AD.DirectionR) Mustek_SendData (chip, ES01_0B_AD9826OffsetRedN, chip->AD.OffsetR); else Mustek_SendData (chip, ES01_0A_AD9826OffsetRedP, chip->AD.OffsetR); if (chip->AD.DirectionG) Mustek_SendData (chip, ES01_0D_AD9826OffsetGreenN, chip->AD.OffsetG); else Mustek_SendData (chip, ES01_0C_AD9826OffsetGreenP, chip->AD.OffsetG); if (chip->AD.DirectionB) Mustek_SendData (chip, ES01_0F_AD9826OffsetBlueN, chip->AD.OffsetB); else Mustek_SendData (chip, ES01_0E_AD9826OffsetBlueP, chip->AD.OffsetB); LLFSetRamAddress (chip, 0x0, PackAreaStartAddress - (512 * 8 - 1), ACCESS_DRAM); Mustek_SendData (chip, ES01_F3_ActionOption, MOTOR_MOVE_TO_FIRST_LINE_DISABLE | MOTOR_BACK_HOME_AFTER_SCAN_DISABLE | SCAN_ENABLE | SCAN_BACK_TRACKING_DISABLE | INVERT_MOTOR_DIRECTION_DISABLE | UNIFORM_MOTOR_AND_SCAN_SPEED_ENABLE | ES01_STATIC_SCAN_DISABLE | MOTOR_TEST_LOOP_DISABLE); Mustek_SendData (chip, ES01_9A_AFEControl, AD9826_AFE | AUTO_CHANGE_AFE_GAIN_OFFSET_DISABLE); Mustek_SendData (chip, ES01_00_ADAFEConfiguration, 0x70); Mustek_SendData (chip, ES01_02_ADAFEMuxConfig, 0x80); DBG (DBG_ASIC, "SetAFEGainOffset:Exit\n"); return status; } static STATUS SetLEDTime (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "SetLEDTime:Enter\n"); Mustek_SendData (chip, ES01_B8_ChannelRedExpStartPixelLSB, LOBYTE (chip->Timing.ChannelR_StartPixel)); Mustek_SendData (chip, ES01_B9_ChannelRedExpStartPixelMSB, HIBYTE (chip->Timing.ChannelR_StartPixel)); Mustek_SendData (chip, ES01_BA_ChannelRedExpEndPixelLSB, LOBYTE (chip->Timing.ChannelR_EndPixel)); Mustek_SendData (chip, ES01_BB_ChannelRedExpEndPixelMSB, HIBYTE (chip->Timing.ChannelR_EndPixel)); Mustek_SendData (chip, ES01_BC_ChannelGreenExpStartPixelLSB, LOBYTE (chip->Timing.ChannelG_StartPixel)); Mustek_SendData (chip, ES01_BD_ChannelGreenExpStartPixelMSB, HIBYTE (chip->Timing.ChannelG_StartPixel)); Mustek_SendData (chip, ES01_BE_ChannelGreenExpEndPixelLSB, LOBYTE (chip->Timing.ChannelG_EndPixel)); Mustek_SendData (chip, ES01_BF_ChannelGreenExpEndPixelMSB, HIBYTE (chip->Timing.ChannelG_EndPixel)); Mustek_SendData (chip, ES01_C0_ChannelBlueExpStartPixelLSB, LOBYTE (chip->Timing.ChannelB_StartPixel)); Mustek_SendData (chip, ES01_C1_ChannelBlueExpStartPixelMSB, HIBYTE (chip->Timing.ChannelB_StartPixel)); Mustek_SendData (chip, ES01_C2_ChannelBlueExpEndPixelLSB, LOBYTE (chip->Timing.ChannelB_EndPixel)); Mustek_SendData (chip, ES01_C3_ChannelBlueExpEndPixelMSB, HIBYTE (chip->Timing.ChannelB_EndPixel)); DBG (DBG_ASIC, "SetLEDTime:Exit\n"); return status; } static STATUS SetScanMode (PAsic chip, SANE_Byte bScanBits) { STATUS status = STATUS_GOOD; SANE_Byte temp_f5_register = 0; SANE_Byte GrayBWChannel; DBG (DBG_ASIC, "SetScanMode():Enter; set f5 register\n"); if (bScanBits >= 24) { temp_f5_register |= COLOR_ES02; } else { temp_f5_register |= GRAY_ES02; } if ((bScanBits == 8) || (bScanBits == 24)) { temp_f5_register |= _8_BITS_ES02; } else if (bScanBits == 1) { temp_f5_register |= _1_BIT_ES02; } else { temp_f5_register |= _16_BITS_ES02; } if (bScanBits < 24) { GrayBWChannel = 1; } else { GrayBWChannel = 4; } if (GrayBWChannel == 0) { temp_f5_register |= GRAY_RED_ES02; } else if (GrayBWChannel == 1) { temp_f5_register |= GRAY_GREEN_ES02; } else if (GrayBWChannel == 2) { temp_f5_register |= GRAY_BLUE_ES02; } else { temp_f5_register |= GRAY_GREEN_BLUE_ES02; } status = Mustek_SendData (chip, ES01_F5_ScanDataFormat, temp_f5_register); DBG (DBG_ASIC, "F5_ScanDataFormat=0x%x\n", temp_f5_register); DBG (DBG_ASIC, "SetScanMode():Exit\n"); return status; } static STATUS SetPackAddress (PAsic chip, unsigned short wXResolution, unsigned short wWidth, unsigned short wX, double XRatioAdderDouble, double XRatioTypeDouble, SANE_Byte byClear_Pulse_Width, unsigned short * PValidPixelNumber) { STATUS status = STATUS_GOOD; SANE_Byte OverLapPixel; SANE_Byte TotalLineShift; unsigned short SegmentTotalPixel; unsigned int dwLineTotalPixel; unsigned short ValidPixelNumber = *PValidPixelNumber; unsigned int FinalLinePixelPerSegment; SANE_Byte InValidPixelNumber; unsigned int CISPackAreaStartAddress; SANE_Byte PackAreaUseLine; unsigned int MaxPixelHW; int i; DBG (DBG_ASIC, "SetPackAddress:Enter\n"); OverLapPixel = 0; TotalLineShift = 1; PackAreaUseLine = TotalLineShift + 1; if (wXResolution > (SENSOR_DPI / 2)) { ValidPixelNumber = ValidPixelNumberFor1200DPI; OverLapPixel = OverLapPixelNumber1200; } else { ValidPixelNumber = ValidPixelNumberFor600DPI; OverLapPixel = OverLapPixelNumber600; } ValidPixelNumber = (unsigned short) ((wWidth + 10 + 15) * XRatioAdderDouble); ValidPixelNumber >>= 4; ValidPixelNumber <<= 4; ValidPixelNumber += (OverLapPixel * 2); for (i = 0; i < 16; i++) { Mustek_SendData (chip, ES01_2B0_SEGMENT0_OVERLAP_SEGMENT1 + i, OverLapPixel); Mustek_SendData (chip, ES01_2C0_VALID_PIXEL_PARAMETER_OF_SEGMENT1 + i, 0); } FinalLinePixelPerSegment = ValidPixelNumber + OverLapPixel * 2; if ((FinalLinePixelPerSegment % 8) > 0) { InValidPixelNumber = (SANE_Byte) (8 - (FinalLinePixelPerSegment % 8)); } else { InValidPixelNumber = 0; } Mustek_SendData (chip, ES01_1B0_SEGMENT_PIXEL_NUMBER_LB, LOBYTE (ValidPixelNumber)); Mustek_SendData (chip, ES01_1B1_SEGMENT_PIXEL_NUMBER_HB, HIBYTE (ValidPixelNumber)); SegmentTotalPixel = ValidPixelNumber + OverLapPixel * 2 + InValidPixelNumber; Mustek_SendData (chip, ES01_169_NUMBER_OF_SEGMENT_PIXEL_LB, LOBYTE (ValidPixelNumber)); Mustek_SendData (chip, ES01_16A_NUMBER_OF_SEGMENT_PIXEL_HB, HIBYTE (ValidPixelNumber)); Mustek_SendData (chip, ES01_16B_BETWEEN_SEGMENT_INVALID_PIXEL, 0); Mustek_SendData (chip, ES01_B6_LineWidthPixelLSB, LOBYTE (ValidPixelNumber)); Mustek_SendData (chip, ES01_B7_LineWidthPixelMSB, HIBYTE (ValidPixelNumber)); Mustek_SendData (chip, ES01_19A_CHANNEL_LINE_GAP_LB, LOBYTE (ValidPixelNumber)); Mustek_SendData (chip, ES01_19B_CHANNEL_LINE_GAP_HB, HIBYTE (ValidPixelNumber)); DBG (DBG_ASIC, "ValidPixelNumber=%d\n", ValidPixelNumber); for (i = 0; i < 36; i++) { Mustek_SendData (chip, 0x270 + i, 0); } Mustek_SendData (chip, 0x270, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 1))); Mustek_SendData (chip, 0x271, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 1) >> 8)); Mustek_SendData (chip, 0x272, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 1) >> 16)); Mustek_SendData (chip, 0x27C, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 2))); Mustek_SendData (chip, 0x27D, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 2) >> 8)); Mustek_SendData (chip, 0x27E, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 2) >> 16)); Mustek_SendData (chip, 0x288, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 3))); Mustek_SendData (chip, 0x289, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 3) >> 8)); Mustek_SendData (chip, 0x28A, (SANE_Byte) ((SegmentTotalPixel * (PackAreaUseLine) * 3) >> 16)); DBG (DBG_ASIC, "channel gap=%d\n", SegmentTotalPixel * (PackAreaUseLine)); Mustek_SendData (chip, ES01_B4_StartPixelLSB, LOBYTE (wX + 0)); Mustek_SendData (chip, ES01_B5_StartPixelMSB, HIBYTE (wX + 0)); dwLineTotalPixel = ValidPixelNumber; Mustek_SendData (chip, ES01_1B9_LINE_PIXEL_NUMBER_LB, LOBYTE (XRatioTypeDouble * (dwLineTotalPixel - 1))); Mustek_SendData (chip, ES01_1BA_LINE_PIXEL_NUMBER_HB, HIBYTE (XRatioTypeDouble * (dwLineTotalPixel - 1))); /* final start read out pixel */ Mustek_SendData (chip, ES01_1F4_START_READ_OUT_PIXEL_LB, LOBYTE (0)); Mustek_SendData (chip, ES01_1F5_START_READ_OUT_PIXEL_HB, HIBYTE (0)); MaxPixelHW = (dwLineTotalPixel + InValidPixelNumber) - 10; if (wWidth > MaxPixelHW) { DBG (DBG_ERR, "read out pixel over max pixel! image will shift!!!\n"); } /* final read pixel width */ Mustek_SendData (chip, ES01_1F6_READ_OUT_PIXEL_LENGTH_LB, LOBYTE (wWidth + 9)); Mustek_SendData (chip, ES01_1F7_READ_OUT_PIXEL_LENGTH_HB, HIBYTE (wWidth + 9)); /* data output sequence */ Mustek_SendData (chip, ES01_1F8_PACK_CHANNEL_SELECT_B0, 0); Mustek_SendData (chip, ES01_1F9_PACK_CHANNEL_SELECT_B1, 0); Mustek_SendData (chip, ES01_1FA_PACK_CHANNEL_SELECT_B2, 0x18); Mustek_SendData (chip, ES01_1FB_PACK_CHANNEL_SIZE_B0, (SANE_Byte) ((SegmentTotalPixel * PackAreaUseLine))); Mustek_SendData (chip, ES01_1FC_PACK_CHANNEL_SIZE_B1, (SANE_Byte) ((SegmentTotalPixel * PackAreaUseLine) >> 8)); Mustek_SendData (chip, ES01_1FD_PACK_CHANNEL_SIZE_B2, (SANE_Byte) ((SegmentTotalPixel * PackAreaUseLine) >> 16)); Mustek_SendData (chip, ES01_16C_LINE_SHIFT_OUT_TIMES_DIRECTION, 0x01); Mustek_SendData (chip, ES01_1CE_LINE_SEGMENT_NUMBER, 0x00); Mustek_SendData (chip, ES01_D8_PHTG_EDGE_TIMING_ADJUST, 0x17); Mustek_SendData (chip, ES01_D9_CLEAR_PULSE_WIDTH, byClear_Pulse_Width); Mustek_SendData (chip, ES01_DA_CLEAR_SIGNAL_INVERTING_OUTPUT, 0x54 | 0x01); Mustek_SendData (chip, ES01_CD_TG_R_CONTROL, 0x3C); Mustek_SendData (chip, ES01_CE_TG_G_CONTROL, 0); Mustek_SendData (chip, ES01_CF_TG_B_CONTROL, 0x3C); /* set pack area address */ CISPackAreaStartAddress = PackAreaStartAddress; DBG (DBG_ASIC, "CISPackAreaStartAddress=%d\n", CISPackAreaStartAddress); /* cycle 1 */ Mustek_SendData (chip, ES01_16D_EXPOSURE_CYCLE1_SEGMENT1_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0))); Mustek_SendData (chip, ES01_16E_EXPOSURE_CYCLE1_SEGMENT1_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0) >> 8)); Mustek_SendData (chip, ES01_16F_EXPOSURE_CYCLE1_SEGMENT1_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0) >> 16)); Mustek_SendData (chip, ES01_170_EXPOSURE_CYCLE1_SEGMENT2_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_171_EXPOSURE_CYCLE1_SEGMENT2_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_172_EXPOSURE_CYCLE1_SEGMENT2_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); Mustek_SendData (chip, ES01_173_EXPOSURE_CYCLE1_SEGMENT3_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_174_EXPOSURE_CYCLE1_SEGMENT3_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_175_EXPOSURE_CYCLE1_SEGMENT3_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); Mustek_SendData (chip, ES01_176_EXPOSURE_CYCLE1_SEGMENT4_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_177_EXPOSURE_CYCLE1_SEGMENT4_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_178_EXPOSURE_CYCLE1_SEGMENT4_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); /* cycle 2 */ Mustek_SendData (chip, ES01_179_EXPOSURE_CYCLE2_SEGMENT1_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_17A_EXPOSURE_CYCLE2_SEGMENT1_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_17B_EXPOSURE_CYCLE2_SEGMENT1_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); Mustek_SendData (chip, ES01_17C_EXPOSURE_CYCLE2_SEGMENT2_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_17D_EXPOSURE_CYCLE2_SEGMENT2_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_17E_EXPOSURE_CYCLE2_SEGMENT2_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); Mustek_SendData (chip, ES01_17F_EXPOSURE_CYCLE2_SEGMENT3_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_180_EXPOSURE_CYCLE2_SEGMENT3_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_181_EXPOSURE_CYCLE2_SEGMENT3_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); Mustek_SendData (chip, ES01_182_EXPOSURE_CYCLE2_SEGMENT4_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_183_EXPOSURE_CYCLE2_SEGMENT4_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_184_EXPOSURE_CYCLE2_SEGMENT4_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); /* cycle 3 */ Mustek_SendData (chip, ES01_185_EXPOSURE_CYCLE3_SEGMENT1_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_186_EXPOSURE_CYCLE3_SEGMENT1_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_187_EXPOSURE_CYCLE3_SEGMENT1_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); Mustek_SendData (chip, ES01_188_EXPOSURE_CYCLE3_SEGMENT2_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_189_EXPOSURE_CYCLE3_SEGMENT2_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_18A_EXPOSURE_CYCLE3_SEGMENT2_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); Mustek_SendData (chip, ES01_18B_EXPOSURE_CYCLE3_SEGMENT3_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_18C_EXPOSURE_CYCLE3_SEGMENT3_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_18D_EXPOSURE_CYCLE3_SEGMENT3_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); Mustek_SendData (chip, ES01_18E_EXPOSURE_CYCLE3_SEGMENT4_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000))); Mustek_SendData (chip, ES01_18F_EXPOSURE_CYCLE3_SEGMENT4_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 8)); Mustek_SendData (chip, ES01_190_EXPOSURE_CYCLE3_SEGMENT4_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + 0xC0000) >> 16)); DBG (DBG_ASIC, "set CISPackAreaStartAddress ok\n"); Mustek_SendData (chip, 0x260, InValidPixelNumber); Mustek_SendData (chip, 0x261, InValidPixelNumber << 4); Mustek_SendData (chip, 0x262, InValidPixelNumber); Mustek_SendData (chip, 0x263, 0); DBG (DBG_ASIC, "InValidPixelNumber=%d\n", InValidPixelNumber); Mustek_SendData (chip, 0x264, 0); Mustek_SendData (chip, 0x265, 0); Mustek_SendData (chip, 0x266, 0); Mustek_SendData (chip, 0x267, 0); Mustek_SendData (chip, 0x268, 0); Mustek_SendData (chip, 0x269, 0); Mustek_SendData (chip, 0x26A, 0); Mustek_SendData (chip, 0x26B, 0); Mustek_SendData (chip, 0x26C, 0); Mustek_SendData (chip, 0x26D, 0); Mustek_SendData (chip, 0x26E, 0); Mustek_SendData (chip, 0x26F, 0); DBG (DBG_ASIC, "Set Invalid Pixel ok\n"); /* Pack Start Address */ Mustek_SendData (chip, ES01_19E_PACK_AREA_R_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 0))))); Mustek_SendData (chip, ES01_19F_PACK_AREA_R_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 0))) >> 8)); Mustek_SendData (chip, ES01_1A0_PACK_AREA_R_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 0))) >> 16)); Mustek_SendData (chip, ES01_1A1_PACK_AREA_G_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 1))))); Mustek_SendData (chip, ES01_1A2_PACK_AREA_G_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 1))) >> 8)); Mustek_SendData (chip, ES01_1A3_PACK_AREA_G_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 1))) >> 16)); Mustek_SendData (chip, ES01_1A4_PACK_AREA_B_START_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 2))))); Mustek_SendData (chip, ES01_1A5_PACK_AREA_B_START_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 2))) >> 8)); Mustek_SendData (chip, ES01_1A6_PACK_AREA_B_START_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 2))) >> 16)); /* Pack End Address */ Mustek_SendData (chip, ES01_1A7_PACK_AREA_R_END_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 1) - 1)))); Mustek_SendData (chip, ES01_1A8_PACK_AREA_R_END_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 1) - 1)) >> 8)); Mustek_SendData (chip, ES01_1A9_PACK_AREA_R_END_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 1) - 1)) >> 16)); Mustek_SendData (chip, ES01_1AA_PACK_AREA_G_END_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 2) - 1)))); Mustek_SendData (chip, ES01_1AB_PACK_AREA_G_END_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 2) - 1)) >> 8)); Mustek_SendData (chip, ES01_1AC_PACK_AREA_G_END_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 2) - 1)) >> 16)); Mustek_SendData (chip, ES01_1AD_PACK_AREA_B_END_ADDR_BYTE0, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 3) - 1)))); Mustek_SendData (chip, ES01_1AE_PACK_AREA_B_END_ADDR_BYTE1, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 3) - 1)) >> 8)); Mustek_SendData (chip, ES01_1AF_PACK_AREA_B_END_ADDR_BYTE2, (SANE_Byte) ((CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 3) - 1)) >> 16)); DBG (DBG_ASIC, "CISPackAreaStartAddress + (SegmentTotalPixel*(PackAreaUseLine*1))=%d\n", (CISPackAreaStartAddress + (SegmentTotalPixel * (PackAreaUseLine * 1)))); Mustek_SendData (chip, ES01_19C_MAX_PACK_LINE, PackAreaUseLine); status = Mustek_SendData (chip, ES01_19D_PACK_THRESHOLD_LINE, TotalLineShift); DBG (DBG_ASIC, "PackAreaUseLine=%d,TotalLineShift=%d\n", PackAreaUseLine, TotalLineShift); *PValidPixelNumber = ValidPixelNumber; DBG (DBG_ASIC, "SetPackAddress:Enter\n"); return status; } static STATUS SetExtraSetting (PAsic chip, unsigned short wXResolution, unsigned short wCCD_PixelNumber, SANE_Bool isCaribrate) { STATUS status = STATUS_GOOD; SANE_Byte byPHTG_PulseWidth, byPHTG_WaitWidth; SANE_Byte temp_ff_register = 0; SANE_Byte bThreshold = 128; DBG (DBG_ASIC, "SetExtraSetting:Enter\n"); Mustek_SendData (chip, ES01_B8_ChannelRedExpStartPixelLSB, LOBYTE (chip->Timing.ChannelR_StartPixel)); Mustek_SendData (chip, ES01_B9_ChannelRedExpStartPixelMSB, HIBYTE (chip->Timing.ChannelR_StartPixel)); Mustek_SendData (chip, ES01_BA_ChannelRedExpEndPixelLSB, LOBYTE (chip->Timing.ChannelR_EndPixel)); Mustek_SendData (chip, ES01_BB_ChannelRedExpEndPixelMSB, HIBYTE (chip->Timing.ChannelR_EndPixel)); Mustek_SendData (chip, ES01_BC_ChannelGreenExpStartPixelLSB, LOBYTE (chip->Timing.ChannelG_StartPixel)); Mustek_SendData (chip, ES01_BD_ChannelGreenExpStartPixelMSB, HIBYTE (chip->Timing.ChannelG_StartPixel)); Mustek_SendData (chip, ES01_BE_ChannelGreenExpEndPixelLSB, LOBYTE (chip->Timing.ChannelG_EndPixel)); Mustek_SendData (chip, ES01_BF_ChannelGreenExpEndPixelMSB, HIBYTE (chip->Timing.ChannelG_EndPixel)); Mustek_SendData (chip, ES01_C0_ChannelBlueExpStartPixelLSB, LOBYTE (chip->Timing.ChannelB_StartPixel)); Mustek_SendData (chip, ES01_C1_ChannelBlueExpStartPixelMSB, HIBYTE (chip->Timing.ChannelB_StartPixel)); Mustek_SendData (chip, ES01_C2_ChannelBlueExpEndPixelLSB, LOBYTE (chip->Timing.ChannelB_EndPixel)); Mustek_SendData (chip, ES01_C3_ChannelBlueExpEndPixelMSB, HIBYTE (chip->Timing.ChannelB_EndPixel)); byPHTG_PulseWidth = chip->Timing.PHTG_PluseWidth; byPHTG_WaitWidth = chip->Timing.PHTG_WaitWidth; Mustek_SendData (chip, ES01_B2_PHTGPulseWidth, byPHTG_PulseWidth); Mustek_SendData (chip, ES01_B3_PHTGWaitWidth, byPHTG_WaitWidth); Mustek_SendData (chip, ES01_CC_PHTGTimingAdjust, chip->Timing.PHTG_TimingAdj); Mustek_SendData (chip, ES01_D0_PH1_0, chip->Timing.PHTG_TimingSetup); DBG (DBG_ASIC, "ChannelR_StartPixel=%d,ChannelR_EndPixel=%d\n", chip->Timing.ChannelR_StartPixel, chip->Timing.ChannelR_EndPixel); if (wXResolution == 1200) { Mustek_SendData (chip, ES01_DE_CCD_SETUP_REGISTER, chip->Timing.DE_CCD_SETUP_REGISTER_1200); } else { Mustek_SendData (chip, ES01_DE_CCD_SETUP_REGISTER, chip->Timing.DE_CCD_SETUP_REGISTER_600); } if (isCaribrate == TRUE) { temp_ff_register |= BYPASS_DARK_SHADING_ENABLE; temp_ff_register |= BYPASS_WHITE_SHADING_ENABLE; } else /*Setwindow */ { temp_ff_register |= BYPASS_DARK_SHADING_DISABLE; temp_ff_register |= BYPASS_WHITE_SHADING_DISABLE; } temp_ff_register |= BYPASS_PRE_GAMMA_ENABLE; temp_ff_register |= BYPASS_CONVOLUTION_ENABLE; temp_ff_register |= BYPASS_MATRIX_ENABLE; temp_ff_register |= BYPASS_GAMMA_ENABLE; if (isCaribrate == TRUE) { Mustek_SendData (chip, ES01_FF_SCAN_IMAGE_OPTION, 0xfc | (0x00 & 0x03)); DBG (DBG_ASIC, "FF_SCAN_IMAGE_OPTION=0x%x\n", 0xfc | (0x00 & 0x03)); } else /*Setwindow */ { Mustek_SendData (chip, ES01_FF_SCAN_IMAGE_OPTION, temp_ff_register | (0x00 & 0x03)); DBG (DBG_ASIC, "FF_SCAN_IMAGE_OPTION=0x%x\n", temp_ff_register | (0x00 & 0x03)); } /* pixel process time */ Mustek_SendData (chip, ES01_B0_CCDPixelLSB, LOBYTE (wCCD_PixelNumber)); Mustek_SendData (chip, ES01_B1_CCDPixelMSB, HIBYTE (wCCD_PixelNumber)); Mustek_SendData (chip, ES01_DF_ICG_CONTROL, 0x17); DBG (DBG_ASIC, "wCCD_PixelNumber=%d\n", wCCD_PixelNumber); Mustek_SendData (chip, ES01_88_LINE_ART_THRESHOLD_HIGH_VALUE, bThreshold); Mustek_SendData (chip, ES01_89_LINE_ART_THRESHOLD_LOW_VALUE, bThreshold - 1); DBG (DBG_ASIC, "bThreshold=%d\n", bThreshold); usleep (50000); DBG (DBG_ASIC, "SetExtraSetting:Exit\n"); return status; } /* ---------------------- high level asic functions ------------------------ */ /* HOLD: We don't want to have global vid/pids */ static unsigned short ProductID = 0x0409; static unsigned short VendorID = 0x055f; static SANE_String_Const device_name; static SANE_Status attach_one_scanner (SANE_String_Const devname) { DBG (DBG_ASIC, "attach_one_scanner: enter\n"); DBG (DBG_INFO, "attach_one_scanner: devname = %s\n", devname); device_name = devname; return SANE_STATUS_GOOD; } static STATUS Asic_Open (PAsic chip, SANE_Byte *pDeviceName) { STATUS status; SANE_Status sane_status; DBG (DBG_ASIC, "Asic_Open: Enter\n"); device_name = NULL; if (chip->firmwarestate > FS_OPENED) { DBG (DBG_ASIC, "chip has been opened. fd=%d\n", chip->fd); return STATUS_INVAL; } /* init usb */ sanei_usb_init (); /* find scanner */ sane_status = sanei_usb_find_devices (VendorID, ProductID, attach_one_scanner); if (sane_status != SANE_STATUS_GOOD) { DBG (DBG_ERR, "Asic_Open: sanei_usb_find_devices failed: %s\n", sane_strstatus (sane_status)); return STATUS_INVAL; } /* open usb */ if (device_name == NULL) { DBG (DBG_ERR, "Asic_Open: no scanner found\n"); return STATUS_INVAL; } sane_status = sanei_usb_open (device_name, &chip->fd); if (sane_status != SANE_STATUS_GOOD) { DBG (DBG_ERR, "Asic_Open: sanei_usb_open of %s failed: %s\n", device_name, sane_strstatus (sane_status)); return STATUS_INVAL; } /* open scanner chip */ status = OpenScanChip (chip); if (status != STATUS_GOOD) { sanei_usb_close (chip->fd); DBG (DBG_ASIC, "Asic_Open: OpenScanChip error\n"); return status; } Mustek_SendData (chip, ES01_94_PowerSaveControl, 0x27); Mustek_SendData (chip, ES01_86_DisableAllClockWhenIdle, CLOSE_ALL_CLOCK_DISABLE); Mustek_SendData (chip, ES01_79_AFEMCLK_SDRAMCLK_DELAY_CONTROL, SDRAMCLK_DELAY_12_ns); /* SDRAM initial sequence */ Mustek_SendData (chip, ES01_87_SDRAM_Timing, 0xf1); Mustek_SendData (chip, ES01_87_SDRAM_Timing, 0xa5); Mustek_SendData (chip, ES01_87_SDRAM_Timing, 0x91); Mustek_SendData (chip, ES01_87_SDRAM_Timing, 0x81); Mustek_SendData (chip, ES01_87_SDRAM_Timing, 0xf0); chip->firmwarestate = FS_OPENED; Asic_WaitUnitReady (chip); DBG (DBG_ASIC, "Asic_WaitUnitReady\n"); status = SafeInitialChip (chip); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Asic_Open: SafeInitialChip error\n"); return status; } pDeviceName = (SANE_Byte *) strdup (device_name); if (!pDeviceName) { DBG (DBG_ERR, "Asic_Open: not enough memory\n"); return STATUS_INVAL; } DBG (DBG_INFO, "Asic_Open: device %s successfully opened\n", pDeviceName); DBG (DBG_ASIC, "Asic_Open: Exit\n"); return status; } static STATUS Asic_Close (PAsic chip) { STATUS status; DBG (DBG_ASIC, "Asic_Close: Enter\n"); if (chip->firmwarestate < FS_OPENED) { DBG (DBG_ASIC, "Asic_Close: Scanner is not opened\n"); return STATUS_GOOD; } if (chip->firmwarestate > FS_OPENED) { DBG (DBG_ASIC, "Asic_Close: Scanner is scanning, try to stop scanning\n"); Asic_ScanStop (chip); } Mustek_SendData (chip, ES01_86_DisableAllClockWhenIdle, CLOSE_ALL_CLOCK_ENABLE); status = CloseScanChip (chip); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Asic_Close: CloseScanChip error\n"); return status; } sanei_usb_close (chip->fd); chip->firmwarestate = FS_ATTACHED; DBG (DBG_ASIC, "Asic_Close: Exit\n"); return status; } static STATUS Asic_TurnLamp (PAsic chip, SANE_Bool isLampOn) { STATUS status = STATUS_GOOD; SANE_Byte PWM; DBG (DBG_ASIC, "Asic_TurnLamp: Enter\n"); if (chip->firmwarestate < FS_OPENED) { DBG (DBG_ERR, "Asic_TurnLamp: Scanner is not opened\n"); return STATUS_INVAL; } if (chip->firmwarestate > FS_OPENED) { Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); } if (isLampOn) { PWM = LAMP0_PWM_DEFAULT; } else { PWM = 0; } Mustek_SendData (chip, ES01_99_LAMP_PWM_FREQ_CONTROL, 1); Mustek_SendData (chip, ES01_90_Lamp0PWM, PWM); DBG (DBG_ASIC, "Lamp0 PWM = %d\n", PWM); chip->firmwarestate = FS_OPENED; DBG (DBG_ASIC, "Asic_TurnLamp: Exit\n"); return status; } static STATUS Asic_TurnTA (PAsic chip, SANE_Bool isTAOn) { SANE_Byte PWM; DBG (DBG_ASIC, "Asic_TurnTA: Enter\n"); if (chip->firmwarestate < FS_OPENED) { DBG (DBG_ERR, "Asic_TurnTA: Scanner is not opened\n"); return STATUS_INVAL; } if (chip->firmwarestate > FS_OPENED) Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); if (isTAOn) { PWM = LAMP1_PWM_DEFAULT; } else { PWM = 0; } Mustek_SendData (chip, ES01_99_LAMP_PWM_FREQ_CONTROL, 1); Mustek_SendData (chip, ES01_91_Lamp1PWM, PWM); DBG (DBG_ASIC, "Lamp1 PWM = %d\n", PWM); chip->firmwarestate = FS_OPENED; DBG (DBG_ASIC, "Asic_TurnTA: Exit\n"); return STATUS_GOOD; } static STATUS Asic_WaitUnitReady (PAsic chip) { STATUS status = STATUS_GOOD; SANE_Byte temp_status; int i = 0; DBG (DBG_ASIC, "Asic_WaitUnitReady:Enter\n"); if (chip->firmwarestate < FS_OPENED) { DBG (DBG_ERR, "Asic_WaitUnitReady: Scanner has not been opened\n"); return STATUS_INVAL; } do { status = GetChipStatus (chip, 1, &temp_status); if (status != STATUS_GOOD) { DBG (DBG_ASIC, "WaitChipIdle:Error!\n"); return status; } i++; usleep (100000); } while (((temp_status & 0x1f) != 0) && i < 300); DBG (DBG_ASIC, "Wait %d s\n", (unsigned short) (i * 0.1)); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); chip->motorstate = MS_STILL; DBG (DBG_ASIC, "Asic_WaitUnitReady: Exit\n"); return status; } #if SANE_UNUSED static STATUS Asic_Release (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "Asic_Release()\n"); if (chip->firmwarestate > FS_ATTACHED) status = Asic_Close (chip); chip->firmwarestate = FS_NULL; DBG (DBG_ASIC, "Asic_Release: Exit\n"); return status; } #endif static STATUS Asic_Initialize (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "Asic_Initialize:Enter\n"); chip->motorstate = MS_STILL; chip->dwBytesCountPerRow = 0; chip->lpGammaTable = NULL; DBG (DBG_ASIC, "isFirstOpenChip=%d\n", chip->isFirstOpenChip); chip->isFirstOpenChip = TRUE; DBG (DBG_ASIC, "isFirstOpenChip=%d\n", chip->isFirstOpenChip); chip->SWWidth = 0; chip->TA_Status = TA_UNKNOW; chip->lpShadingTable = NULL; chip->isMotorMove = MOTOR_0_ENABLE; Asic_Reset (chip); InitTiming (chip); chip->isUniformSpeedToScan = UNIFORM_MOTOR_AND_SCAN_SPEED_DISABLE; chip->isMotorGoToFirstLine = MOTOR_MOVE_TO_FIRST_LINE_ENABLE; chip->UsbHost = HT_USB10; DBG (DBG_ASIC, "Asic_Initialize: Exit\n"); return status; } static STATUS Asic_SetWindow (PAsic chip, SANE_Byte bScanBits, unsigned short wXResolution, unsigned short wYResolution, unsigned short wX, unsigned short wY, unsigned short wWidth, unsigned short wLength) { STATUS status = STATUS_GOOD; unsigned short ValidPixelNumber; unsigned short BytePerPixel = 0; unsigned int dwTotalLineTheBufferNeed = 0; unsigned short dwTotal_CCDResolution = 1200; unsigned short wThinkCCDResolution = 0; unsigned short wCCD_PixelNumber = 0; unsigned int dwLineWidthPixel = 0; unsigned short wNowMotorDPI; unsigned short XRatioTypeWord; double XRatioTypeDouble; double XRatioAdderDouble; LLF_MOTORMOVE *lpMotorStepsTable = (LLF_MOTORMOVE *) malloc (sizeof (LLF_MOTORMOVE)); SANE_Byte byDummyCycleNum = 0; unsigned short Total_MotorDPI; unsigned short wMultiMotorStep = 1; SANE_Byte bMotorMoveType = _MOTOR_MOVE_TYPE; SANE_Byte byClear_Pulse_Width = 0; unsigned int dwLinePixelReport; SANE_Byte byPHTG_PulseWidth, byPHTG_WaitWidth; unsigned short StartSpeed, EndSpeed; LLF_CALCULATEMOTORTABLE CalMotorTable; LLF_MOTOR_CURRENT_AND_PHASE CurrentPhase; LLF_RAMACCESS RamAccess; unsigned int dwStartAddr, dwEndAddr, dwTableBaseAddr, dwShadingTableAddr; SANE_Byte isMotorMoveToFirstLine = chip->isMotorGoToFirstLine; SANE_Byte isUniformSpeedToScan = chip->isUniformSpeedToScan; SANE_Byte isScanBackTracking = SCAN_BACK_TRACKING_ENABLE; unsigned short * lpMotorTable; unsigned int RealTableSize; double dbXRatioAdderDouble; unsigned short wFullBank; DBG (DBG_ASIC, "Asic_SetWindow: Enter\n"); DBG (DBG_ASIC, "bScanBits=%d,wXResolution=%d,wYResolution=%d,wX=%d,wY=%d,wWidth=%d,wLength=%d\n", bScanBits, wXResolution, wYResolution, wX, wY, wWidth, wLength); if (chip->firmwarestate != FS_OPENED) { DBG (DBG_ERR, "Asic_SetWindow: Scanner is not opened\n"); return STATUS_INVAL; } Mustek_SendData (chip, ES01_F3_ActionOption, 0); Mustek_SendData (chip, ES01_86_DisableAllClockWhenIdle, CLOSE_ALL_CLOCK_DISABLE); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); status = Asic_WaitUnitReady (chip); /* dummy clock mode */ Mustek_SendData (chip, 0x1CD, 0); /* LED Flash */ Mustek_SendData (chip, ES01_94_PowerSaveControl, 0x27 | 64 | 128); /* calculate byte per line */ if (bScanBits > 24) { BytePerPixel = 6; chip->dwBytesCountPerRow = (unsigned int) (wWidth) * 6; } else if (bScanBits == 24) { BytePerPixel = 3; chip->dwBytesCountPerRow = (unsigned int) (wWidth) * 3; } else if ((bScanBits > 8) && (bScanBits <= 16)) { BytePerPixel = 2; chip->dwBytesCountPerRow = (unsigned int) (wWidth) * 2; } else if ((bScanBits == 8)) { BytePerPixel = 1; chip->dwBytesCountPerRow = (unsigned int) (wWidth); } else if ((bScanBits < 8)) { BytePerPixel = 1; chip->dwBytesCountPerRow = (unsigned int) (wWidth); } DBG (DBG_ASIC, "dwBytesCountPerRow = %d\n", chip->dwBytesCountPerRow); byDummyCycleNum = 0; if (chip->lsLightSource == LS_REFLECTIVE) { if (chip->UsbHost == HT_USB10) { switch (wYResolution) { case 2400: case 1200: if (chip->dwBytesCountPerRow > 22000) byDummyCycleNum = 4; else if (chip->dwBytesCountPerRow > 15000) byDummyCycleNum = 3; else if (chip->dwBytesCountPerRow > 10000) byDummyCycleNum = 2; else if (chip->dwBytesCountPerRow > 5000) byDummyCycleNum = 1; break; case 600: case 300: case 150: case 100: if (chip->dwBytesCountPerRow > 21000) byDummyCycleNum = 7; else if (chip->dwBytesCountPerRow > 18000) byDummyCycleNum = 6; else if (chip->dwBytesCountPerRow > 15000) byDummyCycleNum = 5; else if (chip->dwBytesCountPerRow > 12000) byDummyCycleNum = 4; else if (chip->dwBytesCountPerRow > 9000) byDummyCycleNum = 3; else if (chip->dwBytesCountPerRow > 6000) byDummyCycleNum = 2; else if (chip->dwBytesCountPerRow > 3000) byDummyCycleNum = 1; break; case 75: case 50: byDummyCycleNum = 1; break; default: byDummyCycleNum = 0; break; } } else { switch (wYResolution) { case 2400: case 1200: case 75: case 50: byDummyCycleNum = 1; break; default: byDummyCycleNum = 0; break; } } } dwTotalLineTheBufferNeed = wLength; chip->Scan.Dpi = wXResolution; CCDTiming (chip); dwTotal_CCDResolution = SENSOR_DPI; if (chip->lsLightSource == LS_REFLECTIVE) { if (wXResolution > (dwTotal_CCDResolution / 2)) { /* full ccd resolution 1200dpi */ wThinkCCDResolution = dwTotal_CCDResolution; Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x01); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x01); wCCD_PixelNumber = chip->Timing.wCCDPixelNumber_1200; } else { /*600dpi */ wThinkCCDResolution = dwTotal_CCDResolution / 2; Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x01); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x00); wCCD_PixelNumber = chip->Timing.wCCDPixelNumber_600; } } else { if (wXResolution > (dwTotal_CCDResolution / 2)) { wThinkCCDResolution = dwTotal_CCDResolution; Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x01); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x01); wCCD_PixelNumber = TA_IMAGE_PIXELNUMBER; } else { wThinkCCDResolution = dwTotal_CCDResolution / 2; Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x01); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x00); wCCD_PixelNumber = TA_IMAGE_PIXELNUMBER; } } dwLineWidthPixel = wWidth; SetLineTimeAndExposure (chip); Mustek_SendData (chip, ES01_CB_CCDDummyCycleNumber, byDummyCycleNum); SetLEDTime (chip); /* calculate Y ratio */ Total_MotorDPI = 1200; wNowMotorDPI = Total_MotorDPI; /* SetADConverter */ Mustek_SendData (chip, ES01_74_HARDWARE_SETTING, MOTOR1_SERIAL_INTERFACE_G10_8_ENABLE | LED_OUT_G11_DISABLE | SLAVE_SERIAL_INTERFACE_G15_14_DISABLE | SHUTTLE_CCD_DISABLE); /* set AFE */ Mustek_SendData (chip, ES01_9A_AFEControl, AD9826_AFE | AUTO_CHANGE_AFE_GAIN_OFFSET_DISABLE); SetAFEGainOffset (chip); Mustek_SendData (chip, ES01_F7_DigitalControl, DIGITAL_REDUCE_DISABLE); /* calculate X ratio */ XRatioTypeDouble = wXResolution; XRatioTypeDouble /= wThinkCCDResolution; XRatioAdderDouble = 1 / XRatioTypeDouble; XRatioTypeWord = (unsigned short) (XRatioTypeDouble * 32768); /* 32768 = 2^15 */ XRatioAdderDouble = (double) (XRatioTypeWord) / 32768; XRatioAdderDouble = 1 / XRatioAdderDouble; /* 0x8000 = 1.00000 -> get all pixel */ Mustek_SendData (chip, ES01_9E_HorizontalRatio1to15LSB, LOBYTE (XRatioTypeWord)); Mustek_SendData (chip, ES01_9F_HorizontalRatio1to15MSB, HIBYTE (XRatioTypeWord)); /* SetMotorType */ Mustek_SendData (chip, ES01_A6_MotorOption, MOTOR_0_ENABLE | MOTOR_1_DISABLE | HOME_SENSOR_0_ENABLE | ES03_TABLE_DEFINE); Mustek_SendData (chip, ES01_F6_MorotControl1, SPEED_UNIT_1_PIXEL_TIME | MOTOR_SYNC_UNIT_1_PIXEL_TIME); /* SetScanStepTable */ /*set Motor move type */ if (wYResolution >= 1200) bMotorMoveType = _8_TABLE_SPACE_FOR_1_DIV_2_STEP; switch (bMotorMoveType) { case _4_TABLE_SPACE_FOR_FULL_STEP: wMultiMotorStep = 1; break; case _8_TABLE_SPACE_FOR_1_DIV_2_STEP: wMultiMotorStep = 2; break; case _16_TABLE_SPACE_FOR_1_DIV_4_STEP: wMultiMotorStep = 4; break; case _32_TABLE_SPACE_FOR_1_DIV_8_STEP: wMultiMotorStep = 8; break; } wY *= wMultiMotorStep; SetScanMode (chip, bScanBits); /*set white shading int and dec */ if (chip->lsLightSource == LS_REFLECTIVE) Mustek_SendData (chip, ES01_F8_WHITE_SHADING_DATA_FORMAT, ES01_SHADING_3_INT_13_DEC); else Mustek_SendData (chip, ES01_F8_WHITE_SHADING_DATA_FORMAT, ES01_SHADING_4_INT_12_DEC); SetPackAddress (chip, wXResolution, wWidth, wX, XRatioAdderDouble, XRatioTypeDouble, byClear_Pulse_Width, &ValidPixelNumber); SetExtraSetting (chip, wXResolution, wCCD_PixelNumber, FALSE); /* calculate line time */ byPHTG_PulseWidth = chip->Timing.PHTG_PluseWidth; byPHTG_WaitWidth = chip->Timing.PHTG_WaitWidth; dwLinePixelReport = ((byClear_Pulse_Width + 1) * 2 + (byPHTG_PulseWidth + 1) * (1) + (byPHTG_WaitWidth + 1) * (1) + (wCCD_PixelNumber + 1)) * (byDummyCycleNum + 1); DBG (DBG_ASIC, "Motor Time = %d\n", (dwLinePixelReport * wYResolution / wNowMotorDPI) / wMultiMotorStep); if ((dwLinePixelReport * wYResolution / wNowMotorDPI) / wMultiMotorStep > 64000) { DBG (DBG_ASIC, "Motor Time Over Flow !!!\n"); } EndSpeed = (unsigned short) ((dwLinePixelReport * wYResolution / wNowMotorDPI) / wMultiMotorStep); SetMotorStepTable (chip, lpMotorStepsTable, wY, dwTotalLineTheBufferNeed * wNowMotorDPI / wYResolution * wMultiMotorStep, wYResolution); /*modified by Chester 92/04/08 */ if (EndSpeed >= 20000) { Asic_MotorMove (chip, 1, wY / wMultiMotorStep); isUniformSpeedToScan = UNIFORM_MOTOR_AND_SCAN_SPEED_ENABLE; isScanBackTracking = SCAN_BACK_TRACKING_DISABLE; isMotorMoveToFirstLine = MOTOR_MOVE_TO_FIRST_LINE_DISABLE; } Mustek_SendData (chip, ES01_F3_ActionOption, isMotorMoveToFirstLine | MOTOR_BACK_HOME_AFTER_SCAN_DISABLE | SCAN_ENABLE | isScanBackTracking | INVERT_MOTOR_DIRECTION_DISABLE | isUniformSpeedToScan | ES01_STATIC_SCAN_DISABLE | MOTOR_TEST_LOOP_DISABLE); if (EndSpeed > 8000) { StartSpeed = EndSpeed; } else { if (EndSpeed <= 1000) StartSpeed = EndSpeed + 4500; else StartSpeed = EndSpeed + 3500; } Mustek_SendData (chip, ES01_FD_MotorFixedspeedLSB, LOBYTE (EndSpeed)); Mustek_SendData (chip, ES01_FE_MotorFixedspeedMSB, HIBYTE (EndSpeed)); lpMotorTable = (unsigned short *) malloc (512 * 8 * 2); memset (lpMotorTable, 0, 512 * 8 * sizeof (unsigned short)); CalMotorTable.StartSpeed = StartSpeed; CalMotorTable.EndSpeed = EndSpeed; CalMotorTable.AccStepBeforeScan = lpMotorStepsTable->wScanAccSteps; CalMotorTable.DecStepAfterScan = lpMotorStepsTable->bScanDecSteps; CalMotorTable.lpMotorTable = lpMotorTable; CalculateMotorTable (&CalMotorTable, wYResolution); CurrentPhase.MotorDriverIs3967 = 0; CurrentPhase.FillPhase = 1; CurrentPhase.MoveType = bMotorMoveType; SetMotorCurrent (chip, EndSpeed, &CurrentPhase); LLFSetMotorCurrentAndPhase (chip, &CurrentPhase); DBG (DBG_ASIC, "EndSpeed = %d, BytesCountPerRow=%d, MotorCurrentTable=%d, LinePixelReport=%d\n", EndSpeed, chip->dwBytesCountPerRow, CurrentPhase.MotorCurrentTableA[0], dwLinePixelReport); /* write motor table */ RealTableSize = 512 * 8; dwTableBaseAddr = PackAreaStartAddress - RealTableSize; dwStartAddr = dwTableBaseAddr; RamAccess.ReadWrite = WRITE_RAM; RamAccess.IsOnChipGamma = EXTERNAL_RAM; RamAccess.DramDelayTime = SDRAMCLK_DELAY_12_ns; RamAccess.LoStartAddress = (unsigned short) (dwStartAddr); RamAccess.HiStartAddress = (unsigned short) (dwStartAddr >> 16); RamAccess.RwSize = RealTableSize * 2; RamAccess.BufferPtr = (SANE_Byte *) lpMotorTable; LLFRamAccess (chip, &RamAccess); Mustek_SendData (chip, ES01_DB_PH_RESET_EDGE_TIMING_ADJUST, 0x00); Mustek_SendData (chip, ES01_DC_CLEAR_EDGE_TO_PH_TG_EDGE_WIDTH, 0); Mustek_SendData (chip, ES01_9D_MotorTableAddrA14_A21, (SANE_Byte) (dwTableBaseAddr >> TABLE_OFFSET_BASE)); /* set address and shading table */ /*set image buffer range and write shading table */ RealTableSize = (ACC_DEC_STEP_TABLE_SIZE * NUM_OF_ACC_DEC_STEP_TABLE) + ShadingTableSize (ValidPixelNumber); dwShadingTableAddr = PackAreaStartAddress - (((RealTableSize + (TABLE_BASE_SIZE - 1)) >> TABLE_OFFSET_BASE) << TABLE_OFFSET_BASE); dwEndAddr = dwShadingTableAddr - 1; dwStartAddr = dwShadingTableAddr; if (wXResolution > 600) dbXRatioAdderDouble = 1200 / wXResolution; else dbXRatioAdderDouble = 600 / wXResolution; RamAccess.ReadWrite = WRITE_RAM; RamAccess.IsOnChipGamma = EXTERNAL_RAM; RamAccess.DramDelayTime = SDRAMCLK_DELAY_12_ns; RamAccess.LoStartAddress = (unsigned short) (dwStartAddr); RamAccess.HiStartAddress = (unsigned short) (dwStartAddr >> 16); RamAccess.RwSize = ShadingTableSize ((int) ((wWidth + 4) * dbXRatioAdderDouble)) * sizeof (unsigned short); RamAccess.BufferPtr = (SANE_Byte *) chip->lpShadingTable; LLFRamAccess (chip, &RamAccess); /*tell scan chip the shading table address, unit is 2^15 bytes(2^14 word) */ Mustek_SendData (chip, ES01_9B_ShadingTableAddrA14_A21, (SANE_Byte) (dwShadingTableAddr >> TABLE_OFFSET_BASE)); /*empty bank */ Mustek_SendData (chip, ES01_FB_BufferEmptySize16WordLSB, LOBYTE (WaitBufferOneLineSize >> (7 - 3))); Mustek_SendData (chip, ES01_FC_BufferEmptySize16WordMSB, HIBYTE (WaitBufferOneLineSize >> (7 - 3))); /*full bank */ wFullBank = (unsigned short) ((dwEndAddr - (((dwLineWidthPixel * BytePerPixel) / 2) * 3 * 1)) / BANK_SIZE); Mustek_SendData (chip, ES01_F9_BufferFullSize16WordLSB, LOBYTE (wFullBank)); Mustek_SendData (chip, ES01_FA_BufferFullSize16WordMSB, HIBYTE (wFullBank)); /* set buffer address */ LLFSetRamAddress (chip, 0x0, dwEndAddr, ACCESS_DRAM); Mustek_SendData (chip, ES01_00_ADAFEConfiguration, 0x70); Mustek_SendData (chip, ES01_02_ADAFEMuxConfig, 0x80); free (lpMotorTable); free (lpMotorStepsTable); chip->firmwarestate = FS_OPENED; DBG (DBG_ASIC, "Asic_SetWindow: Exit\n"); return status; } static STATUS Asic_Reset (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "Asic_Reset: Enter\n"); chip->lsLightSource = LS_REFLECTIVE; chip->dwBytesCountPerRow = 0; chip->AD.DirectionR = 0; chip->AD.DirectionG = 0; chip->AD.DirectionB = 0; chip->AD.GainR = 0; chip->AD.GainG = 0; chip->AD.GainB = 0; chip->AD.OffsetR = 0; chip->AD.OffsetG = 0; chip->AD.OffsetB = 0; chip->Scan.TotalMotorSteps = 60000; chip->Scan.StartLine = 0; chip->Scan.StartPixel = 0; DBG (DBG_ASIC, "Asic_Reset: Exit\n"); return status; } static STATUS Asic_SetSource (PAsic chip, LIGHTSOURCE lsLightSource) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "Asic_SetSource: Enter\n"); chip->lsLightSource = lsLightSource; switch (chip->lsLightSource) { case 1: DBG (DBG_ASIC, "Asic_SetSource: Source is Reflect\n"); break; case 2: DBG (DBG_ASIC, "Asic_SetSource: Source is Position\n"); break; case 4: DBG (DBG_ASIC, "Asic_SetSource: Source is Negtive\n"); break; default: DBG (DBG_ASIC, "Asic_SetSource: Source error\n"); } DBG (DBG_ASIC, "Asic_SetSource: Exit\n"); return status; } static STATUS Asic_ScanStart (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "Asic_ScanStart: Enter\n"); if (chip->firmwarestate != FS_OPENED) { DBG (DBG_ERR, "Asic_ScanStart: Scanner is not opened\n"); return STATUS_INVAL; } Mustek_SendData (chip, ES01_8B_Status, 0x1c | 0x20); Mustek_WriteAddressLineForRegister (chip, 0x8B); Mustek_ClearFIFO (chip); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_ENABLE); chip->firmwarestate = FS_SCANNING; DBG (DBG_ASIC, "Asic_ScanStart: Exit\n"); return status; } static STATUS Asic_ScanStop (PAsic chip) { STATUS status = STATUS_GOOD; SANE_Byte temps[2]; SANE_Byte buf[4]; DBG (DBG_ASIC, "Asic_ScanStop: Enter\n"); if (chip->firmwarestate < FS_SCANNING) { return status; } usleep (100 * 1000); buf[0] = 0x02; /*stop */ buf[1] = 0x02; buf[2] = 0x02; buf[3] = 0x02; status = WriteIOControl (chip, 0xc0, 0, 4, buf); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Asic_ScanStop: Stop scan error\n"); return status; } buf[0] = 0x00; /*clear */ buf[1] = 0x00; buf[2] = 0x00; buf[3] = 0x00; status = WriteIOControl (chip, 0xc0, 0, 4, buf); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Asic_ScanStop: Clear scan error\n"); return status; } status = Mustek_DMARead (chip, 2, temps); if (status != STATUS_GOOD) { DBG (DBG_ERR, "Asic_ScanStop: DMAReadGeneralMode error\n"); return status; } Mustek_SendData (chip, ES01_F3_ActionOption, 0); Mustek_SendData (chip, ES01_86_DisableAllClockWhenIdle, CLOSE_ALL_CLOCK_DISABLE); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); Mustek_ClearFIFO (chip); chip->firmwarestate = FS_OPENED; DBG (DBG_ASIC, "Asic_ScanStop: Exit\n"); return status; } static STATUS Asic_ReadImage (PAsic chip, SANE_Byte * pBuffer, unsigned short LinesCount) { STATUS status = STATUS_GOOD; unsigned int dwXferBytes; DBG (DBG_ASIC, "Asic_ReadImage: Enter : LinesCount = %d\n", LinesCount); if (chip->firmwarestate != FS_SCANNING) { DBG (DBG_ERR, "Asic_ReadImage: Scanner is not scanning\n"); return STATUS_INVAL; } dwXferBytes = (unsigned int) (LinesCount) * chip->dwBytesCountPerRow; DBG (DBG_ASIC, "Asic_ReadImage: chip->dwBytesCountPerRow = %d\n", chip->dwBytesCountPerRow); /* HOLD: an unsigned long can't be < 0 if (dwXferBytes < 0) { DBG (DBG_ASIC, "Asic_ReadImage: dwXferBytes <0\n"); return STATUS_INVAL; } */ if (dwXferBytes == 0) { DBG (DBG_ASIC, "Asic_ReadImage: dwXferBytes == 0\n"); return STATUS_GOOD; } status = Mustek_DMARead (chip, dwXferBytes, pBuffer); DBG (DBG_ASIC, "Asic_ReadImage: Exit\n"); return status; } #if SANE_UNUSED static STATUS Asic_CheckFunctionKey (PAsic chip, SANE_Byte * key) { STATUS status = STATUS_GOOD; SANE_Byte bBuffer_1 = 0xff; SANE_Byte bBuffer_2 = 0xff; DBG (DBG_ASIC, "Asic_CheckFunctionKey: Enter\n"); if (chip->firmwarestate != FS_OPENED) { DBG (DBG_ERR, "Asic_CheckFunctionKey: Scanner is not Opened\n"); return STATUS_INVAL; } Mustek_SendData (chip, ES01_97_GPIOControl0_7, 0x00); Mustek_SendData (chip, ES01_95_GPIOValue0_7, 0x17); Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x00); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x08); GetChipStatus (chip, 0x02, &bBuffer_1); GetChipStatus (chip, 0x03, &bBuffer_2); if (((0xff - bBuffer_1) & 0x10) == 0x10) *key = 0x01; if (((0xff - bBuffer_1) & 0x01) == 0x01) *key = 0x02; if (((0xff - bBuffer_1) & 0x04) == 0x04) *key = 0x04; if (((0xff - bBuffer_2) & 0x08) == 0x08) *key = 0x08; if (((0xff - bBuffer_1) & 0x02) == 0x02) *key = 0x10; DBG (DBG_ASIC, "CheckFunctionKey=%d\n", *key); DBG (DBG_ASIC, "Asic_CheckFunctionKey: Exit\n"); return status; } #endif static STATUS Asic_IsTAConnected (PAsic chip, SANE_Bool * hasTA) { SANE_Byte bBuffer_1 = 0xff; DBG (DBG_ASIC, "Asic_IsTAConnected: Enter\n"); Mustek_SendData (chip, ES01_97_GPIOControl0_7, 0x00); Mustek_SendData (chip, ES01_95_GPIOValue0_7, 0x00); Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x00); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x00); GetChipStatus (chip, 0x02, &bBuffer_1); if (((0xff - bBuffer_1) & 0x08) == 0x08) *hasTA = TRUE; else *hasTA = FALSE; DBG (DBG_ASIC, "hasTA=%d\n", *hasTA); DBG (DBG_ASIC, "Asic_IsTAConnected():Exit\n"); return STATUS_GOOD; } #if SANE_UNUSED static STATUS Asic_DownloadGammaTable (PAsic chip, void * lpBuffer) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "Asic_DownloadGammaTable()\n"); chip->lpGammaTable = lpBuffer; DBG (DBG_ASIC, "Asic_DownloadGammaTable: Exit\n"); return status; } #endif static STATUS Asic_ReadCalibrationData (PAsic chip, void * pBuffer, unsigned int dwXferBytes, SANE_Byte bScanBits) { STATUS status = STATUS_GOOD; SANE_Byte * pCalBuffer; unsigned int dwTotalReadData; unsigned int dwReadImageData; DBG (DBG_ASIC, "Asic_ReadCalibrationData: Enter\n"); if (chip->firmwarestate != FS_SCANNING) { DBG (DBG_ERR, "Asic_ReadCalibrationData: Scanner is not scanning\n"); return STATUS_INVAL; } if (bScanBits == 24) { unsigned int i; pCalBuffer = (SANE_Byte *) malloc (dwXferBytes); if (pCalBuffer == NULL) { DBG (DBG_ERR, "Asic_ReadCalibrationData: Can't malloc bCalBuffer memory\n"); return STATUS_MEM_ERROR; } for (dwTotalReadData = 0; dwTotalReadData < dwXferBytes;) { dwReadImageData = (dwXferBytes - dwTotalReadData) < 65536 ? (dwXferBytes - dwTotalReadData) : 65536; Mustek_DMARead (chip, dwReadImageData, (SANE_Byte *) (pCalBuffer + dwTotalReadData)); dwTotalReadData += dwReadImageData; } dwXferBytes /= 3; for (i = 0; i < dwXferBytes; i++) { *((SANE_Byte *) pBuffer + i) = *(pCalBuffer + i * 3); *((SANE_Byte *) pBuffer + dwXferBytes + i) = *(pCalBuffer + i * 3 + 1); *((SANE_Byte *) pBuffer + dwXferBytes * 2 + i) = *(pCalBuffer + i * 3 + 2); } free (pCalBuffer); } else if (bScanBits == 8) { for (dwTotalReadData = 0; dwTotalReadData < dwXferBytes;) { dwReadImageData = (dwXferBytes - dwTotalReadData) < 65536 ? (dwXferBytes - dwTotalReadData) : 65536; Mustek_DMARead (chip, dwReadImageData, (SANE_Byte *) pBuffer + dwTotalReadData); dwTotalReadData += dwReadImageData; } } DBG (DBG_ASIC, "Asic_ReadCalibrationData: Exit\n"); return status; } static STATUS Asic_SetMotorType (PAsic chip, SANE_Bool isMotorMove, SANE_Bool isUniformSpeed) { STATUS status = STATUS_GOOD; isUniformSpeed = isUniformSpeed; DBG (DBG_ASIC, "Asic_SetMotorType:Enter\n"); if (isMotorMove) { chip->isMotorMove = MOTOR_0_ENABLE; } else chip->isMotorMove = MOTOR_0_DISABLE; DBG (DBG_ASIC, "isMotorMove=%d\n", chip->isMotorMove); DBG (DBG_ASIC, "Asic_SetMotorType: Exit\n"); return status; } static STATUS Asic_MotorMove (PAsic chip, SANE_Bool isForward, unsigned int dwTotalSteps) { STATUS status = STATUS_GOOD; unsigned short *NormalMoveMotorTable; LLF_CALCULATEMOTORTABLE CalMotorTable; LLF_MOTOR_CURRENT_AND_PHASE CurrentPhase; LLF_SETMOTORTABLE LLF_SetMotorTable; LLF_MOTORMOVE MotorMove; DBG (DBG_ASIC, "Asic_MotorMove:Enter\n"); NormalMoveMotorTable = (unsigned short *) malloc (512 * 8 * 2); CalMotorTable.StartSpeed = 5000; CalMotorTable.EndSpeed = 1800; CalMotorTable.AccStepBeforeScan = 511; CalMotorTable.lpMotorTable = NormalMoveMotorTable; LLFCalculateMotorTable (&CalMotorTable); CurrentPhase.MotorDriverIs3967 = 0; CurrentPhase.MotorCurrentTableA[0] = 200; CurrentPhase.MotorCurrentTableB[0] = 200; CurrentPhase.MoveType = _4_TABLE_SPACE_FOR_FULL_STEP; LLFSetMotorCurrentAndPhase (chip, &CurrentPhase); LLF_SetMotorTable.MotorTableAddress = 0; LLF_SetMotorTable.MotorTablePtr = NormalMoveMotorTable; LLFSetMotorTable (chip, &LLF_SetMotorTable); free (NormalMoveMotorTable); MotorMove.MotorSelect = MOTOR_0_ENABLE | MOTOR_1_DISABLE; MotorMove.MotorMoveUnit = ES03_TABLE_DEFINE; MotorMove.MotorSpeedUnit = SPEED_UNIT_1_PIXEL_TIME; MotorMove.MotorSyncUnit = MOTOR_SYNC_UNIT_1_PIXEL_TIME; MotorMove.HomeSensorSelect = HOME_SENSOR_0_ENABLE; MotorMove.ActionMode = ACTION_MODE_ACCDEC_MOVE; MotorMove.ActionType = isForward; if (dwTotalSteps > 1000) { MotorMove.AccStep = 511; MotorMove.DecStep = 255; MotorMove.FixMoveSteps = dwTotalSteps - (511 + 255); } else { MotorMove.ActionMode = ACTION_MODE_UNIFORM_SPEED_MOVE; MotorMove.AccStep = 1; MotorMove.DecStep = 1; MotorMove.FixMoveSteps = dwTotalSteps - 2; } MotorMove.FixMoveSpeed = 7000; MotorMove.WaitOrNoWait = TRUE; LLFMotorMove (chip, &MotorMove); DBG (DBG_ASIC, "Asic_MotorMove: Exit\n"); return status; } static STATUS Asic_CarriageHome (PAsic chip, SANE_Bool isTA) { STATUS status = STATUS_GOOD; SANE_Bool LampHome, TAHome; isTA = isTA; DBG (DBG_ASIC, "Asic_CarriageHome:Enter\n"); status = IsCarriageHome (chip, &LampHome, &TAHome); if (!LampHome) { status = MotorBackHome (chip, TRUE); } DBG (DBG_ASIC, "Asic_CarriageHome: Exit\n"); return status; } static STATUS Asic_SetShadingTable (PAsic chip, unsigned short * lpWhiteShading, unsigned short * lpDarkShading, unsigned short wXResolution, unsigned short wWidth, unsigned short wX) { STATUS status = STATUS_GOOD; unsigned short i, j, n; unsigned short wValidPixelNumber; double dbXRatioAdderDouble; unsigned int wShadingTableSize; wX = wX; DBG (DBG_ASIC, "Asic_SetShadingTable:Enter\n"); if (chip->firmwarestate < FS_OPENED) OpenScanChip (chip); if (chip->firmwarestate == FS_SCANNING) Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); if (wXResolution > 600) dbXRatioAdderDouble = 1200 / wXResolution; else dbXRatioAdderDouble = 600 / wXResolution; wValidPixelNumber = (unsigned short) ((wWidth + 4) * dbXRatioAdderDouble); DBG (DBG_ASIC, "wValidPixelNumber = %d\n", wValidPixelNumber); /* clear old Shading table, if it has. */ /* first 4 element and lastest 5 of Shading table can't been used */ wShadingTableSize = (ShadingTableSize (wValidPixelNumber)) * sizeof (unsigned short); if (chip->lpShadingTable != NULL) { free (chip->lpShadingTable); } DBG (DBG_ASIC, "Alloc a new shading table= %d Byte!\n", wShadingTableSize); chip->lpShadingTable = (SANE_Byte *) malloc (wShadingTableSize); if (chip->lpShadingTable == NULL) { DBG (DBG_ASIC, "lpShadingTable == NULL\n"); return STATUS_MEM_ERROR; } n = 0; for (i = 0; i <= (wValidPixelNumber / 40); i++) { if (i < (wValidPixelNumber / 40)) { for (j = 0; j < 40; j++) { *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6) = *((unsigned short *) lpDarkShading + n * 3); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 2) = *((unsigned short *) lpDarkShading + n * 3 + 1); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 4) = *((unsigned short *) lpDarkShading + n * 3 + 2); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 1) = *((unsigned short *) lpWhiteShading + n * 3); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 3) = *((unsigned short *) lpWhiteShading + n * 3 + 1); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 5) = *((unsigned short *) lpWhiteShading + n * 3 + 2); if ((j % (unsigned short) dbXRatioAdderDouble) == (dbXRatioAdderDouble - 1)) n++; if (i == 0 && j < 4 * dbXRatioAdderDouble) n = 0; } } else { for (j = 0; j < (wValidPixelNumber % 40); j++) { *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6) = *((unsigned short *) lpDarkShading + (n) * 3); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 2) = *((unsigned short *) lpDarkShading + (n) * 3 + 1); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 4) = *((unsigned short *) lpDarkShading + (n) * 3 + 2); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 1) = *((unsigned short *) lpWhiteShading + (n) * 3); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 3) = *((unsigned short *) lpWhiteShading + (n) * 3 + 1); *((unsigned short *) chip->lpShadingTable + i * 256 + j * 6 + 5) = *((unsigned short *) lpWhiteShading + (n) * 3 + 2); if ((j % (unsigned short) dbXRatioAdderDouble) == (dbXRatioAdderDouble - 1)) n++; if (i == 0 && j < 4 * dbXRatioAdderDouble) n = 0; } } } DBG (DBG_ASIC, "Asic_SetShadingTable: Exit\n"); return status; } static STATUS Asic_WaitCarriageHome (PAsic chip, SANE_Bool isTA) { STATUS status = STATUS_GOOD; SANE_Bool LampHome, TAHome; int i; isTA = isTA; DBG (DBG_ASIC, "Asic_WaitCarriageHome:Enter\n"); for (i = 0; i < 100; i++) { status = IsCarriageHome (chip, &LampHome, &TAHome); if (LampHome) break; usleep (300000); } if (i == 100) status = STATUS_DEVICE_BUSY; DBG (DBG_ASIC, "Wait %d s\n", (unsigned short) (i * 0.3)); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); chip->firmwarestate = FS_OPENED; chip->motorstate = MS_STILL; DBG (DBG_ASIC, "Asic_WaitCarriageHome: Exit\n"); return status; } static STATUS Asic_SetCalibrate (PAsic chip, SANE_Byte bScanBits, unsigned short wXResolution, unsigned short wYResolution, unsigned short wX, unsigned short wY, unsigned short wWidth, unsigned short wLength, SANE_Bool isShading) { STATUS status = STATUS_GOOD; unsigned short ValidPixelNumber; unsigned short wPerLineNeedBufferSize = 0; unsigned short BytePerPixel = 0; unsigned int dwTotalLineTheBufferNeed = 0; unsigned short dwTotal_CCDResolution = 0; unsigned short wThinkCCDResolution = 0; unsigned short wCCD_PixelNumber = 0; unsigned short wScanAccSteps = 1; SANE_Byte byScanDecSteps = 1; unsigned int dwLineWidthPixel = 0; unsigned short wNowMotorDPI; unsigned short XRatioTypeWord; double XRatioTypeDouble; double XRatioAdderDouble; LLF_MOTORMOVE *lpMotorStepsTable = (LLF_MOTORMOVE *) malloc (sizeof (LLF_MOTORMOVE)); SANE_Byte byDummyCycleNum = 1; unsigned short Total_MotorDPI; unsigned short BeforeScanFixSpeedStep = 0; unsigned short BackTrackFixSpeedStep = 20; unsigned short wMultiMotorStep = 1; SANE_Byte bMotorMoveType = _MOTOR_MOVE_TYPE; SANE_Byte isMotorMoveToFirstLine = MOTOR_MOVE_TO_FIRST_LINE_DISABLE; SANE_Byte isUniformSpeedToScan = UNIFORM_MOTOR_AND_SCAN_SPEED_ENABLE; SANE_Byte isScanBackTracking = SCAN_BACK_TRACKING_DISABLE; unsigned int TotalStep = 0; unsigned short StartSpeed, EndSpeed; LLF_CALCULATEMOTORTABLE CalMotorTable; LLF_MOTOR_CURRENT_AND_PHASE CurrentPhase; LLF_RAMACCESS RamAccess; unsigned int dwStartAddr, dwEndAddr, dwTableBaseAddr; SANE_Byte byClear_Pulse_Width = 0; unsigned int dwLinePixelReport = 0; SANE_Byte byPHTG_PulseWidth, byPHTG_WaitWidth; unsigned short * lpMotorTable = (unsigned short *) malloc (512 * 8 * 2); unsigned int RealTableSize; unsigned short wFullBank; DBG (DBG_ASIC, "Asic_SetCalibrate: Enter\n"); DBG (DBG_ASIC, "bScanBits=%d,wXResolution=%d, wYResolution=%d, wX=%d, wY=%d, wWidth=%d, wLength=%d\n", bScanBits, wXResolution, wYResolution, wX, wY, wWidth, wLength); if (chip->firmwarestate != FS_OPENED) { DBG (DBG_ERR, "Asic_SetCalibrate: Scanner is not opened\n"); return STATUS_INVAL; } if (lpMotorStepsTable == NULL) { DBG (DBG_ERR, "Asic_SetCalibrate: insufficiency memory!\n"); return STATUS_INVAL; } DBG (DBG_ASIC, "malloc LLF_MOTORMOVE =%ld Byte\n", (long int) (sizeof (LLF_MOTORMOVE))); Mustek_SendData (chip, ES01_F3_ActionOption, 0); Mustek_SendData (chip, ES01_86_DisableAllClockWhenIdle, CLOSE_ALL_CLOCK_DISABLE); Mustek_SendData (chip, ES01_F4_ActiveTriger, ACTION_TRIGER_DISABLE); status = Asic_WaitUnitReady (chip); Mustek_SendData (chip, 0x1CD, 0); Mustek_SendData (chip, ES01_94_PowerSaveControl, 0x27 | 64 | 128); if (bScanBits > 24) { wPerLineNeedBufferSize = wWidth * 6; BytePerPixel = 6; chip->dwBytesCountPerRow = (unsigned int) (wWidth) * 6; } else if (bScanBits == 24) { wPerLineNeedBufferSize = wWidth * 3; chip->dwCalibrationBytesCountPerRow = wWidth * 3; BytePerPixel = 3; chip->dwBytesCountPerRow = (unsigned int) (wWidth) * 3; } else if ((bScanBits > 8) && (bScanBits <= 16)) { wPerLineNeedBufferSize = wWidth * 2; BytePerPixel = 2; chip->dwBytesCountPerRow = (unsigned int) (wWidth) * 2; } else if ((bScanBits == 8)) { wPerLineNeedBufferSize = wWidth; BytePerPixel = 1; chip->dwBytesCountPerRow = (unsigned int) (wWidth); } else if ((bScanBits < 8)) { wPerLineNeedBufferSize = wWidth >> 3; BytePerPixel = 1; chip->dwBytesCountPerRow = (unsigned int) (wWidth); } DBG (DBG_ASIC, "wPerLineNeedBufferSize=%d,BytePerPixel=%d,dwBytesCountPerRow=%d\n", wPerLineNeedBufferSize, BytePerPixel, chip->dwBytesCountPerRow); dwTotalLineTheBufferNeed = wLength; DBG (DBG_ASIC, "wPerLineNeedBufferSize=%d,wLength=%d\n", wPerLineNeedBufferSize, wLength); chip->Scan.Dpi = wXResolution; CCDTiming (chip); dwTotal_CCDResolution = SENSOR_DPI; if (chip->lsLightSource == LS_REFLECTIVE) { if (wXResolution > (dwTotal_CCDResolution / 2)) { wThinkCCDResolution = dwTotal_CCDResolution; Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x01); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x01); wCCD_PixelNumber = chip->Timing.wCCDPixelNumber_1200; } else { wThinkCCDResolution = dwTotal_CCDResolution / 2; Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x01); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x00); wCCD_PixelNumber = chip->Timing.wCCDPixelNumber_600; } } else { if (wXResolution > (dwTotal_CCDResolution / 2)) { wThinkCCDResolution = dwTotal_CCDResolution; Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x01); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x01); wCCD_PixelNumber = TA_CAL_PIXELNUMBER; } else { wThinkCCDResolution = dwTotal_CCDResolution / 2; Mustek_SendData (chip, ES01_98_GPIOControl8_15, 0x01); Mustek_SendData (chip, ES01_96_GPIOValue8_15, 0x00); wCCD_PixelNumber = TA_CAL_PIXELNUMBER; } } DBG (DBG_ASIC, "wThinkCCDResolution=%d,wCCD_PixelNumber=%d\n", wThinkCCDResolution, wCCD_PixelNumber); dwLineWidthPixel = wWidth; if (isShading) wYResolution = 600; DBG (DBG_ASIC, "dwLineWidthPixel=%d,wYResolution=%d\n", dwLineWidthPixel, wYResolution); SetLineTimeAndExposure (chip); if (wYResolution == 600) { Mustek_SendData (chip, ES01_CB_CCDDummyCycleNumber, byDummyCycleNum); DBG (DBG_ASIC, "Find Boundary CCDDummyCycleNumber == %d\n", byDummyCycleNum); } SetLEDTime (chip); /* calculate Y ratio */ Total_MotorDPI = 1200; wNowMotorDPI = Total_MotorDPI; DBG (DBG_ASIC, "wNowMotorDPI=%d\n", wNowMotorDPI); /* SetADConverter */ Mustek_SendData (chip, ES01_74_HARDWARE_SETTING, MOTOR1_SERIAL_INTERFACE_G10_8_ENABLE | LED_OUT_G11_DISABLE | SLAVE_SERIAL_INTERFACE_G15_14_DISABLE | SHUTTLE_CCD_DISABLE); /* set AFE */ Mustek_SendData (chip, ES01_9A_AFEControl, AD9826_AFE | AUTO_CHANGE_AFE_GAIN_OFFSET_DISABLE); Mustek_SendData (chip, ES01_F7_DigitalControl, DIGITAL_REDUCE_DISABLE); XRatioTypeDouble = wXResolution; XRatioTypeDouble /= wThinkCCDResolution; XRatioAdderDouble = 1 / XRatioTypeDouble; XRatioTypeWord = (unsigned short) (XRatioTypeDouble * 32768); XRatioAdderDouble = (double) (XRatioTypeWord) / 32768; XRatioAdderDouble = 1 / XRatioAdderDouble; Mustek_SendData (chip, ES01_9E_HorizontalRatio1to15LSB, LOBYTE (XRatioTypeWord)); Mustek_SendData (chip, ES01_9F_HorizontalRatio1to15MSB, HIBYTE (XRatioTypeWord)); DBG (DBG_ASIC, "XRatioTypeDouble=%.2f,XRatioAdderDouble=%.2f,XRatioTypeWord=%d\n", XRatioTypeDouble, XRatioAdderDouble, XRatioTypeWord); if (chip->isMotorMove == MOTOR_0_ENABLE) { Mustek_SendData (chip, ES01_A6_MotorOption, MOTOR_0_ENABLE | MOTOR_1_DISABLE | HOME_SENSOR_0_ENABLE | ES03_TABLE_DEFINE); } else { Mustek_SendData (chip, ES01_A6_MotorOption, MOTOR_0_DISABLE | MOTOR_1_DISABLE | HOME_SENSOR_0_ENABLE | ES03_TABLE_DEFINE); } DBG (DBG_ASIC, "isMotorMove=%d\n", chip->isMotorMove); Mustek_SendData (chip, ES01_F6_MorotControl1, SPEED_UNIT_1_PIXEL_TIME | MOTOR_SYNC_UNIT_1_PIXEL_TIME); wScanAccSteps = 1; byScanDecSteps = 1; DBG (DBG_ASIC, "wScanAccSteps=%d,byScanDecSteps=%d\n", wScanAccSteps, byScanDecSteps); Mustek_SendData (chip, ES01_AE_MotorSyncPixelNumberM16LSB, LOBYTE (0)); Mustek_SendData (chip, ES01_AF_MotorSyncPixelNumberM16MSB, HIBYTE (0)); DBG (DBG_ASIC, "MotorSyncPixelNumber=%d\n", 0); Mustek_SendData (chip, ES01_EC_ScanAccStep0_7, LOBYTE (wScanAccSteps)); Mustek_SendData (chip, ES01_ED_ScanAccStep8_8, HIBYTE (wScanAccSteps)); DBG (DBG_ASIC, "wScanAccSteps=%d\n", wScanAccSteps); DBG (DBG_ASIC, "BeforeScanFixSpeedStep=%d,BackTrackFixSpeedStep=%d\n", BeforeScanFixSpeedStep, BackTrackFixSpeedStep); Mustek_SendData (chip, ES01_EE_FixScanStepLSB, LOBYTE (BeforeScanFixSpeedStep)); Mustek_SendData (chip, ES01_8A_FixScanStepMSB, HIBYTE (BeforeScanFixSpeedStep)); DBG (DBG_ASIC, "BeforeScanFixSpeedStep=%d\n", BeforeScanFixSpeedStep); Mustek_SendData (chip, ES01_EF_ScanDecStep, byScanDecSteps); DBG (DBG_ASIC, "byScanDecSteps=%d\n", byScanDecSteps); Mustek_SendData (chip, ES01_E6_ScanBackTrackingStepLSB, LOBYTE (BackTrackFixSpeedStep)); Mustek_SendData (chip, ES01_E7_ScanBackTrackingStepMSB, HIBYTE (BackTrackFixSpeedStep)); DBG (DBG_ASIC, "BackTrackFixSpeedStep=%d\n", BackTrackFixSpeedStep); Mustek_SendData (chip, ES01_E8_ScanRestartStepLSB, LOBYTE (BackTrackFixSpeedStep)); Mustek_SendData (chip, ES01_E9_ScanRestartStepMSB, HIBYTE (BackTrackFixSpeedStep)); DBG (DBG_ASIC, "BackTrackFixSpeedStep=%d\n", BackTrackFixSpeedStep); switch (bMotorMoveType) { case _4_TABLE_SPACE_FOR_FULL_STEP: wMultiMotorStep = 1; break; case _8_TABLE_SPACE_FOR_1_DIV_2_STEP: wMultiMotorStep = 2; break; case _16_TABLE_SPACE_FOR_1_DIV_4_STEP: wMultiMotorStep = 4; break; case _32_TABLE_SPACE_FOR_1_DIV_8_STEP: wMultiMotorStep = 8; break; } DBG (DBG_ASIC, "wMultiMotorStep=%d\n", wMultiMotorStep); TotalStep = wScanAccSteps + BeforeScanFixSpeedStep + (dwTotalLineTheBufferNeed * wNowMotorDPI / wYResolution) + byScanDecSteps; DBG (DBG_ASIC, "TotalStep=%d\n", TotalStep); Mustek_SendData (chip, ES01_F0_ScanImageStep0_7, (SANE_Byte) (TotalStep)); Mustek_SendData (chip, ES01_F1_ScanImageStep8_15, (SANE_Byte) (TotalStep >> 8)); Mustek_SendData (chip, ES01_F2_ScanImageStep16_19, (SANE_Byte) (TotalStep >> 16)); SetScanMode (chip, bScanBits); DBG (DBG_ASIC, "isMotorMoveToFirstLine=%d,isUniformSpeedToScan=%d,isScanBackTracking=%d\n", isMotorMoveToFirstLine, isUniformSpeedToScan, isScanBackTracking); Mustek_SendData (chip, ES01_F3_ActionOption, isMotorMoveToFirstLine | MOTOR_BACK_HOME_AFTER_SCAN_DISABLE | SCAN_ENABLE | isScanBackTracking | INVERT_MOTOR_DIRECTION_DISABLE | isUniformSpeedToScan | ES01_STATIC_SCAN_DISABLE | MOTOR_TEST_LOOP_DISABLE); if (chip->lsLightSource == LS_REFLECTIVE) Mustek_SendData (chip, ES01_F8_WHITE_SHADING_DATA_FORMAT, ES01_SHADING_3_INT_13_DEC); else Mustek_SendData (chip, ES01_F8_WHITE_SHADING_DATA_FORMAT, ES01_SHADING_4_INT_12_DEC); SetPackAddress (chip, wXResolution, wWidth, wX, XRatioAdderDouble, XRatioTypeDouble, byClear_Pulse_Width, &ValidPixelNumber); SetExtraSetting (chip, wXResolution, wCCD_PixelNumber, TRUE); byPHTG_PulseWidth = chip->Timing.PHTG_PluseWidth; byPHTG_WaitWidth = chip->Timing.PHTG_WaitWidth; dwLinePixelReport = ((byClear_Pulse_Width + 1) * 2 + (byPHTG_PulseWidth + 1) * (1) + (byPHTG_WaitWidth + 1) * (1) + (wCCD_PixelNumber + 1)) * (byDummyCycleNum + 1); DBG (DBG_ASIC, "Motor Time = %d\n", (dwLinePixelReport * wYResolution / wNowMotorDPI)); if ((dwLinePixelReport * wYResolution / wNowMotorDPI) > 64000) { DBG (DBG_ASIC, "Motor Time Over Flow !!!\n"); } EndSpeed = (unsigned short) (dwLinePixelReport / (wNowMotorDPI / wYResolution)); if (wXResolution > 600) { StartSpeed = EndSpeed; } else { StartSpeed = EndSpeed + 3500; } DBG (DBG_ASIC, "StartSpeed =%d, EndSpeed = %d\n", StartSpeed, EndSpeed); Mustek_SendData (chip, ES01_FD_MotorFixedspeedLSB, LOBYTE (EndSpeed)); Mustek_SendData (chip, ES01_FE_MotorFixedspeedMSB, HIBYTE (EndSpeed)); memset (lpMotorTable, 0, 512 * 8 * sizeof (unsigned short)); CalMotorTable.StartSpeed = StartSpeed; CalMotorTable.EndSpeed = EndSpeed; CalMotorTable.AccStepBeforeScan = wScanAccSteps; CalMotorTable.lpMotorTable = lpMotorTable; LLFCalculateMotorTable (&CalMotorTable); CurrentPhase.MotorDriverIs3967 = 0; CurrentPhase.FillPhase = 1; CurrentPhase.MoveType = bMotorMoveType; CurrentPhase.MotorCurrentTableA[0] = 200; CurrentPhase.MotorCurrentTableB[0] = 200; LLFSetMotorCurrentAndPhase (chip, &CurrentPhase); RealTableSize = 512 * 8; dwTableBaseAddr = PackAreaStartAddress - RealTableSize; dwStartAddr = dwTableBaseAddr; RamAccess.ReadWrite = WRITE_RAM; RamAccess.IsOnChipGamma = EXTERNAL_RAM; RamAccess.DramDelayTime = SDRAMCLK_DELAY_12_ns; RamAccess.LoStartAddress = (unsigned short) (dwStartAddr); RamAccess.HiStartAddress = (unsigned short) (dwStartAddr >> 16); RamAccess.RwSize = RealTableSize * 2; RamAccess.BufferPtr = (SANE_Byte *) lpMotorTable; LLFRamAccess (chip, &RamAccess); Mustek_SendData (chip, ES01_9D_MotorTableAddrA14_A21, (SANE_Byte) (dwTableBaseAddr >> TABLE_OFFSET_BASE)); dwEndAddr = PackAreaStartAddress - (512 * 8) - 1; Mustek_SendData (chip, ES01_FB_BufferEmptySize16WordLSB, LOBYTE (WaitBufferOneLineSize >> (7 - 3))); Mustek_SendData (chip, ES01_FC_BufferEmptySize16WordMSB, HIBYTE (WaitBufferOneLineSize >> (7 - 3))); wFullBank = (unsigned short) ((dwEndAddr - (((dwLineWidthPixel * BytePerPixel) / 2) * 3 * 1)) / BANK_SIZE); Mustek_SendData (chip, ES01_F9_BufferFullSize16WordLSB, LOBYTE (wFullBank)); Mustek_SendData (chip, ES01_FA_BufferFullSize16WordMSB, HIBYTE (wFullBank)); Mustek_SendData (chip, ES01_DB_PH_RESET_EDGE_TIMING_ADJUST, 0x00); LLFSetRamAddress (chip, 0x0, dwEndAddr, ACCESS_DRAM); Mustek_SendData (chip, ES01_DC_CLEAR_EDGE_TO_PH_TG_EDGE_WIDTH, 0); Mustek_SendData (chip, ES01_00_ADAFEConfiguration, 0x70); Mustek_SendData (chip, ES01_02_ADAFEMuxConfig, 0x80); free (lpMotorTable); free (lpMotorStepsTable); DBG (DBG_ASIC, "Asic_SetCalibrate: Exit\n"); return status; } static STATUS Asic_SetAFEGainOffset (PAsic chip) { STATUS status = STATUS_GOOD; DBG (DBG_ASIC, "Asic_SetAFEGainOffset:Enter\n"); status = SetAFEGainOffset (chip); DBG (DBG_ASIC, "Asic_SetAFEGainOffset: Exit\n"); return status; } sane-backends-1.0.27/backend/s9036.conf.in0000664000175000017500000000001512112021330014626 00000000000000/dev/scanner sane-backends-1.0.27/backend/dc210.c0000664000175000017500000010447712775312260013610 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. dc210.c 11/11/98 This file (C) 1998 Brian J. Murrell This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for the Kodak DC-210 digital camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! (feedback to: sane-dc210@interlinx.bc.ca This backend is based somewhat on the dc25 backend included in this package by Peter Fales ***************************************************************************/ #include "../include/sane/config.h" #include #include #include #include #include #include #include "../include/sane/sanei_jpeg.h" #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME dc210 #include "../include/sane/sanei_backend.h" #include "dc210.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define MAGIC (void *)0xab730324 #define DC210_CONFIG_FILE "dc210.conf" #define THUMBSIZE 20736 #ifdef B115200 # define DEFAULT_BAUD_RATE B115200 #else # define DEFAULT_BAUD_RATE B38400 #endif #if defined (__sgi) # define DEFAULT_TTY "/dev/ttyd1" /* Irix */ #elif defined (__sun) # define DEFAULT_TTY "/dev/term/a" /* Solaris */ #elif defined (hpux) # define DEFAULT_TTY "/dev/tty1d0" /* HP-UX */ #elif defined (__osf__) # define DEFAULT_TTY "/dev/tty00" /* Digital UNIX */ #else # define DEFAULT_TTY "/dev/ttyS0" /* Linux */ #endif static SANE_Bool is_open = 0; static SANE_Bool dc210_opt_thumbnails; static SANE_Bool dc210_opt_snap; static SANE_Bool dc210_opt_lowres; static SANE_Bool dc210_opt_erase; static SANE_Bool dumpinquiry; static struct jpeg_decompress_struct cinfo; static djpeg_dest_ptr dest_mgr = NULL; static unsigned long cmdrespause = 250000UL; /* pause after sending cmd */ static unsigned long breakpause = 1000000UL; /* pause after sending break */ static int bytes_in_buffer; static int bytes_read_from_buffer; static int total_bytes_read; static DC210 Camera; static SANE_Range image_range = { 0, 14, 0 }; static SANE_Option_Descriptor sod[] = { { SANE_NAME_NUM_OPTIONS, SANE_TITLE_NUM_OPTIONS, SANE_DESC_NUM_OPTIONS, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define D25_OPT_IMAGE_SELECTION 1 { "", "Image Selection", "Selection of the image to load.", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0, 0, SANE_CONSTRAINT_NONE, {NULL} } , #define DC210_OPT_IMAGE_NUMBER 2 { "image", "Image Number", "Select Image Number to load from camera", SANE_TYPE_INT, SANE_UNIT_NONE, 4, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(void *) & image_range} } , #define DC210_OPT_THUMBS 3 { "thumbs", "Load Thumbnail", "Load the image as thumbnail.", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC210_OPT_SNAP 4 { "snap", "Snap new picture", "Take new picture and download it", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT /* | SANE_CAP_ADVANCED */ , SANE_CONSTRAINT_NONE, {NULL} } , #define DC210_OPT_LOWRES 5 { "lowres", "Low Resolution", "Resolution of new pictures", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE /* | SANE_CAP_ADVANCED */ , SANE_CONSTRAINT_NONE, {NULL} } , #define DC210_OPT_ERASE 6 { "erase", "Erase", "Erase the picture after downloading", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC210_OPT_DEFAULT 7 { "default-enhancements", "Defaults", "Set default values for enhancement controls.", SANE_TYPE_BUTTON, SANE_UNIT_NONE, 0, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC210_OPT_INIT_DC210 8 { "camera-init", "Re-establish Communications", "Re-establish communications with camera (in case of timeout, etc.)", SANE_TYPE_BUTTON, SANE_UNIT_NONE, 0, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } }; static SANE_Parameters parms = { SANE_FRAME_RGB, 0, 0, /* Number of bytes returned per scan line: */ 0, /* Number of pixels per scan line. */ 0, /* Number of lines for the current scan. */ 8, /* Number of bits per sample. */ }; static unsigned char shoot_pck[] = SHOOT_PCK; static unsigned char init_pck[] = INIT_PCK; static unsigned char thumb_pck[] = THUMBS_PCK; static unsigned char pic_pck[] = PICS_PCK; static unsigned char pic_info_pck[] = PICS_INFO_PCK; static unsigned char info_pck[] = INFO_PCK; static unsigned char erase_pck[] = ERASE_PCK; static unsigned char res_pck[] = RES_PCK; static struct pkt_speed speeds[] = SPEEDS; static struct termios tty_orig; #include #include static int send_pck (int fd, unsigned char *pck) { int n; unsigned char r = 0xf0; /* prime the loop with a "camera busy" */ /* keep trying if camera says it's busy */ while (r == 0xf0) { /* * Not quite sure why we need this, but the program works a whole * lot better (at least on the DC210) with this short delay. */ if (write (fd, (char *) pck, 8) != 8) { DBG (2, "send_pck: error: write returned -1\n"); return -1; } /* need to wait before we read command result */ usleep (cmdrespause); if ((n = read (fd, (char *) &r, 1)) != 1) { DBG (2, "send_pck: error: read returned -1\n"); return -1; } } return (r == 0xd1) ? 0 : -1; } static int init_dc210 (DC210 * camera) { struct termios tty_new; int speed_index; for (speed_index = 0; speed_index < NELEMS (speeds); speed_index++) { if (speeds[speed_index].baud == camera->baud) { init_pck[2] = speeds[speed_index].pkt_code[0]; init_pck[3] = speeds[speed_index].pkt_code[1]; break; } } if (init_pck[2] == 0) { DBG (2, "unsupported baud rate.\n"); return -1; } /* Open device file. */ if ((camera->fd = open (camera->tty_name, O_RDWR)) == -1) { DBG (2, "init_dc210: error: could not open %s for read/write\n", camera->tty_name); return -1; } /* Save old device information to restore when we are done. */ if (tcgetattr (camera->fd, &tty_orig) == -1) { DBG (2, "init_dc210: error: could not get attributes\n"); return -1; } memcpy ((char *) &tty_new, (char *) &tty_orig, sizeof (struct termios)); /* We need the device to be raw. 8 bits even parity on 9600 baud to start. */ #ifdef HAVE_CFMAKERAW cfmakeraw (&tty_new); #else /* Modified to set the port REALLY as required. Code inspired by the gPhoto2 serial port setup */ /* input control settings */ tty_new.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC | IXANY | IXON | IXOFF | INPCK | ISTRIP); tty_new.c_iflag |= (BRKINT | IGNPAR); /* output control settings */ tty_new.c_oflag &= ~OPOST; /* hardware control settings */ tty_new.c_cflag = (tty_new.c_cflag & ~CSIZE) | CS8; tty_new.c_cflag &= ~(PARENB | PARODD | CSTOPB); # if defined(__sgi) tty_new.c_cflag &= ~CNEW_RTSCTS; # else /* OS/2 doesn't have CRTSCTS - will this work for them? */ # ifdef CRTSCTS tty_new.c_cflag &= ~CRTSCTS; # endif # endif tty_new.c_cflag |= CLOCAL | CREAD; #endif /* line discipline settings */ tty_new.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE | ECHOK | IEXTEN); tty_new.c_cc[VMIN] = 0; tty_new.c_cc[VTIME] = 5; cfsetospeed (&tty_new, B9600); cfsetispeed (&tty_new, B9600); if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) { DBG (2, "init_dc210: error: could not set attributes\n"); return -1; } /* send a break to get it back to a known state */ /* Used to supply a non-zero argument to tcsendbreak(), TCSBRK, * and TCSBRKP, but that is system dependent. e.g. on irix a non-zero * value does a drain instead of a break. A zero value is universally * used to send a break. */ #ifdef HAVE_TCSENDBREAK tcsendbreak (camera->fd, 0); # if defined(__sgi) tcdrain (camera->fd); # endif # elif defined(TCSBRKP) ioctl (camera->fd, TCSBRKP, 0); # elif defined(TCSBRK) ioctl (camera->fd, TCSBRK, 0); #endif /* and wait for it to recover from the break */ #ifdef HAVE_USLEEP usleep (breakpause); #else sleep (1); #endif if (send_pck (camera->fd, init_pck) == -1) { /* * The camera always powers up at 9600, so we try * that first. However, it may be already set to * a different speed. Try the entries in the table: */ for (speed_index = NELEMS (speeds) - 1; speed_index > 0; speed_index--) { int x; DBG (3, "init_dc210: changing speed to %d\n", (int) speeds[speed_index].baud); cfsetospeed (&tty_new, speeds[speed_index].baud); cfsetispeed (&tty_new, speeds[speed_index].baud); if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) { DBG (2, "init_dc210: error: could not set attributes\n"); return -1; } for (x = 0; x < 3; x++) if (send_pck (camera->fd, init_pck) != -1) break; } if (speed_index == 0) { tcsetattr (camera->fd, TCSANOW, &tty_orig); DBG (2, "init_dc210: error: no suitable baud rate\n"); return -1; } } /* Set speed to requested speed. */ cfsetospeed (&tty_new, Camera.baud); cfsetispeed (&tty_new, Camera.baud); if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) { DBG (2, "init_dc210: error: could not set attributes\n"); return -1; } return camera->fd; } static void close_dc210 (int fd) { /* * Put the camera back to 9600 baud */ if (close (fd) == -1) { DBG (4, "close_dc210: error: could not close device\n"); } } int get_info (DC210 * camera) { char f[] = "get_info"; unsigned char buf[256]; if (send_pck (camera->fd, info_pck) == -1) { DBG (2, "%s: error: send_pck returned -1\n", f); return -1; } DBG (9, "%s: read info packet\n", f); if (read_data (camera->fd, buf, 256) == -1) { DBG (2, "%s: error: read_data returned -1\n", f); return -1; } if (end_of_data (camera->fd) == -1) { DBG (2, "%s: error: end_of_data returned -1\n", f); return -1; } camera->model = buf[1]; camera->ver_major = buf[2]; camera->ver_minor = buf[3]; camera->pic_taken = buf[56] << 8 | buf[57]; camera->pic_left = buf[72] << 8 | buf[73]; camera->flags.low_res = buf[22]; camera->flags.low_batt = buf[8]; return 0; } static int read_data (int fd, unsigned char *buf, int sz) { unsigned char ccsum; unsigned char rcsum; unsigned char c; int n; int r = 0; int i; /* read the control byte */ if (read (fd, &c, 1) != 1) { DBG (2, "read_data: error: read for packet control byte returned bad status\n"); return -1; } if (c != 1) { DBG (2, "read_data: error: incorrect packet control byte: %02x\n", c); return -1; } for (n = 0; n < sz && (r = read (fd, (char *) &buf[n], sz - n)) > 0; n += r) ; if (r <= 0) { DBG (2, "read_data: error: read returned -1\n"); return -1; } if (n < sz || read (fd, &rcsum, 1) != 1) { DBG (2, "read_data: error: buffer underrun or no checksum\n"); return -1; } for (i = 0, ccsum = 0; i < n; i++) ccsum ^= buf[i]; if (ccsum != rcsum) { DBG (2, "read_data: error: bad checksum (%02x !=%02x)\n", rcsum, ccsum); return -1; } c = 0xd2; if (write (fd, (char *) &c, 1) != 1) { DBG (2, "read_data: error: write ack\n"); return -1; } return 0; } static int end_of_data (int fd) { unsigned char c; do { /* loop until the camera isn't busy */ if (read (fd, &c, 1) != 1) { DBG (2, "end_of_data: error: read returned -1\n"); return -1; } if (c == 0) /* got successful end of data */ return 0; /* return success */ sleep (1); /* not too fast */ } while (c == 0xf0); /* Accck! Not busy, but not a good end of data either */ if (c != 0) { DBG (2, "end_of_data: error: bad EOD from camera (%02x)\n", (unsigned) c); return -1; } return 0; /* should never get here but shut gcc -Wall up */ } static int erase (int fd) { if (send_pck (fd, erase_pck) == -1) { DBG (3, "erase: error: send_pck returned -1\n"); return -1; } if (end_of_data (fd) == -1) { DBG (3, "erase: error: end_of_data returned -1\n"); return -1; } return 0; } static int change_res (int fd, unsigned char res) { char f[] = "change_res"; DBG (127, "%s called\n", f); if (res != 0 && res != 1) { DBG (3, "%s: error: unsupported resolution\n", f); return -1; } /* cameras resolution semantics are opposite of ours */ res = !res; DBG (127, "%s: setting res to %d\n", f, res); res_pck[2] = res; if (send_pck (fd, res_pck) == -1) { DBG (4, "%s: error: send_pck returned -1\n", f); } if (end_of_data (fd) == -1) { DBG (4, "%s: error: end_of_data returned -1\n", f); } return 0; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { char f[] = "sane_init"; char dev_name[PATH_MAX], *p; size_t len; FILE *fp; int baud; DBG_INIT (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (DC210_CONFIG_FILE); /* defaults */ Camera.baud = DEFAULT_BAUD_RATE; Camera.tty_name = DEFAULT_TTY; if (!fp) { /* default to /dev/whatever instead of insisting on config file */ DBG (1, "%s: missing config file '%s'\n", f, DC210_CONFIG_FILE); } else { while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { dev_name[sizeof (dev_name) - 1] = '\0'; DBG (20, "%s: config- %s\n", f, dev_name); if (dev_name[0] == '#') continue; /* ignore line comments */ len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ if (strncmp (dev_name, "port=", 5) == 0) { p = strchr (dev_name, '/'); if (p) Camera.tty_name = strdup (p); DBG (20, "Config file port=%s\n", Camera.tty_name); } else if (strncmp (dev_name, "baud=", 5) == 0) { baud = atoi (&dev_name[5]); switch (baud) { case 9600: Camera.baud = B9600; break; case 19200: Camera.baud = B19200; break; case 38400: Camera.baud = B38400; break; #ifdef B57600 case 57600: Camera.baud = B57600; break; #endif #ifdef B115200 case 115200: Camera.baud = B115200; break; #endif } DBG (20, "Config file baud=%d\n", Camera.baud); } else if (strcmp (dev_name, "dumpinquiry") == 0) { dumpinquiry = SANE_TRUE; } else if (strncmp (dev_name, "cmdrespause=", 12) == 0) { cmdrespause = atoi (&dev_name[12]); DBG (20, "Config file cmdrespause=%lu\n", cmdrespause); } else if (strncmp (dev_name, "breakpause=", 11) == 0) { breakpause = atoi (&dev_name[11]); DBG (20, "Config file breakpause=%lu\n", breakpause); } } fclose (fp); } if (init_dc210 (&Camera) == -1) return SANE_STATUS_INVAL; if (get_info (&Camera) == -1) { DBG (2, "error: could not get info\n"); close_dc210 (Camera.fd); return SANE_STATUS_INVAL; } if (Camera.pic_taken == 0) { sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; image_range.min = 0; image_range.max = 0; } else { sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; image_range.min = 1; image_range.max = Camera.pic_taken; } /* load the current images array */ Camera.Pictures = get_pictures_info (); if (Camera.pic_taken == 0) { Camera.current_picture_number = 0; parms.bytes_per_line = 0; parms.pixels_per_line = 0; parms.lines = 0; } else { Camera.current_picture_number = 1; if (Camera.Pictures[Camera.current_picture_number - 1].low_res) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } } if (dumpinquiry) { DBG (0, "\nCamera information:\n~~~~~~~~~~~~~~~~~\n\n"); DBG (0, "Model...........: DC%x\n", Camera.model); DBG (0, "Firmware version: %d.%d\n", Camera.ver_major, Camera.ver_minor); DBG (0, "Pictures........: %d/%d\n", Camera.pic_taken, Camera.pic_taken + Camera.pic_left); DBG (0, "Resolution......: %s\n", Camera.flags.low_res ? "low" : "high"); DBG (0, "Battery state...: %s\n", Camera.flags.low_batt ? "low" : "good"); } return SANE_STATUS_GOOD; } void sane_exit (void) { } /* Device select/open/close */ static const SANE_Device dev[] = { { "0", "Kodak", "DC-210", "still camera"}, }; SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { static const SANE_Device *devlist[] = { dev + 0, 0 }; DBG (127, "sane_get_devices called\n"); *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { int i; DBG (127, "sane_open for device %s\n", devicename); if (!devicename[0]) { i = 0; } else { for (i = 0; i < NELEMS (dev); ++i) { if (strcmp (devicename, dev[i].name) == 0) { break; } } } if (i >= NELEMS (dev)) { return SANE_STATUS_INVAL; } if (is_open) { return SANE_STATUS_DEVICE_BUSY; } is_open = 1; *handle = MAGIC; DBG (3, "sane_open: pictures taken=%d\n", Camera.pic_taken); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { DBG (127, "sane_close called\n"); if (handle == MAGIC) is_open = 0; DBG (127, "sane_close returning\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { if (handle != MAGIC || !is_open) return NULL; /* wrong device */ if (option < 0 || option >= NELEMS (sod)) return NULL; return &sod[option]; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { SANE_Int myinfo = 0; SANE_Status status; DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n", handle, sod[option].title, (action == SANE_ACTION_SET_VALUE ? "SET" : (action == SANE_ACTION_GET_VALUE ? "GET" : "SETAUTO")), value, (void *)info); if (handle != MAGIC || !is_open) return SANE_STATUS_INVAL; /* Unknown handle ... */ if (option < 0 || option >= NELEMS (sod)) return SANE_STATUS_INVAL; /* Unknown option ... */ switch (action) { case SANE_ACTION_SET_VALUE: status = sanei_constrain_value (sod + option, value, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (1, "Constraint error in control_option\n"); return status; } switch (option) { case DC210_OPT_IMAGE_NUMBER: Camera.current_picture_number = *(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; /* get the image's resolution */ if (Camera.Pictures[Camera.current_picture_number - 1].low_res) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } break; case DC210_OPT_THUMBS: dc210_opt_thumbnails = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; if (dc210_opt_thumbnails) { /* * DC210 thumbnail are 96x72x8x3 */ parms.bytes_per_line = 96 * 3; parms.pixels_per_line = 96; parms.lines = 72; } else { if (Camera.Pictures[Camera.current_picture_number - 1].low_res) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } } break; case DC210_OPT_SNAP: dc210_opt_snap = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; /* if we are snapping a new one */ if (dc210_opt_snap) { /* activate the resolution setting */ sod[DC210_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE; /* and de-activate the image number selector */ sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; } else { /* deactivate the resolution setting */ sod[DC210_OPT_LOWRES].cap |= SANE_CAP_INACTIVE; /* and activate the image number selector */ sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; } /* set params according to resolution settings */ if (dc210_opt_lowres) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } break; case DC210_OPT_LOWRES: dc210_opt_lowres = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; if (!dc210_opt_thumbnails) { /* XXX - change the number of pictures left depending on resolution perhaps just call get_info again? */ if (dc210_opt_lowres) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } } break; case DC210_OPT_ERASE: dc210_opt_erase = !!*(SANE_Word *) value; break; case DC210_OPT_DEFAULT: DBG (1, "Fixme: Set all defaults here!\n"); break; case DC210_OPT_INIT_DC210: if ((Camera.fd = init_dc210 (&Camera)) == -1) { return SANE_STATUS_INVAL; } break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_GET_VALUE: switch (option) { case 0: *(SANE_Word *) value = NELEMS (sod); break; case DC210_OPT_IMAGE_NUMBER: *(SANE_Word *) value = Camera.current_picture_number; break; case DC210_OPT_THUMBS: *(SANE_Word *) value = dc210_opt_thumbnails; break; case DC210_OPT_SNAP: *(SANE_Word *) value = dc210_opt_snap; break; case DC210_OPT_LOWRES: *(SANE_Word *) value = dc210_opt_lowres; break; case DC210_OPT_ERASE: *(SANE_Word *) value = dc210_opt_erase; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_AUTO: switch (option) { default: return SANE_STATUS_UNSUPPORTED; /* We are DUMB */ } } if (info) *info = myinfo; return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int rc = SANE_STATUS_GOOD; DBG (127, "sane_get_params called\n"); if (handle != MAGIC || !is_open) rc = SANE_STATUS_INVAL; /* Unknown handle ... */ parms.last_frame = SANE_TRUE; /* Have no idea what this does */ *params = parms; DBG (127, "sane_get_params return %d\n", rc); return rc; } typedef struct { struct jpeg_source_mgr pub; JOCTET *buffer; } my_source_mgr; typedef my_source_mgr *my_src_ptr; METHODDEF (void) sanei_jpeg_init_source (j_decompress_ptr __sane_unused__ cinfo) { /* nothing to do */ } METHODDEF (boolean) sanei_jpeg_fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; if (read_data (Camera.fd, src->buffer, 1024) == -1) { DBG (5, "sane_start: read_data failed\n"); src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; return FALSE; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = 1024; return TRUE; } METHODDEF (void) sanei_jpeg_skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr) cinfo->src; if (num_bytes > 0) { while (num_bytes > (long) src->pub.bytes_in_buffer) { num_bytes -= (long) src->pub.bytes_in_buffer; (void) sanei_jpeg_fill_input_buffer (cinfo); } } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; } METHODDEF (void) sanei_jpeg_term_source (j_decompress_ptr __sane_unused__ cinfo) { /* no work necessary here */ } SANE_Status sane_start (SANE_Handle handle) { DBG (127, "sane_start called\n"); if (handle != MAGIC || !is_open || (Camera.current_picture_number == 0 && dc210_opt_snap == SANE_FALSE)) return SANE_STATUS_INVAL; /* Unknown handle ... */ if (Camera.scanning) return SANE_STATUS_EOF; if (dc210_opt_snap) { /* * Don't allow picture unless there is room in the * camera. */ if (Camera.pic_left == 0) { DBG (3, "No room to store new picture\n"); return SANE_STATUS_INVAL; } if (snap_pic (Camera.fd) != SANE_STATUS_GOOD) { DBG (1, "Failed to snap new picture\n"); return SANE_STATUS_INVAL; } } if (dc210_opt_thumbnails) { thumb_pck[3] = (unsigned char) Camera.current_picture_number - 1; thumb_pck[4] = 1; if (send_pck (Camera.fd, thumb_pck) == -1) { DBG (4, "sane_start: error: send_pck returned -1\n"); return SANE_STATUS_INVAL; } parms.bytes_per_line = 96 * 3; parms.pixels_per_line = 96; parms.lines = 72; bytes_in_buffer = 0; bytes_read_from_buffer = 0; } else { my_src_ptr src; struct jpeg_error_mgr jerr; pic_pck[3] = (unsigned char) Camera.current_picture_number - 1; if (send_pck (Camera.fd, pic_pck) == -1) { DBG (4, "sane_start: error: send_pck returned -1\n"); return SANE_STATUS_INVAL; } cinfo.err = jpeg_std_error (&jerr); jpeg_create_decompress (&cinfo); cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) & cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr)); src = (my_src_ptr) cinfo.src; src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) & cinfo, JPOOL_PERMANENT, 1024 * sizeof (JOCTET)); src->pub.init_source = sanei_jpeg_init_source; src->pub.fill_input_buffer = sanei_jpeg_fill_input_buffer; src->pub.skip_input_data = sanei_jpeg_skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* default */ src->pub.term_source = sanei_jpeg_term_source; src->pub.bytes_in_buffer = 0; src->pub.next_input_byte = NULL; (void) jpeg_read_header (&cinfo, TRUE); dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo); (void) jpeg_start_decompress (&cinfo); } Camera.scanning = SANE_TRUE; /* don't overlap scan requests */ total_bytes_read = 0; return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle __sane_unused__ handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { static char buffer[1024]; if (dc210_opt_thumbnails) { if (total_bytes_read == THUMBSIZE) { if (dc210_opt_erase) { if (erase (Camera.fd) == -1) { DBG (1, "Failed to erase memory\n"); return SANE_STATUS_INVAL; } Camera.pic_taken--; Camera.pic_left++; Camera.current_picture_number = Camera.pic_taken; image_range.max--; } return SANE_STATUS_EOF; } *length = 0; if (!(bytes_in_buffer - bytes_read_from_buffer)) { if (read_data (Camera.fd, (unsigned char *) buffer, 1024) == -1) { DBG (5, "sane_read: read_data failed\n"); return SANE_STATUS_INVAL; } bytes_in_buffer = 1024; bytes_read_from_buffer = 0; } while (bytes_read_from_buffer < bytes_in_buffer && max_length && total_bytes_read < THUMBSIZE) { *data++ = buffer[bytes_read_from_buffer++]; (*length)++; max_length--; total_bytes_read++; } if (total_bytes_read == THUMBSIZE) { if (end_of_data (Camera.fd) == -1) { DBG (4, "sane_read: end_of_data error\n"); return SANE_STATUS_INVAL; } else { return SANE_STATUS_GOOD; } } else { return SANE_STATUS_GOOD; } } else { int lines = 0; if (cinfo.output_scanline >= cinfo.output_height) { /* clean up comms with the camera */ if (end_of_data (Camera.fd) == -1) { DBG (2, "sane_read: error: end_of_data returned -1\n"); return SANE_STATUS_INVAL; } if (dc210_opt_erase) { DBG (127, "sane_read bp%d, erase image\n", __LINE__); if (erase (Camera.fd) == -1) { DBG (1, "Failed to erase memory\n"); return SANE_STATUS_INVAL; } Camera.pic_taken--; Camera.pic_left++; Camera.current_picture_number = Camera.pic_taken; image_range.max--; } return SANE_STATUS_EOF; } /* XXX - we should read more than 1 line at a time here */ lines = 1; (void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines); (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) data); *length = cinfo.output_width * cinfo.output_components * lines; return SANE_STATUS_GOOD; } } void sane_cancel (SANE_Handle __sane_unused__ handle) { DBG (127, "sane_cancel() called\n"); if (Camera.scanning) Camera.scanning = SANE_FALSE; /* done with scan */ else DBG (127, "sane_cancel() aborted, scanner not scanning\n"); } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { return SANE_STATUS_UNSUPPORTED; } static PictureInfo * get_pictures_info (void) { char f[] = "get_pictures_info"; unsigned int p; PictureInfo *pics; if ((pics = (PictureInfo *) malloc (Camera.pic_taken * sizeof (PictureInfo))) == NULL) { DBG (4, "%s: error: allocate memory for pictures array\n", f); return NULL; } for (p = 0; p < (unsigned int) Camera.pic_taken; p++) { if (get_picture_info (pics + p, p) == -1) { free (pics); return NULL; } } return pics; } static int get_picture_info (PictureInfo * pic, int p) { char f[] = "get_picture_info"; static char buffer[256]; DBG (4, "%s: info for pic #%d\n", f, p); pic_info_pck[3] = (unsigned char) p; if (send_pck (Camera.fd, pic_info_pck) == -1) { DBG (4, "%s: error: send_pck returned -1\n", f); return -1; } if (read_data (Camera.fd, (unsigned char *) buffer, 256) == -1) { DBG (2, "%s: error: read_data returned -1\n", f); return -1; } if (end_of_data (Camera.fd) == -1) { DBG (2, "%s: error: end_of_data returned -1\n", f); return -1; } if (buffer[3] == 0) { pic->low_res = SANE_TRUE; } else if (buffer[3] == 1) { pic->low_res = SANE_FALSE; } else { DBG (2, "%s: error: unknown resolution code %u\n", f, buffer[3]); return -1; } pic->size = (buffer[8] & 0xFF) << 24; pic->size |= (buffer[9] & 0xFF) << 16; pic->size |= (buffer[10] & 0xFF) << 8; pic->size |= (buffer[11] & 0xFF); return 0; } static SANE_Status snap_pic (int fd) { char f[] = "snap_pic"; /* make sure camera is set to our settings state */ if (change_res (Camera.fd, dc210_opt_lowres) == -1) { DBG (1, "%s: Failed to set resolution\n", f); return SANE_STATUS_INVAL; } /* take the picture */ if (send_pck (fd, shoot_pck) == -1) { DBG (4, "%s: error: send_pck returned -1\n", f); return SANE_STATUS_INVAL; } else { if (end_of_data (Camera.fd) == -1) { DBG (2, "%s: error: end_of_data returned -1\n", f); return SANE_STATUS_INVAL; } } Camera.pic_taken++; Camera.pic_left--; Camera.current_picture_number = Camera.pic_taken; image_range.max++; sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; /* add this one to the Pictures array */ if ((Camera.Pictures = (PictureInfo *) realloc (Camera.Pictures, Camera.pic_taken * sizeof (PictureInfo))) == NULL) { DBG (4, "%s: error: allocate memory for pictures array\n", f); return SANE_STATUS_INVAL; } if (get_picture_info (Camera.Pictures + Camera.pic_taken, Camera.pic_taken) == -1) { DBG (1, "%s: Failed to get new picture info\n", f); /* XXX - I guess we should try to erase the image here */ return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/pieusb_specific.h0000664000175000017500000003720013106201017016107 00000000000000/* sane - Scanner Access Now Easy. pieusb_specific.h Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIEUSB_SPECIFIC_H #define PIEUSB_SPECIFIC_H #include "../include/sane/sanei_ir.h" #include "../include/sane/sanei_backend.h" #include "pieusb_scancmd.h" #include "pieusb_buffer.h" /* Settings for scan modes available to SANE */ /* In addition to those defined in sane.h */ #define SANE_VALUE_SCAN_MODE_RGBI "RGBI" /* Scanner settings for colors to scan */ #define SCAN_ONE_PASS_RGBI 0x90 #define SCAN_ONE_PASS_COLOR 0x80 #define SCAN_FILTER_INFRARED 0x10 #define SCAN_FILTER_BLUE 0x08 #define SCAN_FILTER_GREEN 0x04 #define SCAN_FILTER_RED 0x02 #define SCAN_FILTER_NEUTRAL 0x01 /* Settings for color depth of scan */ #define SCAN_COLOR_DEPTH_16 0x20 #define SCAN_COLOR_DEPTH_12 0x10 #define SCAN_COLOR_DEPTH_10 0x08 #define SCAN_COLOR_DEPTH_8 0x04 #define SCAN_COLOR_DEPTH_4 0x02 #define SCAN_COLOR_DEPTH_1 0x01 /* Settings for format of the scanned data */ #define SCAN_COLOR_FORMAT_INDEX 0x04 #define SCAN_COLOR_FORMAT_LINE 0x02 #define SCAN_COLOR_FORMAT_PIXEL 0x01 /* Settings for calibration mode */ #define SCAN_CALIBRATION_DEFAULT "default values" #define SCAN_CALIBRATION_AUTO "from internal test" #define SCAN_CALIBRATION_PREVIEW "from preview" #define SCAN_CALIBRATION_OPTIONS "from options" /* Settings for additional gain */ #define SCAN_GAIN_ADJUST_03 "* 0.3" #define SCAN_GAIN_ADJUST_05 "* 0.5" #define SCAN_GAIN_ADJUST_08 "* 0.8" #define SCAN_GAIN_ADJUST_10 "* 1.0" #define SCAN_GAIN_ADJUST_12 "* 1.2" #define SCAN_GAIN_ADJUST_16 "* 1.6" #define SCAN_GAIN_ADJUST_19 "* 1.9" #define SCAN_GAIN_ADJUST_24 "* 2.4" #define SCAN_GAIN_ADJUST_30 "* 3.0" /* Post-processing */ #define POST_SW_COLORS (1 << 0) /* gain, negatives, ..., can be done at any time */ #define POST_SW_IRED (1 << 1) /* remove spectral overlap, needs complete scan */ #define POST_SW_DIRT (1 << 2) /* our digital lavabo, needs complete scan */ #define POST_SW_GRAIN (1 << 3) /* smoothen a bit */ #define POST_SW_CROP (1 << 4) /* trim whole image in sane_start before sane_get_parameters() is answered */ #define POST_SW_IRED_MASK (POST_SW_IRED | POST_SW_DIRT) #define POST_SW_ACCUM_MASK (POST_SW_IRED_MASK | POST_SW_GRAIN | POST_SW_CROP) #define DEFAULT_GAIN 19 /* 0x13 */ #define DEFAULT_EXPOSURE 2937 /* 0xb79 minimum value, see Pieusb_Settings */ #define DEFAULT_OFFSET 0 #define DEFAULT_LIGHT 4 #define DEFAULT_ADDITIONAL_ENTRIES 1 #define DEFAULT_DOUBLE_TIMES 0 /* -------------------------------------------------------------------------- * * DEVICE DEFINITION STRUCTURES * * --------------------------------------------------------------------------*/ /* Options supported by the scanner */ enum Pieusb_Option { OPT_NUM_OPTS = 0, /* ------------------------------------------- */ OPT_MODE_GROUP, OPT_MODE, /* scan mode */ OPT_BIT_DEPTH, /* number of bits to encode a color */ OPT_RESOLUTION, /* number of pixels per inch */ OPT_HALFTONE_PATTERN, /* halftone pattern to use (see halftone_list) */ OPT_THRESHOLD, /* halftone threshold */ OPT_SHARPEN, /* create a sharper scan at the cost of scan time */ OPT_SHADING_ANALYSIS, /* do shading analysis before the scan */ OPT_FAST_INFRARED, /* scan infrared channel faster but less accurate */ OPT_ADVANCE_SLIDE, /* auto-advance slide after scan */ OPT_CALIBRATION_MODE, /* use auto-calibarion settings for scan */ /* ------------------------------------------- */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ /* ------------------------------------------- */ OPT_ENHANCEMENT_GROUP, OPT_CORRECT_SHADING, /* correct scanned data for lamp variations (shading) */ OPT_CORRECT_INFRARED, /* correct infrared for red crosstalk */ OPT_CLEAN_IMAGE, /* detect and remove dust and scratch artifacts */ OPT_GAIN_ADJUST, /* adjust gain (a simpler option than setting gain, exposure and offset directly) */ OPT_CROP_IMAGE, /* automatically crop image */ OPT_SMOOTH_IMAGE, /* smoothen image */ OPT_TRANSFORM_TO_SRGB, /* transform to approximate sRGB data */ OPT_INVERT_IMAGE, /* transform negative to positive */ /* ------------------------------------------- */ OPT_ADVANCED_GROUP, OPT_PREVIEW, /* scan a preview before the actual scan */ OPT_SAVE_SHADINGDATA, /* output shading data */ OPT_SAVE_CCDMASK, /* output CCD mask */ OPT_LIGHT, OPT_DOUBLE_TIMES, OPT_SET_EXPOSURE_R, /* exposure times for R */ OPT_SET_EXPOSURE_G, /* exposure times for G */ OPT_SET_EXPOSURE_B, /* exposure times for B */ OPT_SET_EXPOSURE_I, /* exposure times for I */ OPT_SET_GAIN_R, /* gain for R */ OPT_SET_GAIN_G, /* gain for G */ OPT_SET_GAIN_B, /* gain for B */ OPT_SET_GAIN_I, /* gain for I */ OPT_SET_OFFSET_R, /* offset for R */ OPT_SET_OFFSET_G, /* offset for G */ OPT_SET_OFFSET_B, /* offset for B */ OPT_SET_OFFSET_I, /* offset for I */ /* must come last: */ NUM_OPTIONS }; /* Forward declaration (see pieusb_scancmd.h) */ struct Pieusb_Shading_Parameters; /* Device characteristics of a Pieusb USB scanner */ struct Pieusb_Device_Definition { struct Pieusb_Device_Definition *next; SANE_Device sane; /* name = string like "libusb:001:006" == NO! this should be "CrystalScan 7200" or "ProScan 7200"... * vendor = "PIE/Pieusb" * model = "CrystalScan 7200" or "ProScan 7200" * type = "film scanner" */ /* char *devicename; => sane->name */ /* char *vendor; => sane->vendor */ /* char *product; => sane->model */ SANE_Word vendorId; SANE_Word productId; /* USB id's like 0x05e3 0x0145, see pieusb.conf */ SANE_String version; /* INQUIRY productRevision */ SANE_Byte model; /* INQUIRY model */ SANE_Byte flags; /* pieusb.conf flags */ /* Ranges for various quantities */ SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; SANE_Range exposure_range; /* Unit is a 8051 machine cycle, which is approximately 1 us. (Exactly: 12 cycles at 11.059 Mhz = 1.085 us.) */ SANE_Range dust_range; SANE_Range shadow_range; SANE_Range highlight_range; /* Enumerated ranges vor various quantities */ SANE_String scan_mode_list[7]; /* names of scan modes (see saneopts.h) */ SANE_String calibration_mode_list[6]; /* names of calibration modes */ SANE_String gain_adjust_list[10]; /* gain adjustment values */ SANE_Word bpp_list[5]; /* bit depths */ SANE_String halftone_list[17]; /* names of the halftone patterns from the scanner */ SANE_String speed_list[9]; /* names of available speeds */ SANE_String ir_sw_list[4]; SANE_String crop_sw_list[4]; SANE_Word grain_sw_list[6]; /* Maximum resolution values */ int maximum_resolution_x; /* maximum x-resolution */ int maximum_resolution_y; /* maximum y-resolution */ int maximum_resolution; /* Geometry */ double scan_bed_width; /* flatbed width in inches (horizontal) */ double scan_bed_height; /* flatbed height in inches (vertical) */ int slide_top_left_x; /* top-left location of slide w.r.t. scan bed */ int slide_top_left_y; /* top-left location of slide w.r.t. scan bed */ double slide_width; /* transparency width in inches */ double slide_height; /* transparency length in inches */ /* Integer and bit-encoded properties */ int halftone_patterns; /* number of halftones supported */ int color_filters; /* available colour filters: Infrared-0-0-OnePassColor-B-G-R-N */ int color_depths; /* available colour depths: 0-0-16-12-10-8-4-1 */ int color_formats; /* colour data format: 0-0-0-0-0-Index-Line-Pixel */ int image_formats; /* image data format: 0-0-0-0-OKLine-BlkOne-Motorola-Intel */ int scan_capabilities; /* additional scanner features, number of speeds: PowerSave-ExtCal-0-FastPreview-DisableCal-[CalSpeeds=3] */ int optional_devices; /* optional devices: MultiPageLoad-?-?-0-0-TransModule1-TransModule-AutoDocFeeder */ int enhancements; /* enhancements: unknown coding */ int gamma_bits; /* no of bits used for gamma table */ int fast_preview_resolution; /* fast preview resolution */ int minimum_highlight; /* min highlight % that can be used */ int maximum_shadow; /* max shadow % that can be used */ int calibration_equation; /* which calibration equation to use */ int minimum_exposure; /* min exposure */ int maximum_exposure; /* max exposure */ struct Pieusb_Shading_Parameters_Info shading_parameters[4]; /* array with shading data parameters */ int x0, y0, x1, y1; SANE_String production; SANE_String timestamp; SANE_String signature; }; typedef struct Pieusb_Device_Definition Pieusb_Device_Definition; /* -------------------------------------------------------------------------- * * CURRENTLY ACTIVE DEVICES * * --------------------------------------------------------------------------*/ /* This structure holds information about an instance of an active scanner */ struct Pieusb_Scanner { struct Pieusb_Scanner *next; struct Pieusb_Device_Definition *device; /* pointer to device definition */ int device_number; /* scanner device number (as determined by USB) */ /* SANE option descriptions and settings for this scanner instance */ SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; /* Scan state */ struct Pieusb_Scanner_State state; SANE_Int scanning; /* true if busy scanning */ SANE_Int cancel_request; /* if true, scanner should terminate a scan */ /* Scan settings */ struct Pieusb_Mode mode; struct Pieusb_Settings settings; struct Pieusb_Scan_Frame frame; SANE_Parameters scan_parameters; /* Shading data and CCD-mask */ #define PIEUSB_CCD_MASK_SIZE 0x1a1d /* pieusb 5340; */ /* cyberview: 6685 0x1a1d */ SANE_Byte *ccd_mask; /* malloc'ed in sane_open */ SANE_Int ccd_mask_size; SANE_Bool shading_data_present; /* don't correct shading if not present */ SANE_Int shading_mean[SHADING_PARAMETERS_INFO_COUNT]; /* mean shading value for each color (average all 45 lines) */ SANE_Int shading_max[SHADING_PARAMETERS_INFO_COUNT]; /* maximum shading value for each color (for all 45 lines) */ SANE_Int* shading_ref[SHADING_PARAMETERS_INFO_COUNT]; /* 4 arrays of shading references for each pixel on a line and for each color */ /* Calibration using preview */ SANE_Bool preview_done; SANE_Int preview_exposure[4]; /* exposure values used in preview */ SANE_Int preview_gain[4]; /* gain values used in preview */ SANE_Int preview_offset[4]; /* offset values used in preview */ SANE_Int preview_lower_bound[4]; /* lowest RGBI values in preview */ SANE_Int preview_upper_bound[4]; /* highest RGBI values in preview */ /* Post processing options */ /* SANE_Int processing; */ double *ln_lut; /* logarithmic lookup table */ /* Reading buffer */ struct Pieusb_Read_Buffer buffer; }; typedef struct Pieusb_Scanner Pieusb_Scanner; SANE_Status sanei_pieusb_parse_config_line(const char* config_line, SANE_Word* vendor_id, SANE_Word* product_id, SANE_Int* model_number, SANE_Int* flags); /* sub to sane_start() */ SANE_Status sanei_pieusb_post (Pieusb_Scanner *scanner, uint16_t **in_img, int planes); void sanei_pieusb_correct_shading(struct Pieusb_Scanner *scanner, struct Pieusb_Read_Buffer *buffer); SANE_Status sanei_pieusb_get_scan_data(Pieusb_Scanner * scanner, SANE_Int parameter_bytes); SANE_Status sanei_pieusb_get_parameters(Pieusb_Scanner * scanner, SANE_Int *parameter_bytes); SANE_Status sanei_pieusb_get_ccd_mask(Pieusb_Scanner * scanner); SANE_Status sanei_pieusb_get_shading_data(Pieusb_Scanner * scanner); SANE_Status sanei_pieusb_set_mode_from_options(Pieusb_Scanner * scanner); SANE_Status sanei_pieusb_set_gain_offset(Pieusb_Scanner * scanner, const char* calibration_mode); SANE_Status sanei_pieusb_set_frame_from_options(Pieusb_Scanner * scanner); void sanei_pieusb_print_options(struct Pieusb_Scanner *scanner); /* sub to sane_control_option() and sane_start() */ int sanei_pieusb_analyse_options(struct Pieusb_Scanner *scanner); SANE_Bool sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags); SANE_Status sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags); /* sub to sane_init() and sane_open() */ SANE_Status sanei_pieusb_find_device_callback (const char *devicename); /* sub to sane_open() */ SANE_Status sanei_pieusb_init_options (Pieusb_Scanner * scanner); /* sub to sane_start(), sane_read() and sane_close() */ SANE_Status sanei_pieusb_on_cancel (Pieusb_Scanner * scanner); SANE_Status sanei_pieusb_wait_ready(Pieusb_Scanner *scanner, SANE_Int device_number); SANE_Status sanei_pieusb_analyze_preview(Pieusb_Scanner * scanner); #endif /* PIEUSB_SPECIFIC_H */ sane-backends-1.0.27/backend/mustek_usb_high.h0000664000175000017500000004063512112021330016133 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Mustek. Originally maintained by Tom Wang Copyright (C) 2001, 2002 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek 1200UB and similar USB flatbed scanners. */ #ifndef mustek_usb_high_h #define mustek_usb_high_h #include "mustek_usb_mid.h" /* ---------------------------------- macros ------------------------------ */ #define I8O8RGB 0 #define I8O8MONO 1 #define I4O1MONO 2 /* ---------------------------------- types ------------------------------- */ struct Mustek_Usb_Device; typedef SANE_Status (*Powerdelay_Function) (ma1017 *, SANE_Byte); typedef SANE_Status (*Getline_Function) (struct Mustek_Usb_Device * dev, SANE_Byte *, SANE_Bool is_order_invert); typedef SANE_Status (*Backtrack_Function) (struct Mustek_Usb_Device * dev); typedef enum Colormode { RGB48 = 0, RGB42 = 1, RGB36 = 2, RGB30 = 3, RGB24 = 4, GRAY16 = 5, GRAY14 = 6, GRAY12 = 7, GRAY10 = 8, GRAY8 = 9, TEXT = 10, RGB48EXT = 11, RGB42EXT = 12, RGB36EXT = 13, RGB30EXT = 14, RGB24EXT = 15, GRAY16EXT = 16, GRAY14EXT = 17, GRAY12EXT = 18, GRAY10EXT = 19, GRAY8EXT = 20, TEXTEXT = 21 } Colormode; typedef enum Signal_State { SS_UNKNOWN = 0, SS_BRIGHTER = 1, SS_DARKER = 2, SS_EQUAL = 3 } Signal_State; typedef struct Calibrator { /* Calibration Data */ SANE_Bool is_prepared; SANE_Word *k_white; SANE_Word *k_dark; /* Working Buffer */ double *white_line; double *dark_line; SANE_Int *white_buffer; /* Necessary Parameters */ SANE_Word k_white_level; SANE_Word k_dark_level; SANE_Word major_average; SANE_Word minor_average; SANE_Word filter; SANE_Word white_needed; SANE_Word dark_needed; SANE_Word max_width; SANE_Word width; SANE_Word threshold; SANE_Word *gamma_table; SANE_Byte calibrator_type; } Calibrator; enum Mustek_Usb_Modes { MUSTEK_USB_MODE_LINEART = 0, MUSTEK_USB_MODE_GRAY, MUSTEK_USB_MODE_COLOR }; enum Mustek_Usb_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_RESOLUTION, OPT_PREVIEW, OPT_GEOMETRY_GROUP, /* 5 */ OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, /* 10 */ OPT_THRESHOLD, OPT_CUSTOM_GAMMA, OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, /* must come last: */ NUM_OPTIONS }; typedef struct Mustek_Usb_Device { struct Mustek_Usb_Device *next; SANE_String name; SANE_Device sane; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; /* max width & max height in 300 dpi */ SANE_Int max_width; SANE_Int max_height; ma1017 *chip; /* registers of the scanner controller chip */ Colormode scan_mode; SANE_Word x_dpi; SANE_Word y_dpi; SANE_Word x; SANE_Word y; SANE_Word width; SANE_Word height; SANE_Word bytes_per_row; SANE_Word bpp; SANE_Byte *scan_buffer; SANE_Byte *scan_buffer_start; size_t scan_buffer_len; SANE_Byte *temp_buffer; SANE_Byte *temp_buffer_start; size_t temp_buffer_len; SANE_Word line_switch; SANE_Word line_offset; SANE_Bool is_cis_detected; SANE_Word init_bytes_per_strip; SANE_Word adjust_length_300; SANE_Word adjust_length_600; SANE_Word init_min_expose_time; SANE_Word init_skips_per_row_300; SANE_Word init_skips_per_row_600; SANE_Word init_j_lines; SANE_Word init_k_lines; SANE_Word init_k_filter; SANE_Int init_k_loops; SANE_Word init_pixel_rate_lines; SANE_Word init_pixel_rate_filts; SANE_Word init_powerdelay_lines; SANE_Word init_home_lines; SANE_Word init_dark_lines; SANE_Word init_k_level; SANE_Byte init_max_power_delay; SANE_Byte init_min_power_delay; SANE_Byte init_adjust_way; double init_green_black_factor; double init_blue_black_factor; double init_red_black_factor; double init_gray_black_factor; double init_green_factor; double init_blue_factor; double init_red_factor; double init_gray_factor; SANE_Int init_red_rgb_600_pga; SANE_Int init_green_rgb_600_pga; SANE_Int init_blue_rgb_600_pga; SANE_Int init_mono_600_pga; SANE_Int init_red_rgb_300_pga; SANE_Int init_green_rgb_300_pga; SANE_Int init_blue_rgb_300_pga; SANE_Int init_mono_300_pga; SANE_Word init_expose_time; SANE_Byte init_red_rgb_600_power_delay; SANE_Byte init_green_rgb_600_power_delay; SANE_Byte init_blue_rgb_600_power_delay; SANE_Byte init_red_mono_600_power_delay; SANE_Byte init_green_mono_600_power_delay; SANE_Byte init_blue_mono_600_power_delay; SANE_Byte init_red_rgb_300_power_delay; SANE_Byte init_green_rgb_300_power_delay; SANE_Byte init_blue_rgb_300_power_delay; SANE_Byte init_red_mono_300_power_delay; SANE_Byte init_green_mono_300_power_delay; SANE_Byte init_blue_mono_300_power_delay; SANE_Byte init_threshold; SANE_Byte init_top_ref; SANE_Byte init_front_end; SANE_Byte init_red_offset; SANE_Byte init_green_offset; SANE_Byte init_blue_offset; SANE_Int init_rgb_24_back_track; SANE_Int init_mono_8_back_track; SANE_Bool is_open; SANE_Bool is_prepared; SANE_Word expose_time; SANE_Word dummy; SANE_Word bytes_per_strip; SANE_Byte *image_buffer; SANE_Byte *red; SANE_Byte *green; SANE_Byte *blue; Getline_Function get_line; Backtrack_Function backtrack; SANE_Bool is_adjusted_rgb_600_power_delay; SANE_Bool is_adjusted_mono_600_power_delay; SANE_Bool is_adjusted_rgb_300_power_delay; SANE_Bool is_adjusted_mono_300_power_delay; SANE_Bool is_evaluate_pixel_rate; SANE_Int red_rgb_600_pga; SANE_Int green_rgb_600_pga; SANE_Int blue_rgb_600_pga; SANE_Int mono_600_pga; SANE_Byte red_rgb_600_power_delay; SANE_Byte green_rgb_600_power_delay; SANE_Byte blue_rgb_600_power_delay; SANE_Byte red_mono_600_power_delay; SANE_Byte green_mono_600_power_delay; SANE_Byte blue_mono_600_power_delay; SANE_Int red_rgb_300_pga; SANE_Int green_rgb_300_pga; SANE_Int blue_rgb_300_pga; SANE_Int mono_300_pga; SANE_Byte red_rgb_300_power_delay; SANE_Byte green_rgb_300_power_delay; SANE_Byte blue_rgb_300_power_delay; SANE_Byte red_mono_300_power_delay; SANE_Byte green_mono_300_power_delay; SANE_Byte blue_mono_300_power_delay; SANE_Word pixel_rate; SANE_Byte threshold; SANE_Word *gamma_table; SANE_Word skips_per_row; /* CCD */ SANE_Bool is_adjusted_mono_600_offset; SANE_Bool is_adjusted_mono_600_exposure; SANE_Word mono_600_exposure; Calibrator *red_calibrator; Calibrator *green_calibrator; Calibrator *blue_calibrator; Calibrator *mono_calibrator; SANE_Char device_name[256]; SANE_Bool is_sensor_detected; } Mustek_Usb_Device; typedef struct Mustek_Usb_Scanner { /* all the state needed to define a scan request: */ struct Mustek_Usb_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Int channels; /* scan window in inches: top left x+y and width+height */ double tl_x; double tl_y; double width; double height; /* scan window in dots (at current resolution): top left x+y and width+height */ SANE_Int tl_x_dots; SANE_Int tl_y_dots; SANE_Int width_dots; SANE_Int height_dots; SANE_Word bpp; SANE_Bool scanning; SANE_Parameters params; SANE_Word read_rows; SANE_Word red_gamma_table[256]; SANE_Word green_gamma_table[256]; SANE_Word blue_gamma_table[256]; SANE_Word gray_gamma_table[256]; SANE_Word linear_gamma_table[256]; SANE_Word *red_table; SANE_Word *green_table; SANE_Word *blue_table; SANE_Word *gray_table; SANE_Word total_bytes; SANE_Word total_lines; /* scanner dependent/low-level state: */ Mustek_Usb_Device *hw; } Mustek_Usb_Scanner; /* ------------------- calibration function declarations ------------------ */ static SANE_Status usb_high_cal_init (Calibrator * cal, SANE_Byte type, SANE_Word target_white, SANE_Word target_dark); static SANE_Status usb_high_cal_exit (Calibrator * cal); static SANE_Status usb_high_cal_embed_gamma (Calibrator * cal, SANE_Word * gamma_table); static SANE_Status usb_high_cal_prepare (Calibrator * cal, SANE_Word max_width); static SANE_Status usb_high_cal_setup (Calibrator * cal, SANE_Word major_average, SANE_Word minor_average, SANE_Word filter, SANE_Word width, SANE_Word * white_needed, SANE_Word * dark_needed); static SANE_Status usb_high_cal_evaluate_white (Calibrator * cal, double factor); static SANE_Status usb_high_cal_evaluate_dark (Calibrator * cal, double factor); static SANE_Status usb_high_cal_evaluate_calibrator (Calibrator * cal); static SANE_Status usb_high_cal_fill_in_white (Calibrator * cal, SANE_Word major, SANE_Word minor, void *white_pattern); static SANE_Status usb_high_cal_fill_in_dark (Calibrator * cal, SANE_Word major, SANE_Word minor, void *dark_pattern); static SANE_Status usb_high_cal_calibrate (Calibrator * cal, void *src, void *target); static SANE_Status usb_high_cal_i8o8_fill_in_white (Calibrator * cal, SANE_Word major, SANE_Word minor, void *white_pattern); static SANE_Status usb_high_cal_i8o8_fill_in_dark (Calibrator * cal, SANE_Word major, SANE_Word minor, void *dark_pattern); static SANE_Status usb_high_cal_i8o8_mono_calibrate (Calibrator * cal, void *src, void *target); static SANE_Status usb_high_cal_i8o8_rgb_calibrate (Calibrator * cal, void *src, void *target); static SANE_Status usb_high_cal_i4o1_fill_in_white (Calibrator * cal, SANE_Word major, SANE_Word minor, void *white_pattern); static SANE_Status usb_high_cal_i4o1_fill_in_dark (Calibrator * cal, SANE_Word major, SANE_Word minor, void *dark_pattern); static SANE_Status usb_high_cal_i4o1_calibrate (Calibrator * cal, void *src, void *target); /* -------------------- scanning function declarations -------------------- */ static SANE_Status usb_high_scan_init (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_exit (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_prepare (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_clearup (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_turn_power (Mustek_Usb_Device * dev, SANE_Bool is_on); static SANE_Status usb_high_scan_back_home (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_set_threshold (Mustek_Usb_Device * dev, SANE_Byte threshold); static SANE_Status usb_high_scan_embed_gamma (Mustek_Usb_Device * dev, SANE_Word * gamma_table); static SANE_Status usb_high_scan_reset (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_suggest_parameters (Mustek_Usb_Device * dev, SANE_Word dpi, SANE_Word x, SANE_Word y, SANE_Word width, SANE_Word height, Colormode color_mode); static SANE_Status usb_high_scan_detect_sensor (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_setup_scan (Mustek_Usb_Device * dev, Colormode color_mode, SANE_Word x_dpi, SANE_Word y_dpi, SANE_Bool is_invert, SANE_Word x, SANE_Word y, SANE_Word width); static SANE_Status usb_high_scan_get_rows (Mustek_Usb_Device * dev, SANE_Byte * block, SANE_Word rows, SANE_Bool is_order_invert); static SANE_Status usb_high_scan_stop_scan (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_step_forward (Mustek_Usb_Device * dev, SANE_Int step_count); static SANE_Status usb_high_scan_safe_forward (Mustek_Usb_Device * dev, SANE_Int step_count); static SANE_Status usb_high_scan_init_asic (Mustek_Usb_Device * dev, Sensor_Type sensor); static SANE_Status usb_high_scan_wait_carriage_home (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_hardware_calibration (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_line_calibration (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_prepare_scan (Mustek_Usb_Device * dev); static SANE_Word usb_high_scan_calculate_max_rgb_600_expose (Mustek_Usb_Device * dev, SANE_Byte * ideal_red_pd, SANE_Byte * ideal_green_pd, SANE_Byte * ideal_blue_pd); static SANE_Word usb_high_scan_calculate_max_mono_600_expose (Mustek_Usb_Device * dev, SANE_Byte * ideal_red_pd, SANE_Byte * ideal_green_pd, SANE_Byte * ideal_blue_pd); static SANE_Status usb_high_scan_prepare_rgb_signal_600_dpi (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_prepare_mono_signal_600_dpi (Mustek_Usb_Device * dev); static SANE_Word usb_high_scan_calculate_max_rgb_300_expose (Mustek_Usb_Device * dev, SANE_Byte * ideal_red_pd, SANE_Byte * ideal_green_pd, SANE_Byte * ideal_blue_pd); static SANE_Word usb_high_scan_calculate_max_mono_300_expose (Mustek_Usb_Device * dev, SANE_Byte * ideal_red_pd, SANE_Byte * ideal_green_pd, SANE_Byte * ideal_blue_pd); static SANE_Status usb_high_scan_prepare_rgb_signal_300_dpi (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_prepare_mono_signal_300_dpi (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_evaluate_max_level (Mustek_Usb_Device * dev, SANE_Word sample_lines, SANE_Int sample_length, SANE_Byte * ret_max_level); static SANE_Status usb_high_scan_bssc_power_delay (Mustek_Usb_Device * dev, Powerdelay_Function set_power_delay, Signal_State * signal_state, SANE_Byte * target, SANE_Byte max, SANE_Byte min, SANE_Byte threshold, SANE_Int length); static SANE_Status usb_high_scan_adjust_rgb_600_power_delay (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_adjust_mono_600_power_delay (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_adjust_mono_600_exposure (Mustek_Usb_Device * dev); #if 0 /* CCD */ static SANE_Status usb_high_scan_adjust_mono_600_offset (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_adjust_mono_600_pga (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_adjust_mono_600_skips_per_row (Mustek_Usb_Device * dev); #endif static SANE_Status usb_high_scan_adjust_rgb_300_power_delay (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_adjust_mono_300_power_delay (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_evaluate_pixel_rate (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_calibration_rgb_24 (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_calibration_mono_8 (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_prepare_rgb_24 (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_prepare_mono_8 (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_get_rgb_24_bit_line (Mustek_Usb_Device * dev, SANE_Byte * line, SANE_Bool is_order_invert); static SANE_Status usb_high_scan_get_mono_8_bit_line (Mustek_Usb_Device * dev, SANE_Byte * line, SANE_Bool is_order_invert); static SANE_Status usb_high_scan_backtrack_rgb_24 (Mustek_Usb_Device * dev); static SANE_Status usb_high_scan_backtrack_mono_8 (Mustek_Usb_Device * dev); #endif /* mustek_usb_high_h */ sane-backends-1.0.27/backend/sane_strstatus.c0000664000175000017500000000670012112021330016023 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang and Andreas Beck This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements the backend-independent parts of SANE. */ #include #include "../include/sane/sane.h" #ifndef SANE_I18N #define SANE_I18N(text) text #endif SANE_String_Const sane_strstatus (SANE_Status status) { static char buf[80]; switch (status) { case SANE_STATUS_GOOD: return SANE_I18N("Success"); case SANE_STATUS_UNSUPPORTED: return SANE_I18N("Operation not supported"); case SANE_STATUS_CANCELLED: return SANE_I18N("Operation was cancelled"); case SANE_STATUS_DEVICE_BUSY: return SANE_I18N("Device busy"); case SANE_STATUS_INVAL: return SANE_I18N("Invalid argument"); case SANE_STATUS_EOF: return SANE_I18N("End of file reached"); case SANE_STATUS_JAMMED: return SANE_I18N("Document feeder jammed"); case SANE_STATUS_NO_DOCS: return SANE_I18N("Document feeder out of documents"); case SANE_STATUS_COVER_OPEN: return SANE_I18N("Scanner cover is open"); case SANE_STATUS_IO_ERROR: return SANE_I18N("Error during device I/O"); case SANE_STATUS_NO_MEM: return SANE_I18N("Out of memory"); case SANE_STATUS_ACCESS_DENIED: return SANE_I18N("Access to resource has been denied"); #ifdef SANE_STATUS_WARMING_UP case SANE_STATUS_WARMING_UP: return SANE_I18N("Lamp not ready, please retry"); #endif #ifdef SANE_STATUS_HW_LOCKED case SANE_STATUS_HW_LOCKED: return SANE_I18N("Scanner mechanism locked for transport"); #endif default: /* non-reentrant, but better than nothing */ sprintf (buf, "Unknown SANE status code %d", status); return buf; } } sane-backends-1.0.27/backend/ibm-scsi.c0000664000175000017500000002745312112021330014457 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* */ #include /* SCSI commands that the Ibm scanners understand: */ #define IBM_SCSI_TEST_UNIT_READY 0x00 #define IBM_SCSI_SET_WINDOW 0x24 #define IBM_SCSI_GET_WINDOW 0x25 #define IBM_SCSI_READ_SCANNED_DATA 0x28 #define IBM_SCSI_INQUIRY 0x12 #define IBM_SCSI_MODE_SELECT 0x15 #define IBM_SCSI_START_SCAN 0x1b #define IBM_SCSI_MODE_SENSE 0x1a #define IBM_SCSI_GET_BUFFER_STATUS 0x34 #define IBM_SCSI_OBJECT_POSITION 0x31 /* How long do we wait for scanner to have data for us */ #define MAX_WAITING_TIME 15 /* for object_position command */ #define OBJECT_POSITION_UNLOAD 0 #define OBJECT_POSITION_LOAD 1 struct scsi_window_cmd { SANE_Byte opcode; SANE_Byte byte2; SANE_Byte reserved[4]; SANE_Byte len[3]; SANE_Byte control; }; struct scsi_mode_select_cmd { SANE_Byte opcode; SANE_Byte byte2; #define SMS_SP 0x01 #define SMS_PF 0x10 SANE_Byte page_code; /* for mode_sense, reserved for mode_select */ SANE_Byte unused[1]; SANE_Byte len; SANE_Byte control; }; struct scsi_mode_header { SANE_Byte data_length; /* Sense data length */ SANE_Byte medium_type; SANE_Byte dev_spec; SANE_Byte blk_desc_len; }; /* next struct introduced by mf */ struct scsi_object_position_cmd { SANE_Byte opcode; SANE_Byte position_func; SANE_Byte count[3]; SANE_Byte res[3]; SANE_Byte control; SANE_Byte res2; }; struct scsi_get_buffer_status_cmd { SANE_Byte opcode; SANE_Byte byte2; SANE_Byte res[5]; SANE_Byte len[2]; SANE_Byte control; }; struct scsi_status_desc { SANE_Byte window_id; SANE_Byte byte2; SANE_Byte available[3]; SANE_Byte filled[3]; }; struct scsi_status_data { SANE_Byte len[3]; SANE_Byte byte4; struct scsi_status_desc desc; }; struct scsi_start_scan_cmd { SANE_Byte opcode; SANE_Byte byte2; SANE_Byte unused[2]; SANE_Byte len; SANE_Byte control; }; struct scsi_read_scanner_cmd { SANE_Byte opcode; SANE_Byte byte2; SANE_Byte data_type; SANE_Byte byte3; SANE_Byte data_type_qualifier[2]; SANE_Byte len[3]; SANE_Byte control; }; static SANE_Status test_unit_ready (int fd) { static SANE_Byte cmd[6]; SANE_Status status; DBG (11, ">> test_unit_ready\n"); cmd[0] = IBM_SCSI_TEST_UNIT_READY; memset (cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, "<< test_unit_ready\n"); return (status); } static SANE_Status inquiry (int fd, void *buf, size_t * buf_size) { static SANE_Byte cmd[6]; SANE_Status status; DBG (11, ">> inquiry\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = IBM_SCSI_INQUIRY; cmd[4] = *buf_size; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); DBG (11, "<< inquiry\n"); return (status); } static SANE_Status mode_select (int fd, struct mode_pages *mp) { static struct { struct scsi_mode_select_cmd cmd; struct scsi_mode_header smh; struct mode_pages mp; } select_cmd; SANE_Status status; DBG (11, ">> mode_select\n"); memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd.opcode = IBM_SCSI_MODE_SELECT; select_cmd.cmd.byte2 |= SMS_PF; select_cmd.cmd.len = sizeof(select_cmd.smh) + sizeof(select_cmd.mp); /* next line by mf */ /* select_cmd.cmd.page_code= 20; */ memcpy (&select_cmd.mp, mp, sizeof(*mp)); status = sanei_scsi_cmd (fd, &select_cmd, sizeof (select_cmd), 0, 0); DBG (11, "<< mode_select\n"); return (status); } #if 0 static SANE_Status mode_sense (int fd, struct mode_pages *mp, SANE_Byte page_code) { static struct scsi_mode_select_cmd cmd; /* no type, we can reuse it for sensing */ static struct { struct scsi_mode_header smh; struct mode_pages mp; } select_data; static size_t select_size = sizeof(select_data); SANE_Status status; DBG (11, ">> mode_sense\n"); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = IBM_SCSI_MODE_SENSE; cmd.page_code = page_code; cmd.len = sizeof(select_data); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &select_data, &select_size); memcpy (mp, &select_data.mp, sizeof(*mp)); DBG (11, "<< mode_sense\n"); return (status); } #endif static SANE_Status trigger_scan (int fd) { static struct scsi_start_scan_cmd cmd; static char window_id_list[1] = { '\0' }; /* scan start data out */ static size_t wl_size = 1; SANE_Status status; DBG (11, ">> trigger scan\n"); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = IBM_SCSI_START_SCAN; cmd.len = wl_size; /* next line by mf */ /* cmd.unused[0] = 1; */ if (wl_size) status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &window_id_list, &wl_size); else status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), 0, 0); DBG (11, "<< trigger scan\n"); return (status); } static SANE_Status set_window (int fd, struct ibm_window_data *iwd) { static struct { struct scsi_window_cmd cmd; struct ibm_window_data iwd; } win; SANE_Status status; DBG (11, ">> set_window\n"); memset (&win, 0, sizeof (win)); win.cmd.opcode = IBM_SCSI_SET_WINDOW; _lto3b(sizeof(*iwd), win.cmd.len); memcpy (&win.iwd, iwd, sizeof(*iwd)); status = sanei_scsi_cmd (fd, &win, sizeof (win), 0, 0); DBG (11, "<< set_window\n"); return (status); } static SANE_Status get_window (int fd, struct ibm_window_data *iwd) { static struct scsi_window_cmd cmd; static size_t iwd_size; SANE_Status status; iwd_size = sizeof(*iwd); DBG (11, ">> get_window datalen = %lu\n", (unsigned long) iwd_size); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = IBM_SCSI_GET_WINDOW; #if 1 /* it was if 0 */ cmd.byte2 |= (SANE_Byte)0x01; /* set Single bit to get one window desc. */ #endif _lto3b(iwd_size, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), iwd, &iwd_size); DBG (11, "<< get_window, datalen = %lu\n", (unsigned long) iwd_size); return (status); } static SANE_Status read_data (int fd, void *buf, size_t * buf_size) { static struct scsi_read_scanner_cmd cmd; SANE_Status status; DBG (11, ">> read_data %lu\n", (unsigned long) *buf_size); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = IBM_SCSI_READ_SCANNED_DATA; _lto3b(*buf_size, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), buf, buf_size); DBG (11, "<< read_data %lu\n", (unsigned long) *buf_size); return (status); } static SANE_Status object_position (int fd, int load) { static struct scsi_object_position_cmd cmd; SANE_Status status; DBG (11, ">> object_position\n"); #if 0 /* At least the Ricoh 420 doesn't like that command */ DBG (11, "object_position: ignored\n"); return SANE_STATUS_GOOD; #endif memset (&cmd, 0, sizeof (cmd)); cmd.opcode = IBM_SCSI_OBJECT_POSITION; if (load) cmd.position_func = OBJECT_POSITION_LOAD; else cmd.position_func = OBJECT_POSITION_UNLOAD; _lto3b(1, cmd.count); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), 0, 0); DBG (11, "<< object_position\n"); return (status); } static SANE_Status get_data_status (int fd, struct scsi_status_desc *dbs) { static struct scsi_get_buffer_status_cmd cmd; static struct scsi_status_data ssd; size_t ssd_size = sizeof(ssd); SANE_Status status; DBG (11, ">> get_data_status %lu\n", (unsigned long) ssd_size); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = IBM_SCSI_GET_BUFFER_STATUS; _lto2b(ssd_size, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &ssd, &ssd_size); memcpy (dbs, &ssd.desc, sizeof(*dbs)); if (status == SANE_STATUS_GOOD && ((unsigned int) _3btol(ssd.len) <= sizeof(*dbs) || _3btol(ssd.desc.filled) == 0)) { DBG (11, "get_data_status: busy\n"); status = SANE_STATUS_DEVICE_BUSY; } DBG (11, "<< get_data_status %lu\n", (unsigned long) ssd_size); return (status); } #if 0 static SANE_Status ibm_wait_ready_tur (int fd) { struct timeval now, start; SANE_Status status; gettimeofday (&start, 0); while (1) { DBG(3, "scsi_wait_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG(1, "scsi_wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG(1, "ibm_wait_ready: timed out after %lu seconds\n", (u_long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; } } return SANE_STATUS_INVAL; } #endif static SANE_Status ibm_wait_ready (Ibm_Scanner * s) { struct scsi_status_desc dbs; time_t now, start; SANE_Status status; start = time(NULL); while (1) { status = get_data_status (s->fd, &dbs); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG(1, "scsi_wait_ready: get datat status failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: now = time(NULL); if (now - start >= MAX_WAITING_TIME) { DBG(1, "ibm_wait_ready: timed out after %lu seconds\n", (u_long) (now - start)); return SANE_STATUS_INVAL; } break; case SANE_STATUS_GOOD: DBG(11, "ibm_wait_ready: %d bytes ready\n", _3btol(dbs.filled)); return status; break; } usleep (1000000); /* retry after 100ms */ } return SANE_STATUS_INVAL; } sane-backends-1.0.27/backend/hs2p-scsi.c0000664000175000017500000021106213106201017014561 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Jeremy Johnson This file is part of a SANE backend for Ricoh IS450 and IS420 family of HS2P Scanners using the SCSI controller. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include #include "hs2p.h" static SANE_String_Const print_devtype (SANE_Byte devtype) { int i = devtype; static SANE_String devtypes[] = { "disk", "tape", "printer", "processor", "CD-writer", "CD-drive", "scanner", "optical-drive", "jukebox", "communicator" }; return (i >= 0 && i < NELEMS (devtypes)) ? devtypes[i] : "unknown-device"; } static void print_bytes (const void *buf, size_t bufsize) { const SANE_Byte *bp; unsigned i; for (i = 0, bp = buf; i < bufsize; i++, bp++) DBG (DBG_error, "%3d: 0x%02x %d\n", i, *bp, *bp); } static void ScannerDump (HS2P_Scanner * s) { int i; HS2P_Info *info; SANE_Device *sdev; info = &s->hw->info; sdev = &s->hw->sane; DBG (DBG_info, "\n\n"); DBG (DBG_info, ">> ScannerDump:\n"); DBG (DBG_info, "SANE Device: '%s' Vendor: '%s' Model: '%s' Type: '%s'\n", sdev->name, sdev->vendor, sdev->model, sdev->type); DBG (DBG_info, "Type: '%s' Vendor: '%s' Product: '%s' Revision: '%s'\n", print_devtype (info->devtype), info->vendor, info->product, info->revision); DBG (DBG_info, "Automatic Document Feeder: %s%s%s%s\n", info->hasADF ? "Installed " : "Not Installed ", info->hasSimplex ? "simplex" : "", info->hasDuplex ? "duplex" : "", info->hasARDF ? "reverse double-sided" : ""); DBG (DBG_info, "Endorser :%s\n", info->hasEndorser ? " " : " "); DBG (DBG_info, "Image Processing Unit:%s\n", info->hasIPU ? " " : " "); DBG (DBG_info, "Extended Board :%s\n", info->hasXBD ? " " : " "); DBG (DBG_info, "\n"); DBG (DBG_info, "Image Composition Support\n"); DBG (DBG_info, "Line Art (B/W) Support : %s\n", info->supports_lineart ? "Yes" : "No"); DBG (DBG_info, "Dithering (Halftone) Support: %s\n", info->supports_dithering ? "Yes" : "No"); DBG (DBG_info, "Error Diffusion Support : %s\n", info->supports_errordiffusion ? "Yes" : "No"); DBG (DBG_info, "Color Support : %s\n", info->supports_color ? "Yes" : "No"); DBG (DBG_info, "4 Bit Gray Support : %s\n", info->supports_4bitgray ? "Yes" : "No"); DBG (DBG_info, "5-8 Bit Gray Support : %s\n", info->supports_8bitgray ? "Yes" : "No"); DBG (DBG_info, "Image Data processing:%s%s%s%s%s%s\n", info->supports_whiteframing ? " " : "", info->supports_blackframing ? " " : "", info->supports_edgeextraction ? " " : "", info->supports_noiseremoval ? " " : "", info->supports_smoothing ? " " : "", info->supports_linebolding ? " " : ""); DBG (DBG_info, "Image Compression:%s%s%s%s\n", info->supports_MH ? " " : "", info->supports_MR ? " " : "", info->supports_MMR ? " " : "", info->supports_MHB ? " " : ""); DBG (DBG_info, "Marker Recognition: %s\n", info->supports_markerrecognition ? "" : ""); DBG (DBG_info, "Size Recognition : %s\n", info->supports_sizerecognition ? "" : ""); DBG (DBG_info, "X Maximum Output Pixels = %d\n", info->xmaxoutputpixels); /* DBG (DBG_info, "Optional Features:%s%s%s%s\n", info->canBorderRecog ? " " : "", info->canBarCode ? " " : "", info->canIcon ? " " : "", info->canSection ? "
" : ""); */ DBG (DBG_info, "Max bytes per scan-line: %d (%d pixels)\n", info->xmaxoutputpixels / 8, info->xmaxoutputpixels); DBG (DBG_info, "Basic resolution (X/Y) : %d/%d\n", info->resBasicX, info->resBasicY); DBG (DBG_info, "Maximum resolution (X/Y) : %d/%d\n", info->resMaxX, info->resMaxY); DBG (DBG_info, "Minimum resolution (X/Y) : %d/%d\n", info->resMinX, info->resMinY); DBG (DBG_info, "Standard Resolutions:\n"); for (i = 1; i <= info->resStdList[0]; i++) DBG (DBG_info, " %d\n", info->resStdList[i]); DBG (DBG_info, "Window Width/Height (in basic res) %d/%d (%.2f/%.2f inches)\n", info->winWidth, info->winHeight, (info->resBasicX != 0) ? ((float) info->winWidth) / info->resBasicX : 0.0, (info->resBasicY) ? ((float) info->winHeight) / info->resBasicY : 0.0); /* DBG (DBG_info, "Summary:%s%s%s\n", info->canDuplex ? "Duplex Scanner" : "Simplex Scanner", info->canACE ? " (ACE capable)" : "", info->canCheckADF ? " (ADF Paper Sensor capable)" : ""); */ DBG (DBG_info, "Buffer Full Ratio = %#02x\n", info->cxn.buffer_full_ratio); DBG (DBG_info, "Buffer Empty Ratio = %#02x\n", info->cxn.buffer_empty_ratio); DBG (DBG_info, "Bus Inactive Limit = %#02x\n", info->cxn.bus_inactive_limit[0] << 8 | info->cxn. bus_inactive_limit[1]); DBG (DBG_info, "Disconnect Time Limit = %#04x\n", info->cxn.disconnect_time_limit[0] << 8 | info->cxn. disconnect_time_limit[1]); DBG (DBG_info, "Connect Time Limit = %#02x\n", info->cxn.connect_time_limit[0] << 8 | info->cxn. connect_time_limit[1]); DBG (DBG_info, "Maximum Burst Size = %#04x\n", info->cxn.maximum_burst_size[0] << 8 | info->cxn. maximum_burst_size[1]); DBG (DBG_info, "DTDC = %#02x\n", info->cxn.dtdc & 0x03); DBG (DBG_info, "White Balance is %s\n", info->white_balance == 1 ? "Absolute" : "Relative"); DBG (DBG_info, "Medium Wait Timer is \n"); /* get_medium_wait_timer(fd) */ DBG (DBG_info, "Scan Wait Mode is %s\n", info->scan_wait_mode == 0 ? "OFF" : "ON"); DBG (DBG_info, "Service Mode is in Select %s Mode\n", info->service_mode == 0 ? "Self-Diagnostics" : "Optical Adjustment"); sprintf (info->inquiry_data, "Vendor: %s Product: %s Rev: %s %s%s\n", info->vendor, info->product, info->revision, info->hasADF && info->hasDuplex ? "Duplex Scanner" : "", info->hasADF && info->hasSimplex ? "Simplex Scanner" : ""); DBG (DBG_info, "duplex_default=%d\n", info->default_duplex); /* DBG (DBG_info, "autoborder_default=%d\n", info->autoborder_default); DBG (DBG_info, "batch_default=%d\n", info->batch_default); DBG (DBG_info, "deskew_default=%d\n", info->deskew_default); DBG (DBG_info, "check_adf_default=%d\n", info->check_adf_default); DBG (DBG_info, "timeout_adf_default=%d\n", info->timeout_adf_default); DBG (DBG_info, "timeout_manual_default=%d\n", info->timeout_manual_default); DBG (DBG_info, "control_panel_default=%d\n", info->control_panel_default); */ DBG (DBG_info, "bmu = %d\n", info->bmu); DBG (DBG_info, "mud = %d\n", info->mud); DBG (DBG_info, "white balance = %#0x\n", info->white_balance); DBG (DBG_info, "adf control = %#0x\n", info->adf_control); DBG (DBG_info, "adf mode control = %#0x\n", info->adf_mode_control); DBG (DBG_info, "endorser control = %#0x\n", info->endorser_control); DBG (DBG_info, "endorser string = %s\n", info->endorser_string); DBG (DBG_info, "scan wait mode = %#0x\n", info->scan_wait_mode); DBG (DBG_info, "service mode = %#0x\n", info->service_mode); DBG (DBG_info, "BasicXRes = %d\n", info->resBasicX); DBG (DBG_info, "BasicYRes = %d\n", info->resBasicY); DBG (DBG_info, "XResStep = %d\n", info->resXstep); DBG (DBG_info, "YResStep = %d\n", info->resYstep); DBG (DBG_info, "MaxXres = %d\n", info->resMaxX); DBG (DBG_info, "MaxYres = %d\n", info->resMaxY); DBG (DBG_info, "MinXres = %d\n", info->resMinX); DBG (DBG_info, "MinYres = %d\n", info->resMinY); DBG (DBG_info, "Width = %d\n", info->winWidth); DBG (DBG_info, "Height = %d\n", info->winHeight); DBG (DBG_info, "<< ScannerDump\n"); } static void print_vpd_info (struct inquiry_vpd_data *vbuf) { DBG (DBG_info, "VPD IDENTIFIER C0H\n"); DBG (DBG_info, "[00] Peripheral %#02x\n", vbuf->devtype); DBG (DBG_info, "[01] Page Code %#02x\n", vbuf->pagecode); DBG (DBG_info, "[02] reserved %#02x\n", vbuf->byte2); DBG (DBG_info, "[03] Page Length %#02x\n", vbuf->pagelength); DBG (DBG_info, "[04] ADF ID %#02x\n", vbuf->adf_id); DBG (DBG_info, "[05] Endorser ID %#02x\n", vbuf->end_id); DBG (DBG_info, "[06] Image Processing Unit %#02x\n", vbuf->ipu_id); DBG (DBG_info, "[07] Image Composition %#02x\n", vbuf->imagecomposition); DBG (DBG_info, "[08] Image Data Processing %lu\n", _2btol (&vbuf->imagedataprocessing[0])); DBG (DBG_info, "[10] Compression %#02x\n", vbuf->compression); DBG (DBG_info, "[11] Marker Recognition %#02x\n", vbuf->markerrecognition); DBG (DBG_info, "[12] Size Recognition %#02x\n", vbuf->sizerecognition); DBG (DBG_info, "[13] reserved %#02x\n", vbuf->byte13); DBG (DBG_info, "[14] X Maximum Output Pixel %lu\n", _2btol (&vbuf->xmaxoutputpixels[0])); } static void print_jis_info (struct inquiry_jis_data *jbuf) { DBG (DBG_info, "JIS IDENTIFIER F0H\n"); DBG (DBG_info, "[00] devtype %#02x\n", jbuf->devtype); DBG (DBG_info, "[01] Page Code %#02x\n", jbuf->pagecode); DBG (DBG_info, "[02] JIS Ver %#02x\n", jbuf->jisversion); DBG (DBG_info, "[03] reserved1 %#02x\n", jbuf->reserved1); DBG (DBG_info, "[04] Page Len %#02x\n", jbuf->alloclen); DBG (DBG_info, "[05] BasicXRes %lu\n", _2btol (&jbuf->BasicRes.x[0])); DBG (DBG_info, "[07] BasicYRes %lu\n", _2btol (&jbuf->BasicRes.y[0])); DBG (DBG_info, "[09] Resolution step %#02x\n", jbuf->resolutionstep); DBG (DBG_info, "[10] MaxXRes %lu\n", _2btol (&jbuf->MaxRes.x[0])); DBG (DBG_info, "[12] MaxYRes %lu\n", _2btol (&jbuf->MaxRes.y[0])); DBG (DBG_info, "[14] MinXRes %lu\n", _2btol (&jbuf->MinRes.x[0])); DBG (DBG_info, "[16] MinYRes %lu\n", _2btol (&jbuf->MinRes.y[0])); DBG (DBG_info, "[18] Std Res %#0x\n", (jbuf->standardres[0] << 8) | jbuf->standardres[1]); DBG (DBG_info, "[20] Win Width %lu\n", _4btol (&jbuf->Window.width[0])); /* Manual says 4787/12B3H pixels @400dpi = 12in */ DBG (DBG_info, "[24] Win Len %lu\n", _4btol (&jbuf->Window.length[0])); /* Manual says 6803/1A93H pixels @400dpi = 17in) */ DBG (DBG_info, "[28] function %#02x\n", jbuf->functions); DBG (DBG_info, "[29] reserved %#02x\n", jbuf->reserved2); } /* 1-3-1 TEST UNIT READY Byte0: | 0x00 | Byte1: | 7-5 Logical Unit Number | Reserved | Byte2: | Reserved | Byte3: | Reserved | Byte4: | Reserved | Byte5: | 7-6 Vendor Unique | 5-2 Reserved | 1 Flag | 0 Link | */ static SANE_Status test_unit_ready (int fd) { static SANE_Byte cmd[6]; SANE_Status status; DBG (DBG_proc, ">> test_unit_ready\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = HS2P_SCSI_TEST_UNIT_READY; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (DBG_proc, "<< test_unit_ready\n"); return (status); } /* 1-3-2 REQUEST SENSE Byte0: | 0x00 | Byte1: | 7-5 Logical Unit Number | Reserved | Byte2: | Reserved | Byte3: | Reserved | Byte4: | Allocation Length | Byte5: | 7-6 Vendor Unique | 5-2 Reserved | 1 Flag | 0 Link | */ #if 0 static SANE_Status get_sense_data (int fd, SENSE_DATA * sense_data) { SANE_Status status; DBG (DBG_sane_proc, ">> get_sense_data\n"); static SANE_Byte cmd[6]; size_t len; len = sizeof (*sense_data); memset (sense_data, 0, len); memset (cmd, 0, sizeof (cmd)); cmd[0] = HS2P_SCSI_REQUEST_SENSE; cmd[4] = len; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), sense_data, &len); DBG (DBG_proc, "<< get_sense_data\n"); return (status); } #endif static SANE_Status print_sense_data (int dbg_level, SENSE_DATA * data) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte *bp, *end; SANE_Int i; DBG (DBG_sane_proc, ">> print_sense_data\n"); bp = (SANE_Byte *) data; end = bp + (SANE_Byte) sizeof (SENSE_DATA); for (i = 0; bp < end; bp++, i++) { DBG (dbg_level, "Byte #%2d is %3d, 0x%02x\n", i, *bp, *bp); } DBG (dbg_level, "Valid=%1d, ErrorCode=%#x\n", (data->error_code & 0x80) >> 7, data->error_code & 0x7F); DBG (dbg_level, "Segment number = %d\n", data->segment_number); DBG (dbg_level, "F-mark=%1d, EOM=%1d, ILI=%1d, Reserved=%1d, SenseKey=%#x\n", (data->sense_key & 0x80) >> 7, (data->sense_key & 0x40) >> 6, (data->sense_key & 0x20) >> 5, (data->sense_key & 0x10) >> 4, (data->sense_key & 0x0F)); DBG (dbg_level, "Information Byte = %lu\n", _4btol (data->information)); DBG (dbg_level, "Additional Sense Length = %d\n", data->sense_length); DBG (dbg_level, "Command Specific Information = %lu\n", _4btol (data->command_specific_information)); DBG (dbg_level, "Additional Sense Code = %#x\n", data->sense_code); DBG (dbg_level, "Additional Sense Code Qualifier = %#x\n", data->sense_code_qualifier); DBG (DBG_proc, "<< print_sense_data\n"); return (status); } static struct sense_key * lookup_sensekey_errmsg (int code) { int i; struct sense_key *k = &sensekey_errmsg[0]; for (i = 0; i < 16; i++, k++) if (k->key == code) return k; return NULL; } static struct ASCQ * lookup_ascq_errmsg (unsigned int code) { unsigned int i; struct ASCQ *k = &ascq_errmsg[0]; for (i = 0; i < 74; i++, k++) if (k->codequalifier == code) return k; return NULL; } /* a sensible sense handler arg is a pointer to the associated HS2P_Scanner structure SENSE DATA FORMAT: 14 bytes bits[7-0] Byte 0: [7]:valid [6-0]:Error Code Byte 1: Segment Number Byte 2: [7]: F-mark; [6]:EOM; [5]:ILI; [4]:reserved; [3-0]:Sense Key Byte 3: Information Byte Byte 4: Information Byte Byte 5: Information Byte Byte 6: Information Byte Byte 7: Additional Sense Length (n-7) Byte 8: Command Specific Information Byte 9: Command Specific Information Byte 10: Command Specific Information Byte 11: Command Specific Information Byte 12: Additional Sense Code Byte 13: Additional Sense Code Qualifier */ static SANE_Status sense_handler (int __sane_unused__ scsi_fd, u_char * sense_buffer, void *sd) { u_char sense, asc, ascq, EOM, ILI, ErrorCode, ValidData; u_long MissingBytes; char *sense_str = ""; struct sense_key *skey; struct ASCQ *ascq_key; SENSE_DATA *sdp = (SENSE_DATA *) sd; SANE_Int i; SANE_Status status = SANE_STATUS_INVAL; SANE_Char print_sense[(16 * 3) + 1]; DBG (DBG_proc, ">> sense_handler\n"); if (DBG_LEVEL >= DBG_info) print_sense_data (DBG_LEVEL, (SENSE_DATA *) sense_buffer); /* store sense_buffer */ DBG (DBG_info, ">> copying %lu bytes from sense_buffer[] to sense_data\n", (u_long) sizeof (SENSE_DATA)); memcpy (sdp, sense_buffer, sizeof (SENSE_DATA)); if (DBG_LEVEL >= DBG_info) print_sense_data (DBG_LEVEL, sdp); ErrorCode = sense_buffer[0] & 0x7F; ValidData = (sense_buffer[0] & 0x80) != 0; sense = sense_buffer[2] & 0x0f; /* Sense Key */ asc = sense_buffer[12]; /* Additional Sense Code */ ascq = sense_buffer[13]; /* Additional Sense Code Qualifier */ EOM = (sense_buffer[2] & 0x40) != 0; /* End Of Media */ ILI = (sense_buffer[2] & 0x20) != 0; /* Invalid Length Indicator */ MissingBytes = ValidData ? _4btol (&sense_buffer[3]) : 0; DBG (DBG_sense, "sense_handler: sense_buffer=%#x, sense=%#x, asc=%#x, ascq=%#x\n", sense_buffer[0], sense, asc, ascq); DBG (DBG_sense, "sense_handler: ErrorCode %02x ValidData: %d " "EOM: %d ILI: %d MissingBytes: %lu\n", ErrorCode, ValidData, EOM, ILI, MissingBytes); memset (print_sense, '\0', sizeof (print_sense)); for (i = 0; i < 16; i++) sprintf (print_sense + strlen (print_sense), "%02x ", sense_buffer[i]); DBG (DBG_sense, "sense_handler: sense=%s\n", print_sense); if (ErrorCode != 0x70 && ErrorCode != 0x71) { DBG (DBG_error, "sense_handler: error code is invalid.\n"); return SANE_STATUS_IO_ERROR; /* error code is invalid */ } skey = lookup_sensekey_errmsg (sense); /* simple sequential search */ DBG (DBG_sense, "sense_handler: sense_key=%#x '%s - %s'\n", skey->key, skey->meaning, skey->description); DBG (DBG_sense, "Looking up ascq=(%#x,%#x)=%#x\n", asc, ascq, (asc << 8) | ascq); ascq_key = lookup_ascq_errmsg ((asc << 8) | ascq); /* simple sequential search */ DBG (DBG_sense, "sense_handler: ascq=(%#x,%#x): %#x '%s'\n", asc, ascq, ascq_key->codequalifier, ascq_key->description); /* handle each sense key: Translate from HS2P message to SANE_STATUS_ message * SANE_STATUS_GOOD, _ACCESS_DEINIED, _NO_MEM, _INVAL, _IO_ERROR, _DEVICE_BUSY, * _EOF, _UNSUPPORTED, _CANCELLED, _JAMMED, _NO_DOCS, _COVER_OPEN */ switch (sense) { case 0x00: /* no sense */ status = SANE_STATUS_GOOD; break; case 0x01: /* recovered error */ status = SANE_STATUS_INVAL; break; case 0x02: /* not ready */ status = SANE_STATUS_DEVICE_BUSY; break; case 0x03: /* medium error */ status = SANE_STATUS_JAMMED; break; case 0x04: /* hardware error */ status = SANE_STATUS_IO_ERROR; break; case 0x05: /* illegal request */ status = SANE_STATUS_INVAL; break; case 0x06: /* unit attention */ status = SANE_STATUS_GOOD; break; case 0x07: /* data protect */ status = SANE_STATUS_INVAL; break; case 0x08: /* blank check */ status = SANE_STATUS_INVAL; break; case 0x09: /* vendor specific */ status = SANE_STATUS_INVAL; break; case 0x0A: /* copy aborted */ status = SANE_STATUS_CANCELLED; break; case 0x0B: /* aborted command */ status = SANE_STATUS_CANCELLED; break; case 0x0C: /* equal */ status = SANE_STATUS_INVAL; break; case 0x0D: /* volume overflow */ status = SANE_STATUS_INVAL; break; case 0x0E: /* miscompare */ status = SANE_STATUS_INVAL; break; case 0x0F: /* reserved */ status = SANE_STATUS_INVAL; break; } if (ErrorCode == 0x70) /* Additional Sense Codes available */ switch ((asc << 8) | ascq) { case 0x0000: /* No additional Information */ status = SANE_STATUS_GOOD; break; case 0x0002: /* End of Medium */ status = SANE_STATUS_NO_DOCS; break; case 0x0005: /* End of Data */ status = SANE_STATUS_EOF; break; case 0x0400: /* LUN not ready */ status = SANE_STATUS_DEVICE_BUSY; break; case 0x0401: /* LUN becoming ready */ status = SANE_STATUS_DEVICE_BUSY; break; case 0x0403: /* LUN not ready. Manual intervention needed */ status = SANE_STATUS_IO_ERROR; break; case 0x0500: /* LUN doesn't respond to selection */ status = SANE_STATUS_INVAL; break; case 0x0700: /* Multiple peripheral devices selected */ status = SANE_STATUS_INVAL; break; case 0x1100: /* Unrecovered read error */ status = SANE_STATUS_IO_ERROR; break; case 0x1101: /* Read retries exhausted */ status = SANE_STATUS_IO_ERROR; break; case 0x1501: /* Mechanical positioning error */ status = SANE_STATUS_IO_ERROR; break; case 0x1A00: /* Parameter list length error */ status = SANE_STATUS_INVAL; break; case 0x2000: /* Invalid command operation code */ status = SANE_STATUS_INVAL; break; case 0x2400: /* Invalid field in CDB (check field pointer) */ status = SANE_STATUS_INVAL; break; case 0x2500: /* LUN not supported */ status = SANE_STATUS_UNSUPPORTED; break; case 0x2600: /* Invalid field in parameter list (check field pointer) */ status = SANE_STATUS_INVAL; break; case 0x2900: /* Power on, reset, or BUS DEVICE RESET occurred */ status = SANE_STATUS_GOOD; break; case 0x2A01: /* (MODE parameter changed) */ status = SANE_STATUS_INVAL; break; case 0x2C00: /* Command sequence error */ status = SANE_STATUS_INVAL; break; case 0x2C01: /* Too many windows specified */ status = SANE_STATUS_INVAL; break; case 0x2C02: /* Invalid combination of windows specified */ status = SANE_STATUS_INVAL; break; case 0x3700: /* (Rounded paramter) */ status = SANE_STATUS_INVAL; break; case 0x3900: /* (Saving parameters not supported) */ status = SANE_STATUS_INVAL; break; case 0x3A00: /* Medium not present */ status = SANE_STATUS_NO_DOCS; break; case 0x3B09: /* Read past end of medium */ status = SANE_STATUS_EOF; break; case 0x3B0B: /* Position past end of medium */ status = SANE_STATUS_EOF; break; case 0x3D00: /* Invalid bits in IDENTIFY message */ status = SANE_STATUS_INVAL; break; case 0x4300: /* Message error */ status = SANE_STATUS_INVAL; break; case 0x4500: /* Select/Reselect failure */ status = SANE_STATUS_IO_ERROR; break; case 0x4700: /* (SCSI parity error) */ status = SANE_STATUS_IO_ERROR; break; case 0x4800: /* Initiator detected error message received */ status = SANE_STATUS_IO_ERROR; break; case 0x4900: /* Invalid message error */ status = SANE_STATUS_INVAL; break; case 0x4B00: /* Data phase error */ status = SANE_STATUS_IO_ERROR; break; case 0x5300: /* (Media Load/Eject failed) */ status = SANE_STATUS_IO_ERROR; break; case 0x6000: /* Lamp failure */ status = SANE_STATUS_IO_ERROR; break; case 0x6001: /* Shading error */ status = SANE_STATUS_IO_ERROR; break; case 0x6002: /* White adjustment error */ status = SANE_STATUS_IO_ERROR; break; case 0x6010: /* Reverse Side Lamp Failure */ status = SANE_STATUS_IO_ERROR; break; case 0x6200: /* Scan head positioning error */ status = SANE_STATUS_IO_ERROR; break; case 0x6300: /* Document Waiting Cancel */ status = SANE_STATUS_CANCELLED; break; case 0x8000: /* (PSU over heate) */ status = SANE_STATUS_IO_ERROR; break; case 0x8001: /* (PSU 24V fuse down) */ status = SANE_STATUS_IO_ERROR; break; case 0x8002: /* (ADF 24V fuse down) */ status = SANE_STATUS_IO_ERROR; break; case 0x8003: /* (5V fuse down) */ status = SANE_STATUS_IO_ERROR; break; case 0x8004: /* (-12V fuse down) */ status = SANE_STATUS_IO_ERROR; break; case 0x8100: /* (ADF 24V power off) */ status = SANE_STATUS_IO_ERROR; break; case 0x8102: /* (Base 12V power off) */ status = SANE_STATUS_IO_ERROR; break; case 0x8103: /* Lamp cover open (Lamp 24V power off) */ status = SANE_STATUS_IO_ERROR; break; case 0x8104: /* (-12V power off) */ status = SANE_STATUS_IO_ERROR; break; case 0x8105: /* (Endorser 6V power off) */ status = SANE_STATUS_IO_ERROR; break; case 0x8106: /* SCU 3.3V power down error */ status = SANE_STATUS_IO_ERROR; break; case 0x8107: /* RCU 3.3V power down error */ status = SANE_STATUS_IO_ERROR; break; case 0x8108: /* OIPU 3.3V power down error */ status = SANE_STATUS_IO_ERROR; break; case 0x8200: /* Memory Error (Bus error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8210: /* Reverse-side memory error (Bus error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8300: /* (Image data processing LSI error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8301: /* (Interface LSI error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8302: /* (SCSI controller error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8303: /* (Compression unit error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8304: /* (Marker detect unit error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8400: /* Endorser error */ status = SANE_STATUS_IO_ERROR; break; case 0x8500: /* (Origin Positioning error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8600: /* Mechanical Time Out error (Pick Up Roller error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8700: /* (Heater error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8800: /* (Thermistor error) */ status = SANE_STATUS_IO_ERROR; break; case 0x8900: /* ADF cover open */ status = SANE_STATUS_COVER_OPEN; break; case 0x8901: /* (ADF lift up) */ status = SANE_STATUS_COVER_OPEN; break; case 0x8902: /* Document jam error for ADF */ status = SANE_STATUS_JAMMED; break; case 0x8903: /* Document misfeed for ADF */ status = SANE_STATUS_JAMMED; break; case 0x8A00: /* (Interlock open) */ status = SANE_STATUS_COVER_OPEN; break; case 0x8B00: /* (Not enough memory) */ status = SANE_STATUS_NO_MEM; break; case 0x8C00: /* Size Detection failed */ status = SANE_STATUS_IO_ERROR; break; default: /* Should never get here */ status = SANE_STATUS_INVAL; DBG (DBG_sense, "sense_handler: 'Undocumented code': ascq=(%#x,%#x)\n", asc & 0xFF00, ascq & 0x00FF); break; } DBG (DBG_proc, "sense_handler %s: '%s'-'%s' '%s' return:%d\n", sense_str, skey->meaning, skey->description, ascq_key->description, status); return status; } /* VPD IDENTIFIER Page Code 0x00 * A list of all Page Codes supported by scanner is returned as data * Byte0 => bit7-5: Peripheral Qualifier, bits4-0: Peripheral Device Type * Byte1 => Page Code of CDB is set as Page Code 0 * Byte2 => Reserved * Byte3 => Page Length is 2 because scanner supports just two page codes: C0H and F0H * Byte4 => First Support Page Code * Byte5 => Second Support Page Code */ #if 0 static SANE_Status vpd_indentifier_00H (int fd) { static SANE_Byte cmd[6]; SANE_Status status; DBG (DBG_proc, ">> vpd_identifier_00H\n"); cmd[0] = HS2P_SCSI_REQUEST_SENSE; memset (cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (DBG_proc, "<< vpd_identifier_00H\n"); return (status); } #endif #if 0 static SANE_Status vpd_identifier_C0H (int fd) { static SANE_Byte cmd[6]; SANE_Status status; DBG (DBG_proc, ">> vpd_identifier_C0H\n"); cmd[0] = HS2P_SCSI_REQUEST_SENSE; memset (cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (DBG_proc, "<< vpd_identifier_C0H\n"); return (status); } #endif /* 1-3-3 INQUIRY : 6 bytes: * Byte0 => 0x12 * Byte1 => bits7-5: Logical Unit number * bits4-1: Reserved * bit0: EVPD * Byte2 => Page Code * Byte3 => Reserved * Byte4 => Allocation Length * Byte5 => bits7-6: Vendor Unique * bits5-2: Reserved * bit1: Flag * bit0: Link */ static SANE_Status inquiry (int fd, void *buf, size_t * buf_size, SANE_Byte evpd, SANE_Byte page_code) { static SANE_Byte cmd[6]; SANE_Status status; DBG (DBG_proc, ">> inquiry\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = HS2P_SCSI_INQUIRY; cmd[1] = evpd; cmd[2] = page_code; /*cmd[3] Reserved */ cmd[4] = *buf_size; /*cmd[5] vendorunique+reserved+flag+link */ status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); DBG (DBG_proc, "<< inquiry\n"); return (status); } /* 1-3-6 MODE SELECT -- sets various operation mode parameters for scanner */ static SANE_Status mode_select (int fd, MP * settings) { static struct { SELECT cmd; /* Mode page Select command */ MP mp; /* Hdr + Parameters */ } msc; /* Mode Select Command */ SANE_Status status; size_t npages; DBG (DBG_proc, ">> mode_select\n"); memset (&msc, 0, sizeof (msc)); /* Fill struct with zeros */ msc.cmd.opcode = HS2P_SCSI_MODE_SELECT; /* choose Mode Select Command */ msc.cmd.byte1 &= ~SMS_SP; /* unset bit0 SavePage to 0 */ msc.cmd.byte1 |= SMS_PF; /* set bit4 PageFormat to 1 */ npages = (settings->page.code == 2) ? 16 : 8; msc.cmd.len = sizeof (msc.mp.hdr) + npages; /* either 4+8 or 4+20 */ memcpy (&msc.mp, settings, msc.cmd.len); /* Copy hdr+pages from Settings to msc.mp */ memset (&msc.mp.hdr, 0, sizeof (msc.mp.hdr)); /* make sure the hdr is all zeros */ /* msc.hdr.data_len = 0x00; msc.hdr.medium_type = 0x00; msc.hdr.dev_spec = 0x00; msc.hdr.blk_desc_len = 0x00; */ /* Now execute the whole command */ if ((status = sanei_scsi_cmd (fd, &msc, sizeof (msc.cmd) + msc.cmd.len, 0, 0)) != SANE_STATUS_GOOD) { DBG (DBG_error, "ERROR: mode_select: %s\n", sane_strstatus (status)); DBG (DBG_error, "PRINTING CMD BLOCK:\n"); print_bytes (&msc.cmd, sizeof (msc.cmd)); DBG (DBG_error, "PRINTING MP HEADER:\n"); print_bytes (&msc.mp.hdr, sizeof (msc.mp.hdr)); DBG (DBG_error, "PRINTING MP PAGES:\n"); print_bytes (&msc.mp.page, msc.cmd.len); } DBG (DBG_proc, "<< mode_select\n"); return (status); } /* 1-3-7 MODE SENSE -- gets various operation mode parameters from scanner */ static SANE_Status mode_sense (int fd, MP * buf, SANE_Byte page_code) { SANE_Status status; SENSE cmd; /* 6byte cmd */ MP msp; /* Mode Sense Page * 4byte hdr + {2bytes +14 bytes} * buffer to hold mode sense data gotten from scanner */ size_t nbytes; DBG (DBG_proc, ">>>>> mode_sense: fd=%d, page_code=%#02x\n", fd, page_code); nbytes = sizeof (msp); DBG (DBG_info, ">>>>> mode_sense: Zero'ing ModeSenseCommand msc and msp structures\n"); memset (&cmd, 0, sizeof (cmd)); /* Fill cmd struct with zeros */ memset (&msp, 0, sizeof (msp)); /* Fill msp struct with zeros */ /* set up Mode Sense Command */ DBG (DBG_info, ">>>>> mode_sense: Initializing Mode Sense cmd\n"); cmd.opcode = HS2P_SCSI_MODE_SENSE; cmd.dbd &= ~(1 << 3); /* Disable Block Description (bit3) is set to 0 */ cmd.pc = (page_code & 0x3F); /* bits 5-0 */ cmd.pc &= ~(0x03 << 6); /* unset PC Field (bits7-6) * 00 Curent Value is the only effective value * 01 Changeable Value * 10 Default Value * 11 Saved Value */ /* cmd.len = ??? Allocation Length */ /* Now execute the whole command and store results in msc */ DBG (DBG_info, ">>>>> mode_sense: sanei_scsi_cmd\n"); DBG (DBG_info, ">>>>> cmd.opcode=%#0x cmd.dbd=%#02x, cmd.pc=%#02x\n", cmd.opcode, cmd.dbd, cmd.pc); nbytes = (page_code == 2) ? 20 : 12; DBG (DBG_info, ">>>>> sizeof(cmd)=%lu sizeof(msp)=%lu sizeof(hdr)=%lu sizeof(page)=%lu requesting %lu bytes\n", (u_long) sizeof (cmd), (u_long) sizeof (msp), (u_long) sizeof (msp.hdr), (u_long) sizeof (msp.page), (u_long) nbytes); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &msp, &nbytes); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "ERROR mode_sense: sanei_scsi_cmd error \"%s\"\n", sane_strstatus (status)); DBG (DBG_error, ">>>>> mode sense: number of bytes received from scanner: %lu\n", (u_long) nbytes); DBG (DBG_error, "PRINTING CMD BLOCK:\n"); print_bytes (&cmd, sizeof (cmd)); DBG (DBG_error, "PRINTING MP HEADER:\n"); print_bytes (&msp.hdr, sizeof (msp.hdr)); DBG (DBG_error, "PRINTING MP PAGES:\n"); print_bytes (&msp.page, sizeof (msp.page)); } else { /* nbytes = (page_code==2)? 14 : 6; */ DBG (DBG_info, ">> >> got %lu bytes from scanner\n", (u_long) nbytes); nbytes -= 4; /* we won't copy 4 byte hdr */ DBG (DBG_info, ">>>>> copying from msp to calling function's buf\n" ">>>>> msp.page_size=%lu bytes=%lu buf_size=%lu\n", (u_long) sizeof (msp.page), (u_long) nbytes, (u_long) sizeof (*buf)); memcpy (buf, &(msp.page), nbytes); } DBG (DBG_proc, "<<<<< mode_sense\n"); return (status); } static SANE_Status set_window (int fd, SWD * swd) { static struct { struct set_window_cmd cmd; struct set_window_data swd; } win; SANE_Status status; static size_t wdl, tl; /*window descriptor length, transfer length */ DBG (DBG_proc, ">> set_window\n"); /* initialize our struct with zeros */ memset (&win, 0, sizeof (win)); /* fill in struct with opcode */ win.cmd.opcode = HS2P_SCSI_SET_WINDOW; /* bytes 1-5 are reserved */ /* Transfer length is header + window data */ tl = sizeof (*swd); _lto3b (tl, &win.cmd.len[0]); /* 8 + (2*320) = 648 */ DBG (DBG_info, "set_window: SET WINDOW COMMAND Transfer Length = %lu (should be 648)\n", (unsigned long) tl); /* Copy data from swd (including 8-byte header) to win.swd */ DBG (DBG_info, "set_window: COPYING %lu bytes from settings to Set Window Command (%lu)\n", (u_long) sizeof (*swd), (u_long) sizeof (win.swd)); if (!memcpy (&(win.swd), swd, sizeof (*swd))) { DBG (DBG_error, "set_window: error with memcpy\n"); } /* Set Window Data Header: 0-5:reserved; 6-7:Window Descriptor Lenght=640 */ wdl = sizeof (win.swd) - sizeof (win.swd.hdr); _lto2b (wdl, &win.swd.hdr.len[0]); DBG (DBG_info, "set_window: SET WINDOW COMMAND Window Descriptor Length = %lu (should be 640)\n", (unsigned long) wdl); /* Now execute command */ DBG (DBG_info, "set_window: calling sanei_scsi_cmd(%d,&win,%lu, NULL, NULL)\n", fd, (u_long) sizeof (win)); status = sanei_scsi_cmd (fd, &win, sizeof (win), NULL, NULL); /* status = sanei_scsi_cmd2 (fd, &win.cmd, sizeof(win.cmd), &win.swd, sizeof(win.swd), NULL, NULL); */ if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "*********************\n"); DBG (DBG_error, "ERROR: set_window: %s\n", sane_strstatus (status)); DBG (DBG_error, "PRINTING SWD CMD BLK:\n"); print_bytes (&win.cmd, sizeof (win.cmd)); DBG (DBG_error, "PRINTING SWD HEADER:\n"); print_bytes (&win.swd.hdr, sizeof (win.swd.hdr)); DBG (DBG_error, "PRINTING SWD DATA[0]:\n"); print_bytes (&win.swd.data[0], sizeof (win.swd.data[0])); DBG (DBG_error, "PRINTING SWD DATA[1]:\n"); print_bytes (&win.swd.data[1], sizeof (win.swd.data[1])); DBG (DBG_error, "*********************\n"); } DBG (DBG_proc, "<< set_window\n"); return (status); } static SANE_Status get_window (int fd, GWD * gwd) { struct get_window_cmd cmd; SANE_Status status; static size_t gwd_size; DBG (DBG_proc, ">> get_window\n"); gwd_size = sizeof (*gwd); DBG (DBG_info, ">> get_window datalen = %lu\n", (unsigned long) gwd_size); /* fill in get_window_cmd */ memset (&cmd, 0, sizeof (cmd)); /* CLEAR cmd */ cmd.opcode = HS2P_SCSI_GET_WINDOW; cmd.byte1 &= ~0x01; /* unset single bit 0 */ cmd.win_id = 0x00; /* either 0 or 1 */ _lto3b (gwd_size, cmd.len); /* Transfer Length is byte length of DATA to be returned */ status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), gwd, &gwd_size); DBG (DBG_proc, "<< get_window, datalen = %lu\n", (unsigned long) gwd_size); return (status); } static void print_window_data (SWD * buf) { int i, j, k; struct hs2p_window_data *data; struct window_section *ws; DBG (DBG_proc, ">> print_window_data\n"); DBG (DBG_info, "HEADER\n"); for (i = 0; i < 6; i++) DBG (DBG_info, "%#02x\n", buf->hdr.reserved[i]); DBG (DBG_info, "Window Descriptor Length=%lu\n\n", _2btol (buf->hdr.len)); for (i = 0; i < 2; i++) { data = &buf->data[i]; DBG (DBG_info, "Window Identifier = %d\n", data->window_id); DBG (DBG_info, "AutoBit = %#x\n", data->auto_bit); DBG (DBG_info, "X-Axis Resolution = %lu\n", _2btol (data->xres)); DBG (DBG_info, "Y-Axis Resolution = %lu\n", _2btol (data->yres)); DBG (DBG_info, "X-Axis Upper Left = %lu\n", _4btol (data->ulx)); DBG (DBG_info, "Y-Axis Upper Left = %lu\n", _4btol (data->uly)); DBG (DBG_info, "Window Width = %lu\n", _4btol (data->width)); DBG (DBG_info, "Window Length = %lu\n", _4btol (data->length)); DBG (DBG_info, "Brightness = %d\n", data->brightness); DBG (DBG_info, "Threshold = %d\n", data->threshold); DBG (DBG_info, "Contrast = %d\n", data->contrast); DBG (DBG_info, "Image Composition = %#0x\n", data->image_composition); DBG (DBG_info, "Bits per Pixel = %d\n", data->bpp); DBG (DBG_info, "Halftone Code = %#0x\n", data->halftone_code); DBG (DBG_info, "Halftone Id = %#0x\n", data->halftone_id); DBG (DBG_info, "Byte29 = %#0x RIF=%d PaddingType=%d\n", data->byte29, data->byte29 & 0x80, data->byte29 & 0x7); DBG (DBG_info, "Bit Ordering = %lu\n", _2btol (data->bit_ordering)); DBG (DBG_info, "Compression Type = %#x\n", data->compression_type); DBG (DBG_info, "Compression Arg = %#x\n", data->compression_arg); for (j = 0; j < 6; j++) DBG (DBG_info, "Reserved=%#x\n", data->reserved2[j]); DBG (DBG_info, "Ignored = %#x\n", data->ignored1); DBG (DBG_info, "Ignored = %#x\n", data->ignored2); DBG (DBG_info, "Byte42 = %#x MRIF=%d Filtering=%d GammaID=%d\n", data->byte42, data->byte42 & 0x80, data->byte42 & 0x70, data->byte42 & 0x0F); DBG (DBG_info, "Ignored = %#x\n", data->ignored3); DBG (DBG_info, "Ignored = %#x\n", data->ignored4); DBG (DBG_info, "Binary Filtering = %#x\n", data->binary_filtering); DBG (DBG_info, "Ignored = %#x\n", data->ignored5); DBG (DBG_info, "Ignored = %#x\n", data->ignored6); DBG (DBG_info, "Automatic Separation = %#x\n", data->automatic_separation); DBG (DBG_info, "Ignored = %#x\n", data->ignored7); DBG (DBG_info, "Automatic Binarization = %#x\n", data->automatic_binarization); for (j = 0; j < 13; j++) DBG (DBG_info, "Ignored = %#x\n", data->ignored8[j]); for (k = 0; k < 8; k++) { ws = &data->sec[k]; DBG (DBG_info, "\n\n"); DBG (DBG_info, "SECTION %d\n", k); DBG (DBG_info, "Section Enable Flat (sef bit) = %#x\n", ws->sef); DBG (DBG_info, "ignored = %d\n", ws->ignored0); DBG (DBG_info, "Upper Left X = %lu\n", _4btol (ws->ulx)); DBG (DBG_info, "Upper Left Y = %lu\n", _4btol (ws->uly)); DBG (DBG_info, "Width = %lu\n", _4btol (ws->width)); DBG (DBG_info, "Length = %lu\n", _4btol (ws->length)); DBG (DBG_info, "Binary Filtering = %#x\n", ws->binary_filtering); DBG (DBG_info, "ignored = %d\n", ws->ignored1); DBG (DBG_info, "Threshold = %#x\n", ws->threshold); DBG (DBG_info, "ignored = %d\n", ws->ignored2); DBG (DBG_info, "Image Composition = %#x\n", ws->image_composition); DBG (DBG_info, "Halftone Id = %#x\n", ws->halftone_id); DBG (DBG_info, "Halftone Code = %#x\n", ws->halftone_code); for (j = 0; j < 7; j++) DBG (DBG_info, "ignored = %d\n", ws->ignored3[j]); } } DBG (DBG_proc, "<< print_window_data\n"); } static SANE_Status read_data (int fd, void *buf, size_t * buf_size, SANE_Byte dtc, u_long dtq) { static struct scsi_rs_scanner_cmd cmd; SANE_Status status; DBG (DBG_proc, ">> read_data buf_size=%lu dtc=0x%2.2x dtq=%lu\n", (unsigned long) *buf_size, (int) dtc, dtq); if (fd < 0) { DBG (DBG_error, "read_data: scanner is closed!\n"); return SANE_STATUS_INVAL; } memset (&cmd, 0, sizeof (cmd)); /* CLEAR */ cmd.opcode = HS2P_SCSI_READ_DATA; cmd.dtc = dtc; _lto2b (dtq, cmd.dtq); _lto3b (*buf_size, cmd.len); DBG (DBG_info, "read_data ready to send scsi cmd\n"); DBG (DBG_info, "opcode=0x%2.2x, dtc=0x%2.2x, dtq=%lu, transfer len =%d\n", cmd.opcode, cmd.dtc, _2btol (cmd.dtq), _3btol (cmd.len)); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), buf, buf_size); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "read_data: %s\n", sane_strstatus (status)); DBG (DBG_proc, "<< read_data %lu\n", (unsigned long) *buf_size); return (status); } #if 0 static SANE_Status send_data (int fd, void *buf, size_t * buf_size) { static struct scsi_rs_scanner_cmd cmd; SANE_Status status; DBG (DBG_proc, ">> send_data %lu\n", (unsigned long) *buf_size); memset (&cmd, 0, sizeof (cmd)); /* CLEAR */ memcpy (&cmd, buf, sizeof (*buf)); /* Fill in our struct with set values */ cmd.opcode = HS2P_SCSI_SEND_DATA; _lto3b (*buf_size, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), buf, buf_size); DBG (DBG_proc, "<< send_data %lu\n", (unsigned long) *buf_size); return (status); } #endif static SANE_Bool is_valid_endorser_character (char c) { int i = (int) c; /* 44 characters can be printed by endorser */ if (i >= 0x30 && i <= 0x3A) return SANE_TRUE; /* 0123456789: */ if (i == 0x23) return SANE_TRUE; /* # */ if (i == 0x27) return SANE_TRUE; /* ` */ if (i >= 0x2C && i <= 0x2F) return SANE_TRUE; /* '-./ */ if (i == 0x20) return SANE_TRUE; /* space */ if (i >= 0x41 && i <= 0x5A) return SANE_TRUE; /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ if (i >= 0x61 && i <= 0x7A) return SANE_TRUE; /* abcdefghijklmnopqrstuvwxyz */ return SANE_FALSE; } static SANE_Status set_endorser_string (int fd, SANE_String s) { struct { struct scsi_rs_scanner_cmd cmd; SANE_Byte endorser[19]; } out; char *t; int i, len; SANE_Status status; DBG (DBG_proc, ">> set_endorser_string %s\n", s); for (i = 0, t = s; *t != '\0' && i < 19; i++) { DBG (DBG_info, "CHAR=%c\n", *t); if (!is_valid_endorser_character (*t++)) return SANE_STATUS_INVAL; } len = strlen (s); memset (&out, 0, sizeof (out)); /* CLEAR */ out.cmd.opcode = HS2P_SCSI_SEND_DATA; /* 2AH */ out.cmd.dtc = 0x80; /* Endorser Data */ _lto3b (len, &out.cmd.len[0]); /* 19 bytes max */ memset (&out.endorser[0], ' ', 19); /* fill with spaces */ memcpy (&out.endorser[0], s, len); status = sanei_scsi_cmd (fd, &out, sizeof (out), NULL, NULL); DBG (DBG_proc, "<< set_endorser_string s=\"%s\" len=%d\n", s, len); return (status); } static SANE_Status hs2p_send_gamma (HS2P_Scanner * s) { SANE_Status status; struct { struct scsi_rs_scanner_cmd cmd; SANE_Byte gamma[2 + GAMMA_LENGTH]; } out; int i; size_t len = sizeof (out.gamma); DBG (DBG_proc, ">> teco_send_gamma\n"); memset (&out, 0, sizeof (out)); /* CLEAR */ out.cmd.opcode = HS2P_SCSI_SEND_DATA; /* 2AH */ out.cmd.dtc = 0x03; /* Gamma Function Data */ _lto3b (len, &out.cmd.len[0]); /* 19 bytes max */ out.gamma[0] = 0x08; /* Gamma ID for Download table */ out.gamma[1] = 0x08; /* The Number of gray scale (M) = 8 */ for (i = 0; i < GAMMA_LENGTH; i++) { out.gamma[i + 2] = s->gamma_table[i]; } status = sanei_scsi_cmd (s->fd, &out, sizeof (out), NULL, NULL); DBG (DBG_proc, "<< teco_send_gamma\n"); return (status); } #if 0 static SANE_Status clear_maintenance_data (int fd, int code, char XorY, int number) { struct { struct scsi_rs_scanner_cmd cmd; char string[20]; } out; SANE_Status status; DBG (DBG_proc, ">> set_maintenance data\n"); memset (&out, 0, sizeof (out)); /* CLEAR */ out.cmd.opcode = HS2P_SCSI_SEND_DATA; /* 2AH */ out.cmd.dtc = 0x85; /* Maintenance Data */ _lto3b (20, out.cmd.len); /* 20 bytes */ switch (code) { case 1: strcpy (out.string, "EEPROM ALL ALL RESET"); break; case 2: strcpy (out.string, "EEPROM ALL RESET"); break; case 3: strcpy (out.string, "ADF RESET"); break; case 4: strcpy (out.string, "FLATBED RESET"); break; case 5: strcpy (out.string, "LAMP RESET"); break; case 6: sprintf (out.string, "EEPROM ADF %c %+4.1d", XorY, number); break; case 7: sprintf (out.string, "EEPROM BOOK %c %4.1d", XorY, number); break; case 8: sprintf (out.string, "WHITE ADJUST DATA %3d", number); break; case 9: strcpy (out.string, "EEPROM FIRST WHITE ODD"); break; case 10: strcpy (out.string, "EEPROM FIRST WHITE EVEN"); break; case 11: strcpy (out.string, "R ADF RESET"); break; case 12: strcpy (out.string, "R LAMP RESET"); break; case 13: sprintf (out.string, "EEPROM R ADF %c %4.1d", XorY, number); break; case 14: strcpy (out.string, "ENDORSER RESET"); break; } status = sanei_scsi_cmd (fd, &out, sizeof (out), NULL, NULL); DBG (DBG_proc, "<< set_maintenance data\n"); return (status); } #endif #if 0 static SANE_Status read_halftone_mask (int fd, SANE_Byte halftone_id, void *buf, size_t * buf_size) { static struct scsi_rs_scanner_cmd cmd; SANE_Status status; SANE_Int len; DBG (DBG_proc, ">> read_halftone_mask\n"); memset (&cmd, 0, sizeof (cmd)); /* CLEAR */ cmd.opcode = HS2P_SCSI_READ_DATA; cmd.dtc = DATA_TYPE_HALFTONE; _lto2b (halftone_id, cmd.dtq); /* Each cell of an NxM dither pattern is 1 byte from the set {2,3,4,6,8,16} */ switch (halftone_id) { case 0x01: len = 32; break; /* 8x4, 45 degree */ case 0x02: len = 36; break; /* 6x6, spiral */ case 0x03: len = 16; break; /* 4x4, spiral */ case 0x04: len = 64; break; /* 8x8, 90 degree */ case 0x05: len = 70; break; /* 70 lines */ case 0x06: len = 95; break; /* 95 lines */ case 0x07: len = 180; break; /* 180 lines */ case 0x08: len = 128; break; /* 16x8, 45 degree */ case 0x09: len = 256; break; /* 16x16, 90 degree */ case 0x0A: len = 64; break; /* 8x8, Bayer */ default: return SANE_STATUS_INVAL; /* Reserved */ } _lto3b (len, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), buf, buf_size); DBG (DBG_proc, "<< read_halftone_mask\n"); return (status); } #endif #if 0 static SANE_Status set_halftone_mask (int fd, SANE_Byte halftone_id, void *buf, size_t * buf_size) { static struct scsi_rs_scanner_cmd cmd; SANE_Status status; DBG (DBG_proc, ">> set_halftone_mask\n"); memset (&cmd, 0, sizeof (cmd)); /* CLEAR */ cmd.opcode = HS2P_SCSI_READ_DATA; cmd.dtc = DATA_TYPE_HALFTONE; _lto2b (halftone_id, cmd.dtq); /* Each cell of an NxM dither pattern is 1 byte from the set {2,3,4,6,8,16} * 0x80, 0x81 are User definable custom dither patterns */ if (halftone_id != 0x80 && halftone_id != 0x81) return SANE_STATUS_INVAL; _lto3b (*buf_size, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), buf, buf_size); DBG (DBG_proc, "<< set_halftone_mask\n"); return (status); } #endif #if 0 static SANE_Status read_gamma_function (int fd) { SANE_Status status = SANE_STATUS_GOOD; return (status); } static SANE_Status read_endorser_data (int fd) { SANE_Status status = SANE_STATUS_GOOD; return (status); } static SANE_Status read_size_data (int fd) { SANE_Status status = SANE_STATUS_GOOD; return (status); } #endif #if 0 static SANE_Status read_maintenance_data (int fd) { SANE_Status status = SANE_STATUS_GOOD; return (status); } #endif /* Bit0: is 0 if document on ADF; else 1 * Bit1: is 0 if ADF cover is closed; else 1 * Bit2: reserved * Bits7-3: reserved */ #if 0 static SANE_Status read_adf_status (int fd, SANE_Byte * adf_status_byte) { SANE_Status status = SANE_STATUS_GOOD; struct scsi_rs_scanner_cmd cmd; static size_t len = 1; DBG (DBG_proc, ">> read_adf_status\n"); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = HS2P_SCSI_READ_DATA; cmd.dtc = DATA_TYPE_ADF_STATUS; _lto3b (0x01, cmd.len); /* convert 0x01 into 3-byte Transfer Length */ if ((status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), adf_status_byte, &len)) != SANE_STATUS_GOOD) { DBG (DBG_error, "read_adf_status ERROR: %s\n", sane_strstatus (status)); } DBG (DBG_proc, "<< read_adf_status\n"); return (status); } #endif /* * read_ipu_photoletter_parameters * read_ipu_threshold_parameters * read_sensor_data (WHAT DATA TYPE CODE?) */ /* SEND CMD */ /* * send_halftone_mask * send_gamma_function * send_endorser_data * send_maintenance_data * EPROM All Clear * EPROM Counter Clear * ADF Counter Clear * Flatbed Counter Clear * Lamp Counter Clear * ADF Register Data * Flatbed Register Data * White Adjustment Data * White level first Data (ODD) * White level first Data (EVEN) * Reverse side ADF Counter Clear * Reverse side Lamp Counter Clear * Reverse side ADF Register Data * Endorser Character Counter Clear * send_ipu_parameters */ /* OBJECT POSITION */ /* GET DATA BUFFER STATUS */ /* 1-3-4 MODE SELECT */ /* 1-3-5 Reserve Unit: 0x16 * 1-3-6 Release Unit: 0x17 */ static SANE_Status unit_cmd (int fd, SANE_Byte opcode) { static struct { SANE_Byte opcode; /* 16H: Reserve Unit 17H: Release Unit */ SANE_Byte byte1; /* 7-5: LUN; 4: 3rd Party; 3-1: 3rd Party Device; 0: Reserved */ SANE_Byte reserved[3]; SANE_Byte control; /* 7-6: Vendor Unique; 5-2: Reserved; 1: Flag; 0: Link */ } cmd; SANE_Byte LUN = (0x00 & 0x07) << 5; SANE_Status status; DBG (DBG_proc, ">> unit_cmd\n"); cmd.opcode = opcode; cmd.byte1 = LUN & 0xE1; /* Mask=11100001 3rd Party and 3rd Party Device must be 0 */ memset (&cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), 0, 0); DBG (DBG_proc, "<< unit_cmd\n"); return (status); } /* The OBJECT POSITION command is used for carriage control or * document feed and eject with ADF * * Position Function: Byte1 bits2-0 * 000 Unload instructs document eject * 001 Load instructs document feed to scan start position * 010 Absolute Positioning - instructs carriage to move to carriage lock position * The carriage moves in the Y-axis direction as the amount set in Count when * count>0 * (Not supported in IS420) * */ static SANE_Status object_position (int fd, int load) { static struct scsi_object_position_cmd cmd; SANE_Status status; DBG (DBG_proc, ">> object_position\n"); /* byte 0 opcode * byte 1 position function * bytes 2-4 reserved * bytes 5-8 reserved * byte 9 control */ memset (&cmd, 0, sizeof (cmd)); cmd.opcode = HS2P_SCSI_OBJECT_POSITION; if (load) cmd.position_func = OBJECT_POSITION_LOAD; else cmd.position_func = OBJECT_POSITION_UNLOAD; status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), 0, 0); DBG (DBG_proc, "<< object_position\n"); return (status); } static SANE_Status get_data_status (int fd, STATUS_DATA * dbs) { static GET_DBS_CMD cmd; static STATUS_BUFFER buf; /* hdr + data */ size_t bufsize = sizeof (buf); SANE_Status status; DBG (DBG_proc, ">> get_data_status %lu\n", (unsigned long) bufsize); /* Set up GET DATA BUFFER STATUS cmd */ memset (&cmd, 0, sizeof (cmd)); /* CLEAR cmd */ cmd.opcode = HS2P_SCSI_GET_BUFFER_STATUS; cmd.wait &= ~0x01; /* unset Wait bit0 */ _lto2b (bufsize, cmd.len); /* Now execute cmd, and put returned results in buf */ status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &buf, &bufsize); /* Now copy from buf.data to dbs */ memcpy (dbs, &buf.data, sizeof (*dbs)); if (status == SANE_STATUS_GOOD && ((unsigned int) _3btol (buf.hdr.len) <= sizeof (*dbs) || _3btol (buf.data.filled) == 0)) { DBG (DBG_info, "get_data_status: busy\n"); status = SANE_STATUS_DEVICE_BUSY; } DBG (DBG_proc, "<< get_data_status %lu\n", (unsigned long) bufsize); return (status); } /* 1-3-7 MODE SENSE */ /* 1-3-8 SCAN */ /* 1-3-9 Receive Diagnostic * Byte0: 1CH * Byte1: 7-5 LUN; 4-0: reserved * Byte2: Reserved * Byte3-4: Allocation Length * Byte5: 7-6: Vendor Unique; 5-2: Reserved; 1: Flag; 0: Link * * This command is treated as a dummy command * Return GOOD unless there is an error in command in which case it returns CHECK */ /* * The IS450 performs 7 self-diagnostics tests * 1) Home position error check * 2) Exposure lamp error check * 3) White level error check * 4) Document table error check * 5) SCU error check * 6) RCU error check * 7) Memory error check * * and uses the lights on the scanner to indicate the result * * PowerOn MachineBusy DocumentInPlace Error * (green) (green) (green) (red) * * SCU error check Blinking Blinking * RCU error check Blinking On Blinking * Home position error check Blinking Blinking Blinking On * Exposure lamp error check Blinking Blinking On On * White level error check Blinking Blinking * Memory Error (Simplex) Blinking * Memory Error (Duplex) Blinking * */ #if 0 static SANE_Status receive_diagnostic (int fd) { static SANE_Byte cmd[6]; SANE_Status status; DBG (DBG_proc, ">> receive_diagnostic\n"); cmd[0] = HS2P_SCSI_RECEIVE_DIAGNOSTICS; memset (cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (DBG_proc, "<< receive_diagnostic\n"); return (status); } #endif /* 1-3-10 Send Diagnostic * Byte0: 1DH * Byte1: 7-5 LUN; 4: PF; 3: Reserved; 2: S-Test; 1: DevOfl; 0: U-Ofl * Byte2: Reserved * Byte3-4: Parameter List Length * Byte5: 7-6: Vendor Unique; 5-2: Reserved; 1: Flag; 0: Link * This command executes self-diagnostic and optical-adjustment * PF, DevOfl, and Parameter List Length must be 0 or CHECK condition is returned. */ #if 0 static SANE_Status send_diagnostic (int fd) { static SANE_Byte cmd[6]; SANE_Status status; DBG (DBG_proc, ">> send_diagnostic\n"); cmd[0] = HS2P_SCSI_SEND_DIAGNOSTICS; cmd[1] = 0x00 & (1 << 2) & 0xED; /* Set Self-Test bit and clear PF, DevOfl bits */ cmd[3] = 0x00; cmd[4] = 0x00; /* Parameter list (bytes3-4) must be 0x00 */ memset (cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (DBG_proc, "<< send_diagnostic\n"); return (status); } #endif /* 1-3-8 SCAN command is used to instruct scanner to start scanning */ static SANE_Status trigger_scan (HS2P_Scanner * s) { static struct { START_SCAN cmd; SANE_Byte wid[2]; /* scanner supports up to 2 windows */ } scan; SANE_Status status; DBG (DBG_proc, ">> trigger scan\n"); memset (&scan, 0, sizeof (scan)); /* CLEAR scan */ scan.cmd.opcode = HS2P_SCSI_START_SCAN; /* Transfer length is the byte length of Window List transferred * Window List is a list of Window Identifier created by SET WINDOW command * Since only 1 Window is supported by SCAN command, 0 or 1 is used for Window Identifier * and 1 or 2 for length status = sanei_scsi_cmd (s->fd, &trigger, sizeof (trigger), &window_id_list[0], &wl_size); */ scan.cmd.len = (s->val[OPT_DUPLEX].w == SANE_TRUE) ? 2 : 1; DBG (DBG_info, "trigger_scan: sending %d Window Id to scanner\n", scan.cmd.len); status = sanei_scsi_cmd (s->fd, &scan, sizeof (scan.cmd) + scan.cmd.len, NULL, NULL); DBG (DBG_proc, "<< trigger scan\n"); return (status); } #define MAX_WAITING_TIME 15 static SANE_Status hs2p_wait_ready (HS2P_Scanner * s) { STATUS_DATA dbs; /* Status Buffer Status DATA */ time_t now, start; SANE_Status status; start = time (NULL); while (1) { status = get_data_status (s->fd, &dbs); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG (DBG_error, "scsi_wait_ready: get datat status failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: now = time (NULL); if (now - start >= MAX_WAITING_TIME) { DBG (DBG_error, "hs2p_wait_ready: timed out after %lu seconds\n", (u_long) (now - start)); return SANE_STATUS_INVAL; } break; case SANE_STATUS_GOOD: DBG (DBG_proc, "hs2p_wait_ready: %d bytes ready\n", _3btol (dbs.filled)); return status; break; } usleep (1000000); /* retry after 100ms */ } return SANE_STATUS_INVAL; } /* MODE PAGES GET/SET */ static SANE_Status connection_parameters (int fd, MP_CXN * settings, SANE_Bool flag) { SANE_Status status; MP_CXN buf; size_t nbytes; DBG (DBG_proc, ">> connection_parameters\n"); nbytes = sizeof (buf); if (flag) { /* GET */ DBG (DBG_info, ">> GET connection_parameters >> calling mode_sense\n"); status = mode_sense (fd, (MP *) & buf, (SANE_Byte) PAGE_CODE_CONNECTION); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_connection_parameters: MODE_SELECT failed with status=%d\n", status); return (status); } memcpy (settings, &buf, nbytes); } else { /* SET */ DBG (DBG_info, ">> SET connection_parameters >> calling mode_select\n"); /* Fill in struct then hand off to mode_select */ memset (&buf, 0, sizeof (buf)); /* Fill struct with zeros */ memcpy (&buf, settings, nbytes); /* Make sure calling function didn't change these bytes */ memset (&buf.hdr, 0, sizeof (buf.hdr)); /* Make sure 4bytes are 0 */ buf.code = PAGE_CODE_CONNECTION; /* bits5-0: Page Code 02H */ buf.code &= ~(1 << 7); /* Bit7 PS is set to 0 */ buf.len = 0x0E; /* This is the only page with 14 bytes */ status = mode_select (fd, (MP *) & buf); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "set_connection_parameters: MODE_SELECT failed with status=%d\n", status); return (-1); } } DBG (DBG_proc, "<< connection_parameters\n"); return (status); } static SANE_Status get_basic_measurement_unit (int fd, SANE_Int * bmu, SANE_Int * mud) { SANE_Status status; MP_SMU buf; DBG (DBG_proc, ">> get_basic_measurement_unit: fd=\"%d\"\n", fd); status = mode_sense (fd, (MP *) & buf, (SANE_Byte) PAGE_CODE_SCANNING_MEASUREMENTS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "set_basic_measurement_unit: MODE_SELECT failed with status=%d\n", status); return (SANE_STATUS_INVAL); } *bmu = buf.bmu; *mud = ((buf.mud[0] << 8) | buf.mud[1]); DBG (DBG_proc, "<< get_basic_measurement_unit: bmu=%d mud=%d\n", *bmu, *mud); return (status); } static SANE_Status set_basic_measurement_unit (int fd, SANE_Byte bmu) { MP_SMU buf; /* Mode Page Scanning Measurements Page Code */ SANE_Status status; SANE_Int mud; size_t bufsize = sizeof (buf); DBG (DBG_proc, ">> set_basic_measurement_unit: %d\n", bmu); /* Set up buf */ memset (&buf, 0, bufsize); /* CLEAR buf */ buf.code = PAGE_CODE_SCANNING_MEASUREMENTS; /* bits5-0: Page Code */ buf.code &= ~(1 << 7); /* Bit7 PS is set to 0 */ buf.len = 0x06; buf.bmu = bmu; /* Power on default is POINTS */ mud = (bmu == INCHES) ? DEFAULT_MUD : 1; DBG (DBG_info, "SET_BASIC_MEASUREMENT_UNIT: bmu=%d mud=%d\n", bmu, mud); _lto2b (mud, &buf.mud[0]); /* buf.mud[0] = (mud >> 8) & 0xff; buf.mud[1] = (mud & 0xff); */ status = mode_select (fd, (MP *) & buf); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "set_basic_measurement_unit: MODE_SELECT failed with status=%d\n", status); status = SANE_STATUS_INVAL; } DBG (DBG_proc, "<< set_basic_measurement_unit: opcode=%d len=%d bmu=%d mud=%ld\n", buf.code, buf.len, buf.bmu, _2btol (&buf.mud[0])); return (status); } static SANE_Status adf_control (int fd, SANE_Bool flag, SANE_Byte * adf_control, SANE_Byte * adf_mode, SANE_Byte * mwt) { SANE_Status status; MP_ADF buf; size_t bufsize = sizeof (buf); DBG (DBG_proc, ">> adf_control\n"); memset (&buf, 0, bufsize); /* Fill struct with zeros */ if (flag) { /* GET */ DBG (DBG_info, ">> GET ADF_control>> calling mode_sense\n"); status = mode_sense (fd, (MP *) & buf, (SANE_Byte) PAGE_CODE_ADF_CONTROL); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_adf_control: MODE_SELECT failed\n"); return (status); } *adf_control = buf.adf_control; *adf_mode = buf.adf_mode_control; *mwt = buf.medium_wait_timer; } else { /* SET */ /* Fill in struct then hand off to mode_select */ buf.code = PAGE_CODE_ADF_CONTROL; /* bits5-0: Page Code */ buf.code &= ~(1 << 7); /* Bit7 PS is set to 0 */ buf.len = 0x06; /* Byte2: adf_control: 7-2:reserved; 1-0:adf_control: Default 00H Flatbed, 01H Simplex, 02H Duplex */ /* Byte3: adf_mode_control: 7-3:reserved; 2: Prefeed Mode: 0 invalid, 1 valid; 1-0: ignored */ /* Byte4: medium_wait_timer: timeout period. Not supported */ buf.adf_control = (*adf_control & 0x03); buf.adf_mode_control = (*adf_mode & 0x04); buf.medium_wait_timer = *mwt; status = mode_select (fd, (MP *) & buf); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "set_adf_control: MODE_SELECT failed with status=%d\n", status); return (status); } } DBG (DBG_proc, ">> adf_control\n"); return (status); } static SANE_Status white_balance (int fd, int *val, SANE_Bool flag) { SANE_Status status; MP_WhiteBal buf; /* White Balance Page Code */ size_t bufsize = sizeof (buf); memset (&buf, 0, bufsize); if (flag) { /* GET */ DBG (DBG_proc, ">> GET white_balance>> calling mode_sense\n"); status = mode_sense (fd, (MP *) & buf, (SANE_Byte) PAGE_CODE_WHITE_BALANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_white_balance: MODE_SELECT failed with status=%d\n", status); return (status); } *val = buf.white_balance; } else { /* SET */ /* Fill in struct then hand off to mode_select */ memset (&buf, 0, sizeof (buf)); /* Fill struct with zeros */ buf.code = PAGE_CODE_WHITE_BALANCE; /* bits5-0: Page Code */ buf.code &= ~(1 << 7); /* Bit7 PS is set to 0 */ buf.len = 0x06; buf.white_balance = *val; /* Power on default is RELATIVE_WHITE */ status = mode_select (fd, (MP *) & buf); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "set_white_balance: MODE_SELECT failed with status=%d\n", status); return (status); } } DBG (DBG_proc, "<< white balance: buf.white_balance=%#02x\n", buf.white_balance); return (status); } #if 0 static SANE_Int lamp_timer (int fd, int val, SANE_Bool flag) { SANE_Status status; MP_LampTimer buf; /* Lamp Timer Page Code */ DBG (DBG_proc, ">> lamp timer\n"); if (flag) { /* GET */ DBG (DBG_info, ">> GET lamp_timer>> calling mode_sense\n"); if ((status = mode_sense (fd, (MP *) & buf, (SANE_Byte) PAGE_CODE_LAMP_TIMER_SET)) != SANE_STATUS_GOOD) { DBG (DBG_error, "get_lamp_timer: MODE_SELECT failed\n"); return (-1); } } else { /* SET */ /* Fill in struct then hand off to mode_select */ memset (&buf, 0, sizeof (buf)); /* Fill struct with zeros */ buf.code = PAGE_CODE_LAMP_TIMER_SET; /* bits5-0: Page Code */ buf.code &= ~(1 << 7); /* Bit7 PS is set to 0 */ buf.len = 0x06; buf.time_on = val; /* time lamp has been on */ if ((status = mode_select (fd, (MP *) & buf)) != SANE_STATUS_GOOD) { DBG (DBG_error, "set_lamp_timer: MODE_SELECT failed with status=%d\n", status); return (-1); } } DBG (DBG_proc, "<< lamp timer\n"); return (buf.time_on); } #endif static SANE_Status endorser_control (int fd, int *val, SANE_Bool flag) { SANE_Status status; MP_EndCtrl buf; /* MPHdr (4bytes) + MPP (8bytes) */ SANE_Byte mask = 0x7; /* 7-3:reserved; 2-0: Endorser Control */ size_t bufsize = sizeof (buf); DBG (DBG_proc, ">> endorser_control: fd=%d val=%d flag=%d\n", fd, *val, flag); memset (&buf, 0, bufsize); /* Fill struct with zeros */ if (flag) { /* GET */ DBG (DBG_info, ">> GET endorser control >> calling mode_sense\n"); status = mode_sense (fd, (MP *) & buf, (SANE_Byte) PAGE_CODE_ENDORSER_CONTROL); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_endorser_control: MODE_SELECT failed with status=%d\n", status); return (status); } *val = buf.endorser_control & mask; } else { /* SET */ DBG (DBG_info, ">> SET endorser control >> calling mode_select\n"); /* Fill in struct then hand off to mode_select */ memset (&buf, 0, sizeof (buf)); /* Fill struct with zeros */ buf.code = PAGE_CODE_ENDORSER_CONTROL; /* bits5-0: Page Code */ buf.code &= ~(1 << 7); /* Bit7 PS is set to 0 */ buf.len = 0x06; buf.endorser_control = *val & mask; /* Power on default is OFF */ status = mode_select (fd, (MP *) & buf); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "set_endorser_control: MODE_SELECT failed with status=%d\n", status); return (status); } } DBG (DBG_proc, "<< endorser_control: endorser_control=%#02x\n", buf.endorser_control); return (status); } /* When SCAN, READ, or LOAD (in ADF mode) is issued, scanner waits until operator panel start button is pressed */ static SANE_Status scan_wait_mode (int fd, int val, SANE_Bool flag) { SANE_Status status; MP_SWM buf; /* Scan Wait Mode Page Code */ DBG (DBG_proc, ">> scan_wait_mode\n"); if (flag) { /* GET */ DBG (DBG_info, ">> GET scan_wait_mode >> calling mode_sense\n"); status = mode_sense (fd, (MP *) & buf, (SANE_Byte) PAGE_CODE_SCAN_WAIT_MODE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_scan_wait_mode: MODE_SELECT failed with status=%d\n", status); return (-1); } } else { /* SET */ /* Fill in struct then hand off to mode_select */ memset (&buf, 0, sizeof (buf)); /* Fill struct with zeros */ buf.code = PAGE_CODE_SCAN_WAIT_MODE; /* bits5-0: Page Code */ buf.code &= ~(1 << 7); /* Bit7 PS is set to 0 */ buf.len = 0x06; buf.swm = 0x00; if (val == 1) buf.swm |= 1; /* set bit 1 if scan_wait_mode ON */ else buf.swm &= ~1; /* unset bit 1 if scan_wait_mode OFF */ DBG (DBG_info, ">> SET scan_wait_mode >> calling mode_sense\n"); if ((status = mode_select (fd, (MP *) & buf)) != SANE_STATUS_GOOD) { DBG (DBG_error, "mode_select ERROR %s\n", sane_strstatus (status)); } } DBG (DBG_proc, "<< scan_wait_mode: buf.swm=%#02x\n", buf.swm); return (status); } /* Selectable when Send Diagnostics command is performed */ static SANE_Int service_mode (int fd, int val, SANE_Bool flag) { SANE_Status status; MP_SRV buf; /* Service Mode Page Code */ DBG (DBG_proc, ">> service_mode\n"); if (flag) { /* GET */ DBG (DBG_info, ">> GET service_mode >> calling mode_sense\n"); status = mode_sense (fd, (MP *) & buf, (SANE_Byte) PAGE_CODE_SERVICE_MODE_SELECT); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_service_mode: MODE_SELECT failed with status=%d\n", status); return (-1); } } else { /* SET */ /* Fill in struct then hand off to mode_select */ memset (&buf, 0, sizeof (buf)); /* Fill struct with zeros */ buf.code = PAGE_CODE_SERVICE_MODE_SELECT; /* bits5-0: Page Code */ buf.code &= ~(1 << 7); /* Bit7 PS is set to 0 */ buf.len = 0x06; /* 0H: Self-Diagnostics Mode, 1H: Optical Adjustment Mode */ buf.service = val & 0x01; status = mode_select (fd, (MP *) & buf); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "set_service_mode: MODE_SELECT failed with status=%d\n", status); return (-1); } } DBG (DBG_proc, "<< service_mode\n"); return (buf.service & 0x01); } sane-backends-1.0.27/backend/genesys_gl846.c0000664000175000017500000030245412775312261015374 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2012-2013 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file * * This file handles GL846 and GL845 ASICs since they are really close to each other. */ #undef BACKEND_NAME #define BACKEND_NAME genesys_gl846 #include "genesys_gl846.h" /**************************************************************************** Low level function ****************************************************************************/ /* ------------------------------------------------------------------------ */ /* Read and write RAM, registers and AFE */ /* ------------------------------------------------------------------------ */ /** @brief read scanned data * Read in 0xeff0 maximum sized blocks. This read is done in 2 * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the * remainder. Read addr is always 0x10000000 with the memory layout setup. * @param dev device to read data from * @param addr address within ASIC memory space, unused but kept for API * @param data pointer where to store the read data * @param len size to read */ static SANE_Status gl846_bulk_read_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size, target, read, done; uint8_t outdata[8]; uint8_t *buffer; DBG (DBG_io, "gl846_bulk_read_data: requesting %lu bytes at addr=0x%02x\n", (u_long) len, addr); if (len == 0) return SANE_STATUS_GOOD; target = len; buffer = data; /* loop until computed data size is read */ while (target) { if (target > 0xeff0) { size = 0xeff0; } else { size = target; } /* hard coded 0x10000000 addr */ outdata[0] = 0; outdata[1] = 0; outdata[2] = 0; outdata[3] = 0x10; /* data size to transfer */ outdata[4] = (size & 0xff); outdata[5] = ((size >> 8) & 0xff); outdata[6] = ((size >> 16) & 0xff); outdata[7] = ((size >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, 0x00, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s failed while writing command: %s\n", __func__, sane_strstatus (status)); return status; } /* blocks must be multiple of 512 but not last block */ read = size; if (read >= 512) { read /= 512; read *= 512; } DBG (DBG_io2, "gl846_bulk_read_data: trying to read %lu bytes of data\n", (u_long) read); status = sanei_usb_read_bulk (dev->dn, buffer, &read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } done=read; DBG (DBG_io2, "gl846_bulk_read_data: %lu bytes of data read\n", (u_long) done); /* read less than 512 bytes remainder */ if (read < size) { read = size - read; DBG (DBG_io2, "gl846_bulk_read_data: trying to read %lu bytes of data\n", (u_long) read); status = sanei_usb_read_bulk (dev->dn, buffer+done, &read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } done=read; DBG (DBG_io2, "gl846_bulk_read_data: %lu bytes of data read\n", (u_long) done); } DBG (DBG_io2, "%s: read %lu bytes, %lu remaining\n", __func__, (u_long) size, (u_long) (target - size)); target -= size; buffer += size; } if (DBG_LEVEL >= DBG_data && dev->binary!=NULL) { fwrite(data, len, 1, dev->binary); } DBGCOMPLETED; return SANE_STATUS_GOOD; } /**************************************************************************** Mid level functions ****************************************************************************/ static SANE_Bool gl846_get_fast_feed_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG02); if (r && (r->value & REG02_FASTFED)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl846_get_filter_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_FILTER)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl846_get_lineart_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_LINEART)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl846_get_bitset_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_BITSET)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl846_get_gain4_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x06); if (r && (r->value & REG06_GAIN4)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl846_test_buffer_empty_bit (SANE_Byte val) { if (val & REG41_BUFEMPTY) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl846_test_motor_flag_bit (SANE_Byte val) { if (val & REG41_MOTORENB) return SANE_TRUE; return SANE_FALSE; } /** * compute the step multiplier used */ static int gl846_get_step_multiplier (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; int value = 1; r = sanei_genesys_get_address (regs, 0x9d); if (r != NULL) { value = (r->value & 0x0f)>>1; value = 1 << value; } DBG (DBG_io, "%s: step multiplier is %d\n", __func__, value); return value; } /** @brief sensor profile * search for the database of motor profiles and get the best one. Each * profile is at a specific dpihw. Use LiDE 110 table by default. * @param sensor_type sensor id * @param dpi hardware dpi for the scan * @return a pointer to a Sensor_Profile struct */ static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi) { unsigned int i; int idx; i=0; idx=-1; while(i=dpi && sensors[i].dpimodel->ccd_type, xres); return sensor->exposure; } /** @brief sensor specific settings */ static void gl846_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs, int dpi) { Genesys_Register_Set *r; Sensor_Profile *sensor; int dpihw, i; uint16_t exp; DBGSTART; dpihw=sanei_genesys_compute_dpihw(dev,dpi); for (i = 0x06; i < 0x0e; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); if (r) r->value = dev->sensor.regs_0x10_0x1d[i]; } for (i = 0; i < 9; i++) { r = sanei_genesys_get_address (regs, 0x52 + i); if (r) r->value = dev->sensor.regs_0x52_0x5e[i]; } /* set EXPDUMMY and CKxMAP */ dpihw=sanei_genesys_compute_dpihw(dev,dpi); sensor=get_sensor_profile(dev->model->ccd_type, dpihw); sanei_genesys_set_reg_from_set(regs,REG_EXPDMY,(uint8_t)((sensor->expdummy) & 0xff)); /* if no calibration has been done, set default values for exposures */ exp=dev->sensor.regs_0x10_0x1d[0]*256+dev->sensor.regs_0x10_0x1d[1]; if(exp==0) { exp=sensor->expr; } sanei_genesys_set_double(regs,REG_EXPR,exp); exp=dev->sensor.regs_0x10_0x1d[2]*256+dev->sensor.regs_0x10_0x1d[3]; if(exp==0) { exp=sensor->expg; } sanei_genesys_set_double(regs,REG_EXPG,exp); exp=dev->sensor.regs_0x10_0x1d[4]*256+dev->sensor.regs_0x10_0x1d[5]; if(exp==0) { exp=sensor->expb; } sanei_genesys_set_double(regs,REG_EXPB,exp); sanei_genesys_set_triple(regs,REG_CK1MAP,sensor->ck1map); sanei_genesys_set_triple(regs,REG_CK3MAP,sensor->ck3map); sanei_genesys_set_triple(regs,REG_CK4MAP,sensor->ck4map); /* order of the sub-segments */ dev->order=sensor->order; r = sanei_genesys_get_address (regs, 0x17); r->value = sensor->r17; DBGCOMPLETED; } /* returns the max register bulk size */ static int gl846_bulk_full_size (void) { return GENESYS_GL846_MAX_REGS; } /** @brief set all registers to default values . * This function is called only once at the beginning and * fills register startup values for registers reused across scans. * Those that are rarely modified or not modified are written * individually. * @param dev device structure holding register set to initialize */ static void gl846_init_registers (Genesys_Device * dev) { DBGSTART; memset (dev->reg, 0, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); SETREG (0x01,0x60); SETREG (0x02,0x38); SETREG (0x03,0x03); SETREG (0x04,0x22); SETREG (0x05,0x60); SETREG (0x06,0x10); SETREG (0x08,0x60); SETREG (0x09,0x00); SETREG (0x0a,0x00); SETREG (0x0b,0x8b); SETREG (0x0c,0x00); SETREG (0x0d,0x00); SETREG (0x10,0x00); SETREG (0x11,0x00); SETREG (0x12,0x00); SETREG (0x13,0x00); SETREG (0x14,0x00); SETREG (0x15,0x00); SETREG (0x16,0xbb); SETREG (0x17,0x13); SETREG (0x18,0x10); SETREG (0x19,0x2a); SETREG (0x1a,0x34); SETREG (0x1b,0x00); SETREG (0x1c,0x20); SETREG (0x1d,0x06); SETREG (0x1e,0xf0); SETREG (0x1f,0x01); SETREG (0x20,0x03); SETREG (0x21,0x10); SETREG (0x22,0x60); SETREG (0x23,0x60); SETREG (0x24,0x60); SETREG (0x25,0x00); SETREG (0x26,0x00); SETREG (0x27,0x00); SETREG (0x2c,0x00); SETREG (0x2d,0x00); SETREG (0x2e,0x80); SETREG (0x2f,0x80); SETREG (0x30,0x00); SETREG (0x31,0x00); SETREG (0x32,0x00); SETREG (0x33,0x00); SETREG (0x34,0x1f); SETREG (0x35,0x00); SETREG (0x36,0x40); SETREG (0x37,0x00); SETREG (0x38,0x2a); SETREG (0x39,0xf8); SETREG (0x3d,0x00); SETREG (0x3e,0x00); SETREG (0x3f,0x01); SETREG (0x52,0x02); SETREG (0x53,0x04); SETREG (0x54,0x06); SETREG (0x55,0x08); SETREG (0x56,0x0a); SETREG (0x57,0x00); SETREG (0x58,0x59); SETREG (0x59,0x31); SETREG (0x5a,0x40); SETREG (0x5e,0x1f); SETREG (0x5f,0x01); SETREG (0x60,0x00); SETREG (0x61,0x00); SETREG (0x62,0x00); SETREG (0x63,0x00); SETREG (0x64,0x00); SETREG (0x65,0x00); SETREG (0x67,0x7f); SETREG (0x68,0x7f); SETREG (0x69,0x01); SETREG (0x6a,0x01); SETREG (0x70,0x01); SETREG (0x71,0x00); SETREG (0x72,0x02); SETREG (0x73,0x01); SETREG (0x74,0x00); SETREG (0x75,0x00); SETREG (0x76,0x00); SETREG (0x77,0x00); SETREG (0x78,0x00); SETREG (0x79,0x3f); SETREG (0x7a,0x00); SETREG (0x7b,0x09); SETREG (0x7c,0x99); SETREG (0x7d,0x20); SETREG (0x7f,0x05); SETREG (0x80,0x4f); SETREG (0x87,0x02); SETREG (0x94,0xff); SETREG (0x9d,0x04); SETREG (0x9e,0x00); SETREG (0xa1,0xe0); SETREG (0xa2,0x1f); SETREG (0xab,0xc0); SETREG (0xbb,0x00); SETREG (0xbc,0x0f); SETREG (0xdb,0xff); SETREG (0xfe,0x08); SETREG (0xff,0x02); SETREG (0x98,0x20); SETREG (0x99,0x00); SETREG (0x9a,0x90); SETREG (0x9b,0x00); SETREG (0xf8,0x05); /* fine tune upon device description */ dev->reg[reg_0x05].value &= ~REG05_DPIHW; switch (dev->sensor.optical_res) { case 600: dev->reg[reg_0x05].value |= REG05_DPIHW_600; break; case 1200: dev->reg[reg_0x05].value |= REG05_DPIHW_1200; break; case 2400: dev->reg[reg_0x05].value |= REG05_DPIHW_2400; break; case 4800: dev->reg[reg_0x05].value |= REG05_DPIHW_4800; break; } /* initalize calibration reg */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); DBGCOMPLETED; } /**@brief send slope table for motor movement * Send slope_table in machine byte order * @param dev device to send slope table * @param table_nr index of the slope table in ASIC memory * Must be in the [0-4] range. * @param slope_table pointer to 16 bit values array of the slope table * @param steps number of elements in the slope table */ static SANE_Status gl846_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps) { SANE_Status status; uint8_t *table; int i; char msg[10000]; DBG (DBG_proc, "%s (table_nr = %d, steps = %d)\n", __func__, table_nr, steps); /* sanity check */ if(table_nr<0 || table_nr>4) { DBG (DBG_error, "%s: invalid table number %d!\n", __func__, table_nr); return SANE_STATUS_INVAL; } table = (uint8_t *) malloc (steps * 2); for (i = 0; i < steps; i++) { table[i * 2] = slope_table[i] & 0xff; table[i * 2 + 1] = slope_table[i] >> 8; } if (DBG_LEVEL >= DBG_io) { sprintf (msg, "write slope %d (%d)=", table_nr, steps); for (i = 0; i < steps; i++) { sprintf (msg+strlen(msg), "%d", slope_table[i]); } DBG (DBG_io, "%s: %s\n", __func__, msg); } /* slope table addresses are fixed */ status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, 0x10000000 + 0x4000 * table_nr, steps * 2, table); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: write to AHB failed writing slope table %d (%s)\n", __func__, table_nr, sane_strstatus (status)); } free (table); DBGCOMPLETED; return status; } /** * Set register values of Analog Device type frontend * */ static SANE_Status gl846_set_adi_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status = SANE_STATUS_GOOD; int i; uint16_t val; uint8_t val8; DBGSTART; /* wait for FE to be ready */ status = sanei_genesys_get_status (dev, &val8); while (val8 & REG41_FEBUSY) { usleep (10000); status = sanei_genesys_get_status (dev, &val8); }; if (set == AFE_INIT) { DBG (DBG_proc, "%s(): setting DAC %u\n", __func__, dev->model->dac_type); /* sets to default values */ sanei_genesys_init_fe (dev); } /* write them to analog frontend */ val = dev->frontend.reg[0]; status = sanei_genesys_fe_write_data (dev, 0x00, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write reg0: %s\n", __func__, sane_strstatus (status)); return status; } val = dev->frontend.reg[1]; status = sanei_genesys_fe_write_data (dev, 0x01, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write reg1: %s\n", __func__, sane_strstatus (status)); return status; } for (i = 0; i < 3; i++) { val = dev->frontend.gain[i]; status = sanei_genesys_fe_write_data (dev, 0x02 + i, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write gain %d: %s\n", __func__, i, sane_strstatus (status)); return status; } } for (i = 0; i < 3; i++) { val = dev->frontend.offset[i]; status = sanei_genesys_fe_write_data (dev, 0x05 + i, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write offset %d: %s\n", __func__, i, sane_strstatus (status)); return status; } } DBGCOMPLETED; return status; } static SANE_Status gl846_homsnr_gpio(Genesys_Device *dev) { uint8_t val; SANE_Status status=SANE_STATUS_GOOD; RIE (sanei_genesys_read_register (dev, REG6C, &val)); val |= 0x41; RIE (sanei_genesys_write_register (dev, REG6C, val)); return status; } /* Set values of analog frontend */ static SANE_Status gl846_set_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status; DBG(DBG_proc, "gl846_set_fe (%s)\n", set == AFE_INIT ? "init" : set == AFE_SET ? "set" : set == AFE_POWER_SAVE ? "powersave" : "huh?"); /* route to specific analog frontend setup */ switch (dev->reg[reg_0x04].value & REG04_FESET) { case 0x02: /* ADI FE */ status = gl846_set_adi_fe(dev, set); break; default: DBG(DBG_proc, "gl846_set_fe(): unsupported frontend type %d\n", dev->reg[reg_0x04].value & REG04_FESET); status = SANE_STATUS_UNSUPPORTED; } DBGCOMPLETED; return status; } /** @brief set up motor related register for scan */ static SANE_Status gl846_init_motor_regs_scan (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int scan_exposure_time, float scan_yres, int scan_step_type, unsigned int scan_lines, unsigned int scan_dummy, unsigned int feed_steps, int scan_power_mode, unsigned int flags) { SANE_Status status; int use_fast_fed; unsigned int fast_dpi; uint16_t scan_table[SLOPE_TABLE_SIZE]; uint16_t fast_table[SLOPE_TABLE_SIZE]; int scan_steps, fast_steps, factor; unsigned int feedl, dist; Genesys_Register_Set *r; uint32_t z1, z2; unsigned int min_restep = 0x20; uint8_t val; int fast_step_type; unsigned int ccdlmt,tgtime; DBGSTART; DBG (DBG_proc, "gl846_init_motor_regs_scan : scan_exposure_time=%d, " "scan_yres=%g, scan_step_type=%d, scan_lines=%d, scan_dummy=%d, " "feed_steps=%d, scan_power_mode=%d, flags=%x\n", scan_exposure_time, scan_yres, scan_step_type, scan_lines, scan_dummy, feed_steps, scan_power_mode, flags); /* get step multiplier */ factor = gl846_get_step_multiplier (reg); use_fast_fed=0; /* no fast fed since feed works well */ if(dev->settings.yres==4444 && feed_steps>100 && ((flags & MOTOR_FLAG_FEED)==0)) { use_fast_fed=1; } DBG (DBG_io, "%s: use_fast_fed=%d\n", __func__, use_fast_fed); sanei_genesys_set_triple(reg, REG_LINCNT, scan_lines); DBG (DBG_io, "%s: lincnt=%d\n", __func__, scan_lines); /* compute register 02 value */ r = sanei_genesys_get_address (reg, REG02); r->value = 0x00; r->value |= REG02_MTRPWR; if (use_fast_fed) r->value |= REG02_FASTFED; else r->value &= ~REG02_FASTFED; if (flags & MOTOR_FLAG_AUTO_GO_HOME) r->value |= REG02_AGOHOME | REG02_NOTHOME; if ((flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE) ||(scan_yres>=dev->sensor.optical_res)) { r->value |= REG02_ACDCDIS; } /* scan and backtracking slope table */ sanei_genesys_slope_table(scan_table, &scan_steps, scan_yres, scan_exposure_time, dev->motor.base_ydpi, scan_step_type, factor, dev->model->motor_type, gl846_motors); RIE(gl846_send_slope_table (dev, SCAN_TABLE, scan_table, scan_steps*factor)); RIE(gl846_send_slope_table (dev, BACKTRACK_TABLE, scan_table, scan_steps*factor)); /* fast table */ fast_dpi=sanei_genesys_get_lowest_ydpi(dev); fast_step_type=scan_step_type; if(scan_step_type>=2) { fast_step_type=2; } sanei_genesys_slope_table(fast_table, &fast_steps, fast_dpi, scan_exposure_time, dev->motor.base_ydpi, fast_step_type, factor, dev->model->motor_type, gl846_motors); /* manual override of high start value */ fast_table[0]=fast_table[1]; RIE(gl846_send_slope_table (dev, STOP_TABLE, fast_table, fast_steps*factor)); RIE(gl846_send_slope_table (dev, FAST_TABLE, fast_table, fast_steps*factor)); RIE(gl846_send_slope_table (dev, HOME_TABLE, fast_table, fast_steps*factor)); /* correct move distance by acceleration and deceleration amounts */ feedl=feed_steps; if (use_fast_fed) { feedl<<=fast_step_type; dist=(scan_steps+2*fast_steps)*factor; /* TODO read and decode REGAB */ r = sanei_genesys_get_address (reg, 0x5e); dist += (r->value & 31); /* FEDCNT */ r = sanei_genesys_get_address (reg, REG_FEDCNT); dist += r->value; } else { feedl<<=scan_step_type; dist=scan_steps*factor; if (flags & MOTOR_FLAG_FEED) dist *=2; } DBG (DBG_io2, "%s: scan steps=%d\n", __func__, scan_steps); DBG (DBG_io2, "%s: acceleration distance=%d\n", __func__, dist); /* check for overflow */ if(distvalue & REG0C_CCDLMT)+1; r = sanei_genesys_get_address (reg, REG1C); tgtime=1<<(r->value & REG1C_TGTIME); /* hi res motor speed GPIO */ /* RIE (sanei_genesys_read_register (dev, REG6C, &effective)); */ /* if quarter step, bipolar Vref2 */ /* XXX STEF XXX GPIO if (scan_step_type > 1) { if (scan_step_type < 3) { val = effective & ~REG6C_GPIO13; } else { val = effective | REG6C_GPIO13; } } else { val = effective; } RIE (sanei_genesys_write_register (dev, REG6C, val)); */ /* effective scan */ /* RIE (sanei_genesys_read_register (dev, REG6C, &effective)); val = effective | REG6C_GPIO10; RIE (sanei_genesys_write_register (dev, REG6C, val)); */ if(dev->model->gpo_type==GPO_IMG101) { if(scan_yres==sanei_genesys_compute_dpihw(dev,scan_yres)) { val=1; } else { val=0; } RIE (sanei_genesys_write_register (dev, REG7E, val)); } min_restep=scan_steps/2-1; if (min_restep < 1) min_restep = 1; r = sanei_genesys_get_address (reg, REG_FWDSTEP); r->value = min_restep; r = sanei_genesys_get_address (reg, REG_BWDSTEP); r->value = min_restep; sanei_genesys_calculate_zmode2(use_fast_fed, scan_exposure_time*ccdlmt*tgtime, scan_table, scan_steps*factor, feedl, min_restep*factor, &z1, &z2); DBG (DBG_info, "gl846_init_motor_regs_scan: z1 = %d\n", z1); sanei_genesys_set_triple(reg, REG60, z1 | (scan_step_type << (16+REG60S_STEPSEL))); DBG (DBG_info, "gl846_init_motor_regs_scan: z2 = %d\n", z2); sanei_genesys_set_triple(reg, REG63, z2 | (scan_step_type << (16+REG63S_FSTPSEL))); r = sanei_genesys_get_address (reg, 0x1e); r->value &= 0xf0; /* 0 dummy lines */ r->value |= scan_dummy; /* dummy lines */ r = sanei_genesys_get_address (reg, REG67); r->value = 0x7f; r = sanei_genesys_get_address (reg, REG68); r->value = 0x7f; r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = scan_steps; r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = scan_steps; r = sanei_genesys_get_address (reg, REG_FSHDEC); r->value = scan_steps; r = sanei_genesys_get_address (reg, REG_FMOVNO); r->value = fast_steps; r = sanei_genesys_get_address (reg, REG_FMOVDEC); r->value = fast_steps; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief set up registers related to sensor * Set up the following registers 0x01 0x03 0x10-0x015 R/G/B exposures 0x19 EXPDMY 0x2e BWHI 0x2f BWLO 0x04 0x87 0x05 0x2c,0x2d DPISET 0x30,0x31 STRPIXEL 0x32,0x33 ENDPIXEL 0x35,0x36,0x37 MAXWD [25:2] (>>2) 0x38,0x39 LPERIOD 0x34 DUMMY */ static SANE_Status gl846_init_optical_regs_scan (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int exposure_time, int used_res, unsigned int start, unsigned int pixels, int channels, int depth, SANE_Bool half_ccd, int color_filter, int flags) { unsigned int words_per_line; unsigned int startx, endx, used_pixels; unsigned int dpiset, dpihw,segnb,cksel,factor; unsigned int bytes; Genesys_Register_Set *r; SANE_Status status; Sensor_Profile *sensor; DBG (DBG_proc, "gl846_init_optical_regs_scan : exposure_time=%d, " "used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, " "half_ccd=%d, flags=%x\n", exposure_time, used_res, start, pixels, channels, depth, half_ccd, flags); /* resolution is divided according to CKSEL */ r = sanei_genesys_get_address (reg, REG18); cksel= (r->value & REG18_CKSEL)+1; DBG (DBG_io2, "%s: cksel=%d\n", __func__, cksel); /* to manage high resolution device while keeping good * low resolution scanning speed, we make hardware dpi vary */ dpihw=sanei_genesys_compute_dpihw(dev, used_res * cksel); factor=dev->sensor.optical_res/dpihw; DBG (DBG_io2, "%s: dpihw=%d (factor=%d)\n", __func__, dpihw, factor); /* sensor parameters */ sensor=get_sensor_profile(dev->model->ccd_type, dpihw); gl846_setup_sensor (dev, reg, dpihw); dpiset = used_res * cksel; /* start and end coordinate in optical dpi coordinates */ startx = start/cksel+dev->sensor.CCD_start_xoffset; used_pixels=pixels/cksel; /* end of sensor window */ endx = startx + used_pixels; /* sensors are built from 600 dpi segments for LiDE 100/200 * and 1200 dpi for the 700F */ if (dev->model->flags & GENESYS_FLAG_SIS_SENSOR) { segnb=dpihw/600; } else { segnb=1; } /* compute pixel coordinate in the given dpihw space, * taking segments into account */ startx/=factor*segnb; endx/=factor*segnb; dev->len=endx-startx; dev->dist=0; dev->skip=0; /* in cas of multi-segments sensor, we have to add the witdh * of the sensor crossed by the scan area */ if (dev->model->flags & GENESYS_FLAG_SIS_SENSOR && segnb>1) { dev->dist = sensor->segcnt; } /* use a segcnt rounded to next even number */ endx += ((dev->dist+1)&0xfffe)*(segnb-1); used_pixels=endx-startx; status = gl846_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_init_optical_regs_scan: failed to set frontend: %s\n", sane_strstatus (status)); return status; } /* enable shading */ r = sanei_genesys_get_address (reg, REG01); r->value &= ~REG01_SCAN; r->value |= REG01_SHDAREA; if ((flags & OPTICAL_FLAG_DISABLE_SHADING) || (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) { r->value &= ~REG01_DVDSET; } else { r->value |= REG01_DVDSET; } r = sanei_genesys_get_address (reg, REG03); r->value &= ~REG03_AVEENB; if (flags & OPTICAL_FLAG_DISABLE_LAMP) r->value &= ~REG03_LAMPPWR; else r->value |= REG03_LAMPPWR; /* BW threshold */ r = sanei_genesys_get_address (reg, 0x2e); r->value = dev->settings.threshold; r = sanei_genesys_get_address (reg, 0x2f); r->value = dev->settings.threshold; /* monochrome / color scan */ r = sanei_genesys_get_address (reg, REG04); switch (depth) { case 1: r->value &= ~REG04_BITSET; r->value |= REG04_LINEART; break; case 8: r->value &= ~(REG04_LINEART | REG04_BITSET); break; case 16: r->value &= ~REG04_LINEART; r->value |= REG04_BITSET; break; } r->value &= ~(REG04_FILTER | REG04_AFEMOD); if (channels == 1) { switch (color_filter) { case 0: r->value |= 0x24; /* red filter */ break; case 2: r->value |= 0x2c; /* blue filter */ break; default: r->value |= 0x28; /* green filter */ break; } } else r->value |= 0x20; /* mono */ /* register 05 */ r = sanei_genesys_get_address (reg, REG05); /* set up dpihw */ r->value &= ~REG05_DPIHW; switch(dpihw) { case 600: r->value |= REG05_DPIHW_600; break; case 1200: r->value |= REG05_DPIHW_1200; break; case 2400: r->value |= REG05_DPIHW_2400; break; case 4800: r->value |= REG05_DPIHW_4800; break; } /* enable gamma tables */ if (flags & OPTICAL_FLAG_DISABLE_GAMMA) r->value &= ~REG05_GMMENB; else r->value |= REG05_GMMENB; /* CIS scanners can do true gray by setting LEDADD */ /* we set up LEDADD only when asked */ if (dev->model->is_cis == SANE_TRUE) { r = sanei_genesys_get_address (reg, 0x87); r->value &= ~REG87_LEDADD; if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) { r->value |= REG87_LEDADD; } /* RGB weighting r = sanei_genesys_get_address (reg, 0x01); r->value &= ~REG01_TRUEGRAY; if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) { r->value |= REG01_TRUEGRAY; }*/ } /* words(16bit) before gamma, conversion to 8 bit or lineart*/ words_per_line = (used_pixels * dpiset) / dpihw; bytes=depth/8; if (depth == 1) { words_per_line = (words_per_line+7)/8 ; dev->len = (dev->len >> 3) + ((dev->len & 7) ? 1 : 0); dev->dist = (dev->dist >> 3) + ((dev->dist & 7) ? 1 : 0); } else { words_per_line *= bytes; dev->dist *= bytes; dev->len *= bytes; } dev->bpl = words_per_line; dev->cur=0; dev->segnb=segnb; dev->line_interp = 0; sanei_genesys_set_double(reg,REG_DPISET,dpiset); DBG (DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset); sanei_genesys_set_double(reg,REG_STRPIXEL,startx); sanei_genesys_set_double(reg,REG_ENDPIXEL,endx); DBG (DBG_io2, "%s: startx=%d\n", __func__, startx); DBG (DBG_io2, "%s: endx =%d\n", __func__, endx); DBG (DBG_io2, "%s: used_pixels=%d\n", __func__, used_pixels); DBG (DBG_io2, "%s: pixels =%d\n", __func__, pixels); DBG (DBG_io2, "%s: depth =%d\n", __func__, depth); DBG (DBG_io2, "%s: dev->bpl =%lu\n", __func__, (unsigned long)dev->bpl); DBG (DBG_io2, "%s: dev->len =%lu\n", __func__, (unsigned long)dev->len); DBG (DBG_io2, "%s: dev->dist =%lu\n", __func__, (unsigned long)dev->dist); DBG (DBG_io2, "%s: dev->segnb =%lu\n", __func__, (unsigned long)dev->segnb); words_per_line *= channels; dev->wpl = words_per_line; if(dev->oe_buffer.buffer!=NULL) { sanei_genesys_buffer_free (&(dev->oe_buffer)); } RIE (sanei_genesys_buffer_alloc (&(dev->oe_buffer), dev->wpl)); /* MAXWD is expressed in 4 words unit */ sanei_genesys_set_triple(reg, REG_MAXWD, (words_per_line >> 2)); DBG (DBG_io2, "%s: words_per_line used=%d\n", __func__, words_per_line); sanei_genesys_set_double(reg, REG_LPERIOD, exposure_time); DBG (DBG_io2, "%s: exposure_time used=%d\n", __func__, exposure_time); r = sanei_genesys_get_address (reg, 0x34); r->value = dev->sensor.dummy_pixel; DBGCOMPLETED; return SANE_STATUS_GOOD; } /* set up registers for an actual scan * * this function sets up the scanner to scan in normal or single line mode */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ float yres, /*dpi */ float startx, /*optical_res, from dummy_pixel+1 */ float starty, /*base_ydpi, from home! */ float pixels, float lines, unsigned int depth, unsigned int channels, int color_filter, unsigned int flags) { int used_res; int start, used_pixels; int bytes_per_line; int move; unsigned int lincnt; unsigned int oflags; /**> optical flags */ unsigned int mflags; /**> motor flags */ int exposure_time; int stagger; int slope_dpi = 0; int dummy = 0; int scan_step_type = 1; int scan_power_mode = 0; int max_shift; size_t requested_buffer_size, read_buffer_size; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; SANE_Status status; DBG (DBG_info, "gl846_init_scan_regs settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g/%g\n" "Depth/Channels: %u/%u\n" "Flags : %x\n\n", xres, yres, lines, pixels, startx, starty, depth, channels, flags); /* we may have 2 domains for ccd: xres below or above half ccd max dpi */ if (dev->sensor.optical_res < 2 * xres || !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)) { half_ccd = SANE_FALSE; } else { half_ccd = SANE_TRUE; } /* optical_res */ optical_res = dev->sensor.optical_res; if (half_ccd) optical_res /= 2; /* stagger */ if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "gl846_init_scan_regs : stagger=%d lines\n", stagger); /* used_res */ if (flags & SCAN_FLAG_USE_OPTICAL_RES) { used_res = optical_res; } else { /* resolution is choosen from a list */ used_res = xres; } /* compute scan parameters values */ /* pixels are allways given at full optical resolution */ /* use detected left margin and fixed value */ /* start */ /* add x coordinates */ start = startx; if (stagger > 0) start |= 1; /* compute correct pixels number */ /* pixels */ used_pixels = (pixels * optical_res) / xres; /* round up pixels number if needed */ if (used_pixels * xres < pixels * optical_res) used_pixels++; dummy = 3-channels; /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ if (dev->model->is_cis) slope_dpi = yres * channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); exposure_time = gl846_compute_exposure (dev, used_res); scan_step_type = sanei_genesys_compute_step_type(gl846_motors, dev->model->motor_type, exposure_time); DBG (DBG_info, "gl846_init_scan_regs : exposure_time=%d pixels\n", exposure_time); DBG (DBG_info, "gl846_init_scan_regs : scan_step_type=%d\n", scan_step_type); /*** optical parameters ***/ /* in case of dynamic lineart, we use an internal 8 bit gray scan * to generate 1 lineart data */ if ((flags & SCAN_FLAG_DYNAMIC_LINEART) && (dev->settings.scan_mode == SCAN_MODE_LINEART)) { depth = 8; } /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ oflags = 0; if(flags & SCAN_FLAG_DISABLE_SHADING) oflags |= OPTICAL_FLAG_DISABLE_SHADING; if(flags & SCAN_FLAG_DISABLE_GAMMA) oflags |= OPTICAL_FLAG_DISABLE_GAMMA; if(flags & SCAN_FLAG_DISABLE_LAMP) oflags |= OPTICAL_FLAG_DISABLE_LAMP; if (dev->model->is_cis && dev->settings.true_gray) { oflags |= OPTICAL_FLAG_ENABLE_LEDADD; } status = gl846_init_optical_regs_scan (dev, reg, exposure_time, used_res, start, used_pixels, channels, depth, half_ccd, color_filter, oflags); if (status != SANE_STATUS_GOOD) return status; /*** motor parameters ***/ /* max_shift */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,flags); /* lincnt */ lincnt = lines + max_shift + stagger; /* add tl_y to base movement */ move = starty; DBG (DBG_info, "gl846_init_scan_regs: move=%d steps\n", move); mflags=0; if(flags & SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE) mflags |= MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE; if(flags & SCAN_FLAG_FEEDING) mflags |= MOTOR_FLAG_FEED; status = gl846_init_motor_regs_scan (dev, reg, exposure_time, slope_dpi, scan_step_type, dev->model->is_cis ? lincnt * channels : lincnt, dummy, move, scan_power_mode, mflags); if (status != SANE_STATUS_GOOD) return status; /*** prepares data reordering ***/ /* words_per_line */ bytes_per_line = (used_pixels * used_res) / optical_res; bytes_per_line = (bytes_per_line * channels * depth) / 8; requested_buffer_size = 8 * bytes_per_line; /* we must use a round number of bytes_per_line */ /* XXX STEF XXX if (requested_buffer_size > BULKIN_MAXSIZE) requested_buffer_size = (BULKIN_MAXSIZE / bytes_per_line) * bytes_per_line; */ read_buffer_size = 2 * requested_buffer_size + ((max_shift + stagger) * used_pixels * channels * depth) / 8; RIE (sanei_genesys_buffer_free (&(dev->read_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->lines_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer), requested_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->out_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer), (8 * dev->settings.pixels * channels * depth) / 8)); dev->read_bytes_left = bytes_per_line * lincnt; DBG (DBG_info, "gl846_init_scan_regs: physical bytes to read = %lu\n", (u_long) dev->read_bytes_left); dev->read_active = SANE_TRUE; dev->current_setup.pixels = (used_pixels * used_res) / optical_res; dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure_time; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; /* TODO: should this be done elsewhere? */ /* scan bytes to send to the frontend */ /* theory : target_size = (dev->settings.pixels * dev->settings.lines * channels * depth) / 8; but it suffers from integer overflow so we do the following: 1 bit color images store color data byte-wise, eg byte 0 contains 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains 8 bits of blue. This does not fix the overflow, though. 644mp*16 = 10gp, leading to an overflow -- pierre */ dev->total_bytes_read = 0; if (depth == 1) dev->total_bytes_to_read = ((dev->settings.pixels * dev->settings.lines) / 8 + (((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) * channels; else dev->total_bytes_to_read = dev->settings.pixels * dev->settings.lines * channels * (depth / 8); DBG (DBG_info, "gl846_init_scan_regs: total bytes to send = %lu\n", (u_long) dev->total_bytes_to_read); /* END TODO */ DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl846_calculate_current_setup (Genesys_Device * dev) { int channels; int depth; int start; float xres; /*dpi */ float yres; /*dpi */ float startx; /*optical_res, from dummy_pixel+1 */ float pixels; float lines; int used_res; int used_pixels; unsigned int lincnt; int exposure_time; int stagger; int slope_dpi; int dummy = 0; int max_shift; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; DBG (DBG_info, "gl846_calculate_current_setup settings:\n" "Resolution: %uDPI\n" "Lines : %u\n" "PPL : %u\n" "Startpos : %.3f/%.3f\n" "Scan mode : %d\n\n", dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* channels */ if (dev->settings.scan_mode == 4) /* single pass color */ channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == 0) depth = 1; /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; xres = dev->settings.xres; /*dpi */ yres = dev->settings.yres; /*dpi */ startx = start; /*optical_res, from dummy_pixel+1 */ pixels = dev->settings.pixels; lines = dev->settings.lines; DBG (DBG_info, "gl846_calculate_current_setup settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g\n" "Depth/Channels: %u/%u\n\n", xres, yres, lines, pixels, startx, depth, channels); /* half_ccd */ /* we have 2 domains for ccd: xres below or above half ccd max dpi */ if ((dev->sensor.optical_res < 2 * xres) || !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)) { half_ccd = SANE_FALSE; } else { half_ccd = SANE_TRUE; } /* optical_res */ optical_res = dev->sensor.optical_res; /* stagger */ if (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "gl846_calculate_current_setup: stagger=%d lines\n", stagger); /* resolution is choosen from a fixed list */ used_res = xres; /* compute scan parameters values */ /* pixels are allways given at half or full CCD optical resolution */ /* use detected left margin and fixed value */ /* compute correct pixels number */ used_pixels = (pixels * optical_res) / used_res; dummy = 3-channels; /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ if (dev->model->is_cis) slope_dpi = yres * channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); exposure_time = gl846_compute_exposure (dev, used_res); DBG (DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time); /* max_shift */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0); /* lincnt */ lincnt = lines + max_shift + stagger; dev->current_setup.pixels = (used_pixels * used_res) / optical_res; dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure_time; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; DBGCOMPLETED; return SANE_STATUS_GOOD; } static void gl846_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set) { DBG (DBG_proc, "gl846_set_motor_power\n"); if (set) { sanei_genesys_set_reg_from_set (regs, REG02, sanei_genesys_read_reg_from_set (regs, REG02) | REG02_MTRPWR); } else { sanei_genesys_set_reg_from_set (regs, REG02, sanei_genesys_read_reg_from_set (regs, REG02) & ~REG02_MTRPWR); } } static void gl846_set_lamp_power (Genesys_Device __sane_unused__ * dev, Genesys_Register_Set * regs, SANE_Bool set) { if (set) { sanei_genesys_set_reg_from_set (regs, REG03, sanei_genesys_read_reg_from_set (regs, REG03) | REG03_LAMPPWR); } else { sanei_genesys_set_reg_from_set (regs, REG03, sanei_genesys_read_reg_from_set (regs, REG03) & ~REG03_LAMPPWR); } } /*for fast power saving methods only, like disabling certain amplifiers*/ static SANE_Status gl846_save_power (Genesys_Device * dev, SANE_Bool enable) { DBG (DBG_proc, "gl846_save_power: enable = %d\n", enable); if (dev == NULL) return SANE_STATUS_INVAL; DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl846_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ ) { DBG (DBG_proc, "gl846_set_powersaving (delay = %d)\n", delay); if (dev == NULL) return SANE_STATUS_INVAL; DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl846_start_action (Genesys_Device * dev) { return sanei_genesys_write_register (dev, 0x0f, 0x01); } #ifndef UNIT_TESTING static #endif SANE_Status gl846_stop_action (Genesys_Device * dev) { SANE_Status status; uint8_t val40, val; unsigned int loop; DBGSTART; /* post scan gpio : without that HOMSNR is unreliable */ gl846_homsnr_gpio(dev); status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } status = sanei_genesys_read_register (dev, REG40, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* only stop action if needed */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)) { DBG (DBG_info, "%s: already stopped\n", __func__); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* ends scan */ val = sanei_genesys_read_reg_from_set (dev->reg, REG01); val &= ~REG01_SCAN; sanei_genesys_set_reg_from_set (dev->reg, REG01, val); status = sanei_genesys_write_register (dev, REG01, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write register 01: %s\n", __func__, sane_strstatus (status)); return status; } usleep (100 * 1000); loop = 10; while (loop > 0) { status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } status = sanei_genesys_read_register (dev, REG40, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* if scanner is in command mode, we are done */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG) && !(val & REG41_MOTORENB)) { DBGCOMPLETED; return SANE_STATUS_GOOD; } usleep (100 * 1000); loop--; } DBGCOMPLETED; return SANE_STATUS_IO_ERROR; } /* Send the low-level scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor) { SANE_Status status; uint8_t val; Genesys_Register_Set *r; DBGSTART; /* XXX STEF XXX SCAN GPIO */ /* RIE (sanei_genesys_read_register (dev, REG6C, &val)); RIE (sanei_genesys_write_register (dev, REG6C, val)); */ val = REG0D_CLRLNCNT; RIE (sanei_genesys_write_register (dev, REG0D, val)); val = REG0D_CLRMCNT; RIE (sanei_genesys_write_register (dev, REG0D, val)); RIE (sanei_genesys_read_register (dev, REG01, &val)); val |= REG01_SCAN; RIE (sanei_genesys_write_register (dev, REG01, val)); r = sanei_genesys_get_address (reg, REG01); r->value = val; if (start_motor) { RIE (sanei_genesys_write_register (dev, REG0F, 1)); } else { RIE (sanei_genesys_write_register (dev, REG0F, 0)); } DBGCOMPLETED; return status; } /* Send the stop scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop) { SANE_Status status; DBG (DBG_proc, "gl846_end_scan (check_stop = %d)\n", check_stop); if (reg == NULL) return SANE_STATUS_INVAL; if (dev->model->is_sheetfed == SANE_TRUE) { status = SANE_STATUS_GOOD; } else /* flat bed scanners */ { status = gl846_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_end_scan: failed to stop: %s\n", sane_strstatus (status)); return status; } } DBGCOMPLETED; return status; } /* Moves the slider to the home (top) postion slowly */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) { Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; float resolution; uint8_t val; int loop = 0; int scan_mode; DBG (DBG_proc, "gl846_slow_back_home (wait_until_home = %d)\n", wait_until_home); if(dev->usb_mode<0) { DBGCOMPLETED; return SANE_STATUS_GOOD; } /* post scan gpio : without that HOMSNR is unreliable */ gl846_homsnr_gpio(dev); /* first read gives HOME_SENSOR true */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } usleep (100000); /* sleep 100 ms */ /* second is reliable */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } /* is sensor at home? */ if (val & HOMESNR) { DBG (DBG_info, "%s: already at home, completed\n", __func__); dev->scanhead_position_in_steps = 0; DBGCOMPLETED; return SANE_STATUS_GOOD; } memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); /* TODO add scan_mode to the API */ scan_mode= dev->settings.scan_mode; dev->settings.scan_mode=SCAN_MODE_LINEART; status = gl846_init_scan_regs (dev, local_reg, resolution, resolution, 100, 30000, 100, 100, 8, 1, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_slow_back_home: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } dev->settings.scan_mode=scan_mode; /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); /* set up for reverse */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS)); status = gl846_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_slow_back_home: failed to start motor: %s\n", sane_strstatus (status)); gl846_stop_action (dev); /* send original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS); return status; } /* post scan gpio : without that HOMSNR is unreliable */ gl846_homsnr_gpio(dev); if (wait_until_home) { while (loop < 300) /* do not wait longer then 30 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (val & HOMESNR) /* home sensor */ { DBG (DBG_info, "gl846_slow_back_home: reached home position\n"); gl846_stop_action (dev); dev->scanhead_position_in_steps = 0; DBGCOMPLETED; return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ ++loop; } /* when we come here then the scanner needed too much time for this, so we better stop the motor */ gl846_stop_action (dev); DBG (DBG_error, "gl846_slow_back_home: timeout while waiting for scanhead to go home\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_info, "gl846_slow_back_home: scanhead is still moving\n"); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi from very top of scanner */ static SANE_Status gl846_search_start_position (Genesys_Device * dev) { int size; SANE_Status status; uint8_t *data; Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS]; int steps; int pixels = 600; int dpi = 300; DBG (DBG_proc, "gl846_search_start_position\n"); memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); /* sets for a 200 lines * 600 pixels */ /* normal scan with no shading */ status = gl846_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, /*we should give a small offset here~60 steps */ 600, dev->model->search_lines, 8, 1, 1, /*green */ SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_search_start_position: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } /* send to scanner */ status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_search_start_position: failed to bulk write registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } size = pixels * dev->model->search_lines; data = malloc (size); if (!data) { DBG (DBG_error, "gl846_search_start_position: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } status = gl846_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_start_position: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, pixels, dev->model->search_lines); status = gl846_end_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_start_position: failed to end scan: %s\n", sane_strstatus (status)); return status; } /* update regs to copy ASIC internal state */ memcpy (dev->reg, local_reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); /*TODO: find out where sanei_genesys_search_reference_point stores information, and use that correctly*/ status = sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels, dev->model->search_lines); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_start_position: failed to set search reference point: %s\n", sane_strstatus (status)); return status; } free (data); return SANE_STATUS_GOOD; } /* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status gl846_init_regs_for_coarse_calibration (Genesys_Device * dev) { SANE_Status status; uint8_t channels; uint8_t cksel; DBG (DBG_proc, "gl846_init_regs_for_coarse_calibration\n"); cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */ /* set line size */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; status = gl846_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, dev->sensor.optical_res / cksel, 20, 16, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_init_register_for_coarse_calibration: Failed to setup scan: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl846_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n", dev->sensor.optical_res / cksel, dev->settings.xres); status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_init_register_for_coarse_calibration: Failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief moves the slider to steps at motor base dpi * @param dev device to work on * @param steps number of steps to move in base_dpi line count * */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_feed (Genesys_Device * dev, unsigned int steps) { Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; float resolution; uint8_t val; DBGSTART; DBG (DBG_io, "%s: steps=%d\n", __func__, steps); /* prepare local registers */ memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); status = gl846_init_scan_regs (dev, local_reg, resolution, resolution, 0, steps, 100, 3, 8, 3, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_FEEDING | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_feed: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } /* set exposure to zero */ sanei_genesys_set_triple(local_reg,REG_EXPR,0); sanei_genesys_set_triple(local_reg,REG_EXPG,0); sanei_genesys_set_triple(local_reg,REG_EXPB,0); /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT)); RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT)); /* set up for no scan */ r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; /* send registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS)); status = gl846_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to start motor: %s\n", __func__, sane_strstatus (status)); gl846_stop_action (dev); /* restore original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS); return status; } /* wait until feed count reaches the required value, but do not * exceed 30s */ do { status = sanei_genesys_get_status (dev, &val); } while (status == SANE_STATUS_GOOD && !(val & FEEDFSH)); /* then stop scanning */ RIE(gl846_stop_action (dev)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* init registers for shading calibration */ static SANE_Status gl846_init_regs_for_shading (Genesys_Device * dev) { SANE_Status status; float move; DBGSTART; dev->calib_channels = 3; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); dev->calib_resolution = sanei_genesys_compute_dpihw(dev,dev->settings.xres); dev->calib_lines = dev->model->shading_lines; if(dev->calib_resolution==4800) dev->calib_lines *= 2; dev->calib_pixels = (dev->sensor.sensor_pixels*dev->calib_resolution)/dev->sensor.optical_res; DBG (DBG_io, "%s: calib_lines = %d\n", __func__, (unsigned int)dev->calib_lines); DBG (DBG_io, "%s: calib_pixels = %d\n", __func__, (unsigned int)dev->calib_pixels); /* this is aworkaround insufficent distance for slope * motor acceleration TODO special motor slope for shading */ move=1; if(dev->calib_resolution<1200) { move=40; } status = gl846_init_scan_regs (dev, dev->calib_reg, dev->calib_resolution, dev->calib_resolution, 0, move, dev->calib_pixels, dev->calib_lines, 16, dev->calib_channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __func__, sane_strstatus (status)); return status; } /* we use GENESYS_FLAG_SHADING_REPARK */ dev->scanhead_position_in_steps = 0; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief set up registers for the actual scan */ static SANE_Status gl846_init_regs_for_scan (Genesys_Device * dev) { int channels; int flags; int depth; float move; int move_dpi; float start; SANE_Status status; DBG (DBG_info, "gl846_init_regs_for_scan settings:\nResolution: %uDPI\n" "Lines : %u\nPPL : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n", dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* channels */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == SCAN_MODE_LINEART) depth = 1; /* steps to move to reach scanning area: - first we move to physical start of scanning either by a fixed steps amount from the black strip or by a fixed amount from parking position, minus the steps done during shading calibration - then we move by the needed offset whitin physical scanning area assumption: steps are expressed at maximum motor resolution we need: SANE_Fixed y_offset; SANE_Fixed y_size; SANE_Fixed y_offset_calib; mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */ /* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is relative from origin, else, it is from parking position */ move_dpi = dev->motor.base_ydpi; move = SANE_UNFIX (dev->model->y_offset); move += dev->settings.tl_y; move = (move * move_dpi) / MM_PER_INCH; move -= dev->scanhead_position_in_steps; DBG (DBG_info, "%s: move=%f steps\n",__func__, move); /* fast move to scan area */ /* we don't move fast the whole distance since it would involve * computing acceleration/deceleration distance for scan * resolution. So leave a remainder for it so scan makes the final * move tuning */ if(channels*dev->settings.yres>=600 && move>700) { status = gl846_feed (dev, move-500); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to move to scan area\n",__func__); return status; } move=500; } DBG (DBG_info, "gl846_init_regs_for_scan: move=%f steps\n", move); DBG (DBG_info, "%s: move=%f steps\n", __func__, move); /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; flags = 0; /* emulated lineart from gray data is required for now */ if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; } /* backtracking isn't handled well, so don't enable it */ flags |= SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE; status = gl846_init_scan_regs (dev, dev->reg, dev->settings.xres, dev->settings.yres, start, move, dev->settings.pixels, dev->settings.lines, depth, channels, dev->settings.color_filter, flags); if (status != SANE_STATUS_GOOD) return status; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * Send shading calibration data. The buffer is considered to always hold values * for all the channels. */ static SANE_Status gl846_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) { SANE_Status status = SANE_STATUS_GOOD; uint32_t addr, length, i, x, factor, pixels; uint32_t dpiset, dpihw, strpixel, endpixel; uint16_t tempo; uint32_t lines, channels; uint8_t val,*buffer,*ptr,*src; DBGSTART; DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__func__,size); /* shading data is plit in 3 (up to 5 with IR) areas write(0x10014000,0x00000dd8) URB 23429 bulk_out len 3544 wrote 0x33 0x10 0x.... write(0x1003e000,0x00000dd8) write(0x10068000,0x00000dd8) */ length = (uint32_t) (size / 3); sanei_genesys_get_double(dev->reg,REG_STRPIXEL,&tempo); strpixel=tempo; sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&tempo); endpixel=tempo; /* compute deletion factor */ sanei_genesys_get_double(dev->reg,REG_DPISET,&tempo); dpiset=tempo; DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d, PIXELS=%d, DPISET=%d\n",__func__,strpixel,endpixel,endpixel-strpixel,dpiset); dpihw=sanei_genesys_compute_dpihw(dev,dpiset); factor=dpihw/dpiset; DBG( DBG_io2, "%s: factor=%d\n",__func__,factor); if(DBG_LEVEL>=DBG_data) { dev->binary=fopen("binary.pnm","wb"); sanei_genesys_get_triple(dev->reg, REG_LINCNT, &lines); channels=dev->current_setup.channels; if(dev->binary!=NULL) { fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255); } } pixels=endpixel-strpixel; /* since we're using SHDAREA, substract startx coordinate from shading */ strpixel-=((dev->sensor.CCD_start_xoffset*600)/dev->sensor.optical_res); /* turn pixel value into bytes 2x16 bits words */ strpixel*=2*2; pixels*=2*2; /* allocate temporary buffer */ buffer=(uint8_t *)malloc(pixels); memset(buffer,0,pixels); DBG( DBG_io2, "%s: using chunks of %d (0x%04x) bytes\n",__func__,pixels,pixels); /* base addr of data has been written in reg D0-D4 in 4K word, so AHB address * is 8192*reg value */ /* write actual color channel data */ for(i=0;i<3;i++) { /* build up actual shading data by copying the part from the full width one * to the one corresponding to SHDAREA */ ptr=buffer; /* iterate on both sensor segment */ for(x=0;xdn, dev->usb_mode, addr, pixels, buffer); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_send_shading_data; write to AHB failed (%s)\n", sane_strstatus (status)); free(buffer); return status; } } free(buffer); DBGCOMPLETED; return status; } /** @brief calibrates led exposure * Calibrate exposure by scanning a white area until the used exposure gives * data white enough. * @param dev device to calibrate */ static SANE_Status gl846_led_calibration (Genesys_Device * dev) { int num_pixels; int total_size; int used_res; uint8_t *line; int i, j; SANE_Status status = SANE_STATUS_GOOD; int val; int channels, depth; int avg[3], top[3], bottom[3]; int turn; char fn[20]; uint16_t exp[3]; Sensor_Profile *sensor; float move; SANE_Bool acceptable; DBGSTART; move = SANE_UNFIX (dev->model->y_offset_calib); move = (move * (dev->motor.base_ydpi/4)) / MM_PER_INCH; if(move>20) { RIE(gl846_feed (dev, move)); } DBG (DBG_io, "%s: move=%f steps\n", __func__, move); /* offset calibration is always done in color mode */ channels = 3; depth=16; used_res=sanei_genesys_compute_dpihw(dev,dev->settings.xres); sensor=get_sensor_profile(dev->model->ccd_type, used_res); num_pixels = (dev->sensor.sensor_pixels*used_res)/dev->sensor.optical_res; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); /* set up for the calibration scan */ status = gl846_init_scan_regs (dev, dev->calib_reg, used_res, used_res, 0, 0, num_pixels, 1, depth, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } total_size = num_pixels * channels * (depth/8) * 1; /* colors * bytes_per_color * scan lines */ line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; /* initial loop values and boundaries */ exp[0]=sensor->expr; exp[1]=sensor->expg; exp[2]=sensor->expb; bottom[0]=29000; bottom[1]=29000; bottom[2]=29000; top[0]=41000; top[1]=51000; top[2]=51000; turn = 0; /* no move during led calibration */ gl846_set_motor_power (dev->calib_reg, SANE_FALSE); do { /* set up exposure */ sanei_genesys_set_double(dev->calib_reg,REG_EXPR,exp[0]); sanei_genesys_set_double(dev->calib_reg,REG_EXPG,exp[1]); sanei_genesys_set_double(dev->calib_reg,REG_EXPB,exp[2]); /* write registers and scan data */ RIEF (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), line); DBG (DBG_info, "gl846_led_calibration: starting line reading\n"); RIEF (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); /* stop scanning */ RIEF (gl846_stop_action (dev), line); if (DBG_LEVEL >= DBG_data) { snprintf (fn, 20, "led_%02d.pnm", turn); sanei_genesys_write_pnm_file (fn, line, depth, channels, num_pixels, 1); } /* compute average */ for (j = 0; j < channels; j++) { avg[j] = 0; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * num_pixels + 1] * 256 + line[i * 2 + j * 2 * num_pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; avg[j] += val; } avg[j] /= num_pixels; } DBG (DBG_info, "gl846_led_calibration: average: %d,%d,%d\n", avg[0], avg[1], avg[2]); /* check if exposure gives average within the boundaries */ acceptable = SANE_TRUE; for(i=0;i<3;i++) { if(avg[i]top[i]) { exp[i]=(exp[i]*top[i])/avg[i]; acceptable = SANE_FALSE; } } turn++; } while (!acceptable && turn < 100); DBG (DBG_info, "gl846_led_calibration: acceptable exposure: %d,%d,%d\n", exp[0], exp[1], exp[2]); /* set these values as final ones for scan */ sanei_genesys_set_double(dev->reg,REG_EXPR,exp[0]); sanei_genesys_set_double(dev->reg,REG_EXPG,exp[1]); sanei_genesys_set_double(dev->reg,REG_EXPB,exp[2]); /* store in this struct since it is the one used by cache calibration */ dev->sensor.regs_0x10_0x1d[0] = (exp[0] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[1] = exp[0] & 0xff; dev->sensor.regs_0x10_0x1d[2] = (exp[1] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[3] = exp[1] & 0xff; dev->sensor.regs_0x10_0x1d[4] = (exp[2] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[5] = exp[2] & 0xff; /* cleanup before return */ free (line); /* go back home */ if(move>20) { status=gl846_slow_back_home (dev, SANE_TRUE); } DBGCOMPLETED; return status; } /** * set up GPIO/GPOE for idle state */ static SANE_Status gl846_init_gpio (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; int idx=0; DBGSTART; /* search GPIO profile */ while(gpios[idx].sensor_id!=0 && dev->model->gpo_type!=gpios[idx].sensor_id) { idx++; } if(gpios[idx].sensor_id==0) { DBG (DBG_error, "%s: failed to find GPIO profile for sensor_id=%d\n", __func__, dev->model->ccd_type); return SANE_STATUS_INVAL; } RIE (sanei_genesys_write_register (dev, REGA7, gpios[idx].ra7)); RIE (sanei_genesys_write_register (dev, REGA6, gpios[idx].ra6)); RIE (sanei_genesys_write_register (dev, REG6B, gpios[idx].r6b)); RIE (sanei_genesys_write_register (dev, REG6C, gpios[idx].r6c)); RIE (sanei_genesys_write_register (dev, REG6D, gpios[idx].r6d)); RIE (sanei_genesys_write_register (dev, REG6E, gpios[idx].r6e)); RIE (sanei_genesys_write_register (dev, REG6F, gpios[idx].r6f)); RIE (sanei_genesys_write_register (dev, REGA8, gpios[idx].ra8)); RIE (sanei_genesys_write_register (dev, REGA9, gpios[idx].ra9)); DBGCOMPLETED; return status; } /** * set memory layout by filling values in dedicated registers */ static SANE_Status gl846_init_memory_layout (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; int idx = 0, i; uint8_t val; DBGSTART /* point to per model memory layout */ idx = 0; while(layouts[idx].model!=NULL && strcmp(dev->model->name,layouts[idx].model)!=0) { if(strcmp(dev->model->name,layouts[idx].model)!=0) idx++; } if(layouts[idx].model==NULL) { DBG(DBG_error, "%s: failed to find memory layout for model %s!\n", __func__, dev->model->name); return SANE_STATUS_INVAL; } /* CLKSET and DRAMSEL */ val = layouts[idx].dramsel; RIE (sanei_genesys_write_register (dev, REG0B, val)); dev->reg[reg_0x0b].value = val; /* prevent further writings by bulk write register */ dev->reg[reg_0x0b].address = 0x00; /* setup base address for shading and scanned data. */ for(i=0;i<10;i++) { sanei_genesys_write_register (dev, 0xe0+i, layouts[idx].rx[i]); } DBGCOMPLETED; return status; } /* * * initialize ASIC from power on condition */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_boot (Genesys_Device * dev, SANE_Bool cold) { SANE_Status status; uint8_t val; DBGSTART; /* reset ASIC if cold boot */ if(cold) { RIE (sanei_genesys_write_register (dev, 0x0e, 0x01)); RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); } if(dev->usb_mode == 1) { val = 0x14; } else { val = 0x11; } RIE (sanei_genesys_write_0x8c (dev, 0x0f, val)); /* test CHKVER */ RIE (sanei_genesys_read_register (dev, REG40, &val)); if (val & REG40_CHKVER) { RIE (sanei_genesys_read_register (dev, 0x00, &val)); DBG (DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val); } /* Set default values for registers */ gl846_init_registers (dev); /* Write initial registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL846_MAX_REGS)); /* Enable DRAM by setting a rising edge on bit 3 of reg 0x0b */ val = dev->reg[reg_0x0b].value & REG0B_DRAMSEL; val = (val | REG0B_ENBDRAM); RIE (sanei_genesys_write_register (dev, REG0B, val)); dev->reg[reg_0x0b].value = val; /* CIS_LINE */ if (dev->model->is_cis) { SETREG (0x08, REG08_CIS_LINE); RIE (sanei_genesys_write_register (dev, 0x08, dev->reg[reg_0x08].value)); } /* set up clocks */ RIE (sanei_genesys_write_0x8c (dev, 0x10, 0x0e)); RIE (sanei_genesys_write_0x8c (dev, 0x13, 0x0e)); /* setup gpio */ RIE (gl846_init_gpio (dev)); /* setup internal memory layout */ RIE (gl846_init_memory_layout (dev)); SETREG (0xf8, 0x05); RIE (sanei_genesys_write_register (dev, 0xf8, dev->reg[reg_0xf8].value)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * initialize backend and ASIC : registers, motor tables, and gamma tables * then ensure scanner's head is at home */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_init (Genesys_Device * dev) { SANE_Status status; DBG_INIT (); DBGSTART; status=sanei_genesys_asic_init(dev, GENESYS_GL846_MAX_REGS); DBGCOMPLETED; return status; } static SANE_Status gl846_update_hardware_sensors (Genesys_Scanner * s) { /* do what is needed to get a new set of events, but try to not lose any of them. */ SANE_Status status = SANE_STATUS_GOOD; uint8_t val; uint8_t scan, file, email, copy; switch(s->dev->model->gpo_type) { default: scan=0x01; file=0x02; email=0x04; copy=0x08; } RIE (sanei_genesys_read_register (s->dev, REG6D, &val)); if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b) s->val[OPT_SCAN_SW].b = (val & scan) == 0; if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b) s->val[OPT_FILE_SW].b = (val & file) == 0; if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b) s->val[OPT_EMAIL_SW].b = (val & email) == 0; if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b) s->val[OPT_COPY_SW].b = (val & copy) == 0; return status; } /** @brief search for a full width black or white strip. * This function searches for a black or white stripe across the scanning area. * When searching backward, the searched area must completely be of the desired * color since this area will be used for calibration which scans forward. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward * @param black SANE_TRUE if searching for a black strip, SANE_FALSE for a white strip * @return SANE_STATUS_GOOD if a matching strip is found, SANE_STATUS_UNSUPPORTED if not */ static SANE_Status gl846_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black) { unsigned int pixels, lines, channels; SANE_Status status; Genesys_Register_Set local_reg[GENESYS_GL846_MAX_REGS]; size_t size; uint8_t *data; int steps, depth, dpi; unsigned int pass, count, found, x, y; char title[80]; Genesys_Register_Set *r; DBG (DBG_proc, "gl846_search_strip %s %s\n", black ? "black" : "white", forward ? "forward" : "reverse"); status = gl846_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_search_strip: gl846_set_fe() failed: %s\n", sane_strstatus(status)); return status; } status = gl846_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_search_strip: failed to stop: %s\n", sane_strstatus (status)); return status; } /* set up for a gray scan at lowest dpi */ dpi = 9600; for (x = 0; x < MAX_RESOLUTIONS; x++) { if (dev->model->xdpi_values[x] > 0 && dev->model->xdpi_values[x] < dpi) dpi = dev->model->xdpi_values[x]; } channels = 1; /* 10 MM */ /* lines = (10 * dpi) / MM_PER_INCH; */ /* shading calibation is done with dev->motor.base_ydpi */ lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi; depth = 8; pixels = (dev->sensor.sensor_pixels * dpi) / dev->sensor.optical_res; size = pixels * channels * lines * (depth / 8); data = malloc (size); if (!data) { DBG (DBG_error, "gl846_search_strip: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } dev->scanhead_position_in_steps = 0; memcpy (local_reg, dev->reg, GENESYS_GL846_MAX_REGS * sizeof (Genesys_Register_Set)); status = gl846_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, pixels, lines, depth, channels, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "gl846_search_strip: failed to setup for scan: %s\n", sane_strstatus (status)); return status; } /* set up for reverse or forward */ r = sanei_genesys_get_address (local_reg, REG02); if (forward) r->value &= ~REG02_MTRREV; else r->value |= REG02_MTRREV; status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "gl846_search_strip: Failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } status = gl846_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_strip: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } status = gl846_stop_action (dev); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_strip: gl846_stop_action failed\n"); return status; } pass = 0; if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s_%s%02d.pnm", black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass); sanei_genesys_write_pnm_file (title, data, depth, channels, pixels, lines); } /* loop until strip is found or maximum pass number done */ found = 0; while (pass < 20 && !found) { status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL846_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_search_strip: Failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } /* now start scan */ status = gl846_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_strip: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } status = gl846_stop_action (dev); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl846_search_strip: gl846_stop_action failed\n"); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s_%s%02d.pnm", black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass); sanei_genesys_write_pnm_file (title, data, depth, channels, pixels, lines); } /* search data to find black strip */ /* when searching forward, we only need one line of the searched color since we * will scan forward. But when doing backward search, we need all the area of the * same color */ if (forward) { for (y = 0; y < lines && !found; y++) { count = 0; /* count of white/black pixels depending on the color searched */ for (x = 0; x < pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * pixels + x] > 90) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * pixels + x] < 60) { count++; } } /* at end of line, if count >= 3%, line is not fully of the desired color * so we must go to next line of the buffer */ /* count*100/pixels < 3 */ if ((count * 100) / pixels < 3) { found = 1; DBG (DBG_data, "gl846_search_strip: strip found forward during pass %d at line %d\n", pass, y); } else { DBG (DBG_data, "gl846_search_strip: pixels=%d, count=%d (%d%%)\n", pixels, count, (100 * count) / pixels); } } } else /* since calibration scans are done forward, we need the whole area to be of the required color when searching backward */ { count = 0; for (y = 0; y < lines; y++) { /* count of white/black pixels depending on the color searched */ for (x = 0; x < pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * pixels + x] > 90) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * pixels + x] < 60) { count++; } } } /* at end of area, if count >= 3%, area is not fully of the desired color * so we must go to next buffer */ if ((count * 100) / (pixels * lines) < 3) { found = 1; DBG (DBG_data, "gl846_search_strip: strip found backward during pass %d \n", pass); } else { DBG (DBG_data, "gl846_search_strip: pixels=%d, count=%d (%d%%)\n", pixels, count, (100 * count) / pixels); } } pass++; } free (data); if (found) { status = SANE_STATUS_GOOD; DBG (DBG_info, "gl846_search_strip: %s strip found\n", black ? "black" : "white"); } else { status = SANE_STATUS_UNSUPPORTED; DBG (DBG_info, "gl846_search_strip: %s strip not found\n", black ? "black" : "white"); } DBGCOMPLETED; return status; } /** * average dark pixels of a 8 bits scan */ static int dark_average (uint8_t * data, unsigned int pixels, unsigned int lines, unsigned int channels, unsigned int black) { unsigned int i, j, k, average, count; unsigned int avg[3]; uint8_t val; /* computes average value on black margin */ for (k = 0; k < channels; k++) { avg[k] = 0; count = 0; for (i = 0; i < lines; i++) { for (j = 0; j < black; j++) { val = data[i * channels * pixels + j + k]; avg[k] += val; count++; } } if (count) avg[k] /= count; DBG (DBG_info, "dark_average: avg[%d] = %d\n", k, avg[k]); } average = 0; for (i = 0; i < channels; i++) average += avg[i]; average /= channels; DBG (DBG_info, "dark_average: average = %d\n", average); return average; } static SANE_Status gl846_offset_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; uint8_t *first_line, *second_line, reg04; unsigned int channels, bpp; char title[32]; int pass = 0, avg, total_size; int topavg, bottomavg, resolution, lines; int top, bottom, black_pixels, pixels; DBGSTART; /* no gain nor offset for AKM AFE */ RIE (sanei_genesys_read_register (dev, REG04, ®04)); if ((reg04 & REG04_FESET) == 0x02) { DBGCOMPLETED; return status; } /* offset calibration is always done in color mode */ channels = 3; resolution=dev->sensor.optical_res; dev->calib_pixels = dev->sensor.sensor_pixels; lines=1; bpp=8; pixels= (dev->sensor.sensor_pixels*resolution) / dev->sensor.optical_res; black_pixels = (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res; DBG (DBG_io2, "gl846_offset_calibration: black_pixels=%d\n", black_pixels); status = gl846_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, pixels, lines, bpp, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_offset_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } gl846_set_motor_power (dev->calib_reg, SANE_FALSE); /* allocate memory for scans */ total_size = pixels * channels * lines * (bpp/8); /* colors * bytes_per_color * scan lines */ first_line = malloc (total_size); if (!first_line) return SANE_STATUS_NO_MEM; second_line = malloc (total_size); if (!second_line) { free (first_line); return SANE_STATUS_NO_MEM; } /* init gain */ dev->frontend.gain[0] = 0; dev->frontend.gain[1] = 0; dev->frontend.gain[2] = 0; /* scan with no move */ bottom = 10; dev->frontend.offset[0] = bottom; dev->frontend.offset[1] = bottom; dev->frontend.offset[2] = bottom; RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl846_offset_calibration: starting first line reading\n"); RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size), first_line, second_line); if (DBG_LEVEL >= DBG_data) { snprintf(title,20,"offset%03d.pnm",bottom); sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines); } bottomavg = dark_average (first_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl846_offset_calibration: bottom avg=%d\n", bottomavg); /* now top value */ top = 255; dev->frontend.offset[0] = top; dev->frontend.offset[1] = top; dev->frontend.offset[2] = top; RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl846_offset_calibration: starting second line reading\n"); RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); topavg = dark_average (second_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl846_offset_calibration: top avg=%d\n", topavg); /* loop until acceptable level */ while ((pass < 32) && (top - bottom > 1)) { pass++; /* settings for new scan */ dev->frontend.offset[0] = (top + bottom) / 2; dev->frontend.offset[1] = (top + bottom) / 2; dev->frontend.offset[2] = (top + bottom) / 2; /* scan with no move */ RIEF2 (gl846_set_fe(dev, AFE_SET), first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl846_offset_calibration: starting second line reading\n"); RIEF2 (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); if (DBG_LEVEL >= DBG_data) { sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]); sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines); } avg = dark_average (second_line, pixels, lines, channels, black_pixels); DBG (DBG_info, "gl846_offset_calibration: avg=%d offset=%d\n", avg, dev->frontend.offset[1]); /* compute new boundaries */ if (topavg == avg) { topavg = avg; top = dev->frontend.offset[1]; } else { bottomavg = avg; bottom = dev->frontend.offset[1]; } } DBG (DBG_info, "gl846_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); /* cleanup before return */ free (first_line); free (second_line); DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl846_coarse_gain_calibration (Genesys_Device * dev, int dpi) { int pixels; int total_size; uint8_t *line, reg04; int i, j, channels; SANE_Status status = SANE_STATUS_GOOD; int max[3]; float gain[3],coeff; int val, code, lines; int resolution; int bpp; DBG (DBG_proc, "gl846_coarse_gain_calibration: dpi = %d\n", dpi); /* no gain nor offset for AKM AFE */ RIE (sanei_genesys_read_register (dev, REG04, ®04)); if ((reg04 & REG04_FESET) == 0x02) { DBGCOMPLETED; return status; } /* coarse gain calibration is always done in color mode */ channels = 3; /* follow CKSEL */ if(dev->settings.xressensor.optical_res) { coeff=0.9; /*resolution=dev->sensor.optical_res/2;*/ resolution=dev->sensor.optical_res; } else { resolution=dev->sensor.optical_res; coeff=1.0; } lines=10; bpp=8; pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; status = gl846_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, pixels, lines, bpp, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); gl846_set_motor_power (dev->calib_reg, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl846_coarse_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } RIE (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL846_MAX_REGS)); total_size = pixels * channels * (16/bpp) * lines; line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; RIEF (gl846_set_fe(dev, AFE_SET), line); RIEF (gl846_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("coarse.pnm", line, bpp, channels, pixels, lines); /* average value on each channel */ for (j = 0; j < channels; j++) { max[j] = 0; for (i = pixels/4; i < (pixels*3/4); i++) { if (dev->model->is_cis) val = line[i + j * pixels]; else val = line[i * channels + j]; max[j] += val; } max[j] = max[j] / (pixels/2); gain[j] = ((float) dev->sensor.gain_white_ref*coeff) / max[j]; /* turn logical gain value into gain code, checking for overflow */ code = 283 - 208 / gain[j]; if (code > 255) code = 255; else if (code < 0) code = 0; dev->frontend.gain[j] = code; DBG (DBG_proc, "gl846_coarse_gain_calibration: channel %d, max=%d, gain = %f, setting:%d\n", j, max[j], gain[j], dev->frontend.gain[j]); } if (dev->model->is_cis) { if (dev->frontend.gain[0] > dev->frontend.gain[1]) dev->frontend.gain[0] = dev->frontend.gain[1]; if (dev->frontend.gain[0] > dev->frontend.gain[2]) dev->frontend.gain[0] = dev->frontend.gain[2]; dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0]; } free (line); RIE (gl846_stop_action (dev)); status=gl846_slow_back_home (dev, SANE_TRUE); DBGCOMPLETED; return status; } /** the gl846 command set */ static Genesys_Command_Set gl846_cmd_set = { "gl846-generic", /* the name of this set */ gl846_init, NULL, gl846_init_regs_for_coarse_calibration, gl846_init_regs_for_shading, gl846_init_regs_for_scan, gl846_get_filter_bit, gl846_get_lineart_bit, gl846_get_bitset_bit, gl846_get_gain4_bit, gl846_get_fast_feed_bit, gl846_test_buffer_empty_bit, gl846_test_motor_flag_bit, gl846_bulk_full_size, gl846_set_fe, gl846_set_powersaving, gl846_save_power, gl846_set_motor_power, gl846_set_lamp_power, gl846_begin_scan, gl846_end_scan, sanei_genesys_send_gamma_table, gl846_search_start_position, gl846_offset_calibration, gl846_coarse_gain_calibration, gl846_led_calibration, gl846_slow_back_home, NULL, sanei_genesys_bulk_write_register, NULL, gl846_bulk_read_data, gl846_update_hardware_sensors, NULL, NULL, NULL, gl846_search_strip, sanei_genesys_is_compatible_calibration, NULL, gl846_send_shading_data, gl846_calculate_current_setup, gl846_boot, NULL }; SANE_Status sanei_gl846_init_cmd_set (Genesys_Device * dev) { dev->model->cmd_set = &gl846_cmd_set; return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/epjitsu-cmd.h0000664000175000017500000012523213073301665015217 00000000000000static void putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) { int i; for (i = nbytes - 1; i >= 0; i--) { pnt[i] = value & 0xff; value = value >> 8; } } #define SET_WINDOW_LEN 72 #define set_SW_byte7(out, val) out[7] = val #define set_SW_xres(out, val) putnbyte(out + 0x0a, val, 2) #define set_SW_yres(out, val) putnbyte(out + 0x0c, val, 2) #define set_SW_xpix(out, val) putnbyte(out + 0x16, val, 4) #define set_SW_ypix(out, val) putnbyte(out + 0x1a, val, 4) #define set_SW_compo(out, val) out[0x21] = val /*color=5,gray=2*/ #define set_SW_bpp(out, val) out[0x22] = val #define set_SW_byte31(out, val) out[0x31] = val #define set_SW_byte32(out, val) out[0x32] = val #define set_SW_byte33(out, val) out[0x33] = val #define set_SW_lpb(out, val) out[0x34] = val #define set_SW_byte35(out, val) out[0x35] = val #define set_SW_byte36(out, val) out[0x36] = val #define set_SW_byte38(out, val) out[0x38] = val /*move motor?*/ #define set_SW_fres(out, val) putnbyte(out + 0x39, val, 2) /*************** COARSE CALIBRATION DEFAULT PAYLOAD *************/ /* 1b c6 (send coarse cal) command payload - not resolution specific? */ /* first group of 3 is offset?, larger # == brighter */ /* second group of 3 is gain?, larger # == brighter */ static unsigned char coarseCalData_FI60F[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x26, 0x00, 0x26, 0x00, 0x26, 0x00, 0x00, 0x0b, 0x22, 0x00, 0x00, 0x0b, 0x22, 0x00, 0x00, 0x0b, 0x22 }; static unsigned char coarseCalData_S300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char coarseCalData_S1300i[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char coarseCalData_S1100[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** fi-60F 300dpi gray *************/ #if 0 static unsigned char setWindowScan_FI60F_300_g[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x06, 0xd5, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x6c, 0x01, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** fi-60F 400dpi gray *************/ static unsigned char setWindowScan_FI60F_400_g[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x09, 0x1c, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0xca, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** fi-60F 600dpi gray *************/ static unsigned char setWindowScan_FI60F_600_g[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x0d, 0xaa, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0xca, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif /*************** fi-60F 150dpi *************/ static unsigned char setWindowScan_FI60F_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x48, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** fi-60F 200dpi *************/ static unsigned char setWindowScan_FI60F_200[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x04, 0x8e, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x48, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** fi-60F 300dpi *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x1c20 bytes) */ static unsigned char setWindowCoarseCal_FI60F_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x1c20 bytes) */ static unsigned char setWindowFineCal_FI60F_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0x3840 bytes) */ static unsigned char setWindowSendCal_FI60F_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_FI60F_300[] = { /* plus 0x3840 data bytes */ 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x00, 0x04 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_FI60F_300[] = { 0x39, 0x3f, 0x39, 0x3f, 0x39, 0x3f, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_FI60F_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x06, 0xd5, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x48, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** fi-60F 400dpi *************/ static unsigned char setWindowScan_FI60F_400[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x00, 0x09, 0x1c, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** fi-60F 600dpi *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x2160 bytes) */ static unsigned char setWindowCoarseCal_FI60F_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x2160 bytes) */ static unsigned char setWindowFineCal_FI60F_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0x42c0 bytes) */ static unsigned char setWindowSendCal_FI60F_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x00, 0x0d, 0xaa, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_FI60F_600[] = { 0x4f, 0x10, 0x4f, 0x10, 0x4f, 0x10, 0x4f, 0x10, 0x4f, 0x10, 0x4f, 0x10, 0x00, 0x04 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_FI60F_600[] = { 0x2b, 0x40, 0x2b, 0x40, 0x2b, 0x40, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_FI60F_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x00, 0x0d, 0xaa, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S300 150dpi *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S300_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x63c0 bytes) */ static unsigned char setWindowFineCal_S300_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc780 bytes) */ static unsigned char setWindowSendCal_S300_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S300_150[] = { /* plus 0xc780 data bytes */ 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0x00, 0x04 /*0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0x00, 0x05*/ }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S300_150[] = { /* plus 0xc780 data bytes */ 0x77, 0x26, 0x77, 0x26, 0x77, 0x26, 0x07 /*0xd0, 0x34, 0xd0, 0x34, 0xd0, 0x34, 0x08*/ }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S300_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xc8, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S300 225dpi *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S300_225[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x63c0 bytes) */ static unsigned char setWindowFineCal_S300_225[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc780 bytes) */ static unsigned char setWindowSendCal_S300_225[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S300_225[] = { /* plus 0xc780 data bytes */ 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0x00, 0x04 /*0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0x00, 0x05*/ }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S300_225[] = { /* plus 0xc780 data bytes */ 0x77, 0x26, 0x77, 0x26, 0x77, 0x26, 0x07 /*0xd0, 0x34, 0xd0, 0x34, 0xd0, 0x34, 0x08*/ }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S300_225[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x34, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S300 300dpi *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x6000 bytes) */ static unsigned char setWindowCoarseCal_S300_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x6000 bytes) */ static unsigned char setWindowFineCal_S300_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc000 bytes) */ static unsigned char setWindowSendCal_S300_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S300_300[] = { /* plus 0xc000 data bytes */ 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0x00, 0x04 /*0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x00, 0x05*/ }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S300_300[] = { /* plus 0xc000 data bytes */ 0x77, 0x26, 0x77, 0x26, 0x77, 0x26, 0x07 /*0xb8, 0x34, 0xb8, 0x34, 0xb8, 0x34, 0x08*/ }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S300_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x0d, 0xc4, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S300 600dpi USB and AC power *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0xbc40 bytes) */ static unsigned char setWindowCoarseCal_S300_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0xbc40 bytes) */ static unsigned char setWindowFineCal_S300_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0x17880 bytes) */ static unsigned char setWindowSendCal_S300_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S300_600[] = { 0x7f, 0x0b, 0x7f, 0x0b, 0x7f, 0x0b, 0x7f, 0x0b, 0x7f, 0x0b, 0x7f, 0x0b, 0x00, 0x04 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S300_600[] = { 0xc7, 0x23, 0xc7, 0x23, 0xc7, 0x23, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S300_600[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x40, 0x00, 0x00, 0x24, 0x21, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*S300/S1300/S1300i can also use a USB power cable, but it requires a different set of params?*/ /*************** S300/S1300/S1300i 150dpi USB *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S300_150_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x63c0 bytes) */ static unsigned char setWindowFineCal_S300_150_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc780 bytes) */ static unsigned char setWindowSendCal_S300_150_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S300_150_U[] = { /* plus 0xc780 data bytes */ 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0x00, 0x04 /*0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0x00, 0x05*/ }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S300_150_U[] = { /* plus 0xc780 data bytes */ 0x77, 0x26, 0x77, 0x26, 0x77, 0x26, 0x07 /*0xd0, 0x34, 0xd0, 0x34, 0xd0, 0x34, 0x08*/ }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S300_150_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x00, 0x09, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S300/S1300/S1300i 225dpi USB *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S300_225_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x63c0 bytes) */ static unsigned char setWindowFineCal_S300_225_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc780 bytes) */ static unsigned char setWindowSendCal_S300_225_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S300_225_U[] = { /* plus 0xc780 data bytes */ 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0x00, 0x04 /*0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0x00, 0x05*/ }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S300_225_U[] = { /* plus 0xc780 data bytes */ 0x77, 0x26, 0x77, 0x26, 0x77, 0x26, 0x07 /*0xd0, 0x34, 0xd0, 0x34, 0xd0, 0x34, 0x08*/ }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S300_225_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xe0, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S300/S1300/S1300i 300dpi USB *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S300_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x63c0 bytes) */ static unsigned char setWindowFineCal_S300_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xf0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc780 bytes) */ static unsigned char setWindowSendCal_S300_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S300_300_U[] = { /* plus 0xc780 data bytes */ 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0xe2, 0x0a, 0x00, 0x04 /*0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0xa5, 0x0b, 0x00, 0x05*/ }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S300_300_U[] = { /* plus 0xc780 data bytes */ 0x77, 0x26, 0x77, 0x26, 0x77, 0x26, 0x07 /*0xd0, 0x34, 0xd0, 0x34, 0xd0, 0x34, 0x08*/ }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S300_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xf0, 0x00, 0x00, 0x12, 0x11, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S300/S1300/S1300i USB is same as AC power *************/ /*************** S1300i 150dpi *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x5e24 bytes) */ static unsigned char setWindowCoarseCal_S1300i_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x5e24 bytes) */ static unsigned char setWindowFineCal_S1300i_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xbc40 bytes) */ static unsigned char setWindowSendCal_S1300i_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S1300i_150[] = { /* plus 0xc780 data bytes */ 0xc4, 0x06, 0xc4, 0x06, 0xc4, 0x06, 0xc4, 0x06, 0xc4, 0x06, 0xc4, 0x06, 0x00, 0x04 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S1300i_150[] = { /* plus 0xc780 data bytes */ 0xd7, 0x3b, 0xd7, 0x3b, 0xd7, 0x3b, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S1300i_150[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0x00, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S1300i 225dpi *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x63c0 bytes) */ static unsigned char setWindowCoarseCal_S1300i_225[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x63c0 bytes) */ static unsigned char setWindowFineCal_S1300i_225[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xc780 bytes) */ static unsigned char setWindowSendCal_S1300i_225[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S1300i_225[] = { /* plus 0xc780 data bytes */ 0x2f, 0x07, 0x2f, 0x07, 0x2f, 0x07, 0x2f, 0x07, 0x2f, 0x07, 0x2f, 0x07, 0x00, 0x04 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S1300i_225[] = { /* plus 0xc780 data bytes */ 0xa5, 0x3b, 0xa5, 0x3b, 0xa5, 0x3b, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S1300i_225[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S1300i 300dpi *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x5ee0 bytes) */ static unsigned char setWindowCoarseCal_S1300i_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x5ee0 bytes) */ static unsigned char setWindowFineCal_S1300i_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0xbdc0 bytes) */ static unsigned char setWindowSendCal_S1300i_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S1300i_300[] = { /* plus 0xc000 data bytes */ 0xdd, 0x06, 0xdd, 0x06, 0xdd, 0x06, 0xdd, 0x06, 0xdd, 0x06, 0xdd, 0x06, 0x00, 0x04 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S1300i_300[] = { /* plus 0xc000 data bytes */ 0x75, 0x3c, 0x75, 0x3c, 0x75, 0x3c, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S1300i_300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xc0, 0x00, 0x00, 0x0d, 0xc4, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S1300i 600dpi AC power is same as S300 *************/ /*************** except the calibration headers *************/ /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S1300i_USB[] = { 0x4d, 0x06, 0x4d, 0x06, 0x4d, 0x06, 0x4d, 0x06, 0x4d, 0x06, 0x4d, 0x06, 0x00, 0x04 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S1300i_USB[] = { 0x8f, 0x40, 0x8f, 0x40, 0x8f, 0x40, 0x07 }; /*************** S1300i all resolutions USB power is same as S300 *************/ /*************** S1100 300dpi USB *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x45a0 bytes) */ static unsigned char setWindowCoarseCal_S1100_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x45a0 bytes) */ static unsigned char setWindowFineCal_S1100_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0x45a0 bytes) */ static unsigned char setWindowSendCal_S1100_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xd0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S1100_300_U[] = { /* plus 0x45a0 data bytes */ 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x00, 0x03 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S1100_300_U[] = { /* plus 0x45a0 data bytes */ 0x63, 0x86, 0x63, 0x86, 0x63, 0x86, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S1100_300_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x1b, 0xe1, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*************** S1100 600dpi USB *************/ /* 1b d1 (set window) before coarse cal (read 1 line of 0x3e20 bytes) */ static unsigned char setWindowCoarseCal_S1100_600_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before fine cal (read 16 lines of 0x3e20 bytes) */ static unsigned char setWindowFineCal_S1100_600_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b d1 (set window) before gain/offset tables (write 1 line of 0x7c40 bytes) */ static unsigned char setWindowSendCal_S1100_600_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 1b c3 (gain?) command header */ static unsigned char sendCal1Header_S1100_600_U[] = { /* plus 0x7c40 data bytes */ 0xff, 0x11, 0xff, 0x11, 0xff, 0x11, 0xff, 0x11, 0xff, 0x11, 0xff, 0x11, 0x00, 0x03 }; /* 1b c4 (offset?) command header */ static unsigned char sendCal2Header_S1100_600_U[] = { /* plus 0x7c40 data bytes */ 0x4b, 0x81, 0x4b, 0x81, 0x4b, 0x81, 0x07 }; /* 1b d1 (set window) before scan */ static unsigned char setWindowScan_S1100_600_U[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf0, 0x00, 0x00, 0x37, 0xbf, 0x00, 0x00, 0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; sane-backends-1.0.27/backend/epjitsu.h0000664000175000017500000002640413073301665014457 00000000000000#ifndef EPJITSU_H #define EPJITSU_H /* * Part of SANE - Scanner Access Now Easy. * Please see opening comment in epjitsu.c */ /* ------------------------------------------------------------------------- * This option list has to contain all options for all scanners supported by * this driver. If a certain scanner cannot handle a certain option, there's * still the possibility to say so, later. */ enum scanner_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_SOURCE, /*adffront/adfback/adfduplex/fb*/ OPT_MODE, /*mono/gray/color*/ OPT_RES, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_PAGE_WIDTH, OPT_PAGE_HEIGHT, OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_GAMMA, OPT_THRESHOLD, OPT_THRESHOLD_CURVE, OPT_SENSOR_GROUP, OPT_SCAN_SW, OPT_HOPPER, OPT_TOP, OPT_ADF_OPEN, OPT_SLEEP, /* must come last: */ NUM_OPTIONS }; #define FIRMWARE_LENGTH 0x10000 #define MAX_IMG_PASS 0x10000 #define MAX_IMG_BLOCK 0x80000 struct image { int width_pix; int width_bytes; int height; int pages; int mode; int x_res; int y_res; int x_start_offset; int x_offset_bytes; int y_skip_offset; unsigned char * buffer; }; struct transfer { int plane_width; /* in RGB pixels */ int plane_stride; /* in bytes */ int line_stride; /* in bytes */ int total_bytes; int rx_bytes; int done; int mode; int x_res; int y_res; unsigned char * raw_data; struct image * image; }; struct page { int bytes_total; int bytes_scanned; int bytes_read; int lines_rx; /* received from scanner */ int lines_pass; /* passed thru from scanner to user (might be smaller than tx for 225dpi) */ int lines_tx; /* transmitted to user */ int done; struct image *image; }; struct scanner { /* --------------------------------------------------------------------- */ /* immutable values which are set during init of scanner. */ struct scanner *next; int missing; int model; int usb_power; int has_fb; int has_adf; int has_adf_duplex; int min_res; int max_res; float white_factor[3]; int adf_height_padding; /* the scan size in 1/1200th inches, NOT basic_units or sane units */ int max_x; int max_y; int min_x; int min_y; /* --------------------------------------------------------------------- */ /* immutable values which are set during inquiry probing of the scanner. */ SANE_Device sane; /*contains: name, vendor, model, type*/ /* --------------------------------------------------------------------- */ /* changeable SANE_Option structs provide our interface to frontend. */ /* long array of option structs */ SANE_Option_Descriptor opt[NUM_OPTIONS]; /* --------------------------------------------------------------------- */ /* some options require lists of strings or numbers, we keep them here */ /* instead of in global vars so that they can differ for each scanner */ /*mode group, room for lineart, gray, color, null */ SANE_String_Const source_list[5]; SANE_String_Const mode_list[4]; SANE_Range res_range; /*geometry group*/ SANE_Range tl_x_range; SANE_Range tl_y_range; SANE_Range br_x_range; SANE_Range br_y_range; SANE_Range paper_x_range; SANE_Range paper_y_range; /*enhancement group*/ SANE_Range brightness_range; SANE_Range contrast_range; SANE_Range gamma_range; SANE_Range threshold_range; SANE_Range threshold_curve_range; /* --------------------------------------------------------------------- */ /* changeable vars to hold user input. modified by SANE_Options above */ /*mode group*/ int source; /* adf or fb */ int mode; /* color,lineart,etc */ int resolution; /* dpi */ /*geometry group*/ /* The desired size of the scan, all in 1/1200 inch */ int tl_x; int tl_y; int br_x; int br_y; int page_width; int page_height; /*enhancement group*/ int brightness; int contrast; int gamma; int threshold; int threshold_curve; int height; /* may run out on adf */ /* --------------------------------------------------------------------- */ /* values which are set by user parameter changes, scanner specific */ unsigned char * setWindowCoarseCal; /* sent before coarse cal */ size_t setWindowCoarseCalLen; unsigned char * setWindowFineCal; /* sent before fine cal */ size_t setWindowFineCalLen; unsigned char * setWindowSendCal; /* sent before send cal */ size_t setWindowSendCalLen; unsigned char * sendCal1Header; /* part of 1b c3 command */ size_t sendCal1HeaderLen; unsigned char * sendCal2Header; /* part of 1b c4 command */ size_t sendCal2HeaderLen; unsigned char * setWindowScan; /* sent before scan */ size_t setWindowScanLen; /* --------------------------------------------------------------------- */ /* values which are set by scanning functions to keep track of pages, etc */ int started; int side; /* holds temp buffers for getting 16 lines of cal data */ struct transfer cal_image; struct image coarsecal; struct image darkcal; struct image lightcal; /* holds temp buffer for building calibration data */ struct transfer cal_data; struct image sendcal; /* scanner transmits more data per line than requested */ /* due to padding and/or duplex interlacing */ /* the scan struct holds these larger numbers, but image buffer is unused */ struct { int done; int mode; int x_res; int y_res; int height; int rx_bytes; int width_bytes; int total_bytes; } fullscan; /* The page structs contain data about the progress as the application reads */ /* data from the front/back image buffers via the sane_read() function */ struct page pages[2]; /* scanner transmits data in blocks, up to 512k */ /* but always ends on a scanline. */ /* the block struct holds the most recent buffer */ struct transfer block_xfr; struct image block_img; /* temporary buffers used by dynamic threshold code */ struct image dt; unsigned char dt_lut[256]; /* final-sized front image, always used */ struct image front; /* final-sized back image, only used during duplex/backside */ struct image back; /* --------------------------------------------------------------------- */ /* values used by the command and data sending function */ int fd; /* The scanner device file descriptor. */ /* --------------------------------------------------------------------- */ /* values which are used by the get hardware status command */ time_t last_ghs; int hw_scan_sw; int hw_hopper; int hw_top; int hw_adf_open; int hw_sleep; }; #define MODEL_NONE (1<<0) #define MODEL_S300 (1<<1) #define MODEL_FI60F (1<<2) #define MODEL_S1100 (1<<3) #define MODEL_S1300i (1<<4) #define MODEL_FI65F (1<<5) #define USB_COMMAND_TIME 10000 #define USB_DATA_TIME 10000 #define SIDE_FRONT 0 #define SIDE_BACK 1 #define SOURCE_FLATBED 0 #define SOURCE_ADF_FRONT 1 #define SOURCE_ADF_BACK 2 #define SOURCE_ADF_DUPLEX 3 #define MODE_COLOR 0 #define MODE_GRAYSCALE 1 #define MODE_LINEART 2 #define WINDOW_COARSECAL 0 #define WINDOW_FINECAL 1 #define WINDOW_SENDCAL 2 #define WINDOW_SCAN 3 #define EPJITSU_PAPER_INGEST 1 #define EPJITSU_PAPER_EJECT 0 /* ------------------------------------------------------------------------- */ #define MM_PER_UNIT_UNFIX SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0)) #define MM_PER_UNIT_FIX SANE_FIX(SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0))) #define SCANNER_UNIT_TO_FIXED_MM(number) SANE_FIX((number) * MM_PER_UNIT_UNFIX) #define FIXED_MM_TO_SCANNER_UNIT(number) SANE_UNFIX(number) / MM_PER_UNIT_UNFIX #define PIX_TO_SCANNER_UNIT(number, dpi) SANE_UNFIX(SANE_FIX((number) * 1200 / dpi )) #define SCANNER_UNIT_TO_PIX(number, dpi) SANE_UNFIX(SANE_FIX((number) * dpi / 1200 )) #define CONFIG_FILE "epjitsu.conf" #ifndef PATH_MAX # define PATH_MAX 1024 #endif /* ------------------------------------------------------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle); SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking); SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp); const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info); SANE_Status sane_start (SANE_Handle handle); SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len); void sane_cancel (SANE_Handle h); void sane_close (SANE_Handle h); void sane_exit (void); /* ------------------------------------------------------------------------- */ static SANE_Status attach_one (const char *devicename); static SANE_Status connect_fd (struct scanner *s); static SANE_Status disconnect_fd (struct scanner *s); static SANE_Status do_cmd(struct scanner *s, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ); /* static SANE_Status load_calibration (struct scanner *s); static SANE_Status read_from_scanner_gray(struct scanner *s); */ /* commands */ static SANE_Status load_fw(struct scanner *s); static SANE_Status get_ident(struct scanner *s); static SANE_Status change_params(struct scanner *s); static SANE_Status destroy(struct scanner *s); static SANE_Status teardown_buffers(struct scanner *s); static SANE_Status setup_buffers(struct scanner *s); static SANE_Status object_position(struct scanner *s, int ingest); static SANE_Status six5 (struct scanner *s); static SANE_Status coarsecal(struct scanner *s); static SANE_Status finecal(struct scanner *s); static SANE_Status send_lut(struct scanner *s); static SANE_Status lamp(struct scanner *s, unsigned char set); static SANE_Status set_window(struct scanner *s, int window); static SANE_Status scan(struct scanner *s); static SANE_Status read_from_scanner(struct scanner *s, struct transfer *tp); static SANE_Status descramble_raw_gray(struct scanner *s, struct transfer * tp); static SANE_Status descramble_raw(struct scanner *s, struct transfer * tp); static SANE_Status copy_block_to_page(struct scanner *s, int side); static SANE_Status binarize_line(struct scanner *s, unsigned char *lineOut, int width); static SANE_Status get_hardware_status (struct scanner *s); static SANE_Status load_lut (unsigned char * lut, int in_bits, int out_bits, int out_min, int out_max, int slope, int offset); static int get_page_width (struct scanner *s); static int get_page_height (struct scanner *s); static unsigned char get_stat(struct scanner *s); /* utils */ static void update_transfer_totals(struct transfer * t); static void hexdump (int level, char *comment, unsigned char *p, int l); static size_t maxStringSize (const SANE_String_Const strings[]); #endif /* EPJITSU_H */ sane-backends-1.0.27/backend/ibm.c0000664000175000017500000010402512775312261013534 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* This file implements a SANE backend for the Ibm 2456 flatbed scanner, written by mf . It derives from the backend for Ricoh flatbed scanners written by Feico W. Dillema. Currently maintained by Henning Meier-Geinitz . */ #define BUILD 5 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #define BACKEND_NAME ibm #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define IBM_CONFIG_FILE "ibm.conf" #include "ibm.h" #include "ibm-scsi.c" #define MAX(a,b) ((a) > (b) ? (a) : (b)) static int num_devices = 0; static Ibm_Device *first_dev = NULL; static Ibm_Scanner *first_handle = NULL; /* static int is50 = 0; */ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; DBG (11, ">> max_string_size\n"); for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } DBG (11, "<< max_string_size\n"); return max_size; } static SANE_Status attach (const char *devnam, Ibm_Device ** devp) { SANE_Status status; Ibm_Device *dev; int fd; struct inquiry_data ibuf; struct measurements_units_page mup; struct ibm_window_data wbuf; size_t buf_size; char *str; DBG (11, ">> attach\n"); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } DBG (3, "attach: opening %s\n", devnam); status = sanei_scsi_open (devnam, &fd, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } DBG (3, "attach: sending INQUIRY\n"); memset (&ibuf, 0, sizeof (ibuf)); buf_size = sizeof(ibuf); /* next line by mf */ ibuf.byte2 = 2; status = inquiry (fd, &ibuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } if (ibuf.devtype != 6) { DBG (1, "attach: device \"%s\" is not a scanner\n", devnam); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } if (!( (strncmp ((char *)ibuf.vendor, "IBM", 3) ==0 && strncmp ((char *)ibuf.product, "2456", 4) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS420", 5) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS410", 5) == 0) || (strncmp ((char *)ibuf.vendor, "RICOH", 5) == 0 && strncmp ((char *)ibuf.product, "IS430", 5) == 0) )) { DBG (1, "attach: device \"%s\" doesn't look like a scanner I know\n", devnam); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } DBG (3, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } /* * Causes a problem with RICOH IS420 * Ignore this function ... seems to work ok * Suggested to George Murphy george@topfloor.ie by henning */ if (strncmp((char *)ibuf.vendor, "RICOH", 5) != 0 && strncmp((char *)ibuf.product, "IS420", 5) != 0) { DBG (3, "attach: sending OBJECT POSITION\n"); status = object_position (fd, OBJECT_POSITION_UNLOAD); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: OBJECT POSTITION failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } } memset (&mup, 0, sizeof (mup)); mup.page_code = MEASUREMENTS_PAGE; mup.parameter_length = 0x06; mup.bmu = INCHES; mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff; mup.mud[1] = (DEFAULT_MUD & 0xff); #if 0 DBG (3, "attach: sending MODE SELECT\n"); status = mode_select (fd, (struct mode_pages *) &mup); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #endif #if 0 DBG (3, "attach: sending MODE SENSE\n"); memset (&mup, 0, sizeof (mup)); status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SENSE failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #endif DBG (3, "attach: sending GET WINDOW\n"); memset (&wbuf, 0, sizeof (wbuf)); status = get_window (fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET_WINDOW failed %d\n", status); sanei_scsi_close (fd); DBG (11, "<< attach\n"); return (SANE_STATUS_INVAL); } sanei_scsi_close (fd); dev = malloc (sizeof (*dev)); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devnam); dev->sane.vendor = "IBM"; str = malloc (sizeof(ibuf.product) + sizeof(ibuf.revision) + 1); if (str) { str[0] = '\0'; strncat (str, (char *)ibuf.product, sizeof(ibuf.product)); strncat (str, (char *)ibuf.revision, sizeof(ibuf.revision)); } dev->sane.model = str; dev->sane.type = "flatbed scanner"; DBG (5, "dev->sane.name = %s\n", dev->sane.name); DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor); DBG (5, "dev->sane.model = %s\n", dev->sane.model); DBG (5, "dev->sane.type = %s\n", dev->sane.type); dev->info.xres_default = _2btol(wbuf.x_res); dev->info.yres_default = _2btol(wbuf.y_res); dev->info.image_mode_default = wbuf.image_comp; /* if you throw the MRIF bit the brighness control reverses too */ /* so I reverse the reversal in software for symmetry's sake */ /* I should make this into an option */ if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME) { dev->info.brightness_default = 256 - wbuf.brightness; /* if (is50) dev->info.contrast_default = wbuf.contrast; else */ dev->info.contrast_default = 256 - wbuf.contrast; } else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */ { dev->info.brightness_default = wbuf.brightness; dev->info.contrast_default = wbuf.contrast; } /* da rivedere dev->info.adf_default = wbuf.adf_state; */ dev->info.adf_default = ADF_UNUSED; dev->info.adf_default = IBM_PAPER_USER_DEFINED; #if 1 dev->info.bmu = mup.bmu; dev->info.mud = _2btol(mup.mud); if (dev->info.mud == 0) { /* The Ricoh says it uses points as default Basic Measurement Unit */ /* but gives a Measurement Unit Divisor of zero */ /* So, we set it to the default (SCSI-standard) of 1200 */ /* with BMU in inches, i.e. 1200 points equal 1 inch */ dev->info.bmu = INCHES; dev->info.mud = DEFAULT_MUD; } #else dev->info.bmu = INCHES; dev->info.mud = DEFAULT_MUD; #endif DBG (5, "xres_default=%d\n", dev->info.xres_default); DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max); DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min); DBG (5, "yres_default=%d\n", dev->info.yres_default); DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max); DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min); DBG (5, "x_range.max=%d\n", dev->info.x_range.max); DBG (5, "y_range.max=%d\n", dev->info.y_range.max); DBG (5, "image_mode=%d\n", dev->info.image_mode_default); DBG (5, "brightness=%d\n", dev->info.brightness_default); DBG (5, "contrast=%d\n", dev->info.contrast_default); DBG (5, "adf_state=%d\n", dev->info.adf_default); DBG (5, "bmu=%d\n", dev->info.bmu); DBG (5, "mud=%d\n", dev->info.mud); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (11, "<< attach\n"); return (SANE_STATUS_GOOD); } static SANE_Status attach_one(const char *devnam) { attach (devnam, NULL); return SANE_STATUS_GOOD; } static SANE_Status init_options (Ibm_Scanner * s) { int i; DBG (11, ">> init_options\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[s->hw->info.image_mode_default]); /* x resolution */ s->opt[OPT_X_RESOLUTION].name = "X" SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].title = "X " SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_X_RESOLUTION].constraint.range = &ibm2456_res_range; s->val[OPT_X_RESOLUTION].w = s->hw->info.xres_default; /* if (is50) s->opt[OPT_X_RESOLUTION].constraint.range = &is50_res_range; else */ s->opt[OPT_X_RESOLUTION].constraint.range = &ibm2456_res_range; /* y resolution */ s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_Y_RESOLUTION].w = s->hw->info.yres_default; s->opt[OPT_Y_RESOLUTION].constraint.range = &ibm2456_res_range; /* adf */ s->opt[OPT_ADF].name = "adf"; s->opt[OPT_ADF].title = "Use ADF"; s->opt[OPT_ADF].desc = "Uses the automatic document feeder."; s->opt[OPT_ADF].type = SANE_TYPE_BOOL; s->opt[OPT_ADF].unit = SANE_UNIT_NONE; s->opt[OPT_ADF].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_ADF].b = s->hw->info.adf_default; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* paper */ s->opt[OPT_PAPER].name = "paper"; s->opt[OPT_PAPER].title = "Paper format"; s->opt[OPT_PAPER].desc = "Sets the paper format."; s->opt[OPT_PAPER].type = SANE_TYPE_STRING; s->opt[OPT_PAPER].size = max_string_size (paper_list); s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_PAPER].constraint.string_list = paper_list; s->val[OPT_PAPER].s = strdup (paper_list[s->hw->info.paper_default]); /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_INT; s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &default_x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_INT; s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &default_y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_INT; s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &default_x_range; s->val[OPT_BR_X].w = default_x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_INT; s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &default_y_range; s->val[OPT_BR_Y].w = default_y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range; s->val[OPT_BRIGHTNESS].w = s->hw->info.brightness_default; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &u8_range; s->val[OPT_CONTRAST].w = s->hw->info.contrast_default; DBG (11, "<< init_options\n"); return SANE_STATUS_GOOD; } static SANE_Status do_cancel (Ibm_Scanner * s) { SANE_Status status; DBG (11, ">> do_cancel\n"); DBG (3, "cancel: sending OBJECT POSITION\n"); status = object_position (s->fd, OBJECT_POSITION_UNLOAD); if (status != SANE_STATUS_GOOD) { DBG (1, "cancel: OBJECT POSTITION failed\n"); } s->scanning = SANE_FALSE; if (s->fd >= 0) { sanei_scsi_close (s->fd); s->fd = -1; } DBG (11, "<< do_cancel\n"); return (SANE_STATUS_CANCELLED); } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char devnam[PATH_MAX] = "/dev/scanner"; FILE *fp; DBG_INIT (); DBG (11, ">> sane_init (authorize %s null)\n", (authorize) ? "!=" : "=="); #if defined PACKAGE && defined VERSION DBG (2, "sane_init: ibm backend version %d.%d-%d (" PACKAGE " " VERSION ")\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); #endif if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open(IBM_CONFIG_FILE); if (fp) { char line[PATH_MAX], *lp; size_t len; /* read config file */ while (sanei_config_read (line, sizeof (line), fp)) { if (line[0] == '#') /* ignore line comments */ continue; len = strlen (line); if (!len) continue; /* ignore empty lines */ /* skip white space: */ for (lp = line; isspace(*lp); ++lp); strcpy (devnam, lp); } fclose (fp); } sanei_config_attach_matching_devices (devnam, attach_one); DBG (11, "<< sane_init\n"); return SANE_STATUS_GOOD; } void sane_exit (void) { Ibm_Device *dev, *next; DBG (11, ">> sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free (dev); } DBG (11, "<< sane_exit\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { static const SANE_Device **devlist = 0; Ibm_Device *dev; int i; DBG (11, ">> sane_get_devices (local_only = %d)\n", local_only); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return (SANE_STATUS_NO_MEM); i = 0; for (dev = first_dev; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (11, "<< sane_get_devices\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devnam, SANE_Handle * handle) { SANE_Status status; Ibm_Device *dev; Ibm_Scanner *s; DBG (11, ">> sane_open\n"); if (devnam[0] == '\0') { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) break; } if (!dev) { status = attach (devnam, &dev); if (status != SANE_STATUS_GOOD) return (status); } } else { dev = first_dev; } if (!dev) return (SANE_STATUS_INVAL); s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->hw = dev; init_options (s); s->next = first_handle; first_handle = s; *handle = s; DBG (11, "<< sane_open\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Ibm_Scanner *s = (Ibm_Scanner *) handle; DBG (11, ">> sane_close\n"); if (s->fd != -1) sanei_scsi_close (s->fd); free (s); DBG (11, ">> sane_close\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Ibm_Scanner *s = handle; DBG (11, ">> sane_get_option_descriptor\n"); if ((unsigned) option >= NUM_OPTIONS) return (0); DBG (11, "<< sane_get_option_descriptor\n"); return (s->opt + option); } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Ibm_Scanner *s = handle; SANE_Status status; SANE_Word cap; DBG (11, ">> sane_control_option\n"); if (info) *info = 0; if (s->scanning) return (SANE_STATUS_DEVICE_BUSY); if (option >= NUM_OPTIONS) return (SANE_STATUS_INVAL); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return (SANE_STATUS_INVAL); if (action == SANE_ACTION_GET_VALUE) { DBG (11, "sane_control_option get_value\n"); switch (option) { /* word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: *(SANE_Word *) val = s->val[option].w; return (SANE_STATUS_GOOD); /* bool options: */ case OPT_ADF: *(SANE_Bool *) val = s->val[option].b; return (SANE_STATUS_GOOD); /* string options: */ case OPT_MODE: case OPT_PAPER: strcpy (val, s->val[option].s); return (SANE_STATUS_GOOD); } } else { DBG (11, "sane_control_option set_value\n"); if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; s->val[option].w = *(SANE_Word *) val; /* resets the paper format to user defined */ if (strcmp(s->val[OPT_PAPER].s, paper_list[IBM_PAPER_USER_DEFINED]) != 0) { if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (s->val[OPT_PAPER].s) free (s->val[OPT_PAPER].s); s->val[OPT_PAPER].s = strdup (paper_list[IBM_PAPER_USER_DEFINED]); } return (SANE_STATUS_GOOD); case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_MODE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return (SANE_STATUS_GOOD); case OPT_ADF: s->val[option].b = *(SANE_Bool *) val; if (*(SANE_Bool *) val) s->adf_state = ADF_ARMED; else s->adf_state = ADF_UNUSED; return (SANE_STATUS_GOOD); case OPT_PAPER: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[OPT_PAPER].s, "User") != 0) { s->val[OPT_TL_X].w = 0; s->val[OPT_TL_Y].w = 0; if (strcmp (s->val[OPT_PAPER].s, "A3") == 0) { s->val[OPT_BR_X].w = PAPER_A3_W; s->val[OPT_BR_Y].w = PAPER_A3_H; } else if (strcmp (s->val[OPT_PAPER].s, "A4") == 0) { s->val[OPT_BR_X].w = PAPER_A4_W; s->val[OPT_BR_Y].w = PAPER_A4_H; } else if (strcmp (s->val[OPT_PAPER].s, "A4R") == 0) { s->val[OPT_BR_X].w = PAPER_A4R_W; s->val[OPT_BR_Y].w = PAPER_A4R_H; } else if (strcmp (s->val[OPT_PAPER].s, "A5") == 0) { s->val[OPT_BR_X].w = PAPER_A5_W; s->val[OPT_BR_Y].w = PAPER_A5_H; } else if (strcmp (s->val[OPT_PAPER].s, "A5R") == 0) { s->val[OPT_BR_X].w = PAPER_A5R_W; s->val[OPT_BR_Y].w = PAPER_A5R_H; } else if (strcmp (s->val[OPT_PAPER].s, "A6") == 0) { s->val[OPT_BR_X].w = PAPER_A6_W; s->val[OPT_BR_Y].w = PAPER_A6_H; } else if (strcmp (s->val[OPT_PAPER].s, "B4") == 0) { s->val[OPT_BR_X].w = PAPER_B4_W; s->val[OPT_BR_Y].w = PAPER_B4_H; } else if (strcmp (s->val[OPT_PAPER].s, "Legal") == 0) { s->val[OPT_BR_X].w = PAPER_LEGAL_W; s->val[OPT_BR_Y].w = PAPER_LEGAL_H; } else if (strcmp (s->val[OPT_PAPER].s, "Letter") == 0) { s->val[OPT_BR_X].w = PAPER_LETTER_W; s->val[OPT_BR_Y].w = PAPER_LETTER_H; } } return (SANE_STATUS_GOOD); } } } DBG (11, "<< sane_control_option\n"); return (SANE_STATUS_INVAL); } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Ibm_Scanner *s = handle; DBG (11, ">> sane_get_parameters\n"); if (!s->scanning) { int width, length, xres, yres; const char *mode; memset (&s->params, 0, sizeof (s->params)); width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w; length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w; xres = s->val[OPT_X_RESOLUTION].w; yres = s->val[OPT_Y_RESOLUTION].w; /* make best-effort guess at what parameters will look like once scanning starts. */ if (xres > 0 && yres > 0 && width > 0 && length > 0) { s->params.pixels_per_line = width * xres / s->hw->info.mud; s->params.lines = length * yres / s->hw->info.mud; } mode = s->val[OPT_MODE].s; if ((strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) || (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE)) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line / 8; /* the Ibm truncates to the byte boundary, so: chop! */ s->params.pixels_per_line = s->params.bytes_per_line * 8; s->params.depth = 1; } else /* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */ { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } s->params.last_frame = SANE_TRUE; } else DBG (5, "sane_get_parameters: scanning, so can't get params\n"); if (params) *params = s->params; DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w); DBG (11, "<< sane_get_parameters\n"); return (SANE_STATUS_GOOD); } SANE_Status sane_start (SANE_Handle handle) { char *mode_str; Ibm_Scanner *s = handle; SANE_Status status; struct ibm_window_data wbuf; struct measurements_units_page mup; DBG (11, ">> sane_start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return (status); } mode_str = s->val[OPT_MODE].s; s->xres = s->val[OPT_X_RESOLUTION].w; s->yres = s->val[OPT_Y_RESOLUTION].w; s->ulx = s->val[OPT_TL_X].w; s->uly = s->val[OPT_TL_Y].w; s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w; s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w; s->brightness = s->val[OPT_BRIGHTNESS].w; s->contrast = s->val[OPT_CONTRAST].w; s->bpp = s->params.depth; if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->image_composition = IBM_BINARY_MONOCHROME; } else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { s->image_composition = IBM_DITHERED_MONOCHROME; } else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0) { s->image_composition = IBM_GRAYSCALE; } memset (&wbuf, 0, sizeof (wbuf)); /* next line commented out by mf */ /* _lto2b(sizeof(wbuf) - 8, wbuf.len); */ /* next line by mf */ _lto2b(IBM_WINDOW_DATA_SIZE, wbuf.len); /* size=320 */ _lto2b(s->xres, wbuf.x_res); _lto2b(s->yres, wbuf.y_res); _lto4b(s->ulx, wbuf.x_org); _lto4b(s->uly, wbuf.y_org); _lto4b(s->width, wbuf.width); _lto4b(s->length, wbuf.length); wbuf.image_comp = s->image_composition; /* if you throw the MRIF bit the brighness control reverses too */ /* so I reverse the reversal in software for symmetry's sake */ if (wbuf.image_comp == IBM_GRAYSCALE || wbuf.image_comp == IBM_DITHERED_MONOCHROME) { if (wbuf.image_comp == IBM_GRAYSCALE) wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x80; /* it was 0x90 */ if (wbuf.image_comp == IBM_DITHERED_MONOCHROME) wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10; wbuf.brightness = 256 - (SANE_Byte) s->brightness; /* if (is50) wbuf.contrast = (SANE_Byte) s->contrast; else */ wbuf.contrast = 256 - (SANE_Byte) s->contrast; } else /* wbuf.image_comp == IBM_BINARY_MONOCHROME */ { wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00; wbuf.brightness = (SANE_Byte) s->brightness; wbuf.contrast = (SANE_Byte) s->contrast; } wbuf.threshold = 0; wbuf.bits_per_pixel = s->bpp; wbuf.halftone_code = 2; /* diithering */ wbuf.halftone_id = 0x0A; /* 8x8 Bayer pattenr */ wbuf.pad_type = 3; wbuf.bit_ordering[0] = 0; wbuf.bit_ordering[1] = 7; /* modified by mf (it was 3) */ DBG (5, "xres=%d\n", _2btol(wbuf.x_res)); DBG (5, "yres=%d\n", _2btol(wbuf.y_res)); DBG (5, "ulx=%d\n", _4btol(wbuf.x_org)); DBG (5, "uly=%d\n", _4btol(wbuf.y_org)); DBG (5, "width=%d\n", _4btol(wbuf.width)); DBG (5, "length=%d\n", _4btol(wbuf.length)); DBG (5, "image_comp=%d\n", wbuf.image_comp); DBG (11, "sane_start: sending SET WINDOW\n"); status = set_window (s->fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (11, "sane_start: sending GET WINDOW\n"); memset (&wbuf, 0, sizeof (wbuf)); status = get_window (s->fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (5, "xres=%d\n", _2btol(wbuf.x_res)); DBG (5, "yres=%d\n", _2btol(wbuf.y_res)); DBG (5, "ulx=%d\n", _4btol(wbuf.x_org)); DBG (5, "uly=%d\n", _4btol(wbuf.y_org)); DBG (5, "width=%d\n", _4btol(wbuf.width)); DBG (5, "length=%d\n", _4btol(wbuf.length)); DBG (5, "image_comp=%d\n", wbuf.image_comp); DBG (11, "sane_start: sending MODE SELECT\n"); memset (&mup, 0, sizeof (mup)); mup.page_code = MEASUREMENTS_PAGE; mup.parameter_length = 0x06; mup.bmu = INCHES; mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff; mup.mud[1] = (DEFAULT_MUD & 0xff); /* next lines by mf */ mup.adf_page_code = 0x26; mup.adf_parameter_length = 6; if (s->adf_state == ADF_ARMED) mup.adf_control = 1; else mup.adf_control = 0; /* end lines by mf */ status = mode_select (s->fd, (struct mode_pages *) &mup); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT failed\n"); return (SANE_STATUS_INVAL); } status = trigger_scan (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "start of scan failed: %s\n", sane_strstatus (status)); /* next line introduced not to freeze xscanimage */ do_cancel(s); return status; } /* Wait for scanner to become ready to transmit data */ status = ibm_wait_ready (s); if (status != SANE_STATUS_GOOD) { DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status)); return (status); } s->bytes_to_read = s->params.bytes_per_line * s->params.lines; DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w); s->scanning = SANE_TRUE; DBG (11, "<< sane_start\n"); return (SANE_STATUS_GOOD); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Ibm_Scanner *s = handle; SANE_Status status; size_t nread; DBG (11, ">> sane_read\n"); *len = 0; DBG (11, "sane_read: bytes left to read: %ld\n", (u_long) s->bytes_to_read); if (s->bytes_to_read == 0) { do_cancel (s); return (SANE_STATUS_EOF); } if (!s->scanning) { DBG (11, "sane_read: scanning is false!\n"); return (do_cancel (s)); } nread = max_len; if (nread > s->bytes_to_read) nread = s->bytes_to_read; DBG (11, "sane_read: read %ld bytes\n", (u_long) nread); status = read_data (s->fd, buf, &nread); if (status != SANE_STATUS_GOOD) { DBG (11, "sane_read: read error\n"); do_cancel (s); return (SANE_STATUS_IO_ERROR); } *len = nread; s->bytes_to_read -= nread; DBG (11, "<< sane_read\n"); return (SANE_STATUS_GOOD); } void sane_cancel (SANE_Handle handle) { Ibm_Scanner *s = handle; DBG (11, ">> sane_cancel\n"); s->scanning = SANE_FALSE; DBG (11, "<< sane_cancel\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (5, ">> sane_set_io_mode (handle = %p, non_blocking = %d)\n", handle, non_blocking); DBG (5, "<< sane_set_io_mode\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (5, ">> sane_get_select_fd (handle = %p, fd = %p)\n", handle, (void *) fd); DBG (5, "<< sane_get_select_fd\n"); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/xerox_mfp-tcp.c0000664000175000017500000001061713063340150015550 00000000000000/* * SANE backend for * Samsung SCX-4500W * * Network Scanners Support * Copyright 2010 Alexander Kuznetsov * * This program is licensed under GPL + SANE exception. * More info at http://www.sane-project.org/license.html * */ #undef BACKEND_NAME #define BACKEND_NAME xerox_mfp #define DEBUG_DECLARE_ONLY #define DEBUG_NOT_STATIC #include "sane/config.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #include "sane/saneopts.h" #include "sane/sanei_scsi.h" #include "sane/sanei_usb.h" #include "sane/sanei_pio.h" #include "sane/sanei_tcp.h" #include "sane/sanei_udp.h" #include "sane/sanei_backend.h" #include "sane/sanei_config.h" #include "xerox_mfp.h" #define RECV_TIMEOUT 1 /* seconds */ extern int sanei_debug_xerox_mfp; int tcp_dev_request(struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen) { size_t bytes_recv = 0; ssize_t rc = 1; size_t len; /* Send request, if any */ if (cmd && cmdlen) { len = (size_t)sanei_tcp_write(dev->dn, cmd, cmdlen); if (len != cmdlen) { DBG(1, "%s: sent only %lu bytes of %lu\n", __func__, (u_long)len, (u_long)cmdlen); return SANE_STATUS_IO_ERROR; } } /* Receive response, if expected */ if (resp && resplen) { DBG(3, "%s: wait for %i bytes\n", __func__, (int)*resplen); while (bytes_recv < *resplen && rc > 0) { rc = recv(dev->dn, resp+bytes_recv, *resplen-bytes_recv, 0); if (rc > 0) bytes_recv += rc; else { DBG(1, "%s: error %s, bytes requested: %i, bytes read: %i\n", __func__, strerror(errno), (int)*resplen, (int)bytes_recv); *resplen = bytes_recv; /* TODO: do something smarter than that! */ return SANE_STATUS_GOOD; return SANE_STATUS_IO_ERROR; } } } *resplen = bytes_recv; return SANE_STATUS_GOOD; } SANE_Status tcp_dev_open(struct device *dev) { SANE_Status status; char *strhost; char *strport; int port; struct servent *sp; struct timeval tv; SANE_String_Const devname; devname = dev->sane.name; DBG(3, "%s: open %s\n", __func__, devname); if (strncmp(devname, "tcp", 3) != 0) return SANE_STATUS_INVAL; devname += 3; devname = sanei_config_skip_whitespace(devname); if (!*devname) return SANE_STATUS_INVAL; devname = sanei_config_get_string(devname, &strhost); devname = sanei_config_skip_whitespace(devname); if (*devname) devname = sanei_config_get_string(devname, &strport); else strport = "9400"; if (isdigit(*strport)) { port = atoi(strport); } else { if ((sp = getservbyname(strport, "tcp"))) { port = ntohs(sp->s_port); } else { DBG(1, "%s: unknown TCP service %s\n", __func__, strport); return SANE_STATUS_IO_ERROR; } } status = sanei_tcp_open(strhost, port, &dev->dn); if (status == SANE_STATUS_GOOD) { tv.tv_sec = RECV_TIMEOUT; tv.tv_usec = 0; if (setsockopt(dev->dn, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv) < 0) { DBG(1, "%s: setsockopts %s", __func__, strerror(errno)); } } return status; } void tcp_dev_close(struct device *dev) { if (!dev) return; DBG(3, "%s: closing dev %p\n", __func__, (void *)dev); /* finish all operations */ if (dev->scanning) { dev->cancel = 1; /* flush READ_IMAGE data */ if (dev->reading) sane_read(dev, NULL, 1, NULL); /* send cancel if not sent before */ if (dev->state != SANE_STATUS_CANCELLED) ret_cancel(dev, 0); } sanei_tcp_close(dev->dn); dev->dn = -1; } SANE_Status tcp_configure_device(const char *devname, SANE_Status(*list_one)(SANE_String_Const devname)) { /* TODO: LAN scanners multicast discovery. devname would contain "tcp auto" We find new devnames and feed them to `list_one_device' one by one */ return list_one(devname); } /* xerox_mfp-tcp.c */ sane-backends-1.0.27/backend/rts88xx_lib.h0000664000175000017500000001565012775277260015206 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007-2012 stef.dev@free.fr This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef RTS88XX_LIB_H #define RTS88XX_LIB_H #include "../include/sane/sane.h" #include "../include/sane/sanei_usb.h" #include #include /* TODO put his in a place where it can be reused */ #define DBG_error0 0 /* errors/warnings printed even with debuglevel 0 */ #define DBG_error 1 /* fatal errors */ #define DBG_init 2 /* initialization and scanning time messages */ #define DBG_warn 3 /* warnings and non-fatal errors */ #define DBG_info 4 /* informational messages */ #define DBG_proc 5 /* starting/finishing functions */ #define DBG_io 6 /* io functions */ #define DBG_io2 7 /* io functions that are called very often */ #define DBG_data 8 /* log data sent and received */ /* * defines for registers name */ #define CONTROL_REG 0xb3 #define CONTROLER_REG 0x1d /* geometry registers */ #define START_LINE 0x60 #define END_LINE 0x62 #define START_PIXEL 0x66 #define END_PIXEL 0x6c #define RTS88XX_MAX_XFER_SIZE 0xFFC0 #define LOBYTE(x) ((uint8_t)((x) & 0xFF)) #define HIBYTE(x) ((uint8_t)((x) >> 8)) /* this function init the rts88xx library */ void sanei_rts88xx_lib_init (void); SANE_Bool sanei_rts88xx_is_color (SANE_Byte * regs); void sanei_rts88xx_set_gray_scan (SANE_Byte * regs); void sanei_rts88xx_set_color_scan (SANE_Byte * regs); void sanei_rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, SANE_Byte blue); void sanei_rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, SANE_Byte blue); void sanei_rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency); /* * set scan area */ void sanei_rts88xx_set_scan_area (SANE_Byte * reg, SANE_Int ystart, SANE_Int yend, SANE_Int xstart, SANE_Int xend); /* * read one register at given index */ SANE_Status sanei_rts88xx_read_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg); /* * read scanned data from scanner up to the size given. The actual length read is returned. */ SANE_Status sanei_rts88xx_read_data (SANE_Int devnum, SANE_Word * length, unsigned char *dest); /* * write one register at given index */ SANE_Status sanei_rts88xx_write_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg); /* * write length consecutive registers, starting at index * register 0xb3 is never wrote in bulk register write, so we split * write if it belongs to the register set sent */ SANE_Status sanei_rts88xx_write_regs (SANE_Int devnum, SANE_Int start, SANE_Byte * source, SANE_Int length); /* read several registers starting at the given index */ SANE_Status sanei_rts88xx_read_regs (SANE_Int devnum, SANE_Int start, SANE_Byte * dest, SANE_Int length); /* * get status by reading registers 0x10 and 0x11 */ SANE_Status sanei_rts88xx_get_status (SANE_Int devnum, SANE_Byte * regs); /* * set status by writing registers 0x10 and 0x11 */ SANE_Status sanei_rts88xx_set_status (SANE_Int devnum, SANE_Byte * regs, SANE_Byte reg10, SANE_Byte reg11); /* * get lamp status by reading registers 0x84 to 0x8d */ SANE_Status sanei_rts88xx_get_lamp_status (SANE_Int devnum, SANE_Byte * regs); /* reset lamp */ SANE_Status sanei_rts88xx_reset_lamp (SANE_Int devnum, SANE_Byte * regs); /* get lcd panel status */ SANE_Status sanei_rts88xx_get_lcd (SANE_Int devnum, SANE_Byte * regs); /* * write to special control register CONTROL_REG=0xb3 */ SANE_Status sanei_rts88xx_write_control (SANE_Int devnum, SANE_Byte value); /* * send the cancel control sequence */ SANE_Status sanei_rts88xx_cancel (SANE_Int devnum); /* * read available data count from scanner */ SANE_Status sanei_rts88xx_data_count (SANE_Int devnum, SANE_Word * count); /* * wait for scanned data to be available, if busy is true, check is scanner is busy * while waiting. The number of data bytes of available data is returned in 'count'. */ SANE_Status sanei_rts88xx_wait_data (SANE_Int devnum, SANE_Bool busy, SANE_Word * count); /* * write the given number of bytes pointed by value into memory */ SANE_Status sanei_rts88xx_write_mem (SANE_Int devnum, SANE_Int length, SANE_Int extra, SANE_Byte * value); /* * set memory with the given data */ SANE_Status sanei_rts88xx_set_mem (SANE_Int devnum, SANE_Byte ctrl1, SANE_Byte ctrl2, SANE_Int length, SANE_Byte * value); /* * read the given number of bytes from memory into buffer */ SANE_Status sanei_rts88xx_read_mem (SANE_Int devnum, SANE_Int length, SANE_Byte * value); /* * get memory */ SANE_Status sanei_rts88xx_get_mem (SANE_Int devnum, SANE_Byte ctrl1, SANE_Byte ctrl2, SANE_Int length, SANE_Byte * value); /* * write to the nvram controler */ SANE_Status sanei_rts88xx_nvram_ctrl (SANE_Int devnum, SANE_Int length, SANE_Byte * value); /* * setup nvram */ SANE_Status sanei_rts88xx_setup_nvram (SANE_Int devnum, SANE_Int length, SANE_Byte * value); /* does a simple scan, putting data in image */ /* SANE_Status sanei_rts88xx_simple_scan (SANE_Int devnum, SANE_Byte * regs, int regcount, SANE_Word size, unsigned char *image); */ #endif /* not RTS88XX_LIB_H */ sane-backends-1.0.27/backend/u12-ccd.c0000664000175000017500000012620612112021330014103 00000000000000/* @file u12-ccd.c * @brief here we have the whole code to intialize the CCD and DAC stuff * * based on sources acquired from Plustek Inc. * Copyright (c) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /*************************** some definitions ********************************/ #define _REFLECTION 0 #define _TRANSPARENCY 1 #define _NEGATIVE 2 #define _NUM_OF_CCDREGS_W8143 25 #define _NUM_OF_DACREGS_W8143 10 #define _NUM_OF_CCDREGS_S1224 29 #define _NUM_OF_DACREGS_S1224 7 #define _NUM_OF_CCDREGS_S8531 29 #define _NUM_OF_DACREGS_S8531 9 /*************************** some local vars *********************************/ static pFnVoid u12ccd_InitFunc = NULL; static RegDef W3797CCDParams[4][_NUM_OF_CCDREGS_W8143] = { { {0x2c, 0x02}, {0x39, 0x2a}, {0x3a, 0x0a}, {0x3b, 0x37}, {0x3c, 0x16}, {0x41, 0x0e}, {0x42, 0x90}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x03}, {0x48, 0x27}, {0x49, 0x2f}, {0x4a, 0x09}, {0x4b, 0x03}, {0x4c, 0x07}, {0x4d, 0x06}, {0x4e, 0x06}, {0x67, 0x00}, {0x50, 0x08}, {0x51, 0x0e}, {0x52, 0x0c}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x3d}, {0x3a, 0x04}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x1f}, {0x42, 0x8c}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x00}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x01}, {0x51, 0x06}, {0x52, 0x09}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x00}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x04}, {0x42, 0x1e}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xf9}, {0x4b, 0x04}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x03}, {0x67, 0x00}, {0x50, 0x06}, {0x51, 0x03}, {0x52, 0x09}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x18}, {0x3a, 0x04}, {0x3b, 0x1d}, {0x3c, 0x03}, {0x41, 0x0c}, {0x42, 0x84}, {0x43, 0x03}, {0x44, 0x0a}, {0x45, 0x08}, {0x46, 0xfa}, {0x47, 0x04}, {0x48, 0x0a}, {0x49, 0x08}, {0x4a, 0xf2}, {0x4b, 0x02}, {0x4c, 0x03}, {0x4d, 0x02}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x00}, {0x51, 0x09}, {0x52, 0x03}, {0x53, 0x03}, {0xf0, 0x00} } }; static RegDef W3799CCDParams[4][_NUM_OF_CCDREGS_W8143] = { { {0x2c, 0x02}, {0x39, 0x2c}, {0x3a, 0x05}, {0x3b, 0x3c}, {0x3c, 0x0e}, {0x41, 0x0e}, {0x42, 0x90}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x02}, {0x48, 0x27}, {0x49, 0x2f}, {0x4a, 0x09}, {0x4b, 0x05}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x06}, {0x67, 0x00}, {0x50, 0x08}, {0x51, 0x0d}, {0x52, 0x0c}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x3d}, {0x3a, 0x04}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x1f}, {0x42, 0x8c}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x00}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x01}, {0x51, 0x06}, {0x52, 0x12}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x00}, {0x39, 0x16}, {0x3a, 0x02}, {0x3b, 0x1a}, {0x3c, 0x05}, {0x41, 0x04}, {0x42, 0x1e}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xf9}, {0x4b, 0x04}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x03}, {0x67, 0x00}, {0x50, 0x06}, {0x51, 0x03}, {0x52, 0x09}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x18}, {0x3a, 0x04}, {0x3b, 0x1d}, {0x3c, 0x03}, {0x41, 0x0c}, {0x42, 0x84}, {0x43, 0x03}, {0x44, 0x0a}, {0x45, 0x08}, {0x46, 0xfa}, {0x47, 0x03}, {0x48, 0x0a}, {0x49, 0x08}, {0x4a, 0xf2}, {0x4b, 0x02}, {0x4c, 0x03}, {0x4d, 0x02}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x00}, {0x51, 0x09}, {0x52, 0x03}, {0x53, 0x03}, {0xf0, 0x00} } }; /* Genius ColorPage Vivid III */ static RegDef W548CCDParams[4][_NUM_OF_CCDREGS_W8143] = { { {0x2c, 0x02}, {0x39, 0x2c}, {0x3a, 0x05}, {0x3b, 0x3c}, {0x3c, 0x0e}, {0x41, 0x0e}, {0x42, 0x90}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x02}, {0x48, 0x27}, {0x49, 0x2f}, {0x4a, 0x09}, {0x4b, 0x05}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x06}, {0x67, 0x00}, {0x50, 0x08}, {0x51, 0x0d}, {0x52, 0x0c}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x3d}, {0x3a, 0x04}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x1f}, {0x42, 0x8c}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x00}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x01}, {0x51, 0x06}, {0x52, 0x12}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x00}, {0x39, 0x16}, {0x3a, 0x02}, {0x3b, 0x1a}, {0x3c, 0x05}, {0x41, 0x04}, {0x42, 0x1e}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xf9}, {0x4b, 0x04}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x03}, {0x67, 0x00}, {0x50, 0x06}, {0x51, 0x03}, {0x52, 0x09}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x18}, {0x3a, 0x04}, {0x3b, 0x1d}, {0x3c, 0x03}, {0x41, 0x0c}, {0x42, 0x84}, {0x43, 0x03}, {0x44, 0x0a}, {0x45, 0x08}, {0x46, 0xfa}, {0x47, 0x03}, {0x48, 0x0a}, {0x49, 0x08}, {0x4a, 0xf2}, {0x4b, 0x02}, {0x4c, 0x03}, {0x4d, 0x02}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x00}, {0x51, 0x09}, {0x52, 0x03}, {0x53, 0x03}, {0xf0, 0x00} } }; static RegDef S3797CCDParams[4][_NUM_OF_CCDREGS_S1224] = { { {0x2c, 0x00}, {0x39, 0x2a}, {0x3a, 0x0a}, {0x3b, 0x37}, {0x3c, 0x16}, {0x41, 0x2c}, {0x42, 0x9f}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x03}, {0x48, 0x27}, {0x49, 0x27}, {0x4a, 0x09}, {0x4b, 0x0b}, {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x0b}, {0x50, 0x13}, {0x51, 0x06}, {0x52, 0x06}, {0x53, 0x0b}, {0x67, 0x00}, {0x6f, 0x20}, {0x70, 0x06}, {0x60, 0x07}, {0x61, 0x9f}, {0x65, 0x01} }, { {0x2c, 0x00}, {0x39, 0x3d}, {0x3a, 0x06}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x3d}, {0x42, 0x92}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x1b}, {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x0b}, {0x50, 0x23}, {0x51, 0x06}, {0x52, 0x06}, {0x53, 0x0b}, {0x67, 0x00}, {0x6f, 0x30}, {0x70, 0x06}, {0x60, 0x17}, {0x61, 0x9f}, {0x65, 0x01} }, { {0x2c, 0x02}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x1c}, {0x42, 0x99}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x09}, {0x4c, 0x13}, {0x4d, 0x14}, {0x4e, 0x09}, {0x50, 0x09}, {0x51, 0x14}, {0x52, 0x13}, {0x53, 0x01}, {0x67, 0x00}, {0x6f, 0xff}, {0x70, 0x7f}, {0x60, 0x04}, {0x61, 0x8f}, {0x65, 0x01} }, { {0x2c, 0x02}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x1c}, {0x42, 0x99}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x09}, {0x4c, 0x13}, {0x4d, 0x14}, {0x4e, 0x09}, {0x50, 0x09}, {0x51, 0x14}, {0x52, 0x13}, {0x53, 0x01}, {0x67, 0x00}, {0x6f, 0xff}, {0x70, 0x7f}, {0x60, 0x04}, {0x61, 0x8f}, {0x65, 0x01} } }; static RegDef S3799CCDParams[4][_NUM_OF_CCDREGS_S1224] = { { {0x2c, 0x00}, {0x39, 0x2a}, {0x3a, 0x0a}, {0x3b, 0x37}, {0x3c, 0x16}, {0x41, 0x2c}, {0x42, 0x8f}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x01}, {0x48, 0x27}, {0x49, 0x27}, {0x4a, 0x09}, {0x4b, 0x0b}, {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x0b}, {0x50, 0x13}, {0x51, 0x06}, {0x52, 0x06}, {0x53, 0x0b}, {0x67, 0x00}, {0x6f, 0x20}, {0x70, 0x06}, {0x60, 0x07}, {0x61, 0x9f}, {0x65, 0x01} }, { {0x2c, 0x00}, {0x39, 0x3d}, {0x3a, 0x06}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x3d}, {0x42, 0x92}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x1b}, {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x0b}, {0x50, 0x23}, {0x51, 0x06}, {0x52, 0x06}, {0x53, 0x0b}, {0x67, 0x00}, {0x6f, 0x30}, {0x70, 0x06}, {0x60, 0x17}, {0x61, 0x9f}, {0x65, 0x01} }, { {0x2c, 0x02}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x1c}, {0x42, 0x99}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x09}, {0x4c, 0x13}, {0x4d, 0x14}, {0x4e, 0x09}, {0x50, 0x09}, {0x51, 0x14}, {0x52, 0x13}, {0x53, 0x01}, {0x67, 0x00}, {0x6f, 0xff}, {0x70, 0x7f}, {0x60, 0x04}, {0x61, 0x8f}, {0x65, 0x01} }, { {0x2c, 0x00}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x1c}, {0x42, 0x99}, {0x43, 0x03}, {0x44, 0x0a}, {0x45, 0x08}, {0x46, 0xfa}, {0x47, 0x03}, {0x48, 0x0a}, {0x49, 0x08}, {0x4a, 0xf2}, {0x4b, 0x02}, {0x4c, 0x03}, {0x4d, 0x02}, {0x4e, 0x0e}, {0x50, 0x00}, {0x51, 0x09}, {0x52, 0x03}, {0x53, 0x03}, {0x67, 0x00}, {0x6f, 0xff}, {0x70, 0x7f}, {0x60, 0x04}, {0x61, 0x8f}, {0x65, 0x01} } }; static RegDef WolfsonDAC8143[_NUM_OF_DACREGS_W8143] = { {0x01, 0x01}, {0x02, 0x04}, {0x03, 0x42}, {0x05, 0x10}, {0x20, 0xd0}, {0x21, 0xd0}, {0x22, 0xd0}, {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00} }; static RegDef SamsungDAC8531[_NUM_OF_DACREGS_S8531] = { {0x00, 0x51}, {0x02, 0x01}, {0x01, 0x80}, {0x00, 0x55}, {0x02, 0x01}, {0x01, 0x80}, {0x00, 0x59}, {0x02, 0x01}, {0x01, 0x80} }; static RegDef SamsungDAC1224[_NUM_OF_DACREGS_S1224] ={ {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x03, 0x80}, {0x04, 0x06}, {0x05, 0x06}, {0x06, 0x06} }; static ShadingVarDef ShadingVar3797[3] = { { {{99, 100, 94}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x04, 0x00, 0x00}}, {{0xcc, 0xcc, 0xcc}}, 0 }, { {{100, 90, 100}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0xcc, 0xcc, 0xcc}}, 0 }, { {{90, 90, 90}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x80, 0x80, 0x80}}, 0 } }; static ShadingVarDef ShadingVar3799[3] = { { {{100, 97, 92}}, {{0x90, 0xe0, 0x80}}, {{0x70, 0xc0, 0x60}}, {{0x90, 0x34, 0x3c}}, {{0x80, 0x80, 0x80}}, 0 }, { {{75, 75, 75}}, {{0x30, 0x30, 0x30}}, {{0x10, 0x10, 0x10}}, {{0x20, 0x20, 0x20}}, {{0x80, 0x80, 0x80}}, 0 }, { {{80, 75, 64}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x80, 0x80, 0x80}}, 0 } }; /* Genius ColorPage Vivid III */ static ShadingVarDef ShadingVar548[3] = { { {{100, 97, 92}}, {{0x90, 0xe0, 0x80}}, {{0x70, 0xc0, 0x60}}, {{0x90, 0x34, 0x3c}}, {{0x80, 0x80, 0x80}}, 0 }, { {{75, 75, 75}}, {{0x30, 0x30, 0x30}}, {{0x10, 0x10, 0x10}}, {{0x20, 0x20, 0x20}}, {{0x80, 0x80, 0x80}}, 0 }, { {{80, 75, 64}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x80, 0x80, 0x80}}, 0 } }; static ShadingVarDef ShadingVar3777[3] = { { {{100, 100, 100}}, {{0x90, 0xe0, 0x80}}, {{0x70, 0xc0, 0x60}}, {{0x90, 0x34, 0x3c}}, {{0x80, 0x80, 0x80}}, 0 }, { {{75, 75, 75}}, {{0x30, 0x30, 0x30}}, {{0x10, 0x10, 0x10}}, {{0x20, 0x20, 0x20}}, {{0x80, 0x80, 0x80}}, 0 }, { {{80, 75, 64}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x80, 0x80, 0x80}}, 0 } }; /*************************** local functions *********************************/ /** */ static void fnCCDInitWolfson3797( U12_Device *dev ) { if( dev->shade.intermediate & _ScanMode_Mono ) dev->shade.pCcdDac->DarkDAC.Colors.Green = 0xcc; else if( dev->shade.intermediate & _ScanMode_AverageOut) dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x68; else dev->shade.pCcdDac->DarkDAC.Colors.Green = 0xa0; if((dev->shade.intermediate & _ScanMode_AverageOut) || (dev->DataInf.dwScanFlag & _SCANDEF_Negative)) { WolfsonDAC8143[3].val = 0x12; } else { WolfsonDAC8143[3].val = 0x10; } } /** */ static void fnCCDInitSamsung3797( U12_Device *dev ) { if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA)) { if (!(dev->shade.intermediate & _ScanMode_AverageOut)) { if( dev->PCBID == _OPTICWORKS2000 ) { dev->shade.pCcdDac->GainResize.Colors.Red = 102; dev->shade.pCcdDac->GainResize.Colors.Green = 102; dev->shade.pCcdDac->GainResize.Colors.Blue = 97; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x40; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x40; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x40; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x48; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x40; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x40; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x38; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x48; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x38; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x40; } else { dev->shade.pCcdDac->GainResize.Colors.Red = 99; dev->shade.pCcdDac->GainResize.Colors.Green = 101; dev->shade.pCcdDac->GainResize.Colors.Blue = 94; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x40; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x40; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x40; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x04; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x00; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x00; } } else { if( dev->PCBID == _OPTICWORKS2000 ) { dev->shade.pCcdDac->GainResize.Colors.Red = 100; dev->shade.pCcdDac->GainResize.Colors.Green = 100; dev->shade.pCcdDac->GainResize.Colors.Blue = 96; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x30; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x30; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x48; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x48; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x48; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x38; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x38; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x38; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x48; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x48; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x48; } else { dev->shade.pCcdDac->GainResize.Colors.Red = 100; /* 98 */ dev->shade.pCcdDac->GainResize.Colors.Green = 103; /* 106 */ dev->shade.pCcdDac->GainResize.Colors.Blue = 96; /* 96 */ dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x20; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x10; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x10; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x110; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x1f0; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x190; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x100; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x1e0; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x180; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x20; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x10; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x20; } } } } /** */ static void fnCCDInitWolfson3799( U12_Device *dev ) { if(!(dev->DataInf.dwScanFlag & _SCANDEF_Negative)) { if (!(dev->shade.intermediate & _ScanMode_AverageOut)) { dev->shade.pCcdDac->GainResize.Colors.Red = 103; dev->shade.pCcdDac->GainResize.Colors.Green = 102; dev->shade.pCcdDac->GainResize.Colors.Blue = 99; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0xc8; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0xc8; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0xc8; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x48; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x40; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x48; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x18; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x2c; } else { dev->shade.pCcdDac->GainResize.Colors.Red = 100; dev->shade.pCcdDac->GainResize.Colors.Green = 98; dev->shade.pCcdDac->GainResize.Colors.Blue = 95; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0xd0; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0xd0; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0xd0; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x0; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x0; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x0; } } else { dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x80; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x80; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x80; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x28; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; dev->shade.pCcdDac->DarkOffSub.Colors.Red = -0x38; dev->shade.pCcdDac->DarkOffSub.Colors.Green = -0x108; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = -0x1c8; } } /** */ static void fnCCDInitWolfson548( U12_Device *dev ) { if (!(dev->shade.intermediate & _ScanMode_AverageOut)) { dev->shade.pCcdDac->GainResize.Colors.Red = 103; dev->shade.pCcdDac->GainResize.Colors.Green = 102; dev->shade.pCcdDac->GainResize.Colors.Blue = 99; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0xc8; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0xc8; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0xc8; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x48; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x40; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x48; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x18; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x2c; } else { dev->shade.pCcdDac->GainResize.Colors.Red = 100; dev->shade.pCcdDac->GainResize.Colors.Green = 98; dev->shade.pCcdDac->GainResize.Colors.Blue = 95; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0xd0; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0xd0; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0xd0; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x0; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x0; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x0; } } /** */ static void fnCCDInitSamsung3777( U12_Device *dev ) { if(!(dev->DataInf.dwScanFlag & _SCANDEF_Negative)) { if (!(dev->shade.intermediate & _ScanMode_AverageOut)) { dev->shade.pCcdDac->GainResize.Colors.Red = 109; dev->shade.pCcdDac->GainResize.Colors.Green = 108; dev->shade.pCcdDac->GainResize.Colors.Blue = 105; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x4a; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x4a; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x4a; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x3c; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x38; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x38; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x2c; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x30; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x30; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x3C; } else { dev->shade.pCcdDac->GainResize.Colors.Red = 108; dev->shade.pCcdDac->GainResize.Colors.Green = 107; dev->shade.pCcdDac->GainResize.Colors.Blue = 104; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x50; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x50; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x50; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x40; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x40; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x40; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x20; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x20; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x20; } } else { dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x80; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x80; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x80; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x28; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; dev->shade.pCcdDac->DarkOffSub.Colors.Red = -0x38; dev->shade.pCcdDac->DarkOffSub.Colors.Green = -0x108; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = -0x1c8; } } /** */ static void fnCCDInitSamsung3799( U12_Device *dev ) { if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA)) { if (!(dev->shade.intermediate & _ScanMode_AverageOut)) { if( dev->PCBID == _SCANNER2Button ) { dev->shade.pCcdDac->GainResize.Colors.Red = 109; dev->shade.pCcdDac->GainResize.Colors.Green = 109; dev->shade.pCcdDac->GainResize.Colors.Blue = 105; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x68; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x68; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x68; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x24; /* 0 */ dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x20; /* 0 */ dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x1c; /* 0 */ } else { dev->shade.pCcdDac->GainResize.Colors.Red = 98; dev->shade.pCcdDac->GainResize.Colors.Green = 97; dev->shade.pCcdDac->GainResize.Colors.Blue = 92; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x90; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x90; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x90; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0xc0; /* 0x90 */ dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0xc0; /* 0xe0 */ dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0xc0; /* 0x80 */ dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0xb0; /* 0x70 */ dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0xb0; /* 0xc0 */ dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0xb0; /* 0x60 */ dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x24; /* 0x90 */ dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x00; /* 0x34 */ dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x0c; /* 0x3c */ } } else { if( dev->PCBID == _SCANNER2Button ) { dev->shade.pCcdDac->GainResize.Colors.Red = 107; dev->shade.pCcdDac->GainResize.Colors.Green = 106; dev->shade.pCcdDac->GainResize.Colors.Blue = 103; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x48; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x48; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x48; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x28; /* 0 */ dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x18; /* 0 */ dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x20; /* 0 */ } else { dev->shade.pCcdDac->GainResize.Colors.Red = 104; dev->shade.pCcdDac->GainResize.Colors.Green = 107; dev->shade.pCcdDac->GainResize.Colors.Blue = 99; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x30; /* 0x80 */ dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x30; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x30; /* 0x0a0 */ dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x150; /* 0x170 */ dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x130; /* 0x90 */ dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x110; /* 0x130 */ dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x140; /* 0x150 */ dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x120; /* 0x70 */ dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x100; /* 0x120 */ dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0xF0; /* 0x90 */ dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0xD4; /* 0x50 */ dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0xCC; /* 0x60 */ } } } } /** */ static void fnCCDInitESIC3799( U12_Device *dev ) { if(!(dev->DataInf.dwScanFlag & _SCANDEF_Negative)) { if (!(dev->shade.intermediate & _ScanMode_AverageOut)) { dev->shade.pCcdDac->GainResize.Colors.Red = 100; dev->shade.pCcdDac->GainResize.Colors.Green = 99; dev->shade.pCcdDac->GainResize.Colors.Blue = 94; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0xc8; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0xc8; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0xc8; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x58; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x38; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x48; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x48; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x38; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x58; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0x38; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0x48; } else { dev->shade.pCcdDac->GainResize.Colors.Red = 100; dev->shade.pCcdDac->GainResize.Colors.Green = 98; dev->shade.pCcdDac->GainResize.Colors.Blue = 93; dev->shade.pCcdDac->DarkDAC.Colors.Red = 0xd0; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0xd0; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0xd0; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x108; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0xf8; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0xc8; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x100; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0xf0; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0xc0; dev->shade.pCcdDac->DarkOffSub.Colors.Red = 0x108; dev->shade.pCcdDac->DarkOffSub.Colors.Green = 0xf8; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = 0xc8; } } else { dev->shade.pCcdDac->DarkDAC.Colors.Red = 0x80; dev->shade.pCcdDac->DarkDAC.Colors.Green = 0x80; dev->shade.pCcdDac->DarkDAC.Colors.Blue = 0x80; dev->shade.pCcdDac->DarkCmpHi.Colors.Red = 0x28; dev->shade.pCcdDac->DarkCmpHi.Colors.Green = 0x28; dev->shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x28; dev->shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; dev->shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; dev->shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; dev->shade.pCcdDac->DarkOffSub.Colors.Red = -0x38; dev->shade.pCcdDac->DarkOffSub.Colors.Green = -0x38; dev->shade.pCcdDac->DarkOffSub.Colors.Blue = -0x38; } } /** */ static void fnDarkOffsetWolfson3797( U12_Device *dev, ShadingVarDef *sTbl, u_long dwCh ) { if(( dev->shade.DarkOffset.wColors[dwCh] -= sTbl->DarkOffSub.wColors[dwCh]) > 0xfff ) { dev->shade.DarkOffset.wColors[dwCh] = 0; } } /** */ static void fnDarkOffsetSamsung3777( U12_Device *dev, ShadingVarDef *sTbl, u_long dwCh ) { dev->shade.DarkOffset.wColors[dwCh] += sTbl->DarkOffSub.wColors [dwCh]; } /** */ static void fnDarkOffsetSamsung3797( U12_Device *dev, ShadingVarDef *sTbl, u_long dwCh ) { if( dev->shade.DarkOffset.wColors[dwCh] > sTbl->DarkOffSub.wColors[dwCh] ) dev->shade.DarkOffset.wColors[dwCh] -= sTbl->DarkOffSub.wColors[dwCh]; else dev->shade.DarkOffset.wColors[dwCh] = 0; } /** */ static void fnDarkOffsetSamsung3799( U12_Device *dev, ShadingVarDef *sTbl, u_long dwCh ) { if( dev->shade.DarkOffset.wColors[dwCh] > sTbl->DarkOffSub.wColors[dwCh]) dev->shade.DarkOffset.wColors[dwCh] -= sTbl->DarkOffSub.wColors[dwCh]; else dev->shade.DarkOffset.wColors[dwCh] = 0; } /** */ static void fnDACDarkWolfson( U12_Device *dev, ShadingVarDef *sTbl, u_long dwCh, u_short wDarkest ) { u_short w = dev->shade.DarkDAC.bColors[dwCh]; if( wDarkest > sTbl->DarkCmpHi.wColors[dwCh] ) { wDarkest -= sTbl->DarkCmpHi.wColors[dwCh]; if( wDarkest > dev->shade.wDarkLevels) w += (u_short)wDarkest / dev->shade.wDarkLevels; else w++; if (w > 0xff) w = 0xff; if(w != (u_short)dev->shade.DarkDAC.bColors[dwCh] ) { dev->shade.DarkDAC.bColors[dwCh] = (SANE_Byte)w; dev->shade.fStop = SANE_FALSE; } } else { if((wDarkest < sTbl->DarkCmpLo.wColors[dwCh]) && dev->shade.DarkDAC.bColors[dwCh]) { if( wDarkest ) w = (u_short)dev->shade.DarkDAC.bColors[dwCh] - 2U; else w = (u_short)dev->shade.DarkDAC.bColors[dwCh] - dev->shade.wDarkLevels; if ((short) w < 0) w = 0; if( w != (u_short)dev->shade.DarkDAC.bColors[dwCh] ) { dev->shade.DarkDAC.bColors [dwCh] = (SANE_Byte)w; dev->shade.fStop = SANE_FALSE; } } } } /** */ static void fnDACDarkSamsung( U12_Device *dev, ShadingVarDef *sTbl, u_long dwCh, u_short wDarkest ) { u_short w; if( wDarkest > sTbl->DarkCmpHi.wColors[dwCh] ) { wDarkest -= sTbl->DarkCmpHi.wColors[dwCh]; if( wDarkest > dev->shade.wDarkLevels ) w = (u_short)dev->shade.DarkDAC.bColors[dwCh] - wDarkest / dev->shade.wDarkLevels; else w = (u_short)dev->shade.DarkDAC.bColors[dwCh] - 1U; if((short) w < 0) w = 0; if(w != (u_short)dev->shade.DarkDAC.bColors[dwCh]) { dev->shade.DarkDAC.bColors [dwCh] = (SANE_Byte)w; dev->shade.fStop = SANE_FALSE; } } else { if((wDarkest < sTbl->DarkCmpLo.wColors[dwCh]) && dev->shade.DarkDAC.bColors[dwCh]) { if( wDarkest ) w = (u_short)dev->shade.DarkDAC.bColors[dwCh] + 2U; else w = dev->shade.wDarkLevels + (u_short)dev->shade.DarkDAC.bColors[dwCh]; if (w > 0xff) w = 0xff; if(w != (u_short)dev->shade.DarkDAC.bColors[dwCh]) { dev->shade.DarkDAC.bColors[dwCh] = (SANE_Byte)w; dev->shade.fStop = SANE_FALSE; } } } } /************************ exported functions *********************************/ /** according to detected CCD and DAC, we set their correct init values * and functions */ static void u12ccd_InitCCDandDAC( U12_Device *dev, SANE_Bool shading ) { u_short w; ShadingVarDef *pDAC_CCD; DBG( _DBG_INFO, "CCD & DAC init\n" ); /* some presets */ dev->f0_8_16 = SANE_FALSE; switch( dev->DACType ) { case _DA_WOLFSON8143: DBG( _DBG_INFO, "* DAC: WOLFSON 8143\n" ); switch( dev->CCDID ) { case _CCD_3797: DBG( _DBG_INFO, "* CCD-3797\n" ); pDAC_CCD = ShadingVar3797; u12ccd_InitFunc = fnCCDInitWolfson3797; dev->fnDarkOffset = fnDarkOffsetWolfson3797; dev->fnDACDark = fnDACDarkWolfson; dev->CCDRegs = (RegDef*)W3797CCDParams; break; case _CCD_548: DBG( _DBG_INFO, "* CCD-548\n" ); pDAC_CCD = ShadingVar548; u12ccd_InitFunc = fnCCDInitWolfson548; dev->fnDarkOffset = fnDarkOffsetWolfson3797; dev->fnDACDark = fnDACDarkWolfson; dev->CCDRegs = (RegDef*)W548CCDParams; break; default: DBG( _DBG_INFO, "* CCD-3799\n" ); pDAC_CCD = ShadingVar3799; u12ccd_InitFunc = fnCCDInitWolfson3799; /* CHECK: org was to fnDarkOffsetWolfson3797 */ dev->fnDarkOffset = fnDarkOffsetWolfson3797; dev->fnDACDark = fnDACDarkWolfson; dev->CCDRegs = (RegDef*)W3799CCDParams; } dev->numCCDRegs = _NUM_OF_CCDREGS_W8143; dev->numDACRegs = _NUM_OF_DACREGS_W8143; dev->DACRegs = WolfsonDAC8143; dev->RegDACOffset.Red = 0x20; dev->RegDACOffset.Green = 0x21; dev->RegDACOffset.Blue = 0x22; dev->RegDACGain.Red = 0x28; dev->RegDACGain.Green = 0x29; dev->RegDACGain.Blue = 0x2a; if( dev->shade.intermediate & _ScanMode_AverageOut ) { dev->shade.bUniGain = 1; dev->shade.bGainDouble = 1; } else { dev->shade.bUniGain = 2; dev->shade.bGainDouble = 4; } dev->shade.bMinGain = 1; dev->shade.bMaxGain = 0x1f; dev->shade.wDarkLevels = 10; if( dev->shade.intermediate == _ScanMode_Color ) WolfsonDAC8143[2].val = 0x52; else WolfsonDAC8143[2].val = 0x42; if (dev->shade.intermediate == _ScanMode_Mono ) WolfsonDAC8143[0].val = 7; else WolfsonDAC8143[0].val = 3; break; case _DA_SAMSUNG1224: DBG( _DBG_INFO, "* DAC: Samsung 1224\n" ); switch( dev->CCDID ) { case _CCD_3797: DBG( _DBG_INFO, "* CCD-3797\n" ); pDAC_CCD = ShadingVar3797; u12ccd_InitFunc = fnCCDInitSamsung3797; dev->fnDarkOffset = fnDarkOffsetSamsung3797; dev->fnDACDark = fnDACDarkSamsung; dev->CCDRegs = (RegDef*)S3797CCDParams; break; default: DBG( _DBG_INFO, "* CCD-3799\n" ); pDAC_CCD = ShadingVar3799; u12ccd_InitFunc = fnCCDInitSamsung3799; dev->fnDarkOffset = fnDarkOffsetSamsung3799; dev->fnDACDark = fnDACDarkSamsung; dev->CCDRegs = (RegDef*)S3799CCDParams; } dev->numCCDRegs = _NUM_OF_CCDREGS_S1224; dev->numDACRegs = _NUM_OF_DACREGS_S1224; dev->DACRegs = SamsungDAC1224; dev->RegDACOffset.Red = 1; dev->RegDACOffset.Green = 2; dev->RegDACOffset.Blue = 3; dev->RegDACGain.Red = 4; dev->RegDACGain.Green = 5; dev->RegDACGain.Blue = 6; dev->shade.bGainDouble = 6; dev->shade.bUniGain = 7; dev->shade.bMinGain = 0; dev->shade.bMaxGain = 0x1f; dev->shade.wDarkLevels = 10; if( dev->shade.intermediate & _ScanMode_Mono ) SamsungDAC1224[0].val = 0x57; else SamsungDAC1224[0].val = 0x51; break; case _DA_ESIC: DBG( _DBG_INFO, "* DAC: ESIC\n" ); switch( dev->CCDID ) { case _CCD_3797: DBG( _DBG_INFO, "* CCD-3797\n" ); pDAC_CCD = ShadingVar3797; u12ccd_InitFunc = fnCCDInitWolfson3797; dev->fnDarkOffset = fnDarkOffsetWolfson3797; dev->fnDACDark = fnDACDarkWolfson; dev->CCDRegs = (RegDef*)W3797CCDParams; break; default: DBG( _DBG_INFO, "* CCD-3799\n" ); pDAC_CCD = ShadingVar3799; u12ccd_InitFunc = fnCCDInitESIC3799; dev->fnDarkOffset = fnDarkOffsetWolfson3797; dev->fnDACDark = fnDACDarkWolfson; dev->CCDRegs = (RegDef*)W3799CCDParams; } dev->numCCDRegs = _NUM_OF_CCDREGS_W8143; dev->numDACRegs = _NUM_OF_DACREGS_W8143; dev->DACRegs = WolfsonDAC8143; dev->RegDACOffset.Red = 0x20; dev->RegDACOffset.Green = 0x21; dev->RegDACOffset.Blue = 0x22; dev->RegDACGain.Red = 0x28; dev->RegDACGain.Green = 0x29; dev->RegDACGain.Blue = 0x2a; if( dev->shade.intermediate & _ScanMode_AverageOut ) { dev->shade.bUniGain = 1; dev->shade.bGainDouble = 1; } else { dev->shade.bUniGain = 2; dev->shade.bGainDouble = 4; } dev->shade.bMinGain = 1; dev->shade.bMaxGain = 0x1f; dev->shade.wDarkLevels = 10; if( dev->shade.intermediate == _ScanMode_Color ) WolfsonDAC8143[2].val = 0x52; else WolfsonDAC8143[2].val = 0x42; if(dev->shade.intermediate == _ScanMode_Mono ) WolfsonDAC8143[0].val = 7; else WolfsonDAC8143[0].val = 3; break; default: DBG( _DBG_INFO, "* DAC: SAMSUNG 8531\n" ); switch( dev->CCDID ) { case _CCD_3797: DBG( _DBG_INFO, "* CCD-3797\n" ); pDAC_CCD = ShadingVar3797; u12ccd_InitFunc = fnCCDInitSamsung3797; dev->fnDarkOffset = fnDarkOffsetSamsung3797; dev->fnDACDark = fnDACDarkSamsung; dev->CCDRegs = (RegDef*)S3797CCDParams; break; case _CCD_3777: DBG( _DBG_INFO, "* CCD-3777\n" ); pDAC_CCD = ShadingVar3777; u12ccd_InitFunc = fnCCDInitSamsung3777; dev->fnDarkOffset = fnDarkOffsetSamsung3777; dev->fnDACDark = fnDACDarkSamsung; dev->CCDRegs = (RegDef*)S3797CCDParams; dev->f0_8_16 = SANE_TRUE; break; default: DBG( _DBG_INFO, "* CCD-3799\n" ); pDAC_CCD = ShadingVar3799; u12ccd_InitFunc = fnCCDInitSamsung3799; dev->fnDarkOffset = fnDarkOffsetSamsung3799; dev->fnDACDark = fnDACDarkSamsung; dev->CCDRegs = (RegDef*)S3799CCDParams; } dev->numCCDRegs = _NUM_OF_CCDREGS_S8531; dev->numDACRegs = _NUM_OF_DACREGS_S8531; dev->DACRegs = SamsungDAC8531; dev->RegDACOffset.Red = 1; dev->RegDACOffset.Green = 1; dev->RegDACOffset.Blue = 1; dev->RegDACGain.Red = 2; dev->RegDACGain.Green = 2; dev->RegDACGain.Blue = 2; dev->shade.bGainDouble = 6; dev->shade.bMinGain = 1; dev->shade.bMaxGain = 0x1f; if( dev->DataInf.dwScanFlag & _SCANDEF_TPA ) dev->shade.bUniGain = 2; else dev->shade.bUniGain = 7; dev->shade.wDarkLevels = 10; if( dev->shade.intermediate & _ScanMode_Mono ) { SamsungDAC8531[0].val = 0x57; SamsungDAC8531[3].val = 0x57; SamsungDAC8531[6].val = 0x57; } else { SamsungDAC8531[0].val = 0x51; SamsungDAC8531[3].val = 0x55; SamsungDAC8531[6].val = 0x59; } } if( shading ) { if( !(dev->DataInf.dwScanFlag & _SCANDEF_TPA)) dev->shade.pCcdDac = &pDAC_CCD[_REFLECTION]; else { if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency ) dev->shade.pCcdDac = &pDAC_CCD[_TRANSPARENCY]; else dev->shade.pCcdDac = &pDAC_CCD[_NEGATIVE]; } } else { dev->shade.pCcdDac = &pDAC_CCD[_REFLECTION]; } /* as we now have the correct init function, call it */ u12ccd_InitFunc( dev ); DBG( _DBG_INFO, "* Programming DAC (%u regs)\n", dev->numDACRegs ); for( w = 0; w < dev->numDACRegs; w++ ) { DBG( _DBG_INFO, "* [0x%02x] = 0x%02x\n", dev->DACRegs[w].reg, dev->DACRegs[w].val ); #if 0 u12io_DataRegisterToDAC( dev, dev->DACRegs[w].reg, dev->DACRegs[w].val ); #else u12io_DataToRegister( dev, REG_ADCADDR, dev->DACRegs[w].reg ); u12io_DataToRegister( dev, REG_ADCDATA, dev->DACRegs[w].val ); u12io_DataToRegister( dev, REG_ADCSERIALOUT, dev->DACRegs[w].val ); #endif } DBG( _DBG_INFO, "CCD & DAC init done.\n" ); } /* END U12-CCD.C ............................................................*/ sane-backends-1.0.27/backend/hp4200.c0000664000175000017500000022474112775312261013712 00000000000000/* Copyright (C) 2000 by Adrian Perez Jorge This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Developers: Adrian Perez Jorge (APJ) - Creator of the original HP4200C backend code. adrianpj@easynews.com Andrew John Lewis (AJL) - lewi0235@tc.umn.edu Arnar Mar Hrafnkelsson (AMH) - addi@umich.edu Frank Zago some cleanups and integration into SANE Henning Meier-Geinitz more cleanups, bug fixes TODO: - support more scanning resolutions. - support different color depths. - support gray and lineart. - improve scanning speed. Compute scanning parameters based on the image size and the scanner-to-host bandwidth. - improve image quality. - fix problem concerning mangled images */ #define BUILD 2 #define BACKEND_NAME hp4200 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_pv8630.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_backend.h" #include "hp4200.h" #include "hp4200_lm9830.c" #define HP4200_CONFIG_FILE "hp4200.conf" /*--------------------------------------------------------------------------*/ #if 0 /* Some of these resolution need work in color shifting. */ static const SANE_Int dpi_list[] = { 8, 50, 75, 100, 150, 200, 300, 400, 600 }; #else static const SANE_Int dpi_list[] = { 4, 75, 150, 300, 600 }; #endif static SANE_Range x_range = { SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0 }; static SANE_Range y_range = { SANE_FIX (0), SANE_FIX (11.75 * MM_PER_INCH), 0 }; static const SANE_Range u8_range = { 0, 255, 0 }; struct coarse_t { int min_red; int min_green; int min_blue; int max_red; int max_green; int max_blue; int red_gain; int red_offset; int green_gain; int green_offset; int blue_gain; int blue_offset; }; static const double hdpi_mapping[8] = { 1, 1.5, 2, 3, 4, 6, 8, 12 }; static HP4200_Device *first_device = NULL; /* device list head */ static int n_devices = 0; /* the device count */ static const SANE_Device **devlist = NULL; static unsigned char getreg (HP4200_Scanner * s, unsigned char reg) { unsigned char reg_value; if ((reg > 0x08) && (reg < 0x5b)) return (unsigned char) LOBYTE (s->regs[reg]); else { lm9830_read_register (s->fd, reg, ®_value); return reg_value; } } static void setreg (HP4200_Scanner * s, unsigned char reg, unsigned char reg_value) { s->regs[reg] = reg_value; /* dirty bit should be clear with this */ if ((reg < 0x08) || (reg > 0x5b)) { lm9830_write_register (s->fd, reg, reg_value); } } static void setbits (HP4200_Scanner * s, unsigned char reg, unsigned char bitmap) { s->regs[reg] = (s->regs[reg] & 0xff) | bitmap; if ((reg < 0x08) || (reg > 0x5b)) { lm9830_write_register (s->fd, reg, LOBYTE (s->regs[reg])); } } static void clearbits (HP4200_Scanner * s, unsigned char reg, unsigned char mask) { s->regs[reg] = (s->regs[reg] & ~mask) & 0xff; if ((reg < 0x08) || (reg > 0x5b)) { lm9830_write_register (s->fd, reg, LOBYTE (s->regs[reg])); } } static int cache_write (HP4200_Scanner * s) { int i; #ifdef DEBUG_REG_CACHE int counter = 0; #endif DBG (DBG_proc, "Writing registers\n"); for (i = 0; i < 0x80; i++) if (!(s->regs[i] & 0x100)) { /* modified register */ #ifdef DEBUG_REG_CACHE fprintf (stderr, "%.2x", i); if (counter == 8) fprintf (stderr, "\n"); else fprintf (stderr, ", "); counter = (counter + 1) % 9; #endif lm9830_write_register (s->fd, i, s->regs[i]); s->regs[i] |= 0x100; /* register is updated */ } return 0; } /* * HP4200-dependent register initialization. */ static int hp4200_init_registers (HP4200_Scanner * s) { /* set up hardware parameters */ s->hw_parms.crystal_frequency = 48000000; s->hw_parms.SRAM_size = 128; /* Kb */ s->hw_parms.scan_area_width = 5100; /* pixels */ s->hw_parms.scan_area_length = 11; /* inches */ s->hw_parms.min_pixel_data_buffer_limit = 1024; /* bytes */ s->hw_parms.sensor_line_separation = 4; /* lines */ s->hw_parms.sensor_max_integration_time = 12; /* milliseconds */ s->hw_parms.home_sensor = 2; s->hw_parms.sensor_resolution = 1; /* 600 dpi */ s->hw_parms.motor_full_steps_per_inch = 300; s->hw_parms.motor_max_speed = 1.4; /* inches/second */ s->hw_parms.num_tr_pulses = 1; s->hw_parms.guard_band_duration = 1; s->hw_parms.pulse_duration = 3; s->hw_parms.fsteps_25_speed = 3; s->hw_parms.fsteps_50_speed = 3; s->hw_parms.target_value.red = 1000; s->hw_parms.target_value.green = 1000; s->hw_parms.target_value.blue = 1000; { int i; /* * we are using a cache-like data structure so registers whose * values were written to the lm9830 and aren't volatile, have * bit 0x100 activated. This bit must be cleared if you want the * value to be written to the chip once cache_write() is called. */ /* clears the registers cache */ memset (s->regs, 0, sizeof (s->regs)); /* * registers 0x00 - 0x07 are non-cacheable/volatile, so don't * read the values using the cache. Instead use direct functions * to read/write registers. */ for (i = 0; i < 0x08; i++) s->regs[i] = 0x100; } setreg (s, 0x70, 0x70); /* noise filter */ setreg (s, 0x0b, INPUT_SIGNAL_POLARITY_NEGATIVE | CDS_ON | SENSOR_STANDARD | SENSOR_RESOLUTION_600 | LINE_SKIPPING_COLOR_PHASE_DELAY (0)); setreg (s, 0x0c, PHI1_POLARITY_POSITIVE | PHI2_POLARITY_POSITIVE | RS_POLARITY_POSITIVE | CP1_POLARITY_POSITIVE | CP2_POLARITY_POSITIVE | TR1_POLARITY_NEGATIVE | TR2_POLARITY_NEGATIVE); setreg (s, 0x0d, PHI1_ACTIVE | PHI2_ACTIVE | RS_ACTIVE | CP1_ACTIVE | CP2_OFF | TR1_ACTIVE | TR2_OFF | NUMBER_OF_TR_PULSES (s->hw_parms.num_tr_pulses)); setreg (s, 0x0e, TR_PULSE_DURATION (s->hw_parms.pulse_duration) | TR_PHI1_GUARDBAND_DURATION (s->hw_parms.guard_band_duration)); /* for pixel rate timing */ setreg (s, 0x0f, 6); setreg (s, 0x10, 23); setreg (s, 0x11, 1); setreg (s, 0x12, 3); setreg (s, 0x13, 3); /* 0 */ setreg (s, 0x14, 5); /* 0 */ setreg (s, 0x15, 0); setreg (s, 0x16, 0); setreg (s, 0x17, 11); setreg (s, 0x18, 2); /* 1 */ setreg (s, 0x19, CIS_TR1_TIMING_OFF | FAKE_OPTICAL_BLACK_PIXELS_OFF); setreg (s, 0x1a, 0); setreg (s, 0x1b, 0); setreg (s, 0x1c, 0x0d); setreg (s, 0x1d, 0x21); setreg (s, 0x27, TR_RED_DROP (0) | TR_GREEN_DROP (0) | TR_BLUE_DROP (0)); setreg (s, 0x28, 0x00); setreg (s, 0x29, ILLUMINATION_MODE (1)); setreg (s, 0x2a, HIBYTE (0)); /* 0 */ setreg (s, 0x2b, LOBYTE (0)); /* 0 */ setreg (s, 0x2c, HIBYTE (16383)); setreg (s, 0x2d, LOBYTE (16383)); setreg (s, 0x2e, HIBYTE (2)); /* 2 */ setreg (s, 0x2f, LOBYTE (2)); /* 1 */ setreg (s, 0x30, HIBYTE (0)); setreg (s, 0x31, LOBYTE (0)); setreg (s, 0x32, HIBYTE (0)); setreg (s, 0x33, LOBYTE (0)); setreg (s, 0x34, HIBYTE (32)); setreg (s, 0x35, LOBYTE (32)); setreg (s, 0x36, HIBYTE (48)); setreg (s, 0x37, LOBYTE (48)); setreg (s, 0x42, EPP_MODE | PPORT_DRIVE_CURRENT (3)); setreg (s, 0x43, RAM_SIZE_128 | SRAM_DRIVER_CURRENT (3) | SRAM_BANDWIDTH_8 | SCANNING_FULL_DUPLEX); setreg (s, 0x45, MICRO_STEPPING | CURRENT_SENSING_PHASES (2) | PHASE_A_POLARITY_POSITIVE | PHASE_B_POLARITY_POSITIVE | STEPPER_MOTOR_OUTPUT); setreg (s, 0x4a, HIBYTE (100)); setreg (s, 0x4b, LOBYTE (100)); setreg (s, 0x4c, HIBYTE (0)); setreg (s, 0x4d, LOBYTE (0)); /* resume scan threshold */ setreg (s, 0x4f, 64); /* steps to reverse */ setreg (s, 0x50, 40); setreg (s, 0x51, ACCELERATION_PROFILE_STOPPED (3) | ACCELERATION_PROFILE_25P (s->hw_parms.fsteps_25_speed) | ACCELERATION_PROFILE_50P (s->hw_parms.fsteps_50_speed)); setreg (s, 0x54, NON_REVERSING_EXTRA_LINES (0) | FIRST_LINE_TO_PROCESS (0)); setreg (s, 0x55, KICKSTART_STEPS (0) | HOLD_CURRENT_TIMEOUT (2)); /* stepper PWM frequency */ setreg (s, 0x56, 8); /* stepper pwm duty cycle */ setreg (s, 0x57, 23); setreg (s, 0x58, PAPER_SENSOR_1_POLARITY_HIGH | PAPER_SENSOR_1_TRIGGER_EDGE | PAPER_SENSOR_1_NO_STOP_SCAN | PAPER_SENSOR_2_POLARITY_HIGH | PAPER_SENSOR_2_TRIGGER_EDGE | PAPER_SENSOR_2_STOP_SCAN); setreg (s, 0x59, MISCIO_1_TYPE_OUTPUT | MISCIO_1_POLARITY_HIGH | MISCIO_1_TRIGGER_EDGE | MISCIO_1_OUTPUT_STATE_HIGH | MISCIO_2_TYPE_OUTPUT | MISCIO_2_POLARITY_HIGH | MISCIO_2_TRIGGER_EDGE | MISCIO_2_OUTPUT_STATE_HIGH); return 0; } #ifdef DEBUG static int dump_register_cache (HP4200_Scanner * s) { int i; for (i = 0; i < 0x80; i++) { fprintf (stderr, "%.2x:0x%.2x", i, s->regs[i]); if ((i + 1) % 8) fprintf (stderr, ", "); else fprintf (stderr, "\n"); } fputs ("", stderr); return 0; } #endif /* * returns the scanner head to home position */ static int hp4200_goto_home (HP4200_Scanner * s) { unsigned char cmd_reg; unsigned char status_reg; unsigned char old_paper_sensor_reg; cmd_reg = getreg (s, 0x07); if (cmd_reg != 2) { unsigned char paper_sensor_reg; unsigned char sensor_bit[2] = { 0x02, 0x10 }; /* sensor head is not returning */ /* let's see if it's already at home */ /* first put paper (head) sensor level sensitive */ paper_sensor_reg = getreg (s, 0x58); old_paper_sensor_reg = paper_sensor_reg; paper_sensor_reg &= ~sensor_bit[s->hw_parms.home_sensor - 1]; setreg (s, 0x58, paper_sensor_reg); cache_write (s); /* if the scan head is not at home then move motor backwards */ status_reg = getreg (s, 0x02); setreg (s, 0x58, old_paper_sensor_reg); cache_write (s); if (!(status_reg & s->hw_parms.home_sensor)) { setreg (s, 0x07, 0x08); usleep (10 * 1000); setreg (s, 0x07, 0x00); usleep (10 * 1000); setreg (s, 0x07, 0x02); } } return 0; } #define HP4200_CHECK_INTERVAL 1000 /* usecs between status checks */ static int hp4200_wait_homed (HP4200_Scanner * s) { unsigned char cmd_reg; cmd_reg = getreg (s, 0x07); while (cmd_reg != 0) { usleep (HP4200_CHECK_INTERVAL); cmd_reg = getreg (s, 0x07); } return 0; } static int compute_fastfeed_step_size (unsigned long crystal_freq, int mclk, float max_speed, int steps_per_inch, int color_mode) { int aux; int r; if (color_mode == 0) r = 24; else r = 8; aux = floor (crystal_freq / ((double) mclk * max_speed * 4.0 * steps_per_inch * r)); if (aux < 2) aux = 2; return aux; } static SANE_Status read_available_data (HP4200_Scanner * s, SANE_Byte * buffer, size_t * byte_count) { SANE_Status status; unsigned char scankb1; unsigned char scankb2; size_t to_read; size_t really_read; size_t chunk; assert (buffer != NULL); *byte_count = 0; do { scankb1 = getreg (s, 0x01); scankb2 = getreg (s, 0x01); if (s->aborted_by_user) return SANE_STATUS_CANCELLED; } while ((scankb1 != scankb2) || (scankb1 < 12)); to_read = scankb1 * 1024; while (to_read) { if (s->aborted_by_user) return SANE_STATUS_CANCELLED; chunk = (to_read > 0xffff) ? 0xffff : to_read; sanei_pv8630_write_byte (s->fd, PV8630_REPPADDRESS, 0x00); sanei_pv8630_prep_bulkread (s->fd, chunk); really_read = chunk; if ((status = sanei_usb_read_bulk (s->fd, buffer, &really_read)) != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_usb_read_bulk failed (%s)\n", sane_strstatus (status)); return status; } if (really_read > to_read) { DBG (DBG_error, "USB stack read more bytes than requested!\n"); return SANE_STATUS_IO_ERROR; } *byte_count += really_read; buffer += really_read; to_read -= really_read; #ifdef DEBUG fprintf (stderr, "read %d bytes\n", really_read); #endif } return SANE_STATUS_GOOD; } #ifdef unused static int compute_datalink_bandwidth (HP4200_Scanner * s) { int line_size; int pause_limit; unsigned int color_mode; /* * Line size for 8 bpp, the entire scan area width (plus the * status byte) at optical resolution. */ if (s->user_parms.color) { line_size = 3 * s->hw_parms.scan_area_width + 1; color_mode = 0; setreg (s, 0x26, color_mode); /* 3 channel pixel rate color */ } else { line_size = s->hw_parms.scan_area_width + 1; color_mode = 4; setreg (s, 0x26, 0x08 | color_mode); /* 1 channel mode A (green) */ } setreg (s, 0x09, (3 << 3)); /* h-divider = 1, 8 bpp */ { int first_white_pixel; unsigned int line_end; first_white_pixel = s->hw_parms.sensor_pixel_end - 10; line_end = first_white_pixel + s->hw_parms.scan_area_width; if (line_end > (s->hw_parms.sensor_num_pixels - 20)) line_end = s->hw_parms.sensor_num_pixels - 20; setreg (s, 0x1c, HIBYTE (s->hw_parms.sensor_pixel_start)); setreg (s, 0x1d, LOBYTE (s->hw_parms.sensor_pixel_end)); setreg (s, 0x1e, HIBYTE (first_white_pixel)); setreg (s, 0x1f, LOBYTE (first_white_pixel)); setreg (s, 0x20, HIBYTE (s->hw_parms.sensor_num_pixels)); setreg (s, 0x21, LOBYTE (s->hw_parms.sensor_num_pixels)); setreg (s, 0x22, getreg (s, 0x1e)); setreg (s, 0x23, getreg (s, 0x1f)); setreg (s, 0x24, HIBYTE (line_end)); setreg (s, 0x25, LOBYTE (line_end)); } /* * During transfer rate calculation don't forward scanner sensor. * Stay in the calibration region. */ setreg (s, 0x4f, 0); clearbits (s, 0x45, 0x10); /* * Pause the scan when memory is full. */ pause_limit = s->hw_parms.SRAM_size - (line_size / 1024) - 1; setreg (s, 0x4e, pause_limit & 0xff); s->mclk = compute_min_mclk (s->hw_parms.SRAM_bandwidth, s->hw_parms.crystal_frequency); /* * Set step size to fast speed. */ { int step_size; step_size = compute_fastfeed_step_size (s->hw_parms.crystal_frequency, s->mclk, s->hw_parms.scan_bar_max_speed, s->hw_parms.motor_full_steps_per_inch, color_mode); setreg (s, 0x46, HIBYTE (step_size)); setreg (s, 0x47, LOBYTE (step_size)); setreg (s, 0x48, HIBYTE (step_size)); setreg (s, 0x49, LOBYTE (step_size)); } cache_write (s); /* dump_register_cache (s); */ /* * scan during 1 sec. aprox. */ setreg (s, 0x07, 0x08); setreg (s, 0x07, 0x03); { struct timeval tv_before; struct timeval tv_after; int elapsed_time_ms = 0; long bytes_read_total; SANE_Byte *buffer; buffer = malloc (2 * 98304); /* check this */ if (!buffer) { DBG (DBG_error, "compute_datalink_bandwidth: malloc failed\n"); return 0; } bytes_read_total = 0; gettimeofday (&tv_before, NULL); do { size_t bytes_read; SANE_Status status; status = read_available_data (s, buffer, &bytes_read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_available_data failed (%s)\n", sane_strstatus (status)); return 0; } bytes_read_total += bytes_read; gettimeofday (&tv_after, NULL); elapsed_time_ms = (tv_after.tv_sec - tv_before.tv_sec) * 1000; elapsed_time_ms += (tv_after.tv_usec - tv_before.tv_usec) / 1000; } while (elapsed_time_ms < 1000); setreg (s, 0x07, 0x00); free (buffer); s->msrd_parms.datalink_bandwidth = bytes_read_total / (elapsed_time_ms / 1000); #ifdef DEBUG fprintf (stderr, "PC Transfer rate = %d bytes/sec. (%ld/%d)\n", s->msrd_parms.datalink_bandwidth, bytes_read_total, elapsed_time_ms); #endif } return 0; } #endif static void compute_first_gain_offset (int target, int max, int min, int *gain, int *offset, int *max_gain, int *min_offset) { *gain = (int) 15.0 *(target / (max - min) - 0.933); *offset = (int) (-1.0 * min / (512.0 * 0.0195)); if (*gain >= 32) { *gain = (int) 15.0 *(target / 3.0 / (max - min) - 0.933); *offset = (int) -3.0 * min / (512.0 * 0.0195); } if (*gain < 0) *gain = 0; else if (*gain > 63) *gain = 63; if (*offset < -31) *offset = -31; else if (*offset > 31) *offset = 31; *max_gain = 63; *min_offset = -31; } #define DATA_PORT_READ (1 << 5) #define DATA_PORT_WRITE 0 static int write_gamma (HP4200_Scanner * s) { int color; int i; unsigned char gamma[1024]; unsigned char read_gamma[1024]; int retval; size_t to_read; size_t to_write; for (color = 0; color < 3; color++) { for (i = 0; i < 1024; i++) gamma[i] = s->user_parms.gamma[color][i]; setreg (s, 0x03, color << 1); setreg (s, 0x04, DATA_PORT_WRITE); setreg (s, 0x05, 0x00); sanei_pv8630_write_byte (s->fd, PV8630_REPPADDRESS, 0x06); sanei_pv8630_prep_bulkwrite (s->fd, sizeof (gamma)); to_write = sizeof (gamma); sanei_usb_write_bulk (s->fd, gamma, &to_write); /* check if gamma vector was correctly written */ setreg (s, 0x03, color << 1); setreg (s, 0x04, DATA_PORT_READ); setreg (s, 0x05, 0x00); sanei_pv8630_write_byte (s->fd, PV8630_REPPADDRESS, 0x06); sanei_pv8630_prep_bulkread (s->fd, sizeof (read_gamma)); to_read = sizeof (read_gamma); sanei_usb_read_bulk (s->fd, read_gamma, &to_read); retval = memcmp (read_gamma, gamma, sizeof (read_gamma)); if (retval != 0) { DBG (DBG_error, "error: color %d has bad gamma table\n", color); } #ifdef DEBUG else fprintf (stderr, "color %d gamma table is good\n", color); #endif } return 0; } static int write_default_offset_gain (HP4200_Scanner * s, SANE_Byte * gain_offset, int size, int color) { SANE_Byte *check_data; int retval; size_t to_read; size_t to_write; setreg (s, 0x03, (color << 1) | 1); setreg (s, 0x04, DATA_PORT_WRITE); setreg (s, 0x05, 0x00); sanei_pv8630_write_byte (s->fd, PV8630_REPPADDRESS, 0x06); sanei_pv8630_prep_bulkwrite (s->fd, size); to_write = size; sanei_usb_write_bulk (s->fd, gain_offset, &to_write); check_data = malloc (size); setreg (s, 0x03, (color << 1) | 1); setreg (s, 0x04, DATA_PORT_READ); setreg (s, 0x05, 0x00); sanei_pv8630_write_byte (s->fd, PV8630_REPPADDRESS, 0x06); sanei_pv8630_prep_bulkread (s->fd, size); to_read = size; sanei_usb_read_bulk (s->fd, check_data, &to_read); retval = memcmp (gain_offset, check_data, size); free (check_data); if (retval != 0) { DBG (DBG_error, "error: color %d has bad gain/offset table\n", color); } #ifdef DEBUG else fprintf (stderr, "color %d gain/offset table is good\n", color); #endif return 0; } static int compute_gain_offset (int target, int max, int min, int *gain, int *offset, int *max_gain, int *min_offset) { int gain_stable; int is_unstable; gain_stable = 1; /* unless the opposite is said */ is_unstable = 0; if (max > target) { if (*gain > 0) { (*gain)--; *max_gain = *gain; gain_stable = 0; is_unstable |= 1; } else { DBG (DBG_error, "error: integration time too long.\n"); return -1; } } else { if (*gain < *max_gain) { (*gain)++; gain_stable = 0; is_unstable |= 1; } } if (min == 0) { if (*offset < 31) { (*offset)++; if (gain_stable) *min_offset = *offset; is_unstable |= 1; } else { DBG (DBG_error, "error: max static has pixel value == 0\n"); return -1; } } else { if (*offset > *min_offset) { (*offset)--; is_unstable |= 1; } } return is_unstable; } static int compute_bytes_per_line (int width_in_pixels, unsigned char hdpi_code, unsigned char pixel_packing, unsigned char data_mode, unsigned char AFE_operation, int m) { const int dpi_qot_mul[] = { 1, 2, 1, 1, 1, 1, 1, 1 }; const int dpi_qot_div[] = { 1, 3, 2, 3, 4, 6, 8, 12 }; int pixels_per_line; int bytes_per_line; int pixels_per_byte; int status_bytes; const int pixels_per_byte_mapping[] = { 8, 4, 2, 1 }; assert (hdpi_code <= 7); pixels_per_line = (width_in_pixels * dpi_qot_mul[hdpi_code]) / dpi_qot_div[hdpi_code]; if ((width_in_pixels * dpi_qot_mul[hdpi_code]) % dpi_qot_div[hdpi_code]) pixels_per_line++; status_bytes = (m == 0) ? 1 : m; if (data_mode == 1) pixels_per_byte = 1; /* should be 0.5 but later bytes_per_line will be multiplied by 2, and also the number of status bytes, that in this case should be 2. umm.. maybe this should be done in the cleaner way. */ else { assert (pixel_packing <= 3); pixels_per_byte = pixels_per_byte_mapping[pixel_packing]; } switch (AFE_operation) { case PIXEL_RATE_3_CHANNELS: bytes_per_line = ((pixels_per_line * 3) / pixels_per_byte) + status_bytes; break; case MODEA_1_CHANNEL: bytes_per_line = (pixels_per_line / pixels_per_byte) + status_bytes; break; default: /* Not implemented! (yet?) and not used. * This case should not happen. */ assert (0); } if (data_mode == 1) /* see big note above */ bytes_per_line *= 2; return bytes_per_line; } static int compute_pause_limit (hardware_parameters_t * hw_parms, int bytes_per_line) { int coef_size; const int coef_mapping[] = { 16, 32 }; int pause_limit; coef_size = coef_mapping[hw_parms->sensor_resolution & 0x01]; pause_limit = hw_parms->SRAM_size - coef_size - (bytes_per_line / 1024) - 1; if (pause_limit > 2) pause_limit -= 2; return pause_limit; } static int compute_dpd (HP4200_Scanner * s, int step_size, int line_end) { int tr, dpd; tr = 1 /* color mode */ * (line_end + ((s->hw_parms.num_tr_pulses + 1) * (2 * s->hw_parms.guard_band_duration + s->hw_parms.pulse_duration + 1) + 3 - s->hw_parms.num_tr_pulses)); if (tr == 0) return 0; dpd = (((s->hw_parms.fsteps_25_speed * 4) + (s->hw_parms.fsteps_50_speed * 2) + s->hw_parms.steps_to_reverse) * 4 * step_size) % tr; dpd = tr - dpd; return dpd; } static SANE_Status read_required_bytes (HP4200_Scanner * s, int required, SANE_Byte * buffer) { int read_count = 0; unsigned char scankb1; unsigned char scankb2; size_t to_read; size_t really_read; size_t chunk; SANE_Status status; assert (buffer != NULL); while (required) { do { scankb1 = getreg (s, 0x01); scankb2 = getreg (s, 0x01); if (s->aborted_by_user) return SANE_STATUS_CANCELLED; } while ((scankb1 != scankb2) || (scankb1 < 12)); to_read = min (required, (scankb1 * 1024)); while (to_read) { if (s->aborted_by_user) return SANE_STATUS_CANCELLED; chunk = (to_read > 0xffff) ? 0xffff : to_read; sanei_pv8630_write_byte (s->fd, PV8630_REPPADDRESS, 0x00); sanei_pv8630_prep_bulkread (s->fd, chunk); really_read = chunk; if ((status = sanei_usb_read_bulk (s->fd, buffer, &really_read)) != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_usb_read_bulk failed (%s)\n", sane_strstatus (status)); return status; } if (really_read > chunk) { DBG (DBG_error, "USB stack read more bytes than requested!\n"); return SANE_STATUS_IO_ERROR; } buffer += really_read; required -= really_read; to_read -= really_read; read_count += really_read; } } return SANE_STATUS_GOOD; } static SANE_Status scanner_buffer_init (scanner_buffer_t * sb, int size_in_kb) { sb->size = size_in_kb * 1024 + 3; sb->buffer = malloc (sb->size); if (!sb->buffer) return SANE_STATUS_NO_MEM; sb->num_bytes = 0; sb->data_ptr = sb->buffer; return SANE_STATUS_GOOD; } static SANE_Status scanner_buffer_read (HP4200_Scanner * s) { SANE_Status status; size_t num_bytes_read_now; assert (s->scanner_buffer.num_bytes <= 3); memcpy (s->scanner_buffer.buffer, s->scanner_buffer.data_ptr, 3); status = read_available_data (s, s->scanner_buffer.buffer + s->scanner_buffer.num_bytes, &num_bytes_read_now); s->scanner_buffer.data_ptr = s->scanner_buffer.buffer; s->scanner_buffer.num_bytes += num_bytes_read_now; return status; } #define OFFSET_CODE_SIGN(off) (((off) < 0) ? (-(off) & 0x1f) | 0x20 : (off)) #define OFFSET_DECODE_SIGN(off) (((off) & 0x20) ? -(off & 0x1f) : (off)) static SANE_Status do_coarse_calibration (HP4200_Scanner * s, struct coarse_t *coarse) { SANE_Status status; unsigned char *cal_line = NULL; unsigned char *cal_line_ptr; int cal_line_size; /* local scanning params */ int active_pixels_start; int line_end; int data_pixels_start; int data_pixels_end; int dpd; int step_size; int ff_step_size; char steps_to_reverse; char line_rate_color; int vdpi; /* vertical dots per inch */ int hdpi_code; int calibrated; int first_time; int red_offset = 0; int green_offset = 0; int blue_offset = 0; int red_gain = 1; int green_gain = 1; int blue_gain = 1; int min_red_offset = -31; int min_green_offset = -31; int min_blue_offset = -31; int max_red_gain = 63; int max_green_gain = 63; int max_blue_gain = 63; int max_red; int min_red; int max_green; int min_green; int max_blue; int min_blue; static char me[] = "do_coarse_calibration"; DBG (DBG_proc, "%s\n", me); setreg (s, 0x07, 0x00); usleep (10 * 1000); vdpi = 150; hdpi_code = 0; active_pixels_start = 0x40; line_end = 0x2ee0; s->mclk_div = 2; data_pixels_start = 0x40; data_pixels_end = (int) (data_pixels_start + s->hw_parms.scan_area_width); data_pixels_end = min (data_pixels_end, line_end - 20); cal_line_size = s->hw_parms.scan_area_width * 3 * 2 + 2; setreg (s, 0x1e, HIBYTE (active_pixels_start)); setreg (s, 0x1f, LOBYTE (active_pixels_start)); setreg (s, 0x20, HIBYTE (line_end)); setreg (s, 0x21, LOBYTE (line_end)); setreg (s, 0x22, HIBYTE (data_pixels_start)); setreg (s, 0x23, LOBYTE (data_pixels_start)); setreg (s, 0x24, HIBYTE (data_pixels_end)); setreg (s, 0x25, LOBYTE (data_pixels_end)); setreg (s, 0x26, PIXEL_RATE_3_CHANNELS | GRAY_CHANNEL_RED | TR_RED (0) | TR_GREEN (0) | TR_BLUE (0)); setreg (s, 0x08, (s->mclk_div - 1) * 2); setreg (s, 0x09, hdpi_code | PIXEL_PACKING (3) | DATAMODE (1)); setreg (s, 0x0a, 0); /* reserved and strange register */ setreg (s, 0x38, red_offset); setreg (s, 0x39, green_offset); setreg (s, 0x3a, blue_offset); setreg (s, 0x3b, red_gain); setreg (s, 0x3c, green_gain); setreg (s, 0x3d, blue_gain); setreg (s, 0x5e, 0x80); setreg (s, 0x3e, 0x00); /* 1.5:1, 6/10 bits, 2*fixed */ setreg (s, 0x3f, 0x00); setreg (s, 0x40, 0x00); setreg (s, 0x41, 0x00); setreg (s, 0x4e, 0x5b - 0x3c); /* max Kb to pause */ setreg (s, 0x4f, 0x02); /* min Kb to resume */ line_rate_color = 1; step_size = (vdpi * line_end * line_rate_color) / (4 * s->hw_parms.motor_full_steps_per_inch); dpd = compute_dpd (s, step_size, line_end); /* 0x0ada; */ #ifdef DEBUG fprintf (stderr, "dpd = %d\n", dpd); #endif setreg (s, 0x52, HIBYTE (dpd)); setreg (s, 0x53, LOBYTE (dpd)); setreg (s, 0x46, HIBYTE (step_size)); setreg (s, 0x47, LOBYTE (step_size)); ff_step_size = compute_fastfeed_step_size (s->hw_parms.crystal_frequency, s->mclk_div, s->hw_parms.motor_max_speed, s->hw_parms.motor_full_steps_per_inch, 0); /* 0x0190; */ setreg (s, 0x48, HIBYTE (ff_step_size)); setreg (s, 0x49, LOBYTE (ff_step_size)); setreg (s, 0x4b, 0x15); steps_to_reverse = 0x3f; setreg (s, 0x50, steps_to_reverse); setreg (s, 0x51, 0x15); /* accel profile */ /* this is to stay the motor stopped */ clearbits (s, 0x45, (1 << 4)); cache_write (s); calibrated = 0; first_time = 1; cal_line = malloc (cal_line_size + 1024); do { unsigned char cmd_reg; /* resets the lm9830 before start scanning */ setreg (s, 0x07, 0x08); do { setreg (s, 0x07, 0x03); cmd_reg = getreg (s, 0x07); } while (cmd_reg != 0x03); cal_line_ptr = cal_line; status = read_required_bytes (s, cal_line_size, cal_line_ptr); if (status != SANE_STATUS_GOOD) goto done; setreg (s, 0x07, 0x00); { unsigned int i; min_red = max_red = (cal_line[0] * 256 + cal_line[1]) >> 2; min_green = max_green = (cal_line[2] * 256 + cal_line[3]) >> 2; min_blue = max_blue = (cal_line[4] * 256 + cal_line[5]) >> 2; for (i = 6; i < (s->hw_parms.scan_area_width * 3 * 2); i += 6) { int value; value = cal_line[i] * 256 + cal_line[i + 1]; value >>= 2; if (value > max_red) max_red = value; value = cal_line[i + 2] * 256 + cal_line[i + 3]; value >>= 2; if (value > max_green) max_green = value; value = cal_line[i + 4] * 256 + cal_line[i + 5]; value >>= 2; if (value > max_blue) max_blue = value; value = cal_line[i] * 256 + cal_line[i + 1]; value >>= 2; if (value < min_red) min_red = value; value = cal_line[i + 2] * 256 + cal_line[i + 3]; value >>= 2; if (value < min_green) min_green = value; value = cal_line[i + 4] * 256 + cal_line[i + 5]; value >>= 2; if (value < min_blue) min_blue = value; } #ifdef DEBUG fprintf (stderr, "max_red:%d max_green:%d max_blue:%d\n", max_red, max_green, max_blue); fprintf (stderr, "min_red:%d min_green:%d min_blue:%d\n", min_red, min_green, min_blue); #endif if (first_time) { first_time = 0; compute_first_gain_offset (s->hw_parms.target_value.red, max_red, min_red, &red_gain, &red_offset, &max_red_gain, &min_red_offset); compute_first_gain_offset (s->hw_parms.target_value.green, max_green, min_green, &green_gain, &green_offset, &max_green_gain, &min_green_offset); compute_first_gain_offset (s->hw_parms.target_value.blue, max_blue, min_blue, &blue_gain, &blue_offset, &max_blue_gain, &min_blue_offset); } else { int retval; /* this code should check return value -1 for error */ retval = compute_gain_offset (s->hw_parms.target_value.red, max_red, min_red, &red_gain, &red_offset, &max_red_gain, &min_red_offset); if (retval < 0) break; retval |= compute_gain_offset (s->hw_parms.target_value.green, max_green, min_green, &green_gain, &green_offset, &max_green_gain, &min_green_offset); if (retval < 0) break; retval |= compute_gain_offset (s->hw_parms.target_value.blue, max_blue, min_blue, &blue_gain, &blue_offset, &max_blue_gain, &min_blue_offset); if (retval < 0) break; calibrated = !retval; } setreg (s, 0x3b, red_gain); setreg (s, 0x3c, green_gain); setreg (s, 0x3d, blue_gain); setreg (s, 0x38, OFFSET_CODE_SIGN (red_offset)); setreg (s, 0x39, OFFSET_CODE_SIGN (green_offset)); setreg (s, 0x3a, OFFSET_CODE_SIGN (blue_offset)); #ifdef DEBUG fprintf (stderr, "%d, %d, %d %d, %d, %d\n", red_gain, green_gain, blue_gain, red_offset, green_offset, blue_offset); #endif cache_write (s); } } while (!calibrated); coarse->min_red = min_red; coarse->min_green = min_green; coarse->min_blue = min_blue; coarse->max_red = max_red; coarse->max_green = max_green; coarse->max_blue = max_blue; coarse->red_gain = red_gain; coarse->green_gain = green_gain; coarse->blue_gain = blue_gain; coarse->red_offset = red_offset; coarse->green_offset = green_offset; coarse->blue_offset = blue_offset; status = SANE_STATUS_GOOD; done: if (cal_line) free (cal_line); return status; } static int compute_corr_code (int average, int min_color, int range, int target) { int value; int corr_code; value = average - min_color; if (value > 0) corr_code = (int) (range * ((double) target / (double) value - 1.0) + 0.5); else corr_code = 0; if (corr_code < 0) corr_code = 0; else if (corr_code > 2048) corr_code = 0; else if (corr_code > 1023) corr_code = 1023; return corr_code; } static int compute_hdpi_code (int hres) { int hdpi_code; /* Calculate the horizontal DPI code based on the requested horizontal resolution. Defaults to 150dpi. */ switch (hres) { case 600: hdpi_code = 0; break; case 400: hdpi_code = 1; break; case 300: hdpi_code = 2; break; case 200: hdpi_code = 3; break; case 150: hdpi_code = 4; break; case 100: hdpi_code = 5; break; case 75: hdpi_code = 6; break; case 50: hdpi_code = 7; break; default: hdpi_code = 4; } return hdpi_code; } static SANE_Status do_fine_calibration (HP4200_Scanner * s, struct coarse_t *coarse) { SANE_Status status; unsigned char *cal_line; unsigned char *cal_line_ptr; int *average; SANE_Byte red_gain_offset[5460 * 2]; SANE_Byte green_gain_offset[5460 * 2]; SANE_Byte blue_gain_offset[5460 * 2]; int *corr_red = NULL; int *corr_green = NULL; int *corr_blue = NULL; int registro[30][5460 * 3]; int cal_line_size; /* local scanning params */ int active_pixels_start; int line_end; int line_length; int data_pixels_start; int data_pixels_end; int dpd; int step_size; int ff_step_size; char steps_to_reverse; char hdpi_div; char line_rate_color; int vdpi; /* vertical dots per inch */ int hdpi_code; int calibrated; int lines_to_process; static char me[] = "do_fine_calibration"; DBG (DBG_proc, "%s\n", me); setreg (s, 0x07, 0x00); usleep (10 * 1000); vdpi = 150; hdpi_code = compute_hdpi_code (s->user_parms.horizontal_resolution); /* figure out which horizontal divider to use based on the calculated horizontal dpi code */ hdpi_div = hdpi_mapping[hdpi_code]; active_pixels_start = 0x40; line_end = 0x2ee0; line_length = s->user_parms.image_width * hdpi_div; s->mclk_div = 2; data_pixels_start = 0x72 + s->runtime_parms.first_pixel * hdpi_div; data_pixels_end = (int) (data_pixels_start + s->user_parms.image_width * hdpi_div); data_pixels_end = min (data_pixels_end, line_end - 20); cal_line_size = line_length * 3 * 2 + 2; setreg (s, 0x1e, HIBYTE (active_pixels_start)); setreg (s, 0x1f, LOBYTE (active_pixels_start)); setreg (s, 0x20, HIBYTE (line_end)); setreg (s, 0x21, LOBYTE (line_end)); setreg (s, 0x22, HIBYTE (data_pixels_start)); setreg (s, 0x23, LOBYTE (data_pixels_start)); setreg (s, 0x24, HIBYTE (data_pixels_end)); setreg (s, 0x25, LOBYTE (data_pixels_end)); setreg (s, 0x26, PIXEL_RATE_3_CHANNELS | GRAY_CHANNEL_RED | TR_RED (0) | TR_GREEN (0) | TR_BLUE (0)); setreg (s, 0x08, (s->mclk_div - 1) * 2); setreg (s, 0x09, 0 | PIXEL_PACKING (3) | DATAMODE (1)); setreg (s, 0x0a, 0); /* reserved and strange register */ setreg (s, 0x38, 1); setreg (s, 0x39, 1); setreg (s, 0x3a, 1); setreg (s, 0x3b, coarse->red_gain); setreg (s, 0x3c, coarse->green_gain); setreg (s, 0x3d, coarse->blue_gain); setreg (s, 0x5e, 0x80); setreg (s, 0x3e, 0x00); /* 1.5:1, 6/10 bits, 2*fixed */ setreg (s, 0x3f, 0x00); setreg (s, 0x40, 0x00); setreg (s, 0x41, 0x00); setreg (s, 0x4e, 0x5b - 0x3c); /* max Kb to pause */ setreg (s, 0x4f, 0x02); /* min Kb to resume */ line_rate_color = 1; step_size = (vdpi * line_end * line_rate_color) / (4 * s->hw_parms.motor_full_steps_per_inch); dpd = compute_dpd (s, step_size, line_end); /* 0x0ada; */ #ifdef DEBUG fprintf (stderr, "dpd = %d\n", dpd); #endif setreg (s, 0x52, HIBYTE (dpd)); setreg (s, 0x53, LOBYTE (dpd)); setreg (s, 0x46, HIBYTE (step_size)); setreg (s, 0x47, LOBYTE (step_size)); ff_step_size = compute_fastfeed_step_size (s->hw_parms.crystal_frequency, s->mclk_div, s->hw_parms.motor_max_speed, s->hw_parms.motor_full_steps_per_inch, 0); /* 0x0190; */ setreg (s, 0x48, HIBYTE (ff_step_size)); setreg (s, 0x49, LOBYTE (ff_step_size)); setreg (s, 0x4b, 0x15); steps_to_reverse = 0x3f; setreg (s, 0x50, steps_to_reverse); setreg (s, 0x51, 0x15); /* accel profile */ /* this is to activate the motor */ setbits (s, 0x45, (1 << 4)); lines_to_process = 8 * step_size * 4 / line_end; if (lines_to_process < 1) lines_to_process = 1; #ifdef DEBUG fprintf (stderr, "lines to process = %d\n", lines_to_process); #endif setreg (s, 0x58, 0); cache_write (s); calibrated = 0; cal_line = malloc (cal_line_size + 1024); average = malloc (sizeof (int) * line_length * 3); memset (average, 0, sizeof (int) * line_length * 3); { int i; for (i = 0; i < 12; i++) { memset (registro[i], 0, 5460 * 3); } } /* resets the lm9830 before start scanning */ setreg (s, 0x07, 0x08); setreg (s, 0x07, 0x03); usleep (100); do { cal_line_ptr = cal_line; status = read_required_bytes (s, cal_line_size, cal_line_ptr); if (status != SANE_STATUS_GOOD) goto done; { int i, j; if (calibrated == 0) for (j = 0, i = 0; i < (line_length * 3); i++, j += 2) { average[i] = (cal_line[j] * 256 + cal_line[j + 1]) >> 2; registro[calibrated][i] = average[i]; } else for (j = 0, i = 0; i < (line_length * 3); i++, j += 2) { int value; value = (cal_line[j] * 256 + cal_line[j + 1]) >> 2; average[i] += value; average[i] /= 2; registro[calibrated][i] = value; } } calibrated++; } while (calibrated < lines_to_process); lm9830_write_register (s->fd, 0x07, 0x00); usleep (10 * 1000); #if 0 { int i; int j = 0; do { for (i = 3; (i + 6) < (line_length * 3); i += 3) { average[i] = (2 * average[i - 3] + average[i] + 2 * average[i + 3]) / 5; average[i + 1] = (2 * average[i - 2] + average[i + 1] + 2 * average[i + 4]) / 5; average[i + 2] = (2 * average[i - 1] + average[i + 2] + 2 * average[i + 5]) / 5; } j++; } while (j < 3); } #endif { int i; int max_red; int min_red; int max_green; int min_green; int max_blue; int min_blue; min_red = max_red = average[0]; min_green = max_green = average[1]; min_blue = max_blue = average[2]; for (i = 3; i < (line_length * 3); i += 3) { int value; value = average[i]; if (value > max_red) max_red = value; value = average[i + 1]; if (value > max_green) max_green = value; value = average[i + 2]; if (value > max_blue) max_blue = value; value = average[i]; if (value < min_red) min_red = value; value = average[i + 1]; if (value < min_green) min_green = value; value = average[i + 2]; if (value < min_blue) min_blue = value; } #ifdef DEBUG fprintf (stderr, "max_red:%d max_green:%d max_blue:%d\n", max_red, max_green, max_blue); fprintf (stderr, "min_red:%d min_green:%d min_blue:%d\n", min_red, min_green, min_blue); #endif /* do fine calibration */ { int min_white_red; int min_white_green; int min_white_blue; double ratio; int range; double aux; int min_white_err; int j; min_white_red = min_white_green = min_white_blue = 0x3ff; for (i = 0; i < (line_length * 3); i += 3) { int value; value = average[i] - coarse->min_red; if ((value > 0) && (value < min_white_red)) min_white_red = value; value = average[i + 1] - coarse->min_green; if ((value > 0) && (value < min_white_green)) min_white_green = value; value = average[i + 2] - coarse->min_blue; if ((value > 0) && (value < min_white_blue)) min_white_blue = value; } ratio = 0; min_white_err = 0x3ff; aux = (double) s->hw_parms.target_value.red / min_white_red; if (aux > ratio) ratio = aux; if (min_white_err > min_white_red) min_white_err = min_white_red; aux = (double) s->hw_parms.target_value.green / min_white_green; if (aux > ratio) ratio = aux; if (min_white_err > min_white_green) min_white_err = min_white_green; aux = (double) s->hw_parms.target_value.blue / min_white_blue; if (aux > ratio) ratio = aux; if (min_white_err > min_white_blue) min_white_err = min_white_blue; #ifdef DEBUG fprintf (stderr, "min_white_err = %d, ratio = %f\n", min_white_err, ratio); #endif if (ratio <= 1.5) range = 2048; else if (ratio <= 2.0) range = 1024; else range = 512; corr_red = malloc (sizeof (int) * line_length); corr_green = malloc (sizeof (int) * line_length); corr_blue = malloc (sizeof (int) * line_length); for (i = 0, j = 0; i < (line_length * 3); i += 3, j++) { corr_red[j] = compute_corr_code (average[i], coarse->min_red, range, s->hw_parms.target_value.red); corr_green[j] = compute_corr_code (average[i + 1], coarse->min_green, range, s->hw_parms.target_value.green); corr_blue[j] = compute_corr_code (average[i + 2], coarse->min_blue, range, s->hw_parms.target_value.blue); } #ifdef DEBUG { FILE *kaka; int i; kaka = fopen ("corr.raw", "w"); for (i = 0; i < line_length; i++) { fprintf (kaka, "%d %d %d %d %d %d ", corr_red[i], corr_green[i], corr_blue[i], average[3 * i], average[3 * i + 1], average[3 * i + 2]); fprintf (kaka, "%d %d %d %d %d %d %d %d %d ", registro[0][3 * i], registro[0][3 * i + 1], registro[0][3 * i + 2], registro[1][3 * i], registro[1][3 * i + 1], registro[1][3 * i + 2], registro[2][3 * i], registro[2][3 * i + 1], registro[2][3 * i + 2]); fprintf (kaka, "%d %d %d %d %d %d %d %d %d\n", registro[3][3 * i], registro[3][3 * i + 1], registro[3][3 * i + 2], registro[4][3 * i], registro[4][3 * i + 1], registro[4][3 * i + 2], registro[5][3 * i], registro[5][3 * i + 1], registro[5][3 * i + 2]); } fclose (kaka); } #endif { int max_black; int use_six_eight_bits; max_black = max (coarse->min_red, coarse->min_green); max_black = max (max_black, coarse->min_blue); use_six_eight_bits = (max_black < 64); if (use_six_eight_bits) { setreg (s, 0x3e, (1 << 4) | (1 << 3) | (1024 / range)); } else { setreg (s, 0x3e, (1 << 4) | (1 << 3) | (1 << 2) | (1024 / range)); } memset (red_gain_offset, 0, sizeof (red_gain_offset)); memset (green_gain_offset, 0, sizeof (green_gain_offset)); memset (blue_gain_offset, 0, sizeof (blue_gain_offset)); for (i = 0, j = (data_pixels_start - active_pixels_start) * 2; i < line_length; i++, j += 2) { if (use_six_eight_bits) { red_gain_offset[j] = (coarse->min_red << 2) | ((corr_red[i] >> 8) & 0x03); red_gain_offset[j + 1] = corr_red[i] & 0xff; green_gain_offset[j] = (coarse->min_green << 2) | ((corr_green[i] >> 8) & 0x03); green_gain_offset[j + 1] = corr_green[i] & 0xff; blue_gain_offset[j] = (coarse->min_blue << 2) | ((corr_blue[i] >> 8) & 0x03); blue_gain_offset[j + 1] = corr_blue[i] & 0xff; } else { red_gain_offset[j] = coarse->min_red; red_gain_offset[j + 1] = corr_red[j] >> 2; green_gain_offset[j] = coarse->min_green; green_gain_offset[j + 1] = corr_green[j] >> 2; blue_gain_offset[j] = coarse->min_blue; blue_gain_offset[j + 1] = corr_blue[j] >> 2; } } write_default_offset_gain (s, red_gain_offset, 5460 * 2, 0); write_default_offset_gain (s, green_gain_offset, 5460 * 2, 1); write_default_offset_gain (s, blue_gain_offset, 5460 * 2, 2); } } } status = SANE_STATUS_GOOD; done: if (corr_red) free (corr_red); if (corr_green) free (corr_green); if (corr_blue) free (corr_blue); if (cal_line) free (cal_line); if (average) free (average); return status; } static void ciclic_buffer_init_offset_correction (ciclic_buffer_t * cb, int vres) { cb->blue_idx = 0; switch (vres) { case 600: cb->green_idx = 4; cb->red_idx = 8; cb->first_good_line = 8; break; case 400: cb->green_idx = 3; cb->red_idx = 6; cb->first_good_line = 6; break; case 300: cb->green_idx = 2; cb->red_idx = 4; cb->first_good_line = 4; break; case 200: cb->blue_idx = 0; cb->green_idx = 1; cb->red_idx = 2; cb->first_good_line = 4; break; case 150: cb->green_idx = 1; cb->red_idx = 2; cb->first_good_line = 2; break; case 75: cb->green_idx = 1; cb->red_idx = 2; cb->first_good_line = 2; break; default: cb->green_idx = 0; cb->red_idx = 0; cb->first_good_line = 0; break; } cb->buffer_position = cb->buffer_ptrs[cb->first_good_line]; } static SANE_Status ciclic_buffer_init (ciclic_buffer_t * cb, SANE_Int bytes_per_line, int vres, int status_bytes) { cb->good_bytes = 0; cb->num_lines = 12; cb->size = bytes_per_line * cb->num_lines; cb->can_consume = cb->size + cb->num_lines * status_bytes; cb->buffer = malloc (cb->size); if (!cb->buffer) return SANE_STATUS_NO_MEM; { int i; unsigned char *buffer; unsigned char **ptrs; ptrs = cb->buffer_ptrs = (unsigned char **) malloc (sizeof (unsigned char *) * cb->num_lines); if (!cb->buffer_ptrs) return SANE_STATUS_NO_MEM; buffer = cb->buffer; for (i = 0; i < cb->num_lines; i++) { ptrs[i] = buffer; buffer += bytes_per_line; } } cb->current_line = 0; cb->pixel_position = 0; ciclic_buffer_init_offset_correction (cb, vres); return SANE_STATUS_GOOD; } static int prepare_for_a_scan (HP4200_Scanner * s) { /* local scanning params */ int active_pixels_start; int line_end; int data_pixels_start; int data_pixels_end; int ff_step_size; int dpd; int step_size; char steps_to_reverse; char hdpi_div; char line_rate_color; int hdpi_code; unsigned char pixel_packing; unsigned char data_mode; unsigned char AFE_operation; int pause_limit; int n = 0, m = 0; setreg (s, 0x07, 0x00); usleep (10 * 1000); hdpi_code = compute_hdpi_code (s->user_parms.horizontal_resolution); /* figure out which horizontal divider to use based on the calculated horizontal dpi code */ hdpi_div = hdpi_mapping[hdpi_code]; /* image_width is set to the correct number of pixels by calling fxn. This might be the reason we can't do high res full width scans though...not sure. */ /*s->user_parms.image_width /= 4; */ active_pixels_start = 0x40; line_end = 0x2ee0; /* 2ee0 */ s->mclk_div = 2; data_pixels_start = 0x72 + s->runtime_parms.first_pixel * hdpi_div; data_pixels_end = (int) (data_pixels_start + s->user_parms.image_width * hdpi_div); data_pixels_end = min (data_pixels_end, line_end - 20); setreg (s, 0x1e, HIBYTE (active_pixels_start)); setreg (s, 0x1f, LOBYTE (active_pixels_start)); setreg (s, 0x20, HIBYTE (line_end)); setreg (s, 0x21, LOBYTE (line_end)); setreg (s, 0x22, HIBYTE (data_pixels_start)); setreg (s, 0x23, LOBYTE (data_pixels_start)); setreg (s, 0x24, HIBYTE (data_pixels_end)); setreg (s, 0x25, LOBYTE (data_pixels_end)); AFE_operation = PIXEL_RATE_3_CHANNELS; setreg (s, 0x26, AFE_operation | GRAY_CHANNEL_RED | TR_RED (0) | TR_GREEN (0) | TR_BLUE (0)); setreg (s, 0x08, (s->mclk_div - 1) * 2); pixel_packing = 3; data_mode = 0; setreg (s, 0x09, hdpi_code | PIXEL_PACKING (pixel_packing) | DATAMODE (data_mode)); setreg (s, 0x0a, 0); /* reserved and strange register */ setreg (s, 0x5c, 0x00); setreg (s, 0x5d, 0x00); setreg (s, 0x5e, 0x00); if (s->user_parms.vertical_resolution == 1200) { /* 1 out of 2 */ n = 1; m = 2; } setreg (s, 0x44, (256 - n) & 0xff); setreg (s, 0x5a, m); s->runtime_parms.status_bytes = (m == 0) ? 1 : m; if (data_mode == 1) s->runtime_parms.status_bytes *= 2; s->runtime_parms.scanner_line_size = compute_bytes_per_line (data_pixels_end - data_pixels_start, hdpi_code, pixel_packing, data_mode, AFE_operation, m); pause_limit = compute_pause_limit (&(s->hw_parms), s->runtime_parms.scanner_line_size); #ifdef DEBUG fprintf (stderr, "scanner_line_size = %d\npause_limit = %d\n", s->runtime_parms.scanner_line_size, pause_limit); #endif setreg (s, 0x4e, pause_limit); /* max Kb to pause */ setreg (s, 0x4f, 0x02); /* min Kb to resume */ line_rate_color = 1; step_size = (s->user_parms.vertical_resolution * line_end * line_rate_color) / (4 * s->hw_parms.motor_full_steps_per_inch); if (s->val[OPT_BACKTRACK].b) { steps_to_reverse = 0x3f; setreg (s, 0x50, steps_to_reverse); setreg (s, 0x51, 0x15); /* accel profile */ } else { s->hw_parms.steps_to_reverse = 0; setreg (s, 0x50, s->hw_parms.steps_to_reverse); setreg (s, 0x51, 0); /* accel profile */ s->hw_parms.fsteps_25_speed = 0; s->hw_parms.fsteps_50_speed = 0; } dpd = compute_dpd (s, step_size, line_end); /* 0x0ada; */ #ifdef DEBUG fprintf (stderr, "dpd = %d\n", dpd); #endif setreg (s, 0x52, HIBYTE (dpd)); setreg (s, 0x53, LOBYTE (dpd)); setreg (s, 0x46, HIBYTE (step_size)); setreg (s, 0x47, LOBYTE (step_size)); ff_step_size = compute_fastfeed_step_size (s->hw_parms.crystal_frequency, s->mclk_div, s->hw_parms.motor_max_speed, s->hw_parms. motor_full_steps_per_inch, 0); setreg (s, 0x48, HIBYTE (ff_step_size)); setreg (s, 0x49, LOBYTE (ff_step_size)); setreg (s, 0x4b, 0x15); /* this is to stay the motor running */ setbits (s, 0x45, (1 << 4)); setreg (s, 0x4a, HIBYTE (47 + s->runtime_parms.steps_to_skip)); setreg (s, 0x4b, LOBYTE (47 + s->runtime_parms.steps_to_skip)); setreg (s, 0x58, 0); ciclic_buffer_init (&(s->ciclic_buffer), s->runtime_parms.image_line_size, s->user_parms.vertical_resolution, s->runtime_parms.status_bytes); s->runtime_parms.num_bytes_left_to_scan = s->user_parms.lines_to_scan * s->runtime_parms.image_line_size; #ifdef DEBUG fprintf (stderr, "bytes to scan = %ld\n", s->runtime_parms.num_bytes_left_to_scan); #endif cache_write (s); #ifdef DEBUG lm9830_dump_registers (s->fd); #endif lm9830_reset (s->fd); setreg (s, 0x07, 0x03); usleep (100); return SANE_STATUS_GOOD; } static SANE_Status end_scan (HP4200_Scanner * s) { s->scanning = SANE_FALSE; setreg (s, 0x07, 0x00); lm9830_reset (s->fd); setbits (s, 0x58, PAPER_SENSOR_2_STOP_SCAN); cache_write (s); setreg (s, 0x07, 0x02); /* Free some buffers */ if (s->ciclic_buffer.buffer) { free (s->ciclic_buffer.buffer); s->ciclic_buffer.buffer = NULL; } if (s->ciclic_buffer.buffer_ptrs) { free (s->ciclic_buffer.buffer_ptrs); s->ciclic_buffer.buffer_ptrs = NULL; } if (s->scanner_buffer.buffer) { free (s->scanner_buffer.buffer); s->scanner_buffer.buffer = NULL; } return SANE_STATUS_GOOD; } static int hp4200_init_scanner (HP4200_Scanner * s) { int ff_step_size; int mclk_div; lm9830_ini_scanner (s->fd, NULL); hp4200_init_registers (s); scanner_buffer_init (&(s->scanner_buffer), s->hw_parms.SRAM_size); setreg (s, 0x07, 0x08); usleep (10 * 1000); setreg (s, 0x07, 0x00); usleep (10 * 1000); mclk_div = 2; setreg (s, 0x08, (mclk_div - 1) * 2); ff_step_size = compute_fastfeed_step_size (s->hw_parms.crystal_frequency, mclk_div, s->hw_parms.motor_max_speed, s->hw_parms.motor_full_steps_per_inch, 0); setreg (s, 0x48, HIBYTE (ff_step_size)); setreg (s, 0x49, LOBYTE (ff_step_size)); setbits (s, 0x45, (1 << 4)); cache_write (s); return 0; } static void ciclic_buffer_copy (ciclic_buffer_t * cb, SANE_Byte * buf, SANE_Int num_bytes, int image_line_size, int status_bytes) { int biggest_upper_block_size; int upper_block_size; int lower_block_size; int bytes_to_be_a_entire_line; /* copy the upper block */ biggest_upper_block_size = cb->size - (cb->buffer_position - cb->buffer); upper_block_size = min (biggest_upper_block_size, num_bytes); memcpy (buf, cb->buffer_position, upper_block_size); cb->good_bytes -= upper_block_size; bytes_to_be_a_entire_line = (cb->buffer_position - cb->buffer) % image_line_size; cb->can_consume += upper_block_size + status_bytes * (((bytes_to_be_a_entire_line + upper_block_size) / image_line_size) - 1); if (num_bytes < biggest_upper_block_size) { cb->buffer_position += num_bytes; return; } /* copy the lower block */ lower_block_size = num_bytes - biggest_upper_block_size; if (lower_block_size > 0) { memcpy (buf + biggest_upper_block_size, cb->buffer, lower_block_size); cb->good_bytes -= lower_block_size; cb->can_consume += lower_block_size + status_bytes * (lower_block_size / image_line_size); cb->buffer_position = cb->buffer + lower_block_size; } else { cb->buffer_position = cb->buffer; } assert (cb->good_bytes >= 0); assert (lower_block_size >= 0); } static void ciclic_buffer_consume (ciclic_buffer_t * cb, scanner_buffer_t * scanner_buffer, int image_width, int status_bytes) { int to_consume; int to_consume_now; int i; int processed; to_consume = min (cb->can_consume, scanner_buffer->num_bytes); while (to_consume) { if (cb->pixel_position == image_width) { if (scanner_buffer->num_bytes >= status_bytes) { /* forget status bytes */ scanner_buffer->data_ptr += status_bytes; scanner_buffer->num_bytes -= status_bytes; cb->can_consume -= status_bytes; to_consume -= status_bytes; cb->pixel_position = 0; /* back to the start pixel */ cb->red_idx = (cb->red_idx + 1) % cb->num_lines; cb->green_idx = (cb->green_idx + 1) % cb->num_lines; cb->blue_idx = (cb->blue_idx + 1) % cb->num_lines; cb->current_line++; } else break; } to_consume_now = min ((image_width - cb->pixel_position) * 3, to_consume); if (to_consume_now < 3) break; for (i = cb->pixel_position * 3; to_consume_now >= 3; i += 3, to_consume_now -= 3) { cb->buffer_ptrs[cb->red_idx][i] = scanner_buffer->data_ptr[0]; cb->buffer_ptrs[cb->green_idx][i + 1] = scanner_buffer->data_ptr[1]; cb->buffer_ptrs[cb->blue_idx][i + 2] = scanner_buffer->data_ptr[2]; scanner_buffer->data_ptr += 3; } processed = i - (cb->pixel_position * 3); cb->pixel_position = i / 3; to_consume -= processed; cb->can_consume -= processed; scanner_buffer->num_bytes -= processed; if (cb->current_line > cb->first_good_line) cb->good_bytes += processed; } } SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) { SANE_Status status; int to_copy_now; int bytes_to_copy_to_frontend; HP4200_Scanner *s = h; static char me[] = "sane_read"; DBG (DBG_proc, "%s\n", me); if (!(s->scanning)) { /* OOPS, not scanning */ return SANE_STATUS_CANCELLED; } if (!buf || !len) return SANE_STATUS_INVAL; *len = 0; if (s->runtime_parms.num_bytes_left_to_scan == 0) { end_scan (s); return SANE_STATUS_EOF; } bytes_to_copy_to_frontend = min (s->runtime_parms.num_bytes_left_to_scan, maxlen); /* first copy available data from the ciclic buffer */ to_copy_now = min (s->ciclic_buffer.good_bytes, bytes_to_copy_to_frontend); if (to_copy_now > 0) { ciclic_buffer_copy (&(s->ciclic_buffer), buf, to_copy_now, s->runtime_parms.image_line_size, s->runtime_parms.status_bytes); buf += to_copy_now; bytes_to_copy_to_frontend -= to_copy_now; *len += to_copy_now; } /* if not enough bytes, get data from the scanner */ while (bytes_to_copy_to_frontend) { if (s->scanner_buffer.num_bytes < 3) { /* cicl buf consumes modulo 3 bytes at least now for rgb color 8 bpp fixme: but this is ugly and not generic */ status = scanner_buffer_read (s); if (status == SANE_STATUS_CANCELLED) { end_scan (s); s->aborted_by_user = SANE_FALSE; return status; } if (status != SANE_STATUS_GOOD) return status; } while ((s->scanner_buffer.num_bytes > 3) && bytes_to_copy_to_frontend) { ciclic_buffer_consume (&(s->ciclic_buffer), &(s->scanner_buffer), s->user_parms.image_width, s->runtime_parms.status_bytes); to_copy_now = min (s->ciclic_buffer.good_bytes, bytes_to_copy_to_frontend); if (to_copy_now > 0) { ciclic_buffer_copy (&(s->ciclic_buffer), buf, to_copy_now, s->runtime_parms.image_line_size, s->runtime_parms.status_bytes); buf += to_copy_now; bytes_to_copy_to_frontend -= to_copy_now; *len += to_copy_now; } } } s->runtime_parms.num_bytes_left_to_scan -= *len; if (s->runtime_parms.num_bytes_left_to_scan < 0) *len += s->runtime_parms.num_bytes_left_to_scan; return SANE_STATUS_GOOD; } static HP4200_Device * find_device (SANE_String_Const name) { static char me[] = "find_device"; HP4200_Device *dev; DBG (DBG_proc, "%s\n", me); for (dev = first_device; dev; dev = dev->next) { if (strcmp (dev->dev.name, name) == 0) { return dev; } } return NULL; } static SANE_Status add_device (SANE_String_Const name, HP4200_Device ** argpd) { int fd; HP4200_Device *pd; static const char me[] = "add_device"; SANE_Status status; DBG (DBG_proc, "%s(%s)\n", me, name); /* Avoid adding the same device more than once */ if ((pd = find_device (name))) { if (argpd) *argpd = pd; return SANE_STATUS_GOOD; } /* open the device file, but read only or read/write to perform ioctl's ? */ if ((status = sanei_usb_open (name, &fd)) != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: open(%s) failed: %s\n", me, name, sane_strstatus (status)); return SANE_STATUS_INVAL; } /* put here some code to probe that the device attached to the device file is a supported scanner. Maybe some ioctl */ sanei_usb_close (fd); pd = (HP4200_Device *) calloc (1, sizeof (HP4200_Device)); if (!pd) { DBG (DBG_error, "%s: out of memory allocating device.\n", me); return SANE_STATUS_NO_MEM; } pd->dev.name = strdup (name); pd->dev.vendor = "Hewlett-Packard"; pd->dev.model = "HP-4200"; pd->dev.type = "flatbed scanner"; if (!pd->dev.name || !pd->dev.vendor || !pd->dev.model || !pd->dev.type) { DBG (DBG_error, "%s: out of memory allocating device descriptor strings.\n", me); free (pd); return SANE_STATUS_NO_MEM; } pd->handle = NULL; pd->next = first_device; first_device = pd; n_devices++; if (argpd) *argpd = pd; return SANE_STATUS_GOOD; } static SANE_Status attach (SANE_String_Const name) { static char me[] = "attach"; DBG (DBG_proc, "%s\n", me); return add_device (name, NULL); } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { static const char me[] = "sane_hp4200_init"; char dev_name[PATH_MAX]; FILE *fp; authorize = authorize; /* keep gcc quiet */ DBG_INIT (); DBG (DBG_proc, "%s\n", me); DBG (DBG_error, "SANE hp4200 backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); /* put some version_code checks here */ if (NULL != version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); } sanei_usb_init (); sanei_pv8630_init (); fp = sanei_config_open (HP4200_CONFIG_FILE); if (!fp) { DBG (DBG_error, "%s: configuration file not found!\n", me); return SANE_STATUS_INVAL; } else { while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; if (strlen (dev_name) == 0) continue; /* ignore empty lines */ DBG (DBG_info, "%s: looking for devices matching %s\n", me, dev_name); sanei_usb_attach_matching_devices (dev_name, attach); } fclose (fp); } return SANE_STATUS_GOOD; } void sane_exit (void) { HP4200_Device *device, *next; DBG (DBG_proc, "sane_hp4200_exit\n"); for (device = first_device; device; device = next) { next = device->next; if (device->handle) { sane_close (device->handle); } if (device->dev.name) { free ((void *) device->dev.name); } free (device); } first_device = NULL; if (devlist) { free (devlist); devlist = NULL; } n_devices = 0; DBG (DBG_proc, "sane_exit: exit\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { int i; HP4200_Device *pdev; DBG (DBG_proc, "sane_get_devices (%p, %d)\n", (void *) device_list, local_only); /* Waste the last list returned from this function */ if (devlist) free (devlist); devlist = (const SANE_Device **) malloc ((n_devices + 1) * sizeof (SANE_Device *)); if (!devlist) { DBG (DBG_error, "sane_get_devices: out of memory\n"); return SANE_STATUS_NO_MEM; } for (i = 0, pdev = first_device; pdev; i++, pdev = pdev->next) { devlist[i] = &(pdev->dev); } devlist[i] = NULL; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } static void init_options (HP4200_Scanner * s) { s->opt[OPT_NUM_OPTS].name = ""; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; s->opt[OPT_NUM_OPTS].size = sizeof (SANE_Word); s->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; s->opt[OPT_RES].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RES].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RES].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RES].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_RES].type = SANE_TYPE_INT; s->opt[OPT_RES].size = sizeof (SANE_Word); s->opt[OPT_RES].unit = SANE_UNIT_DPI; s->opt[OPT_RES].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RES].constraint.word_list = dpi_list; s->val[OPT_RES].w = 150; s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].size = sizeof (SANE_Fixed); s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &x_range; s->val[OPT_TL_X].w = x_range.min; s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].size = sizeof (SANE_Fixed); s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &y_range; s->val[OPT_TL_Y].w = y_range.min; s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].size = sizeof (SANE_Fixed); s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &x_range; s->val[OPT_BR_X].w = x_range.max; s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].size = sizeof (SANE_Fixed); s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &y_range; s->val[OPT_BR_Y].w = y_range.max; s->opt[OPT_BACKTRACK].name = SANE_NAME_BACKTRACK; s->opt[OPT_BACKTRACK].title = SANE_TITLE_BACKTRACK; s->opt[OPT_BACKTRACK].desc = SANE_DESC_BACKTRACK; s->opt[OPT_BACKTRACK].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_BACKTRACK].type = SANE_TYPE_BOOL; s->opt[OPT_BACKTRACK].size = sizeof (SANE_Bool); s->opt[OPT_BACKTRACK].unit = SANE_UNIT_NONE; s->opt[OPT_BACKTRACK].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_BACKTRACK].b = SANE_TRUE; s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].size = 1024 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = s->user_parms.gamma[0]; s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].size = 1024 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = s->user_parms.gamma[1]; s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].size = 1024 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = s->user_parms.gamma[2]; { int i; double gamma = 2.0; for (i = 0; i < 1024; i++) { s->user_parms.gamma[0][i] = 255 * pow (((double) i + 1) / 1024, 1.0 / gamma); s->user_parms.gamma[1][i] = s->user_parms.gamma[0][i]; s->user_parms.gamma[2][i] = s->user_parms.gamma[0][i]; #ifdef DEBUG printf ("%d %d\n", i, s->user_parms.gamma[0][i]); #endif } } /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].size = sizeof (SANE_Word); s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = SANE_FALSE; } SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h) { static const char me[] = "sane_hp4200_open"; SANE_Status status; HP4200_Device *dev; HP4200_Scanner *s; DBG (DBG_proc, "%s (%s, %p)\n", me, name, (void *) h); if (name && name[0]) { dev = find_device (name); if (!dev) { status = add_device (name, &dev); if (status != SANE_STATUS_GOOD) return status; } } else { dev = first_device; } if (!dev) return SANE_STATUS_INVAL; if (!h) return SANE_STATUS_INVAL; s = *h = (HP4200_Scanner *) calloc (1, sizeof (HP4200_Scanner)); if (!s) { DBG (DBG_error, "%s: out of memory creating scanner structure.\n", me); return SANE_STATUS_NO_MEM; } dev->handle = s; s->aborted_by_user = SANE_FALSE; s->ciclic_buffer.buffer = NULL; s->scanner_buffer.buffer = NULL; s->dev = dev; s->user_parms.image_width = 0; s->user_parms.lines_to_scan = 0; s->user_parms.vertical_resolution = 0; s->scanning = SANE_FALSE; s->fd = -1; init_options (s); if ((sanei_usb_open (dev->dev.name, &s->fd) != SANE_STATUS_GOOD)) { DBG (DBG_error, "%s: Can't open %s.\n", me, dev->dev.name); return SANE_STATUS_IO_ERROR; /* fixme: return busy when file is being accessed already */ } return SANE_STATUS_GOOD; } void sane_close (SANE_Handle h) { HP4200_Scanner *s = (HP4200_Scanner *) h; DBG (DBG_proc, "sane_hp4200_close (%p)\n", (void *) h); if (s) { s->dev->handle = NULL; if (s->fd != -1) { sanei_usb_close (s->fd); } free (s); } } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int n) { static char me[] = "sane_get_option_descriptor"; HP4200_Scanner *s = (HP4200_Scanner *) h; DBG (DBG_proc, "%s\n", me); if ((n < 0) || (n >= NUM_OPTIONS)) return NULL; return s->opt + n; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { HP4200_Scanner *s = (HP4200_Scanner *) handle; SANE_Status status; SANE_Int myinfo = 0; SANE_Word cap; DBG (DBG_proc, "sane_control_option\n"); if (info) *info = 0; if (s->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { case OPT_NUM_OPTS: case OPT_RES: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_PREVIEW: *(SANE_Word *) val = s->val[option].w; break; case OPT_BACKTRACK: *(SANE_Bool *) val = s->val[option].b; break; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); break; default: return SANE_STATUS_UNSUPPORTED; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, &myinfo); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* Numeric side-effect free options */ case OPT_PREVIEW: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* Numeric side-effect options */ case OPT_RES: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: myinfo |= SANE_INFO_RELOAD_PARAMS; s->val[option].w = *(SANE_Word *) val; break; case OPT_BACKTRACK: s->val[option].b = *(SANE_Bool *) val; break; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); break; default: return SANE_STATUS_UNSUPPORTED; } } else { return SANE_STATUS_UNSUPPORTED; } if (info) *info = myinfo; return SANE_STATUS_GOOD; } static void compute_parameters (HP4200_Scanner * s) { int resolution; int opt_tl_x; int opt_br_x; int opt_tl_y; int opt_br_y; if (s->val[OPT_PREVIEW].w == SANE_TRUE) { resolution = 50; opt_tl_x = SANE_UNFIX (x_range.min); opt_tl_y = SANE_UNFIX (y_range.min); opt_br_x = SANE_UNFIX (x_range.max); opt_br_y = SANE_UNFIX (y_range.max); } else { resolution = s->val[OPT_RES].w; opt_tl_x = SANE_UNFIX (s->val[OPT_TL_X].w); opt_tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w); opt_br_x = SANE_UNFIX (s->val[OPT_BR_X].w); opt_br_y = SANE_UNFIX (s->val[OPT_BR_Y].w); } s->user_parms.horizontal_resolution = resolution; s->user_parms.vertical_resolution = resolution; s->runtime_parms.steps_to_skip = floor (300.0 / MM_PER_INCH * opt_tl_y); s->user_parms.lines_to_scan = floor ((opt_br_y - opt_tl_y) / MM_PER_INCH * resolution); s->user_parms.image_width = floor ((opt_br_x - opt_tl_x) / MM_PER_INCH * resolution); s->runtime_parms.first_pixel = floor (opt_tl_x / MM_PER_INCH * resolution); /* fixme: add support for more depth's and bpp's. */ s->runtime_parms.image_line_size = s->user_parms.image_width * 3; } SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p) { static char me[] = "sane_get_parameters"; HP4200_Scanner *s = (HP4200_Scanner *) h; DBG (DBG_proc, "%s\n", me); if (!p) return SANE_STATUS_INVAL; p->format = SANE_FRAME_RGB; p->last_frame = SANE_TRUE; p->depth = 8; if (!s->scanning) { compute_parameters (s); } p->lines = s->user_parms.lines_to_scan; p->pixels_per_line = s->user_parms.image_width; p->bytes_per_line = s->runtime_parms.image_line_size; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle h) { HP4200_Scanner *s = (HP4200_Scanner *) h; struct coarse_t coarse; static char me[] = "sane_start"; DBG (DBG_proc, "%s\n", me); s->scanning = SANE_TRUE; s->aborted_by_user = SANE_FALSE; s->user_parms.color = SANE_TRUE; compute_parameters (s); hp4200_init_scanner (s); hp4200_goto_home (s); hp4200_wait_homed (s); /* restore default register values here... */ write_gamma (s); hp4200_init_registers (s); lm9830_ini_scanner (s->fd, NULL); /* um... do not call cache_write() here, don't know why :( */ do_coarse_calibration (s, &coarse); do_fine_calibration (s, &coarse); prepare_for_a_scan (s); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle h) { static char me[] = "sane_cancel"; HP4200_Scanner *s = (HP4200_Scanner *) h; DBG (DBG_proc, "%s\n", me); s->aborted_by_user = SANE_TRUE; end_scan (s); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { HP4200_Scanner *dev = handle; SANE_Status status; non_blocking = non_blocking; /* silence gcc */ if (dev->scanning == SANE_FALSE) { return SANE_STATUS_INVAL; } if (non_blocking == SANE_FALSE) { status = SANE_STATUS_GOOD; } else { status = SANE_STATUS_UNSUPPORTED; } DBG (DBG_proc, "sane_set_io_mode: exit\n"); return status; } SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fd) { static char me[] = "sane_get_select_fd"; h = h; /* keep gcc quiet */ fd = fd; /* keep gcc quiet */ DBG (DBG_proc, "%s\n", me); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/hp4200.h0000664000175000017500000001500012112021330013654 00000000000000/* Copyright (C) 2000 by Adrian Perez Jorge This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _HP4200_H #define _HP4200_H #include #define MCLKDIV_SCALING 2 #define NUM_REGISTERS 0x80 #define min(a, b) (((a) < (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b)) /*--------------------------------------------------------------------------*/ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /*--------------------------------------------------------------------------*/ enum HP4200_Option { OPT_NUM_OPTS = 0, OPT_RES, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_BACKTRACK, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_PREVIEW, NUM_OPTIONS /* must come last */ }; /* already declared in the sane includes... typedef union { SANE_Word w; SANE_Bool b; SANE_Fixed f; SANE_Word *wa; } Option_Value; */ enum ScannerModels { HP4200 }; typedef struct HP4200_Device { struct HP4200_Device *next; SANE_Device dev; SANE_Handle handle; } HP4200_Device; struct _scanner_buffer_t { unsigned char *buffer; /* buffer memory space */ int size; /* size of the buffer */ int num_bytes; /* number of bytes left (to read) */ unsigned char *data_ptr; /* cursor in buffer */ }; typedef struct _scanner_buffer_t scanner_buffer_t; struct _ciclic_buffer_t { int good_bytes; /* number of valid bytes of the image */ int num_lines; /* number of lines of the ciclic buffer */ int size; /* size in bytes of the buffer space */ unsigned char *buffer; /* pointer to the buffer space */ unsigned char **buffer_ptrs; /* pointers to the beginning of each line in the buffer space */ int can_consume; /* num of bytes the ciclic buf can consume */ int current_line; /* current scanned line */ int first_good_line; /* number of lines to fill the ``pipeline'' */ unsigned char *buffer_position; /* pointer to the first byte that can be copied */ int pixel_position; /* pixel position in current line */ /* color indexes for the proper line in the ciclic buffer */ int red_idx; int green_idx; int blue_idx; }; typedef struct _ciclic_buffer_t ciclic_buffer_t; struct _hardware_parameters_t { unsigned int SRAM_size; unsigned char SRAM_bandwidth; unsigned long crystal_frequency; unsigned int min_pixel_data_buffer_limit; unsigned int motor_full_steps_per_inch; float motor_max_speed; unsigned int scan_bar_max_speed; unsigned int start_of_scanning_area; unsigned int calibration_strip_height; unsigned int scan_area_width; double scan_area_length; /* in inches */ unsigned int sensor_num_pixels; unsigned int sensor_pixel_start; unsigned int sensor_pixel_end; int sensor_cds_state; /* 0 == off, 1 == on */ int sensor_signal_polarity; /* 0 == ??, 1 == ?? */ int sensor_max_integration_time; int sensor_line_separation; int sensor_type; unsigned int sensor_resolution; int sensor_control_signals_polarity; int sensor_control_signals_state; int sensor_control_pixel_rate_timing; int sensor_control_line_rate_timing; unsigned int sensor_black_clamp_timing; /* ??? */ unsigned int sensor_CIS_timing; int sensor_toshiba_timing; int sensor_color_modes; /* bitmask telling color modes supported */ int illumination_mode; int motor_control_mode; int motor_paper_sense_mode; int motor_pause_reverse_mode; int misc_io_mode; int num_tr_pulses; int guard_band_duration; int pulse_duration; int fsteps_25_speed; int fsteps_50_speed; int steps_to_reverse; struct { int red; int green; int blue; } target_value; unsigned short home_sensor; }; typedef struct _hardware_parameters_t hardware_parameters_t; struct _user_parameters_t { unsigned int image_width; unsigned int lines_to_scan; unsigned int horizontal_resolution; unsigned int vertical_resolution; int hres_reduction_method; /* interpolation/??? */ int vres_reduction_method; SANE_Bool color; /* color/grayscale */ int bpp; int scan_mode; /* preview/full scan */ SANE_Bool no_reverse; SANE_Word gamma[3][1024]; /* gamma table for rgb */ }; typedef struct _user_parameters_t user_parameters_t; struct _measured_parameters_t { unsigned int datalink_bandwidth; struct { int red; int green; int blue; } coarse_calibration_data; struct { int *pRedOffset; int *pGreenOffset; int *pBlueOffset; int *pRedGain; int *pGreenGain; int *pBlueGain; } fine_calibration_data; int max_integration_time; int color_mode; }; typedef struct _measured_parameters_t measured_parameters_t; struct _runtime_parameters_t { long num_bytes_left_to_scan; int status_bytes; /* number of status bytes per line */ int image_line_size; /* line size in bytes without status bytes */ int scanner_line_size; /* line size in bytes including the status bytes */ int first_pixel; /* first pixel in the line to be scanned */ int steps_to_skip; }; typedef struct _runtime_parameters_t runtime_parameters_t; struct _HP4200_Scanner { struct _HP4200_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Bool scanning; SANE_Bool aborted_by_user; SANE_Parameters params; HP4200_Device *dev; hardware_parameters_t hw_parms; user_parameters_t user_parms; measured_parameters_t msrd_parms; unsigned int regs[NUM_REGISTERS]; int mclk; float mclk_div; int fd; ciclic_buffer_t ciclic_buffer; scanner_buffer_t scanner_buffer; runtime_parameters_t runtime_parms; }; typedef struct _HP4200_Scanner HP4200_Scanner; #endif /* !_HP4200_H */ sane-backends-1.0.27/backend/pint.c0000664000175000017500000006222712112021330013721 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Gordon Matzigkeit Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include extern int errno; #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include #include #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define PINT_CONFIG_FILE "pint.conf" #include "pint.h" #define DECIPOINTS_PER_MM (720.0 / MM_PER_INCH) #define TWELVEHUNDS_PER_MM (1200.0 / MM_PER_INCH) static int num_devices; static PINT_Device *first_dev; static PINT_Scanner *first_handle; /* A zero-terminated list of valid scanner modes. */ static SANE_String_Const mode_list[8]; static const SANE_Range s7_range = { -127, /* minimum */ 127, /* maximum */ 1 /* quantization */ }; static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status attach (const char *devname, PINT_Device **devp) { int fd; long lastguess, inc; PINT_Device *dev; struct scan_io scanio; for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } DBG(3, "attach: opening %s\n", devname); fd = open (devname, O_RDONLY, 0); if (fd < 0) { DBG(1, "attach: open failed (%s)\n", strerror (errno)); return SANE_STATUS_INVAL; } DBG(3, "attach: sending SCIOCGET\n"); if (ioctl (fd, SCIOCGET, &scanio) < 0) { DBG(1, "attach: get status failed (%s)\n", strerror (errno)); close (fd); return SANE_STATUS_INVAL; } dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset(dev, 0, sizeof (*dev)); /* Copy the original scanner state to the device structure. */ memcpy (&dev->scanio, &scanio, sizeof (dev->scanio)); /* FIXME: PINT currently has no good way to determine maxima and minima. So, do binary searches to find out what limits the driver has. */ /* Assume that minimum range of x and y is 0. */ dev->x_range.min = SANE_FIX (0); dev->y_range.min = SANE_FIX (0); dev->x_range.quant = 0; dev->y_range.quant = 0; /* x range */ inc = 8.5 * 1200; /* Converge on the maximum scan width. */ while ((inc /= 2) != 0) { /* Move towards the extremum until we overflow. */ do { lastguess = scanio.scan_width; scanio.scan_width += inc; } while (ioctl (fd, SCIOCSET, &scanio) >= 0); /* Pick the last valid guess, divide by two, and try again. */ scanio.scan_width = lastguess; } dev->x_range.max = SANE_FIX (scanio.scan_width / TWELVEHUNDS_PER_MM); /* y range */ inc = 11 * 1200; while ((inc /= 2) != 0) { do { lastguess = scanio.scan_height; scanio.scan_height += inc; } while (ioctl (fd, SCIOCSET, &scanio) >= 0); scanio.scan_height = lastguess; } dev->y_range.max = SANE_FIX (scanio.scan_height / TWELVEHUNDS_PER_MM); /* Converge on the minimum scan resolution. */ dev->dpi_range.quant = 1; if (scanio.scan_x_resolution > scanio.scan_y_resolution) scanio.scan_x_resolution = scanio.scan_y_resolution; else scanio.scan_y_resolution = scanio.scan_x_resolution; inc = -scanio.scan_x_resolution; while ((inc /= 2) != 0) { do { lastguess = scanio.scan_x_resolution; scanio.scan_x_resolution = scanio.scan_y_resolution += inc; } while (ioctl (fd, SCIOCSET, &scanio) >= 0); scanio.scan_x_resolution = scanio.scan_y_resolution = lastguess; } dev->dpi_range.min = scanio.scan_x_resolution; /* Converge on the maximum scan resolution. */ inc = 600; while ((inc /= 2) != 0) { do { lastguess = scanio.scan_x_resolution; scanio.scan_x_resolution = scanio.scan_y_resolution += inc; } while (ioctl (fd, SCIOCSET, &scanio) >= 0); scanio.scan_x_resolution = scanio.scan_y_resolution = lastguess; } dev->dpi_range.max = scanio.scan_x_resolution; /* Determine the valid scan modes for mode_list. */ lastguess = 0; #define CHECK_MODE(flag,modename) \ scanio.scan_image_mode = flag; \ if (ioctl (fd, SCIOCSET, &scanio) >= 0) \ mode_list[lastguess ++] = modename CHECK_MODE(SIM_BINARY_MONOCHROME, SANE_VALUE_SCAN_MODE_LINEART); CHECK_MODE(SIM_DITHERED_MONOCHROME, SANE_VALUE_SCAN_MODE_HALFTONE); CHECK_MODE(SIM_GRAYSCALE, SANE_VALUE_SCAN_MODE_GRAY); CHECK_MODE(SIM_COLOR, SANE_VALUE_SCAN_MODE_COLOR); CHECK_MODE(SIM_RED, "Red"); CHECK_MODE(SIM_GREEN, "Green"); CHECK_MODE(SIM_BLUE, "Blue"); #undef CHECK_MODE /* Zero-terminate the list of modes. */ mode_list[lastguess] = 0; /* Restore the scanner state. */ if (ioctl (fd, SCIOCSET, &dev->scanio)) DBG (2, "cannot reset original scanner state: %s\n", strerror (errno)); close (fd); dev->sane.name = strdup (devname); /* Determine vendor. */ switch (scanio.scan_scanner_type) { case EPSON_ES300C: dev->sane.vendor = "Epson"; break; case FUJITSU_M3096G: dev->sane.vendor = "Fujitsu"; break; case HP_SCANJET_IIC: dev->sane.vendor = "HP"; break; case IBM_2456: dev->sane.vendor = "IBM"; break; case MUSTEK_06000CX: case MUSTEK_12000CX: dev->sane.vendor = "Mustek"; break; case RICOH_FS1: case RICOH_IS410: case RICOH_IS50: dev->sane.vendor = "Ricoh"; break; case SHARP_JX600: dev->sane.vendor = "Sharp"; break; case UMAX_UC630: case UMAX_UG630: dev->sane.vendor = "UMAX"; break; default: dev->sane.vendor = "PINT"; } /* Determine model. */ switch (scanio.scan_scanner_type) { case EPSON_ES300C: dev->sane.vendor = "Epson"; break; case FUJITSU_M3096G: dev->sane.model = "M3096G"; break; case HP_SCANJET_IIC: dev->sane.model = "ScanJet IIc"; break; case IBM_2456: dev->sane.vendor = "IBM"; break; case MUSTEK_06000CX: case MUSTEK_12000CX: dev->sane.vendor = "Mustek"; break; case RICOH_FS1: dev->sane.model = "FS1"; break; case RICOH_IS410: dev->sane.model = "IS-410"; break; case RICOH_IS50: dev->sane.vendor = "Ricoh"; break; case SHARP_JX600: dev->sane.vendor = "Sharp"; break; case UMAX_UC630: case UMAX_UG630: dev->sane.vendor = "UMAX"; break; default: dev->sane.model = "unknown"; } /* Determine the scanner type. */ switch (scanio.scan_scanner_type) { case HP_SCANJET_IIC: dev->sane.type = "flatbed scanner"; /* FIXME: which of these are flatbed or handhelds? */ case EPSON_ES300C: case FUJITSU_M3096G: case IBM_2456: case MUSTEK_06000CX: case MUSTEK_12000CX: case RICOH_FS1: case RICOH_IS410: case RICOH_IS50: case SHARP_JX600: case UMAX_UC630: case UMAX_UG630: default: dev->sane.type = "generic scanner"; } DBG(1, "attach: found %s %s, x=%g-%gmm, y=%g-%gmm, " "resolution=%d-%ddpi\n", dev->sane.vendor, dev->sane.model, SANE_UNFIX (dev->x_range.min), SANE_UNFIX (dev->x_range.max), SANE_UNFIX (dev->y_range.min), SANE_UNFIX (dev->y_range.max), dev->dpi_range.min, dev->dpi_range.max); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static SANE_Status init_options (PINT_Scanner *s) { int i; int x0, x1, y0, y1; memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; /* Translate the current PINT mode into a string. */ switch (s->hw->scanio.scan_image_mode) { case SIM_BINARY_MONOCHROME: s->val[OPT_MODE].s = strdup (mode_list[0]); break; case SIM_DITHERED_MONOCHROME: s->val[OPT_MODE].s = strdup (mode_list[1]); break; case SIM_COLOR: s->val[OPT_MODE].s = strdup (mode_list[3]); break; case SIM_RED: s->val[OPT_MODE].s = strdup (mode_list[4]); break; case SIM_GREEN: s->val[OPT_MODE].s = strdup (mode_list[5]); break; case SIM_BLUE: s->val[OPT_MODE].s = strdup (mode_list[6]); break; case SIM_GRAYSCALE: default: s->val[OPT_MODE].s = strdup (mode_list[2]); } /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = (s->hw->scanio.scan_x_resolution > s->hw->scanio.scan_y_resolution) ? s->hw->scanio.scan_x_resolution : s->hw->scanio.scan_y_resolution; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Calculate the x and y millimetre coordinates from the scanio. */ x0 = SANE_FIX (s->hw->scanio.scan_x_origin / TWELVEHUNDS_PER_MM); y0 = SANE_FIX (s->hw->scanio.scan_y_origin / TWELVEHUNDS_PER_MM); x1 = SANE_FIX ((s->hw->scanio.scan_x_origin + s->hw->scanio.scan_width) / TWELVEHUNDS_PER_MM); y1 = SANE_FIX ((s->hw->scanio.scan_y_origin + s->hw->scanio.scan_height) / TWELVEHUNDS_PER_MM); /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = x0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = y0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = x1; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = y1; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &s7_range; s->val[OPT_BRIGHTNESS].w = s->hw->scanio.scan_brightness - 128; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &s7_range; s->val[OPT_CONTRAST].w = s->hw->scanio.scan_contrast - 128; return SANE_STATUS_GOOD; } static SANE_Status do_cancel (PINT_Scanner *s) { /* FIXME: PINT doesn't have any good way to cancel ScanJets right now. */ #define gobble_up_buf_len 1024 char buf[gobble_up_buf_len]; /* Send the restart code. */ buf[0] = ioctl (s->fd, SCIOCRESTART, 0); if (!s->scanning) return SANE_STATUS_CANCELLED; s->scanning = SANE_FALSE; /* Read to the end of the file. */ while (read (s->fd, buf, gobble_up_buf_len) > 0) ; #undef gobble_up_buf_len /* Finally, close the file descriptor. */ if (s->fd >= 0) { close (s->fd); s->fd = -1; } return SANE_STATUS_CANCELLED; } SANE_Status sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; DBG_INIT(); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (PINT_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ attach (dev_name, 0); } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { PINT_Device *dev, *next; for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free (dev); } } SANE_Status sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) { static const SANE_Device **devlist = 0; PINT_Device *dev; int i; if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle *handle) { SANE_Status status; PINT_Device *dev; PINT_Scanner *s; if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } } else /* empty devicename -> use first device */ dev = first_dev; if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->hw = dev; s->fd = -1; init_options (s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { PINT_Scanner *prev, *s; /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG(1, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (s->scanning) do_cancel (handle); if (prev) prev->next = s->next; else first_handle = s->next; free (handle); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { PINT_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int *info) { PINT_Scanner *s = handle; SANE_Status status; SANE_Word cap; if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; } } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) { PINT_Scanner *s = handle; struct scan_io scanio; if (!s->scanning) { u_long x0, y0, width, height; const char *mode; /* Grab the scanio for this device. */ if (s->fd < 0) { s->fd = open (s->hw->sane.name, O_RDONLY, 0); if (s->fd < 0) { DBG(1, "open of %s failed: %s\n", s->hw->sane.name, strerror (errno)); return SANE_STATUS_INVAL; } } if (ioctl (s->fd, SCIOCGET, &scanio) < 0) { DBG(1, "getting scanner state failed: %s", strerror (errno)); return SANE_STATUS_INVAL; } memset (&s->params, 0, sizeof (s->params)); /* FIXME: there is some lossage here: the parameters change due to roundoff errors between converting to fixed point millimetres and back. */ x0 = SANE_UNFIX (s->val[OPT_TL_X].w * TWELVEHUNDS_PER_MM); y0 = SANE_UNFIX (s->val[OPT_TL_Y].w * TWELVEHUNDS_PER_MM); width = SANE_UNFIX ((s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * TWELVEHUNDS_PER_MM); height = SANE_UNFIX ((s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) * TWELVEHUNDS_PER_MM); /* x and y dpi: */ scanio.scan_x_resolution = s->val[OPT_RESOLUTION].w; scanio.scan_y_resolution = s->val[OPT_RESOLUTION].w; /* set scan extents, in 1/1200'ths of an inch */ scanio.scan_x_origin = x0; scanio.scan_y_origin = y0; scanio.scan_width = width; scanio.scan_height = height; /* brightness and contrast */ scanio.scan_brightness = s->val[OPT_BRIGHTNESS].w + 128; scanio.scan_contrast = s->val[OPT_CONTRAST].w + 128; /* set the scan image mode */ mode = s->val[OPT_MODE].s; if (!strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART)) { s->params.format = SANE_FRAME_GRAY; scanio.scan_image_mode = SIM_BINARY_MONOCHROME; } else if (!strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE)) { s->params.format = SANE_FRAME_GRAY; scanio.scan_image_mode = SIM_DITHERED_MONOCHROME; } else if (!strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY)) { s->params.format = SANE_FRAME_GRAY; scanio.scan_image_mode = SIM_GRAYSCALE; } else if (!strcmp (mode, "Red")) { s->params.format = SANE_FRAME_RED; scanio.scan_image_mode = SIM_RED; } else if (!strcmp (mode, "Green")) { s->params.format = SANE_FRAME_GREEN; scanio.scan_image_mode = SIM_GREEN; } else if (!strcmp (mode, "Blue")) { s->params.format = SANE_FRAME_BLUE; scanio.scan_image_mode = SIM_BLUE; } else { s->params.format = SANE_FRAME_RGB; scanio.scan_image_mode = SIM_COLOR; } /* inquire resulting size of image after setting it up */ if (ioctl (s->fd, SCIOCSET, &scanio) < 0) { DBG(1, "setting scan parameters failed: %s", strerror (errno)); return SANE_STATUS_INVAL; } if (ioctl (s->fd, SCIOCGET, &scanio) < 0) { DBG(1, "getting scan parameters failed: %s", strerror (errno)); return SANE_STATUS_INVAL; } /* Save all the PINT-computed values. */ s->params.pixels_per_line = scanio.scan_pixels_per_line; s->params.bytes_per_line = (scanio.scan_bits_per_pixel * scanio.scan_pixels_per_line + 7) / 8; s->params.lines = scanio.scan_lines; s->params.depth = (scanio.scan_image_mode == SIM_COLOR) ? scanio.scan_bits_per_pixel / 3 : scanio.scan_bits_per_pixel; /* FIXME: this will need to be different for hand scanners. */ s->params.last_frame = SANE_TRUE; } if (params) *params = s->params; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { PINT_Scanner *s = handle; SANE_Status status; /* First make sure we have a current parameter set. This call actually uses the PINT driver to do the calculations, so we trust its results. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; DBG(1, "%d pixels per line, %d bytes, %d lines high, dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, s->val[OPT_RESOLUTION].w); /* The scan is triggered in sane_read. */ s->scanning = SANE_TRUE; return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { PINT_Scanner *s = handle; ssize_t nread; *len = 0; if (!s->scanning) return do_cancel (s); /* Verrry simple. Just suck up all the data PINT passes to us. */ nread = read (s->fd, buf, max_len); if (nread <= 0) { do_cancel (s); return (nread == 0) ? SANE_STATUS_EOF : SANE_STATUS_IO_ERROR; } *len = nread; return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { PINT_Scanner *s = handle; do_cancel (s); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int *fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/qcam.c0000664000175000017500000016205012112021330013663 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Connectix QuickCam. At present, only the color camera is supported though the driver should be able to easily accommodate black and white cameras. Portions of this code are derived from Scott Laird's qcam driver. It's copyright notice is reproduced here: Copyright (C) 1996 by Scott Laird Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef _AIX # include "lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "lalloca.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME qcam #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define QCAM_CONFIG_FILE "qcam.conf" #include "qcam.h" /* status bits */ #define NeedRamTable (1 << 1) #define BlackBalanceInProgress (1 << 6) #define CameraNotReady (1 << 7) /* lpdata bits: */ #define Cmd0_7 0xff #define CamRdy2 ( 1 << 0) /* byte mode */ #define Data0_6 (0x7f << 1) /* byte mode */ /* lpstatus bits: */ #define CamRdy1 ( 1 << 3) /* nibble mode */ #define Nibble0_3 (0x0f << 4) /* nibble mode */ #define Data7_11 (0x1f << 3) /* byte mode */ /* lpcontrol bits: */ #define Strobe ( 1 << 0) /* unused */ #define Autofeed ( 1 << 1) #define Reset_N ( 1 << 2) #define PCAck ( 1 << 3) #define BiDir ( 1 << 5) static int num_devices; static QC_Device *first_dev; static QC_Scanner *first_handle; static const SANE_String_Const resolution_list[] = { "Low", /* million-mode */ "High", /* billion-mode */ 0 }; static const SANE_Int mono_depth_list[] = { 2, /* # of elements */ 4, 6 }; static const SANE_Int color_depth_list[] = { /*2 */ 1, /* # of elements */ /*16, */ 24 /* "thousand" mode not implemented yet */ }; static const SANE_Int xfer_scale_list[] = { 3, /* # of elements */ 1, 2, 4 }; static const SANE_Range u8_range = { /* min, max, quantization */ 0, 255, 0 }; static const SANE_Range brightness_range = { /* min, max, quantization */ 0, 254, 0 /* 255 is bulb mode! */ }; static const SANE_Range x_range[] = { /* min, max, quantization */ {0, 338, 2}, /* million mode */ {0, 676, 4}, /* billion mode */ }; static const SANE_Range odd_x_range[] = { /* min, max, quantization */ {1, 339, 2}, /* million mode */ {3, 683, 4}, /* billion mode */ }; static const SANE_Range y_range[] = { /* min, max, quantization */ {0, 249, 1}, /* million mode */ {0, 498, 2}, /* billion mode */ }; static const SANE_Range odd_y_range[] = { /* min, max, quantization */ {0, 249, 1}, /* million mode */ {1, 499, 2}, /* billion mode */ }; static const SANE_Range bw_x_range = { 0, 334, 2 }; static const SANE_Range odd_bw_x_range = { 1, 335, 2 }; static const SANE_Range bw_y_range = { 0, 241, 1 }; static const SANE_Range odd_bw_y_range = { 1, 242, 1 }; #if defined(HAVE_SYS_IO_H) || defined(HAVE_ASM_IO_H) || defined (HAVE_SYS_HW_H) #ifdef HAVE_SYS_IO_H # include /* GNU libc based OS */ #elif HAVE_ASM_IO_H # include /* older Linux */ #elif HAVE_SYS_HW_H # include /* OS/2 */ #endif #endif /* || || */ #define read_lpdata(d) inb ((d)->port) #define read_lpstatus(d) inb ((d)->port + 1) #define read_lpcontrol(d) inb ((d)->port + 2) #define write_lpdata(d,v) outb ((v), (d)->port) #define write_lpcontrol(d,v) outb ((v), (d)->port + 2) static SANE_Status enable_ports (QC_Device * q) { /* better safe than sorry */ if (q->port < 0x278 || q->port > 0x3bc) return SANE_STATUS_INVAL; if (ioperm (q->port, 3, 1) < 0) return SANE_STATUS_INVAL; return SANE_STATUS_GOOD; } static SANE_Status disable_ports (QC_Device * q) { if (ioperm (q->port, 3, 0) < 0) return SANE_STATUS_INVAL; return SANE_STATUS_GOOD; } /* We need a short delay loop -- somthing well under a millisecond. Unfortunately, adding 2 usleep(1)'s to qc_command slowed it down by a factor of over 1000 over the same loop with 2 usleep(0)'s, and that's too slow -- qc_start was taking over a second to run. This seems to help, but if anyone has a good speed-independent pause routine, please tell me. -- Scott If you're worried about hogging the CPU: don't worry, the qcam interface leaves you no choice, so this doesn't make the situation any worse... */ static int qc_wait (QC_Device * q) { return read_lpstatus (q); } /* This function uses POSIX fcntl-style locking on a file created in the /tmp directory. Because it uses the Unix record locking facility, locks are relinquished automatically on process termination, so "dead locks" are not a problem. (FYI, the lock file will remain after process termination, but this is actually desired so that the next process need not re-creat(2)e it... just lock it.) The wait argument indicates whether or not this funciton should "block" waiting for the previous lock to be relinquished. This is ideal so that multiple processes (eg. qcam) taking "snapshots" can peacefully coexist. -- Dave Plonka (plonka@carroll1.cc.edu) */ static SANE_Status qc_lock_wait (QC_Device * q, int wait) { #ifdef F_SETLK #ifndef HAVE_STRUCT_FLOCK struct flock { off_t l_start; off_t l_len; pid_t l_pid; short l_type; short l_whence; }; #endif /* !HAVE_STRUCT_FLOCK */ struct flock sfl; #endif DBG (3, "qc_lock_wait: acquiring lock for 0x%x\n", q->port); #ifdef F_SETLK memset (&sfl, 0, sizeof (sfl)); #endif if (q->lock_fd < 0) { char lockfile[128]; sprintf (lockfile, "/tmp/LOCK.qcam.0x%x", q->port); q->lock_fd = open (lockfile, O_WRONLY | O_CREAT | O_EXCL, 0666); if (q->lock_fd < 0) { DBG (1, "qc_lock_wait: failed to open %s (%s)\n", lockfile, strerror (errno)); return SANE_STATUS_INVAL; } } #ifdef F_SETLK sfl.l_type = F_WRLCK; if (fcntl (q->lock_fd, wait ? F_SETLKW : F_SETLK, &sfl) != 0) { DBG (1, "qc_lock_wait: failed to acquire lock (%s)\n", strerror (errno)); return SANE_STATUS_INVAL; } #endif DBG (3, "qc_lock_wait: got lock for 0x%x\n", q->port); return SANE_STATUS_GOOD; } static SANE_Status qc_unlock (QC_Device * q) { SANE_Status status; char lockfile[128]; #ifdef F_SETLK #ifndef HAVE_STRUCT_FLOCK struct flock { off_t l_start; off_t l_len; pid_t l_pid; short l_type; short l_whence; }; #endif /* !HAVE_STRUCT_FLOCK */ struct flock sfl; #endif DBG (3, "qc_unlock: releasing lock for 0x%x\n", q->port); #ifdef F_SETLK memset (&sfl, 0, sizeof (sfl)); #endif if (q->lock_fd < 0) { DBG (3, "qc_unlock; port was not locked\n"); return SANE_STATUS_INVAL; } /* clear the exclusive lock */ #ifdef F_SETLK sfl.l_type = F_UNLCK; if (fcntl (q->lock_fd, F_SETLK, &sfl) != 0) { DBG (3, "qc_unlock: failed to release lock (%s)\n", strerror (errno)); return SANE_STATUS_INVAL; } #endif sprintf (lockfile, "/tmp/LOCK.qcam.0x%x", q->port); DBG (1, "qc_unlock: /tmp/LOCK.qcam.0x%x\n", q->port); unlink (lockfile); close (q->lock_fd); q->lock_fd = -1; DBG (1, "qc_unlock: exit\n"); status = SANE_STATUS_GOOD; return status; } static SANE_Status qc_lock (QC_Device * q) { return qc_lock_wait (q, 1); } /* Busy-waits for a handshake signal from the QuickCam. Almost all communication with the camera requires handshaking. This is why qcam is a CPU hog. */ static int qc_waithand (QC_Device * q, int val) { int status; while (((status = read_lpstatus (q)) & CamRdy1) != val); return status; } /* This is used when the qcam is in bidirectional ("byte") mode, and the handshaking signal is CamRdy2 (bit 0 of data reg) instead of CamRdy1 (bit 3 of status register). It also returns the last value read, since this data is useful. */ static unsigned int qc_waithand2 (QC_Device * q, int val) { unsigned int status; do { status = read_lpdata (q); } while ((status & CamRdy2) != (unsigned int) val); return status; } static unsigned int qc_send (QC_Device * q, unsigned int byte) { unsigned int echo; int n1, n2; write_lpdata (q, byte); qc_wait (q); write_lpcontrol (q, Autofeed | Reset_N); qc_wait (q); n1 = qc_waithand (q, CamRdy1); write_lpcontrol (q, Autofeed | Reset_N | PCAck); qc_wait (q); n2 = qc_waithand (q, 0); echo = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); #ifndef NDEBUG if (echo != byte) { DBG (1, "qc_send: sent 0x%02x, camera echoed 0x%02x\n", byte, echo); n2 = read_lpstatus (q); echo = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); if (echo != byte) DBG (1, "qc_send: (re-read does not help)\n"); else DBG (1, "qc_send: (fixed on re-read)\n"); } #endif return echo; } static int qc_readparam (QC_Device * q) { int n1, n2; int cmd; write_lpcontrol (q, Autofeed | Reset_N); /* clear PCAck */ n1 = qc_waithand (q, CamRdy1); write_lpcontrol (q, Autofeed | Reset_N | PCAck); /* set PCAck */ n2 = qc_waithand (q, 0); cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); return cmd; } static unsigned int qc_getstatus (QC_Device * q) { unsigned int status; qc_send (q, QC_SEND_STATUS); status = qc_readparam (q); DBG (3, "qc_getstatus: status=0x%02x\n", status); return status; } static void qc_setscanmode (QC_Scanner * s, u_int * modep) { QC_Device *q = s->hw; u_int mode = 0; if (q->version != QC_COLOR) { switch (s->val[OPT_XFER_SCALE].w) { case 1: mode = 0; break; case 2: mode = 4; break; case 4: mode = 8; break; } switch (s->val[OPT_DEPTH].w) { case 4: break; case 6: mode += 2; break; } } else { switch (s->val[OPT_XFER_SCALE].w) { case 1: mode = 0; break; case 2: mode = 2; break; case 4: mode = 4; break; } if (s->resolution == QC_RES_LOW) mode |= 0x18; /* millions mode */ else mode |= 0x10; /* billions mode */ } if (s->val[OPT_TEST].w) mode |= 0x40; /* test mode */ if (q->port_mode == QC_BIDIR) mode |= 1; DBG (2, "scanmode (before increment): 0x%x\n", mode); if (q->version == QC_COLOR) ++mode; *modep = mode; } /* Read data bytes from the camera. The number of bytes read is returned as the function result. Depending on the mode, it may be either 1, 3 or 6. On failure, 0 is returned. If buffer is 0, the internal state-machine is reset. */ static size_t qc_readbytes (QC_Scanner * s, unsigned char buffer[]) { QC_Device *q = s->hw; unsigned int hi, lo; unsigned int hi2, lo2; size_t bytes = 0; if (!buffer) { s->readbytes_state = 0; return 0; } switch (q->port_mode) { case QC_BIDIR: /* bi-directional port */ /* read off 24 bits: */ write_lpcontrol (q, Autofeed | Reset_N | BiDir); lo = qc_waithand2 (q, 1) >> 1; hi = (read_lpstatus (q) >> 3) & 0x1f; write_lpcontrol (q, Autofeed | Reset_N | PCAck | BiDir); lo2 = qc_waithand2 (q, 0) >> 1; hi2 = (read_lpstatus (q) >> 3) & 0x1f; if (q->version == QC_COLOR) { /* is Nibble3 inverted for color quickcams only? */ hi ^= 0x10; hi2 ^= 0x10; } switch (s->val[OPT_DEPTH].w) { case 4: buffer[0] = lo & 0xf; buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3); buffer[2] = (hi & 0x1e) >> 1; buffer[3] = lo2 & 0xf; buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3); buffer[5] = (hi2 & 0x1e) >> 1; bytes = 6; break; case 6: buffer[0] = lo & 0x3f; buffer[1] = ((lo & 0x40) >> 6) | (hi << 1); buffer[2] = lo2 & 0x3f; buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1); bytes = 4; break; case 24: buffer[0] = lo | ((hi & 0x1) << 7); buffer[1] = ((hi2 & 0x1e) >> 1) | ((hi & 0x1e) << 3); buffer[2] = lo2 | ((hi2 & 0x1) << 7); bytes = 3; break; } break; case QC_UNIDIR: /* Unidirectional Port */ write_lpcontrol (q, Autofeed | Reset_N); lo = (qc_waithand (q, CamRdy1) & 0xf0) >> 4; write_lpcontrol (q, Autofeed | Reset_N | PCAck); hi = (qc_waithand (q, 0) & 0xf0) >> 4; if (q->version == QC_COLOR) { /* invert Nibble3 */ hi ^= 8; lo ^= 8; } switch (s->val[OPT_DEPTH].w) { case 4: buffer[0] = lo; buffer[1] = hi; bytes = 2; break; case 6: switch (s->readbytes_state) { case 0: buffer[0] = (lo << 2) | ((hi & 0xc) >> 2); s->saved_bits = (hi & 3) << 4; s->readbytes_state = 1; bytes = 1; break; case 1: buffer[0] = lo | s->saved_bits; s->saved_bits = hi << 2; s->readbytes_state = 2; bytes = 1; break; case 2: buffer[0] = ((lo & 0xc) >> 2) | s->saved_bits; buffer[1] = ((lo & 3) << 4) | hi; s->readbytes_state = 0; bytes = 2; break; default: DBG (1, "qc_readbytes: bad unidir 6-bit stat %d\n", s->readbytes_state); break; } break; case 24: buffer[0] = (lo << 4) | hi; bytes = 1; break; default: DBG (1, "qc_readbytes: bad unidir bit depth %d\n", s->val[OPT_DEPTH].w); break; } break; default: DBG (1, "qc_readbytes: bad port_mode %d\n", q->port_mode); break; } return bytes; } static void qc_reset (QC_Device * q) { write_lpcontrol (q, Strobe | Autofeed | Reset_N | PCAck); qc_wait (q); write_lpcontrol (q, Strobe | Autofeed | PCAck); qc_wait (q); write_lpcontrol (q, Strobe | Autofeed | Reset_N | PCAck); } /* This function is executed as a child process. The reason this is executed as a subprocess is because the qcam interface directly reads off of a I/O port (rather than a filedescriptor). Thus, to have something to select() on, we transfer the data through a pipe. WARNING: Since this is executed as a subprocess, it's NOT possible to update any of the variables in the main process (in particular the scanner state cannot be updated). */ static jmp_buf env; static void sighandler (int signal) { DBG (3, "sighandler: got signal %d\n", signal); longjmp (env, 1); } /* Original despeckling code by Patrick Reynolds */ static void despeckle (int width, int height, SANE_Byte * in, SANE_Byte * out) { long x, i; /* The light-check threshold. Higher numbers remove more lights but blur the image more. 30 is good for indoor lighting. */ # define NO_LIGHTS 30 /* macros to make the code a little more readable, p=previous, n=next */ # define R in[i*3] # define G in[i*3+1] # define B in[i*3+2] # define pR in[i*3-3] # define pG in[i*3-2] # define pB in[i*3-1] # define nR in[i*3+3] # define nG in[i*3+4] # define nB in[i*3+5] DBG (1, "despeckle: width=%d, height=%d\n", width, height); for (x = i = 0; i < width * height; ++i) { if (x == 0 || x == width - 1) memcpy (&out[i * 3], &in[i * 3], 3); else { if (R - (G + B) / 2 > NO_LIGHTS + ((pR - (pG + pB) / 2) + (nR - (nG + nB) / 2))) out[i * 3] = (pR + nR) / 2; else out[i * 3] = R; if (G - (R + B) / 2 > NO_LIGHTS + ((pG - (pR + pB) / 2) + (nG - (nR + nB) / 2))) out[i * 3 + 1] = (pG + nG) / 2; else out[i * 3 + 1] = G; if (B - (G + R) / 2 > NO_LIGHTS + ((pB - (pG + pR) / 2) + (nB - (nG + nR) / 2))) out[i * 3 + 2] = (pB + nB) / 2; else out[i * 3 + 2] = B; } if (++x >= width) x = 0; } # undef R # undef G # undef B # undef pR # undef pG # undef pB # undef nR # undef nG # undef nB } static void despeckle32 (int width, int height, SANE_Byte * in, SANE_Byte * out) { long x, i; /* macros to make the code a little more readable, p=previous, n=next */ # define B in[i*4] # define Ga in[i*4 + 1] # define Gb in[i*4 + 1] /* ignore Gb and use Ga instead---Gb is weird */ # define R in[i*4 + 3] # define pB in[i*4 - 4] # define pGa in[i*4 - 3] # define pGb in[i*4 - 1] /* ignore Gb and use Ga instead---Gb is weird */ # define pR in[i*4 - 1] # define nB in[i*4 + 4] # define nGa in[i*4 + 5] # define nGb in[i*4 + 5] /* ignore Gb and use Ga instead---Gb is weird */ # define nR in[i*4 + 7] DBG (1, "despeckle32: width=%d, height=%d\n", width, height); for (x = i = 0; i < width * height; ++i) { if (x == 0 || x == width - 1) memcpy (&out[i * 4], &in[i * 4], 4); else { if (x >= width - 2) /* the last red pixel seems to be black at all times, use R instead: */ nR = R; if (R - ((Ga + Gb) / 2 + B) / 2 > NO_LIGHTS + ((pR - ((pGa + pGb) / 2 + pB) / 2) + (nR - ((nGa + nGb) / 2 + nB) / 2))) out[i * 4 + 3] = (pR + nR) / 2; else out[i * 4 + 3] = R; if (Ga - (R + B) / 2 > NO_LIGHTS + ((pGa - (pR + pB) / 2) + (nGa - (nR + nB) / 2))) out[i * 4 + 1] = (pGa + nGa) / 2; else out[i * 4 + 1] = Ga; if (Gb - (R + B) / 2 > NO_LIGHTS + ((pGb - (pR + pB) / 2) + (nGb - (nR + nB) / 2))) out[i * 4 + 2] = (pGb + nGb) / 2; else out[i * 4 + 2] = Gb; if (B - ((Ga + Gb) / 2 + R) / 2 > NO_LIGHTS + ((pB - ((pGa + pGb) / 2 + pR) / 2) + (nB - ((nGa + nGb) / 2 + nR) / 2))) out[i * 4 + 0] = (pB + nB) / 2; else out[i * 4 + 0] = B; } if (++x >= width) x = 0; } # undef R # undef Ga # undef Gb # undef B # undef pR # undef pGa # undef pGb # undef pB # undef nR # undef nGa # undef nGb # undef nB } static int reader_process (QC_Scanner * s, int in_fd, int out_fd) { static SANE_Byte *buffer = 0, *extra = 0; static size_t buffer_size = 0; size_t count, len, num_bytes; QC_Device *q = s->hw; QC_Scan_Request req; int width, height; SANE_Byte *src; FILE *ofp; DBG (5, "reader_process: enter\n"); enable_ports (q); ofp = fdopen (out_fd, "w"); if (!ofp) return 1; while (1) { if (setjmp (env)) { char ch; /* acknowledge the signal: */ DBG (1, "reader_process: sending signal ACK\n"); fwrite (&ch, 1, 1, ofp); fflush (ofp); /* force everything out the pipe */ continue; } signal (SIGINT, sighandler); /* the main process gets us started by writing a size_t giving the number of bytes we should expect: */ if (read (in_fd, &req, sizeof (req)) != sizeof (req)) { perror ("read"); return 1; } num_bytes = req.num_bytes; DBG (3, "reader_process: got request for %lu bytes\n", (u_long) num_bytes); /* Don't do this in sane_start() since there may be a long timespan between it and the first sane_read(), which would result in poor images. */ qc_send (q, QC_SEND_VIDEO_FRAME); qc_send (q, req.mode); if (req.despeckle && (!extra || buffer_size < num_bytes || buffer_size >= 2 * num_bytes)) { if (extra) extra = realloc (extra, num_bytes); else extra = malloc (num_bytes); if (!extra) { DBG (1, "reader_process: malloc(%ld) failed\n", (long) num_bytes); exit (1); } } if (buffer_size < num_bytes || buffer_size >= 2 * num_bytes) { if (buffer) buffer = realloc (buffer, num_bytes); else buffer = malloc (num_bytes); if (!buffer) { DBG (1, "reader_process: malloc(%ld) failed\n", (long) num_bytes); exit (1); } buffer_size = num_bytes; } if (q->port_mode == QC_BIDIR) { /* turn port into input port */ write_lpcontrol (q, Autofeed | Reset_N | PCAck | BiDir); usleep (3); write_lpcontrol (q, Autofeed | Reset_N | BiDir); qc_waithand (q, CamRdy1); write_lpcontrol (q, Autofeed | Reset_N | PCAck | BiDir); qc_waithand (q, 0); } if (q->version == QC_COLOR) for (len = 0; len < num_bytes; len += count) count = qc_readbytes (s, buffer + len); else { /* strange -- should be 15:63 below, but 4bpp is odd */ int shift, invert; unsigned int i; u_char val; switch (s->val[OPT_DEPTH].w) { case 4: invert = 16; shift = 4; break; case 6: invert = 63; shift = 2; break; default: DBG (1, "reader_process: unexpected depth %d\n", s->val[OPT_DEPTH].w); return 1; } for (len = 0; len < num_bytes; len += count) { count = qc_readbytes (s, buffer + len); for (i = 0; i < count; ++i) { /* 4bpp is odd (again) -- inverter is 16, not 15, but output must be 0-15 */ val = buffer[len + i]; if (val > 0 || invert != 16) val = invert - val; buffer[len + i] = (val << shift) | (val >> (8 - 2 * shift)); } } qc_readbytes (s, 0); /* reset state machine */ } /* we're done reading this frame: */ DBG (2, "reader_process: frame complete\n"); if (q->port_mode == QC_BIDIR) { /* return port to output mode */ write_lpcontrol (q, Autofeed); usleep (3); write_lpcontrol (q, Autofeed | Reset_N); usleep (3); write_lpcontrol (q, Autofeed | Reset_N | PCAck); } if (req.resolution == QC_RES_HIGH) { SANE_Byte buf[6]; int x, y; /* in billions mode, we need to oversample the data: */ src = buffer; width = req.params.pixels_per_line; height = req.params.lines; if (req.despeckle) { despeckle32 (width / 2, req.params.lines / 2, buffer, extra); src = extra; } assert (!(width & 1)); /* width must be even */ for (y = 0; y < height; ++y) { /* even line */ for (x = 0; x < width; x += 2) { int red1, green1, blue1, green2, blue2; blue1 = src[0]; green1 = src[1]; red1 = src[3]; if (x >= width - 2) { red1 = src[-1]; /* last red seems to be missing */ blue2 = blue1; green2 = green1; } else { blue2 = src[4]; green2 = src[5]; } src += 4; buf[0] = red1; buf[1] = green1; buf[2] = blue1; buf[3] = red1; buf[4] = green2; buf[5] = blue2; if (fwrite (buf, 1, 6, ofp) != 6) { perror ("fwrite: short write"); return 1; } } if (++y >= height) break; src -= 2 * width; /* 4 bytes/pixel -> 2 pixels of 3 bytes each */ /* odd line */ for (x = 0; x < width; x += 2) { int red1, green3, blue3, green4, blue4; int yoff; if (x >= width - 2) red1 = src[-1]; /* last red seems to be missing */ else red1 = src[3]; yoff = 2 * width; if (y >= height - 1) yoff = 0; green3 = src[yoff + 1]; blue3 = src[yoff + 0]; if (x >= width - 2) { blue4 = blue3; green4 = green3; } else { blue4 = src[yoff + 4]; green4 = src[yoff + 5]; } src += 4; buf[0] = red1; buf[1] = green3; buf[2] = blue3; buf[3] = red1; buf[4] = green4; buf[5] = blue4; if (fwrite (buf, 1, 6, ofp) != 6) { perror ("fwrite: short write"); return 1; } } } } else { src = buffer; if (req.despeckle) { despeckle (req.params.pixels_per_line, req.params.lines, buffer, extra); src = extra; } /* now write the whole thing to the main process: */ if (fwrite (src, 1, num_bytes, ofp) != num_bytes) { perror ("fwrite: short write"); return 1; } } fflush (ofp); } assert (SANE_FALSE); /* not reached */ DBG (5, "reader_process: exit\n"); return 1; } static SANE_Status attach (const char *devname, QC_Device ** devp) { int i, n1, n2, s1, s2, cmd, port, force_unidir; SANE_Status result, status; QC_Device *q; char *endp; DBG (3, "attach: enter\n"); errno = 0; force_unidir = 0; if (devname[0] == 'u') { force_unidir = 1; ++devname; } port = strtol (devname, &endp, 0); if (endp == devname || errno == ERANGE) { DBG (1, "attach: invalid port address `%s'\n", devname); return SANE_STATUS_INVAL; } for (q = first_dev; q; q = q->next) if (port == q->port) { if (devp) *devp = q; return SANE_STATUS_GOOD; } q = malloc (sizeof (*q)); if (!q) return SANE_STATUS_NO_MEM; memset (q, 0, sizeof (*q)); q->port = port; q->lock_fd = -1; result = enable_ports (q); if (result != SANE_STATUS_GOOD) { DBG (1, "attach: cannot enable ports (%s)\n", strerror (errno)); free (q); return SANE_STATUS_INVAL; } /* lock camera while we determine its version: */ qc_lock (q); qc_reset (q); write_lpdata (q, QC_SEND_VERSION); qc_wait (q); write_lpcontrol (q, Autofeed | Reset_N); /* make PCAck inactive */ qc_wait (q); for (i = 0; (i < 1000) && !(s1 = (n1 = read_lpstatus (q)) & CamRdy1); i++); if (!s1) { DBG (2, "attach: failed to get CamRdy1 at port 0x%x\n", q->port); goto unlock_and_fail; } write_lpcontrol (q, Autofeed | Reset_N | PCAck); qc_wait (q); for (i = 0; (i < 1000) && (s2 = (n2 = read_lpstatus (q)) & CamRdy1); i++); if (s2) { DBG (2, "attach: CamRdy1 failed to clear at port 0x%x\n", q->port); goto unlock_and_fail; } cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4); if (cmd != QC_SEND_VERSION) { DBG (2, "attach: got 0x%02x instead of 0x%02x\n", cmd, QC_SEND_VERSION); goto unlock_and_fail; } q->version = qc_readparam (q); DBG (1, "attach: found QuickCam version 0x%02x\n", q->version); q->port_mode = QC_UNIDIR; if (!force_unidir) { write_lpcontrol (q, BiDir); write_lpdata (q, 0x75); if (read_lpdata (q) != 0x75) q->port_mode = QC_BIDIR; } /* For some reason the color quickcam needs two set-black commands after a reset. Thus, we now set the black-level to some reasonable value (0) so that the next set-black level command will really go through. */ if (q->version == QC_COLOR) { qc_send (q, QC_SET_BLACK); qc_send (q, 0); DBG (3, "attach: resetting black_level\n"); /* wait for set black level command to finish: */ while (qc_getstatus (q) & (CameraNotReady | BlackBalanceInProgress)) usleep (10000); } status = qc_unlock (q); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: status qc_unlock NOK\n"); /* status = SANE_STATUS_GOOD; */ } q->sane.name = strdup (devname); q->sane.vendor = "Connectix"; q->sane.model = (q->version == QC_COLOR) ? "Color QuickCam" : "B&W QuickCam"; q->sane.type = "video camera"; ++num_devices; q->next = first_dev; first_dev = q; if (devp) *devp = q; DBG (3, "attach: exit status OK\n"); status = SANE_STATUS_GOOD; return status; unlock_and_fail: status = qc_unlock (q); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: unlock_and_fail status qc_unlock NOK\n"); } free (q); DBG (3, "attach: exit status NOK\n"); status = SANE_STATUS_INVAL; return status; } static SANE_Status init_options (QC_Scanner * s) { int i; DBG (3, "init_options: enter\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = (SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT); } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_STRING; s->opt[OPT_RESOLUTION].size = 5; /* sizeof("High") */ s->opt[OPT_RESOLUTION].unit = SANE_UNIT_NONE; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_RESOLUTION].constraint.string_list = resolution_list; s->val[OPT_RESOLUTION].s = strdup (resolution_list[QC_RES_LOW]); /* bit-depth */ s->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_DEPTH].title = "Pixel depth"; s->opt[OPT_DEPTH].desc = "Number of bits per pixel."; s->opt[OPT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_DEPTH].unit = SANE_UNIT_BIT; s->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_DEPTH].constraint.word_list = color_depth_list; s->val[OPT_DEPTH].w = color_depth_list[NELEMS (color_depth_list) - 1]; /* test */ s->opt[OPT_TEST].name = "test-image"; s->opt[OPT_TEST].title = "Force test image"; s->opt[OPT_TEST].desc = "Acquire a test-image instead of the image seen by the camera. " "The test image consists of red, green, and blue squares of " "32x32 pixels each. Use this to find out whether the " "camera is connected properly."; s->opt[OPT_TEST].type = SANE_TYPE_BOOL; s->val[OPT_TEST].w = SANE_FALSE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_INT; s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &x_range[QC_RES_LOW]; s->val[OPT_TL_X].w = 10; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_INT; s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &y_range[QC_RES_LOW]; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_INT; s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &odd_x_range[QC_RES_LOW]; s->val[OPT_BR_X].w = 339; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_INT; s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &odd_y_range[QC_RES_LOW]; s->val[OPT_BR_Y].w = 245; /* xfer-scale */ s->opt[OPT_XFER_SCALE].name = "transfer-scale"; s->opt[OPT_XFER_SCALE].title = "Transfer scale"; s->opt[OPT_XFER_SCALE].desc = "The transferscale determines how many of the acquired pixels actually " "get sent to the computer. For example, a transfer scale of 2 would " "request that every other acquired pixel would be omitted. That is, " "when scanning a 200 pixel wide and 100 pixel tall area, the resulting " "image would be only 100x50 pixels large. Using a large transfer scale " "improves acquisition speed, but reduces resolution."; s->opt[OPT_XFER_SCALE].type = SANE_TYPE_INT; s->opt[OPT_XFER_SCALE].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_XFER_SCALE].constraint.word_list = xfer_scale_list; s->val[OPT_XFER_SCALE].w = xfer_scale_list[1]; /* despeckle */ s->opt[OPT_DESPECKLE].name = "despeckle"; s->opt[OPT_DESPECKLE].title = "Speckle filter"; s->opt[OPT_DESPECKLE].desc = "Turning on this filter will remove the " "christmas lights that are typically present in dark images."; s->opt[OPT_DESPECKLE].type = SANE_TYPE_BOOL; s->opt[OPT_DESPECKLE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_DESPECKLE].w = 0; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS " In a conventional camera, this control corresponds to the " "exposure time."; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_AUTOMATIC; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &brightness_range; s->val[OPT_BRIGHTNESS].w = 135; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &u8_range; s->val[OPT_CONTRAST].w = 104; /* black-level */ s->opt[OPT_BLACK_LEVEL].name = SANE_NAME_BLACK_LEVEL; s->opt[OPT_BLACK_LEVEL].title = SANE_TITLE_BLACK_LEVEL; s->opt[OPT_BLACK_LEVEL].desc = SANE_DESC_BLACK_LEVEL " This value should be selected so that black areas just start " "to look really black (not gray)."; s->opt[OPT_BLACK_LEVEL].type = SANE_TYPE_INT; s->opt[OPT_BLACK_LEVEL].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BLACK_LEVEL].constraint.range = &u8_range; s->val[OPT_BLACK_LEVEL].w = 0; /* white-level */ s->opt[OPT_WHITE_LEVEL].name = SANE_NAME_WHITE_LEVEL; s->opt[OPT_WHITE_LEVEL].title = SANE_TITLE_WHITE_LEVEL; s->opt[OPT_WHITE_LEVEL].desc = SANE_DESC_WHITE_LEVEL " This value should be selected so that white areas just start " "to look really white (not gray)."; s->opt[OPT_WHITE_LEVEL].type = SANE_TYPE_INT; s->opt[OPT_WHITE_LEVEL].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_WHITE_LEVEL].constraint.range = &u8_range; s->val[OPT_WHITE_LEVEL].w = 150; /* hue */ s->opt[OPT_HUE].name = SANE_NAME_HUE; s->opt[OPT_HUE].title = SANE_TITLE_HUE; s->opt[OPT_HUE].desc = SANE_DESC_HUE; s->opt[OPT_HUE].type = SANE_TYPE_INT; s->opt[OPT_HUE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_HUE].constraint.range = &u8_range; s->val[OPT_HUE].w = 128; /* saturation */ s->opt[OPT_SATURATION].name = SANE_NAME_SATURATION; s->opt[OPT_SATURATION].title = SANE_TITLE_SATURATION; s->opt[OPT_SATURATION].desc = SANE_DESC_SATURATION; s->opt[OPT_SATURATION].type = SANE_TYPE_INT; s->opt[OPT_SATURATION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_SATURATION].constraint.range = &u8_range; s->val[OPT_SATURATION].w = 100; DBG (3, "init_options: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX], *str; size_t len; FILE *fp; authorize = authorize; /* silence compilation warnings */ DBG_INIT (); DBG (1, "sane_init: enter\n"); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (QCAM_CONFIG_FILE); if (!fp) { DBG (1, "sane_init: file `%s' not accessible\n", QCAM_CONFIG_FILE); return SANE_STATUS_INVAL; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ for (str = dev_name; *str && !isspace (*str) && *str != '#'; ++str); *str = '\0'; attach (dev_name, 0); } fclose (fp); DBG (1, "sane_init: exit\n"); return SANE_STATUS_GOOD; } void sane_exit (void) { QC_Device *dev, *next; static const SANE_Device **devlist; DBG (5, "sane_exit: enter\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); disable_ports (dev); free (dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (5, "sane_exit: exit\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { static const SANE_Device **devlist = 0; QC_Device *dev; int i; DBG (5, "sane_get_devices: enter\n"); local_only = local_only; /* silence compilation warnings */ if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (5, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { SANE_Status status; QC_Device *dev; QC_Scanner *s; DBG (5, "sane_open: enter: (devicename = %s)\n", devicename); if (devicename[0]) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } else /* empty devicname -> use first device */ dev = first_dev; if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->user_corner = 0; s->hw = dev; s->value_changed = ~0; /* ensure all options get updated */ s->reader_pid = -1; s->to_child = -1; s->from_child = -1; s->read_fd = -1; init_options (s); /* The contrast option seems to have an effect for b&w cameras only, so don't give the user the impression that this is a useful thing to set... */ if (s->hw->version == QC_COLOR) s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; else { /* Black level, Hue and Saturation are things the b&w cameras know nothing about. Despeckle might be useful, but this code seems to work for color cameras only right now. The framesize seems to work better in these ranges. */ s->opt[OPT_DESPECKLE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BLACK_LEVEL].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HUE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SATURATION].cap |= SANE_CAP_INACTIVE; s->opt[OPT_RESOLUTION].cap |= SANE_CAP_INACTIVE; s->opt[OPT_TEST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_DEPTH].constraint.word_list = mono_depth_list; s->val[OPT_DEPTH].w = mono_depth_list[NELEMS (mono_depth_list) - 1]; s->opt[OPT_TL_X].constraint.range = &bw_x_range; s->val[OPT_TL_X].w = 14; s->opt[OPT_TL_Y].constraint.range = &bw_y_range; s->val[OPT_TL_Y].w = 0; s->opt[OPT_BR_X].constraint.range = &odd_bw_x_range; s->val[OPT_BR_X].w = 333; s->opt[OPT_BR_Y].constraint.range = &odd_bw_y_range; s->val[OPT_BR_Y].w = 239; s->val[OPT_BRIGHTNESS].w = 170; s->val[OPT_CONTRAST].w = 150; s->val[OPT_WHITE_LEVEL].w = 150; } /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; DBG (5, "sane_open: exit\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { QC_Scanner *prev, *s; DBG (5, "sane_close: enter\n"); /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (1, "sane_close: bad handle %p\n", handle); return; /* oops, not a handle we know about */ } if (prev) prev->next = s->next; else first_handle = s->next; if (s->scanning) sane_cancel (handle); if (s->reader_pid >= 0) { kill (s->reader_pid, SIGTERM); waitpid (s->reader_pid, 0, 0); s->reader_pid = 0; } if (s->to_child >= 0) close (s->to_child); if (s->from_child >= 0) close (s->from_child); if (s->read_fd >= 0) close (s->read_fd); free (s); DBG (5, "sane_close: exit\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { QC_Scanner *s = handle; DBG (5, "sane_get_option_descriptor: enter\n"); if ((unsigned) option >= NUM_OPTIONS) return 0; DBG (5, "sane_get_option_descriptor: exit\n"); return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { QC_Scanner *s = handle; QC_Resolution old_res; SANE_Status status; SANE_Word cap; char *old_val; int i; DBG (5, "sane_control_option: enter\n"); if (info) *info = 0; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_DEPTH: case OPT_DESPECKLE: case OPT_TEST: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_XFER_SCALE: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_BLACK_LEVEL: case OPT_WHITE_LEVEL: case OPT_HUE: case OPT_SATURATION: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; /* string options: */ case OPT_RESOLUTION: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; default: DBG (1, "control_option: option %d unknown\n", option); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; if (option >= OPT_TL_X && option <= OPT_BR_Y) s->user_corner |= 1 << (option - OPT_TL_X); assert (option <= 31); s->value_changed |= 1 << option; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_XFER_SCALE: case OPT_DEPTH: if (!s->scanning && info && s->val[option].w != *(SANE_Word *) val) /* only signal the reload params if we're not scanning---no point in creating the frontend useless work */ *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_NUM_OPTS: case OPT_TEST: case OPT_DESPECKLE: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_BLACK_LEVEL: case OPT_WHITE_LEVEL: case OPT_HUE: case OPT_SATURATION: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* options with side-effects: */ case OPT_RESOLUTION: old_val = s->val[OPT_RESOLUTION].s; if (strcmp (old_val, val) != 0) return SANE_STATUS_GOOD; /* no change */ if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; if (!s->scanning) *info |= SANE_INFO_RELOAD_PARAMS; } free (old_val); s->val[OPT_RESOLUTION].s = strdup (val); /* low-resolution mode: */ old_res = s->resolution; s->resolution = QC_RES_LOW; if (strcmp (val, resolution_list[QC_RES_HIGH]) == 0) /* high-resolution mode: */ s->resolution = QC_RES_HIGH; s->opt[OPT_TL_X].constraint.range = &x_range[s->resolution]; s->opt[OPT_BR_X].constraint.range = &odd_x_range[s->resolution]; s->opt[OPT_TL_Y].constraint.range = &y_range[s->resolution]; s->opt[OPT_BR_Y].constraint.range = &odd_y_range[s->resolution]; if (old_res == QC_RES_LOW && s->resolution == QC_RES_HIGH) { for (i = OPT_TL_X; i <= OPT_BR_Y; ++i) s->val[i].w *= 2; s->val[OPT_BR_X].w += 1; s->val[OPT_BR_Y].w += 1; s->opt[OPT_TEST].cap |= SANE_CAP_INACTIVE; } else if (old_res == QC_RES_HIGH && s->resolution == QC_RES_LOW) { for (i = OPT_TL_X; i <= OPT_BR_Y; ++i) s->val[i].w /= 2; s->opt[OPT_TEST].cap &= ~SANE_CAP_INACTIVE; } if (!(s->user_corner & 0x4)) s->val[OPT_BR_X].w = odd_x_range[s->resolution].max; if (!(s->user_corner & 0x8)) s->val[OPT_BR_Y].w = odd_y_range[s->resolution].max - 4; /* make sure the affected options have valid values: */ for (i = OPT_TL_X; i <= OPT_BR_Y; ++i) if (s->val[i].w > s->opt[i].constraint.range->max) s->val[i].w = s->opt[i].constraint.range->max; DBG (5, "sane_control_option: exit\n"); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_AUTO) { switch (option) { case OPT_BRIGHTNESS: /* not implemented yet */ DBG (5, "sane_control_option: exit\n"); return SANE_STATUS_GOOD; default: break; } } DBG (5, "sane_control_option: NOK exit\n"); return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { QC_Scanner *s = handle; QC_Device *q = s->hw; int xfer_scale; size_t Bpp = 3; /* # of bytes per pixel */ DBG (5, "sane_get_parameters: enter\n"); if (!s->scanning) { /* Only compute new parameters when not scanning---allows changing width/height etc while scan is in progress. */ xfer_scale = s->val[OPT_XFER_SCALE].w; s->params.format = SANE_FRAME_RGB; if (q->version != QC_COLOR) { s->params.format = SANE_FRAME_GRAY; Bpp = 1; } s->params.last_frame = SANE_TRUE; s->params.pixels_per_line = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w + 1; s->params.pixels_per_line /= xfer_scale; s->params.pixels_per_line &= ~1UL; /* ensure it's even */ if (s->params.pixels_per_line < 2) s->params.pixels_per_line = 2; s->params.lines = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w + 1; s->params.lines /= xfer_scale; if (s->params.lines < 1) s->params.lines = 1; s->params.bytes_per_line = Bpp * s->params.pixels_per_line; s->params.depth = 8; } if (params) *params = s->params; DBG (5, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { int top, left, width, height, undecimated_width, undecimated_height; QC_Scanner *s = handle; QC_Device *q = s->hw; QC_Scan_Request req; DBG (5, "sane_start: enter\n"); if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (s->reader_pid < 0) { int p2c_pipe[2]; /* parent->child pipe */ int c2p_pipe[2]; /* child->parent pipe */ if (pipe (p2c_pipe) < 0 || pipe (c2p_pipe) < 0) { DBG (3, "start: failed to create pipes\n"); return SANE_STATUS_IO_ERROR; } s->reader_pid = fork (); if (s->reader_pid == 0) { /* this is the child */ signal (SIGHUP, SIG_DFL); signal (SIGINT, SIG_DFL); signal (SIGPIPE, SIG_DFL); signal (SIGTERM, SIG_DFL); _exit (reader_process (s, p2c_pipe[0], c2p_pipe[1])); } close (p2c_pipe[0]); close (c2p_pipe[1]); s->to_child = p2c_pipe[1]; s->from_child = c2p_pipe[0]; } s->read_fd = dup (s->from_child); sane_get_parameters (s, 0); /* ensure uptodate parameters */ qc_lock (q); s->holding_lock = SANE_TRUE; if (q->version == QC_COLOR) { qc_send (q, QC_SET_SPEED); qc_send (q, 2); /* wait for camera to become ready: */ while (qc_getstatus (q) & CameraNotReady) usleep (10000); /* Only send black_level if necessary; this optimization may fail if two applications access the camera in an interleaved fashion; but the black-level command is slow enough that it cannot be issued for every image acquisition. */ if (s->value_changed & (1 << OPT_BLACK_LEVEL)) { s->value_changed &= ~(1 << OPT_BLACK_LEVEL); qc_send (q, QC_SET_BLACK); qc_send (q, s->val[OPT_BLACK_LEVEL].w); DBG (3, "start: black_level=%d\n", s->val[OPT_BLACK_LEVEL].w); /* wait for set black level command to finish: */ while (qc_getstatus (q) & (CameraNotReady | BlackBalanceInProgress)) usleep (10000); } if (s->value_changed & (1 << OPT_HUE)) { s->value_changed &= ~(1 << OPT_HUE); qc_send (q, QC_COL_SET_HUE); qc_send (q, s->val[OPT_HUE].w); } if (s->value_changed & (1 << OPT_SATURATION)) { s->value_changed &= ~(1 << OPT_SATURATION); qc_send (q, QC_SET_SATURATION); qc_send (q, s->val[OPT_SATURATION].w); } } if (q->version != QC_COLOR) qc_reset (q); if (s->value_changed & (1 << OPT_CONTRAST)) { s->value_changed &= ~(1 << OPT_CONTRAST); qc_send (q, ((q->version == QC_COLOR) ? QC_COL_SET_CONTRAST : QC_MONO_SET_CONTRAST)); qc_send (q, s->val[OPT_CONTRAST].w); } if (s->value_changed & (1 << OPT_BRIGHTNESS)) { s->value_changed &= ~(1 << OPT_BRIGHTNESS); qc_send (q, QC_SET_BRIGHTNESS); qc_send (q, s->val[OPT_BRIGHTNESS].w); } width = s->params.pixels_per_line; height = s->params.lines; if (s->resolution == QC_RES_HIGH) { width /= 2; /* the expansion occurs through oversampling */ height /= 2; /* we acquire only half the lines that we generate */ } undecimated_width = width * s->val[OPT_XFER_SCALE].w; undecimated_height = height * s->val[OPT_XFER_SCALE].w; s->num_bytes = 0; s->bytes_per_frame = s->params.lines * s->params.bytes_per_line; qc_send (q, QC_SET_NUM_V); qc_send (q, undecimated_height); if (q->version == QC_COLOR) { qc_send (q, QC_SET_NUM_H); qc_send (q, undecimated_width / 2); } else { int val, val2; if (q->port_mode == QC_UNIDIR && s->val[OPT_DEPTH].w == 6) { val = undecimated_width; val2 = s->val[OPT_XFER_SCALE].w * 4; } else { val = undecimated_width * s->val[OPT_DEPTH].w; val2 = ((q->port_mode == QC_BIDIR) ? 24 : 8) * s->val[OPT_XFER_SCALE].w; } val = (val + val2 - 1) / val2; qc_send (q, QC_SET_NUM_H); qc_send (q, val); } left = s->val[OPT_TL_X].w / 2; top = s->val[OPT_TL_Y].w; if (s->resolution == QC_RES_HIGH) { left /= 2; top /= 2; } DBG (3, "sane_start: top=%d, left=%d, white=%d, bright=%d, contr=%d\n", top, left, s->val[OPT_WHITE_LEVEL].w, s->val[OPT_BRIGHTNESS].w, s->val[OPT_CONTRAST].w); qc_send (q, QC_SET_LEFT); qc_send (q, left); qc_send (q, QC_SET_TOP); qc_send (q, top + 1); /* not sure why this is so... ;-( */ if (s->value_changed & (1 << OPT_WHITE_LEVEL)) { s->value_changed &= ~(1 << OPT_WHITE_LEVEL); qc_send (q, QC_SET_WHITE); qc_send (q, s->val[OPT_WHITE_LEVEL].w); } DBG (2, "start: %s %d lines of %d pixels each (%ld bytes) => %dx%d\n", (q->port_mode == QC_BIDIR) ? "bidir" : "unidir", height, width, (long) s->bytes_per_frame, s->params.pixels_per_line, s->params.lines); /* send scan request to reader process: */ qc_setscanmode (s, &req.mode); req.num_bytes = width * height; if (q->version == QC_COLOR) { if (s->resolution == QC_RES_LOW) req.num_bytes *= 3; else req.num_bytes *= 4; } req.resolution = s->resolution; req.params = s->params; req.despeckle = s->val[OPT_DESPECKLE].w; write (s->to_child, &req, sizeof (req)); s->scanning = SANE_TRUE; s->deliver_eof = 0; DBG (5, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * lenp) { SANE_Status status; QC_Scanner *s = handle; QC_Device *q = s->hw; ssize_t nread; size_t len; DBG (5, "sane_read: enter\n"); *lenp = 0; if (s->deliver_eof) { s->deliver_eof = 0; return SANE_STATUS_EOF; } if (!s->scanning) return SANE_STATUS_CANCELLED; len = max_len; if (s->num_bytes + len > s->bytes_per_frame) len = s->bytes_per_frame - s->num_bytes; DBG (8, "read(buf=%p,num_bytes=%ld,max_len=%d,len=%ld)\n", buf, (long) s->num_bytes, max_len, (long) len); nread = read (s->read_fd, buf, len); if (nread <= 0) { if (nread == 0 || errno == EAGAIN) { DBG (3, "read: no more data available\n"); return SANE_STATUS_GOOD; } DBG (3, "read: short read (%s)\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } if (nread > 0 && s->holding_lock) { status = qc_unlock (q); /* now we can unlock the camera */ if (status != SANE_STATUS_GOOD) DBG(3, "sane_read: qc_unlock error\n"); s->holding_lock = SANE_FALSE; } s->num_bytes += nread; if (s->num_bytes >= s->bytes_per_frame) { s->scanning = SANE_FALSE; close (s->read_fd); s->read_fd = -1; s->deliver_eof = 1; } if (lenp) *lenp = nread; DBG (5, "sane_read: exit, read got %d bytes\n", *lenp); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { QC_Scanner *s = handle; SANE_Bool was_scanning; SANE_Status status; DBG (5, "sane_cancel: enter\n"); was_scanning = s->scanning; s->scanning = SANE_FALSE; s->deliver_eof = 0; if (s->read_fd >= 0) { close (s->read_fd); s->read_fd = -1; } if (s->reader_pid >= 0 && was_scanning) { char buf[1024]; ssize_t nread; int flags; DBG (1, "cancel: cancelling read request\n"); kill (s->reader_pid, SIGINT); /* tell reader to stop reading */ /* save non-blocking i/o flags: */ flags = fcntl (s->from_child, F_GETFL, 0); /* block until we read at least one byte: */ read (s->from_child, buf, 1); /* put descriptor in non-blocking i/o: */ fcntl (s->from_child, F_SETFL, O_NONBLOCK); /* read what's left over in the pipe/file buffer: */ do { while ((nread = read (s->from_child, buf, sizeof (buf))) > 0); usleep (100000); nread = read (s->from_child, buf, sizeof (buf)); } while (nread > 0); /* now restore non-blocking i/o flag: */ fcntl (s->from_child, F_SETFL, flags & O_NONBLOCK); waitpid (s->reader_pid, 0, 0); s->reader_pid = 0; DBG (1, "cancel: cancellation completed\n"); } if (s->holding_lock) { status = qc_unlock (s->hw); if (status != SANE_STATUS_GOOD) DBG(3, "sane_cancel: qc_unlock error\n"); s->holding_lock = SANE_FALSE; } DBG (5, "sane_cancel: exit\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { QC_Scanner *s = handle; DBG (5, "sane_set_io_mode: enter\n"); if (!s->scanning) return SANE_STATUS_INVAL; if (fcntl (s->read_fd, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) return SANE_STATUS_IO_ERROR; DBG (5, "sane_set_io_mode: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { QC_Scanner *s = handle; DBG (5, "sane_get_select_fd: enter\n"); if (!s->scanning) return SANE_STATUS_INVAL; *fd = s->read_fd; DBG (5, "sane_get_select_fd: exit\n"); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/dmc.h0000664000175000017500000000764112112021330013516 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998 David F. Skoll This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ */ #ifndef polaroid_dmc_h #define polaroid_dmc_h #include #define BYTES_PER_RAW_LINE 1599 typedef enum { OPT_NUM_OPTS = 0, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_MODE_GROUP, /* Image acquisition mode */ OPT_IMAGE_MODE, /* Thumbnail, center cut or MFI'd image */ OPT_ASA, /* ASA Settings */ OPT_SHUTTER_SPEED, /* Shutter speed */ OPT_WHITE_BALANCE, /* White balance */ /* must come last: */ NUM_OPTIONS } DMC_Option; typedef struct DMC_Device { struct DMC_Device *next; SANE_Device sane; SANE_Range shutterSpeedRange; unsigned int shutterSpeed; int asa; int whiteBalance; } DMC_Device; typedef struct DMC_Camera { /* all the state needed to define a scan request: */ struct DMC_Camera *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; size_t bytes_to_read; SANE_Range tl_x_range; SANE_Range tl_y_range; SANE_Range br_x_range; SANE_Range br_y_range; int imageMode; /* The DMC needs certain reads to be done in one chunk, meaning we might have to buffer them. */ char *readBuffer; char *readPtr; int inViewfinderMode; int fd; /* SCSI filedescriptor */ SANE_Byte currentRawLine[BYTES_PER_RAW_LINE]; SANE_Byte nextRawLine[BYTES_PER_RAW_LINE]; int nextRawLineValid; /* scanner dependent/low-level state: */ DMC_Device *hw; } DMC_Camera; /* We only support the following four imaging modes */ #define IMAGE_MFI 0x0000 /* 801x600 filtered image */ #define IMAGE_VIEWFINDER 0x0001 /* 270x201 viewfinder image */ #define IMAGE_RAW 0x0002 /* 1599x600 raw image */ #define IMAGE_THUMB 0x0003 /* 80x60 thumbnail image */ #define IMAGE_SUPER_RES 0x0004 #define NUM_IMAGE_MODES 5 #define ASA_25 0 #define ASA_50 1 #define ASA_100 2 #define WHITE_BALANCE_DAYLIGHT 0 #define WHITE_BALANCE_INCANDESCENT 1 #define WHITE_BALANCE_FLUORESCENT 2 #endif /* polaroid_dmc_h */ sane-backends-1.0.27/backend/plustek_pp.conf.in0000664000175000017500000000165712112021330016245 00000000000000# Plustek-PP SANE Backend configuration file # For use with Plustek parallel-port scanners # # # user either [direct] or [kernel] to access the scanner # when using [kernel], device specifies the device-node, which is created # by the kernel-module loader (applies only to Linux) # when using [direct], device is used to set the parallel-port base address # or a device-name suitable for libieee1284, i.e. parport0 # #[direct] #device 0x378 # # example for accessing the scanner via libieee1284 # [direct] device parport0 # # leave the default values as specified in /etc/modules.conf # option warmup -1 option lOffOnEnd -1 option lampOff -1 # model override switch, mostly for cosmetic changes, if the autodetection # does not work or could not work correctly #option mov 7 # # example for accessing the scanner via the kernel module # #[kernel] #device /dev/pt_drv # #option warmup -1 #option lOffOnEnd -1 #option lampOff -1 sane-backends-1.0.27/backend/mustek_pp_decl.h0000664000175000017500000000720512112021330015745 00000000000000 #ifndef MUSTEK_PP_DECL_H #define MUSTEK_PP_DECL_H /* debug driver, version 0.11-devel, author Jochen Eisinger */ static SANE_Status debug_drv_init (SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach); static void debug_drv_capabilities (SANE_Int info, SANE_String *model, SANE_String *vendor, SANE_String *type, SANE_Int *maxres, SANE_Int *minres, SANE_Int *maxhsize, SANE_Int *maxvsize, SANE_Int *caps); static SANE_Status debug_drv_open (SANE_String port, SANE_Int caps, SANE_Int *fd); static void debug_drv_setup (SANE_Handle hndl); static SANE_Status debug_drv_config (SANE_Handle hndl, SANE_String_Const optname, SANE_String_Const optval); static void debug_drv_close (SANE_Handle hndl); static SANE_Status debug_drv_start (SANE_Handle hndl); static void debug_drv_read (SANE_Handle hndl, SANE_Byte *buffer); static void debug_drv_stop (SANE_Handle hndl); /* CIS drivers for 600CP, 1200CP, and 1200CP+ Version 0.13-beta, author Eddy De Greef */ static SANE_Status cis600_drv_init (SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach); static SANE_Status cis1200_drv_init (SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach); static SANE_Status cis1200p_drv_init(SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach); static void cis_drv_capabilities(SANE_Int info, SANE_String *model, SANE_String *vendor, SANE_String *type, SANE_Int *maxres, SANE_Int *minres, SANE_Int *maxhsize, SANE_Int *maxvsize, SANE_Int *caps); static SANE_Status cis_drv_open (SANE_String port, SANE_Int caps, SANE_Int *fd); static void cis_drv_setup (SANE_Handle hndl); static SANE_Status cis_drv_config (SANE_Handle hndl, SANE_String_Const optname, SANE_String_Const optval); static void cis_drv_close (SANE_Handle hndl); static SANE_Status cis_drv_start (SANE_Handle hndl); static void cis_drv_read (SANE_Handle hndl, SANE_Byte *buffer); static void cis_drv_stop (SANE_Handle hndl); /* CCD drivers for 300 dpi models Version 0.11-devel, author Jochen Eisinger */ static SANE_Status ccd300_init (SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach); static void ccd300_capabilities(SANE_Int info, SANE_String *model, SANE_String *vendor, SANE_String *type, SANE_Int *maxres, SANE_Int *minres, SANE_Int *maxhsize, SANE_Int *maxvsize, SANE_Int *caps); static SANE_Status ccd300_open (SANE_String port, SANE_Int caps, SANE_Int *fd); static void ccd300_setup (SANE_Handle hndl); static SANE_Status ccd300_config (SANE_Handle hndl, SANE_String_Const optname, SANE_String_Const optval); static void ccd300_close (SANE_Handle hndl); static SANE_Status ccd300_start (SANE_Handle hndl); static void ccd300_read (SANE_Handle hndl, SANE_Byte *buffer); static void ccd300_stop (SANE_Handle hndl); #endif sane-backends-1.0.27/backend/hp5590_cmds.c0000664000175000017500000017314713063340150014725 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Ilia Sotnikov HP ScanJet 4570c support by Markham Thomas This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 Scanners */ #include "../include/sane/config.h" #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ #ifdef HAVE_NETINET_IN_H # include #endif /* HAVE_NETINET_IN_H */ #include #include #include "../include/sane/sanei_debug.h" #include "../include/_stdint.h" #include "hp5590_low.h" #include "hp5590_cmds.h" static const struct hp5590_model hp5590_models[] = { { SCANNER_HP4570, 0x03f0, 0x1305, "SILITEKIElwood", "4570C/5500C", "Workgroup scanner", PF_NONE }, { SCANNER_HP5550, 0x03f0, 0x1205, "SILITEKIPenguin", "4500C/5550C", "Workgroup scanner", PF_NO_USB_IN_USB_ACK /* These devices need no * acknowledgement after USB-in-USB * commands */ }, { SCANNER_HP5590, 0x03f0, 0x1705, "SILITEKIPenguin", "5590", "Workgroup scanner", PF_NONE }, { SCANNER_HP7650, 0x03f0, 0x1805, "SILITEKIArnold", "7650", "Document scanner", PF_NONE } }; /* Debug levels */ #define DBG_err 0 #define DBG_proc 10 #define DBG_cmds 40 #define hp5590_cmds_assert(exp) if(!(exp)) { \ DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\ return SANE_STATUS_INVAL; \ } #define WAKEUP_TIMEOUT 90 /* First byte of init (0x12 cmd) response */ #define INIT_FLAG_TMA 1 << 0 #define INIT_FLAG_ADF 1 << 1 #define INIT_FLAG_LCD 1 << 3 /* Power (0x24 cmd) */ #define POWER_FLAG_ON 1 << 1 /* ADF (0x03 cmd) */ #define FLAG_ADF_EMPTY 1 << 1 #define PART_NUMBER_LEN 10 #define REVERSE_MAP_LEN 128 * 1024 / sizeof(uint16_t) #define FORWARD_MAP_LEN 128 * 1024 / sizeof(uint16_t) /* Button flags */ /* From left to rigth */ /* 1: Power * 1: Scan * 2: Collect * 3: File * 4: Email * 5: Copy * 6,7: Up/down * 8: Mode * 9: Cancel */ #define BUTTON_FLAG_EMAIL 1 << 15 #define BUTTON_FLAG_COPY 1 << 14 #define BUTTON_FLAG_DOWN 1 << 13 #define BUTTON_FLAG_MODE 1 << 12 #define BUTTON_FLAG_UP 1 << 11 #define BUTTON_FLAG_FILE 1 << 9 #define BUTTON_FLAG_POWER 1 << 5 #define BUTTON_FLAG_SCAN 1 << 2 #define BUTTON_FLAG_COLLECT 1 << 1 #define BUTTON_FLAG_CANCEL 1 << 0 #define CMD_INIT 0x0012 #define CMD_EEPROM_ADDR 0x00f2 #define CMD_EEPROM_READ 0x0bf0 #define CMD_EEPROM_WRITE 0x0bf1 #define CMD_DATA_STATUS 0x0001 #define CMD_STOP_SCAN 0x011b #define CMD_CONTROL_LAMP 0x00c0 #define CMD_POWER_STATUS 0x0024 #define CMD_SELECT_SOURCE 0x00d6 #define CMD_MISC_STATUS 0x0003 #define CMD_LOCK_UNLOCK 0x0000 #define CMD_SET_BASE_DPI 0x0015 #define CMD_SET_COLOR_MAP 0x0240 #define CMD_SET_SCAN_PARAMS 0x0025 #define CMD_GET_IMAGE_PARAMS 0x0034 #define CMD_START_SCAN 0x051b #define CMD_BUTTON_STATUS 0x0020 struct init_resp { uint8_t flags; /* bit 0 - TMA, bit 1 - ADF, bit 3 - LCD present */ uint8_t id[15]; /* SILITEKPenguin */ uint8_t pad1[9]; /* 00 00 00 00 00 00 00 00 00 */ uint8_t version[5]; /* 0.0.67 */ uint16_t max_dpi_x; /* 09 60 = 2400 */ uint16_t max_dpi_y; /* 09 60 = 2400 */ uint16_t max_pixels_x; /* 4F B0 = 20400 (20400 / 2400 = 8.5") */ uint16_t max_pixels_y; /* 6D E0 = 28128 (28128 / 2400 = 11.72") */ uint8_t pad2[8]; /* 00 00 00 00 00 00 00 00 */ uint16_t motor_param_normal; /* 00 64 = 100 */ uint16_t motor_param_max; /* 03 E8 = 1000 */ } __attribute__ ((packed)); struct power_resp { uint8_t flags; uint16_t unk1; } __attribute__ ((packed)); /* * 215.9 mm x 297.2 mm * 8.5" x 11.72" * * 50 : 425.00 x 586.00 * 75 : 637.50 x 879.50 * 100 : 850.00 x 1172.00 * 150 : 1275.00 x 1758.00 (base DPI) * 200 : 1700.00 x 2344.00 * 300 : 2550.00 x 3516.00 (base DPI) * 400 : 3400.00 x 4688.00 * 600 : 5100.00 x 7032.00 (base DPI) */ #define SCAN_PARAMS_SOURCE_TMA_NEGATIVES 1 << 0 #define SCAN_PARAMS_SOURCE_TMA_SLIDES 1 << 1 #define SCAN_PARAMS_SOURCE_ADF 1 << 2 #define SCAN_PARAMS_SOURCE_FLATBED 1 << 3 #define SCAN_PARAMS_SOURCE_SIMPLEX 1 << 4 #define SCAN_PARAMS_SOURCE_DUPLEX 1 << 6 struct scan_params { uint8_t source; /* * TMA Negatives : 11 = 17 * TMA Slides : 12 = 18 * ADF : 14 = 20 * Flatbed : 18 = 24 * ADF Duplex : 54 = 84 */ uint16_t dpi_x; /* * 50 : 00 64 = 100 * 75 : 00 64 = 100 * 100 : 00 64 = 100 * 150 : 00 c8 = 200 * 200 : 00 c8 = 200 * 300 : 01 2c = 300 * 400 : 02 58 = 600 * 600 : 02 58 = 600 * 1200 : 04 b0 = 1200 */ uint16_t dpi_y; /* * 50 : 00 64 = 100 * 75 : 00 64 = 100 * 100 : 00 64 = 100 * 150 : 00 c8 = 200 * 200 : 00 c8 = 200 * 300 : 01 2c = 300 * 400 : 02 58 = 600 * 600 : 02 58 = 600 * 1200 : 04 b0 = 1200 */ uint16_t top_x; /* * pixels * (Base DPI / current DPI) * 00 00, 01 6e = 366 (x = 425 - 302 = 123) * 04 b0 = 1200 (x = 425 - 24 = 401) */ uint16_t top_y; /* * pixels * (Base DPI / current DPI) * 00 00, 06 99 = 1689 (y = 585 - 21 = 564) */ uint16_t size_x; /* X pixels in Base DPI (CMD 15) * 50 : 04f8 = 1272 ; 150 * 75 : 04f8 = 1272 ; 150 * 100 : 04f8 = 1272 ; 150 * 100 TMA : 00fc = 252 ; 150 * 150 : 09f6 = 2550, 09f0 = 2544, 09f4 = 2548 ; 300 * 200 : 09f0 = 2544, 09f6 = 2550, 09f6 = 2550 ; 300 * 300 : 09f6 = 2550, 09f0 = 2544, 09f4 = 2548 ; 300 * 300 TMA : 01fc = 508 ; 300 * 400 : 13ec = 5100 ; 600 * 600 : 13e8 = 5096, 13ec = 5100 ,13ec = 5100 ; 600 * 1200 : 27a8 = 10152 ; 1200 */ uint16_t size_y; /* Y pixels in Base DPI (CMD 15) * 50 : 06db = 1755 ; 150 * 75 : 06da = 1754 ; 150 * 100 : 06db = 1755 ; 150 * 100 TMA : 0384 = 900 ; 150 * 150 : 0db6 = 3510 ; 300 * 200 : 0db6 = 3510 ; 300 * 300 : 0db6 = 3510 ; 300 * 300 TMA : 0708 = 1800 ; 300 * 400 : 1b6c = 7020 ; 600 * 600 : 1b6c = 7020 ; 600 * 1200 : 36d8 = 14040 ; 1200 */ uint16_t unk1; /* 00 80 */ uint16_t bw_gray_flag; /* * 00 40 - bw (ntsc gray)/gray, * 00 20 - bw (by green band), * 00 10 - bw (by red band), * 00 30 - bw (by blue band), * 00 00 - color */ uint8_t pixel_bits; /* * bw 50/75/150/400 : 08 = 8 * bw 100/200/300/600/1200 : 01 = 1 * gray 50/75/100/150/200/400/600 : 08 = 8 * color 24 bit 50/75/100/150/200/400/600 : 18 = 24 * color 48 bit 100/200 : 30 = 48 */ uint16_t flags; /* * 50/75/100/150/200/300 : e8 40 = 59456 * 400/600/1200 : c8 40 = 51264 */ uint16_t motor_param1; /* * 00 64 = 100 */ uint16_t motor_param2; /* * 00 64 = 100 - ADF, Flatbed, TMA slides * 00 c8 = 200 - TMA Negatives */ uint16_t motor_param3; /* * 00 64 = 100 - ADF, Flatbed, TMA slides * 01 90 = 400 - TMA negatives */ uint32_t pad1; /* 00 00 00 00 */ uint16_t pad2; /* 00 00 */ uint8_t mode; /* 00 - normal scan, 04 - preview scan */ uint16_t pad3; /* 00 00 */ uint16_t line_width; /* Based on current .dpi_x * bw 50 : 03 50 = 848 * gray 50 : 03 50 = 848 * color 50 : 09 f0 = 2544 (3 * gray) * * bw 75 : 03 50 = 848 * gray 75 : 03 50 = 848 * color 75 : 09 f0 = 2544 (3 * gray) * * bw 100 : 00 6a = 106 * gray 100 : 03 50 = 848 (8 * bw) * color 100(24) : 09 f0 = 2544 (3 * gray) * color 100(48) : 13 e0 = 5088 (2 * color 24) * color 100(48) TMA : 03 f0 = 1008 * * bw 150 : 06 a4 = 1700 * gray 150 : 06 a4 = 1700 * color 150 : 13 ec = 5100 (3 * gray) * * bw 200 : 00 d4 = 212 * gray 200 : 06 a4 = 1700 (8 * bw) * color 200(24) : 13 ec = 5100 (3 * gray) * color 200(48) : 27 a8 = 10152 * * bw 300 : 01 3e = 318 * gray 300 : 09 f4 = 2548 (8 * bw) * color 300 : 1d dc = 7644 (3 * gray) * color 300(48) TMA : 0b e8 = 3048 * * bw 400 : 13 ec = 5100 * gray 400 : 13 ec = 5100 * color 400 : 3b c4 = 15300 (3 * gray) * * bw 600 : 02 7d = 637 * gray 600 : 13 ec = 5100 (8 * bw) * color 600 : 3b c4 = 15300 (3 * gray) * * bw 1200 : 04 f5 = 1269 */ } __attribute__ ((packed)); struct image_params { uint8_t signature; /* c0 */ uint8_t pad1; /* 00 */ uint32_t image_size; /* * bw 50 : 00 0f 23 a0 = 992 160 * gray 50 : 00 0f 23 a0 = 992 160 * color 50 : 00 2d 6a e0 = 2 976 480 * * bw 75 : 00 0f 20 50 = 991 312 * gray 75 : 00 0f 20 50 = 991 312 * color 75 : 00 2d 60 f0 = 2 973 936 * color 75(48) : 00 5a 86 40 = 5 932 608 * * bw 100 : 00 01 e4 74 = 124 020 * gray 100 : 00 0f 23 a0 = 992 160 * color 100 : 00 2d 6a e0 = 2 976 480 * color 100(48) : 00 5a 68 10 = 5 924 880 * color 100(48), preview: 00 5a d5 c0 = 5 952 960 * * bw 150 : 00 3c b3 10 = 3 978 000 * gray 150 : 00 3c b3 10 = 3 978 000 * color 150 : 00 b6 19 30 = 11 934 000 * color 150(48) : 01 6a 7b a0 = 23 755 680 * * bw 200 : 00 07 91 d0 = 496 080 * gray 200 : 00 3c b3 10 = 3 978 000 * color 200 : 00 b6 19 30 = 11 934 000 * color 200(48) : 01 6a f3 a0 = 23 786 400 * * bw 300 : 00 11 08 14 = 1 116 180 * gray 300 : 00 88 77 78 = 8 943 480 * color 300 : 01 99 66 68 = 26 830 440 * * bw 400 : 02 22 4b 90 = 35 802 000 * gray 400 : 02 22 4b 90 = 35 802 000 * color 400 : 06 66 e2 b0 = 107 406 000 * * bw 600 : 00 44 3b bc = 4 471 740 * gray 600 : 02 22 4b 90 = 35 802 000 * color 600 : 06 66 e2 b0 = 107 406 000 */ uint16_t pad2; /* 00 00 */ uint16_t line_width; uint16_t real_size_y; uint32_t pad3; /* 00 00 00 00 */ } __attribute__ ((packed)); struct lamp_state { uint8_t unk1; /* 02 */ uint8_t flag; /* 01 on start, 02 - TMA, 03 - all other */ uint16_t turnoff_time; /* 0a 0a, 03 36, 0f 36 */ } __attribute__ ((packed)); struct color_map { uint8_t color1[6]; /* 00 00 00 00 01 00 */ uint8_t color2[6]; /* 00 00 00 00 01 00 */ uint8_t color3[6]; /* 00 00 00 00 01 00 */ } __attribute__ ((packed)); struct reg_03 { uint8_t unk1; /* 0x0b - ADF ready, 0x03 - not */ uint8_t unk2; /* 0x80 */ uint8_t adf_flags; /* 0x01 - ADF ready when selected, 0x02 - not */ } __attribute__ ((packed)); /******************************************************************************/ static SANE_Status hp5590_model_def (enum hp_scanner_types scanner_type, const struct hp5590_model ** model) { unsigned int i; hp5590_cmds_assert (model != NULL); for (i = 0; i < sizeof (hp5590_models) / sizeof (struct hp5590_model); i++) { if (hp5590_models[i].scanner_type == scanner_type) { *model = &hp5590_models[i]; return SANE_STATUS_GOOD; } } return SANE_STATUS_INVAL; } /******************************************************************************/ static SANE_Status hp5590_vendor_product_id (enum hp_scanner_types scanner_type, SANE_Word * vendor_id, SANE_Word * product_id) { const struct hp5590_model *model; SANE_Status ret; hp5590_cmds_assert (vendor_id != NULL); hp5590_cmds_assert (product_id != NULL); ret = hp5590_model_def (scanner_type, &model); if (ret != SANE_STATUS_GOOD) return ret; *vendor_id = model->usb_vendor_id; *product_id = model->usb_product_id; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_init_scanner (SANE_Int dn, enum proto_flags proto_flags, struct scanner_info ** info, enum hp_scanner_types scanner_type) { struct init_resp init_resp; char id_buf[sizeof (init_resp.id) + 1]; char ver_buf[sizeof (init_resp.version) + 1]; SANE_Status ret; const struct hp5590_model *scanner_model; /* * 0A 53 49 4C 49 54 45 4B 49 50 65 6E 67 75 69 6E .SILITEKIPenguin * 00 00 00 00 00 00 00 00 00 30 2E 30 36 37 09 60 .........0.067.. * 09 60 4F B0 6D E0 00 00 00 00 00 00 00 00 00 64 ..O.m..........d * 03 E8 .. */ DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (init_resp) == 50); /* Init scanner */ ret = hp5590_cmd (dn, proto_flags, CMD_IN | CMD_VERIFY, CMD_INIT, (unsigned char *) &init_resp, sizeof (init_resp), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; memset (id_buf, 0, sizeof (id_buf)); memcpy (id_buf, init_resp.id, sizeof (id_buf) - 1); scanner_model = NULL; if (scanner_type != SCANNER_NONE) { unsigned int i; for (i = 0; i < sizeof (hp5590_models) / sizeof (struct hp5590_model); i++) { if (hp5590_models[i].scanner_type == scanner_type) { if (strcmp (id_buf, hp5590_models[i].vendor_id) != 0) { DBG (DBG_err, "%s: Vendor id mismatch for scanner HP%s - " "required '%s', got '%s'\n", __func__, hp5590_models[i].model, hp5590_models[i].vendor_id, id_buf); return SANE_STATUS_INVAL; } scanner_model = &hp5590_models[i]; break; } } hp5590_cmds_assert (scanner_model != NULL); } if (scanner_model) { DBG (DBG_cmds, "HP%s flags (0x%02x)\n", scanner_model->model, init_resp.flags); DBG (DBG_cmds, "HP%s flags: ADF %s, TMA %s, LCD %s\n", scanner_model->model, init_resp.flags & INIT_FLAG_ADF ? "yes" : "no", init_resp.flags & INIT_FLAG_TMA ? "yes" : "no", init_resp.flags & INIT_FLAG_LCD ? "yes" : "no"); memset (ver_buf, 0, sizeof (ver_buf)); memcpy (ver_buf, init_resp.version, sizeof (ver_buf) - 1); DBG (DBG_cmds, "HP%s firmware version: %s\n", scanner_model->model, ver_buf); DBG (DBG_cmds, "HP%s max resolution X: %u DPI\n", scanner_model->model, ntohs (init_resp.max_dpi_x)); DBG (DBG_cmds, "HP%s max resolution Y: %u DPI\n", scanner_model->model, ntohs (init_resp.max_dpi_y)); DBG (DBG_cmds, "HP%s max pixels X: %u\n", scanner_model->model, ntohs (init_resp.max_pixels_x)); DBG (DBG_cmds, "HP%s max pixels Y: %u\n", scanner_model->model, ntohs (init_resp.max_pixels_y)); DBG (DBG_cmds, "HP%s max size X: %.3f inches\n", scanner_model->model, ntohs (init_resp.max_pixels_x) * 1.0 / ntohs (init_resp.max_dpi_x)); DBG (DBG_cmds, "HP%s max size Y: %.3f inches\n", scanner_model->model, ntohs (init_resp.max_pixels_y) * 1.0 / ntohs (init_resp.max_dpi_y)); DBG (DBG_cmds, "HP%s normal motor param: %u, max motor param: %u\n", scanner_model->model, ntohs (init_resp.motor_param_normal), ntohs (init_resp.motor_param_max)); } if (info) { *info = malloc (sizeof (struct scanner_info)); if (!*info) { DBG (DBG_err, "Memory allocation failed\n"); return SANE_STATUS_NO_MEM; } memset (*info, 0, sizeof (struct scanner_info)); (*info)->max_dpi_x = ntohs (init_resp.max_dpi_x); (*info)->max_dpi_y = ntohs (init_resp.max_dpi_y); (*info)->max_pixels_x = ntohs (init_resp.max_pixels_x) - 1; (*info)->max_pixels_y = ntohs (init_resp.max_pixels_y) + 1; (*info)->max_size_x = (*info)->max_pixels_x * 1.0 / (*info)->max_dpi_x; (*info)->max_size_y = (*info)->max_pixels_y * 1.0 / (*info)->max_dpi_y; (*info)->features = FEATURE_NONE; if (init_resp.flags & INIT_FLAG_LCD) (*info)->features |= FEATURE_LCD; if (init_resp.flags & INIT_FLAG_ADF) (*info)->features |= FEATURE_ADF; if (init_resp.flags & INIT_FLAG_TMA) (*info)->features |= FEATURE_TMA; if (scanner_model) { (*info)->model = scanner_model->model; (*info)->kind = scanner_model->kind; } } ret = hp5590_get_status (dn, proto_flags); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: scanner reports non-zero status: %s\n", __func__, sane_strstatus (ret)); return ret; } DBG (DBG_cmds, "%s: scanner status OK\n", __func__); return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_read_eeprom (SANE_Int dn, enum proto_flags proto_flags, unsigned int addr, unsigned char *data, unsigned int size) { uint8_t eeprom_addr = addr; SANE_Status ret; hp5590_cmds_assert (data != NULL); hp5590_cmds_assert (sizeof (eeprom_addr) == 1); DBG (DBG_proc, "%s\n", __func__); DBG (DBG_proc, "Reading EEPROM: addr %04x, size %u\n", addr, size); ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_EEPROM_ADDR, (unsigned char *) &eeprom_addr, sizeof (eeprom_addr), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_cmd (dn, proto_flags, CMD_IN | CMD_VERIFY, CMD_EEPROM_READ, data, size, CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_write_eeprom (SANE_Int dn, enum proto_flags proto_flags, unsigned int addr, unsigned char *data, unsigned int size) { uint8_t eeprom_addr = addr; SANE_Status ret; hp5590_cmds_assert (data != NULL); hp5590_cmds_assert (sizeof (eeprom_addr) == 1); DBG (DBG_proc, "%s\n", __func__); DBG (DBG_proc, "Writing EEPROM: addr %04x, size: %u\n", addr, size); ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_EEPROM_ADDR, (unsigned char *) &eeprom_addr, sizeof (eeprom_addr), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_EEPROM_WRITE, data, size, CORE_DATA); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_read_scan_count (SANE_Int dn, enum proto_flags proto_flags, unsigned int *count) { uint32_t scan_count; SANE_Status ret; hp5590_cmds_assert (count != NULL); hp5590_cmds_assert (sizeof (scan_count) == 4); DBG (DBG_proc, "%s\n", __func__); DBG (DBG_proc, "Reading scan count\n"); ret = hp5590_read_eeprom (dn, proto_flags, 0x00, (unsigned char *) &scan_count, sizeof (scan_count)); if (ret != SANE_STATUS_GOOD) return ret; /* Host order */ *count = scan_count; DBG (DBG_proc, "Scan count %u\n", *count); return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_inc_scan_count (SANE_Int dn, enum proto_flags proto_flags) { uint32_t scan_count; unsigned int count; unsigned int new_count; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (scan_count) == 4); ret = hp5590_read_scan_count (dn, proto_flags, &count); if (ret != SANE_STATUS_GOOD) return ret; scan_count = ++count; ret = hp5590_write_eeprom (dn, proto_flags, 0x00, (unsigned char *) &scan_count, sizeof (scan_count)); if (ret != SANE_STATUS_GOOD) return ret; /* Verify its setting */ ret = hp5590_read_scan_count (dn, proto_flags, &new_count); if (ret != SANE_STATUS_GOOD) return ret; if (count != new_count) { DBG (DBG_err, "Scan count wasn't set\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_read_max_scan_count (SANE_Int dn, enum proto_flags proto_flags, unsigned int *max_count) { uint8_t max_scan_count[3]; SANE_Status ret; hp5590_cmds_assert (max_count != NULL); hp5590_cmds_assert (sizeof (max_scan_count) == 3); DBG (DBG_proc, "%s\n", __func__); DBG (DBG_proc, "Reading max scan count\n"); ret = hp5590_read_eeprom (dn, proto_flags, 0x10, (unsigned char *) max_scan_count, sizeof (max_scan_count)); if (ret != SANE_STATUS_GOOD) return ret; /* Host order */ *max_count = 0; memcpy (max_count, max_scan_count, sizeof (max_scan_count)); DBG (DBG_proc, "Max scan count %u\n", *max_count); return SANE_STATUS_GOOD; } /*************************************************************************** * * EEPROM contents: * * 0000: 6A 11 00 00 FF FF FF FF FF FF FF FF 09 0E 0F 00 j............... * 0010: 0C 13 0F 00 00 3A 00 FF FF FF 4E 35 39 45 54 52 ..........N59ETR * 0020: 31 52 4D 00 FF FF 00 16 00 0A 00 0D 00 11 00 10 1RM............. * 0030: FF FF FF FF FF FF FF FF FF 00 FF FF FF FF FF FF ................ * 0040: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 0050: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 0060: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 0070: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 0080: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 0090: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 00A0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 00B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 00C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 00D0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 00E0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ................ * 00F0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ............... * * Addr 0x00, len: 0x04 - scan count (little-endian) * Addr 0x1A, len: 0x0A - part number (w/o first 'CN' letters) * Addr 0x10, len: 0x03 - max scan count (little-endian) (0C 13 0F) * */ /******************************************************************************/ static __sane_unused__ SANE_Status hp5590_read_eeprom_all_cmd (SANE_Int dn, enum proto_flags proto_flags) { uint8_t eeprom[255]; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); ret = hp5590_read_eeprom (dn, proto_flags, 0x00, (unsigned char *) eeprom, sizeof (eeprom)); if (ret != SANE_STATUS_GOOD) return ret; /* FIXME: Debug output */ return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_read_part_number (SANE_Int dn, enum proto_flags proto_flags) { unsigned int part_number_len = PART_NUMBER_LEN; unsigned char part_number[PART_NUMBER_LEN + 1]; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); memset (part_number, 0, sizeof (part_number)); ret = hp5590_read_eeprom (dn, proto_flags, 0x1a, part_number, part_number_len); if (ret != SANE_STATUS_GOOD) return ret; DBG (DBG_cmds, "Part number: '%s'\n", part_number); return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_is_data_available (SANE_Int dn, enum proto_flags proto_flags) { uint8_t data_status; SANE_Status ret; SANE_Bool data_available; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (data_status) == 1); data_available = SANE_FALSE; ret = hp5590_cmd (dn, proto_flags, CMD_IN | CMD_VERIFY, CMD_DATA_STATUS, (unsigned char *) &data_status, sizeof (data_status), CORE_DATA); if (ret != SANE_STATUS_GOOD) return ret; DBG (DBG_cmds, "%s: Data status: %02x\n", __func__, data_status); if (data_status == 0x40) data_available = SANE_TRUE; DBG (DBG_cmds, "%s: Data is %s\n", __func__, data_available == SANE_TRUE ? "available" : "not available"); return data_available == SANE_TRUE ? SANE_STATUS_GOOD : SANE_STATUS_NO_DOCS; } /******************************************************************************/ static SANE_Status hp5590_stop_scan (SANE_Int dn, enum proto_flags proto_flags) { uint8_t reg_011b = 0x40; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (reg_011b) == 1); ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_STOP_SCAN, (unsigned char *) ®_011b, sizeof (reg_011b), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; /* FIXME */ return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_turnon_lamp (SANE_Int dn, enum proto_flags proto_flags, enum hp5590_lamp_state state) { struct lamp_state lamp_state; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (lamp_state) == 4); if (state == LAMP_STATE_TURNON) { /* Turn on lamp */ lamp_state.unk1 = 0x02; lamp_state.flag = 0x01; lamp_state.turnoff_time = htons (0x0a0a); DBG (DBG_cmds, "%s: turning lamp on\n", __func__); } if (state == LAMP_STATE_TURNOFF) { /* Turn off lamp */ lamp_state.unk1 = 0x02; lamp_state.flag = 0x02; lamp_state.turnoff_time = htons (0x0a0a); DBG (DBG_cmds, "%s: turning lamp off\n", __func__); } if (state == LAMP_STATE_SET_TURNOFF_TIME) { /* Turn on lamp */ lamp_state.unk1 = 0x02; lamp_state.flag = 0x03; lamp_state.turnoff_time = htons (0x0336); DBG (DBG_cmds, "%s: setting turnoff time\n", __func__); } if (state == LAMP_STATE_SET_TURNOFF_TIME_LONG) { /* Turn on lamp */ lamp_state.unk1 = 0x02; lamp_state.flag = 0x03; lamp_state.turnoff_time = htons (0x0f36); DBG (DBG_cmds, "%s: setting long turnoff time\n", __func__); } ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_CONTROL_LAMP, (unsigned char *) &lamp_state, sizeof (lamp_state), CORE_DATA); if (ret != SANE_STATUS_GOOD) return ret; if (state == LAMP_STATE_TURNON) { ret = hp5590_init_scanner (dn, proto_flags, NULL, SCANNER_NONE); if (ret != SANE_STATUS_GOOD) return ret; } return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_power_status (SANE_Int dn, enum proto_flags proto_flags) { struct power_resp power_resp; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (power_resp) == 3); ret = hp5590_cmd (dn, proto_flags, CMD_IN | CMD_VERIFY, CMD_POWER_STATUS, (unsigned char *) &power_resp, sizeof (power_resp), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; DBG (DBG_cmds, "Power status: %s (%02x)\n", power_resp.flags & POWER_FLAG_ON ? "on" : "off", power_resp.flags); if (!(power_resp.flags & POWER_FLAG_ON)) { DBG (DBG_cmds, "Turning lamp on\n"); ret = hp5590_turnon_lamp (dn, proto_flags, LAMP_STATE_TURNON); if (ret != SANE_STATUS_GOOD) return ret; } return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_read_error_code (SANE_Int dn, enum proto_flags proto_flags, unsigned int *adf_flags) { struct reg_03 reg_03; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (reg_03) == 3); hp5590_cmds_assert (adf_flags != NULL); memset (®_03, 0, sizeof (reg_03)); *adf_flags = 0; ret = hp5590_cmd (dn, proto_flags, CMD_IN, CMD_MISC_STATUS, (unsigned char *) ®_03, sizeof (reg_03), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; DBG (DBG_cmds, "%s: adf_flags: %04x\n", __func__, reg_03.adf_flags); DBG (DBG_cmds, "%s: unk1 : %04x\n", __func__, reg_03.unk1); DBG (DBG_cmds, "%s: unk2 : %04x\n", __func__, reg_03.unk2); *adf_flags = reg_03.adf_flags; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_reset_scan_head (SANE_Int dn, enum proto_flags proto_flags) { SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); ret = hp5590_turnon_lamp (dn, proto_flags, LAMP_STATE_TURNOFF); if (ret != SANE_STATUS_GOOD) return ret; usleep (100 * 1000); ret = hp5590_turnon_lamp (dn, proto_flags, LAMP_STATE_TURNON); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_select_source_and_wakeup (SANE_Int dn, enum proto_flags proto_flags, enum scan_sources source, SANE_Bool extend_lamp_timeout) { uint8_t reg_d6 = 0x04; SANE_Status ret; unsigned int adf_flags; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (reg_d6) == 1); if (source == SOURCE_TMA_SLIDES || source == SOURCE_TMA_NEGATIVES) { ret = hp5590_turnon_lamp (dn, proto_flags, LAMP_STATE_TURNOFF); if (ret != SANE_STATUS_GOOD) return ret; } else { ret = hp5590_turnon_lamp (dn, proto_flags, extend_lamp_timeout == SANE_TRUE ? LAMP_STATE_SET_TURNOFF_TIME_LONG : LAMP_STATE_SET_TURNOFF_TIME); if (ret != SANE_STATUS_GOOD) return ret; } switch (source) { case SOURCE_ADF: case SOURCE_ADF_DUPLEX: reg_d6 = 0x03; break; case SOURCE_FLATBED: reg_d6 = 0x04; break; case SOURCE_TMA_SLIDES: reg_d6 = 0x02; break; case SOURCE_TMA_NEGATIVES: reg_d6 = 0x01; break; case SOURCE_NONE: DBG (DBG_err, "Scan source not selected\n"); return SANE_STATUS_INVAL; default: DBG (DBG_err, "Unknown scan source: %u\n", source); return SANE_STATUS_INVAL; } DBG (DBG_cmds, "Scan source: %u\n", reg_d6); ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_SELECT_SOURCE, (unsigned char *) ®_d6, sizeof (reg_d6), CORE_NONE); if (ret != SANE_STATUS_GOOD && ret != SANE_STATUS_DEVICE_BUSY) return ret; ret = hp5590_read_error_code (dn, proto_flags, &adf_flags); if (ret != SANE_STATUS_GOOD) return ret; if (adf_flags & FLAG_ADF_EMPTY) { DBG (DBG_cmds, "ADF empty\n"); return SANE_STATUS_NO_DOCS; } return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_lock_unlock_scanner (SANE_Int dn, enum proto_flags proto_flags) { uint8_t reg_00 = 0x01; SANE_Status ret; unsigned int adf_flags; unsigned int waiting; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (reg_00) == 1); for (waiting = 0; waiting < WAKEUP_TIMEOUT; waiting++, sleep (1)) { ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_LOCK_UNLOCK, (unsigned char *) ®_00, sizeof (reg_00), CORE_NONE); if (ret == SANE_STATUS_GOOD) break; if (ret != SANE_STATUS_DEVICE_BUSY) return ret; DBG (DBG_cmds, "Waiting for scanner...\n"); ret = hp5590_read_error_code (dn, proto_flags, &adf_flags); if (ret != SANE_STATUS_GOOD) return ret; if (adf_flags & FLAG_ADF_EMPTY) { DBG (DBG_cmds, "ADF empty\n"); return SANE_STATUS_NO_DOCS; } } if (waiting == WAKEUP_TIMEOUT) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_set_base_dpi (SANE_Int dn, enum proto_flags proto_flags, struct scanner_info *scanner_info, unsigned int base_dpi) { uint16_t _base_dpi; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (scanner_info != NULL); hp5590_cmds_assert (base_dpi != 0); hp5590_cmds_assert (sizeof (_base_dpi) == 2); if (base_dpi > scanner_info->max_dpi_x || base_dpi > scanner_info->max_dpi_y) { DBG (DBG_err, "Base DPI too large " "(given: %u, max X DPI: %u, max Y DPI: %u)\n", base_dpi, scanner_info->max_dpi_x, scanner_info->max_dpi_y); return SANE_STATUS_INVAL; } _base_dpi = htons (base_dpi); ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_SET_BASE_DPI, (unsigned char *) &_base_dpi, sizeof (_base_dpi), CORE_DATA); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_set_color_map (SANE_Int dn, enum proto_flags proto_flags, unsigned int base_dpi) { struct color_map color_map; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (color_map) == 18); hp5590_cmds_assert (base_dpi != 0); memset (&color_map, 0, sizeof (color_map)); if (base_dpi < 2400) { color_map.color1[4] = 0x01; color_map.color2[4] = 0x01; color_map.color3[4] = 0x01; } else { color_map.color1[2] = 0xff; color_map.color1[3] = 0x01; color_map.color1[4] = 0x04; color_map.color1[5] = 0x02; color_map.color2[2] = 0xff; color_map.color2[3] = 0x01; color_map.color2[4] = 0x04; color_map.color2[5] = 0x02; color_map.color3[2] = 0xff; color_map.color3[3] = 0x01; color_map.color3[4] = 0x04; color_map.color3[5] = 0x02; } ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_SET_COLOR_MAP, (unsigned char *) &color_map, sizeof (color_map), CORE_DATA); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /****************************************************************************** * Calculate base DPI * Base DPI is what image dimensions are calculated on (top X,Y; bottom X,Y) * Calculated according the following rules: * Base DPI is 150 when 0 < DPI < 150; * Base DPI is 300 when 150 <= DPI <= 300; * Base DPI is 600 when 300 < DPI <= 600; * Base DPI is 1200 when 600 < DPI; */ static SANE_Status calc_base_dpi (unsigned int dpi, unsigned int *base_dpi) { DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (base_dpi != NULL); hp5590_cmds_assert (dpi != 0); *base_dpi = 0; if (dpi < 150) { *base_dpi = 150; return SANE_STATUS_GOOD; } if (dpi >= 150 && dpi <= 300) { *base_dpi = 300; return SANE_STATUS_GOOD; } if (dpi > 300 && dpi <= 600) { *base_dpi = 600; return SANE_STATUS_GOOD; } if (dpi > 600 && dpi <= 1200) { *base_dpi = 1200; return SANE_STATUS_GOOD; } if (dpi > 1200 && dpi <= 2400) { *base_dpi = 2400; return SANE_STATUS_GOOD; } DBG (DBG_err, "Error calculating base DPI (given DPI: %u)\n", dpi); return SANE_STATUS_INVAL; } /******************************************************************************/ static SANE_Status calc_scanner_dpi (unsigned int dpi, unsigned int *scanner_dpi) { DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (scanner_dpi != NULL); hp5590_cmds_assert (dpi != 0); if (dpi <= 100) { *scanner_dpi = 100; return SANE_STATUS_GOOD; } if (dpi > 100 && dpi <= 200) { *scanner_dpi = 200; return SANE_STATUS_GOOD; } if (dpi == 300) { *scanner_dpi = 300; return SANE_STATUS_GOOD; } if (dpi > 300 && dpi <= 600) { *scanner_dpi = 600; return SANE_STATUS_GOOD; } if (dpi > 600 && dpi <= 1200) { *scanner_dpi = 1200; return SANE_STATUS_GOOD; } if (dpi > 1200 && dpi <= 2400) { *scanner_dpi = 2400; return SANE_STATUS_GOOD; } DBG (DBG_err, "Error calculating scanner DPI (given DPI: %u)\n", dpi); return SANE_STATUS_INVAL; } /******************************************************************************/ static SANE_Status hp5590_calc_pixel_bits (unsigned int dpi, enum color_depths color_depth, unsigned int *pixel_bits) { unsigned int scanner_dpi; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (pixel_bits != NULL); hp5590_cmds_assert (dpi != 0); ret = calc_scanner_dpi (dpi, &scanner_dpi); if (ret != SANE_STATUS_GOOD) return ret; if (color_depth == DEPTH_COLOR_48) { *pixel_bits = 48; return SANE_STATUS_GOOD; } if (color_depth == DEPTH_COLOR_24) { *pixel_bits = 24; return SANE_STATUS_GOOD; } if (color_depth == DEPTH_GRAY) { *pixel_bits = 8; return SANE_STATUS_GOOD; } if (color_depth == DEPTH_BW) { if (dpi == scanner_dpi) *pixel_bits = 1; else *pixel_bits = 8; return SANE_STATUS_GOOD; } DBG (DBG_err, "Error calculating pixel bits (given DPI: %u)\n", dpi); return SANE_STATUS_INVAL; } /******************************************************************************/ static SANE_Status hp5590_set_scan_area (SANE_Int dn, enum proto_flags proto_flags, struct scanner_info *scanner_info, unsigned int top_x, unsigned int top_y, unsigned int width, unsigned int height, unsigned int dpi, enum color_depths color_depth, enum scan_modes scan_mode, enum scan_sources scan_source) { struct scan_params scan_params; unsigned int scanner_top_x; unsigned int scanner_top_y; unsigned int scanner_pixels_x; unsigned int scanner_pixels_y; unsigned int base_dpi; unsigned int scanner_dpi; unsigned int pixel_bits; unsigned int scanner_line_width; unsigned int max_pixels_x_current_dpi; unsigned int max_pixels_y_current_dpi; unsigned int pixels_x; unsigned int pixels_y; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (scan_params) == 37); hp5590_cmds_assert (dpi != 0); hp5590_cmds_assert (scanner_info != NULL); memset (&scan_params, 0, sizeof (scan_params)); scan_params.source = SCAN_PARAMS_SOURCE_SIMPLEX; if (scan_source == SOURCE_ADF) scan_params.source |= SCAN_PARAMS_SOURCE_ADF; if (scan_source == SOURCE_ADF_DUPLEX) scan_params.source |= SCAN_PARAMS_SOURCE_ADF | SCAN_PARAMS_SOURCE_DUPLEX; if (scan_source == SOURCE_FLATBED) scan_params.source |= SCAN_PARAMS_SOURCE_FLATBED; if (scan_source == SOURCE_TMA_SLIDES) scan_params.source |= SCAN_PARAMS_SOURCE_TMA_SLIDES; if (scan_source == SOURCE_TMA_NEGATIVES) scan_params.source |= SCAN_PARAMS_SOURCE_TMA_NEGATIVES; DBG (DBG_cmds, "Scan params. source : 0x%04x\n", scan_params.source); DBG (DBG_cmds, "DPI: %u\n", dpi); if (dpi > scanner_info->max_dpi_x || dpi > scanner_info->max_dpi_y) { DBG (DBG_err, "DPI too large " "(given: %u, max X DPI: %u, max Y DPI: %u)\n", dpi, scanner_info->max_dpi_x, scanner_info->max_dpi_y); return SANE_STATUS_INVAL; } ret = calc_base_dpi (dpi, &base_dpi); if (ret != SANE_STATUS_GOOD) return ret; DBG (DBG_cmds, "Base DPI: %u\n", base_dpi); ret = calc_scanner_dpi (dpi, &scanner_dpi); if (ret != SANE_STATUS_GOOD) return ret; DBG (DBG_cmds, "Scanner DPI: %u\n", scanner_dpi); scan_params.dpi_x = htons (scanner_dpi); scan_params.dpi_y = htons (scanner_dpi); DBG (DBG_cmds, "DPI X: 0x%04x\n", scanner_dpi); DBG (DBG_cmds, "DPI Y: 0x%04x\n", scanner_dpi); ret = hp5590_calc_pixel_bits (dpi, color_depth, &pixel_bits); if (ret != SANE_STATUS_GOOD) return ret; DBG (DBG_cmds, "Pixel bits: %u\n", pixel_bits); scan_params.pixel_bits = pixel_bits; scan_params.bw_gray_flag = 0; if (color_depth == DEPTH_BW || color_depth == DEPTH_GRAY) scan_params.bw_gray_flag = htons (0x40); scan_params.flags = htons (0xe840); if (dpi > 300 && dpi <= 1200) scan_params.flags = htons (0xc840); if (dpi > 1200) scan_params.flags = htons (0xc040); scan_params.motor_param1 = htons (100); scan_params.motor_param2 = htons (100); scan_params.motor_param3 = htons (100); if (scan_source == SOURCE_TMA_NEGATIVES) { scan_params.motor_param2 = htons (200); scan_params.motor_param3 = htons (400); } scan_params.unk1 = htons (0x80); scan_params.mode = 0; if (scan_mode == MODE_PREVIEW) scan_params.mode = 0x04; max_pixels_x_current_dpi = (float) scanner_info->max_size_x * dpi; max_pixels_y_current_dpi = (float) scanner_info->max_size_y * dpi; if ( scan_source == SOURCE_TMA_NEGATIVES || scan_source == SOURCE_TMA_SLIDES) { max_pixels_x_current_dpi = (float) (TMA_MAX_X_INCHES * dpi); max_pixels_y_current_dpi = (float) (TMA_MAX_Y_INCHES * dpi); } /* In ADF mode the device can scan up to ADF_MAX_Y_INCHES, which is usually * bigger than what scanner reports back during initialization */ if ( scan_source == SOURCE_ADF ) max_pixels_y_current_dpi = (float) (ADF_MAX_Y_INCHES * dpi); /* Allow two times of max pixels for ADF Duplex mode */ if (scan_source == SOURCE_ADF_DUPLEX) max_pixels_y_current_dpi *= 2; pixels_x = width; pixels_y = height; scanner_top_x = (float) (top_x * (1.0 * base_dpi / dpi)); scanner_top_y = (float) (top_y * (1.0 * base_dpi / dpi)); scanner_pixels_x = (float) (pixels_x * (1.0 * base_dpi / dpi)); scanner_pixels_y = (float) (pixels_y * (1.0 * base_dpi / dpi)); DBG (DBG_cmds, "Top X: %u, top Y: %u, size X: %u, size Y: %u\n", top_x, top_y, pixels_x, pixels_y); DBG (DBG_cmds, "Scanner top X: %u, top Y: %u, size X: %u, size Y: %u\n", scanner_top_x, scanner_top_y, scanner_pixels_x, scanner_pixels_y); if (top_x + pixels_x > max_pixels_x_current_dpi) { DBG (DBG_err, "Top X (%u) + pixels X (%u) exceeds max X %u\n", top_x, pixels_x, max_pixels_x_current_dpi); return SANE_STATUS_INVAL; } if (top_y + pixels_y > max_pixels_y_current_dpi) { DBG (DBG_err, "Top Y (%u) + pixels Y (%u) exceeds max Y %u\n", top_y, pixels_y, max_pixels_y_current_dpi); return SANE_STATUS_INVAL; } scan_params.top_x = htons (scanner_top_x); scan_params.top_y = htons (scanner_top_y); scan_params.size_x = htons (scanner_pixels_x); scan_params.size_y = htons (scanner_pixels_y); scanner_line_width = (float) (pixels_x * (1.0 * scanner_dpi / dpi) / 8 * pixel_bits); /* Scanner hangs at scan command if line width less than 18 */ if (scanner_line_width < 18) { DBG (DBG_err, "Line width too smal, extending to minimum\n"); scanner_line_width = 18; } scan_params.line_width = htons (scanner_line_width); DBG (DBG_cmds, "Line width: %u\n", scanner_line_width); ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_SET_SCAN_PARAMS, (unsigned char *) &scan_params, sizeof (scan_params), CORE_DATA); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_read_image_params (SANE_Int dn, enum proto_flags proto_flags) { struct image_params image_params; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (image_params) == 16); memset (&image_params, 0, sizeof (image_params)); ret = hp5590_cmd (dn, proto_flags, CMD_IN | CMD_VERIFY, CMD_GET_IMAGE_PARAMS, (unsigned char *) &image_params, sizeof (image_params), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; if (image_params.signature != 0xc0) { DBG (DBG_err, "Wrong signature for image parameters structure " "received (needed 0xc0, got %02x)\n", image_params.signature); return SANE_STATUS_IO_ERROR; } DBG (DBG_cmds, "Received image params:\n"); DBG (DBG_cmds, "Signature %02x\n", image_params.signature); DBG (DBG_cmds, "Image size %lu (%04lx)\n", (unsigned long) ntohl (image_params.image_size), (unsigned long) ntohl (image_params.image_size)); DBG (DBG_cmds, "Line width: %u (%02x)\n", ntohs (image_params.line_width), ntohs (image_params.line_width)); DBG (DBG_cmds, "Actual size Y: %u (%02x)\n", ntohs (image_params.real_size_y), ntohs (image_params.real_size_y)); return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_set_scan_params (SANE_Int dn, enum proto_flags proto_flags, struct scanner_info * scanner_info, unsigned int top_x, unsigned int top_y, unsigned int width, unsigned int height, unsigned int dpi, enum color_depths color_depth, enum scan_modes scan_mode, enum scan_sources scan_source) { unsigned int base_dpi; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (scanner_info != NULL); hp5590_cmds_assert (dpi != 0); /* Lock scanner */ ret = hp5590_lock_unlock_scanner (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; /* Set base DPI */ ret = calc_base_dpi (dpi, &base_dpi); if (ret != SANE_STATUS_GOOD) { /* Unlock scanner */ hp5590_lock_unlock_scanner (dn, proto_flags); return ret; } DBG (DBG_cmds, "Set base DPI: %u\n", base_dpi); ret = hp5590_set_base_dpi (dn, proto_flags, scanner_info, base_dpi); if (ret != SANE_STATUS_GOOD) { /* Unlock scanner */ hp5590_lock_unlock_scanner (dn, proto_flags); return ret; } /* Set color map */ ret = hp5590_set_color_map (dn, proto_flags, base_dpi); if (ret != SANE_STATUS_GOOD) { /* Unlock scanner */ hp5590_lock_unlock_scanner (dn, proto_flags); return ret; } ret = hp5590_set_scan_area (dn, proto_flags, scanner_info, top_x, top_y, width, height, dpi, color_depth, scan_mode, scan_source); if (ret != SANE_STATUS_GOOD) { /* Unlock scanner */ hp5590_lock_unlock_scanner (dn, proto_flags); return ret; } ret = hp5590_read_image_params (dn, proto_flags); if (ret != SANE_STATUS_GOOD) { /* Unlock scanner */ hp5590_lock_unlock_scanner (dn, proto_flags); return ret; } /* Unlock scanner */ ret = hp5590_lock_unlock_scanner (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_send_reverse_calibration_map (SANE_Int dn, enum proto_flags proto_flags) { unsigned int reverse_map_size = REVERSE_MAP_LEN; uint16_t reverse_map[REVERSE_MAP_LEN]; unsigned int i; uint16_t val; unsigned int len; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); DBG (DBG_proc, "Preparing reverse calibration map\n"); val = 0xffff; len = reverse_map_size / 4; for (i = 0; i < len; i++) { reverse_map[i] = htons (val); val -= 1; } for (i = len; i < len * 2; i++) { reverse_map[i] = htons (val); val -= 1; } for (i = len * 2; i < len * 3; i++) { reverse_map[i] = htons (val); val -= 1; } for (i = len * 3; i < len * 4; i++) { reverse_map[i] = htons (0xffff); } DBG (DBG_proc, "Done preparing reverse calibration map\n"); ret = hp5590_bulk_write (dn, proto_flags, 0x2b, (unsigned char *) reverse_map, reverse_map_size * sizeof (uint16_t)); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_send_forward_calibration_maps (SANE_Int dn, enum proto_flags proto_flags) { unsigned int forward_map_size = FORWARD_MAP_LEN; uint16_t forward_map[FORWARD_MAP_LEN]; SANE_Status ret; unsigned int i; uint16_t val; DBG (DBG_proc, "%s\n", __func__); DBG (DBG_proc, "Preparing forward calibration map\n"); val = 0x0000; for (i = 0; i < forward_map_size; i++) { forward_map[i] = htons (val); if (val < 0xffff) val += 1; } DBG (DBG_proc, "Done preparing forward calibration map\n"); ret = hp5590_bulk_write (dn, proto_flags, 0x012a, (unsigned char *) forward_map, forward_map_size * sizeof (uint16_t)); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_bulk_write (dn, proto_flags, 0x022a, (unsigned char *) forward_map, forward_map_size * sizeof (uint16_t)); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_bulk_write (dn, proto_flags, 0x032a, (unsigned char *) forward_map, forward_map_size * sizeof (uint16_t)); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_read (SANE_Int dn, enum proto_flags proto_flags, unsigned char *bytes, unsigned int size, void *state) { SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (bytes != NULL); hp5590_cmds_assert (state != NULL); ret = hp5590_bulk_read (dn, proto_flags, bytes, size, state); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_start_scan (SANE_Int dn, enum proto_flags proto_flags) { uint8_t reg_051b = 0x40; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (sizeof (reg_051b) == 1); ret = hp5590_cmd (dn, proto_flags, CMD_VERIFY, CMD_START_SCAN, (unsigned char *) ®_051b, sizeof (reg_051b), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status hp5590_read_buttons (SANE_Int dn, enum proto_flags proto_flags, enum button_status * status) { uint16_t button_status; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); hp5590_cmds_assert (status != NULL); hp5590_cmds_assert (sizeof (button_status) == 2); ret = hp5590_cmd (dn, proto_flags, CMD_IN | CMD_VERIFY, CMD_BUTTON_STATUS, (unsigned char *) &button_status, sizeof (button_status), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; *status = BUTTON_NONE; /* Network order */ button_status = ntohs (button_status); DBG (DBG_cmds, "Button status: %04x\n", button_status); DBG (DBG_cmds, "Power: %s, Scan: %s, Collect: %s, File: %s, Email: %s, Copy: %s, " "Up: %s, Down: %s, Mode: %s, Cancel: %s\n", button_status & BUTTON_FLAG_POWER ? " on" : "off", button_status & BUTTON_FLAG_SCAN ? " on" : "off", button_status & BUTTON_FLAG_COLLECT ? " on" : "off", button_status & BUTTON_FLAG_FILE ? " on" : "off", button_status & BUTTON_FLAG_EMAIL ? " on" : "off", button_status & BUTTON_FLAG_COPY ? " on" : "off", button_status & BUTTON_FLAG_UP ? " on" : "off", button_status & BUTTON_FLAG_DOWN ? " on" : "off", button_status & BUTTON_FLAG_MODE ? " on" : "off", button_status & BUTTON_FLAG_CANCEL ? " on" : "off"); if (button_status & BUTTON_FLAG_POWER) *status = BUTTON_POWER; if (button_status & BUTTON_FLAG_SCAN) *status = BUTTON_SCAN; if (button_status & BUTTON_FLAG_COLLECT) *status = BUTTON_COLLECT; if (button_status & BUTTON_FLAG_FILE) *status = BUTTON_FILE; if (button_status & BUTTON_FLAG_EMAIL) *status = BUTTON_EMAIL; if (button_status & BUTTON_FLAG_COPY) *status = BUTTON_COPY; if (button_status & BUTTON_FLAG_UP) *status = BUTTON_UP; if (button_status & BUTTON_FLAG_DOWN) *status = BUTTON_DOWN; if (button_status & BUTTON_FLAG_MODE) *status = BUTTON_MODE; if (button_status & BUTTON_FLAG_CANCEL) *status = BUTTON_CANCEL; return SANE_STATUS_GOOD; } /* SET SCAN PARAMETERS ==================== 50 ======================= BW 50 (425 x 585) 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 03 50 BW 50 reduced top left (261 x 469) 18 00 64 00 64 00 00 00 00 03 0c 05 7f 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 02 08 BW 50 reduced top right (302 x 498) 18 00 64 00 64 01 6e 00 00 03 8a 05 d6 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 02 5c BW 50 X 0, small width (16 x 585) 18 00 64 00 64 00 00 00 00 00 30 06 db 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 00 20 BW 50 X large, small width (24 x 585) 18 00 64 00 64 04 b0 00 00 00 48 06 db 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 00 30 BW 50 Y 0, small height (425 x 21) 18 00 64 00 64 00 00 00 00 04 f8 00 3f 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 03 50 BW 50 Y large, small height (425 x 21) 18 00 64 00 64 00 00 06 99 04 f8 00 3f 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 03 50 GRAY 50 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 03 50 COLOR 50 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 09 f0 ==================== 75 ======================= BW 75 18 00 64 00 64 00 00 00 00 04 f8 06 da 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 03 50 GRAY 75 18 00 64 00 64 00 00 00 00 04 f8 06 da 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 03 50 COLOR 75 18 00 64 00 64 00 00 00 00 04 f8 06 da 00 80 00 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 09 f0 COLOR 75 48 bit 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 04 00 00 13 e0 =================== 100 ======================= BW 100 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00 40 01 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 00 6a GRAY 100 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 03 50 COLOR 100 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 09 f0 COLOR 100 48bit, preview 18 00 64 00 64 00 00 00 00 04 f8 06 db 00 80 00 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 04 00 00 13 e0 COLOR 100 48bit 18 00 64 00 64 00 00 00 00 04 f2 06 db 00 80 00 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 13 c8 COLOR 100 48bit, TMA negatives 11 00 64 00 64 00 00 00 00 00 fc 03 84 00 80 00 00 30 e8 40 00 64 00 c8 01 90 00 00 00 00 00 00 00 00 00 03 f0 COLOR 100 48bit, TMA slides 12 00 64 00 64 00 00 00 00 00 fc 03 84 00 80 00 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 03 f0 =================== 150 ======================= BW 150 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 06 a4 GRAY 150 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 06 a4 COLOR 150 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 13 ec COLOR 150 48 bit 18 00 c8 00 c8 00 00 00 00 09 ea 0d b6 00 80 00 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 27 a8 =================== 200 ======================= BW 200 18 00 c8 00 c8 00 00 00 00 09 f0 0d b6 00 80 00 40 01 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 00 d4 GRAY 200 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 06 a4 COLOR 200 18 00 c8 00 c8 00 00 00 00 09 f6 0d b6 00 80 00 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 13 ec COLOR 200 48 bit 18 00 c8 00 c8 00 00 00 00 09 f6 0d aa 00 80 00 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 27 d8 =================== 300 ======================= BW 300 18 01 2c 01 2c 00 00 00 00 09 f0 0d b6 00 80 00 40 01 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 01 3e GRAY 300 18 01 2c 01 2c 00 00 00 00 09 f4 0d b6 00 80 00 40 08 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 09 f4 COLOR 300 18 01 2c 01 2c 00 00 00 00 09 f4 0d b6 00 80 00 00 18 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 1d dc COLOR 300 48bit, TMA negatives 11 01 2c 01 2c 00 00 00 06 01 fc 07 02 00 80 00 00 30 e8 40 00 64 00 c8 01 90 00 00 00 00 00 00 00 00 00 0b e8 COLOR 300 48bit, TMA slides 12 01 2c 01 2c 00 00 00 00 01 fc 07 08 00 80 00 00 30 e8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 0b e8 ==================== 400 ====================== BW 400 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00 40 08 c8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 13 ec GRAY 400 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00 40 08 c8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 13 ec COLOR 400 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00 00 18 c8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 3b c4 ==================== 600 ====================== BW 600 18 02 58 02 58 00 00 00 00 13 e8 1b 6c 00 80 00 40 01 c8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 02 7d GRAY 600 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00 40 08 c8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 13 ec COLOR 600 18 02 58 02 58 00 00 00 00 13 ec 1b 6c 00 80 00 00 18 c8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 3b c4 ==================== 1200 ===================== BW 1200 18 04 b0 04 b0 00 00 00 00 27 a8 36 d8 00 80 00 40 01 c8 40 00 64 00 64 00 64 00 00 00 00 00 00 00 00 00 04 f5 */ /* READ SCAN PARAMETERS ====================== 50 ===================== BW 50 c0 00 00 0f 23 a0 00 00 03 50 04 92 00 00 00 00 GRAY 50 c0 00 00 0f 23 a0 00 00 03 50 04 92 00 00 00 00 COLOR 50 c0 00 00 2d 6a e0 00 00 09 f0 04 92 00 00 00 00 ====================== 75 ===================== BW 75 c0 00 00 0f 20 50 00 00 03 50 04 91 00 00 00 00 GRAY 75 c0 00 00 0f 20 50 00 00 03 50 04 91 00 00 00 00 COLOR 75 c0 00 00 2d 60 f0 00 00 09 f0 04 91 00 00 00 00 COLOR 75 48 bit c0 00 00 5a 86 40 00 00 13 e0 04 8e 00 00 00 00 ===================== 100 ===================== BW 100 c0 00 00 01 e4 74 00 00 00 6a 04 92 00 00 00 00 GRAY 100 c0 00 00 0f 23 a0 00 00 03 50 04 92 00 00 00 00 COLOR 100 c0 00 00 2d 6a e0 00 00 09 f0 04 92 00 00 00 00 COLOR 100, 48 bit preview c0 00 00 5a d5 c0 00 00 13 e0 04 92 00 00 00 00 COLOR 100, 48 bit c0 00 00 5a 68 10 00 00 13 c8 04 92 00 00 00 00 ===================== 150 ===================== BW 150 c0 00 00 3c b3 10 00 00 06 a4 09 24 00 00 00 00 GRAY 150 c0 00 00 3c b3 10 00 00 06 a4 09 24 00 00 00 00 COLOR 150 c0 00 00 b6 19 30 00 00 13 ec 09 24 00 00 00 00 COLOR 150 48bit c0 00 01 6a 7b a0 00 00 27 a8 09 24 00 00 00 00 ===================== 200 ===================== BW 200 c0 00 00 07 91 d0 00 00 00 d4 09 24 00 00 00 00 GRAY 200 c0 00 00 3c b3 10 00 00 06 a4 09 24 00 00 00 00 COLOR 200 c0 00 00 b6 19 30 00 00 13 ec 09 24 00 00 00 00 COLOR 200 48 bit c0 00 01 6a f3 a0 00 00 27 d8 09 1c 00 00 00 00 ===================== 300 ===================== BW 300 c0 00 00 11 08 14 00 00 01 3e 0d b6 00 00 00 00 GRAY 300 c0 00 00 88 77 78 00 00 09 f4 0d b6 00 00 00 00 COLOR 300 c0 00 01 99 66 68 00 00 1d dc 0d b6 00 00 00 00 ===================== 400 ===================== BW 400 c0 00 02 22 4b 90 00 00 13 ec 1b 6c 00 00 00 00 GRAY 400 c0 00 02 22 4b 90 00 00 13 ec 1b 6c 00 00 00 00 COLOR 400 c0 00 06 66 e2 b0 00 00 3b c4 1b 6c 00 00 00 00 ===================== 600 ===================== BW 600 c0 00 00 44 3b bc 00 00 02 7d 1b 6c 00 00 00 00 GRAY 600 c0 00 02 22 4b 90 00 00 13 ec 1b 6c 00 00 00 00 COLOR 600 c0 00 06 66 e2 b0 00 00 3b c4 1b 6c 00 00 00 00 */ /* vim: sw=2 ts=8 */ sane-backends-1.0.27/backend/hp5400_sanei.h0000664000175000017500000001012512112021330015041 00000000000000#ifndef _HP5400_SANEI_H_ #define _HP5400_SANEI_H_ /* sane - Scanner Access Now Easy. Copyright (C) 2003 Martijn van Oosterhout Copyright (C) 2003 Thomas Soumarmon Copyright (c) 2003 Henning Meier-Geinitz, Originally copied from HP3300 testtools. Original notice follows: Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Transport layer for communication with HP5400/5470 scanner. Implementation using sanei_usb Additions to support bulk data transport. Added debugging info - 19/02/2003 Martijn Changed to use sanei_usb instead of direct /dev/usb/scanner access - 15/04/2003 Henning */ #define CMD_INITBULK1 0x0087 /* send 0x14 */ #define CMD_INITBULK2 0x0083 /* send 0x24 */ #define CMD_INITBULK3 0x0082 /* transfer length 0xf000 */ HP5400_SANE_STATIC void _UsbWriteControl (int fd, int iValue, int iIndex, void *pabData, int iSize); HP5400_SANE_STATIC void hp5400_command_write_noverify (int fd, int iValue, void *pabData, int iSize); HP5400_SANE_STATIC void _UsbReadControl (int fd, int iValue, int iIndex, void *pabData, int iSize); HP5400_SANE_STATIC int hp5400_open (const char *filename); HP5400_SANE_STATIC void hp5400_close (int iHandle); /* returns value > 0 if verify ok */ HP5400_SANE_STATIC int hp5400_command_verify (int iHandle, int iCmd); /* returns > 0 if command OK */ HP5400_SANE_STATIC int hp5400_command_read_noverify (int iHandle, int iCmd, int iLen, void *pbData); /* returns > 0 if command OK */ HP5400_SANE_STATIC int hp5400_command_read (int iHandle, int iCmd, int iLen, void *pbData); /* returns >0 if command OK */ HP5400_SANE_STATIC int hp5400_command_write (int iHandle, int iCmd, int iLen, void *pbData); #ifdef STANDALONE /* returns >0 if command OK */ HP5400_SANE_STATIC int hp5400_bulk_read (int iHandle, size_t len, int block, FILE * file); #endif /* returns >0 if command OK */ HP5400_SANE_STATIC int hp5400_bulk_read_block (int iHandle, int iCmd, void *cmd, int cmdlen, void *buffer, int len); /* returns >0 if command OK */ HP5400_SANE_STATIC int hp5400_bulk_command_write (int iHandle, int iCmd, void *cmd, int cmdlen, int datalen, int block, char *data); /** ScannerIsOn retrieve on/off status from scanner @return 1 if is on 0 if is off -1 if is not reachable */ HP5400_SANE_STATIC int hp5400_isOn (int iHandle); #endif sane-backends-1.0.27/backend/canon630u.c0000664000175000017500000006253012775312260014504 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002, Nathan Rutman Copyright (C) 2001, Marcio Luis Teixeira Parts copyright (C) 1996, 1997 Andreas Beck Parts copyright (C) 2000, 2001 Michael Herder Parts copyright (C) 2001 Henning Meier-Geinitz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #define BUILD 1 #define MM_IN_INCH 25.4 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_usb.h" #define BACKEND_NAME canon630u #define CANONUSB_CONFIG_FILE "canon630u.conf" #include "../include/sane/sanei_backend.h" #include "canon630u-common.c" typedef struct Canon_Device { struct Canon_Device *next; SANE_String name; SANE_Device sane; } Canon_Device; typedef struct Canon_Scanner { struct Canon_Scanner *next; Canon_Device *device; CANON_Handle scan; } Canon_Scanner; static int num_devices = 0; static const SANE_Device **devlist = NULL; static Canon_Device *first_dev = NULL; static Canon_Scanner *first_handle = NULL; static SANE_Parameters parms = { SANE_FRAME_RGB, 0, 0, /* Number of bytes returned per scan line: */ 0, /* Number of pixels per scan line. */ 0, /* Number of lines for the current scan. */ 8 /* Number of bits per sample. */ }; struct _SANE_Option { SANE_Option_Descriptor *descriptor; SANE_Status (*callback) (struct _SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info); }; typedef struct _SANE_Option SANE_Option; /*-----------------------------------------------------------------*/ static SANE_Word getNumberOfOptions (void); /* Forward declaration */ /* This read-only option returns the number of options available for the device. It should be the first option in the options array declared below. */ static SANE_Option_Descriptor optionNumOptionsDescriptor = { SANE_NAME_NUM_OPTIONS, SANE_TITLE_NUM_OPTIONS, SANE_DESC_NUM_OPTIONS, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Status optionNumOptionsCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { option = option; handle = handle; info = info; /* Eliminate warning about unused parameters */ if (action != SANE_ACTION_GET_VALUE) return SANE_STATUS_INVAL; *(SANE_Word *) value = getNumberOfOptions (); return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* This option lets the user force scanner calibration. Normally, this is done only once, at first scan after powerup. */ static SANE_Word optionCalibrateValue = SANE_FALSE; static SANE_Option_Descriptor optionCalibrateDescriptor = { "cal", SANE_I18N ("Calibrate Scanner"), SANE_I18N ("Force scanner calibration before scan"), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Status optionCalibrateCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { handle = handle; option = option; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: *info |= SANE_INFO_RELOAD_PARAMS; optionCalibrateValue = *(SANE_Bool *) value; break; case SANE_ACTION_GET_VALUE: *(SANE_Word *) value = optionCalibrateValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* This option lets the user select the scan resolution. The Canon fb630u scanner supports the following resolutions: 75, 150, 300, 600, 1200 */ static const SANE_Word optionResolutionList[] = { 4, /* Number of elements */ 75, 150, 300, 600 /* Resolution list */ /* also 600x1200, but ignore that for now. */ }; static SANE_Option_Descriptor optionResolutionDescriptor = { SANE_NAME_SCAN_RESOLUTION, SANE_TITLE_SCAN_RESOLUTION, SANE_DESC_SCAN_RESOLUTION, SANE_TYPE_INT, SANE_UNIT_DPI, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC, SANE_CONSTRAINT_WORD_LIST, {(const SANE_String_Const *) optionResolutionList} }; static SANE_Word optionResolutionValue = 75; static SANE_Status optionResolutionCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { SANE_Status status; SANE_Word autoValue = 75; handle = handle; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: status = sanei_constrain_value (option->descriptor, (void *) &autoValue, info); if (status != SANE_STATUS_GOOD) return status; optionResolutionValue = autoValue; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_SET_VALUE: *info |= SANE_INFO_RELOAD_PARAMS; optionResolutionValue = *(SANE_Word *) value; break; case SANE_ACTION_GET_VALUE: *(SANE_Word *) value = optionResolutionValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ #ifdef GRAY /* This option lets the user select a gray scale scan */ static SANE_Word optionGrayscaleValue = SANE_FALSE; static SANE_Option_Descriptor optionGrayscaleDescriptor = { "gray", SANE_I18N ("Grayscale scan"), SANE_I18N ("Do a grayscale rather than color scan"), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Status optionGrayscaleCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { handle = handle; option = option; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: *info |= SANE_INFO_RELOAD_PARAMS; optionGrayscaleValue = *(SANE_Bool *) value; break; case SANE_ACTION_GET_VALUE: *(SANE_Word *) value = optionGrayscaleValue; break; } return SANE_STATUS_GOOD; } #endif /* GRAY */ /*-----------------------------------------------------------------*/ /* Analog Gain setting */ static const SANE_Range aGainRange = { 0, /* minimum */ 64, /* maximum */ 1 /* quantization */ }; static SANE_Int optionAGainValue = 1; static SANE_Option_Descriptor optionAGainDescriptor = { "gain", SANE_I18N ("Analog Gain"), SANE_I18N ("Increase or decrease the analog gain of the CCD array"), SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Int), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) &aGainRange} }; static SANE_Status optionAGainCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { option = option; handle = handle; info = info; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionAGainValue = *(SANE_Int *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Int *) value = optionAGainValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* Scanner gamma setting */ static SANE_Fixed optionGammaValue = SANE_FIX (1.6); static SANE_Option_Descriptor optionGammaDescriptor = { "gamma", SANE_I18N ("Gamma Correction"), SANE_I18N ("Selects the gamma corrected transfer curve"), SANE_TYPE_FIXED, SANE_UNIT_NONE, sizeof (SANE_Int), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Status optionGammaCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { option = option; handle = handle; info = info; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionGammaValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionGammaValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* Scan range */ static const SANE_Range widthRange = { 0, /* minimum */ SANE_FIX (CANON_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */ 0 /* quantization */ }; static const SANE_Range heightRange = { 0, /* minimum */ SANE_FIX (CANON_MAX_HEIGHT * MM_IN_INCH / 600), /* maximum */ 0 /* quantization */ }; /*-----------------------------------------------------------------*/ /* This option controls the top-left-x corner of the scan */ static SANE_Fixed optionTopLeftXValue = 0; static SANE_Option_Descriptor optionTopLeftXDescriptor = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Fixed), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) &widthRange} }; static SANE_Status optionTopLeftXCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { option = option; handle = handle; value = value; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionTopLeftXValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionTopLeftXValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* This option controls the top-left-y corner of the scan */ static SANE_Fixed optionTopLeftYValue = 0; static SANE_Option_Descriptor optionTopLeftYDescriptor = { SANE_NAME_SCAN_TL_Y, SANE_TITLE_SCAN_TL_Y, SANE_DESC_SCAN_TL_Y, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Fixed), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) &heightRange} }; static SANE_Status optionTopLeftYCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { /* Eliminate warnings about unused parameters */ option = option; handle = handle; switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionTopLeftYValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionTopLeftYValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* This option controls the bot-right-x corner of the scan Default to 215.9mm, max. */ static SANE_Fixed optionBotRightXValue = SANE_FIX (215.9); static SANE_Option_Descriptor optionBotRightXDescriptor = { SANE_NAME_SCAN_BR_X, SANE_TITLE_SCAN_BR_X, SANE_DESC_SCAN_BR_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Fixed), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) &widthRange} }; static SANE_Status optionBotRightXCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { /* Eliminate warnings about unused parameters */ option = option; handle = handle; switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionBotRightXValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionBotRightXValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* This option controls the bot-right-y corner of the scan Default to 296.3mm, max */ static SANE_Fixed optionBotRightYValue = SANE_FIX (296.3); static SANE_Option_Descriptor optionBotRightYDescriptor = { SANE_NAME_SCAN_BR_Y, SANE_TITLE_SCAN_BR_Y, SANE_DESC_SCAN_BR_Y, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Fixed), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) &heightRange} }; static SANE_Status optionBotRightYCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { /* Eliminate warnings about unused parameters */ option = option; handle = handle; switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionBotRightYValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionBotRightYValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* The following array binds the option descriptors to their respective callback routines */ static SANE_Option so[] = { {&optionNumOptionsDescriptor, optionNumOptionsCallback}, {&optionResolutionDescriptor, optionResolutionCallback}, {&optionCalibrateDescriptor, optionCalibrateCallback}, #ifdef GRAY {&optionGrayscaleDescriptor, optionGrayscaleCallback}, #endif {&optionAGainDescriptor, optionAGainCallback}, {&optionGammaDescriptor, optionGammaCallback}, {&optionTopLeftXDescriptor, optionTopLeftXCallback}, {&optionTopLeftYDescriptor, optionTopLeftYCallback}, {&optionBotRightXDescriptor, optionBotRightXCallback}, {&optionBotRightYDescriptor, optionBotRightYCallback} }; static SANE_Word getNumberOfOptions (void) { return NELEMS (so); } /* This routine dispatches the control message to the appropriate callback routine, it outght to be called by sane_control_option after any driver specific validation. */ static SANE_Status dispatch_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { SANE_Option *op = so + option; SANE_Int myinfo = 0; SANE_Status status = SANE_STATUS_GOOD; if (option < 0 || option >= NELEMS (so)) return SANE_STATUS_INVAL; /* Unknown option ... */ if ((action == SANE_ACTION_SET_VALUE) && ((op->descriptor->cap & SANE_CAP_SOFT_SELECT) == 0)) return SANE_STATUS_INVAL; if ((action == SANE_ACTION_GET_VALUE) && ((op->descriptor->cap & SANE_CAP_SOFT_DETECT) == 0)) return SANE_STATUS_INVAL; if ((action == SANE_ACTION_SET_AUTO) && ((op->descriptor->cap & SANE_CAP_AUTOMATIC) == 0)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_SET_VALUE) { status = sanei_constrain_value (op->descriptor, value, &myinfo); if (status != SANE_STATUS_GOOD) return status; } status = (op->callback) (op, handle, action, value, &myinfo); if (info) *info = myinfo; return status; } static SANE_Status attach_scanner (const char *devicename, Canon_Device ** devp) { CANON_Handle scan; Canon_Device *dev; SANE_Status status; DBG (3, "attach_scanner: %s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } } dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, '\0', sizeof (Canon_Device)); /* clear structure */ DBG (4, "attach_scanner: opening %s\n", devicename); status = CANON_open_device (&scan, devicename); if (status != SANE_STATUS_GOOD) { DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename); free (dev); return status; } dev->name = strdup (devicename); dev->sane.name = dev->name; dev->sane.vendor = "CANON"; dev->sane.model = CANON_get_device_name (&scan); dev->sane.type = "flatbed scanner"; CANON_close_device (&scan); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } /* callback function for sanei_usb_attach_matching_devices */ static SANE_Status attach_one (const char *name) { attach_scanner (name, 0); return SANE_STATUS_GOOD; } /* Find our devices */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char config_line[PATH_MAX]; size_t len; FILE *fp; DBG_INIT (); #if 0 DBG_LEVEL = 10; #endif DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); DBG (1, "sane_init: SANE Canon630u backend version %d.%d.%d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); sanei_usb_init (); fp = sanei_config_open (CANONUSB_CONFIG_FILE); if (!fp) { /* no config-file: try these */ attach_scanner ("/dev/scanner", 0); attach_scanner ("/dev/usbscanner", 0); attach_scanner ("/dev/usb/scanner", 0); return SANE_STATUS_GOOD; } DBG (3, "reading configure file %s\n", CANONUSB_CONFIG_FILE); while (sanei_config_read (config_line, sizeof (config_line), fp)) { if (config_line[0] == '#') continue; /* ignore line comments */ len = strlen (config_line); if (!len) continue; /* ignore empty lines */ DBG (4, "attach_matching_devices(%s)\n", config_line); sanei_usb_attach_matching_devices (config_line, attach_one); } DBG (4, "finished reading configure file\n"); fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { Canon_Device *dev, *next; DBG (3, "sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free (dev->name); free (dev); } if (devlist) free (devlist); return; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Canon_Device *dev; int i; DBG (3, "sane_get_devices(local_only = %d)\n", local_only); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Canon_Device *dev; SANE_Status status; Canon_Scanner *scanner; DBG (3, "sane_open\n"); if (devicename[0]) /* search for devicename */ { DBG (4, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } } else { DBG (2, "sane_open: no devicename, opening first device\n"); dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; scanner = malloc (sizeof (*scanner)); if (!scanner) return SANE_STATUS_NO_MEM; memset (scanner, 0, sizeof (*scanner)); scanner->device = dev; status = CANON_open_device (&scanner->scan, dev->sane.name); if (status != SANE_STATUS_GOOD) { free (scanner); return status; } *handle = scanner; /* insert newly opened handle into list of open handles: */ scanner->next = first_handle; first_handle = scanner; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Canon_Scanner *prev, *scanner; DBG (3, "sane_close\n"); if (!first_handle) { DBG (1, "ERROR: sane_close: no handles opened\n"); return; } /* remove handle from list of open handles: */ prev = NULL; for (scanner = first_handle; scanner; scanner = scanner->next) { if (scanner == handle) break; prev = scanner; } if (!scanner) { DBG (1, "ERROR: sane_close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (prev) prev->next = scanner->next; else first_handle = scanner->next; CANON_close_device (&scanner->scan); free (scanner); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { handle = handle; /* Eliminate compiler warning */ DBG (3, "sane_get_option_descriptor: option = %d\n", option); if (option < 0 || option >= NELEMS (so)) return NULL; return so[option].descriptor; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { handle = handle; /* Eliminate compiler warning */ DBG (3, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", handle, option, action, value, (void *)info); return dispatch_control_option (handle, option, action, value, info); } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int rc = SANE_STATUS_GOOD; int w = SANE_UNFIX (optionBotRightXValue - optionTopLeftXValue) / MM_IN_INCH * optionResolutionValue; int h = SANE_UNFIX (optionBotRightYValue - optionTopLeftYValue) / MM_IN_INCH * optionResolutionValue; handle = handle; /* Eliminate compiler warning */ DBG (3, "sane_get_parameters\n"); parms.depth = 8; parms.last_frame = SANE_TRUE; parms.pixels_per_line = w; parms.lines = h; #ifdef GRAY if (optionGrayscaleValue == SANE_TRUE) { parms.format = SANE_FRAME_GRAY; parms.bytes_per_line = w; } else #endif { parms.format = SANE_FRAME_RGB; parms.bytes_per_line = w * 3; } *params = parms; return rc; } SANE_Status sane_start (SANE_Handle handle) { Canon_Scanner *scanner = handle; SANE_Status res; DBG (3, "sane_start\n"); res = CANON_set_scan_parameters (&scanner->scan, optionCalibrateValue, #ifdef GRAY optionGrayscaleValue, #else SANE_FALSE, #endif SANE_UNFIX (optionTopLeftXValue) / MM_IN_INCH * 600, SANE_UNFIX (optionTopLeftYValue) / MM_IN_INCH * 600, SANE_UNFIX (optionBotRightXValue) / MM_IN_INCH * 600, SANE_UNFIX (optionBotRightYValue) / MM_IN_INCH * 600, optionResolutionValue, optionAGainValue, SANE_UNFIX (optionGammaValue)); if (res != SANE_STATUS_GOOD) return res; return CANON_start_scan (&scanner->scan); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { Canon_Scanner *scanner = handle; return CANON_read (&scanner->scan, data, max_length, length); } void sane_cancel (SANE_Handle handle) { DBG (3, "sane_cancel: handle = %p\n", handle); DBG (3, "sane_cancel: cancelling is unsupported in this backend\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, non_blocking); if (non_blocking != SANE_FALSE) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { handle = handle; /* silence gcc */ fd = fd; /* silence gcc */ return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/niash_core.h0000664000175000017500000001126312112021330015060 00000000000000/* Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. $Id$ */ /* Core NIASH chip functions. */ #ifndef _NIASH_CORE_H_ #define _NIASH_CORE_H_ #include #include "niash_xfer.h" /* for EScannerModel */ #define HP3300C_RIGHT 330 #define HP3300C_TOP 452 #define HP3300C_BOTTOM (HP3300C_TOP + 14200UL) #define HW_PIXELS 5300 /* number of pixels supported by hardware */ #define HW_DPI 600 /* horizontal resolution of hardware */ #define HW_LPI 1200 /* vertical resolution of hardware */ #define BYTES_PER_PIXEL 3 typedef struct { int iXferHandle; /* handle used for data transfer to HW */ int iTopLeftX; /* in mm */ int iTopLeftY; /* in mm */ int iSensorSkew; /* in units of 1/1200 inch */ int iSkipLines; /* lines of garbage to skip */ SANE_Bool fReg07; /* NIASH00019 */ SANE_Bool fGamma16; /* if TRUE, gamma entries are 16 bit */ int iExpTime; SANE_Bool iReversedHead; /* Head is reversed */ int iBufferSize; /* Size of internal scan buffer */ EScannerModel eModel; } THWParams; typedef struct { int iDpi; /* horizontal resolution */ int iLpi; /* vertical resolution */ int iTop; /* in HW coordinates */ int iLeft; /* in HW coordinates */ int iWidth; /* pixels */ int iHeight; /* lines */ int iBottom; int fCalib; /* if TRUE, disable backtracking? */ } TScanParams; typedef struct { unsigned char *pabXferBuf; /* transfer buffer */ int iCurLine; /* current line in the transfer buffer */ int iBytesPerLine; /* unsigned chars in one scan line */ int iLinesPerXferBuf; /* number of lines held in the transfer buffer */ int iLinesLeft; /* transfer (down) counter for pabXFerBuf */ int iSaneBytesPerLine; /* how many unsigned chars to be read by SANE per line */ int iScaleDownDpi; /* factors used to emulate lower resolutions */ int iScaleDownLpi; /* than those offered by hardware */ int iSkipLines; /* line to skip at the start of scan */ int iWidth; /* number of pixels expected by SANE */ unsigned char *pabCircBuf; /* circular buffer */ int iLinesPerCircBuf; /* lines held in the circular buffer */ int iRedLine, iGrnLine, /* start indices for the color information */ iBluLine; /* in the circular buffer */ unsigned char *pabLineBuf; /* buffer used to pass data to SANE */ } TDataPipe; STATIC int NiashOpen (THWParams * pHWParams, const char *pszName); STATIC void NiashClose (THWParams * pHWParams); /* more sof. method that also returns the values of the white (RGB) value */ STATIC SANE_Bool SimpleCalibExt (THWParams * pHWPar, unsigned char *pabCalibTable, unsigned char *pabCalWhite); STATIC SANE_Bool GetLamp (THWParams * pHWParams, SANE_Bool * pfLampIsOn); STATIC SANE_Bool SetLamp (THWParams * pHWParams, SANE_Bool fLampOn); STATIC SANE_Bool InitScan (TScanParams * pParams, THWParams * pHWParams); STATIC void FinishScan (THWParams * pHWParams); STATIC void CalcGamma (unsigned char *pabTable, double Gamma); STATIC void WriteGammaCalibTable (unsigned char *pabGammaR, unsigned char *pabGammaG, unsigned char *pabGammaB, unsigned char *pabCalibTable, int iGain, int iOffset, THWParams * pHWPar); /* set -1 for iHeight to disable all checks on buffer transfers */ /* iWidth is in pixels of SANE */ /* iHeight is lines in scanner resolution */ STATIC void CircBufferInit (int iHandle, TDataPipe * p, int iWidth, int iHeight, int iMisAlignment, SANE_Bool iReversedHead, int iScaleDownDpi, int iScaleDownLpi); /* returns false, when trying to read after end of buffer */ STATIC SANE_Bool CircBufferGetLine (int iHandle, TDataPipe * p, unsigned char *pabLine, SANE_Bool iReversedHead); /* returns false, when trying to read after end of buffer if fReturn==SANE_TRUE, the head will return automatically on an end of scan */ STATIC SANE_Bool CircBufferGetLineEx (int iHandle, TDataPipe * p, unsigned char *pabLine, SANE_Bool iReversedHead, SANE_Bool fReturn); STATIC void CircBufferExit (TDataPipe * p); #endif /* _NIASH_CORE_H_ */ sane-backends-1.0.27/backend/stubs.c0000664000175000017500000000275412112021330014106 00000000000000#define STUBS #include "../include/sane/sanei_backend.h" /* Now define the wrappers (we could use aliases here, but go for robustness for now...: */ SANE_Status sane_init (SANE_Int *vc, SANE_Auth_Callback cb) { return ENTRY(init) (vc, cb); } SANE_Status sane_get_devices (const SANE_Device ***dl, SANE_Bool local) { return ENTRY(get_devices) (dl, local); } SANE_Status sane_open (SANE_String_Const name, SANE_Handle *h) { return ENTRY(open) (name, h); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int opt) { return ENTRY(get_option_descriptor) (h, opt); } SANE_Status sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act, void *val, SANE_Word *info) { return ENTRY(control_option) (h, opt, act, val, info); } SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters *parms) { return ENTRY(get_parameters) (h, parms); } SANE_Status sane_start (SANE_Handle h) { return ENTRY(start) (h); } SANE_Status sane_read (SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp) { return ENTRY(read) (h, buf, maxlen, lenp); } SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) { return ENTRY(set_io_mode) (h, non_blocking); } SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) { return ENTRY(get_select_fd) (h, fdp); } void sane_cancel (SANE_Handle h) { ENTRY(cancel) (h); } void sane_close (SANE_Handle h) { ENTRY(close) (h); } void sane_exit (void) { ENTRY(exit) (); } sane-backends-1.0.27/backend/epson2-io.h0000664000175000017500000000304712112021330014562 00000000000000/* * Prototypes for epson2 I/O functions * * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for original copyrights. * * Copyright (C) 2006 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #ifndef epson2_io_h #define epson2_io_h extern unsigned int r_cmd_count; extern unsigned int w_cmd_count; SANE_Status e2_cmd_simple(Epson_Scanner * s, void *buf, size_t buf_size); int e2_send(Epson_Scanner * s, void *buf, size_t buf_size, size_t reply_len, SANE_Status * status); ssize_t e2_recv(Epson_Scanner * s, void *buf, ssize_t buf_size, SANE_Status * status); SANE_Status e2_txrx(Epson_Scanner * s, unsigned char *txbuf, size_t txlen, unsigned char *rxbuf, size_t rxlen); SANE_Status e2_recv_info_block(Epson_Scanner * s, unsigned char *scanner_status, size_t info_size, size_t * payload_size); SANE_Status e2_cmd_info_block(SANE_Handle handle, unsigned char *params, unsigned char params_len, size_t reply_len, unsigned char **buf, size_t * buf_len); SANE_Status e2_ack(Epson_Scanner * s); SANE_Status e2_ack_next(Epson_Scanner * s, size_t reply_len); SANE_Status e2_cancel(Epson_Scanner * s); SANE_Status e2_esc_cmd(Epson_Scanner * s, unsigned char cmd, unsigned char val); #endif /* epson2_io_h */ sane-backends-1.0.27/backend/hp3900_debug.c0000664000175000017500000017421312775312261015064 00000000000000/* HP Scanjet 3900 series - Debugging functions for standalone Copyright (C) 2005-2008 Jonathan Bravo Lopez This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* debugging level messages */ #define DBG_ERR 0x00 /* Only important errors */ #define DBG_VRB 0x01 /* verbose messages */ #define DBG_FNC 0x02 /* Function names and parameters */ #define DBG_CTL 0x03 /* USB Ctl data */ #define DBG_BLK 0x04 /* USB Bulk data */ #include #ifdef HAVE_TIFFIO_H #include /* dbg_tiff_save */ #endif /* headers */ static void dump_shading (struct st_calibration *myCalib); static char *dbg_scantype (SANE_Int type); static void dbg_scanmodes (struct st_device *dev); static void dbg_motorcurves (struct st_device *dev); static void dbg_motormoves (struct st_device *dev); static void dbg_hwdcfg (struct st_hwdconfig *params); static void dbg_ScanParams (struct st_scanparams *params); static void dbg_calibtable (struct st_gain_offset *params); static char *dbg_colour (SANE_Int colour); static void dbg_motorcfg (struct st_motorcfg *motorcfg); static void dbg_buttons (struct st_buttons *buttons); static void dbg_sensor (struct st_sensorcfg *sensor); static void dbg_timing (struct st_timing *mt); static void dbg_sensorclock (struct st_cph *cph); static void dbg_tiff_save (char *sFile, SANE_Int width, SANE_Int height, SANE_Int depth, SANE_Int colortype, SANE_Int res_x, SANE_Int res_y, SANE_Byte * buffer, SANE_Int size); static void dbg_autoref (struct st_scanparams *scancfg, SANE_Byte * pattern, SANE_Int ser1, SANE_Int ser2, SANE_Int ler); #ifdef developing static void dbg_buffer (SANE_Int level, char *title, SANE_Byte * buffer, SANE_Int size, SANE_Int start); static void dbg_registers (SANE_Byte * buffer); #endif #ifdef STANDALONE /* implementation */ int DBG_LEVEL = 0; static void DBG (int level, const char *msg, ...) { va_list ap; va_start (ap, msg); if (level <= DBG_LEVEL) vfprintf (stderr, msg, ap); va_end (ap); } #endif /* debugging functions */ static void dump_shading (struct st_calibration *myCalib) { if (myCalib != NULL) { SANE_Int colour, a; FILE *shadingfile[3]; shadingfile[0] = fopen ("RShading.txt", "w"); shadingfile[1] = fopen ("GShading.txt", "w"); shadingfile[2] = fopen ("BShading.txt", "w"); for (colour = 0; colour < 3; colour++) { if (shadingfile[colour] != NULL) { for (a = 0; a < myCalib->shadinglength; a++) fprintf (shadingfile[colour], "%04i: %04x %04x\n", a, (unsigned int) myCalib->white_shading[colour][a], (unsigned int) myCalib->black_shading[colour][a]); fclose (shadingfile[colour]); } } } } static char * dbg_scantype (SANE_Int type) { switch (type) { case ST_NORMAL: return "ST_NORMAL"; break; case ST_TA: return "ST_TA"; break; case ST_NEG: return "ST_NEG"; break; default: return "Unknown"; break; } } static void dbg_sensorclock (struct st_cph *cph) { if (cph != NULL) { DBG (DBG_FNC, " -> cph->p1 = %f\n", cph->p1); DBG (DBG_FNC, " -> cph->p2 = %f\n", cph->p2); DBG (DBG_FNC, " -> cph->ps = %i\n", cph->ps); DBG (DBG_FNC, " -> cph->ge = %i\n", cph->ge); DBG (DBG_FNC, " -> cph->go = %i\n", cph->go); } else DBG (DBG_FNC, " -> cph is NULL\n"); } static void dbg_timing (struct st_timing *mt) { if (mt != NULL) { DBG (DBG_FNC, " -> mt->cdss[0] = %i\n", _B0 (mt->cdss[0])); DBG (DBG_FNC, " -> mt->cdsc[0] = %i\n", _B0 (mt->cdsc[0])); DBG (DBG_FNC, " -> mt->cdss[1] = %i\n", _B0 (mt->cdss[1])); DBG (DBG_FNC, " -> mt->cdsc[1] = %i\n", _B0 (mt->cdsc[1])); DBG (DBG_FNC, " -> mt->cnpp = %i\n", _B0 (mt->cnpp)); DBG (DBG_FNC, " -> mt->cvtrp0 = %i\n", _B0 (mt->cvtrp[0])); DBG (DBG_FNC, " -> mt->cvtrp1 = %i\n", _B0 (mt->cvtrp[1])); DBG (DBG_FNC, " -> mt->cvtrp2 = %i\n", _B0 (mt->cvtrp[2])); DBG (DBG_FNC, " -> mt->cvtrfpw = %i\n", _B0 (mt->cvtrfpw)); DBG (DBG_FNC, " -> mt->cvtrbpw = %i\n", _B0 (mt->cvtrbpw)); DBG (DBG_FNC, " -> mt->cvtrw = %i\n", _B0 (mt->cvtrw)); DBG (DBG_FNC, " -> mt->clamps = 0x%08x\n", mt->clamps); DBG (DBG_FNC, " -> mt->clampe = 0x%08x\n", mt->clampe); DBG (DBG_FNC, " -> mt->adcclkp0 = %f\n", mt->adcclkp[0]); DBG (DBG_FNC, " -> mt->adcclkp1 = %f\n", mt->adcclkp[1]); DBG (DBG_FNC, " -> mt->adcclkp2e = %i\n", mt->adcclkp2e); DBG (DBG_FNC, " -> mt->cphbp2s = %i\n", mt->cphbp2s); DBG (DBG_FNC, " -> mt->cphbp2e = %i\n", mt->cphbp2e); } else DBG (DBG_FNC, " -> mt is NULL\n"); } static void dbg_sensor (struct st_sensorcfg *sensor) { if (sensor != NULL) { DBG (DBG_FNC, " -> type, name, res , {chn_color }, {chn_gray}, {rgb_order }, line_dist, evnodd_dist\n"); DBG (DBG_FNC, " -> ----, ----, --- , {--, --, --}, {--, -- }, {--, --, --}, ---------, -----------\n"); DBG (DBG_FNC, " -> %4i, %4i, %4i, {%2i, %2i, %2i}, {%2i, %2i }, {%2i, %2i, %2i}, %9i, %11i\n", sensor->type, sensor->name, sensor->resolution, sensor->channel_color[0], sensor->channel_color[1], sensor->channel_color[2], sensor->channel_gray[0], sensor->channel_gray[1], sensor->rgb_order[0], sensor->rgb_order[1], sensor->rgb_order[2], sensor->line_distance, sensor->evenodd_distance); } else DBG (DBG_FNC, " -> sensor is NULL\n"); } static void dbg_buttons (struct st_buttons *buttons) { if (buttons != NULL) { DBG (DBG_FNC, " -> count, btn1, btn2, btn3, btn4, btn5, btn6\n"); DBG (DBG_FNC, " -> -----, ----, ----, ----, ----, ----, ----\n"); DBG (DBG_FNC, " -> %5i, %4i, %4i, %4i, %4i, %4i, %4i\n", buttons->count, buttons->mask[0], buttons->mask[1], buttons->mask[2], buttons->mask[3], buttons->mask[4], buttons->mask[5]); } else DBG (DBG_FNC, " -> buttons is NULL\n"); } static void dbg_scanmodes (struct st_device *dev) { if (dev->scanmodes_count > 0) { SANE_Int a; struct st_scanmode *reg; DBG (DBG_FNC, " -> ##, ST , CM , RES , TM, CV, SR, CLK, CTPC , BKS , STT, DML, { Exposure times }, { Max exposure times }, MP , MExp16, MExpF, MExp, MRI, MSI, MMTIR, MMTIRH, SK\n"); DBG (DBG_FNC, " -> --, ---------, ----------, --- , --, --, --, ---, ------, ----, ---, ---, {------ ------ ------}, {------ ------ ------}, ---, ------, -----, ----, ---, ---, -----, ------, --\n"); for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { DBG (DBG_FNC, " -> %2i, %9s, %10s, %4i, %2i, %2i, %2i, %3i, %6i, %4i, %3i, %3i, {%6i, %6i, %6i}, {%6i, %6i, %6i}, %3i, %6i, %5i, %4i, %3i, %3i, %5i, %6i, %2i\n", a, dbg_scantype (reg->scantype), dbg_colour (reg->colormode), reg->resolution, reg->timing, reg->motorcurve, reg->samplerate, reg->systemclock, reg->ctpc, reg->motorbackstep, reg->scanmotorsteptype, reg->dummyline, reg->expt[0], reg->expt[1], reg->expt[2], reg->mexpt[0], reg->mexpt[1], reg->mexpt[2], reg->motorplus, reg->multiexposurefor16bitmode, reg->multiexposureforfullspeed, reg->multiexposure, reg->mri, reg->msi, reg->mmtir, reg->mmtirh, reg->skiplinecount); } } } } static void dbg_motorcurves (struct st_device *dev) { if (dev->mtrsetting != NULL) { struct st_motorcurve *mtc; SANE_Int a = 0; while (a < dev->mtrsetting_count) { DBG (DBG_FNC, " -> Motorcurve %2i: ", a); mtc = dev->mtrsetting[a]; if (mtc != NULL) { DBG (DBG_FNC, "mri=%i msi=%i skip=%i bckstp=%i\n", mtc->mri, mtc->msi, mtc->skiplinecount, mtc->motorbackstep); if (mtc->curve_count > 0) { char *sdata = (char *) malloc (256); if (sdata != NULL) { char *sline = (char *) malloc (256); if (sline != NULL) { SANE_Int count; struct st_curve *crv; DBG (DBG_FNC, " -> ##, dir, type , count, from, to , steps\n"); DBG (DBG_FNC, " -> --, ---, ----------, -----, ----, ----, -----\n"); count = 0; while (count < mtc->curve_count) { memset (sline, 0, 256); snprintf (sdata, 256, " -> %02i, ", count); strcat (sline, sdata); crv = mtc->curve[count]; if (crv != NULL) { if (crv->crv_speed == ACC_CURVE) strcat (sline, "ACC, "); else strcat (sline, "DEC, "); switch (crv->crv_type) { case CRV_NORMALSCAN: strcat (sline, "NORMALSCAN, "); break; case CRV_PARKHOME: strcat (sline, "PARKHOME , "); break; case CRV_SMEARING: strcat (sline, "SMEARING , "); break; case CRV_BUFFERFULL: strcat (sline, "BUFFERFULL, "); break; default: snprintf (sdata, 256, "unknown %2i, ", crv->crv_type); strcat (sline, sdata); break; } snprintf (sdata, 256, "%5i, ", crv->step_count); strcat (sline, sdata); if (crv->step_count > 0) { SANE_Int stpcount = 0; snprintf (sdata, 256, "%4i, %4i| ", crv->step[0], crv->step[crv->step_count - 1]); strcat (sline, sdata); while (stpcount < crv->step_count) { if (stpcount == 10) { strcat (sline, "..."); break; } if (stpcount > 0) strcat (sline, ", "); snprintf (sdata, 256, "%4i", crv->step[stpcount]); strcat (sline, sdata); stpcount++; } strcat (sline, "\n"); } else strcat (sline, "NONE\n"); } else strcat (sline, "NULL ...\n"); DBG (DBG_FNC, "%s", sline); count++; } free (sline); } free (sdata); } } } else DBG (DBG_FNC, "NULL\n"); a++; } } } static void dbg_motormoves (struct st_device *dev) { if (dev->motormove_count > 0) { SANE_Int a; struct st_motormove *reg; DBG (DBG_FNC, " -> ##, CLK, CTPC, STT, CV\n"); DBG (DBG_FNC, " -> --, ---, ----, ---, --\n"); for (a = 0; a < dev->motormove_count; a++) { reg = dev->motormove[a]; if (reg != NULL) { DBG (DBG_FNC, " -> %2i, %3i, %4i, %3i, %2i\n", a, reg->systemclock, reg->ctpc, reg->scanmotorsteptype, reg->motorcurve); } } } } static void dbg_hwdcfg (struct st_hwdconfig *params) { if (params != NULL) { DBG (DBG_FNC, " -> Low level config:\n"); DBG (DBG_FNC, " -> startpos = %i\n", params->startpos); DBG (DBG_FNC, " -> arrangeline = %s\n", (params->arrangeline == FIX_BY_SOFT) ? "FIX_BY_SOFT" : (params->arrangeline == FIX_BY_HARD) ? "FIX_BY_HARD" : "FIX_BY_NONE"); DBG (DBG_FNC, " -> scantype = %s\n", dbg_scantype (params->scantype)); DBG (DBG_FNC, " -> compression = %i\n", params->compression); DBG (DBG_FNC, " -> use_gamma_tables = %i\n", params->use_gamma_tables); DBG (DBG_FNC, " -> gamma_tablesize = %i\n", params->gamma_tablesize); DBG (DBG_FNC, " -> white_shading = %i\n", params->white_shading); DBG (DBG_FNC, " -> black_shading = %i\n", params->black_shading); DBG (DBG_FNC, " -> unk3 = %i\n", params->unk3); DBG (DBG_FNC, " -> motorplus = %i\n", params->motorplus); DBG (DBG_FNC, " -> static_head = %i\n", params->static_head); DBG (DBG_FNC, " -> motor_direction = %s\n", (params->motor_direction == MTR_FORWARD) ? "FORWARD" : "BACKWARD"); DBG (DBG_FNC, " -> dummy_scan = %i\n", params->dummy_scan); DBG (DBG_FNC, " -> highresolution = %i\n", params->highresolution); DBG (DBG_FNC, " -> sensorevenodddistance = %i\n", params->sensorevenodddistance); DBG (DBG_FNC, " -> calibrate = %i\n", params->calibrate); } } static void dbg_ScanParams (struct st_scanparams *params) { if (params != NULL) { DBG (DBG_FNC, " -> Scan params:\n"); DBG (DBG_FNC, " -> colormode = %s\n", dbg_colour (params->colormode)); DBG (DBG_FNC, " -> depth = %i\n", params->depth); DBG (DBG_FNC, " -> samplerate = %i\n", params->samplerate); DBG (DBG_FNC, " -> timing = %i\n", params->timing); DBG (DBG_FNC, " -> channel = %i\n", params->channel); DBG (DBG_FNC, " -> sensorresolution = %i\n", params->sensorresolution); DBG (DBG_FNC, " -> resolution_x = %i\n", params->resolution_x); DBG (DBG_FNC, " -> resolution_y = %i\n", params->resolution_y); DBG (DBG_FNC, " -> left = %i\n", params->coord.left); DBG (DBG_FNC, " -> width = %i\n", params->coord.width); DBG (DBG_FNC, " -> top = %i\n", params->coord.top); DBG (DBG_FNC, " -> height = %i\n", params->coord.height); DBG (DBG_FNC, " -> shadinglength = %i\n", params->shadinglength); DBG (DBG_FNC, " -> v157c = %i\n", params->v157c); DBG (DBG_FNC, " -> bytesperline = %i\n", params->bytesperline); DBG (DBG_FNC, " -> expt = %i\n", params->expt); DBG (DBG_FNC, " *> startpos = %i\n", params->startpos); DBG (DBG_FNC, " *> leftleading = %i\n", params->leftleading); DBG (DBG_FNC, " *> ser = %i\n", params->ser); DBG (DBG_FNC, " *> ler = %i\n", params->ler); DBG (DBG_FNC, " *> scantype = %s\n", dbg_scantype (params->scantype)); } } static void dbg_calibtable (struct st_gain_offset *params) { if (params != NULL) { DBG (DBG_FNC, " -> Calib table:\n"); DBG (DBG_FNC, " -> type R G B\n"); DBG (DBG_FNC, " -> ----- --- --- ---B\n"); DBG (DBG_FNC, " -> edcg1 = %3i , %3i , %3i\n", params->edcg1[0], params->edcg1[1], params->edcg1[2]); DBG (DBG_FNC, " -> edcg2 = %3i , %3i , %3i\n", params->edcg2[0], params->edcg2[1], params->edcg2[2]); DBG (DBG_FNC, " -> odcg1 = %3i , %3i , %3i\n", params->odcg1[0], params->odcg1[1], params->odcg1[2]); DBG (DBG_FNC, " -> odcg2 = %3i , %3i , %3i\n", params->odcg2[0], params->odcg2[1], params->odcg2[2]); DBG (DBG_FNC, " -> pag = %3i , %3i , %3i\n", params->pag[0], params->pag[1], params->pag[2]); DBG (DBG_FNC, " -> vgag1 = %3i , %3i , %3i\n", params->vgag1[0], params->vgag1[1], params->vgag1[2]); DBG (DBG_FNC, " -> vgag2 = %3i , %3i , %3i\n", params->vgag2[0], params->vgag2[1], params->vgag2[2]); } } static char * dbg_colour (SANE_Int colour) { switch (colour) { case CM_COLOR: return "CM_COLOR"; break; case CM_GRAY: return "CM_GRAY"; break; case CM_LINEART: return "CM_LINEART"; break; default: return "Unknown"; break; } } static void dbg_motorcfg (struct st_motorcfg *motorcfg) { if (motorcfg != NULL) { DBG (DBG_FNC, " -> type, res , freq, speed, base, high, park, change\n"); DBG (DBG_FNC, " -> ----, --- , ----, -----, ----, ----, ----, ------\n"); DBG (DBG_FNC, " -> %4i, %4i, %4i, %5i, %4i, %4i, %4i, %6i\n", motorcfg->type, motorcfg->resolution, motorcfg->pwmfrequency, motorcfg->basespeedpps, motorcfg->basespeedmotormove, motorcfg->highspeedmotormove, motorcfg->parkhomemotormove, motorcfg->changemotorcurrent); } } static void dbg_tiff_save (char *sFile, SANE_Int width, SANE_Int height, SANE_Int depth, SANE_Int colortype, SANE_Int res_x, SANE_Int res_y, SANE_Byte * buffer, SANE_Int size) { #ifdef HAVE_TIFFIO_H if (buffer != NULL) { char *path = getenv ("HOME"); if (path != NULL) { char filename[512]; TIFF *image; if (snprintf (filename, 512, "%s/%s", path, sFile) > 0) { /* Open the TIFF file */ if ((image = TIFFOpen (filename, "w")) != NULL) { char desc[256]; SANE_Int spp = (colortype == CM_GRAY) ? 1 : 3; SANE_Int ct = (colortype == CM_GRAY) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB; snprintf (desc, 256, "Created with hp3900 %s", BACKEND_VRSN); /* We need to set some values for basic tags before we can add any data */ TIFFSetField (image, TIFFTAG_IMAGEWIDTH, width); TIFFSetField (image, TIFFTAG_IMAGELENGTH, height); TIFFSetField (image, TIFFTAG_BITSPERSAMPLE, depth); TIFFSetField (image, TIFFTAG_SAMPLESPERPIXEL, spp); TIFFSetField (image, TIFFTAG_PHOTOMETRIC, ct); TIFFSetField (image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); TIFFSetField (image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField (image, TIFFTAG_XRESOLUTION, (double) res_x); TIFFSetField (image, TIFFTAG_YRESOLUTION, (double) res_y); TIFFSetField (image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); TIFFSetField (image, TIFFTAG_IMAGEDESCRIPTION, desc); /* Write the information to the file */ TIFFWriteRawStrip (image, 0, buffer, size); TIFFClose (image); } } else DBG (DBG_ERR, "- dbg_tiff_save: Error generating filename\n"); } else DBG (DBG_ERR, "- dbg_tiff_save: Environment HOME variable does not exist\n"); } #else /* silent gcc */ sFile = sFile; width = width; height = height; depth = depth; colortype = colortype; res_x = res_x; res_y = res_y; buffer = buffer; size = size; DBG (DBG_ERR, "- dbg_tiff_save: tiffio not supported\n"); #endif } static void dbg_autoref (struct st_scanparams *scancfg, SANE_Byte * pattern, SANE_Int ser1, SANE_Int ser2, SANE_Int ler) { /* this function generates post-autoref.tiff */ SANE_Byte *img = malloc (sizeof (SANE_Byte) * (scancfg->coord.width * scancfg->coord.height * 3)); if (img != NULL) { SANE_Int c, value; /* generate image from 1 gray channel to 3 color channels */ for (c = 0; c < (scancfg->coord.width * scancfg->coord.height); c++) { value = *(pattern + c); *(img + (3 * c)) = value; *(img + (3 * c) + 1) = value; *(img + (3 * c) + 2) = value; } for (c = 0; c < scancfg->coord.height; c++) { /* line for first SER */ if (c < (ler + 5)) { *(img + (scancfg->coord.width * c * 3) + (3 * ser1)) = 0; *(img + (scancfg->coord.width * c * 3) + (3 * ser1) + 1) = 255; *(img + (scancfg->coord.width * c * 3) + (3 * ser1) + 2) = 0; } /* line for second SER */ if (c > (ler - 5)) { *(img + (scancfg->coord.width * c * 3) + (3 * ser2)) = 90; *(img + (scancfg->coord.width * c * 3) + (3 * ser2) + 1) = 90; *(img + (scancfg->coord.width * c * 3) + (3 * ser2) + 2) = 255; } /* vertical lines of the pointer */ if ((c > (ler - 5)) && (c < (ler + 5))) { if ((ser2 - 5) >= 0) { *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 - 5))) = 255; *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 - 5)) + 1) = 255; *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 - 5)) + 2) = 0; } if ((ser2 + 5) < scancfg->coord.width) { *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 + 5))) = 255; *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 + 5)) + 1) = 255; *(img + (scancfg->coord.width * c * 3) + (3 * (ser2 + 5)) + 2) = 0; } } } /* line for first LER */ for (c = 0; c < scancfg->coord.width; c++) { if ((c > (ser1 - 5)) && (c < (ser2 + 5))) { if (c != (ser2 - 5)) { *(img + (scancfg->coord.width * ler * 3) + (3 * c)) = 255; *(img + (scancfg->coord.width * ler * 3) + (3 * c) + 1) = 90; *(img + (scancfg->coord.width * ler * 3) + (3 * c) + 2) = 90; } /* horizontal lines of the pointer */ if ((c > (ser2 - 5)) && (c < (ser2 + 5))) { if ((ler - 5) >= 0) { *(img + (scancfg->coord.width * (ler - 5) * 3) + (3 * c)) = 255; *(img + (scancfg->coord.width * (ler - 5) * 3) + (3 * c) + 1) = 255; *(img + (scancfg->coord.width * (ler - 5) * 3) + (3 * c) + 2) = 0; } if ((ler + 5) < scancfg->coord.height) { *(img + (scancfg->coord.width * (ler + 5) * 3) + (3 * c)) = 255; *(img + (scancfg->coord.width * (ler + 5) * 3) + (3 * c) + 1) = 255; *(img + (scancfg->coord.width * (ler + 5) * 3) + (3 * c) + 2) = 0; } } } } dbg_tiff_save ("post-autoref.tiff", scancfg->coord.width, scancfg->coord.height, 8, CM_COLOR, scancfg->resolution_x, scancfg->resolution_y, img, scancfg->coord.height * scancfg->coord.width * 3); /* free generated image */ free (img); } } #ifdef developing static void dbg_buffer (SANE_Int level, char *title, SANE_Byte * buffer, SANE_Int size, SANE_Int start) { if (level <= DBG_LEVEL) { DBG (level, "%s ", title); if ((size > 0) && (buffer != NULL)) { SANE_Int cont, data, offset = 0; SANE_Int col = 0; char text[9]; char *sline = NULL; char *sdata = NULL; sline = (char *) malloc (81); if (sline != NULL) { sdata = (char *) malloc (81); if (sdata != NULL) { for (cont = 0; cont < size; cont++) { if (col == 0) { if (cont == 0) snprintf (sline, 80, " BF: "); else snprintf (sline, 80, " "); bzero (&text, sizeof (text)); } data = _B0 (buffer[cont]); text[col] = (data > 31) ? data : '·'; snprintf (sdata, 80, "%02x ", data); sline = strcat (sline, sdata); col++; offset++; if (col == 8) { col = 0; snprintf (sdata, 80, " : %s : 0x%04x\n", text, start + offset - 8); sline = strcat (sline, sdata); DBG (level, "%s", sline); bzero (sline, 81); } } if (col > 0) { for (cont = col; cont < 8; cont++) { snprintf (sdata, 80, "-- "); sline = strcat (sline, sdata); offset++; } snprintf (sdata, 80, " : %s : 0x%04x\n", text, start + offset - 8); sline = strcat (sline, sdata); DBG (level, "%s", sline); bzero (sline, 81); } free (sdata); } free (sline); } } else DBG (level, " BF: Empty buffer\n"); } } static void dbg_registers (SANE_Byte * buffer) { /* buffer size must be RT_BUFFER_LEN bytes */ /*SANE_Int iValue, iValue2; double dValue; DBG(DBG_FNC, "\n----------------------------------------------------\n"); DBG(DBG_FNC, """RTS8822 Control Registers Info""\nAddress Info\n------- ----\n"); iValue = data_lsb_get(&buffer[0x000], 1); DBG(DBG_FNC, "\n0x0000"); DBG(DBG_FNC, " bit[0..3] = systemclock: 0x%02x\n", iValue & 0x0f); DBG(DBG_FNC, " bit[4] = 0x%02x : MLOCK\n", (iValue >> 4) & 1); DBG(DBG_FNC, " bit[5] = 0x%02x : Bit to reset scanner\n", (iValue >> 5) & 1); DBG(DBG_FNC, " bit[6] = 0x%02x : ?\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = 0x%02x : RTS_IsExecuting\n", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x001], 1); DBG(DBG_FNC, "0x0001 bit[0] = 0x%02x : ?\n", iValue & 1); DBG(DBG_FNC, " bit[1] = 0x%02x : (is 1 if has motorcurves)\n", (iValue >> 1) & 1); DBG(DBG_FNC, " bit[2] = 0x%02x : ?\n", (iValue >> 2) & 1); DBG(DBG_FNC, " bit[3] = 0x%02x : ?\n", (iValue >> 3) & 1); DBG(DBG_FNC, " bit[4] = 0x%02x : dummy scan\n", (iValue >> 4) & 1); DBG(DBG_FNC, " bit[5..7] = 0x%02x : ?\n", (iValue >> 5) & 7); dbg_buffer(DBG_FNC, "\n0x0002", &buffer[0x002], 0x0e, 0x02); iValue = data_lsb_get(&buffer[0x010], 1); DBG(DBG_FNC, "\n0x0010 bit[0..4] = 0x%02x : cvrs\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5] = 0x%02x : Enable CCD\n", ((iValue >> 5) & 1)); DBG(DBG_FNC, " bit[6] = 0x%02x : Enable CCD channel 1\n", ((iValue >> 6) & 1)); DBG(DBG_FNC, " bit[7] = 0x%02x : Enable CCD channel 2\n", ((iValue >> 7) & 1)); iValue = data_lsb_get(&buffer[0x011], 1); DBG(DBG_FNC, "\n0x0011 bit[0..6] = ?: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[7] = 0x%02x : sensor type (CCD=0|CIS=1)\n", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x012], 1); DBG(DBG_FNC, "0x0012 bit[0..5] = 0x%02x [0x%02x,0x%02x,0x%02x] rgb channel order\n", (iValue & 0x3f), (iValue >> 4) & 3, (iValue >> 2) & 3, iValue & 3); DBG(DBG_FNC, " bit[6..7] = channels_per_dot : 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x013], 1); DBG(DBG_FNC, "\n0x0013"); DBG(DBG_FNC, " bit[0..1] = Pre-Amplifier Gain[RED] : 0x%02x\n", iValue & 3); DBG(DBG_FNC, " bit[2..3] = Pre-Amplifier Gain[GREEN] : 0x%02x\n", (iValue >> 2) & 3); DBG(DBG_FNC, " bit[4..5] = Pre-Amplifier Gain[BLUE] : 0x%02x\n", (iValue >> 4) & 3); DBG(DBG_FNC, " bit[6] = ? : 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = Enable CCD channel 3: : 0x%02x\n", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x014], 1); DBG(DBG_FNC, "\n0x0014"); DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 1 [RED] : 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5..7] = Top Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); iValue = data_lsb_get(&buffer[0x015], 1); DBG(DBG_FNC, "0x0015"); DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 1 [GREEN] : 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5..7] = Middle Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); iValue = data_lsb_get(&buffer[0x016], 1); DBG(DBG_FNC, "0x0016"); DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 1 [BLUE] : 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5..7] = Bottom Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); iValue = data_lsb_get(&buffer[0x017], 1); DBG(DBG_FNC, "0x0017"); DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 2 [RED] : 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5..7] = Top Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); iValue = data_lsb_get(&buffer[0x018], 1); DBG(DBG_FNC, "0x0018"); DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 2 [GREEN] : 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5..7] = Middle Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); iValue = data_lsb_get(&buffer[0x019], 1); DBG(DBG_FNC, "0x0019"); DBG(DBG_FNC, " bit[0..4] = Variable Gain Amplifier 2 [BLUE] : 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5..7] = Bottom Reference Voltage: 0x%02x\n", (iValue >> 5) & 3); iValue = data_lsb_get(&buffer[0x01a], 1); iValue2 = data_lsb_get(&buffer[0x01b], 1); DBG(DBG_FNC, "\n0x001a-0x001b\n"); DBG(DBG_FNC, " Red Even offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); DBG(DBG_FNC, " Red Even offset 2: 0x%02x\n", iValue2 & 0x3f); iValue = data_lsb_get(&buffer[0x01c], 1); iValue2 = data_lsb_get(&buffer[0x01d], 1); DBG(DBG_FNC, "0x001c-0x001d\n"); DBG(DBG_FNC, " Red Odd offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); DBG(DBG_FNC, " Red Odd offset 2: 0x%02x\n", iValue2 & 0x3f); iValue = data_lsb_get(&buffer[0x01e], 1); iValue2 = data_lsb_get(&buffer[0x01f], 1); DBG(DBG_FNC, "0x001e-0x001f\n"); DBG(DBG_FNC, " Green Even offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); DBG(DBG_FNC, " Green Even offset 2: 0x%02x\n", iValue2 & 0x3f); iValue = data_lsb_get(&buffer[0x020], 1); iValue2 = data_lsb_get(&buffer[0x021], 1); DBG(DBG_FNC, "0x0020-0x0021\n"); DBG(DBG_FNC, " Green Odd offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); DBG(DBG_FNC, " Green Odd offset 2: 0x%02x\n", iValue2 & 0x3f); iValue = data_lsb_get(&buffer[0x022], 1); iValue2 = data_lsb_get(&buffer[0x023], 1); DBG(DBG_FNC, "0x0022-0x0023\n"); DBG(DBG_FNC, " Blue Even offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); DBG(DBG_FNC, " Blue Even offset 2: 0x%02x\n", iValue2 & 0x3f); iValue = data_lsb_get(&buffer[0x024], 1); iValue2 = data_lsb_get(&buffer[0x025], 1); DBG(DBG_FNC, "0x0024-0x0025\n"); DBG(DBG_FNC, " Blue Odd offset 1: 0x%02x\n", ((iValue2 & 0x80) << 1) | iValue); DBG(DBG_FNC, " Blue Odd offset 2: 0x%02x\n", iValue2 & 0x3f); dbg_buffer(DBG_FNC, "\n0x0026", &buffer[0x026], 0x03, 0x26); iValue = data_lsb_get(&buffer[0x029], 1); DBG(DBG_FNC, "\n0x0029"); DBG(DBG_FNC, " First connection to scanner? : 0x%02x\n", iValue); dbg_buffer(DBG_FNC, "\n0x002a", &buffer[0x02a], 0x06, 0x2a); DBG(DBG_FNC, "\nExposure times:\n"); iValue = data_lsb_get(&buffer[0x030], 3); DBG(DBG_FNC, "0x0030 Line exposure time : %i us\n", iValue); iValue = data_lsb_get(&buffer[0x033], 3); DBG(DBG_FNC, "\n0x0033 mexpts[RED] : %i us\n", iValue); iValue = data_lsb_get(&buffer[0x036], 3); DBG(DBG_FNC, "0x0036 expts[RED] : %i us\n", iValue); iValue = data_lsb_get(&buffer[0x039], 3); DBG(DBG_FNC, "0x0039 mexpts[GREEN]: %i us\n", iValue); iValue = data_lsb_get(&buffer[0x03c], 3); DBG(DBG_FNC, "0x003c expts[GREEN]: %i us\n", iValue); iValue = data_lsb_get(&buffer[0x03f], 3); DBG(DBG_FNC, "0x003f mexpts[BLUE] : %i us\n", iValue); iValue = data_lsb_get(&buffer[0x042], 3); DBG(DBG_FNC, "0x0042 expts[BLUE] : %i us\n", iValue); iValue = data_lsb_get(&buffer[0x045], 1); DBG(DBG_FNC, "\n0x0045 bit[0..4] = timing.cvtrfpw: 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5] = timing.cvtrp[2]: 0x%02x\n", (iValue >> 5) & 1); DBG(DBG_FNC, " bit[6] = timing.cvtrp[1]: 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = timing.cvtrp[0]: 0x%02x\n", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x046], 1); DBG(DBG_FNC, "0x0046"); DBG(DBG_FNC, " bit[0..4] = timing.cvtrbpw: 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5..7] = ?: 0x%02x\n", (iValue >> 5) & 3); iValue = data_lsb_get(&buffer[0x047], 1); DBG(DBG_FNC, "0x0047"); DBG(DBG_FNC, " timing.cvtrw: 0x%02x\n", iValue); iValue = data_lsb_get(&buffer[0x04c], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x04a], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x048], 0x02); DBG(DBG_FNC, "\n0x0048 Linear image sensor clock 1\n"); DBG(DBG_FNC, " bit[0..35] = timing.cph0p1: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x04c], 0x01); DBG(DBG_FNC, " bit[36] = timing.cph0go: 0x%02x\n", (iValue >> 4) & 1); DBG(DBG_FNC, " bit[37] = timing.cph0ge: 0x%02x\n", (iValue >> 5) & 1); DBG(DBG_FNC, " bit[38] = timing.cph0ps: 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x051], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x04f], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x04d], 0x02); DBG(DBG_FNC, "0x004d"); DBG(DBG_FNC, " bit[0..35] = timing.cph0p2: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x056], 1) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x054], 2); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x052], 2); DBG(DBG_FNC, "\n0x0052 Linear image sensor clock 2\n"); DBG(DBG_FNC, " bit[0..35] = timing.cph1p1: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x056], 1); DBG(DBG_FNC, " bit[36] = timing.cph1go: 0x%02x\n", (iValue >> 4) & 1); DBG(DBG_FNC, " bit[37] = timing.cph1ge: 0x%02x\n", (iValue >> 5) & 1); DBG(DBG_FNC, " bit[38] = timing.cph1ps: 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x05b], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x059], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x057], 0x02); DBG(DBG_FNC, "0x0057"); DBG(DBG_FNC, " bit[0..35] = timing.cph1p2: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x05b], 0x01); DBG(DBG_FNC, " bits[36..39] = %02x\n", (iValue >> 0x04) & 0x0f); DBG(DBG_FNC, " bit[36] = ?: %02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = ?: %02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = ?: %02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: %02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x060], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x05e], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x05c], 0x02); DBG(DBG_FNC, "\n0x005c Linear Image Sensor Clock 3\n"); DBG(DBG_FNC, " bit[0..35] = timing.cph2p1: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x060], 0x01); DBG(DBG_FNC, " bit[36] = timing.cph2go: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = timing.cph2ge: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = timing.cph2ps: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x065], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x063], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x061], 0x02); DBG(DBG_FNC, "0x0061"); DBG(DBG_FNC, " bit[0..35] = timing.cph2p2: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x065], 0x01); DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x06a], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x068], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x066], 0x02); DBG(DBG_FNC, "\n0x0066 Linear Image Sensor Clock 4\n"); DBG(DBG_FNC, " bit[0..35] = timing.cph3p1: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x06a], 0x01); DBG(DBG_FNC, " bit[36] = timing.cph3go: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = timing.cph3ge: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = timing.cph3ps: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x06f], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x06d], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x06b], 0x02); DBG(DBG_FNC, "0x006b"); DBG(DBG_FNC, " bit[0..35] = timing.cph3p2: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x06f], 0x01); DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x074], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x072], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x070], 0x02); DBG(DBG_FNC, "\n0x0070 Linear Image Sensor Clock 5\n"); DBG(DBG_FNC, " bit[0..35] = timing.cph4p1: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x074], 0x01); DBG(DBG_FNC, " bit[36] = timing.cph4go: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = timing.cph4ge: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = timing.cph4ps: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x079], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x077], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x075], 0x02); DBG(DBG_FNC, "0x0075"); DBG(DBG_FNC, " bit[0..35] = timing.cph4p2: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x079], 0x01); DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x07e], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x07c], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x07a], 0x02); DBG(DBG_FNC, "\n0x007a Linear Image Sensor Clock 6\n"); DBG(DBG_FNC, " bit[0..35] = timing.cph5p1: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x07e], 0x01); DBG(DBG_FNC, " bit[36] = timing.cph5go: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = timing.cph5ge: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = timing.cph5ps: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x083], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x081], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x07f], 0x02); DBG(DBG_FNC, "0x007f"); DBG(DBG_FNC, " bit[0..35] = timing.cph5p2: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x083], 0x01); DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); iValue = data_lsb_get(&buffer[0x084], 3); DBG(DBG_FNC, "\n0x0084"); DBG(DBG_FNC, " timing.cphbp2s : 0x%06x\n", iValue); iValue = data_lsb_get(&buffer[0x087], 3); DBG(DBG_FNC, "0x0087"); DBG(DBG_FNC, " timing.cphbp2e : 0x%06x\n", iValue); iValue = data_lsb_get(&buffer[0x08a], 3); DBG(DBG_FNC, "0x008a"); DBG(DBG_FNC, " timing.clamps : 0x%08x\n", iValue); iValue = data_lsb_get(&buffer[0x08d], 3); DBG(DBG_FNC, "0x008d"); DBG(DBG_FNC, " timing.clampe or cphbp2e : 0x%08x\n", iValue); iValue = data_lsb_get(&buffer[0x092], 0x01); DBG(DBG_FNC, "\n0x0092 Correlated-Double-Sample 1\n"); DBG(DBG_FNC, " bit[0..5] = timing.cdss[0]: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x093], 0x01); DBG(DBG_FNC, "0x0093"); DBG(DBG_FNC, " bit[0..5] = timing.cdsc[0]: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x094], 0x01); DBG(DBG_FNC, "\n0x0094 Correlated-Double-Sample 2\n"); DBG(DBG_FNC, " bit[0..5] = timing.cdss[1]: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x095], 0x01); DBG(DBG_FNC, "0x0095"); DBG(DBG_FNC, " bit[0..5] = timing.cdsc[1]: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x096], 0x01); DBG(DBG_FNC, "0x0096"); DBG(DBG_FNC, " bit[0..5] = timing.cnpp: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x09b], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x099], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x097], 0x02); DBG(DBG_FNC, "\n0x0097 Analog to Digital Converter clock 1\n"); DBG(DBG_FNC, " bit[0..35] = timing.adcclkp[0]: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x09b], 0x01); DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); DBG(DBG_FNC, " bit[36] = ?: 0x%02x\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); dbg_buffer(DBG_FNC, "\n0x009c CIS sensor 1", &buffer[0x09c], 0x06, 0x9c); dbg_buffer(DBG_FNC, "0x00a2 CIS sensor 2", &buffer[0x0a2], 0x06, 0xa2); dbg_buffer(DBG_FNC, "0x00a8 CIS sensor 3", &buffer[0x0a8], 0x06, 0xa8); iValue = data_lsb_get(&buffer[0x0ae], 0x01); DBG(DBG_FNC, "\n0x00ae"); DBG(DBG_FNC, " bit[0..5] = ?: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x0af], 0x01); DBG(DBG_FNC, "0x00af"); DBG(DBG_FNC, " bit[0..2] = ?: 0x%02x\n", iValue & 7); DBG(DBG_FNC, " bit[3..7] = ?: 0x%02x\n", (iValue >> 3) & 0x1f); iValue = data_lsb_get(&buffer[0x0b0], 2); DBG(DBG_FNC, "\n0x00b0"); DBG(DBG_FNC, " Left : 0x%04x\n", iValue); iValue = data_lsb_get(&buffer[0x0b2], 2); DBG(DBG_FNC, "0x00b2"); DBG(DBG_FNC, " Right: 0x%04x\n", iValue); dbg_buffer(DBG_FNC, "\n0x00b4", &buffer[0x0b4], 12, 0xb4); iValue = data_lsb_get(&buffer[0x0c0], 0x01); DBG(DBG_FNC, "\n0x00c0"); DBG(DBG_FNC, " bit[0..4] = resolution ratio: 0x%02x\n", iValue & 0x1f); DBG(DBG_FNC, " bit[5..7] = ?: 0x%02x\n", (iValue >> 5) & 7); iValue = data_lsb_get(&buffer[0x0c5], 0x01) & 0x0f; dValue = iValue * pow(2, 32); iValue = data_lsb_get(&buffer[0x0c3], 0x02); dValue = dValue + (iValue * pow(2, 16)) + data_lsb_get(&buffer[0x0c1], 2); DBG(DBG_FNC, "\n0x00c1 Analog to Digital Converter clock 2\n"); DBG(DBG_FNC, " bit[0..35] = timing.adcclkp[1]: %.0f.\n", dValue); iValue = data_lsb_get(&buffer[0x0c5], 0x01); DBG(DBG_FNC, " bits[36..39] = 0x%02x\n", (iValue >> 0x04) & 0x0f); DBG(DBG_FNC, " bit[36] = ?: 0x%02x (equal to bit[32])\n", (iValue >> 0x04) & 0x01); DBG(DBG_FNC, " bit[37] = ?: 0x%02x\n", (iValue >> 0x05) & 0x01); DBG(DBG_FNC, " bit[38] = ?: 0x%02x\n", (iValue >> 0x06) & 0x01); DBG(DBG_FNC, " bit[39] = ?: 0x%02x\n", (iValue >> 0x07) & 0x01); dbg_buffer(DBG_FNC, "\n0x00c6", &buffer[0x0c6], 0x0a, 0xc6); iValue = ((buffer[0x0d4] & 0x0f) << 0x10) + data_lsb_get(&buffer[0x0d0], 0x02); DBG(DBG_FNC, "\n0x00d0"); DBG(DBG_FNC, " Top : 0x%04x\n", iValue); iValue = ((buffer[0x0d4] & 0xf0) << 0x06)+ data_lsb_get(&buffer[0x0d2], 0x02); DBG(DBG_FNC, "x00d2"); DBG(DBG_FNC, " Down: 0x%04x\n", iValue); iValue = _B0(buffer[0x0d5]); DBG(DBG_FNC, "0x00d5"); DBG(DBG_FNC, " ?: 0x%04x\n", iValue); iValue = data_lsb_get(&buffer[0x0d6], 1); DBG(DBG_FNC, "\n0x00d6"); DBG(DBG_FNC, " bit[0..3] = ? : 0x%02x\n", iValue & 0xf); DBG(DBG_FNC, " bit[4..7] = dummyline: 0x%02x\n", (iValue >> 4) & 0xf); iValue = data_lsb_get(&buffer[0x0d7], 0x01); DBG(DBG_FNC, "\n0x00d7"); DBG(DBG_FNC, " bit[0..5] = motor pwm frequency: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6] = ?: 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = motor type: 0x%02x ", (iValue >> 7) & 1); if (((iValue >> 7) & 1) == MT_OUTPUTSTATE) DBG(DBG_FNC, ": Output state machine\n"); else DBG(DBG_FNC, "On-Chip PWM\n"); iValue = data_lsb_get(&buffer[0x0d8], 0x01); DBG(DBG_FNC, "\n0x00d8"); DBG(DBG_FNC, " bit[0..5] = ?: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6] = scantype (0=Normal|1=TMA) : 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = enable head movement : 0x%02x :", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x0d9], 0x01); DBG(DBG_FNC, "\n0x00d9"); DBG(DBG_FNC, " bit[0..2] = ?: 0x%02x\n", iValue & 7); DBG(DBG_FNC, " bit[3] = ?: 0x%02x\n", (iValue >> 3) & 1); DBG(DBG_FNC, " bit[4..6] = motor step type: 0x%02x: ", (iValue >> 4) & 7); switch((iValue >> 4) & 7) { case 0: DBG(DBG_FNC, "full (1)\n"); break; case 1: DBG(DBG_FNC, "half (1/2)\n"); break; case 2: DBG(DBG_FNC, "quart (1/4)\n"); break; case 3: DBG(DBG_FNC, "(1/8)\n"); break; default: DBG(DBG_FNC, "unknown\n"); break; } DBG(DBG_FNC, " bit[7] = Motor direction: 0x%02x = ", (iValue >> 7) & 1); if (((iValue >> 7) & 1) == 0) DBG(DBG_FNC, "Backward\n"); else DBG(DBG_FNC, "Forward\n"); iValue = data_lsb_get(&buffer[0x0dd], 0x01); DBG(DBG_FNC, "\n0x00da"); DBG(DBG_FNC, " msi = 0x%03x\n", ((iValue & 3) << 8) + data_lsb_get(&buffer[0x0da], 1)); DBG(DBG_FNC, "0x00db"); DBG(DBG_FNC, " motorbackstep1 = 0x%03x\n", ((iValue & 0x0c) << 6) + data_lsb_get(&buffer[0x0db], 1)); DBG(DBG_FNC, "0x00dc"); DBG(DBG_FNC, " motorbackstep2 = 0x%03x\n", ((iValue & 0x30) << 4) + data_lsb_get(&buffer[0x0dc], 1)); iValue = data_lsb_get(&buffer[0x0dd], 0x01); DBG(DBG_FNC, "0x00dd"); DBG(DBG_FNC, " bit[7] = Motor enabled?: 0x%02x = ", (iValue >> 7) & 1); if (((iValue >> 7) & 1) == 0) DBG(DBG_FNC, "Yes\n"); else DBG(DBG_FNC, "No\n"); iValue = data_lsb_get(&buffer[0x0de], 0x02); DBG(DBG_FNC, "\n0x00de"); DBG(DBG_FNC, " bit[00..11] = ?: 0x%02x\n", iValue & 0xfff); DBG(DBG_FNC, " bit[12..15] = ?: 0x%02x\n", (iValue >> 12) & 0x0f); iValue = data_lsb_get(&buffer[0x0df], 0x01); DBG(DBG_FNC, "\n0x00df"); DBG(DBG_FNC, " bit[0..3] = ?: 0x%02x\n", iValue & 0x0f); DBG(DBG_FNC, " bit[4] = has_motorcurves?: 0x%02x\n", (iValue >> 4) & 0x01); DBG(DBG_FNC, " bit[5..7] = ?: 0x%02x\n", (iValue >> 5) & 7); iValue = data_lsb_get(&buffer[0x0e0], 1); DBG(DBG_FNC, "\n0x00e0 step size - 1 : 0x%02x\n", iValue); iValue = data_lsb_get(&buffer[0x0e1], 3); DBG(DBG_FNC, "\n0x00e1 0x%06x : last step of accurve.normalscan table\n", iValue); iValue = data_lsb_get(&buffer[0x0e4], 3); DBG(DBG_FNC, "0x00e4 0x%06x : last step of accurve.smearing table\n", iValue); iValue = data_lsb_get(&buffer[0x0e7], 3); DBG(DBG_FNC, "0x00e7 0x%06x : last step of accurve.parkhome table\n", iValue); iValue = data_lsb_get(&buffer[0x0ea], 3); DBG(DBG_FNC, "0x00ea 0x%06x : last step of deccurve.scanbufferfull table\n", iValue); iValue = data_lsb_get(&buffer[0x0ed], 3); DBG(DBG_FNC, "0x00ed 0x%06x : last step of deccurve.normalscan table\n", iValue); iValue = data_lsb_get(&buffer[0x0f0], 3); DBG(DBG_FNC, "0x00f0 0x%06x : last step of deccurve.smearing table\n", iValue); iValue = data_lsb_get(&buffer[0x0f3], 3); DBG(DBG_FNC, "0x00f3 0x%06x : last step of deccurve.parkhome table\n", iValue); iValue = data_lsb_get(&buffer[0x0f6], 2); DBG(DBG_FNC, "\n0x00f6 bit[00..13] = 0x%04x : ptr to accurve.normalscan step table\n", iValue & 0x3fff); DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x0f8], 2); DBG(DBG_FNC, "0x00f8"); DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to deccurve.scanbufferfull step table\n", iValue & 0x3fff); DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x0fa], 2); DBG(DBG_FNC, "0x00fa"); DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to accurve.smearing step table\n", iValue & 0x3fff); DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x0fc], 2); DBG(DBG_FNC, "0x00fc"); DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to deccurve.smearing step table\n", iValue & 0x3fff); DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x0fe], 2); DBG(DBG_FNC, "0x00fe"); DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to deccurve.normalscan step table\n", iValue & 0x3fff); DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x100], 2); DBG(DBG_FNC, "0x0100"); DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to accurve.parkhome step table\n", iValue & 0x3fff); DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x102], 2); DBG(DBG_FNC, "0x0102"); DBG(DBG_FNC, " bit[00..13] = 0x%04x : ptr to deccurve.parkhome step table\n", iValue & 0x3fff); DBG(DBG_FNC, " bit[14..15] = 0x%04x : ?\n",(iValue >> 14) & 3); dbg_buffer(DBG_FNC, "\n0x0104 Motor resource", &buffer[0x104], 0x20, 0x104); dbg_buffer(DBG_FNC, "\n0x0124", &buffer[0x124], 0x22, 0x124); iValue = data_lsb_get(&buffer[0x146], 1); DBG(DBG_FNC, "\n0x0146"); DBG(DBG_FNC, " bit[0..3] = Lamp pulse-width modulation frequency : 0x%02x\n", iValue & 0xf); DBG(DBG_FNC, " bit[4] = timer enabled? : 0x%02x\n", (iValue >> 4) & 1); DBG(DBG_FNC, " bit[5] = ? : 0x%02x\n", (iValue >> 5) & 1); DBG(DBG_FNC, " bit[6] = lamp turned on? : 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = sensor type : 0x%02x ", (iValue >> 7) & 1); if (((iValue >> 7) & 1) != 0) DBG(DBG_FNC, "CCD\n"); else DBG(DBG_FNC, "CIS\n"); iValue = data_lsb_get(&buffer[0x147], 1); DBG(DBG_FNC, "\n0x0147"); DBG(DBG_FNC, " time to turn off lamp = 0x%02x (minutes * 2.682163611980331)\n", iValue); iValue = data_lsb_get(&buffer[0x148], 1); DBG(DBG_FNC, "\n0x0148"); DBG(DBG_FNC, " bit[0..5] = Lamp pulse-width modulation duty cycle : 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ? : 0x%02x\n",(iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x149], 1); DBG(DBG_FNC, "\n0x0149"); DBG(DBG_FNC, " bit[0..5] = even_odd_distance : 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ? : 0x%02x\n",(iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x14a], 1); DBG(DBG_FNC, "0x014a"); DBG(DBG_FNC, " bit[0..5] = sensor line distance : 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n",(iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x14b], 1); DBG(DBG_FNC, "0x014b"); DBG(DBG_FNC, " bit[0..5] = sensor line distance + even_odd_distance: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n",(iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x14c], 1); DBG(DBG_FNC, "0x014c"); DBG(DBG_FNC, " bit[0..5] = sensor line distance * 2: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x14d], 1); DBG(DBG_FNC, "0x014d"); DBG(DBG_FNC, " bit[0..5] = (sensor line distance * 2) + even_odd_distance: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 3); iValue = data_lsb_get(&buffer[0x14e], 1); DBG(DBG_FNC, "\n0x014e"); DBG(DBG_FNC, " bit[0..3] = ?: 0x%02x\n", iValue & 0xf); DBG(DBG_FNC, " bit[4] = ?: 0x%02x\n", (iValue >> 4) & 1); DBG(DBG_FNC, " bit[5..7] = ?: 0x%02x\n", (iValue >> 5) & 7); dbg_buffer(DBG_FNC, "\n0x014f", &buffer[0x14f], 0x05, 0x14f); iValue = data_lsb_get(&buffer[0x154], 1); DBG(DBG_FNC, "\n0x0154"); DBG(DBG_FNC, " bit[0..3] = ?: 0x%02x\n", iValue & 0xf); DBG(DBG_FNC, " bit[4..5] = ?: 0x%02x\n", (iValue >> 4) & 3); DBG(DBG_FNC, " bit[6..7] = ?: 0x%02x\n", (iValue >> 6) & 7); iValue = data_lsb_get(&buffer[0x155], 1); DBG(DBG_FNC, "\n0x0155"); DBG(DBG_FNC, " bit[0..3] = ?: 0x%02x\n", iValue & 0x0f); DBG(DBG_FNC, " bit[4] = 0x%02x : ", (iValue >> 4) & 1); if (((iValue >> 4) & 1) == 0) DBG(DBG_FNC, "flb lamp\n"); else DBG(DBG_FNC, "tma lamp\n"); DBG(DBG_FNC, " bit[5..7] = ? : 0x%02x\n", (iValue >> 5) & 7); dbg_buffer(DBG_FNC, "\n0x0156", &buffer[0x156], 0x02, 0x156); iValue = data_lsb_get(&buffer[0x158], 1); DBG(DBG_FNC, "\n0x0158"); DBG(DBG_FNC, " bit[0..3] = %02x : Scanner buttons ", iValue & 0x0f); if ((iValue & 0x0f) == 0x0f) DBG(DBG_FNC, "enabled\n"); else DBG(DBG_FNC, "dissabled\n"); DBG(DBG_FNC, " bit[4..7] = ? : 0x%02x\n", (iValue >> 4) & 0x0f); dbg_buffer(DBG_FNC, "\n0x0159", &buffer[0x159], 11, 0x159); iValue = data_lsb_get(&buffer[0x164], 1); DBG(DBG_FNC, "\n0x0164"); DBG(DBG_FNC, " bit[0..6] = ?: 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); dbg_buffer(DBG_FNC, "\n0x0165", &buffer[0x165], 3, 0x165); iValue = data_lsb_get(&buffer[0x168], 1); DBG(DBG_FNC, "\n0x0168 Buttons status : 0x%02x\n", iValue); DBG(DBG_FNC, " bit[0] = button 1 : 0x%02x\n", iValue & 1); DBG(DBG_FNC, " bit[1] = button 2 : 0x%02x\n", (iValue >> 1) & 1); DBG(DBG_FNC, " bit[2] = button 4 : 0x%02x\n", (iValue >> 2) & 1); DBG(DBG_FNC, " bit[3] = button 3 : 0x%02x\n", (iValue >> 3) & 1); DBG(DBG_FNC, " bit[4] = button ? : 0x%02x\n", (iValue >> 4) & 1); DBG(DBG_FNC, " bit[5] = button ? : 0x%02x\n", (iValue >> 5) & 1); DBG(DBG_FNC, " bit[6] = ? : 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x169], 1); DBG(DBG_FNC, "\n0x0169", iValue); DBG(DBG_FNC, " bit[0] = ? : 0x%02x\n", iValue & 1); DBG(DBG_FNC, " bit[1] = tma attached? : 0x%02x\n", (iValue >> 1) & 1); DBG(DBG_FNC, " bit[2..7] = ? : 0x%02x\n", (iValue >> 2) & 0x3f); iValue = data_lsb_get(&buffer[0x16a], 1); DBG(DBG_FNC, "\n0x016a Buttons status 2: 0x%02x\n", iValue); DBG(DBG_FNC, " bit[0] = button 1 : 0x%02x\n", iValue & 1); DBG(DBG_FNC, " bit[1] = button 2 : 0x%02x\n", (iValue >> 1) & 1); DBG(DBG_FNC, " bit[2] = button 4 : 0x%02x\n", (iValue >> 2) & 1); DBG(DBG_FNC, " bit[3] = button 3 : 0x%02x\n", (iValue >> 3) & 1); DBG(DBG_FNC, " bit[4] = button ? : 0x%02x\n", (iValue >> 4) & 1); DBG(DBG_FNC, " bit[5] = button ? : 0x%02x\n", (iValue >> 5) & 1); DBG(DBG_FNC, " bit[6] = ? : 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); dbg_buffer(DBG_FNC, "\n0x016b", &buffer[0x16b], 4, 0x16b); iValue = data_lsb_get(&buffer[0x16f], 1); DBG(DBG_FNC, "\n0x016f"); DBG(DBG_FNC, " bit[0..5] = ? : 0x%02x\n", iValue & 0x3f); DBG(DBG_FNC, " bit[6] = is lamp at home? : 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = ?: %02x\n", (iValue >> 7) & 1); dbg_buffer(DBG_FNC, "\n0x0170", &buffer[0x170], 0x17, 0x170); iValue = data_lsb_get(&buffer[0x187], 1); DBG(DBG_FNC, "\n0x0187"); DBG(DBG_FNC, " bit[0..3] = ? : 0x%02x\n", iValue & 0xf); DBG(DBG_FNC, " bit[4..7] = mclkioc : 0x%02x\n", (iValue >> 4) & 0xf); dbg_buffer(DBG_FNC, "\n0x0188", &buffer[0x188], 0x16, 0x188); iValue = data_lsb_get(&buffer[0x19e], 2); DBG(DBG_FNC, "\n0x019e"); DBG(DBG_FNC, " binary threshold low : 0x%04x\n", (iValue >> 8) + ((iValue << 8) & 0xff00)); iValue = data_lsb_get(&buffer[0x1a0], 2); DBG(DBG_FNC, "\n0x01a0"); DBG(DBG_FNC, " binary threshold high : 0x%04x\n", (iValue >> 8) + ((iValue << 8) & 0xff00)); dbg_buffer(DBG_FNC, "\n0x01a2", &buffer[0x1a2], 0x12, 0x1a2); iValue = data_lsb_get(&buffer[0x1b4], 2); DBG(DBG_FNC, "\n0x01b4"); DBG(DBG_FNC, " bit[00..13] = Ptr to red gamma table (table_size * 0) : 0x%04x\n", (iValue & 0x3fff)); DBG(DBG_FNC, " bit[14..15] = ? : 0x%02x\n", (iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x1b6], 2); DBG(DBG_FNC, "0x01b6"); DBG(DBG_FNC, " bit[00..13] = Ptr to green gamma table (table_size * 1) : 0x%04x\n", (iValue & 0x3fff)); DBG(DBG_FNC, " bit[14..15] = ? : 0x%02x\n", (iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x1b8], 2); DBG(DBG_FNC, "0x01b8"); DBG(DBG_FNC, " bit[00..13] = Ptr to blue gamma table (table_size * 2) : 0x%04x\n", (iValue & 0x3fff)); DBG(DBG_FNC, " bit[14..15] = ? : 0x%02x\n", (iValue >> 14) & 3); iValue = data_lsb_get(&buffer[0x1ba], 1); DBG(DBG_FNC, "\n0x01ba"); DBG(DBG_FNC, " ? : 0x%02x\n", iValue); iValue = data_lsb_get(&buffer[0x1bb], 2); DBG(DBG_FNC, "0x01bb"); DBG(DBG_FNC, " ? : 0x%04x\n", iValue + ((data_lsb_get(&buffer[0x1bf], 1) & 1) << 16)); iValue = data_lsb_get(&buffer[0x1bd], 2); DBG(DBG_FNC, "0x01bd"); DBG(DBG_FNC, " ? : 0x%04x\n", iValue + (((data_lsb_get(&buffer[0x1bf], 1) >> 1) & 3) << 16)); iValue = data_lsb_get(&buffer[0x1c0], 3); DBG(DBG_FNC, "0x01c0"); DBG(DBG_FNC, " bit[0..19] = ? : 0x%06x\n", iValue & 0xfffff); iValue = data_lsb_get(&buffer[0x1bf], 2); DBG(DBG_FNC, "\n0x01bf"); DBG(DBG_FNC, " bit[3..4] = ? : 0x%02x\n", (iValue >> 3) & 3); DBG(DBG_FNC, " bit[5..7] = ? : 0x%02x\n", (iValue >> 5) & 7); iValue = data_lsb_get(&buffer[0x1c2], 3); DBG(DBG_FNC, "\n0x01c2"); DBG(DBG_FNC, " bit[4..23] = ? : 0x%06x\n", ((iValue >> 8) & 0xffff) + (((iValue >> 4) & 0xf) << 16)); iValue = data_lsb_get(&buffer[0x1c5], 3); DBG(DBG_FNC, "0x01c5"); DBG(DBG_FNC, " bit[00..19] = ? : 0x%06x\n", iValue & 0xfffff); DBG(DBG_FNC, " bit[20..23] = ? : 0x%02x\n", (iValue >> 20) & 0xf); dbg_buffer(DBG_FNC, "\n0x01c8", &buffer[0x1c8], 7, 0x1c8); iValue = data_lsb_get(&buffer[0x1cf], 3); DBG(DBG_FNC, "\n0x01cf"); DBG(DBG_FNC, " bit[0] = ? : 0x%02x\n", iValue & 1); DBG(DBG_FNC, " bit[1] = shading base (0 = 0x4000|1= 0x2000) : 0x%02x\n", (iValue >> 1) & 1); DBG(DBG_FNC, " bit[2] = white shading correction : 0x%02x\n", (iValue >> 2) & 1); DBG(DBG_FNC, " bit[3] = black shading correction : 0x%02x\n", (iValue >> 3) & 1); DBG(DBG_FNC, " bit[4..5] = 0x%02x : ", (iValue >> 4) & 3); switch ((iValue >> 4) & 3) { case 0: DBG(DBG_FNC, "8 bits per channel"); break; case 1: DBG(DBG_FNC, "12 bits per channel"); break; case 2: DBG(DBG_FNC, "16 bits per channel"); break; case 3: DBG(DBG_FNC, "lineart mode"); break; } DBG(DBG_FNC, "\n"); DBG(DBG_FNC, " bit[6] = samplerate: 0x%02x ", (iValue >> 6) & 1); if (((iValue >> 6) & 1) == PIXEL_RATE) DBG(DBG_FNC, "PIXEL_RATE\n"); else DBG(DBG_FNC, "LINE_RATE\n"); DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); iValue = data_lsb_get(&buffer[0x1d0], 1); DBG(DBG_FNC, "\n0x01d0"); DBG(DBG_FNC, " bit[0] = 0x%02x\n", iValue & 1); DBG(DBG_FNC, " bit[1] = 0x%02x\n", (iValue >> 1) & 1); DBG(DBG_FNC, " bit[2..3] = gamma table size : 0x%02x ", (iValue >> 2) & 3); switch ((iValue >> 2) & 3) { case 0: DBG(DBG_FNC, "bit[0] + 0x100") ;break; case 1: DBG(DBG_FNC, "bit[0] + 0x400") ;break; case 2: DBG(DBG_FNC, "bit[0] + 0x1000") ;break; } DBG(DBG_FNC, "\n"); DBG(DBG_FNC, " bit[4..5] = ? : 0x%02x\n", (iValue >> 4) & 3); DBG(DBG_FNC, " bit[6] = use gamma tables? : 0x%02x\n", (iValue >> 6) & 1); DBG(DBG_FNC, " bit[7] = ? : 0x%02x\n", (iValue >> 7) & 1); dbg_buffer(DBG_FNC, "\n0x01d1", &buffer[0x1d1], 0x430, 0x1d1); DBG(DBG_FNC, "----------------------------------------------------\n\n"); */ /*exit(0); */ } #endif sane-backends-1.0.27/backend/plustek.conf.in0000664000175000017500000001005612112021330015537 00000000000000# Plustek-SANE Backend configuration file # For use with LM9831/2/3 based USB scanners # # each device needs at least two lines: # - [usb] vendor-ID and product-ID # - device devicename # i.e. for Plustek (0x07B3) UT12/16/24 (0x0017) # [usb] 0x07B3 0x0017 # device /dev/usbscanner # or # device libusb:bbb:ddd # where bbb is the busnumber and ddd the device number # make sure that your user has access to /proc/bus/usb/bbb/ddd # # additionally you can specify some options # warmup, lOffOnEnd, lampOff # # For autodetection use # [usb] # device /dev/usbscanner # # or simply # [usb] # # or if you want a specific device but you have no idea about the # device node or you use libusb, simply set vendor- and product-ID # [usb] 0x07B3 0x0017 # device auto # # NOTE: autodetection is safe, as it uses the info it got # from the USB subsystem. If you're not using the # autodetection, you MUST have attached that device # at your USB-port, that you have specified... # [usb] # # options for the previous USB entry # # switch lamp off after xxx secs, 0 disables the feature # (can also be set via frontend) option lampOff 300 # warmup period in seconds, 0 means no warmup, -1 means auto-warmup # (can also be set via frontend) option warmup -1 # 0 means leave lamp-status untouched, not 0 means switch off # on sane_close # (can also be set via frontend) option lOffOnEnd 1 # # options to tweak the image start-position # (WARNING: there's no internal range check!!!) # # for the normal scan area # option posOffX 0 option posOffY 0 # for transparencies option tpaOffX 0 option tpaOffY 0 # for negatives option negOffX 0 option negOffY 0 # # for setting the calibration strip position # (WARNING: there's no internal range check!!!) # -1 means use built in # (can also be set via frontend) option posShadingY -1 option tpaShadingY -1 option negShadingY -1 # # to invert the negatives, 0 disables the feature # option invertNegatives 0 # # to disable the internal sensor speedup function, # 1 disables the feature # option disableSpeedup 0 # # to save/restore coarse calibration data # (can also be set via frontend) option cacheCalData 0 # # use alternate calibration routines # option altCalibration 0 # # for skipping whole calibration step # option skipCalibration 0 # # for skipping entire fine calibration step # coarse calibration is done # option skipFine 0 # # discard the result of the fine white calibration # option skipFineWhite 0 # # some scanners have a dark calibration strip, in # general this one should be used for calibration. # As this could cause some trouble, this option # overrides that and the dark calibration will be # done by switching the lamp off # option skipDarkStrip 0 # for replacing the gain values found during coarse # calibration # (can also be set via frontend) option red_gain -1 option green_gain -1 option blue_gain -1 # for replacing the offset values found during coarse # calibration # (can also be set via frontend) option red_offset -1 option green_offset -1 option blue_offset -1 # # for replacing the default lampoff settings, this # works only for CIS devices like CanoScan LiDE20 # (can also be set via frontend) option red_lampoff -1 option green_lampoff -1 option blue_lampoff -1 # # for adjusting the default gamma values # (can also be set via frontend) option redGamma 1.0 option greenGamma 1.0 option blueGamma 1.0 option grayGamma 1.0 # # to enable TPA (EPSON or UMAX, if autodetection fails) # 0 means default behaviour as specified in the internal tables # 1 means enable (needed for UMAX 3450) option enableTPA 0 # # model override functionality, currently only available for # Mustek devices, using NSCs' vendor ID: 0x0400 and # also their product ID: 0x1000 (LM9831) 0x1001 (LM9832) # # mov/PID | 0x1000 | 0x1001 # --------------------------------------- # 0 (default)| BearPaw1200 | BearPaw 2400 # 1 | ignored | BearPaw 1200 # option mov 0 # # and of course the device-name # # device /dev/usbscanner device auto # # to define a new device, start with a new section: # [usb] # sane-backends-1.0.27/backend/coolscan.conf.in0000664000175000017500000000004212112021330015643 00000000000000scsi Nikon * Scanner /dev/scanner sane-backends-1.0.27/backend/epson2-cct.c0000664000175000017500000010654212112021330014723 00000000000000/* epson2 hardware colour correction coefficients * Copyright (C) 2001-2009 SEIKO EPSON Corporation * Copyright (C) 2009 Tower Technologies * * License: GPLv2 * * This file is part of the SANE epson2 backend and has been derived * from the epkowa backend distributed with Image Scan! * */ /*! Hardware colour correction coefficients (CCC). Each entry starts with a unique identifier, followed by four CCC profiles; the first is for reflective materials, the second for colour negatives, the third for monochrome negatives, and the fourth and last one is for colour positives. */ #define DEBUG_DECLARE_ONLY #include "epson2.h" const struct epson_profile epson_cct_profiles[] = { {0x00, /* default */ {{1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x05, /* ES-6000H */ {{1.1419,-0.0596,-0.0825,-0.1234, 1.2812,-0.1413, 0.0703,-0.5720, 1.5016}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1419,-0.0596,-0.0825,-0.1234, 1.2812,-0.1413, 0.0703,-0.5720, 1.5016}}}, {0x06, /* GT-6600 */ {{1.1442,-0.0705,-0.0737,-0.0702, 1.1013,-0.0311,-0.0080,-0.3588, 1.3668}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x07, /* GT-7600 */ {{1.1967,-0.1379,-0.0588,-0.0538, 1.0385, 0.0153, 0.0348,-0.4070, 1.3721}, {1.0010,-0.0010, 0.0000,-0.1120, 1.1710,-0.0590, 0.0000,-0.0910, 1.0920}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1967,-0.1379,-0.0588,-0.0538, 1.0385, 0.0153, 0.0348,-0.4070, 1.3721}}}, {0x0D, /* ES-2000 */ {{1.1980,-0.1365,-0.0616,-0.1530, 1.1729,-0.0198,-0.0025,-0.2776, 1.2801}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1980,-0.1365,-0.0616,-0.1530, 1.1729,-0.0198,-0.0025,-0.2776, 1.2801}}}, {0x0F, /* ES-8500 */ {{1.0961,-0.0181,-0.0779,-0.1279, 1.1957,-0.0678, 0.0315,-0.3891, 1.3576}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0961,-0.0181,-0.0779,-0.1279, 1.1957,-0.0678, 0.0315,-0.3891, 1.3576}}}, {0x15, /* GT-6700 */ {{1.0999,-0.0425,-0.0574,-0.0806, 1.0835,-0.0028, 0.0057,-0.2924, 1.2866}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x16, /* GT-8700 */ {{1.2020,-0.1518,-0.0502,-0.0847, 1.1385,-0.0538, 0.0059,-0.3255, 1.3196}, {1.0030,-0.0030, 0.0000,-0.0980, 1.1500,-0.0520,-0.0030,-0.0840, 1.0880}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2456,-0.1617,-0.0839,-0.1160, 1.1862,-0.0702,-0.0036,-0.3438, 1.3473}}}, {0x18, /* GT-7700 */ {{1.1339,-0.0526,-0.0813,-0.1177, 1.1661,-0.0485,-0.0030,-0.3298, 1.3328}, {1.0010,-0.0010, 0.0000,-0.1120, 1.1710,-0.0590, 0.0000,-0.0910, 1.0920}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2066,-0.0360,-0.1706,-0.1313, 1.2523,-0.1210,-0.0299,-0.3377, 1.3676}}}, {0x1A, /* ES-9000H */ {{1.0986, 0.0235,-0.1221,-0.1294, 1.0896, 0.0399, 0.0928,-0.6043, 1.5115}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x1B, /* ES-2200 */ {{1.1855,-0.1372,-0.0483,-0.2060, 1.2468,-0.0407, 0.0358,-0.3059, 1.2701}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1976,-0.1182,-0.0794,-0.1578, 1.2720,-0.1142, 0.0122,-0.3467, 1.3345}}}, {0x1D, /* GT-7200 */ {{1.0675,-0.0586,-0.0088,-0.0332, 0.9716, 0.0616, 0.0175,-0.4054, 1.3879}, {1.0090,-0.0090, 0.0000,-0.0390, 1.0750,-0.0360,-0.0070,-0.1060, 1.1130}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1394,-0.0829,-0.0564,-0.0003, 1.0008,-0.0004,-0.0059,-0.3674, 1.3733}}}, {0x1F, /* GT-8200 */ {{1.0800,-0.0607,-0.0193,-0.0787, 1.0846,-0.0059, 0.0135,-0.3334, 1.3199}, {1.0040,-0.0040, 0.0000,-0.0780, 1.1360,-0.0570,-0.0020,-0.0810, 1.0830}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1334,-0.0929,-0.0405,-0.0418, 1.0689,-0.0271,-0.0521,-0.3262, 1.3783}}}, {0x21, /* GT-9700 */ {{1.0919,-0.0739,-0.0180,-0.0941, 1.1150,-0.0209, 0.0220,-0.3744, 1.3524}, {1.0090,-0.0100, 0.0010,-0.0720, 1.1310,-0.0600, 0.0000,-0.1000, 1.1000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1374,-0.1396, 0.0021,-0.0489, 1.0655,-0.0166, 0.0081,-0.3492, 1.3411}}}, {0x23, /* GT-7300 */ {{1.0339,-0.0166,-0.0173,-0.0117, 0.9797, 0.0319, 0.0010,-0.3609, 1.3599}, {1.0090,-0.0090, 0.0000,-0.0390, 1.0750,-0.0360,-0.0070,-0.1060, 1.1130}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1666,-0.0898,-0.0768,-0.0076, 1.0157,-0.0081, 0.0012,-0.3048, 1.3036}}}, {0x25, /* GT-8300 */ {{1.0800,-0.0607,-0.0193,-0.0787, 1.0846,-0.0059, 0.0135,-0.3334, 1.3199}, {1.0040,-0.0040, 0.0000,-0.0780, 1.1360,-0.0570,-0.0020,-0.0810, 1.0830}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1334,-0.0929,-0.0405,-0.0418, 1.0689,-0.0271,-0.0521,-0.3262, 1.3783}}}, {0x27, /* GT-9300 */ {{1.0919,-0.0739,-0.0180,-0.0941, 1.1150,-0.0209, 0.0220,-0.3744, 1.3524}, {1.0083,-0.0094, 0.0011,-0.0760, 1.1379,-0.0619,-0.0002,-0.0945, 1.0947}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1952,-0.1519,-0.0433,-0.0932, 1.1613,-0.0681,-0.0418,-0.3140, 1.3558}}}, {0x29, /* GT-9800F */ {{1.0369,-0.0210,-0.0160,-0.0820, 1.1160,-0.0341, 0.0150,-0.5035, 1.4885}, {1.0122,-0.0151, 0.0029,-0.0861, 1.1402,-0.0542,-0.0061,-0.1607, 1.1669}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1764,-0.1749,-0.0014,-0.0590, 1.0983,-0.0393, 0.0208,-0.5194, 1.4986}}}, {0x2B, /* ES-7000H */ {{1.0305,-0.0116,-0.0189,-0.0936, 1.1245,-0.0309,-0.0072,-0.1413, 1.1485}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x32, /* GT-9400 */ {{1.0932,-0.0529,-0.0403,-0.1077, 1.1416,-0.0338, 0.0079,-0.5525, 1.5446}, {1.0259,-0.0356, 0.0097,-0.1085, 1.2225,-0.1140,-0.0046,-0.1848, 1.1894}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2720,-0.2665,-0.0054,-0.0672, 1.1301,-0.0629,-0.0048,-0.3917, 1.3965}}}, {0x2D, /* CC-600PX */ {{1.0436,-0.0078,-0.0359,-0.0169, 1.0114, 0.0056, 0.0308,-0.4425, 1.4117}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x3A, /* PM-A850 */ {{1.1150,-0.0677,-0.0473,-0.1179, 1.1681,-0.0502, 0.0052,-0.4858, 1.4806}, {1.0133,-0.0151, 0.0017,-0.1216, 1.2207,-0.0991,-0.0003,-0.1512, 1.1515}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2105,-0.1644,-0.0461,-0.1124, 1.1945,-0.0820,-0.0450,-0.3367, 1.3817}}}, {0x36, /* CX5300/CX5400 */ {{1.0848,-0.0153,-0.0695,-0.0902, 1.0611, 0.0291, 0.0344,-0.5002, 1.4658}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x34, /* GT-X700 */ {{1.1032,-0.0590,-0.0442,-0.1915, 1.3371,-0.1456, 0.0387,-0.5804, 1.5417}, {1.0232,-0.0258, 0.0026,-0.1296, 1.2882,-0.1587,-0.0011,-0.1928, 1.1940}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2662,-0.2664, 0.0002,-0.1050, 1.3168,-0.2118,-0.0058,-0.4370, 1.4428}}}, {0x38, /* RX500/RX510 */ {{1.1150,-0.0677,-0.0473,-0.1179, 1.1681,-0.0502, 0.0052,-0.4858, 1.4806}, {1.0133,-0.0151, 0.0017,-0.1216, 1.2207,-0.0991,-0.0003,-0.1512, 1.1515}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2105,-0.1644,-0.0461,-0.1124, 1.1945,-0.0820,-0.0450,-0.3367, 1.3817}}}, {0x37, /* CX6300/CX6400 */ {{0.9640, 0.1455,-0.1095, 0.0108, 1.1933,-0.2041, 0.0071,-0.3487, 1.3416}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x3F, /* ES-10000G */ {{1.1223,-0.0985,-0.0238,-0.0847, 1.1502,-0.0655, 0.0118,-0.5022, 1.4904}, {1.0077,-0.0129, 0.0052,-0.0904, 1.1785,-0.0881, 0.0000,-0.1528, 1.1528}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1927,-0.1646,-0.0280,-0.0655, 1.1033,-0.0378, 0.0034,-0.4173, 1.4139}}}, {0x41, /* GT-F500/F550 */ {{1.0732,-0.0581,-0.0150,-0.0897, 1.1553,-0.0657,-0.0179,-0.6500, 1.6679}, {1.0163,-0.0203, 0.0040,-0.1125, 1.1797,-0.0672,-0.0091,-0.2343, 1.2434}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2437,-0.2022,-0.0415,-0.0352, 1.0735,-0.0383,-0.0188,-0.5020, 1.5209}}}, {0x43, /* GT-F600 */ {{1.0782,-0.0697,-0.0085,-0.1605, 1.2862,-0.1257, 0.0148,-0.5854, 1.5706}, {1.0136,-0.0151, 0.0016,-0.1836, 1.3422,-0.1586,-0.0014,-0.1851, 1.1865}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1491,-0.1456,-0.0035,-0.0990, 1.2657,-0.1666, 0.0015,-0.3868, 1.3853}}}, {0x46, /* CX3500/CX3600/CX4500/CX4600 */ {{0.9828, 0.0924,-0.0752, 0.0255, 1.1510,-0.1765, 0.0049,-0.3250, 1.3201}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x48, /* PM-A700/RX420/RX430 */ {{0.9716, 0.0927,-0.0643, 0.0010, 1.1068,-0.1078, 0.0101,-0.3046, 1.2945}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x49, /* CX6500/CX6600 */ {{0.9640, 0.1455,-0.1095, 0.0108, 1.1933,-0.2041, 0.0071,-0.3487, 1.3416}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x4B, /* PM-A870 */ {{1.1150,-0.0677,-0.0473,-0.1179, 1.1681,-0.0502, 0.0052,-0.4858, 1.4806}, {1.0133,-0.0151, 0.0017,-0.1216, 1.2207,-0.0991,-0.0003,-0.1512, 1.1515}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2105,-0.1644,-0.0461,-0.1124, 1.1945,-0.0820,-0.0450,-0.3367, 1.3817}}}, {0x4D, /* PM-A900 */ {{1.1011,-0.0824,-0.0186,-0.0970, 1.1991,-0.1021,-0.0161,-0.6247, 1.6408}, {1.0259,-0.0356, 0.0097,-0.1085, 1.2225,-0.1140,-0.0046,-0.1848, 1.1894}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2150,-0.2074,-0.0076,-0.0521, 1.1430,-0.0909,-0.0204,-0.4156, 1.4360}}}, {0x4F, /* GT-X800 */ {{1.1052,-0.0850,-0.0202,-0.1050, 1.2294,-0.1245,-0.0486,-0.4160, 1.4646}, {1.0255,-0.0272, 0.0017,-0.0919, 1.2098,-0.1180,-0.0021,-0.1296, 1.1317}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2950,-0.2619,-0.0332,-0.0562, 1.1587,-0.1025,-0.0397,-0.3100, 1.3497}}}, {0x51, /* LP-A500 */ {{1.0614,-0.0361,-0.0253,-0.1081, 1.1320,-0.0240,-0.0536,-0.2045, 1.2580}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x52, /* GT-F520/F570 */ {{1.0978,-0.0806,-0.0173,-0.0802, 1.1515,-0.0713,-0.0476,-0.4656, 1.5132}, {1.0192,-0.0192, 0.0000,-0.0974, 1.1846,-0.0872,-0.0031,-0.1797, 1.1828}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2490,-0.2030,-0.0460,-0.0469, 1.1046,-0.0577,-0.0361,-0.3857, 1.4217}}}, {0x54, /* GT-X750 */ {{1.0905,-0.0654,-0.0251,-0.1030, 1.1801,-0.0771,-0.0685,-0.4238, 1.4923}, {1.0206,-0.0207, 0.0000,-0.0890, 1.1770,-0.0880,-0.0014,-0.1450, 1.1464}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.3041,-0.2907,-0.0134,-0.0383, 1.0908,-0.0525,-0.0327,-0.2947, 1.3275}}}, {0x56, /* LP-M5500 */ {{1.0784,-0.0560,-0.0224,-0.1793, 1.2234,-0.0441,-0.0041,-0.2636, 1.2677}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x57, /* Stylus CX3700/CX3800/DX3800 */ {{0.9828, 0.0924,-0.0752, 0.0255, 1.1510,-0.1765, 0.0049,-0.3250, 1.3201}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x58, /* PX-A650/Stylus CX4700/CX4800/DX4800 */ {{0.9716, 0.0927,-0.0643, 0.0010, 1.1068,-0.1078, 0.0101,-0.3046, 1.2945}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x59, /* Stylus CX4100/CX4200/DX4200 */ {{0.9716, 0.0927,-0.0643, 0.0010, 1.1068,-0.1078, 0.0101,-0.3046, 1.2945}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x5B, /* Stylus CX7700/CX7800 */ {{0.9764, 0.1095,-0.0859, 0.0149, 1.1154,-0.1303, 0.0051,-0.2851, 1.2800}, {1.0024,-0.0149, 0.0124,-0.2569, 1.3432,-0.0864,-0.0043,-0.1306, 1.1349}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1003,-0.0493,-0.0510,-0.1607, 1.2748,-0.1142,-0.0059,-0.3161, 1.3220}}}, {0x5D, /* Stylus Photo RX520/RX530 */ {{0.9764, 0.1095,-0.0859, 0.0149, 1.1154,-0.1303, 0.0051,-0.2851, 1.2800}, {1.0024,-0.0149, 0.0124,-0.2569, 1.3432,-0.0864,-0.0043,-0.1306, 1.1349}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.1003,-0.0493,-0.0510,-0.1607, 1.2748,-0.1142,-0.0059,-0.3161, 1.3220}}}, {0x5F, /* Stylus Photo RX640/RX650 */ {{1.0697,-0.0561,-0.0137,-0.0824, 1.1291,-0.0467,-0.0390,-0.5218, 1.5608}, {1.0208,-0.0209, 0.0000,-0.0923, 1.2017,-0.1093,-0.0020,-0.1290, 1.1310}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2606,-0.2125,-0.0482,-0.0567, 1.1441,-0.0874,-0.0431,-0.3490, 1.3921}}}, {0x61, /* PM-A950 */ {{1.0921,-0.0722,-0.0199,-0.0831, 1.1550,-0.0718,-0.0452,-0.3721, 1.4173}, {1.0168,-0.0168, 0.0000,-0.0953, 1.1928,-0.0975,-0.0012,-0.1235, 1.1247}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2603,-0.2763, 0.0155,-0.0398, 1.1033,-0.0635,-0.0249,-0.2675, 1.2924}}}, {0x63, /* GT-X900 */ {{1.0976,-0.0789,-0.0187,-0.0958, 1.1821,-0.0863,-0.0565,-0.4179, 1.4744}, {1.0250,-0.0267, 0.0016,-0.0930, 1.2108,-0.1178,-0.0022,-0.1296, 1.1317}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.3111,-0.2979,-0.0132,-0.0441, 1.1148,-0.0707,-0.0348,-0.2971, 1.3319}}}, {0x65, /* ES-H300 */ {{1.0359,-0.0146,-0.0213,-0.0752, 1.0963,-0.0211,-0.0456,-0.3238, 1.3693}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x66, /* GT-S600/F650, Perfection V10/V100 */ {{1.0878,-0.0667,-0.0211,-0.0892, 1.1513,-0.0622,-0.0654,-0.5175, 1.5829}, {1.0208,-0.0209, 0.0000,-0.0923, 1.2017,-0.1093,-0.0020,-0.1290, 1.1310}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2688,-0.2522,-0.0166,-0.0559, 1.1291,-0.0733,-0.0377,-0.3519, 1.3896}}}, {0x68, /* GT-F700, Perfection V350 */ {{1.0950,-0.0646,-0.0305,-0.0792, 1.1398,-0.0606,-0.0123,-0.5175, 1.5298}, {1.0258,-0.0306, 0.0048,-0.0995, 1.2173,-0.1178,-0.0054,-0.1242, 1.1296}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2697,-0.2501,-0.0195,-0.0351, 1.1236,-0.0885,-0.0131,-0.3268, 1.3400}}}, {0x6A, /* Stylus CX2800/CX2900/ME200 */ {{0.9828, 0.0924,-0.0752, 0.0255, 1.1510,-0.1765, 0.0049,-0.3250, 1.3201}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x6B, /* Stylus PX-A620, CX3900/DX4000 */ {{0.9828, 0.0924,-0.0752, 0.0255, 1.1510,-0.1765, 0.0049,-0.3250, 1.3201}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x6C, /* Stylus CX5900/CX6000/DX6000 */ {{0.9716, 0.0927,-0.0643, 0.0010, 1.1068,-0.1078, 0.0101,-0.3046, 1.2945}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x70, /* Stylus Photo RX560/RX580/RX590 */ {{0.9533, 0.0885,-0.0418, 0.0033, 1.0627,-0.0660,-0.0137,-0.1904, 1.2041}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x71, /* PM-A920 */ {{1.0697,-0.0561,-0.0137,-0.0824, 1.1291,-0.0467,-0.0390,-0.5218, 1.5608}, {1.0208,-0.0209, 0.0000,-0.0923, 1.2017,-0.1093,-0.0020,-0.1290, 1.1310}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2606,-0.2125,-0.0482,-0.0567, 1.1441,-0.0874,-0.0431,-0.3490, 1.3921}}}, {0x73, /* PM-A970 */ {{1.0828,-0.0739,-0.0089,-0.0895, 1.1597,-0.0702,-0.0531,-0.4291, 1.4822}, {1.0258,-0.0306, 0.0048,-0.0995, 1.2173,-0.1178,-0.0054,-0.1242, 1.1296}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2579,-0.2384,-0.0195,-0.0569, 1.1454,-0.0884,-0.0411,-0.3072, 1.3483}}}, {0x75, /* PM-T990 */ {{1.0828,-0.0739,-0.0089,-0.0895, 1.1597,-0.0702,-0.0531,-0.4291, 1.4822}, {1.0258,-0.0306, 0.0048,-0.0995, 1.2173,-0.1178,-0.0054,-0.1242, 1.1296}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.2579,-0.2384,-0.0195,-0.0569, 1.1454,-0.0884,-0.0411,-0.3072, 1.3483}}}, {0x77, /* Stylus CX4900/CX5000/DX5000 */ {{0.9716, 0.0927,-0.0643, 0.0010, 1.1068,-0.1078, 0.0101,-0.3046, 1.2945}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x78, /* LP-M5600 */ {{1.0784,-0.0560,-0.0224,-0.1793, 1.2234,-0.0441,-0.0041,-0.2636, 1.2677}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x79, /* AcuLaser CX21 */ {{1.0614,-0.0361,-0.0253,-0.1081, 1.1320,-0.0240,-0.0536,-0.2045, 1.2580}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x7A, /* GT-F670, Perfection V200 */ {{1.1754,-0.1173,-0.0580,-0.0687, 1.1307,-0.0620,-0.0255,-0.4699, 1.4954}, {1.0150,-0.0173, 0.0022,-0.0853, 1.2238,-0.1384,-0.0073,-0.1490, 1.1562}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.4283,-0.4335, 0.0052,-0.0170, 1.1308,-0.1138,-0.0147,-0.2230, 1.2377}}}, {0x7C, /* GT-X770, Perfection V500 */ {{1.2470,-0.2041,-0.0429,-0.1920, 1.2918,-0.0998,-0.0100,-0.2503, 1.2603}, {1.0050,-0.0076, 0.0026,-0.2532, 1.1289, 0.1243,-0.0733,-0.0960, 1.1693}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.4724,-0.4599,-0.0125,-0.0876, 1.1562,-0.0686,-0.0097,-0.2278, 1.2375}}}, {0x7E, /* Stylus CX4300/CX4400/CX5500/CX5600/DX4400 */ {{0.9828, 0.0924,-0.0752, 0.0255, 1.1510,-0.1765, 0.0049,-0.3250, 1.3201}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x7F, /* PX-A640, Stylus CX7300/CX7400/DX7400 */ {{1.0936,-0.0142,-0.0795,-0.0001, 1.0951,-0.0949, 0.0308,-0.2967, 1.2659}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x80, /* PX-A740, Stylus CX8300/CX8400/DX8400 */ {{1.0936,-0.0142,-0.0795,-0.0001, 1.0951,-0.0949, 0.0308,-0.2967, 1.2659}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x81, /* PX-FA700, Stylus CX9300F/CX9400Fax/DX9400F */ {{1.1090,-0.0304,-0.0786, 0.0194, 1.1078,-0.1272,-0.0077,-0.1293, 1.1370}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x82, /* PM-T960 */ {{1.1622,-0.1102,-0.0519,-0.0717, 1.1060,-0.0343,-0.0248,-0.4138, 1.4385}, {0.9913, 0.0082, 0.0005,-0.1259, 1.0452, 0.0807,-0.0072,-0.0767, 1.0839}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.3900,-0.3008,-0.0892,-0.0254, 1.0890,-0.0636,-0.0300,-0.2501, 1.2801}}}, {0x84, /* PM-A940, Stylus Photo RX680/RX685/RX690 */ {{1.0934,-0.0042,-0.0892, 0.0052, 1.1019,-0.1071, 0.0259,-0.2651, 1.2392}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x85, /* PM-A840/A840S, Stylus Photo RX585/RX595/RX610 */ {{1.0534, 0.0399,-0.0934, 0.0098, 1.0589,-0.0687, 0.0016,-0.1131, 1.1115}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x86, /* GT-D1000, GT-1500 */ {{1.1945,-0.1413,-0.0532,-0.1929, 1.2525,-0.0596,-0.0235,-0.2761, 1.2996}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x87, /* GT-X970 */ {{1.1978,-0.1417,-0.0561,-0.0852, 1.1610,-0.0758,-0.0395,-0.3212, 1.3607}, {1.0000, 0.0009,-0.0009,-0.1268, 1.0523, 0.0745,-0.0075,-0.0873, 1.0948}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.4475,-0.3957,-0.0518,-0.0138, 1.0644,-0.0506,-0.0199,-0.2050, 1.2249}}}, {0x97, /* LP-M5000 */ {{1.1115,-0.0377,-0.0738,-0.0658, 1.0624, 0.0034, 0.0042,-0.2883, 1.2841}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x89, /* LP-M6000 */ {{1.1115,-0.0377,-0.0738,-0.0658, 1.0624, 0.0034, 0.0042,-0.2883, 1.2841}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x8A, /* ES-H7200, GT-20000 */ {{1.1221,-0.0396,-0.0825,-0.0718, 1.0822,-0.0104, 0.0112,-0.2995, 1.2883}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x8B, /* GT-F720/S620, Perfection V30/V300 */ {{1.2402,-0.1891,-0.0511,-0.1535, 1.2008,-0.0473,-0.0316,-0.3293, 1.3609}, {1.0027,-0.0048, 0.0021,-0.2067, 1.0878, 0.1189,-0.0408,-0.0767, 1.1175}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.4524,-0.4346,-0.0178,-0.0601, 1.1273,-0.0672,-0.0173,-0.1823, 1.1996}}}, {0x8D, /* Stylus NX200/SX200/TX200 */ {{1.0936,-0.0142,-0.0795,-0.0001, 1.0951,-0.0949, 0.0308,-0.2967, 1.2659}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x8E, /* PX-501A, Stylus NX400/SX400/TX400 */ {{1.0936,-0.0142,-0.0795,-0.0001, 1.0951,-0.0949, 0.0308,-0.2967, 1.2659}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x8F, /* Stylus NX300 / Stylus Office BX300F/TX300F / ME Office 600F */ {{1.1090,-0.0304,-0.0786, 0.0194, 1.1078,-0.1272,-0.0077,-0.1293, 1.1370}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x90, /* PX-601F, Stylus SX600FW/TX600FW / Stylus Office BX600FW / WorkForce 600 */ {{1.0316, 0.0864,-0.1180, 0.0268, 1.1111,-0.1379, 0.0213,-0.2235, 1.2022}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x91, /* EP-901A/901F, Artisan 800 / Stylus Photo PX800FW/FX800FW */ {{1.0777, 0.0152,-0.0929, 0.0244, 1.1221,-0.1465, 0.0103,-0.1544, 1.1441}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x92, /* EP-801A, Artisan 700 / Stylus Photo PX700W/TX700W */ {{1.0777, 0.0152,-0.0929, 0.0244, 1.1221,-0.1465, 0.0103,-0.1544, 1.1441}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x93, /* PX-401A, Stylus NX100/SX100/TX100 / ME 300 */ {{1.0934,-0.0042,-0.0892, 0.0052, 1.1019,-0.1071, 0.0259,-0.2651, 1.2392}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x96, /* WorkForce 500 */ {{1.1090,-0.0304,-0.0786, 0.0194, 1.1078,-0.1272,-0.0077,-0.1293, 1.1370}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x98, {{1.0936,-0.0142,-0.0795,-0.0001, 1.0951,-0.0949, 0.0308,-0.2967, 1.2659}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x99, {{1.1090,-0.0304,-0.0786, 0.0194, 1.1078,-0.1272,-0.0077,-0.1293, 1.1370}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x9A, {{1.0779, 0.0132,-0.0911, 0.0214, 1.1003,-0.1217, 0.0109,-0.1487, 1.1378}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x9B, {{1.0779, 0.0132,-0.0911, 0.0214, 1.1003,-0.1217, 0.0109,-0.1487, 1.1378}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x9C, {{1.0316, 0.0864,-0.1180, 0.0268, 1.1111,-0.1379, 0.0213,-0.2235, 1.2022}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x9D, {{1.0316, 0.0864,-0.1180, 0.0268, 1.1111,-0.1379, 0.0213,-0.2235, 1.2022}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x9E, {{1.0534, 0.0399,-0.0934, 0.0098, 1.0589,-0.0687, 0.0016,-0.1131, 1.1115}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0x9F, {{1.0777, 0.0152,-0.0929, 0.0244, 1.1221,-0.1465, 0.0103,-0.1544, 1.1441}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0xA0, {{1.0777, 0.0152,-0.0929, 0.0244, 1.1221,-0.1465, 0.0103,-0.1544, 1.1441}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}}}, {0xA1, {{1.2578,-0.2140,-0.0438,-0.1939, 1.2856,-0.0917,-0.0258,-0.2642, 1.2900}, {0.9989,-0.0018, 0.0029,-0.2608, 1.1305, 0.1303,-0.0802,-0.0807, 1.1609}, {1.0000, 0.0000, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, 0.0000, 1.0000}, {1.4431,-0.4193,-0.0238,-0.0915, 1.1507,-0.0592,-0.0226,-0.1978, 1.2204}}}, {0xFF, /* terminator */ {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0}}} }; /* cat hw-data.c | grep '{"' | cut -d ',' -f1,2 | awk '{ print $0 " },"}' */ const struct epson_profile_map epson_cct_models[] = { {"GT-10000", 0x05 }, {"ES-6000", 0x05 }, {"Perfection610", 0x06 }, {"GT-6600", 0x06 }, {"Perfection1200", 0x07 }, {"GT-7600", 0x07 }, {"Expression1600", 0x0D }, {"ES-2000", 0x0D }, {"Expression1640XL", 0x0F }, {"ES-8500", 0x0F }, {"Perfection640", 0x15 }, {"GT-6700", 0x15 }, {"Perfection1640", 0x16 }, {"GT-8700", 0x16 }, {"Perfection1240", 0x18 }, {"GT-7700", 0x18 }, {"GT-30000", 0x1A }, {"ES-9000H", 0x1A }, {"Expression1680", 0x1B }, {"ES-2200", 0x1B }, {"GT-7200", 0x1D }, {"GT-8200", 0x1F }, {"GT-9700", 0x21 }, {"GT-7300", 0x23 }, {"GT-8300", 0x25 }, {"GT-9300", 0x27 }, {"GT-9800", 0x29 }, {"ES-7000H", 0x2B }, {"LP-A500", 0x51 }, {"AL-CX11", 0x51 }, {"GT-9400", 0x32 }, {"CC-600PX", 0x2D }, {"PM-A850", 0x3A }, {"CX5400", 0x36 }, {"GT-X700", 0x34 }, {"RX500", 0x38 }, {"PX-A650", 0x37 }, {"ES-10000G", 0x3F }, {"Expression10000", 0x3F }, {"CX4600", 0x46 }, {"CX6600", 0x49 }, {"CX3600", 0x46 }, {"RX420", 0x48 }, {"PM-A700", 0x48 }, {"PM-A870", 0x4B }, {"GT-F500", 0x41 }, {"GT-F600", 0x43 }, {"PM-A900", 0x4D }, {"GT-X800", 0x4F }, {"GT-X750", 0x54 }, {"LP-M5500", 0x56 }, {"LP-M5600", 0x78 }, {"GT-F520", 0x52 }, {"CX3800", 0x57 }, {"CX7800", 0x5B }, {"PM-A750", 0x5D }, {"CX4800", 0x58 }, {"CX4200", 0x59 }, {"PM-A950", 0x61 }, {"PM-A890", 0x5F }, {"GT-X900", 0x63 }, {"CX4000", 0x6B }, {"CX3000v", 0x6A }, {"ES-H300", 0x65 }, {"CX6000", 0x6C }, {"PM-A820", 0x70 }, {"PM-A920", 0x71 }, {"PM-A970", 0x73 }, {"PM-T990", 0x75 }, {"CX5000", 0x77 }, {"GT-S600", 0x66 }, {"GT-F700", 0x68 }, {"AL-CX21", 0x79 }, {"GT-F670", 0x7A }, {"GT-X770", 0x7C }, {"CX4400", 0x7E }, {"CX7400", 0x7F }, {"CX8400", 0x80 }, {"CX9400Fax", 0x81 }, {"PM-T960", 0x82 }, {"PM-A940", 0x84 }, {"PM-A840", 0x85 }, {"GT-D1000", 0x86 }, {"GT-X970", 0x87 }, {"LP-M5000", 0x97 }, {"LP-M6000", 0x89 }, {"ES-H7200", 0x8A }, {"GT-20000", 0x8A }, {"NX200", 0x8D }, {"NX400", 0x8E }, {"NX100", 0x93 }, {"NX300", 0x8F }, {"WorkForce 600", 0x90 }, {"Artisan 800", 0x91 }, {"Artisan 700", 0x92 }, {"WorkForce 500", 0x96 }, {"GT-F720", 0x8B }, {"GT-S620", 0x8B }, {"GT-S50", 0x00 }, {"GT-S80", 0x00 }, {"PID 0851", 0x98 }, {"PID 084D", 0x99 }, {"PID 084F", 0x9A }, {"PID 0854", 0x9B }, {"PID 0856", 0x9C }, {"PID 0855", 0x9D }, {"PID 0850", 0x9E }, {"PID 0852", 0xA0 }, {"PID 0853", 0x9F }, {"GT-X820", 0xA1 }, {NULL, 0x00 } /* terminator */ }; sane-backends-1.0.27/backend/coolscan3.conf.in0000664000175000017500000000136212112021330015734 00000000000000# coolscan3.conf: sample configuration file for coolscan3 backend # # The following entrie checks for your scanner by manufacturer (SCSI) # and by vendor and product ID (USB). This is what the backend does when # no configuration file can be found. # auto # You can also configure the backend for specific device files, but this # should not normally be necessary (under Linux at least). # Syntax for specific devices: : # # For a SCSI scanner, uncomment and edit the following line: #scsi:/dev/scanner # # For a USB scanner, uncomment and edit the following line: #usb:/dev/usbscanner # # For an IEEE 1394 scanner, use the SBP2 protocol (under Linux, use the # sbp2 kernel module), and your scanner will be handled as a SCSI device. sane-backends-1.0.27/backend/epsonds-cmd.h0000664000175000017500000000164712775312261015214 00000000000000/* * epsonds-cmd.h - Epson ESC/I-2 routines. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #ifndef epsonds_cmd_h #define epsonds_cmd_h SANE_Status esci2_info(epsonds_scanner *s); SANE_Status esci2_fin(epsonds_scanner *s); SANE_Status esci2_can(epsonds_scanner *s); SANE_Status esci2_capa(epsonds_scanner *s); SANE_Status esci2_resa(epsonds_scanner *s); SANE_Status esci2_stat(epsonds_scanner *s); SANE_Status esci2_para(epsonds_scanner *s, char *parameters); SANE_Status esci2_mech(epsonds_scanner *s, char *parameters); SANE_Status esci2_trdt(epsonds_scanner *s); SANE_Status esci2_img(struct epsonds_scanner *s, SANE_Int *length) ; #endif sane-backends-1.0.27/backend/kodakaio.h0000664000175000017500000001143612775312261014557 00000000000000/* * kodakaio.c - SANE library for Kodak ESP Aio scanners. * * Copyright (C) 2011-2013 Paul Newall * * Based on the Magicolor sane backend: * Based on the epson2 sane backend: * Based on Kazuhiro Sasayama previous * work on epson.[ch] file from the SANE package. * Please see those files for additional copyrights. * Author: Paul Newall * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. 29/12/12 added KodakAio_Scanner.ack 2/1/13 added KodakAio_Scanner.background[] */ #ifndef kodakaio_h #define kodakaio_h #undef BACKEND_NAME #define BACKEND_NAME kodakaio #define DEBUG_NOT_STATIC #include #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" /* Silence the compiler for unused arguments */ #define NOT_USED(x) ( (void)(x) ) #define KODAKAIO_CONFIG_FILE "kodakaio.conf" #define NUM_OF_HEX_ELEMENTS (16) /* number of hex numbers per line for data dump */ #define DEVICE_NAME_LEN (16) /* length of device name in extended status */ #define CAP_DEFAULT 0 /* Structure holding the device capabilities */ struct KodakaioCap { SANE_Word id; /* USB pid */ const char *cmds; /* may be used for different command sets in future */ const char *model; SANE_Int out_ep, in_ep; /* USB bulk out/in endpoints */ SANE_Int optical_res; /* optical resolution */ SANE_Range dpi_range; /* max/min resolutions */ SANE_Int *res_list; /* list of resolutions */ SANE_Int res_list_size; /* number of entries in this list */ SANE_Int maxDepth; /* max. color depth */ SANE_Word *depth_list; /* list of color depths */ /* SANE_Range brightness; brightness range */ SANE_Range fbf_x_range; /* flattbed x range */ SANE_Range fbf_y_range; /* flattbed y range */ SANE_Bool ADF; /* ADF is installed */ SANE_Bool adf_duplex; /* does the ADF handle duplex scanning */ SANE_Range adf_x_range; /* autom. document feeder x range */ SANE_Range adf_y_range; /* autom. document feeder y range */ }; /* Options:OPT_BRIGHTNESS, used to be after BIT_DEPTH */ enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_THRESHOLD, OPT_BIT_DEPTH, OPT_RESOLUTION, OPT_TRIALOPT, /* for debuggging */ OPT_PREVIEW, OPT_SOURCE, OPT_ADF_MODE, OPT_PADDING, /* Selects padding of adf pages to the specified length */ OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, NUM_OPTIONS }; typedef enum { /* hardware connection to the scanner */ SANE_KODAKAIO_NODEV, /* default, no HW specified yet */ SANE_KODAKAIO_USB, /* USB interface */ SANE_KODAKAIO_NET /* network interface */ } Kodakaio_Connection_Type; /* Structure holding the hardware description */ struct Kodak_Device { struct Kodak_Device *next; int missing; char *name; char *model; SANE_Device sane; SANE_Range *x_range; /* x range w/out extension */ SANE_Range *y_range; /* y range w/out extension */ Kodakaio_Connection_Type connection; struct KodakaioCap *cap; }; typedef struct Kodak_Device Kodak_Device; /* Structure holding an instance of a scanner (i.e. scanner has been opened) */ struct KodakAio_Scanner { struct KodakAio_Scanner *next; struct Kodak_Device *hw; int fd; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; SANE_Bool ack; /* scanner has finished a page (happens early with adf and padding) */ SANE_Bool eof; /* backend has finished a page (after padding with adf) */ SANE_Byte *buf, *end, *ptr; SANE_Bool canceling; SANE_Bool scanning; /* scan in progress */ SANE_Bool adf_loaded; /* paper in adf */ SANE_Int background[3]; /* stores background RGB components for padding */ SANE_Int left, top; /* in optres units? */ SANE_Int width, height; /* in optres units? */ /* SANE_Int threshold; 0..255 for lineart*/ /* image block data */ SANE_Int data_len; SANE_Int block_len; SANE_Int last_len; /* to be phased out */ SANE_Int blocks; /* to be phased out */ SANE_Int counter; SANE_Int bytes_unread; /* to track when to stop */ /* Used to store how many bytes of the current pixel line we have already * read in previous read attempts. Since each line will be padded * to multiples of 512 bytes, this is needed to know which bytes * to ignore. NOT NEEDED FOR KODAKAIO */ SANE_Int bytes_read_in_line; SANE_Byte *line_buffer; /* How many bytes are scanned per line */ SANE_Int scan_bytes_per_line; }; typedef struct KodakAio_Scanner KodakAio_Scanner; struct mode_param { int flags; int colors; int depth; }; enum { MODE_COLOR, MODE_GRAY, MODE_LINEART }; #endif sane-backends-1.0.27/backend/dell1600n_net.conf.in0000664000175000017500000000075412112021330016327 00000000000000# An example config file for dell1600n_net backend. # # Jon Chambers , 2006-08-12 # # For scanner(s) not detected by the default UDP broadcast method (eg: perhaps it # is not on your local network) then you can add one or more "named_scanner" entries # explicitly giving the hostname/IP address. Uncomment one of the following and # modify the hostname appropriately: # #named_scanner: printer #named_scanner: 192.168.0.20 #named_scanner: myscanner.somewhere.else.org sane-backends-1.0.27/backend/lexmark.conf.in0000664000175000017500000000016712112021330015515 00000000000000# X11xx series usb 0x043d 0x007c # X12xx series usb 0x043d 0x007d # Dell A920 usb 0x413c 0x5105 # X74 usb 0x43d 0x0060 sane-backends-1.0.27/backend/plustek-usb.h0000664000175000017500000006073412775277260015271 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usb.h * @brief Main defines for the USB devices. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2013 Gerhard Jaeger * * History: * - 0.40 - starting version of the USB support * - 0.41 - added workaround flag to struct DevCaps * - 0.42 - added MODEL_NOPLUSTEK * - replaced fLM9831 by chip (valid entries: _LM9831, _LM9832, _LM9833) * - added _WAF_MISC_IO3_LAMP for UMAX 3400 * - 0.43 - added _WAF_MISC_IOx_LAMP (x=1,2,4,5) * - added CLKDef * - 0.44 - added vendor and product ID to struct DeviceDef * - added _WAF_BYPASS_CALIBRATION * - added _WAF_INV_NEGATIVE_MAP * - 0.45 - added _WAF_SKIP_FINE for skipping fine calibration * - added _WAF_SKIP_WHITEFINE for skipping fine white calibration * - added MCLK setting for 16 bit modes * - added _WAF_FIX_GAIN and _WAF_FIX_OFS * - 0.46 - added UMAX1200 for 5400 model * - removed _WAF_FIX_GAIN and _WAF_FIX_OFS * - added skipCoarseCalib to ScanDef * - added additional defines for cis and epson-ccd sensor * - 0.47 - cleanup work * - added gamma to struct HWDefault * - 0.48 - added DEVCAPSFLAG_LargeTPA * - added _WAF_BIN_FROM_COLOR and _WAF_GRAY_FROM_COLOR * - added dHighSpeed to struct HwDefault * - 0.49 - added a_bRegs, fModFirstHome and fLastScanIsAdf * to struct DeviceDef * - added CRYSTAL_FREQ * - added IPCDef * - 0.50 - cleanup * - removed obsolete _WAF_BLACKFINE * - added MODEL_CANON_LIDE25 * - 0.51 - added _WAF_MISC_IO_BUTTONS plus _BUTTON stuff * - added _WAF_USE_ALT_DESC * - added DEVCAPSFLAG_SheetFed * - added dpi_thresh and lineend to motor structure * - 0.52 - added MODEL_QSCAN * - added MODEL_QSCAN_A6 (thanks to Hiroshi Miura) * - changed DCapsDef, lamp -> misc_io * - bPCB is now ushort to be "missused" by non Plustek * devices (as threshhold for resetting sensor order) * - added _WAF_LOFF_ON_START and _WAF_ONLY_8BIT * - added MODEL_TSCAN_A4 * - added attribute packed for data access structs * - added _WAF_INC_DARKTGT * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __PLUSTEK_USB_H__ #define __PLUSTEK_USB_H__ /** CCD ID (PCB ID): total 3 bits (on Plustek devices) */ #define kNEC3799 0 #define kSONY518 1 #define kSONY548 2 #define kNEC8861 3 #define kNEC3778 4 #define kNECSLIM 5 #define kCIS650 6 #define kCIS670 7 #define kCIS1220 8 #define kCIS1240 9 #define kEPSON 10 /** 48MHz Quartz */ #define CRYSTAL_FREQ 48000000UL /*********************************** plustek_types.h!!! ************************/ /* makes trouble with gcc3 #define _SWAP(x,y) (x)^=(y)^=(x)^=(y) */ #define _SWAP(x,y) { (x)^=(y); (x)^=((y)^=(x));} #define _LOWORD(x) ((u_short)(x & 0xffff)) #define _HIWORD(x) ((u_short)(x >> 16)) #define _LOBYTE(x) ((u_char)((x) & 0xFF)) #define _HIBYTE(x) ((u_char)((x) >> 8)) #define _HILO2WORD(x) ((u_short)x.bHi * 256U + x.bLo) #define _LOHI2WORD(x) ((u_short)x.bLo * 256U + x.bHi) #define _PHILO2WORD(x) ((u_short)x->bHi * 256U + x->bLo) #define _PLOHI2WORD(x) ((u_short)x->bLo * 256U + x->bHi) #define PACKED8 __attribute__ ((packed,aligned(1))) #define PACKED16 __attribute__ ((packed,aligned(2))) /* useful for RGB-values */ typedef struct { u_char Red; u_char Green; u_char Blue; } PACKED8 RGBByteDef; typedef struct { u_short Red; u_short Green; u_short Blue; } PACKED16 RGBUShortDef; typedef struct { u_long Red; u_long Green; u_long Blue; } RGBULongDef; typedef struct { u_char a_bColor[3]; } PACKED8 ColorByteDef; typedef struct { u_char bHi; u_char bLo; } PACKED8 HiLoDef; typedef union { HiLoDef HiLo[3]; u_short Colors[3]; } PACKED16 ColorWordDef; typedef union { HiLoDef HiLo; u_short Mono; } PACKED16 MonoWordDef; typedef union { u_char *pb; u_short *pw; MonoWordDef *pmw; ColorByteDef *pcb; ColorWordDef *pcw; RGBByteDef *pb_rgb; RGBUShortDef *pw_rgb; HiLoDef *philo; } __attribute__ ((aligned(4))) AnyPtr; typedef struct { unsigned short x; unsigned short y; } XY; #define _VAR_NOT_USED(x) ((x)=(x)) /*****************************************************************************/ #define IDEAL_GainNormal 0xf000UL /* 240 */ #define IDEAL_GainPositive 0xfe00UL /* 254 */ #define IDEAL_Offset 0x1000UL /* 20 */ #define GAIN_Target 65535UL /** Chip-types */ typedef enum _CHIPSET { _LM9831, _LM9832, _LM9833 } eChipDef; /** ScanParam.bCalibration */ enum _SHADINGID { PARAM_Scan, PARAM_Gain, PARAM_DarkShading, PARAM_WhiteShading, PARAM_Offset }; /** ScanParam.bDataType */ enum _SCANDATATYPE { SCANDATATYPE_BW, SCANDATATYPE_Gray, SCANDATATYPE_Color }; /** DCapsDef.bSensorColor */ enum _SENSORCOLOR { SENSORORDER_rgb, SENSORORDER_rbg, SENSORORDER_gbr, SENSORORDER_grb, SENSORORDER_brg, SENSORORDER_bgr }; /** DCapsDef.wFlags */ enum _DEVCAPSFLAG { DEVCAPSFLAG_Normal = 0x0001, DEVCAPSFLAG_Positive = 0x0002, DEVCAPSFLAG_Negative = 0x0004, DEVCAPSFLAG_TPA = 0x0006, DEVCAPSFLAG_Adf = 0x0008, DEVCAPSFLAG_LargeTPA = 0x0010, DEVCAPSFLAG_SheetFed = 0x0020 }; /** to allow some workarounds */ enum _WORKAROUNDS { _WAF_NONE = 0x00000000, /* no fix anywhere needed */ _WAF_BSHIFT7_BUG = 0x00000001, /* to fix U12 bug in 14bit mode */ _WAF_MISC_IO_LAMPS = 0x00000002, /* special lamp switching */ _WAF_BLACKFINE = 0x00000004, /* use black calibration strip */ _WAF_BYPASS_CALIBRATION = 0x00000008, /* no calibration,use linear gamma */ _WAF_INV_NEGATIVE_MAP = 0x00000010, /* the backend does the neg. stuff */ _WAF_SKIP_FINE = 0x00000020, /* skip the fine calbration */ _WAF_SKIP_WHITEFINE = 0x00000040, /* skip the fine white calbration */ _WAF_BIN_FROM_COLOR = 0x00000080, /* generate binary & gray images */ _WAF_GRAY_FROM_COLOR = 0x00000100, /* from color scans */ _WAF_MISC_IO_BUTTONS = 0x00000200, /* special handling for buttons */ _WAF_USE_ALT_DESC = 0x00000400, /* use alternate manufacturer */ _WAF_RESET_SO_TO_RGB = 0x00000800, /* set sensororder to RGB(CIS only)*/ _WAF_LOFF_ON_START = 0x00001000, /* switch lamp off before scanning */ _WAF_ONLY_8BIT = 0x00002000, /* scanner allows only 8 bit modes */ _WAF_INC_DARKTGT = 0x00004000 /* allow tgt darklevel adjustment */ }; /** for lamps connected to the misc I/O pins*/ enum _LAMPS { _NO_MIO = 0, _MIO1 = 0x0001, _MIO2 = 0x0002, _MIO3 = 0x0004, _MIO4 = 0x0008, _MIO5 = 0x0010, _MIO6 = 0x0020 }; #define _PSENSE_SHIFT 24 #define _PSENSE_MASK 0xFF000000 #define _BUTTON_SHIFT 16 #define _BUTTON_MASK 0xFF0000 #define _TPA_SHIFT 8 #define _TPA_MASK 0xFF00 enum _BUTTONS { _NO_BUTTON = 0, _PORT0 = ((_MIO1 | _MIO2) << _BUTTON_SHIFT), _PORT1 = ((_MIO3 | _MIO4) << _BUTTON_SHIFT), _PORT2 = ((_MIO5 | _MIO6) << _BUTTON_SHIFT) }; enum _PAPER_SENSE { _PS_INP1 = (0x01 << _PSENSE_SHIFT), _PS_INP2 = (0x02 << _PSENSE_SHIFT), _PS_INP_MIO1 = (_MIO1 << (_PSENSE_SHIFT+2)), _PS_INP_MIO2 = (_MIO2 << (_PSENSE_SHIFT+2)), _PS_INP_MIO3 = (_MIO3 << (_PSENSE_SHIFT+2)), _PS_INP_MIO4 = (_MIO4 << (_PSENSE_SHIFT+2)), _PS_INP_MIO5 = (_MIO5 << (_PSENSE_SHIFT+2)), _PS_INP_MIO6 = (_MIO6 << (_PSENSE_SHIFT+2)) }; /** for encoding a misc I/O register as TPA */ #define _TPA(register) ((u_long)(register << _TPA_SHIFT)) /** Mask to check for available TPA */ #define _HAS_TPA(flag) (flag & _TPA_MASK) /** Get the TPA misc I/O register */ #define _GET_TPALAMP(flag) ((flag >> _TPA_SHIFT) & 0xFF) /** Get the Papersense port*/ #define _GET_PAPERSENSE_PORT(flag) ((flag >> _PSENSE_SHIFT) & 0xFF) /** motor types */ typedef enum { MODEL_KaoHsiung = 0, MODEL_HuaLien, MODEL_Tokyo600, MODEL_EPSON, /**< for EPSON1250/1260 */ MODEL_MUSTEK600, /**< for BearPaw 1200 */ MODEL_MUSTEK1200, /**< for BearPaw 2400 */ MODEL_HP, /**< for HP2x00 */ MODEL_CANON600 , /**< for CanoScan 600dpi models */ MODEL_CANON1200, /**< for Canon 1200dpi models */ MODEL_CANONCCD1200, /**< for Canon CCD 1200dpi models */ MODEL_CANON_LIDE25, /**< for CanoScan LiDE25 */ MODEL_UMAX, /**< for UMAX 3400/3450 */ MODEL_UMAX1200, /**< for UMAX 5400 */ MODEL_TSCAN, /**< for Syscan TravelScan A6 */ MODEL_TSCAN_A4, /**< for Syscan TravelScan A4 */ MODEL_QSCAN, /**< for PandP Q-Scan A4 */ MODEL_QSCAN_A6, /**< for PandP Q-Scan A6 */ MODEL_LAST } eModelDef; /** to distinguish between Plustek and other devices */ #define _IS_PLUSTEKMOTOR(x) (x<=MODEL_Tokyo600) /** Generic usage */ enum _CHANNEL { CHANNEL_red, CHANNEL_green, CHANNEL_blue, CHANNEL_rgb }; /** motor movement */ enum MODULEMOVE { MOVE_Forward, MOVE_Backward, MOVE_Both, MOVE_ToPaperSensor, MOVE_EjectAllPapers, MOVE_SkipPaperSensor, MOVE_ToShading }; /** SCANDEF.dwFlags */ enum SCANFLAG { SCANDEF_Transparency = 0x00000100, /* Scanning from transparency*/ SCANDEF_Negative = 0x00000200, /* Scanning from negative */ SCANDEF_QualityScan = 0x00000400, /* Scanning in quality mode */ SCANDEF_ContinuousScan = 0x00001000, SCANDEF_Adf = 0x00002000, /* Scan from ADF tray */ SCANFLAG_bgr = 0x00004000, SCANFLAG_BottomUp = 0x00008000, SCANFLAG_DWORDBoundary = 0x00020000, SCANFLAG_RightAlign = 0x00040000, SCANFLAG_StillModule = 0x00080000, SCANFLAG_Pseudo48 = 0x08000000, SCANFLAG_SampleY = 0x04000000, SCANFLAG_Calibration = 0x10000000, SCANFLAG_Scanning = 0x20020000, SCANFLAG_StartScan = 0x40000000 }; typedef struct Origins { long lLeft; /* How many pix to move the scanning org left, in optic res */ long lUp; /* How many pix to move the scanning or up, in optic res */ } OrgDef; typedef struct SrcAttr { XY DataOrigin; /**< The origin x is from visible pixel not CCD */ /* pixel 0, in 300 DPI base. */ /* The origin y is from visible top */ /* (glass area), in 300 DPI */ short ShadingOriginY; /**< The origin y is from top of scanner body */ short DarkShadOrgY; /**< if the device has a dark calibration strip */ XY Size; /**< Scanning width/height, in 300 DPI base. */ XY MinDpi; /**< Minimum dpi supported for scanning */ } SrcAttrDef; typedef struct DevCaps { SrcAttrDef Normal; /**< Reflection */ SrcAttrDef Positive; /**< Positive film */ SrcAttrDef Negative; /**< Negative film */ SrcAttrDef Adf; /**< Adf device */ XY OpticDpi; /**< Maximum DPI */ u_short wFlags; /**< Flag to indicate what kinds of elements */ /* are available */ u_char bSensorOrder; /**< CCD color sequences, see _SENSORORDER */ u_char bSensorDistance; /**< CCD Color distance */ u_char bButtons; /**< Number of buttons */ u_char bCCD; /**< CCD ID */ u_short bPCB; /**< PCB ID/or threshold (only CIS) */ u_long workaroundFlag; /**< Flag to allow special work arounds, see */ /* _WORKAROUNDS */ u_long misc_io; /**< for lamp, papersense and buttons */ } DCapsDef; /** * for keeping intial illumination settings */ typedef struct { u_char mode; u_short red_lamp_on; u_short red_lamp_off; u_short green_lamp_on; u_short green_lamp_off; u_short blue_lamp_on; u_short blue_lamp_off; } IllumiDef; /** basic register settings */ typedef struct HWDefault { double dMaxMotorSpeed; /* Inches/second, max. scan speed */ double dMaxMoveSpeed; /* Inches/second, max. move speed */ double dHighSpeed; /* for speeding up the sensor */ double dIntegrationTimeLowLamp; double dIntegrationTimeHighLamp; u_short wMotorDpi; /* Full step DPI */ u_short wDRAMSize; /* in KB */ double dMinIntegrationTimeLowres; /*in ms. */ double dMinIntegrationTimeHighres; /* in ms. */ u_short wGreenPWMDutyCycleLow; u_short wGreenPWMDutyCycleHigh; /* Registers */ u_char bSensorConfiguration; /* 0x0b */ /* Sensor control settings */ u_char bReg_0x0c; u_char bReg_0x0d; u_char bReg_0x0e; u_char bReg_0x0f_Mono [10]; /* 0x0f to 0x18 */ u_char bReg_0x0f_Color [10]; /* 0x0f to 0x18 */ /* color mode settings */ u_char bReg_0x26; u_char bReg_0x27; /* illumination mode reg 0x29 (runtime) */ u_char bReg_0x29; /* initial illumination settings */ IllumiDef illu_mono; IllumiDef illu_color; /* 0x1a & 0x1b, remember the u_char order is not Intel * format, you have to pay your attention when you * write this value to register. */ u_short StepperPhaseCorrection; /* Sensor Pixel Configuration * Actually, the wActivePixelsStart will be set to 0 for shading purpose. * We have to keep these values to adjust the origins when user does the * scan. These settings are based on optic resolution. */ u_char bOpticBlackStart; /* 0x1c */ u_char bOpticBlackEnd; /* 0x1d */ u_short wActivePixelsStart; /* 0x1e & 0x1f */ u_short wLineEnd; /* 0x20 & 0x21 */ /* illumination settings (runtime) */ u_short red_lamp_on; /* 0x2c & 0x2d */ u_short red_lamp_off; /* 0x2e & 0x2f */ u_short green_lamp_on; /* 0x30 & 0x31 */ u_short green_lamp_off; /* 0x32 & 0x33 */ u_short blue_lamp_on; /* 0x34 & 0x35 */ u_short blue_lamp_off; /* 0x36 & 0x37 */ /* Misc */ u_char bReg_0x45; u_short wStepsAfterPaperSensor2;/* 0x4c & 0x4d */ u_char bStepsToReverse; /* 0x50 */ u_char bReg_0x51; u_char bReg_0x54; u_char bReg_0x55; u_char bReg_0x56; u_char bReg_0x57; u_char bReg_0x58; u_char bReg_0x59; u_char bReg_0x5a; u_char bReg_0x5b; u_char bReg_0x5c; u_char bReg_0x5d; u_char bReg_0x5e; eChipDef chip; /* chiptype */ eModelDef motorModel; /* to identify used motor */ double gamma; /* default gamma setting */ } HWDef; /** device description during runtime */ typedef struct DeviceDef { char* ModelStr; /**< pointer to our model string */ int vendor; /**< vendor ID */ int product; /**< product ID */ DCapsDef Caps; /**< pointer to the attribute of current dev */ HWDef HwSetting; /**< Pointer to the characteristics of device */ SrcAttrDef *pSource; /**< Scanning src, it's equal to Caps.Normal */ /**< on the source that the user specified. */ OrgDef Normal; /**< Reflection - Pix to adjust scanning orgs */ OrgDef Positive; /**< Pos film - Pix to adjust scanning orgs */ OrgDef Negative; /**< Neg film - Pix to adjust scanning orgs */ OrgDef Adf; /**< Adf - Pixels to adjust scanning origins */ u_long dwTicksLampOn; /**< The ticks when lamp turns on */ u_long dwLampOnPeriod;/**< How many seconds to keep lamp on */ SANE_Bool bLampOffOnEnd; /**< switch lamp off on end or keep cur. state*/ int currentLamp; /**< The lamp ID of the currently used lamp */ SANE_Bool fModFirstHome; /**< */ SANE_Bool fLastScanIsAdf;/**< */ u_char a_bRegs[0x80]; /**< our global register file */ } DeviceDef; typedef struct Settings { char *pIDString; DCapsDef *pDevCaps; HWDef *pHwDef; char *pModelString; } SetDef; /** */ typedef struct { /** User Information */ u_long dwBytes; /**< bytes per line */ u_long dwPixels; /**< pixels per line */ u_long dwLines; /**< lines */ /** Driver Info */ u_long dwValidPixels; /**< only valid pixels, not incl. pad pix(B/W,Gray)*/ u_long dwPhyPixels; /**< inlcude pad pixels for ASIC (B/W, Gray) */ u_long dwPhyBytes; /**< bytes to read from ASIC */ u_long dwPhyLines; /**< should include the extra lines accord to the */ /* request dpi (CCD lines distance) */ u_long dwTotalBytes; /**< Total bytes per scan */ } WinInfo; /** */ typedef struct { /* OUTPUT - Driver returned area. All are based on physical * scanning conditions. */ WinInfo Size; /* i/p: * dwPixels, dwBytes(without u_long boundary factor) * dwLines in user specified dpi * o/p: * dwPhyPixels, dwPhyBytes, dwPhyLines * so after called, caller have to change it */ XY PhyDpi; /* Driver DPI */ /* INPUT - User info. All sizes and coordinates are specified in the * unit based on 300 DPI */ XY UserDpi; /**< User specified DPI */ XY Origin; /**< Scanning origin in optic dpi */ double dMCLK; /**< for positive & negative & Adf */ short brightness; short contrast; u_char bSource; /**< Reflection/Positive/Negative/Adf(SOURCE_xxx)*/ u_char bDataType; /**< Bw, Gray or Color (see _SCANDATATYPE) */ u_char bBitDepth; /**< 1/8/14 */ u_char bChannels; /**< Color or Gray */ u_char bCalibration; /**< 1 or 2: the origin.x is from CCD pixel 0 and * the origin.y is from Top of scanner. * In this case, the WININFO.dwPhyLines * will not included the extra lines for * color distance factor. * 0: normal scan, the both directions have to * add the distance */ int swOffset[3]; /**< for calibration adjustment */ int swGain[3]; /**< for calibration adjustment */ } ScanParam; struct Plustek_Device; /** structure to hold all necessary buffer informations for current scan */ typedef struct ScanDef { SANE_Bool fCalibrated; /**< calibrated or not */ SANE_Bool skipCoarseCalib;/**< skip coarse calibration or not */ u_long dwFlag; /**< scan attributes */ ScanParam sParam; /**< all we need to scan */ AnyPtr UserBuf; /**< pointer to the user buffer */ u_long dwLinesUser; /**< Number of lines of user buffer */ u_long dwBytesLine; /**< Bytes per line of user buffer. */ u_long dwLinesToProcess; /** Image processing routine according to the scan mode */ void (*pfnProcess)(struct Plustek_Device*); u_long* pScanBuffer; /**< our scan buffer */ u_long dwLinesPerScanBufs; u_long dwNumberOfScanBufs; u_long dwLinesScanBuf; u_char* pbScanBufBegin; u_char* pbScanBufEnd; u_char* pbGetDataBuf; u_long dwBytesScanBuf; u_long dwLinesDiscard; u_long dwRedShift; u_long dwGreenShift; u_long dwBlueShift; AnyPtr Green; AnyPtr Red; AnyPtr Blue; long lBufAdjust; /**< bytes to adjust buffer pointer */ /* after a image line processed */ u_short wSumY; /**< for line sampling */ u_char bLineDistance; /**< Color offset in specific dpi y */ int fGrayFromColor; /**< channel to use for gray mode */ u_char bLinesToSkip; /**< how many lines to skip at start */ } ScanDef; /** max number of different colck settings */ #define _MAX_CLK 10 /** structure to hold PWN settings */ typedef struct { u_char pwm; /**< PWM */ u_char pwm_duty; /**< PWM duty cycles */ u_char scan_lines_per_line; /**< lines to scan to obtain 1 real line will be used in 16bit color modes only */ } MDef; /** according to the CCD and motor, we provide various settings */ typedef struct { eModelDef motorModel; /**< the motor ID */ u_char pwm_fast; /**< PWM during fast movement */ u_char pwm_duty_fast; /**< PWM duty during fast movement */ u_char mclk_fast; /**< MCLK during fast movement */ u_short dpi_thresh; u_short lineend; /** * here we define some ranges for better supporting * non-Plustek devices with it's different hardware * we can set the MCLK and the motor PWM stuff for color * and gray modes (8bit and 14/16bit modes) * 0 1 2 3 4 5 6 7 8 9 * <= 75 <=100 <=150 <=200 <=300 <=400 <=600 <= 800 <=1200 <=2400DPI */ MDef motor_sets[_MAX_CLK]; /**< motor PWM settings during scan */ double color_mclk_8[_MAX_CLK]; /**< MCLK settings for color scan */ double color_mclk_16[_MAX_CLK]; /**< MCLK settings for color (16bit) scan*/ double gray_mclk_8[_MAX_CLK]; /**< MCLK settings for gray scan */ double gray_mclk_16[_MAX_CLK]; /**< MCLK settings for gray (16bit) scan */ } ClkMotorDef; /** for transferring some info between child and parent after calibration */ #define _MAX_SHAD 0x4000 #define _SHADING_BUF (_MAX_SHAD*3) /**< max size of the shading buffer */ typedef struct { u_long transferRate; } IPCDef; #endif /* guard __PLUSTEK_USB_H__ */ /* END PLUSTEK-USB.H ........................................................*/ sane-backends-1.0.27/backend/pieusb_buffer.c0000664000175000017500000006034612775312261015614 00000000000000/* sane - Scanner Access Now Easy. pieusb_buffer.c Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ========================================================================= * * Read buffer * * Data obtained from the scanner cannot be presented to the frontend immediately. * The scanner returns data in the 'index' or 'line' color format, which means it * returns data in batches which contain a single color of a scan line. * * These must finally be converted into the SANE data format (data for a single * pixel in consecutive bytes). Apart from that, sane_read() must be able to * return any amount of data bytes. * * In between, data processing may be necessary, usually requiring the whole * image to be available. * * To accommodate all this, the buffer stores all samples as 16-bit values, even * if the original values are 8-bit or even 1 bit. This is a waste of space, but * makes processing much easier, and it is only temporary. * * The read buffer is constructed by a call to buffer_create(), which initializes * the buffer based on width, height, number of colors and depth. The buffer * contains data organized in color planes, with each plane consisting of lines, * each line of a fixed number of (single color) pixels, and each pixel of a fixed * number of bits (or bytes). * * The buffer maintains read and write pointers. * * Multi-color data with a bit depth of 1 are packed in single color bytes, so * the data obtained from the scanner does not need conversion. * * ========================================================================= */ #define DEBUG_DECLARE_ONLY /* Configuration defines */ #include "../include/sane/config.h" /* SANE includes */ #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_config.h" /* Backend includes */ #define BACKEND_NAME pieusb #include "../include/sane/sanei_backend.h" #include "pieusb.h" #include "pieusb_specific.h" #include "pieusb_buffer.h" #ifdef HAVE_ALLOCA_H #include #endif #include #include #include #include "byteorder.h" static void buffer_update_read_index(struct Pieusb_Read_Buffer* buffer, int increment); /* READER */ /** * Initialize the buffer. * A scanner has a Pieusb_Read_Buffer struct as one of its members. * * @param buffer the buffer to initialize * @param width number of pixels on a line (row) * @param height number of lines in the buffer (pixels in a column) * @param colors bitmap specifying the colors in the scanned data (bitmap: 0000 IBGR) * @param depth number of bits of a color * @param bigendian how to store multi-byte values: bigendian if true * @param maximum_size maximum size of buffer (-1 = size of image) */ SANE_Status sanei_pieusb_buffer_create(struct Pieusb_Read_Buffer* buffer, SANE_Int width, SANE_Int height, SANE_Byte color_spec, SANE_Byte depth) { int k, result; unsigned int buffer_size_bytes; unsigned char g; /* Base parameters */ buffer->width = width; buffer->height = height; buffer->colors = 0; if (color_spec & 0x01) { buffer->color_index_red = 0; buffer->colors++; } else { buffer->color_index_red = -1; } if (color_spec & 0x02) { buffer->color_index_green = 1; buffer->colors++; } else { buffer->color_index_green = -1; } if (color_spec & 0x04) { buffer->color_index_blue = 2; buffer->colors++; } else { buffer->color_index_blue = -1; } if (color_spec & 0x08) { buffer->color_index_infrared = 3; buffer->colors++; } else { buffer->color_index_infrared = -1; } if (buffer->colors == 0) { DBG(DBG_error, "sanei_pieusb_buffer_create(): no colors specified\n"); return SANE_STATUS_INVAL; } buffer->depth = depth; if (depth < 1 || depth > 16) { DBG(DBG_error, "sanei_pieusb_buffer_create(): unsupported depth %d\n", depth); return SANE_STATUS_INVAL; } buffer->packing_density = (depth == 1) ? 8 : 1; /* These are all the situations we have */ /* Derived*/ buffer->packet_size_bytes = (buffer->depth * buffer->packing_density + 7) / 8; buffer->line_size_packets = (buffer->width + buffer->packing_density -1) / buffer->packing_density; buffer->line_size_bytes = buffer->line_size_packets * buffer->packet_size_bytes; buffer->image_size_bytes = buffer->colors * buffer->height * buffer->line_size_bytes; /* Create empty file */ snprintf(buffer->buffer_name, L_tmpnam, "/tmp/sane.XXXXXX"); if (buffer->data_file != 0) /* might still be open from previous invocation */ close(buffer->data_file); buffer->data_file = mkstemp(buffer->buffer_name); if (buffer->data_file == -1) { buffer->data_file = 0; buffer->data = NULL; perror("sanei_pieusb_buffer_create(): error opening image buffer file"); return SANE_STATUS_IO_ERROR; } /* Stretch the file size */ buffer_size_bytes = buffer->width * buffer->height * buffer->colors * sizeof(SANE_Uint); if (buffer_size_bytes == 0) { close(buffer->data_file); buffer->data_file = 0; DBG(DBG_error, "sanei_pieusb_buffer_create(): buffer_size is zero: width %d, height %d, colors %d\n", buffer->width, buffer->height, buffer->colors); return SANE_STATUS_INVAL; } result = lseek(buffer->data_file, buffer_size_bytes-1, SEEK_SET); if (result == -1) { close(buffer->data_file); buffer->data_file = 0; buffer->data = NULL; DBG(DBG_error, "sanei_pieusb_buffer_create(): error calling lseek() to 'stretch' the file to %d bytes\n", buffer_size_bytes-1); perror("sanei_pieusb_buffer_create(): error calling lseek()"); return SANE_STATUS_INVAL; } /* Write one byte at the end */ g = 0x00; result = write(buffer->data_file, &g, 1); if (result < 0) { close(buffer->data_file); buffer->data_file = 0; buffer->data = NULL; perror("sanei_pieusb_buffer_create(): error writing a byte at the end of the file"); return SANE_STATUS_IO_ERROR; } #ifdef HAVE_MMAP /* Create memory map */ buffer->data = mmap(NULL, buffer_size_bytes, PROT_WRITE | PROT_READ, MAP_SHARED, buffer->data_file, 0); if (buffer->data == MAP_FAILED) { close(buffer->data_file); buffer->data = NULL; perror("sanei_pieusb_buffer_create(): error mapping file"); return SANE_STATUS_INVAL; } #else #error mmap(2) not available, aborting #endif buffer->data_size = buffer_size_bytes; /* Reading and writing */ buffer->p_read = calloc(buffer->colors, sizeof(SANE_Uint*)); if (buffer->p_read == NULL) return SANE_STATUS_NO_MEM; buffer->p_write = calloc(buffer->colors, sizeof(SANE_Uint*)); if (buffer->p_write == NULL) return SANE_STATUS_NO_MEM; for (k = 0; k < buffer->colors; k++) { buffer->p_write[k] = buffer->data + k * buffer->height * buffer->width; buffer->p_read[k] = buffer->p_write[k]; } buffer->read_index[0] = 0; buffer->read_index[1] = 0; buffer->read_index[2] = 0; buffer->read_index[3] = 0; /* Statistics */ buffer->bytes_read = 0; buffer->bytes_written = 0; buffer->bytes_unread = 0; DBG(DBG_info,"pieusb: Read buffer created: w=%d h=%d ncol=%d depth=%d in file %s\n", buffer->width, buffer->height, buffer->colors, buffer->depth, buffer->buffer_name); return SANE_STATUS_GOOD; } /** * Delete buffer and free its resources * * @param buffer */ void sanei_pieusb_buffer_delete(struct Pieusb_Read_Buffer* buffer) { #ifdef HAVE_MMAP munmap(buffer->data, buffer->data_size); #else #error mmap(2) not available, aborting #endif /* ftruncate(buffer->data_file,0); Can we delete given a file-descriptor? */ close(buffer->data_file); /* remove fs entry */ unlink(buffer->buffer_name); buffer->data_file = 0; buffer->data_size = 0; free(buffer->p_read); free(buffer->p_write); buffer->data = 0; buffer->width = 0; buffer->height = 0; buffer->depth = 0; buffer->colors = 0; buffer->packing_density = 0; DBG(DBG_info,"pieusb: Read buffer deleted\n"); } /** * Add a line to the reader buffer, for the given color. * The buffer checks and decides how to interpret the data. * * @param buffer * @param color Color code for line * @param line * @param size Number of bytes in line * @return 1 if successful, 0 if not */ SANE_Int sanei_pieusb_buffer_put_single_color_line(struct Pieusb_Read_Buffer* buffer, SANE_Byte color, void* line, SANE_Int size) { SANE_Int c, k, m, n; /* Check index code */ c = -1; switch (color) { case 'R': c = buffer->color_index_red; break; case 'G': c = buffer->color_index_green; break; case 'B': c = buffer->color_index_blue; break; case 'I': c = buffer->color_index_infrared; break; } if (c == -1) { DBG(DBG_error, "sanei_pieusb_buffer_put_single_color_line(): color '%c' not specified when buffer was created\n", color); return 0; } DBG(DBG_info_buffer, "sanei_pieusb_buffer_put_single_color_line() line color = %d (0=R, 1=G, 2=B, 3=I)\n",c); /* Check line size (for a line with a single color) */ if (buffer->line_size_bytes != size) { DBG(DBG_error, "sanei_pieusb_buffer_put_single_color_line(): incorrect line size, expecting %d, got %d\n", buffer->line_size_bytes, size); return 0; } /* The general approach for all densities and packet sizes * - process packet_size_bytes at a time * - use packing_density to decode the full packet into separate values * - now save these values as neighbouring pixels on the current line * Use custom code for the 1-byte and 2-byte single sample cases, * because the general approach is a bit overkill for them. */ if (buffer->packet_size_bytes == 1 && buffer->packing_density == 1) { uint8_t* p_packet = (uint8_t*)line; n = 0; while (n < size) { /* Get next packet data & store in buffer */ *buffer->p_write[c]++ = *p_packet++; n++; } } else if (buffer->packet_size_bytes == 2 && buffer->packing_density == 1) { uint16_t* p_packet = (uint16_t*)line; n = 0; while (n < size) { /* Get next packet data & store in buffer */ *buffer->p_write[c]++ = le16toh (*p_packet++); n += 2; } } else { uint8_t* p_packet = (uint8_t*)line; uint8_t *packet = (uint8_t *)alloca(buffer->packet_size_bytes * sizeof(uint8_t)); SANE_Uint val; uint8_t mask = ~(0xFF >> buffer->depth); /* byte with depth most significant bits set */ n = 0; while (n < size) { /* Get next packet data */ for (k = 0; k < buffer->packet_size_bytes; k++) packet[k] = *p_packet++; /* Unpack packing_density samples from packet. Of course, * buffer->depth * packing_density <= # bits in packet. * That is checked at buffer creation. */ for (k = 0; k < buffer->packing_density; k++) { /* Take 1st depth bits and store in val */ val = (packet[0] & mask) >> (8-buffer->depth); /* Now shift packet bytes depth bits left */ for (m = 0; m < buffer->packet_size_bytes; m++) { /* Shift left one sample */ packet[m] <<= buffer->depth; if (m < buffer->packet_size_bytes-1) { /* If there are more bytes, insert 1st depth bits of next byte */ packet[m] |= (packet[m+1] >> (8-buffer->depth)); } } /* Store in buffer */ *buffer->p_write[c]++ = val; } n += buffer->packet_size_bytes; } } /* Update state & statistics */ buffer->bytes_written += size; buffer->bytes_unread += size; /* Output current buffer state */ /* buffer_output_state(buffer); */ return 1; } /** * Write line of full color pixels to the buffer. * * @param buffer Read buffer * @param pixel array of full color pixel data * @param size Number of bytes in the line * @return 1 if successful, 0 if not */ /** * */ SANE_Int sanei_pieusb_buffer_put_full_color_line(struct Pieusb_Read_Buffer* buffer, void* line, int size) { int k, c, m, n; DBG(DBG_info_buffer, "sanei_pieusb_buffer_put_full_color_line() entered\n"); /* Check line size */ if (buffer->line_size_bytes * buffer->colors != size) { DBG(DBG_error, "sanei_pieusb_buffer_put_full_color_line(): incorrect line size, expecting %d, got %d\n", buffer->line_size_bytes * buffer->colors, size); return 0; } /* The general approach for all densities and packet sizes * - process packet_size_bytes at a time * - use packing_density to decode the full packet into separate values * - now save these values as neighbouring pixels on the current line * Use custom code for the 1-byte and 2-byte single sample cases, * because the general approach is a bit overkill for them. */ if (buffer->packet_size_bytes == 1 && buffer->packing_density == 1) { uint8_t* p_packet = (uint8_t*)line; n = 0; while (n < size) { /* Get next packet data & store in buffer */ for (c = 0; c < buffer->colors; c++) { *buffer->p_write[c]++ = *p_packet++; n++; } } } else if (buffer->packet_size_bytes == 2 && buffer->packing_density == 1) { uint16_t* p_packet = (uint16_t*)line; n = 0; while (n < size) { /* Get next packet data & store in buffer */ for (c = 0; c < buffer->colors; c++) { *buffer->p_write[c]++ = le16toh (*p_packet++); n += 2; } } } else { uint8_t* p_packet = (uint8_t*)line; uint8_t *packet = (uint8_t *)alloca(buffer->packet_size_bytes * sizeof(uint8_t)); SANE_Uint val; uint8_t mask = ~(0xFF >> buffer->depth); /* byte with depth most significant bits set */ /* DBG(DBG_info,"buffer_put_full_color_line(): mask %02x\n",mask); */ n = 0; while (n < size) { /* Get next packet data */ for (c = 0; c < buffer->colors; c++) { for (k = 0; k < buffer->packet_size_bytes; k++) { packet[k] = *p_packet++; /* DBG(DBG_info,"buffer_put_full_color_line(): packet[%d] = %02x\n",k,packet[k]); */ } /* Unpack packing_density samples from packet. Of course, * buffer->depth * packing_density <= # bits in packet. * That is checked at buffer creation. */ for (k = 0; k < buffer->packing_density; k++) { /* Take 1st depth bits and store in val */ val = (packet[0] & mask) >> (8-buffer->depth); /* DBG(DBG_info,"buffer_put_full_color_line(): val[%d] = %02x\n",k,val); */ /* Now shift packet bytes depth bits left */ for (m = 0; m < buffer->packet_size_bytes; m++) { /* Shift left one sample */ packet[m] <<= buffer->depth; /* DBG(DBG_info,"buffer_put_full_color_line(): shift packet[%d] = %02x\n",m,packet[m]); */ if (m < buffer->packet_size_bytes-1) { /* If there are more bytes, insert 1st depth bits of next byte */ packet[m] |= (packet[m+1] >> (8-buffer->depth)); /* DBG(DBG_info,"buffer_put_full_color_line(): shift packet[%d] = %02x\n",m,packet[m]); */ } } /* Store in buffer */ *buffer->p_write[c]++ = val; } n += buffer->packet_size_bytes; } } } /* Update state & statistics */ buffer->bytes_written += size; buffer->bytes_unread += size; /* Output current buffer state */ /* buffer_output_state(buffer); */ return 1; } /** * Return bytes from the buffer. Do not mind pixel boundaries. * Since the image data is organized in color planes, return bytes from the * planes in the defined order. Take care to return multi-byte values after * each other. Pack unpacked values. * * @param buffer Buffer to return bytes from. * @param data Byte array to return bytes in * @param max_len Maximum number of bytes returned * @param len Actual number of bytes returned */ void sanei_pieusb_buffer_get(struct Pieusb_Read_Buffer* buffer, SANE_Byte* data, SANE_Int max_len, SANE_Int* len) { SANE_Byte *pdata; SANE_Int n, i, n_bits, N; DBG(DBG_info_buffer, "sanei_pieusb_buffer_get() entered\n"); /* Read from the p_read locations */ pdata = data; n = 0; N = buffer->width * buffer->height; /* Determine bytes to return */ if (buffer->packet_size_bytes == 1 && buffer->packing_density == 1) { /* Single byte values in buffer */ while (n < max_len && buffer->bytes_read < buffer->image_size_bytes) { /* Return byte*/ *pdata++ = *(buffer->data + N*buffer->read_index[0] + buffer->width*buffer->read_index[1] + buffer->read_index[2]) & 0xFF; /* Update read indices */ buffer_update_read_index(buffer,1); /* Update number of bytes read */ buffer->bytes_read++; n++; } } else if (buffer->packet_size_bytes == 1 && buffer->packing_density == 8) { /* Unpacked bits in buffer: repack */ while (n < max_len && buffer->bytes_read < buffer->image_size_bytes) { uint8_t val = 0; /* How many bits to pack? At the end of a line it may be less than 8 */ n_bits = 8; if (buffer->width - buffer->read_index[2] < 8) { n_bits = buffer->width - buffer->read_index[2]; } /* Pack n_bits samples from same color plane */ for (i = 0; i < n_bits; i++) { if (*(buffer->data + N*buffer->read_index[0] + buffer->width*buffer->read_index[1] + buffer->read_index[2] + i) > 0) { val |= (0x80 >> i); } } /* Return byte */ *pdata++ = val; /* Update read indices */ buffer_update_read_index(buffer,n_bits); /* Update number of bytes read */ buffer->bytes_read++; n++; } } else if (buffer->packet_size_bytes == 2) { /* Two-byte values in buffer */ while (n < max_len && buffer->bytes_read < buffer->image_size_bytes) { /* Pointer to byte to return */ SANE_Uint val = *(buffer->data + N*buffer->read_index[0] + buffer->width*buffer->read_index[1] + buffer->read_index[2]); /* Return byte */ if (buffer->read_index[3] == 0) { *pdata++ = *((SANE_Byte*)(&val)); } else { *pdata++ = *((SANE_Byte*)(&val)+1); } /* Update read indices */ buffer_update_read_index(buffer,1); /* Update number of bytes read */ buffer->bytes_read++; n++; } } else { /* not implemented */ DBG(DBG_error, "buffer_put(): paccket size & density of %d/%d not implementd\n", buffer->packet_size_bytes, buffer->packing_density); return; } *len = n; /* Update statistics */ buffer->bytes_unread -= n; /* Output current buffer state */ /* buffer_output_state(buffer); */ } /** * Update read index to point a given number of bytes past the current position. * * @param buffer the buffer to initialize * @param increment the amount of bytes to move the index */ static void buffer_update_read_index(struct Pieusb_Read_Buffer* buffer, int increment) { /* Update read indices * [3] = byte-index in 2-byte value: increased first, if we have 2-byte data * [2] = index of pixel on line: increased after color plane * [1] = index of line: increased after line is complete * [0] = color index: increased first since SANE requires full color pixels */ if (buffer->read_index[3] == 0 && buffer->packet_size_bytes == 2) { buffer->read_index[3] = 1; } else { buffer->read_index[3] = 0; buffer->read_index[0]++; if (buffer->read_index[0] == buffer->colors) { buffer->read_index[0] = 0; buffer->read_index[2] += increment; if (buffer->read_index[2] >= buffer->width) { buffer->read_index[2] = 0; buffer->read_index[1]++; } } } } #if 0 /** * Display the buffer state. * * @param buffer the buffer to initialize */ static void buffer_output_state(struct Pieusb_Read_Buffer* buffer) { SANE_Int line_size; SANE_Int N, k, loc[4]; line_size = buffer->line_size_bytes * buffer->colors; /* Full line size in bytes */ DBG(DBG_info_buffer, "Buffer data\n"); DBG(DBG_info_buffer," width/height/colors/depth = %d %d %d %d (buffer size %d)\n", buffer->width, buffer->height, buffer->colors, buffer->depth, buffer->image_size_bytes); /* Summary */ N = buffer->width * buffer->height; for (k = 0; k < buffer->colors; k++) { loc[k] = buffer->p_read[k] - buffer->data - k*N; } for (k = buffer->colors; k < 4; k++) { loc[k] = 0; } DBG(DBG_info_buffer, " reading at: lines = %d:%d:%d:%d\n", loc[0], loc[1], loc[2], loc[3]); for (k = 0; k < buffer->colors; k++) { loc[k] = buffer->p_write[k] - buffer->data - k*N; } for (k = buffer->colors; k < 4; k++) { loc[k] = 0; } DBG(DBG_info_buffer, " writing at: lines = %d:%d:%d:%d\n", loc[0], loc[1], loc[2], loc[3]); /* Progress */ double fdata = (double)buffer->bytes_unread/buffer->image_size_bytes*100; double fread = (double)buffer->bytes_read/buffer->image_size_bytes*100; double fwritten = (double)buffer->bytes_written/buffer->image_size_bytes*100; DBG(DBG_info_buffer, " byte counts: image = %d, data = %d (%.0f%%), read = %d (%.0f%%), written = %d (%.0f%%)\n", buffer->image_size_bytes, buffer->bytes_unread, fdata, buffer->bytes_read, fread, buffer->bytes_written, fwritten); DBG(DBG_info_buffer, " line counts: image = %.1f, data = %.1f, read = %.1f, written = %.1f\n", (double)buffer->image_size_bytes/line_size, (double)buffer->bytes_unread/line_size, (double)buffer->bytes_read/line_size, (double)buffer->bytes_written/line_size); } #endif sane-backends-1.0.27/backend/lm9830.h0000664000175000017500000000254212112021330013702 00000000000000/* (c) 2001 Nathan Rutman nathan@gordian.com 11/13/01 National Semi LM9830 scanner-on-a-chip register defs */ #ifndef LM9830_H #define LM9830_H /* LM9830 registers (see lm9830 datasheet for a full description */ #define IMAGE_DATA_AVAIL 0x01 #define STATUS 0x02 #define DATAPORT_TARGET 0x03 #define DATAPORT_ADDR 0x04 #define DATAPORT 0x06 #define COMMAND 0x07 #define CLOCK_DIV 0x08 /* Master clock divider */ #define ACTIVE_PX_START 0x1e /* Active pixel start */ #define LINE_END 0x20 #define DATA_PX_START 0x22 #define DATA_PX_END 0x24 #define COLOR_MODE 0x26 #define LAMP_R_ON 0x2c #define LAMP_R_OFF 0x2e #define LAMP_G_ON 0x30 #define LAMP_G_OFF 0x32 #define LAMP_B_ON 0x34 #define LAMP_B_OFF 0x36 #define PARALLEL_PORT 0x42 /* Parallel port settings */ #define MICROSTEP 0x45 #define STEP_SIZE 0x46 #define FAST_STEP 0x48 #define SKIP_STEPS 0x4a #define BUFFER_LIMIT 0x4e /* Pause scanning when buffer is this full */ #define BUFFER_RESUME 0x4f #define REVERSE_STEPS 0x50 #define STEP_PWM 0x57 #define PAPER_SENSOR 0x58 /* Register 02 flags */ #define STATUS_HOME 0x02 #define STATUS_PAUSE 0x10 #define STATUS_POWER 0x20 /* Register 03 flags */ #define DP_GAMMA 0x00 #define DP_OFFSET 0x01 #define DP_R 0x00 #define DP_G 0x02 #define DP_B 0x04 /* Register 04 flags */ #define DP_WRITE 0x0000 #define DP_READ 0x2000 #endif /* LM9830_H */ sane-backends-1.0.27/backend/pixma_bjnp_private.h0000664000175000017500000002766413063340150016655 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2008 by Louis Lagendijk This file is part of the SANE package. Data structures and definitions for bjnp backend for the Common UNIX Printing System (CUPS). These coded instructions, statements, and computer programs are the property of Louis Lagendijk and are protected by Federal copyright law. Distribution and use rights are outlined in the file "LICENSE.txt" "LICENSE" which should have been included with this file. If this file is missing or damaged, see the license at "http://www.cups.org/". This file is subject to the Apple OS-Developed Software exception. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* * BJNP definitions */ /* selection of options */ /* This works now, disable when it gives you problems */ #define PIXMA_BJNP_USE_STATUS 1 /* sizes */ #define BJNP_PRINTBUF_MAX 1400 /* size of printbuffer */ #define BJNP_CMD_MAX 2048 /* size of BJNP response buffer */ #define BJNP_RESP_MAX 2048 /* size of BJNP response buffer */ #define BJNP_SOCK_MAX 256 /* maximum number of open sockets */ #define BJNP_MODEL_MAX 64 /* max allowed size for make&model */ #define BJNP_STATUS_MAX 256 /* max size for status string */ #define BJNP_IEEE1284_MAX 1024 /* max. allowed size of IEEE1284 id */ #define BJNP_METHOD_MAX 16 /* max length of method */ #define BJNP_HOST_MAX 128 /* max length of hostname or address */ #define BJNP_PORT_MAX 64 /* max length of port string */ #define BJNP_ARGS_MAX 128 /* max length of argument string */ #define BJNP_SERIAL_MAX 16 /* maximum length of serial number */ #define BJNP_NO_DEVICES 16 /* max number of open devices */ #define BJNP_SCAN_BUF_MAX 65536 /* size of scanner data intermediate buffer */ #define BJNP_BLOCKSIZE_START 512 /* startsize for last block detection */ /* timers */ #define BJNP_BROADCAST_INTERVAL 10 /* ms between broadcasts */ #define BJNP_BC_RESPONSE_TIMEOUT 500 /* waiting time for broadc. responses */ #define BJNP_TIMEOUT_DEFAULT 1000 /* minimum tiemout value for network operations */ #define BJNP_USLEEP_MS 1000 /* sleep for 1 msec */ /* retries */ #define BJNP_MAX_SELECT_ATTEMPTS 3 /* max nr of retries on select (EINTR) */ #define BJNP_MAX_BROADCAST_ATTEMPTS 2 /* number of broadcast packets to be sent */ #define BJNP_UDP_RETRY_MAX 3 /* max nt of retries on a udp command */ #define bjnp_dbg DBG #include "../include/sane/sanei_debug.h" /* loglevel definitions */ #define LOG_CRIT 0 #define LOG_NOTICE 1 #define LOG_INFO 2 #define LOG_DEBUG 3 #define LOG_DEBUG2 4 #define LOG_DEBUG3 5 #define BJNP_RESTART_POLL -1 /*************************************/ /* BJNP protocol related definitions */ /*************************************/ /* port numbers */ typedef enum bjnp_port_e { MFNP_PORT_SCAN = 8610, BJNP_PORT_PRINT = 8611, BJNP_PORT_SCAN = 8612, BJNP_PORT_3 = 8613, BJNP_PORT_4 = 8614 } bjnp_port_t; typedef enum { PROTOCOL_BJNP = 0, PROTOCOL_MFNP = 1, PROTOCOL_NONE =2 } bjnp_protocol_t; typedef struct { bjnp_protocol_t protocol_version; int default_port; char * proto_string; char * method_string; } bjnp_protocol_defs_t; bjnp_protocol_defs_t bjnp_protocol_defs[] = { {PROTOCOL_BJNP, BJNP_PORT_SCAN,"BJNP", "bjnp"}, {PROTOCOL_MFNP, MFNP_PORT_SCAN,"MFNP", "mfnp"}, {PROTOCOL_NONE, -1, NULL, NULL} }; /* commands */ typedef enum bjnp_cmd_e { CMD_UDP_DISCOVER = 0x01, /* discover if service type is listening at this port */ CMD_UDP_START_SCAN = 0x02, /* start scan pressed, sent from scanner to 224.0.0.1 */ CMD_UDP_JOB_DETAILS = 0x10, /* send print/ scanner job owner details */ CMD_UDP_CLOSE = 0x11, /* request connection closure */ CMD_UDP_GET_STATUS = 0x20, /* get printer status */ CMD_TCP_REQ = 0x20, /* read data from device */ CMD_TCP_SEND = 0x21, /* send data to device */ CMD_UDP_GET_ID = 0x30, /* get printer identity */ CMD_UDP_POLL = 0x32 /* poll scanner for button status */ } bjnp_cmd_t; /* command type */ typedef enum uint8_t { BJNP_CMD_PRINT = 0x1, /* printer command */ BJNP_CMD_SCAN = 0x2, /* scanner command */ BJNP_RES_PRINT = 0x81, /* printer response */ BJNP_RES_SCAN = 0x82 /* scanner response */ } bjnp_cmd_type_t; /***************************/ /* BJNP protocol structure */ /***************************/ /* The common protocol header */ struct __attribute__ ((__packed__)) BJNP_command { char BJNP_id[4]; /* string: BJNP */ uint8_t dev_type; /* 1 = printer, 2 = scanner */ /* responses have MSB set */ uint8_t cmd_code; /* command code/response code */ int16_t unknown1; /* unknown, always 0? */ int16_t seq_no; /* sequence number */ uint16_t session_id; /* session id for printing */ uint32_t payload_len; /* length of command buffer */ }; /* Layout of the init response buffer */ struct __attribute__ ((__packed__)) DISCOVER_RESPONSE { struct BJNP_command response; /* reponse header */ char unknown1[4]; /* 00 01 08 00 */ char mac_len; /* length of mac address */ char addr_len; /* length of address field */ unsigned char mac_addr[6]; /* printers mac address */ union { struct __attribute__ ((__packed__)) { unsigned char ipv4_addr[4]; } ipv4; struct __attribute__ ((__packed__)) { unsigned char ipv6_addr_1[16]; unsigned char ipv6_addr_2[16]; } ipv6; } addresses; }; /* layout of payload for the JOB_DETAILS command */ struct __attribute__ ((__packed__)) JOB_DETAILS { struct BJNP_command cmd; /* command header */ char unknown[8]; /* don't know what these are for */ char hostname[64]; /* hostname of sender */ char username[64]; /* username */ char jobtitle[256]; /* job title */ }; /* layout of the poll command, not everything is complete */ struct __attribute__ ((__packed__)) POLL_DETAILS { struct BJNP_command cmd; /* command header */ uint16_t type; /* 0, 1, 2 or 5 */ /* 05 = reset status */ union { struct __attribute__ ((__packed__)) { char empty0[78]; /* type 0 has only 0 */ } type0; /* length = 80 */ struct __attribute__ ((__packed__)) { char empty1[6]; /* 0 */ char user_host[64]; /* unicode user hostname */ uint64_t emtpy2; /* 0 */ } type1; /* length = 80 */ struct __attribute__ ((__packed__)) { uint16_t empty_1; /* 00 00 */ uint32_t dialog; /* constant dialog id, from previous response */ char user_host[64]; /* unicode user hostname */ uint32_t unknown_1; /* 00 00 00 14 */ uint32_t empty_2[5]; /* only 0 */ uint32_t unknown_2; /* 00 00 00 10 */ char ascii_date[16]; /* YYYYMMDDHHMMSS only for type 2 */ } type2; /* length = 116 */ struct __attribute__ ((__packed__)) { uint16_t empty_1; /* 00 00 */ uint32_t dialog; /* constant dialog id, from previous response */ char user_host[64]; /* unicode user hostname */ uint32_t unknown_1; /* 00 00 00 14 */ uint32_t key; /* copied from key field in status msg */ uint32_t unknown_3[5]; /* only 0 */ } type5; /* length = 100 */ } extensions; }; /* the poll response layout */ struct __attribute__ ((__packed__)) POLL_RESPONSE { struct BJNP_command cmd; /* command header */ unsigned char result[4]; /* unknown stuff, result[2] = 80 -> status is available*/ /* result[8] is dialog, size? */ uint32_t dialog; /* to be returned in next request */ uint32_t unknown_2; /* returns the 00 00 00 14 from unknown_2 in request */ uint32_t key; /* to be returned in type 5 status reset */ unsigned char status[20]; /* interrupt status */ }; /* Layout of ID and status responses */ struct __attribute__ ((__packed__)) IDENTITY { struct BJNP_command cmd; union __attribute__ ((__packed__)) { struct __attribute__ ((__packed__)) payload_s { uint16_t id_len; /* length of identity */ char id[BJNP_IEEE1284_MAX]; /* identity */ } bjnp; struct __attribute__ ((__packed__)) mfnp { char id[BJNP_IEEE1284_MAX]; } mfnp; } payload; }; /* response to TCP print command */ struct __attribute__ ((__packed__)) SCAN_BUF { struct BJNP_command cmd; char scan_data[65536]; }; /**************************/ /* Local enum definitions */ /**************************/ typedef enum bjnp_paper_status_e { BJNP_PAPER_UNKNOWN = -1, BJNP_PAPER_OK = 0, BJNP_PAPER_OUT = 1 } bjnp_paper_status_t; typedef enum { BJNP_STATUS_GOOD, BJNP_STATUS_INVAL, BJNP_STATUS_ALREADY_ALLOCATED } BJNP_Status; /* button polling */ typedef enum { BJNP_POLL_STOPPED = 0, BJNP_POLL_STARTED = 1, BJNP_POLL_STATUS_RECEIVED = 2 } BJNP_polling_status_e; typedef union { struct sockaddr_storage storage; struct sockaddr addr; struct sockaddr_in ipv4; struct sockaddr_in6 ipv6; } bjnp_sockaddr_t; typedef enum { BJNP_ADDRESS_IS_LINK_LOCAL = 0, BJNP_ADDRESS_IS_GLOBAL = 1, BJNP_ADDRESS_HAS_FQDN = 2 } bjnp_address_type_t; /* * Device information for opened devices */ typedef struct device_s { int open; /* connection to scanner is opened */ /* protocol version */ int protocol; char *protocol_string; /* sockets */ int tcp_socket; /* open tcp socket for communcation to scannner */ int16_t serial; /* sequence number of command */ /* communication state */ int session_id; /* session id used in bjnp protocol for TCP packets */ int last_cmd; /* last command sent */ /* TCP bulk read state information */ size_t blocksize; /* size of (TCP) blocks returned by the scanner */ size_t scanner_data_left; /* TCP data left from last read request */ char last_block; /* last TCP read command was shorter than blocksize */ /* device information */ char mac_address[BJNP_HOST_MAX]; /* mac-address, used as device serial no */ bjnp_sockaddr_t * addr; /* ip-address of the scanner */ int address_level; /* link local, public or has a FQDN */ int bjnp_timeout; /* timeout (msec) for next poll command */ int bjnp_min_timeout; /* device specific min timeout */ #ifdef PIXMA_BJNP_USE_STATUS /* polling state information */ char polling_status; /* status polling ongoing */ uint32_t dialog; /* poll dialog */ uint32_t status_key; /* key of last received status message */ #endif } bjnp_device_t; sane-backends-1.0.27/backend/dell1600n_net.c0000664000175000017500000016434212775312260015247 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2006 Jon Chambers This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Dell 1600n network scan driver for SANE. To debug: SANE_DEBUG_DELL1600N_NET=255 scanimage --verbose 2>scan.errs 1>scan.png */ /*********************************************************** * INCLUDES ***********************************************************/ #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #define BACKEND_NAME dell1600n_net #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include #include #include #include #include /* :NOTE: these are likely to be platform-specific! */ #include #include #include #include #include #include #include /* OS/2... */ #ifndef SHUT_RDWR #define SHUT_RDWR 2 #endif /*********************************************************** * DEFINITIONS ***********************************************************/ /* Maximum number of scanners */ #define MAX_SCANNERS 32 /* version number */ #define DRIVER_VERSION SANE_VERSION_CODE( SANE_CURRENT_MAJOR, V_MINOR, 0 ) /* size of buffer for socket communication */ #define SOCK_BUF_SIZE 2048 /* size of registation name */ #define REG_NAME_SIZE 64 struct DeviceRecord { SANE_Device m_device; char * m_pName; /* storage of name */ char * m_pModel; /* storage of model */ }; /* a buffer struct to store "stuff" */ struct ComBuf { size_t m_capacity; /* current allocated size in bytes */ size_t m_used; /* current used size in bytes */ unsigned char *m_pBuf; /* storage (or NULL if none allocated) */ }; /* state data for a single scanner connection */ struct ScannerState { int m_udpFd; /* file descriptor to UDP socket */ int m_tcpFd; /* file descriptor to TCP socket */ struct sockaddr_in m_sockAddr; /* printer address */ struct ComBuf m_buf; /* buffer for network data */ struct ComBuf m_imageData; /* storage for decoded image data */ int m_numPages; /* number of complete pages (host byte order) */ struct ComBuf m_pageInfo; /* "array" of numPages PageInfo structs */ int m_bFinish; /* set non-0 to signal that we are finished */ int m_bCancelled; /* set non-0 that bFinish state arose from cancelation */ char m_regName[REG_NAME_SIZE]; /* name with which to register */ unsigned short m_xres; /* x resolution (network byte order) */ unsigned short m_yres; /* y resolution (network byte order) */ unsigned int m_composition; /* composition (0x01=>TIFF/PDF,0x40=>JPEG) (network byte order) */ unsigned char m_brightness; /* brightness */ unsigned int m_compression; /* compression (0x08=>CCIT Group 4,0x20=>JPEG) (network byte order) */ unsigned int m_fileType; /* file type (2=>TIFF,4=>PDF,8=>JPEG)(network byte order) */ unsigned int m_pixelWidth; /* width in pixels (network byte order) */ unsigned int m_pixelHeight; /* height in pixels (network byte order) */ unsigned int m_bytesRead; /* bytes read by SANE (host byte order) */ unsigned int m_currentPageBytes;/* number of bytes of current page read (host byte order) */ }; /* state data for a single page NOTE: all ints are in host byte order */ struct PageInfo { int m_width; /* pixel width */ int m_height; /* pixel height */ int m_totalSize; /* total page size (bytes) */ int m_bytesRemaining; /* number of bytes not yet passed to SANE client */ }; /* struct for in-memory jpeg decompression */ struct JpegDataDecompState { struct jpeg_decompress_struct m_cinfo; /* base struct */ unsigned char *m_pData; /* data pointer */ unsigned int m_bytesRemaining; /* amount of unprocessed data */ }; /* initial ComBuf allocation */ #define INITIAL_COM_BUF_SIZE 1024 /*********************************************************** * FUNCTION PROTOTYPES ***********************************************************/ /* print hex buffer to stdout */ static void HexDump (int debugLevel, const unsigned char *buf, size_t bufSize); /* clears gKnownDevices array */ static void ClearKnownDevices (void); /* initialise a ComBuf struct */ static int InitComBuf (struct ComBuf *pBuf); /* free a ComBuf struct */ static void FreeComBuf (struct ComBuf *pBuf); /* add data to a ComBuf struct */ static int AppendToComBuf (struct ComBuf *pBuf, const unsigned char *pData, size_t datSize); /* remove data from the front of a ComBuf struct */ static int PopFromComBuf (struct ComBuf *pBuf, size_t datSize); /* initialise a packet */ static int InitPacket (struct ComBuf *pBuf, char type); /* append message to a packet */ static int AppendMessageToPacket (struct ComBuf *pBuf, char messageType, char *messageName, char valueType, void *pValue, size_t valueLen); /* write length data to packet header */ static void FinalisePacket (struct ComBuf *pBuf); /* \return 1 if message is complete, 0 otherwise */ static int MessageIsComplete (unsigned char *pData, size_t size); /* process a registration broadcast response \return DeviceRecord pointer on success (caller frees), NULL on failure */ static struct DeviceRecord *ProcessFindResponse (unsigned char *pData, size_t size); /* frees a scanner state struct stored in gOpenScanners */ static void FreeScannerState (int iHandle); /* \return 1 if iHandle is a valid member of gOpenScanners, 0 otherwise */ static int ValidScannerNumber (int iHandle); /* process UDP responses, \return 0 in success, >0 otherwise */ static int ProcessUdpResponse (unsigned char *pData, size_t size, struct ScannerState *pState); /* process TCP responses, \return 0 in success, >0 otherwise */ static int ProcessTcpResponse (struct ScannerState *pState, struct ComBuf *pTcpBufBuf); /* Process the data from a single scanned page, \return 0 in success, >0 otherwise */ static int ProcessPageData (struct ScannerState *pState); /* Libjpeg decompression interface */ static void JpegDecompInitSource (j_decompress_ptr cinfo); static boolean JpegDecompFillInputBuffer (j_decompress_ptr cinfo); static void JpegDecompSkipInputData (j_decompress_ptr cinfo, long numBytes); static void JpegDecompTermSource (j_decompress_ptr cinfo); /*********************************************************** * GLOBALS ***********************************************************/ /* Results of last call to sane_get_devices */ static struct DeviceRecord *gKnownDevices[MAX_SCANNERS]; /* Array of open scanner device states. :NOTE: (int)SANE_Handle is an offset into this array */ static struct ScannerState *gOpenScanners[MAX_SCANNERS]; /* scanner port */ static unsigned short gScannerPort = 1124; /* ms to wait for registration replies */ static unsigned short gRegReplyWaitMs = 300; /*********************************************************** * FUNCTION IMPLEMENTATIONS ***********************************************************/ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { /* init globals */ memset (gKnownDevices, 0, sizeof (gKnownDevices)); memset (gOpenScanners, 0, sizeof (gOpenScanners)); /* report version */ *version_code = DRIVER_VERSION; /* init debug */ DBG_INIT (); return SANE_STATUS_GOOD; } /* sane_init */ /***********************************************************/ void sane_exit (void) { int iHandle; /* clean up */ ClearKnownDevices (); for (iHandle = 0; iHandle < MAX_SCANNERS; ++iHandle) { if (gOpenScanners[iHandle]) FreeScannerState (iHandle); } } /* sane_exit */ /***********************************************************/ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { int ret; unsigned char sockBuf[SOCK_BUF_SIZE]; int sock, optYes; struct DeviceRecord *pDevice; struct ComBuf queryPacket; struct sockaddr_in remoteAddr; unsigned char ucVal; fd_set readFds; struct timeval selTimeVal; int nread, iNextDevice; FILE *fConfig; char configBuf[ 256 ]; const char *pVal; int valLen; /* init variables */ ret = SANE_STATUS_GOOD; sock = 0; pDevice = NULL; optYes = 1; InitComBuf (&queryPacket); /* clear previous results */ ClearKnownDevices (); iNextDevice = 0; /* look for a config file */ fConfig = sanei_config_open( "dell1600n_net.conf" ); if ( fConfig ) { while ( ! feof( fConfig ) ) { if ( ! sanei_config_read ( configBuf, sizeof( configBuf ), fConfig ) ) break; /* skip whitespace */ pVal = sanei_config_skip_whitespace ( configBuf ); /* skip comments */ if ( *pVal == '#' ) continue; /* process named_scanner */ valLen = strlen( "named_scanner:" ); if ( ! strncmp( pVal, "extra_scanner:", valLen ) ){ pVal = sanei_config_skip_whitespace ( pVal + valLen ); pDevice = malloc (sizeof (struct DeviceRecord)); if (!pDevice) { DBG (1, "sane_get_devices: memory allocation failure\n"); break; } pDevice->m_pName = strdup (pVal); pDevice->m_device.vendor = "Dell"; pDevice->m_pModel = strdup( "1600n" ); pDevice->m_device.type = "multi-function peripheral"; pDevice->m_device.name = pDevice->m_pName; pDevice->m_device.model = pDevice->m_pModel; /* add to list */ gKnownDevices[iNextDevice++] = pDevice; continue; } /* if */ } /* while */ /* Close the file */ fclose( fConfig ); } /* open UDP socket */ sock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock == -1) { DBG (1, "Error creating socket\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &optYes, sizeof (optYes)); /* prepare select mask */ FD_ZERO (&readFds); FD_SET (sock, &readFds); selTimeVal.tv_sec = 0; selTimeVal.tv_usec = gRegReplyWaitMs * 1000; /* init a packet */ InitPacket (&queryPacket, 0x01); /* add query */ ucVal = 0; AppendMessageToPacket (&queryPacket, 0x25, "std-scan-discovery-all", 0x02, &ucVal, sizeof (ucVal)); FinalisePacket (&queryPacket); DBG (10, "Sending:\n"); HexDump (10, queryPacket.m_pBuf, queryPacket.m_used); remoteAddr.sin_family = AF_INET; remoteAddr.sin_port = htons (gScannerPort); remoteAddr.sin_addr.s_addr = 0xFFFFFFFF; /* broadcast */ if (sendto (sock, queryPacket.m_pBuf, queryPacket.m_used, 0, &remoteAddr, sizeof (remoteAddr)) == -1) { DBG (1, "Error sending broadcast packet\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } /* process replies */ while (select (sock + 1, &readFds, NULL, NULL, &selTimeVal)) { /* break if we've got no more storage space in array */ if (iNextDevice >= MAX_SCANNERS) { DBG (1, "sane_get_devices: more than %d devices, ignoring\n", MAX_SCANNERS); break; } nread = read (sock, sockBuf, sizeof (sockBuf)); DBG (5, "Got a broadcast response, (%d bytes)\n", nread); if (nread <= 0) break; HexDump (10, sockBuf, nread); /* process response (skipping bad ones) */ if (!(pDevice = ProcessFindResponse (sockBuf, nread))) continue; /* add to list */ gKnownDevices[iNextDevice++] = pDevice; } /* while */ /* report our finds */ *device_list = (const SANE_Device **) gKnownDevices; cleanup: if (sock) close (sock); FreeComBuf (&queryPacket); return ret; } /* sane_get_devices */ /***********************************************************/ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { int iHandle = -1, i; SANE_Status status = SANE_STATUS_GOOD; struct hostent *pHostent; char *pDot; DBG( 5, "sane_open: %s\n", devicename ); /* find the next available scanner pointer in gOpenScanners */ for (i = 0; i < MAX_SCANNERS; ++i) { if (gOpenScanners[i]) continue; iHandle = i; break; } /* for */ if (iHandle == -1) { DBG (1, "sane_open: no space left in gOpenScanners array\n"); status = SANE_STATUS_NO_MEM; goto cleanup; } /* allocate some space */ if (!(gOpenScanners[iHandle] = malloc (sizeof (struct ScannerState)))) { status = SANE_STATUS_NO_MEM; goto cleanup; } /* init data */ memset (gOpenScanners[iHandle], 0, sizeof (struct ScannerState)); InitComBuf (&gOpenScanners[iHandle]->m_buf); InitComBuf (&gOpenScanners[iHandle]->m_imageData); InitComBuf (&gOpenScanners[iHandle]->m_pageInfo); gOpenScanners[iHandle]->m_xres = ntohs (200); gOpenScanners[iHandle]->m_yres = ntohs (200); gOpenScanners[iHandle]->m_composition = ntohl (0x01); gOpenScanners[iHandle]->m_brightness = 0x80; gOpenScanners[iHandle]->m_compression = ntohl (0x08); gOpenScanners[iHandle]->m_fileType = ntohl (0x02); /* look up scanner name */ pHostent = gethostbyname (devicename); if ((!pHostent) || (!pHostent->h_addr_list)) { DBG (1, "sane_open: error looking up scanner name %s\n", devicename); status = SANE_STATUS_INVAL; goto cleanup; } /* open a UDP socket */ if (!(gOpenScanners[iHandle]->m_udpFd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP))) { DBG (1, "sane_open: error opening socket\n"); status = SANE_STATUS_IO_ERROR; goto cleanup; } /* connect to the scanner */ memset (&gOpenScanners[iHandle]->m_sockAddr, 0, sizeof (gOpenScanners[iHandle]->m_sockAddr)); gOpenScanners[iHandle]->m_sockAddr.sin_family = AF_INET; gOpenScanners[iHandle]->m_sockAddr.sin_port = htons (gScannerPort); memcpy (&gOpenScanners[iHandle]->m_sockAddr.sin_addr, pHostent->h_addr_list[0], pHostent->h_length); if (connect (gOpenScanners[iHandle]->m_udpFd, (struct sockaddr *) &gOpenScanners[iHandle]->m_sockAddr, sizeof (gOpenScanners[iHandle]->m_sockAddr))) { DBG (1, "sane_open: error connecting to %s:%d\n", devicename, gScannerPort); status = SANE_STATUS_IO_ERROR; goto cleanup; } /* set fallback registration name */ sprintf (gOpenScanners[iHandle]->m_regName, "Sane"); /* try to fill in hostname */ gethostname (gOpenScanners[iHandle]->m_regName, REG_NAME_SIZE); /* just in case... */ gOpenScanners[iHandle]->m_regName[REG_NAME_SIZE - 1] = 0; /* chop off any domain (if any) */ if ((pDot = strchr (gOpenScanners[iHandle]->m_regName, '.'))) *pDot = 0; DBG (5, "sane_open: connected to %s:%d as %s\n", devicename, gScannerPort, gOpenScanners[iHandle]->m_regName); /* set the handle */ *handle = (SANE_Handle) (unsigned long)iHandle; return status; cleanup: if (iHandle != -1) FreeScannerState (iHandle); return status; } /* sane_open */ /***********************************************************/ void sane_close (SANE_Handle handle) { DBG( 5, "sane_close: %lx\n", (unsigned long)handle ); FreeScannerState ((unsigned long) handle); } /* sane_close */ /***********************************************************/ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle __sane_unused__ handle, SANE_Int option) { static SANE_Option_Descriptor numOptions = { "num_options", "Number of options", "Number of options", SANE_TYPE_INT, SANE_UNIT_NONE, 1, 0, 0, {0} }; if (option == 0) return &numOptions; else return NULL; } /* sane_get_option_descriptor */ /***********************************************************/ SANE_Status sane_control_option (SANE_Handle __sane_unused__ handle, SANE_Int option, SANE_Action action, void *value, SANE_Int __sane_unused__ * info) { static int numOptions = 1; if (action == SANE_ACTION_GET_VALUE && option == 0) *(int *) value = numOptions; return SANE_STATUS_GOOD; } /* sane_control_option */ /***********************************************************/ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int iHandle = (int) (unsigned long)handle; unsigned int width, height, imageSize; struct PageInfo pageInfo; if (!gOpenScanners[iHandle]) return SANE_STATUS_INVAL; /* fetch page info */ memcpy( & pageInfo, gOpenScanners[iHandle]->m_pageInfo.m_pBuf, sizeof( pageInfo ) ); width = pageInfo.m_width; height = pageInfo.m_height; imageSize = width * height * 3; DBG( 5, "sane_get_parameters: bytes remaining on this page: %d, num pages: %d, size: %dx%d\n", pageInfo.m_bytesRemaining, gOpenScanners[iHandle]->m_numPages, width, height ); DBG (5, "sane_get_parameters: handle %x: bytes outstanding: %lu, image size: %d\n", iHandle, (unsigned long)gOpenScanners[iHandle]->m_imageData.m_used, imageSize); /* check for enough data */ /* if (gOpenScanners[iHandle]->m_imageData.m_used < imageSize) { DBG (1, "sane_get_parameters: handle %d: not enough data: %d < %d\n", iHandle, gOpenScanners[iHandle]->m_imageData.m_used, imageSize); return SANE_STATUS_INVAL; } */ params->format = SANE_FRAME_RGB; params->last_frame = SANE_TRUE; params->lines = height; params->depth = 8; params->pixels_per_line = width; params->bytes_per_line = width * 3; return SANE_STATUS_GOOD; } /* sane_get_parameters */ /***********************************************************/ SANE_Status sane_start (SANE_Handle handle) { SANE_Status status = SANE_STATUS_GOOD; struct ComBuf buf; unsigned char sockBuf[SOCK_BUF_SIZE]; int iHandle, nread; int errorCheck = 0; struct sockaddr_in myAddr; socklen_t addrSize; fd_set readFds; struct timeval selTimeVal; iHandle = (int) (unsigned long)handle; DBG( 5, "sane_start: %x\n", iHandle ); /* fetch and check scanner index */ if (!ValidScannerNumber (iHandle)) return SANE_STATUS_INVAL; /* check if we still have oustanding pages of data on this handle */ if (gOpenScanners[iHandle]->m_imageData.m_used){ /* remove empty page */ PopFromComBuf ( & gOpenScanners[iHandle]->m_pageInfo, sizeof( struct PageInfo ) ); return SANE_STATUS_GOOD; } /* determine local IP address */ addrSize = sizeof (myAddr); if (getsockname (gOpenScanners[iHandle]->m_udpFd, &myAddr, &addrSize)) { DBG (1, "sane_start: Error getting own IP address\n"); return SANE_STATUS_IO_ERROR; } /* init a buffer for our registration message */ errorCheck |= InitComBuf (&buf); /* build packet */ errorCheck |= InitPacket (&buf, 1); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-subscribe-user-name", 0x0b, gOpenScanners[iHandle]->m_regName, strlen (gOpenScanners[iHandle]->m_regName)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-subscribe-ip-address", 0x0a, &myAddr.sin_addr, 4); FinalisePacket (&buf); /* check nothing went wrong along the way */ if (errorCheck) { status = SANE_STATUS_NO_MEM; goto cleanup; } /* send the packet */ send (gOpenScanners[iHandle]->m_udpFd, buf.m_pBuf, buf.m_used, 0); /* loop until done */ gOpenScanners[iHandle]->m_bFinish = 0; while (!gOpenScanners[iHandle]->m_bFinish) { /* prepare select mask */ FD_ZERO (&readFds); FD_SET (gOpenScanners[iHandle]->m_udpFd, &readFds); selTimeVal.tv_sec = 1; selTimeVal.tv_usec = 0; DBG (5, "sane_start: waiting for scan signal\n"); /* wait again if nothing received */ if (!select (gOpenScanners[iHandle]->m_udpFd + 1, &readFds, NULL, NULL, &selTimeVal)) continue; /* read from socket */ nread = read (gOpenScanners[iHandle]->m_udpFd, sockBuf, sizeof (sockBuf)); if (nread <= 0) { DBG (1, "sane_start: read returned %d\n", nread); break; } /* process the response */ if (ProcessUdpResponse (sockBuf, nread, gOpenScanners[iHandle])) { status = SANE_STATUS_IO_ERROR; goto cleanup; } } /* while */ /* check whether we were cancelled */ if ( gOpenScanners[iHandle]->m_bCancelled ) status = SANE_STATUS_CANCELLED; cleanup: FreeComBuf (&buf); return status; } /* sane_start */ /***********************************************************/ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { int iHandle = (int) (unsigned long)handle; int dataSize; struct PageInfo pageInfo; DBG( 5, "sane_read: %x (max_length=%d)\n", iHandle, max_length ); *length = 0; if (!gOpenScanners[iHandle]) return SANE_STATUS_INVAL; /* check for end of data (no further pages) */ if ( ( ! gOpenScanners[iHandle]->m_imageData.m_used ) || ( ! gOpenScanners[iHandle]->m_numPages ) ) { /* remove empty page if there are no more cached pages */ PopFromComBuf ( & gOpenScanners[iHandle]->m_pageInfo, sizeof( struct PageInfo ) ); return SANE_STATUS_EOF; } /* fetch page info */ memcpy( & pageInfo, gOpenScanners[iHandle]->m_pageInfo.m_pBuf, sizeof( pageInfo ) ); /* check for end of page data (we still have further cached pages) */ if ( pageInfo.m_bytesRemaining < 1 ) return SANE_STATUS_EOF; /* send the remainder of the current image */ dataSize = pageInfo.m_bytesRemaining; /* unless there's not enough room in the output buffer */ if (dataSize > max_length) dataSize = max_length; /* update the data sent counters */ gOpenScanners[iHandle]->m_bytesRead += dataSize; pageInfo.m_bytesRemaining -= dataSize; /* update counter */ memcpy( gOpenScanners[iHandle]->m_pageInfo.m_pBuf, & pageInfo, sizeof( pageInfo ) ); /* check for end of page */ if ( pageInfo.m_bytesRemaining < 1 ){ /* yes, so remove page info */ gOpenScanners[iHandle]->m_numPages--; } /* if */ DBG (5, "sane_read: sending %d bytes, image total %d, %d page bytes remaining, %lu total remaining, image: %dx%d\n", dataSize, gOpenScanners[iHandle]->m_bytesRead, pageInfo.m_bytesRemaining , (unsigned long)(gOpenScanners[iHandle]->m_imageData.m_used - dataSize), pageInfo.m_width, pageInfo.m_height); /* copy the data */ memcpy (data, gOpenScanners[iHandle]->m_imageData.m_pBuf, dataSize); if (PopFromComBuf (&gOpenScanners[iHandle]->m_imageData, dataSize)) return SANE_STATUS_NO_MEM; *length = dataSize; return SANE_STATUS_GOOD; } /* sane_read */ /***********************************************************/ void sane_cancel (SANE_Handle handle) { int iHandle = (int) (unsigned long)handle; DBG( 5, "sane_cancel: %x\n", iHandle ); /* signal that bad things are afoot */ gOpenScanners[iHandle]->m_bFinish = 1; gOpenScanners[iHandle]->m_bCancelled = 1; } /* sane_cancel */ /***********************************************************/ SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { return SANE_STATUS_UNSUPPORTED; } /* sane_set_io_mode */ /***********************************************************/ SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { return SANE_STATUS_UNSUPPORTED; } /* sane_get_select_fd */ /***********************************************************/ /* Clears the contents of gKnownDevices and zeros it */ void ClearKnownDevices () { int i; for (i = 0; i < MAX_SCANNERS; ++i) { if (gKnownDevices[i]) { if (gKnownDevices[i]->m_pName) free ( gKnownDevices[i]->m_pName ); if (gKnownDevices[i]->m_pModel) free ( gKnownDevices[i]->m_pModel ); free ( gKnownDevices[i] ); } gKnownDevices[i] = NULL; } } /* ClearKnownDevices */ /***********************************************************/ /* print hex buffer to debug output */ void HexDump (int debugLevel, const unsigned char *buf, size_t bufSize) { unsigned int i, j; size_t lineBufFree; char itemBuf[16] = { 0 }, lineBuf[256] = { 0 }; if (DBG_LEVEL < debugLevel) return; for (i = 0; i < bufSize; ++i) { if (!(i % 16)) sprintf (lineBuf, "%p: ", (buf + i)); sprintf (itemBuf, "%02x ", (const unsigned int) buf[i]); lineBufFree = sizeof (lineBuf) - strlen (lineBuf) - 1; strncat (lineBuf, itemBuf, lineBufFree); if ((i + 1) % 16) continue; /* print string equivalent */ for (j = i - 15; j <= i; ++j) { if ((buf[j] >= 0x20) && (!(buf[j] & 0x80))) { sprintf (itemBuf, "%c", buf[j]); } else { sprintf (itemBuf, "."); } lineBufFree = sizeof (lineBuf) - strlen (lineBuf) - 1; strncat (lineBuf, itemBuf, lineBufFree); } /* for j */ DBG (debugLevel, "%s\n", lineBuf); lineBuf[0] = 0; } /* for i */ if (i % 16) { for (j = (i % 16); j < 16; ++j) { lineBufFree = sizeof (lineBuf) - strlen (lineBuf) - 1; strncat (lineBuf, " ", lineBufFree); } for (j = 1 + i - ((i + 1) % 16); j < i; ++j) { if ((buf[j] >= 0x20) && (!(buf[j] & 0x80))) { sprintf (itemBuf, "%c", buf[j]); } else { strcpy (itemBuf, "."); } lineBufFree = sizeof (lineBuf) - strlen (lineBuf) - 1; strncat (lineBuf, itemBuf, lineBufFree); } DBG (debugLevel, "%s\n", lineBuf); } } /* HexDump */ /***********************************************************/ /* initialise a ComBuf struct \return 0 on success, >0 on failure */ int InitComBuf (struct ComBuf *pBuf) { memset (pBuf, 0, sizeof (struct ComBuf)); pBuf->m_pBuf = malloc (INITIAL_COM_BUF_SIZE); if (!pBuf->m_pBuf) return 1; pBuf->m_capacity = INITIAL_COM_BUF_SIZE; pBuf->m_used = 0; return 0; } /* InitComBuf */ /***********************************************************/ /* free a ComBuf struct */ void FreeComBuf (struct ComBuf *pBuf) { if (pBuf->m_pBuf) free (pBuf->m_pBuf); memset (pBuf, 0, sizeof (struct ComBuf)); } /* FreeComBuf */ /***********************************************************/ /* add data to a ComBuf struct \return 0 on success, >0 on failure \note If pData is NULL then buffer size will be increased but no copying will take place \note In case of failure pBuf will be released using FreeComBuf */ int AppendToComBuf (struct ComBuf *pBuf, const unsigned char *pData, size_t datSize) { size_t newSize; /* check we have enough space */ if (pBuf->m_used + datSize > pBuf->m_capacity) { /* nope - allocate some more */ newSize = pBuf->m_used + datSize + INITIAL_COM_BUF_SIZE; pBuf->m_pBuf = realloc (pBuf->m_pBuf, newSize); if (!pBuf->m_pBuf) { DBG (1, "AppendToComBuf: memory allocation error"); FreeComBuf (pBuf); return (1); } pBuf->m_capacity = newSize; } /* if */ /* add data */ if (pData) memcpy (pBuf->m_pBuf + pBuf->m_used, pData, datSize); pBuf->m_used += datSize; return 0; } /* AppendToComBuf */ /***********************************************************/ /* append message to a packet \return 0 if ok, 1 if bad */ int AppendMessageToPacket (struct ComBuf *pBuf, /* packet to which to append */ char messageType, /* type of message */ char *messageName, /* name of message */ char valueType, /* type of value */ void *pValue, /* pointer to value */ size_t valueLen /* length of value (bytes) */ ) { unsigned short slen; /* message type */ AppendToComBuf (pBuf, (void *) &messageType, 1); /* message length */ slen = htons (strlen (messageName)); AppendToComBuf (pBuf, (void *) &slen, 2); /* and name */ AppendToComBuf (pBuf, (void *) messageName, strlen (messageName)); /* and value type */ AppendToComBuf (pBuf, (void *) &valueType, 1); /* value length */ slen = htons (valueLen); AppendToComBuf (pBuf, (void *) &slen, 2); /* and value */ return (AppendToComBuf (pBuf, (void *) pValue, valueLen)); } /* AppendMessageToPacket */ /***********************************************************/ /* Initialise a packet \param pBuf : An initialise ComBuf \param type : either 0x01 ("normal" ) or 0x02 ("reply" ) \return 0 on success, >0 otherwise */ int InitPacket (struct ComBuf *pBuf, char type) { char header[8] = { 2, 0, 0, 2, 0, 0, 0, 0 }; header[2] = type; /* reset size */ pBuf->m_used = 0; /* add header */ return (AppendToComBuf (pBuf, (void *) &header, 8)); } /* InitPacket */ /***********************************************************/ /* write length data to packet header */ void FinalisePacket (struct ComBuf *pBuf) { /* sanity check */ if (pBuf->m_used < 8) return; /* set the size */ *((unsigned short *) (pBuf->m_pBuf + 6)) = htons (pBuf->m_used - 8); DBG (20, "FinalisePacket: outgoing packet:\n"); HexDump (20, pBuf->m_pBuf, pBuf->m_used); } /* FinalisePacket */ /***********************************************************/ /* \return 1 if message is complete, 0 otherwise */ int MessageIsComplete (unsigned char *pData, size_t size) { unsigned short dataSize; /* sanity check */ if (size < 8) return 0; /* :NOTE: we can't just cast to a short as data may not be aligned */ dataSize = (((unsigned short) pData[6]) << 8) | pData[7]; DBG (20, "MessageIsComplete: data size = %d\n", dataSize); if (size >= (size_t) (dataSize + 8)) return 1; else return 0; } /* MessageIsComplete */ /***********************************************************/ /* process a registration broadcast response \return struct DeviceRecord pointer on success (caller frees), NULL on failure */ struct DeviceRecord * ProcessFindResponse (unsigned char *pData, size_t size) { struct DeviceRecord *pDevice = NULL; unsigned short messageSize, nameSize, valueSize; unsigned char *pItem, *pEnd, *pValue; char printerName[256] = { 0 }; char printerModel[256] = "1600n"; char *pModel, *pName; DBG (10, "ProcessFindResponse: processing %lu bytes, pData=%p\n", (unsigned long)size, pData); /* check we have a complete packet */ if (!MessageIsComplete (pData, size)) { DBG (1, "ProcessFindResponse: Ignoring incomplete packet\n"); return NULL; } /* extract data size */ messageSize = (((unsigned short) (pData[6])) << 8) | pData[7]; /* loop through items in message */ pItem = pData + 8; pEnd = pItem + messageSize; while (pItem < pEnd) { pItem++; nameSize = (((unsigned short) pItem[0]) << 8) | pItem[1]; pItem += 2; pName = (char *) pItem; pItem += nameSize; pItem++; valueSize = (((unsigned short) pItem[0]) << 8) | pItem[1]; pItem += 2; pValue = pItem; pItem += valueSize; /* process the item */ if (!strncmp ("std-scan-discovery-ip", pName, nameSize)) { snprintf (printerName, sizeof (printerName), "%d.%d.%d.%d", (int) pValue[0], (int) pValue[1], (int) pValue[2], (int) pValue[3]); DBG (2, "%s\n", printerName); } else if (!strncmp ("std-scan-discovery-model-name", pName, nameSize)) { memset (printerModel, 0, sizeof (printerModel)); if (valueSize > (sizeof (printerModel) - 1)) valueSize = sizeof (printerModel) - 1; memcpy (printerModel, pValue, valueSize); DBG (2, "std-scan-discovery-model-name: %s\n", printerModel); } } /* while pItem */ /* just in case nothing sensible was found */ if ( ! strlen( printerName ) ) return NULL; pDevice = malloc (sizeof (struct DeviceRecord)); if (!pDevice) { DBG (1, "ProcessFindResponse: memory allocation failure\n"); return NULL; } /* knock off "Dell " from start of model name */ pModel = printerModel; if ( ! strncmp( pModel, "Dell ", 5 ) ) pModel += 5; pDevice->m_pName = strdup( printerName ); pDevice->m_device.vendor = "Dell"; pDevice->m_pModel = strdup (pModel); pDevice->m_device.type = "multi-function peripheral"; pDevice->m_device.name = pDevice->m_pName; pDevice->m_device.model = pDevice->m_pModel; return pDevice; } /* ProcessFindResponse */ /***********************************************************/ /* frees a scanner state struct stored in gOpenScanners */ void FreeScannerState (int iHandle) { /* check range etc */ if (!ValidScannerNumber (iHandle)) return; /* close UDP handle */ if (gOpenScanners[iHandle]->m_udpFd) close (gOpenScanners[iHandle]->m_udpFd); /* free m_buf */ FreeComBuf (&gOpenScanners[iHandle]->m_buf); /* free m_imageData */ FreeComBuf (&gOpenScanners[iHandle]->m_imageData); /* free the struct */ free (gOpenScanners[iHandle]); /* set pointer to NULL */ gOpenScanners[iHandle] = NULL; } /* FreeScannerState */ /***********************************************************/ /* \return 1 if iHandle is a valid member of gOpenScanners, 0 otherwise */ int ValidScannerNumber (int iHandle) { /* check range */ if ((iHandle < 0) || (iHandle >= MAX_SCANNERS)) { DBG (1, "ValidScannerNumber: invalid scanner index %d", iHandle); return 0; } /* check non-NULL pointer */ if (!gOpenScanners[iHandle]) { DBG (1, "ValidScannerNumber: NULL scanner struct %d", iHandle); return 0; } /* OK */ return 1; } /* ValidScannerNumber */ /***********************************************************/ /* process UDP responses \return 0 in success, >0 otherwise */ static int ProcessUdpResponse (unsigned char *pData, size_t size, struct ScannerState *pState) { unsigned short messageSize, nameSize, valueSize; unsigned char *pItem, *pEnd; char sockBuf[SOCK_BUF_SIZE], *pName; struct ComBuf tcpBuf; int nread; unsigned int numUsed; HexDump (15, pData, size); DBG (10, "ProcessUdpResponse: processing %lu bytes, pData=%p\n", (unsigned long)size, pData); /* check we have a complete packet */ if (!MessageIsComplete (pData, size)) { DBG (1, "ProcessUdpResponse: Ignoring incomplete packet\n"); return 1; } /* init a com buf for use in tcp communication */ InitComBuf (&tcpBuf); /* extract data size */ messageSize = (((unsigned short) (pData[6])) << 8) | pData[7]; /* loop through items in message */ pItem = pData + 8; pEnd = pItem + messageSize; while (pItem < pEnd) { pItem++; nameSize = (((unsigned short) pItem[0]) << 8) | pItem[1]; pItem += 2; pName = (char *) pItem; pItem += nameSize; pItem++; valueSize = (((unsigned short) pItem[0]) << 8) | pItem[1]; pItem += 2; pItem += valueSize; /* process the item */ if (!strncmp ("std-scan-request-tcp-connection", pName, nameSize)) { /* open TCP socket to scanner */ if (!(pState->m_tcpFd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP))) { DBG (1, "ProcessUdpResponse: error opening TCP socket\n"); return 2; } if (connect (pState->m_tcpFd, (struct sockaddr *) &pState->m_sockAddr, sizeof (pState->m_sockAddr))) { DBG (1, "ProcessUdpResponse: error connecting to scanner TCP port\n"); goto cleanup; } DBG (1, "ProcessUdpResponse: opened TCP connection to scanner\n"); /* clear read buf */ tcpBuf.m_used = 0; /* TCP read loop */ while (1) { nread = read (pState->m_tcpFd, sockBuf, sizeof (sockBuf)); if (nread <= 0) { DBG (1, "ProcessUdpResponse: TCP read returned %d\n", nread); break; } /* append message to buffer */ if (AppendToComBuf (&tcpBuf, (unsigned char *) sockBuf, nread)) goto cleanup; /* process all available responses */ while (tcpBuf.m_used) { /* note the buffer size before the call */ numUsed = tcpBuf.m_used; /* process the response */ if (ProcessTcpResponse (pState, &tcpBuf)) goto cleanup; /* if the buffer size has not changed then assume no more processing is possible */ if (numUsed == tcpBuf.m_used) break; } /* while */ } /* while */ close (pState->m_tcpFd); DBG (1, "ProcessUdpResponse: closed TCP connection to scanner\n"); /* signal end of session */ pState->m_bFinish = 1; } /* if */ } /* while pItem */ return 0; cleanup: FreeComBuf (&tcpBuf); close (pState->m_tcpFd); return 3; } /* ProcessUdpResponse */ /***********************************************************/ /* process TCP responses, \return 0 in success, >0 otherwise */ int ProcessTcpResponse (struct ScannerState *pState, struct ComBuf *pTcpBuf) { struct ComBuf buf; unsigned short messageSize = 0, nameSize, valueSize, dataChunkSize; unsigned char *pItem, *pEnd, *pValue; unsigned char *pData = pTcpBuf->m_pBuf; char *pName; unsigned int uiVal; int errorCheck = 0; int bProcessImage = 0; DBG (10, "ProcessTcpResponse: processing %lu bytes, pData=%p\n", (unsigned long)pTcpBuf->m_used, pData); HexDump (15, pData, pTcpBuf->m_used); /* if message not complete then wait for more to arrive */ if (!MessageIsComplete (pData, pTcpBuf->m_used)) { DBG (10, "ProcessTcpResponse: incomplete message, returning\n"); return 0; } /* init a buffer for our outbound messages */ if (InitComBuf (&buf)) { errorCheck |= 1; goto cleanup; } /* extract data size */ messageSize = (((unsigned short) (pData[6])) << 8) | pData[7]; /* loop through items in message */ pItem = pData + 8; pEnd = pItem + messageSize; while (pItem < pEnd) { pItem++; nameSize = (((unsigned short) pItem[0]) << 8) | pItem[1]; pItem += 2; pName = (char *) pItem; pItem += nameSize; pItem++; valueSize = (((unsigned short) pItem[0]) << 8) | pItem[1]; pItem += 2; pValue = pItem; pItem += valueSize; /* process the item */ if (!strncmp ("std-scan-session-open", pName, nameSize)) { errorCheck |= InitPacket (&buf, 0x02); uiVal = 0; errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-session-open-response", 0x05, &uiVal, sizeof (uiVal)); FinalisePacket (&buf); send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0); } else if (!strncmp ("std-scan-getclientpref", pName, nameSize)) { errorCheck |= InitPacket (&buf, 0x02); uiVal = 0; errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-x1", 0x05, &uiVal, sizeof (uiVal)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-x2", 0x05, &uiVal, sizeof (uiVal)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-y1", 0x05, &uiVal, sizeof (uiVal)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-y2", 0x05, &uiVal, sizeof (uiVal)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-xresolution", 0x04, &pState->m_xres, sizeof (pState->m_xres)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-yresolution", 0x04, &pState->m_yres, sizeof (pState->m_yres)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-image-composition", 0x06, &pState->m_composition, sizeof (pState->m_composition)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-brightness", 0x02, &pState->m_brightness, sizeof (pState->m_brightness)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-image-compression", 0x06, &pState->m_compression, sizeof (pState->m_compression)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-file-type", 0x06, &pState->m_fileType, sizeof (pState->m_fileType)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-paper-size-detect", 0x06, &uiVal, sizeof (uiVal)); errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-getclientpref-paper-scanner-type", 0x06, &uiVal, sizeof (uiVal)); FinalisePacket (&buf); send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0); } else if (!strncmp ("std-scan-document-start", pName, nameSize)) { errorCheck |= InitPacket (&buf, 0x02); uiVal = 0; errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-document-start-response", 0x05, &uiVal, sizeof (uiVal)); FinalisePacket (&buf); send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0); } else if (!strncmp ("std-scan-document-file-type", pName, nameSize)) { memcpy (&pState->m_fileType, pValue, sizeof (pState->m_fileType)); DBG (5, "File type: %x\n", ntohl (pState->m_fileType)); } else if (!strncmp ("std-scan-document-image-compression", pName, nameSize)) { memcpy (&pState->m_compression, pValue, sizeof (pState->m_compression)); DBG (5, "Compression: %x\n", ntohl (pState->m_compression)); } else if (!strncmp ("std-scan-document-xresolution", pName, nameSize)) { memcpy (&pState->m_xres, pValue, sizeof (pState->m_xres)); DBG (5, "X resolution: %d\n", ntohs (pState->m_xres)); } else if (!strncmp ("std-scan-document-yresolution", pName, nameSize)) { memcpy (&pState->m_yres, pValue, sizeof (pState->m_yres)); DBG (5, "Y resolution: %d\n", ntohs (pState->m_yres)); } else if (!strncmp ("std-scan-page-widthpixel", pName, nameSize)) { if (1 || !pState->m_pixelWidth) { memcpy (&pState->m_pixelWidth, pValue, sizeof (pState->m_pixelWidth)); DBG (5, "Width: %d\n", ntohl (pState->m_pixelWidth)); } else { DBG (5, "Ignoring width (already have a value)\n"); } } else if (!strncmp ("std-scan-page-heightpixel", pName, nameSize)) { if (1 || !pState->m_pixelHeight) { memcpy (&pState->m_pixelHeight, pValue, sizeof (pState->m_pixelHeight)); DBG (5, "Height: %d\n", ntohl (pState->m_pixelHeight)); } else { DBG (5, "Ignoring height (already have a value)\n"); } } else if (!strncmp ("std-scan-page-start", pName, nameSize)) { errorCheck |= InitPacket (&buf, 0x02); uiVal = 0; errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-page-start-response", 0x05, &uiVal, sizeof (uiVal)); FinalisePacket (&buf); send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0); /* reset the data buffer ready to store a new page */ pState->m_buf.m_used = 0; /* init current page size */ pState->m_currentPageBytes = 0; pState->m_pixelWidth = 0; pState->m_pixelHeight = 0; } else if (!strncmp ("std-scan-page-end", pName, nameSize)) { bProcessImage = 1; errorCheck |= InitPacket (&buf, 0x02); uiVal = 0; errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-page-end-response", 0x05, &uiVal, sizeof (uiVal)); FinalisePacket (&buf); send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0); } else if (!strncmp ("std-scan-document-end", pName, nameSize)) { errorCheck |= InitPacket (&buf, 0x02); uiVal = 0; errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-document-end-response", 0x05, &uiVal, sizeof (uiVal)); FinalisePacket (&buf); send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0); /* reset the data buffer ready to store a new page */ pState->m_buf.m_used = 0; } else if (!strncmp ("std-scan-session-end", pName, nameSize)) { errorCheck |= InitPacket (&buf, 0x02); uiVal = 0; errorCheck |= AppendMessageToPacket (&buf, 0x22, "std-scan-session-end-response", 0x05, &uiVal, sizeof (uiVal)); FinalisePacket (&buf); send (pState->m_tcpFd, buf.m_pBuf, buf.m_used, 0); /* initialise a shutodwn of the socket */ shutdown (pState->m_tcpFd, SHUT_RDWR); } else if (!strncmp ("std-scan-scandata-error", pName, nameSize)) { /* determine the size of data in this chunk */ dataChunkSize = (pItem[6] << 8) + pItem[7]; pItem += 8; DBG (10, "Reading %d bytes of scan data\n", dataChunkSize); /* append message to buffer */ errorCheck |= AppendToComBuf (&pState->m_buf, pItem, dataChunkSize); pItem += dataChunkSize; DBG (10, "Accumulated %lu bytes of scan data so far\n", (unsigned long)pState->m_buf.m_used); } /* if */ } /* while */ /* process page data if required */ if ( bProcessImage ) errorCheck |= ProcessPageData (pState); cleanup: /* remove processed data (including 8 byte header) from start of tcp buffer */ PopFromComBuf (pTcpBuf, messageSize + 8); /* free com buf */ FreeComBuf (&buf); return errorCheck; } /* ProcessTcpResponse */ /***********************************************************/ /* remove data from the front of a ComBuf struct \return 0 if sucessful, >0 otherwise */ int PopFromComBuf (struct ComBuf *pBuf, size_t datSize) { /* check if we're trying to remove more data than is present */ if (datSize > pBuf->m_used) { pBuf->m_used = 0; return 1; } /* check easy cases */ if ((!datSize) || (datSize == pBuf->m_used)) { pBuf->m_used -= datSize; return 0; } /* move remaining memory contents to start */ memmove (pBuf->m_pBuf, pBuf->m_pBuf + datSize, pBuf->m_used - datSize); pBuf->m_used -= datSize; return 0; } /* PopFromComBuf */ /***********************************************************/ /* Process the data from a single scanned page, \return 0 in success, >0 otherwise */ int ProcessPageData (struct ScannerState *pState) { FILE *fTmp; int fdTmp; struct jpeg_source_mgr jpegSrcMgr; struct JpegDataDecompState jpegCinfo; struct jpeg_error_mgr jpegErr; int numPixels, iPixel, width, height, scanLineSize, imageBytes; int ret = 0; struct PageInfo pageInfo; JSAMPLE *pJpegLine = NULL; uint32 *pTiffRgba = NULL; unsigned char *pOut; char tiffErrBuf[1024]; TIFF *pTiff = NULL; /* If there's no data then there's nothing to write */ if (!pState->m_buf.m_used) return 0; DBG (1, "ProcessPageData: Got compression %x\n", ntohl (pState->m_compression)); switch (ntohl (pState->m_compression)) { case 0x20: /* decode as JPEG if appropriate */ { jpegSrcMgr.resync_to_restart = jpeg_resync_to_restart; jpegSrcMgr.init_source = JpegDecompInitSource; jpegSrcMgr.fill_input_buffer = JpegDecompFillInputBuffer; jpegSrcMgr.skip_input_data = JpegDecompSkipInputData; jpegSrcMgr.term_source = JpegDecompTermSource; jpegCinfo.m_cinfo.err = jpeg_std_error (&jpegErr); jpeg_create_decompress (&jpegCinfo.m_cinfo); jpegCinfo.m_cinfo.src = &jpegSrcMgr; jpegCinfo.m_bytesRemaining = pState->m_buf.m_used; jpegCinfo.m_pData = pState->m_buf.m_pBuf; jpeg_read_header (&jpegCinfo.m_cinfo, TRUE); jpeg_start_decompress (&jpegCinfo.m_cinfo); /* allocate space for a single scanline */ scanLineSize = jpegCinfo.m_cinfo.output_width * jpegCinfo.m_cinfo.output_components; DBG (1, "ProcessPageData: image dimensions: %d x %d, line size: %d\n", jpegCinfo.m_cinfo.output_width, jpegCinfo.m_cinfo.output_height, scanLineSize); pJpegLine = calloc (scanLineSize, sizeof (JSAMPLE)); if (!pJpegLine) { DBG (1, "ProcessPageData: memory allocation error\n"); ret = 1; goto JPEG_CLEANUP; } /* if */ /* note dimensions - may be different from those previously reported */ pState->m_pixelWidth = htonl (jpegCinfo.m_cinfo.output_width); pState->m_pixelHeight = htonl (jpegCinfo.m_cinfo.output_height); /* decode scanlines */ while (jpegCinfo.m_cinfo.output_scanline < jpegCinfo.m_cinfo.output_height) { DBG (20, "Reading scanline %d of %d\n", jpegCinfo.m_cinfo.output_scanline, jpegCinfo.m_cinfo.output_height); /* read scanline */ jpeg_read_scanlines (&jpegCinfo.m_cinfo, &pJpegLine, 1); /* append to output buffer */ ret |= AppendToComBuf (&pState->m_imageData, pJpegLine, scanLineSize); } /* while */ /* update info for this page */ pageInfo.m_width = jpegCinfo.m_cinfo.output_width; pageInfo.m_height = jpegCinfo.m_cinfo.output_height; pageInfo.m_totalSize = pageInfo.m_width * pageInfo.m_height * 3; pageInfo.m_bytesRemaining = pageInfo.m_totalSize; DBG( 1, "Process page data: page %d: JPEG image: %d x %d, %d bytes\n", pState->m_numPages, pageInfo.m_width, pageInfo.m_height, pageInfo.m_totalSize ); ret |= AppendToComBuf( & pState->m_pageInfo, (unsigned char*)& pageInfo, sizeof( pageInfo ) ); ++( pState->m_numPages ); JPEG_CLEANUP: jpeg_finish_decompress (&jpegCinfo.m_cinfo); jpeg_destroy_decompress (&jpegCinfo.m_cinfo); if (pJpegLine) free (pJpegLine); return ret; } /* case JPEG */ case 0x08: /* CCITT Group 4 Fax data */ { /* get a temp file :TODO: 2006-04-18: Use TIFFClientOpen and do everything in RAM */ fTmp = tmpfile (); fdTmp = fileno (fTmp); pTiff = TIFFFdOpen (fdTmp, "tempfile", "w"); if (!pTiff) { DBG (1, "ProcessPageData: Error opening temp TIFF file"); ret = SANE_STATUS_IO_ERROR; goto TIFF_CLEANUP; } /* create a TIFF file */ width = ntohl (pState->m_pixelWidth); height = ntohl (pState->m_pixelHeight); TIFFSetField (pTiff, TIFFTAG_IMAGEWIDTH, width); TIFFSetField (pTiff, TIFFTAG_IMAGELENGTH, height); TIFFSetField (pTiff, TIFFTAG_BITSPERSAMPLE, 1); TIFFSetField (pTiff, TIFFTAG_PHOTOMETRIC, 0); /* 0 is white */ TIFFSetField (pTiff, TIFFTAG_COMPRESSION, 4); /* CCITT Group 4 */ TIFFSetField (pTiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFWriteRawStrip (pTiff, 0, pState->m_buf.m_pBuf, pState->m_buf.m_used); if (0 > TIFFRGBAImageOK (pTiff, tiffErrBuf)) { DBG (1, "ProcessPageData: %s\n", tiffErrBuf); ret = SANE_STATUS_IO_ERROR; goto TIFF_CLEANUP; } /* allocate space for RGBA representation of image */ numPixels = height * width; DBG (20, "ProcessPageData: num TIFF RGBA pixels: %d\n", numPixels); if (!(pTiffRgba = calloc (numPixels, sizeof (u_long)))) { ret = SANE_STATUS_NO_MEM; goto TIFF_CLEANUP; } /* make space in image buffer to store the results */ imageBytes = width * height * 3; ret |= AppendToComBuf (&pState->m_imageData, NULL, imageBytes); if (ret) goto TIFF_CLEANUP; /* get a pointer to the start of the output data */ pOut = pState->m_imageData.m_pBuf + pState->m_imageData.m_used - imageBytes; /* read RGBA image */ DBG (20, "ProcessPageData: setting up read buffer\n"); TIFFReadBufferSetup (pTiff, NULL, width * height * sizeof (u_long)); DBG (20, "ProcessPageData: reading RGBA data\n"); TIFFReadRGBAImageOriented (pTiff, width, height, pTiffRgba, ORIENTATION_TOPLEFT, 0); /* loop over pixels */ for (iPixel = 0; iPixel < numPixels; ++iPixel) { *(pOut++) = TIFFGetR (pTiffRgba[iPixel]); *(pOut++) = TIFFGetG (pTiffRgba[iPixel]); *(pOut++) = TIFFGetB (pTiffRgba[iPixel]); } /* for iRow */ /* update info for this page */ pageInfo.m_width = width; pageInfo.m_height = height; pageInfo.m_totalSize = pageInfo.m_width * pageInfo.m_height * 3; pageInfo.m_bytesRemaining = pageInfo.m_totalSize; DBG( 1, "Process page data: page %d: TIFF image: %d x %d, %d bytes\n", pState->m_numPages, width, height, pageInfo.m_totalSize ); ret |= AppendToComBuf( & pState->m_pageInfo, (unsigned char*)& pageInfo, sizeof( pageInfo ) ); ++( pState->m_numPages ); TIFF_CLEANUP: if (pTiff) TIFFClose (pTiff); if (fTmp) fclose (fTmp); if (pTiffRgba) free (pTiffRgba); return ret; } /* case CCITT */ default: /* this is not expected or very useful */ { DBG (1, "ProcessPageData: Unexpected compression flag %d\n", ntohl (pState->m_compression)); ret = SANE_STATUS_IO_ERROR; } } /* switch */ return ret; } /* ProcessPageData */ /***********************************************************/ void JpegDecompInitSource (j_decompress_ptr cinfo) /* Libjpeg decompression interface */ { cinfo->src->bytes_in_buffer = 0; } /* JpegDecompInitSource */ /***********************************************************/ boolean JpegDecompFillInputBuffer (j_decompress_ptr cinfo) /* Libjpeg decompression interface */ { struct JpegDataDecompState *pState = (struct JpegDataDecompState *) cinfo; static const unsigned char eoiByte[] = { 0xFF, JPEG_EOI }; DBG (10, "JpegDecompFillInputBuffer: bytes remaining: %d\n", pState->m_bytesRemaining); if (!pState->m_bytesRemaining) { /* no input data available so return dummy data */ cinfo->src->bytes_in_buffer = 2; cinfo->src->next_input_byte = (const JOCTET *) eoiByte; } else { /* point to data */ cinfo->src->bytes_in_buffer = pState->m_bytesRemaining; cinfo->src->next_input_byte = (const JOCTET *) pState->m_pData; /* note that data is now gone */ pState->m_bytesRemaining = 0; } /* if */ return TRUE; } /* JpegDecompFillInputBuffer */ /***********************************************************/ void JpegDecompSkipInputData (j_decompress_ptr cinfo, long numBytes) /* Libjpeg decompression interface */ { DBG (10, "JpegDecompSkipInputData: skipping %ld bytes\n", numBytes); cinfo->src->bytes_in_buffer -= numBytes; cinfo->src->next_input_byte += numBytes; } /* JpegDecompSkipInputData */ /***********************************************************/ void JpegDecompTermSource (j_decompress_ptr __sane_unused__ cinfo) /* Libjpeg decompression interface */ { /* nothing to do */ } /* JpegDecompTermSource */ /***********************************************************/ sane-backends-1.0.27/backend/canon_pp.c0000664000175000017500000014777312112021330014556 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2002 Matthew C. Duggan and Simon Krix This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. ----- canon_pp.c: $Revision$ This file is part of the canon_pp backend, supporting Canon FBX30P and NX40P scanners */ #ifdef _AIX #include /* MUST come first for AIX! */ #endif #define BACKEND_NAME canon_pp #define THREE_BITS 0xE0 #define TWO_BITS 0xC0 #define MM_PER_IN 25.4 #ifndef NOSANE #include "../include/sane/config.h" #endif #ifndef VERSION #define VERSION "$Revision$" #endif #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "canon_pp-dev.h" #include "canon_pp-io.h" #include "canon_pp.h" /* #include "../include/sane/sanei_pio.h" */ #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" /* #include "../include/sane/sanei_debug.h" */ /* Prototypes */ static SANE_Status init_device(struct parport *pp); /* create a calibration file and give it initial values */ static int init_cal(char *file); static SANE_Status fix_weights_file(CANONP_Scanner *cs); static SANE_Status detect_mode(CANONP_Scanner *cs); /* Global Variables (ack!) */ /* The first device in a linked list of devices */ static CANONP_Scanner *first_dev = NULL; /* The default scanner to open */ static char *def_scanner = NULL; /* The number of devices */ static int num_devices = 0; /* ieee1284 parallel ports */ struct parport_list pl; /* leftover from the last read */ static SANE_Byte *read_leftover = NULL; /* leftover from the last read */ static SANE_Bool force_nibble = SANE_FALSE; /* Constants */ /* Colour Modes */ static const SANE_String_Const cmodes[] = { SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; /* bit depths */ static const SANE_String_Const depths[] = { "8", "12", NULL }; /* resolutions */ static const SANE_Int res300[] = {3, 75, 150, 300}; static const SANE_Int res600[] = {4, 75, 150, 300, 600}; /************************************************************************* * * sane_init() * * Initialises data for the list of scanners, stored in canon-p.conf. * * Scanners are not sent any commands until sane_open() is called. * *************************************************************************/ SANE_Status sane_init (SANE_Int *vc, SANE_Auth_Callback cb) { SANE_Status status = SANE_STATUS_GOOD; int i, tmp; int tmp_im = INITMODE_AUTO; FILE *fp; char line[81]; /* plus 1 for a null */ char *tmp_wf, *tmp_port; CANONP_Scanner *s_tmp; DBG_INIT(); #if defined PACKAGE && defined VERSION DBG(2, ">> sane_init (version %s null, authorize %s null): " PACKAGE " " VERSION "\n", (vc) ? "!=" : "==", (cb) ? "!=" : "=="); #endif if(vc) *vc = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); DBG(2,"sane_init: >> ieee1284_find_ports\n"); /* Find lp ports */ tmp = ieee1284_find_ports(&pl, 0); DBG(2,"sane_init: %d << ieee1284_find_ports\n", tmp); if (tmp != E1284_OK) { DBG(1,"sane_init: Error trying to get port list\n"); return SANE_STATUS_IO_ERROR; } if (pl.portc < 1) { DBG(1,"sane_init: Error, no parallel ports found.\n"); return SANE_STATUS_IO_ERROR; } DBG(10,"sane_init: %i parallel port(s) found.\n", pl.portc); /* Setup data structures for each port */ for(i=0; iname); status = init_device(pl.portv[i]); /* Now's a good time to quit if we got an error */ if (status != SANE_STATUS_GOOD) return status; } /* This should never be true here */ if (num_devices == 0) status = SANE_STATUS_IO_ERROR; /* just to be extra sure, the line will always have an end: */ line[sizeof(line)-1] = '\0'; /* * Read information from config file: pixel weight location and default * port. */ if((fp = sanei_config_open(CANONP_CONFIG_FILE))) { while(sanei_config_read(line, sizeof (line) - 1, fp)) { DBG(100, "sane_init: >%s<\n", line); if(line[0] == '#') /* ignore line comments */ continue; if(!strlen(line)) continue; /* ignore empty lines */ if(strncmp(line,"calibrate ", 10) == 0) { /* warning: pointer trickyness ahead * Do not free tmp_port! */ DBG(40, "sane_init: calibrate line, %s\n", line); tmp_wf = strdup(line+10); tmp_port = strstr(tmp_wf, " "); if ((tmp_port == tmp_wf) || (tmp_port == NULL)) { /* They have used an old style config * file which does not specify scanner * Assume first port */ DBG(1, "sane_init: old config line:" "\"%s\". Please add " "a port argument.\n", line); /* first_dev should never be null here * because we found at least one * parallel port above */ first_dev->weights_file = tmp_wf; DBG(100, "sane_init: Successfully " "parsed (old) cal, " "weight file is " "'%s'.\n", tmp_wf); continue; } /* Now find which scanner wants * this calibration file */ s_tmp = first_dev; DBG(100, "sane_init: Finding scanner on port " "'%s'\n", tmp_port+1); while (s_tmp != NULL) { if (!strcmp(s_tmp->params.port->name, tmp_port+1)) { DBG(100, "sane_init: Found!\n"); /* Now terminate the weight * file string */ *tmp_port = '\0'; s_tmp->weights_file = tmp_wf; DBG(100, "sane_init: Parsed " "cal, for port" " '%s', weight" " file is '%s'" ".\n", s_tmp->params. port->name, tmp_wf); break; } s_tmp = s_tmp->next; } if (s_tmp == NULL) { /* we made it all the way through the * list and didn't find the port */ free(tmp_wf); DBG(10, "sane_init: calibrate line is " "for unknown port!\n"); } continue; } if(strncmp(line,"ieee1284 ", 9) == 0) { DBG(100, "sane_init: Successfully parsed " "default scanner.\n"); /* this will be our default scanner */ def_scanner = strdup(line+9); continue; } if(strncmp(line,"force_nibble", 12) == 0) { DBG(100, "sane_init: force_nibble " "requested.\n"); force_nibble = SANE_TRUE; continue; } if(strncmp(line,"init_mode ", 10) == 0) { /* parse what sort of initialisation mode to * use */ if (strncmp(line+10, "FB620P", 6) == 0) tmp_im = INITMODE_20P; else if (strncmp(line+10, "FB630P", 6) == 0) tmp_im = INITMODE_30P; else if (strncmp(line+10, "AUTO", 4) == 0) tmp_im = INITMODE_AUTO; /* now work out which port it blongs to */ tmp_port = strstr(line+10, " "); if (tmp_port == NULL) { /* first_dev should never be null here * because we found at least one * parallel port above */ first_dev->init_mode = tmp_im; DBG(100, "sane_init: Parsed init-1.\n"); continue; } s_tmp = first_dev; while (s_tmp != NULL) { if (!strcmp(s_tmp->params.port->name, tmp_port+1)) { s_tmp->init_mode = tmp_im; DBG(100, "sane_init: Parsed " "init.\n"); break; } s_tmp = s_tmp->next; } if (s_tmp == NULL) { /* we made it all the way through the * list and didn't find the port */ DBG(10, "sane_init: init_mode line is " "for unknown port!\n"); } continue; } DBG(1, "sane_init: Unknown configuration command!"); } fclose (fp); } /* There should now be a LL of ports starting at first_dev */ for (s_tmp = first_dev; s_tmp != NULL; s_tmp = s_tmp->next) { /* Assume there's no scanner present until proven otherwise */ s_tmp->scanner_present = SANE_FALSE; /* Try to detect if there's a scanner there, and if so, * what sort of scanner it is */ status = detect_mode(s_tmp); if (status != SANE_STATUS_GOOD) { DBG(10,"sane_init: Error detecting port mode on %s!\n", s_tmp->params.port->name); s_tmp->scanner_present = SANE_FALSE; continue; } /* detect_mode suceeded, so the port is open. This beholdens * us to call ieee1284_close in any of the remaining error * cases in this loop. */ #if 0 tmp = sanei_canon_pp_detect(s_tmp->params.port, s_tmp->init_mode); if (tmp && (s_tmp->ieee1284_mode != M1284_NIBBLE)) { /* A failure, try again in nibble mode... */ DBG(1, "sane_init: Failed on ECP mode, falling " "back to nibble mode\n"); s_tmp->ieee1284_mode = M1284_NIBBLE; sanei_canon_pp_set_ieee1284_mode(s_tmp->ieee1284_mode); tmp = sanei_canon_pp_detect(s_tmp->params.port, s_tmp->init_mode); } /* still no go? */ if (tmp) { DBG(1,"sane_init: couldn't find a scanner on port " "%s\n", s_tmp->params.port->name); ieee1284_close(s_tmp->params.port); continue; } #endif /* all signs point to yes, try it out */ if (ieee1284_claim(s_tmp->params.port) != E1284_OK) { DBG(10, "sane_init: Couldn't claim port %s.\n", s_tmp->params.port->name); ieee1284_close(s_tmp->params.port); continue; } DBG(2, "sane_init: >> initialise\n"); tmp = sanei_canon_pp_initialise(&(s_tmp->params), s_tmp->init_mode); DBG(2, "sane_init: << %d initialise\n", tmp); if (tmp) { DBG(10, "sane_init: Couldn't contact scanner on port " "%s. Probably no scanner there?\n", s_tmp->params.port->name); ieee1284_release(s_tmp->params.port); ieee1284_close(s_tmp->params.port); s_tmp->scanner_present = SANE_FALSE; continue; } /* put it back to sleep until we're ready to * open for business again - this will only work * if we actually have a scanner there! */ DBG(100, "sane_init: And back to sleep again\n"); sanei_canon_pp_sleep_scanner(s_tmp->params.port); /* leave the port open but not claimed - this is regardless * of the return value of initialise */ ieee1284_release(s_tmp->params.port); /* Finally, we're sure there's a scanner there! Now we * just have to load the weights file...*/ if (fix_weights_file(s_tmp) != SANE_STATUS_GOOD) { DBG(1, "sane_init: Eeek! fix_weights_file failed for " "scanner on port %s!\n", s_tmp->params.port->name); /* non-fatal.. scans will look ugly as sin unless * they calibrate */ } /* Cocked, locked and ready to rock */ s_tmp->hw.model = s_tmp->params.name; s_tmp->scanner_present = SANE_TRUE; } DBG(2, "<< sane_init\n"); return status; } /************************************************************************* * * sane_get_devices() * * Gives a list of devices avaialable. In our case, that's the linked * list produced by sane_init. * *************************************************************************/ SANE_Status sane_get_devices (const SANE_Device ***dl, SANE_Bool local) { static const SANE_Device **devlist; CANONP_Scanner *dev; int i; DBG(2, ">> sane_get_devices (%p, %d)\n", (const void*)dl, local); if (dl == NULL) { DBG(1, "sane_get_devices: ERROR: devlist pointer is NULL!"); return SANE_STATUS_INVAL; } if (devlist != NULL) { /* this has been called already */ *dl = devlist; return SANE_STATUS_GOOD; } devlist = malloc((num_devices + 1) * sizeof(*devlist)); if (devlist == NULL) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; dev != NULL; dev = dev->next) { if (dev->scanner_present == SANE_TRUE) { devlist[i] = &(dev->hw); i++; } } devlist[i] = NULL; *dl = devlist; DBG(2, "<< sane_get_devices\n"); return SANE_STATUS_GOOD; } /************************************************************************* * * sane_open() * * Open the scanner described by name. Ask libieee1284 to claim the port * and call Simon's init code. Also configure data structures. * *************************************************************************/ SANE_Status sane_open (SANE_String_Const name, SANE_Handle *h) { CANONP_Scanner *cs; SANE_Range *tmp_range; int tmp; DBG(2, ">> sane_open (h=%p, name=\"%s\")\n", (void *)h, name); if ((h == NULL) || (name == NULL)) { DBG(2,"sane_open: Null pointer received!\n"); return SANE_STATUS_INVAL; } if (!strlen(name)) { DBG(10,"sane_open: Empty name given, assuming first/" "default scanner\n"); if (def_scanner == NULL) name = first_dev->params.port->name; else name = def_scanner; /* we don't _have_ to fit this name, so _don't_ fail if it's * not there */ cs = first_dev; while((cs != NULL) && strcmp(cs->params.port->name, name)) cs = cs->next; /* if we didn't find the port they want, or there's no scanner * there, we just want to find _any_ scanner */ if ((cs == NULL) || (cs->scanner_present != SANE_TRUE)) { cs = first_dev; while((cs != NULL) && (cs->scanner_present == SANE_FALSE)) cs = cs->next; } } else { /* they're dead keen for this name, so _do_ fail if it's * not there */ cs = first_dev; while((cs != NULL) && strcmp(cs->params.port->name, name)) cs = cs->next; } if (cs == NULL) { DBG(2,"sane_open: No scanner found or requested port " "doesn't exist (%s)\n", name); return SANE_STATUS_IO_ERROR; } if (cs->scanner_present == SANE_FALSE) { DBG(1,"sane_open: Request to open port with no scanner " "(%s)\n", name); return SANE_STATUS_IO_ERROR; } if (cs->opened == SANE_TRUE) { DBG(2,"sane_open; Oi!, That scanner's already open.\n"); return SANE_STATUS_DEVICE_BUSY; } /* If the scanner has already been opened once, we don't have to do * this setup again */ if (cs->setup == SANE_TRUE) { cs->opened = SANE_TRUE; *h = (SANE_Handle)cs; return SANE_STATUS_GOOD; } tmp = ieee1284_claim(cs->params.port); if (tmp != E1284_OK) { DBG(1, "sane_open: Could not claim port!\n"); return SANE_STATUS_IO_ERROR; } /* I put the scanner to sleep before, better wake it back up */ DBG(2, "sane_open: >> initialise\n"); tmp = sanei_canon_pp_initialise(&(cs->params), cs->init_mode); DBG(2, "sane_open: << %d initialise\n", tmp); if (tmp != 0) { DBG(1, "sane_open: initialise returned %d, something is " "wrong with the scanner!\n", tmp); DBG(1, "sane_open: Can't contact scanner. Try power " "cycling scanner, and unplug any " "printers\n"); ieee1284_release(cs->params.port); return SANE_STATUS_IO_ERROR; } if (cs->weights_file != NULL) DBG(2, "sane_open: >> load_weights(%s, %p)\n", cs->weights_file, (const void *)(&(cs->params))); else DBG(2, "sane_open: >> load_weights(NULL, %p)\n", (const void *)(&(cs->params))); tmp = sanei_canon_pp_load_weights(cs->weights_file, &(cs->params)); DBG(2, "sane_open: << %d load_weights\n", tmp); if (tmp != 0) { DBG(1, "sane_open: WARNING: Error on load_weights: " "returned %d. This could be due to a corrupt " "calibration file. Try recalibrating and if " "problems persist, please report the problem " "to the canon_pp maintainer\n", tmp); cs->cal_valid = SANE_FALSE; } else { cs->cal_valid = SANE_TRUE; DBG(10, "sane_open: loadweights successful, uploading gamma" " profile...\n"); tmp = sanei_canon_pp_adjust_gamma(&(cs->params)); if (tmp != 0) DBG(1, "sane_open: WARNING: adjust_gamma returned " "%d!\n", tmp); DBG(10, "sane_open: after adjust_gamma Status = %i\n", sanei_canon_pp_check_status(cs->params.port)); } /* Configure ranges etc */ /* Resolution - determined by magic number */ if (cs->params.scanheadwidth == 2552) cs->opt[OPT_RESOLUTION].constraint.word_list = res300; else cs->opt[OPT_RESOLUTION].constraint.word_list = res600; /* TL-X */ if(!(tmp_range = malloc(sizeof(*tmp_range)))) return SANE_STATUS_NO_MEM; (*tmp_range).min = 0; (*tmp_range).max = 215; cs->opt[OPT_TL_X].constraint.range = tmp_range; /* TL-Y */ if(!(tmp_range = malloc(sizeof(*tmp_range)))) return SANE_STATUS_NO_MEM; (*tmp_range).min = 0; (*tmp_range).max = 296; cs->opt[OPT_TL_Y].constraint.range = tmp_range; /* BR-X */ if(!(tmp_range = malloc(sizeof(*tmp_range)))) return SANE_STATUS_NO_MEM; (*tmp_range).min = 3; (*tmp_range).max = 216; cs->opt[OPT_BR_X].constraint.range = tmp_range; /* BR-Y */ if(!(tmp_range = malloc(sizeof(*tmp_range)))) return SANE_STATUS_NO_MEM; (*tmp_range).min = 1; (*tmp_range).max = 297; cs->opt[OPT_BR_Y].constraint.range = tmp_range; cs->opened = SANE_TRUE; cs->setup = SANE_TRUE; *h = (SANE_Handle)cs; DBG(2, "<< sane_open\n"); return SANE_STATUS_GOOD; } /************************************************************************* * * sane_get_option_descriptor() * * Return the structure for option number opt. * *************************************************************************/ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int opt) { CANONP_Scanner *cs = ((CANONP_Scanner *)h); /*DBG(2, ">> sane_get_option_descriptor (h=%p, opt=%d)\n", h, opt);*/ if (h == NULL) { DBG(10,"sane_get_option_descriptor: WARNING: h==NULL!\n"); return NULL; } if ((unsigned)opt >= NUM_OPTIONS) { DBG(10,"sane_get_option_descriptor: Note: opt >= " "NUM_OPTIONS!\n"); return NULL; } if (cs->opened == SANE_FALSE) { DBG(1,"sane_get_option_descriptor: That scanner (%p) ain't " "open yet\n", h); return NULL; } /*DBG(2, "<< sane_get_option_descriptor\n");*/ return (cs->opt + opt); } /************************************************************************* * * sane_control_option() * * Set a value for one of the options provided. * *************************************************************************/ SANE_Status sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act, void *val, SANE_Word *info) { CANONP_Scanner *cs = ((CANONP_Scanner *)h); int i = 0, tmp, maxresi; DBG(2, ">> sane_control_option (h=%p, opt=%d, act=%d)\n", h,opt,act); /* Do some sanity checks on the parameters * note that val can be null for buttons */ if ((h == NULL) || ((val == NULL) && (opt != OPT_CAL))) /* || (info == NULL)) - Don't check this any more.. * frontends seem to like passing a null */ { DBG(1,"sane_control_option: Frontend passed me a null! " "(h=%p,val=%p,info=%p)\n",(void*)h, val,(void*)info); return SANE_STATUS_INVAL; } if (((unsigned)opt) >= NUM_OPTIONS) { DBG(1,"sane_control_option: I don't do option %d.\n", opt); return SANE_STATUS_INVAL; } if (cs->opened == SANE_FALSE) { DBG(1,"sane_control_option: That scanner (%p) ain't " "open yet\n", h); return SANE_STATUS_INVAL; } if (cs->scanning == SANE_TRUE) { DBG(1,"sane_control_option: That scanner (%p) is scanning!\n", h); return SANE_STATUS_DEVICE_BUSY; } switch(act) { case SANE_ACTION_GET_VALUE: switch (opt) { case OPT_COLOUR_MODE: strcpy((char *)val, cmodes[cs->vals[opt]]); break; case OPT_DEPTH: strcpy((char *)val, depths[cs->vals[opt]]); break; case OPT_RESOLUTION: *((int *)val) = res600[cs->vals[opt]]; break; default: *((int *)val) = cs->vals[opt]; break; } break; case SANE_ACTION_SET_VALUE: /* val has been checked for NULL if opt != OPT_CAL */ if (opt != OPT_CAL) i = *((int *)val); if (info != NULL) *info = 0; switch (opt) { case OPT_NUM_OPTIONS: /* you can't set that! */ return SANE_STATUS_INVAL; case OPT_RESOLUTION: i = cs->vals[opt]; cs->vals[opt] = 1; maxresi = cs->opt[OPT_RESOLUTION]. constraint.word_list[0]; while ((cs->vals[opt] <= maxresi) && (res600[cs->vals[opt]] < *((int *)val))) { cs->vals[opt] += 1; } if (res600[cs->vals[opt]] != *((int *)val)) { if (info != NULL) *info |= SANE_INFO_INEXACT; } break; case OPT_COLOUR_MODE: cs->vals[opt] = 0; while ((cmodes[cs->vals[opt]] != NULL) && strcmp(cmodes[cs->vals[opt]], (char *)val)) { cs->vals[opt] += 1; } if (info != NULL) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_DEPTH: cs->vals[opt] = 0; while ((depths[cs->vals[opt]] != NULL) && strcmp(depths[cs->vals[opt]], (char *)val)) { cs->vals[opt] += 1; } if (info != NULL) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_TL_X: case OPT_BR_X: case OPT_TL_Y: case OPT_BR_Y: if ((iopt[opt].constraint.range->min) || (i>cs->opt[opt].constraint.range->max)) return SANE_STATUS_INVAL; cs->vals[opt] = i; break; case OPT_CAL: /* Call the calibration code */ if ((cs->weights_file==NULL) || cs->cal_readonly ) DBG(2, ">> calibrate(x, " "NULL)\n"); else DBG(2, ">> calibrate(x," "%s)\n", cs->weights_file); if (cs->cal_readonly) tmp = sanei_canon_pp_calibrate( &(cs->params), NULL); else tmp = sanei_canon_pp_calibrate( &(cs->params), cs->weights_file); DBG(2, "<< %d calibrate\n", tmp); if (tmp != 0) { DBG(1, "sane_control_option: " "WARNING: " "calibrate " "returned %d!", tmp); cs->cal_valid = SANE_FALSE; return SANE_STATUS_IO_ERROR; } else { cs->cal_valid = SANE_TRUE; } break; /*case OPT_PREVIEW: if (i) cs->vals[opt] = 1; else cs->vals[opt] = 0; break;*/ default: /* Should never happen */ return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_AUTO: DBG(2, "sane_control_option: attempt at " "automatic control! (unsupported)\n"); /* Auto? are they mad? I'm not that smart! */ /* fall through. */ default: return SANE_STATUS_INVAL; } DBG(2, "<< sane_control_option\n"); return SANE_STATUS_GOOD; } /************************************************************************* * * sane_get_parameters() * * Get information about the next packet. If a scan hasn't started, results * only have to be best guesses. * *************************************************************************/ SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters *params) { int res, max_width, max_height, max_res; CANONP_Scanner *cs = ((CANONP_Scanner *)h); DBG(2, ">> sane_get_parameters (h=%p, params=%p)\n", (void*)h, (void*)params); if (h == NULL) return SANE_STATUS_INVAL; if (cs->opened == SANE_FALSE) { DBG(1,"sane_get_parameters: That scanner (%p) ain't " "open yet\n", h); return SANE_STATUS_INVAL; } /* We use 600 res list here because the 300 res list is just a shorter * version, so this will always work. */ res = res600[cs->vals[OPT_RESOLUTION]]; /* * These don't change whether we're scanning or not * NOTE: Assumes options don't change after scanning commences, which * is part of the standard */ /* Copy the options stored in the vals into the scaninfo */ params->pixels_per_line = ((cs->vals[OPT_BR_X] - cs->vals[OPT_TL_X]) * res) / MM_PER_IN; params->lines = ((cs->vals[OPT_BR_Y] - cs->vals[OPT_TL_Y]) * res) / MM_PER_IN; /* FIXME: Magic numbers ahead! */ max_res = cs->params.scanheadwidth == 2552 ? 300 : 600; /* x values have to be divisible by 4 (round down) */ params->pixels_per_line -= (params->pixels_per_line%4); /* Can't scan less than 64 */ if (params->pixels_per_line < 64) params->pixels_per_line = 64; max_width = cs->params.scanheadwidth / (max_res / res); max_height = (cs->params.scanheadwidth == 2552 ? 3508 : 7016) / (max_res / res); if(params->pixels_per_line > max_width) params->pixels_per_line = max_width; if(params->lines > max_height) params->lines = max_height; params->depth = cs->vals[OPT_DEPTH] ? 16 : 8; switch (cs->vals[OPT_COLOUR_MODE]) { case 0: params->format = SANE_FRAME_GRAY; break; case 1: params->format = SANE_FRAME_RGB; break; default: /* shouldn't happen */ break; } if (!(params->pixels_per_line)) { params->last_frame = SANE_TRUE; params->lines = 0; } /* Always the "last frame" */ params->last_frame = SANE_TRUE; params->bytes_per_line = params->pixels_per_line * (params->depth/8) * (cs->vals[OPT_COLOUR_MODE] ? 3 : 1); DBG(10, "get_params: bytes_per_line=%d, pixels_per_line=%d, lines=%d\n" "max_res=%d, res=%d, max_height=%d, br_y=%d, tl_y=%d, " "mm_per_in=%f\n", params->bytes_per_line, params->pixels_per_line, params->lines, max_res, res, max_height, cs->vals[OPT_BR_Y], cs->vals[OPT_TL_Y], MM_PER_IN); DBG(2, "<< sane_get_parameters\n"); return SANE_STATUS_GOOD; } /************************************************************************* * * sane_start() * * Starts scanning an image. * *************************************************************************/ SANE_Status sane_start (SANE_Handle h) { unsigned int i, res, max_width, max_height, max_res, tmp; CANONP_Scanner *cs = ((CANONP_Scanner *)h); DBG(2, ">> sane_start (h=%p)\n", h); if (h == NULL) return SANE_STATUS_INVAL; if (cs->scanning) return SANE_STATUS_DEVICE_BUSY; if (cs->opened == SANE_FALSE) { DBG(1,"sane_start: That scanner (%p) ain't " "open yet\n", h); return SANE_STATUS_INVAL; } /* We use 600 res list here because the 300 res list is just a shorter * version, so this will always work. */ res = res600[cs->vals[OPT_RESOLUTION]]; /* Copy the options stored in the vals into the scaninfo */ cs->scan.width = ((cs->vals[OPT_BR_X] - cs->vals[OPT_TL_X]) * res) / MM_PER_IN; cs->scan.height = ((cs->vals[OPT_BR_Y] - cs->vals[OPT_TL_Y]) * res) / MM_PER_IN; cs->scan.xoffset = (cs->vals[OPT_TL_X] * res) / MM_PER_IN; cs->scan.yoffset = (cs->vals[OPT_TL_Y] * res) / MM_PER_IN; /* * These values have to pass the requirements of not exceeding * dimensions (simple clipping) and both width values have to be some * integer multiple of 4 */ /* FIXME: Magic numbers ahead! */ max_res = cs->params.scanheadwidth == 2552 ? 300 : 600; /* x values have to be divisible by 4 (round down) */ cs->scan.width -= (cs->scan.width%4); cs->scan.xoffset -= (cs->scan.xoffset%4); /* Can't scan less than 64 */ if (cs->scan.width < 64) cs->scan.width = 64; max_width = cs->params.scanheadwidth / (max_res / res); max_height = (cs->params.scanheadwidth == 2552 ? 3508 : 7016) / (max_res / res); if (cs->scan.width > max_width) cs->scan.width = max_width; if (cs->scan.width + cs->scan.xoffset > max_width) cs->scan.xoffset = max_width - cs->scan.width; if (cs->scan.height > max_height) cs->scan.height = max_height; /* We pass a value to init_scan which is the power of 2 that 75 * is multiplied by for the resolution. ie: * 75 -> 0 * 150 -> 1 * 300 -> 2 * 600 -> 4 * * This rather strange parameter is a result of the way the scanner * takes its resolution argument */ i = 0; while (res > 75) { i++; res = res >> 1; } /* FIXME? xres == yres for now. */ cs->scan.xresolution = i; cs->scan.yresolution = i; if (((cs->vals[OPT_BR_Y] - cs->vals[OPT_TL_Y]) <= 0) || ((cs->vals[OPT_BR_X] - cs->vals[OPT_TL_X]) <= 0)) { DBG(1,"sane_start: height = %d, Width = %d. " "Can't scan void range!", cs->scan.height, cs->scan.width); return SANE_STATUS_INVAL; } cs->scan.mode = cs->vals[OPT_COLOUR_MODE]; DBG(10, ">> init_scan()\n"); tmp = sanei_canon_pp_init_scan(&(cs->params), &(cs->scan)); DBG(10, "<< %d init_scan\n", tmp); if (tmp != 0) { DBG(1,"sane_start: WARNING: init_scan returned %d!", tmp); return SANE_STATUS_IO_ERROR; } cs->scanning = SANE_TRUE; cs->cancelled = SANE_FALSE; cs->sent_eof = SANE_FALSE; cs->lines_scanned = 0; cs->bytes_sent = 0; DBG(2, "<< sane_start\n"); return SANE_STATUS_GOOD; } /************************************************************************* * * sane_read() * * Reads some information from the buffer. * *************************************************************************/ SANE_Status sane_read (SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp) { CANONP_Scanner *cs = ((CANONP_Scanner *)h); image_segment *is; unsigned int lines, bytes, bpl; unsigned int i; short *shortptr; SANE_Byte *charptr; int tmp; static SANE_Byte *lbuf; static unsigned int bytesleft; DBG(2, ">> sane_read (h=%p, buf=%p, maxlen=%d)\n", h, (const void *)buf, maxlen); /* default to returning 0 - for errors */ *lenp = 0; if ((h == NULL) || (buf == NULL) || (lenp == NULL)) { DBG(1, "sane_read: This frontend's passing me dodgy gear! " "(h=%p, buf=%p, lenp=%p)\n", (void*)h, (void*)buf, (void*)lenp); return SANE_STATUS_INVAL; } /* Now we have to see if we have some leftover from last time */ if (read_leftover != NULL) { /* feed some more data in until we've run out - don't care * whether or not we _think_ the scanner is scanning now, * because we may still have data left over to send */ DBG(200, "sane_read: didn't send it all last time\n"); /* Now feed it some data from lbuf */ if (bytesleft <= (unsigned int)maxlen) { /* enough buffer to send the lot */ memcpy(buf, read_leftover, bytesleft); free(lbuf); *lenp = bytesleft; lbuf = NULL; read_leftover = NULL; bytesleft = 0; cs->bytes_sent += bytesleft; return SANE_STATUS_GOOD; } else { /* only enough to send maxlen */ memcpy(buf, read_leftover, maxlen); read_leftover += maxlen; bytesleft -= maxlen; *lenp = maxlen; cs->bytes_sent += maxlen; DBG(100, "sane_read: sent %d bytes, still have %d to " "go\n", maxlen, bytesleft); return SANE_STATUS_GOOD; } } /* Has the last scan ended (other than by cancelling)? */ if (((unsigned)cs->scan.height <= (unsigned)cs->lines_scanned) || (cs->sent_eof) || !(cs->scanning)) { cs->sent_eof = SANE_TRUE; cs->scanning = SANE_FALSE; cs->cancelled = SANE_FALSE; cs->lines_scanned = 0; cs->bytes_sent = 0; read_leftover = NULL; return SANE_STATUS_EOF; } /* At this point we have to read more data from the scanner - or the * scan has been cancelled, which means we have to call read_segment * to leave the scanner consistant */ /* Decide how many lines we can fit into this buffer */ if (cs->vals[OPT_DEPTH] == 0) bpl = cs->scan.width * (cs->vals[OPT_COLOUR_MODE] ? 3 : 1); else bpl = cs->scan.width * (cs->vals[OPT_COLOUR_MODE] ? 6 : 2); /* New way: scan a whole scanner buffer full, and return as much as * the frontend wants. It's faster and more reliable since the * scanners crack the shits if we ask for too many small packets */ lines = (BUF_MAX * 4 / 5) / bpl; if (lines > (cs->scan.height - cs->lines_scanned)) lines = cs->scan.height - cs->lines_scanned; if (!lines) { /* can't fit a whole line into the buffer * (should never happen!) */ lines = 1; } bytes = lines * bpl; /* Allocate a local buffer to hold the data while we play */ if ((lbuf = malloc(bytes)) == NULL) { DBG(10, "sane_read: Not enough memory to hold a " "local buffer. You're doomed\n"); return SANE_STATUS_NO_MEM; } /* This call required a lot of debugging information.. */ DBG(10, "sane_read: Here's what we're sending read_segment:\n"); DBG(10, "scanner setup: shw=%d xres=%d yres=%d %d %d id=%s\n", cs->params.scanheadwidth, cs->params.natural_xresolution, cs->params.natural_yresolution, cs->params.max_xresolution, cs->params.max_yresolution, (cs->params.id_string)+8); DBG(10, "scan_params->: width=%d, height=%d, xoffset=%d, " "yoffset=%d\n\txresolution=%d, yresolution=%d, " "mode=%d, (lines=%d)\n", cs->scan.width, cs->scan.height, cs->scan.xoffset, cs->scan.yoffset, cs->scan.xresolution, cs->scan.yresolution, cs->scan.mode, lines); DBG(2, ">> read_segment(x, x, x, %d, %d, %d)\n", lines, cs->cal_valid, cs->scan.height - cs->lines_scanned); tmp = sanei_canon_pp_read_segment(&is, &(cs->params), &(cs->scan), lines, cs->cal_valid, cs->scan.height - cs->lines_scanned); DBG(2, "<< %d read_segment\n", tmp); if (tmp != 0) { if (cs->cancelled) { DBG(10, "sane_read: cancelling.\n"); cs->sent_eof = SANE_TRUE; cs->scanning = SANE_FALSE; read_leftover = NULL; sanei_canon_pp_abort_scan(&(cs->params)); return SANE_STATUS_CANCELLED; } DBG(1, "sane_read: WARNING: read_segment returned %d!\n", tmp); return SANE_STATUS_IO_ERROR; } DBG(10, "sane_read: bpl=%d, lines=%d, bytes=%d\n", bpl, lines, bytes); cs->lines_scanned += lines; /* translate data out of buffer */ if (cs->vals[OPT_DEPTH] == 0) { /* 8bpp */ for(i = 0; i < bytes; i++) { charptr = lbuf + i; if (cs->vals[OPT_COLOUR_MODE]) { if (i % 3 == 0) charptr += 2; if (i % 3 == 2) charptr -= 2; } *charptr = *((char *)(is->image_data) + (i*2)); } } else { /* 16bpp */ for(i = 0; i < (bytes/2); i++) { shortptr = ((short *)lbuf + i); if (cs->vals[OPT_COLOUR_MODE]) { if (i % 3 == 0) shortptr += 2; if (i % 3 == 2) shortptr -= 2; } *shortptr = MAKE_SHORT( *((char *)(is->image_data) + (i*2)), *((char *)(is->image_data) + (i*2)+1) ); } } /* Free data structures allocated in read_segment */ free(is->image_data); free(is); /* Now feed it some data from lbuf */ if (bytes <= (unsigned int)maxlen) { /* enough buffer to send the lot */ memcpy(buf, lbuf, bytes); *lenp = bytes; free(lbuf); lbuf = NULL; read_leftover = NULL; bytesleft = 0; cs->bytes_sent += bytes; } else { /* only enough to send maxlen */ memcpy(buf, lbuf, maxlen); *lenp = maxlen; read_leftover = lbuf + maxlen; bytesleft = bytes - maxlen; cs->bytes_sent += maxlen; DBG(100, "sane_read: sent %d bytes, still have %d to go\n", maxlen, bytesleft); } if ((unsigned)cs->lines_scanned >= cs->scan.height) { /* The scan is over! Don't need to call anything in the * hardware, it will sort itself out */ DBG(10, "sane_read: Scan is finished.\n"); cs->scanning = SANE_FALSE; cs->lines_scanned = 0; cs->bytes_sent = 0; } DBG(2, "<< sane_read\n"); return SANE_STATUS_GOOD; } /************************************************************************* * * sane_cancel() * * Cancels a scan in progress * *************************************************************************/ void sane_cancel (SANE_Handle h) { /* Note: assume handle is valid apart from NULLs */ CANONP_Scanner *cs = ((CANONP_Scanner *)h); DBG(2, ">> sane_cancel (h=%p)\n", h); if (h == NULL) return; read_leftover = NULL; if (!(cs->scanning)) { DBG(2, "<< sane_cancel (not scanning)\n"); return; } cs->cancelled = SANE_TRUE; cs->params.abort_now = 1; DBG(2, "<< sane_cancel\n"); } /************************************************************************* * * sane_close() * * Closes a scanner handle. Scanner is assumed to be free after this. * *************************************************************************/ void sane_close (SANE_Handle h) { /* Note: assume handle is valid apart from NULLs */ CANONP_Scanner *cs = ((CANONP_Scanner *)h); DBG(2, ">> sane_close (h=%p)\n", h); if (h == NULL) return; if (cs->opened == SANE_FALSE) { DBG(1,"sane_close: That scanner (%p) ain't " "open yet\n", h); return; } /* Put scanner back in transparent mode */ sanei_canon_pp_close_scanner(&(cs->params)); cs->opened = SANE_FALSE; /* if it was scanning, it's not any more */ cs->scanning = SANE_FALSE; cs->sent_eof = SANE_TRUE; ieee1284_release(cs->params.port); DBG(2, "<< sane_close\n"); } /************************************************************************* * * sane_exit() * * Shut it down! * *************************************************************************/ void sane_exit (void) { CANONP_Scanner *dev, *next; DBG(2, ">> sane_exit\n"); for (dev = first_dev; dev != NULL; dev = next) { next = dev->next; /* These were only created if the scanner has been init'd */ /* Should normally nullify pointers after freeing, but in * this case we're about to free the whole structure so * theres not a lot of point. */ /* Constraints (mostly) allocated when the scanner is opened */ if(dev->opt[OPT_TL_X].constraint.range) free((void *)(dev->opt[OPT_TL_X].constraint.range)); if(dev->opt[OPT_TL_Y].constraint.range) free((void *)(dev->opt[OPT_TL_Y].constraint.range)); if(dev->opt[OPT_BR_X].constraint.range) free((void *)(dev->opt[OPT_BR_X].constraint.range)); if(dev->opt[OPT_BR_Y].constraint.range) free((void *)(dev->opt[OPT_BR_Y].constraint.range)); /* Weights file now on a per-scanner basis */ if (dev->weights_file != NULL) free(dev->weights_file); if (dev->scanner_present) { if (dev->opened == SANE_TRUE) { /* naughty boys, should have closed first */ ieee1284_release(dev->params.port); } ieee1284_close(dev->params.port); } free (dev); } first_dev = NULL; def_scanner = NULL; read_leftover = NULL; num_devices = 0; /* FIXEDME: this created a segfault in DLL code. */ /* Bug was fixed in libieee1284 0.1.5 */ ieee1284_free_ports(&pl); DBG(2, "<< sane_exit\n"); } /************************************************************************* * * init_device() * * (Not part of the SANE API) * * Initialises a CANONP_Scanner data structure for a new device. * NOTE: The device is not ready to scan until initialise() has been * called in scan library! * *************************************************************************/ static SANE_Status init_device(struct parport *pp) { int i; static const char *hw_vendor = "CANON"; static const char *hw_type = "flatbed scanner"; static const char *opt_names[] = { SANE_NAME_NUM_OPTIONS, SANE_NAME_SCAN_RESOLUTION, SANE_NAME_SCAN_MODE, SANE_NAME_BIT_DEPTH, SANE_NAME_SCAN_TL_X, SANE_NAME_SCAN_TL_Y, SANE_NAME_SCAN_BR_X, SANE_NAME_SCAN_BR_Y, SANE_NAME_QUALITY_CAL #if 0 SANE_NAME_GAMMA_R, SANE_NAME_GAMMA_G, SANE_NAME_GAMMA_B #endif }; static const char *opt_titles[] = { SANE_TITLE_NUM_OPTIONS, SANE_TITLE_SCAN_RESOLUTION, SANE_TITLE_SCAN_MODE, SANE_TITLE_BIT_DEPTH, SANE_TITLE_SCAN_TL_X, SANE_TITLE_SCAN_TL_Y, SANE_TITLE_SCAN_BR_X, SANE_TITLE_SCAN_BR_Y, SANE_TITLE_QUALITY_CAL #if 0 SANE_TITLE_GAMMA_R, SANE_TITLE_GAMMA_G, SANE_TITLE_GAMMA_B #endif }; static const char *opt_descs[] = { SANE_DESC_NUM_OPTIONS, SANE_DESC_SCAN_RESOLUTION, SANE_DESC_SCAN_MODE, SANE_DESC_BIT_DEPTH, SANE_DESC_SCAN_TL_X, SANE_DESC_SCAN_TL_Y, SANE_DESC_SCAN_BR_X, SANE_DESC_SCAN_BR_Y, SANE_DESC_QUALITY_CAL #if 0 SANE_DESC_GAMMA_R, SANE_DESC_GAMMA_G, SANE_DESC_GAMMA_B #endif }; CANONP_Scanner *cs = NULL; DBG(2, ">> init_device\n"); cs = malloc(sizeof(*cs)); if (cs == NULL) { return SANE_STATUS_NO_MEM; } memset(cs, 0, sizeof(*cs)); #if 0 if ((cs->params.port = malloc(sizeof(*(cs->params.port)))) == NULL) return SANE_STATUS_NO_MEM; memcpy(cs->params.port, pp, sizeof(*pp)); #endif cs->params.port = pp; /* ensure these are null to start off with, otherwise they might be * erroneously free'd. Note that we set everything to 0 above * but that's not *always* the same thing */ cs->params.blackweight = NULL; cs->params.redweight = NULL; cs->params.greenweight = NULL; cs->params.blueweight = NULL; /* Set some sensible defaults */ cs->hw.name = cs->params.port->name; cs->hw.vendor = hw_vendor; cs->hw.type = hw_type; cs->opened = SANE_FALSE; cs->scanning = SANE_FALSE; cs->cancelled = SANE_FALSE; cs->sent_eof = SANE_TRUE; cs->lines_scanned = 0; cs->bytes_sent = 0; cs->init_mode = INITMODE_AUTO; DBG(10, "init_device: [configuring options]\n"); /* take a punt at each option, then we change it later */ for (i = 0; i < NUM_OPTIONS; i++) { cs->opt[i].name = opt_names[i]; cs->opt[i].title = opt_titles[i]; cs->opt[i].desc = opt_descs[i]; cs->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; cs->opt[i].type = SANE_TYPE_INT; cs->opt[i].size = sizeof(SANE_Int); } DBG(100, "init_device: configuring opt: num_options\n"); /* The number of options option */ cs->opt[OPT_NUM_OPTIONS].unit = SANE_UNIT_NONE; cs->opt[OPT_NUM_OPTIONS].cap = SANE_CAP_SOFT_DETECT; cs->vals[OPT_NUM_OPTIONS] = NUM_OPTIONS; DBG(100, "init_device: configuring opt: resolution\n"); /* The resolution of scanning (X res == Y res for now)*/ cs->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; cs->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; /* should never point at first element (wordlist size) */ cs->vals[OPT_RESOLUTION] = 1; DBG(100, "init_device: configuring opt: colour mode\n"); /* The colour mode (0=grey 1=rgb) */ cs->opt[OPT_COLOUR_MODE].type = SANE_TYPE_STRING; cs->opt[OPT_COLOUR_MODE].size = 20; cs->opt[OPT_COLOUR_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; /* Set this one here because it doesn't change by scanner (yet) */ cs->opt[OPT_COLOUR_MODE].constraint.string_list = cmodes; DBG(100, "init_device: configuring opt: bit depth\n"); /* The bit depth */ cs->opt[OPT_DEPTH].type = SANE_TYPE_STRING; cs->opt[OPT_DEPTH].size = 20; cs->opt[OPT_DEPTH].cap |= SANE_CAP_EMULATED; cs->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_STRING_LIST; cs->opt[OPT_DEPTH].constraint.string_list = depths; DBG(100, "init_device: configuring opt: tl-x\n"); /* The top-left-x */ cs->opt[OPT_TL_X].unit = SANE_UNIT_MM; cs->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; DBG(100, "init_device: configuring opt: tl-y\n"); /* The top-left-y */ cs->opt[OPT_TL_Y].unit = SANE_UNIT_MM; cs->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; DBG(100, "init_device: configuring opt: br-x\n"); /* The bottom-right-x */ cs->opt[OPT_BR_X].unit = SANE_UNIT_MM; cs->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; /* default scan width */ cs->vals[OPT_BR_X] = 100; DBG(100, "init_device: configuring opt: br-y\n"); /* The bottom-right-y */ cs->opt[OPT_BR_Y].unit = SANE_UNIT_MM; cs->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; cs->vals[OPT_BR_Y] = 100; DBG(100, "init_device: configuring opt: calibrate\n"); /* The calibration button */ cs->opt[OPT_CAL].type = SANE_TYPE_BUTTON; cs->opt[OPT_CAL].constraint_type = SANE_CONSTRAINT_NONE; if (cs->cal_readonly) cs->opt[OPT_CAL].cap |= SANE_CAP_INACTIVE; #if 0 /* the gamma values (once we do them) */ cs->opt[OPT_GAMMA_R].caps |= SANE_CAP_ADVANCED; cs->opt[OPT_GAMMA_G].caps |= SANE_CAP_ADVANCED; cs->opt[OPT_GAMMA_B].caps |= SANE_CAP_ADVANCED; #endif /* * NOTE: Ranges and lists are actually set when scanner is opened, * becase that's when we find out what sort of scanner it is */ DBG(100, "init_device: done opts\n"); /* add it to the head of the tree */ cs->next = first_dev; first_dev = cs; num_devices++; DBG(2, "<< init_device\n"); return SANE_STATUS_GOOD; } /************************************************************************* * * These two are optional ones... maybe if I get really keen? * *************************************************************************/ SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) { DBG(2, ">> sane_set_io_mode (%p, %d) (not really supported)\n", h, non_blocking); if (non_blocking == SANE_FALSE) return SANE_STATUS_GOOD; DBG(2, "<< sane_set_io_mode\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) { DBG(2, ">> sane_get_select_fd (%p, %p) (not supported)\n", h, (const void *)fdp); DBG(2, "<< sane_get_select_fd\n"); return SANE_STATUS_UNSUPPORTED; } /************************************************************************* * * init_cal(): Try to create a calibration file * has to be changed. * ************************************************************************/ static int init_cal(char *file) { char *tmp, *path; int f, i; if ((f = open(file, O_CREAT | O_WRONLY, 0600)) < 0) { if (errno == ENOENT) { /* we need to try and make ~/.sane perhaps - * find the last / in the file path, and try * to create it */ if ((tmp = strrchr(file, '/')) == NULL) return -1; path = strdup(file); *(path + (tmp-file)) = '\0'; i = mkdir(path, 0777); free(path); if (i) return -1; /* Path has been created, now try this again.. */ if ((f = open(file, O_CREAT | O_WRONLY, 0600)) < 0) return -1; } else { /* Error is something like access denied - too * hard to fix, so i give up... */ return -1; } } /* should probably set defaults here.. */ close(f); return 0; } /************************************************************************* * * fix_weights_file(): Ensures that the weights_file setting for a given * scanner is valid * ************************************************************************/ static SANE_Status fix_weights_file(CANONP_Scanner *cs) { char *tmp, *myhome, buf[PATH_MAX]; int i; struct stat *f_stat; if (cs == NULL) { DBG(0, "fix_weights_file: FATAL: NULL passed by my code, " "please report this!\n"); return SANE_STATUS_INVAL; } /* Assume this is false and then correct it */ cs->cal_readonly = SANE_FALSE; if (cs->weights_file == NULL) { /* Will be of form canon_pp-calibration-parport0 or -0x378 */ sprintf(buf, "~/.sane/canon_pp-calibration-%s", cs->params.port->name); cs->weights_file = strdup(buf); } /* Get the user's home dir if they used ~ */ if (cs->weights_file[0] == '~') { if ((tmp = malloc(PATH_MAX)) == NULL) return SANE_STATUS_NO_MEM; if ((myhome = getenv("HOME")) == NULL) { DBG(0,"fix_weights_file: FATAL: ~ used, but $HOME not" " set!\n"); free(tmp); tmp = NULL; return SANE_STATUS_INVAL; } strncpy(tmp, myhome, PATH_MAX); strncpy(tmp+strlen(tmp), (cs->weights_file)+1, PATH_MAX-strlen(tmp)); free(cs->weights_file); cs->weights_file = tmp; } if ((f_stat = malloc(sizeof(*f_stat))) == NULL) return SANE_STATUS_NO_MEM; if(stat(cs->weights_file, f_stat)) { /* this non-intuitive if basically is if we got some error that * wasn't no-such-file, or we can't create the file.. */ if ((errno != ENOENT) || init_cal(cs->weights_file)) { /* Some nasty error returned. Give up. */ DBG(2,"fix_weights_file: error stating cal file" " (%s)\n", strerror(errno)); DBG(2,"fix_weights_file: Changes to cal data won't" " be saved!\n"); free(cs->weights_file); cs->weights_file = NULL; } } else { /* No error returned.. Check read/writability */ i = open(cs->weights_file, O_RDWR | O_APPEND); if (i <= 0) { DBG(10,"fix_weighs_file: Note: Changes to cal data " "won't be saved!\n"); i = open(cs->weights_file, O_RDONLY); if (i <= 0) { /* * Open failed (do i care why?) */ DBG(2,"fix_weights_file: error opening cal " "(%s)\n", strerror(errno)); free(cs->weights_file); cs->weights_file = NULL; } else { DBG(2,"fix_weights_file: file is read-only, " "changes won't be saved\n"); cs->cal_readonly = SANE_TRUE; close(i); } } else { /* good! */ DBG(10,"fix_weights_file: Calibration file is good " "for opening!\n"); close(i); } } /* cleanup */ free(f_stat); return SANE_STATUS_GOOD; } /* detect_mode * PRE: * cs->params.port is not open * POST: * cs->params.port is left opened iff SANE_STATUS_GOOD returned. */ SANE_Status detect_mode(CANONP_Scanner *cs) { int capabilities, tmp; /* Open then claim parallel port using libieee1284 */ DBG(10,"detect_mode: Opening port %s\n", (cs->params.port->name)); tmp = ieee1284_open(cs->params.port, 0, &capabilities); if (tmp != E1284_OK) { switch (tmp) { case E1284_INVALIDPORT: DBG(1, "detect_mode: Invalid port.\n"); break; case E1284_SYS: DBG(1, "detect_mode: System error: %s\n", strerror(errno)); break; case E1284_INIT: DBG(1, "detect_mode: Initialisation error.\n"); break; default: DBG(1, "detect_mode: Unknown error.\n"); break; } return SANE_STATUS_IO_ERROR; } DBG(10,"detect_mode: Claiming port.\n"); if (ieee1284_claim(cs->params.port) != E1284_OK) { DBG(1,"detect_mode: Unable to claim port\n"); ieee1284_close(cs->params.port); return SANE_STATUS_IO_ERROR; } /* Check that compatibility-mode (required) is supported */ if (!(capabilities & CAP1284_COMPAT)) { DBG(0,"detect_mode: Compatibility mode (required) not " "supported.\n"); ieee1284_release(cs->params.port); ieee1284_close(cs->params.port); return SANE_STATUS_IO_ERROR; } /* Check capabilities which will enchance speed */ if (capabilities & CAP1284_ECP) DBG(2, "detect_mode: Port supports ECP-H.\n"); else if (capabilities & CAP1284_ECPSWE) DBG(2, "detect_mode: Port supports ECP-S.\n"); if (capabilities & CAP1284_IRQ) DBG(2, "detect_mode: Port supports interrupts.\n"); if (capabilities & CAP1284_DMA) DBG(2, "detect_mode: Port supports DMA.\n"); /* Check whether ECP mode is possible */ if (capabilities & CAP1284_ECP) { cs->ieee1284_mode = M1284_ECP; DBG(10, "detect_mode: Using ECP-H Mode\n"); } else if (capabilities & CAP1284_ECPSWE) { cs->ieee1284_mode = M1284_ECPSWE; DBG(10, "detect_mode: Using ECP-S Mode\n"); } else if (capabilities & CAP1284_NIBBLE) { cs->ieee1284_mode = M1284_NIBBLE; DBG(10, "detect_mode: Using nibble mode\n"); } else { DBG(0, "detect_mode: No supported parport modes available!\n"); ieee1284_release(cs->params.port); ieee1284_close(cs->params.port); return SANE_STATUS_IO_ERROR; } /* Check to make sure ECP mode really is supported */ /* Have disabled the hardware ECP check because it's always supported * by libieee1284 now, and it's too prone to hitting a ppdev bug */ /* Disabled check entirely.. check now in initialise when we * actually do a read */ #if 0 if ((cs->ieee1284_mode == M1284_ECP) || (cs->ieee1284_mode == M1284_ECPSWE)) { DBG(1, "detect_mode: attempting a 0 byte read, if we hang " "here, it's a ppdev bug!\n"); /* * 29/06/02 * NOTE: * This causes an infinite loop in ppdev on 2.4.18. * Not checking on hardware ECP mode should work-around * effectively. * * I have sent email to twaugh about it, should be fixed in * 2.4.19 and above. */ if (ieee1284_ecp_read_data(cs->params.port, 0, NULL, 0) == E1284_NOTIMPL) { DBG(10, "detect_mode: Your version of libieee1284 " "doesn't support ECP mode - defaulting" " to nibble mode instead.\n"); cs->ieee1284_mode = M1284_NIBBLE; } } #endif if (force_nibble == SANE_TRUE) { DBG(10, "detect_mode: Nibble mode force in effect.\n"); cs->ieee1284_mode = M1284_NIBBLE; } ieee1284_release(cs->params.port); sanei_canon_pp_set_ieee1284_mode(cs->ieee1284_mode); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/genesys_gl646.c0000664000175000017500000046753713106201017015371 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Oliver Rauch Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2004 Gerhard Jaeger Copyright (C) 2004-2013 Stéphane Voltz Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2007 Luke Copyright (C) 2011 Alexey Osipov for HP2400 description and tuning This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME #define BACKEND_NAME genesys_gl646 #include "genesys_gl646.h" /** * returns the value hold by a 3 word register * @param regs register set from which reading the value * @param regnum number of the register to read * @return 24 bit value of the register */ static uint32_t gl646_get_triple_reg (Genesys_Register_Set * regs, int regnum) { Genesys_Register_Set *r = NULL; uint32_t ret = 0; r = sanei_genesys_get_address (regs, regnum); ret = r->value; r = sanei_genesys_get_address (regs, regnum + 1); ret = (ret << 8) + r->value; r = sanei_genesys_get_address (regs, regnum + 2); ret = (ret << 8) + r->value; return ret; } /** * returns the value hold by a 2 word register * @param regs register set from which reading the value * @param regnum number of the register to read * @return 16 bit value of the register */ static uint32_t gl646_get_double_reg (Genesys_Register_Set * regs, int regnum) { Genesys_Register_Set *r = NULL; uint32_t ret = 0; r = sanei_genesys_get_address (regs, regnum); ret = r->value; r = sanei_genesys_get_address (regs, regnum + 1); ret = (ret << 8) + r->value; return ret; } /* Write to many registers */ static SANE_Status gl646_bulk_write_register (Genesys_Device * dev, Genesys_Register_Set * reg, size_t elems) { SANE_Status status; uint8_t outdata[8]; uint8_t buffer[GENESYS_MAX_REGS * 2]; size_t size; unsigned int i; /* handle differently sized register sets, reg[0x00] may be the last one */ i = 0; while ((i < elems) && (reg[i].address != 0)) i++; elems = i; size = i * 2; DBG (DBG_io, "gl646_bulk_write_register (elems= %lu, size = %lu)\n", (u_long) elems, (u_long) size); outdata[0] = BULK_OUT; outdata[1] = BULK_REGISTER; outdata[2] = 0x00; outdata[3] = 0x00; outdata[4] = (size & 0xff); outdata[5] = ((size >> 8) & 0xff); outdata[6] = ((size >> 16) & 0xff); outdata[7] = ((size >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_bulk_write_register: failed while writing command: %s\n", sane_strstatus (status)); return status; } /* copy registers and values in data buffer */ for (i = 0; i < size; i += 2) { buffer[i] = reg[i / 2].address; buffer[i + 1] = reg[i / 2].value; } status = sanei_usb_write_bulk (dev->dn, buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_bulk_write_register: failed while writing bulk data: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io2) { for (i = 0; i < size; i += 2) { DBG (DBG_io2, "reg[0x%02x] = 0x%02x\n", buffer[i], buffer[i + 1]); } /* when full size, decode register content */ if (elems > 60) { DBG (DBG_io2, "DPISET =%d\n", gl646_get_double_reg (reg, REG_DPISET)); DBG (DBG_io2, "DUMMY =%d\n", sanei_genesys_get_address (reg, REG_DUMMY)->value); DBG (DBG_io2, "STRPIXEL =%d\n", gl646_get_double_reg (reg, REG_STRPIXEL)); DBG (DBG_io2, "ENDPIXEL =%d\n", gl646_get_double_reg (reg, REG_ENDPIXEL)); DBG (DBG_io2, "LINCNT =%d\n", gl646_get_triple_reg (reg, REG_LINCNT)); DBG (DBG_io2, "MAXWD =%d\n", gl646_get_triple_reg (reg, REG_MAXWD)); DBG (DBG_io2, "LPERIOD =%d\n", gl646_get_double_reg (reg, REG_LPERIOD)); DBG (DBG_io2, "FEEDL =%d\n", gl646_get_triple_reg (reg, REG_FEEDL)); } } DBG (DBG_io, "gl646_bulk_write_register: wrote %lu bytes, %lu registers\n", (u_long) size, (u_long) elems); return status; } /* Write bulk data (e.g. shading, gamma) */ static SANE_Status gl646_bulk_write_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size; uint8_t outdata[8]; DBG (DBG_io, "gl646_bulk_write_data writing %lu bytes\n", (u_long) len); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX, 1, &addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_bulk_write_data failed while setting register: %s\n", sane_strstatus (status)); return status; } while (len) { if (len > BULKOUT_MAXSIZE) size = BULKOUT_MAXSIZE; else size = len; outdata[0] = BULK_OUT; outdata[1] = BULK_RAM; outdata[2] = 0x00; outdata[3] = 0x00; outdata[4] = (size & 0xff); outdata[5] = ((size >> 8) & 0xff); outdata[6] = ((size >> 16) & 0xff); outdata[7] = ((size >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_bulk_write_data failed while writing command: %s\n", sane_strstatus (status)); return status; } status = sanei_usb_write_bulk (dev->dn, data, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_bulk_write_data failed while writing bulk data: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io2, "gl646_bulk_write_data wrote %lu bytes, %lu remaining\n", (u_long) size, (u_long) (len - size)); len -= size; data += size; } DBG (DBG_io, "gl646_bulk_write_data: end\n"); return status; } /** * reads value from gpio endpoint */ static SANE_Status gl646_gpio_read (SANE_Int dn, uint8_t * value) { return sanei_usb_control_msg (dn, REQUEST_TYPE_IN, REQUEST_REGISTER, GPIO_READ, INDEX, 1, value); } /** * writes the given value to gpio endpoint */ static SANE_Status gl646_gpio_write (SANE_Int dn, uint8_t value) { DBG (DBG_proc, "gl646_gpio_write(0x%02x)\n", value); return sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, GPIO_WRITE, INDEX, 1, &value); } /** * writes the given value to gpio output enable endpoint */ static SANE_Status gl646_gpio_output_enable (SANE_Int dn, uint8_t value) { DBG (DBG_proc, "gl646_gpio_output_enable(0x%02x)\n", value); return sanei_usb_control_msg (dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, GPIO_OUTPUT_ENABLE, INDEX, 1, &value); } /* Read bulk data (e.g. scanned data) */ static SANE_Status gl646_bulk_read_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size; uint8_t outdata[8]; DBG (DBG_io, "gl646_bulk_read_data: requesting %lu bytes\n", (u_long) len); /* write requested size */ status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX, 1, &addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_bulk_read_data failed while setting register: %s\n", sane_strstatus (status)); return status; } outdata[0] = BULK_IN; outdata[1] = BULK_RAM; outdata[2] = 0x00; outdata[3] = 0x00; outdata[4] = (len & 0xff); outdata[5] = ((len >> 8) & 0xff); outdata[6] = ((len >> 16) & 0xff); outdata[7] = ((len >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_bulk_read_data failed while writing command: %s\n", sane_strstatus (status)); return status; } while (len) { if (len > GL646_BULKIN_MAXSIZE) size = GL646_BULKIN_MAXSIZE; else size = len; DBG (DBG_io2, "gl646_bulk_read_data: trying to read %lu bytes of data\n", (u_long) size); status = sanei_usb_read_bulk (dev->dn, data, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io2, "gl646_bulk_read_data read %lu bytes, %lu remaining\n", (u_long) size, (u_long) (len - size)); len -= size; data += size; } if (dev->model->is_sheetfed == SANE_TRUE) { gl646_detect_document_end (dev); } DBG (DBG_io, "gl646_bulk_read_data: end\n"); return status; } #if 0 static SANE_Status read_triple_reg (Genesys_Device * dev, int index, unsigned int *words) { SANE_Status status; uint8_t value; DBG (DBG_proc, "read_triple_reg\n"); RIE (sanei_genesys_read_register (dev, index + 2, &value)); *words = value; RIE (sanei_genesys_read_register (dev, index + 1, &value)); *words += (value * 256); RIE (sanei_genesys_read_register (dev, index, &value)); if (dev->model->asic_type == GENESYS_GL646) *words += ((value & 0x03) * 256 * 256); else *words += ((value & 0x0f) * 256 * 256); DBG (DBG_proc, "read_triple_reg: value=%d\n", *words); return status; } #endif static SANE_Bool gl646_get_fast_feed_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x02); if (r && (r->value & REG02_FASTFED)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl646_get_filter_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x04); if (r && (r->value & REG04_FILTER)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl646_get_lineart_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x04); if (r && (r->value & REG04_LINEART)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl646_get_bitset_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x04); if (r && (r->value & REG04_BITSET)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl646_get_gain4_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x06); if (r && (r->value & REG06_GAIN4)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl646_test_buffer_empty_bit (SANE_Byte val) { if (val & REG41_BUFEMPTY) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl646_test_motor_flag_bit (SANE_Byte val) { if (val & REG41_MOTMFLG) return SANE_TRUE; return SANE_FALSE; } static void gl646_set_triple_reg (Genesys_Register_Set * regs, int regnum, uint32_t value) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, regnum); r->value = LOBYTE (HIWORD (value)); r = sanei_genesys_get_address (regs, regnum + 1); r->value = HIBYTE (LOWORD (value)); r = sanei_genesys_get_address (regs, regnum + 2); r->value = LOBYTE (LOWORD (value)); } static void gl646_set_double_reg (Genesys_Register_Set * regs, int regnum, uint16_t value) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, regnum); r->value = HIBYTE (LOWORD (value)); r = sanei_genesys_get_address (regs, regnum + 1); r->value = LOBYTE (LOWORD (value)); } /** * decodes and prints content of status (0x41) register * @param val value read from reg41 */ static void print_status (uint8_t val) { char msg[80]; sprintf (msg, "%s%s%s%s%s%s%s%s", val & REG41_PWRBIT ? "PWRBIT " : "", val & REG41_BUFEMPTY ? "BUFEMPTY " : "", val & REG41_FEEDFSH ? "FEEDFSH " : "", val & REG41_SCANFSH ? "SCANFSH " : "", val & REG41_HOMESNR ? "HOMESNR " : "", val & REG41_LAMPSTS ? "LAMPSTS " : "", val & REG41_FEBUSY ? "FEBUSY " : "", val & REG41_MOTMFLG ? "MOTMFLG" : ""); DBG (DBG_info, "status=%s\n", msg); } /** * start scanner's motor * @param dev scanner's device */ static SANE_Status gl646_start_motor (Genesys_Device * dev) { return sanei_genesys_write_register (dev, 0x0f, 0x01); } /** * stop scanner's motor * @param dev scanner's device */ static SANE_Status gl646_stop_motor (Genesys_Device * dev) { return sanei_genesys_write_register (dev, 0x0f, 0x00); } /** * find the lowest resolution for the sensor in the given mode. * @param sensor id of the sensor * @param color true is color mode * @return the closest resolution for the sensor and mode */ static int get_lowest_resolution (int sensor, SANE_Bool color) { int i, nb; int dpi; i = 0; dpi = 9600; nb = sizeof (sensor_master) / sizeof (Sensor_Master); while (i < nb) { /* computes distance and keep mode if it is closer than previous */ if (sensor == sensor_master[i].sensor && sensor_master[i].color == color) { if (sensor_master[i].dpi < dpi) { dpi = sensor_master[i].dpi; } } i++; } DBG (DBG_info, "get_lowest_resolution: %d\n", dpi); return dpi; } /** * find the closest match in mode tables for the given resolution and scan mode. * @param sensor id of the sensor * @param required required resolution * @param color true is color mode * @return the closest resolution for the sensor and mode */ static int get_closest_resolution (int sensor, int required, SANE_Bool color) { int i, nb; int dist, dpi; i = 0; dpi = 0; dist = 9600; nb = sizeof (sensor_master) / sizeof (Sensor_Master); while (i < nb) { /* exit on perfect match */ if (sensor == sensor_master[i].sensor && sensor_master[i].dpi == required && sensor_master[i].color == color) { DBG (DBG_info, "get_closest_resolution: match found for %d\n", required); return required; } /* computes distance and keep mode if it is closer than previous */ if (sensor == sensor_master[i].sensor && sensor_master[i].color == color) { if (abs (sensor_master[i].dpi - required) < dist) { dpi = sensor_master[i].dpi; dist = abs (sensor_master[i].dpi - required); } } i++; } DBG (DBG_info, "get_closest_resolution: closest match for %d is %d\n", required, dpi); return dpi; } /** * Computes if sensor will be set up for half ccd pixels for the given * scan mode. * @param sensor id of the sensor * @param required required resolution * @param color true is color mode * @return SANE_TRUE if half ccd is used */ static SANE_Bool is_half_ccd (int sensor, int required, SANE_Bool color) { int i, nb; i = 0; nb = sizeof (sensor_master) / sizeof (Sensor_Master); while (i < nb) { /* exit on perfect match */ if (sensor == sensor_master[i].sensor && sensor_master[i].dpi == required && sensor_master[i].color == color) { DBG (DBG_io, "is_half_ccd: match found for %d (half_ccd=%d)\n", required, sensor_master[i].half_ccd); return sensor_master[i].half_ccd; } i++; } DBG (DBG_info, "is_half_ccd: failed to find match for %d dpi\n", required); return SANE_FALSE; } /** * Returns the cksel values used by the required scan mode. * @param sensor id of the sensor * @param required required resolution * @param color true is color mode * @return cksel value for mode */ static int get_cksel (int sensor, int required, SANE_Bool color) { int i, nb; i = 0; nb = sizeof (sensor_master) / sizeof (Sensor_Master); while (i < nb) { /* exit on perfect match */ if (sensor == sensor_master[i].sensor && sensor_master[i].dpi == required && sensor_master[i].color == color) { DBG (DBG_io, "get_cksel: match found for %d (cksel=%d)\n", required, sensor_master[i].cksel); return sensor_master[i].cksel; } i++; } DBG (DBG_error, "get_cksel: failed to find match for %d dpi\n", required); /* fail safe fallback */ return 1; } /** * Setup register and motor tables for a scan at the * given resolution and color mode. TODO try to not use any filed from * the device. * @param dev pointer to a struct describing the device * @param regs register set to fill * @param scan_settings scan's settings * @param slope_table1 first motor table to fill * @param slope_table2 second motor table to fill * @param resolution dpi of the scan * @param move distance to move (at scan's dpi) before scan * @param linecnt number of lines to scan at scan's dpi * @param startx start of scan area on CCD at CCD's optical resolution * @param endx end of scan area on CCD at CCD's optical resolution * @param color SANE_TRUE is color scan * @param depth 1, 8 or 16 bits data sample * @return SANE_STATUS_GOOD if registers could be set, SANE_STATUS_INVAL if * conditions can't be met. * @note No harcoded SENSOR or MOTOR 'names' should be present and * registers are set from settings tables and flags related * to the hardware capabilities. * */ static SANE_Status gl646_setup_registers (Genesys_Device * dev, Genesys_Register_Set * regs, Genesys_Settings scan_settings, uint16_t * slope_table1, uint16_t * slope_table2, SANE_Int resolution, uint32_t move, uint32_t linecnt, uint16_t startx, uint16_t endx, SANE_Bool color, SANE_Int depth) { SANE_Status status = SANE_STATUS_GOOD; int i, nb; Sensor_Master *sensor = NULL; Motor_Master *motor = NULL; Sensor_Settings *settings = NULL; Genesys_Register_Set *r; unsigned int used1, used2, vfinal; unsigned int bpp; /**> bytes per pixel */ uint32_t z1, z2; uint16_t ex, sx; int channels = 1, stagger, words_per_line, max_shift; size_t requested_buffer_size; size_t read_buffer_size; SANE_Bool half_ccd = SANE_FALSE; SANE_Int xresolution; int feedl; DBG (DBG_proc, "gl646_setup_registers: start\n"); DBG (DBG_info, "gl646_setup_registers: startx=%d, endx=%d, linecnt=%d\n", startx, endx, linecnt); /* x resolution is capped by sensor's capability */ if (resolution > dev->sensor.optical_res) { xresolution = dev->sensor.optical_res; } else { xresolution = resolution; } /* for the given resolution, search for master * sensor mode setting */ i = 0; nb = sizeof (sensor_master) / sizeof (Sensor_Master); while (i < nb) { if (dev->model->ccd_type == sensor_master[i].sensor && sensor_master[i].dpi == xresolution && sensor_master[i].color == color) { sensor = &sensor_master[i]; } i++; } if (sensor == NULL) { DBG (DBG_error, "gl646_setup_registers: unable to find settings for sensor %d at %d dpi color=%d\n", dev->model->ccd_type, xresolution, color); return SANE_STATUS_INVAL; } /* for the given resolution, search for master * motor mode setting */ i = 0; nb = sizeof (motor_master) / sizeof (Motor_Master); while (i < nb) { if (dev->model->motor_type == motor_master[i].motor && motor_master[i].dpi == resolution && motor_master[i].color == color) { motor = &motor_master[i]; } i++; } if (motor == NULL) { DBG (DBG_error, "gl646_setup_registers: unable to find settings for motor %d at %d dpi, color=%d\n", dev->model->motor_type, resolution, color); return SANE_STATUS_INVAL; } /* now we can search for the specific sensor settings */ i = 0; nb = sizeof (sensor_settings) / sizeof (Sensor_Settings); while (i < nb) { if (sensor->sensor == sensor_settings[i].sensor && sensor->cksel == sensor_settings[i].cksel) { settings = &sensor_settings[i]; } i++; } if (settings == NULL) { DBG (DBG_error, "gl646_setup_registers: unable to find settings for sensor %d with '%d' ccd timing\n", sensor->sensor, sensor->cksel); return SANE_STATUS_INVAL; } /* half_ccd if manual clock programming or dpi is half dpiset */ half_ccd = sensor->half_ccd; /* now apply values from settings to registers */ if (sensor->regs_0x10_0x15 != NULL) { for (i = 0; i < 6; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); r->value = sensor->regs_0x10_0x15[i]; } } else { for (i = 0; i < 6; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); r->value = 0; } } for (i = 0; i < 4; i++) { r = sanei_genesys_get_address (regs, 0x08 + i); if (half_ccd == SANE_TRUE) r->value = settings->manual_0x08_0x0b[i]; else r->value = settings->regs_0x08_0x0b[i]; } for (i = 0; i < 8; i++) { r = sanei_genesys_get_address (regs, 0x16 + i); r->value = settings->regs_0x16_0x1d[i]; } for (i = 0; i < 13; i++) { r = sanei_genesys_get_address (regs, 0x52 + i); r->value = settings->regs_0x52_0x5e[i]; } if (half_ccd == SANE_TRUE) { for (i = 0; i < 7; i++) { r = sanei_genesys_get_address (regs, 0x52 + i); r->value = settings->manual_0x52_0x58[i]; } } /* now generate slope tables : we are not using generate_slope_table3 yet */ sanei_genesys_generate_slope_table (slope_table1, motor->steps1, motor->steps1 + 1, motor->vend1, motor->vstart1, motor->vend1, motor->steps1, motor->g1, &used1, &vfinal); sanei_genesys_generate_slope_table (slope_table2, motor->steps2, motor->steps2 + 1, motor->vend2, motor->vstart2, motor->vend2, motor->steps2, motor->g2, &used2, &vfinal); if (color == SANE_TRUE) channels = 3; else channels = 1; /* R01 */ /* now setup other registers for final scan (ie with shading enabled) */ /* watch dog + shading + scan enable */ regs[reg_0x01].value |= REG01_DOGENB | REG01_DVDSET | REG01_SCAN; if (dev->model->is_cis == SANE_TRUE) regs[reg_0x01].value |= REG01_CISSET; else regs[reg_0x01].value &= ~REG01_CISSET; /* if device has no calibration, don't enable shading correction */ if (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION) { regs[reg_0x01].value &= ~REG01_DVDSET; } regs[reg_0x01].value &= ~REG01_FASTMOD; if (motor->fastmod) regs[reg_0x01].value |= REG01_FASTMOD; /* R02 */ /* allow moving when buffer full by default */ if (dev->model->is_sheetfed == SANE_FALSE) dev->reg[reg_0x02].value &= ~REG02_ACDCDIS; else dev->reg[reg_0x02].value |= REG02_ACDCDIS; /* setup motor power and direction */ regs[reg_0x02].value |= REG02_MTRPWR; regs[reg_0x02].value &= ~REG02_MTRREV; /* fastfed enabled (2 motor slope tables) */ if (motor->fastfed) regs[reg_0x02].value |= REG02_FASTFED; else regs[reg_0x02].value &= ~REG02_FASTFED; /* step type */ regs[reg_0x02].value &= ~REG02_STEPSEL; switch (motor->steptype) { case FULL_STEP: break; case HALF_STEP: regs[reg_0x02].value |= 1; break; case QUATER_STEP: regs[reg_0x02].value |= 2; break; default: regs[reg_0x02].value |= 3; break; } /* if sheetfed, no AGOHOME */ if (dev->model->is_sheetfed == SANE_TRUE) { regs[reg_0x02].value &= ~REG02_AGOHOME; } else { regs[reg_0x02].value |= REG02_AGOHOME; } /* R03 */ regs[reg_0x03].value &= ~REG03_AVEENB; /* regs[reg_0x03].value |= REG03_AVEENB; */ regs[reg_0x03].value &= ~REG03_LAMPDOG; /* select XPA */ regs[reg_0x03].value &= ~REG03_XPASEL; if (scan_settings.scan_method == SCAN_METHOD_TRANSPARENCY) { regs[reg_0x03].value |= REG03_XPASEL; } /* R04 */ /* monochrome / color scan */ switch (depth) { case 1: regs[reg_0x04].value &= ~REG04_BITSET; regs[reg_0x04].value |= REG04_LINEART; break; case 8: regs[reg_0x04].value &= ~(REG04_LINEART | REG04_BITSET); break; case 16: regs[reg_0x04].value &= ~REG04_LINEART; regs[reg_0x04].value |= REG04_BITSET; break; } /* R05 */ regs[reg_0x05].value &= ~REG05_DPIHW; switch (dev->sensor.optical_res) { case 600: regs[reg_0x05].value |= REG05_DPIHW_600; break; case 1200: regs[reg_0x05].value |= REG05_DPIHW_1200; break; case 2400: regs[reg_0x05].value |= REG05_DPIHW_2400; break; default: regs[reg_0x05].value |= REG05_DPIHW; } /* gamma enable for scans */ if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) regs[reg_0x05].value |= REG05_GMM14BIT; regs[reg_0x05].value &= ~REG05_GMMENB; /* true CIS gray if needed */ if (dev->model->is_cis == SANE_TRUE && color == SANE_FALSE && dev->settings.true_gray) { regs[reg_0x05].value |= REG05_LEDADD; } else { regs[reg_0x05].value &= ~REG05_LEDADD; } /* cktoggle, ckdelay and cksel at once, cktdelay=2 => half_ccd for md5345 */ regs[reg_0x18].value = sensor->r18; /* manual CCD/2 clock programming => half_ccd for hp2300 */ regs[reg_0x1d].value = sensor->r1d; /* HP2400 1200dpi mode tuning */ if (dev->model->ccd_type == CCD_HP2400) { /* reset count of dummy lines to zero */ regs[reg_0x1e].value &= ~REG1E_LINESEL; if (scan_settings.xres >= 1200) { /* there must be one dummy line */ regs[reg_0x1e].value |= 1 & REG1E_LINESEL; /* GPO12 need to be set to zero */ regs[reg_0x66].value &= ~0x20; } else { /* set GPO12 back to one */ regs[reg_0x66].value |= 0x20; } } /* motor steps used */ regs[reg_0x21].value = motor->steps1; regs[reg_0x22].value = motor->fwdbwd; regs[reg_0x23].value = motor->fwdbwd; regs[reg_0x24].value = motor->steps1; /* scanned area height must be enlarged by max color shift needed */ max_shift=sanei_genesys_compute_max_shift(dev,channels,scan_settings.yres,0); /* we adjust linecnt according to real motor dpi */ linecnt = (linecnt * motor->ydpi) / scan_settings.yres + max_shift; /* at QUATER_STEP lines are 'staggered' and need correction */ stagger = 0; if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) { /* for HP3670, stagger happens only at >=1200 dpi */ if ((dev->model->motor_type != MOTOR_HP3670 && dev->model->motor_type != MOTOR_HP2400) || scan_settings.yres >= dev->sensor.optical_res) { stagger = (4 * scan_settings.yres) / dev->motor.base_ydpi; } } linecnt += stagger; DBG (DBG_info, "gl646_setup_registers : max_shift=%d, stagger=%d lines\n", max_shift, stagger); /* CIS scanners read one line per color channel * since gray mode use 'add' we also read 3 channels even not in * color mode */ if (dev->model->is_cis == SANE_TRUE) { gl646_set_triple_reg (regs, REG_LINCNT, linecnt * 3); linecnt *= channels; } else { gl646_set_triple_reg (regs, REG_LINCNT, linecnt); } /* scanner's x coordinates are expressed in physical DPI but they must be divided by cksel */ sx = startx / sensor->cksel; ex = endx / sensor->cksel; if (half_ccd == SANE_TRUE) { sx /= 2; ex /= 2; } gl646_set_double_reg (regs, REG_STRPIXEL, sx); gl646_set_double_reg (regs, REG_ENDPIXEL, ex); DBG (DBG_info, "gl646_setup_registers: startx=%d, endx=%d, half_ccd=%d\n", sx, ex, half_ccd); /* words_per_line must be computed according to the scan's resolution */ /* in fact, words_per_line _gives_ the actual scan resolution */ words_per_line = (((endx - startx) * sensor->xdpi) / dev->sensor.optical_res); bpp=depth/8; if (depth == 1) { words_per_line = (words_per_line+7)/8 ; bpp=1; } else { words_per_line *= bpp; } dev->bpl = words_per_line; words_per_line *= channels; dev->wpl = words_per_line; DBG (DBG_info, "gl646_setup_registers: wpl=%d\n", words_per_line); gl646_set_triple_reg (regs, REG_MAXWD, words_per_line); gl646_set_double_reg (regs, REG_DPISET, sensor->dpiset); gl646_set_double_reg (regs, REG_LPERIOD, sensor->exposure); /* move distance must be adjusted to take into account the extra lines * read to reorder data */ feedl = move; if (stagger + max_shift > 0 && feedl != 0) { if (feedl > ((max_shift + stagger) * dev->motor.optical_ydpi) / motor->ydpi) feedl = feedl - ((max_shift + stagger) * dev->motor.optical_ydpi) / motor->ydpi; } /* we assume all scans are done with 2 tables */ /* feedl = feed_steps - fast_slope_steps*2 - (slow_slope_steps >> scan_step_type); */ /* but head has moved due to shading calibration => dev->scanhead_position_in_steps */ if (feedl > 0) { /* take into account the distance moved during calibration */ /* feedl -= dev->scanhead_position_in_steps; */ DBG (DBG_info, "gl646_setup_registers: initial move=%d\n", feedl); DBG (DBG_info, "gl646_setup_registers: scanhead_position_in_steps=%d\n", dev->scanhead_position_in_steps); /* TODO clean up this when I'll fully understand. * for now, special casing each motor */ switch (dev->model->motor_type) { case MOTOR_5345: switch (motor->ydpi) { case 200: feedl -= 70; break; case 300: feedl -= 70; break; case 400: feedl += 130; break; case 600: feedl += 160; break; case 1200: feedl += 160; break; case 2400: feedl += 180; break; default: break; } break; case MOTOR_HP2300: switch (motor->ydpi) { case 75: feedl -= 180; break; case 150: feedl += 0; break; case 300: feedl += 30; break; case 600: feedl += 35; break; case 1200: feedl += 45; break; default: break; } break; case MOTOR_HP2400: switch (motor->ydpi) { case 150: feedl += 150; break; case 300: feedl += 220; break; case 600: feedl += 260; break; case 1200: feedl += 280; /* 300 */ break; case 50: feedl += 0; break; case 100: feedl += 100; break; default: break; } break; /* theorical value */ default: if (motor->fastfed) { feedl = feedl - 2 * motor->steps2 - (motor->steps1 >> motor->steptype); } else { feedl = feedl - (motor->steps1 >> motor->steptype); } break; } /* security */ if (feedl < 0) feedl = 0; } DBG (DBG_info, "gl646_setup_registers: final move=%d\n", feedl); gl646_set_triple_reg (regs, REG_FEEDL, feedl); regs[reg_0x65].value = motor->mtrpwm; sanei_genesys_calculate_zmode2 (regs[reg_0x02].value & REG02_FASTFED, sensor->exposure, slope_table1, motor->steps1, move, motor->fwdbwd, &z1, &z2); /* no z1/z2 for sheetfed scanners */ if (dev->model->is_sheetfed == SANE_TRUE) { z1 = 0; z2 = 0; } gl646_set_double_reg (regs, REG_Z1MOD, z1); gl646_set_double_reg (regs, REG_Z2MOD, z2); regs[reg_0x6b].value = motor->steps2; regs[reg_0x6c].value = (regs[reg_0x6c].value & REG6C_TGTIME) | ((z1 >> 13) & 0x38) | ((z2 >> 16) & 0x07); RIE (write_control (dev, xresolution)); /* setup analog frontend */ RIE (gl646_set_fe (dev, AFE_SET, xresolution)); /* now we're done with registers setup values used by data transfer */ /* we setup values needed for the data transfer */ /* we must use a round number of words_per_line */ requested_buffer_size = 8 * words_per_line; read_buffer_size = 2 * requested_buffer_size + ((max_shift + stagger) * scan_settings.pixels * channels * depth) / 8; RIE (sanei_genesys_buffer_free (&(dev->read_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->lines_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer), requested_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->out_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer), 8 * scan_settings.pixels * channels * bpp)); /* scan bytes to read */ dev->read_bytes_left = words_per_line * linecnt; DBG (DBG_info, "gl646_setup_registers: physical bytes to read = %lu\n", (u_long) dev->read_bytes_left); dev->read_active = SANE_TRUE; dev->current_setup.pixels = ((endx - startx) * sensor->xdpi) / dev->sensor.optical_res; dev->current_setup.lines = linecnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = sensor->exposure; dev->current_setup.xres = sensor->xdpi; dev->current_setup.yres = motor->ydpi; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; /* total_bytes_to_read is the number of byte to send to frontend * total_bytes_read is the number of bytes sent to frontend * read_bytes_left is the number of bytes to read from the scanner */ dev->total_bytes_read = 0; if (depth == 1) dev->total_bytes_to_read = ((scan_settings.pixels * scan_settings.lines) / 8 + (((scan_settings.pixels * scan_settings.lines) % 8) ? 1 : 0)) * channels; else dev->total_bytes_to_read = scan_settings.pixels * scan_settings.lines * channels * bpp; DBG (DBG_proc, "gl646_setup_registers: end\n"); return SANE_STATUS_GOOD; } /** copy sensor specific settings */ /* *dev : device infos *regs : regiters to be set extended : do extended set up half_ccd: set up for half ccd resolution all registers 08-0B, 10-1D, 52-5E are set up. They shouldn't appear anywhere else but in register init */ static void gl646_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs) { Genesys_Register_Set *r; int i; DBG (DBG_proc, "gl646_setup_sensor: start\n"); for (i = 0; i < 4; i++) { r = sanei_genesys_get_address (regs, 0x08 + i); r->value = dev->sensor.regs_0x08_0x0b[i]; } for (i = 0; i < 14; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); r->value = dev->sensor.regs_0x10_0x1d[i]; } for (i = 0; i < 13; i++) { r = sanei_genesys_get_address (regs, 0x52 + i); r->value = dev->sensor.regs_0x52_0x5e[i]; } DBG (DBG_proc, "gl646_setup_sensor: end\n"); } /** Test if the ASIC works */ static SANE_Status gl646_asic_test (Genesys_Device * dev) { SANE_Status status; uint8_t val; uint8_t *data; uint8_t *verify_data; size_t size, verify_size; unsigned int i; DBG (DBG_proc, "gl646_asic_test: start\n"); /* set and read exposure time, compare if it's the same */ status = sanei_genesys_write_register (dev, 0x38, 0xde); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_asic_test: failed to write register: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_write_register (dev, 0x39, 0xad); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_asic_test: failed to write register: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_read_register (dev, 0x4e, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_asic_test: failed to read register: %s\n", sane_strstatus (status)); return status; } if (val != 0xde) /* value of register 0x38 */ { DBG (DBG_error, "gl646_asic_test: register contains invalid value\n"); return SANE_STATUS_IO_ERROR; } status = sanei_genesys_read_register (dev, 0x4f, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_asic_test: failed to read register: %s\n", sane_strstatus (status)); return status; } if (val != 0xad) /* value of register 0x39 */ { DBG (DBG_error, "gl646_asic_test: register contains invalid value\n"); return SANE_STATUS_IO_ERROR; } /* ram test: */ size = 0x40000; verify_size = size + 0x80; /* todo: looks like the read size must be a multiple of 128? otherwise the read doesn't succeed the second time after the scanner has been plugged in. Very strange. */ data = (uint8_t *) malloc (size); if (!data) { DBG (DBG_error, "gl646_asic_test: could not allocate memory\n"); return SANE_STATUS_NO_MEM; } verify_data = (uint8_t *) malloc (verify_size); if (!verify_data) { free (data); DBG (DBG_error, "gl646_asic_test: could not allocate memory\n"); return SANE_STATUS_NO_MEM; } for (i = 0; i < (size - 1); i += 2) { data[i] = i / 512; data[i + 1] = (i / 2) % 256; } status = sanei_genesys_set_buffer_address (dev, 0x0000); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_asic_test: failed to set buffer address: %s\n", sane_strstatus (status)); free (data); free (verify_data); return status; } status = gl646_bulk_write_data (dev, 0x3c, data, size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_asic_test: failed to bulk write data: %s\n", sane_strstatus (status)); free (data); free (verify_data); return status; } status = sanei_genesys_set_buffer_address (dev, 0x0000); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_asic_test: failed to set buffer address: %s\n", sane_strstatus (status)); free (data); free (verify_data); return status; } status = gl646_bulk_read_data (dev, 0x45, (uint8_t *) verify_data, verify_size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_asic_test: failed to bulk read data: %s\n", sane_strstatus (status)); free (data); free (verify_data); return status; } /* i + 2 is needed as the changed address goes into effect only after one data word is sent. */ for (i = 0; i < size; i++) { if (verify_data[i + 2] != data[i]) { DBG (DBG_error, "gl646_asic_test: data verification error\n"); free (data); free (verify_data); return SANE_STATUS_IO_ERROR; } } free (data); free (verify_data); DBG (DBG_info, "gl646_asic_test: end\n"); return SANE_STATUS_GOOD; } /* returns the max register bulk size */ static int gl646_bulk_full_size (void) { return GENESYS_GL646_MAX_REGS; } /** * Set all registers to default values after init * @param dev scannerr's device to set */ static void gl646_init_regs (Genesys_Device * dev) { int nr, addr; DBG (DBG_proc, "gl646_init_regs\n"); nr = 0; memset (dev->reg, 0, GENESYS_MAX_REGS * sizeof (Genesys_Register_Set)); for (addr = 1; addr <= 0x0b; addr++) dev->reg[nr++].address = addr; for (addr = 0x10; addr <= 0x29; addr++) dev->reg[nr++].address = addr; for (addr = 0x2c; addr <= 0x39; addr++) dev->reg[nr++].address = addr; for (addr = 0x3d; addr <= 0x3f; addr++) dev->reg[nr++].address = addr; for (addr = 0x52; addr <= 0x5e; addr++) dev->reg[nr++].address = addr; for (addr = 0x60; addr <= 0x6d; addr++) dev->reg[nr++].address = addr; dev->reg[reg_0x01].value = 0x20 /*0x22 */ ; /* enable shading, CCD, color, 1M */ dev->reg[reg_0x02].value = 0x30 /*0x38 */ ; /* auto home, one-table-move, full step */ if (dev->model->motor_type == MOTOR_5345) dev->reg[reg_0x02].value |= 0x01; /* half-step */ switch (dev->model->motor_type) { case MOTOR_5345: dev->reg[reg_0x02].value |= 0x01; /* half-step */ break; case MOTOR_XP200: /* for this sheetfed scanner, no AGOHOME, nor backtracking */ dev->reg[reg_0x02].value = 0x50; break; default: break; } dev->reg[reg_0x03].value = 0x1f /*0x17 */ ; /* lamp on */ dev->reg[reg_0x04].value = 0x13 /*0x03 */ ; /* 8 bits data, 16 bits A/D, color, Wolfson fe *//* todo: according to spec, 0x0 is reserved? */ switch (dev->model->dac_type) { case DAC_AD_XP200: dev->reg[reg_0x04].value = 0x12; break; default: /* Wolfson frontend */ dev->reg[reg_0x04].value = 0x13; break; } dev->reg[reg_0x05].value = 0x00; /* 12 bits gamma, disable gamma, 24 clocks/pixel */ switch (dev->sensor.optical_res) { case 600: dev->reg[reg_0x05].value |= REG05_DPIHW_600; break; case 1200: dev->reg[reg_0x05].value |= REG05_DPIHW_1200; break; case 2400: dev->reg[reg_0x05].value |= REG05_DPIHW_2400; break; default: dev->reg[reg_0x05].value |= REG05_DPIHW; break; } if (dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) dev->reg[reg_0x05].value |= REG05_GMM14BIT; if (dev->model->dac_type == DAC_AD_XP200) dev->reg[reg_0x05].value |= 0x01; /* 12 clocks/pixel */ if (dev->model->ccd_type == CCD_HP2300) dev->reg[reg_0x06].value = 0x00; /* PWRBIT off, shading gain=4, normal AFE image capture */ else dev->reg[reg_0x06].value = 0x18; /* PWRBIT on, shading gain=8, normal AFE image capture */ gl646_setup_sensor (dev, dev->reg); dev->reg[reg_0x1e].value = 0xf0; /* watch-dog time */ switch (dev->model->ccd_type) { case CCD_HP2300: dev->reg[reg_0x1e].value = 0xf0; dev->reg[reg_0x1f].value = 0x10; dev->reg[reg_0x20].value = 0x20; break; case CCD_HP2400: dev->reg[reg_0x1e].value = 0x80; dev->reg[reg_0x1f].value = 0x10; dev->reg[reg_0x20].value = 0x20; break; case CCD_HP3670: dev->reg[reg_0x19].value = 0x2a; dev->reg[reg_0x1e].value = 0x80; dev->reg[reg_0x1f].value = 0x10; dev->reg[reg_0x20].value = 0x20; break; case CIS_XP200: dev->reg[reg_0x1e].value = 0x10; dev->reg[reg_0x1f].value = 0x01; dev->reg[reg_0x20].value = 0x50; break; default: dev->reg[reg_0x1f].value = 0x01; dev->reg[reg_0x20].value = 0x50; break; } dev->reg[reg_0x21].value = 0x08 /*0x20 */ ; /* table one steps number for forward slope curve of the acc/dec */ dev->reg[reg_0x22].value = 0x10 /*0x08 */ ; /* steps number of the forward steps for start/stop */ dev->reg[reg_0x23].value = 0x10 /*0x08 */ ; /* steps number of the backward steps for start/stop */ dev->reg[reg_0x24].value = 0x08 /*0x20 */ ; /* table one steps number backward slope curve of the acc/dec */ dev->reg[reg_0x25].value = 0x00; /* scan line numbers (7000) */ dev->reg[reg_0x26].value = 0x00 /*0x1b */ ; dev->reg[reg_0x27].value = 0xd4 /*0x58 */ ; dev->reg[reg_0x28].value = 0x01; /* PWM duty for lamp control */ dev->reg[reg_0x29].value = 0xff; dev->reg[reg_0x2c].value = 0x02; /* set resolution (600 DPI) */ dev->reg[reg_0x2d].value = 0x58; dev->reg[reg_0x2e].value = 0x78; /* set black&white threshold high level */ dev->reg[reg_0x2f].value = 0x7f; /* set black&white threshold low level */ dev->reg[reg_0x30].value = 0x00; /* begin pixel position (16) */ dev->reg[reg_0x31].value = dev->sensor.dummy_pixel /*0x10 */ ; /* TGW + 2*TG_SHLD + x */ dev->reg[reg_0x32].value = 0x2a /*0x15 */ ; /* end pixel position (5390) */ dev->reg[reg_0x33].value = 0xf8 /*0x0e */ ; /* TGW + 2*TG_SHLD + y */ dev->reg[reg_0x34].value = dev->sensor.dummy_pixel; dev->reg[reg_0x35].value = 0x01 /*0x00 */ ; /* set maximum word size per line, for buffer full control (10800) */ dev->reg[reg_0x36].value = 0x00 /*0x2a */ ; dev->reg[reg_0x37].value = 0x00 /*0x30 */ ; dev->reg[reg_0x38].value = HIBYTE (dev->settings.exposure_time) /*0x2a */ ; /* line period (exposure time = 11000 pixels) */ dev->reg[reg_0x39].value = LOBYTE (dev->settings.exposure_time) /*0xf8 */ ; dev->reg[reg_0x3d].value = 0x00; /* set feed steps number of motor move */ dev->reg[reg_0x3e].value = 0x00; dev->reg[reg_0x3f].value = 0x01 /*0x00 */ ; dev->reg[reg_0x60].value = 0x00; /* Z1MOD, 60h:61h:(6D b5:b3), remainder for start/stop */ dev->reg[reg_0x61].value = 0x00; /* (21h+22h)/LPeriod */ dev->reg[reg_0x62].value = 0x00; /* Z2MODE, 62h:63h:(6D b2:b0), remainder for start scan */ dev->reg[reg_0x63].value = 0x00; /* (3Dh+3Eh+3Fh)/LPeriod for one-table mode,(21h+1Fh)/LPeriod */ dev->reg[reg_0x64].value = 0x00; /* motor PWM frequency */ dev->reg[reg_0x65].value = 0x00; /* PWM duty cycle for table one motor phase (63 = max) */ if (dev->model->motor_type == MOTOR_5345) dev->reg[reg_0x65].value = 0x02; /* PWM duty cycle for table one motor phase (63 = max) */ dev->reg[reg_0x66].value = dev->gpo.value[0]; dev->reg[reg_0x67].value = dev->gpo.value[1]; dev->reg[reg_0x68].value = dev->gpo.enable[0]; dev->reg[reg_0x69].value = dev->gpo.enable[1]; switch (dev->model->motor_type) { case MOTOR_HP2300: case MOTOR_HP2400: dev->reg[reg_0x6a].value = 0x7f; /* table two steps number for acc/dec */ dev->reg[reg_0x6b].value = 0x78; /* table two steps number for acc/dec */ dev->reg[reg_0x6d].value = 0x7f; break; case MOTOR_5345: dev->reg[reg_0x6a].value = 0x42; /* table two fast moving step type, PWM duty for table two */ dev->reg[reg_0x6b].value = 0xff; /* table two steps number for acc/dec */ dev->reg[reg_0x6d].value = 0x41; /* select deceleration steps whenever go home (0), accel/decel stop time (31 * LPeriod) */ break; case MOTOR_XP200: dev->reg[reg_0x6a].value = 0x7f; /* table two fast moving step type, PWM duty for table two */ dev->reg[reg_0x6b].value = 0x08; /* table two steps number for acc/dec */ dev->reg[reg_0x6d].value = 0x01; /* select deceleration steps whenever go home (0), accel/decel stop time (31 * LPeriod) */ break; case MOTOR_HP3670: dev->reg[reg_0x6a].value = 0x41; /* table two steps number for acc/dec */ dev->reg[reg_0x6b].value = 0xc8; /* table two steps number for acc/dec */ dev->reg[reg_0x6d].value = 0x7f; break; default: dev->reg[reg_0x6a].value = 0x40; /* table two fast moving step type, PWM duty for table two */ dev->reg[reg_0x6b].value = 0xff; /* table two steps number for acc/dec */ dev->reg[reg_0x6d].value = 0x01; /* select deceleration steps whenever go home (0), accel/decel stop time (31 * LPeriod) */ break; } dev->reg[reg_0x6c].value = 0x00; /* peroid times for LPeriod, expR,expG,expB, Z1MODE, Z2MODE (one period time) */ } /* Send slope table for motor movement slope_table in machine byte order */ static SANE_Status gl646_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps) { int dpihw; int start_address; SANE_Status status; uint8_t *table; #ifdef WORDS_BIGENDIAN int i; #endif DBG (DBG_proc, "gl646_send_slope_table (table_nr = %d, steps = %d)=%d .. %d\n", table_nr, steps, slope_table[0], slope_table[steps - 1]); dpihw = dev->reg[reg_0x05].value >> 6; if (dpihw == 0) /* 600 dpi */ start_address = 0x08000; else if (dpihw == 1) /* 1200 dpi */ start_address = 0x10000; else if (dpihw == 2) /* 2400 dpi */ start_address = 0x1f800; else /* reserved */ return SANE_STATUS_INVAL; #ifdef WORDS_BIGENDIAN table = (uint8_t *) malloc (steps * 2); for (i = 0; i < steps; i++) { table[i * 2] = slope_table[i] & 0xff; table[i * 2 + 1] = slope_table[i] >> 8; } #else table = (uint8_t *) slope_table; #endif status = sanei_genesys_set_buffer_address (dev, start_address + table_nr * 0x100); if (status != SANE_STATUS_GOOD) { #ifdef WORDS_BIGENDIAN free (table); #endif DBG (DBG_error, "gl646_send_slope_table: failed to set buffer address: %s\n", sane_strstatus (status)); return status; } status = gl646_bulk_write_data (dev, 0x3c, (uint8_t *) table, steps * 2); if (status != SANE_STATUS_GOOD) { #ifdef WORDS_BIGENDIAN free (table); #endif DBG (DBG_error, "gl646_send_slope_table: failed to send slope table: %s\n", sane_strstatus (status)); return status; } #ifdef WORDS_BIGENDIAN free (table); #endif DBG (DBG_proc, "gl646_send_slope_table: end\n"); return status; } /* Set values of Analog Device type frontend */ static SANE_Status gl646_set_ad_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status = SANE_STATUS_GOOD; int i; uint16_t val; DBG (DBG_proc, "gl646_set_ad_fe(): start\n"); if (set == AFE_INIT) { DBG (DBG_proc, "gl646_set_ad_fe(): setting DAC %u\n", dev->model->dac_type); /* sets to default values */ sanei_genesys_init_fe (dev); /* write them to analog frontend */ val = dev->frontend.reg[0]; status = sanei_genesys_fe_write_data (dev, 0x00, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_ad_fe: failed to write reg0: %s\n", sane_strstatus (status)); return status; } val = dev->frontend.reg[1]; status = sanei_genesys_fe_write_data (dev, 0x01, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_ad_fe: failed to write reg1: %s\n", sane_strstatus (status)); return status; } } if (set == AFE_SET) { for (i = 0; i < 3; i++) { val = dev->frontend.gain[i]; status = sanei_genesys_fe_write_data (dev, 0x02 + i, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_ad_fe: failed to write gain %d: %s\n", i, sane_strstatus (status)); return status; } } for (i = 0; i < 3; i++) { val = dev->frontend.offset[i]; status = sanei_genesys_fe_write_data (dev, 0x05 + i, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_ad_fe: failed to write offset %d: %s\n", i, sane_strstatus (status)); return status; } } } /* if (set == AFE_POWER_SAVE) { status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0] | 0x04); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_ad_fe: failed to write reg0: %s\n", sane_strstatus (status)); return status; } } */ DBG (DBG_proc, "gl646_set_ad_fe(): end\n"); return status; } /** set up analog frontend * set up analog frontend * @param dev device to set up * @param set action from AFE_SET, AFE_INIT and AFE_POWERSAVE * @param dpi resolution of the scan since it affects settings * @return SANE_STATUS_GOOD if evrithing OK */ static SANE_Status gl646_wm_hp3670 (Genesys_Device * dev, uint8_t set, int dpi) { SANE_Status status = SANE_STATUS_GOOD; int i; DBGSTART; switch (set) { case AFE_INIT: status = sanei_genesys_fe_write_data (dev, 0x04, 0x80); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: reset failed: %s\n", sane_strstatus (status)); return status; } usleep (200000UL); RIE (sanei_genesys_write_register (dev, 0x50, 0x00)); sanei_genesys_init_fe (dev); status = sanei_genesys_fe_write_data (dev, 0x01, dev->frontend.reg[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: writing reg1 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x02, dev->frontend.reg[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: writing reg2 failed: %s\n", sane_strstatus (status)); return status; } status = gl646_gpio_output_enable (dev->dn, 0x07); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: failed to enable GPIO: %s\n", sane_strstatus (status)); return status; } break; case AFE_POWER_SAVE: status = sanei_genesys_fe_write_data (dev, 0x01, 0x06); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: writing reg1 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x06, 0x0f); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: writing reg6 failed: %s\n", sane_strstatus (status)); return status; } return status; break; default: /* AFE_SET */ /* mode setup */ i = dev->frontend.reg[3]; if (dpi > dev->sensor.optical_res / 2) { /* fe_reg_0x03 must be 0x12 for 1200 dpi in DAC_WOLFSON_HP3670. * DAC_WOLFSON_HP2400 in 1200 dpi mode works well with * fe_reg_0x03 set to 0x32 or 0x12 but not to 0x02 */ i = 0x12; } status = sanei_genesys_fe_write_data (dev, 0x03, i); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: writing reg3 failed: %s\n", sane_strstatus (status)); return status; } /* offset and sign (or msb/lsb ?) */ for (i = 0; i < 3; i++) { status = sanei_genesys_fe_write_data (dev, 0x20 + i, dev->frontend.offset[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: writing offset%d failed: %s\n", i, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x24 + i, dev->frontend.sign[i]); /* MSB/LSB ? */ if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: writing sign%d failed: %s\n", i, sane_strstatus (status)); return status; } } /* gain */ for (i = 0; i < 3; i++) { status = sanei_genesys_fe_write_data (dev, 0x28 + i, dev->frontend.gain[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_wm_hp3670: writing gain%d failed: %s\n", i, sane_strstatus (status)); return status; } } } DBGCOMPLETED; return status; } /** Set values of analog frontend * @param dev device to set * @param set action to execute * @param dpi dpi to setup the AFE * @return error or SANE_STATUS_GOOD */ #ifndef UNIT_TESTING static #endif SANE_Status gl646_set_fe (Genesys_Device * dev, uint8_t set, int dpi) { SANE_Status status; int i; uint8_t val; DBG (DBG_proc, "gl646_set_fe (%s,%d)\n", set == AFE_INIT ? "init" : set == AFE_SET ? "set" : set == AFE_POWER_SAVE ? "powersave" : "huh?", dpi); /* Analog Device type frontend */ if ((dev->reg[reg_0x04].value & REG04_FESET) == 0x02) return gl646_set_ad_fe (dev, set); /* Wolfson type frontend */ if ((dev->reg[reg_0x04].value & REG04_FESET) != 0x03) { DBG (DBG_proc, "gl646_set_fe(): unsupported frontend type %d\n", dev->reg[reg_0x04].value & REG04_FESET); return SANE_STATUS_UNSUPPORTED; } /* per frontend function to keep code clean */ switch (dev->model->dac_type) { case DAC_WOLFSON_HP3670: case DAC_WOLFSON_HP2400: return gl646_wm_hp3670 (dev, set, dpi); break; default: DBG (DBG_proc, "gl646_set_fe(): using old method\n"); break; } /* initialize analog frontend */ if (set == AFE_INIT) { DBG (DBG_proc, "gl646_set_fe(): setting DAC %u\n", dev->model->dac_type); sanei_genesys_init_fe (dev); /* reset only done on init */ status = sanei_genesys_fe_write_data (dev, 0x04, 0x80); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: init fe failed: %s\n", sane_strstatus (status)); return status; } /* enable GPIO for some models */ if (dev->model->ccd_type == CCD_HP2300) { val = 0x07; status = gl646_gpio_output_enable (dev->dn, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: failed to enable GPIO: %s\n", sane_strstatus (status)); return status; } } return status; } /* set fontend to power saving mode */ if (set == AFE_POWER_SAVE) { status = sanei_genesys_fe_write_data (dev, 0x01, 0x02); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing data failed: %s\n", sane_strstatus (status)); } return status; } /* here starts AFE_SET */ /* TODO : base this test on cfg reg3 or a CCD family flag to be created */ /* if (dev->model->ccd_type != CCD_HP2300 && dev->model->ccd_type != CCD_HP3670 && dev->model->ccd_type != CCD_HP2400) */ { status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing reg0 failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x02, dev->frontend.reg[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing reg2 failed: %s\n", sane_strstatus (status)); return status; } } /* start with reg3 */ status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.reg[3]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing reg3 failed: %s\n", sane_strstatus (status)); return status; } switch (dev->model->ccd_type) { default: for (i = 0; i < 3; i++) { status = sanei_genesys_fe_write_data (dev, 0x24 + i, dev->frontend.sign[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing sign[%d] failed: %s\n", i, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x28 + i, dev->frontend.gain[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing gain[%d] failed: %s\n", i, sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x20 + i, dev->frontend.offset[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing offset[%d] failed: %s\n", i, sane_strstatus (status)); return status; } } break; /* just can't have it to work .... case CCD_HP2300: case CCD_HP2400: case CCD_HP3670: status = sanei_genesys_fe_write_data (dev, 0x23, dev->frontend.offset[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing offset[1] failed: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x28, dev->frontend.gain[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing gain[1] failed: %s\n", sane_strstatus (status)); return status; } break; */ } /* end with reg1 */ status = sanei_genesys_fe_write_data (dev, 0x01, dev->frontend.reg[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_set_fe: writing reg1 failed: %s\n", sane_strstatus (status)); return status; } DBG (DBG_proc, "gl646_set_fe: end\n"); return SANE_STATUS_GOOD; } /** Set values of analog frontend * this this the public interface, the gl646 as to use one more * parameter to work effectively, hence the redirection * @param dev device to set * @param set action to execute * @return error or SANE_STATUS_GOOD */ #ifndef UNIT_TESTING static #endif SANE_Status gl646_public_set_fe (Genesys_Device * dev, uint8_t set) { return gl646_set_fe (dev, set, dev->settings.yres); } static void gl646_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set) { if (set) { sanei_genesys_set_reg_from_set (regs, 0x02, sanei_genesys_read_reg_from_set (regs, 0x02) | REG02_MTRPWR); } else { sanei_genesys_set_reg_from_set (regs, 0x02, sanei_genesys_read_reg_from_set (regs, 0x02) & ~REG02_MTRPWR); } } static void gl646_set_lamp_power (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool set) { if (dev) { if (set) { sanei_genesys_set_reg_from_set (regs, 0x03, sanei_genesys_read_reg_from_set (regs, 0x03) | REG03_LAMPPWR); } else { sanei_genesys_set_reg_from_set (regs, 0x03, sanei_genesys_read_reg_from_set (regs, 0x03) & ~REG03_LAMPPWR); } } } /** * enters or leaves power saving mode * limited to AFE for now. * @param dev scanner's device * @param enable SANE_TRUE to enable power saving, SANE_FALSE to leave it * @return allways SANE_STATUS_GOOD */ GENESYS_STATIC SANE_Status gl646_save_power (Genesys_Device * dev, SANE_Bool enable) { DBGSTART; DBG (DBG_info, "gl646_save_power: enable = %d\n", enable); if (enable) { /* gl646_set_fe (dev, AFE_POWER_SAVE); */ } else { gl646_set_fe (dev, AFE_INIT, 0); } DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl646_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ ) { SANE_Status status = SANE_STATUS_GOOD; Genesys_Register_Set local_reg[6]; int rate, exposure_time, tgtime, time; DBG (DBG_proc, "gl646_set_powersaving (delay = %d)\n", delay); local_reg[0].address = 0x01; local_reg[0].value = sanei_genesys_read_reg_from_set (dev->reg, 0x01); /* disable fastmode */ local_reg[1].address = 0x03; local_reg[1].value = sanei_genesys_read_reg_from_set (dev->reg, 0x03); /* Lamp power control */ local_reg[2].address = 0x05; local_reg[2].value = sanei_genesys_read_reg_from_set (dev->reg, 0x05) & ~REG05_BASESEL; /* 24 clocks/pixel */ local_reg[3].address = 0x38; /* line period low */ local_reg[3].value = 0x00; local_reg[4].address = 0x39; /* line period high */ local_reg[4].value = 0x00; local_reg[5].address = 0x6c; /* period times for LPeriod, expR,expG,expB, Z1MODE, Z2MODE */ local_reg[5].value = 0x00; if (!delay) local_reg[1].value = local_reg[1].value & 0xf0; /* disable lampdog and set lamptime = 0 */ else if (delay < 20) local_reg[1].value = (local_reg[1].value & 0xf0) | 0x09; /* enable lampdog and set lamptime = 1 */ else local_reg[1].value = (local_reg[1].value & 0xf0) | 0x0f; /* enable lampdog and set lamptime = 7 */ time = delay * 1000 * 60; /* -> msec */ exposure_time = (uint32_t) (time * 32000.0 / (24.0 * 64.0 * (local_reg[1].value & REG03_LAMPTIM) * 1024.0) + 0.5); /* 32000 = system clock, 24 = clocks per pixel */ rate = (exposure_time + 65536) / 65536; if (rate > 4) { rate = 8; tgtime = 3; } else if (rate > 2) { rate = 4; tgtime = 2; } else if (rate > 1) { rate = 2; tgtime = 1; } else { rate = 1; tgtime = 0; } local_reg[5].value |= tgtime << 6; exposure_time /= rate; if (exposure_time > 65535) exposure_time = 65535; local_reg[3].value = exposure_time / 256; /* highbyte */ local_reg[4].value = exposure_time & 255; /* lowbyte */ status = gl646_bulk_write_register (dev, local_reg, sizeof (local_reg) / sizeof (local_reg[0])); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "gl646_set_powersaving: Failed to bulk write registers: %s\n", sane_strstatus (status)); DBG (DBG_proc, "gl646_set_powersaving: end\n"); return status; } /** * loads document into scanner * currently only used by XP200 * bit2 (0x04) of gpio is paper event (document in/out) on XP200 * HOMESNR is set if no document in front of sensor, the sequence of events is * paper event -> document is in the sheet feeder * HOMESNR becomes 0 -> document reach sensor * HOMESNR becomes 1 ->document left sensor * paper event -> document is out */ #ifndef UNIT_TESTING static #endif SANE_Status gl646_load_document (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; Genesys_Register_Set regs[11]; unsigned int used, vfinal, count; uint16_t slope_table[255]; uint8_t val; DBG (DBG_proc, "gl646_load_document: start\n"); /* no need to load document is flatbed scanner */ if (dev->model->is_sheetfed == SANE_FALSE) { DBG (DBG_proc, "gl646_load_document: nothing to load\n"); DBG (DBG_proc, "gl646_load_document: end\n"); return SANE_STATUS_GOOD; } status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_load_document: failed to read status: %s\n", sane_strstatus (status)); return status; } /* HOMSNR is set if a document is inserted */ if ((val & REG41_HOMESNR)) { /* if no document, waits for a paper event to start loading */ /* with a 60 seconde minutes timeout */ count = 0; do { status = gl646_gpio_read (dev->dn, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_load_document: failed to read paper sensor %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl646_load_document: GPIO=0x%02x\n", val); if ((val & 0x04) != 0x04) { DBG (DBG_warn, "gl646_load_document: no paper detected\n"); } usleep (200000UL); /* sleep 200 ms */ count++; } while (((val & 0x04) != 0x04) && (count < 300)); /* 1 min time out */ if (count == 300) { DBG (DBG_error, "gl646_load_document: timeout waiting for document\n"); return SANE_STATUS_NO_DOCS; } } /* set up to fast move before scan then move until document is detected */ regs[0].address = 0x01; regs[0].value = 0x90; /* AGOME, 2 slopes motor moving */ regs[1].address = 0x02; regs[1].value = 0x79; /* motor feeding steps to 0 */ regs[2].address = 0x3d; regs[2].value = 0; regs[3].address = 0x3e; regs[3].value = 0; regs[4].address = 0x3f; regs[4].value = 0; /* 50 fast moving steps */ regs[5].address = 0x6b; regs[5].value = 50; /* set GPO */ regs[6].address = 0x66; regs[6].value = 0x30; /* stesp NO */ regs[7].address = 0x21; regs[7].value = 4; regs[8].address = 0x22; regs[8].value = 1; regs[9].address = 0x23; regs[9].value = 1; regs[10].address = 0x24; regs[10].value = 4; /* generate slope table 2 */ sanei_genesys_generate_slope_table (slope_table, 50, 51, 2400, 6000, 2400, 50, 0.25, &used, &vfinal); /* document loading: * send regs * start motor * wait e1 status to become e0 */ status = gl646_send_slope_table (dev, 1, slope_table, 50); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_load_document: failed to send slope table 1: %s\n", sane_strstatus (status)); return status; } status = gl646_bulk_write_register (dev, regs, sizeof (regs) / sizeof (regs[0])); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_load_document: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } status = gl646_start_motor (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_load_document: failed to start motor: %s\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } count = 0; do { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_load_document: failed to read status: %s\n", sane_strstatus (status)); return status; } usleep (200000UL); /* sleep 200 ms */ count++; } while ((val & REG41_MOTMFLG) && (count < 300)); if (count == 300) { DBG (DBG_error, "gl646_load_document: can't load document\n"); return SANE_STATUS_JAMMED; } /* when loading OK, document is here */ dev->document = SANE_TRUE; /* set up to idle */ regs[1].value = 0x71; regs[4].value = 1; regs[5].value = 8; status = gl646_bulk_write_register (dev, regs, sizeof (regs) / sizeof (regs[0])); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_load_document: failed to bulk write idle registers: %s\n", sane_strstatus (status)); return status; } DBG (DBG_proc, "gl646_load_document: end\n"); return status; } /** * detects end of document and adjust current scan * to take it into account * used by sheetfed scanners */ static SANE_Status gl646_detect_document_end (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; uint8_t val, gpio; unsigned int bytes_left, lines; DBG (DBG_proc, "gl646_detect_document_end: start\n"); /* test for document presence */ RIE (sanei_genesys_get_status (dev, &val)); if (DBG_LEVEL > DBG_info) { print_status (val); } status = gl646_gpio_read (dev->dn, &gpio); DBG (DBG_info, "gl646_detect_document_end: GPIO=0x%02x\n", gpio); /* detect document event. There one event when the document go in, * then another when it leaves */ if ((dev->document == SANE_TRUE) && (gpio & 0x04) && (dev->total_bytes_read > 0)) { DBG (DBG_info, "gl646_detect_document_end: no more document\n"); dev->document = SANE_FALSE; /* adjust number of bytes to read: * total_bytes_to_read is the number of byte to send to frontend * total_bytes_read is the number of bytes sent to frontend * read_bytes_left is the number of bytes to read from the scanner */ DBG (DBG_io, "gl646_detect_document_end: total_bytes_to_read=%lu\n", (u_long) dev->total_bytes_to_read); DBG (DBG_io, "gl646_detect_document_end: total_bytes_read =%lu\n", (u_long) dev->total_bytes_read); DBG (DBG_io, "gl646_detect_document_end: read_bytes_left =%lu\n", (u_long) dev->read_bytes_left); /* amount of data available from scanner is what to scan */ status = sanei_genesys_read_valid_words (dev, &bytes_left); /* we add the number of lines needed to read the last part of the document in */ lines = (SANE_UNFIX (dev->model->y_offset) * dev->current_setup.yres) / MM_PER_INCH; DBG (DBG_io, "gl646_detect_document_end: adding %d line to flush\n", lines); bytes_left += lines * dev->wpl; if (dev->current_setup.depth > 8) { bytes_left = 2 * bytes_left; } if (dev->current_setup.channels > 1) { bytes_left = 3 * bytes_left; } if (bytes_left < dev->read_bytes_left) { dev->total_bytes_to_read = dev->total_bytes_read + bytes_left; dev->read_bytes_left = bytes_left; } DBG (DBG_io, "gl646_detect_document_end: total_bytes_to_read=%lu\n", (u_long) dev->total_bytes_to_read); DBG (DBG_io, "gl646_detect_document_end: total_bytes_read =%lu\n", (u_long) dev->total_bytes_read); DBG (DBG_io, "gl646_detect_document_end: read_bytes_left =%lu\n", (u_long) dev->read_bytes_left); } DBG (DBG_proc, "gl646_detect_document_end: end\n"); return status; } /** * eject document from the feeder * currently only used by XP200 * TODO we currently rely on AGOHOME not being set for sheetfed scanners, * maybe check this flag in eject to let the document being eject automaticaly */ static SANE_Status gl646_eject_document (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; Genesys_Register_Set regs[11]; unsigned int used, vfinal, count; uint16_t slope_table[255]; uint8_t gpio, state; DBG (DBG_proc, "gl646_eject_document: start\n"); /* at the end there will be noe more document */ dev->document = SANE_FALSE; /* first check for document event */ status = gl646_gpio_read (dev->dn, &gpio); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to read paper sensor %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl646_eject_document: GPIO=0x%02x\n", gpio); /* test status : paper event + HOMESNR -> no more doc ? */ status = sanei_genesys_get_status (dev, &state); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to read status: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl646_eject_document: state=0x%02x\n", state); if (DBG_LEVEL > DBG_info) { print_status (state); } /* HOMSNR=0 if no document inserted */ if ((state & REG41_HOMESNR) != 0) { dev->document = SANE_FALSE; DBG (DBG_info, "gl646_eject_document: no more document to eject\n"); DBG (DBG_proc, "gl646_eject_document: end\n"); return status; } /* there is a document inserted, eject it */ status = sanei_genesys_write_register (dev, 0x01, 0xb0); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to write register: %s\n", sane_strstatus (status)); return status; } /* wait for motor to stop */ do { usleep (200000UL); status = sanei_genesys_get_status (dev, &state); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to read status: %s\n", sane_strstatus (status)); return status; } } while (state & REG41_MOTMFLG); /* set up to fast move before scan then move until document is detected */ regs[0].address = 0x01; regs[0].value = 0xb0; /* AGOME, 2 slopes motor moving , eject 'backward' */ regs[1].address = 0x02; regs[1].value = 0x5d; /* motor feeding steps to 119880 */ regs[2].address = 0x3d; regs[2].value = 1; regs[3].address = 0x3e; regs[3].value = 0xd4; regs[4].address = 0x3f; regs[4].value = 0x48; /* 60 fast moving steps */ regs[5].address = 0x6b; regs[5].value = 60; /* set GPO */ regs[6].address = 0x66; regs[6].value = 0x30; /* stesp NO */ regs[7].address = 0x21; regs[7].value = 4; regs[8].address = 0x22; regs[8].value = 1; regs[9].address = 0x23; regs[9].value = 1; regs[10].address = 0x24; regs[10].value = 4; /* generate slope table 2 */ sanei_genesys_generate_slope_table (slope_table, 60, 61, 1600, 10000, 1600, 60, 0.25, &used, &vfinal); /* document eject: * send regs * start motor * wait c1 status to become c8 : HOMESNR and ~MOTFLAG */ status = gl646_send_slope_table (dev, 1, slope_table, 60); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to send slope table 1: %s\n", sane_strstatus (status)); return status; } status = gl646_bulk_write_register (dev, regs, sizeof (regs) / sizeof (regs[0])); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } status = gl646_start_motor (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to start motor: %s\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } /* loop until paper sensor tells paper is out, and till motor is running */ /* use a 30 timeout */ count = 0; do { status = sanei_genesys_get_status (dev, &state); print_status (state); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to read status: %s\n", sane_strstatus (status)); return status; } usleep (200000UL); /* sleep 200 ms */ count++; } while (((state & REG41_HOMESNR) == 0) && (count < 150)); /* read GPIO on exit */ status = gl646_gpio_read (dev->dn, &gpio); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_eject_document: failed to read paper sensor %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl646_eject_document: GPIO=0x%02x\n", gpio); DBG (DBG_proc, "gl646_eject_document: end\n"); return status; } /* Send the low-level scan command */ static SANE_Status gl646_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor) { SANE_Status status; Genesys_Register_Set local_reg[3]; DBG (DBG_proc, "gl646_begin_scan\n"); local_reg[0].address = 0x03; local_reg[0].value = sanei_genesys_read_reg_from_set (reg, 0x03); local_reg[1].address = 0x01; local_reg[1].value = sanei_genesys_read_reg_from_set (reg, 0x01) | REG01_SCAN; /* set scan bit */ local_reg[2].address = 0x0f; if (start_motor) local_reg[2].value = 0x01; else local_reg[2].value = 0x00; /* do not start motor yet */ status = gl646_bulk_write_register (dev, local_reg, sizeof (local_reg) / sizeof (local_reg[0])); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_begin_scan: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } DBG (DBG_proc, "gl646_begin_scan: end\n"); return status; } /* Send the stop scan command */ static SANE_Status end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop, SANE_Bool eject) { SANE_Status status = SANE_STATUS_GOOD; int i = 0; uint8_t val, scanfsh = 0; DBG (DBG_proc, "end_scan (check_stop = %d, eject = %d)\n", check_stop, eject); /* we need to compute scanfsh before cancelling scan */ if (dev->model->is_sheetfed == SANE_TRUE) { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "end_scan: failed to read register: %s\n", sane_strstatus (status)); return status; } if (val & REG41_SCANFSH) scanfsh = 1; if (DBG_LEVEL > DBG_io2) { print_status (val); } } /* ends scan */ val = sanei_genesys_read_reg_from_set (reg, 0x01); val &= ~REG01_SCAN; sanei_genesys_set_reg_from_set (reg, 0x01, val); status = sanei_genesys_write_register (dev, 0x01, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "end_scan: failed to write register 01: %s\n", sane_strstatus (status)); return status; } /* for sheetfed scanners, we may have to eject document */ if (dev->model->is_sheetfed == SANE_TRUE) { if (eject == SANE_TRUE && dev->document == SANE_TRUE) { status = gl646_eject_document (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "end_scan: failed to eject document\n"); return status; } } if (check_stop) { for (i = 0; i < 30; i++) /* do not wait longer than wait 3 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "end_scan: failed to read register: %s\n", sane_strstatus (status)); return status; } if (val & REG41_SCANFSH) scanfsh = 1; if (DBG_LEVEL > DBG_io2) { print_status (val); } if (!(val & REG41_MOTMFLG) && (val & REG41_FEEDFSH) && scanfsh) { DBG (DBG_proc, "end_scan: scanfeed finished\n"); break; /* leave for loop */ } usleep (10000UL); /* sleep 100 ms */ } } } else /* flat bed scanners */ { if (check_stop) { for (i = 0; i < 300; i++) /* do not wait longer than wait 30 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "end_scan: failed to read register: %s\n", sane_strstatus (status)); return status; } if (val & REG41_SCANFSH) scanfsh = 1; if (DBG_LEVEL > DBG_io) { print_status (val); } if (!(val & REG41_MOTMFLG) && (val & REG41_FEEDFSH) && scanfsh) { DBG (DBG_proc, "end_scan: scanfeed finished\n"); break; /* leave while loop */ } if ((!(val & REG41_MOTMFLG)) && (val & REG41_HOMESNR)) { DBG (DBG_proc, "end_scan: head at home\n"); break; /* leave while loop */ } usleep (10000UL); /* sleep 100 ms */ } } } DBG (DBG_proc, "end_scan: end (i=%u)\n", i); return status; } /* Send the stop scan command */ static SANE_Status gl646_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop) { return end_scan (dev, reg, check_stop, SANE_FALSE); } /** * parks head * @param dev scanner's device * @param wait_until_home true if the function waits until head parked */ GENESYS_STATIC SANE_Status gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) { SANE_Status status; Genesys_Settings settings; uint8_t val; int i; int loop = 0; DBG (DBG_proc, "gl646_slow_back_home: start , wait_until_home = %d\n", wait_until_home); status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL > DBG_io) { print_status (val); } dev->scanhead_position_in_steps = 0; if (val & REG41_HOMESNR) /* is sensor at home? */ { DBG (DBG_info, "gl646_slow_back_home: end since already at home\n"); return SANE_STATUS_GOOD; } /* stop motor if needed */ if (val & REG41_MOTMFLG) { status = gl646_stop_motor (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_slow_back_home: failed to stop motor: %s\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } usleep (200000UL); } /* when scanhead is moving then wait until scanhead stops or timeout */ DBG (DBG_info, "gl646_slow_back_home: ensuring that motor is off\n"); val = REG41_MOTMFLG; for (i = 400; i > 0 && (val & REG41_MOTMFLG); i--) /* do not wait longer than 40 seconds, count down to get i = 0 when busy */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_slow_back_home: Failed to read home sensor & motor status: %s\n", sane_strstatus (status)); return status; } if (((val & (REG41_MOTMFLG | REG41_HOMESNR)) == REG41_HOMESNR)) /* at home and motor is off */ { DBG (DBG_info, "gl646_slow_back_home: already at home and not moving\n"); return SANE_STATUS_GOOD; } usleep (100 * 1000); /* sleep 100 ms (todo: fixed to really sleep 100 ms) */ } if (!i) /* the loop counted down to 0, scanner still is busy */ { DBG (DBG_error, "gl646_slow_back_home: motor is still on: device busy\n"); return SANE_STATUS_DEVICE_BUSY; } /* setup for a backward scan of 65535 steps, with no actual data reading */ settings.scan_method = SCAN_METHOD_FLATBED; settings.scan_mode = SCAN_MODE_COLOR; settings.xres = get_lowest_resolution (dev->model->ccd_type, SANE_FALSE); settings.yres = settings.xres; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = 600; settings.lines = 1; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; status = setup_for_scan (dev, dev->reg, settings, SANE_TRUE, SANE_TRUE, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup for scan: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* backward , no actual data scanned TODO more setup flags to avoid this register manipulations ? */ dev->reg[reg_0x02].value |= REG02_MTRREV; dev->reg[reg_0x01].value &= ~REG01_SCAN; gl646_set_triple_reg (dev->reg, REG_FEEDL, 65535); /* sets frontend */ status = gl646_set_fe (dev, AFE_SET, settings.xres); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to set frontend: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* write scan registers */ status = gl646_bulk_write_register (dev, dev->reg, sizeof (dev->reg) / sizeof (dev->reg[0])); if (status != SANE_STATUS_GOOD) DBG (DBG_error, "gl646_slow_back_home: failed to bulk write registers: %s\n", sane_strstatus (status)); /* registers are restored to an iddl state, give up if no head to park */ if (dev->model->is_sheetfed == SANE_TRUE) { DBG (DBG_proc, "gl646_slow_back_home: end \n"); return SANE_STATUS_GOOD; } /* starts scan */ status = gl646_begin_scan (dev, dev->reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_slow_back_home: failed to begin scan: \n"); return status; } /* loop until head parked */ if (wait_until_home) { while (loop < 300) /* do not wait longer then 30 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_slow_back_home: Failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (val & 0x08) /* home sensor */ { DBG (DBG_info, "gl646_slow_back_home: reached home position\n"); DBG (DBG_proc, "gl646_slow_back_home: end\n"); usleep (500000); /* sleep 500 ms before returning */ return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ ++loop; } /* when we come here then the scanner needed too much time for this, so we better stop the motor */ gl646_stop_motor (dev); end_scan (dev, dev->reg, SANE_TRUE, SANE_FALSE); DBG (DBG_error, "gl646_slow_back_home: timeout while waiting for scanhead to go home\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_info, "gl646_slow_back_home: scanhead is still moving\n"); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * Automatically set top-left edge of the scan area by scanning an * area at 300 dpi from very top of scanner * @param dev device stucture describing the scanner * @return SANE_STATUS_GOOD in cas of success, else failure code */ static SANE_Status gl646_search_start_position (Genesys_Device * dev) { SANE_Status status; unsigned char *data = NULL; Genesys_Settings settings; unsigned int resolution, x, y; DBG (DBG_proc, "gl646_search_start_position: start\n"); /* we scan at 300 dpi */ resolution = get_closest_resolution (dev->model->ccd_type, 300, SANE_FALSE); /* fill settings for a gray level scan */ settings.scan_method = SCAN_METHOD_FLATBED; settings.scan_mode = SCAN_MODE_GRAY; settings.xres = resolution; settings.yres = resolution; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = 600; settings.lines = dev->model->search_lines; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; /* scan the desired area */ status = simple_scan (dev, settings, SANE_TRUE, SANE_TRUE, SANE_FALSE, &data); /* process data if scan is OK */ if (status == SANE_STATUS_GOOD) { /* handle stagger case : reorder gray data and thus loose some lines */ if (dev->current_setup.stagger > 0) { DBG (DBG_proc, "gl646_search_start_position: 'un-staggering'\n"); for (y = 0; y < settings.lines - dev->current_setup.stagger; y++) { /* one point out of 2 is 'unaligned' */ for (x = 0; x < settings.pixels; x += 2) { data[y * settings.pixels + x] = data[(y + dev->current_setup.stagger) * settings.pixels + x]; } } /* correct line number */ settings.lines -= dev->current_setup.stagger; } if (DBG_LEVEL >= DBG_data) { sanei_genesys_write_pnm_file ("search_position.pnm", data, settings.depth, 1, settings.pixels, settings.lines); } } else { DBG (DBG_error, "gl646_search_start_position: simple_scan failed\n"); free (data); DBGCOMPLETED; return status; } /* now search reference points on the data */ status = sanei_genesys_search_reference_point (dev, data, dev->sensor.CCD_start_xoffset, resolution, settings.pixels, settings.lines); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_search_start_position: failed to set search reference point: %s\n", sane_strstatus (status)); } free (data); DBGCOMPLETED; return status; } /** * internally overriden during effective calibration * sets up register for coarse gain calibration */ static SANE_Status gl646_init_regs_for_coarse_calibration (Genesys_Device * dev) { DBG (DBG_proc, "gl646_init_regs_for_coarse_calibration\n"); DBG (DBG_proc, "gl646_init_register_for_coarse_calibration: end\n"); /* to make compilers happy ... */ if (!dev) { return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /** * init registers for shading calibration * we assume that scanner's head is on an area suiting shading calibration. * We scan a full scan width area by the shading line number for the device * at either at full sensor's resolution or half depending upon half_ccd * @param dev scanner's device * @return SANE_STATUS_GOOD if success, else error code */ static SANE_Status gl646_init_regs_for_shading (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; Genesys_Settings settings; /* 1: no half_ccd, 2: use half number of pixels */ int half_ccd = 1; int cksel = 1; DBG (DBG_proc, "gl646_init_register_for_shading: start\n"); /* when shading all (full width) line, we must adapt to half_ccd case */ if (dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE) { /* walk the master mode list to find if half_ccd */ if (is_half_ccd (dev->model->ccd_type, dev->settings.xres, SANE_TRUE) == SANE_TRUE) { half_ccd = 2; } } /* fill settings for scan : always a color scan */ settings.scan_method = dev->settings.scan_method; settings.scan_mode = dev->settings.scan_mode; if (dev->model->is_cis == SANE_FALSE) { settings.scan_mode = SCAN_MODE_COLOR; } settings.xres = dev->sensor.optical_res / half_ccd; cksel = get_cksel (dev->model->ccd_type, dev->settings.xres, SANE_TRUE); settings.xres = settings.xres / cksel; settings.yres = settings.xres; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = (dev->sensor.sensor_pixels * settings.xres) / dev->sensor.optical_res; dev->calib_lines = dev->model->shading_lines; settings.lines = dev->calib_lines * (3 - half_ccd); settings.depth = 16; settings.color_filter = dev->settings.color_filter; settings.disable_interpolation = dev->settings.disable_interpolation; settings.threshold = dev->settings.threshold; settings.exposure_time = dev->settings.exposure_time; settings.dynamic_lineart = SANE_FALSE; /* keep account of the movement for final scan move */ dev->scanhead_position_in_steps += settings.lines; /* we don't want top offset, but we need right margin to be the same * than the one for the final scan */ status = setup_for_scan (dev, dev->reg, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); /* used when sending shading calibration data */ dev->calib_pixels = settings.pixels; dev->calib_channels = dev->current_setup.channels; if (dev->model->is_cis == SANE_FALSE) { dev->calib_channels = 3; } /* no shading */ dev->reg[reg_0x01].value &= ~REG01_DVDSET; dev->reg[reg_0x02].value |= REG02_ACDCDIS; /* ease backtracking */ dev->reg[reg_0x02].value &= ~(REG02_FASTFED | REG02_AGOHOME); dev->reg[reg_0x05].value &= ~REG05_GMMENB; gl646_set_motor_power (dev->reg, SANE_FALSE); /* TODO another flag to setup regs ? */ /* enforce needed LINCNT, getting rid of extra lines for color reordering */ if (dev->model->is_cis == SANE_FALSE) { gl646_set_triple_reg (dev->reg, REG_LINCNT, dev->calib_lines); } else { gl646_set_triple_reg (dev->reg, REG_LINCNT, dev->calib_lines * 3); } /* copy reg to calib_reg */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL646_MAX_REGS * sizeof (Genesys_Register_Set)); /* this is an hack to make calibration cache working .... */ /* if we don't do this, cache will be identified at the shading calibration * dpi which is different from calibration one */ dev->current_setup.xres = dev->settings.xres; DBG (DBG_info, "gl646_init_register_for_shading:\n\tdev->settings.xres=%d\n\tdev->settings.yres=%d\n", dev->settings.xres, dev->settings.yres); DBG (DBG_proc, "gl646_init_register_for_shading: end\n"); return status; } /** * set up registers for the actual scan. The scan's parameters are given * through the device settings. It allocates the scan buffers. */ static SANE_Status gl646_init_regs_for_scan (Genesys_Device * dev) { SANE_Status status; DBGSTART; /* park head after calibration if needed */ if (dev->scanhead_position_in_steps > 0 && dev->settings.scan_method == SCAN_METHOD_FLATBED) { RIE(gl646_slow_back_home (dev, SANE_TRUE)); dev->scanhead_position_in_steps = 0; } RIE(setup_for_scan (dev, dev->reg, dev->settings, SANE_FALSE, SANE_TRUE, SANE_TRUE)); /* gamma is only enabled at final scan time */ if (dev->settings.depth < 16) dev->reg[reg_0x05].value |= REG05_GMMENB; DBGCOMPLETED; return status; } /** * set up registers for the actual scan. The scan's parameters are given * through the device settings. It allocates the scan buffers. * @param dev scanner's device * @param regs registers to set up * @param settings settings of scan * @param split SANE_TRUE if move to scan area is split from scan, SANE_FALSE is * scan first moves to area * @param xcorrection take x geometry correction into account (fixed and detected offsets) * @param ycorrection take y geometry correction into account */ GENESYS_STATIC SANE_Status setup_for_scan (Genesys_Device * dev, Genesys_Register_Set *regs, Genesys_Settings settings, SANE_Bool split, SANE_Bool xcorrection, SANE_Bool ycorrection) { SANE_Status status = SANE_STATUS_GOOD; SANE_Bool color; SANE_Int depth; int channels; uint16_t startx = 0, endx, pixels; int move = 0; DBGSTART; DBG (DBG_info, "%s settings:\nResolution: %ux%uDPI\n" "Lines : %u\nPixels : %u\nStartpos : %.3f/%.3f\nScan mode : %d\nScan method: %s\n\n", __func__, settings.xres, settings.yres, settings.lines, settings.pixels, settings.tl_x, settings.tl_y, settings.scan_mode, settings.scan_method == SCAN_METHOD_FLATBED ? "flatbed" : "XPA"); if (settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ { channels = 3; color = SANE_TRUE; } else { channels = 1; color = SANE_FALSE; } depth=settings.depth; if (settings.scan_mode == SCAN_MODE_LINEART) { if (settings.dynamic_lineart == SANE_TRUE) { depth = 8; } else { /* XXX STEF XXX : why does the common layer never send depth=1 ? */ depth = 1; } } /* compute distance to move */ move = 0; /* XXX STEF XXX MD5345 -> optical_ydpi, other base_ydpi => half/full step ? */ if (split == SANE_FALSE) { if (dev->model->is_sheetfed == SANE_FALSE) { if (ycorrection == SANE_TRUE) { move = (SANE_UNFIX (dev->model->y_offset) * dev->motor.optical_ydpi) / MM_PER_INCH; } /* add tl_y to base movement */ move += (settings.tl_y * dev->motor.optical_ydpi) / MM_PER_INCH; } else { move += (settings.tl_y * dev->motor.optical_ydpi) / MM_PER_INCH; } DBG (DBG_info, "%s: move=%d steps\n", __func__, move); /* security check */ if (move < 0) { DBG (DBG_error, "%s: overriding negative move value %d\n", __func__, move); move = 0; } } DBG (DBG_info, "%s: move=%d steps\n", __func__, move); /* pixels are allways given at full CCD optical resolution */ /* use detected left margin and fixed value */ if (xcorrection == SANE_TRUE) { if (dev->sensor.CCD_start_xoffset > 0) startx = dev->sensor.CCD_start_xoffset; else startx = dev->sensor.dummy_pixel; if (settings.scan_method == SCAN_METHOD_FLATBED) { startx += ((SANE_UNFIX (dev->model->x_offset) * dev->sensor.optical_res) / MM_PER_INCH); } else { startx += ((SANE_UNFIX (dev->model->x_offset_ta) * dev->sensor.optical_res) / MM_PER_INCH); } } else { /* startx cannot be below dummy pixel value */ startx = dev->sensor.dummy_pixel; } /* add x coordinates : expressed in sensor max dpi */ startx += (settings.tl_x * dev->sensor.optical_res) / MM_PER_INCH; /* stagger works with odd start cordinates */ if (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE) startx |= 1; pixels = (settings.pixels * dev->sensor.optical_res) / settings.xres; /* special requirement for 400 dpi on 1200 dpi sensors */ if (settings.xres == 400) { pixels = (pixels / 6) * 6; } endx = startx + pixels; /* TODO check for pixel width overflow */ /* set up correct values for scan (gamma and shading enabled) */ status = gl646_setup_registers (dev, regs, settings, dev->slope_table0, dev->slope_table1, settings.xres, move, settings.lines, startx, endx, color, depth); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed setup registers: %s\n", __func__, sane_strstatus (status)); return status; } /* now post-process values for register and options fine tuning */ /* select color filter based on settings */ regs[reg_0x04].value &= ~REG04_FILTER; if (channels == 1) { switch (settings.color_filter) { /* red */ case 0: regs[reg_0x04].value |= 0x04; break; /* green */ case 1: regs[reg_0x04].value |= 0x08; break; /* blue */ case 2: regs[reg_0x04].value |= 0x0c; break; default: break; } } /* send computed slope tables */ status = gl646_send_slope_table (dev, 0, dev->slope_table0, sanei_genesys_read_reg_from_set (regs, 0x21)); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to send slope table 0: %s\n", __func__, sane_strstatus (status)); return status; } status = gl646_send_slope_table (dev, 1, dev->slope_table1, sanei_genesys_read_reg_from_set (regs, 0x6b)); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to send slope table 1: %s\n", __func__, sane_strstatus (status)); return status; } DBGCOMPLETED; return status; } /** * this function sen gamm table to ASIC */ static SANE_Status gl646_send_gamma_table (Genesys_Device * dev) { int size; int address; SANE_Status status; uint8_t *gamma; int bits; DBGSTART; /* gamma table size */ if (dev->reg[reg_0x05].value & REG05_GMMTYPE) { size = 16384; bits = 14; } else { size = 4096; bits = 12; } /* allocate temporary gamma tables: 16 bits words, 3 channels */ gamma = (uint8_t *) malloc (size * 2 * 3); if (gamma==NULL) { return SANE_STATUS_NO_MEM; } RIE(sanei_genesys_generate_gamma_buffer(dev, bits, size-1, size, gamma)); /* table address */ switch (dev->reg[reg_0x05].value >> 6) { case 0: /* 600 dpi */ address = 0x09000; break; case 1: /* 1200 dpi */ address = 0x11000; break; case 2: /* 2400 dpi */ address = 0x20000; break; default: free (gamma); return SANE_STATUS_INVAL; } /* send address */ status = sanei_genesys_set_buffer_address (dev, address); if (status != SANE_STATUS_GOOD) { free (gamma); DBG (DBG_error, "gl646_send_gamma_table: failed to set buffer address: %s\n", sane_strstatus (status)); return status; } /* send data */ status = gl646_bulk_write_data (dev, 0x3c, (uint8_t *) gamma, size * 2 * 3); if (status != SANE_STATUS_GOOD) { free (gamma); DBG (DBG_error, "gl646_send_gamma_table: failed to send gamma table: %s\n", sane_strstatus (status)); return status; } free (gamma); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief this function does the led calibration. * this function does the led calibration by scanning one line of the calibration * area below scanner's top on white strip. The scope of this function is * currently limited to the XP200 */ static SANE_Status gl646_led_calibration (Genesys_Device * dev) { int total_size; uint8_t *line; unsigned int i, j; SANE_Status status = SANE_STATUS_GOOD; int val; unsigned int channels; int avg[3], avga, avge; int turn; char fn[20]; uint16_t expr, expg, expb; Genesys_Settings settings; SANE_Int resolution; SANE_Bool acceptable = SANE_FALSE; DBG (DBG_proc, "gl646_led_calibration\n"); if (!dev->model->is_cis) { DBG (DBG_proc, "gl646_led_calibration: not a cis scanner, nothing to do...\n"); return SANE_STATUS_GOOD; } /* get led calibration resolution */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) { resolution = get_closest_resolution (dev->model->ccd_type, dev->sensor.optical_res, SANE_TRUE); settings.scan_mode = SCAN_MODE_COLOR; channels = 3; } else { resolution = get_closest_resolution (dev->model->ccd_type, dev->sensor.optical_res, SANE_FALSE); settings.scan_mode = SCAN_MODE_GRAY; channels = 1; } /* offset calibration is always done in color mode */ settings.scan_method = SCAN_METHOD_FLATBED; settings.xres = resolution; settings.yres = resolution; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; settings.lines = 1; settings.depth = 16; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; /* colors * bytes_per_color * scan lines */ total_size = settings.pixels * channels * 2 * 1; line = malloc (total_size); if (!line) { DBG (DBG_error, "gl646_led_calibration: failed to allocate %d bytes\n", total_size); return SANE_STATUS_NO_MEM; } /* we try to get equal bright leds here: loop: average per color adjust exposure times Sensor_Master uint8_t regs_0x10_0x15[6]; */ expr = (dev->sensor.regs_0x10_0x1d[0] << 8) | dev->sensor.regs_0x10_0x1d[1]; expg = (dev->sensor.regs_0x10_0x1d[2] << 8) | dev->sensor.regs_0x10_0x1d[3]; expb = (dev->sensor.regs_0x10_0x1d[4] << 8) | dev->sensor.regs_0x10_0x1d[5]; turn = 0; do { dev->sensor.regs_0x10_0x1d[0] = (expr >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[1] = expr & 0xff; dev->sensor.regs_0x10_0x1d[2] = (expg >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[3] = expg & 0xff; dev->sensor.regs_0x10_0x1d[4] = (expb >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[5] = expb & 0xff; DBG (DBG_info, "gl646_led_calibration: starting first line reading\n"); status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &line); if (status != SANE_STATUS_GOOD) { free(line); DBG (DBG_error, "gl646_led_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) { snprintf (fn, 20, "led_%02d.pnm", turn); sanei_genesys_write_pnm_file (fn, line, 16, channels, settings.pixels, 1); } acceptable = SANE_TRUE; for (j = 0; j < channels; j++) { avg[j] = 0; for (i = 0; i < settings.pixels; i++) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * settings.pixels + 1] * 256 + line[i * 2 + j * 2 * settings.pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; avg[j] += val; } avg[j] /= settings.pixels; } DBG (DBG_info, "gl646_led_calibration: average: " "%d,%d,%d\n", avg[0], avg[1], avg[2]); acceptable = SANE_TRUE; if (!acceptable) { avga = (avg[0] + avg[1] + avg[2]) / 3; expr = (expr * avga) / avg[0]; expg = (expg * avga) / avg[1]; expb = (expb * avga) / avg[2]; /* keep exposure time in a working window */ avge = (expr + expg + expb) / 3; if (avge > 0x2000) { expr = (expr * 0x2000) / avge; expg = (expg * 0x2000) / avge; expb = (expb * 0x2000) / avge; } if (avge < 0x400) { expr = (expr * 0x400) / avge; expg = (expg * 0x400) / avge; expb = (expb * 0x400) / avge; } } turn++; } while (!acceptable && turn < 100); DBG (DBG_info, "gl646_led_calibration: acceptable exposure: 0x%04x,0x%04x,0x%04x\n", expr, expg, expb); /* cleanup before return */ free (line); DBGCOMPLETED; return status; } /** * average dark pixels of a scan */ static int dark_average (uint8_t * data, unsigned int pixels, unsigned int lines, unsigned int channels, unsigned int black) { unsigned int i, j, k, average, count; unsigned int avg[3]; uint8_t val; /* computes average value on black margin */ for (k = 0; k < channels; k++) { avg[k] = 0; count = 0; for (i = 0; i < lines; i++) { for (j = 0; j < black; j++) { val = data[i * channels * pixels + j + k]; avg[k] += val; count++; } } if (count) avg[k] /= count; DBG (DBG_info, "dark_average: avg[%d] = %d\n", k, avg[k]); } average = 0; for (i = 0; i < channels; i++) average += avg[i]; average /= channels; DBG (DBG_info, "dark_average: average = %d\n", average); return average; } /** @brief calibration for AD frontend devices * we do simple scan until all black_pixels are higher than 0, * raising offset at each turn. */ static SANE_Status ad_fe_offset_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; uint8_t *line; unsigned int channels; char title[32]; int pass = 0; SANE_Int resolution; Genesys_Settings settings; unsigned int x, y, adr, min; unsigned int bottom, black_pixels; DBG (DBG_proc, "ad_fe_offset_calibration: start\n"); resolution = get_closest_resolution (dev->model->ccd_type, dev->sensor.optical_res, SANE_TRUE); channels = 3; black_pixels = (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res; DBG (DBG_io2, "ad_fe_offset_calibration: black_pixels=%d\n", black_pixels); settings.scan_method = SCAN_METHOD_FLATBED; settings.scan_mode = SCAN_MODE_COLOR; settings.xres = resolution; settings.yres = resolution; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; settings.lines = CALIBRATION_LINES; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; /* scan first line of data with no gain */ dev->frontend.gain[0] = 0; dev->frontend.gain[1] = 0; dev->frontend.gain[2] = 0; /* scan with no move */ bottom = 1; do { pass++; dev->frontend.offset[0] = bottom; dev->frontend.offset[1] = bottom; dev->frontend.offset[2] = bottom; status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &line); if (status != SANE_STATUS_GOOD) { free(line); DBG (DBG_error, "ad_fe_offset_calibration: failed to scan first line\n"); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "offset%03d.pnm", (int)bottom); sanei_genesys_write_pnm_file (title, line, 8, channels, settings.pixels, settings.lines); } min = 0; for (y = 0; y < settings.lines; y++) { for (x = 0; x < black_pixels; x++) { adr = (x + y * settings.pixels) * channels; if (line[adr] > min) min = line[adr]; if (line[adr + 1] > min) min = line[adr + 1]; if (line[adr + 2] > min) min = line[adr + 2]; } } free (line); DBG (DBG_io2, "ad_fe_offset_calibration: pass=%d, min=%d\n", pass, min); bottom++; } while (pass < 128 && min == 0); if (pass == 128) { DBG (DBG_error, "ad_fe_offset_calibration: failed to find correct offset\n"); return SANE_STATUS_INVAL; } DBG (DBG_info, "ad_fe_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); DBG (DBG_proc, "ad_fe_offset_calibration: end\n"); return status; } #define DARK_TARGET 8 /** * This function does the offset calibration by scanning one line of the calibration * area below scanner's top. There is a black margin and the remaining is white. * genesys_search_start() must have been called so that the offsets and margins * are already known. * @param dev scanner's device * @return SANE_STATUS_GOOD if success, else error code is failure */ static SANE_Status gl646_offset_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; uint8_t *first_line, *second_line; unsigned int channels; char title[32]; int pass = 0, avg; SANE_Int resolution; Genesys_Settings settings; int topavg, bottomavg; int top, bottom, black_pixels; /* Analog Device fronted have a different calibration */ if (dev->model->dac_type == DAC_AD_XP200) { return ad_fe_offset_calibration (dev); } DBG (DBG_proc, "gl646_offset_calibration: start\n"); /* setup for a RGB scan, one full sensor's width line */ /* resolution is the one from the final scan */ if (dev->settings.xres > dev->sensor.optical_res) { resolution = get_closest_resolution (dev->model->ccd_type, dev->sensor.optical_res, SANE_TRUE); } else { resolution = get_closest_resolution (dev->model->ccd_type, dev->settings.xres, SANE_TRUE); } channels = 3; black_pixels = (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res; DBG (DBG_io2, "gl646_offset_calibration: black_pixels=%d\n", black_pixels); settings.scan_method = SCAN_METHOD_FLATBED; settings.scan_mode = SCAN_MODE_COLOR; settings.xres = resolution; settings.yres = resolution; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; settings.lines = CALIBRATION_LINES; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; /* scan first line of data with no gain, but with offset from * last calibration */ dev->frontend.gain[0] = 0; dev->frontend.gain[1] = 0; dev->frontend.gain[2] = 0; /* scan with no move */ bottom = 90; dev->frontend.offset[0] = bottom; dev->frontend.offset[1] = bottom; dev->frontend.offset[2] = bottom; status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &first_line); if (status != SANE_STATUS_GOOD) { free(first_line); DBG (DBG_error, "gl646_offset_calibration: failed to scan first line\n"); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "offset%03d.pnm", bottom); sanei_genesys_write_pnm_file (title, first_line, 8, channels, settings.pixels, settings.lines); } bottomavg = dark_average (first_line, settings.pixels, settings.lines, channels, black_pixels); free (first_line); DBG (DBG_io2, "gl646_offset_calibration: bottom avg=%d\n", bottomavg); /* now top value */ top = 231; dev->frontend.offset[0] = top; dev->frontend.offset[1] = top; dev->frontend.offset[2] = top; status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line); if (status != SANE_STATUS_GOOD) { free(second_line); DBG (DBG_error, "gl646_offset_calibration: failed to scan first line\n"); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "offset%03d.pnm", top); sanei_genesys_write_pnm_file (title, second_line, 8, channels, settings.pixels, settings.lines); } topavg = dark_average (second_line, settings.pixels, settings.lines, channels, black_pixels); free (second_line); DBG (DBG_io2, "gl646_offset_calibration: top avg=%d\n", topavg); /* loop until acceptable level */ while ((pass < 32) && (top - bottom > 1)) { pass++; /* settings for new scan */ dev->frontend.offset[0] = (top + bottom) / 2; dev->frontend.offset[1] = (top + bottom) / 2; dev->frontend.offset[2] = (top + bottom) / 2; /* scan with no move */ status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line); if (status != SANE_STATUS_GOOD) { free(second_line); DBG (DBG_error, "gl646_offset_calibration: failed to scan first line\n"); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]); sanei_genesys_write_pnm_file (title, second_line, 8, channels, settings.pixels, settings.lines); } avg = dark_average (second_line, settings.pixels, settings.lines, channels, black_pixels); DBG (DBG_info, "gl646_offset_calibration: avg=%d offset=%d\n", avg, dev->frontend.offset[1]); free (second_line); /* compute new boundaries */ if (topavg == avg) { topavg = avg; top = dev->frontend.offset[1]; } else { bottomavg = avg; bottom = dev->frontend.offset[1]; } } /* in case of debug do a final scan to get result */ if (DBG_LEVEL >= DBG_data) { status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &second_line); if (status != SANE_STATUS_GOOD) { free(second_line); DBG (DBG_error, "gl646_offset_calibration: failed to scan final line\n"); return status; } sanei_genesys_write_pnm_file ("offset-final.pnm", second_line, 8, channels, settings.pixels, settings.lines); free (second_line); } DBG (DBG_info, "gl646_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); DBG (DBG_proc, "gl646_offset_calibration: end\n"); return status; } /** @brief gain calibration for Analog Device frontends * Alternative coarse gain calibration */ static SANE_Status ad_fe_coarse_gain_calibration (Genesys_Device * dev, int dpi) { uint8_t *line; unsigned int i, channels, val; unsigned int size, count, resolution, pass; SANE_Status status = SANE_STATUS_GOOD; float average; Genesys_Settings settings; char title[32]; DBGSTART; /* setup for a RGB scan, one full sensor's width line */ /* resolution is the one from the final scan */ resolution = get_closest_resolution (dev->model->ccd_type, dpi, SANE_TRUE); channels = 3; settings.scan_mode = SCAN_MODE_COLOR; settings.scan_method = SCAN_METHOD_FLATBED; settings.xres = resolution; settings.yres = resolution; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; settings.lines = CALIBRATION_LINES; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; size = channels * settings.pixels * settings.lines; /* start gain value */ dev->frontend.gain[0] = 1; dev->frontend.gain[1] = 1; dev->frontend.gain[2] = 1; average = 0; pass = 0; /* loop until each channel raises to acceptable level */ while ((average < dev->sensor.gain_white_ref) && (pass < 30)) { /* scan with no move */ status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &line); if (status != SANE_STATUS_GOOD) { free(line); DBG (DBG_error, "ad_fe_coarse_gain_calibration: failed to scan first line\n"); return status; } /* log scanning data */ if (DBG_LEVEL >= DBG_data) { sprintf (title, "alternative_coarse%02d.pnm", (int)pass); sanei_genesys_write_pnm_file (title, line, 8, channels, settings.pixels, settings.lines); } pass++; /* computes white average */ average = 0; count = 0; for (i = 0; i < size; i++) { val = line[i]; average += val; count++; } average = average / count; /* adjusts gain for the channel */ if (average < dev->sensor.gain_white_ref) dev->frontend.gain[0]++; dev->frontend.gain[1] = dev->frontend.gain[0]; dev->frontend.gain[2] = dev->frontend.gain[0]; DBG (DBG_proc, "ad_fe_coarse_gain_calibration: average = %.2f, gain = %d\n", average, dev->frontend.gain[0]); free (line); } DBG (DBG_info, "ad_fe_coarse_gain_calibration: gains=(%d,%d,%d)\n", dev->frontend.gain[0], dev->frontend.gain[1], dev->frontend.gain[2]); DBGCOMPLETED; return status; } /** * Alternative coarse gain calibration * this on uses the settings from offset_calibration. First scan moves so * we can go to calibration area for XPA. * @param dev device for scan * @param dpi resolutnio to calibrate at */ static SANE_Status gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi) { uint8_t *line; unsigned int i, j, k, channels, val, maximum, idx; unsigned int count, resolution, pass; SANE_Status status = SANE_STATUS_GOOD; float average[3]; Genesys_Settings settings; char title[32]; if (dev->model->ccd_type == CIS_XP200) { return ad_fe_coarse_gain_calibration (dev, dev->sensor.optical_res); } DBGSTART; /* setup for a RGB scan, one full sensor's width line */ /* resolution is the one from the final scan */ channels = 3; /* we are searching a sensor resolution */ if (dpi > dev->sensor.optical_res) { resolution = dev->sensor.optical_res; } else { resolution = get_closest_resolution (dev->model->ccd_type, dev->settings.xres, SANE_TRUE); } settings.scan_method = dev->settings.scan_method; settings.scan_mode = SCAN_MODE_COLOR; settings.xres = resolution; settings.yres = resolution; settings.tl_y = 0; if (settings.scan_method == SCAN_METHOD_FLATBED) { settings.tl_x = 0; settings.pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; } else { settings.tl_x = SANE_UNFIX (dev->model->x_offset_ta); settings.pixels = (SANE_UNFIX (dev->model->x_size_ta) * resolution) / MM_PER_INCH; } settings.lines = CALIBRATION_LINES; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; /* start gain value */ dev->frontend.gain[0] = 1; dev->frontend.gain[1] = 1; dev->frontend.gain[2] = 1; if (channels > 1) { average[0] = 0; average[1] = 0; average[2] = 0; idx = 0; } else { average[0] = 255; average[1] = 255; average[2] = 255; idx = dev->settings.color_filter; average[idx] = 0; } pass = 0; /* loop until each channel raises to acceptable level */ while (((average[0] < dev->sensor.gain_white_ref) || (average[1] < dev->sensor.gain_white_ref) || (average[2] < dev->sensor.gain_white_ref)) && (pass < 30)) { /* scan with no move */ status = simple_scan (dev, settings, SANE_FALSE, SANE_TRUE, SANE_FALSE, &line); if (status != SANE_STATUS_GOOD) { free(line); DBG (DBG_error, "%s: failed to scan first line\n", __func__); return status; } /* log scanning data */ if (DBG_LEVEL >= DBG_data) { sprintf (title, "coarse_gain%02d.pnm", (int)pass); sanei_genesys_write_pnm_file (title, line, 8, channels, settings.pixels, settings.lines); } pass++; /* average high level for each channel and compute gain to reach the target code we only use the central half of the CCD data */ for (k = idx; k < idx + channels; k++) { /* we find the maximum white value, so we can deduce a threshold to average white values */ maximum = 0; for (i = 0; i < settings.lines; i++) { for (j = 0; j < settings.pixels; j++) { val = line[i * channels * settings.pixels + j + k]; if (val > maximum) maximum = val; } } /* threshold */ maximum *= 0.9; /* computes white average */ average[k] = 0; count = 0; for (i = 0; i < settings.lines; i++) { for (j = 0; j < settings.pixels; j++) { /* averaging only white points allow us not to care about dark margins */ val = line[i * channels * settings.pixels + j + k]; if (val > maximum) { average[k] += val; count++; } } } average[k] = average[k] / count; /* adjusts gain for the channel */ if (average[k] < dev->sensor.gain_white_ref) dev->frontend.gain[k]++; DBG (DBG_proc, "%s: channel %d, average = %.2f, gain = %d\n", __func__, k, average[k], dev->frontend.gain[k]); } free (line); } if (channels < 3) { dev->frontend.gain[1] = dev->frontend.gain[0]; dev->frontend.gain[2] = dev->frontend.gain[0]; } DBG (DBG_info, "%s: gains=(%d,%d,%d)\n", __func__, dev->frontend.gain[0], dev->frontend.gain[1], dev->frontend.gain[2]); DBGCOMPLETED; return status; } /** * sets up the scanner's register for warming up. We scan 2 lines without moving. * */ static SANE_Status gl646_init_regs_for_warmup (Genesys_Device * dev, Genesys_Register_Set * local_reg, int *channels, int *total_size) { SANE_Status status = SANE_STATUS_GOOD; Genesys_Settings settings; int resolution, lines; DBG (DBG_proc, "gl646_init_regs_for_warmup: start\n"); sanei_genesys_init_fe (dev); resolution = get_closest_resolution (dev->model->ccd_type, 300, SANE_FALSE); /* set up for a half width 2 lines gray scan without moving */ settings.scan_method = SCAN_METHOD_FLATBED; settings.scan_mode = SCAN_MODE_GRAY; settings.xres = resolution; settings.yres = resolution; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; settings.lines = 2; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; /* setup for scan */ status = setup_for_scan (dev, dev->reg, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_init_regs_for_warmup: setup_for_scan failed (%s)\n", sane_strstatus (status)); return status; } /* we are not going to move, so clear these bits */ dev->reg[reg_0x02].value &= ~(REG02_FASTFED | REG02_AGOHOME); /* don't enable any correction for this scan */ dev->reg[reg_0x01].value &= ~REG01_DVDSET; /* copy to local_reg */ memcpy (local_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); /* turn off motor during this scan */ gl646_set_motor_power (local_reg, SANE_FALSE); /* returned value to higher level warmup function */ *channels = 1; lines = gl646_get_triple_reg (local_reg, REG_LINCNT) + 1; *total_size = lines * settings.pixels; /* now registers are ok, write them to scanner */ RIE (gl646_set_fe (dev, AFE_SET, settings.xres)); RIE (gl646_bulk_write_register (dev, local_reg, GENESYS_GL646_MAX_REGS)); DBGCOMPLETED; return status; } /* * this function moves head without scanning, forward, then backward * so that the head goes to park position. * as a by-product, also check for lock */ static SANE_Status gl646_repark_head (Genesys_Device * dev) { SANE_Status status; Genesys_Settings settings; unsigned int expected, steps; DBG (DBG_proc, "gl646_repark_head: start\n"); settings.scan_method = SCAN_METHOD_FLATBED; settings.scan_mode = SCAN_MODE_COLOR; settings.xres = get_closest_resolution (dev->model->ccd_type, 75, SANE_FALSE); settings.yres = settings.xres; settings.tl_x = 0; settings.tl_y = 5; settings.pixels = 600; settings.lines = 4; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; status = setup_for_scan (dev, dev->reg, settings, SANE_FALSE, SANE_FALSE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_repark_head: failed to setup for scan: %s\n", sane_strstatus (status)); return status; } /* TODO seems wrong ... no effective scan */ dev->reg[reg_0x01].value &= ~REG01_SCAN; status = gl646_bulk_write_register (dev, dev->reg, GENESYS_GL646_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_repark_head: failed to send registers: %s\n", sane_strstatus (status)); return status; } /* start scan */ status = gl646_begin_scan (dev, dev->reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_repark_head: failed to begin scan: \n"); return status; } expected = gl646_get_triple_reg (dev->reg, REG_FEEDL); do { usleep (100 * 1000); status = sanei_genesys_read_feed_steps (dev, &steps); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_repark_head: failed to read feed steps: %s\n", sane_strstatus (status)); return status; } } while (steps < expected); /* toggle motor flag, put an huge step number and redo move backward */ status = gl646_slow_back_home (dev, 1); DBG (DBG_proc, "gl646_repark_head: end\n"); return status; } /* * * initialize ASIC : registers, motor tables, and gamma tables * then ensure scanner's head is at home * @param dev device description of the scanner to initailize * @return SANE_STATUS_GOOD if success, error code if failure */ static SANE_Status gl646_init (Genesys_Device * dev) { SANE_Status status; struct timeval tv; uint8_t cold = 0, val = 0; uint32_t addr = 0xdead; int size, i; size_t len; DBG_INIT (); DBG (DBG_proc, "gl646_init: start\n"); /* to detect real power up condition, we write to REG41 * with pwrbit set, then read it back. When scanner is cold (just replugged) * PWRBIT will be set in the returned value */ RIE (sanei_genesys_get_status (dev, &cold)); DBG (DBG_info, "gl646_init: status=0x%02x\n", cold); cold = !(cold & REG41_PWRBIT); if (cold) { DBG (DBG_info, "gl646_init: device is cold\n"); } else { DBG (DBG_info, "gl646_init: device is hot\n"); } /* if scanning session hasn't been initialized, set it up */ if (!dev->already_initialized) { dev->dark_average_data = NULL; dev->white_average_data = NULL; dev->settings.color_filter = 1; /* green filter by default */ gettimeofday (&tv, NULL); dev->init_date = tv.tv_sec; switch (dev->model->motor_type) { /* set to 11111 to spot bugs, sanei_genesys_exposure_time should have obsoleted this field */ case MOTOR_5345: dev->settings.exposure_time = 11111; break; case MOTOR_ST24: dev->settings.exposure_time = 11000; break; default: dev->settings.exposure_time = 11000; break; } /* Set default values for registers */ gl646_init_regs (dev); /* build default gamma tables */ if (dev->reg[reg_0x05].value & REG05_GMMTYPE) size = 16384; else size = 4096; for(i=0;i<3;i++) { if (dev->sensor.gamma_table[i] == NULL) { dev->sensor.gamma_table[i] = (uint16_t *) malloc (2 * size); if (dev->sensor.gamma_table[i] == NULL) { DBG (DBG_error, "gl646_init: could not allocate memory for gamma table %d\n",i); return SANE_STATUS_NO_MEM; } sanei_genesys_create_gamma_table (dev->sensor.gamma_table[i], size, size - 1, size - 1, dev->sensor.gamma[i]); } } /* Init shading data */ RIE (sanei_genesys_init_shading_data (dev, dev->sensor.sensor_pixels)); /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, (GENESYS_GL646_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); } /* execute physical unit init only if cold */ if (cold) { DBG (DBG_info, "gl646_init: device is cold\n"); val = 0x04; RIE (sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_INIT, INDEX, 1, &val)); /* ASIC reset */ RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); usleep (100000UL); /* sleep 100 ms */ /* Write initial registers */ RIE (gl646_bulk_write_register (dev, dev->reg, GENESYS_GL646_MAX_REGS)); /* Test ASIC and RAM */ if (!(dev->model->flags & GENESYS_FLAG_LAZY_INIT)) { RIE (gl646_asic_test (dev)); } /* send gamma tables if needed */ status = gl646_send_gamma_table (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_init: failed to send generic gamma tables: %s\n", sane_strstatus (status)); return status; } /* Set powersaving (default = 15 minutes) */ RIE (gl646_set_powersaving (dev, 15)); } /* end if cold */ /* Set analog frontend */ RIE (gl646_set_fe (dev, AFE_INIT, 0)); /* GPO enabling for XP200 */ if (dev->model->ccd_type == CIS_XP200) { sanei_genesys_write_register (dev, 0x68, dev->gpo.enable[0]); sanei_genesys_write_register (dev, 0x69, dev->gpo.enable[1]); /* enable GPIO */ val = 6; status = gl646_gpio_output_enable (dev->dn, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_init: GPO enable failed ... %s\n", sane_strstatus (status)); } val = 0; /* writes 0 to GPIO */ status = gl646_gpio_write (dev->dn, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_init: GPO write failed ... %s\n", sane_strstatus (status)); } /* clear GPIO enable */ status = gl646_gpio_output_enable (dev->dn, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_init: GPO disable failed ... %s\n", sane_strstatus (status)); } sanei_genesys_write_register (dev, 0x66, 0x10); sanei_genesys_write_register (dev, 0x66, 0x00); sanei_genesys_write_register (dev, 0x66, 0x10); } /* MD6471/G2410 and XP200 read/write data from an undocumented memory area which * is after the second slope table */ if (dev->model->gpo_type != GPO_HP3670 && dev->model->gpo_type != GPO_HP2400) { switch (dev->sensor.optical_res) { case 600: addr = 0x08200; break; case 1200: addr = 0x10200; break; case 2400: addr = 0x1fa00; break; } status = sanei_genesys_set_buffer_address (dev, addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_init: failed to set up control address\n"); return SANE_STATUS_INVAL; } sanei_usb_set_timeout (2 * 1000); len = 6; status = gl646_bulk_read_data (dev, 0x45, dev->control, len); /* for some reason, read fails here for MD6471, HP2300 and XP200 * one time out of 2 scanimage launches */ if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "gl646_init: failed to read control\n"); status = gl646_bulk_read_data (dev, 0x45, dev->control, len); } if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "gl646_init: failed to read control\n"); return SANE_STATUS_INVAL; } else { DBG (DBG_info, "gl646_init: control read=0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", dev->control[0], dev->control[1], dev->control[2], dev->control[3], dev->control[4], dev->control[5]); } sanei_usb_set_timeout (30 * 1000); } else /* HP2400 and HP3670 case */ { dev->control[0] = 0x00; dev->control[1] = 0x00; dev->control[2] = 0x01; dev->control[3] = 0x00; dev->control[4] = 0x00; dev->control[5] = 0x00; } /* ensure head is correctly parked, and check lock */ if (dev->model->is_sheetfed == SANE_FALSE) { if (dev->model->flags & GENESYS_FLAG_REPARK) { status = gl646_repark_head (dev); if (status != SANE_STATUS_GOOD) { if (status == SANE_STATUS_INVAL) { DBG (DBG_error0, "Your scanner is locked. Please move the lock switch " "to the unlocked position\n"); #ifdef SANE_STATUS_HW_LOCKED return SANE_STATUS_HW_LOCKED; #else return SANE_STATUS_JAMMED; #endif } else DBG (DBG_error, "gl646_init: gl646_repark_head failed: %s\n", sane_strstatus (status)); return status; } } else { RIE (gl646_slow_back_home (dev, SANE_TRUE)); } } /* here session and device are initialized */ dev->already_initialized = SANE_TRUE; DBG (DBG_proc, "gl646_init: end\n"); return SANE_STATUS_GOOD; } GENESYS_STATIC SANE_Status gl646_move_to_ta (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; DBGSTART; if (simple_move (dev, SANE_UNFIX (dev->model->y_offset_calib_ta)) != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_move_to_ta: failed to move to calibration area\n"); return status; } DBGCOMPLETED; return status; } /** * Does a simple scan: ie no line reordering and avanced data buffering and * shading correction. Memory for data is allocated in this function * and must be freed by caller. * @param dev device of the scanner * @param settings parameters of the scan * @param move SANE_TRUE if moving during scan * @param forward SANE_TRUE if moving forward during scan * @param shading SANE_TRUE to enable shading correction * @param data pointer for the data */ GENESYS_STATIC SANE_Status simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, SANE_Bool forward, SANE_Bool shading, unsigned char **data) { SANE_Status status = SANE_STATUS_INVAL; unsigned int size, lines, x, y, bpp; SANE_Bool empty, split; unsigned char *buffer; int count; uint8_t val; DBG (DBG_proc, "simple_scan: starting\n"); DBG (DBG_io, "simple_scan: move=%d, forward=%d, shading=%d\n", move, forward, shading); /* round up to multiple of 3 in case of CIS scanner */ if (dev->model->is_cis == SANE_TRUE) { settings.lines = ((settings.lines + 2) / 3) * 3; } /* setup for move then scan */ if (move == SANE_TRUE && settings.tl_y > 0) { split = SANE_FALSE; } else { split = SANE_TRUE; } status = setup_for_scan (dev, dev->reg, settings, split, SANE_FALSE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "simple_scan: setup_for_scan failed (%s)\n", sane_strstatus (status)); return status; } /* allocate memory fo scan : LINCNT may have been adjusted for CCD reordering */ if (dev->model->is_cis == SANE_TRUE) { lines = gl646_get_triple_reg (dev->reg, REG_LINCNT) / 3; } else { lines = gl646_get_triple_reg (dev->reg, REG_LINCNT) + 1; } size = lines * settings.pixels; if (settings.depth == 16) bpp = 2; else bpp = 1; size *= bpp; if (settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ size *= 3; *data = malloc (size); if (!*data) { DBG (DBG_error, "simple_scan: failed to allocate %d bytes of memory\n", size); return SANE_STATUS_NO_MEM; } DBG (DBG_io, "simple_scan: allocated %d bytes of memory for %d lines\n", size, lines); /* put back real line number in settings */ settings.lines = lines; /* initialize frontend */ status = gl646_set_fe (dev, AFE_SET, settings.xres); if (status != SANE_STATUS_GOOD) { free (*data); DBG (DBG_error, "simple_scan: failed to set frontend: %s\n", sane_strstatus (status)); return status; } /* no shading correction and not watch dog for simple scan */ dev->reg[reg_0x01].value &= ~(REG01_DVDSET | REG01_DOGENB); if (shading == SANE_TRUE) { dev->reg[reg_0x01].value |= REG01_DVDSET; } /* enable gamma table for the scan */ dev->reg[reg_0x05].value |= REG05_GMMENB; /* one table movement for simple scan */ dev->reg[reg_0x02].value &= ~REG02_FASTFED; if (move == SANE_FALSE) { /* clear motor power flag if no move */ dev->reg[reg_0x02].value &= ~REG02_MTRPWR; /* no automatic go home if no movement */ dev->reg[reg_0x02].value &= ~REG02_AGOHOME; } if (forward == SANE_FALSE) { dev->reg[reg_0x02].value |= REG02_MTRREV; } else { dev->reg[reg_0x02].value &= ~REG02_MTRREV; } /* no automatic go home when using XPA */ if (settings.scan_method == SCAN_METHOD_TRANSPARENCY) { dev->reg[reg_0x02].value &= ~REG02_AGOHOME; } /* write scan registers */ status = gl646_bulk_write_register (dev, dev->reg, sizeof (dev->reg) / sizeof (dev->reg[0])); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "simple_scan: failed to bulk write registers: %s\n", sane_strstatus (status)); free (*data); return status; } /* starts scan */ status = gl646_begin_scan (dev, dev->reg, move); if (status != SANE_STATUS_GOOD) { free (*data); DBG (DBG_error, "simple_scan: failed to begin scan: \n"); return status; } /* wait for buffers to be filled */ count = 0; do { usleep (10000UL); RIE (sanei_genesys_get_status (dev, &val)); if (DBG_LEVEL > DBG_info) { print_status (val); } RIE (sanei_genesys_test_buffer_empty (dev, &empty)); count++; } while (empty && count < 1000); if (count == 1000) { free (*data); DBG (DBG_error, "simple_scan: failed toread data\n"); return SANE_STATUS_IO_ERROR; } /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, *data, size); if (status != SANE_STATUS_GOOD) { free (*data); DBG (DBG_error, "simple_scan: failed to read data: %s\n", sane_strstatus (status)); return status; } /* in case of CIS scanner, we must reorder data */ if (dev->model->is_cis == SANE_TRUE && settings.scan_mode == SCAN_MODE_COLOR) { /* alloc one line sized working buffer */ buffer = (unsigned char *) malloc (settings.pixels * 3 * bpp); if (buffer == NULL) { DBG (DBG_error, "simple_scan: failed to allocate %d bytes of memory\n", settings.pixels * 3); return SANE_STATUS_NO_MEM; } /* reorder one line of data and put it back to buffer */ if (bpp == 1) { for (y = 0; y < lines; y++) { /* reorder line */ for (x = 0; x < settings.pixels; x++) { buffer[x * 3] = (*data)[y * settings.pixels * 3 + x]; buffer[x * 3 + 1] = (*data)[y * settings.pixels * 3 + settings.pixels + x]; buffer[x * 3 + 2] = (*data)[y * settings.pixels * 3 + 2 * settings.pixels + x]; } /* copy line back */ memcpy ((*data) + settings.pixels * 3 * y, buffer, settings.pixels * 3); } } else { for (y = 0; y < lines; y++) { /* reorder line */ for (x = 0; x < settings.pixels; x++) { buffer[x * 6] = (*data)[y * settings.pixels * 6 + x * 2]; buffer[x * 6 + 1] = (*data)[y * settings.pixels * 6 + x * 2 + 1]; buffer[x * 6 + 2] = (*data)[y * settings.pixels * 6 + 2 * settings.pixels + x * 2]; buffer[x * 6 + 3] = (*data)[y * settings.pixels * 6 + 2 * settings.pixels + x * 2 + 1]; buffer[x * 6 + 4] = (*data)[y * settings.pixels * 6 + 4 * settings.pixels + x * 2]; buffer[x * 6 + 5] = (*data)[y * settings.pixels * 6 + 4 * settings.pixels + x * 2 + 1]; } /* copy line back */ memcpy ((*data) + settings.pixels * 6 * y, buffer, settings.pixels * 6); } } free (buffer); } /* end scan , waiting the motor to stop if needed (if moving), but without ejecting doc */ status = end_scan (dev, dev->reg, SANE_TRUE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { free (*data); DBG (DBG_error, "simple_scan: failed to end scan: %s\n", sane_strstatus (status)); return status; } DBG (DBG_proc, "simple_scan: end\n"); return status; } /** * Does a simple move of the given distance by doing a scan at lowest resolution * shading correction. Memory for data is allocated in this function * and must be freed by caller. * @param dev device of the scanner * @param distance distance to move in MM */ #ifndef UNIT_TESTING static #endif SANE_Status simple_move (Genesys_Device * dev, SANE_Int distance) { SANE_Status status; unsigned char *data = NULL; Genesys_Settings settings; DBG (DBG_proc, "simple_move: %d mm\n", distance); /* TODO give a no AGOHOME flag */ settings.scan_method = SCAN_METHOD_TRANSPARENCY; settings.scan_mode = SCAN_MODE_COLOR; settings.xres = get_lowest_resolution (dev->model->ccd_type, SANE_TRUE); settings.yres = settings.xres; settings.tl_y = 0; settings.tl_x = 0; settings.pixels = (dev->sensor.sensor_pixels * settings.xres) / dev->sensor.optical_res; settings.lines = (distance * settings.xres) / MM_PER_INCH; settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; status = simple_scan (dev, settings, SANE_TRUE, SANE_TRUE, SANE_FALSE, &data); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "simple_move: simple_scan failed\n"); } free (data); DBGCOMPLETED return status; } /** * update the status of the required sensor in the scanner session * the last_val fileds are used to make events 'sticky' */ static SANE_Status gl646_update_hardware_sensors (Genesys_Scanner * session) { Genesys_Device *dev = session->dev; uint8_t value; SANE_Status status; /* do what is needed to get a new set of events, but try to not loose any of them. */ status = gl646_gpio_read (dev->dn, &value); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_update_hardware_sensors: failed to read GPIO %s\n", sane_strstatus (status)); return status; } DBG (DBG_io, "gl646_update_hardware_sensors: GPIO=0x%02x\n", value); /* scan button */ if ((dev->model->buttons & GENESYS_HAS_SCAN_SW) && session->val[OPT_SCAN_SW].b == session->last_val[OPT_SCAN_SW].b) { switch (dev->model->gpo_type) { case GPO_XP200: session->val[OPT_SCAN_SW].b = ((value & 0x02) != 0); break; case GPO_5345: session->val[OPT_SCAN_SW].b = (value == 0x16); break; case GPO_HP2300: session->val[OPT_SCAN_SW].b = (value == 0x6c); break; case GPO_HP3670: case GPO_HP2400: session->val[OPT_SCAN_SW].b = ((value & 0x20) == 0); break; default: return SANE_STATUS_UNSUPPORTED; } } /* email button */ if ((dev->model->buttons & GENESYS_HAS_EMAIL_SW) && session->val[OPT_EMAIL_SW].b == session->last_val[OPT_EMAIL_SW].b) { switch (dev->model->gpo_type) { case GPO_5345: session->val[OPT_EMAIL_SW].b = (value == 0x12); break; case GPO_HP3670: case GPO_HP2400: session->val[OPT_EMAIL_SW].b = ((value & 0x08) == 0); break; default: return SANE_STATUS_UNSUPPORTED; } } /* copy button */ if ((dev->model->buttons & GENESYS_HAS_COPY_SW) && session->val[OPT_COPY_SW].b == session->last_val[OPT_COPY_SW].b) { switch (dev->model->gpo_type) { case GPO_5345: session->val[OPT_COPY_SW].b = (value == 0x11); break; case GPO_HP2300: session->val[OPT_COPY_SW].b = (value == 0x5c); break; case GPO_HP3670: case GPO_HP2400: session->val[OPT_COPY_SW].b = ((value & 0x10) == 0); break; default: return SANE_STATUS_UNSUPPORTED; } } /* power button */ if ((dev->model->buttons & GENESYS_HAS_POWER_SW) && session->val[OPT_POWER_SW].b == session->last_val[OPT_POWER_SW].b) { switch (dev->model->gpo_type) { case GPO_5345: session->val[OPT_POWER_SW].b = (value == 0x14); break; default: return SANE_STATUS_UNSUPPORTED; } } /* ocr button */ if ((dev->model->buttons & GENESYS_HAS_OCR_SW) && session->val[OPT_OCR_SW].b == session->last_val[OPT_OCR_SW].b) { switch (dev->model->gpo_type) { case GPO_5345: session->val[OPT_OCR_SW].b = (value == 0x13); break; default: return SANE_STATUS_UNSUPPORTED; } } /* document detection */ if ((dev->model->buttons & GENESYS_HAS_PAGE_LOADED_SW) && session->val[OPT_PAGE_LOADED_SW].b == session->last_val[OPT_PAGE_LOADED_SW].b) { switch (dev->model->gpo_type) { case GPO_XP200: session->val[OPT_PAGE_LOADED_SW].b = ((value & 0x04) != 0); break; default: return SANE_STATUS_UNSUPPORTED; } } /* XPA detection */ if (dev->model->flags & GENESYS_FLAG_XPA) { switch (dev->model->gpo_type) { case GPO_HP3670: case GPO_HP2400: /* test if XPA is plugged-in */ if ((value & 0x40) == 0) { DBG (DBG_io, "gl646_update_hardware_sensors: enabling XPA\n"); session->opt[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE; } else { DBG (DBG_io, "gl646_update_hardware_sensors: disabling XPA\n"); session->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; } break; default: return SANE_STATUS_UNSUPPORTED; } } return status; } static SANE_Status write_control (Genesys_Device * dev, int resolution) { SANE_Status status; uint8_t control[4]; uint32_t addr = 0xdead; /* 2300 does not write to 'control' */ if (dev->model->motor_type == MOTOR_HP2300) return SANE_STATUS_GOOD; /* MD6471/G2410/HP2300 and XP200 read/write data from an undocumented memory area which * is after the second slope table */ switch (dev->sensor.optical_res) { case 600: addr = 0x08200; break; case 1200: addr = 0x10200; break; case 2400: addr = 0x1fa00; break; default: DBG (DBG_error, "write_control: failed to compute control address\n"); return SANE_STATUS_INVAL; } /* XP200 sets dpi, what other scanner put is unknown yet */ switch (dev->model->motor_type) { case MOTOR_XP200: /* we put scan's dpi, not motor one */ control[0] = LOBYTE (resolution); control[1] = HIBYTE (resolution); control[2] = dev->control[4]; control[3] = dev->control[5]; break; case MOTOR_HP3670: case MOTOR_HP2400: case MOTOR_5345: default: control[0] = dev->control[2]; control[1] = dev->control[3]; control[2] = dev->control[4]; control[3] = dev->control[5]; break; } DBG (DBG_info, "write_control: control write=0x%02x 0x%02x 0x%02x 0x%02x\n", control[0], control[1], control[2], control[3]); status = sanei_genesys_set_buffer_address (dev, addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "write_control: failed to set up control address\n"); return SANE_STATUS_INVAL; } status = gl646_bulk_write_data (dev, 0x3c, control, 4); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "write_control: failed to set up control\n"); return SANE_STATUS_INVAL; } return status; } /** * check if a stored calibration is compatible with requested scan. * @return SANE_STATUS_GOOD if compatible, SANE_STATUS_UNSUPPORTED if not. * Whenever an error is met, it is returned. * @param dev scanner device * @param cache cache entry to test * @param for_overwrite reserved for future use ... */ static SANE_Status gl646_is_compatible_calibration (Genesys_Device * dev, Genesys_Calibration_Cache * cache, int for_overwrite) { #ifdef HAVE_SYS_TIME_H struct timeval time; #endif int compatible = 1; DBG (DBG_proc, "gl646_is_compatible_calibration: start (for_overwrite=%d)\n", for_overwrite); if (cache == NULL) return SANE_STATUS_UNSUPPORTED; /* build minimal current_setup for calibration cache use only, it will be better * computed when during setup for scan */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) { dev->current_setup.channels = 3; } else { dev->current_setup.channels = 1; } dev->current_setup.xres = dev->settings.xres; dev->current_setup.scan_method = dev->settings.scan_method; DBG (DBG_io, "gl646_is_compatible_calibration: requested=(%d,%f), tested=(%d,%f)\n", dev->current_setup.channels, dev->current_setup.xres, cache->used_setup.channels, cache->used_setup.xres); /* a calibration cache is compatible if color mode and x dpi match the user * requested scan. In the case of CIS scanners, dpi isn't a criteria */ if (dev->model->is_cis == SANE_FALSE) { compatible = ((dev->current_setup.channels == cache->used_setup.channels) && (((int) dev->current_setup.xres) == ((int) cache->used_setup.xres))); } else { compatible = (dev->current_setup.channels == cache->used_setup.channels); } if (dev->current_setup.scan_method != cache->used_setup.scan_method) { DBG (DBG_io, "gl646_is_compatible_calibration: current method=%d, used=%d\n", dev->current_setup.scan_method, cache->used_setup.scan_method); compatible = 0; } if (!compatible) { DBG (DBG_proc, "gl646_is_compatible_calibration: completed, non compatible cache\n"); return SANE_STATUS_UNSUPPORTED; } /* a cache entry expires after 30 minutes for non sheetfed scanners */ /* this is not taken into account when overwriting cache entries */ #ifdef HAVE_SYS_TIME_H if(for_overwrite == SANE_FALSE) { gettimeofday (&time, NULL); if ((time.tv_sec - cache->last_calibration > 30 * 60) && (dev->model->is_sheetfed == SANE_FALSE)) { DBG (DBG_proc, "gl646_is_compatible_calibration: expired entry, non compatible cache\n"); return SANE_STATUS_UNSUPPORTED; } } #endif DBG (DBG_proc, "gl646_is_compatible_calibration: completed, cache compatible\n"); return SANE_STATUS_GOOD; } /** * search for a full width black or white strip. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward * @param black SANE_TRUE if searching for a black strip, SANE_FALSE for a white strip * @return SANE_STATUS_GOOD if a matching strip is found, SANE_STATUS_UNSUPPORTED if not */ static SANE_Status gl646_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black) { SANE_Status status = SANE_STATUS_GOOD; SANE_Bool half_ccd = SANE_FALSE; Genesys_Settings settings; int res = get_closest_resolution (dev->model->ccd_type, 75, SANE_FALSE); unsigned char *data = NULL; unsigned int pass, count, found, x, y; char title[80]; DBG (DBG_proc, "gl646_search_strip: start\n"); /* adapt to half_ccd case */ if (dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE) { /* walk the master mode list to find if half_ccd */ if (is_half_ccd (dev->model->ccd_type, res, SANE_TRUE) == SANE_TRUE) { half_ccd = SANE_TRUE; } } /* we set up for a lowest available resolution color grey scan, full width */ settings.scan_method = SCAN_METHOD_FLATBED; settings.scan_mode = SCAN_MODE_GRAY; settings.xres = res; settings.yres = res; settings.tl_x = 0; settings.tl_y = 0; settings.pixels = (SANE_UNFIX (dev->model->x_size) * res) / MM_PER_INCH; if (half_ccd == SANE_TRUE) { settings.pixels /= 2; } /* 15 mm at at time */ settings.lines = (15 * settings.yres) / MM_PER_INCH; /* may become a parameter from genesys_devices.c */ settings.depth = 8; settings.color_filter = 0; settings.disable_interpolation = 0; settings.threshold = 0; settings.exposure_time = 0; settings.dynamic_lineart = SANE_FALSE; /* signals if a strip of the given color has been found */ found = 0; /* detection pass done */ pass = 0; /* loop until strip is found or maximum pass number done */ while (pass < 20 && !found) { /* scan a full width strip */ status = simple_scan (dev, settings, SANE_TRUE, forward, SANE_FALSE, &data); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl646_search_strip: simple_scan failed\n"); free (data); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s%02d.pnm", forward ? "fwd" : "bwd", (int)pass); sanei_genesys_write_pnm_file (title, data, settings.depth, 1, settings.pixels, settings.lines); } /* search data to find black strip */ /* when searching forward, we only need one line of the searched color since we * will scan forward. But when doing backward search, we need all the area of the * same color */ if (forward) { for (y = 0; y < settings.lines && !found; y++) { count = 0; /* count of white/black pixels depending on the color searched */ for (x = 0; x < settings.pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * settings.pixels + x] > 90) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * settings.pixels + x] < 60) { count++; } } /* at end of line, if count >= 3%, line is not fully of the desired color * so we must go to next line of the buffer */ /* count*100/pixels < 3 */ if ((count * 100) / settings.pixels < 3) { found = 1; DBG (DBG_data, "gl646_search_strip: strip found forward during pass %d at line %d\n", pass, y); } else { DBG (DBG_data, "gl646_search_strip: pixels=%d, count=%d\n", settings.pixels, count); } } } else /* since calibration scans are done forward, we need the whole area to be of the required color when searching backward */ { count = 0; for (y = 0; y < settings.lines; y++) { /* count of white/black pixels depending on the color searched */ for (x = 0; x < settings.pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * settings.pixels + x] > 60) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * settings.pixels + x] < 60) { count++; } } } /* at end of area, if count >= 3%, area is not fully of the desired color * so we must go to next buffer */ if ((count * 100) / (settings.pixels * settings.lines) < 3) { found = 1; DBG (DBG_data, "gl646_search_strip: strip found backward during pass %d \n", pass); } else { DBG (DBG_data, "gl646_search_strip: pixels=%d, count=%d\n", settings.pixels, count); } } pass++; } free (data); if (found) { status = SANE_STATUS_GOOD; DBG (DBG_info, "gl646_search_strip: strip found\n"); } else { status = SANE_STATUS_UNSUPPORTED; DBG (DBG_info, "gl646_search_strip: strip not found\n"); } return status; } /** the gl646 command set */ static Genesys_Command_Set gl646_cmd_set = { "gl646-generic", /* the name of this set */ gl646_init, gl646_init_regs_for_warmup, gl646_init_regs_for_coarse_calibration, gl646_init_regs_for_shading, gl646_init_regs_for_scan, gl646_get_filter_bit, gl646_get_lineart_bit, gl646_get_bitset_bit, gl646_get_gain4_bit, gl646_get_fast_feed_bit, gl646_test_buffer_empty_bit, gl646_test_motor_flag_bit, gl646_bulk_full_size, gl646_public_set_fe, gl646_set_powersaving, gl646_save_power, gl646_set_motor_power, gl646_set_lamp_power, gl646_begin_scan, gl646_end_scan, gl646_send_gamma_table, gl646_search_start_position, gl646_offset_calibration, gl646_coarse_gain_calibration, gl646_led_calibration, gl646_slow_back_home, NULL, gl646_bulk_write_register, gl646_bulk_write_data, gl646_bulk_read_data, gl646_update_hardware_sensors, /* sheetfed related functions */ gl646_load_document, gl646_detect_document_end, gl646_eject_document, gl646_search_strip, gl646_is_compatible_calibration, gl646_move_to_ta, NULL, NULL, NULL, NULL }; SANE_Status sanei_gl646_init_cmd_set (Genesys_Device * dev) { dev->model->cmd_set = &gl646_cmd_set; return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/mustek_pp_cis.c0000664000175000017500000025770312775312261015646 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2003 Eddy De Greef This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek PP flatbed _CIS_ scanners. */ /* Global picture Mustek_PP_handle -> Mustek_PP_dev -> priv = Mustek_PP_CIS_dev -> CIS */ /* * This flag determines whether the scanner uses fast skipping at high * resolutions. It is possible that this fast skipping introduces * inaccuracies. It if turns out to be a problem, fast skipping can * be disabled by setting this flag to 0. */ #define MUSTEK_PP_CIS_FAST_SKIP 1 #define MUSTEK_PP_CIS_WAIT_BANK 200 /* * These parameters determine where the scanable area starts at the top. * If there is a consistent offset error, you can tune it through these * parameters. Note that an inaccuracy in the order of 1 mm seems to be * normal for the Mustek 600/1200 CP series. */ #define MUSTEK_PP_CIS_600CP_DEFAULT_SKIP 250 #define MUSTEK_PP_CIS_1200CP_DEFAULT_SKIP 330 /* * Number of scan lines on which the average is taken to determine the * maximum number of color levels. */ #define MUSTEK_PP_CIS_AVERAGE_COUNT 32 #define MUSTEK_PP_CIS600 1 #define MUSTEK_PP_CIS1200 2 #define MUSTEK_PP_CIS1200PLUS 3 #define MUSTEK_PP_CIS_CHANNEL_RED 0 #define MUSTEK_PP_CIS_CHANNEL_GREEN 1 #define MUSTEK_PP_CIS_CHANNEL_BLUE 2 #define MUSTEK_PP_CIS_CHANNEL_GRAY 1 #define MUSTEK_PP_CIS_MAX_H_PIXEL 5118 #define MUSTEK_PP_CIS_MAX_V_PIXEL 7000 #define MUSTEK_PP_CIS_MOTOR_REVERSE 0 #include "../include/sane/config.h" #include #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H # include #endif #include "../include/sane/sane.h" #include "../include/sane/sanei_pa4s2.h" #define DEBUG_DECLARE_ONLY #include "mustek_pp.h" #include "mustek_pp_decl.h" #include "mustek_pp_cis.h" /****************************************************************************** ****************************************************************************** *** MA1015 chipset related functionality *** ****************************************************************************** *****************************************************************************/ /* These defines control some debugging functionality #define M1015_TRACE_REGS -> trace the status of the internal registers #define M1015_LOG_HL -> create a high-level log file (register-level) #define M1015_LOG_LL -> create a low-level log file (byte-level) By default, all logging/tracing is turned off. */ /****************************************************************************** * Low level logging: logs read and writes at the byte level, similar to * the sequences produced by tool of Jochen Eisinger * for analysing the TWAIN driver communication. * This simplifies comparison of the sequences. *****************************************************************************/ #ifdef M1015_LOG_LL static FILE* M1015_LOG_1; #define M1015_START_LL\ M1015_LOG_1 = fopen("cis_ll.log", "w"); #define M1015_STOP_LL\ fclose(M1015_LOG_1); #define SANEI_PA4S2_WRITEBYTE(fd, reg, val)\ do\ {\ sanei_pa4s2_writebyte (fd, reg, val);\ fprintf(M1015_LOG_1, "\tsanei_pa4s2_writebyte(fd, %d, 0x%02X);\n", \ reg, val);\ } while (0) static const char* cis_last_rreg_name; static int cis_read_count; #define SANEI_PA4S2_READBEGIN(fd, reg)\ do\ {\ cis_last_rreg_name = Mustek_PP_1015_reg_r_name(reg);\ cis_read_count = 0;\ sanei_pa4s2_readbegin(fd, reg);\ } while (0) #define SANEI_PA4S2_READBYTE(fd, val)\ do\ {\ sanei_pa4s2_readbyte(fd, val);\ ++cis_read_count;\ } while (0) #define SANEI_PA4S2_READEND(fd)\ do\ {\ sanei_pa4s2_readend(fd);\ fprintf(M1015_LOG_1, "\tread_reg(%s, %d);\n", \ cis_last_rreg_name, cis_read_count);\ } while (0) #define M1015_MARK_LL(info)\ fprintf(M1015_LOG_1, "* %s\n", info); #else /* M1015_LOG_LL */ #define M1015_START_LL #define M1015_STOP_LL #define SANEI_PA4S2_WRITEBYTE(fd, reg, val)\ sanei_pa4s2_writebyte (fd, reg, val) #define SANEI_PA4S2_READBEGIN(fd, reg)\ sanei_pa4s2_readbegin(fd, reg) #define SANEI_PA4S2_READBYTE(fd, val)\ sanei_pa4s2_readbyte(fd, val) #define SANEI_PA4S2_READEND(fd)\ sanei_pa4s2_readend(fd) #define M1015_MARK_LL(info) #endif /* M1015_LOG_LL */ /****************************************************************************** * High-level logging: traces the flow of the driver in a hierarchical way * up to the level of register acccesses. *****************************************************************************/ #ifdef M1015_LOG_HL static FILE* M1015_LOG_2; static char hl_prev_line[4096], hl_next_line[4096], hl_repeat_count; /* * A few variables for hierarchical log message indentation. */ static const char* cis_indent_start = " "; static const char* cis_indent; static const char* cis_indent_end; #define M1015_START_HL\ M1015_LOG_2 = fopen("cis_hl.log", "w");\ cis_indent = cis_indent_start + strlen(cis_indent_start);\ cis_indent_end = cis_indent;\ hl_prev_line[0] = 0;\ hl_next_line[0] = 0;\ hl_repeat_count = 0; #define M1015_FLUSH_HL\ if (strcmp(hl_prev_line, hl_next_line))\ {\ fprintf(M1015_LOG_2, &hl_prev_line[0]);\ strcpy(&hl_prev_line[0], &hl_next_line[0]);\ if (hl_repeat_count != 0)\ {\ fprintf(M1015_LOG_2, "%s [last message repeated %d times]\n",\ cis_indent, hl_repeat_count+1); \ }\ hl_repeat_count = 0;\ }\ else\ {\ hl_repeat_count += 1;\ } #define M1015_MARK(info)\ sprintf(&hl_next_line[0], "%s+ %s\n", cis_indent, info);\ M1015_FLUSH_HL #define M1015_STOP_HL\ hl_next_line[0] = 0;\ M1015_FLUSH_HL\ fclose(M1015_LOG_2); #else /* M1015_LOG_HL */ #define M1015_START_HL #define M1015_STOP_HL #define M1015_MARK(info) #define M1015_FLUSH_HL #endif /* M1015_LOG_HL */ #ifdef M1015_TRACE_REGS #define M1015_DISPLAY_REGS(dev, msg) Mustek_PP_1015_display_regs(dev, msg) #define M1015_DISPLAY_REG(msg, val) Mustek_PP_1015_display_reg(msg, val) #else #define M1015_DISPLAY_REGS(dev, msg) #define M1015_DISPLAY_REG(msg, val) #endif #if defined (M1015_LOG_HL) || defined (M1015_LOG_LL) static const char* Mustek_PP_1015_reg_r_name(Mustek_PP_1015R_reg id) { static const char* names[4] = { "ASIC", "SCAN_VAL", "MOTOR", "BANK_COUNT" }; return names[id & 0x03]; } static const char* Mustek_PP_1015_bit_name(Mustek_PP_1015R_bit id) { static const char* names[4] = { "????", "MOTOR_HOME", "????", "MOTOR_BUSY" }; return names[id & 0x03]; } static const char* Mustek_PP_1015_reg_w_name(Mustek_PP_1015R_reg id) { static const char* names[4][4] = { { "RED_REF", "GREEN_REF", "BLUE_REF", "DPI_CONTROL" }, { "BYTE_COUNT_HB", "BYTE_COUNT_LB", "SKIP_COUNT", "EXPOSE_TIME" }, { "SRAM_SOURCE_PC", "MOTOR_CONTROL", "UNKNOWN_42", "UNKNOWN_82" }, { "POWER_ON_DELAY", "CCD_TIMING", "CCD_TIMING_ADJ", "RIGHT_BOUND" } }; return names[(id & 0x30) >> 4][id & 0x03]; } #endif /****************************************************************************** * Converts a register value to a hex/dec/bin representation. *****************************************************************************/ static const char* Mustek_PP_1015_show_val(int val) { /* Since we use a static temporary buffer, we must make sure that the buffer isn't altered while it is still in use (typically because more than one value is converted in a printf statement). Therefore the buffer is organized as a ring buffer. If should contain at least 21 elements in order to be able to display all registers with one printf statement. */ #define Mustek_PP_1015_RING_BUFFER_SIZE 50 static char buf[Mustek_PP_1015_RING_BUFFER_SIZE][64]; static int index = 0; int i; char* current = (char*)buf[index++]; if (index >= Mustek_PP_1015_RING_BUFFER_SIZE) index = 0; if (val < 0) { /* The register has not been initialized yet. */ sprintf(current, "---- (---) --------"); } else { sprintf(current, "0x%02X (%3d) ", val & 0xFF, val & 0xFF); for (i=0; i<8; ++i) { sprintf(current+11+i, "%d", (val >> (7-i)) & 1); } } return current; } #ifdef M1015_TRACE_REGS /****************************************************************************** * Displays the contents of all registers of the scanner on stderr. *****************************************************************************/ static void Mustek_PP_1015_display_regs(Mustek_PP_CIS_dev * dev, const char* info) { /* * Register naming convention: * Rx : read-only register no. x * ByWx : write-only register no. x of bank no. y */ fprintf(stderr, "\n" "Register status: %s\n" "\n" " R0: %s : ASIC info\n" " R1: %s : scan value\n" " R2: %s : CCD/motor info\n" " R3: %s : bank count\n" "\n" " B0W0: %s : red reference\n" " B0W1: %s : green reference\n" " B0W2: %s : blue reference\n" " B0W3: %s : DPI control\n" "\n" " B1W0: %s : byte count, high byte\n" " B1W1: %s : byte count, low byte\n" " B1W2: %s : skip x32 pixels\n" " B1W3: %s : expose time (CCDWIDTH)\n" "\n" " B2W0: %s : SRAM source PC\n" " B2W1: %s : motor control\n" " B2W2: %s : -\n" " B2W3: %s : -\n" "\n" " B3W0: %s : power on delay\n" " B3W1: %s : CCD timing - always 0x05\n" " B3W2: %s : CCD timing adjust - always 0x00\n" " B3W3: %s : right bound (not used)\n" "\n" " CHAN: %s : channel [%s]\n" "\n", info, Mustek_PP_1015_show_val (dev->CIS.regs.in_regs[0]), Mustek_PP_1015_show_val (dev->CIS.regs.in_regs[1]), Mustek_PP_1015_show_val (dev->CIS.regs.in_regs[2]), Mustek_PP_1015_show_val (dev->CIS.regs.in_regs[3]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[0][0]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[0][1]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[0][2]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[0][3]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[1][0]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[1][1]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[1][2]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[1][3]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[2][0]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[2][1]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[2][2]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[2][3]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[3][0]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[3][1]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[3][2]), Mustek_PP_1015_show_val (dev->CIS.regs.out_regs[3][3]), Mustek_PP_1015_show_val (dev->CIS.regs.channel), (dev->CIS.regs.channel == 0x80 ? "RED" : (dev->CIS.regs.channel == 0x40 ? "GREEN" : (dev->CIS.regs.channel == 0xC0 ? "BLUE" : "unknown"))) ); } /****************************************************************************** * Displays a single register value *****************************************************************************/ static void Mustek_PP_1015_display_reg(const char* info, int val) { fprintf (stderr, "%s: %s\n", info, Mustek_PP_1015_show_val(val)); } #endif /* M1015_TRACE_REGS */ /****************************************************************************** * * Reads one of the 4 internal registers of the scanner * * 0: ASIC identification * 1: scan values * 2: CCD info / motor info * 3: bank count info * *****************************************************************************/ static SANE_Byte Mustek_PP_1015_read_reg(Mustek_PP_CIS_dev * dev, Mustek_PP_1015R_reg reg) { SANE_Byte tmp; assert(reg <= 3); SANEI_PA4S2_READBEGIN (dev->desc->fd, reg & 0x03); SANEI_PA4S2_READBYTE (dev->desc->fd, &tmp); SANEI_PA4S2_READEND (dev->desc->fd); #ifdef M1015_LOG_HL sprintf(&hl_next_line[0], "%s read_reg(%s); [%s]\n", cis_indent, Mustek_PP_1015_reg_r_name(reg), Mustek_PP_1015_show_val(tmp)); M1015_FLUSH_HL; #endif #ifdef M1015_TRACE_REGS dev->CIS.regs.in_regs[reg & 0x03] = tmp; #endif return tmp; } /****************************************************************************** * * Waits for a bit of register to become 1 or 0. The period of checking can be * controlled through the sleep parameter (microseconds). * *****************************************************************************/ static SANE_Bool Mustek_PP_1015_wait_bit(Mustek_PP_CIS_dev * dev, Mustek_PP_1015R_reg reg, Mustek_PP_1015R_bit bit, SANE_Bool on, unsigned period) { SANE_Byte tmp; SANE_Byte mask, val; int tries = 0; assert(reg <= 3); assert(bit <= 3); mask = 1 << bit; /* We don't want to wait forever */ while (dev->desc->state != STATE_CANCELLED) { #if defined (M1015_LOG_LL) || defined (M1015_LOG_HL) ++tries; #endif sanei_pa4s2_readbegin (dev->desc->fd, reg & 0x03); sanei_pa4s2_readbyte (dev->desc->fd, &tmp); sanei_pa4s2_readend (dev->desc->fd); #ifdef M1015_LOG_HL sprintf(&hl_next_line[0], "%s wait_bit(%s, %s, %d): %s %s;\n", cis_indent, Mustek_PP_1015_reg_r_name(reg), Mustek_PP_1015_bit_name(bit), on?1:0, Mustek_PP_1015_show_val(mask), Mustek_PP_1015_show_val(tmp)); M1015_FLUSH_HL; #endif val = ((on == SANE_TRUE) ? tmp : ~tmp ) & mask; if (val != 0) break; if (period) usleep(period); if (tries > 50000) { #ifdef M1015_LOG_HL sprintf(&hl_next_line[0], "%s wait_bit(%s, %s, %d): failed;\n", cis_indent, Mustek_PP_1015_reg_r_name(reg), Mustek_PP_1015_bit_name(bit), on?1:0); M1015_FLUSH_HL; #endif DBG(2, "Mustek_PP_1015_wait_bit: failed (reg %d, bit %d, on: %d)\n", reg, bit, on?1:0); return SANE_FALSE; } } #ifdef M1015_LOG_HL sprintf(&hl_next_line[0], "%s wait_bit(%s, %s, %d);\n", cis_indent, Mustek_PP_1015_reg_r_name(reg), Mustek_PP_1015_bit_name(bit), on?1:0); M1015_FLUSH_HL; #endif #ifdef M1015_LOG_LL fprintf(M1015_LOG_1, "\tread_reg(%s, %d);\n", Mustek_PP_1015_reg_r_name(reg), tries); #endif #ifdef M1015_TRACE_REGS dev->CIS.regs.in_regs[reg & 0x03] = tmp; #endif return dev->desc->state != STATE_CANCELLED ? SANE_TRUE : SANE_FALSE; } /****************************************************************************** * * Writes one out of 4 registers of one of the 4 register banks (I guess) * * Bank 0 * 0: voltage red --+ * 1: voltage green +-> always set to 0x96 * 2: voltage blue --+ * 3: DPI control * * Bank 1 * 0: line adjust (?) - high byte * 1: line adjust (?) - low byte * 2: unknown (values seen: 0x00, 0x02, 0x03, 0x1D) * 3: expose time (?) (values seen: 0xAA, 0xFD, 0xFE, 0xFF) * * Bank 2 * 0: unknown, used to start linear sequence during calibration * 1: motor control code (forward, return home, ...) * 2: never used * 3: never used * * Bank 3 * 0: reduction factor (16bit internal -> 8bit) -> target for calibration * 1: unknown -> always set to 0x05 * 2: unknown -> always set to 0x00 * 3: never used * *****************************************************************************/ static void Mustek_PP_1015_write_reg(Mustek_PP_CIS_dev * dev, Mustek_PP_1015W_reg reg, SANE_Byte val) { SANE_Byte regBank = (reg & 0xF0) >> 4; SANE_Byte regNo = (reg & 0x0F); assert (regNo <= 3); assert (regBank <= 3); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, (1 << (4+regNo))+ regBank); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 5, val); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, regBank); #ifdef M1015_TRACE_REGS dev->CIS.regs.out_regs[regBank][regNo] = val; #endif #ifdef M1015_LOG_HL sprintf(&hl_next_line[0], "%s write_reg(%s, 0x%02X);\n", cis_indent, Mustek_PP_1015_reg_w_name(reg), val); M1015_FLUSH_HL; #endif } /****************************************************************************** * * Writes 2 values to 2 adjecent registers. * It is probably equivalent to 2 simple write operations (but I'm not sure). * * val1 is written to register[regNo] * val2 is written to register[regNo+1] * *****************************************************************************/ static void Mustek_PP_1015_write_reg2(Mustek_PP_CIS_dev * dev, Mustek_PP_1015W_reg reg, SANE_Byte val1, SANE_Byte val2) { SANE_Byte regBank = (reg & 0xF0) >> 4; SANE_Byte regNo = (reg & 0x0F); assert (regNo <= 2); assert (regBank <= 3); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, (1 << (4+regNo))+ regBank); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 5, val1); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, (1 << (5+regNo))+ regBank); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 5, val2); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, regBank); #ifdef M1015_TRACE_REGS dev->CIS.regs.out_regs[regBank][regNo] = val1; dev->CIS.regs.out_regs[regBank][regNo+1] = val2; #endif #ifdef M1015_LOG_HL sprintf(&hl_next_line[0], "%s write_reg2(%s, 0x%02X, 0x%02X);\n", cis_indent, Mustek_PP_1015_reg_w_name(reg), val1, val2); M1015_FLUSH_HL; #endif } /****************************************************************************** * * Writes 3 values to 3 adjecent registers. * It is probably equivalent to 3 simple write operations (but I'm not sure). * * val1 is written to register[regNo] * val2 is written to register[regNo+1] * val3 is written to register[regNo+2] * *****************************************************************************/ static void Mustek_PP_1015_write_reg3(Mustek_PP_CIS_dev * dev, Mustek_PP_1015W_reg reg, SANE_Byte val1, SANE_Byte val2, SANE_Byte val3) { SANE_Byte regBank = (reg & 0xF0) >> 4; SANE_Byte regNo = (reg & 0x0F); assert (regNo <= 1); assert (regBank <= 3); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, (1 << (4+regNo))+ regBank); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 5, val1); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, (1 << (5+regNo))+ regBank); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 5, val2); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, (1 << (6+regNo))+ regBank); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 5, val3); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, regBank); #ifdef M1015_TRACE_REGS dev->CIS.regs.out_regs[regBank][regNo ] = val1; dev->CIS.regs.out_regs[regBank][regNo+1] = val2; dev->CIS.regs.out_regs[regBank][regNo+2] = val3; #endif #ifdef M1015_LOG_HL sprintf(&hl_next_line[0], "%s write_reg3(%s, 0x%02X, 0x%02X, 0x%02X);\n", cis_indent, Mustek_PP_1015_reg_w_name(reg), val1, val2, val3); M1015_FLUSH_HL; #endif } /****************************************************************************** * Opens a register for a (series of) write operation(s). *****************************************************************************/ static void Mustek_PP_1015_write_reg_start(Mustek_PP_CIS_dev * dev, Mustek_PP_1015W_reg reg) { SANE_Byte regBank = (reg & 0xF0) >> 4; SANE_Byte regNo = (reg & 0x0F); assert (regNo <= 3); assert (regBank <= 3); dev->CIS.regs.current_write_reg = reg; #ifdef M1015_LOG_HL dev->CIS.regs.write_count = 0; #endif SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, (1 << (4+regNo))+ regBank); } /****************************************************************************** * Writes a value to the currently open register. *****************************************************************************/ static void Mustek_PP_1015_write_reg_val(Mustek_PP_CIS_dev * dev, SANE_Byte val) { #ifdef M1015_TRACE_REGS SANE_Byte regBank = (dev->CIS.regs.current_write_reg & 0xF0) >> 4; SANE_Byte regNo = (dev->CIS.regs.current_write_reg & 0x0F); assert (regNo <= 3); assert (regBank <= 3); dev->CIS.regs.out_regs[regBank][regNo] = val; #endif SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 5, val); #ifdef M1015_LOG_HL ++dev->CIS.regs.write_count; #endif } /****************************************************************************** * Closes a register after a (series of) write operation(s). *****************************************************************************/ static void Mustek_PP_1015_write_reg_stop(Mustek_PP_CIS_dev * dev) { SANE_Byte regBank = (dev->CIS.regs.current_write_reg & 0xF0) >> 4; #ifdef M1015_LOG_HL SANE_Byte regNo = (dev->CIS.regs.current_write_reg & 0x0F); assert (regNo <= 3); sprintf(&hl_next_line[0], "%s write_reg_multi(%s, *%d);\n", cis_indent, Mustek_PP_1015_reg_w_name(dev->CIS.regs.current_write_reg), dev->CIS.regs.write_count); M1015_FLUSH_HL; #endif assert (regBank <= 3); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, regBank); } /****************************************************************************** * * Sends a command to the scanner. The command should not access one of the * internal registers, ie., the 3rd bit should not be zero. * *****************************************************************************/ static void Mustek_PP_1015_send_command(Mustek_PP_CIS_dev * dev, SANE_Byte command) { assert (command & 0x04); SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, command); #ifdef M1015_LOG_HL sprintf(&hl_next_line[0], "%s send_command(0x%02X);\n", cis_indent, command); M1015_FLUSH_HL; #endif } /****************************************************************************** ############################################################################## ## CIS driver ## ############################################################################## *****************************************************************************/ /****************************************************************************** * Resolution conversion functions *****************************************************************************/ static int max2hw_hres(Mustek_PP_CIS_dev *dev, int dist) { return (int)((dist * dev->CIS.hw_hres) / dev->desc->dev->maxres + 0.5); } #ifdef NOT_USED static int max2hw_vres(Mustek_PP_CIS_dev *dev, int dist) { return (int)((dist * dev->CIS.hw_vres) / dev->desc->dev->maxres + 0.5); } #endif static int max2cis_hres(Mustek_PP_CIS_dev *dev, int dist) { return (int)((dist * dev->CIS.cisRes) / dev->desc->dev->maxres + 0.5); } static int cis2max_res(Mustek_PP_CIS_dev *dev, int dist) { return (int)((dist * dev->desc->dev->maxres) / dev->CIS.cisRes + 0.5); } #ifdef NOT_USED static int hw2max_vres(Mustek_PP_CIS_dev *dev, int dist) { return (int)((dist * dev->desc->dev->maxres) / dev->CIS.hw_vres + 0.5); } #endif /****************************************************************************** * Attempts to extract the current bank no. *****************************************************************************/ static void cis_get_bank_count(Mustek_PP_CIS_dev *dev) { dev->bank_count = (Mustek_PP_1015_read_reg(dev, MA1015R_BANK_COUNT) & 0x7); if (dev->CIS.use8KBank) dev->bank_count >>= 1; } /****************************************************************************** * Triggers a bank switch (I assume). *****************************************************************************/ static void cis_set_sti(Mustek_PP_CIS_dev *dev) { SANEI_PA4S2_WRITEBYTE(dev->desc->fd, 3, 0xFF); dev->bank_count++; dev->bank_count &= (dev->CIS.use8KBank == SANE_TRUE) ? 3 : 7; } /****************************************************************************** * Wait till the bank with a given number becomes available. *****************************************************************************/ static SANE_Bool cis_wait_bank_change (Mustek_PP_CIS_dev * dev, int bankcount) { struct timeval start, end; unsigned long diff; int firsttime = 1; gettimeofday (&start, NULL); do { if (1 /*niceload*/) { if (firsttime) firsttime = 0; else usleep (10); /* for a little nicer load */ } cis_get_bank_count (dev); gettimeofday (&end, NULL); diff = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); } while ((dev->bank_count != bankcount) && (diff < MUSTEK_PP_CIS_WAIT_BANK)); if (dev->bank_count != bankcount && dev->desc->state != STATE_CANCELLED) { u_char tmp; tmp = Mustek_PP_1015_read_reg(dev, 3); DBG(2, "cis_wait_bank_change: Missed a bank: got %d [%s], " "wanted %d, waited %d msec\n", dev->bank_count, Mustek_PP_1015_show_val(tmp), bankcount, MUSTEK_PP_CIS_WAIT_BANK); } return dev->bank_count == bankcount ? SANE_TRUE : SANE_FALSE; } /****************************************************************************** * Configure the CIS for a given resolution. * * CIS scanners seem to have 2 modes: * * low resolution (50-300 DPI) and * high resolution (300-600 DPI). * * Depending on the resolution requested by the user, the scanner is used * in high or low resolution mode. In high resolution mode, the motor step * sizes are also reduced by a factor of two. * *****************************************************************************/ static void cis_set_dpi_value (Mustek_PP_CIS_dev * dev) { u_char val = 0; if (dev->model == MUSTEK_PP_CIS1200PLUS) { /* Toshiba CIS: only 600 DPI + decimation */ switch (dev->CIS.hw_hres) { case 75: val = 0x48; /* 1/8 */ break; case 100: val = 0x08; /* 1/6 */ break; case 200: val = 0x00; /* 1/3 */ break; case 300: val = 0x50; /* 2/4 */ break; case 400: val = 0x10; /* 2/3 */ break; case 600: val = 0x20; /* 3/3 */ break; default: assert (0); } } else { /* Canon CIS: sensor can use 300 or 600 DPI */ switch (dev->CIS.hw_hres) { case 50: val = 0x08; /* 1/6 */ break; case 100: val = 0x00; /* 1/3 */ break; case 200: val = 0x10; /* 2/3 */ break; case 300: val = 0x20; /* 3/3 */ break; case 400: val = 0x10; /* 2/3 */ break; case 600: val = 0x20; /* 3/3 */ break; default: assert (0); } } Mustek_PP_1015_write_reg(dev, MA1015W_DPI_CONTROL, val | 0x04); DBG (4, "cis_set_dpi_value: dpi: %d -> value 0x%02x\n", dev->CIS.hw_hres, val); } static void cis_set_ccd_channel (Mustek_PP_CIS_dev * dev) { SANE_Byte codes[] = { 0x84, 0x44, 0xC4 }; SANE_Byte chancode; assert (dev->CIS.channel < 3); chancode = codes[dev->CIS.channel]; /* The TWAIN driver sets an extra bit in lineart mode. When I do this too, I don't see any effect on the image. Moreover, for 1 resolution, namely 400 dpi, the bank counter seems to behave strangely, and the synchronization get completely lost. I guess the software conversion from gray to lineart is good enough, so I'll leave it like that. if (dev->CIS.setParameters) { chancode |= (dev->desc->mode == MODE_BW) ? 0x20: 0; } */ SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, chancode); #ifdef M1015_TRACE_REGS dev->CIS.regs.channel = chancode; #endif } static void cis_config_ccd (Mustek_PP_CIS_dev * dev) { SANE_Int skipCount, byteCount; if (dev->CIS.res != 0) dev->CIS.hres_step = SANE_FIX ((float) dev->CIS.hw_hres / (float) dev->CIS.res); /* CIS: <= 300 dpi -> 0x86 > 300 dpi -> 0x96 */ if (dev->CIS.cisRes == 600) SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, 0x96); else SANEI_PA4S2_WRITEBYTE (dev->desc->fd, 6, 0x86); cis_set_dpi_value(dev); if (dev->CIS.setParameters) { dev->CIS.channel = dev->desc->mode == MODE_COLOR ? MUSTEK_PP_CIS_CHANNEL_RED : MUSTEK_PP_CIS_CHANNEL_GRAY; } else { dev->CIS.channel = MUSTEK_PP_CIS_CHANNEL_GRAY; } cis_set_ccd_channel (dev); Mustek_PP_1015_write_reg (dev, MA1015W_POWER_ON_DELAY, 0xAA); Mustek_PP_1015_write_reg (dev, MA1015W_CCD_TIMING, 0x05); Mustek_PP_1015_write_reg (dev, MA1015W_CCD_TIMING_ADJ, 0x00); Mustek_PP_1015_send_command (dev, 0x45); /* or 0x05 for no 8kbank */ /* * Unknown sequence. * Seems to be always the same during configuration, independent of the * mode and the resolution. */ CIS_CLEAR_FULLFLAG(dev); CIS_INC_READ(dev); CIS_CLEAR_READ_BANK(dev); CIS_CLEAR_WRITE_ADDR(dev); CIS_CLEAR_WRITE_BANK(dev); CIS_CLEAR_TOGGLE(dev); /* # SkipImage = expressed in max resolution (600 DPI) # # Formulas # # <= 300 DPI: # # Skip = 67 + skipimage/2 # # Skip1 = Skip / 32 # Skip2 = Skip % 32 # # Bytes = Skip2 * hw_hres/300 + (imagebytes * hw_hres/res) + 2 # # > 300 DPI # # Skip = 67 + skipimage # # Skip1 = Skip / 32 # Skip2 = Skip % 32 # # Bytes = Skip2*hw_hres/600 + (imagebytes * hw_hres/res) + 2 # */ skipCount = 67; /* Hardware parameter - fixed */ if (dev->CIS.setParameters == SANE_TRUE) { /* * It seems that the TWAIN driver always adds 2 mm extra. When I do the * inverse calculation from the parameters that driver sends, I always * get a difference of exactly 2mm, at every resolution and for * different positions of the scan area. Moreover, when I don't add this * offset, the resulting scan seems to start 2mm to soon. * I can't find this back in the backend of the TWAIN driver, but I * assume that this 2mm offset is taken care off at the higher levels. */ DBG(4, "cis_config_ccd: Skip count: %d\n", skipCount); skipCount += max2cis_hres(dev, dev->CIS.skipimagebytes); DBG(4, "cis_config_ccd: Skip count: %d (cis res: %d)\n", skipCount, dev->CIS.cisRes); skipCount += (int)(2.0/25.4*dev->CIS.cisRes); DBG(4, "cis_config_ccd: Skip count: %d\n", skipCount); Mustek_PP_1015_write_reg (dev, MA1015W_SKIP_COUNT, skipCount / 32); DBG(4, "cis_config_ccd: Skip count: %d (x32)\n", skipCount / 32); } else { Mustek_PP_1015_write_reg (dev, MA1015W_SKIP_COUNT, 0); DBG(4, "cis_config_ccd: Skip count: 67 (x32)\n"); } skipCount %= 32; skipCount = cis2max_res(dev, skipCount); /* Back to max res */ Mustek_PP_1015_write_reg(dev, MA1015W_EXPOSE_TIME, dev->CIS.exposeTime); DBG(4, "cis_config_ccd: skipcount: %d imagebytes: %d\n", skipCount, dev->CIS.imagebytes); /* set_initial_skip_1015 (dev); */ if (dev->CIS.setParameters == SANE_TRUE) { Mustek_PP_1015_write_reg(dev, MA1015W_EXPOSE_TIME, dev->CIS.exposeTime); Mustek_PP_1015_write_reg(dev, MA1015W_POWER_ON_DELAY, 0xAA); /* The TWAIN drivers always sends the same value: 0x96 */ Mustek_PP_1015_write_reg3(dev, MA1015W_RED_REF, 0x96, 0x96, 0x96); dev->CIS.adjustskip = max2hw_hres(dev, skipCount); byteCount = max2hw_hres(dev, skipCount + dev->CIS.imagebytes) + 2; dev->CIS.setParameters = SANE_FALSE; } else { dev->CIS.adjustskip = 0; byteCount = max2hw_hres(dev, skipCount); } DBG(4, "cis_config_ccd: adjust skip: %d bytecount: %d\n", dev->CIS.adjustskip, byteCount); Mustek_PP_1015_write_reg2(dev, MA1015W_BYTE_COUNT_HB, byteCount >> 8, byteCount & 0xFF); cis_get_bank_count (dev); DBG(5, "cis_config_ccd: done\n"); } static SANE_Bool cis_wait_motor_stable (Mustek_PP_CIS_dev * dev) { static struct timeval timeoutVal; SANE_Bool ret = Mustek_PP_1015_wait_bit (dev, MA1015R_MOTOR, MA1015B_MOTOR_STABLE, SANE_FALSE, 0); #ifdef HAVE_SYS_SELECT_H if (dev->engine_delay > 0) { timeoutVal.tv_sec = 0; timeoutVal.tv_usec = dev->engine_delay*1000; select(0, NULL, NULL, NULL, &timeoutVal); } #endif return ret; } static void cis_motor_forward (Mustek_PP_CIS_dev * dev) { SANE_Byte control; if (dev->model == MUSTEK_PP_CIS600) { switch (dev->CIS.hw_vres) { case 150: control = 0x7B; break; case 300: control = 0x73; break; case 600: control = 0x13; break; default: exit(1); } } else { switch (dev->CIS.hw_vres) { case 300: control = 0x7B; break; case 600: control = 0x73; break; case 1200: control = 0x13; break; default: exit(1); } } #if MUSTEK_PP_CIS_MOTOR_REVERSE == 1 control ^= 0x10; #endif DBG(4, "cis_motor_forward: @%d dpi: 0x%02X.\n", dev->CIS.hw_vres, control); if (!cis_wait_motor_stable (dev)) return; Mustek_PP_1015_write_reg(dev, MA1015W_MOTOR_CONTROL, control); } static void cis_move_motor (Mustek_PP_CIS_dev * dev, SANE_Int steps) /* steps @ maxres */ { /* Note: steps is expressed at maximum resolution */ SANE_Byte fullStep = 0x13, biStep = 0x73, quadStep = 0x7B; SANE_Int fullSteps, biSteps, quadSteps; /* * During a multi-step feed, the expose time is fixed. The value depends * on the type of the motor (600/1200 CP) */ SANE_Byte savedExposeTime = dev->CIS.exposeTime; dev->CIS.exposeTime = 85; DBG(4, "cis_move_motor: Moving motor %d steps.\n", steps); /* Just in case ... */ if (steps < 0) { DBG(1, "cis_move_motor: trying to move negative steps: %d\n", steps); steps = 0; /* We must go through the configuration procedure */ } /* * Using the parameter settings for the 600 CP on a 1200 CP scanner * doesn't work: the engine doesn't move and makes a sharp noise, which * doesn't sound too healthy. It could be harmful to the motor ! * Apparently, the same happens on a real 600 CP (reported by Disma * Goggia), so it's probably better to always use the 1200 CP settings. */ dev->CIS.exposeTime <<= 1; cis_config_ccd(dev); dev->CIS.exposeTime = savedExposeTime; /* * This is a minor speed optimization: when we are using the high * resolution mode, long feeds (eg, to move to a scan area at the bottom * of the page) can be made almost twice as fast by using double motor * steps as much as possible. * It is possible, though, that fast skipping (which is the default) is * not very accurate on some scanners. Therefore, the user can disable * this through the configuration file. */ fullSteps = steps & 1; biSteps = steps >> 1; if (dev->fast_skip) { quadSteps = biSteps >> 1; biSteps &= 1; } else { quadSteps = 0; } M1015_DISPLAY_REGS(dev, "Before move"); #if MUSTEK_PP_CIS_MOTOR_REVERSE == 1 fullStep ^= 0x10; biStep ^= 0x10; quadStep ^= 0x10; #endif DBG(4, "cis_move_motor: 4x%d 2x%d 1x%d\n", quadSteps, biSteps, fullSteps); /* Note: the TWAIN driver opens the motor control register only once before the loop, and closes it after the loop. I've tried this too, but it resulted in inaccurate skip distances; therefore, the motor control register is now opened and closed for each step. */ while (quadSteps-- > 0 && dev->desc->state != STATE_CANCELLED) { cis_wait_motor_stable (dev); Mustek_PP_1015_write_reg(dev, MA1015W_MOTOR_CONTROL, quadStep); } while (biSteps-- > 0 && dev->desc->state != STATE_CANCELLED) { cis_wait_motor_stable (dev); Mustek_PP_1015_write_reg(dev, MA1015W_MOTOR_CONTROL, biStep); } while (fullSteps-- > 0 && dev->desc->state != STATE_CANCELLED) { cis_wait_motor_stable (dev); Mustek_PP_1015_write_reg(dev, MA1015W_MOTOR_CONTROL, fullStep); } } static void cis_set_et_pd_sti (Mustek_PP_CIS_dev * dev) { Mustek_PP_1015_write_reg(dev, MA1015W_EXPOSE_TIME, dev->CIS.exposeTime); Mustek_PP_1015_write_reg(dev, MA1015W_POWER_ON_DELAY, dev->CIS.powerOnDelay[dev->CIS.channel]); cis_set_ccd_channel (dev); cis_set_sti (dev); } /* * Prepare the scanner for catching the next channel and, if necessary, * move the head one step further. */ static SANE_Bool cis_wait_next_channel (Mustek_PP_CIS_dev * dev) { int moveAtChannel = dev->desc->mode == MODE_COLOR ? MUSTEK_PP_CIS_CHANNEL_BLUE : MUSTEK_PP_CIS_CHANNEL_GRAY; if (!cis_wait_bank_change (dev, dev->bank_count)) { DBG(2, "cis_wait_next_channel: Could not get next bank.\n"); return SANE_FALSE; } moveAtChannel = (dev->desc->mode == MODE_COLOR) ? MUSTEK_PP_CIS_CHANNEL_BLUE : MUSTEK_PP_CIS_CHANNEL_GRAY; if (dev->CIS.channel == moveAtChannel && !dev->CIS.dontMove) { cis_motor_forward (dev); } cis_set_et_pd_sti (dev); if (dev->desc->mode == MODE_COLOR) { ++dev->CIS.channel; dev->CIS.channel %= 3; } return SANE_TRUE; } /* * Wait for the device to be ready for scanning. Cycles through the different * channels and sets the parameters (only green channel in gray/lineart). */ static SANE_Bool cis_wait_read_ready (Mustek_PP_CIS_dev * dev) { int channel; dev->CIS.dontIncRead = SANE_TRUE; dev->CIS.channel = dev->desc->mode == MODE_COLOR ? MUSTEK_PP_CIS_CHANNEL_RED : MUSTEK_PP_CIS_CHANNEL_GRAY; for (channel = 0; channel < 3; ++channel) { if (!cis_wait_next_channel(dev)) return SANE_FALSE; } return SANE_TRUE; } static int delay_read (int delay) { /* * A (very) smart compiler may complete optimize the delay loop away. By * adding some difficult data dependencies, we can try to prevent this. */ static int prevent_removal, i; for (i = 0; iCIS.adjustskip, cval; int bpos = 0; SANE_Byte low_val = 0, hi_val = 255; if (pixel <= 0) return; SANEI_PA4S2_READBEGIN (dev->desc->fd, 1); while(skips-- >= 0) { if (dev->CIS.delay) delay_read(dev->CIS.delay); SANEI_PA4S2_READBYTE (dev->desc->fd, &color); } if (dev->CIS.hw_hres == dev->CIS.res) { /* One-to one mapping */ DBG (6, "cis_read_line_low_level: one-to-one\n"); for (ctr = 0; ctr < pixel; ctr++) { if (dev->CIS.delay) delay_read(dev->CIS.delay); SANEI_PA4S2_READBYTE (dev->desc->fd, &color); cval = color; if (calib_low) { low_val = calib_low[ctr] ; } if (calib_hi) { hi_val = calib_hi[ctr] ; } cval -= low_val ; cval <<= 8 ; cval /= hi_val-low_val ; if (cval < 0) cval = 0; else if (cval > 255) cval = 255; if (gamma) cval = gamma[cval]; buf[ctr] = cval; } } else if (dev->CIS.hw_hres > dev->CIS.res) { /* Sub-sampling */ int pos = 0; DBG (6, "cis_read_line_low_level: sub-sampling\n"); ctr = 0; do { if (dev->CIS.delay) delay_read(dev->CIS.delay); SANEI_PA4S2_READBYTE (dev->desc->fd, &color); cval = color; if (ctr < (pos >> SANE_FIXED_SCALE_SHIFT)) { ctr++; continue; } ctr++; pos += dev->CIS.hres_step; if (calib_low) { low_val = calib_low[bpos] ; } if (calib_hi) { hi_val = calib_hi[bpos] ; } cval -= low_val ; cval <<= 8 ; cval /= hi_val-low_val ; if (cval < 0) cval = 0 ; else if (cval > 255) cval = 255 ; if (gamma) cval = gamma[cval]; buf[bpos++] = cval; } while (bpos < pixel); } else { int calctr = 0; SANE_Int pos = 0, nextPos = 1; /* Step: eg: 600 DPI -> 700 DPI -> hres_step = 6/7 -> step = 1/7 */ SANE_Int step = SANE_FIX(1) - dev->CIS.hres_step; /* Super-sampling */ DBG (6, "cis_read_line_low_level: super-sampling\n"); do { if (dev->CIS.delay) delay_read(dev->CIS.delay); SANEI_PA4S2_READBYTE (dev->desc->fd, &color); cval = color; if (calib_low) { low_val = calib_low[calctr] ; } if (calib_hi) { hi_val = calib_hi[calctr] ; } if (++calctr >= dev->calib_pixels) { /* Avoid array boundary violations due to rounding errors (due to the incremental calculation, the current position may be inaccurate to up to two pixels, so we may need to read a few extra bytes -> use the last calibration value) */ calctr = dev->calib_pixels - 1; DBG (3, "cis_read_line_low_level: calibration overshoot\n"); } cval -= low_val ; cval <<= 8 ; cval /= hi_val-low_val ; if (cval < 0) cval = 0 ; else if (cval > 255) cval = 255 ; if (gamma) cval = gamma[cval]; pos += step; if ((pos >> SANE_FIXED_SCALE_SHIFT) >= nextPos) { nextPos++; /* Insert an interpolated value */ buf[bpos] = (buf[bpos-1] + cval)/2; /* Interpolate */ ++bpos; /* Store the plain value, but only if we still need pixels */ if (bpos < pixel) buf[bpos++] = cval; pos += step; /* Take interpolated value into account for pos */ } else { buf[bpos++] = cval; } } while (bpos < pixel); } SANEI_PA4S2_READEND (dev->desc->fd); DBG (6, "cis_read_line_low_level: done\n"); } static SANE_Bool cis_read_line (Mustek_PP_CIS_dev * dev, SANE_Byte* buf, SANE_Int pixel, SANE_Bool raw) { if (!dev->CIS.dontIncRead) CIS_INC_READ(dev); else dev->CIS.dontIncRead = SANE_FALSE; if (raw) { /* No color correction; raw data */ cis_read_line_low_level (dev, buf, pixel, NULL, NULL, NULL); } else { /* Color correction */ cis_read_line_low_level (dev, buf, pixel, dev->calib_low[dev->CIS.channel], dev->calib_hi[dev->CIS.channel], (dev->desc->val[OPT_CUSTOM_GAMMA].w ? dev->desc->gamma_table[dev->CIS.channel] : NULL)); } return cis_wait_next_channel(dev); } static void cis_get_next_line (Mustek_PP_CIS_dev * dev, SANE_Byte * buf) { SANE_Byte *dest, *tmpbuf = dev->tmpbuf; int ctr, channel, first, last, stride, step = dev->CIS.line_step; SANE_Byte gotline; if (dev->desc->mode == MODE_COLOR) { first = MUSTEK_PP_CIS_CHANNEL_RED; last = MUSTEK_PP_CIS_CHANNEL_BLUE; stride = 3; } else { first = MUSTEK_PP_CIS_CHANNEL_GRAY; last = MUSTEK_PP_CIS_CHANNEL_GRAY; stride = 1; } gotline = SANE_FALSE; do { dev->ccd_line++; if ((dev->line_diff >> SANE_FIXED_SCALE_SHIFT) != dev->ccd_line) { cis_motor_forward (dev); continue; } dev->line_diff += step; for (channel = first; channel <= last; ++channel) { if (!cis_read_line(dev, tmpbuf, dev->desc->params.pixels_per_line, SANE_FALSE)) return; dest = buf + channel - first; for (ctr = 0; ctr < dev->desc->params.pixels_per_line; ctr++) { *dest = tmpbuf[ctr]; dest += stride; } } gotline = SANE_TRUE; } while (!gotline && dev->desc->state != STATE_CANCELLED); } static void cis_get_grayscale_line (Mustek_PP_CIS_dev * dev, SANE_Byte * buf) { cis_get_next_line(dev, buf); } static void cis_get_lineart_line (Mustek_PP_CIS_dev * dev, SANE_Byte * buf) { int ctr; SANE_Byte gbuf[MUSTEK_PP_CIS_MAX_H_PIXEL * 2]; cis_get_grayscale_line (dev, gbuf); memset (buf, 0xFF, dev->desc->params.bytes_per_line); for (ctr = 0; ctr < dev->desc->params.pixels_per_line; ctr++) buf[ctr >> 3] ^= ((gbuf[ctr] > dev->bw_limit) ? (1 << (7 - ctr % 8)) : 0); } static void cis_get_color_line (Mustek_PP_CIS_dev * dev, SANE_Byte * buf) { cis_get_next_line(dev, buf); } /****************************************************************************** * Saves the state of the device during reset and calibration. *****************************************************************************/ static void cis_save_state (Mustek_PP_CIS_dev * dev) { dev->Saved_CIS = dev->CIS; } /****************************************************************************** * Restores the state of the device after reset and calibration. *****************************************************************************/ static void cis_restore_state (Mustek_PP_CIS_dev * dev) { dev->CIS = dev->Saved_CIS; } #define CIS_TOO_BRIGHT 1 #define CIS_OK 0 #define CIS_TOO_DARK -1 static int cis_check_result(SANE_Byte* buffer, int pixel) { int i, maxVal = 0; for (i=0;i maxVal) maxVal = buffer[i]; if (maxVal > 250) return CIS_TOO_BRIGHT; if (maxVal < 240) return CIS_TOO_DARK; return CIS_OK; } static SANE_Bool cis_maximize_dynamic_range(Mustek_PP_CIS_dev * dev) { /* The device is in its final configuration already. */ int i, j, pixel, channel, minExposeTime, first, last; SANE_Byte powerOnDelayLower[3], powerOnDelayUpper[3], exposeTime[3]; SANE_Byte buf[3][MUSTEK_PP_CIS_MAX_H_PIXEL]; SANE_Int pixels = dev->calib_pixels; DBG(3, "cis_maximize_dynamic_range: starting\n"); for (channel = 0; channel < 3; ++channel) { exposeTime[channel] = 254; dev->CIS.powerOnDelay[channel] = 170; powerOnDelayLower[channel] = 1; powerOnDelayUpper[channel] = 254; } dev->CIS.setParameters = SANE_TRUE; dev->CIS.exposeTime = exposeTime[MUSTEK_PP_CIS_CHANNEL_GREEN]; cis_config_ccd(dev); M1015_DISPLAY_REGS(dev, "before maximizing dynamic range"); dev->CIS.dontMove = SANE_TRUE; /* Don't move while calibrating */ if (!cis_wait_read_ready(dev) && dev->desc->state != STATE_CANCELLED) { DBG(2, "cis_maximize_dynamic_range: DEVICE NOT READY!\n"); return SANE_FALSE; } if (dev->desc->mode == MODE_COLOR) { first = MUSTEK_PP_CIS_CHANNEL_RED; last = MUSTEK_PP_CIS_CHANNEL_BLUE; } else { first = MUSTEK_PP_CIS_CHANNEL_GRAY; last = MUSTEK_PP_CIS_CHANNEL_GRAY; } dev->CIS.channel = first; /* Perform a kind of binary search. In the worst case, we should find the optimal power delay values after 8 iterations */ for( i=0; i<8; i++) { for (channel = first; channel <= last; ++channel) { dev->CIS.powerOnDelay[channel] = (powerOnDelayLower[channel] + powerOnDelayUpper[channel]) / 2; } Mustek_PP_1015_write_reg(dev, MA1015W_POWER_ON_DELAY, dev->CIS.powerOnDelay[1]); /* Green */ for (pixel = 0; pixel < pixels; ++pixel) { buf[0][pixel] = buf[1][pixel] = buf[2][pixel] = 255; } /* Scan 4 lines, but ignore the first 3 ones. */ for (j = 0; j < 4; ++j) { for (channel = first; channel <= last; ++channel) { if (!cis_read_line(dev, &buf[channel][0], pixels, /* raw = */ SANE_TRUE)) return SANE_FALSE; } } for (channel = first; channel <= last; ++channel) { switch (cis_check_result(buf[channel], pixels)) { case CIS_TOO_BRIGHT: powerOnDelayLower[channel] = dev->CIS.powerOnDelay[channel]; break; case CIS_TOO_DARK: powerOnDelayUpper[channel] = dev->CIS.powerOnDelay[channel]; break; default: break; } } DBG (4, "cis_maximize_dynamic_range: power on delay %3d %3d %3d\n", dev->CIS.powerOnDelay[0], dev->CIS.powerOnDelay[1], dev->CIS.powerOnDelay[2]); } dev->CIS.dontMove = SANE_FALSE; DBG (3, "cis_maximize_dynamic_range: power on delay %3d %3d %3d\n", dev->CIS.powerOnDelay[0], dev->CIS.powerOnDelay[1], dev->CIS.powerOnDelay[2]); minExposeTime = (dev->CIS.hw_hres <= 300) ? 170 : 253; for (channel = first; channel <= last; ++channel) { dev->CIS.powerOnDelay[channel] = (powerOnDelayLower[channel] + powerOnDelayUpper[channel]) / 2; exposeTime[channel] -= dev->CIS.powerOnDelay[channel] - 1; dev->CIS.powerOnDelay[channel] = 1; if (exposeTime[channel] < minExposeTime) { dev->CIS.powerOnDelay[channel] += minExposeTime - exposeTime[channel]; exposeTime[channel] = minExposeTime; } } dev->CIS.exposeTime = exposeTime[MUSTEK_PP_CIS_CHANNEL_GREEN]; DBG (3, "cis_maximize_dynamic_range: expose time: %3d\n", exposeTime[1]); DBG (3, "cis_maximize_dynamic_range: power on delay %3d %3d %3d\n", dev->CIS.powerOnDelay[0], dev->CIS.powerOnDelay[1], dev->CIS.powerOnDelay[2]); /* * Short the calibration. Temporary, to find out what is wrong with * the calibration on a 600 CP. * dev->CIS.exposeTime = 170; dev->CIS.powerOnDelay[0] = 120; dev->CIS.powerOnDelay[1] = 120; dev->CIS.powerOnDelay[2] = 120; */ return SANE_TRUE; } static SANE_Bool cis_measure_extremes(Mustek_PP_CIS_dev * dev, SANE_Byte* calib[3], SANE_Int pixels, SANE_Int first, SANE_Int last) { SANE_Byte buf[3][MUSTEK_PP_CIS_MAX_H_PIXEL]; SANE_Byte min[3][MUSTEK_PP_CIS_MAX_H_PIXEL]; SANE_Byte max[3][MUSTEK_PP_CIS_MAX_H_PIXEL]; SANE_Int sum[3][MUSTEK_PP_CIS_MAX_H_PIXEL]; int channel, cnt, p; memset((void*)&min, 255, 3*MUSTEK_PP_CIS_MAX_H_PIXEL*sizeof(SANE_Byte)); memset((void*)&max, 0, 3*MUSTEK_PP_CIS_MAX_H_PIXEL*sizeof(SANE_Byte)); memset((void*)&sum, 0, 3*MUSTEK_PP_CIS_MAX_H_PIXEL*sizeof(SANE_Int)); dev->CIS.channel = first; /* Purge the banks first (there's always a 3-cycle delay) */ for (channel = first; channel <= last; ++channel) { if (!cis_read_line(dev, &buf[channel%3][0], pixels, /* raw = */ SANE_TRUE)) return SANE_FALSE; } --dev->CIS.skipsToOrigin; for (cnt = 0; cnt < MUSTEK_PP_CIS_AVERAGE_COUNT + 2; ++cnt) { for (channel = first; channel <= last; ++channel) { DBG(4, "cis_measure_extremes: Reading line %d - channel %d\n", cnt, channel); if (!cis_read_line(dev, &buf[channel][0], pixels, /* raw = */ SANE_TRUE)) return SANE_FALSE; for (p = 0; p < pixels; ++p) { SANE_Byte val = buf[channel][p]; if (val < min[channel][p]) min[channel][p] = val; if (val > max[channel][p]) max[channel][p] = val; sum[channel][p] += val; } } --dev->CIS.skipsToOrigin; } DBG(4, "cis_measure_extremes: Averaging\n"); for (channel = first; channel <= last; ++channel) { /* Ignore the extreme values and take the average of the others. */ for (p = 0; p < pixels; ++p) { sum[channel][p] -= min[channel][p] + max[channel][p]; sum[channel][p] /= MUSTEK_PP_CIS_AVERAGE_COUNT; if (calib[channel]) calib[channel][p] = sum[channel][p]; } } DBG(4, "cis_measure_extremes: Done\n"); return SANE_TRUE; } static SANE_Bool cis_normalize_ranges(Mustek_PP_CIS_dev * dev) { SANE_Byte cal_low, cal_hi ; SANE_Byte powerOnDelay[3] ; SANE_Int pixels = dev->calib_pixels; SANE_Int channel, p, first, last; if (dev->desc->mode == MODE_COLOR) { first = MUSTEK_PP_CIS_CHANNEL_RED; last = MUSTEK_PP_CIS_CHANNEL_BLUE; } else { first = MUSTEK_PP_CIS_CHANNEL_GRAY; last = MUSTEK_PP_CIS_CHANNEL_GRAY; } DBG(3, "cis_normalize_ranges: Measuring high extremes\n"); /* Measure extremes with normal lighting */ if (!cis_measure_extremes(dev, dev->calib_hi, pixels, first, last)) { return SANE_FALSE; } /* Measure extremes without lighting */ for (channel=first; channel<=last; ++channel) { powerOnDelay[channel] = dev->CIS.powerOnDelay[channel]; dev->CIS.powerOnDelay[channel] = dev->CIS.exposeTime; } DBG(3, "cis_normalize_ranges: Measuring low extremes\n"); if (!cis_measure_extremes(dev, dev->calib_low, pixels, first, last)) { return SANE_FALSE; } /* Restore settings */ for (channel=first; channel<=last; ++channel) { dev->CIS.powerOnDelay[channel] = powerOnDelay[channel]; } /* Make sure calib_hi is greater than calib_low */ for (channel = first; channel <= last; ++channel) { for (p = 0; pcalib_low[channel]) { cal_low = dev->calib_low[channel][p]; } else { cal_low = 0; } if (dev->calib_hi[channel]) { cal_hi = dev->calib_hi[channel][p]; } else { cal_hi = 255; } if (cal_hi <= cal_low) { if(cal_hi<255) { /* calib_hi exists, else cal_hi would be 255 */ dev->calib_hi[channel][p] = cal_low+1; } else { /* calib_low exists, else cal_low would be 0, < 255 */ dev->calib_low[channel][p] = cal_hi-1; } } } } DBG(3, "cis_normalize_ranges: calibration done\n"); return SANE_TRUE; } /* * This routine measures the time that we have to wait between reading * to pixels from the scanner. Especially at low resolutions, but also * for narrow-width scans at high resolutions, reading too fast cause * color stability problems. * This routine sends a test pattern to the scanner memory banks and tries * to measure how fast it can be retrieved without errors. * The same is done by the TWAIN driver (TESTIO.CPP:TestDelay). */ static SANE_Bool cis_measure_delay(Mustek_PP_CIS_dev * dev) { SANE_Byte buf[2][2048]; unsigned i, j, d; int saved_res; SANE_Bool error = SANE_FALSE; CIS_CLEAR_FULLFLAG(dev); CIS_CLEAR_WRITE_ADDR(dev); CIS_CLEAR_WRITE_BANK(dev); CIS_INC_READ(dev); CIS_CLEAR_READ_BANK(dev); M1015_DISPLAY_REGS(dev, "Before delay measurement"); assert(dev->CIS.adjustskip == 0); /* Sawtooth */ for (i=0; i<2048; ++i) { buf[0][i] = i % 255; /* Why 255 ? Seems to have no real importance */ } Mustek_PP_1015_write_reg_start(dev, MA1015W_SRAM_SOURCE_PC); for (i=0; i<2048; ++i) { Mustek_PP_1015_write_reg_val(dev, buf[0][i]); } Mustek_PP_1015_write_reg_stop(dev); /* Bank offset measurement */ dev->CIS.delay = 0; /* Initialize to zero, measure next */ saved_res = dev->CIS.res; dev->CIS.res = dev->CIS.hw_hres; /* * Note: the TWAIN driver seems to have a fast EPP mode too. That one is * tried first, and then they try the normal mode. I haven't figured out * yet how the fast mode works, so I'll only check the normal mode for now. * Moreover, from the behaviour that I've witnessed from the TWAIN driver, * I must conclude that the fast mode probably doesn't work on my computer, * so I can't test it anyhow. */ /* Gradually increase the delay till we have no more errors */ for (d = 0; d < 75 /* 255 */ && dev->desc->state != STATE_CANCELLED; d += 5) { dev->CIS.delay = d; /* * We read the line 5 times to make sure that all garbage is flushed. */ for (i=0; i<5; ++i) { CIS_INC_READ(dev); CIS_CLEAR_READ_BANK(dev); cis_read_line_low_level (dev, &buf[1][0], 2048, NULL, NULL, NULL); if (dev->desc->state == STATE_CANCELLED) return SANE_FALSE; } error = SANE_FALSE; /* Check 100 times whether we can read without errors. */ for (i=0; i<100 && !error; ++i) { CIS_INC_READ(dev); CIS_CLEAR_READ_BANK(dev); cis_read_line_low_level (dev, &buf[1][0], 2048, NULL, NULL, NULL); if (dev->desc->state == STATE_CANCELLED) return SANE_FALSE; for (j=0; j<2048; ++j) { if (buf[0][j] != buf[1][j]) { error = SANE_TRUE; break; } } } DBG (3, "cis_measure_delay: delay %d\n", dev->CIS.delay); if (!error) break; } dev->CIS.res = saved_res; if (error) { fprintf(stderr, "mustek_pp_cis: failed to measure delay.\n"); fprintf(stderr, "Buffer contents:\n"); for (j = 0; j < 20; ++j) { fprintf(stderr, "%d ", buf[1][j]); } fprintf(stderr, "\n"); dev->CIS.delay = 0; } DBG (3, "cis_measure_delay: delay %d\n", dev->CIS.delay); return SANE_TRUE; } static void cis_motor_control (Mustek_PP_CIS_dev * dev, u_char control) { cis_wait_motor_stable (dev); Mustek_PP_1015_write_reg(dev, MA1015W_MOTOR_CONTROL, control); } static void cis_return_home (Mustek_PP_CIS_dev * dev, SANE_Bool nowait) { SANE_Byte savedExposeTime = dev->CIS.exposeTime; DBG(4, "cis_return_home: returning home; nowait: %d\n", nowait); /* During a return-home, the expose time is fixed. */ dev->CIS.exposeTime = 170; cis_config_ccd(dev); dev->CIS.exposeTime = savedExposeTime; cis_motor_control (dev, 0xEB); if (nowait == SANE_FALSE) Mustek_PP_1015_wait_bit(dev, MA1015R_MOTOR, MA1015B_MOTOR_HOME, SANE_TRUE, 1000); } /****************************************************************************** * Does a full reset of the device, ie. configures the CIS to a default * resolution of 300 DPI (in high or low resolution mode, depending on the * resolution requested by the user). *****************************************************************************/ static void cis_reset_device (Mustek_PP_CIS_dev * dev) { DBG(4, "cis_reset_device: resetting device\n"); dev->CIS.adjustskip = 0; dev->CIS.dontIncRead = SANE_TRUE; dev->CIS.dontMove = SANE_FALSE; cis_save_state(dev); dev->CIS.hw_hres = 300; dev->CIS.channel = MUSTEK_PP_CIS_CHANNEL_GREEN; dev->CIS.setParameters = SANE_FALSE; dev->CIS.exposeTime = 0xAA; cis_config_ccd (dev); cis_restore_state(dev); } static SANE_Bool cis_calibrate (Mustek_PP_CIS_dev * dev) { int i, saved_res = dev->CIS.res, saved_vres = dev->CIS.hw_vres; /* * Flow of operation observed from the twain driver * (it is assumed that the lamp is at the origin, and that the CIS is * configured for 300 DPI, ie. cis_reset_device has been called.) * * - Reset the device and return the lamp to its home position * * - Unknown short sequence * * - Send a sawtooth-like pattern to one of the memory banks. * * - Repetitive read_line of 2048 bytes, interleaved with an unknown * command. The number varies between 102 and 170 times, but there * doesn't seem to be any correlation with the current mode of the * scanner, so I assume that the exact number isn't really relevant. * The values that are read are the one that were sent to the bank, * rotated by 1 byte in my case. * * * It seems that the width of the black border is being measured at * this stage, possibly multiple times till it stabilizes. * I assume that the buffer is read 100 times to allow the lamp to * warm up and that the width of the black border is then being * measured till it stabilizes. That would explain the minimum number * of 102 iterations that I've seen. * * - reset the device * * - move the motor 110 steps forward. The TWAIN driver moves 90 steps, * and I've used 90 steps for a long time too, but occasionally, * 90 steps is a fraction to short to reach the start of the * calibration strip (the motor movements are not very accurate; * an offset of 1 mm is not unusual). Therefore, I've increased it to * 110 steps. This gives us an additional 1.6 mm slack, which should * prevent calibration errors. * (Note that the MUSTEK_PP_CIS_????CP_DEFAULT_SKIP constants have to * be adjusted if the number of steps is altered.) * * - configure the CIS : actual resolution + set parameters * */ /* * We must make sure that we are in the scanning state; otherwise we may * still be in the canceled state from a previous scan (even if terminated * normally), and the whole calibration would go wrong. */ dev->desc->state = STATE_SCANNING; cis_reset_device (dev); cis_return_home (dev, SANE_FALSE); /* Wait till it's home */ /* Use maximum resolution during calibration; otherwise we may calibrate past the calibration strip. */ dev->CIS.hw_vres = dev->desc->dev->maxres; /* This field remembers how many steps we still have to go @ max res */ dev->CIS.skipsToOrigin = dev->top_skip; /*max2hw_vres(dev, dev->top_skip); */ if (!cis_measure_delay(dev)) return SANE_FALSE; cis_reset_device (dev); /* Move motor 110 steps @ 300 DPI */ Mustek_PP_1015_write_reg_start(dev, MA1015W_MOTOR_CONTROL); for (i=0; i<110; ++i) { if (dev->model == MUSTEK_PP_CIS600) { Mustek_PP_1015_write_reg_val (dev, 0x73); } else { Mustek_PP_1015_write_reg_val (dev, 0x7B); } cis_wait_motor_stable (dev); } Mustek_PP_1015_write_reg_stop(dev); /* Next, we maximize the dynamic range of the scanner. During calibration we don't want to extrapolate, so we limit the resolution if necessary */ if (dev->CIS.hw_hres < dev->CIS.res) dev->CIS.res = dev->CIS.hw_hres; if (!cis_maximize_dynamic_range(dev)) return SANE_FALSE; if (!cis_normalize_ranges(dev)) return SANE_FALSE; dev->CIS.res = saved_res; dev->CIS.hw_vres = saved_vres; /* Convert steps back to max res size, which are used during skipping */ /* dev->CIS.skipsToOrigin = hw2max_vres(dev, dev->CIS.skipsToOrigin); */ /* Move to the origin */ DBG(3, "cis_calibrate: remaining skips to origin @maxres: %d\n", dev->CIS.skipsToOrigin); cis_move_motor(dev, dev->CIS.skipsToOrigin); if (dev->calib_mode) { /* In calibration mode, we scan the interior of the scanner before the glass plate in order to find the position of the calibration strip and the start of the glass plate. */ DBG(3, "cis_calibrate: running in calibration mode. Returning home.\n"); cis_return_home (dev, SANE_FALSE); /* Wait till it's home */ } return dev->desc->state != STATE_CANCELLED ? SANE_TRUE : SANE_FALSE; } /****************************************************************************** ****************************************************************************** *** Mustek PP interface *** ****************************************************************************** *****************************************************************************/ /****************************************************************************** * Init * ******************************************************************************/ /* Shared initialization routine */ static SANE_Status cis_attach(SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach, SANE_Int driverNo, SANE_Int info) { int fd; SANE_Status status; u_char asic; status = sanei_pa4s2_open (port, &fd); if (status != SANE_STATUS_GOOD) { SANE_Status altStatus; SANE_String_Const altPort; DBG (2, "cis_attach: couldn't attach to `%s' (%s)\n", port, sane_strstatus (status)); /* Make migration to libieee1284 painless for users that used direct io in the past */ if (strcmp(port, "0x378") == 0) altPort = "parport0"; else if (strcmp(port, "0x278") == 0) altPort = "parport1"; else if (strcmp(port, "0x3BC") == 0) altPort = "parport2"; else return status; DBG (2, "cis_attach: trying alternative port name: %s\n", altPort); altStatus = sanei_pa4s2_open (altPort, &fd); if (altStatus != SANE_STATUS_GOOD) { DBG (2, "cis_attach: couldn't attach to alternative port `%s' " "(%s)\n", altPort, sane_strstatus (altStatus)); return status; /* Return original status, not alternative status */ } } M1015_START_LL; M1015_START_HL; sanei_pa4s2_enable (fd, SANE_TRUE); SANEI_PA4S2_READBEGIN (fd, 0); SANEI_PA4S2_READBYTE (fd, &asic); SANEI_PA4S2_READEND (fd); sanei_pa4s2_enable (fd, SANE_FALSE); sanei_pa4s2_close (fd); if (asic != 0xA5) /* Identifies the MA1015 chipset */ { /* CIS driver only works for MA1015 chipset */ DBG (2, "cis_attach: asic id (0x%02x) not recognized\n", asic); return SANE_STATUS_INVAL; } DBG (3, "cis_attach: device %s attached\n", name); DBG (3, "cis_attach: asic 0x%02x\n", asic); return attach(port, name, driverNo, info); } SANE_Status cis600_drv_init(SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach) { if (options != CAP_NOTHING) return SANE_STATUS_INVAL; return cis_attach(port, name, attach, MUSTEK_PP_CIS600, MUSTEK_PP_CIS600); } SANE_Status cis1200_drv_init(SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach) { if (options != CAP_NOTHING) return SANE_STATUS_INVAL; return cis_attach(port, name, attach, MUSTEK_PP_CIS1200, MUSTEK_PP_CIS1200); } SANE_Status cis1200p_drv_init(SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach) { if (options != CAP_NOTHING) return SANE_STATUS_INVAL; return cis_attach(port, name, attach, MUSTEK_PP_CIS1200PLUS, MUSTEK_PP_CIS1200PLUS); } /****************************************************************************** * Capabilities * ******************************************************************************/ void cis_drv_capabilities(SANE_Int info, SANE_String *model, SANE_String *vendor, SANE_String *type, SANE_Int *maxres, SANE_Int *minres, SANE_Int *maxhsize, SANE_Int *maxvsize, SANE_Int *caps) { *vendor = strdup("Mustek"); *type = strdup("flatbed scanner"); *caps = CAP_NOTHING; switch(info) { case MUSTEK_PP_CIS600: *model = strdup("600CP"); *maxres = 600; *minres = 50; *maxhsize = MUSTEK_PP_CIS_MAX_H_PIXEL; *maxvsize = MUSTEK_PP_CIS_MAX_V_PIXEL; break; case MUSTEK_PP_CIS1200: *model = strdup("1200CP"); *maxres = 1200; *minres = 50; *maxhsize = MUSTEK_PP_CIS_MAX_H_PIXEL*2; *maxvsize = MUSTEK_PP_CIS_MAX_V_PIXEL*2; break; case MUSTEK_PP_CIS1200PLUS: *model = strdup("1200CP+"); *maxres = 1200; *minres = 50; *maxhsize = MUSTEK_PP_CIS_MAX_H_PIXEL*2; *maxvsize = MUSTEK_PP_CIS_MAX_V_PIXEL*2; break; } } /****************************************************************************** * Open * ******************************************************************************/ SANE_Status cis_drv_open (SANE_String port, SANE_Int caps, SANE_Int *fd) { SANE_Status status; if (caps != CAP_NOTHING) { DBG (1, "cis_drv_open: called with unknown capabilities (0x%02X)\n", caps); return SANE_STATUS_INVAL; } DBG (3, "cis_drv_open: called for port %s\n", port); status = sanei_pa4s2_open (port, fd); if (status != SANE_STATUS_GOOD) { SANE_Status altStatus; SANE_String_Const altPort; DBG (2, "cis_attach: couldn't attach to `%s' (%s)\n", port, sane_strstatus (status)); /* Make migration to libieee1284 painless for users that used direct io in the past */ if (strcmp(port, "0x378") == 0) altPort = "parport0"; else if (strcmp(port, "0x278") == 0) altPort = "parport1"; else if (strcmp(port, "0x3BC") == 0) altPort = "parport2"; else return status; DBG (2, "cis_attach: trying alternative port name: %s\n", altPort); altStatus = sanei_pa4s2_open (altPort, fd); if (altStatus != SANE_STATUS_GOOD) { DBG (2, "cis_attach: couldn't attach to alternative port `%s' " "(%s)\n", altPort, sane_strstatus (altStatus)); return status; /* Return original status, not alternative status */ } } return SANE_STATUS_GOOD; } /****************************************************************************** * Setup * ******************************************************************************/ void cis_drv_setup (SANE_Handle hndl) { Mustek_pp_Handle *dev = hndl; Mustek_PP_CIS_dev *cisdev; cisdev = (Mustek_PP_CIS_dev*)malloc(sizeof(Mustek_PP_CIS_dev)); if (cisdev == NULL) { DBG (2, "cis_drv_setup: not enough memory for device descriptor\n"); sanei_pa4s2_close (dev->fd); return; } memset(cisdev, 0, sizeof(Mustek_PP_CIS_dev)); DBG(3, "cis_drv_setup: cis device allocated\n"); dev->lamp_on = 0; dev->priv = cisdev; cisdev->desc = dev; cisdev->model = dev->dev->info; cisdev->CIS.hw_hres = 300; cisdev->CIS.cisRes = 300; cisdev->CIS.hw_vres = 300; /* Default values for configurable parameters; configuration file may override them. */ cisdev->fast_skip = SANE_TRUE; cisdev->bw_limit = 127; cisdev->calib_mode = SANE_FALSE; cisdev->engine_delay = 0; if (cisdev->model == MUSTEK_PP_CIS600) { cisdev->top_skip = MUSTEK_PP_CIS_600CP_DEFAULT_SKIP; } else { cisdev->top_skip = MUSTEK_PP_CIS_1200CP_DEFAULT_SKIP; } } /****************************************************************************** * Config * ******************************************************************************/ SANE_Status cis_drv_config(SANE_Handle hndl, SANE_String_Const optname, SANE_String_Const optval) { Mustek_pp_Handle *dev = hndl; Mustek_PP_CIS_dev *cisdev = dev->priv; int value = 0; double dvalue = 0; DBG (3, "cis_drv_cfg option: %s=%s\n", optname, optval ? optval : ""); if (!strcmp(optname, "top_adjust")) { if (!optval) { DBG (1, "cis_drv_config: missing value for option top_adjust\n"); return SANE_STATUS_INVAL; } dvalue = atof(optval); /* An adjustment of +/- 5 mm should be sufficient and safe */ if (dvalue < -5.0) { DBG (1, "cis_drv_config: value for option top_adjust too small: " "%.2f < -5; limiting to -5 mm\n", dvalue); dvalue = -5.0; } if (dvalue > 5.0) { DBG (1, "cis_drv_config: value for option top_adjust too large: " "%.2f > 5; limiting to 5 mm\n", dvalue); dvalue = 5.0; } /* In practice, there is a lower bound on the value that can be used, but if the top_skip value is smaller than that value, the only result will be that the driver tries to move the head a negative number of steps after calibration. The move routine just ignores negative steps, so no harm can be done. */ cisdev->top_skip += MM_TO_PIXEL(dvalue, dev->dev->maxres); DBG (3, "cis_drv_config: setting top skip value to %d\n", cisdev->top_skip); /* Just to be cautious; we don't want the head to hit the bottom */ if (cisdev->top_skip > 600) cisdev->top_skip = 600; if (cisdev->top_skip < -600) cisdev->top_skip = -600; } else if (!strcmp(optname, "slow_skip")) { if (optval) { DBG (1, "cis_drv_config: unexpected value for option slow_skip\n"); return SANE_STATUS_INVAL; } DBG (3, "cis_drv_config: disabling fast skipping\n"); cisdev->fast_skip = SANE_FALSE; } else if (!strcmp(optname, "bw")) { if (!optval) { DBG (1, "cis_drv_config: missing value for option bw\n"); return SANE_STATUS_INVAL; } value = atoi(optval); if (value < 0 || value > 255) { DBG (1, "cis_drv_config: value for option bw out of range: " "%d < 0 or %d > 255\n", value, value); return SANE_STATUS_INVAL; } cisdev->bw_limit = value; } else if (!strcmp(optname, "calibration_mode")) { if (optval) { DBG (1, "cis_drv_config: unexpected value for option calibration_mode\n"); return SANE_STATUS_INVAL; } DBG (3, "cis_drv_config: using calibration mode\n"); cisdev->calib_mode = SANE_TRUE; } else if (!strcmp(optname, "engine_delay")) { if (!optval) { DBG (1, "cis_drv_config: missing value for option engine_delay\n"); return SANE_STATUS_INVAL; } value = atoi(optval); if (value < 0 || value > 100) /* 100 ms is already pretty slow */ { DBG (1, "cis_drv_config: value for option engine_delay out of range: " "%d < 0 or %d > 100\n", value, value); return SANE_STATUS_INVAL; } cisdev->engine_delay = value; } else { DBG (1, "cis_drv_config: unknown options %s\n", optname); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /****************************************************************************** * Close * ******************************************************************************/ void cis_drv_close (SANE_Handle hndl) { Mustek_pp_Handle *dev = hndl; Mustek_PP_CIS_dev *cisdev = dev->priv; DBG (3, "cis_close: resetting device.\n"); sanei_pa4s2_enable (dev->fd, SANE_TRUE); cis_reset_device (cisdev); DBG (3, "cis_close: returning home.\n"); cis_return_home (cisdev, SANE_TRUE); /* Don't wait */ DBG (3, "cis_close: disabling fd.\n"); sanei_pa4s2_enable (dev->fd, SANE_FALSE); DBG (3, "cis_close: closing fd.\n"); sanei_pa4s2_close (dev->fd); DBG (3, "cis_close: done.\n"); DBG (6, "cis_close: lamp_on: %d\n", (int)dev->lamp_on); M1015_STOP_LL; M1015_STOP_HL; } /****************************************************************************** * Start * ******************************************************************************/ SANE_Status cis_drv_start (SANE_Handle hndl) { Mustek_pp_Handle *dev = hndl; Mustek_PP_CIS_dev *cisdev = dev->priv; SANE_Int pixels = dev->params.pixels_per_line; if (!cisdev) { DBG (2, "cis_drv_start: not enough memory for device\n"); return SANE_STATUS_NO_MEM; } cisdev->CIS.exposeTime = 0xAA; cisdev->CIS.setParameters = SANE_FALSE; cisdev->CIS.use8KBank = SANE_TRUE; cisdev->CIS.imagebytes = dev->bottomX - dev->topX; cisdev->CIS.skipimagebytes = dev->topX; cisdev->CIS.res = dev->res; DBG (3, "cis_drv_start: %d dpi\n", dev->res); if (dev->res <= 50 && cisdev->model != MUSTEK_PP_CIS1200PLUS) { cisdev->CIS.hw_hres = 50; } else if (dev->res <= 75 && cisdev->model == MUSTEK_PP_CIS1200PLUS) { cisdev->CIS.hw_hres = 75; } else if (dev->res <= 100) { cisdev->CIS.hw_hres = 100; } else if (dev->res <= 200) { cisdev->CIS.hw_hres = 200; } else if (dev->res <= 300) { cisdev->CIS.hw_hres = 300; } else { if (cisdev->model == MUSTEK_PP_CIS600) { cisdev->CIS.hw_hres = 300; /* Limit for 600 CP */ } else if (dev->res <= 400) { cisdev->CIS.hw_hres = 400; } else { cisdev->CIS.hw_hres = 600; /* Limit for 1200 CP/CP+ */ } } if (cisdev->model == MUSTEK_PP_CIS600) { if (dev->res <= 150) { cisdev->CIS.hw_vres = 150; } else if (dev->res <= 300) { cisdev->CIS.hw_vres = 300; } else { cisdev->CIS.hw_vres = 600; } } else { if (dev->res <= 300) { cisdev->CIS.hw_vres = 300; } else if (dev->res <= 600) { cisdev->CIS.hw_vres = 600; } else { cisdev->CIS.hw_vres = 1200; } } if (cisdev->model == MUSTEK_PP_CIS600 || (cisdev->model == MUSTEK_PP_CIS1200 && dev->res <= 300)) cisdev->CIS.cisRes = 300; else cisdev->CIS.cisRes = 600; /* Calibration only makes sense for hardware pixels, not for interpolated pixels, so we limit the number of calibration pixels to the maximum number of hardware pixels corresponding to the selected area */ if (dev->res > cisdev->CIS.hw_hres) cisdev->calib_pixels = (pixels * cisdev->CIS.hw_hres) / dev->res; else cisdev->calib_pixels = pixels; DBG (3, "cis_drv_start: hres: %d vres: %d cisres: %d\n", cisdev->CIS.hw_hres, cisdev->CIS.hw_vres, cisdev->CIS.cisRes); sanei_pa4s2_enable (dev->fd, SANE_TRUE); cis_reset_device (cisdev); cis_return_home (cisdev, SANE_TRUE); /* Don't wait here */ #ifdef M1015_TRACE_REGS { int i, j; /* * Set all registers to -1 (uninitialized) */ for (i=0; i<4; ++i) { cisdev->CIS.regs.in_regs[i] = -1; for (j=0; j<4; ++j) { cisdev->CIS.regs.out_regs[i][j] = -1; } } cisdev->CIS.regs.channel = -1; /* These values have been read earlier. */ cisdev->CIS.regs.in_regs[0] = 0xA5; } #endif cis_reset_device (cisdev); cis_return_home (cisdev, SANE_TRUE); /* no wait */ /* Allocate memory for temporary color buffer */ cisdev->tmpbuf = malloc (pixels); if (cisdev->tmpbuf == NULL) { sanei_pa4s2_enable (dev->fd, SANE_FALSE); DBG (2, "cis_drv_start: not enough memory for temporary buffer\n"); free(cisdev); dev->priv = NULL; return SANE_STATUS_NO_MEM; } /* Allocate memory for calibration; calibrating interpolated pixels makes no sense */ if (pixels > (dev->dev->maxhsize >> 1)) pixels = (dev->dev->maxhsize >> 1); cisdev->calib_low[1] = malloc (pixels); cisdev->calib_hi[1] = malloc (pixels); if (cisdev->calib_low[1] == NULL || cisdev->calib_hi[1] == NULL) { free (cisdev->calib_low[1]); cisdev->calib_low[1] = NULL; free (cisdev->calib_hi[1]); cisdev->calib_hi[1] = NULL; sanei_pa4s2_enable (dev->fd, SANE_FALSE); DBG (2, "cis_drv_start: not enough memory for calibration buffer\n"); free(cisdev->tmpbuf); cisdev->tmpbuf = NULL; free(cisdev); dev->priv = NULL; return SANE_STATUS_NO_MEM; } cisdev->calib_low[0] = NULL; cisdev->calib_low[2] = NULL; cisdev->calib_hi[0] = NULL; cisdev->calib_hi[2] = NULL; if (dev->mode == MODE_COLOR) { cisdev->calib_low[0] = malloc (pixels); cisdev->calib_low[2] = malloc (pixels); cisdev->calib_hi[0] = malloc (pixels); cisdev->calib_hi[2] = malloc (pixels); if ((cisdev->calib_low[0] == NULL) || (cisdev->calib_low[2] == NULL) || (cisdev->calib_hi[0] == NULL) || (cisdev->calib_hi[2] == NULL)) { free (cisdev->calib_low[0]); cisdev->calib_low[0] = NULL; free (cisdev->calib_low[1]); cisdev->calib_low[1] = NULL; free (cisdev->calib_low[2]); cisdev->calib_low[2] = NULL; free (cisdev->calib_hi[0]); cisdev->calib_hi[0] = NULL; free (cisdev->calib_hi[1]); cisdev->calib_hi[1] = NULL; free (cisdev->calib_hi[2]); cisdev->calib_hi[2] = NULL; free(cisdev->tmpbuf); cisdev->tmpbuf = NULL; free(cisdev); dev->priv = NULL; sanei_pa4s2_enable (dev->fd, SANE_FALSE); DBG (2, "cis_drv_start: not enough memory for color calib buffer\n"); return SANE_STATUS_NO_MEM; } } DBG (3, "cis_drv_start: executing calibration\n"); if (!cis_calibrate (cisdev)) { free (cisdev->calib_low[0]); cisdev->calib_low[0] = NULL; free (cisdev->calib_low[1]); cisdev->calib_low[1] = NULL; free (cisdev->calib_low[2]); cisdev->calib_low[2] = NULL; free (cisdev->calib_hi[0]); cisdev->calib_hi[0] = NULL; free (cisdev->calib_hi[1]); cisdev->calib_hi[1] = NULL; free (cisdev->calib_hi[2]); cisdev->calib_hi[2] = NULL; free(cisdev->tmpbuf); cisdev->tmpbuf = NULL; free(cisdev); dev->priv = NULL; return SANE_STATUS_CANCELLED; /* Most likely cause */ } /* M1015_DISPLAY_REGS(dev, "after calibration"); */ cis_get_bank_count(cisdev); cis_move_motor (cisdev, dev->topY); /* Measured in max resolution */ /* It is vital to reinitialize the scanner right before we start the real scanning. Otherwise the bank synchronization may have gotten lost by the time we reach the top of the scan area */ cisdev->CIS.setParameters = SANE_TRUE; cis_config_ccd(cisdev); cis_wait_read_ready(cisdev); sanei_pa4s2_enable (dev->fd, SANE_FALSE); cisdev->CIS.line_step = SANE_FIX ((float) cisdev->CIS.hw_vres / (float) cisdev->CIS.res); /* * It is very important that line_diff is not initialized at zero ! * If it is set to zero, the motor will keep on moving forever (or better, * till the scanner breaks). */ cisdev->line_diff = cisdev->CIS.line_step; cisdev->ccd_line = 0; cisdev->line = 0; cisdev->lines_left = dev->params.lines; dev->state = STATE_SCANNING; DBG (3, "cis_drv_start: device ready for scanning\n"); return SANE_STATUS_GOOD; } /****************************************************************************** * Read * ******************************************************************************/ void cis_drv_read (SANE_Handle hndl, SANE_Byte *buffer) { Mustek_pp_Handle *dev = hndl; Mustek_PP_CIS_dev *cisdev = dev->priv; DBG(6, "cis_drv_read: Reading line\n"); sanei_pa4s2_enable (dev->fd, SANE_TRUE); switch (dev->mode) { case MODE_BW: cis_get_lineart_line(cisdev, buffer); break; case MODE_GRAYSCALE: cis_get_grayscale_line(cisdev, buffer); break; case MODE_COLOR: cis_get_color_line(cisdev, buffer); break; } sanei_pa4s2_enable (dev->fd, SANE_FALSE); } /****************************************************************************** * Stop * ******************************************************************************/ void cis_drv_stop (SANE_Handle hndl) { Mustek_pp_Handle *dev = hndl; Mustek_PP_CIS_dev *cisdev = dev->priv; /* device is scanning: return lamp and free buffers */ DBG (3, "cis_drv_stop: stopping current scan\n"); dev->state = STATE_CANCELLED; DBG (9, "cis_drv_stop: enabling fd\n"); sanei_pa4s2_enable (dev->fd, SANE_TRUE); Mustek_PP_1015_write_reg(cisdev, MA1015W_MOTOR_CONTROL, 0); /* stop */ DBG (9, "cis_drv_stop: resetting device (1)\n"); cis_reset_device (cisdev); DBG (9, "cis_drv_stop: returning home\n"); cis_return_home (cisdev, SANE_TRUE); /* don't wait */ DBG (9, "cis_drv_stop: resetting device (2)\n"); cis_reset_device (cisdev); DBG (9, "cis_drv_stop: disabling fd\n"); sanei_pa4s2_enable (dev->fd, SANE_FALSE); DBG (9, "cis_drv_stop: freeing buffers\n"); /* This is no good: canceling while the device is scanning and freeing the data buffers can result in illegal memory accesses if the device is still scanning in another thread. */ free (cisdev->calib_low[1]); cisdev->calib_low[1] = NULL; free (cisdev->calib_hi[1]); cisdev->calib_hi[1] = NULL; free (cisdev->tmpbuf); cisdev->tmpbuf = NULL; DBG (3, "cis_drv_stop: freed green and temporary buffers\n"); if (cisdev->CIS.mode == MODE_COLOR) { free (cisdev->calib_low[0]); cisdev->calib_low[0] = NULL; free (cisdev->calib_low[2]); cisdev->calib_low[2] = NULL; free (cisdev->calib_hi[0]); cisdev->calib_hi[0] = NULL; free (cisdev->calib_hi[2]); cisdev->calib_hi[2] = NULL; } DBG (3, "cis_drv_stop: freed buffers\n"); DBG (6, "cis_drv_stop: lamp_on: %d\n", (int)dev->lamp_on); } sane-backends-1.0.27/backend/sm3840.h0000664000175000017500000000654312775312261013736 00000000000000/* sane - Scanner Access Now Easy. ScanMaker 3840 Backend Copyright (C) 2005-7 Earle F. Philhower, III earle@ziplabel.com - http://www.ziplabel.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef sm3840_h #define sm3840_h #include #include #include "../include/sane/sane.h" typedef enum SM3840_Option { OPT_NUM_OPTS = 0, OPT_MODE, OPT_RESOLUTION, OPT_BIT_DEPTH, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_BRIGHTNESS, OPT_CONTRAST, OPT_LAMP_TIMEOUT, OPT_THRESHOLD, /* must come last */ NUM_OPTIONS } SM3840_Option; #include "sm3840_params.h" typedef struct SM3840_Device { struct SM3840_Device *next; SANE_Device sane; } SM3840_Device; typedef struct SM3840_Scan { struct SM3840_Scan *next; SANE_Option_Descriptor options_list[NUM_OPTIONS]; Option_Value value[NUM_OPTIONS]; SANE_Int udev; SANE_Bool scanning; SANE_Bool cancelled; SANE_Parameters sane_params; SM3840_Params sm3840_params; SANE_Byte *line_buffer; /* One remapped/etc line */ size_t remaining; /* How much of line_buffer is still good? */ size_t offset; /* Offset in line_buffer where unread data lives */ int linesleft; /* How many lines to read from scanner? */ int linesread; /* Total lines returned to SANE */ /* record_line state parameters */ int save_i; unsigned char *save_scan_line; unsigned char *save_dpi1200_remap; unsigned char *save_color_remap; unsigned char threshold; int save_dither_err; } SM3840_Scan; #ifndef PATH_MAX #define PATH_MAX 1024 #endif #define SM3840_CONFIG_FILE "sm3840.conf" #define SCAN_BUF_SIZE 65536 #endif /* sm3840_h */ sane-backends-1.0.27/backend/bh.c0000664000175000017500000034120312775312260013356 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1999,2000 Tom Martone This file is part of a SANE backend for Bell and Howell Copiscan II Scanners using the Remote SCSI Controller(RSC). This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_config.h" #define BACKEND_NAME bh #include "../include/sane/sanei_backend.h" #define BUILD 4 #include "bh.h" #define MIN(x,y) ((x)<(y) ? (x) : (y)) #define MAX(x,y) ((x)>(y) ? (x) : (y)) static const SANE_Device **devlist = 0; static int num_devices = 0; static BH_Device *first_dev = NULL; static BH_Scanner *first_handle = NULL; static SANE_Char inquiry_data[255] = "Bell+Howell scanner"; static SANE_Int disable_optional_frames = 0; static SANE_Int fake_inquiry = 0; static int allblank(const char *s) { while (s && *s) if (!isspace(*s++)) return 0; return 1; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static void trim_spaces(char *s, size_t n) { for (s += (n-1); n > 0; n--, s--) { if (*s && !isspace(*s)) break; *s = '\0'; } } static SANE_String_Const print_devtype (SANE_Byte devtype) { static SANE_String devtypes[] = { "disk", "tape", "printer", "processor", "CD-writer", "CD-drive", "scanner", "optical-drive", "jukebox", "communicator" }; return (devtype > 0 && devtype < NELEMS(devtypes)) ? devtypes[devtype] : "unknown-device"; } static SANE_String_Const print_barcodetype (SANE_Int i) { return (i > 0 && i < NELEMS(barcode_search_bar_list)) ? barcode_search_bar_list[i] : (SANE_String_Const) "unknown"; } static SANE_String_Const print_orientation (SANE_Int i) { switch(i) { case 0: case 7: return "vertical upwards"; case 1: case 2: return "horizontal right"; case 3: case 4: return "vertical downwards"; case 5: case 6: return "horizontal left"; default: return "unknown"; } } static SANE_String_Const print_read_type (SANE_Int i) { static char buf[32]; SANE_Int n; /* translate BH_SCSI_READ_TYPE_ codes to a human-readable string */ if (i == BH_SCSI_READ_TYPE_FRONT) { strcpy(buf, "front page"); } else if (i == BH_SCSI_READ_TYPE_BACK) { strcpy(buf, "back page"); } else if (i > BH_SCSI_READ_TYPE_FRONT && i <= BH_SCSI_READ_TYPE_FRONT + NUM_SECTIONS) { n = i - BH_SCSI_READ_TYPE_FRONT; sprintf(buf, "front section %d", n); } else if (i > BH_SCSI_READ_TYPE_BACK && i <= BH_SCSI_READ_TYPE_BACK + NUM_SECTIONS) { n = i - BH_SCSI_READ_TYPE_BACK; sprintf(buf, "back section %d", n); } else if (i == BH_SCSI_READ_TYPE_FRONT_BARCODE) { strcpy(buf, "front page barcode"); } else if (i == BH_SCSI_READ_TYPE_BACK_BARCODE) { strcpy(buf, "back page barcode"); } else if (i > BH_SCSI_READ_TYPE_FRONT_BARCODE && i <= BH_SCSI_READ_TYPE_FRONT_BARCODE + NUM_SECTIONS) { n = i - BH_SCSI_READ_TYPE_FRONT_BARCODE; sprintf(buf, "front barcode section %d", n); } else if (i > BH_SCSI_READ_TYPE_BACK_BARCODE && i <= BH_SCSI_READ_TYPE_BACK_BARCODE + NUM_SECTIONS) { n = i - BH_SCSI_READ_TYPE_BACK_BARCODE; sprintf(buf, "back barcode section %d", n); } else if (i == BH_SCSI_READ_TYPE_FRONT_PATCHCODE) { strcpy(buf, "front page patchcode"); } else if (i == BH_SCSI_READ_TYPE_BACK_PATCHCODE) { strcpy(buf, "back page patchcode"); } else if (i > BH_SCSI_READ_TYPE_FRONT_PATCHCODE && i <= BH_SCSI_READ_TYPE_FRONT_PATCHCODE + NUM_SECTIONS) { n = i - BH_SCSI_READ_TYPE_FRONT_PATCHCODE; sprintf(buf, "front patchcode section %d", n); } else if (i > BH_SCSI_READ_TYPE_BACK_PATCHCODE && i <= BH_SCSI_READ_TYPE_BACK_PATCHCODE + NUM_SECTIONS) { n = i - BH_SCSI_READ_TYPE_BACK_PATCHCODE; sprintf(buf, "back patchcode section %d", n); } else if (i == BH_SCSI_READ_TYPE_FRONT_ICON) { strcpy(buf, "front page icon"); } else if (i == BH_SCSI_READ_TYPE_BACK_ICON) { strcpy(buf, "back page icon"); } else if (i == BH_SCSI_READ_TYPE_SENDBARFILE) { strcpy(buf, "transmit bar/patch codes"); } else { strcpy(buf, "unknown"); } return buf; } static SANE_Int get_rotation_id(char *s) { SANE_Int i; for (i = 0; rotation_list[i]; i++) if (strcmp(s, rotation_list[i]) == 0) break; /* unknown strings are treated as '0' */ return rotation_list[i] ? i : 0; } static SANE_Int get_compression_id(char *s) { SANE_Int i; for (i = 0; compression_list[i]; i++) if (strcmp(s, compression_list[i]) == 0) break; /* unknown strings are treated as 'none' */ return compression_list[i] ? i : 0; } static SANE_Int get_barcode_id(char *s) { SANE_Int i; for (i = 0; barcode_search_bar_list[i]; i++) if (strcmp(s, barcode_search_bar_list[i]) == 0) break; /* unknown strings are treated as 'none' */ return barcode_search_bar_list[i] ? i : 0; } static SANE_Int get_scan_mode_id(char *s) { SANE_Int i; for (i = 0; scan_mode_list[i]; i++) if (strcmp(s, scan_mode_list[i]) == 0) break; /* unknown strings are treated as 'lineart' */ return scan_mode_list[i] ? i : 0; } static SANE_Int get_paper_id(char *s) { SANE_Int i; for (i = 0; paper_list[i]; i++) if (strcmp(s, paper_list[i]) == 0) break; /* unknown strings are treated as 'custom' */ return paper_list[i] ? i : 0; } static SANE_Int get_barcode_search_mode(char *s) { SANE_Int i; if (strcmp(s, "horizontal") == 0) { i = 1; } else if (strcmp(s, "vertical") == 0) { i = 2; } else if (strcmp(s, "vert-horiz") == 0) { i = 6; } else if (strcmp(s, "horiz-vert") == 0) { i = 9; } else { /* unknown strings are treated as 'horiz-vert' */ DBG(1, "get_barcode_search_mode: unrecognized string `%s'\n", s); i = 9; } return i; } static void appendStdList(BH_Info *sc, SANE_Int res) { /* append entry to resolution list - a SANE_WORD_LIST */ sc->resStdList[sc->resStdList[0]+1] = res; sc->resStdList[0]++; } static void ScannerDump(BH_Scanner *s) { int i; BH_Info *info; SANE_Device *sdev; info = &s->hw->info; sdev = &s->hw->sane; DBG (1, "SANE Device: '%s' Vendor: '%s' Model: '%s' Type: '%s'\n", sdev->name, sdev->vendor, sdev->model, sdev->type); DBG (1, "Type: '%s' Vendor: '%s' Product: '%s' Revision: '%s'\n", print_devtype(info->devtype), info->vendor, info->product, info->revision); DBG (1, "Automatic Document Feeder:%s\n", info->canADF ? " " : " "); DBG (1, "Colors:%s%s\n", info->colorBandW ? " " : "", info->colorHalftone ? " " : ""); DBG (1, "Data processing:%s%s%s%s%s%s\n", info->canWhiteFrame ? " " : "", info->canBlackFrame ? " " : "", info->canEdgeExtract ? " " : "", info->canNoiseFilter ? " " : "", info->canSmooth ? " " : "", info->canLineBold ? " " : ""); DBG (1, "Compression:%s%s%s\n", info->comprG3_1D ? " " : "", info->comprG3_2D ? " " : "", info->comprG4 ? " " : ""); DBG (1, "Optional Features:%s%s%s%s\n", info->canBorderRecog ? " " : "", info->canBarCode ? " " : "", info->canIcon ? " " : "", info->canSection ? "
" : ""); DBG (1, "Max bytes per scan-line: %d (%d pixels)\n", info->lineMaxBytes, info->lineMaxBytes * 8); DBG (1, "Basic resolution (X/Y): %d/%d\n", info->resBasicX, info->resBasicY); DBG (1, "Maximum resolution (X/Y): %d/%d\n", info->resMaxX, info->resMaxY); DBG (1, "Minimum resolution (X/Y): %d/%d\n", info->resMinX, info->resMinY); DBG (1, "Standard Resolutions:\n"); for (i = 0; i < info->resStdList[0]; i++) DBG (1, " %d\n", info->resStdList[i+1]); DBG (1, "Window Width/Height (in basic res) %d/%d (%.2f/%.2f inches)\n", info->winWidth, info->winHeight, (info->resBasicX != 0) ? ((float) info->winWidth) / info->resBasicX : 0.0, (info->resBasicY) ? ((float) info->winHeight) / info->resBasicY : 0.0); DBG (1, "Summary:%s%s%s\n", info->canDuplex ? "Duplex Scanner" : "Simplex Scanner", info->canACE ? " (ACE capable)" : "", info->canCheckADF ? " (ADF Paper Sensor capable)" : ""); sprintf(inquiry_data, "Vendor: %s Product: %s Rev: %s %s%s%s\n", info->vendor, info->product, info->revision, info->canDuplex ? "Duplex Scanner" : "Simplex Scanner", info->canACE ? " (ACE capable)" : "", info->canCheckADF ? " (ADF Paper Sensor capable)" : ""); DBG (5, "autoborder_default=%d\n", info->autoborder_default); DBG (5, "batch_default=%d\n", info->batch_default); DBG (5, "deskew_default=%d\n", info->deskew_default); DBG (5, "check_adf_default=%d\n", info->check_adf_default); DBG (5, "duplex_default=%d\n", info->duplex_default); DBG (5, "timeout_adf_default=%d\n", info->timeout_adf_default); DBG (5, "timeout_manual_default=%d\n", info->timeout_manual_default); DBG (5, "control_panel_default=%d\n", info->control_panel_default); } static SANE_Status test_unit_ready (int fd) { static SANE_Byte cmd[6]; SANE_Status status; DBG (3, "test_unit_ready called\n"); cmd[0] = BH_SCSI_TEST_UNIT_READY; memset (cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); return status; } static SANE_Status object_position (BH_Scanner *s) { static SANE_Byte cmd[10]; SANE_Status status; DBG (3, "object_position called\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = BH_SCSI_OBJECT_POSITION; cmd[1] = 0x01; status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0); return status; } static SANE_Status read_barcode_data (BH_Scanner *s, FILE *fp) { static SANE_Byte cmd[10]; SANE_Status status; SANE_Int num_found = 0; double w, l, x, y, res; struct barcode_data buf; size_t buf_size = sizeof(buf); DBG (3, "read_barcode_data called\n"); memset (&cmd, 0, sizeof (cmd)); cmd[0] = BH_SCSI_READ_SCANNED_DATA; cmd[2] = s->readlist[s->readptr]; _lto3b(buf_size, &cmd[6]); /* transfer length */ s->barcode_not_found = SANE_FALSE; do { memset (&buf, 0, sizeof(buf)); status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &buf, &buf_size); if (status != SANE_STATUS_GOOD) break; if (s->barcode_not_found == SANE_TRUE) break; num_found++; buf.barcodedata[sizeof(buf.barcodedata)-1] = '\0'; /* calculate the bounding rectangle */ x = MIN((int) _2btol(buf.posxb), (int) _2btol(buf.posxa)); y = MIN((int) _2btol(buf.posyb), (int) _2btol(buf.posyd)); w = MAX((int) _2btol(buf.posxd), (int) _2btol(buf.posxd)) - x; l = MAX((int) _2btol(buf.posya), (int) _2btol(buf.posyc)) - y; /* convert from pixels to mm */ res = _OPT_VAL_WORD(s, OPT_RESOLUTION); if (res <= 0.0) { /* avoid divide by zero */ DBG(1, "read_barcode_data: warning: " "encountered bad resolution value '%f', replacing with '%f'\n", res, 200.0); res = 200.0; } x = x * MM_PER_INCH / res; y = y * MM_PER_INCH / res; w = w * MM_PER_INCH / res; l = l * MM_PER_INCH / res; /* add a bit of a border around the edges */ x = MAX(0.0, x - BH_DECODE_FUDGE); y = MAX(0.0, y - BH_DECODE_FUDGE); w += (BH_DECODE_FUDGE * 4); l += (BH_DECODE_FUDGE * 4); /* write the decoded barcode data into the file */ fprintf(fp, "\n
%s
\n", print_read_type((int) s->readlist[s->readptr])); fprintf(fp, " %s\n %d\n", print_barcodetype((int) _2btol(buf.barcodetype)), (int) _2btol(buf.statusflag)); fprintf(fp, " %s\n", print_orientation((int) _2btol(buf.barcodeorientation))); fprintf(fp, " \n %d%d\n", (int) _2btol(buf.posxb), (int) _2btol(buf.posyb)); fprintf(fp, " %d%d\n", (int) _2btol(buf.posxd), (int) _2btol(buf.posyd)); fprintf(fp, " %d%d\n", (int) _2btol(buf.posxa), (int) _2btol(buf.posya)); fprintf(fp, "
%d%d
\n
\n", (int) _2btol(buf.posxc), (int) _2btol(buf.posyc)); fprintf(fp, " %.2fx%.2f+%.2f+%.2f\n", w, l, x, y); fprintf(fp, " %d\n %d\n", (int) _2btol(buf.barcodesearchtime), (int) buf.barcodelen); fprintf(fp, " %s\n
\n", buf.barcodedata); } while (num_found <= BH_DECODE_TRIES); DBG (3, "read_barcode_data: found %d barcodes, returning %s\n", num_found, sane_strstatus(status)); return status; } static SANE_Status read_icon_data (BH_Scanner *s) { static SANE_Byte cmd[10]; SANE_Status status; struct icon_data buf; size_t buf_size = sizeof(buf); DBG (3, "read_icon_data called\n"); memset (&cmd, 0, sizeof (cmd)); cmd[0] = BH_SCSI_READ_SCANNED_DATA; cmd[2] = s->readlist[s->readptr]; _lto3b(buf_size, &cmd[6]); /* transfer length */ memset (&buf, 0, sizeof(buf)); status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &buf, &buf_size); /* set the fields in the scanner handle for later reference */ s->iconwidth = _4btol(buf.iconwidth); s->iconlength = _4btol(buf.iconlength); DBG(3, "read_icon_data: windowwidth:%lu, windowlength:%lu\n", _4btol(buf.windowwidth), _4btol(buf.windowlength)); DBG(3, "read_icon_data: iconwidth:%lu, iconlength:%lu, iconwidth(bytes):%lu\n", _4btol(buf.iconwidth), _4btol(buf.iconlength), _4btol(buf.iconwidthbytes)); DBG(3, "read_icon_data: bitordering:%02x, icondatalen:%lu\n", buf.bitordering, _4btol(buf.icondatalen)); DBG (3, "read_icon_data returning %d\n", status); return status; } static SANE_Status read_barfile (BH_Scanner *s, void *buf, size_t *buf_size) { SANE_Status status = SANE_STATUS_GOOD; size_t nread; DBG (3, "read_barfile called (%lu bytes)\n", (u_long) *buf_size); if (s->barf != NULL) { /* this function needs to set InvalidBytes so it looks * like a B&H scsi EOF */ if ((nread = fread(buf, 1, *buf_size, s->barf)) < *buf_size) { /* set InvalidBytes */ s->InvalidBytes = *buf_size - nread; if (ferror(s->barf)) { status = SANE_STATUS_IO_ERROR; fclose(s->barf); s->barf = NULL; unlink(s->barfname); } else if (feof(s->barf)) { /* it also needs to close the file and delete it when EOF is * reached. */ fclose(s->barf); s->barf = NULL; unlink(s->barfname); } } } else { /* set InvalidBytes */ s->InvalidBytes = *buf_size; } return status; } static SANE_Status read_data (BH_Scanner *s, void *buf, size_t *buf_size) { static SANE_Byte cmd[10]; SANE_Status status; DBG (3, "read_data called (%lu bytes)\n", (u_long) *buf_size); if (s->readlist[s->readptr] == BH_SCSI_READ_TYPE_SENDBARFILE) { /* call special barcode data read function. */ status = read_barfile(s, buf, buf_size); } else { memset (&cmd, 0, sizeof (cmd)); cmd[0] = BH_SCSI_READ_SCANNED_DATA; cmd[2] = s->readlist[s->readptr]; _lto3b(*buf_size, &cmd[6]); /* transfer length */ status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, buf_size); } return status; } static SANE_Status mode_select_measurement (BH_Scanner *s) { static struct { SANE_Byte cmd[6]; struct mode_page_03 mp; } select_cmd; SANE_Status status; DBG (3, "mode_select_measurement called (bmu:%d mud:%d)\n", s->bmu, s->mud); memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; select_cmd.cmd[1] = 0x10; select_cmd.cmd[4] = sizeof(select_cmd.mp); select_cmd.mp.pagecode = BH_MODE_MEASUREMENT_PAGE_CODE; select_cmd.mp.paramlen = 0x06; select_cmd.mp.bmu = s->bmu; _lto2b(s->mud, select_cmd.mp.mud); status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); return status; } static SANE_Status mode_select_timeout (BH_Scanner *s) { static struct { SANE_Byte cmd[6]; struct mode_page_20 mp; } select_cmd; SANE_Status status; DBG (3, "mode_select_timeout called\n"); memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; select_cmd.cmd[1] = 0x10; select_cmd.cmd[4] = sizeof(select_cmd.mp); select_cmd.mp.pagecode = BH_MODE_TIMEOUT_PAGE_CODE; select_cmd.mp.paramlen = 0x06; select_cmd.mp.timeoutmanual = _OPT_VAL_WORD(s, OPT_TIMEOUT_MANUAL); select_cmd.mp.timeoutadf = _OPT_VAL_WORD(s, OPT_TIMEOUT_ADF); status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); return status; } static SANE_Status mode_select_icon (BH_Scanner *s) { static struct { SANE_Byte cmd[6]; struct mode_page_21 mp; } select_cmd; SANE_Status status; DBG (3, "mode_select_icon called\n"); memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; select_cmd.cmd[1] = 0x10; select_cmd.cmd[4] = sizeof(select_cmd.mp); select_cmd.mp.pagecode = BH_MODE_ICON_PAGE_CODE; select_cmd.mp.paramlen = 0x06; _lto2b(_OPT_VAL_WORD(s, OPT_ICON_WIDTH), select_cmd.mp.iconwidth); _lto2b(_OPT_VAL_WORD(s, OPT_ICON_LENGTH), select_cmd.mp.iconlength); status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); return status; } static SANE_Status mode_select_barcode_priority (BH_Scanner *s) { static struct { SANE_Byte cmd[6]; struct mode_page_30 mp; } select_cmd; SANE_Status status; int i; DBG (3, "mode_select_barcode_priority called\n"); memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; select_cmd.cmd[1] = 0x10; select_cmd.cmd[4] = sizeof(select_cmd.mp); select_cmd.mp.pagecode = BH_MODE_BARCODE_PRIORITY_PAGE_CODE; select_cmd.mp.paramlen = 0x06; for (i = 0; i < NUM_SEARCH_BARS; i++) { /* anything after a 'none' is ignored */ if ((select_cmd.mp.priority[i] = s->search_bars[i]) == 0) break; } status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); return status; } static SANE_Status mode_select_barcode_param1 (BH_Scanner *s) { static struct { SANE_Byte cmd[6]; struct mode_page_31 mp; } select_cmd; SANE_Status status; DBG (3, "mode_select_barcode_param1 called\n"); memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; select_cmd.cmd[1] = 0x10; select_cmd.cmd[4] = sizeof(select_cmd.mp); select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM1_PAGE_CODE; select_cmd.mp.paramlen = 0x06; _lto2b((SANE_Int)_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BARCODE_HMIN), select_cmd.mp.minbarheight); select_cmd.mp.searchcount = _OPT_VAL_WORD(s, OPT_BARCODE_SEARCH_COUNT); select_cmd.mp.searchmode = get_barcode_search_mode(_OPT_VAL_STRING(s, OPT_BARCODE_SEARCH_MODE)); _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_SEARCH_TIMEOUT), select_cmd.mp.searchtimeout); status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); return status; } static SANE_Status mode_select_barcode_param2 (BH_Scanner *s) { static struct { SANE_Byte cmd[6]; struct mode_page_32 mp; } select_cmd; SANE_Status status; size_t len; DBG (3, "mode_select_barcode_param2 called\n"); /* first we'll do a mode sense, then we'll overwrite with * our new values, and then do a mode select */ memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SENSE; select_cmd.cmd[2] = BH_MODE_BARCODE_PARAM2_PAGE_CODE; select_cmd.cmd[4] = sizeof(select_cmd.mp); len = sizeof(select_cmd.mp); status = sanei_scsi_cmd (s->fd, &select_cmd.cmd, sizeof (select_cmd.cmd), &select_cmd.mp, &len); if (status == SANE_STATUS_GOOD) { DBG(8, "mode_select_barcode_param2: sensed values: relmax:%d barmin:%d barmax:%d\n", (int) _2btol(select_cmd.mp.relmax), (int) _2btol(select_cmd.mp.barmin), (int) _2btol(select_cmd.mp.barmax)); memset (&select_cmd.cmd, 0, sizeof (select_cmd.cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; select_cmd.cmd[1] = 0x10; select_cmd.cmd[4] = sizeof(select_cmd.mp); select_cmd.mp.modedatalen = 0x00; select_cmd.mp.mediumtype = 0x00; select_cmd.mp.devicespecificparam = 0x00; select_cmd.mp.blockdescriptorlen = 0x00; select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM2_PAGE_CODE; select_cmd.mp.paramlen = 0x06; /* only overwrite the default values if the option is non-zero */ if (_OPT_VAL_WORD(s, OPT_BARCODE_RELMAX) != 0) { _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_RELMAX), select_cmd.mp.relmax); } if (_OPT_VAL_WORD(s, OPT_BARCODE_BARMIN) != 0) { _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_BARMIN), select_cmd.mp.barmin); } if (_OPT_VAL_WORD(s, OPT_BARCODE_BARMAX) != 0) { _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_BARMAX), select_cmd.mp.barmax); } DBG(8, "mode_select_barcode_param2: param values: relmax:%d barmin:%d barmax:%d\n", (int) _OPT_VAL_WORD(s, OPT_BARCODE_RELMAX), (int) _OPT_VAL_WORD(s, OPT_BARCODE_BARMIN), (int) _OPT_VAL_WORD(s, OPT_BARCODE_BARMAX)); DBG(8, "mode_select_barcode_param2: select values: relmax:%d barmin:%d barmax:%d\n", (int) _2btol(select_cmd.mp.relmax), (int) _2btol(select_cmd.mp.barmin), (int) _2btol(select_cmd.mp.barmax)); status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); } return status; } static SANE_Status mode_select_barcode_param3 (BH_Scanner *s) { static struct { SANE_Byte cmd[6]; struct mode_page_33 mp; } select_cmd; SANE_Status status; size_t len; DBG (3, "mode_select_barcode_param3 called\n"); /* first we'll do a mode sense, then we'll overwrite with * our new values, and then do a mode select */ memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SENSE; select_cmd.cmd[2] = BH_MODE_BARCODE_PARAM3_PAGE_CODE; select_cmd.cmd[4] = sizeof(select_cmd.mp); len = sizeof(select_cmd.mp); status = sanei_scsi_cmd (s->fd, &select_cmd.cmd, sizeof (select_cmd.cmd), &select_cmd.mp, &len); if (status == SANE_STATUS_GOOD) { DBG(8, "mode_select_barcode_param3: sensed values: contrast:%d patchmode:%d\n", (int) _2btol(select_cmd.mp.barcodecontrast), (int) _2btol(select_cmd.mp.patchmode)); memset (&select_cmd.cmd, 0, sizeof (select_cmd.cmd)); select_cmd.cmd[0] = BH_SCSI_MODE_SELECT; select_cmd.cmd[1] = 0x10; select_cmd.cmd[4] = sizeof(select_cmd.mp); select_cmd.mp.modedatalen = 0x00; select_cmd.mp.mediumtype = 0x00; select_cmd.mp.devicespecificparam = 0x00; select_cmd.mp.blockdescriptorlen = 0x00; select_cmd.mp.pagecode = BH_MODE_BARCODE_PARAM3_PAGE_CODE; select_cmd.mp.paramlen = 0x06; /* only overwrite the default values if the option is non-zero */ if (_OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST) != 0) { _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST), select_cmd.mp.barcodecontrast); } if (_OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE) != 0) { _lto2b(_OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE), select_cmd.mp.patchmode); } DBG(8, "mode_select_barcode_param3: param values: contrast:%d patchmode:%d\n", (int) _OPT_VAL_WORD(s, OPT_BARCODE_CONTRAST), (int) _OPT_VAL_WORD(s, OPT_BARCODE_PATCHMODE)); DBG(8, "mode_select_barcode_param3: select values: contrast:%d patchmode:%d\n", (int) _2btol(select_cmd.mp.barcodecontrast), (int) _2btol(select_cmd.mp.patchmode)); status = sanei_scsi_cmd (s->fd, &select_cmd, sizeof (select_cmd), 0, 0); } return status; } static SANE_Status inquiry (int fd, void *buf, size_t *buf_size, SANE_Byte evpd, SANE_Byte page_code) { static SANE_Byte cmd[6]; SANE_Status status; DBG (3, "inquiry called\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = BH_SCSI_INQUIRY; cmd[1] = evpd; cmd[2] = page_code; cmd[4] = *buf_size; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); return status; } static SANE_Status set_window (BH_Scanner *s, SANE_Byte batchmode) { static struct { SANE_Byte cmd[10]; SANE_Byte hdr[8]; struct window_data window; } set_window_cmd; SANE_Status status; SANE_Int width, length, i, format, rotation, deskew ; DBG (3, "set_window called\n"); /* set to thousandths for set_window */ s->bmu = BH_UNIT_INCH; s->mud = 1000; status = mode_select_measurement(s); if (status != SANE_STATUS_GOOD) return status; memset (&set_window_cmd, 0, sizeof (set_window_cmd)); set_window_cmd.cmd[0] = BH_SCSI_SET_WINDOW; DBG(3, "set_window: sizeof(hdr) %d, sizeof(window): %d\n", (int)sizeof(set_window_cmd.hdr), (int)sizeof(set_window_cmd.window)); _lto3b(sizeof(set_window_cmd.hdr) + sizeof(set_window_cmd.window), &set_window_cmd.cmd[6]); _lto2b(256, &set_window_cmd.hdr[6]); set_window_cmd.window.windowid = 0; set_window_cmd.window.autoborder = _OPT_VAL_WORD(s, OPT_AUTOBORDER); DBG (5, "autoborder set to=%d\n", set_window_cmd.window.autoborder); _lto2b(_OPT_VAL_WORD(s, OPT_RESOLUTION), set_window_cmd.window.xres); _lto2b(_OPT_VAL_WORD(s, OPT_RESOLUTION), set_window_cmd.window.yres); _lto4b((int) _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X), set_window_cmd.window.ulx); _lto4b((int) _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y), set_window_cmd.window.uly); width = (SANE_Int) (_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_X) - _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X)); length = (SANE_Int) (_OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_Y) - _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y)); _lto4b(width, set_window_cmd.window.windowwidth); _lto4b(length, set_window_cmd.window.windowlength); /* brightness (1-255) 0 is default, aka 128. Ignored with ACE scanners */ set_window_cmd.window.brightness = _OPT_VAL_WORD(s, OPT_BRIGHTNESS); /* threshold (1-255) 0 is default, aka 128. Ignored with ACE scanners */ set_window_cmd.window.threshold = _OPT_VAL_WORD(s, OPT_THRESHOLD); /*!!! contrast (not used) */ /*!!! set_window_cmd.window.contrast = _OPT_VAL_WORD(s, OPT_CONTRAST); */ /* imagecomposition 0x00 lineart, 0x01 dithered/halftone, 0x02 grayscale*/ set_window_cmd.window.imagecomposition = get_scan_mode_id(_OPT_VAL_STRING(s, OPT_SCAN_MODE)); set_window_cmd.window.bitsperpixel = 0x01; /*!!! halftone code (not used) */ /*!!! halftone id (not used) */ set_window_cmd.window.paddingtype = 0x03; /* truncate byte */ if (_OPT_VAL_WORD(s, OPT_NEGATIVE) == SANE_TRUE) { /* reverse image format (valid when bitsperpixel=1) * 0x00 normal, 0x01 reversed. This is bit 7 of paddingtype. */ set_window_cmd.window.paddingtype |= 0x80; } set_window_cmd.window.bitordering[0] = 0x00; /* we must always sent plain gray data in preview mode */ format = (_OPT_VAL_WORD(s, OPT_PREVIEW)) ? BH_COMP_NONE : get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); switch (format) { case BH_COMP_G31D: set_window_cmd.window.compressiontype = 0x01; set_window_cmd.window.compressionarg = 0x00; set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ break; case BH_COMP_G32D: set_window_cmd.window.compressiontype = 0x02; set_window_cmd.window.compressionarg = 0x04; set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ break; case BH_COMP_G42D: set_window_cmd.window.compressiontype = 0x03; set_window_cmd.window.compressionarg = 0x00; set_window_cmd.window.bitordering[1] = 0x01; /* Bit ordering LSB */ break; case BH_COMP_NONE: default: set_window_cmd.window.compressiontype = 0x00; set_window_cmd.window.compressionarg = 0x00; set_window_cmd.window.bitordering[1] = 0x00; /* n/a */ break; } /* rotation and deskew settings, if autoborder is turned on */ if(set_window_cmd.window.autoborder){ /*--- setting byte 46 of the window descriptor block only works with autoborder */ rotation = get_rotation_id(_OPT_VAL_STRING(s, OPT_ROTATION)); if (_OPT_VAL_WORD(s, OPT_DESKEW) == SANE_TRUE) deskew = BH_DESKEW_ENABLE; else deskew = BH_DESKEW_DISABLE; set_window_cmd.window.border_rotation = ( rotation | deskew ); /*--- deskew assumes autoborder */ } /* remote - 0x00 ACE set in window; 0x01 ACE set by control panel */ set_window_cmd.window.remote = _OPT_VAL_WORD(s, OPT_CONTROL_PANEL); if (set_window_cmd.window.remote == 0x00) { /* acefunction (ignored on non-ACE scanners) */ set_window_cmd.window.acefunction = _OPT_VAL_WORD(s, OPT_ACE_FUNCTION); /* acesensitivity (ignored on non-ACE scanners) */ set_window_cmd.window.acesensitivity = _OPT_VAL_WORD(s, OPT_ACE_SENSITIVITY); } set_window_cmd.window.batchmode = batchmode; /* fill in the section descriptor blocks */ for (i = 0; i < s->num_sections; i++) { BH_SectionBlock *b; b = &set_window_cmd.window.sectionblock[i]; _lto4b(s->sections[i].left, b->ul_x); _lto4b(s->sections[i].top, b->ul_y); _lto4b(s->sections[i].width, b->width); _lto4b(s->sections[i].length, b->length); b->compressiontype = s->sections[i].compressiontype; b->compressionarg = s->sections[i].compressionarg; } status = sanei_scsi_cmd (s->fd, &set_window_cmd, sizeof (set_window_cmd), 0, 0); DBG (5, "sanei_scsi_cmd executed, status=%d\n", status ); if (status != SANE_STATUS_GOOD) return status; /* set to points for reading */ s->bmu = BH_UNIT_POINT; s->mud = 1; status = mode_select_measurement(s); return status; } static SANE_Status get_window (BH_Scanner *s, SANE_Int *w, SANE_Int *h, SANE_Bool backpage) { SANE_Byte cmd[10]; static struct { SANE_Byte hdr[8]; struct window_data window; } get_window_data; SANE_Status status; SANE_Int x, y, i = 0, get_window_delay = 1; SANE_Bool autoborder; size_t len; DBG (3, "get_window called\n"); autoborder = _OPT_VAL_WORD(s, OPT_AUTOBORDER) == 1; while (1) { i++; memset (&cmd, 0, sizeof (cmd)); memset (&get_window_data, 0, sizeof (get_window_data)); cmd[0] = BH_SCSI_GET_WINDOW; _lto3b(sizeof(get_window_data), &cmd[6]); _lto2b(256, &get_window_data.hdr[6]); get_window_data.window.windowid = (backpage == SANE_TRUE) ? 1 : 0; len = sizeof(get_window_data); status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), &get_window_data, &len); if (status == SANE_STATUS_GOOD) { x =_4btol(get_window_data.window.ulx); y =_4btol(get_window_data.window.uly); *w =_4btol(get_window_data.window.windowwidth); *h =_4btol(get_window_data.window.windowlength); if (autoborder) { /* we try repeatedly until we get the autoborder bit set */ if (get_window_data.window.autoborder != 1 && i < BH_AUTOBORDER_TRIES) { DBG (5, "waiting %d second[s], try: %d\n",get_window_delay,i); sleep(get_window_delay); /*--- page 4-5 of B&H Copiscan 8000 ESC OEM Tech Manual */ /*--- requires at least 50ms wait between each GET WINDOW command */ /*--- experience shows that this can take 3 to 4 seconds */ continue; } if (get_window_data.window.autoborder != 1) { DBG(1, "Automatic Border Detection not done within %d tries\n", BH_AUTOBORDER_TRIES); status = SANE_STATUS_IO_ERROR; } DBG (0, "page dimension: wide:%d high:%d \n",*w,*h); } DBG (3, "*** Window size: %dx%d+%d+%d\n", *w, *h, x, y); DBG (5, "*** get_window found autoborder=%02xh\n", get_window_data.window.autoborder); DBG (5, "*** get_window found border_rotation=%02xh\n", get_window_data.window.border_rotation); } /* we are 'outta here' */ break; } return status; } static SANE_Status get_parameters (SANE_Handle handle, SANE_Parameters *params) { BH_Scanner *s = handle; SANE_Int width, length, res, comp; double br_x, tl_x, br_y, tl_y; SANE_Frame format; DBG(3, "get_parameters called\n"); memset (&s->params, 0, sizeof (s->params)); res = _OPT_VAL_WORD(s, OPT_RESOLUTION); /* make best-effort guess at what parameters will look like once the scan starts. */ br_x = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_X); br_y = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_BR_Y); tl_x = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_X); tl_y = _OPT_VAL_WORD_THOUSANDTHS(s, OPT_TL_Y); width = (br_x - tl_x + 1) * res / 1000.0; length = (br_y - tl_y + 1) * res / 1000.0; /* figure out the default image format for front/back pages */ comp = get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); switch (comp) { case BH_COMP_G31D: format = SANE_FRAME_G31D; break; case BH_COMP_G32D: format = SANE_FRAME_G32D; break; case BH_COMP_G42D: format = SANE_FRAME_G42D; break; case BH_COMP_NONE: default: format = SANE_FRAME_GRAY; break; } if (s->scanning) { SANE_Int w, l, status; SANE_Byte itemtype; itemtype = s->readlist[s->readptr]; /* update parameters based on the current item */ status = SANE_STATUS_GOOD; if (itemtype == BH_SCSI_READ_TYPE_FRONT) { DBG (3, "get_parameters: sending GET WINDOW (front)\n"); status = get_window (s, &w, &l, SANE_FALSE); if (status == SANE_STATUS_GOOD) { width = w; length = l; } } else if (itemtype == BH_SCSI_READ_TYPE_BACK) { DBG (3, "get_parameters: sending GET WINDOW (back)\n"); status = get_window (s, &w, &l, SANE_TRUE); if (status == SANE_STATUS_GOOD) { width = w; length = l; } } else if (itemtype == BH_SCSI_READ_TYPE_FRONT_ICON || itemtype == BH_SCSI_READ_TYPE_BACK_ICON) { /* the icon is never compressed */ format = SANE_FRAME_GRAY; width = s->iconwidth; length = s->iconlength; } else if (itemtype > BH_SCSI_READ_TYPE_FRONT && itemtype <= (BH_SCSI_READ_TYPE_FRONT + NUM_SECTIONS)) { /* a front section */ SANE_Int sectnum = itemtype - BH_SCSI_READ_TYPE_FRONT; format = s->sections[sectnum - 1].format; /* convert from thousandths to pixels */ width = s->sections[sectnum - 1].width * res / 1000.0; length = s->sections[sectnum - 1].length * res / 1000.0; } else if (itemtype > BH_SCSI_READ_TYPE_BACK && itemtype <= (BH_SCSI_READ_TYPE_BACK + NUM_SECTIONS)) { /* a back section */ SANE_Int sectnum = itemtype - BH_SCSI_READ_TYPE_BACK; format = s->sections[sectnum - 1].format; /* convert from thousandths to pixels */ width = s->sections[sectnum - 1].width * res / 1000.0; length = s->sections[sectnum - 1].length * res / 1000.0; } else if ( (itemtype >= BH_SCSI_READ_TYPE_BACK_BARCODE && itemtype <= (BH_SCSI_READ_TYPE_BACK_BARCODE + NUM_SECTIONS)) || (itemtype >= BH_SCSI_READ_TYPE_FRONT_BARCODE && itemtype <= (BH_SCSI_READ_TYPE_FRONT_BARCODE + NUM_SECTIONS)) ) { /* decoded barcode data */ format = SANE_FRAME_TEXT; width = 8; length = -1; } else if (itemtype == BH_SCSI_READ_TYPE_SENDBARFILE) { /* decoded barcode data file */ format = SANE_FRAME_TEXT; width = 8; length = -1; } else { format = SANE_FRAME_GRAY; width = 8; length = -1; DBG(1, "get_parameters: unrecognized read itemtype: %d\n", itemtype); } if (status != SANE_STATUS_GOOD) { DBG(1, "get_parameters: failed\n"); return status; } } if (res <= 0 || width <= 0) { DBG(1, "get_parameters:illegal parameters res=%d, width=%d, length=%d\n", res, width, length); return SANE_STATUS_INVAL; } /* we disable our compression/barcode formats in preview as well * as with the disable_optional_frames configuration option. NOTE: * we may still be delivering 'wierd' data and lying about it being _GRAY! */ if (format != SANE_FRAME_GRAY && (_OPT_VAL_WORD(s, OPT_PREVIEW) || disable_optional_frames)) { DBG(1, "get_parameters: warning: delivering %s data as gray", sane_strframe(format)); format = SANE_FRAME_GRAY; } s->params.format = format; s->params.depth = 1; s->params.last_frame = SANE_TRUE; s->params.pixels_per_line = width; s->params.lines = length; s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; /* The Bell and Howell truncates to the byte */ s->params.pixels_per_line = s->params.bytes_per_line * 8; if (params) *params = s->params; DBG (1, "get_parameters: format=%d, pixels/line=%d, bytes/line=%d, " "lines=%d, dpi=%d\n", (int) s->params.format, s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, res); return SANE_STATUS_GOOD; } static SANE_Status section_parse(const char *val, BH_Section *sect, SANE_Int res, SANE_Int comp) { SANE_Status status = SANE_STATUS_INVAL; char buf[255+1], *x, *y, *w, *l, *f, *ep; const char *seps = "x+:"; double mm, fpixels; u_long pixels; DBG(3, "section_parse called\n"); /* a section option looks something like this: * x++: * Example: * 76.2x25.4+50.8+0:frontbar:back:front * the width, length, tl-x, and tl-y are in mm. * the function codes are one or more of: * front, back, frontbar, backbar, frontpatch, backpatch */ if (strlen(val) > sizeof(buf) - 1) { DBG(1, "section_parse: option string too long\n"); status = SANE_STATUS_INVAL; } else { do { strcpy(buf, val); x = y = w = l = f = NULL; w = strtok(buf, seps); if (w) l = strtok(NULL, seps); if (l) x = strtok(NULL, seps); if (x) y = strtok(NULL, seps); if (y) f = strtok(NULL, seps); if (!x || !y || !w || !l) break; mm = strtod(x, &ep); if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; sect->left = mm * 1000.0 / MM_PER_INCH; mm = strtod(y, &ep); if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; sect->top = mm * 1000.0 / MM_PER_INCH; mm = strtod(w, &ep); if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; sect->width = mm * 1000.0 / MM_PER_INCH; /* the window width must be truncated to 16 bit points */ fpixels = sect->width * res / 1000.0; pixels = fpixels / 16; sect->width = pixels * 16 * 1000 / res; mm = strtod(l, &ep); if (*ep != '\0' || errno == ERANGE || mm < 0.0) break; sect->length = mm * 1000.0 / MM_PER_INCH; status = SANE_STATUS_GOOD; while (f) { /* parse the function modifiers and set flags */ if (strcmp(f, "front") == 0) sect->flags |= BH_SECTION_FRONT_IMAGE; else if (strcmp(f, "frontbar") == 0) sect->flags |= BH_SECTION_FRONT_BAR; else if (strcmp(f, "frontpatch") == 0) sect->flags |= BH_SECTION_FRONT_PATCH; else if (strcmp(f, "back") == 0) sect->flags |= BH_SECTION_BACK_IMAGE; else if (strcmp(f, "backbar") == 0) sect->flags |= BH_SECTION_BACK_BAR; else if (strcmp(f, "backpatch") == 0) sect->flags |= BH_SECTION_BACK_PATCH; else if (strcmp(f, "g42d") == 0) comp = BH_COMP_G42D; else if (strcmp(f, "g32d") == 0) comp = BH_COMP_G32D; else if (strcmp(f, "g31d") == 0) comp = BH_COMP_G31D; else if (strcmp(f, "none") == 0) comp = BH_COMP_NONE; else DBG(1, "section_parse: ignoring unrecognized function " "code '%s'\n", f); f = strtok(NULL, seps); } switch (comp) { case BH_COMP_G31D: sect->compressiontype = 0x01; sect->compressionarg = 0x00; sect->format = SANE_FRAME_G31D; break; case BH_COMP_G32D: sect->compressiontype = 0x02; sect->compressionarg = 0x04; sect->format = SANE_FRAME_G32D; break; case BH_COMP_G42D: sect->compressiontype = 0x03; sect->compressionarg = 0x00; sect->format = SANE_FRAME_G42D; break; case BH_COMP_NONE: default: sect->compressiontype = 0x00; sect->compressionarg = 0x00; sect->format = SANE_FRAME_GRAY; break; } DBG(3, "section_parse: converted '%s' (mm) to " "%ldx%ld+%ld+%ld (thousandths) " "flags=%02x compression=[%d,%d] frame=%s\n", val, sect->width, sect->length, sect->left, sect->top, sect->flags, sect->compressiontype, sect->compressionarg, sane_strframe(sect->format)); } while (0); /* perform 'loop' once */ } return status; } static SANE_Status setup_sections (BH_Scanner *s, const char *val) { SANE_Status status = SANE_STATUS_GOOD; SANE_Int sectnum = 0; char buf[255+1], *section; DBG(3, "setup_sections called\n"); memset(s->sections, '\0', sizeof(s->sections)); if (strlen(val) > sizeof(buf) - 1) { DBG(1, "setup_sections: option string too long\n"); status = SANE_STATUS_INVAL; } else { strcpy(buf, val); section = strtok(buf, ","); while (section != NULL && sectnum < NUM_SECTIONS) { if (!allblank(section)) { SANE_Int res = _OPT_VAL_WORD(s, OPT_RESOLUTION); SANE_Int format = get_compression_id(_OPT_VAL_STRING(s, OPT_COMPRESSION)); status = section_parse(section, &s->sections[sectnum], res, format); if (status != SANE_STATUS_GOOD) { DBG(1, "setup_sections: error parsing section `%s'\n", section); break; } sectnum++; } section += strlen(section) + 1; if (section > buf + strlen(val)) break; section = strtok(section, ","); } } s->num_sections = sectnum; return status; } static SANE_Status start_setup (BH_Scanner *s) { SANE_Status status; SANE_Bool duplex; SANE_Int i, imagecnt; SANE_Byte batchmode; DBG(3, "start_setup called\n"); duplex = _OPT_VAL_WORD(s, OPT_DUPLEX); /* get the _SECTION option, parse it and fill in the sections */ status = setup_sections(s, _OPT_VAL_STRING(s, OPT_SECTION)); if (status != SANE_STATUS_GOOD) { DBG(1, "start_setup: setup_sections failed: %s\n", sane_strstatus(status)); return status; } /* see whether we'll be decoding barcodes and * set the barcodes flag appropriately */ if (s->search_bars[0] == 0) { s->barcodes = SANE_FALSE; } else { s->barcodes = SANE_TRUE; } /* see whether we'll be handling icons (thumbnails) * set the icons flag appropriately */ if (_OPT_VAL_WORD(s, OPT_ICON_WIDTH) >= 8 && _OPT_VAL_WORD(s, OPT_ICON_LENGTH) >= 8) { s->icons = SANE_TRUE; } else { s->icons = SANE_FALSE; } /* calculate a new readlist for this 'batch' */ s->readptr = s->readcnt = 0; /* always read the front image */ s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT; /* read back page only if duplex is true */ if (duplex == SANE_TRUE) { s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK; } /* add image section reads to the readlist */ for (i = 0; i < s->num_sections; i++) { SANE_Word flags = s->sections[i].flags; if (flags & BH_SECTION_FRONT_IMAGE) s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT + i + 1; if (flags & BH_SECTION_BACK_IMAGE) s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK + i + 1; } /* icons (thumbnails) */ if (s->icons) { s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_ICON; /* read back icon only if duplex is true */ if (duplex == SANE_TRUE) { s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_ICON; } } /* NOTE: It is important that all of the image data comes before * the barcode/patchcode data. */ /* barcodes */ imagecnt = s->readcnt; if (s->barcodes) { if (s->num_sections == 0) { /* we only decode the entire page(s) if there are no * sections defined */ s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_BARCODE; /* read back barcode only if duplex is true */ if (duplex == SANE_TRUE) { s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_BARCODE; } } else { /* add barcode section reads to the readlist */ for (i = 0; i < s->num_sections; i++) { SANE_Word flags = s->sections[i].flags; if (flags & BH_SECTION_FRONT_BAR) s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_BARCODE + i + 1; if (flags & BH_SECTION_BACK_BAR) s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_BARCODE + i + 1; } } } /* patchcodes */ if (s->patchcodes) { if (s->num_sections == 0) { /* we only decode the entire page(s) if there are no * sections defined */ s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_PATCHCODE; /* read back patchcode only if duplex is true */ if (duplex == SANE_TRUE) { s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_PATCHCODE; } } else { /* add patchcode section reads to the readlist */ for (i = 0; i < s->num_sections; i++) { SANE_Word flags = s->sections[i].flags; if (flags & BH_SECTION_FRONT_PATCH) s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_FRONT_PATCHCODE + i + 1; if (flags & BH_SECTION_BACK_PATCH) s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_BACK_PATCHCODE + i + 1; } } } /* add the special item to the read list which transfers the barcode * file that's built as a result of processing barcode and patchcode * readitems. NOTE: this one must be last! */ if (s->readcnt > imagecnt) { s->readlist[s->readcnt++] = BH_SCSI_READ_TYPE_SENDBARFILE; } if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE) { /* if batchmode is enabled, then call set_window to * abort the batch (even though there might not (and probably * isn't) a batch in progress). This avoids a batch start error * in the case where a previous batch was not aborted. */ DBG(5, "start_setup: calling set_window to abort batch\n"); set_window(s, BH_BATCH_ABORT); batchmode = BH_BATCH_ENABLE; } else { batchmode = BH_BATCH_DISABLE; } DBG(5, "start_setup: duplex=%s, barcodes=%s, patchcodes=%s, " "icons=%s, batch=%s\n", (duplex == SANE_TRUE) ? "yes" : "no", (s->barcodes == SANE_TRUE) ? "yes" : "no", (s->patchcodes == SANE_TRUE) ? "yes" : "no", (s->icons == SANE_TRUE) ? "yes" : "no", (batchmode == BH_BATCH_ENABLE) ? "yes" : "no"); DBG(5, "start_setup: sections=%d\n", s->num_sections); for (i = 0; i < s->num_sections; i++) { DBG(5, "start_setup: " "[%d] %lux%lu+%lu+%lu flags=%02x compression=[%d,%d]\n", i+1, s->sections[i].width, s->sections[i].length, s->sections[i].left, s->sections[i].top, s->sections[i].flags, s->sections[i].compressiontype, s->sections[i].compressionarg); } DBG(5, "start_setup: read list length=%d\n", s->readcnt); for (i = 0; i < s->readcnt; i++) { DBG(5, "start_setup: [%d] %s\n", i+1, print_read_type(s->readlist[i])); } DBG(5, "start_setup: sending SET WINDOW\n"); status = set_window(s, batchmode); if (status != SANE_STATUS_GOOD) { DBG(1, "start_setup: SET WINDOW failed: %s\n", sane_strstatus(status)); return status; } DBG(5, "start_setup: sending mode_select_timeout\n"); status = mode_select_timeout(s); if (status != SANE_STATUS_GOOD) { DBG(1, "start_setup: mode_select_timeout failed: %s\n", sane_strstatus(status)); return status; } if (s->icons == SANE_TRUE) { DBG(5, "start_setup: sending mode_select_icon\n"); status = mode_select_icon(s); if (status != SANE_STATUS_GOOD) { DBG(1, "start_setup: mode_select_icon failed: %s\n", sane_strstatus(status)); return status; } } if (s->barcodes == SANE_TRUE) { DBG(5, "start_setup: sending mode_select_barcode_priority\n"); status = mode_select_barcode_priority(s); if (status != SANE_STATUS_GOOD) { DBG(1, "start_setup: mode_select_barcode_priority failed: %s\n", sane_strstatus(status)); return status; } DBG(5, "start_setup: sending mode_select_barcode_param1\n"); status = mode_select_barcode_param1(s); if (status != SANE_STATUS_GOOD) { DBG(1, "start_setup: mode_select_barcode_param1 failed: %s\n", sane_strstatus(status)); return status; } DBG(5, "start_setup: sending mode_select_barcode_param2\n"); status = mode_select_barcode_param2(s); if (status != SANE_STATUS_GOOD) { DBG(1, "start_setup: mode_select_barcode_param2 failed: %s\n", sane_strstatus(status)); return status; } DBG(5, "start_setup: sending mode_select_barcode_param3\n"); status = mode_select_barcode_param3(s); if (status != SANE_STATUS_GOOD) { DBG(1, "start_setup: mode_select_barcode_param3 failed: %s\n", sane_strstatus(status)); return status; } } return status; } static SANE_Status start_scan (BH_Scanner *s) { static SANE_Byte cmd[8]; SANE_Status status = SANE_STATUS_GOOD; SANE_Bool check_adf, duplex; DBG (3, "start_scan called\n"); /* SANE front ends will call this function between 'FRAMES'. * A single scan on the B&H may result in up to 56 different * things to read (20 are SANE image frames, 36 are non-SANE * data - decoded bar/patch codes). */ if (s->readcnt > 1 && s->scanning == SANE_TRUE) { DBG(3, "start_scan: any more items in the readlist?\n"); /* we've been reading data from this scan, so we just * move on to the next item in the readlist without * starting a new scan. */ s->readptr++; if (s->readptr < s->readcnt) { SANE_Byte itemtype; for (; s->readptr < s->readcnt; s->readptr++) { itemtype = s->readlist[s->readptr]; DBG(3, "start_scan: advance readlist(%d, %d)\n", s->readptr, (int) itemtype); /* 'dance' by the non-SANE data streams * like bar/patch code data */ if (!BH_HAS_IMAGE_DATA(itemtype)) { int fd; FILE *fp; strncpy(s->barfname, "/tmp/bhXXXXXX", sizeof(s->barfname)); s->barfname[sizeof(s->barfname)-1] = '\0'; fd = mkstemp(s->barfname); if (fd !=-1 && (fp = fdopen(fd, "w")) != NULL) { fprintf(fp, "\n"); for (; s->readptr < s->readcnt && status == SANE_STATUS_GOOD; s->readptr++) { if (s->readlist[s->readptr] == BH_SCSI_READ_TYPE_SENDBARFILE) { break; } status = read_barcode_data(s, fp); if (status != SANE_STATUS_GOOD) break; } fprintf(fp, "\n"); /* close file; re-open for read(setting s->barfd) */ fclose(fp); if ((s->barf = fopen(s->barfname, "r")) == NULL) { DBG(1, "sane_start: error opening barfile `%s'\n", s->barfname); status = SANE_STATUS_IO_ERROR; } } else { DBG(1, "sane_start: error opening barfile `%s'\n", s->barfname); status = SANE_STATUS_IO_ERROR; } } else if (itemtype == BH_SCSI_READ_TYPE_FRONT_ICON || itemtype == BH_SCSI_READ_TYPE_BACK_ICON) { /* read the icon header setting the iconwidth and iconlength * to the actual values so get_parameters will have them. * Subsequent calls to sane_read will get pure image data * since the icon header has been consumed. */ status = read_icon_data(s); } if (status == SANE_STATUS_GOOD) { /* update our parameters to reflect the new item */ status = get_parameters (s, 0); } if (status != SANE_STATUS_GOOD) s->scanning = SANE_FALSE; return status; } /* if we reach here, we're finished with the readlist and * will drop through to start a new scan */ } } s->readptr = 0; check_adf = _OPT_VAL_WORD(s, OPT_CHECK_ADF); duplex = _OPT_VAL_WORD(s, OPT_DUPLEX); memset (&cmd, 0, sizeof (cmd)); cmd[0] = BH_SCSI_START_SCAN; cmd[4] = (duplex == SANE_TRUE) ? 2 : 1; cmd[6] = 0; cmd[7] = 1; if (check_adf) { status = object_position(s); if (status != SANE_STATUS_GOOD) { DBG(3, "object_position: returned %d\n", status); return status; } } status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); if (status == SANE_STATUS_GOOD) { s->scanning = SANE_TRUE; /* update our parameters, * now that we're scanning we'll do a GET_WINDOW */ status = get_parameters (s, 0); if (status != SANE_STATUS_GOOD) { s->scanning = SANE_FALSE; } } return status; } /* a sensible sense handler, courtesy of Franck; arg is a pointer to the associated BH_Scanner structure */ static SANE_Status sense_handler (int scsi_fd, u_char *result, void *arg) { BH_Scanner *s = (BH_Scanner *) arg; u_char sense, asc, ascq, EOM, ILI, ErrorCode, ValidData; u_long InvalidBytes; char *sense_str = "", *as_str = ""; SANE_Int i; SANE_Status status = SANE_STATUS_INVAL; SANE_Char print_sense[(16 * 3) + 1]; scsi_fd = scsi_fd; /* get rid of compiler warning */ ErrorCode = result[0] & 0x7F; ValidData = (result[0] & 0x80) != 0; sense = result[2] & 0x0f; /* Key */ asc = result[12]; /* Code */ ascq = result[13]; /* Qual */ EOM = (result[2] & 0x40) != 0; /* End Of Media */ ILI = (result[2] & 0x20) != 0; /* Invalid Length Indicator */ InvalidBytes = ValidData ? _4btol(&result[3]) : 0; DBG(3, "sense_handler: result=%x, sense=%x, asc=%x, ascq=%x\n", result[0], sense, asc, ascq); DBG(3, "sense_handler: ErrorCode %02x ValidData: %d " "EOM: %d ILI: %d InvalidBytes: %lu\n", ErrorCode, ValidData, EOM, ILI, InvalidBytes); memset(print_sense, '\0', sizeof(print_sense)); for (i = 0; i < 16; i++) { sprintf(print_sense + strlen(print_sense), "%02x ", result[i]); } DBG(5, "sense_handler: sense=%s\n", print_sense); if (ErrorCode != 0x70 && ErrorCode != 0x71) { DBG (3, "sense_handler: error code is invalid.\n"); return SANE_STATUS_IO_ERROR; /* error code is invalid */ } /* handle each sense key; * RSC supports 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0B */ switch (sense) { case 0x00: /* no sense */ sense_str = "No sense."; status = SANE_STATUS_GOOD; if (ILI && asc == 0x00 && ascq == 0x05) { /* from read_data function */ as_str = "ILI bit is set."; if (s != NULL) { s->InvalidBytes = InvalidBytes; } status = SANE_STATUS_GOOD; } else if (EOM && asc == 0x00 && ascq == 0x02) { /* from adfStatus or startScan function */ as_str = "Out of paper in the hopper."; status = SANE_STATUS_NO_DOCS; } else if (EOM) { /* from adfStatus or startScan function */ as_str = "Out of paper in the hopper."; status = SANE_STATUS_NO_DOCS; } break; case 0x01: /* recovered error */ sense_str = "Recovered error."; status = SANE_STATUS_GOOD; break; case 0x02: /* not ready */ sense_str = "Not ready."; status = SANE_STATUS_DEVICE_BUSY; if (asc == 0x40 && ascq == 0x01) { as_str = "P.O.D. error: Scanner not found."; status = SANE_STATUS_INVAL; } else if (asc == 0x40 && ascq == 0x02) { as_str = "P.O.D. error: Scanner not ready(paper in transport)."; status = SANE_STATUS_DEVICE_BUSY; } else if (asc == 0x40 && ascq == 0x03) { as_str = "P.O.D. error: Unknown scanner."; status = SANE_STATUS_INVAL; } break; case 0x03: /* medium error */ sense_str = "Medium error."; status = SANE_STATUS_IO_ERROR; if (asc == 0x00 && ascq == 0x00) { as_str = "Scanner error: paper jam detected."; status = SANE_STATUS_JAMMED; } break; case 0x04: /* hardware error */ sense_str = "Hardware error."; status = SANE_STATUS_IO_ERROR; if (asc == 0x60 && ascq == 0x00) { as_str = "Scanner error: illumination lamps failure."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x03) { as_str = "Communication error between RSC and scanner."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x06) { as_str = "Scanner error: page detected but lamps are off."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x07) { as_str = "Scanner error: camera white level problem."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x08) { /* could be caught from start_scan or read_data */ /* stop button pressed */ as_str = "Scanner error: operator pressed the Stop key."; status = SANE_STATUS_NO_DOCS; } else if (asc == 0x80 && ascq == 0x12) { as_str = "Scanner error: transport motor failure."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x15) { as_str = "Scanner error: device / page sensor(s) bouncing."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x16) { as_str = "Scanner error: feeder is not attached."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x18) { as_str = "Scanner error: logic system general failure."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x34) { as_str = "Scanner error: no dual logic communication."; status = SANE_STATUS_IO_ERROR; } break; case 0x05: /* illegal request */ sense_str = "Illegal request."; status = SANE_STATUS_INVAL; if (asc == 0x1a && ascq == 0x00) { as_str = "Parameter list length error."; status = SANE_STATUS_INVAL; } else if (asc == 0x20 && ascq == 0x00) { as_str = "Invalid command operation code."; status = SANE_STATUS_INVAL; } else if (asc == 0x24 && ascq == 0x00) { /* caught from object_position (via reverse engineering) */ /* Not supported? */ as_str = "Invalid field in CDB."; status = SANE_STATUS_INVAL; } else if (asc == 0x25 && ascq == 0x00) { as_str = "Unsupported LUN."; status = SANE_STATUS_INVAL; } else if (asc == 0x26 && ascq == 0x00) { /* caught from mode_select (as well as others) */ /* Bar/Patch code detection support not installed */ /* See Appendix A, Section A.5 */ as_str = "Invalid field in parameter list."; status = SANE_STATUS_INVAL; } else if (asc == 0x2c && ascq == 0x00) { /* we were getting this in read_data during the time that the ADF was misbehaving. Hopefully we will not see it anymore. */ as_str = "Command out of sequence."; status = SANE_STATUS_INVAL; } else if (asc == 0x2c && ascq == 0x01) { as_str = "Too many windows defined."; status = SANE_STATUS_INVAL; } else if (asc == 0x2c && ascq == 0x02) { as_str = "Batch start error."; status = SANE_STATUS_INVAL; } else if (asc == 0x2c && ascq == 0x03) { as_str = "Batch abort error."; status = SANE_STATUS_INVAL; } else if (asc == 0x3d && ascq == 0x00) { as_str = "Invalid bits in IDENTIFY message."; status = SANE_STATUS_INVAL; } break; case 0x06: /* unit attention */ sense_str = "Unit attention."; status = SANE_STATUS_IO_ERROR; if (asc == 0x04 && ascq == 0x01) { as_str = "Reset detected, LUN is becoming ready."; status = SANE_STATUS_DEVICE_BUSY; } break; case 0x07: /* data protect */ sense_str = "Data protect."; status = SANE_STATUS_IO_ERROR; break; case 0x08: /* blank check */ sense_str = "Blank check."; status = SANE_STATUS_IO_ERROR; break; case 0x09: /* vendor specific */ sense_str = "Vendor specific."; status = SANE_STATUS_IO_ERROR; break; case 0x0A: /* copy aborted */ sense_str = "Copy aborted."; status = SANE_STATUS_IO_ERROR; break; case 0x0B: /* aborted command */ sense_str = "Aborted command."; status = SANE_STATUS_IO_ERROR; if (asc == 0x00 && ascq == 0x00) { as_str = "Aborted command (unspecified error)."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x08 && ascq == 0x01) { /* caught from start_scan */ /* manual feed timeout */ as_str = "SCSI Time-out, paper Time-out (SCAN command)."; status = SANE_STATUS_NO_DOCS; } else if (asc == 0x47 && ascq == 0x00) { as_str = "SCSI parity error."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x00) { as_str = "Aborted command due to memory error."; status = SANE_STATUS_IO_ERROR; } else if (asc == 0x80 && ascq == 0x01) { /* caught from read_data */ /* section border error; border is outside the main window */ /* See Appendix A, Section A.4 */ as_str = "Section Read error (out of border)."; status = SANE_STATUS_INVAL; } else if (asc == 0x80 && ascq == 0x02) { /* caught from read_data */ /* No code found; no barcode data is found */ /* See Appendix A, Section A.5 */ s->barcode_not_found = SANE_TRUE; as_str = "No Bar/Patch Code found."; status = SANE_STATUS_GOOD; } else if (asc == 0x80 && ascq == 0x03) { as_str = "Icon Read error (out of border)."; status = SANE_STATUS_INVAL; } break; case 0x0C: /* equal */ sense_str = "Equal."; status = SANE_STATUS_IO_ERROR; break; case 0x0D: /* volume overflow */ sense_str = "Volume overflow."; status = SANE_STATUS_IO_ERROR; break; case 0x0E: /* miscompare */ sense_str = "Miscompare."; status = SANE_STATUS_IO_ERROR; break; case 0x0F: /* reserved */ sense_str = "Reserved."; status = SANE_STATUS_IO_ERROR; break; default: sense_str = "Unhandled case."; status = SANE_STATUS_IO_ERROR; break; } DBG(3, "sense_handler: '%s' '%s' return:%d\n", sense_str, as_str, status); return status; } static SANE_Status init_options (BH_Scanner * s) { int i; DBG (3, "init_options called\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_MODE_GROUP].name = ""; s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE_GROUP; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Preview: */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_PREVIEW].w = 0; /* Inquiry */ s->opt[OPT_INQUIRY].name = SANE_NAME_INQUIRY; s->opt[OPT_INQUIRY].title = SANE_TITLE_INQUIRY; s->opt[OPT_INQUIRY].desc = SANE_DESC_INQUIRY; s->opt[OPT_INQUIRY].type = SANE_TYPE_STRING; s->opt[OPT_INQUIRY].size = sizeof(inquiry_data); s->opt[OPT_INQUIRY].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_INQUIRY].s = strdup(inquiry_data); s->opt[OPT_INQUIRY].cap = SANE_CAP_SOFT_DETECT; /* scan mode */ s->opt[OPT_SCAN_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_SCAN_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_SCAN_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_SCAN_MODE].type = SANE_TYPE_STRING; s->opt[OPT_SCAN_MODE].size = max_string_size (scan_mode_list); s->opt[OPT_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SCAN_MODE].constraint.string_list = scan_mode_list; s->val[OPT_SCAN_MODE].s = strdup (scan_mode_list[0]); /* Standard resolutions */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->info.resStdList; s->val[OPT_RESOLUTION].w = s->hw->info.res_default; /* compression */ s->opt[OPT_COMPRESSION].name = SANE_NAME_COMPRESSION; s->opt[OPT_COMPRESSION].title = SANE_TITLE_COMPRESSION; s->opt[OPT_COMPRESSION].desc = SANE_DESC_COMPRESSION; s->opt[OPT_COMPRESSION].type = SANE_TYPE_STRING; s->opt[OPT_COMPRESSION].size = max_string_size (compression_list); s->opt[OPT_COMPRESSION].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_COMPRESSION].constraint.string_list = compression_list; s->val[OPT_COMPRESSION].s = strdup (compression_list[0]); if (s->hw->info.colorHalftone == SANE_FALSE) { s->opt[OPT_SCAN_MODE].size = max_string_size (scan_mode_min_list); s->opt[OPT_SCAN_MODE].constraint.string_list = scan_mode_min_list; } if (s->hw->info.comprG3_1D == SANE_FALSE || s->hw->info.comprG3_2D == SANE_FALSE || s->hw->info.comprG4 == SANE_FALSE) { s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE; } /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].name = ""; s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY_GROUP; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Autoborder: */ s->opt[OPT_AUTOBORDER].name = SANE_NAME_AUTOBORDER; s->opt[OPT_AUTOBORDER].title = SANE_TITLE_AUTOBORDER; s->opt[OPT_AUTOBORDER].desc = SANE_DESC_AUTOBORDER; s->opt[OPT_AUTOBORDER].type = SANE_TYPE_BOOL; s->opt[OPT_AUTOBORDER].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_AUTOBORDER].w = s->hw->info.autoborder_default; /* Paper Size */ s->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE; s->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE; s->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE; s->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING; s->opt[OPT_PAPER_SIZE].size = max_string_size (paper_list); s->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_PAPER_SIZE].constraint.string_list = paper_list; s->val[OPT_PAPER_SIZE].s = strdup (paper_list[0]); /* rotation */ s->opt[OPT_ROTATION].name = SANE_NAME_ROTATION; s->opt[OPT_ROTATION].title = SANE_TITLE_ROTATION; s->opt[OPT_ROTATION].desc = SANE_DESC_ROTATION; s->opt[OPT_ROTATION].type = SANE_TYPE_STRING; s->opt[OPT_ROTATION].size = max_string_size (rotation_list); s->opt[OPT_ROTATION].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_ROTATION].constraint.string_list = rotation_list; s->val[OPT_ROTATION].s = strdup (rotation_list[0]); /* Deskew: */ s->opt[OPT_DESKEW].name = SANE_NAME_DESKEW; s->opt[OPT_DESKEW].title = SANE_TITLE_DESKEW; s->opt[OPT_DESKEW].desc = SANE_DESC_DESKEW; s->opt[OPT_DESKEW].type = SANE_TYPE_BOOL; s->opt[OPT_DESKEW].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_DESKEW].w = s->hw->info.deskew_default; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &(s->hw->info.x_range); s->val[OPT_TL_X].w = SANE_FIX(0.0); /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &(s->hw->info.y_range); s->val[OPT_TL_Y].w = SANE_FIX(0.0); /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &(s->hw->info.x_range); s->val[OPT_BR_X].w = s->hw->info.x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &(s->hw->info.y_range); s->val[OPT_BR_Y].w = s->hw->info.y_range.max; if (s->hw->info.canBorderRecog == SANE_FALSE) { s->opt[OPT_AUTOBORDER].cap |= SANE_CAP_INACTIVE; } /* "Feeder" group: */ s->opt[OPT_FEEDER_GROUP].name = ""; s->opt[OPT_FEEDER_GROUP].title = SANE_TITLE_FEEDER_GROUP; s->opt[OPT_FEEDER_GROUP].desc = ""; s->opt[OPT_FEEDER_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_FEEDER_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_FEEDER_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan source */ s->opt[OPT_SCAN_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SCAN_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SCAN_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SCAN_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SCAN_SOURCE].size = max_string_size (scan_source_list); s->opt[OPT_SCAN_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SCAN_SOURCE].constraint.string_list = scan_source_list; s->val[OPT_SCAN_SOURCE].s = strdup (scan_source_list[0]); /* Batch: */ s->opt[OPT_BATCH].name = SANE_NAME_BATCH; s->opt[OPT_BATCH].title = SANE_TITLE_BATCH; s->opt[OPT_BATCH].desc = SANE_DESC_BATCH; s->opt[OPT_BATCH].type = SANE_TYPE_BOOL; s->opt[OPT_BATCH].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_BATCH].w = s->hw->info.batch_default; /* Check ADF: */ s->opt[OPT_CHECK_ADF].name = SANE_NAME_CHECK_ADF; s->opt[OPT_CHECK_ADF].title = SANE_TITLE_CHECK_ADF; s->opt[OPT_CHECK_ADF].desc = SANE_DESC_CHECK_ADF; s->opt[OPT_CHECK_ADF].type = SANE_TYPE_BOOL; s->opt[OPT_CHECK_ADF].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_CHECK_ADF].w = s->hw->info.check_adf_default; /* Duplex: */ s->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX; s->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX; s->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX; s->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL; s->opt[OPT_DUPLEX].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_DUPLEX].w = s->hw->info.duplex_default; /* timeout adf */ s->opt[OPT_TIMEOUT_ADF].name = SANE_NAME_TIMEOUT_ADF; s->opt[OPT_TIMEOUT_ADF].title = SANE_TITLE_TIMEOUT_ADF; s->opt[OPT_TIMEOUT_ADF].desc = SANE_DESC_TIMEOUT_ADF; s->opt[OPT_TIMEOUT_ADF].type = SANE_TYPE_INT; s->opt[OPT_TIMEOUT_ADF].unit = SANE_UNIT_NONE; s->opt[OPT_TIMEOUT_ADF].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TIMEOUT_ADF].constraint.range = &u8_range; s->val[OPT_TIMEOUT_ADF].w = s->hw->info.timeout_adf_default; /* timeout manual */ s->opt[OPT_TIMEOUT_MANUAL].name = SANE_NAME_TIMEOUT_MANUAL; s->opt[OPT_TIMEOUT_MANUAL].title = SANE_TITLE_TIMEOUT_MANUAL; s->opt[OPT_TIMEOUT_MANUAL].desc = SANE_DESC_TIMEOUT_MANUAL; s->opt[OPT_TIMEOUT_MANUAL].type = SANE_TYPE_INT; s->opt[OPT_TIMEOUT_MANUAL].unit = SANE_UNIT_NONE; s->opt[OPT_TIMEOUT_MANUAL].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TIMEOUT_MANUAL].constraint.range = &u8_range; s->val[OPT_TIMEOUT_MANUAL].w = s->hw->info.timeout_manual_default; if (s->hw->info.canCheckADF == SANE_FALSE) { s->opt[OPT_CHECK_ADF].cap |= SANE_CAP_INACTIVE; } if (s->hw->info.canDuplex == SANE_FALSE) { s->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE; } if (s->hw->info.canADF == SANE_FALSE) { s->opt[OPT_TIMEOUT_ADF].cap |= SANE_CAP_INACTIVE; } /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].name = ""; s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Control Panel: */ s->opt[OPT_CONTROL_PANEL].name = SANE_NAME_CONTROL_PANEL; s->opt[OPT_CONTROL_PANEL].title = SANE_TITLE_CONTROL_PANEL; s->opt[OPT_CONTROL_PANEL].desc = SANE_DESC_CONTROL_PANEL; s->opt[OPT_CONTROL_PANEL].type = SANE_TYPE_BOOL; s->opt[OPT_CONTROL_PANEL].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_CONTROL_PANEL].w = s->hw->info.control_panel_default; /* Ace_Function */ s->opt[OPT_ACE_FUNCTION].name = SANE_NAME_ACE_FUNCTION; s->opt[OPT_ACE_FUNCTION].title = SANE_TITLE_ACE_FUNCTION; s->opt[OPT_ACE_FUNCTION].desc = SANE_DESC_ACE_FUNCTION; s->opt[OPT_ACE_FUNCTION].type = SANE_TYPE_INT; s->opt[OPT_ACE_FUNCTION].unit = SANE_UNIT_NONE; s->opt[OPT_ACE_FUNCTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_ACE_FUNCTION].constraint.range = &ace_function_range; s->val[OPT_ACE_FUNCTION].w = 0; /* Ace_Sensitivity */ s->opt[OPT_ACE_SENSITIVITY].name = SANE_NAME_ACE_SENSITIVITY; s->opt[OPT_ACE_SENSITIVITY].title = SANE_TITLE_ACE_SENSITIVITY; s->opt[OPT_ACE_SENSITIVITY].desc = SANE_DESC_ACE_SENSITIVITY; s->opt[OPT_ACE_SENSITIVITY].type = SANE_TYPE_INT; s->opt[OPT_ACE_SENSITIVITY].unit = SANE_UNIT_NONE; s->opt[OPT_ACE_SENSITIVITY].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_ACE_SENSITIVITY].constraint.range = &ace_sensitivity_range; s->val[OPT_ACE_SENSITIVITY].w = 4; /* Brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range; s->val[OPT_BRIGHTNESS].w = 0; /* Threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &u8_range; s->val[OPT_THRESHOLD].w = 0; /* Contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &u8_range; s->val[OPT_CONTRAST].w = 0; /* Negative: */ s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; s->opt[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE; s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL; s->opt[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_NEGATIVE].w = SANE_FALSE; /* Contrast is not used in any case; why did we add it? */ s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; if (s->hw->info.control_panel_default == SANE_TRUE) { s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; } else if (s->hw->info.canACE == SANE_FALSE) { s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; } /* "ICON" group: */ s->opt[OPT_ICON_GROUP].name = ""; s->opt[OPT_ICON_GROUP].title = SANE_TITLE_ICON_GROUP; s->opt[OPT_ICON_GROUP].desc = ""; s->opt[OPT_ICON_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ICON_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_ICON_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Icon_Width */ s->opt[OPT_ICON_WIDTH].name = SANE_NAME_ICON_WIDTH; s->opt[OPT_ICON_WIDTH].title = SANE_TITLE_ICON_WIDTH; s->opt[OPT_ICON_WIDTH].desc = SANE_DESC_ICON_WIDTH; s->opt[OPT_ICON_WIDTH].type = SANE_TYPE_INT; s->opt[OPT_ICON_WIDTH].unit = SANE_UNIT_PIXEL; s->opt[OPT_ICON_WIDTH].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_ICON_WIDTH].constraint.range = &icon_range; s->val[OPT_ICON_WIDTH].w = 0; /* Icon_Length */ s->opt[OPT_ICON_LENGTH].name = SANE_NAME_ICON_LENGTH; s->opt[OPT_ICON_LENGTH].title = SANE_TITLE_ICON_LENGTH; s->opt[OPT_ICON_LENGTH].desc = SANE_DESC_ICON_LENGTH; s->opt[OPT_ICON_LENGTH].type = SANE_TYPE_INT; s->opt[OPT_ICON_LENGTH].unit = SANE_UNIT_PIXEL; s->opt[OPT_ICON_LENGTH].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_ICON_LENGTH].constraint.range = &icon_range; s->val[OPT_ICON_LENGTH].w = 0; if (s->hw->info.canIcon == SANE_FALSE) { s->opt[OPT_ICON_GROUP].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ICON_WIDTH].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ICON_LENGTH].cap |= SANE_CAP_INACTIVE; } /* "Barcode" group: */ s->opt[OPT_BARCODE_GROUP].name = ""; s->opt[OPT_BARCODE_GROUP].title = SANE_TITLE_BARCODE_GROUP; s->opt[OPT_BARCODE_GROUP].desc = ""; s->opt[OPT_BARCODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_BARCODE_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_BARCODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Add to barcode search priority. */ s->opt[OPT_BARCODE_SEARCH_BAR].name = SANE_NAME_BARCODE_SEARCH_BAR; s->opt[OPT_BARCODE_SEARCH_BAR].title = SANE_TITLE_BARCODE_SEARCH_BAR; s->opt[OPT_BARCODE_SEARCH_BAR].desc = SANE_DESC_BARCODE_SEARCH_BAR; s->opt[OPT_BARCODE_SEARCH_BAR].type = SANE_TYPE_STRING; s->opt[OPT_BARCODE_SEARCH_BAR].unit = SANE_UNIT_NONE; s->opt[OPT_BARCODE_SEARCH_BAR].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_BARCODE_SEARCH_BAR].constraint.string_list = barcode_search_bar_list; s->opt[OPT_BARCODE_SEARCH_BAR].size = max_string_size (barcode_search_bar_list); s->val[OPT_BARCODE_SEARCH_BAR].s = strdup (barcode_search_bar_list[0]); /* Barcode search count (1-7, default 1). */ s->opt[OPT_BARCODE_SEARCH_COUNT].name = SANE_NAME_BARCODE_SEARCH_COUNT; s->opt[OPT_BARCODE_SEARCH_COUNT].title = SANE_TITLE_BARCODE_SEARCH_COUNT; s->opt[OPT_BARCODE_SEARCH_COUNT].desc = SANE_DESC_BARCODE_SEARCH_COUNT; s->opt[OPT_BARCODE_SEARCH_COUNT].type = SANE_TYPE_INT; s->opt[OPT_BARCODE_SEARCH_COUNT].unit = SANE_UNIT_NONE; s->opt[OPT_BARCODE_SEARCH_COUNT].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BARCODE_SEARCH_COUNT].constraint.range = &barcode_search_count_range; s->val[OPT_BARCODE_SEARCH_COUNT].w = 3; /* Barcode search mode. horiz-vert, horizontal, vertical, vert-horiz */ s->opt[OPT_BARCODE_SEARCH_MODE].name = SANE_NAME_BARCODE_SEARCH_MODE; s->opt[OPT_BARCODE_SEARCH_MODE].title = SANE_TITLE_BARCODE_SEARCH_MODE; s->opt[OPT_BARCODE_SEARCH_MODE].desc = SANE_DESC_BARCODE_SEARCH_MODE; s->opt[OPT_BARCODE_SEARCH_MODE].type = SANE_TYPE_STRING; s->opt[OPT_BARCODE_SEARCH_MODE].size = max_string_size (barcode_search_mode_list); s->opt[OPT_BARCODE_SEARCH_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_BARCODE_SEARCH_MODE].constraint.string_list = barcode_search_mode_list; s->val[OPT_BARCODE_SEARCH_MODE].s = strdup(barcode_search_mode_list[0]); /* Patch code min height (def=5mm) */ s->opt[OPT_BARCODE_HMIN].name = SANE_NAME_BARCODE_HMIN; s->opt[OPT_BARCODE_HMIN].title = SANE_TITLE_BARCODE_HMIN; s->opt[OPT_BARCODE_HMIN].desc = SANE_DESC_BARCODE_HMIN; s->opt[OPT_BARCODE_HMIN].type = SANE_TYPE_INT; s->opt[OPT_BARCODE_HMIN].unit = SANE_UNIT_MM; s->opt[OPT_BARCODE_HMIN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BARCODE_HMIN].constraint.range = &barcode_hmin_range; s->val[OPT_BARCODE_HMIN].w = 5; /* Barcode search timeout in ms (20-65535,default is 10000). */ s->opt[OPT_BARCODE_SEARCH_TIMEOUT].name = SANE_NAME_BARCODE_SEARCH_TIMEOUT; s->opt[OPT_BARCODE_SEARCH_TIMEOUT].title = SANE_TITLE_BARCODE_SEARCH_TIMEOUT; s->opt[OPT_BARCODE_SEARCH_TIMEOUT].desc = SANE_DESC_BARCODE_SEARCH_TIMEOUT; s->opt[OPT_BARCODE_SEARCH_TIMEOUT].type = SANE_TYPE_INT; s->opt[OPT_BARCODE_SEARCH_TIMEOUT].unit = SANE_UNIT_MICROSECOND; s->opt[OPT_BARCODE_SEARCH_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BARCODE_SEARCH_TIMEOUT].constraint.range = &barcode_search_timeout_range; s->val[OPT_BARCODE_SEARCH_TIMEOUT].w = 10000; /* Specify image sections and functions */ s->opt[OPT_SECTION].name = SANE_NAME_SECTION; s->opt[OPT_SECTION].title = SANE_TITLE_SECTION; s->opt[OPT_SECTION].desc = SANE_DESC_SECTION; s->opt[OPT_SECTION].type = SANE_TYPE_STRING; s->opt[OPT_SECTION].unit = SANE_UNIT_NONE; s->opt[OPT_SECTION].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_SECTION].size = 255; s->val[OPT_SECTION].s = strdup (""); /* Barcode_Relmax */ s->opt[OPT_BARCODE_RELMAX].name = SANE_NAME_BARCODE_RELMAX; s->opt[OPT_BARCODE_RELMAX].title = SANE_TITLE_BARCODE_RELMAX; s->opt[OPT_BARCODE_RELMAX].desc = SANE_DESC_BARCODE_RELMAX; s->opt[OPT_BARCODE_RELMAX].type = SANE_TYPE_INT; s->opt[OPT_BARCODE_RELMAX].unit = SANE_UNIT_NONE; s->opt[OPT_BARCODE_RELMAX].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BARCODE_RELMAX].constraint.range = &u8_range; s->val[OPT_BARCODE_RELMAX].w = 0; /* Barcode_Barmin */ s->opt[OPT_BARCODE_BARMIN].name = SANE_NAME_BARCODE_BARMIN; s->opt[OPT_BARCODE_BARMIN].title = SANE_TITLE_BARCODE_BARMIN; s->opt[OPT_BARCODE_BARMIN].desc = SANE_DESC_BARCODE_BARMIN; s->opt[OPT_BARCODE_BARMIN].type = SANE_TYPE_INT; s->opt[OPT_BARCODE_BARMIN].unit = SANE_UNIT_NONE; s->opt[OPT_BARCODE_BARMIN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BARCODE_BARMIN].constraint.range = &u8_range; s->val[OPT_BARCODE_BARMIN].w = 0; /* Barcode_Barmax */ s->opt[OPT_BARCODE_BARMAX].name = SANE_NAME_BARCODE_BARMAX; s->opt[OPT_BARCODE_BARMAX].title = SANE_TITLE_BARCODE_BARMAX; s->opt[OPT_BARCODE_BARMAX].desc = SANE_DESC_BARCODE_BARMAX; s->opt[OPT_BARCODE_BARMAX].type = SANE_TYPE_INT; s->opt[OPT_BARCODE_BARMAX].unit = SANE_UNIT_NONE; s->opt[OPT_BARCODE_BARMAX].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BARCODE_BARMAX].constraint.range = &u8_range; s->val[OPT_BARCODE_BARMAX].w = 0; /* Barcode_Contrast */ s->opt[OPT_BARCODE_CONTRAST].name = SANE_NAME_BARCODE_CONTRAST; s->opt[OPT_BARCODE_CONTRAST].title = SANE_TITLE_BARCODE_CONTRAST; s->opt[OPT_BARCODE_CONTRAST].desc = SANE_DESC_BARCODE_CONTRAST; s->opt[OPT_BARCODE_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_BARCODE_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_BARCODE_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BARCODE_CONTRAST].constraint.range = &barcode_contrast_range; s->val[OPT_BARCODE_CONTRAST].w = 3; /* Barcode_Patchmode */ s->opt[OPT_BARCODE_PATCHMODE].name = SANE_NAME_BARCODE_PATCHMODE; s->opt[OPT_BARCODE_PATCHMODE].title = SANE_TITLE_BARCODE_PATCHMODE; s->opt[OPT_BARCODE_PATCHMODE].desc = SANE_DESC_BARCODE_PATCHMODE; s->opt[OPT_BARCODE_PATCHMODE].type = SANE_TYPE_INT; s->opt[OPT_BARCODE_PATCHMODE].unit = SANE_UNIT_NONE; s->opt[OPT_BARCODE_PATCHMODE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BARCODE_PATCHMODE].constraint.range = &barcode_patchmode_range; s->val[OPT_BARCODE_PATCHMODE].w = 0; if (s->hw->info.canSection == SANE_FALSE) { s->opt[OPT_SECTION].cap |= SANE_CAP_INACTIVE; } if (s->hw->info.canBarCode == SANE_FALSE) { s->opt[OPT_BARCODE_GROUP].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_SEARCH_BAR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_SEARCH_COUNT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_SEARCH_MODE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_HMIN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_SEARCH_TIMEOUT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_RELMAX].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_BARMIN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_BARMAX].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BARCODE_PATCHMODE].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; } static SANE_Status attach (const char *devnam, BH_Device ** devp) { SANE_Status status; BH_Device *dev; struct inquiry_standard_data ibuf; struct inquiry_vpd_data vbuf; struct inquiry_jis_data jbuf; size_t buf_size; int fd = -1; double mm; DBG (3, "attach called\n"); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } } #ifdef FAKE_INQUIRY if (fake_inquiry) { DBG (3, "attach: faking inquiry of %s\n", devnam); memset (&ibuf, 0, sizeof (ibuf)); ibuf.devtype = 6; memcpy(ibuf.vendor, "**FAKE**", 8); memcpy(ibuf.product, "COPISCAN II 6338", 16); memcpy(ibuf.revision, "0016", 4); DBG (1, "attach: reported devtype='%d', vendor='%.8s', " "product='%.16s', revision='%.4s'\n", ibuf.devtype, ibuf.vendor, ibuf.product, ibuf.revision); memset (&vbuf, 0, sizeof (vbuf)); memset (&jbuf, 0, sizeof (jbuf)); } else #endif { DBG (3, "attach: opening %s\n", devnam); status = sanei_scsi_open (devnam, &fd, sense_handler, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return status; } DBG (3, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } DBG (3, "attach: sending INQUIRY (standard data)\n"); memset (&ibuf, 0, sizeof (ibuf)); buf_size = sizeof(ibuf); status = inquiry (fd, &ibuf, &buf_size, 0, BH_INQUIRY_STANDARD_PAGE_CODE); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry (standard data) failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } DBG (1, "attach: reported devtype='%d', vendor='%.8s', " "product='%.16s', revision='%.4s'\n", ibuf.devtype, ibuf.vendor, ibuf.product, ibuf.revision); if (ibuf.devtype != 6 || strncmp ((char *)ibuf.vendor, "B&H SCSI", 8) != 0 || strncmp ((char *)ibuf.product, "COPISCAN ", 9) != 0) { DBG (1, "attach: device is not a recognized Bell and Howell scanner\n"); sanei_scsi_close (fd); return SANE_STATUS_INVAL; } DBG (3, "attach: sending INQUIRY (vpd data)\n"); memset (&vbuf, 0, sizeof (vbuf)); buf_size = sizeof(vbuf); status = inquiry (fd, &vbuf, &buf_size, 1, BH_INQUIRY_VPD_PAGE_CODE); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry (vpd data) failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } DBG (3, "attach: sending INQUIRY (jis data)\n"); memset (&jbuf, 0, sizeof (jbuf)); buf_size = sizeof(jbuf); status = inquiry (fd, &jbuf, &buf_size, 1, BH_INQUIRY_JIS_PAGE_CODE); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry (jis data) failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } sanei_scsi_close (fd); } dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (*dev)); dev->info.devtype = ibuf.devtype; sprintf(dev->info.vendor, "%.8s", ibuf.vendor); trim_spaces(dev->info.vendor, sizeof(dev->info.vendor)); sprintf(dev->info.product, "%.16s", ibuf.product); trim_spaces(dev->info.product, sizeof(dev->info.product)); sprintf(dev->info.revision, "%.4s", ibuf.revision); trim_spaces(dev->info.revision, sizeof(dev->info.revision)); dev->sane.name = strdup (devnam); dev->sane.vendor = strdup(dev->info.vendor); dev->sane.model = strdup(dev->info.product);; dev->sane.type = strdup(print_devtype(dev->info.devtype)); /* set capabilities from vpd */ dev->info.canADF = vbuf.adf & 0x01; dev->info.colorBandW = vbuf.imagecomposition & 0x01; dev->info.colorHalftone = vbuf.imagecomposition & 0x02; dev->info.canWhiteFrame = vbuf.imagedataprocessing[1] & 0x01; dev->info.canBlackFrame = vbuf.imagedataprocessing[1] & 0x02; dev->info.canEdgeExtract = vbuf.imagedataprocessing[1] & 0x04; dev->info.canNoiseFilter = vbuf.imagedataprocessing[1] & 0x08; dev->info.canSmooth = vbuf.imagedataprocessing[1] & 0x10; dev->info.canLineBold = vbuf.imagedataprocessing[1] & 0x20; dev->info.comprG3_1D = vbuf.compression & 0x01; dev->info.comprG3_2D = vbuf.compression & 0x02; dev->info.comprG4 = vbuf.compression & 0x04; dev->info.canBorderRecog = vbuf.sizerecognition & 0x01; dev->info.canBarCode = vbuf.optionalfeatures & 0x01; dev->info.canIcon = vbuf.optionalfeatures & 0x02; dev->info.canSection = vbuf.optionalfeatures & 0x04; dev->info.lineMaxBytes = _2btol(vbuf.xmaxoutputbytes); #ifdef FAKE_INQUIRY if (fake_inquiry) { dev->info.canADF = SANE_FALSE; dev->info.colorBandW = SANE_TRUE; dev->info.colorHalftone = SANE_TRUE; dev->info.canWhiteFrame = SANE_TRUE; dev->info.canBlackFrame = SANE_TRUE; dev->info.canEdgeExtract = SANE_TRUE; dev->info.canNoiseFilter = SANE_TRUE; dev->info.canSmooth = SANE_TRUE; dev->info.canLineBold = SANE_TRUE; dev->info.comprG3_1D = SANE_TRUE; dev->info.comprG3_2D = SANE_TRUE; dev->info.comprG4 = SANE_TRUE; dev->info.canBorderRecog = SANE_TRUE; dev->info.canBarCode = SANE_TRUE; dev->info.canIcon = SANE_TRUE; dev->info.canSection = SANE_TRUE; dev->info.lineMaxBytes = 450; } #endif /* set capabilities from jis */ dev->info.resBasicX = _2btol(jbuf.basicxres); dev->info.resBasicY = _2btol(jbuf.basicyres); dev->info.resMaxX = _2btol(jbuf.maxxres); dev->info.resMaxY = _2btol(jbuf.maxyres); dev->info.resMinX = _2btol(jbuf.minxres); dev->info.resMinY = _2btol(jbuf.minyres); /* set the length of the list to zero first, then append standard resolutions */ dev->info.resStdList[0] = 0; if (jbuf.standardres[0] & 0x80) appendStdList(&dev->info, 60); if (jbuf.standardres[0] & 0x40) appendStdList(&dev->info, 75); if (jbuf.standardres[0] & 0x20) appendStdList(&dev->info, 100); if (jbuf.standardres[0] & 0x10) appendStdList(&dev->info, 120); if (jbuf.standardres[0] & 0x08) appendStdList(&dev->info, 150); if (jbuf.standardres[0] & 0x04) appendStdList(&dev->info, 160); if (jbuf.standardres[0] & 0x02) appendStdList(&dev->info, 180); if (jbuf.standardres[0] & 0x01) appendStdList(&dev->info, 200); if (jbuf.standardres[1] & 0x80) appendStdList(&dev->info, 240); if (jbuf.standardres[1] & 0x40) appendStdList(&dev->info, 300); if (jbuf.standardres[1] & 0x20) appendStdList(&dev->info, 320); if (jbuf.standardres[1] & 0x10) appendStdList(&dev->info, 400); if (jbuf.standardres[1] & 0x08) appendStdList(&dev->info, 480); if (jbuf.standardres[1] & 0x04) appendStdList(&dev->info, 600); if (jbuf.standardres[1] & 0x02) appendStdList(&dev->info, 800); if (jbuf.standardres[1] & 0x01) appendStdList(&dev->info, 1200); if (dev->info.resStdList[0] == 0) { /* make a default standard resolutions for 200 and 300dpi */ DBG(1, "attach: no standard resolutions reported\n"); dev->info.resStdList[0] = 2; dev->info.resStdList[1] = 200; dev->info.resStdList[2] = 300; dev->info.resBasicX = dev->info.resBasicY = 300; } dev->info.winWidth = _4btol(jbuf.windowwidth); dev->info.winHeight = _4btol(jbuf.windowlength); if (dev->info.winWidth <= 0) { dev->info.winWidth = (SANE_Int) (dev->info.resBasicX * 8.5); DBG(1, "attach: invalid window width reported, using %d\n", dev->info.winWidth); } if (dev->info.winHeight <= 0) { dev->info.winHeight = dev->info.resBasicY * 14; DBG(1, "attach: invalid window height reported, using %d\n", dev->info.winHeight); } mm = (dev->info.resBasicX > 0) ? ((double) dev->info.winWidth / (double) dev->info.resBasicX * MM_PER_INCH) : 0.0; dev->info.x_range.min = SANE_FIX(0.0); dev->info.x_range.max = SANE_FIX(mm); dev->info.x_range.quant = SANE_FIX(0.0); mm = (dev->info.resBasicY > 0) ? ((double) dev->info.winHeight / (double) dev->info.resBasicY * MM_PER_INCH) : 0.0; dev->info.y_range.min = SANE_FIX(0.0); dev->info.y_range.max = SANE_FIX(mm); dev->info.y_range.quant = SANE_FIX(0.0); /* set additional discovered/guessed capabilities */ /* if all of the ACE capabilities are present, declare it ACE capable */ dev->info.canACE = dev->info.canEdgeExtract && dev->info.canNoiseFilter && dev->info.canSmooth && dev->info.canLineBold; /* if the model is known to be a duplex, declare it duplex capable */ if (strcmp(dev->info.product, "COPISCAN II 6338") == 0) { dev->info.canDuplex = SANE_TRUE; } else { dev->info.canDuplex = SANE_FALSE; } /* the paper sensor requires RSC revision 1.4 or higher and an * installed feeder. NOTE: It also requires SW-4 on and the * AccufeedPlus feeder, but we cannot discover that. */ if (strcmp(dev->info.revision, "0014") >= 0) { dev->info.canCheckADF = dev->info.canADF; } else { dev->info.canCheckADF = SANE_FALSE; } /* set option defaults based on inquiry information */ dev->info.res_default = dev->info.resBasicX; dev->info.autoborder_default = dev->info.canBorderRecog; dev->info.batch_default = SANE_FALSE; dev->info.deskew_default = SANE_FALSE; dev->info.check_adf_default = SANE_FALSE; dev->info.duplex_default = SANE_FALSE; dev->info.timeout_adf_default = 0; dev->info.timeout_manual_default = 0; dev->info.control_panel_default = dev->info.canACE; ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static SANE_Status attach_one(const char *devnam) { attach (devnam, NULL); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) { char devnam[PATH_MAX] = "/dev/scanner"; FILE *fp; authorize = authorize; /* get rid of compiler warning */ DBG_INIT(); DBG(3, "sane_init called\n"); DBG(1, "Bell+Howell SANE backend %d.%d build %d %s endian\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, _is_host_little_endian() ? "little" : "big"); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); fp = sanei_config_open(BH_CONFIG_FILE); if (fp) { char line[PATH_MAX]; const char *lp; size_t len; /* read config file */ while (sanei_config_read (line, sizeof (line), fp)) { if (line[0] == '#') /* ignore line comments */ continue; len = strlen (line); if (!len) continue; /* ignore empty lines */ lp = sanei_config_skip_whitespace (line); DBG(16, "sane_init: processing config file line '%s'\n", line); if (strncmp(lp, "option", 6) == 0 && (isspace (lp[6]) || lp[6] == '\0')) { lp += 6; lp = sanei_config_skip_whitespace (lp); if (strncmp(lp, "disable-optional-frames", 23) == 0) { DBG(1, "sane_init: configuration option " "'disable-optional-frames' set\n"); disable_optional_frames = 1; } else if (strncmp(lp, "fake-inquiry", 12) == 0) { DBG(1, "sane_init: configuration option " "'fake-inquiry' set\n"); fake_inquiry = 1; } else { DBG(1, "sane_init: ignoring unknown " "configuration option '%s'\n", lp); } } else { DBG(16, "sane_init: found a device: line '%s'\n", lp); strncpy (devnam, lp, sizeof(devnam)); devnam[sizeof(devnam)-1] = '\0'; sanei_config_attach_matching_devices(devnam, attach_one); } } fclose (fp); } else { /* configure the /dev/scanner device in the absence of config file */ sanei_config_attach_matching_devices ("/dev/scanner", attach_one); } return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device ***device_list, SANE_Bool local) { BH_Device *dev; int i; DBG(3, "sane_get_devices called\n"); local = local; /* get rid of compiler warning */ if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devnam, SANE_Handle *handle) { SANE_Status status; BH_Device *dev; BH_Scanner *s; DBG(3, "sane_open called\n"); if (devnam[0] != '\0') { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) break; } if (!dev) { status = attach (devnam, &dev); if (status != SANE_STATUS_GOOD) return status; } } else { dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->hw = dev; s->bmu = BH_UNIT_POINT; s->mud = 1; ScannerDump(s); init_options (s); s->next = first_handle; first_handle = s; /* initialize our parameters */ get_parameters(s, 0); *handle = s; #ifdef FAKE_INQUIRY if (fake_inquiry) { DBG (1, "sane_open: faking open of %s\n", s->hw->sane.name); } else #endif { status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return status; } } return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { BH_Scanner *s = handle; DBG(3, "sane_get_option_descriptor called (option:%d)\n", option); if ((unsigned) option >= NUM_OPTIONS) return 0; return (s->opt + option); } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Word *info) { BH_Scanner *s = handle; SANE_Status status; SANE_Word cap; SANE_String_Const name; DBG(3, "sane_control_option called\n"); name = s->opt[option].name ? s->opt[option].name : "(nil)"; if (info) *info = 0; if (s->scanning && action == SANE_ACTION_SET_VALUE) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { DBG(16, "sane_control_option: get_value %s [#%d]\n", name, option); switch (option) { /* word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_TIMEOUT_ADF: case OPT_TIMEOUT_MANUAL: case OPT_ACE_FUNCTION: case OPT_ACE_SENSITIVITY: case OPT_BRIGHTNESS: case OPT_THRESHOLD: case OPT_CONTRAST: case OPT_ICON_WIDTH: case OPT_ICON_LENGTH: case OPT_BARCODE_SEARCH_COUNT: case OPT_BARCODE_HMIN: case OPT_BARCODE_SEARCH_TIMEOUT: case OPT_BARCODE_RELMAX: case OPT_BARCODE_BARMIN: case OPT_BARCODE_BARMAX: case OPT_BARCODE_CONTRAST: case OPT_BARCODE_PATCHMODE: case OPT_NUM_OPTS: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; /* string options: */ case OPT_INQUIRY: case OPT_SCAN_SOURCE: case OPT_SCAN_MODE: case OPT_COMPRESSION: case OPT_PAPER_SIZE: case OPT_ROTATION: case OPT_BARCODE_SEARCH_BAR: case OPT_BARCODE_SEARCH_MODE: case OPT_SECTION: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; /* boolean options: */ case OPT_PREVIEW: case OPT_AUTOBORDER: case OPT_DESKEW: case OPT_BATCH: case OPT_CHECK_ADF: case OPT_DUPLEX: case OPT_CONTROL_PANEL: case OPT_NEGATIVE: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; default: DBG(1, "sane_control_option:invalid option number %d\n", option); return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { switch (s->opt[option].type) { case SANE_TYPE_BOOL: case SANE_TYPE_INT: DBG(16, "sane_control_option: set_value %s [#%d] to %d\n", name, option, *(SANE_Word *) val); break; case SANE_TYPE_FIXED: DBG(16, "sane_control_option: set_value %s [#%d] to %f\n", name, option, SANE_UNFIX(*(SANE_Word *) val)); break; case SANE_TYPE_STRING: DBG(16, "sane_control_option: set_value %s [#%d] to %s\n", name, option, (char *) val); break; default: DBG(16, "sane_control_option: set_value %s [#%d]\n", name, option); } if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: /* make sure that paper-size is set to custom */ if (s->val[option].w != *(SANE_Word *) val) { if (info) *info |= SANE_INFO_RELOAD_PARAMS; if (get_paper_id(_OPT_VAL_STRING(s, OPT_PAPER_SIZE)) != 0) { if (info) *info |= SANE_INFO_RELOAD_OPTIONS; /* set paper size to 'custom' */ free (s->val[OPT_PAPER_SIZE].s); s->val[OPT_PAPER_SIZE].s = strdup(paper_list[0]); } } /* fall through */ case OPT_RESOLUTION: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_TIMEOUT_ADF: case OPT_TIMEOUT_MANUAL: case OPT_ACE_FUNCTION: case OPT_ACE_SENSITIVITY: case OPT_BRIGHTNESS: case OPT_THRESHOLD: case OPT_CONTRAST: case OPT_ICON_WIDTH: case OPT_ICON_LENGTH: case OPT_BARCODE_SEARCH_COUNT: case OPT_BARCODE_HMIN: case OPT_BARCODE_SEARCH_TIMEOUT: case OPT_BARCODE_RELMAX: case OPT_BARCODE_BARMIN: case OPT_BARCODE_BARMAX: case OPT_BARCODE_CONTRAST: case OPT_BARCODE_PATCHMODE: case OPT_NUM_OPTS: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* string options */ case OPT_BARCODE_SEARCH_BAR: /*!!! we're supporting only a single barcode type via the option */ s->search_bars[0] = get_barcode_id(val); /* fall through */ case OPT_SCAN_SOURCE: case OPT_COMPRESSION: case OPT_ROTATION: case OPT_BARCODE_SEARCH_MODE: case OPT_SECTION: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return SANE_STATUS_GOOD; /* boolean options: */ case OPT_AUTOBORDER: /*!!! autoborder true disables geometry controls * and sets them to defaults? */ /* fall through */ case OPT_PREVIEW: case OPT_BATCH: case OPT_DESKEW: case OPT_CHECK_ADF: case OPT_DUPLEX: case OPT_NEGATIVE: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* options with side effects */ case OPT_CONTROL_PANEL: /* a boolean option */ /* control-panel true enables/disables some enhancement controls */ if (s->val[option].w != *(SANE_Word *) val) { if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[option].w = *(SANE_Word *) val; if (*(SANE_Word *) val == SANE_TRUE) { if (s->hw->info.canACE == SANE_TRUE) { s->opt[OPT_ACE_FUNCTION].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ACE_SENSITIVITY].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; } } else { if (s->hw->info.canACE == SANE_TRUE) { s->opt[OPT_ACE_FUNCTION].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_ACE_SENSITIVITY].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } } } return SANE_STATUS_GOOD; case OPT_SCAN_MODE: /* a string option */ /* scan mode != lineart disables compression, setting it to * 'none' */ if (strcmp (s->val[option].s, (SANE_String) val)) { if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (get_scan_mode_id((SANE_String) val) != 0) { /* scan mode is not lineart, disable compression * and set compression to 'none' */ s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE; if (s->val[OPT_COMPRESSION].s && get_compression_id(s->val[OPT_COMPRESSION].s) != 0) { free (s->val[OPT_COMPRESSION].s); s->val[OPT_COMPRESSION].s = strdup(compression_list[0]); } } else { /* scan mode is lineart, enable compression */ s->opt[OPT_COMPRESSION].cap &= ~SANE_CAP_INACTIVE; } free (s->val[option].s); s->val[option].s = strdup (val); } return SANE_STATUS_GOOD; case OPT_PAPER_SIZE: /* a string option */ /* changes geometry options, therefore _RELOAD_PARAMS and _RELOAD_OPTIONS */ if (strcmp (s->val[option].s, (SANE_String) val)) { SANE_Int paper_id = get_paper_id((SANE_String) val); /* paper_id 0 is a special case (custom) that * disables the paper size control of geometry */ if (paper_id != 0) { double left, x_max, y_max, x, y; x_max = SANE_UNFIX(s->hw->info.x_range.max); y_max = SANE_UNFIX(s->hw->info.y_range.max); /* a dimension of 0.0 (or less) is replaced with the max value */ x = (paper_sizes[paper_id].width <= 0.0) ? x_max : paper_sizes[paper_id].width; y = (paper_sizes[paper_id].length <= 0.0) ? y_max : paper_sizes[paper_id].length; if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; /* set geometry options based on paper size */ /* set geometry options based on paper size */ if (s->hw->info.canADF) { /* when the feeder is used the paper is centered in the * hopper; with the manual feed it is aligned left. */ left = (x_max - x) / 2.0; if (left < 0.0) left = 0.0; } else { left = 0.0; } s->val[OPT_TL_X].w = SANE_FIX(left); s->val[OPT_TL_Y].w = SANE_FIX(0.0); s->val[OPT_BR_X].w = SANE_FIX(MIN(x + left, x_max)); s->val[OPT_BR_Y].w = SANE_FIX(MIN(y, y_max)); } free (s->val[option].s); s->val[option].s = strdup (val); } return SANE_STATUS_GOOD; default: DBG(1, "sane_control_option:invalid option number %d\n", option); return SANE_STATUS_INVAL; } } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) { BH_Scanner *s = handle; SANE_Int status = SANE_STATUS_GOOD; DBG(3, "sane_get_parameters called\n"); if (params) { SANE_Int res; if (!s->scanning) { /* update our parameters ONLY if we're not scanning */ status = get_parameters(s, 0); } *params = s->params; res = _OPT_VAL_WORD(s, OPT_RESOLUTION); DBG (1, "get_parameters: format=%d, pixels/line=%d, bytes/line=%d, " "lines=%d, dpi=%d\n", (int) s->params.format, s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, res); } return status; } SANE_Status sane_start (SANE_Handle handle) { BH_Scanner *s = handle; SANE_Status status; DBG(3, "sane_start called\n"); s->cancelled = SANE_FALSE; if (s->scanning == SANE_FALSE) { /* get preliminary parameters */ status = get_parameters (s, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: get_parameters failed: %s\n", sane_strstatus (status)); return status; } /* Do the setup once per 'batch'. The SANE standard requires the * frontend to call sane_cancel once all desired frames have been * acquired. That is when scanning is set back to SANE_FALSE and * the 'batch' is considered done. */ status = start_setup (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: start_setup failed: %s\n", sane_strstatus (status)); return status; } } status = start_scan (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: start_scan failed: %s\n", sane_strstatus (status)); return status; } return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len) { BH_Scanner *s = handle; SANE_Status status; size_t nread; DBG(3, "sane_read called\n"); *len = 0; if (s->cancelled) { DBG (3, "sane_read: cancelled!\n"); return SANE_STATUS_CANCELLED; } if (!s->scanning) { DBG (3, "sane_read: scanning is false!\n"); sane_cancel(s); return SANE_STATUS_CANCELLED; } nread = maxlen; DBG (3, "sane_read: request %lu bytes\n", (u_long) nread); /* set InvalidBytes to 0 before read; sense_handler will set it * to non-zero if we do the last partial read. */ s->InvalidBytes = 0; status = read_data (s, buf, &nread); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_read: read_data failed %s\n", sane_strstatus(status)); sane_cancel (s); return status; } nread = maxlen - s->InvalidBytes; DBG (3, "sane_read: got %lu bytes\n", (u_long) nread); *len = nread; return (maxlen != 0 && nread == 0) ? SANE_STATUS_EOF : SANE_STATUS_GOOD; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { #ifdef NONBLOCKSUPPORTED BH_Scanner *s = handle; #endif DBG(3, "sane_set_io_mode called: non_blocking=%d\n", non_blocking); #ifdef NONBLOCKSUPPORTED if (s->fd < 0) { return SANE_STATUS_INVAL; } if (fcntl (s->fd, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { DBG(1, "sane_set_io_mode: error setting io mode\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; #else handle = handle; /* get rid of compiler warning */ return (non_blocking == 1) ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD; #endif } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int *fd) { #ifdef NONBLOCKSUPPORTED BH_Scanner *s = handle; #endif DBG(3, "sane_get_select_fd called\n"); #ifdef NONBLOCKSUPPORTED if (s->fd < 0) { return SANE_STATUS_INVAL; } *fd = s->fd; return SANE_STATUS_GOOD; #else handle = handle; fd = fd; /* get rid of compiler warning */ return SANE_STATUS_UNSUPPORTED; #endif } void sane_cancel (SANE_Handle handle) { BH_Scanner *s = (BH_Scanner *) handle; DBG(3, "sane_cancel called\n"); if (s->scanning) { /* if batchmode is enabled, then call set_window to * abort the batch */ if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE) { DBG(5, "sane_cancel: calling set_window to abort batch\n"); set_window(s, BH_BATCH_ABORT); } } s->scanning = SANE_FALSE; s->cancelled = SANE_TRUE; } void sane_close (SANE_Handle handle) { BH_Scanner *s = (BH_Scanner *) handle; DBG(3, "sane_close called\n"); if (s->fd != -1) sanei_scsi_close (s->fd); s->fd = -1; free (s); } void sane_exit (void) { BH_Device *dev, *next; DBG(3, "sane_exit called\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free (dev); } if (devlist) free (devlist); } sane-backends-1.0.27/backend/epsonds-io.c0000664000175000017500000001002413106201017015021 00000000000000/* * epsonds-io.c - Epson ESC/I-2 driver, low level I/O. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #include #include /* sleep */ #ifdef HAVE_SYS_TYPES_H #include #endif #include "epsonds.h" #include "epsonds-io.h" #include "epsonds-net.h" #ifdef HAVE_SYS_TYPES_H #include #endif size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status, size_t reply_len) { DBG(32, "%s: size = %lu\n", __func__, (u_long) length); if (length == 2) { char *cmd = buf; switch (cmd[0]) { case FS: DBG(9, "%s: FS %c\n", __func__, cmd[1]); break; } } if (s->hw->connection == SANE_EPSONDS_NET) { return epsonds_net_write(s, 0x2000, buf, length, reply_len, status); } else if (s->hw->connection == SANE_EPSONDS_USB) { size_t n = length; *status = sanei_usb_write_bulk(s->fd, buf, &n); return n; } /* never reached */ *status = SANE_STATUS_INVAL; return 0; } size_t eds_recv(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status) { size_t n = length; /* network interface needs to read header back even data is 0.*/ DBG(30, "%s: size = %ld, buf = %p\n", __func__, (long) length, buf); *status = SANE_STATUS_GOOD; if (s->hw->connection == SANE_EPSONDS_NET) { n = epsonds_net_read(s, buf, length, status); } else if (s->hw->connection == SANE_EPSONDS_USB) { /* !!! only report an error if we don't read anything */ if (n) { *status = sanei_usb_read_bulk(s->fd, (SANE_Byte *)buf, (size_t *) &n); if (n > 0) *status = SANE_STATUS_GOOD; } } if (n < length) { DBG(1, "%s: expected = %lu, got = %ld, canceling: %d\n", __func__, (u_long)length, (long)n, s->canceling); *status = SANE_STATUS_IO_ERROR; } return n; } /* Simple function to exchange a fixed amount of data with the scanner */ SANE_Status eds_txrx(epsonds_scanner* s, char *txbuf, size_t txlen, char *rxbuf, size_t rxlen) { SANE_Status status; size_t done; done = eds_send(s, txbuf, txlen, &status, rxlen); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status)); return status; } if (done != txlen) { DBG(1, "%s: tx err, short write\n", __func__); return SANE_STATUS_IO_ERROR; } done = eds_recv(s, rxbuf, rxlen, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status)); } return status; } /* This function should be used to send codes that only requires the scanner * to give back an ACK or a NAK, namely FS X or FS Y */ SANE_Status eds_control(epsonds_scanner *s, void *buf, size_t buf_size) { char result; SANE_Status status; DBG(12, "%s: size = %lu\n", __func__, (u_long) buf_size); status = eds_txrx(s, buf, buf_size, &result, 1); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: failed, %s\n", __func__, sane_strstatus(status)); return status; } if (result == ACK) return SANE_STATUS_GOOD; if (result == NAK) { DBG(3, "%s: NAK\n", __func__); return SANE_STATUS_INVAL; } DBG(1, "%s: result is neither ACK nor NAK but 0x%02x\n", __func__, result); return SANE_STATUS_INVAL; } SANE_Status eds_fsy(epsonds_scanner *s) { return eds_control(s, "\x1CY", 2); } SANE_Status eds_fsx(epsonds_scanner *s) { // SANE_Status status = eds_control(s, "\x1CZ", 2); SANE_Status status = eds_control(s, "\x1CX", 2); if (status == SANE_STATUS_GOOD) { s->locked = 1; } return status; } SANE_Status eds_lock(epsonds_scanner *s) { SANE_Status status; DBG(5, "%s\n", __func__); if (s->hw->connection == SANE_EPSONDS_USB) { sanei_usb_set_timeout(USB_SHORT_TIMEOUT); } status = eds_fsx(s); if (s->hw->connection == SANE_EPSONDS_USB) { sanei_usb_set_timeout(USB_TIMEOUT); } return status; } sane-backends-1.0.27/backend/hp-option.c0000664000175000017500000036201412775312261014706 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ /* $Log$ Revision 1.13 2005/04/13 12:50:07 ellert-guest Add missing SANE_I18N, Regenerate .po files accordingly, Update Swedish translations Revision 1.12 2003/10/09 19:32:50 kig-guest Bug #300241: fix invers image on 3c/4c/6100C at 10 bit depth */ /* pwd.h not available ? */ #if (defined(__IBMC__) || defined(__IBMCPP__)) #ifndef _AIX # define SANE_HOME_HP "SANE_HOME_HP" #endif #endif /* To be done: dont reallocate choice accessors */ /* #define HP_ALLOC_CHOICEACC_ONCE 1 */ /* #define HP_EXPERIMENTAL */ /* #define STUBS extern int sanei_debug_hp; */ #define DEBUG_DECLARE_ONLY #include "../include/sane/config.h" #include "../include/sane/sanei_backend.h" #include "../include/lalloca.h" #include #include #include "../include/lassert.h" #ifndef SANE_HOME_HP #include #endif #include #include #include #include #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "hp.h" #include "hp-option.h" #include "hp-accessor.h" #include "hp-scsi.h" #include "hp-scl.h" #include "hp-device.h" /* FIXME: descriptors should be static? */ typedef SANE_Option_Descriptor * _HpSaneOption; typedef struct hp_option_descriptor_s * _HpOptionDescriptor; typedef struct hp_option_s * _HpOption; typedef struct hp_data_info_s * HpDataInfo; typedef struct hp_data_info_s * _HpDataInfo; typedef HpAccessor HpAccessorOptd; static hp_bool_t hp_optset_isEnabled (HpOptSet this, HpData data, const char *name, const HpDeviceInfo *info); static HpOption hp_optset_get (HpOptSet this, HpOptionDescriptor optd); static HpOption hp_optset_getByName (HpOptSet this, const char * name); static SANE_Status hp_download_calib_file (HpScsi scsi); static SANE_Status hp_probe_parameter_support_table (enum hp_device_compat_e compat, HpScl scl, int value); #define HP_EOL -9999 /* Don't need requiries for commands that are probed */ #define HP_PROBE_SCL_COMMAND 1 /* Scale factor for vectors (gtk seems not to like vectors/curves * in y-range 0.0,...,1.0) */ #define HP_VECTOR_SCALE (256.0) /* * */ struct hp_option_s { HpOptionDescriptor descriptor; HpAccessorOptd optd_acsr; HpAccessor data_acsr; void * extra; }; struct hp_option_descriptor_s { const char * name; const char * title; const char * desc; SANE_Value_Type type; SANE_Unit unit; SANE_Int cap; enum hp_device_compat_e requires; /* model dependent support flags */ /* probe for option support */ SANE_Status (*probe) (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data); SANE_Status (*program) (HpOption this, HpScsi scsi, HpOptSet optset, HpData data); hp_bool_t (*enable) (HpOption this, HpOptSet optset, HpData data, const HpDeviceInfo *info); hp_bool_t has_global_effect; hp_bool_t affects_scan_params; hp_bool_t program_immediate; hp_bool_t suppress_for_scan; hp_bool_t may_change; /* This stuff should really be in a subclasses: */ HpScl scl_command; int minval, maxval, startval; /* for simulation */ HpChoice choices; }; struct hp_data_info_s { HpScl scl; }; static const struct hp_option_descriptor_s NUM_OPTIONS[1], PREVIEW_MODE[1], SCAN_MODE[1], SCAN_RESOLUTION[1], CUSTOM_GAMMA[1], GAMMA_VECTOR_8x8[1], #ifdef ENABLE_7x12_TONEMAPS GAMMA_VECTOR_7x12[1], RGB_TONEMAP[1], GAMMA_VECTOR_R[1], GAMMA_VECTOR_G[1], GAMMA_VECTOR_B[1], #endif HALFTONE_PATTERN[1], MEDIA[1], OUT8[1], BIT_DEPTH[1], SCAN_SOURCE[1], #ifdef FAKE_COLORSEP_MATRIXES SEPMATRIX[1], #endif MATRIX_TYPE[1]; /* Check if a certain scanner model supports a command with a given parameter * value. The function returns SANE_STATUS_GOOD if the command and the * value is found in the support table of that scanner. * It returns SANE_STATUS_UNSUPPORTED if the command is found in the support * table of that scanner, but the value is not included in the table. * It returns SANE_STATUS_EOF if there is no information about that command * and that scanner in the support table. */ static SANE_Status hp_probe_parameter_support_table (enum hp_device_compat_e compat, HpScl scl, int value) {int k, j; char *eptr; static int photosmart_output_type[] = /* HP Photosmart: only b/w, gray, color is supported */ { HP_COMPAT_PS, SCL_OUTPUT_DATA_TYPE, 0, 4, 5, HP_EOL }; static int *support_table[] = { photosmart_output_type }; eptr = getenv ("SANE_HP_CHK_TABLE"); if ((eptr != NULL) && (*eptr == '0')) return SANE_STATUS_EOF; for (k = 0; k < (int)(sizeof (support_table)/sizeof (support_table[0])); k++) { if ((scl == support_table[k][1]) && (support_table[k][0] & compat)) { for (j = 2; support_table[k][j] != HP_EOL; j++) if (support_table[k][j] == value) return SANE_STATUS_GOOD; return SANE_STATUS_UNSUPPORTED; } } return SANE_STATUS_EOF; } /* * class HpChoice */ typedef struct hp_choice_s * _HpChoice; static hp_bool_t hp_choice_isSupported (HpChoice choice, int minval, int maxval) { return ( choice->is_emulated || ( choice->val >= minval && choice->val <= maxval ) ); } static hp_bool_t hp_probed_choice_isSupported (HpScsi scsi, HpScl scl, HpChoice choice, int minval, int maxval) { hp_bool_t isSupported; SANE_Status status; enum hp_device_compat_e compat; if ( choice->is_emulated ) { DBG(3, "probed_choice: value %d is emulated\n", choice->val); return ( 1 ); } if ( choice->val < minval || choice->val > maxval ) { DBG(3, "probed_choice: value %d out of range (%d,%d)\n", choice->val, minval, maxval); return ( 0 ); } if (sanei_hp_device_probe (&compat, scsi) != SANE_STATUS_GOOD) { DBG(1, "probed_choice: Could not get compatibilities for scanner\n"); return ( 0 ); } status = hp_probe_parameter_support_table (compat, scl, choice->val); if (status == SANE_STATUS_GOOD) { DBG(3, "probed_choice: command/value found in support table\n"); return ( 1 ); } else if (status == SANE_STATUS_UNSUPPORTED) { DBG(3, "probed_choice: command found in support table, but value n.s.\n"); return ( 0 ); } /* Not in the support table. Try to inquire */ /* Fix me: It seems that the scanner does not raise a parameter error */ /* after specifiying an unsupported command-value. */ sanei_hp_scl_clearErrors (scsi); sanei_hp_scl_set (scsi, scl, choice->val); isSupported = ( sanei_hp_scl_errcheck (scsi) == SANE_STATUS_GOOD ); DBG(3, "probed_choice: value %d %s\n", choice->val, isSupported ? "supported" : "not supported"); return isSupported; } hp_bool_t sanei_hp_choice_isEnabled (HpChoice this, HpOptSet optset, HpData data, const HpDeviceInfo *info) { if (!this->enable) return 1; return (*this->enable)(this, optset, data, info); } static hp_bool_t _cenable_incolor (HpChoice __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) { return sanei_hp_optset_scanmode(optset, data) == HP_SCANMODE_COLOR; } static hp_bool_t _cenable_notcolor (HpChoice __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) { return sanei_hp_optset_scanmode(optset, data) != HP_SCANMODE_COLOR; } /* * class HpAccessorOptd */ static HpAccessorOptd hp_accessor_optd_new (HpData data) { return sanei_hp_accessor_new(data, sizeof(SANE_Option_Descriptor)); } static _HpSaneOption hp_accessor_optd_data (HpAccessorOptd this, HpData data) { return sanei__hp_accessor_data(this, data); } /* * class OptionDescriptor */ static SANE_Status hp_option_descriptor_probe (HpOptionDescriptor desc, HpScsi scsi, HpOptSet optset, HpData data, HpOption * newoptp) { _HpOption new; SANE_Status status; _HpSaneOption optd; new = sanei_hp_alloc(sizeof(*new)); new->descriptor = desc; if (!(new->optd_acsr = hp_accessor_optd_new(data))) return SANE_STATUS_NO_MEM; new->data_acsr = 0; optd = hp_accessor_optd_data(new->optd_acsr, data); memset(optd, 0, sizeof(*optd)); optd->name = desc->name; optd->title = desc->title; optd->desc = desc->desc; optd->type = desc->type; optd->unit = desc->unit; optd->cap = desc->cap; /* * Probe function will set optd->size, optd->constraint_type, * and optd->constraint. * and also new->accessor * and possibly new->extra */ if (desc->probe) { if (FAILED( status = (*desc->probe)(new, scsi, optset, data) )) { /* hp_accessor_optd_destoy(new->optd_acsr) */ sanei_hp_free(new); return status; } } *newoptp = new; return SANE_STATUS_GOOD; } /* * class Option */ static HpSaneOption hp_option_saneoption (HpOption this, HpData data) { return hp_accessor_optd_data(this->optd_acsr, data); } static _HpSaneOption _hp_option_saneoption (HpOption this, HpData data) { return hp_accessor_optd_data(this->optd_acsr, data); } static SANE_Status hp_option_download (HpOption this, HpData data, HpOptSet optset, HpScsi scsi) { HpScl scl = this->descriptor->scl_command; int value; if (IS_SCL_CONTROL(scl)) { value = sanei_hp_accessor_getint(this->data_acsr, data); if ( (scl == SCL_DATA_WIDTH) && (sanei_hp_optset_scanmode (optset, data) == HP_SCANMODE_COLOR) ) { value *= 3; } return sanei_hp_scl_set(scsi, scl, value); } else if (IS_SCL_DATA_TYPE(scl)) return sanei_hp_scl_download(scsi, scl, sanei_hp_accessor_data(this->data_acsr, data), sanei_hp_accessor_size(this->data_acsr)); assert(!scl); return SANE_STATUS_INVAL; } static SANE_Status hp_option_upload (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { HpScl scl = this->descriptor->scl_command; int val; if (IS_SCL_CONTROL(scl)) { RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, &val, 0, 0) ); if ( (scl == SCL_DATA_WIDTH) && (sanei_hp_optset_scanmode (optset, data) == HP_SCANMODE_COLOR) ) { val /= 3; } sanei_hp_accessor_setint(this->data_acsr, data, val); return SANE_STATUS_GOOD; } else if (IS_SCL_DATA_TYPE(scl)) return sanei_hp_scl_upload(scsi, scl, sanei__hp_accessor_data(this->data_acsr, data), sanei_hp_accessor_size(this->data_acsr)); assert(!scl); return SANE_STATUS_INVAL; } static SANE_Status hp_option_program (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { const HpDeviceInfo *info; DBG(10, "hp_option_program: name=%s, enable=0x%08lx, program=0x%08lx\n", this->descriptor->name, (long)this->descriptor->enable, (long)this->descriptor->program); /* Replaced by flag suppress_for_scan * if (this->descriptor->program_immediate) * { * DBG(10, "hp_option_program: is program_immediate. Dont program now.\n"); * return SANE_STATUS_GOOD; * } */ if (!this->descriptor->program) return SANE_STATUS_GOOD; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); if (this->descriptor->enable && !(*this->descriptor->enable)(this, optset, data, info)) return SANE_STATUS_GOOD; return (*this->descriptor->program)(this, scsi, optset, data); } static SANE_Status hp_option_get (HpOption this, HpData data, void * valp) { if (!this->data_acsr) return SANE_STATUS_INVAL; return sanei_hp_accessor_get(this->data_acsr, data, valp); } static hp_bool_t _values_are_equal (HpOption this, HpData data, const void * val1, const void * val2) { HpSaneOption optd = hp_option_saneoption(this, data); if (optd->type == SANE_TYPE_STRING) return strncmp((const char *)val1, (const char *)val2, optd->size) == 0; else return memcmp(val1, val2, optd->size) == 0; } static hp_bool_t hp_option_isImmediate (HpOption this) { return ( this->descriptor->program_immediate && this->descriptor->program ); } static SANE_Status hp_option_imm_set (HpOptSet optset, HpOption this, HpData data, void * valp, SANE_Int * info, HpScsi scsi) { HpSaneOption optd = hp_option_saneoption(this, data); hp_byte_t * old_val = alloca(optd->size); SANE_Status status; assert (this->descriptor->program_immediate && this->descriptor->program); if (!SANE_OPTION_IS_SETTABLE(optd->cap)) return SANE_STATUS_INVAL; DBG(10,"hp_option_imm_set: %s\n", this->descriptor->name); if ( this->descriptor->type == SANE_TYPE_BUTTON ) { status = (*this->descriptor->program)(this, scsi, optset, data); if ( !FAILED(status) && info ) { if (this->descriptor->has_global_effect) *info |= SANE_INFO_RELOAD_OPTIONS; if (this->descriptor->affects_scan_params) *info |= SANE_INFO_RELOAD_PARAMS; } return status; } if ( !this->data_acsr ) return SANE_STATUS_INVAL; if (!old_val) return SANE_STATUS_NO_MEM; if (FAILED( status = sanei_constrain_value(optd, valp, info) )) { DBG(1, "option_imm_set: %s: constrain_value failed :%s\n", this->descriptor->name, sane_strstatus(status)); return status; } RETURN_IF_FAIL( sanei_hp_accessor_get(this->data_acsr, data, old_val) ); if (_values_are_equal(this, data, old_val, valp)) { DBG(3, "option_imm_set: value unchanged\n"); return SANE_STATUS_GOOD; } if (info) memcpy(old_val, valp, optd->size); /* Save requested value */ RETURN_IF_FAIL( sanei_hp_accessor_set(this->data_acsr, data, valp) ); if ( this->descriptor->type == SANE_TYPE_STRING ) RETURN_IF_FAIL( (*this->descriptor->program)(this, scsi, optset, data) ); if (info) { if (!_values_are_equal(this, data, old_val, valp)) *info |= SANE_INFO_INEXACT; if (this->descriptor->has_global_effect) *info |= SANE_INFO_RELOAD_OPTIONS; if (this->descriptor->affects_scan_params) *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; } static SANE_Status hp_option_set (HpOption this, HpData data, void * valp, SANE_Int * info) { HpSaneOption optd = hp_option_saneoption(this, data); hp_byte_t * old_val = alloca(optd->size); SANE_Status status; char sval[64]; if (!SANE_OPTION_IS_SETTABLE(optd->cap) || !this->data_acsr) return SANE_STATUS_INVAL; if (!old_val) return SANE_STATUS_NO_MEM; sval[0] = '\0'; if (this->descriptor->type == SANE_TYPE_INT) sprintf (sval," value=%d", *(int*)valp); DBG(10,"hp_option_set: %s%s\n", this->descriptor->name, sval); if (FAILED( status = sanei_constrain_value(optd, valp, info) )) { DBG(1, "option_set: %s: constrain_value failed :%s\n", this->descriptor->name, sane_strstatus(status)); return status; } RETURN_IF_FAIL( sanei_hp_accessor_get(this->data_acsr, data, old_val) ); if (_values_are_equal(this, data, old_val, valp)) { DBG(3, "option_set: %s: value unchanged\n",this->descriptor->name); return SANE_STATUS_GOOD; } if (info) memcpy(old_val, valp, optd->size); /* Save requested value */ RETURN_IF_FAIL( sanei_hp_accessor_set(this->data_acsr, data, valp) ); if (info) { if (!_values_are_equal(this, data, old_val, valp)) *info |= SANE_INFO_INEXACT; if (this->descriptor->has_global_effect) *info |= SANE_INFO_RELOAD_OPTIONS; if (this->descriptor->affects_scan_params) *info |= SANE_INFO_RELOAD_PARAMS; DBG(3, "option_set: %s: info=0x%lx\n",this->descriptor->name, (long)*info); } return SANE_STATUS_GOOD; } static int hp_option_getint (HpOption this, HpData data) { return sanei_hp_accessor_getint(this->data_acsr, data); } static SANE_Status hp_option_imm_control (HpOptSet optset, HpOption this, HpData data, SANE_Action action, void * valp, SANE_Int *infop, HpScsi scsi) { HpSaneOption optd = hp_option_saneoption(this, data); if (!SANE_OPTION_IS_ACTIVE(optd->cap)) return SANE_STATUS_INVAL; switch (action) { case SANE_ACTION_GET_VALUE: return hp_option_get(this, data, valp); case SANE_ACTION_SET_VALUE: return hp_option_imm_set(optset, this, data, valp, infop, scsi); case SANE_ACTION_SET_AUTO: default: return SANE_STATUS_INVAL; } } static SANE_Status hp_option_control (HpOption this, HpData data, SANE_Action action, void * valp, SANE_Int *infop) { HpSaneOption optd = hp_option_saneoption(this, data); if (!SANE_OPTION_IS_ACTIVE(optd->cap)) return SANE_STATUS_INVAL; switch (action) { case SANE_ACTION_GET_VALUE: return hp_option_get(this, data, valp); case SANE_ACTION_SET_VALUE: return hp_option_set(this, data, valp, infop); case SANE_ACTION_SET_AUTO: default: return SANE_STATUS_INVAL; } } static void hp_option_reprogram (HpOption this, HpOptSet optset, HpData data, HpScsi scsi) { if (this->descriptor->may_change) { DBG(5, "hp_option_reprogram: %s\n", this->descriptor->name); hp_option_program (this, scsi, optset, data); } } static void hp_option_reprobe (HpOption this, HpOptSet optset, HpData data, HpScsi scsi) { if (this->descriptor->may_change) { DBG(5, "hp_option_reprobe: %s\n", this->descriptor->name); (*this->descriptor->probe)((_HpOption)this, scsi, optset, data); } } static void hp_option_updateEnable (HpOption this, HpOptSet optset, HpData data, const HpDeviceInfo *info) { hp_bool_t (*f)(HpOption, HpOptSet, HpData, const HpDeviceInfo *) = this->descriptor->enable; _HpSaneOption optd = _hp_option_saneoption(this, data); if (!f || (*f)(this, optset, data, info)) optd->cap &= ~SANE_CAP_INACTIVE; else optd->cap |= SANE_CAP_INACTIVE; } static hp_bool_t hp_option_isInternal (HpOption this) { return this->descriptor->name[0] == '_'; } /* * Option probe functions */ static SANE_Status _set_range (HpOption opt, HpData data, SANE_Word min, SANE_Word quant, SANE_Word max) { _HpSaneOption optd = _hp_option_saneoption(opt, data); SANE_Range * range = sanei_hp_alloc(sizeof(*range)); /* FIXME: leak? */ if (! range) return SANE_STATUS_NO_MEM; range->min = min; range->max = max; range->quant = quant; optd->constraint.range = range; optd->constraint_type = SANE_CONSTRAINT_RANGE; return SANE_STATUS_GOOD; } static void _set_size (HpOption opt, HpData data, SANE_Int size) { _hp_option_saneoption(opt, data)->size = size; } /* #ifdef HP_EXPERIMENTAL */ static SANE_Status _probe_int (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { HpScl scl = this->descriptor->scl_command; int minval, maxval; int val = 0; assert(scl); RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, &val, &minval, &maxval) ); if (minval >= maxval) return SANE_STATUS_UNSUPPORTED; /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_int_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_size(this, data, sizeof(SANE_Int)); return _set_range(this, data, minval, 1, maxval); } /* #endif */ static SANE_Status _probe_int_brightness (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { HpScl scl = this->descriptor->scl_command; int minval, maxval; int val = 0; hp_bool_t simulate; assert(scl); simulate = ( sanei_hp_device_support_get ( sanei_hp_scsi_devicename (scsi), scl, 0, 0) != SANE_STATUS_GOOD ); if ( simulate ) { val = this->descriptor->startval; minval = this->descriptor->minval; maxval = this->descriptor->maxval; } else { RETURN_IF_FAIL ( sanei_hp_scl_inquire(scsi,scl,&val,&minval,&maxval) ); } if (minval >= maxval) return SANE_STATUS_UNSUPPORTED; /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_int_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_size(this, data, sizeof(SANE_Int)); return _set_range(this, data, minval, 1, maxval); } static SANE_Status _probe_resolution (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { int minval, maxval, min2, max2; int val = 0, val2; int quant = 1; enum hp_device_compat_e compat; /* Check for supported resolutions in both directions */ RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_X_RESOLUTION, &val, &minval, &maxval) ); RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_Y_RESOLUTION, &val2, &min2, &max2)); if ( min2 > minval ) minval = min2; if ( max2 < maxval ) maxval = max2; if (minval >= maxval) return SANE_STATUS_UNSUPPORTED; /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_int_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_size(this, data, sizeof(SANE_Int)); /* The HP OfficeJet Pro 1150C crashes the scan head when scanning at * resolutions less than 42 dpi. Set a safe minimum resolution. * Hopefully 50 dpi is safe enough. */ if ((sanei_hp_device_probe(&compat,scsi)==SANE_STATUS_GOOD) && ((compat&(HP_COMPAT_OJ_1150C|HP_COMPAT_OJ_1170C))==HP_COMPAT_OJ_1150C)) { if (minval<50) minval=50; } /* HP Photosmart scanner does not allow scanning at arbitrary resolutions */ /* for slides/negatives. Must be multiple of 300 dpi. Set quantization. */ if ( (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_PS) ) {int val, mi, ma; if ( (sanei_hp_scl_inquire(scsi, SCL_MEDIA, &val, &mi, &ma) == SANE_STATUS_GOOD) && ((val == HP_MEDIA_SLIDE) || (val == HP_MEDIA_NEGATIVE)) ) quant = 300; minval = (minval+quant-1)/quant; minval *= quant; maxval = (maxval+quant-1)/quant; maxval *= quant; } DBG(5, "_probe_resolution: set range %d..%d, quant=%d\n",minval,maxval,quant); return _set_range(this, data, minval, quant, maxval); } static SANE_Status _probe_bool (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { HpScl scl = this->descriptor->scl_command; int val = 0; if (scl) RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, &val, 0, 0) ); /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_bool_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_size(this, data, sizeof(SANE_Bool)); return SANE_STATUS_GOOD; } static SANE_Status _probe_change_doc (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) {SANE_Status status; int cap = 0; DBG(2, "probe_change_doc: inquire ADF capability\n"); status = sanei_hp_scl_inquire(scsi, SCL_ADF_CAPABILITY, &cap, 0, 0); if ( (status != SANE_STATUS_GOOD) || (cap == 0)) return SANE_STATUS_UNSUPPORTED; DBG(2, "probe_change_doc: check if change document is supported\n"); status = sanei_hp_scl_inquire(scsi, SCL_CHANGE_DOC, &cap, 0, 0); if ( status != SANE_STATUS_GOOD ) return SANE_STATUS_UNSUPPORTED; /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_bool_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, cap); _set_size(this, data, sizeof(SANE_Bool)); return SANE_STATUS_GOOD; } /* The OfficeJets support SCL_UNLOAD even when no ADF is installed, so * this function was added to check for SCL_ADF_CAPABILITY, similar to * _probe_change_doc(), to hide the unnecessary "Unload" button on * non-ADF OfficeJets. */ static SANE_Status _probe_unload (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) {SANE_Status status; int cap = 0; DBG(2, "probe_unload: inquire ADF capability\n"); status = sanei_hp_scl_inquire(scsi, SCL_ADF_CAPABILITY, &cap, 0, 0); if ( (status != SANE_STATUS_GOOD) || (cap == 0)) return SANE_STATUS_UNSUPPORTED; DBG(2, "probe_unload: check if unload is supported\n"); status = sanei_hp_scl_inquire(scsi, SCL_UNLOAD, &cap, 0, 0); if ( status != SANE_STATUS_GOOD ) return SANE_STATUS_UNSUPPORTED; /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_bool_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, cap); _set_size(this, data, sizeof(SANE_Bool)); return SANE_STATUS_GOOD; } static SANE_Status _probe_calibrate (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { int val = 0; /* Always false */ int minval, maxval; int media; int download_calib_file = 1; enum hp_device_compat_e compat; /* The OfficeJets don't seem to support calibration, so we'll * remove it from the option list to reduce frontend clutter. */ if ((sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_OJ_1150C)) { return SANE_STATUS_UNSUPPORTED; } /* If we have a Photosmart scanner, we only download the calibration file */ /* when medium is set to prints */ media = -1; if (sanei_hp_scl_inquire(scsi, SCL_MEDIA, &val, &minval, &maxval) == SANE_STATUS_GOOD) media = val; /* 3: prints, 2: slides, 1: negatives */ if ( (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_PS) && (media != HP_MEDIA_PRINT)) download_calib_file = 0; /* Recalibrate can not be probed, because it has no inquire ID. */ /* And the desired ID of 10963 does not work. So we have to trust */ /* the evaluated HP model number. */ /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_bool_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_size(this, data, sizeof(SANE_Bool)); /* Try to download calibration map */ if (download_calib_file) hp_download_calib_file ( scsi ); return SANE_STATUS_GOOD; } static HpChoice _make_choice_list (HpChoice choice, int minval, int maxval) { static struct hp_choice_s bad = { 0, 0, 0, 0, 0 }; /* FIXME: hack */ /* FIXME: Another memory leak */ if (!choice->name) return 0; else if (hp_choice_isSupported(choice, minval, maxval)) { _HpChoice new = sanei_hp_memdup(choice, sizeof(*new)); if (!new) return &bad; new->next = _make_choice_list(choice + 1, minval, maxval); return new; } else return _make_choice_list(choice + 1, minval, maxval); } static HpChoice _make_probed_choice_list (HpScsi scsi, HpScl scl, HpChoice choice, int minval, int maxval) { static struct hp_choice_s bad = { 0, 0, 0, 0, 0 }; /* FIXME: hack */ /* FIXME: Another memory leak */ if (!choice->name) return 0; else if (hp_probed_choice_isSupported(scsi, scl, choice, minval, maxval)) { _HpChoice new = sanei_hp_memdup(choice, sizeof(*new)); if (!new) return &bad; new->next = _make_probed_choice_list(scsi, scl, choice + 1, minval, maxval); return new; } else return _make_probed_choice_list(scsi, scl, choice + 1, minval, maxval); } static void _set_stringlist (HpOption this, HpData data, SANE_String_Const * strlist) { _HpSaneOption optd = _hp_option_saneoption(this, data); optd->constraint.string_list = strlist; optd->constraint_type = SANE_CONSTRAINT_STRING_LIST; } static SANE_Status _probe_choice (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { HpScl scl = this->descriptor->scl_command; int minval, maxval, val; HpChoice choices; const HpDeviceInfo *info; enum hp_device_compat_e compat; RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, &val, &minval, &maxval) ); DBG(3, "choice_option_probe: '%s': val, min, max = %d, %d, %d\n", this->descriptor->name, val, minval, maxval); info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); /* Datawidth needs a special handling. The choicelist consists of */ /* values of bits per sample. But the minval/maxval uses bits per pixel */ if ( scl == SCL_DATA_WIDTH ) { enum hp_scanmode_e scanmode = sanei_hp_optset_scanmode (optset, data); /* The data width inquiries seem not to work properly on PhotoSmart */ /* Sometimes they report just 24 bits, but support 30 bits too. */ /* Sometimes they report min/max to be 24/8. Assume they all support */ /* at least 10 bits per channel for RGB. Grayscale is only supported */ /* with 8 bits. */ if ( (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_PS)) { if (scanmode == HP_SCANMODE_GRAYSCALE) { minval = 8; if (maxval < 8) maxval = 8; } else if (scanmode == HP_SCANMODE_COLOR) { minval = 24; if (maxval < 30) maxval = 30; } DBG(1, "choice_option_probe: set max. datawidth to %d for photosmart\n", maxval); } if ( scanmode == HP_SCANMODE_COLOR ) { minval /= 3; if ( minval <= 0) minval = 1; maxval /= 3; if ( maxval <= 0) maxval = 1; val /= 3; if (val <= 0) val = 1; } #if 0 /* The OfficeJets claim to support >8 bits per color, but it may not * work on some models. This code (if not commented out) disables it. */ if ((sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_OJ_1150C)) { if (maxval>8) maxval=8; } #endif } choices = _make_choice_list(this->descriptor->choices, minval, maxval); if (choices && !choices->name) /* FIXME: hack */ return SANE_STATUS_NO_MEM; if (!choices) return SANE_STATUS_UNSUPPORTED; /* If no accessor, create one here. */ #ifdef HP_ALLOC_CHOICEACC_ONCE if (!(this->data_acsr)) #endif this->data_acsr = sanei_hp_accessor_choice_new(data, choices, this->descriptor->may_change); if (!(this->data_acsr)) return SANE_STATUS_NO_MEM; sanei_hp_accessor_setint(this->data_acsr, data, val); _set_stringlist(this, data, sanei_hp_accessor_choice_strlist((HpAccessorChoice)this->data_acsr, 0, 0, info)); _set_size(this, data, sanei_hp_accessor_choice_maxsize((HpAccessorChoice)this->data_acsr)); return SANE_STATUS_GOOD; } static SANE_Status _probe_each_choice (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { HpScl scl = this->descriptor->scl_command; int minval, maxval, val; HpChoice choices; const HpDeviceInfo *info; RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, &val, &minval, &maxval) ); DBG(3, "choice_option_probe_each: '%s': val, min, max = %d, %d, %d\n", this->descriptor->name, val, minval, maxval); DBG(3, "choice_option_probe_each: test all values for '%s' separately\n", this->descriptor->name); info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); choices = _make_probed_choice_list(scsi, scl, this->descriptor->choices, minval, maxval); DBG(3, "choice_option_probe_each: restore previous value %d for '%s'\n", val, this->descriptor->name); /* Restore current value */ RETURN_IF_FAIL( sanei_hp_scl_set(scsi, scl, val) ); if (choices && !choices->name) /* FIXME: hack */ return SANE_STATUS_NO_MEM; if (!choices) return SANE_STATUS_UNSUPPORTED; /* If we dont have an accessor, get one */ #ifdef HP_ALLOC_CHOICEACC_ONCE if (!this->data_acsr) #endif { if (!(this->data_acsr = sanei_hp_accessor_choice_new(data, choices, this->descriptor->may_change ))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_stringlist(this, data, sanei_hp_accessor_choice_strlist((HpAccessorChoice)this->data_acsr, 0, 0, info)); _set_size(this, data, sanei_hp_accessor_choice_maxsize((HpAccessorChoice)this->data_acsr)); return SANE_STATUS_GOOD; } /* pseudo probe for exposure times in Photosmart */ static SANE_Status _probe_ps_exposure_time (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { int minval = 0, maxval = 9, val = 0; HpChoice choices; const HpDeviceInfo *info; choices = _make_choice_list(this->descriptor->choices, minval, maxval); if (choices && !choices->name) /* FIXME: hack */ return SANE_STATUS_NO_MEM; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); /* If we dont have an accessor, get one */ #ifdef HP_ALLOC_CHOICEACC_ONCE if (!this->data_acsr) #endif { if (!(this->data_acsr = sanei_hp_accessor_choice_new(data, choices, this->descriptor->may_change ))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_stringlist(this, data, sanei_hp_accessor_choice_strlist((HpAccessorChoice)this->data_acsr, 0, 0, info)); _set_size(this, data, sanei_hp_accessor_choice_maxsize((HpAccessorChoice)this->data_acsr)); return SANE_STATUS_GOOD; } /* probe scan type (normal, adf, xpa) */ static SANE_Status _probe_scan_type (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { int val; int numchoices = 0; HpChoice choices; SANE_Status status; const HpDeviceInfo *info; struct hp_choice_s scan_types[4]; struct hp_choice_s nch = { 0, 0, 0, 0, 0 }; enum hp_device_compat_e compat; /* We always have normal scan mode */ scan_types[numchoices++] = this->descriptor->choices[0]; if ( sanei_hp_device_probe (&compat, scsi) != SANE_STATUS_GOOD ) compat = 0; /* Inquire ADF Capability. PhotoSmart scanner reports ADF capability, */ /* but it makes no sense. */ if ((compat & HP_COMPAT_PS) == 0) { status = sanei_hp_scl_inquire(scsi, SCL_ADF_CAPABILITY, &val, 0, 0); if ( (status == SANE_STATUS_GOOD) && (val == 1) ) { scan_types[numchoices++] = this->descriptor->choices[1]; } } /* Inquire XPA capability is supported only by IIcx and 6100c/4c/3c. */ /* But more devices support XPA scan window. So dont inquire XPA cap. */ if ( compat & ( HP_COMPAT_2CX | HP_COMPAT_4C | HP_COMPAT_4P | HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_6200C) && !(compat&HP_COMPAT_OJ_1150C) ) { scan_types[numchoices++] = this->descriptor->choices[2]; } /* Only normal scan type available ? No need to display choice */ if (numchoices <= 1) return SANE_STATUS_UNSUPPORTED; scan_types[numchoices] = nch; val = 0; choices = _make_choice_list(scan_types, 0, numchoices); if (choices && !choices->name) /* FIXME: hack */ return SANE_STATUS_NO_MEM; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); /* If we dont have an accessor, get one */ #ifdef HP_ALLOC_CHOICEACC_ONCE if (!this->data_acsr) #endif { if (!(this->data_acsr = sanei_hp_accessor_choice_new(data, choices, this->descriptor->may_change ))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_stringlist(this, data, sanei_hp_accessor_choice_strlist((HpAccessorChoice)this->data_acsr, 0, 0, info)); _set_size(this, data, sanei_hp_accessor_choice_maxsize((HpAccessorChoice)this->data_acsr)); return SANE_STATUS_GOOD; } static SANE_Status _probe_mirror_horiz (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { HpScl scl = this->descriptor->scl_command; int minval, maxval, val, sec_dir; HpChoice choices; const HpDeviceInfo *info; RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, &val, &minval, &maxval) ); DBG(3, "probe_mirror_horiz: '%s': val, min, max = %d, %d, %d\n", this->descriptor->name, val, minval, maxval); /* Look if the device supports the (?) inquire secondary scan-direction */ if ( sanei_hp_scl_inquire(scsi, SCL_SECONDARY_SCANDIR, &sec_dir, 0, 0) == SANE_STATUS_GOOD ) minval = HP_MIRROR_HORIZ_CONDITIONAL; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); choices = _make_choice_list(this->descriptor->choices, minval, maxval); if (choices && !choices->name) /* FIXME: hack */ return SANE_STATUS_NO_MEM; if (!choices) return SANE_STATUS_UNSUPPORTED; /* If we dont have an accessor, get one */ #ifdef HP_ALLOC_CHOICEACC_ONCE if (!this->data_acsr) #endif { if (!(this->data_acsr = sanei_hp_accessor_choice_new(data, choices, this->descriptor->may_change ))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_stringlist(this, data, sanei_hp_accessor_choice_strlist((HpAccessorChoice)this->data_acsr, 0, 0, info)); _set_size(this, data, sanei_hp_accessor_choice_maxsize((HpAccessorChoice)this->data_acsr)); return SANE_STATUS_GOOD; } static SANE_Status _probe_mirror_vert (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { int minval = HP_MIRROR_VERT_OFF, maxval = HP_MIRROR_VERT_ON, val = HP_MIRROR_VERT_OFF; int sec_dir; HpChoice choices; const HpDeviceInfo *info; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); /* Look if the device supports the (?) inquire secondary scan-direction */ if ( sanei_hp_scl_inquire(scsi, SCL_SECONDARY_SCANDIR, &sec_dir, 0, 0) == SANE_STATUS_GOOD ) maxval = HP_MIRROR_VERT_CONDITIONAL; choices = _make_choice_list(this->descriptor->choices, minval, maxval); if (choices && !choices->name) /* FIXME: hack */ return SANE_STATUS_NO_MEM; if (!choices) return SANE_STATUS_UNSUPPORTED; /* If we dont have an accessor, get one */ #ifdef HP_ALLOC_CHOICEACC_ONCE if (!this->data_acsr) #endif { if (!(this->data_acsr = sanei_hp_accessor_choice_new(data, choices, this->descriptor->may_change ))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_stringlist(this, data, sanei_hp_accessor_choice_strlist((HpAccessorChoice)this->data_acsr, 0, 0, info)); _set_size(this, data, sanei_hp_accessor_choice_maxsize((HpAccessorChoice)this->data_acsr)); return SANE_STATUS_GOOD; } static SANE_Status _probe_front_button(_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { int val = 0; if ( sanei_hp_scl_inquire(scsi, SCL_FRONT_BUTTON, &val, 0, 0) != SANE_STATUS_GOOD ) return SANE_STATUS_UNSUPPORTED; _set_size(this, data, sizeof(SANE_Bool)); /* If we dont have an accessor, get one */ if (!this->data_acsr) { if ( !(this->data_acsr = sanei_hp_accessor_bool_new(data)) ) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, 0); return SANE_STATUS_GOOD; } static SANE_Status _probe_geometry (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { HpScl scl = this->descriptor->scl_command; hp_bool_t is_tl = 0; hp_bool_t active_xpa = sanei_hp_is_active_xpa ( scsi ); int minval, maxval; SANE_Fixed fval; /* There might have been a reason for inquiring the extent */ /* by using the maxval of the position. But this does not work */ /* when scanning from ADF. The Y-pos is then inquired with -1..0. */ /* First try to get the values with SCL_X/Y_POS. If this is not ok, */ /* use SCL_X/Y_EXTENT */ if (scl == SCL_X_EXTENT) { scl = SCL_X_POS; } else if (scl == SCL_Y_EXTENT) { scl = SCL_Y_POS; } else is_tl = 1; RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, 0, &minval, &maxval) ); if (minval >= maxval) return SANE_STATUS_INVAL; /* Bad maximum value for extent-inquiry ? */ if ( (!is_tl) && (maxval <= 0) ) { scl = (scl == SCL_X_POS) ? SCL_X_EXTENT : SCL_Y_EXTENT; RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, 0, &minval, &maxval) ); if (minval >= maxval) return SANE_STATUS_INVAL; } if ((scl == SCL_X_EXTENT) || (scl == SCL_Y_EXTENT)) { /* Max. extent is larger than max. position. Reduce extent */ maxval--; DBG(3, "probe_geometry: Inquiry by extent. Reduced maxval to %lu\n", (unsigned long)maxval); } /* Need a new accessor ? */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_fixed_new(data))) return SANE_STATUS_NO_MEM; } /* The active xpa is only 5x5 inches */ if ( (!is_tl) && active_xpa && (sanei_hp_optset_scan_type (optset, data) == SCL_XPA_SCAN) ) { DBG(3,"Set maxval to 1500 because of active XPA\n"); maxval = 1500; } fval = is_tl ? SANE_FIX(0.0) : maxval * SANE_FIX(MM_PER_DEVPIX); RETURN_IF_FAIL( sanei_hp_accessor_set(this->data_acsr, data, &fval) ); _set_size(this, data, sizeof(SANE_Fixed)); return _set_range(this, data, minval * SANE_FIX(MM_PER_DEVPIX), 1, maxval * SANE_FIX(MM_PER_DEVPIX)); } static SANE_Status _probe_download_type (HpScl scl, HpScsi scsi) { SANE_Status status; sanei_hp_scl_clearErrors (scsi); sanei_hp_scl_set (scsi, SCL_DOWNLOAD_TYPE, SCL_INQ_ID(scl)); status = sanei_hp_scl_errcheck (scsi); DBG(3, "probe_download_type: Download type %d %ssupported\n", SCL_INQ_ID(scl), (status == SANE_STATUS_GOOD) ? "" : "not "); return status; } static SANE_Status _probe_custom_gamma (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { HpScl scl = this->descriptor->scl_command; HpScl scl_tonemap = SCL_8x8TONE_MAP; SANE_Status status; hp_bool_t simulate; int val = 0, minval, maxval; int id = SCL_INQ_ID(scl_tonemap); /* Check if download type supported */ status = sanei_hp_device_support_get ( sanei_hp_scsi_devicename (scsi), SCL_DOWNLOAD_TYPE, &minval, &maxval); simulate = (status != SANE_STATUS_GOOD) || (id < minval) || (id > maxval); if (simulate) { DBG(3, "probe_custom_gamma: Download type 2 not supported. Simulate\n"); } else { RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, &val, 0, 0) ); } /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_bool_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, val); _set_size(this, data, sizeof(SANE_Bool)); return SANE_STATUS_GOOD; } static SANE_Status _probe_vector (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { static struct vector_type_s { HpScl scl; unsigned length, depth; HpAccessor (*creator)(HpData data, unsigned length, unsigned depth); } types[] = { { SCL_8x8TONE_MAP, 256, 8, sanei_hp_accessor_gamma_vector_new }, #ifdef ENABLE_7x12_TONEMAPS { SCL_BW7x12TONE_MAP, 129, 12, sanei_hp_accessor_gamma_vector_new }, { SCL_7x12TONE_MAP, 3 * 129, 12, sanei_hp_accessor_gamma_vector_new }, #endif #ifdef ENABLE_16x16_DITHERS { SCL_BW16x16DITHER, 256, 8, sanei_hp_accessor_vector_new }, #endif { SCL_BW8x8DITHER, 64, 8, sanei_hp_accessor_vector_new }, { SCL_8x9MATRIX_COEFF, 9, 8, sanei_hp_accessor_matrix_vector_new }, #ifdef ENABLE_10BIT_MATRIXES { SCL_10x9MATRIX_COEFF, 9, 10, sanei_hp_accessor_matrix_vector_new }, { SCL_10x3MATRIX_COEFF, 3, 10, sanei_hp_accessor_matrix_vector_new }, #endif { 0, 0, 0, 0 } }; static struct subvector_type_s { HpOptionDescriptor desc; unsigned nchan, chan; HpOptionDescriptor super; } subvec_types[] = { #ifdef ENABLE_7x12_TONEMAPS { GAMMA_VECTOR_R, 3, 0, RGB_TONEMAP }, { GAMMA_VECTOR_G, 3, 1, RGB_TONEMAP }, { GAMMA_VECTOR_B, 3, 2, RGB_TONEMAP }, #endif { 0, 0, 0, 0 }, }; HpScl scl = this->descriptor->scl_command; HpAccessorVector vec; if (scl) { struct vector_type_s *type; for (type = types; type->scl; type++) if (type->scl == scl) break; assert(type->scl); RETURN_IF_FAIL ( _probe_download_type (scl, scsi) ); /* If we dont have an accessor, get one */ #ifdef HP_ALLOC_CHOICEACC_ONCE if (!this->data_acsr) #endif { this->data_acsr = (*type->creator)(data, type->length, type->depth); } } else { struct subvector_type_s *type; HpOption super; for (type = subvec_types; type->desc; type++) if (type->desc == this->descriptor) break; assert(type->desc); super = hp_optset_get(optset, type->super); assert(super); /* If we dont have an accessor, get one */ #ifdef HP_ALLOC_CHOICEACC_ONCE if (!this->data_acsr) #endif { this->data_acsr = sanei_hp_accessor_subvector_new( (HpAccessorVector) super->data_acsr, type->nchan, type->chan); } } if (!this->data_acsr) return SANE_STATUS_NO_MEM; vec = (HpAccessorVector)this->data_acsr; _set_size(this, data, sizeof(SANE_Fixed) * sanei_hp_accessor_vector_length(vec)); return _set_range(this, data, sanei_hp_accessor_vector_minval(vec), 1, sanei_hp_accessor_vector_maxval(vec)); } static SANE_Status _probe_gamma_vector (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { SANE_Fixed * buf; int i; size_t size, length; RETURN_IF_FAIL( _probe_vector(this, scsi, optset, data) ); /* Initialize to linear map */ size = hp_option_saneoption(this, data)->size; if (!(buf = alloca(size))) return SANE_STATUS_NO_MEM; length = size / sizeof(SANE_Fixed); for (i = 0; i < (int)length; i++) buf[i] = (SANE_FIX(HP_VECTOR_SCALE* 1.0) * i + (length-1) / 2) / length; return sanei_hp_accessor_set(this->data_acsr, data, buf); } static SANE_Status _probe_horiz_dither (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { int dim = 8; size_t size; int i, j; SANE_Fixed * buf; if (this->descriptor->scl_command == SCL_BW16x16DITHER) dim = 16; RETURN_IF_FAIL( _probe_vector(this, scsi, optset, data) ); /* Select vertical dither pattern, and upload it */ RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_BW_DITHER, HP_DITHER_VERTICAL) ); RETURN_IF_FAIL( hp_option_upload(this, scsi, optset, data) ); /* Flip it to get a horizontal dither pattern */ size = hp_option_saneoption(this, data)->size; assert(size == dim * dim * sizeof(SANE_Fixed)); if (!(buf = alloca(size))) return SANE_STATUS_NO_MEM; #define SWAP_FIXED(x,y) do { SANE_Fixed tmp = x; x = y; y = tmp; } while(0) RETURN_IF_FAIL( sanei_hp_accessor_get(this->data_acsr, data, buf) ); for (i = 0; i < dim; i++) for (j = i + 1; j < dim; j++) SWAP_FIXED(buf[i * dim + j], buf[j * dim + i]); return sanei_hp_accessor_set(this->data_acsr, data, buf); } static SANE_Status _probe_matrix (_HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { RETURN_IF_FAIL( _probe_vector(this, scsi, optset, data) ); /* Initial value: select RGB matrix, and upload it. */ RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_MATRIX, HP_MATRIX_RGB) ); return hp_option_upload(this, scsi, optset, data); } static SANE_Status _probe_num_options (_HpOption this, HpScsi __sane_unused__ scsi, HpOptSet __sane_unused__ optset, HpData data) { /* If we dont have an accessor, get one */ if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_int_new(data))) return SANE_STATUS_NO_MEM; } _set_size(this, data, sizeof(SANE_Int)); return SANE_STATUS_GOOD; } static SANE_Status _probe_devpix (_HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { HpScl scl = this->descriptor->scl_command; int resolution; if (FAILED( sanei_hp_scl_inquire(scsi, scl, &resolution, 0, 0) )) { DBG(1, "probe_devpix: inquiry failed, assume 300 ppi\n"); resolution = 300; } if (!this->data_acsr) { if (!(this->data_acsr = sanei_hp_accessor_int_new(data))) return SANE_STATUS_NO_MEM; } sanei_hp_accessor_setint(this->data_acsr, data, resolution); _set_size(this, data, sizeof(SANE_Int)); return SANE_STATUS_GOOD; } /* * Simulate functions */ static SANE_Status _simulate_brightness (HpOption this, HpData data, HpScsi scsi) { int k, val, newval; unsigned char *brightness_map; HpDeviceInfo *info; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); assert (info); val = sanei_hp_accessor_getint(this->data_acsr, data); DBG(3, "simulate_brightness: value = %d\n", val); /* Update brightness map in info structure */ brightness_map = &(info->simulate.brightness_map[0]); val *= 2; /* A value of 127 should give a totally white image */ for (k = 0; k < 256; k++) { newval = k + val; if (newval < 0) newval = 0; else if (newval > 255) newval = 255; brightness_map[k] = (unsigned char)newval; } return SANE_STATUS_GOOD; } static int hp_contrast (int x, int g) {int y = 0; if (g < -127) g = -127; else if (g > 127) g = 127; if (x < 0) x = 0; else if (x > 255) x = 255; if (g == 0) { y = x; } else if (g < 0) { g = -g; y = x * (255 - 2*g); y = y/255 + g; } else { if (x <= g) y = 0; else if (x >= 255-g) y = 255; else { y = (x - g)*255; y /= (255 - 2*g); } } return y; } static SANE_Status _simulate_contrast (HpOption this, HpData data, HpScsi scsi) { int k, val, newval; unsigned char *contrast_map; HpDeviceInfo *info; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); assert (info); val = sanei_hp_accessor_getint(this->data_acsr, data); DBG(3, "simulate_contrast: value = %d\n", val); /* Update contrast map in info structure */ contrast_map = &(info->simulate.contrast_map[0]); for (k = 0; k < 256; k++) { newval = hp_contrast (k, val); if (newval < 0) newval = 0; else if (newval > 255) newval = 255; contrast_map[k] = (unsigned char)newval; } return SANE_STATUS_GOOD; } /* * Option download functions */ static SANE_Status _program_generic (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { return hp_option_download(this, data, optset, scsi); } static SANE_Status _program_geometry (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { /* #define HP_LIMIT_ADF_WINDOW */ #ifndef HP_LIMIT_ADF_WINDOW return hp_option_download(this, data, optset, scsi); #else HpScl scl = this->descriptor->scl_command; int value; SANE_Status Status; if (sanei_hp_optset_scan_type (optset, data) != SCL_ADF_SCAN) return hp_option_download(this, data, optset, scsi); /* ADF may crash when scanning only a window ? */ if ( (scl == SCL_X_POS) || (scl == SCL_Y_POS) ) { value = 0; DBG(3,"program_geometry: set %c-pos to %d\n", (scl == SCL_X_POS) ? 'x' : 'y', value); } else if ( scl == SCL_X_EXTENT ) { value = 2550; DBG(3,"program_geometry: set x-extent to %d\n", value); } else { value = 4200; DBG(3,"program_geometry: set y-extent to %d\n", value); } Status = sanei_hp_scl_set(scsi, scl, value); return Status; #endif } static SANE_Status _program_data_width (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { HpScl scl = this->descriptor->scl_command; int value = sanei_hp_accessor_getint(this->data_acsr, data); SANE_Status status; if ( sanei_hp_optset_scanmode (optset, data) == HP_SCANMODE_COLOR ) { value *= 3; if (value < 24) { DBG(3,"program_data_width: map datawith from %d to 24\n", (int)value); value = 24; } } status = sanei_hp_scl_set(scsi, scl, value); return status; } static SANE_Status _program_generic_simulate (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { HpScl scl = this->descriptor->scl_command; const char *devname = sanei_hp_scsi_devicename (scsi); int simulate; /* Check if command is supported */ simulate = ( sanei_hp_device_support_get (devname, scl, 0, 0) != SANE_STATUS_GOOD ); /* Save simulate flag */ sanei_hp_device_simulate_set (devname, scl, simulate); if ( !simulate ) /* Let the device do it */ return hp_option_download(this, data, optset, scsi); DBG(3, "program_generic: %lu not programmed. Will be simulated\n", (unsigned long)(SCL_INQ_ID(scl))); switch (scl) { case SCL_BRIGHTNESS: _simulate_brightness (this, data, scsi); break; case SCL_CONTRAST: _simulate_contrast (this, data,scsi); break; default: DBG(1, "program_generic: No simulation for %lu\n", (unsigned long)(SCL_INQ_ID(scl))); break; } return SANE_STATUS_GOOD; } static SANE_Status _simulate_custom_gamma (HpOption gvector, HpScsi scsi, HpData data) { size_t size = sanei_hp_accessor_size(gvector->data_acsr); const unsigned char *vector_data = (const unsigned char *)sanei_hp_accessor_data(gvector->data_acsr, data); HpDeviceInfo *info; int k, newval; DBG(3,"program_custom_gamma_simulate: save gamma map\n"); if (size != 256) { DBG(1,"program_custom_gamma_simulate: size of vector is %d.\ Should be 256.\n", (int)size); return SANE_STATUS_INVAL; } RETURN_IF_FAIL (sanei_hp_scl_set(scsi, SCL_TONE_MAP, 0)); info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); info->simulate.gamma_simulate = 1; for (k = 0; k < 256; k++) { newval = 255 - vector_data[255-k]; if (newval < 0) newval = 0; else if (newval > 255) newval = 255; info->simulate.gamma_map[k] = newval; } return SANE_STATUS_GOOD; } static SANE_Status _program_tonemap (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { hp_bool_t use_custom_map = hp_option_getint(this, data); HpOption gvector = 0; int type = 0; if (!use_custom_map) return sanei_hp_scl_set(scsi, SCL_TONE_MAP, 0); #ifdef ENABLE_7x12_TONEMAPS /* Try to find the appropriate 5P style tonemap. */ if (sanei_hp_optset_scanmode(optset, data) == HP_SCANMODE_COLOR) { type = -1; gvector = hp_optset_get(optset, RGB_TONEMAP); } else { type = -2; gvector = hp_optset_get(optset, GAMMA_VECTOR_7x12); } #endif /* If that failed, just use 8x8 tonemap */ if (!gvector) { HpScl scl_tonemap = SCL_8x8TONE_MAP; hp_bool_t simulate; int id = SCL_INQ_ID(scl_tonemap); int minval, maxval; SANE_Status status; type = -1; gvector = hp_optset_get(optset, GAMMA_VECTOR_8x8); /* Check if download type supported */ status = sanei_hp_device_support_get ( sanei_hp_scsi_devicename (scsi), SCL_DOWNLOAD_TYPE, &minval, &maxval); simulate = (status != SANE_STATUS_GOOD) || (id < minval) || (id > maxval); if (simulate) return _simulate_custom_gamma (gvector, scsi, data); } assert(gvector != 0); RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_TONE_MAP, type) ); return hp_option_download(gvector, data, optset, scsi); } static SANE_Status _program_dither (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { enum hp_dither_type_e type = hp_option_getint(this, data); HpOption dither; switch (type) { case HP_DITHER_CUSTOM: dither = hp_optset_getByName(optset, SANE_NAME_HALFTONE_PATTERN); assert(dither != 0); break; case HP_DITHER_HORIZONTAL: dither = hp_optset_getByName(optset, HP_NAME_HORIZONTAL_DITHER); type = HP_DITHER_CUSTOM; assert(dither != 0); break; default: dither = 0; break; } RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_BW_DITHER, type) ); if (!dither) return SANE_STATUS_GOOD; return hp_option_download(dither, data, optset, scsi); } #ifdef FAKE_COLORSEP_MATRIXES static HpOption _get_sepmatrix (HpOptSet optset, HpData data, enum hp_matrix_type_e type) { SANE_Fixed buf[9]; HpOption matrix = hp_optset_get(optset, SEPMATRIX); memset(buf, 0, sizeof(buf)); if (type == HP_MATRIX_RED) buf[1] = SANE_FIX(1.0); else if (type == HP_MATRIX_GREEN) buf[4] = SANE_FIX(1.0); else if (type == HP_MATRIX_BLUE) buf[7] = SANE_FIX(1.0); else { assert(!"Bad colorsep type"); return 0; } sanei_hp_accessor_set(matrix->data_acsr, data, buf); return matrix; } #endif static SANE_Status _program_matrix (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { enum hp_matrix_type_e type = hp_option_getint(this, data); HpOption matrix = 0; if (type == HP_MATRIX_AUTO) return SANE_STATUS_GOOD; /* Default to matrix set by mode */ /* Download custom matrix, if we need it. */ if (type == HP_MATRIX_CUSTOM) { matrix = hp_optset_getByName(optset, SANE_NAME_MATRIX_RGB); assert(matrix); } #ifdef FAKE_COLORSEP_MATRIXES else if (type == HP_MATRIX_RED || type == HP_MATRIX_BLUE || type == HP_MATRIX_GREEN) { matrix = _get_sepmatrix(optset, data, type); type = HP_MATRIX_CUSTOM; assert(matrix); } #else else if (type == HP_MATRIX_GREEN) type = HP_MATRIX_PASS; #endif RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_MATRIX, type) ); if (matrix) RETURN_IF_FAIL( hp_option_download(matrix, data, optset, scsi) ); return SANE_STATUS_GOOD; } static SANE_Status _program_resolution (HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { int xresolution = hp_option_getint(this, data); int yresolution = xresolution; int xscale = 100, yscale = 100; #ifdef FIX_PHOTOSMART int minval, maxval, media; enum hp_device_compat_e compat; /* HP Photosmart scanner has problems with scanning slides/negatives */ /* at arbitrary resolutions. The following tests did not work: */ /* xres = yres = next lower multiple of 300, xscale = yscale > 100: */ /* xres = yres = next higher multiple of 300, xscale = yscale < 100: */ /* xres = next lower multiple of 300, xscale > 100 */ /* xres = next higher multiple of 300, xscale < 100 */ /* yres = next lower multiple of 300, yscale > 100 */ /* yres = next higher multiple of 300, yscale < 100 */ /* The image extent was ok, but the content was streched in y-direction */ if (xresolution > 300) { if ( (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_PS) && (sanei_hp_scl_inquire(scsi, SCL_MEDIA, &media, &minval, &maxval) == SANE_STATUS_GOOD) && ((media == HP_MEDIA_SLIDE) || (media == HP_MEDIA_NEGATIVE))) {int next_resolution; next_resolution = (xresolution % 300) * 300; if (next_resolution < 300) next_resolution = 300; yresolution = next_resolution; yscale = (int)(100.0 * xresolution / yresolution); } } #endif RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_X_SCALE, xscale) ); RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_Y_SCALE, yscale) ); RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_X_RESOLUTION, xresolution) ); RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_Y_RESOLUTION, yresolution) ); return SANE_STATUS_GOOD; } static char * get_home_dir (void) { #ifdef SANE_HOME_HP return getenv (SANE_HOME_HP); #else struct passwd *pw; pw = getpwuid (getuid ()); /* Look if we can find our home directory */ return pw ? pw->pw_dir : NULL; #endif } static char * get_calib_filename (HpScsi scsi) { char *homedir; char *calib_filename, *cf; const char *devname = sanei_hp_scsi_devicename (scsi); int name_len; homedir = get_home_dir (); /* Look if we can find our home directory */ if (!homedir) return NULL; name_len = strlen (homedir) + 33; if ( devname ) name_len += strlen (devname); calib_filename = sanei_hp_allocz (name_len); if (!calib_filename) return NULL; strcpy (calib_filename, homedir); strcat (calib_filename, "/.sane/calib-hp"); if ( devname && devname[0] ) /* Replace '/' by "+-" */ { cf = calib_filename + strlen (calib_filename); *(cf++) = ':'; while (*devname) { if (*devname == '/') *(cf++) = '+', *(cf++) = '-'; else *(cf++) = *devname; devname++; } } strcat (calib_filename, ".dat"); return calib_filename; } static SANE_Status read_calib_file (int *nbytes, char **calib_data, HpScsi scsi) { SANE_Status status = SANE_STATUS_GOOD; char *calib_filename; FILE *calib_file; int err, c1, c2, c3, c4; *nbytes = 0; *calib_data = NULL; calib_filename = get_calib_filename ( scsi ); if (!calib_filename) return SANE_STATUS_NO_MEM; calib_file = fopen (calib_filename, "rb"); if ( calib_file ) { err = ((c1 = getc (calib_file)) == EOF); err |= ((c2 = getc (calib_file)) == EOF); err |= ((c3 = getc (calib_file)) == EOF); err |= ((c4 = getc (calib_file)) == EOF); *nbytes = (c1 << 24) | (c2 << 16) | (c3 << 8) | c4; if ( err ) { DBG(1, "read_calib_file: Error reading calibration data size\n"); status = SANE_STATUS_EOF; } else { *calib_data = sanei_hp_alloc ( *nbytes ); if ( !*calib_data ) { status = SANE_STATUS_NO_MEM; } else { err |= ((int)fread (*calib_data,1,*nbytes,calib_file) != *nbytes); if ( err ) { DBG(1, "read_calib_file: Error reading calibration data\n"); sanei_hp_free ( *calib_data ); status = SANE_STATUS_EOF; } } } fclose ( calib_file ); } else { DBG(1, "read_calib_file: Error opening calibration file %s\ for reading\n", calib_filename); status = SANE_STATUS_EOF; } sanei_hp_free (calib_filename); return ( status ); } static SANE_Status write_calib_file (int nbytes, char *data, HpScsi scsi) { SANE_Status status = SANE_STATUS_GOOD; char *calib_filename; int err; FILE *calib_file; calib_filename = get_calib_filename ( scsi ); if (!calib_filename) return SANE_STATUS_NO_MEM; calib_file = fopen (calib_filename, "wb"); if ( calib_file ) { err = (putc ((nbytes >> 24) & 0xff, calib_file) == EOF); err |= (putc ((nbytes >> 16) & 0xff, calib_file) == EOF); err |= (putc ((nbytes >> 8) & 0xff, calib_file) == EOF); err |= (putc (nbytes & 0xff, calib_file) == EOF); err |= ((int)fwrite (data, 1, nbytes, calib_file) != nbytes); fclose (calib_file); if ( err ) { DBG(1, "write_calib_file: Error writing calibration data\n"); unlink (calib_filename); status = SANE_STATUS_EOF; } } else { DBG(1, "write_calib_file: Error opening calibration file %s\ for writing\n", calib_filename); status = SANE_STATUS_EOF; } sanei_hp_free (calib_filename); return (status); } static SANE_Status _program_media (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { int req_media, minval, maxval, current_media; HpScl scl = this->descriptor->scl_command; req_media = sanei_hp_accessor_getint(this->data_acsr, data); RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, scl, ¤t_media, &minval, &maxval) ); if (current_media == req_media) return SANE_STATUS_GOOD; /* Unload scanner */ RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_UNLOAD, 0) ); /* Select new media */ RETURN_IF_FAIL( hp_option_download(this, data, optset, scsi)); /* Update support list */ sanei_hp_device_support_probe (scsi); if (req_media == HP_MEDIA_PRINT) hp_download_calib_file (scsi); return SANE_STATUS_GOOD; } static SANE_Status _program_unload_after_scan (HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { HpDeviceInfo *info; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); assert (info); info->unload_after_scan = sanei_hp_accessor_getint(this->data_acsr, data); DBG(3,"program_unload_after_scan: flag = %lu\n", (unsigned long)info->unload_after_scan); return SANE_STATUS_GOOD; } static SANE_Status _program_lamp_off (HpOption __sane_unused__ this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData __sane_unused__ data) { DBG(3,"program_lamp_off: shut off lamp\n"); return sanei_hp_scl_set(scsi, SCL_LAMPTEST, 0); } static SANE_Status _program_scan_type (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { int req_scan_type; req_scan_type = sanei_hp_accessor_getint(this->data_acsr, data); if ( req_scan_type == HP_SCANTYPE_XPA ) { enum hp_scanmode_e scan_mode = sanei_hp_optset_scanmode(optset, data); static unsigned char xpa_matrix_coeff[] = { 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80 }; static unsigned char xpa_tone_map[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfe,0x0f, 0xe1,0x0f,0xd3,0x0f,0xc4,0x0f,0xb5,0x0f,0xa6,0x0f,0x97,0x0f,0x88,0x0f,0x79,0x0f, 0x6a,0x0f,0x5b,0x0f,0x4b,0x0f,0x3c,0x0f,0x2c,0x0f,0x1d,0x0f,0x0d,0x0e,0xfe,0x0e, 0xee,0x0e,0xde,0x0e,0xce,0x0e,0xbe,0x0e,0xae,0x0e,0x9e,0x0e,0x8e,0x0e,0x7d,0x0e, 0x6d,0x0e,0x5c,0x0e,0x4c,0x0e,0x3b,0x0e,0x2a,0x0e,0x19,0x0e,0x08,0x0d,0xf7,0x0d, 0xe6,0x0d,0xd5,0x0d,0xc4,0x0d,0xb2,0x0d,0xa1,0x0d,0x8f,0x0d,0x7d,0x0d,0x6b,0x0d, 0x59,0x0d,0x47,0x0d,0x35,0x0d,0x22,0x0d,0x10,0x0c,0xfd,0x0c,0xeb,0x0c,0xd8,0x0c, 0xc5,0x0c,0xb2,0x0c,0x9e,0x0c,0x8b,0x0c,0x77,0x0c,0x64,0x0c,0x50,0x0c,0x3c,0x0c, 0x28,0x0c,0x14,0x0b,0xff,0x0b,0xeb,0x0b,0xd6,0x0b,0xc1,0x0b,0xac,0x0b,0x96,0x0b, 0x81,0x0b,0x6b,0x0b,0x55,0x0b,0x3f,0x0b,0x29,0x0b,0x12,0x0a,0xfc,0x0a,0xe5,0x0a, 0xce,0x0a,0xb6,0x0a,0x9e,0x0a,0x87,0x0a,0x6e,0x0a,0x56,0x0a,0x3d,0x0a,0x24,0x0a, 0x0b,0x09,0xf1,0x09,0xd8,0x09,0xbd,0x09,0xa3,0x09,0x88,0x09,0x6d,0x09,0x51,0x09, 0x35,0x09,0x19,0x08,0xfc,0x08,0xdf,0x08,0xc1,0x08,0xa3,0x08,0x84,0x08,0x65,0x08, 0x45,0x08,0x24,0x08,0x03,0x07,0xe1,0x07,0xbe,0x07,0x9b,0x07,0x78,0x07,0x53,0x07, 0x2d,0x07,0x07,0x06,0xdf,0x06,0xb7,0x06,0x8d,0x06,0x62,0x06,0x36,0x06,0x07,0x05, 0xd8,0x05,0xa6,0x05,0x72,0x05,0x3c,0x04,0xfc,0x04,0x7c,0x03,0xfc,0x03,0x7c,0x02, 0xfc,0x02,0x7c,0x01,0xfc,0x01,0x7c,0x00,0xfc,0x00,0x7c,0x00,0x00,0x0f,0xfe,0x0f, 0xe1,0x0f,0xd3,0x0f,0xc4,0x0f,0xb5,0x0f,0xa6,0x0f,0x97,0x0f,0x88,0x0f,0x79,0x0f, 0x6a,0x0f,0x5b,0x0f,0x4b,0x0f,0x3c,0x0f,0x2c,0x0f,0x1d,0x0f,0x0d,0x0e,0xfe,0x0e, 0xee,0x0e,0xde,0x0e,0xce,0x0e,0xbe,0x0e,0xae,0x0e,0x9e,0x0e,0x8e,0x0e,0x7d,0x0e, 0x6d,0x0e,0x5c,0x0e,0x4c,0x0e,0x3b,0x0e,0x2a,0x0e,0x19,0x0e,0x08,0x0d,0xf7,0x0d, 0xe6,0x0d,0xd5,0x0d,0xc4,0x0d,0xb2,0x0d,0xa1,0x0d,0x8f,0x0d,0x7d,0x0d,0x6b,0x0d, 0x59,0x0d,0x47,0x0d,0x35,0x0d,0x22,0x0d,0x10,0x0c,0xfd,0x0c,0xeb,0x0c,0xd8,0x0c, 0xc5,0x0c,0xb2,0x0c,0x9e,0x0c,0x8b,0x0c,0x77,0x0c,0x64,0x0c,0x50,0x0c,0x3c,0x0c, 0x28,0x0c,0x14,0x0b,0xff,0x0b,0xeb,0x0b,0xd6,0x0b,0xc1,0x0b,0xac,0x0b,0x96,0x0b, 0x81,0x0b,0x6b,0x0b,0x55,0x0b,0x3f,0x0b,0x29,0x0b,0x12,0x0a,0xfc,0x0a,0xe5,0x0a, 0xce,0x0a,0xb6,0x0a,0x9e,0x0a,0x87,0x0a,0x6e,0x0a,0x56,0x0a,0x3d,0x0a,0x24,0x0a, 0x0b,0x09,0xf1,0x09,0xd8,0x09,0xbd,0x09,0xa3,0x09,0x88,0x09,0x6d,0x09,0x51,0x09, 0x35,0x09,0x19,0x08,0xfc,0x08,0xdf,0x08,0xc1,0x08,0xa3,0x08,0x84,0x08,0x65,0x08, 0x45,0x08,0x24,0x08,0x03,0x07,0xe1,0x07,0xbe,0x07,0x9b,0x07,0x78,0x07,0x53,0x07, 0x2d,0x07,0x07,0x06,0xdf,0x06,0xb7,0x06,0x8d,0x06,0x62,0x06,0x36,0x06,0x07,0x05, 0xd8,0x05,0xa6,0x05,0x72,0x05,0x3c,0x04,0xfc,0x04,0x7c,0x03,0xfc,0x03,0x7c,0x02, 0xfc,0x02,0x7c,0x01,0xfc,0x01,0x7c,0x00,0xfc,0x00,0x7c,0x00,0x00,0x0f,0xfe,0x0f, 0xe1,0x0f,0xd3,0x0f,0xc4,0x0f,0xb5,0x0f,0xa6,0x0f,0x97,0x0f,0x88,0x0f,0x79,0x0f, 0x6a,0x0f,0x5b,0x0f,0x4b,0x0f,0x3c,0x0f,0x2c,0x0f,0x1d,0x0f,0x0d,0x0e,0xfe,0x0e, 0xee,0x0e,0xde,0x0e,0xce,0x0e,0xbe,0x0e,0xae,0x0e,0x9e,0x0e,0x8e,0x0e,0x7d,0x0e, 0x6d,0x0e,0x5c,0x0e,0x4c,0x0e,0x3b,0x0e,0x2a,0x0e,0x19,0x0e,0x08,0x0d,0xf7,0x0d, 0xe6,0x0d,0xd5,0x0d,0xc4,0x0d,0xb2,0x0d,0xa1,0x0d,0x8f,0x0d,0x7d,0x0d,0x6b,0x0d, 0x59,0x0d,0x47,0x0d,0x35,0x0d,0x22,0x0d,0x10,0x0c,0xfd,0x0c,0xeb,0x0c,0xd8,0x0c, 0xc5,0x0c,0xb2,0x0c,0x9e,0x0c,0x8b,0x0c,0x77,0x0c,0x64,0x0c,0x50,0x0c,0x3c,0x0c, 0x28,0x0c,0x14,0x0b,0xff,0x0b,0xeb,0x0b,0xd6,0x0b,0xc1,0x0b,0xac,0x0b,0x96,0x0b, 0x81,0x0b,0x6b,0x0b,0x55,0x0b,0x3f,0x0b,0x29,0x0b,0x12,0x0a,0xfc,0x0a,0xe5,0x0a, 0xce,0x0a,0xb6,0x0a,0x9e,0x0a,0x87,0x0a,0x6e,0x0a,0x56,0x0a,0x3d,0x0a,0x24,0x0a, 0x0b,0x09,0xf1,0x09,0xd8,0x09,0xbd,0x09,0xa3,0x09,0x88,0x09,0x6d,0x09,0x51,0x09, 0x35,0x09,0x19,0x08,0xfc,0x08,0xdf,0x08,0xc1,0x08,0xa3,0x08,0x84,0x08,0x65,0x08, 0x45,0x08,0x24,0x08,0x03,0x07,0xe1,0x07,0xbe,0x07,0x9b,0x07,0x78,0x07,0x53,0x07, 0x2d,0x07,0x07,0x06,0xdf,0x06,0xb7,0x06,0x8d,0x06,0x62,0x06,0x36,0x06,0x07,0x05, 0xd8,0x05,0xa6,0x05,0x72,0x05,0x3c,0x04,0xfc,0x04,0x7c,0x03,0xfc,0x03,0x7c,0x02, 0xfc,0x02,0x7c,0x01,0xfc,0x01,0x7c,0x00,0xfc,0x00,0x7c,0x00,0x00 }; sanei_hp_scl_set(scsi, SCL_RESERVED1, 0); /* dont know */ sanei_hp_scl_set(scsi, SCL_10952, 0); /* Calibration mode */ if ( sanei_hp_is_active_xpa (scsi) && ( (scan_mode==HP_SCANMODE_COLOR) || (scan_mode==HP_SCANMODE_GRAYSCALE)) ) { DBG (3,"program_scan_type: set tone map for active XPA\n"); sanei_hp_scl_download (scsi, SCL_10x9MATRIX_COEFF, xpa_matrix_coeff, sizeof (xpa_matrix_coeff)); sanei_hp_scl_set(scsi, SCL_MATRIX, -1); /* Set matrix coefficient */ sanei_hp_scl_download (scsi, SCL_7x12TONE_MAP, xpa_tone_map, sizeof (xpa_tone_map)); sanei_hp_scl_set(scsi, SCL_TONE_MAP, -1); /* Select tone map */ } } return SANE_STATUS_GOOD; } static SANE_Status _program_change_doc (HpOption __sane_unused__ this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData __sane_unused__ data) { int istat; DBG(2, "program_change_doc: inquire ADF ready\n"); RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_ADF_READY, &istat, 0, 0) ); if ( istat != 1 ) /* ADF not ready */ { DBG(2, "program_change_doc: ADF not ready\n"); return SANE_STATUS_INVAL; } DBG(2, "program_change_doc: inquire paper in ADF\n"); RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_ADF_BIN, &istat, 0, 0) ); if ( istat == 0 ) /* Nothing in ADF BIN */ { DBG(2, "program_change_doc: nothing in ADF BIN. Just Unload.\n"); return sanei_hp_scl_set(scsi, SCL_UNLOAD, 0); } DBG(2, "program_change_doc: Clear errors and change document.\n"); RETURN_IF_FAIL( sanei_hp_scl_clearErrors (scsi) ); RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_CHANGE_DOC, 0) ); return sanei_hp_scl_errcheck (scsi); } static SANE_Status _program_unload (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { hp_bool_t adfscan = ( sanei_hp_optset_scan_type (optset, data) == SCL_ADF_SCAN ); /* If we have an ADF, try to see if it is ready to unload */ if (adfscan) {int val; if ( sanei_hp_scl_inquire(scsi, SCL_ADF_RDY_UNLOAD, &val, 0, 0) == SANE_STATUS_GOOD ) { DBG(3, "program_unload: ADF is%sready to unload\n", val ? " " : " not "); } else { DBG(3, "program_unload: Command 'Ready to unload' not supported\n"); } } return hp_option_download(this, data, optset, scsi); } static SANE_Status _program_calibrate (HpOption __sane_unused__ this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData __sane_unused__ data) { struct passwd *pw; SANE_Status status = SANE_STATUS_GOOD; size_t calib_size; char *calib_buf; RETURN_IF_FAIL ( sanei_hp_scl_calibrate(scsi) ); /* Start calibration */ pw = getpwuid (getuid ()); /* Look if we can find our home directory */ if (!pw) return SANE_STATUS_GOOD; DBG(3, "_program_calibrate: Read calibration data\n"); RETURN_IF_FAIL ( sanei_hp_scl_upload_binary (scsi, SCL_CALIB_MAP, &calib_size, &calib_buf) ); DBG(3, "_program_calibrate: Got %lu bytes of calibration data\n", (unsigned long) calib_size); write_calib_file (calib_size, calib_buf, scsi); sanei_hp_free (calib_buf); return (status); } /* The exposure time of the HP Photosmart can be changed by overwriting * some headers of the calibration data. The scanner uses a slower stepping * speed for higher exposure times */ static SANE_Status _program_ps_exposure_time (HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { SANE_Status status = SANE_STATUS_GOOD; size_t calib_size = 0; char *calib_buf = NULL; int i; int option = hp_option_getint(this, data); static char *exposure[] = {"\x00\x64\x00\x64\x00\x64", /* 100% */ "\x00\x7d\x00\x7d\x00\x7d", /* 125% */ "\x00\x96\x00\x96\x00\x96", /* 150% */ "\x00\xaf\x00\xaf\x00\xaf", /* 175% */ "\x00\xc0\x00\xc0\x00\xc0", /* 200% */ "\x00\xe1\x00\xe1\x00\xe1", /* 225% */ "\x00\xfa\x00\xfa\x00\xfa", /* 250% */ "\x01\x13\x01\x13\x01\x13", /* 275% */ "\x01\x24\x01\x24\x01\x24", /* 300% */ "\x00\x64\x00\xc0\x01\x24"}; /* Negatives */ /* Negatives get some extra blue to penetrate the orange mask and less red to not saturate the red channel; R:G:B = 100:200:300 */ /* We dont use the 100% case. It may cause mechanical problems */ if ((option < 1) || (option > 9)) return 0; RETURN_IF_FAIL ( sanei_hp_scl_upload_binary (scsi, SCL_CALIB_MAP, &calib_size, &calib_buf) ); DBG(3, "_program_ps_exposure_time: Got %lu bytes of calibration data\n", (unsigned long) calib_size); for (i = 0; i < 6; i++) calib_buf[24 + i] = exposure[option][i]; status = sanei_hp_scl_download ( scsi, SCL_CALIB_MAP, calib_buf, (size_t)calib_size); /* see what the scanner did to our alterations */ /* * RETURN_IF_FAIL ( sanei_hp_scl_upload_binary (scsi, SCL_CALIB_MAP, * &calib_size, &calib_buf) ); * * for (i = 0; i < 9; i++) * DBG(1, ">%x ", (unsigned char) calib_buf[24 + i]); */ sanei_hp_free (calib_buf); return (status); } static SANE_Status _program_scanmode (HpOption this, HpScsi scsi, HpOptSet optset, HpData data) { enum hp_scanmode_e new_mode = hp_option_getint(this, data); int invert = 0; int fw_invert = 0; /* Flag: does firmware do inversion ? */ int is_model_4c = 0; enum hp_device_compat_e compat; hp_bool_t disable_xpa = ( sanei_hp_optset_scan_type (optset, data) != SCL_XPA_SCAN ); /* Seems that models 3c/4c/6100C invert image data at 10 bit by themself. */ /* So we must not invert it by the invert command. */ if ( (sanei_hp_device_probe (&compat,scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_4C) ) { is_model_4c = 1; DBG(3, "program_scanmode: model 3c/4c/6100C recognized\n"); } if (is_model_4c) { const HpDeviceInfo *info; int data_width; HpOption option; int is_preview = 0; /* Preview uses maximum 8 bit. So we don't need to check data width */ option = hp_optset_getByName (optset, SANE_NAME_PREVIEW); if ( option ) is_preview = hp_option_getint (option, data); info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); if ( (!is_preview) && hp_optset_isEnabled (optset, data, SANE_NAME_BIT_DEPTH, info)) { data_width = sanei_hp_optset_data_width (optset, data); if ((data_width == 10) || (data_width == 30)) { fw_invert = 1; DBG(3, "program_scanmode: firmware is doing inversion\n"); } } } /* Disabling XPA resets some settings in the scanner. */ /* Scanmode is the first we program. So set XPA prior to scanmode */ DBG(3, "program_scanmode: disable XPA = %d\n", (int)disable_xpa); sanei_hp_scl_set(scsi, SCL_XPA_DISABLE, disable_xpa); RETURN_IF_FAIL( hp_option_download(this, data, optset, scsi) ); switch (new_mode) { case HP_SCANMODE_GRAYSCALE: /* Make sure that it is not b/w. Correct data width will be set later */ RETURN_IF_FAIL( sanei_hp_scl_set(scsi, SCL_DATA_WIDTH, 8) ); invert = 1; if (fw_invert) invert = 0; /* For active XPA we use a tone map. Dont invert */ if ( (!disable_xpa) && sanei_hp_is_active_xpa (scsi) ) invert = 0; break; case HP_SCANMODE_COLOR: invert = 1; if (fw_invert) invert = 0; /* For active XPA we use a tone map. Dont invert */ if ( (!disable_xpa) && sanei_hp_is_active_xpa (scsi) ) invert = 0; break; default: break; } return sanei_hp_scl_set(scsi, SCL_INVERSE_IMAGE, invert); } static SANE_Status _program_mirror_horiz (HpOption this, HpScsi scsi, HpOptSet __sane_unused__ optset, HpData data) { int sec_dir, mirror = hp_option_getint(this, data); if ( mirror == HP_MIRROR_HORIZ_CONDITIONAL ) { RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_SECONDARY_SCANDIR, &sec_dir, 0, 0) ); mirror = (sec_dir == 1); } return sanei_hp_scl_set(scsi, SCL_MIRROR_IMAGE, mirror); } /* * Option enable predicates */ static hp_bool_t _enable_choice (HpOption this, HpOptSet optset, HpData data, const HpDeviceInfo *info) { SANE_String_Const * strlist = sanei_hp_accessor_choice_strlist((HpAccessorChoice) this->data_acsr, optset, data, info); _set_stringlist(this, data, strlist); assert(strlist[0]); return strlist[0] != 0; } #ifdef ENABLE_7x12_TONEMAPS static hp_bool_t _enable_rgb_maps (HpOption this, HpOptSet optset, HpData data, const HpDeviceInfo *info) { HpOption cgam = hp_optset_get(optset, CUSTOM_GAMMA); return (cgam && hp_option_getint(cgam, data) && sanei_hp_optset_scanmode(optset, data) == HP_SCANMODE_COLOR); } #endif static hp_bool_t _enable_mono_map (HpOption __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) { HpOption cgam = hp_optset_get(optset, CUSTOM_GAMMA); return (cgam && hp_option_getint(cgam, data) && ( sanei_hp_optset_scanmode(optset, data) != HP_SCANMODE_COLOR || ! hp_optset_getByName(optset, SANE_NAME_GAMMA_VECTOR_R) )); } static hp_bool_t _enable_rgb_matrix (HpOption __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) { HpOption type = hp_optset_get(optset, MATRIX_TYPE); return type && hp_option_getint(type, data) == HP_MATRIX_CUSTOM; } static hp_bool_t _enable_brightness (HpOption this, HpOptSet optset, HpData data, const HpDeviceInfo *info) { HpOption cgam = hp_optset_get(optset, CUSTOM_GAMMA); HpScl scl = this->descriptor->scl_command; int simulate; simulate = ( sanei_hp_device_support_get ( info->devname, scl, 0, 0 ) != SANE_STATUS_GOOD ); /* If brightness is simulated, we only do it for gray/color */ if ( simulate ) {HpOption mode = hp_optset_get(optset, SCAN_MODE); int val = hp_option_getint (mode, data); int disable; disable = (val != HP_SCANMODE_GRAYSCALE) && (val != HP_SCANMODE_COLOR); if (disable) { if ( cgam ) /* Disable custom gamma. */ { val = 0; hp_option_set (cgam, data, &val, 0); } return 0; } } return !cgam || !hp_option_getint(cgam, data); } static hp_bool_t _enable_autoback (HpOption __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) { return sanei_hp_optset_scanmode(optset, data) == HP_SCANMODE_LINEART; } static hp_bool_t _enable_custom_gamma (HpOption this, HpOptSet optset, HpData data, const HpDeviceInfo *info) { HpScl scl_tonemap = SCL_8x8TONE_MAP; int id = SCL_INQ_ID(scl_tonemap); int simulate, minval, maxval; SANE_Status status; /* Check if download type supported */ status = sanei_hp_device_support_get ( info->devname, SCL_DOWNLOAD_TYPE, &minval, &maxval); simulate = (status != SANE_STATUS_GOOD) || (id < minval) || (id > maxval); /* If custom gamma is simulated, we only do it for gray/color */ if ( simulate ) {HpOption mode = hp_optset_get(optset, SCAN_MODE); int val; if ( mode ) { val = hp_option_getint (mode, data); if ((val != HP_SCANMODE_GRAYSCALE) && (val != HP_SCANMODE_COLOR)) { val = 0; hp_option_set (this, data, &val, 0); return 0; } } } return 1; } static hp_bool_t _enable_halftone (HpOption __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) { return sanei_hp_optset_scanmode(optset, data) == HP_SCANMODE_HALFTONE; } static hp_bool_t _enable_halftonevec (HpOption __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) { if (sanei_hp_optset_scanmode(optset, data) == HP_SCANMODE_HALFTONE) { HpOption dither = hp_optset_get(optset, HALFTONE_PATTERN); return dither && hp_option_getint(dither, data) == HP_DITHER_CUSTOM; } return 0; } static hp_bool_t _enable_data_width (HpOption __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) {enum hp_scanmode_e mode; mode = sanei_hp_optset_scanmode (optset, data); return ( (mode == HP_SCANMODE_GRAYSCALE) || (mode == HP_SCANMODE_COLOR) ); } static hp_bool_t _enable_out8 (HpOption __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo *info) { if (hp_optset_isEnabled (optset, data, SANE_NAME_BIT_DEPTH, info)) { int data_width = sanei_hp_optset_data_width (optset, data); return (((data_width > 8) && (data_width <= 16)) || (data_width > 24)); } return 0; } static hp_bool_t _enable_calibrate (HpOption __sane_unused__ this, HpOptSet optset, HpData data, const HpDeviceInfo __sane_unused__ *info) { HpOption media = hp_optset_get(optset, MEDIA); /* If we dont have the media button, we should have calibrate */ if ( !media ) return 1; return hp_option_getint(media, data) == HP_MEDIA_PRINT; } static SANE_Status hp_download_calib_file (HpScsi scsi) { int nbytes; char *calib_data; SANE_Status status; RETURN_IF_FAIL ( read_calib_file ( &nbytes, &calib_data, scsi ) ); DBG(3, "hp_download_calib_file: Got %d bytes calibration data\n", nbytes); status = sanei_hp_scl_download ( scsi, SCL_CALIB_MAP, calib_data, (size_t) nbytes); sanei_hp_free ( calib_data ); DBG(3, "hp_download_calib_file: download %s\n", (status == SANE_STATUS_GOOD) ? "successful" : "failed"); return status; } /* * The actual option descriptors. */ #if (defined(__IBMC__) || defined(__IBMCPP__)) #ifndef _AIX #define INT INT #endif #endif #define SCANNER_OPTION(name,type,unit) \ PASTE(SANE_NAME_,name), \ PASTE(SANE_TITLE_,name), \ PASTE(SANE_DESC_,name), \ PASTE(SANE_TYPE_,type), \ PASTE(SANE_UNIT_,unit), \ SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT #define CONSTANT_OPTION(name,type,unit) \ PASTE(SANE_NAME_,name), \ PASTE(SANE_TITLE_,name), \ PASTE(SANE_DESC_,name), \ PASTE(SANE_TYPE_,type), \ PASTE(SANE_UNIT_,unit), \ SANE_CAP_SOFT_DETECT #define INTERNAL_OPTION(name,type,unit) \ PASTE(HP_NAME_,name), "", "", \ PASTE(SANE_TYPE_,type), \ PASTE(SANE_UNIT_,unit), \ SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT #define OPTION_GROUP(name) "", name, "", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0 #define ADVANCED_GROUP(name) \ "", name, "", SANE_TYPE_GROUP, SANE_UNIT_NONE, SANE_CAP_ADVANCED #define REQUIRES(req) req #define NO_REQUIRES REQUIRES(0) static const struct hp_option_descriptor_s NUM_OPTIONS[1] = {{ CONSTANT_OPTION(NUM_OPTIONS, INT, NONE), NO_REQUIRES, _probe_num_options, 0,0,0,0,0,0,0,0,0,0,0,0 /* for gcc-s sake */ }}; static const struct hp_option_descriptor_s SCAN_MODE_GROUP[1] = {{ OPTION_GROUP(SANE_I18N("Scan Mode")), 0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* for gcc-s sake */ }}; /* Preview stuff */ static const struct hp_option_descriptor_s PREVIEW_MODE[1] = {{ SCANNER_OPTION(PREVIEW, BOOL, NONE), NO_REQUIRES, _probe_bool, 0,0,0,0,0,0,0,0,0,0,0,0 /* for gcc-s sake */ }}; static const struct hp_choice_s _scanmode_choices[] = { { HP_SCANMODE_LINEART, SANE_VALUE_SCAN_MODE_LINEART, 0, 0, 0 }, { HP_SCANMODE_HALFTONE, SANE_VALUE_SCAN_MODE_HALFTONE, 0, 0, 0 }, { HP_SCANMODE_GRAYSCALE, SANE_VALUE_SCAN_MODE_GRAY, 0, 0, 0 }, { HP_SCANMODE_COLOR, SANE_VALUE_SCAN_MODE_COLOR, 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s SCAN_MODE[1] = {{ SCANNER_OPTION(SCAN_MODE, STRING, NONE), NO_REQUIRES, _probe_each_choice, _program_scanmode, 0, 1, 1, 1, 0, 0, SCL_OUTPUT_DATA_TYPE, 0, 0, 0, _scanmode_choices }}; static const struct hp_option_descriptor_s SCAN_RESOLUTION[1] = {{ SCANNER_OPTION(SCAN_RESOLUTION, INT, DPI), NO_REQUIRES, _probe_resolution, _program_resolution, 0, 0, 1, 0, 0, 1, SCL_X_RESOLUTION, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s DEVPIX_RESOLUTION[1] = {{ INTERNAL_OPTION(DEVPIX_RESOLUTION, INT, DPI), NO_REQUIRES, _probe_devpix, 0, 0, 0, 0, 0, 0, 1, SCL_DEVPIX_RESOLUTION, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s ENHANCEMENT_GROUP[1] = {{ OPTION_GROUP(SANE_I18N("Enhancement")), 0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* for gcc-s sake */ }}; static const struct hp_option_descriptor_s BRIGHTNESS[1] = {{ SCANNER_OPTION(BRIGHTNESS, INT, NONE), NO_REQUIRES, _probe_int_brightness, _program_generic_simulate, _enable_brightness, 0, 0, 0, 0, 0, SCL_BRIGHTNESS, -127, 127, 0, 0 }}; static const struct hp_option_descriptor_s CONTRAST[1] = {{ SCANNER_OPTION(CONTRAST, INT, NONE), NO_REQUIRES, _probe_int_brightness, _program_generic_simulate, _enable_brightness, 0, 0, 0, 0, 0, SCL_CONTRAST, -127, 127, 0, 0 }}; #ifdef SCL_SHARPENING static const struct hp_option_descriptor_s SHARPENING[1] = {{ SCANNER_OPTION(SHARPENING, INT, NONE), NO_REQUIRES, _probe_int, _program_generic, 0, 0, 0, 0, 0, 0, SCL_SHARPENING, -127, 127, 0, 0 }}; #endif static const struct hp_option_descriptor_s AUTO_THRESHOLD[1] = {{ SCANNER_OPTION(AUTO_THRESHOLD, BOOL, NONE), NO_REQUIRES, _probe_bool, _program_generic, _enable_autoback, 0, 0, 0, 0, 0, SCL_AUTO_BKGRND, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s ADVANCED_GROUP[1] = {{ ADVANCED_GROUP(SANE_I18N("Advanced Options")), 0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* for gcc-s sake */ }}; /* FIXME: make this a choice? (BW or RGB custom) */ static const struct hp_option_descriptor_s CUSTOM_GAMMA[1] = {{ SCANNER_OPTION(CUSTOM_GAMMA, BOOL, NONE), NO_REQUIRES, _probe_custom_gamma, _program_tonemap, _enable_custom_gamma, 1, 0, 0, 0, 0, SCL_TONE_MAP, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s GAMMA_VECTOR_8x8[1] = {{ SCANNER_OPTION(GAMMA_VECTOR, FIXED, NONE), NO_REQUIRES, _probe_gamma_vector, 0, _enable_mono_map, 0, 0, 0, 0, 0, SCL_8x8TONE_MAP, 0, 0, 0, 0 }}; #ifdef ENABLE_7x12_TONEMAPS static const struct hp_option_descriptor_s GAMMA_VECTOR_7x12[1] = {{ SCANNER_OPTION(GAMMA_VECTOR, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_PS | HP_COMPAT_6200C |HP_COMPAT_5200C|HP_COMPAT_6300C), _probe_gamma_vector, 0, _enable_mono_map, 0, 0, 0, 0, 0, SCL_BW7x12TONE_MAP, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s RGB_TONEMAP[1] = {{ INTERNAL_OPTION(RGB_TONEMAP, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_PS | HP_COMPAT_6200C |HP_COMPAT_5200C|HP_COMPAT_6300C), _probe_gamma_vector, 0, 0, 0, 0, 0, 0, 0, SCL_7x12TONE_MAP, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s GAMMA_VECTOR_R[1] = {{ SCANNER_OPTION(GAMMA_VECTOR_R, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_PS | HP_COMPAT_6200C |HP_COMPAT_5200C|HP_COMPAT_6300C), _probe_gamma_vector, 0, _enable_rgb_maps, 0,0,0,0,0,0,0,0,0,0 }}; static const struct hp_option_descriptor_s GAMMA_VECTOR_G[1] = {{ SCANNER_OPTION(GAMMA_VECTOR_G, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_PS | HP_COMPAT_6200C |HP_COMPAT_5200C|HP_COMPAT_6300C), _probe_gamma_vector, 0, _enable_rgb_maps, 0,0,0,0,0,0,0,0,0,0 }}; static const struct hp_option_descriptor_s GAMMA_VECTOR_B[1] = {{ SCANNER_OPTION(GAMMA_VECTOR_B, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_PS | HP_COMPAT_6200C |HP_COMPAT_5200C|HP_COMPAT_6300C), _probe_gamma_vector, 0, _enable_rgb_maps, 0,0,0,0,0,0,0,0,0,0 }}; #endif static const struct hp_choice_s _halftone_choices[] = { { HP_DITHER_COARSE, SANE_I18N("Coarse"), 0, 0, 0 }, { HP_DITHER_FINE, SANE_I18N("Fine"), 0, 0, 0 }, { HP_DITHER_BAYER, SANE_I18N("Bayer"), 0, 0, 0 }, { HP_DITHER_VERTICAL, SANE_I18N("Vertical"), 0, 0, 0 }, { HP_DITHER_HORIZONTAL, SANE_I18N("Horizontal"), 0, 1, 0 }, { HP_DITHER_CUSTOM, SANE_I18N("Custom"), 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s HALFTONE_PATTERN[1] = {{ SCANNER_OPTION(HALFTONE_PATTERN, STRING, NONE), NO_REQUIRES, _probe_each_choice, _program_dither, _enable_halftone, 1, 0, 0, 0, 0, SCL_BW_DITHER, 0, 0, 0, _halftone_choices }}; /* FIXME: Halftone dimension? */ #ifdef ENABLE_16X16_DITHERS static const struct hp_option_descriptor_s HALFTONE_PATTERN_16x16[1] = {{ SCANNER_OPTION(HALFTONE_PATTERN, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_4P | HP_COMPAT_4C | HP_COMPAT_5100C | HP_COMPAT_6200C | HP_COMPAT_5200C | HP_COMPAT_6300C), _probe_horiz_dither, 0, _enable_halftonevec, 0, 0, 0, 0, 0, SCL_BW16x16DITHER }}; static const struct hp_option_descriptor_s HORIZONTAL_DITHER_16x16[1] = {{ INTERNAL_OPTION(HORIZONTAL_DITHER, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_4P | HP_COMPAT_4C | HP_COMPAT_5100C | HP_COMPAT_6200C | HP_COMPAT_5200C | HP_COMPAT_6300C), _probe_horiz_dither, 0, 0, 0, 0, 0, 0, 0, SCL_BW16x16DITHER }}; #endif static const struct hp_option_descriptor_s HALFTONE_PATTERN_8x8[1] = {{ SCANNER_OPTION(HALFTONE_PATTERN, FIXED, NONE), NO_REQUIRES, _probe_horiz_dither, 0, _enable_halftonevec, 0, 0, 0, 0, 0, SCL_BW8x8DITHER, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s HORIZONTAL_DITHER_8x8[1] = {{ INTERNAL_OPTION(HORIZONTAL_DITHER, FIXED, NONE), NO_REQUIRES, _probe_horiz_dither, 0, 0, 0, 0, 0, 0, 0, SCL_BW8x8DITHER, 0, 0, 0, 0 }}; static const struct hp_choice_s _matrix_choices[] = { { HP_MATRIX_AUTO, SANE_I18N("Auto"), 0, 1, 0 }, { HP_MATRIX_RGB, SANE_I18N("NTSC RGB"), _cenable_incolor, 0, 0 }, { HP_MATRIX_XPA_RGB, SANE_I18N("XPA RGB"), _cenable_incolor, 0, 0 }, { HP_MATRIX_PASS, SANE_I18N("Pass-through"), _cenable_incolor, 0, 0 }, { HP_MATRIX_BW, SANE_I18N("NTSC Gray"), _cenable_notcolor, 0, 0 }, { HP_MATRIX_XPA_BW, SANE_I18N("XPA Gray"), _cenable_notcolor, 0, 0 }, { HP_MATRIX_RED, SANE_I18N("Red"), _cenable_notcolor, 0, 0 }, { HP_MATRIX_GREEN, SANE_I18N("Green"), _cenable_notcolor, 1, 0 }, { HP_MATRIX_BLUE, SANE_I18N("Blue"), _cenable_notcolor, 0, 0 }, #ifdef ENABLE_CUSTOM_MATRIX { HP_MATRIX_CUSTOM, SANE_I18N("Custom"), 0, 0, 0 }, #endif { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s MATRIX_TYPE[1] = {{ SCANNER_OPTION(MATRIX_TYPE, STRING, NONE), NO_REQUIRES, _probe_each_choice, _program_matrix, _enable_choice, 1, 0, 0, 0, 0, SCL_MATRIX, 0, 0, 0, _matrix_choices }}; static const struct hp_option_descriptor_s MATRIX_RGB[1] = {{ SCANNER_OPTION(MATRIX_RGB, FIXED, NONE), NO_REQUIRES, _probe_matrix, 0, _enable_rgb_matrix, 0, 0, 0, 0, 0, SCL_8x9MATRIX_COEFF, 0, 0, 0, 0 }}; #ifdef FAKE_COLORSEP_MATRIXES static const struct hp_option_descriptor_s SEPMATRIX[1] = {{ INTERNAL_OPTION(SEPMATRIX, FIXED, NONE), NO_REQUIRES, _probe_vector, 0, 0, 0, 0, 0, 0, 0, SCL_8x9MATRIX_COEFF, 0, 0, 0, 0 }}; #endif #ifdef ENABLE_10BIT_MATRIXES static const struct hp_option_descriptor_s MATRIX_RGB10[1] = {{ SCANNER_OPTION(MATRIX_RGB, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_6200C | HP_COMPAT_5200C | HP_COMPAT_6300C), _probe_matrix, 0, _enable_rgb_matrix, 0, 0, 0, 0, 0, SCL_10x9MATRIX_COEFF, 0, 0, 0, 0 }}; #endif #ifdef NotYetSupported static const struct hp_option_descriptor_s BWMATRIX_GRAY10[1] = {{ SCANNER_OPTION(MATRIX_GRAY, FIXED, NONE), REQUIRES(HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_6200C | HP_COMPAT_5200C | HP_COMPAT_6300C), _probe_matrix, 0, _enable_gray_matrix, 0, 0, 0, 0, 0, SCL_10x3MATRIX_COEFF, 0, 0, 0, 0 }}; #endif static const struct hp_choice_s _scan_speed_choices[] = { { 0, SANE_I18N("Auto"), 0, 0, 0 }, { 1, SANE_I18N("Slow"), 0, 0, 0 }, { 2, SANE_I18N("Normal"), 0, 0, 0 }, { 3, SANE_I18N("Fast"), 0, 0, 0 }, { 4, SANE_I18N("Extra Fast"), 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s SCAN_SPEED[1] = {{ SCANNER_OPTION(SCAN_SPEED, STRING, NONE), NO_REQUIRES, _probe_each_choice, _program_generic, 0, 0, 0, 0, 0, 1, SCL_SPEED, 0, 0, 0, _scan_speed_choices }}; static const struct hp_choice_s _smoothing_choices[] = { { 0, SANE_I18N("Auto"), 0, 0, 0 }, { 3, SANE_I18N("Off"), 0, 0, 0 }, { 1, SANE_I18N("2-pixel"), 0, 0, 0 }, { 2, SANE_I18N("4-pixel"), 0, 0, 0 }, { 4, SANE_I18N("8-pixel"), 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s SMOOTHING[1] = {{ SCANNER_OPTION(SMOOTHING, STRING, NONE), NO_REQUIRES, _probe_each_choice, _program_generic, 0, 0, 0, 0, 0, 0, SCL_FILTER, 0, 0, 0, _smoothing_choices }}; static const struct hp_choice_s _media_choices[] = { { HP_MEDIA_PRINT, SANE_I18N("Print"), 0, 0, 0 }, { HP_MEDIA_SLIDE, SANE_I18N("Slide"), 0, 0, 0 }, { HP_MEDIA_NEGATIVE, SANE_I18N("Film-strip"), 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s MEDIA[1] = {{ SCANNER_OPTION(MEDIA, STRING, NONE), NO_REQUIRES, _probe_choice, _program_media, 0, 1, 1, 1, 1, 0, SCL_MEDIA, 0, 0, 0, _media_choices }}; static const struct hp_choice_s _data_widths[] = { {1, "1", 0, 0, 0}, {8, "8", 0, 0, 0}, {10, "10", 0, 0, 0}, {12, "12", 0, 0, 0}, {14, "14", 0, 0, 0}, {16, "16", 0, 0, 0}, {0, 0, 0, 0, 0} }; static const struct hp_option_descriptor_s BIT_DEPTH[1] = {{ SCANNER_OPTION(BIT_DEPTH, STRING, NONE), NO_REQUIRES, _probe_choice, _program_data_width, _enable_data_width, 1, 1, 1, 0, 1, SCL_DATA_WIDTH, 0, 0, 0, _data_widths }}; static const struct hp_option_descriptor_s OUT8[1] = { { SCANNER_OPTION(OUTPUT_8BIT, BOOL, NONE), NO_REQUIRES, /* enum hp_device_compat_e requires */ _probe_bool, /* SANE_Status (*probe)() */ 0, /* SANE_Status (*program)() */ _enable_out8, /* hp_bool_t (*enable)() */ 0, /* hp_bool_t has_global_effect */ 0, /* hp_bool_t affects_scan_params */ 0, /* hp_bool_t program_immediate */ 0, /* hp_bool_t suppress_for_scan */ 0, /* hp_bool_t may_change */ 0, /* HpScl scl_command */ 0, /* int minval */ 0, /* int maxval */ 0, /* int startval */ 0 /* HpChoice choices */ } }; /* The 100% setting may cause problems within the scanner */ static const struct hp_choice_s _ps_exposure_times[] = { /* {0, "100%", 0, 0, 0}, */ { 0, SANE_I18N("Default"), 0, 0, 0 }, {1, "125%", 0, 0, 0}, {2, "150%", 0, 0, 0}, {3, "175%", 0, 0, 0}, {4, "200%", 0, 0, 0}, {5, "225%", 0, 0, 0}, {6, "250%", 0, 0, 0}, {7, "275%", 0, 0, 0}, {8, "300%", 0, 0, 0}, {9, SANE_I18N("Negative"), 0, 0, 0}, {0, 0, 0, 0, 0} }; /* Photosmart exposure time */ static const struct hp_option_descriptor_s PS_EXPOSURE_TIME[1] = {{ SCANNER_OPTION(PS_EXPOSURE_TIME, STRING, NONE), REQUIRES( HP_COMPAT_PS ), _probe_ps_exposure_time, _program_ps_exposure_time, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _ps_exposure_times }}; /* Normal, ADF or XPA scanning. Because scanning from ADF can change */ /* the extent of the scanning area, this option is marked to change */ /* global settings. The user should switch to ADF scanning after */ /* placing paper in the ADF. */ static const struct hp_choice_s _scan_types[] = { { HP_SCANTYPE_NORMAL, SANE_I18N("Normal"), 0, 0, 0 }, { HP_SCANTYPE_ADF, SANE_I18N("ADF"), 0, 0, 0 }, { HP_SCANTYPE_XPA, SANE_I18N("XPA"), 0, 0, 0 }, {0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s SCAN_SOURCE[1] = {{ SCANNER_OPTION(SCAN_SOURCE, STRING, NONE), NO_REQUIRES, _probe_scan_type, _program_scan_type, 0, 1, 1, 1, 0, 0, SCL_START_SCAN, 0, 0, 0, _scan_types }}; /* Unload after is only necessary for PhotoScanner */ static const struct hp_option_descriptor_s UNLOAD_AFTER_SCAN[1] = {{ SCANNER_OPTION(UNLOAD_AFTER_SCAN, BOOL, NONE), REQUIRES(HP_COMPAT_PS), _probe_bool, _program_unload_after_scan, 0, 0, 0, 0, 1, 0, SCL_UNLOAD, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s CHANGE_DOC[1] = {{ SCANNER_OPTION(CHANGE_DOC, BUTTON, NONE), NO_REQUIRES, _probe_change_doc, _program_change_doc, 0, 1, 1, 1, 1, 0, SCL_CHANGE_DOC, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s UNLOAD[1] = {{ SCANNER_OPTION(UNLOAD, BUTTON, NONE), NO_REQUIRES, _probe_unload, _program_unload, 0, 0, 0, 1, 1, 0, SCL_UNLOAD, 0, 0, 0, 0 }}; /* There is no inquire ID-for the calibrate command. */ /* So here we need the requiries. */ static const struct hp_option_descriptor_s CALIBRATE[1] = {{ SCANNER_OPTION(CALIBRATE, BUTTON, NONE), REQUIRES(HP_COMPAT_PS), _probe_calibrate, _program_calibrate, _enable_calibrate, 0, 0, 1, 1, 0, SCL_CALIBRATE, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s GEOMETRY_GROUP[1] = {{ ADVANCED_GROUP(SANE_I18N("Geometry")), 0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* for gcc-s sake */ }}; static const struct hp_option_descriptor_s SCAN_TL_X[1] = {{ SCANNER_OPTION(SCAN_TL_X, FIXED, MM), NO_REQUIRES, _probe_geometry, _program_geometry, 0, 0, 1, 0, 0, 1, SCL_X_POS, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s SCAN_TL_Y[1] = {{ SCANNER_OPTION(SCAN_TL_Y, FIXED, MM), NO_REQUIRES, _probe_geometry, _program_geometry, 0, 0, 1, 0, 0, 1, SCL_Y_POS, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s SCAN_BR_X[1] = {{ SCANNER_OPTION(SCAN_BR_X, FIXED, MM), NO_REQUIRES, _probe_geometry, _program_geometry, 0, 0, 1, 0, 0, 1, SCL_X_EXTENT, 0, 0, 0, 0 }}; static const struct hp_option_descriptor_s SCAN_BR_Y[1] = {{ SCANNER_OPTION(SCAN_BR_Y, FIXED, MM), NO_REQUIRES, _probe_geometry, _program_geometry, 0, 0, 1, 0, 0, 1, SCL_Y_EXTENT, 0, 0, 0, 0 }}; static const struct hp_choice_s _mirror_horiz_choices[] = { { HP_MIRROR_HORIZ_OFF, SANE_I18N("Off"), 0, 0, 0 }, { HP_MIRROR_HORIZ_ON, SANE_I18N("On"), 0, 0, 0 }, { HP_MIRROR_HORIZ_CONDITIONAL, SANE_I18N("Conditional"), 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s MIRROR_HORIZ[1] = {{ SCANNER_OPTION(MIRROR_HORIZ, STRING, NONE), NO_REQUIRES, _probe_mirror_horiz, _program_mirror_horiz, 0, 0, 0, 0, 0, 0, SCL_MIRROR_IMAGE, 0, 0, 0, _mirror_horiz_choices }}; static const struct hp_choice_s _mirror_vert_choices[] = { { HP_MIRROR_VERT_OFF, SANE_I18N("Off"), 0, 0, 0 }, { HP_MIRROR_VERT_ON, SANE_I18N("On"), 0, 0, 0 }, { HP_MIRROR_VERT_CONDITIONAL, SANE_I18N("Conditional"), 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s MIRROR_VERT[1] = {{ SCANNER_OPTION(MIRROR_VERT, STRING, NONE), NO_REQUIRES, _probe_mirror_vert, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _mirror_vert_choices }}; static const struct hp_option_descriptor_s BUTTON_WAIT[1] = { { SCANNER_OPTION(BUTTON_WAIT, BOOL, NONE), NO_REQUIRES, /* enum hp_device_compat_e requires */ _probe_front_button, /* SANE_Status (*probe)() */ 0, /* SANE_Status (*program)() */ 0, /* hp_bool_t (*enable)() */ 0, /* hp_bool_t has_global_effect */ 0, /* hp_bool_t affects_scan_params */ 0, /* hp_bool_t program_immediate */ 0, /* hp_bool_t suppress_for_scan */ 0, /* hp_bool_t may_change */ 0, /* HpScl scl_command */ 0, /* int minval */ 0, /* int maxval */ 0, /* int startval */ 0 /* HpChoice choices */ } }; static const struct hp_option_descriptor_s LAMP_OFF[1] = { { SCANNER_OPTION(LAMP_OFF, BUTTON, NONE), /* Lamp off instruction not supported by Photosmart */ REQUIRES( HP_COMPAT_PLUS | HP_COMPAT_2C | HP_COMPAT_2P | HP_COMPAT_2CX | HP_COMPAT_4C | HP_COMPAT_3P | HP_COMPAT_4P | HP_COMPAT_5P | HP_COMPAT_5100C | HP_COMPAT_6200C | HP_COMPAT_5200C | HP_COMPAT_6300C), /* enum hp_device_compat_e requires */ _probe_bool, /* SANE_Status (*probe)() */ _program_lamp_off, /* SANE_Status (*program)() */ 0, /* hp_bool_t (*enable)() */ 0, /* hp_bool_t has_global_effect */ 0, /* hp_bool_t affects_scan_params */ 1, /* hp_bool_t program_immediate */ 1, /* hp_bool_t suppress_for_scan */ 0, /* hp_bool_t may_change */ SCL_LAMPTEST, /* HpScl scl_command */ 0, /* int minval */ 0, /* int maxval */ 0, /* int startval */ 0 /* HpChoice choices */ } }; #ifdef HP_EXPERIMENTAL static const struct hp_choice_s _range_choices[] = { { 0, "0", 0, 0, 0 }, { 1, "1", 0, 0, 0 }, { 2, "2", 0, 0, 0 }, { 3, "3", 0, 0, 0 }, { 4, "4", 0, 0, 0 }, { 5, "5", 0, 0, 0 }, { 6, "6", 0, 0, 0 }, { 7, "7", 0, 0, 0 }, { 8, "8", 0, 0, 0 }, { 9, "9", 0, 0, 0 }, { 0, 0, 0, 0, 0 } }; static const struct hp_option_descriptor_s EXPERIMENT_GROUP[1] = {{ ADVANCED_GROUP(SANE_I18N("Experiment")) 0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* for gcc-s sake */ }}; static const struct hp_option_descriptor_s PROBE_10470[1] = {{ SCANNER_OPTION(10470, STRING, NONE), NO_REQUIRES, _probe_each_choice, _program_generic, 0, 0, 0, 0, 0, 0, SCL_10470, 0, 0, 0, _range_choices }}; static const struct hp_option_descriptor_s PROBE_10485[1] = {{ SCANNER_OPTION(10485, STRING, NONE), NO_REQUIRES, _probe_each_choice, _program_generic, 0, 0, 0, 0, 0, 0, SCL_10485, 0, 0, 0, _range_choices }}; static const struct hp_option_descriptor_s PROBE_10952[1] = {{ SCANNER_OPTION(10952, STRING, NONE), NO_REQUIRES, _probe_each_choice, _program_generic, 0, 0, 0, 0, 0, 0, SCL_10952, 0, 0, 0, _range_choices }}; static const struct hp_option_descriptor_s PROBE_10967[1] = {{ SCANNER_OPTION(10967, INT, NONE), NO_REQUIRES, _probe_int, _program_generic, 0, 0, 0, 0, 0, 0, SCL_10967, 0, 0, 0, 0 }}; #endif static HpOptionDescriptor hp_options[] = { NUM_OPTIONS, SCAN_MODE_GROUP, PREVIEW_MODE, SCAN_MODE, SCAN_RESOLUTION, DEVPIX_RESOLUTION, ENHANCEMENT_GROUP, BRIGHTNESS, CONTRAST, #ifdef SCL_SHARPENING SHARPENING, #endif AUTO_THRESHOLD, ADVANCED_GROUP, CUSTOM_GAMMA, #ifdef ENABLE_7x12_TONEMAPS GAMMA_VECTOR_7x12, RGB_TONEMAP, GAMMA_VECTOR_R, GAMMA_VECTOR_G, GAMMA_VECTOR_B, #endif GAMMA_VECTOR_8x8, MATRIX_TYPE, #ifdef FAKE_COLORSEP_MATRIXES SEPMATRIX, #endif #ifdef ENABLE_10BIT_MATRIXES MATRIX_RGB10, /* FIXME: unsupported: MATRIX_GRAY10, */ #endif MATRIX_RGB, HALFTONE_PATTERN, #ifdef ENABLE_16X16_DITHERS HALFTONE_PATTERN_16x16, HORIZONTAL_DITHER_16x16, #endif HALFTONE_PATTERN_8x8, HORIZONTAL_DITHER_8x8, SCAN_SPEED, SMOOTHING, MEDIA, PS_EXPOSURE_TIME, BIT_DEPTH, OUT8, SCAN_SOURCE, BUTTON_WAIT, LAMP_OFF, UNLOAD_AFTER_SCAN, CHANGE_DOC, UNLOAD, CALIBRATE, GEOMETRY_GROUP, SCAN_TL_X, SCAN_TL_Y, SCAN_BR_X, SCAN_BR_Y, MIRROR_HORIZ, MIRROR_VERT, #ifdef HP_EXPERIMENTAL EXPERIMENT_GROUP, PROBE_10470, PROBE_10485, PROBE_10952, PROBE_10967, #endif 0 }; /* * class HpOptSet */ struct hp_optset_s { #define OPTION_LIST_MAX sizeof(hp_options)/sizeof(hp_options[0]) HpOption options[OPTION_LIST_MAX]; size_t num_sane_opts; size_t num_opts; /* Magic accessors to get coord in actual scan pixels: */ HpAccessor tl_x, tl_y, br_x, br_y; }; static HpOption hp_optset_get (HpOptSet this, HpOptionDescriptor optd) { HpOption * optp = this->options; int i = this->num_opts; while (i--) { if ((*optp)->descriptor == optd) return *optp; optp++; } return 0; } static HpOption hp_optset_getByIndex (HpOptSet this, int optnum) { if ((optnum < 0) || (optnum >= (int)this->num_sane_opts)) return 0; return this->options[optnum]; } static HpOption hp_optset_getByName (HpOptSet this, const char * name) { HpOption * optp = this->options; int i = this->num_opts; while (i--) { if (strcmp((*optp)->descriptor->name, name) == 0) return *optp; optp++; } return 0; } static _HpOption _hp_optset_get (HpOptSet this, HpOptionDescriptor opt) { /* Cast away const-ness */ return (_HpOption) hp_optset_get(this, opt); } enum hp_scanmode_e sanei_hp_optset_scanmode (HpOptSet this, HpData data) { HpOption mode = hp_optset_get(this, SCAN_MODE); assert(mode); return hp_option_getint(mode, data); } hp_bool_t sanei_hp_optset_output_8bit (HpOptSet this, HpData data) { HpOption option_out8; int out8; option_out8 = hp_optset_get(this, OUT8); if (option_out8) { out8 = hp_option_getint(option_out8, data); return out8; } return 0; } /* Returns the data width that is send to the scanner, depending */ /* on the scanmode. (b/w: 1, gray: 8..12, color: 24..36 */ int sanei_hp_optset_data_width (HpOptSet this, HpData data) { enum hp_scanmode_e mode = sanei_hp_optset_scanmode (this, data); int datawidth = 0; HpOption opt_dwidth; switch (mode) { case HP_SCANMODE_LINEART: case HP_SCANMODE_HALFTONE: datawidth = 1; break; case HP_SCANMODE_GRAYSCALE: opt_dwidth = hp_optset_get(this, BIT_DEPTH); if (opt_dwidth) datawidth = hp_option_getint (opt_dwidth, data); else datawidth = 8; break; case HP_SCANMODE_COLOR: opt_dwidth = hp_optset_get(this, BIT_DEPTH); if (opt_dwidth) datawidth = 3 * hp_option_getint (opt_dwidth, data); else datawidth = 24; break; } return datawidth; } hp_bool_t sanei_hp_optset_mirror_vert (HpOptSet this, HpData data, HpScsi scsi) { HpOption mode; int mirror, sec_dir; mode = hp_optset_get(this, MIRROR_VERT); assert(mode); mirror = hp_option_getint(mode, data); if (mirror == HP_MIRROR_VERT_CONDITIONAL) { mirror = HP_MIRROR_VERT_OFF; if ( ( sanei_hp_scl_inquire(scsi, SCL_SECONDARY_SCANDIR, &sec_dir, 0, 0) == SANE_STATUS_GOOD ) && ( sec_dir == 1 ) ) mirror = HP_MIRROR_VERT_ON; } return mirror == HP_MIRROR_VERT_ON; } hp_bool_t sanei_hp_optset_start_wait(HpOptSet this, HpData data) { HpOption mode; int wait; if ((mode = hp_optset_get(this, BUTTON_WAIT)) == 0) return(0); wait = hp_option_getint(mode, data); return(wait); } HpScl sanei_hp_optset_scan_type (HpOptSet this, HpData data) { HpOption mode; HpScl scl = SCL_START_SCAN; int scantype; mode = hp_optset_get(this, SCAN_SOURCE); if (mode) { scantype = hp_option_getint(mode, data); DBG(5, "sanei_hp_optset_scan_type: scantype=%d\n", scantype); switch (scantype) { case 1: scl = SCL_ADF_SCAN; break; case 2: scl = SCL_XPA_SCAN; break; default: scl = SCL_START_SCAN; break; } } return scl; } static void hp_optset_add (HpOptSet this, HpOption opt) { assert(this->num_opts < OPTION_LIST_MAX); /* * Keep internal options at the end of the list. */ if (hp_option_isInternal(opt)) this->options[this->num_opts] = opt; else { if (this->num_opts != this->num_sane_opts) memmove(&this->options[this->num_sane_opts + 1], &this->options[this->num_sane_opts], ( (this->num_opts - this->num_sane_opts) * sizeof(*this->options) )); this->options[this->num_sane_opts++] = opt; } this->num_opts++; } static SANE_Status hp_optset_fix_geometry_options (HpOptSet this) { _HpOption tl_x = _hp_optset_get(this, SCAN_TL_X); _HpOption tl_y = _hp_optset_get(this, SCAN_TL_Y); _HpOption br_x = _hp_optset_get(this, SCAN_BR_X); _HpOption br_y = _hp_optset_get(this, SCAN_BR_Y); HpOption scanres = hp_optset_get(this, SCAN_RESOLUTION); HpOption devpix = hp_optset_get(this, DEVPIX_RESOLUTION); HpAccessor tl_xa, tl_ya, br_xa, br_ya; assert(tl_x && tl_y && br_x && br_y); /* Geometry options missing */ tl_xa = tl_x->data_acsr; tl_ya = tl_y->data_acsr; br_xa = br_x->data_acsr; br_ya = br_y->data_acsr; assert(tl_xa && tl_ya && br_xa && br_ya); assert(scanres->data_acsr && devpix->data_acsr); /* Magic accessors that will read out in device pixels */ tl_x->data_acsr = sanei_hp_accessor_geometry_new(tl_xa, br_xa, 0, devpix->data_acsr); tl_y->data_acsr = sanei_hp_accessor_geometry_new(tl_ya, br_ya, 0, devpix->data_acsr); br_x->data_acsr = sanei_hp_accessor_geometry_new(br_xa, tl_xa, 1, devpix->data_acsr); br_y->data_acsr = sanei_hp_accessor_geometry_new(br_ya, tl_ya, 1, devpix->data_acsr); if (!tl_x->data_acsr || !tl_y->data_acsr || !br_x->data_acsr || !br_y->data_acsr) return SANE_STATUS_NO_MEM; /* Magic accessors that will read out in scan pixels */ this->tl_x = sanei_hp_accessor_geometry_new(tl_xa, br_xa, 0, scanres->data_acsr); this->tl_y = sanei_hp_accessor_geometry_new(tl_ya, br_ya, 0, scanres->data_acsr); this->br_x = sanei_hp_accessor_geometry_new(br_xa, tl_xa, 1, scanres->data_acsr); this->br_y = sanei_hp_accessor_geometry_new(br_ya, tl_ya, 1, scanres->data_acsr); if (!this->tl_x || !this->tl_y || !this->br_x || !this->br_y) return SANE_STATUS_NO_MEM; return SANE_STATUS_GOOD; } static void hp_optset_reprogram (HpOptSet this, HpData data, HpScsi scsi) { int i; DBG(5, "hp_optset_reprogram: %lu options\n", (unsigned long) this->num_opts); for (i = 0; i < (int)this->num_opts; i++) hp_option_reprogram(this->options[i], this, data, scsi); DBG(5, "hp_optset_reprogram: finished\n"); } static void hp_optset_reprobe (HpOptSet this, HpData data, HpScsi scsi) { int i; DBG(5, "hp_optset_reprobe: %lu options\n", (unsigned long) this->num_opts); for (i = 0; i < (int)this->num_opts; i++) hp_option_reprobe(this->options[i], this, data, scsi); DBG(5, "hp_optset_reprobe: finished\n"); } static void hp_optset_updateEnables (HpOptSet this, HpData data, const HpDeviceInfo *info) { int i; DBG(5, "hp_optset_updateEnables: %lu options\n", (unsigned long) this->num_opts); for (i = 0; i < (int)this->num_opts; i++) hp_option_updateEnable(this->options[i], this, data, info); } static hp_bool_t hp_optset_isEnabled (HpOptSet this, HpData data, const char *name, const HpDeviceInfo *info) { HpOption optpt; optpt = hp_optset_getByName (this, name); if (!optpt) /* Not found ? Not enabled */ return 0; if (!(optpt->descriptor->enable)) /* No enable necessary ? Enabled */ return 1; return (*optpt->descriptor->enable)(optpt, this, data, info); } /* This function is only called from sanei_hp_handle_startScan() */ SANE_Status sanei_hp_optset_download (HpOptSet this, HpData data, HpScsi scsi) { int i, errcount = 0; DBG(3, "Start downloading parameters to scanner\n"); /* Reset scanner to wake it up */ /* Reset would switch off XPA lamp and switch on scanner lamp. */ /* Only do a reset if not in active XPA mode */ if ( (sanei_hp_optset_scan_type (this, data) != SCL_XPA_SCAN) || (!sanei_hp_is_active_xpa (scsi)) ) { RETURN_IF_FAIL(sanei_hp_scl_reset (scsi)); } RETURN_IF_FAIL(sanei_hp_scl_clearErrors (scsi)); sanei_hp_device_simulate_clear ( sanei_hp_scsi_devicename (scsi) ); for (i = 0; i < (int)this->num_opts; i++) { if ( (this->options[i])->descriptor->suppress_for_scan ) { DBG(3,"sanei_hp_optset_download: %s suppressed for scan\n", (this->options[i])->descriptor->name); } else { RETURN_IF_FAIL( hp_option_program(this->options[i], scsi, this, data) ); if ( sanei_hp_scl_errcheck (scsi) != SANE_STATUS_GOOD ) { errcount++; DBG(3, "Option %s generated scanner error\n", this->options[i]->descriptor->name); RETURN_IF_FAIL(sanei_hp_scl_clearErrors (scsi)); } } } DBG(3, "Downloading parameters finished.\n"); /* Check preview */ {HpOption option; int is_preview, data_width; const HpDeviceInfo *info; option = hp_optset_getByName (this, SANE_NAME_PREVIEW); if ( option ) { is_preview = hp_option_getint (option, data); if ( is_preview ) { /* For preview we only use 8 bit per channel */ DBG(3, "sanei_hp_optset_download: Set up preview options\n"); info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); if (hp_optset_isEnabled (this, data, SANE_NAME_BIT_DEPTH, info)) { data_width = sanei_hp_optset_data_width (this, data); if (data_width > 24) { sanei_hp_scl_set(scsi, SCL_DATA_WIDTH, 24); } else if ((data_width > 8) && (data_width <= 16)) { sanei_hp_scl_set(scsi, SCL_DATA_WIDTH, 8); } } } } } return SANE_STATUS_GOOD; } SANE_Status sanei_hp_optset_new(HpOptSet * newp, HpScsi scsi, HpDevice dev) { HpOptionDescriptor * ptr; HpOptSet this = sanei_hp_allocz(sizeof(*this)); SANE_Status status; HpOption option; const HpDeviceInfo *info; if (!this) return SANE_STATUS_NO_MEM; /* FIXME: more DBG's */ for (ptr = hp_options; *ptr; ptr++) { HpOptionDescriptor desc = *ptr; DBG(8, "sanei_hp_optset_new: %s\n", desc->name); if (desc->requires && !sanei_hp_device_compat(dev, desc->requires)) continue; if (desc->type != SANE_TYPE_GROUP && hp_optset_getByName(this, desc->name)) continue; status = hp_option_descriptor_probe(desc, scsi, this, dev->data, &option); if (UNSUPPORTED(status)) continue; if (FAILED(status)) { DBG(1, "Option '%s': probe failed: %s\n", desc->name, sane_strstatus(status)); sanei_hp_free(this); return status; } hp_optset_add(this, option); } /* Set NUM_OPTIONS */ assert(this->options[0]->descriptor == NUM_OPTIONS); sanei_hp_accessor_setint(this->options[0]->data_acsr, dev->data, this->num_sane_opts); /* Now for some kludges */ status = hp_optset_fix_geometry_options(this); if (FAILED(status)) { sanei_hp_free(this); return status; } info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); hp_optset_updateEnables(this, dev->data, info); *newp = this; return SANE_STATUS_GOOD; } hp_bool_t sanei_hp_optset_isImmediate (HpOptSet this, int optnum) { HpOption opt = hp_optset_getByIndex(this, optnum); if (!opt) return 0; return hp_option_isImmediate (opt); } SANE_Status sanei_hp_optset_control (HpOptSet this, HpData data, int optnum, SANE_Action action, void * valp, SANE_Int *infop, HpScsi scsi, hp_bool_t immediate) { HpOption opt = hp_optset_getByIndex(this, optnum); SANE_Int my_info = 0, my_val = 0; DBG(3,"sanei_hp_optset_control: %s\n", opt ? opt->descriptor->name : ""); if (infop) *infop = 0; else infop = &my_info; if (!opt) return SANE_STATUS_INVAL; /* There are problems with SANE_ACTION_GET_VALUE and valp == 0. */ /* Check if we really need valp. */ if ((action == SANE_ACTION_GET_VALUE) && (!valp)) { /* Options without a value ? */ if ( (opt->descriptor->type == SANE_TYPE_BUTTON) || (opt->descriptor->type == SANE_TYPE_GROUP)) { valp = &my_val; /* Just simulate a return value locally. */ } else /* Others must return a value. So this is invalid */ { DBG(1, "sanei_hp_optset_control: get value, but valp == 0\n"); return SANE_STATUS_INVAL; } } if (immediate) RETURN_IF_FAIL( hp_option_imm_control(this, opt, data, action, valp, infop, scsi) ); else RETURN_IF_FAIL( hp_option_control(opt, data, action, valp, infop ) ); if ((*infop & SANE_INFO_RELOAD_OPTIONS) != 0) {const HpDeviceInfo *info; DBG(3,"sanei_hp_optset_control: reprobe\n"); /* At first we try to reprogram the parameters that may have changed */ /* by an option that had a global effect. This is necessary to */ /* specify options in an arbitrary order. Example: */ /* Changing scan mode resets scan resolution in the scanner. */ /* If resolution is set from the API before scan mode, we must */ /* reprogram the resolution afterwards. */ hp_optset_reprogram(this, data, scsi); hp_optset_reprobe(this, data, scsi); info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); hp_optset_updateEnables(this, data, info); } return SANE_STATUS_GOOD; } SANE_Status sanei_hp_optset_guessParameters (HpOptSet this, HpData data, SANE_Parameters * p) { /* These are magic accessors which actually get the extent, not the * absolute position... */ int xextent = sanei_hp_accessor_getint(this->br_x, data); int yextent = sanei_hp_accessor_getint(this->br_y, data); int data_width; assert(xextent > 0 && yextent > 0); p->last_frame = SANE_TRUE; p->pixels_per_line = xextent; p->lines = yextent; switch (sanei_hp_optset_scanmode(this, data)) { case HP_SCANMODE_LINEART: /* Lineart */ case HP_SCANMODE_HALFTONE: /* Halftone */ p->format = SANE_FRAME_GRAY; p->depth = 1; p->bytes_per_line = (p->pixels_per_line + 7) / 8; break; case HP_SCANMODE_GRAYSCALE: /* Grayscale */ p->format = SANE_FRAME_GRAY; p->depth = 8; p->bytes_per_line = p->pixels_per_line; if ( !sanei_hp_optset_output_8bit (this, data) ) { data_width = sanei_hp_optset_data_width (this, data); if ( data_width > 8 ) { p->depth *= 2; p->bytes_per_line *= 2; } } break; case HP_SCANMODE_COLOR: /* RGB */ p->format = SANE_FRAME_RGB; p->depth = 8; p->bytes_per_line = 3 * p->pixels_per_line; if ( !sanei_hp_optset_output_8bit (this, data) ) { data_width = sanei_hp_optset_data_width (this, data); if ( data_width > 24 ) { p->depth *= 2; p->bytes_per_line *= 2; } } break; default: assert(!"Bad scan mode?"); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sanei_hp_optset_saneoption (HpOptSet this, HpData data, int optnum) { HpOption opt = hp_optset_getByIndex(this, optnum); if (!opt) return 0; return hp_option_saneoption(opt, data); } sane-backends-1.0.27/backend/umax-usb.c0000664000175000017500000002351612112021330014506 00000000000000/* ---------------------------------------------------------------------- */ /* sane - Scanner Access Now Easy. umax-usb.c (C) 2001-2002 Frank Zago This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for UMAX USB flatbed scanners. */ /* ---------------------------------------------------------------------- */ #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_pv8630.h" /* USB specific parts */ /* Apparently this will recover from some errors. */ static void pv8630_mini_init_scanner(int fd) { DBG(DBG_info, "mini_init_scanner\n"); /* (re-)init the device (?) */ sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04 ); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02 ); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02 ); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xd0, 0xff, 1000); } /* Length of the CDB given the SCSI command. The last two are not correct (vendor reserved). */ static u_char cdb_sizes[8] = { 6, 10, 10, 6, 16, 12, 0, 0 }; #define CDB_SIZE(opcode) cdb_sizes[(((opcode) >> 5) & 7)] /* Sends a CDB to the scanner. Also sends the parameters and receives * the data, if necessary. When this function returns with a * SANE_STATUS_GOOD, the SCSI command has been completed. * * Note: I don't know about deferred commands. */ static SANE_Status sanei_umaxusb_cmd(int fd, const void *src, size_t src_size, void *dst, size_t * dst_size) { unsigned char result; size_t cmd_size = CDB_SIZE (*(const char *) src); size_t param_size = src_size - cmd_size; const char * param_ptr = ((const char *) src) + cmd_size; size_t tmp_len; DBG(DBG_info, "Sending SCSI cmd 0x%02x cdb len %ld, param len %ld, result len %ld\n", ((const unsigned char *)src)[0], (long)cmd_size, (long)param_size, dst_size? (long)*dst_size:(long)0); /* This looks like some kind of pre-initialization. */ sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x0c); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); /* Send the CDB and check it's been received OK. */ sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x16); sanei_pv8630_flush_buffer(fd); sanei_pv8630_prep_bulkwrite(fd, cmd_size); tmp_len = cmd_size; sanei_pv8630_bulkwrite(fd, src, &tmp_len); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf8, 0xff, 1000); sanei_pv8630_flush_buffer(fd); sanei_pv8630_prep_bulkread(fd, 1); result = 0xA5; /* to be sure */ tmp_len = 1; sanei_pv8630_bulkread(fd, &result, &tmp_len); if (result != 0) { DBG(DBG_info, "error in sanei_pv8630_bulkread (got %02x)\n", result); if (result == 8) { pv8630_mini_init_scanner(fd); } return(SANE_STATUS_IO_ERROR); } /* Send the parameters and check they've been received OK. */ if (param_size) { sanei_pv8630_flush_buffer(fd); sanei_pv8630_prep_bulkwrite(fd, param_size); tmp_len = param_size; sanei_pv8630_bulkwrite(fd, param_ptr, &tmp_len); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf8, 0xff, 1000); sanei_pv8630_flush_buffer(fd); sanei_pv8630_prep_bulkread(fd, 1); result = 0xA5; /* to be sure */ tmp_len = 1; sanei_pv8630_bulkread(fd, &result, &tmp_len); if (result != 0) { DBG(DBG_info, "error in sanei_pv8630_bulkread (got %02x)\n", result); if (result == 8) { pv8630_mini_init_scanner(fd); } return(SANE_STATUS_IO_ERROR); } } /* If the SCSI command expect a return, get it. */ if (dst_size != NULL && *dst_size != 0 && dst != NULL) { sanei_pv8630_flush_buffer(fd); sanei_pv8630_prep_bulkread(fd, *dst_size); sanei_pv8630_bulkread(fd, dst, dst_size); DBG(DBG_info, " SCSI cmd returned %lu bytes\n", (u_long) *dst_size); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf8, 0xff, 1000); sanei_pv8630_flush_buffer(fd); sanei_pv8630_prep_bulkread(fd, 1); result = 0x5A; /* just to be sure */ tmp_len = 1; sanei_pv8630_bulkread(fd, &result, &tmp_len); if (result != 0) { DBG(DBG_info, "error in sanei_pv8630_bulkread (got %02x)\n", result); if (result == 8) { pv8630_mini_init_scanner(fd); } return(SANE_STATUS_IO_ERROR); } } sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xd0, 0xff, 1000); DBG(DBG_info, " SCSI command successfully executed\n"); return(SANE_STATUS_GOOD); } /* Initialize the PowerVision 8630. */ static SANE_Status pv8630_init_umaxusb_scanner(int fd) { DBG(DBG_info, "Initializing the PV8630\n"); /* Init the device */ sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xd0, 0xff, 1000); sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x0c); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x0c); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf8, 0xff, 1000); sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x02); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xd0, 0xff, 1000); sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x0c); sanei_pv8630_wait_byte(fd, PV8630_RSTATUS, 0xf0, 0xff, 1000); sanei_pv8630_write_byte(fd, PV8630_UNKNOWN, 0x04); sanei_pv8630_write_byte(fd, PV8630_RMODE, 0x16); DBG(DBG_info, "PV8630 initialized\n"); return(SANE_STATUS_GOOD); } /* * SCSI functions for the emulation. * * The following functions emulate their sanei_scsi_* counterpart. * */ /* * sanei_umaxusb_req_wait() and sanei_umaxusb_req_enter() * * I don't know if it is possible to queue the reads to the * scanner. So The queing is disabled. The performance does not seems * to be bad anyway. */ static void *umaxusb_req_buffer; /* keep the buffer ptr as an ID */ static SANE_Status sanei_umaxusb_req_enter (int fd, const void *src, size_t src_size, void *dst, size_t * dst_size, void **idp) { umaxusb_req_buffer = *idp = dst; return(sanei_umaxusb_cmd(fd, src, src_size, dst, dst_size)); } static SANE_Status sanei_umaxusb_req_wait (void *id) { if (id != umaxusb_req_buffer) { DBG(DBG_info, "sanei_umaxusb_req_wait: AIE, invalid id\n"); return(SANE_STATUS_IO_ERROR); } return(SANE_STATUS_GOOD); } /* Open the device. */ static SANE_Status sanei_umaxusb_open (const char *dev, int *fdp, SANEI_SCSI_Sense_Handler handler, void *handler_arg) { SANE_Status status; handler = handler; /* silence gcc */ handler_arg = handler_arg; /* silence gcc */ status = sanei_usb_open (dev, fdp); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_umaxusb_open: open of `%s' failed: %s\n", dev, sane_strstatus(status)); return status; } else { SANE_Word vendor; SANE_Word product; /* We have openned the device. Check that it is a USB scanner. */ if (sanei_usb_get_vendor_product (*fdp, &vendor, &product) != SANE_STATUS_GOOD) { /* This is not a USB scanner, or SANE or the OS doesn't support it. */ sanei_usb_close(*fdp); *fdp = -1; return SANE_STATUS_UNSUPPORTED; } /* So it's a scanner. Does this backend support it? * Only the UMAX 2200 USB is currently supported. */ if ((vendor != 0x1606) || (product != 0x0230)) { sanei_usb_close(*fdp); *fdp = -1; return SANE_STATUS_UNSUPPORTED; } /* It's a good scanner. Initialize it. * * Note: pv8630_init_umaxusb_scanner() is for the UMAX * 2200. Other UMAX scanner might need a different * initialization routine. */ pv8630_init_umaxusb_scanner(*fdp); } return(SANE_STATUS_GOOD); } /* sanei_umaxusb_open_extended() is just a passthrough for sanei_umaxusb_open(). */ static SANE_Status sanei_umaxusb_open_extended (const char *dev, int *fdp, SANEI_SCSI_Sense_Handler handler, void *handler_arg, int *buffersize) { buffersize = buffersize; return(sanei_umaxusb_open(dev, fdp, handler, handler_arg)); } /* Close the scanner. */ static void sanei_umaxusb_close (int fd) { sanei_usb_close(fd); } sane-backends-1.0.27/backend/epsonds-io.h0000664000175000017500000000174512775312261015057 00000000000000/* * epsonds-io.h - Epson ESC/I-2 driver, low level I/O. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #ifndef epsonds_io_h #define epsonds_io_h #define USB_TIMEOUT (6 * 1000) #define USB_SHORT_TIMEOUT (1 * 800) size_t eds_send(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status, size_t reply_len); size_t eds_recv(epsonds_scanner *s, void *buf, size_t length, SANE_Status *status); SANE_Status eds_txrx(epsonds_scanner *s, char *txbuf, size_t txlen, char *rxbuf, size_t rxlen); SANE_Status eds_control(epsonds_scanner *s, void *buf, size_t buf_size); SANE_Status eds_fsy(epsonds_scanner *s); SANE_Status eds_fsx(epsonds_scanner *s); SANE_Status eds_lock(epsonds_scanner *s); #endif sane-backends-1.0.27/backend/snapscan-options.c0000664000175000017500000021076712775312261016277 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997, 1998, 2001, 2013 Franck Schnefra, Michel Roelofs, Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson, Andrew Goodbody, Oliver Schwartz and Kevin Charter This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is a component of the implementation of a backend for many of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ SANE SnapScan backend */ /* default option values */ #define DEFAULT_RES 300 #define DEFAULT_PREVIEW SANE_FALSE #define DEFAULT_HIGHQUALITY SANE_FALSE #define DEFAULT_BRIGHTNESS 0 #define DEFAULT_CONTRAST 0 #define DEFAULT_GAMMA SANE_FIX(1.8) #define DEFAULT_HALFTONE SANE_FALSE #define DEFAULT_NEGATIVE SANE_FALSE #define DEFAULT_THRESHOLD 50 #define DEFAULT_QUALITY SANE_TRUE #define DEFAULT_CUSTOM_GAMMA SANE_FALSE #define DEFAULT_GAMMA_BIND SANE_FALSE static SANE_Int def_rgb_lpr = 4; static SANE_Int def_gs_lpr = 12; static SANE_Int def_bpp = 8; static SANE_Int def_frame_no = 1; /* predefined preview mode name */ static char md_auto[] = "Auto"; /* predefined focus mode name */ static char md_manual[] = "Manual"; /* predefined scan mode names */ static char md_colour[] = SANE_VALUE_SCAN_MODE_COLOR; static char md_bilevelcolour[] = SANE_VALUE_SCAN_MODE_HALFTONE; static char md_greyscale[] = SANE_VALUE_SCAN_MODE_GRAY; static char md_lineart[] = SANE_VALUE_SCAN_MODE_LINEART; /* predefined scan source names */ static char src_flatbed[] = SANE_I18N("Flatbed"); static char src_tpo[] = SANE_I18N("Transparency Adapter"); static char src_adf[] = SANE_I18N("Document Feeder"); /* predefined scan window setting names */ static char pdw_none[] = SANE_I18N("None"); static char pdw_6X4[] = SANE_I18N("6x4 (inch)"); static char pdw_8X10[] = SANE_I18N("8x10 (inch)"); static char pdw_85X11[] = SANE_I18N("8.5x11 (inch)"); /* predefined dither matrix names */ static char dm_none[] = SANE_I18N("Halftoning Unsupported"); static char dm_dd8x8[] = SANE_I18N("DispersedDot8x8"); static char dm_dd16x16[] = SANE_I18N("DispersedDot16x16"); /* strings */ static char lpr_desc[] = SANE_I18N( "Number of scan lines to request in a SCSI read. " "Changing this parameter allows you to tune the speed at which " "data is read from the scanner during scans. If this is set too " "low, the scanner will have to stop periodically in the middle of " "a scan; if it's set too high, X-based frontends may stop responding " "to X events and your system could bog down."); static char frame_desc[] = SANE_I18N( "Frame number of media holder that should be scanned."); static char focus_mode_desc[] = SANE_I18N( "Use manual or automatic selection of focus point."); static char focus_desc[] = SANE_I18N( "Focus point for scanning."); /* ranges */ static const SANE_Range x_range_fb = { SANE_FIX (0.0), SANE_FIX (216.0), 0 }; /* mm */ static const SANE_Range y_range_fb = { SANE_FIX (0.0), SANE_FIX (297.0), 0 }; /* mm */ /* default TPO range (shortest y_range to avoid tray collision. */ static const SANE_Range x_range_tpo_default = { SANE_FIX (0.0), SANE_FIX (129.0), 0 }; /* mm */ static const SANE_Range y_range_tpo_default = { SANE_FIX (0.0), SANE_FIX (180.0), 0 }; /* mm */ /* TPO range for the Agfa 1236 */ static const SANE_Range x_range_tpo_1236 = { SANE_FIX (0.0), SANE_FIX (203.0), 0 }; /* mm */ static const SANE_Range y_range_tpo_1236 = { SANE_FIX (0.0), SANE_FIX (254.0), 0 }; /* mm */ /* TPO range for the Agfa e50 */ static const SANE_Range x_range_tpo_e50 = { SANE_FIX (0.0), SANE_FIX (40.0), 0 }; /* mm */ static const SANE_Range y_range_tpo_e50 = { SANE_FIX (0.0), SANE_FIX (240.0), 0 }; /* mm */ /* TPO range for the Epson 1670 */ static const SANE_Range x_range_tpo_1670 = { SANE_FIX (0.0), SANE_FIX (101.0), 0 }; /* mm */ static const SANE_Range y_range_tpo_1670 = { SANE_FIX (0.0), SANE_FIX (228.0), 0 }; /* mm */ /* TPO range for the Epson 2480 */ static const SANE_Range x_range_tpo_2480 = { SANE_FIX (0.0), SANE_FIX (55.0), 0 }; /* mm */ static const SANE_Range y_range_tpo_2480 = { SANE_FIX (0.0), SANE_FIX (125.0), 0 }; /* mm */ /* TPO range for the Epson 2580 */ static const SANE_Range x_range_tpo_2580 = { SANE_FIX (0.0), SANE_FIX (55.0), 0 }; /* mm */ static const SANE_Range y_range_tpo_2580 = { SANE_FIX (0.0), SANE_FIX (80.0), 0 }; /* mm */ /* TPO range for the Scanwit 2720S */ static const SANE_Range x_range_tpo_2720s = { SANE_FIX (0.0), SANE_FIX (23.6), 0 }; /* mm */ static const SANE_Range y_range_tpo_2720s = { SANE_FIX (0.0), SANE_FIX (35.7), 0 }; /* mm */ /* TPO range for the Epson 3490 */ static const SANE_Range x_range_tpo_3490 = { SANE_FIX (0.0), SANE_FIX (33.0), 0 }; /* mm */ static const SANE_Range y_range_tpo_3490 = { SANE_FIX (0.0), SANE_FIX (162.0), 0 }; /* mm */ static SANE_Range x_range_tpo; static SANE_Range y_range_tpo; static const SANE_Range gamma_range = { SANE_FIX (0.0), SANE_FIX (4.0), 0 }; static const SANE_Range gamma_vrange = { 0, 65535, 1 }; static const SANE_Range lpr_range = { 1, 50, 1 }; static const SANE_Range frame_range = { 1, 6, 1 }; static const SANE_Range focus_range = { 0, 0x300, 6 }; static const SANE_Range brightness_range = { -400 << SANE_FIXED_SCALE_SHIFT, 400 << SANE_FIXED_SCALE_SHIFT, 1 << SANE_FIXED_SCALE_SHIFT }; static const SANE_Range contrast_range = { -100 << SANE_FIXED_SCALE_SHIFT, 400 << SANE_FIXED_SCALE_SHIFT, 1 << SANE_FIXED_SCALE_SHIFT }; static const SANE_Range positive_percent_range = { 0 << SANE_FIXED_SCALE_SHIFT, 100 << SANE_FIXED_SCALE_SHIFT, 1 << SANE_FIXED_SCALE_SHIFT }; static void control_options(SnapScan_Scanner *pss); /* init_options -- initialize the option set for a scanner; expects the scanner structure's hardware configuration byte (hconfig) to be valid. ARGS: a pointer to an existing scanner structure RET: nothing SIDE: the option set of *ps is initialized; this includes both the option descriptors and the option values themselves */ static void init_options (SnapScan_Scanner * ps) { static SANE_Word resolutions_300[] = {6, 50, 75, 100, 150, 200, 300}; static SANE_Word resolutions_600[] = {8, 50, 75, 100, 150, 200, 300, 450, 600}; static SANE_Word resolutions_1200[] = {10, 50, 75, 100, 150, 200, 300, 450, 600, 900, 1200}; static SANE_Word resolutions_1200_5000e[] = {9, 50, 75, 100, 150, 200, 300, 450, 600, 1200}; static SANE_Word resolutions_1600[] = {10, 50, 75, 100, 150, 200, 300, 400, 600, 800, 1600}; static SANE_Word resolutions_2400[] = {10, 50, 75, 100, 150, 200, 300, 400, 600, 1200, 2400}; static SANE_Word resolutions_2700[] = {4, 337, 675, 1350, 2700}; static SANE_Word resolutions_3200[] = {15, 50, 150, 200, 240, 266, 300, 350, 360, 400, 600, 720, 800, 1200, 1600, 3200}; static SANE_String_Const names_all[] = {md_colour, md_bilevelcolour, md_greyscale, md_lineart, NULL}; static SANE_String_Const names_basic[] = {md_colour, md_greyscale, md_lineart, NULL}; static SANE_String_Const preview_names_all[] = {md_auto, md_colour, md_bilevelcolour, md_greyscale, md_lineart, NULL}; static SANE_String_Const preview_names_basic[] = {md_auto, md_colour, md_greyscale, md_lineart, NULL}; static SANE_String_Const focus_modes[] = {md_auto, md_manual, NULL}; static SANE_Int bit_depth_list[4]; int bit_depths; SANE_Option_Descriptor *po = ps->options; /* Initialize TPO range */ switch (ps->pdev->model) { case SNAPSCAN1236: x_range_tpo = x_range_tpo_1236; y_range_tpo = y_range_tpo_1236; break; case SNAPSCANE20: case SNAPSCANE50: case SNAPSCANE52: x_range_tpo = x_range_tpo_e50; y_range_tpo = y_range_tpo_e50; break; case PERFECTION1270: case PERFECTION1670: x_range_tpo = x_range_tpo_1670; y_range_tpo = y_range_tpo_1670; break; case PERFECTION2480: if (ps->hconfig_epson & 0x20) { x_range_tpo = x_range_tpo_2580; y_range_tpo = y_range_tpo_2580; } else { x_range_tpo = x_range_tpo_2480; y_range_tpo = y_range_tpo_2480; } break; case SCANWIT2720S: x_range_tpo = x_range_tpo_2720s; y_range_tpo = y_range_tpo_2720s; break; case PERFECTION3490: x_range_tpo = x_range_tpo_3490; y_range_tpo = y_range_tpo_3490; break; default: x_range_tpo = x_range_tpo_default; y_range_tpo = y_range_tpo_default; break; } /* Initialize option descriptors */ po[OPT_COUNT].name = SANE_NAME_NUM_OPTIONS; po[OPT_COUNT].title = SANE_TITLE_NUM_OPTIONS; po[OPT_COUNT].desc = SANE_DESC_NUM_OPTIONS; po[OPT_COUNT].type = SANE_TYPE_INT; po[OPT_COUNT].unit = SANE_UNIT_NONE; po[OPT_COUNT].size = sizeof (SANE_Word); po[OPT_COUNT].cap = SANE_CAP_SOFT_DETECT; { static SANE_Range count_range = {NUM_OPTS, NUM_OPTS, 0}; po[OPT_COUNT].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_COUNT].constraint.range = &count_range; } po[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); po[OPT_MODE_GROUP].desc = ""; po[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; po[OPT_MODE_GROUP].cap = 0; po[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; ps->res = DEFAULT_RES; po[OPT_SCANRES].name = SANE_NAME_SCAN_RESOLUTION; po[OPT_SCANRES].title = SANE_TITLE_SCAN_RESOLUTION; po[OPT_SCANRES].desc = SANE_DESC_SCAN_RESOLUTION; po[OPT_SCANRES].type = SANE_TYPE_INT; po[OPT_SCANRES].unit = SANE_UNIT_DPI; po[OPT_SCANRES].size = sizeof (SANE_Word); po[OPT_SCANRES].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; po[OPT_SCANRES].constraint_type = SANE_CONSTRAINT_WORD_LIST; switch (ps->pdev->model) { case SNAPSCAN310: case PRISA310: /* WG changed */ po[OPT_SCANRES].constraint.word_list = resolutions_300; break; case SNAPSCANE50: case SNAPSCANE52: case PRISA5300: case PRISA1240: case ARCUS1200: po[OPT_SCANRES].constraint.word_list = resolutions_1200; break; case PRISA5000E: case PRISA5000: case PRISA5150: po[OPT_SCANRES].constraint.word_list = resolutions_1200_5000e; break; case PERFECTION1670: po[OPT_SCANRES].constraint.word_list = resolutions_1600; break; case PERFECTION2480: po[OPT_SCANRES].constraint.word_list = resolutions_2400; break; case PERFECTION3490: po[OPT_SCANRES].constraint.word_list = resolutions_3200; break; case SCANWIT2720S: po[OPT_SCANRES].constraint.word_list = resolutions_2700; ps->val[OPT_SCANRES].w = 1350; ps->res = 1350; break; default: po[OPT_SCANRES].constraint.word_list = resolutions_600; break; } DBG (DL_OPTION_TRACE, "sane_init_options resolution is %d\n", ps->res); po[OPT_PREVIEW].name = SANE_NAME_PREVIEW; po[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; po[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; po[OPT_PREVIEW].type = SANE_TYPE_BOOL; po[OPT_PREVIEW].unit = SANE_UNIT_NONE; po[OPT_PREVIEW].size = sizeof (SANE_Word); po[OPT_PREVIEW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; po[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; ps->preview = DEFAULT_PREVIEW; po[OPT_HIGHQUALITY].name = "high-quality"; po[OPT_HIGHQUALITY].title = SANE_I18N("Quality scan"); po[OPT_HIGHQUALITY].desc = SANE_I18N("Highest quality but lower speed"); po[OPT_HIGHQUALITY].type = SANE_TYPE_BOOL; po[OPT_HIGHQUALITY].unit = SANE_UNIT_NONE; po[OPT_HIGHQUALITY].size = sizeof (SANE_Word); po[OPT_HIGHQUALITY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; po[OPT_HIGHQUALITY].constraint_type = SANE_CONSTRAINT_NONE; ps->highquality = DEFAULT_HIGHQUALITY; if (ps->pdev->model == PERFECTION1270) { po[OPT_HIGHQUALITY].cap |= SANE_CAP_INACTIVE; ps->val[OPT_HIGHQUALITY].b = SANE_TRUE; ps->highquality=SANE_TRUE; } po[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; po[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; po[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; po[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; po[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; po[OPT_BRIGHTNESS].size = sizeof (int); po[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; po[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_BRIGHTNESS].constraint.range = &brightness_range; ps->bright = DEFAULT_BRIGHTNESS; po[OPT_CONTRAST].name = SANE_NAME_CONTRAST; po[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; po[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; po[OPT_CONTRAST].type = SANE_TYPE_FIXED; po[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; po[OPT_CONTRAST].size = sizeof (int); po[OPT_CONTRAST].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; po[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_CONTRAST].constraint.range = &contrast_range; ps->contrast = DEFAULT_CONTRAST; po[OPT_MODE].name = SANE_NAME_SCAN_MODE; po[OPT_MODE].title = SANE_TITLE_SCAN_MODE; po[OPT_MODE].desc = SANE_DESC_SCAN_MODE; po[OPT_MODE].type = SANE_TYPE_STRING; po[OPT_MODE].unit = SANE_UNIT_NONE; po[OPT_MODE].size = 32; po[OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; po[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; switch (ps->pdev->model) { case SNAPSCAN310: case PRISA310: case PERFECTION3490: po[OPT_MODE].constraint.string_list = names_basic; break; default: po[OPT_MODE].constraint.string_list = names_all; break; } ps->mode_s = md_colour; ps->mode = MD_COLOUR; po[OPT_PREVIEW_MODE].name = "preview-mode"; po[OPT_PREVIEW_MODE].title = SANE_I18N("Preview mode"); po[OPT_PREVIEW_MODE].desc = SANE_I18N( "Select the mode for previews. Greyscale previews usually give " "the best combination of speed and detail."); po[OPT_PREVIEW_MODE].type = SANE_TYPE_STRING; po[OPT_PREVIEW_MODE].unit = SANE_UNIT_NONE; po[OPT_PREVIEW_MODE].size = 32; po[OPT_PREVIEW_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; po[OPT_PREVIEW_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; switch (ps->pdev->model) { case SNAPSCAN310: case PRISA310: case PERFECTION3490: po[OPT_PREVIEW_MODE].constraint.string_list = preview_names_basic; break; default: po[OPT_PREVIEW_MODE].constraint.string_list = preview_names_all; break; } ps->preview_mode_s = md_auto; ps->preview_mode = ps->mode; /* source */ po[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; po[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; po[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; po[OPT_SOURCE].type = SANE_TYPE_STRING; po[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC; po[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; { static SANE_String_Const source_list[3]; int i = 0; source_list[i++]= src_flatbed; if (ps->hconfig & HCFG_TPO) { source_list[i++] = src_tpo; po[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE; } if (ps->hconfig & HCFG_ADF) { source_list[i++] = src_adf; po[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE; } source_list[i] = 0; po[OPT_SOURCE].size = max_string_size(source_list); po[OPT_SOURCE].constraint.string_list = source_list; if (ps->pdev->model == SCANWIT2720S) { ps->source = SRC_TPO; ps->source_s = (SANE_Char *) strdup(src_tpo); ps->pdev->x_range.max = x_range_tpo.max; ps->pdev->y_range.max = y_range_tpo.max; } else { ps->source = SRC_FLATBED; ps->source_s = (SANE_Char *) strdup(src_flatbed); } } po[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); po[OPT_GEOMETRY_GROUP].desc = ""; po[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; po[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; po[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; po[OPT_TLX].name = SANE_NAME_SCAN_TL_X; po[OPT_TLX].title = SANE_TITLE_SCAN_TL_X; po[OPT_TLX].desc = SANE_DESC_SCAN_TL_X; po[OPT_TLX].type = SANE_TYPE_FIXED; po[OPT_TLX].unit = SANE_UNIT_MM; po[OPT_TLX].size = sizeof (SANE_Word); po[OPT_TLX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; po[OPT_TLX].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_TLX].constraint.range = &(ps->pdev->x_range); ps->tlx = ps->pdev->x_range.min; po[OPT_TLY].name = SANE_NAME_SCAN_TL_Y; po[OPT_TLY].title = SANE_TITLE_SCAN_TL_Y; po[OPT_TLY].desc = SANE_DESC_SCAN_TL_Y; po[OPT_TLY].type = SANE_TYPE_FIXED; po[OPT_TLY].unit = SANE_UNIT_MM; po[OPT_TLY].size = sizeof (SANE_Word); po[OPT_TLY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; po[OPT_TLY].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_TLY].constraint.range = &(ps->pdev->y_range); ps->tly = ps->pdev->y_range.min; po[OPT_BRX].name = SANE_NAME_SCAN_BR_X; po[OPT_BRX].title = SANE_TITLE_SCAN_BR_X; po[OPT_BRX].desc = SANE_DESC_SCAN_BR_X; po[OPT_BRX].type = SANE_TYPE_FIXED; po[OPT_BRX].unit = SANE_UNIT_MM; po[OPT_BRX].size = sizeof (SANE_Word); po[OPT_BRX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; po[OPT_BRX].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_BRX].constraint.range = &(ps->pdev->x_range); ps->brx = ps->pdev->x_range.max; po[OPT_BRY].name = SANE_NAME_SCAN_BR_Y; po[OPT_BRY].title = SANE_TITLE_SCAN_BR_Y; po[OPT_BRY].desc = SANE_DESC_SCAN_BR_Y; po[OPT_BRY].type = SANE_TYPE_FIXED; po[OPT_BRY].unit = SANE_UNIT_MM; po[OPT_BRY].size = sizeof (SANE_Word); po[OPT_BRY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC; po[OPT_BRY].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_BRY].constraint.range = &(ps->pdev->y_range); ps->bry = ps->pdev->y_range.max; po[OPT_PREDEF_WINDOW].name = "predef-window"; po[OPT_PREDEF_WINDOW].title = SANE_I18N("Predefined settings"); po[OPT_PREDEF_WINDOW].desc = SANE_I18N( "Provides standard scanning areas for photographs, printed pages " "and the like."); po[OPT_PREDEF_WINDOW].type = SANE_TYPE_STRING; po[OPT_PREDEF_WINDOW].unit = SANE_UNIT_NONE; po[OPT_PREDEF_WINDOW].size = 32; po[OPT_PREDEF_WINDOW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; { static SANE_String_Const names[] = {pdw_none, pdw_6X4, pdw_8X10, pdw_85X11, NULL}; po[OPT_PREDEF_WINDOW].constraint_type = SANE_CONSTRAINT_STRING_LIST; po[OPT_PREDEF_WINDOW].constraint.string_list = names; } ps->predef_window = pdw_none; po[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement"); po[OPT_ENHANCEMENT_GROUP].desc = ""; po[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; po[OPT_ENHANCEMENT_GROUP].cap = 0; po[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* bit depth */ po[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; po[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; po[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; po[OPT_BIT_DEPTH].type = SANE_TYPE_INT; po[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT; po[OPT_BIT_DEPTH].size = sizeof (SANE_Word); po[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; po[OPT_BIT_DEPTH].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; bit_depths = 0; bit_depth_list[++bit_depths] = def_bpp; switch (ps->pdev->model) { case PERFECTION2480: case PERFECTION3490: bit_depth_list[++bit_depths] = 16; break; case SCANWIT2720S: bit_depth_list[bit_depths] = 12; break; default: break; } bit_depth_list[0] = bit_depths; po[OPT_BIT_DEPTH].constraint.word_list = bit_depth_list; if (ps->pdev->model == SCANWIT2720S) { ps->val[OPT_BIT_DEPTH].w = 12; ps->bpp_scan = 12; } else { ps->val[OPT_BIT_DEPTH].w = def_bpp; ps->bpp_scan = def_bpp; } po[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL; po[OPT_QUALITY_CAL].title = SANE_TITLE_QUALITY_CAL; po[OPT_QUALITY_CAL].desc = SANE_DESC_QUALITY_CAL; po[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL; po[OPT_QUALITY_CAL].unit = SANE_UNIT_NONE; po[OPT_QUALITY_CAL].size = sizeof (SANE_Bool); po[OPT_QUALITY_CAL].constraint_type = SANE_CONSTRAINT_NONE; po[OPT_QUALITY_CAL].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; ps->val[OPT_QUALITY_CAL].b = DEFAULT_QUALITY; /* Disable quality calibration option if not supported Note: Snapscan e52 and Prisa5300 do not support quality calibration, although HCFG_CAL_ALLOWED is set. */ if ((!(ps->hconfig & HCFG_CAL_ALLOWED)) || (ps->pdev->model == SNAPSCANE52) || (ps->pdev->model == PERFECTION1670) || (ps->pdev->model == PRISA5150) || (ps->pdev->model == PRISA5300)) { po[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE; ps->val[OPT_QUALITY_CAL].b = SANE_FALSE; } if ((ps->pdev->model == PRISA5150) || (ps->pdev->model == STYLUS_CX1500)) { po[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE; ps->val[OPT_QUALITY_CAL].b = SANE_TRUE; } po[OPT_GAMMA_BIND].name = SANE_NAME_ANALOG_GAMMA_BIND; po[OPT_GAMMA_BIND].title = SANE_TITLE_ANALOG_GAMMA_BIND; po[OPT_GAMMA_BIND].desc = SANE_DESC_ANALOG_GAMMA_BIND; po[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL; po[OPT_GAMMA_BIND].unit = SANE_UNIT_NONE; po[OPT_GAMMA_BIND].size = sizeof (SANE_Bool); po[OPT_GAMMA_BIND].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; po[OPT_GAMMA_BIND].constraint_type = SANE_CONSTRAINT_NONE; ps->val[OPT_GAMMA_BIND].b = DEFAULT_GAMMA_BIND; po[OPT_GAMMA_GS].name = SANE_NAME_ANALOG_GAMMA; po[OPT_GAMMA_GS].title = SANE_TITLE_ANALOG_GAMMA; po[OPT_GAMMA_GS].desc = SANE_DESC_ANALOG_GAMMA; po[OPT_GAMMA_GS].type = SANE_TYPE_FIXED; po[OPT_GAMMA_GS].unit = SANE_UNIT_NONE; po[OPT_GAMMA_GS].size = sizeof (SANE_Word); po[OPT_GAMMA_GS].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; po[OPT_GAMMA_GS].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GAMMA_GS].constraint.range = &gamma_range; ps->gamma_gs = DEFAULT_GAMMA; po[OPT_GAMMA_R].name = SANE_NAME_ANALOG_GAMMA_R; po[OPT_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R; po[OPT_GAMMA_R].desc = SANE_DESC_ANALOG_GAMMA_R; po[OPT_GAMMA_R].type = SANE_TYPE_FIXED; po[OPT_GAMMA_R].unit = SANE_UNIT_NONE; po[OPT_GAMMA_R].size = sizeof (SANE_Word); po[OPT_GAMMA_R].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GAMMA_R].constraint.range = &gamma_range; ps->gamma_r = DEFAULT_GAMMA; po[OPT_GAMMA_G].name = SANE_NAME_ANALOG_GAMMA_G; po[OPT_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G; po[OPT_GAMMA_G].desc = SANE_DESC_ANALOG_GAMMA_G; po[OPT_GAMMA_G].type = SANE_TYPE_FIXED; po[OPT_GAMMA_G].unit = SANE_UNIT_NONE; po[OPT_GAMMA_G].size = sizeof (SANE_Word); po[OPT_GAMMA_G].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GAMMA_G].constraint.range = &gamma_range; ps->gamma_g = DEFAULT_GAMMA; po[OPT_GAMMA_B].name = SANE_NAME_ANALOG_GAMMA_B; po[OPT_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B; po[OPT_GAMMA_B].desc = SANE_DESC_ANALOG_GAMMA_B; po[OPT_GAMMA_B].type = SANE_TYPE_FIXED; po[OPT_GAMMA_B].unit = SANE_UNIT_NONE; po[OPT_GAMMA_B].size = sizeof (SANE_Word); po[OPT_GAMMA_B].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GAMMA_B].constraint.range = &gamma_range; ps->gamma_b = DEFAULT_GAMMA; po[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; po[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; po[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; po[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; po[OPT_CUSTOM_GAMMA].unit = SANE_UNIT_NONE; po[OPT_CUSTOM_GAMMA].size = sizeof (SANE_Bool); po[OPT_CUSTOM_GAMMA].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; ps->val[OPT_CUSTOM_GAMMA].b = DEFAULT_CUSTOM_GAMMA; po[OPT_GAMMA_VECTOR_GS].name = SANE_NAME_GAMMA_VECTOR; po[OPT_GAMMA_VECTOR_GS].title = SANE_TITLE_GAMMA_VECTOR; po[OPT_GAMMA_VECTOR_GS].desc = SANE_DESC_GAMMA_VECTOR; po[OPT_GAMMA_VECTOR_GS].type = SANE_TYPE_INT; po[OPT_GAMMA_VECTOR_GS].unit = SANE_UNIT_NONE; po[OPT_GAMMA_VECTOR_GS].size = ps->gamma_length * sizeof (SANE_Word); po[OPT_GAMMA_VECTOR_GS].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_GAMMA_VECTOR_GS].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GAMMA_VECTOR_GS].constraint.range = &gamma_vrange; ps->val[OPT_GAMMA_VECTOR_GS].wa = ps->gamma_table_gs; po[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; po[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; po[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; po[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; po[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; po[OPT_GAMMA_VECTOR_R].size = ps->gamma_length * sizeof (SANE_Word); po[OPT_GAMMA_VECTOR_R].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_vrange; ps->val[OPT_GAMMA_VECTOR_R].wa = ps->gamma_table_r; po[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; po[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; po[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; po[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; po[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; po[OPT_GAMMA_VECTOR_G].size = ps->gamma_length * sizeof (SANE_Word); po[OPT_GAMMA_VECTOR_G].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_vrange; ps->val[OPT_GAMMA_VECTOR_G].wa = ps->gamma_table_g; po[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; po[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; po[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; po[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; po[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; po[OPT_GAMMA_VECTOR_B].size = ps->gamma_length * sizeof (SANE_Word); po[OPT_GAMMA_VECTOR_B].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_vrange; ps->val[OPT_GAMMA_VECTOR_B].wa = ps->gamma_table_b; po[OPT_HALFTONE].name = SANE_NAME_HALFTONE; po[OPT_HALFTONE].title = SANE_TITLE_HALFTONE; po[OPT_HALFTONE].desc = SANE_DESC_HALFTONE; po[OPT_HALFTONE].type = SANE_TYPE_BOOL; po[OPT_HALFTONE].unit = SANE_UNIT_NONE; po[OPT_HALFTONE].size = sizeof (SANE_Bool); po[OPT_HALFTONE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_NONE; ps->halftone = DEFAULT_HALFTONE; po[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; po[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; po[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; po[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; po[OPT_HALFTONE_PATTERN].unit = SANE_UNIT_NONE; po[OPT_HALFTONE_PATTERN].size = 32; po[OPT_HALFTONE_PATTERN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; switch (ps->hconfig & HCFG_HT) { case HCFG_HT: /* both 16x16, 8x8 matrices */ { static SANE_String_Const names[] = {dm_dd8x8, dm_dd16x16, NULL}; po[OPT_HALFTONE_PATTERN].constraint.string_list = names; ps->dither_matrix = dm_dd8x8; } break; case HCFG_HT16: /* 16x16 matrices only */ { static SANE_String_Const names[] = {dm_dd16x16, NULL}; po[OPT_HALFTONE_PATTERN].constraint.string_list = names; ps->dither_matrix = dm_dd16x16; } break; case HCFG_HT8: /* 8x8 matrices only */ { static SANE_String_Const names[] = {dm_dd8x8, NULL}; po[OPT_HALFTONE_PATTERN].constraint.string_list = names; ps->dither_matrix = dm_dd8x8; } break; default: /* no halftone matrices */ { static SANE_String_Const names[] = {dm_none, NULL}; po[OPT_HALFTONE_PATTERN].constraint.string_list = names; ps->dither_matrix = dm_none; } } po[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; po[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; po[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE; po[OPT_NEGATIVE].type = SANE_TYPE_BOOL; po[OPT_NEGATIVE].unit = SANE_UNIT_NONE; po[OPT_NEGATIVE].size = sizeof (SANE_Bool); po[OPT_NEGATIVE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC; po[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE; ps->negative = DEFAULT_NEGATIVE; po[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; po[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; po[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; po[OPT_THRESHOLD].type = SANE_TYPE_FIXED; po[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; po[OPT_THRESHOLD].size = sizeof (SANE_Int); po[OPT_THRESHOLD].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_THRESHOLD].constraint.range = &positive_percent_range; ps->threshold = DEFAULT_THRESHOLD; po[OPT_FRAME_NO].name = SANE_I18N("Frame"); po[OPT_FRAME_NO].title = SANE_I18N("Frame to be scanned"); po[OPT_FRAME_NO].desc = frame_desc; po[OPT_FRAME_NO].type = SANE_TYPE_INT; po[OPT_FRAME_NO].unit = SANE_UNIT_NONE; po[OPT_FRAME_NO].size = sizeof (SANE_Int); po[OPT_FRAME_NO].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_FRAME_NO].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_FRAME_NO].constraint.range = &frame_range; ps->frame_no = def_frame_no; po[OPT_FOCUS_MODE].name = SANE_I18N("Focus-mode"); po[OPT_FOCUS_MODE].title = SANE_I18N("Auto or manual focus"); po[OPT_FOCUS_MODE].desc = focus_mode_desc; po[OPT_FOCUS_MODE].type = SANE_TYPE_STRING; po[OPT_FOCUS_MODE].unit = SANE_UNIT_NONE; po[OPT_FOCUS_MODE].size = 16; po[OPT_FOCUS_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_FOCUS_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; po[OPT_FOCUS_MODE].constraint.string_list = focus_modes; ps->focus_mode_s= md_auto; ps->focus_mode = MD_AUTO; po[OPT_FOCUS_POINT].name = SANE_I18N("Focus-point"); po[OPT_FOCUS_POINT].title = SANE_I18N("Focus point"); po[OPT_FOCUS_POINT].desc = focus_desc; po[OPT_FOCUS_POINT].type = SANE_TYPE_INT; po[OPT_FOCUS_POINT].unit = SANE_UNIT_NONE; po[OPT_FOCUS_POINT].size = sizeof (SANE_Int); po[OPT_FOCUS_POINT].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; po[OPT_FOCUS_POINT].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_FOCUS_POINT].constraint.range = &focus_range; po[OPT_ADVANCED_GROUP].title = SANE_I18N("Advanced"); po[OPT_ADVANCED_GROUP].desc = ""; po[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; po[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; po[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; po[OPT_RGB_LPR].name = "rgb-lpr"; po[OPT_RGB_LPR].title = SANE_I18N("Colour lines per read"); po[OPT_RGB_LPR].desc = lpr_desc; po[OPT_RGB_LPR].type = SANE_TYPE_INT; po[OPT_RGB_LPR].unit = SANE_UNIT_NONE; po[OPT_RGB_LPR].size = sizeof (SANE_Word); po[OPT_RGB_LPR].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; po[OPT_RGB_LPR].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_RGB_LPR].constraint.range = &lpr_range; ps->rgb_lpr = def_rgb_lpr; po[OPT_GS_LPR].name = "gs-lpr"; po[OPT_GS_LPR].title = SANE_I18N("Greyscale lines per read"); po[OPT_GS_LPR].desc = lpr_desc; po[OPT_GS_LPR].type = SANE_TYPE_INT; po[OPT_GS_LPR].unit = SANE_UNIT_NONE; po[OPT_GS_LPR].size = sizeof (SANE_Word); po[OPT_GS_LPR].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED | SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC; po[OPT_GS_LPR].constraint_type = SANE_CONSTRAINT_RANGE; po[OPT_GS_LPR].constraint.range = &lpr_range; ps->gs_lpr = def_gs_lpr; control_options(ps); } const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle h, SANE_Int n) { DBG (DL_OPTION_TRACE, "sane_snapscan_get_option_descriptor (%p, %ld)\n", (void *) h, (long) n); if ((n >= 0) && (n < NUM_OPTS)) return ((SnapScan_Scanner *) h)->options + n; return NULL; } /* Activates or deactivates options depending on mode */ static void control_options(SnapScan_Scanner *pss) { /* first deactivate all options */ pss->options[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; pss->options[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; pss->options[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_GS].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_R].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_G].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_B].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_VECTOR_GS].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; pss->options[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; if ((pss->mode == MD_COLOUR) || ((pss->mode == MD_BILEVELCOLOUR) && (pss->hconfig & HCFG_HT) && pss->halftone)) { pss->options[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; if (pss->val[OPT_CUSTOM_GAMMA].b) { if (pss->val[OPT_GAMMA_BIND].b) { pss->options[OPT_GAMMA_VECTOR_GS].cap &= ~SANE_CAP_INACTIVE; } else { pss->options[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { pss->options[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; if (pss->val[OPT_GAMMA_BIND].b) { pss->options[OPT_GAMMA_GS].cap &= ~SANE_CAP_INACTIVE; } else { pss->options[OPT_GAMMA_R].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_G].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_B].cap &= ~SANE_CAP_INACTIVE; } } } else if ((pss->mode == MD_GREYSCALE) || ((pss->mode == MD_LINEART) && (pss->hconfig & HCFG_HT) && pss->halftone)) { pss->options[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (pss->val[OPT_CUSTOM_GAMMA].b) { pss->options[OPT_GAMMA_VECTOR_GS].cap &= ~SANE_CAP_INACTIVE; } else { pss->options[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_GAMMA_GS].cap &= ~SANE_CAP_INACTIVE; } } if ((pss->mode == MD_GREYSCALE) || (pss->mode == MD_COLOUR)) { switch(pss->pdev->model) { case PERFECTION2480: case PERFECTION3490: pss->options[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; break; default: break; } } if (pss->pdev->model == SCANWIT2720S) { pss->options[OPT_FRAME_NO].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_FOCUS_MODE].cap &= ~SANE_CAP_INACTIVE; if (pss->focus_mode == MD_MANUAL) { pss->options[OPT_FOCUS_POINT].cap &= ~SANE_CAP_INACTIVE; } } } SANE_Status sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int *i) { static const char *me = "sane_snapscan_control_option"; SnapScan_Scanner *pss = h; SnapScan_Device *pdev = pss->pdev; static SANE_Status status; DBG (DL_OPTION_TRACE, "%s (%p, %ld, %ld, %p, %p)\n", me, (void *) h, (long) n, (long) a, v, (void *) i); switch (a) { case SANE_ACTION_GET_VALUE: /* prevent getting of inactive options */ if (!SANE_OPTION_IS_ACTIVE(pss->options[n].cap)) { return SANE_STATUS_INVAL; } switch (n) { case OPT_COUNT: *(SANE_Int *) v = NUM_OPTS; break; case OPT_SCANRES: *(SANE_Int *) v = pss->res; break; case OPT_PREVIEW: *(SANE_Bool *) v = pss->preview; break; case OPT_HIGHQUALITY: *(SANE_Bool *) v = pss->highquality; break; case OPT_MODE: DBG (DL_VERBOSE, "%s: writing \"%s\" to location %p\n", me, pss->mode_s, (SANE_String) v); strcpy ((SANE_String) v, pss->mode_s); break; case OPT_PREVIEW_MODE: DBG (DL_VERBOSE, "%s: writing \"%s\" to location %p\n", me, pss->preview_mode_s, (SANE_String) v); strcpy ((SANE_String) v, pss->preview_mode_s); break; case OPT_SOURCE: strcpy (v, pss->source_s); break; case OPT_TLX: *(SANE_Fixed *) v = pss->tlx; break; case OPT_TLY: *(SANE_Fixed *) v = pss->tly; break; case OPT_BRX: *(SANE_Fixed *) v = pss->brx; break; case OPT_BRY: *(SANE_Fixed *) v = pss->bry; break; case OPT_BRIGHTNESS: *(SANE_Int *) v = pss->bright << SANE_FIXED_SCALE_SHIFT; break; case OPT_CONTRAST: *(SANE_Int *) v = pss->contrast << SANE_FIXED_SCALE_SHIFT; break; case OPT_PREDEF_WINDOW: DBG (DL_VERBOSE, "%s: writing \"%s\" to location %p\n", me, pss->predef_window, (SANE_String) v); strcpy ((SANE_String) v, pss->predef_window); break; case OPT_GAMMA_GS: *(SANE_Fixed *) v = pss->gamma_gs; break; case OPT_GAMMA_R: *(SANE_Fixed *) v = pss->gamma_r; break; case OPT_GAMMA_G: *(SANE_Fixed *) v = pss->gamma_g; break; case OPT_GAMMA_B: *(SANE_Fixed *) v = pss->gamma_b; break; case OPT_CUSTOM_GAMMA: case OPT_GAMMA_BIND: case OPT_QUALITY_CAL: *(SANE_Bool *) v = pss->val[n].b; break; case OPT_GAMMA_VECTOR_GS: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (v, pss->val[n].wa, pss->options[n].size); break; case OPT_HALFTONE: *(SANE_Bool *) v = pss->halftone; break; case OPT_HALFTONE_PATTERN: DBG (DL_VERBOSE, "%s: writing \"%s\" to location %p\n", me, pss->dither_matrix, (SANE_String) v); strcpy ((SANE_String) v, pss->dither_matrix); break; case OPT_NEGATIVE: *(SANE_Bool *) v = pss->negative; break; case OPT_THRESHOLD: *(SANE_Int *) v = pss->threshold << SANE_FIXED_SCALE_SHIFT; break; case OPT_RGB_LPR: *(SANE_Int *) v = pss->rgb_lpr; break; case OPT_GS_LPR: *(SANE_Int *) v = pss->gs_lpr; break; case OPT_BIT_DEPTH: *(SANE_Int *) v = pss->val[OPT_BIT_DEPTH].w; break; case OPT_FRAME_NO: *(SANE_Int *) v = pss->frame_no; break; case OPT_FOCUS_MODE: strcpy ((SANE_String) v, pss->focus_mode_s); break; case OPT_FOCUS_POINT: *(SANE_Int *) v = pss->focus; break; default: DBG (DL_MAJOR_ERROR, "%s: invalid option number %ld\n", me, (long) n); return SANE_STATUS_UNSUPPORTED; } break; case SANE_ACTION_SET_VALUE: if (i) *i = 0; /* prevent setting of inactive options */ if ((!SANE_OPTION_IS_SETTABLE(pss->options[n].cap)) || (!SANE_OPTION_IS_ACTIVE(pss->options[n].cap))) { return SANE_STATUS_INVAL; } /* prevent setting of options during a scan */ if ((pss->state==ST_SCAN_INIT) || (pss->state==ST_SCANNING)) { DBG(DL_INFO, "set value for option %s ignored: scanner is still scanning (status %d)\n", pss->options[n].name, pss->state ); return SANE_STATUS_DEVICE_BUSY; } status = sanei_constrain_value(&pss->options[n], v, i); if (status != SANE_STATUS_GOOD) { return status; } switch (n) { case OPT_COUNT: return SANE_STATUS_UNSUPPORTED; case OPT_SCANRES: pss->res = *(SANE_Int *) v; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_PREVIEW: pss->preview = *(SANE_Bool *) v; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_HIGHQUALITY: pss->highquality = *(SANE_Bool *) v; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_MODE: { char *s = (SANE_String) v; if (strcmp (s, md_colour) == 0) { pss->mode_s = md_colour; pss->mode = MD_COLOUR; if (pss->preview_mode_s == md_auto) pss->preview_mode = MD_COLOUR; pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE; pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (s, md_bilevelcolour) == 0) { int ht_cap = pss->hconfig & HCFG_HT; pss->mode_s = md_bilevelcolour; pss->mode = MD_BILEVELCOLOUR; if (pss->preview_mode_s == md_auto) pss->preview_mode = MD_BILEVELCOLOUR; if (ht_cap) pss->options[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; if (ht_cap && pss->halftone) { pss->options[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } else { pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; } pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE; pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (s, md_greyscale) == 0) { pss->mode_s = md_greyscale; pss->mode = MD_GREYSCALE; if (pss->preview_mode_s == md_auto) pss->preview_mode = MD_GREYSCALE; pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GS_LPR].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_RGB_LPR].cap |= SANE_CAP_INACTIVE; } else if (strcmp (s, md_lineart) == 0) { int ht_cap = pss->hconfig & HCFG_HT; pss->mode_s = md_lineart; pss->mode = MD_LINEART; if (pss->preview_mode_s == md_auto) pss->preview_mode = MD_LINEART; if (ht_cap) pss->options[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; if (ht_cap && pss->halftone) { pss->options[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; } else { pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; pss->options[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } pss->options[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_GS_LPR].cap &= ~SANE_CAP_INACTIVE; pss->options[OPT_RGB_LPR].cap |= SANE_CAP_INACTIVE; } else { DBG (DL_MAJOR_ERROR, "%s: internal error: given illegal mode " "string \"%s\"\n", me, s); } } control_options (pss); if (i) *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_PREVIEW_MODE: { char *s = (SANE_String) v; if (strcmp (s, md_auto) == 0) { pss->preview_mode_s = md_auto; pss->preview_mode = pss->mode; } else if (strcmp (s, md_colour) == 0) { pss->preview_mode_s = md_colour; pss->preview_mode = MD_COLOUR; } else if (strcmp (s, md_bilevelcolour) == 0) { pss->preview_mode_s = md_bilevelcolour; pss->preview_mode = MD_BILEVELCOLOUR; } else if (strcmp (s, md_greyscale) == 0) { pss->preview_mode_s = md_greyscale; pss->preview_mode = MD_GREYSCALE; } else if (strcmp (s, md_lineart) == 0) { pss->preview_mode_s = md_lineart; pss->preview_mode = MD_LINEART; } else { DBG (DL_MAJOR_ERROR, "%s: internal error: given illegal mode string " "\"%s\"\n", me, s); } break; } case OPT_SOURCE: if (strcmp(v, src_flatbed) == 0) { pss->source = SRC_FLATBED; pss->pdev->x_range.max = x_range_fb.max; pss->pdev->y_range.max = y_range_fb.max; } else if (strcmp(v, src_tpo) == 0) { pss->source = SRC_TPO; pss->pdev->x_range.max = x_range_tpo.max; pss->pdev->y_range.max = y_range_tpo.max; } else if (strcmp(v, src_adf) == 0) { pss->source = SRC_ADF; pss->pdev->x_range.max = x_range_fb.max; pss->pdev->y_range.max = y_range_fb.max; } else { DBG (DL_MAJOR_ERROR, "%s: internal error: given illegal source string " "\"%s\"\n", me, (char *) v); } /* Adjust actual range values to new max values */ if (pss->brx > pss->pdev->x_range.max) pss->brx = pss->pdev->x_range.max; if (pss->bry > pss->pdev->y_range.max) pss->bry = pss->pdev->y_range.max; pss->predef_window = pdw_none; if (pss->source_s) free (pss->source_s); pss->source_s = (SANE_Char *) strdup(v); if (i) *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_TLX: pss->tlx = *(SANE_Fixed *) v; pss->predef_window = pdw_none; if (pss->tlx > pdev->x_range.max) { pss->tlx = pdev->x_range.max; } if (pss->brx < pss->tlx) { pss->brx = pss->tlx; } if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_TLY: pss->tly = *(SANE_Fixed *) v; pss->predef_window = pdw_none; if (pss->tly > pdev->y_range.max){ pss->tly = pdev->y_range.max; } if (pss->bry < pss->tly) { pss->bry = pss->tly; } if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BRX: pss->brx = *(SANE_Fixed *) v; pss->predef_window = pdw_none; if (pss->brx < pdev->x_range.min) { pss->brx = pdev->x_range.min; } if (pss->brx < pss->tlx) { pss->tlx = pss->brx; } if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BRY: pss->bry = *(SANE_Fixed *) v; pss->predef_window = pdw_none; if (pss->bry < pdev->y_range.min) { pss->bry = pdev->y_range.min; } if (pss->bry < pss->tly) { pss->tly = pss->bry; } if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BRIGHTNESS: pss->bright = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT; break; case OPT_CONTRAST: pss->contrast = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT; break; case OPT_PREDEF_WINDOW: { char *s = (SANE_String) v; if (strcmp (s, pdw_none) != 0) { pss->tlx = 0; pss->tly = 0; if (strcmp (s, pdw_6X4) == 0) { pss->predef_window = pdw_6X4; pss->brx = SANE_FIX (6.0*MM_PER_IN); pss->bry = SANE_FIX (4.0*MM_PER_IN); } else if (strcmp (s, pdw_8X10) == 0) { pss->predef_window = pdw_8X10; pss->brx = SANE_FIX (8.0*MM_PER_IN); pss->bry = SANE_FIX (10.0*MM_PER_IN); } else if (strcmp (s, pdw_85X11) == 0) { pss->predef_window = pdw_85X11; pss->brx = SANE_FIX (8.5*MM_PER_IN); pss->bry = SANE_FIX (11.0*MM_PER_IN); } else { DBG (DL_MAJOR_ERROR, "%s: trying to set predef window with " "garbage value.", me); pss->predef_window = pdw_none; pss->brx = SANE_FIX (6.0*MM_PER_IN); pss->bry = SANE_FIX (4.0*MM_PER_IN); } } else { pss->predef_window = pdw_none; } } if (i) *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_GAMMA_GS: pss->gamma_gs = *(SANE_Fixed *) v; break; case OPT_GAMMA_R: pss->gamma_r = *(SANE_Fixed *) v; break; case OPT_GAMMA_G: pss->gamma_g = *(SANE_Fixed *) v; break; case OPT_GAMMA_B: pss->gamma_b = *(SANE_Fixed *) v; break; case OPT_QUALITY_CAL: pss->val[n].b = *(SANE_Bool *)v; break; case OPT_CUSTOM_GAMMA: case OPT_GAMMA_BIND: { SANE_Bool b = *(SANE_Bool *) v; if (b == pss->val[n].b) { break; } pss->val[n].b = b; control_options (pss); if (i) { *i |= SANE_INFO_RELOAD_OPTIONS; } break; } case OPT_GAMMA_VECTOR_GS: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy(pss->val[n].wa, v, pss->options[n].size); break; case OPT_HALFTONE: pss->halftone = *(SANE_Bool *) v; if (pss->halftone) { switch (pss->mode) { case MD_BILEVELCOLOUR: break; case MD_LINEART: pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; break; default: break; } pss->options[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } else { pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (pss->mode == MD_LINEART) pss->options[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } control_options (pss); if (i) *i = SANE_INFO_RELOAD_OPTIONS; break; case OPT_HALFTONE_PATTERN: { char *s = (SANE_String) v; if (strcmp (s, dm_dd8x8) == 0) { pss->dither_matrix = dm_dd8x8; } else if (strcmp (s, dm_dd16x16) == 0) { pss->dither_matrix = dm_dd16x16; } else { DBG (DL_MAJOR_ERROR, "%s: internal error: given illegal halftone pattern " "string \"%s\"\n", me, s); } } break; case OPT_NEGATIVE: pss->negative = *(SANE_Bool *) v; break; case OPT_THRESHOLD: pss->threshold = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT; break; case OPT_RGB_LPR: pss->rgb_lpr = *(SANE_Int *) v; break; case OPT_GS_LPR: pss->gs_lpr = *(SANE_Int *) v; break; case OPT_BIT_DEPTH: pss->val[OPT_BIT_DEPTH].w = *(SANE_Int *) v; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_FRAME_NO: pss->frame_no = *(SANE_Int *) v; break; case OPT_FOCUS_MODE: { char *s = (SANE_String) v; if (strcmp (s, md_manual) == 0) { pss->focus_mode_s = md_manual; pss->focus_mode = MD_MANUAL; pss->options[OPT_FOCUS_POINT].cap &= ~SANE_CAP_INACTIVE; } else { pss->focus_mode_s = md_auto; pss->focus_mode = MD_AUTO; pss->options[OPT_FOCUS_POINT].cap |= SANE_CAP_INACTIVE; } if (i) *i = SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; } case OPT_FOCUS_POINT: pss->focus = *(SANE_Int *) v; break; default: DBG (DL_MAJOR_ERROR, "%s: invalid option number %ld\n", me, (long) n); return SANE_STATUS_UNSUPPORTED; } DBG (DL_OPTION_TRACE, "%s: option %s set to value ", me, pss->options[n].name); switch (pss->options[n].type) { case SANE_TYPE_INT: DBG (DL_OPTION_TRACE, "%ld\n", (long) (*(SANE_Int *) v)); break; case SANE_TYPE_BOOL: { char *valstr = (*(SANE_Bool *) v == SANE_TRUE) ? "TRUE" : "FALSE"; DBG (DL_OPTION_TRACE, "%s\n", valstr); } break; default: DBG (DL_OPTION_TRACE, "other than an integer or boolean.\n"); break; } break; case SANE_ACTION_SET_AUTO: if (i) *i = 0; switch (n) { case OPT_SCANRES: if (pss->pdev->model == SCANWIT2720S) { pss->res = 1350; } else { pss->res = 300; } if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_PREVIEW: pss->preview = SANE_FALSE; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_HIGHQUALITY: pss->highquality = SANE_FALSE; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_MODE: pss->mode_s = md_colour; pss->mode = MD_COLOUR; pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE; pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE; control_options (pss); if (i) *i = SANE_INFO_RELOAD_OPTIONS; break; case OPT_PREVIEW_MODE: pss->preview_mode_s = md_greyscale; pss->preview_mode = MD_GREYSCALE; break; case OPT_SOURCE: if (pss->pdev->model == SCANWIT2720S) { pss->source = SRC_TPO; pss->pdev->x_range.max = x_range_tpo.max; pss->pdev->y_range.max = y_range_tpo.max; pss->predef_window = pdw_none; if (pss->source_s) free (pss->source_s); pss->source_s = (SANE_Char *) strdup(src_tpo); } else { pss->source = SRC_FLATBED; pss->pdev->x_range.max = x_range_fb.max; pss->pdev->y_range.max = y_range_fb.max; pss->predef_window = pdw_none; if (pss->source_s) free (pss->source_s); pss->source_s = (SANE_Char *) strdup(src_flatbed); } if (i) *i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_TLX: pss->tlx = pss->pdev->x_range.min; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_TLY: pss->tly = pss->pdev->y_range.min; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BRX: pss->brx = pss->pdev->x_range.max; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BRY: pss->bry = pss->pdev->y_range.max; if (i) *i |= SANE_INFO_RELOAD_PARAMS; break; case OPT_NEGATIVE: pss->negative = DEFAULT_NEGATIVE; break; case OPT_RGB_LPR: pss->rgb_lpr = def_rgb_lpr; break; case OPT_GS_LPR: pss->gs_lpr = def_gs_lpr; break; case OPT_BIT_DEPTH: if (pss->pdev->model == SCANWIT2720S) { pss->val[OPT_BIT_DEPTH].w = 12; } else { pss->val[OPT_BIT_DEPTH].w = def_bpp; } break; case OPT_FRAME_NO: pss->frame_no = def_frame_no; break; case OPT_FOCUS_MODE: pss->focus_mode_s = md_auto; pss->focus_mode = MD_AUTO; if (i) *i = SANE_INFO_RELOAD_OPTIONS; break; case OPT_FOCUS_POINT: pss->focus = 0x13e; break; default: DBG (DL_MAJOR_ERROR, "%s: invalid option number %ld\n", me, (long) n); return SANE_STATUS_UNSUPPORTED; } break; default: DBG (DL_MAJOR_ERROR, "%s: invalid action code %ld\n", me, (long) a); return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; } /* * $Log$ * Revision 1.35 2006/01/06 20:59:17 oliver-guest * Some fixes for the Epson Stylus CX 1500 * * Revision 1.34 2006/01/01 22:57:01 oliver-guest * Added calibration data for Benq 5150 / 5250, preliminary support for Epson Stylus CX 1500 * * Revision 1.33 2005/12/04 15:03:00 oliver-guest * Some fixes for Benq 5150 * * Revision 1.32 2005/11/23 20:57:01 oliver-guest * Disable bilevel colour / halftoning for Epson 3490 * * Revision 1.31 2005/11/17 23:47:10 oliver-guest * Revert previous 'fix', disable 2400 dpi for Epson 3490, use 1600 dpi instead * * Revision 1.30 2005/11/15 20:11:18 oliver-guest * Enabled quality calibration for the Epson 3490 * * Revision 1.29 2005/10/31 21:08:47 oliver-guest * Distinguish between Benq 5000/5000E/5000U * * Revision 1.28 2005/10/24 19:46:40 oliver-guest * Preview and range fix for Epson 2480/2580 * * Revision 1.27 2005/10/13 22:43:30 oliver-guest * Fixes for 16 bit scan mode from Simon Munton * * Revision 1.26 2005/10/11 18:47:07 oliver-guest * Fixes for Epson 3490 and 16 bit scan mode * * Revision 1.25 2005/09/28 22:09:26 oliver-guest * Reenabled enhanced inquiry command for Epson scanners (duh\!) * * Revision 1.24 2005/09/28 21:33:10 oliver-guest * Added 16 bit option for Epson scanners (untested) * * Revision 1.23 2005/08/16 20:15:10 oliver-guest * Removed C++-style comment * * Revision 1.22 2005/08/15 18:06:37 oliver-guest * Added support for Epson 3490/3590 (thanks to Matt Judge) * * Revision 1.21 2005/07/20 21:37:29 oliver-guest * Changed TPO scanning area for 2480/2580, reenabled 2400 DPI for 2480/2580 * * Revision 1.20 2005/05/22 11:50:24 oliver-guest * Disabled 2400 DPI for Epson 2480 * * Revision 1.19 2004/12/09 23:21:47 oliver-guest * Added quality calibration for Epson 2480 (by Simon Munton) * * Revision 1.18 2004/12/01 22:12:02 oliver-guest * Added support for Epson 1270 * * Revision 1.17 2004/09/02 20:59:11 oliver-guest * Added support for Epson 2480 * * Revision 1.16 2004/04/08 21:53:10 oliver-guest * Use sanei_thread in snapscan backend * * Revision 1.15 2004/04/02 20:19:23 oliver-guest * Various bugfixes for gamma corretion (thanks to Robert Tsien) * * Revision 1.14 2004/02/01 13:32:26 oliver-guest * Fixed resolutions for Epson 1670 * * Revision 1.13 2003/11/28 23:23:18 oliver-guest * Correct length of wordlist for resolutions_1600 * * Revision 1.12 2003/11/09 21:43:45 oliver-guest * Disabled quality calibration for Epson Perfection 1670 * * Revision 1.11 2003/11/08 09:50:27 oliver-guest * Fix TPO scanning range for Epson 1670 * * Revision 1.10 2003/10/21 20:43:25 oliver-guest * Bugfixes for SnapScan backend * * Revision 1.9 2003/10/07 18:29:20 oliver-guest * Initial support for Epson 1670, minor bugfix * * Revision 1.8 2003/08/19 21:05:08 oliverschwartz * Scanner ID cleanup * * Revision 1.7 2003/04/30 20:49:39 oliverschwartz * SnapScan backend 1.4.26 * * Revision 1.8 2003/04/30 20:42:18 oliverschwartz * Added support for Agfa Arcus 1200 (supplied by Valtteri Vuorikoski) * * Revision 1.7 2003/04/02 21:17:12 oliverschwartz * Fix for 1200 DPI with Acer 5000 * * Revision 1.6 2002/07/12 23:23:06 oliverschwartz * Disable quality calibration for 5300 * * Revision 1.5 2002/06/06 20:40:00 oliverschwartz * Changed default scan area for transparancy unit of SnapScan e50 * * Revision 1.4 2002/05/02 18:28:44 oliverschwartz * Added ADF support * * Revision 1.3 2002/04/27 14:43:59 oliverschwartz * - Remove SCSI debug options * - Fix option handling (errors detected by tstbackend) * * Revision 1.2 2002/04/23 22:50:24 oliverschwartz * Improve handling of scan area options * * Revision 1.1 2002/03/24 12:07:15 oliverschwartz * Moved option functions from snapscan.c to snapscan-options.c * * * */ sane-backends-1.0.27/backend/hpsj5s.conf.in0000664000175000017500000000002612112021330015260 00000000000000#hpsj5s.conf #parport0sane-backends-1.0.27/backend/hp5590.c0000664000175000017500000012221112775312261013714 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Ilia Sotnikov HP ScanJet 4570c support by Markham Thomas This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 Scanners */ #include "../include/sane/config.h" #include #include #include #ifdef HAVE_SYS_TYPES_H #include #endif #include "../include/sane/sane.h" #define BACKEND_NAME hp5590 #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/saneopts.h" #include "hp5590_cmds.c" #include "hp5590_low.c" /* Debug levels */ #define DBG_err 0 #define DBG_proc 10 #define DBG_verbose 20 #define hp5590_assert(exp) if(!(exp)) { \ DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\ return SANE_STATUS_INVAL; \ } #define hp5590_assert_void_return(exp) if(!(exp)) { \ DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\ return; \ } /* #define HAS_WORKING_COLOR_48 */ #define BUILD 7 #define USB_TIMEOUT 30 * 1000 static SANE_Word res_list[] = { 6, 100, 200, 300, 600, 1200, 2400 }; #define SANE_VALUE_SCAN_SOURCE_FLATBED SANE_I18N("Flatbed") #define SANE_VALUE_SCAN_SOURCE_ADF SANE_I18N("ADF") #define SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX SANE_I18N("ADF Duplex") #define SANE_VALUE_SCAN_SOURCE_TMA_SLIDES SANE_I18N("TMA Slides") #define SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES SANE_I18N("TMA Negatives") #define SANE_VALUE_SCAN_MODE_COLOR_24 SANE_VALUE_SCAN_MODE_COLOR #define SANE_VALUE_SCAN_MODE_COLOR_48 SANE_I18N("Color (48 bits)") #define SANE_NAME_LAMP_TIMEOUT "extend-lamp-timeout" #define SANE_TITLE_LAMP_TIMEOUT SANE_I18N("Extend lamp timeout") #define SANE_DESC_LAMP_TIMEOUT SANE_I18N("Extends lamp timeout (from 15 minutes to 1 hour)") #define SANE_NAME_WAIT_FOR_BUTTON "wait-for-button" #define SANE_TITLE_WAIT_FOR_BUTTON SANE_I18N("Wait for button") #define SANE_DESC_WAIT_FOR_BUTTON SANE_I18N("Waits for button before scanning") #define MAX_SCAN_SOURCE_VALUE_LEN 24 #define MAX_SCAN_MODE_VALUE_LEN 24 static SANE_Range range_x, range_y, range_qual; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_COLOR_24, #ifdef HAS_WORKING_COLOR_48 SANE_VALUE_SCAN_MODE_COLOR_48, #endif /* HAS_WORKING_COLOR_48 */ SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_LINEART, NULL }; enum hp5590_opt_idx { HP5590_OPT_NUM = 0, HP5590_OPT_TL_X, HP5590_OPT_TL_Y, HP5590_OPT_BR_X, HP5590_OPT_BR_Y, HP5590_OPT_MODE, HP5590_OPT_SOURCE, HP5590_OPT_RESOLUTION, HP5590_OPT_LAMP_TIMEOUT, HP5590_OPT_WAIT_FOR_BUTTON, HP5590_OPT_PREVIEW, HP5590_OPT_LAST }; struct hp5590_scanner { struct scanner_info *info; enum proto_flags proto_flags; SANE_Device sane; SANE_Int dn; float br_x, br_y, tl_x, tl_y; unsigned int dpi; enum color_depths depth; enum scan_sources source; SANE_Bool extend_lamp_timeout; SANE_Bool wait_for_button; SANE_Bool preview; unsigned int quality; SANE_Option_Descriptor *opts; struct hp5590_scanner *next; unsigned int image_size; SANE_Int transferred_image_size; void *bulk_read_state; SANE_Bool scanning; }; static struct hp5590_scanner *scanners_list; /******************************************************************************/ static SANE_Status calc_image_params (struct hp5590_scanner *scanner, unsigned int *pixel_bits, unsigned int *pixels_per_line, unsigned int *bytes_per_line, unsigned int *lines, unsigned int *image_size) { unsigned int _pixel_bits; SANE_Status ret; unsigned int _pixels_per_line; unsigned int _bytes_per_line; unsigned int _lines; unsigned int _image_size; float var; DBG (DBG_proc, "%s\n", __func__); if (!scanner) return SANE_STATUS_INVAL; ret = hp5590_calc_pixel_bits (scanner->dpi, scanner->depth, &_pixel_bits); if (ret != SANE_STATUS_GOOD) return ret; var = (float) (1.0 * (scanner->br_x - scanner->tl_x) * scanner->dpi); _pixels_per_line = var; if (var > _pixels_per_line) _pixels_per_line++; var = (float) (1.0 * (scanner->br_y - scanner->tl_y) * scanner->dpi); _lines = var; if (var > _lines) _lines++; var = (float) (1.0 * _pixels_per_line / 8 * _pixel_bits); _bytes_per_line = var; if (var > _bytes_per_line) _bytes_per_line++; _image_size = _lines * _bytes_per_line; DBG (DBG_verbose, "%s: pixel_bits: %u, pixels_per_line: %u, " "bytes_per_line: %u, lines: %u, image_size: %u\n", __func__, _pixel_bits, _pixels_per_line, _bytes_per_line, _lines, _image_size); if (pixel_bits) *pixel_bits = _pixel_bits; if (pixels_per_line) *pixels_per_line = _pixels_per_line; if (bytes_per_line) *bytes_per_line = _bytes_per_line; if (lines) *lines = _lines; if (image_size) *image_size = _image_size; return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status attach_usb_device (SANE_String_Const devname, enum hp_scanner_types hp_scanner_type) { struct scanner_info *info; struct hp5590_scanner *scanner, *ptr; unsigned int max_count, count; SANE_Int dn; SANE_Status ret; const struct hp5590_model *hp5590_model; DBG (DBG_proc, "%s: Opening USB device\n", __func__); if (sanei_usb_open (devname, &dn) != SANE_STATUS_GOOD) return SANE_STATUS_IO_ERROR; DBG (DBG_proc, "%s: USB device opened\n", __func__); ret = hp5590_model_def (hp_scanner_type, &hp5590_model); if (ret != SANE_STATUS_GOOD) return ret; if (hp5590_init_scanner (dn, hp5590_model->proto_flags, &info, hp_scanner_type) != 0) return SANE_STATUS_IO_ERROR; DBG (1, "%s: found HP%s scanner at '%s'\n", __func__, info->model, devname); DBG (DBG_verbose, "%s: Reading max scan count\n", __func__); if (hp5590_read_max_scan_count (dn, hp5590_model->proto_flags, &max_count) != 0) return SANE_STATUS_IO_ERROR; DBG (DBG_verbose, "%s: Max Scanning count %u\n", __func__, max_count); DBG (DBG_verbose, "%s: Reading scan count\n", __func__); if (hp5590_read_scan_count (dn, hp5590_model->proto_flags, &count) != 0) return SANE_STATUS_IO_ERROR; DBG (DBG_verbose, "%s: Scanning count %u\n", __func__, count); ret = hp5590_read_part_number (dn, hp5590_model->proto_flags); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_stop_scan (dn, hp5590_model->proto_flags); if (ret != SANE_STATUS_GOOD) return ret; scanner = malloc (sizeof(struct hp5590_scanner)); if (!scanner) return SANE_STATUS_NO_MEM; memset (scanner, 0, sizeof(struct hp5590_scanner)); scanner->sane.model = info->model; scanner->sane.vendor = "HP"; scanner->sane.type = info->kind; scanner->sane.name = devname; scanner->dn = dn; scanner->proto_flags = hp5590_model->proto_flags; scanner->info = info; scanner->bulk_read_state = NULL; scanner->opts = NULL; if (!scanners_list) scanners_list = scanner; else { for (ptr = scanners_list; ptr->next; ptr = ptr->next); ptr->next = scanner; } return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status attach_hp4570 (SANE_String_Const devname) { return attach_usb_device (devname, SCANNER_HP4570); } /******************************************************************************/ static SANE_Status attach_hp5550 (SANE_String_Const devname) { return attach_usb_device (devname, SCANNER_HP5550); } /******************************************************************************/ static SANE_Status attach_hp5590 (SANE_String_Const devname) { return attach_usb_device (devname, SCANNER_HP5590); } /******************************************************************************/ static SANE_Status attach_hp7650 (SANE_String_Const devname) { return attach_usb_device (devname, SCANNER_HP7650); } /******************************************************************************/ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { SANE_Status ret; SANE_Word vendor_id, product_id; DBG_INIT(); DBG (1, "SANE backed for HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 %u.%u.%u\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (1, "(c) Ilia Sotnikov \n"); if (version_code) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, BUILD); sanei_usb_init(); sanei_usb_set_timeout (USB_TIMEOUT); scanners_list = NULL; ret = hp5590_vendor_product_id (SCANNER_HP4570, &vendor_id, &product_id); if (ret != SANE_STATUS_GOOD) return ret; ret = sanei_usb_find_devices (vendor_id, product_id, attach_hp4570); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_vendor_product_id (SCANNER_HP5550, &vendor_id, &product_id); if (ret != SANE_STATUS_GOOD) return ret; ret = sanei_usb_find_devices (vendor_id, product_id, attach_hp5550); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_vendor_product_id (SCANNER_HP5590, &vendor_id, &product_id); if (ret != SANE_STATUS_GOOD) return ret; ret = sanei_usb_find_devices (vendor_id, product_id, attach_hp5590); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_vendor_product_id (SCANNER_HP7650, &vendor_id, &product_id); if (ret != SANE_STATUS_GOOD) return ret; ret = sanei_usb_find_devices (vendor_id, product_id, attach_hp7650); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ void sane_exit (void) { struct hp5590_scanner *ptr, *pnext; DBG (DBG_proc, "%s\n", __func__); for (ptr = scanners_list; ptr; ptr = pnext) { if (ptr->opts != NULL) free (ptr->opts); pnext = ptr->next; free (ptr); } } /******************************************************************************/ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { struct hp5590_scanner *ptr; unsigned int found, i; DBG (DBG_proc, "%s, local only: %u\n", __func__, local_only); if (!device_list) return SANE_STATUS_INVAL; for (found = 0, ptr = scanners_list; ptr; found++, ptr = ptr->next); DBG (1, "Found %u devices\n", found); found++; *device_list = malloc (found * sizeof (SANE_Device)); if (!*device_list) return SANE_STATUS_NO_MEM; memset (*device_list, 0, found * sizeof(SANE_Device)); for (i = 0, ptr = scanners_list; ptr; i++, ptr = ptr->next) { (*device_list)[i] = &(ptr->sane); } return SANE_STATUS_GOOD; } /******************************************************************************/ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { struct hp5590_scanner *ptr; SANE_Option_Descriptor *opts; unsigned int available_sources; SANE_String_Const *sources_list; unsigned int source_idx; DBG (DBG_proc, "%s: device name: %s\n", __func__, devicename); if (!handle) return SANE_STATUS_INVAL; /* Allow to open the first available device by specifying zero-length name */ if (!devicename || !devicename[0]) { ptr = scanners_list; } else { for (ptr = scanners_list; ptr && strcmp (ptr->sane.name, devicename) != 0; ptr = ptr->next); } if (!ptr) return SANE_STATUS_INVAL; ptr->tl_x = 0; ptr->tl_y = 0; ptr->br_x = ptr->info->max_size_x; ptr->br_y = ptr->info->max_size_y; ptr->dpi = res_list[1]; ptr->depth = DEPTH_BW; ptr->source = SOURCE_FLATBED; ptr->extend_lamp_timeout = SANE_FALSE; ptr->wait_for_button = SANE_FALSE; ptr->preview = SANE_FALSE; ptr->quality = 4; ptr->image_size = 0; ptr->scanning = SANE_FALSE; *handle = ptr; opts = malloc (sizeof (SANE_Option_Descriptor) * HP5590_OPT_LAST); if (!opts) return SANE_STATUS_NO_MEM; opts[HP5590_OPT_NUM].name = SANE_NAME_NUM_OPTIONS; opts[HP5590_OPT_NUM].title = SANE_TITLE_NUM_OPTIONS; opts[HP5590_OPT_NUM].desc = SANE_DESC_NUM_OPTIONS; opts[HP5590_OPT_NUM].type = SANE_TYPE_INT; opts[HP5590_OPT_NUM].unit = SANE_UNIT_NONE; opts[HP5590_OPT_NUM].size = sizeof(SANE_Word); opts[HP5590_OPT_NUM].cap = SANE_CAP_INACTIVE | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_NUM].constraint_type = SANE_CONSTRAINT_NONE; opts[HP5590_OPT_NUM].constraint.string_list = NULL; range_x.min = SANE_FIX(0); range_x.max = SANE_FIX(ptr->info->max_size_x * 25.4); range_x.quant = SANE_FIX(0.1); range_y.min = SANE_FIX(0); range_y.max = SANE_FIX(ptr->info->max_size_y * 25.4); range_y.quant = SANE_FIX(0.1); range_qual.min = SANE_FIX(4); range_qual.max = SANE_FIX(16); range_qual.quant = SANE_FIX(1); opts[HP5590_OPT_TL_X].name = SANE_NAME_SCAN_TL_X; opts[HP5590_OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; opts[HP5590_OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; opts[HP5590_OPT_TL_X].type = SANE_TYPE_FIXED; opts[HP5590_OPT_TL_X].unit = SANE_UNIT_MM; opts[HP5590_OPT_TL_X].size = sizeof(SANE_Fixed); opts[HP5590_OPT_TL_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; opts[HP5590_OPT_TL_X].constraint.range = &range_x; opts[HP5590_OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; opts[HP5590_OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; opts[HP5590_OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; opts[HP5590_OPT_TL_Y].type = SANE_TYPE_FIXED; opts[HP5590_OPT_TL_Y].unit = SANE_UNIT_MM; opts[HP5590_OPT_TL_Y].size = sizeof(SANE_Fixed); opts[HP5590_OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; opts[HP5590_OPT_TL_Y].constraint.range = &range_y; opts[HP5590_OPT_BR_X].name = SANE_NAME_SCAN_BR_X; opts[HP5590_OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; opts[HP5590_OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; opts[HP5590_OPT_BR_X].type = SANE_TYPE_FIXED; opts[HP5590_OPT_BR_X].unit = SANE_UNIT_MM; opts[HP5590_OPT_BR_X].size = sizeof(SANE_Fixed); opts[HP5590_OPT_BR_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; opts[HP5590_OPT_BR_X].constraint.range = &range_x; opts[HP5590_OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; opts[HP5590_OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; opts[HP5590_OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; opts[HP5590_OPT_BR_Y].type = SANE_TYPE_FIXED; opts[HP5590_OPT_BR_Y].unit = SANE_UNIT_MM; opts[HP5590_OPT_BR_Y].size = sizeof(SANE_Fixed); opts[HP5590_OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; opts[HP5590_OPT_BR_Y].constraint.range = &range_y; opts[HP5590_OPT_MODE].name = SANE_NAME_SCAN_MODE; opts[HP5590_OPT_MODE].title = SANE_TITLE_SCAN_MODE; opts[HP5590_OPT_MODE].desc = SANE_DESC_SCAN_MODE; opts[HP5590_OPT_MODE].type = SANE_TYPE_STRING; opts[HP5590_OPT_MODE].unit = SANE_UNIT_NONE; opts[HP5590_OPT_MODE].size = MAX_SCAN_MODE_VALUE_LEN; opts[HP5590_OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; opts[HP5590_OPT_MODE].constraint.string_list = mode_list; available_sources = 1; /* Flatbed is always available */ if (ptr->info->features & FEATURE_ADF) available_sources += 2; if (ptr->info->features & FEATURE_TMA) available_sources += 2; available_sources++; /* Count terminating NULL */ sources_list = malloc (available_sources * sizeof (SANE_String_Const)); if (!sources_list) return SANE_STATUS_NO_MEM; source_idx = 0; sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_FLATBED; if (ptr->info->features & FEATURE_ADF) { sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_ADF; sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX; } if (ptr->info->features & FEATURE_TMA) { sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_TMA_SLIDES; sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES; } sources_list[source_idx] = NULL; opts[HP5590_OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; opts[HP5590_OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; opts[HP5590_OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; opts[HP5590_OPT_SOURCE].type = SANE_TYPE_STRING; opts[HP5590_OPT_SOURCE].unit = SANE_UNIT_NONE; opts[HP5590_OPT_SOURCE].size = MAX_SCAN_SOURCE_VALUE_LEN; opts[HP5590_OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; opts[HP5590_OPT_SOURCE].constraint.string_list = sources_list; opts[HP5590_OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; opts[HP5590_OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; opts[HP5590_OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; opts[HP5590_OPT_RESOLUTION].type = SANE_TYPE_INT; opts[HP5590_OPT_RESOLUTION].unit = SANE_UNIT_DPI; opts[HP5590_OPT_RESOLUTION].size = sizeof(SANE_Int); opts[HP5590_OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; opts[HP5590_OPT_RESOLUTION].constraint.word_list = res_list; opts[HP5590_OPT_LAMP_TIMEOUT].name = SANE_NAME_LAMP_TIMEOUT; opts[HP5590_OPT_LAMP_TIMEOUT].title = SANE_TITLE_LAMP_TIMEOUT; opts[HP5590_OPT_LAMP_TIMEOUT].desc = SANE_DESC_LAMP_TIMEOUT; opts[HP5590_OPT_LAMP_TIMEOUT].type = SANE_TYPE_BOOL; opts[HP5590_OPT_LAMP_TIMEOUT].unit = SANE_UNIT_NONE; opts[HP5590_OPT_LAMP_TIMEOUT].size = sizeof(SANE_Bool); opts[HP5590_OPT_LAMP_TIMEOUT].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; opts[HP5590_OPT_LAMP_TIMEOUT].constraint_type = SANE_CONSTRAINT_NONE; opts[HP5590_OPT_LAMP_TIMEOUT].constraint.string_list = NULL; opts[HP5590_OPT_WAIT_FOR_BUTTON].name = SANE_NAME_WAIT_FOR_BUTTON; opts[HP5590_OPT_WAIT_FOR_BUTTON].title = SANE_TITLE_WAIT_FOR_BUTTON; opts[HP5590_OPT_WAIT_FOR_BUTTON].desc = SANE_DESC_WAIT_FOR_BUTTON; opts[HP5590_OPT_WAIT_FOR_BUTTON].type = SANE_TYPE_BOOL; opts[HP5590_OPT_WAIT_FOR_BUTTON].unit = SANE_UNIT_NONE; opts[HP5590_OPT_WAIT_FOR_BUTTON].size = sizeof(SANE_Bool); opts[HP5590_OPT_WAIT_FOR_BUTTON].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_WAIT_FOR_BUTTON].constraint_type = SANE_CONSTRAINT_NONE; opts[HP5590_OPT_WAIT_FOR_BUTTON].constraint.string_list = NULL; opts[HP5590_OPT_PREVIEW].name = SANE_NAME_PREVIEW; opts[HP5590_OPT_PREVIEW].title = SANE_TITLE_PREVIEW; opts[HP5590_OPT_PREVIEW].desc = SANE_DESC_PREVIEW; opts[HP5590_OPT_PREVIEW].type = SANE_TYPE_BOOL; opts[HP5590_OPT_PREVIEW].unit = SANE_UNIT_NONE; opts[HP5590_OPT_PREVIEW].size = sizeof(SANE_Bool); opts[HP5590_OPT_PREVIEW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; opts[HP5590_OPT_PREVIEW].constraint.string_list = NULL; ptr->opts = opts; return SANE_STATUS_GOOD; } /******************************************************************************/ void sane_close (SANE_Handle handle) { struct hp5590_scanner *scanner = handle; DBG (DBG_proc, "%s\n", __func__); sanei_usb_close (scanner->dn); scanner->dn = -1; } /******************************************************************************/ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct hp5590_scanner *scanner = handle; DBG (DBG_proc, "%s, option: %u\n", __func__, option); if (option >= HP5590_OPT_LAST) return NULL; return &scanner->opts[option]; } /******************************************************************************/ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { struct hp5590_scanner *scanner = handle; if (!value) return SANE_STATUS_INVAL; if (!handle) return SANE_STATUS_INVAL; if (option >= HP5590_OPT_LAST) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { if (option == HP5590_OPT_NUM) { DBG(3, "%s: get total number of options - %u\n", __func__, HP5590_OPT_LAST); *((SANE_Int *) value) = HP5590_OPT_LAST; return SANE_STATUS_GOOD; } if (!scanner->opts) return SANE_STATUS_INVAL; DBG (DBG_proc, "%s: get option '%s' value\n", __func__, scanner->opts[option].name); if (option == HP5590_OPT_BR_X) { *(SANE_Fixed *) value = SANE_FIX (scanner->br_x * 25.4); } if (option == HP5590_OPT_BR_Y) { *(SANE_Fixed *) value = SANE_FIX (scanner->br_y * 25.4); } if (option == HP5590_OPT_TL_X) { *(SANE_Fixed *) value = SANE_FIX ((scanner->tl_x) * 25.4); } if (option == HP5590_OPT_TL_Y) { *(SANE_Fixed *) value = SANE_FIX (scanner->tl_y * 25.4); } if (option == HP5590_OPT_MODE) { switch (scanner->depth) { case DEPTH_BW: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_MODE_LINEART, strlen (SANE_VALUE_SCAN_MODE_LINEART)); break; case DEPTH_GRAY: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_MODE_GRAY, strlen (SANE_VALUE_SCAN_MODE_GRAY)); break; case DEPTH_COLOR_24: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_MODE_COLOR_24, strlen (SANE_VALUE_SCAN_MODE_COLOR_24)); break; case DEPTH_COLOR_48: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_MODE_COLOR_48, strlen (SANE_VALUE_SCAN_MODE_COLOR_48)); break; default: return SANE_STATUS_INVAL; } } if (option == HP5590_OPT_SOURCE) { switch (scanner->source) { case SOURCE_FLATBED: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_FLATBED, strlen (SANE_VALUE_SCAN_SOURCE_FLATBED)); break; case SOURCE_ADF: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_ADF, strlen (SANE_VALUE_SCAN_SOURCE_ADF)); break; case SOURCE_ADF_DUPLEX: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX, strlen (SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX)); break; case SOURCE_TMA_SLIDES: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_TMA_SLIDES, strlen (SANE_VALUE_SCAN_SOURCE_TMA_SLIDES)); break; case SOURCE_TMA_NEGATIVES: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES, strlen (SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES)); break; case SOURCE_NONE: default: return SANE_STATUS_INVAL; } } if (option == HP5590_OPT_RESOLUTION) { *(SANE_Int *) value = scanner->dpi; } if (option == HP5590_OPT_LAMP_TIMEOUT) { *(SANE_Bool *) value = scanner->extend_lamp_timeout; } if (option == HP5590_OPT_WAIT_FOR_BUTTON) { *(SANE_Bool *) value = scanner->wait_for_button; } if (option == HP5590_OPT_PREVIEW) { *(SANE_Bool *) value = scanner->preview; } } if (action == SANE_ACTION_SET_VALUE) { if (option == HP5590_OPT_NUM) return SANE_STATUS_INVAL; if (option == HP5590_OPT_BR_X) { float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; if (val <= scanner->tl_x) return SANE_STATUS_GOOD; scanner->br_x = val; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_BR_Y) { float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; if (val <= scanner->tl_y) return SANE_STATUS_GOOD; scanner->br_y = val; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_TL_X) { float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; if (val >= scanner->br_x) return SANE_STATUS_GOOD; scanner->tl_x = val; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_TL_Y) { float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; if (val >= scanner->br_y) return SANE_STATUS_GOOD; scanner->tl_y = val; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_MODE) { if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_LINEART) == 0) { scanner->depth = DEPTH_BW; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_GRAY) == 0) { scanner->depth = DEPTH_GRAY; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_COLOR_24) == 0) { scanner->depth = DEPTH_COLOR_24; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_COLOR_48) == 0) { scanner->depth = DEPTH_COLOR_48; } if (info) *info = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } if (option == HP5590_OPT_SOURCE) { range_y.max = SANE_FIX(scanner->info->max_size_y * 25.4); if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_FLATBED) == 0) { scanner->source = SOURCE_FLATBED; range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); range_y.max = SANE_FIX(scanner->info->max_size_y * 25.4); scanner->br_x = scanner->info->max_size_x; scanner->br_y = scanner->info->max_size_y; } /* In ADF modes the device can scan up to ADF_MAX_Y_INCHES, which is usually * bigger than what scanner reports back during initialization */ if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_ADF) == 0) { scanner->source = SOURCE_ADF; range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); range_y.max = SANE_FIX(ADF_MAX_Y_INCHES * 25.4); scanner->br_x = scanner->info->max_size_x; scanner->br_y = ADF_MAX_Y_INCHES * 25.4; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX) == 0) { scanner->source = SOURCE_ADF_DUPLEX; range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); range_y.max = SANE_FIX(ADF_MAX_Y_INCHES * 25.4 * 2); scanner->br_y = ADF_MAX_Y_INCHES * 25.4 * 2; scanner->br_x = scanner->info->max_size_x; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_TMA_SLIDES) == 0) { scanner->source = SOURCE_TMA_SLIDES; range_x.max = SANE_FIX(TMA_MAX_X_INCHES * 25.4); range_y.max = SANE_FIX(TMA_MAX_Y_INCHES * 25.4); scanner->br_x = TMA_MAX_X_INCHES * 25.4; scanner->br_y = TMA_MAX_Y_INCHES * 25.4; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES) == 0) { scanner->source = SOURCE_TMA_NEGATIVES; range_x.max = SANE_FIX(TMA_MAX_X_INCHES * 25.4); range_y.max = SANE_FIX(TMA_MAX_Y_INCHES * 25.4); scanner->br_x = TMA_MAX_X_INCHES * 25.4; scanner->br_y = TMA_MAX_Y_INCHES * 25.4; } if (info) *info = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } if (option == HP5590_OPT_RESOLUTION) { scanner->dpi = *(SANE_Int *) value; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_LAMP_TIMEOUT) { scanner->extend_lamp_timeout = *(SANE_Bool *) value; } if (option == HP5590_OPT_WAIT_FOR_BUTTON) { scanner->wait_for_button = *(SANE_Bool *) value; } if (option == HP5590_OPT_PREVIEW) { scanner->preview = *(SANE_Bool *) value; } } return SANE_STATUS_GOOD; } /******************************************************************************/ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { struct hp5590_scanner *scanner = handle; SANE_Status ret; unsigned int pixel_bits; DBG (DBG_proc, "%s\n", __func__); if (!params) return SANE_STATUS_INVAL; if (!handle) return SANE_STATUS_INVAL; ret = calc_image_params (scanner, (unsigned int *) &pixel_bits, (unsigned int *) ¶ms->pixels_per_line, (unsigned int *) ¶ms->bytes_per_line, (unsigned int *) ¶ms->lines, NULL); if (ret != SANE_STATUS_GOOD) return ret; switch (scanner->depth) { case DEPTH_BW: params->depth = pixel_bits; params->format = SANE_FRAME_GRAY; params->last_frame = SANE_TRUE; break; case DEPTH_GRAY: params->depth = pixel_bits; params->format = SANE_FRAME_GRAY; params->last_frame = SANE_TRUE; break; case DEPTH_COLOR_24: params->depth = pixel_bits / 3; params->last_frame = SANE_TRUE; params->format = SANE_FRAME_RGB; break; case DEPTH_COLOR_48: params->depth = pixel_bits / 3; params->last_frame = SANE_TRUE; params->format = SANE_FRAME_RGB; break; default: DBG(0, "%s: Unknown depth\n", __func__); return SANE_STATUS_INVAL; } DBG (DBG_proc, "format: %u, last_frame: %u, bytes_per_line: %u, " "pixels_per_line: %u, lines: %u, depth: %u\n", params->format, params->last_frame, params->bytes_per_line, params->pixels_per_line, params->lines, params->depth); return SANE_STATUS_GOOD; } /******************************************************************************/ SANE_Status sane_start (SANE_Handle handle) { struct hp5590_scanner *scanner = handle; SANE_Status ret; unsigned int bytes_per_line; DBG (DBG_proc, "%s\n", __func__); if (!scanner) return SANE_STATUS_INVAL; if ( scanner->scanning == SANE_TRUE && ( scanner->source == SOURCE_ADF || scanner->source == SOURCE_ADF_DUPLEX)) { DBG (DBG_verbose, "%s: Scanner is scanning, check if more data is available\n", __func__); ret = hp5590_is_data_available (scanner->dn, scanner->proto_flags); if (ret == SANE_STATUS_GOOD) { DBG (DBG_verbose, "%s: More data is available\n", __func__); scanner->transferred_image_size = scanner->image_size; return SANE_STATUS_GOOD; } if (ret != SANE_STATUS_NO_DOCS) return ret; } sane_cancel (handle); if (scanner->wait_for_button) { enum button_status status; for (;;) { ret = hp5590_read_buttons (scanner->dn, scanner->proto_flags, &status); if (ret != SANE_STATUS_GOOD) return ret; if (status == BUTTON_CANCEL) return SANE_STATUS_CANCELLED; if (status != BUTTON_NONE && status != BUTTON_POWER) break; sleep (1); } } DBG (DBG_verbose, "Init scanner\n"); ret = hp5590_init_scanner (scanner->dn, scanner->proto_flags, NULL, SCANNER_NONE); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_power_status (scanner->dn, scanner->proto_flags); if (ret != SANE_STATUS_GOOD) return ret; DBG (DBG_verbose, "Wakeup\n"); ret = hp5590_select_source_and_wakeup (scanner->dn, scanner->proto_flags, scanner->source, scanner->extend_lamp_timeout); if (ret != SANE_STATUS_GOOD) return ret; ret = hp5590_set_scan_params (scanner->dn, scanner->proto_flags, scanner->info, scanner->tl_x * scanner->dpi, scanner->tl_y * scanner->dpi, (scanner->br_x - scanner->tl_x) * scanner->dpi, (scanner->br_y - scanner->tl_y) * scanner->dpi, scanner->dpi, scanner->depth, scanner->preview ? MODE_PREVIEW : MODE_NORMAL, scanner->source); if (ret != SANE_STATUS_GOOD) { hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); return ret; } ret = calc_image_params (scanner, NULL, NULL, &bytes_per_line, NULL, &scanner->image_size); if (ret != SANE_STATUS_GOOD) { hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); return ret; } scanner->transferred_image_size = scanner->image_size; if ( scanner->depth == DEPTH_COLOR_24 || scanner->depth == DEPTH_COLOR_48) { DBG (1, "Color 24/48 bits: checking if image size is correctly " "aligned on number of colors\n"); if (bytes_per_line % 3) { DBG (DBG_err, "Color 24/48 bits: image size doesn't lined up on number of colors (3) " "(image size: %u, bytes per line %u)\n", scanner->image_size, bytes_per_line); hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); return SANE_STATUS_INVAL; } DBG (1, "Color 24/48 bits: image size is correctly aligned on number of colors " "(image size: %u, bytes per line %u)\n", scanner->image_size, bytes_per_line); DBG (1, "Color 24/48 bits: checking if image size is correctly " "aligned on bytes per line\n"); if (scanner->image_size % bytes_per_line) { DBG (DBG_err, "Color 24/48 bits: image size doesn't lined up on bytes per line " "(image size: %u, bytes per line %u)\n", scanner->image_size, bytes_per_line); hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); return SANE_STATUS_INVAL; } DBG (1, "Color 24/48 bits: image size correctly aligned on bytes per line " "(images size: %u, bytes per line: %u)\n", scanner->image_size, bytes_per_line); } DBG (DBG_verbose, "Final image size: %u\n", scanner->image_size); DBG (DBG_verbose, "Reverse calibration maps\n"); ret = hp5590_send_reverse_calibration_map (scanner->dn, scanner->proto_flags); if (ret != SANE_STATUS_GOOD) { hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); return ret; } DBG (DBG_verbose, "Forward calibration maps\n"); ret = hp5590_send_forward_calibration_maps (scanner->dn, scanner->proto_flags); if (ret != SANE_STATUS_GOOD) { hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); return ret; } scanner->scanning = SANE_TRUE; DBG (DBG_verbose, "Starting scan\n"); ret = hp5590_start_scan (scanner->dn, scanner->proto_flags); /* Check for paper jam */ if ( ret == SANE_STATUS_DEVICE_BUSY && ( scanner->source == SOURCE_ADF || scanner->source == SOURCE_ADF_DUPLEX)) return SANE_STATUS_JAMMED; if (ret != SANE_STATUS_GOOD) { hp5590_reset_scan_head (scanner->dn, scanner->proto_flags); return ret; } return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status convert_lineart (struct hp5590_scanner *scanner, SANE_Byte *data, SANE_Int size) { SANE_Int i; DBG (DBG_proc, "%s\n", __func__); hp5590_assert (scanner != NULL); hp5590_assert (data != NULL); /* Invert lineart */ if (scanner->depth == DEPTH_BW) { for (i = 0; i < size; i++) data[i] ^= 0xff; } return SANE_STATUS_GOOD; } /******************************************************************************/ static SANE_Status convert_to_rgb (struct hp5590_scanner *scanner, SANE_Byte *data, SANE_Int size) { unsigned int pixels_per_line; unsigned int bytes_per_color; unsigned int bytes_per_line; unsigned int lines; unsigned int i, j; unsigned char *buf; unsigned char *ptr; SANE_Status ret; hp5590_assert (scanner != NULL); hp5590_assert (data != NULL); if ( scanner->depth == DEPTH_BW || scanner->depth == DEPTH_GRAY) return SANE_STATUS_GOOD; DBG (DBG_proc, "%s\n", __func__); #ifndef HAS_WORKING_COLOR_48 if (scanner->depth == DEPTH_COLOR_48) return SANE_STATUS_UNSUPPORTED; #endif ret = calc_image_params (scanner, NULL, &pixels_per_line, &bytes_per_line, NULL, NULL); if (ret != SANE_STATUS_GOOD) return ret; lines = size / bytes_per_line; bytes_per_color = bytes_per_line / 3; DBG (DBG_verbose, "Length : %u\n", size); DBG (DBG_verbose, "Converting row RGB to normal RGB\n"); DBG (DBG_verbose, "Bytes per line %u\n", bytes_per_line); DBG (DBG_verbose, "Bytes per color %u\n", bytes_per_color); DBG (DBG_verbose, "Lines %u\n", lines); buf = malloc (bytes_per_line); if (!buf) return SANE_STATUS_NO_MEM; ptr = data; for (j = 0; j < lines; ptr += bytes_per_line, j++) { memset (buf, 0, bytes_per_line); for (i = 0; i < pixels_per_line; i++) { if (scanner->depth == DEPTH_COLOR_24) { /* R */ buf[i*3] = ptr[i]; /* G */ buf[i*3+1] = ptr[i+bytes_per_color]; /* B */ buf[i*3+2] = ptr[i+bytes_per_color*2]; } else { /* R */ buf[i*6] = ptr[2*i+1]; buf[i*6+1] = ptr[2*i]; /* G */ buf[i*6+2] = ptr[2*i+bytes_per_color+1]; buf[i*6+3] = ptr[2*i+bytes_per_color]; /* B */ buf[i*6+4] = ptr[2*i+bytes_per_color*2+1]; buf[i*6+5] = ptr[2*i+bytes_per_color*2]; } } /* Invert pixels in case of TMA Negatives source has been selected */ if (scanner->source == SOURCE_TMA_NEGATIVES) { for (i = 0; i < bytes_per_line; i++) buf[i] ^= 0xff; } memcpy (ptr, buf, bytes_per_line); } free (buf); return SANE_STATUS_GOOD; } /******************************************************************************/ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { struct hp5590_scanner *scanner = handle; SANE_Status ret; DBG (DBG_proc, "%s, length %u, left %u\n", __func__, max_length, scanner->transferred_image_size); if (!length) { scanner->scanning = SANE_FALSE; return SANE_STATUS_INVAL; } if (scanner->transferred_image_size == 0) { *length = 0; DBG (DBG_verbose, "Setting scan count\n"); ret = hp5590_inc_scan_count (scanner->dn, scanner->proto_flags); if (ret != SANE_STATUS_GOOD) return ret; /* Don't free bulk read state, some bytes could be left * for the next images from ADF */ return SANE_STATUS_EOF; } if (!scanner->bulk_read_state) { ret = hp5590_low_init_bulk_read_state (&scanner->bulk_read_state); if (ret != SANE_STATUS_GOOD) { scanner->scanning = SANE_FALSE; return ret; } } *length = max_length; if (*length > scanner->transferred_image_size) *length = scanner->transferred_image_size; if ( scanner->depth == DEPTH_COLOR_24 || scanner->depth == DEPTH_COLOR_48) { unsigned int bytes_per_line; ret = calc_image_params (scanner, NULL, NULL, &bytes_per_line, NULL, NULL); if (ret != SANE_STATUS_GOOD) return ret; *length -= *length % bytes_per_line; DBG (2, "Aligning requested size to bytes per line " "(requested: %u, aligned: %u)\n", max_length, *length); } ret = hp5590_read (scanner->dn, scanner->proto_flags, data, *length, scanner->bulk_read_state); if (ret != SANE_STATUS_GOOD) { scanner->scanning = SANE_FALSE; return ret; } scanner->transferred_image_size -= *length; ret = convert_to_rgb (scanner, data, *length); if (ret != SANE_STATUS_GOOD) { scanner->scanning = SANE_FALSE; return ret; } ret = convert_lineart (scanner, data, *length); if (ret != SANE_STATUS_GOOD) return ret; return SANE_STATUS_GOOD; } /******************************************************************************/ void sane_cancel (SANE_Handle handle) { struct hp5590_scanner *scanner = handle; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); scanner->scanning = SANE_FALSE; if (scanner->dn < 0) return; hp5590_low_free_bulk_read_state (&scanner->bulk_read_state); ret = hp5590_stop_scan (scanner->dn, scanner->proto_flags); if (ret != SANE_STATUS_GOOD) return; } /******************************************************************************/ SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { DBG (DBG_proc, "%s\n", __func__); return SANE_STATUS_UNSUPPORTED; } /******************************************************************************/ SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { DBG (DBG_proc, "%s\n", __func__); return SANE_STATUS_UNSUPPORTED; } /* vim: sw=2 ts=8 */ sane-backends-1.0.27/backend/pixma_common.h0000664000175000017500000001705112775312261015462 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIXMA_COMMON_H #define PIXMA_COMMON_H #include /* time_t */ #include "pixma.h" /*! \defgroup subdriver Subdriver Interface * \brief Subdriver interface. */ /*! \defgroup debug Debug utilities * \brief Debug utilities. */ #ifdef NDEBUG # define PDBG(x) do {} while(0) # define PASSERT(x) do {} while(0) #else # define PDBG(x) x # define PASSERT(x) do { \ if (!(x)) \ pixma_dbg(1, "ASSERT failed:%s:%d: " \ #x "\n", __FILE__, __LINE__); \ } while(0) #endif #define PIXMA_STATUS_OK 0x0606 #define PIXMA_STATUS_FAILED 0x1515 #define PIXMA_STATUS_BUSY 0x1414 #define PIXMA_MAX_ID_LEN 30 /* These may have been defined elsewhere */ #ifndef MIN #define MIN(x,y) (((x) < (y)) ? (x):(y)) #endif #ifndef MAX #define MAX(x,y) (((x) < (y)) ? (y):(x)) #endif #define ALIGN_SUP(x,n) (((x) + (n) - 1) / (n) * (n)) #define ALIGN_INF(x,n) (((x) / (n)) * (n)) struct pixma_io_t; struct pixma_limits_t { unsigned xdpi, ydpi; unsigned width, height; }; struct pixma_cmdbuf_t { unsigned cmd_header_len, res_header_len, cmd_len_field_ofs; unsigned expected_reslen, cmdlen; int reslen; unsigned size; uint8_t *buf; }; struct pixma_imagebuf_t { uint8_t *wptr, *wend; const uint8_t *rptr, *rend; }; struct pixma_t { pixma_t *next; struct pixma_io_t *io; const pixma_scan_ops_t *ops; pixma_scan_param_t *param; const pixma_config_t *cfg; char id[PIXMA_MAX_ID_LEN + 1]; int cancel; /* NOTE: It can be set in a signal handler. */ uint32_t events; void *subdriver; /* can be used by model driver. */ int rec_tmo; /* receive timeout [s] */ /* private */ uint64_t cur_image_size; pixma_imagebuf_t imagebuf; unsigned scanning:1; unsigned underrun:1; }; /** \addtogroup subdriver * @{ */ /** Scan operations for subdriver. */ struct pixma_scan_ops_t { /** Allocate a data structure for the subdriver. It is called after the * core driver connected to the scanner. The subdriver should reset the * scanner to a known state in this function. */ int (*open) (pixma_t *); /** Free resources allocated by the subdriver. Don't forget to send abort * command to the scanner if it is scanning. */ void (*close) (pixma_t *); /** Setup the scanner for scan parameters defined in \a s->param. */ int (*scan) (pixma_t * s); /** Fill a buffer with image data. The subdriver has two choices: * -# Fill the buffer pointed by ib->wptr directly and leave * ib->rptr and ib->rend untouched. The length of the buffer is * ib->wend - ib->wptr. It must update ib->wptr accordingly. * -# Update ib->rptr and ib->rend to point to the beginning and * the end of the internal buffer resp. The length of the buffer * is ib->rend - ib->rptr. This function is called again if * and only if pixma_read_image() has copied the whole buffer. * * The subdriver must wait until there is at least one byte to read or * return 0 for the end of image. */ int (*fill_buffer) (pixma_t *, pixma_imagebuf_t * ib); /** Cancel the scan operation if necessary and free resources allocated in * scan(). */ void (*finish_scan) (pixma_t *); /** [Optional] Wait for a user's event, e.g. button event. \a timeout is * in milliseconds. If an event occured before it's timed out, flags in * \a s->events should be set accordingly. * \see PIXMA_EV_* */ void (*wait_event) (pixma_t * s, int timeout); /** Check the scan parameters. The parameters can be adjusted if they are * out of range, e.g. width > max_width. */ int (*check_param) (pixma_t *, pixma_scan_param_t *); /** Read the device status. \see pixma_get_device_status() */ int (*get_status) (pixma_t *, pixma_device_status_t *); }; /** \name Funtions for read and write big-endian integer values */ /**@{*/ void pixma_set_be16 (uint16_t x, uint8_t * buf); void pixma_set_be32 (uint32_t x, uint8_t * buf); uint16_t pixma_get_be16 (const uint8_t * buf); uint32_t pixma_get_be32 (const uint8_t * buf); /**@}*/ /** \name Utility functions */ /**@{*/ uint8_t pixma_sum_bytes (const void *data, unsigned len); int pixma_check_dpi (unsigned dpi, unsigned max); void pixma_sleep (unsigned long usec); void pixma_get_time (time_t * sec, uint32_t * usec); uint8_t * pixma_r_to_ir (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c); uint8_t * pixma_rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c); uint8_t * pixma_binarize_line(pixma_scan_param_t *, uint8_t * dst, uint8_t * src, unsigned width, unsigned c); /**@}*/ /** \name Command related functions */ /**@{*/ int pixma_cmd_transaction (pixma_t *, const void *cmd, unsigned cmdlen, void *data, unsigned expected_len); int pixma_check_result (pixma_cmdbuf_t *); uint8_t *pixma_newcmd (pixma_cmdbuf_t *, unsigned cmd, unsigned dataout, unsigned datain); int pixma_exec (pixma_t *, pixma_cmdbuf_t *); int pixma_exec_short_cmd (pixma_t *, pixma_cmdbuf_t *, unsigned cmd); int pixma_map_status_errno (unsigned status); /**@}*/ #define pixma_fill_checksum(start, end) do { \ *(end) = -pixma_sum_bytes(start, (end)-(start)); \ } while(0) /** @} end of group subdriver */ /** \addtogroup debug * @{ */ void pixma_set_debug_level (int level); #ifndef NDEBUG void pixma_hexdump (int level, const void *d_, unsigned len); /* len: length of data or error code. size: if >= 0, force to print 'size' bytes. max: maximum number of bytes to print(-1 means no limit). */ void pixma_dump (int level, const char *type, const void *data, int len, int size, int max); # define DEBUG_DECLARE_ONLY # include "../include/sane/sanei_debug.h" #endif /* NDEBUG */ /** @} end of group debug */ #endif sane-backends-1.0.27/backend/plustek-pp_procfs.c0000664000175000017500000002724012775277260016461 00000000000000/* @file plustek-pp_procfs.c * @brief this is the interface to the proc filesystem * * Copyright (C) 2000-2013 Gerhard Jaeger * * History: * - 0.37 - initial version * - 0.38 - changes according to generic structure changes * - 0.39 - added info about forceMode and slowIO * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - replace _PTDRV_VERx by _PTDRV_VERSTR * - cleanup * - 0.44 - PROC_FS changes for newer kernel * - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifdef __KERNEL__ #include #include "plustek-pp_scan.h" /* toggled by your kernel configuration */ #ifdef CONFIG_PROC_FS /****************************** static vars **********************************/ /** for the proc filesystem */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) extern struct proc_dir_entry proc_root; #endif static struct proc_dir_entry *base = NULL; static struct proc_dir_entry *binfo = NULL; static ULong devcount; /** parallel port modes... */ static char *procfsPortModes[] = { "EPP", "SPP", "BiDi (PS/2)", "ECP" "unknown", NULL }; /** CCD-Types (as for ASIC 98001 based series) */ static TabDef procfsCCDTypes98001[] = { { _CCD_3797, "3797" }, { _CCD_3717, "3717" }, { _CCD_535, "535" }, { _CCD_2556, "2556" }, { _CCD_518, "518" }, { _CCD_539, "539" }, { -1 , "unknown" } }; /** CCD-Types (as for ASIC 98003 based series) */ static TabDef procfsCCDTypes98003[] = { { _CCD_3797, "3797" }, { _CCD_3799, "3799" }, { _CCD_535, "535" }, { _CCD_2556, "2556" }, { _CCD_518, "518" }, { _CCD_539, "539" }, { _CCD_3777, "3777" }, { _CCD_548 , "548" }, { -1 , "unknown" } }; /****************************** local functions ******************************/ #ifndef LINUX_24 /** This is called as the fill_inode function when an inode * is going into (fill = 1) or out of service (fill = 0). * * Note: only the top-level directory needs to do this; if * a lower level is referenced, the parent will be as well. * * Here simply a dummy function */ static void procfsFillFunc( struct inode *inode, int fill ) { } #endif /** returns a pointer to the port-mode string */ static const char* procfsGetMode( int mode ) { if((mode < _PORT_EPP) || (mode > _PORT_ECP)) return procfsPortModes[_PORT_ECP+1]; return procfsPortModes[mode]; } /** determines CCD-Type string */ static const char* procfsGetCCDType( pScanData ps ) { int i; int ccd_id = ps->Device.bCCDID; pTabDef tab = procfsCCDTypes98001; if( _IS_ASIC98(ps->sCaps.AsicID)) { if(_ASIC_IS_98003 == ps->sCaps.AsicID) tab = procfsCCDTypes98003; /* seek down the description table */ for( i = 0; -1 != tab[i].id; i++ ) { if( tab[i].id == ccd_id ) return tab[i].desc; } } else { /* for older scanners only this info is available */ if( ps->fSonyCCD ) return "SONY Type"; else return "NEC/TOSHIBA Type"; } /* return the last entry if nothing applies! */ return tab[(sizeof(procfsCCDTypes98001)/sizeof(TabDef)-1)].desc; } /** will be called when reading the proc filesystem: * cat /proc/pt_drv/info */ static int procfsBInfoReadProc( char *buf, char **start, off_t offset, int count, int *eof, void *data ) { int len = 0; len += sprintf( buf, "Plustek Flatbed Scanner Driver version "_PTDRV_VERSTR"\n" ); len += sprintf( buf + len, "IOCTL-Version: 0x%08x\n",_PTDRV_IOCTL_VERSION); return len; } /** will be called when reading the proc filesystem: * cat /proc/pt_drv/deviceX/info */ static int procfsInfoReadProc( char *buf, char **start, off_t offset, int count, int *eof, void *data ) { int len = 0; pScanData ps = (pScanData)data; /* Tell us something about the device... */ if( NULL != ps ) { len += sprintf( buf+len, "Model : %s\n", MiscGetModelName(ps->sCaps.Model)); len += sprintf( buf+len, "Portaddress : 0x%X\n", ps->IO.portBase ); len += sprintf( buf+len, "Portmode : %s (%s I/O, %s)\n", procfsGetMode(ps->IO.portMode), (ps->IO.slowIO == _TRUE?"delayed":"fast"), (ps->IO.forceMode == 0?"autodetect":"forced")); len += sprintf( buf+len, "Buttons : %u\n", ps->Device.buttons); len += sprintf( buf+len, "Warmuptime : %us\n", ps->warmup ); len += sprintf( buf+len, "Lamp timeout: %us\n", ps->lampoff ); len += sprintf( buf+len, "mov-switch : %u\n", ps->ModelOverride ); len += sprintf( buf+len, "I/O-delay : %u\n", ps->IO.delay ); len += sprintf( buf+len, "CCD-Type : %s\n", procfsGetCCDType(ps)); len += sprintf( buf+len, "TPA : %s\n", (ps->sCaps.dwFlag & SFLAG_TPA) ? "yes":"no" ); } return len; } /** will be called when reading the proc filesystem: * cat /proc/pt_drv/devicex/buttony */ static int procfsButtonsReadProc( char *buf, char **start, off_t offset, int count, int *eof, void *data ) { Byte b; int bc = 0; int len = 0; pScanData ps = (pScanData)data; if( NULL != ps ) { bc = ps->Device.buttons; } /* Check the buttons... */ if( 0 != bc ) { if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) { MiscClaimPort( ps ); b = IODataRegisterFromScanner( ps, ps->RegStatus ); if(_FLAG_P96_KEY == (b & _FLAG_P96_KEY)) b = 0; else b = 1; MiscReleasePort( ps ); len += sprintf( buf + len, "%u\n", b ); } else bc = 0; } if( 0 == bc ) len += sprintf( buf + len, "none\n" ); return len; } /** create a procfs entry */ static struct proc_dir_entry *new_entry( const char *name, mode_t mode, struct proc_dir_entry *parent ) { #ifndef LINUX_24 int len; #endif struct proc_dir_entry *ent; if (mode == S_IFDIR) mode |= S_IRUGO | S_IXUGO; else if (mode == 0) mode = S_IFREG | S_IRUGO; #ifndef LINUX_24 len = strlen(name) + 1; /* allocate memory for the entry and the name */ ent = kmalloc(sizeof(struct proc_dir_entry) + len, GFP_KERNEL); if( NULL == ent ) return NULL; memset(ent, 0, sizeof(struct proc_dir_entry)); /* position pointer of name to end of the structure*/ ent->name = ((char *) ent) + sizeof(*ent); strcpy((char *)ent->name, name ); ent->namelen = strlen(name); ent->mode = mode; if (S_ISDIR(mode)) { ent->nlink = 2; ent->fill_inode = &procfsFillFunc; } else { ent->nlink = 1; } proc_register( parent, ent ); #else if (mode == S_IFDIR) ent = proc_mkdir( name, parent ); else ent = create_proc_entry( name, mode, parent ); #endif return ent; } /** shutdown one proc fs entry */ static inline void destroy_proc_entry( struct proc_dir_entry *root, struct proc_dir_entry **d ) { #ifndef LINUX_24 proc_unregister( root, (*d)->low_ino ); kfree(*d); #else DBG(DBG_HIGH, "pt_drv: proc del '%s' root='%s'\n", (*d)->name, root->name); remove_proc_entry((*d)->name, root ); #endif *d = NULL; } /** shutdown the proc-tree for one device */ static void destroy_proc_tree( pScanData ps ) { int i; DBG( DBG_HIGH, "pt_drv: destroy_proc_tree !\n" ); if( ps ) { if( ps->procDir.entry ) { if( ps->procDir.info ) destroy_proc_entry( ps->procDir.entry, &ps->procDir.info ); for( i = 0; i < ps->Device.buttons; i++ ) { if( ps->procDir.buttons[i] ) destroy_proc_entry(ps->procDir.entry, &ps->procDir.buttons[i]); } destroy_proc_entry( base, &ps->procDir.entry ); } } } /*************************** exported functions ******************************/ /** initialize our proc-fs stuff */ int ProcFsInitialize( void ) { DBG( DBG_HIGH, "ProcFsInitialize()\n" ); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) base = new_entry( _DRV_NAME, S_IFDIR, &proc_root ); #else base = new_entry( _DRV_NAME, S_IFDIR, NULL ); #endif if( NULL != base ) { devcount = 0; binfo = new_entry( "info", 0, base ); if( NULL != binfo ) { binfo->read_proc = procfsBInfoReadProc; binfo->data = &devcount; } } return _OK; } /** cleanup the base entry */ void ProcFsShutdown( void ) { DBG( DBG_HIGH, "ProcFsShutdown()\n" ); if( NULL != base ) { if( NULL != binfo ) destroy_proc_entry( base, &binfo ); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) destroy_proc_entry( &proc_root, &base ); #else destroy_proc_entry( NULL, &base ); #endif } devcount = 0; } /** will be called for each device, that has been found */ void ProcFsRegisterDevice( pScanData ps ) { int i; char str[20]; if( NULL == base ) { printk( KERN_ERR "pt_drv : proc not initialised yet!\n"); return; } memset( &ps->procDir, 0, sizeof(ProcDirDef)); sprintf( str, "device%u", ps->devno ); ps->procDir.entry = new_entry( str, S_IFDIR, base ); if( NULL == ps->procDir.entry ) goto error_exit; ps->procDir.info = new_entry( "info", 0, ps->procDir.entry ); if( NULL == ps->procDir.info ) goto error_exit; ps->procDir.info->read_proc = procfsInfoReadProc; ps->procDir.info->data = ps; for( i = 0; i < ps->Device.buttons; i++ ) { sprintf( str, "button%u", i ); ps->procDir.buttons[i] = new_entry( str, 0, ps->procDir.entry ); if( NULL == ps->procDir.buttons[i] ) goto error_exit; ps->procDir.buttons[i]->read_proc = procfsButtonsReadProc; ps->procDir.buttons[i]->data = ps; } devcount++; return; error_exit: printk(KERN_ERR "pt_drv: failure registering /proc/ entry %s.\n", str ); destroy_proc_tree( ps ); } /** cleanup the proc-fs for a certain device */ void ProcFsUnregisterDevice( pScanData ps ) { destroy_proc_tree( ps ); } #else /* CONFIG_PROC_FS */ int ProcFsInitialize( void ) { return _OK; } void ProcFsShutdown( void ) { } void ProcFsRegisterDevice( pScanData ps ) { } void ProcFsUnregisterDevice( pScanData ps ) { } #endif #endif /* guard __KERNEL__ */ /* END PLUSTEK-PP_PROCFS.C ..................................................*/ sane-backends-1.0.27/backend/kvs40xx.c0000664000175000017500000003602412775277260014330 00000000000000/* Copyright (C) 2009, Panasonic Russia Ltd. Copyright (C) 2010,2011, m. allan noah */ /* Panasonic KV-S40xx USB-SCSI scanner driver. */ #include "../include/sane/config.h" #include /*isspace*/ #include /*tan*/ #include #include #include #define DEBUG_NOT_STATIC #include "../include/sane/sanei_backend.h" #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_scsi.h" #include "lassert.h" #include "kvs40xx.h" #include "sane/sanei_debug.h" #define DATA_TAIL 0x200 struct known_device { const SANE_Int id; const SANE_Device scanner; }; static const struct known_device known_devices[] = { { KV_S4085C, { "MATSHITA", "KV-S4085C", "High Speed Color ADF Scanner", "scanner" }, }, { KV_S4065C, { "MATSHITA", "KV-S4065C", "High Speed Color ADF Scanner", "scanner" }, }, { KV_S7075C, { "MATSHITA", "KV-S7075C", "High Speed Color ADF Scanner", "scanner" }, }, }; static inline SANE_Status buf_init(struct buf *b, SANE_Int sz) { const int num = sz / BUF_SIZE + 1; b->buf = (u8 **) realloc(b->buf, num * sizeof(u8 *)); if (!b->buf) return SANE_STATUS_NO_MEM; memset(b->buf, 0, num * sizeof(void *)); b->size = b->head = b->tail = 0; b->sem = 0; b->st = SANE_STATUS_GOOD; pthread_cond_init(&b->cond, NULL); pthread_mutex_init(&b->mu, NULL); return SANE_STATUS_GOOD; } static inline void buf_deinit(struct buf *b) { int i; if (!b->buf) return; for (i = b->head; i < b->tail; i++) if (b->buf[i]) free(b->buf[i]); free(b->buf); b->buf = NULL; b->head = b->tail = 0; } static inline SANE_Status new_buf(struct buf *b, u8 ** p) { b->buf[b->tail] = (u8 *) malloc(BUF_SIZE); if (!b->buf[b->tail]) return SANE_STATUS_NO_MEM; *p = b->buf[b->tail]; ++b->tail; return SANE_STATUS_GOOD; } static inline SANE_Status buf_get_err(struct buf *b) { return b->size ? SANE_STATUS_GOOD : b->st; } static inline void buf_set_st(struct buf *b, SANE_Status st) { pthread_mutex_lock(&b->mu); b->st = st; if (buf_get_err(b)) pthread_cond_signal(&b->cond); pthread_mutex_unlock(&b->mu); } static inline void buf_cancel(struct buf *b) { buf_set_st(b, SANE_STATUS_CANCELLED); } static inline void push_buf(struct buf *b, SANE_Int sz) { pthread_mutex_lock(&b->mu); b->sem++; b->size += sz; pthread_cond_signal(&b->cond); pthread_mutex_unlock(&b->mu); } static inline u8 *get_buf(struct buf *b, SANE_Int * sz) { SANE_Status err = buf_get_err(b); if (err) return NULL; pthread_mutex_lock(&b->mu); while (!b->sem && !buf_get_err(b)) pthread_cond_wait(&b->cond, &b->mu); b->sem--; err = buf_get_err(b); if (!err) { *sz = b->size < BUF_SIZE ? b->size : BUF_SIZE; b->size -= *sz; } pthread_mutex_unlock(&b->mu); return err ? NULL : b->buf[b->head]; } static inline void pop_buf(struct buf *b) { free(b->buf[b->head]); b->buf[b->head] = NULL; ++b->head; } SANE_Status sane_init (SANE_Int __sane_unused__ * version_code, SANE_Auth_Callback __sane_unused__ authorize) { DBG_INIT (); DBG (DBG_INFO, "This is panasonic kvs40xx driver\n"); *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, 1); /* Initialize USB */ sanei_usb_init (); return SANE_STATUS_GOOD; } /* * List of available devices, allocated by sane_get_devices, released * by sane_exit() */ static SANE_Device **devlist = NULL; static unsigned curr_scan_dev = 0; void sane_exit (void) { if (devlist) { int i; for (i = 0; devlist[i]; i++) { free ((void *) devlist[i]); } free ((void *) devlist); devlist = NULL; } } SANE_Status attach (SANE_String_Const devname); SANE_Status attach (SANE_String_Const devname) { int i = 0; if (devlist) { for (; devlist[i]; i++); devlist = realloc (devlist, sizeof (SANE_Device *) * (i + 1)); if (!devlist) return SANE_STATUS_NO_MEM; } else { devlist = malloc (sizeof (SANE_Device *) * 2); if (!devlist) return SANE_STATUS_NO_MEM; } devlist[i] = malloc (sizeof (SANE_Device)); if (!devlist[i]) return SANE_STATUS_NO_MEM; memcpy (devlist[i], &known_devices[curr_scan_dev].scanner, sizeof (SANE_Device)); devlist[i]->name = strdup (devname); /* terminate device list with NULL entry: */ devlist[i + 1] = 0; DBG (DBG_INFO, "%s device attached\n", devname); return SANE_STATUS_GOOD; } /* Get device list */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { if (devlist) { int i; for (i = 0; devlist[i]; i++) { free ((void *) devlist[i]); } free ((void *) devlist); devlist = NULL; } for (curr_scan_dev = 0; curr_scan_dev < sizeof (known_devices) / sizeof (known_devices[0]); curr_scan_dev++) { sanei_usb_find_devices (PANASONIC_ID, known_devices[curr_scan_dev].id, attach); } for (curr_scan_dev = 0; curr_scan_dev < sizeof (known_devices) / sizeof (known_devices[0]); curr_scan_dev++) { sanei_scsi_find_devices (known_devices[curr_scan_dev]. scanner.vendor, known_devices[curr_scan_dev]. scanner.model, NULL, -1, -1, -1, -1, attach); } if(device_list) *device_list = (const SANE_Device **) devlist; return SANE_STATUS_GOOD; } /* Open device, return the device handle */ SANE_Status sane_open (SANE_String_Const devname, SANE_Handle * handle) { unsigned i, j, id = 0; struct scanner *s; SANE_Int h, bus; SANE_Status st = SANE_STATUS_GOOD; if (!devlist) { st = sane_get_devices (NULL, 0); if (st) return st; } for (i = 0; devlist[i]; i++) { if (!strcmp (devlist[i]->name, devname)) break; } if (!devlist[i]) return SANE_STATUS_INVAL; for (j = 0; j < sizeof (known_devices) / sizeof (known_devices[0]); j++) { if (!strcmp (devlist[i]->model, known_devices[j].scanner.model)) { id = known_devices[j].id; break; } } st = sanei_usb_open (devname, &h); if (st == SANE_STATUS_ACCESS_DENIED) return st; if (st) { st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL); if (st) { return st; } bus = SCSI; } else { bus = USB; st = sanei_usb_claim_interface (h, 0); if (st) { sanei_usb_close (h); return st; } } s = malloc (sizeof (struct scanner)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (struct scanner)); s->buffer = malloc (MAX_READ_DATA_SIZE + BULK_HEADER_SIZE); if (!s->buffer) return SANE_STATUS_NO_MEM; s->file = h; s->bus = bus; s->id = id; strcpy (s->name, devname); *handle = s; for (i = 0; i < 3; i++) { st = kvs40xx_test_unit_ready (s); if (st) { if (s->bus == SCSI) { sanei_scsi_close (s->file); st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL); if (st) return st; } else { sanei_usb_release_interface (s->file, 0); sanei_usb_close (s->file); st = sanei_usb_open (devname, &h); if (st) return st; st = sanei_usb_claim_interface (h, 0); if (st) { sanei_usb_close (h); return st; } } s->file = h; } else break; } if (i == 3) return SANE_STATUS_DEVICE_BUSY; if (id == KV_S4085C || id == KV_S4065C) { char str[16]; st = inquiry (s, str); if (st) goto err; if (id == KV_S4085C) s->id = !strcmp (str, "KV-S4085CL") ? KV_S4085CL : KV_S4085CW; else s->id = !strcmp (str, "KV-S4065CL") ? KV_S4065CL : KV_S4065CW; } kvs40xx_init_options (s); st = kvs40xx_set_timeout (s, s->val[FEED_TIMEOUT].w); if (st) goto err; return SANE_STATUS_GOOD; err: sane_close (s); return st; } /* Close device */ void sane_close (SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; unsigned i; hopper_down (s); if (s->bus == USB) { sanei_usb_release_interface (s->file, 0); sanei_usb_close (s->file); } else sanei_scsi_close (s->file); for (i = 1; i < NUM_OPTIONS; i++) { if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s) free (s->val[i].s); } for (i = 0; i < sizeof (s->buf) / sizeof (s->buf[0]); i++) buf_deinit (&s->buf[i]); free (s->buffer); free (s); } /* Get option descriptor */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS || option < 0) return NULL; return s->opt + option; } static SANE_Status wait_document (struct scanner *s) { SANE_Status st; int i; if (!strcmp ("fb", s->val[SOURCE].s)) return SANE_STATUS_GOOD; if (!strcmp ("off", s->val[MANUALFEED].s)) return kvs40xx_document_exist (s); for (i = 0; i < s->val[FEED_TIMEOUT].w; i++) { st = kvs40xx_document_exist (s); if (st != SANE_STATUS_NO_DOCS) return st; sleep (1); } return SANE_STATUS_NO_DOCS; } static SANE_Status read_image_duplex(SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; SANE_Status st = SANE_STATUS_GOOD; unsigned read, side; int i; struct side { unsigned mx, eof; u8 *p; struct buf *buf; } a[2], *b; for (i = 0; i < 2; i++) { a[i].mx = BUF_SIZE; a[i].eof = 0; a[i].buf = &s->buf[i]; st = new_buf(&s->buf[i], &a[i].p); if (st) goto err; } for (b = &a[0], side = SIDE_FRONT; (!a[0].eof || !a[1].eof);) { pthread_testcancel(); if (b->mx == 0) { push_buf(b->buf, BUF_SIZE); st = new_buf(b->buf, &b->p); if (st) goto err; b->mx = BUF_SIZE; } st = kvs40xx_read_image_data(s, s->page, side, b->p + BUF_SIZE - b->mx, b->mx, &read); b->mx -= read; if (st) { if (st != INCORRECT_LENGTH && st != SANE_STATUS_EOF) goto err; if (st == SANE_STATUS_EOF) { b->eof = 1; push_buf(b->buf, BUF_SIZE - b->mx); } side ^= SIDE_BACK; b = &a[side == SIDE_FRONT ? 0 : 1]; } } err: for (i = 0; i < 2; i++) buf_set_st(&s->buf[i], st); return st; } static SANE_Status read_image_simplex(SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; SANE_Status st = SANE_STATUS_GOOD; for (; (!st || st == INCORRECT_LENGTH);) { unsigned read, mx; unsigned char *p = NULL; st = new_buf(&s->buf[0], &p); for (read = 0, mx = BUF_SIZE; mx && (!st || st == INCORRECT_LENGTH); mx -= read) { pthread_testcancel(); st = kvs40xx_read_image_data(s, s->page, SIDE_FRONT, p + BUF_SIZE - mx, mx, &read); } push_buf(&s->buf[0], BUF_SIZE - mx); } buf_set_st(&s->buf[0], st); return st; } static SANE_Status read_data(struct scanner *s) { SANE_Status st; int duplex = s->val[DUPLEX].w; s->read = 0; s->side = SIDE_FRONT; st = duplex ? read_image_duplex(s) : read_image_simplex(s); if (st && (st != SANE_STATUS_EOF)) goto err; st = kvs40xx_read_picture_element(s, SIDE_FRONT, &s->params); if (st) goto err; if (!s->params.lines) { st = SANE_STATUS_INVAL; goto err; } sane_get_parameters(s, NULL); s->page++; return SANE_STATUS_GOOD; err: s->scanning = 0; return st; } /* Start scanning */ SANE_Status sane_start (SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; SANE_Status st = SANE_STATUS_GOOD; int duplex = s->val[DUPLEX].w, i; unsigned data_avalible; int start = 0; if (s->thread) { pthread_join (s->thread, NULL); s->thread = 0; } if (!s->scanning) { st = kvs40xx_test_unit_ready (s); if (st) return st; st = wait_document (s); if (st) return st; st = kvs40xx_reset_window (s); if (st) return st; st = kvs40xx_set_window (s, SIDE_FRONT); if (st) return st; if (duplex) { st = kvs40xx_set_window (s, SIDE_BACK); if (st) return st; } st = kvs40xx_scan (s); if (st) return st; if (s->val[CROP].b || s->val[LENGTHCTL].b || s->val[LONG_PAPER].b) { unsigned w, h, res = s->val[RESOLUTION].w; SANE_Parameters *p = &s->params; w = 297; /*A3 */ h = 420; p->pixels_per_line = w * res / 25.4 + .5; p->lines = h * res / 25.4 + .5; } else { st = kvs40xx_read_picture_element (s, SIDE_FRONT, &s->params); if (st) return st; } start = 1; s->scanning = 1; s->page = 0; s->read = 0; s->side = SIDE_FRONT; sane_get_parameters (s, NULL); } if (duplex && s->side == SIDE_FRONT && !start) { s->side = SIDE_BACK; s->read = 0; return SANE_STATUS_GOOD; } do { st = get_buffer_status(s, &data_avalible); if (st) goto err; } while (!data_avalible); for (i = 0; i < (duplex ? 2 : 1); i++) { st = buf_init (&s->buf[i], s->side_size); if (st) goto err; } if (pthread_create (&s->thread, NULL, (void *(*)(void *)) read_data, s)) { st = SANE_STATUS_IO_ERROR; goto err; } if (s->val[CROP].b || s->val[LENGTHCTL].b || s->val[LONG_PAPER].b) { pthread_join (s->thread, NULL); s->thread = 0; } return SANE_STATUS_GOOD; err: s->scanning = 0; return st; } SANE_Status sane_read(SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct scanner *s = (struct scanner *) handle; int duplex = s->val[DUPLEX].w; struct buf *b = s->side == SIDE_FRONT ? &s->buf[0] : &s->buf[1]; SANE_Status err = buf_get_err(b); SANE_Int inbuf = 0; *len = 0; if (!s->scanning) return SANE_STATUS_EOF; if (err) goto out; if (s->read) { *len = max_len < (SANE_Int) s->read ? max_len : (SANE_Int) s->read; memcpy(buf, s->data + BUF_SIZE - s->read, *len); s->read -= *len; if (!s->read) pop_buf(b); goto out; } s->data = get_buf(b, &inbuf); if (!s->data) goto out; *len = max_len < inbuf ? max_len : inbuf; if (*len > BUF_SIZE) *len = BUF_SIZE; memcpy(buf, s->data, *len); s->read = inbuf > BUF_SIZE ? BUF_SIZE - *len : inbuf - *len; if (!s->read) pop_buf(b); out: err = *len ? SANE_STATUS_GOOD : buf_get_err(b); if (err == SANE_STATUS_EOF) { if (strcmp(s->val[FEEDER_MODE].s, SANE_I18N("continuous"))) { if (!duplex || s->side == SIDE_BACK) s->scanning = 0; } buf_deinit(b); } else if (err) { unsigned i; for (i = 0; i < sizeof(s->buf) / sizeof(s->buf[0]); i++) buf_deinit(&s->buf[i]); } return err; } void sane_cancel (SANE_Handle handle) { unsigned i; struct scanner *s = (struct scanner *) handle; if (s->scanning && !strcmp (s->val[FEEDER_MODE].s, SANE_I18N ("continuous"))) { stop_adf (s); } if (s->thread) { pthread_cancel (s->thread); pthread_join (s->thread, NULL); s->thread = 0; } for (i = 0; i < sizeof (s->buf) / sizeof (s->buf[0]); i++) buf_deinit (&s->buf[i]); s->scanning = 0; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ h, SANE_Bool __sane_unused__ m) { return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ * fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/teco2.conf.in0000664000175000017500000000117412112021330015065 00000000000000# VM3564 RELISYS AVEC II S3 scanner scsi "RELISYS" "AVEC II S3" # VM356A Primax Jewel 4800 scanner scsi "Primax" "Jewel" # VM356A Relisys APOLLO Express 3 scsi "RELISYS" "APOLLO Express 3" # VM3575 Relisys AVEC Super 3 scsi "RELISYS" "AVEC Super 3" # VM3575 Relisys SCORPIO Super 3 # VM3575 Mustek ScanMagic 4830S # VM6586 Relisys SCORPIO Pro-S scsi "" "Flatbed Scanner" # VM656A Relisys APOLLO Express 6 scsi "RELISYS" "APOLLO Express 6" # VM6575 Relisys SCORPIO Pro scsi "RELISYS" "SCORPIO Pro" # VM6575 Primax Profi 9600 scsi "Primax" "Profi 9600" # VM6586 Primax Profi 19200 scsi "Primax" "Profi 19200" /dev/scanner sane-backends-1.0.27/backend/mustek_pp.h0000664000175000017500000001570512112021330014762 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2003 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef mustek_pp_h #define mustek_pp_h #if defined(HAVE_SYS_TYPES_H) # include #endif #if defined(HAVE_SYS_TIME_H) # include #endif #define DEBUG_NOT_STATIC #include "../include/sane/sanei_debug.h" /* Please note: ASSERT won't go away if you define NDEBUG, it just won't * output a message when ASSERT failes. So if "cond" does anything, it will * be executed, even if NDEBUG is defined... */ #define ASSERT(cond, retval) do { \ if (!(cond)) { \ DBG(2, "assertion %s failed\n", \ STRINGIFY(cond)); \ if (retval >= 0) \ return retval; \ else \ return; \ } \ } /* This macro uses a otherwise unused argument */ #if defined(__GNUC__) # define __UNUSED__ __attribute__ ((unused)) #else # define __UNUSED__ #endif /* the function init uses this callback to register a device to the backend */ typedef SANE_Status (*SANE_Attach_Callback) (SANE_String_Const port, SANE_String_Const name, SANE_Int driver, SANE_Int info); typedef struct { const char *driver; const char *author; const char *version; /* this function detects the presence of a scanner at the * given location */ SANE_Status (*init)(SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach); /* this function returns the informationen needed to set up * the device entry. the info parameter is passed from * init to the attach_callback to this function, to * help to identify the device, before it is registered */ void (*capabilities)(SANE_Int info, SANE_String *model, SANE_String *vendor, SANE_String *type, SANE_Int *maxres, SANE_Int *minres, SANE_Int *maxhsize, SANE_Int *maxvsize, SANE_Int *caps); /* tries to open the given device. returns a fd on success */ SANE_Status (*open)(SANE_String port, SANE_Int caps, SANE_Int *fd); /* start scanning session */ void (*setup)(SANE_Handle hndl); /* processes a configuration option */ SANE_Status (*config)(SANE_Handle hndl, SANE_String_Const optname, SANE_String_Const optval); /* stop scanning session */ void (*close)(SANE_Handle hndl); /* start actuall scan */ SANE_Status (*start)(SANE_Handle hndl); /* read data (one line) */ void (*read)(SANE_Handle hndl, SANE_Byte *buffer); /* stop scanner and return scanhead home */ void (*stop)(SANE_Handle hndl); } Mustek_pp_Functions; /* Drivers */ #define MUSTEK_PP_NUM_DRIVERS ((int)(sizeof(Mustek_pp_Drivers) / \ sizeof(Mustek_pp_Functions))) #define CAP_NOTHING 0 #define CAP_GAMMA_CORRECT 1 #define CAP_INVERT 2 #define CAP_SPEED_SELECT 4 #define CAP_LAMP_OFF 8 #define CAP_TA 16 #define CAP_DEPTH 32 /* Structure for holding name/value options from the configuration file */ typedef struct Mustek_pp_config_option { SANE_String name; SANE_String value; } Mustek_pp_config_option; typedef struct Mustek_pp_Device { struct Mustek_pp_Device *next; SANE_Device sane; /* non-const copy of SANE_Device */ SANE_String name, vendor, model, type; /* port */ SANE_String port; /* part describing hardware capabilities */ int minres; int maxres; int maxhsize; int maxvsize; int caps; /* functions */ Mustek_pp_Functions *func; /* Modified by EDG: device identification is needed to initialize private device descriptor */ SANE_Int info; /* Array of configuration file options */ int numcfgoptions; Mustek_pp_config_option *cfgoptions; } Mustek_pp_Device; #define STATE_IDLE 0 #define STATE_CANCELLED 1 #define STATE_SCANNING 2 #define MODE_BW 0 #define MODE_GRAYSCALE 1 #define MODE_COLOR 2 #define SPEED_SLOWEST 0 #define SPEED_SLOWER 1 #define SPEED_NORMAL 2 #define SPEED_FASTER 3 #define SPEED_FASTEST 4 enum Mustek_pp_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_DEPTH, OPT_RESOLUTION, OPT_PREVIEW, OPT_GRAY_PREVIEW, OPT_SPEED, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_INVERT, OPT_CUSTOM_GAMMA, /* use custom gamma tables? */ /* The gamma vectors MUST appear in the order gray, red, green, blue. */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, /* must come last: */ NUM_OPTIONS }; typedef struct Mustek_pp_Handle { struct Mustek_pp_Handle *next; Mustek_pp_Device *dev; int fd; int reader; int pipe; int state; int topX, topY; int bottomX, bottomY; int mode; int res; /* gamma table, etc... */ SANE_Int gamma_table[4][256]; int do_gamma; int invert; int use_ta; int depth; int speed; /* current parameters */ SANE_Parameters params; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; SANE_Range gamma_range; /* options */ SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; time_t lamp_on; void *priv; } Mustek_pp_Handle; #endif /* mustek_pp_h */ sane-backends-1.0.27/backend/epjitsu.c0000664000175000017500000044705113073301665014457 00000000000000/* sane - Scanner Access Now Easy. This file implements a SANE backend for the Fujitsu fi-60F, the ScanSnap S300/S1300, and (hopefully) other Epson-based scanners. Copyright 2007-2015 by m. allan noah Copyright 2009 by Richard Goedeken Development funded by Microdea, Inc., TrueCheck, Inc. and Archivista, GmbH -------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. -------------------------------------------------------------------------- The source code is divided in sections which you can easily find by searching for the tag "@@". Section 1 - Init & static stuff Section 2 - sane_init, _get_devices, _open & friends Section 3 - sane_*_option functions Section 4 - sane_start, _get_param, _read & friends Section 5 - sane_close functions Section 6 - misc functions Changes: v0, 2007-08-08, MAN - initial alpha release, S300 raw data only v1, 2007-09-03, MAN - only supports 300dpi duplex binary for S300 v2, 2007-09-05, MAN - add resolution option (only one choice) - add simplex option v3, 2007-09-12, MAN - add support for 150 dpi resolution v4, 2007-10-03, MAN - change binarization algo to use average of all channels v5, 2007-10-10, MAN - move data blocks to separate file - add basic fi-60F support (600dpi color) v6, 2007-11-12, MAN - move various data vars into transfer structs - move most of read_from_scanner to sane_read - add single line reads to calibration code - generate calibration buffer from above reads v7, 2007-12-05, MAN - split calibration into fine and coarse functions - add S300 fine calibration code - add S300 color and grayscale support v8, 2007-12-06, MAN - change sane_start to call ingest earlier - enable SOURCE_ADF_BACK - add if() around memcopy and better debugs in sane_read - shorten default scan sizes from 15.4 to 11.75 inches v9, 2007-12-17, MAN - fi-60F 300 & 600 dpi support (150 is non-square?) - fi-60F gray & binary support - fi-60F improved calibration v10, 2007-12-19, MAN (SANE v1.0.19) - fix missing function (and memory leak) v11 2008-02-14, MAN - sanei_config_read has already cleaned string (#310597) v12 2008-02-28, MAN - cleanup double free bug with new destroy() v13 2008-09-18, MAN - add working page-height control - add working brightness, contrast and threshold controls - add disabled threshold curve and geometry controls - move initialization code to sane_get_devices, for hotplugging v14 2008-09-24, MAN - support S300 on USB power - support S300 225x200 and 600x600 scans - support for automatic paper length detection (parm.lines = -1) v15 2008-09-24, MAN - expose hardware buttons/sensors as options for S300 v16 2008-10-01, MAN - split fill_frontback_buffers_S300 into 3 functions - enable threshold_curve option - add 1-D dynamic binary thresholding code - remove y-resolution option - pad 225x200 data to 225x225 v17 2008-10-03, MAN - increase scan height ~1/2 inch due to head offset - change page length autodetection condition v18 2009-01-21, MAN - dont export private symbols v19 2009-08-31, RG - rewritten calibration routines v20 2010-02-09, MAN (SANE 1.0.21 to 1.0.24) - cleanup #include lines & copyright - add S1300 v21 2011-04-15, MAN - unreleased attempt at S1100 support v22 2014-05-15, MAN/Hiroshi Miura - port some S1100 changes from v21 - add paper size support v23 2014-05-20, MAN - add S1300i support - fix buffer overruns in read_from_scanner - set default page width - simplified the 225x200 resolution code v24 2014-06-01, MAN - enable fine calibration for S1300i 225 & 300 dpi, and S300 150 dpi v25 2014-06-04, MAN - initial support for fi-65F - initial support for S1100 v26 2014-06-28, MAN - add resolution scaling - fix 150 dpi settings for fi-60F and fi-65F - make adf_height_padding variable - make white_factor variable v27 2015-01-24, MAN - don't override br_x and br_y - call change_params after changing page_width v28 2015-03-23, MAN - call get_hardware_status before starting scan v29 2017-03-18, MAN - fix infinite loop when scaling in Y direction v30 2017-03-21, MAN - fix image truncation when using 150 DPI in Y direction - add 200 and 400 DPI Y direction support for fi-60F/65F v31 2017-04-09, MAN - hardware gray support for fi-60F/65F (disabled pending calibration) - merge fi-60F/65F settings SANE FLOW DIAGRAM - sane_init() : initialize backend . - sane_get_devices() : query list of scanner devices . - sane_open() : open a particular scanner device . . - sane_set_io_mode : set blocking mode . . - sane_get_select_fd : get scanner fd . . . . - sane_get_option_descriptor() : get option information . . - sane_control_option() : change option values . . - sane_get_parameters() : returns estimated scan parameters . . - (repeat previous 3 functions) . . . . - sane_start() : start image acquisition . . - sane_get_parameters() : returns actual scan parameters . . - sane_read() : read image data (from pipe) . . (sane_read called multiple times; after sane_read returns EOF, . . loop may continue with sane_start which may return a 2nd page . . when doing duplex scans, or load the next page from the ADF) . . . . - sane_cancel() : cancel operation . - sane_close() : close opened scanner device - sane_exit() : terminate use of backend */ /* * @@ Section 1 - Init */ #include "../include/sane/config.h" #include /*memcpy...*/ #include /*isspace*/ #include /*tan*/ #include /*usleep*/ #include /*time*/ #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "epjitsu.h" #include "epjitsu-cmd.h" #define DEBUG 1 #define BUILD 31 #ifndef MAX3 #define MAX3(a,b,c) ((a) > (b) ? ((a) > (c) ? a : c) : ((b) > (c) ? b : c)) #endif unsigned char global_firmware_filename[PATH_MAX]; /* values for SANE_DEBUG_EPJITSU env var: - errors 5 - function trace 10 - function detail 15 - get/setopt cmds 20 - usb cmd trace 25 - usb cmd detail 30 - useless noise 35 */ /* Calibration settings */ #define COARSE_OFFSET_TARGET 15 static int coarse_gain_min[3] = { 88, 88, 88 }; /* front, back, FI-60F 3rd plane */ static int coarse_gain_max[3] = { 92, 92, 92 }; static int fine_gain_target[3] = {185, 150, 170}; /* front, back, FI-60F is this ok? */ /* ------------------------------------------------------------------------- */ #define STRING_FLATBED SANE_I18N("Flatbed") #define STRING_ADFFRONT SANE_I18N("ADF Front") #define STRING_ADFBACK SANE_I18N("ADF Back") #define STRING_ADFDUPLEX SANE_I18N("ADF Duplex") #define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART #define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY #define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR /* * used by attach* and sane_get_devices * a ptr to a null term array of ptrs to SANE_Device structs * a ptr to a single-linked list of scanner structs */ static const SANE_Device **sane_devArray = NULL; static struct scanner *scanner_devList = NULL; /* * @@ Section 2 - SANE & scanner init code */ /* * Called by SANE initially. * * From the SANE spec: * This function must be called before any other SANE function can be * called. The behavior of a SANE backend is undefined if this * function is not called first. The version code of the backend is * returned in the value pointed to by version_code. If that pointer * is NULL, no version code is returned. Argument authorize is either * a pointer to a function that is invoked when the backend requires * authentication for a specific resource or NULL if the frontend does * not support authentication. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { authorize = authorize; /* get rid of compiler warning */ DBG_INIT (); DBG (10, "sane_init: start\n"); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (5, "sane_init: epjitsu backend %d.%d.%d, from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); DBG (10, "sane_init: finish\n"); return SANE_STATUS_GOOD; } /* * Called by SANE to find out about supported devices. * * From the SANE spec: * This function can be used to query the list of devices that are * available. If the function executes successfully, it stores a * pointer to a NULL terminated array of pointers to SANE_Device * structures in *device_list. The returned list is guaranteed to * remain unchanged and valid until (a) another call to this function * is performed or (b) a call to sane_exit() is performed. This * function can be called repeatedly to detect when new devices become * available. If argument local_only is true, only local devices are * returned (devices directly attached to the machine that SANE is * running on). If it is false, the device list includes all remote * devices that are accessible to the SANE library. * * SANE does not require that this function is called before a * sane_open() call is performed. A device name may be specified * explicitly by a user which would make it unnecessary and * undesirable to call this function first. * * Read the config file, find scanners with help from sanei_* * store in global device structs */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { SANE_Status ret = SANE_STATUS_GOOD; struct scanner * s; struct scanner * prev = NULL; char line[PATH_MAX]; const char *lp; FILE *fp; int num_devices=0; int i=0; local_only = local_only; /* get rid of compiler warning */ DBG (10, "sane_get_devices: start\n"); /* mark all existing scanners as missing, attach_one will remove mark */ for (s = scanner_devList; s; s = s->next) { s->missing = 1; } sanei_usb_init(); fp = sanei_config_open (CONFIG_FILE); if (fp) { DBG (15, "sane_get_devices: reading config file %s\n", CONFIG_FILE); while (sanei_config_read (line, PATH_MAX, fp)) { lp = line; /* ignore comments */ if (*lp == '#') continue; /* skip empty lines */ if (*lp == 0) continue; if ((strncmp ("firmware", lp, 8) == 0) && isspace (lp[8])) { lp += 8; lp = sanei_config_skip_whitespace (lp); DBG (15, "sane_get_devices: firmware '%s'\n", lp); strncpy((char *)global_firmware_filename,lp,PATH_MAX); } else if ((strncmp ("usb", lp, 3) == 0) && isspace (lp[3])) { DBG (15, "sane_get_devices: looking for '%s'\n", lp); sanei_usb_attach_matching_devices(lp, attach_one); } else{ DBG (5, "sane_get_devices: config line \"%s\" ignored.\n", lp); } } fclose (fp); } else { DBG (5, "sane_get_devices: no config file '%s'!\n", CONFIG_FILE); } /*delete missing scanners from list*/ for (s = scanner_devList; s;) { if(s->missing){ DBG (5, "sane_get_devices: missing scanner %s\n",s->sane.name); /*splice s out of list by changing pointer in prev to next*/ if(prev){ prev->next = s->next; free(s); s=prev->next; } /*remove s from head of list, using prev to cache it*/ else{ prev = s; s = s->next; free(prev); prev=NULL; /*reset head to next s*/ scanner_devList = s; } } else{ prev = s; s=prev->next; } } for (s = scanner_devList; s; s=s->next) { DBG (15, "sane_get_devices: found scanner %s\n",s->sane.name); num_devices++; } DBG (15, "sane_get_devices: found %d scanner(s)\n",num_devices); if (sane_devArray) free (sane_devArray); sane_devArray = calloc (num_devices + 1, sizeof (SANE_Device*)); if (!sane_devArray) return SANE_STATUS_NO_MEM; for (s = scanner_devList; s; s=s->next) { sane_devArray[i++] = (SANE_Device *)&s->sane; } sane_devArray[i] = 0; if(device_list){ *device_list = sane_devArray; } DBG (10, "sane_get_devices: finish\n"); return ret; } /* callback used by sane_init * build the scanner struct and link to global list * unless struct is already loaded, then pretend */ static SANE_Status attach_one (const char *name) { struct scanner *s; int ret, i; DBG (10, "attach_one: start '%s'\n", name); for (s = scanner_devList; s; s = s->next) { if (strcmp (s->sane.name, name) == 0) { DBG (10, "attach_one: already attached!\n"); s->missing = 0; return SANE_STATUS_GOOD; } } /* build a scanner struct to hold it */ DBG (15, "attach_one: init struct\n"); if ((s = calloc (sizeof (*s), 1)) == NULL) return SANE_STATUS_NO_MEM; /* copy the device name */ s->sane.name = strdup (name); if (!s->sane.name){ destroy(s); return SANE_STATUS_NO_MEM; } /* connect the fd */ DBG (15, "attach_one: connect fd\n"); s->fd = -1; ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ destroy(s); return ret; } /* load the firmware file into scanner */ ret = load_fw(s); if (ret != SANE_STATUS_GOOD) { destroy(s); DBG (5, "attach_one: firmware load failed\n"); return ret; } /* Now query the device to load its vendor/model/version */ ret = get_ident(s); if (ret != SANE_STATUS_GOOD) { destroy(s); DBG (5, "attach_one: identify failed\n"); return ret; } DBG (15, "attach_one: Found %s scanner %s at %s\n", s->sane.vendor, s->sane.model, s->sane.name); if (strstr (s->sane.model, "S1300i")){ unsigned char stat; DBG (15, "attach_one: Found S1300i\n"); stat = get_stat(s); if(stat & 0x01){ DBG (5, "attach_one: on USB power?\n"); s->usb_power=1; } s->model = MODEL_S1300i; s->has_adf = 1; s->has_adf_duplex = 1; s->min_res = 50; s->max_res = 600; s->adf_height_padding = 600; /* Blue, Red, Green */ s->white_factor[0] = 1.0; s->white_factor[1] = 0.93; s->white_factor[2] = 0.98; s->source = SOURCE_ADF_FRONT; s->mode = MODE_LINEART; s->resolution = 300; s->page_height = 11.5 * 1200; s->page_width = 8.5 * 1200; s->threshold = 120; s->threshold_curve = 55; } else if (strstr (s->sane.model, "S300") || strstr (s->sane.model, "S1300")){ unsigned char stat; DBG (15, "attach_one: Found S300/S1300\n"); stat = get_stat(s); if(stat & 0x01){ DBG (5, "attach_one: on USB power?\n"); s->usb_power=1; } s->model = MODEL_S300; s->has_adf = 1; s->has_adf_duplex = 1; s->min_res = 50; s->max_res = 600; s->adf_height_padding = 600; /* Blue, Red, Green */ s->white_factor[0] = 1.0; s->white_factor[1] = 0.93; s->white_factor[2] = 0.98; s->source = SOURCE_ADF_FRONT; s->mode = MODE_LINEART; s->resolution = 300; s->page_height = 11.5 * 1200; s->page_width = 8.5 * 1200; s->threshold = 120; s->threshold_curve = 55; } else if (strstr (s->sane.model, "S1100")){ DBG (15, "attach_one: Found S1100\n"); s->model = MODEL_S1100; s->usb_power = 1; s->has_adf = 1; s->has_adf_duplex = 0; s->min_res = 50; s->max_res = 600; s->adf_height_padding = 450; /* Blue, Red, Green */ s->white_factor[0] = 0.95; s->white_factor[1] = 1.0; s->white_factor[2] = 1.0; s->source = SOURCE_ADF_FRONT; s->mode = MODE_LINEART; s->resolution = 300; s->page_height = 11.5 * 1200; s->page_width = 8.5 * 1200; s->threshold = 120; s->threshold_curve = 55; } else if (strstr (s->sane.model, "fi-60F")){ DBG (15, "attach_one: Found fi-60F\n"); s->model = MODEL_FI60F; s->has_fb = 1; s->min_res = 50; s->max_res = 600; /* Blue, Red, Green */ s->white_factor[0] = 1.0; s->white_factor[1] = 0.93; s->white_factor[2] = 0.98; s->source = SOURCE_FLATBED; s->mode = MODE_COLOR; s->resolution = 300; s->page_height = 5.83 * 1200; s->page_width = 4.1 * 1200; s->threshold = 120; s->threshold_curve = 55; } else if (strstr (s->sane.model, "fi-65F")){ DBG (15, "attach_one: Found fi-65F\n"); s->model = MODEL_FI65F; s->has_fb = 1; s->min_res = 50; s->max_res = 600; /* Blue, Red, Green */ s->white_factor[0] = 1.0; s->white_factor[1] = 0.93; s->white_factor[2] = 0.98; s->source = SOURCE_FLATBED; s->mode = MODE_COLOR; s->resolution = 300; s->page_height = 5.83 * 1200; s->page_width = 4.1 * 1200; s->threshold = 120; s->threshold_curve = 55; } else{ DBG (15, "attach_one: Found other\n"); } /* set SANE option 'values' to good defaults */ DBG (15, "attach_one: init options\n"); /* go ahead and setup the first opt, because * frontend may call control_option on it * before calling get_option_descriptor */ memset (s->opt, 0, sizeof (s->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].name = "filler"; s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_INACTIVE; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; DBG (15, "attach_one: init settings\n"); ret = change_params(s); /* we close the connection, so that another backend can talk to scanner */ disconnect_fd(s); s->next = scanner_devList; scanner_devList = s; DBG (10, "attach_one: finish\n"); return SANE_STATUS_GOOD; } /* * connect the fd in the scanner struct */ static SANE_Status connect_fd (struct scanner *s) { SANE_Status ret; DBG (10, "connect_fd: start\n"); if(s->fd > -1){ DBG (5, "connect_fd: already open\n"); ret = SANE_STATUS_GOOD; } else { DBG (15, "connect_fd: opening USB device\n"); ret = sanei_usb_open (s->sane.name, &(s->fd)); } if(ret != SANE_STATUS_GOOD){ DBG (5, "connect_fd: could not open device: %d\n", ret); } DBG (10, "connect_fd: finish\n"); return ret; } /* * try to load fw into scanner */ static SANE_Status load_fw (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int file, i; int len = 0; unsigned char * buf; unsigned char cmd[4]; size_t cmdLen; unsigned char stat[2]; size_t statLen; DBG (10, "load_fw: start\n"); /*check status*/ /*reuse stat buffer*/ stat[0] = get_stat(s); if(stat[0] & 0x10){ DBG (5, "load_fw: firmware already loaded?\n"); return SANE_STATUS_GOOD; } if(!global_firmware_filename[0]){ DBG (5, "load_fw: missing filename\n"); return SANE_STATUS_NO_DOCS; } file = open((char *)global_firmware_filename,O_RDONLY); if(!file){ DBG (5, "load_fw: failed to open file %s\n",global_firmware_filename); return SANE_STATUS_NO_DOCS; } /* skip first 256 (=0x100) bytes */ if(lseek(file,0x100,SEEK_SET) != 0x100){ DBG (5, "load_fw: failed to lseek file %s\n",global_firmware_filename); close(file); return SANE_STATUS_NO_DOCS; } buf = malloc(FIRMWARE_LENGTH); if(!buf){ DBG (5, "load_fw: failed to alloc mem\n"); close(file); return SANE_STATUS_NO_MEM; } len = read(file,buf,FIRMWARE_LENGTH); close(file); if(len != FIRMWARE_LENGTH){ DBG (5, "load_fw: firmware file %s wrong length\n", global_firmware_filename); free(buf); return SANE_STATUS_NO_DOCS; } DBG (15, "load_fw: read firmware file %s ok\n", global_firmware_filename); /* firmware upload is in three commands */ /*start/status*/ cmd[0] = 0x1b; cmd[1] = 0x06; cmdLen = 2; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "load_fw: error on cmd 1\n"); free(buf); return ret; } if(stat[0] != 6){ DBG (5, "load_fw: bad stat on cmd 1\n"); free(buf); return SANE_STATUS_IO_ERROR; } /*length/data*/ cmd[0] = 0x01; cmd[1] = 0x00; cmd[2] = 0x01; cmd[3] = 0x00; cmdLen = 4; ret = do_cmd( s, 0, cmd, cmdLen, buf, FIRMWARE_LENGTH, NULL, 0 ); if(ret){ DBG (5, "load_fw: error on cmd 2\n"); free(buf); return ret; } /*checksum/status*/ cmd[0] = 0; for(i=0;i= 0; i--){ in[i] = 0; } s->sane.vendor = strndup((char *)in, 8); for (i = 23; (in[i] == ' ' || in[i] == 0xff) && i >= 8; i--){ in[i] = 0; } s->sane.model= strndup((char *)in+8, 24); s->sane.type = "scanner"; DBG (10, "get_ident: finish\n"); return ret; } /* * From the SANE spec: * This function is used to establish a connection to a particular * device. The name of the device to be opened is passed in argument * name. If the call completes successfully, a handle for the device * is returned in *h. As a special case, specifying a zero-length * string as the device requests opening the first available device * (if there is such a device). */ SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle) { struct scanner *dev = NULL; struct scanner *s = NULL; SANE_Status ret; DBG (10, "sane_open: start\n"); if(scanner_devList){ DBG (15, "sane_open: searching currently attached scanners\n"); } else{ DBG (15, "sane_open: no scanners currently attached, attaching\n"); ret = sane_get_devices(NULL,0); if(ret != SANE_STATUS_GOOD){ return ret; } } if(name[0] == 0){ DBG (15, "sane_open: no device requested, using default\n"); s = scanner_devList; } else{ DBG (15, "sane_open: device %s requested, attaching\n", name); for (dev = scanner_devList; dev; dev = dev->next) { if (strcmp (dev->sane.name, name) == 0) { s = dev; break; } } } if (!s) { DBG (5, "sane_open: no device found\n"); return SANE_STATUS_INVAL; } DBG (15, "sane_open: device %s found\n", s->sane.name); *handle = s; /* connect the fd so we can talk to scanner */ ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ return ret; } DBG (10, "sane_open: finish\n"); return SANE_STATUS_GOOD; } /* * @@ Section 3 - SANE Options functions */ /* * Returns the options we know. * * From the SANE spec: * This function is used to access option descriptors. The function * returns the option descriptor for option number n of the device * represented by handle h. Option number 0 is guaranteed to be a * valid option. Its value is an integer that specifies the number of * options that are available for device handle h (the count includes * option 0). If n is not a valid option index, the function returns * NULL. The returned option descriptor is guaranteed to remain valid * (and at the returned address) until the device is closed. */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct scanner *s = handle; int i; SANE_Option_Descriptor *opt = &s->opt[option]; DBG (20, "sane_get_option_descriptor: %d\n", option); if ((unsigned) option >= NUM_OPTIONS) return NULL; /* "Mode" group -------------------------------------------------------- */ if(option==OPT_MODE_GROUP){ opt->title = "Scan Mode"; opt->desc = ""; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* source */ else if(option==OPT_SOURCE){ i=0; if(s->has_fb){ s->source_list[i++]=STRING_FLATBED; } if(s->has_adf){ s->source_list[i++]=STRING_ADFFRONT; if(s->has_adf_duplex){ s->source_list[i++]=STRING_ADFBACK; s->source_list[i++]=STRING_ADFDUPLEX; } } s->source_list[i]=NULL; opt->name = SANE_NAME_SCAN_SOURCE; opt->title = SANE_TITLE_SCAN_SOURCE; opt->desc = SANE_DESC_SCAN_SOURCE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->source_list; opt->size = maxStringSize (opt->constraint.string_list); if(i > 1){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } } /* scan mode */ else if(option==OPT_MODE){ i=0; s->mode_list[i++]=STRING_LINEART; s->mode_list[i++]=STRING_GRAYSCALE; s->mode_list[i++]=STRING_COLOR; s->mode_list[i]=NULL; opt->name = SANE_NAME_SCAN_MODE; opt->title = SANE_TITLE_SCAN_MODE; opt->desc = SANE_DESC_SCAN_MODE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->mode_list; opt->size = maxStringSize (opt->constraint.string_list); if(i > 1){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } } else if(option==OPT_RES){ opt->name = SANE_NAME_SCAN_RESOLUTION; opt->title = SANE_TITLE_SCAN_RESOLUTION; opt->desc = SANE_DESC_SCAN_RESOLUTION; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_DPI; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->res_range.min = s->min_res; s->res_range.max = s->max_res; s->res_range.quant = 1; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->res_range; } /* "Geometry" group ---------------------------------------------------- */ if(option==OPT_GEOMETRY_GROUP){ opt->name = SANE_NAME_GEOMETRY; opt->title = SANE_TITLE_GEOMETRY; opt->desc = SANE_DESC_GEOMETRY; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* top-left x */ if(option==OPT_TL_X){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->tl_x_range.min = SCANNER_UNIT_TO_FIXED_MM(0); s->tl_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)-s->min_x); s->tl_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_TL_X; opt->title = SANE_TITLE_SCAN_TL_X; opt->desc = SANE_DESC_SCAN_TL_X; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->tl_x_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opt->cap = SANE_CAP_INACTIVE; } /* top-left y */ if(option==OPT_TL_Y){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->tl_y_range.min = SCANNER_UNIT_TO_FIXED_MM(0); s->tl_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)-s->min_y); s->tl_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_TL_Y; opt->title = SANE_TITLE_SCAN_TL_Y; opt->desc = SANE_DESC_SCAN_TL_Y; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->tl_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* bottom-right x */ if(option==OPT_BR_X){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->br_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->br_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); s->br_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_BR_X; opt->title = SANE_TITLE_SCAN_BR_X; opt->desc = SANE_DESC_SCAN_BR_X; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->br_x_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opt->cap = SANE_CAP_INACTIVE; } /* bottom-right y */ if(option==OPT_BR_Y){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->br_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->br_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); s->br_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_BR_Y; opt->title = SANE_TITLE_SCAN_BR_Y; opt->desc = SANE_DESC_SCAN_BR_Y; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->br_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opt->cap = SANE_CAP_INACTIVE; } /* page width */ if(option==OPT_PAGE_WIDTH){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->paper_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->paper_x_range.max = SCANNER_UNIT_TO_FIXED_MM(s->max_x); s->paper_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_PAGE_WIDTH; opt->title = SANE_TITLE_PAGE_WIDTH; opt->desc = SANE_DESC_PAGE_WIDTH; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_x_range; if(s->has_adf){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; } } else{ opt->cap = SANE_CAP_INACTIVE; } } /* page height */ if(option==OPT_PAGE_HEIGHT){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->paper_y_range.min = SCANNER_UNIT_TO_FIXED_MM(0); s->paper_y_range.max = SCANNER_UNIT_TO_FIXED_MM(s->max_y); s->paper_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_PAGE_HEIGHT; opt->title = SANE_TITLE_PAGE_HEIGHT; opt->desc = "Specifies the height of the media, 0 will auto-detect."; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_y_range; if(s->has_adf){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; } } else{ opt->cap = SANE_CAP_INACTIVE; } } /* "Enhancement" group ------------------------------------------------- */ if(option==OPT_ENHANCEMENT_GROUP){ opt->name = SANE_NAME_ENHANCEMENT; opt->title = SANE_TITLE_ENHANCEMENT; opt->desc = SANE_DESC_ENHANCEMENT; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* brightness */ if(option==OPT_BRIGHTNESS){ opt->name = SANE_NAME_BRIGHTNESS; opt->title = SANE_TITLE_BRIGHTNESS; opt->desc = SANE_DESC_BRIGHTNESS; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->brightness_range; s->brightness_range.quant=1; s->brightness_range.min=-127; s->brightness_range.max=127; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* contrast */ if(option==OPT_CONTRAST){ opt->name = SANE_NAME_CONTRAST; opt->title = SANE_TITLE_CONTRAST; opt->desc = SANE_DESC_CONTRAST; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->contrast_range; s->contrast_range.quant=1; s->contrast_range.min=-127; s->contrast_range.max=127; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* gamma */ if(option==OPT_GAMMA){ opt->name = "gamma"; opt->title = "Gamma function exponent"; opt->desc = "Changes intensity of midtones"; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->gamma_range; /* value ranges from .3 to 5, should be log scale? */ s->gamma_range.quant=SANE_FIX(0.01); s->gamma_range.min=SANE_FIX(0.3); s->gamma_range.max=SANE_FIX(5); /*if (s->num_download_gamma){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; }*/ opt->cap = SANE_CAP_INACTIVE; } /*threshold*/ if(option==OPT_THRESHOLD){ opt->name = SANE_NAME_THRESHOLD; opt->title = SANE_TITLE_THRESHOLD; opt->desc = SANE_DESC_THRESHOLD; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->threshold_range; s->threshold_range.min=0; s->threshold_range.max=255; s->threshold_range.quant=1; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->mode != MODE_LINEART){ opt->cap |= SANE_CAP_INACTIVE; } } if(option==OPT_THRESHOLD_CURVE){ opt->name = "threshold-curve"; opt->title = "Threshold curve"; opt->desc = "Dynamic threshold curve, from light to dark, normally 50-65"; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->threshold_curve_range; s->threshold_curve_range.min=0; s->threshold_curve_range.max=127; s->threshold_curve_range.quant=1; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->mode != MODE_LINEART){ opt->cap |= SANE_CAP_INACTIVE; } } /* "Sensor" group ------------------------------------------------------ */ if(option==OPT_SENSOR_GROUP){ opt->name = SANE_NAME_SENSORS; opt->title = SANE_TITLE_SENSORS; opt->desc = SANE_DESC_SENSORS; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; /*flaming hack to get scanimage to hide group*/ if (!s->has_adf) opt->type = SANE_TYPE_BOOL; } if(option==OPT_SCAN_SW){ opt->name = SANE_NAME_SCAN; opt->title = SANE_TITLE_SCAN; opt->desc = SANE_DESC_SCAN; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_adf) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_HOPPER){ opt->name = SANE_NAME_PAGE_LOADED; opt->title = SANE_TITLE_PAGE_LOADED; opt->desc = SANE_DESC_PAGE_LOADED; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_adf) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_TOP){ opt->name = "top-edge"; opt->title = "Top edge"; opt->desc = "Paper is pulled partly into adf"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_adf) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_ADF_OPEN){ opt->name = SANE_NAME_COVER_OPEN; opt->title = SANE_TITLE_COVER_OPEN; opt->desc = SANE_DESC_COVER_OPEN; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_adf) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_SLEEP){ opt->name = "power-save"; opt->title = "Power saving"; opt->desc = "Scanner in power saving mode"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_adf) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } return opt; } /** * Gets or sets an option value. * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which * the option is controlled is specified by parameter action. The * possible values of this parameter are described in more detail * below. The value of the option is passed through argument val. It * is a pointer to the memory that holds the option value. The memory * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon * encountering the first NUL terminator in the string. If argument i * is not NULL, the value of *i will be set to provide details on how * well the request has been met. */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { struct scanner *s = (struct scanner *) handle; SANE_Int dummy = 0; /* Make sure that all those statements involving *info cannot break (better * than having to do "if (info) ..." everywhere!) */ if (info == 0) info = &dummy; if (option >= NUM_OPTIONS) { DBG (5, "sane_control_option: %d too big\n", option); return SANE_STATUS_INVAL; } if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) { DBG (5, "sane_control_option: %d inactive\n", option); return SANE_STATUS_INVAL; } /* * SANE_ACTION_GET_VALUE: We have to find out the current setting and * return it in a human-readable form (often, text). */ if (action == SANE_ACTION_GET_VALUE) { SANE_Word * val_p = (SANE_Word *) val; DBG (20, "sane_control_option: get value for '%s' (%d)\n", s->opt[option].name,option); switch (option) { case OPT_NUM_OPTS: *val_p = NUM_OPTIONS; return SANE_STATUS_GOOD; case OPT_SOURCE: if(s->source == SOURCE_FLATBED){ strcpy (val, STRING_FLATBED); } else if(s->source == SOURCE_ADF_FRONT){ strcpy (val, STRING_ADFFRONT); } else if(s->source == SOURCE_ADF_BACK){ strcpy (val, STRING_ADFBACK); } else if(s->source == SOURCE_ADF_DUPLEX){ strcpy (val, STRING_ADFDUPLEX); } else{ DBG(5,"missing option val for source\n"); } return SANE_STATUS_GOOD; case OPT_MODE: if(s->mode == MODE_LINEART){ strcpy (val, STRING_LINEART); } else if(s->mode == MODE_GRAYSCALE){ strcpy (val, STRING_GRAYSCALE); } else if(s->mode == MODE_COLOR){ strcpy (val, STRING_COLOR); } return SANE_STATUS_GOOD; case OPT_RES: *val_p = s->resolution; return SANE_STATUS_GOOD; case OPT_TL_X: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->tl_x); return SANE_STATUS_GOOD; case OPT_TL_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->tl_y); return SANE_STATUS_GOOD; case OPT_BR_X: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->br_x); return SANE_STATUS_GOOD; case OPT_BR_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->br_y); return SANE_STATUS_GOOD; case OPT_PAGE_WIDTH: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->page_width); return SANE_STATUS_GOOD; case OPT_PAGE_HEIGHT: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->page_height); return SANE_STATUS_GOOD; case OPT_BRIGHTNESS: *val_p = s->brightness; return SANE_STATUS_GOOD; case OPT_CONTRAST: *val_p = s->contrast; return SANE_STATUS_GOOD; case OPT_GAMMA: *val_p = SANE_FIX(s->gamma); return SANE_STATUS_GOOD; case OPT_THRESHOLD: *val_p = s->threshold; return SANE_STATUS_GOOD; case OPT_THRESHOLD_CURVE: *val_p = s->threshold_curve; return SANE_STATUS_GOOD; /* Sensor Group */ case OPT_SCAN_SW: get_hardware_status(s); *val_p = s->hw_scan_sw; return SANE_STATUS_GOOD; case OPT_HOPPER: get_hardware_status(s); *val_p = s->hw_hopper; return SANE_STATUS_GOOD; case OPT_TOP: get_hardware_status(s); *val_p = s->hw_top; return SANE_STATUS_GOOD; case OPT_ADF_OPEN: get_hardware_status(s); *val_p = s->hw_adf_open; return SANE_STATUS_GOOD; case OPT_SLEEP: get_hardware_status(s); *val_p = s->hw_sleep; return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { int tmp; SANE_Word val_c; SANE_Status status; DBG (20, "sane_control_option: set value for '%s' (%d)\n", s->opt[option].name,option); if ( s->started ) { DBG (5, "sane_control_option: cant set, device busy\n"); return SANE_STATUS_DEVICE_BUSY; } if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) { DBG (5, "sane_control_option: not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (5, "sane_control_option: bad value\n"); return status; } /* may have been changed by constrain, so dont copy until now */ val_c = *(SANE_Word *)val; /* * Note - for those options which can assume one of a list of * valid values, we can safely assume that they will have * exactly one of those values because that's what * sanei_constrain_value does. Hence no "else: invalid" branches * below. */ switch (option) { /* Mode Group */ case OPT_SOURCE: if (!strcmp (val, STRING_ADFFRONT)) { tmp = SOURCE_ADF_FRONT; } else if (!strcmp (val, STRING_ADFBACK)) { tmp = SOURCE_ADF_BACK; } else if (!strcmp (val, STRING_ADFDUPLEX)) { tmp = SOURCE_ADF_DUPLEX; } else{ tmp = SOURCE_FLATBED; } if (s->source == tmp) return SANE_STATUS_GOOD; s->source = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_MODE: if (!strcmp (val, STRING_LINEART)) { tmp = MODE_LINEART; } else if (!strcmp (val, STRING_GRAYSCALE)) { tmp = MODE_GRAYSCALE; } else{ tmp = MODE_COLOR; } if (tmp == s->mode) return SANE_STATUS_GOOD; s->mode = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_RES: if (s->resolution == val_c) return SANE_STATUS_GOOD; s->resolution = val_c; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; /* Geometry Group */ case OPT_TL_X: if (s->tl_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->tl_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_TL_Y: if (s->tl_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->tl_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return change_params(s); case OPT_BR_X: if (s->br_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_BR_Y: if (s->br_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->br_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_PAGE_WIDTH: if (s->page_width == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->page_width = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return change_params(s); case OPT_PAGE_HEIGHT: if (s->page_height == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->page_height = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return change_params(s); /* Enhancement Group */ case OPT_BRIGHTNESS: s->brightness = val_c; return SANE_STATUS_GOOD; case OPT_CONTRAST: s->contrast = val_c; return SANE_STATUS_GOOD; case OPT_GAMMA: s->gamma = SANE_UNFIX(val_c); return SANE_STATUS_GOOD; case OPT_THRESHOLD: s->threshold = val_c; return SANE_STATUS_GOOD; case OPT_THRESHOLD_CURVE: s->threshold_curve = val_c; return SANE_STATUS_GOOD; } /* switch */ } /* else */ return SANE_STATUS_INVAL; } /* use height and width to initialize rest of transfer vals */ static void update_transfer_totals(struct transfer * t) { if (t->image == NULL) return; t->total_bytes = t->line_stride * t->image->height; t->rx_bytes = 0; t->done = 0; } /* each model has various settings that differ based on X resolution */ /* we hard-code the list (determined from usb snoops) here */ struct model_res { int model; int mode; int x_res; int y_res; int usb_power; int max_x; int min_x; int max_y; int min_y; int line_stride; /* byte width of 1 raw side, with padding */ int plane_stride; /* byte width of 1 raw color plane, with padding */ int plane_width; /* byte width of 1 raw color plane, without padding */ int block_height; int cal_line_stride; int cal_plane_stride; int cal_plane_width; unsigned char * sw_coarsecal; unsigned char * sw_finecal; unsigned char * sw_sendcal; unsigned char * head_cal1; unsigned char * head_cal2; unsigned char * sw_scan; }; static struct model_res settings[] = { /*S300 AC*/ /* model mode xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ { MODEL_S300, MODE_COLOR, 150, 150, 0, 1296, 32, 2662, 32, 4256*3, 1480*3, 1296, 41, 8512*3, 2960*3, 2592, setWindowCoarseCal_S300_150, setWindowFineCal_S300_150, setWindowSendCal_S300_150, sendCal1Header_S300_150, sendCal2Header_S300_150, setWindowScan_S300_150 }, { MODEL_S300, MODE_COLOR, 225, 200, 0, 1944, 32, 3993, 32, 6144*3, 2100*3, 1944, 28, 8192*3, 2800*3, 2592, setWindowCoarseCal_S300_225, setWindowFineCal_S300_225, setWindowSendCal_S300_225, sendCal1Header_S300_225, sendCal2Header_S300_225, setWindowScan_S300_225 }, { MODEL_S300, MODE_COLOR, 300, 300, 0, 2592, 32, 5324, 32, 8192*3, 2800*3, 2592, 21, 8192*3, 2800*3, 2592, setWindowCoarseCal_S300_300, setWindowFineCal_S300_300, setWindowSendCal_S300_300, sendCal1Header_S300_300, sendCal2Header_S300_300, setWindowScan_S300_300 }, { MODEL_S300, MODE_COLOR, 600, 600, 0, 5184, 32, 10648, 32, 16064*3, 5440*3, 5184, 10, 16064*3, 5440*3, 5184, setWindowCoarseCal_S300_600, setWindowFineCal_S300_600, setWindowSendCal_S300_600, sendCal1Header_S300_600, sendCal2Header_S300_600, setWindowScan_S300_600 }, /*S300 USB*/ /* model mode xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ { MODEL_S300, MODE_COLOR, 150, 150, 1, 1296, 32, 2662, 32, 7216*3, 2960*3, 1296, 24, 14432*3, 5920*3, 2592, setWindowCoarseCal_S300_150_U, setWindowFineCal_S300_150_U, setWindowSendCal_S300_150_U, sendCal1Header_S300_150_U, sendCal2Header_S300_150_U, setWindowScan_S300_150_U }, { MODEL_S300, MODE_COLOR, 225, 200, 1, 1944, 32, 3993, 32, 10584*3, 4320*3, 1944, 16, 14112*3, 5760*3, 2592, setWindowCoarseCal_S300_225_U, setWindowFineCal_S300_225_U, setWindowSendCal_S300_225_U, sendCal1Header_S300_225_U, sendCal2Header_S300_225_U, setWindowScan_S300_225_U }, { MODEL_S300, MODE_COLOR, 300, 300, 1, 2592, 32, 5324, 32, 15872*3, 6640*3, 2592, 11, 15872*3, 6640*3, 2592, setWindowCoarseCal_S300_300_U, setWindowFineCal_S300_300_U, setWindowSendCal_S300_300_U, sendCal1Header_S300_300_U, sendCal2Header_S300_300_U, setWindowScan_S300_300_U }, { MODEL_S300, MODE_COLOR, 600, 600, 1, 5184, 32, 10648, 32, 16064*3, 5440*3, 5184, 10, 16064*3, 5440*3, 5184, setWindowCoarseCal_S300_600, setWindowFineCal_S300_600, setWindowSendCal_S300_600, sendCal1Header_S300_600, sendCal2Header_S300_600, setWindowScan_S300_600 }, /*S1300i AC*/ /* model mode xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ { MODEL_S1300i, MODE_COLOR, 150, 150, 0, 1296, 32, 2662, 32, 4016*3, 1360*3, 1296, 43, 8032*3, 2720*3, 2592, setWindowCoarseCal_S1300i_150, setWindowFineCal_S1300i_150, setWindowSendCal_S1300i_150, sendCal1Header_S1300i_150, sendCal2Header_S1300i_150, setWindowScan_S1300i_150 }, { MODEL_S1300i, MODE_COLOR, 225, 200, 0, 1944, 32, 3993, 32, 6072*3, 2063*3, 1944, 28, 8096*3, 2752*3, 2592, setWindowCoarseCal_S1300i_225, setWindowFineCal_S1300i_225, setWindowSendCal_S1300i_225, sendCal1Header_S1300i_225, sendCal2Header_S1300i_225, setWindowScan_S1300i_225 }, { MODEL_S1300i, MODE_COLOR, 300, 300, 0, 2592, 32, 5324, 32, 8096*3, 2751*3, 2592, 21, 8096*3, 2752*3, 2592, setWindowCoarseCal_S1300i_300, setWindowFineCal_S1300i_300, setWindowSendCal_S1300i_300, sendCal1Header_S1300i_300, sendCal2Header_S1300i_300, setWindowScan_S1300i_300 }, /*NOTE: S1300i uses S300 data blocks for remainder*/ { MODEL_S1300i, MODE_COLOR, 600, 600, 0, 5184, 32, 10648, 32, 16064*3, 5440*3, 5184, 10, 16064*3, 5440*3, 5184, setWindowCoarseCal_S300_600, setWindowFineCal_S300_600, setWindowSendCal_S300_600, sendCal1Header_S300_600, sendCal2Header_S300_600, setWindowScan_S300_600 }, /*S1300i USB*/ /* model mode xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ { MODEL_S1300i, MODE_COLOR, 150, 150, 1, 1296, 32, 2662, 32, 7216*3, 2960*3, 1296, 24, 14432*3, 5920*3, 2592, setWindowCoarseCal_S300_150_U, setWindowFineCal_S300_150_U, setWindowSendCal_S300_150_U, sendCal1Header_S1300i_USB, sendCal2Header_S1300i_USB, setWindowScan_S300_150_U }, { MODEL_S1300i, MODE_COLOR, 225, 200, 1, 1944, 32, 3993, 32, 10584*3, 4320*3, 1944, 16, 14112*3, 5760*3, 2592, setWindowCoarseCal_S300_225_U, setWindowFineCal_S300_225_U, setWindowSendCal_S300_225_U, sendCal1Header_S1300i_USB, sendCal2Header_S1300i_USB, setWindowScan_S300_225_U }, { MODEL_S1300i, MODE_COLOR, 300, 300, 1, 2592, 32, 5324, 32, 15872*3, 6640*3, 2592, 11, 15872*3, 6640*3, 2592, setWindowCoarseCal_S300_300_U, setWindowFineCal_S300_300_U, setWindowSendCal_S300_300_U, sendCal1Header_S1300i_USB, sendCal2Header_S1300i_USB, setWindowScan_S300_300_U }, { MODEL_S1300i, MODE_COLOR, 600, 600, 1, 5184, 32, 10648, 32, 16064*3, 5440*3, 5184, 10, 16064*3, 5440*3, 5184, setWindowCoarseCal_S300_600, setWindowFineCal_S300_600, setWindowSendCal_S300_600, sendCal1Header_S1300i_USB, sendCal2Header_S1300i_USB, setWindowScan_S300_600 }, /*fi-60F/65F GRAY */ /* model mode xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ /* disabled until calibration code supports grayscale { MODEL_FI60F | MODEL_FI65F, MODE_GRAYSCALE, 300, 300, 0, 1296, 32, 1749, 32, 1440, 480, 432, 364, 2400*3, 958*3, 432, setWindowCoarseCal_FI60F_300, setWindowFineCal_FI60F_300, setWindowSendCal_FI60F_300, sendCal1Header_FI60F_300, sendCal2Header_FI60F_300, setWindowScan_FI60F_300_g }, { MODEL_FI60F | MODEL_FI65F, MODE_GRAYSCALE, 600, 400, 0, 2592, 32, 2332, 32, 2592, 864, 864, 202, 2848*3, 978*3, 864, setWindowCoarseCal_FI60F_600, setWindowFineCal_FI60F_600, setWindowSendCal_FI60F_600, sendCal1Header_FI60F_600, sendCal2Header_FI60F_600, setWindowScan_FI60F_400_g }, { MODEL_FI60F | MODEL_FI65F, MODE_GRAYSCALE, 600, 600, 0, 2592, 32, 3498, 32, 2592, 864, 864, 202, 2848*3, 978*3, 864, setWindowCoarseCal_FI60F_600, setWindowFineCal_FI60F_600, setWindowSendCal_FI60F_600, sendCal1Header_FI60F_600, sendCal2Header_FI60F_600, setWindowScan_FI60F_600_g }, */ /*fi-60F/65F*/ /* model mode xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ { MODEL_FI60F | MODEL_FI65F, MODE_COLOR, 300, 150, 0, 1296, 32, 875, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432, setWindowCoarseCal_FI60F_300, setWindowFineCal_FI60F_300, setWindowSendCal_FI60F_300, sendCal1Header_FI60F_300, sendCal2Header_FI60F_300, setWindowScan_FI60F_150 }, { MODEL_FI60F | MODEL_FI65F, MODE_COLOR, 300, 200, 0, 1296, 32, 1166, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432, setWindowCoarseCal_FI60F_300, setWindowFineCal_FI60F_300, setWindowSendCal_FI60F_300, sendCal1Header_FI60F_300, sendCal2Header_FI60F_300, setWindowScan_FI60F_200 }, { MODEL_FI60F | MODEL_FI65F, MODE_COLOR, 300, 300, 0, 1296, 32, 1749, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432, setWindowCoarseCal_FI60F_300, setWindowFineCal_FI60F_300, setWindowSendCal_FI60F_300, sendCal1Header_FI60F_300, sendCal2Header_FI60F_300, setWindowScan_FI60F_300 }, { MODEL_FI60F | MODEL_FI65F, MODE_COLOR, 600, 400, 0, 2592, 32, 2332, 32, 2848*3, 978*3, 864, 61, 2848*3, 978*3, 864, setWindowCoarseCal_FI60F_600, setWindowFineCal_FI60F_600, setWindowSendCal_FI60F_600, sendCal1Header_FI60F_600, sendCal2Header_FI60F_600, setWindowScan_FI60F_400 }, { MODEL_FI60F | MODEL_FI65F, MODE_COLOR, 600, 600, 0, 2592, 32, 3498, 32, 2848*3, 978*3, 864, 61, 2848*3, 978*3, 864, setWindowCoarseCal_FI60F_600, setWindowFineCal_FI60F_600, setWindowSendCal_FI60F_600, sendCal1Header_FI60F_600, sendCal2Header_FI60F_600, setWindowScan_FI60F_600 }, /*S1100 USB*/ /* model mode xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */ { MODEL_S1100, MODE_COLOR, 300, 300, 1, 2592, 32, 5324, 32, 8912, 3160, 2592, 58, 8912, 3160, 2592, setWindowCoarseCal_S1100_300_U, setWindowFineCal_S1100_300_U, setWindowSendCal_S1100_300_U, sendCal1Header_S1100_300_U, sendCal2Header_S1100_300_U, setWindowScan_S1100_300_U }, { MODEL_S1100, MODE_COLOR, 600, 600, 1, 5184, 32, 10648, 32, 15904, 5360, 5184, 32, 15904, 5360, 5184, setWindowCoarseCal_S1100_600_U, setWindowFineCal_S1100_600_U, setWindowSendCal_S1100_600_U, sendCal1Header_S1100_600_U, sendCal2Header_S1100_600_U, setWindowScan_S1100_600_U }, { MODEL_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }, }; /* * clean up scanner struct vals when user changes mode, res, etc */ static SANE_Status change_params(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int img_heads, img_pages, width; int i=0; DBG (10, "change_params: start\n"); do { if(settings[i].model & s->model && settings[i].mode <= s->mode && settings[i].x_res >= s->resolution && settings[i].y_res >= s->resolution && settings[i].usb_power == s->usb_power ){ break; } i++; } while (settings[i].model); if (!settings[i].model){ return SANE_STATUS_INVAL; } /*1200 dpi*/ s->max_x = PIX_TO_SCANNER_UNIT( settings[i].max_x, settings[i].x_res ); s->min_x = PIX_TO_SCANNER_UNIT( settings[i].min_x, settings[i].x_res ); s->max_y = PIX_TO_SCANNER_UNIT( settings[i].max_y, settings[i].y_res ); s->min_y = PIX_TO_SCANNER_UNIT( settings[i].min_y, settings[i].y_res ); /*current dpi*/ s->setWindowCoarseCal = settings[i].sw_coarsecal; s->setWindowCoarseCalLen = SET_WINDOW_LEN; s->setWindowFineCal = settings[i].sw_finecal; s->setWindowFineCalLen = SET_WINDOW_LEN; s->setWindowSendCal = settings[i].sw_sendcal; s->setWindowSendCalLen = SET_WINDOW_LEN; s->sendCal1Header = settings[i].head_cal1; s->sendCal1HeaderLen = 14; s->sendCal2Header = settings[i].head_cal2; s->sendCal2HeaderLen = 7; s->setWindowScan = settings[i].sw_scan; s->setWindowScanLen = SET_WINDOW_LEN; if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { img_heads = 1; /* image width is the same as the plane width on the S300 */ img_pages = 2; } else if (s->model == MODEL_S1100) { img_heads = 1; /* image width is the same as the plane width on the S1000 */ img_pages = 1; } else /* MODEL_FI60F or MODEL_FI65F */ { img_heads = 3; /* image width is 3* the plane width on the FI-60F */ img_pages = 1; } /* height */ if (s->tl_y > s->max_y - s->min_y) s->tl_y = s->max_y - s->min_y - s->adf_height_padding; if (s->tl_y + s->page_height > s->max_y - s->adf_height_padding) s->page_height = s->max_y - s->adf_height_padding - s->tl_y; if (s->page_height < s->min_y && s->page_height > 0) s->page_height = s->min_y; if (s->tl_y + s->page_height > s->max_y) s->tl_y = s->max_y - s->adf_height_padding - s->page_height; if (s->tl_y < 0) s->tl_y = 0; if (s->page_height > 0) { s->br_y = s->tl_y + s->page_height; } else { s->br_y = s->max_y; } /*width*/ if (s->page_width > s->max_x) s->page_width = s->max_x; else if (s->page_width < s->min_x) s->page_width = s->min_x; s->tl_x = (s->max_x - s->page_width)/2; s->br_x = (s->max_x + s->page_width)/2; /*=============================================================*/ /* set up the calibration scan structs */ /* generally full width, short height, full resolution */ s->cal_image.line_stride = settings[i].cal_line_stride; s->cal_image.plane_stride = settings[i].cal_plane_stride; s->cal_image.plane_width = settings[i].cal_plane_width; s->cal_image.mode = MODE_COLOR; s->cal_image.x_res = settings[i].x_res; s->cal_image.y_res = settings[i].y_res; s->cal_image.raw_data = NULL; s->cal_image.image = NULL; /* width is the same, but there are 2 bytes per pixel component */ s->cal_data.line_stride = settings[i].cal_line_stride * 2; s->cal_data.plane_stride = settings[i].cal_plane_stride * 2; s->cal_data.plane_width = settings[i].cal_plane_width; s->cal_data.mode = MODE_COLOR; s->cal_data.x_res = settings[i].x_res; s->cal_data.y_res = settings[i].y_res; s->cal_data.raw_data = NULL; s->cal_data.image = &s->sendcal; /*=============================================================*/ /* set up the calibration image blocks */ width = s->cal_image.plane_width * img_heads; s->coarsecal.width_pix = s->darkcal.width_pix = s->lightcal.width_pix = width; s->coarsecal.width_bytes = s->darkcal.width_bytes = s->lightcal.width_bytes = width * 3; s->coarsecal.height = 1; s->coarsecal.mode = MODE_COLOR; s->coarsecal.x_res = s->darkcal.x_res = s->lightcal.x_res = settings[i].x_res; s->coarsecal.y_res = s->darkcal.y_res = s->lightcal.y_res = settings[i].y_res; s->darkcal.height = s->lightcal.height = 16; s->coarsecal.pages = s->darkcal.pages = s->lightcal.pages = img_pages; s->coarsecal.buffer = s->darkcal.buffer = s->lightcal.buffer = NULL; /* set up the calibration data block */ width = s->cal_data.plane_width * img_heads; s->sendcal.width_pix = width; s->sendcal.width_bytes = width * 6; /* 2 bytes of cal data per pixel component */ s->sendcal.height = 1; s->sendcal.mode = MODE_COLOR; s->sendcal.x_res = settings[i].x_res; s->sendcal.y_res = settings[i].y_res; s->sendcal.pages = img_pages; s->sendcal.buffer = NULL; /*=============================================================*/ /* set up the fullscan parameters */ /* this is bookkeeping for what we actually pull from the scanner */ /* note that this has no image, just dimensions and counters */ s->fullscan.width_bytes = settings[i].line_stride; s->fullscan.mode = settings[i].mode; s->fullscan.x_res = settings[i].x_res; s->fullscan.y_res = settings[i].y_res; if(s->source == SOURCE_FLATBED || !s->page_height) { /* flatbed and adf in autodetect always ask for all*/ s->fullscan.height = SCANNER_UNIT_TO_PIX(s->max_y, s->fullscan.y_res); } else { /* adf with specified paper size requires padding on top of page_height (~1/2in) */ s->fullscan.height = SCANNER_UNIT_TO_PIX((s->page_height + s->tl_y + s->adf_height_padding), s->fullscan.y_res); } /*=============================================================*/ /* set up the input block raw struct */ /* this holds up to 512k of raw scan data */ s->block_xfr.line_stride = settings[i].line_stride; s->block_xfr.plane_stride = settings[i].plane_stride; s->block_xfr.plane_width = settings[i].plane_width; s->block_xfr.mode = settings[i].mode; s->block_xfr.x_res = settings[i].x_res; s->block_xfr.y_res = settings[i].y_res; s->block_xfr.raw_data = NULL; s->block_xfr.image = &s->block_img; /* set up the input block image struct */ /* note that this is the same width/x_res as the final output image */ /* but the mode, height and y_res are the same as block_xfr */ width = (settings[i].max_x * s->resolution / settings[i].x_res); s->block_img.width_pix = width; s->block_img.width_bytes = width * (settings[i].mode == MODE_COLOR ? 3 : 1); s->block_img.height = settings[i].block_height; s->block_img.mode = settings[i].mode; s->block_img.x_res = s->resolution; s->block_img.y_res = settings[i].y_res; s->block_img.pages = img_pages; s->block_img.buffer = NULL; /*=============================================================*/ /* set up the output image structs */ /* output image might be different from scan due to interpolation */ s->front.mode = s->mode; s->front.x_res = s->resolution; s->front.y_res = s->resolution; if(s->source == SOURCE_FLATBED) { /* flatbed ignores the tly */ s->front.height = SCANNER_UNIT_TO_PIX(s->max_y - s->tl_y, s->front.y_res); } else if(!s->page_height) { /* adf in autodetect always asks for all */ s->front.height = SCANNER_UNIT_TO_PIX(s->max_y, s->front.y_res); } else { /* adf with specified paper size */ s->front.height = SCANNER_UNIT_TO_PIX(s->page_height, s->front.y_res); } s->front.width_pix = s->block_img.width_pix; s->front.x_start_offset = (s->block_xfr.image->width_pix - s->front.width_pix)/2; switch (s->mode) { case MODE_COLOR: s->front.width_bytes = s->front.width_pix*3; s->front.x_offset_bytes = s->front.x_start_offset *3; break; case MODE_GRAYSCALE: s->front.width_bytes = s->front.width_pix; s->front.x_offset_bytes = s->front.x_start_offset; break; default: /*binary*/ s->front.width_bytes = s->front.width_pix/8; s->front.width_pix = s->front.width_bytes * 8; /*s->page_width = PIX_TO_SCANNER_UNIT(s->front.width_pix, (img_heads * s->resolution_x));*/ s->front.x_offset_bytes = s->front.x_start_offset/8; break; } /* ADF front need to remove padding header */ if (s->source != SOURCE_FLATBED) { s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y+s->adf_height_padding, s->fullscan.y_res); } else { s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->fullscan.y_res); } s->front.pages = 1; s->front.buffer = NULL; /* back settings always same as front settings */ s->back.width_pix = s->front.width_pix; s->back.width_bytes = s->front.width_bytes; s->back.mode = s->front.mode; s->back.x_res = s->front.x_res; s->back.y_res = s->front.y_res; s->back.height = s->front.height; s->back.x_start_offset = s->front.x_start_offset; s->back.x_offset_bytes = s->front.x_offset_bytes; s->back.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->fullscan.y_res); s->back.pages = 1; s->back.buffer = NULL; /* dynamic threshold temp buffer, in gray */ s->dt.width_pix = s->front.width_pix; s->dt.width_bytes = s->front.width_pix; s->dt.mode = MODE_GRAYSCALE; s->dt.x_res = s->front.x_res; s->dt.y_res = s->front.y_res; s->dt.height = 1; s->dt.pages = 1; s->dt.buffer = NULL; /* set up the pointers to the page images in the page structs */ s->pages[SIDE_FRONT].image = &s->front; s->pages[SIDE_BACK].image = &s->back; s->pages[SIDE_FRONT].done = 0; s->pages[SIDE_BACK].done = 0; DBG (10, "change_params: finish\n"); return ret; } /* Function to build a lookup table (LUT), often used by scanners to implement brightness/contrast/gamma or by backends to speed binarization/thresholding offset and slope inputs are -127 to +127 slope rotates line around central input/output val, 0 makes horizontal line pos zero neg . x . . x . x . . x out . x .xxxxxxxxxxx . x . x . . x ....x....... ............ .......x.... in in in offset moves line vertically, and clamps to output range 0 keeps the line crossing the center of the table high low . xxxxxxxx . . x . out x . x . . x ............ xxxxxxxx.... in in out_min/max provide bounds on output values, useful when building thresholding lut. 0 and 255 are good defaults otherwise. */ static SANE_Status load_lut (unsigned char * lut, int in_bits, int out_bits, int out_min, int out_max, int slope, int offset) { SANE_Status ret = SANE_STATUS_GOOD; int i, j; double shift, rise; int max_in_val = (1 << in_bits) - 1; int max_out_val = (1 << out_bits) - 1; unsigned char * lut_p = lut; DBG (10, "load_lut: start\n"); /* slope is converted to rise per unit run: * first [-127,127] to [-1,1] * then multiply by PI/2 to convert to radians * then take the tangent (T.O.A) * then multiply by the normal linear slope * because the table may not be square, i.e. 1024x256*/ rise = tan((double)slope/127 * M_PI/2) * max_out_val / max_in_val; /* line must stay vertically centered, so figure * out vertical offset at central input value */ shift = (double)max_out_val/2 - (rise*max_in_val/2); /* convert the user offset setting to scale of output * first [-127,127] to [-1,1] * then to [-max_out_val/2,max_out_val/2]*/ shift += (double)offset / 127 * max_out_val / 2; for(i=0;i<=max_in_val;i++){ j = rise*i + shift; if(jout_max){ j=out_max; } *lut_p=j; lut_p++; } hexdump(5, "load_lut: ", lut, max_in_val+1); DBG (10, "load_lut: finish\n"); return ret; } /* * @@ Section 4 - SANE scanning functions */ /* * Called by SANE to retrieve information about the type of data * that the current scan will return. * * From the SANE spec: * This function is used to obtain the current scan parameters. The * returned parameters are guaranteed to be accurate between the time * a scan has been started (sane_start() has been called) and the * completion of that request. Outside of that window, the returned * values are best-effort estimates of what the parameters will be * when sane_start() gets invoked. * * Calling this function before a scan has actually started allows, * for example, to get an estimate of how big the scanned image will * be. The parameters passed to this function are the handle h of the * device for which the parameters should be obtained and a pointer p * to a parameter structure. */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { struct scanner *s = (struct scanner *) handle; DBG (10, "sane_get_parameters: start\n"); params->pixels_per_line = s->front.width_pix; params->bytes_per_line = s->front.width_bytes; if(!s->page_height){ params->lines = -1; } else{ params->lines = s->front.height; } params->last_frame = 1; if (s->mode == MODE_COLOR) { params->format = SANE_FRAME_RGB; params->depth = 8; } else if (s->mode == MODE_GRAYSCALE) { params->format = SANE_FRAME_GRAY; params->depth = 8; } else if (s->mode == MODE_LINEART) { params->format = SANE_FRAME_GRAY; params->depth = 1; } DBG (15, "\tdepth %d\n", params->depth); DBG (15, "\tlines %d\n", params->lines); DBG (15, "\tpixels_per_line %d\n", params->pixels_per_line); DBG (15, "\tbytes_per_line %d\n", params->bytes_per_line); DBG (10, "sane_get_parameters: finish\n"); return SANE_STATUS_GOOD; } /* * Called by SANE when a page acquisition operation is to be started. * FIXME: wont handle SOURCE_ADF_BACK */ SANE_Status sane_start (SANE_Handle handle) { struct scanner *s = handle; SANE_Status ret; int i; DBG (10, "sane_start: start\n"); /* set side marker on first page */ if(!s->started){ if(s->source == SOURCE_ADF_BACK){ s->side = SIDE_BACK; } else{ s->side = SIDE_FRONT; } } /* if already running, duplex needs to switch sides */ else if(s->source == SOURCE_ADF_DUPLEX){ s->side = !s->side; } /* recent scanners need ghs called before scanning */ ret = get_hardware_status(s); /* ingest paper with adf */ if( s->source == SOURCE_ADF_BACK || s->source == SOURCE_ADF_FRONT || (s->source == SOURCE_ADF_DUPLEX && s->side == SIDE_FRONT) ){ ret = object_position(s,EPJITSU_PAPER_INGEST); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to ingest\n"); sane_cancel((SANE_Handle)s); return ret; } } /* first page requires buffers, etc */ if(!s->started){ DBG(15,"sane_start: first page\n"); s->started=1; ret = teardown_buffers(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to teardown buffers\n"); sane_cancel((SANE_Handle)s); return SANE_STATUS_NO_MEM; } ret = change_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to change_params\n"); sane_cancel((SANE_Handle)s); return SANE_STATUS_NO_MEM; } ret = setup_buffers(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to setup buffers\n"); sane_cancel((SANE_Handle)s); return SANE_STATUS_NO_MEM; } ret = load_lut(s->dt_lut, 8, 8, 50, 205, s->threshold_curve, s->threshold-127); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to load_lut for dt\n"); sane_cancel((SANE_Handle)s); return ret; } ret = coarsecal(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to coarsecal\n"); sane_cancel((SANE_Handle)s); return ret; } ret = finecal(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to finecal\n"); sane_cancel((SANE_Handle)s); return ret; } ret = send_lut(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to send lut\n"); sane_cancel((SANE_Handle)s); return ret; } ret = lamp(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to heat lamp\n"); sane_cancel((SANE_Handle)s); return ret; } /*should this be between each page*/ ret = set_window(s,WINDOW_SCAN); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to set window\n"); sane_cancel((SANE_Handle)s); return ret; } } /* reset everything when starting any front, or just back */ if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK){ DBG(15,"sane_start: reset counters\n"); /* reset scan */ s->fullscan.done = 0; s->fullscan.rx_bytes = 0; s->fullscan.total_bytes = s->fullscan.width_bytes * s->fullscan.height; /* reset block */ update_transfer_totals(&s->block_xfr); /* reset front and back page counters */ for (i = 0; i < 2; i++) { struct image *page_img = s->pages[i].image; s->pages[i].bytes_total = page_img->width_bytes * page_img->height; s->pages[i].bytes_scanned = 0; s->pages[i].bytes_read = 0; s->pages[i].lines_rx = 0; s->pages[i].lines_pass = 0; s->pages[i].lines_tx = 0; s->pages[i].done = 0; } ret = scan(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to start scan\n"); sane_cancel((SANE_Handle)s); return ret; } } else{ DBG(15,"sane_start: back side\n"); } DBG (10, "sane_start: finish\n"); return SANE_STATUS_GOOD; } /* the +8 on all the lengths is to makeup for potential block trailers */ static SANE_Status setup_buffers(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "setup_buffers: start\n"); /* temporary cal data */ s->coarsecal.buffer = calloc (1,s->coarsecal.width_bytes * s->coarsecal.height * s->coarsecal.pages); if(!s->coarsecal.buffer){ DBG (5, "setup_buffers: ERROR: failed to setup coarse cal buffer\n"); return SANE_STATUS_NO_MEM; } s->darkcal.buffer = calloc (1,s->darkcal.width_bytes * s->darkcal.height * s->darkcal.pages); if(!s->darkcal.buffer){ DBG (5, "setup_buffers: ERROR: failed to setup fine cal buffer\n"); return SANE_STATUS_NO_MEM; } s->lightcal.buffer = calloc (1,s->lightcal.width_bytes * s->lightcal.height * s->lightcal.pages); if(!s->lightcal.buffer){ DBG (5, "setup_buffers: ERROR: failed to setup fine cal buffer\n"); return SANE_STATUS_NO_MEM; } s->sendcal.buffer = calloc (1,s->sendcal.width_bytes * s->sendcal.height * s->sendcal.pages); if(!s->sendcal.buffer){ DBG (5, "setup_buffers: ERROR: failed to setup send cal buffer\n"); return SANE_STATUS_NO_MEM; } s->cal_image.raw_data = calloc(1, s->cal_image.line_stride * 16 + 8); /* maximum 16 lines input for fine calibration */ if(!s->cal_image.raw_data){ DBG (5, "setup_buffers: ERROR: failed to setup calibration input raw data buffer\n"); return SANE_STATUS_NO_MEM; } s->cal_data.raw_data = calloc(1, s->cal_data.line_stride); /* only 1 line of data is sent */ if(!s->cal_data.raw_data){ DBG (5, "setup_buffers: ERROR: failed to setup calibration output raw data buffer\n"); return SANE_STATUS_NO_MEM; } /* grab up to 512K at a time */ s->block_img.buffer = calloc (1,s->block_img.width_bytes * s->block_img.height * s->block_img.pages); if(!s->block_img.buffer){ DBG (5, "setup_buffers: ERROR: failed to setup block image buffer\n"); return SANE_STATUS_NO_MEM; } s->block_xfr.raw_data = calloc(1, s->block_xfr.line_stride * s->block_img.height + 8); if(!s->block_xfr.raw_data){ DBG (5, "setup_buffers: ERROR: failed to setup block raw data buffer\n"); return SANE_STATUS_NO_MEM; } /* one grayscale line for dynamic threshold */ s->dt.buffer = calloc (1,s->dt.width_bytes * s->dt.height * s->dt.pages); if(!s->dt.buffer){ DBG (5, "setup_buffers: ERROR: failed to setup dt buffer\n"); return SANE_STATUS_NO_MEM; } /* make image buffer to hold frontside data */ if(s->source != SOURCE_ADF_BACK){ s->front.buffer = calloc (1,s->front.width_bytes * s->front.height * s->front.pages); if(!s->front.buffer){ DBG (5, "setup_buffers: ERROR: failed to setup front buffer\n"); return SANE_STATUS_NO_MEM; } } /* make image buffer to hold backside data */ if(s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK){ s->back.buffer = calloc (1,s->back.width_bytes * s->back.height * s->back.pages); if(!s->back.buffer){ DBG (5, "setup_buffers: ERROR: failed to setup back buffer\n"); return SANE_STATUS_NO_MEM; } } DBG (10, "setup_buffers: finish\n"); return ret; } /* coarse calibration consists of: 1. turn lamp off (d0) 2. set window for single line of data (d1) 3. get line (d2) 4. update dark coarse cal (c6) 5. return to #3 if not dark enough 6. turn lamp on (d0) 7. get line (d2) 8. update light coarse cal (c6) 9. return to #7 if not light enough */ static SANE_Status coarsecal_send_cal(struct scanner *s, unsigned char *pay) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[2]; unsigned char stat[1]; size_t cmdLen,statLen,payLen; DBG (5, "coarsecal_send_cal: start\n"); /* send coarse cal (c6) */ cmd[0] = 0x1b; cmd[1] = 0xc6; cmdLen = 2; stat[0] = 0; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "coarsecal_send_cal: error sending c6 cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "coarsecal_send_cal: cmd bad c6 status?\n"); return SANE_STATUS_IO_ERROR; } /*send coarse cal payload*/ stat[0] = 0; statLen = 1; payLen = 28; ret = do_cmd( s, 0, pay, payLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "coarsecal_send_cal: error sending c6 payload\n"); return ret; } if(stat[0] != 6){ DBG (5, "coarsecal_send_cal: c6 payload bad status?\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "coarsecal_send_cal: finish\n"); return ret; } static SANE_Status coarsecal_get_line(struct scanner *s, struct image *img) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[2]; unsigned char stat[1]; size_t cmdLen,statLen; DBG (5, "coarsecal_get_line: start\n"); /* send scan d2 command */ cmd[0] = 0x1b; cmd[1] = 0xd2; cmdLen = 2; stat[0] = 0; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "coarsecal_get_line: error sending d2 cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "coarsecal_get_line: cmd bad d2 status?\n"); return SANE_STATUS_IO_ERROR; } s->cal_image.image = img; update_transfer_totals(&s->cal_image); while(!s->cal_image.done){ ret = read_from_scanner(s,&s->cal_image); if(ret){ DBG (5, "coarsecal_get_line: cant read from scanner\n"); return ret; } } /* convert the raw data into normal packed pixel data */ descramble_raw(s, &s->cal_image); DBG (5, "coarsecal_get_line: finish\n"); return ret; } static SANE_Status coarsecal_dark(struct scanner *s, unsigned char *pay) { SANE_Status ret = SANE_STATUS_GOOD; int try_count, cal_good[2], x, j; int param[2], zcount[2], high_param[2], low_param[2], avg[2], maxval[2]; DBG (5, "coarsecal_dark: start\n"); /* dark cal, lamp off */ ret = lamp(s,0); if(ret){ DBG (5, "coarsecal_dark: error lamp off\n"); return ret; } try_count = 8; param[0] = 63; param[1] = 63; low_param[0] = low_param[1] = -64; /* The S300 will accept coarse offsets from -128 to 127 */ high_param[0] = high_param[1] = 63; /* By our range is limited to converge faster */ cal_good[0] = cal_good[1] = 0; while (try_count > 0){ try_count--; /* update the coarsecal payload to use our new dark offset parameters */ if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { pay[5] = param[0]; pay[7] = param[1]; } else /* MODEL_S1100 or MODEL_FI60F or MODEL_FI65F */ { pay[5] = param[0]; pay[7] = param[0]; pay[9] = param[0]; } ret = coarsecal_send_cal(s, pay); DBG(15, "coarsecal_dark offset: parameter front: %i back: %i\n", param[0], param[1]); ret = coarsecal_get_line(s, &s->coarsecal); /* gather statistics: count the proportion of 0-valued pixels */ /* since the lamp is off, there's no point in looking at the green or blue data - they're all from the same sensor anyway */ zcount[0] = zcount[1] = 0; avg[0] = avg[1] = 0; maxval[0] = maxval[1] = 0; for (j = 0; j < s->coarsecal.pages; j++) { int page_offset = j * s->coarsecal.width_bytes * s->coarsecal.height; for (x = 0; x < s->coarsecal.width_bytes; x++) { int val = s->coarsecal.buffer[page_offset + x]; avg[j] += val; if (val == 0) zcount[j]++; if (val > maxval[j]) maxval[j] = val; } } /* convert the zero counts from a pixel count to a proportion in tenths of a percent */ for (j = 0; j < s->coarsecal.pages; j++) { avg[j] /= s->coarsecal.width_bytes; zcount[j] = zcount[j] * 1000 / s->coarsecal.width_bytes; } DBG(15, "coarsecal_dark offset: average pixel values front: %i back: %i\n", avg[0], avg[1]); DBG(15, "coarsecal_dark offset: maximum pixel values front: %i back: %i\n", maxval[0], maxval[1]); DBG(15, "coarsecal_dark offset: 0-valued pixel count front: %f%% back: %f%%\n", zcount[0] / 10.0f, zcount[1] / 10.0f); /* check the values, adjust parameters if they are not within the target range */ for (j = 0; j < s->coarsecal.pages; j++) { if (!cal_good[j]) { if (avg[j] > COARSE_OFFSET_TARGET) { high_param[j] = param[j]; param[j] = (low_param[j] + high_param[j]) / 2; } else if (avg[j] < COARSE_OFFSET_TARGET) { low_param[j] = param[j]; param[j] = (low_param[j] + high_param[j]) / 2; } else cal_good[j] = 1; } } if (cal_good[0] + cal_good[1] == s->coarsecal.pages) break; } /* continue looping for up to 8 tries */ DBG (5, "coarsecal_dark: finish\n"); return ret; } static SANE_Status coarsecal_light(struct scanner *s, unsigned char *pay) { SANE_Status ret = SANE_STATUS_GOOD; int try_count, cal_good[2], x, i, j; int param[2], zcount[2], high_param[2], low_param[2], avg[2]; int rgb_avg[2][3], rgb_hicount[2][3]; DBG (5, "coarsecal_light: start\n"); /* light cal, lamp on */ ret = lamp(s,1); if(ret){ DBG (5, "coarsecal_light: error lamp on\n"); return ret; } try_count = 8; param[0] = pay[11]; param[1] = pay[13]; low_param[0] = low_param[1] = 0; high_param[0] = high_param[1] = 63; cal_good[0] = cal_good[1] = 0; while (try_count > 0){ try_count--; ret = coarsecal_send_cal(s, pay); DBG(15, "coarsecal_light gain: parameter front: %i back: %i\n", param[0], param[1]); ret = coarsecal_get_line(s, &s->coarsecal); /* gather statistics: count the proportion of 255-valued pixels in each color channel */ /* count the average pixel value in each color channel */ for (i = 0; i < s->coarsecal.pages; i++) for (j = 0; j < 3; j++) rgb_avg[i][j] = rgb_hicount[i][j] = 0; for (i = 0; i < s->coarsecal.pages; i++) { for (x = 0; x < s->coarsecal.width_pix; x++) { /* get color channel values and count of pixels pegged at 255 */ unsigned char *rgbpix = s->coarsecal.buffer + (i * s->coarsecal.width_bytes * s->coarsecal.height) + x * 3; for (j = 0; j < 3; j++) { rgb_avg[i][j] += rgbpix[j]; if (rgbpix[j] == 255) rgb_hicount[i][j]++; } } } /* apply the color correction factors to the averages */ for (i = 0; i < s->coarsecal.pages; i++) for (j = 0; j < 3; j++) rgb_avg[i][j] *= s->white_factor[j]; /* set the gain so that none of the color channels are clipping, ie take the highest channel values */ for (i = 0; i < s->coarsecal.pages; i++) { avg[i] = MAX3(rgb_avg[i][0], rgb_avg[i][1], rgb_avg[i][2]) / s->coarsecal.width_pix; for (j = 0; j < 3; j++) rgb_avg[i][j] /= s->coarsecal.width_pix; } /* convert the 255-counts from a pixel count to a proportion in tenths of a percent */ for (i = 0; i < s->coarsecal.pages; i++) { for (j = 0; j < 3; j++) { rgb_hicount[i][j] = rgb_hicount[i][j] * 1000 / s->coarsecal.width_pix; } zcount[i] = MAX3(rgb_hicount[i][0], rgb_hicount[i][1], rgb_hicount[i][2]); } DBG(15, "coarsecal_light gain: average RGB values front: (%i,%i,%i) back: (%i,%i,%i)\n", rgb_avg[0][0], rgb_avg[0][1], rgb_avg[0][2], rgb_avg[1][0], rgb_avg[1][1], rgb_avg[1][2]); DBG(15, "coarsecal_light gain: 255-valued pixel count front: (%g,%g,%g) back: (%g,%g,%g)\n", rgb_hicount[0][0]/10.0f, rgb_hicount[0][1]/10.0f, rgb_hicount[0][2]/10.0f, rgb_hicount[1][0]/10.0f, rgb_hicount[1][1]/10.0f, rgb_hicount[1][2]/10.0f); /* check the values, adjust parameters if they are not within the target range */ for (x = 0; x < s->coarsecal.pages; x++) { if (!cal_good[x]) { if (zcount[x] > 9 || avg[x] > coarse_gain_max[x]) { high_param[x] = param[x]; param[x] = (low_param[x] + high_param[x]) / 2; } else if (avg[x] < coarse_gain_min[x]) { low_param[x] = param[x]; param[x] = (low_param[x] + high_param[x]) / 2; } else cal_good[x] = 1; } } if (cal_good[0] + cal_good[1] == s->coarsecal.pages) break; /* update the coarsecal payload to use the new gain parameters */ if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { pay[11] = param[0]; pay[13] = param[1]; } else /* MODEL_S1100 or MODEL_FI60F or MODEL_FI65F */ { pay[11] = param[0]; pay[13] = param[0]; pay[15] = param[0]; } } DBG (5, "coarsecal_light: finish\n"); return ret; } static SANE_Status coarsecal(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char pay[28]; size_t payLen; DBG (10, "coarsecal: start\n"); payLen = sizeof(pay); if(s->model == MODEL_S300){ memcpy(pay,coarseCalData_S300,payLen); } else if(s->model == MODEL_S1300i){ memcpy(pay,coarseCalData_S1300i,payLen); } else if(s->model == MODEL_S1100){ memcpy(pay,coarseCalData_S1100,payLen); } else{ memcpy(pay,coarseCalData_FI60F,payLen); } /* ask for 1 line */ ret = set_window(s, WINDOW_COARSECAL); if(ret){ DBG (5, "coarsecal: error sending setwindow\n"); return ret; } if(s->model == MODEL_S1100){ ret = coarsecal_send_cal(s, pay); } else{ ret = coarsecal_dark(s, pay); ret = coarsecal_light(s, pay); } DBG (10, "coarsecal: finish\n"); return ret; } static SANE_Status finecal_send_cal(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; size_t cmdLen = 2; unsigned char cmd[2]; size_t statLen = 1; unsigned char stat[2]; int i, j, k; unsigned char *p_out, *p_in = s->sendcal.buffer; int planes; if(s->model == MODEL_FI60F || s->model == MODEL_FI65F) planes = 3; if(s->model == MODEL_S300 || s->model == MODEL_S1300i) planes = 2; /* scramble the raster buffer data into scanner raw format */ /* this is reverse of descramble_raw */ memset(s->cal_data.raw_data, 0, s->cal_data.line_stride); if(s->model == MODEL_S1100){ planes = 1; for (k = 0; k < s->sendcal.width_pix; k++){ /* column (x) */ /* input is RrGgBb (capital is offset, small is gain) */ /* output is Bb...BbRr...RrGg...Gg*/ /*red*/ p_out = s->cal_data.raw_data + s->cal_data.plane_stride + k*2; *p_out = *p_in; p_out++; p_in++; *p_out = *p_in; p_in++; /*green*/ p_out = s->cal_data.raw_data + 2*s->cal_data.plane_stride + k*2; *p_out = *p_in; p_out++; p_in++; *p_out = *p_in; p_in++; /*blue*/ p_out = s->cal_data.raw_data + k*2; *p_out = *p_in; p_out++; p_in++; *p_out = *p_in; p_in++; } } else{ for (i = 0; i < planes; i++) for (j = 0; j < s->cal_data.plane_width; j++) for (k = 0; k < 3; k++) { p_out = (s->cal_data.raw_data + k * s->cal_data.plane_stride + j * 6 + i * 2); *p_out = *p_in++; /* dark offset */ p_out++; *p_out = *p_in++; /* gain */ } } ret = set_window(s, WINDOW_SENDCAL); if(ret){ DBG (5, "finecal_send_cal: error sending setwindow\n"); return ret; } /*first unknown cal block*/ cmd[0] = 0x1b; cmd[1] = 0xc3; stat[0] = 0; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "finecal_send_cal: error sending c3 cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "finecal_send_cal: cmd bad c3 status?\n"); return SANE_STATUS_IO_ERROR; } /*send header*/ /*send payload*/ statLen = 1; ret = do_cmd( s, 0, s->sendCal1Header, s->sendCal1HeaderLen, s->cal_data.raw_data, s->cal_data.line_stride, stat, &statLen ); if(ret){ DBG (5, "finecal_send_cal: error sending c3 payload\n"); return ret; } if(stat[0] != 6){ DBG (5, "finecal_send_cal: payload bad c3 status?\n"); return SANE_STATUS_IO_ERROR; } /*second unknown cal block*/ cmd[1] = 0xc4; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "finecal_send_cal: error sending c4 cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "finecal_send_cal: cmd bad c4 status?\n"); return SANE_STATUS_IO_ERROR; } /*send header*/ /*send payload*/ statLen = 1; ret = do_cmd( s, 0, s->sendCal2Header, s->sendCal2HeaderLen, s->cal_data.raw_data, s->cal_data.line_stride, stat, &statLen ); if(ret){ DBG (5, "finecal_send_cal: error sending c4 payload\n"); return ret; } if(stat[0] != 6){ DBG (5, "finecal_send_cal: payload bad c4 status?\n"); return SANE_STATUS_IO_ERROR; } return ret; } static SANE_Status finecal_get_line(struct scanner *s, struct image *img) { SANE_Status ret = SANE_STATUS_GOOD; size_t cmdLen = 2; unsigned char cmd[2]; size_t statLen = 1; unsigned char stat[2]; int round_offset = img->height / 2; int i, j, k; /* ask for 16 lines */ ret = set_window(s, WINDOW_FINECAL); if(ret){ DBG (5, "finecal_get_line: error sending setwindowcal\n"); return ret; } /* send scan d2 command */ cmd[0] = 0x1b; cmd[1] = 0xd2; stat[0] = 0; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "finecal_get_line: error sending d2 cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "finecal_get_line: cmd bad d2 status?\n"); return SANE_STATUS_IO_ERROR; } s->cal_image.image = img; update_transfer_totals(&s->cal_image); while(!s->cal_image.done){ ret = read_from_scanner(s,&s->cal_image); if(ret){ DBG (5, "finecal_get_line: cant read from scanner\n"); return ret; } } /* convert the raw data into normal packed pixel data */ descramble_raw(s, &s->cal_image); /* average the columns of pixels together and put the results in the top line(s) */ for (i = 0; i < img->pages; i++) { unsigned char *linepix = img->buffer + i * img->width_bytes * img->height; unsigned char *avgpix = img->buffer + i * img->width_bytes; for (j = 0; j < img->width_bytes; j++) { int total = 0; for (k = 0; k < img->height; k++) total += linepix[j + k * img->width_bytes]; avgpix[j] = (total + round_offset) / img->height; } } return ret; } /* roundf() is c99, so we provide our own, though this version wont return -0 */ static float round2(float x) { return (float)(x >= 0.0) ? (int)(x+0.5) : (int)(x-0.5); } static SANE_Status finecal(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int max_pages; int gain_delta = 0xff - 0xbf; float *gain_slope, *last_error; int i, j, k, idx, try_count, cal_good; DBG (10, "finecal: start\n"); if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { /* S300, S1300 */ max_pages = 2; } else /* fi-60f, S1100 */ { max_pages = 1; } /* set fine dark offset to 0 and fix all fine gains to lowest parameter (0xFF) */ for (i = 0; i < s->sendcal.width_bytes * s->sendcal.pages / 2; i++) { s->sendcal.buffer[i*2] = 0; s->sendcal.buffer[i*2+1] = 0xff; } ret = finecal_send_cal(s); if(ret) return ret; /* grab rows with lamp on */ ret = lamp(s,1); if(ret){ DBG (5, "finecal: error lamp on\n"); return ret; } /* read the low-gain average of 16 lines */ ret = finecal_get_line(s, &s->darkcal); if(ret) return ret; /* set fine dark offset to 0 and fine gain to a fixed higher-gain parameter (0xBF) */ for (i = 0; i < s->sendcal.width_bytes * s->sendcal.pages / 2; i++) { s->sendcal.buffer[i*2] = 0; s->sendcal.buffer[i*2+1] = 0xbf; } ret = finecal_send_cal(s); if(ret) return ret; /* read the high-gain average of 16 lines */ ret = finecal_get_line(s, &s->lightcal); if(ret) return ret; /* calculate the per pixel slope of pixel value delta over gain delta */ gain_slope = malloc(s->lightcal.width_bytes * s->lightcal.pages * sizeof(float)); if (!gain_slope) return SANE_STATUS_NO_MEM; idx = 0; for (i = 0; i < s->lightcal.pages; i++) { for (j = 0; j < s->lightcal.width_pix; j++) { for (k = 0; k < 3; k++) { int value_delta = s->lightcal.buffer[idx] - s->darkcal.buffer[idx]; /* limit this slope to 1 or less, to avoid overshoot if the lightcal ref input is clipped at 255 */ if (value_delta < gain_delta) gain_slope[idx] = -1.0; else gain_slope[idx] = (float) -gain_delta / value_delta; idx++; } } } /* keep track of the last iteration's pixel error. If we overshoot, we can reduce the value of the gain slope */ last_error = malloc(s->lightcal.width_bytes * s->lightcal.pages * sizeof(float)); if (!last_error) { free(gain_slope); return SANE_STATUS_NO_MEM; } for (i = 0; i < s->lightcal.width_bytes * s->lightcal.pages; i++) last_error[i] = 0.0; /* fine calibration feedback loop */ try_count = 8; while (try_count > 0) { int min_value[2][3], max_value[2][3]; float avg_value[2][3], variance[2][3]; int high_pegs = 0, low_pegs = 0; try_count--; /* clear statistics arrays */ for (i = 0; i < max_pages; i++) { for (k = 0; k < 3; k++) { min_value[i][k] = 0xff; max_value[i][k] = 0; avg_value[i][k] = 0; variance[i][k] = 0; } } /* gather statistics and calculate new fine gain parameters based on observed error and the value/gain slope */ idx = 0; for (i = 0; i < max_pages; i++) { for (j = 0; j < s->lightcal.width_pix; j++) { for (k = 0; k < 3; k++) { int pixvalue = s->lightcal.buffer[idx]; float pixerror = (fine_gain_target[i] * s->white_factor[k] - pixvalue); int oldgain = s->sendcal.buffer[idx * 2 + 1]; int newgain; /* if we overshot the last correction, reduce the gain_slope */ if (pixerror * last_error[idx] < 0.0) gain_slope[idx] *= 0.75; last_error[idx] = pixerror; /* set the new gain */ newgain = oldgain + (int) round2(pixerror * gain_slope[idx]); if (newgain < 0) { low_pegs++; s->sendcal.buffer[idx * 2 + 1] = 0; } else if (newgain > 0xff) { high_pegs++; s->sendcal.buffer[idx * 2 + 1] = 0xff; } else s->sendcal.buffer[idx * 2 + 1] = newgain; /* update statistics */ if (pixvalue < min_value[i][k]) min_value[i][k] = pixvalue; if (pixvalue > max_value[i][k]) max_value[i][k] = pixvalue; avg_value[i][k] += pixerror; variance[i][k] += (pixerror * pixerror); idx++; } } } /* finish the statistics calculations */ cal_good = 1; for (i = 0; i < max_pages; i++) { for (k = 0; k < 3; k++) { float sum = avg_value[i][k]; float sum2 = variance[i][k]; avg_value[i][k] = sum / s->lightcal.width_pix; variance[i][k] = ((sum2 - (sum * sum / s->lightcal.width_pix)) / s->lightcal.width_pix); /* if any color channel is too far out of whack, set cal_good to 0 so we'll iterate again */ if (fabs(avg_value[i][k]) > 1.0 || variance[i][k] > 3.0) cal_good = 0; } } /* print debug info */ DBG (15, "finecal: -------------------- Gain\n"); DBG (15, "finecal: RGB Average Error - Front: (%.1f,%.1f,%.1f) - Back: (%.1f,%.1f,%.1f)\n", avg_value[0][0], avg_value[0][1], avg_value[0][2], avg_value[1][0], avg_value[1][1], avg_value[1][2]); DBG (15, "finecal: RGB Maximum - Front: (%i,%i,%i) - Back: (%i,%i,%i)\n", max_value[0][0], max_value[0][1], max_value[0][2], max_value[1][0], max_value[1][1], max_value[1][2]); DBG (15, "finecal: RGB Minimum - Front: (%i,%i,%i) - Back: (%i,%i,%i)\n", min_value[0][0], min_value[0][1], min_value[0][2], min_value[1][0], min_value[1][1], min_value[1][2]); DBG (15, "finecal: Variance - Front: (%.1f,%.1f,%.1f) - Back: (%.1f,%.1f,%.1f)\n", variance[0][0], variance[0][1], variance[0][2], variance[1][0], variance[1][1], variance[1][2]); DBG (15, "finecal: Pegged gain parameters - High (0xff): %i - Low (0): %i\n", high_pegs, low_pegs); /* break out of the loop if our calibration is done */ if (cal_good) break; /* send the new calibration and read a new line */ ret = finecal_send_cal(s); if(ret) { free(gain_slope); free(last_error); return ret; } ret = finecal_get_line(s, &s->lightcal); if(ret) { free(gain_slope); free(last_error); return ret; } } /* release the memory for the reference slope data */ free(gain_slope); free(last_error); DBG (10, "finecal: finish\n"); return ret; } /* * set scanner lamp brightness */ static SANE_Status lamp(struct scanner *s, unsigned char set) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[2]; size_t cmdLen = 2; unsigned char stat[1]; size_t statLen = 1; DBG (10, "lamp: start (%d)\n", set); /*send cmd*/ cmd[0] = 0x1b; cmd[1] = 0xd0; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "lamp: error sending cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "lamp: cmd bad status?\n"); return SANE_STATUS_IO_ERROR; } /*send payload*/ cmd[0] = set; cmdLen = 1; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "lamp: error sending payload\n"); return ret; } if(stat[0] != 6){ DBG (5, "lamp: payload bad status?\n"); return SANE_STATUS_IO_ERROR; } DBG (10, "lamp: finish\n"); return ret; } static SANE_Status set_window(struct scanner *s, int window) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[] = {0x1b, 0xd1}; size_t cmdLen = sizeof(cmd); unsigned char stat[] = {0}; size_t statLen = sizeof(stat); unsigned char * payload; size_t paylen = SET_WINDOW_LEN; DBG (10, "set_window: start, window %d\n",window); switch (window) { case WINDOW_COARSECAL: payload = s->setWindowCoarseCal; paylen = s->setWindowCoarseCalLen; break; case WINDOW_FINECAL: payload = s->setWindowFineCal; paylen = s->setWindowFineCalLen; break; case WINDOW_SENDCAL: payload = s->setWindowSendCal; paylen = s->setWindowSendCalLen; break; case WINDOW_SCAN: payload = s->setWindowScan; paylen = s->setWindowScanLen; set_SW_ypix(payload,s->fullscan.height); break; default: DBG (5, "set_window: unknown window\n"); return SANE_STATUS_INVAL; } /*send cmd*/ ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "set_window: error sending cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "set_window: cmd bad status?\n"); return SANE_STATUS_IO_ERROR; } /*send payload*/ statLen = 1; ret = do_cmd( s, 0, payload, paylen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "set_window: error sending payload\n"); return ret; } if(stat[0] != 6){ DBG (5, "set_window: payload bad status?\n"); return SANE_STATUS_IO_ERROR; } DBG (10, "set_window: finish\n"); return ret; } /* instead of internal brightness/contrast/gamma scanners uses 12bit x 12bit LUT default is linear table of slope 1 brightness and contrast inputs are -127 to +127 contrast rotates slope of line around central input val high low . x . . x . xx out . x . xxxxxxxx . x xx ....x....... ............ in in then brightness moves line vertically, and clamps to 8bit bright dark . xxxxxxxx . . x . out x . x . . x ............ xxxxxxxx.... in in */ static SANE_Status send_lut (struct scanner *s) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[] = {0x1b, 0xc5}; size_t cmdLen = 2; unsigned char stat[1]; size_t statLen = 1; unsigned char *out; size_t outLen; int i, j; double b, slope, offset; int width; int height; DBG (10, "send_lut: start\n"); if (s->model == MODEL_S1100){ outLen = 0x200; width = outLen / 2; /* 1 color, 2 bytes */ height = width; /* square table */ } else if (s->model == MODEL_FI65F){ outLen = 0x600; width = outLen / 6; /* 3 color, 2 bytes */ height = width; /* square table */ } else { outLen = 0x6000; width = outLen / 6; /* 3 colors, 2 bytes */ height = width; /* square table */ } out = ( unsigned char *)malloc(outLen*sizeof(unsigned char)); if (out == NULL){ return SANE_STATUS_NO_MEM; } /* contrast is converted to a slope [0,90] degrees: * first [-127,127] to [0,254] then to [0,1] * then multiply by PI/2 to convert to radians * then take the tangent to get slope (T.O.A) * then multiply by the normal linear slope * because the table may not be square, i.e. 1024x256*/ slope = tan(((double)s->contrast+127)/254 * M_PI/2); /* contrast slope must stay centered, so figure * out vertical offset at central input value */ offset = height/2 - slope*width/2; /* convert the user brightness setting (-127 to +127) * into a scale that covers the range required * to slide the contrast curve entirely off the table */ b = ((double)s->brightness/127) * (slope*(width-1) + offset); DBG (15, "send_lut: %d %f %d %f %f\n", s->brightness, b, s->contrast, slope, offset); for(i=0;i(height-1)){ j=height-1; } if (s->model == MODEL_S1100){ /*only one table, be order*/ out[i*2] = (j >> 8) & 0xff; out[i*2+1] = j & 0xff; } else if (s->model == MODEL_FI65F){ /*first table, be order*/ out[i*2] = (j >> 8) & 0xff; out[i*2+1] = j & 0xff; /*second table, be order*/ out[width*2 + i*2] = (j >> 8) & 0xff; out[width*2 + i*2+1] = j & 0xff; /*third table, be order*/ out[width*4 + i*2] = (j >> 8) & 0xff; out[width*4 + i*2+1] = j & 0xff; } else { /*first table, le order*/ out[i*2] = j & 0xff; out[i*2+1] = (j >> 8) & 0x0f; /*second table, le order*/ out[width*2 + i*2] = j & 0xff; out[width*2 + i*2+1] = (j >> 8) & 0x0f; /*third table, le order*/ out[width*4 + i*2] = j & 0xff; out[width*4 + i*2+1] = (j >> 8) & 0x0f; } } ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "send_lut: error sending cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "send_lut: cmd bad status?\n"); return SANE_STATUS_IO_ERROR; } statLen = 1; ret = do_cmd( s, 0, out, outLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "send_lut: error sending out\n"); return ret; } if(stat[0] != 6){ DBG (5, "send_lut: out bad status?\n"); return SANE_STATUS_IO_ERROR; } DBG (10, "send_lut: finish\n"); return ret; } static SANE_Status get_hardware_status (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "get_hardware_status: start\n"); /* only run this once every second */ if (s->last_ghs < time(NULL)) { unsigned char cmd[2]; size_t cmdLen = sizeof(cmd); unsigned char pay[4]; size_t payLen = sizeof(pay); DBG (15, "get_hardware_status: running\n"); cmd[0] = 0x1b; cmd[1] = 0x33; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, pay, &payLen ); if(ret){ DBG (5, "get_hardware_status: error sending cmd\n"); return ret; } hexdump(5,"ghspayload: ", pay, payLen); s->last_ghs = time(NULL); s->hw_top = ((pay[0] >> 7) & 0x01); s->hw_hopper = !((pay[0] >> 6) & 0x01); s->hw_adf_open = ((pay[0] >> 5) & 0x01); s->hw_sleep = ((pay[1] >> 7) & 0x01); s->hw_scan_sw = ((pay[1] >> 0) & 0x01); } DBG (10, "get_hardware_status: finish\n"); return ret; } static SANE_Status object_position(struct scanner *s, int ingest) { SANE_Status ret = SANE_STATUS_GOOD; int i; unsigned char cmd[2]; size_t cmdLen = sizeof(cmd); unsigned char stat[1]; size_t statLen = sizeof(stat); unsigned char pay[2]; size_t payLen = sizeof(pay); DBG (10, "object_position: start\n"); i = (ingest)?5:1; while(i--){ /*send paper load cmd*/ cmd[0] = 0x1b; cmd[1] = 0xd4; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "object_position: error sending cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "object_position: cmd bad status? %d\n",stat[0]); continue; } /*send payload*/ statLen = 1; payLen = 1; pay[0] = ingest; ret = do_cmd( s, 0, pay, payLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "object_position: error sending payload\n"); return ret; } if(stat[0] == 6){ DBG (5, "object_position: found paper?\n"); break; } else if(stat[0] == 0x15 || stat[0] == 0){ DBG (5, "object_position: no paper?\n"); ret=SANE_STATUS_NO_DOCS; continue; } else{ DBG (5, "object_position: payload bad status?\n"); return SANE_STATUS_IO_ERROR; } } DBG (10, "object_position: finish\n"); return ret; } static SANE_Status scan(struct scanner *s) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[] = {0x1b, 0xd2}; size_t cmdLen = 2; unsigned char stat[1]; size_t statLen = 1; DBG (10, "scan: start\n"); if(s->model == MODEL_S300 || s->model == MODEL_S1100 || s->model == MODEL_S1300i){ cmd[1] = 0xd6; } ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "scan: error sending cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "scan: cmd bad status?\n"); return SANE_STATUS_IO_ERROR; } DBG (10, "scan: finish\n"); return ret; } /* * Called by SANE to read data. * * From the SANE spec: * This function is used to read image data from the device * represented by handle h. Argument buf is a pointer to a memory * area that is at least maxlen bytes long. The number of bytes * returned is stored in *len. A backend must set this to zero when * the call fails (i.e., when a status other than SANE_STATUS_GOOD is * returned). * * When the call succeeds, the number of bytes returned can be * anywhere in the range from 0 to maxlen bytes. */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct scanner *s = (struct scanner *) handle; SANE_Status ret=SANE_STATUS_GOOD; struct page * page; DBG (10, "sane_read: start si:%d len:%d max:%d\n",s->side,*len,max_len); *len = 0; /* cancelled? */ if(!s->started){ DBG (5, "sane_read: call sane_start first\n"); return SANE_STATUS_CANCELLED; } page = &s->pages[s->side]; /* have sent all of current buffer */ if(s->fullscan.done && page->done){ DBG (10, "sane_read: returning eof\n"); /*S1100 needs help to turn off button*/ if(s->model == MODEL_S1100){ usleep(15000); /* eject paper */ ret = object_position(s,EPJITSU_PAPER_EJECT); if (ret != SANE_STATUS_GOOD && ret != SANE_STATUS_NO_DOCS) { DBG (5, "sane_read: ERROR: failed to eject\n"); return ret; } /* reset flashing button? */ ret = six5(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_read: ERROR: failed to six5\n"); return ret; } } return SANE_STATUS_EOF; } /* scan not finished, get more into block buffer */ if(!s->fullscan.done) { /* block buffer currently empty, clean up */ if(!s->block_xfr.rx_bytes) { /* block buffer bigger than remainder of scan, shrink block */ int remainTotal = s->fullscan.total_bytes - s->fullscan.rx_bytes; if(remainTotal < s->block_xfr.total_bytes) { DBG (15, "sane_read: shrinking block to %lu\n", (unsigned long)remainTotal); s->block_xfr.total_bytes = remainTotal; } /* send d3 cmd for S300, S1100, S1300 */ if(s->model == MODEL_S300 || s->model == MODEL_S1100 || s->model == MODEL_S1300i) { unsigned char cmd[] = {0x1b, 0xd3}; size_t cmdLen = 2; unsigned char stat[1]; size_t statLen = 1; DBG (15, "sane_read: d3\n"); ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "sane_read: error sending d3 cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "sane_read: cmd bad status?\n"); return SANE_STATUS_IO_ERROR; } } } ret = read_from_scanner(s, &s->block_xfr); if(ret){ DBG (5, "sane_read: cant read from scanner\n"); return ret; } /* block filled, copy to front/back */ if(s->block_xfr.done) { DBG (15, "sane_read: block buffer full\n"); /* convert the raw color data into normal packed pixel data */ descramble_raw(s, &s->block_xfr); s->block_xfr.done = 0; /* get the 0x43 cmd for the S300, S1100, S1300 */ if(s->model == MODEL_S300 || s->model == MODEL_S1100 || s->model == MODEL_S1300i){ unsigned char cmd[] = {0x1b, 0x43}; size_t cmdLen = 2; unsigned char in[10]; size_t inLen = 10; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, in, &inLen ); hexdump(15, "cmd 43: ", in, inLen); if(ret){ DBG (5, "sane_read: error sending 43 cmd\n"); return ret; } /*copy backside data into buffer*/ if( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK ) ret = copy_block_to_page(s, SIDE_BACK); /*copy frontside data into buffer*/ if( s->source != SOURCE_ADF_BACK ) ret = copy_block_to_page(s, SIDE_FRONT); if(ret){ DBG (5, "sane_read: cant copy to front/back\n"); return ret; } s->fullscan.rx_bytes += s->block_xfr.rx_bytes; /* autodetect mode, check for change length */ if( s->source != SOURCE_FLATBED && !s->page_height ){ int get = (in[6] << 8) | in[7]; /*always have to get full blocks*/ if(get % s->block_img.height){ get += s->block_img.height - (get % s->block_img.height); } if(get < s->fullscan.height){ DBG (15, "sane_read: paper out? %d\n",get); s->fullscan.total_bytes = s->fullscan.width_bytes * get; } } } else { /*fi-60f*/ ret = copy_block_to_page(s, SIDE_FRONT); if(ret){ DBG (5, "sane_read: cant copy to front/back\n"); return ret; } s->fullscan.rx_bytes += s->block_xfr.rx_bytes; } /* reset for next pass */ update_transfer_totals(&s->block_xfr); /* scan now finished */ if(s->fullscan.rx_bytes == s->fullscan.total_bytes){ DBG (15, "sane_read: last block\n"); s->fullscan.done = 1; } } } *len = page->bytes_scanned - page->bytes_read; if(*len > max_len){ *len = max_len; } if(*len){ DBG (10, "sane_read: copy rx:%d tx:%d tot:%d len:%d\n", page->bytes_scanned, page->bytes_read, page->bytes_total,*len); memcpy(buf, page->image->buffer + page->bytes_read, *len); page->bytes_read += *len; /* sent it all, return eof on next read */ if(page->bytes_read == page->bytes_scanned && s->fullscan.done){ DBG (10, "sane_read: side done\n"); page->done = 1; } } DBG (10, "sane_read: finish si:%d len:%d max:%d\n",s->side,*len,max_len); return ret; } static SANE_Status six5 (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[2]; size_t cmdLen = sizeof(cmd); unsigned char stat[1]; size_t statLen = sizeof(stat); DBG (10, "six5: start\n"); cmd[0] = 0x1b; cmd[1] = 0x65; statLen = 1; ret = do_cmd( s, 0, cmd, cmdLen, NULL, 0, stat, &statLen ); if(ret){ DBG (5, "six5: error sending cmd\n"); return ret; } if(stat[0] != 6){ DBG (5, "six5: cmd bad status? %d\n",stat[0]); return SANE_STATUS_IO_ERROR; } DBG (10, "six5: finish\n"); return ret; } /* de-scrambles the raw data from the scanner into the image buffer */ /* the output image might be lower dpi than input image, so we scale horizontally */ /* if the input image is mirrored left to right, we do not correct it here */ /* if the input image has padding (at the end or between heads), it is removed here */ static SANE_Status descramble_raw(struct scanner *s, struct transfer * tp) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char *p_out = tp->image->buffer; int height = tp->total_bytes / tp->line_stride; int i, j, k; /* raw gray data handled in another function */ if(tp->mode == MODE_GRAYSCALE){ return descramble_raw_gray(s, tp); } DBG(15, "descramble_raw: start\n"); if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { for (i = 0; i < 2; i++){ /* page, front/back */ for (j = 0; j < height; j++){ /* row (y)*/ int curr_col = 0; int r=0, g=0, b=0, ppc=0; for (k = 0; k <= tp->plane_width; k++){ /* column (x) */ int this_col = k*tp->image->x_res/tp->x_res; /* going to change output pixel, dump rgb and reset */ if(ppc && curr_col != this_col){ *p_out = r/ppc; p_out++; *p_out = g/ppc; p_out++; *p_out = b/ppc; p_out++; r = g = b = ppc = 0; curr_col = this_col; } if(k == tp->plane_width || this_col >= tp->image->width_pix){ break; } /*red is first*/ r += tp->raw_data[j*tp->line_stride + k*3 + i]; /*green is second*/ g += tp->raw_data[j*tp->line_stride + tp->plane_stride + k*3 + i]; /*blue is third*/ b += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k*3 + i]; ppc++; } } } } else if (s->model == MODEL_S1100){ for (j = 0; j < height; j++){ /* row (y)*/ int curr_col = 0; int r=0, g=0, b=0, ppc=0; for (k = 0; k <= tp->plane_width; k++){ /* column (x) */ int this_col = k*tp->image->x_res/tp->x_res; /* going to change output pixel, dump rgb and reset */ if(ppc && curr_col != this_col){ *p_out = r/ppc; p_out++; *p_out = g/ppc; p_out++; *p_out = b/ppc; p_out++; r = g = b = ppc = 0; curr_col = this_col; } if(k == tp->plane_width || this_col >= tp->image->width_pix){ break; } /*red is second*/ r += tp->raw_data[j*tp->line_stride + tp->plane_stride + k]; /*green is third*/ g += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k]; /*blue is first*/ b += tp->raw_data[j*tp->line_stride + k]; ppc++; } } } else { /* MODEL_FI60F or MODEL_FI65F */ for (j = 0; j < height; j++){ /* row (y)*/ int curr_col = 0; for (i = 0; i < 3; i++){ /* read head */ int r=0, g=0, b=0, ppc=0; for (k = 0; k <= tp->plane_width; k++){ /* column (x) within the read head */ int this_col = (k+i*tp->plane_width)*tp->image->x_res/tp->x_res; /* going to change output pixel, dump rgb and reset */ if(ppc && curr_col != this_col){ *p_out = r/ppc; p_out++; *p_out = g/ppc; p_out++; *p_out = b/ppc; p_out++; r = g = b = ppc = 0; curr_col = this_col; } if(k == tp->plane_width || this_col >= tp->image->width_pix){ break; } /*red is first*/ r += tp->raw_data[j*tp->line_stride + k*3 + i]; /*green is second*/ g += tp->raw_data[j*tp->line_stride + tp->plane_stride + k*3 + i]; /*blue is third*/ b += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k*3 + i]; ppc++; } } } } DBG(15, "descramble_raw: finish %d\n", ret); return ret; } /* de-scrambles the raw gray data from the scanner into the image buffer */ /* the output image might be lower dpi than input image, so we scale horizontally */ /* if the input image is mirrored left to right, we do not correct it here */ /* if the input image has padding (at the end or between heads), it is removed here */ static SANE_Status descramble_raw_gray(struct scanner *s, struct transfer * tp) { SANE_Status ret = SANE_STATUS_GOOD; int height = tp->total_bytes / tp->line_stride; int row, col_out; DBG(15, "descramble_raw_gray: start\n"); if (s->model == MODEL_FI60F || s->model == MODEL_FI65F) { for (row = 0; row < height; row++){ unsigned char *p_in = tp->raw_data + row * tp->line_stride; unsigned char *p_out = tp->image->buffer + row * tp->image->width_pix; for (col_out = 0; col_out < tp->image->width_pix; col_out++){ int col_in = col_out * tp->x_res/tp->image->x_res; int offset = col_in%tp->plane_width; int step = col_in/tp->plane_width; *p_out = *(p_in + offset*3 + step); p_out++; } } } else{ DBG(5, "internal error: descramble_raw_gray not supported\n"); ret = SANE_STATUS_INVAL; } DBG(15, "descramble_raw_gray: finish %d\n", ret); return ret; } /* fills block buffer a little per pass */ static SANE_Status read_from_scanner(struct scanner *s, struct transfer * tp) { SANE_Status ret=SANE_STATUS_GOOD; size_t bytes = MAX_IMG_PASS; size_t remainBlock = tp->total_bytes - tp->rx_bytes + 8; unsigned char * buf; size_t bufLen; /* determine amount to ask for, S1300i wants big requests */ if(bytes > remainBlock && s->model != MODEL_S1300i){ bytes = remainBlock; } if (tp->image == NULL) { DBG(5, "internal error: read_from_scanner called with no destination image.\n"); return SANE_STATUS_INVAL; } DBG (10, "read_from_scanner: start rB:%lu len:%lu\n", (unsigned long)remainBlock, (unsigned long)bytes); if(!bytes){ DBG(10, "read_from_scanner: no bytes!\n"); return SANE_STATUS_INVAL; } bufLen = bytes; buf = malloc(bufLen); if(!buf){ DBG (5, "read_from_scanner: failed to alloc mem\n"); return SANE_STATUS_NO_MEM; } ret = do_cmd( s, 0, NULL, 0, NULL, 0, buf, &bytes ); /* full read or short read */ if (ret == SANE_STATUS_GOOD || (ret == SANE_STATUS_EOF && bytes) ) { DBG(15,"read_from_scanner: got GOOD/EOF (%lu)\n",(unsigned long)bytes); if(bytes > remainBlock){ DBG(15,"read_from_scanner: block too big?\n"); bytes = remainBlock; } if(bytes == remainBlock){ DBG(15,"read_from_scanner: block done, ignoring trailer\n"); bytes -= 8; tp->done = 1; } memcpy(tp->raw_data + tp->rx_bytes, buf, bytes); tp->rx_bytes += bytes; ret = SANE_STATUS_GOOD; } else { DBG(5, "read_from_scanner: error reading status = %d\n", ret); } free(buf); DBG (10, "read_from_scanner: finish rB:%lu len:%lu\n", (unsigned long)(tp->total_bytes - tp->rx_bytes + 8), (unsigned long)bytes); return ret; } /* copies block buffer into front or back image buffer */ /* converts pixel data from input mode (color/gray) to output mode (color/gray/binary) */ /* the output image might be lower dpi than input image, so we scale vertically */ /* the input is already scaled horizontally and padding skipped if required */ /* if the input is mirrored left to right, we fix it here */ static SANE_Status copy_block_to_page(struct scanner *s,int side) { SANE_Status ret = SANE_STATUS_GOOD; struct transfer * block = &s->block_xfr; struct page * page = &s->pages[side]; int image_height = block->total_bytes / block->line_stride; int page_width = page->image->width_pix; int block_page_stride = block->image->width_bytes * block->image->height; int line_reverse = (side == SIDE_BACK) || (s->model == MODEL_FI60F) || (s->model == MODEL_FI65F); int i,j,k=0; int curr_in_row = s->fullscan.rx_bytes/s->fullscan.width_bytes; int last_out_row = (page->bytes_scanned / page->image->width_bytes) - 1; DBG (10, "copy_block_to_page: start\n"); /* skip padding and tl_y */ if (s->fullscan.rx_bytes + s->block_xfr.rx_bytes <= block->line_stride * page->image->y_skip_offset) { DBG (10, "copy_block_to_page: before the start? %d\n", side); return ret; } else if (s->fullscan.rx_bytes < block->line_stride * page->image->y_skip_offset) { k = page->image->y_skip_offset - s->fullscan.rx_bytes / block->line_stride; DBG (10, "copy_block_to_page: k start? %d\n", k); } /* loop over all the lines in the block */ for (i = k; i < image_height; i++) { /* determine source and dest rows (dpi scaling) */ int this_in_row = curr_in_row + i; int this_out_row = (this_in_row - page->image->y_skip_offset) * page->image->y_res / s->fullscan.y_res; DBG (15, "copy_block_to_page: in %d out %d lastout %d\n", this_in_row, this_out_row, last_out_row); DBG (15, "copy_block_to_page: bs %d wb %d\n", page->bytes_scanned, page->image->width_bytes); /* don't walk off the end of the output buffer */ if(this_out_row >= page->image->height || this_out_row < 0){ DBG (10, "copy_block_to_page: out of space? %d\n", side); DBG (10, "copy_block_to_page: rx:%d tx:%d tot:%d line:%d\n", page->bytes_scanned, page->bytes_read, page->bytes_total,page->image->width_bytes); return ret; } /* ok, different output row, so we do the math */ if(this_out_row > last_out_row){ unsigned char * p_in = block->image->buffer + (side * block_page_stride) + (i * block->image->width_bytes) + page->image->x_start_offset * 3; unsigned char * p_out = page->image->buffer + this_out_row * page->image->width_bytes; unsigned char * lineStart = p_out; last_out_row = this_out_row; if (block->mode == MODE_COLOR){ /* reverse order for back side or FI-60F scanner */ if (line_reverse) p_in += (page_width - 1) * 3; /* convert all of the pixels in this row */ for (j = 0; j < page_width; j++) { unsigned char r, g, b; if (s->model == MODEL_S300 || s->model == MODEL_S1300i) { r = p_in[1]; g = p_in[2]; b = p_in[0]; } else /* MODEL_FI60F or MODEL_FI65F or MODEL_S1100 */ { r = p_in[0]; g = p_in[1]; b = p_in[2]; } if (s->mode == MODE_COLOR) { *p_out++ = r; *p_out++ = g; *p_out++ = b; } else if (s->mode == MODE_GRAYSCALE) { *p_out++ = (r + g + b) / 3; } else if (s->mode == MODE_LINEART) { s->dt.buffer[j] = (r + g + b) / 3; /* stores dt temp image buffer and binarize afterward */ } if (line_reverse) p_in -= 3; else p_in += 3; } } /* grayscale input */ else{ unsigned char * p_in = block->image->buffer + (side * block_page_stride) + (i * block->image->width_bytes) + page->image->x_start_offset; /* reverse order for back side or FI-60F scanner */ if (line_reverse) p_in += (page_width - 1); //memcpy(p_out,p_in,page->image->width_bytes); for (j = 0; j < page_width; j++) { if (s->mode == MODE_GRAYSCALE) { *p_out++ = *p_in; } else if (s->mode == MODE_LINEART) { s->dt.buffer[j] = *p_in; /* stores dt temp image buffer and binarize afterward */ } if (line_reverse) p_in--; else p_in++; } } /* skip non-transfer pixels in block image buffer */ if (line_reverse) p_in -= page->image->x_offset_bytes; else p_in += page->image->x_offset_bytes; /* for MODE_LINEART, binarize the gray line stored in the temp image buffer(dt) */ /* bacause dt.width = page_width, we pass page_width */ if (s->mode == MODE_LINEART) binarize_line(s, lineStart, page_width); page->bytes_scanned += page->image->width_bytes; } } DBG (10, "copy_block_to_page: finish\n"); return ret; } /*uses the threshold/threshold_curve to control binarization*/ static SANE_Status binarize_line(struct scanner *s, unsigned char *lineOut, int width) { SANE_Status ret = SANE_STATUS_GOOD; int j, windowX, sum = 0; /* ~1mm works best, but the window needs to have odd # of pixels */ windowX = 6 * s->resolution / 150; if (!(windowX % 2)) windowX++; /*second, prefill the sliding sum*/ for (j = 0; j < windowX; j++) sum += s->dt.buffer[j]; /* third, walk the dt buffer, update the sliding sum, */ /* determine threshold, output bits */ for (j = 0; j < width; j++) { /*output image location*/ int offset = j % 8; unsigned char mask = 0x80 >> offset; int thresh = s->threshold; /* move sum/update threshold only if there is a curve*/ if (s->threshold_curve) { int addCol = j + windowX/2; int dropCol = addCol - windowX; if (dropCol >= 0 && addCol < width) { sum -= s->dt.buffer[dropCol]; sum += s->dt.buffer[addCol]; } thresh = s->dt_lut[sum/windowX]; } /*use average to lookup threshold*/ if (s->dt.buffer[j] > thresh) *lineOut &= ~mask; /* white */ else *lineOut |= mask; /* black */ if (offset == 7) lineOut++; } return ret; } /* * @@ Section 4 - SANE cleanup functions */ /* * Cancels a scan. * * From the SANE spec: * This function is used to immediately or as quickly as possible * cancel the currently pending operation of the device represented by * handle h. This function can be called at any time (as long as * handle h is a valid handle) but usually affects long-running * operations only (such as image is acquisition). It is safe to call * this function asynchronously (e.g., from within a signal handler). * It is important to note that completion of this operaton does not * imply that the currently pending operation has been cancelled. It * only guarantees that cancellation has been initiated. Cancellation * completes only when the cancelled call returns (typically with a * status value of SANE_STATUS_CANCELLED). Since the SANE API does * not require any other operations to be re-entrant, this implies * that a frontend must not call any other operation until the * cancelled operation has returned. */ void sane_cancel (SANE_Handle handle) { /*FIXME: actually ask the scanner to stop?*/ struct scanner * s = (struct scanner *) handle; DBG (10, "sane_cancel: start\n"); s->started = 0; DBG (10, "sane_cancel: finish\n"); } /* * Ends use of the scanner. * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is * presently active, a call to sane_cancel() is performed first. After * this function returns, handle h must not be used anymore. */ void sane_close (SANE_Handle handle) { struct scanner * s = (struct scanner *) handle; DBG (10, "sane_close: start\n"); /* still connected- drop it */ if(s->fd >= 0){ sane_cancel(handle); lamp(s, 0); disconnect_fd(s); } DBG (10, "sane_close: finish\n"); } static SANE_Status disconnect_fd (struct scanner *s) { DBG (10, "disconnect_fd: start\n"); if(s->fd > -1){ DBG (15, "disconnecting usb device\n"); sanei_usb_close (s->fd); s->fd = -1; } DBG (10, "disconnect_fd: finish\n"); return SANE_STATUS_GOOD; } static SANE_Status destroy(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "destroy: start\n"); teardown_buffers(s); if(s->sane.name){ free((void *) s->sane.name); } if(s->sane.vendor){ free((void *) s->sane.vendor); } if(s->sane.model){ free((void *) s->sane.model); } free(s); DBG (10, "destroy: finish\n"); return ret; } static SANE_Status teardown_buffers(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "teardown_buffers: start\n"); /* temporary cal data */ if(s->coarsecal.buffer){ free(s->coarsecal.buffer); s->coarsecal.buffer = NULL; } if(s->darkcal.buffer){ free(s->darkcal.buffer); s->darkcal.buffer = NULL; } if(s->sendcal.buffer){ free(s->sendcal.buffer); s->sendcal.buffer = NULL; } if(s->cal_image.raw_data){ free(s->cal_image.raw_data); s->cal_image.raw_data = NULL; } if(s->cal_data.raw_data){ free(s->cal_data.raw_data); s->cal_data.raw_data = NULL; } /* image slice */ if(s->block_img.buffer){ free(s->block_img.buffer); s->block_img.buffer = NULL; } if(s->block_xfr.raw_data){ free(s->block_xfr.raw_data); s->block_xfr.raw_data = NULL; } /* dynamic thresh slice */ if(s->dt.buffer){ free(s->dt.buffer); s->dt.buffer = NULL; } /* image buffer to hold frontside data */ if(s->front.buffer){ free(s->front.buffer); s->front.buffer = NULL; } /* image buffer to hold backside data */ if(s->back.buffer){ free(s->back.buffer); s->back.buffer = NULL; } DBG (10, "teardown_buffers: finish\n"); return ret; } /* * Terminates the backend. * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be * open (it is recommended to close device handles explicitly through * a call to sane_close(), but backends are required to release all * resources upon a call to this function). After this function * returns, no function other than sane_init() may be called * (regardless of the status value returned by sane_exit(). Neglecting * to call this function may result in some resources not being * released properly. */ void sane_exit (void) { struct scanner *dev, *next; DBG (10, "sane_exit: start\n"); for (dev = scanner_devList; dev; dev = next) { next = dev->next; destroy(dev); } if (sane_devArray) free (sane_devArray); scanner_devList = NULL; sane_devArray = NULL; DBG (10, "sane_exit: finish\n"); } /* * @@ Section 5 - misc helper functions */ /* * take a bunch of pointers, send commands to scanner */ static SANE_Status do_cmd(struct scanner *s, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { /* sanei_usb overwrites the transfer size, so make some local copies */ size_t loc_cmdLen = cmdLen; size_t loc_outLen = outLen; size_t loc_inLen = 0; int cmdTime = USB_COMMAND_TIME; int outTime = USB_DATA_TIME; int inTime = USB_DATA_TIME; int ret = 0; DBG (10, "do_cmd: start\n"); if(shortTime){ cmdTime /= 20; outTime /= 20; inTime /= 20; } /* this command has a cmd component, and a place to get it */ if(cmdBuff && cmdLen && cmdTime){ /* change timeout */ sanei_usb_set_timeout(cmdTime); /* write the command out */ DBG(25, "cmd: writing %ld bytes, timeout %d\n", (long)cmdLen, cmdTime); hexdump(30, "cmd: >>", cmdBuff, cmdLen); ret = sanei_usb_write_bulk(s->fd, cmdBuff, &cmdLen); DBG(25, "cmd: wrote %ld bytes, retVal %d\n", (long)cmdLen, ret); if(ret == SANE_STATUS_EOF){ DBG(5,"cmd: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"cmd: return error '%s'\n",sane_strstatus(ret)); return ret; } if(loc_cmdLen != cmdLen){ DBG(5,"cmd: wrong size %ld/%ld\n", (long)loc_cmdLen, (long)cmdLen); return SANE_STATUS_IO_ERROR; } } /* this command has a write component, and a place to get it */ if(outBuff && outLen && outTime){ /* change timeout */ sanei_usb_set_timeout(outTime); DBG(25, "out: writing %ld bytes, timeout %d\n", (long)outLen, outTime); hexdump(30, "out: >>", outBuff, outLen); ret = sanei_usb_write_bulk(s->fd, outBuff, &outLen); DBG(25, "out: wrote %ld bytes, retVal %d\n", (long)outLen, ret); if(ret == SANE_STATUS_EOF){ DBG(5,"out: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"out: return error '%s'\n",sane_strstatus(ret)); return ret; } if(loc_outLen != outLen){ DBG(5,"out: wrong size %ld/%ld\n", (long)loc_outLen, (long)outLen); return SANE_STATUS_IO_ERROR; } } /* this command has a read component, and a place to put it */ if(inBuff && inLen && inTime){ loc_inLen = *inLen; DBG(25, "in: memset %ld bytes\n", (long)*inLen); memset(inBuff,0,*inLen); /* change timeout */ sanei_usb_set_timeout(inTime); DBG(25, "in: reading %ld bytes, timeout %d\n", (long)*inLen, inTime); ret = sanei_usb_read_bulk(s->fd, inBuff, inLen); DBG(25, "in: retVal %d\n", ret); if(ret == SANE_STATUS_EOF){ DBG(5,"in: got EOF, continuing\n"); } else if(ret != SANE_STATUS_GOOD){ DBG(5,"in: return error '%s'\n",sane_strstatus(ret)); return ret; } DBG(25, "in: read %ld bytes\n", (long)*inLen); if(*inLen){ hexdump(30, "in: <<", inBuff, *inLen); } if(loc_inLen != *inLen){ ret = SANE_STATUS_EOF; DBG(5,"in: short read %ld/%ld\n", (long)loc_inLen, (long)*inLen); } } DBG (10, "do_cmd: finish\n"); return ret; } /** * Convenience method to determine longest string size in a list. */ static size_t maxStringSize (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /** * Prints a hex dump of the given buffer onto the debug output stream. */ static void hexdump (int level, char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; if(DBG_LEVEL < level) return; DBG (level, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { *ptr = '\0'; DBG (level, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3x:", i); ptr += 4; } sprintf (ptr, " %2.2x", *p); ptr += 3; } *ptr = '\0'; DBG (level, "%s\n", line); } /** * An advanced method we don't support but have to define. */ SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) { DBG (10, "sane_set_io_mode\n"); DBG (15, "%d %p\n", non_blocking, h); return SANE_STATUS_UNSUPPORTED; } /** * An advanced method we don't support but have to define. */ SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) { DBG (10, "sane_get_select_fd\n"); DBG (15, "%p %d\n", h, *fdp); return SANE_STATUS_UNSUPPORTED; } /* s->page_width stores the user setting * for the paper width in adf. sometimes, * we need a value that differs from this * due to using FB */ static int get_page_width(struct scanner *s) { /* scanner max for fb */ if(s->source == SOURCE_FLATBED){ return s->max_x; } return s->page_width; } /* s->page_height stores the user setting * for the paper height in adf. sometimes, * we need a value that differs from this * due to using FB. */ static int get_page_height(struct scanner *s) { /* scanner max for fb */ if(s->source == SOURCE_FLATBED){ return s->max_y; } return s->page_height; } sane-backends-1.0.27/backend/hp-option.h0000664000175000017500000002323412112021330014664 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ /* $Id$ */ #ifndef HP_OPTION_H_INCLUDED #define HP_OPTION_H_INCLUDED #include "hp.h" /* * Non-standard SANE options * * FIXME: this should become standard */ #ifndef SANE_NAME_SHARPENING # define SANE_NAME_SHARPENING "sharpening" # define SANE_TITLE_SHARPENING SANE_I18N("Sharpening") # define SANE_DESC_SHARPENING SANE_I18N("Set sharpening value.") #endif #ifndef SANE_NAME_AUTO_THRESHOLD # define SANE_NAME_AUTO_THRESHOLD "auto-threshold" # define SANE_TITLE_AUTO_THRESHOLD SANE_I18N("Auto Threshold") # define SANE_DESC_AUTO_THRESHOLD \ SANE_I18N("Enable automatic determination of threshold for line-art scans.") #endif #ifndef SANE_NAME_SMOOTHING # define SANE_NAME_SMOOTHING "smoothing" # define SANE_TITLE_SMOOTHING SANE_I18N("Smoothing") # define SANE_DESC_SMOOTHING SANE_I18N("Select smoothing filter.") #endif #ifndef SANE_NAME_UNLOAD_AFTER_SCAN # define SANE_NAME_UNLOAD_AFTER_SCAN "unload-after-scan" # define SANE_TITLE_UNLOAD_AFTER_SCAN SANE_I18N("Unload media after scan") # define SANE_DESC_UNLOAD_AFTER_SCAN SANE_I18N("Unloads the media after a scan.") #endif #ifndef SANE_NAME_CHANGE_DOC # define SANE_NAME_CHANGE_DOC "change-document" # define SANE_TITLE_CHANGE_DOC SANE_I18N("Change document") # define SANE_DESC_CHANGE_DOC SANE_I18N("Change Document.") #endif #ifndef SANE_NAME_UNLOAD # define SANE_NAME_UNLOAD "unload" # define SANE_TITLE_UNLOAD SANE_I18N("Unload") # define SANE_DESC_UNLOAD SANE_I18N("Unload Document.") #endif #ifndef SANE_NAME_CALIBRATE # define SANE_NAME_CALIBRATE "calibrate" # define SANE_TITLE_CALIBRATE SANE_I18N("Calibrate") # define SANE_DESC_CALIBRATE SANE_I18N("Start calibration process.") #endif #ifndef SANE_NAME_MEDIA # define SANE_NAME_MEDIA "media-type" # define SANE_TITLE_MEDIA SANE_I18N("Media") # define SANE_DESC_MEDIA SANE_I18N("Set type of media.") #endif #ifndef SANE_NAME_PS_EXPOSURE_TIME # define SANE_NAME_PS_EXPOSURE_TIME "ps-exposure-time" # define SANE_TITLE_PS_EXPOSURE_TIME SANE_I18N("Exposure time") # define SANE_DESC_PS_EXPOSURE_TIME \ SANE_I18N("A longer exposure time lets the scanner\ collect more light. Suggested use is 175% for prints,\ 150% for normal slides and \"Negative\" for\ negative film. For dark (underexposed) images you can increase this value.") #endif #ifndef SANE_NAME_MATRIX_TYPE # define SANE_NAME_MATRIX_TYPE "matrix-type" # define SANE_TITLE_MATRIX_TYPE SANE_I18N("Color Matrix") /* FIXME: better description */ # define SANE_DESC_MATRIX_TYPE SANE_I18N("Set the scanners color matrix.") #endif #ifndef SANE_NAME_MATRIX_RGB # define SANE_NAME_MATRIX_RGB "matrix-rgb" # define SANE_TITLE_MATRIX_RGB SANE_I18N("Color Matrix") # define SANE_DESC_MATRIX_RGB SANE_I18N("Custom color matrix.") #endif #ifndef SANE_NAME_MATRIX_GRAY # define SANE_NAME_MATRIX_GRAY "matrix-gray" # define SANE_TITLE_MATRIX_GRAY SANE_I18N("Mono Color Matrix") # define SANE_DESC_MATRIX_GRAY SANE_I18N("Custom color matrix for grayscale scans.") #endif #ifndef SANE_NAME_MIRROR_HORIZ # define SANE_NAME_MIRROR_HORIZ "mirror-horizontal" # define SANE_TITLE_MIRROR_HORIZ SANE_I18N("Mirror horizontal") # define SANE_DESC_MIRROR_HORIZ SANE_I18N("Mirror image horizontally.") #endif #ifndef SANE_NAME_MIRROR_VERT # define SANE_NAME_MIRROR_VERT "mirror-vertical" # define SANE_TITLE_MIRROR_VERT SANE_I18N("Mirror vertical") # define SANE_DESC_MIRROR_VERT SANE_I18N("Mirror image vertically.") #endif #ifndef SANE_NAME_UPDATE # define SANE_NAME_UPDATE "update-options" # define SANE_TITLE_UPDATE SANE_I18N("Update options") # define SANE_DESC_UPDATE SANE_I18N("Update options.") #endif #ifndef SANE_NAME_OUTPUT_8BIT # define SANE_NAME_OUTPUT_8BIT "output-8bit" # define SANE_TITLE_OUTPUT_8BIT SANE_I18N("8 bit output") # define SANE_DESC_OUTPUT_8BIT \ SANE_I18N("Use bit depth greater eight internally,\ but output only eight bits.") #endif #ifndef SANE_NAME_BUTTON_WAIT # define SANE_NAME_BUTTON_WAIT "button-wait" # define SANE_TITLE_BUTTON_WAIT SANE_I18N("Front button wait") # define SANE_DESC_BUTTON_WAIT SANE_I18N("Wait to scan for front-panel button push.") # define HP_BUTTON_WAIT_NO 0 # define HP_BUTTON_WAIT_YES 1 #endif #ifndef SANE_NAME_LAMP_OFF # define SANE_NAME_LAMP_OFF "lamp-off" # define SANE_TITLE_LAMP_OFF SANE_I18N("Shut off lamp") # define SANE_DESC_LAMP_OFF SANE_I18N("Shut off scanner lamp.") # define HP_LAMP_OFF_NO 0 # define HP_LAMP_OFF_YES 1 #endif /* Some test stuff to see what undocumented SCL-commands do */ # define SANE_NAME_10470 "10470" # define SANE_TITLE_10470 "10470" # define SANE_DESC_10470 "10470." # define SANE_NAME_10485 "10485" # define SANE_TITLE_10485 "10485" # define SANE_DESC_10485 "10485." # define SANE_NAME_10952 "10952" # define SANE_TITLE_10952 "10952" # define SANE_DESC_10952 "10952." # define SANE_NAME_10967 "10967" # define SANE_TITLE_10967 "10967" # define SANE_DESC_10967 "10967." /* * Internal option names which are not presented to the SANE frontend. */ #define HP_NAME_HORIZONTAL_DITHER "__hdither__" #define HP_NAME_DEVPIX_RESOLUTION "__devpix_resolution__" #ifdef ENABLE_7x12_TONEMAPS # define HP_NAME_RGB_TONEMAP "__rgb_tonemap__" #endif #ifdef FAKE_COLORSEP_MATRIXES # define HP_NAME_SEPMATRIX "__sepmatrix__" #endif struct hp_choice_s { int val; const char *name; hp_bool_t (*enable)(HpChoice this, HpOptSet optset, HpData data, const HpDeviceInfo *info); hp_bool_t is_emulated:1; HpChoice next; }; enum hp_scanmode_e { HP_SCANMODE_LINEART = 0, HP_SCANMODE_HALFTONE = 3, HP_SCANMODE_GRAYSCALE = 4, HP_SCANMODE_COLOR = 5 }; enum hp_scantype_e { HP_SCANTYPE_NORMAL = 0, HP_SCANTYPE_ADF = 1, HP_SCANTYPE_XPA = 2 }; enum hp_dither_type_e { HP_DITHER_CUSTOM = -1, HP_DITHER_COARSE = 0, HP_DITHER_FINE = 1, HP_DITHER_BAYER = 2, HP_DITHER_VERTICAL = 3, HP_DITHER_HORIZONTAL }; enum hp_matrix_type_e { HP_MATRIX_AUTO = -256, HP_MATRIX_GREEN = -257, HP_MATRIX_CUSTOM_BW = -2, HP_MATRIX_CUSTOM = -1, HP_MATRIX_RGB = 0, HP_MATRIX_BW = 1, HP_MATRIX_PASS = 2, HP_MATRIX_RED = 3, HP_MATRIX_BLUE = 4, HP_MATRIX_XPA_RGB = 5, HP_MATRIX_XPA_BW = 6 }; enum hp_mirror_horiz_e { HP_MIRROR_HORIZ_CONDITIONAL = -256, HP_MIRROR_HORIZ_OFF = 0, HP_MIRROR_HORIZ_ON = 1 }; enum hp_mirror_vert_e { HP_MIRROR_VERT_OFF = -258, HP_MIRROR_VERT_ON = -257, HP_MIRROR_VERT_CONDITIONAL = -256 }; enum hp_media_e { HP_MEDIA_NEGATIVE = 1, HP_MEDIA_SLIDE = 2, HP_MEDIA_PRINT = 3 }; hp_bool_t sanei_hp_choice_isEnabled (HpChoice this, HpOptSet optset, HpData data, const HpDeviceInfo *info); SANE_Status sanei_hp_optset_new(HpOptSet * newp, HpScsi scsi, HpDevice dev); SANE_Status sanei_hp_optset_download (HpOptSet this, HpData data, HpScsi scsi); SANE_Status sanei_hp_optset_control (HpOptSet this, HpData data, int optnum, SANE_Action action, void * valp, SANE_Int *infop, HpScsi scsi, hp_bool_t immediate); SANE_Status sanei_hp_optset_guessParameters (HpOptSet this, HpData data, SANE_Parameters * p); enum hp_scanmode_e sanei_hp_optset_scanmode (HpOptSet this, HpData data); hp_bool_t sanei_hp_optset_output_8bit (HpOptSet this, HpData data); int sanei_hp_optset_data_width (HpOptSet this, HpData data); hp_bool_t sanei_hp_optset_isImmediate (HpOptSet this, int optnum); hp_bool_t sanei_hp_optset_mirror_vert (HpOptSet this, HpData data, HpScsi scsi); hp_bool_t sanei_hp_optset_start_wait(HpOptSet this, HpData data); HpScl sanei_hp_optset_scan_type (HpOptSet this, HpData data); const SANE_Option_Descriptor * sanei_hp_optset_saneoption (HpOptSet this, HpData data, int optnum); #endif /* HP_OPTION_H_INCLUDED */ sane-backends-1.0.27/backend/net.c0000664000175000017500000017556613106201017013556 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang Copyright (C) 2003, 2008 Julien BLACHE AF-independent code + IPv6, Avahi support This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE network-based meta backend. */ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include "../include/_stdint.h" #include #include #include #include #include #include #ifdef HAVE_LIBC_H # include /* NeXTStep/OpenStep */ #endif #include #include #include #include /* OS/2 needs this _after_ , grrr... */ #ifdef WITH_AVAHI # include # include # include # include # include # define SANED_SERVICE_DNS "_sane-port._tcp" static AvahiClient *avahi_client = NULL; static AvahiThreadedPoll *avahi_thread = NULL; static AvahiServiceBrowser *avahi_browser = NULL; #endif /* WITH_AVAHI */ #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_net.h" #include "../include/sane/sanei_codec_bin.h" #include "net.h" #define BACKEND_NAME net #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define NET_CONFIG_FILE "net.conf" /* Please increase version number with every change (don't forget to update net.desc) */ /* define the version string depending on which network code is used */ #if defined (HAVE_GETADDRINFO) && defined (HAVE_GETNAMEINFO) # define NET_USES_AF_INDEP # ifdef ENABLE_IPV6 # define NET_VERSION "1.0.14 (AF-indep+IPv6)" # else # define NET_VERSION "1.0.14 (AF-indep)" # endif /* ENABLE_IPV6 */ #else # undef ENABLE_IPV6 # define NET_VERSION "1.0.14" #endif /* HAVE_GETADDRINFO && HAVE_GETNAMEINFO */ static SANE_Auth_Callback auth_callback; static Net_Device *first_device; static Net_Scanner *first_handle; static const SANE_Device **devlist; static int client_big_endian; /* 1 == big endian; 0 == little endian */ static int server_big_endian; /* 1 == big endian; 0 == little endian */ static int depth; /* bits per pixel */ static int connect_timeout = -1; /* timeout for connection to saned */ #ifndef NET_USES_AF_INDEP static int saned_port; #endif /* !NET_USES_AF_INDEP */ /* This variable is only needed, if the depth is 16bit/channel and client/server have different endianness. A value of -1 means, that there's no hang over; otherwise the value has to be casted to SANE_Byte. hang_over means, that there is a remaining byte from a previous call to sane_read, which could not be byte-swapped, e.g. because the frontend requested an odd number of bytes. */ static int hang_over; /* This variable is only needed, if the depth is 16bit/channel and client/server have different endianness. A value of -1 means, that there's no left over; otherwise the value has to be casted to SANE_Byte. left_over means, that there is a remaining byte from a previous call to sane_read, which already is in the correct byte order, but could not be returned, e.g. because the frontend requested only one byte per call. */ static int left_over; #ifdef NET_USES_AF_INDEP static SANE_Status add_device (const char *name, Net_Device ** ndp) { struct addrinfo hints; struct addrinfo *res; struct addrinfo *resp; struct sockaddr_in *sin; #ifdef ENABLE_IPV6 struct sockaddr_in6 *sin6; #endif /* ENABLE_IPV6 */ Net_Device *nd = NULL; int error; short sane_port = htons (6566); DBG (1, "add_device: adding backend %s\n", name); for (nd = first_device; nd; nd = nd->next) if (strcmp (nd->name, name) == 0) { DBG (1, "add_device: already in list\n"); if (ndp) *ndp = nd; return SANE_STATUS_GOOD; } memset (&hints, 0, sizeof(hints)); # ifdef ENABLE_IPV6 hints.ai_family = PF_UNSPEC; # else hints.ai_family = PF_INET; # endif /* ENABLE_IPV6 */ error = getaddrinfo (name, "sane-port", &hints, &res); if (error) { error = getaddrinfo (name, NULL, &hints, &res); if (error) { DBG (1, "add_device: error while getting address of host %s: %s\n", name, gai_strerror (error)); return SANE_STATUS_IO_ERROR; } else { for (resp = res; resp != NULL; resp = resp->ai_next) { switch (resp->ai_family) { case AF_INET: sin = (struct sockaddr_in *) resp->ai_addr; sin->sin_port = sane_port; break; #ifdef ENABLE_IPV6 case AF_INET6: sin6 = (struct sockaddr_in6 *) resp->ai_addr; sin6->sin6_port = sane_port; break; #endif /* ENABLE_IPV6 */ } } } } nd = malloc (sizeof (Net_Device)); if (!nd) { DBG (1, "add_device: not enough memory for Net_Device struct\n"); freeaddrinfo (res); return SANE_STATUS_NO_MEM; } memset (nd, 0, sizeof (Net_Device)); nd->name = strdup (name); if (!nd->name) { DBG (1, "add_device: not enough memory to duplicate name\n"); free(nd); return SANE_STATUS_NO_MEM; } nd->addr = res; nd->ctl = -1; nd->next = first_device; first_device = nd; if (ndp) *ndp = nd; DBG (2, "add_device: backend %s added\n", name); return SANE_STATUS_GOOD; } #else /* !NET_USES_AF_INDEP */ static SANE_Status add_device (const char *name, Net_Device ** ndp) { struct hostent *he; Net_Device *nd; struct sockaddr_in *sin; DBG (1, "add_device: adding backend %s\n", name); for (nd = first_device; nd; nd = nd->next) if (strcmp (nd->name, name) == 0) { DBG (1, "add_device: already in list\n"); if (ndp) *ndp = nd; return SANE_STATUS_GOOD; } he = gethostbyname (name); if (!he) { DBG (1, "add_device: can't get address of host %s\n", name); return SANE_STATUS_IO_ERROR; } if (he->h_addrtype != AF_INET) { DBG (1, "add_device: don't know how to deal with addr family %d\n", he->h_addrtype); return SANE_STATUS_INVAL; } nd = malloc (sizeof (*nd)); if (!nd) { DBG (1, "add_device: not enough memory for Net_Device struct\n"); return SANE_STATUS_NO_MEM; } memset (nd, 0, sizeof (*nd)); nd->name = strdup (name); if (!nd->name) { DBG (1, "add_device: not enough memory to duplicate name\n"); free (nd); return SANE_STATUS_NO_MEM; } nd->addr.sa_family = he->h_addrtype; sin = (struct sockaddr_in *) &nd->addr; memcpy (&sin->sin_addr, he->h_addr_list[0], he->h_length); nd->ctl = -1; nd->next = first_device; first_device = nd; if (ndp) *ndp = nd; DBG (2, "add_device: backend %s added\n", name); return SANE_STATUS_GOOD; } #endif /* NET_USES_AF_INDEP */ #ifdef NET_USES_AF_INDEP static SANE_Status connect_dev (Net_Device * dev) { struct addrinfo *addrp; SANE_Word version_code; SANE_Init_Reply reply; SANE_Status status = SANE_STATUS_IO_ERROR; SANE_Init_Req req; SANE_Bool connected = SANE_FALSE; #ifdef TCP_NODELAY int on = 1; int level = -1; #endif struct timeval tv; int i; DBG (2, "connect_dev: trying to connect to %s\n", dev->name); for (addrp = dev->addr, i = 0; (addrp != NULL) && (connected == SANE_FALSE); addrp = addrp->ai_next, i++) { # ifdef ENABLE_IPV6 if ((addrp->ai_family != AF_INET) && (addrp->ai_family != AF_INET6)) # else /* !ENABLE_IPV6 */ if (addrp->ai_family != AF_INET) # endif /* ENABLE_IPV6 */ { DBG (1, "connect_dev: [%d] don't know how to deal with addr family %d\n", i, addrp->ai_family); continue; } dev->ctl = socket (addrp->ai_family, SOCK_STREAM, 0); if (dev->ctl < 0) { DBG (1, "connect_dev: [%d] failed to obtain socket (%s)\n", i, strerror (errno)); dev->ctl = -1; continue; } /* Set SO_SNDTIMEO for the connection to saned */ if (connect_timeout > 0) { tv.tv_sec = connect_timeout; tv.tv_usec = 0; if (setsockopt (dev->ctl, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { DBG (1, "connect_dev: [%d] failed to set SO_SNDTIMEO (%s)\n", i, strerror (errno)); } } if (connect (dev->ctl, addrp->ai_addr, addrp->ai_addrlen) < 0) { DBG (1, "connect_dev: [%d] failed to connect (%s)\n", i, strerror (errno)); dev->ctl = -1; continue; } DBG (3, "connect_dev: [%d] connection succeeded (%s)\n", i, (addrp->ai_family == AF_INET6) ? "IPv6" : "IPv4"); dev->addr_used = addrp; connected = SANE_TRUE; } if (connected != SANE_TRUE) { DBG (1, "connect_dev: couldn't connect to host (see messages above)\n"); return SANE_STATUS_IO_ERROR; } #else /* !NET_USES_AF_INDEP */ static SANE_Status connect_dev (Net_Device * dev) { struct sockaddr_in *sin; SANE_Word version_code; SANE_Init_Reply reply; SANE_Status status = SANE_STATUS_IO_ERROR; SANE_Init_Req req; #ifdef TCP_NODELAY int on = 1; int level = -1; #endif struct timeval tv; DBG (2, "connect_dev: trying to connect to %s\n", dev->name); if (dev->addr.sa_family != AF_INET) { DBG (1, "connect_dev: don't know how to deal with addr family %d\n", dev->addr.sa_family); return SANE_STATUS_IO_ERROR; } dev->ctl = socket (dev->addr.sa_family, SOCK_STREAM, 0); if (dev->ctl < 0) { DBG (1, "connect_dev: failed to obtain socket (%s)\n", strerror (errno)); dev->ctl = -1; return SANE_STATUS_IO_ERROR; } sin = (struct sockaddr_in *) &dev->addr; sin->sin_port = saned_port; /* Set SO_SNDTIMEO for the connection to saned */ if (connect_timeout > 0) { tv.tv_sec = connect_timeout; tv.tv_usec = 0; if (setsockopt (dev->ctl, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { DBG (1, "connect_dev: failed to set SO_SNDTIMEO (%s)\n", strerror (errno)); } } if (connect (dev->ctl, &dev->addr, sizeof (dev->addr)) < 0) { DBG (1, "connect_dev: failed to connect (%s)\n", strerror (errno)); dev->ctl = -1; return SANE_STATUS_IO_ERROR; } DBG (3, "connect_dev: connection succeeded\n"); #endif /* NET_USES_AF_INDEP */ /* We're connected now, so reset SO_SNDTIMEO to the default value of 0 */ if (connect_timeout > 0) { tv.tv_sec = 0; tv.tv_usec = 0; if (setsockopt (dev->ctl, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { DBG (1, "connect_dev: failed to reset SO_SNDTIMEO (%s)\n", strerror (errno)); } } #ifdef TCP_NODELAY # ifdef SOL_TCP level = SOL_TCP; # else /* !SOL_TCP */ /* Look up the protocol level in the protocols database. */ { struct protoent *p; p = getprotobyname ("tcp"); if (p == 0) DBG (1, "connect_dev: cannot look up `tcp' protocol number"); else level = p->p_proto; } # endif /* SOL_TCP */ if (level == -1 || setsockopt (dev->ctl, level, TCP_NODELAY, &on, sizeof (on))) DBG (1, "connect_dev: failed to put send socket in TCP_NODELAY mode (%s)", strerror (errno)); #endif /* !TCP_NODELAY */ DBG (2, "connect_dev: sanei_w_init\n"); sanei_w_init (&dev->wire, sanei_codec_bin_init); dev->wire.io.fd = dev->ctl; dev->wire.io.read = read; dev->wire.io.write = write; /* exchange version codes with the server: */ req.version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, SANEI_NET_PROTOCOL_VERSION); req.username = getlogin (); DBG (2, "connect_dev: net_init (user=%s, local version=%d.%d.%d)\n", req.username, V_MAJOR, V_MINOR, SANEI_NET_PROTOCOL_VERSION); sanei_w_call (&dev->wire, SANE_NET_INIT, (WireCodecFunc) sanei_w_init_req, &req, (WireCodecFunc) sanei_w_init_reply, &reply); if (dev->wire.status != 0) { DBG (1, "connect_dev: argument marshalling error (%s)\n", strerror (dev->wire.status)); status = SANE_STATUS_IO_ERROR; goto fail; } status = reply.status; version_code = reply.version_code; DBG (2, "connect_dev: freeing init reply (status=%s, remote " "version=%d.%d.%d)\n", sane_strstatus (status), SANE_VERSION_MAJOR (version_code), SANE_VERSION_MINOR (version_code), SANE_VERSION_BUILD (version_code)); sanei_w_free (&dev->wire, (WireCodecFunc) sanei_w_init_reply, &reply); if (status != 0) { DBG (1, "connect_dev: access to %s denied\n", dev->name); goto fail; } if (SANE_VERSION_MAJOR (version_code) != V_MAJOR) { DBG (1, "connect_dev: major version mismatch: got %d, expected %d\n", SANE_VERSION_MAJOR (version_code), V_MAJOR); status = SANE_STATUS_IO_ERROR; goto fail; } if (SANE_VERSION_BUILD (version_code) != SANEI_NET_PROTOCOL_VERSION && SANE_VERSION_BUILD (version_code) != 2) { DBG (1, "connect_dev: network protocol version mismatch: " "got %d, expected %d\n", SANE_VERSION_BUILD (version_code), SANEI_NET_PROTOCOL_VERSION); status = SANE_STATUS_IO_ERROR; goto fail; } dev->wire.version = SANE_VERSION_BUILD (version_code); DBG (4, "connect_dev: done\n"); return SANE_STATUS_GOOD; fail: DBG (2, "connect_dev: closing connection to %s\n", dev->name); close (dev->ctl); dev->ctl = -1; return status; } static SANE_Status fetch_options (Net_Scanner * s) { int option_number; DBG (3, "fetch_options: %p\n", (void *) s); if (s->opt.num_options) { DBG (2, "fetch_options: %d option descriptors cached... freeing\n", s->opt.num_options); sanei_w_set_dir (&s->hw->wire, WIRE_FREE); s->hw->wire.status = 0; sanei_w_option_descriptor_array (&s->hw->wire, &s->opt); if (s->hw->wire.status) { DBG (1, "fetch_options: failed to free old list (%s)\n", strerror (s->hw->wire.status)); return SANE_STATUS_IO_ERROR; } } DBG (3, "fetch_options: get_option_descriptors\n"); sanei_w_call (&s->hw->wire, SANE_NET_GET_OPTION_DESCRIPTORS, (WireCodecFunc) sanei_w_word, &s->handle, (WireCodecFunc) sanei_w_option_descriptor_array, &s->opt); if (s->hw->wire.status) { DBG (1, "fetch_options: failed to get option descriptors (%s)\n", strerror (s->hw->wire.status)); return SANE_STATUS_IO_ERROR; } if (s->local_opt.num_options == 0) { DBG (3, "fetch_options: creating %d local option descriptors\n", s->opt.num_options); s->local_opt.desc = malloc (s->opt.num_options * sizeof (s->local_opt.desc)); if (!s->local_opt.desc) { DBG (1, "fetch_options: couldn't malloc s->local_opt.desc\n"); return SANE_STATUS_NO_MEM; } for (option_number = 0; option_number < s->opt.num_options; option_number++) { s->local_opt.desc[option_number] = malloc (sizeof (SANE_Option_Descriptor)); if (!s->local_opt.desc[option_number]) { DBG (1, "fetch_options: couldn't malloc " "s->local_opt.desc[%d]\n", option_number); return SANE_STATUS_NO_MEM; } } s->local_opt.num_options = s->opt.num_options; } else if (s->local_opt.num_options != s->opt.num_options) { DBG (1, "fetch_options: option number count changed during runtime?\n"); return SANE_STATUS_INVAL; } DBG (3, "fetch_options: copying %d option descriptors\n", s->opt.num_options); for (option_number = 0; option_number < s->opt.num_options; option_number++) { memcpy (s->local_opt.desc[option_number], s->opt.desc[option_number], sizeof (SANE_Option_Descriptor)); } s->options_valid = 1; DBG (3, "fetch_options: %d options fetched\n", s->opt.num_options); return SANE_STATUS_GOOD; } static SANE_Status do_cancel (Net_Scanner * s) { DBG (2, "do_cancel: %p\n", (void *) s); s->hw->auth_active = 0; if (s->data >= 0) { DBG (3, "do_cancel: closing data pipe\n"); close (s->data); s->data = -1; } return SANE_STATUS_CANCELLED; } static void do_authorization (Net_Device * dev, SANE_String resource) { SANE_Authorization_Req req; SANE_Char username[SANE_MAX_USERNAME_LEN]; SANE_Char password[SANE_MAX_PASSWORD_LEN]; char *net_resource; DBG (2, "do_authorization: dev=%p resource=%s\n", (void *) dev, resource); dev->auth_active = 1; memset (&req, 0, sizeof (req)); memset (username, 0, sizeof (SANE_Char) * SANE_MAX_USERNAME_LEN); memset (password, 0, sizeof (SANE_Char) * SANE_MAX_PASSWORD_LEN); net_resource = malloc (strlen (resource) + 6 + strlen (dev->name)); if (net_resource != NULL) { sprintf (net_resource, "net:%s:%s", dev->name, resource); if (auth_callback) { DBG (2, "do_authorization: invoking auth_callback, resource = %s\n", net_resource); (*auth_callback) (net_resource, username, password); } else DBG (1, "do_authorization: no auth_callback present\n"); free (net_resource); } else /* Is this necessary? If we don't have these few bytes we will get in trouble later anyway */ { DBG (1, "do_authorization: not enough memory for net_resource\n"); if (auth_callback) { DBG (2, "do_authorization: invoking auth_callback, resource = %s\n", resource); (*auth_callback) (resource, username, password); } else DBG (1, "do_authorization: no auth_callback present\n"); } if (dev->auth_active) { SANE_Word ack; req.resource = resource; req.username = username; req.password = password; DBG (2, "do_authorization: relaying authentication data\n"); sanei_w_call (&dev->wire, SANE_NET_AUTHORIZE, (WireCodecFunc) sanei_w_authorization_req, &req, (WireCodecFunc) sanei_w_word, &ack); } else DBG (1, "do_authorization: auth_active is false... strange\n"); } #ifdef WITH_AVAHI static void net_avahi_resolve_callback (AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { char a[AVAHI_ADDRESS_STR_MAX]; char *t; /* unused */ interface = interface; protocol = protocol; userdata = userdata; if (!r) return; switch (event) { case AVAHI_RESOLVER_FAILURE: DBG (1, "net_avahi_resolve_callback: failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror (avahi_client_errno (avahi_service_resolver_get_client (r)))); break; case AVAHI_RESOLVER_FOUND: DBG (3, "net_avahi_resolve_callback: service '%s' of type '%s' in domain '%s':\n", name, type, domain); avahi_address_snprint(a, sizeof (a), address); t = avahi_string_list_to_string (txt); DBG (3, "\t%s:%u (%s)\n\tTXT=%s\n\tcookie is %u\n\tis_local: %i\n\tour_own: %i\n" "\twide_area: %i\n\tmulticast: %i\n\tcached: %i\n", host_name, port, a, t, avahi_string_list_get_service_cookie (txt), !!(flags & AVAHI_LOOKUP_RESULT_LOCAL), !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN), !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA), !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST), !!(flags & AVAHI_LOOKUP_RESULT_CACHED)); /* TODO: evaluate TXT record */ /* Try first with the name */ if (add_device (host_name, NULL) != SANE_STATUS_GOOD) { DBG (1, "net_avahi_resolve_callback: couldn't add backend with name %s\n", host_name); /* Then try the raw IP address */ if (add_device (t, NULL) != SANE_STATUS_GOOD) DBG (1, "net_avahi_resolve_callback: couldn't add backend with IP address %s either\n", t); } avahi_free (t); break; } avahi_service_resolver_free(r); } static void net_avahi_browse_callback (AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) { AvahiProtocol proto; /* unused */ flags = flags; userdata = userdata; if (!b) return; switch (event) { case AVAHI_BROWSER_FAILURE: DBG (1, "net_avahi_browse_callback: %s\n", avahi_strerror (avahi_client_errno (avahi_service_browser_get_client (b)))); avahi_threaded_poll_quit (avahi_thread); return; case AVAHI_BROWSER_NEW: DBG (3, "net_avahi_browse_callback: NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); /* The server will actually be added to our list in the resolver callback */ /* The resolver object will be freed in the resolver callback, or by * the server if it terminates before the callback is called. */ #ifdef ENABLE_IPV6 proto = AVAHI_PROTO_UNSPEC; #else proto = AVAHI_PROTO_INET; #endif /* ENABLE_IPV6 */ if (!(avahi_service_resolver_new (avahi_client, interface, protocol, name, type, domain, proto, 0, net_avahi_resolve_callback, NULL))) DBG (2, "net_avahi_browse_callback: failed to resolve service '%s': %s\n", name, avahi_strerror (avahi_client_errno (avahi_client))); break; case AVAHI_BROWSER_REMOVE: DBG (3, "net_avahi_browse_callback: REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain); /* With the current architecture, we cannot safely remove a server from the list */ break; case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: DBG (3, "net_avahi_browse_callback: %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; } } static void net_avahi_callback (AvahiClient *c, AvahiClientState state, void * userdata) { AvahiProtocol proto; int error; /* unused */ userdata = userdata; if (!c) return; switch (state) { case AVAHI_CLIENT_CONNECTING: break; case AVAHI_CLIENT_S_COLLISION: case AVAHI_CLIENT_S_REGISTERING: case AVAHI_CLIENT_S_RUNNING: if (avahi_browser) return; #ifdef ENABLE_IPV6 proto = AVAHI_PROTO_UNSPEC; #else proto = AVAHI_PROTO_INET; #endif /* ENABLE_IPV6 */ avahi_browser = avahi_service_browser_new (c, AVAHI_IF_UNSPEC, proto, SANED_SERVICE_DNS, NULL, 0, net_avahi_browse_callback, NULL); if (avahi_browser == NULL) { DBG (1, "net_avahi_callback: could not create service browser: %s\n", avahi_strerror (avahi_client_errno (c))); avahi_threaded_poll_quit (avahi_thread); } break; case AVAHI_CLIENT_FAILURE: error = avahi_client_errno (c); if (error == AVAHI_ERR_DISCONNECTED) { /* Server disappeared - try to reconnect */ if (avahi_browser) { avahi_service_browser_free (avahi_browser); avahi_browser = NULL; } avahi_client_free (avahi_client); avahi_client = NULL; avahi_client = avahi_client_new (avahi_threaded_poll_get (avahi_thread), AVAHI_CLIENT_NO_FAIL, net_avahi_callback, NULL, &error); if (avahi_client == NULL) { DBG (1, "net_avahi_init: could not create Avahi client: %s\n", avahi_strerror (error)); avahi_threaded_poll_quit (avahi_thread); } } else { /* Another error happened - game over */ DBG (1, "net_avahi_callback: server connection failure: %s\n", avahi_strerror (error)); avahi_threaded_poll_quit (avahi_thread); } break; } } static void net_avahi_init (void) { int error; avahi_thread = avahi_threaded_poll_new (); if (avahi_thread == NULL) { DBG (1, "net_avahi_init: could not create threaded poll object\n"); goto fail; } avahi_client = avahi_client_new (avahi_threaded_poll_get (avahi_thread), AVAHI_CLIENT_NO_FAIL, net_avahi_callback, NULL, &error); if (avahi_client == NULL) { DBG (1, "net_avahi_init: could not create Avahi client: %s\n", avahi_strerror (error)); goto fail; } if (avahi_threaded_poll_start (avahi_thread) < 0) { DBG (1, "net_avahi_init: Avahi thread failed to start\n"); goto fail; } /* All done */ return; fail: DBG (1, "net_avahi_init: Avahi init failed, support disabled\n"); if (avahi_client) { avahi_client_free (avahi_client); avahi_client = NULL; } if (avahi_thread) { avahi_threaded_poll_free (avahi_thread); avahi_thread = NULL; } } static void net_avahi_cleanup (void) { if (!avahi_thread) return; DBG (1, "net_avahi_cleanup: stopping thread\n"); avahi_threaded_poll_stop (avahi_thread); if (avahi_browser) avahi_service_browser_free (avahi_browser); if (avahi_client) avahi_client_free (avahi_client); avahi_threaded_poll_free (avahi_thread); DBG (1, "net_avahi_cleanup: done\n"); } #endif /* WITH_AVAHI */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char device_name[PATH_MAX]; const char *optval; const char *env; size_t len; FILE *fp; short ns = 0x1234; unsigned char *p = (unsigned char *)(&ns); #ifndef NET_USES_AF_INDEP struct servent *serv; #endif /* !NET_USES_AF_INDEP */ DBG_INIT (); DBG (2, "sane_init: authorize %s null, version_code %s null\n", (authorize) ? "!=" : "==", (version_code) ? "!=" : "=="); devlist = NULL; first_device = NULL; first_handle = NULL; #ifdef WITH_AVAHI net_avahi_init (); #endif /* WITH_AVAHI */ auth_callback = authorize; /* Return the version number of the sane-backends package to allow the frontend to print them. This is done only for net and dll, because these backends are usually called by the frontend. */ if (version_code) *version_code = SANE_VERSION_CODE (SANE_DLL_V_MAJOR, SANE_DLL_V_MINOR, SANE_DLL_V_BUILD); DBG (1, "sane_init: SANE net backend version %s from %s\n", NET_VERSION, PACKAGE_STRING); /* determine (client) machine byte order */ if (*p == 0x12) { client_big_endian = 1; DBG (3, "sane_init: Client has big endian byte order\n"); } else { client_big_endian = 0; DBG (3, "sane_init: Client has little endian byte order\n"); } #ifndef NET_USES_AF_INDEP DBG (2, "sane_init: determining sane service port\n"); serv = getservbyname ("sane-port", "tcp"); if (serv) { DBG (2, "sane_init: found port %d\n", ntohs (serv->s_port)); saned_port = serv->s_port; } else { saned_port = htons (6566); DBG (1, "sane_init: could not find `sane-port' service (%s); using default " "port %d\n", strerror (errno), ntohs (saned_port)); } #endif /* !NET_USES_AF_INDEP */ DBG (2, "sane_init: searching for config file\n"); fp = sanei_config_open (NET_CONFIG_FILE); if (fp) { while (sanei_config_read (device_name, sizeof (device_name), fp)) { if (device_name[0] == '#') /* ignore line comments */ continue; len = strlen (device_name); if (!len) continue; /* ignore empty lines */ /* * Check for net backend options. * Anything that isn't an option is a saned host. */ if (strstr(device_name, "connect_timeout") != NULL) { /* Look for the = sign; if it's not there, error out */ optval = strchr(device_name, '='); if (!optval) continue; optval = sanei_config_skip_whitespace (++optval); if ((optval != NULL) && (*optval != '\0')) { connect_timeout = atoi(optval); DBG (2, "sane_init: connect timeout set to %d seconds\n", connect_timeout); } continue; } #ifdef WITH_AVAHI avahi_threaded_poll_lock (avahi_thread); #endif /* WITH_AVAHI */ DBG (2, "sane_init: trying to add %s\n", device_name); add_device (device_name, 0); #ifdef WITH_AVAHI avahi_threaded_poll_unlock (avahi_thread); #endif /* WITH_AVAHI */ } fclose (fp); DBG (2, "sane_init: done reading config\n"); } else DBG (1, "sane_init: could not open config file (%s): %s\n", NET_CONFIG_FILE, strerror (errno)); DBG (2, "sane_init: evaluating environment variable SANE_NET_HOSTS\n"); env = getenv ("SANE_NET_HOSTS"); if (env) { char *copy, *next, *host; if ((copy = strdup (env)) != NULL) { next = copy; while ((host = strsep (&next, ":"))) { #ifdef ENABLE_IPV6 if (host[0] == '[') { /* skip '[' (host[0]) */ host++; /* get the rest of the IPv6 addr (we're screwed if ] is missing) * Is it worth checking for the matching ] ? Not for now. */ strsep (&next, "]"); /* add back the ":" that got removed by the strsep() */ host[strlen (host)] = ':'; /* host now holds the IPv6 address */ /* skip the ':' that could be after ] (avoids a call to strsep() */ if (next[0] == ':') next++; } /* * if the IPv6 is last in the list, the strsep() call in the while() * will return a string with the first char being '\0'. Skip it. */ if (host[0] == '\0') continue; #endif /* ENABLE_IPV6 */ #ifdef WITH_AVAHI avahi_threaded_poll_lock (avahi_thread); #endif /* WITH_AVAHI */ DBG (2, "sane_init: trying to add %s\n", host); add_device (host, 0); #ifdef WITH_AVAHI avahi_threaded_poll_unlock (avahi_thread); #endif /* WITH_AVAHI */ } free (copy); } else DBG (1, "sane_init: not enough memory to duplicate " "environment variable\n"); } DBG (2, "sane_init: evaluating environment variable SANE_NET_TIMEOUT\n"); env = getenv ("SANE_NET_TIMEOUT"); if (env) { connect_timeout = atoi(env); DBG (2, "sane_init: connect timeout set to %d seconds from env\n", connect_timeout); } DBG (2, "sane_init: done\n"); return SANE_STATUS_GOOD; } void sane_exit (void) { Net_Scanner *handle, *next_handle; Net_Device *dev, *next_device; int i; DBG (1, "sane_exit: exiting\n"); #ifdef WITH_AVAHI net_avahi_cleanup (); #endif /* WITH_AVAHI */ /* first, close all handles: */ for (handle = first_handle; handle; handle = next_handle) { next_handle = handle->next; sane_close (handle); } first_handle = 0; /* now close all devices: */ for (dev = first_device; dev; dev = next_device) { next_device = dev->next; DBG (2, "sane_exit: closing dev %p, ctl=%d\n", (void *) dev, dev->ctl); if (dev->ctl >= 0) { sanei_w_call (&dev->wire, SANE_NET_EXIT, (WireCodecFunc) sanei_w_void, 0, (WireCodecFunc) sanei_w_void, 0); sanei_w_exit (&dev->wire); close (dev->ctl); } if (dev->name) free ((void *) dev->name); #ifdef NET_USES_AF_INDEP if (dev->addr) freeaddrinfo(dev->addr); #endif /* NET_USES_AF_INDEP */ free (dev); } if (devlist) { for (i = 0; devlist[i]; ++i) { if (devlist[i]->vendor) free ((void *) devlist[i]->vendor); if (devlist[i]->model) free ((void *) devlist[i]->model); if (devlist[i]->type) free ((void *) devlist[i]->type); free ((void *) devlist[i]); } free (devlist); } DBG (3, "sane_exit: finished.\n"); } /* Note that a call to get_devices() implies that we'll have to connect to all remote hosts. To avoid this, you can call sane_open() directly (assuming you know the name of the backend/device). This is appropriate for the command-line interface of SANE, for example. */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { static int devlist_size = 0, devlist_len = 0; static const SANE_Device *empty_devlist[1] = { 0 }; SANE_Get_Devices_Reply reply; SANE_Status status; Net_Device *dev; char *full_name; int i, num_devs; size_t len; #define ASSERT_SPACE(n) \ { \ if (devlist_len + (n) > devlist_size) \ { \ devlist_size += (n) + 15; \ if (devlist) \ devlist = realloc (devlist, devlist_size * sizeof (devlist[0])); \ else \ devlist = malloc (devlist_size * sizeof (devlist[0])); \ if (!devlist) \ { \ DBG (1, "sane_get_devices: not enough memory\n"); \ return SANE_STATUS_NO_MEM; \ } \ } \ } DBG (3, "sane_get_devices: local_only = %d\n", local_only); if (local_only) { *device_list = empty_devlist; return SANE_STATUS_GOOD; } if (devlist) { DBG (2, "sane_get_devices: freeing devlist\n"); for (i = 0; devlist[i]; ++i) { if (devlist[i]->vendor) free ((void *) devlist[i]->vendor); if (devlist[i]->model) free ((void *) devlist[i]->model); if (devlist[i]->type) free ((void *) devlist[i]->type); free ((void *) devlist[i]); } free (devlist); devlist = 0; } devlist_len = 0; devlist_size = 0; for (dev = first_device; dev; dev = dev->next) { if (dev->ctl < 0) { status = connect_dev (dev); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_get_devices: ignoring failure to connect to %s\n", dev->name); continue; } } sanei_w_call (&dev->wire, SANE_NET_GET_DEVICES, (WireCodecFunc) sanei_w_void, 0, (WireCodecFunc) sanei_w_get_devices_reply, &reply); if (reply.status != SANE_STATUS_GOOD) { DBG (1, "sane_get_devices: ignoring rpc-returned status %s\n", sane_strstatus (reply.status)); sanei_w_free (&dev->wire, (WireCodecFunc) sanei_w_get_devices_reply, &reply); continue; } /* count the number of devices for this backend: */ for (num_devs = 0; reply.device_list[num_devs]; ++num_devs); ASSERT_SPACE (num_devs); for (i = 0; i < num_devs; ++i) { SANE_Device *rdev; char *mem; #ifdef ENABLE_IPV6 SANE_Bool IPv6 = SANE_FALSE; #endif /* ENABLE_IPV6 */ /* create a new device entry with a device name that is the sum of the backend name a colon and the backend's device name: */ len = strlen (dev->name) + 1 + strlen (reply.device_list[i]->name); #ifdef ENABLE_IPV6 if (strchr (dev->name, ':') != NULL) { len += 2; IPv6 = SANE_TRUE; } #endif /* ENABLE_IPV6 */ mem = malloc (sizeof (*dev) + len + 1); if (!mem) { DBG (1, "sane_get_devices: not enough free memory\n"); sanei_w_free (&dev->wire, (WireCodecFunc) sanei_w_get_devices_reply, &reply); return SANE_STATUS_NO_MEM; } memset (mem, 0, sizeof (*dev) + len); full_name = mem + sizeof (*dev); #ifdef ENABLE_IPV6 if (IPv6 == SANE_TRUE) strcat (full_name, "["); #endif /* ENABLE_IPV6 */ strcat (full_name, dev->name); #ifdef ENABLE_IPV6 if (IPv6 == SANE_TRUE) strcat (full_name, "]"); #endif /* ENABLE_IPV6 */ strcat (full_name, ":"); strcat (full_name, reply.device_list[i]->name); DBG (3, "sane_get_devices: got %s\n", full_name); rdev = (SANE_Device *) mem; rdev->name = full_name; rdev->vendor = strdup (reply.device_list[i]->vendor); rdev->model = strdup (reply.device_list[i]->model); rdev->type = strdup (reply.device_list[i]->type); if ((!rdev->vendor) || (!rdev->model) || (!rdev->type)) { DBG (1, "sane_get_devices: not enough free memory\n"); if (rdev->vendor) free ((void *) rdev->vendor); if (rdev->model) free ((void *) rdev->model); if (rdev->type) free ((void *) rdev->type); free (rdev); sanei_w_free (&dev->wire, (WireCodecFunc) sanei_w_get_devices_reply, &reply); return SANE_STATUS_NO_MEM; } devlist[devlist_len++] = rdev; } /* now free up the rpc return value: */ sanei_w_free (&dev->wire, (WireCodecFunc) sanei_w_get_devices_reply, &reply); } /* terminate device list with NULL entry: */ ASSERT_SPACE (1); devlist[devlist_len++] = 0; *device_list = devlist; DBG (2, "sane_get_devices: finished (%d devices)\n", devlist_len - 1); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle) { SANE_Open_Reply reply; const char *dev_name; #ifdef ENABLE_IPV6 const char *tmp_name; SANE_Bool v6addr = SANE_FALSE; #endif /* ENABLE_IPV6 */ SANE_String nd_name; SANE_Status status; SANE_Word handle; SANE_Word ack; Net_Device *dev; Net_Scanner *s; int need_auth; DBG (3, "sane_open(\"%s\")\n", full_name); #ifdef ENABLE_IPV6 /* * Check whether a numerical IPv6 host was specified * [2001:42:42::12] <== check for '[' as full_name[0] * ex: [2001:42:42::12]:test:0 (syntax taken from Apache 2) */ if (full_name[0] == '[') { v6addr = SANE_TRUE; tmp_name = strchr (full_name, ']'); if (!tmp_name) { DBG (1, "sane_open: incorrect host address: missing matching ']'\n"); return SANE_STATUS_INVAL; } } else tmp_name = full_name; dev_name = strchr (tmp_name, ':'); #else /* !ENABLE_IPV6 */ dev_name = strchr (full_name, ':'); #endif /* ENABLE_IPV6 */ if (dev_name) { #ifdef strndupa # ifdef ENABLE_IPV6 if (v6addr == SANE_TRUE) nd_name = strndupa (full_name + 1, dev_name - full_name - 2); else nd_name = strndupa (full_name, dev_name - full_name); # else /* !ENABLE_IPV6 */ nd_name = strndupa (full_name, dev_name - full_name); # endif /* ENABLE_IPV6 */ if (!nd_name) { DBG (1, "sane_open: not enough free memory\n"); return SANE_STATUS_NO_MEM; } #else char *tmp; # ifdef ENABLE_IPV6 if (v6addr == SANE_TRUE) tmp = alloca (dev_name - full_name - 2 + 1); else tmp = alloca (dev_name - full_name + 1); # else /* !ENABLE_IPV6 */ tmp = alloca (dev_name - full_name + 1); # endif /* ENABLE_IPV6 */ if (!tmp) { DBG (1, "sane_open: not enough free memory\n"); return SANE_STATUS_NO_MEM; } # ifdef ENABLE_IPV6 if (v6addr == SANE_TRUE) { memcpy (tmp, full_name + 1, dev_name - full_name - 2); tmp[dev_name - full_name - 2] = '\0'; } else { memcpy (tmp, full_name, dev_name - full_name); tmp[dev_name - full_name] = '\0'; } # else /* !ENABLE_IPV6 */ memcpy (tmp, full_name, dev_name - full_name); tmp[dev_name - full_name] = '\0'; # endif /* ENABLE_IPV6 */ nd_name = tmp; #endif ++dev_name; /* skip colon */ } else { /* if no colon interpret full_name as the host name; an empty device name will cause us to open the first device of that host. */ #ifdef ENABLE_IPV6 if (v6addr == SANE_TRUE) { nd_name = alloca (strlen (full_name) - 2 + 1); if (!nd_name) { DBG (1, "sane_open: not enough free memory\n"); return SANE_STATUS_NO_MEM; } memcpy (nd_name, full_name + 1, strlen (full_name) - 2); nd_name[strlen (full_name) - 2] = '\0'; } else nd_name = (char *) full_name; #else /* !ENABLE_IPV6 */ nd_name = (char *) full_name; #endif /* ENABLE_IPV6 */ dev_name = ""; } DBG (2, "sane_open: host = %s, device = %s\n", nd_name, dev_name); if (!nd_name[0]) { /* Unlike other backends, we never allow an empty backend-name. Otherwise, it's possible that sane_open("") will result in endless looping (consider the case where NET is the first backend...) */ DBG (1, "sane_open: empty backend name is not allowed\n"); return SANE_STATUS_INVAL; } else for (dev = first_device; dev; dev = dev->next) if (strcmp (dev->name, nd_name) == 0) break; if (!dev) { DBG (1, "sane_open: device %s not found, trying to register it anyway\n", nd_name); #ifdef WITH_AVAHI avahi_threaded_poll_lock (avahi_thread); #endif /* WITH_AVAHI */ status = add_device (nd_name, &dev); #ifdef WITH_AVAHI avahi_threaded_poll_unlock (avahi_thread); #endif /* WITH_AVAHI */ if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: could not open device\n"); return status; } } else DBG (2, "sane_open: device found in list\n"); if (dev->ctl < 0) { DBG (2, "sane_open: device not connected yet...\n"); status = connect_dev (dev); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: could not connect to device\n"); return status; } } DBG (3, "sane_open: net_open\n"); sanei_w_call (&dev->wire, SANE_NET_OPEN, (WireCodecFunc) sanei_w_string, &dev_name, (WireCodecFunc) sanei_w_open_reply, &reply); do { if (dev->wire.status != 0) { DBG (1, "sane_open: open rpc call failed (%s)\n", strerror (dev->wire.status)); return SANE_STATUS_IO_ERROR; } status = reply.status; handle = reply.handle; need_auth = (reply.resource_to_authorize != 0); if (need_auth) { DBG (3, "sane_open: authorization required\n"); do_authorization (dev, reply.resource_to_authorize); sanei_w_free (&dev->wire, (WireCodecFunc) sanei_w_open_reply, &reply); if (dev->wire.direction != WIRE_DECODE) sanei_w_set_dir (&dev->wire, WIRE_DECODE); sanei_w_open_reply (&dev->wire, &reply); continue; } else sanei_w_free (&dev->wire, (WireCodecFunc) sanei_w_open_reply, &reply); if (need_auth && !dev->auth_active) { DBG (2, "sane_open: open cancelled\n"); return SANE_STATUS_CANCELLED; } if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: remote open failed\n"); return reply.status; } } while (need_auth); s = malloc (sizeof (*s)); if (!s) { DBG (1, "sane_open: not enough free memory\n"); return SANE_STATUS_NO_MEM; } memset (s, 0, sizeof (*s)); s->hw = dev; s->handle = handle; s->data = -1; s->next = first_handle; s->local_opt.desc = 0; s->local_opt.num_options = 0; DBG (3, "sane_open: getting option descriptors\n"); status = fetch_options (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: fetch_options failed (%s), closing device again\n", sane_strstatus (status)); sanei_w_call (&s->hw->wire, SANE_NET_CLOSE, (WireCodecFunc) sanei_w_word, &s->handle, (WireCodecFunc) sanei_w_word, &ack); free (s); return status; } first_handle = s; *meta_handle = s; DBG (3, "sane_open: success\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Net_Scanner *prev, *s; SANE_Word ack; int option_number; DBG (3, "sane_close: handle %p\n", handle); prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (1, "sane_close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (prev) prev->next = s->next; else first_handle = s->next; if (s->opt.num_options) { DBG (2, "sane_close: removing cached option descriptors\n"); sanei_w_set_dir (&s->hw->wire, WIRE_FREE); s->hw->wire.status = 0; sanei_w_option_descriptor_array (&s->hw->wire, &s->opt); if (s->hw->wire.status) DBG (1, "sane_close: couldn't free sanei_w_option_descriptor_array " "(%s)\n", sane_strstatus (s->hw->wire.status)); } DBG (2, "sane_close: removing local option descriptors\n"); for (option_number = 0; option_number < s->local_opt.num_options; option_number++) free (s->local_opt.desc[option_number]); if (s->local_opt.desc) free (s->local_opt.desc); DBG (2, "sane_close: net_close\n"); sanei_w_call (&s->hw->wire, SANE_NET_CLOSE, (WireCodecFunc) sanei_w_word, &s->handle, (WireCodecFunc) sanei_w_word, &ack); if (s->data >= 0) { DBG (2, "sane_close: closing data pipe\n"); close (s->data); } free (s); DBG (2, "sane_close: done\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Net_Scanner *s = handle; SANE_Status status; DBG (3, "sane_get_option_descriptor: option %d\n", option); if (!s->options_valid) { DBG (3, "sane_get_option_descriptor: getting option descriptors\n"); status = fetch_options (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_get_option_descriptor: fetch_options failed (%s)\n", sane_strstatus (status)); return 0; } } if (((SANE_Word) option >= s->opt.num_options) || (option < 0)) { DBG (2, "sane_get_option_descriptor: invalid option number\n"); return 0; } return s->local_opt.desc[option]; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Word * info) { Net_Scanner *s = handle; SANE_Control_Option_Req req; SANE_Control_Option_Reply reply; SANE_Status status; size_t value_size; int need_auth; SANE_Word local_info; DBG (3, "sane_control_option: option %d, action %d\n", option, action); if (!s->options_valid) { DBG (1, "sane_control_option: FRONTEND BUG: option descriptors reload needed\n"); return SANE_STATUS_INVAL; } if (((SANE_Word) option >= s->opt.num_options) || (option < 0)) { DBG (1, "sane_control_option: invalid option number\n"); return SANE_STATUS_INVAL; } switch (s->opt.desc[option]->type) { case SANE_TYPE_BUTTON: case SANE_TYPE_GROUP: /* shouldn't happen... */ /* the SANE standard defines that the option size of a BUTTON or GROUP is IGNORED. */ value_size = 0; break; case SANE_TYPE_STRING: /* strings can be smaller than size */ value_size = s->opt.desc[option]->size; if ((action == SANE_ACTION_SET_VALUE) && (((SANE_Int) strlen ((SANE_String) value) + 1) < s->opt.desc[option]->size)) value_size = strlen ((SANE_String) value) + 1; break; default: value_size = s->opt.desc[option]->size; break; } /* Avoid leaking memory bits */ if (value && (action != SANE_ACTION_SET_VALUE)) memset (value, 0, value_size); /* for SET_AUTO the parameter ``value'' is ignored */ if (action == SANE_ACTION_SET_AUTO) value_size = 0; req.handle = s->handle; req.option = option; req.action = action; req.value_type = s->opt.desc[option]->type; req.value_size = value_size; req.value = value; local_info = 0; DBG (3, "sane_control_option: remote control option\n"); sanei_w_call (&s->hw->wire, SANE_NET_CONTROL_OPTION, (WireCodecFunc) sanei_w_control_option_req, &req, (WireCodecFunc) sanei_w_control_option_reply, &reply); do { status = reply.status; need_auth = (reply.resource_to_authorize != 0); if (need_auth) { DBG (3, "sane_control_option: auth required\n"); do_authorization (s->hw, reply.resource_to_authorize); sanei_w_free (&s->hw->wire, (WireCodecFunc) sanei_w_control_option_reply, &reply); sanei_w_set_dir (&s->hw->wire, WIRE_DECODE); sanei_w_control_option_reply (&s->hw->wire, &reply); continue; } else if (status == SANE_STATUS_GOOD) { local_info = reply.info; if (info) *info = reply.info; if (value_size > 0) { if ((SANE_Word) value_size == reply.value_size) memcpy (value, reply.value, reply.value_size); else DBG (1, "sane_control_option: size changed from %d to %d\n", s->opt.desc[option]->size, reply.value_size); } if (reply.info & SANE_INFO_RELOAD_OPTIONS) s->options_valid = 0; } sanei_w_free (&s->hw->wire, (WireCodecFunc) sanei_w_control_option_reply, &reply); if (need_auth && !s->hw->auth_active) return SANE_STATUS_CANCELLED; } while (need_auth); DBG (2, "sane_control_option: remote done (%s, info %x)\n", sane_strstatus (status), local_info); if ((status == SANE_STATUS_GOOD) && (info == NULL) && (local_info & SANE_INFO_RELOAD_OPTIONS)) { DBG (2, "sane_control_option: reloading options as frontend does not care\n"); status = fetch_options (s); DBG (2, "sane_control_option: reload done (%s)\n", sane_strstatus (status)); } DBG (2, "sane_control_option: done (%s, info %x)\n", sane_strstatus (status), local_info); return status; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Net_Scanner *s = handle; SANE_Get_Parameters_Reply reply; SANE_Status status; DBG (3, "sane_get_parameters\n"); if (!params) { DBG (1, "sane_get_parameters: parameter params not supplied\n"); return SANE_STATUS_INVAL; } DBG (3, "sane_get_parameters: remote get parameters\n"); sanei_w_call (&s->hw->wire, SANE_NET_GET_PARAMETERS, (WireCodecFunc) sanei_w_word, &s->handle, (WireCodecFunc) sanei_w_get_parameters_reply, &reply); status = reply.status; *params = reply.params; depth = reply.params.depth; sanei_w_free (&s->hw->wire, (WireCodecFunc) sanei_w_get_parameters_reply, &reply); DBG (3, "sane_get_parameters: returned status %s\n", sane_strstatus (status)); return status; } #ifdef NET_USES_AF_INDEP SANE_Status sane_start (SANE_Handle handle) { Net_Scanner *s = handle; SANE_Start_Reply reply; struct sockaddr_in sin; struct sockaddr *sa; #ifdef ENABLE_IPV6 struct sockaddr_in6 sin6; #endif /* ENABLE_IPV6 */ SANE_Status status; int fd, need_auth; socklen_t len; uint16_t port; /* Internet-specific */ DBG (3, "sane_start\n"); hang_over = -1; left_over = -1; if (s->data >= 0) { DBG (2, "sane_start: data pipe already exists\n"); return SANE_STATUS_INVAL; } /* Do this ahead of time so in case anything fails, we can recover gracefully (without hanging our server). */ switch (s->hw->addr_used->ai_family) { case AF_INET: len = sizeof (sin); sa = (struct sockaddr *) &sin; break; #ifdef ENABLE_IPV6 case AF_INET6: len = sizeof (sin6); sa = (struct sockaddr *) &sin6; break; #endif /* ENABLE_IPV6 */ default: DBG (1, "sane_start: unknown address family : %d\n", s->hw->addr_used->ai_family); return SANE_STATUS_INVAL; } if (getpeername (s->hw->ctl, sa, &len) < 0) { DBG (1, "sane_start: getpeername() failed (%s)\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } fd = socket (s->hw->addr_used->ai_family, SOCK_STREAM, 0); if (fd < 0) { DBG (1, "sane_start: socket() failed (%s)\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } DBG (3, "sane_start: remote start\n"); sanei_w_call (&s->hw->wire, SANE_NET_START, (WireCodecFunc) sanei_w_word, &s->handle, (WireCodecFunc) sanei_w_start_reply, &reply); do { status = reply.status; port = reply.port; if (reply.byte_order == 0x1234) { server_big_endian = 0; DBG (1, "sane_start: server has little endian byte order\n"); } else { server_big_endian = 1; DBG (1, "sane_start: server has big endian byte order\n"); } need_auth = (reply.resource_to_authorize != 0); if (need_auth) { DBG (3, "sane_start: auth required\n"); do_authorization (s->hw, reply.resource_to_authorize); sanei_w_free (&s->hw->wire, (WireCodecFunc) sanei_w_start_reply, &reply); sanei_w_set_dir (&s->hw->wire, WIRE_DECODE); sanei_w_start_reply (&s->hw->wire, &reply); continue; } sanei_w_free (&s->hw->wire, (WireCodecFunc) sanei_w_start_reply, &reply); if (need_auth && !s->hw->auth_active) return SANE_STATUS_CANCELLED; if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: remote start failed (%s)\n", sane_strstatus (status)); close (fd); return status; } } while (need_auth); DBG (3, "sane_start: remote start finished, data at port %hu\n", port); switch (s->hw->addr_used->ai_family) { case AF_INET: sin.sin_port = htons (port); break; #ifdef ENABLE_IPV6 case AF_INET6: sin6.sin6_port = htons (port); break; #endif /* ENABLE_IPV6 */ } if (connect (fd, sa, len) < 0) { DBG (1, "sane_start: connect() failed (%s)\n", strerror (errno)); close (fd); return SANE_STATUS_IO_ERROR; } shutdown (fd, 1); s->data = fd; s->reclen_buf_offset = 0; s->bytes_remaining = 0; DBG (3, "sane_start: done (%s)\n", sane_strstatus (status)); return status; } #else /* !NET_USES_AF_INDEP */ SANE_Status sane_start (SANE_Handle handle) { Net_Scanner *s = handle; SANE_Start_Reply reply; struct sockaddr_in sin; SANE_Status status; int fd, need_auth; socklen_t len; uint16_t port; /* Internet-specific */ DBG (3, "sane_start\n"); hang_over = -1; left_over = -1; if (s->data >= 0) { DBG (2, "sane_start: data pipe already exists\n"); return SANE_STATUS_INVAL; } /* Do this ahead of time so in case anything fails, we can recover gracefully (without hanging our server). */ len = sizeof (sin); if (getpeername (s->hw->ctl, (struct sockaddr *) &sin, &len) < 0) { DBG (1, "sane_start: getpeername() failed (%s)\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } fd = socket (s->hw->addr.sa_family, SOCK_STREAM, 0); if (fd < 0) { DBG (1, "sane_start: socket() failed (%s)\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } DBG (3, "sane_start: remote start\n"); sanei_w_call (&s->hw->wire, SANE_NET_START, (WireCodecFunc) sanei_w_word, &s->handle, (WireCodecFunc) sanei_w_start_reply, &reply); do { status = reply.status; port = reply.port; if (reply.byte_order == 0x1234) { server_big_endian = 0; DBG (1, "sane_start: server has little endian byte order\n"); } else { server_big_endian = 1; DBG (1, "sane_start: server has big endian byte order\n"); } need_auth = (reply.resource_to_authorize != 0); if (need_auth) { DBG (3, "sane_start: auth required\n"); do_authorization (s->hw, reply.resource_to_authorize); sanei_w_free (&s->hw->wire, (WireCodecFunc) sanei_w_start_reply, &reply); sanei_w_set_dir (&s->hw->wire, WIRE_DECODE); sanei_w_start_reply (&s->hw->wire, &reply); continue; } sanei_w_free (&s->hw->wire, (WireCodecFunc) sanei_w_start_reply, &reply); if (need_auth && !s->hw->auth_active) return SANE_STATUS_CANCELLED; if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: remote start failed (%s)\n", sane_strstatus (status)); close (fd); return status; } } while (need_auth); DBG (3, "sane_start: remote start finished, data at port %hu\n", port); sin.sin_port = htons (port); if (connect (fd, (struct sockaddr *) &sin, len) < 0) { DBG (1, "sane_start: connect() failed (%s)\n", strerror (errno)); close (fd); return SANE_STATUS_IO_ERROR; } shutdown (fd, 1); s->data = fd; s->reclen_buf_offset = 0; s->bytes_remaining = 0; DBG (3, "sane_start: done (%s)\n", sane_strstatus (status)); return status; } #endif /* NET_USES_AF_INDEP */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { Net_Scanner *s = handle; ssize_t nread; SANE_Int cnt; SANE_Int start_cnt; SANE_Int end_cnt; SANE_Byte swap_buf; SANE_Byte temp_hang_over; int is_even; DBG (3, "sane_read: handle=%p, data=%p, max_length=%d, length=%p\n", handle, data, max_length, (void *) length); if (!length) { DBG (1, "sane_read: length == NULL\n"); return SANE_STATUS_INVAL; } is_even = 1; *length = 0; /* If there's a left over, i.e. a byte already in the correct byte order, return it immediately; otherwise read may fail with a SANE_STATUS_EOF and the caller never can read the last byte */ if ((depth == 16) && (server_big_endian != client_big_endian)) { if (left_over > -1) { DBG (3, "sane_read: left_over from previous call, return " "immediately\n"); /* return the byte, we've currently scanned; hang_over becomes left_over */ *data = (SANE_Byte) left_over; left_over = -1; *length = 1; return SANE_STATUS_GOOD; } } if (s->data < 0) { DBG (1, "sane_read: data pipe doesn't exist, scan cancelled?\n"); return SANE_STATUS_CANCELLED; } if (s->bytes_remaining == 0) { /* boy, is this painful or what? */ DBG (4, "sane_read: reading packet length\n"); nread = read (s->data, s->reclen_buf + s->reclen_buf_offset, 4 - s->reclen_buf_offset); if (nread < 0) { DBG (3, "sane_read: read failed (%s)\n", strerror (errno)); if (errno == EAGAIN) { DBG (3, "sane_read: try again later\n"); return SANE_STATUS_GOOD; } else { DBG (1, "sane_read: cancelling read\n"); do_cancel (s); return SANE_STATUS_IO_ERROR; } } DBG (4, "sane_read: read %lu bytes, %d from 4 total\n", (u_long) nread, s->reclen_buf_offset); s->reclen_buf_offset += nread; if (s->reclen_buf_offset < 4) { DBG (4, "sane_read: enough for now\n"); return SANE_STATUS_GOOD; } s->reclen_buf_offset = 0; s->bytes_remaining = (((u_long) s->reclen_buf[0] << 24) | ((u_long) s->reclen_buf[1] << 16) | ((u_long) s->reclen_buf[2] << 8) | ((u_long) s->reclen_buf[3] << 0)); DBG (3, "sane_read: next record length=%ld bytes\n", (long) s->bytes_remaining); if (s->bytes_remaining == 0xffffffff) { char ch; DBG (2, "sane_read: received error signal\n"); /* turn off non-blocking I/O (s->data will be closed anyhow): */ fcntl (s->data, F_SETFL, 0); /* read the status byte: */ if (read (s->data, &ch, sizeof (ch)) != 1) { DBG (1, "sane_read: failed to read error code\n"); ch = SANE_STATUS_IO_ERROR; } DBG (1, "sane_read: error code %s\n", sane_strstatus ((SANE_Status) ch)); do_cancel (s); return (SANE_Status) ch; } } if (max_length > (SANE_Int) s->bytes_remaining) max_length = s->bytes_remaining; nread = read (s->data, data, max_length); if (nread < 0) { DBG (2, "sane_read: error code %s\n", strerror (errno)); if (errno == EAGAIN) return SANE_STATUS_GOOD; else { DBG (1, "sane_read: cancelling scan\n"); do_cancel (s); return SANE_STATUS_IO_ERROR; } } s->bytes_remaining -= nread; *length = nread; /* Check whether we are scanning with a depth of 16 bits/pixel and whether server and client have different byte order. If this is true, then it's neccessary to check whether read returned an odd number. If an odd number has been returned, we must save the last byte. */ if ((depth == 16) && (server_big_endian != client_big_endian)) { DBG (1,"sane_read: client/server have different byte order; " "must swap\n"); /* special case: 1 byte scanned and hang_over */ if ((nread == 1) && (hang_over > -1)) { /* return the byte, we've currently scanned; hang_over becomes left_over */ left_over = hang_over; hang_over = -1; return SANE_STATUS_GOOD; } /* check whether an even or an odd number of bytes has been scanned */ if ((nread % 2) == 0) is_even = 1; else is_even = 0; /* check, whether there's a hang over from a previous call; in this case we memcopy the data up one byte */ if ((nread > 1) && (hang_over > -1)) { /* store last byte */ temp_hang_over = *(data + nread - 1); memmove (data + 1, data, nread - 1); *data = (SANE_Byte) hang_over; /* what happens with the last byte depends on whether the number of bytes is even or odd */ if (is_even == 1) { /* number of bytes is even; no new hang_over, exchange last byte with hang over; last byte becomes left_over */ left_over = *(data + nread - 1); *(data + nread - 1) = temp_hang_over; hang_over = -1; start_cnt = 0; /* last byte already swapped */ end_cnt = nread - 2; } else { /* number of bytes is odd; last byte becomes new hang_over */ hang_over = temp_hang_over; left_over = -1; start_cnt = 0; end_cnt = nread - 1; } } else if (nread == 1) { /* if only one byte has been read, save it as hang_over and return length=0 */ hang_over = (int) *data; *length = 0; return SANE_STATUS_GOOD; } else { /* no hang_over; test for even or odd byte number */ if(is_even == 1) { start_cnt = 0; end_cnt = *length; } else { start_cnt = 0; hang_over = *(data + *length - 1); *length -= 1; end_cnt = *length; } } /* swap the bytes */ for (cnt = start_cnt; cnt < end_cnt - 1; cnt += 2) { swap_buf = *(data + cnt); *(data + cnt) = *(data + cnt + 1); *(data + cnt + 1) = swap_buf; } } DBG (3, "sane_read: %lu bytes read, %lu remaining\n", (u_long) nread, (u_long) s->bytes_remaining); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Net_Scanner *s = handle; SANE_Word ack; DBG (3, "sane_cancel: sending net_cancel\n"); sanei_w_call (&s->hw->wire, SANE_NET_CANCEL, (WireCodecFunc) sanei_w_word, &s->handle, (WireCodecFunc) sanei_w_word, &ack); do_cancel (s); DBG (4, "sane_cancel: done\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Net_Scanner *s = handle; DBG (3, "sane_set_io_mode: non_blocking = %d\n", non_blocking); if (s->data < 0) { DBG (1, "sane_set_io_mode: pipe doesn't exist\n"); return SANE_STATUS_INVAL; } if (fcntl (s->data, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { DBG (1, "sane_set_io_mode: fcntl failed (%s)\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Net_Scanner *s = handle; DBG (3, "sane_get_select_fd\n"); if (s->data < 0) { DBG (1, "sane_get_select_fd: pipe doesn't exist\n"); return SANE_STATUS_INVAL; } *fd = s->data; DBG (3, "sane_get_select_fd: done; *fd = %d\n", *fd); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/mustek_pp_cis.h0000664000175000017500000002307712112021330015621 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2003 Eddy De Greef This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek PP flatbed _CIS_ scanners. */ #ifndef mustek_pp_cis_h #define mustek_pp_cis_h #include "../include/sane/sane.h" /****************************************************************************** * Read register symbols. *****************************************************************************/ typedef enum { MA1015R_ASIC = 0x00, MA1015R_SCAN_VAL = 0x01, MA1015R_MOTOR = 0x02, MA1015R_BANK_COUNT = 0x03 } Mustek_PP_1015R_reg; /****************************************************************************** * Read register bitmask symbols. *****************************************************************************/ typedef enum { MA1015B_MOTOR_HOME = 0x01, MA1015B_MOTOR_STABLE = 0x03 } Mustek_PP_1015R_bit; /****************************************************************************** * Write register symbols: (bank number << 4) + register number. *****************************************************************************/ typedef enum { MA1015W_RED_REF = 0x00, MA1015W_GREEN_REF = 0x01, MA1015W_BLUE_REF = 0x02, MA1015W_DPI_CONTROL = 0x03, MA1015W_BYTE_COUNT_HB = 0x10, MA1015W_BYTE_COUNT_LB = 0x11, MA1015W_SKIP_COUNT = 0x12, MA1015W_EXPOSE_TIME = 0x13, MA1015W_SRAM_SOURCE_PC = 0x20, MA1015W_MOTOR_CONTROL = 0x21, MA1015W_UNKNOWN_42 = 0x22, MA1015W_UNKNOWN_82 = 0x23, MA1015W_POWER_ON_DELAY = 0x30, MA1015W_CCD_TIMING = 0x31, MA1015W_CCD_TIMING_ADJ = 0x32, MA1015W_RIGHT_BOUND = 0x33 } Mustek_PP_1015W_reg; /****************************************************************************** * Mustek MA1015 register tracing structure. * Can be used to trace the status of the registers of the MA1015 chipset * during debugging. Most fields are not used in production code. *****************************************************************************/ typedef struct Mustek_PP_1015_Registers { SANE_Byte in_regs[4]; SANE_Byte out_regs[4][4]; SANE_Byte channel; Mustek_PP_1015R_reg current_read_reg; SANE_Int read_count; Mustek_PP_1015W_reg current_write_reg; /* always used */ SANE_Int write_count; } Mustek_PP_1015_Registers; /****************************************************************************** * CIS information *****************************************************************************/ typedef struct Mustek_PP_CIS_Info { /* Expose time (= time the lamp is on ?) */ SANE_Byte exposeTime; /* Power-on delay (= time between lamp on and start of capturing ?) */ SANE_Byte powerOnDelay[3]; /* Motor step control */ SANE_Byte phaseType; /* Use 8K bank or 4K bank */ SANE_Bool use8KBank; /* High resolution (600 DPI) or not (300 DPI) */ SANE_Bool highRes; /* delay between pixels; reading too fast causes stability problems */ SANE_Int delay; /* Register representation */ Mustek_PP_1015_Registers regs; /* Current color channel */ SANE_Int channel; /* Blocks motor movements during calibration */ SANE_Bool dontMove; /* Prevents read increment the before the first read */ SANE_Bool dontIncRead; /* Controls whether or not calibration parameters are transmitted during CIS configuration */ SANE_Bool setParameters; /* Number of lines to skip to reach the origin (used during calibration) */ SANE_Int skipsToOrigin; /* Physical resolution of the CIS: either 300 or 600 DPI */ SANE_Int cisRes; /* CCD mode (color/grayscale/lineart) */ SANE_Int mode; /* how many positions to skip until scan area starts @ max res */ SANE_Int skipimagebytes; /* how many image bytes to scan @ max res */ SANE_Int imagebytes; /* total skip, adjusted to resolution */ SANE_Int adjustskip; /* current resolution */ SANE_Int res; /* current horizontal hardware resolution */ SANE_Int hw_hres; /* current vertical hardware resolution */ SANE_Int hw_vres; /* how many positions to scan for one pixel */ SANE_Int hres_step; /* how many lines to scan for one scanline */ SANE_Int line_step; /* inversion */ SANE_Bool invert; } Mustek_PP_CIS_Info; struct Mustek_pp_Handle; typedef struct Mustek_PP_CIS_dev { /* device descriptor */ struct Mustek_pp_Handle *desc; /* model identification (600CP/1200CP/1200CP+) */ SANE_Int model; /* CIS status */ Mustek_PP_CIS_Info CIS; /* used during calibration & return_home */ Mustek_PP_CIS_Info Saved_CIS; /* bank count */ int bank_count; /* those are used to count the hardware line the scanner is at, the line the current bank is at and the lines we've scanned */ int line; int line_diff; int ccd_line; int lines_left; /* Configuration parameters that the user can calibrate */ /* Starting position at the top */ SANE_Int top_skip; /* Use fast skipping method for head movements ? (default: yes) */ SANE_Bool fast_skip; /* Discrimination value to choose between black and white */ SANE_Byte bw_limit; /* Run in calibration mode ? (default: no) */ SANE_Bool calib_mode; /* Extra delay between engine commands (ms). Default: zero. */ SANE_Int engine_delay; /* temporary buffer for 1 line (of one color) */ SANE_Byte *tmpbuf; /* calibration buffers (low cut, high cut) */ SANE_Byte *calib_low[3]; SANE_Byte *calib_hi[3]; /* Number of pixels in calibration buffers (<= number of pixels to scan) */ int calib_pixels; } Mustek_PP_CIS_dev; #define CIS_AVERAGE_NONE(dev) Mustek_PP_1015_send_command(dev, 0x05) #define CIS_AVERAGE_TWOPIXEL(dev) Mustek_PP_1015_send_command(dev, 0x15) #define CIS_AVERAGE_THREEPIXEL(dev) Mustek_PP_1015_send_command(dev, 0x35) #define CIS_WIDTH_4K(dev) Mustek_PP_1015_send_command(dev, 0x05) #define CIS_WIDTH_8K(dev) Mustek_PP_1015_send_command(dev, 0x45) #define CIS_STOP_TOGGLE(dev) Mustek_PP_1015_send_command(dev, 0x85) #define CIS_PIP_AS_INPUT(dev) Mustek_PP_1015_send_command(dev, 0x46) #define CIS_PIP_AS_OUTPUT_0(dev) Mustek_PP_1015_send_command(dev, 0x06) #define CIS_PIP_AS_OUTPUT_1(dev) Mustek_PP_1015_send_command(dev, 0x16) #define CIS_POP_AS_INPUT(dev) Mustek_PP_1015_send_command(dev, 0x86) #define CIS_POP_AS_OUTPUT_0(dev) Mustek_PP_1015_send_command(dev, 0x06) #define CIS_POP_AS_OUTPUT_1(dev) Mustek_PP_1015_send_command(dev, 0x26) #define CIS_INC_READ(dev) Mustek_PP_1015_send_command(dev, 0x07) #define CIS_CLEAR_WRITE_BANK(dev) Mustek_PP_1015_send_command(dev, 0x17) #define CIS_CLEAR_READ_BANK(dev) Mustek_PP_1015_send_command(dev, 0x27) #define CIS_CLEAR_FULLFLAG(dev) Mustek_PP_1015_send_command(dev, 0x37) #define CIS_POWER_ON(dev) Mustek_PP_1015_send_command(dev, 0x47) #define CIS_POWER_OFF(dev) Mustek_PP_1015_send_command(dev, 0x57) #define CIS_CLEAR_WRITE_ADDR(dev) Mustek_PP_1015_send_command(dev, 0x67) #define CIS_CLEAR_TOGGLE(dev) Mustek_PP_1015_send_command(dev, 0x77) #define CIS_NO(dev) Mustek_PP_1015_send_command(dev, 0x08) #define CIS_OST_POS(dev) Mustek_PP_1015_send_command(dev, 0x18) #define CIS_OST_TYP(dev) Mustek_PP_1015_send_command(dev, 0x28) #define CIS_OP_MOD_0(dev) Mustek_PP_1015_send_command(dev, 0x48) #define CIS_OP_MOD_1(dev) Mustek_PP_1015_send_command(dev, 0x88) #endif /* __mustek_pp_cis_h */ sane-backends-1.0.27/backend/mustek_scsi_pp.h0000664000175000017500000001027712112021330016002 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 James Perry This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements the SCSI-over-parallel port protocol used in, for example, the Paragon 600 II EP */ #ifndef mustek_scsi_pp_h #define mustek_scsi_pp_h static int mustek_scsi_pp_get_time (void); /** * Open the connection to a Mustek SCSI-over-pp device. * * @param dev Port address as text. * @param fd Information about port address and I/O method. fd is not a file * descriptor. The name and type are used for compatibility reasons. * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_INVAL - if the port address can't be interpreted * - SANE_STATUS_IO_ERROR - if the device file for a port couldn't be accessed */ static SANE_Status mustek_scsi_pp_open (const char *dev, int *fd); /** * Close the connection to a Mustek SCSI-over-PP device. * * @param fd Information about port address and I/O method. * */ static void mustek_scsi_pp_close (int fd); /** * Exit Mustek SCSI-over-PP. */ static void mustek_scsi_pp_exit (void); /** * Find out if the device is ready to accept new commands. * * @param fd Information about port address and I/O method. * * @return * - SANE_STATUS_GOOD - if the device is ready * - SANE_STATUS_DEVICE_BUSY if the device is still busy (try again later) */ static SANE_Status mustek_scsi_pp_test_ready (int fd); /** * Send a command to the Mustek SCSI-over-pp device. * * @param fd Information about port address and I/O method. * @param src Data to be sent to the device. * @param src_size Size of data to be sent to the device. * @param dst Data to be received from the device. * @param dst_size Size of data to be received from the device * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - if an error occured during the dialog with the * device */ static SANE_Status mustek_scsi_pp_cmd (int fd, const void *src, size_t src_size, void *dst, size_t * dst_size); /** * Read scanned image data. * * @param fd Information about port address and I/O method. * @param planes Bytes per pixel (3 for color, 1 for all other modes) * @param buf Buffer for image data. * @param lines Number of lines * @param bpl Bytes per line * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_IO_ERROR - if an error occured during the dialog with the * device */ static SANE_Status mustek_scsi_pp_rdata (int fd, int planes, SANE_Byte * buf, int lines, int bpl); #endif /* mustek_scsi_pp_h */ sane-backends-1.0.27/backend/coolscan.h0000664000175000017500000002403512112021330014550 00000000000000/* --------------------------------------------------------------------- */ /* coolscan.h - headerfile for SANE-backend for coolscan scanners This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* --------------------------------------------------------------------- */ #ifndef coolscan_h #define coolscan_h #include "sys/types.h" enum Coolscan_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_SOURCE, OPT_RESOLUTION, OPT_PREVIEW_RESOLUTION, OPT_TYPE, OPT_BIT_DEPTH, OPT_PRESCAN, OPT_PRESCAN_NOW, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_GAMMA_BIND, OPT_ANALOG_GAMMA, OPT_AVERAGING, OPT_RGB_CONTROL, OPT_BRIGHTNESS, OPT_R_BRIGHTNESS, OPT_G_BRIGHTNESS, OPT_B_BRIGHTNESS, OPT_CONTRAST, OPT_R_CONTRAST, OPT_G_CONTRAST, OPT_B_CONTRAST, OPT_EXPOSURE, OPT_R_EXPOSURE, OPT_G_EXPOSURE, OPT_B_EXPOSURE, OPT_R_SHIFT, OPT_G_SHIFT, OPT_B_SHIFT, OPT_ADVANCED_GROUP, OPT_PREVIEW, /* preview */ OPT_AUTOFOCUS, /* autofocus */ OPT_IRED_RED, OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, /* must come last: */ NUM_OPTIONS }; typedef struct Image_Pos { int start; /* start position of image on film strip */ int end; /* end position of image on film strip */ int offset /* always 0 */; int height; /* image height always 2591 */ } Image_Pos_t; typedef struct Coolscan { struct Coolscan *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; SANE_Pid reader_pid; int reader_fds; int pipe; int scanning; /*--------------------------*/ SANE_Device sane; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; /*--------------------------*/ /* buffer used for scsi-transfer and writing*/ unsigned char *buffer; unsigned char *obuffer; unsigned int row_bufsize; char *devicename; /* name of the scanner device */ int sfd; /* output file descriptor, scanner device */ char vendor[9]; /* will be Nikon */ char product[17]; /* e.g. "LS-1000 " or so */ char version[5]; /* e.g. V1.6 */ int LS; /* index in scanner_str */ int cont; /* continue although scanner is unknown */ int verbose; /* 1,2=output informations */ int asf; /* Automatic Slide Feeder enabled? */ int MUD; /* Measurement Unit Divisor (1200 or 2700) */ int inquiry_len; /* length of inquiry return block [36] */ int inquiry_wdb_len; /* length of window descriptor block [117] */ int wdb_len; /* use this length of WDB */ double width; /* use this width of scan-area */ double length; /* use this length of scan-area */ int x_nres; int y_nres; int x_p_nres; /* same as above, but apply to preview */ int y_p_nres; int tlx; /* Left edge in 'Internal Length Units'. */ int tly; /* Top edge in ILU */ int brx; /* Right edge in ILU. */ int bry; /* Bottom edge in ILU. */ int bits_per_color; /* bits per color (8/10/12) */ int bits_per_pixel; /* bits per pixel (24/30/40) */ int negative; /* Negative/positive object */ int dropoutcolor; /* Which color to scan when gray */ int transfermode; /**/ int gammaselection; /* Linear/Monitor*/ int shading; int averaging; int brightness_R; int brightness_G; int brightness_B; int contrast_R; int contrast_G; int contrast_B; int exposure_R; int exposure_G; int exposure_B; int shift_R; int shift_G; int shift_B; int set_auto; /* 0 or 1, don't know what it is */ int preview; /* 1 if preview */ int autofocus; /* when to do autofocus */ #define AF_NEVER 0x00 #define AF_PREVIEW 0x01 #define AF_SCAN 0x02 #define AF_PREANDSCAN 0x03 int colormode; /* GREYSCALE or RGB */ int colormode_p; /* GREYSCALE or RGB for preview */ #define GREYSCALE 0x01 #define RGB 0x07 #define IRED 0x08 #define RGBI 0x0f int low_byte_first; /* 1 if little-endian - 0 if big-endian */ /* Internal information */ int adbits; /* Number of A/D bits [8 or 12] */ int outputbits; /* Number of output image data bits [8] */ int maxres; /* Maximum resolution [2700] (dpi) */ int xmax; /* X-axis coordinate maximum value (basic measurement unit when measurement unit divisor = 1200) [1151] */ int ymax; /* Y-axis coordinate maximum value (basic measurement unit when measurement unit divisor = 1200) [1727] */ int xmaxpix; /* X-axis coordinate maximum value (pixel address value) [2591] */ int ymaxpix; /* Y-axis coordinate maximum value (pixel address value) [3887] */ int ycurrent; /* Current stage position (Y-axis direction pixel address) [0-7652] */ int currentfocus; /* Current focus position (focus direction address) [0-200] */ int currentscanpitch; /* Current scan pitch [1-25] */ int autofeeder; /* Provision of auto feeder [Yes: 1, No: 0] */ int analoggamma; /* Analog gamma support [Yes: 1, No: 0] */ int derr[8]; /* Device error code (0 is latest, 7 oldest) */ int wbetr_r; /* White balance exposure time variable (R) */ int webtr_g; /* White balance exposure time variable (G) */ int webtr_b; /* White balance exposure time variable (B) */ int pretv_r; /* Prescan result exposure time variable (R) */ int pretv_g; /* Prescan result exposure time variable (G) */ int pretv_b; /* Prescan result exposure time variable (B) */ int cetv_r; /* Current exposure time variable (R) */ int cetv_g; /* Current exposure time variable (G) */ int cetv_b; /* Current exposure time variable (B) */ int ietu_r; /* Internal exposure time unit (R) */ int ietu_g; /* Internal exposure time unit (G) */ int ietu_b; /* Internal exposure time unit (B) */ int limitcondition; /* Condition of each limit SW, DIP SW, etc. */ int offsetdata_r; /* Offset data (R) */ int offsetdata_g; /* Offset data (G) */ int offsetdata_b; /* Offset data (B) */ char power_on_errors[8]; /* Records of error code at power on */ /* End of internal information */ int brightness; /* (128) cbhs_range 0-255, halftone mode */ int contrast; /* (128) cbhs_range 0-255, halftone-mode */ int prescan; /* */ int rgb_control; /* */ int gamma_bind; /* TRUE -> RGB */ int lutlength; /* length of gamma table */ int max_lut_val; /* maximum value in lut */ SANE_Word gamma[4096]; /* gamma value for RGB */ SANE_Word gamma_r[4096]; /* gamma value for red */ SANE_Word gamma_g[4096]; /* gamma value for green */ SANE_Word gamma_b[4096]; /* gamma value for blue */ int luti[4096]; /* lut value for infrared */ int lutr[4096]; /* lut value for red */ int lutg[4096]; /* lut value for green */ int lutb[4096]; /* lut value for blue */ char *gamma_file_r; /* file for gamma download */ char *gamma_file_g; /* file for gamma download */ char *gamma_file_b; /* file for gamma download */ int analog_gamma_r; /* analog gamma red and grey */ int analog_gamma_g; /* analog gamma green */ int analog_gamma_b; /* analog gamma blue */ /* Infrared correction values */ int ired_red; int ired_green; int ired_blue; int feeder; /* type of feeder used */ int numima; /* number of images on film strip */ int posima; /* current image */ Image_Pos_t ipos[6]; /* positions for 6 images */ #define STRIP_FEEDER 1 #define MOUNT_FEEDER 2 } Coolscan_t; typedef struct { char *scanner; char *inquiry; int inquiry_len; } inquiry_blk; /* ==================================================================== */ /* names of scanners that are supported because */ /* the inquiry_return_block is ok and driver is tested */ static char *scanner_str[] = { "COOLSCAN II ", "LS-1000 ", "COOLSCANIII ", "LS-2000 ", }; #define known_scanners 4 /* Comment this line if you havn't patched sane.h to include SANE_FRAME_RGBA */ /* #define HAS_IRED 1 */ #endif /* coolscan-sane_h */ sane-backends-1.0.27/backend/rts8891_low.h0000664000175000017500000002301612775277260015026 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007-2012 stef.dev@free.fr This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef RTS8891_LOW_H #define RTS8891_LOW_H #include #include "../include/sane/sane.h" #define DBG_error0 0 /* errors/warnings printed even with devuglevel 0 */ #define DBG_error 1 /* fatal errors */ #define DBG_init 2 /* initialization and scanning time messages */ #define DBG_warn 3 /* warnings and non-fatal errors */ #define DBG_info 4 /* informational messages */ #define DBG_proc 5 /* starting/finishing functions */ #define DBG_io 6 /* io functions */ #define DBG_io2 7 /* io functions that are called very often */ #define DBG_data 8 /* log image data */ /* Flags */ #define RTS8891_FLAG_UNTESTED (1 << 0) /* Print a warning for these scanners */ #define RTS8891_FLAG_EMULATED_GRAY_MODE (2 << 0) /* gray scans are emulated using comor modes */ #define LOWORD(x) ((uint16_t)(x & 0xffff)) #define HIWORD(x) ((uint16_t)(x >> 16)) #define LOBYTE(x) ((uint8_t)((x) & 0xFF)) #define HIBYTE(x) ((uint8_t)((x) >> 8)) #define MAX_SCANNERS 32 #define MAX_RESOLUTIONS 16 #define SENSOR_TYPE_BARE 0 /* sensor for hp4470 sold bare */ #define SENSOR_TYPE_XPA 1 /* sensor for hp4470 sold with XPA */ #define SENSOR_TYPE_4400 2 /* sensor for hp4400 */ #define SENSOR_TYPE_4400_BARE 3 /* sensor for hp4400 */ #define SENSOR_TYPE_MAX 3 /* maximum sensor number value */ /* Forward typedefs */ typedef struct Rts8891_Device Rts8891_Device; #define SET_DOUBLE(regs,idx,value) regs[idx]=(SANE_Byte)((value)>>8); regs[idx-1]=(SANE_Byte)((value) & 0xff); /* * defines for RTS8891 registers name */ #define BUTTONS_REG2 0x1a #define LINK_REG 0xb1 #define LAMP_REG 0xd9 #define LAMP_BRIGHT_REG 0xda /* double reg (E6,E5) -> timing doubles when y resolution doubles * E6 is high byte, possibly exposure */ #define EXPOSURE_REG 0xe6 #define TIMING_REG 0x81 #define TIMING1_REG 0x83 /* holds REG8180+1 */ #define TIMING2_REG 0x8a /* holds REG8180+2 */ /* this struc describes a particular model which is handled by the backend */ /* available resolutions, physical goemetry, scanning area, ... */ typedef struct Rts8891_Model { SANE_String_Const name; SANE_String_Const vendor; SANE_String_Const product; SANE_String_Const type; SANE_Int xdpi_values[MAX_RESOLUTIONS]; /* possible x resolutions */ SANE_Int ydpi_values[MAX_RESOLUTIONS]; /* possible y resolutions */ SANE_Int max_xdpi; /* physical maximum x dpi */ SANE_Int max_ydpi; /* physical maximum y dpi */ SANE_Int min_ydpi; /* physical minimum y dpi */ SANE_Fixed x_offset; /* Start of scan area in mm */ SANE_Fixed y_offset; /* Start of scan area in mm */ SANE_Fixed x_size; /* Size of scan area in mm */ SANE_Fixed y_size; /* Size of scan area in mm */ SANE_Fixed x_offset_ta; /* Start of scan area in TA mode in mm */ SANE_Fixed y_offset_ta; /* Start of scan area in TA mode in mm */ SANE_Fixed x_size_ta; /* Size of scan area in TA mode in mm */ SANE_Fixed y_size_ta; /* Size of scan area in TA mode in mm */ /* Line-distance correction (in pixel at max optical dpi) for CCD scanners */ SANE_Int ld_shift_r; /* red */ SANE_Int ld_shift_g; /* green */ SANE_Int ld_shift_b; /* blue */ /* default sensor type */ SANE_Int sensor; /* default gamma table */ SANE_Word gamma[256]; SANE_Int buttons; /* number of buttons for the scanner */ char *button_name[11]; /* option names for buttons */ char *button_title[11]; /* option titles for buttons */ SANE_Word flags; /* allow per model behaviour control */ } Rts8891_Model; /** * device specific configuration structure to hold option values */ typedef struct Rts8891_Config { /**< index number in device table to override detection */ SANE_Word modelnumber; /**< id of the snedor type, must match SENSOR_TYPE_* defines */ SANE_Word sensornumber; /**< if true, use release/acquire to allow the same device * to be used by several frontends */ SANE_Bool allowsharing; } Rts8891_Config; /** * device descriptor */ struct Rts8891_Device { /**< Next device in linked list */ struct Rts8891_Device *next; /**< USB device number for libusb */ SANE_Int devnum; SANE_String file_name; Rts8891_Model *model; /* points to a structure that decribes model specifics */ SANE_Int sensor; /* sensor id */ SANE_Bool initialized; /* true if device has been intialized */ SANE_Bool needs_warming; /* true if device needs warming up */ SANE_Bool parking; /* true if device is parking head */ /* values detected during find origin */ /* TODO these are currently unused after detection */ SANE_Int left_offset; /* pixels to skip to be on left start of the scanning area */ SANE_Int top_offset; /* lines to skip to be at top of the scanning area */ /* gains from calibration */ SANE_Int red_gain; SANE_Int green_gain; SANE_Int blue_gain; /* offsets from calibration */ SANE_Int red_offset; SANE_Int green_offset; SANE_Int blue_offset; /* actual dpi used at hardware level may differ from the one * at SANE level */ SANE_Int xdpi; SANE_Int ydpi; /* the effective scan area at hardware level may be different from * the one at the SANE level*/ SANE_Int lines; /* lines to scan */ SANE_Int pixels; /* width of scan area */ SANE_Int bytes_per_line; /* number of bytes per line */ SANE_Int xstart; /* x start coordinate */ SANE_Int ystart; /* y start coordinate */ /* line distance shift for the active scan */ SANE_Int lds_r; SANE_Int lds_g; SANE_Int lds_b; /* threshold to give 0/1 nit in lineart */ SANE_Int threshold; /* max value from lds_r, lds_g and lds_b */ SANE_Int lds_max; /* amount of data needed to correct ripple effect at highest dpi */ SANE_Int ripple; /* register set of the scanner */ SANE_Int reg_count; SANE_Byte regs[255]; /* shading calibration data */ SANE_Byte *shading_data; /* data buffer read from scanner */ SANE_Byte *scanned_data; /* size of the buffer */ SANE_Int data_size; /* start of the data within scanned data */ SANE_Byte *start; /* current pointer within scanned data */ SANE_Byte *current; /* end of the data buffer */ SANE_Byte *end; /** * amount of bytes read from scanner */ SANE_Int read; /** * total amount of bytes to read for the scan */ SANE_Int to_read; #ifdef HAVE_SYS_TIME_H /** * last scan time, used to detect if warming-up is needed */ struct timeval last_scan; /** * warming-up start time */ struct timeval start_time; #endif /** * device configuration options */ Rts8891_Config conf; }; /* * This struct is used to build a static list of USB IDs and link them * to a struct that describes the corresponding model. */ typedef struct Rts8891_USB_Device_Entry { SANE_Word vendor_id; /**< USB vendor identifier */ SANE_Word product_id; /**< USB product identifier */ Rts8891_Model *model; /**< Scanner model information */ } Rts8891_USB_Device_Entry; /* this function init the rts8891 library */ void rts8891_lib_init (void); /***********************************/ /* RTS8891 ASIC specific functions */ /***********************************/ /* this functions commits pending scan command */ static SANE_Status rts8891_commit (SANE_Int devnum, SANE_Byte value); /* wait for head to park to home position */ static SANE_Status rts8891_wait_for_home (struct Rts8891_Device *device, SANE_Byte * regs); /** * move the head backward by a huge line number then poll home sensor until * head has get back home */ static SANE_Status rts8891_park (struct Rts8891_Device *device, SANE_Byte * regs, SANE_Bool wait); #endif /* not RTS8891_LOW_H */ sane-backends-1.0.27/backend/pint.h0000664000175000017500000000607012112021330013720 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Gordon Matzigkeit This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef _PINT_H #define _PINT_H #include /* FIXME - in the PINT sources, this is set to ifdef __NetBSD__ */ #include #ifdef HAVE_SYS_SCANIO_H #include #endif typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* FIXME: eventually need to have both X and Y resolution. */ OPT_RESOLUTION, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, /* must come last: */ NUM_OPTIONS } PINT_Option; typedef struct PINT_Device { struct PINT_Device *next; SANE_Device sane; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; struct scan_io scanio; /* Scanner hardware state. */ } PINT_Device; typedef struct PINT_Scanner { /* all the state needed to define a scan request: */ struct PINT_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; int scanning; SANE_Parameters params; int fd; /* Device file descriptor */ /* scanner dependent/low-level state: */ PINT_Device *hw; } PINT_Scanner; #endif /* _PINT_H */ sane-backends-1.0.27/backend/gt68xx_low.c0000664000175000017500000007242012112021330014774 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov Copyright (C) 2002 - 2007 Henning Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file * @brief Implementation of the low-level scanner interface functions. */ #include "gt68xx_low.h" #include "../include/sane/sane.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_usb.h" #include #include #ifdef USE_FORK #include #include #include "gt68xx_shm_channel.c" #endif /** Check that the device pointer is not NULL. * * @param dev Pointer to the device object (GT68xx_Device). * @param func_name Function name (for use in debug messages). */ #define CHECK_DEV_NOT_NULL(dev, func_name) \ do { \ IF_DBG( \ if (!(dev)) \ { \ DBG (0, "BUG: NULL device\n"); \ return SANE_STATUS_INVAL; \ } \ ) \ } while (SANE_FALSE) /** Check that the device is open. * * @param dev Pointer to the device object (GT68xx_Device). * @param func_name Function name (for use in debug messages). */ #define CHECK_DEV_OPEN(dev, func_name) \ do { \ IF_DBG( \ CHECK_DEV_NOT_NULL ((dev), (func_name)); \ if ((dev)->fd == -1) \ { \ DBG (0, "%s: BUG: device %p not open\n", (func_name), \ ((void *) dev)); \ return SANE_STATUS_INVAL; \ } \ ) \ } while (SANE_FALSE) /** Check that the device is open and active. * * @param dev Pointer to the device (GT68xx_Device). * @param func_name Function name (for use in debug messages). */ #define CHECK_DEV_ACTIVE(dev, func_name) \ do { \ IF_DBG( \ CHECK_DEV_OPEN ((dev), (func_name)); \ if (!(dev)->active) \ { \ DBG (0, "%s: BUG: device %p not active\n", (func_name), \ ((void *) dev)); \ return SANE_STATUS_INVAL; \ } \ ) \ } while (SANE_FALSE) #ifndef NDEBUG /** Dump a request packet for debugging purposes. * * @param prefix String printed before the packet contents. * @param req The request packet to be dumped. */ static void dump_req (SANE_String_Const prefix, GT68xx_Packet req) { int i; char buf[GT68XX_PACKET_SIZE * 3 + 1]; for (i = 0; i < GT68XX_PACKET_SIZE; ++i) sprintf (buf + i * 3, " %02x", req[i]); DBG (8, "%s%s\n", prefix, buf); } #endif /* not NDEBUG */ /** Dump a request packet if the debug level is at 8 or above. * * @param prefix String printed before the packet contents. * @param req The request packet to be dumped. */ #define DUMP_REQ(prefix, req) \ do { IF_DBG( if (DBG_LEVEL >= 8) dump_req ((prefix), (req)); ) } while (0) SANE_Status gt68xx_device_new (GT68xx_Device ** dev_return) { GT68xx_Device *dev; DBG (7, "gt68xx_device_new: enter\n"); if (!dev_return) return SANE_STATUS_INVAL; dev = (GT68xx_Device *) malloc (sizeof (GT68xx_Device)); if (!dev) { DBG (3, "gt68xx_device_new: couldn't malloc %lu bytes for device\n", (u_long) sizeof (GT68xx_Device)); *dev_return = 0; return SANE_STATUS_NO_MEM; } *dev_return = dev; memset (dev, 0, sizeof (GT68xx_Device)); dev->fd = -1; dev->active = SANE_FALSE; dev->model = NULL; dev->command_set_private = NULL; dev->read_buffer = NULL; dev->read_buffer_size = 32768; dev->manual_selection = SANE_FALSE; #ifdef USE_FORK dev->shm_channel = NULL; #endif /* USE_FORK */ DBG (7, "gt68xx_device_new:: leave: ok\n"); return SANE_STATUS_GOOD; } SANE_Status gt68xx_device_free (GT68xx_Device * dev) { DBG (7, "gt68xx_device_free: enter: dev=%p\n", (void *) dev); if (dev) { if (dev->active) gt68xx_device_deactivate (dev); if (dev->fd != -1) gt68xx_device_close (dev); if (dev->model && dev->model->allocated) { DBG (7, "gt68xx_device_free: freeing model data %p\n", (void *) dev->model); free (dev->model); } DBG (7, "gt68xx_device_free: freeing dev\n"); free (dev); } DBG (7, "gt68xx_device_free: leave: ok\n"); return SANE_STATUS_GOOD; } static GT68xx_USB_Device_Entry * gt68xx_find_usb_device_entry (SANE_Word vendor, SANE_Word product) { GT68xx_USB_Device_Entry *entry; for (entry = gt68xx_usb_device_list; entry->model; ++entry) { if (vendor == entry->vendor && product == entry->product) return entry; } return NULL; } static SANE_Status gt68xx_device_identify (GT68xx_Device * dev) { SANE_Status status; SANE_Word vendor, product; GT68xx_USB_Device_Entry *entry; CHECK_DEV_OPEN (dev, "gt68xx_device_identify"); status = sanei_usb_get_vendor_product (dev->fd, &vendor, &product); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_identify: error getting USB id: %s\n", sane_strstatus (status)); return status; } entry = gt68xx_find_usb_device_entry (vendor, product); if (entry) { dev->model = entry->model; } else { dev->model = NULL; DBG (3, "gt68xx_device_identify: unknown USB device (vendor 0x%04x, " "product 0x%04x)\n", vendor, product); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } SANE_Status gt68xx_device_open (GT68xx_Device * dev, const char *dev_name) { SANE_Status status; SANE_Int fd; DBG (7, "gt68xx_device_open: enter: dev=%p\n", (void *) dev); CHECK_DEV_NOT_NULL (dev, "gt68xx_device_open"); if (dev->fd != -1) { DBG (3, "gt68xx_device_open: device already open\n"); return SANE_STATUS_INVAL; } status = sanei_usb_open (dev_name, &fd); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_open: sanei_usb_open failed: %s\n", sane_strstatus (status)); return status; } dev->fd = fd; if (!dev->model) gt68xx_device_identify (dev); DBG (7, "gt68xx_device_open: leave: ok\n"); return SANE_STATUS_GOOD; } SANE_Status gt68xx_device_close (GT68xx_Device * dev) { DBG (7, "gt68xx_device_close: enter: dev=%p\n", (void *) dev); CHECK_DEV_OPEN (dev, "gt68xx_device_close"); if (dev->active) gt68xx_device_deactivate (dev); sanei_usb_close (dev->fd); dev->fd = -1; DBG (7, "gt68xx_device_close: leave: ok\n"); return SANE_STATUS_GOOD; } SANE_Bool gt68xx_device_is_configured (GT68xx_Device * dev) { if (dev && dev->model && dev->model->command_set) return SANE_TRUE; else return SANE_FALSE; } SANE_Status gt68xx_device_set_model (GT68xx_Device * dev, GT68xx_Model * model) { if (dev->active) { DBG (3, "gt68xx_device_set_model: device already active\n"); return SANE_STATUS_INVAL; } if (dev->model && dev->model->allocated) free (dev->model); dev->model = model; return SANE_STATUS_GOOD; } static SANE_Bool gt68xx_device_get_model (SANE_String name, GT68xx_Model ** model) { GT68xx_USB_Device_Entry *entry; for (entry = gt68xx_usb_device_list; entry->model; ++entry) { if (strcmp (name, entry->model->name) == 0) { *model = entry->model; return SANE_TRUE; } } return SANE_FALSE; } SANE_Status gt68xx_device_activate (GT68xx_Device * dev) { SANE_Status status; CHECK_DEV_OPEN (dev, "gt68xx_device_activate"); if (dev->active) { DBG (3, "gt68xx_device_activate: device already active\n"); return SANE_STATUS_INVAL; } if (!gt68xx_device_is_configured (dev)) { DBG (3, "gt68xx_device_activate: device is not configured\n"); return SANE_STATUS_INVAL; } DBG (7, "gt68xx_device_activate: model \"%s\"\n", dev->model->name); if (dev->model->command_set->activate) { status = (*dev->model->command_set->activate) (dev); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_activate: command-set-specific " "activate failed: %s\n", sane_strstatus (status)); return status; } } dev->afe = malloc (sizeof (*dev->afe)); dev->exposure = malloc (sizeof (*dev->exposure)); if (!dev->afe || !dev->exposure) return SANE_STATUS_NO_MEM; memcpy (dev->afe, &dev->model->afe_params, sizeof (*dev->afe)); memcpy (dev->exposure, &dev->model->exposure, sizeof (*dev->exposure)); dev->gamma_value = dev->model->default_gamma_value; dev->active = SANE_TRUE; return SANE_STATUS_GOOD; } SANE_Status gt68xx_device_deactivate (GT68xx_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; CHECK_DEV_ACTIVE (dev, "gt68xx_device_deactivate"); if (dev->read_active) gt68xx_device_read_finish (dev); if (dev->model->command_set->deactivate) { status = (*dev->model->command_set->deactivate) (dev); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_deactivate: command set-specific deactivate failed: %s\n", sane_strstatus (status)); /* proceed with deactivate anyway */ } } if (dev->afe) free (dev->afe); dev->afe = 0; if (dev->exposure) free (dev->exposure); dev->exposure = 0; dev->active = SANE_FALSE; return status; } SANE_Status gt68xx_device_memory_write (GT68xx_Device * dev, SANE_Word addr, SANE_Word size, SANE_Byte * data) { SANE_Status status; DBG (8, "gt68xx_device_memory_write: dev=%p, addr=0x%x, size=0x%x, data=%p\n", (void *) dev, addr, size, data); CHECK_DEV_ACTIVE (dev, "gt68xx_device_memory_write"); status = sanei_usb_control_msg (dev->fd, 0x40, dev->model->command_set->request, dev->model->command_set->memory_write_value, addr, size, data); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_memory_write: sanei_usb_control_msg failed: %s\n", sane_strstatus (status)); } return status; } SANE_Status gt68xx_device_memory_read (GT68xx_Device * dev, SANE_Word addr, SANE_Word size, SANE_Byte * data) { SANE_Status status; DBG (8, "gt68xx_device_memory_read: dev=%p, addr=0x%x, size=0x%x, data=%p\n", (void *) dev, addr, size, data); CHECK_DEV_ACTIVE (dev, "gt68xx_device_memory_read"); status = sanei_usb_control_msg (dev->fd, 0xc0, dev->model->command_set->request, dev->model->command_set->memory_read_value, addr, size, data); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_memory_read: sanei_usb_control_msg failed: %s\n", sane_strstatus (status)); } return status; } static SANE_Status gt68xx_device_generic_req (GT68xx_Device * dev, SANE_Byte request_type, SANE_Word request, SANE_Word cmd_value, SANE_Word cmd_index, SANE_Word res_value, SANE_Word res_index, GT68xx_Packet cmd, GT68xx_Packet res, size_t res_size) { SANE_Status status; DBG (7, "gt68xx_device_generic_req: command=0x%02x\n", cmd[0]); DUMP_REQ (">>", cmd); CHECK_DEV_ACTIVE (dev, "gt68xx_device_generic_req"); status = sanei_usb_control_msg (dev->fd, request_type, request, cmd_value, cmd_index, GT68XX_PACKET_SIZE, cmd); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_generic_req: writing command failed: %s\n", sane_strstatus (status)); return status; } memset (res, 0, sizeof (GT68xx_Packet)); status = sanei_usb_control_msg (dev->fd, request_type | 0x80, request, res_value, res_index, res_size, res); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_generic_req: reading response failed: %s\n", sane_strstatus (status)); return status; } DUMP_REQ ("<<", res); return status; } SANE_Status gt68xx_device_req (GT68xx_Device * dev, GT68xx_Packet cmd, GT68xx_Packet res) { GT68xx_Command_Set *command_set = dev->model->command_set; return gt68xx_device_generic_req (dev, command_set->request_type, command_set->request, command_set->send_cmd_value, command_set->send_cmd_index, command_set->recv_res_value, command_set->recv_res_index, cmd, res, GT68XX_PACKET_SIZE); } SANE_Status gt68xx_device_small_req (GT68xx_Device * dev, GT68xx_Packet cmd, GT68xx_Packet res) { GT68xx_Command_Set *command_set = dev->model->command_set; GT68xx_Packet fixed_cmd; int i; for (i = 0; i < 8; ++i) memcpy (fixed_cmd + i * 8, cmd, 8); return gt68xx_device_generic_req (dev, command_set->request_type, command_set->request, command_set->send_small_cmd_value, command_set->send_small_cmd_index, command_set->recv_small_res_value, command_set->recv_small_res_index, fixed_cmd, res, 0x08); } SANE_Status gt68xx_device_download_firmware (GT68xx_Device * dev, SANE_Byte * data, SANE_Word size) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_download_firmware"); if (dev->model->command_set->download_firmware) return (*dev->model->command_set->download_firmware) (dev, data, size); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_get_power_status"); if (dev->model->command_set->get_power_status) return (*dev->model->command_set->get_power_status) (dev, power_ok); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_get_ta_status (GT68xx_Device * dev, SANE_Bool * ta_attached) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_get_ta_status"); if (dev->model->command_set->get_ta_status) return (*dev->model->command_set->get_ta_status) (dev, ta_attached); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp, SANE_Bool ta_lamp) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_lamp_control"); if (dev->model->command_set->lamp_control) return (*dev->model->command_set->lamp_control) (dev, fb_lamp, ta_lamp); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_is_moving (GT68xx_Device * dev, SANE_Bool * moving) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_is_moving"); if (dev->model->command_set->is_moving) return (*dev->model->command_set->is_moving) (dev, moving); else return SANE_STATUS_UNSUPPORTED; } /* currently not used */ #if 0 static SANE_Status gt68xx_device_move_relative (GT68xx_Device * dev, SANE_Int distance) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_move_relative"); if (dev->model->command_set->move_relative) return (*dev->model->command_set->move_relative) (dev, distance); else return SANE_STATUS_UNSUPPORTED; } #endif SANE_Status gt68xx_device_carriage_home (GT68xx_Device * dev) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_carriage_home"); if (dev->model->command_set->carriage_home) return (*dev->model->command_set->carriage_home) (dev); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_paperfeed (GT68xx_Device * dev) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_paperfeed"); if (dev->model->command_set->paperfeed) return (*dev->model->command_set->paperfeed) (dev); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_start_scan (GT68xx_Device * dev) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_start_scan"); if (dev->model->command_set->start_scan) return (*dev->model->command_set->start_scan) (dev); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_read_scanned_data (GT68xx_Device * dev, SANE_Bool * ready) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_read_scanned_data"); if (dev->model->command_set->read_scanned_data) return (*dev->model->command_set->read_scanned_data) (dev, ready); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_setup_scan (GT68xx_Device * dev, GT68xx_Scan_Request * request, GT68xx_Scan_Action action, GT68xx_Scan_Parameters * params) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_setup_scan"); if (dev->model->command_set->setup_scan) return (*dev->model->command_set->setup_scan) (dev, request, action, params); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_set_afe (GT68xx_Device * dev, GT68xx_AFE_Parameters * params) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_set_afe"); if (dev->model->command_set->set_afe) return (*dev->model->command_set->set_afe) (dev, params); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_set_exposure_time (GT68xx_Device * dev, GT68xx_Exposure_Parameters * params) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_set_exposure_time"); if (dev->model->command_set->set_exposure_time) return (*dev->model->command_set->set_exposure_time) (dev, params); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_stop_scan (GT68xx_Device * dev) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_stop_scan"); if (dev->model->command_set->stop_scan) return (*dev->model->command_set->stop_scan) (dev); else return SANE_STATUS_UNSUPPORTED; } SANE_Status gt68xx_device_read_raw (GT68xx_Device * dev, SANE_Byte * buffer, size_t * size) { SANE_Status status; CHECK_DEV_ACTIVE (dev, "gt68xx_device_read_raw"); DBG (7, "gt68xx_device_read_raw: enter: size=%lu\n", (unsigned long) *size); status = sanei_usb_read_bulk (dev->fd, buffer, size); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_read_raw: bulk read failed: %s\n", sane_strstatus (status)); return status; } DBG (7, "gt68xx_device_read_raw: leave: size=%lu\n", (unsigned long) *size); return SANE_STATUS_GOOD; } SANE_Status gt68xx_device_set_read_buffer_size (GT68xx_Device * dev, size_t buffer_size) { CHECK_DEV_NOT_NULL (dev, "gt68xx_device_set_read_buffer_size"); if (dev->read_active) { DBG (3, "gt68xx_device_set_read_buffer_size: BUG: read already " "active\n"); return SANE_STATUS_INVAL; } buffer_size = (buffer_size + 63UL) & ~63UL; if (buffer_size > 0) { dev->requested_buffer_size = buffer_size; return SANE_STATUS_GOOD; } DBG (3, "gt68xx_device_set_read_buffer_size: bad buffer size\n"); return SANE_STATUS_INVAL; } SANE_Status gt68xx_device_read_prepare (GT68xx_Device * dev, size_t expected_count, SANE_Bool final_scan) { size_t buffer_size; CHECK_DEV_ACTIVE (dev, "gt68xx_device_read_prepare"); if (dev->read_active) { DBG (3, "gt68xx_device_read_prepare: read already active\n"); return SANE_STATUS_INVAL; } DBG (5, "gt68xx_device_read_prepare: total size: %lu bytes\n", (unsigned long) expected_count); buffer_size = dev->requested_buffer_size; DBG (5, "gt68xx_device_read_prepare: requested buffer size: %lu\n", (unsigned long) buffer_size); if (buffer_size > expected_count) { buffer_size = (expected_count + 63UL) & ~63UL; } DBG (5, "gt68xx_device_read_prepare: real size: %lu\n", (unsigned long) buffer_size); dev->read_buffer_size = buffer_size; dev->read_buffer = (SANE_Byte *) malloc (buffer_size); if (!dev->read_buffer) { DBG (3, "gt68xx_device_read_prepare: not enough memory for the read buffer (%lu bytes)\n", (unsigned long) buffer_size); return SANE_STATUS_NO_MEM; } dev->read_active = SANE_TRUE; dev->final_scan = final_scan; dev->read_pos = dev->read_bytes_in_buffer = 0; dev->read_bytes_left = expected_count; return SANE_STATUS_GOOD; } #ifdef USE_FORK static SANE_Status gt68xx_reader_process (GT68xx_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; SANE_Int buffer_id; SANE_Byte *buffer_addr; size_t size; SANE_Int line = 0; size_t read_bytes_left = dev->read_bytes_left; shm_channel_writer_init (dev->shm_channel); while (read_bytes_left > 0) { status = shm_channel_writer_get_buffer (dev->shm_channel, &buffer_id, &buffer_addr); if (status != SANE_STATUS_GOOD) break; DBG (9, "gt68xx_reader_process: buffer %d: get\n", buffer_id); size = dev->read_buffer_size; DBG (9, "gt68xx_reader_process: buffer %d: trying to read %lu bytes " "(%lu bytes left, line %d)\n", buffer_id, (unsigned long) size, (unsigned long) read_bytes_left, line); status = gt68xx_device_read_raw (dev, buffer_addr, &size); if (status != SANE_STATUS_GOOD) break; DBG (9, "gt68xx_reader_process: buffer %d: read %lu bytes (line %d)\n", buffer_id, (unsigned long) size, line); status = shm_channel_writer_put_buffer (dev->shm_channel, buffer_id, size); if (status != SANE_STATUS_GOOD) break; DBG (9, "gt68xx_reader_process: buffer %d: put\n", buffer_id); read_bytes_left -= size; line++; } DBG (9, "gt68xx_reader_process: finished, now sleeping\n"); if (status != SANE_STATUS_GOOD) return status; sleep (5 * 60); /* wait until we are killed (or timeout) */ shm_channel_writer_close (dev->shm_channel); return status; } static SANE_Status gt68xx_device_read_start_fork (GT68xx_Device * dev) { SANE_Status status; int pid; if (dev->shm_channel) { DBG (3, "gt68xx_device_read_start_fork: BUG: shm_channel already created\n"); return SANE_STATUS_INVAL; } status = shm_channel_new (dev->read_buffer_size, SHM_BUFFERS, &dev->shm_channel); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_read_start_fork: cannot create shared memory channel: " "%s\n", sane_strstatus (status)); dev->shm_channel = NULL; return status; } pid = fork (); if (pid == -1) { DBG (3, "gt68xx_device_read_start_fork: cannot fork: %s\n", strerror (errno)); shm_channel_free (dev->shm_channel); dev->shm_channel = NULL; return SANE_STATUS_NO_MEM; } if (pid == 0) { /* Child process */ status = gt68xx_reader_process (dev); _exit (status); } else { /* Parent process */ dev->reader_pid = pid; shm_channel_reader_init (dev->shm_channel); shm_channel_reader_start (dev->shm_channel); return SANE_STATUS_GOOD; } } #endif /* USE_FORK */ static SANE_Status gt68xx_device_read_start (GT68xx_Device * dev) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_read_start"); #ifdef USE_FORK /* Don't fork a separate process for every calibration scan. */ if (dev->final_scan) return gt68xx_device_read_start_fork (dev); #endif /* USE_FORK */ return SANE_STATUS_GOOD; } SANE_Status gt68xx_device_read (GT68xx_Device * dev, SANE_Byte * buffer, size_t * size) { SANE_Status status; size_t byte_count = 0; size_t left_to_read = *size; size_t transfer_size, block_size, raw_block_size; #ifdef USE_FORK SANE_Int buffer_id; SANE_Byte *buffer_addr; SANE_Int buffer_bytes; #endif /* USE_FORK */ CHECK_DEV_ACTIVE (dev, "gt68xx_device_read"); if (!dev->read_active) { DBG (3, "gt68xx_device_read: read not active\n"); return SANE_STATUS_INVAL; } while (left_to_read > 0) { if (dev->read_bytes_in_buffer == 0) { block_size = dev->read_buffer_size; if (block_size > dev->read_bytes_left) block_size = dev->read_bytes_left; if (block_size == 0) break; raw_block_size = (block_size + 63UL) & ~63UL; DBG (7, "gt68xx_device_read: trying to read %ld bytes\n", (long) raw_block_size); #ifdef USE_FORK if (dev->shm_channel) { status = shm_channel_reader_get_buffer (dev->shm_channel, &buffer_id, &buffer_addr, &buffer_bytes); if (status == SANE_STATUS_GOOD && buffer_addr != NULL) { DBG (9, "gt68xx_device_read: buffer %d: get\n", buffer_id); memcpy (dev->read_buffer, buffer_addr, buffer_bytes); shm_channel_reader_put_buffer (dev->shm_channel, buffer_id); DBG (9, "gt68xx_device_read: buffer %d: put\n", buffer_id); } } else #endif /* USE_FORK */ status = gt68xx_device_read_raw (dev, dev->read_buffer, &raw_block_size); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_device_read: read failed\n"); return status; } dev->read_pos = 0; dev->read_bytes_in_buffer = block_size; dev->read_bytes_left -= block_size; } transfer_size = left_to_read; if (transfer_size > dev->read_bytes_in_buffer) transfer_size = dev->read_bytes_in_buffer; if (transfer_size > 0) { memcpy (buffer, dev->read_buffer + dev->read_pos, transfer_size); dev->read_pos += transfer_size; dev->read_bytes_in_buffer -= transfer_size; byte_count += transfer_size; left_to_read -= transfer_size; buffer += transfer_size; } } *size = byte_count; if (byte_count == 0) return SANE_STATUS_EOF; else return SANE_STATUS_GOOD; } SANE_Status gt68xx_device_read_finish (GT68xx_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; CHECK_DEV_ACTIVE (dev, "gt68xx_device_read_finish"); if (!dev->read_active) { DBG (3, "gt68xx_device_read_finish: read not active\n"); return SANE_STATUS_INVAL; } DBG (7, "gt68xx_device_read_finish: read_bytes_left = %ld\n", (long) dev->read_bytes_left); #ifdef USE_FORK if (dev->reader_pid != 0) { int pid_status; /* usleep (100000); */ DBG (7, "gt68xx_device_read_finish: trying to kill reader process\n"); kill (dev->reader_pid, SIGKILL); waitpid (dev->reader_pid, &pid_status, 0); if (WIFEXITED (pid_status)) status = WEXITSTATUS (pid_status); DBG (7, "gt68xx_device_read_finish: reader process killed\n"); dev->reader_pid = 0; } if (dev->shm_channel) { shm_channel_free (dev->shm_channel); dev->shm_channel = NULL; } #endif /* USE_FORK */ free (dev->read_buffer); dev->read_buffer = NULL; dev->read_active = SANE_FALSE; DBG (7, "gt68xx_device_read_finish: exit (%s)\n", sane_strstatus (status)); return status; } static SANE_Status gt68xx_device_check_result (GT68xx_Packet res, SANE_Byte command) { if (res[0] != 0) { DBG (1, "gt68xx_device_check_result: result was %2X %2X " "(expected: %2X %2X)\n", res[0], res[1], 0, command); return SANE_STATUS_IO_ERROR; } /* The Gt681xfw.usb firmware doesn't return the command byte in the second byte, so we can't rely on that test */ if (res[1] != command) DBG (5, "gt68xx_device_check_result: warning: result was %2X %2X " "(expected: %2X %2X)\n", res[0], res[1], 0, command); return SANE_STATUS_GOOD; } SANE_Status gt68xx_device_get_id (GT68xx_Device * dev) { CHECK_DEV_ACTIVE (dev, "gt68xx_device_get_id"); if (dev->model->command_set->get_id) return (*dev->model->command_set->get_id) (dev); else return SANE_STATUS_UNSUPPORTED; } static void gt68xx_device_fix_descriptor (GT68xx_Device * dev) { SANE_Byte data[8]; sanei_usb_control_msg (dev->fd, 0x80, 0x06, 0x01 << 8, 0, 8, data); } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/hp5400_debug.h0000664000175000017500000000501212112021330015027 00000000000000#ifndef __HP5400_DEBUG_H_ #define __HP5400_DEBUG_H_ /* sane - Scanner Access Now Easy. Copyright (C) 2003 Martijn van Oosterhout Copyright (C) 2003 Thomas Soumarmon Originally copied from HP3300 testtools. Original notice follows: Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef STANDALONE #define DEBUG_NOT_STATIC #define DEBUG_DECLARE_ONLY #include "../include/sane/sanei_debug.h" #define DBG_ASSERT 1 #define DBG_ERR 16 #define DBG_MSG 32 #define HP5400_DBG DBG #define HP5400_SANE_STATIC static #else #include #define LOCAL_DBG #define HP5400_DBG fprintf extern FILE *DBG_ASSERT; extern FILE *DBG_ERR; extern FILE *DBG_MSG; void hp5400_dbg_start(); #define HP5400_SANE_STATIC #endif #endif sane-backends-1.0.27/backend/sp15c-scsi.h0000664000175000017500000004760012112021330014644 00000000000000#ifndef SP15C_SCSI_H #define SP15C_SCSI_H static const char RCSid_sh[] = "$Header$"; /* sane - Scanner Access Now Easy. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Fujitsu ScanParner 15c flatbed/ADF scanners. It was derived from the COOLSCAN driver. Written by Randolph Bentson */ /* ------------------------------------------------------------------------- */ /* * $Log$ * Revision 1.6 2005/09/19 19:57:48 fzago-guest * Replaced __unused__ with __sane_unused__ to avoid a namespace conflict. * * Revision 1.5 2004/11/13 19:53:04 fzago-guest * Fixes some warnings. * * Revision 1.4 2003/12/27 17:48:38 hmg-guest * Silenced some compilation warnings. * * Revision 1.3 2000/08/12 15:09:37 pere * Merge devel (v1.0.3) into head branch. * * Revision 1.1.2.4 2000/03/14 17:47:12 abel * new version of the Sharp backend added. * * Revision 1.1.2.3 2000/02/14 14:20:19 pere * Make lint_catcher static to avoid link problems with duplicate symbols. * * Revision 1.1.2.2 2000/01/26 03:51:48 pere * Updated backends sp15c (v1.12) and m3096g (v1.11). * * Revision 1.7 2000/01/05 05:27:34 bentson * indent to barfin' GNU style * * Revision 1.6 1999/12/03 20:56:44 bentson * add MEDIA CHECK command * * Revision 1.5 1999/11/24 15:57:50 bentson * add license * * Revision 1.4 1999/11/23 19:04:08 bentson * clean up and enhance inquiry command * * Revision 1.3 1999/11/23 06:42:19 bentson * add 4-bit grayscale support; fix color count field placement * * Revision 1.2 1999/11/22 18:15:43 bentson * more work on color support * * Revision 1.1 1999/11/19 15:09:08 bentson * cribbed from m3096g * */ /****************************************************/ static inline void setbitfield (unsigned char *pageaddr, int mask, int shift, int val) \ { *pageaddr = (*pageaddr & ~(mask << shift)) | ((val & mask) << shift); } /* ------------------------------------------------------------------------- */ static inline void resetbitfield (unsigned char *pageaddr, int mask, int shift, int val) \ { *pageaddr = (*pageaddr & ~(mask << shift)) | (((!val) & mask) << shift); } /* ------------------------------------------------------------------------- */ static inline int getbitfield (unsigned char *pageaddr, int mask, int shift) \ { return ((*pageaddr >> shift) & mask); } /* ------------------------------------------------------------------------- */ static inline int getnbyte (unsigned char *pnt, int nbytes) \ { unsigned int result = 0; int i; #ifdef DEBUG assert (nbytes < 5); #endif for (i = 0; i < nbytes; i++) result = (result << 8) | (pnt[i] & 0xff); return result; } /* ------------------------------------------------------------------------- */ static inline void putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) \ { int i; #ifdef DEBUG assert (nbytes < 5); #endif for (i = nbytes - 1; i >= 0; i--) \ { pnt[i] = value & 0xff; value = value >> 8; } } /* ==================================================================== */ /* SCSI commands */ typedef struct { unsigned char *cmd; unsigned int size; } scsiblk; /* ==================================================================== */ #define RESERVE_UNIT 0x16 #define RELEASE_UNIT 0x17 #define INQUIRY 0x12 #define REQUEST_SENSE 0x03 #define SEND_DIAGNOSTIC 0x1d #define TEST_UNIT_READY 0x00 #define SET_WINDOW 0x24 #define SET_SUBWINDOW 0xc0 #define OBJECT_POSITION 0x31 #define MEDIA_CHECK 0x08 #define SEND 0x2a #define READ 0x28 #define MODE_SELECT 0x15 #define MODE_SENSE 0x1a #define SCAN 0x1b /* ==================================================================== */ static unsigned char reserve_unitC[] = {RESERVE_UNIT, 0x00, 0x00, 0x00, 0x00, 0x00}; static scsiblk reserve_unitB = {reserve_unitC, sizeof (reserve_unitC)}; /* ==================================================================== */ static unsigned char release_unitC[] = {RELEASE_UNIT, 0x00, 0x00, 0x00, 0x00, 0x00}; static scsiblk release_unitB = {release_unitC, sizeof (release_unitC)}; /* ==================================================================== */ static unsigned char inquiryC[] = {INQUIRY, 0x00, 0x00, 0x00, 0x1f, 0x00}; static scsiblk inquiryB = {inquiryC, sizeof (inquiryC)}; #define set_IN_return_size(icb,val) icb[0x04]=val #define set_IN_length(out,n) out[0x04]=n-5 #define get_IN_periph_qual(in) getbitfield(in, 0x07, 5) #define IN_periph_qual_lun 0x00 #define IN_periph_qual_nolun 0x03 #define get_IN_periph_devtype(in) getbitfield(in, 0x1f, 0) #define IN_periph_devtype_scanner 0x06 #define IN_periph_devtype_unknown 0x1f #define get_IN_response_format(in) getbitfield(in + 0x03, 0x0f, 0) #define IN_recognized 0x02 #define get_IN_additional_length(in) in[0x04] #define get_IN_vendor(in, buf) strncpy(buf, in + 0x08, 0x08) #define get_IN_product(in, buf) strncpy(buf, in + 0x10, 0x010) #define get_IN_version(in, buf) strncpy(buf, in + 0x20, 0x04) #define get_IN_color_mode(in) getbitfield(in + 0x24, 0xf, 0) #define get_IN_color_seq(in) getbitfield(in + 0x24, 0x7, 4) #define get_IN_adf(in) getbitfield(in + 0x24, 0x1, 7) /* ==================================================================== */ static unsigned char request_senseC[] = {REQUEST_SENSE, 0x00, 0x00, 0x00, 0x00, 0x00}; static scsiblk request_senseB = {request_senseC, sizeof (request_senseC)}; #define set_RS_allocation_length(sb,val) sb[0x04] = (unsigned char)val /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) /* normally 0 */ #define get_RS_additional_length(b) b[0x07] /* always 10 */ #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /* valid, always 0 */ #define rs_return_block_size 18 /* Says Nikon */ /* ==================================================================== */ static unsigned char send_diagnosticC[] = {SEND_DIAGNOSTIC, 0x04, 0x00, 0x00, 0x00, 0x00}; static scsiblk send_diagnosticB = {send_diagnosticC, sizeof (send_diagnosticC)}; /* ==================================================================== */ static unsigned char test_unit_readyC[] = {TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00}; static scsiblk test_unit_readyB = {test_unit_readyC, sizeof (test_unit_readyC)}; /* ==================================================================== */ static unsigned char set_windowC[] = {SET_WINDOW, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}; /* opcode, lun, _____4 X reserved____, _transfer length, ctl */ static scsiblk set_windowB = {set_windowC, sizeof (set_windowC)}; #define set_SW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) #define get_SW_xferlen(sb) getnbyte(sb + 0x06, 3) /* ==================================================================== */ static unsigned char set_subwindowC[] = {SET_SUBWINDOW}; static scsiblk set_subwindowB = {set_subwindowC, sizeof (set_subwindowC)}; /* ==================================================================== */ static unsigned char object_positionC[] = {OBJECT_POSITION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* ADF, _____Count_____, ________Reserved______, Ctl */ static scsiblk object_positionB = {object_positionC, sizeof (object_positionC)}; #define set_OP_autofeed(b,val) setbitfield(b+0x01, 0x07, 0, val) #define OP_Discharge 0x00 #define OP_Feed 0x01 /* ==================================================================== */ static unsigned char media_checkC[] = {MEDIA_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00}; /* ADF, _Reserved_, Len, Ctl */ static scsiblk media_checkB = {media_checkC, sizeof (media_checkC)}; #define set_MC_return_size(sb,val) sb[0x04]=val #define get_MC_adf_status(sb) sb[0x00] #define MC_ADF_OK 0x01 /* ==================================================================== */ static unsigned char media_parameter_data_blockC[] = { 0x00 }; static scsiblk media_parameter_data_blockB = {media_parameter_data_blockC, sizeof (media_parameter_data_blockC)}; /* ==================================================================== */ static unsigned char sendC[] = {SEND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static scsiblk sendB = {sendC, sizeof (sendC)}; #define set_S_datatype_code(sb, val) sb[0x02] = (unsigned char)val #define S_datatype_imagedatai 0x00 #define S_EX_datatype_LUT 0x01 /* Experiment code */ #define S_EX_datatype_shading_data 0xa0 /* Experiment code */ #define S_user_reg_gamma 0xc0 #define S_device_internal_info 0x03 #define set_S_datatype_qual_upper(sb, val) sb[0x04] = (unsigned char)val #define S_DQ_none 0x00 #define S_DQ_Rcomp 0x06 #define S_DQ_Gcomp 0x07 #define S_DQ_Bcomp 0x08 #define S_DQ_Reg1 0x01 #define S_DQ_Reg2 0x02 #define S_DQ_Reg3 0x03 #define set_S_xfer_length(sb, val) putnbyte(sb + 0x06, val, 3) /* static unsigned char gamma_user_LUT_LS1K[512] = { 0x00 }; static scsiblk gamma_user_LUT_LS1K_LS1K = { gamma_user_LUT_LS1K, sizeof(gamma_user_LUT_LS1K) }; */ /* ==================================================================== */ static unsigned char readC[] = {READ, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* Type, rsvd, type qual, __xfer length__, Ctl */ static scsiblk readB = {readC, sizeof (readC)}; #define set_R_datatype_code(sb, val) sb[0x02] = val #define R_datatype_imagedata 0x00 #define R_pixel_size 0x80 #define set_R_xfer_length(sb, val) putnbyte(sb + 0x06, val, 3) /* ==================================================================== */ static unsigned char mode_selectC[] = {MODE_SELECT, 0x10, 0x00, 0x00, 0x00, 0x00}; static scsiblk mode_selectB = {mode_selectC, sizeof (mode_selectC)}; /* ==================================================================== */ static unsigned char mode_senseC[] = {MODE_SENSE, 0x18, 0x03, 0x00, 0x00, 0x00, /* PF set, page type 03 */ }; static scsiblk mode_senseB = {mode_senseC, sizeof (mode_senseC)}; #define set_MS_DBD(b, val) setbitfield(b, 0x01, 3, (val?1:0)) #define set_MS_len(b, val) putnbyte(b+0x04, val, 1) #define get_MS_MUD(b) getnbyte(b+(0x04+((int)*(b+0x3)))+0x4,2) /* ==================================================================== */ static unsigned char scanC[] = {SCAN, 0x00, 0x00, 0x00, 0x00, 0x00}; static scsiblk scanB = {scanC, sizeof (scanC)}; #define set_SC_xfer_length(sb, val) sb[0x04] = (unsigned char)val /* ==================================================================== */ /* We use the same structure for both SET WINDOW and GET WINDOW. */ static unsigned char window_parameter_data_blockC[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00, /* Window Descriptor Length */ }; static scsiblk window_parameter_data_blockB = {window_parameter_data_blockC, sizeof (window_parameter_data_blockC)}; #define set_WDPB_wdblen(sb, len) putnbyte(sb + 0x06, len, 2) #define get_WDPB_wdblen(sb) getnbyte(sb + 0x06, 2) #define WDB_size_empty 0x28 /* wdb_len if nothing is set by inquiry */ #define WDB_size_BW 0x40 #define WDB_size_Color 0x33 #define WDB_size_max 0xff /* ==================================================================== */ static unsigned char window_descriptor_blockC[] = { 0x00, /* 0x00 *//* Window Identifier */ #define set_WD_wid(sb, val) sb[0] = val #define WD_wid_all 0x00 /* Only one supported */ 0x00, /* 0x01 *//* reserved, AUTO */ #define set_WD_auto(sb, val) setbitfield(sb + 0x01, 1, 0, val) #define get_WD_auto(sb) getbitfield(sb + 0x01, 1, 0) 0x00, 0x00, /* 0x02 *//* X resolution in dpi, 0 => 400 */ #define set_WD_Xres(sb, val) putnbyte(sb + 0x02, val, 2) #define get_WD_Xres(sb) getnbyte(sb + 0x02, 2) 0x00, 0x00, /* 0x04 *//* Y resolution in dpi, 0 => 400 */ #define set_WD_Yres(sb, val) putnbyte(sb + 0x04, val, 2) #define get_WD_Yres(sb) getnbyte(sb + 0x04, 2) 0x00, 0x00, 0x00, 0x00, /* 0x06 *//* Upper Left X in inch/1200 */ #define set_WD_ULX(sb, val) putnbyte(sb + 0x06, val, 4) #define get_WD_ULX(sb) getnbyte(sb + 0x06, 4) 0x00, 0x00, 0x00, 0x00, /* 0x0a *//* Upper Left Y in inch/1200 */ #define set_WD_ULY(sb, val) putnbyte(sb + 0x0a, val, 4) #define get_WD_ULY(sb) getnbyte(sb + 0x0a, 4) 0x00, 0x00, 0x00, 0x00, /* 0x0e *//* Width */ #define set_WD_width(sb, val) putnbyte(sb + 0x0e, val, 4) #define get_WD_width(sb) getnbyte(sb + 0x0e, 4) #define WD_width 10200 0x00, 0x00, 0x00, 0x00, /* 0x12 *//* Length */ #define set_WD_length(sb, val) putnbyte(sb + 0x12, val, 4) #define get_WD_length(sb) getnbyte(sb + 0x12, 4) #define WD_length 13200 0x00, /* 0x16 *//* Brightness */ #define set_WD_brightness(sb, val) sb[0x16] = val #define get_WD_brightness(sb) sb[0x16] #define WD_brightness 0x80 0x00, /* 0x17 *//* Threshold */ #define set_WD_threshold(sb, val) sb[0x17] = val #define get_WD_threshold(sb) sb[0x17] #define WD_threshold 0x80 0x00, /* 0x18 *//* Contrast */ #define set_WD_contrast(sb, val) sb[0x18] = val #define get_WD_contrast(sb) sb[0x18] 0x05, /* 0x19 *//* Image composition */ #define set_WD_composition(sb, val) sb[0x19] = val #define get_WD_composition(sb) sb[0x19] /* lineart, halftone, greyscale, binary color, dither color, multi-color */ #define WD_comp_LA 0 #define WD_comp_HT 1 #define WD_comp_GS 2 #define WD_comp_BC 3 #define WD_comp_DC 4 #define WD_comp_MC 5 #define WD_comp_G4 10 #define WD_comp_G8 11 0x08, /* 0x1a *//* Bits/Pixel */ #define set_WD_bitsperpixel(sb, val) sb[0x1a] = val #define get_WD_bitsperpixel(sb) sb[0x1a] 0x00, 0x00, /* 0x1b *//* Halftone pattern */ #define set_WD_halftone(sb, val) putnbyte(sb + 0x1b, val, 2) #define get_WD_halftone(sb) getnbyte(sb + 0x1b, 2) 0x00, /* 0x1d *//*************** STUFF ***************/ #define set_WD_rif(sb, val) setbitfield(sb + 0x1d, 1, 7, val) #define get_WD_rif(sb) getbitfield(sb + 0x1d, 1, 7) #define set_WD_pad(sb, val) setbitfield(sb + 0x1d, 7, 0, val) #define get_WD_pad(sb) getbitfield(sb + 0x1d, 7, 0) 0x00, 0x00, /* 0x1e *//* bit ordering */ #define set_WD_bitorder(sb, val) putnbyte(sb + 0x1e, val, 2) #define get_WD_bitorder(sb) getnbyte(sb + 0x1e, 2) 0x00, /* 0x20 *//* compression type */ #define set_WD_compress_type(sb, val) sb[0x20] = val #define get_WD_compress_type(sb) sb[0x20] 0x00, /* 0x21 *//* compression argument */ #define set_WD_compress_arg(sb, val) sb[0x21] = val #define get_WD_compress_arg(sb) sb[0x21] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x22 *//* reserved */ 0x00, /* 0x28 *//* vendor id code */ #define set_WD_vendor_id_code(sb, val) sb[0x28] = val #define get_WD_vendor_id_code(sb) sb[0x28] #define WD_bw 0x00 #define WD_color 0xFF 0x00, /* 0x29 C *//* parm length */ #define set_WD_parm_length(sb, val) sb[0x29] = val #define get_WD_parm_length(sb) sb[0x29] 0x00, /* 0x2a C *//* ADF, source, Color */ #define set_WD_adf(sb, val) setbitfield(sb + 0x2a, 1, 7, val) #define get_WD_adf(sb) getbitfield(sb + 0x2a, 1, 7) #define set_WD_source(sb, val) setbitfield(sb + 0x2a, 1, 6, val) #define get_WD_source(sb) getbitfield(sb + 0x2a, 1, 6) #define set_WD_color(sb, val) setbitfield(sb + 0x2a, 7, 3, val) #define get_WD_color(sb) getbitfield(sb + 0x2a, 7, 3) #define WD_color_green 0 #define WD_color_red 1 #define WD_color_greenx 2 #define WD_color_blue 3 #define WD_color_rgb 4 0x00, /* 0x2b C *//* highlight color */ #define set_WD_highlight_color(sb, val) sb[0x2b] = val #define get_WD_highlight_color(sb) sb[0x2b] 0x00, /* 0x2c C *//* shadow value */ #define set_WD_shadow_value(sb, val) sb[0x2c] = val #define get_WD_shadow_value(sb) sb[0x2c] 0x00, 0x00, /* 0x2d C *//* line width */ #define set_WD_line_width(sb, val) putnbyte(sb + 0x2d, val, 2) #define get_WD_line_width(sb) getnbyte(sb + 0x2d, 2) 0x00, 0x00, /* 0x2f C *//* line count */ #define set_WD_line_count(sb, val) putnbyte(sb + 0x2f, val, 2) #define get_WD_line_count(sb) getnbyte(sb + 0x2f, 2) 0x00, /* 0x31 *//* reserved */ 0x00, /* 0x32 *//* reserved */ 0x00, /* 0x33 *//* reserved */ 0x00, /* 0x34 *//* reserved */ 0x00, /* 0x35 *//* paper size */ #define set_WD_paper_size(sb, val) sb[0x35] = val #define get_WD_paper_size(sb) sb[0x35] 0x00, 0x00, 0x00, 0x00, /* 0x36 BW *//* paper width X */ #define set_WD_paper_width_X(sb, val) putnbyte(sb + 0x36, val, 4) #define get_WD_paper_width_X(sb) getnbyte(sb + 0x36, 4) 0x00, 0x00, 0x00, 0x00, /* 0x3a BW *//* paper length Y */ #define set_WD_paper_length_Y(sb, val) putnbyte(sb+0x3a, val, 4) #define get_WD_paper_length_Y(sb) getnbyte(sb + 0x3a, 4) 0x00, /* 0x3e *//* reserved */ 0x00, /* 0x3f *//* reserved */ /* 0x40 (last) */ }; static scsiblk window_descriptor_blockB = {window_descriptor_blockC, sizeof (window_descriptor_blockC)}; /* ==================================================================== */ #if 0 #define set_WDB_length(wdb,len) (wdb.size = (len)) #define WDB_OFF(b) (b + set_window.size) #define WDB_OFF(b, n) (b + set_window.size + \ window_parameter_data_block.size + \ ( window_descriptor_block.size * (n - 1) ) ) #define set_WDPB_wdbnum(sb,n) set_WPDB_wdblen(sb,window_descriptor_block.size*n) #endif /* ==================================================================== */ static scsiblk __sane_unused__ *lint_catcher[] = {&reserve_unitB, &release_unitB, &inquiryB, &request_senseB, &send_diagnosticB, &test_unit_readyB, &set_windowB, &set_subwindowB, &object_positionB, &media_checkB, &media_parameter_data_blockB, &sendB, &readB, &mode_selectB, &mode_senseB, &scanB, &window_parameter_data_blockB, &window_descriptor_blockB}; #endif /* SP15C_SCSI_H */ sane-backends-1.0.27/backend/mustek_usb_low.c0000664000175000017500000020463112112021330016006 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Mustek. Originally maintained by Tom Wang Copyright (C) 2001 - 2004 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek 1200UB and similar USB flatbed scanners. */ #include #include "../include/sane/sane.h" #include "../include/sane/sanei_usb.h" #include "mustek_usb_low.h" SANE_Status usb_low_init (ma1017 ** chip_address) { SANE_Int i; ma1017 *chip; DBG (7, "usb_low_init: start\n"); if (!chip_address) return SANE_STATUS_INVAL; chip = (ma1017 *) malloc (sizeof (ma1017)); if (!chip) { DBG (3, "usb_low_init: couldn't malloc %ld bytes for chip\n", (long int) sizeof (ma1017)); *chip_address = 0; return SANE_STATUS_NO_MEM; } *chip_address = chip; /* io */ chip->is_rowing = SANE_FALSE; chip->is_opened = SANE_FALSE; chip->fd = -1; /* Construction/Destruction */ chip->is_opened = SANE_FALSE; chip->is_rowing = SANE_FALSE; /* A2 */ chip->append = 0x00; chip->test_sram = 0x00; chip->fix_pattern = 0x00; /* A4 */ chip->select = 0x00; chip->frontend = 0x00; /* A6 */ chip->rgb_sel_pin = 0x02; chip->asic_io_pins = 0x9c; /* A7 */ chip->timing = 0xe8; chip->sram_bank = 0x02; /* A8 */ chip->dummy_msb = 0x00; chip->ccd_width_msb = 0x00; chip->cmt_table_length = 0x00; /* A9 */ chip->cmt_second_pos = 0x00; /* A10 + A8ID5 */ chip->ccd_width = 0x0c80; /* A11 + A8ID6 */ chip->dummy = 0x0020; /* A12 + A13 */ chip->byte_width = 0x09f6; /* A14 + A30W */ chip->loop_count = 0x0db5; /* A15 */ chip->motor_enable = 0x00; chip->motor_movement = 0x60; chip->motor_direction = 0x10; chip->motor_signal = 0x00; chip->motor_home = 0x00; /* A16 */ chip->pixel_depth = 0x00; chip->image_invert = 0x00; chip->optical_600 = 0x00; chip->sample_way = 0x06; /* A17 + A18 + A19 */ chip->red_ref = 0xff; chip->green_ref = 0xff; chip->blue_ref = 0xff; /* A20 + A21 + A22 */ chip->red_pd = 0x00; chip->green_pd = 0x00; chip->blue_pd = 0x00; /* A23 */ chip->a23 = 0x80; /* A24 */ chip->fy1_delay = 0x00; chip->special_ad = 0x00; /* A27 */ chip->sclk = 0x00; chip->sen = 0x00; chip->serial_length = 0x10; /* Use for Rowing */ chip->get_row = NULL; chip->cmt_table_length_word = 0x00000000; chip->cmt_second_pos_word = 0x00000000; chip->row_size = 0x00; chip->soft_resample = 0x01; chip->total_lines = 0x00; chip->lines_left = 0x00; for (i = 0; i < 32; i++) chip->is_transfer_table[i] = SANE_FALSE; chip->sensor = ST_CANON600; chip->motor = MT_1200; chip->total_read_urbs = 0; chip->total_write_urbs = 0; DBG (7, "usb_low_init: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_exit (ma1017 * chip) { DBG (7, "usb_low_exit: chip = %p\n", (void *) chip); if (chip) { if (chip->fd >= 0 && chip->is_opened) usb_low_close (chip); DBG (7, "usb_low_exit: freeing chip\n"); free (chip); } DBG (5, "usb_low_exit: read %d URBs, wrote %d URBs\n", chip->total_read_urbs, chip->total_write_urbs); DBG (7, "usb_low_exit: exit\n"); return SANE_STATUS_GOOD; } /* A0 ~ A1 */ SANE_Status usb_low_set_cmt_table (ma1017 * chip, SANE_Int index, Channel channel, SANE_Bool is_move_motor, SANE_Bool is_transfer) { SANE_Byte pattern = ((SANE_Byte) index) << 4; SANE_Byte reg_no = 0; SANE_Status status; DBG (7, "usb_low_set_cmt_table: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_cmt_table: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_cmt_table: stop rowing first\n"); return SANE_STATUS_INVAL; } if ((unsigned int) index > 31) { DBG (7, "usb_low_set_cmt_table: CMT index (%d) exceed 31", index); return SANE_STATUS_INVAL; } switch (channel) { case CH_RED: pattern |= 0x04; break; case CH_GREEN: pattern |= 0x08; break; case CH_BLUE: pattern |= 0x0c; break; default: break; } if (is_move_motor) pattern |= 0x02; if (is_transfer) pattern |= 0x01; if (index > 15) reg_no++; RIE (usb_low_write_reg (chip, reg_no, pattern)); chip->is_transfer_table[index] = is_transfer; DBG (7, "usb_low_set_cmt_table: exit\n"); return SANE_STATUS_GOOD; } /* A2 */ SANE_Status usb_low_get_a2 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a2: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a2: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a2: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 2, &pattern)); chip->append = pattern & 0x10; chip->test_sram = pattern & 0x20; chip->fix_pattern = pattern & 0x80; if (value) *value = pattern; DBG (7, "usb_low_get_a2: exit, value =%d\n", pattern); return SANE_STATUS_GOOD; } SANE_Status usb_low_start_cmt_table (ma1017 * chip) { SANE_Byte data_field[2]; SANE_Status status; size_t n; DBG (7, "usb_low_start_cmt_table: start\n"); data_field[0] = 0x02 | chip->append | chip->test_sram | chip->fix_pattern; data_field[1] = 2; if (!chip->is_opened) { DBG (3, "usb_low_start_cmt_table: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (7, "usb_low_start_cmt_table: Already Rowing\n"); return SANE_STATUS_INVAL; } data_field[1] |= 0x60; n = 2; status = sanei_usb_write_bulk (chip->fd, data_field, &n); if (status != SANE_STATUS_GOOD || n != 2) { DBG (3, "usb_low_start_cmt_table: can't write, wanted 2 bytes, " "wrote %lu bytes\n", (unsigned long int) n); return SANE_STATUS_IO_ERROR; } chip->total_write_urbs++; chip->is_rowing = SANE_TRUE; DBG (7, "usb_low_start_cmt_table: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_stop_cmt_table (ma1017 * chip) { SANE_Byte data_field[2]; SANE_Byte read_byte; size_t n; SANE_Status status; DBG (7, "usb_low_stop_cmt_table: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_stop_cmt_table: not opened yet\n"); return SANE_STATUS_INVAL; } if (!chip->is_rowing) { DBG (7, "usb_low_stop_cmt_table: Not Rowing yet\n"); return SANE_STATUS_INVAL; } data_field[0] = 0x01 | chip->append | chip->test_sram | chip->fix_pattern; data_field[1] = 2; data_field[1] |= 0x80; n = 2; status = sanei_usb_write_bulk (chip->fd, data_field, &n); if (status != SANE_STATUS_GOOD || n != 2) { DBG (3, "usb_low_stop_cmt_table: couldn't write, wanted 2 bytes, wrote " "%lu bytes\n", (unsigned long int) n); return SANE_STATUS_IO_ERROR; } chip->total_write_urbs++; n = 1; status = sanei_usb_read_bulk (chip->fd, &read_byte, &n); if (status != SANE_STATUS_GOOD || n != 1) { DBG (3, "usb_low_stop_cmt_table: couldn't read, wanted 1 byte, got %lu " "bytes\n", (unsigned long int) n); return SANE_STATUS_IO_ERROR; } chip->total_read_urbs++; chip->is_rowing = SANE_FALSE; DBG (7, "usb_low_stop_cmt_table: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_test_sram_mode (ma1017 * chip, SANE_Bool is_test) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_test_sram_mode: start\n"); data = chip->append | chip->test_sram | chip->fix_pattern; reg_no = 2; if (!chip->is_opened) { DBG (3, "usb_low_set_test_sram_mode: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_test_sram_mode: stop rowing first\n"); return SANE_STATUS_INVAL; } if (is_test) chip->test_sram = 0x20; else chip->test_sram = 0x00; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_test_sram_mode: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_fix_pattern (ma1017 * chip, SANE_Bool is_fix) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_fix_pattern: start\n"); data = chip->append | chip->test_sram | chip->fix_pattern; reg_no = 2; if (!chip->is_opened) { DBG (3, "usb_low_set_fix_pattern: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_fix_pattern: stop rowing first\n"); return SANE_STATUS_INVAL; } if (is_fix) chip->fix_pattern = 0x80; else chip->fix_pattern = 0x00; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_fix_pattern: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_adjust_timing (ma1017 * chip, SANE_Byte data) { SANE_Status status; SANE_Byte reg_no; DBG (7, "usb_low_adjust_timing: start\n"); reg_no = 3; if (!chip->is_opened) { DBG (3, "usb_low_adjust_timing: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_adjust_timing: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_adjust_timing: exit\n"); return SANE_STATUS_GOOD; } /* A4 */ SANE_Status usb_low_get_a4 (ma1017 * chip, SANE_Byte * value) { SANE_Status status; SANE_Byte pattern; DBG (7, "usb_low_get_a4: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a4: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a4: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 4, &pattern)); chip->select = pattern & 0xfe; chip->frontend = pattern & 0x01; if (value) *value = pattern; DBG (7, "usb_low_get_a4: exit, value=%d\n", pattern); return SANE_STATUS_GOOD; } SANE_Status usb_low_select_timing (ma1017 * chip, SANE_Byte data) { SANE_Status status; SANE_Byte reg_no; DBG (7, "usb_low_select_timing: start\n"); reg_no = 4; if (!chip->is_opened) { DBG (3, "usb_low_select_timing: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_select_timing: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->select = data & 0xfe; chip->frontend = data & 0x01; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_select_timing: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_turn_frontend_mode (ma1017 * chip, SANE_Bool is_on) { SANE_Status status; SANE_Byte data, reg_no; DBG (7, "usb_low_turn_frontend_mode: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_turn_frontend_mode: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_turn_frontend_mode: stop rowing first\n"); return SANE_STATUS_INVAL; } if (is_on) chip->frontend = 0x01; else chip->frontend = 0x00; data = chip->select | chip->frontend; reg_no = 4; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_turn_frontend_mode: exit\n"); return SANE_STATUS_GOOD; } /* A6 */ SANE_Status usb_low_get_a6 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a6: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a6: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a6: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 6, &pattern)); chip->asic_io_pins = pattern & 0xdc; chip->rgb_sel_pin = pattern & 0x03; if (value) *value = pattern; DBG (7, "usb_low_get_a6: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_asic_io_pins (ma1017 * chip, SANE_Byte data) { SANE_Status status; SANE_Byte reg_no; DBG (7, "usb_low_set_asic_io_pins: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_asic_io_pins: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_asic_io_pins: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->asic_io_pins = data & 0xdc; data = chip->asic_io_pins | chip->rgb_sel_pin; reg_no = 6; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_asic_io_pins: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_rgb_sel_pins (ma1017 * chip, SANE_Byte data) { SANE_Status status; SANE_Byte reg_no; DBG (7, "usb_low_set_rgb_sel_pins: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_rgb_sel_pins: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_rgb_sel_pins: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->rgb_sel_pin = data & 0x03; data = chip->asic_io_pins | chip->rgb_sel_pin; reg_no = 6; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_rgb_sel_pins: exit\n"); return SANE_STATUS_GOOD; /* was false? */ } /* A7 */ SANE_Status usb_low_get_a7 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a7: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a7: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a7: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 7, &pattern)); if (value) *value = pattern; chip->timing = pattern & 0xfc; chip->sram_bank = pattern & 0x03; DBG (7, "usb_low_get_a7: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_timing (ma1017 * chip, SANE_Byte data) { SANE_Status status; SANE_Byte reg_no; DBG (7, "usb_low_set_timing: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_timing: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_timing: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->timing = data & 0xfc; data = chip->timing | chip->sram_bank; reg_no = 7; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_timing: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_sram_bank (ma1017 * chip, Banksize banksize) { SANE_Status status; SANE_Byte data, reg_no; DBG (7, "usb_low_set_sram_bank: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_sram_bank: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_sram_bank: stop rowing first\n"); return SANE_STATUS_INVAL; } switch (banksize) { case BS_4K: chip->sram_bank = 0x00; break; case BS_8K: chip->sram_bank = 0x01; break; case BS_16K: chip->sram_bank = 0x02; break; default: DBG (3, "usb_low_set_sram_bank: bsBankSize error\n"); return SANE_STATUS_INVAL; break; } data = chip->timing | chip->sram_bank; reg_no = 7; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_sram_bank: exit\n"); return SANE_STATUS_GOOD; } /* A8 */ SANE_Status usb_low_get_a8 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a8: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a8: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a8: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 8, &pattern)); chip->dummy_msb = pattern & 0x40; chip->ccd_width_msb = pattern & 0x20; chip->cmt_table_length = pattern & 0x1f; chip->ccd_width = ((chip->ccd_width / 32) & 0x00ff) * 32 + ((chip->ccd_width_msb == 0) ? 0 : 0x0100 * 32); chip->dummy = ((chip->dummy / 32) & 0x00ff) * 32 + ((chip->dummy_msb == 0) ? 0 : 0x0100 * 32); if (value) *value = pattern; DBG (7, "usb_low_get_a8: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_cmt_table_length (ma1017 * chip, SANE_Byte table_length) { SANE_Status status; SANE_Byte data, reg_no; DBG (7, "usb_low_set_cmt_table_length: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_cmt_table_length: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_cmt_table_length: stop rowing first\n"); return SANE_STATUS_INVAL; } if (table_length > 32) { DBG (3, "usb_low_set_cmt_table_length: length %d exceeds 32\n", (int) table_length); return SANE_STATUS_INVAL; } if (table_length == 0) { DBG (3, "usb_low_set_cmt_table_length: length is 0\n"); return SANE_STATUS_INVAL; } chip->cmt_table_length = table_length - 1; chip->cmt_table_length_word = (SANE_Word) table_length; data = chip->cmt_table_length | chip->ccd_width_msb | chip->dummy_msb; reg_no = 8; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_cmt_table_length: exit\n"); return SANE_STATUS_GOOD; } /* A9 */ SANE_Status usb_low_get_a9 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a9: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a9: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a9: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 9, &pattern)); chip->cmt_second_pos = pattern & 0x1f; if (value) *value = pattern; DBG (7, "usb_low_get_a9: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_cmt_second_position (ma1017 * chip, SANE_Byte position) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_cmt_second_position: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_cmt_second_position: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_cmt_second_position: stop rowing first\n"); return SANE_STATUS_INVAL; } if (position > 31) { DBG (3, "usb_low_set_cmt_second_position: length: %d exceeds 31\n", (int) position); return SANE_STATUS_INVAL; } chip->cmt_second_pos = position; chip->cmt_second_pos_word = (SANE_Word) (position); data = chip->cmt_second_pos; reg_no = 9; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_cmt_second_position: exit\n"); return SANE_STATUS_GOOD; } /* A10 + A8ID5 */ SANE_Status usb_low_get_a10 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a10: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a10: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a10: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 10, &pattern)); chip->ccd_width = ((SANE_Word) (pattern)) * 32 + ((chip->ccd_width_msb == 0) ? 0 : 0x0100 * 32); if (value) *value = pattern; DBG (7, "usb_low_get_a10: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_ccd_width (ma1017 * chip, SANE_Word ccd_width) { SANE_Status status; SANE_Byte data, reg_no; DBG (7, "usb_low_set_ccd_width: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_ccd_width: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_ccd_width: stop rowing first\n"); return SANE_STATUS_INVAL; } if (ccd_width / 32 > 0x01ff) { DBG (3, "usb_low_set_ccd_width: width %d too high\n", (int) ccd_width); return SANE_STATUS_INVAL; } chip->ccd_width = ccd_width; ccd_width /= 32; if (HIBYTE (ccd_width) == 0x01) chip->ccd_width_msb = 0x20; else chip->ccd_width_msb = 0x00; data = chip->cmt_table_length | chip->ccd_width_msb | chip->dummy_msb; reg_no = 8; RIE (usb_low_write_reg (chip, reg_no, data)); data = LOBYTE (ccd_width); reg_no = 10; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_ccd_width: exit\n"); return SANE_STATUS_GOOD; } /* A11 + A8ID6 */ SANE_Status usb_low_get_a11 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a11: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a11: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a11: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 11, &pattern)); chip->dummy = ((SANE_Word) (pattern)) * 32 + ((chip->dummy_msb == 0) ? 0 : 0x0100 * 32); if (value) *value = pattern; DBG (7, "usb_low_get_a11: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_dummy (ma1017 * chip, SANE_Word dummy) { SANE_Status status; SANE_Byte data, reg_no; DBG (7, "usb_low_set_dummy: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_dummy: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_dummy: stop rowing first\n"); return SANE_STATUS_INVAL; } if (dummy / 32 > 0x01ff) { DBG (7, "usb_low_set_dummy: width %d exceeded\n", (int) dummy); return SANE_STATUS_INVAL; } chip->dummy = dummy; dummy /= 32; dummy++; if (HIBYTE (dummy) == 0x01) chip->dummy_msb = 0x40; else chip->dummy_msb = 0x00; data = chip->cmt_table_length | chip->ccd_width_msb | chip->dummy_msb; reg_no = 8; RIE (usb_low_write_reg (chip, reg_no, data)); data = LOBYTE (dummy); reg_no = 11; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_dummy: exit\n"); return SANE_STATUS_GOOD; } /* A12 + A13 */ SANE_Status usb_low_get_a12 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a12: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a12: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a12: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 12, &pattern)); chip->byte_width = (chip->byte_width & 0x3f00) + ((SANE_Word) pattern); chip->soft_resample = (chip->soft_resample == 0) ? 1 : chip->soft_resample; chip->get_row = (chip->soft_resample == 1) ? &usb_low_get_row_direct : &usb_low_get_row_resample; chip->row_size = chip->byte_width / chip->soft_resample; if (value) *value = pattern; DBG (7, "usb_low_get_a12: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_get_a13 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a13: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a13: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a13: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 13, &pattern)); chip->byte_width = (chip->byte_width & 0x00ff) + (((SANE_Word) (pattern & 0x3f)) << 8); chip->soft_resample = (chip->soft_resample == 0) ? 1 : chip->soft_resample; chip->get_row = (chip->soft_resample == 1) ? &usb_low_get_row_direct : &usb_low_get_row_resample; chip->row_size = chip->byte_width / chip->soft_resample; if (value) *value = pattern; DBG (7, "usb_low_get_a13: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_image_byte_width (ma1017 * chip, SANE_Word row_size) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_image_byte_width: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_image_byte_width: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_image_byte_width: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->row_size = row_size; chip->soft_resample = (chip->soft_resample == 0) ? 1 : chip->soft_resample; chip->get_row = (chip->soft_resample == 1) ? &usb_low_get_row_direct : &usb_low_get_row_resample; chip->byte_width = chip->row_size * chip->soft_resample; if (chip->byte_width > 0x3fff) { DBG (3, "usb_low_set_image_byte_width: width %d exceeded\n", (int) chip->byte_width); return SANE_STATUS_INVAL; } data = LOBYTE (chip->byte_width); reg_no = 12; RIE (usb_low_write_reg (chip, reg_no, data)); data = HIBYTE (chip->byte_width); reg_no = 13; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_image_byte_width: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_soft_resample (ma1017 * chip, SANE_Word soft_resample) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_soft_resample: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_soft_resample: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_soft_resample: stop rowing first\n"); return SANE_STATUS_INVAL; } if (soft_resample == 0x00) { DBG (3, "usb_low_set_soft_resample: soft_resample==0\n"); return SANE_STATUS_INVAL; } chip->soft_resample = soft_resample; chip->get_row = (chip->soft_resample == 1) ? &usb_low_get_row_direct : &usb_low_get_row_resample; chip->byte_width = chip->row_size * chip->soft_resample; if (chip->byte_width > 0x3fff) { DBG (3, "usb_low_set_soft_resample: width %d exceeded", (int) chip->byte_width); return SANE_STATUS_INVAL; } data = LOBYTE (chip->byte_width); reg_no = 12; RIE (usb_low_write_reg (chip, reg_no, data)); data = HIBYTE (chip->byte_width); reg_no = 13; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_soft_resample: exit\n"); return SANE_STATUS_GOOD; } /* A14 + A30W */ SANE_Status usb_low_set_cmt_loop_count (ma1017 * chip, SANE_Word loop_count) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_cmt_loop_count: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_cmt_loop_count: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_cmt_loop_count: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->loop_count = loop_count; data = LOBYTE (loop_count); reg_no = 14; RIE (usb_low_write_reg (chip, reg_no, data)); data = HIBYTE (loop_count); reg_no = 30; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_cmt_loop_count: exit\n"); return SANE_STATUS_GOOD; } /* A15 */ SANE_Status usb_low_get_a15 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a15: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a15: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a15: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 15, &pattern)); chip->motor_enable = pattern & 0x80; chip->motor_movement = pattern & 0x68; chip->motor_direction = pattern & 10; chip->motor_signal = pattern & 0x06; chip->motor_home = pattern & 0x01; if (value) *value = pattern; DBG (7, "usb_low_get_a15: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_enable_motor (ma1017 * chip, SANE_Bool is_enable) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_enable_motor: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_enable_motor: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_enable_motor: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->motor_enable = 0x00; if (is_enable) chip->motor_enable |= 0x80; data = chip->motor_enable | chip->motor_movement | chip->motor_direction | chip->motor_signal | chip->motor_home; reg_no = 15; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_enable_motor: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_motor_movement (ma1017 * chip, SANE_Bool is_full_step, SANE_Bool is_double_phase, SANE_Bool is_two_step) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_motor_movement: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_motor_movement: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_motor_movement: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->motor_movement = 0x00; if (is_full_step) chip->motor_movement |= 0x40; if (is_double_phase) chip->motor_movement |= 0x20; if (is_two_step) chip->motor_movement |= 0x08; data = chip->motor_enable | chip->motor_movement | chip->motor_direction | chip->motor_signal | chip->motor_home; reg_no = 15; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_motor_movement: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_motor_direction (ma1017 * chip, SANE_Bool is_backward) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_motor_direction: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_motor_direction: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_motor_direction: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->motor_direction = 0x00; if (is_backward) chip->motor_direction |= 0x10; data = chip->motor_enable | chip->motor_movement | chip->motor_direction | chip->motor_signal | chip->motor_home; reg_no = 15; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_motor_direction: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_motor_signal (ma1017 * chip, SANE_Byte signal) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_motor_signal: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_motor_signal: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_motor_signal: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->motor_signal = signal & 0x06; data = chip->motor_enable | chip->motor_movement | chip->motor_direction | chip->motor_signal | chip->motor_home; reg_no = 15; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_motor_signal: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_move_motor_home (ma1017 * chip, SANE_Bool is_home, SANE_Bool is_backward) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_move_motor_home: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_move_motor_home: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_move_motor_home: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->motor_enable = 0x00; chip->motor_direction = 0x00; chip->motor_home = 0x00; if (is_backward) chip->motor_direction |= 0x10; if (is_home) { chip->motor_enable |= 0x80; chip->motor_home |= 0x01; } data = chip->motor_enable | chip->motor_movement | chip->motor_direction | chip->motor_signal | chip->motor_home; reg_no = 15; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_move_motor_home: exit\n"); return SANE_STATUS_GOOD; } /* A16 */ SANE_Status usb_low_get_a16 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a16: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a16: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a16: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 16, &pattern)); chip->pixel_depth = pattern & 0xe0; chip->image_invert = pattern & 0x10; chip->optical_600 = pattern & 0x08; chip->sample_way = pattern & 0x07; if (value) *value = pattern; DBG (7, "usb_low_get_a16: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_image_dpi (ma1017 * chip, SANE_Bool is_optical600, Sampleway sampleway) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_image_dpi: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_image_dpi: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_image_dpi: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->optical_600 = 0x00; chip->sample_way = 0x00; if (is_optical600) chip->optical_600 |= 0x08; switch (sampleway) { case SW_P1P6: chip->sample_way = 0x01; break; case SW_P2P6: chip->sample_way = 0x02; break; case SW_P3P6: chip->sample_way = 0x03; break; case SW_P4P6: chip->sample_way = 0x04; break; case SW_P5P6: chip->sample_way = 0x05; break; case SW_P6P6: chip->sample_way = 0x06; break; default: DBG (3, "usb_low_set_image_dpi: swsample_way error\n"); return SANE_STATUS_INVAL; break; } data = chip->pixel_depth | chip->image_invert | chip->optical_600 | chip->sample_way; reg_no = 16; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_image_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_pixel_depth (ma1017 * chip, Pixeldepth pixeldepth) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_pixel_depth: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_pixel_depth: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_pixel_depth: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->pixel_depth = 0x00; switch (pixeldepth) { case PD_1BIT: chip->pixel_depth = 0x80; break; case PD_4BIT: chip->pixel_depth = 0xc0; break; case PD_8BIT: chip->pixel_depth = 0x00; break; case PD_12BIT: chip->pixel_depth = 0x20; break; default: DBG (3, "usb_low_set_pixel_depth: pdPixelDepth error\n"); return SANE_STATUS_INVAL; } data = chip->pixel_depth | chip->image_invert | chip->optical_600 | chip->sample_way; reg_no = 16; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_SetPixelDeepth: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_invert_image (ma1017 * chip, SANE_Bool is_invert) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_invert_image: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_invert_image: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_invert_image: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->image_invert = 0x00; if (is_invert) chip->image_invert |= 0x10; data = chip->pixel_depth | chip->image_invert | chip->optical_600 | chip->sample_way; reg_no = 16; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_invert_image: exit\n"); return SANE_STATUS_GOOD; } /* A17 + A18 + A19 */ SANE_Status usb_low_get_a17 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a17: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a17: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a17: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 17, &pattern)); chip->red_ref = pattern; if (value) *value = pattern; DBG (7, "usb_low_get_a17: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_get_a18 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a18: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a18: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a18: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 18, &pattern)); chip->green_ref = pattern; if (value) *value = pattern; DBG (7, "usb_low_get_a18: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_get_a19 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a19: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a19: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a19:stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 19, &pattern)); chip->blue_ref = pattern; if (value) *value = pattern; DBG (7, "usb_low_get_a19: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_red_ref (ma1017 * chip, SANE_Byte red_ref) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_red_ref: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_red_ref: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_red_ref: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->red_ref = red_ref; data = red_ref; reg_no = 17; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_red_ref: stop\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_green_ref (ma1017 * chip, SANE_Byte green_ref) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_green_ref: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_green_ref: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_green_ref: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->green_ref = green_ref; data = green_ref; reg_no = 18; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_green_ref: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_blue_ref (ma1017 * chip, SANE_Byte blue_ref) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_blue_ref: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_blue_ref: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_blue_ref: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->blue_ref = blue_ref; data = blue_ref; reg_no = 19; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_blue_ref: stop\n"); return SANE_STATUS_GOOD; } /* A20 + A21 + A22 */ SANE_Status usb_low_get_a20 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a20: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a20: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a20: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 20, &pattern)); chip->red_pd = pattern; if (value) *value = pattern; DBG (7, "usb_low_get_a20: stop\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_get_a21 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a21: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a21: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a21: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 21, &pattern)); chip->green_pd = pattern; if (value) *value = pattern; DBG (7, "usb_low_get_a21: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_get_a22 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a22: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a22: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a22: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 22, &pattern)); chip->blue_pd = pattern; if (value) *value = pattern; DBG (7, "usb_low_get_a22: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_red_pd (ma1017 * chip, SANE_Byte red_pd) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_red_pd: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_red_pd: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_red_pd: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->red_pd = red_pd; data = chip->red_pd; reg_no = 20; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_red_pd: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_green_pd (ma1017 * chip, SANE_Byte green_pd) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_green_pd: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_green_pd: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_green_pd: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->green_pd = green_pd; data = chip->green_pd; reg_no = 21; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_green_pd: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_blue_pd (ma1017 * chip, SANE_Byte blue_pd) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_blue_pd: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_blue_pd: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_blue_pd: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->blue_pd = blue_pd; data = chip->blue_pd; reg_no = 22; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_blue_pd: exit\n"); return SANE_STATUS_GOOD; } /* A23 */ SANE_Status usb_low_get_a23 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a23: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a23: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a23: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 23, &pattern)); chip->a23 = pattern; if (value) *value = pattern; DBG (7, "usb_low_get_a23: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_turn_peripheral_power (ma1017 * chip, SANE_Bool is_on) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_turn_peripheral_power: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_turn_peripheral_power: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_turn_peripheral_power: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->a23 &= 0x7f; if (is_on) chip->a23 |= 0x80; data = chip->a23; reg_no = 23; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_turn_peripheral_power: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_turn_lamp_power (ma1017 * chip, SANE_Bool is_on) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_turn_lamp_power: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_turn_lamp_power: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_turn_lamp_power: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->a23 &= 0xbf; if (is_on) chip->a23 |= 0x40; data = chip->a23; reg_no = 23; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_turn_lamp_power: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_io_3 (ma1017 * chip, SANE_Bool is_high) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_io_3: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_io_3: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_io_3: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->a23 &= 0xf7; if (is_high) chip->a23 |= 0x08; data = chip->a23; reg_no = 23; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_io_3: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_led_light_all (ma1017 * chip, SANE_Bool is_light_all) { SANE_Byte data, reg_no; SANE_Status status; DBG (7, "usb_low_set_led_light_all: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_led_light_all: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_led_light_all: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->a23 &= 0xfe; if (is_light_all) chip->a23 |= 0x01; data = chip->a23; reg_no = 23; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_led_light_all: exit\n"); return SANE_STATUS_GOOD; } /* A24 */ SANE_Status usb_low_get_a24 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a24: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a24: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a24: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 24, &pattern)); chip->fy1_delay = pattern & 0x01; chip->special_ad = pattern & 0x02; if (value) *value = pattern; DBG (7, "usb_low_get_a24: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_ad_timing (ma1017 * chip, SANE_Byte data) { SANE_Byte reg_no; SANE_Status status; DBG (7, "usb_low_set_ad_timing: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_ad_timing: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_ad_timing: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->fy1_delay = data & 0x01; chip->special_ad = data & 0x02; data = chip->special_ad | chip->fy1_delay; reg_no = 24; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_ad_timing: exit\n"); return SANE_STATUS_GOOD; } /* A25 + A26 */ SANE_Status usb_low_set_serial_byte1 (ma1017 * chip, SANE_Byte data) { SANE_Byte reg_no; SANE_Status status; DBG (7, "usb_low_set_serial_byte1: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_serial_byte1: not opened\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_serial_byte1: stop rowing first\n"); return SANE_STATUS_INVAL; } reg_no = 25; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_serial_byte1: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_serial_byte2 (ma1017 * chip, SANE_Byte data) { SANE_Byte reg_no; SANE_Status status; DBG (7, "usb_low_set_serial_byte2: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_serial_byte2: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_serial_byte2: stop rowing first\n"); return SANE_STATUS_INVAL; } reg_no = 26; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_serial_byte2: exit\n"); return SANE_STATUS_GOOD; } /* A27 */ SANE_Status usb_low_get_a27 (ma1017 * chip, SANE_Byte * value) { SANE_Byte pattern; SANE_Status status; DBG (7, "usb_low_get_a27: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_a27: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_a27: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 27, &pattern)); chip->sclk = pattern & 0x80; chip->sen = pattern & 0x40; chip->serial_length = pattern & 0x1f; if (value) *value = pattern; DBG (7, "usb_low_get_a27: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_set_serial_format (ma1017 * chip, SANE_Byte data) { SANE_Byte reg_no; SANE_Status status; DBG (7, "usb_low_set_serial_format: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_set_serial_format: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_set_serial_format: stop rowing first\n"); return SANE_STATUS_INVAL; } chip->sclk = data & 0x80; chip->sen = data & 0x40; chip->serial_length = data & 0x1f; reg_no = 27; RIE (usb_low_write_reg (chip, reg_no, data)); DBG (7, "usb_low_set_serial_format: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_get_home_sensor (ma1017 * chip) { SANE_Byte data; SANE_Status status; DBG (7, "usb_low_get_home_sensor: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_get_home_sensor: not opened yet\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_get_home_sensor: stop rowing first\n"); return SANE_STATUS_INVAL; } RIE (usb_low_read_reg (chip, 31, &data)); DBG (7, "usb_low_get_home_sensor: exit\n"); if ((data & 0x80) != 0) return SANE_STATUS_GOOD; else return SANE_STATUS_IO_ERROR; } /* Special Mode */ SANE_Status usb_low_start_rowing (ma1017 * chip) { SANE_Word line_of_first = 0; SANE_Word line_of_second = 0; SANE_Int i; SANE_Status status; DBG (7, "usb_low_start_rowing: start\n"); if (chip->loop_count == 0) { DBG (3, "usb_low_start_rowing loop_count hasn't been set yet\n"); return SANE_STATUS_INVAL; } if (chip->cmt_table_length_word == 0) { DBG (3, "usb_low_start_rowing: cmt_table_length_word hasn't been set " "yet\n"); return SANE_STATUS_INVAL; } if (chip->cmt_table_length_word <= chip->cmt_second_pos_word) { DBG (3, "usb_low_start_rowing: cmt_second_pos_word cannot be larger " "than cmt_table_length_word\n"); return SANE_STATUS_INVAL; } for (i = 0; i < (int) chip->cmt_second_pos_word; i++) { if (chip->is_transfer_table[i]) line_of_first++; } for (; i < (int) chip->cmt_table_length_word; i++) { if (chip->is_transfer_table[i]) { line_of_first++; line_of_second++; } } chip->total_lines = ((SANE_Word) (chip->loop_count - 1)) * line_of_second + line_of_first; chip->lines_left = chip->total_lines; RIE (usb_low_start_cmt_table (chip)); DBG (7, "usb_low_start_rowing: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_stop_rowing (ma1017 * chip) { SANE_Status status; DBG (7, "usb_low_stop_rowing: start\n"); RIE (usb_low_stop_cmt_table (chip)); DBG (7, "usb_low_stop_rowing: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_wait_rowing_stop (ma1017 * chip) { SANE_Status status; DBG (7, "usb_low_wait_rowing_stop: start\n"); if (chip->total_lines != 0) { DBG (3, "usb_low_wait_rowing_stop: total_lines must be 0\n"); return SANE_STATUS_INVAL; } RIE (usb_low_wait_rowing (chip)); chip->is_rowing = SANE_FALSE; DBG (7, "usb_low_wait_rowing_stop: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_read_all_registers (ma1017 * chip) { SANE_Status status; DBG (7, "usb_low_read_all_registers: start\n"); RIE (usb_low_get_a2 (chip, 0)); RIE (usb_low_get_a4 (chip, 0)); RIE (usb_low_get_a6 (chip, 0)); RIE (usb_low_get_a7 (chip, 0)); RIE (usb_low_get_a8 (chip, 0)); RIE (usb_low_get_a9 (chip, 0)); RIE (usb_low_get_a10 (chip, 0)); RIE (usb_low_get_a11 (chip, 0)); RIE (usb_low_get_a12 (chip, 0)); RIE (usb_low_get_a13 (chip, 0)); RIE (usb_low_get_a15 (chip, 0)); RIE (usb_low_get_a16 (chip, 0)); RIE (usb_low_get_a17 (chip, 0)); RIE (usb_low_get_a18 (chip, 0)); RIE (usb_low_get_a19 (chip, 0)); RIE (usb_low_get_a20 (chip, 0)); RIE (usb_low_get_a21 (chip, 0)); RIE (usb_low_get_a22 (chip, 0)); RIE (usb_low_get_a23 (chip, 0)); RIE (usb_low_get_a24 (chip, 0)); RIE (usb_low_get_a27 (chip, 0)); return SANE_STATUS_GOOD; DBG (7, "usb_low_read_all_registers: exit\n"); } SANE_Status usb_low_get_row (ma1017 * chip, SANE_Byte * data, SANE_Word * lines_left) { SANE_Status status; DBG (7, "usb_low_get_row: start\n"); RIE ((*chip->get_row) (chip, data, lines_left)); DBG (7, "usb_low_get_row: exit\n"); return SANE_STATUS_GOOD;; } SANE_Status usb_low_get_row_direct (ma1017 * chip, SANE_Byte * data, SANE_Word * lines_left) { SANE_Status status; DBG (7, "usb_low_get_row_direct: start\n"); if (chip->lines_left == 0) { DBG (3, "usb_low_get_row_direct: lines_left == 0\n"); return SANE_STATUS_INVAL; } if (chip->lines_left <= 1) { RIE (usb_low_read_rows (chip, data, chip->byte_width)); RIE (usb_low_wait_rowing (chip)); chip->lines_left = 0x00; chip->is_rowing = SANE_FALSE; *lines_left = 0; } else { RIE (usb_low_read_rows (chip, data, chip->byte_width)); chip->lines_left--; *lines_left = chip->lines_left; } DBG (7, "usb_low_get_row_direct: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_get_row_resample (ma1017 * chip, SANE_Byte * data, SANE_Word * lines_left) { static SANE_Byte resample_buffer[8 * 1024]; SANE_Word *pixel_temp; SANE_Word i; SANE_Word j; SANE_Word k; SANE_Status status; DBG (7, "usb_low_get_row_resample: start\n"); if (chip->lines_left == 0) { DBG (3, "usb_low_get_row_resample: lines_left == 0\n"); return SANE_STATUS_INVAL; } if (chip->lines_left <= 1) { RIE (usb_low_read_rows (chip, resample_buffer, chip->byte_width)); if ((chip->sensor == ST_CANON600) && (chip->pixel_depth == 0x20)) { pixel_temp = (SANE_Word *) malloc (6 * 1024 * sizeof (SANE_Word)); if (!pixel_temp) return SANE_STATUS_NO_MEM; j = 0; for (i = 0; i < chip->byte_width; i += 3) { pixel_temp[j] = (SANE_Word) resample_buffer[i]; pixel_temp[j] |= ((SANE_Word) (resample_buffer[i + 1] & 0xf0)) << 4; j++; pixel_temp[j] = ((SANE_Word) (resample_buffer[i + 1] & 0x0f)) << 8; pixel_temp[j] |= (SANE_Word) resample_buffer[i + 2]; j++; } k = 0; for (i = 0; i < j; i += chip->soft_resample * 2) { data[k] = (SANE_Byte) (pixel_temp[i] & 0x00ff); k++; data[k] = (SANE_Byte) ((pixel_temp[i] & 0x0f00) >> 4); data[k] |= (SANE_Byte) ((pixel_temp[i + 2] & 0x0f00) >> 8); k++; data[k] = (SANE_Byte) (pixel_temp[i + 2] & 0x00ff); k++; } free (pixel_temp); } else /* fixme ? */ { for (i = 0; i < chip->byte_width; i += chip->soft_resample) *(data++) = resample_buffer[i]; } RIE (usb_low_wait_rowing (chip)); chip->lines_left = 0x00; chip->is_rowing = SANE_FALSE; *lines_left = 0; } else { RIE (usb_low_read_rows (chip, resample_buffer, chip->byte_width)); if ((chip->sensor == ST_CANON600) && (chip->pixel_depth == 0x20)) { pixel_temp = (SANE_Word *) malloc (6 * 1024 * sizeof (SANE_Word)); if (!pixel_temp) return SANE_STATUS_NO_MEM; j = 0; for (i = 0; i < chip->byte_width; i += 3) { pixel_temp[j] = (SANE_Word) resample_buffer[i]; pixel_temp[j] |= ((SANE_Word) (resample_buffer[i + 1] & 0xf0)) << 4; j++; pixel_temp[j] = ((SANE_Word) (resample_buffer[i + 1] & 0x0f)) << 8; pixel_temp[j] |= (SANE_Word) resample_buffer[i + 2]; j++; } k = 0; for (i = 0; i < j; i += chip->soft_resample * 2) { data[k] = (SANE_Byte) (pixel_temp[i] & 0x00ff); k++; data[k] = (SANE_Byte) ((pixel_temp[i] & 0x0f00) >> 4); data[k] |= (SANE_Byte) ((pixel_temp[i + 2] & 0x0f00) >> 8); k++; data[k] = (SANE_Byte) (pixel_temp[i + 2] & 0x00ff); k++; } free (pixel_temp); } else /* fixme? */ { for (i = 0; i < chip->byte_width; i += chip->soft_resample) *(data++) = resample_buffer[i]; } chip->lines_left--; *lines_left = chip->lines_left; } DBG (7, "usb_low_get_row_resample: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_wait_rowing (ma1017 * chip) { SANE_Byte read_byte; size_t n; SANE_Status status; DBG (7, "usb_low_wait_rowing: start\n"); if (!chip->is_opened) { DBG (3, "usb_low_wait_rowing: open first\n"); return SANE_STATUS_INVAL; } if (!chip->is_rowing) { DBG (3, "usb_low_wait_rowing: not rowing\n"); return SANE_STATUS_INVAL; } n = 1; status = sanei_usb_read_bulk (chip->fd, (SANE_Byte *) & read_byte, &n); if (status != SANE_STATUS_GOOD || n != 1) { DBG (3, "usb_low_wait_rowing: couldn't read: %s\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } chip->total_read_urbs++; chip->is_rowing = SANE_FALSE; DBG (7, "usb_low_wait_rowing: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_read_rows (ma1017 * chip, SANE_Byte * data, SANE_Word byte_count) { size_t n, bytes_total; SANE_Status status; DBG (7, "usb_low_read_rows: start\n"); if (!(chip->is_opened)) { DBG (3, "usb_low_read_rows: is_opened==SANE_FALSE\n"); return SANE_STATUS_INVAL; } if (!(chip->is_rowing)) { DBG (3, "usb_low_read_rows: is_rowing==SANE_FALSE\n"); return SANE_STATUS_INVAL; } n = MIN (byte_count, chip->max_block_size); bytes_total = 0; while ((SANE_Word) bytes_total < byte_count) { status = sanei_usb_read_bulk (chip->fd, (SANE_Byte *) (data + bytes_total), &n); if (status != SANE_STATUS_GOOD) { DBG (7, "usb_low_read_rows: problems during read: %s -- exiting\n", sane_strstatus (status)); return status; } /* Count the number of URBs. This is a bit tricky, as we are reading bigger chunks here but the scanner can only handle 64 bytes at once. */ chip->total_read_urbs += ((n + 63) / 64); bytes_total += n; if ((SANE_Word) bytes_total != byte_count) { DBG (7, "usb_low_read_rows: wanted %d, got %d " "bytes (%d in total) -- retrying\n", byte_count, (SANE_Word) n, (SANE_Word) bytes_total); } n = MIN ((byte_count - (SANE_Word) bytes_total), chip->max_block_size); } DBG (7, "usb_low_read_rows: exit, read %d bytes\n", (SANE_Word) bytes_total); return SANE_STATUS_GOOD; } SANE_Status usb_low_write_reg (ma1017 * chip, SANE_Byte reg_no, SANE_Byte data) { size_t n; SANE_Status status; SANE_Byte data_field[2]; data_field[0] = data; data_field[1] = reg_no; if (!chip->is_opened) { DBG (3, "usb_low_write_reg: open first\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_write_reg: rowing, stop first\n"); return SANE_STATUS_INVAL; } if (reg_no > 0x20) { DBG (3, "usb_low_write_reg: reg_no out of range\n"); return SANE_STATUS_INVAL; } n = 2; status = sanei_usb_write_bulk (chip->fd, data_field, &n); if (status != SANE_STATUS_GOOD || n != 2) { DBG (3, "usb_low_write_reg: couldn't write, tried to write %d, " "wrote %lu: %s\n", 2, (unsigned long int) n, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } chip->total_write_urbs++; DBG (7, "usb_low_write_reg: reg: 0x%02x, value: 0x%02x\n", reg_no, data); return SANE_STATUS_GOOD; } SANE_Status usb_low_read_reg (ma1017 * chip, SANE_Byte reg_no, SANE_Byte * data) { SANE_Byte data_field[2]; SANE_Byte read_byte; size_t n; SANE_Status status; data_field[0] = 0x00; data_field[1] = reg_no | 0x20; if (!chip->is_opened) { DBG (3, "usb_low_read_reg: open first\n"); return SANE_STATUS_INVAL; } if (chip->is_rowing) { DBG (3, "usb_low_read_reg: rowing, stop first\n"); return SANE_STATUS_INVAL; } if (reg_no > 0x20) { DBG (3, "usb_low_read_reg: reg_no out of range\n"); return SANE_STATUS_INVAL; } n = 2; DBG (5, "usb_low_read_reg: trying to write %lu bytes\n", (unsigned long int) n); status = sanei_usb_write_bulk (chip->fd, data_field, &n); if (status != SANE_STATUS_GOOD || n != 2) { DBG (3, "usb_low_read_reg: couldn't write, tried to write %d, " "wrote %lu: %s\n", 2, (unsigned long int) n, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } chip->total_write_urbs++; n = 1; DBG (5, "usb_low_read_reg: trying to read %lu bytes\n", (unsigned long int) n); status = sanei_usb_read_bulk (chip->fd, (SANE_Byte *) & read_byte, &n); if (status != SANE_STATUS_GOOD || n != 1) { DBG (3, "usb_low_read_reg: couldn't read, tried to read %lu, " "read %lu: %s\n", (unsigned long int) 1, (unsigned long int) n, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } chip->total_read_urbs++; if (data) *data = read_byte; DBG (7, "usb_low_read_reg: Reg: 0x%02x, Value: 0x%02x\n", reg_no, read_byte); return SANE_STATUS_GOOD; } SANE_Status usb_low_identify_scanner (SANE_Int fd, Mustek_Type * scanner_type) { SANE_Status status; SANE_Word devvendor, devproduct; Mustek_Type devtype; DBG (7, "usb_low_identify_scanner: start\n"); status = sanei_usb_get_vendor_product (fd, &devvendor, &devproduct); devtype = MT_UNKNOWN; if (status == SANE_STATUS_GOOD) { if (devvendor == 0x055f) { switch (devproduct) { case 0x0001: devtype = MT_1200CU; break; case 0x0002: devtype = MT_600CU; break; case 0x0003: devtype = MT_1200USB; break; case 0x0006: devtype = MT_1200UB; break; case 0x0008: devtype = MT_1200CU_PLUS; break; case 0x0873: devtype = MT_600USB; break; default: if (scanner_type) *scanner_type = devtype; DBG (3, "usb_low_identify_scanner: unknown product id: " "0x%04x\n", devproduct); return SANE_STATUS_INVAL; break; } } else { if (scanner_type) *scanner_type = devtype; DBG (3, "usb_low_identify_scanner: unknown vendor id: 0x%04d\n", devvendor); return SANE_STATUS_INVAL; } } if (scanner_type) *scanner_type = devtype; DBG (7, "usb_low_identify_scanner: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_low_open (ma1017 * chip, SANE_String_Const devname) { SANE_Status status; Mustek_Type scanner_type; DBG (7, "usb_low_open: start: chip = %p\n", (void *) chip); if (chip->is_rowing) { DBG (3, "usb_low_open: already rowing\n"); return SANE_STATUS_INVAL; } if (chip->is_opened) { DBG (3, "usb_low_open: already opened\n"); return SANE_STATUS_INVAL; } status = sanei_usb_open ((SANE_String_Const) devname, &chip->fd); if (status == SANE_STATUS_GOOD) { DBG (7, "usb_low_open: device %s successfully opened\n", devname); chip->is_opened = SANE_TRUE; /* Try to get vendor and device ids */ DBG (7, "usb_low_open: trying to identify device `%s'\n", devname); status = usb_low_identify_scanner (chip->fd, &scanner_type); if (status != SANE_STATUS_GOOD) { DBG (3, "usb_low_open: device `%s' doesn't look like a supported " "scanner\n", devname); sanei_usb_close (chip->fd); return status; } else { if (scanner_type == MT_UNKNOWN) { DBG (3, "usb_low_open: device `%s' can't be identified\n", devname); } else if (scanner_type != chip->scanner_type) { DBG (3, "usb_low_open: device `%s' is supported but" "it's not the same as at the start\n", devname); return SANE_STATUS_INVAL; } } } else { DBG (1, "usb_low_open: device %s couldn't be opened: %s\n", devname, sane_strstatus (status)); return status; } chip->is_opened = SANE_TRUE; RIE (usb_low_read_all_registers (chip)); DBG (7, "usb_low_open: exit, type is %d\n", scanner_type); return SANE_STATUS_GOOD; } SANE_Status usb_low_close (ma1017 * chip) { DBG (7, "usb_low_close: start, chip=%p\n", (void *) chip); if (!chip->is_opened) { DBG (3, "usb_low_close: already close or never opened\n"); return SANE_STATUS_INVAL; } if (chip->fd >= 0) { SANE_Byte dummy; if (chip->is_rowing) usb_low_stop_rowing (chip); /* Now make sure that both the number of written and read URBs is even. Use some dummy writes/reads. That's to avoid a nasty bug in the MA 1017 chipset that causes timeouts when the number of URBs is odd (toggle bug). */ if ((chip->total_read_urbs % 2) == 1) usb_low_get_a4 (chip, &dummy); if ((chip->total_write_urbs % 2) == 1) usb_low_set_fix_pattern (chip, SANE_FALSE); sanei_usb_close (chip->fd); chip->fd = -1; } chip->is_opened = SANE_FALSE; chip->is_rowing = SANE_FALSE; DBG (7, "usb_low_close: exit\n"); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/test-picture.c0000664000175000017500000005430212112021330015372 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Henning Meier-Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements test picture functions for the test backend. */ #define BUFFER_SIZE (64 * 1024) static SANE_Bool little_endian (void); static SANE_Status init_picture_buffer (Test_Device * test_device, SANE_Byte ** buffer, size_t * buffer_size) { SANE_Word pattern_size = 0, pattern_distance = 0; SANE_Word line_count, b_size; SANE_Word lines = 0; SANE_Word bpl = test_device->bytes_per_line; SANE_Word ppl = test_device->pixels_per_line; SANE_Byte *b; SANE_Bool is_little_endian = little_endian (); if (test_device->val[opt_invert_endianess].w) is_little_endian ^= 1; DBG (2, "(child) init_picture_buffer test_device=%p, buffer=%p, " "buffer_size=%p\n",(void*)test_device,(void*)buffer,(void*)buffer_size); if (strcmp (test_device->val[opt_test_picture].s, "Solid black") == 0 || strcmp (test_device->val[opt_test_picture].s, "Solid white") == 0) { SANE_Byte pattern = 0; b_size = BUFFER_SIZE; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; if (strcmp (test_device->val[opt_test_picture].s, "Solid black") == 0) { DBG (3, "(child) init_picture_buffer: drawing solid black test " "picture %d bytes\n", b_size); if (test_device->params.format == SANE_FRAME_GRAY && test_device->params.depth == 1) pattern = 0xff; else pattern = 0x00; } else { DBG (3, "(child) init_picture_buffer: drawing solid white test " "picture %d bytes\n", b_size); if (test_device->params.format == SANE_FRAME_GRAY && test_device->params.depth == 1) pattern = 0x00; else pattern = 0xff; } memset (b, pattern, b_size); return SANE_STATUS_GOOD; } /* Grid */ if (strcmp (test_device->val[opt_test_picture].s, "Grid") == 0) { double p_size = (10.0 * SANE_UNFIX (test_device->val[opt_resolution].w) / MM_PER_INCH); SANE_Word increment = 1; if (test_device->params.format == SANE_FRAME_RGB) increment *= 3; if (test_device->params.depth == 16) increment *= 2; lines = 2 * p_size + 0.5; b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing grid test picture " "%d bytes, %d bpl, %d ppl, %d lines\n", b_size, bpl, ppl, lines); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = 0; for (x = 0; x < bpl; x += increment) { SANE_Word x1; SANE_Byte color = 0; if (test_device->params.depth == 1) { if (test_device->params.format == SANE_FRAME_GRAY || (test_device->params.format >= SANE_FRAME_RED && test_device->params.format <= SANE_FRAME_BLUE)) { SANE_Byte value = 0; for (x1 = 0; x1 < 8; x1++) { SANE_Word xfull = x * 8 + (7 - x1); if (xfull < ppl) { if ((((SANE_Word) (xfull / p_size)) % 2) ^ !(line_count > (SANE_Word) (p_size + 0.5))) color = 0x0; else color = 0x1; } else color = (rand ()) & 0x01; value |= (color << x1); } b[line_count * bpl + x] = value; } else /* SANE_FRAME_RGB */ { SANE_Byte value = 0; for (x1 = 0; x1 < 8; x1++) { SANE_Word xfull = x * 8 / 3 + (7 - x1); if (xfull < ppl) { if (((SANE_Word) (xfull / p_size) % 2) ^ (line_count > (SANE_Word) (p_size + 0.5))) color = 0x0; else color = 0x1; } else color = (rand ()) & 0x01; value |= (color << x1); } for (x1 = 0; x1 < increment; x1++) b[line_count * bpl + x + x1] = value; } } else /* depth = 8, 16 */ { if (x / increment < ppl) if ((((SANE_Int) (x / increment / p_size)) % 2) ^ (line_count > (SANE_Int) (p_size + 0.5))) color = 0x00; else color = 0xff; else color = (rand ()) & 0xff; for (x1 = 0; x1 < increment; x1++) b[line_count * bpl + x + x1] = color; } } } return SANE_STATUS_GOOD; } /* Color patterns */ if (test_device->params.format == SANE_FRAME_GRAY && test_device->params.depth == 1) { /* 1 bit black/white */ pattern_size = 16; pattern_distance = 0; lines = 2 * (pattern_size + pattern_distance); b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing b/w test picture " "%d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 255, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = 0; if (line_count >= lines / 2) x += (pattern_size + pattern_distance) / 8; while (x < bpl) { SANE_Word width; width = pattern_size / 8; if (x + width >= bpl) width = bpl - x; memset (b + line_count * bpl + x, 0x00, width); x += (pattern_size + pattern_distance) * 2 / 8; } } } else if (test_device->params.format == SANE_FRAME_GRAY && test_device->params.depth == 8) { /* 8 bit gray */ pattern_size = 4; pattern_distance = 1; lines = 2 * (pattern_size + pattern_distance); b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing 8 bit gray test picture " "%d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 0x55, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = pattern_distance; if (line_count % (pattern_size + pattern_distance) < pattern_distance) continue; while (x < bpl) { SANE_Word width; SANE_Byte color; width = pattern_size; if (x + width >= bpl) width = bpl - x; if (line_count > (pattern_size + pattern_distance)) color = 0xff - ((x / (pattern_size + pattern_distance)) & 0xff); else color = (x / (pattern_size + pattern_distance)) & 0xff; memset (b + line_count * bpl + x, color, width); x += (pattern_size + pattern_distance); } } } else if (test_device->params.format == SANE_FRAME_GRAY && test_device->params.depth == 16) { /* 16 bit gray */ pattern_size = 256; pattern_distance = 4; lines = 1 * (pattern_size + pattern_distance); b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing 16 bit gray test picture " "%d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 0x55, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = pattern_distance * 2; if (line_count % (pattern_size + pattern_distance) < pattern_distance) continue; while (x < bpl) { SANE_Word width; SANE_Word x1; SANE_Byte pattern_lo, pattern_hi; width = pattern_size * 2; if (x + width >= bpl) width = bpl - x; pattern_lo = ((line_count - pattern_distance) % (pattern_size + pattern_distance)) & 0xff; for (x1 = 0; x1 < width; x1 += 2) { pattern_hi = (x1 / 2) & 0xff; if (is_little_endian) { b[line_count * bpl + x + x1 + 0] = pattern_lo; b[line_count * bpl + x + x1 + 1] = pattern_hi; } else { b[line_count * bpl + x + x1 + 0] = pattern_hi; b[line_count * bpl + x + x1 + 1] = pattern_lo; } } x += ((pattern_size + pattern_distance) * 2); } } } else if (test_device->params.format == SANE_FRAME_RGB && test_device->params.depth == 1) { /* 1 bit color */ pattern_size = 16; pattern_distance = 0; lines = 2 * (pattern_size + pattern_distance); b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing color lineart test " "picture %d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 0x55, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = 0; SANE_Byte color = 0, color_r = 0, color_g = 0, color_b = 0; if (line_count >= lines / 2) color = 7; while (x < bpl) { SANE_Word width; SANE_Word x2 = 0; width = pattern_size / 8 * 3; if (x + width >= bpl) width = bpl - x; color_b = (color & 1) * 0xff; color_g = ((color >> 1) & 1) * 0xff; color_r = ((color >> 2) & 1) * 0xff; for (x2 = 0; x2 < width; x2 += 3) { b[line_count * bpl + x + x2 + 0] = color_r; b[line_count * bpl + x + x2 + 1] = color_g; b[line_count * bpl + x + x2 + 2] = color_b; } if (line_count < lines / 2) { ++color; if (color >= 8) color = 0; } else { if (color == 0) color = 8; --color; } x += ((pattern_size + pattern_distance) / 8 * 3); } } } else if ((test_device->params.format == SANE_FRAME_RED || test_device->params.format == SANE_FRAME_GREEN || test_device->params.format == SANE_FRAME_BLUE) && test_device->params.depth == 1) { /* 1 bit color three-pass */ pattern_size = 16; pattern_distance = 0; lines = 2 * (pattern_size + pattern_distance); b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing color lineart three-pass " "test picture %d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 0x55, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = 0; SANE_Byte color = 0, color_r = 0, color_g = 0, color_b = 0; if (line_count >= lines / 2) color = 7; while (x < bpl) { SANE_Word width; SANE_Word x2 = 0; width = pattern_size / 8; if (x + width >= bpl) width = bpl - x; color_b = (color & 1) * 0xff; color_g = ((color >> 1) & 1) * 0xff; color_r = ((color >> 2) & 1) * 0xff; for (x2 = 0; x2 < width; x2++) { if (test_device->params.format == SANE_FRAME_RED) b[line_count * bpl + x + x2] = color_r; else if (test_device->params.format == SANE_FRAME_GREEN) b[line_count * bpl + x + x2] = color_g; else b[line_count * bpl + x + x2] = color_b; } if (line_count < lines / 2) { ++color; if (color >= 8) color = 0; } else { if (color == 0) color = 8; --color; } x += (pattern_size + pattern_distance) / 8; } } } else if (test_device->params.format == SANE_FRAME_RGB && test_device->params.depth == 8) { /* 8 bit color */ pattern_size = 4; pattern_distance = 1; lines = 6 * (pattern_size + pattern_distance); b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing 8 bit color test picture " "%d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 0x55, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = pattern_distance * 3; if (line_count % (pattern_size + pattern_distance) < pattern_distance) continue; while (x < bpl) { SANE_Word width; SANE_Byte color = 0, color_r = 0, color_g = 0, color_b = 0; SANE_Word x1; width = pattern_size * 3; if (x + width >= bpl) width = bpl - x; if ((line_count / (pattern_size + pattern_distance)) & 1) color = 0xff - ((x / ((pattern_size + pattern_distance) * 3)) & 0xff); else color = (x / ((pattern_size + pattern_distance) * 3)) & 0xff; if (line_count / (pattern_size + pattern_distance) < 2) { color_r = color; color_g = 0; color_b = 0; } else if (line_count / (pattern_size + pattern_distance) < 4) { color_r = 0; color_g = color; color_b = 0; } else { color_r = 0; color_g = 0; color_b = color; } for (x1 = 0; x1 < width; x1 += 3) { b[line_count * bpl + x + x1 + 0] = color_r; b[line_count * bpl + x + x1 + 1] = color_g; b[line_count * bpl + x + x1 + 2] = color_b; } x += ((pattern_size + pattern_distance) * 3); } } } else if ((test_device->params.format == SANE_FRAME_RED || test_device->params.format == SANE_FRAME_GREEN || test_device->params.format == SANE_FRAME_BLUE) && test_device->params.depth == 8) { /* 8 bit color three-pass */ pattern_size = 4; pattern_distance = 1; lines = 6 * (pattern_size + pattern_distance); b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing 8 bit color three-pass " "test picture %d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 0x55, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = pattern_distance; if (line_count % (pattern_size + pattern_distance) < pattern_distance) continue; while (x < bpl) { SANE_Word width; SANE_Byte color = 0; width = pattern_size; if (x + width >= bpl) width = bpl - x; if ((line_count / (pattern_size + pattern_distance)) & 1) color = 0xff - (x / ((pattern_size + pattern_distance)) & 0xff); else color = (x / (pattern_size + pattern_distance)) & 0xff; if (line_count / (pattern_size + pattern_distance) < 2) { if (test_device->params.format != SANE_FRAME_RED) color = 0x00; } else if (line_count / (pattern_size + pattern_distance) < 4) { if (test_device->params.format != SANE_FRAME_GREEN) color = 0x00; } else { if (test_device->params.format != SANE_FRAME_BLUE) color = 0x00; } memset (b + line_count * bpl + x, color, width); x += (pattern_size + pattern_distance); } } } else if (test_device->params.format == SANE_FRAME_RGB && test_device->params.depth == 16) { /* 16 bit color */ pattern_size = 256; pattern_distance = 4; lines = pattern_size + pattern_distance; b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing 16 bit color test picture " "%d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 0x55, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = pattern_distance * 2 * 3; if (line_count % (pattern_size + pattern_distance) < pattern_distance) continue; while (x < bpl) { SANE_Word width; SANE_Word x1; SANE_Byte color_hi = 0, color_lo = 0; SANE_Byte color_hi_r = 0, color_lo_r = 0; SANE_Byte color_hi_g = 0, color_lo_g = 0; SANE_Byte color_hi_b = 0, color_lo_b = 0; width = pattern_size * 2 * 3; if (x + width >= bpl) width = bpl - x; for (x1 = 0; x1 < width; x1 += 6) { color_lo = ((line_count + pattern_size) % (pattern_size + pattern_distance)) & 0xff; color_hi = (x1 / 6) & 0xff; if (((x / ((pattern_size + pattern_distance) * 6)) % 3) == 0) { color_lo_r = color_lo; color_hi_r = color_hi; color_lo_g = 0; color_hi_g = 0; color_lo_b = 0; color_hi_b = 0; } else if (((x / ((pattern_size + pattern_distance) * 6)) % 3) == 1) { color_lo_r = 0; color_hi_r = 0; color_lo_g = color_lo; color_hi_g = color_hi; color_lo_b = 0; color_hi_b = 0; } else { color_lo_r = 0; color_hi_r = 0; color_lo_g = 0; color_hi_g = 0; color_lo_b = color_lo; color_hi_b = color_hi; } if (is_little_endian) { b[line_count * bpl + x + x1 + 0] = color_lo_r; b[line_count * bpl + x + x1 + 1] = color_hi_r; b[line_count * bpl + x + x1 + 2] = color_lo_g; b[line_count * bpl + x + x1 + 3] = color_hi_g; b[line_count * bpl + x + x1 + 4] = color_lo_b; b[line_count * bpl + x + x1 + 5] = color_hi_b; } else { b[line_count * bpl + x + x1 + 0] = color_hi_r; b[line_count * bpl + x + x1 + 1] = color_lo_r; b[line_count * bpl + x + x1 + 2] = color_hi_g; b[line_count * bpl + x + x1 + 3] = color_lo_g; b[line_count * bpl + x + x1 + 4] = color_hi_b; b[line_count * bpl + x + x1 + 5] = color_lo_b; } } x += ((pattern_size + pattern_distance) * 2 * 3); } } } else if ((test_device->params.format == SANE_FRAME_RED || test_device->params.format == SANE_FRAME_GREEN || test_device->params.format == SANE_FRAME_BLUE) && test_device->params.depth == 16) { /* 16 bit color three-pass */ pattern_size = 256; pattern_distance = 4; lines = pattern_size + pattern_distance; b_size = lines * bpl; if (buffer_size) *buffer_size = b_size; b = malloc (b_size); if (!b) { DBG (1, "(child) init_picture_buffer: couldn't malloc buffer\n"); return SANE_STATUS_NO_MEM; } if (buffer) *buffer = b; DBG (3, "(child) init_picture_buffer: drawing 16 bit color three-pass " "test picture %d bytes, %d bpl, %d lines\n", b_size, bpl, lines); memset (b, 0x55, b_size); for (line_count = 0; line_count < lines; line_count++) { SANE_Word x = pattern_distance * 2; if (line_count % (pattern_size + pattern_distance) < pattern_distance) continue; while (x < bpl) { SANE_Word width; SANE_Word x1; SANE_Byte color_hi = 0, color_lo = 0; width = pattern_size * 2; if (x + width >= bpl) width = bpl - x; for (x1 = 0; x1 < width; x1 += 2) { color_lo = ((line_count + pattern_size) % (pattern_size + pattern_distance)) & 0xff; color_hi = (x1 / 2) & 0xff; if (((x / ((pattern_size + pattern_distance) * 2)) % 3) == 0) { if (test_device->params.format != SANE_FRAME_RED) { color_lo = 0x00; color_hi = 0x00; } } else if (((x / ((pattern_size + pattern_distance) * 2)) % 3) == 1) { if (test_device->params.format != SANE_FRAME_GREEN) { color_lo = 0x00; color_hi = 0x00; } } else { if (test_device->params.format != SANE_FRAME_BLUE) { color_lo = 0x00; color_hi = 0x00; } } if (is_little_endian) { b[line_count * bpl + x + x1 + 0] = color_lo; b[line_count * bpl + x + x1 + 1] = color_hi; } else { b[line_count * bpl + x + x1 + 0] = color_hi; b[line_count * bpl + x + x1 + 1] = color_lo; } } x += ((pattern_size + pattern_distance) * 2); } } } else /* Huh? */ { DBG (1, "(child) init_picture_buffer: unknown mode\n"); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/canon_pp.conf.in0000664000175000017500000000221012112021330015636 00000000000000# Define which port to use if one isn't specified - you should only have # one of these lines! # This is the default port to be used - others will be detected ieee1284 parport0 # Define the location of our pixel weight file, can begin with ~/ if needed. # You can have as many of these as you like - lines with ports that don't exist # will be ignored. # # Parameters are: # calibrate /path/to/calibration-file port-name # # The format of port-name is dependant on your OS version. # # If a file isn't speficied, the default name will be # ~/.sane/canon_pp-calibration-[port-name] calibrate ~/.sane/canon_pp-calibration-pp0 parport0 # calibrate /etc/sane/my_calibration parport1 # Enable the next line if you're having trouble with ECP mode such as I/O # errors. Nibble mode is slower, but more reliable. #force_nibble # Set a default initialisation mode for each port. Valid modes are: # AUTO (attempts to automatically detect by trying both methods) # FB620P (10101010 style.. also works for FB320P) # FB630P (11001100 style.. also works for FB330P, N340P, N640P) init_mode AUTO parport0 # init_mode FB620P parport0 # init_mode FB630P parport0 sane-backends-1.0.27/backend/u12-io.c0000664000175000017500000005055612112021330013765 00000000000000/** @file u12-io.c * @brief The I/O functions to the U12 backend stuff. * * Copyright (c) 2003-2004 Gerhard Jaeger * GeneSys Logic I/O stuff derived from canon630u-common.c which has * been written by Nathan Rutman * * History: * - 0.01 - initial version * - 0.02 - changed u12io_GetFifoLength() behaviour * - added delays to reset function * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /** Format: * cacheLen[0] = ASIC-ID * cacheLen[1] = SCANSTATE ? * cacheLen[2] = REG-STATUS ? * cacheLen[3] = ?? * cacheLen[4] = FIFO-LEN (RED) HiByte LW * cacheLen[5] = FIFO-LEN (RED) LoByte LW * cacheLen[6] = FIFO-LEN (RED) LoByte HW * cacheLen[7] = FIFO-LEN (GREEN) HiByte LW * cacheLen[8] = FIFO-LEN (GREEN) LoByte LW * cacheLen[9] = FIFO-LEN (GREEN) LoByte HW * cacheLen[10] = FIFO-LEN (BLUE) HiByte LW * cacheLen[11] = FIFO-LEN (BLUE) LoByte LW * cacheLen[12] = FIFO-LEN (BLUE) LoByte HW */ static SANE_Byte cacheLen[13]; /** This function is used to detect a cancel condition, * our ESC key is the SIGUSR1 signal. It is sent by the backend when the * cancel button has been pressed * * @param - none * @return the function returns SANE_TRUE if a cancel condition has been * detected, if not, it returns SANE_FALSE */ static SANE_Bool u12io_IsEscPressed( void ) { sigset_t sigs; sigpending( &sigs ); if( sigismember( &sigs, SIGUSR1 )) { DBG( _DBG_INFO, "SIGUSR1 is pending --> Cancel detected\n" ); return SANE_TRUE; } return SANE_FALSE; } /** fall asleep for some micro-seconds... */ static void u12io_udelay( unsigned long usec ) { struct timeval now, deadline; if( usec == 0 ) return; gettimeofday( &deadline, NULL ); deadline.tv_usec += usec; deadline.tv_sec += deadline.tv_usec / 1000000; deadline.tv_usec %= 1000000; do { gettimeofday( &now, NULL ); } while ((now.tv_sec < deadline.tv_sec) || (now.tv_sec == deadline.tv_sec && now.tv_usec < deadline.tv_usec)); } /** Initializes a timer. * @param timer - pointer to the timer to start * @param us - timeout value in micro-seconds */ static void u12io_StartTimer( TimerDef *timer , unsigned long us ) { struct timeval start_time; gettimeofday( &start_time, NULL ); *timer = start_time.tv_sec * 1e6 + start_time.tv_usec + us; } /** Checks if a timer has been expired or not. * @param timer - pointer to the timer to check * @return Function returns SANE_TRUE when the timer has been expired, * otherwise SANE_FALSE */ static SANE_Bool u12io_CheckTimer( TimerDef *timer ) { struct timeval current_time; gettimeofday(¤t_time, NULL); if((current_time.tv_sec * 1e6 + current_time.tv_usec) > *timer ) return SANE_TRUE; return SANE_FALSE; } /* GL640 communication functions for Genesys Logic GL640USB * USB-IEEE1284 parallel port bridge */ /* Assign status and verify a good return code */ #define CHK(A) {if( (status = A) != SANE_STATUS_GOOD ) { \ DBG( _DBG_ERROR, "Failure on line of %s: %d\n", __FILE__, \ __LINE__ ); return A; }} /** Register codes for the bridge. These are NOT the registers for the ASIC * on the other side of the bridge. */ typedef enum { GL640_BULK_SETUP = 0x82, GL640_EPP_ADDR = 0x83, GL640_EPP_DATA_READ = 0x84, GL640_EPP_DATA_WRITE = 0x85, GL640_SPP_STATUS = 0x86, GL640_SPP_CONTROL = 0x87, GL640_SPP_DATA = 0x88, GL640_GPIO_OE = 0x89, GL640_GPIO_READ = 0x8a, GL640_GPIO_WRITE = 0x8b } GL640_Request; /** for setting up bulk transfers */ static SANE_Byte bulk_setup_data[] = { 0, 0x11, 0, 0, 0, 0, 0, 0 }; /** Write to the usb-parallel port bridge. */ static SANE_Status gl640WriteControl(int fd, GL640_Request req, u_char * data, unsigned int size) { SANE_Status status; status = sanei_usb_control_msg( fd, /* rqttype */ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT /*0x40 */ , /* rqt */ (size > 1) ? 0x04 : 0x0C, /* val */ (SANE_Int) req, /* ind */ 0, /* len */ size, /* dat */ data); if( status != SANE_STATUS_GOOD ) { DBG( _DBG_ERROR, "gl640WriteControl error\n"); } return status; } /** Read from the usb-parallel port bridge. */ static SANE_Status gl640ReadControl( int fd, GL640_Request req, u_char *data, unsigned int size ) { SANE_Status status; status = sanei_usb_control_msg( fd, /* rqttype */ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN /*0xc0 */ , /* rqt */ (size > 1) ? 0x04 : 0x0C, /* val */ (SANE_Int) req, /* ind */ 0, /* len */ size, /* dat */ data); if( status != SANE_STATUS_GOOD ) { DBG( _DBG_ERROR, "gl640ReadControl error\n"); } return status; } /** Wrappers to write a single byte to the bridge */ static inline SANE_Status gl640WriteReq( int fd, GL640_Request req, u_char data ) { return gl640WriteControl( fd, req, &data, 1); } /** Wrappers to read a single byte from the bridge */ static inline SANE_Status gl640ReadReq( int fd, GL640_Request req, u_char *data ) { return gl640ReadControl( fd, req, data, 1 ); } /** Write USB bulk data * setup is an apparently scanner-specific sequence: * {(0=read, 1=write), 0x00, 0x00, 0x00, sizelo, sizehi, 0x00, 0x00} * setup[1] = 0x11 --> data to register * setup[1] = 0x01 --> data to scanner memory */ static SANE_Status gl640WriteBulk( int fd, u_char *setup, u_char *data, size_t size ) { SANE_Status status; setup[0] = 1; setup[4] = (size) & 0xFF; setup[5] = (size >> 8) & 0xFF; setup[6] = 0; CHK (gl640WriteControl (fd, GL640_BULK_SETUP, setup, 8)); status = sanei_usb_write_bulk (fd, data, &size); if( status != SANE_STATUS_GOOD ) { DBG( _DBG_ERROR, "gl640WriteBulk error\n"); } return status; } /** Read USB bulk data * setup is an apparently scanner-specific sequence: * {(0=read, 1=write), 0x00, 0x00, 0x00, sizelo, sizehi, 0x00, 0x00} * setup[1] = 0x00 --> data from scanner memory * setup[1] = 0x0c --> data from scanner fifo? */ static SANE_Status gl640ReadBulk( int fd, u_char *setup, u_char *data, size_t size, int mod ) { SANE_Byte *len_info; size_t complete, current, toget; SANE_Status status; setup[0] = 0; setup[4] = (size) & 0xFF; setup[5] = (size >> 8) & 0xFF; setup[6] = mod; CHK (gl640WriteControl (fd, GL640_BULK_SETUP, setup, 8)); len_info = NULL; toget = size; if( mod ) { toget *= mod; len_info = data + toget; toget += 13; } for( complete = 0; complete < toget; ) { current = toget - complete; status = sanei_usb_read_bulk( fd, data, ¤t ); if( status != SANE_STATUS_GOOD ) { DBG( _DBG_ERROR, "gl640ReadBulk error\n"); break; } data += current; complete += current; } if( len_info ) { memcpy( cacheLen, len_info, 13 ); } return status; } /* now the functions to access PP registers */ /** read the contents of the status register */ static SANE_Byte inb_status( int fd ) { u_char data = 0xff; gl640ReadReq( fd, GL640_SPP_STATUS, &data ); return data; } /** write a byte to the SPP data port */ static SANE_Status outb_data( int fd, u_char data ) { return gl640WriteReq( fd, GL640_SPP_DATA, data); } /** write to the parport control register */ static SANE_Status outb_ctrl( int fd, u_char data ) { return gl640WriteReq( fd, GL640_SPP_CONTROL, data); } /************************* ASIC access stuff *********************************/ /** write a register number to the ASIC */ static void u12io_RegisterToScanner( U12_Device *dev, SANE_Byte reg ) { if( dev->mode == _PP_MODE_EPP ) { gl640WriteReq( dev->fd, GL640_EPP_ADDR, reg ); } else { /* write register number to read from to SPP data-port */ outb_data( dev->fd, reg ); /* signal that to the ASIC */ outb_ctrl( dev->fd, _CTRL_SIGNAL_REGWRITE ); _DODELAY(20); outb_ctrl( dev->fd, _CTRL_END_REGWRITE ); } } /** as the name says, we switch to SPP mode */ static void u12io_SwitchToSPPMode( U12_Device *dev ) { dev->mode = _PP_MODE_SPP; outb_ctrl( dev->fd, _CTRL_GENSIGNAL ); } /** as the name says, we switch to SPP mode */ static void u12io_SwitchToEPPMode( U12_Device *dev ) { u12io_RegisterToScanner( dev, REG_EPPENABLE ); dev->mode = _PP_MODE_EPP; } /** read data from SPP status port */ static SANE_Byte u12io_DataFromSPP( U12_Device *dev ) { SANE_Byte data, tmp; /* read low nibble */ tmp = inb_status( dev->fd ); outb_ctrl( dev->fd, (_CTRL_GENSIGNAL + _CTRL_STROBE)); /* read high nibble */ data = inb_status( dev->fd ); data &= 0xf0; /* combine with low nibble */ data |= (tmp >> 4); return data; } /** Read the content of specific ASIC register */ static SANE_Byte u12io_DataFromRegister( U12_Device *dev, SANE_Byte reg ) { SANE_Byte val; if( dev->mode == _PP_MODE_EPP ) { gl640WriteReq( dev->fd, GL640_EPP_ADDR, reg ); gl640ReadReq ( dev->fd, GL640_EPP_DATA_READ, &val ); } else { u12io_RegisterToScanner( dev, reg ); val = u12io_DataFromSPP( dev ); } return val; } /** */ static void u12io_CloseScanPath( U12_Device *dev ) { DBG( _DBG_INFO, "u12io_CloseScanPath()\n" ); /* FIXME: Probaly not needed */ #if 0 u12io_RegisterToScanner( dev, 0xff ); #endif u12io_RegisterToScanner( dev, REG_SWITCHBUS ); dev->mode = _PP_MODE_SPP; } /** try to connect to scanner */ static SANE_Bool u12io_OpenScanPath( U12_Device *dev ) { u_char tmp; DBG( _DBG_INFO, "u12io_OpenScanPath()\n" ); u12io_SwitchToSPPMode( dev ); outb_data( dev->fd, _ID_TO_PRINTER ); _DODELAY(20); outb_data( dev->fd, _ID1ST ); _DODELAY(5); outb_data( dev->fd, _ID2ND ); _DODELAY(5); outb_data( dev->fd, _ID3RD ); _DODELAY(5); outb_data( dev->fd, _ID4TH ); _DODELAY(5); tmp = u12io_DataFromRegister( dev, REG_ASICID ); if( ASIC_ID == tmp ) { u12io_SwitchToEPPMode( dev ); return SANE_TRUE; } DBG( _DBG_ERROR, "u12io_OpenScanPath() failed!\n" ); return SANE_FALSE; } /** Write data to asic (SPP mode only) */ static void u12io_DataToScanner( U12_Device *dev , SANE_Byte bValue ) { if( dev->mode != _PP_MODE_SPP ) { DBG( _DBG_ERROR, "u12io_DataToScanner() in wrong mode!\n" ); return; } /* output data */ outb_data( dev->fd, bValue ); /* notify asic there is data */ outb_ctrl( dev->fd, _CTRL_SIGNAL_DATAWRITE ); /* end write cycle */ outb_ctrl( dev->fd, _CTRL_END_DATAWRITE ); } /** Write data to specific ASIC's register */ static SANE_Status u12io_DataToRegister( U12_Device *dev, SANE_Byte reg, SANE_Byte data ) { SANE_Status status; SANE_Byte buf[2]; if( dev->mode == _PP_MODE_EPP ) { buf[0] = reg; buf[1] = data; bulk_setup_data[1] = 0x11; CHK( gl640WriteBulk ( dev->fd, bulk_setup_data, buf, 2 )); } else { u12io_RegisterToScanner( dev, reg ); u12io_DataToScanner( dev, data ); } return SANE_STATUS_GOOD; } /** Write data-buffer to specific ASIC's register * The format in the buffer is * reg(0),val(0),reg(1),val(1),..., reg(len-1),val(len-1) */ static SANE_Status u12io_DataToRegs( U12_Device *dev, SANE_Byte *buf, int len ) { SANE_Status status; if( dev->mode != _PP_MODE_EPP ) { DBG( _DBG_ERROR, "u12io_DataToRegs() in wrong mode!\n" ); return SANE_STATUS_IO_ERROR; } bulk_setup_data[1] = 0x11; CHK( gl640WriteBulk ( dev->fd, bulk_setup_data, buf, len*2 )); return SANE_STATUS_GOOD; } /** write data to the DAC */ static void u12io_DataRegisterToDAC( U12_Device *dev, SANE_Byte reg, SANE_Byte val ) { SANE_Byte buf[6]; buf[0] = REG_ADCADDR; buf[1] = reg; buf[2] = REG_ADCDATA; buf[3] = val; buf[4] = REG_ADCSERIALOUT; buf[5] = val; u12io_DataToRegs( dev, buf, 3 ); } /** write data block to scanner */ static SANE_Status u12io_MoveDataToScanner( U12_Device *dev, SANE_Byte *buf, int len ) { SANE_Status status; /* u12io_RegisterToScanner( dev, REG_INITDATAFIFO ); */ u12io_RegisterToScanner( dev, REG_WRITEDATAMODE ); bulk_setup_data[1] = 0x01; CHK( gl640WriteBulk( dev->fd, bulk_setup_data, buf, len )); bulk_setup_data[1] = 0x11; return SANE_STATUS_GOOD; } static SANE_Status u12io_ReadData( U12_Device *dev, SANE_Byte *buf, int len ) { SANE_Status status; u12io_DataToRegister( dev, REG_MODECONTROL, dev->regs.RD_ModeControl ); /* u12io_RegisterToScanner( dev, REG_INITDATAFIFO ); */ u12io_RegisterToScanner( dev, REG_READDATAMODE ); bulk_setup_data[1] = 0x00; CHK (gl640ReadBulk( dev->fd, bulk_setup_data, buf, len, 0 )); bulk_setup_data[1] = 0x11; return SANE_STATUS_GOOD; } /** perform a SW reset of ASIC P98003 */ static void u12io_SoftwareReset( U12_Device *dev ) { DBG( _DBG_INFO, "Device reset (%i)!!!\n", dev->fd ); u12io_DataToRegister( dev, REG_TESTMODE, _SW_TESTMODE ); outb_data( dev->fd, _ID_TO_PRINTER ); _DODELAY(20); outb_data( dev->fd, _RESET1ST ); _DODELAY(5); outb_data( dev->fd, _RESET2ND ); _DODELAY(5); outb_data( dev->fd, _RESET3RD ); _DODELAY(5); outb_data( dev->fd, _RESET4TH ); _DODELAY(250); } /** */ static SANE_Bool u12io_IsConnected( U12_Device *dev ) { int c, mode; SANE_Byte tmp, rb[6]; DBG( _DBG_INFO, "u12io_IsConnected()\n" ); tmp = inb_status( dev->fd ); DBG( _DBG_INFO, "* tmp1 = 0x%02x\n", tmp ); gl640WriteReq( dev->fd, GL640_EPP_ADDR, REG_ASICID ); gl640ReadReq ( dev->fd, GL640_EPP_DATA_READ, &tmp ); DBG( _DBG_INFO, "* REG_ASICID = 0x%02x\n", tmp ); if( tmp != ASIC_ID ) { DBG( _DBG_INFO, "* Scanner is NOT connected!\n" ); tmp = inb_status( dev->fd ); DBG( _DBG_INFO, "* tmp2 = 0x%02x\n", tmp ); gl640WriteReq( dev->fd, GL640_EPP_ADDR, REG_ASICID ); gl640ReadReq ( dev->fd, GL640_EPP_DATA_READ, &tmp ); DBG( _DBG_INFO, "* REG_ASICID = 0x%02x\n", tmp ); if( tmp == 0x02 ) { mode = dev->mode; dev->mode = _PP_MODE_EPP; u12io_DataToRegister( dev, REG_ADCADDR, 0x01 ); u12io_DataToRegister( dev, REG_ADCDATA, 0x00 ); u12io_DataToRegister( dev, REG_ADCSERIALOUT, 0x00 ); c = 0; _SET_REG( rb, c, REG_MODECONTROL, 0x19 ); _SET_REG( rb, c, REG_STEPCONTROL, 0xff ); _SET_REG( rb, c, REG_MOTOR0CONTROL, 0 ); u12io_DataToRegs( dev, rb, c ); dev->mode = mode ; } return SANE_FALSE; } u12io_SwitchToEPPMode( dev ); DBG( _DBG_INFO, "* Scanner is connected!\n" ); return SANE_TRUE; } /** */ static SANE_Byte u12io_GetExtendedStatus( U12_Device *dev ) { SANE_Byte b; b = u12io_DataFromRegister( dev, REG_STATUS2 ); if( b == 0xff ) return 0; return b; } /** */ static SANE_Status u12io_ReadMonoData( U12_Device *dev, SANE_Byte *buf, u_long len ) { SANE_Status status; bulk_setup_data[1] = 0x0c; bulk_setup_data[2] = ((dev->regs.RD_ModeControl >> 3) + 1); CHK (gl640ReadBulk( dev->fd, bulk_setup_data, buf, len, 1 )); bulk_setup_data[1] = 0x11; bulk_setup_data[2] = 0; return SANE_STATUS_GOOD; } /** */ static SANE_Status u12io_ReadColorData( U12_Device *dev, SANE_Byte *buf, u_long len ) { SANE_Status status; bulk_setup_data[1] = 0x0c; CHK (gl640ReadBulk( dev->fd, bulk_setup_data, buf, len, 3 )); bulk_setup_data[1] = 0x11; return SANE_STATUS_GOOD; } /** read the recent state count */ static SANE_Byte u12io_GetScanState( U12_Device *dev ) { if( cacheLen[0] == 0x83 ) { DBG( _DBG_READ, "u12io_GetScanState(cached) = 0x%02x\n", cacheLen[1] ); return cacheLen[1]; } return u12io_DataFromRegister( dev, REG_GETSCANSTATE ); } /** download a scanstate-table */ static SANE_Status u12io_DownloadScanStates( U12_Device *dev ) { SANE_Status status; TimerDef timer; u12io_RegisterToScanner( dev, REG_SCANSTATECONTROL ); bulk_setup_data[1] = 0x01; CHK( gl640WriteBulk( dev->fd, bulk_setup_data, dev->scanStates, _SCANSTATE_BYTES )); bulk_setup_data[1] = 0x11; /* FIXME: refreshState probably always FALSE */ if( dev->scan.refreshState ) { u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); u12io_StartTimer( &timer, (_SECOND/2)); do { if (!( u12io_GetScanState( dev ) & _SCANSTATE_STOP)) break; } while( !u12io_CheckTimer(&timer)); } return SANE_STATUS_GOOD; } /** - initializes the scan states * - sets all necessary registers * FIXME: first copy to buffer, then use u12io_DataToRegs() */ static void u12io_PutOnAllRegisters( U12_Device *dev ) { SANE_Byte *val, reg; SANE_Byte *rb, buf[100]; int c; /* setup scan states */ u12io_DownloadScanStates( dev ); c = 0; rb = buf; *(rb++) = REG_MODECONTROL; *(rb++) = dev->regs.RD_ModeControl; c++; *(rb++) = REG_STEPCONTROL; *(rb++) = dev->regs.RD_StepControl; c++; *(rb++) = REG_MOTOR0CONTROL; *(rb++) = dev->regs.RD_Motor0Control; c++; *(rb++) = REG_LINECONTROL; *(rb++) = dev->regs.RD_LineControl; c++; *(rb++) = REG_XSTEPTIME; *(rb++) = dev->regs.RD_XStepTime; c++; *(rb++) = REG_MODELCONTROL; *(rb++) = dev->regs.RD_ModelControl; c++; /* the 1st register to write */ val = (SANE_Byte*)&dev->regs.RD_Dpi; /* 0x21 - 0x28 */ for( reg = REG_DPILO; reg <= REG_THRESHOLDHI; reg++, val++ ) { *(rb++) = reg; *(rb++) = *val; c++; } u12io_DataToRegs( dev, buf, c ); u12io_RegisterToScanner( dev, REG_INITDATAFIFO ); u12io_DataToRegister( dev, REG_MODECONTROL, _ModeScan ); } /** */ static void u12io_ResetFifoLen( void ) { memset( cacheLen, 0, 13 ); } /** */ static u_long u12io_GetFifoLength( U12_Device *dev ) { SANE_Status status; size_t toget; SANE_Byte data[64]; u_long len, len_r, len_g, len_b; if( cacheLen[0] == 0x83 ) { DBG( _DBG_READ, "Using cached FIFO len\n" ); memcpy( data, cacheLen, 13 ); u12io_ResetFifoLen(); } else { memset( bulk_setup_data, 0, 8 ); bulk_setup_data[1] = 0x0c; CHK (gl640WriteControl(dev->fd, GL640_BULK_SETUP, bulk_setup_data, 8)); toget = 13; status = sanei_usb_read_bulk( dev->fd, data, &toget ); if( status != SANE_STATUS_GOOD ) { DBG( _DBG_ERROR, "ReadBulk error\n"); return SANE_FALSE; } bulk_setup_data[1] = 0x11; memcpy( cacheLen, data, 13 ); } len_r = (u_long)data[5] * 256 + (u_long)data[4]; len_g = (u_long)data[8] * 256 + (u_long)data[7]; len_b = (u_long)data[11] * 256 + (u_long)data[10]; if( dev->DataInf.wPhyDataType < COLOR_TRUE24 ) { len = len_g; } else { len = len_r; if( len_g < len ) len = len_g; if( len_b < len ) len = len_b; } DBG( _DBG_READ, "FIFO-LEN: %lu %lu %lu = %lu\n", len_r, len_g, len_b, len ); return len; } /** */ static SANE_Bool u12io_ReadOneShadingLine( U12_Device *dev, SANE_Byte *buf, u_long len ) { TimerDef timer; SANE_Status status; DBG( _DBG_READ, "u12io_ReadOneShadingLine()\n" ); u12io_StartTimer( &timer, _SECOND ); dev->scan.bFifoSelect = REG_GFIFOOFFSET; do { u12io_ResetFifoLen(); if( u12io_GetFifoLength( dev ) >= dev->regs.RD_Pixels ) { status = u12io_ReadColorData( dev, buf, len ); if( status != SANE_STATUS_GOOD ) { DBG( _DBG_ERROR, "ReadColorData error\n"); return SANE_FALSE; } DBG( _DBG_READ, "* done\n" ); return SANE_TRUE; } } while( !u12io_CheckTimer( &timer )); DBG( _DBG_ERROR, "u12io_ReadOneShadingLine() failed!\n" ); return SANE_FALSE; } /* END U12-IO.C .............................................................*/ sane-backends-1.0.27/backend/hp4200_lm9830.c0000664000175000017500000001307212112021330014672 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Adrian Perez Jorge This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a backend for the HP4200C flatbed scanner */ #include "hp4200_lm9830.h" static SANE_Status lm9830_read_register (int fd, unsigned char reg, unsigned char *data) { SANE_Status retval; if (!data) return -SANE_STATUS_INVAL; retval = sanei_pv8630_write_byte (fd, PV8630_REPPADDRESS, reg); if (retval != SANE_STATUS_GOOD) return retval; return sanei_pv8630_read_byte (fd, PV8630_RDATA, data); } static SANE_Status lm9830_write_register (int fd, unsigned char reg, unsigned char value) { SANE_Status retval; retval = sanei_pv8630_write_byte (fd, PV8630_REPPADDRESS, reg); if (retval != SANE_STATUS_GOOD) return retval; return sanei_pv8630_write_byte (fd, PV8630_RDATA, value); } #ifdef DEBUG static int lm9830_dump_registers (int fd) { int i; unsigned char value = 0; for (i = 0; i < 0x80; i++) { lm9830_read_register (fd, i, &value); printf ("%.2x:0x%.2x", i, value); if ((i + 1) % 8) printf (", "); else printf ("\n"); } puts (""); return 0; } #endif #if 0 static int pv8630_reset_buttons (int fd) { lm9830_write_register (fd, 0x59, 0x10); lm9830_write_register (fd, 0x59, 0x90); return 0; } #endif #if 0 static int lm9830_lamp_off (int fd) { lm9830_write_register (fd, 0x07, 0x00); lm9830_write_register (fd, 0x2c, 0x00); lm9830_write_register (fd, 0x2d, 0x01); lm9830_write_register (fd, 0x2e, 0x3f); lm9830_write_register (fd, 0x2f, 0xff); return 0; } static int lm9830_lamp_on (int fd) { lm9830_write_register (fd, 0x07, 0x00); lm9830_write_register (fd, 0x2c, 0x3f); lm9830_write_register (fd, 0x2d, 0xff); lm9830_write_register (fd, 0x2e, 0x00); lm9830_write_register (fd, 0x2f, 0x01); return 0; } #endif #if 0 /* * This function prints what button was pressed (the time before this * code was executed). */ static int hp4200c_what_button (int fd) { unsigned char button; pv8630_read_buttons (fd, &button); if (button & 0x08) puts ("Scan"); if (button & 0x10) puts ("Copy"); if (button & 0x20) puts ("E-mail"); if ((button & 0x38) == 0) puts ("None"); pv8630_reset_buttons (fd); return 0; } #endif static int lm9830_ini_scanner (int fd, unsigned char *regs) { #ifdef unused unsigned char inittable[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1A, 0x00, 0x0A, 0x60, 0x2F, 0x13, 0x06, 0x17, 0x01, 0x03, 0x03, 0x05, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x21, 0x00, 0x40, 0x15, 0x18, 0x00, 0x40, 0x02, 0x98, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x25, 0x25, 0x24, 0x28, 0x24, 0x28, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1D, 0x00, 0x13, 0x05, 0x48, 0x01, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x02, 0x00, 0x15, 0x00, 0x45, 0x00, 0x10, 0x08, 0x17, 0x2B, 0x90, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00 }; #endif unsigned char daisy[] = { 0x99, 0x66, 0xcc, 0x33 }; unsigned char *regdata; unsigned int i; sanei_pv8630_write_byte (fd, PV8630_RMODE, 0x02); for (i = 0; i < sizeof (daisy); i++) { sanei_pv8630_write_byte (fd, PV8630_RDATA, daisy[i]); } sanei_pv8630_write_byte (fd, PV8630_RMODE, 0x16); lm9830_write_register (fd, 0x42, 0x06); if (!regs) return 0; /* regdata = inittable; */ else regdata = regs; for (i = 8; i < 0x60; i++) { lm9830_write_register (fd, i, regdata[i]); } for (i = 0x60; i < 0x70; i++) { lm9830_write_register (fd, i, 0); } lm9830_write_register (fd, 0x70, 0x70); for (i = 0x71; i < 0x80; i++) { lm9830_write_register (fd, i, 0); } return 0; } static int lm9830_reset (int fd) { lm9830_write_register (fd, 0x07, 0x08); usleep (100); lm9830_write_register (fd, 0x07, 0x00); usleep (100); return 0; } sane-backends-1.0.27/backend/kodakaio.c0000664000175000017500000033474313106201017014544 00000000000000/* * kodakaio.c - SANE library for Kodak ESP Aio scanners. * * Copyright (C) 2011-2017 Paul Newall * * Based on the Magicolor sane backend: * Based on the epson2 sane backend: * Based on Kazuhiro Sasayama previous * work on epson.[ch] file from the SANE package. * Please see those files for additional copyrights. * Author: Paul Newall * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. * Modified 30/12/14 to fix bug where network connection was broken after 30s of idle time. * The connection is now made in sane_start and ended in sane_cancel. * 01/01/13 Now with adf, the scan can be padded to make up the full page length, * or the page can terminate at the end of the paper. This is a selectable option. * 25/11/12 Using avahi now for net autodiscovery. Use configure option --enable-avahi * 1/5/17 patched to use local pointer for avahi callback */ /* Packages to add to a clean ubuntu install libavahi-common-dev libusb-dev libsnmp-dev convenient lines to paste export SANE_DEBUG_KODAKAIO=20 for ubuntu prior to 12.10 ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-avahi --without-api-spec BACKENDS="kodakaio test" for ubuntu 12.10 ./configure --prefix=/usr --libdir=/usr/lib/i386-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --without-api-spec BACKENDS="kodakaio test" for ubuntu 14.10 up to at least 17.04 ./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --without-api-spec BACKENDS="kodakaio test" If you want to use the test backend, for example with sane-troubleshoot, you should enable it in /etc/sane.d/dll.conf */ /* SANE-FLOW-DIAGRAM Kodakaio commands in [] brackets - sane_init() : initialize backend, attach scanners(devicename,0) . - sane_get_devices() : query list of scanner-devices . - sane_open() : open a particular scanner-device and attach_scanner(devicename,&dev) . . - sane_set_io_mode : set blocking-mode . . - sane_get_select_fd : get scanner-fd . . - sane_get_option_descriptor() : get option informations . . - sane_control_option() : change option values . . . . - sane_start() : start image aquisition [V,L,F,S,C,D,O,Z] first time or after cancel. [(F),E,G] every time . . - sane_get_parameters() : returns actual scan-parameters . . - sane_read() : read image-data (from pipe) . . - sane_cancel() : cancel operation, kill reader_process [(F), U] . - sane_close() : close opened scanner-device, do_cancel, free buffer and handle - sane_exit() : terminate use of backend, free devicename and device-struture */ /* FUNCTION-TREE sane_init sane_open device_detect k_dev_init open_scanner close_scanner sane_get_devices init_options (open_scanner - moved to sane_start 27/12/14 ) sane_control_option getvalue setvalue search_string_list change_source activateOption deactivateOption sane_start open_scanner k_init_parametersta k_lock_scanner k_hello k_set_scanning_parameters print_params k_start_scan cmd_start_scan print_status k_send kodakaio_txrxack sane_get_parameters print_params sane_read k_read cmd_read_data (reads one block) k_recv cmp_array sane_cancel cmd_cancel_scan close_scanner sane_close (close_scanner - moved to sane_cancel 27/12/14) sane_exit free_devices k_recv kodakaio_net_read dump_hex_buffer_dense k_send sanei_kodakaio_net_write_raw dump_hex_buffer_dense open_scanner sanei_kodakaio_net_open close_scanner k_scan_finish cmd_cancel_scan sanei_kodakaio_net_close or sanei_usb_close detect_usb kodakaio_getNumberOfUSBProductIds attach_one_config - (Passed to sanei_configure_attach) kodakaio_getNumberOfUSBProductIds kodak_network_discovery client_callback browse_callback resolve_callback ProcessAvahiDevice attach_one_net attach_one_net attach device_detect attach_one_usb - (passed to sanei_usb_find_devices) attach device_detect k_lock_scanner kodakaio_txrx k_send k_recv kodakaio_txrxack k_send k_recv cmd_set_color_curve kodakaio_expect_ack k_recv cmd_cancel_scan kodakaio_txrxack cmd_set_scanning_parameters kodakaio_txrxack device_detect k_dev_init */ #define KODAKAIO_VERSION 02 #define KODAKAIO_REVISION 7 #define KODAKAIO_BUILD 3 /* for usb (but also used for net though it's not required). */ #define MAX_BLOCK_SIZE 32768 #define SCANNER_READ_TIMEOUT 15 /* POLL_ITN_MS sets the individual poll timeout for network discovery */ #define POLL_ITN_MS 20 /* debugging levels: In terminal use: export SANE_DEBUG_KODAKAIO=40 to set the level to 40 or whatever level you want. Then you can scan with scanimage or simple-scan from terminal and see debug info use these defines to promote certain functions that you are interested in define low values to make detail of a section appear when DBG level is low define a high value eg 99 to get normal behaviour. */ #define DBG_READ 99 #define DBG_AUTO 99 /* for autodiscovery */ /* normal levels. This system is a plan rather than a reality * * 127 recv buffer * 125 send buffer * 35 fine-grained status and progress * 30 sane_read * 25 setvalue, getvalue, control_option * 20 low-level (I/O) functions * 15 mid-level functions * 10 high-level functions * 7 open/close/attach * 6 print_params * 5 basic functions * 3 status info and progress * 2 sane api * 1 errors & warnings */ #include "sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #if WITH_AVAHI /* used for auto detecting network printers */ #include #include #include #include #include #include #endif #include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_tcp.h" #include "../include/sane/sanei_udp.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" #include "kodakaio.h" /* vendor and product ids that are allowed */ #define SANE_KODAKAIO_VENDOR_ID (0x040a) #define min(x,y) (((x)<(y))?(x):(y)) /* I think these timeouts (ms) are defaults, overridden by any timeouts in the kodakaio.conf file */ static int K_SNMP_Timeout = 3000; /* used for any auto detection method */ static int K_Scan_Data_Timeout = 10000; static int K_Request_Timeout = 5000; /* static int bitposn=0; was used to pack bits into bytes in lineart mode */ /* This file is used to store directly the raster returned by the scanner for debugging If RawScanPath has no length it will not be created */ FILE *RawScan = NULL; /* example: char RawScanPath[] = "TestRawScan.pgm"; */ char RawScanPath[] = ""; /* empty path means no raw scan file is made */ /* * Devices supported by this backend */ /* kodak command strings */ static unsigned char KodakEsp_V[] = {0x1b,'S','V',0,0,0,0,0}; /* version?? */ static unsigned char KodakEsp_v[] = {0x1b,'s','v',0,0,0,0,0}; /* reply to version?? */ static unsigned char KodakEsp_Lock[] = {0x1b,'S','L',0,0,0,0,0}; /* Locks scanner */ static unsigned char KodakEsp_UnLock[] = {0x1b,'S','U',0,0,0,0,0}; /* Unlocks scanner */ static unsigned char KodakEsp_Ack[] = {0x1b,'S','S',0,0,0,0,0}; /* Acknowledge for all commands */ /* the bytes after esc S S 0 may indicate status: S S 0 1 = docs in adf */ static unsigned char KodakEsp_F[] = {0x1b,'S','F',0,0,0,0,0}; /* Purpose not known? colour balance?*/ static unsigned char KodakEsp_Comp[] = {0x1b,'S','C',3,8,3,0,0}; /* 3,8,3,1,0 does compression. */ /* The compression method is unknown */ /* static unsigned char KodakEsp_E[] = {0x1b,'S','E',1,0,0,0,0}; NET Purpose not known */ /* the extra 1 below could be despeckle option? maybe only for Hero 9.1 but no errors with ESP5250 */ static unsigned char KodakEsp_E[] = {0x1b,'S','E',1,1,0,0,0}; static unsigned char KodakEsp_Go[] = {0x1b,'S','G',0,0,0,0,0}; /* Starts the scan */ /* Other commands are: D (resolution), O (top left), Z (bottom right), R, G, B (curves) */ /* What is the relationship between these and the ranges in cap? */ static SANE_Int kodakaio_resolution_list[] = {75, 150, 300, 600, 1200}; static SANE_Int kodakaio_depth_list[] = {1,8}; /* The first value is the number of following entries */ /* strings to try and match the model ';' separator static unsigned char SupportedMatchString[] = "KODAK ESP;KODAK HERO;KODAK OFFICE HERO;ADVENT WiFi AIO;"; */ static struct KodakaioCap kodakaio_cap[] = { /* usbid,commandtype, modelname, USBoutEP, USBinEP, opticalres, {dpi range}, pointer to res list, res list size max depth, pointer to depth list, flatbed x range, flatbed y range, adf present, adf duplex, adf x range, adf y range (y range should be set a little shorter than the paper being scanned) The following are not used but may be in future commandtype, max depth, pointer to depth list */ /* list of cap data the first scanner is the default */ /* KODAK AIO DEFAULT, */ { 0x9999, "esp", "KODAK AIO DEFAULT", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(100), 0}, {0, SANE_FIX(100), 0} /* ADF x/y ranges (TODO!) */ }, /* KODAK ESP 5100, */ { 0x4025, "esp", "KODAK ESP 5100 AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP 5300, */ { 0x4026, "esp", "KODAK ESP 5300 AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP 5500, */ { 0x4027, "esp", "KODAK ESP 5500 AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP 5000, */ { 0x4028, "esp", "KODAK ESP 5000 Series AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP 3300, */ { 0x4031, "esp", "KODAK ESP 3300 Series AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP5, */ { 0x4032, "esp", "KODAK ESP 5 AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP7, */ { 0x403E, "esp", "KODAK ESP 7 AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP9, */ { 0x403F, "esp", "KODAK ESP 9 AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP5210 or 5250, */ { 0x4041, "esp", "KODAK ESP 5200 Series AiO", -1, 0x82, /* USBoutEP, USBinEP (-1 means find one) */ 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP3200 , */ { 0x4043, "esp", "KODAK ESP 3200 Series AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP4100 , */ { 0x4053, "esp", "KODAK ESP Office 4100 Series AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP6100 , */ { 0x4054, "esp", "KODAK ESP Office 6100 Series AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_TRUE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP7200 , */ { 0x4056, "esp", "KODAK ESP 7200 Series AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP C110 , */ { 0x4057, "esp", "KODAK ESP C110 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP C115 , */ { 0x4058, "esp", "KODAK ESP C115 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP 2150 , */ { 0x4059, "esp", "KODAK ESP Office 2150 Series", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_TRUE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP C310 , */ { 0x405D, "esp", "KODAK ESP C310 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP C315 , */ { 0x405E, "esp", "KODAK ESP C315 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* ADVENT AW10, */ { 0x4060, "esp", "ADVENT WiFi AIO AW10", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, {from, to, 0} 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_TRUE, SANE_FALSE, /* ADF, duplex. */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK HERO 6.1, */ { 0x4062, "esp", "KODAK OFFICE HERO 6.1 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, {from, to, 0} 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_TRUE, SANE_FALSE, /* ADF, duplex. */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK HERO 7.1, */ { 0x4063, "esp", "KODAK HERO 7.1 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, {from, to, 0} 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_TRUE, /* ADF, duplex. */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK HERO 5.1, */ { 0x4064, "esp", "KODAK HERO 5.1 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, {from, to, 0} 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_TRUE, /* ADF, duplex.*/ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP9200 , */ { 0x4065, "esp", "KODAK ESP 9200 Series AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_TRUE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK ESP2170 , */ { 0x4066, "esp", "KODAK ESP Office 2170 Series", -1, 0x82, 1200, {75, 1200, 0}, kodakaio_resolution_list, 5, /* 1200 dpi optical, {from, to, 0} 5 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_TRUE, SANE_FALSE, /* ADF, duplex */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK HERO 9.1, */ { 0x4067, "esp", "KODAK HERO 9.1 AiO", -1, 0x82, 1200, {75, 1200, 0}, kodakaio_resolution_list, 5, /* 1200 dpi optical, {from, to, 0} 5 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_TRUE, SANE_FALSE, /* ADF, duplex. */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK HERO 4.1, */ { 0x4069, "esp", "KODAK HERO 4.1 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, {from, to, 0} 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_TRUE, SANE_FALSE, /* ADF, duplex.*/ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* KODAK HERO 3.1, */ { 0x406D, "esp", "KODAK HERO 3.1 AiO", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, {from, to, 0} 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_TRUE, /* ADF, duplex. */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ }, /* spare use for specified usbid */ { 0, "esp", "specified", -1, 0x82, 600, {75, 600, 0}, kodakaio_resolution_list, 4, /* 600 dpi max, {from, to, 0} 4 resolutions */ 8, kodakaio_depth_list, /* color depth max 8, list above */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(11.7 * MM_PER_INCH), 0}, /* FBF x/y ranges */ SANE_FALSE, SANE_TRUE, /* ADF, duplex. */ {0, SANE_FIX(8.5 * MM_PER_INCH), 0}, {0, SANE_FIX(14 * MM_PER_INCH), 0} /* 14 ADF x/y ranges */ } }; /**************************************************************************** * General configuration parameter definitions ****************************************************************************/ /* * Definition of the mode_param struct, that is used to * specify the valid parameters for the different scan modes. * * The depth variable gets updated when the bit depth is modified. */ /* could be affecting what data sane delivers */ static struct mode_param mode_params[] = { {0x03, 3, 24}, /* Color, 3 colors, 24 bit */ {0x02, 1, 8}, /* Grayscale, 1 color, 8 bit */ {0x00, 1, 1} /* Lineart, 1 color, 8 bit (was 8 bit) */ }; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_LINEART, NULL }; static const SANE_String_Const adf_mode_list[] = { SANE_I18N("Simplex"), SANE_I18N("Duplex"), NULL }; /* Define the different scan sources */ #define FBF_STR SANE_I18N("Flatbed") #define ADF_STR SANE_I18N("Automatic Document Feeder") /* * source list need one dummy entry (save device settings is crashing). * NOTE: no const - this list gets created while exploring the capabilities * of the scanner. Here space is reserved for 3 entries + NULL ? */ static SANE_String_Const source_list[] = { FBF_STR, NULL, NULL, NULL }; static const SANE_Range percent_range_fixed = {SANE_FIX(0.0), SANE_FIX(100.0), SANE_FIX(1.0)}; /*static const SANE_Range percent_range_int = {0, 100, 1};*/ /* prototypes */ static SANE_Status attach_one_usb(SANE_String_Const devname); static SANE_Status attach_one_net(SANE_String_Const devname, unsigned int device); void kodakaio_com_str(unsigned char *buf, char *fmt_buf); int cmparray (unsigned char *array1, unsigned char *array2, size_t len); #if WITH_AVAHI static struct KodakaioCap *get_device_from_identification (const char *ident, const char *vid, const char *pid); void ProcessAvahiDevice(const char *device_id, const char *vid, const char *pid, const char *ip_addr); #endif /* Some utility functions */ static size_t max_string_size(const SANE_String_Const strings[]) { /* returns the length of the longest string in an array of strings */ size_t size, max_size = 0; int i; for (i = 0; strings[i]; i++) { size = strlen(strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static void print_params(const SANE_Parameters params, int level) { DBG(level, "formats: binary=?, grey=%d, colour=%d\n",SANE_FRAME_GRAY, SANE_FRAME_RGB ); DBG(level, "params.format = %d\n", params.format); DBG(level, "params.last_frame = %d\n", params.last_frame); DBG(level, "params.bytes_per_line = %d\n", params.bytes_per_line); DBG(level, "params.pixels_per_line = %d\n", params.pixels_per_line); DBG(level, "params.lines = %d\n", params.lines); DBG(level, "params.depth = %d\n", params.depth); } static void print_status(KodakAio_Scanner *s,int level) { DBG(level, "print_status with level %d\n", level); DBG(level, "s->bytes_unread = %d\n", s->bytes_unread); /* DBG(level, "params.last_frame = %d\n", params.last_frame); DBG(level, "params.bytes_per_line = %d\n", params.bytes_per_line); DBG(level, "params.pixels_per_line = %d\n", params.pixels_per_line); DBG(level, "params.lines = %d\n", params.lines); DBG(level, "params.depth = %d\n", params.depth); */ } /**************************************************************************** * Low-level Network communication functions ****************************************************************************/ static int kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted, SANE_Status * status) /* there seems to be a condition where this returns no error and no data without detecting a timeout That is probably if the scanner disconnected the network connection */ { size_t size, read = 0; struct pollfd fds[1]; int pollreply; *status = SANE_STATUS_GOOD; /* poll for data-to-be-read (using K_Request_Timeout) */ fds[0].fd = s->fd; fds[0].events = POLLIN; fds[0].revents = 0; if ((pollreply = poll (fds, 1, K_Request_Timeout)) <= 0) { if (pollreply == 0) DBG(1, "net poll timeout\n"); else /* pollreply is -ve */ DBG(1, "net poll error\n"); *status = SANE_STATUS_IO_ERROR; return read; } else if((fds[0].revents & POLLIN) && !(fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))) { while (read < wanted) { DBG(50, "reading: read %lu, wanted %lu\n",read, wanted); size = sanei_tcp_read(s->fd, buf + read, wanted - read); if (size == 0) { DBG(1, "No data read. Scanner may have disconnected\n"); break; } read += size; } if (read == 0) *status = SANE_STATUS_IO_ERROR; DBG(32, "net read %lu bytes:%x,%x,%x,%x,%x,%x,%x,%x\n",(unsigned long)read,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]); return read; } else DBG(1, "Unknown problem with poll\n"); return read; } static int sanei_kodakaio_net_write_raw(struct KodakAio_Scanner *s, const unsigned char *buf, size_t buf_size, SANE_Status *status) { DBG(32, "net write:%x,%x,%x,%x,%x,%x,%x,%x\n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]); sanei_tcp_write(s->fd, buf, buf_size); /* TODO: Check whether sending failed... */ *status = SANE_STATUS_GOOD; return buf_size; } static SANE_Status sanei_kodakaio_net_open(struct KodakAio_Scanner *s) { struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; DBG(5, "%s\n", __func__); setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); return SANE_STATUS_GOOD; } static SANE_Status sanei_kodakaio_net_close(struct KodakAio_Scanner *s) { NOT_USED(s); /* Does nothing - maybe should close the socket ? */ return SANE_STATUS_GOOD; } /**************************************************************************** * Low-level USB communication functions ****************************************************************************/ static int kodakaio_getNumberOfUSBProductIds (void) { return sizeof (kodakaio_cap) / sizeof (struct KodakaioCap); } /**************************************************************************** * low-level communication commands ****************************************************************************/ static void dump_hex_buffer_dense (int level, const unsigned char *buf, size_t buf_size) { size_t k; char msg[1024], fmt_buf[1024]; memset (&msg[0], 0x00, 1024); memset (&fmt_buf[0], 0x00, 1024); for (k = 0; k < min(buf_size, 80); k++) { if (k % 16 == 0) { if (k>0) { DBG (level, "%s\n", msg); memset (&msg[0], 0x00, 1024); } sprintf (fmt_buf, " 0x%04lx ", (unsigned long)k); strcat (msg, fmt_buf); } if (k % 8 == 0) { strcat (msg, " "); } sprintf (fmt_buf, " %02x" , buf[k]); strcat (msg, fmt_buf); } if (msg[0] != 0 ) { DBG (level, "%s\n", msg); } } /* changing params to char seems to cause a stack problem */ void kodakaio_com_str(unsigned char *buf, char *fmt_buf) { /* returns a printable string version of the first 8 bytes assuming they are a kodakaio command*/ if(buf[0] == 0x1b) { sprintf (fmt_buf, "esc %c %c %02x %02x %02x %02x %02x", buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); } else { sprintf (fmt_buf, "%02x %02x %02x %02x %02x %02x %02x %02x", buf[0],buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); } } static int k_send(KodakAio_Scanner * s, void *buf, size_t buf_size, SANE_Status * status) { char fmt_buf[25]; kodakaio_com_str(buf, fmt_buf); DBG(15, "%s: size = %lu :%s\n", __func__, (u_long) buf_size, fmt_buf); if (DBG_LEVEL >= 125) { const unsigned char *s = buf; DBG(125, "complete buffer:\n"); dump_hex_buffer_dense (125, s, buf_size); } if (s->hw->connection == SANE_KODAKAIO_NET) { return sanei_kodakaio_net_write_raw(s, buf, buf_size, status); } else if (s->hw->connection == SANE_KODAKAIO_USB) { size_t n; n = buf_size; *status = sanei_usb_write_bulk(s->fd, buf, &n); DBG(50, "USB: wrote %lu bytes, status: %s\n", (unsigned long)n, sane_strstatus(*status)); return n; } *status = SANE_STATUS_INVAL; return 0; } static ssize_t k_recv(KodakAio_Scanner * s, void *buf, ssize_t buf_size, SANE_Status * status) { /* requests and receives data this function makes the split between USB and NET this function called by a number of others In USB mode, this function will wait until data is available for a maximum of SCANNER_READ_TIMEOUT seconds. In NET mode the timeout is in kodakaio_net_read */ ssize_t n = 0; char fmt_buf[25]; time_t time_start; time_t time_now; struct timespec usb_delay, usb_rem; usb_delay.tv_sec = 0; usb_delay.tv_nsec = 300000000; /* 0.3 sec */ if (s->hw->connection == SANE_KODAKAIO_NET) { time(&time_start); DBG(min(16,DBG_READ), "[%ld] %s: net req size = %ld ", (long) time_start, __func__, (long) buf_size); n = kodakaio_net_read(s, buf, buf_size, status); DBG(min(16,DBG_READ), "returned %lu\n", (unsigned long)n); if (*status != SANE_STATUS_GOOD) { DBG(1, "%s: err returned from kodakaio_net_read, %s\n", __func__, sane_strstatus(*status)); } } else if (s->hw->connection == SANE_KODAKAIO_USB) { /* Start the clock for USB timeout */ time(&time_start); /* Loop until we have data */ while (n == 0) { n = buf_size; /* but what if the data is an exact number of blocks? */ DBG(min(16,DBG_READ), "[%ld] %s: usb req size = %ld ", (long) time_start, __func__, (long) n); *status = sanei_usb_read_bulk(s->fd, (SANE_Byte *) buf, (size_t *) & n); DBG(min(16,DBG_READ), "returned %ld\n", (long) n); if(*status != SANE_STATUS_GOOD) { DBG(min(16,DBG_READ), "sanei_usb_read_bulk gave %s\n", sane_strstatus(*status)); if (*status == SANE_STATUS_EOF) { /* If we have EOF status, wait for more data */ time(&time_now); if (difftime(time_now, time_start) < SCANNER_READ_TIMEOUT) { nanosleep(&usb_delay, &usb_rem); } else { /* Timeout */ return n; } } else { /* If we've encountered another type of error, return */ return n; } } } } if (n == 8) { kodakaio_com_str(buf, fmt_buf); DBG(min(14,DBG_READ), "%s: size = %ld, got %s\n", __func__, (long int)n, fmt_buf); } /* dump buffer if appropriate */ if (DBG_LEVEL >= 127 && n > 0) { const unsigned char* b=buf; dump_hex_buffer_dense (125, b, buf_size); } return n; } static SANE_Status kodakaio_expect_ack(KodakAio_Scanner *s, unsigned char *rxbuf) /* gets 8 byte reply, checks reply is an Ack and returns appropriate status */ { SANE_Status status; k_recv(s, rxbuf, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status)); return status; } /* strncmp ignores diffent possible responses like escSS00000 and escSS02000 */ if (strncmp((char *)KodakEsp_Ack,(char *)rxbuf,4)!=0) { DBG (1, "No Ack received, Expected 0x%2x %2x %2x %2x... got 0x%2x %2x %2x %2x...\n", KodakEsp_Ack[0], KodakEsp_Ack[1], KodakEsp_Ack[2], KodakEsp_Ack[3],rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3]); return SANE_STATUS_IO_ERROR; } return status; } static SANE_Status kodakaio_txrx(KodakAio_Scanner *s, unsigned char *txbuf, unsigned char *rxbuf) /* Sends 8 byte data to scanner and returns reply and appropriate status. */ { SANE_Status status; ssize_t n = 0; k_send(s, txbuf, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status)); return status; } n = k_recv(s, rxbuf, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: %s gave rx err, %s\n", __func__, "txvalue", sane_strstatus(status)); return status; } if (n == 0) { DBG(1, "%s: try 1 k_recv returned 0 bytes with status %s\n", __func__, sane_strstatus(status)); n = k_recv(s, rxbuf, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: %s gave rx err, %s\n", __func__, "txvalue", sane_strstatus(status)); return status; } if (n == 0) { DBG(1, "%s: try 2 k_recv returned 0 bytes with status %s\n", __func__, sane_strstatus(status)); return status; } } return status; } static SANE_Status kodakaio_txrxack(KodakAio_Scanner *s, unsigned char *txbuf, unsigned char *rxbuf) /* Sends 8 byte data to scanner, gets 8 byte reply, checks reply is an Ack and returns appropriate status */ { SANE_Status status; k_send(s, txbuf, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status)); return status; } k_recv(s, rxbuf, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: %s gave rx err, %s\n", __func__, "txvalue", sane_strstatus(status)); return status; } /* strncmp ignores different possible responses like escSS00000 and escSS02000 */ if (strncmp((char *)KodakEsp_Ack,(char *)rxbuf,3) == 0) { /* was 4 byte comp */ if (rxbuf[4] == 0x01 && s->adf_loaded == SANE_FALSE) { s->adf_loaded = SANE_TRUE; DBG(5, "%s: News - docs in ADF\n", __func__); } else if (rxbuf[4] != 0x01 && s->adf_loaded == SANE_TRUE) { s->adf_loaded = SANE_FALSE; DBG(5, "%s: News - ADF is empty\n", __func__); } } else { DBG (1, "No Ack received, Sent 0x%2x %2x %2x %2x... got 0x%2x %2x %2x %2x...\n", txbuf[0], txbuf[1], txbuf[2], txbuf[3],rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3]); return SANE_STATUS_IO_ERROR; } return status; } /* unused function static ssize_t kodakaio_rxflush(KodakAio_Scanner *s) Tries to get 64 byte reply and returns number of bytes read { SANE_Status status; unsigned char rxbuf[64]; ssize_t n = 0; n = k_recv(s, rxbuf, 64, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: %s gave rx err, %s\n", __func__, "status", sane_strstatus(status)); } DBG(5, "%s: flushed, %d bytes\n", __func__, (int)n); return n; } */ /* * high-level communication commands */ static SANE_Status k_hello (KodakAio_Scanner * s) { SANE_Status status; unsigned char reply[8]; char fmt_buf[25]; DBG(5, "%s\n", __func__); /* check that there is nothing already in the input buffer before starting kodakaio_rxflush(s); */ /* preset the reply, so I can see if it gets changed */ reply[0] = 0; reply[1] = 1; reply[2] = 2; reply[3] = 3; reply[4] = 4; reply[5] = 5; reply[6] = 6; reply[7] = 7; if((status = kodakaio_txrx(s, KodakEsp_V, reply))!= SANE_STATUS_GOOD) { DBG(1, "%s: KodakEsp_V failure, %s\n", __func__, sane_strstatus(status)); return SANE_STATUS_IO_ERROR; } if (strncmp((char *) reply, (char *) KodakEsp_v, 3)!=0) { kodakaio_com_str(reply, fmt_buf); DBG(1, "%s: KodakEsp_v err, got %s\n", __func__, fmt_buf); return SANE_STATUS_IO_ERROR; } DBG(5, "%s: OK %s\n", __func__, sane_strstatus(status)); return status; } /* Start scan command */ static SANE_Status cmd_start_scan (SANE_Handle handle, size_t expect_total) /* expect_total is the expected total no of bytes just for info -ve value not a problem? or is it for size_t? */ { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; SANE_Status status = SANE_STATUS_GOOD; unsigned char reply[8]; /*send the start command here */ print_status(s, 5); /*adf added 20/2/12, apparently an extra KodakEsp_F is sent when the adf is used */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { /* adf is in use */ if (! s->adf_loaded) return SANE_STATUS_CANCELLED; /* was SANE_STATUS_NO_DOCS; */ if (kodakaio_txrxack(s, KodakEsp_F, reply)!= SANE_STATUS_GOOD) { DBG(1, "%s: Did not get a good reply to KodakEsp_F\n", __func__); return SANE_STATUS_IO_ERROR; } } if (kodakaio_txrxack(s, KodakEsp_E, reply)!= SANE_STATUS_GOOD) { DBG(1, "%s: Did not get a good reply to KodakEsp_E\n", __func__); return SANE_STATUS_IO_ERROR; } DBG(20, "starting the scan, expected total bytes %lu\n",(unsigned long)expect_total); k_send(s, KodakEsp_Go, 8, &status); if (status != SANE_STATUS_GOOD) DBG(1, "%s: KodakEsp_Go command NOT successfully sent\n", __func__); else { DBG(30, "%s: KodakEsp_Go command successfully sent\n", __func__); s->scanning = SANE_TRUE; } return status; } static SANE_Status cmd_cancel_scan (SANE_Handle handle) { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; unsigned char reply[8]; /* adf added 20/2/12 should it be adf? or adf with paper in? */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { /* adf */ if (kodakaio_txrxack(s, KodakEsp_F, reply)!= SANE_STATUS_GOOD) { DBG(1, "%s: KodakEsp_F command failed\n", __func__); return SANE_STATUS_IO_ERROR; } if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD) { DBG(1, "%s: KodakEsp_UnLock command failed\n", __func__); return SANE_STATUS_IO_ERROR; } DBG(5, "%s unlocked the scanner with adf F U\n", __func__); } else { /* no adf */ if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD) { DBG(1, "%s: KodakEsp_UnLock command failed\n", __func__); return SANE_STATUS_IO_ERROR; } DBG(5, "%s unlocked the scanner U\n", __func__); } s->scanning = SANE_FALSE; return SANE_STATUS_GOOD; } static SANE_Status cmd_get_scanning_parameters(SANE_Handle handle, SANE_Frame *format, SANE_Int *depth, SANE_Int *data_pixels, SANE_Int *pixels_per_line, SANE_Int *lines) { /* data_pixels is per line. Old mc cmd read this stuff from the scanner. I don't think kodak can do that easily */ KodakAio_Scanner *s = (KodakAio_Scanner *) handle; SANE_Status status = SANE_STATUS_GOOD; NOT_USED (format); NOT_USED (depth); DBG(10, "%s\n", __func__); /* Calculate returned values */ *lines = s->params.lines; *pixels_per_line = s->params.pixels_per_line; *data_pixels = s->params.pixels_per_line; DBG (20, "%s: data_pixels = %u, lines = %u, " "pixels_per_line = %u)\n", __func__, *data_pixels, *lines, *pixels_per_line); return status; } /* Set color curve command, low level, sends commands to the scanner*/ static SANE_Status cmd_set_color_curve(SANE_Handle handle, unsigned char col) { /* sends the color curve data for one color*/ KodakAio_Scanner *s = (KodakAio_Scanner *) handle; SANE_Status status = SANE_STATUS_GOOD; unsigned char tx_col[8]; unsigned char rx[8]; unsigned char tx_curve[256]; int i; /* 7/9/14 was unsigned char and that stopped the loop that made the linear curve from going to 255 */ DBG(32, "%s: start\n", __func__); tx_col[0]=0x1b; tx_col[1]='S'; tx_col[2]='K'; tx_col[3]=col; tx_col[4]=0; tx_col[5]=0; tx_col[6]=0; tx_col[7]=0; /* linear curve now but could send tailor made curves in future */ for(i=0;i<=255;++i) tx_curve[i]=i; /* 7/9/14 was i<255 the missing elements caused speckles */ k_send(s, tx_col, 8, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, "curve command"); return status; } k_send(s, tx_curve, 256, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, "curve data"); return status; } if (kodakaio_expect_ack(s, rx) != SANE_STATUS_GOOD) return SANE_STATUS_IO_ERROR; DBG(10, "%s: sent curve OK, \n", __func__); return status; } /* Set scanning parameters command, low level, sends commands to the scanner*/ static SANE_Status cmd_set_scanning_parameters(SANE_Handle handle, int resolution, int tl_x, int tl_y, int width, int height, unsigned char source) /* NB. here int tl_x, int tl_y, int width, int height are in DPI units, not optres units! */ /* sends params to scanner, but should we store them too? */ { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; SANE_Status status = SANE_STATUS_GOOD; unsigned char tx_S[8]; unsigned char tx_dpi[8]; unsigned char tx_topleft[8]; unsigned char tx_widthheight[8]; unsigned char bufread[8]; int i; /*don't know the purpose of F yet. windows USB repeated 4 x why? does it affect the colour balance?*/ DBG(8, "%s\n", __func__); for(i=0;i<4;++i) { kodakaio_txrxack(s, KodakEsp_F, bufread); sleep(1); } /* kodakaio_txrxack(s, KodakEsp_F, bufread); for net, just once */ /* Source? bed /ADF */ tx_S[0]=0x1b; tx_S[1]='S'; tx_S[2]='S'; tx_S[3]=source; tx_S[4]=0; tx_S[5]=0; tx_S[6]=0; tx_S[7]=0; kodakaio_txrxack(s, tx_S, bufread); /* Compression */ kodakaio_txrxack(s, KodakEsp_Comp, bufread); /* DPI resolution */ tx_dpi[0]=0x1b; tx_dpi[1]='S'; tx_dpi[2]='D'; tx_dpi[3]=resolution & 0xff; tx_dpi[4]=(resolution >> 8) & 0xff; tx_dpi[5]=resolution & 0xff; tx_dpi[6]=(resolution >> 8) & 0xff; tx_dpi[7]=0; kodakaio_txrxack(s, tx_dpi, bufread); /* colour curves don't seem to be sent for usb preview but it seems to do no harm to send them */ cmd_set_color_curve(s, 'R'); cmd_set_color_curve(s, 'G'); cmd_set_color_curve(s, 'B'); /* Origin top left s->tl_x and s->tl_y are in optres units this command needs actual DPI units*/ DBG(20, "%s: left (DPI)=%d, top (DPI)=%d\n", __func__, tl_x , tl_y); tx_topleft[0]=0x1b; tx_topleft[1]='S'; tx_topleft[2]='O'; tx_topleft[3]=(tl_x) & 0xff; tx_topleft[4]=((tl_x) >> 8) & 0xff; tx_topleft[5]=(tl_y) & 0xff; tx_topleft[6]=((tl_y) >> 8) & 0xff; tx_topleft[7]=0; kodakaio_txrxack(s, tx_topleft, bufread); /* Z width height note the s->width and s->height are in optres units this command needs actual DPI units*/ tx_widthheight[0]=0x1b; tx_widthheight[1]='S'; tx_widthheight[2]='Z'; tx_widthheight[3]=(width) & 0xff; tx_widthheight[4]=((width) >> 8) & 0xff; tx_widthheight[5]=(height) & 0xff; tx_widthheight[6]=((height) >> 8) & 0xff; tx_widthheight[7]=0; kodakaio_txrxack(s, tx_widthheight, bufread); if (status != SANE_STATUS_GOOD) DBG(1, "%s: Data NOT successfully sent\n", __func__); else DBG(20, "%s: Data successfully sent\n", __func__); return status; } int cmparray (unsigned char *array1, unsigned char *array2, size_t len) { /* compares len bytes of the arrays returns 0 if they match returns the first missmatch position if they don't match */ unsigned int i; for(i=0; iack and do padding if the padding option is selected if no padding option return EOF */ KodakAio_Scanner *s = (KodakAio_Scanner *) handle; SANE_Status status; int oldtimeout = K_Request_Timeout; size_t bytecount; unsigned char *Last8; /* will point to the last 8 chars in buf */ int i, line, lines; if (s->ack && s->val[OPT_PADDING].w) { /* do padding of whole block*/ /* memset(buf, 0x80, *len); need to work out the background colour for this */ lines = *len / s->params.bytes_per_line; for (line=0; line < lines; ++line) { for (i=0; i< s->params.pixels_per_line; ++i) { buf[line * s->params.bytes_per_line + i] = s->background[0]; /*red */ buf[line * s->params.bytes_per_line + s->params.pixels_per_line + i] = s->background[1]; /*green */ buf[line * s->params.bytes_per_line + 2 * s->params.pixels_per_line + i] = s->background[2]; /*blue */ } } s->bytes_unread -= *len; if (s->bytes_unread < 0) s->bytes_unread = 0; return SANE_STATUS_GOOD; } if (s->ack && !s->val[OPT_PADDING].w) { s->bytes_unread = 0; s->eof = SANE_TRUE; return SANE_STATUS_EOF; } /* Temporarily set the poll timeout long instead of short, * because a color scan needs >5 seconds to initialize. Is this needed for kodak? maybe */ K_Request_Timeout = K_Scan_Data_Timeout; sanei_usb_set_timeout (K_Scan_Data_Timeout); bytecount = k_recv(s, buf, *len, &status); K_Request_Timeout = oldtimeout; sanei_usb_set_timeout (oldtimeout); /* We may need to do some special thing with the block request size to cope with usb blocks of any length in order to keep the ack bytes, when using adf, at the end of one block ie not split between blocks. But it seems that the scanner takes care of that, and gives you the ack as a separate 8 byte block */ if (bytecount >= 8) { /* it may be the last block from the scanner so look for Ack response in last 8 bytes */ Last8 = buf + bytecount - 8; /* only compare 4 bytes because we sometimes get escSS02.. or escSS00.. is 4 the right number ? */ if (cmparray(Last8,KodakEsp_Ack,4) == 0) { DBG(min(10,DBG_READ), "%s: found KodakEsp_Ack at %lu bytes of %lu\n", __func__, (unsigned long) bytecount, (unsigned long) *len); s->ack = SANE_TRUE; *len = bytecount - 8; /* discard the Ack response */ s->bytes_unread -= *len; /* return a short block */ } else { /* a not full buffer is returned usb does this */ DBG(min(10,DBG_READ), "%s: buffer not full, got %lu bytes of %lu\n", __func__, (unsigned long) bytecount, (unsigned long) *len); *len = bytecount; s->bytes_unread -= bytecount; } } else { DBG(min(1,DBG_READ), "%s: tiny read, got %lu bytes of %lu\n", __func__, (unsigned long) bytecount, (unsigned long) *len); return SANE_STATUS_IO_ERROR; } lines = *len / s->params.bytes_per_line; if (lines > 1) { /* store average colour as background. That's not the ideal method but it's easy to implement. What's it used for? */ s->background[0] = 0; s->background[1] = 0; s->background[2] = 0; for (line=0; line < lines; ++line) { for (i=0; i< s->params.pixels_per_line; ++i) { s->background[0] += buf[line * s->params.bytes_per_line + i]; /*red */ s->background[1] += buf[line * s->params.bytes_per_line + s->params.pixels_per_line + i]; /*green */ s->background[2] += buf[line * s->params.bytes_per_line + 2 * s->params.pixels_per_line + i]; /*blue */ } } s->background[0] = s->background[0] / (lines * s->params.pixels_per_line); s->background[1] = s->background[1] / (lines * s->params.pixels_per_line); s->background[2] = s->background[2] / (lines * s->params.pixels_per_line); } if (status == SANE_STATUS_GOOD) if (s->bytes_unread <= 0) DBG(min(2,DBG_READ), "%s: Page fully read %d blocks, %ld bytes unread\n", __func__, s->counter, (long) s->bytes_unread); else DBG(min(20,DBG_READ), "%s: Image data successfully read %ld bytes, %ld bytes unread\n", __func__, (long) bytecount, (long) s->bytes_unread); else if (s->ack) /* was (status == SANE_STATUS_EOF) */ DBG(min(2,DBG_READ), "%s: scanner data read ended %d blocks %ld bytes, %ld bytes unread\n", __func__, s->counter, (long) bytecount, (long) s->bytes_unread); else DBG(min(1,DBG_READ), "%s: Image data read stopped with %s after %d blocks %ld bytes, %ld bytes unread\n", __func__, sane_strstatus(status), s->counter, (long) bytecount, (long) s->bytes_unread); return status; } /**************************************************************************** * kodakaio backend high-level operations ****************************************************************************/ static void k_dev_init(Kodak_Device *dev, const char *devname, int conntype) { DBG(5, "%s for %s\n", __func__,devname); dev->name = NULL; dev->model = NULL; dev->connection = conntype; dev->sane.name = devname; dev->sane.model = NULL; dev->sane.type = "flatbed scanner"; dev->sane.vendor = "Kodak"; dev->cap = &kodakaio_cap[CAP_DEFAULT]; } static SANE_Status k_set_model(KodakAio_Scanner * s, const char *model, size_t len) { unsigned char *buf; unsigned char *p; struct Kodak_Device *dev = s->hw; if (len<1) return SANE_STATUS_INVAL; /* to handle missing model */ buf = malloc(len + 1); if (buf == NULL) return SANE_STATUS_NO_MEM; memcpy(buf, model, len); buf[len] = '\0'; p = &buf[len - 1]; while (*p == ' ') { *p = '\0'; p--; } if (dev->model) free(dev->model); dev->model = strndup((const char *) buf, len); dev->sane.model = dev->model; DBG(10, "%s: model is '%s'\n", __func__, dev->model); free(buf); return SANE_STATUS_GOOD; } static void k_set_device (SANE_Handle handle, SANE_Word device) { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; Kodak_Device *dev = s->hw; int n; DBG(10, "%s: 0x%x\n", __func__, device); for (n = 0; n < NELEMS (kodakaio_cap); n++) { if (kodakaio_cap[n].id == device) break; } if (n < NELEMS(kodakaio_cap)) { dev->cap = &kodakaio_cap[n]; } else { dev->cap = &kodakaio_cap[CAP_DEFAULT]; DBG(1, " unknown device 0x%x, using default %s\n", device, dev->cap->model); } k_set_model (s, dev->cap->model, strlen (dev->cap->model)); } static SANE_Status k_discover_capabilities(KodakAio_Scanner *s) { SANE_Status status = SANE_STATUS_GOOD; Kodak_Device *dev = s->hw; SANE_String_Const *source_list_add = source_list; DBG(10, "%s\n", __func__); /* always add flatbed */ *source_list_add++ = FBF_STR; /* TODO: How can I check for existence of an ADF??? */ if (dev->cap->ADF == SANE_TRUE) { *source_list_add++ = ADF_STR; DBG(10, "%s: added adf to list\n", __func__); } /* TODO: Is there any capability that we can extract from the * device by some scanner command? So far, it looks like * the device does not support any reporting. */ dev->x_range = &dev->cap->fbf_x_range; dev->y_range = &dev->cap->fbf_y_range; DBG(10, " x-range: %f %f\n", SANE_UNFIX(dev->x_range->min), SANE_UNFIX(dev->x_range->max)); DBG(10, " y-range: %f %f\n", SANE_UNFIX(dev->y_range->min), SANE_UNFIX(dev->y_range->max)); DBG(5, "End of %s, status:%s\n", __func__, sane_strstatus(status)); *source_list_add = NULL; /* add end marker to source list */ return status; } static SANE_Status k_setup_block_mode (KodakAio_Scanner *s) { /* works for USB and for net changing to make block size = a number of complete lines 28/12/12 */ s->block_len = MAX_BLOCK_SIZE / s->scan_bytes_per_line * s->scan_bytes_per_line; s->bytes_unread = s->data_len; s->counter = 0; s->bytes_read_in_line = 0; if (s->line_buffer) free(s->line_buffer); s->line_buffer = malloc(s->scan_bytes_per_line); if (s->line_buffer == NULL) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } DBG (10, " %s: Setup block mode - scan_bytes_per_line=%d, pixels_per_line=%d, depth=%d, data_len=%d, block_len=%d, blocks=%d, last_len=%d\n", __func__, s->scan_bytes_per_line, s->params.pixels_per_line, s->params.depth, s->data_len, s->block_len, s->blocks, s->last_len); return SANE_STATUS_GOOD; } /* Call the commands to set scanning parameters In the Kodak Aio the parameters are: (x1b,"S","F",0,0,0,0,0) (x1b,"S","S",1,0,0,0,0) #It looks like the 4th param byte of the C command is compression 1=compress, 0=no compression #1st (or 3rd) param could be channels, 2nd could be bits per channel (x1b,"S","C",3,8,3,0,0) #3,8,3,1,0) was what the kodak software used with compression (x1b,"S","D",LowByte(Res),HighByte(Res),LowByte(Res),HighByte(Res),0) #resolution in DPI SendColour(tcpCliSock,"R") SendColour(tcpCliSock,"G") SendColour(tcpCliSock,"B") (x1b,"S","O",LowByte(x0*Res),HighByte(x0*Res),LowByte(y0*Res),HighByte(y0*Res),0) #top left in pixels (x1b,"S","Z",LowByte(x1*Res),HighByte(x1*Res),LowByte(y1*Res),HighByte(y1*Res),0) #bot right in pixels (x1b,"S","E",1,0,0,0,0) */ static SANE_Status k_lock_scanner (KodakAio_Scanner * s) { SANE_Status status; unsigned char reply[8]; status = k_hello(s); if(status != SANE_STATUS_GOOD) { DBG(1, "%s k_hello failed with %s\n", __func__, sane_strstatus(status)); return status; } if (kodakaio_txrxack(s, KodakEsp_Lock, reply)!= SANE_STATUS_GOOD) { DBG(1, "%s Could not lock scanner\n", __func__); return SANE_STATUS_IO_ERROR; } if (s->adf_loaded) DBG(5, "%s scanner locked, with docs in adf\n", __func__); else DBG(5, "%s scanner locked, with no docs in adf\n", __func__); return SANE_STATUS_GOOD; } static SANE_Status k_set_scanning_parameters(KodakAio_Scanner * s) { SANE_Status status; unsigned char rs, source; SANE_Int scan_pixels_per_line = 0; int dpi, optres; dpi = s->val[OPT_RESOLUTION].w; optres = s->hw->cap->optical_res; /* Find the resolution in the res list and assign the index (rs) */ for (rs=0; rs < s->hw->cap->res_list_size; rs++ ) { if ( dpi == s->hw->cap->res_list[rs] ) break; } /* ADF used? */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { source = 0x00; } else { source = 0x01; } /* TODO: Any way to set PREVIEW??? */ /* Remaining bytes unused */ status = cmd_set_scanning_parameters(s, dpi, s->left * dpi / optres, s->top * dpi / optres, /* top/left start (dpi units)*/ s->params.pixels_per_line, s->params.lines, /* extent was s->width, s->height*/ source); /* source */ if (status != SANE_STATUS_GOOD) DBG (1, "%s: Command cmd_set_scanning_parameters failed, %s\n", __func__, sane_strstatus(status)); /* Now query the scanner for the current image parameters */ status = cmd_get_scanning_parameters (s, &s->params.format, &s->params.depth, &scan_pixels_per_line, &s->params.pixels_per_line, &s->params.lines); if (status != SANE_STATUS_GOOD) { DBG (1, "%s: Command cmd_get_scanning_parameters failed, %s\n", __func__, sane_strstatus(status)); return status; } /* Calculate how many bytes are really used per line */ s->params.bytes_per_line = ceil (s->params.pixels_per_line * s->params.depth / 8.0); if (s->val[OPT_MODE].w == MODE_COLOR) s->params.bytes_per_line *= 3; /* Calculate how many bytes per line will be returned by the scanner. magicolor needed this because it uses padding so scan bytes per line != image bytes per line. * The values needed for this are returned by get_scanning_parameters */ s->scan_bytes_per_line = 3 * ceil (scan_pixels_per_line); /* we always scan in colour 8 bit */ s->data_len = s->scan_bytes_per_line * floor (s->height * dpi / optres + 0.5); /* NB this is the length for a full scan */ DBG (5, "Check: scan_bytes_per_line = %d s->params.bytes_per_line = %d \n", s->scan_bytes_per_line, s->params.bytes_per_line); /* k_setup_block_mode at the start of each page for adf to work */ status = k_setup_block_mode (s); if (status != SANE_STATUS_GOOD) DBG (1, "%s: Command k_setup_block_mode failed, %s\n", __func__, sane_strstatus(status)); DBG (18, "%s: bytes_read_in_line: %d\n", __func__, s->bytes_read_in_line); return status; } static SANE_Status k_check_adf(KodakAio_Scanner * s) { /* 20/2/12 detect paper in the adf? acknowledge esc S S 00 01.. ?*/ if (! s->adf_loaded) { DBG(5, "%s: NO DOCS\n", __func__); return SANE_STATUS_NO_DOCS; } else { /* TODO: Check for jam in ADF */ DBG(5, "%s: DOCS IN ADF\n", __func__); return SANE_STATUS_GOOD; } } static SANE_Status k_scan_finish(KodakAio_Scanner * s) { SANE_Status status = SANE_STATUS_GOOD; DBG(10, "%s called\n", __func__); /* If we have not yet read all data, cancel the scan */ if (s->buf && !s->eof) status = cmd_cancel_scan (s); if (s->line_buffer) free (s->line_buffer); s->line_buffer = NULL; free(s->buf); s->buf = s->end = s->ptr = NULL; return status; } static void k_copy_image_data(KodakAio_Scanner * s, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) /* copies the read data from s->line_buffer to the position in data pointer to by s->ptr uncompressed data is RRRR...GGGG...BBBB per line */ { SANE_Int bytes_available; SANE_Int threshold; DBG (min(18,DBG_READ), "%s: bytes_read in line: %d\n", __func__, s->bytes_read_in_line); *length = 0; threshold = 255 - (int) (SANE_UNFIX(s->val[OPT_THRESHOLD].w) * 255.0 / 100.0 + 0.5); /* 255 - for the grey scale version */ DBG (20, "%s: threshold: %d\n", __func__, threshold); while ((max_length >= s->params.bytes_per_line) && (s->ptr < s->end)) { SANE_Int bytes_to_copy = s->scan_bytes_per_line - s->bytes_read_in_line; /* First, fill the line buffer for the current line: */ bytes_available = (s->end - s->ptr); /* Don't copy more than we have buffer and available */ if (bytes_to_copy > bytes_available) bytes_to_copy = bytes_available; if (bytes_to_copy > 0) { memcpy (s->line_buffer + s->bytes_read_in_line, s->ptr, bytes_to_copy); s->ptr += bytes_to_copy; s->bytes_read_in_line += bytes_to_copy; } /* We have filled as much as possible of the current line * with data from the scanner. If we have a complete line, * copy it over. line points to the current byte in the input s->line_buffer data points to the output buffer*/ if ((s->bytes_read_in_line >= s->scan_bytes_per_line) && (s->params.bytes_per_line <= max_length)) { SANE_Int i; SANE_Byte *line = s->line_buffer; *length += s->params.bytes_per_line; for (i=0; i< s->params.pixels_per_line; ++i) { /* different behaviour for each mode */ if (s->val[OPT_MODE].w == MODE_COLOR){ /*interlace was subtracting from 255 until 6/9/14 */ *data++ = 255-line[0]; /*red */ *data++ = 255-line[s->params.pixels_per_line]; /*green */ *data++ = 255-line[2 * s->params.pixels_per_line]; /*blue */ } else if (s->val[OPT_MODE].w == MODE_LINEART) { /* gives 1 bit output */ /*output image location*/ int offset = i % 8; unsigned char mask = 0x80 >> offset; /*set if any colour is over the threshold */ if (line[0] < threshold || line[s->params.pixels_per_line] < threshold || line[2 * s->params.pixels_per_line] < threshold) *data &= ~mask; /* white clear the bit in mask */ else *data |= mask; /* black set the bit in mask */ if (offset == 7 || i == s->params.pixels_per_line-1) data++; /* move on a byte if the byte is full or the line is complete */ } else { /* greyscale - Average the 3 colours */ *data++ = (255-line[0] +255-line[s->params.pixels_per_line] +255-line[2 * s->params.pixels_per_line]) / 3; } line++; } /*debug file The same for color or grey because the scan is colour */ if (RawScan != NULL) { for (i=0; i< s->scan_bytes_per_line; ++i) fputc(s->line_buffer[i],RawScan); } max_length -= s->params.bytes_per_line; s->bytes_read_in_line -= s->scan_bytes_per_line; } } } static SANE_Status k_init_parametersta(KodakAio_Scanner * s) { int dpi, optres; /* struct mode_param *mparam; */ DBG(10, "%s\n", __func__); memset(&s->params, 0, sizeof(SANE_Parameters)); dpi = s->val[OPT_RESOLUTION].w; optres = s->hw->cap->optical_res; /* mparam = &mode_params[s->val[OPT_MODE].w];does this get used? */ if (SANE_UNFIX(s->val[OPT_BR_Y].w) == 0 || SANE_UNFIX(s->val[OPT_BR_X].w) == 0) return SANE_STATUS_INVAL; /* TODO: Use OPT_RESOLUTION or fixed 600dpi for left/top/width/height? */ s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) * optres) + 0.5; s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) * optres) + 0.5; /* width in pixels */ s->width = ((SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) / MM_PER_INCH) * optres) + 0.5; s->height = ((SANE_UNFIX(s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) / MM_PER_INCH) * optres) + 0.5; DBG(20, "%s: s->width = %d, s->height = %d optres units\n", __func__, s->width, s->height); s->params.pixels_per_line = s->width * dpi / optres + 0.5; /* ADF used without padding? added 30/12/12 */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0 && !s->val[OPT_PADDING].w) s->params.lines = -1; else s->params.lines = s->height * dpi / optres + 0.5; DBG(20, "%s: resolution = %d, preview = %d\n", __func__, dpi, s->val[OPT_PREVIEW].w); DBG(20, "%s: %p %p tlx %f tly %f brx %f bry %f [mm]\n", __func__, (void *) s, (void *) s->val, SANE_UNFIX(s->val[OPT_TL_X].w), SANE_UNFIX(s->val[OPT_TL_Y].w), SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w)); /* * The default color depth is stored in mode_params.depth:‭ */ if (mode_params[s->val[OPT_MODE].w].depth == 1) s->params.depth = 1; else { s->params.depth = s->val[OPT_BIT_DEPTH].w; } DBG(20, "%s: bit depth = s->params.depth = %d\n", __func__,s->params.depth); s->params.last_frame = SANE_TRUE; s->params.bytes_per_line = 3 * ceil (s->params.depth * s->params.pixels_per_line / 8.0); /* kodak only scans in color and conversion to grey or lineart is done in the driver s->params.format = SANE_FRAME_RGB; */ DBG(20, "%s: s->val[OPT_MODE].w = %d (color is %d)\n", __func__,s->val[OPT_MODE].w, MODE_COLOR); if (s->val[OPT_MODE].w == MODE_COLOR) s->params.format = SANE_FRAME_RGB; else if (s->val[OPT_MODE].w == MODE_LINEART) s->params.format = SANE_FRAME_GRAY; else s->params.format = SANE_FRAME_GRAY; DBG(20, "%s: format=%d, bytes_per_line=%d, lines=%d\n", __func__, s->params.format, s->params.bytes_per_line, s->params.lines); return (s->params.lines >= -1) ? SANE_STATUS_GOOD : SANE_STATUS_INVAL; } static SANE_Status k_start_scan(KodakAio_Scanner * s) { SANE_Status status; status = cmd_start_scan (s, s->data_len); if (status != SANE_STATUS_GOOD ) { DBG (1, "%s: starting the scan failed (%s)\n", __func__, sane_strstatus(status)); } return status; } static SANE_Status k_read(struct KodakAio_Scanner *s) { unsigned char rx[8]; /* monitors progress of blocks and calls cmd_read_data to get each block you don't know how many blocks there will be in advance because their size may be determined by the scanner*/ SANE_Status status = SANE_STATUS_GOOD; size_t buf_len = 0; /* have we passed everything we read to sane? */ if (s->ptr == s->end) { if (s->eof) return SANE_STATUS_EOF; s->counter++; if (s->bytes_unread >= s->block_len) buf_len = s->block_len; else buf_len = s->bytes_unread; DBG(min(20,DBG_READ), "%s: block %d, size %lu\n", __func__, s->counter, (unsigned long) buf_len); /* receive image data + error code */ status = cmd_read_data (s, s->buf, &buf_len); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { /* was just GOOD 20/2/12 */ DBG (1, "%s: Receiving image data failed (%s)\n", __func__, sane_strstatus(status)); cmd_cancel_scan(s); return status; } DBG(min(14,DBG_READ), "%s: success %lu bytes of block %d, %d remain\n", __func__, (unsigned long) buf_len, s->counter, s->bytes_unread); if (s->bytes_unread > 0) { if (s->canceling) { cmd_cancel_scan(s); return SANE_STATUS_CANCELLED; } if (status == SANE_STATUS_EOF) { /* page ended prematurely. */ } } else { /* s->bytes_unread <=0 This is the end of a page */ s->eof = SANE_TRUE; DBG(min(10,DBG_READ), "%s: set EOF after %d blocks\n=============\n", __func__, s->counter); /* look for the terminating ack if required */ if (!s->ack) { if (kodakaio_expect_ack(s, rx) == SANE_STATUS_GOOD) { s->ack = SANE_TRUE; } else { DBG(min(1,DBG_READ), "%s: Did not get expected ack at end of page\n", __func__); return SANE_STATUS_IO_ERROR; } } } s->end = s->buf + buf_len; s->ptr = s->buf; } else { DBG(min(20,DBG_READ), "%s: data left in buffer\n", __func__); } return status; } /* * SANE API implementation (high-level functions) */ #if WITH_AVAHI static struct KodakaioCap * get_device_from_identification (const char *ident, const char *vid, const char *pid) { int n; SANE_Word pidnum, vidnum; if(sscanf(vid, "%x", (unsigned int *)&vidnum) == EOF) { DBG(5, "could not convert hex vid <%s>\n", vid); return NULL; } if(sscanf(pid, "%x", (unsigned int *)&pidnum) == EOF) { DBG(5, "could not convert hex pid <%s>\n", pid); return NULL; } for (n = 0; n < NELEMS (kodakaio_cap); n++) { if (strcmp (kodakaio_cap[n].model, ident)==0) { DBG(20, "matched <%s> & <%s>\n", kodakaio_cap[n].model, ident); return &kodakaio_cap[n]; } else if (kodakaio_cap[n].id == pidnum && 0x040A == vidnum) { DBG(20, "matched <%s> & <%s:%s>\n", kodakaio_cap[n].model, vid, pid); return &kodakaio_cap[n]; } else { DBG(20, "not found <%s> & <%s>\n", kodakaio_cap[n].model, pid); } } return NULL; } #endif /* WITH_AVAHI */ /* * close_scanner() * * Close the open scanner. Depending on the connection method, a different * close function is called. */ static void close_scanner(KodakAio_Scanner *s) { DBG(7, "%s: fd = %d\n", __func__, s->fd); if (s->fd == -1) return; k_scan_finish(s); if (s->hw->connection == SANE_KODAKAIO_NET) { sanei_kodakaio_net_close(s); sanei_tcp_close(s->fd); } else if (s->hw->connection == SANE_KODAKAIO_USB) { sanei_usb_close(s->fd); } s->fd = -1; } static SANE_Bool split_scanner_name (const char *name, char * IP, unsigned int *model) { const char *device = name; const char *qm; *model = 0; /* cut off leading net: */ if (strncmp(device, "net:", 4) == 0) device = &device[4]; qm = strchr(device, '?'); if (qm != NULL) { size_t len = qm-device; strncpy (IP, device, len); IP[len] = '\0'; qm++; if (strncmp(qm, "model=", 6) == 0) { qm += 6; if (!sscanf(qm, "0x%x", model)) sscanf(qm, "%x", model); } } else { strcpy (IP, device); } return SANE_TRUE; } /* * open_scanner() * * Open the scanner device. Depending on the connection method, * different open functions are called. */ static SANE_Status open_scanner(KodakAio_Scanner *s) { SANE_Status status = 0; DBG(7, "%s: %s\n", __func__, s->hw->sane.name); if (s->fd != -1) { DBG(10, "scanner is already open: fd = %d\n", s->fd); return SANE_STATUS_GOOD; /* no need to open the scanner */ } if (s->hw->connection == SANE_KODAKAIO_NET) { /* device name has the form net:ipaddr?model=... */ char IP[1024]; unsigned int model = 0; if (!split_scanner_name (s->hw->sane.name, IP, &model)) return SANE_STATUS_INVAL; DBG(10, "split_scanner_name OK model=0x%x\n",model); /* normal with IP */ status = sanei_tcp_open(IP, 9101, &s->fd); /* (host,port,file pointer) */ if (status != SANE_STATUS_GOOD ) DBG(1, "Is network scanner switched on?\n"); if (model>0) k_set_device (s, model); if (status == SANE_STATUS_GOOD) { status = sanei_kodakaio_net_open (s); } else DBG(1, "status was not good at net open\n"); } else if (s->hw->connection == SANE_KODAKAIO_USB) { DBG(7, "trying to open usb\n"); status = sanei_usb_open(s->hw->sane.name, &s->fd); if (s->hw->cap->out_ep>0) sanei_usb_set_endpoint (s->fd, USB_DIR_OUT | USB_ENDPOINT_TYPE_BULK, s->hw->cap->out_ep); if (s->hw->cap->in_ep>0) sanei_usb_set_endpoint (s->fd, USB_DIR_IN | USB_ENDPOINT_TYPE_BULK, s->hw->cap->in_ep); } if (status == SANE_STATUS_ACCESS_DENIED) { DBG(1, "please check that you have permissions on the device.\n"); DBG(1, "if this is a multi-function device with a printer,\n"); DBG(1, "disable any conflicting driver (like usblp).\n"); } if (status != SANE_STATUS_GOOD) DBG(1, "%s open failed: %s\n", s->hw->sane.name, sane_strstatus(status)); else DBG(3, "scanner opened\n"); /* add check here of usb properties? */ /*sanei_usb_get_descriptor( SANE_Int dn, struct sanei_usb_dev_descriptor *desc );*/ return status; } static SANE_Status detect_usb(struct KodakAio_Scanner *s) { SANE_Status status; SANE_Word vendor, product; int i, numIds; SANE_Bool is_valid; /* if the sanei_usb_get_vendor_product call is not supported, * then we just ignore this and rely on the user to config * the correct device. */ status = sanei_usb_get_vendor_product(s->fd, &vendor, &product); if (status != SANE_STATUS_GOOD) { DBG(1, "the device cannot be verified - will continue\n"); return SANE_STATUS_GOOD; } /* check the vendor ID to see if we are dealing with a kodak device */ if (vendor != SANE_KODAKAIO_VENDOR_ID) { /* this is not a supported vendor ID */ DBG(1, "not a Kodak Aio device at %s (vendor id=0x%x)\n", s->hw->sane.name, vendor); return SANE_STATUS_INVAL; } numIds = kodakaio_getNumberOfUSBProductIds(); is_valid = SANE_FALSE; i = 0; /* check all known product IDs to verify that we know * about the device */ while (i != numIds && !is_valid) { /* if (product == kodakaio_usb_product_ids[i]) */ if (product == kodakaio_cap[i].id) is_valid = SANE_TRUE; i++; } if (is_valid == SANE_FALSE) { DBG(1, "the device at %s is not a supported (product id=0x%x)\n", s->hw->sane.name, product); return SANE_STATUS_INVAL; } DBG(2, "found valid usb Kodak Aio scanner: 0x%x/0x%x (vendorID/productID)\n", vendor, product); k_set_device(s, product); /* added 21/12/11 to try and get a name for the device */ return SANE_STATUS_GOOD; } /* * used by attach* and sane_get_devices * a ptr to a single-linked list of Kodak_Device structs * a ptr to a null term array of ptrs to SANE_Device structs */ static int num_devices; /* number of scanners attached to backend */ static Kodak_Device *first_dev; /* first scanner in list */ static const SANE_Device **devlist = NULL; static struct KodakAio_Scanner * scanner_create(struct Kodak_Device *dev, SANE_Status *status) { struct KodakAio_Scanner *s; s = malloc(sizeof(struct KodakAio_Scanner)); if (s == NULL) { *status = SANE_STATUS_NO_MEM; return NULL; } memset(s, 0x00, sizeof(struct KodakAio_Scanner)); s->fd = -1; s->hw = dev; return s; } static struct KodakAio_Scanner * device_detect(const char *name, int type, SANE_Status *status) { struct KodakAio_Scanner *s; struct Kodak_Device *dev; /* try to find the device in our list */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, name) == 0) { dev->missing = 0; DBG (10, "%s: Device %s already attached!\n", __func__, name); return scanner_create(dev, status); } } if (type == SANE_KODAKAIO_NODEV) { *status = SANE_STATUS_INVAL; return NULL; } /* alloc and clear our device structure */ dev = malloc(sizeof(*dev)); if (!dev) { *status = SANE_STATUS_NO_MEM; return NULL; } memset(dev, 0x00, sizeof(struct Kodak_Device)); s = scanner_create(dev, status); if (s == NULL) return NULL; k_dev_init(dev, name, type); *status = open_scanner(s); if (*status != SANE_STATUS_GOOD) { free(s); free(dev); return NULL; } /* from now on, close_scanner() must be called */ /* USB requires special care */ if (dev->connection == SANE_KODAKAIO_USB) { *status = detect_usb(s); } if (*status != SANE_STATUS_GOOD) goto close; /* set name and model (if not already set) */ if (dev->model == NULL) k_set_model(s, "generic", 7); dev->name = strdup(name); dev->sane.name = dev->name; /* do we need to discover capabilities here? */ *status = k_discover_capabilities(s); if (*status != SANE_STATUS_GOOD) goto close; if (source_list[0] == NULL || dev->cap->dpi_range.min == 0) { DBG(1, "something is wrong in the discovery process, aborting.\n"); *status = SANE_STATUS_IO_ERROR; goto close; } /* add this scanner to the device list */ num_devices++; dev->missing = 0; dev->next = first_dev; first_dev = dev; return s; close: close_scanner(s); free(dev); free(s); return NULL; } #if WITH_AVAHI /* ProcessAvahiDevice is called to process each discovered device in turn */ void ProcessAvahiDevice(const char *device_id, const char *vid, const char *pid, const char *ip_addr) { struct KodakaioCap *cap; DBG(min(10,DBG_AUTO),"device_id = <%s> vid:pid = <%s:%s>\n", device_id,vid,pid); /* check if it is a model likely to be supported: "KODAK ESP" or "KODAK HERO" DBG(min(10,DBG_AUTO),"look up model <%s>\n", device_model); */ cap = get_device_from_identification("", vid, pid); if (cap == NULL) { return; } DBG(min(10,DBG_AUTO), "%s: Found autodiscovered device: %s (type 0x%x)\n", __func__, cap->model, cap->id); attach_one_net (ip_addr, cap->id); } static void resolve_callback( AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, AVAHI_GCC_UNUSED void* userdata) { AvahiStringList *vid_pair_list = NULL, *pid_pair_list = NULL; char *pidkey, *pidvalue; char *vidkey, *vidvalue; size_t valuesize; NOT_USED (flags); assert(r); /* Called whenever a service has been resolved successfully or timed out */ switch (event) { case AVAHI_RESOLVER_FAILURE: DBG(min(1,DBG_AUTO), "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r)))); break; case AVAHI_RESOLVER_FOUND: { char a[AVAHI_ADDRESS_STR_MAX]; avahi_address_snprint(a, sizeof(a), address); /* Output short for Kodak ESP */ DBG(min(10,DBG_AUTO), "%s:%u %s\n", a,port,host_name); vid_pair_list = avahi_string_list_find(txt, "vid"); if(vid_pair_list != NULL) { avahi_string_list_get_pair(vid_pair_list, &vidkey, &vidvalue, &valuesize); DBG(min(10,DBG_AUTO), "%s=%s ", vidkey, vidvalue); } else DBG(min(10,DBG_AUTO), "failed to find key vid\n"); pid_pair_list = avahi_string_list_find(txt, "pid"); if(pid_pair_list != NULL) { avahi_string_list_get_pair(pid_pair_list, &pidkey, &pidvalue, &valuesize); DBG(min(10,DBG_AUTO), "%s=%s\n", pidkey, pidvalue); } else DBG(min(10,DBG_AUTO), "failed to find key pid\n"); if(pid_pair_list != NULL && vid_pair_list != NULL) { ProcessAvahiDevice(name, vidvalue, pidvalue, a); } else DBG(min(10,DBG_AUTO), "didn't call ProcessAvahiDevice\n"); if(vid_pair_list != NULL) { avahi_free(vidkey); avahi_free(vidvalue); DBG(min(15,DBG_AUTO), "vidkey and vidvalue freed\n"); } if(pid_pair_list != NULL) { avahi_free(pidkey); avahi_free(pidvalue); DBG(min(15,DBG_AUTO), "pidkey and pidvalue freed\n"); } } } DBG(min(10,DBG_AUTO), "ending resolve_callback\n"); avahi_service_resolver_free(r); } static void browse_callback( AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata) { AvahiSimplePoll *simple_poll = userdata; AvahiClient *c = avahi_service_browser_get_client (b); /* Called whenever a new services becomes available on the LAN or is removed from the LAN */ switch (event) { case AVAHI_BROWSER_FAILURE: DBG(min(1,DBG_AUTO), "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)))); avahi_simple_poll_quit(simple_poll); return; case AVAHI_BROWSER_NEW: DBG(min(5,DBG_AUTO), "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); /* We ignore the returned resolver object. In the callback function we free it. If the server is terminated before the callback function is called the server will free the resolver for us. */ if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, c))) DBG(min(1,DBG_AUTO), "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c))); break; case AVAHI_BROWSER_REMOVE: DBG(min(1,DBG_AUTO), "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain); break; case AVAHI_BROWSER_ALL_FOR_NOW: case AVAHI_BROWSER_CACHE_EXHAUSTED: DBG(min(5,DBG_AUTO), "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; } } static void client_callback(AvahiClient *c, AvahiClientState state, void * userdata) { AvahiSimplePoll *simple_poll = userdata; assert(c); /* Called whenever the client or server state changes */ if (state == AVAHI_CLIENT_FAILURE) { DBG(min(1,DBG_AUTO), "Server connection failure: %s\n", avahi_strerror(avahi_client_errno(c))); avahi_simple_poll_quit(simple_poll); } } static int kodak_network_discovery(const char*host) /* If host = NULL do autodiscovery. If host != NULL try to verify the model First version only does autodiscovery */ { AvahiSimplePoll *simple_poll; AvahiClient *client = NULL; AvahiServiceBrowser *sb = NULL; int error; int i, ret = 1; NOT_USED(host); DBG(2, "%s: called\n", __func__); /* Allocate main loop object */ if (!(simple_poll = avahi_simple_poll_new())) { DBG(min(1,DBG_AUTO), "Failed to create simple poll object.\n"); goto fail; } /* Allocate a new client */ client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, simple_poll, &error); /* Check wether creating the client object succeeded */ if (!client) { DBG(min(1,DBG_AUTO), "Failed to create client: %s\n", avahi_strerror(error)); goto fail; } /* Create the service browser */ if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_scanner._tcp", NULL, 0, browse_callback, simple_poll))) { DBG(min(1,DBG_AUTO), "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client))); goto fail; } /* Run the main loop */ for(i=1;i 0) { snprintf(name, 1024, "net:%s?model=0x%x", dev, model); } else { snprintf(name, 1024, "net:%s", dev); } return attach(name, SANE_KODAKAIO_NET); } static SANE_Status attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) { int vendor, product, timeout; int len = strlen(line); DBG(7, "%s: len = %d, line = %s\n", __func__, len, line); if (sscanf(line, "usb %i %i", &vendor, &product) == 2) { /* add the vendor and product IDs to the list of * known devices before we call the attach function */ int numIds = kodakaio_getNumberOfUSBProductIds(); if (vendor != SANE_KODAKAIO_VENDOR_ID) { DBG(7, "Wrong vendor: numIds = %d, vendor = %d\n", numIds, vendor); return SANE_STATUS_INVAL; /* this is not a Kodak device */ } /* kodakaio_usb_product_ids[numIds - 1] = product; */ kodakaio_cap[numIds - 1].id = product; sanei_usb_attach_matching_devices(line, attach_one_usb); } else if (strncmp(line, "usb", 3) == 0 && len == 3) { int i, numIds; /* auto detect ? */ numIds = kodakaio_getNumberOfUSBProductIds(); for (i = 0; i < numIds; i++) { /* sanei_usb_find_devices(SANE_KODAKAIO_VENDOR_ID, kodakaio_usb_product_ids[i], attach_one_usb); */ sanei_usb_find_devices(SANE_KODAKAIO_VENDOR_ID, kodakaio_cap[i].id, attach_one_usb); } } else if (strncmp(line, "net", 3) == 0) { /* remove the "net" sub string */ const char *name = sanei_config_skip_whitespace(line + 3); char IP[1024]; unsigned int model = 0; if (strncmp(name, "autodiscovery", 13) == 0) { #if WITH_AVAHI DBG (30, "%s: Initiating network autodiscovery via avahi\n", __func__); kodak_network_discovery(NULL); #else DBG (20, "%s: Network autodiscovery not done because not configured with avahi.\n", __func__); #endif } else if (sscanf(name, "%s %x", IP, &model) == 2) { DBG(30, "%s: Using network device on IP %s, forcing model 0x%x\n", __func__, IP, model); attach_one_net(IP, model); } else { DBG(1, "%s: net entry %s may be a host name?\n", __func__, name); attach_one_net(name, 0); } } else if (sscanf(line, "snmp-timeout %i\n", &timeout)) { /* Timeout for auto network discovery */ DBG(50, "%s: network auto-discovery timeout set to %d\n", __func__, timeout); K_SNMP_Timeout = timeout; } else if (sscanf(line, "scan-data-timeout %i\n", &timeout)) { /* Timeout for scan data requests */ DBG(50, "%s: Scan data timeout set to %d\n", __func__, timeout); K_Scan_Data_Timeout = timeout; } else if (sscanf(line, "request-timeout %i\n", &timeout)) { /* Timeout for all other read requests */ DBG(50, "%s: Request timeout set to %d\n", __func__, timeout); K_Request_Timeout = timeout; } else { /* TODO: Warning about unparsable line! */ } return SANE_STATUS_GOOD; } static void free_devices(void) { Kodak_Device *dev, *next; DBG(5, "%s\n", __func__); for (dev = first_dev; dev; dev = next) { next = dev->next; free(dev->name); free(dev->model); free(dev); } if (devlist) free(devlist); devlist = NULL; first_dev = NULL; } SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) { DBG_INIT(); DBG(1, "========================================== \n"); DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__); DBG(1, "kodakaio backend, version %i.%i.%i\n", KODAKAIO_VERSION, KODAKAIO_REVISION, KODAKAIO_BUILD); DBG(2, "%s: called\n", __func__); if (version_code != NULL) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, KODAKAIO_BUILD); sanei_usb_init(); #if WITH_AVAHI DBG(min(3,DBG_AUTO), "avahi detected\n"); #else DBG(min(3,DBG_AUTO), "avahi not detected\n"); #endif return SANE_STATUS_GOOD; } /* Clean up the list of attached scanners. */ void sane_exit(void) { DBG(5, "%s\n", __func__); free_devices(); } SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool __sane_unused__ local_only) { Kodak_Device *dev, *s, *prev=0; int i; DBG(2, "%s: called\n", __func__); sanei_usb_init(); /* mark all existing scanners as missing, attach_one will remove mark */ for (s = first_dev; s; s = s->next) { s->missing = 1; } /* Read the config, mark each device as found, possibly add new devs */ sanei_configure_attach(KODAKAIO_CONFIG_FILE, NULL, attach_one_config); /*delete missing scanners from list*/ for (s = first_dev; s;) { if (s->missing) { DBG (5, "%s: missing scanner %s\n", __func__, s->name); /*splice s out of list by changing pointer in prev to next*/ if (prev) { prev->next = s->next; free (s); s = prev->next; num_devices--; } else { /*remove s from head of list */ first_dev = s->next; free(s); s = first_dev; prev=NULL; num_devices--; } } else { prev = s; s = prev->next; } } DBG (15, "%s: found %d scanner(s)\n", __func__, num_devices); for (s = first_dev; s; s=s->next) { DBG (15, "%s: found scanner %s\n", __func__, s->name); } if (devlist) free (devlist); devlist = malloc((num_devices + 1) * sizeof(devlist[0])); if (!devlist) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } DBG(5, "%s - results:\n", __func__); for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) { DBG(5, " %d (%d): %s\n", i, dev->connection, dev->model); devlist[i] = &dev->sane; } devlist[i] = NULL; if(device_list){ *device_list = devlist; } return SANE_STATUS_GOOD; } static SANE_Status init_options(KodakAio_Scanner *s) { int i; SANE_Word *res_list; DBG(5, "%s: called\n", __func__); for (i = 0; i < NUM_OPTIONS; i++) { s->opt[i].size = sizeof(SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_MODE_GROUP].name = SANE_NAME_STANDARD; s->opt[OPT_MODE_GROUP].title = SANE_TITLE_STANDARD; s->opt[OPT_MODE_GROUP].desc = SANE_DESC_STANDARD; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size(mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = MODE_COLOR; /* default */ DBG(20, "%s: mode_list has first entry %s, default mode is %s\n", __func__, mode_list[0],mode_list[s->val[OPT_MODE].w]); /* theshold the sane std says should be SANE_TYPE_FIXED 0..100 but all other backends seem to use INT 0..255 */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; s->opt[OPT_THRESHOLD].size = sizeof(SANE_Word); s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &percent_range_fixed; s->val[OPT_THRESHOLD].w = SANE_FIX(50.0); DBG(20, "%s: threshold initialised to fixed %f\n", __func__, SANE_UNFIX(s->val[OPT_THRESHOLD].w)); /* theshold the sane std says should be SANE_TYPE_FIXED 0..100 but all other backends seem to use INT 0..255 s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; s->opt[OPT_THRESHOLD].size = sizeof(SANE_Word); s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &percent_range_int; s->val[OPT_THRESHOLD].w = 51; DBG(20, "%s: threshold initialised to int %d\n", __func__, s->val[OPT_THRESHOLD].w); */ /* bit depth */ s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE; s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_BIT_DEPTH].constraint.word_list = s->hw->cap->depth_list; s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; s->val[OPT_BIT_DEPTH].w = s->hw->cap->depth_list[1]; /* the first "real" element is the default */ DBG(20, "%s: depth list has depth_list[0] = %d entries\n", __func__, s->hw->cap->depth_list[0]); if (s->hw->cap->depth_list[0] == 1) { /* only one element in the list -> hide the option */ s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; DBG(20, "%s: Only one depth in list so inactive option\n", __func__); } /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; res_list = malloc((s->hw->cap->res_list_size + 1) * sizeof(SANE_Word)); if (res_list == NULL) { return SANE_STATUS_NO_MEM; } *(res_list) = s->hw->cap->res_list_size; memcpy(&(res_list[1]), s->hw->cap->res_list, s->hw->cap->res_list_size * sizeof(SANE_Word)); s->opt[OPT_RESOLUTION].constraint.word_list = res_list; s->val[OPT_RESOLUTION].w = s->hw->cap->dpi_range.min; /* trial option for debugging s->opt[OPT_TRIALOPT].name = "trialoption"; s->opt[OPT_TRIALOPT].title = "trialoption"; s->opt[OPT_TRIALOPT].desc = "trialoption"; s->opt[OPT_TRIALOPT].type = SANE_TYPE_INT; s->opt[OPT_TRIALOPT].unit = SANE_UNIT_NONE; s->opt[OPT_TRIALOPT].size = sizeof(SANE_Word); s->opt[OPT_TRIALOPT].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TRIALOPT].constraint.range = &percent_range_int; s->val[OPT_TRIALOPT].w = 1; */ /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_PREVIEW].w = SANE_FALSE; for(i=0;source_list[i]!=NULL;++i) DBG(18, "source_list: %s\n",source_list[i]); /* source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].size = max_string_size(source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].w = 0; /* always use Flatbed as default */ if ((!s->hw->cap->ADF)) { DBG(9, "device with no adf detected source option inactive\n"); s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; } /* Are there any ESP scanners that are duplex? */ s->opt[OPT_ADF_MODE].name = "adf-mode"; s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode"); s->opt[OPT_ADF_MODE].desc = SANE_I18N("Selects the ADF mode (simplex/duplex)"); s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING; s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list); s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list; s->val[OPT_ADF_MODE].w = 0; /* simplex */ if ((!s->hw->cap->ADF) || (!s->hw->cap->adf_duplex)) s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].name = SANE_NAME_GEOMETRY; s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY; s->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range->max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range->max; /* padding short pages in adf */ s->opt[OPT_PADDING].name = "adf-padding"; s->opt[OPT_PADDING].title = "pad short adf pages"; s->opt[OPT_PADDING].desc = "Selects whether to make short pages up to full length"; s->opt[OPT_PADDING].type = SANE_TYPE_BOOL; s->val[OPT_PADDING].w = SANE_FALSE; if ((!s->hw->cap->ADF) || (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) != 0)) { DBG(9, "adf not source so padding option off and inactive\n"); s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; } SANE_Status sane_open(SANE_String_Const name, SANE_Handle *handle) { SANE_Status status; KodakAio_Scanner *s = NULL; int l = strlen(name); DBG(2, "%s: name = %s\n", __func__, name); /* probe if empty device name provided */ if (l == 0) { status = sane_get_devices(NULL,0); if (status != SANE_STATUS_GOOD) { return status; } if (first_dev == NULL) { DBG(1, "no device detected\n"); return SANE_STATUS_INVAL; } s = device_detect(first_dev->sane.name, first_dev->connection, &status); if (s == NULL) { DBG(1, "cannot open a perfectly valid device (%s)," " please report to the authors\n", name); return SANE_STATUS_INVAL; } } else { if (strncmp(name, "net:", 4) == 0) { s = device_detect(name, SANE_KODAKAIO_NET, &status); if (s == NULL) return status; } else if (strncmp(name, "libusb:", 7) == 0) { s = device_detect(name, SANE_KODAKAIO_USB, &status); if (s == NULL) return status; } else { /* as a last resort, check for a match * in the device list. This should handle platforms without libusb. */ if (first_dev == NULL) { status = sane_get_devices(NULL,0); if (status != SANE_STATUS_GOOD) { return status; } } s = device_detect(name, SANE_KODAKAIO_NODEV, &status); if (s == NULL) { DBG(1, "invalid device name: %s\n", name); return SANE_STATUS_INVAL; } } } /* s is always valid here */ DBG(10, "handle obtained\n"); status = k_discover_capabilities(s); /* added 27/12/11 to fix source list problem maybe we should only be rebuilding the source list here? */ if (status != SANE_STATUS_GOOD) return status; init_options(s); *handle = (SANE_Handle) s; /* moving the open scanner section below to sane_start 27/12/14 status = open_scanner(s); if (status != SANE_STATUS_GOOD) { free(s); return status; } */ return status; } void sane_close(SANE_Handle handle) { KodakAio_Scanner *s; /* * XXX Test if there is still data pending from * the scanner. If so, then do a cancel */ s = (KodakAio_Scanner *) handle; DBG(2, "%s: called\n", __func__); /* moving the close scanner section below to sane_cancel 27/12/14 */ if (s->fd != -1) close_scanner(s); /* end of section */ if(RawScan != NULL) fclose(RawScan); RawScan = NULL; free(s); } const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) { /* this may be a sane call, but it happens way too often to have DBG level 2 */ KodakAio_Scanner *s = (KodakAio_Scanner *) handle; DBG(30, "%s: called for option %d\n", __func__, option); if (option < 0 || option >= NUM_OPTIONS) return NULL; return s->opt + option; } static const SANE_String_Const * search_string_list(const SANE_String_Const *list, SANE_String value) { while (*list != NULL && strcmp(value, *list) != 0) list++; return ((*list == NULL) ? NULL : list); } /* Activate, deactivate an option. Subroutines so we can add debugging info if we want. The change flag is set to TRUE if we changed an option. If we did not change an option, then the value of the changed flag is not modified. */ static void activateOption(KodakAio_Scanner *s, SANE_Int option, SANE_Bool *change) { if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { s->opt[option].cap &= ~SANE_CAP_INACTIVE; *change = SANE_TRUE; } } static void deactivateOption(KodakAio_Scanner *s, SANE_Int option, SANE_Bool *change) { if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { s->opt[option].cap |= SANE_CAP_INACTIVE; *change = SANE_TRUE; } } static SANE_Status getvalue(SANE_Handle handle, SANE_Int option, void *value) { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); DBG(17, "%s: option = %d\n", __func__, option); switch (option) { case OPT_NUM_OPTS: case OPT_BIT_DEPTH: /* case OPT_TRIALOPT: */ case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *((SANE_Word *) value) = sval->w; DBG(20, "%s: got option %d as %d\n", __func__, option, *((SANE_Word *) value)); break; case OPT_THRESHOLD: *((SANE_Word *) value) = sval->w; DBG(20, "%s: got option %d as %f\n", __func__, option, SANE_UNFIX(*((SANE_Word *) value))); /*DBG(20, "%s: got option %d as %d\n", __func__, option, *((SANE_Word *) value));*/ break; case OPT_MODE: case OPT_SOURCE: case OPT_ADF_MODE: strcpy((char *) value, sopt->constraint.string_list[sval->w]); break; case OPT_PADDING: *((SANE_Bool *) value) = sval->w; break; default: DBG(20, "%s: returning inval\n", __func__); return SANE_STATUS_INVAL; } DBG(20, "%s: returning good\n", __func__); return SANE_STATUS_GOOD; } /* * Handles setting the source (flatbed, or auto document feeder (ADF)). * */ static void change_source(KodakAio_Scanner *s, SANE_Int optindex, char *value) { int force_max = SANE_FALSE; SANE_Bool dummy; DBG(5, "%s: optindex = %d, source = '%s'\n", __func__, optindex, value); if (s->val[OPT_SOURCE].w == optindex) return; s->val[OPT_SOURCE].w = optindex; if (s->val[OPT_TL_X].w == s->hw->x_range->min && s->val[OPT_TL_Y].w == s->hw->y_range->min && s->val[OPT_BR_X].w == s->hw->x_range->max && s->val[OPT_BR_Y].w == s->hw->y_range->max) { force_max = SANE_TRUE; } if (strcmp(ADF_STR, value) == 0) { s->hw->x_range = &s->hw->cap->adf_x_range; s->hw->y_range = &s->hw->cap->adf_y_range; if (s->hw->cap->adf_duplex) { activateOption(s, OPT_ADF_MODE, &dummy); } else { deactivateOption(s, OPT_ADF_MODE, &dummy); s->val[OPT_ADF_MODE].w = 0; } activateOption(s, OPT_PADDING, &dummy); DBG(5, "adf activated flag = %d\n",s->hw->cap->adf_duplex); } else { /* ADF not active */ s->hw->x_range = &s->hw->cap->fbf_x_range; s->hw->y_range = &s->hw->cap->fbf_y_range; deactivateOption(s, OPT_ADF_MODE, &dummy); deactivateOption(s, OPT_PADDING, &dummy); } s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max) s->val[OPT_TL_X].w = s->hw->x_range->min; if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max) s->val[OPT_TL_Y].w = s->hw->y_range->min; if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max) s->val[OPT_BR_X].w = s->hw->x_range->max; if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max) s->val[OPT_BR_Y].w = s->hw->y_range->max; } static SANE_Status setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); SANE_Status status; const SANE_String_Const *optval = NULL; int optindex = 0; SANE_Bool reload = SANE_FALSE; DBG(17, "%s: option = %d, value = %p, as word: %d\n", __func__, option, value, *(SANE_Word *) value); status = sanei_constrain_value(sopt, value, info); if (status != SANE_STATUS_GOOD) return status; if (info && value && (*info & SANE_INFO_INEXACT) && sopt->type == SANE_TYPE_INT) DBG(17, "%s: constrained val = %d\n", __func__, *(SANE_Word *) value); if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) { optval = search_string_list(sopt->constraint.string_list, (char *) value); if (optval == NULL) return SANE_STATUS_INVAL; optindex = optval - sopt->constraint.string_list; } switch (option) { case OPT_MODE: { sval->w = optindex; /* if binary, then disable the bit depth selection and enable threshold */ if (optindex == MODE_LINEART) { DBG(17, "%s: binary mode setting depth to 1\n", __func__); s->val[OPT_BIT_DEPTH].w = 1; s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { if (s->hw->cap->depth_list[0] == 1) { /* only one entry in the list ? */ DBG(17, "%s: non-binary mode but only one depth available\n", __func__); s->val[OPT_BIT_DEPTH].w = s->hw->cap->depth_list[1]; s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; } else { /* there is a list to choose from ? */ DBG(17, "%s: non-binary mode and depth list available\n", __func__); s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* does not work in xsane ? */ } } reload = SANE_TRUE; break; } case OPT_BIT_DEPTH: sval->w = *((SANE_Word *) value); mode_params[s->val[OPT_MODE].w].depth = sval->w; reload = SANE_TRUE; break; case OPT_THRESHOLD: sval->w = *((SANE_Word *) value); DBG(17, "setting threshold to %f\n", SANE_UNFIX(sval->w)); /*DBG(17, "setting threshold to %d\n", sval->w);*/ /*reload = SANE_TRUE; what does this do?*/ break; case OPT_RESOLUTION: sval->w = *((SANE_Word *) value); DBG(17, "setting resolution to %d\n", sval->w); reload = SANE_TRUE; break; case OPT_BR_X: case OPT_BR_Y: sval->w = *((SANE_Word *) value); if (SANE_UNFIX(sval->w) == 0) { DBG(17, "invalid br-x or br-y\n"); return SANE_STATUS_INVAL; } /* passthru */ case OPT_TL_X: case OPT_TL_Y: sval->w = *((SANE_Word *) value); DBG(17, "setting size to %f\n", SANE_UNFIX(sval->w)); if (NULL != info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_SOURCE: change_source(s, optindex, (char *) value); reload = SANE_TRUE; break; case OPT_ADF_MODE: sval->w = optindex; /* Simple lists */ break; case OPT_PADDING: sval->w = *((SANE_Word *) value); break; /* case OPT_TRIALOPT: */ case OPT_PREVIEW: /* needed? */ sval->w = *((SANE_Word *) value); break; default: return SANE_STATUS_INVAL; } if (reload && info != NULL) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; DBG(17, "%s: end\n", __func__); return SANE_STATUS_GOOD; } SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info) { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; if (option < 0 || option >= NUM_OPTIONS) { DBG(1, "%s: option num = %d out of range (0..%d)\n", __func__, option, NUM_OPTIONS - 1); return SANE_STATUS_INVAL; } DBG(5, "%s: action = %x, option = %d %s\n", __func__, action, option, s->opt[option].name); if (info != NULL) *info = 0; switch (action) { case SANE_ACTION_GET_VALUE: return getvalue(handle, option, value); case SANE_ACTION_SET_VALUE: return setvalue(handle, option, value, info); default: return SANE_STATUS_INVAL; } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters *params) { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; DBG(2, "%s: called\n", __func__); if (params == NULL) DBG(1, "%s: params is NULL\n", __func__); /* * If sane_start was already called, then just retrieve the parameters * from the scanner data structure */ if (!s->eof && s->ptr != NULL) { DBG(5, "scan in progress, returning saved params structure\n"); } else { /* otherwise initialize the params structure and gather the data */ k_init_parametersta(s); } if (params != NULL) *params = s->params; print_params(s->params,20); return SANE_STATUS_GOOD; } /* * This function is part of the SANE API and gets called from the front end to * start the scan process. */ SANE_Status sane_start(SANE_Handle handle) { KodakAio_Scanner *s = (KodakAio_Scanner *) handle; SANE_Status status; DBG(2, "%s: called\n", __func__); if(! s->scanning) { /* calc scanning parameters */ status = k_init_parametersta(s); if (status != SANE_STATUS_GOOD) return status; /* set scanning parameters; also query the current image * parameters from the sanner and save * them to s->params Only set scanning params the first time, or after a cancel try change 22/2/12 take lock scanner out of k_set_scanning_parameters */ /* moved open_scanner here 27/12/14 from sane_open */ status = open_scanner(s); if (status != SANE_STATUS_GOOD) { free(s); return status; } /* end of open scanner section */ status = k_lock_scanner(s); if (status != SANE_STATUS_GOOD) { DBG(1, "could not lock scanner\n"); return status; } } status = k_set_scanning_parameters(s); if (status != SANE_STATUS_GOOD) return status; print_params(s->params, 5); /* if we scan from ADF, check if it is loaded */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { status = k_check_adf(s); if (status != SANE_STATUS_GOOD) { /* returning SANE_STATUS_NO_DOCS seems not to cause simple-scan to end the adf scan, so we cancel */ status = SANE_STATUS_CANCELLED; DBG(10, "%s: returning %s\n", __func__, sane_strstatus(status)); return status; } } /* prepare buffer here so that a memory allocation failure * will leave the scanner in a sane state. */ s->buf = realloc(s->buf, s->block_len); if (s->buf == NULL) return SANE_STATUS_NO_MEM; s->eof = SANE_FALSE; /* page not finished */ s->ack = SANE_FALSE; /* page from scanner not finished */ s->ptr = s->end = s->buf; s->canceling = SANE_FALSE; if (strlen(RawScanPath) > 0 && s->params.lines > 0) RawScan = fopen(RawScanPath, "wb");/* open the debug file if it has a name */ if(RawScan) fprintf(RawScan, "P5\n%d %d\n%d\n",s->scan_bytes_per_line, s->params.lines, 255); /* start scanning */ DBG(2, "%s: scanning...\n", __func__); status = k_start_scan(s); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: start failed: %s\n", __func__, sane_strstatus(status)); return status; } return status; } /* this moves data from our buffers to SANE */ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length) { SANE_Status status; KodakAio_Scanner *s = (KodakAio_Scanner *) handle; if (s->buf == NULL || s->canceling) return SANE_STATUS_CANCELLED; *length = 0; DBG(18, "sane-read, bytes unread %d\n",s->bytes_unread); status = k_read(s); if (status == SANE_STATUS_CANCELLED) { k_scan_finish(s); return status; } k_copy_image_data(s, data, max_length, length); DBG(18, "%d lines read, status: %s\n", *length / s->params.bytes_per_line, sane_strstatus(status)); /* continue reading if appropriate */ if (status == SANE_STATUS_GOOD) return status; /* not sure if we want to finish (unlock scanner) here or in sane_close */ /* k_scan_finish(s); */ return status; } void sane_cancel(SANE_Handle handle) { SANE_Status status; KodakAio_Scanner *s = (KodakAio_Scanner *) handle; DBG(2, "%s: called\n", __func__); status = cmd_cancel_scan(s); if (status != SANE_STATUS_GOOD) DBG(1, "%s: cmd_cancel_scan failed: %s\n", __func__, sane_strstatus(status)); /* moved from close scanner section 27/12/14 */ if (s->fd != -1) close_scanner(s); /* end of section */ } /* * SANE_Status sane_set_io_mode() * * not supported - for asynchronous I/O */ SANE_Status sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { return SANE_STATUS_UNSUPPORTED; } /* * SANE_Status sane_get_select_fd() * * not supported - for asynchronous I/O */ SANE_Status sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/lexmark.c0000664000175000017500000011164212775312261014433 00000000000000/* lexmark.c: SANE backend for Lexmark scanners. (C) 2003-2004 Lexmark International, Inc. (Original Source code) (C) 2005 Fred Odendaal (C) 2006-2013 Stéphane Voltz (C) 2010 "Torsten Houwaart" X74 support This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. **************************************************************************/ #include "lexmark.h" #define LEXMARK_CONFIG_FILE "lexmark.conf" #define BUILD 32 #define MAX_OPTION_STRING_SIZE 255 static Lexmark_Device *first_lexmark_device = 0; static SANE_Int num_lexmark_device = 0; static const SANE_Device **sane_device_list = NULL; /* Program globals F.O - Should this be per device?*/ static SANE_Bool initialized = SANE_FALSE; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_LINEART, NULL }; /* possible resolutions are: 75x75, 150x150, 300x300, 600x600, 600x1200 */ static SANE_Int x1100_dpi_list[] = { 5, 75, 150, 300, 600, 1200 }; static SANE_Int a920_dpi_list[] = { 4, 75, 150, 300, 600 }; static SANE_Int x1200_dpi_list[] = { 4, 75, 150, 300, 600 }; static SANE_Int x74_dpi_list[] = { 75, 150, 300, 600 }; static SANE_Range threshold_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (100.0), /* maximum */ SANE_FIX (1.0) /* quantization */ }; static const SANE_Range gain_range = { 0, /* minimum */ 31, /* maximum */ 0 /* quantization */ }; /* for now known models (2 ...) have the same scan window geometry. coordinates are expressed in pixels, with a quantization factor of 8 to have 'even' coordinates at 75 dpi */ static SANE_Range x_range = { 0, /* minimum */ 5104, /* maximum */ 16 /* quantization : 16 is required so we never have an odd width */ }; static SANE_Range y_range = { 0, /* minimum */ 6848, /* maximum */ /* 7032, for X74 */ 8 /* quantization */ }; /* static functions */ static SANE_Status init_options (Lexmark_Device * lexmark_device); static SANE_Status attachLexmark (SANE_String_Const devname); SANE_Status init_options (Lexmark_Device * dev) { SANE_Option_Descriptor *od; DBG (2, "init_options: dev = %p\n", (void *) dev); /* number of options */ od = &(dev->opt[OPT_NUM_OPTS]); od->name = SANE_NAME_NUM_OPTIONS; od->title = SANE_TITLE_NUM_OPTIONS; od->desc = SANE_DESC_NUM_OPTIONS; od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; dev->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* mode - sets the scan mode: Color, Gray, or Line Art */ od = &(dev->opt[OPT_MODE]); od->name = SANE_NAME_SCAN_MODE; od->title = SANE_TITLE_SCAN_MODE; od->desc = SANE_DESC_SCAN_MODE;; od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = MAX_OPTION_STRING_SIZE; od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = mode_list; dev->val[OPT_MODE].s = malloc (od->size); if (!dev->val[OPT_MODE].s) return SANE_STATUS_NO_MEM; strcpy (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR); /* resolution */ od = &(dev->opt[OPT_RESOLUTION]); od->name = SANE_NAME_SCAN_RESOLUTION; od->title = SANE_TITLE_SCAN_RESOLUTION; od->desc = SANE_DESC_SCAN_RESOLUTION; od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_DPI; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_WORD_LIST; switch (dev->model.sensor_type) { case X1100_2C_SENSOR: case A920_SENSOR: od->constraint.word_list = a920_dpi_list; break; case X1100_B2_SENSOR: od->constraint.word_list = x1100_dpi_list; break; case X1200_SENSOR: case X1200_USB2_SENSOR: od->constraint.word_list = x1200_dpi_list; break; case X74_SENSOR: od->constraint.word_list = x74_dpi_list; break; } dev->val[OPT_RESOLUTION].w = 75; /* preview mode */ od = &(dev->opt[OPT_PREVIEW]); od->name = SANE_NAME_PREVIEW; od->title = SANE_TITLE_PREVIEW; od->desc = SANE_DESC_PREVIEW; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->type = SANE_TYPE_BOOL; od->constraint_type = SANE_CONSTRAINT_NONE; dev->val[OPT_PREVIEW].w = SANE_FALSE; /* "Geometry" group: */ od = &(dev->opt[OPT_GEOMETRY_GROUP]); od->name = ""; od->title = SANE_I18N ("Geometry"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->size = 0; od->constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ od = &(dev->opt[OPT_TL_X]); od->name = SANE_NAME_SCAN_TL_X; od->title = SANE_TITLE_SCAN_TL_X; od->desc = SANE_DESC_SCAN_TL_X; od->type = SANE_TYPE_INT; od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->size = sizeof (SANE_Word); od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &x_range; dev->val[OPT_TL_X].w = 0; /* top-left y */ od = &(dev->opt[OPT_TL_Y]); od->name = SANE_NAME_SCAN_TL_Y; od->title = SANE_TITLE_SCAN_TL_Y; od->desc = SANE_DESC_SCAN_TL_Y; od->type = SANE_TYPE_INT; od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->size = sizeof (SANE_Word); od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &y_range; dev->val[OPT_TL_Y].w = 0; /* bottom-right x */ od = &(dev->opt[OPT_BR_X]); od->name = SANE_NAME_SCAN_BR_X; od->title = SANE_TITLE_SCAN_BR_X; od->desc = SANE_DESC_SCAN_BR_X; od->type = SANE_TYPE_INT; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &x_range; dev->val[OPT_BR_X].w = x_range.max; /* bottom-right y */ od = &(dev->opt[OPT_BR_Y]); od->name = SANE_NAME_SCAN_BR_Y; od->title = SANE_TITLE_SCAN_BR_Y; od->desc = SANE_DESC_SCAN_BR_Y; od->type = SANE_TYPE_INT; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &y_range; dev->val[OPT_BR_Y].w = y_range.max; /* threshold */ od = &(dev->opt[OPT_THRESHOLD]); od->name = SANE_NAME_THRESHOLD; od->title = SANE_TITLE_THRESHOLD; od->desc = SANE_DESC_THRESHOLD; od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_PERCENT; od->size = sizeof (SANE_Fixed); od->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &threshold_range; dev->val[OPT_THRESHOLD].w = SANE_FIX (50.0); /* gain group */ dev->opt[OPT_MANUAL_GAIN].name = "manual-channel-gain"; dev->opt[OPT_MANUAL_GAIN].title = SANE_I18N ("Gain"); dev->opt[OPT_MANUAL_GAIN].desc = SANE_I18N ("Color channels gain settings"); dev->opt[OPT_MANUAL_GAIN].type = SANE_TYPE_BOOL; dev->opt[OPT_MANUAL_GAIN].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; dev->opt[OPT_MANUAL_GAIN].size = sizeof (SANE_Bool); dev->val[OPT_MANUAL_GAIN].w = SANE_FALSE; /* gray gain */ dev->opt[OPT_GRAY_GAIN].name = "gray-gain"; dev->opt[OPT_GRAY_GAIN].title = SANE_I18N ("Gray gain"); dev->opt[OPT_GRAY_GAIN].desc = SANE_I18N ("Sets gray channel gain"); dev->opt[OPT_GRAY_GAIN].type = SANE_TYPE_INT; dev->opt[OPT_GRAY_GAIN].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_GRAY_GAIN].unit = SANE_UNIT_NONE; dev->opt[OPT_GRAY_GAIN].size = sizeof (SANE_Int); dev->opt[OPT_GRAY_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GRAY_GAIN].constraint.range = &gain_range; dev->val[OPT_GRAY_GAIN].w = 10; /* red gain */ dev->opt[OPT_RED_GAIN].name = "red-gain"; dev->opt[OPT_RED_GAIN].title = SANE_I18N ("Red gain"); dev->opt[OPT_RED_GAIN].desc = SANE_I18N ("Sets red channel gain"); dev->opt[OPT_RED_GAIN].type = SANE_TYPE_INT; dev->opt[OPT_RED_GAIN].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_RED_GAIN].unit = SANE_UNIT_NONE; dev->opt[OPT_RED_GAIN].size = sizeof (SANE_Int); dev->opt[OPT_RED_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RED_GAIN].constraint.range = &gain_range; dev->val[OPT_RED_GAIN].w = 10; /* green gain */ dev->opt[OPT_GREEN_GAIN].name = "green-gain"; dev->opt[OPT_GREEN_GAIN].title = SANE_I18N ("Green gain"); dev->opt[OPT_GREEN_GAIN].desc = SANE_I18N ("Sets green channel gain"); dev->opt[OPT_GREEN_GAIN].type = SANE_TYPE_INT; dev->opt[OPT_GREEN_GAIN].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_GREEN_GAIN].unit = SANE_UNIT_NONE; dev->opt[OPT_GREEN_GAIN].size = sizeof (SANE_Int); dev->opt[OPT_GREEN_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GREEN_GAIN].constraint.range = &gain_range; dev->val[OPT_GREEN_GAIN].w = 10; /* blue gain */ dev->opt[OPT_BLUE_GAIN].name = "blue-gain"; dev->opt[OPT_BLUE_GAIN].title = SANE_I18N ("Blue gain"); dev->opt[OPT_BLUE_GAIN].desc = SANE_I18N ("Sets blue channel gain"); dev->opt[OPT_BLUE_GAIN].type = SANE_TYPE_INT; dev->opt[OPT_BLUE_GAIN].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_BLUE_GAIN].unit = SANE_UNIT_NONE; dev->opt[OPT_BLUE_GAIN].size = sizeof (SANE_Int); dev->opt[OPT_BLUE_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BLUE_GAIN].constraint.range = &gain_range; dev->val[OPT_BLUE_GAIN].w = 10; return SANE_STATUS_GOOD; } /***************************** SANE API ****************************/ SANE_Status attachLexmark (SANE_String_Const devname) { Lexmark_Device *lexmark_device; SANE_Int dn, vendor, product, variant; SANE_Status status; DBG (2, "attachLexmark: devname=%s\n", devname); for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { /* already attached devices */ if (strcmp (lexmark_device->sane.name, devname) == 0) { lexmark_device->missing = SANE_FALSE; return SANE_STATUS_GOOD; } } lexmark_device = (Lexmark_Device *) malloc (sizeof (Lexmark_Device)); if (lexmark_device == NULL) return SANE_STATUS_NO_MEM; #ifdef FAKE_USB status = SANE_STATUS_GOOD; #else status = sanei_usb_open (devname, &dn); #endif if (status != SANE_STATUS_GOOD) { DBG (1, "attachLexmark: couldn't open device `%s': %s\n", devname, sane_strstatus (status)); return status; } else DBG (2, "attachLexmark: device `%s' successfully opened\n", devname); #ifdef FAKE_USB status = SANE_STATUS_GOOD; /* put the id of the model you want to fake here */ vendor = 0x043d; product = 0x007c; /* X11xx */ variant = 0xb2; #else variant = 0; status = sanei_usb_get_vendor_product (dn, &vendor, &product); #endif if (status != SANE_STATUS_GOOD) { DBG (1, "attachLexmark: couldn't get vendor and product ids of device `%s': %s\n", devname, sane_strstatus (status)); #ifndef FAKE_USB sanei_usb_close (dn); #endif return status; } #ifndef FAKE_USB sanei_usb_close (dn); #endif DBG (2, "attachLexmark: testing device `%s': 0x%04x:0x%04x, variant=%d\n", devname, vendor, product, variant); if (sanei_lexmark_low_assign_model (lexmark_device, devname, vendor, product, variant) != SANE_STATUS_GOOD) { DBG (2, "attachLexmark: unsupported device `%s': 0x%04x:0x%04x\n", devname, vendor, product); return SANE_STATUS_UNSUPPORTED; } /* add new device to device list */ /* there are two variant of the scanner with the same USB id, * so we need to read registers from scanner to detect which one * is really connected */ status = sanei_lexmark_low_open_device (lexmark_device); sanei_usb_close (lexmark_device->devnum); /* set up scanner start status */ sanei_lexmark_low_init (lexmark_device); /* Set the default resolution here */ lexmark_device->x_dpi = 75; lexmark_device->y_dpi = 75; /* Make the pointer to the read buffer null here */ lexmark_device->read_buffer = NULL; /* Set the default threshold for lineart mode here */ lexmark_device->threshold = 0x80; lexmark_device->shading_coeff = NULL; /* mark device as present */ lexmark_device->missing = SANE_FALSE; /* insert it a the start of the chained list */ lexmark_device->next = first_lexmark_device; first_lexmark_device = lexmark_device; num_lexmark_device++; return status; } /** probe for supported lexmark devices * This function scan usb and try to attached to scanner * configured in lexmark.conf . */ static SANE_Status probe_lexmark_devices (void) { FILE *fp; SANE_Char line[PATH_MAX]; const char *lp; SANE_Int vendor, product; size_t len; Lexmark_Device *dev; /* mark already detected devices as missing, during device probe * detected devices will clear this flag */ dev = first_lexmark_device; while (dev != NULL) { dev->missing = SANE_TRUE; dev = dev->next; } /* open config file, parse option and try to open * any device configure in it */ fp = sanei_config_open (LEXMARK_CONFIG_FILE); if (!fp) { return SANE_STATUS_ACCESS_DENIED; } while (sanei_config_read (line, PATH_MAX, fp)) { /* ignore comments */ if (line[0] == '#') continue; len = strlen (line); /* delete newline characters at end */ if (line[len - 1] == '\n') line[--len] = '\0'; lp = sanei_config_skip_whitespace (line); /* skip empty lines */ if (*lp == 0) continue; if (sscanf (lp, "usb %i %i", &vendor, &product) == 2) ; else if (strncmp ("libusb", lp, 6) == 0) ; else if ((strncmp ("usb", lp, 3) == 0) && isspace (lp[3])) { lp += 3; lp = sanei_config_skip_whitespace (lp); } else continue; #ifdef FAKE_USB attachLexmark ("FAKE_USB"); #else sanei_usb_attach_matching_devices (lp, attachLexmark); #endif } fclose (fp); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { SANE_Status status; DBG_INIT (); DBG (1, "SANE Lexmark backend version %d.%d.%d-devel\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (2, "sane_init: version_code=%p\n", (void *) version_code); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); #ifndef FAKE_USB sanei_usb_init (); #endif status = probe_lexmark_devices (); if (status == SANE_STATUS_GOOD) { initialized = SANE_TRUE; } else { initialized = SANE_FALSE; } return status; } void sane_exit (void) { Lexmark_Device *lexmark_device, *next_lexmark_device; DBG (2, "sane_exit\n"); if (!initialized) return; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = next_lexmark_device) { next_lexmark_device = lexmark_device->next; sanei_lexmark_low_destroy (lexmark_device); free (lexmark_device); } if (sane_device_list) free (sane_device_list); sanei_usb_exit(); initialized = SANE_FALSE; return; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Lexmark_Device *lexmark_device; SANE_Int index; DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n", (void *) device_list, local_only); /* hot-plug case : detection of newly connected scanners */ sanei_usb_scan_devices (); probe_lexmark_devices (); if (sane_device_list) free (sane_device_list); sane_device_list = malloc ((num_lexmark_device + 1) * sizeof (sane_device_list[0])); if (!sane_device_list) return SANE_STATUS_NO_MEM; index = 0; lexmark_device = first_lexmark_device; while (lexmark_device != NULL) { if (lexmark_device->missing == SANE_FALSE) { sane_device_list[index] = &(lexmark_device->sane); index++; } lexmark_device = lexmark_device->next; } sane_device_list[index] = 0; *device_list = sane_device_list; return SANE_STATUS_GOOD; } /** * Open the backend, ie return the struct handle of a detected scanner * The struct returned is choosne if it matches the name given, which is * usefull when several scanners handled by the backend have been detected. * However, special case empty string "" and "lexmark" pick the first * available handle. */ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Lexmark_Device *lexmark_device; SANE_Status status; DBG (2, "sane_open: devicename=\"%s\", handle=%p\n", devicename, (void *) handle); if (!initialized) { DBG (2, "sane_open: not initialized\n"); return SANE_STATUS_INVAL; } if (!handle) { DBG (2, "sane_open: no handle\n"); return SANE_STATUS_INVAL; } /* walk the linked list of scanner device until ther is a match * with the device name */ for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { DBG (2, "sane_open: devname from list: %s\n", lexmark_device->sane.name); if (strcmp (devicename, "") == 0 || strcmp (devicename, "lexmark") == 0 || strcmp (devicename, lexmark_device->sane.name) == 0) break; } *handle = lexmark_device; if (!lexmark_device) { DBG (2, "sane_open: Not a lexmark device\n"); return SANE_STATUS_INVAL; } status = init_options (lexmark_device); if (status != SANE_STATUS_GOOD) return status; status = sanei_lexmark_low_open_device (lexmark_device); DBG (2, "sane_open: end.\n"); return status; } void sane_close (SANE_Handle handle) { Lexmark_Device *lexmark_device; DBG (2, "sane_close: handle=%p\n", (void *) handle); if (!initialized) return; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } if (!lexmark_device) return; sanei_lexmark_low_close_device (lexmark_device); return; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Lexmark_Device *lexmark_device; DBG (2, "sane_get_option_descriptor: handle=%p, option = %d\n", (void *) handle, option); if (!initialized) return NULL; /* Check for valid option number */ if ((option < 0) || (option >= NUM_OPTIONS)) return NULL; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } if (!lexmark_device) return NULL; if (lexmark_device->opt[option].name) { DBG (2, "sane_get_option_descriptor: name=%s\n", lexmark_device->opt[option].name); } return &(lexmark_device->opt[option]); } /* rebuilds parameters if needed, called each time SANE_INFO_RELOAD_OPTIONS is set */ static void calc_parameters (Lexmark_Device * lexmark_device) { if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { lexmark_device->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { lexmark_device->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; } /* changing color mode implies changing gain setting */ if (lexmark_device->val[OPT_MANUAL_GAIN].w == SANE_TRUE) { if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) != 0) { lexmark_device->opt[OPT_GRAY_GAIN].cap &= ~SANE_CAP_INACTIVE; lexmark_device->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE; lexmark_device->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE; lexmark_device->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE; } else { lexmark_device->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; lexmark_device->opt[OPT_RED_GAIN].cap &= ~SANE_CAP_INACTIVE; lexmark_device->opt[OPT_GREEN_GAIN].cap &= ~SANE_CAP_INACTIVE; lexmark_device->opt[OPT_BLUE_GAIN].cap &= ~SANE_CAP_INACTIVE; } } else { lexmark_device->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; lexmark_device->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE; lexmark_device->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE; lexmark_device->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE; } } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { Lexmark_Device *lexmark_device; SANE_Status status; SANE_Word w; DBG (2, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", (void *) handle, option, action, (void *) value, (void *) info); if (!initialized) return SANE_STATUS_INVAL; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } if (!lexmark_device) return SANE_STATUS_INVAL; if (value == NULL) return SANE_STATUS_INVAL; if (info != NULL) *info = 0; if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_INVAL; if (lexmark_device->opt[option].type == SANE_TYPE_GROUP) return SANE_STATUS_INVAL; switch (action) { case SANE_ACTION_SET_AUTO: if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) return SANE_STATUS_INVAL; if (!(lexmark_device->opt[option].cap & SANE_CAP_AUTOMATIC)) return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) return SANE_STATUS_INVAL; /* Make sure boolean values are only TRUE or FALSE */ if (lexmark_device->opt[option].type == SANE_TYPE_BOOL) { if (! ((*(SANE_Bool *) value == SANE_FALSE) || (*(SANE_Bool *) value == SANE_TRUE))) return SANE_STATUS_INVAL; } /* Check range constraints */ if (lexmark_device->opt[option].constraint_type == SANE_CONSTRAINT_RANGE) { status = sanei_constrain_value (&(lexmark_device->opt[option]), value, info); if (status != SANE_STATUS_GOOD) { DBG (2, "SANE_CONTROL_OPTION: Bad value for range\n"); return SANE_STATUS_INVAL; } } switch (option) { case OPT_NUM_OPTS: case OPT_RESOLUTION: lexmark_device->val[option].w = *(SANE_Int *) value; sane_get_parameters (handle, 0); break; case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: DBG (2, "Option value set to %d (%s)\n", *(SANE_Word *) value, lexmark_device->opt[option].name); lexmark_device->val[option].w = *(SANE_Word *) value; if (lexmark_device->val[OPT_TL_X].w > lexmark_device->val[OPT_BR_X].w) { w = lexmark_device->val[OPT_TL_X].w; lexmark_device->val[OPT_TL_X].w = lexmark_device->val[OPT_BR_X].w; lexmark_device->val[OPT_BR_X].w = w; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } if (lexmark_device->val[OPT_TL_Y].w > lexmark_device->val[OPT_BR_Y].w) { w = lexmark_device->val[OPT_TL_Y].w; lexmark_device->val[OPT_TL_Y].w = lexmark_device->val[OPT_BR_Y].w; lexmark_device->val[OPT_BR_Y].w = w; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } break; case OPT_THRESHOLD: lexmark_device->val[option].w = *(SANE_Fixed *) value; lexmark_device->threshold = (0xFF * lexmark_device->val[option].w) / 100; break; case OPT_PREVIEW: lexmark_device->val[option].w = *(SANE_Int *) value; if (*(SANE_Word *) value) { lexmark_device->y_dpi = lexmark_device->val[OPT_RESOLUTION].w; lexmark_device->val[OPT_RESOLUTION].w = 75; } else { lexmark_device->val[OPT_RESOLUTION].w = lexmark_device->y_dpi; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; sane_get_parameters (handle, 0); if (info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_GRAY_GAIN: case OPT_GREEN_GAIN: case OPT_RED_GAIN: case OPT_BLUE_GAIN: lexmark_device->val[option].w = *(SANE_Word *) value; return SANE_STATUS_GOOD; break; case OPT_MODE: strcpy (lexmark_device->val[option].s, value); calc_parameters (lexmark_device); if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_MANUAL_GAIN: w = *(SANE_Word *) value; if (w == lexmark_device->val[OPT_MANUAL_GAIN].w) return SANE_STATUS_GOOD; /* no change */ lexmark_device->val[OPT_MANUAL_GAIN].w = w; calc_parameters (lexmark_device); if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; } if (info != NULL) *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: switch (option) { case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_MANUAL_GAIN: case OPT_GRAY_GAIN: case OPT_GREEN_GAIN: case OPT_RED_GAIN: case OPT_BLUE_GAIN: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *) value = lexmark_device->val[option].w; DBG (2, "Option value = %d (%s)\n", *(SANE_Word *) value, lexmark_device->opt[option].name); break; case OPT_THRESHOLD: *(SANE_Fixed *) value = lexmark_device->val[option].w; DBG (2, "Option value = %f\n", SANE_UNFIX (*(SANE_Fixed *) value)); break; case OPT_MODE: strcpy (value, lexmark_device->val[option].s); break; default: return SANE_STATUS_INVAL; } break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Lexmark_Device *lexmark_device; SANE_Parameters *device_params; SANE_Int xres, yres, width_px, height_px; SANE_Int channels, bitsperchannel; DBG (2, "sane_get_parameters: handle=%p, params=%p\n", (void *) handle, (void *) params); if (!initialized) return SANE_STATUS_INVAL; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } if (!lexmark_device) return SANE_STATUS_INVAL; yres = lexmark_device->val[OPT_RESOLUTION].w; if (yres == 1200) xres = 600; else xres = yres; /* 24 bit colour = 8 bits/channel for each of the RGB channels */ channels = 3; bitsperchannel = 8; /* If not color there is only 1 channel */ if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) != 0) { channels = 1; bitsperchannel = 8; } /* geometry in pixels */ width_px = lexmark_device->val[OPT_BR_X].w - lexmark_device->val[OPT_TL_X].w; height_px = lexmark_device->val[OPT_BR_Y].w - lexmark_device->val[OPT_TL_Y].w; DBG (7, "sane_get_parameters: tl=(%d,%d) br=(%d,%d)\n", lexmark_device->val[OPT_TL_X].w, lexmark_device->val[OPT_TL_Y].w, lexmark_device->val[OPT_BR_X].w, lexmark_device->val[OPT_BR_Y].w); /* we must tell the front end the bitsperchannel for lineart is really */ /* only 1, so it can calculate the correct image size */ /* If not color there is only 1 channel */ if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { bitsperchannel = 1; } device_params = &(lexmark_device->params); device_params->format = SANE_FRAME_RGB; if (channels == 1) device_params->format = SANE_FRAME_GRAY; device_params->last_frame = SANE_TRUE; device_params->lines = (height_px * yres) / 600; device_params->depth = bitsperchannel; device_params->pixels_per_line = (width_px * xres) / 600; /* we always read an even number of sensor pixels */ if (device_params->pixels_per_line & 1) device_params->pixels_per_line++; /* data_size is the size transferred from the scanner to the backend */ /* therefore bitsperchannel is the same for gray and lineart */ /* note: bytes_per_line has been divided by 8 in lineart mode */ lexmark_device->data_size = channels * device_params->pixels_per_line * device_params->lines; if (bitsperchannel == 1) { device_params->bytes_per_line = (SANE_Int) ((7 + device_params->pixels_per_line) / 8); } else { device_params->bytes_per_line = (SANE_Int) (channels * device_params->pixels_per_line); } DBG (2, "sane_get_parameters: Data size determined as %ld\n", lexmark_device->data_size); DBG (2, "sane_get_parameters: \n"); if (device_params->format == SANE_FRAME_GRAY) DBG (2, " format: SANE_FRAME_GRAY\n"); else if (device_params->format == SANE_FRAME_RGB) DBG (2, " format: SANE_FRAME_RGB\n"); else DBG (2, " format: UNKNOWN\n"); if (device_params->last_frame == SANE_TRUE) DBG (2, " last_frame: TRUE\n"); else DBG (2, " last_frame: FALSE\n"); DBG (2, " lines %d\n", device_params->lines); DBG (2, " depth %d\n", device_params->depth); DBG (2, " pixels_per_line %d\n", device_params->pixels_per_line); DBG (2, " bytes_per_line %d\n", device_params->bytes_per_line); if (params != 0) { params->format = device_params->format; params->last_frame = device_params->last_frame; params->lines = device_params->lines; params->depth = device_params->depth; params->pixels_per_line = device_params->pixels_per_line; params->bytes_per_line = device_params->bytes_per_line; } return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Lexmark_Device *lexmark_device; SANE_Int offset; SANE_Status status; int resolution; DBG (2, "sane_start: handle=%p\n", (void *) handle); if (!initialized) return SANE_STATUS_INVAL; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } sane_get_parameters (handle, 0); if ((lexmark_device->params.lines == 0) || (lexmark_device->params.pixels_per_line == 0) || (lexmark_device->params.bytes_per_line == 0)) { DBG (2, "sane_start: \n"); DBG (2, " ERROR: Zero size encountered in:\n"); DBG (2, " number of lines, bytes per line, or pixels per line\n"); return SANE_STATUS_INVAL; } lexmark_device->device_cancelled = SANE_FALSE; lexmark_device->data_ctr = 0; lexmark_device->eof = SANE_FALSE; /* Need this cancel_ctr to determine how many times sane_cancel is called since it is called more than once. */ lexmark_device->cancel_ctr = 0; /* Find Home */ if (sanei_lexmark_low_search_home_fwd (lexmark_device)) { DBG (2, "sane_start: Scan head initially at home position\n"); } else { /* We may have been rewound too far, so move forward the distance from the edge to the home position */ sanei_lexmark_low_move_fwd (0x01a8, lexmark_device, lexmark_device->shadow_regs); /* Scan backwards until we find home */ sanei_lexmark_low_search_home_bwd (lexmark_device); } /* do calibration before offset detection , use sensor max dpi, not motor's one */ resolution = lexmark_device->val[OPT_RESOLUTION].w; if (resolution > 600) { resolution = 600; } sanei_lexmark_low_set_scan_regs (lexmark_device, resolution, 0, SANE_FALSE); status = sanei_lexmark_low_calibration (lexmark_device); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: calibration failed : %s ! \n", sane_strstatus (status)); return status; } /* At this point we're somewhere in the dot. We need to read a number of lines greater than the diameter of the dot and determine how many lines past the dot we've gone. We then use this information to see how far the scan head must move before starting the scan. */ /* offset is in 600 dpi unit */ offset = sanei_lexmark_low_find_start_line (lexmark_device); DBG (7, "start line offset=%d\n", offset); /* Set the shadow registers for scan with the options (resolution, mode, size) set in the front end. Pass the offset so we can get the vert. start. */ sanei_lexmark_low_set_scan_regs (lexmark_device, lexmark_device->val[OPT_RESOLUTION].w, offset, SANE_TRUE); if (sanei_lexmark_low_start_scan (lexmark_device) == SANE_STATUS_GOOD) { DBG (2, "sane_start: scan started\n"); return SANE_STATUS_GOOD; } else { lexmark_device->device_cancelled = SANE_TRUE; return SANE_STATUS_INVAL; } } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { Lexmark_Device *lexmark_device; long bytes_read; DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n", (void *) handle, (void *) data, max_length, (void *) length); if (!initialized) { DBG (2, "sane_read: Not initialized\n"); return SANE_STATUS_INVAL; } for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } if (lexmark_device->device_cancelled) { DBG (2, "sane_read: Device was cancelled\n"); /* We don't know how far we've gone, so search for home. */ sanei_lexmark_low_search_home_bwd (lexmark_device); return SANE_STATUS_EOF; } if (!length) { DBG (2, "sane_read: NULL length pointer\n"); return SANE_STATUS_INVAL; } *length = 0; if (lexmark_device->eof) { DBG (2, "sane_read: Trying to read past EOF\n"); return SANE_STATUS_EOF; } if (!data) return SANE_STATUS_INVAL; bytes_read = sanei_lexmark_low_read_scan_data (data, max_length, lexmark_device); if (bytes_read < 0) return SANE_STATUS_IO_ERROR; else if (bytes_read == 0) return SANE_STATUS_EOF; else { *length = bytes_read; lexmark_device->data_ctr += bytes_read; } return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Lexmark_Device *lexmark_device; /* ssize_t bytes_read; */ DBG (2, "sane_cancel: handle = %p\n", (void *) handle); if (!initialized) return; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } /*If sane_cancel called more than once, return */ if (++lexmark_device->cancel_ctr > 1) return; /* Set the device flag so the next call to sane_read() can stop the scan. */ lexmark_device->device_cancelled = SANE_TRUE; return; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Lexmark_Device *lexmark_device; DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", (void *) handle, non_blocking); if (!initialized) return SANE_STATUS_INVAL; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } if (non_blocking) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Lexmark_Device *lexmark_device; DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", (void *) handle, fd ? "!=" : "="); if (!initialized) return SANE_STATUS_INVAL; for (lexmark_device = first_lexmark_device; lexmark_device; lexmark_device = lexmark_device->next) { if (lexmark_device == handle) break; } return SANE_STATUS_UNSUPPORTED; } /***************************** END OF SANE API ****************************/ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/mustek_usb_high.c0000664000175000017500000024744312112021330016134 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Mustek. Originally maintained by Tom Wang Copyright (C) 2001, 2002 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek 1200UB and similar USB flatbed scanners. */ #include "mustek_usb_high.h" #include "mustek_usb_mid.c" /* ------------------------ calibration functions ------------------------- */ static SANE_Byte gray_map[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static inline double filter_lower_end (SANE_Int * buffer, SANE_Word total_count, SANE_Word filter_count) { SANE_Word bound = total_count - 1; SANE_Word left_count = total_count - filter_count; SANE_Int temp = 0; SANE_Word i, j; SANE_Int sum = 0; for (i = 0; i < bound; i++) { for (j = 0; j < bound - i; j++) { if (buffer[j + 1] > buffer[j]) { temp = buffer[j]; buffer[j] = buffer[j + 1]; buffer[j + 1] = temp; } } } for (i = 0; i < left_count; i++) sum += buffer[i]; return (double) sum; } SANE_Status usb_high_cal_init (Calibrator * cal, SANE_Byte type, SANE_Word target_white, SANE_Word target_dark) { DBG (5, "usb_high_cal_init: start, cal=%p, type=%d, target_white=%d " "target_dark=%d\n", (void *) cal, type, target_white, target_dark); cal->is_prepared = SANE_FALSE; cal->k_white = NULL; cal->k_dark = NULL; /* Working Buffer */ cal->white_line = NULL; cal->dark_line = NULL; cal->white_buffer = NULL; /* Necessary Parameters */ cal->k_white_level = 240 << 8; cal->k_dark_level = 0; cal->threshold = 2048; cal->major_average = 0; cal->minor_average = 0; cal->filter = 0; cal->white_needed = 0; cal->dark_needed = 0; cal->max_width = 0; cal->width = 100; cal->gamma_table = 0; cal->calibrator_type = type; cal->k_white_level = target_white / 16; cal->k_dark_level = 0; DBG (5, "usb_high_cal_init: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_exit (Calibrator * cal) { DBG (5, "usb_high_cal_exit: start\n"); if (!cal) { DBG (3, "usb_high_cal_exit: cal == NULL\n"); return SANE_STATUS_INVAL; } if (!cal->is_prepared) { DBG (3, "usb_high_cal_exit: !is_prepared\n"); return SANE_STATUS_INVAL; } DBG (5, "usb_high_cal_exit: 1\n"); if (cal->k_dark) { free (cal->k_dark); } cal->k_dark = NULL; DBG (5, "usb_high_cal_exit: 2\n"); if (cal->k_white) { free (cal->k_white); } cal->k_white = NULL; DBG (5, "usb_high_cal_exit: 3\n"); cal->is_prepared = SANE_FALSE; DBG (5, "usb_high_cal_exit: 4\n"); DBG (5, "usb_high_cal_exit: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_embed_gamma (Calibrator * cal, SANE_Word * gamma_table) { DBG (5, "usb_high_cal_embed_gamma: start\n"); cal->gamma_table = gamma_table; DBG (5, "usb_high_cal_embed_gamma: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_prepare (Calibrator * cal, SANE_Word max_width) { DBG (5, "usb_high_cal_Parepare: start\n"); if (cal->is_prepared) { DBG (3, "usb_high_cal_Parepare: is_prepared\n"); return SANE_STATUS_INVAL; } if (cal->k_white) { free (cal->k_white); } cal->k_white = (SANE_Word *) malloc (max_width * sizeof (SANE_Word)); if (!cal->k_white) return SANE_STATUS_NO_MEM; if (cal->k_dark) { free (cal->k_dark); } cal->k_dark = (SANE_Word *) malloc (max_width * sizeof (SANE_Word)); if (!cal->k_dark) return SANE_STATUS_NO_MEM; cal->max_width = max_width; cal->is_prepared = SANE_TRUE; DBG (5, "usb_high_cal_Parepare: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_setup (Calibrator * cal, SANE_Word major_average, SANE_Word minor_average, SANE_Word filter, SANE_Word width, SANE_Word * white_needed, SANE_Word * dark_needed) { SANE_Int i; DBG (5, "usb_high_cal_setup: start\n"); if (!cal->is_prepared) { DBG (3, "usb_high_cal_setup: !is_prepared\n"); return SANE_STATUS_INVAL; } if (major_average == 0) { DBG (3, "usb_high_cal_setup: major_average==0\n"); return SANE_STATUS_INVAL; } if (minor_average == 0) { DBG (3, "usb_high_cal_setup: minor_average==0\n"); return SANE_STATUS_INVAL; } if (width > cal->max_width) { DBG (3, "usb_high_cal_setup: width>max_width\n"); return SANE_STATUS_INVAL; } cal->major_average = major_average; cal->minor_average = minor_average; cal->filter = filter; cal->width = width; cal->white_needed = major_average * 16 + filter; cal->dark_needed = major_average * 16; *white_needed = cal->white_needed; *dark_needed = cal->dark_needed; if (cal->white_line) { free (cal->white_line); } cal->white_line = (double *) malloc (cal->width * sizeof (double)); if (!cal->white_line) return SANE_STATUS_NO_MEM; if (cal->dark_line) { free (cal->dark_line); } cal->dark_line = (double *) malloc (cal->width * sizeof (double)); if (!cal->dark_line) return SANE_STATUS_NO_MEM; for (i = 0; i < cal->width; i++) { cal->white_line[i] = 0.0; cal->dark_line[i] = 0.0; } if (cal->white_buffer) { free (cal->white_buffer); } cal->white_buffer = (SANE_Int *) malloc (cal->white_needed * cal->width * sizeof (SANE_Int)); if (!cal->white_buffer) return SANE_STATUS_NO_MEM; for (i = 0; i < cal->white_needed * cal->width; i++) { *(cal->white_buffer + i) = 0; } return SANE_STATUS_GOOD; DBG (5, "usb_high_cal_setup: start\n"); } SANE_Status usb_high_cal_evaluate_white (Calibrator * cal, double factor) { /* Caculate white_line */ double loop_division; double average; SANE_Int *buffer; SANE_Word i, j; DBG (5, "usb_high_cal_evaluate_white: start\n"); loop_division = (double) (cal->major_average * cal->minor_average); buffer = (SANE_Int *) malloc (cal->white_needed * sizeof (SANE_Int)); if (!buffer) return SANE_STATUS_NO_MEM; if (cal->white_buffer == NULL) { DBG (3, "usb_high_cal_evaluate_white: white_buffer==NULL\n"); return SANE_STATUS_NO_MEM; } for (i = 0; i < cal->width; i++) { for (j = 0; j < cal->white_needed; j++) { *(buffer + j) = *(cal->white_buffer + j * cal->width + i); } average = filter_lower_end (buffer, cal->white_needed, cal->filter) * factor / loop_division; if (average >= 4096.0) cal->white_line[i] = 4095.9999; else if (average < 0.0) cal->white_line[i] = 0.0; else cal->white_line[i] = average; } free (buffer); buffer = NULL; free (cal->white_buffer); cal->white_buffer = NULL; DBG (5, "usb_high_cal_evaluate_white: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_evaluate_dark (Calibrator * cal, double factor) { SANE_Word i; double loop_division; DBG (5, "usb_high_cal_evaluate_dark: start\n"); /* Caculate dark_line */ factor *= 16.0; loop_division = (double) (cal->major_average * cal->minor_average); for (i = 0; i < cal->width; i++) { cal->dark_line[i] /= loop_division; cal->dark_line[i] -= factor; if (cal->dark_line[i] < 0.0) cal->dark_line[i] = 0.0; } DBG (5, "usb_high_cal_evaluate_dark: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_evaluate_calibrator (Calibrator * cal) { SANE_Int average = 0; SANE_Word i; DBG (5, "usb_high_cal_evaluate_calibrator: start\n"); if (cal->white_line == NULL) { DBG (3, "usb_high_cal_evaluate_calibrator: white_line==NULL\n"); return SANE_FALSE; } if (cal->dark_line == NULL) { DBG (3, "usb_high_cal_evaluate_calibrator: dark_line==NULL\n"); return SANE_FALSE; } for (i = 0; i < cal->width; i++) { average = (SANE_Int) (cal->white_line[i]) - (SANE_Int) (cal->dark_line[i]); if (average <= 0) average = 1; else if (average >= 4096) average = 4095; cal->k_white[i] = (SANE_Word) (average); cal->k_dark[i] = (SANE_Word) (cal->dark_line[i]); } free (cal->dark_line); cal->dark_line = NULL; free (cal->white_line); cal->white_line = NULL; DBG (5, "usb_high_cal_evaluate_calibrator: start\n"); return SANE_STATUS_GOOD; } /* virtual function switcher */ SANE_Status usb_high_cal_fill_in_white (Calibrator * cal, SANE_Word major, SANE_Word minor, void *white_pattern) { DBG (5, "usb_high_cal_fill_in_white: start\n"); switch (cal->calibrator_type) { case I8O8RGB: case I8O8MONO: return usb_high_cal_i8o8_fill_in_white (cal, major, minor, white_pattern); break; case I4O1MONO: return usb_high_cal_i4o1_fill_in_white (cal, major, minor, white_pattern); break; } DBG (5, "usb_high_cal_fill_in_white: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_fill_in_dark (Calibrator * cal, SANE_Word major, SANE_Word minor, void *dark_pattern) { DBG (5, "usb_high_cal_fill_in_dark: start\n"); switch (cal->calibrator_type) { case I8O8RGB: case I8O8MONO: return usb_high_cal_i8o8_fill_in_dark (cal, major, minor, dark_pattern); break; case I4O1MONO: return usb_high_cal_i4o1_fill_in_dark (cal, major, minor, dark_pattern); break; } DBG (5, "usb_high_cal_fill_in_dark: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_calibrate (Calibrator * cal, void *src, void *target) { DBG (5, "usb_high_cal_calibrate: start\n"); switch (cal->calibrator_type) { case I8O8RGB: return usb_high_cal_i8o8_rgb_calibrate (cal, src, target); break; case I8O8MONO: return usb_high_cal_i8o8_mono_calibrate (cal, src, target); break; case I4O1MONO: return usb_high_cal_i4o1_calibrate (cal, src, target); break; } DBG (5, "usb_high_cal_calibrate: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_i8o8_fill_in_white (Calibrator * cal, SANE_Word major, SANE_Word minor, void *white_pattern) { SANE_Byte *pattern; SANE_Word j; pattern = (SANE_Byte *) white_pattern; DBG (5, "usb_high_cal_i8o8_fill_in_white: start, minor=%d\n", minor); if (!cal->is_prepared) { DBG (3, "usb_high_cal_i8o8_fill_in_white: !is_prepared\n"); return SANE_STATUS_INVAL; } if (cal->white_needed == 0) { DBG (3, "usb_high_cal_i8o8_fill_in_white: white_needed==0\n"); return SANE_STATUS_INVAL; } for (j = 0; j < cal->width; j++) { *(cal->white_buffer + major * cal->width + j) += (SANE_Int) (pattern[j]); } DBG (5, "usb_high_cal_i8o8_fill_in_white: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_i8o8_fill_in_dark (Calibrator * cal, SANE_Word major, SANE_Word minor, void *dark_pattern) { SANE_Byte *pattern = (SANE_Byte *) dark_pattern; SANE_Word j; DBG (5, "usb_high_cal_i8o8_fill_in_dark: start, major=%d, minor=%d\n", major, minor); if (!cal->is_prepared) { DBG (3, "usb_high_cal_i8o8_fill_in_dark: !is_prepared\n"); return SANE_FALSE; } if (cal->dark_needed == 0) { DBG (3, "usb_high_cal_i8o8_fill_in_dark: dark_needed==0\n"); return SANE_FALSE; } for (j = 0; j < cal->width; j++) { cal->dark_line[j] += (double) (pattern[j]); } DBG (5, "usb_high_cal_i8o8_fill_in_dark: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_i4o1_fill_in_white (Calibrator * cal, SANE_Word major, SANE_Word minor, void *white_pattern) { SANE_Byte *pattern; SANE_Word j = 0; pattern = (SANE_Byte *) white_pattern; DBG (5, "usb_high_cal_i4o1_fill_in_white: minor=%d\n", minor); if (!cal->is_prepared) { DBG (3, "usb_high_cal_i4o1_fill_in_white: !is_prepared\n"); return SANE_STATUS_INVAL; } if (cal->white_needed == 0) { DBG (3, "usb_high_cal_i4o1_fill_in_white: white_needed==0\n"); return SANE_STATUS_INVAL; } while (j < cal->width) { *(cal->white_buffer + major * cal->width + j) += (SANE_Int) (*(pattern) & 0xf0); j++; if (j >= cal->width) break; *(cal->white_buffer + major * cal->width + j) += (SANE_Int) ((SANE_Byte) (*(pattern++) << 4)); j++; } DBG (5, "usb_high_cal_i8o8_fill_in_white: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_i4o1_fill_in_dark (Calibrator * cal, SANE_Word major, SANE_Word minor, void *dark_pattern) { SANE_Byte *pattern; SANE_Word j = 0; pattern = (SANE_Byte *) dark_pattern; DBG (5, "usb_high_cal_i4o1_fill_in_dark: start, major=%d, minor=%d\n", major, minor); if (!cal->is_prepared) { DBG (3, "usb_high_cal_i4o1_fill_in_dark: !is_prepared\n"); return SANE_STATUS_INVAL; } if (cal->dark_needed == 0) { DBG (5, "usb_high_cal_i4o1_fill_in_dark: dark_needed==0\n"); return SANE_STATUS_INVAL; } while (j < cal->width) { cal->dark_line[j++] += (double) (*(pattern) & 0xf0); if (j >= cal->width) break; cal->dark_line[j++] += (double) ((SANE_Byte) (*(pattern++) << 4)); } DBG (5, "usb_high_cal_i4o1_fill_in_dark: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_i8o8_mono_calibrate (Calibrator * cal, void *src, void *target) { SANE_Byte *gray_src; SANE_Byte *gray_target; SANE_Int base = 0; SANE_Word value = 0; SANE_Word i; DBG (5, "usb_high_cal_i8o8_mono_calibrate: start\n"); gray_src = (SANE_Byte *) src; gray_target = (SANE_Byte *) target; if (cal->gamma_table == NULL) { SANE_Word k_white_level = cal->k_white_level >> 4; for (i = 0; i < cal->width; i++) { base = (SANE_Int) ((SANE_Word) (gray_src[i]) << 4) - (SANE_Int) (cal->k_dark[i]); if (base < 0) base = 0; value = ((SANE_Word) (base) * k_white_level) / cal->k_white[i]; if (value > 0x00ff) value = 0x00ff; gray_target[i] = (SANE_Byte) (value); } } else { for (i = 0; i < cal->width; i++) { base = (SANE_Int) ((SANE_Word) (gray_src[i]) << 4) - (SANE_Int) (cal->k_dark[i]); if (base < 0) base = 0; value = ((SANE_Word) (base) * cal->k_white_level) / cal->k_white[i]; if (value > 0x0fff) value = 0x0fff; gray_target[i] = (SANE_Byte) (cal->gamma_table[value]); } } DBG (5, "usb_high_cal_i8o8_mono_calibrate: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_i8o8_rgb_calibrate (Calibrator * cal, void *src, void *target) { SANE_Byte *gray_src; SANE_Byte *rgb_target; SANE_Int base = 0; SANE_Word value = 0; SANE_Word i; DBG (5, "usb_high_cal_i8o8_rgb_calibrate: start\n"); gray_src = (SANE_Byte *) src; rgb_target = (SANE_Byte *) target; if (cal->gamma_table == NULL) { SANE_Word k_white_level = cal->k_white_level >> 4; for (i = 0; i < cal->width; i++) { base = (SANE_Int) ((SANE_Word) (gray_src[i]) << 4) - (SANE_Int) (cal->k_dark[i]); if (base < 0) base = 0; value = ((SANE_Word) (base) * k_white_level) / cal->k_white[i]; if (value > 0x00ff) value = 0x00ff; *rgb_target = (SANE_Byte) (value); rgb_target += 3; } } else { for (i = 0; i < cal->width; i++) { base = (SANE_Int) ((SANE_Word) (gray_src[i]) << 4) - (SANE_Int) (cal->k_dark[i]); if (base < 0) base = 0; value = ((SANE_Word) (base) * cal->k_white_level) / cal->k_white[i]; if (value > 0x0fff) value = 0x0fff; *(rgb_target) = (SANE_Byte) (cal->gamma_table[value]); rgb_target += 3; } } DBG (5, "usb_high_cal_i8o8_rgb_calibrate: start\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_cal_i4o1_calibrate (Calibrator * cal, void *src, void *target) { SANE_Byte *local_src; SANE_Byte *local_target; SANE_Int base = 0; SANE_Word value = 0; SANE_Word j = 0; SANE_Int count = 0; DBG (5, "usb_high_cal_i4o1_calibrate: start\n"); local_src = (SANE_Byte *) src; local_target = (SANE_Byte *) target; *local_target = 0; while (j < cal->width) { base = (SANE_Int) ((SANE_Word) (*local_src & 0xf0) << 4) - (SANE_Int) (cal->k_dark[j]); if (base < 0) base = 0; value = ((SANE_Word) (base) * cal->k_white_level) / cal->k_white[j]; if (value > 0x0fff) value = 0x0fff; if (value >= cal->threshold) *(local_target) |= gray_map[count]; count++; j++; if (j >= cal->width) break; base = (SANE_Int) ((SANE_Word) (*(local_src++) & 0x0f) << 8) - (SANE_Int) (cal->k_dark[j]); if (base < 0) base = 0; value = ((SANE_Word) (base) * cal->k_white_level) / cal->k_white[j]; if (value > 0x0fff) value = 0x0fff; if (value >= cal->threshold) *(local_target) |= gray_map[count]; count++; if (count >= 8) { local_target++; *local_target = 0; count = 0; } j++; } DBG (5, "usb_high_cal_i4o1_calibrate: exit\n"); return SANE_STATUS_GOOD; } /* --------------------------- scan functions ----------------------------- */ SANE_Status usb_high_scan_init (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_init: start\n"); dev->init_bytes_per_strip = 8 * 1024; dev->adjust_length_300 = 2560; dev->adjust_length_600 = 5120; dev->init_min_expose_time = 4992; dev->init_skips_per_row_300 = 56; /* this value must be times of 6 */ dev->init_skips_per_row_600 = 72; /* this value must be times of 6 */ dev->init_j_lines = 154; dev->init_k_lines = 16; dev->init_k_filter = 8; dev->init_k_loops = 2; dev->init_pixel_rate_lines = 50; dev->init_pixel_rate_filts = 37; dev->init_powerdelay_lines = 2; dev->init_home_lines = 160; dev->init_dark_lines = 50; dev->init_k_level = 245; dev->init_max_power_delay = 240; dev->init_min_power_delay = 136; dev->init_adjust_way = 1; dev->init_green_black_factor = 0.0; dev->init_blue_black_factor = 0.0; dev->init_red_black_factor = 0.0; dev->init_gray_black_factor = 0.0; dev->init_green_factor = 0.82004; dev->init_blue_factor = 0.84954; dev->init_red_factor = 0.826375; dev->init_gray_factor = 0.833375; dev->init_red_rgb_600_pga = 8; dev->init_green_rgb_600_pga = 8; dev->init_blue_rgb_600_pga = 8; dev->init_mono_600_pga = 8; dev->init_red_rgb_300_pga = 8; dev->init_green_rgb_300_pga = 8; dev->init_blue_rgb_300_pga = 8; dev->init_mono_300_pga = 8; dev->init_expose_time = 9024; dev->init_red_rgb_600_power_delay = 80; dev->init_green_rgb_600_power_delay = 80; dev->init_blue_rgb_600_power_delay = 80; dev->init_red_mono_600_power_delay = 80; dev->init_green_mono_600_power_delay = 80; dev->init_blue_mono_600_power_delay = 80; dev->init_red_rgb_300_power_delay = 80; dev->init_green_rgb_300_power_delay = 80; dev->init_blue_rgb_300_power_delay = 80; dev->init_red_mono_300_power_delay = 80; dev->init_green_mono_300_power_delay = 80; dev->init_blue_mono_300_power_delay = 80; dev->init_threshold = 128; dev->init_top_ref = 128; dev->init_front_end = 16; dev->init_red_offset = 0; dev->init_green_offset = 0; dev->init_blue_offset = 0; dev->init_rgb_24_back_track = 80; dev->init_mono_8_back_track = 80; dev->is_open = SANE_FALSE; dev->is_prepared = SANE_FALSE; dev->expose_time = 4000; dev->width = 2550; dev->x_dpi = 300; dev->y_dpi = 300; dev->scan_mode = RGB24EXT; dev->bytes_per_row = 2550 * 3; dev->dummy = 0; dev->bytes_per_strip = 2550; dev->image_buffer = NULL; dev->red = NULL; dev->green = NULL; dev->blue = NULL; dev->get_line = NULL; dev->backtrack = NULL; dev->is_adjusted_rgb_600_power_delay = SANE_FALSE; dev->is_adjusted_mono_600_power_delay = SANE_FALSE; dev->is_adjusted_rgb_300_power_delay = SANE_FALSE; dev->is_adjusted_mono_300_power_delay = SANE_FALSE; dev->is_evaluate_pixel_rate = SANE_FALSE; dev->red_rgb_600_pga = 0; dev->green_rgb_600_pga = 0; dev->blue_rgb_600_pga = 0; dev->mono_600_pga = 0; dev->red_rgb_600_power_delay = 0; dev->green_rgb_600_power_delay = 0; dev->blue_rgb_600_power_delay = 0; dev->red_mono_600_power_delay = 0; dev->green_mono_600_power_delay = 0; dev->blue_mono_600_power_delay = 0; dev->red_rgb_300_pga = 0; dev->green_rgb_300_pga = 0; dev->blue_rgb_300_pga = 0; dev->mono_300_pga = 0; dev->red_rgb_300_power_delay = 0; dev->green_rgb_300_power_delay = 0; dev->blue_rgb_300_power_delay = 0; dev->red_mono_300_power_delay = 0; dev->green_mono_300_power_delay = 0; dev->blue_mono_300_power_delay = 0; dev->pixel_rate = 2000; dev->threshold = 128; dev->gamma_table = 0; dev->skips_per_row = 0; dev->red_calibrator = NULL; dev->green_calibrator = NULL; dev->blue_calibrator = NULL; dev->mono_calibrator = NULL; dev->is_cis_detected = SANE_FALSE; dev->is_sensor_detected = SANE_FALSE; RIE (usb_low_init (&dev->chip)); DBG (5, "usb_high_scan_init: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_exit (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_exit: start\n"); if (!dev->chip) { DBG (5, "usb_high_scan_exit: already exited (`%s')\n", dev->name); return SANE_STATUS_INVAL; } RIE (usb_low_exit (dev->chip)); dev->chip = 0; DBG (5, "usb_high_scan_exit: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_prepare (Mustek_Usb_Device * dev) { DBG (5, "usb_high_scan_prepare: start dev=%p\n", (void *) dev); if (dev->is_prepared) { DBG (5, "usb_high_scan_prepare: is already prepared\n"); return SANE_STATUS_GOOD; } if (dev->image_buffer) { free (dev->image_buffer); } dev->image_buffer = (SANE_Byte *) malloc (dev->init_bytes_per_strip * 3); if (!dev->image_buffer) return SANE_STATUS_NO_MEM; dev->red = dev->image_buffer; dev->green = dev->image_buffer + dev->init_bytes_per_strip; dev->blue = dev->image_buffer + dev->init_bytes_per_strip * 2; dev->is_prepared = SANE_TRUE; DBG (5, "usb_high_scan_prepare: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_clearup (Mustek_Usb_Device * dev) { DBG (5, "usb_high_scan_clearup: start, dev=%p\n", (void *) dev); if (!dev->is_prepared) { DBG (3, "usb_high_scan_clearup: is not prepared\n"); return SANE_STATUS_INVAL; } if (dev->image_buffer) { free (dev->image_buffer); } dev->image_buffer = NULL; dev->red = NULL; dev->green = NULL; dev->blue = NULL; dev->is_prepared = SANE_FALSE; DBG (5, "usb_high_scan_clearup: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_turn_power (Mustek_Usb_Device * dev, SANE_Bool is_on) { SANE_Status status; DBG (5, "usb_high_scan_turn_power: start, turn %s power\n", is_on ? "on" : "off"); if (is_on) { if (dev->is_open) { DBG (3, "usb_high_scan_turn_power: wanted to turn on power, " "but scanner already open\n"); return SANE_STATUS_INVAL; } RIE (usb_low_open (dev->chip, dev->device_name)); dev->is_open = SANE_TRUE; RIE (usb_low_turn_peripheral_power (dev->chip, SANE_TRUE)); RIE (usb_low_turn_lamp_power (dev->chip, SANE_TRUE)); } else { if (!dev->is_open) { DBG (3, "usb_high_scan_turn_power: wanted to turn off power, " "but scanner already closed\n"); return SANE_STATUS_INVAL; } RIE (usb_low_turn_lamp_power (dev->chip, SANE_FALSE)); RIE (usb_low_close (dev->chip)); dev->is_open = SANE_FALSE; } DBG (5, "usb_high_scan_turn_power: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_back_home (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_back_home: start\n"); if (!dev->is_open) { DBG (3, "usb_high_scan_back_home: not open\n"); return SANE_STATUS_INVAL; } RIE (usb_low_set_ccd_width (dev->chip, dev->init_min_expose_time)); RIE (usb_mid_motor_prepare_home (dev->chip)); DBG (5, "usb_high_scan_back_home: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_set_threshold (Mustek_Usb_Device * dev, SANE_Byte threshold) { DBG (5, "usb_high_scan_set_threshold: start, dev=%p, threshold=%d\n", (void *) dev, threshold); dev->threshold = threshold; DBG (5, "usb_high_scan_set_threshold: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_embed_gamma (Mustek_Usb_Device * dev, SANE_Word * gamma_table) { DBG (5, "usb_high_scan_embed_gamma: start, dev=%p, gamma_table=%p\n", (void *) dev, (void *) gamma_table); if (!dev->is_prepared) { DBG (5, "usb_high_scan_embed_gamma !is_prepared\n"); return SANE_STATUS_INVAL; } dev->gamma_table = gamma_table; DBG (5, "usb_high_scan_embed_gamma: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_reset (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_reset: start\n"); if (!dev->is_open) { DBG (3, "usb_high_scan_reset: not open\n"); return SANE_STATUS_INVAL; } if (!dev->is_prepared) { DBG (3, "usb_high_scan_reset: !is_prepared\n"); return SANE_STATUS_INVAL; } RIE (usb_high_scan_init_asic (dev, dev->chip->sensor)); RIE (usb_low_set_ccd_width (dev->chip, dev->init_min_expose_time)); RIE (usb_mid_motor_prepare_home (dev->chip)); RIE (usb_high_scan_set_threshold (dev, dev->init_threshold)); RIE (usb_high_scan_embed_gamma (dev, NULL)); dev->is_adjusted_rgb_600_power_delay = SANE_FALSE; dev->is_adjusted_mono_600_power_delay = SANE_FALSE; dev->is_adjusted_rgb_300_power_delay = SANE_FALSE; dev->is_adjusted_mono_300_power_delay = SANE_FALSE; dev->is_evaluate_pixel_rate = SANE_FALSE; DBG (5, "usb_high_scan_reset: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_wait_carriage_home (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_wait_carriage_home: start\n"); status = usb_low_get_home_sensor (dev->chip); if (status != SANE_STATUS_GOOD) { RIE (usb_low_set_ccd_width (dev->chip, dev->init_min_expose_time)); RIE (usb_mid_motor_prepare_home (dev->chip)); do { status = usb_low_get_home_sensor (dev->chip); if (status != SANE_STATUS_GOOD) usleep (18 * 1000); } while (status != SANE_STATUS_GOOD); } /* No Motor & Forward */ RIE (usb_low_move_motor_home (dev->chip, SANE_FALSE, SANE_FALSE)); DBG (5, "usb_high_scan_wait_carriage_home: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_hardware_calibration (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_hardware_calibration: start\n"); if (dev->is_cis_detected) RIE (usb_high_scan_safe_forward (dev, dev->init_home_lines)); switch (dev->init_adjust_way) { case 1: /* CIS */ switch (dev->scan_mode) { case RGB24EXT: if (usb_mid_sensor_is600_mode (dev->chip, dev->x_dpi)) { dev->expose_time = dev->init_expose_time; dev->red_rgb_600_pga = dev->init_red_rgb_600_pga; dev->green_rgb_600_pga = dev->init_green_rgb_600_pga; dev->blue_rgb_600_pga = dev->init_blue_rgb_600_pga; RIE (usb_high_scan_adjust_rgb_600_power_delay (dev)); } else { dev->expose_time = dev->init_expose_time; dev->red_rgb_300_pga = dev->init_red_rgb_300_pga; dev->green_rgb_300_pga = dev->init_green_rgb_300_pga; dev->blue_rgb_300_pga = dev->init_blue_rgb_300_pga; RIE (usb_high_scan_adjust_rgb_300_power_delay (dev)); } break; case GRAY8EXT: if (usb_mid_sensor_is600_mode (dev->chip, dev->x_dpi)) { dev->expose_time = dev->init_expose_time; dev->mono_600_pga = dev->init_mono_600_pga; RIE (usb_high_scan_evaluate_pixel_rate (dev)); RIE (usb_high_scan_adjust_mono_600_power_delay (dev)); } else { dev->expose_time = dev->init_expose_time; dev->mono_300_pga = dev->init_mono_300_pga; RIE (usb_high_scan_evaluate_pixel_rate (dev)); RIE (usb_high_scan_adjust_mono_300_power_delay (dev)); } break; default: break; } break; case 3: /* CCD */ switch (dev->scan_mode) { case RGB24EXT: dev->red_rgb_600_pga = dev->init_red_rgb_600_pga; dev->green_rgb_600_pga = dev->init_green_rgb_600_pga; dev->blue_rgb_600_pga = dev->init_blue_rgb_600_pga; dev->skips_per_row = dev->init_skips_per_row_600; /* RIE(usb_high_scan_adjust_rgb_600_exposure (dev); fixme */ /* RIE(usb_high_scan_adjust_rgb_600_offset (dev); fixme */ /* RIE(usb_high_scan_adjust_rgb_600_pga (dev); fixme */ /* m_isAdjustedRgb600Offset=FALSE; */ /* RIE(usb_high_scan_adjust_rgb_600_offset (dev); fixme */ /* RIE(usb_high_scan_adjust_rgb_600_skips_per_row (dev); fixme */ break; case GRAY8EXT: dev->mono_600_pga = dev->init_mono_600_pga; dev->skips_per_row = dev->init_skips_per_row_600; RIE (usb_high_scan_adjust_mono_600_exposure (dev)); /* RIE(usb_high_scan_adjust_mono_600_offset (dev); fixme */ /* RIE(usb_high_scan_adjust_mono_600_pga (dev); fixme */ dev->is_adjusted_mono_600_offset = SANE_FALSE; /* RIE(usb_high_scan_adjust_mono_600_offset (dev); fixme */ /* RIE(usb_high_scan_adjust_mono_600_skips_per_row (dev); fixme */ break; default: break; } break; default: dev->expose_time = dev->init_expose_time; dev->red_rgb_600_power_delay = dev->init_red_rgb_600_power_delay; dev->green_rgb_600_power_delay = dev->init_green_rgb_600_power_delay; dev->blue_rgb_600_power_delay = dev->init_blue_rgb_600_power_delay; dev->red_mono_600_power_delay = dev->init_red_mono_600_power_delay; dev->green_mono_600_power_delay = dev->init_green_mono_600_power_delay; dev->blue_mono_600_power_delay = dev->init_blue_mono_600_power_delay; dev->red_rgb_600_pga = dev->init_red_rgb_600_pga; dev->green_rgb_600_pga = dev->init_green_rgb_600_pga; dev->blue_rgb_600_pga = dev->init_blue_rgb_600_pga; dev->mono_600_pga = dev->init_mono_600_pga; dev->red_rgb_300_power_delay = dev->init_red_rgb_300_power_delay; dev->green_rgb_300_power_delay = dev->init_green_rgb_300_power_delay; dev->blue_rgb_300_power_delay = dev->init_blue_rgb_300_power_delay; dev->red_mono_300_power_delay = dev->init_red_mono_300_power_delay; dev->green_mono_300_power_delay = dev->init_green_mono_300_power_delay; dev->blue_mono_300_power_delay = dev->init_blue_mono_300_power_delay; dev->red_rgb_300_pga = dev->init_red_rgb_300_pga; dev->green_rgb_300_pga = dev->init_green_rgb_300_pga; dev->blue_rgb_300_pga = dev->init_blue_rgb_300_pga; dev->mono_300_pga = dev->init_mono_300_pga; break; } DBG (5, "usb_high_scan_hardware_calibration: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_line_calibration (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_line_calibration: start\n"); switch (dev->scan_mode) { case RGB24EXT: RIE (usb_high_scan_prepare_rgb_24 (dev)); if (usb_mid_sensor_is600_mode (dev->chip, dev->x_dpi)) RIE (usb_high_scan_prepare_rgb_signal_600_dpi (dev)); else RIE (usb_high_scan_prepare_rgb_signal_300_dpi (dev)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, dev->x_dpi)); RIE (usb_high_scan_calibration_rgb_24 (dev)); break; case GRAY8EXT: RIE (usb_high_scan_prepare_mono_8 (dev)); if (usb_mid_sensor_is600_mode (dev->chip, dev->x_dpi)) RIE (usb_high_scan_prepare_mono_signal_600_dpi (dev)); else RIE (usb_high_scan_prepare_mono_signal_300_dpi (dev)); RIE (usb_mid_sensor_prepare_mono (dev->chip, dev->x_dpi)); RIE (usb_high_scan_calibration_mono_8 (dev)); break; default: DBG (3, "usb_high_scan_line_calibration: mode not matched\n"); return SANE_STATUS_INVAL; break; } DBG (5, "usb_high_scan_line_calibration: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_prepare_scan (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_prepare_scan: start\n"); switch (dev->scan_mode) { case RGB24EXT: RIE (usb_high_scan_prepare_rgb_24 (dev)); dev->get_line = &usb_high_scan_get_rgb_24_bit_line; dev->backtrack = &usb_high_scan_backtrack_rgb_24; if (usb_mid_sensor_is600_mode (dev->chip, dev->x_dpi)) RIE (usb_high_scan_prepare_rgb_signal_600_dpi (dev)); else RIE (usb_high_scan_prepare_rgb_signal_300_dpi (dev)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, dev->x_dpi)); RIE (usb_mid_motor_prepare_rgb (dev->chip, dev->y_dpi)); break; case GRAY8EXT: RIE (usb_high_scan_prepare_mono_8 (dev)); dev->get_line = &usb_high_scan_get_mono_8_bit_line; dev->backtrack = &usb_high_scan_backtrack_mono_8; if (usb_mid_sensor_is600_mode (dev->chip, dev->x_dpi)) RIE (usb_high_scan_prepare_mono_signal_600_dpi (dev)); else RIE (usb_high_scan_prepare_mono_signal_300_dpi (dev)); RIE (usb_mid_sensor_prepare_mono (dev->chip, dev->x_dpi)); RIE (usb_mid_motor_prepare_mono (dev->chip, dev->y_dpi)); break; default: DBG (5, "usb_high_scan_prepare_scan: unmatched mode\n"); return SANE_STATUS_INVAL; break; } DBG (5, "usb_high_scan_prepare_scan: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_suggest_parameters (Mustek_Usb_Device * dev, SANE_Word dpi, SANE_Word x, SANE_Word y, SANE_Word width, SANE_Word height, Colormode color_mode) { SANE_Status status; DBG (5, "usb_high_scan_suggest_parameters: start\n"); RIE (usb_high_scan_detect_sensor (dev)); /* Looking up Optical Y Resolution */ RIE (usb_mid_motor_get_dpi (dev->chip, dpi, &dev->y_dpi)); /* Looking up Optical X Resolution */ RIE (usb_mid_sensor_get_dpi (dev->chip, dpi, &dev->x_dpi)); dev->x = x * dev->x_dpi / dpi; dev->y = y * dev->y_dpi / dpi; dev->width = width * dev->x_dpi / dpi; dev->height = height * dev->y_dpi / dpi; switch (color_mode) { case RGB24: dev->scan_mode = RGB24EXT; dev->bytes_per_row = dev->width * 3; dev->bpp = 24; break; case GRAY8: dev->scan_mode = GRAY8EXT; dev->bpp = 8; dev->bytes_per_row = dev->width; break; default: DBG (3, "usb_high_scan_suggest_parameters: unmatched mode\n"); return SANE_STATUS_INVAL; break; } DBG (5, "usb_high_scan_suggest_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_detect_sensor (Mustek_Usb_Device * dev) { if (dev->is_sensor_detected) { DBG (5, "usb_high_scan_detect_sensor: sensor already detected\n"); return SANE_STATUS_GOOD; } dev->is_sensor_detected = SANE_TRUE; switch (dev->chip->scanner_type) { case MT_600CU: dev->chip->sensor = ST_CANON300; dev->chip->motor = MT_600; dev->is_cis_detected = SANE_TRUE; DBG (4, "usb_high_scan_detect_sensor: sensor=Canon 300 dpi, motor=" "600 dpi\n"); break; case MT_1200USB: dev->chip->sensor = ST_NEC600; dev->chip->motor = MT_1200; dev->init_min_expose_time = 2250; dev->init_skips_per_row_600 = 0; dev->init_home_lines = 32; dev->init_dark_lines = 10; dev->init_max_power_delay = 220; dev->init_min_power_delay = 220; dev->init_adjust_way = 3; dev->init_red_rgb_600_pga = 30; dev->init_green_rgb_600_pga = 30; dev->init_blue_rgb_600_pga = 30; dev->init_mono_600_pga = 30; dev->init_expose_time = 16000; dev->init_top_ref = 6; dev->init_front_end = 12; dev->init_red_offset = 128; dev->init_green_offset = 128; dev->init_blue_offset = 128; dev->init_rgb_24_back_track = 0; dev->init_mono_8_back_track = 40; dev->is_cis_detected = SANE_FALSE; DBG (4, "usb_high_scan_detect_sensor: sensor=Canon 600 dpi, motor=" "1200 dpi\n"); break; case MT_1200UB: case MT_1200CU_PLUS: case MT_1200CU: /* need to check if it's a 300600 or 600 dpi sensor */ { SANE_Byte *buffer; static SANE_Word l_temp = 0, r_temp = 0; SANE_Int i; SANE_Status status; SANE_Word lines_left; dev->chip->motor = MT_1200; dev->is_cis_detected = SANE_TRUE; buffer = NULL; l_temp = 0; r_temp = 0; buffer = (SANE_Byte *) malloc (dev->init_bytes_per_strip); if (!buffer) return SANE_STATUS_NO_MEM; for (i = 0; i < 5400; i++) buffer[i] = 0xaa; dev->scan_mode = GRAY8EXT; dev->x_dpi = 600; dev->y_dpi = 1200; dev->width = 5400; RIE (usb_high_scan_init_asic (dev, ST_CANON600)); RIE (usb_low_turn_peripheral_power (dev->chip, SANE_TRUE)); RIE (usb_low_enable_motor (dev->chip, SANE_TRUE)); /* Enable Motor */ RIE (usb_low_turn_lamp_power (dev->chip, SANE_TRUE)); RIE (usb_low_invert_image (dev->chip, SANE_FALSE)); RIE (usb_low_set_image_dpi (dev->chip, SANE_TRUE, SW_P6P6)); dev->bytes_per_strip = dev->adjust_length_600; dev->bytes_per_row = 5400; dev->dummy = 0; RIE (usb_high_scan_wait_carriage_home (dev)); RIE (usb_high_scan_hardware_calibration (dev)); RIE (usb_high_scan_prepare_scan (dev)); /* Get Data */ RIE (usb_low_start_rowing (dev->chip)); RIE (usb_low_get_row (dev->chip, buffer, &lines_left)); RIE (usb_low_stop_rowing (dev->chip)); /* Calculate */ for (i = 0; i < 256; i++) l_temp = l_temp + buffer[512 + i]; for (i = 0; i < 256; i++) r_temp = r_temp + buffer[3500 + i]; l_temp = l_temp / 256; r_temp = r_temp / 256; /* 300/600 switch CIS or 600 CIS */ DBG (5, "usb_high_scan_detect_sensor: l_temp=%d, r_temp=%d\n", l_temp, r_temp); if (r_temp > 50) { dev->chip->sensor = ST_CANON600; DBG (4, "usb_high_scan_detect_sensor: sensor=Canon 600 dpi, motor=" "1200 dpi\n"); } else { DBG (4, "usb_high_scan_detect_sensor: sensor=Canon 300/600 dpi, " "motor=1200 dpi\n"); dev->chip->sensor = ST_CANON300600; } /* Release Resource */ free (buffer); buffer = NULL; break; } default: DBG (5, "usb_high_scan_detect_sensor: I don't know this scanner type " "(%d)\n", dev->chip->scanner_type); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_setup_scan (Mustek_Usb_Device * dev, Colormode color_mode, SANE_Word x_dpi, SANE_Word y_dpi, SANE_Bool is_invert, SANE_Word x, SANE_Word y, SANE_Word width) { SANE_Status status; SANE_Word upper_bound; SANE_Word left_bound; DBG (5, "usb_high_scan_setup_scan: start, is_invert=%d\n", is_invert); if (!dev->is_open) { DBG (5, "usb_high_scan_setup_scan: not open\n"); return SANE_STATUS_INVAL; } if (!dev->is_prepared) { DBG (5, "usb_high_scan_setup_scan: !is_prepared\n"); return SANE_STATUS_INVAL; } RIE (usb_high_scan_init_asic (dev, dev->chip->sensor)); RIE (usb_low_turn_peripheral_power (dev->chip, SANE_TRUE)); RIE (usb_low_enable_motor (dev->chip, SANE_TRUE)); /* Enable Motor */ RIE (usb_low_turn_lamp_power (dev->chip, SANE_TRUE)); RIE (usb_low_invert_image (dev->chip, SANE_FALSE)); if (!dev->is_cis_detected) { usb_mid_front_set_front_end_mode (dev->chip, 16); usb_mid_front_enable (dev->chip, SANE_TRUE); usb_mid_front_set_top_reference (dev->chip, 244); usb_mid_front_set_rgb_signal (dev->chip); } /* Compute necessary variables */ dev->scan_mode = color_mode; dev->x_dpi = x_dpi; dev->y_dpi = y_dpi; dev->width = width; switch (dev->scan_mode) { case RGB24EXT: dev->bytes_per_row = 3 * dev->width; upper_bound = ((y * 600) / dev->y_dpi) + dev->init_j_lines; break; case GRAY8EXT: dev->bytes_per_row = dev->width; upper_bound = ((y * 600) / dev->y_dpi) + dev->init_j_lines + 4; /* fixme */ break; default: upper_bound = ((y * 600) / dev->y_dpi) + dev->init_j_lines + 4; break; } if (usb_mid_sensor_is600_mode (dev->chip, dev->x_dpi)) { /* in 600dpi */ left_bound = (x * 600 / dev->x_dpi) + dev->init_skips_per_row_600; dev->skips_per_row = (((left_bound % 32) * dev->x_dpi + 300) / 600); } else { /* in 300dpi */ left_bound = (x * 300 / dev->x_dpi) + dev->init_skips_per_row_300; dev->skips_per_row = (((left_bound % 32) * dev->x_dpi + 150) / 300); } dev->dummy = (left_bound / 32) * 32; switch (dev->scan_mode) { case RGB24EXT: dev->bytes_per_strip = dev->skips_per_row + dev->width; break; case GRAY8EXT: dev->bytes_per_strip = dev->skips_per_row + dev->width; break; default: break; } dev->bytes_per_strip = ((dev->bytes_per_strip + 1) / 2) * 2; /* make bytes_per_strip is as 2n to advoid 64n+1 */ RIE (usb_high_scan_wait_carriage_home (dev)); RIE (usb_high_scan_hardware_calibration (dev)); RIE (usb_high_scan_line_calibration (dev)); RIE (usb_high_scan_step_forward (dev, upper_bound)); RIE (usb_high_scan_prepare_scan (dev)); RIE (usb_low_start_rowing (dev->chip)); /* pat_chromator fixme (init for calibration?) */ DBG (5, "usb_high_scan_setup_scan: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_get_rows (Mustek_Usb_Device * dev, SANE_Byte * block, SANE_Word rows, SANE_Bool is_order_invert) { SANE_Status status; DBG (5, "usb_high_scan_get_rows: start, %d rows\n", rows); if (!dev->is_open) { DBG (3, "usb_high_scan_get_rows: not open\n"); return SANE_STATUS_INVAL; } if (!dev->is_prepared) { DBG (3, "usb_high_scan_get_rows: !is_prepared\n"); return SANE_STATUS_INVAL; } while (rows > 0) { RIE ((*dev->get_line) (dev, block, is_order_invert)); block += dev->bytes_per_row; rows--; } DBG (5, "usb_high_scan_get_rows: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_stop_scan (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_stop_scan: start\n"); if (!dev->is_open) { DBG (3, "usb_high_scan_stop_scan: not open\n"); return SANE_STATUS_INVAL; } if (!dev->is_prepared) { DBG (3, "usb_high_scan_stop_scan: !is_prepared\n"); return SANE_STATUS_INVAL; } switch (dev->scan_mode) { case RGB24EXT: RIE (usb_high_cal_exit (dev->blue_calibrator)); if (dev->blue_calibrator) free (dev->blue_calibrator); dev->blue_calibrator = NULL; RIE (usb_high_cal_exit (dev->green_calibrator)); if (dev->green_calibrator) free (dev->green_calibrator); dev->green_calibrator = NULL; RIE (usb_high_cal_exit (dev->red_calibrator)); if (dev->red_calibrator) free (dev->red_calibrator); dev->red_calibrator = NULL; break; case GRAY8EXT: RIE (usb_high_cal_exit (dev->mono_calibrator)); if (dev->mono_calibrator) free (dev->mono_calibrator); dev->mono_calibrator = NULL; break; default: break; } RIE (usb_low_stop_rowing (dev->chip)); if (!dev->is_cis_detected) RIE (usb_low_turn_lamp_power (dev->chip, SANE_FALSE)); DBG (5, "usb_high_scan_stop_scan: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_init_asic (Mustek_Usb_Device * dev, Sensor_Type sensor) { SANE_Byte ccd_dpi = 0; SANE_Byte select = 0; SANE_Byte adjust = 0; SANE_Byte pin = 0; SANE_Byte motor = 0; SANE_Bool fix_pattern = SANE_FALSE; SANE_Byte ad_timing = 0; Banksize bank_size; SANE_Status status; DBG (5, "usb_high_scan_init_asic: start\n"); switch (sensor) { case ST_TOSHIBA600: ccd_dpi = 32; select = 240; adjust = 0; pin = 18; motor = 0; fix_pattern = SANE_FALSE; ad_timing = 0; bank_size = BS_16K; DBG (5, "usb_high_scan_init_asic: sensor is set to TOSHIBA600\n"); break; case ST_CANON300: ccd_dpi = 232; select = 232; adjust = 0; pin = 18; motor = 0; fix_pattern = SANE_FALSE; ad_timing = 1; bank_size = BS_4K; DBG (5, "usb_high_scan_init_asic: sensor is set to CANON300\n"); break; case ST_CANON300600: ccd_dpi = 232; select = 232; adjust = 64; pin = 18; motor = 0; fix_pattern = SANE_FALSE; ad_timing = 1; bank_size = BS_16K; DBG (5, "usb_high_scan_init_asic: sensor is set to CANON300600\n"); break; case ST_CANON600: ccd_dpi = 232; select = 232; adjust = 64; pin = 18; motor = 0; fix_pattern = SANE_FALSE; ad_timing = 1; bank_size = BS_16K; DBG (5, "usb_high_scan_init_asic: sensor is set to CANON600\n"); break; case ST_NEC600: /* fixme */ ccd_dpi = 32; select = 224; adjust = 112; pin = 18; motor = 0; fix_pattern = SANE_FALSE; ad_timing = 0; bank_size = BS_16K; DBG (5, "usb_high_scan_init_asic: sensor is set to NEC600\n"); break; default: DBG (5, "usb_high_scan_init_asic: unknown sensor\n"); return SANE_STATUS_INVAL; break; } RIE (usb_low_adjust_timing (dev->chip, adjust)); RIE (usb_low_select_timing (dev->chip, select)); RIE (usb_low_set_timing (dev->chip, ccd_dpi)); RIE (usb_low_set_sram_bank (dev->chip, bank_size)); RIE (usb_low_set_asic_io_pins (dev->chip, pin)); RIE (usb_low_set_rgb_sel_pins (dev->chip, pin)); RIE (usb_low_set_motor_signal (dev->chip, motor)); RIE (usb_low_set_test_sram_mode (dev->chip, SANE_FALSE)); RIE (usb_low_set_fix_pattern (dev->chip, fix_pattern)); RIE (usb_low_set_ad_timing (dev->chip, ad_timing)); DBG (5, "usb_high_scan_init_asic: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_evaluate_max_level (Mustek_Usb_Device * dev, SANE_Word sample_lines, SANE_Int sample_length, SANE_Byte * ret_max_level) { SANE_Byte max_level = 0; SANE_Word i; SANE_Int j; SANE_Status status; SANE_Word lines_left; DBG (5, "usb_high_scan_evaluate_max_level: start\n"); sample_length -= 20; RIE (usb_low_start_rowing (dev->chip)); for (i = 0; i < sample_lines; i++) { RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); for (j = 20; j < sample_length; j++) { if (max_level < dev->green[j]) max_level = dev->green[j]; } } RIE (usb_low_stop_rowing (dev->chip)); if (ret_max_level) *ret_max_level = max_level; DBG (5, "usb_high_scan_evaluate_max_level: exit, max_level = %d\n", max_level); return SANE_STATUS_GOOD; } /* Binary Search for Single Channel Power Delay */ SANE_Status usb_high_scan_bssc_power_delay (Mustek_Usb_Device * dev, Powerdelay_Function set_power_delay, Signal_State * signal_state, SANE_Byte * target, SANE_Byte max, SANE_Byte min, SANE_Byte threshold, SANE_Int length) { SANE_Byte max_level; SANE_Byte max_max = max; SANE_Byte min_min = min; SANE_Status status; DBG (5, "usb_high_scan_bssc_power_delay: start\n"); *target = (max + min) / 2; RIE ((*set_power_delay) (dev->chip, *target)); while (*target != min) { RIE (usb_high_scan_evaluate_max_level (dev, dev->init_powerdelay_lines, length, &max_level)); if (max_level > threshold) { min = *target; *target = (max + min) / 2; *signal_state = SS_BRIGHTER; } else if (max_level < threshold) { max = *target; *target = (max + min) / 2; *signal_state = SS_DARKER; } else if (max_level == threshold) { /* Found. */ *signal_state = SS_EQUAL; return SANE_STATUS_GOOD; } RIE ((*set_power_delay) (dev->chip, *target)); } /* Fail... */ if (max == max_max || min == min_min) { /* Boundary check */ if (max == max_max) /*target on max side */ *target = max_max; else *target = min_min; RIE ((*set_power_delay) (dev->chip, *target)); RIE (usb_high_scan_evaluate_max_level (dev, dev->init_powerdelay_lines, length, &max_level)); if (max_level > threshold) { *signal_state = SS_BRIGHTER; } else if (max_level < threshold) { *signal_state = SS_DARKER; } else if (max_level == threshold) { *signal_state = SS_EQUAL; } } else { /* Fail... will always on mimnum side, make it darker */ target++; *signal_state = SS_DARKER; } DBG (5, "usb_high_scan_bssc_power_delay: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_adjust_rgb_600_power_delay (Mustek_Usb_Device * dev) { SANE_Status status; SANE_Byte max_power_delay; Signal_State signal_state = SS_UNKNOWN; DBG (5, "usb_high_scan_adjust_rgb_600_power_delay: start\n"); max_power_delay = (SANE_Byte) (dev->expose_time / 64); if (dev->is_adjusted_rgb_600_power_delay) return SANE_STATUS_GOOD; /* Setup Initial State */ dev->red_rgb_600_power_delay = max_power_delay; dev->green_rgb_600_power_delay = max_power_delay; dev->blue_rgb_600_power_delay = max_power_delay; RIE (usb_low_set_ccd_width (dev->chip, dev->expose_time)); RIE (usb_mid_front_set_front_end_mode (dev->chip, dev->init_front_end)); RIE (usb_mid_front_set_top_reference (dev->chip, dev->init_top_ref)); RIE (usb_mid_front_set_red_offset (dev->chip, dev->init_red_offset)); RIE (usb_mid_front_set_green_offset (dev->chip, dev->init_green_offset)); RIE (usb_mid_front_set_blue_offset (dev->chip, dev->init_blue_offset)); RIE (usb_mid_front_set_rgb_signal (dev->chip)); RIE (usb_low_set_dummy (dev->chip, dev->init_skips_per_row_600)); RIE (usb_low_set_image_byte_width (dev->chip, dev->adjust_length_600)); RIE (usb_low_set_pixel_depth (dev->chip, PD_8BIT)); /* adjust GreenPD */ RIE (usb_mid_motor_prepare_adjust (dev->chip, CH_GREEN)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, 600)); signal_state = SS_UNKNOWN; RIE (usb_mid_front_set_green_pga (dev->chip, dev->green_rgb_600_pga)); RIE (usb_high_scan_bssc_power_delay (dev, &usb_low_set_green_pd, &signal_state, &dev->green_rgb_600_power_delay, max_power_delay, 0, dev->init_max_power_delay, dev->adjust_length_600)); /* adjust BluePD */ RIE (usb_mid_motor_prepare_adjust (dev->chip, CH_BLUE)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, 600)); signal_state = SS_UNKNOWN; RIE (usb_mid_front_set_blue_pga (dev->chip, dev->blue_rgb_600_pga)); RIE (usb_high_scan_bssc_power_delay (dev, &usb_low_set_blue_pd, &signal_state, &dev->blue_rgb_600_power_delay, max_power_delay, 0, dev->init_max_power_delay, dev->adjust_length_600)); /* adjust RedPD */ RIE (usb_mid_motor_prepare_adjust (dev->chip, CH_RED)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, 600)); signal_state = SS_UNKNOWN; RIE (usb_mid_front_set_red_pga (dev->chip, dev->red_rgb_600_pga)); RIE (usb_high_scan_bssc_power_delay (dev, &usb_low_set_red_pd, &signal_state, &dev->red_rgb_600_power_delay, max_power_delay, 0, dev->init_max_power_delay, dev->adjust_length_600)); dev->is_adjusted_rgb_600_power_delay = SANE_TRUE; DBG (5, "usb_high_scan_adjust_rgb_600_power_delay: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_adjust_mono_600_power_delay (Mustek_Usb_Device * dev) { SANE_Byte max_power_delay; Signal_State signal_state = SS_UNKNOWN; SANE_Status status; DBG (5, "usb_high_scan_adjust_mono_600_power_delay: start\n"); max_power_delay = (SANE_Byte) (dev->expose_time / 64); if (dev->is_adjusted_mono_600_power_delay) return SANE_STATUS_GOOD; /* Setup Initial State */ dev->red_mono_600_power_delay = max_power_delay; dev->green_mono_600_power_delay = max_power_delay; dev->blue_mono_600_power_delay = max_power_delay; /* Compute Gray PD */ RIE (usb_low_set_ccd_width (dev->chip, dev->expose_time)); RIE (usb_mid_front_set_front_end_mode (dev->chip, dev->init_front_end)); RIE (usb_mid_front_set_top_reference (dev->chip, dev->init_top_ref)); RIE (usb_mid_front_set_red_offset (dev->chip, dev->init_red_offset)); RIE (usb_mid_front_set_green_offset (dev->chip, dev->init_green_offset)); RIE (usb_mid_front_set_blue_offset (dev->chip, dev->init_blue_offset)); RIE (usb_mid_front_set_rgb_signal (dev->chip)); RIE (usb_low_set_dummy (dev->chip, dev->init_skips_per_row_600)); RIE (usb_low_set_image_byte_width (dev->chip, dev->adjust_length_600)); RIE (usb_low_set_pixel_depth (dev->chip, PD_8BIT)); /* adjust GreenGrayPD */ RIE (usb_mid_motor_prepare_adjust (dev->chip, CH_GREEN)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, 600)); signal_state = SS_UNKNOWN; RIE (usb_mid_front_set_red_pga (dev->chip, dev->mono_600_pga)); RIE (usb_mid_front_set_green_pga (dev->chip, dev->mono_600_pga)); RIE (usb_mid_front_set_blue_pga (dev->chip, dev->mono_600_pga)); RIE (usb_high_scan_bssc_power_delay (dev, &usb_low_set_green_pd, &signal_state, &dev->green_mono_600_power_delay, max_power_delay, 0, dev->init_max_power_delay, dev->adjust_length_600)); dev->is_adjusted_mono_600_power_delay = SANE_TRUE; DBG (5, "usb_high_scan_adjust_mono_600_power_delay: exit\n"); return SANE_STATUS_GOOD; } /* CCD */ SANE_Status usb_high_scan_adjust_mono_600_exposure (Mustek_Usb_Device * dev) { SANE_Word transfer_time; SANE_Status status; DBG (5, "usb_high_scan_adjust_mono_600_exposure: start\n"); if (dev->is_adjusted_mono_600_exposure) return SANE_STATUS_GOOD; RIE (usb_high_scan_evaluate_pixel_rate (dev)); transfer_time = dev->pixel_rate * dev->x_dpi / 600; if (transfer_time > 16000) transfer_time = 16000; dev->mono_600_exposure = MAX (5504, MAX (transfer_time, usb_mid_motor_mono_capability (dev->chip, dev->y_dpi))); dev->mono_600_exposure = ((dev->mono_600_exposure + 63) / 64) * 64; dev->is_adjusted_mono_600_exposure = SANE_TRUE; DBG (5, "usb_high_scan_adjust_mono_600_exposure: exit\n"); return SANE_STATUS_GOOD; } #if 0 /* CCD */ SANE_Status usb_high_scan_adjust_mono_600_offset (Mustek_Usb_Device * dev) { DBG (5, "usb_high_scan_adjust_mono_600_offset: start\n"); if (dev->is_adjusted_mono_600_offset) return SANE_STATUS_GOOD; DBG (5, "usb_high_scan_adjust_mono_600_offset: exit\n"); return SANE_STATUS_GOOD; } /* CCD */ SANE_Status usb_high_scan_adjust_mono_600_pga (Mustek_Usb_Device * dev) { DBG (5, "usb_high_scan_adjust_mono_600_pga: start (dev = %p)\n", dev); DBG (5, "usb_high_scan_adjust_mono_600_pga: exit\n"); return SANE_STATUS_GOOD; } /* CCD */ SANE_Status usb_high_scan_adjust_mono_600_skips_per_row (Mustek_Usb_Device * dev) { DBG (5, "usb_high_scan_adjust_mono_600_skips_per_row: start (dev = %p)\n", dev); DBG (5, "usb_high_scan_adjust_mono_600_skips_per_row: exit\n"); return SANE_STATUS_GOOD; } #endif SANE_Status usb_high_scan_adjust_rgb_300_power_delay (Mustek_Usb_Device * dev) { /* Setup Initial State */ SANE_Byte max_power_delay; Signal_State signal_state = SS_UNKNOWN; SANE_Status status; DBG (5, "usb_high_scan_adjust_rgb_300_power_delay: start\n"); max_power_delay = (SANE_Byte) (dev->expose_time / 64); if (dev->is_adjusted_rgb_300_power_delay) return SANE_STATUS_GOOD; dev->red_rgb_300_power_delay = max_power_delay; dev->green_rgb_300_power_delay = max_power_delay; dev->blue_rgb_300_power_delay = max_power_delay; RIE (usb_low_set_ccd_width (dev->chip, dev->expose_time)); RIE (usb_mid_front_set_front_end_mode (dev->chip, dev->init_front_end)); RIE (usb_mid_front_set_top_reference (dev->chip, dev->init_top_ref)); RIE (usb_mid_front_set_red_offset (dev->chip, dev->init_red_offset)); RIE (usb_mid_front_set_green_offset (dev->chip, dev->init_green_offset)); RIE (usb_mid_front_set_blue_offset (dev->chip, dev->init_blue_offset)); RIE (usb_mid_front_set_rgb_signal (dev->chip)); RIE (usb_low_set_dummy (dev->chip, dev->init_skips_per_row_300)); RIE (usb_low_set_image_byte_width (dev->chip, dev->adjust_length_300)); RIE (usb_low_set_pixel_depth (dev->chip, PD_8BIT)); /* adjust GreenPD */ RIE (usb_mid_motor_prepare_adjust (dev->chip, CH_GREEN)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, 300)); signal_state = SS_UNKNOWN; RIE (usb_mid_front_set_green_pga (dev->chip, dev->green_rgb_300_pga)); RIE (usb_high_scan_bssc_power_delay (dev, &usb_low_set_green_pd, &signal_state, &dev->green_rgb_300_power_delay, max_power_delay, 0, dev->init_max_power_delay, dev->adjust_length_300)); /* adjust BluePD */ RIE (usb_mid_motor_prepare_adjust (dev->chip, CH_BLUE)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, 300)); signal_state = SS_UNKNOWN; RIE (usb_mid_front_set_blue_pga (dev->chip, dev->blue_rgb_300_pga)); RIE (usb_high_scan_bssc_power_delay (dev, &usb_low_set_blue_pd, &signal_state, &dev->blue_rgb_300_power_delay, max_power_delay, 0, dev->init_max_power_delay, dev->adjust_length_300)); /* adjust RedPD */ RIE (usb_mid_motor_prepare_adjust (dev->chip, CH_RED)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, 300)); signal_state = SS_UNKNOWN; RIE (usb_mid_front_set_red_pga (dev->chip, dev->red_rgb_300_pga)); RIE (usb_high_scan_bssc_power_delay (dev, &usb_low_set_red_pd, &signal_state, &dev->red_rgb_300_power_delay, max_power_delay, 0, dev->init_max_power_delay, dev->adjust_length_300)); dev->is_adjusted_rgb_300_power_delay = SANE_TRUE; DBG (5, "usb_high_scan_adjust_rgb_300_power_delay: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_adjust_mono_300_power_delay (Mustek_Usb_Device * dev) { SANE_Byte max_power_delay; Signal_State signal_state = SS_UNKNOWN; SANE_Status status; DBG (5, "usb_high_scan_adjust_mono_300_power_delay: start\n"); max_power_delay = (SANE_Byte) (dev->expose_time / 64); if (dev->is_adjusted_mono_300_power_delay) return SANE_STATUS_GOOD; /* Setup Initial State */ dev->red_mono_300_power_delay = max_power_delay; dev->green_mono_300_power_delay = max_power_delay; dev->blue_mono_300_power_delay = max_power_delay; /* Compute Gray PD */ RIE (usb_low_set_ccd_width (dev->chip, dev->expose_time)); RIE (usb_mid_front_set_front_end_mode (dev->chip, dev->init_front_end)); RIE (usb_mid_front_set_top_reference (dev->chip, dev->init_top_ref)); RIE (usb_mid_front_set_red_offset (dev->chip, dev->init_red_offset)); RIE (usb_mid_front_set_green_offset (dev->chip, dev->init_green_offset)); RIE (usb_mid_front_set_blue_offset (dev->chip, dev->init_blue_offset)); RIE (usb_mid_front_set_rgb_signal (dev->chip)); RIE (usb_low_set_dummy (dev->chip, dev->init_skips_per_row_300)); RIE (usb_low_set_image_byte_width (dev->chip, dev->adjust_length_300)); RIE (usb_low_set_pixel_depth (dev->chip, PD_8BIT)); /* adjust GreenGrayPD */ RIE (usb_mid_motor_prepare_adjust (dev->chip, CH_GREEN)); RIE (usb_mid_sensor_prepare_rgb (dev->chip, 300)); signal_state = SS_UNKNOWN; RIE (usb_mid_front_set_red_pga (dev->chip, dev->mono_300_pga)); RIE (usb_mid_front_set_green_pga (dev->chip, dev->mono_300_pga)); RIE (usb_mid_front_set_blue_pga (dev->chip, dev->mono_300_pga)); RIE (usb_high_scan_bssc_power_delay (dev, &usb_low_set_green_pd, &signal_state, &dev->green_mono_300_power_delay, max_power_delay, 0, dev->init_max_power_delay, dev->adjust_length_300)); dev->is_adjusted_mono_300_power_delay = SANE_TRUE; DBG (5, "usb_high_scan_adjust_mono_300_power_delay: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_evaluate_pixel_rate (Mustek_Usb_Device * dev) { DBG (5, "usb_high_scan_evaluate_pixel_rate: start, dev=%p\n", (void *) dev); /* fixme: new for CCD */ dev->pixel_rate = 2000; dev->is_evaluate_pixel_rate = SANE_TRUE; DBG (5, "usb_high_scan_evaluate_pixel_rate: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_calibration_rgb_24 (Mustek_Usb_Device * dev) { SANE_Word white_need; SANE_Word dark_need; SANE_Word i; SANE_Status status; SANE_Word lines_left; SANE_Word minor_average; DBG (5, "usb_high_scan_calibration_rgb_24: start, dev=%p\n", (void *) dev); if (dev->is_cis_detected) { RIE (usb_mid_motor_prepare_calibrate_rgb (dev->chip, dev->y_dpi)); RIE (usb_low_turn_lamp_power (dev->chip, SANE_TRUE)); minor_average = 2; } else { minor_average = 1; } dev->red_calibrator = (Calibrator *) malloc (sizeof (Calibrator)); if (!dev->red_calibrator) return SANE_STATUS_NO_MEM; RIE (usb_high_cal_init (dev->red_calibrator, I8O8RGB, dev->init_k_level << 8, 0)); RIE (usb_high_cal_prepare (dev->red_calibrator, dev->width)); RIE (usb_high_cal_embed_gamma (dev->red_calibrator, dev->gamma_table)); RIE (usb_high_cal_setup (dev->red_calibrator, 1, minor_average, 8, dev->width, &white_need, &dark_need)); dev->green_calibrator = (Calibrator *) malloc (sizeof (Calibrator)); if (!dev->green_calibrator) return SANE_STATUS_NO_MEM; RIE (usb_high_cal_init (dev->green_calibrator, I8O8RGB, dev->init_k_level << 8, 0)); RIE (usb_high_cal_prepare (dev->green_calibrator, dev->width)); RIE (usb_high_cal_embed_gamma (dev->green_calibrator, dev->gamma_table)); RIE (usb_high_cal_setup (dev->green_calibrator, 1, minor_average, 8, dev->width, &white_need, &dark_need)); dev->blue_calibrator = (Calibrator *) malloc (sizeof (Calibrator)); if (!dev->blue_calibrator) return SANE_STATUS_NO_MEM; RIE (usb_high_cal_init (dev->blue_calibrator, I8O8RGB, dev->init_k_level << 8, 0)); RIE (usb_high_cal_prepare (dev->blue_calibrator, dev->width)); RIE (usb_high_cal_embed_gamma (dev->blue_calibrator, dev->gamma_table)); RIE (usb_high_cal_setup (dev->blue_calibrator, 1, minor_average, 8, dev->width, &white_need, &dark_need)); /* K White */ RIE (usb_low_start_rowing (dev->chip)); for (i = 0; i < white_need; i++) { /* Read Green Channel */ RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); RIE (usb_high_cal_fill_in_white (dev->green_calibrator, i, 0, (void *) (dev->green + dev->skips_per_row))); RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); RIE (usb_high_cal_fill_in_white (dev->green_calibrator, i, 1, (void *) (dev->green + dev->skips_per_row))); /* Read Blue Channel */ RIE (usb_low_get_row (dev->chip, dev->blue, &lines_left)); RIE (usb_high_cal_fill_in_white (dev->blue_calibrator, i, 0, (void *) (dev->blue + dev->skips_per_row))); RIE (usb_low_get_row (dev->chip, dev->blue, &lines_left)); RIE (usb_high_cal_fill_in_white (dev->blue_calibrator, i, 1, (void *) (dev->blue + dev->skips_per_row))); /* Read Red Channel */ RIE (usb_low_get_row (dev->chip, dev->red, &lines_left)); RIE (usb_high_cal_fill_in_white (dev->red_calibrator, i, 0, (void *) (dev->red + dev->skips_per_row))); RIE (usb_low_get_row (dev->chip, dev->red, &lines_left)); RIE (usb_high_cal_fill_in_white (dev->red_calibrator, i, 1, (void *) (dev->red + dev->skips_per_row))); } RIE (usb_low_stop_rowing (dev->chip)); /* Caculate average */ RIE (usb_high_cal_evaluate_white (dev->green_calibrator, dev->init_green_factor)); RIE (usb_high_cal_evaluate_white (dev->blue_calibrator, dev->init_blue_factor)); RIE (usb_high_cal_evaluate_white (dev->red_calibrator, dev->init_red_factor)); RIE (usb_mid_motor_prepare_calibrate_rgb (dev->chip, dev->y_dpi)); RIE (usb_low_enable_motor (dev->chip, SANE_FALSE)); RIE (usb_low_turn_lamp_power (dev->chip, SANE_FALSE)); /* K Black */ RIE (usb_low_start_rowing (dev->chip)); for (i = 0; i < dark_need; i++) { /* Read Green Channel */ RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); RIE (usb_high_cal_fill_in_dark (dev->green_calibrator, i, 0, (void *) (dev->green + dev->skips_per_row))); RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); RIE (usb_high_cal_fill_in_dark (dev->green_calibrator, i, 1, (void *) (dev->green + dev->skips_per_row))); /* Read Blue Channel */ RIE (usb_low_get_row (dev->chip, dev->blue, &lines_left)); RIE (usb_high_cal_fill_in_dark (dev->blue_calibrator, i, 0, (void *) (dev->blue + dev->skips_per_row))); RIE (usb_low_get_row (dev->chip, dev->blue, &lines_left)); RIE (usb_high_cal_fill_in_dark (dev->blue_calibrator, i, 1, (void *) (dev->blue + dev->skips_per_row))); /* Read Red Channel */ RIE (usb_low_get_row (dev->chip, dev->red, &lines_left)); RIE (usb_high_cal_fill_in_dark (dev->red_calibrator, i, 0, (void *) (dev->red + dev->skips_per_row))); RIE (usb_low_get_row (dev->chip, dev->red, &lines_left)); RIE (usb_high_cal_fill_in_dark (dev->red_calibrator, i, 1, (void *) (dev->red + dev->skips_per_row))); } RIE (usb_low_stop_rowing (dev->chip)); RIE (usb_low_turn_lamp_power (dev->chip, SANE_TRUE)); /* Calculate average */ RIE (usb_high_cal_evaluate_dark (dev->green_calibrator, dev->init_green_black_factor)); RIE (usb_high_cal_evaluate_dark (dev->blue_calibrator, dev->init_blue_black_factor)); RIE (usb_high_cal_evaluate_dark (dev->red_calibrator, dev->init_red_black_factor)); /* Calculate Mapping */ RIE (usb_high_cal_evaluate_calibrator (dev->green_calibrator)); RIE (usb_high_cal_evaluate_calibrator (dev->blue_calibrator)); RIE (usb_high_cal_evaluate_calibrator (dev->red_calibrator)); DBG (5, "usb_high_scan_calibration_rgb_24: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_calibration_mono_8 (Mustek_Usb_Device * dev) { SANE_Word white_need; SANE_Word dark_need; SANE_Word i; SANE_Status status; SANE_Word lines_left; DBG (5, "usb_high_scan_calibration_mono_8: start\n"); RIE (usb_mid_motor_prepare_calibrate_mono (dev->chip, dev->y_dpi)); RIE (usb_low_turn_lamp_power (dev->chip, SANE_TRUE)); dev->mono_calibrator = (Calibrator *) malloc (sizeof (Calibrator)); if (!dev->mono_calibrator) return SANE_STATUS_NO_MEM; RIE (usb_high_cal_init (dev->mono_calibrator, I8O8MONO, dev->init_k_level << 8, 0)); RIE (usb_high_cal_prepare (dev->mono_calibrator, dev->width)); RIE (usb_high_cal_embed_gamma (dev->mono_calibrator, dev->gamma_table)); RIE (usb_high_cal_setup (dev->mono_calibrator, 1, 1, 8, dev->width, &white_need, &dark_need)); /* K White */ RIE (usb_low_start_rowing (dev->chip)); for (i = 0; i < white_need; i++) { /* Read Green Channel */ RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); RIE (usb_high_cal_fill_in_white (dev->mono_calibrator, i, 0, (void *) (dev->green + dev->skips_per_row))); } RIE (usb_low_stop_rowing (dev->chip)); /* Caculate average */ RIE (usb_high_cal_evaluate_white (dev->mono_calibrator, dev->init_gray_factor)); RIE (usb_mid_motor_prepare_calibrate_mono (dev->chip, dev->y_dpi)); RIE (usb_low_enable_motor (dev->chip, SANE_FALSE)); RIE (usb_low_turn_lamp_power (dev->chip, SANE_FALSE)); /* K Black */ RIE (usb_low_start_rowing (dev->chip)); for (i = 0; i < dark_need; i++) { /* Read Green Channel */ RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); RIE (usb_high_cal_fill_in_dark (dev->mono_calibrator, i, 0, (void *) (dev->green + dev->skips_per_row))); } RIE (usb_low_stop_rowing (dev->chip)); RIE (usb_low_turn_lamp_power (dev->chip, SANE_TRUE)); /* Caculate Green Black */ RIE (usb_high_cal_evaluate_dark (dev->mono_calibrator, dev->init_gray_black_factor)); /* Caculate Mapping */ RIE (usb_high_cal_evaluate_calibrator (dev->mono_calibrator)); DBG (5, "usb_high_scan_calibration_mono_8: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_step_forward (Mustek_Usb_Device * dev, SANE_Int step_count) { SANE_Status status; DBG (5, "usb_high_scan_step_forward: start\n"); if (step_count <= 0) return SANE_STATUS_INVAL; /* Initialize */ RIE (usb_low_set_ccd_width (dev->chip, dev->init_min_expose_time)); RIE (usb_low_set_motor_direction (dev->chip, SANE_FALSE)); RIE (usb_mid_motor_prepare_step (dev->chip, (SANE_Word) step_count)); /* Startup */ RIE (usb_low_start_rowing (dev->chip)); /* Wait for stop */ /* Linux USB seems buggy on timeout... sleep before really try */ /* to read the flag from scanner */ usleep (step_count * 2 * 1000); RIE (usb_low_wait_rowing_stop (dev->chip)); if (!dev->is_cis_detected) RIE (usb_low_set_ccd_width (dev->chip, dev->expose_time)); DBG (5, "usb_high_scan_step_forward: start\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_safe_forward (Mustek_Usb_Device * dev, SANE_Int step_count) { SANE_Status status; DBG (5, "usb_high_scan_safe_forward: start\n"); if (step_count <= 0) return SANE_STATUS_INVAL; /* Initialize */ RIE (usb_low_set_ccd_width (dev->chip, 5400)); RIE (usb_low_set_motor_direction (dev->chip, SANE_FALSE)); RIE (usb_mid_motor_prepare_step (dev->chip, (SANE_Word) step_count)); /* Startup */ RIE (usb_low_start_rowing (dev->chip)); /* Wait to Stop */ RIE (usb_low_wait_rowing_stop (dev->chip)); RIE (usb_low_set_ccd_width (dev->chip, dev->expose_time)); DBG (5, "usb_high_scan_safe_forward: exit\n"); return SANE_STATUS_GOOD; } SANE_Word usb_high_scan_calculate_max_rgb_600_expose (Mustek_Usb_Device * dev, SANE_Byte * ideal_red_pd, SANE_Byte * ideal_green_pd, SANE_Byte * ideal_blue_pd) { SANE_Word red_light_up; SANE_Word green_light_up; SANE_Word blue_light_up; SANE_Word max_light_up; SANE_Word ideal_expose_time; DBG (5, "usb_high_scan_calculate_max_rgb_600_expose: dev=%p\n", (void *) dev); red_light_up = dev->expose_time - dev->red_rgb_600_power_delay * 64; green_light_up = dev->expose_time - dev->green_rgb_600_power_delay * 64; blue_light_up = dev->expose_time - dev->blue_rgb_600_power_delay * 64; max_light_up = MAX (red_light_up, MAX (green_light_up, blue_light_up)); if (dev->chip->sensor == ST_NEC600) { ideal_expose_time = MAX (MAX (5504, max_light_up), usb_mid_motor_rgb_capability (dev->chip, dev->y_dpi)); } else { ideal_expose_time = MAX (MAX (5376, max_light_up), usb_mid_motor_rgb_capability (dev->chip, dev->y_dpi)); } ideal_expose_time = (ideal_expose_time + 63) / 64 * 64; *ideal_red_pd = (SANE_Byte) ((ideal_expose_time - red_light_up) / 64); *ideal_green_pd = (SANE_Byte) ((ideal_expose_time - green_light_up) / 64); *ideal_blue_pd = (SANE_Byte) ((ideal_expose_time - blue_light_up) / 64); DBG (5, "usb_high_scan_calculate_max_rgb_600_expose: exit\n"); return ideal_expose_time; } SANE_Word usb_high_scan_calculate_max_mono_600_expose (Mustek_Usb_Device * dev, SANE_Byte * ideal_red_pd, SANE_Byte * ideal_green_pd, SANE_Byte * ideal_blue_pd) { SANE_Word max_light_up; SANE_Word ideal_expose_time; SANE_Word transfer_time; DBG (5, "usb_high_scan_calculate_max_mono_600_expose: dev=%p\n", (void *) dev); max_light_up = dev->expose_time - dev->green_mono_600_power_delay * 64; transfer_time = (SANE_Word) ((SANE_Word) (dev->pixel_rate) * (SANE_Word) (dev->x_dpi) / 600); /* base on 600, but double it. */ if (transfer_time > 16000) transfer_time = 16000; if (dev->chip->sensor == ST_NEC600) { ideal_expose_time = MAX (MAX (5504, max_light_up), MAX (transfer_time, usb_mid_motor_mono_capability (dev->chip, dev->y_dpi))); } else { ideal_expose_time = MAX (MAX (5376, max_light_up), MAX (transfer_time, usb_mid_motor_mono_capability (dev->chip, dev->y_dpi))); } ideal_expose_time = (ideal_expose_time + 63) / 64 * 64; *ideal_red_pd = (SANE_Byte) ((ideal_expose_time) / 64); *ideal_green_pd = (SANE_Byte) ((ideal_expose_time - max_light_up) / 64); *ideal_blue_pd = (SANE_Byte) ((ideal_expose_time) / 64); DBG (5, "usb_high_scan_calculate_max_mono_600_expose: exit\n"); return ideal_expose_time; } SANE_Word usb_high_scan_calculate_max_rgb_300_expose (Mustek_Usb_Device * dev, SANE_Byte * ideal_red_pd, SANE_Byte * ideal_green_pd, SANE_Byte * ideal_blue_pd) { SANE_Word red_light_up; SANE_Word green_light_up; SANE_Word blue_light_up; SANE_Word max_light_up; SANE_Word ideal_expose_time; DBG (5, "usb_high_scan_calculate_max_rgb_300_expose: start\n"); red_light_up = dev->expose_time - dev->red_rgb_300_power_delay * 64; green_light_up = dev->expose_time - dev->green_rgb_300_power_delay * 64; blue_light_up = dev->expose_time - dev->blue_rgb_300_power_delay * 64; max_light_up = MAX (red_light_up, MAX (green_light_up, blue_light_up)); if (dev->chip->sensor == ST_CANON300600) { ideal_expose_time = MAX (MAX (2624, max_light_up), usb_mid_motor_rgb_capability (dev->chip, dev->y_dpi)); } else if (dev->chip->sensor == ST_CANON300) { ideal_expose_time = MAX (MAX (2624, max_light_up), /* fixme? */ usb_mid_motor_rgb_capability (dev->chip, dev->y_dpi)); } else { ideal_expose_time = MAX (MAX (5376, max_light_up), usb_mid_motor_rgb_capability (dev->chip, dev->y_dpi)); } ideal_expose_time = (ideal_expose_time + 63) / 64 * 64; *ideal_red_pd = (SANE_Byte) ((ideal_expose_time - red_light_up) / 64); *ideal_green_pd = (SANE_Byte) ((ideal_expose_time - green_light_up) / 64); *ideal_blue_pd = (SANE_Byte) ((ideal_expose_time - blue_light_up) / 64); DBG (5, "usb_high_scan_calculate_max_rgb_300_expose: exit\n"); return ideal_expose_time; } SANE_Word usb_high_scan_calculate_max_mono_300_expose (Mustek_Usb_Device * dev, SANE_Byte * ideal_red_pd, SANE_Byte * ideal_green_pd, SANE_Byte * ideal_blue_pd) { SANE_Word max_light_up; SANE_Word transfer_time; SANE_Word ideal_expose_time; DBG (5, "usb_high_scan_calculate_max_mono_300_expose: start\n"); max_light_up = dev->expose_time - dev->green_mono_300_power_delay * 64; transfer_time = (SANE_Word) ((SANE_Word) (dev->pixel_rate) * (SANE_Word) (dev->x_dpi) / 600); /* base on 600, but double it. */ if (transfer_time > 16000) transfer_time = 16000; if (dev->chip->sensor == ST_CANON300600) { ideal_expose_time = MAX (MAX (2688, max_light_up), MAX (transfer_time, usb_mid_motor_mono_capability (dev->chip, dev->y_dpi))); } else if (dev->chip->sensor == ST_CANON300) { ideal_expose_time = MAX (MAX (2688, max_light_up), /* fixme? */ MAX (transfer_time, usb_mid_motor_mono_capability (dev->chip, dev-> y_dpi))); } else { ideal_expose_time = MAX (MAX (5376, max_light_up), MAX (transfer_time, usb_mid_motor_mono_capability (dev->chip, dev->y_dpi))); } ideal_expose_time = (ideal_expose_time + 63) / 64 * 64; *ideal_red_pd = (SANE_Byte) ((ideal_expose_time) / 64); *ideal_green_pd = (SANE_Byte) ((ideal_expose_time - max_light_up) / 64); *ideal_blue_pd = (SANE_Byte) ((ideal_expose_time) / 64); DBG (5, "usb_high_scan_calculate_max_mono_300_expose: exit\n"); return ideal_expose_time; } SANE_Status usb_high_scan_prepare_rgb_signal_600_dpi (Mustek_Usb_Device * dev) { SANE_Byte ideal_red_pd, ideal_green_pd, ideal_blue_pd; SANE_Word ideal_expose_time; SANE_Status status; DBG (5, "usb_high_scan_prepare_rgb_signal_600_dpi: start\n"); ideal_expose_time = usb_high_scan_calculate_max_rgb_600_expose (dev, &ideal_red_pd, &ideal_green_pd, &ideal_blue_pd); RIE (usb_low_set_ccd_width (dev->chip, ideal_expose_time)); RIE (usb_mid_front_set_front_end_mode (dev->chip, dev->init_front_end)); RIE (usb_mid_front_set_top_reference (dev->chip, dev->init_top_ref)); RIE (usb_mid_front_set_red_offset (dev->chip, dev->init_red_offset)); RIE (usb_mid_front_set_green_offset (dev->chip, dev->init_green_offset)); RIE (usb_mid_front_set_blue_offset (dev->chip, dev->init_blue_offset)); RIE (usb_mid_front_set_red_pga (dev->chip, dev->red_rgb_600_pga)); RIE (usb_mid_front_set_green_pga (dev->chip, dev->green_rgb_600_pga)); RIE (usb_mid_front_set_blue_pga (dev->chip, dev->blue_rgb_600_pga)); RIE (usb_mid_front_set_rgb_signal (dev->chip)); RIE (usb_low_set_red_pd (dev->chip, ideal_red_pd)); RIE (usb_low_set_green_pd (dev->chip, ideal_green_pd)); RIE (usb_low_set_blue_pd (dev->chip, ideal_blue_pd)); DBG (5, "usb_high_scan_prepare_rgb_signal_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_prepare_mono_signal_600_dpi (Mustek_Usb_Device * dev) { SANE_Byte ideal_red_pd, ideal_green_pd, ideal_blue_pd; SANE_Word ideal_expose_time; SANE_Status status; DBG (5, "usb_high_scan_prepare_mono_signal_600_dpi: start\n"); ideal_expose_time = usb_high_scan_calculate_max_mono_600_expose (dev, &ideal_red_pd, &ideal_green_pd, &ideal_blue_pd); RIE (usb_low_set_ccd_width (dev->chip, ideal_expose_time)); RIE (usb_mid_front_set_front_end_mode (dev->chip, dev->init_front_end)); RIE (usb_mid_front_set_top_reference (dev->chip, dev->init_top_ref)); RIE (usb_mid_front_set_red_offset (dev->chip, dev->init_red_offset)); RIE (usb_mid_front_set_green_offset (dev->chip, dev->init_green_offset)); RIE (usb_mid_front_set_blue_offset (dev->chip, dev->init_blue_offset)); RIE (usb_mid_front_set_red_pga (dev->chip, dev->mono_600_pga)); RIE (usb_mid_front_set_green_pga (dev->chip, dev->mono_600_pga)); RIE (usb_mid_front_set_blue_pga (dev->chip, dev->mono_600_pga)); RIE (usb_mid_front_set_rgb_signal (dev->chip)); RIE (usb_low_set_red_pd (dev->chip, ideal_red_pd)); RIE (usb_low_set_green_pd (dev->chip, ideal_green_pd)); RIE (usb_low_set_blue_pd (dev->chip, ideal_blue_pd)); DBG (5, "usb_high_scan_prepare_mono_signal_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_prepare_rgb_signal_300_dpi (Mustek_Usb_Device * dev) { SANE_Byte ideal_red_pd, ideal_green_pd, ideal_blue_pd; SANE_Word ideal_expose_time; SANE_Status status; DBG (5, "usb_high_scan_prepare_rgb_signal_300_dpi: start\n"); ideal_expose_time = usb_high_scan_calculate_max_rgb_300_expose (dev, &ideal_red_pd, &ideal_green_pd, &ideal_blue_pd); RIE (usb_low_set_ccd_width (dev->chip, ideal_expose_time)); RIE (usb_mid_front_set_front_end_mode (dev->chip, dev->init_front_end)); RIE (usb_mid_front_set_top_reference (dev->chip, dev->init_top_ref)); RIE (usb_mid_front_set_red_offset (dev->chip, dev->init_red_offset)); RIE (usb_mid_front_set_green_offset (dev->chip, dev->init_green_offset)); RIE (usb_mid_front_set_blue_offset (dev->chip, dev->init_blue_offset)); RIE (usb_mid_front_set_red_pga (dev->chip, dev->red_rgb_300_pga)); RIE (usb_mid_front_set_green_pga (dev->chip, dev->green_rgb_300_pga)); RIE (usb_mid_front_set_blue_pga (dev->chip, dev->blue_rgb_300_pga)); RIE (usb_mid_front_set_rgb_signal (dev->chip)); RIE (usb_low_set_red_pd (dev->chip, ideal_red_pd)); RIE (usb_low_set_green_pd (dev->chip, ideal_green_pd)); RIE (usb_low_set_blue_pd (dev->chip, ideal_blue_pd)); DBG (5, "usb_high_scan_prepare_rgb_signal_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_prepare_mono_signal_300_dpi (Mustek_Usb_Device * dev) { /* Setup Scan Here */ SANE_Byte ideal_red_pd, ideal_green_pd, ideal_blue_pd; SANE_Word ideal_expose_time; SANE_Status status; DBG (5, "usb_high_scan_prepare_mono_signal_300_dpi: start\n"); ideal_expose_time = usb_high_scan_calculate_max_mono_300_expose (dev, &ideal_red_pd, &ideal_green_pd, &ideal_blue_pd); RIE (usb_low_set_ccd_width (dev->chip, ideal_expose_time)); RIE (usb_mid_front_set_front_end_mode (dev->chip, dev->init_front_end)); RIE (usb_mid_front_set_top_reference (dev->chip, dev->init_top_ref)); RIE (usb_mid_front_set_red_offset (dev->chip, dev->init_red_offset)); RIE (usb_mid_front_set_green_offset (dev->chip, dev->init_green_offset)); RIE (usb_mid_front_set_blue_offset (dev->chip, dev->init_blue_offset)); RIE (usb_mid_front_set_red_pga (dev->chip, dev->mono_300_pga)); RIE (usb_mid_front_set_green_pga (dev->chip, dev->mono_300_pga)); RIE (usb_mid_front_set_blue_pga (dev->chip, dev->mono_300_pga)); RIE (usb_mid_front_set_rgb_signal (dev->chip)); RIE (usb_low_set_red_pd (dev->chip, ideal_red_pd)); RIE (usb_low_set_green_pd (dev->chip, ideal_green_pd)); RIE (usb_low_set_blue_pd (dev->chip, ideal_blue_pd)); DBG (5, "usb_high_scan_prepare_mono_signal_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_prepare_rgb_24 (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_prepare_rgb_24: start\n"); RIE (usb_low_set_image_byte_width (dev->chip, dev->bytes_per_strip)); RIE (usb_low_set_dummy (dev->chip, dev->dummy)); RIE (usb_low_set_pixel_depth (dev->chip, PD_8BIT)); DBG (5, "usb_high_scan_prepare_rgb_24: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_prepare_mono_8 (Mustek_Usb_Device * dev) { SANE_Status status; DBG (5, "usb_high_scan_prepare_mono_8: start\n"); RIE (usb_low_set_image_byte_width (dev->chip, dev->bytes_per_strip)); RIE (usb_low_set_dummy (dev->chip, dev->dummy)); RIE (usb_low_set_pixel_depth (dev->chip, PD_8BIT)); DBG (5, "usb_high_scan_prepare_mono_8: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_get_rgb_24_bit_line (Mustek_Usb_Device * dev, SANE_Byte * line, SANE_Bool is_order_invert) { SANE_Status status; SANE_Word lines_left; DBG (5, "usb_high_scan_get_rgb_24_bit_line: start, dev=%p, line=%p, " "is_order_invert=%d\n", (void *) dev, line, is_order_invert); RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); RIE (usb_low_get_row (dev->chip, dev->blue, &lines_left)); RIE (usb_low_get_row (dev->chip, dev->red, &lines_left)); RIE (usb_high_cal_calibrate (dev->green_calibrator, dev->green + dev->skips_per_row, line + 1)); RIE (usb_high_cal_calibrate (dev->blue_calibrator, dev->blue + dev->skips_per_row, line + ((is_order_invert) ? 0 : 2))); RIE (usb_high_cal_calibrate (dev->red_calibrator, dev->red + dev->skips_per_row, line + ((is_order_invert) ? 2 : 0))); DBG (5, "usb_high_scan_get_rgb_24_bit_line: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_get_mono_8_bit_line (Mustek_Usb_Device * dev, SANE_Byte * line, SANE_Bool is_order_invert) { SANE_Status status; SANE_Word lines_left; DBG (5, "usb_high_scan_get_mono_8_bit_line: start, dev=%p, line=%p, " "is_order_invert=%d\n", (void *) dev, line, is_order_invert); RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); RIE (usb_high_cal_calibrate (dev->mono_calibrator, dev->green + dev->skips_per_row, line)); DBG (5, "usb_high_scan_get_mono_8_bit_line: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_backtrack_rgb_24 (Mustek_Usb_Device * dev) { DBG (5, "usb_high_scan_backtrack_rgb_24: noop, dev=%p\n", (void *) dev); return SANE_STATUS_GOOD; } SANE_Status usb_high_scan_backtrack_mono_8 (Mustek_Usb_Device * dev) { SANE_Int i; SANE_Status status; SANE_Word lines_left; DBG (5, "usb_high_scan_backtrack_mono_8: start, dev=%p\n", (void *) dev); if (dev->y_dpi >= 300) { RIE (usb_low_stop_rowing (dev->chip)); RIE (usb_low_set_motor_direction (dev->chip, SANE_TRUE)); RIE (usb_low_start_rowing (dev->chip)); for (i = 0; i < dev->init_mono_8_back_track; i++) { RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); } usleep (100 * 1000); RIE (usb_low_stop_rowing (dev->chip)); RIE (usb_low_set_motor_direction (dev->chip, SANE_FALSE)); RIE (usb_low_start_rowing (dev->chip)); for (i = 0; i < dev->init_mono_8_back_track; i++) { RIE (usb_low_get_row (dev->chip, dev->green, &lines_left)); } } DBG (5, "usb_high_scan_backtrack_mono_8: exit\n"); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/microtek2.conf.in0000664000175000017500000000042712112021330015750 00000000000000# See sane-microtek2(5) for a description of the options option dump 1 #option strip-height 14.0 option no-backtrack-option on option lightlid-35 on option toggle-lamp on option lineart-autoadjust on option backend-calibration on #option colorbalance-adjust on scsi * * Scanner sane-backends-1.0.27/backend/mustek_usb_mid.h0000664000175000017500000003250712112021330015764 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Mustek. Originally maintained by Tom Wang Copyright (C) 2001, 2002 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek 1200UB and similar USB flatbed scanners. */ #ifndef mustek_usb_mid_h #define mustek_usb_mid_h #include "mustek_usb_low.h" #include "../include/sane/sane.h" /* ---------------------------------- macros ------------------------------ */ /* ---------------- sensor NEC 600 CCD function declarations -------------- */ static SANE_Status usb_mid_n600_prepare_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_n600_prepare_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_n600_prepare_rgb_600_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_rgb_400_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_rgb_300_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_rgb_200_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_rgb_100_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_rgb_50_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_mono_600_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_mono_400_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_mono_300_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_mono_200_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_mono_100_dpi (ma1017 * chip); static SANE_Status usb_mid_n600_prepare_mono_50_dpi (ma1017 * chip); /* ----------------- sensor 600 CIS function declarations ----------------- */ static SANE_Status usb_mid_c600_prepare_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_c600_prepare_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_c600_prepare_rgb_600_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_rgb_400_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_rgb_300_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_rgb_200_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_rgb_150_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_rgb_100_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_rgb_50_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_mono_600_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_mono_400_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_mono_300_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_mono_200_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_mono_150_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_mono_100_dpi (ma1017 * chip); static SANE_Status usb_mid_c600_prepare_mono_50_dpi (ma1017 * chip); /* -------------- sensor 300/600 CIS function declarations ---------------- */ static SANE_Status usb_mid_c300600_prepare_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_c300600_prepare_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_c300600_prepare_rgb_600_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_rgb_400_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_rgb_300_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_rgb_200_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_rgb_150_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_rgb_100_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_rgb_50_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_mono_600_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_mono_400_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_mono_300_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_mono_200_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_mono_150_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_mono_100_dpi (ma1017 * chip); static SANE_Status usb_mid_c300600_prepare_mono_50_dpi (ma1017 * chip); /* ----------------- sensor 300 CIS function declarations ----------------- */ static SANE_Status usb_mid_c300_prepare_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_c300_prepare_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_c300_prepare_rgb_300_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_rgb_200_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_rgb_150_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_rgb_100_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_rgb_50_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_mono_300_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_mono_200_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_mono_150_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_mono_100_dpi (ma1017 * chip); static SANE_Status usb_mid_c300_prepare_mono_50_dpi (ma1017 * chip); /* --------------------- sensor function declarations -------------------- */ static SANE_Bool usb_mid_sensor_is600_mode (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_sensor_prepare_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_sensor_prepare_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_sensor_get_dpi (ma1017 * chip, SANE_Word wanted_dpi, SANE_Word * dpi); /* ------------------- motor 1200 function declarations ------------------ */ static SANE_Status usb_mid_motor1200_prepare_rgb_1200_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_400_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_600_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_200_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_150_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_100_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_50_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_1200_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_400_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_600_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_200_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_150_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_100_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_50_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_half_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_bi_full_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb_bi_full_x2300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_half_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_bi_full_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_mono_bi_full_x2300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor1200_prepare_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor1200_prepare_calibrate_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor1200_prepare_calibrate_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor1200_prepare_step (ma1017 * chip, SANE_Word step_count); static SANE_Status usb_mid_motor1200_prepare_home (ma1017 * chip); static SANE_Status usb_mid_motor1200_prepare_adjust (ma1017 * chip, Channel channel); static SANE_Word usb_mid_motor1200_rgb_capability (SANE_Word dpi); static SANE_Word usb_mid_motor1200_mono_capability (SANE_Word dpi); /* ---------------600 dpi motor function declarations --------------------- */ static SANE_Status usb_mid_motor600_prepare_rgb_600_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_rgb_200_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_rgb_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_rgb_150_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_rgb_100_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_rgb_50_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_mono_600_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_mono_200_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_mono_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_mono_150_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_mono_100_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_mono_50_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_rgb_half_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_rgb_bi_full_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_mono_half_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_mono_bi_full_300_dpi (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor600_prepare_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor600_prepare_calibrate_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor600_prepare_calibrate_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor600_prepare_step (ma1017 * chip, SANE_Word step_count); static SANE_Status usb_mid_motor600_prepare_home (ma1017 * chip); static SANE_Status usb_mid_motor600_prepare_adjust (ma1017 * chip, Channel channel); static SANE_Word usb_mid_motor600_rgb_capability (SANE_Word dpi); static SANE_Word usb_mid_motor600_mono_capability (SANE_Word dpi); /* ------------------ motor function declarations ------------------------ */ static SANE_Status usb_mid_motor_prepare_home (ma1017 * chip); static SANE_Status usb_mid_motor_prepare_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor_prepare_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor_prepare_adjust (ma1017 * chip, Channel channel); static SANE_Status usb_mid_motor_prepare_calibrate_rgb (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor_prepare_calibrate_mono (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor_prepare_step (ma1017 * chip, SANE_Word step_count); static SANE_Word usb_mid_motor_rgb_capability (ma1017 * chip, SANE_Word dpi); static SANE_Word usb_mid_motor_mono_capability (ma1017 * chip, SANE_Word dpi); static SANE_Status usb_mid_motor_get_dpi (ma1017 * chip, SANE_Word wanted_dpi, SANE_Word * dpi); /* --------------------- frontend function declarations ------------------- */ static SANE_Status usb_mid_front_set_front_end_mode (ma1017 * chip, SANE_Byte mode); static SANE_Status usb_mid_front_enable (ma1017 * chip, SANE_Bool is_enable); static SANE_Status usb_mid_front_set_top_reference (ma1017 * chip, SANE_Byte top); static SANE_Status usb_mid_front_set_red_offset (ma1017 * chip, SANE_Byte offset); static SANE_Status usb_mid_front_set_green_offset (ma1017 * chip, SANE_Byte offset); static SANE_Status usb_mid_front_set_blue_offset (ma1017 * chip, SANE_Byte offset); static SANE_Status usb_mid_front_set_red_pga (ma1017 * chip, SANE_Byte pga); static SANE_Status usb_mid_front_set_green_pga (ma1017 * chip, SANE_Byte pga); static SANE_Status usb_mid_front_set_blue_pga (ma1017 * chip, SANE_Byte pga); static SANE_Status usb_mid_front_set_rgb_signal (ma1017 * chip); #if 0 /* CCD */ static SANE_Word usb_mid_frontend_max_offset_index (ma1017 * chip); #define OFFSET_TABLE_SIZE 256 #endif #endif /* mustek_usb_mid_h */ sane-backends-1.0.27/backend/p5.h0000664000175000017500000001260212775277260013326 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2009-2012 stef.dev@free.fr This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** @file p5.h * @brief Declaration of high level structures used by the p5 backend. * * The structures and functions declared here are used to do the deal with * the SANE API. */ #ifndef P5_H #define P5_H #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" /**< macro to enable an option */ #define ENABLE(OPTION) session->options[OPTION].descriptor.cap &= ~SANE_CAP_INACTIVE /**< macro to disable an option */ #define DISABLE(OPTION) session->options[OPTION].descriptor.cap |= SANE_CAP_INACTIVE /** macro to test is an option is active */ #define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) /**< name of the configuration file */ #define P5_CONFIG_FILE "p5.conf" /**< macro to define texts that should translated */ #ifndef SANE_I18N #define SANE_I18N(text) text #endif /** color mode names */ /* @{ */ #define COLOR_MODE "Color" #define GRAY_MODE "Gray" #define LINEART_MODE "Lineart" /* @} */ #include "p5_device.h" /** * List of all SANE options available for the frontend. Given a specific * device, some options may be set to inactive when the scanner model is * detected. The default values and the ranges they belong maybe also model * dependent. */ enum P5_Options { OPT_NUM_OPTS = 0, /** first enum which must be zero */ /** @name standard options group */ /* @{ */ OPT_STANDARD_GROUP, OPT_MODE, /** set the mode: color, grey levels or lineart */ OPT_PREVIEW, /** set up for preview */ OPT_RESOLUTION, /** set scan's resolution */ /* @} */ /** @name geometry group * geometry related options */ /* @{ */ OPT_GEOMETRY_GROUP, /** group of options defining the position and size of the scanned area */ OPT_TL_X, /** top-left x of the scanned area*/ OPT_TL_Y, /** top-left y of the scanned area*/ OPT_BR_X, /** bottom-right x of the scanned area*/ OPT_BR_Y, /** bottom-right y of the scanned area*/ /* @} */ /** @name sensor group * detectors group */ /* @{ */ OPT_SENSOR_GROUP, OPT_PAGE_LOADED_SW, OPT_NEED_CALIBRATION_SW, /* @} */ /** @name button group * buttons group */ /* @{ */ OPT_BUTTON_GROUP, OPT_CALIBRATE, OPT_CLEAR_CALIBRATION, /* @} */ /** @name option list terminator * must come last so it can be used for array and list size */ NUM_OPTIONS }; /** * Contains one SANE option description and its value. */ typedef struct P5_Option { SANE_Option_Descriptor descriptor; /** option description */ Option_Value value; /** option value */ } P5_Option; /** * Frontend session. This struct holds informations usefull for * the functions defined in SANE's standard. Informations closer * to the hardware are in the P5_Device structure. There is * as many session structure than frontends using the backend. */ typedef struct P5_Session { /** * Point to the next session in a linked list */ struct P5_Session *next; /** * low-level device object used by the session */ P5_Device *dev; /** * array of possible options and their values for the backend */ P5_Option options[NUM_OPTIONS]; /** * SANE_True if a scan is in progress, ie sane_start has been called. * Stay SANE_True until sane_cancel() is called. */ SANE_Bool scanning; /** @brief non blocking flag * SANE_TRUE if sane_read are non-blocking, ie returns immediatly if there * is no data available from the scanning device. Modified by sane_set_io_mode() */ SANE_Bool non_blocking; /** * SANE Parameters describes what the next or current scan will be * according to the current values of the options */ SANE_Parameters params; /** * bytes to send to frontend for the scan */ SANE_Int to_send; /** * bytes currently sent to frontend during the scan */ SANE_Int sent; } P5_Session; static SANE_Status probe_p5_devices (void); static P5_Model *probe (const char *devicename); static SANE_Status config_attach (SANEI_Config * config, const char *devname); static SANE_Status attach_p5 (const char *name, SANEI_Config * config); static SANE_Status init_options (struct P5_Session *session); static SANE_Status compute_parameters (struct P5_Session *session); /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ #endif /* not P5_H */ sane-backends-1.0.27/backend/apple.h0000664000175000017500000001437412112021330014055 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998 Milon Firikis based on David Mosberger-Tang previous Work on mustek.c file from the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef apple_h #define apple_h #include /* Warning: if you uncomment the next line you 'll get zero functionality. All the scanner specific function such as sane_read, attach and the others will return without doing anything. This way you can run the backend without an attached scanner just to see if it gets its control variables in a proper way. TODO: This could be a nice thing to do as a sane config option at runtime. This way one can debug the gui-ipc part of the backend without actually has the scanner. */ #if 0 #define NEUTRALIZE_BACKEND #define APPLE_MODEL_SELECT APPLESCANNER #endif #undef CALIBRATION_FUNCTIONALITY #undef RESERVE_RELEASE_HACK #ifdef RESERVE_RELEASE_HACK /* Also Try these with zero */ #define CONTROLLER_SCSI_ID 7 #define SETTHIRDPARTY 0x10 #endif #define ERROR_MESSAGE 1 #define USER_MESSAGE 5 #define FLOW_CONTROL 50 #define VARIABLE_CONTROL 70 #define DEBUG_SPECIAL 100 #define IO_MESSAGE 110 #define INNER_LOOP 120 /* mode values: */ enum Apple_Modes { APPLE_MODE_LINEART=0, APPLE_MODE_HALFTONE, APPLE_MODE_GRAY, APPLE_MODE_BICOLOR, EMPTY_DONT_USE_IT, APPLE_MODE_COLOR }; enum Apple_Option { OPT_NUM_OPTS = 0, OPT_HWDETECT_GROUP, OPT_MODEL, OPT_MODE_GROUP, OPT_MODE, OPT_RESOLUTION, OPT_PREVIEW, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, /* COMMON */ OPT_BRIGHTNESS, OPT_CONTRAST, OPT_THRESHOLD, /* AppleScanner only */ OPT_GRAYMAP, OPT_AUTOBACKGROUND, OPT_AUTOBACKGROUND_THRESHOLD, /* AppleScanner & OneScanner */ OPT_HALFTONE_PATTERN, OPT_HALFTONE_FILE, /* ColorOneScanner Only */ OPT_VOLT_REF, OPT_VOLT_REF_TOP, OPT_VOLT_REF_BOTTOM, /* misc : advanced */ OPT_MISC_GROUP, /* all */ OPT_LAMP, /* AppleScanner Only */ OPT_WAIT, /* OneScanner only */ OPT_CALIBRATE, OPT_SPEED, /* OneScanner && ColorOneScanner */ OPT_LED, OPT_CCD, /* ColorOneScanner only */ OPT_MTF_CIRCUIT, OPT_ICP, OPT_POLARITY, /* color group : advanced */ OPT_COLOR_GROUP, #ifdef CALIBRATION_FUNCTIONALITY /* OneScanner */ OPT_CALIBRATION_VECTOR, /* ColorOneScanner */ OPT_CALIBRATION_VECTOR_RED, OPT_CALIBRATION_VECTOR_GREEN, OPT_CALIBRATION_VECTOR_BLUE, #endif /* OneScanner && ColorOneScanner */ OPT_DOWNLOAD_CALIBRATION_VECTOR, /* ColorOneScanner */ OPT_CUSTOM_CCT, OPT_CCT, OPT_DOWNLOAD_CCT, OPT_CUSTOM_GAMMA, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_DOWNLOAD_GAMMA, OPT_COLOR_SENSOR, /* must come last: */ NUM_OPTIONS }; /* This is a hack to get fast the model of the Attached Scanner */ /* But it Works well and I am not considering in "fix" it */ enum SCANNERMODEL { OPT_NUM_SCANNERS = 0, APPLESCANNER, ONESCANNER, COLORONESCANNER, NUM_SCANNERS }; typedef struct Apple_Device { struct Apple_Device *next; SANE_Int ScannerModel; SANE_Device sane; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; SANE_Int MaxWidth; SANE_Int MaxHeight; unsigned flags; } Apple_Device; typedef struct Apple_Scanner { /* all the state needed to define a scan request: */ struct Apple_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; /* First we put here all the scan variables */ /* These are needed for converting back and forth the scan area */ SANE_Int bpp; /* The actual bpp, before scaling */ double ulx; double uly; double wx; double wy; SANE_Int ULx; SANE_Int ULy; SANE_Int Width; SANE_Int Height; /* TODO: Initialize this beasts with malloc instead of statically allocation. */ SANE_Int calibration_vector[2550]; SANE_Int calibration_vector_red[2700]; SANE_Int calibration_vector_green[2700]; SANE_Int calibration_vector_blue[2700]; SANE_Fixed cct3x3[9]; SANE_Int gamma_table[3][256]; SANE_Int halftone_pattern[64]; SANE_Bool scanning; SANE_Bool AbortedByUser; int pass; /* pass number */ SANE_Parameters params; int fd; /* SCSI filedescriptor */ /* scanner dependent/low-level state: */ Apple_Device *hw; } Apple_Scanner; #endif /* apple_h */ sane-backends-1.0.27/backend/plustek-pp_image.c0000664000175000017500000014517512775277260016257 00000000000000/* @file plustek-pp_image.c * @brief functions to convert scanner data into image data * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - no changes * - 0.33 - no changes * - 0.34 - reactivated code in imageP96WaitLineData() to recover from * loosing data * - 0.35 - no changes * - 0.36 - removed comment * - added wDither exchange to imageP9xSetupScanSettings * - added fnHalftoneDirect1 which provides dithering by using random * thresholds * - removed the swapping behaviour for model OP_600 in * fnP96ColorDirect() according to the Primax 4800 Direct tests * - changes, due to define renaming * - removed _ASIC_96001 specific stuff to invert colors * - 0.37 - removed // comments * - corrected output of 12bit/pixel * - 0.38 - added P12 stuff * - renamed WaitLineData functions to ReadOneImageLine * - 0.39 - fixed a problem in imageP98003ReadOneImageLine, that causes * these I/O timeouts... * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - fixed a problem for the 12bit modes fo ASIC9800x based devices * - changed include names * - 0.43 - removed floating point stuff * - cleanup * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /************************ local definitions **********************************/ #define _LINE_TIMEOUT (_SECOND * 5 ) /* max 5 second per line ! */ /*************************** local vars **************************************/ static UShort wPreviewScanned = 0; static ExpXStepDef posScan[5] = {{128, 8}, {96, 12}, {96, 24}, {96, 48}, {96, 96}}; static ExpXStepDef negScan[5] = {{128, 8}, {96, 12}, {96, 24}, {96, 48}, {96, 96}}; static ExpXStepDef nmlScan[4][5] = { {{160, 10}, {96, 12}, {96, 24}, {96, 48}, {96, 96}}, /* EPP */ {{160, 10}, {128, 16}, {128, 32}, {192, 96}, {192, 96}}, /* SPP */ {{160, 10}, {96, 12}, {96, 24}, {160, 80}, {160, 160}}, /* BPP */ {{160, 10}, {96, 12}, {96, 24}, {96, 48}, {96, 96}} /* ECP */ }; static ThreshDef xferSpeed[4] = { {0, 3200, 2500}, {0, 1200, 800}, {0, 800, 1250}, {0, 3200, 2500} }; /*************************** local functions *********************************/ /** return the correct DPI-value * The ASIC 96001/3 models are limited to an optical resolution of 300 Dpi * so it´s necessary to scale in X and Y direction (see scale.c)! */ static UShort imageGetPhysDPI( pScanData ps, pImgDef pImgInf, Bool fDpiX ) { if( _IS_ASIC98(ps->sCaps.AsicID)) { if (fDpiX) { if (pImgInf->xyDpi.x > ps->LensInf.rDpiX.wPhyMax) return ps->LensInf.rDpiX.wPhyMax; else return pImgInf->xyDpi.x; } else { if (pImgInf->xyDpi.y > ps->LensInf.rDpiY.wPhyMax) return ps->LensInf.rDpiY.wPhyMax; else return pImgInf->xyDpi.y; } } else { if (fDpiX) { if (pImgInf->wDataType >= COLOR_TRUE24) { if (pImgInf->xyDpi.x > ps->LensInf.rDpiX.wPhyMax) return ps->LensInf.rDpiX.wPhyMax; else return pImgInf->xyDpi.x; } else { if (pImgInf->xyDpi.x > (ps->LensInf.rDpiX.wPhyMax * 2)) return (ps->LensInf.rDpiX.wPhyMax * 2); else return pImgInf->xyDpi.x; } } else { if (pImgInf->wDataType >= COLOR_TRUE24 ) { if (pImgInf->xyDpi.y > (ps->LensInf.rDpiY.wPhyMax / 2)) return (ps->LensInf.rDpiY.wPhyMax / 2); else return pImgInf->xyDpi.y; } else { if (pImgInf->xyDpi.y > ps->LensInf.rDpiY.wPhyMax) return ps->LensInf.rDpiY.wPhyMax; else return pImgInf->xyDpi.y; } } } } /***************************************************************************** * Sampling stuff for ASIC 98003 * *****************************************************************************/ static Bool fnEveryLines( pScanData ps ) { _VAR_NOT_USED( ps ); return _TRUE; } static Bool fnSampleLines( pScanData ps ) { ps->DataInf.wYSum += ps->DataInf.xyAppDpi.y; if( ps->DataInf.wYSum >= ps->DataInf.xyPhyDpi.y ) { ps->DataInf.wYSum -= ps->DataInf.xyPhyDpi.y; return _TRUE; } return _FALSE; } static Bool fnSamplePreview( pScanData ps ) { ps->DataInf.wYSum += wPreviewScanned; if( ps->DataInf.wYSum >= 150 ) { ps->DataInf.wYSum -= 150; return _TRUE; } return _FALSE; } /***************************************************************************** * Data Processing Routines * *****************************************************************************/ static Bool fnReadToDriver( pScanData ps ) { ps->AsicReg.RD_ModeControl = _ModeFifoBSel; IOReadScannerImageData( ps, ps->Scan.BufPut.blue.bp, ps->DataInf.dwAsicBytesPerPlane ); ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, ps->Scan.BufPut.green.bp, ps->DataInf.dwAsicBytesPerPlane ); if( ps->Scan.gd_gk.wGreenKeep ) ps->Scan.gd_gk.wGreenKeep--; else { ps->Scan.BufPut.green.bp += ps->DataInf.dwAsicBytesPerPlane; if( ps->Scan.BufPut.green.bp >= ps->Scan.BufEnd.green.bp ) ps->Scan.BufPut.green.bp = ps->Scan.BufBegin.green.bp; } ps->AsicReg.RD_ModeControl = _ModeFifoRSel; IOReadScannerImageData( ps, ps->Scan.BufPut.red.bp, ps->DataInf.dwAsicBytesPerPlane ); ps->Scan.BufPut.red.bp += ps->DataInf.dwAsicBytesPerPlane; if( ps->Scan.BufPut.red.bp >= ps->Scan.BufEnd.red.bp ) ps->Scan.BufPut.red.bp = ps->Scan.BufBegin.red.bp; if( ps->Scan.bd_rk.wRedKeep ) { ps->Scan.bd_rk.wRedKeep--; return _FALSE; } else { ps->Scan.BufData.green.bp = ps->Scan.BufGet.green.bp; if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) { ps->Scan.BufData.red.bp = ps->Scan.BufGet.blue.bp; ps->Scan.BufData.blue.bp = ps->Scan.BufGet.red.bp; } else { ps->Scan.BufData.red.bp = ps->Scan.BufGet.red.bp; ps->Scan.BufData.blue.bp = ps->Scan.BufGet.blue.bp; } ps->Scan.BufGet.red.bp += ps->DataInf.dwAsicBytesPerPlane; ps->Scan.BufGet.green.bp += ps->DataInf.dwAsicBytesPerPlane; if( ps->Scan.BufGet.red.bp >= ps->Scan.BufEnd.red.bp ) ps->Scan.BufGet.red.bp = ps->Scan.BufBegin.red.bp; if( ps->Scan.BufGet.green.bp >= ps->Scan.BufEnd.green.bp ) ps->Scan.BufGet.green.bp = ps->Scan.BufBegin.green.bp; return _TRUE; } } static Bool fnReadOutScanner( pScanData ps ) { if( ps->Scan.bd_rk.wBlueDiscard ) { ps->Scan.bd_rk.wBlueDiscard--; ps->AsicReg.RD_ModeControl = _ModeFifoBSel; IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf, ps->DataInf.dwAsicBytesPerPlane ); if( ps->Scan.gd_gk.wGreenDiscard ) { ps->Scan.gd_gk.wGreenDiscard--; ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf, ps->DataInf.dwAsicBytesPerPlane); } return _FALSE; } else { IOReadColorData( ps, ps->Bufs.b1.pReadBuf, ps->DataInf.dwAsicBytesPerPlane ); return _TRUE; } } /** Interpolates the gray data by using averaged the continuous pixels */ static void fnP96GrayDirect( pScanData ps, pVoid pBuf, pVoid pImg, ULong bl ) { pUChar src, dest; src = (pUChar)pImg; dest = (pUChar)pBuf; for (; bl; bl--, src++, dest++ ) *dest = ps->pbMapRed [*src]; } /** This routine used in the condition: * 1) The data type is B/W or GrayScale. * 2) The required horizontal resolution doesn't exceed the optic spec. * 3) The required vertical resolution exceeds the optic spec. * So, the vertcal lines have to average with previous line to smooth the * image. */ static void fnDataDirect( pScanData ps, pVoid pBuf, pVoid pImg, ULong bl ) { _VAR_NOT_USED( ps ); memcpy( pBuf, pImg, bl ); } /** According to dither matrix to convert the input gray scale data into * one-bit data. */ static void fnHalftoneDirect0( pScanData ps, pVoid pb, pVoid pImg, ULong bL ) { pUChar pDither, src, dest; ULong dw; src = (pUChar)pImg; dest = (pUChar)pb; pDither = &ps->a_bDitherPattern[ps->dwDitherIndex]; for( ; bL; bL--, dest++, pDither -= 8 ) { for( dw = 8; dw; dw--, src++, pDither++ ) { if( *src < *pDither ) { *dest = (*dest << 1) | 0x01; } else { *dest <<= 1; } } } ps->dwDitherIndex = (ps->dwDitherIndex + 8) & 0x3f; } /** use random generator to make halftoning */ static void fnHalftoneDirect1( pScanData ps, pVoid pb, pVoid pImg, ULong bL ) { pUChar src, dest; UChar threshold; ULong dw; _VAR_NOT_USED( ps ); src = (pUChar)pImg; dest = (pUChar)pb; for (; bL; bL--, dest++ ) { for (dw = 8; dw; dw--, src++ ) { threshold = (UChar)MiscLongRand(); if (*src < threshold ) { *dest = (*dest << 1) | 0x01; } else { *dest <<= 1; } } } } /** Merges the color planes to pixels style without enlarge operation. */ static void fnP98ColorDirect( pScanData ps, pVoid pb, pVoid pImg, ULong bL ) { pUChar src; pRGBByteDef dest; src = (pUChar)pImg; dest = (pRGBByteDef)pb; for ( bL = ps->DataInf.dwAsicPixelsPerPlane; bL; bL--, src++, dest++) { dest->Red = *src; dest->Green = src[ps->DataInf.dwAsicPixelsPerPlane]; dest->Blue = src[ps->DataInf.dwAsicPixelsPerPlane*2]; } } static void fnP96ColorDirect( pScanData ps, pVoid pb, pVoid pImg, ULong bL ) { pUChar src; pRGBByteDef dest; src = (pUChar)pImg; dest = (pRGBByteDef)pb; for ( bL = ps->DataInf.dwAsicPixelsPerPlane; bL; bL--, dest++, src++) { dest->Red =ps->pbMapRed[*src]; dest->Green=ps->pbMapGreen[src[ps->DataInf.dwAsicPixelsPerPlane]]; dest->Blue =ps->pbMapBlue[src[ps->DataInf.dwAsicPixelsPerPlane*2]]; } } /** Merges the color planes to pixels style without enlarge operation. * The scanner returns the pixel data in Motorola-Format, so we have to swap */ static void fnP98Color48( pScanData ps, pVoid pb, pVoid pImg, ULong bL ) { pUShort src; pRGBUShortDef dest; register ULong i; _VAR_NOT_USED( bL ); src = (pUShort)pImg; dest = (pRGBUShortDef)pb; for ( i = ps->DataInf.dwAsicPixelsPerPlane; i; i--, src++, dest++) { dest->Red = *src; dest->Green = src[ps->DataInf.dwAsicPixelsPerPlane]; dest->Blue = src[ps->DataInf.dwAsicPixelsPerPlane * 2]; } } /** prepare for scanning */ static int imageP98SetupScanSettings( pScanData ps, pScanInfo pInf ) { UShort brightness; DBG( DBG_LOW, "imageP98SetupScanSettings()\n" ); ps->DataInf.dwScanFlag = pInf->ImgDef.dwFlag; ps->DataInf.dwVxdFlag = 0; ps->DataInf.crImage = pInf->ImgDef.crArea; /* AdjustOriginXByLens * [NOTE] * Here we just simply adjust it to double (600 DPI is two times of * 300 DPI), but if this model is a multi-lens scanner, we should adjust * it according to different lens. */ ps->DataInf.crImage.x <<= 1; ps->DataInf.xyAppDpi = pInf->ImgDef.xyDpi; ps->DataInf.siBrightness = pInf->siBrightness; ps->DataInf.wDither = pInf->wDither; ps->DataInf.wAppDataType = pInf->ImgDef.wDataType; ps->GetImageInfo( ps, &pInf->ImgDef ); if (ps->DataInf.dwVxdFlag & _VF_DATATOUSERBUFFER) { ps->Scan.DataProcess = fnDataDirect; } if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) { ps->Scan.lBufferAdjust = -(Long)ps->DataInf.dwAppBytesPerLine; } else { ps->Scan.lBufferAdjust = (Long)ps->DataInf.dwAppBytesPerLine; } DBG( DBG_LOW, "Scan settings:\n" ); DBG( DBG_LOW, "ImageInfo: (x=%u,y=%u,dx=%u,dy=%u)\n", ps->DataInf.crImage.x, ps->DataInf.crImage.y, ps->DataInf.crImage.cx, ps->DataInf.crImage.cy ); /* * SetBwBrightness * [NOTE] * * 0 _DEF_BW_THRESHOLD 255 * +-------------------------+--------------------------------+ * |<------- Black --------->|<----------- White ------------>| * So, if user wish to make image darker, the threshold value should be * higher than _defBwThreshold, otherwise it should lower than the * _DefBwThreshold. * Darker = _DefBwThreshold + White * Input / 127; * Input < 0, and White = 255 - _DefBwThreshold, so * = _DefBwThreshold - (255 - _DefBwThreshold) * Input / 127; * The brighter is the same idea. * * CHECK: it seems that the brightness only works for the binary mode ! */ if( ps->DataInf.wPhyDataType != COLOR_BW ) {/* if not line art */ ps->wBrightness = pInf->siBrightness; /* use internal tables for */ ps->wContrast = pInf->siContrast; /* brightness and contrast */ pInf->siBrightness = 0; /* don't use asic for threshold */ } /* CHECK: We have now two methods for setting the brightness... */ DBG( DBG_LOW, "brightness = %i\n", pInf->siBrightness ); if (ps->DataInf.siBrightness < 0) { brightness = (UShort)(_DEF_BW_THRESHOLD - (255 - _DEF_BW_THRESHOLD) * ps->DataInf.siBrightness /127); } else { brightness = (UShort)(_DEF_BW_THRESHOLD - _DEF_BW_THRESHOLD * ps->DataInf.siBrightness /127); } ps->AsicReg.RD_ThresholdControl = brightness; DBG( DBG_LOW, "1. brightness = %i\n", brightness ); if( ps->DataInf.siBrightness >= 0 ) { brightness = (short)((long)(-(255 - _DEF_BW_THRESHOLD) * ps->DataInf.siBrightness) / 127 + _DEF_BW_THRESHOLD); } else { brightness = (short)((long)(_DEF_BW_THRESHOLD * ps->DataInf.siBrightness) / 127 + _DEF_BW_THRESHOLD); } brightness = (brightness ^ 0xff) & 0xff; if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->AsicReg.RD_ThresholdControl = brightness; DBG( DBG_LOW, "2. brightness = %i\n", brightness ); } ps->DataInf.pCurrentBuffer = ps->pScanBuffer1; return _OK; } /** */ static void imageP98DoCopyBuffer( pScanData ps, pUChar pImage ) { memcpy( ps->pFilterBuf, pImage, ps->DataInf.dwAsicBytesPerPlane ); ps->pFilterBuf += 5120; if (ps->pFilterBuf >= ps->pEndBuf) ps->pFilterBuf = ps->pProcessingBuf; } /** */ static Bool imageP98CopyToFilterBuffer( pScanData ps, pUChar pImage ) { if (ps->fDoFilter) { if (ps->fFilterFirstLine) { imageP98DoCopyBuffer( ps, pImage ); imageP98DoCopyBuffer( ps, pImage ); ps->dwLinesFilter--; return _FALSE; } else { imageP98DoCopyBuffer( ps, pImage ); if ((ps->dwLinesFilter--) == 0) imageP98DoCopyBuffer( ps, pImage); } } return _TRUE; } /** */ static void imageP98UnSharpCompare( pScanData ps, Byte Center, Byte Neighbour, pLong pdwNewValue ) { Byte b; b = (Center >= Neighbour) ? Center - Neighbour : Neighbour - Center ; if (b > ps->bOffsetFilter) { *pdwNewValue -= (Long)Neighbour; ps->dwDivFilter--; } } /** */ static void imageP98DoFilter( pScanData ps, pUChar pPut ) { ULong dw; Long dwNewValue; if (ps->fDoFilter && (ps->DataInf.xyAppDpi.x) >= 600UL) { /* DoUnsharpMask(); */ for (dw = 0; dw < ps->DataInf.dwAsicBytesPerPlane - 2; dw++, pPut++) { ps->dwDivFilter = ps->dwMul; dwNewValue = ((ULong)ps->pGet2[dw+1]) * ps->dwMul; imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw], &dwNewValue); imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw+1], &dwNewValue); imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet1[dw+2], &dwNewValue); imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet2[dw], &dwNewValue); imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet2[dw+2], &dwNewValue); imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw], &dwNewValue); imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw+1], &dwNewValue); imageP98UnSharpCompare( ps, ps->pGet2[dw+1], ps->pGet3[dw+2], &dwNewValue); if( dwNewValue > 0 ) { if((dwNewValue /= ps->dwDivFilter) < 255) { *pPut = (Byte) dwNewValue; } else { *pPut = 255; } } else { *pPut = 0; } } pPut = ps->pGet1; ps->pGet1 = ps->pGet2; ps->pGet2 = ps->pGet3; ps->pGet3 = pPut; } } /** */ static Bool imageP98DataIsReady( pScanData ps ) { Byte b; ps->Scan.fMotorBackward = _FALSE; ps->bMoveDataOutFlag = _DataAfterRefreshState; b = (ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? _BLUE_DATA_READY : _GREEN_DATA_READY; while( _TRUE ) { ps->dwColorRunIndex ++; if(ps->pColorRunTable[ps->dwColorRunIndex] & b) break; } if (b == _GREEN_DATA_READY) { ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, ps->DataInf.pCurrentBuffer, ps->DataInf.dwAsicBytesPerPlane ); imageP98CopyToFilterBuffer( ps, ps->DataInf.pCurrentBuffer ); } else { /* ReadColorImageData() */ if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) { ps->AsicReg.RD_ModeControl = _ModeFifoRSel; IOReadScannerImageData( ps, ps->pScanBuffer1 + ps->DataInf.dwAsicBytesPerPlane * 2, ps->DataInf.dwAsicBytesPerPlane ); ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, ps->pScanBuffer1 + ps->DataInf.dwAsicBytesPerPlane, ps->DataInf.dwAsicBytesPerPlane ); ps->AsicReg.RD_ModeControl = _ModeFifoBSel; IOReadScannerImageData( ps, ps->pScanBuffer1, ps->DataInf.dwAsicBytesPerPlane ); } else { IOReadColorData( ps, ps->pScanBuffer1, ps->DataInf.dwAsicBytesPerPlane ); } } if (ps->fFilterFirstLine) { ps->fFilterFirstLine = _FALSE; return _TRUE; } imageP98DoFilter( ps, ps->DataInf.pCurrentBuffer ); (*ps->Scan.DataProcess)( ps, ps->Scan.bp.pMonoBuf, ps->DataInf.pCurrentBuffer, ps->DataInf.dwAppPhyBytesPerLine ); return _TRUE; } /** here we wait for one data-line */ static Bool imageP98001ReadOneImageLine( pScanData ps ) { ULong dwFifoCounter; TimerDef timer; MiscStartTimer( &timer, _LINE_TIMEOUT ); do { ps->Scan.bNowScanState = IOGetScanState( ps, _FALSE ); dwFifoCounter = IOReadFifoLength( ps ); if (!(ps->Scan.bNowScanState & _SCANSTATE_STOP) && (dwFifoCounter < ps->dwMaxReadFifoData)) { if( ps->Scan.bOldScanState != ps->Scan.bNowScanState ) ps->UpdateDataCurrentReadLine( ps ); if( dwFifoCounter >= ps->Scan.dwMinReadFifo ) return imageP98DataIsReady( ps ); } else { /* ScanStateIsStop */ if (dwFifoCounter >= ps->dwSizeMustProcess) return imageP98DataIsReady( ps ); ps->UpdateDataCurrentReadLine( ps ); if( dwFifoCounter >= ps->Scan.dwMinReadFifo ) return imageP98DataIsReady( ps ); } _DODELAY(10); /* delay 10 ms */ } while (!MiscCheckTimer( &timer )); DBG( DBG_HIGH, "Timeout - Scanner malfunction !!\n" ); MotorToHomePosition(ps); /* timed out, scanner malfunction */ return _FALSE; } /** calculate the image properties according to the scanmode */ static void imageP98GetInfo( pScanData ps, pImgDef pImgInf ) { DBG( DBG_LOW, "imageP98GetInfo()\n" ); ps->DataInf.xyPhyDpi.x = imageGetPhysDPI( ps, pImgInf, _TRUE ); ps->DataInf.xyPhyDpi.y = imageGetPhysDPI( ps, pImgInf, _FALSE ); DBG( DBG_LOW, "xyPhyDpi.x = %u, xyPhyDpi.y = %u\n", ps->DataInf.xyPhyDpi.x, ps->DataInf.xyPhyDpi.y ); DBG( DBG_LOW, "crArea.x = %u, crArea.y = %u\n", pImgInf->crArea.x, pImgInf->crArea.y ); DBG( DBG_LOW, "crArea.cx = %u, crArea.cy = %u\n", pImgInf->crArea.cx, pImgInf->crArea.cy ); ps->DataInf.XYRatio = 1000 * ps->DataInf.xyPhyDpi.y/ps->DataInf.xyPhyDpi.x; DBG( DBG_LOW, "xyDpi.x = %u, xyDpi.y = %u, XYRatio = %u\n", pImgInf->xyDpi.x, pImgInf->xyDpi.y, ps->DataInf.XYRatio ); ps->DataInf.dwAppLinesPerArea = (ULong)pImgInf->crArea.cy * pImgInf->xyDpi.y / _MEASURE_BASE; ps->DataInf.dwAppPixelsPerLine = (ULong)pImgInf->crArea.cx * pImgInf->xyDpi.x / _MEASURE_BASE; ps->DataInf.dwPhysBytesPerLine = (ULong)pImgInf->crArea.cx * ps->DataInf.xyPhyDpi.x / _MEASURE_BASE; if( pImgInf->wDataType <= COLOR_HALFTONE ) { ps->DataInf.dwAsicPixelsPerPlane = (ps->DataInf.dwAppPixelsPerLine+7UL)& 0xfffffff8UL; ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppBytesPerLine = ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAsicBytesPerPlane = ps->DataInf.dwAsicPixelsPerPlane>>3; } else { ps->DataInf.dwAsicBytesPerPlane = ps->DataInf.dwAsicPixelsPerPlane = ps->DataInf.dwAppPixelsPerLine; } if( COLOR_TRUE48 == pImgInf->wDataType ) { ps->DataInf.dwAsicBytesPerPlane *= 2; } switch( pImgInf->wDataType ) { case COLOR_BW: ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER; ps->DataInf.wPhyDataType = COLOR_BW; ps->Shade.bIntermediate = _ScanMode_Mono; break; case COLOR_HALFTONE: if( ps->DataInf.wDither == 2 ) { ps->Scan.DataProcess = fnHalftoneDirect1; } else { ps->Scan.DataProcess = fnHalftoneDirect0; } /* * CHANGE: it seems, that we have to use the same settings as for 256GRAY */ ps->DataInf.dwAsicBytesPerPlane = ps->DataInf.dwAsicPixelsPerPlane = ps->DataInf.dwAppPixelsPerLine; ps->DataInf.wPhyDataType = COLOR_256GRAY; ps->Shade.bIntermediate = _ScanMode_Mono; break; case COLOR_256GRAY: ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER; ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine; ps->DataInf.wPhyDataType = COLOR_256GRAY; ps->Shade.bIntermediate = _ScanMode_Mono; break; case COLOR_TRUE24: ps->Scan.DataProcess = fnP98ColorDirect; ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 3; ps->DataInf.wPhyDataType = COLOR_TRUE24; ps->Shade.bIntermediate = _ScanMode_Color; break; case COLOR_TRUE48: ps->Scan.DataProcess = fnP98Color48; ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 6; ps->DataInf.wPhyDataType = COLOR_TRUE48; ps->Shade.bIntermediate = _ScanMode_Color; break; } if (pImgInf->dwFlag & SCANDEF_BoundaryDWORD) { ps->DataInf.dwAppBytesPerLine = (ps->DataInf.dwAppPhyBytesPerLine + 3) & 0xfffffffc; } else { if (pImgInf->dwFlag & SCANDEF_BoundaryWORD) { ps->DataInf.dwAppBytesPerLine = (ps->DataInf.dwAppPhyBytesPerLine + 1) & 0xfffffffe; } else { ps->DataInf.dwAppBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine; } } DBG( DBG_LOW, "AppLinesPerArea = %u\n", ps->DataInf.dwAppLinesPerArea ); DBG( DBG_LOW, "AppPixelsPerLine = %u\n", ps->DataInf.dwAppPixelsPerLine ); DBG( DBG_LOW, "AppPhyBytesPerLine = %u\n", ps->DataInf.dwAppPhyBytesPerLine ); DBG( DBG_LOW, "AppBytesPerLine = %u\n", ps->DataInf.dwAppBytesPerLine ); DBG( DBG_LOW, "AsicPixelsPerPlane = %u\n", ps->DataInf.dwAsicPixelsPerPlane ); DBG( DBG_LOW, "AsicBytesPerPlane = %u\n", ps->DataInf.dwAsicBytesPerPlane ); DBG( DBG_LOW, "AsicBytesPerLine = %u\n", ps->DataInf.dwAsicBytesPerLine ); DBG( DBG_LOW, "Physical Bytes = %u\n", ps->DataInf.dwPhysBytesPerLine ); } /** */ static void imageP96GetInfo( pScanData ps, pImgDef pImgInf ) { DBG( DBG_LOW, "imageP96GetInfo()\n" ); ps->DataInf.xyPhyDpi.x = imageGetPhysDPI( ps, pImgInf, _TRUE ); ps->DataInf.xyPhyDpi.y = imageGetPhysDPI( ps, pImgInf, _FALSE ); DBG( DBG_LOW, "xyPhyDpi.x = %u, xyPhyDpi.y = %u\n", ps->DataInf.xyPhyDpi.x, ps->DataInf.xyPhyDpi.y ); DBG( DBG_LOW, "crArea.x = %u, crArea.y = %u\n", pImgInf->crArea.x, pImgInf->crArea.y ); DBG( DBG_LOW, "crArea.cx = %u, crArea.cy = %u\n", pImgInf->crArea.cx, pImgInf->crArea.cy ); ps->DataInf.XYRatio = 1000 * ps->DataInf.xyPhyDpi.y/ps->DataInf.xyPhyDpi.x; DBG( DBG_LOW, "xyDpi.x = %u, xyDpi.y = %u, XYRatio = %u\n", pImgInf->xyDpi.x, pImgInf->xyDpi.y, ps->DataInf.XYRatio ); ps->DataInf.dwAppLinesPerArea = (ULong)pImgInf->crArea.cy * pImgInf->xyDpi.y / _MEASURE_BASE; ps->DataInf.dwAsicBytesPerPlane = ps->DataInf.dwAsicPixelsPerPlane = (ULong)ps->DataInf.xyPhyDpi.x * pImgInf->crArea.cx / _MEASURE_BASE; ps->DataInf.dwAppPixelsPerLine = (ULong)pImgInf->crArea.cx * pImgInf->xyDpi.x / _MEASURE_BASE; ps->DataInf.dwPhysBytesPerLine = (ULong)pImgInf->crArea.cx * ps->DataInf.xyPhyDpi.x / _MEASURE_BASE; ps->DataInf.wPhyDataType = ps->DataInf.wAppDataType; switch( pImgInf->wDataType ) { case COLOR_BW: ps->DataInf.dwAsicBytesPerPlane = (ps->DataInf.dwAsicPixelsPerPlane + 7) >> 3; ps->DataInf.dwAppPhyBytesPerLine = (ps->DataInf.dwAppPixelsPerLine + 7) >> 3; ps->DataInf.dwVxdFlag |= _VF_DATATOUSERBUFFER; ps->Scan.DataProcess = fnDataDirect; break; case COLOR_HALFTONE: ps->DataInf.dwAppPhyBytesPerLine = (ps->DataInf.dwAsicPixelsPerPlane + 7) >> 3; if( ps->DataInf.wDither == 2 ) { ps->Scan.DataProcess = fnHalftoneDirect1; } else { ps->Scan.DataProcess = fnHalftoneDirect0; } ps->DataInf.wPhyDataType = COLOR_256GRAY; break; case COLOR_256GRAY: ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine; ps->Scan.DataProcess = fnP96GrayDirect; break; case COLOR_TRUE24: #ifdef _A3I_EN ps->Scan.DataProcess = fnP98ColorDirect; #else ps->Scan.DataProcess = fnP96ColorDirect; #endif ps->DataInf.dwAppPhyBytesPerLine = ps->DataInf.dwAppPixelsPerLine * 3; } if( pImgInf->dwFlag & SCANDEF_BoundaryDWORD ) { ps->DataInf.dwAppBytesPerLine = (ps->DataInf.dwAppPhyBytesPerLine + 3) & 0xfffffffc; } else { if ( pImgInf->dwFlag & SCANDEF_BoundaryWORD ) { ps->DataInf.dwAppBytesPerLine = (ps->DataInf.dwAppPhyBytesPerLine + 1) & 0xfffffffe; } else { ps->DataInf.dwAppBytesPerLine = ps->DataInf.dwAppPhyBytesPerLine; } } if (ps->DataInf.wPhyDataType == COLOR_TRUE24) ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAsicBytesPerPlane * 3; else ps->DataInf.dwAsicBytesPerLine = ps->DataInf.dwAsicBytesPerPlane; /* WORK: AsicBytesPerLine only used for ASIC_98001 based scanners - try to remove ** that, also try to remove redundant info */ DBG( DBG_LOW, "AppLinesPerArea = %u\n", ps->DataInf.dwAppLinesPerArea ); DBG( DBG_LOW, "AppPixelsPerLine = %u\n", ps->DataInf.dwAppPixelsPerLine ); DBG( DBG_LOW, "AppPhyBytesPerLine = %u\n", ps->DataInf.dwAppPhyBytesPerLine ); DBG( DBG_LOW, "AppBytesPerLine = %u\n", ps->DataInf.dwAppBytesPerLine ); DBG( DBG_LOW, "AsicPixelsPerPlane = %u\n", ps->DataInf.dwAsicPixelsPerPlane ); DBG( DBG_LOW, "AsicBytesPerPlane = %u\n", ps->DataInf.dwAsicBytesPerPlane ); DBG( DBG_LOW, "AsicBytesPerLine = %u\n", ps->DataInf.dwAsicBytesPerLine ); DBG( DBG_LOW, "Physical Bytes = %u\n", ps->DataInf.dwPhysBytesPerLine ); } /** here we wait for one data-line */ static Bool imageP96ReadOneImageLine( pScanData ps ) { Bool result = _FALSE; Byte bData, bFifoCount; TimerDef timer; MiscStartTimer( &timer, _LINE_TIMEOUT); do { bFifoCount = IODataRegisterFromScanner( ps, ps->RegFifoOffset ); /* CHECK ps->bMoveDataOutFlag will never be set to _DataFromStopState !!!*/ #if 1 if ((bFifoCount < ps->bMinReadFifo) && (ps->bMoveDataOutFlag == _DataFromStopState)) { bData = IOGetScanState( ps, _FALSE); if (!(bData & _SCANSTATE_STOP)) { if (bData < ps->bCurrentLineCount) bData += _NUMBER_OF_SCANSTEPS; if ((bData - ps->bCurrentLineCount) < _SCANSTATE_BYTES) continue; } ps->bMoveDataOutFlag = _DataAfterRefreshState; } #endif /* // HEINER:A3I // if( ps->bMoveDataOutFlag != _DataFromStopState ) // ps->UpdateDataCurrentReadLine( ps ); */ if( bFifoCount >= ps->bMinReadFifo ) { /* data is ready */ for (; !(*ps->pCurrentColorRunTable & (ps->RedDataReady | ps->GreenDataReady | _BLUE_DATA_READY)); ps->pCurrentColorRunTable++); #ifdef DEBUG if( ps->pCurrentColorRunTable > (ps->pColorRunTable+ps->BufferForColorRunTable)) DBG( DBG_LOW, "WARNING: pCurrentColorRunTab>pColorRunTable\n"); #endif if (ps->DataInf.wPhyDataType == COLOR_TRUE24) { /* read color planes (either R/G/B or R/B/G sequence that * depends on COLOR CCD, see below */ if (*ps->pCurrentColorRunTable & ps->b1stColor) { *ps->pCurrentColorRunTable &= ps->b1stMask; IOReadScannerImageData (ps, ps->pPutBufR, ps->DataInf.dwAsicBytesPerPlane); ps->pPutBufR += ps->BufferSizePerModel; if (ps->pPutBufR == ps->pEndBufR) ps->pPutBufR = ps->pPrescan16; } else if (*ps->pCurrentColorRunTable & ps->b2ndColor) { *ps->pCurrentColorRunTable &= ps->b2ndMask; IOReadScannerImageData( ps, ps->pPutBufG, ps->DataInf.dwAsicBytesPerPlane); ps->pPutBufG += ps->BufferSizePerModel; if (ps->pPutBufG == ps->pEndBufG) ps->pPutBufG = ps->pPrescan8; } else { *ps->pCurrentColorRunTable &= ps->b3rdMask; ps->pCurrentColorRunTable++; /* processed this step */ /* according to CCD type & image placement method to * read third color into corresponding location. * SONY CCD: Red, Green and Blue. * TOSHIBA CCD: Red, Blue and Green. * SCANDEF_BmpStyle: Blue, Green and Red, Otherwise * Red, Green and Blue. */ if (ps->b3rdColor & ps->GreenDataReady) { /* Green always in middle */ IOReadScannerImageData (ps, ps->DataInf.pCurrentBuffer + ps->DataInf.dwAsicBytesPerPlane, ps->DataInf.dwAsicBytesPerPlane); } else { /* Blue depends the request style from caller */ if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) { /* BMP style, blue is the first one */ IOReadScannerImageData (ps, ps->DataInf.pCurrentBuffer, ps->DataInf.dwAsicBytesPerPlane); } else { /* Blue is the last one */ IOReadScannerImageData (ps, ps->DataInf.pCurrentBuffer + ps->DataInf.dwAsicBytesPerPlane * 2, ps->DataInf.dwAsicBytesPerPlane); } } /* reassemble 3 color lines for separated RGB value */ if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) { /* BMP style, red is last one */ memcpy( ps->DataInf.pCurrentBuffer + ps->DataInf.dwAsicBytesPerPlane * 2, ps->pGetBufR, ps->DataInf.dwAsicBytesPerPlane); } else { /* Red is first one */ memcpy( ps->DataInf.pCurrentBuffer, ps->pGetBufR, ps->DataInf.dwAsicBytesPerPlane ); } if (ps->b2ndColor & ps->GreenDataReady) { /* Green always in middle */ memcpy( ps->DataInf.pCurrentBuffer + ps->DataInf.dwAsicBytesPerPlane, ps->pGetBufG, ps->DataInf.dwAsicBytesPerPlane); } else { /* Blue depends the request style from caller */ if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) { /* BMP style, blue is the first one */ memcpy( ps->DataInf.pCurrentBuffer, ps->pGetBufG, ps->DataInf.dwAsicBytesPerPlane); } else { /* BMP style, blue is the last one */ memcpy( ps->DataInf.pCurrentBuffer + ps->DataInf.dwAsicBytesPerPlane * 2, ps->pGetBufG, ps->DataInf.dwAsicBytesPerPlane ); } } /* Adjust the get pointers */ ps->pGetBufR += ps->BufferSizePerModel; ps->pGetBufG += ps->BufferSizePerModel; if (ps->pGetBufR == ps->pEndBufR) ps->pGetBufR = ps->pPrescan16; if (ps->pGetBufG == ps->pEndBufG) ps->pGetBufG = ps->pPrescan8; result = _TRUE; /* Line data in buffer */ break; } /* reset timer for new 10-second interval */ MiscStartTimer( &timer, (10 * _SECOND)); } else { /* Gray Image */ *ps->pCurrentColorRunTable &= 0xf0; /* leave high nibble for debug */ ps->pCurrentColorRunTable++; /* this step has been processed */ IOReadScannerImageData( ps, ps->DataInf.pCurrentBuffer, ps->DataInf.dwAsicBytesPerPlane ); result = _TRUE; break; } } /* HEINER:A3I */ if( ps->bMoveDataOutFlag != _DataFromStopState ) ps->UpdateDataCurrentReadLine( ps ); } while (!MiscCheckTimer( &timer)); if( _TRUE == result ) { (*ps->Scan.DataProcess)( ps, ps->Scan.bp.pMonoBuf, ps->DataInf.pCurrentBuffer, ps->DataInf.dwAppPhyBytesPerLine ); return _TRUE; } DBG( DBG_HIGH, "Timeout - Scanner malfunction !!\n" ); MotorToHomePosition(ps); return _FALSE; } /** prepare for scanning */ static int imageP96SetupScanSettings( pScanData ps, pScanInfo pInf ) { DBG( DBG_LOW, "imageSetupP96ScanSettings()\n" ); ps->DataInf.dwVxdFlag = 0; if (pInf->ImgDef.dwFlag & SCANDEF_BuildBwMap) ps->DataInf.dwVxdFlag |= _VF_BUILDMAP; ps->DataInf.dwScanFlag = pInf->ImgDef.dwFlag; ps->DataInf.crImage = pInf->ImgDef.crArea; /* scale according to DPI */ ps->DataInf.crImage.x *= ps->PhysicalDpi / _MEASURE_BASE; ps->DataInf.crImage.cx *= ps->PhysicalDpi / _MEASURE_BASE; if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { ps->DataInf.crImage.x += _Transparency48OriginOffsetX; ps->DataInf.crImage.y += _Transparency48OriginOffsetY; } ps->DataInf.xyAppDpi = pInf->ImgDef.xyDpi; ps->DataInf.wAppDataType = pInf->ImgDef.wDataType; ps->DataInf.wDither = pInf->wDither; ps->GetImageInfo( ps, &pInf->ImgDef ); /* try to get brightness to work */ if (ps->DataInf.wPhyDataType != COLOR_BW) { /* if not line art */ ps->wBrightness = pInf->siBrightness; /* use internal tables for */ ps->wContrast = pInf->siContrast; /* brightness and contrast */ pInf->siBrightness = 0; /* don't use asic for threshold */ } ps->DataInf.siBrightness = pInf->siBrightness; if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) ps->Scan.lBufferAdjust = -(Long)ps->DataInf.dwAppBytesPerLine; else ps->Scan.lBufferAdjust = (Long)ps->DataInf.dwAppBytesPerLine; if (ps->DataInf.siBrightness < 0) ps->DataInf.siBrightness = 255 - (_DEF_BW_THRESHOLD * ps->DataInf.siBrightness / 127 + _DEF_BW_THRESHOLD); else ps->DataInf.siBrightness = 255 - ((255 - _DEF_BW_THRESHOLD) * ps->DataInf.siBrightness / 127 + _DEF_BW_THRESHOLD); ps->AsicReg.RD_ThresholdControl = (Byte)ps->DataInf.siBrightness; ps->DataInf.pCurrentBuffer = ps->pScanBuffer1; return _OK; } /** */ static Bool imageP98003DataIsReady( pScanData ps ) { pUChar pb; if( ps->Scan.bDiscardAll ) { ps->Scan.bDiscardAll--; if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) { ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, ps->Bufs.b1.pReadBuf, ps->DataInf.dwAsicBytesPerPlane ); } else { IOReadColorData( ps, ps->Bufs.b1.pReadBuf, ps->DataInf.dwAsicBytesPerPlane ); } return _FALSE; } if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) { ps->AsicReg.RD_ModeControl = _ModeFifoGSel; pb = ps->Scan.bp.pMonoBuf; /* use a larger buffer during halftone reads...*/ if( ps->DataInf.wAppDataType == COLOR_HALFTONE ) pb = ps->Scan.BufPut.red.bp; IOReadScannerImageData( ps, pb, ps->DataInf.dwAsicBytesPerPlane ); } else { if( !ps->Scan.DataRead( ps )) { return _FALSE; } } if( ps->Scan.DoSample( ps )) { if( ps->Scan.dwLinesToRead == 1 && !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP)) IORegisterToScanner( ps, ps->RegRefreshScanState ); /* direct is done here without copying...*/ if( fnDataDirect != ps->Scan.DataProcess ) { (*ps->Scan.DataProcess)(ps, (pVoid)(ps->Scan.bp.pMonoBuf ), (pVoid)(ps->Scan.BufPut.red.bp), ps->DataInf.dwAppPhyBytesPerLine); } return _TRUE; } return _FALSE; } /** */ static Bool imageP98003ReadOneImageLine( pScanData ps ) { Byte b, state; TimerDef timer, t2; MiscStartTimer( &timer, _LINE_TIMEOUT ); MiscStartTimer( &t2, _SECOND*2 ); do { state = IOGetScanState( ps, _TRUE ); ps->Scan.bNowScanState = (state & _SCANSTATE_MASK); if( state & _SCANSTATE_STOP ) { MotorP98003ModuleForwardBackward( ps ); if( IOReadFifoLength( ps ) >= ps->Scan.dwMinReadFifo ) if( imageP98003DataIsReady( ps )) return _TRUE; } else { ps->Scan.bModuleState = _MotorInNormalState; b = ps->Scan.bNowScanState - ps->Scan.bOldScanState; if((char) b < 0) b += _NUMBER_OF_SCANSTEPS; if( b >= ps->Scan.bRefresh ) { IORegisterToScanner( ps, ps->RegRefreshScanState ); ps->Scan.bOldScanState = IOGetScanState( ps, _TRUE ); ps->Scan.bOldScanState &= _SCANSTATE_MASK; } if( IOReadFifoLength( ps ) >= ps->Scan.dwMaxReadFifo ) { if( imageP98003DataIsReady( ps )) return _TRUE; } else { b = ps->Scan.bNowScanState - ps->Scan.bOldScanState; if((char) b < 0) b += _NUMBER_OF_SCANSTEPS; if( b >= ps->Scan.bRefresh ) { IORegisterToScanner( ps, ps->RegRefreshScanState ); ps->Scan.bOldScanState = IOGetScanState( ps, _TRUE ); ps->Scan.bOldScanState &= _SCANSTATE_MASK; } if( IOReadFifoLength( ps ) >= ps->Scan.dwMinReadFifo ) { if( imageP98003DataIsReady( ps )) return _TRUE; } } } _DODELAY(5); /* delay 5 ms */ } while( !MiscCheckTimer( &timer )); #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "Timeout - Scanner malfunction !!\n" ); MotorToHomePosition(ps); /* timed out, scanner malfunction */ return _FALSE; } /** */ static void imageP98003SetupScanStateVariables( pScanData ps, ULong index ) { DataType var; ps->Scan.dpiIdx = index; if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) { if(((ps->IO.portMode == _PORT_BIDI) || (ps->IO.portMode == _PORT_SPP)) && (ps->DataInf.wPhyDataType > COLOR_TRUE24) && (ps->DataInf.xyAppDpi.y >= 600)) { ps->Shade.wExposure = nmlScan[ps->IO.portMode][index].exposureTime; ps->Shade.wXStep = nmlScan[ps->IO.portMode][index].xStepTime; } else { ps->Shade.wExposure = nmlScan[_PORT_EPP][index].exposureTime; ps->Shade.wXStep = nmlScan[_PORT_EPP][index].xStepTime; } if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) { ps->Shade.wExposure >>= 1; ps->Shade.wXStep >>= 1; } } else { if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) { ps->Shade.wExposure = posScan[index].exposureTime; ps->Shade.wXStep = posScan[index].xStepTime; } else { ps->Shade.wExposure = ps->Scan.negScan[index].exposureTime; ps->Shade.wXStep = ps->Scan.negScan[index].xStepTime; } } ps->Scan.dwInterlace = 0; ps->Scan.dwInterval = 1; if( ps->DataInf.wPhyDataType == COLOR_BW ) var.dwValue = xferSpeed[ps->IO.portMode].thresholdBW; else { if( ps->DataInf.wPhyDataType == COLOR_256GRAY ) var.dwValue = xferSpeed[ps->IO.portMode].thresholdGray; else var.dwValue = xferSpeed[ps->IO.portMode].thresholdColor; } /* for small size/descreen */ if((ps->DataInf.xyAppDpi.y >= 300) && var.dwValue && (ps->DataInf.dwAsicBytesPerPlane <= var.dwValue)) { ps->Scan.dwInterval <<= 1; } if( var.dwValue && ps->DataInf.dwAsicBytesPerPlane > var.dwValue ) { if((var.dwValue << 1) > ps->DataInf.dwAsicBytesPerPlane) ps->Scan.dwInterval <<= 1; else if((var.dwValue << 2) > ps->DataInf.dwAsicBytesPerPlane) ps->Scan.dwInterval <<= 2; else ps->Scan.dwInterval <<= 3; } /* 48 bit/600 dpi/Bpp mode will scan failed */ if(((ps->IO.portMode == _PORT_BIDI) || (ps->IO.portMode == _PORT_SPP)) && (ps->DataInf.wPhyDataType > COLOR_TRUE24) && (ps->DataInf.xyAppDpi.y >= 600)) { ps->Scan.dwInterval <<= 1; } if( ps->DataInf.wPhyDataType >= COLOR_TRUE24 ) { if( ps->DataInf.xyPhyDpi.y > 75U ) { if( ps->Device.f0_8_16 ) { ps->Scan.gd_gk.wGreenDiscard = ps->DataInf.xyPhyDpi.y / 75U; } else { ps->Scan.gd_gk.wGreenDiscard = ps->DataInf.xyPhyDpi.y / 150U; } } else { ps->Scan.gd_gk.wGreenDiscard = 1; } ps->Scan.bd_rk.wBlueDiscard = ps->Scan.gd_gk.wGreenDiscard << 1; } else { ps->Scan.bd_rk.wBlueDiscard = ps->Scan.gd_gk.wGreenDiscard = 0; } } /** PrepareScanningVariables() !!! */ static int imageP98003SetupScanSettings( pScanData ps, pScanInfo pInf ) { DBG( DBG_LOW, "imageP98003SetupScanSettings()\n" ); /* call the one for ASIC 98001 first */ imageP98SetupScanSettings( ps, pInf ); if( !(ps->DataInf.dwScanFlag & SCANDEF_TPA )) { ps->Scan.dwScanOrigin = ps->Device.lUpNormal * 4 + _RFT_SCANNING_ORG; } else if( ps->DataInf.dwScanFlag & SCANDEF_Transparency) { ps->Scan.dwScanOrigin = ps->Device.lUpPositive * 4 + _POS_SCANNING_ORG; } else { ps->Scan.dwScanOrigin = ps->Device.lUpNegative * 4 + _NEG_SCANNING_ORG; } ps->Scan.dwScanOrigin += ps->Device.dwModelOriginY; /* ------- Setup CCD Offset variables ------- */ if( ps->DataInf.xyAppDpi.y <= 75 ) { if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) { ps->Scan.bDiscardAll = 0; ps->DataInf.xyPhyDpi.y = 150; ps->Shade.bIntermediate |= _ScanMode_AverageOut; imageP98003SetupScanStateVariables( ps, 1 ); ps->Scan.gd_gk.wGreenDiscard = 0; if( ps->DataInf.xyAppDpi.y >= 38 ) ps->Scan.bd_rk.wBlueDiscard = 1; else ps->Scan.bd_rk.wBlueDiscard = 0; if( ps->DataInf.wPhyDataType >= COLOR_256GRAY ) { ps->Shade.wXStep = 6; ps->Shade.wExposure = 8 * ps->Shade.wXStep; } } else { if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA) && (ps->DataInf.xyAppDpi.y <= 50) && (ps->DataInf.wPhyDataType >= COLOR_TRUE24)) { ps->Shade.bIntermediate |= _ScanMode_AverageOut; } if((ps->DataInf.wPhyDataTypeDevice.f0_8_16 || (ps->Shade.bIntermediate & _ScanMode_AverageOut)) { ps->Scan.bDiscardAll = 1; ps->DataInf.xyPhyDpi.y = 75; imageP98003SetupScanStateVariables( ps, 0 ); } else { ps->Scan.bDiscardAll = 2; ps->DataInf.xyPhyDpi.y = 150; imageP98003SetupScanStateVariables( ps, 1 ); } } } else { if( ps->DataInf.xyAppDpi.y <= 150 ) { ps->Scan.bDiscardAll = 2; ps->DataInf.xyPhyDpi.y = 150; imageP98003SetupScanStateVariables( ps, 1 ); } else if( ps->DataInf.xyAppDpi.y <= 300 ) { ps->Scan.bDiscardAll = 4; ps->DataInf.xyPhyDpi.y = 300; imageP98003SetupScanStateVariables( ps, 2 ); } else if( ps->DataInf.xyAppDpi.y <= 600 ) { ps->Scan.bDiscardAll = 8; ps->DataInf.xyPhyDpi.y = 600; imageP98003SetupScanStateVariables( ps, 3 ); } else { ps->Scan.bDiscardAll = 16; ps->DataInf.xyPhyDpi.y = 1200; imageP98003SetupScanStateVariables( ps, 4 ); } } /* ------- Lines have to sample or not? ------- */ if( ps->DataInf.xyAppDpi.y == ps->DataInf.xyPhyDpi.y ) { DBG( DBG_LOW, "Sample every line\n" ); ps->Scan.DoSample = fnEveryLines; } else { if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) { DBG( DBG_LOW, "Sample preview\n" ); ps->Scan.DoSample = fnSamplePreview; ps->DataInf.wYSum = 150; if( ps->DataInf.xyAppDpi.y >= 38 ) wPreviewScanned = ps->DataInf.xyAppDpi.y * 2; else if( ps->DataInf.xyAppDpi.y >= 19 ) wPreviewScanned = ps->DataInf.xyAppDpi.y * 4; else wPreviewScanned = ps->DataInf.xyAppDpi.y * 8; } else { DBG( DBG_LOW, "Sample lines (%u - %u)...\n", ps->DataInf.xyPhyDpi.y, ps->DataInf.xyAppDpi.y ); ps->Scan.DoSample = fnSampleLines; ps->DataInf.wYSum = ps->DataInf.xyPhyDpi.y - ps->DataInf.xyAppDpi.y; } } /* * now assign the buffer pointers for image aquisition */ ps->Scan.p48BitBuf.pb = NULL; if( ps->DataInf.wPhyDataType >= COLOR_TRUE24 ) { ULong r,g,b; r = (ULong)_SIZE_REDFIFO / ps->DataInf.dwAsicBytesPerPlane - ps->Scan.bd_rk.wRedKeep; g = (ULong)_SIZE_GREENFIFO / ps->DataInf.dwAsicBytesPerPlane - ps->Scan.gd_gk.wGreenKeep; if((int)r < 16 || (int)g < 16) { b = (ULong)(ps->Scan.bd_rk.wRedKeep + ps->Scan.gd_gk.wGreenKeep + 2U) * ps->DataInf.dwAsicBytesPerPlane; DBG( DBG_LOW, "48Bit buffer request: len=%u bytes, available=%u\n", b, ps->TotalBufferRequire ); if( b > ps->TotalBufferRequire ) return _E_NORESOURCE; ps->Scan.p48BitBuf.pb = ps->Bufs.b1.pReadBuf; } } if( ps->Scan.p48BitBuf.pb ){ ps->Scan.DataRead = fnReadToDriver; ps->Scan.BufGet.red.bp = ps->Scan.BufPut.red.bp = ps->Scan.BufBegin.red.bp = ps->Scan.p48BitBuf.pb; ps->Scan.BufEnd.red.bp = ps->Scan.BufBegin.green.bp = ps->Scan.BufGet.green.bp = ps->Scan.BufPut.green.bp = ps->Scan.p48BitBuf.pb + ps->DataInf.dwAsicBytesPerLine * (ps->Scan.bd_rk.wRedKeep + 1U); ps->Scan.BufEnd.green.bp = ps->Scan.BufBegin.green.bp + ps->DataInf.dwAsicBytesPerLine * (ps->Scan.gd_gk.wGreenKeep + 1U); ps->Scan.BufPut.blue.bp = ps->Scan.BufGet.blue.bp = ps->Bufs.b1.pReadBuf + ps->DataInf.dwAsicBytesPerLine * 2; } else { ps->Scan.DataRead = fnReadOutScanner; ps->Scan.BufPut.red.bp = ps->Bufs.b1.pReadBuf; ps->Scan.BufData.green.bp = ps->Scan.BufPut.green.bp = ps->Scan.BufPut.red.bp + ps->DataInf.dwAsicBytesPerLine; ps->Scan.BufPut.blue.bp = ps->Scan.BufPut.green.bp + ps->DataInf.dwAsicBytesPerLine; if( ps->DataInf.dwScanFlag & SCANDEF_ColorBGROrder ) { ps->Scan.BufData.red.bp = ps->Scan.BufPut.blue.bp; ps->Scan.BufData.blue.bp = ps->Scan.BufPut.red.bp; } else { ps->Scan.BufData.red.bp = ps->Scan.BufPut.red.bp; ps->Scan.BufData.blue.bp = ps->Scan.BufPut.blue.bp; } } /* CHECK: maybe remove this stuff */ if( ps->DataInf.dwScanFlag & SCANDEF_Transparency) { posScan[1].exposureTime = 96; posScan[1].xStepTime = 12; posScan[2].exposureTime = 96; posScan[2].xStepTime = 24; posScan[3].exposureTime = 96; posScan[3].xStepTime = 48; posScan[4].exposureTime = 96; posScan[4].xStepTime = 96; /* Reset shading Exposure Time & xStep Time */ ps->Shade.wExposure = posScan[ps->Scan.dpiIdx].exposureTime; ps->Shade.wXStep = posScan[ps->Scan.dpiIdx].xStepTime; } else if( ps->DataInf.dwScanFlag & SCANDEF_Negative) { ps->Scan.negScan[1].exposureTime = 96; ps->Scan.negScan[1].xStepTime = 12; ps->Scan.negScan[2].exposureTime = 96; ps->Scan.negScan[2].xStepTime = 24; ps->Scan.negScan[3].exposureTime = 96; ps->Scan.negScan[3].xStepTime = 48; ps->Scan.negScan[4].exposureTime = 96; ps->Scan.negScan[4].xStepTime = 96; /* Reset shading Exposure Time & xStep Time */ ps->Shade.wExposure = ps->Scan.negScan[ps->Scan.dpiIdx].exposureTime; ps->Shade.wXStep = ps->Scan.negScan[ps->Scan.dpiIdx].xStepTime; } return _OK; } /************************ exported functions *********************************/ /** */ _LOC int ImageInitialize( pScanData ps ) { DBG( DBG_HIGH, "ImageInitialize()\n" ); if( NULL == ps ) return _E_NULLPTR; ps->Scan.dpiIdx = 0; ps->Scan.negScan = negScan; /* * depending on the asic, we set some functions */ if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ps->GetImageInfo = imageP98GetInfo; ps->SetupScanSettings = imageP98SetupScanSettings; ps->ReadOneImageLine = imageP98001ReadOneImageLine; } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->GetImageInfo = imageP98GetInfo; ps->SetupScanSettings = imageP98003SetupScanSettings; ps->ReadOneImageLine = imageP98003ReadOneImageLine; } else if( _IS_ASIC96(ps->sCaps.AsicID)) { ps->GetImageInfo = imageP96GetInfo; ps->SetupScanSettings = imageP96SetupScanSettings; ps->ReadOneImageLine = imageP96ReadOneImageLine; } else { DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); return _E_NOSUPP; } return _OK; } /* END PLUSTEK-PP_IMAGE.C ...................................................*/ sane-backends-1.0.27/backend/plustek-usbimg.c0000664000175000017500000013621312112021330015717 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbimg.c * @brief Image processing functions for copying and scaling image lines. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2007 Gerhard Jaeger * * History: * - 0.40 - starting version of the USB support * - 0.41 - fixed the 14bit problem for LM9831 devices * - 0.42 - no changes * - 0.43 - no changes * - 0.44 - added CIS parts and dumpPic function * - 0.45 - added gray scaling functions for CIS devices * - fixed usb_GrayScale16 function * - fixed a bug in usb_ColorScale16_2 function * - fixed endless loop bug * - fixed a bug in usb_GrayScalePseudo16 function * - fixed a bug in usb_GrayDuplicatePseudo16 function * - removed the scaler stuff for CIS devices * - 0.46 - minor fixes * - 0.47 - added big-endian/little endian stuff * - 0.48 - fixed usb_ColorDuplicateGray16() and * usb_ColorScaleGray16() * - added usb_BWScaleFromColor() and usb_BWDuplicateFromColor() * - cleanup * - 0.49 - a_bRegs is now part of the device structure * - 0.50 - cleanup * - 0.51 - added usb_ColorDuplicateGray16_2(), usb_ColorScaleGray16_2() * usb_BWScaleFromColor_2() and usb_BWDuplicateFromColor_2() * - 0.52 - cleanup * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #define _SCALER 1000 static u_char bShift, Shift; static u_short wSum, Mask; /* */ static u_char BitTable[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static u_char BitsReverseTable[256] = { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; /************************ some helper functions ******************************/ static void ReverseBits( int b, u_char **pTar, int *iByte, int *iWeightSum, int iSrcWeight, int iTarWeight, int cMax ) { int bit; cMax = (1 << cMax); if(iSrcWeight == iTarWeight) { for( bit = 1; bit < cMax; bit <<= 1) { *iByte <<= 1; if(b & bit) *iByte |= 1; if(*iByte >= 0x100) { **pTar++ = (u_char)*iByte; *iByte = 1; } } } else { for( bit = 1; bit < cMax; bit <<= 1 ) { *iWeightSum += iTarWeight; while(*iWeightSum >= iSrcWeight) { *iWeightSum -= iSrcWeight; *iByte <<= 1; if(b & bit) *iByte |= 1; if(*iByte >= 0x100) { **pTar++ = (u_char)*iByte; *iByte = 1; } } } } } static void usb_ReverseBitStream( u_char *pSrc, u_char *pTar, int iPixels, int iBufSize, int iSrcWeight/* = 0*/, int iTarWeight/* = 0*/, int iPadBit/* = 1*/) { int i; int iByte = 1; int cBytes = iPixels / 8; int cBits = iPixels % 8; u_char bPad = iPadBit? 0xff: 0; u_char *pTarget = pTar; int iWeightSum = 0; if(iSrcWeight == iTarWeight) { if(cBits) { int cShift = 8 - cBits; for(i = cBytes, pSrc = pSrc + cBytes - 1; i > 0; i--, pSrc--, pTar++) *pTar = BitsReverseTable[(u_char)((*pSrc << cBits) | (*(pSrc+1) >> cShift))]; ReverseBits(*(pSrc+1) >> cShift, &pTar, &iByte, &iWeightSum, iSrcWeight, iTarWeight, cBits); } else /* byte boundary */ { for(i = cBytes, pSrc = pSrc + cBytes - 1; i > 0; i--, pSrc--, pTar++) *pTar = BitsReverseTable[*pSrc]; } } else /* To shrink or enlarge */ { if(cBits) { int cShift = 8 - cBits; for(i = cBytes, pSrc = pSrc + cBytes - 1; i > 0; i--, pSrc--) ReverseBits((*pSrc << cBits) | (*(pSrc+1) >> cShift), &pTar, &iByte, &iWeightSum, iSrcWeight, iTarWeight, 8); ReverseBits(*(pSrc+1) >> cShift, &pTar, &iByte, &iWeightSum, iSrcWeight, iTarWeight, cBits); } else /* byte boundary */ { for(i = cBytes, pSrc = pSrc + cBytes - 1; i > 0; i--, pSrc--) ReverseBits(*pSrc, &pTar, &iByte, &iWeightSum, iSrcWeight, iTarWeight, 8); } } if(iByte != 1) { while(iByte < 0x100) { iByte <<= 1; iByte |= iPadBit; } *pTar++ = (u_char)iByte; } cBytes = (int)(pTar - pTarget); for(i = iBufSize - cBytes; i > 0; i--, pTar++) *pTar = bPad; } /** */ static void usb_AverageColorByte( Plustek_Device *dev ) { u_long dw; ScanDef *scan = &dev->scanning; if((scan->sParam.bSource == SOURCE_Negative || scan->sParam.bSource == SOURCE_Transparency) && scan->sParam.PhyDpi.x > 800) { for (dw = 0; dw < (scan->sParam.Size.dwPhyPixels - 1); dw++) { scan->Red.pcb[dw].a_bColor[0] = (u_char)(((u_short)scan->Red.pcb[dw].a_bColor[0] + (u_short)scan->Red.pcb[dw + 1].a_bColor[0]) / 2); scan->Green.pcb[dw].a_bColor[0] = (u_char)(((u_short)scan->Green.pcb[dw].a_bColor[0] + (u_short)scan->Green.pcb[dw + 1].a_bColor[0]) / 2); scan->Blue.pcb[dw].a_bColor[0] = (u_char)(((u_short)scan->Blue.pcb[dw].a_bColor[0] + (u_short)scan->Blue.pcb[dw + 1].a_bColor[0]) / 2); } } } /** */ static void usb_AverageColorWord( Plustek_Device *dev ) { u_char ls = 2; u_long dw; ScanDef *scan = &dev->scanning; if((scan->sParam.bSource == SOURCE_Negative || scan->sParam.bSource == SOURCE_Transparency) && scan->sParam.PhyDpi.x > 800) { scan->Red.pcw[0].Colors[0] = _HILO2WORD(scan->Red.pcw[0].HiLo[0]) >> ls; scan->Green.pcw[0].Colors[0] = _HILO2WORD(scan->Green.pcw[0].HiLo[0]) >> ls; scan->Blue.pcw[0].Colors[0] = _HILO2WORD(scan->Blue.pcw[0].HiLo[0]) >> ls; for (dw = 0; dw < (scan->sParam.Size.dwPhyPixels - 1); dw++) { scan->Red.pcw[dw + 1].Colors[0] = _HILO2WORD(scan->Red.pcw[dw + 1].HiLo[0]) >> ls; scan->Green.pcw[dw + 1].Colors[0] = _HILO2WORD(scan->Green.pcw[dw + 1].HiLo[0]) >> ls; scan->Blue.pcw[dw + 1].Colors[0] = _HILO2WORD(scan->Blue.pcw[dw + 1].HiLo[0]) >> ls; scan->Red.pcw[dw].Colors[0] = (u_short)(((u_long)scan->Red.pcw[dw].Colors[0] + (u_long)scan->Red.pcw[dw + 1].Colors[0]) / 2); scan->Green.pcw[dw].Colors[0] = (u_short)(((u_long)scan->Green.pcw[dw].Colors[0] + (u_long)scan->Green.pcw[dw + 1].Colors[0]) / 2); scan->Blue.pcw[dw].Colors[0] = (u_short)(((u_long)scan->Blue.pcw[dw].Colors[0] + (u_long)scan->Blue.pcw[dw + 1].Colors[0]) / 2); scan->Red.pcw[dw].Colors[0] = _HILO2WORD(scan->Red.pcw[dw].HiLo[0]) << ls; scan->Green.pcw[dw].Colors[0] = _HILO2WORD(scan->Green.pcw[dw].HiLo[0]) << ls; scan->Blue.pcw[dw].Colors[0] = _HILO2WORD(scan->Blue.pcw[dw].HiLo[0]) << ls; } scan->Red.pcw[dw].Colors[0] = _HILO2WORD(scan->Red.pcw[dw].HiLo[0]) << ls; scan->Green.pcw[dw].Colors[0] = _HILO2WORD(scan->Green.pcw[dw].HiLo[0]) << ls; scan->Blue.pcw[dw].Colors[0] = _HILO2WORD(scan->Blue.pcw[dw].HiLo[0]) << ls; } } /** */ static void usb_AverageGrayByte( Plustek_Device *dev ) { u_long dw; ScanDef *scan = &dev->scanning; if((scan->sParam.bSource == SOURCE_Negative || scan->sParam.bSource == SOURCE_Transparency) && scan->sParam.PhyDpi.x > 800) { for (dw = 0; dw < (scan->sParam.Size.dwPhyPixels - 1); dw++) scan->Green.pb[dw] = (u_char)(((u_short)scan->Green.pb[dw]+ (u_short)scan->Green.pb[dw+1]) / 2); } } /** */ static void usb_AverageGrayWord( Plustek_Device *dev ) { u_long dw; ScanDef *scan = &dev->scanning; if((scan->sParam.bSource == SOURCE_Negative || scan->sParam.bSource == SOURCE_Transparency) && scan->sParam.PhyDpi.x > 800) { scan->Green.pw[0] = _HILO2WORD(scan->Green.philo[0]) >> 2; for (dw = 0; dw < (scan->sParam.Size.dwPhyPixels - 1); dw++) { scan->Green.pw[dw + 1] = _HILO2WORD(scan->Green.philo[dw+1]) >> 2; scan->Green.pw[dw] = (u_short)(((u_long)scan->Green.pw[dw]+ (u_long)scan->Green.pw[dw+1]) / 2); scan->Green.pw[dw] = _HILO2WORD(scan->Green.philo[dw]) << 2; } scan->Green.pw[dw] = _HILO2WORD(scan->Green.philo[dw]) << 2; } } /** * returns the zoom value, used for our scaling algorithm (DDA algo * digital differential analyzer). */ static int usb_GetScaler( ScanDef *scan ) { double ratio; ratio = (double)scan->sParam.UserDpi.x/ (double)scan->sParam.PhyDpi.x; return (int)(1.0/ratio * _SCALER); } /******************************* the copy functions **************************/ /** do a simple memcopy from scan-buffer to user buffer */ static void usb_ColorDuplicate8( Plustek_Device *dev ) { int next; u_long dw, pixels; ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } for( dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next ) { scan->UserBuf.pb_rgb[pixels].Red = scan->Red.pcb[dw].a_bColor[0]; scan->UserBuf.pb_rgb[pixels].Green = scan->Green.pcb[dw].a_bColor[0]; scan->UserBuf.pb_rgb[pixels].Blue = scan->Blue.pcb[dw].a_bColor[0]; } } /** reorder from rgb line to rgb pixel (CIS scanner) */ static void usb_ColorDuplicate8_2( Plustek_Device *dev ) { int next; u_long dw, pixels; ScanDef *scan = &dev->scanning; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } for( dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next ) { scan->UserBuf.pb_rgb[pixels].Red = (u_char)scan->Red.pb[dw]; scan->UserBuf.pb_rgb[pixels].Green = (u_char)scan->Green.pb[dw]; scan->UserBuf.pb_rgb[pixels].Blue = (u_char)scan->Blue.pb[dw]; } } /** */ static void usb_ColorDuplicate16( Plustek_Device *dev ) { int next; u_char ls; u_long dw, pixels; ScanDef *scan = &dev->scanning; SANE_Bool swap = usb_HostSwap(); usb_AverageColorWord( dev ); if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { if( swap ) { scan->UserBuf.pw_rgb[pixels].Red = _HILO2WORD(scan->Red.pcw[dw].HiLo[0]) >> ls; scan->UserBuf.pw_rgb[pixels].Green = _HILO2WORD(scan->Green.pcw[dw].HiLo[0]) >> ls; scan->UserBuf.pw_rgb[pixels].Blue = _HILO2WORD(scan->Blue.pcw[dw].HiLo[0]) >> ls; } else { scan->UserBuf.pw_rgb[pixels].Red = scan->Red.pw[dw] >> ls; scan->UserBuf.pw_rgb[pixels].Green= scan->Green.pw[dw] >> ls; scan->UserBuf.pw_rgb[pixels].Blue = scan->Blue.pw[dw] >> ls; } } } /** */ static void usb_ColorDuplicate16_2( Plustek_Device *dev ) { int next; u_char ls; HiLoDef tmp; u_long dw, pixels; ScanDef *scan = &dev->scanning; SANE_Bool swap = usb_HostSwap(); usb_AverageColorWord( dev ); if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; for( dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { if( swap ) { tmp = *((HiLoDef*)&scan->Red.pw[dw]); scan->UserBuf.pw_rgb[pixels].Red = _HILO2WORD(tmp) >> ls; tmp = *((HiLoDef*)&scan->Green.pw[dw]); scan->UserBuf.pw_rgb[pixels].Green = _HILO2WORD(tmp) >> ls; tmp = *((HiLoDef*)&scan->Blue.pw[dw]); scan->UserBuf.pw_rgb[pixels].Blue = _HILO2WORD(tmp) >> ls; } else { scan->UserBuf.pw_rgb[pixels].Red = scan->Red.pw[dw] >> ls; scan->UserBuf.pw_rgb[pixels].Green = scan->Green.pw[dw] >> ls; scan->UserBuf.pw_rgb[pixels].Blue = scan->Blue.pw[dw] >> ls; } } } /** */ static void usb_ColorDuplicatePseudo16( Plustek_Device *dev ) { int next; u_short wR, wG, wB; u_long dw, pixels; ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); if (scan->sParam.bSource == SOURCE_ADF) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } wR = (u_short)scan->Red.pcb[0].a_bColor[0]; wG = (u_short)scan->Green.pcb[0].a_bColor[0]; wB = (u_short)scan->Blue.pcb[0].a_bColor[0]; for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { scan->UserBuf.pw_rgb[pixels].Red = (wR + scan->Red.pcb[dw].a_bColor[0]) << bShift; scan->UserBuf.pw_rgb[pixels].Green = (wG + scan->Green.pcb[dw].a_bColor[0]) << bShift; scan->UserBuf.pw_rgb[pixels].Blue = (wB + scan->Blue.pcb[dw].a_bColor[0]) << bShift; wR = (u_short)scan->Red.pcb[dw].a_bColor[0]; wG = (u_short)scan->Green.pcb[dw].a_bColor[0]; wB = (u_short)scan->Blue.pcb[dw].a_bColor[0]; } } /** */ static void usb_ColorDuplicateGray( Plustek_Device *dev ) { int next; u_long dw, pixels; ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); if (scan->sParam.bSource == SOURCE_ADF) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } switch(scan->fGrayFromColor) { case 1: for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pb[pixels] = scan->Red.pcb[dw].a_bColor[0]; break; case 2: for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pb[pixels] = scan->Green.pcb[dw].a_bColor[0]; break; case 3: for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pb[pixels] = scan->Blue.pcb[dw].a_bColor[0]; break; } } /** */ static void usb_ColorDuplicateGray_2( Plustek_Device *dev ) { int next; u_long dw, pixels; ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); if (scan->sParam.bSource == SOURCE_ADF) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } switch(scan->fGrayFromColor) { case 1: for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pb[pixels] = scan->Red.pb[dw]; break; case 3: for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pb[pixels] = scan->Blue.pb[dw]; break; default: for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pb[pixels] = scan->Green.pb[dw]; break; } } /** */ static void usb_ColorDuplicateGray16( Plustek_Device *dev ) { int next; u_char ls; u_long dw, pixels; ScanDef *scan = &dev->scanning; SANE_Bool swap = usb_HostSwap(); usb_AverageColorWord( dev ); if (scan->sParam.bSource == SOURCE_ADF) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; switch(scan->fGrayFromColor) { case 1: if( swap ) { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pw[pixels] = _HILO2WORD(scan->Red.pcw[dw].HiLo[0]) >> ls; } else { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pw[pixels] = scan->Red.pw[dw] >> ls; } break; case 2: if( swap ) { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pw[pixels] = _HILO2WORD(scan->Green.pcw[dw].HiLo[0]) >> ls; } else { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pw[pixels] = scan->Green.pw[dw] >> ls; } break; case 3: if( swap ) { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pw[pixels] = _HILO2WORD(scan->Blue.pcw[dw].HiLo[0]) >> ls; } else { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) scan->UserBuf.pw[pixels] = scan->Blue.pw[dw] >> ls; } break; } } /** */ static void usb_ColorDuplicateGray16_2( Plustek_Device *dev ) { int next; u_char ls; u_long dw, pixels; HiLoDef tmp; ScanDef *scan = &dev->scanning; SANE_Bool swap = usb_HostSwap(); usb_AverageColorWord( dev ); if (scan->sParam.bSource == SOURCE_ADF) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; switch(scan->fGrayFromColor) { case 1: if( swap ) { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { tmp = *((HiLoDef*)&scan->Red.pw[dw]); scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls; } } else { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { scan->UserBuf.pw[pixels] = scan->Red.pw[dw] >> ls; } } break; case 2: if( swap ) { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { tmp = *((HiLoDef*)&scan->Green.pw[dw]); scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls; } } else { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { scan->UserBuf.pw[pixels] = scan->Green.pw[dw] >> ls; } } break; case 3: if( swap ) { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { tmp = *((HiLoDef*)&scan->Blue.pw[dw]); scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls; } } else { for (dw = 0; dw < scan->sParam.Size.dwPixels; dw++, pixels += next) { scan->UserBuf.pw[pixels] = scan->Blue.pw[dw] >> ls; } } break; } } /** */ static void usb_GrayDuplicate8( Plustek_Device *dev ) { u_char *dest, *src; u_long pixels; ScanDef *scan = &dev->scanning; usb_AverageGrayByte( dev ); if( scan->sParam.bSource == SOURCE_ADF ) { pixels = scan->sParam.Size.dwPixels; src = scan->Green.pb; dest = scan->UserBuf.pb + pixels - 1; for(; pixels; pixels--, src++, dest--) *dest = *src; } else { memcpy( scan->UserBuf.pb, scan->Green.pb, scan->sParam.Size.dwBytes ); } } /** */ static void usb_GrayDuplicate16( Plustek_Device *dev ) { int next; u_char ls; u_short *dest; u_long pixels; HiLoDef *pwm; ScanDef *scan = &dev->scanning; SANE_Bool swap = usb_HostSwap(); usb_AverageGrayWord( dev ); if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; dest = scan->UserBuf.pw + scan->sParam.Size.dwPixels - 1; } else { next = 1; dest = scan->UserBuf.pw; } if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; pwm = scan->Green.philo; for( pixels=scan->sParam.Size.dwPixels; pixels--; pwm++, dest += next ) { if( swap ) *dest = (_PHILO2WORD(pwm)) >> ls; else *dest = (_PLOHI2WORD(pwm)) >> ls; } } /** */ static void usb_GrayDuplicatePseudo16( Plustek_Device *dev ) { u_char *src; int next; u_short g; u_short *dest; u_long pixels; ScanDef *scan = &dev->scanning; usb_AverageGrayByte( dev ); if (scan->sParam.bSource == SOURCE_ADF) { next = -1; dest = scan->UserBuf.pw + scan->sParam.Size.dwPixels - 1; } else { next = 1; dest = scan->UserBuf.pw; } src = scan->Green.pb; g = (u_short)*src; for( pixels=scan->sParam.Size.dwPixels; pixels--; src++, dest += next ) { *dest = (g + *src) << bShift; g = (u_short)*src; } } /** copy binary data to the user buffer */ static void usb_BWDuplicate( Plustek_Device *dev ) { ScanDef *scan = &dev->scanning; if(scan->sParam.bSource == SOURCE_ADF) { usb_ReverseBitStream( scan->Green.pb, scan->UserBuf.pb, scan->sParam.Size.dwValidPixels, scan->dwBytesLine, 0, 0, 1 ); } else { memcpy( scan->UserBuf.pb, scan->Green.pb, scan->sParam.Size.dwBytes ); } } /** generate binary data from one of the three color inputs according to the * value in fGrayFromColor (CCD version) */ static void usb_BWDuplicateFromColor( Plustek_Device *dev ) { int next; u_char d, s, *dest; u_short j; u_long pixels; ColorByteDef *src; ScanDef *scan = &dev->scanning; if( scan->sParam.bSource == SOURCE_ADF ) { dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1; next = -1; } else { dest = scan->UserBuf.pb; next = 1; } switch(scan->fGrayFromColor) { case 1: src = scan->Red.pcb; break; case 3: src = scan->Blue.pcb; break; default: src = scan->Green.pcb; break; } d = j = 0; for( pixels = scan->sParam.Size.dwPixels; pixels; pixels--, src++ ) { s = src->a_bColor[0]; if( s != 0 ) d |= BitTable[j]; j++; if( j == 8 ) { *dest = d; dest += next; d = j = 0; } } } /** generate binary data from one of the three color inputs according to the * value in fGrayFromColor (CIS version) */ static void usb_BWDuplicateFromColor_2( Plustek_Device *dev ) { int next; u_char d, *dest, *src; u_short j; u_long pixels; ScanDef *scan = &dev->scanning; if( scan->sParam.bSource == SOURCE_ADF ) { dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1; next = -1; } else { dest = scan->UserBuf.pb; next = 1; } switch(scan->fGrayFromColor) { case 1: src = scan->Red.pb; break; case 3: src = scan->Blue.pb; break; default: src = scan->Green.pb; break; } d = j = 0; for( pixels = scan->sParam.Size.dwPixels; pixels; pixels--, src++ ) { if( *src != 0 ) d |= BitTable[j]; j++; if( j == 8 ) { *dest = d; dest += next; d = j = 0; } } } /************************** the scaling functions ****************************/ /** */ static void usb_ColorScaleGray( Plustek_Device *dev ) { int izoom, ddax, next; u_long dw, pixels; ColorByteDef *src; ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } switch(scan->fGrayFromColor) { case 1: src = scan->Red.pcb; break; case 3: src = scan->Blue.pcb; break; default: src = scan->Green.pcb; break; } izoom = usb_GetScaler( scan ); for( ddax = 0; dw; src++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { scan->UserBuf.pb[pixels] = src->a_bColor[0]; pixels += next; ddax += izoom; dw--; } } } /** */ static void usb_ColorScaleGray_2( Plustek_Device *dev ) { u_char *src; int izoom, ddax, next; u_long dw, pixels; ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } switch(scan->fGrayFromColor) { case 1: src = scan->Red.pb; break; case 3: src = scan->Blue.pb; break; default: src = scan->Green.pb; break; } izoom = usb_GetScaler( scan ); for( ddax = 0; dw; src++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { scan->UserBuf.pb[pixels] = *src; pixels += next; ddax += izoom; dw--; } } } /** */ static void usb_ColorScaleGray16( Plustek_Device *dev ) { u_char ls; int izoom, ddax, next; u_long dw, pixels, bitsput; SANE_Bool swap = usb_HostSwap(); ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } izoom = usb_GetScaler( scan ); if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; switch( scan->fGrayFromColor ) { case 1: for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { if( swap ) { scan->UserBuf.pw[pixels] = _HILO2WORD(scan->Red.pcw[bitsput].HiLo[0]) >> ls; } else { scan->UserBuf.pw[pixels] = scan->Red.pw[bitsput] >> ls; } pixels += next; ddax += izoom; dw--; } } break; case 2: for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { if( swap ) { scan->UserBuf.pw[pixels] = _HILO2WORD(scan->Green.pcw[bitsput].HiLo[0]) >> ls; } else { scan->UserBuf.pw[pixels] = scan->Green.pw[bitsput] >> ls; } pixels += next; ddax += izoom; dw--; } } break; case 3: for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { if( swap ) { scan->UserBuf.pw[pixels] = _HILO2WORD(scan->Blue.pcw[bitsput].HiLo[0]) >> ls; } else { scan->UserBuf.pw[pixels] = scan->Blue.pw[bitsput] >> ls; } pixels += next; ddax += izoom; dw--; } } break; } } /** */ static void usb_ColorScaleGray16_2( Plustek_Device *dev ) { u_char ls; int izoom, ddax, next; u_long dw, pixels, bitsput; HiLoDef tmp; SANE_Bool swap = usb_HostSwap(); ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } izoom = usb_GetScaler( scan ); if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; switch( scan->fGrayFromColor ) { case 1: for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { if( swap ) { tmp = *((HiLoDef*)&scan->Red.pw[bitsput]); scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls; } else { scan->UserBuf.pw[pixels] = scan->Red.pw[dw] >> ls; } pixels += next; ddax += izoom; dw--; } } break; case 2: for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { if( swap ) { tmp = *((HiLoDef*)&scan->Green.pw[bitsput]); scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls; } else { scan->UserBuf.pw[pixels] = scan->Green.pw[bitsput] >> ls; } pixels += next; ddax += izoom; dw--; } } break; case 3: for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { if( swap ) { tmp = *((HiLoDef*)&scan->Blue.pw[bitsput]); scan->UserBuf.pw[pixels] = _HILO2WORD(tmp) >> ls; } else { scan->UserBuf.pw[pixels] = scan->Blue.pw[bitsput] >> ls; } pixels += next; ddax += izoom; dw--; } } break; } } /** here we copy and scale from scanner world to user world... */ static void usb_ColorScale8( Plustek_Device *dev ) { int izoom, ddax, next; u_long dw, pixels, bitsput; ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } izoom = usb_GetScaler( scan ); for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { scan->UserBuf.pb_rgb[pixels].Red = scan->Red.pcb[bitsput].a_bColor[0]; scan->UserBuf.pb_rgb[pixels].Green = scan->Green.pcb[bitsput].a_bColor[0]; scan->UserBuf.pb_rgb[pixels].Blue = scan->Blue.pcb[bitsput].a_bColor[0]; pixels += next; ddax += izoom; dw--; } } } static void usb_ColorScale8_2( Plustek_Device *dev ) { int izoom, ddax, next; u_long dw, pixels, bitsput; ScanDef *scan = &dev->scanning; dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } izoom = usb_GetScaler( scan ); for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { scan->UserBuf.pb_rgb[pixels].Red = scan->Red.pb[bitsput]; scan->UserBuf.pb_rgb[pixels].Green = scan->Green.pb[bitsput]; scan->UserBuf.pb_rgb[pixels].Blue = scan->Blue.pb[bitsput]; pixels += next; ddax += izoom; dw--; } } } /** */ static void usb_ColorScale16( Plustek_Device *dev ) { u_char ls; int izoom, ddax, next; u_long dw, pixels, bitsput; SANE_Bool swap = usb_HostSwap(); ScanDef *scan = &dev->scanning; usb_AverageColorWord( dev ); dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } izoom = usb_GetScaler( scan ); if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { if( swap ) { scan->UserBuf.pw_rgb[pixels].Red = _HILO2WORD(scan->Red.pcw[bitsput].HiLo[0]) >> ls; scan->UserBuf.pw_rgb[pixels].Green = _HILO2WORD(scan->Green.pcw[bitsput].HiLo[0]) >> ls; scan->UserBuf.pw_rgb[pixels].Blue = _HILO2WORD(scan->Blue.pcw[bitsput].HiLo[0]) >> ls; } else { scan->UserBuf.pw_rgb[pixels].Red = scan->Red.pw[bitsput]>>ls; scan->UserBuf.pw_rgb[pixels].Green = scan->Green.pw[bitsput] >> ls; scan->UserBuf.pw_rgb[pixels].Blue = scan->Blue.pw[bitsput] >> ls; } pixels += next; ddax += izoom; dw--; } } } /** */ static void usb_ColorScale16_2( Plustek_Device *dev ) { u_char ls; HiLoDef tmp; int izoom, ddax, next; u_long dw, pixels, bitsput; SANE_Bool swap = usb_HostSwap(); ScanDef *scan = &dev->scanning; usb_AverageColorWord( dev ); dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } izoom = usb_GetScaler( scan ); if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { if( swap ) { tmp = *((HiLoDef*)&scan->Red.pw[bitsput]); scan->UserBuf.pw_rgb[pixels].Red = _HILO2WORD(tmp) >> ls; tmp = *((HiLoDef*)&scan->Green.pw[bitsput]); scan->UserBuf.pw_rgb[pixels].Green = _HILO2WORD(tmp) >> ls; tmp = *((HiLoDef*)&scan->Blue.pw[bitsput]); scan->UserBuf.pw_rgb[pixels].Blue = _HILO2WORD(tmp) >> ls; } else { scan->UserBuf.pw_rgb[pixels].Red = scan->Red.pw[bitsput] >> ls; scan->UserBuf.pw_rgb[pixels].Green = scan->Green.pw[bitsput] >> ls; scan->UserBuf.pw_rgb[pixels].Blue = scan->Blue.pw[bitsput] >> ls; } pixels += next; ddax += izoom; dw--; } } } /** */ static void usb_ColorScalePseudo16( Plustek_Device *dev ) { int izoom, ddax, next; u_short wR, wG, wB; u_long dw, pixels, bitsput; ScanDef *scan = &dev->scanning; usb_AverageColorByte( dev ); dw = scan->sParam.Size.dwPixels; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; pixels = scan->sParam.Size.dwPixels - 1; } else { next = 1; pixels = 0; } izoom = usb_GetScaler( scan ); wR = (u_short)scan->Red.pcb[0].a_bColor[0]; wG = (u_short)scan->Green.pcb[0].a_bColor[1]; wB = (u_short)scan->Blue.pcb[0].a_bColor[2]; for( bitsput = 0, ddax = 0; dw; bitsput++ ) { ddax -= _SCALER; while((ddax < 0) && (dw > 0)) { scan->UserBuf.pw_rgb[pixels].Red = (wR + scan->Red.pcb[bitsput].a_bColor[0]) << bShift; scan->UserBuf.pw_rgb[pixels].Green = (wG + scan->Green.pcb[bitsput].a_bColor[0]) << bShift; scan->UserBuf.pw_rgb[pixels].Blue = (wB + scan->Blue.pcb[bitsput].a_bColor[0]) << bShift; pixels += next; ddax += izoom; dw--; } wR = (u_short)scan->Red.pcb[bitsput].a_bColor[0]; wG = (u_short)scan->Green.pcb[bitsput].a_bColor[0]; wB = (u_short)scan->Blue.pcb[bitsput].a_bColor[0]; } } /** */ static void usb_BWScale( Plustek_Device *dev ) { u_char tmp, *dest, *src; int izoom, ddax; u_long i, dw; ScanDef *scan = &dev->scanning; src = scan->Green.pb; if( scan->sParam.bSource == SOURCE_ADF ) { int iSum = wSum; usb_ReverseBitStream(scan->Green.pb, scan->UserBuf.pb, scan->sParam.Size.dwValidPixels, scan->dwBytesLine, scan->sParam.PhyDpi.x, scan->sParam.UserDpi.x, 1 ); wSum = iSum; return; } else { dest = scan->UserBuf.pb; } izoom = usb_GetScaler( scan ); memset( dest, 0, scan->dwBytesLine ); ddax = 0; dw = 0; for( i = 0; i < scan->sParam.Size.dwValidPixels; i++ ) { ddax -= _SCALER; while( ddax < 0 ) { tmp = src[(i>>3)]; if((dw>>3) < scan->sParam.Size.dwValidPixels ) { if( 0 != (tmp &= (1 << ((~(i & 0x7))&0x7)))) dest[dw>>3] |= (1 << ((~(dw & 0x7))&0x7)); } dw++; ddax += izoom; } } } /** */ static void usb_BWScaleFromColor( Plustek_Device *dev ) { u_char d, s, *dest; u_short j; u_long pixels; int izoom, ddax, next; ColorByteDef *src; ScanDef *scan = &dev->scanning; if (scan->sParam.bSource == SOURCE_ADF) { dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1; next = -1; } else { dest = scan->UserBuf.pb; next = 1; } /* setup the source buffer */ switch(scan->fGrayFromColor) { case 1: src = scan->Red.pcb; break; case 3: src = scan->Blue.pcb; break; default: src = scan->Green.pcb; break; } izoom = usb_GetScaler( scan ); ddax = 0; d = j = 0; for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) { ddax -= _SCALER; while((ddax < 0) && (pixels > 0)) { s = src->a_bColor[0]; if( s != 0 ) d |= BitTable[j]; j++; if( j == 8 ) { *dest = d; dest += next; d = j = 0; } ddax += izoom; pixels--; } } } /** */ static void usb_BWScaleFromColor_2( Plustek_Device *dev ) { u_char d, *dest, *src; u_short j; u_long pixels; int izoom, ddax, next; ScanDef *scan = &dev->scanning; if (scan->sParam.bSource == SOURCE_ADF) { dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1; next = -1; } else { dest = scan->UserBuf.pb; next = 1; } /* setup the source buffer */ switch(scan->fGrayFromColor) { case 1: src = scan->Red.pb; break; case 3: src = scan->Blue.pb; break; default: src = scan->Green.pb; break; } izoom = usb_GetScaler( scan ); ddax = 0; d = j = 0; for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) { ddax -= _SCALER; while((ddax < 0) && (pixels > 0)) { if( *src != 0 ) d |= BitTable[j]; j++; if( j == 8 ) { *dest = d; dest += next; d = j = 0; } ddax += izoom; pixels--; } } } /** */ static void usb_GrayScale8( Plustek_Device *dev ) { u_char *dest, *src; int izoom, ddax, next; u_long pixels; ScanDef *scan = &dev->scanning; usb_AverageGrayByte( dev ); src = scan->Green.pb; if( scan->sParam.bSource == SOURCE_ADF ) { dest = scan->UserBuf.pb + scan->sParam.Size.dwPixels - 1; next = -1; } else { dest = scan->UserBuf.pb; next = 1; } izoom = usb_GetScaler( scan ); ddax = 0; for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) { ddax -= _SCALER; while((ddax < 0) && (pixels > 0)) { *dest = *src; dest += next; ddax += izoom; pixels--; } } } /** */ static void usb_GrayScale16( Plustek_Device *dev ) { u_char ls; int izoom, ddax, next; u_short *dest; u_long pixels; HiLoDef *pwm; ScanDef *scan = &dev->scanning; SANE_Bool swap = usb_HostSwap(); usb_AverageGrayWord( dev); pwm = scan->Green.philo; wSum = scan->sParam.PhyDpi.x; if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; dest = scan->UserBuf.pw + scan->sParam.Size.dwPixels - 1; } else { next = 1; dest = scan->UserBuf.pw; } izoom = usb_GetScaler( scan ); ddax = 0; if( scan->dwFlag & SCANFLAG_RightAlign ) ls = Shift; else ls = 0; for( pixels = scan->sParam.Size.dwPixels; pixels; pwm++ ) { ddax -= _SCALER; while((ddax < 0) && (pixels > 0)) { if( swap ) *dest = _PHILO2WORD(pwm) >> ls; else *dest = _PLOHI2WORD(pwm) >> ls; dest += next; ddax += izoom; pixels--; } } } /** */ static void usb_GrayScalePseudo16( Plustek_Device *dev ) { u_char *src; int izoom, ddax, next; u_short *dest, g; u_long pixels; ScanDef *scan = &dev->scanning; usb_AverageGrayByte( dev ); if( scan->sParam.bSource == SOURCE_ADF ) { next = -1; dest = scan->UserBuf.pw + scan->sParam.Size.dwPixels - 1; } else { next = 1; dest = scan->UserBuf.pw; } src = scan->Green.pb; g = (u_short)*src; izoom = usb_GetScaler( scan ); ddax = 0; for( pixels = scan->sParam.Size.dwPixels; pixels; src++ ) { ddax -= _SCALER; while((ddax < 0) && (pixels > 0)) { *dest = (g + *src) << bShift; dest += next; ddax += izoom; pixels--; } g = (u_short)*src; } } /** function to select the apropriate pixel copy function */ static void usb_GetImageProc( Plustek_Device *dev ) { ScanDef *scan = &dev->scanning; DCapsDef *sc = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; bShift = 0; if( scan->sParam.UserDpi.x != scan->sParam.PhyDpi.x ) { /* Pixel scaling... */ switch( scan->sParam.bDataType ) { case SCANDATATYPE_Color: if (scan->sParam.bBitDepth > 8) { if( usb_IsCISDevice(dev)){ scan->pfnProcess = usb_ColorScale16_2; DBG( _DBG_INFO, "ImageProc is: ColorScale16_2\n" ); } else { scan->pfnProcess = usb_ColorScale16; DBG( _DBG_INFO, "ImageProc is: ColorScale16\n" ); } if (scan->fGrayFromColor) { if( usb_IsCISDevice(dev)){ scan->pfnProcess = usb_ColorScaleGray16_2; DBG( _DBG_INFO, "ImageProc is: ColorScaleGray16_2\n" ); } else { scan->pfnProcess = usb_ColorScaleGray16; DBG( _DBG_INFO, "ImageProc is: ColorScaleGray16\n" ); } } } else if (scan->dwFlag & SCANFLAG_Pseudo48) { scan->pfnProcess = usb_ColorScalePseudo16; DBG( _DBG_INFO, "ImageProc is: ColorScalePseudo16\n" ); } else if (scan->fGrayFromColor) { if( usb_IsCISDevice(dev)){ if (scan->fGrayFromColor > 7 ) { scan->pfnProcess = usb_BWScaleFromColor_2; DBG( _DBG_INFO, "ImageProc is: BWScaleFromColor_2\n" ); } else { scan->pfnProcess = usb_ColorScaleGray_2; DBG( _DBG_INFO, "ImageProc is: ColorScaleGray_2\n" ); } } else { if (scan->fGrayFromColor > 7 ) { scan->pfnProcess = usb_BWScaleFromColor; DBG( _DBG_INFO, "ImageProc is: BWScaleFromColor\n" ); } else { scan->pfnProcess = usb_ColorScaleGray; DBG( _DBG_INFO, "ImageProc is: ColorScaleGray\n" ); } } } else { if( usb_IsCISDevice(dev)){ scan->pfnProcess = usb_ColorScale8_2; DBG( _DBG_INFO, "ImageProc is: ColorScale8_2\n" ); } else { scan->pfnProcess = usb_ColorScale8; DBG( _DBG_INFO, "ImageProc is: ColorScale8\n" ); } } break; case SCANDATATYPE_Gray: if (scan->sParam.bBitDepth > 8) { scan->pfnProcess = usb_GrayScale16; DBG( _DBG_INFO, "ImageProc is: GrayScale16\n" ); } else { if (scan->dwFlag & SCANFLAG_Pseudo48) { scan->pfnProcess = usb_GrayScalePseudo16; DBG( _DBG_INFO, "ImageProc is: GrayScalePseudo16\n" ); } else { scan->pfnProcess = usb_GrayScale8; DBG( _DBG_INFO, "ImageProc is: GrayScale8\n" ); } } break; default: scan->pfnProcess = usb_BWScale; DBG( _DBG_INFO, "ImageProc is: BWScale\n" ); break; } } else { /* Pixel copy */ switch( scan->sParam.bDataType ) { case SCANDATATYPE_Color: if (scan->sParam.bBitDepth > 8) { if( usb_IsCISDevice(dev)){ scan->pfnProcess = usb_ColorDuplicate16_2; DBG( _DBG_INFO, "ImageProc is: ColorDuplicate16_2\n" ); } else { scan->pfnProcess = usb_ColorDuplicate16; DBG( _DBG_INFO, "ImageProc is: ColorDuplicate16\n" ); } if (scan->fGrayFromColor) { if( usb_IsCISDevice(dev)){ scan->pfnProcess = usb_ColorDuplicateGray16_2; DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray16_2\n" ); } else { scan->pfnProcess = usb_ColorDuplicateGray16; DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray16\n" ); } } } else if (scan->dwFlag & SCANFLAG_Pseudo48) { scan->pfnProcess = usb_ColorDuplicatePseudo16; DBG( _DBG_INFO, "ImageProc is: ColorDuplicatePseudo16\n" ); } else if (scan->fGrayFromColor) { if( usb_IsCISDevice(dev)){ if (scan->fGrayFromColor > 7 ) { scan->pfnProcess = usb_BWDuplicateFromColor_2; DBG( _DBG_INFO, "ImageProc is: BWDuplicateFromColor_2\n" ); } else { scan->pfnProcess = usb_ColorDuplicateGray_2; DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray_2\n" ); } } else { if (scan->fGrayFromColor > 7 ) { scan->pfnProcess = usb_BWDuplicateFromColor; DBG( _DBG_INFO, "ImageProc is: BWDuplicateFromColor\n" ); } else { scan->pfnProcess = usb_ColorDuplicateGray; DBG( _DBG_INFO, "ImageProc is: ColorDuplicateGray\n" ); } } } else { if( usb_IsCISDevice(dev)){ scan->pfnProcess = usb_ColorDuplicate8_2; DBG( _DBG_INFO, "ImageProc is: ColorDuplicate8_2\n" ); } else { scan->pfnProcess = usb_ColorDuplicate8; DBG( _DBG_INFO, "ImageProc is: ColorDuplicate8\n" ); } } break; case SCANDATATYPE_Gray: if (scan->sParam.bBitDepth > 8) { scan->pfnProcess = usb_GrayDuplicate16; DBG( _DBG_INFO, "ImageProc is: GrayDuplicate16\n" ); } else { if (scan->dwFlag & SCANFLAG_Pseudo48) { scan->pfnProcess = usb_GrayDuplicatePseudo16; DBG( _DBG_INFO, "ImageProc is: GrayDuplicatePseudo16\n" ); } else { scan->pfnProcess = usb_GrayDuplicate8; DBG( _DBG_INFO, "ImageProc is: GrayDuplicate8\n" ); } } break; default: scan->pfnProcess = usb_BWDuplicate; DBG( _DBG_INFO, "ImageProc is: BWDuplicate\n" ); break; } } if( scan->sParam.bBitDepth == 8 ) { if( scan->dwFlag & SCANFLAG_Pseudo48 ) { if( scan->dwFlag & SCANFLAG_RightAlign ) { bShift = 5; } else { /* this should fix the Bearpaw/U12 discrepancy * in general the fix is needed, but not for the U12 * why? - no idea! */ if(_WAF_BSHIFT7_BUG == (_WAF_BSHIFT7_BUG & sc->workaroundFlag)) bShift = 0; /* Holger Bischof 16.12.2001 */ else bShift = 7; } DBG( _DBG_INFO, "bShift adjusted: %u\n", bShift ); } } if( _LM9833 == hw->chip ) { Shift = 0; Mask = 0xFFFF; } else { Shift = 2; Mask = 0xFFFC; } } /** * here we read the image data into our intermediate buffer (in the NT version * the function was implemented as thread) */ static SANE_Int usb_ReadData( Plustek_Device *dev ) { u_long dw, dwRet, dwBytes, pl; ScanDef *scan = &dev->scanning; HWDef *hw = &dev->usbDev.HwSetting; DBG( _DBG_READ, "usb_ReadData()\n" ); pl = dev->usbDev.a_bRegs[0x4e] * hw->wDRAMSize/128; while( scan->sParam.Size.dwTotalBytes ) { if( usb_IsEscPressed()) { DBG( _DBG_INFO, "usb_ReadData() - Cancel detected...\n" ); return 0; } if( scan->sParam.Size.dwTotalBytes > scan->dwBytesScanBuf ) dw = scan->dwBytesScanBuf; else dw = scan->sParam.Size.dwTotalBytes; scan->sParam.Size.dwTotalBytes -= dw; if(!scan->sParam.Size.dwTotalBytes && dw < (pl * 1024)) { if(!(dev->usbDev.a_bRegs[0x4e] = (u_char)ceil((double)dw / (4.0 * hw->wDRAMSize)))) { dev->usbDev.a_bRegs[0x4e] = 1; } dev->usbDev.a_bRegs[0x4f] = 0; sanei_lm983x_write( dev->fd, 0x4e, &dev->usbDev.a_bRegs[0x4e], 2, SANE_TRUE ); } while( scan->bLinesToSkip ) { DBG( _DBG_READ, "Skipping %u lines\n", scan->bLinesToSkip ); dwBytes = scan->bLinesToSkip * scan->sParam.Size.dwPhyBytes; if (dwBytes > scan->dwBytesScanBuf) { dwBytes = scan->dwBytesScanBuf; scan->bLinesToSkip -= scan->dwLinesScanBuf; } else { scan->bLinesToSkip = 0; } if( !usb_ScanReadImage( dev, scan->pbGetDataBuf, dwBytes )) return 0; } if( usb_ScanReadImage( dev, scan->pbGetDataBuf, dw )) { dumpPic("plustek-pic.raw", scan->pbGetDataBuf, dw, 0); if( scan->dwLinesDiscard ) { DBG(_DBG_READ, "Discarding %lu lines\n", scan->dwLinesDiscard); dwRet = dw / scan->sParam.Size.dwPhyBytes; if (scan->dwLinesDiscard > dwRet) { scan->dwLinesDiscard -= dwRet; dwRet = 0; } else { dwRet -= scan->dwLinesDiscard; scan->dwLinesDiscard = 0; } } else { dwRet = dw / scan->sParam.Size.dwPhyBytes; } scan->pbGetDataBuf += scan->dwBytesScanBuf; if( scan->pbGetDataBuf >= scan->pbScanBufEnd ) { scan->pbGetDataBuf = scan->pbScanBufBegin; } if( dwRet ) return dwRet; } } return 0; } /* END PLUSTEK-USBIMG.C .....................................................*/ sane-backends-1.0.27/backend/p5.c0000664000175000017500000017665512775277260013344 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2009-12 Stéphane Voltz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* -------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /*! \mainpage Primax PagePartner Parallel Port scanner Index Page * * \section intro_sec Introduction * * This backend provides support for the Prima PagePartner sheet fed parallel * port scanner. * * \section sane_api SANE API * * \subsection sane_flow sane flow SANE FLOW - sane_init() : initialize backend, attach scanners. - sane_get_devices() : query list of scanner devices, backend must probe for new devices. - sane_open() : open a particular scanner device, adding a handle to the opened device - sane_set_io_mode() : set blocking mode - sane_get_select_fd() : get scanner fd - sane_get_option_descriptor() : get option information - sane_control_option() : change option values - sane_start() : start image acquisition - sane_get_parameters() : returns actual scan parameters for the ongoing scan - sane_read() : read image data - sane_cancel() : cancel operation, end scan - sane_close() : close opened scanner device, freeing scanner handle - sane_exit() : terminate use of backend, freeing all resources for attached devices when last frontend quits */ /** * the build number allow to know which version of the backend is running. */ #define BUILD 2301 #include "p5.h" /** * Import directly the low level part needed to * operate scanner. The alternative is to prefix all public functions * with sanei_p5_ ,and have all the functions prototyped in * p5_device.h . */ #include "p5_device.c" /** * number of time the backend has been loaded by sane_init. */ static int init_count = 0; /** * NULL terminated list of opened frontend sessions. Sessions are * inserted here on sane_open() and removed on sane_close(). */ static P5_Session *sessions = NULL; /** * NULL terminated list of detected physical devices. * The same device may be opened several time by different sessions. * Entry are inserted here by the attach() function. * */ static P5_Device *devices = NULL; /** * NULL terminated list of devices needed by sane_get_devices(), since * the result returned must stay consistent until next call. */ static const SANE_Device **devlist = 0; /** * list of possible color modes */ static SANE_String_Const mode_list[] = { SANE_I18N (COLOR_MODE), SANE_I18N (GRAY_MODE), /* SANE_I18N (LINEART_MODE), not supported yet */ 0 }; static SANE_Range x_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (216.0), /* maximum */ SANE_FIX (0.0) /* quantization */ }; static SANE_Range y_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (299.0), /* maximum */ SANE_FIX (0.0) /* no quantization */ }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* no quantization */ }; static const SANE_Range threshold_percentage_range = { SANE_FIX (0), /* minimum */ SANE_FIX (100), /* maximum */ SANE_FIX (1) /* quantization */ }; /** * finds the maximum string length in a string array. */ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /**> placeholders for decoded configuration values */ static P5_Config p5cfg; /* ------------------------------------------------------------------------- */ /* * SANE Interface */ /** * Called by SANE initially. * * From the SANE spec: * This function must be called before any other SANE function can be * called. The behavior of a SANE backend is undefined if this * function is not called first. The version code of the backend is * returned in the value pointed to by version_code. If that pointer * is NULL, no version code is returned. Argument authorize is either * a pointer to a function that is invoked when the backend requires * authentication for a specific resource or NULL if the frontend does * not support authentication. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { SANE_Status status; authorize = authorize; /* get rid of compiler warning */ init_count++; /* init backend debug */ DBG_INIT (); DBG (DBG_info, "SANE P5 backend version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_proc, "sane_init: start\n"); DBG (DBG_trace, "sane_init: init_count=%d\n", init_count); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); /* cold-plugging case : probe for already plugged devices */ status = probe_p5_devices (); DBG (DBG_proc, "sane_init: exit\n"); return status; } /** * Called by SANE to find out about supported devices. * * From the SANE spec: * This function can be used to query the list of devices that are * available. If the function executes successfully, it stores a * pointer to a NULL terminated array of pointers to SANE_Device * structures in *device_list. The returned list is guaranteed to * remain unchanged and valid until (a) another call to this function * is performed or (b) a call to sane_exit() is performed. This * function can be called repeatedly to detect when new devices become * available. If argument local_only is true, only local devices are * returned (devices directly attached to the machine that SANE is * running on). If it is false, the device list includes all remote * devices that are accessible to the SANE library. * * SANE does not require that this function is called before a * sane_open() call is performed. A device name may be specified * explicitly by a user which would make it unnecessary and * undesirable to call this function first. * @param device_list pointer where to store the device list * @param local_only SANE_TRUE if only local devices are required. * @return SANE_STATUS_GOOD when successfull */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { int dev_num, devnr; struct P5_Device *device; SANE_Device *sane_device; int i; DBG (DBG_proc, "sane_get_devices: start: local_only = %s\n", local_only == SANE_TRUE ? "true" : "false"); /* free existing devlist first */ if (devlist) { for (i = 0; devlist[i] != NULL; i++) free ((void *)devlist[i]); free (devlist); devlist = NULL; } /** * Since sane_get_devices() may be called repeatedly to detect new devices, * the device detection must be run at each call. We are handling * hot-plugging : we probe for devices plugged since sane_init() was called. */ probe_p5_devices (); /* if no devices detected, just return an empty list */ if (devices == NULL) { devlist = malloc (sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; devlist[0] = NULL; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit with no device\n"); return SANE_STATUS_GOOD; } /* count physical devices */ devnr = 1; device = devices; while (device->next) { devnr++; device = device->next; } /* allocate room for the list, plus 1 for the NULL terminator */ devlist = malloc ((devnr + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; *device_list = devlist; dev_num = 0; device = devices; /* we build a list of SANE_Device from the list of attached devices */ for (i = 0; i < devnr; i++) { /* add device according to local only flag */ if ((local_only == SANE_TRUE && device->local == SANE_TRUE) || local_only == SANE_FALSE) { /* allocate memory to add the device */ sane_device = malloc (sizeof (*sane_device)); if (!sane_device) { return SANE_STATUS_NO_MEM; } /* copy data */ sane_device->name = device->name; sane_device->vendor = device->model->vendor; sane_device->model = device->model->product; sane_device->type = device->model->type; devlist[dev_num] = sane_device; /* increment device counter */ dev_num++; } /* go to next detected device */ device = device->next; } devlist[dev_num] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } /** * Called to establish connection with the session. This function will * also establish meaningful defaults and initialize the options. * * From the SANE spec: * This function is used to establish a connection to a particular * device. The name of the device to be opened is passed in argument * name. If the call completes successfully, a handle for the device * is returned in *h. As a special case, specifying a zero-length * string as the device requests opening the first available device * (if there is such a device). Another special case is to only give * the name of the backend as the device name, in this case the first * available device will also be used. * @param name name of the device to open * @param handle opaque pointer where to store the pointer of * the opened P5_Session * @return SANE_STATUS_GOOD on success */ SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle) { struct P5_Session *session = NULL; struct P5_Device *device = NULL; DBG (DBG_proc, "sane_open: start (devicename=%s)\n", name); /* check there is at least a device */ if (devices == NULL) { DBG (DBG_proc, "sane_open: exit, no device to open!\n"); return SANE_STATUS_INVAL; } if (name[0] == 0 || strncmp (name, "p5", strlen ("p5")) == 0) { DBG (DBG_info, "sane_open: no specific device requested, using default\n"); if (devices) { device = devices; DBG (DBG_info, "sane_open: device %s used as default device\n", device->name); } } else { DBG (DBG_info, "sane_open: device %s requested\n", name); /* walk the device list until we find a matching name */ device = devices; while (device && strcmp (device->name, name) != 0) { DBG (DBG_trace, "sane_open: device %s doesn't match\n", device->name); device = device->next; } } /* check wether we have found a match or reach the end of the device list */ if (!device) { DBG (DBG_info, "sane_open: no device found\n"); return SANE_STATUS_INVAL; } /* now we have a device, duplicate it and return it in handle */ DBG (DBG_info, "sane_open: device %s found\n", name); /* device initialization */ if (device->initialized == SANE_FALSE) { /** * call to hardware initialization function here. */ device->fd = open_pp (device->name); if (device->fd < 0) { DBG (DBG_error, "sane_open: failed to open '%s' device!\n", device->name); return SANE_STATUS_INVAL; } /* now try to connect to scanner */ if (connect (device->fd) != SANE_TRUE) { DBG (DBG_error, "sane_open: failed to connect!\n"); close_pp (device->fd); return SANE_STATUS_INVAL; } /* load calibration data */ restore_calibration (device); /* device link is OK now */ device->initialized = SANE_TRUE; } device->buffer = NULL; device->gain = NULL; device->offset = NULL; /* prepare handle to return */ session = (P5_Session *) malloc (sizeof (P5_Session)); if (session == NULL) { DBG (DBG_proc, "sane_open: exit OOM\n"); return SANE_STATUS_NO_MEM; } /* initalize session */ session->dev = device; session->scanning = SANE_FALSE; session->non_blocking = SANE_FALSE; /* initialize SANE options for this session */ init_options (session); /* add the handle to the linked list of sessions */ session->next = sessions; sessions = session; /* store result */ *handle = session; /* exit success */ DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } /** * Set non blocking mode. In this mode, read return immediatly when * no data is available whithin sane_read(), instead of polling the scanner. */ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { P5_Session *session = (P5_Session *) handle; DBG (DBG_proc, "sane_set_io_mode: start\n"); if (session->scanning != SANE_TRUE) { DBG (DBG_error, "sane_set_io_mode: called out of a scan\n"); return SANE_STATUS_INVAL; } session->non_blocking = non_blocking; DBG (DBG_info, "sane_set_io_mode: I/O mode set to %sblocking.\n", non_blocking ? "non " : " "); DBG (DBG_proc, "sane_set_io_mode: exit\n"); return SANE_STATUS_GOOD; } /** * An advanced method we don't support but have to define. At SANE API * level this function is meant to provide a file descriptor on which the * frontend can do select()/poll() to wait for data. */ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fdp) { /* make compiler happy ... */ handle = handle; fdp = fdp; DBG (DBG_proc, "sane_get_select_fd: start\n"); DBG (DBG_warn, "sane_get_select_fd: unsupported ...\n"); DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } /** * Returns the options we know. * * From the SANE spec: * This function is used to access option descriptors. The function * returns the option descriptor for option number n of the device * represented by handle h. Option number 0 is guaranteed to be a * valid option. Its value is an integer that specifies the number of * options that are available for device handle h (the count includes * option 0). If n is not a valid option index, the function returns * NULL. The returned option descriptor is guaranteed to remain valid * (and at the returned address) until the device is closed. */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct P5_Session *session = handle; DBG (DBG_proc, "sane_get_option_descriptor: start\n"); if ((unsigned) option >= NUM_OPTIONS) return NULL; DBG (DBG_info, "sane_get_option_descriptor: \"%s\"\n", session->options[option].descriptor.name); DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return &(session->options[option].descriptor); } /** * sets automatic value for an option , called by sane_control_option after * all checks have been done */ static SANE_Status set_automatic_value (P5_Session * s, int option, SANE_Int * myinfo) { SANE_Status status = SANE_STATUS_GOOD; SANE_Int i, min; SANE_Word *dpi_list; switch (option) { case OPT_TL_X: s->options[OPT_TL_X].value.w = x_range.min; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_TL_Y: s->options[OPT_TL_Y].value.w = y_range.min; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BR_X: s->options[OPT_BR_X].value.w = x_range.max; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BR_Y: s->options[OPT_BR_Y].value.w = y_range.max; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_RESOLUTION: /* we set up to the lowest available dpi value */ dpi_list = (SANE_Word *) s->options[OPT_RESOLUTION].descriptor.constraint. word_list; min = 65536; for (i = 1; i < dpi_list[0]; i++) { if (dpi_list[i] < min) min = dpi_list[i]; } s->options[OPT_RESOLUTION].value.w = min; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_PREVIEW: s->options[OPT_PREVIEW].value.w = SANE_FALSE; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_MODE: if (s->options[OPT_MODE].value.s) free (s->options[OPT_MODE].value.s); s->options[OPT_MODE].value.s = strdup (mode_list[0]); *myinfo |= SANE_INFO_RELOAD_OPTIONS; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; default: DBG (DBG_warn, "set_automatic_value: can't set unknown option %d\n", option); } return status; } /** * sets an option , called by sane_control_option after all * checks have been done */ static SANE_Status set_option_value (P5_Session * s, int option, void *val, SANE_Int * myinfo) { SANE_Status status = SANE_STATUS_GOOD; SANE_Word tmpw; switch (option) { case OPT_TL_X: case OPT_BR_X: case OPT_TL_Y: case OPT_BR_Y: s->options[option].value.w = *(SANE_Word *) val; /* we ensure geometry is coherent */ /* this happens when user drags TL corner right or below the BR point */ if (s->options[OPT_BR_Y].value.w < s->options[OPT_TL_Y].value.w) { tmpw = s->options[OPT_BR_Y].value.w; s->options[OPT_BR_Y].value.w = s->options[OPT_TL_Y].value.w; s->options[OPT_TL_Y].value.w = tmpw; } if (s->options[OPT_BR_X].value.w < s->options[OPT_TL_X].value.w) { tmpw = s->options[OPT_BR_X].value.w; s->options[OPT_BR_X].value.w = s->options[OPT_TL_X].value.w; s->options[OPT_TL_X].value.w = tmpw; } *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_RESOLUTION: case OPT_PREVIEW: s->options[option].value.w = *(SANE_Word *) val; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_MODE: if (s->options[option].value.s) free (s->options[option].value.s); s->options[option].value.s = strdup (val); *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_CALIBRATE: status = sheetfed_calibration (s->dev); *myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case OPT_CLEAR_CALIBRATION: cleanup_calibration (s->dev); *myinfo |= SANE_INFO_RELOAD_OPTIONS; break; default: DBG (DBG_warn, "set_option_value: can't set unknown option %d\n", option); } return status; } /** * gets an option , called by sane_control_option after all checks * have been done */ static SANE_Status get_option_value (P5_Session * s, int option, void *val) { SANE_Status status; switch (option) { /* word or word equivalent options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *) val = s->options[option].value.w; break; /* string options: */ case OPT_MODE: strcpy (val, s->options[option].value.s); break; /* sensor options */ case OPT_PAGE_LOADED_SW: status = test_document (s->dev->fd); if (status == SANE_STATUS_GOOD) s->options[option].value.b = SANE_TRUE; else s->options[option].value.b = SANE_FALSE; *(SANE_Bool *) val = s->options[option].value.b; break; case OPT_NEED_CALIBRATION_SW: *(SANE_Bool *) val = !s->dev->calibrated; break; /* unhandled options */ default: DBG (DBG_warn, "get_option_value: can't get unknown option %d\n", option); } return SANE_STATUS_GOOD; } /** * Gets or sets an option value. * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which * the option is controlled is specified by parameter action. The * possible values of this parameter are described in more detail * below. The value of the option is passed through argument val. It * is a pointer to the memory that holds the option value. The memory * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon * encountering the first NUL terminator in the string. If argument i * is not NULL, the value of *i will be set to provide details on how * well the request has been met. * action is SANE_ACTION_GET_VALUE, SANE_ACTION_SET_VALUE or SANE_ACTION_SET_AUTO */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { P5_Session *s = handle; SANE_Status status; SANE_Word cap; SANE_Int myinfo = 0; DBG (DBG_io2, "sane_control_option: start: action = %s, option = %s (%d)\n", (action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_SET_VALUE) ? "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->options[option].descriptor.name, option); if (info) *info = 0; /* do checks before trying to apply action */ if (s->scanning) { DBG (DBG_warn, "sane_control_option: don't call this function while " "scanning (option = %s (%d))\n", s->options[option].descriptor.name, option); return SANE_STATUS_DEVICE_BUSY; } /* option must be within existing range */ if (option >= NUM_OPTIONS || option < 0) { DBG (DBG_warn, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", option); return SANE_STATUS_INVAL; } /* don't access an inactive option */ cap = s->options[option].descriptor.cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (DBG_warn, "sane_control_option: option %d is inactive\n", option); return SANE_STATUS_INVAL; } /* now checks have been done, apply action */ switch (action) { case SANE_ACTION_GET_VALUE: status = get_option_value (s, option, val); break; case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_warn, "sane_control_option: option %d is not settable\n", option); return SANE_STATUS_INVAL; } status = sanei_constrain_value (&s->options[option].descriptor, val, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } /* return immediatly if no change */ if (s->options[option].descriptor.type == SANE_TYPE_INT && *(SANE_Word *) val == s->options[option].value.w) { status = SANE_STATUS_GOOD; } else { /* apply change */ status = set_option_value (s, option, val, &myinfo); } break; case SANE_ACTION_SET_AUTO: /* sets automatic values */ if (!(cap & SANE_CAP_AUTOMATIC)) { DBG (DBG_warn, "sane_control_option: option %d is not autosettable\n", option); return SANE_STATUS_INVAL; } status = set_automatic_value (s, option, &myinfo); break; default: DBG (DBG_error, "sane_control_option: invalid action %d\n", action); status = SANE_STATUS_INVAL; break; } if (info) *info = myinfo; DBG (DBG_io2, "sane_control_option: exit\n"); return status; } /** * Called by SANE when a page acquisition operation is to be started. * @param handle opaque handle to a frontend session * @return SANE_STATUS_GOOD on success, SANE_STATUS_BUSY if the device is * in use by another session or SANE_STATUS_WARMING_UP if the device is * warming up. In this case the fronted as to call sane_start again until * warming up is done. Any other values returned are error status. */ SANE_Status sane_start (SANE_Handle handle) { struct P5_Session *session = handle; int status = SANE_STATUS_GOOD; P5_Device *dev = session->dev; DBG (DBG_proc, "sane_start: start\n"); /* if already scanning, tell we're busy */ if (session->scanning == SANE_TRUE) { DBG (DBG_info, "sane_start: device is already scanning\n"); return SANE_STATUS_DEVICE_BUSY; } /* check that the device has been initialized */ if (dev->initialized == SANE_FALSE) { DBG (DBG_error, "sane_start: device is not initialized\n"); return SANE_STATUS_INVAL; } /* check if there is a document */ status = test_document (dev->fd); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: device is already scanning\n"); return status; } /* we compute all the scan parameters so that */ /* we will be able to set up the registers correctly */ compute_parameters (session); /* move to scan area if needed */ if (dev->ystart > 0) { status = move (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: failed to move to scan area\n"); return SANE_STATUS_INVAL; } } /* send scan command */ status = start_scan (dev, dev->mode, dev->ydpi, dev->xstart, dev->pixels); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: failed to start scan\n"); return SANE_STATUS_INVAL; } /* allocates work buffer */ if (dev->buffer != NULL) { free (dev->buffer); } dev->position = 0; dev->top = 0; /* compute amount of lines needed for lds correction */ dev->bottom = dev->bytes_per_line * 2 * dev->lds; /* computes buffer size, 66 color lines plus eventual amount needed for lds */ dev->size = dev->pixels * 3 * 66 + dev->bottom; dev->buffer = (uint8_t *) malloc (dev->size); if (dev->buffer == NULL) { DBG (DBG_error, "sane_start: failed to allocate %lu bytes\n", (unsigned long)dev->size); sane_cancel (handle); return SANE_STATUS_NO_MEM; } /* return now the scan has been initiated */ session->scanning = SANE_TRUE; session->sent = 0; DBG (DBG_io, "sane_start: to_send=%d\n", session->to_send); DBG (DBG_io, "sane_start: size=%lu\n", (unsigned long)dev->size); DBG (DBG_io, "sane_start: top=%lu\n", (unsigned long)dev->top); DBG (DBG_io, "sane_start: bottom=%lu\n", (unsigned long)dev->bottom); DBG (DBG_io, "sane_start: position=%lu\n", (unsigned long)dev->position); DBG (DBG_proc, "sane_start: exit\n"); return status; } /** @brief compute scan parameters * This function computes two set of parameters. The one for the SANE's standard * and the other for the hardware. Among these parameters are the bit depth, total * number of lines, total number of columns, extra line to read for data reordering... * @param session fronted session to compute final scan parameters * @return SANE_STATUS_GOOD on success */ static SANE_Status compute_parameters (P5_Session * session) { P5_Device *dev = session->dev; SANE_Int dpi; /* dpi for scan */ SANE_String mode; SANE_Status status = SANE_STATUS_GOOD; int tl_x, tl_y, br_x, br_y; mode = session->options[OPT_MODE].value.s; dpi = session->options[OPT_RESOLUTION].value.w; /* scan coordinates */ tl_x = SANE_UNFIX (session->options[OPT_TL_X].value.w); tl_y = SANE_UNFIX (session->options[OPT_TL_Y].value.w); br_x = SANE_UNFIX (session->options[OPT_BR_X].value.w); br_y = SANE_UNFIX (session->options[OPT_BR_Y].value.w); /* only single pass scanning supported */ session->params.last_frame = SANE_TRUE; /* gray modes */ if (strcmp (mode, GRAY_MODE) == 0) { session->params.format = SANE_FRAME_GRAY; dev->mode = MODE_GRAY; dev->lds = 0; } else if (strcmp (mode, LINEART_MODE) == 0) { session->params.format = SANE_FRAME_GRAY; dev->mode = MODE_LINEART; dev->lds = 0; } else { /* Color */ session->params.format = SANE_FRAME_RGB; dev->mode = MODE_COLOR; dev->lds = (dev->model->lds * dpi) / dev->model->max_ydpi; } /* SANE level values */ session->params.lines = ((br_y - tl_y) * dpi) / MM_PER_INCH; if (session->params.lines == 0) session->params.lines = 1; session->params.pixels_per_line = ((br_x - tl_x) * dpi) / MM_PER_INCH; if (session->params.pixels_per_line == 0) session->params.pixels_per_line = 1; DBG (DBG_data, "compute_parameters: pixels_per_line =%d\n", session->params.pixels_per_line); if (strcmp (mode, LINEART_MODE) == 0) { session->params.depth = 1; /* in lineart, having pixels multiple of 8 avoids a costly test */ /* at each bit to see we must go to the next byte */ /* TODO : implement this requirement in sane_control_option */ session->params.pixels_per_line = ((session->params.pixels_per_line + 7) / 8) * 8; } else session->params.depth = 8; /* width needs to be even */ if (session->params.pixels_per_line & 1) session->params.pixels_per_line++; /* Hardware settings : they can differ from the ones at SANE level */ /* for instance the effective DPI used by a sensor may be higher */ /* than the one needed for the SANE scan parameters */ dev->lines = session->params.lines; dev->pixels = session->params.pixels_per_line; /* motor and sensor DPI */ dev->xdpi = dpi; dev->ydpi = dpi; /* handle bounds of motor's dpi range */ if (dev->ydpi > dev->model->max_ydpi) { dev->ydpi = dev->model->max_ydpi; dev->lines = (dev->lines * dev->model->max_ydpi) / dpi; if (dev->lines == 0) dev->lines = 1; /* round number of lines */ session->params.lines = (session->params.lines / dev->lines) * dev->lines; if (session->params.lines == 0) session->params.lines = 1; } if (dev->ydpi < dev->model->min_ydpi) { dev->ydpi = dev->model->min_ydpi; dev->lines = (dev->lines * dev->model->min_ydpi) / dpi; } /* hardware values */ dev->xstart = ((SANE_UNFIX (dev->model->x_offset) + tl_x) * dpi) / MM_PER_INCH; dev->ystart = ((SANE_UNFIX (dev->model->y_offset) + tl_y) * dev->ydpi) / MM_PER_INCH; /* take lds correction into account when moving to scan area */ if (dev->ystart > 2 * dev->lds) dev->ystart -= 2 * dev->lds; /* computes bytes per line */ session->params.bytes_per_line = session->params.pixels_per_line; dev->bytes_per_line = dev->pixels; if (session->params.format == SANE_FRAME_RGB) { dev->bytes_per_line *= 3; } /* in lineart mode we adjust bytes_per_line needed by frontend */ /* we do that here because we needed sent/to_send to be as if */ /* there was no lineart */ if (session->params.depth == 1) { session->params.bytes_per_line = (session->params.bytes_per_line + 7) / 8; } session->params.bytes_per_line = dev->bytes_per_line; session->to_send = session->params.bytes_per_line * session->params.lines; session->params.bytes_per_line = dev->bytes_per_line; DBG (DBG_data, "compute_parameters: bytes_per_line =%d\n", session->params.bytes_per_line); DBG (DBG_data, "compute_parameters: depth =%d\n", session->params.depth); DBG (DBG_data, "compute_parameters: lines =%d\n", session->params.lines); DBG (DBG_data, "compute_parameters: image size =%d\n", session->to_send); DBG (DBG_data, "compute_parameters: xstart =%d\n", dev->xstart); DBG (DBG_data, "compute_parameters: ystart =%d\n", dev->ystart); DBG (DBG_data, "compute_parameters: dev lines =%d\n", dev->lines); DBG (DBG_data, "compute_parameters: dev bytes per line=%d\n", dev->bytes_per_line); DBG (DBG_data, "compute_parameters: dev pixels =%d\n", dev->pixels); DBG (DBG_data, "compute_parameters: lds =%d\n", dev->lds); return status; } /** * Called by SANE to retrieve information about the type of data * that the current scan will return. * * From the SANE spec: * This function is used to obtain the current scan parameters. The * returned parameters are guaranteed to be accurate between the time * a scan has been started (sane_start() has been called) and the * completion of that request. Outside of that window, the returned * values are best-effort estimates of what the parameters will be * when sane_start() gets invoked. * * Calling this function before a scan has actually started allows, * for example, to get an estimate of how big the scanned image will * be. The parameters passed to this function are the handle of the * device for which the parameters should be obtained and a pointer * to a parameter structure. */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { SANE_Status status; struct P5_Session *session = (struct P5_Session *) handle; DBG (DBG_proc, "sane_get_parameters: start\n"); /* call parameters computing function */ status = compute_parameters (session); if (status == SANE_STATUS_GOOD && params) *params = session->params; DBG (DBG_proc, "sane_get_parameters: exit\n"); return status; } /** * Called by SANE to read data. * * From the SANE spec: * This function is used to read image data from the device * represented by handle h. Argument buf is a pointer to a memory * area that is at least maxlen bytes long. The number of bytes * returned is stored in *len. A backend must set this to zero when * the call fails (i.e., when a status other than SANE_STATUS_GOOD is * returned). * * When the call succeeds, the number of bytes returned can be * anywhere in the range from 0 to maxlen bytes. * * Returned data is read from working buffer. */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct P5_Session *session = (struct P5_Session *) handle; struct P5_Device *dev = session->dev; SANE_Status status = SANE_STATUS_GOOD; int count; int size, lines; SANE_Bool x2; SANE_Int i; DBG (DBG_proc, "sane_read: start\n"); DBG (DBG_io, "sane_read: up to %d bytes required by frontend\n", max_len); /* some sanity checks first to protect from would be buggy frontends */ if (!session) { DBG (DBG_error, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } if (!buf) { DBG (DBG_error, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (!len) { DBG (DBG_error, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } /* no data read yet */ *len = 0; /* check if session is scanning */ if (!session->scanning) { DBG (DBG_warn, "sane_read: scan was cancelled, is over or has not been initiated yet\n"); return SANE_STATUS_CANCELLED; } /* check for EOF, must be done before any physical read */ if (session->sent >= session->to_send) { DBG (DBG_io, "sane_read: end of scan reached\n"); return SANE_STATUS_EOF; } /* if working buffer is empty, we do a physical data read */ if (dev->top <= dev->bottom) { DBG (DBG_io, "sane_read: physical data read\n"); /* check is there is data available. In case of non-blocking mode we return * as soon it is detected there is no data yet. Reads must by done line by * line, so we read only when count is bigger than bytes per line * */ count = available_bytes (dev->fd); DBG (DBG_io, "sane_read: count=%d bytes\n", count); if (count < dev->bytes_per_line && session->non_blocking == SANE_TRUE) { DBG (DBG_io, "sane_read: scanner hasn't enough data available\n"); DBG (DBG_proc, "sane_read: exit\n"); return SANE_STATUS_GOOD; } /* now we can wait for data here */ while (count < dev->bytes_per_line) { /* test if document left the feeder, so we have to terminate the scan */ status = test_document (dev->fd); if (status == SANE_STATUS_NO_DOCS) { session->to_send = session->sent; return SANE_STATUS_EOF; } /* don't call scanner too often */ usleep (10000); count = available_bytes (dev->fd); } /** compute size of physical data to read * on first read, position will be 0, while it will be 'bottom' * for the subsequent reads. * We try to read a complete buffer */ size = dev->size - dev->position; if (session->to_send - session->sent < size) { /* not enough data left, so read remainder of scan */ size = session->to_send - session->sent; } /* 600 dpi is 300x600 physical, and 400 is 200x400 */ if (dev->ydpi > dev->model->max_xdpi) { x2 = SANE_TRUE; } else { x2 = SANE_FALSE; } lines = read_line (dev, dev->buffer + dev->position, dev->bytes_per_line, size / dev->bytes_per_line, SANE_TRUE, x2, dev->mode, dev->calibrated); /* handle document end detection TODO try to recover the partial * buffer already read before EOD */ if (lines == -1) { DBG (DBG_io, "sane_read: error reading line\n"); return SANE_STATUS_IO_ERROR; } /* gather lines until we have more than needed for lds */ dev->position += lines * dev->bytes_per_line; dev->top = dev->position; if (dev->position > dev->bottom) { dev->position = dev->bottom; } DBG (DBG_io, "sane_read: size =%lu\n", (unsigned long)dev->size); DBG (DBG_io, "sane_read: bottom =%lu\n", (unsigned long)dev->bottom); DBG (DBG_io, "sane_read: position=%lu\n", (unsigned long)dev->position); DBG (DBG_io, "sane_read: top =%lu\n", (unsigned long)dev->top); } /* end of physical data reading */ /* logical data reading */ /* check if there data available in working buffer */ if (dev->position < dev->top && dev->position >= dev->bottom) { DBG (DBG_io, "sane_read: logical data read\n"); /* we have more data in internal buffer than asked , * then send only max data */ size = dev->top - dev->position; if (max_len < size) { *len = max_len; } else /* if we don't have enough, send all what we have */ { *len = dev->top - dev->position; } /* data copy */ if (dev->lds == 0) { memcpy (buf, dev->buffer + dev->position, *len); } else { /* compute count of bytes for lds */ count = dev->lds * dev->bytes_per_line; /* adjust for lds as we copy data to frontend */ for (i = 0; i < *len; i++) { switch ((dev->position + i) % 3) { /* red */ case 0: buf[i] = dev->buffer[dev->position + i - 2 * count]; break; /* green */ case 1: buf[i] = dev->buffer[dev->position + i - count]; break; /* blue */ default: buf[i] = dev->buffer[dev->position + i]; break; } } } dev->position += *len; /* update byte accounting */ session->sent += *len; DBG (DBG_io, "sane_read: sent %d bytes from buffer to frontend\n", *len); return SANE_STATUS_GOOD; } /* check if we exhausted working buffer */ if (dev->position >= dev->top && dev->position >= dev->bottom) { /* copy extra lines needed for lds in next buffer */ if (dev->position > dev->bottom && dev->lds > 0) { memcpy (dev->buffer, dev->buffer + dev->position - dev->bottom, dev->bottom); } /* restart buffer */ dev->position = dev->bottom; dev->top = 0; } DBG (DBG_io, "sane_read: size =%lu\n", (unsigned long)dev->size); DBG (DBG_io, "sane_read: bottom =%lu\n", (unsigned long)dev->bottom); DBG (DBG_io, "sane_read: position=%lu\n", (unsigned long)dev->position); DBG (DBG_io, "sane_read: top =%lu\n", (unsigned long)dev->top); DBG (DBG_proc, "sane_read: exit\n"); return status; } /** * Cancels a scan. * * From the SANE spec: * This function is used to immediately or as quickly as possible * cancel the currently pending operation of the device represented by * handle h. This function can be called at any time (as long as * handle h is a valid handle) but usually affects long-running * operations only (such as image is acquisition). It is safe to call * this function asynchronously (e.g., from within a signal handler). * It is important to note that completion of this operaton does not * imply that the currently pending operation has been cancelled. It * only guarantees that cancellation has been initiated. Cancellation * completes only when the cancelled call returns (typically with a * status value of SANE_STATUS_CANCELLED). Since the SANE API does * not require any other operations to be re-entrant, this implies * that a frontend must not call any other operation until the * cancelled operation has returned. */ void sane_cancel (SANE_Handle handle) { P5_Session *session = handle; DBG (DBG_proc, "sane_cancel: start\n"); /* if scanning, abort and park head */ if (session->scanning == SANE_TRUE) { /* detects if we are called after the scan is finished, * or if the scan is aborted */ if (session->sent < session->to_send) { DBG (DBG_info, "sane_cancel: aborting scan.\n"); /* device hasn't finished scan, we are aborting it * and we may have to do something specific for it here */ } else { DBG (DBG_info, "sane_cancel: cleaning up after scan.\n"); } session->scanning = SANE_FALSE; } eject (session->dev->fd); DBG (DBG_proc, "sane_cancel: exit\n"); } /** * Ends use of the session. * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is * presently active, a call to sane_cancel() is performed first. After * this function returns, handle h must not be used anymore. * * Handle resources are free'd before disposing the handle. But devices * resources must not be mdofied, since it could be used or reused until * sane_exit() is called. */ void sane_close (SANE_Handle handle) { P5_Session *prev, *session; DBG (DBG_proc, "sane_close: start\n"); /* remove handle from list of open handles: */ prev = NULL; for (session = sessions; session; session = session->next) { if (session == handle) break; prev = session; } if (!session) { DBG (DBG_error0, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } /* cancel any active scan */ if (session->scanning == SANE_TRUE) { sane_cancel (handle); } if (prev) prev->next = session->next; else sessions = session->next; /* close low level device */ if (session->dev->initialized == SANE_TRUE) { if (session->dev->calibrated == SANE_TRUE) { save_calibration (session->dev); } disconnect (session->dev->fd); close_pp (session->dev->fd); session->dev->fd = -1; session->dev->initialized = SANE_FALSE; /* free device data */ if (session->dev->buffer != NULL) { free (session->dev->buffer); } if (session->dev->buffer != NULL) { free (session->dev->gain); free (session->dev->offset); } if (session->dev->calibrated == SANE_TRUE) { cleanup_calibration (session->dev); } } /* free per session data */ free (session->options[OPT_MODE].value.s); free ((void *)session->options[OPT_RESOLUTION].descriptor.constraint.word_list); free (session); DBG (DBG_proc, "sane_close: exit\n"); } /** * Terminates the backend. * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be * open (it is recommended to close device handles explicitly through * a call to sane_close(), but backends are required to release all * resources upon a call to this function). After this function * returns, no function other than sane_init() may be called * (regardless of the status value returned by sane_exit(). Neglecting * to call this function may result in some resources not being * released properly. */ void sane_exit (void) { struct P5_Session *session, *next; struct P5_Device *dev, *nextdev; int i; DBG (DBG_proc, "sane_exit: start\n"); init_count--; if (init_count > 0) { DBG (DBG_info, "sane_exit: still %d fronteds to leave before effective exit.\n", init_count); return; } /* free session structs */ for (session = sessions; session; session = next) { next = session->next; sane_close ((SANE_Handle *) session); free (session); } sessions = NULL; /* free devices structs */ for (dev = devices; dev; dev = nextdev) { nextdev = dev->next; free (dev->name); free (dev); } devices = NULL; /* now list of devices */ if (devlist) { i = 0; while ((SANE_Device *) devlist[i]) { free ((SANE_Device *) devlist[i]); i++; } free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); } /** @brief probe for all supported devices * This functions tries to probe if any of the supported devices of * the backend is present. Each detected device will be added to the * 'devices' list */ static SANE_Status probe_p5_devices (void) { /**> configuration structure used during attach */ SANEI_Config config; /**> list of configuration options */ SANE_Option_Descriptor *cfg_options[NUM_CFG_OPTIONS]; /**> placeholders pointers for option values */ void *values[NUM_CFG_OPTIONS]; int i; SANE_Status status; DBG (DBG_proc, "probe_p5_devices: start\n"); /* initialize configuration options */ cfg_options[CFG_MODEL_NAME] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); cfg_options[CFG_MODEL_NAME]->name = "modelname"; cfg_options[CFG_MODEL_NAME]->desc = "user provided scanner's model name"; cfg_options[CFG_MODEL_NAME]->type = SANE_TYPE_INT; cfg_options[CFG_MODEL_NAME]->unit = SANE_UNIT_NONE; cfg_options[CFG_MODEL_NAME]->size = sizeof (SANE_Word); cfg_options[CFG_MODEL_NAME]->cap = SANE_CAP_SOFT_SELECT; cfg_options[CFG_MODEL_NAME]->constraint_type = SANE_CONSTRAINT_NONE; values[CFG_MODEL_NAME] = &p5cfg.modelname; /* set configuration options structure */ config.descriptors = cfg_options; config.values = values; config.count = NUM_CFG_OPTIONS; /* generic configure and attach function */ status = sanei_configure_attach (P5_CONFIG_FILE, &config, config_attach); /* free allocated options */ for (i = 0; i < NUM_CFG_OPTIONS; i++) { free (cfg_options[i]); } DBG (DBG_proc, "probe_p5_devices: end\n"); return status; } /** This function is called by sanei_configure_attach to try * to attach the backend to a device specified by the configuration file. * * @param config configuration structure filled with values read * from configuration file * @param devname name of the device to try to attach to, it is * the unprocessed line of the configuration file * * @return status SANE_STATUS_GOOD if no errors (even if no matching * devices found) * SANE_STATUS_INVAL in case of error */ static SANE_Status config_attach (SANEI_Config * config, const char *devname) { /* currently, the config is a global variable so config is useless here */ /* the correct thing would be to have a generic sanei_attach_matching_devices * using an attach function with a config parameter */ config = config; /* the devname has been processed and is ready to be used * directly. The config struct contains all the configuration data for * the corresponding device. Since there is no ressources common to each * backends regarding parallel port, we can directly call the attach * function. */ attach_p5 (devname, config); return SANE_STATUS_GOOD; } /** @brief try to attach to a device by its name * The attach tries to open the given device and match it * with devices handled by the backend. The configuration parameter * contains the values of the already parsed configuration options * from the conf file. * @param config configuration structure filled with values read * from configuration file * @param devicename name of the device to try to attach to, it is * the unprocessed line of the configuration file * * @return status SANE_STATUS_GOOD if no errors (even if no matching * devices found) * SANE_STATUS_NOM_MEM if there isn't enough memory to allocate the * device structure * SANE_STATUS_UNSUPPORTED if the device if unknown by the backend * SANE_STATUS_INVAL in case of other error */ static SANE_Status attach_p5 (const char *devicename, SANEI_Config * config) { struct P5_Device *device; struct P5_Model *model; DBG (DBG_proc, "attach(%s): start\n", devicename); if(config==NULL) { DBG (DBG_warn, "attach: config is NULL\n"); } /* search if we already have it attached */ for (device = devices; device; device = device->next) { if (strcmp (device->name, devicename) == 0) { DBG (DBG_info, "attach: device already attached\n"); DBG (DBG_proc, "attach: exit\n"); return SANE_STATUS_GOOD; } } /** * do physical probe of the device here. In case the device is recognized, * we allocate a device struct and give it options and model. * Else we return SANE_STATUS_UNSUPPORTED. */ model = probe (devicename); if (model == NULL) { DBG (DBG_info, "attach: device %s is not managed by the backend\n", devicename); DBG (DBG_proc, "attach: exit\n"); return SANE_STATUS_UNSUPPORTED; } /* allocate device struct */ device = malloc (sizeof (*device)); if (device == NULL) { return SANE_STATUS_NO_MEM; DBG (DBG_proc, "attach: exit\n"); } memset (device, 0, sizeof (*device)); device->model = model; /* name of the device */ device->name = strdup (devicename); DBG (DBG_info, "attach: found %s %s %s at %s\n", device->model->vendor, device->model->product, device->model->type, device->name); /* we insert new device at start of the chained list */ /* head of the list becomes the next, and start is replaced */ /* with the new session struct */ device->next = devices; devices = device; /* intialization is done at sane_open */ device->initialized = SANE_FALSE; device->calibrated = SANE_FALSE; DBG (DBG_proc, "attach: exit\n"); return SANE_STATUS_GOOD; } /** @brief set initial value for the scanning options * for each sessions, control options are initalized based on the capability * of the model of the physical device. * @param session scanner session to initialize options * @return SANE_STATUS_GOOD on success */ static SANE_Status init_options (struct P5_Session *session) { SANE_Int option, i, min, idx; SANE_Word *dpi_list; P5_Model *model = session->dev->model; DBG (DBG_proc, "init_options: start\n"); /* we first initialize each options with a default value */ memset (session->options, 0, sizeof (session->options[OPT_NUM_OPTS])); for (option = 0; option < NUM_OPTIONS; option++) { session->options[option].descriptor.size = sizeof (SANE_Word); session->options[option].descriptor.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* we set up all the options listed in the P5_Option enum */ /* last option / end of list marker */ session->options[OPT_NUM_OPTS].descriptor.name = SANE_NAME_NUM_OPTIONS; session->options[OPT_NUM_OPTS].descriptor.title = SANE_TITLE_NUM_OPTIONS; session->options[OPT_NUM_OPTS].descriptor.desc = SANE_DESC_NUM_OPTIONS; session->options[OPT_NUM_OPTS].descriptor.type = SANE_TYPE_INT; session->options[OPT_NUM_OPTS].descriptor.cap = SANE_CAP_SOFT_DETECT; session->options[OPT_NUM_OPTS].value.w = NUM_OPTIONS; /* "Standard" group: */ session->options[OPT_STANDARD_GROUP].descriptor.title = SANE_TITLE_STANDARD; session->options[OPT_STANDARD_GROUP].descriptor.name = SANE_NAME_STANDARD; session->options[OPT_STANDARD_GROUP].descriptor.desc = SANE_DESC_STANDARD; session->options[OPT_STANDARD_GROUP].descriptor.type = SANE_TYPE_GROUP; session->options[OPT_STANDARD_GROUP].descriptor.size = 0; session->options[OPT_STANDARD_GROUP].descriptor.cap = 0; session->options[OPT_STANDARD_GROUP].descriptor.constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ session->options[OPT_MODE].descriptor.name = SANE_NAME_SCAN_MODE; session->options[OPT_MODE].descriptor.title = SANE_TITLE_SCAN_MODE; session->options[OPT_MODE].descriptor.desc = SANE_DESC_SCAN_MODE; session->options[OPT_MODE].descriptor.type = SANE_TYPE_STRING; session->options[OPT_MODE].descriptor.cap |= SANE_CAP_AUTOMATIC; session->options[OPT_MODE].descriptor.constraint_type = SANE_CONSTRAINT_STRING_LIST; session->options[OPT_MODE].descriptor.size = max_string_size (mode_list); session->options[OPT_MODE].descriptor.constraint.string_list = mode_list; session->options[OPT_MODE].value.s = strdup (mode_list[0]); /* preview */ session->options[OPT_PREVIEW].descriptor.name = SANE_NAME_PREVIEW; session->options[OPT_PREVIEW].descriptor.title = SANE_TITLE_PREVIEW; session->options[OPT_PREVIEW].descriptor.desc = SANE_DESC_PREVIEW; session->options[OPT_PREVIEW].descriptor.type = SANE_TYPE_BOOL; session->options[OPT_PREVIEW].descriptor.cap |= SANE_CAP_AUTOMATIC; session->options[OPT_PREVIEW].descriptor.unit = SANE_UNIT_NONE; session->options[OPT_PREVIEW].descriptor.constraint_type = SANE_CONSTRAINT_NONE; session->options[OPT_PREVIEW].value.w = SANE_FALSE; /** @brief build resolution list * We merge xdpi and ydpi list to provide only one resolution option control. * This is the most common case for backends and fronteds and give 'square' * pixels. The SANE API allow to control x and y dpi independantly, but this is * rarely done and may confuse both frontends and users. In case a dpi value exists * for one but not for the other, the backend will have to crop data so that the * frontend is unaffected. A common case is that motor resolution (ydpi) is higher * than sensor resolution (xdpi), so scan lines must be scaled up to keep square * pixel when doing sane_read(). * TODO this deserves a dedicated function and some unit testing */ /* find minimum first */ min = 65535; for (i = 0; i < MAX_RESOLUTIONS && model->xdpi_values[i] > 0; i++) { if (model->xdpi_values[i] < min) min = model->xdpi_values[i]; } for (i = 0; i < MAX_RESOLUTIONS && model->ydpi_values[i] > 0; i++) { if (model->ydpi_values[i] < min) min = model->ydpi_values[i]; } dpi_list = malloc ((MAX_RESOLUTIONS * 2 + 1) * sizeof (SANE_Word)); if (!dpi_list) return SANE_STATUS_NO_MEM; dpi_list[1] = min; idx = 2; /* find any value greater than the last used min and * less than the max value */ do { min = 65535; for (i = 0; i < MAX_RESOLUTIONS && model->xdpi_values[i] > 0; i++) { if (model->xdpi_values[i] < min && model->xdpi_values[i] > dpi_list[idx - 1]) min = model->xdpi_values[i]; } for (i = 0; i < MAX_RESOLUTIONS && model->ydpi_values[i] > 0; i++) { if (model->ydpi_values[i] < min && model->ydpi_values[i] > dpi_list[idx - 1]) min = model->ydpi_values[i]; } if (min < 65535) { dpi_list[idx] = min; idx++; } } while (min != 65535); dpi_list[idx] = 0; /* the count of different resolution is put at the beginning */ dpi_list[0] = idx - 1; session->options[OPT_RESOLUTION].descriptor.name = SANE_NAME_SCAN_RESOLUTION; session->options[OPT_RESOLUTION].descriptor.title = SANE_TITLE_SCAN_RESOLUTION; session->options[OPT_RESOLUTION].descriptor.desc = SANE_DESC_SCAN_RESOLUTION; session->options[OPT_RESOLUTION].descriptor.type = SANE_TYPE_INT; session->options[OPT_RESOLUTION].descriptor.cap |= SANE_CAP_AUTOMATIC; session->options[OPT_RESOLUTION].descriptor.unit = SANE_UNIT_DPI; session->options[OPT_RESOLUTION].descriptor.constraint_type = SANE_CONSTRAINT_WORD_LIST; session->options[OPT_RESOLUTION].descriptor.constraint.word_list = dpi_list; /* initial value is lowest available dpi */ session->options[OPT_RESOLUTION].value.w = min; /* "Geometry" group: */ session->options[OPT_GEOMETRY_GROUP].descriptor.title = SANE_TITLE_GEOMETRY; session->options[OPT_GEOMETRY_GROUP].descriptor.name = SANE_NAME_GEOMETRY; session->options[OPT_GEOMETRY_GROUP].descriptor.desc = SANE_DESC_GEOMETRY; session->options[OPT_GEOMETRY_GROUP].descriptor.type = SANE_TYPE_GROUP; session->options[OPT_GEOMETRY_GROUP].descriptor.cap = SANE_CAP_ADVANCED; session->options[OPT_GEOMETRY_GROUP].descriptor.size = 0; session->options[OPT_GEOMETRY_GROUP].descriptor.constraint_type = SANE_CONSTRAINT_NONE; /* adapt the constraint range to the detected model */ x_range.max = model->x_size; y_range.max = model->y_size; /* top-left x */ session->options[OPT_TL_X].descriptor.name = SANE_NAME_SCAN_TL_X; session->options[OPT_TL_X].descriptor.title = SANE_TITLE_SCAN_TL_X; session->options[OPT_TL_X].descriptor.desc = SANE_DESC_SCAN_TL_X; session->options[OPT_TL_X].descriptor.type = SANE_TYPE_FIXED; session->options[OPT_TL_X].descriptor.cap |= SANE_CAP_AUTOMATIC; session->options[OPT_TL_X].descriptor.unit = SANE_UNIT_MM; session->options[OPT_TL_X].descriptor.constraint_type = SANE_CONSTRAINT_RANGE; session->options[OPT_TL_X].descriptor.constraint.range = &x_range; session->options[OPT_TL_X].value.w = 0; /* top-left y */ session->options[OPT_TL_Y].descriptor.name = SANE_NAME_SCAN_TL_Y; session->options[OPT_TL_Y].descriptor.title = SANE_TITLE_SCAN_TL_Y; session->options[OPT_TL_Y].descriptor.desc = SANE_DESC_SCAN_TL_Y; session->options[OPT_TL_Y].descriptor.type = SANE_TYPE_FIXED; session->options[OPT_TL_Y].descriptor.cap |= SANE_CAP_AUTOMATIC; session->options[OPT_TL_Y].descriptor.unit = SANE_UNIT_MM; session->options[OPT_TL_Y].descriptor.constraint_type = SANE_CONSTRAINT_RANGE; session->options[OPT_TL_Y].descriptor.constraint.range = &y_range; session->options[OPT_TL_Y].value.w = 0; /* bottom-right x */ session->options[OPT_BR_X].descriptor.name = SANE_NAME_SCAN_BR_X; session->options[OPT_BR_X].descriptor.title = SANE_TITLE_SCAN_BR_X; session->options[OPT_BR_X].descriptor.desc = SANE_DESC_SCAN_BR_X; session->options[OPT_BR_X].descriptor.type = SANE_TYPE_FIXED; session->options[OPT_BR_X].descriptor.cap |= SANE_CAP_AUTOMATIC; session->options[OPT_BR_X].descriptor.unit = SANE_UNIT_MM; session->options[OPT_BR_X].descriptor.constraint_type = SANE_CONSTRAINT_RANGE; session->options[OPT_BR_X].descriptor.constraint.range = &x_range; session->options[OPT_BR_X].value.w = x_range.max; /* bottom-right y */ session->options[OPT_BR_Y].descriptor.name = SANE_NAME_SCAN_BR_Y; session->options[OPT_BR_Y].descriptor.title = SANE_TITLE_SCAN_BR_Y; session->options[OPT_BR_Y].descriptor.desc = SANE_DESC_SCAN_BR_Y; session->options[OPT_BR_Y].descriptor.type = SANE_TYPE_FIXED; session->options[OPT_BR_Y].descriptor.cap |= SANE_CAP_AUTOMATIC; session->options[OPT_BR_Y].descriptor.unit = SANE_UNIT_MM; session->options[OPT_BR_Y].descriptor.constraint_type = SANE_CONSTRAINT_RANGE; session->options[OPT_BR_Y].descriptor.constraint.range = &y_range; session->options[OPT_BR_Y].value.w = y_range.max; /* sensor group */ session->options[OPT_SENSOR_GROUP].descriptor.name = SANE_NAME_SENSORS; session->options[OPT_SENSOR_GROUP].descriptor.title = SANE_TITLE_SENSORS; session->options[OPT_SENSOR_GROUP].descriptor.desc = SANE_DESC_SENSORS; session->options[OPT_SENSOR_GROUP].descriptor.type = SANE_TYPE_GROUP; session->options[OPT_SENSOR_GROUP].descriptor.constraint_type = SANE_CONSTRAINT_NONE; /* page loaded sensor */ session->options[OPT_PAGE_LOADED_SW].descriptor.name = SANE_NAME_PAGE_LOADED; session->options[OPT_PAGE_LOADED_SW].descriptor.title = SANE_TITLE_PAGE_LOADED; session->options[OPT_PAGE_LOADED_SW].descriptor.desc = SANE_DESC_PAGE_LOADED; session->options[OPT_PAGE_LOADED_SW].descriptor.type = SANE_TYPE_BOOL; session->options[OPT_PAGE_LOADED_SW].descriptor.unit = SANE_UNIT_NONE; session->options[OPT_PAGE_LOADED_SW].descriptor.cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; session->options[OPT_PAGE_LOADED_SW].value.b = 0; /* calibration needed */ session->options[OPT_NEED_CALIBRATION_SW].descriptor.name = "need-calibration"; session->options[OPT_NEED_CALIBRATION_SW].descriptor.title = SANE_I18N ("Need calibration"); session->options[OPT_NEED_CALIBRATION_SW].descriptor.desc = SANE_I18N ("The scanner needs calibration for the current settings"); session->options[OPT_NEED_CALIBRATION_SW].descriptor.type = SANE_TYPE_BOOL; session->options[OPT_NEED_CALIBRATION_SW].descriptor.unit = SANE_UNIT_NONE; session->options[OPT_NEED_CALIBRATION_SW].descriptor.cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; session->options[OPT_NEED_CALIBRATION_SW].value.b = 0; /* button group */ session->options[OPT_BUTTON_GROUP].descriptor.name = "Buttons"; session->options[OPT_BUTTON_GROUP].descriptor.title = SANE_I18N ("Buttons"); session->options[OPT_BUTTON_GROUP].descriptor.desc = SANE_I18N ("Buttons"); session->options[OPT_BUTTON_GROUP].descriptor.type = SANE_TYPE_GROUP; session->options[OPT_BUTTON_GROUP].descriptor.constraint_type = SANE_CONSTRAINT_NONE; /* calibrate button */ session->options[OPT_CALIBRATE].descriptor.name = "calibrate"; session->options[OPT_CALIBRATE].descriptor.title = SANE_I18N ("Calibrate"); session->options[OPT_CALIBRATE].descriptor.desc = SANE_I18N ("Start calibration using special sheet"); session->options[OPT_CALIBRATE].descriptor.type = SANE_TYPE_BUTTON; session->options[OPT_CALIBRATE].descriptor.unit = SANE_UNIT_NONE; session->options[OPT_CALIBRATE].descriptor.cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; session->options[OPT_CALIBRATE].value.b = 0; /* clear calibration cache button */ session->options[OPT_CLEAR_CALIBRATION].descriptor.name = "clear"; session->options[OPT_CLEAR_CALIBRATION].descriptor.title = SANE_I18N ("Clear calibration"); session->options[OPT_CLEAR_CALIBRATION].descriptor.desc = SANE_I18N ("Clear calibration cache"); session->options[OPT_CLEAR_CALIBRATION].descriptor.type = SANE_TYPE_BUTTON; session->options[OPT_CLEAR_CALIBRATION].descriptor.unit = SANE_UNIT_NONE; session->options[OPT_CLEAR_CALIBRATION].descriptor.cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; session->options[OPT_CLEAR_CALIBRATION].value.b = 0; /* until work on calibration isfinished */ DISABLE (OPT_CALIBRATE); DISABLE (OPT_CLEAR_CALIBRATION); DBG (DBG_proc, "init_options: exit\n"); return SANE_STATUS_GOOD; } /** @brief physical probe of a device * This function probes for a scanning device using the given name. If the * device is managed, a model structure describing the device will be returned. * @param devicename low level device to access to probe hardware * @return NULL is the device is unsupported, or a model struct describing the * device. */ P5_Model * probe (const char *devicename) { int fd; /* open parallel port device */ fd = open_pp (devicename); if (fd < 0) { DBG (DBG_error, "probe: failed to open '%s' device!\n", devicename); return NULL; } /* now try to connect to scanner */ if (connect (fd) != SANE_TRUE) { DBG (DBG_error, "probe: failed to connect!\n"); close_pp (fd); return NULL; } /* set up for memory test */ write_reg (fd, REG1, 0x00); write_reg (fd, REG7, 0x00); write_reg (fd, REG0, 0x00); write_reg (fd, REG1, 0x00); write_reg (fd, REGF, 0x80); if (memtest (fd, 0x0100) != SANE_TRUE) { disconnect (fd); close_pp (fd); DBG (DBG_error, "probe: memory test failed!\n"); return NULL; } else { DBG (DBG_info, "memtest() OK...\n"); } write_reg (fd, REG7, 0x00); /* check for document presence 0xC6: present, 0xC3 no document */ test_document (fd); /* release device nd parport for next uses */ disconnect (fd); close_pp (fd); /* for there is only one supported model, so we use hardcoded values */ DBG (DBG_proc, "probe: exit\n"); return &pagepartner_model; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/kvs1025_low.h0000664000175000017500000002031412617742237014771 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. */ /* sane - Scanner Access Now Easy. Panasonic KV-S1020C / KV-S1025C USB scanners. */ #ifndef __KVS1025_LOW_H #define __KVS1025_LOW_H #include "kvs1025_cmds.h" #define VENDOR_ID 0x04DA typedef enum { KV_S1020C = 0x1007, KV_S1025C = 0x1006, KV_S1045C = 0x1010 } KV_MODEL_TYPE; /* Store an integer in 2, 3 or 4 byte in a big-endian array. */ #define Ito16(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 0) & 0xff; \ } #define Ito24(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 0) & 0xff; \ } #define Ito32(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 24) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[3] = ((val) >> 0) & 0xff; \ } /* 32 bits from an array to an integer (eg ntohl). */ #define B32TOI(buf) \ ((((unsigned char *)buf)[0] << 24) | \ (((unsigned char *)buf)[1] << 16) | \ (((unsigned char *)buf)[2] << 8) | \ (((unsigned char *)buf)[3] << 0)) /* 24 bits from an array to an integer. */ #define B24TOI(buf) \ (((unsigned char *)buf)[0] << 16) | \ (((unsigned char *)buf)[1] << 8) | \ (((unsigned char *)buf)[2] << 0)) #define SCSI_FD int #define SCSI_BUFFER_SIZE (0x40000-12) typedef enum { KV_SCSI_BUS = 0x01, KV_USB_BUS = 0x02 } KV_BUS_MODE; typedef enum { SM_BINARY = 0x00, SM_DITHER = 0x01, SM_GRAYSCALE = 0x02, SM_COLOR = 0x05 } KV_SCAN_MODE; typedef struct { unsigned char data[16]; int len; } CDB; typedef struct { int width; int height; } KV_PAPER_SIZE; /* remarked -- KV-S1020C / KV-S1025C supports ADF only typedef enum { TRUPER_ADF = 0, TRUPER_FLATBED = 1 } KV_SCAN_SOURCE; */ /* options */ typedef enum { OPT_NUM_OPTS = 0, /* General options */ OPT_MODE_GROUP, OPT_MODE, /* scanner modes */ OPT_RESOLUTION, /* X and Y resolution */ OPT_DUPLEX, /* Duplex mode */ OPT_SCAN_SOURCE, /* Scan source, fixed to ADF */ OPT_FEEDER_MODE, /* Feeder mode, fixed to Continous */ OPT_LONGPAPER, /* Long paper mode */ OPT_LENGTHCTL, /* Length control mode */ OPT_MANUALFEED, /* Manual feed mode */ OPT_FEED_TIMEOUT, /* Feed timeout */ OPT_DBLFEED, /* Double feed detection mode */ OPT_FIT_TO_PAGE, /* Scanner shrinks image to fit scanned page */ /* Geometry group */ OPT_GEOMETRY_GROUP, OPT_PAPER_SIZE, /* Paper size */ OPT_LANDSCAPE, /* true if landscape; new for Truper 3200/3600 */ OPT_TL_X, /* upper left X */ OPT_TL_Y, /* upper left Y */ OPT_BR_X, /* bottom right X */ OPT_BR_Y, /* bottom right Y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, /* Brightness */ OPT_CONTRAST, /* Contrast */ OPT_AUTOMATIC_THRESHOLD, /* Binary threshold */ OPT_HALFTONE_PATTERN, /* Halftone pattern */ OPT_AUTOMATIC_SEPARATION, /* Automatic separation */ OPT_WHITE_LEVEL, /* White level */ OPT_NOISE_REDUCTION, /* Noise reduction */ OPT_IMAGE_EMPHASIS, /* Image emphasis */ OPT_GAMMA, /* Gamma */ OPT_LAMP, /* Lamp -- color drop out */ OPT_INVERSE, /* Inverse image */ OPT_MIRROR, /* Mirror image */ OPT_JPEG, /* JPEG Compression */ OPT_ROTATE, /* Rotate image */ OPT_SWDESKEW, /* Software deskew */ OPT_SWDESPECK, /* Software despeckle */ OPT_SWDEROTATE, /* Software detect/correct 90 deg. rotation */ OPT_SWCROP, /* Software autocrop */ OPT_SWSKIP, /* Software blank page skip */ /* must come last: */ OPT_NUM_OPTIONS } KV_OPTION; typedef struct { int memory_size; /* in MB */ int min_resolution; /* in DPI */ int max_resolution; /* in DPI */ int step_resolution; /* in DPI */ int support_duplex; /* 1 if true */ int support_lamp; /* 1 if true */ int max_x_range; /* in mm */ int max_y_range; /* in mm */ } KV_SUPPORT_INFO; typedef struct kv_scanner_dev { struct kv_scanner_dev *next; SANE_Device sane; /* Infos from inquiry. */ char scsi_type; char scsi_type_str[32]; char scsi_vendor[12]; char scsi_product[20]; char scsi_version[8]; /* Bus info */ KV_BUS_MODE bus_mode; SANE_Int usb_fd; char device_name[100]; char *scsi_device_name; SCSI_FD scsi_fd; KV_MODEL_TYPE model_type; SANE_Parameters params[2]; /* SCSI handling */ SANE_Byte *buffer0; SANE_Byte *buffer; /* buffer = buffer0 + 12 */ /* for USB bulk transfer, a 12 bytes container is required for each block */ /* Scanning handling. */ int scanning; /* TRUE if a scan is running. */ int current_page; /* the current page number, 0 is page 1 */ int current_side; /* the current side */ int bytes_to_read[2]; /* bytes to read */ /* --------------------------------------------------------------------- */ /* values used by the software enhancment code (deskew, crop, etc) */ SANE_Status deskew_stat; int deskew_vals[2]; double deskew_slope; SANE_Status crop_stat; int crop_vals[4]; /* Support info */ KV_SUPPORT_INFO support_info; SANE_Range x_range, y_range; /* Options */ SANE_Option_Descriptor opt[OPT_NUM_OPTIONS]; Option_Value val[OPT_NUM_OPTIONS]; SANE_Bool option_set; /* Image buffer */ SANE_Byte *img_buffers[2]; SANE_Byte *img_pt[2]; int img_size[2]; } KV_DEV, *PKV_DEV; #define GET_OPT_VAL_W(dev, idx) ((dev)->val[idx].w) #define GET_OPT_VAL_L(dev, idx, token) get_optval_list(dev, idx, \ go_##token##_list, go_##token##_val) #define IS_DUPLEX(dev) GET_OPT_VAL_W(dev, OPT_DUPLEX) /* Prototypes in kvs1025_opt.c */ int get_optval_list (const PKV_DEV dev, int idx, const SANE_String_Const * str_list, const int *val_list); KV_SCAN_MODE kv_get_mode (const PKV_DEV dev); int kv_get_depth (KV_SCAN_MODE mode); void kv_calc_paper_size (const PKV_DEV dev, int *w, int *h); const SANE_Option_Descriptor *kv_get_option_descriptor (PKV_DEV dev, SANE_Int option); void kv_init_options (PKV_DEV dev); SANE_Status kv_control_option (PKV_DEV dev, SANE_Int option, SANE_Action action, void *val, SANE_Int * info); void hexdump (int level, const char *comment, unsigned char *p, int l); void kv_set_window_data (PKV_DEV dev, KV_SCAN_MODE scan_mode, int side, unsigned char *windowdata); /* Prototypes in kvs1025_low.c */ SANE_Status kv_enum_devices (void); void kv_get_devices_list (const SANE_Device *** devices_list); void kv_exit (void); SANE_Status kv_open (PKV_DEV dev); SANE_Bool kv_already_open (PKV_DEV dev); SANE_Status kv_open_by_name (SANE_String_Const devicename, SANE_Handle * handle); void kv_close (PKV_DEV dev); SANE_Status kv_send_command (PKV_DEV dev, PKV_CMD_HEADER header, PKV_CMD_RESPONSE response); /* Commands */ SANE_Status CMD_test_unit_ready (PKV_DEV dev, SANE_Bool * ready); SANE_Status CMD_read_support_info (PKV_DEV dev); SANE_Status CMD_scan (PKV_DEV dev); SANE_Status CMD_set_window (PKV_DEV dev, int side, PKV_CMD_RESPONSE rs); SANE_Status CMD_reset_window (PKV_DEV dev); SANE_Status CMD_get_buff_status (PKV_DEV dev, int *front_size, int *back_size); SANE_Status CMD_wait_buff_status (PKV_DEV dev, int *front_size, int *back_size); SANE_Status CMD_read_pic_elements (PKV_DEV dev, int page, int side, int *width, int *height); SANE_Status CMD_read_image (PKV_DEV dev, int page, int side, unsigned char *buffer, int *psize, KV_CMD_RESPONSE * rs); SANE_Status CMD_wait_document_existanse (PKV_DEV dev); SANE_Status CMD_get_document_existanse (PKV_DEV dev); SANE_Status CMD_set_timeout (PKV_DEV dev, SANE_Word timeout); SANE_Status CMD_request_sense (PKV_DEV dev); /* Scan routines */ SANE_Status AllocateImageBuffer (PKV_DEV dev); SANE_Status ReadImageDataSimplex (PKV_DEV dev, int page); SANE_Status ReadImageDataDuplex (PKV_DEV dev, int page); SANE_Status ReadImageData (PKV_DEV dev, int page); SANE_Status buffer_deskew (PKV_DEV dev, int side); SANE_Status buffer_crop (PKV_DEV dev, int side); SANE_Status buffer_despeck (PKV_DEV dev, int side); int buffer_isblank (PKV_DEV dev, int side); SANE_Status buffer_rotate(PKV_DEV dev, int side); #endif /* #ifndef __KVS1025_LOW_H */ sane-backends-1.0.27/backend/pieusb_buffer.h0000664000175000017500000001115712775312261015615 00000000000000/* sane - Scanner Access Now Easy. pieusb_buffer.h Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIEUSB_BUFFER_H #define PIEUSB_BUFFER_H #include "pieusb.h" #include "../include/sane/sanei_ir.h" struct Pieusb_Read_Buffer { SANE_Uint* data; /* image data - always store as 16 bit values; mmap'ed */ unsigned int data_size; /* size of mmap region */ SANE_Int data_file; /* associated file if memory mapped */ char buffer_name[L_tmpnam]; /* Buffer parameters */ SANE_Int width; /* number of pixels on a line */ SANE_Int height; /* number of lines in buffer */ SANE_Int colors; /* number of colors in a pixel */ SANE_Int depth; /* number of bits of a color */ SANE_Int packing_density; /* number of single color samples packed together */ /* Derived quantities * All derived quantities pertain to the image, not to the buffer */ SANE_Int packet_size_bytes; /* number of bytes of a packet of samples = round_up(depth*packing_density/8) */ SANE_Int line_size_packets; /* number of packets on a single color line = round-down((width+packing_density-1)/packing_density) */ SANE_Int line_size_bytes; /* number of bytes on a single color line = line_size_packets*packet_size_bytes */ SANE_Int image_size_bytes; /* total number of bytes in the buffer (= colors * height * line_size_packets* packet_size_bytes) */ SANE_Int color_index_red; /* color index of the red color plane (-1 if not used) */ SANE_Int color_index_green; /* color index of the green color plane (-1 if not used) */ SANE_Int color_index_blue; /* color index of the blue color plane (-1 if not used) */ SANE_Int color_index_infrared; /* color index of the infrared color plane (-1 if not used) */ /* Reading - byte oriented */ SANE_Uint** p_read; /* array of pointers to next sample to read for each color plane */ SANE_Int read_index[4]; /* location where to read next (color-index, height-index, width-index, byte-index) */ SANE_Int bytes_read; /* number of bytes read from the buffer */ SANE_Int bytes_unread; /* number of bytes not yet read from the buffer */ SANE_Int bytes_written; /* number of bytes written to the buffer */ /* Writing */ SANE_Uint** p_write; /* array of pointers to next byte to write for each color plane */ }; void sanei_pieusb_buffer_get(struct Pieusb_Read_Buffer* buffer, SANE_Byte* data, SANE_Int max_len, SANE_Int* len); SANE_Status sanei_pieusb_buffer_create(struct Pieusb_Read_Buffer* buffer, SANE_Int width, SANE_Int height, SANE_Byte colors, SANE_Byte depth); void sanei_pieusb_buffer_delete(struct Pieusb_Read_Buffer* buffer); SANE_Int sanei_pieusb_buffer_put_full_color_line(struct Pieusb_Read_Buffer* buffer, void* line, int size); SANE_Int sanei_pieusb_buffer_put_single_color_line(struct Pieusb_Read_Buffer* buffer, SANE_Byte color, void* line, SANE_Int size); #endif /* PIEUSB_BUFFER_H */ sane-backends-1.0.27/backend/leo.conf.in0000664000175000017500000000016112112021330014623 00000000000000# The FS-1130 respond to all luns scsi ACROSS * Scanner * * * 0 # LEO S3 scsi "LEO" "LEOScan-S3" /dev/scanner sane-backends-1.0.27/backend/v4l.h0000664000175000017500000002063612206472662013505 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang Updates and bugfixes (C) 2002. 2003 Henning Meier-Geinitz This file is part of the SANE package. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef v4l_h #define v4l_h #ifndef __LINUX_VIDEODEV_H /* Kernel interface */ /* Only the stuff we need. For more features, more defines are needed */ #define VID_TYPE_CAPTURE 1 /* Can capture */ #define VID_TYPE_TUNER 2 /* Can tune */ #define VID_TYPE_TELETEXT 4 /* Does teletext */ #define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ #define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ #define VID_TYPE_CLIPPING 32 /* Can clip */ #define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ #define VID_TYPE_SCALES 128 /* Scalable */ #define VID_TYPE_MONOCHROME 256 /* Monochrome only */ #define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ #define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ #define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ #define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ #define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ struct video_capability { char name[32]; int type; int channels; /* Num channels */ int audios; /* Num audio devices */ int maxwidth; /* Supported width */ int maxheight; /* And height */ int minwidth; /* Supported width */ int minheight; /* And height */ }; struct video_picture { __u16 brightness; __u16 hue; __u16 colour; __u16 contrast; __u16 whiteness; /* Black and white only */ __u16 depth; /* Capture depth */ __u16 palette; /* Palette in use */ #define VIDEO_PALETTE_GREY 1 /* Linear greyscale */ #define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */ #define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */ #define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */ #define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */ #define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */ #define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */ #define VIDEO_PALETTE_YUYV 8 #define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ #define VIDEO_PALETTE_YUV420 10 #define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ #define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ #define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ #define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ #define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */ #define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */ #define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */ #define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */ }; struct video_window { __u32 x,y; /* Position of window */ __u32 width,height; /* Its size */ __u32 chromakey; __u32 flags; struct video_clip *clips; /* Set only */ int clipcount; #define VIDEO_WINDOW_INTERLACE 1 #define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */ #define VIDEO_CLIP_BITMAP -1 /* bitmap is 1024x625, a '1' bit represents a clipped pixel */ #define VIDEO_CLIPMAP_SIZE (128 * 625) }; #define VIDEO_MAX_FRAME 32 struct video_mbuf { int size; /* Total memory to map */ int frames; /* Frames */ int offsets[VIDEO_MAX_FRAME]; }; struct video_mmap { unsigned int frame; /* Frame (0 - n) for double buffer */ int height,width; unsigned int format; /* should be VIDEO_PALETTE_* */ }; struct video_channel { int channel; char name[32]; int tuners; __u32 flags; #define VIDEO_VC_TUNER 1 /* Channel has a tuner */ #define VIDEO_VC_AUDIO 2 /* Channel has audio */ __u16 type; #define VIDEO_TYPE_TV 1 #define VIDEO_TYPE_CAMERA 2 __u16 norm; /* Norm set by channel */ }; #define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ #define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ #define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ #define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */ #define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */ #define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */ #define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */ #define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */ #define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */ #define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ #define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */ #define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */ #define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */ #define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */ #define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */ #define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */ #define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */ #define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */ #define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */ #define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */ #define VIDIOCGUNIT _IOR('v',21, struct video_unit) /* Get attached units */ #define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get subcapture */ #define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set subcapture */ #define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */ #define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */ #define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */ #define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */ #define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */ #define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */ /* end of kernel interface */ #endif /* !__LINUX_VIDEODEV_H */ #include <../include/sane/sane.h> #define MAX_CHANNELS 32 typedef enum { V4L_RES_LOW = 0, V4L_RES_HIGH } V4L_Resolution; typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_CHANNEL, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_HUE, OPT_COLOR, OPT_CONTRAST, OPT_WHITE_LEVEL, /* must come last: */ NUM_OPTIONS } V4L_Option; typedef struct V4L_Device { struct V4L_Device *next; SANE_Device sane; } V4L_Device; typedef struct V4L_Scanner { struct V4L_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; V4L_Resolution resolution; SANE_Parameters params; SANE_String_Const devicename; /* Name of the Device */ int fd; /* Filedescriptor */ SANE_Int user_corner; /* bitmask of user-selected coordinates */ SANE_Bool scanning; SANE_Bool deliver_eof; SANE_Bool is_mmap; /* Do we use mmap ? */ /* state for reading a frame: */ size_t num_bytes; /* # of bytes read so far */ size_t bytes_per_frame; /* total number of bytes in frame */ struct video_capability capability; struct video_picture pict; struct video_window window; struct video_mbuf mbuf; struct video_mmap mmap; SANE_String_Const channel[MAX_CHANNELS]; SANE_Int buffercount; } V4L_Scanner; #endif /* v4l_h */ sane-backends-1.0.27/backend/pieusb_scancmd.c0000664000175000017500000012650013106201017015727 00000000000000/* sane - Scanner Access Now Easy. pieusb_scancmd.c Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ========================================================================= * * Pieusb scanner commands * * Each scanner command has its own function. * See the sort description preceeding each function. * * ========================================================================= */ #define DEBUG_DECLARE_ONLY #include "pieusb.h" #include "pieusb_scancmd.h" #include "pieusb_usb.h" #ifdef HAVE_ALLOCA_H #include #endif #include /* for time() */ static void _prep_scsi_cmd(SANE_Byte* command_bytes, SANE_Byte command, SANE_Word size); /* ========================================================================= * * Pieusb utility functions * * ========================================================================= */ /* * Get the unsigned char value in the array at given offset */ static SANE_Byte _get_byte(SANE_Byte* array, SANE_Byte offset) { return *(array+offset); } /* * Set the array at given offset to the given unsigned char value */ static void _set_byte(SANE_Byte val, SANE_Byte* array, SANE_Byte offset) { *(array+offset) = val; } /* * Get the unsigned short value in the array at given offset. * All data in structures is little-endian, so the LSB comes first * SANE_Int is 4 bytes, but that is not a problem. */ static SANE_Int _get_short(SANE_Byte* array, SANE_Byte offset) { SANE_Int i = *(array+offset+1); i <<= 8; i += *(array+offset); return i; } /* * Put the bytes of a short int value into an unsigned char array * All data in structures is little-endian, so start with LSB */ static void _set_short(SANE_Word val, SANE_Byte* array, SANE_Byte offset) { *(array+offset) = val & 0xFF; *(array+offset+1) = (val>>8) & 0xFF; } /* * Get the signed int value in the array at given offset. * All data in structures is little-endian, so the LSB comes first */ static SANE_Int _get_int(SANE_Byte* array, SANE_Byte offset) { SANE_Int i = *(array+offset+3); i <<= 8; i += *(array+offset+2); i <<= 8; i += *(array+offset+1); i <<= 8; i += *(array+offset); return i; } #if 0 /* unused */ /* * Put the bytes of a signed int value into an unsigned char array * All data in structures is little-endian, so start with LSB */ static void _set_int(SANE_Word val, SANE_Byte* array, SANE_Byte offset) { *(array+offset) = val & 0xFF; *(array+offset+1) = (val>>8) & 0xFF; *(array+offset+2) = (val>>16) & 0xFF; *(array+offset+3) = (val>>24) & 0xFF; } #endif /* * Copy count unsigned char values from src to dst */ static void _copy_bytes(SANE_Byte* dst, SANE_Byte* src, SANE_Byte count) { SANE_Byte k; for (k=0; k>8) & 0xFF; } } /** * Perform a TEST UNIT READY (SCSI command code 0x00) * Returns status->pieusb_status: * - PIEUSB_STATUS_GOOD if device is ready * - PIEUSB_STATUS_DEVICE_BUSY if device is still busy after timeout * - other SANE status code if TEST UNIT READY failed or if it returned * CHECK CONDITION and REQUEST SENSE failed * * @param device_number Device number * @return Pieusb_Command_Status SANE_STATUS_GOOD if ready, SANE_STATUS_DEVICE_BUSY if not */ void sanei_pieusb_cmd_test_unit_ready(SANE_Int device_number, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; DBG (DBG_info_scan, "sanei_pieusb_cmd_test_unit_ready()\n"); _prep_scsi_cmd (command, SCSI_TEST_UNIT_READY, 0); status->pieusb_status = sanei_pieusb_command (device_number, command, NULL, 0); DBG (DBG_info_scan, "sanei_pieusb_cmd_test_unit_ready() return status = %s\n", sane_strstatus(status->pieusb_status)); } /** * slide action * @param action SLIDE_NEXT, SLIDE_PREV, SLIDE_INIT, SLIDE_RELOAD * @return Pieusb_Command_Status */ void sanei_pieusb_cmd_slide(SANE_Int device_number, slide_action action, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define SLIDE_DATA_SIZE 4 SANE_Byte data[SLIDE_DATA_SIZE]; DBG (DBG_info_scan, "sanei_pieusb_cmd_slide(0x%02x)\n", action); _prep_scsi_cmd(command, SCSI_SLIDE, SLIDE_DATA_SIZE); memset(data, '\0', SLIDE_DATA_SIZE); data[0] = action; data[1] = 0x01; status->pieusb_status = sanei_pieusb_command(device_number, command, data, SLIDE_DATA_SIZE); #undef SLIDE_DATA_SIZE } /** * Perform a REQUEST SENSE (SCSI command code 0x03) * Returns status->pieusb_status: * - PIEUSB_STATUS_GOOD is the command executes OK * - other SANE status code if REQUEST SENSE fails * The sense fields in status are always 0. A REQUEST SENSE is not repeated if * the device returns PIEUSB_STATUS_DEVICE_BUSY. * * @param device_number Device number * @param sense Sense data * @param status Command result status * @see struc Pieusb_Sense */ void sanei_pieusb_cmd_get_sense(SANE_Int device_number, struct Pieusb_Sense* sense, struct Pieusb_Command_Status *status, PIEUSB_Status *ret) { SANE_Byte command[SCSI_COMMAND_LEN]; #define DATA_SIZE 14 SANE_Int size = DATA_SIZE; SANE_Byte data[DATA_SIZE]; PIEUSB_Status st; SANE_Char* sd; DBG (DBG_info_scan, "sanei_pieusb_cmd_get_sense()\n"); _prep_scsi_cmd(command, SCSI_REQUEST_SENSE, size); memset(data, '\0', size); st = sanei_pieusb_command(device_number, command, data, size); if (st != PIEUSB_STATUS_GOOD) { status->pieusb_status = st; /*FIXME*/ return; } /* Decode data recieved */ sense->errorCode = _get_byte (data, 0); sense->segment = _get_byte (data, 1); sense->senseKey = _get_byte (data, 2); _copy_bytes (sense->info, data+3, 4); sense->addLength = _get_byte (data, 7); _copy_bytes (sense->cmdInfo, data+8, 4); sense->senseCode = _get_byte (data, 12); sense->senseQualifier = _get_byte (data, 13); status->pieusb_status = PIEUSB_STATUS_GOOD; #undef DATA_SIZE DBG (DBG_info_scan, "\tsense details:\n"); DBG (DBG_info_scan, "\t\terror......... : 0x%02x\n", sense->errorCode); DBG (DBG_info_scan, "\t\tsegment....... : %d\n", sense->segment); DBG (DBG_info_scan, "\t\tsenseKey...... : 0x%02x\n", sense->senseKey); DBG (DBG_info_scan, "\t\tinfo.......... : %02x %02x %02x %02x\n", sense->info[0], sense->info[1], sense->info[2], sense->info[3]); DBG (DBG_info_scan, "\t\taddLength..... : %d\n", sense->addLength); DBG (DBG_info_scan, "\t\tcmdInfo....... : %02x %02x %02x %02x\n", sense->cmdInfo[0], sense->cmdInfo[1], sense->cmdInfo[2], sense->cmdInfo[3]); DBG (DBG_info_scan, "\t\tsenseCode..... : 0x%02x\n", sense->senseCode); DBG (DBG_info_scan, "\t\tsenseQualifier : 0x%02x\n", sense->senseQualifier); sd = sanei_pieusb_decode_sense (sense, ret?ret:&st); DBG (DBG_info_scan, "\tsense: %s\n", sd); free(sd); } /** * Read the scan frame with the specified index. This requires two * commands, one to ask the device to prepare the pattern, and one to read it. * * @param device_number Device number * @param frame Scan frame * @return Pieusb_Command_Status * @see Pieusb_Scan_Frame */ void sanei_pieusb_cmd_get_scan_frame(SANE_Int device_number, SANE_Int index, struct Pieusb_Scan_Frame* frame, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define FRAME_SIZE 256 /* Assumed maximum frame size */ SANE_Int size = FRAME_SIZE; SANE_Byte data[FRAME_SIZE]; PIEUSB_Status st; DBG (DBG_info_scan, "sanei_pieusb_cmd_get_scan_frame()\n"); /* Ask scanner to prepare the scan frame with the given index. Only SCSI_COMMAND_LEN bytes of data. */ _prep_scsi_cmd (command, SCSI_WRITE, SCSI_COMMAND_LEN); memset (data, '\0', SCSI_COMMAND_LEN); data[0] = SCSI_SCAN_FRAME | 0x80; /* set bit 7 means prepare read */ data[4] = index; st = sanei_pieusb_command (device_number, command, data, SCSI_COMMAND_LEN); if (st != PIEUSB_STATUS_GOOD) { status->pieusb_status = st; /* FIXME */ return; } /* Read scan frame */ _prep_scsi_cmd (command, SCSI_READ, size); memset(data, '\0', size); status->pieusb_status = sanei_pieusb_command (device_number, command, data, size); /* Decode data */ frame->index = _get_byte (data, 4); frame->x0 = _get_short (data, 6); frame->y0 = _get_short (data, 8); frame->x1 = _get_short (data, 10); frame->y1 = _get_short (data, 12); DBG (DBG_info_scan, "sanei_pieusb_cmd_get_scan_frame() set:\n"); DBG (DBG_info_scan, " x0,y0 = %d,%d\n", frame->x0, frame->y0); DBG (DBG_info_scan, " x1,y1 = %d,%d\n", frame->x1, frame->y1); DBG (DBG_info_scan, " index = %d\n", frame->index); #undef FRAME_SIZE } /** * command 17 - unknown */ void sanei_pieusb_cmd_17(SANE_Int device_number, SANE_Int value, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define CMD_17_SIZE 6 SANE_Byte data[CMD_17_SIZE]; DBG (DBG_info_scan, "sanei_pieusb_cmd_17(%d)\n", value); _prep_scsi_cmd (command, SCSI_WRITE, CMD_17_SIZE); memset (data, '\0', CMD_17_SIZE); _set_short (SCSI_CMD_17, data, 0); _set_short (2, data, 2); _set_short (value, data, 4); status->pieusb_status = sanei_pieusb_command (device_number, command, data, CMD_17_SIZE); #undef CMD_17_SIZE if (status->pieusb_status != PIEUSB_STATUS_GOOD) { DBG (DBG_info_scan, "sanei_pieusb_cmd_17 failed: 0x%02x\n", status->pieusb_status); return; } } /** * Read the shading data parameters. This requires two * commands, one to ask the device to prepare the value, and one to read it. * * @param device_number Device number * @param shading Shading data parameters * @return Pieusb_Command_Status * @see Pieusb_Shading_Parameters */ void sanei_pieusb_cmd_get_shading_parms(SANE_Int device_number, struct Pieusb_Shading_Parameters_Info* shading, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define SHADING_SIZE 32 #define PREP_READ_SIZE 6 SANE_Int size = SHADING_SIZE; SANE_Byte data[SHADING_SIZE]; int k; DBG (DBG_info_scan, "sanei_pieusb_cmd_get_shading_parms()\n"); /* Ask scanner to prepare the scan frame with the given index. Only SCSI_COMMAND_LEN bytes of data. */ _prep_scsi_cmd (command, SCSI_WRITE, SCSI_COMMAND_LEN); memset (data, '\0', PREP_READ_SIZE); data[0] = SCSI_CALIBRATION_INFO | 0x80; /* set bit 7 means prepare read */ status->pieusb_status = sanei_pieusb_command (device_number, command, data, PREP_READ_SIZE); if (status->pieusb_status != PIEUSB_STATUS_GOOD) { return; } /* Read shading parameters */ _prep_scsi_cmd(command, SCSI_READ, size); memset (data, '\0', size); status->pieusb_status = sanei_pieusb_command (device_number, command, data, size); if (status->pieusb_status != PIEUSB_STATUS_GOOD) { return; } /* Decode data [32 bytes] 0: 95 00 type 2: 1c 00 payload len 4: 04 entries 5: 06 entry size 6: 04 00 ? 8: 00 10 10 14 1a 1d type send recv nlines pixPerLine(2bytes) 14: 08 10 10 14 1a 1d 20: 10 10 10 14 1a 1d 26: 20 10 10 14 1a 1d */ for (k = 0; k < data[4]; k++) { shading[k].type = _get_byte (data, 8 + data[5]*k); shading[k].sendBits = _get_byte (data, 9 + data[5]*k); shading[k].recieveBits = _get_byte (data, 10 + data[5]*k); shading[k].nLines = _get_byte (data, 11 + data[5]*k); shading[k].pixelsPerLine = _get_short (data, 12 + data[5]*k); } #undef PREP_READ_SIZE #undef SHADING_SIZE } /** * Read scanned data from the scanner memory into a byte array. The lines * argument specifies how many lines will be read, the size argument specifies * the total amount of bytes in these lines. Use sanei_pieusb_cmd_get_parameters() to * determine the current line size and the number of available lines.\n * If there is scanned data available, it should be read. Waiting too long * causes the scan to stop, probably because a buffer is filled to its limits * (if so, it is approximately 2Mb in size). I haven't tried what happens if you * start reading after a stop. Reading to fast causes the scanner to return * a busy status, which is not a problem. * This is a SCSI READ command (code 0x08). It is distinguished from the other * READ commands by the context in which it is issued: see sanei_pieusb_cmd_start_scan(). * * @param device_number * @param data * @param lines * @param size * @return Pieusb_Command_Status */ void sanei_pieusb_cmd_get_scanned_lines(SANE_Int device_number, SANE_Byte* data, SANE_Int lines, SANE_Int size, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; DBG (DBG_info_scan, "sanei_pieusb_cmd_get_scanned_lines(): %d lines (%d bytes)\n", lines, size); _prep_scsi_cmd (command, SCSI_READ, lines); memset (data, '\0', size); status->pieusb_status = sanei_pieusb_command (device_number, command, data, size); } /** * Set the scan frame with the given index to the frame. The command is a SCSI * WRITE command (code SCSI_WRITE, write code SCSI_SCAN_FRAME). * * @param device_number Device number * @param index Frame index (0-7) * @param frame Scan frame * @return Pieusb_Command_Status * @see Pieusb_Scan_Frame */ void sanei_pieusb_cmd_set_scan_frame(SANE_Int device_number, SANE_Int index, struct Pieusb_Scan_Frame* frame, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define FRAME_SIZE 14 SANE_Int size = FRAME_SIZE; SANE_Byte data[FRAME_SIZE]; DBG (DBG_info_scan, "sanei_pieusb_cmd_set_scan_frame()\n"); _prep_scsi_cmd(command, SCSI_WRITE, size); DBG (DBG_info_scan, " x0,y0 = %d,%d\n", frame->x0, frame->y0); DBG (DBG_info_scan, " x1,y1 = %d,%d\n", frame->x1, frame->y1); DBG (DBG_info_scan, " index = %d\n", index); /* Code data */ memset (data, '\0', size); _set_short (SCSI_SCAN_FRAME, data, 0); _set_short (size-4, data, 2); /* size: one frame, 5 shorts */ _set_short (index, data, 4); _set_short (frame->x0, data, 6); _set_short (frame->y0, data, 8); _set_short (frame->x1, data, 10); _set_short (frame->y1, data, 12); status->pieusb_status = sanei_pieusb_command (device_number, command, data, size); #undef FRAME_SIZE } /** * Set the relative exposure time to the given values. Only the first * Pieusb_Exposure_Time_Color is used. The command is a SCSI * WRITE command (code SCSI_WRITE, write code SCSI_EXPOSURE). * * @param device_number Device number * @param time Relative exposure time * @return Pieusb_Command_Status * @see Pieusb_Exposure_Time */ void sanei_pieusb_cmd_set_exposure_time(SANE_Int device_number, struct Pieusb_Exposure_Time* time, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define EXPOSURE_DATA_SIZE 8 SANE_Byte data[EXPOSURE_DATA_SIZE]; struct Pieusb_Exposure_Time_Color *exptime; int i; DBG (DBG_info_scan, "sanei_pieusb_cmd_set_exposure_time()\n"); for (i = 0; i < 3; ++i) { /* R, G, B */ _prep_scsi_cmd (command, SCSI_WRITE, EXPOSURE_DATA_SIZE); memset (data, '\0', EXPOSURE_DATA_SIZE); exptime = &(time->color[i]); _set_short (SCSI_EXPOSURE, data, 0); _set_short (EXPOSURE_DATA_SIZE-4, data, 2); /* short: RGB, short: value */ _set_short (exptime->filter, data, 4); /* 1: neutral, 2: R, 4: G, 8: B */ _set_short (exptime->value, data, 6); status->pieusb_status = sanei_pieusb_command (device_number, command, data, EXPOSURE_DATA_SIZE); if (status->pieusb_status != PIEUSB_STATUS_GOOD) break; } #undef EXPOSURE_DATA_SIZE } /** * Set the highlight and shadow levels to the given values. Only the first * Pieusb_Highlight_Shadow_Color is used. The command is a SCSI * WRITE command (code SCSI_WRITE, write code SCSI_HIGHLIGHT_SHADOW). * * @param device_number Device number * @param hgltshdw highlight and shadow level * @return Pieusb_Command_Status * @see Pieusb_Highlight_Shadow */ void sanei_pieusb_cmd_set_highlight_shadow(SANE_Int device_number, struct Pieusb_Highlight_Shadow* hgltshdw, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define HIGHLIGHT_SHADOW_SIZE 8 SANE_Byte data[HIGHLIGHT_SHADOW_SIZE]; struct Pieusb_Highlight_Shadow_Color *color; int i; DBG (DBG_info_scan, "sanei_pieusb_cmd_set_highlight_shadow()\n"); for (i = 0; i < 3; ++i) { /* R, G, B */ _prep_scsi_cmd (command, SCSI_WRITE, HIGHLIGHT_SHADOW_SIZE); memset (data, '\0', HIGHLIGHT_SHADOW_SIZE); color = &(hgltshdw->color[i]); _set_short (SCSI_HIGHLIGHT_SHADOW, data, 0); _set_short (HIGHLIGHT_SHADOW_SIZE-4, data, 2); /* short: RGB, short: value */ _set_short (color->filter, data, 4); /* 1: neutral, 2: R, 4: G, 8: B */ _set_short (color->value, data, 6); status->pieusb_status = sanei_pieusb_command (device_number, command, data, HIGHLIGHT_SHADOW_SIZE); if (status->pieusb_status != PIEUSB_STATUS_GOOD) break; } #undef HIGHLIGHT_SHADOW_SIZE } /* SCSI PARAM, code 0x0F */ /** * Get the parameters of an executed scan, such as width, lines and bytes, which * are needed to calculate the parameters of the READ-commands which read the * actual scan data. * * @param device_number Device number * @param parameters Scan parameters * @return Pieusb_Command_Status * @see Pieusb_Scan_Parameters */ void sanei_pieusb_cmd_get_parameters(SANE_Int device_number, struct Pieusb_Scan_Parameters* parameters, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define PARAMETER_SIZE 18 SANE_Int size = PARAMETER_SIZE; SANE_Byte data[PARAMETER_SIZE]; DBG (DBG_info_scan, "sanei_pieusb_cmd_get_parameters()\n"); _prep_scsi_cmd (command, SCSI_PARAM, size); memset (data, '\0', size); status->pieusb_status = sanei_pieusb_command(device_number, command, data, size); if (status->pieusb_status != PIEUSB_STATUS_GOOD) { return; } /* cyberview: * 0: e6 02 width 0x2e6 - 742 * 2: e0 02 lines 0x2e0 - 736 * 4: e6 02 bytes 0x2e6 - 742 * 6: 08 filterOffeset1 8 * 7: 08 filterOffset2 8 * 8: c9 1c 00 00 period 7369 * c: 00 00 scsi transfer rate * e: d7 00 available lines 215 * 10:00 00 */ /* Decode data recieved */ parameters->width = _get_short(data, 0); parameters->lines = _get_short(data, 2); parameters->bytes = _get_short(data, 4); parameters->filterOffset1 = _get_byte(data, 6); parameters->filterOffset2 = _get_byte(data, 7); parameters->period = _get_int(data, 8); /* unused */ parameters->scsiTransferRate = _get_short(data, 12); /* unused */ parameters->availableLines = _get_short(data, 14); DBG (DBG_info_scan, "sanei_pieusb_cmd_get_parameters() read:\n"); DBG (DBG_info_scan, " width = %d\n", parameters->width); DBG (DBG_info_scan, " lines = %d\n", parameters->lines); DBG (DBG_info_scan, " bytes = %d\n", parameters->bytes); DBG (DBG_info_scan, " offset1 = %d\n", parameters->filterOffset1); DBG (DBG_info_scan, " offset2 = %d\n", parameters->filterOffset2); DBG (DBG_info_scan, " available lines = %d\n", parameters->availableLines); #undef PARAMETER_SIZE } /** * Read INQUIRY block from device (SCSI command code 0x12). This block contains * information about the properties of the scanner. * Returns status->pieusb_status: * - PIEUSB_STATUS_GOOD if the INQUIRY command succeeded * - PIEUSB_STATUS_DEVICE_BUSY if device is busy after repeat retries * - other SANE status code if INQUIRY failed or if it returned CHECK CONDITION * and REQUEST SENSE failed * * @param device_number Device number * @param data Input or output data buffer * @param size Size of the data buffer * @return Pieusb_Command_Status * @see Pieusb_Scanner_Properties */ void sanei_pieusb_cmd_inquiry(SANE_Int device_number, struct Pieusb_Scanner_Properties* inq, SANE_Byte size, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define INQUIRY_SIZE 256 SANE_Byte data[INQUIRY_SIZE]; int k; DBG (DBG_info_scan, "sanei_pieusb_cmd_inquiry()\n"); _prep_scsi_cmd (command, SCSI_INQUIRY, size); memset (data, '\0', INQUIRY_SIZE); /* size may be less than INQUIRY_SIZE, so prevent returning noise */ status->pieusb_status = sanei_pieusb_command (device_number, command, data, size); if (status->pieusb_status != PIEUSB_STATUS_GOOD) { return; } /* Decode data recieved */ inq->deviceType = _get_byte(data, 0); inq->additionalLength = _get_byte(data, 4); _copy_bytes((SANE_Byte*)(inq->vendor), data+8, 8); /* Note: not 0-terminated */ _copy_bytes((SANE_Byte*)(inq->product), data+16, 16); /* Note: not 0-terminated */ _copy_bytes((SANE_Byte*)(inq->productRevision), data+32, 4); /* Note: not 0-terminated */ /* 1st Vendor-specific block, 20 bytes, see pie_get_inquiry_values(), partially: */ inq->maxResolutionX = _get_short(data, 36); inq->maxResolutionY = _get_short(data, 38); inq->maxScanWidth = _get_short(data, 40); inq->maxScanHeight = _get_short(data, 42); inq->filters = _get_byte(data, 44); inq->colorDepths = _get_byte(data, 45); inq->colorFormat = _get_byte(data, 46); inq->imageFormat = _get_byte(data, 48); inq->scanCapability = _get_byte(data, 49); inq->optionalDevices = _get_byte(data, 50); inq->enhancements = _get_byte(data, 51); inq->gammaBits = _get_byte(data, 52); inq->lastFilter = _get_byte(data, 53); inq->previewScanResolution = _get_short(data, 54); /* 2nd vendor specific block (36 bytes at offset 96) */ _copy_bytes((SANE_Byte*)(inq->firmwareVersion), data+96, 4); inq->firmwareVersion[4]=0x00; inq->halftones = _get_byte(data, 100); inq->minumumHighlight = _get_byte(data, 101); inq->maximumShadow = _get_byte(data, 102); inq->calibrationEquation = _get_byte(data, 103); inq->maximumExposure = _get_short(data ,104); inq->minimumExposure = _get_short(data ,106); inq->x0 = _get_short(data, 108); inq->y0 = _get_short(data, 110); inq->x1 = _get_short(data, 112); inq->y1 = _get_short(data, 114); inq->model = _get_short(data, 116); _copy_bytes((SANE_Byte*)(inq->production), data+120, 4); _copy_bytes((SANE_Byte*)(inq->timestamp), data+124, 20); _copy_bytes((SANE_Byte*)(inq->signature), data+144, 40); /* remove newline in signature */ for (k=0; k<40; k++) if (inq->signature[k]==0x0a || inq->signature[k]==0x0d) inq->signature[k]=' '; #undef INQUIRY_SIZE } /** * Set scan mode parameters, such as resolution, colors to scan, color depth, * color format, and a couple of scan quality settings (sharpen, skip * calibration, fast infrared). It performs the SCSI-command MODE SELECT, * code 0x15. * * @param device_number Device number * @param mode Mode parameters * @return Pieusb_Command_Status * @see Pieusb_Mode */ void sanei_pieusb_cmd_set_mode(SANE_Int device_number, struct Pieusb_Mode* mode, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define MODE_SIZE 16 SANE_Int size = MODE_SIZE; SANE_Byte data[MODE_SIZE]; SANE_Byte quality; DBG (DBG_info_scan, "sanei_pieusb_cmd_set_mode()\n"); _prep_scsi_cmd(command, SCSI_MODE_SELECT, size); DBG (DBG_info_scan, "sanei_pieusb_cmd_set_mode() set:\n"); DBG (DBG_info_scan, " resolution = %d\n", mode->resolution); DBG (DBG_info_scan, " passes = %02x\n", mode->passes); DBG (DBG_info_scan, " depth = %02x\n", mode->colorDepth); DBG (DBG_info_scan, " color format = %02x\n", mode->colorFormat); DBG (DBG_info_scan, " sharpen = %d\n", mode->sharpen); DBG (DBG_info_scan, " skip calibration = %d\n", mode->skipShadingAnalysis); DBG (DBG_info_scan, " fast infrared = %d\n", mode->fastInfrared); DBG (DBG_info_scan, " halftone pattern = %d\n", mode->halftonePattern); DBG (DBG_info_scan, " line threshold = %d\n", mode->lineThreshold); /* Code data */ /* cyberview * 00 0f entries * f4 01 resolution 500 * 80 RGB (90: RGBI) * 04 color depth (4: 8 bit, 20: 16 bit) * 04 color format * 00 * 01 byte order * 08 quality bitmask: 80=fast infrared, 08=skip shading analysis, 02=sharpen * 00 00 * 00 halftone pattern * 80 line threshold * 10 00 * * pieusb * 0: 00 0f * 2: e8 03 resolution 1000 * 4: 80 passes * 5: 04 color depth * 6: 04 color format * 7: 00 * 8: 01 byte order * 9: 02 quality bitmask: sharpen * a: 00 00 * c: 00 halftone pattern * d: 7f line threshold * e: 00 00 */ memset (data, '\0', size); _set_byte (size-1, data, 1); _set_short (mode->resolution, data, 2); _set_byte (mode->passes, data, 4); _set_byte (mode->colorDepth, data, 5); _set_byte (mode->colorFormat, data, 6); _set_byte (mode->byteOrder, data, 8); quality = 0x00; if (mode->sharpen) quality |= 0x02; if (mode->skipShadingAnalysis) quality |= 0x08; if (mode->fastInfrared) quality |= 0x80; _set_byte (quality, data, 9); _set_byte (mode->halftonePattern, data, 12); _set_byte (mode->lineThreshold, data, 13); _set_byte (0x10, data, 14); /* ? */ status->pieusb_status = sanei_pieusb_command (device_number, command, data, size); #undef MODE_SIZE } /* SCSI COPY, code 0x18 */ /** * Get the currently used CCD-mask, which defines which pixels have been used in * the scan, and which allows to relate scan data to shading data. A mask is a * 5340 byte array which consists only contains the values 0x00 and 0x70. A * value of 0x00 indicates the pixel is used, a value of 0x70 that it is not.\n * The number of 0x00 bytes equals the number of pixels on a line.\n * The mask begins with a number of 0x70 bytes equal to the scan frame x0-value * divided by 2.\n * The SCSI-command COPY (code 0x18) is used for function. * * @param device_number Device number * @param mask * @return Pieusb_Command_Status */ void sanei_pieusb_cmd_get_ccd_mask(SANE_Int device_number, SANE_Byte* mask, SANE_Int mask_size, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; DBG (DBG_info_scan, "sanei_pieusb_cmd_get_ccd_mask()\n"); _prep_scsi_cmd (command, SCSI_COPY, mask_size); memset (mask, '\0', mask_size); status->pieusb_status = sanei_pieusb_command (device_number, command, mask, mask_size); } /** * Get scan mode parameters, such as resolution, colors to scan, color depth, * color format, and a couple of scan quality settings (sharpen, skip * calibration, fast infrared). It performs the SCSI-command MODE SELECT, * code 0x1A. * * @param device_number Device number * @param mode Mode parameters * @return Pieusb_Command_Status * @see Pieusb_Mode */ void sanei_pieusb_cmd_get_mode(SANE_Int device_number, struct Pieusb_Mode* mode, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define MODE_SIZE 16 SANE_Int size = MODE_SIZE; SANE_Byte data[MODE_SIZE]; SANE_Byte quality; DBG (DBG_info_scan, "sanei_pieusb_cmd_get_mode()\n"); _prep_scsi_cmd (command, SCSI_MODE_SENSE, size); memset (data, '\0', size); status->pieusb_status = sanei_pieusb_command(device_number, command, data, size); if (status->pieusb_status != PIEUSB_STATUS_GOOD) { return; } /* Decode data recieved */ mode->resolution = _get_short (data, 2); mode->passes = _get_byte (data, 4); mode->colorDepth = _get_byte (data, 5); mode->colorFormat = _get_byte (data, 6); mode->byteOrder = _get_byte (data, 8); quality = _get_byte (data, 9); mode->sharpen = (quality |= 0x02) ? SANE_TRUE : SANE_FALSE; mode->skipShadingAnalysis = (quality |= 0x08) ? SANE_TRUE : SANE_FALSE; mode->fastInfrared = (quality |= 0x80) ? SANE_TRUE : SANE_FALSE; mode->halftonePattern = _get_byte (data, 12); mode->lineThreshold = _get_byte (data, 13); DBG (DBG_info_scan, "cmdGetMode():\n"); DBG (DBG_info_scan, " resolution = %d\n", mode->resolution); DBG (DBG_info_scan, " passes = %02x\n", mode->passes); DBG (DBG_info_scan, " depth = %02x\n", mode->colorDepth); DBG (DBG_info_scan, " color format = %02x\n", mode->colorFormat); DBG (DBG_info_scan, " sharpen = %d\n", mode->sharpen); DBG (DBG_info_scan, " skip calibration = %d\n", mode->skipShadingAnalysis); DBG (DBG_info_scan, " fast infrared = %d\n", mode->fastInfrared); DBG (DBG_info_scan, " halftone pattern = %d\n", mode->halftonePattern); DBG (DBG_info_scan, " line threshold = %d\n", mode->lineThreshold); #undef MODE_SIZE } /** * Start a scan (SCSI SCAN command, code 0x1B, size byte = 0x01).\n * There are four phases in a scan process. During each phase a limited number of * commands is available. The phases are:\n * 1. Calibration phase: make previously collected shading correction data available\n * 2. Line-by-line scan & read phase\n * 3. Output CCD-mask phase\n * 4. Scan and output scan data phase\n * * The calibration phase is skipped if Pieusb_Mode.skipCalibration is set. If * the scanner determines a calibration is necessary, a CHECK CONDIDITION response * is returned. Available command during this phase:\n * 1. sanei_pieusb_cmd_test_unit_ready()\n * 2. sanei_pieusb_cmd_get_scanned_lines(): read shading correction lines\n * 3. sanei_pieusb_cmd_stop_scan: abort scanning process\n * 4. sanei_pieusb_cmd_get_gain_offset() : the settings are generated during the initialisation of this phase, so they are current\n * 5. cmdSetSettings(): settings take effect in the next scan phase\n\n * The line-by-line phase is only entered if Pieusb_Mode.div_10[0] bit 5 is * set. It is not implemented.\n\n * In the CCD-mask output phase the CCD-mask is read. Available command during this phase:\n * 1. sanei_pieusb_cmd_test_unit_ready()\n * 2. sanei_pieusb_cmd_get_ccd_mask()\n * 3. sanei_pieusb_cmd_stop_scan: abort scanning process\n\n * In the 'scan and output scan data' phase, the slide is scanned while data is * read in the mean time. Available command during this phase:\n * 1. sanei_pieusb_cmd_test_unit_ready()\n * 2. sanei_pieusb_cmd_get_scanned_lines()\n * 2. sanei_pieusb_cmd_get_parameters()\n * 4. sanei_pieusb_cmd_stop_scan: abort scanning process\n * * @param device_number Device number * @return Pieusb_Command_Status */ void sanei_pieusb_cmd_start_scan(SANE_Int device_number, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; DBG (DBG_info_scan, "sanei_pieusb_cmd_start_scan()\n"); _prep_scsi_cmd (command, SCSI_SCAN, 1); status->pieusb_status = sanei_pieusb_command (device_number, command, NULL, 0); } /** * Stop a scan started with sanei_pieusb_cmd_start_scan(). It issues a SCSI SCAN command, * code 0x1B, with size byte = 0x00. * * @param device_number Device number * @return Pieusb_Command_Status */ void sanei_pieusb_cmd_stop_scan(SANE_Int device_number, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; DBG (DBG_info_scan, "sanei_pieusb_cmd_stop_scan()\n"); _prep_scsi_cmd (command, SCSI_SCAN, 0); status->pieusb_status = sanei_pieusb_command (device_number, command, NULL, 0); } /** * Set scan head to a specific position, depending on the value for mode:\n * mode = 1: Returns the scan head to the resting position, after a short move * forward. If this command is left out between two scans, the second scan is * up-down-mirrored, and scanning starts where the proevious scan stopped.\n * mode = 2: Resets the scan head an then moves it forward depending on 'size', * but it is a bit unpredictable to what position. The scanner may attempt to * move the head past its physical end position. The mode is not implemented.\n * mode = 3: This command positions the scan head to the start of the slide.\n * mode = 4 or 5: The command forwards (4) or retreats (5) the scan head the * given amount of steps (in size).\n * The SCSI code is 0xD2, there is no related command name. * * @param device_number Device number * @param mode * @param size * @return Pieusb_Command_Status */ void sanei_pieusb_cmd_set_scan_head(SANE_Int device_number, SANE_Int mode, SANE_Int steps, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define SCAN_HEAD_SIZE 4 SANE_Int size = SCAN_HEAD_SIZE; SANE_Byte data[SCAN_HEAD_SIZE]; DBG (DBG_info_scan, "sanei_pieusb_cmd_set_scan_head()\n"); _prep_scsi_cmd (command, SCSI_SET_SCAN_HEAD, size); /* Code data */ memset (data, '\0', size); switch (mode) { case 1: data[0] = 2; break; case 2: DBG (DBG_error, "sanei_pieusb_cmd_set_scan_head() mode 2 unreliable, possibly dangerous\n"); status->pieusb_status = PIEUSB_STATUS_INVAL; return; case 3: data[0] = 8; break; case 4: data[0] = 0; /* forward */ data[2] = (steps>>8) & 0xFF; data[3] = steps & 0xFF; break; case 5: data[0] = 1; /* backward */ data[2] = (steps>>8) & 0xFF; data[3] = steps & 0xFF; break; } status->pieusb_status = sanei_pieusb_command(device_number, command, data, size); #undef SCAN_HEAD_SIZE } /** * Get internal scanner settings which have resulted from an auto-calibration * procedure. This procedure only runs when calibrating (Scan phase 1), so the * data returned are relatively static.\n * The SCSI code is 0xD7, there is no related command name. * * @param device_number Device number * @param settings Settings for gain and offset for the four colors RGBI * @return Pieusb_Command_Status * @see Pieusb_Settings */ void sanei_pieusb_cmd_get_gain_offset(SANE_Int device_number, struct Pieusb_Settings* settings, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define GAIN_OFFSET_SIZE 103 SANE_Int size = GAIN_OFFSET_SIZE; SANE_Byte data[GAIN_OFFSET_SIZE]; int k; SANE_Byte val[3]; DBG (DBG_info_scan, "sanei_pieusb_cmd_get_gain_offset()\n"); _prep_scsi_cmd (command, SCSI_READ_GAIN_OFFSET, size); memset (data, '\0', size); status->pieusb_status = sanei_pieusb_command(device_number, command, data, size); if (status->pieusb_status != PIEUSB_STATUS_GOOD) { return; } /* Decode data received */ _get_shorts (settings->saturationLevel, data+54, 3); _get_shorts (settings->exposureTime, data+60, 3); _copy_bytes (val, data+66, 3); for (k = 0; k < 3; k++) settings->offset[k] = val[k]; _copy_bytes (val, data+72, 3); for (k = 0; k < 3; k++) settings->gain[k] = val[k]; settings->light = _get_byte (data, 75); settings->exposureTime[3] = _get_short (data, 98); settings->offset[3] = _get_byte (data, 100); settings->gain[3] = _get_byte (data, 102); DBG (DBG_info, "sanei_pieusb_cmd_get_gain_offset() set:\n"); DBG (DBG_info, " saturationlevels = %d-%d-%d\n", settings->saturationLevel[0], settings->saturationLevel[1], settings->saturationLevel[2]); DBG (DBG_info, " ---\n"); DBG (DBG_info, " exposure times = %d-%d-%d-%d\n", settings->exposureTime[0], settings->exposureTime[1], settings->exposureTime[2], settings->exposureTime[3]); DBG (DBG_info, " gain = %d-%d-%d-%d\n", settings->gain[0], settings->gain[1], settings->gain[2], settings->gain[3]); DBG (DBG_info, " offset = %d-%d-%d-%d\n", settings->offset[0], settings->offset[1], settings->offset[2], settings->offset[3]); DBG (DBG_info, " light = %02x\n", settings->light); DBG (DBG_info, " double times = %02x\n", settings->doubleTimes); DBG (DBG_info, " extra entries = %02x\n", settings->extraEntries); #undef GAIN_OFFSET_SIZE } /** * Set internal scanner settings such as gain and offset.\n * There are two effective moments for this command:\n * 1. For a scan without calibration phase: before the sanei_pieusb_cmd_start_scan() command; * 2. For a sccan with calibration phase: before (or during) reading the shading reference data. * The SCSI code is 0xDC, there is no related command name. * * @param device_number Device number * @param settings Settings for gain and offset for the four colors RGBI * @return Pieusb_Command_Status * @see Pieusb_Settings */ void sanei_pieusb_cmd_set_gain_offset(SANE_Int device_number, struct Pieusb_Settings* settings, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define GAIN_OFFSET_SIZE 29 SANE_Int size = GAIN_OFFSET_SIZE; SANE_Byte data[GAIN_OFFSET_SIZE]; int k; SANE_Byte val[3]; DBG (DBG_info_scan, "sanei_pieusb_cmd_set_gain_offset()\n"); _prep_scsi_cmd (command, SCSI_WRITE_GAIN_OFFSET, size); DBG (DBG_info, "sanei_pieusb_cmd_set_gain_offset() set:\n"); DBG (DBG_info, " exposure times = %d-%d-%d-%d\n", settings->exposureTime[0], settings->exposureTime[1], settings->exposureTime[2], settings->exposureTime[3]); DBG (DBG_info, " gain = %d-%d-%d-%d\n", settings->gain[0], settings->gain[1], settings->gain[2], settings->gain[3]); DBG (DBG_info, " offset = %d-%d-%d-%d\n", settings->offset[0], settings->offset[1], settings->offset[2], settings->offset[3]); DBG (DBG_info, " light = %02x\n", settings->light); DBG (DBG_info, " double times = %02x\n", settings->doubleTimes); DBG (DBG_info, " extra entries = %02x\n", settings->extraEntries); /* Code data */ memset (data, '\0', size); _set_shorts (settings->exposureTime, data, 3); for (k = 0; k < 3; k++) { val[k] = settings->offset[k]; } _copy_bytes (data + 6, val, 3); for (k = 0; k < 3; k++) { val[k] = settings->gain[k]; } _copy_bytes (data + 12, val, 3); _set_byte (settings->light, data, 15); _set_byte (settings->extraEntries, data, 16); _set_byte (settings->doubleTimes, data, 17); _set_short (settings->exposureTime[3], data, 18); _set_byte (settings->offset[3], data, 20); _set_byte (settings->gain[3], data, 22); /* * pieusb-get_gain_offset: * 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 00000030: a9 00 88 00 b1 00 00 00 00 00 00 00 04 10 04 10 )...1........... * 00000040: 04 10 53 4f 6e 00 00 00 2e 21 21 05 04 10 df 2d ..SOn....!!..._- * 00000050: a3 5c e7 f2 a1 2c b3 c4 42 df 32 42 eb 82 8e e0 #\gr!,3DB_2Bk..` * 00000060: 87 be 04 10 4f 00 2c .>..O., * * cyberview: * 00000000: 65 22 57 18 19 19 - exposure time RGB * 00000006: 51 4e 6a - offset RGB * 00000009: 00 00 00 * 0000000c: 21 21 21 - gain RGB * 0000000f: 05 - light * 00000010: 01 - extra entries * 00000011: 00 - double times * 00000012: 04 10 - exposure time I * 00000014: 4e 00 - offset I * 00000016: 2a - gain I * 00000017: 00 00 00 00 00 00 * * pieusb: * 00000000: 04 10 04 10 04 10 - exposure time RGB * 00000006: 53 4f 6e - offset RGB * 00000009: 00 00 00 * 0000000c: 2e 21 21 - gain RGB * 0000000f: 05 - light * 00000010: 00 - extra entries * 00000011: 00 - double times * 00000012: 04 10 - exposure time I * 00000014: 4f 00 - offset I * 00000016: 2c - gain I * 00000017: 00 00 00 00 00 00 */ status->pieusb_status = sanei_pieusb_command(device_number, command, data, size); #undef GAIN_OFFSET_SIZE } /** * Get scanner state information: button pushed, * warming up, scanning. * * @param device_number Device number * @param state State information * @return Pieusb_Command_Status */ void sanei_pieusb_cmd_read_state(SANE_Int device_number, struct Pieusb_Scanner_State* state, struct Pieusb_Command_Status *status) { SANE_Byte command[SCSI_COMMAND_LEN]; #define GET_STATE_SIZE 12 SANE_Byte data[GET_STATE_SIZE]; SANE_Int size = GET_STATE_SIZE; /* Execute READ STATUS command */ DBG (DBG_info_scan, "sanei_pieusb_cmd_read_state()\n"); _prep_scsi_cmd (command, SCSI_READ_STATE, size); memset (data, '\0', size); status->pieusb_status = sanei_pieusb_command (device_number, command, data, size); if (status->pieusb_status == PIEUSB_STATUS_WARMING_UP || status->pieusb_status == PIEUSB_STATUS_DEVICE_BUSY) { data[5] = 1; status->pieusb_status = PIEUSB_STATUS_GOOD; } /* Decode data recieved */ state->buttonPushed = _get_byte(data, 0); state->warmingUp = _get_byte(data, 5); state->scanning = _get_byte(data, 6); /* state->busy = _get_byte(data, 8); */ DBG (DBG_info_scan, "sanei_pieusb_cmd_read_state(): button %d, warmingUp %d, scanning %d, busy? %d\n", state->buttonPushed, state->warmingUp, state->scanning, _get_byte(data, 8)); #undef GET_STATE_SIZE } /** * Prepare SCSI_COMMAND_LEN-byte command array with command code and size value * * @param command * @param code * @param size */ static void _prep_scsi_cmd(SANE_Byte* command, SANE_Byte code, SANE_Word size) { memset(command, '\0', SCSI_COMMAND_LEN); command[0] = code; command[3] = (size>>8) & 0xFF; /* lsb first */ command[4] = size & 0xFF; } sane-backends-1.0.27/backend/u12-tpa.c0000664000175000017500000003673012112021330014140 00000000000000/* @file u12-pp_tpa.c * @brief Here we find some adjustments according to the scan source. * * based on sources acquired from Plustek Inc. * Copyright (C) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - cleanup * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /** this function does some reshading, when scanning negatives on an ASIC 98003 * based scanner */ static void u12tpa_Reshading( U12_Device *dev ) { SANE_Byte bHi[3], bHiLeft[3], bHiRight[3]; u_long i, dwR, dwG, dwB, dwSum; u_long dwIndex, dwIndexRight, dwIndexLeft; DataPointer RedPtr, GreenPtr, BluePtr; TimerDef timer; DBG( _DBG_INFO, "u12tpa_Reshading()\n" ); bHi[0] = bHi[1] = bHi[2] = 0; dev->scan.negScan[1].exposureTime = 144; dev->scan.negScan[1].xStepTime = 18; dev->scan.negScan[2].exposureTime = 144; dev->scan.negScan[2].xStepTime = 36; dev->scan.negScan[3].exposureTime = 144; dev->scan.negScan[3].xStepTime = 72; dev->scan.negScan[4].exposureTime = 144; dev->scan.negScan[4].xStepTime = 144; dev->shade.wExposure = dev->scan.negScan[dev->scan.dpiIdx].exposureTime; dev->shade.wXStep = dev->scan.negScan[dev->scan.dpiIdx].xStepTime; u12io_StartTimer( &timer, _SECOND ); u12io_ResetFifoLen(); while(!(u12io_GetScanState( dev ) & _SCANSTATE_STOP) && (!u12io_CheckTimer(&timer))); u12io_DataToRegister( dev, REG_XSTEPTIME, (SANE_Byte)(dev->regs.RD_LineControl >> 4)); _DODELAY( 12 ); u12motor_PositionYProc( dev, _NEG_SHADING_OFFS ); u12io_DataToRegister( dev, REG_XSTEPTIME, dev->regs.RD_XStepTime ); dev->regs.RD_ScanControl = _SCAN_BYTEMODE; u12hw_SelectLampSource( dev ); u12io_DataToRegister( dev, REG_LINECONTROL, _LOBYTE(dev->shade.wExposure)); u12io_DataToRegister( dev, REG_XSTEPTIME, _LOBYTE(dev->shade.wXStep)); dev->regs.RD_LineControl = _LOBYTE(dev->shade.wExposure); dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure); dev->regs.RD_XStepTime = (SANE_Byte)(dev->shade.wExposure); dev->regs.RD_ModeControl = _ModeScan; dev->regs.RD_Motor0Control = _FORWARD_MOTOR; dev->regs.RD_Origin = (u_short)dev->scan.negBegin; dev->regs.RD_Pixels = _NEG_PAGEWIDTH600; memset( dev->scanStates, 0, _SCANSTATE_BYTES ); /* put 9 scan states to make sure there are 8 lines available at least */ for( i = 0; i <= 12; i++) dev->scanStates[i] = 0x8f; u12io_PutOnAllRegisters( dev ); _DODELAY( 70 ); /* prepare the buffers... */ memset( dev->bufs.TpaBuf.pb, 0, _SIZE_TPA_DATA_BUF ); RedPtr.pb = dev->bufs.b1.pShadingMap; GreenPtr.pb = RedPtr.pb + _NEG_PAGEWIDTH600; BluePtr.pb = GreenPtr.pb + _NEG_PAGEWIDTH600; for( dwSum = 8; dwSum--; ) { u12io_ReadOneShadingLine( dev, dev->bufs.b1.pShadingMap, _NEG_PAGEWIDTH600 ); for( i = 0; i < _NEG_PAGEWIDTH600; i++) { dev->bufs.TpaBuf.pusrgb[i].Red += RedPtr.pb[i]; dev->bufs.TpaBuf.pusrgb[i].Green += GreenPtr.pb[i]; dev->bufs.TpaBuf.pusrgb[i].Blue += BluePtr.pb[i]; } } for( i = 0; i < (_NEG_PAGEWIDTH600 * 3UL); i++ ) dev->bufs.TpaBuf.pb[i] = dev->bufs.TpaBuf.pw[i] >> 3; RedPtr.pb = dev->bufs.TpaBuf.pb; /* Convert RGB to gray scale (Brightness), and average 16 pixels */ for( bHiRight[1] = 0, i = dwIndexRight = 0; i < _NEG_PAGEWIDTH600 / 2; i += 16 ) { bHiRight [0] = (SANE_Byte)(((((u_long) RedPtr.pbrgb [i].Red + (u_long) RedPtr.pbrgb[i + 1].Red + (u_long) RedPtr.pbrgb[i + 2].Red + (u_long) RedPtr.pbrgb[i + 3].Red + (u_long) RedPtr.pbrgb[i + 4].Red + (u_long) RedPtr.pbrgb[i + 5].Red + (u_long) RedPtr.pbrgb[i + 6].Red + (u_long) RedPtr.pbrgb[i + 7].Red + (u_long) RedPtr.pbrgb[i + 8].Red + (u_long) RedPtr.pbrgb[i + 9].Red + (u_long) RedPtr.pbrgb[i + 10].Red + (u_long) RedPtr.pbrgb[i + 11].Red + (u_long) RedPtr.pbrgb[i + 12].Red + (u_long) RedPtr.pbrgb[i + 13].Red + (u_long) RedPtr.pbrgb[i + 14].Red + (u_long) RedPtr.pbrgb[i + 15].Red) >> 4) * 30UL + (((u_long) RedPtr.pbrgb[i].Green + (u_long) RedPtr.pbrgb[i + 1].Green + (u_long) RedPtr.pbrgb[i + 2].Green + (u_long) RedPtr.pbrgb[i + 3].Green + (u_long) RedPtr.pbrgb[i + 4].Green + (u_long) RedPtr.pbrgb[i + 5].Green + (u_long) RedPtr.pbrgb[i + 6].Green + (u_long) RedPtr.pbrgb[i + 7].Green + (u_long) RedPtr.pbrgb[i + 8].Green + (u_long) RedPtr.pbrgb[i + 9].Green + (u_long) RedPtr.pbrgb[i + 10].Green + (u_long) RedPtr.pbrgb[i + 11].Green + (u_long) RedPtr.pbrgb[i + 12].Green + (u_long) RedPtr.pbrgb[i + 13].Green + (u_long) RedPtr.pbrgb[i + 14].Green + (u_long) RedPtr.pbrgb[i + 15].Green) >> 4) * 59UL + (((u_long) RedPtr.pbrgb[i].Blue + (u_long) RedPtr.pbrgb[i + 1].Blue + (u_long) RedPtr.pbrgb[i + 2].Blue + (u_long) RedPtr.pbrgb[i + 3].Blue + (u_long) RedPtr.pbrgb[i + 4].Blue + (u_long) RedPtr.pbrgb[i + 5].Blue + (u_long) RedPtr.pbrgb[i + 6].Blue + (u_long) RedPtr.pbrgb[i + 7].Blue + (u_long) RedPtr.pbrgb[i + 8].Blue + (u_long) RedPtr.pbrgb[i + 9].Blue + (u_long) RedPtr.pbrgb[i + 10].Blue + (u_long) RedPtr.pbrgb[i + 11].Blue + (u_long) RedPtr.pbrgb[i + 12].Blue + (u_long) RedPtr.pbrgb[i + 13].Blue + (u_long) RedPtr.pbrgb[i + 14].Blue + (u_long) RedPtr.pbrgb[i + 15].Blue) >> 4) * 11UL) / 100UL); if( bHiRight[1] < bHiRight[0] ) { bHiRight[1] = bHiRight[0]; dwIndexRight = i; } } /* Convert RGB to gray scale (Brightness), and average 16 pixels */ for( bHiLeft[1] = 0, i = dwIndexLeft = _NEG_PAGEWIDTH / 2; i < _NEG_PAGEWIDTH600; i += 16 ) { bHiLeft [0] = (SANE_Byte)(((((u_long) RedPtr.pbrgb[i].Red + (u_long) RedPtr.pbrgb[i + 1].Red + (u_long) RedPtr.pbrgb[i + 2].Red + (u_long) RedPtr.pbrgb[i + 3].Red + (u_long) RedPtr.pbrgb[i + 4].Red + (u_long) RedPtr.pbrgb[i + 5].Red + (u_long) RedPtr.pbrgb[i + 6].Red + (u_long) RedPtr.pbrgb[i + 7].Red + (u_long) RedPtr.pbrgb[i + 8].Red + (u_long) RedPtr.pbrgb[i + 9].Red + (u_long) RedPtr.pbrgb[i + 10].Red + (u_long) RedPtr.pbrgb[i + 11].Red + (u_long) RedPtr.pbrgb[i + 12].Red + (u_long) RedPtr.pbrgb[i + 13].Red + (u_long) RedPtr.pbrgb[i + 14].Red + (u_long) RedPtr.pbrgb[i + 15].Red) >> 4) * 30UL + (((u_long) RedPtr.pbrgb[i].Green + (u_long) RedPtr.pbrgb[i + 1].Green + (u_long) RedPtr.pbrgb[i + 2].Green + (u_long) RedPtr.pbrgb[i + 3].Green + (u_long) RedPtr.pbrgb[i + 4].Green + (u_long) RedPtr.pbrgb[i + 5].Green + (u_long) RedPtr.pbrgb[i + 6].Green + (u_long) RedPtr.pbrgb[i + 7].Green + (u_long) RedPtr.pbrgb[i + 8].Green + (u_long) RedPtr.pbrgb[i + 9].Green + (u_long) RedPtr.pbrgb[i + 10].Green + (u_long) RedPtr.pbrgb[i + 11].Green + (u_long) RedPtr.pbrgb[i + 12].Green + (u_long) RedPtr.pbrgb[i + 13].Green + (u_long) RedPtr.pbrgb[i + 14].Green + (u_long) RedPtr.pbrgb[i + 15].Green) >> 4) * 59UL + (((u_long) RedPtr.pbrgb[i].Blue + (u_long) RedPtr.pbrgb[i + 1].Blue + (u_long) RedPtr.pbrgb[i + 2].Blue + (u_long) RedPtr.pbrgb[i + 3].Blue + (u_long) RedPtr.pbrgb[i + 4].Blue + (u_long) RedPtr.pbrgb[i + 5].Blue + (u_long) RedPtr.pbrgb[i + 6].Blue + (u_long) RedPtr.pbrgb[i + 7].Blue + (u_long) RedPtr.pbrgb[i + 8].Blue + (u_long) RedPtr.pbrgb[i + 9].Blue + (u_long) RedPtr.pbrgb[i + 10].Blue + (u_long) RedPtr.pbrgb[i + 11].Blue + (u_long) RedPtr.pbrgb[i + 12].Blue + (u_long) RedPtr.pbrgb[i + 13].Blue + (u_long) RedPtr.pbrgb[i + 14].Blue + (u_long) RedPtr.pbrgb[i + 15].Blue) >> 4) * 11UL) / 100UL); if( bHiLeft[1] < bHiLeft[0] ) { bHiLeft[1] = bHiLeft[0]; dwIndexLeft = i; } } if((bHiLeft[1] < 200) && (bHiRight[1] < 200)) { if( bHiLeft[1] < bHiRight[1] ) dwIndex = dwIndexRight; else dwIndex = dwIndexLeft; } else { if( bHiLeft[1] > 200 ) dwIndex = dwIndexRight; else dwIndex = dwIndexLeft; } /* Get the hilight */ RedPtr.pusrgb = dev->bufs.b2.pSumRGB + dwIndex + dev->regs.RD_Origin + _SHADING_BEGINX; for( dwR = dwG = dwB = 0, i = 16; i--; RedPtr.pusrgb++ ) { dwR += RedPtr.pusrgb->Red; dwG += RedPtr.pusrgb->Green; dwB += RedPtr.pusrgb->Blue; } dwR >>= 8; dwG >>= 8; dwB >>= 8; if( dwR > dwG && dwR > dwB ) dev->shade.bGainHigh = (SANE_Byte)dwR; /* >> 4 for average, >> 4 to 8-bit */ else { if( dwG > dwR && dwG > dwB ) dev->shade.bGainHigh = (SANE_Byte)dwG; else dev->shade.bGainHigh = (SANE_Byte)dwB; } dev->shade.bGainHigh = (SANE_Byte)(dev->shade.bGainHigh - 0x18); dev->shade.bGainLow = (SANE_Byte)(dev->shade.bGainHigh - 0x10); /* Reshading to get the new gain */ dev->shade.Hilight.Colors.Red = 0; dev->shade.Hilight.Colors.Green = 0; dev->shade.Hilight.Colors.Blue = 0; dev->shade.Gain.Colors.Red++; dev->shade.Gain.Colors.Green++; dev->shade.Gain.Colors.Blue++; dev->shade.fStop = SANE_FALSE; RedPtr.pb = dev->bufs.b1.pShadingMap + dwIndex; GreenPtr.pb = RedPtr.pb + _NEG_PAGEWIDTH600; BluePtr.pb = GreenPtr.pb + _NEG_PAGEWIDTH600; for( i = 16; i-- && !dev->shade.fStop;) { dev->shade.fStop = SANE_TRUE; u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain ); u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle ); dev->regs.RD_ScanControl = _SCAN_BYTEMODE; u12hw_SelectLampSource( dev ); dev->regs.RD_ModeControl = _ModeScan; dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; dev->regs.RD_Motor0Control = _FORWARD_MOTOR; memset( dev->scanStates, 0, _SCANSTATE_BYTES ); dev->scanStates[1] = 0x77; u12io_PutOnAllRegisters( dev ); _DODELAY( 50 ); if(u12io_ReadOneShadingLine( dev, dev->bufs.b1.pShadingMap,_NEG_PAGEWIDTH600)) { bHi[0] = u12shading_SumGains( RedPtr.pb, 32 ); bHi[1] = u12shading_SumGains( GreenPtr.pb, 32 ); bHi[2] = u12shading_SumGains( BluePtr.pb, 32 ); if( !bHi[0] || !bHi[1] || !bHi[2]) { dev->shade.fStop = SANE_FALSE; } else { u12shading_AdjustGain( dev, _CHANNEL_RED, bHi[0] ); u12shading_AdjustGain( dev, _CHANNEL_GREEN, bHi[1] ); u12shading_AdjustGain( dev, _CHANNEL_BLUE, bHi[2] ); } } else { dev->shade.fStop = SANE_FALSE; } } u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain ); /* Set RGB Gain */ if( dwR && dwG && dwB ) { if(dev->CCDID == _CCD_3797 || dev->DACType == _DA_ESIC ) { dev->shade.pCcdDac->GainResize.Colors.Red = (u_short)((u_long)bHi[0] * 100UL / dwR); dev->shade.pCcdDac->GainResize.Colors.Green = (u_short)((u_long)bHi[1] * 100UL / dwG); dev->shade.pCcdDac->GainResize.Colors.Blue = (u_short)((u_long)bHi[2] * 100UL / dwB); } else { dev->shade.pCcdDac->GainResize.Colors.Red = (u_short)((u_long)bHi[0] * 90UL / dwR); dev->shade.pCcdDac->GainResize.Colors.Green = (u_short)((u_long)bHi[1] * 77UL / dwG); dev->shade.pCcdDac->GainResize.Colors.Blue = (u_short)((u_long)bHi[2] * 73UL / dwB); } dev->shade.DarkOffset.Colors.Red += (u_short)((dwR > bHi[0]) ? dwR - bHi[0] : 0); dev->shade.DarkOffset.Colors.Green += (u_short)((dwG > bHi[1]) ? dwG - bHi[1] : 0); dev->shade.DarkOffset.Colors.Blue += (u_short)((dwB > bHi[2]) ? dwB - bHi[2] : 0); if( dev->DACType != _DA_ESIC && dev->CCDID != _CCD_3799 ) { dev->shade.DarkOffset.Colors.Red = (u_short)(dev->shade.DarkOffset.Colors.Red * dev->shade.pCcdDac->GainResize.Colors.Red / 100UL); dev->shade.DarkOffset.Colors.Green = (u_short)(dev->shade.DarkOffset.Colors.Green * dev->shade.pCcdDac->GainResize.Colors.Green / 100UL); dev->shade.DarkOffset.Colors.Blue = (u_short)(dev->shade.DarkOffset.Colors.Blue * dev->shade.pCcdDac->GainResize.Colors.Blue / 100UL); } } /* AdjustDark () */ dev->regs.RD_Origin = _SHADING_BEGINX; dev->regs.RD_Pixels = 5400; } /** perform some adjustments according to the source (normal, transparency etc) */ static void u12tpa_FindCenterPointer( U12_Device *dev ) { u_long i; u_long width; u_long left; u_long right; RGBUShortDef *pwSum = dev->bufs.b2.pSumRGB; if( dev->DataInf.dwScanFlag & _SCANDEF_Negative ) width = _NEG_PAGEWIDTH600; else width = _NEG_PAGEWIDTH600 - 94; /* 2.54 cm tolerance */ left = _DATA_ORIGIN_X + _NEG_ORG_OFFSETX * 2 - 600; right = _DATA_ORIGIN_X + _NEG_ORG_OFFSETX * 2 + _NEG_PAGEWIDTH600 + 600; for( i = 5400UL - left, pwSum = dev->bufs.b2.pSumRGB; i--; left++) if( pwSum[left].Red > _NEG_EDGE_VALUE && pwSum[left].Green > _NEG_EDGE_VALUE && pwSum[left].Blue > _NEG_EDGE_VALUE) break; for( i = 5400UL - left, pwSum = dev->bufs.b2.pSumRGB; i--; right--) if( pwSum[right].Red > _NEG_EDGE_VALUE && pwSum[right].Green > _NEG_EDGE_VALUE && pwSum[right].Blue > _NEG_EDGE_VALUE) break; if((right <= left) || ((right - left) < width)) { if( dev->DataInf.dwScanFlag & _SCANDEF_Negative ) dev->scan.negBegin = _DATA_ORIGIN_X + _NEG_ORG_OFFSETX * 2; else dev->scan.posBegin = _DATA_ORIGIN_X + _POS_ORG_OFFSETX * 2; } else { if( dev->DataInf.dwScanFlag & _SCANDEF_Negative ) dev->scan.negBegin = (right + left) / 2UL - _NEG_PAGEWIDTH; else dev->scan.posBegin = (right + left) / 2UL - _POS_PAGEWIDTH; } } /* END U12_TPA.C ............................................................*/ sane-backends-1.0.27/backend/plustek-pp_types.h0000664000175000017500000001145712775277260016341 00000000000000/* @file plustek-pp_types.h * @brief some typedefs and error codes * * Copyright (C) 2000-2013 Gerhard Jaeger * * History: * 0.30 - initial version * 0.31 - no changes * 0.32 - added _VAR_NOT_USED() * 0.33 - no changes * 0.34 - no changes * 0.35 - no changes * 0.36 - added _E_ABORT and _E_VERSION * 0.37 - moved _MAX_DEVICES to plustek_scan.h * added pChar and TabDef * 0.38 - comment change for _E_NOSUPP * added RGBByteDef, RGBWordDef and RGBULongDef * replaced AllPointer by DataPointer * replaced AllType by DataType * added _LOBYTE and _HIBYTE stuff * added _E_NO_ASIC and _E_NORESOURCE * 0.39 - no changes * 0.40 - moved _VAR_NOT_USED and TabDef to plustek-share.h * 0.41 - no changes * 0.42 - moved errorcodes to plustek-share.h * 0.43 - no changes * 0.44 - define Long and ULong types to use int32_t, so * the code should still work on 64 bit machines * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __DRV_TYPES_H__ #define __DRV_TYPES_H__ /* define some useful types */ typedef int Bool; typedef char Char; typedef char *pChar; typedef unsigned char UChar; typedef UChar *pUChar; typedef unsigned char Byte; typedef Byte *pByte; typedef short Short; typedef unsigned short UShort; typedef UShort *pUShort; typedef unsigned int UInt; typedef UInt *pUInt; /* these definitions will fail for 64 bit machines! */ #if 0 typedef long Long; typedef long *pLong; typedef unsigned long ULong; #endif typedef int32_t Long; typedef int32_t *pLong; typedef uint32_t ULong; typedef ULong *pULong; typedef void *pVoid; /* * the boolean values */ #ifndef _TRUE # define _TRUE 1 #endif #ifndef _FALSE # define _FALSE 0 #endif #define _LOWORD(x) ((UShort)(x & 0xffff)) #define _HIWORD(x) ((UShort)(x >> 16)) #define _LOBYTE(x) ((Byte)((x) & 0xFF)) #define _HIBYTE(x) ((Byte)((x) >> 8)) /* * some useful things... */ typedef struct { Byte b1st; Byte b2nd; } WordVal, *pWordVal; typedef struct { WordVal w1st; WordVal w2nd; } DWordVal, *pDWordVal; /* useful for RGB-values */ typedef struct { Byte Red; Byte Green; Byte Blue; } RGBByteDef, *pRGBByteDef; typedef struct { UShort Red; UShort Green; UShort Blue; } RGBUShortDef, *pRGBUShortDef; typedef struct { union { pUChar bp; pUShort usp; pULong ulp; } red; union { pUChar bp; pUShort usp; pULong ulp; } green; union { pUChar bp; pUShort usp; pULong ulp; } blue; } RBGPtrDef; typedef struct { ULong Red; ULong Green; ULong Blue; } RGBULongDef, *pRGBULongDef; typedef union { pUChar pb; pUShort pw; pULong pdw; pRGBByteDef pbrgb; pRGBUShortDef pusrgb; pRGBULongDef pulrgb; } DataPointer, *pDataPointer; typedef union { WordVal wOverlap; DWordVal dwOverlap; ULong dwValue; UShort wValue; Byte bValue; } DataType, *pDataType; #endif /* guard __DRV_TYPES_H__ */ /* END PLUSTEK-PP_TYPES.H ...................................................*/ sane-backends-1.0.27/backend/hp5400_internal.h0000664000175000017500000002034212112021330015560 00000000000000#ifndef _HP5400_INTERNAL_H_ #define _HP5400_INTERNAL_H_ /* sane - Scanner Access Now Easy. (C) 2003 Thomas Soumarmon (c) 2003 Martijn van Oosterhout, kleptog@svana.org (c) 2002 Bertrik Sikken, bertrik@zonnet.nl This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. HP5400/5470 Test util. Currently is only able to read back the scanner version string, but this basically demonstrates ability to communicate with the scanner. Massively expanded. Can do calibration scan, upload gamma and calibration tables and stores the results of a scan. - 19/02/2003 Martijn */ #include "../include/_stdint.h" #ifdef __GNUC__ #define PACKED __attribute__ ((packed)) #else #define PACKED #endif /* If this is enabled, a copy of the raw data from the scanner will be saved to imagedebug.dat and the attempted conversion to imagedebug.ppm */ /* #define IMAGE_DEBUG */ /* If this is defined you get extra info on the calibration */ /* #define CALIB_DEBUG */ #define CMD_GETVERSION 0x1200 #define CMD_GETUITEXT 0xf00b #define CMD_GETCMDID 0xc500 #define CMD_SCANREQUEST 0x2505 /* This is for previews */ #define CMD_SCANREQUEST2 0x2500 /* This is for real scans */ #define CMD_SCANRESPONSE 0x3400 /* Testing stuff to make it work */ #define CMD_SETDPI 0x1500 /* ??? */ #define CMD_STOPSCAN 0x1B01 /* 0x40 = lamp in on, 0x00 = lamp is off */ #define CMD_STARTSCAN 0x1B05 /* 0x40 = lamp in on, 0x00 = lamp is off */ #define CMD_UNKNOWN 0x2300 /* Send fixed string */ #define CMD_UNKNOWN2 0xD600 /* ??? Set to 0x04 */ #define CMD_UNKNOWN3 0xC000 /* ??? Set to 02 03 03 3C */ #define CMD_SETOFFSET 0xE700 /* two ints in network order. X-offset, Y-offset of full scan */ /* Given values seem to be 0x0054 (=4.57mm) and 0x0282 (=54.36mm) */ #define CMD_INITBULK1 0x0087 /* send 0x14 */ #define CMD_INITBULK2 0x0083 /* send 0x24 */ #define CMD_INITBULK3 0x0082 /* transfer length 0xf000 */ struct ScanRequest { uint8_t x1; /* Set to 0x08 */ uint16_t dpix, dpiy; /* Set to 75, 150 or 300 in network order */ uint16_t offx, offy; /* Offset to scan, in 1/300th of dpi, in network order */ uint16_t lenx, leny; /* Size of scan, in 1/300th of dpi, in network order */ uint16_t flags1, flags2, flags3; /* Undetermined flag info */ /* Known combinations are: 1st calibration scan: 0x0000, 0x0010, 0x1820 = 24bpp 2nd calibration scan: 0x0000, 0x0010, 0x3020 = 48bpp ??? 3rd calibration scan: 0x0000, 0x0010, 0x3024 = 48bpp ??? Preview scan: 0x0080, 0x0000, 0x18E8 = 8bpp 4th & 5th like 2nd and 3rd B&W scan: 0x0080, 0x0040, 0x08E8 = 8bpp 6th & 7th like 2nd and 3rd True colour scan 0x0080, 0x0040, 0x18E8 = 24bpp */ uint8_t zero; /* Seems to always be zero */ uint16_t gamma[3]; /* Set to 100 in network order. Gamma? */ uint16_t pad[3]; /* Zero padding ot 32 bytes??? */ } PACKED; /* More known combos (All 24-bit): 300 x 300 light calibration: 0x0000, 0x0010, 0x1820 300 x 300 dark calibration: 0x0000, 0x0010, 0x3024 75 x 75 preview scan: 0x0080, 0x0000, 0x18E8 300 x 300 full scan: 0x0080, 0x0000, 0x18E8 600 x 300 light calibration: 0x0000, 0x0010, 0x3000 600 x 300 dark calibration: 0x0000, 0x0010, 0x3004 600 x 600 full scan: 0x0080, 0x0000, 0x18C8 1200 x 300 light calibration: 0x0000, 0x0010, 0x3000 1200 x 300 dark calibration: 0x0000, 0x0010, 0x3004 1200 x 1200 full scan: 0x0080, 0x0000, 0x18C8 2400 x 300 light calibration: 0x0000, 0x0010, 0x3000 2400 x 300 dark calibration: 0x0000, 0x0010, 0x3004 2400 x 2400 full scan: 0x0080, 0x0000, 0x18C0 */ struct ScanResponse { uint16_t x1; /* Usually 0x0000 or 0x4000 */ uint32_t transfersize; /* Number of bytes to be transferred */ uint32_t xsize; /* Shape of returned bitmap */ uint16_t ysize; /* Why does the X get more bytes? */ uint16_t pad[2]; /* Zero padding to 16 bytes??? */ } PACKED; HP5400_SANE_STATIC int InitScan2 (enum ScanType type, struct ScanRequest *req, THWParams * pHWParams, struct ScanResponse *res, int iColourOffset, int code); HP5400_SANE_STATIC void FinishScan (THWParams * pHWParams); HP5400_SANE_STATIC int WriteByte (int iHandle, int cmd, char data); HP5400_SANE_STATIC int SetLamp (THWParams * pHWParams, int fLampOn); HP5400_SANE_STATIC int WarmupLamp (int iHandle); HP5400_SANE_STATIC int SetCalibration (int iHandle, int numPixels, unsigned int *low_vals[3], unsigned int *high_vals[3], int dpi); HP5400_SANE_STATIC void WriteGammaCalibTable (int iHandle, const int *pabGammaR, const int *pabGammaG, const int *pabGammaB); #ifdef STANDALONE HP5400_SANE_STATIC void SetDefaultGamma (int iHandle); #endif HP5400_SANE_STATIC void CircBufferInit (int iHandle, TDataPipe * p, int iBytesPerLine, int bpp, int iMisAlignment, int blksize, int iTransferSize); HP5400_SANE_STATIC int CircBufferGetLine (int iHandle, TDataPipe * p, void *pabLine); HP5400_SANE_STATIC void CircBufferExit (TDataPipe * p); #ifdef STANDALONE HP5400_SANE_STATIC void DecodeImage (FILE * file, int planes, int bpp, int xsize, int ysize, const char *filename); HP5400_SANE_STATIC int hp5400_test_scan_response (struct ScanResponse *resp, struct ScanRequest *req); #endif HP5400_SANE_STATIC int DoAverageScan (int iHandle, struct ScanRequest *req, int code, unsigned int **array); #ifdef STANDALONE HP5400_SANE_STATIC int DoScan (int iHandle, struct ScanRequest *req, const char *filename, int code, struct ScanResponse *res); #endif HP5400_SANE_STATIC int Calibrate (int iHandle, int dpi); #ifdef STANDALONE HP5400_SANE_STATIC int hp5400_scan (int iHandle, TScanParams * params, THWParams * pHWParams, const char *filename); HP5400_SANE_STATIC int PreviewScan (int iHandle); HP5400_SANE_STATIC int InitScanner (int iHandle); #endif HP5400_SANE_STATIC int InitScan (enum ScanType scantype, TScanParams * pParams, THWParams * pHWParams); HP5400_SANE_STATIC void FinishScan (THWParams * pHWParams); HP5400_SANE_STATIC int HP5400Open (THWParams * params, const char *filename); HP5400_SANE_STATIC void HP5400Close (THWParams * params); HP5400_SANE_STATIC int HP5400Detect (const char *filename, int (*_ReportDevice) (TScannerModel * pModel, const char *pszDeviceName)); HP5400_SANE_STATIC int InitHp5400_internal( void ); HP5400_SANE_STATIC int FreeHp5400_internal( void ); #ifdef STANDALONE int main (int argc, char *argv[]); #endif #endif sane-backends-1.0.27/backend/pixma_rename.h0000664000175000017500000001070312617742237015443 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIXMA_RENAME_H #define PIXMA_RENAME_H #undef BACKEND_NAME #define BACKEND_NAME pixma #define pixma_cancel sanei_pixma_cancel #define pixma_check_dpi sanei_pixma_check_dpi #define pixma_check_result sanei_pixma_check_result #define pixma_check_scan_param sanei_pixma_check_scan_param #define pixma_cleanup sanei_pixma_cleanup #define pixma_close sanei_pixma_close #define pixma_cmd_transaction sanei_pixma_cmd_transaction #define pixma_collect_devices sanei_pixma_collect_devices #define pixma_connect sanei_pixma_connect #define pixma_dbg DBG #define pixma_disconnect sanei_pixma_disconnect #define pixma_dump sanei_pixma_dump #define pixma_enable_background sanei_pixma_enable_background #define pixma_exec sanei_pixma_exec #define pixma_exec_short_cmd sanei_pixma_exec_short_cmd #define pixma_fill_gamma_table sanei_pixma_fill_gamma_table #define pixma_find_scanners sanei_pixma_find_scanners #define pixma_get_be16 sanei_pixma_get_be16 #define pixma_get_be32 sanei_pixma_get_be32 #define pixma_get_config sanei_pixma_get_config #define pixma_get_device_config sanei_pixma_get_device_config #define pixma_get_device_id sanei_pixma_get_device_id #define pixma_get_device_model sanei_pixma_get_device_model #define pixma_get_device_status sanei_pixma_get_device_status #define pixma_get_string sanei_pixma_get_string #define pixma_get_time sanei_pixma_get_time #define pixma_hexdump sanei_pixma_hexdump #define pixma_init sanei_pixma_init #define pixma_io_cleanup sanei_pixma_io_cleanup #define pixma_io_init sanei_pixma_io_init #define pixma_map_status_errno sanei_pixma_map_status_errno #define pixma_mp150_devices sanei_pixma_mp150_devices #define pixma_mp730_devices sanei_pixma_mp730_devices #define pixma_mp750_devices sanei_pixma_mp750_devices #define pixma_mp810_devices sanei_pixma_mp810_devices #define pixma_iclass_devices sanei_pixma_iclass_devices #define pixma_newcmd sanei_pixma_newcmd #define pixma_open sanei_pixma_open #define pixma_print_supported_devices sanei_pixma_print_supported_devices #define pixma_read_image sanei_pixma_read_image #define pixma_read sanei_pixma_read #define pixma_reset_device sanei_pixma_reset_device #define pixma_scan sanei_pixma_scan #define pixma_set_be16 sanei_pixma_set_be16 #define pixma_set_be32 sanei_pixma_set_be32 #define pixma_set_debug_level sanei_pixma_set_debug_level #define pixma_set_interrupt_mode sanei_pixma_set_interrupt_mode #define pixma_sleep sanei_pixma_sleep #define pixma_strerror sanei_pixma_strerror #define pixma_sum_bytes sanei_pixma_sum_bytes #define pixma_wait_event sanei_pixma_wait_event #define pixma_wait_interrupt sanei_pixma_wait_interrupt #define pixma_write sanei_pixma_write #endif sane-backends-1.0.27/backend/hp-handle.h0000664000175000017500000000547412112021330014615 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ #ifndef HP_HANDLE_INCLUDED #define HP_HANDLE_INCLUDED #include "hp.h" HpHandle sanei_hp_handle_new (HpDevice dev); void sanei_hp_handle_destroy (HpHandle this); const SANE_Option_Descriptor * sanei_hp_handle_saneoption (HpHandle this, SANE_Int optnum); SANE_Status sanei_hp_handle_control(HpHandle this, SANE_Int optnum, SANE_Action action, void *valp, SANE_Int *info); SANE_Status sanei_hp_handle_getParameters (HpHandle this, SANE_Parameters *params); SANE_Status sanei_hp_handle_startScan (HpHandle this); SANE_Status sanei_hp_handle_read (HpHandle this, void * buf, size_t *lengthp); void sanei_hp_handle_cancel (HpHandle this); SANE_Status sanei_hp_handle_setNonblocking (HpHandle this, hp_bool_t non_blocking); SANE_Status sanei_hp_handle_getPipefd (HpHandle this, SANE_Int *fd); #endif /* HP_HANDLE_INCLUDED */ sane-backends-1.0.27/backend/plustek-pp_map.c0000664000175000017500000002025412112021330015702 00000000000000/* @file plustek-pp_map.c * @brief functions to create and manipulate lookup tables. * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2004 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - brightness and contrast is working (see mapAdjust) * - 0.32 - no changes * - 0.33 - disabled a few functions * - 0.34 - added new dither matrix for checking * - 0.35 - no changes * - 0.36 - activated Dithermap 1 * - removed some unused functions * - added additional SCANDEF_Inverse check to MapSetupDither() * - fixed the double inversion bug, the map always compensates * - the scanner hw-settings * - 0.37 - code cleanup * - 0.38 - added P12 stuff * - 0.39 - no changes * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - made MapAdjust global * - changed include names * - 0.43 - cleanup, removed floating point stuff * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** local vars **************************************/ /*WORK: * create other thresholds for the dither maps */ static Byte mapDitherMatrix0[_DITHERSIZE] = { 0, 32, 8, 40, 2, 34, 10, 42, 48, 16, 56, 24, 50, 18, 58, 26, 12, 44, 4, 36, 14, 46, 6, 38, 60, 28, 52, 20, 62, 30, 54, 22, 3, 35, 11, 43, 1, 33, 9, 41, 51, 19, 59, 27, 49, 17, 57, 25, 15, 47, 7, 39, 13, 45, 5, 37, 63, 31, 55, 23, 61, 29, 53, 21 }; static Byte mapDitherMatrix1[_DITHERSIZE] = { 2, 60, 16, 56, 3, 57, 13, 53, 34, 18, 48, 32, 35, 19, 45, 29, 10, 50, 6, 63, 11, 51, 7, 61, 42, 26, 38, 22, 43, 27, 39, 23, 4, 58, 14, 54, 1, 59, 15, 55, 36, 20, 46, 30, 33, 17, 47, 31, 12, 52, 8, 62, 9, 49, 5, 63, 44, 28, 40, 24, 41, 25, 37, 21 }; /*************************** local functions *********************************/ /** set the selected dither maps... */ static void mapSetDitherMap( pScanData ps ) { ULong i; pUChar pDitherSource; pUChar pDither = ps->a_bDitherPattern; if( 0 == ps->DataInf.wDither ) { DBG( DBG_LOW, "Using Dithermatrix 0\n" ); pDitherSource = mapDitherMatrix0; } else { DBG( DBG_LOW, "Using Dithermatrix 1\n" ); pDitherSource = mapDitherMatrix1; } for( i = 0; i < _DITHERSIZE; i++ ) { pDither[i] = pDitherSource[i]; } } /** nothing more to say */ static void mapInvertMap( pScanData ps ) { pULong pdw; ULong dw, size; DBG( DBG_LOW, "mapInvertMap()\n" ); if( _IS_ASIC98(ps->sCaps.AsicID)) { size = 4096; } else { size = 256; } for (pdw = (pULong)ps->a_bMapTable, dw = size * 3 / 4; dw; dw--, pdw++) { *pdw = ~(*pdw); } } /** as the name says... */ static void mapInvertDitherMap( pScanData ps ) { if( ps->DataInf.dwScanFlag & SCANDEF_Inverse ) { ULong dw; pULong pDither = (pULong)ps->a_bDitherPattern; DBG( DBG_LOW, "mapInvertDitherMap()\n" ); mapInvertMap( ps ); for (dw = 0; dw < 16; dw++) { pDither[dw] = ~pDither[dw]; } } } /** build linear map... */ static void mapBuildLinearMap( pScanData ps ) { ULong i; DBG( DBG_LOW, "mapBuildLinearMap()\n" ); if( _IS_ASIC98(ps->sCaps.AsicID)) { for( i = 0; i < 4096; i++ ) { ps->a_bMapTable[i] = (UChar)(i >> 4); ps->a_bMapTable[4096+i] = (UChar)(i >> 4); ps->a_bMapTable[8192+i] = (UChar)(i >> 4); } } else { for( i = 0; i < 256; i++ ) { ps->a_bMapTable[i] = (UChar)(i & 0xff); ps->a_bMapTable[256+i] = (UChar)(i & 0xff); ps->a_bMapTable[512+i] = (UChar)(i & 0xff); } } } /************************ exported functions *********************************/ /** create a mapping table * in the original code this map will be created by the TWAIN application * and the is being downloaded to the driver, as I don't have the code * we have to try to build up such a table here */ _LOC void MapInitialize( pScanData ps ) { mapBuildLinearMap( ps ); MapAdjust( ps, _MAP_MASTER ); } /** setup dither maps */ _LOC void MapSetupDither( pScanData ps ) { DBG( DBG_LOW, "MapSetupDither() - %u\n", ps->DataInf.wAppDataType ); if( COLOR_HALFTONE == ps->DataInf.wAppDataType ) { mapSetDitherMap( ps ); if (ps->DataInf.dwScanFlag & SCANDEF_Inverse) mapInvertDitherMap( ps ); } } /** adjust acording to brightness and contrast */ _LOC void MapAdjust( pScanData ps, int which ) { ULong i, tabLen, dw; ULong *pdw; long b, c, tmp; DBG( DBG_LOW, "MapAdjust(%u)\n", which ); if( _IS_ASIC98(ps->sCaps.AsicID)) { tabLen = 4096; } else { tabLen = 256; } /* adjust brightness (b) and contrast (c) using the function: * s'(x,y) = (s(x,y) + b) * c * b = [-127, 127] * c = [0,2] */ /* scale brightness and contrast... */ b = ps->wBrightness * 192; c = ps->wContrast + 100; DBG( DBG_LOW, "brightness = %i -> %i\n", ps->wBrightness, (UChar)(b/100)); DBG( DBG_LOW, "contrast*100 = %i -> %i\n", ps->wContrast, (int)(c)); for( i = 0; i < tabLen; i++ ) { if((_MAP_MASTER == which) || (_MAP_RED == which)) { tmp = ((((long)ps->a_bMapTable[i] * 100) + b) *c ) / 10000; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; ps->a_bMapTable[i] = (UChar)tmp; } if((_MAP_MASTER == which) || (_MAP_GREEN == which)) { tmp = ((((long)ps->a_bMapTable[tabLen+i] * 100) + b) * c) / 10000; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; ps->a_bMapTable[tabLen+i] = (UChar)tmp; } if((_MAP_MASTER == which) || (_MAP_BLUE == which)) { tmp = ((((long)ps->a_bMapTable[tabLen*2+i] * 100) + b) * c) / 10000; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; ps->a_bMapTable[tabLen*2+i] = (UChar)tmp; } } if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) { DBG( DBG_LOW, "inverting...\n" ); if((_MAP_MASTER == which) || (_MAP_RED == which)) { DBG( DBG_LOW, "inverting RED map\n" ); pdw = (pULong)ps->a_bMapTable; for( dw = tabLen / 4; dw; dw--, pdw++ ) *pdw = ~(*pdw); } if((_MAP_MASTER == which) || (_MAP_GREEN == which)) { DBG( DBG_LOW, "inverting GREEN map\n" ); pdw = (pULong)&ps->a_bMapTable[tabLen]; for( dw = tabLen / 4; dw; dw--, pdw++ ) *pdw = ~(*pdw); } if((_MAP_MASTER == which) || (_MAP_BLUE == which)) { DBG( DBG_LOW, "inverting BLUE map\n" ); pdw = (pULong)&ps->a_bMapTable[tabLen*2]; for( dw = tabLen / 4; dw; dw--, pdw++ ) *pdw = ~(*pdw); } } } /* END PLUSTEK-PP_MAP.C .....................................................*/ sane-backends-1.0.27/backend/umax1220u.conf.in0000664000175000017500000000060212112021330015510 00000000000000# Options for the umax1220u backend # Autodetect the UMAX Astra 1220U usb 0x1606 0x0010 # The following line enables autodetection for the # Astra 2000U and Astra 2100U. However, this driver # isn't entirely compatible, so expect color problems :) usb 0x1606 0x0030 usb 0x1606 0x0130 # device list for non-linux-systems (enable if autodetect fails): #/dev/scanner #/dev/usb/scanner0 sane-backends-1.0.27/backend/mustek.conf.in0000664000175000017500000000411512112021330015357 00000000000000# See sane-mustek(5) for documentation. #--------------------------- Global options --------------------------------- #option strip-height 1 # some SCSI adapters need this; scanning may # be faster without this option #option force-wait # wait for scanner to be ready (only necessary # when scanner freezes) #option disable-double-buffering # try this if you have SCSI trouble #-------------------------- SCSI scanners ----------------------------------- scsi MUSTEK * Scanner # option linedistance-fix # stripes may go away in color mode # option buffersize 1024 # set non standard buffer size (in kb) # option blocksize 2048 # set non standard block size (in kb) # option lineart-fix # lineart may be faster with this option off. # option disable-backtracking # faster, but may produce stripes scsi SCANNER # option linedistance-fix # stripes may go away in color mode # option buffersize 1024 # set non standard buffer size (in kb) # option blocksize 2048 # set non standard block size (in kb) # option lineart-fix # lineart may be faster with this option off. # option disable-backtracking # faster, but may produce stripes /dev/scanner # option linedistance-fix # stripes may go away in color mode # option buffersize 1024 # set non standard buffer size (in kb) # option blocksize 2048 # set non standard block size (in kb) # option lineart-fix # lineart may be faster with this option off. # option disable-backtracking # faster, but may produce stripes #-------------------------- 600 II N ---------------------------------------- #0x2eb # For the 600 II N try one of 0x26b, 0x2ab, # 0x2eb, 0x22b, 0x32b, 0x36b, 0x3ab, 0x3eb. # option linedistance-fix # only neccessary with firmware 2.x #-------------------------- 600 II EP --------------------------------------- #parport0 # parport0, parport1, ..., # or: 0x378(=lpt1), 0x278(=lpt2), 0x3bc(=lpt3) sane-backends-1.0.27/backend/plustek-pp_dbg.h0000664000175000017500000000574512112021330015676 00000000000000/** @file plustek-pp_dbg.c * @brief definition of some debug macros * * Copyright (C) 2000-2004 Gerhard Jaeger * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __DEBUG_H__ #define __DEBUG_H__ /* uncomment this to have an SW-simulatet 98001 device - don't expect to scan*/ /* #define _ASIC_98001_SIM */ /* * the print macros */ #ifdef __KERNEL__ # define _PRINT printk #endif /* * some debug definitions */ #ifdef DEBUG # ifndef __KERNEL__ # include # define _ASSERT(x) assert(x) # else # define _ASSERT(x) # endif # ifndef DBG # define DBG(level, msg, args...) if ((dbg_level) & (level)) { \ _PRINT(msg, ##args); \ } # endif #else # define _ASSERT(x) # ifndef DBG # define DBG(level, msg, args...) # endif #endif /* different debug level */ #define DBG_LOW 0x01 #define DBG_MEDIUM 0x02 #define DBG_HIGH 0x04 #define DBG_HELPERS 0x08 #define DBG_TIMEOUT 0x10 #define DBG_SCAN 0x20 #define DBG_IO 0x40 #define DBG_IOF 0x80 #define DBG_ALL 0xFF /* * standard debug level */ #ifdef DEBUG static int dbg_level=(DBG_ALL & ~(DBG_IO | DBG_IOF)); #endif #endif /* guard __DEBUG_H__ */ /* END PLUSTEK-PP_DBG.H .....................................................*/ sane-backends-1.0.27/backend/plustek-pp_scandata.h0000664000175000017500000004437312775277260016756 00000000000000/* @file plustek-pp_scandata.h * @brief here we define the ScanData structure... * and a lot of register settings * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson *............................................................................. * History: * 0.30 - initial version * 0.31 - no changes * 0.32 - added fWarmupNeeded to struct ScanData * - removed function FillDataToColorTable from struct ScanData * - removed dwLampDelay from struct ScanData * 0.33 - cosmetic changes * - removed PositionLamp from structure * - added dwLastPortMode to struct ScanData * 0.34 - removed WaitBack() function from pScanData structure * - removed wStayMaxStep from pScanData structure * 0.35 - removed SetInitialGainRAM from pScanData structure * - changed ModelStr list * 0.36 - added some defines for the ASIC 96001 (model 4800) * - added wDither to DataInfo structure * - removed dwPreferSize from struct ScannerCaps * - cleanup * - moved all stuff that is used by the backend and the driver * to plustek-share.h which is in the backend directory * - added ModelOverride parameter to struct * - added strcut pardevice to struct * 0.37 - added bIODelay for SPP/BIDI port operations * - added ReadData to struct * - added ProcDirDef * - added ButtonCount * - removed RegisterToScanner from struct * - removed MaxDpiByInterpolation from struct * 0.38 - added function PutToIdleMode() to struct * - added function Calibration() to struct * - changed interface of the ReInitAsic() function * - major changes: moved a lot of stuff to hwdefs.h * - added IO, Device, Shade, Scan and Bufs to struct * 0.39 - added forceMode to struct * - added f97003, b97003DarkR, b97003DarkB, b97003DarkG to struct * 0.40 - no changes * 0.41 - no changes * 0.42 - no changes * 0.43 - changed type of XYRatio from double to long * - cleanup * 0.44 - changes as Long defaults now to int32_t * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __SCANDATA_H__ #define __SCANDATA_H__ /* *Directory information for the /proc interface */ typedef struct { struct proc_dir_entry *entry; /* Directory /proc/pt_drv/X */ struct proc_dir_entry *info; /* .../info */ struct proc_dir_entry *buttons[_MAX_BTNS]; /* .../buttons */ } ProcDirDef, *pProcDirDef; /* * here we have some structs internally used */ typedef struct { ULong dwVxdFlag; ULong dwScanFlag; /* * CHECK: why there are dups ? */ ULong dwAppLinesPerArea; ULong dwAppPixelsPerLine; ULong dwAppPhyBytesPerLine; ULong dwAppBytesPerLine; ULong dwAsicPixelsPerPlane; ULong dwAsicBytesPerPlane; ULong dwAsicBytesPerLine; CropRect crImage; XY xyAppDpi; XY xyPhyDpi; pUChar pCurrentBuffer; UShort wPhyDataType; UShort wAppDataType; UShort wYSum; short siBrightness; /* CHANGE added these vars for scaling */ Long XYRatio; ULong dwPhysBytesPerLine; /* * CHANGE added this for selecting dither method */ UShort wDither; } DataInfo, *pDataInfo; /* * here it is, the great structure */ typedef struct scandata { #ifdef __KERNEL__ UInt flags; /* as follows: */ #define _PTDRV_INITALIZED 0x00000001 #define _PTDRV_OPEN 0x00000002 struct pardevice *pardev; /* for accessing parport... */ struct parport *pp; ProcDirDef procDir; #else int pardev; /* parport handle in user-space */ #endif /* * device control */ ULong devno; int lampoff; int warmup; int lOffonEnd; /* * CHECK for controlling the ECP-mode (not used now) */ #if 0 Byte bOldECR; Bool fECPReadWriteTest; Bool fSkipEcpFlag; Bool fECPFlag; Bool fECPtoEPP; Bool fECRFIFO; #endif /* * the following stuff gets changed on a per model basis */ UShort ModelOverride; /* for non-auto detection stuff */ UShort Offset70; /* CHECK: --> to Device */ UShort BufferSizeBase; /* --> to Device */ UShort BufferSizePerModel; /* --> to Device */ UShort TimePerLine; /* --> to Device */ /* * scanner properties */ RegData AsicReg; /* here we have the 98001/3 register set */ Reg96 Asic96Reg; /* here we hold the 96001/3 specific regs */ LensInfo LensInf; ScannerCaps sCaps; ULong dwScannerSize; Byte bCurrentSpeed; pUChar pbMapRed; pUChar pbMapGreen; pUChar pbMapBlue; ULong TotalBufferRequire; ULong BufferForColorRunTable; UShort PhysicalDpi; UShort RdPix; /* for ASIC 96003 devices */ Byte a_bMapTable[4096 * 3]; /* pre 98001 was 256 * 3 */ Byte a_nbNewAdrPointer[_SCANSTATE_BYTES]; /* * for P9600x ASIC based scanners */ Bool fColorMoreRedFlag; Bool fColorMoreBlueFlag; Bool fSonyCCD; Bool f97003; Byte AsicRedColor; Byte AsicGreenColor; Byte RedDataReady; Byte GreenDataReady; Byte b1stColorByte; Byte b1stColor; Byte b1stMask; Byte b2ndColorByte; Byte b2ndColor; Byte b2ndMask; Byte b3rdColorByte; Byte b3rdColor; Byte b3rdMask; Byte b1stLinesOffset; Byte b2ndLinesOffset; Byte bLampOn; Byte bExtraAdd; Byte bFifoCount; Byte bMinReadFifo; Byte FullStep; Byte StepMask; Byte MotorOn; Byte MotorFreeRun; Byte IgnorePF; Byte bMotorStepTableNo; /* for ASIC 97003... */ Byte b97003DarkR; Byte b97003DarkG; Byte b97003DarkB; /* CHECK: to Scan!!!! */ pUChar pGetBufR; /* NOTE: these aren't actually Red/Green buffer */ pUChar pGetBufG; /* pointers but instead are used */ pUChar pPutBufR; /* generically to point to the first 2 */ pUChar pPutBufG; /* color buffers as temp storage */ pUChar pCurrentColorRunTable; UShort a_wGrayInitTime[3]; UShort a_wColorInitTime[3]; UShort BackwardSteps; UShort wLinesPer64kTime; UShort ShadingBufferSize; UShort ShadingBankSize; UShort ShadingBankRed; UShort ShadingBankGreen; UShort ShadingBankBlue; UShort ShadingScanLineBlks; UShort ShadingScanLineLen; UShort wOverBlue; UShort FBKScanLineBlks; UShort FBKScanLineLenBase; UShort FBKScanLineLen; UShort OneScanLineLen; /* * the DAC part - to Shade !!! */ UShort wsDACCompareHighRed, wsDACCompareLowRed; UShort wsDACCompareHighGreen, wsDACCompareLowGreen; UShort wsDACCompareHighBlue, wsDACCompareLowBlue; UShort wsDACOffsetRed, wsDACOffsetGreen, wsDACOffsetBlue; Byte bsPreRedDAC, bsPreGreenDAC, bsPreBlueDAC; Byte bRedDAC, bGreenDAC, bBlueDAC; Byte bRedGainIndex, bGreenGainIndex, bBlueGainIndex; /* * for image description */ DataInfo DataInf; Bool fReshaded; ULong dwDitherIndex; Bool fDoFilter, fFilterFirstLine; ULong dwDivFilter; ULong dwMul; Byte bOffsetFilter; ULong dwLinesFilter; pUChar pFilterBuf, pEndBuf; pUChar pGet1, pGet2, pGet3; Byte bSetScanModeFlag; /* see Section 5 - Scanmodes --> ps->Shade.bIntermediate*/ /* * some admin vals (they used to be global vars in the original driver) */ Bool fScanningStatus; Byte bLastLampStatus; Bool fWarmupNeeded; ULong dwOffset70; ULong dwMaxReadFifoData; /* * */ pUChar pColorRunTable; pUChar pPrescan16; pUChar pPrescan8; UShort BufferForDataRead1; ULong BufferFor1stColor; ULong BufferFor2ndColor; pUChar driverbuf; pUChar pEndBufR; pUChar pEndBufG; pUChar pProcessingBuf; /* * formerly used as global vars in ioproc.c, now in genericio.c */ pUChar pScanBuffer1; pUChar pScanBuffer2; pModeTypeVar lpEppColorHomePos; pModeTypeVar lpEppColorExposure; pModeTypeVar lpBppColorHomePos; pModeTypeVar lpSppColorHomePos; UShort wMinCmpDpi; pModeTypeVar a_ColorSettings; pDiffModeVar a_tabDiffParam; Byte bSpeed48; Byte bSpeed32; Byte bSpeed24; Byte bSpeed16; Byte bSpeed12; Byte bSpeed8; Byte bSpeed6; Byte bSpeed4; Byte bSpeed3; Byte bSpeed2; Byte bSpeed1; Byte bHpMotor; Byte bStepSpeed; ULong dwFullStateSpeed; /* * reference to globals from motor.c */ Bool fHalfStepTableFlag; Bool fFullLength; Byte bMoveDataOutFlag; Byte bExtraMotorCtrl; Byte bFastMoveFlag; Byte bOldStateCount; Byte bMotorSpeedData; Byte bCurrentLineCount; Byte bNewGap; Byte bNewCurrentLineCountGap; UShort wMaxMoveStep; ULong dwScanStateCount; ULong dwColorRunIndex; pByte a_bColorByteTable; pUChar pScanState; pUShort a_wMoveStepTable; /* * for shading - dac.c * CHECK: move to ps->Shade */ Byte bShadingTimeFlag; ULong dwShadow, dwShadowCh; ULong dwHilight, dwHilightCh; ULong dwShadingLen, dwShadingPixels; pUShort pwShadow; /* * from transform.c */ Byte bRedHigh, bGreenHigh, bBlueHigh; UShort wPosAdjustX; UShort wNegAdjustX; UShort wReduceRedFactor; UShort wReduceGreenFactor; UShort wReduceBlueFactor; ULong dwOffsetNegative; /* * reference to globals from map.c */ #define _DITHERSIZE 64 Byte a_bDitherPattern[_DITHERSIZE]; Short wBrightness; Short wContrast; UShort wInitialStep; ULong dwSizeMustProcess; /* * here we have pointers to the functions to call */ Bool (*OpenScanPath) (pScanData); void (*CloseScanPath) (pScanData); int (*ReadWriteTest) (pScanData); void (*PutToIdleMode) (pScanData); int (*Calibration) (pScanData); void (*SetupScannerVariables) (pScanData); int (*SetupScanSettings) (pScanData, pScanInfo pInf ); void (*GetImageInfo) (pScanData, pImgDef pInf ); Bool (*WaitForShading) (pScanData); void (*WaitForPositionY) (pScanData); void (*InitialSetCurrentSpeed) (pScanData); Bool (*GotoShadingPosition) (pScanData); void (*SetupScanningCondition) (pScanData); void (*SetMotorSpeed) (pScanData,Byte bSpeed,Bool fSetRunState); void (*FillRunNewAdrPointer) (pScanData); void (*SetupMotorRunTable) (pScanData); void (*PauseColorMotorRunStates) (pScanData); void (*UpdateDataCurrentReadLine)(pScanData); Bool (*ReadOneImageLine) (pScanData); /* used only by ASIC9800x Part of the driver ! */ void (*ReInitAsic) (pScanData, Bool shading); /* value used to read nibble's */ Byte CtrlReadHighNibble; Byte CtrlReadLowNibble; /* * asic register offset values */ Byte RegSwitchBus; Byte RegEPPEnable; Byte RegECPEnable; Byte RegReadDataMode; Byte RegWriteDataMode; Byte RegInitDataFifo; Byte RegForceStep; Byte RegInitScanState; Byte RegRefreshScanState; Byte RegThresholdGapControl; Byte RegADCAddress; Byte RegADCData; Byte RegADCPixelOffset; Byte RegADCSerialOutStr; Byte RegResetConfig; Byte RegLensPosition; Byte RegStatus; Byte RegWaitStateInsert; Byte RegFifoOffset; Byte RegRFifoOffset; Byte RegGFifoOffset; Byte RegBFifoOffset; Byte RegBitDepth; Byte RegStepControl; Byte RegMotor0Control; Byte RegXStepTime; Byte RegGetScanState; Byte RegAsicID; Byte RegReadIOBufBus; Byte RegMemoryLow; Byte RegMemoryHigh; Byte RegModeControl; Byte RegLineControl; Byte RegScanControl; Byte RegMotorControl; #define _MotorDirForward 0x01 /* go forward */ #define _MotorOn 0x02 /* turn on motor */ #define _MotorIgnorePF 0x04 /* motor rolling don't care */ /* paper define flag */ #define _MotorFreeRun 0x80 /*ScanState count don't stop */ /* Following bits (bit 3 & 4 are depended on StatusPort */ /* bit-7:MotorType when it is 1: */ #define _Motor1FullStep 0x08 /* bit 4 is ignored */ /* When it is 0: */ #define _Motor0FullStepWeak 0 /* Full step (driving weak) */ #define _Motor0HalfStep 0x10 /* 1/2 step */ #define _Motor0QuarterStep 0x08 /* 1/4 step */ #define _Motor0FullStepStrong 0x18 /* Full step (driving strong)*/ #define _MotorStepMask 0xe7 /* for 96001 */ #define _MotorFullStep96001 0x02 #define _MotorOn96001 0x04 #define _MotorIgnorePF96001 0x08 Byte RegConfiguration; Byte RegModelControl; Byte RegModel1Control; Byte RegMemAccessControl; #define _MemBanks 64 /* the number of banks, 5 ls bits */ #define _MemBankMask (_MemBanks - 1) #define _MemBankSize1k 0 #define _MemBankSize2k 0x40 #define _MemBankSize4k 0x80 #define _MemBankSize8k 0xc0 /* 96001 specific */ #define _MemBankSize2k96001 0x00 #define _MemBankSize4k96001 0x40 #define _MemBankSize8k96001 0x80 Byte RegDpiLow; Byte RegDpiHigh; Byte RegScanPosLow; Byte RegScanPosHigh; Byte RegWidthPixelsLow; Byte RegWidthPixelsHigh; Byte RegThresholdLow; Byte RegThresholdHigh; Byte RegThresholdControl; Byte RegWatchDogControl; #define _WDOnIntervalMask 0x0f /* WD * 8192 scan lines to turn off Lamp */ #define _WDMotorLongInterval 0x40 /* short = 8192 lines time long = 32768 lines time */ #define _WDEnable 0x80 Byte RegModelControl2; #define _Model2ChannelSlct 0 #define _Model2ChannelMult 0x01 /* bit on/off accords to JONES */ #define _Model2CCSInvert 0x02 #define _Model2DirectOutPort 0x04 #define _Model2PipeLineDelayN 0x08 #define _Model2ShiftGapTiming10 0x10 #define _Model2BtnKeyPassThrough 0x20 Byte RegRedDCAdjust; Byte RegGreenDCAdjust; Byte RegBlueDCAdjust; Byte RegRedChShadingOffset; Byte RegGreenChShadingOffset; Byte RegBlueChShadingOffset; Byte RegRedChDarkOffset; Byte RegGreenChDarkOffset; Byte RegBlueChDarkOffset; Byte RegWriteIOBusDecode1; Byte RegWriteIOBusDecode2; Byte RegScanStateControl; #define _ScanStateEvenMask 0x0f #define _ScanStateOddMask 0xf0 Byte RegRedChEvenOffset; Byte RegGreenChEvenOffset; Byte RegBlueChEvenOffset; Byte RegRedChOddOffset; Byte RegGreenChOddOffset; Byte RegBlueChOddOffset; Byte RegRedGainOutDirect; Byte RegGreenGainOutDirect; Byte RegBlueGainOutDirect; Byte RegLedControl; #define _LedCmdActEnable 0x04 #define _LedMotorActEnable 0x08 #define _LedClrChActEnable 0x10 /* Color Channel Action */ #define _LedLightOnActEnable 0x20 #define _LedHostTurnOnEnable 0x40 #define _LedActControl 0x80 Byte RegShadingCorrectCtrl; #define _ShadingRCorrectX1 0 #define _ShadingRCorrectX2 0x01 #define _ShadingRCorrectX3 0x02 #define _ShadingRCorrectX4 0x03 #define _ShadingGCorrectX1 0 #define _ShadingGCorrectX2 0x04 #define _ShadingGCorrectX3 0x08 #define _ShadingGCorrectX4 0x0c #define _ShadingBCorrectX1 0 #define _ShadingBCorrectX2 0x10 #define _ShadingBCorrectX3 0x20 #define _ShadingBCorrectX4 0x30 Byte RegScanStateBegin; Byte RegRedChDarkOffsetLow; Byte RegRedChDarkOffsetHigh; Byte RegGreenChDarkOffsetLow; Byte RegGreenChDarkOffsetHigh; Byte RegBlueChDarkOffsetLow; Byte RegBlueChDarkOffsetHigh; Byte RegResetPulse0; Byte RegResetPulse1; Byte RegCCDClampTiming0; Byte RegCCDClampTiming1; Byte RegVSMPTiming0; Byte RegVSMPTiming1; Byte RegCCDQ1Timing0; Byte RegCCDQ1Timing1; Byte RegCCDQ1Timing2; Byte RegCCDQ1Timing3; Byte RegCCDQ2Timing0; Byte RegCCDQ2Timing1; Byte RegCCDQ2Timing2; Byte RegCCDQ2Timing3; Byte RegADCclockTiming0; Byte RegADCclockTiming1; Byte RegADCclockTiming2; Byte RegADCclockTiming3; Byte RegADCDVTiming0; Byte RegADCDVTiming1; Byte RegADCDVTiming2; Byte RegADCDVTiming3; Byte RegScanStateEnd; /* ASIC 98003 specific*/ Byte RegFifoFullLength0; Byte RegFifoFullLength1; Byte RegFifoFullLength2; Byte RegMotorTotalStep0; Byte RegMotorTotalStep1; Byte RegMotorFreeRunCount0; Byte RegMotorFreeRunCount1; Byte RegScanControl1; Byte RegMotorFreeRunTrigger; Byte RegResetMTSC; Byte RegMotor1Control; Byte RegMotor2Control; Byte RegMotorDriverType; Byte RegStatus2; Byte RegExtendedLineControl; Byte RegExtendedXStep; Byte RegPllPredivider; Byte RegPllMaindivider; Byte RegPllPostdivider; Byte RegClockSelector; Byte RegTestMode; /* CHECK: subject to change */ IODef IO; DeviceDef Device; ShadingDef Shade; ScanDef Scan; BufferDef Bufs; } ScanData; #endif /* guard __SCANDATA_H__ */ /* END PLUTSEK-PP_SCANDATA.H ................................................*/ sane-backends-1.0.27/backend/hs2p.c0000664000175000017500000034144712112021330013627 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Jeremy Johnson This file is part of a SANE backend for Ricoh IS450 and IS420 family of HS2P Scanners using the SCSI controller. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* SANE-FLOW-DIAGRAM - sane_init() : initialize backend, attach scanners . - sane_get_devices() : query list of scanner-devices . - sane_open() : open a particular scanner-device . . - attach : to the device . . . init_options : initialize SANE_OPTIONS array . . - sane_set_io_mode : set blocking-mode . . - sane_get_select_fd : get scanner-fd . . - sane_get_option_descriptor() : get option informations . . - sane_control_option() : change option values . . . . - sane_start() : start image aquisition . . - sane_get_parameters() : returns actual scan-parameters . . - sane_read() : read image-data (from pipe) . . . . - sane_cancel() : cancel operation . - sane_close() : close opened scanner-device - sane_exit() : terminate use of backend */ #define BUILD 1 /* Begin includes */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_thread.h" #define BACKEND_NAME hs2p #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "hs2p-scsi.c" /* Begin macros */ #define MIN(x,y) ((x)<(y) ? (x) : (y)) #define MAX(x,y) ((x)>(y) ? (x) : (y)) /* Begin static constants */ static int num_devices = 0; static HS2P_Device *first_dev = NULL; static HS2P_Scanner *first_handle = NULL; static SANE_Char inquiry_data[255] = "HS2P scanner"; /* static SANE_Int disable_optional_frames = 0; static SANE_Int fake_inquiry = 0; */ static HS2P_HWEntry HS2P_Device_List[] = { {"RICOH", "IS450"}, {"RICOH", "IS430"}, /*untested */ {"RICOH", "IS420"}, /*untested */ {"RICOH", "IS01"}, /*untested */ {"RICOH", "IS02"}, /*untested */ {NULL, NULL} /*sentinel */ }; #if 0 static int allblank (const char *s) { while (s && *s) if (!isspace (*s++)) return 0; return 1; } #endif static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; int i; DBG (DBG_proc, ">> max_string_size\n"); for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } DBG (DBG_proc, "<< max_string_size\n"); return max_size; } static void trim_spaces (char *s, size_t n) { for (s += (n - 1); n > 0; n--, s--) { if (*s && !isspace (*s)) break; *s = '\0'; } } static SANE_Bool is_device_supported (char *device) { HS2P_HWEntry *hw; for (hw = &HS2P_Device_List[0]; hw->mfg != NULL; hw++) if (strncmp (device, hw->model, strlen (hw->model)) == 0) break; /* found a match */ return (hw == NULL) ? SANE_FALSE : SANE_TRUE; } static SANE_Int get_list_index (const char *list[], char *s) /* sequential search */ { SANE_Int i; for (i = 0; list[i]; i++) if (strcmp (s, list[i]) == 0) return i; /* FOUND */ /* unknown paper_list strings are treated as 'custom' */ /* unknown compression_list strings are treated as 'none' */ /* unknown scan_source_list strings are treated as 'ADF' */ return 0; } static SANE_Int get_val_id_strndx (struct val_id *vi, int len, SANE_Int val) { int i; for (i = 0; i < len; i++) if (vi[i].val == val) return vi[i].id; /* FOUND */ return vi[0].id; /* NOT FOUND so let's default to first */ } static SANE_Status init_options (HS2P_Scanner * s) { SANE_Int i; DBG (DBG_proc, ">> init_options\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* * "Scan Mode" GROUP: */ s->opt[OPT_MODE_GROUP].name = ""; s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE_GROUP; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Preview: */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_PREVIEW].w = SANE_FALSE; /* Inquiry */ s->opt[OPT_INQUIRY].name = SANE_NAME_INQUIRY; s->opt[OPT_INQUIRY].title = SANE_TITLE_INQUIRY; s->opt[OPT_INQUIRY].desc = SANE_DESC_INQUIRY; s->opt[OPT_INQUIRY].type = SANE_TYPE_STRING; s->opt[OPT_INQUIRY].size = sizeof (inquiry_data); s->opt[OPT_INQUIRY].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_INQUIRY].s = strdup (inquiry_data); s->opt[OPT_INQUIRY].cap = SANE_CAP_SOFT_DETECT; /* Display Only */ /* Scan mode */ s->opt[OPT_SCAN_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_SCAN_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_SCAN_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_SCAN_MODE].type = SANE_TYPE_STRING; s->opt[OPT_SCAN_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_SCAN_MODE].size = max_string_size ((SANE_String_Const *) scan_mode_list); s->opt[OPT_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SCAN_MODE].constraint.string_list = (SANE_String_Const *) & scan_mode_list[0]; s->val[OPT_SCAN_MODE].s = strdup (scan_mode_list[0]); s->image_composition = LINEART; /* Standard resolutions */ s->opt[OPT_RESOLUTION].name = "std-" SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = "Std-" SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = "Std " SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->info.resStdList; s->val[OPT_RESOLUTION].w = s->hw->info.default_res; /* X Resolution */ s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_X_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = "X " SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_X_RESOLUTION].constraint.range = &(s->hw->info.xres_range); s->val[OPT_X_RESOLUTION].w = s->hw->info.resBasicX; /* Y Resolution */ s->opt[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION; s->opt[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION; s->opt[OPT_Y_RESOLUTION].desc = "Y " SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_Y_RESOLUTION].constraint.range = &(s->hw->info.yres_range); s->val[OPT_Y_RESOLUTION].w = s->hw->info.resBasicY; /* Compression */ s->opt[OPT_COMPRESSION].name = SANE_NAME_COMPRESSION; s->opt[OPT_COMPRESSION].title = SANE_TITLE_COMPRESSION; s->opt[OPT_COMPRESSION].desc = SANE_DESC_COMPRESSION; s->opt[OPT_COMPRESSION].type = SANE_TYPE_STRING; s->opt[OPT_COMPRESSION].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_COMPRESSION].size = max_string_size ((SANE_String_Const *) compression_list); s->opt[OPT_COMPRESSION].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_COMPRESSION].constraint.string_list = (SANE_String_Const *) & compression_list[0]; s->val[OPT_COMPRESSION].s = strdup (compression_list[0]); if (s->hw->info.supports_MH == SANE_FALSE || /* MH G3 1-D */ s->hw->info.supports_MR == SANE_FALSE || /* MR G3 2-D */ s->hw->info.supports_MMR == SANE_FALSE || /* MMR G4 2-D */ s->hw->info.supports_MHB == SANE_FALSE) /* MH byte boundary */ { s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE; } /* * "Geometry" GROUP: */ s->opt[OPT_GEOMETRY_GROUP].name = ""; s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY_GROUP; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Auto Size Recognition available if IPU installed */ s->opt[OPT_AUTO_SIZE].name = SANE_NAME_AUTO_SIZE; s->opt[OPT_AUTO_SIZE].title = SANE_TITLE_AUTO_SIZE; s->opt[OPT_AUTO_SIZE].desc = SANE_DESC_AUTO_SIZE; s->opt[OPT_AUTO_SIZE].type = SANE_TYPE_BOOL; s->opt[OPT_AUTO_SIZE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_AUTO_SIZE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_AUTO_SIZE].w = SANE_FALSE; if (!s->hw->info.supports_sizerecognition) s->opt[OPT_AUTO_SIZE].cap |= SANE_CAP_INACTIVE; /* Pad short documents to requested length with white space */ s->opt[OPT_PADDING].name = SANE_NAME_PADDING; s->opt[OPT_PADDING].title = SANE_TITLE_PADDING; s->opt[OPT_PADDING].desc = SANE_DESC_PADDING; s->opt[OPT_PADDING].type = SANE_TYPE_BOOL; s->opt[OPT_PADDING].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_PADDING].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_PADDING].w = SANE_TRUE; /*if (!s->hw->info.hasADF) s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE; FIXME: compare to user setting, not the existence of FB? if (!strcmp (scan_source_list, "FB")) s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE; */ /* Permanently disable OPT_PADDING */ s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE; /* Paper Orientation */ s->opt[OPT_PAGE_ORIENTATION].name = SANE_NAME_ORIENTATION; s->opt[OPT_PAGE_ORIENTATION].title = SANE_TITLE_ORIENTATION; s->opt[OPT_PAGE_ORIENTATION].desc = SANE_DESC_ORIENTATION; s->opt[OPT_PAGE_ORIENTATION].type = SANE_TYPE_STRING; s->opt[OPT_PAGE_ORIENTATION].size = max_string_size (orientation_list); s->opt[OPT_PAGE_ORIENTATION].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_PAGE_ORIENTATION].constraint.string_list = &orientation_list[0]; s->val[OPT_PAGE_ORIENTATION].s = strdup (orientation_list[0]); /* Paper Size */ s->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE; s->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE; s->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE; s->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING; s->opt[OPT_PAPER_SIZE].size = max_string_size (paper_list); s->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_PAPER_SIZE].constraint.string_list = &paper_list[0]; s->val[OPT_PAPER_SIZE].s = strdup (paper_list[0]); /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &(s->hw->info.x_range); s->val[OPT_TL_X].w = SANE_FIX (0.0); /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &(s->hw->info.y_range); s->val[OPT_TL_Y].w = SANE_FIX (0.0); /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &(s->hw->info.x_range); s->val[OPT_BR_X].w = s->hw->info.x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &(s->hw->info.y_range); s->val[OPT_BR_Y].w = s->hw->info.y_range.max; DBG (DBG_info, "INIT_OPTIONS: ul(x,y) = (%d,%d) br(x,y) = (%d,%d)\n", (unsigned) SANE_UNFIX (s->val[OPT_TL_X].w), (unsigned) SANE_UNFIX (s->val[OPT_TL_Y].w), (unsigned) SANE_UNFIX (s->val[OPT_BR_X].w), (unsigned) SANE_UNFIX (s->val[OPT_BR_Y].w)); /* Autoborder */ /* Rotation */ /* Deskew */ /* * "Feeder" GROUP: */ s->opt[OPT_FEEDER_GROUP].name = ""; s->opt[OPT_FEEDER_GROUP].title = SANE_TITLE_FEEDER_GROUP; s->opt[OPT_FEEDER_GROUP].desc = ""; s->opt[OPT_FEEDER_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_FEEDER_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_FEEDER_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scan Source */ s->opt[OPT_SCAN_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SCAN_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SCAN_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SCAN_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SCAN_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_SCAN_SOURCE].size = max_string_size (scan_source_list); s->opt[OPT_SCAN_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SCAN_SOURCE].constraint.string_list = (SANE_String_Const *) & scan_source_list[0]; s->val[OPT_SCAN_SOURCE].s = strdup (scan_source_list[0]); if (!s->hw->info.hasADF) s->opt[OPT_SCAN_SOURCE].cap |= SANE_CAP_INACTIVE; /* Duplex: */ s->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX; s->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX; s->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX; s->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL; s->opt[OPT_DUPLEX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_DUPLEX].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_DUPLEX].w = s->hw->info.default_duplex; if (!s->hw->info.hasDuplex) s->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE; /* Prefeed: */ s->opt[OPT_PREFEED].name = SANE_NAME_PREFEED; s->opt[OPT_PREFEED].title = SANE_TITLE_PREFEED; s->opt[OPT_PREFEED].desc = SANE_DESC_PREFEED; s->opt[OPT_PREFEED].type = SANE_TYPE_BOOL; s->opt[OPT_PREFEED].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_PREFEED].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_PREFEED].w = SANE_FALSE; s->opt[OPT_PREFEED].cap |= SANE_CAP_INACTIVE; /* Endorser: */ s->opt[OPT_ENDORSER].name = SANE_NAME_ENDORSER; s->opt[OPT_ENDORSER].title = SANE_TITLE_ENDORSER; s->opt[OPT_ENDORSER].desc = SANE_DESC_ENDORSER; s->opt[OPT_ENDORSER].type = SANE_TYPE_BOOL; s->opt[OPT_ENDORSER].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_ENDORSER].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_ENDORSER].w = s->hw->info.endorser_control; if (!s->hw->info.hasEndorser) s->opt[OPT_ENDORSER].cap |= SANE_CAP_INACTIVE; /* Endorser String: */ s->opt[OPT_ENDORSER_STRING].name = SANE_NAME_ENDORSER_STRING; s->opt[OPT_ENDORSER_STRING].title = SANE_TITLE_ENDORSER_STRING; s->opt[OPT_ENDORSER_STRING].desc = SANE_DESC_ENDORSER_STRING; s->opt[OPT_ENDORSER_STRING].type = SANE_TYPE_STRING; s->opt[OPT_ENDORSER_STRING].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_ENDORSER_STRING].size = sizeof (s->hw->info.endorser_string); s->opt[OPT_ENDORSER_STRING].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_ENDORSER_STRING].s = strdup (s->hw->info.endorser_string); if (!s->hw->info.hasEndorser) s->opt[OPT_ENDORSER_STRING].cap |= SANE_CAP_INACTIVE; /* Batch */ /* Check ADF */ /* timeout ADF */ /* timeout Manual */ /* * "Enhancement" GROUP: */ s->opt[OPT_ENHANCEMENT_GROUP].name = ""; s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Halftone Type */ s->opt[OPT_HALFTONE_CODE].name = SANE_NAME_HALFTONE_CODE; s->opt[OPT_HALFTONE_CODE].title = SANE_TITLE_HALFTONE_CODE; s->opt[OPT_HALFTONE_CODE].desc = SANE_DESC_HALFTONE_CODE; s->opt[OPT_HALFTONE_CODE].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE_CODE].size = max_string_size (halftone_code); s->opt[OPT_HALFTONE_CODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_HALFTONE_CODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_HALFTONE_CODE].constraint.string_list = (SANE_String_Const *) & halftone_code[0]; s->val[OPT_HALFTONE_CODE].s = strdup (halftone_code[0]); if (s->image_composition == LINEART) s->opt[OPT_HALFTONE_CODE].cap |= SANE_CAP_INACTIVE; /* Halftone patterns */ s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE_PATTERN].size = max_string_size ((SANE_String_Const *) halftone_pattern_list); s->opt[OPT_HALFTONE_PATTERN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = (SANE_String_Const *) & halftone_pattern_list[0]; s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[0]); if (s->image_composition == LINEART) s->opt[OPT_HALFTONE_CODE].cap |= SANE_CAP_INACTIVE; /* Gray Filter */ s->opt[OPT_GRAYFILTER].name = SANE_NAME_GRAYFILTER; s->opt[OPT_GRAYFILTER].title = SANE_TITLE_GRAYFILTER; s->opt[OPT_GRAYFILTER].desc = SANE_DESC_GRAYFILTER; s->opt[OPT_GRAYFILTER].type = SANE_TYPE_STRING; s->opt[OPT_GRAYFILTER].size = max_string_size (grayfilter_list); s->opt[OPT_GRAYFILTER].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_GRAYFILTER].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_GRAYFILTER].constraint.string_list = (SANE_String_Const *) & grayfilter_list[0]; s->val[OPT_GRAYFILTER].s = strdup (grayfilter_list[0]); /* Scan Wait Mode */ s->opt[OPT_SCAN_WAIT_MODE].name = SANE_NAME_SCAN_WAIT_MODE; s->opt[OPT_SCAN_WAIT_MODE].title = SANE_TITLE_SCAN_WAIT_MODE; s->opt[OPT_SCAN_WAIT_MODE].desc = SANE_DESC_SCAN_WAIT_MODE; s->opt[OPT_SCAN_WAIT_MODE].type = SANE_TYPE_BOOL; s->opt[OPT_SCAN_WAIT_MODE].unit = SANE_UNIT_NONE; s->val[OPT_SCAN_WAIT_MODE].w = (s->hw->info.scan_wait_mode) ? SANE_TRUE : SANE_FALSE; /* Brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->info.brightness_range; s->val[OPT_BRIGHTNESS].w = 128; /* Threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &s->hw->info.threshold_range; s->val[OPT_THRESHOLD].w = 128; /* Contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &s->hw->info.contrast_range; s->val[OPT_CONTRAST].w = 128; /* Gamma */ s->opt[OPT_GAMMA].name = SANE_NAME_GAMMA; s->opt[OPT_GAMMA].title = SANE_TITLE_GAMMA; s->opt[OPT_GAMMA].desc = SANE_DESC_GAMMA; s->opt[OPT_GAMMA].type = SANE_TYPE_STRING; s->opt[OPT_GAMMA].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_GAMMA].size = max_string_size ((SANE_String_Const *) gamma_list); /* s->opt[OPT_GAMMA].type = SANE_TYPE_INT; s->opt[OPT_GAMMA].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA].constraint.range = &u8_range; s->val[OPT_GAMMA].w = 0; */ s->opt[OPT_GAMMA].type = SANE_TYPE_STRING; s->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_GAMMA].constraint.string_list = (SANE_String_Const *) & gamma_list[0]; s->val[OPT_GAMMA].s = strdup (gamma_list[0]); /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->opt[OPT_CUSTOM_GAMMA].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR_GRAY].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR_GRAY].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR_GRAY].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR_GRAY].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_GAMMA_VECTOR_GRAY].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_GRAY].size = GAMMA_LENGTH * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_GRAY].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_GRAY].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_GRAY].wa = s->gamma_table; s->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; /* Control Panel */ /* ACE Function */ /* ACE Sensitivity */ /* Binary Smoothing Filter */ s->opt[OPT_SMOOTHING].name = SANE_NAME_SMOOTHING; s->opt[OPT_SMOOTHING].title = SANE_TITLE_SMOOTHING; s->opt[OPT_SMOOTHING].desc = SANE_DESC_SMOOTHING; s->opt[OPT_SMOOTHING].type = SANE_TYPE_BOOL; s->opt[OPT_SMOOTHING].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_SMOOTHING].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_SMOOTHING].w = SANE_FALSE; if (!s->hw->info.hasIPU) s->opt[OPT_SMOOTHING].cap |= SANE_CAP_INACTIVE; /* Binary Noise Removal Filter */ s->opt[OPT_NOISEREMOVAL].name = SANE_NAME_NOISEREMOVAL; s->opt[OPT_NOISEREMOVAL].title = SANE_TITLE_NOISEREMOVAL; s->opt[OPT_NOISEREMOVAL].desc = SANE_DESC_NOISEREMOVAL; s->opt[OPT_NOISEREMOVAL].type = SANE_TYPE_STRING; s->opt[OPT_NOISEREMOVAL].size = max_string_size (noisematrix_list); s->opt[OPT_NOISEREMOVAL].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_NOISEREMOVAL].constraint.string_list = (SANE_String_Const *) & noisematrix_list[0]; s->val[OPT_NOISEREMOVAL].s = strdup (noisematrix_list[0]); if (!s->hw->info.hasIPU) s->opt[OPT_NOISEREMOVAL].cap |= SANE_CAP_INACTIVE; /* Automatic Separation */ s->opt[OPT_AUTOSEP].name = SANE_NAME_AUTOSEP; s->opt[OPT_AUTOSEP].title = SANE_TITLE_AUTOSEP; s->opt[OPT_AUTOSEP].desc = SANE_DESC_AUTOSEP; s->opt[OPT_AUTOSEP].type = SANE_TYPE_STRING; s->opt[OPT_AUTOSEP].size = max_string_size (auto_separation_list); s->opt[OPT_AUTOSEP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_AUTOSEP].constraint.string_list = (SANE_String_Const *) & auto_separation_list[0]; s->val[OPT_AUTOSEP].s = strdup (auto_separation_list[0]); if (!s->hw->info.hasIPU) s->opt[OPT_AUTOSEP].cap |= SANE_CAP_INACTIVE; /* Automatic Binarization */ s->opt[OPT_AUTOBIN].name = SANE_NAME_AUTOBIN; s->opt[OPT_AUTOBIN].title = SANE_TITLE_AUTOBIN; s->opt[OPT_AUTOBIN].desc = SANE_DESC_AUTOBIN; s->opt[OPT_AUTOBIN].type = SANE_TYPE_STRING; s->opt[OPT_AUTOBIN].size = max_string_size (auto_binarization_list); s->opt[OPT_AUTOBIN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_AUTOBIN].constraint.string_list = (SANE_String_Const *) & auto_binarization_list[0]; s->val[OPT_AUTOBIN].s = strdup (auto_binarization_list[0]); if (!s->hw->info.hasIPU) s->opt[OPT_AUTOBIN].cap |= SANE_CAP_INACTIVE; /* SECTION * The IS450 supports up to 4 Section; The IS420 supports up to 6 Sections * For each struct window_section[i] we need to fill in ulx,uly,width,height,etc * NOT YET IMPLEMENTED */ /* Negative */ s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; s->opt[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE; s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL; s->opt[OPT_NEGATIVE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_NEGATIVE].w = SANE_FALSE; /* White Balance */ s->opt[OPT_WHITE_BALANCE].name = SANE_NAME_WHITE_BALANCE; s->opt[OPT_WHITE_BALANCE].title = SANE_TITLE_WHITE_BALANCE; s->opt[OPT_WHITE_BALANCE].desc = SANE_DESC_WHITE_BALANCE; s->opt[OPT_WHITE_BALANCE].type = SANE_TYPE_BOOL; s->opt[OPT_WHITE_BALANCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[OPT_WHITE_BALANCE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_WHITE_BALANCE].w = SANE_FALSE; /* F/T = Relative/Absolute White */ /* * "Miscellaneous" GROUP: */ s->opt[OPT_MISCELLANEOUS_GROUP].name = ""; s->opt[OPT_MISCELLANEOUS_GROUP].title = SANE_TITLE_MISCELLANEOUS_GROUP; s->opt[OPT_MISCELLANEOUS_GROUP].desc = ""; s->opt[OPT_MISCELLANEOUS_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MISCELLANEOUS_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_MISCELLANEOUS_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Padding Type: */ s->opt[OPT_PADDING_TYPE].name = SANE_NAME_PADDING_TYPE; s->opt[OPT_PADDING_TYPE].title = SANE_TITLE_PADDING_TYPE; s->opt[OPT_PADDING_TYPE].desc = SANE_DESC_PADDING_TYPE; s->opt[OPT_PADDING_TYPE].type = SANE_TYPE_STRING; s->opt[OPT_PADDING_TYPE].cap = SANE_CAP_SOFT_DETECT; /* Display only */ s->opt[OPT_PADDING_TYPE].size = max_string_size (paddingtype_list); /* s->opt[OPT_PADDING_TYPE].size = sizeof((paddingtype_list[ get_paddingtype_strndx(TRUNCATE) ])); s->opt[OPT_PADDING_TYPE].constraint_type = SANE_CONSTRAINT_NONE; */ s->opt[OPT_PADDING_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_PADDING_TYPE].constraint.string_list = (SANE_String_Const *) & paddingtype_list[0]; s->val[OPT_PADDING_TYPE].s = strdup (paddingtype_list[get_paddingtype_strndx (TRUNCATE)]); DBG (DBG_info, "PADDINGTYPE =%s size=%d\n", s->val[OPT_PADDING_TYPE].s, s->opt[OPT_PADDING_TYPE].size); /* Bit Order s->opt[OPT_BITORDER].name = SANE_NAME_BITORDER; s->opt[OPT_BITORDER].title = SANE_TITLE_BITORDER; s->opt[OPT_BITORDER].desc = SANE_DESC_BITORDER; s->opt[OPT_BITORDER].type = SANE_TYPE_WORD; s->opt[OPT_BITORDER].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_BITORDER].constraint_type = SANE_CONSTRAINT_NONE s->val[OPT_BITORDER].w = 0x7; */ /* Self Diagnostics */ s->opt[OPT_SELF_DIAGNOSTICS].name = SANE_NAME_SELF_DIAGNOSTICS; s->opt[OPT_SELF_DIAGNOSTICS].title = SANE_TITLE_SELF_DIAGNOSTICS; s->opt[OPT_SELF_DIAGNOSTICS].desc = SANE_DESC_SELF_DIAGNOSTICS; s->opt[OPT_SELF_DIAGNOSTICS].type = SANE_TYPE_BUTTON; /* Optical Diagnostics */ s->opt[OPT_OPTICAL_ADJUSTMENT].name = SANE_NAME_OPTICAL_ADJUSTMENT; s->opt[OPT_OPTICAL_ADJUSTMENT].title = SANE_TITLE_OPTICAL_ADJUSTMENT; s->opt[OPT_OPTICAL_ADJUSTMENT].desc = SANE_DESC_OPTICAL_ADJUSTMENT; s->opt[OPT_OPTICAL_ADJUSTMENT].type = SANE_TYPE_BUTTON; /* MAINTENANCE DATA */ s->opt[OPT_DATA_GROUP].name = ""; s->opt[OPT_DATA_GROUP].title = "Maintenance Data"; s->opt[OPT_DATA_GROUP].desc = ""; s->opt[OPT_DATA_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_DATA_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_DATA_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_UPDATE].name = "Update"; s->opt[OPT_UPDATE].title = "Update"; s->opt[OPT_UPDATE].desc = "Update scanner data"; s->opt[OPT_UPDATE].type = SANE_TYPE_BUTTON; s->opt[OPT_NREGX_ADF].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NREGX_ADF].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NREGX_ADF].name = "# registers in main-scanning in ADF mode"; s->opt[OPT_NREGX_ADF].title = "# registers in main-scanning in ADF mode"; s->opt[OPT_NREGX_ADF].desc = "# registers in main-scanning in ADF mode"; s->opt[OPT_NREGX_ADF].type = SANE_TYPE_INT; s->opt[OPT_NREGX_ADF].unit = SANE_UNIT_NONE; s->opt[OPT_NREGX_ADF].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NREGX_ADF].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NREGY_ADF].name = "# registers in sub-scanning in ADF mode"; s->opt[OPT_NREGY_ADF].title = "# registers in sub-scanning in ADF mode"; s->opt[OPT_NREGY_ADF].desc = "# registers in sub-scanning in ADF mode"; s->opt[OPT_NREGY_ADF].type = SANE_TYPE_INT; s->opt[OPT_NREGY_ADF].unit = SANE_UNIT_NONE; s->opt[OPT_NREGY_ADF].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NREGY_ADF].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NREGX_BOOK].name = "# registers in main-scanning in book mode"; s->opt[OPT_NREGX_BOOK].title = "# registers in main-scanning in book mode"; s->opt[OPT_NREGX_BOOK].desc = "# registers in main-scanning in book mode"; s->opt[OPT_NREGX_BOOK].type = SANE_TYPE_INT; s->opt[OPT_NREGX_BOOK].unit = SANE_UNIT_NONE; s->opt[OPT_NREGX_BOOK].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NREGX_BOOK].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NREGY_BOOK].name = "# registers in sub-scanning in book mode"; s->opt[OPT_NREGY_BOOK].title = "# registers in sub-scanning in book mode"; s->opt[OPT_NREGY_BOOK].desc = "# registers in sub-scanning in book mode"; s->opt[OPT_NREGY_BOOK].type = SANE_TYPE_INT; s->opt[OPT_NREGY_BOOK].unit = SANE_UNIT_NONE; s->opt[OPT_NREGY_BOOK].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NREGY_BOOK].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NSCANS_ADF].name = "# ADF Scans"; s->opt[OPT_NSCANS_ADF].title = "# ADF Scans"; s->opt[OPT_NSCANS_ADF].desc = "# ADF Scans"; s->opt[OPT_NSCANS_ADF].type = SANE_TYPE_INT; s->opt[OPT_NSCANS_ADF].unit = SANE_UNIT_NONE; s->opt[OPT_NSCANS_ADF].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NSCANS_ADF].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NSCANS_BOOK].name = "# BOOK Scans"; s->opt[OPT_NSCANS_BOOK].title = "# BOOK Scans"; s->opt[OPT_NSCANS_BOOK].desc = "# BOOK Scans"; s->opt[OPT_NSCANS_BOOK].type = SANE_TYPE_INT; s->opt[OPT_NSCANS_BOOK].unit = SANE_UNIT_NONE; s->opt[OPT_NSCANS_BOOK].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NSCANS_BOOK].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_LAMP_TIME].name = "LAMP TIME"; s->opt[OPT_LAMP_TIME].title = "LAMP TIME"; s->opt[OPT_LAMP_TIME].desc = "LAMP TIME"; s->opt[OPT_LAMP_TIME].type = SANE_TYPE_INT; s->opt[OPT_LAMP_TIME].unit = SANE_UNIT_NONE; s->opt[OPT_LAMP_TIME].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_LAMP_TIME].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_EO_ODD].name = "E/O Balance ODD"; s->opt[OPT_EO_ODD].title = "E/O Balance ODD"; s->opt[OPT_EO_ODD].desc = "Adj. of E/O Balance in black level ODD"; s->opt[OPT_EO_ODD].type = SANE_TYPE_INT; s->opt[OPT_EO_ODD].unit = SANE_UNIT_NONE; s->opt[OPT_EO_ODD].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_EO_ODD].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_EO_EVEN].name = "E/O Balance EVEN"; s->opt[OPT_EO_EVEN].title = "E/O Balance EVEN"; s->opt[OPT_EO_EVEN].desc = "Adj. of E/O Balance in black level EVEN"; s->opt[OPT_EO_EVEN].type = SANE_TYPE_INT; s->opt[OPT_EO_EVEN].unit = SANE_UNIT_NONE; s->opt[OPT_EO_EVEN].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_EO_EVEN].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_BLACK_LEVEL_ODD].name = "Black Level ODD"; s->opt[OPT_BLACK_LEVEL_ODD].title = "Black Level ODD"; s->opt[OPT_BLACK_LEVEL_ODD].desc = "Adj. data in black level (ODD)"; s->opt[OPT_BLACK_LEVEL_ODD].type = SANE_TYPE_INT; s->opt[OPT_BLACK_LEVEL_ODD].unit = SANE_UNIT_NONE; s->opt[OPT_BLACK_LEVEL_ODD].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_BLACK_LEVEL_ODD].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_BLACK_LEVEL_EVEN].name = "Black Level EVEN"; s->opt[OPT_BLACK_LEVEL_EVEN].title = "Black Level EVEN"; s->opt[OPT_BLACK_LEVEL_EVEN].desc = "Adj. data in black level (EVEN)"; s->opt[OPT_BLACK_LEVEL_EVEN].type = SANE_TYPE_INT; s->opt[OPT_BLACK_LEVEL_EVEN].unit = SANE_UNIT_NONE; s->opt[OPT_BLACK_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_BLACK_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_WHITE_LEVEL_ODD].name = "White Level ODD"; s->opt[OPT_WHITE_LEVEL_ODD].title = "White Level ODD"; s->opt[OPT_WHITE_LEVEL_ODD].desc = "Adj. data in White level (ODD)"; s->opt[OPT_WHITE_LEVEL_ODD].type = SANE_TYPE_INT; s->opt[OPT_WHITE_LEVEL_ODD].unit = SANE_UNIT_NONE; s->opt[OPT_WHITE_LEVEL_ODD].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_WHITE_LEVEL_ODD].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_WHITE_LEVEL_EVEN].name = "White Level EVEN"; s->opt[OPT_WHITE_LEVEL_EVEN].title = "White Level EVEN"; s->opt[OPT_WHITE_LEVEL_EVEN].desc = "Adj. data in White level (EVEN)"; s->opt[OPT_WHITE_LEVEL_EVEN].type = SANE_TYPE_INT; s->opt[OPT_WHITE_LEVEL_EVEN].unit = SANE_UNIT_NONE; s->opt[OPT_WHITE_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_WHITE_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_WHITE_LEVEL_EVEN].name = "White Level EVEN"; s->opt[OPT_WHITE_LEVEL_EVEN].title = "White Level EVEN"; s->opt[OPT_WHITE_LEVEL_EVEN].desc = "Adj. data in White level (EVEN)"; s->opt[OPT_WHITE_LEVEL_EVEN].type = SANE_TYPE_INT; s->opt[OPT_WHITE_LEVEL_EVEN].unit = SANE_UNIT_NONE; s->opt[OPT_WHITE_LEVEL_EVEN].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_WHITE_LEVEL_EVEN].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_DENSITY].name = "Density Adjustment"; s->opt[OPT_DENSITY].title = "Density Adjustment"; s->opt[OPT_DENSITY].desc = "Density adjustment of std. white board"; s->opt[OPT_DENSITY].type = SANE_TYPE_INT; s->opt[OPT_DENSITY].unit = SANE_UNIT_NONE; s->opt[OPT_DENSITY].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_DENSITY].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_FIRST_ADJ_WHITE_ODD].name = "1st adj. in white level (ODD)"; s->opt[OPT_FIRST_ADJ_WHITE_ODD].title = "1st adj. in white level (ODD)"; s->opt[OPT_FIRST_ADJ_WHITE_ODD].desc = "1st adj. in white level (ODD)"; s->opt[OPT_FIRST_ADJ_WHITE_ODD].type = SANE_TYPE_INT; s->opt[OPT_FIRST_ADJ_WHITE_ODD].unit = SANE_UNIT_NONE; s->opt[OPT_FIRST_ADJ_WHITE_ODD].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_FIRST_ADJ_WHITE_ODD].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_FIRST_ADJ_WHITE_EVEN].name = "1st adj. in white level (EVEN)"; s->opt[OPT_FIRST_ADJ_WHITE_EVEN].title = "1st adj. in white level (EVEN)"; s->opt[OPT_FIRST_ADJ_WHITE_EVEN].desc = "1st adj. in white level (EVEN)"; s->opt[OPT_FIRST_ADJ_WHITE_EVEN].type = SANE_TYPE_INT; s->opt[OPT_FIRST_ADJ_WHITE_EVEN].unit = SANE_UNIT_NONE; s->opt[OPT_FIRST_ADJ_WHITE_EVEN].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_FIRST_ADJ_WHITE_EVEN].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NREGX_REVERSE].name = "# registers of main-scanning of backside"; s->opt[OPT_NREGX_REVERSE].title = "# registers of main-scanning of backside"; s->opt[OPT_NREGX_REVERSE].desc = "# registers of main-scanning of ADF backside"; s->opt[OPT_NREGX_REVERSE].type = SANE_TYPE_INT; s->opt[OPT_NREGX_REVERSE].unit = SANE_UNIT_NONE; s->opt[OPT_NREGX_REVERSE].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NREGX_REVERSE].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NREGY_REVERSE].name = "# registers of sub-scanning of backside"; s->opt[OPT_NREGY_REVERSE].title = "# registers of sub-scanning of backside"; s->opt[OPT_NREGY_REVERSE].desc = "# registers of sub-scanning of ADF backside"; s->opt[OPT_NREGY_REVERSE].type = SANE_TYPE_INT; s->opt[OPT_NREGY_REVERSE].unit = SANE_UNIT_NONE; s->opt[OPT_NREGY_REVERSE].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NREGY_REVERSE].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NSCANS_REVERSE_ADF].name = "# of scans of reverse side in ADF"; s->opt[OPT_NSCANS_REVERSE_ADF].title = "# of scans of reverse side in ADF"; s->opt[OPT_NSCANS_REVERSE_ADF].desc = "# of scans of reverse side in ADF"; s->opt[OPT_NSCANS_REVERSE_ADF].type = SANE_TYPE_INT; s->opt[OPT_NSCANS_REVERSE_ADF].unit = SANE_UNIT_NONE; s->opt[OPT_NSCANS_REVERSE_ADF].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NSCANS_REVERSE_ADF].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_REVERSE_TIME].name = "LAMP TIME (reverse)"; s->opt[OPT_REVERSE_TIME].title = "LAMP TIME (reverse)"; s->opt[OPT_REVERSE_TIME].desc = "LAMP TIME (reverse)"; s->opt[OPT_REVERSE_TIME].type = SANE_TYPE_INT; s->opt[OPT_REVERSE_TIME].unit = SANE_UNIT_NONE; s->opt[OPT_REVERSE_TIME].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_REVERSE_TIME].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NCHARS].name = "# of endorser characters"; s->opt[OPT_NCHARS].title = "# of endorser characters"; s->opt[OPT_NCHARS].desc = "# of endorser characters"; s->opt[OPT_NCHARS].type = SANE_TYPE_INT; s->opt[OPT_NCHARS].unit = SANE_UNIT_NONE; s->opt[OPT_NCHARS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NCHARS].constraint_type = SANE_CONSTRAINT_NONE; DBG (DBG_proc, "<< init_options\n"); return SANE_STATUS_GOOD; } static SANE_Status attach (SANE_String_Const devname, int __sane_unused__ connType, HS2P_Device ** devp) { SANE_Status status; HS2P_Device *dev; struct inquiry_standard_data ibuf; struct inquiry_vpd_data vbuf; struct inquiry_jis_data jbuf; size_t buf_size; int fd = -1; double mm; char device_string[60]; unsigned int i; SANE_String *str; DBG (DBG_sane_proc, ">>> attach:\n"); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } } DBG (DBG_sane_proc, ">>> attach: opening \"%s\"\n", devname); /* sanei_scsi_open takes an option bufsize argument */ status = sanei_scsi_open (devname, &fd, &sense_handler, &(dev->sense_data)); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, ">>> attach: open failed: %s\n", sane_strstatus (status)); return (status); } DBG (DBG_sane_proc, ">>> attach: opened %s fd=%d\n", devname, fd); DBG (DBG_sane_proc, ">>> attach: sending INQUIRY (standard data)\n"); memset (&ibuf, 0, sizeof (ibuf)); buf_size = sizeof (ibuf); status = inquiry (fd, &ibuf, &buf_size, 0, HS2P_INQUIRY_STANDARD_PAGE_CODE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, ">>> attach: inquiry failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } DBG (DBG_info, ">>> attach: reported devtype='%d', vendor='%.8s', product='%.16s', revision='%.4s'\n", ibuf.devtype, ibuf.vendor, ibuf.product, ibuf.revision); DBG (DBG_info, ">>> attach: reported RMB=%#x Ver=%#x ResponseDataFormat=%#x Length=%#x Byte7=%#x\n", ibuf.rmb_evpd, ibuf.version, ibuf.response_data_format, ibuf.length, ibuf.byte7); if (ibuf.devtype != 6 || strncmp ((char *) ibuf.vendor, "RICOH ", 8) != 0) { DBG (DBG_warning, ">>> attach: device is not a RICOH scanner\n"); sanei_scsi_close (fd); return SANE_STATUS_INVAL; } else if (!is_device_supported ((char *) ibuf.product)) { DBG (DBG_warning, ">>> attach: device %s is not yet a supported RICOH scanner\n", ibuf.product); sanei_scsi_close (fd); return SANE_STATUS_INVAL; } /* We should now have an open file descriptor to a supported hs2p scanner */ DBG (DBG_sane_proc, ">>> attach: sending TEST_UNIT_READY\n"); do { status = test_unit_ready (fd); } while (status == HS2P_SK_UNIT_ATTENTION); if (status != HS2P_SCSI_STATUS_GOOD) { DBG (DBG_error, ">>> attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } DBG (DBG_sane_proc, ">>> attach: sending INQUIRY (vpd data)\n"); memset (&vbuf, 0, sizeof (vbuf)); buf_size = sizeof (vbuf); status = inquiry (fd, &vbuf, &buf_size, 1, HS2P_INQUIRY_VPD_PAGE_CODE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, ">>> attach: inquiry (vpd data) failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } print_vpd_info (&vbuf); DBG (DBG_sane_proc, ">>> attach: sending INQUIRY (jis data)\n"); memset (&jbuf, 0, sizeof (jbuf)); buf_size = sizeof (jbuf); status = inquiry (fd, &jbuf, &buf_size, 1, HS2P_INQUIRY_JIS_PAGE_CODE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, ">>> attach: inquiry (jis data) failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } print_jis_info (&jbuf); /* Fill in HS2P_Device {sane;info} */ dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (*dev)); /* Maximum Number of Sub-Sections of Main Scanning Window */ if (strncmp ((char *) ibuf.product, "IS450", 5) == 0) { dev->info.max_win_sections = 4; } else if (strncmp ((char *) ibuf.product, "IS420", 5) == 0) { dev->info.max_win_sections = 6; } /* Some MODE SELECT scanner options */ DBG (DBG_proc, ">>> attach: get_basic_measurement_unit\n"); status = get_basic_measurement_unit (fd, &(dev->info.bmu), &(dev->info.mud)); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, ">>> attach: get_basic_measurement_unit failed (%s)\n", sane_strstatus (status)); DBG (DBG_error, ">>> attach: setting to defaults\n"); status = set_basic_measurement_unit (fd, MILLIMETERS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, ">>> attach: set_basic_measurement_unit failed (%s)\n", sane_strstatus (status)); } } if ((status = get_connection_parameters (fd, &(dev->info.cxn))) != SANE_STATUS_GOOD) { DBG (DBG_error, ">>> attach: get_connection_parameters failed\n"); } status = get_endorser_control (fd, &dev->info.endorser_control); if (status != SANE_STATUS_GOOD || dev->info.endorser_control != 0x01) { DBG (DBG_error, ">>> attach: get_endorser_control failed: return value=%#02x\n", dev->info.endorser_control); dev->info.endorser_control = 0x00; } if ((dev->info.service_mode = get_service_mode (fd)) != 0x00 && dev->info.service_mode != 0x01) { DBG (DBG_error, ">>> attach: get_service_mode failed %#02x\n", dev->info.service_mode); dev->info.service_mode = 0x00; } if ((dev->info.scan_wait_mode = get_scan_wait_mode (fd)) != 0x00 && dev->info.scan_wait_mode != 0x01) { DBG (DBG_error, ">>> attach: get_scan_wait_mode failed: return value=%#02x\n", dev->info.scan_wait_mode); dev->info.scan_wait_mode = 0x00; } status = get_white_balance (fd, &dev->info.white_balance); if (status != SANE_STATUS_GOOD && dev->info.white_balance != 0x01) { DBG (DBG_error, ">>> attach: get_white_balance failed: return value=%#02x\n", dev->info.white_balance); dev->info.white_balance = RELATIVE_WHITE; } DBG (DBG_info, ">>> attach: flushing and closing fd=%d\n", fd); sanei_scsi_req_flush_all (); sanei_scsi_close (fd); dev->info.devtype = ibuf.devtype; snprintf (dev->info.vendor, 9, "%-.5s", ibuf.vendor); /* RICOH */ trim_spaces (dev->info.vendor, sizeof (dev->info.vendor)); snprintf (dev->info.product, 16, "%-.16s", ibuf.product); /* IS450 */ trim_spaces (dev->info.product, sizeof (dev->info.product)); snprintf (dev->info.revision, 5, "%-.4s", ibuf.revision); /* 1R04 */ trim_spaces (dev->info.revision, sizeof (dev->info.revision)); /* SANE_Device sane information */ dev->sane.name = strdup (devname); dev->sane.vendor = (strcmp (dev->info.vendor, "RICOH") == 0) ? strdup ("Ricoh") : strdup (dev->info.vendor); dev->sane.model = strdup (dev->info.product); dev->sane.type = strdup ("sheetfed scanner"); /* dev->sane.email_backend_author = strdup(" jeremy@acjlaw.net"); dev->sane.backend_website = strdup("http://www.acjlaw.net:8080/~jeremy/Ricoh"); */ /* read these values from backend configuration file using parse_configuration dev->sane.location = strdup(); dev->sane.comment = strdup(); dev->sane.backend_version_code = strdup(); */ /* NOT YET USED */ /* dev->sane.backend_capablity_flags = 0x00; */ /* set capabilities from vpd */ /* adf_id: 0=none,1=simplex,2=duplex,3=ARDF,4=reserved; should be 1 or 2 for IS450 family */ dev->info.hasADF = vbuf.adf_id == 0 ? SANE_FALSE : SANE_TRUE; dev->info.hasSimplex = vbuf.adf_id == 1 ? SANE_TRUE : SANE_FALSE; dev->info.hasDuplex = vbuf.adf_id == 2 ? SANE_TRUE : SANE_FALSE; dev->info.hasARDF = vbuf.adf_id == 3 ? SANE_TRUE : SANE_FALSE; /* end_id 0=none,1=Yes,2=reserved; should always be 0 or 1 */ dev->info.hasEndorser = vbuf.end_id == 1 ? SANE_TRUE : SANE_FALSE; for (i = 0; i < 20; i++) dev->info.endorser_string[i] = '\0'; /* ipu_id: Bit0: '0'-no IPU, '1'-has IPU * Bit1: '0'-no extended board, '1'-has extended board; * should always be 0 */ dev->info.hasIPU = (vbuf.ipu_id & 0x01) == 0x01 ? SANE_TRUE : SANE_FALSE; dev->info.hasXBD = (vbuf.ipu_id & 0x02) == 0x02 ? SANE_TRUE : SANE_FALSE; /* Image Composition Byte is set to 0x37 (0011 0111) */ dev->info.supports_lineart = (vbuf.imagecomposition & 0x01) == 0x01 ? SANE_TRUE : SANE_FALSE; /* TRUE */ dev->info.supports_dithering = (vbuf.imagecomposition & 0x02) == 0x02 ? SANE_TRUE : SANE_FALSE; /* TRUE */ dev->info.supports_errordiffusion = (vbuf.imagecomposition & 0x04) == 0x04 ? SANE_TRUE : SANE_FALSE; /* TRUE */ dev->info.supports_color = (vbuf.imagecomposition & 0x08) == 0x08 ? SANE_TRUE : SANE_FALSE; /* FALSE */ dev->info.supports_4bitgray = (vbuf.imagecomposition & 0x10) == 0x10 ? SANE_TRUE : SANE_FALSE; /* TRUE */ dev->info.supports_8bitgray = (vbuf.imagecomposition & 0x20) == 0x20 ? SANE_TRUE : SANE_FALSE; /* TRUE */ /* vbuf.imagecomposition & 0x40; FALSE */ /* vbuf.imagecomposition & 0x80 FALSE reserved */ str = &scan_mode_list[0]; /* array of string pointers */ if (dev->info.supports_lineart) *str++ = strdup (SM_LINEART); if (dev->info.supports_dithering || dev->info.supports_errordiffusion) *str++ = strdup (SM_HALFTONE); if (dev->info.supports_color) *str++ = strdup (SM_COLOR); if (dev->info.supports_4bitgray) *str++ = strdup (SM_4BITGRAY); if (dev->info.supports_8bitgray) *str++ = strdup (SM_8BITGRAY); *str = NULL; snprintf (device_string, 60, "Flatbed%s%s%s%s%s%s", dev->info.hasADF ? "/ADF" : "", dev->info.hasDuplex ? "/Duplex" : "", dev->info.hasEndorser ? "/Endorser" : "", dev->info.hasIPU ? "/IPU" : "", dev->info.supports_color ? " Color" : " B&W", " Scanner"); dev->sane.type = strdup (device_string); /* ACE Image Data Processing Binary Filters * For IS450 this is set to 0x18 (0001 1000) if IPU installed, else 0x00 * For IS420 this is set to 0x3C (0011 1100) if IPU installed, else 0x00 */ dev->info.supports_whiteframing = ((vbuf.imagedataprocessing[0] & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE; dev->info.supports_blackframing = ((vbuf.imagedataprocessing[0] & 0x02) == 0x02) ? SANE_TRUE : SANE_FALSE; dev->info.supports_edgeextraction = ((vbuf.imagedataprocessing[0] & 0x04) == 0x04) ? SANE_TRUE : SANE_FALSE; dev->info.supports_noiseremoval = ((vbuf.imagedataprocessing[0] & 0x08) == 0x08) ? SANE_TRUE : SANE_FALSE; dev->info.supports_smoothing = ((vbuf.imagedataprocessing[0] & 0x10) == 0x10) ? SANE_TRUE : SANE_FALSE; dev->info.supports_linebolding = ((vbuf.imagedataprocessing[0] & 0x20) == 0x20) ? SANE_TRUE : SANE_FALSE; /* Compression Method is not supported for IS450 * is supported for IS420 */ dev->info.supports_MH = ((vbuf.compression & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE; dev->info.supports_MR = ((vbuf.compression & 0x02) == 0x02) ? SANE_TRUE : SANE_FALSE; dev->info.supports_MMR = ((vbuf.compression & 0x04) == 0x04) ? SANE_TRUE : SANE_FALSE; dev->info.supports_MHB = ((vbuf.compression & 0x08) == 0x08) ? SANE_TRUE : SANE_FALSE; /* MH Byte Boundary */ /* compression_list[] will have variable number of elements, but the order will be fixed as follows: */ str = &compression_list[0]; *str++ = strdup ("none"); if (dev->info.supports_MH) *str++ = strdup ("G3 1-D MH"); if (dev->info.supports_MR) *str++ = strdup ("G3 2-D MR"); if (dev->info.supports_MMR) *str++ = strdup ("G4 2-D MMR"); if (dev->info.supports_MHB) *str++ = strdup ("MH Byte Boundary"); *str = NULL; /* Marker Recognition is set to 0x00 */ dev->info.supports_markerrecognition = ((vbuf.markerrecognition & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE; /* Size Recognition * For IS450 this is set to 0x01 when IPU installed; else 0x00 * For IS420 this is set to 0x01 */ dev->info.supports_sizerecognition = ((vbuf.sizerecognition & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE; /* X Maximum Output Pixel in main scanning direction * For IS450 this is set to 0x1360 (4960) * For IS420 this is set to (4880) * [MostSignificantByte LeastSignificantByte] */ dev->info.xmaxoutputpixels = (vbuf.xmaxoutputpixels[0] << 8) | vbuf.xmaxoutputpixels[1]; /* Set capabilities from jis VPD IDENTIFIER Page Code F0H */ dev->info.resBasicX = _2btol (&jbuf.BasicRes.x[0]); /* set to 400 */ dev->info.resBasicY = _2btol (&jbuf.BasicRes.y[0]); /* set to 400 */ dev->info.resXstep = (jbuf.resolutionstep >> 4) & 0x0F; /* set to 1 */ dev->info.resYstep = jbuf.resolutionstep & 0x0F; /* set to 1 */ dev->info.resMaxX = _2btol (&jbuf.MaxRes.x[0]); /* set to 800 */ dev->info.resMaxY = _2btol (&jbuf.MaxRes.y[0]); /* set to 800 */ dev->info.resMinX = _2btol (&jbuf.MinRes.x[0]); /* set to 100 for IS450 and 60 for IS420 */ dev->info.resMinY = _2btol (&jbuf.MinRes.y[0]); /* set to 100 for IS450 and 60 for IS420 */ dev->info.xres_range.min = _2btol (&jbuf.MinRes.x[0]); /* set to 100 for IS450 and 60 for IS420 */ dev->info.xres_range.max = _2btol (&jbuf.MaxRes.x[0]); /* set to 800 */ dev->info.resXstep = (jbuf.resolutionstep >> 4) & 0x0F; /* set to 1 */ dev->info.xres_range.quant = dev->info.resXstep; dev->info.yres_range.min = _2btol (&jbuf.MinRes.y[0]); /* set to 100 for IS450 and 60 for IS420 */ dev->info.yres_range.max = _2btol (&jbuf.MaxRes.y[0]); /* set to 800 */ dev->info.resYstep = jbuf.resolutionstep & 0x0F; /* set to 1 */ dev->info.yres_range.quant = dev->info.resYstep; /* set the length of the list to zero first, then append standard resolutions */ i = 0; if ((jbuf.standardres[0] & 0x80) == 0x80) dev->info.resStdList[++i] = 60; if ((jbuf.standardres[0] & 0x40) == 0x40) dev->info.resStdList[++i] = 75; if ((jbuf.standardres[0] & 0x20) == 0x20) dev->info.resStdList[++i] = 100; if ((jbuf.standardres[0] & 0x10) == 0x10) dev->info.resStdList[++i] = 120; if ((jbuf.standardres[0] & 0x08) == 0x08) dev->info.resStdList[++i] = 150; if ((jbuf.standardres[0] & 0x04) == 0x04) dev->info.resStdList[++i] = 160; if ((jbuf.standardres[0] & 0x02) == 0x02) dev->info.resStdList[++i] = 180; if ((jbuf.standardres[0] & 0x01) == 0x01) dev->info.resStdList[++i] = 200; if ((jbuf.standardres[1] & 0x80) == 0x80) dev->info.resStdList[++i] = 240; if ((jbuf.standardres[1] & 0x40) == 0x40) dev->info.resStdList[++i] = 300; if ((jbuf.standardres[1] & 0x20) == 0x20) dev->info.resStdList[++i] = 320; if ((jbuf.standardres[1] & 0x10) == 0x10) dev->info.resStdList[++i] = 400; if ((jbuf.standardres[1] & 0x08) == 0x08) dev->info.resStdList[++i] = 480; if ((jbuf.standardres[1] & 0x04) == 0x04) dev->info.resStdList[++i] = 600; if ((jbuf.standardres[1] & 0x02) == 0x02) dev->info.resStdList[++i] = 800; if ((jbuf.standardres[1] & 0x01) == 0x01) dev->info.resStdList[++i] = 1200; dev->info.resStdList[0] = i; /* number of resolutions */ if (dev->info.resStdList[0] == 0) { /* make a default standard resolutions for 200 and 300dpi */ DBG (DBG_warning, "attach: no standard resolutions reported\n"); dev->info.resStdList[0] = 2; dev->info.resStdList[1] = 200; dev->info.resStdList[2] = 300; dev->info.resBasicX = dev->info.resBasicY = 300; } DBG (DBG_info, "attach: Window(W/L) = (%lu/%lu)\n", _4btol (&jbuf.Window.width[0]), _4btol (&jbuf.Window.length[0])); dev->info.winWidth = _4btol (&jbuf.Window.width[0]); dev->info.winHeight = _4btol (&jbuf.Window.length[0]); if (dev->info.winWidth <= 0) { dev->info.winWidth = (SANE_Int) (dev->info.resBasicX * 8.5); DBG (DBG_warning, "attach: invalid window width reported, using %d\n", dev->info.winWidth); } if (dev->info.winHeight <= 0) { dev->info.winHeight = dev->info.resBasicY * 14; DBG (DBG_warning, "attach: invalid window height reported, using %d\n", dev->info.winHeight); } /* 4692 / 400 * 25.4 = 297 */ mm = (dev->info.resBasicX > 0) ? ((double) dev->info.winWidth / (double) dev->info.resBasicX * MM_PER_INCH) : 0.0; dev->info.x_range.min = SANE_FIX (0.0); dev->info.x_range.max = SANE_FIX (mm); dev->info.x_range.quant = SANE_FIX (0.0); DBG (DBG_info, "attach: winWidth=%d resBasicX=%d mm/in=%f mm=%f\n", dev->info.winWidth, dev->info.resBasicX, MM_PER_INCH, mm); mm = (dev->info.resBasicY > 0) ? ((double) dev->info.winHeight / (double) dev->info.resBasicY * MM_PER_INCH) : 0.0; dev->info.y_range.min = SANE_FIX (0.0); dev->info.y_range.max = SANE_FIX (mm); dev->info.y_range.quant = SANE_FIX (0.0); DBG (DBG_info, "attach: RANGE x_range.max=%f, y_range.max=%f\n", SANE_UNFIX (dev->info.x_range.max), SANE_UNFIX (dev->info.y_range.max)); /* min, max, quantization light-dark 1-255, 0 means default 128 */ dev->info.brightness_range.min = 1; dev->info.brightness_range.max = 255; dev->info.brightness_range.quant = 1; /* min, max, quantization white-black 1-255, 0 means default 128 */ dev->info.contrast_range.min = 1; dev->info.contrast_range.max = 255; dev->info.contrast_range.quant = 1; /* min, max, quantization low-high 1-255, 0 means default 128 */ dev->info.threshold_range.min = 1; dev->info.threshold_range.max = 255; dev->info.threshold_range.quant = 1; /* jbuf.functions */ dev->info.overflow_support = ((jbuf.functions & 0x01) == 0x01) ? SANE_TRUE : SANE_FALSE; dev->info.lineart_support = ((jbuf.functions & 0x02) == 0x02) ? SANE_TRUE : SANE_FALSE; dev->info.dither_support = ((jbuf.functions & 0x04) == 0x04) ? SANE_TRUE : SANE_FALSE; dev->info.grayscale_support = ((jbuf.functions & 0x08) == 0x08) ? SANE_TRUE : SANE_FALSE; /* set option defaults */ dev->info.default_res = dev->info.resBasicX; dev->info.default_xres = dev->info.resBasicX; dev->info.default_yres = dev->info.resBasicY; dev->info.default_imagecomposition = LINEART; dev->info.default_media = FLATBED; dev->info.default_duplex = SANE_FALSE; /* dev->info.autoborder_default = dev->info.canBorderRecog; */ /* dev->info.batch_default = SANE_FALSE; dev->info.deskew_default = SANE_FALSE; dev->info.check_adf_default = SANE_FALSE; dev->info.timeout_adf_default = 0; dev->info.timeout_manual_default = 0; */ /* dev->info.control_panel_default = dev->info.canACE; Image Data Processing */ ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (DBG_sane_proc, "<<< attach:\n"); return SANE_STATUS_GOOD; } /* SANE callback to attach a SCSI device */ static SANE_Status attach_one_scsi (const char *devname) { return attach (devname, CONNECTION_SCSI, NULL); /* return SANE_STATUS_GOOD; */ } static void parse_configuration_file (FILE * fp) { char line[PATH_MAX], *s, *t; int linenumber; DBG (DBG_proc, ">> parse_configuration_file\n"); if (fp == NULL) { DBG (DBG_proc, ">> parse_configuration_file: No config file present!\n"); } else { /*parse configuration file */ for (linenumber = 0; sanei_config_read (line, sizeof (line), fp); linenumber++) { DBG (DBG_proc, ">> parse_configuration_file: parsing config line \"%s\"\n", line); if (line[0] == '#') continue; /* ignore line comments */ for (s = line; isspace (*s); ++s); /* skip white space: */ for (t = s; *t != '\0'; t++); for (--t; t > s && isspace (*t); t--); *(++t) = '\0'; /*trim trailing space */ if (!strlen (s)) continue; /* ignore empty lines */ if ((t = strstr (s, "scsi ")) != NULL) { /* scsi VENDOR MODEL TYPE BUS CHANNEL ID LUN */ DBG (DBG_proc, ">> parse_configuration_file: config file line %d: trying to attach SCSI: %s'\n", linenumber, line); sanei_config_attach_matching_devices (t, attach_one_scsi); } else if ((t = strstr (s, "/dev/")) != NULL) { /* /dev/scanner /dev/sg0 */ DBG (DBG_proc, ">> parse_configuration_file: config file line %d: trying to attach SCSI: %s'\n", linenumber, line); sanei_config_attach_matching_devices (t, attach_one_scsi); } else if ((t = strstr (s, "option")) != NULL) { for (t += 6; isspace (*t); t++); /* skip to flag */ /* if(strstr(t,"FLAG_VALUE")!=NULL) FLAG_VALUE=SANE_TRUE; */ } else { DBG (DBG_proc, ">> parse_configuration_file: config file line %d: OBSOLETE !! use the scsi keyword!\n", linenumber); DBG (DBG_proc, ">> parse_configuration_file: (see man sane-avision for details): trying to attach SCSI: %s'\n", line); } } fclose (fp); } DBG (DBG_proc, "<< parse_configuration_file\n"); return; } static SANE_Status do_cancel (HS2P_Scanner * s) { SANE_Status status; DBG (DBG_sane_proc, ">> do_cancel\n"); DBG (DBG_proc, "cancel: sending OBJECT POSITION\n"); s->scanning = SANE_FALSE; s->cancelled = SANE_TRUE; s->EOM = SANE_FALSE; if (s->fd >= 0) { if ((status = object_position (s->fd, OBJECT_POSITION_UNLOAD)) != SANE_STATUS_GOOD) { DBG (DBG_error, "cancel: OBJECT POSTITION failed\n"); } sanei_scsi_req_flush_all (); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; } /* if (s->reader_pid > 0){ int exit_status; sanei_thread_kill (s->reader_pid); sanei_thread_waitpid (s->reader_pid, &exit_status); s->reader_pid = 0; } */ DBG (DBG_sane_proc, "<< do_cancel\n"); return (SANE_STATUS_CANCELLED); } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; DBG_INIT (); /* initialize SANE DEBUG */ /*DBG (DBG_sane_init, "> sane_init (authorize = %p)\n", (void *) authorize); */ #if defined PACKAGE && defined VERSION DBG (DBG_sane_init, "> sane_init: hs2p backend version %d.%d-%d (" PACKAGE " " VERSION ")\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); #endif /* sanei_thread_init (); */ if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); if ((fp = sanei_config_open (HS2P_CONFIG_FILE)) != NULL) { parse_configuration_file (fp); } else { DBG (DBG_sane_init, "> sane_init: No config file \"%s\" present!\n", HS2P_CONFIG_FILE); } #if 0 /* avision.c: search for all supported scanners on all scsi busses & channels */ for (hw = &HS2P_Device_List[0]; hw->mfg != NULL; hw++) { sanei_scsi_find_devices (hw->mfg, /*vendor */ hw->model, /*model */ NULL, /*all types */ -1, /*all bus */ -1, /*all channel */ -1, /*all id */ -1, /*all lun */ attach_one_scsi); /*callback */ DBG (2, "sane_init: %s %s\n", hw->mfg, hw->model); } #endif DBG (DBG_sane_init, "< sane_init\n"); return SANE_STATUS_GOOD; } void sane_exit (void) { HS2P_Device *dev, *next; DBG (DBG_proc, ">> sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) (SANE_String_Const *) dev->sane.name); free ((SANE_String_Const *) dev->sane.model); free (dev); } DBG (DBG_proc, "<< sane_exit\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { static const SANE_Device **devlist = 0; HS2P_Device *dev; int i; DBG (DBG_proc, ">> sane_get_devices (local_only = %d)\n", local_only); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return (SANE_STATUS_NO_MEM); i = 0; for (dev = first_dev; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (DBG_proc, "<< sane_get_devices\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devnam, SANE_Handle * handle) { SANE_Status status; HS2P_Device *dev; HS2P_Scanner *s; DBG (DBG_proc, "> sane_open\n"); if (devnam[0] == '\0') { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) break; } if (!dev) { status = attach (devnam, CONNECTION_SCSI, &dev); if (status != SANE_STATUS_GOOD) return (status); } } else { dev = first_dev; } if (!dev) return (SANE_STATUS_INVAL); s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); /* initialize */ s->fd = -1; s->hw = dev; s->hw->info.bmu = s->bmu = MILLIMETERS; /* 01H */ s->hw->info.mud = s->mud = 1; /* If the scale is MM or POINT, mud is fixed to 1 */ s->bpp = 1; /* supports 1,4,6,8 so we set to LINEART 1bpp */ /* s->scanning = SANE_FALSE; s->cancelled = SANE_FALSE; */ /* */ ScannerDump (s); init_options (s); s->next = first_handle; /* insert newly opened handle into list of open handles: */ first_handle = s; /* initialize our parameters here AND in sane_start? get_parameters(s, 0); */ *handle = s; DBG (DBG_proc, "< sane_open\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { HS2P_Scanner *s = (HS2P_Scanner *) handle; char **str; DBG (DBG_proc, ">> sane_close\n"); if (s->fd != -1) sanei_scsi_close (s->fd); free (s); for (str = &compression_list[0]; *str; str++); free (*str); for (str = &scan_mode_list[0]; *str; str++); free (*str); DBG (DBG_proc, "<< sane_close\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { HS2P_Scanner *s = handle; DBG (DBG_proc, ">> sane_get_option_descriptor: %d name=%s\n", option, s->opt[option].name); if ((unsigned) option >= NUM_OPTIONS) return (0); DBG (DBG_info, "<< sane_get_option_descriptor: name=%s\n", s->opt[option].name); return (s->opt + option); } #if 0 static SANE_Int get_scan_mode_id (char *s) /* sequential search */ { SANE_Int i; for (i = 0; scan_mode_list[i]; i++) if (strcmp (s, scan_mode_list[i]) == 0) break; /* unknown strings are treated as 'lineart' */ return scan_mode_list[i] ? i : 0; } #endif static SANE_Status update_hs2p_data (HS2P_Scanner * s) { DBG (DBG_proc, ">> update_hs2p_data\n"); /* OPT_NREGX_ADF: */ DBG (DBG_sane_option, "OPT_NREGX_ADF\n"); s->val[OPT_NREGX_ADF].w = (SANE_Word) s->data.maintenance.nregx_adf; /* OPT_NREGY_ADF: */ DBG (DBG_sane_option, "OPT_NREGY_ADF\n"); s->val[OPT_NREGY_ADF].w = (SANE_Word) s->data.maintenance.nregx_book; /* OPT_NREGX_BOOK: */ DBG (DBG_sane_option, "OPT_NREGX_BOOK\n"); s->val[OPT_NREGX_BOOK].w = (SANE_Word) s->data.maintenance.nregx_book; /* OPT_NREGY_BOOK: */ DBG (DBG_sane_option, "OPT_NREGY_BOOK\n"); s->val[OPT_NREGY_BOOK].w = (SANE_Word) s->data.maintenance.nregy_book; /* OPT_NSCANS_ADF: */ DBG (DBG_sane_option, "OPT_NSCANS_ADF\n"); s->val[OPT_NSCANS_ADF].w = (SANE_Word) _4btol (&(s->data.maintenance.nscans_adf[0])); /* OPT_NSCANS_BOOK: */ DBG (DBG_sane_option, "OPT_NSCANS_BOOK\n"); s->val[OPT_NSCANS_BOOK].w = (SANE_Word) _4btol (&(s->data.maintenance.nscans_book[0])); /* OPT_LAMP_TIME: */ DBG (DBG_sane_option, "OPT_LAMP_TIME\n"); s->val[OPT_LAMP_TIME].w = (SANE_Word) _4btol (&(s->data.maintenance.lamp_time[0])); /* OPT_EO_ODD: */ DBG (DBG_sane_option, "OPT_EO_ODD\n"); s->val[OPT_EO_ODD].w = (SANE_Word) s->data.maintenance.eo_odd; /* OPT_EO_EVEN: */ DBG (DBG_sane_option, "OPT_EO_EVEN\n"); s->val[OPT_EO_EVEN].w = (SANE_Word) s->data.maintenance.eo_even; /* OPT_BLACK_LEVEL_ODD: */ DBG (DBG_sane_option, "OPT_BLACK_LEVEL_ODD\n"); s->val[OPT_BLACK_LEVEL_ODD].w = (SANE_Word) s->data.maintenance.black_level_odd; /* OPT_BLACK_LEVEL_EVEN: */ DBG (DBG_sane_option, "OPT_BLACK_LEVEL_EVEN\n"); s->val[OPT_BLACK_LEVEL_EVEN].w = (SANE_Word) s->data.maintenance.black_level_even; /* OPT_WHITE_LEVEL_ODD: */ DBG (DBG_sane_option, "OPT_WHITE_LEVEL_ODD\n"); s->val[OPT_WHITE_LEVEL_ODD].w = (SANE_Word) _2btol (&(s->data.maintenance.white_level_odd[0])); /* OPT_WHITE_LEVEL_EVEN: */ DBG (DBG_sane_option, "OPT_WHITE_LEVEL_EVEN\n"); s->val[OPT_WHITE_LEVEL_EVEN].w = (SANE_Word) _2btol (&(s->data.maintenance.white_level_even[0])); /* OPT_FIRST_ADJ_WHITE_ODD: */ DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_ODD\n"); s->val[OPT_FIRST_ADJ_WHITE_ODD].w = (SANE_Word) _2btol (&(s->data.maintenance.first_adj_white_odd[0])); /* OPT_FIRST_ADJ_WHITE_EVEN: */ DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_EVEN\n"); s->val[OPT_FIRST_ADJ_WHITE_EVEN].w = (SANE_Word) _2btol (&(s->data.maintenance.first_adj_white_even[0])); /* OPT_DENSITY: */ DBG (DBG_sane_option, "OPT_DENSITY\n"); s->val[OPT_DENSITY].w = (SANE_Word) s->data.maintenance.density_adj; /* OPT_NREGX_REVERSE: */ DBG (DBG_sane_option, "OPT_NREGX_REVERSE\n"); s->val[OPT_NREGX_REVERSE].w = (SANE_Word) s->data.maintenance.nregx_reverse; /* OPT_NREGY_REVERSE: */ DBG (DBG_sane_option, "OPT_NREGY_REVERSE\n"); s->val[OPT_NREGY_REVERSE].w = (SANE_Word) s->data.maintenance.nregy_reverse; /* OPT_NSCANS_REVERSE_ADF: */ DBG (DBG_sane_option, "OPT_NSCANS_REVERSE_ADF\n"); s->val[OPT_NSCANS_REVERSE_ADF].w = (SANE_Word) _4btol (&(s->data.maintenance.nscans_reverse_adf[0])); /* OPT_REVERSE_TIME: */ DBG (DBG_sane_option, "OPT_REVERSE_TIME\n"); s->val[OPT_REVERSE_TIME].w = (SANE_Word) _4btol (&(s->data.maintenance.reverse_time[0])); /* OPT_NCHARS: */ DBG (DBG_sane_option, "OPT_NCHARS\n"); s->val[OPT_NCHARS].w = (SANE_Word) _4btol (&(s->data.maintenance.nchars[0])); DBG (DBG_proc, "<< update_hs2p_data\n"); return SANE_STATUS_GOOD; } static SANE_Status hs2p_open (HS2P_Scanner * s) { SANE_Status status; DBG (DBG_proc, ">> hs2p_open\n"); DBG (DBG_info, ">> hs2p_open: trying to open: name=\"%s\" fd=%d\n", s->hw->sane.name, s->fd); if ((status = sanei_scsi_open (s->hw->sane.name, &s->fd, &sense_handler, &(s->hw->sense_data))) != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: open of %s failed: %d %s\n", s->hw->sane.name, status, sane_strstatus (status)); return (status); } DBG (DBG_info, ">>hs2p_open: OPENED \"%s\" fd=%d\n", s->hw->sane.name, s->fd); if ((status = test_unit_ready (s->fd)) != SANE_STATUS_GOOD) { DBG (DBG_error, "hs2p_open: test_unit_ready() failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return status; } DBG (DBG_proc, "<< hs2p_open\n"); return SANE_STATUS_GOOD; } static SANE_Status hs2p_close (HS2P_Scanner * s) { DBG (DBG_proc, ">> hs2p_close\n"); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; DBG (DBG_proc, "<< hs2p_close\n"); return SANE_STATUS_GOOD; } #include static SANE_Status get_hs2p_data (HS2P_Scanner * s, ...) { SANE_Status status; SANE_Byte *buf; size_t *len = &(s->data.bufsize); int dtc, fd = s->fd; u_long dtq = 0; /* two bytes */ va_list ap; DBG (DBG_proc, ">> get_hs2p_data\n"); if (fd < 0) { status = hs2p_open (s); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_hs2p_data: error opening scanner: %s\n", sane_strstatus (status)); return status; } } for (va_start (ap, s), dtc = va_arg (ap, int); dtc != DATA_TYPE_EOL; dtc = va_arg (ap, int)) { DBG (DBG_proc, ">> get_hs2p_data 0x%2.2x\n", (int) dtc); switch (dtc) { case DATA_TYPE_GAMMA: buf = &(s->data.gamma[0]); *len = sizeof (s->data.gamma); break; case DATA_TYPE_ENDORSER: buf = &(s->data.endorser[0]); *len = sizeof (s->data.endorser); break; case DATA_TYPE_SIZE: buf = &(s->data.size); *len = sizeof (s->data.size); break; case DATA_TYPE_PAGE_LEN: buf = s->data.nlines; *len = sizeof (s->data.nlines); break; case DATA_TYPE_MAINTENANCE: buf = (SANE_Byte *) & (s->data.maintenance); *len = sizeof (s->data.maintenance); break; case DATA_TYPE_ADF_STATUS: buf = &(s->data.adf_status); *len = sizeof (s->data.adf_status); break; case DATA_TYPE_IMAGE: case DATA_TYPE_HALFTONE: default: DBG (DBG_info, "Data Type Code %2.2x not handled.\n", dtc); return SANE_STATUS_INVAL; } DBG (DBG_info, "get_hs2p_data calling read_data for dtc=%2.2x and bufsize=%lu\n", (int) dtc, (u_long) * len); status = read_data (s->fd, buf, len, (SANE_Byte) dtc, dtq); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_scanner_data: ERROR %s\n", sane_strstatus (status)); } } va_end (ap); if (fd < 0) { /* need to return fd to original state */ status = hs2p_close (s); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "get_hs2p_data: error closing fd: %s\n", sane_strstatus (status)); } } DBG (DBG_proc, "<< get_hs2p_data: %d\n", status); return (status); } static SANE_Status print_maintenance_data (MAINTENANCE_DATA * d) { DBG (DBG_proc, ">> print_maintenance_data: \n"); DBG (DBG_LEVEL, "nregx_adf = %d\n", d->nregx_adf); DBG (DBG_LEVEL, "nregy_adf = %d\n", d->nregy_adf); DBG (DBG_LEVEL, "nregx_book = %d\n", d->nregx_book); DBG (DBG_LEVEL, "nregy_book = %d\n", d->nregy_book); DBG (DBG_LEVEL, "nscans_adf = %lu\n", _4btol (&(d->nscans_adf[0]))); DBG (DBG_LEVEL, "nscans_adf = %lu\n", _4btol (&(d->nscans_adf[0]))); DBG (DBG_LEVEL, "lamp time = %lu\n", _4btol (&(d->lamp_time[0]))); DBG (DBG_LEVEL, "eo_odd = %d\n", d->eo_odd); DBG (DBG_LEVEL, "eo_even = %d\n", d->eo_even); DBG (DBG_LEVEL, "black_level_odd = %d\n", d->black_level_odd); DBG (DBG_LEVEL, "black_level_even = %d\n", d->black_level_even); DBG (DBG_LEVEL, "white_level_odd = %lu\n", _2btol (&(d->white_level_odd[0]))); DBG (DBG_LEVEL, "white_level_even = %lu\n", _2btol (&(d->white_level_even[0]))); DBG (DBG_LEVEL, "first_adj_white_odd = %lu\n", _2btol (&(d->first_adj_white_odd[0]))); DBG (DBG_LEVEL, "first_adj_white_even = %lu\n", _2btol (&(d->first_adj_white_even[0]))); DBG (DBG_LEVEL, "density_adj = %d\n", d->density_adj); DBG (DBG_LEVEL, "nregx_reverse = %d\n", d->nregx_reverse); DBG (DBG_LEVEL, "nregy_reverse = %d\n", d->nregy_reverse); DBG (DBG_LEVEL, "nscans_reverse_adf = %lu\n", _4btol (&(d->nscans_reverse_adf[0]))); DBG (DBG_LEVEL, "reverse_time = %lu\n", _4btol (&(d->reverse_time[0]))); DBG (DBG_LEVEL, "nchars = %lu\n", _4btol (&(d->nchars[0]))); DBG (DBG_proc, "<< print_maintenance_data: \n"); return SANE_STATUS_GOOD; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { HS2P_Scanner *s = handle; SANE_Status status; SANE_Word cap; SANE_String_Const name; SANE_Int paper_id; name = s->opt[option].name ? s->opt[option].name : "(nil)"; if (info) *info = 0; DBG (DBG_proc, ">> sane_control_option: %s option=%d name=%s\n", action == SANE_ACTION_GET_VALUE ? "SET" : "GET", option, name); if (s->scanning) return (SANE_STATUS_DEVICE_BUSY); if (option >= NUM_OPTIONS) return (SANE_STATUS_INVAL); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return (SANE_STATUS_INVAL); if (action == SANE_ACTION_GET_VALUE) { DBG (DBG_proc, "sane_control_option get_value option=%d\n", option); switch (option) { /* word options: */ case OPT_RESOLUTION: case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_BRIGHTNESS: case OPT_THRESHOLD: case OPT_CONTRAST: case OPT_NUM_OPTS: *(SANE_Word *) val = s->val[option].w; return (SANE_STATUS_GOOD); /* bool options: */ /*case OPT_AUTOBORDER: case OPT_DESKEW: case OPT_CHECK_ADF: case OPT_BATCH: */ case OPT_PREVIEW: case OPT_SCAN_WAIT_MODE: case OPT_DUPLEX: case OPT_AUTO_SIZE: case OPT_NEGATIVE: case OPT_ENDORSER: case OPT_SMOOTHING: case OPT_WHITE_BALANCE: case OPT_PREFEED: case OPT_CUSTOM_GAMMA: case OPT_PADDING: *(SANE_Bool *) val = s->val[option].w; return (SANE_STATUS_GOOD); /* string options: */ /* case OPT_ADF: */ /* case OPT_BITORDER: */ /* case OPT_ROTATION */ /* case OPT_SECTION: */ case OPT_INQUIRY: case OPT_SCAN_SOURCE: case OPT_PAGE_ORIENTATION: case OPT_PAPER_SIZE: case OPT_SCAN_MODE: case OPT_ENDORSER_STRING: case OPT_COMPRESSION: case OPT_NOISEREMOVAL: case OPT_GRAYFILTER: case OPT_HALFTONE_CODE: case OPT_HALFTONE_PATTERN: case OPT_GAMMA: case OPT_AUTOSEP: case OPT_AUTOBIN: case OPT_PADDING_TYPE: DBG (DBG_proc, "STRING=%s\n", s->val[option].s); strcpy (val, s->val[option].s); return (SANE_STATUS_GOOD); DBG (DBG_proc, "sizeof(val)=%lu sizeof(s)=%lu\n", (u_long) sizeof (val), (u_long) sizeof (s->val[option].s)); return (SANE_STATUS_GOOD); /* gamma */ case OPT_GAMMA_VECTOR_GRAY: memcpy (val, s->val[option].wa, s->opt[option].size); return SANE_STATUS_GOOD; /* MAINTENANCE DATA */ case OPT_DATA_GROUP: case OPT_UPDATE: return SANE_STATUS_GOOD; case OPT_NREGX_ADF: DBG (DBG_sane_option, "OPT_NREGX_ADF\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_adf; return SANE_STATUS_GOOD; case OPT_NREGY_ADF: DBG (DBG_sane_option, "OPT_NREGY_ADF\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_book; return SANE_STATUS_GOOD; case OPT_NREGX_BOOK: DBG (DBG_sane_option, "OPT_NREGX_BOOK\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_book; return SANE_STATUS_GOOD; case OPT_NREGY_BOOK: DBG (DBG_sane_option, "OPT_NREGY_BOOK\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregy_book; return SANE_STATUS_GOOD; case OPT_NSCANS_ADF: DBG (DBG_sane_option, "OPT_NSCANS_ADF\n"); *(SANE_Word *) val = (SANE_Word) _4btol (&(s->data.maintenance.nscans_adf[0])); return SANE_STATUS_GOOD; case OPT_NSCANS_BOOK: DBG (DBG_sane_option, "OPT_NSCANS_BOOK\n"); *(SANE_Word *) val = (SANE_Word) _4btol (&(s->data.maintenance.nscans_book[0])); return SANE_STATUS_GOOD; case OPT_LAMP_TIME: DBG (DBG_sane_option, "OPT_LAMP_TIME\n"); *(SANE_Word *) val = (SANE_Word) _4btol (&(s->data.maintenance.lamp_time[0])); return SANE_STATUS_GOOD; case OPT_EO_ODD: DBG (DBG_sane_option, "OPT_EO_ODD\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.eo_odd; return SANE_STATUS_GOOD; case OPT_EO_EVEN: DBG (DBG_sane_option, "OPT_EO_EVEN\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.eo_even; return SANE_STATUS_GOOD; case OPT_BLACK_LEVEL_ODD: DBG (DBG_sane_option, "OPT_BLACK_LEVEL_ODD\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.black_level_odd; return SANE_STATUS_GOOD; case OPT_BLACK_LEVEL_EVEN: DBG (DBG_sane_option, "OPT_BLACK_LEVEL_EVEN\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.black_level_even; return SANE_STATUS_GOOD; case OPT_WHITE_LEVEL_ODD: DBG (DBG_sane_option, "OPT_WHITE_LEVEL_ODD\n"); *(SANE_Word *) val = (SANE_Word) _2btol (&(s->data.maintenance.white_level_odd[0])); return SANE_STATUS_GOOD; case OPT_WHITE_LEVEL_EVEN: DBG (DBG_sane_option, "OPT_WHITE_LEVEL_EVEN\n"); *(SANE_Word *) val = (SANE_Word) _2btol (&(s->data.maintenance.white_level_even[0])); return SANE_STATUS_GOOD; case OPT_FIRST_ADJ_WHITE_ODD: DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_ODD\n"); *(SANE_Word *) val = (SANE_Word) _2btol (&(s->data.maintenance.first_adj_white_odd[0])); return SANE_STATUS_GOOD; case OPT_FIRST_ADJ_WHITE_EVEN: DBG (DBG_sane_option, "OPT_FIRST_ADJ_WHITE_EVEN\n"); *(SANE_Word *) val = (SANE_Word) _2btol (&(s->data.maintenance.first_adj_white_even[0])); return SANE_STATUS_GOOD; case OPT_DENSITY: DBG (DBG_sane_option, "OPT_DENSITY\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.density_adj; return SANE_STATUS_GOOD; case OPT_NREGX_REVERSE: DBG (DBG_sane_option, "OPT_NREGX_REVERSE\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregx_reverse; return SANE_STATUS_GOOD; case OPT_NREGY_REVERSE: DBG (DBG_sane_option, "OPT_NREGY_REVERSE\n"); *(SANE_Word *) val = (SANE_Word) s->data.maintenance.nregy_reverse; return SANE_STATUS_GOOD; case OPT_NSCANS_REVERSE_ADF: DBG (DBG_sane_option, "OPT_NSCANS_REVERSE_ADF\n"); *(SANE_Word *) val = (SANE_Word) _4btol (&(s->data.maintenance.nscans_reverse_adf[0])); return SANE_STATUS_GOOD; case OPT_REVERSE_TIME: DBG (DBG_sane_option, "OPT_REVERSE_TIME\n"); *(SANE_Word *) val = (SANE_Word) _4btol (&(s->data.maintenance.reverse_time[0])); return SANE_STATUS_GOOD; case OPT_NCHARS: DBG (DBG_sane_option, "OPT_NCHARS\n"); *(SANE_Word *) val = (SANE_Word) _4btol (&(s->data.maintenance.nchars[0])); return (SANE_STATUS_GOOD); default: DBG (DBG_proc, "sane_control_option:invalid option number %d\n", option); return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { DBG (DBG_proc, "sane_control_option set_value\n"); switch (s->opt[option].type) { case SANE_TYPE_BOOL: case SANE_TYPE_INT: DBG (DBG_proc, "sane_control_option: set_value %s [#%d] to %d\n", name, option, *(SANE_Word *) val); break; case SANE_TYPE_FIXED: DBG (DBG_proc, "sane_control_option: set_value %s [#%d] to %f\n", name, option, SANE_UNFIX (*(SANE_Word *) val)); break; case SANE_TYPE_STRING: DBG (DBG_proc, "sane_control_option: set_value %s [#%d] to %s\n", name, option, (char *) val); break; case SANE_TYPE_BUTTON: DBG (DBG_proc, "sane_control_option: set_value %s [#%d]\n", name, option); update_hs2p_data (s); break; default: DBG (DBG_proc, "sane_control_option: set_value %s [#%d]\n", name, option); } if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); if ((status = sanei_constrain_value (s->opt + option, val, info)) != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->opt[OPT_AUTO_SIZE].cap |= SANE_CAP_INACTIVE; /* disable auto size */ /* make sure that paper-size is set to custom */ if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; s->val[option].w = *(SANE_Word *) val; /* resets the paper format to user defined */ if (strcmp (s->val[OPT_PAPER_SIZE].s, paper_list[0]) != 0) /* CUSTOM PAPER SIZE */ { if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (s->val[OPT_PAPER_SIZE].s) free (s->val[OPT_PAPER_SIZE].s); s->val[OPT_PAPER_SIZE].s = strdup (paper_list[0]); /* CUSTOM PAPER SIZE */ } /* fall through */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ /*case OPT_ACE_FUNCTION: case OPT_ACE_SENSITIVITY: */ case OPT_BRIGHTNESS: case OPT_THRESHOLD: case OPT_CONTRAST: case OPT_NUM_OPTS: s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); /* string options */ case OPT_NOISEREMOVAL: case OPT_AUTOSEP: case OPT_AUTOBIN: case OPT_COMPRESSION: case OPT_PADDING_TYPE: case OPT_GRAYFILTER: case OPT_HALFTONE_CODE: case OPT_HALFTONE_PATTERN: case OPT_ENDORSER_STRING: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return SANE_STATUS_GOOD; /* boolean options: */ case OPT_PREVIEW: case OPT_DUPLEX: case OPT_NEGATIVE: case OPT_SCAN_WAIT_MODE: case OPT_ENDORSER: case OPT_SMOOTHING: case OPT_WHITE_BALANCE: case OPT_PREFEED: case OPT_PADDING: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_GRAY: memcpy (s->val[option].wa, val, s->opt[option].size); return SANE_STATUS_GOOD; /* options with side effect */ case OPT_GAMMA: if (strcmp (s->val[option].s, (SANE_String) val)) { if (!strcmp ((SANE_String) val, "User")) { s->val[OPT_CUSTOM_GAMMA].b = SANE_TRUE; s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; /* Brightness and Contrast do not work when downloading Gamma Table */ s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; } else { s->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: s->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; if (s->val[OPT_CUSTOM_GAMMA].w) { s->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_RESOLUTION: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; s->val[option].w = *(SANE_Word *) val; s->val[OPT_X_RESOLUTION].w = *(SANE_Word *) val; s->val[OPT_Y_RESOLUTION].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_SCAN_SOURCE: /* a string option */ /* Since the scanner ejects the sheet in ADF mode * it is impossible to scan multiple sections in one document * In ADF mode, because of mechanical limitations: * the minimum document size is (x,y)=(69mm x 120mm) */ if (info && strcmp ((char *) s->val[option].s, (char *) val)) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (!strcmp ("ADF", (SANE_String) val)) { s->opt[OPT_ENDORSER].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_ENDORSER_STRING].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_PREFEED].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_DUPLEX].cap &= ~SANE_CAP_INACTIVE; /*s->opt[OPT_PADDING].cap &= ~SANE_CAP_INACTIVE; */ } else { /* Flatbed */ s->opt[OPT_ENDORSER].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ENDORSER_STRING].cap |= SANE_CAP_INACTIVE; s->opt[OPT_PREFEED].cap |= SANE_CAP_INACTIVE; s->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE; s->opt[OPT_PADDING].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; case OPT_SCAN_MODE: /* a string option */ /* scan mode != lineart disables compression, setting it to 'none' */ if (strcmp (s->val[option].s, (SANE_String) val)) { if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (!strcmp (SM_LINEART, (SANE_String) val)) { s->image_composition = LINEART; s->opt[OPT_COMPRESSION].cap &= ~SANE_CAP_INACTIVE; /* enable compression control */ s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; /* enable threshold control */ s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; /* disable brightness control */ s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; /* disable contrast control */ s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; /* disable gamma */ s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; /* disable gamma */ s->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; /* disable gamma */ s->opt[OPT_HALFTONE_CODE].cap |= SANE_CAP_INACTIVE; /* disable halftone code */ s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; /* disable halftone pattern */ } else { if (!strcmp (SM_HALFTONE, (SANE_String) val)) { s->image_composition = HALFTONE; s->opt[OPT_HALFTONE_CODE].cap &= ~SANE_CAP_INACTIVE; /* enable halftone code */ s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; /* enable halftone pattern */ } else if (!strcmp (SM_4BITGRAY, (SANE_String) val) || !strcmp (SM_6BITGRAY, (SANE_String) val) || !strcmp (SM_8BITGRAY, (SANE_String) val)) { s->image_composition = GRAYSCALE; s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; /* enable gamma */ s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; /* enable brightness */ s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; /* enable contrast */ s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* disable threshold */ s->opt[OPT_COMPRESSION].cap |= SANE_CAP_INACTIVE; /* disable compression */ s->opt[OPT_HALFTONE_CODE].cap |= SANE_CAP_INACTIVE; /* disable halftone code */ s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; /* disable halftone pattern */ if (s->val[OPT_COMPRESSION].s && get_compression_id (s->val[OPT_COMPRESSION].s) != 0) { free (s->val[OPT_COMPRESSION].s); s->val[OPT_COMPRESSION].s = strdup (compression_list[0]); } } } free (s->val[option].s); s->val[option].s = strdup (val); } return SANE_STATUS_GOOD; case OPT_PAGE_ORIENTATION: if (strcmp (s->val[option].s, (SANE_String) val)) { free (s->val[option].s); s->val[option].s = strdup (val); if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } /* set val to current selected paper size */ paper_id = get_paper_id ((SANE_String) s->val[OPT_PAPER_SIZE].s); goto paper_id; case OPT_PAPER_SIZE: /* a string option */ /* changes geometry options, therefore _RELOAD_PARAMS and _RELOAD_OPTIONS */ s->opt[OPT_AUTO_SIZE].cap |= SANE_CAP_INACTIVE; /* disable auto size */ if (strcmp (s->val[option].s, (SANE_String) val)) { paper_id = get_paper_id ((SANE_String) val); /* paper_id 0 is a special case (custom) that * disables the paper size control of geometry */ paper_id: if (paper_id != 0) { double x_max, y_max, x, y, temp; x_max = SANE_UNFIX (s->hw->info.x_range.max); y_max = SANE_UNFIX (s->hw->info.y_range.max); /* a dimension of 0.0 (or less) is replaced with the max value */ x = (paper_sizes[paper_id].width <= 0.0) ? x_max : paper_sizes[paper_id].width; y = (paper_sizes[paper_id].length <= 0.0) ? y_max : paper_sizes[paper_id].length; if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; if (!strcmp (s->val[OPT_PAGE_ORIENTATION].s, LANDSCAPE)) /* swap */ { temp = y_max; y_max = x_max; x_max = temp; temp = y; y = x; x = temp; } s->val[OPT_TL_X].w = SANE_FIX (0.0); s->val[OPT_TL_Y].w = SANE_FIX (0.0); s->val[OPT_BR_X].w = SANE_FIX (MIN (x, x_max)); s->val[OPT_BR_Y].w = SANE_FIX (MIN (y, y_max)); } free (s->val[option].s); s->val[option].s = strdup (val); } return SANE_STATUS_GOOD; case OPT_UPDATE: /* SANE_TYPE_BUTTON */ DBG (DBG_info, "OPT_UPDATE: ready to call get_hs2p_data: fd=%d\n", s->fd); get_hs2p_data (s, /* DATA_TYPE_GAMMA, */ /* DATA_TYPE_ENDORSER, */ /* DATA_TYPE_SIZE, */ /* DATA_TYPE_PAGE_LEN, */ DATA_TYPE_MAINTENANCE, /* DATA_TYPE_ADF_STATUS, */ /* DATA_TYPE_IMAGE, */ /* DATA_TYPE_HALFTONE, */ DATA_TYPE_EOL); /* va_list end */ update_hs2p_data (s); if (DBG_LEVEL >= DBG_info) print_maintenance_data (&(s->data.maintenance)); if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; } return (SANE_STATUS_GOOD); } DBG (DBG_proc, "<< sane_control_option\n"); return (SANE_STATUS_INVAL); } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { HS2P_Scanner *s = handle; DBG (DBG_proc, ">> sane_get_parameters\n"); if (!s->scanning) { int width, length, xres, yres; const char *mode; memset (&s->params, 0, sizeof (s->params)); /* CLEAR SANE_Parameters */ width = (int) (SANE_UNFIX (s->val[OPT_BR_X].w) - SANE_UNFIX (s->val[OPT_TL_X].w)); length = (int) (SANE_UNFIX (s->val[OPT_BR_Y].w) - SANE_UNFIX (s->val[OPT_TL_Y].w)); xres = s->val[OPT_X_RESOLUTION].w; yres = s->val[OPT_Y_RESOLUTION].w; DBG (DBG_proc, ">>sane_get_parameters: (W/L)=(%d/%d) (xres/yres)=(%d/%d) mud=%d\n", width, length, xres, yres, s->hw->info.mud); /* make best-effort guess at what parameters will look like once scanning starts. */ if (xres > 0 && yres > 0 && width > 0 && length > 0) { /* convert from mm to pixels */ s->params.pixels_per_line = width * xres / s->hw->info.mud / MM_PER_INCH; s->params.lines = length * yres / s->hw->info.mud / MM_PER_INCH; } mode = s->val[OPT_SCAN_MODE].s; if ((strcmp (mode, SM_LINEART) == 0) || (strcmp (mode, SM_HALFTONE)) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line / 8; /* if the scanner truncates to the byte boundary, so: chop! */ s->params.pixels_per_line = s->params.bytes_per_line * 8; s->params.depth = 1; } else /* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */ { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } s->params.last_frame = SANE_TRUE; } else DBG (DBG_proc, "sane_get_parameters: scanning, so can't get params\n"); if (params) *params = s->params; DBG (DBG_proc, "%d pixels per line, %d bytes per line, %d lines high, total %lu bytes, " "dpi=%ld\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, (long) SANE_UNFIX (s->val[OPT_Y_RESOLUTION].w)); DBG (DBG_proc, "<< sane_get_parameters\n"); return (SANE_STATUS_GOOD); } static SANE_Status set_window_data (HS2P_Scanner * s, SWD * wbuf) { struct hs2p_window_data *data; int i, nwin, id, xres, yres, xmax, ymax; long ulx, uly, width, length, number, bytes; double offset; DBG (DBG_proc, ">> set_window_data: sizeof(*wbuf)=%lu; window len=%lu\n", (u_long) sizeof (*wbuf), (u_long) sizeof (wbuf->data)); /* initialize our window buffer with zeros */ DBG (DBG_proc, ">> set_window_data: CLEARING wbuf\n"); memset (wbuf, 0, sizeof (*wbuf)); /* Header */ DBG (DBG_proc, ">> set_window_data: writing Window Descriptor Length =%lu\n", (u_long) sizeof (wbuf->data)); _lto2b (sizeof (wbuf->data), &wbuf->hdr.len[0]); /* X-Axis Resolution 100-800dpi in 1 dpi steps */ xres = s->val[OPT_X_RESOLUTION].w; if (xres < s->hw->info.resMinX || xres > s->hw->info.resMaxX) { DBG (DBG_error, "XRESOLUTION %d IS NOT WITHIN [%d, %d]\n", xres, s->hw->info.resMinX, s->hw->info.resMaxX); return (SANE_STATUS_INVAL); } /* Y-Axis Resolution 100-800dpi in 1 dpi steps */ yres = s->val[OPT_Y_RESOLUTION].w; if (yres < s->hw->info.resMinY || yres > s->hw->info.resMaxY) { DBG (DBG_error, "YRESOLUTION %d IS NOT WITHIN [%d, %d]\n", yres, s->hw->info.resMinY, s->hw->info.resMaxY); return (SANE_STATUS_INVAL); } ulx = (long) SANE_UNFIX (s->val[OPT_TL_X].w); uly = (long) SANE_UNFIX (s->val[OPT_TL_Y].w); DBG (DBG_info, "set_window_data: upperleft=(%ld,%ld)\n", ulx, uly); width = (long) SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); /* Window Width */ length = (long) SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); /* Window Length */ DBG (DBG_info, "set_window_data: WxL= %ld x %ld\n", width, length); /* NOTE: the width in inches converted to byte unit must be the following values or less * Binary: 620 bytes * 4-bits gray: 2480 bytes * 8-bits gray: 4960 bytes */ if (!strcmp (s->val[OPT_SCAN_MODE].s, SM_LINEART)) { bytes = (width / MM_PER_INCH) * (s->val[OPT_X_RESOLUTION].w / 8.0); if (bytes > 620) { DBG (DBG_error, "width in pixels too large: width=%ld x-resolution=%d bytes=%ld\n", width, s->val[OPT_X_RESOLUTION].w, bytes); return (SANE_STATUS_INVAL); } } else if (!strcmp (s->val[OPT_SCAN_MODE].s, SM_4BITGRAY)) { bytes = (width / MM_PER_INCH) * (s->val[OPT_X_RESOLUTION].w / 2.0); if (bytes > 2480) { DBG (DBG_error, "width in pixels too large: width=%ld x-resolution=%d bytes=%ld\n", width, s->val[OPT_X_RESOLUTION].w, bytes); return (SANE_STATUS_INVAL); } } else if (!strcmp (s->val[OPT_SCAN_MODE].s, SM_8BITGRAY)) { bytes = (width / MM_PER_INCH) * (s->val[OPT_X_RESOLUTION].w); if (bytes > 4960) { DBG (DBG_error, "width in pixels too large: width=%ld x-resolution=%d bytes=%ld\n", width, s->val[OPT_X_RESOLUTION].w, bytes); return (SANE_STATUS_INVAL); } } if (strcmp (s->val[OPT_SCAN_SOURCE].s, scan_source_list[ADF]) == 0) { offset = (SANE_UNFIX (s->hw->info.x_range.max) - width) / 2.0; DBG (DBG_info, "set_window_data: ADF origin offset=%f\n", offset); ulx += (long) offset; } if (strcmp (s->val[OPT_SCAN_SOURCE].s, scan_source_list[FB]) == 0) { /* FB */ xmax = 298; /*mm */ ymax = 432; } else { /* ADF */ xmax = 298; ymax = 2000; } /* Boundary Conditions when BMU = MM */ number = ulx + width; if (number <= 0 || number > xmax) { DBG (DBG_error, "NOT WITHIN BOUNDS: ulx=%ld width=%ld sum=%ld\n", ulx, width, number); return (SANE_STATUS_INVAL); } number = uly + length; if (number <= 0 || number > ymax) { DBG (DBG_error, "NOT WITHIN BOUNDS: uly=%ld length=%ld sum=%ld\n", uly, length, number); return (SANE_STATUS_INVAL); } /* For each window (up to 2 if we're duplexing) */ nwin = (s->val[OPT_DUPLEX].w == SANE_TRUE) ? 2 : 1; for (i = 0; i < nwin; i++) { data = &(wbuf->data[i]); data->window_id = i; data->auto_bit &= 0xFE; /* Auto bit set to 0 since auto function isn't supported */ _lto2b (xres, &data->xres[0]); /* Set X resolution */ _lto2b (yres, &data->yres[0]); /* Set Y resolution */ _lto4b (ulx, &data->ulx[0]); /* X-Axis Upper Left */ _lto4b (uly, &data->uly[0]); /* Y-Axis Upper Left */ _lto4b (width, &data->width[0]); /* Window Width */ _lto4b (length, &data->length[0]); /* Window Length */ data->brightness = s->val[OPT_BRIGHTNESS].w; /* black-white: 1-255; 0 is default 128 */ data->threshold = s->val[OPT_THRESHOLD].w; /* light-dark: 1-255; 0 is default 128 */ data->contrast = s->val[OPT_CONTRAST].w; /* low-high: 1-255: 0 is default 128 */ if (data->brightness == 128) data->brightness = 0; if (data->threshold == 128) data->threshold = 0; if (data->contrast == 128) data->contrast = 0; data->image_composition = s->image_composition; data->bpp = s->bpp = s->params.depth; /* Byte 27, 347 Halftone Code: if HALFTONE, then either DITHER or ERROR_DIFFUSION */ if (s->image_composition == HALFTONE) { /* Then let's use pattern selected by user */ data->halftone_code = (get_halftone_code_id (s->val[OPT_HALFTONE_CODE].s) == 0) ? DITHER : ERROR_DIFFUSION; data->halftone_id = get_halftone_pattern_val (s->val[OPT_HALFTONE_PATTERN].s); } else { data->halftone_code = DITHER; /* 00H reserved */ data->halftone_id = 0x01; /* 00H reserved */ } /* Byte 29, 349: RIF:reserved:padding type */ if (data->image_composition == LINEART || data->image_composition == HALFTONE) { if (s->val[OPT_NEGATIVE].w) data->byte29 |= (1 << 7); /* set bit 7 */ else data->byte29 &= ~(1 << 7); /* unset bit 7 */ } /* Padding Type */ data->byte29 |= (paddingtype[get_paddingtype_id (s->val[OPT_PADDING_TYPE].s)]. val & 0x07); /* Bit Ordering: * Manual Says DEFAULT: [1111 1111][1111 1000] * Bits15-8 reserved; * Bit7: '0'-Normal '1'-Mirroring * Bit6-4: Reserved * Bit3: '0'-arrangement from MSB in grayscale mode * '1'-arrangement from LSB in grayscale mode * 2: '0'-unpacked 4-bits grayscale [DEFAULT] * '1'-packed 4-bits grayscale * 1: '0'-output from LSB of each word [DEFAULT] * '1'-output from MSB of each word * 0: '0'-output from bit 0 of each byte [DEFAULT] * '1'-output from bit 7 of each byte */ _lto2b (0x007, &data->bit_ordering[0]); /* Set to Packed4bitGray, MSB, MSbit */ /* Compression Type and Argument NOT SUPPORTED in this scanner */ data->compression_type = 0x00; data->compression_arg = 0x02; /* Byte42: MRIF:Filtering:GammaID */ if (data->image_composition == GRAYSCALE) { if (s->val[OPT_NEGATIVE].w) data->byte42 &= ~(1 << 7); /* unset bit 7 */ else data->byte42 |= (1 << 7); /* set bit 7 */ data->byte42 |= (get_grayfilter_val (s->val[OPT_GRAYFILTER].s) & (7 << 4)); /* set bits 6-4 to GRAYFILTER */ } else { data->byte42 &= ~(1 << 7); /* unset bit 7 */ data->byte42 &= ~(7 << 4); /* unset bits 6-4 */ } /* Bytes 45, 365 Binary Filtering for lineart and halftone can be set when option IPU is installed */ if ((id = get_noisematrix_id (s->val[OPT_NOISEREMOVAL].s)) != 0) { data->binary_filtering |= (1 << 7); /* set bit 7 */ data->binary_filtering |= noisematrix[id].val; /* 00H, 01H, 02H; 03H:Reserved */ } if (s->val[OPT_SMOOTHING].w == SANE_TRUE) data->binary_filtering |= (1 << 6); /* set bit 6 */ /* Automatic separation, automatic binarization, and SECTION is available if Image Processing Unit is installed */ if (s->hw->info.hasIPU) { /* Byte 48: Automatic Separation */ data->automatic_separation = get_auto_separation_val (s->val[OPT_AUTOSEP].s); /* Byte 50: Automatic Binarization */ data->automatic_binarization = get_auto_binarization_val (s->val[OPT_AUTOBIN].s); /* fill in values for each section for(j=0; j> sane_start\n"); s->cancelled = SANE_FALSE; if (s->another_side) { /* Number of bytes to read for one side of sheet */ s->bytes_to_read = s->params.bytes_per_line * s->params.lines; DBG (DBG_info, "SIDE#2 %d pixels per line, %d bytes, %d lines high, dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (int) s->val[OPT_Y_RESOLUTION].w); s->scanning = SANE_TRUE; s->cancelled = SANE_FALSE; s->another_side = SANE_FALSE; /* This is side 2, so no more sides */ DBG (DBG_proc, "<< sane_start\n"); return (SANE_STATUS_GOOD); } if (s->scanning) { DBG (DBG_info, "sane_start: device busy\n"); return SANE_STATUS_DEVICE_BUSY; } /* Let's start a new scan */ if ((status = sane_get_parameters (s, 0)) != SANE_STATUS_GOOD) { /* get preliminary parameters */ DBG (DBG_error, "sane_start: sane_get_parameters failed: %s\n", sane_strstatus (status)); return (status); } DBG (DBG_info, ">> sane_start: trying to open: name=\"%s\" fd=%d\n", s->hw->sane.name, s->fd); if ((status = sanei_scsi_open (s->hw->sane.name, &s->fd, &sense_handler, &(s->hw->sense_data))) != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: open of %s failed: %d %s\n", s->hw->sane.name, status, sane_strstatus (status)); return (status); } DBG (DBG_info, ">>sane_start: OPENED \"%s\" fd=%d\n", s->hw->sane.name, s->fd); if ((status = test_unit_ready (s->fd)) != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: test_unit_ready() failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return status; } if ((status = reserve_unit (s->fd)) != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: reserve_unit() failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } /* NOW SET UP SCANNER ONCE PER BATCH */ DBG (DBG_info, "sane_start: setting basic measurement unit to mm\n"); if ((status = set_basic_measurement_unit (s->fd, s->hw->info.bmu))) { DBG (DBG_error, "set_basic_measurment_unit failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } if (get_scan_source_id (s->val[OPT_SCAN_SOURCE].s) == 0) { mode = FLATBED; } else { mode = (s->val[OPT_DUPLEX].w) ? DUPLEX : SIMPLEX; } prefeed = s->val[OPT_PREFEED].w ? 0x04 : 0x00; DBG (DBG_info, "sane_start: setting scan source to %d %s\n", mode, (SANE_String) s->val[OPT_SCAN_SOURCE].s); DBG (DBG_info, "sane_start: setting prefeed to %d\n", prefeed); if ((status = set_adf_control (s->fd, &mode, &prefeed, &mwt)) != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: error set_adf_control: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } DBG (DBG_info, "sane_start: setting endorser control to %d\n", s->val[OPT_ENDORSER].w); if ((status = set_endorser_control (s->fd, &s->val[OPT_ENDORSER].w)) != SANE_STATUS_GOOD) { DBG (DBG_error, "set_endorser_control failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } if (s->val[OPT_ENDORSER].w) { DBG (DBG_info, "sane_start: setting endorser string to %s\n", s->val[OPT_ENDORSER_STRING].s); if ((status = set_endorser_string (s->fd, (SANE_String) s->val[OPT_ENDORSER_STRING]. s)) != SANE_STATUS_GOOD) { DBG (DBG_error, "set_endorser_string failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } } DBG (DBG_info, "sane_start: setting scan_wait_mode to %d\n", s->val[OPT_SCAN_WAIT_MODE].w); if ((status = set_scan_wait_mode (s->fd, s->val[OPT_SCAN_WAIT_MODE].w)) != SANE_STATUS_GOOD) { DBG (DBG_error, "set_scan_wait_mode failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (DBG_info, "sane_start: setting white_balance to %d\n", s->val[OPT_WHITE_BALANCE].w); if ((status = set_white_balance (s->fd, &s->val[OPT_WHITE_BALANCE].w)) != SANE_STATUS_GOOD) { DBG (DBG_error, "set_white_balance failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } if (s->val[OPT_CUSTOM_GAMMA].b) { /* Custom Gamma needs to be sent to scanner */ DBG (DBG_info, "sane_start: setting custom gamma\n"); if ((status = hs2p_send_gamma (s))) { DBG (DBG_error, "hs2p_send_gamma failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } /* We succeeded, so we don't need to upload this vector again (unless user modifies gamma table) */ s->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE; } DBG (DBG_info, "sane_start: filling in window data buffer \n"); if ((status = set_window_data (s, &wbuf)) != SANE_STATUS_GOOD) { DBG (DBG_error, "set_window_data failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (DBG_info, "sane_start: sending SET WINDOW DATA\n"); if ((status = set_window (s->fd, &wbuf)) != SANE_STATUS_GOOD) { DBG (DBG_error, "SET WINDOW DATA failed: %s\n", sane_strstatus (status)); print_window_data (&wbuf); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (DBG_info, "sane_start: sending GET WINDOW\n"); memset (&gbuf, 0, sizeof (gbuf)); /* CLEAR wbuf */ if ((status = get_window (s->fd, &gbuf)) != SANE_STATUS_GOOD) { DBG (DBG_error, "GET WINDOW failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return (status); } /* DONE WITH SETTING UP SCANNER ONCE PER BATCH */ s->EOM = SANE_FALSE; if (mode != FLATBED) { if ((status = get_hs2p_data (s, DATA_TYPE_ADF_STATUS, DATA_TYPE_EOL)) != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: error reading adf_status: %s\n", sane_strstatus (status)); return (status); } if ((s->data.adf_status & 0x00) == 0x01) { DBG (DBG_warning, "sane_start: No document on ADF\n"); return (SANE_STATUS_NO_DOCS); } else if ((s->data.adf_status & 0x02) == 0x02) { DBG (DBG_warning, "sane_start: ADF cover open!\n"); return (SANE_STATUS_COVER_OPEN); } } status = trigger_scan (s); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "start of scan failed: %s\n", sane_strstatus (status)); print_window_data (&wbuf); /* this line introduced not to freeze xscanimage */ /*do_cancel (s); */ return status; } /* Wait for scanner to become ready to transmit data */ status = hs2p_wait_ready (s); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "GET DATA STATUS failed: %s\n", sane_strstatus (status)); return (status); } s->another_side = (mode == DUPLEX) ? SANE_TRUE : SANE_FALSE; /* Number of bytes to read for one side of sheet */ DBG (DBG_info, "ANOTHER SIDE = %s\n", (s->another_side) ? "TRUE" : "FALSE"); s->bytes_to_read = s->params.bytes_per_line * s->params.lines; DBG (DBG_info, "%d pixels per line, %d bytes, %d lines high, dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (int) s->val[OPT_Y_RESOLUTION].w); s->scanning = SANE_TRUE; s->cancelled = SANE_FALSE; DBG (DBG_proc, "<< sane_start\n"); return (SANE_STATUS_GOOD); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { HS2P_Scanner *s = handle; SANE_Status status; size_t nread, bytes_requested, i, start; SANE_Byte color; DBG (DBG_proc, ">> sane_read\n"); *len = 0; DBG (DBG_info, "sane_read: bytes left to read: %ld\n", (u_long) s->bytes_to_read); if (s->bytes_to_read == 0) { /* We've reached the end of one side of sheet */ if (!s->another_side) { do_cancel (s); return (SANE_STATUS_EOF); } else { /* let frontend call sane_start again to reset bytes_to_read */ DBG (DBG_proc, "<< sane_read: getting another side\n"); return (SANE_STATUS_EOF); } } if (s->cancelled) { DBG (DBG_info, "sane_read: cancelled!\n"); return SANE_STATUS_CANCELLED; } if (!s->scanning) { DBG (DBG_info, "sane_read: scanning is false!\n"); return (do_cancel (s)); } nread = max_len; if (nread > s->bytes_to_read) nread = s->bytes_to_read; bytes_requested = nread; start = 0; pad: if (s->EOM) { if (s->val[OPT_PADDING].w) { DBG (DBG_info, "sane_read s->EOM padding from %ld to %ld\n", (u_long) start, (u_long) bytes_requested); color = (s->val[OPT_NEGATIVE].w) ? 0 : 255; /* pad to requested length */ for (i = start; i < bytes_requested; i++) buf[i] = color; nread = bytes_requested; /* we've padded to bytes_requested */ *len = nread; s->bytes_to_read -= nread; } else /* TRUNCATE: should never reach here */ { *len = nread; s->bytes_to_read = 0; /* EOM */ } } else { DBG (DBG_info, "sane_read: trying to read %ld bytes\n", (u_long) nread); status = read_data (s->fd, buf, &nread, DATA_TYPE_IMAGE, DTQ); switch (status) { case SANE_STATUS_NO_DOCS: DBG (DBG_error, "sane_read: End-Of-Medium detected\n"); s->EOM = SANE_TRUE; /* * If status != SANE_STATUS_GOOD, then sense_handler() has already * been called and the sanei_* functions have already gotten the * sense data buffer (which apparently clears the error conditionn) * so the following doesn't work: get_sense_data (s->fd, &(s->hw->sense_data)); print_sense_data (&(s->hw->sense_data)); */ start = (isset_ILI (s->hw->sense_data)) ? /* Invalid Length Indicator */ bytes_requested - _4btol (s->hw->sense_data.information) : nread; goto pad; break; case SANE_STATUS_GOOD: *len = nread; s->bytes_to_read -= nread; break; default: DBG (DBG_error, "sane_read: read error\n"); do_cancel (s); return (SANE_STATUS_IO_ERROR); } } DBG (DBG_proc, "<< sane_read\n"); return (SANE_STATUS_GOOD); } void sane_cancel (SANE_Handle handle) { HS2P_Scanner *s = handle; DBG (DBG_proc, ">> sane_cancel\n"); if (s->scanning) { /* if batchmode is enabled, then call set_window to abort the batch if (_OPT_VAL_WORD(s, OPT_BATCH) == SANE_TRUE) { DBG(5, "sane_cancel: calling set_window to abort batch\n"); set_window(s, BH_BATCH_ABORT); } */ do_cancel (s); } DBG (DBG_proc, "<< sane_cancel\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (DBG_proc, ">> sane_set_io_mode (handle = %p, non_blocking = %d)\n", handle, non_blocking); DBG (DBG_proc, "<< sane_set_io_mode\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { #ifdef NONBLOCKSUPPORTED HS2P_Scanner *s = handle; #endif DBG (DBG_proc, ">> sane_get_select_fd (handle = %p, fd = %p)\n", handle, (void *) fd); #ifdef NONBLOCKSUPPORTED if (s->fd < 0) { DBG (DBG_proc, "<< sane_get_select_fd\n"); return SANE_STATUS_INVAL; } *fd = s->fd; return SANE_STATUS_GOOD; #else handle = handle; fd = fd; /* get rid of compiler warning */ DBG (DBG_proc, "<< sane_get_select_fd\n"); return SANE_STATUS_UNSUPPORTED; #endif } sane-backends-1.0.27/backend/mustek_usb2.h0000664000175000017500000001154412621242546015236 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2005 Mustek. Originally maintained by Mustek Copyright (C) 2001-2005 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro and similar USB2 scanners. */ #ifndef MUSTEK_USB2_H #define MUSTEK_USB2_H #ifndef SANE_I18N #define SANE_I18N(text) text #endif #define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE #define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE #define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) /* RIE: return if error */ #define RIE(function) do {status = function; if (status != SANE_STATUS_GOOD) \ return status;} while (SANE_FALSE) #define SCAN_BUFFER_SIZE (64 * 1024) #define MAX_RESOLUTIONS 12 #define DEF_LINEARTTHRESHOLD 128 #define PER_ADD_START_LINES 0 #define PRE_ADD_START_X 0 enum Mustek_Usb_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_SOURCE, OPT_RESOLUTION, OPT_PREVIEW, OPT_DEBUG_GROUP, OPT_AUTO_WARMUP, OPT_ENHANCEMENT_GROUP, OPT_THRESHOLD, OPT_GAMMA_VALUE, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ /* must come last: */ NUM_OPTIONS }; typedef struct Scanner_Model { /** @name Identification */ /*@{ */ /** A single lowercase word to be used in the configuration file. */ SANE_String_Const name; /** Device vendor string. */ SANE_String_Const vendor; /** Device model name. */ SANE_String_Const model; /** Name of the firmware file. */ SANE_String_Const firmware_name; /** @name Scanner model parameters */ /*@{ */ SANE_Int dpi_values[MAX_RESOLUTIONS]; /* possible resolutions */ SANE_Fixed x_offset; /* Start of scan area in mm */ SANE_Fixed y_offset; /* Start of scan area in mm */ SANE_Fixed x_size; /* Size of scan area in mm */ SANE_Fixed y_size; /* Size of scan area in mm */ SANE_Fixed x_offset_ta; /* Start of scan area in TA mode in mm */ SANE_Fixed y_offset_ta; /* Start of scan area in TA mode in mm */ SANE_Fixed x_size_ta; /* Size of scan area in TA mode in mm */ SANE_Fixed y_size_ta; /* Size of scan area in TA mode in mm */ RGBORDER line_mode_color_order; /* Order of the CCD/CIS colors */ SANE_Fixed default_gamma_value; /* Default gamma value */ SANE_Bool is_cis; /* Is this a CIS or CCD scanner? */ SANE_Word flags; /* Which hacks are needed for this scanner? */ /*@} */ } Scanner_Model; typedef struct Mustek_Scanner { /* all the state needed to define a scan request: */ struct Mustek_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; unsigned short *gamma_table; SANE_Parameters params; /**< SANE Parameters */ Scanner_Model model; SETPARAMETERS setpara; GETPARAMETERS getpara; SANE_Bool bIsScanning; SANE_Bool bIsReading; SANE_Word read_rows; /* transfer image's lines */ SANE_Byte *Scan_data_buf; /*store Scanned data for transfer */ SANE_Byte *Scan_data_buf_start; /*point to data need to transfer */ size_t scan_buffer_len; /* length of data buf */ } Mustek_Scanner; #endif sane-backends-1.0.27/backend/xerox_mfp.c0000664000175000017500000013341613063340150014767 00000000000000/* * SANE backend for Xerox Phaser 3200MFP et al. * Copyright 2008-2016 ABC * * Network Scanners Support * Copyright 2010 Alexander Kuznetsov * * Color scanning on Samsung M2870 model and Xerox Cognac 3215 & 3225 * models by Laxmeesh Onkar Markod * * This program is licensed under GPL + SANE exception. * More info at http://www.sane-project.org/license.html */ #define DEBUG_NOT_STATIC #define BACKEND_NAME xerox_mfp #include "../include/sane/config.h" #include "../include/lassert.h" #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_thread.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" #ifdef HAVE_LIBJPEG #include #endif #include "xerox_mfp.h" #define BACKEND_BUILD 13 #define XEROX_CONFIG_FILE "xerox_mfp.conf" static const SANE_Device **devlist = NULL; /* sane_get_devices array */ static struct device *devices_head = NULL; /* sane_get_devices list */ enum { TRANSPORT_USB, TRANSPORT_TCP, TRANSPORTS_MAX }; transport available_transports[TRANSPORTS_MAX] = { { "usb", usb_dev_request, usb_dev_open, usb_dev_close, usb_configure_device }, { "tcp", tcp_dev_request, tcp_dev_open, tcp_dev_close, tcp_configure_device }, }; static int resolv_state(int state) { if (state & STATE_DOCUMENT_JAM) return SANE_STATUS_JAMMED; if (state & STATE_NO_DOCUMENT) return SANE_STATUS_NO_DOCS; if (state & STATE_COVER_OPEN) return SANE_STATUS_COVER_OPEN; if (state & STATE_INVALID_AREA) return SANE_STATUS_INVAL; /* sane_start: implies SANE_INFO_RELOAD_OPTIONS */ if (state & STATE_WARMING) #ifdef SANE_STATUS_WARMING_UP return SANE_STATUS_WARMING_UP; #else return SANE_STATUS_DEVICE_BUSY; #endif if (state & STATE_LOCKING) #ifdef SANE_STATUS_HW_LOCKED return SANE_STATUS_HW_LOCKED; #else return SANE_STATUS_JAMMED; #endif if (state & ~STATE_NO_ERROR) return SANE_STATUS_DEVICE_BUSY; return 0; } static char *str_cmd(int cmd) { switch (cmd) { case CMD_ABORT: return "ABORT"; case CMD_INQUIRY: return "INQUIRY"; case CMD_RESERVE_UNIT: return "RESERVE_UNIT"; case CMD_RELEASE_UNIT: return "RELEASE_UNIT"; case CMD_SET_WINDOW: return "SET_WINDOW"; case CMD_READ: return "READ"; case CMD_READ_IMAGE: return "READ_IMAGE"; case CMD_OBJECT_POSITION: return "OBJECT_POSITION"; } return "unknown"; } #define MAX_DUMP 70 const char *encTmpFileName = "/tmp/stmp_enc.tmp"; static int decompress(struct device __sane_unused__ *dev, const char __sane_unused__ *infilename) { #ifdef HAVE_LIBJPEG int rc; int row_stride, width, height, pixel_size; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; unsigned long bmp_size = 0; FILE *pInfile = NULL; JSAMPARRAY buffer; if ((pInfile = fopen(infilename, "rb")) == NULL) { fprintf(stderr, "can't open %s\n", infilename); return -1; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, pInfile); rc = jpeg_read_header(&cinfo, TRUE); if (rc != 1) { jpeg_destroy_decompress(&cinfo); fclose(pInfile); return -1; } jpeg_start_decompress(&cinfo); width = cinfo.output_width; height = cinfo.output_height; pixel_size = cinfo.output_components; bmp_size = width * height * pixel_size; dev->decDataSize = bmp_size; row_stride = width * pixel_size; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); while (cinfo.output_scanline < cinfo.output_height) { buffer[0] = dev->decData + \ (cinfo.output_scanline) * row_stride; jpeg_read_scanlines(&cinfo, buffer, 1); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(pInfile); return 0; #else return -1; #endif } static int copy_decompress_data(struct device *dev, unsigned char *pDest, int maxlen, int *destLen) { int data_size = 0; size_t result = 0, retVal = 0; if (0 == dev->decDataSize) { *destLen = 0; return retVal; } data_size = dev->decDataSize - dev->currentDecDataIndex; if (data_size > maxlen) { data_size = maxlen; } memcpy(pDest, dev->decData+dev->currentDecDataIndex, data_size); result = data_size; *destLen = result; dev->currentDecDataIndex += result; retVal = result; if (dev->decDataSize == dev->currentDecDataIndex) { dev->currentDecDataIndex = 0; dev->decDataSize = 0; } return retVal; } static int decompress_tempfile(struct device *dev) { decompress(dev, encTmpFileName); remove(encTmpFileName); return 0; } static int dump_to_tmp_file(struct device *dev) { unsigned char *pSrc = dev->data; int srcLen = dev->datalen; FILE *pInfile; if ((pInfile = fopen(encTmpFileName, "a")) == NULL) { fprintf(stderr, "can't open %s\n", encTmpFileName); return 0; } fwrite(pSrc, 1, srcLen, pInfile); fclose(pInfile); return srcLen; } static int isSupportedDevice(struct device __sane_unused__ *dev) { #ifdef HAVE_LIBJPEG /* Checking device which supports JPEG Lossy compression for color scanning*/ if (dev->compressionTypes & (1 << 6)) return 1; else return 0; #else return 0; #endif } static void dbg_dump(struct device *dev) { int i; char dbuf[MAX_DUMP * 3 + 1], *dptr = dbuf; int nzlen = dev->reslen; int dlen = MIN(dev->reslen, MAX_DUMP); for (i = dev->reslen - 1; i >= 0; i--, nzlen--) if (dev->res[i] != 0) break; dlen = MIN(dlen, nzlen + 1); for (i = 0; i < dlen; i++, dptr += 3) sprintf(dptr, " %02x", dev->res[i]); DBG(5, "[%lu]%s%s\n", (u_long)dev->reslen, dbuf, (dlen < (int)dev->reslen)? "..." : ""); } /* one command to device */ /* return 0: on error, 1: success */ static int dev_command(struct device *dev, SANE_Byte *cmd, size_t reqlen) { SANE_Status status; size_t sendlen = cmd[3] + 4; SANE_Byte *res = dev->res; assert(reqlen <= sizeof(dev->res)); /* requested len */ dev->reslen = sizeof(dev->res); /* doing full buffer to flush stalled commands */ if (cmd[2] == CMD_SET_WINDOW) { /* Set Window have wrong packet length, huh. */ sendlen = 25; } if (cmd[2] == CMD_READ_IMAGE) { /* Read Image is raw data, don't need to read response */ res = NULL; } dev->state = 0; DBG(4, ":: dev_command(%s[%#x], %lu)\n", str_cmd(cmd[2]), cmd[2], (u_long)reqlen); status = dev->io->dev_request(dev, cmd, sendlen, res, &dev->reslen); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: dev_request: %s\n", __func__, sane_strstatus(status)); dev->state = SANE_STATUS_IO_ERROR; return 0; } if (!res) { /* if not need response just return success */ return 1; } /* normal command reply, some sanity checking */ if (dev->reslen < reqlen) { DBG(1, "%s: illegal response len %lu, need %lu\n", __func__, (u_long)dev->reslen, (u_long)reqlen); dev->state = SANE_STATUS_IO_ERROR; return 0; } else { size_t pktlen; /* len specified in packet */ if (DBG_LEVEL > 3) dbg_dump(dev); if (dev->res[0] != RES_CODE) { DBG(2, "%s: illegal data header %02x\n", __func__, dev->res[0]); dev->state = SANE_STATUS_IO_ERROR; return 0; } pktlen = dev->res[2] + 3; if (dev->reslen != pktlen) { DBG(2, "%s: illegal response len %lu, should be %lu\n", __func__, (u_long)pktlen, (u_long)dev->reslen); dev->state = SANE_STATUS_IO_ERROR; return 0; } if (dev->reslen > reqlen) DBG(2, "%s: too big packet len %lu, need %lu\n", __func__, (u_long)dev->reslen, (u_long)reqlen); } dev->state = 0; if (cmd[2] == CMD_SET_WINDOW || cmd[2] == CMD_OBJECT_POSITION || cmd[2] == CMD_READ || cmd[2] == CMD_RESERVE_UNIT) { if (dev->res[1] == STATUS_BUSY) dev->state = SANE_STATUS_DEVICE_BUSY; else if (dev->res[1] == STATUS_CANCEL) dev->state = SANE_STATUS_CANCELLED; else if (dev->res[1] == STATUS_CHECK) dev->state = resolv_state((cmd[2] == CMD_READ)? (dev->res[12] << 8 | dev->res[13]) : (dev->res[4] << 8 | dev->res[5])); if (dev->state) DBG(3, "%s(%s[%#x]): => %d: %s\n", __func__, str_cmd(cmd[2]), cmd[2], dev->state, sane_strstatus(dev->state)); } return 1; } /* one short command to device */ static int dev_cmd(struct device *dev, SANE_Byte command) { SANE_Byte cmd[4] = { REQ_CODE_A, REQ_CODE_B }; cmd[2] = command; return dev_command(dev, cmd, (command == CMD_INQUIRY)? 70 : 32); } /* stop scanning operation. return previous status */ static SANE_Status dev_stop(struct device *dev) { int state = dev->state; DBG(3, "%s: %p, scanning %d, reserved %d\n", __func__, (void *)dev, dev->scanning, dev->reserved); dev->scanning = 0; /* release */ if (!dev->reserved) return state; dev->reserved = 0; dev_cmd(dev, CMD_RELEASE_UNIT); DBG(3, "total image %d*%d size %d (win %d*%d), %d*%d %d data: %d, out %d bytes\n", dev->para.pixels_per_line, dev->para.lines, dev->total_img_size, dev->win_width, dev->win_len, dev->pixels_per_line, dev->ulines, dev->blocks, dev->total_data_size, dev->total_out_size); dev->state = state; return state; } SANE_Status ret_cancel(struct device *dev, SANE_Status ret) { dev_cmd(dev, CMD_ABORT); if (dev->scanning) { dev_stop(dev); dev->state = SANE_STATUS_CANCELLED; } return ret; } static int cancelled(struct device *dev) { if (dev->cancel) return ret_cancel(dev, 1); return 0; } /* issue command and wait until scanner is not busy */ /* return 0 on error/blocking, 1 is ok and ready */ static int dev_cmd_wait(struct device *dev, int cmd) { int sleeptime = 10; do { if (cancelled(dev)) return 0; if (!dev_cmd(dev, cmd)) { dev->state = SANE_STATUS_IO_ERROR; return 0; } else if (dev->state) { if (dev->state != SANE_STATUS_DEVICE_BUSY) return 0; else { if (dev->non_blocking) { dev->state = SANE_STATUS_GOOD; return 0; } else { if (sleeptime > 1000) sleeptime = 1000; DBG(4, "(%s) sleeping(%d ms).. [%x %x]\n", str_cmd(cmd), sleeptime, dev->res[4], dev->res[5]); usleep(sleeptime * 1000); if (sleeptime < 1000) sleeptime *= (sleeptime < 100)? 10 : 2; } } /* BUSY */ } } while (dev->state == SANE_STATUS_DEVICE_BUSY); return 1; } static int inq_dpi_bits[] = { 75, 150, 0, 0, 200, 300, 0, 0, 600, 0, 0, 1200, 100, 0, 0, 2400, 0, 4800, 0, 9600 }; static int res_dpi_codes[] = { 75, 0, 150, 0, 0, 300, 0, 600, 1200, 200, 100, 2400, 4800, 9600 }; static int SANE_Word_sort(const void *a, const void *b) { return *(const SANE_Word *)a - *(const SANE_Word *)b; } /* resolve inquired dpi list to dpi_list array */ static void resolv_inq_dpi(struct device *dev) { unsigned int i; int res = dev->resolutions; assert(sizeof(inq_dpi_bits) < sizeof(dev->dpi_list)); for (i = 0; i < sizeof(inq_dpi_bits) / sizeof(int); i++) if (inq_dpi_bits[i] && (res & (1 << i))) dev->dpi_list[++dev->dpi_list[0]] = inq_dpi_bits[i]; qsort(&dev->dpi_list[1], dev->dpi_list[0], sizeof(SANE_Word), SANE_Word_sort); } static unsigned int dpi_to_code(int dpi) { unsigned int i; for (i = 0; i < sizeof(res_dpi_codes) / sizeof(int); i++) { if (dpi == res_dpi_codes[i]) return i; } return 0; } static int string_match_index(const SANE_String_Const s[], SANE_String m) { int i; for (i = 0; *s; i++) { SANE_String_Const x = *s++; if (strcasecmp(x, m) == 0) return i; } return 0; } static SANE_String string_match(const SANE_String_Const s[], SANE_String m) { return UNCONST(s[string_match_index(s, m)]); } static size_t max_string_size(SANE_String_Const s[]) { size_t max = 0; while (*s) { size_t size = strlen(*s++) + 1; if (size > max) max = size; } return max; } static SANE_String_Const doc_sources[] = { "Flatbed", "ADF", "Auto", NULL }; static int doc_source_to_code[] = { 0x40, 0x20, 0x80 }; static SANE_String_Const scan_modes[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; static int scan_mode_to_code[] = { 0x00, 0x01, 0x03, 0x05 }; static SANE_Range threshold = { SANE_FIX(30), SANE_FIX(70), SANE_FIX(10) }; static void reset_options(struct device *dev) { dev->val[OPT_RESOLUTION].w = 150; dev->val[OPT_MODE].s = string_match(scan_modes, SANE_VALUE_SCAN_MODE_COLOR); /* if docs loaded in adf use it as default source, flatbed oterwise */ dev->val[OPT_SOURCE].s = UNCONST(doc_sources[(dev->doc_loaded)? 1 : 0]); dev->val[OPT_THRESHOLD].w = SANE_FIX(50); /* this is reported maximum window size, will be fixed later */ dev->win_x_range.min = SANE_FIX(0); dev->win_x_range.max = SANE_FIX((double)dev->max_win_width / PNT_PER_MM); dev->win_x_range.quant = SANE_FIX(1); dev->win_y_range.min = SANE_FIX(0); dev->win_y_range.max = SANE_FIX((double)dev->max_win_len / PNT_PER_MM); dev->win_y_range.quant = SANE_FIX(1); dev->val[OPT_SCAN_TL_X].w = dev->win_x_range.min; dev->val[OPT_SCAN_TL_Y].w = dev->win_y_range.min; dev->val[OPT_SCAN_BR_X].w = dev->win_x_range.max; dev->val[OPT_SCAN_BR_Y].w = dev->win_y_range.max; } static void init_options(struct device *dev) { int i; for (i = 0; i < NUM_OPTIONS; i++) { dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->opt[i].size = sizeof(SANE_Word); dev->opt[i].type = SANE_TYPE_FIXED; dev->val[i].s = NULL; } dev->opt[OPT_NUMOPTIONS].name = SANE_NAME_NUM_OPTIONS; dev->opt[OPT_NUMOPTIONS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUMOPTIONS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUMOPTIONS].type = SANE_TYPE_INT; dev->opt[OPT_NUMOPTIONS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUMOPTIONS].w = NUM_OPTIONS; dev->opt[OPT_GROUP_STD].name = SANE_NAME_STANDARD; dev->opt[OPT_GROUP_STD].title = SANE_TITLE_STANDARD; dev->opt[OPT_GROUP_STD].desc = SANE_DESC_STANDARD; dev->opt[OPT_GROUP_STD].type = SANE_TYPE_GROUP; dev->opt[OPT_GROUP_STD].cap = 0; dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_RESOLUTION].constraint.word_list = dev->dpi_list; dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = max_string_size(scan_modes); dev->opt[OPT_MODE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = scan_modes; dev->opt[OPT_THRESHOLD].name = SANE_NAME_HIGHLIGHT; dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_THRESHOLD].constraint.range = &threshold; dev->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; dev->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; dev->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; dev->opt[OPT_SOURCE].type = SANE_TYPE_STRING; dev->opt[OPT_SOURCE].size = max_string_size(doc_sources); dev->opt[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_SOURCE].constraint.string_list = doc_sources; dev->opt[OPT_GROUP_GEO].name = SANE_NAME_GEOMETRY; dev->opt[OPT_GROUP_GEO].title = SANE_TITLE_GEOMETRY; dev->opt[OPT_GROUP_GEO].desc = SANE_DESC_GEOMETRY; dev->opt[OPT_GROUP_GEO].type = SANE_TYPE_GROUP; dev->opt[OPT_GROUP_GEO].cap = 0; dev->opt[OPT_SCAN_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_SCAN_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_SCAN_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_SCAN_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_SCAN_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_SCAN_TL_X].constraint.range = &dev->win_x_range; dev->opt[OPT_SCAN_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_SCAN_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_SCAN_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_SCAN_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_SCAN_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_SCAN_TL_Y].constraint.range = &dev->win_y_range; dev->opt[OPT_SCAN_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_SCAN_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_SCAN_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_SCAN_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_SCAN_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_SCAN_BR_X].constraint.range = &dev->win_x_range; dev->opt[OPT_SCAN_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_SCAN_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_SCAN_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_SCAN_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_SCAN_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_SCAN_BR_Y].constraint.range = &dev->win_y_range; } /* fill parameters from options */ static void set_parameters(struct device *dev) { double px_to_len; dev->para.last_frame = SANE_TRUE; dev->para.lines = -1; px_to_len = 1200.0 / dev->val[OPT_RESOLUTION].w; #define BETTER_BASEDPI 1 /* tests prove that 1200dpi base is very inexact * so I calculated better values for each axis */ #if BETTER_BASEDPI px_to_len = 1180.0 / dev->val[OPT_RESOLUTION].w; #endif dev->para.pixels_per_line = dev->win_width / px_to_len; dev->para.bytes_per_line = dev->para.pixels_per_line; if (!isSupportedDevice(dev)) { #if BETTER_BASEDPI px_to_len = 1213.9 / dev->val[OPT_RESOLUTION].w; #endif } dev->para.lines = dev->win_len / px_to_len; if (dev->composition == MODE_LINEART || dev->composition == MODE_HALFTONE) { dev->para.format = SANE_FRAME_GRAY; dev->para.depth = 1; dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8; } else if (dev->composition == MODE_GRAY8) { dev->para.format = SANE_FRAME_GRAY; dev->para.depth = 8; dev->para.bytes_per_line = dev->para.pixels_per_line; } else if (dev->composition == MODE_RGB24) { dev->para.format = SANE_FRAME_RGB; dev->para.depth = 8; dev->para.bytes_per_line *= 3; } else { /* this will never happen */ DBG(1, "%s: impossible image composition %d\n", __func__, dev->composition); dev->para.format = SANE_FRAME_GRAY; dev->para.depth = 8; } } /* resolve all options related to scan window */ /* called after option changed and in set_window */ static int fix_window(struct device *dev) { double win_width_mm, win_len_mm; int i; int threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w); dev->resolution = dpi_to_code(dev->val[OPT_RESOLUTION].w); dev->composition = scan_mode_to_code[string_match_index(scan_modes, dev->val[OPT_MODE].s)]; if (dev->composition == MODE_LINEART || dev->composition == MODE_HALFTONE) { dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; } if (threshold < 30) { dev->val[OPT_THRESHOLD].w = SANE_FIX(30); } else if (threshold > 70) { dev->val[OPT_THRESHOLD].w = SANE_FIX(70); } threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w); dev->threshold = (threshold - 30) / 10; dev->val[OPT_THRESHOLD].w = SANE_FIX(dev->threshold * 10 + 30); dev->doc_source = doc_source_to_code[string_match_index(doc_sources, dev->val[OPT_SOURCE].s)]; /* max window len is dependent of document source */ if (dev->doc_source == DOC_FLATBED || (dev->doc_source == DOC_AUTO && !dev->doc_loaded)) dev->max_len = dev->max_len_fb; else dev->max_len = dev->max_len_adf; /* parameters */ dev->win_y_range.max = SANE_FIX((double)dev->max_len / PNT_PER_MM); /* window sanity checking */ for (i = OPT_SCAN_TL_X; i <= OPT_SCAN_BR_Y; i++) { if (dev->val[i].w < dev->opt[i].constraint.range->min) dev->val[i].w = dev->opt[i].constraint.range->min; if (dev->val[i].w > dev->opt[i].constraint.range->max) dev->val[i].w = dev->opt[i].constraint.range->max; } if (dev->val[OPT_SCAN_TL_X].w > dev->val[OPT_SCAN_BR_X].w) SWAP_Word(dev->val[OPT_SCAN_TL_X].w, dev->val[OPT_SCAN_BR_X].w); if (dev->val[OPT_SCAN_TL_Y].w > dev->val[OPT_SCAN_BR_Y].w) SWAP_Word(dev->val[OPT_SCAN_TL_Y].w, dev->val[OPT_SCAN_BR_Y].w); /* recalculate millimeters to inches */ dev->win_off_x = SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w) / MM_PER_INCH; dev->win_off_y = SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w) / MM_PER_INCH; /* calc win size in mm */ win_width_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_X].w) - SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w); win_len_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_Y].w) - SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w); /* convert mm to 1200 dpi points */ dev->win_width = (int)(win_width_mm * PNT_PER_MM); dev->win_len = (int)(win_len_mm * PNT_PER_MM); /* don't scan if window is zero size */ if (!dev->win_width || !dev->win_len) { /* "The scan cannot be started with the current set of options." */ dev->state = SANE_STATUS_INVAL; return 0; } return 1; } static int dev_set_window(struct device *dev) { SANE_Byte cmd[0x19] = { REQ_CODE_A, REQ_CODE_B, CMD_SET_WINDOW, 0x13, MSG_SCANNING_PARAM }; if (!fix_window(dev)) return 0; cmd[0x05] = dev->win_width >> 24; cmd[0x06] = dev->win_width >> 16; cmd[0x07] = dev->win_width >> 8; cmd[0x08] = dev->win_width; cmd[0x09] = dev->win_len >> 24; cmd[0x0a] = dev->win_len >> 16; cmd[0x0b] = dev->win_len >> 8; cmd[0x0c] = dev->win_len; cmd[0x0d] = dev->resolution; /* x */ cmd[0x0e] = dev->resolution; /* y */ cmd[0x0f] = (SANE_Byte)floor(dev->win_off_x); cmd[0x10] = (SANE_Byte)((dev->win_off_x - floor(dev->win_off_x)) * 100); cmd[0x11] = (SANE_Byte)floor(dev->win_off_y); cmd[0x12] = (SANE_Byte)((dev->win_off_y - floor(dev->win_off_y)) * 100); cmd[0x13] = dev->composition; /* Set to JPEG Lossy Compression, if mode is color (only for supported model)... * else go with Uncompressed (For backard compatibility with old models )*/ if (dev->composition == MODE_RGB24) { if (isSupportedDevice(dev)) { cmd[0x14] = 0x6; } } cmd[0x16] = dev->threshold; cmd[0x17] = dev->doc_source; DBG(5, "OFF xi: %02x%02x yi: %02x%02x," " WIN xp: %02x%02x%02x%02x yp %02x%02x%02x%02x," " MAX %08x %08x\n", cmd[0x0f], cmd[0x10], cmd[0x11], cmd[0x12], cmd[0x05], cmd[0x06], cmd[0x07], cmd[0x08], cmd[0x09], cmd[0x0a], cmd[0x0b], cmd[0x0c], dev->max_win_width, dev->max_win_len); return dev_command(dev, cmd, 32); } static SANE_Status dev_inquiry(struct device *dev) { SANE_Byte *ptr; SANE_Char *optr, *xptr; if (!dev_cmd(dev, CMD_INQUIRY)) return SANE_STATUS_IO_ERROR; ptr = dev->res; if (ptr[3] != MSG_PRODUCT_INFO) { DBG(1, "%s: illegal INQUIRY response %02x\n", __func__, ptr[3]); return SANE_STATUS_IO_ERROR; } /* parse reported manufacturer/product names */ dev->sane.vendor = optr = (SANE_Char *) malloc(33); for (ptr += 4; ptr < &dev->res[0x24] && *ptr && *ptr != ' ';) *optr++ = *ptr++; *optr++ = 0; for (; ptr < &dev->res[0x24] && (!*ptr || *ptr == ' '); ptr++) /* skip spaces */; dev->sane.model = optr = (SANE_Char *) malloc(33); xptr = optr; /* is last non space character + 1 */ for (; ptr < &dev->res[0x24] && *ptr;) { if (*ptr != ' ') xptr = optr + 1; *optr++ = *ptr++; } *optr++ = 0; *xptr = 0; DBG(1, "%s: found %s/%s\n", __func__, dev->sane.vendor, dev->sane.model); dev->sane.type = strdup("multi-function peripheral"); dev->resolutions = dev->res[0x37] << 16 | dev->res[0x24] << 8 | dev->res[0x25]; dev->compositions = dev->res[0x27]; dev->max_win_width = dev->res[0x28] << 24 | dev->res[0x29] << 16 | dev->res[0x2a] << 8 | dev->res[0x2b]; dev->max_win_len = dev->res[0x2c] << 24 | dev->res[0x2d] << 16 | dev->res[0x2e] << 8 | dev->res[0x2f]; dev->max_len_adf = dev->res[0x38] << 24 | dev->res[0x39] << 16 | dev->res[0x3a] << 8 | dev->res[0x3b]; dev->max_len_fb = dev->res[0x3c] << 24 | dev->res[0x3d] << 16 | dev->res[0x3e] << 8 | dev->res[0x3f]; dev->line_order = dev->res[0x31]; dev->compressionTypes = dev->res[0x32]; dev->doc_loaded = (dev->res[0x35] == 0x02) && (dev->res[0x26] & 0x03); init_options(dev); reset_options(dev); fix_window(dev); set_parameters(dev); resolv_inq_dpi(dev); return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle h, SANE_Int opt) { struct device *dev = h; DBG(3, "%s: %p, %d\n", __func__, h, opt); if (opt >= NUM_OPTIONS || opt < 0) return NULL; return &dev->opt[opt]; } SANE_Status sane_control_option(SANE_Handle h, SANE_Int opt, SANE_Action act, void *val, SANE_Word *info) { struct device *dev = h; DBG(3, "%s: %p, %d, <%d>, %p, %p\n", __func__, h, opt, act, val, (void *)info); if (!dev || opt >= NUM_OPTIONS || opt < 0) return SANE_STATUS_INVAL; if (info) *info = 0; if (act == SANE_ACTION_GET_VALUE) { /* GET */ if (dev->opt[opt].type == SANE_TYPE_STRING) strcpy(val, dev->val[opt].s); else *(SANE_Word *)val = dev->val[opt].w; } else if (act == SANE_ACTION_SET_VALUE) { /* SET */ SANE_Parameters xpara = dev->para; SANE_Option_Descriptor xopt[NUM_OPTIONS]; Option_Value xval[NUM_OPTIONS]; int i; if (dev->opt[opt].constraint_type == SANE_CONSTRAINT_STRING_LIST) { dev->val[opt].s = string_match(dev->opt[opt].constraint.string_list, val); if (info && strcasecmp(dev->val[opt].s, val)) *info |= SANE_INFO_INEXACT; } else if (opt == OPT_RESOLUTION) dev->val[opt].w = res_dpi_codes[dpi_to_code(*(SANE_Word *)val)]; else dev->val[opt].w = *(SANE_Word *)val; memcpy(&xopt, &dev->opt, sizeof(xopt)); memcpy(&xval, &dev->val, sizeof(xval)); fix_window(dev); set_parameters(dev); /* check for side effects */ if (info) { if (memcmp(&xpara, &dev->para, sizeof(xpara))) *info |= SANE_INFO_RELOAD_PARAMS; if (memcmp(&xopt, &dev->opt, sizeof(xopt))) *info |= SANE_INFO_RELOAD_OPTIONS; for (i = 0; i < NUM_OPTIONS; i++) if (xval[i].w != dev->val[i].w) { if (i == opt) *info |= SANE_INFO_INEXACT; else *info |= SANE_INFO_RELOAD_OPTIONS; } } } DBG(4, "%s: %d, <%d> => %08x, %x\n", __func__, opt, act, val? *(SANE_Word *)val : 0, info? *info : 0); return SANE_STATUS_GOOD; } static void dev_free(struct device *dev) { if (!dev) return; if (dev->sane.name) free(UNCONST(dev->sane.name)); if (dev->sane.vendor) free(UNCONST(dev->sane.vendor)); if (dev->sane.model) free(UNCONST(dev->sane.model)); if (dev->sane.type) free(UNCONST(dev->sane.type)); if (dev->data) free(dev->data); if (dev->decData) { free(dev->decData); dev->decData = NULL; } memset(dev, 0, sizeof(*dev)); free(dev); } static void free_devices(void) { struct device *next; struct device *dev; if (devlist) { free(devlist); devlist = NULL; } for (dev = devices_head; dev; dev = next) { next = dev->next; dev_free(dev); } devices_head = NULL; } static transport *tr_from_devname(SANE_String_Const devname) { if (strncmp("tcp", devname, 3) == 0) return &available_transports[TRANSPORT_TCP]; return &available_transports[TRANSPORT_USB]; } static SANE_Status list_one_device(SANE_String_Const devname) { struct device *dev; SANE_Status status; transport *tr; DBG(4, "%s: %s\n", __func__, devname); for (dev = devices_head; dev; dev = dev->next) { if (strcmp(dev->sane.name, devname) == 0) return SANE_STATUS_GOOD; } tr = tr_from_devname(devname); dev = calloc(1, sizeof(struct device)); if (dev == NULL) return SANE_STATUS_NO_MEM; dev->sane.name = strdup(devname); dev->io = tr; status = tr->dev_open(dev); if (status != SANE_STATUS_GOOD) { dev_free(dev); return status; } /* status = dev_cmd (dev, CMD_ABORT);*/ status = dev_inquiry(dev); tr->dev_close(dev); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: dev_inquiry(%s): %s\n", __func__, dev->sane.name, sane_strstatus(status)); dev_free(dev); return status; } /* good device, add it to list */ dev->next = devices_head; devices_head = dev; return SANE_STATUS_GOOD; } /* SANE API ignores return code of this callback */ static SANE_Status list_conf_devices(UNUSED(SANEI_Config *config), const char *devname) { return tr_from_devname(devname)->configure_device(devname, list_one_device); } SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback cb) { DBG_INIT(); DBG(2, "sane_init: Xerox backend (build %d), version %s null, authorize %s null\n", BACKEND_BUILD, (version_code) ? "!=" : "==", (cb) ? "!=" : "=="); if (version_code) *version_code = SANE_VERSION_CODE(V_MAJOR, V_MINOR, BACKEND_BUILD); sanei_usb_init(); return SANE_STATUS_GOOD; } void sane_exit(void) { struct device *dev; for (dev = devices_head; dev; dev = dev->next) if (dev->dn != -1) sane_close(dev); /* implies flush */ free_devices(); } SANE_Status sane_get_devices(const SANE_Device *** device_list, SANE_Bool local) { SANEI_Config config; struct device *dev; int dev_count; int i; DBG(3, "%s: %p, %d\n", __func__, (const void *)device_list, local); if (devlist) { if (device_list) *device_list = devlist; return SANE_STATUS_GOOD; } free_devices(); config.count = 0; config.descriptors = NULL; config.values = NULL; sanei_configure_attach(XEROX_CONFIG_FILE, &config, list_conf_devices); for (dev_count = 0, dev = devices_head; dev; dev = dev->next) dev_count++; devlist = malloc((dev_count + 1) * sizeof(*devlist)); if (!devlist) { DBG(1, "%s: malloc: no memory\n", __func__); return SANE_STATUS_NO_MEM; } for (i = 0, dev = devices_head; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = NULL; if (device_list) *device_list = devlist; return SANE_STATUS_GOOD; } void sane_close(SANE_Handle h) { struct device *dev = h; if (!dev) return; DBG(3, "%s: %p (%s)\n", __func__, (void *)dev, dev->sane.name); dev->io->dev_close(dev); } SANE_Status sane_open(SANE_String_Const name, SANE_Handle *h) { struct device *dev; DBG(3, "%s: '%s'\n", __func__, name); if (!devlist) sane_get_devices(NULL, SANE_TRUE); if (!name || !*name) { /* special case of empty name: open first available device */ for (dev = devices_head; dev; dev = dev->next) { if (dev->dn != -1) { if (sane_open(dev->sane.name, h) == SANE_STATUS_GOOD) return SANE_STATUS_GOOD; } } } else { for (dev = devices_head; dev; dev = dev->next) { if (strcmp(name, dev->sane.name) == 0) { *h = dev; return dev->io->dev_open(dev); } } } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters(SANE_Handle h, SANE_Parameters *para) { struct device *dev = h; DBG(3, "%s: %p, %p\n", __func__, h, (void *)para); if (!para) return SANE_STATUS_INVAL; *para = dev->para; return SANE_STATUS_GOOD; } /* check if image data is ready, and wait if not */ /* 1: image is acquired, 0: error or non_blocking mode */ static int dev_acquire(struct device *dev) { if (!dev_cmd_wait(dev, CMD_READ)) return dev->state; dev->state = SANE_STATUS_GOOD; dev->vertical = dev->res[0x08] << 8 | dev->res[0x09]; dev->horizontal = dev->res[0x0a] << 8 | dev->res[0x0b]; dev->blocklen = dev->res[4] << 24 | dev->res[5] << 16 | dev->res[6] << 8 | dev->res[7]; dev->final_block = (dev->res[3] == MSG_END_BLOCK)? 1 : 0; dev->pixels_per_line = dev->horizontal; dev->bytes_per_line = dev->horizontal; if (dev->composition == MODE_RGB24) dev->bytes_per_line *= 3; else if (dev->composition == MODE_LINEART || dev->composition == MODE_HALFTONE) dev->pixels_per_line *= 8; DBG(4, "acquiring, size per band v: %d, h: %d, %sblock: %d, slack: %d\n", dev->vertical, dev->horizontal, dev->final_block? "last " : "", dev->blocklen, dev->blocklen - (dev->vertical * dev->bytes_per_line)); if (dev->bytes_per_line > DATASIZE) { DBG(1, "%s: unsupported line size: %d bytes > %d\n", __func__, dev->bytes_per_line, DATASIZE); return ret_cancel(dev, SANE_STATUS_NO_MEM); } dev->reading = 0; /* need to issue READ_IMAGE */ dev->dataindex = 0; dev->datalen = 0; dev->dataoff = 0; return 1; } static int fill_slack(struct device *dev, SANE_Byte *buf, int maxlen) { const int slack = dev->total_img_size - dev->total_out_size; const int havelen = MIN(slack, maxlen); int j; if (havelen <= 0) return 0; for (j = 0; j < havelen; j++) buf[j] = 255; return havelen; } static int copy_plain_trim(struct device *dev, SANE_Byte *buf, int maxlen, int *olenp) { int j; const int linesize = dev->bytes_per_line; int k = dev->dataindex; *olenp = 0; for (j = 0; j < dev->datalen && *olenp < maxlen; j++, k++) { const int x = k % linesize; const int y = k / linesize; if (y >= dev->vertical) break; /* slack */ if (x < dev->para.bytes_per_line && (y + dev->y_off) < dev->para.lines) { *buf++ = dev->data[(dev->dataoff + j) & DATAMASK]; (*olenp)++; } } dev->dataindex = k; return j; } /* return: how much data could be freed from cyclic buffer */ /* convert from RRGGBB to RGBRGB */ static int copy_mix_bands_trim(struct device *dev, SANE_Byte *buf, int maxlen, int *olenp) { int j; const int linesize = dev->bytes_per_line; /* caching real line size */ /* line number of the head of input buffer, * input buffer is always aligned to whole line */ const int y_off = dev->dataindex / linesize; int k = dev->dataindex; /* caching current index of input buffer */ /* can only copy as much as full lines we have */ int havelen = dev->datalen / linesize * linesize - k % linesize; const int bands = 3; *olenp = 0; /* while we have data && they can receive */ for (j = 0; j < havelen && *olenp < maxlen; j++, k++) { const int band = (k % bands) * dev->horizontal; const int x = k % linesize / bands; const int y = k / linesize - y_off; /* y relative to buffer head */ const int y_rly = y + y_off + dev->y_off; /* global y */ if (x < dev->para.pixels_per_line && y_rly < dev->para.lines) { *buf++ = dev->data[(dev->dataoff + band + x + y * linesize) & DATAMASK]; (*olenp)++; } } dev->dataindex = k; /* how much full lines are finished */ return (k / linesize - y_off) * linesize; } SANE_Status sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp) { SANE_Status status; struct device *dev = h; DBG(3, "%s: %p, %p, %d, %p\n", __func__, h, buf, maxlen, (void *)lenp); if (lenp) *lenp = 0; if (!dev) return SANE_STATUS_INVAL; if (!dev->scanning) return SANE_STATUS_EOF; /* if there is no data to read or output from buffer */ if (!dev->blocklen && dev->datalen <= PADDING_SIZE) { /* copying uncompressed data */ if (dev->composition == MODE_RGB24 && isSupportedDevice(dev) && dev->decDataSize > 0) { int diff = dev->total_img_size - dev->total_out_size; int bufLen = (diff < maxlen) ? diff : maxlen; if (0 < diff && 0 < copy_decompress_data(dev, buf, bufLen, lenp)) { dev->total_out_size += *lenp; return SANE_STATUS_GOOD; } } /* and we don't need to acquire next block */ if (dev->final_block) { int slack = dev->total_img_size - dev->total_out_size; /* but we may need to fill slack */ if (buf && lenp && slack > 0) { *lenp = fill_slack(dev, buf, maxlen); dev->total_out_size += *lenp; DBG(9, "<> slack: %d, filled: %d, maxlen %d\n", slack, *lenp, maxlen); return SANE_STATUS_GOOD; } else if (slack < 0) { /* this will never happen */ DBG(1, "image overflow %d bytes\n", dev->total_img_size - dev->total_out_size); } if (isSupportedDevice(dev) && dev->composition == MODE_RGB24) { remove(encTmpFileName); } /* that's all */ dev_stop(dev); return SANE_STATUS_EOF; } /* queue next image block */ if (!dev_acquire(dev)) return dev->state; } if (!dev->reading) { if (cancelled(dev)) return dev->state; DBG(5, "READ_IMAGE\n"); if (!dev_cmd(dev, CMD_READ_IMAGE)) return SANE_STATUS_IO_ERROR; dev->reading++; dev->ulines += dev->vertical; dev->y_off = dev->ulines - dev->vertical; dev->total_data_size += dev->blocklen; dev->blocks++; } do { size_t datalen; int clrlen; /* cleared lines len */ int olen; /* output len */ /* read as much data into the buffer */ datalen = DATAROOM(dev) & USB_BLOCK_MASK; while (datalen && dev->blocklen) { SANE_Byte *rbuf = dev->data + DATATAIL(dev); DBG(9, "<> request len: %lu, [%d, %d; %d]\n", (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen); if ((status = dev->io->dev_request(dev, NULL, 0, rbuf, &datalen)) != SANE_STATUS_GOOD) return status; dev->datalen += datalen; dev->blocklen -= datalen; DBG(9, "<> got %lu, [%d, %d; %d]\n", (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen); if (dev->blocklen < 0) return ret_cancel(dev, SANE_STATUS_IO_ERROR); datalen = DATAROOM(dev) & USB_BLOCK_MASK; } if (buf && lenp) { /* read mode */ /* copy will do minimal of valid data */ if (dev->para.format == SANE_FRAME_RGB && dev->line_order) { if (isSupportedDevice(dev)) { clrlen = dump_to_tmp_file(dev); /* decompress after reading entire block data*/ if (0 == dev->blocklen) { decompress_tempfile(dev); } copy_decompress_data(dev, buf, maxlen, &olen); } else { clrlen = copy_mix_bands_trim(dev, buf, maxlen, &olen); } } else clrlen = copy_plain_trim(dev, buf, maxlen, &olen); dev->datalen -= clrlen; dev->dataoff = (dev->dataoff + clrlen) & DATAMASK; buf += olen; maxlen -= olen; *lenp += olen; dev->total_out_size += olen; DBG(9, "<> olen: %d, clrlen: %d, blocklen: %d/%d, maxlen %d (%d %d %d)\n", olen, clrlen, dev->blocklen, dev->datalen, maxlen, dev->dataindex / dev->bytes_per_line + dev->y_off, dev->y_off, dev->para.lines); /* slack beyond last line */ if (dev->dataindex / dev->bytes_per_line + dev->y_off >= dev->para.lines) { dev->datalen = 0; dev->dataoff = 0; } if (!clrlen || maxlen <= 0) break; } else { /* flush mode */ dev->datalen = 0; dev->dataoff = 0; } } while (dev->blocklen); if (lenp) DBG(9, " ==> %d\n", *lenp); return SANE_STATUS_GOOD; } SANE_Status sane_start(SANE_Handle h) { struct device *dev = h; DBG(3, "%s: %p\n", __func__, h); dev->cancel = 0; dev->scanning = 0; dev->total_img_size = 0; dev->total_out_size = 0; dev->total_data_size = 0; dev->blocks = 0; if (!dev->reserved) { if (!dev_cmd_wait(dev, CMD_RESERVE_UNIT)) return dev->state; dev->reserved++; } if (!dev_set_window(dev) || (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY)) return dev_stop(dev); if (!dev_cmd_wait(dev, CMD_OBJECT_POSITION)) return dev_stop(dev); if (!dev_cmd(dev, CMD_READ) || (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY)) return dev_stop(dev); dev->scanning = 1; dev->final_block = 0; dev->blocklen = 0; dev->pixels_per_line = 0; dev->bytes_per_line = 0; dev->ulines = 0; set_parameters(dev); if (!dev->data && !(dev->data = malloc(DATASIZE))) return ret_cancel(dev, SANE_STATUS_NO_MEM); if (!dev->decData && !(dev->decData = malloc(POST_DATASIZE))) return ret_cancel(dev, SANE_STATUS_NO_MEM); if (!dev_acquire(dev)) return dev->state; /* make sure to have dev->para <= of real size */ if (dev->para.pixels_per_line > dev->pixels_per_line) { dev->para.pixels_per_line = dev->pixels_per_line; dev->para.bytes_per_line = dev->pixels_per_line; } if (dev->composition == MODE_RGB24) dev->para.bytes_per_line = dev->para.pixels_per_line * 3; else if (dev->composition == MODE_LINEART || dev->composition == MODE_HALFTONE) { dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8; dev->para.pixels_per_line = dev->para.bytes_per_line * 8; } else { dev->para.bytes_per_line = dev->para.pixels_per_line; } dev->total_img_size = dev->para.bytes_per_line * dev->para.lines; if (isSupportedDevice(dev) && dev->composition == MODE_RGB24) { int fd; remove(encTmpFileName); /* Precreate temporary file in exclusive mode. */ fd = open(encTmpFileName, O_CREAT|O_EXCL, 0600); if (fd == -1) { DBG(3, "%s: %p, can't create temporary file %s: %s\n", __func__, (void *)dev, encTmpFileName, strerror(errno)); return ret_cancel(dev, SANE_STATUS_ACCESS_DENIED); } close(fd); } dev->currentDecDataIndex = 0; return SANE_STATUS_GOOD; } SANE_Status sane_set_io_mode(SANE_Handle h, SANE_Bool non_blocking) { struct device *dev = h; DBG(3, "%s: %p, %d\n", __func__, h, non_blocking); if (non_blocking) return SANE_STATUS_UNSUPPORTED; dev->non_blocking = non_blocking; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd(SANE_Handle h, SANE_Int *fdp) { DBG(3, "%s: %p, %p\n", __func__, h, (void *)fdp); /* supporting of this will require thread creation */ return SANE_STATUS_UNSUPPORTED; } void sane_cancel(SANE_Handle h) { struct device *dev = h; DBG(3, "%s: %p\n", __func__, h); dev->cancel = 1; } /* xerox_mfp.c */ sane-backends-1.0.27/backend/genesys.c0000664000175000017500000071742513072310420014442 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2004, 2005 Gerhard Jaeger Copyright (C) 2004-2016 Stéphane Voltz Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2006 Laurent Charpentier Copyright (C) 2007 Luke Copyright (C) 2010 Chris Berry and Michael Rickmann for Plustek Opticbook 3600 support Dynamic rasterization code was taken from the epjistsu backend by m. allan noah Software processing for deskew, crop and dspeckle are inspired by allan's noah work in the fujitsu backend This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* * SANE backend for Genesys Logic GL646/GL841/GL842/GL843/GL846/GL847/GL124 based scanners */ #define BUILD 2511 #define BACKEND_NAME genesys #include "genesys.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_magic.h" #include "genesys_devices.c" static SANE_Int num_devices = 0; static Genesys_Device *first_dev = 0; static Genesys_Scanner *first_handle = 0; static const SANE_Device **devlist = 0; /* Array of newly attached devices */ static Genesys_Device **new_dev = 0; /* Length of new_dev array */ static SANE_Int new_dev_len = 0; /* Number of entries alloced for new_dev */ static SANE_Int new_dev_alloced = 0; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, /* SANE_TITLE_HALFTONE, currently unused */ SANE_VALUE_SCAN_MODE_LINEART, 0 }; static SANE_String_Const color_filter_list[] = { SANE_I18N ("Red"), SANE_I18N ("Green"), SANE_I18N ("Blue"), 0 }; static SANE_String_Const cis_color_filter_list[] = { SANE_I18N ("Red"), SANE_I18N ("Green"), SANE_I18N ("Blue"), SANE_I18N ("None"), 0 }; static SANE_String_Const source_list[] = { SANE_I18N (FLATBED), SANE_I18N (TRANSPARENCY_ADAPTER), 0 }; static SANE_Range swdespeck_range = { 1, 9, 1 }; static SANE_Range time_range = { 0, /* minimum */ 60, /* maximum */ 0 /* quantization */ }; static const SANE_Range u12_range = { 0, /* minimum */ 4095, /* maximum */ 0 /* quantization */ }; static const SANE_Range u14_range = { 0, /* minimum */ 16383, /* maximum */ 0 /* quantization */ }; static const SANE_Range u16_range = { 0, /* minimum */ 65535, /* maximum */ 0 /* quantization */ }; static const SANE_Range percentage_range = { SANE_FIX (0), /* minimum */ SANE_FIX (100), /* maximum */ SANE_FIX (1) /* quantization */ }; static const SANE_Range threshold_curve_range = { 0, /* minimum */ 127, /* maximum */ 1 /* quantization */ }; /** * range for brightness and contrast */ static const SANE_Range enhance_range = { -100, /* minimum */ 100, /* maximum */ 1 /* quantization */ }; /** * range for expiration time */ static const SANE_Range expiration_range = { -1, /* minimum */ 30000, /* maximum */ 1 /* quantization */ }; void sanei_genesys_init_structs (Genesys_Device * dev) { unsigned int i, sensor_ok = 0, gpo_ok = 0, motor_ok = 0; /* initialize the sensor data stuff */ for (i = 0; i < sizeof (Sensor) / sizeof (Genesys_Sensor); i++) { if (dev->model->ccd_type == Sensor[i].sensor_id) { memcpy (&dev->sensor, &Sensor[i], sizeof (Genesys_Sensor)); sensor_ok = 1; } } /* initialize the GPO data stuff */ for (i = 0; i < sizeof (Gpo) / sizeof (Genesys_Gpo); i++) { if (dev->model->gpo_type == Gpo[i].gpo_id) { memcpy (&dev->gpo, &Gpo[i], sizeof (Genesys_Gpo)); gpo_ok = 1; } } /* initialize the motor data stuff */ for (i = 0; i < sizeof (Motor) / sizeof (Genesys_Motor); i++) { if (dev->model->motor_type == Motor[i].motor_id) { memcpy (&dev->motor, &Motor[i], sizeof (Genesys_Motor)); motor_ok = 1; } } /* sanity check */ if (sensor_ok == 0 || motor_ok == 0 || gpo_ok == 0) { DBG (DBG_error0, "sanei_genesys_init_structs: bad description(s) for ccd/gpo/motor=%d/%d/%d\n", dev->model->ccd_type, dev->model->gpo_type, dev->model->motor_type); } /* set up initial line distance shift */ dev->ld_shift_r = dev->model->ld_shift_r; dev->ld_shift_g = dev->model->ld_shift_g; dev->ld_shift_b = dev->model->ld_shift_b; } void sanei_genesys_init_fe (Genesys_Device * dev) { unsigned int i; DBGSTART; for (i = 0; i < sizeof (Wolfson) / sizeof (Genesys_Frontend); i++) { if (dev->model->dac_type == Wolfson[i].fe_id) { memcpy (&dev->frontend, &Wolfson[i], sizeof (Genesys_Frontend)); return; } } DBG (DBG_error0, "sanei_genesys_init_fe: failed to find description for dac_type %d\n", dev->model->dac_type); DBG (DBG_info, "sanei_genesys_init_fe: dac_type %d set up\n", dev->model->dac_type); DBGCOMPLETED; } /* main function for slope creation */ /** * This function generates a slope table using the given slope * truncated at the given exposure time or step count, whichever comes first. * The reached step time is then stored in final_exposure and used for the rest * of the table. The summed time of the acceleration steps is returned, and the * number of accerelation steps is put into used_steps. * * @param slope_table Table to write to * @param max_steps Size of slope_table in steps * @param use_steps Maximum number of steps to use for acceleration * @param stop_at Minimum step time to use * @param vstart Start step time of default slope * @param vend End step time of default slope * @param steps Step count of default slope * @param g Power for default slope * @param used_steps Final number of steps is stored here * @param vfinal Final step time is stored here * @return Time for acceleration * @note All times in pixel time. Correction for other motor timings is not * done. */ SANE_Int sanei_genesys_generate_slope_table (uint16_t * slope_table, unsigned int max_steps, unsigned int use_steps, uint16_t stop_at, uint16_t vstart, uint16_t vend, unsigned int steps, double g, unsigned int *used_steps, unsigned int *vfinal) { double t; SANE_Int sum = 0; unsigned int i; unsigned int c = 0; uint16_t t2; unsigned int dummy; unsigned int _vfinal; if (!used_steps) used_steps = &dummy; if (!vfinal) vfinal = &_vfinal; DBG (DBG_proc, "sanei_genesys_generate_slope_table: table size: %d\n", max_steps); DBG (DBG_proc, "sanei_genesys_generate_slope_table: stop at time: %d, use %d steps max\n", stop_at, use_steps); DBG (DBG_proc, "sanei_genesys_generate_slope_table: target slope: " "vstart: %d, vend: %d, steps: %d, g: %g\n", vstart, vend, steps, g); sum = 0; c = 0; *used_steps = 0; if (use_steps < 1) use_steps = 1; if (stop_at < vstart) { t2 = vstart; for (i = 0; i < steps && i < use_steps - 1 && i < max_steps; i++, c++) { t = pow (((double) i) / ((double) (steps - 1)), g); t2 = vstart * (1 - t) + t * vend; if (t2 < stop_at) break; *slope_table++ = t2; /* DBG (DBG_io, "slope_table[%3d] = %5d\n", c, t2); */ sum += t2; } if (t2 > stop_at) { DBG (DBG_warn, "Can not reach target speed(%d) in %d steps.\n", stop_at, use_steps); DBG (DBG_warn, "Expect image to be distorted. " "Ignore this if only feeding.\n"); } *vfinal = t2; *used_steps += i; max_steps -= i; } else *vfinal = stop_at; for (i = 0; i < max_steps; i++, c++) { *slope_table++ = *vfinal; /* DBG (DBG_io, "slope_table[%3d] = %5d\n", c, *vfinal); */ } (*used_steps)++; sum += *vfinal; DBG (DBG_proc, "sanei_genesys_generate_slope_table: returns sum=%d, used %d steps, completed\n", sum, *used_steps); return sum; } /* Generate slope table for motor movement */ /** * This function generates a slope table using the slope from the motor struct * truncated at the given exposure time or step count, whichever comes first. * The reached step time is then stored in final_exposure and used for the rest * of the table. The summed time of the acceleration steps is returned, and the * number of accerelation steps is put into used_steps. * * @param dev Device struct * @param slope_table Table to write to * @param max_step Size of slope_table in steps * @param use_steps Maximum number of steps to use for acceleration * @param step_type Generate table for this step_type. 0=>full, 1=>half, * 2=>quarter * @param exposure_time Minimum exposure time of a scan line * @param yres Resolution of a scan line * @param used_steps Final number of steps is stored here * @param final_exposure Final step time is stored here * @param power_mode Power mode (related to the Vref used) of the motor * @return Time for acceleration * @note all times in pixel time */ SANE_Int sanei_genesys_create_slope_table3 (Genesys_Device * dev, uint16_t * slope_table, int max_step, unsigned int use_steps, int step_type, int exposure_time, double yres, unsigned int *used_steps, unsigned int *final_exposure, int power_mode) { unsigned int sum_time = 0; unsigned int vtarget; unsigned int vend; unsigned int vstart; unsigned int vfinal; DBG (DBG_proc, "%s: step_type = %d, " "exposure_time = %d, yres = %g, power_mode = %d\n", __func__, step_type, exposure_time, yres, power_mode); /* final speed */ vtarget = (exposure_time * yres) / dev->motor.base_ydpi; vstart = dev->motor.slopes[power_mode][step_type].maximum_start_speed; vend = dev->motor.slopes[power_mode][step_type].maximum_speed; vtarget >>= step_type; if (vtarget > 65535) vtarget = 65535; vstart >>= step_type; if (vstart > 65535) vstart = 65535; vend >>= step_type; if (vend > 65535) vend = 65535; sum_time = sanei_genesys_generate_slope_table (slope_table, max_step, use_steps, vtarget, vstart, vend, dev->motor.slopes[power_mode][step_type].minimum_steps << step_type, dev->motor.slopes[power_mode][step_type].g, used_steps, &vfinal); if (final_exposure) *final_exposure = (vfinal * dev->motor.base_ydpi) / yres; DBG (DBG_proc, "sanei_genesys_create_slope_table: returns sum_time=%d, completed\n", sum_time); return sum_time; } /* alternate slope table creation function */ /* the hardcoded values (g and vstart) will go in a motor struct */ static SANE_Int genesys_create_slope_table2 (Genesys_Device * dev, uint16_t * slope_table, int steps, int step_type, int exposure_time, SANE_Bool same_speed, double yres, int power_mode) { double t, g; SANE_Int sum = 0; int vstart, vend; int i; DBG (DBG_proc, "sanei_genesys_create_slope_table2: %d steps, step_type = %d, " "exposure_time = %d, same_speed = %d, yres = %.2f, power_mode = %d\n", steps, step_type, exposure_time, same_speed, yres, power_mode); /* start speed */ if (dev->model->motor_type == MOTOR_5345) { if (yres < dev->motor.base_ydpi / 6) vstart = 2500; else vstart = 2000; } else { if (steps == 2) vstart = exposure_time; else if (steps == 3) vstart = 2 * exposure_time; else if (steps == 4) vstart = 1.5 * exposure_time; else if (steps == 120) vstart = 1.81674 * exposure_time; else vstart = exposure_time; } /* final speed */ vend = (exposure_time * yres) / (dev->motor.base_ydpi * (1 << step_type)); /* type=1 : full type=2 : half type=4 : quarter vend * type * base_ydpi / exposure = yres */ /* acceleration */ switch (steps) { case 255: /* test for special case: fast moving slope */ /* todo: a 'fast' boolean parameter should be better */ if (vstart == 2000) g = 0.2013; else g = 0.1677; break; case 120: g = 0.5; break; case 67: g = 0.5; break; case 64: g = 0.2555; break; case 44: g = 0.5; break; case 4: g = 0.5; break; case 3: g = 1; break; case 2: vstart = vend; g = 1; break; default: g = 0.2635; } /* if same speed, no 'g' */ sum = 0; if (same_speed) { for (i = 0; i < 255; i++) { slope_table[i] = vend; sum += slope_table[i]; DBG (DBG_io, "slope_table[%3d] = %5d\n", i, slope_table[i]); } } else { for (i = 0; i < steps; i++) { t = pow (((double) i) / ((double) (steps - 1)), g); slope_table[i] = vstart * (1 - t) + t * vend; DBG (DBG_io, "slope_table[%3d] = %5d\n", i, slope_table[i]); sum += slope_table[i]; } for (i = steps; i < 255; i++) { slope_table[i] = vend; DBG (DBG_io, "slope_table[%3d] = %5d\n", i, slope_table[i]); sum += slope_table[i]; } } DBG (DBG_proc, "sanei_genesys_create_slope_table2: returns sum=%d, completed\n", sum); return sum; } /* Generate slope table for motor movement */ /* todo: check details */ SANE_Int sanei_genesys_create_slope_table (Genesys_Device * dev, uint16_t * slope_table, int steps, int step_type, int exposure_time, SANE_Bool same_speed, double yres, int power_mode) { double t; double start_speed; double g; uint32_t time_period; int sum_time = 0; int i, divider; int same_step; if (dev->model->motor_type == MOTOR_5345 || dev->model->motor_type == MOTOR_HP2300 || dev->model->motor_type == MOTOR_HP2400) return genesys_create_slope_table2 (dev, slope_table, steps, step_type, exposure_time, same_speed, yres, power_mode); DBG (DBG_proc, "sanei_genesys_create_slope_table: %d steps, step_type = %d, " "exposure_time = %d, same_speed =%d\n", steps, step_type, exposure_time, same_speed); DBG (DBG_proc, "sanei_genesys_create_slope_table: yres = %.2f\n", yres); g = 0.6; start_speed = 0.01; same_step = 4; divider = 1 << step_type; time_period = (uint32_t) (yres * exposure_time / dev->motor.base_ydpi /*MOTOR_GEAR */ ); if ((time_period < 2000) && (same_speed)) same_speed = SANE_FALSE; time_period = time_period / divider; if (same_speed) { for (i = 0; i < steps; i++) { slope_table[i] = (uint16_t) time_period; sum_time += time_period; DBG (DBG_io, "slope_table[%d] = %d\n", i, time_period); } DBG (DBG_info, "sanei_genesys_create_slope_table: returns sum_time=%d, completed\n", sum_time); return sum_time; } if (time_period > MOTOR_SPEED_MAX * 5) { g = 1.0; start_speed = 0.05; same_step = 2; } else if (time_period > MOTOR_SPEED_MAX * 4) { g = 0.8; start_speed = 0.04; same_step = 2; } else if (time_period > MOTOR_SPEED_MAX * 3) { g = 0.7; start_speed = 0.03; same_step = 2; } else if (time_period > MOTOR_SPEED_MAX * 2) { g = 0.6; start_speed = 0.02; same_step = 3; } if (dev->model->motor_type == MOTOR_ST24) { steps = 255; switch ((int) yres) { case 2400: g = 0.1672; start_speed = 1.09; break; case 1200: g = 1; start_speed = 6.4; break; case 600: g = 0.1672; start_speed = 1.09; break; case 400: g = 0.2005; start_speed = 20.0 / 3.0 /*7.5 */ ; break; case 300: g = 0.253; start_speed = 2.182; break; case 150: g = 0.253; start_speed = 4.367; break; default: g = 0.262; start_speed = 7.29; } same_step = 1; } if (steps <= same_step) { time_period = (uint32_t) (yres * exposure_time / dev->motor.base_ydpi /*MOTOR_GEAR */ ); time_period = time_period / divider; if (time_period > 65535) time_period = 65535; for (i = 0; i < same_step; i++) { slope_table[i] = (uint16_t) time_period; sum_time += time_period; DBG (DBG_io, "slope_table[%d] = %d\n", i, time_period); } DBG (DBG_proc, "sanei_genesys_create_slope_table: returns sum_time=%d, completed\n", sum_time); return sum_time; } for (i = 0; i < steps; i++) { double j = ((double) i) - same_step + 1; /* start from 1/16 speed */ if (j <= 0) t = 0; else t = pow (j / (steps - same_step), g); time_period = /* time required for full steps */ (uint32_t) (yres * exposure_time / dev->motor.base_ydpi /*MOTOR_GEAR */ * (start_speed + (1 - start_speed) * t)); time_period = time_period / divider; if (time_period > 65535) time_period = 65535; slope_table[i] = (uint16_t) time_period; sum_time += time_period; DBG (DBG_io, "slope_table[%d] = %d\n", i, slope_table[i]); } DBG (DBG_proc, "sanei_genesys_create_slope_table: returns sum_time=%d, completed\n", sum_time); return sum_time; } /** @brief computes gamma table * Generates a gamma table of the given length within 0 and the given * maximum value * @param gamma_table gamma table to fill * @param size size of the table * @param maximum value allowed for gamma * @param gamma_max maximum gamma value * @param gamma gamma to compute values * @return a gamma table filled with the computed values * */ void sanei_genesys_create_gamma_table (uint16_t * gamma_table, int size, float maximum, float gamma_max, float gamma) { int i; float value; if(gamma_table==NULL) { DBG (DBG_proc, "sanei_genesys_create_gamma_table: gamma table is NULL\n"); return; } DBG (DBG_proc, "sanei_genesys_create_gamma_table: size = %d, " "maximum = %g, gamma_max = %g, gamma = %g\n", size, maximum, gamma_max, gamma); for (i = 0; i < size; i++) { value = gamma_max * pow ((float) i / size, 1.0 / gamma); if (value > maximum) value = maximum; gamma_table[i] = value; } DBG (DBG_proc, "sanei_genesys_create_gamma_table: completed\n"); } /* computes the exposure_time on the basis of the given vertical dpi, the number of pixels the ccd needs to send, the step_type and the corresponding maximum speed from the motor struct */ /* Currently considers maximum motor speed at given step_type, minimum line exposure needed for conversion and led exposure time. TODO: Should also consider maximum transfer rate: ~6.5MB/s. Note: The enhance option of the scanners does _not_ help. It only halves the amount of pixels transfered. */ SANE_Int sanei_genesys_exposure_time2 (Genesys_Device * dev, float ydpi, int step_type, int endpixel, int exposure_by_led, int power_mode) { int exposure_by_ccd = endpixel + 32; int exposure_by_motor = (dev->motor.slopes[power_mode][step_type].maximum_speed * dev->motor.base_ydpi) / ydpi; int exposure = exposure_by_ccd; if (exposure < exposure_by_motor) exposure = exposure_by_motor; if (exposure < exposure_by_led && dev->model->is_cis) exposure = exposure_by_led; DBG (DBG_info, "%s: ydpi=%d, step=%d, endpixel=%d led=%d, power=%d => exposure=%d\n", __func__, (int)ydpi, step_type, endpixel, exposure_by_led, power_mode, exposure); return exposure; } /* computes the exposure_time on the basis of the given horizontal dpi */ /* we will clean/simplify it by using constants from a future motor struct */ SANE_Int sanei_genesys_exposure_time (Genesys_Device * dev, Genesys_Register_Set * reg, int xdpi) { if (dev->model->motor_type == MOTOR_5345) { if (dev->model->cmd_set->get_filter_bit (reg)) { /* monochrome */ switch (xdpi) { case 600: return 8500; case 500: case 400: case 300: case 250: case 200: case 150: return 5500; case 100: return 6500; case 50: return 12000; default: return 11000; } } else { /* color scan */ switch (xdpi) { case 300: case 250: case 200: return 5500; case 50: return 12000; default: return 11000; } } } else if (dev->model->motor_type == MOTOR_HP2400) { if (dev->model->cmd_set->get_filter_bit (reg)) { /* monochrome */ switch (xdpi) { case 200: return 7210; default: return 11111; } } else { /* color scan */ switch (xdpi) { case 600: return 8751; /*11902; 19200 */ default: return 11111; } } } else if (dev->model->motor_type == MOTOR_HP2300) { if (dev->model->cmd_set->get_filter_bit (reg)) { /* monochrome */ switch (xdpi) { case 600: return 8699; /* 3200; */ case 300: return 3200; /*10000;, 3200 -> too dark */ case 150: return 4480; /* 3200 ???, warmup needs 4480 */ case 75: return 5500; default: return 11111; } } else { /* color scan */ switch (xdpi) { case 600: return 8699; case 300: return 4349; case 150: case 75: return 4480; default: return 11111; } } } return dev->settings.exposure_time; } /* Sends a block of shading information to the scanner. The data is placed at address 0x0000 for color mode, gray mode and unconditionally for the following CCD chips: HP2300, HP2400 and HP5345 In the other cases (lineart, halftone on ccd chips not mentioned) the addresses are 0x2a00 for dpihw==0, 0x5500 for dpihw==1 and 0xa800 for dpihw==2. //Note: why this? The data needs to be of size "size", and in little endian byte order. */ #ifndef UNIT_TESTING static #endif SANE_Status genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data, int size) { int dpihw; int start_address; SANE_Status status; DBG (DBG_proc, "%s: (size = %d)\n", __func__, size); /* ASIC higher than gl843 doesn't have register 2A/2B, so we route to * a per ASIC shading data loading function if available. * It is also used for scanners using SHDAREA */ if(dev->model->cmd_set->send_shading_data!=NULL) { status=dev->model->cmd_set->send_shading_data(dev, data, size); DBGCOMPLETED; return status; } /* gl646, gl84[123] case */ dpihw = sanei_genesys_read_reg_from_set (dev->reg, 0x05) >> 6; /* TODO invert the test so only the 2 models behaving like that are * tested instead of adding all the others */ /* many scanners send coefficient for lineart/gray like in color mode */ if (dev->settings.scan_mode < 2 && dev->model->ccd_type != CCD_PLUSTEK3800 && dev->model->ccd_type != CCD_KVSS080 && dev->model->ccd_type != CCD_G4050 && dev->model->ccd_type != CCD_CS4400F && dev->model->ccd_type != CCD_CS8400F && dev->model->ccd_type != CCD_DSMOBILE600 && dev->model->ccd_type != CCD_XP300 && dev->model->ccd_type != CCD_DP665 && dev->model->ccd_type != CCD_DP685 && dev->model->ccd_type != CIS_CANONLIDE80 && dev->model->ccd_type != CCD_ROADWARRIOR && dev->model->ccd_type != CCD_HP2300 && dev->model->ccd_type != CCD_HP2400 && dev->model->ccd_type != CCD_HP3670 && dev->model->ccd_type != CCD_5345) /* lineart, halftone */ { if (dpihw == 0) /* 600 dpi */ start_address = 0x02a00; else if (dpihw == 1) /* 1200 dpi */ start_address = 0x05500; else if (dpihw == 2) /* 2400 dpi */ start_address = 0x0a800; else /* reserved */ return SANE_STATUS_INVAL; } else /* color */ start_address = 0x00; status = sanei_genesys_set_buffer_address (dev, start_address); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to set buffer address: %s\n", __func__, sane_strstatus (status)); return status; } status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, data, size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to send shading table: %s\n", __func__, sane_strstatus (status)); return status; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /* ? */ SANE_Status sanei_genesys_init_shading_data (Genesys_Device * dev, int pixels_per_line) { SANE_Status status; uint8_t *shading_data, *shading_data_ptr; int channels; int i; /* these models don't need to init shading data due to the use of specific send shading data function */ if (dev->model->ccd_type==CCD_KVSS080 || dev->model->ccd_type==CCD_G4050 || dev->model->ccd_type==CCD_CS4400F || dev->model->ccd_type==CCD_CS8400F || dev->model->cmd_set->send_shading_data!=NULL) return SANE_STATUS_GOOD; DBG (DBG_proc, "sanei_genesys_init_shading_data (pixels_per_line = %d)\n", pixels_per_line); if (dev->settings.scan_mode >= 2) /* 3 pass or single pass color */ channels = 3; else channels = 1; shading_data = malloc (pixels_per_line * 4 * channels); /* 16 bit black, 16 bit white */ if (!shading_data) { DBG (DBG_error, "sanei_genesys_init_shading_data: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } shading_data_ptr = shading_data; for (i = 0; i < pixels_per_line * channels; i++) { *shading_data_ptr++ = 0x00; /* dark lo */ *shading_data_ptr++ = 0x00; /* dark hi */ *shading_data_ptr++ = 0x00; /* white lo */ *shading_data_ptr++ = 0x40; /* white hi -> 0x4000 */ } status = genesys_send_offset_and_shading (dev, shading_data, pixels_per_line * 4 * channels); free (shading_data); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to send shading data: %s\n", __func__, sane_strstatus (status)); } DBGCOMPLETED; return status; } /* Find the position of the reference point: takes gray level 8 bits data and find first CCD usable pixel and top of scanning area */ SANE_Status sanei_genesys_search_reference_point (Genesys_Device * dev, uint8_t * data, int start_pixel, int dpi, int width, int height) { int x, y; int current, left, top = 0; uint8_t *image; int size, count; int level = 80; /* edge threshold level */ /*sanity check */ if ((width < 3) || (height < 3)) return SANE_STATUS_INVAL; /* transformed image data */ size = width * height; image = malloc (size); if (!image) { DBG (DBG_error, "sanei_genesys_search_reference_point: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } /* laplace filter to denoise picture */ memcpy (image, data, size); /* to initialize unprocessed part of the image buffer */ for (y = 1; y < height - 1; y++) for (x = 1; x < width - 1; x++) { image[y * width + x] = (data[(y - 1) * width + x + 1] + 2 * data[(y - 1) * width + x] + data[(y - 1) * width + x - 1] + 2 * data[y * width + x + 1] + 4 * data[y * width + x] + 2 * data[y * width + x - 1] + data[(y + 1) * width + x + 1] + 2 * data[(y + 1) * width + x] + data[(y + 1) * width + x - 1]) / 16; } memcpy (data, image, size); if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("laplace.pnm", image, 8, 1, width, height); /* apply X direction sobel filter -1 0 1 -2 0 2 -1 0 1 and finds threshold level */ level = 0; for (y = 2; y < height - 2; y++) for (x = 2; x < width - 2; x++) { current = data[(y - 1) * width + x + 1] - data[(y - 1) * width + x - 1] + 2 * data[y * width + x + 1] - 2 * data[y * width + x - 1] + data[(y + 1) * width + x + 1] - data[(y + 1) * width + x - 1]; if (current < 0) current = -current; if (current > 255) current = 255; image[y * width + x] = current; if (current > level) level = current; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("xsobel.pnm", image, 8, 1, width, height); /* set up detection level */ level = level / 3; /* find left black margin first todo: search top before left we average the result of N searches */ left = 0; count = 0; for (y = 2; y < 11; y++) { x = 8; while ((x < width / 2) && (image[y * width + x] < level)) { image[y * width + x] = 255; x++; } count++; left += x; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("detected-xsobel.pnm", image, 8, 1, width, height); left = left / count; /* turn it in CCD pixel at full sensor optical resolution */ dev->sensor.CCD_start_xoffset = start_pixel + (left * dev->sensor.optical_res) / dpi; /* find top edge by detecting black strip */ /* apply Y direction sobel filter -1 -2 -1 0 0 0 1 2 1 */ level = 0; for (y = 2; y < height - 2; y++) for (x = 2; x < width - 2; x++) { current = -data[(y - 1) * width + x + 1] - 2 * data[(y - 1) * width + x] - data[(y - 1) * width + x - 1] + data[(y + 1) * width + x + 1] + 2 * data[(y + 1) * width + x] + data[(y + 1) * width + x - 1]; if (current < 0) current = -current; if (current > 255) current = 255; image[y * width + x] = current; if (current > level) level = current; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("ysobel.pnm", image, 8, 1, width, height); /* set up detection level */ level = level / 3; /* search top of horizontal black stripe : TODO yet another flag */ if (dev->model->ccd_type == CCD_5345 && dev->model->motor_type == MOTOR_5345) { top = 0; count = 0; for (x = width / 2; x < width - 1; x++) { y = 2; while ((y < height) && (image[x + y * width] < level)) { image[y * width + x] = 255; y++; } count++; top += y; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("detected-ysobel.pnm", image, 8, 1, width, height); top = top / count; /* bottom of black stripe is of fixed witdh, this hardcoded value * will be moved into device struct if more such values are needed */ top += 10; dev->model->y_offset_calib = SANE_FIX ((top * MM_PER_INCH) / dpi); DBG (DBG_info, "sanei_genesys_search_reference_point: black stripe y_offset = %f mm \n", SANE_UNFIX (dev->model->y_offset_calib)); } /* find white corner in dark area : TODO yet another flag */ if ((dev->model->ccd_type == CCD_HP2300 && dev->model->motor_type == MOTOR_HP2300) || (dev->model->ccd_type == CCD_HP2400 && dev->model->motor_type == MOTOR_HP2400) || (dev->model->ccd_type == CCD_HP3670 && dev->model->motor_type == MOTOR_HP3670)) { top = 0; count = 0; for (x = 10; x < 60; x++) { y = 2; while ((y < height) && (image[x + y * width] < level)) y++; top += y; count++; } top = top / count; dev->model->y_offset_calib = SANE_FIX ((top * MM_PER_INCH) / dpi); DBG (DBG_info, "sanei_genesys_search_reference_point: white corner y_offset = %f mm\n", SANE_UNFIX (dev->model->y_offset_calib)); } free (image); DBG (DBG_proc, "sanei_genesys_search_reference_point: CCD_start_xoffset = %d, left = %d, top = %d\n", dev->sensor.CCD_start_xoffset, left, top); return SANE_STATUS_GOOD; } void sanei_genesys_calculate_zmode2 (SANE_Bool two_table, uint32_t exposure_time, uint16_t * slope_table, int reg21, int move, int reg22, uint32_t * z1, uint32_t * z2) { int i; int sum; DBG (DBG_info, "sanei_genesys_calculate_zmode2: two_table=%d\n", two_table); /* acceleration total time */ sum = 0; for (i = 0; i < reg21; i++) sum += slope_table[i]; /* compute Z1MOD */ /* c=sum(slope_table;reg21) d=reg22*cruising speed Z1MOD=(c+d) % exposure_time */ *z1 = (sum + reg22 * slope_table[reg21 - 1]) % exposure_time; /* compute Z2MOD */ /* a=sum(slope_table;reg21), b=move or 1 if 2 tables */ /* Z2MOD=(a+b) % exposure_time */ if (!two_table) sum = sum + (move * slope_table[reg21 - 1]); else sum = sum + slope_table[reg21 - 1]; *z2 = sum % exposure_time; } /* huh? */ /* todo: double check */ /* Z1 and Z2 seem to be a time to synchronize with clock or a phase correction */ /* steps_sum is the result of create_slope_table */ /* last_speed is the last entry of the slope_table */ /* feedl is registers 3d,3e,3f */ /* fastfed is register 02 bit 3 */ /* scanfed is register 1f */ /* fwdstep is register 22 */ /* tgtime is register 6c bit 6+7 >> 6 */ void sanei_genesys_calculate_zmode (uint32_t exposure_time, uint32_t steps_sum, uint16_t last_speed, uint32_t feedl, uint8_t fastfed, uint8_t scanfed, uint8_t fwdstep, uint8_t tgtime, uint32_t * z1, uint32_t * z2) { uint8_t exposure_factor; exposure_factor = pow (2, tgtime); /* todo: originally, this is always 2^0 ! */ /* Z1 is for buffer-full backward forward moving */ *z1 = exposure_factor * ((steps_sum + fwdstep * last_speed) % exposure_time); /* Z2 is for acceleration before scan */ if (fastfed) /* two curve mode */ { *z2 = exposure_factor * ((steps_sum + scanfed * last_speed) % exposure_time); } else /* one curve mode */ { *z2 = exposure_factor * ((steps_sum + feedl * last_speed) % exposure_time); } } static void genesys_adjust_gain (double *applied_multi, uint8_t * new_gain, double multi, uint8_t gain) { double voltage, original_voltage; DBG (DBG_proc, "genesys_adjust_gain: multi=%f, gain=%d\n", multi, gain); voltage = 0.5 + gain * 0.25; original_voltage = voltage; voltage *= multi; *new_gain = (uint8_t) ((voltage - 0.5) * 4); if (*new_gain > 0x0e) *new_gain = 0x0e; voltage = 0.5 + (*new_gain) * 0.25; *applied_multi = voltage / original_voltage; DBG (DBG_proc, "genesys_adjust_gain: orig voltage=%.2f, new voltage=%.2f, " "*applied_multi=%f, *new_gain=%d\n", original_voltage, voltage, *applied_multi, *new_gain); return; } /* todo: is return status necessary (unchecked?) */ static SANE_Status genesys_average_white (Genesys_Device * dev, int channels, int channel, uint8_t * data, int size, int *max_average) { int gain_white_ref, sum, range; int average; int i; DBG (DBG_proc, "genesys_average_white: channels=%d, channel=%d, size=%d\n", channels, channel, size); range = size / 50; if (dev->settings.scan_method == SCAN_METHOD_TRANSPARENCY) /* transparency mode */ gain_white_ref = dev->sensor.fau_gain_white_ref * 256; else gain_white_ref = dev->sensor.gain_white_ref * 256; if (range < 1) range = 1; size = size / (2 * range * channels); data += (channel * 2); *max_average = 0; while (size--) { sum = 0; for (i = 0; i < range; i++) { sum += (*data); sum += *(data + 1) * 256; data += (2 * channels); /* byte based */ } average = (sum / range); if (average > *max_average) *max_average = average; } DBG (DBG_proc, "genesys_average_white: max_average=%d, gain_white_ref = %d, finished\n", *max_average, gain_white_ref); if (*max_average >= gain_white_ref) return SANE_STATUS_INVAL; return SANE_STATUS_GOOD; } /* todo: understand, values are too high */ static int genesys_average_black (Genesys_Device * dev, int channel, uint8_t * data, int pixels) { int i; int sum; int pixel_step; DBG (DBG_proc, "genesys_average_black: channel=%d, pixels=%d\n", channel, pixels); sum = 0; if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ { data += (channel * 2); pixel_step = 3 * 2; } else { pixel_step = 2; } for (i = 0; i < pixels; i++) { sum += *data; sum += *(data + 1) * 256; data += pixel_step; } DBG (DBG_proc, "genesys_average_black = %d\n", sum / pixels); return (int) (sum / pixels); } /* todo: check; it works but the lines 1, 2, and 3 are too dark even with the same offset and gain settings? */ static SANE_Status genesys_coarse_calibration (Genesys_Device * dev) { int size; int black_pixels; int white_average; int channels; SANE_Status status; uint8_t offset[4] = { 0xa0, 0x00, 0xa0, 0x40 }; /* first value isn't used */ uint16_t white[12], dark[12]; int i, j; uint8_t *calibration_data, *all_data; DBG (DBG_info, "genesys_coarse_calibration (scan_mode = %d)\n", dev->settings.scan_mode); black_pixels = dev->sensor.black_pixels * dev->settings.xres / dev->sensor.optical_res; if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; DBG (DBG_info, "channels %d y_size %d xres %d\n", channels, dev->model->y_size, dev->settings.xres); size = channels * 2 * SANE_UNFIX (dev->model->y_size) * dev->settings.xres / 25.4; /* 1 1 mm 1/inch inch/mm */ calibration_data = malloc (size); if (!calibration_data) { DBG (DBG_error, "genesys_coarse_calibration: failed to allocate memory(%d bytes)\n", size); return SANE_STATUS_NO_MEM; } all_data = calloc (1, size * 4); status = dev->model->cmd_set->set_fe (dev, AFE_INIT); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to set frontend: %s\n", __func__, sane_strstatus (status)); free(all_data); free(calibration_data); return status; } dev->frontend.sign[0] = 0; dev->frontend.sign[1] = 0; dev->frontend.sign[2] = 0; dev->frontend.gain[0] = 2; dev->frontend.gain[1] = 2; dev->frontend.gain[2] = 2; /* todo: ? was 2 */ dev->frontend.offset[0] = offset[0]; dev->frontend.offset[1] = offset[0]; dev->frontend.offset[2] = offset[0]; for (i = 0; i < 4; i++) /* read 4 lines */ { if (i < 3) /* first 3 lines */ { dev->frontend.offset[0] = offset[i]; dev->frontend.offset[1] = offset[i]; dev->frontend.offset[2] = offset[i]; } if (i == 1) /* second line */ { double applied_multi; double gain_white_ref; if (dev->settings.scan_method == SCAN_METHOD_TRANSPARENCY) /* Transparency */ gain_white_ref = dev->sensor.fau_gain_white_ref * 256; else gain_white_ref = dev->sensor.gain_white_ref * 256; /* white and black are defined downwards */ genesys_adjust_gain (&applied_multi, &dev->frontend.gain[0], gain_white_ref / (white[0] - dark[0]), dev->frontend.gain[0]); genesys_adjust_gain (&applied_multi, &dev->frontend.gain[1], gain_white_ref / (white[1] - dark[1]), dev->frontend.gain[1]); genesys_adjust_gain (&applied_multi, &dev->frontend.gain[2], gain_white_ref / (white[2] - dark[2]), dev->frontend.gain[2]); dev->frontend.gain[0] = dev->frontend.gain[1] = dev->frontend.gain[2] = 2; status = sanei_genesys_fe_write_data (dev, 0x28, dev->frontend.gain[0]); if (status != SANE_STATUS_GOOD) /* todo: this was 0x28 + 3 ? */ { DBG (DBG_error, "genesys_coarse_calibration: Failed to write gain[0]: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x29, dev->frontend.gain[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: Failed to write gain[1]: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x2a, dev->frontend.gain[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: Failed to write gain[2]: %s\n", sane_strstatus (status)); return status; } } if (i == 3) /* last line */ { double x, y, rate; for (j = 0; j < 3; j++) { x = (double) (dark[(i - 2) * 3 + j] - dark[(i - 1) * 3 + j]) * 254 / (offset[i - 1] / 2 - offset[i - 2] / 2); y = x - x * (offset[i - 1] / 2) / 254 - dark[(i - 1) * 3 + j]; rate = (x - DARK_VALUE - y) * 254 / x + 0.5; dev->frontend.offset[j] = (uint8_t) (rate); if (dev->frontend.offset[j] > 0x7f) dev->frontend.offset[j] = 0x7f; dev->frontend.offset[j] <<= 1; } } status = sanei_genesys_fe_write_data (dev, 0x20, dev->frontend.offset[0]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: Failed to write offset[0]: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x21, dev->frontend.offset[1]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: Failed to write offset[1]: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_fe_write_data (dev, 0x22, dev->frontend.offset[2]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: Failed to write offset[2]: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "genesys_coarse_calibration: doing scan: sign: %d/%d/%d, gain: %d/%d/%d, offset: %d/%d/%d\n", dev->frontend.sign[0], dev->frontend.sign[1], dev->frontend.sign[2], dev->frontend.gain[0], dev->frontend.gain[1], dev->frontend.gain[2], dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); status = dev->model->cmd_set->begin_scan (dev, dev->calib_reg, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: Failed to begin scan: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_read_data_from_scanner (dev, calibration_data, size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: Failed to read data: %s\n", sane_strstatus (status)); return status; } memcpy (all_data + i * size, calibration_data, size); if (i == 3) /* last line */ { SANE_Byte *all_data_8 = malloc (size * 4 / 2); unsigned int count; for (count = 0; count < (unsigned int) (size * 4 / 2); count++) all_data_8[count] = all_data[count * 2 + 1]; status = sanei_genesys_write_pnm_file ("coarse.pnm", all_data_8, 8, channels, size / 6, 4); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: sanei_genesys_write_pnm_file failed: %s\n", sane_strstatus (status)); return status; } } status = dev->model->cmd_set->end_scan (dev, dev->calib_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_coarse_calibration: Failed to end scan: %s\n", sane_strstatus (status)); return status; } if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ { for (j = 0; j < 3; j++) { genesys_average_white (dev, 3, j, calibration_data, size, &white_average); white[i * 3 + j] = white_average; dark[i * 3 + j] = genesys_average_black (dev, j, calibration_data, black_pixels); DBG (DBG_info, "genesys_coarse_calibration: white[%d]=%d, black[%d]=%d\n", i * 3 + j, white[i * 3 + j], i * 3 + j, dark[i * 3 + j]); } } else /* one color-component modes */ { genesys_average_white (dev, 1, 0, calibration_data, size, &white_average); white[i * 3 + 0] = white[i * 3 + 1] = white[i * 3 + 2] = white_average; dark[i * 3 + 0] = dark[i * 3 + 1] = dark[i * 3 + 2] = genesys_average_black (dev, 0, calibration_data, black_pixels); } if (i == 3) { if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ { /* todo: huh? */ dev->dark[0] = (uint16_t) (1.6925 * dark[i * 3 + 0] + 0.1895 * 256); dev->dark[1] = (uint16_t) (1.4013 * dark[i * 3 + 1] + 0.3147 * 256); dev->dark[2] = (uint16_t) (1.2931 * dark[i * 3 + 2] + 0.1558 * 256); } else /* one color-component modes */ { switch (dev->settings.color_filter) { case 0: default: dev->dark[0] = (uint16_t) (1.6925 * dark[i * 3 + 0] + (1.1895 - 1.0) * 256); dev->dark[1] = dev->dark[2] = dev->dark[0]; break; case 1: dev->dark[1] = (uint16_t) (1.4013 * dark[i * 3 + 1] + (1.3147 - 1.0) * 256); dev->dark[0] = dev->dark[2] = dev->dark[1]; break; case 2: dev->dark[2] = (uint16_t) (1.2931 * dark[i * 3 + 2] + (1.1558 - 1.0) * 256); dev->dark[0] = dev->dark[1] = dev->dark[2]; break; } } } } /* for (i = 0; i < 4; i++) */ free(all_data); DBG (DBG_info, "genesys_coarse_calibration: final: sign: %d/%d/%d, gain: %d/%d/%d, offset: %d/%d/%d\n", dev->frontend.sign[0], dev->frontend.sign[1], dev->frontend.sign[2], dev->frontend.gain[0], dev->frontend.gain[1], dev->frontend.gain[2], dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); DBGCOMPLETED; return status; } /* Averages image data. average_data and calibration_data are little endian 16 bit words. */ #ifndef UNIT_TESTING static #endif void genesys_average_data (uint8_t * average_data, uint8_t * calibration_data, uint32_t lines, uint32_t pixel_components_per_line) { uint32_t x, y; uint32_t sum; for (x = 0; x < pixel_components_per_line; x++) { sum = 0; for (y = 0; y < lines; y++) { sum += calibration_data[(x + y * pixel_components_per_line) * 2]; sum += calibration_data[(x + y * pixel_components_per_line) * 2 + 1] * 256; } sum /= lines; *average_data++ = sum & 255; *average_data++ = sum / 256; } } /** * scans a white area with motor and lamp off to get the per CCD pixel offset * that will be used to compute shading coefficient * @param dev scanner's device * @return SANE_STATUS_GOOD if OK, else an error */ static SANE_Status genesys_dark_shading_calibration (Genesys_Device * dev) { SANE_Status status; size_t size; uint32_t pixels_per_line; uint8_t channels; uint8_t *calibration_data; SANE_Bool motor; DBGSTART; /* end pixel - start pixel */ pixels_per_line = dev->calib_pixels; channels = dev->calib_channels; FREE_IFNOT_NULL (dev->dark_average_data); dev->average_size = channels * 2 * pixels_per_line; dev->dark_average_data = malloc (dev->average_size); if (!dev->dark_average_data) { DBG (DBG_error, "genesys_dark_shading_calibration: failed to allocate average memory\n"); return SANE_STATUS_NO_MEM; } /* size is size in bytes for scanarea: bytes_per_line * lines */ size = channels * 2 * pixels_per_line * (dev->calib_lines + 1); calibration_data = malloc (size); if (!calibration_data) { DBG (DBG_error, "genesys_dark_shading_calibration: failed to allocate calibration data memory\n"); return SANE_STATUS_NO_MEM; } motor=SANE_TRUE; if (dev->model->flags & GENESYS_FLAG_SHADING_NO_MOVE) { motor=SANE_FALSE; } /* turn off motor and lamp power for flatbed scanners, but not for sheetfed scanners * because they have a calibration sheet with a sufficient black strip */ if (dev->model->is_sheetfed == SANE_FALSE) { dev->model->cmd_set->set_lamp_power (dev, dev->calib_reg, SANE_FALSE); dev->model->cmd_set->set_motor_power (dev->calib_reg, motor); } else { dev->model->cmd_set->set_lamp_power (dev, dev->calib_reg, SANE_TRUE); dev->model->cmd_set->set_motor_power (dev->calib_reg, motor); } status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, dev->model-> cmd_set->bulk_full_size ()); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "genesys_dark_shading_calibration: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } usleep (200 * 1000); /* wait 200 ms: lamp needs some time to get dark */ status = dev->model->cmd_set->begin_scan (dev, dev->calib_reg, SANE_FALSE); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "genesys_dark_shading_calibration: Failed to begin scan: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_read_data_from_scanner (dev, calibration_data, size); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "genesys_dark_shading_calibration: failed to read data: %s\n", sane_strstatus (status)); return status; } status = dev->model->cmd_set->end_scan (dev, dev->calib_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "genesys_dark_shading_calibration: failed to end scan: %s\n", sane_strstatus (status)); return status; } genesys_average_data (dev->dark_average_data, calibration_data, dev->calib_lines, pixels_per_line * channels); if (DBG_LEVEL >= DBG_data) { sanei_genesys_write_pnm_file ("black_shading.pnm", calibration_data, 16, channels, pixels_per_line, dev->calib_lines); sanei_genesys_write_pnm_file ("black_average.pnm", dev->dark_average_data, 16, channels, pixels_per_line, 1); } free (calibration_data); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* * this function builds dummy dark calibration data so that we can * compute shading coefficient in a clean way * todo: current values are hardcoded, we have to find if they * can be computed from previous calibration data (when doing offset * calibration ?) */ static SANE_Status genesys_dummy_dark_shading (Genesys_Device * dev) { uint32_t pixels_per_line; uint8_t channels; uint32_t x, skip, xend; int dummy1, dummy2, dummy3; /* dummy black average per channel */ DBGSTART; pixels_per_line = dev->calib_pixels; channels = dev->calib_channels; FREE_IFNOT_NULL (dev->dark_average_data); dev->average_size = channels * 2 * pixels_per_line; dev->dark_average_data = malloc (dev->average_size); if (!dev->dark_average_data) { DBG (DBG_error, "genesys_dummy_dark_shading: failed to allocate average memory\n"); return SANE_STATUS_NO_MEM; } memset (dev->dark_average_data, 0x00, channels * 2 * pixels_per_line); /* we average values on 'the left' where CCD pixels are under casing and give darkest values. We then use these as dummy dark calibration */ if (dev->settings.xres <= dev->sensor.optical_res / 2) { skip = 4; xend = 36; } else { skip = 4; xend = 68; } if (dev->model->ccd_type==CCD_G4050 || dev->model->ccd_type==CCD_CS4400F || dev->model->ccd_type==CCD_CS8400F || dev->model->ccd_type==CCD_KVSS080) { skip = 2; xend = dev->sensor.black_pixels; } /* average each channels on half left margin */ dummy1 = 0; dummy2 = 0; dummy3 = 0; for (x = skip + 1; x <= xend; x++) { dummy1 += dev->white_average_data[channels * 2 * x] + 256 * dev->white_average_data[channels * 2 * x + 1]; if (channels > 1) { dummy2 += (dev->white_average_data[channels * 2 * x + 2] + 256 * dev->white_average_data[channels * 2 * x + 3]); dummy3 += (dev->white_average_data[channels * 2 * x + 4] + 256 * dev->white_average_data[channels * 2 * x + 5]); } } dummy1 /= (xend - skip); if (channels > 1) { dummy2 /= (xend - skip); dummy3 /= (xend - skip); } DBG (DBG_proc, "genesys_dummy_dark_shading: dummy1=%d, dummy2=%d, dummy3=%d \n", dummy1, dummy2, dummy3); /* fill dark_average */ for (x = 0; x < pixels_per_line; x++) { dev->dark_average_data[channels * 2 * x] = dummy1 & 0xff; dev->dark_average_data[channels * 2 * x + 1] = dummy1 >> 8; if (channels > 1) { dev->dark_average_data[channels * 2 * x + 2] = dummy2 & 0xff; dev->dark_average_data[channels * 2 * x + 3] = dummy2 >> 8; dev->dark_average_data[channels * 2 * x + 4] = dummy3 & 0xff; dev->dark_average_data[channels * 2 * x + 5] = dummy3 >> 8; } } DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status genesys_white_shading_calibration (Genesys_Device * dev) { SANE_Status status; size_t size; uint32_t pixels_per_line; uint8_t *calibration_data; uint8_t channels; SANE_Bool motor; DBG (DBG_proc, "genesys_white_shading_calibration (lines = %d)\n", (unsigned int)dev->calib_lines); pixels_per_line = dev->calib_pixels; channels = dev->calib_channels; if (dev->white_average_data) free (dev->white_average_data); dev->white_average_data = malloc (channels * 2 * pixels_per_line); if (!dev->white_average_data) { DBG (DBG_error, "genesys_white_shading_calibration: failed to allocate average memory\n"); return SANE_STATUS_NO_MEM; } size = channels * 2 * pixels_per_line * (dev->calib_lines + 1); calibration_data = malloc (size); if (!calibration_data) { DBG (DBG_error, "genesys_white_shading_calibration: failed to allocate calibration memory\n"); return SANE_STATUS_NO_MEM; } motor=SANE_TRUE; if (dev->model->flags & GENESYS_FLAG_SHADING_NO_MOVE) { motor=SANE_FALSE; } /* turn on motor and lamp power */ dev->model->cmd_set->set_lamp_power (dev, dev->calib_reg, SANE_TRUE); dev->model->cmd_set->set_motor_power (dev->calib_reg, motor); /* if needed, go back before doin next scan, by using rewind, registers and * slopes table are kept intact from previous scan */ if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK && dev->model->cmd_set->rewind) { status = dev->model->cmd_set->rewind (dev); } status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, dev->model-> cmd_set->bulk_full_size ()); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "genesys_white_shading_calibration: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION) usleep (500 * 1000); /* wait 500ms to make sure lamp is bright again */ status = dev->model->cmd_set->begin_scan (dev, dev->calib_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "genesys_white_shading_calibration: Failed to begin scan: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_read_data_from_scanner (dev, calibration_data, size); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "genesys_white_shading_calibration: failed to read data: %s\n", sane_strstatus (status)); return status; } status = dev->model->cmd_set->end_scan (dev, dev->calib_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "genesys_white_shading_calibration: failed to end scan: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("white_shading.pnm", calibration_data, 16, channels, pixels_per_line, dev->calib_lines); genesys_average_data (dev->white_average_data, calibration_data, dev->calib_lines, pixels_per_line * channels); if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("white_average.pnm", dev->white_average_data, 16, channels, pixels_per_line, 1); free (calibration_data); /* in case we haven't done dark calibration, build dummy data from white_average */ if (!(dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION)) { status = genesys_dummy_dark_shading (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_white_shading_calibration: failed to do dummy dark shading calibration: %s\n", sane_strstatus (status)); return status; } } if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK) { status = dev->model->cmd_set->slow_back_home (dev, SANE_TRUE); } DBGCOMPLETED; return status; } /* This calibration uses a scan over the calibration target, comprising a * black and a white strip. (So the motor must be on.) */ #ifndef UNIT_TESTING static #endif SANE_Status genesys_dark_white_shading_calibration (Genesys_Device * dev) { SANE_Status status; size_t size; uint32_t pixels_per_line; uint8_t *calibration_data, *average_white, *average_dark; uint8_t channels; unsigned int x; int y; uint32_t dark, white, dark_sum, white_sum, dark_count, white_count, col, dif; SANE_Bool motor; DBG (DBG_proc, "%s: (lines = %d)\n", __func__, (unsigned int)dev->calib_lines); pixels_per_line = dev->calib_pixels; channels = dev->calib_channels; if (dev->white_average_data) free (dev->white_average_data); dev->average_size = channels * 2 * pixels_per_line; dev->white_average_data = malloc (dev->average_size); if (!dev->white_average_data) { DBG (DBG_error, "%s: failed to allocate white average memory\n", __func__); return SANE_STATUS_NO_MEM; } if (dev->dark_average_data) free (dev->dark_average_data); dev->dark_average_data = malloc (channels * 2 * pixels_per_line); if (!dev->dark_average_data) { DBG (DBG_error, "%s: failed to allocate dark average memory\n", __func__); return SANE_STATUS_NO_MEM; } size = channels * 2 * pixels_per_line * dev->calib_lines; calibration_data = malloc (size); if (!calibration_data) { DBG (DBG_error, "%s: failed to allocate calibration memory\n", __func__); return SANE_STATUS_NO_MEM; } motor=SANE_TRUE; if (dev->model->flags & GENESYS_FLAG_SHADING_NO_MOVE) { motor=SANE_FALSE; } /* turn on motor and lamp power */ dev->model->cmd_set->set_lamp_power (dev, dev->calib_reg, SANE_TRUE); dev->model->cmd_set->set_motor_power (dev->calib_reg, motor); status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, dev->model-> cmd_set->bulk_full_size ()); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __func__, sane_strstatus (status)); return status; } status = dev->model->cmd_set->begin_scan (dev, dev->calib_reg, SANE_FALSE); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "%s: failed to begin scan: %s\n", __func__, sane_strstatus (status)); return status; } status = sanei_genesys_read_data_from_scanner (dev, calibration_data, size); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "%s: failed to read data: %s\n", __func__, sane_strstatus (status)); return status; } status = dev->model->cmd_set->end_scan (dev, dev->calib_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (calibration_data); DBG (DBG_error, "%s: Failed to end scan: %s\n", __func__, sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) { if (dev->model->is_cis) { sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data, 16, 1, pixels_per_line*channels, dev->calib_lines); } else { sanei_genesys_write_pnm_file ("black_white_shading.pnm", calibration_data, 16, channels, pixels_per_line, dev->calib_lines); } } average_white = dev->white_average_data; average_dark = dev->dark_average_data; for (x = 0; x < pixels_per_line * channels; x++) { dark = 0xffff; white = 0; for (y = 0; y < (int)dev->calib_lines; y++) { col = calibration_data[(x + y * pixels_per_line * channels) * 2]; col |= calibration_data[(x + y * pixels_per_line * channels) * 2 + 1] << 8; if (col > white) white = col; if (col < dark) dark = col; } dif = white - dark; dark = dark + dif / 8; white = white - dif / 8; dark_count = 0; dark_sum = 0; white_count = 0; white_sum = 0; for (y = 0; y < (int)dev->calib_lines; y++) { col = calibration_data[(x + y * pixels_per_line * channels) * 2]; col |= calibration_data[(x + y * pixels_per_line * channels) * 2 + 1] << 8; if (col >= white) { white_sum += col; white_count++; } if (col <= dark) { dark_sum += col; dark_count++; } } dark_sum /= dark_count; white_sum /= white_count; *average_dark++ = dark_sum & 255; *average_dark++ = dark_sum >> 8; *average_white++ = white_sum & 255; *average_white++ = white_sum >> 8; } if (DBG_LEVEL >= DBG_data) { sanei_genesys_write_pnm_file ("white_average.pnm", dev->white_average_data, 16, channels, pixels_per_line, 1); sanei_genesys_write_pnm_file ("dark_average.pnm", dev->dark_average_data, 16, channels, pixels_per_line, 1); } free (calibration_data); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* computes one coefficient given bright-dark value * @param coeff factor giving 1.00 gain * @param target desired target code * @param value brght-dark value * */ static unsigned int compute_coefficient (unsigned int coeff, unsigned int target, unsigned int value) { int result; if (value > 0) { result = (coeff * target) / value; if (result >= 65535) { result = 65535; } } else { result = coeff; } return result; } /** @brief compute shading coefficients for LiDE scanners * The dark/white shading is actually performed _after_ reducing * resolution via averaging. only dark/white shading data for what would be * first pixel at full resolution is used. * * scanner raw input to output value calculation: * o=(i-off)*(gain/coeff) * * from datasheet: * off=dark_average * gain=coeff*bright_target/(bright_average-dark_average) * works for dark_target==0 * * what we want is these: * bright_target=(bright_average-off)*(gain/coeff) * dark_target=(dark_average-off)*(gain/coeff) * leading to * off = (dark_average*bright_target - bright_average*dark_target)/(bright_target - dark_target) * gain = (bright_target - dark_target)/(bright_average - dark_average)*coeff * * @param dev scanner's device * @param shading_data memory area where to store the computed shading coefficients * @param pixels_per_line number of pixels per line * @param words_per_color memory words per color channel * @param channels number of color channels (actually 1 or 3) * @param o shading coefficients left offset * @param coeff 4000h or 2000h depending on fast scan mode or not (GAIN4 bit) * @param target_bright value of the white target code * @param target_dark value of the black target code */ #ifndef UNIT_TESTING static #endif void compute_averaged_planar (Genesys_Device * dev, uint8_t * shading_data, unsigned int pixels_per_line, unsigned int words_per_color, unsigned int channels, unsigned int o, unsigned int coeff, unsigned int target_bright, unsigned int target_dark) { unsigned int x, i, j, br, dk, res, avgpixels, basepixels, val; unsigned int fill,factor; DBG (DBG_info, "%s: pixels=%d, offset=%d\n", __func__, pixels_per_line, o); /* initialize result */ memset (shading_data, 0xff, words_per_color * 3 * 2); /* strangely i can write 0x20000 bytes beginning at 0x00000 without overwriting slope tables - which begin at address 0x10000(for 1200dpi hw mode): memory is organized in words(2 bytes) instead of single bytes. explains quite some things */ /* another one: the dark/white shading is actually performed _after_ reducing resolution via averaging. only dark/white shading data for what would be first pixel at full resolution is used. */ /* scanner raw input to output value calculation: o=(i-off)*(gain/coeff) from datasheet: off=dark_average gain=coeff*bright_target/(bright_average-dark_average) works for dark_target==0 what we want is these: bright_target=(bright_average-off)*(gain/coeff) dark_target=(dark_average-off)*(gain/coeff) leading to off = (dark_average*bright_target - bright_average*dark_target)/(bright_target - dark_target) gain = (bright_target - dark_target)/(bright_average - dark_average)*coeff */ res = dev->settings.xres; /* duplicate half-ccd logic */ if ((dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE) && dev->settings.xres <= dev->sensor.optical_res / 2) res *= 2; /* this should be evenly dividable */ basepixels = dev->sensor.optical_res / res; /* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */ if (basepixels < 1) avgpixels = 1; else if (basepixels < 6) avgpixels = basepixels; else if (basepixels < 8) avgpixels = 6; else if (basepixels < 10) avgpixels = 8; else if (basepixels < 12) avgpixels = 10; else if (basepixels < 15) avgpixels = 12; else avgpixels = 15; /* LiDE80 packs shading data */ if(dev->model->ccd_type != CIS_CANONLIDE80) { factor=1; fill=avgpixels; } else { factor=avgpixels; fill=1; } DBG (DBG_info, "%s: averaging over %d pixels\n", __func__, avgpixels); DBG (DBG_info, "%s: packing factor is %d\n", __func__, factor); DBG (DBG_info, "%s: fill length is %d\n", __func__, fill); for (x = 0; x <= pixels_per_line - avgpixels; x += avgpixels) { if ((x + o) * 2 * 2 + 3 > words_per_color * 2) break; for (j = 0; j < channels; j++) { dk = 0; br = 0; for (i = 0; i < avgpixels; i++) { /* dark data */ dk += (dev->dark_average_data[(x + i + pixels_per_line * j) * 2] | (dev->dark_average_data [(x + i + pixels_per_line * j) * 2 + 1] << 8)); /* white data */ br += (dev->white_average_data[(x + i + pixels_per_line * j) * 2] | (dev->white_average_data [(x + i + pixels_per_line * j) * 2 + 1] << 8)); } br /= avgpixels; dk /= avgpixels; if (br * target_dark > dk * target_bright) val = 0; else if (dk * target_bright - br * target_dark > 65535 * (target_bright - target_dark)) val = 65535; else { val = (dk * target_bright - br * target_dark) / (target_bright - target_dark); } /*fill all pixels, even if only the last one is relevant*/ for (i = 0; i < fill; i++) { shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j] = val & 0xff; shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 1] = val >> 8; } val = br - dk; if (65535 * val > (target_bright - target_dark) * coeff) { val = (coeff * (target_bright - target_dark)) / val; } else { val = 65535; } /*fill all pixels, even if only the last one is relevant*/ for (i = 0; i < fill; i++) { shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 2] = val & 0xff; shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 3] = val >> 8; } } /* fill remaining channels */ for (j = channels; j < 3; j++) { for (i = 0; i < fill; i++) { shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j ] = shading_data[(x/factor + o + i) * 2 * 2 ]; shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 1] = shading_data[(x/factor + o + i) * 2 * 2 + 1]; shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 2] = shading_data[(x/factor + o + i) * 2 * 2 + 2]; shading_data[(x/factor + o + i) * 2 * 2 + words_per_color * 2 * j + 3] = shading_data[(x/factor + o + i) * 2 * 2 + 3]; } } } } /** * Computes shading coefficient using formula in data sheet. 16bit data values * manipulated here are little endian. For now we assume deletion scanning type * and that there is always 3 channels. * @param dev scanner's device * @param shading_data memory area where to store the computed shading coefficients * @param pixels_per_line number of pixels per line * @param channels number of color channels (actually 1 or 3) * @param cmat color transposition matrix * @param offset shading coefficients left offset * @param coeff 4000h or 2000h depending on fast scan mode or not * @param target value of the target code */ #ifndef UNIT_TESTING static #endif void compute_coefficients (Genesys_Device * dev, uint8_t * shading_data, unsigned int pixels_per_line, unsigned int channels, unsigned int cmat[3], int offset, unsigned int coeff, unsigned int target) { uint8_t *ptr; /* contain 16bit words in little endian */ unsigned int x, c; unsigned int val, br, dk; unsigned int start, end; DBG (DBG_io, "compute_coefficients: pixels_per_line=%d, coeff=0x%04x\n", pixels_per_line, coeff); /* compute start & end values depending of the offset */ if (offset < 0) { start = -1 * offset; end = pixels_per_line; } else { start = 0; end = pixels_per_line - offset; } for (c = 0; c < channels; c++) { for (x = start; x < end; x++) { /* TODO if channels=1 , use filter to know the base addr */ ptr = shading_data + 4 * ((x + offset) * channels + cmat[c]); /* dark data */ dk = dev->dark_average_data[x * 2 * channels + c * 2]; dk += 256 * dev->dark_average_data[x * 2 * channels + c * 2 + 1]; /* white data */ br = dev->white_average_data[x * 2 * channels + c * 2]; br += 256 * dev->white_average_data[x * 2 * channels + c * 2 + 1]; /* compute coeff */ val=compute_coefficient(coeff,target,br-dk); /* assign it */ ptr[0] = dk & 255; ptr[1] = dk / 256; ptr[2] = val & 0xff; ptr[3] = val / 256; } } } /** * Computes shading coefficient using formula in data sheet. 16bit data values * manipulated here are little endian. Data is in planar form, ie grouped by * lines of the same color component. * @param dev scanner's device * @param shading_data memory area where to store the computed shading coefficients * @param factor averaging factor when the calibration scan is done at a higher resolution * than the final scan * @param pixels_per_line number of pixels per line * @param words_per_color total number of shading data words for one color element * @param channels number of color channels (actually 1 or 3) * @param cmat transcoding matrix for color channel order * @param offset shading coefficients left offset * @param coeff 4000h or 2000h depending on fast scan mode or not * @param target white target value */ #ifndef UNIT_TESTING static #endif void compute_planar_coefficients (Genesys_Device * dev, uint8_t * shading_data, unsigned int factor, unsigned int pixels_per_line, unsigned int words_per_color, unsigned int channels, unsigned int cmat[3], unsigned int offset, unsigned int coeff, unsigned int target) { uint8_t *ptr; /* contains 16bit words in little endian */ uint32_t x, c, i; uint32_t val, dk, br; DBG (DBG_io, "compute_planar_coefficients: factor=%d, pixels_per_line=%d, words=0x%X, coeff=0x%04x\n", factor, pixels_per_line, words_per_color, coeff); for (c = 0; c < channels; c++) { /* shading data is larger than pixels_per_line so offset can be neglected */ for (x = 0; x < pixels_per_line; x+=factor) { /* x2 because of 16 bit values, and x2 since one coeff for dark * and another for white */ ptr = shading_data + words_per_color * cmat[c] * 2 + (x + offset) * 4; dk = 0; br = 0; /* average case */ for(i=0;idark_average_data[((x+i) + pixels_per_line * c) * 2 + 1]; dk += dev->dark_average_data[((x+i) + pixels_per_line * c) * 2]; br += 256 * dev->white_average_data[((x+i) + pixels_per_line * c) * 2 + 1]; br += dev->white_average_data[((x+i) + pixels_per_line * c) * 2]; } dk /= factor; br /= factor; val = compute_coefficient (coeff, target, br - dk); /* we duplicate the information to have calibration data at optical resolution */ for (i = 0; i < factor; i++) { ptr[0 + 4 * i] = dk & 255; ptr[1 + 4 * i] = dk / 256; ptr[2 + 4 * i] = val & 0xff; ptr[3 + 4 * i] = val / 256; } } } /* in case of gray level scan, we duplicate shading information on all * three color channels */ if(channels==1) { memcpy(shading_data+cmat[1]*2*words_per_color, shading_data+cmat[0]*2*words_per_color, words_per_color*2); memcpy(shading_data+cmat[2]*2*words_per_color, shading_data+cmat[0]*2*words_per_color, words_per_color*2); } } #ifndef UNIT_TESTING static #endif void compute_shifted_coefficients (Genesys_Device * dev, uint8_t * shading_data, unsigned int pixels_per_line, unsigned int channels, unsigned int cmat[3], int offset, unsigned int coeff, unsigned int target_dark, unsigned int target_bright, unsigned int patch_size) /* contigous extent */ { unsigned int x, avgpixels, basepixels, i, j, val1, val2; unsigned int br_tmp [3], dk_tmp [3]; uint8_t *ptr = shading_data + offset * 3 * 4; /* contain 16bit words in little endian */ unsigned int patch_cnt = offset * 3; /* at start, offset of first patch */ x = dev->settings.xres; if ((dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE) && (dev->settings.xres <= dev->sensor.optical_res / 2)) x *= 2; /* scanner is using half-ccd mode */ basepixels = dev->sensor.optical_res / x; /*this should be evenly dividable */ /* gl841 supports 1/1 1/2 1/3 1/4 1/5 1/6 1/8 1/10 1/12 1/15 averaging */ if (basepixels < 1) avgpixels = 1; else if (basepixels < 6) avgpixels = basepixels; else if (basepixels < 8) avgpixels = 6; else if (basepixels < 10) avgpixels = 8; else if (basepixels < 12) avgpixels = 10; else if (basepixels < 15) avgpixels = 12; else avgpixels = 15; DBG (DBG_info, "compute_shifted_coefficients: pixels_per_line=%d, coeff=0x%04x, averaging over %d pixels\n", pixels_per_line, coeff, avgpixels); for (x = 0; x <= pixels_per_line - avgpixels; x += avgpixels) { memset (&br_tmp, 0, sizeof(br_tmp)); memset (&dk_tmp, 0, sizeof(dk_tmp)); for (i = 0; i < avgpixels; i++) { for (j = 0; j < channels; j++) { br_tmp[j] += (dev->white_average_data[((x + i) * channels + j) * 2] | (dev->white_average_data[((x + i) * channels + j) * 2 + 1] << 8)); dk_tmp[i] += (dev->dark_average_data[((x + i) * channels + j) * 2] | (dev->dark_average_data[((x + i) * channels + j) * 2 + 1] << 8)); } } for (j = 0; j < channels; j++) { br_tmp[j] /= avgpixels; dk_tmp[j] /= avgpixels; if (br_tmp[j] * target_dark > dk_tmp[j] * target_bright) val1 = 0; else if (dk_tmp[j] * target_bright - br_tmp[j] * target_dark > 65535 * (target_bright - target_dark)) val1 = 65535; else val1 = (dk_tmp[j] * target_bright - br_tmp[j] * target_dark) / (target_bright - target_dark); val2 = br_tmp[j] - dk_tmp[j]; if (65535 * val2 > (target_bright - target_dark) * coeff) val2 = (coeff * (target_bright - target_dark)) / val2; else val2 = 65535; br_tmp[j] = val1; dk_tmp[j] = val2; } for (i = 0; i < avgpixels; i++) { for (j = 0; j < channels; j++) { * ptr++ = br_tmp[ cmat[j] ] & 0xff; * ptr++ = br_tmp[ cmat[j] ] >> 8; * ptr++ = dk_tmp[ cmat[j] ] & 0xff; * ptr++ = dk_tmp[ cmat[j] ] >> 8; patch_cnt++; if (patch_cnt == patch_size) { patch_cnt = 0; val1 = cmat[2]; cmat[2] = cmat[1]; cmat[1] = cmat[0]; cmat[0] = val1; } } } } } GENESYS_STATIC SANE_Status genesys_send_shading_coefficient (Genesys_Device * dev) { SANE_Status status; uint32_t pixels_per_line; uint8_t *shading_data; /**> contains 16bit words in little endian */ uint8_t channels; int o; unsigned int length; /**> number of shading calibration data words */ unsigned int factor; unsigned int cmat[3]; /**> matrix of color channels */ unsigned int coeff, target_code, words_per_color = 0; DBGSTART; pixels_per_line = dev->calib_pixels; channels = dev->calib_channels; /* we always build data for three channels, even for gray * we make the shading data such that each color channel data line is contiguous * to the next one, which allow to write the 3 channels in 1 write * during genesys_send_shading_coefficient, some values are words, other bytes * hence the x2 factor */ switch (sanei_genesys_read_reg_from_set (dev->reg, 0x05) >> 6) { /* 600 dpi */ case 0: words_per_color = 0x2a00; break; /* 1200 dpi */ case 1: words_per_color = 0x5500; break; /* 2400 dpi */ case 2: words_per_color = 0xa800; break; /* 4800 dpi */ case 3: words_per_color = 0x15000; break; } /* special case, memory is aligned on 0x5400, this has yet to be explained */ /* could be 0xa800 because sensor is truly 2400 dpi, then halved because * we only set 1200 dpi */ if(dev->model->ccd_type==CIS_CANONLIDE80) { words_per_color = 0x5400; } length = words_per_color * 3 * 2; /* allocate computed size */ shading_data = malloc (length); if (!shading_data) { DBG (DBG_error, "%s: failed to allocate memory\n", __func__); return SANE_STATUS_NO_MEM; } memset (shading_data, 0, length); /* TARGET/(Wn-Dn) = white gain -> ~1.xxx then it is multiplied by 0x2000 or 0x4000 to give an integer Wn = white average for column n Dn = dark average for column n */ if (dev->model->cmd_set->get_gain4_bit (dev->calib_reg)) coeff = 0x4000; else coeff = 0x2000; /* compute avg factor */ if(dev->settings.xres>dev->sensor.optical_res) { factor=1; } else { factor=dev->sensor.optical_res/dev->settings.xres; } /* for GL646, shading data is planar if REG01_FASTMOD is set and * chunky if not. For now we rely on the fact that we know that * each sensor is used only in one mode. Currently only the CIS_XP200 * sets REG01_FASTMOD. */ /* TODO setup a struct in genesys_devices that * will handle these settings instead of having this switch growing up */ cmat[0] = 0; cmat[1] = 1; cmat[2] = 2; switch (dev->model->ccd_type) { case CCD_XP300: case CCD_ROADWARRIOR: case CCD_DP665: case CCD_DP685: case CCD_DSMOBILE600: target_code = 0xdc00; o = 4; compute_planar_coefficients (dev, shading_data, factor, pixels_per_line, words_per_color, channels, cmat, o, coeff, target_code); break; case CIS_XP200: target_code = 0xdc00; o = 2; cmat[0] = 2; /* red is last */ cmat[1] = 0; /* green is first */ cmat[2] = 1; /* blue is second */ compute_planar_coefficients (dev, shading_data, 1, pixels_per_line, words_per_color, channels, cmat, o, coeff, target_code); break; case CCD_HP2300: target_code = 0xdc00; o = 2; if(dev->settings.xres<=dev->sensor.optical_res/2) { o = o - dev->sensor.dummy_pixel / 2; } compute_coefficients (dev, shading_data, pixels_per_line, 3, cmat, o, coeff, target_code); break; case CCD_5345: target_code = 0xe000; o = 4; if(dev->settings.xres<=dev->sensor.optical_res/2) { o = o - dev->sensor.dummy_pixel; } compute_coefficients (dev, shading_data, pixels_per_line, 3, cmat, o, coeff, target_code); break; case CCD_HP3670: case CCD_HP2400: target_code = 0xe000; /* offset is cksel dependent, but we can't use this in common code */ if(dev->settings.xres<=300) { o = -10; /* OK for <=300 */ } else if(dev->settings.xres<=600) { o = -6; /* ok at 600 */ } else { o = +2; } compute_coefficients (dev, shading_data, pixels_per_line, 3, cmat, o, coeff, target_code); break; case CCD_KVSS080: case CCD_PLUSTEK3800: case CCD_G4050: case CCD_CS4400F: case CCD_CS8400F: target_code = 0xe000; o = 0; compute_coefficients (dev, shading_data, pixels_per_line, 3, cmat, o, coeff, target_code); break; case CIS_CANONLIDE700: case CIS_CANONLIDE100: case CIS_CANONLIDE200: case CIS_CANONLIDE110: case CIS_CANONLIDE120: case CIS_CANONLIDE210: case CIS_CANONLIDE220: /* TODO store this in a data struct so we avoid * growing this switch */ if(dev->model->ccd_type!=CIS_CANONLIDE110 && dev->model->ccd_type!=CIS_CANONLIDE210 && dev->model->ccd_type!=CIS_CANONLIDE120 && dev->model->ccd_type!=CIS_CANONLIDE220) target_code=0xdc00; else target_code=0xf000; words_per_color=pixels_per_line*2; length = words_per_color * 3 * 2; free(shading_data); shading_data = malloc (length); if (!shading_data) { DBG (DBG_error, "%s: failed to allocate memory\n", __func__); return SANE_STATUS_NO_MEM; } memset (shading_data, 0, length); compute_planar_coefficients (dev, shading_data, 1, pixels_per_line, words_per_color, channels, cmat, 0, coeff, target_code); break; case CCD_CANONLIDE35: compute_averaged_planar (dev, shading_data, pixels_per_line, words_per_color, channels, 4, coeff, 0xe000, 0x0a00); break; case CIS_CANONLIDE80: compute_averaged_planar (dev, shading_data, pixels_per_line, words_per_color, channels, 0, coeff, 0xd000, 0x0800); break; case CCD_PLUSTEK_3600: compute_shifted_coefficients (dev, shading_data, pixels_per_line, channels, cmat, 12, /* offset */ coeff, 0x0001, /* target_dark */ 0xf900, /* target_bright */ 256); /* patch_size: contigous extent */ break; default: DBG (DBG_error, "%s: sensor %d not supported\n", __func__, dev->model->ccd_type); return SANE_STATUS_UNSUPPORTED; break; } /* do the actual write of shading calibration data to the scanner */ status = genesys_send_offset_and_shading (dev, shading_data, length); free (shading_data); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to send shading data: %s\n", __func__, sane_strstatus (status)); } DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * search calibration cache list for an entry matching required scan. * If one is found, set device calibration with it * @param dev scanner's device * @return SANE_STATUS_UNSUPPORTED if no matching cache entry has been * found, SANE_STATUS_GOOD if one has been found and used. */ static SANE_Status genesys_restore_calibration (Genesys_Device * dev) { SANE_Status status; Genesys_Calibration_Cache *cache; DBGSTART; /* if no cache or no function to evaluate cache entry ther can be no match */ if (!dev->model->cmd_set->is_compatible_calibration || dev->calibration_cache == NULL) return SANE_STATUS_UNSUPPORTED; /* we walk the link list of calibration cache in search for a * matching one */ for (cache = dev->calibration_cache; cache; cache = cache->next) { status = dev->model->cmd_set->is_compatible_calibration (dev, cache, SANE_FALSE); /* SANE_STATUS_GOOD, a matching cache has been found * so we use it to populate calibration data */ if (status == SANE_STATUS_GOOD) { memcpy (&dev->frontend, &cache->frontend, sizeof (dev->frontend)); /* we don't restore the gamma fields */ memcpy (dev->sensor.regs_0x10_0x1d, cache->sensor.regs_0x10_0x1d, 6); free (dev->dark_average_data); free (dev->white_average_data); dev->average_size = cache->average_size; dev->calib_pixels = cache->calib_pixels; dev->calib_channels = cache->calib_channels; dev->dark_average_data = (uint8_t *) malloc (cache->average_size); dev->white_average_data = (uint8_t *) malloc (cache->average_size); if (!dev->dark_average_data || !dev->white_average_data) return SANE_STATUS_NO_MEM; memcpy (dev->dark_average_data, cache->dark_average_data, dev->average_size); memcpy (dev->white_average_data, cache->white_average_data, dev->average_size); if(dev->model->cmd_set->send_shading_data==NULL) { status = genesys_send_shading_coefficient (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_restore_calibration: failed to send shading calibration coefficients: %s\n", sane_strstatus (status)); return status; } } DBG (DBG_proc, "genesys_restore_calibration: restored\n"); return SANE_STATUS_GOOD; } /* here status is either SANE_STATUS_UNSUPPORTED which mean tested cache * entry doesn't match, or an fatal error */ if (status != SANE_STATUS_UNSUPPORTED) { DBG (DBG_error, "genesys_restore_calibration: fail while checking compatibility: %s\n", sane_strstatus (status)); return status; } } DBG (DBG_proc, "genesys_restore_calibration: completed(nothing found)\n"); return SANE_STATUS_UNSUPPORTED; } static SANE_Status genesys_save_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_UNSUPPORTED; Genesys_Calibration_Cache *cache = NULL; #ifdef HAVE_SYS_TIME_H struct timeval time; #endif DBGSTART; if (!dev->model->cmd_set->is_compatible_calibration) return SANE_STATUS_UNSUPPORTED; if (dev->calibration_cache != NULL) { for (cache = dev->calibration_cache; cache; cache = cache->next) { status = dev->model->cmd_set->is_compatible_calibration (dev, cache, SANE_TRUE); if (status == SANE_STATUS_UNSUPPORTED) { continue; } else if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_save_calibration: fail while checking compatibility: %s\n", sane_strstatus (status)); return status; } break; } } /* if we found on overridable cache, we reuse it */ if (cache) { free(cache->dark_average_data); free(cache->white_average_data); } else { /* create a new cache entry and insert it in the linked list */ cache = malloc (sizeof (Genesys_Calibration_Cache)); if (!cache) return SANE_STATUS_NO_MEM; memset (cache, 0, sizeof (Genesys_Calibration_Cache)); cache->next = dev->calibration_cache; dev->calibration_cache = cache; } cache->average_size = dev->average_size; cache->dark_average_data = (uint8_t *) malloc (cache->average_size); if (!cache->dark_average_data) return SANE_STATUS_NO_MEM; cache->white_average_data = (uint8_t *) malloc (cache->average_size); if (!cache->white_average_data) return SANE_STATUS_NO_MEM; memcpy (&cache->used_setup, &dev->current_setup, sizeof (cache->used_setup)); memcpy (&cache->frontend, &dev->frontend, sizeof (cache->frontend)); memcpy (&cache->sensor, &dev->sensor, sizeof (cache->sensor)); cache->calib_pixels = dev->calib_pixels; cache->calib_channels = dev->calib_channels; memcpy (cache->dark_average_data, dev->dark_average_data, cache->average_size); memcpy (cache->white_average_data, dev->white_average_data, cache->average_size); #ifdef HAVE_SYS_TIME_H gettimeofday(&time,NULL); cache->last_calibration = time.tv_sec; #endif DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * does the calibration process for a flatbed scanner * - offset calibration * - gain calibration * - shading calibration * @param dev device to calibrate * @return SANE_STATUS_GOOD if everything when all right, else the error code. */ GENESYS_STATIC SANE_Status genesys_flatbed_calibration (Genesys_Device * dev) { SANE_Status status; uint32_t pixels_per_line; int yres; DBG (DBG_info, "genesys_flatbed_calibration\n"); yres = dev->sensor.optical_res; if (dev->settings.yres <= dev->sensor.optical_res / 2) yres /= 2; /* do offset calibration if needed */ if (dev->model->flags & GENESYS_FLAG_OFFSET_CALIBRATION) { status = dev->model->cmd_set->offset_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: offset calibration failed: %s\n", sane_strstatus (status)); return status; } /* since all the registers are set up correctly, just use them */ status = dev->model->cmd_set->coarse_gain_calibration (dev, yres); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: coarse gain calibration: %s\n", sane_strstatus (status)); return status; } } else /* since we have 2 gain calibration proc, skip second if first one was used. */ { status = dev->model->cmd_set->init_regs_for_coarse_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to send calibration registers: %s\n", sane_strstatus (status)); return status; } status = genesys_coarse_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to do coarse gain calibration: %s\n", sane_strstatus (status)); return status; } } if (dev->model->is_cis) { /* the afe now sends valid data for doing led calibration */ status = dev->model->cmd_set->led_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: led calibration failed: %s\n", sane_strstatus (status)); return status; } /* calibrate afe again to match new exposure */ if (dev->model->flags & GENESYS_FLAG_OFFSET_CALIBRATION) { status = dev->model->cmd_set->offset_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: offset calibration failed: %s\n", sane_strstatus (status)); return status; } /* since all the registers are set up correctly, just use them */ status = dev->model->cmd_set->coarse_gain_calibration (dev, yres); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: coarse gain calibration: %s\n", sane_strstatus (status)); return status; } } else /* since we have 2 gain calibration proc, skip second if first one was used. */ { status = dev->model->cmd_set->init_regs_for_coarse_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to send calibration registers: %s\n", sane_strstatus (status)); return status; } status = genesys_coarse_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to do static calibration: %s\n", sane_strstatus (status)); return status; } } } /* we always use sensor pixel number when the ASIC can't handle multi-segments sensor */ if (!(dev->model->flags & GENESYS_FLAG_SIS_SENSOR)) { pixels_per_line = (SANE_UNFIX (dev->model->x_size) * dev->settings.xres) / MM_PER_INCH; } else { pixels_per_line = dev->sensor.sensor_pixels; } /* send default shading data */ status = sanei_genesys_init_shading_data (dev, pixels_per_line); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to init shading process: %s\n", sane_strstatus (status)); return status; } /* shading calibration */ status = dev->model->cmd_set->init_regs_for_shading (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to send shading " "registers: %s\n", sane_strstatus (status)); return status; } if (dev->model->flags & GENESYS_FLAG_DARK_WHITE_CALIBRATION) { status = genesys_dark_white_shading_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to do dark+white shading calibration: %s\n", sane_strstatus (status)); return status; } } else { if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION) { status = genesys_dark_shading_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to do dark shading calibration: %s\n", sane_strstatus (status)); return status; } } status = genesys_white_shading_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to do white shading calibration: %s\n", sane_strstatus (status)); return status; } } if(dev->model->cmd_set->send_shading_data==NULL) { status = genesys_send_shading_coefficient (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_flatbed_calibration: failed to send shading calibration coefficients: %s\n", sane_strstatus (status)); return status; } } DBG (DBG_info, "genesys_flatbed_calibration: completed\n"); return SANE_STATUS_GOOD; } /** * Does the calibration process for a sheetfed scanner * - offset calibration * - gain calibration * - shading calibration * During calibration a predefined calibration sheet with specific black and white * areas is used. * @param dev device to calibrate * @return SANE_STATUS_GOOD if everything when all right, else the error code. */ static SANE_Status genesys_sheetfed_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; SANE_Bool forward = SANE_TRUE; int xres; DBGSTART; if (dev->model->cmd_set->search_strip == NULL) { DBG (DBG_error, "genesys_sheetfed_calibration: no strip searching function available\n"); return SANE_STATUS_UNSUPPORTED; } /* first step, load document */ status = dev->model->cmd_set->load_document (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to load document: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "genesys_sheetfed_calibration\n"); /* led, offset and gain calibration are influenced by scan * settings. So we set it to sensor resolution */ xres = dev->sensor.optical_res; dev->settings.xres = dev->sensor.optical_res; /* XP200 needs to calibrate a full and half sensor's resolution */ if (dev->model->ccd_type == CIS_XP200 && dev->settings.xres <= dev->sensor.optical_res / 2) dev->settings.xres /= 2; /* the afe needs to sends valid data even before calibration */ /* go to a white area */ status = dev->model->cmd_set->search_strip (dev, forward, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to find white strip: %s\n", sane_strstatus (status)); dev->model->cmd_set->eject_document (dev); return status; } if (dev->model->is_cis) { status = dev->model->cmd_set->led_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: led calibration failed: %s\n", sane_strstatus (status)); return status; } } /* calibrate afe */ if (dev->model->flags & GENESYS_FLAG_OFFSET_CALIBRATION) { status = dev->model->cmd_set->offset_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: offset calibration failed: %s\n", sane_strstatus (status)); return status; } /* since all the registers are set up correctly, just use them */ status = dev->model->cmd_set->coarse_gain_calibration (dev, xres); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: coarse gain calibration: %s\n", sane_strstatus (status)); return status; } } else /* since we have 2 gain calibration proc, skip second if first one was used. */ { status = dev->model->cmd_set->init_regs_for_coarse_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to send calibration registers: %s\n", sane_strstatus (status)); return status; } status = genesys_coarse_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to do static calibration: %s\n", sane_strstatus (status)); return status; } } /* search for a full width black strip and then do a 16 bit scan to * gather black shading data */ if (dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION) { /* seek black/white reverse/forward */ status = dev->model->cmd_set->search_strip (dev, forward, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to find black strip: %s\n", sane_strstatus (status)); dev->model->cmd_set->eject_document (dev); return status; } status = dev->model->cmd_set->init_regs_for_shading (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to do set up registers for shading calibration: %s\n", sane_strstatus (status)); return status; } status = genesys_dark_shading_calibration (dev); if (status != SANE_STATUS_GOOD) { dev->model->cmd_set->eject_document (dev); DBG (DBG_error, "genesys_sheetfed_calibration: failed to do dark shading calibration: %s\n", sane_strstatus (status)); return status; } forward = SANE_FALSE; } /* go to a white area */ status = dev->model->cmd_set->search_strip (dev, forward, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to find white strip: %s\n", sane_strstatus (status)); dev->model->cmd_set->eject_document (dev); return status; } status = dev->model->cmd_set->init_regs_for_shading (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to do set up registers for shading calibration: %s\n", sane_strstatus (status)); return status; } status = genesys_white_shading_calibration (dev); if (status != SANE_STATUS_GOOD) { dev->model->cmd_set->eject_document (dev); DBG (DBG_error, "%s: failed eject target: %s\n", __func__, sane_strstatus (status)); return status; } /* in case we haven't black shading data, build it from black pixels * of white calibration */ if (!(dev->model->flags & GENESYS_FLAG_DARK_CALIBRATION)) { FREE_IFNOT_NULL (dev->dark_average_data); dev->dark_average_data = malloc (dev->average_size); memset (dev->dark_average_data, 0x0f, dev->average_size); /* XXX STEF XXX * with black point in white shading, build an average black * pixel and use it to fill the dark_average * dev->calib_pixels (dev->sensor.sensor_pixels * dev->settings.xres) / dev->sensor.optical_res, dev->calib_lines, */ } /* send the shading coefficient when doing whole line shading * but not when using SHDAREA like GL124 */ if(dev->model->cmd_set->send_shading_data==NULL) { status = genesys_send_shading_coefficient (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to send shading calibration coefficients: %s\n", sane_strstatus (status)); return status; } } /* save the calibration data */ genesys_save_calibration (dev); /* and finally eject calibration sheet */ status = dev->model->cmd_set->eject_document (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_sheetfed_calibration: failed to eject document: %s\n", sane_strstatus (status)); return status; } /* resotre settings */ dev->settings.xres = xres; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * does the calibration process for a device * @param dev device to calibrate */ static SANE_Status genesys_scanner_calibration (Genesys_Device * dev) { if (dev->model->is_sheetfed == SANE_FALSE) { return genesys_flatbed_calibration (dev); } return genesys_sheetfed_calibration (dev); } /* unused function kept in case it may be usefull in the futur */ #if 0 static SANE_Status genesys_wait_not_moving (Genesys_Device * dev, int mseconds) { uint8_t value; SANE_Status status; DBG (DBG_proc, "genesys_wait_not_moving: waiting %d mseconds for motor to stop\n", mseconds); while (mseconds > 0) { RIE (sanei_genesys_get_status (dev, &value)); if (dev->model->cmd_set->test_motor_flag_bit (value)) { usleep (100 * 1000); mseconds -= 100; DBG (DBG_io, "genesys_wait_not_moving: motor is moving, %d mseconds to go\n", mseconds); } else { DBG (DBG_info, "genesys_wait_not_moving: motor is not moving, exiting\n"); return SANE_STATUS_GOOD; } } DBG (DBG_error, "genesys_wait_not_moving: motor is still moving, timeout exceeded\n"); return SANE_STATUS_DEVICE_BUSY; } #endif /* ------------------------------------------------------------------------ */ /* High level (exported) functions */ /* ------------------------------------------------------------------------ */ /* * wait lamp to be warm enough by scanning the same line until * differences between two scans are below a threshold */ static SANE_Status genesys_warmup_lamp (Genesys_Device * dev) { uint8_t *first_line, *second_line; int seconds = 0; int pixel; int channels, total_size; double first_average = 0; double second_average = 0; int difference = 255; int empty, lines = 3; SANE_Status status = SANE_STATUS_IO_ERROR; DBGSTART; /* check if the current chipset implements warmup */ if(dev->model->cmd_set->init_regs_for_warmup==NULL) { DBG (DBG_error, "%s: init_regs_for_warmup not implemented\n", __func__); return status; } dev->model->cmd_set->init_regs_for_warmup (dev, dev->reg, &channels, &total_size); first_line = malloc (total_size); if (!first_line) return SANE_STATUS_NO_MEM; second_line = malloc (total_size); if (!second_line) { free(first_line); DBGCOMPLETED; return SANE_STATUS_NO_MEM; } do { DBG (DBG_info, "genesys_warmup_lamp: one more loop\n"); RIEF2 (dev->model->cmd_set->begin_scan (dev, dev->reg, SANE_FALSE), first_line, second_line); do { sanei_genesys_test_buffer_empty (dev, &empty); } while (empty); status = sanei_genesys_read_data_from_scanner (dev, first_line, total_size); if (status != SANE_STATUS_GOOD) { RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size), first_line, second_line); } RIEF2 (dev->model->cmd_set->end_scan (dev, dev->reg, SANE_TRUE), first_line, second_line); sleep (1); /* sleep 1 s */ seconds++; RIEF2 (dev->model->cmd_set->begin_scan (dev, dev->reg, SANE_FALSE), first_line, second_line); do { sanei_genesys_test_buffer_empty (dev, &empty); usleep (100 * 1000); } while (empty); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); RIEF2 (dev->model->cmd_set->end_scan (dev, dev->reg, SANE_TRUE), first_line, second_line); /* compute difference between the two scans */ for (pixel = 0; pixel < total_size; pixel++) { /* 16 bit data */ if (dev->model->cmd_set->get_bitset_bit (dev->reg)) { first_average += (first_line[pixel] + first_line[pixel + 1] * 256); second_average += (second_line[pixel] + second_line[pixel + 1] * 256); pixel++; } else { first_average += first_line[pixel]; second_average += second_line[pixel]; } } if (dev->model->cmd_set->get_bitset_bit (dev->reg)) { first_average /= pixel; second_average /= pixel; difference = fabs (first_average - second_average); DBG (DBG_info, "genesys_warmup_lamp: average = %.2f, diff = %.3f\n", 100 * ((second_average) / (256 * 256)), 100 * (difference / second_average)); if (second_average > (100 * 256) && (difference / second_average) < 0.002) break; } else { first_average /= pixel; second_average /= pixel; if (DBG_LEVEL >= DBG_data) { sanei_genesys_write_pnm_file ("warmup1.pnm", first_line, 8, channels, total_size / (lines * channels), lines); sanei_genesys_write_pnm_file ("warmup2.pnm", second_line, 8, channels, total_size / (lines * channels), lines); } DBG (DBG_info, "genesys_warmup_lamp: average 1 = %.2f, average 2 = %.2f\n", first_average, second_average); /* if delta below 15/255 ~= 5.8%, lamp is considred warm enough */ if (fabs (first_average - second_average) < 15 && second_average > 55) break; } /* sleep another second before next loop */ sleep (1); seconds++; } while (seconds < WARMUP_TIME); if (seconds >= WARMUP_TIME) { DBG (DBG_error, "genesys_warmup_lamp: warmup timed out after %d seconds. Lamp defective?\n", seconds); status = SANE_STATUS_IO_ERROR; } else { DBG (DBG_info, "genesys_warmup_lamp: warmup succeeded after %d seconds\n", seconds); } free (first_line); free (second_line); DBGCOMPLETED; return status; } /* High-level start of scanning */ static SANE_Status genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off) { SANE_Status status; unsigned int steps, expected; SANE_Bool empty; DBGSTART; /* since not all scanners are set ot wait for head to park * we check we are not still parking before starting a new scan */ if (dev->parking == SANE_TRUE) { status = sanei_genesys_wait_for_home (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to wait for head to park: %s\n", sane_strstatus (status)); return status; } } /* disable power saving*/ status = dev->model->cmd_set->save_power (dev, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to disable power saving mode: %s\n", sane_strstatus (status)); return status; } /* wait for lamp warmup : until a warmup for TRANSPARENCY is designed, skip * it when scanning from XPA. */ if (!(dev->model->flags & GENESYS_FLAG_SKIP_WARMUP) && (dev->settings.scan_method == SCAN_METHOD_FLATBED)) { RIE (genesys_warmup_lamp (dev)); } /* set top left x and y values by scanning the internals if flatbed scanners */ if (dev->model->is_sheetfed == SANE_FALSE) { /* do the geometry detection only once */ if ((dev->model->flags & GENESYS_FLAG_SEARCH_START) && (dev->model->y_offset_calib == 0)) { status = dev->model->cmd_set->search_start_position (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to search start position: %s\n", sane_strstatus (status)); return status; } dev->parking = SANE_FALSE; status = dev->model->cmd_set->slow_back_home (dev, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to move scanhead to " "home position: %s\n", sane_strstatus (status)); return status; } dev->scanhead_position_in_steps = 0; } else { /* Go home */ /* TODO: check we can drop this since we cannot have the scanner's head wandering here */ dev->parking = SANE_FALSE; status = dev->model->cmd_set->slow_back_home (dev, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to move scanhead to " "home position: %s\n", sane_strstatus (status)); return status; } dev->scanhead_position_in_steps = 0; } } /* move to calibration area for transparency adapter */ if ((dev->settings.scan_method == SCAN_METHOD_TRANSPARENCY) && dev->model->cmd_set->move_to_ta != NULL) { status=dev->model->cmd_set->move_to_ta(dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to move to start of transparency adapter: %s\n", sane_strstatus (status)); return status; } } /* load document if needed (for sheetfed scanner for instance) */ if (dev->model->is_sheetfed == SANE_TRUE && dev->model->cmd_set->load_document != NULL) { status = dev->model->cmd_set->load_document (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to load document: %s\n", sane_strstatus (status)); return status; } } /* send gamma tables. They have been set to device or user value * when setting option value */ status = dev->model->cmd_set->send_gamma_table (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to init gamma table: %s\n", sane_strstatus (status)); return status; } /* try to use cached calibration first */ status = genesys_restore_calibration (dev); if (status == SANE_STATUS_UNSUPPORTED) { /* calibration : sheetfed scanners can't calibrate before each scan */ /* and also those who have the NO_CALIBRATION flag */ if (!(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION) &&dev->model->is_sheetfed == SANE_FALSE) { status = genesys_scanner_calibration (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to do scanner calibration: %s\n", sane_strstatus (status)); return status; } genesys_save_calibration (dev); } else { DBG (DBG_warn, "genesys_start_scan: no calibration done\n"); } } else if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to restore calibration: %s\n", sane_strstatus (status)); return status; } /* build look up table for dynamic lineart */ if(dev->settings.dynamic_lineart==SANE_TRUE) { status = sanei_genesys_load_lut(dev->lineart_lut, 8, 8, 50, 205, dev->settings.threshold_curve, dev->settings.threshold-127); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to build lut\n"); return status; } } status = dev->model->cmd_set->init_regs_for_scan (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to do init registers for scan: %s\n", sane_strstatus (status)); return status; } /* no lamp during scan */ if(lamp_off == SANE_TRUE) { dev->model->cmd_set->set_lamp_power (dev, dev->reg, SANE_FALSE); } /* GL124 is using SHDAREA, so we have to wait for scan to be set up before * sending shading data */ if( (dev->model->cmd_set->send_shading_data!=NULL) && !(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) { status = genesys_send_shading_coefficient (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to send shading calibration coefficients: %s\n", sane_strstatus (status)); return status; } } /* now send registers for scan */ status = dev->model->cmd_set->bulk_write_register (dev, dev->reg, dev->model-> cmd_set->bulk_full_size ()); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to bulk write registers, status = %d\n", status); return status; } /* start effective scan */ status = dev->model->cmd_set->begin_scan (dev, dev->reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to begin scan: %s\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } /*do we really need this? the valid data check should be sufficent -- pierre*/ /* waits for head to reach scanning position */ expected = sanei_genesys_read_reg_from_set (dev->reg, 0x3d) * 65536 + sanei_genesys_read_reg_from_set (dev->reg, 0x3e) * 256 + sanei_genesys_read_reg_from_set (dev->reg, 0x3f); do { /* wait 1/10th of second between each test to avoid overloading USB and CPU */ usleep (100 * 1000); status = sanei_genesys_read_feed_steps (dev, &steps); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: Failed to read feed steps: %s\n", sane_strstatus (status)); return status; } } while (steps < expected); /* wait for buffers to be filled */ do { RIE (sanei_genesys_test_buffer_empty (dev, &empty)); } while (empty); /* when doing one or two-table movement, let the motor settle to scanning speed */ /* and scanning start before reading data */ /* the valid data check already waits until the scanner delivers data. this here leads to unnecessary buffer full conditions in the scanner. if (dev->model->cmd_set->get_fast_feed_bit (dev->reg)) usleep (1000 * 1000); else usleep (500 * 1000); */ /* then we wait for at least one word of valid scan data this is also done in sanei_genesys_read_data_from_scanner -- pierre */ if (dev->model->is_sheetfed == SANE_FALSE) { do { usleep (100 * 1000); status = sanei_genesys_read_valid_words (dev, &steps); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_start_scan: failed to read valid words: %s\n", sane_strstatus (status)); return status; } } while (steps < 1); } DBGCOMPLETED; return SANE_STATUS_GOOD; } /* this is _not_ a ringbuffer. if we need a block which does not fit at the end of our available data, we move the available data to the beginning. */ SANE_Status sanei_genesys_buffer_alloc (Genesys_Buffer * buf, size_t size) { buf->buffer = (SANE_Byte *) malloc (size); if (!buf->buffer) return SANE_STATUS_NO_MEM; buf->avail = 0; buf->pos = 0; buf->size = size; return SANE_STATUS_GOOD; } SANE_Status sanei_genesys_buffer_free (Genesys_Buffer * buf) { SANE_Byte *tmp = buf->buffer; buf->avail = 0; buf->size = 0; buf->pos = 0; buf->buffer = NULL; if (tmp) free (tmp); return SANE_STATUS_GOOD; } SANE_Byte * sanei_genesys_buffer_get_write_pos (Genesys_Buffer * buf, size_t size) { if (buf->avail + size > buf->size) return NULL; if (buf->pos + buf->avail + size > buf->size) { memmove (buf->buffer, buf->buffer + buf->pos, buf->avail); buf->pos = 0; } return buf->buffer + buf->pos + buf->avail; } SANE_Byte * sanei_genesys_buffer_get_read_pos (Genesys_Buffer * buf) { return buf->buffer + buf->pos; } SANE_Status sanei_genesys_buffer_produce (Genesys_Buffer * buf, size_t size) { if (size > buf->size - buf->avail) return SANE_STATUS_INVAL; buf->avail += size; return SANE_STATUS_GOOD; } SANE_Status sanei_genesys_buffer_consume (Genesys_Buffer * buf, size_t size) { if (size > buf->avail) return SANE_STATUS_INVAL; buf->avail -= size; buf->pos += size; return SANE_STATUS_GOOD; } #include "genesys_conv.c" static SANE_Status accurate_line_read(Genesys_Device * dev, SANE_Byte *buffer, size_t size) { SANE_Status status; status = dev->model->cmd_set->bulk_read_data (dev, 0x45, buffer, size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "accurate_line_read: failed to read %lu bytes (%s)\n", (u_long) size, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } /* done reading */ dev->oe_buffer.avail = size; dev->oe_buffer.pos = 0; return status; } /** @brief fill buffer while reducing vertical resolution * This function fills a read buffer with scanned data from a sensor * which puts odd and even pixels in 2 different data segment. So a complete * must be read and bytes interleaved to get usable by the other stages * of the backend */ static SANE_Status genesys_fill_line_interp_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, size_t size) { size_t count; SANE_Status status; /* fill buffer if needed */ if (dev->oe_buffer.avail == 0) { status = accurate_line_read(dev,dev->oe_buffer.buffer,dev->oe_buffer.size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read %lu bytes (%s)\n", __func__, (u_long) dev->oe_buffer.size, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } } /* copy size bytes of data, copying from a line when line count matches */ count = 0; while (count < size) { /* line counter */ /* dev->line_interp holds the number of lines scanned for one line of data sent */ if(((dev->line_count/dev->current_setup.channels) % dev->line_interp)==0) { /* copy pixel when line matches */ work_buffer_dst[count] = dev->oe_buffer.buffer[dev->cur + dev->oe_buffer.pos]; count++; } /* always update pointer so we skip uncopied data */ dev->cur++; /* go to next line if needed */ if (dev->cur == dev->len) { dev->oe_buffer.pos += dev->bpl; dev->cur = 0; dev->line_count++; } /* read a new buffer if needed */ if (dev->oe_buffer.pos >= dev->oe_buffer.avail) { status = accurate_line_read(dev,dev->oe_buffer.buffer,dev->oe_buffer.size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read %lu bytes (%s)\n", __func__, (u_long) dev->oe_buffer.size, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } } } return SANE_STATUS_GOOD; } /** @brief fill buffer for segmented sensors * This function fills a read buffer with scanned data from a sensor segmented * in several parts (multi-lines sensors). Data of the same valid area is read * back to back and must be interleaved to get usable by the other stages * of the backend */ static SANE_Status genesys_fill_segmented_buffer (Genesys_Device * dev, uint8_t *work_buffer_dst, size_t size) { size_t count; SANE_Status status; int depth,i,n,k; depth = dev->settings.depth; if (dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart==SANE_FALSE) depth = 1; /* fill buffer if needed */ if (dev->oe_buffer.avail == 0) { status = accurate_line_read(dev,dev->oe_buffer.buffer,dev->oe_buffer.size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read %lu bytes (%s)\n", __func__, (u_long) dev->oe_buffer.size, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } } /* copy size bytes of data, copying from a subwindow of each line * when last line of buffer is exhausted, read another one */ count = 0; while (count < size) { if(dev->settings.double_xres==SANE_TRUE) { /* copy only even pixel */ work_buffer_dst[count] = dev->oe_buffer.buffer[dev->cur + dev->oe_buffer.pos]; /* update counter and pointer */ count++; dev->cur++; } else { if(depth==1) { while (dev->cur < dev->len && count < size) { for(n=0;nsegnb;n++) { work_buffer_dst[count+n] = 0; } /* interleaving is at bit level */ for(i=0;i<8;i++) { k=count+(i*dev->segnb)/8; for(n=0;nsegnb;n++) { work_buffer_dst[k] = work_buffer_dst[k] << 1; if((dev->oe_buffer.buffer[dev->cur + dev->skip + dev->dist*dev->order[n] + dev->oe_buffer.pos])&(128>>i)) { work_buffer_dst[k] |= 1; } } } /* update counter and pointer */ count += dev->segnb; dev->cur++; } } if(depth==8) { while (dev->cur < dev->len && count < size) { for(n=0;nsegnb;n++) { work_buffer_dst[count+n] = dev->oe_buffer.buffer[dev->cur + dev->skip + dev->dist*dev->order[n] + dev->oe_buffer.pos]; } /* update counter and pointer */ count += dev->segnb; dev->cur++; } } if(depth==16) { while (dev->cur < dev->len && count < size) { for(n=0;nsegnb;n++) { work_buffer_dst[count+n*2] = dev->oe_buffer.buffer[dev->cur + dev->skip + dev->dist*dev->order[n] + dev->oe_buffer.pos]; work_buffer_dst[count+n*2+1] = dev->oe_buffer.buffer[dev->cur + dev->skip + dev->dist*dev->order[n] + dev->oe_buffer.pos+1]; } /* update counter and pointer */ count += dev->segnb*2; dev->cur+=2; } } } /* go to next line if needed */ if (dev->cur == dev->len) { dev->oe_buffer.pos += dev->bpl; dev->cur = 0; } /* read a new buffer if needed */ if (dev->oe_buffer.pos >= dev->oe_buffer.avail) { status = accurate_line_read(dev,dev->oe_buffer.buffer,dev->oe_buffer.size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read %lu bytes (%s)\n", __func__, (u_long) dev->oe_buffer.size, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } } } return SANE_STATUS_GOOD; } /** * */ static SANE_Status genesys_fill_read_buffer (Genesys_Device * dev) { size_t size; size_t space; SANE_Status status; uint8_t *work_buffer_dst; DBGSTART; /* for sheetfed scanner, we must check is document is shorter than * the requested scan */ if (dev->model->is_sheetfed == SANE_TRUE) { status = dev->model->cmd_set->detect_document_end (dev); if (status != SANE_STATUS_GOOD) return status; } space = dev->read_buffer.size - dev->read_buffer.avail; work_buffer_dst = sanei_genesys_buffer_get_write_pos (&(dev->read_buffer), space); size = space; /* never read an odd number. exception: last read the chip internal counter does not count half words. */ size &= ~1; /* Some setups need the reads to be multiples of 256 bytes */ size &= ~0xff; if (dev->read_bytes_left < size) { size = dev->read_bytes_left; /*round up to a multiple of 256 bytes */ size += (size & 0xff) ? 0x100 : 0x00; size &= ~0xff; } /* early out if our remaining buffer capacity is too low */ if (size == 0) return SANE_STATUS_GOOD; DBG (DBG_io, "genesys_fill_read_buffer: reading %lu bytes\n", (u_long) size); /* size is already maxed to our needs. for most models bulk_read_data will read as much data as requested. */ /* due to sensors and motors, not all data can be directly used. It * may have to be read from another intermediate buffer and then processed. * There are currently 3 intermediate stages: * - handling of odd/even sensors * - handling of line interpolation for motors that can't have low * enough dpi * - handling of multi-segments sensors * * This is also the place where full duplex data will be handled. */ if (dev->line_interp>0) { /* line interpolation */ status = genesys_fill_line_interp_buffer (dev, work_buffer_dst, size); } else if (dev->segnb>1) { /* multi-segment sensors processing */ status = genesys_fill_segmented_buffer (dev, work_buffer_dst, size); } else /* regular case with no extra copy */ { status = dev->model->cmd_set->bulk_read_data (dev, 0x45, work_buffer_dst, size); } if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_fill_read_buffer: failed to read %lu bytes (%s)\n", (u_long) size, sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } if (size > dev->read_bytes_left) size = dev->read_bytes_left; dev->read_bytes_left -= size; RIE (sanei_genesys_buffer_produce (&(dev->read_buffer), size)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* this function does the effective data read in a manner that suits the scanner. It does data reordering and resizing if need. It also manages EOF and I/O errors, and line distance correction. */ static SANE_Status genesys_read_ordered_data (Genesys_Device * dev, SANE_Byte * destination, size_t * len) { SANE_Status status; size_t bytes, extra; unsigned int channels, depth, src_pixels; unsigned int ccd_shift[12], shift_count; uint8_t *work_buffer_src; uint8_t *work_buffer_dst; unsigned int dst_lines; unsigned int step_1_mode; unsigned int needs_reorder; unsigned int needs_ccd; unsigned int needs_shrink; unsigned int needs_reverse; Genesys_Buffer *src_buffer; Genesys_Buffer *dst_buffer; DBGSTART; if (dev->read_active != SANE_TRUE) { DBG (DBG_error, "genesys_read_ordered_data: read not active!\n"); *len = 0; return SANE_STATUS_INVAL; } DBG (DBG_info, "genesys_read_ordered_data: dumping current_setup:\n" "\tpixels: %d\n" "\tlines: %d\n" "\tdepth: %d\n" "\tchannels: %d\n" "\texposure_time: %d\n" "\txres: %g\n" "\tyres: %g\n" "\thalf_ccd: %s\n" "\tstagger: %d\n" "\tmax_shift: %d\n", dev->current_setup.pixels, dev->current_setup.lines, dev->current_setup.depth, dev->current_setup.channels, dev->current_setup.exposure_time, dev->current_setup.xres, dev->current_setup.yres, dev->current_setup.half_ccd ? "yes" : "no", dev->current_setup.stagger, dev->current_setup.max_shift); /* prepare conversion */ /* current settings */ channels = dev->current_setup.channels; depth = dev->current_setup.depth; src_pixels = dev->current_setup.pixels; needs_reorder = 1; if (channels != 3 && depth != 16) needs_reorder = 0; #ifndef WORDS_BIGENDIAN if (channels != 3 && depth == 16) needs_reorder = 0; if (channels == 3 && depth == 16 && !dev->model->is_cis && dev->model->line_mode_color_order == COLOR_ORDER_RGB) needs_reorder = 0; #endif if (channels == 3 && depth == 8 && !dev->model->is_cis && dev->model->line_mode_color_order == COLOR_ORDER_RGB) needs_reorder = 0; needs_ccd = dev->current_setup.max_shift > 0; needs_shrink = dev->settings.pixels != src_pixels; needs_reverse = depth == 1; DBG (DBG_info, "genesys_read_ordered_data: using filters:%s%s%s%s\n", needs_reorder ? " reorder" : "", needs_ccd ? " ccd" : "", needs_shrink ? " shrink" : "", needs_reverse ? " reverse" : ""); DBG (DBG_info, "genesys_read_ordered_data: frontend requested %lu bytes\n", (u_long) * len); DBG (DBG_info, "genesys_read_ordered_data: bytes_to_read=%lu, total_bytes_read=%lu\n", (u_long) dev->total_bytes_to_read, (u_long) dev->total_bytes_read); /* is there data left to scan */ if (dev->total_bytes_read >= dev->total_bytes_to_read) { DBG (DBG_proc, "genesys_read_ordered_data: nothing more to scan: EOF\n"); *len = 0; /* issue park command immediatly in case scanner can handle it * so we save time */ if (dev->model->is_sheetfed == SANE_FALSE && !(dev->model->flags & GENESYS_FLAG_MUST_WAIT) && dev->parking == SANE_FALSE) { dev->model->cmd_set->slow_back_home (dev, SANE_FALSE); dev->parking = SANE_TRUE; } return SANE_STATUS_EOF; } DBG (DBG_info, "genesys_read_ordered_data: %lu lines left by output\n", ((dev->total_bytes_to_read - dev->total_bytes_read) * 8UL) / (dev->settings.pixels * channels * depth)); DBG (DBG_info, "genesys_read_ordered_data: %lu lines left by input\n", ((dev->read_bytes_left + dev->read_buffer.avail) * 8UL) / (src_pixels * channels * depth)); if (channels == 1) { ccd_shift[0] = 0; ccd_shift[1] = dev->current_setup.stagger; shift_count = 2; } else { ccd_shift[0] = ((dev->ld_shift_r * dev->settings.yres) / dev->motor.base_ydpi); ccd_shift[1] = ((dev->ld_shift_g * dev->settings.yres) / dev->motor.base_ydpi); ccd_shift[2] = ((dev->ld_shift_b * dev->settings.yres) / dev->motor.base_ydpi); ccd_shift[3] = ccd_shift[0] + dev->current_setup.stagger; ccd_shift[4] = ccd_shift[1] + dev->current_setup.stagger; ccd_shift[5] = ccd_shift[2] + dev->current_setup.stagger; shift_count = 6; } /* convert data */ /* 0. fill_read_buffer -------------- read_buffer ---------------------- 1a). (opt)uncis (assumes color components to be laid out planar) 1b). (opt)reverse_RGB (assumes pixels to be BGR or BBGGRR)) -------------- lines_buffer ---------------------- 2a). (opt)line_distance_correction (assumes RGB or RRGGBB) 2b). (opt)unstagger (assumes pixels to be depth*channels/8 bytes long, unshrinked) ------------- shrink_buffer --------------------- 3. (opt)shrink_lines (assumes component separation in pixels) -------------- out_buffer ----------------------- 4. memcpy to destination (for lineart with bit reversal) */ /*FIXME: for lineart we need sub byte addressing in buffers, or conversion to bytes at 0. and back to bits at 4. Problems with the first approach: - its not clear how to check if we need to output an incomplete byte because it is the last one. */ /*FIXME: add lineart support for gl646. in the meantime add logic to convert from gray to lineart at the end? would suffer the above problem, total_bytes_to_read and total_bytes_read help in that case. */ status = genesys_fill_read_buffer (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_read_ordered_data: genesys_fill_read_buffer failed\n"); return status; } src_buffer = &(dev->read_buffer); /* maybe reorder components/bytes */ if (needs_reorder) { /*not implemented for depth == 1.*/ if (depth == 1) { DBG (DBG_error, "Can't reorder single bit data\n"); return SANE_STATUS_INVAL; } dst_buffer = &(dev->lines_buffer); work_buffer_src = sanei_genesys_buffer_get_read_pos (src_buffer); bytes = src_buffer->avail; /*how many bytes can be processed here?*/ /*we are greedy. we work as much as possible*/ if (bytes > dst_buffer->size - dst_buffer->avail) bytes = dst_buffer->size - dst_buffer->avail; dst_lines = (bytes * 8) / (src_pixels * channels * depth); bytes = (dst_lines * src_pixels * channels * depth) / 8; work_buffer_dst = sanei_genesys_buffer_get_write_pos (dst_buffer, bytes); DBG (DBG_info, "genesys_read_ordered_data: reordering %d lines\n", dst_lines); if (dst_lines != 0) { if (channels == 3) { step_1_mode = 0; if (depth == 16) step_1_mode |= 1; if (dev->model->is_cis) step_1_mode |= 2; if (dev->model->line_mode_color_order == COLOR_ORDER_BGR) step_1_mode |= 4; switch (step_1_mode) { case 1: /* RGB, chunky, 16 bit */ #ifdef WORDS_BIGENDIAN status = genesys_reorder_components_endian_16 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels, 3); break; #endif /*WORDS_BIGENDIAN */ case 0: /* RGB, chunky, 8 bit */ status = SANE_STATUS_GOOD; break; case 2: /* RGB, cis, 8 bit */ status = genesys_reorder_components_cis_8 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels); break; case 3: /* RGB, cis, 16 bit */ status = genesys_reorder_components_cis_16 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels); break; case 4: /* BGR, chunky, 8 bit */ status = genesys_reorder_components_bgr_8 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels); break; case 5: /* BGR, chunky, 16 bit */ status = genesys_reorder_components_bgr_16 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels); break; case 6: /* BGR, cis, 8 bit */ status = genesys_reorder_components_cis_bgr_8 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels); break; case 7: /* BGR, cis, 16 bit */ status = genesys_reorder_components_cis_bgr_16 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels); break; } } else { #ifdef WORDS_BIGENDIAN if (depth == 16) { status = genesys_reorder_components_endian_16 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels, 1); } else { status = SANE_STATUS_GOOD; } #else /*!WORDS_BIGENDIAN */ status = SANE_STATUS_GOOD; #endif /*WORDS_BIGENDIAN */ } if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_read_ordered_data: failed to convert byte ordering(%s)\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } RIE (sanei_genesys_buffer_produce (dst_buffer, bytes)); RIE (sanei_genesys_buffer_consume (src_buffer, bytes)); } src_buffer = dst_buffer; } /* maybe reverse effects of ccd layout */ if (needs_ccd) { /*should not happen with depth == 1.*/ if (depth == 1) { DBG (DBG_error, "Can't reverse ccd for single bit data\n"); return SANE_STATUS_INVAL; } dst_buffer = &(dev->shrink_buffer); work_buffer_src = sanei_genesys_buffer_get_read_pos (src_buffer); bytes = src_buffer->avail; extra = (dev->current_setup.max_shift * src_pixels * channels * depth) / 8; /*extra bytes are reserved, and should not be consumed*/ if (bytes < extra) bytes = 0; else bytes -= extra; /*how many bytes can be processed here?*/ /*we are greedy. we work as much as possible*/ if (bytes > dst_buffer->size - dst_buffer->avail) bytes = dst_buffer->size - dst_buffer->avail; dst_lines = (bytes * 8) / (src_pixels * channels * depth); bytes = (dst_lines * src_pixels * channels * depth) / 8; work_buffer_dst = sanei_genesys_buffer_get_write_pos (dst_buffer, bytes); DBG (DBG_info, "genesys_read_ordered_data: un-ccd-ing %d lines\n", dst_lines); if (dst_lines != 0) { if (depth == 8) status = genesys_reverse_ccd_8 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels * channels, ccd_shift, shift_count); else status = genesys_reverse_ccd_16 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels * channels, ccd_shift, shift_count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_read_ordered_data: failed to reverse ccd effects(%s)\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } RIE (sanei_genesys_buffer_produce (dst_buffer, bytes)); RIE (sanei_genesys_buffer_consume (src_buffer, bytes)); } src_buffer = dst_buffer; } /* maybe shrink(or enlarge) lines */ if (needs_shrink) { dst_buffer = &(dev->out_buffer); work_buffer_src = sanei_genesys_buffer_get_read_pos (src_buffer); bytes = src_buffer->avail; /*lines in input*/ dst_lines = (bytes * 8) / (src_pixels * channels * depth); /* how many lines can be processed here? */ /* we are greedy. we work as much as possible */ bytes = dst_buffer->size - dst_buffer->avail; if (dst_lines > (bytes * 8) / (dev->settings.pixels * channels * depth)) dst_lines = (bytes * 8) / (dev->settings.pixels * channels * depth); bytes = (dst_lines * dev->settings.pixels * channels * depth) / 8; work_buffer_dst = sanei_genesys_buffer_get_write_pos (dst_buffer, bytes); DBG (DBG_info, "genesys_read_ordered_data: shrinking %d lines\n", dst_lines); if (dst_lines != 0) { if (depth == 1) status = genesys_shrink_lines_1 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels, dev->settings.pixels, channels); else if (depth == 8) status = genesys_shrink_lines_8 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels, dev->settings.pixels, channels); else status = genesys_shrink_lines_16 (work_buffer_src, work_buffer_dst, dst_lines, src_pixels, dev->settings.pixels, channels); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_read_ordered_data: failed to shrink lines(%s)\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } /* we just consumed this many bytes*/ bytes = (dst_lines * src_pixels * channels * depth) / 8; RIE (sanei_genesys_buffer_consume (src_buffer, bytes)); /* we just created this many bytes*/ bytes = (dst_lines * dev->settings.pixels * channels * depth) / 8; RIE (sanei_genesys_buffer_produce (dst_buffer, bytes)); } src_buffer = dst_buffer; } /* move data to destination */ bytes = src_buffer->avail; if (bytes > *len) bytes = *len; work_buffer_src = sanei_genesys_buffer_get_read_pos (src_buffer); if (needs_reverse) { status = genesys_reverse_bits (work_buffer_src, destination, bytes); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "genesys_read_ordered_data: failed to reverse bits(%s)\n", sane_strstatus (status)); return SANE_STATUS_IO_ERROR; } *len = bytes; } else { memcpy (destination, work_buffer_src, bytes); *len = bytes; } /* avoid signaling some extra data because we have treated a full block * on the last block */ if (dev->total_bytes_read + *len > dev->total_bytes_to_read) *len = dev->total_bytes_to_read - dev->total_bytes_read; /* count bytes sent to frontend */ dev->total_bytes_read += *len; RIE (sanei_genesys_buffer_consume (src_buffer, bytes)); /* end scan if all needed data have been read */ if(dev->total_bytes_read >= dev->total_bytes_to_read) { dev->model->cmd_set->end_scan (dev, dev->reg, SANE_TRUE); if (dev->model->is_sheetfed == SANE_TRUE) { dev->model->cmd_set->eject_document (dev); } } DBG (DBG_proc, "genesys_read_ordered_data: completed, %lu bytes read\n", (u_long) bytes); return SANE_STATUS_GOOD; } /* ------------------------------------------------------------------------ */ /* Start of higher level functions */ /* ------------------------------------------------------------------------ */ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status calc_parameters (Genesys_Scanner * s) { SANE_String mode, source, color_filter; SANE_Status status = SANE_STATUS_GOOD; SANE_Int depth = 0, resolution = 0; double tl_x = 0, tl_y = 0, br_x = 0, br_y = 0; mode = s->val[OPT_MODE].s; source = s->val[OPT_SOURCE].s; color_filter = s->val[OPT_COLOR_FILTER].s; depth = s->val[OPT_BIT_DEPTH].w; resolution = s->val[OPT_RESOLUTION].w; tl_x = SANE_UNFIX (s->val[OPT_TL_X].w); tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w); br_x = SANE_UNFIX (s->val[OPT_BR_X].w); br_y = SANE_UNFIX (s->val[OPT_BR_Y].w); s->params.last_frame = SANE_TRUE; /* only single pass scanning supported */ if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0 || strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) s->params.format = SANE_FRAME_GRAY; else /* Color */ s->params.format = SANE_FRAME_RGB; if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) s->params.depth = 1; else s->params.depth = depth; s->dev->settings.depth = depth; /* interpolation */ s->dev->settings.disable_interpolation = s->val[OPT_DISABLE_INTERPOLATION].w == SANE_TRUE; /* hardware settings */ if (resolution > s->dev->sensor.optical_res && s->dev->settings.disable_interpolation) s->dev->settings.xres = s->dev->sensor.optical_res; else s->dev->settings.xres = resolution; s->dev->settings.yres = resolution; s->params.lines = ((br_y - tl_y) * s->dev->settings.yres) / MM_PER_INCH; s->params.pixels_per_line = ((br_x - tl_x) * resolution) / MM_PER_INCH; /* we need an even pixels number * TODO invert test logic or generalize behaviour across all ASICs */ if ((s->dev->model->flags & GENESYS_FLAG_SIS_SENSOR) || s->dev->model->asic_type == GENESYS_GL847 || s->dev->model->asic_type == GENESYS_GL124 || s->dev->model->asic_type == GENESYS_GL845 || s->dev->model->asic_type == GENESYS_GL846 || s->dev->model->asic_type == GENESYS_GL843) { if (s->dev->settings.xres <= 1200) s->params.pixels_per_line = (s->params.pixels_per_line/4)*4; else s->params.pixels_per_line = (s->params.pixels_per_line/16)*16; } /* corner case for true lineart for sensor with several segments * or when xres is doubled to match yres */ if (s->dev->settings.xres >= 1200 && ( s->dev->model->asic_type == GENESYS_GL124 || s->dev->model->asic_type == GENESYS_GL847 || s->dev->current_setup.xres < s->dev->current_setup.yres ) ) { s->params.pixels_per_line = (s->params.pixels_per_line/16)*16; } s->params.bytes_per_line = s->params.pixels_per_line; if (s->params.depth > 8) { s->params.depth = 16; s->params.bytes_per_line *= 2; } else if (s->params.depth == 1) { s->params.bytes_per_line /= 8; /* round down pixel number really? rounding down means loss of at most 7 pixels! -- pierre */ s->params.pixels_per_line = 8 * s->params.bytes_per_line; } if (s->params.format == SANE_FRAME_RGB) s->params.bytes_per_line *= 3; if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) s->dev->settings.scan_mode = SCAN_MODE_COLOR; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->dev->settings.scan_mode = SCAN_MODE_GRAY; else if (strcmp (mode, SANE_TITLE_HALFTONE) == 0) s->dev->settings.scan_mode = SCAN_MODE_HALFTONE; else /* Lineart */ s->dev->settings.scan_mode = SCAN_MODE_LINEART; /* TODO: change and check */ if (strcmp (source, FLATBED) == 0) s->dev->settings.scan_method = SCAN_METHOD_FLATBED; else /* transparency */ s->dev->settings.scan_method = SCAN_METHOD_TRANSPARENCY; s->dev->settings.lines = s->params.lines; s->dev->settings.pixels = s->params.pixels_per_line; s->dev->settings.tl_x = tl_x; s->dev->settings.tl_y = tl_y; /* threshold setting */ s->dev->settings.threshold = 2.55 * (SANE_UNFIX (s->val[OPT_THRESHOLD].w)); /* color filter */ if (strcmp (color_filter, "Red") == 0) s->dev->settings.color_filter = 0; else if (strcmp (color_filter, "Green") == 0) s->dev->settings.color_filter = 1; else if (strcmp (color_filter, "Blue") == 0) s->dev->settings.color_filter = 2; else s->dev->settings.color_filter = 3; /* true gray */ if (strcmp (color_filter, "None") == 0) s->dev->settings.true_gray = 1; else s->dev->settings.true_gray = 0; /* dynamic lineart */ s->dev->settings.dynamic_lineart = SANE_FALSE; s->dev->settings.threshold_curve=0; if(s->val[OPT_DISABLE_DYNAMIC_LINEART].w ==SANE_FALSE &&s->dev->settings.scan_mode == SCAN_MODE_LINEART) { s->dev->settings.dynamic_lineart = SANE_TRUE; } /* hardware lineart works only when we don't have interleave data * for GL847 scanners, ie up to 600 DPI, then we have to rely on * dynamic_lineart */ if(s->dev->settings.xres > 600 && s->dev->model->asic_type==GENESYS_GL847 && s->dev->settings.scan_mode == SCAN_MODE_LINEART) { s->dev->settings.dynamic_lineart = SANE_TRUE; } /* threshold curve for dynamic rasterization */ s->dev->settings.threshold_curve=s->val[OPT_THRESHOLD_CURVE].w; /* some digital processing requires the whole picture to be buffered */ /* no digital processing takes place when doing preview, or when bit depth is * higher than 8 bits */ if ((s->val[OPT_SWDESPECK].b || s->val[OPT_SWCROP].b || s->val[OPT_SWDESKEW].b || s->val[OPT_SWDEROTATE].b ||(SANE_UNFIX(s->val[OPT_SWSKIP].w)>0)) && (!s->val[OPT_PREVIEW].b) && (s->val[OPT_BIT_DEPTH].w <= 8)) { s->dev->buffer_image=SANE_TRUE; } else { s->dev->buffer_image=SANE_FALSE; } /* brigthness and contrast only for for 8 bit scans */ if(s->val[OPT_BIT_DEPTH].w <= 8) { s->dev->settings.contrast=(s->val[OPT_CONTRAST].w*127)/100; s->dev->settings.brightness=(s->val[OPT_BRIGHTNESS].w*127)/100; } else { s->dev->settings.contrast=0; s->dev->settings.brightness=0; } /* cache expiration time */ s->dev->settings.expiration_time=s->val[OPT_EXPIRATION_TIME].w; return status; } static SANE_Status create_bpp_list (Genesys_Scanner * s, SANE_Int * bpp) { int count; for (count = 0; bpp[count] != 0; count++) ; s->bpp_list[0] = count; for (count = 0; bpp[count] != 0; count++) { s->bpp_list[s->bpp_list[0] - count] = bpp[count]; } return SANE_STATUS_GOOD; } /** @brief this function initialize a gamma vector based on the ASIC: * Set up a default gamma table vector based on device description * gl646: 12 or 14 bits gamma table depending on GENESYS_FLAG_14BIT_GAMMA * gl84x: 16 bits * gl12x: 16 bits * @param scanner pointer to scanner session to get options * @param option option number of the gamma table to set */ static void init_gamma_vector_option (Genesys_Scanner * scanner, int option) { /* the option is inactive until the custom gamma control * is enabled */ scanner->opt[option].type = SANE_TYPE_INT; scanner->opt[option].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; scanner->opt[option].unit = SANE_UNIT_NONE; scanner->opt[option].constraint_type = SANE_CONSTRAINT_RANGE; if (scanner->dev->model->asic_type == GENESYS_GL646) { if ((scanner->dev->model->flags & GENESYS_FLAG_14BIT_GAMMA) != 0) { scanner->opt[option].size = 16384 * sizeof (SANE_Word); scanner->opt[option].constraint.range = &u14_range; } else { /* 12 bits gamma tables */ scanner->opt[option].size = 4096 * sizeof (SANE_Word); scanner->opt[option].constraint.range = &u12_range; } } else { /* other asics have 16 bits words gamma table */ scanner->opt[option].size = 256 * sizeof (SANE_Word); scanner->opt[option].constraint.range = &u16_range; } /* default value is NULL */ scanner->val[option].wa = NULL; } /** * allocate a geometry range * @param size maximum size of the range * @return a pointer to a valid range or NULL */ static SANE_Range *create_range(SANE_Fixed size) { SANE_Range *range=NULL; range=(SANE_Range *)malloc(sizeof(SANE_Range)); if(range!=NULL) { range->min = SANE_FIX (0.0); range->max = size; range->quant = SANE_FIX (0.0); } return range; } /** @brief generate calibration cache file nam * Generates the calibration cache file name to use. * Tries to store the chache in $HOME/.sane or * then fallbacks to $TMPDIR or TMP. The filename * uses the model name if only one scanner is plugged * else is uses the device name when several identical * scanners are in use. * @param currdev current scanner device * @return an allocated string containing a file name */ GENESYS_STATIC char *calibration_filename(Genesys_Device *currdev) { char *tmpstr; char *ptr; char filename[80]; Genesys_Device *dev; unsigned int count; unsigned int i; /* allocate space for result */ tmpstr=malloc(PATH_MAX); if(tmpstr==NULL) { return NULL; } /* first compute the DIR where we can store cache: * 1 - home dir * 2 - $TMPDIR * 3 - $TMP * 4 - tmp dir * 5 - temp dir * 6 - then resort to current dir */ ptr = getenv ("HOME"); if(ptr==NULL) { ptr = getenv ("USERPROFILE"); } if(ptr==NULL) { ptr = getenv ("TMPDIR"); } if(ptr==NULL) { ptr = getenv ("TMP"); } /* now choose filename: * 1 - if only one scanner, name of the model * 2 - if several scanners of the same model, use device name, * replacing special chars */ count=0; /* count models of the same names if several scanners attached */ if(num_devices>1) { for (dev = first_dev; dev; dev = dev->next) { if(strcmp(dev->model->name,currdev->model->name)==0) { count++; } } } if(count>1) { snprintf(filename,sizeof(filename),"%s.cal",currdev->file_name); for(i=0;imodel->name); } /* build final final name : store dir + filename */ if (NULL == ptr) { snprintf (tmpstr, PATH_MAX, "%s", filename); } else { #ifdef HAVE_MKDIR /* make sure .sane directory exists in existing store dir */ snprintf (tmpstr, PATH_MAX, "%s%c.sane", ptr, PATH_SEP); mkdir(tmpstr,0700); #endif snprintf (tmpstr, PATH_MAX, "%s%c.sane%c%s", ptr, PATH_SEP, PATH_SEP, filename); } DBG (DBG_info, "%s: calibration filename >%s<\n", __func__, tmpstr); return tmpstr; } static SANE_Status init_options (Genesys_Scanner * s) { SANE_Int option, count, min_dpi; SANE_Status status; SANE_Word *dpi_list; Genesys_Model *model = s->dev->model; SANE_Range *x_range, *y_range; DBGSTART; memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (option = 0; option < NUM_OPTIONS; ++option) { s->opt[option].size = sizeof (SANE_Word); s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (SANE_VALUE_SCAN_MODE_GRAY); /* scan source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].size = max_string_size (source_list); s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].s = strdup (FLATBED); if (model->flags & GENESYS_FLAG_HAS_UTA) { ENABLE (OPT_SOURCE); } else { DISABLE (OPT_SOURCE); } /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE; s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_PREVIEW].w = SANE_FALSE; /* bit depth */ s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_BIT_DEPTH].size = sizeof (SANE_Word); s->opt[OPT_BIT_DEPTH].constraint.word_list = 0; s->opt[OPT_BIT_DEPTH].constraint.word_list = s->bpp_list; create_bpp_list (s, model->bpp_gray_values); s->val[OPT_BIT_DEPTH].w = 8; if (s->opt[OPT_BIT_DEPTH].constraint.word_list[0] < 2) DISABLE (OPT_BIT_DEPTH); /* resolution */ min_dpi=200000; for (count = 0; model->xdpi_values[count] != 0; count++) { if(model->xdpi_values[count]xdpi_values[count]; } } dpi_list = malloc ((count + 1) * sizeof (SANE_Word)); if (!dpi_list) return SANE_STATUS_NO_MEM; dpi_list[0] = count; for (count = 0; model->xdpi_values[count] != 0; count++) dpi_list[count + 1] = model->xdpi_values[count]; s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; s->val[OPT_RESOLUTION].w = min_dpi; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; x_range=create_range(model->x_size); if(x_range==NULL) { return SANE_STATUS_NO_MEM; } y_range=create_range(model->y_size); if(y_range==NULL) { return SANE_STATUS_NO_MEM; } /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = x_range; s->val[OPT_BR_X].w = x_range->max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = y_range; s->val[OPT_BR_Y].w = y_range->max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_ADVANCED; s->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; init_gamma_vector_option (s, OPT_GAMMA_VECTOR); /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; init_gamma_vector_option (s, OPT_GAMMA_VECTOR_R); /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; init_gamma_vector_option (s, OPT_GAMMA_VECTOR_G); /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; init_gamma_vector_option (s, OPT_GAMMA_VECTOR_B); /* currently, there are only gamma table options in this group, * so if the scanner doesn't support gamma table, disable the * whole group */ if (!(model->flags & GENESYS_FLAG_CUSTOM_GAMMA)) { s->opt[OPT_ENHANCEMENT_GROUP].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; DBG (DBG_info, "init_options: custom gamma disabled\n"); } /* software base image enhancements, these are consuming as many * memory than used by the full scanned image and may fail at high * resolution */ /* software deskew */ s->opt[OPT_SWDESKEW].name = "swdeskew"; s->opt[OPT_SWDESKEW].title = "Software deskew"; s->opt[OPT_SWDESKEW].desc = "Request backend to rotate skewed pages digitally"; s->opt[OPT_SWDESKEW].type = SANE_TYPE_BOOL; s->opt[OPT_SWDESKEW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; s->val[OPT_SWDESKEW].b = SANE_FALSE; /* software deskew */ s->opt[OPT_SWDESPECK].name = "swdespeck"; s->opt[OPT_SWDESPECK].title = "Software despeck"; s->opt[OPT_SWDESPECK].desc = "Request backend to remove lone dots digitally"; s->opt[OPT_SWDESPECK].type = SANE_TYPE_BOOL; s->opt[OPT_SWDESPECK].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; s->val[OPT_SWDESPECK].b = SANE_FALSE; /* software despeckle radius */ s->opt[OPT_DESPECK].name = "despeck"; s->opt[OPT_DESPECK].title = "Software despeckle diameter"; s->opt[OPT_DESPECK].desc = "Maximum diameter of lone dots to remove from scan"; s->opt[OPT_DESPECK].type = SANE_TYPE_INT; s->opt[OPT_DESPECK].unit = SANE_UNIT_NONE; s->opt[OPT_DESPECK].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_DESPECK].constraint.range = &swdespeck_range; s->opt[OPT_DESPECK].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED | SANE_CAP_INACTIVE; s->val[OPT_DESPECK].w = 1; /* crop by software */ s->opt[OPT_SWCROP].name = "swcrop"; s->opt[OPT_SWCROP].title = SANE_I18N ("Software crop"); s->opt[OPT_SWCROP].desc = SANE_I18N ("Request backend to remove border from pages digitally"); s->opt[OPT_SWCROP].type = SANE_TYPE_BOOL; s->opt[OPT_SWCROP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; s->opt[OPT_SWCROP].unit = SANE_UNIT_NONE; s->val[OPT_SWCROP].b = SANE_FALSE; /* Software blank page skip */ s->opt[OPT_SWSKIP].name = "swskip"; s->opt[OPT_SWSKIP].title = SANE_I18N ("Software blank skip percentage"); s->opt[OPT_SWSKIP].desc = SANE_I18N("Request driver to discard pages with low numbers of dark pixels"); s->opt[OPT_SWSKIP].type = SANE_TYPE_FIXED; s->opt[OPT_SWSKIP].unit = SANE_UNIT_PERCENT; s->opt[OPT_SWSKIP].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_SWSKIP].constraint.range = &(percentage_range); s->opt[OPT_SWSKIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; /* disable by default */ s->val[OPT_SWSKIP].w = 0; /* Software Derotate */ s->opt[OPT_SWDEROTATE].name = "swderotate"; s->opt[OPT_SWDEROTATE].title = SANE_I18N ("Software derotate"); s->opt[OPT_SWDEROTATE].desc = SANE_I18N("Request driver to detect and correct 90 degree image rotation"); s->opt[OPT_SWDEROTATE].type = SANE_TYPE_BOOL; s->opt[OPT_SWDEROTATE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; s->opt[OPT_SWDEROTATE].unit = SANE_UNIT_NONE; s->val[OPT_SWDEROTATE].b = SANE_FALSE; /* Software brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &(enhance_range); s->opt[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* disable by default */ s->val[OPT_BRIGHTNESS].w = 0; /* Sowftware contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &(enhance_range); s->opt[OPT_CONTRAST].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* disable by default */ s->val[OPT_CONTRAST].w = 0; /* "Extras" group: */ s->opt[OPT_EXTRAS_GROUP].title = SANE_I18N ("Extras"); s->opt[OPT_EXTRAS_GROUP].desc = ""; s->opt[OPT_EXTRAS_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_EXTRAS_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_EXTRAS_GROUP].size = 0; s->opt[OPT_EXTRAS_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* BW threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &percentage_range; s->val[OPT_THRESHOLD].w = SANE_FIX (50); /* BW threshold curve */ s->opt[OPT_THRESHOLD_CURVE].name = "threshold-curve"; s->opt[OPT_THRESHOLD_CURVE].title = SANE_I18N ("Threshold curve"); s->opt[OPT_THRESHOLD_CURVE].desc = SANE_I18N ("Dynamic threshold curve, from light to dark, normally 50-65"); s->opt[OPT_THRESHOLD_CURVE].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD_CURVE].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD_CURVE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD_CURVE].constraint.range = &threshold_curve_range; s->val[OPT_THRESHOLD_CURVE].w = 50; /* dynamic linart */ s->opt[OPT_DISABLE_DYNAMIC_LINEART].name = "disable-dynamic-lineart"; s->opt[OPT_DISABLE_DYNAMIC_LINEART].title = SANE_I18N ("Disable dynamic lineart"); s->opt[OPT_DISABLE_DYNAMIC_LINEART].desc = SANE_I18N ("Disable use of a software adaptive algorithm to generate lineart relying instead on hardware lineart."); s->opt[OPT_DISABLE_DYNAMIC_LINEART].type = SANE_TYPE_BOOL; s->opt[OPT_DISABLE_DYNAMIC_LINEART].unit = SANE_UNIT_NONE; s->opt[OPT_DISABLE_DYNAMIC_LINEART].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_DISABLE_DYNAMIC_LINEART].w = SANE_FALSE; /* fastmod is required for hw lineart to work */ if ((s->dev->model->asic_type == GENESYS_GL646) &&(s->dev->model->motor_type != MOTOR_XP200)) { s->opt[OPT_DISABLE_DYNAMIC_LINEART].cap = SANE_CAP_INACTIVE; } /* disable_interpolation */ s->opt[OPT_DISABLE_INTERPOLATION].name = "disable-interpolation"; s->opt[OPT_DISABLE_INTERPOLATION].title = SANE_I18N ("Disable interpolation"); s->opt[OPT_DISABLE_INTERPOLATION].desc = SANE_I18N ("When using high resolutions where the horizontal resolution is smaller " "than the vertical resolution this disables horizontal interpolation."); s->opt[OPT_DISABLE_INTERPOLATION].type = SANE_TYPE_BOOL; s->opt[OPT_DISABLE_INTERPOLATION].unit = SANE_UNIT_NONE; s->opt[OPT_DISABLE_INTERPOLATION].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_DISABLE_INTERPOLATION].w = SANE_FALSE; /* color filter */ s->opt[OPT_COLOR_FILTER].name = "color-filter"; s->opt[OPT_COLOR_FILTER].title = SANE_I18N ("Color filter"); s->opt[OPT_COLOR_FILTER].desc = SANE_I18N ("When using gray or lineart this option selects the used color."); s->opt[OPT_COLOR_FILTER].type = SANE_TYPE_STRING; s->opt[OPT_COLOR_FILTER].constraint_type = SANE_CONSTRAINT_STRING_LIST; /* true gray not yet supported for GL847 and GL124 scanners */ if(!model->is_cis || model->asic_type==GENESYS_GL847 || model->asic_type==GENESYS_GL124) { s->opt[OPT_COLOR_FILTER].size = max_string_size (color_filter_list); s->opt[OPT_COLOR_FILTER].constraint.string_list = color_filter_list; s->val[OPT_COLOR_FILTER].s = strdup (s->opt[OPT_COLOR_FILTER].constraint.string_list[1]); } else { s->opt[OPT_COLOR_FILTER].size = max_string_size (cis_color_filter_list); s->opt[OPT_COLOR_FILTER].constraint.string_list = cis_color_filter_list; /* default to "None" ie true gray */ s->val[OPT_COLOR_FILTER].s = strdup (s->opt[OPT_COLOR_FILTER].constraint.string_list[3]); } /* no support for color filter for cis+gl646 scanners */ if (model->asic_type == GENESYS_GL646 && model->is_cis) { DISABLE (OPT_COLOR_FILTER); } /* calibration store file name */ s->opt[OPT_CALIBRATION_FILE].name = "calibration-file"; s->opt[OPT_CALIBRATION_FILE].title = SANE_I18N ("Calibration file"); s->opt[OPT_CALIBRATION_FILE].desc = SANE_I18N ("Specify the calibration file to use"); s->opt[OPT_CALIBRATION_FILE].type = SANE_TYPE_STRING; s->opt[OPT_CALIBRATION_FILE].unit = SANE_UNIT_NONE; s->opt[OPT_CALIBRATION_FILE].size = PATH_MAX; s->opt[OPT_CALIBRATION_FILE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; s->opt[OPT_CALIBRATION_FILE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_CALIBRATION_FILE].s = NULL; /* disable option if ran as root */ #ifdef HAVE_GETUID if(geteuid()==0) { DISABLE (OPT_CALIBRATION_FILE); } #endif /* expiration time for calibration cache entries */ s->opt[OPT_EXPIRATION_TIME].name = "expiration-time"; s->opt[OPT_EXPIRATION_TIME].title = SANE_I18N ("Calibration cache expiration time"); s->opt[OPT_EXPIRATION_TIME].desc = SANE_I18N ("Time (in minutes) before a cached calibration expires. " "A value of 0 means cache is not used. A negative value means cache never expires."); s->opt[OPT_EXPIRATION_TIME].type = SANE_TYPE_INT; s->opt[OPT_EXPIRATION_TIME].unit = SANE_UNIT_NONE; s->opt[OPT_EXPIRATION_TIME].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_EXPIRATION_TIME].constraint.range = &expiration_range; s->val[OPT_EXPIRATION_TIME].w = 60; /* 60 minutes by default */ /* Powersave time (turn lamp off) */ s->opt[OPT_LAMP_OFF_TIME].name = "lamp-off-time"; s->opt[OPT_LAMP_OFF_TIME].title = SANE_I18N ("Lamp off time"); s->opt[OPT_LAMP_OFF_TIME].desc = SANE_I18N ("The lamp will be turned off after the given time (in minutes). " "A value of 0 means, that the lamp won't be turned off."); s->opt[OPT_LAMP_OFF_TIME].type = SANE_TYPE_INT; s->opt[OPT_LAMP_OFF_TIME].unit = SANE_UNIT_NONE; s->opt[OPT_LAMP_OFF_TIME].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_LAMP_OFF_TIME].constraint.range = &time_range; s->val[OPT_LAMP_OFF_TIME].w = 15; /* 15 minutes */ /* turn lamp off during scan */ s->opt[OPT_LAMP_OFF].name = "lamp-off-scan"; s->opt[OPT_LAMP_OFF].title = SANE_I18N ("Lamp off during scan"); s->opt[OPT_LAMP_OFF].desc = SANE_I18N ("The lamp will be turned off during scan. "); s->opt[OPT_LAMP_OFF].type = SANE_TYPE_BOOL; s->opt[OPT_LAMP_OFF].unit = SANE_UNIT_NONE; s->opt[OPT_LAMP_OFF].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_LAMP_OFF].w = SANE_FALSE; s->opt[OPT_SENSOR_GROUP].title = SANE_TITLE_SENSORS; s->opt[OPT_SENSOR_GROUP].desc = SANE_DESC_SENSORS; s->opt[OPT_SENSOR_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_SENSOR_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_SENSOR_GROUP].size = 0; s->opt[OPT_SENSOR_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_SCAN_SW].name = SANE_NAME_SCAN; s->opt[OPT_SCAN_SW].title = SANE_TITLE_SCAN; s->opt[OPT_SCAN_SW].desc = SANE_DESC_SCAN; s->opt[OPT_SCAN_SW].type = SANE_TYPE_BOOL; s->opt[OPT_SCAN_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_SCAN_SW) s->opt[OPT_SCAN_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_SCAN_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_SCAN_SW].b = 0; s->last_val[OPT_SCAN_SW].b = 0; /* SANE_NAME_FILE is not for buttons */ s->opt[OPT_FILE_SW].name = "file"; s->opt[OPT_FILE_SW].title = SANE_I18N ("File button"); s->opt[OPT_FILE_SW].desc = SANE_I18N ("File button"); s->opt[OPT_FILE_SW].type = SANE_TYPE_BOOL; s->opt[OPT_FILE_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_FILE_SW) s->opt[OPT_FILE_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_FILE_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_FILE_SW].b = 0; s->last_val[OPT_FILE_SW].b = 0; s->opt[OPT_EMAIL_SW].name = SANE_NAME_EMAIL; s->opt[OPT_EMAIL_SW].title = SANE_TITLE_EMAIL; s->opt[OPT_EMAIL_SW].desc = SANE_DESC_EMAIL; s->opt[OPT_EMAIL_SW].type = SANE_TYPE_BOOL; s->opt[OPT_EMAIL_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_EMAIL_SW) s->opt[OPT_EMAIL_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_EMAIL_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_EMAIL_SW].b = 0; s->last_val[OPT_EMAIL_SW].b = 0; s->opt[OPT_COPY_SW].name = SANE_NAME_COPY; s->opt[OPT_COPY_SW].title = SANE_TITLE_COPY; s->opt[OPT_COPY_SW].desc = SANE_DESC_COPY; s->opt[OPT_COPY_SW].type = SANE_TYPE_BOOL; s->opt[OPT_COPY_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_COPY_SW) s->opt[OPT_COPY_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_COPY_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_COPY_SW].b = 0; s->last_val[OPT_COPY_SW].b = 0; s->opt[OPT_PAGE_LOADED_SW].name = SANE_NAME_PAGE_LOADED; s->opt[OPT_PAGE_LOADED_SW].title = SANE_TITLE_PAGE_LOADED; s->opt[OPT_PAGE_LOADED_SW].desc = SANE_DESC_PAGE_LOADED; s->opt[OPT_PAGE_LOADED_SW].type = SANE_TYPE_BOOL; s->opt[OPT_PAGE_LOADED_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_PAGE_LOADED_SW) s->opt[OPT_PAGE_LOADED_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_PAGE_LOADED_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_PAGE_LOADED_SW].b = 0; s->last_val[OPT_PAGE_LOADED_SW].b = 0; /* OCR button */ s->opt[OPT_OCR_SW].name = "ocr"; s->opt[OPT_OCR_SW].title = SANE_I18N ("OCR button"); s->opt[OPT_OCR_SW].desc = SANE_I18N ("OCR button"); s->opt[OPT_OCR_SW].type = SANE_TYPE_BOOL; s->opt[OPT_OCR_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_OCR_SW) s->opt[OPT_OCR_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_OCR_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_OCR_SW].b = 0; s->last_val[OPT_OCR_SW].b = 0; /* power button */ s->opt[OPT_POWER_SW].name = "power"; s->opt[OPT_POWER_SW].title = SANE_I18N ("Power button"); s->opt[OPT_POWER_SW].desc = SANE_I18N ("Power button"); s->opt[OPT_POWER_SW].type = SANE_TYPE_BOOL; s->opt[OPT_POWER_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_POWER_SW) s->opt[OPT_POWER_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_POWER_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_POWER_SW].b = 0; s->last_val[OPT_POWER_SW].b = 0; /* extra button */ s->opt[OPT_EXTRA_SW].name = "extra"; s->opt[OPT_EXTRA_SW].title = SANE_I18N ("Extra button"); s->opt[OPT_EXTRA_SW].desc = SANE_I18N ("Extra button"); s->opt[OPT_EXTRA_SW].type = SANE_TYPE_BOOL; s->opt[OPT_EXTRA_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_EXTRA_SW) s->opt[OPT_EXTRA_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_EXTRA_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_EXTRA_SW].b = 0; s->last_val[OPT_EXTRA_SW].b = 0; /* calibration needed */ s->opt[OPT_NEED_CALIBRATION_SW].name = "need-calibration"; s->opt[OPT_NEED_CALIBRATION_SW].title = SANE_I18N ("Need calibration"); s->opt[OPT_NEED_CALIBRATION_SW].desc = SANE_I18N ("The scanner needs calibration for the current settings"); s->opt[OPT_NEED_CALIBRATION_SW].type = SANE_TYPE_BOOL; s->opt[OPT_NEED_CALIBRATION_SW].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_CALIBRATE) s->opt[OPT_NEED_CALIBRATION_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_NEED_CALIBRATION_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_NEED_CALIBRATION_SW].b = 0; s->last_val[OPT_NEED_CALIBRATION_SW].b = 0; /* button group */ s->opt[OPT_BUTTON_GROUP].title = SANE_I18N ("Buttons"); s->opt[OPT_BUTTON_GROUP].desc = ""; s->opt[OPT_BUTTON_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_BUTTON_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_BUTTON_GROUP].size = 0; s->opt[OPT_BUTTON_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* calibrate button */ s->opt[OPT_CALIBRATE].name = "calibrate"; s->opt[OPT_CALIBRATE].title = SANE_I18N ("Calibrate"); s->opt[OPT_CALIBRATE].desc = SANE_I18N ("Start calibration using special sheet"); s->opt[OPT_CALIBRATE].type = SANE_TYPE_BUTTON; s->opt[OPT_CALIBRATE].unit = SANE_UNIT_NONE; if (model->buttons & GENESYS_HAS_CALIBRATE) s->opt[OPT_CALIBRATE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; else s->opt[OPT_CALIBRATE].cap = SANE_CAP_INACTIVE; s->val[OPT_CALIBRATE].b = 0; s->last_val[OPT_CALIBRATE].b = 0; /* clear calibration cache button */ s->opt[OPT_CLEAR_CALIBRATION].name = "clear-calibration"; s->opt[OPT_CLEAR_CALIBRATION].title = SANE_I18N ("Clear calibration"); s->opt[OPT_CLEAR_CALIBRATION].desc = SANE_I18N ("Clear calibration cache"); s->opt[OPT_CLEAR_CALIBRATION].type = SANE_TYPE_BUTTON; s->opt[OPT_CLEAR_CALIBRATION].unit = SANE_UNIT_NONE; s->opt[OPT_CLEAR_CALIBRATION].size = 0; s->opt[OPT_CLEAR_CALIBRATION].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_CLEAR_CALIBRATION].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; s->val[OPT_CLEAR_CALIBRATION].b = 0; s->last_val[OPT_CLEAR_CALIBRATION].b = 0; RIE (calc_parameters (s)); DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Bool present; static SANE_Status check_present (SANE_String_Const devname) { present=SANE_TRUE; DBG (DBG_io, "check_present: %s detected.\n",devname); return SANE_STATUS_GOOD; } /** @brief add a scanner device * Insert the given device into the backend list of devices. * @param dev device to add */ GENESYS_STATIC void add_device(Genesys_Device *dev) { ++num_devices; dev->next = first_dev; first_dev = dev; } static SANE_Status attach (SANE_String_Const devname, Genesys_Device ** devp, SANE_Bool may_wait) { Genesys_Device *dev = 0; SANE_Int dn, vendor, product; SANE_Status status; unsigned int i; DBG (DBG_proc, "attach: start: devp %s NULL, may_wait = %d\n", devp ? "!=" : "==", may_wait); if (devp) *devp = 0; if (!devname) { DBG (DBG_error, "attach: devname == NULL\n"); return SANE_STATUS_INVAL; } for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->file_name, devname) == 0) { if (devp) *devp = dev; DBG (DBG_info, "attach: device `%s' was already in device list\n", devname); return SANE_STATUS_GOOD; } } DBG (DBG_info, "attach: trying to open device `%s'\n", devname); status = sanei_usb_open (devname, &dn); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "attach: couldn't open device `%s': %s\n", devname, sane_strstatus (status)); return status; } else DBG (DBG_info, "attach: device `%s' successfully opened\n", devname); status = sanei_usb_get_vendor_product (dn, &vendor, &product); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "attach: couldn't get vendor and product ids of device `%s': %s\n", devname, sane_strstatus (status)); return status; } /* KV-SS080 is an auxiliary device which requires a master device to be here */ if(vendor == 0x04da && product == 0x100f) { present=SANE_FALSE; sanei_usb_find_devices (vendor, 0x1006, check_present); sanei_usb_find_devices (vendor, 0x1007, check_present); sanei_usb_find_devices (vendor, 0x1010, check_present); if(present==SANE_FALSE) { DBG (DBG_error,"attach: master device not present\n"); return SANE_STATUS_INVAL; } } for (i = 0; i < MAX_SCANNERS && genesys_usb_device_list[i].model != 0; i++) { if (vendor == genesys_usb_device_list[i].vendor && product == genesys_usb_device_list[i].product) { dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; break; } } if (!dev) { DBG (DBG_error, "attach: vendor %d product %d is not supported by this backend\n", vendor, product); return SANE_STATUS_INVAL; } dev->file_name = strdup (devname); if (!dev->file_name) { free(dev); return SANE_STATUS_NO_MEM; } dev->model = genesys_usb_device_list[i].model; dev->vendorId = genesys_usb_device_list[i].vendor; dev->productId = genesys_usb_device_list[i].product; dev->already_initialized = SANE_FALSE; DBG (DBG_info, "attach: found %s flatbed scanner %s at %s\n", dev->model->vendor, dev->model->model, dev->file_name); add_device(dev); if (devp) *devp = dev; sanei_usb_close (dn); DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status attach_one_device (SANE_String_Const devname) { Genesys_Device *dev; SANE_Status status; Genesys_Device **tmp_dev; RIE (attach (devname, &dev, SANE_FALSE)); if (dev) { /* Keep track of newly attached devices so we can set options as necessary. */ tmp_dev=NULL; /* increase device list capacity if needed */ if (new_dev_len >= new_dev_alloced) { new_dev_alloced += 4; if (new_dev) { tmp_dev = new_dev; new_dev = realloc (new_dev, new_dev_alloced * sizeof (new_dev[0])); } else { new_dev = malloc (new_dev_alloced * sizeof (new_dev[0])); tmp_dev = NULL; } if (!new_dev) { FREE_IFNOT_NULL(tmp_dev) DBG (DBG_error, "attach_one_device: out of memory\n"); return SANE_STATUS_NO_MEM; } } new_dev[new_dev_len++] = dev; } return SANE_STATUS_GOOD; } /* configuration framework functions */ static SANE_Status config_attach_genesys (SANEI_Config __sane_unused__ *config, const char *devname) { /* the devname has been processed and is ready to be used * directly. Since the backend is an USB only one, we can * call sanei_usb_attach_matching_devices straight */ sanei_usb_attach_matching_devices (devname, attach_one_device); return SANE_STATUS_GOOD; } /* probes for scanner to attach to the backend */ #ifndef UNIT_TESTING static #endif SANE_Status probe_genesys_devices (void) { SANEI_Config config; SANE_Status status; DBGSTART; new_dev = 0; new_dev_len = 0; new_dev_alloced = 0; /* set configuration options structure : no option for this backend */ config.descriptors = NULL; config.values = NULL; config.count = 0; /* generic configure and attach function */ status = sanei_configure_attach (GENESYS_CONFIG_FILE, &config, config_attach_genesys); if (new_dev_alloced > 0) { new_dev_len = new_dev_alloced = 0; free (new_dev); } DBG(DBG_info, "%s: %d devices currently attached\n", __func__, num_devices); DBGCOMPLETED; return status; } /** * This should be changed if one of the substructures of Genesys_Calibration_Cache change, but it must be changed if there are changes that don't change size -- at least for now, as we store most of Genesys_Calibration_Cache as is. */ #define CALIBRATION_VERSION 1 /** * reads previously cached calibration data * from file define in dev->calib_file */ SANE_Status sanei_genesys_read_calibration (Genesys_Device * dev) { FILE *fp; uint8_t vers = 0; uint32_t size = 0; struct Genesys_Calibration_Cache *cache; SANE_Status status=SANE_STATUS_GOOD; DBGSTART; /* open calibration cache file */ fp = fopen (dev->calib_file, "rb"); if (!fp) { DBG (DBG_info, "Calibration: Cannot open %s\n", dev->calib_file); DBGCOMPLETED; return SANE_STATUS_IO_ERROR; } /* these two checks ensure that most bad things cannot happen */ fread (&vers, 1, 1, fp); if (vers != CALIBRATION_VERSION) { DBG (DBG_info, "Calibration: Bad version\n"); fclose (fp); DBGCOMPLETED; return SANE_STATUS_INVAL; } fread (&size, 4, 1, fp); if (size != sizeof (struct Genesys_Calibration_Cache)) { DBG (DBG_info, "Calibration: Size of calibration cache struct differs\n"); fclose (fp); DBGCOMPLETED; return SANE_STATUS_INVAL; } /* clear device calibration cache */ while(dev->calibration_cache!=NULL) { cache=dev->calibration_cache; dev->calibration_cache=dev->calibration_cache->next; free(cache); } /* loop on cache records in file */ while (!feof (fp) && status==SANE_STATUS_GOOD) { DBG (DBG_info, "sanei_genesys_read_calibration: reading one record\n"); cache = (struct Genesys_Calibration_Cache *) malloc (sizeof (*cache)); if (!cache) { DBG (DBG_error, "sanei_genesys_read_calibration: could not allocate cache struct\n"); break; } #define BILT1( x ) \ do \ { \ if ((x) < 1) \ { \ free(cache); \ DBG (DBG_warn, "sanei_genesys_read_calibration: partial calibration record\n"); \ status=SANE_STATUS_EOF; \ break; \ } \ } while(0) if (fread (&cache->used_setup, sizeof (cache->used_setup), 1, fp) < 1) { /* eof is only detected here */ free (cache); status=SANE_STATUS_GOOD; break; } BILT1 (fread (&cache->last_calibration, sizeof (cache->last_calibration), 1, fp)); BILT1 (fread (&cache->frontend, sizeof (cache->frontend), 1, fp)); /* the gamma (and later) fields are not stored */ BILT1 (fread (&cache->sensor, offsetof (Genesys_Sensor, gamma[0]), 1, fp)); BILT1 (fread (&cache->calib_pixels, sizeof (cache->calib_pixels), 1, fp)); BILT1 (fread (&cache->calib_channels, sizeof (cache->calib_channels), 1, fp)); BILT1 (fread (&cache->average_size, sizeof (cache->average_size), 1, fp)); cache->white_average_data = (uint8_t *) malloc (cache->average_size); cache->dark_average_data = (uint8_t *) malloc (cache->average_size); if (!cache->white_average_data || !cache->dark_average_data) { status=SANE_STATUS_NO_MEM; FREE_IFNOT_NULL (cache->white_average_data); FREE_IFNOT_NULL (cache->dark_average_data); free (cache); DBG (DBG_error, "sanei_genesys_read_calibration: could not allocate space for average data\n"); break; } if (fread (cache->white_average_data, cache->average_size, 1, fp) < 1) { status=SANE_STATUS_EOF; DBG (DBG_warn, "sanei_genesys_read_calibration: partial calibration record\n"); free (cache->white_average_data); free (cache->dark_average_data); free (cache); break; } if (fread (cache->dark_average_data, cache->average_size, 1, fp) < 1) { DBG (DBG_warn, "sanei_genesys_read_calibration: partial calibration record\n"); free (cache->white_average_data); free (cache->dark_average_data); free (cache); status=SANE_STATUS_EOF; break; } #undef BILT1 DBG (DBG_info, "sanei_genesys_read_calibration: adding record to list\n"); cache->next = dev->calibration_cache; dev->calibration_cache = cache; } fclose (fp); DBGCOMPLETED; return status; } static void write_calibration (Genesys_Device * dev) { FILE *fp; uint8_t vers = 0; uint32_t size = 0; struct Genesys_Calibration_Cache *cache; DBGSTART; fp = fopen (dev->calib_file, "wb"); if (!fp) { DBG (DBG_info, "write_calibration: Cannot open %s for writing\n", dev->calib_file); return; } vers = CALIBRATION_VERSION; fwrite (&vers, 1, 1, fp); size = sizeof (struct Genesys_Calibration_Cache); fwrite (&size, 4, 1, fp); for (cache = dev->calibration_cache; cache; cache = cache->next) { fwrite (&cache->used_setup, sizeof (cache->used_setup), 1, fp); fwrite (&cache->last_calibration, sizeof (cache->last_calibration), 1, fp); fwrite (&cache->frontend, sizeof (cache->frontend), 1, fp); /* the gamma (and later) fields are not stored */ fwrite (&cache->sensor, offsetof (Genesys_Sensor, gamma[0]), 1, fp); fwrite (&cache->calib_pixels, sizeof (cache->calib_pixels), 1, fp); fwrite (&cache->calib_channels, sizeof (cache->calib_channels), 1, fp); fwrite (&cache->average_size, sizeof (cache->average_size), 1, fp); fwrite (cache->white_average_data, cache->average_size, 1, fp); fwrite (cache->dark_average_data, cache->average_size, 1, fp); } DBGCOMPLETED; fclose (fp); } /** @brief buffer scanned picture * In order to allow digital processing, we must be able to put all the * scanned picture in a buffer. */ static SANE_Status genesys_buffer_image(Genesys_Scanner *s) { SANE_Status status = SANE_STATUS_GOOD; size_t maximum; /**> maximum bytes size of the scan */ size_t len; /**> length of scanned data read */ size_t total; /**> total of butes read */ size_t size; /**> size of image buffer */ size_t read_size; /**> size of reads */ int lines; /** number of lines of the scan */ Genesys_Device *dev = s->dev; SANE_Byte *lineart=NULL; /* compute maximum number of lines for the scan */ if (s->params.lines > 0) { lines = s->params.lines; } else { lines = (SANE_UNFIX (dev->model->y_size) * dev->settings.yres) / MM_PER_INCH; } DBG (DBG_info, "%s: buffering %d lines of %d bytes\n", __func__, lines, s->params.bytes_per_line); /* maximum bytes to read */ maximum = s->params.bytes_per_line * lines; if(s->dev->settings.dynamic_lineart==SANE_TRUE) { maximum *= 8; } /* initial size of the read buffer */ size = ((2048 * 2048) / s->params.bytes_per_line) * s->params.bytes_per_line; /* read size */ read_size = size / 2; /* allocate memory */ dev->img_buffer = (SANE_Byte *) malloc (size); if (dev->img_buffer == NULL) { DBG (DBG_error, "%s: digital processing requires too much memory.\nConsider disabling it\n", __func__); return SANE_STATUS_NO_MEM; } /* loop reading data until we reach maximum or EOF */ total = 0; while (total < maximum && status != SANE_STATUS_EOF) { len = size - maximum; if (len > read_size) { len = read_size; } status = genesys_read_ordered_data (dev, dev->img_buffer + total, &len); if (status != SANE_STATUS_EOF && status != SANE_STATUS_GOOD) { free (s->dev->img_buffer); DBG (DBG_error, "%s: %s buffering failed\n", __func__, sane_strstatus (status)); return status; } total += len; /* do we need to enlarge read buffer ? */ if (total + read_size > size && status != SANE_STATUS_EOF) { size += read_size; dev->img_buffer = (SANE_Byte *) realloc (dev->img_buffer, size); if (dev->img_buffer == NULL) { DBG (DBG_error0, "%s: digital processing requires too much memory.\nConsider disabling it\n", __func__); return SANE_STATUS_NO_MEM; } } } /* since digital processing is going to take place, * issue head parking command so that the head move while * computing so we can save time */ if (dev->model->is_sheetfed == SANE_FALSE && dev->parking == SANE_FALSE) { dev->model->cmd_set->slow_back_home (dev, dev->model->flags & GENESYS_FLAG_MUST_WAIT); dev->parking = !(s->dev->model->flags & GENESYS_FLAG_MUST_WAIT); } /* in case of dynamic lineart, we have buffered gray data which * must be converted to lineart first */ if(s->dev->settings.dynamic_lineart==SANE_TRUE) { total/=8; lineart=(SANE_Byte *)malloc(total); if (lineart == NULL) { DBG (DBG_error0, "%s: digital processing requires too much memory.\nConsider disabling it\n", __func__); return SANE_STATUS_NO_MEM; } genesys_gray_lineart (dev, dev->img_buffer, lineart, dev->settings.pixels, (total*8)/dev->settings.pixels, dev->settings.threshold); free(dev->img_buffer); dev->img_buffer = lineart; } /* update counters */ dev->total_bytes_to_read = total; dev->total_bytes_read = 0; /* update params */ s->params.lines = total / s->params.bytes_per_line; if (DBG_LEVEL >= DBG_io2) { sanei_genesys_write_pnm_file ("unprocessed.pnm", dev->img_buffer, s->params.depth, s->params.format==SANE_FRAME_RGB ? 3:1, s->params.pixels_per_line, s->params.lines); } return SANE_STATUS_GOOD; } /* -------------------------- SANE API functions ------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { SANE_Status status; DBG_INIT (); DBG (DBG_init, "SANE Genesys backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); #ifdef HAVE_LIBUSB DBG (DBG_init, "SANE Genesys backend built with libusb-1.0\n"); #endif #ifdef HAVE_LIBUSB_LEGACY DBG (DBG_init, "SANE Genesys backend built with libusb\n"); #endif if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_proc, "sane_init: authorize %s null\n", authorize ? "!=" : "=="); /* init usb use */ sanei_usb_init (); /* init sanei_magic */ sanei_magic_init(); DBG (DBG_info, "sane_init: %s endian machine\n", #ifdef WORDS_BIGENDIAN "big" #else "little" #endif ); /* set up to no devices at first */ num_devices = 0; first_dev = 0; first_handle = 0; devlist = 0; /* cold-plug case :detection of allready connected scanners */ status = probe_genesys_devices (); DBGCOMPLETED; return status; } void sane_exit (void) { Genesys_Device *dev, *next; DBGSTART; for (dev = first_dev; dev; dev = next) { /* sane_close() free many fields, not much things left to * do here */ next = dev->next; free (dev->file_name); free (dev); } first_dev = 0; first_handle = 0; if (devlist) free (devlist); devlist = 0; sanei_usb_exit(); DBGCOMPLETED; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Genesys_Device *dev, *prev; SANE_Int index; SANE_Device *sane_device; DBG (DBG_proc, "sane_get_devices: start: local_only = %s\n", local_only == SANE_TRUE ? "true" : "false"); /* hot-plug case : detection of newly connected scanners */ sanei_usb_scan_devices (); probe_genesys_devices (); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; prev = NULL; index = 0; dev = first_dev; while (dev != NULL) { /* check if device removed */ present = SANE_FALSE; sanei_usb_find_devices (dev->vendorId, dev->productId, check_present); if (present) { sane_device = malloc (sizeof (*sane_device)); if (!sane_device) return SANE_STATUS_NO_MEM; sane_device->name = dev->file_name; sane_device->vendor = dev->model->vendor; sane_device->model = dev->model->model; sane_device->type = strdup ("flatbed scanner"); devlist[index] = sane_device; index++; prev = dev; dev = dev->next; } else { /* remove device from internal list */ /* case 1 : removed device is first_dev */ if (prev == NULL) { /* test for another dev */ if (dev->next == NULL) { /* empty the whole list */ free (dev); first_dev = NULL; num_devices = 0; dev = NULL; } else { /* assign new start */ first_dev = dev->next; num_devices--; free (dev); dev = first_dev; } } /* case 2 : removed device is not first_dev */ else { /* link previous dev to next dev */ prev->next = dev->next; free (dev); num_devices--; /* next loop */ dev = prev->next; } } } devlist[index] = 0; *device_list = devlist; DBGCOMPLETED; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Genesys_Device *dev; SANE_Status status; Genesys_Scanner *s; char *tmpstr; DBG (DBG_proc, "sane_open: start (devicename = `%s')\n", devicename); /* devicename="" or devicename="genesys" are default values that use * first available device */ if (devicename[0] && strcmp ("genesys", devicename) != 0) { /* search for the given devicename in the device list */ for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->file_name, devicename) == 0) break; if (!dev) { DBG (DBG_info, "sane_open: couldn't find `%s' in devlist, trying attach\n", devicename); RIE (attach (devicename, &dev, SANE_TRUE)); } else DBG (DBG_info, "sane_open: found `%s' in devlist\n", dev->model->name); } else { /* empty devicename or "genesys" -> use first device */ dev = first_dev; if (dev) { devicename = dev->file_name; DBG (DBG_info, "sane_open: empty devicename, trying `%s'\n", devicename); } } if (!dev) return SANE_STATUS_INVAL; if (dev->model->flags & GENESYS_FLAG_UNTESTED) { DBG (DBG_error0, "WARNING: Your scanner is not fully supported or at least \n"); DBG (DBG_error0, " had only limited testing. Please be careful and \n"); DBG (DBG_error0, " report any failure/success to \n"); DBG (DBG_error0, " sane-devel@lists.alioth.debian.org. Please provide as many\n"); DBG (DBG_error0, " details as possible, e.g. the exact name of your\n"); DBG (DBG_error0, " scanner and what does (not) work.\n"); } status = sanei_usb_open (dev->file_name, &dev->dn); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "sane_open: couldn't open device `%s': %s\n", dev->file_name, sane_strstatus (status)); return status; } s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; s->dev = dev; s->scanning = SANE_FALSE; s->dev->read_buffer.buffer = NULL; s->dev->lines_buffer.buffer = NULL; s->dev->shrink_buffer.buffer = NULL; s->dev->out_buffer.buffer = NULL; s->dev->binarize_buffer.buffer = NULL; s->dev->local_buffer.buffer = NULL; s->dev->parking = SANE_FALSE; s->dev->read_active = SANE_FALSE; s->dev->white_average_data = NULL; s->dev->dark_average_data = NULL; s->dev->calibration_cache = NULL; s->dev->calib_file = NULL; s->dev->img_buffer = NULL; s->dev->line_interp = 0; s->dev->line_count = 0; s->dev->segnb = 0; s->dev->oe_buffer.buffer=NULL; s->dev->binary=NULL; /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; if (!dev->already_initialized) sanei_genesys_init_structs (dev); RIE (init_options (s)); if (sanei_genesys_init_cmd_set (s->dev) != SANE_STATUS_GOOD) { DBG (DBG_error0, "This device doesn't have a valid command set!!\n"); return SANE_STATUS_IO_ERROR; } RIE (dev->model->cmd_set->init (dev)); /* some hardware capabilities are detected through sensors */ RIE (s->dev->model->cmd_set->update_hardware_sensors (s)); /* here is the place to fetch a stored calibration cache */ tmpstr=calibration_filename(s->dev); s->val[OPT_CALIBRATION_FILE].s = strdup (tmpstr); s->dev->calib_file = strdup (tmpstr); DBG (DBG_info, "%s: Calibration filename set to:\n", __func__); DBG (DBG_info, "%s: >%s<\n", __func__, s->dev->calib_file); free(tmpstr); /* now open file, fetch calibration records */ sanei_genesys_read_calibration (s->dev); DBGCOMPLETED; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Genesys_Scanner *prev, *s; Genesys_Calibration_Cache *cache, *next_cache; SANE_Status status; DBGSTART; /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (DBG_error, "sane_close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } /* eject document for sheetfed scanners */ if (s->dev->model->is_sheetfed == SANE_TRUE) { s->dev->model->cmd_set->eject_document (s->dev); } else { /* in case scanner is parking, wait for the head * to reach home position */ if(s->dev->parking==SANE_TRUE) { status = sanei_genesys_wait_for_home (s->dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_close: failed to wait for head to park: %s\n", sane_strstatus (status)); } } } /* enable power saving before leaving */ status = s->dev->model->cmd_set->save_power (s->dev, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_close: failed to enable power saving mode: %s\n", sane_strstatus (status)); } /* here is the place to store calibration cache */ write_calibration (s->dev); for (cache = s->dev->calibration_cache; cache; cache = next_cache) { next_cache = cache->next; free (cache->dark_average_data); free (cache->white_average_data); free (cache); } sanei_genesys_buffer_free (&(s->dev->read_buffer)); sanei_genesys_buffer_free (&(s->dev->lines_buffer)); sanei_genesys_buffer_free (&(s->dev->shrink_buffer)); sanei_genesys_buffer_free (&(s->dev->out_buffer)); sanei_genesys_buffer_free (&(s->dev->binarize_buffer)); sanei_genesys_buffer_free (&(s->dev->local_buffer)); FREE_IFNOT_NULL (s->dev->white_average_data); FREE_IFNOT_NULL (s->dev->dark_average_data); FREE_IFNOT_NULL (s->dev->calib_file); /* free allocated gamma tables */ FREE_IFNOT_NULL (s->dev->sensor.gamma_table[0]); FREE_IFNOT_NULL (s->dev->sensor.gamma_table[1]); FREE_IFNOT_NULL (s->dev->sensor.gamma_table[2]); s->dev->already_initialized = SANE_FALSE; /* for an handful of bytes .. */ free ((void *)(size_t)s->opt[OPT_RESOLUTION].constraint.word_list); free (s->val[OPT_SOURCE].s); free (s->val[OPT_MODE].s); free (s->val[OPT_COLOR_FILTER].s); free ((void *)(size_t)s->opt[OPT_TL_X].constraint.range); free ((void *)(size_t)s->opt[OPT_TL_Y].constraint.range); if (prev) prev->next = s->next; else first_handle = s->next; /* LAMP OFF : same register across all the ASICs */ sanei_genesys_write_register (s->dev, 0x03, 0x00); /* clear before closing */ sanei_usb_clear_halt (s->dev->dn); /* we need this to avoid these ASIC getting stuck * in bulk writes */ sanei_usb_reset (s->dev->dn); sanei_usb_close (s->dev->dn); free (s); DBGCOMPLETED; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Genesys_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; DBG (DBG_io2, "sane_get_option_descriptor: option = %s (%d)\n", s->opt[option].name, option); return s->opt + option; } /* gets an option , called by sane_control_option */ static SANE_Status get_option_value (Genesys_Scanner * s, int option, void *val) { unsigned int i; SANE_Word *table ,tmp; uint16_t *gamma; SANE_Status status = SANE_STATUS_GOOD; Genesys_Calibration_Cache *cache; switch (option) { /* geometry */ case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *) val = s->val[option].w; /* switch coordinate to keep them coherent */ if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w) { tmp=s->val[OPT_BR_X].w; s->val[OPT_BR_X].w=s->val[OPT_TL_X].w; s->val[OPT_TL_X].w=tmp; } if (s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w) { tmp=s->val[OPT_BR_Y].w; s->val[OPT_BR_Y].w=s->val[OPT_TL_Y].w; s->val[OPT_TL_Y].w=tmp; } break; /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_BIT_DEPTH: case OPT_PREVIEW: case OPT_THRESHOLD: case OPT_THRESHOLD_CURVE: case OPT_DISABLE_DYNAMIC_LINEART: case OPT_DISABLE_INTERPOLATION: case OPT_LAMP_OFF: case OPT_LAMP_OFF_TIME: case OPT_SWDESKEW: case OPT_SWCROP: case OPT_SWDESPECK: case OPT_SWDEROTATE: case OPT_SWSKIP: case OPT_DESPECK: case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_EXPIRATION_TIME: *(SANE_Word *) val = s->val[option].w; break; case OPT_CUSTOM_GAMMA: *(SANE_Word *) val = s->val[option].w; break; /* string options: */ case OPT_MODE: case OPT_COLOR_FILTER: case OPT_CALIBRATION_FILE: case OPT_SOURCE: strcpy (val, s->val[option].s); break; /* word array options */ case OPT_GAMMA_VECTOR: table = (SANE_Word *) val; if (strcmp (s->val[OPT_COLOR_FILTER].s, "Red") == 0) { gamma = s->dev->sensor.gamma_table[GENESYS_RED]; } else if (strcmp (s->val[OPT_COLOR_FILTER].s, "Blue") == 0) { gamma = s->dev->sensor.gamma_table[GENESYS_BLUE]; } else { gamma = s->dev->sensor.gamma_table[GENESYS_GREEN]; } for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++) { table[i] = gamma[i]; } break; case OPT_GAMMA_VECTOR_R: table = (SANE_Word *) val; for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++) { table[i] = s->dev->sensor.gamma_table[GENESYS_RED][i]; } break; case OPT_GAMMA_VECTOR_G: table = (SANE_Word *) val; for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++) { table[i] = s->dev->sensor.gamma_table[GENESYS_GREEN][i]; } break; case OPT_GAMMA_VECTOR_B: table = (SANE_Word *) val; for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++) { table[i] = s->dev->sensor.gamma_table[GENESYS_BLUE][i]; } break; /* sensors */ case OPT_SCAN_SW: case OPT_FILE_SW: case OPT_EMAIL_SW: case OPT_COPY_SW: case OPT_PAGE_LOADED_SW: case OPT_OCR_SW: case OPT_POWER_SW: case OPT_EXTRA_SW: RIE (s->dev->model->cmd_set->update_hardware_sensors (s)); *(SANE_Bool *) val = s->val[option].b; s->last_val[option].b = *(SANE_Bool *) val; break; case OPT_NEED_CALIBRATION_SW: /* scanner needs calibration for current mode unless a matching * calibration cache is found */ *(SANE_Bool *) val = SANE_TRUE; for (cache = s->dev->calibration_cache; cache; cache = cache->next) { if (s->dev->model-> cmd_set->is_compatible_calibration (s->dev, cache, SANE_FALSE) == SANE_STATUS_GOOD) { *(SANE_Bool *) val = SANE_FALSE; } } break; default: DBG (DBG_warn, "get_option_value: can't get unknown option %d\n", option); } return status; } /** @brief set calibration file value * Set calibration file value. Load new cache values from file if it exists, * else creates the file*/ static SANE_Status set_calibration_value (Genesys_Scanner * s, int option, void *val) { SANE_Status status=SANE_STATUS_GOOD; char *tmp; Genesys_Device *dev=s->dev; DBGSTART; /* try to load file */ tmp=dev->calib_file; dev->calib_file=val; status=sanei_genesys_read_calibration (dev); /* file exists but is invalid, so fall back to previous cache file * an re-read it */ if (status!=SANE_STATUS_IO_ERROR && status!=SANE_STATUS_GOOD) { dev->calib_file=tmp; status=sanei_genesys_read_calibration (dev); return status; } /* now we can set file name value */ if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (tmp) free (tmp); dev->calib_file = strdup (val); DBG (DBG_info, "%s: Calibration filename set to:\n", __func__); DBG (DBG_info, "%s: >%s<\n", __func__, s->dev->calib_file); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* sets an option , called by sane_control_option */ static SANE_Status set_option_value (Genesys_Scanner * s, int option, void *val, SANE_Int * myinfo) { SANE_Status status = SANE_STATUS_GOOD; SANE_Word *table; unsigned int i; SANE_Range *x_range, *y_range; Genesys_Calibration_Cache *cache, *next_cache; switch (option) { case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; RIE (calc_parameters (s)); *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_RESOLUTION: case OPT_THRESHOLD: case OPT_THRESHOLD_CURVE: case OPT_DISABLE_DYNAMIC_LINEART: case OPT_SWCROP: case OPT_SWDESKEW: case OPT_DESPECK: case OPT_SWDEROTATE: case OPT_SWSKIP: case OPT_DISABLE_INTERPOLATION: case OPT_LAMP_OFF: case OPT_PREVIEW: case OPT_BRIGHTNESS: case OPT_CONTRAST: s->val[option].w = *(SANE_Word *) val; RIE (calc_parameters (s)); *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_SWDESPECK: s->val[option].w = *(SANE_Word *) val; if (s->val[OPT_SWDESPECK].b == SANE_TRUE) { ENABLE(OPT_DESPECK); } else { DISABLE(OPT_DESPECK); } RIE (calc_parameters (s)); *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; /* software enhancement functions only apply to 8 or 1 bits data */ case OPT_BIT_DEPTH: s->val[option].w = *(SANE_Word *) val; if(s->val[OPT_BIT_DEPTH].w>8) { DISABLE(OPT_SWDESKEW); DISABLE(OPT_SWDESPECK); DISABLE(OPT_SWCROP); DISABLE(OPT_DESPECK); DISABLE(OPT_SWDEROTATE); DISABLE(OPT_SWSKIP); DISABLE(OPT_CONTRAST); DISABLE(OPT_BRIGHTNESS); } else { ENABLE(OPT_SWDESKEW); ENABLE(OPT_SWDESPECK); ENABLE(OPT_SWCROP); ENABLE(OPT_DESPECK); ENABLE(OPT_SWDEROTATE); ENABLE(OPT_SWSKIP); ENABLE(OPT_CONTRAST); ENABLE(OPT_BRIGHTNESS); } RIE (calc_parameters (s)); *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_SOURCE: if (strcmp (s->val[option].s, val) != 0) { /* something changed */ if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); /* change geometry constraint to the new source value */ if (strcmp (s->val[option].s, FLATBED) == 0) { x_range=create_range(s->dev->model->x_size); y_range=create_range(s->dev->model->y_size); } else { x_range=create_range(s->dev->model->x_size_ta); y_range=create_range(s->dev->model->y_size_ta); } if(x_range==NULL || y_range==NULL) { return SANE_STATUS_NO_MEM; } /* assign new values */ free((void *)(size_t)s->opt[OPT_TL_X].constraint.range); free((void *)(size_t)s->opt[OPT_TL_Y].constraint.range); s->opt[OPT_TL_X].constraint.range = x_range; s->val[OPT_TL_X].w = 0; s->opt[OPT_TL_Y].constraint.range = y_range; s->val[OPT_TL_Y].w = 0; s->opt[OPT_BR_X].constraint.range = x_range; s->val[OPT_BR_Y].w = y_range->max; s->opt[OPT_BR_Y].constraint.range = y_range; s->val[OPT_BR_X].w = x_range->max; /* signals reload */ *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } break; case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { ENABLE (OPT_THRESHOLD); ENABLE (OPT_THRESHOLD_CURVE); DISABLE (OPT_BIT_DEPTH); if (s->dev->model->asic_type != GENESYS_GL646 || !s->dev->model->is_cis) { ENABLE (OPT_COLOR_FILTER); } ENABLE (OPT_DISABLE_DYNAMIC_LINEART); } else { DISABLE (OPT_THRESHOLD); DISABLE (OPT_THRESHOLD_CURVE); DISABLE (OPT_DISABLE_DYNAMIC_LINEART); if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) { if (s->dev->model->asic_type != GENESYS_GL646 || !s->dev->model->is_cis) { ENABLE (OPT_COLOR_FILTER); } create_bpp_list (s, s->dev->model->bpp_gray_values); } else { DISABLE (OPT_COLOR_FILTER); create_bpp_list (s, s->dev->model->bpp_color_values); } if (s->bpp_list[0] < 2) DISABLE (OPT_BIT_DEPTH); else ENABLE (OPT_BIT_DEPTH); } RIE (calc_parameters (s)); /* if custom gamma, toggle gamma table options according to the mode */ if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE) { if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { DISABLE (OPT_GAMMA_VECTOR); ENABLE (OPT_GAMMA_VECTOR_R); ENABLE (OPT_GAMMA_VECTOR_G); ENABLE (OPT_GAMMA_VECTOR_B); } else { ENABLE (OPT_GAMMA_VECTOR); DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); } } *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_COLOR_FILTER: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); RIE (calc_parameters (s)); break; case OPT_CALIBRATION_FILE: RIE(set_calibration_value (s, option, val)); break; case OPT_LAMP_OFF_TIME: case OPT_EXPIRATION_TIME: if (*(SANE_Word *) val != s->val[option].w) { s->val[option].w = *(SANE_Word *) val; RIE (s->dev->model->cmd_set-> set_powersaving (s->dev, s->val[option].w)); } break; case OPT_CUSTOM_GAMMA: *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; s->val[OPT_CUSTOM_GAMMA].b = *(SANE_Bool *) val; if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE) { if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { DISABLE (OPT_GAMMA_VECTOR); ENABLE (OPT_GAMMA_VECTOR_R); ENABLE (OPT_GAMMA_VECTOR_G); ENABLE (OPT_GAMMA_VECTOR_B); } else { ENABLE (OPT_GAMMA_VECTOR); DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); } } else { DISABLE (OPT_GAMMA_VECTOR); DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); /* restore default sensor gamma table */ /* currently there is no sensor's specific gamma table, * tables are built by sanei_genesys_create_gamma_table */ sanei_genesys_create_gamma_table (s->dev->sensor.gamma_table[GENESYS_RED], s->opt[OPT_GAMMA_VECTOR_R].size / sizeof (SANE_Word), s->opt[OPT_GAMMA_VECTOR_R].constraint.range->max, s->opt[OPT_GAMMA_VECTOR_R].constraint.range->max, s->dev->sensor.gamma[GENESYS_RED]); sanei_genesys_create_gamma_table (s->dev->sensor.gamma_table[GENESYS_GREEN], s->opt[OPT_GAMMA_VECTOR_G].size / sizeof (SANE_Word), s->opt[OPT_GAMMA_VECTOR_G].constraint.range->max, s->opt[OPT_GAMMA_VECTOR_G].constraint.range->max, s->dev->sensor.gamma[GENESYS_GREEN]); sanei_genesys_create_gamma_table (s->dev->sensor.gamma_table[GENESYS_BLUE], s->opt[OPT_GAMMA_VECTOR_B].size / sizeof (SANE_Word), s->opt[OPT_GAMMA_VECTOR_B].constraint.range->max, s->opt[OPT_GAMMA_VECTOR_B].constraint.range->max, s->dev->sensor.gamma[GENESYS_BLUE]); } break; case OPT_GAMMA_VECTOR: table = (SANE_Word *) val; for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++) { s->dev->sensor.gamma_table[GENESYS_RED][i] = table[i]; s->dev->sensor.gamma_table[GENESYS_GREEN][i] = table[i]; s->dev->sensor.gamma_table[GENESYS_BLUE][i] = table[i]; } break; case OPT_GAMMA_VECTOR_R: table = (SANE_Word *) val; for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++) { s->dev->sensor.gamma_table[GENESYS_RED][i] = table[i]; } break; case OPT_GAMMA_VECTOR_G: table = (SANE_Word *) val; for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++) { s->dev->sensor.gamma_table[GENESYS_GREEN][i] = table[i]; } break; case OPT_GAMMA_VECTOR_B: table = (SANE_Word *) val; for (i = 0; i < s->opt[option].size / sizeof (SANE_Word); i++) { s->dev->sensor.gamma_table[GENESYS_BLUE][i] = table[i]; } break; case OPT_CALIBRATE: status = s->dev->model->cmd_set->save_power (s->dev, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to disable power saving mode: %s\n", __func__, sane_strstatus (status)); } else status = genesys_scanner_calibration (s->dev); /* not critical if this fails*/ s->dev->model->cmd_set->save_power (s->dev, SANE_TRUE); /* signals that sensors will have to be read again */ *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_CLEAR_CALIBRATION: /* clear calibration cache */ if (s->dev->calibration_cache != NULL) { for (cache = s->dev->calibration_cache; cache; cache = next_cache) { next_cache = cache->next; free (cache->dark_average_data); free (cache->white_average_data); free (cache); } } s->dev->calibration_cache = NULL; /* remove file */ unlink (s->dev->calib_file); /* signals that sensors will have to be read again */ *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; default: DBG (DBG_warn, "set_option_value: can't set unknown option %d\n", option); } return status; } /* sets and gets scanner option values */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Genesys_Scanner *s = handle; SANE_Status status = SANE_STATUS_GOOD; SANE_Word cap; SANE_Int myinfo = 0; DBG (DBG_io2, "sane_control_option: start: action = %s, option = %s (%d)\n", (action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_SET_VALUE) ? "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->opt[option].name, option); if (info) *info = 0; if (s->scanning) { DBG (DBG_warn, "sane_control_option: don't call this function while " "scanning (option = %s (%d))\n", s->opt[option].name, option); return SANE_STATUS_DEVICE_BUSY; } if (option >= NUM_OPTIONS || option < 0) { DBG (DBG_warn, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", option); return SANE_STATUS_INVAL; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (DBG_warn, "sane_control_option: option %d is inactive\n", option); return SANE_STATUS_INVAL; } switch (action) { case SANE_ACTION_GET_VALUE: status = get_option_value (s, option, val); break; case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_warn, "sane_control_option: option %d is not settable\n", option); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } status = set_option_value (s, option, val, &myinfo); break; case SANE_ACTION_SET_AUTO: DBG (DBG_error, "sane_control_option: SANE_ACTION_SET_AUTO unsupported since no option has SANE_CAP_AUTOMATIC\n"); status = SANE_STATUS_INVAL; break; default: DBG (DBG_warn, "sane_control_option: unknown action %d for option %d\n", action, option); status = SANE_STATUS_INVAL; break; } if (info) *info = myinfo; DBG (DBG_io2, "sane_control_option: exit\n"); return status; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Genesys_Scanner *s = handle; SANE_Status status; DBGSTART; /* don't recompute parameters once data reading is active, ie during scan */ if(s->dev->read_active == SANE_FALSE) { RIE (calc_parameters (s)); } if (params) { *params = s->params; /* in the case of a sheetfed scanner, when full height is specified * we override the computed line number with -1 to signal that we * don't know the real document height. * We don't do that doing buffering image for digital processing */ if (s->dev->model->is_sheetfed == SANE_TRUE && s->dev->buffer_image == SANE_FALSE && s->val[OPT_BR_Y].w == s->opt[OPT_BR_Y].constraint.range->max) { params->lines = -1; } } DBGCOMPLETED; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Genesys_Scanner *s = handle; SANE_Status status=SANE_STATUS_GOOD; DBGSTART; if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w) { DBG (DBG_error0, "sane_start: top left x >= bottom right x --- exiting\n"); return SANE_STATUS_INVAL; } if (s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w) { DBG (DBG_error0, "sane_start: top left y >= bottom right y --- exiting\n"); return SANE_STATUS_INVAL; } /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ RIE (calc_parameters (s)); RIE (genesys_start_scan (s->dev, s->val[OPT_LAMP_OFF].w)); s->scanning = SANE_TRUE; /* allocate intermediate buffer when doing dynamic lineart */ if(s->dev->settings.dynamic_lineart==SANE_TRUE) { RIE (sanei_genesys_buffer_free (&(s->dev->binarize_buffer))); RIE (sanei_genesys_buffer_alloc (&(s->dev->binarize_buffer), s->dev->settings.pixels)); RIE (sanei_genesys_buffer_free (&(s->dev->local_buffer))); RIE (sanei_genesys_buffer_alloc (&(s->dev->local_buffer), s->dev->binarize_buffer.size * 8)); } /* if one of the software enhancement option is selected, * we do the scan internally, process picture then put it an internal * buffer. Since cropping may change scan parameters, we recompute them * at the end */ if (s->dev->buffer_image) { RIE(genesys_buffer_image(s)); /* check if we need to skip this page, sheetfed scanners * can go to next doc while flatbed ones can't */ if (s->val[OPT_SWSKIP].w && IS_ACTIVE(OPT_SWSKIP)) { status = sanei_magic_isBlank(&s->params, s->dev->img_buffer, SANE_UNFIX(s->val[OPT_SWSKIP].w)); if(status == SANE_STATUS_NO_DOCS) { if (s->dev->model->is_sheetfed == SANE_TRUE) { DBG (DBG_info, "sane_start: blank page, recurse\n"); return sane_start(handle); } return status; } } /* deskew image if required */ if(s->val[OPT_SWDESKEW].b == SANE_TRUE) { RIE(genesys_deskew(s)); } /* despeck image if required */ if(s->val[OPT_SWDESPECK].b == SANE_TRUE) { RIE(genesys_despeck(s)); } /* crop image if required */ if(s->val[OPT_SWCROP].b == SANE_TRUE) { RIE(genesys_crop(s)); } /* de-rotate image if required */ if(s->val[OPT_SWDEROTATE].b == SANE_TRUE) { RIE(genesys_derotate(s)); } } DBGCOMPLETED; return status; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Genesys_Scanner *s = handle; Genesys_Device *dev; SANE_Status status=SANE_STATUS_GOOD; size_t local_len; if (!s) { DBG (DBG_error, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } dev=s->dev; if (!dev) { DBG (DBG_error, "sane_read: dev is null!\n"); return SANE_STATUS_INVAL; } if (!buf) { DBG (DBG_error, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (!len) { DBG (DBG_error, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } *len = 0; if (!s->scanning) { DBG (DBG_warn, "sane_read: scan was cancelled, is over or has not been " "initiated yet\n"); return SANE_STATUS_CANCELLED; } DBG (DBG_proc, "sane_read: start, %d maximum bytes required\n", max_len); DBG (DBG_io2, "sane_read: bytes_to_read=%lu, total_bytes_read=%lu\n", (u_long) dev->total_bytes_to_read, (u_long) dev->total_bytes_read); DBG (DBG_io2, "sane_read: physical bytes to read = %lu\n", (u_long) dev->read_bytes_left); if(dev->total_bytes_read>=dev->total_bytes_to_read) { DBG (DBG_proc, "sane_read: nothing more to scan: EOF\n"); /* issue park command immediatly in case scanner can handle it * so we save time */ if (dev->model->is_sheetfed == SANE_FALSE && !(dev->model->flags & GENESYS_FLAG_MUST_WAIT) && dev->parking == SANE_FALSE) { dev->model->cmd_set->slow_back_home (dev, SANE_FALSE); dev->parking = SANE_TRUE; } return SANE_STATUS_EOF; } local_len = max_len; /* in case of image processing, all data has been stored in * buffer_image. So read data from it if it exists, else from scanner */ if(!dev->buffer_image) { /* dynamic lineart is another kind of digital processing that needs * another layer of buffering on top of genesys_read_ordered_data */ if(dev->settings.dynamic_lineart==SANE_TRUE) { /* if buffer is empty, fill it with genesys_read_ordered_data */ if(dev->binarize_buffer.avail==0) { /* store gray data */ local_len=dev->local_buffer.size; status = genesys_read_ordered_data (dev, dev->local_buffer.buffer, &local_len); /* binarize data is read successful */ if(status==SANE_STATUS_GOOD) { dev->local_buffer.avail=local_len; dev->local_buffer.pos=0; dev->binarize_buffer.avail=local_len/8; dev->binarize_buffer.pos=0; genesys_gray_lineart (dev, dev->local_buffer.buffer, dev->binarize_buffer.buffer, dev->settings.pixels, local_len/dev->settings.pixels, dev->settings.threshold); } } /* return data from lineart buffer if any, up to the available amount */ local_len = max_len; if((size_t)max_len>dev->binarize_buffer.avail) { local_len=dev->binarize_buffer.avail; } if(local_len) { memcpy(buf,sanei_genesys_buffer_get_read_pos (&(dev->binarize_buffer)),local_len); RIE (sanei_genesys_buffer_consume (&(dev->binarize_buffer), local_len)); } } else { /* most usual case, direct read of data from scanner */ status = genesys_read_ordered_data (dev, buf, &local_len); } } else /* read data from buffer */ { if(dev->total_bytes_read+local_len>dev->total_bytes_to_read) { local_len=dev->total_bytes_to_read-dev->total_bytes_read; } memcpy(buf,dev->img_buffer+dev->total_bytes_read,local_len); dev->total_bytes_read+=local_len; } *len = local_len; if(local_len>(size_t)max_len) { fprintf (stderr, "[genesys] sane_read: returning incorrect length!!\n"); } DBG (DBG_proc, "sane_read: %d bytes returned\n", *len); return status; } void sane_cancel (SANE_Handle handle) { Genesys_Scanner *s = handle; SANE_Status status = SANE_STATUS_GOOD; DBGSTART; /* end binary logging if needed */ if (s->dev->binary!=NULL) { fclose(s->dev->binary); s->dev->binary=NULL; } s->scanning = SANE_FALSE; s->dev->read_active = SANE_FALSE; if(s->dev->img_buffer!=NULL) { free(s->dev->img_buffer); s->dev->img_buffer=NULL; } /* no need to end scan if we are parking the head */ if(s->dev->parking==SANE_FALSE) { status = s->dev->model->cmd_set->end_scan (s->dev, s->dev->reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_cancel: failed to end scan: %s\n", sane_strstatus (status)); return; } } /* park head if flatbed scanner */ if (s->dev->model->is_sheetfed == SANE_FALSE) { if(s->dev->parking==SANE_FALSE) { status = s->dev->model->cmd_set->slow_back_home (s->dev, s->dev->model->flags & GENESYS_FLAG_MUST_WAIT); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_cancel: failed to move scanhead to home position: %s\n", sane_strstatus (status)); return; } s->dev->parking = !(s->dev->model->flags & GENESYS_FLAG_MUST_WAIT); } } else { /* in case of sheetfed scanners, we have to eject the document if still present */ status = s->dev->model->cmd_set->eject_document (s->dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_cancel: failed to eject document: %s\n", sane_strstatus (status)); return; } } /* enable power saving mode unless we are parking .... */ if(s->dev->parking==SANE_FALSE) { status = s->dev->model->cmd_set->save_power (s->dev, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_cancel: failed to enable power saving mode: %s\n", sane_strstatus (status)); return; } } DBGCOMPLETED; return; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Genesys_Scanner *s = handle; DBG (DBG_proc, "sane_set_io_mode: handle = %p, non_blocking = %s\n", handle, non_blocking == SANE_TRUE ? "true" : "false"); if (!s->scanning) { DBG (DBG_error, "sane_set_io_mode: not scanning\n"); return SANE_STATUS_INVAL; } if (non_blocking) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Genesys_Scanner *s = handle; DBG (DBG_proc, "sane_get_select_fd: handle = %p, fd = %p\n", handle, (void *) fd); if (!s->scanning) { DBG (DBG_error, "sane_get_select_fd: not scanning\n"); return SANE_STATUS_INVAL; } return SANE_STATUS_UNSUPPORTED; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/dc25.conf.in0000664000175000017500000000130012112021330014575 00000000000000# Serial port where the camera is connected ## Linux port=/dev/ttyS0 ## IRIX #port=/dev/ttyd1 ## Solaris #port=/dev/term/a ## HP-UX #port=/dev/tty0p0 ## Digital UNIX #port=/dev/tty01 # Max baud rate for download. Camera always starts at 9600 baud, then # switches to the higher rate ## This works for Linux. Also works for IRIX (6.3 or higher), providing that ## the host is an O2, OCTANE, Origin2000/200, Onyx2, Origin3000/300, Onyx3 or ## a newer SGI hardware [see serial(7)]. #baud=115200 ## This works for most UNIX's baud=38400 # Prints some extra information during the init phase. This can be # handy, but note that printing anything to stderr breaks the saned # network scanning. #dumpinquiry sane-backends-1.0.27/backend/sceptre.h0000664000175000017500000002715512112021330014422 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ */ /* Commands supported by the Sceptre S1200 scanner. */ #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_GET_STATUS 0x02 #define SCSI_INQUIRY 0x12 #define SCSI_MODE_SELECT 0x15 #define SCSI_MODE_SENSE 0x1a #define SCSI_SCAN 0x1b #define SCSI_RECEIVE_DIAG 0x1c #define SCSI_SEND_DIAG 0x1D #define SCSI_SET_WINDOW 0x24 #define SCSI_READ_10 0x28 #define SCSI_REQUEST_SENSE 0x03 #define SCSI_SEND_10 0x2a #define SCSI_GET_DATA_BUFFER_STATUS 0x34 typedef struct { unsigned char data[16]; int len; } CDB; /* Set a specific bit depending on a boolean. * MKSCSI_BIT(TRUE, 3) will generate 0x08. */ #define MKSCSI_BIT(bit, pos) ((bit)? 1<<(pos): 0) /* Set a value in a range of bits. * MKSCSI_I2B(5, 3, 5) will generate 0x28 */ #define MKSCSI_I2B(bits, pos_b, pos_e) ((bits) << (pos_b) & ((1<<((pos_e)-(pos_b)+1))-1)) /* Store an integer in 2, 3 or 4 byte in an array. */ #define Ito16(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 0) & 0xff; \ } #define Ito24(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 0) & 0xff; \ } #define Ito32(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 24) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[3] = ((val) >> 0) & 0xff; \ } #define MKSCSI_TEST_UNIT_READY(cdb) \ cdb.data[0] = SCSI_TEST_UNIT_READY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_GET_STATUS(cdb, buflen) \ cdb.data[0] = SCSI_GET_STATUS; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_INQUIRY(cdb, buflen) \ cdb.data[0] = SCSI_INQUIRY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_MODE_SELECT(cdb, pf, sp, buflen) \ cdb.data[0] = SCSI_MODE_SELECT; \ cdb.data[1] = MKSCSI_BIT(pf, 4) | MKSCSI_BIT(sp, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_MODE_SENSE(cdb, pc, page_code, buflen) \ cdb.data[0] = SCSI_MODE_SENSE; \ cdb.data[1] = 0; \ cdb.data[2] = MKSCSI_I2B(pc, 6, 7) | MKSCSI_I2B(page_code, 0, 5); \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SCAN(cdb) \ cdb.data[0] = SCSI_SCAN; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_RECEIVE_DIAG(cdb, pc, buflen) \ cdb.data[0] = SCSI_RECEIVE_DIAG; \ cdb.data[1] = 0; \ cdb.data[2] = pc; \ cdb.data[3] = (((buflen) >> 8) & 0xff); \ cdb.data[4] = (((buflen) >> 0) & 0xff); \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SEND_DIAG(cdb, buflen) \ cdb.data[0] = SCSI_SEND_DIAG; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = (((buflen) >> 8) & 0xff); \ cdb.data[4] = (((buflen) >> 0) & 0xff); \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SET_WINDOW(cdb, buflen) \ cdb.data[0] = SCSI_SET_WINDOW; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_READ_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_READ_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_REQUEST_SENSE(cdb, buflen) \ cdb.data[0] = SCSI_REQUEST_SENSE; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = (buflen); \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SEND_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_SEND_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_GET_DATA_BUFFER_STATUS(cdb, wait, buflen) \ cdb.data[0] = SCSI_GET_DATA_BUFFER_STATUS; \ cdb.data[1] = MKSCSI_BIT(wait, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = 0; \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; /*--------------------------------------------------------------------------*/ #define length_quant SANE_UNFIX(SANE_FIX(MM_PER_INCH / 600)) #define mmToIlu(mm) ((mm) / length_quant) #define iluToMm(ilu) ((ilu) * length_quant) /*--------------------------------------------------------------------------*/ #define GAMMA_LENGTH 0x100 /* number of value per color */ /*--------------------------------------------------------------------------*/ enum Sceptre_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* scanner modes */ OPT_RESOLUTION, /* X and Y resolution */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* upper left X */ OPT_TL_Y, /* upper left Y */ OPT_BR_X, /* bottom right X */ OPT_BR_Y, /* bottom right Y */ OPT_ENHANCEMENT_GROUP, OPT_CUSTOM_GAMMA, /* Use the custom gamma tables */ OPT_GAMMA_VECTOR_R, /* Custom Red gamma table */ OPT_GAMMA_VECTOR_G, /* Custom Green Gamma table */ OPT_GAMMA_VECTOR_B, /* Custom Blue Gamma table */ OPT_THRESHOLD, /* Threshold */ OPT_HALFTONE_PATTERN, /* Halftone pattern (1 to 4) */ OPT_PREVIEW, /* preview mode */ /* must come last: */ OPT_NUM_OPTIONS }; /*--------------------------------------------------------------------------*/ /* * Scanner supported by this backend. */ struct scanners_supported { /* From scsi inquiry */ int scsi_type; char scsi_vendor[9]; char scsi_product[17]; char *real_vendor; char *real_product; }; /*--------------------------------------------------------------------------*/ #define LINEART_STR SANE_VALUE_SCAN_MODE_LINEART #define HALFTONE_STR SANE_VALUE_SCAN_MODE_HALFTONE #define GRAY_STR SANE_VALUE_SCAN_MODE_GRAY #define COLOR_STR SANE_VALUE_SCAN_MODE_COLOR /*--------------------------------------------------------------------------*/ /* Define a scanner occurence. */ typedef struct Sceptre_Scanner { struct Sceptre_Scanner *next; SANE_Device sane; char *devicename; int sfd; /* device handle */ /* Infos from inquiry. */ char scsi_type; char scsi_vendor[9]; char scsi_product[17]; char scsi_version[5]; /* Scanner infos. */ SANE_Range x_range; SANE_Range y_range; SANE_Range resolution_range; int scnum; /* index of that scanner in * scanners_supported */ /* SCSI handling */ SANE_Byte *buffer; /* for SCSI transfer. */ size_t buffer_size; /* allocated size of buffer */ /* Scanning handling. */ int scanning; /* TRUE is a scan is running. */ int resolution; /* scan resolution */ int x_tl; /* X top left */ int y_tl; /* Y top left */ int x_br; /* X bottom right */ int y_br; /* Y bottom right */ int width; /* width of the scan area in mm */ int length; /* length of the scan area in mm */ enum { SCEPTRE_LINEART, SCEPTRE_HALFTONE, SCEPTRE_GRAYSCALE, SCEPTRE_COLOR } scan_mode; int depth; /* depth per color */ int halftone_param; /* haltone number, valid for SCEPTRE_HALFTONE */ size_t bytes_left; /* number of bytes left to give to the backend */ size_t real_bytes_left; /* number of bytes left the scanner will return. */ SANE_Byte *image; /* keep the raw image here */ size_t image_size; /* allocated size of image */ size_t image_begin; /* first significant byte in image */ size_t image_end; /* first free byte in image */ int color_shift; /* for color scan: number of lines to * shift the colors. The higher the * resolution, the higher this * number. */ int raster_size; /* size of a raster */ int raster_num; /* for colour scan, current raster read */ int raster_real; /* real number of raster in the * scan. This is necessary since I * don't know how to reliably compute * the number of lines */ int raster_ahead; /* max size of the incomplete lines */ int line; /* current line of the scan */ SANE_Parameters params; /* Options */ SANE_Option_Descriptor opt[OPT_NUM_OPTIONS]; Option_Value val[OPT_NUM_OPTIONS]; /* Gamma table. 1 array per colour. */ SANE_Word gamma_R[GAMMA_LENGTH]; SANE_Word gamma_G[GAMMA_LENGTH]; SANE_Word gamma_B[GAMMA_LENGTH]; } Sceptre_Scanner; /*--------------------------------------------------------------------------*/ /* Debug levels. * Should be common to all backends. */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /*--------------------------------------------------------------------------*/ /* 32 bits from an array to an integer (eg ntohl). */ #define B32TOI(buf) \ ((((unsigned char *)buf)[0] << 24) | \ (((unsigned char *)buf)[1] << 16) | \ (((unsigned char *)buf)[2] << 8) | \ (((unsigned char *)buf)[3] << 0)) /* 16 bits from an array to an integer (eg ntohs). */ #define B16TOI(buf) \ ((((unsigned char *)buf)[0] << 8) | \ (((unsigned char *)buf)[1] << 0)) sane-backends-1.0.27/backend/sharp.c0000664000175000017500000037310513106201017014072 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998, 1999 Kazuya Fukuda, Abel Deuring based on BYTEC GmbH Germany Written by Helmut Koeberle previous Work on canon.c file from the SANE package. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Sharp flatbed scanners. */ /* Version 0.32 changes to version 0.31: - support for JX320 added (Thanks to Isaac Wilcox for providind the patch) Version 0.31 changes to version 0.30: - support for JX350 added (Thanks to Shuhei Tomita for providind the patch) changes to version 0.20 - support for the proposed extended open function in sanei_scsi.c added - support for ADF and FSU (transparency adapter) added - simple sense handler added - preview added - added several missing statements "s->fd = -1;" after "sanei_scsi_close(s->fd)" to error returns in sane_start(); - maximum scan sizes are read from the scanner, if a JX330 or JX250 is used. (this avoids the guessing of scan sizes for the JX330) - gamma table support added - "Fixed gamma selection (1.0/2.2)", available for JX330 and JX610, is now implemented for the JX250 by downloading a gamma table - changed the calls to free() and strdup() in sane_control_option to strcpy. (I don't like too frequent unchecked malloc()s and strdups :) Abel) - cleaned up some quirks in option handling, eg, that "threshold" was initially enabled, while the initial scan mode is "color" - cleaned up setting SANE_INFO_RELOAD_OPTIONS and SANE_INFO_RELOAD_PARAMS bits in sane_control_option - bi-level color scans now give useful (8 bit) output - separate thresholds for red, green, blue (bi-level color scan) added */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" /* QUEUEDEBUG should be undefined unless you want to play with the sanei_scsi.c under Linux and/or with the Linux's SG driver, or your suspect problems with command queueing */ #if 0 #define QUEUEDEBUG #define DEBUG #ifdef DEBUG #include #include #endif #endif /* USE_FORK: fork a special reader process */ #ifdef HAVE_SYS_SHM_H #ifndef HAVE_OS2_H #define USE_FORK #endif #endif #ifdef USE_FORK #include #include #include #include #include #include #endif /* USE_FORK */ /* xxx I'm not sure, if I understood the JX610 and JX330 manuals right, that the data for the SEND command should be in ASCII format... SEND commands with a data bock are used, if USE_CUSTOM_GAMMA and / or USE_COLOR_THRESHOLD are enabled. Abel */ #define USE_CUSTOM_GAMMA #define USE_COLOR_THRESHOLD /* enable a short list of some standard resolutions. XSane provides its own resolution list; therefore its is generally not reasonable to enable this list, if you mainly using XSane. But it might be handy if you are working with xscanimage */ /* #define USE_RESOLUTION_LIST */ /* enable separate specification of resolution in X and Y direction. XSane will show the Y-resolution at a quite different place than the X-resolution */ /* #define USE_SEPARATE_Y_RESOLUTION */ #define BACKEND_NAME sharp #include "../include/sane/sanei_backend.h" #include #ifndef PATH_MAX #define PATH_MAX 1024 #endif #define DEFAULT_MUD_JX610 25 #define DEFAULT_MUD_JX320 25 #define DEFAULT_MUD_JX330 1200 #define DEFAULT_MUD_JX250 1200 #define PIX_TO_MM(x, mud) ((x) * 25.4 / mud) #define MM_TO_PIX(x, mud) ((x) * mud / 25.4) #include "../include/sane/sanei_config.h" #define SHARP_CONFIG_FILE "sharp.conf" static int num_devices = 0; static SHARP_Device *first_dev = NULL; static SHARP_Scanner *first_handle = NULL; typedef enum { MODES_LINEART = 0, MODES_GRAY, MODES_LINEART_COLOR, MODES_COLOR } Modes; #define M_LINEART SANE_VALUE_SCAN_MODE_LINEART #define M_GRAY SANE_VALUE_SCAN_MODE_GRAY #define M_LINEART_COLOR SANE_VALUE_SCAN_MODE_COLOR_LINEART #define M_COLOR SANE_VALUE_SCAN_MODE_COLOR static const SANE_String_Const mode_list[] = { M_LINEART, M_GRAY, M_LINEART_COLOR, M_COLOR, 0 }; #define M_BILEVEL "none" #define M_BAYER "Dither Bayer" #define M_SPIRAL "Dither Spiral" #define M_DISPERSED "Dither Dispersed" #define M_ERRDIFFUSION "Error Diffusion" static const SANE_String_Const halftone_list[] = { M_BILEVEL, M_BAYER, M_SPIRAL, M_DISPERSED, M_ERRDIFFUSION, 0 }; #define LIGHT_GREEN "green" #define LIGHT_RED "red" #define LIGHT_BLUE "blue" #define LIGHT_WHITE "white" #define MAX_RETRIES 50 static const SANE_String_Const light_color_list[] = { LIGHT_GREEN, LIGHT_RED, LIGHT_BLUE, LIGHT_WHITE, 0 }; /* possible values for ADF/FSU selection */ static SANE_String use_adf = "Automatic Document Feeder"; static SANE_String use_fsu = "Transparency Adapter"; static SANE_String use_simple = "Flatbed"; /* auto selection of ADF and FSU, as described in the JX330 manual, is a nice idea -- but I assume that the possible scan window sizes depend not only for the JX250, but also for JX330 on the usage of ADF or FSU. Thus, the user might be able to select scan windows of an "illegal" size, which would have to be automatically corrected, and I don't see, how the user could be informed about this "window clipping". More important, I don't see, how the frontend could be informed that the ADF is automatically enabled. Insert a "#define ALLOW_AUTO_SELECT_ADF", if you want to play with this feature. */ #ifdef ALLOW_AUTO_SELECT_ADF static SANE_String_Const use_auto = "AutoSelection"; #endif #define HAVE_FSU 1 #define HAVE_ADF 2 /* The follow #defines are used in SHARP_Scanner.adf_fsu_mode and as indexes for the arrays x_ranges, y_ranges in SHARP_Device */ #define SCAN_SIMPLE 0 #define SCAN_WITH_FSU 1 #define SCAN_WITH_ADF 2 #ifdef ALLOW_AUTO_SELECT_ADF #define SCAN_ADF_FSU_AUTO 3 #endif #define LOAD_PAPER 1 #define UNLOAD_PAPER 0 #define PAPER_MAX 10 #define W_LETTER "11\"x17\"" #define INVOICE "8.5\"x5.5\"" static const SANE_String_Const paper_list_jx610[] = { "A3", "A4", "A5", "A6", "B4", "B5", W_LETTER, "Legal", "Letter", INVOICE, 0 }; static const SANE_String_Const paper_list_jx330[] = { "A4", "A5", "A6", "B5", 0 }; #define GAMMA10 "1.0" #define GAMMA22 "2.2" static const SANE_String_Const gamma_list[] = { GAMMA10, GAMMA22, 0 }; #if 0 #define SPEED_NORMAL "Normal" #define SPEED_FAST "Fast" static const SANE_String_Const speed_list[] = { SPEED_NORMAL, SPEED_FAST, 0 }; #endif #ifdef USE_RESOLUTION_LIST #define RESOLUTION_MAX_JX610 8 static const SANE_String_Const resolution_list_jx610[] = { "50", "75", "100", "150", "200", "300", "400", "600", "Select", 0 }; #define RESOLUTION_MAX_JX250 7 static const SANE_String_Const resolution_list_jx250[] = { "50", "75", "100", "150", "200", "300", "400", "Select", 0 }; #endif #define EDGE_NONE "None" #define EDGE_MIDDLE "Middle" #define EDGE_STRONG "Strong" #define EDGE_BLUR "Blur" static const SANE_String_Const edge_emphasis_list[] = { EDGE_NONE, EDGE_MIDDLE, EDGE_STRONG, EDGE_BLUR, 0 }; #ifdef USE_CUSTOM_GAMMA static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; #endif static SANE_Status sense_handler(int __sane_unused__ fd, u_char *sense_buffer, void *s) { int sense_key; SHARP_Sense_Data *sdat = (SHARP_Sense_Data *) s; #define add_sense_code sense_buffer[12] #define add_sense_qual sense_buffer[13] memcpy(sdat->sb, sense_buffer, 16); DBG(10, "sense code: %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", sense_buffer[0], sense_buffer[1], sense_buffer[2], sense_buffer[3], sense_buffer[4], sense_buffer[5], sense_buffer[6], sense_buffer[7], sense_buffer[8], sense_buffer[9], sense_buffer[10], sense_buffer[11], sense_buffer[12], sense_buffer[13], sense_buffer[14], sense_buffer[15]); sense_key = sense_buffer[2] & 0x0F; /* do we have additional information ? */ if (sense_buffer[7] >= 5) { if (sdat->model == JX610) { /* The JX610 uses somewhat different error codes */ switch (add_sense_code) { case 0x04: DBG(5, "error: scanner not ready\n"); return SANE_STATUS_IO_ERROR; case 0x08: DBG(5, "error: scanner communication failure (time out?)\n"); return SANE_STATUS_IO_ERROR; case 0x1A: DBG(10, "error: parameter list length error\n"); return SANE_STATUS_IO_ERROR; case 0x20: DBG(10, "error: invalid command code\n"); return SANE_STATUS_IO_ERROR; case 0x24: DBG(10, "error: invalid field in CDB\n"); return SANE_STATUS_IO_ERROR; case 0x25: DBG(10, "error: LUN not supported\n"); return SANE_STATUS_IO_ERROR; case 0x26: DBG(10, "error: invalid field in parameter list\n"); return SANE_STATUS_IO_ERROR; case 0x29: DBG(10, "note: reset occurred\n"); return SANE_STATUS_GOOD; case 0x2a: DBG(10, "note: mode parameter change\n"); return SANE_STATUS_GOOD; case 0x37: DBG(10, "note: rounded parameter\n"); return SANE_STATUS_GOOD; case 0x39: DBG(10, "error: saving parameter not supported\n"); return SANE_STATUS_IO_ERROR; case 0x47: DBG(10, "SCSI parity error\n"); return SANE_STATUS_IO_ERROR; case 0x48: DBG(10, "initiator detected error message received\n"); return SANE_STATUS_IO_ERROR; case 0x60: DBG(1, "error: lamp failure\n"); return SANE_STATUS_IO_ERROR; case 0x62: DBG(1, "scan head positioning error\n"); return SANE_STATUS_IO_ERROR; } } else if (sdat->model == JX250 || sdat->model == JX330 || sdat->model == JX350 || sdat->model == JX320) { switch (sense_key) { case 0x02: /* not ready */ switch (add_sense_code) { case 0x80: switch (add_sense_qual) { case 0: DBG(1, "Scanner not ready: ADF cover open\n"); if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR) return SANE_STATUS_COVER_OPEN; else return SANE_STATUS_GOOD; case 1: DBG(1, "Scanner not ready: ADF maintenance " "cover open\n"); if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR) return SANE_STATUS_COVER_OPEN; else return SANE_STATUS_GOOD; default: DBG(5, "Scanner not ready: undocumented reason\n"); return SANE_STATUS_IO_ERROR; } case 0x81: /* NOT TESTED -- I don't have a FSU */ switch (add_sense_qual) { case 0: DBG(1, "Scanner not ready: FSU cover open\n"); if (sdat->complain_on_errors & COMPLAIN_ON_FSU_ERROR) return SANE_STATUS_COVER_OPEN; else return SANE_STATUS_GOOD; case 1: DBG(1, "Scanner not ready: FSU light dispersion " "error\n"); if (sdat->complain_on_errors & COMPLAIN_ON_FSU_ERROR) { return SANE_STATUS_IO_ERROR; } else return SANE_STATUS_GOOD; default: DBG(5, "Scanner not ready: undocumented reason\n"); return SANE_STATUS_IO_ERROR; } default: DBG(5, "Scanner not ready: undocumented reason\n"); return SANE_STATUS_IO_ERROR; } case 0x03: /* medium error */ switch (add_sense_code) { case 0x3a: DBG(1, "ADF is empty\n"); if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR) return SANE_STATUS_NO_DOCS; else return SANE_STATUS_GOOD; case 0x53: DBG(1, "ADF paper jam\n" "Open and close the maintenance cover to clear " "this error\n"); if (sdat->complain_on_errors & COMPLAIN_ON_ADF_ERROR) return SANE_STATUS_JAMMED; else return SANE_STATUS_GOOD; default: DBG(5, "medium error: undocumented reason\n"); return SANE_STATUS_IO_ERROR; } case 0x04: /* hardware error */ switch (add_sense_code) { case 0x08: DBG(1, "hardware error: scanner communication failed\n"); return SANE_STATUS_IO_ERROR; case 0x60: DBG(1, "hardware error: lamp failure\n"); return SANE_STATUS_IO_ERROR; case 0x62: DBG(1, "hardware error: scan head positioning failed\n"); return SANE_STATUS_IO_ERROR; default: DBG(1, "general hardware error\n"); return SANE_STATUS_IO_ERROR; } case 0x05: /* illegal request */ DBG(10, "error: illegal request\n"); return SANE_STATUS_IO_ERROR; case 0x06: /* unit attention */ switch (add_sense_code) { case 0x29: DBG(5, "unit attention: reset occurred\n"); return SANE_STATUS_GOOD; case 0x2a: DBG(5, "unit attention: parameter changed by " "another initiator\n"); return SANE_STATUS_IO_ERROR; default: DBG(5, "unit attention: exact reason not documented\n"); return SANE_STATUS_IO_ERROR; } case 0x09: /* data remains */ DBG(5, "error: data remains\n"); return SANE_STATUS_IO_ERROR; default: DBG(5, "error: sense code not documented\n"); return SANE_STATUS_IO_ERROR; } } } return SANE_STATUS_IO_ERROR; } static SANE_Status test_unit_ready (int fd) { static u_char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< test_unit_ready "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #if 0 static SANE_Status request_sense (int fd, void *sense_buf, size_t *sense_size) { static u_char cmd[] = {REQUEST_SENSE, 0, 0, 0, SENSE_LEN, 0}; SANE_Status status; DBG (11, "<< request_sense "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), sense_buf, sense_size); DBG (11, ">>\n"); return (status); } #endif static SANE_Status inquiry (int fd, void *inq_buf, size_t *inq_size) { static u_char cmd[] = {INQUIRY, 0, 0, 0, INQUIRY_LEN, 0}; SANE_Status status; DBG (11, "<< inquiry "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), inq_buf, inq_size); DBG (11, ">>\n"); return (status); } static SANE_Status mode_select_mud (int fd, int mud) { static u_char cmd[6 + MODEPARAM_LEN] = {MODE_SELECT6, 0x10, 0, 0, MODEPARAM_LEN, 0}; mode_select_param *mp; SANE_Status status; DBG (11, "<< mode_select_mud "); mp = (mode_select_param *)(cmd + 6); memset (mp, 0, MODEPARAM_LEN); mp->page_code = 3; mp->page_length = 6; mp->mud[0] = mud >> 8; mp->mud[1] = mud & 0xFF; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } static SANE_Status mode_select_adf_fsu (int fd, int mode) { static u_char cmd[6 + MODE_SUBDEV_LEN] = {MODE_SELECT6, 0x10, 0, 0, MODE_SUBDEV_LEN, 0}; mode_select_subdevice *mp; SANE_Status status; DBG (11, "<< mode_select_adf_fsu "); mp = (mode_select_subdevice *)(cmd + 6); memset (mp, 0, MODE_SUBDEV_LEN); mp->page_code = 0x20; mp->page_length = 26; switch (mode) { case SCAN_SIMPLE: mp->a_mode = 0x40; mp->f_mode = 0x40; break; case SCAN_WITH_FSU: mp->a_mode = 0; mp->f_mode = 0x40; break; case SCAN_WITH_ADF: mp->a_mode = 0x40; mp->f_mode = 0; break; #ifdef ALLOW_AUTO_SELECT_ADF case: SCAN_ADF_FSU_AUTO: mp->a_mode = 0; mp->f_mode = 0; break; #endif } status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } static SANE_Status wait_ready(int fd); static SANE_Status object_position(int fd, int load) { static u_char cmd[] = {OBJECT_POSITION, 0, 0, 0, 0, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< object_position "); cmd[1] = load; wait_ready(fd); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #if 0 static SANE_Status reserve_unit (int fd) { static u_char cmd[] = {RESERVE_UNIT, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< reserve_unit "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #endif #if 0 static SANE_Status release_unit (int fd) { static u_char cmd[] = {RELEASE_UNIT, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< release_unit "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #endif static SANE_Status mode_sense (int fd, void *modeparam_buf, size_t * modeparam_size, int page) { static u_char cmd[6]; SANE_Status status; DBG (11, "<< mode_sense "); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x1a; cmd[2] = page; cmd[4] = *modeparam_size; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), modeparam_buf, modeparam_size); DBG (11, ">>\n"); return (status); } static SANE_Status scan (int fd) { static u_char cmd[] = {SCAN, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< scan "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #if 0 static SANE_Status send_diagnostics (int fd) { static u_char cmd[] = {SEND_DIAGNOSTIC, 0x04, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< send_diagnostics "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #endif static SANE_Status send (int fd, SHARP_Send * ss) { static u_char cmd[] = {SEND, 0, 0, 0, 0, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< send "); cmd[2] = ss->dtc; cmd[4] = ss->dtq >> 8; cmd[5] = ss->dtq; cmd[6] = ss->length >> 16; cmd[7] = ss->length >> 8; cmd[8] = ss->length >> 0; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } static SANE_Status set_window (int fd, window_param *wp, int len) { static u_char cmd[10 + WINDOW_LEN] = {SET_WINDOW, 0, 0, 0, 0, 0, 0, 0, 0, 0}; window_param *winp; SANE_Status status; DBG (11, "<< set_window "); cmd[8] = len; winp = (window_param *)(cmd + 10); memset (winp, 0, WINDOW_LEN); memcpy (winp, wp, len); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } static SANE_Status get_window (int fd, void *buf, size_t * buf_size) { static u_char cmd[10] = {GET_WINDOW, 0, 0, 0, 0, 0, 0, 0, WINDOW_LEN, 0}; SANE_Status status; DBG (11, "<< get_window "); cmd[8] = *buf_size; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); DBG (11, ">>\n"); return (status); } #ifdef USE_FORK /* the following four functions serve simply the purpose to avoid "over-optimised" code when reader_process and read_data wait for the buffer to become ready. The simple while-loops in these functions which check the buffer status may be optimised so that the machine code only operates with registers instead of using the variable values stored in memory. (This is only a workaround - it would be better to set a compiler pragma, which ensures that the program looks into the RAM in these while loops -- but unfortunately I could not find appropriate information about this at least for gcc, not to speak about other compilers... Abel) */ static int cancel_requested(SHARP_Scanner *s) { return s->rdr_ctl->cancel; } static SANE_Status rdr_status(SHARP_Scanner *s) { return s->rdr_ctl->status; } static int buf_status(SHARP_shmem_ctl *s) { return s->shm_status; } static int reader_running(SHARP_Scanner *s) { return s->rdr_ctl->running; } static int reader_process(SHARP_Scanner *s) { SANE_Status status; sigset_t sigterm_set; static u_char cmd[] = {READ, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int full_count = 0, counted; size_t waitindex, cmdindex; size_t bytes_to_queue; size_t nread; size_t max_bytes_per_read; int max_queue; int i, retries = MAX_RETRIES; SHARP_shmem_ctl *bc; s->rdr_ctl->running = 1; DBG(11, "<< reader_process\n"); sigemptyset (&sigterm_set); bytes_to_queue = s->bytes_to_read; /* it seems that some carriage stops can be avoided with the JX-250, if the data of an integral number of scan lines is read with one SCSI command */ max_bytes_per_read = s->dev->info.bufsize / s->params.bytes_per_line; if (max_bytes_per_read) max_bytes_per_read *= s->params.bytes_per_line; else /* this is a really tiny buffer..*/ max_bytes_per_read = s->dev->info.bufsize; /* wait_ready(s->fd); */ if (s->dev->info.queued_reads <= s->dev->info.buffers) max_queue = s->dev->info.queued_reads; else max_queue = s->dev->info.buffers; if (max_queue <= 0) max_queue = 1; for (i = 0; i < max_queue; i++) { bc = &s->rdr_ctl->buf_ctl[i]; if (bytes_to_queue) { nread = bytes_to_queue; if (nread > max_bytes_per_read) nread = max_bytes_per_read; bc->used = nread; cmd[6] = nread >> 16; cmd[7] = nread >> 8; cmd[8] = nread; #ifdef QUEUEDEBUG DBG(2, "reader: req_enter...\n"); #endif status = sanei_scsi_req_enter (s->fd, cmd, sizeof (cmd), bc->buffer, &bc->used, &bc->qid); #ifdef QUEUEDEBUG DBG(2, "reader: req_enter ok\n"); #endif if (status != SANE_STATUS_GOOD) { DBG(1, "reader_process: read command failed: %s", sane_strstatus(status)); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->status = status; s->rdr_ctl->running = 0; return 2; } bc->shm_status = SHM_BUSY; bc->nreq = bc->used; bytes_to_queue -= bc->nreq; } else { bc->used = 0; bc->shm_status = SHM_EMPTY; } } waitindex = 0; cmdindex = i % s->dev->info.buffers; while(s->bytes_to_read > 0) { if (cancel_requested(s)) { #ifdef QUEUEDEBUG DBG(2, "reader: flushing requests...\n"); #endif #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif #ifdef QUEUEDEBUG DBG(2, "reader: flushing requests ok\n"); #endif s->rdr_ctl->cancel = 0; s->rdr_ctl->status = SANE_STATUS_CANCELLED; s->rdr_ctl->running = 0; DBG(11, " reader_process (cancelled) >>\n"); return 1; } bc = &s->rdr_ctl->buf_ctl[waitindex]; if (bc->shm_status == SHM_BUSY) { #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: waiting for data %li.%06li\n", t.tv_sec, t.tv_usec); } #endif #ifdef QUEUEDEBUG DBG(2, "reader: req_wait...\n"); #endif status = sanei_scsi_req_wait(bc->qid); #ifdef QUEUEDEBUG DBG(2, "reader: req_wait ok\n"); #endif #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: data received %li.%06li\n", t.tv_sec, t.tv_usec); } #endif if (status == SANE_STATUS_DEVICE_BUSY && retries) { bc->used = 0; retries--; DBG(11, "reader: READ command returned BUSY\n"); status = SANE_STATUS_GOOD; usleep(10000); } else if (status != SANE_STATUS_GOOD) { DBG(1, "reader_process: read command failed: %s\n", sane_strstatus(status)); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->status = status; s->rdr_ctl->running = 0; return 2; } else { retries = MAX_RETRIES; } #if 1 s->bytes_to_read -= bc->used; bytes_to_queue += bc->nreq - bc->used; #else /* xxxxxxxxxxxxxxxxxxx TEST xxxxxxxxxxxxxxx */ s->bytes_to_read -= bc->nreq; /* memset(bc->buffer + bc->used, 0, bc->nreq - bc->used); */ bc->used = bc->nreq; /* bytes_to_queue += bc->nreq - bc->used; */ DBG(1, "btr: %i btq: %i nreq: %i nrcv: %i\n", s->bytes_to_read, bytes_to_queue, bc->nreq, bc->used); #endif bc->start = 0; bc->shm_status = SHM_FULL; waitindex++; if (waitindex == s->dev->info.buffers) waitindex = 0; } if (bytes_to_queue) { /* wait until the next buffer is completely read via read_data */ bc = &s->rdr_ctl->buf_ctl[cmdindex]; counted = 0; while (buf_status(bc) != SHM_EMPTY) { if (!counted) { counted = 1; full_count++; } if (cancel_requested(s)) { #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->cancel = 0; s->rdr_ctl->status = SANE_STATUS_CANCELLED; s->rdr_ctl->running = 0; DBG(11, " reader_process (cancelled) >>\n"); return 1; } } nread = bytes_to_queue; if (nread > max_bytes_per_read) nread = max_bytes_per_read; bc->used = nread; cmd[6] = nread >> 16; cmd[7] = nread >> 8; cmd[8] = nread; status = sanei_scsi_req_enter (s->fd, cmd, sizeof (cmd), bc->buffer, &bc->used, &bc->qid); if (status != SANE_STATUS_GOOD) { DBG(1, "reader_process: read command failed: %s", sane_strstatus(status)); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->status = status; s->rdr_ctl->running = 0; return 2; } bc->shm_status = SHM_BUSY; bc->nreq = nread; bytes_to_queue -= nread; cmdindex++; if (cmdindex == s->dev->info.buffers) cmdindex = 0; } if (cancel_requested(s)) { #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->cancel = 0; s->rdr_ctl->status = SANE_STATUS_CANCELLED; s->rdr_ctl->running = 0; DBG(11, " reader_process (cancelled) >>\n"); return 1; } } DBG(1, "buffer full conditions: %i\n", full_count); DBG(11, " reader_process>>\n"); s->rdr_ctl->running = 0; return 0; } static SANE_Status read_data (SHARP_Scanner *s, SANE_Byte *buf, size_t * buf_size) { size_t copysize, copied = 0; SHARP_shmem_ctl *bc; DBG(11, "<< read_data "); bc = &s->rdr_ctl->buf_ctl[s->read_buff]; while (copied < *buf_size) { /* wait until the reader process delivers data or a scanner error occurs: */ while ( buf_status(bc) != SHM_FULL && rdr_status(s) == SANE_STATUS_GOOD) { usleep(10); /* could perhaps be longer. make this user configurable?? */ } if (rdr_status(s) != SANE_STATUS_GOOD) { return rdr_status(s); DBG(11, ">>\n"); } copysize = bc->used - bc->start; if (copysize > *buf_size - copied ) copysize = *buf_size - copied; memcpy(buf, &(bc->buffer[bc->start]), copysize); copied += copysize; buf = &buf[copysize]; bc->start += copysize; if (bc->start >= bc->used) { bc->start = 0; bc->shm_status = SHM_EMPTY; s->read_buff++; if (s->read_buff == s->dev->info.buffers) s->read_buff = 0; bc = &s->rdr_ctl->buf_ctl[s->read_buff]; } } DBG(11, ">>\n"); return SANE_STATUS_GOOD; } #else /* don't USE_FORK: */ static SANE_Status read_data (SHARP_Scanner *s, SANE_Byte *buf, size_t * buf_size) { static u_char cmd[] = {READ, 0, 0, 0, 0, 0, 0, 0, 0, 0}; SANE_Status status = SANE_STATUS_GOOD; size_t remain = *buf_size; size_t nread; int retries = MAX_RETRIES; DBG (11, "<< read_data "); /* sane_read_shuffled requires that read_data returns exactly *buf_size bytes, so it must be guaranteed here. Further make sure that not more bytes are read in than sanei_scsi_max_request_size allows, to avoid a failure of the read command */ while (remain > 0) { nread = remain; if (nread > s->dev->info.bufsize) nread = s->dev->info.bufsize; cmd[6] = nread >> 16; cmd[7] = nread >> 8; cmd[8] = nread; status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), &buf[*buf_size - remain], &nread); if (status == SANE_STATUS_DEVICE_BUSY && retries) { retries--; nread = 0; usleep(10000); } else if (status != SANE_STATUS_GOOD) { DBG(11, ">>\n"); return(status); } else { retries = MAX_RETRIES; } remain -= nread; } DBG (11, ">>\n"); return (status); } #endif static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; DBG (10, "<< max_string_size "); for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } DBG (10, ">>\n"); return max_size; } static SANE_Status wait_ready(int fd) { SANE_Status status; int retry = 0; while ((status = test_unit_ready (fd)) != SANE_STATUS_GOOD) { DBG (5, "wait_ready failed (%d)\n", retry); if (retry++ > 15){ return SANE_STATUS_IO_ERROR; } sleep(3); } return (status); } /* ask the scanner for the maximum scan sizes with/without ADF and FSU. The JX330 manual does mention the sizes. */ static SANE_Status get_max_scan_size(int fd, SHARP_Device *dev, int mode) { SANE_Status status; mode_sense_subdevice m_subdev; size_t buf_size; status = mode_select_adf_fsu(fd, mode); if (status != SANE_STATUS_GOOD) { DBG (1, "get_scan_sizes: MODE_SELECT/subdevice page failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } DBG (3, "get_scan_sizes: sending MODE SENSE/subdevice page\n"); memset (&m_subdev, 0, sizeof (m_subdev)); buf_size = sizeof (m_subdev); status = mode_sense (fd, &m_subdev, &buf_size, 0x20); if (status != SANE_STATUS_GOOD) { DBG (1, "get_scan_sizes: MODE_SENSE/subdevice page failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } dev->info.tl_x_ranges[mode].min = 0; dev->info.tl_x_ranges[mode].max = SANE_FIX(PIX_TO_MM( (m_subdev.max_x[0] << 24) + (m_subdev.max_x[1] << 16) + (m_subdev.max_x[2] << 8) + m_subdev.max_x[3] - 1, dev->info.mud)); dev->info.tl_x_ranges[mode].quant = 0; dev->info.br_x_ranges[mode].min = SANE_FIX(PIX_TO_MM(1, dev->info.mud)); dev->info.br_x_ranges[mode].max = SANE_FIX(PIX_TO_MM( (m_subdev.max_x[0] << 24) + (m_subdev.max_x[1] << 16) + (m_subdev.max_x[2] << 8) + m_subdev.max_x[3], dev->info.mud)); dev->info.br_x_ranges[mode].quant = 0; dev->info.tl_y_ranges[mode].min = 0; if ((dev->sensedat.model != JX250 && dev->sensedat.model != JX350) || mode != SCAN_WITH_FSU) dev->info.tl_y_ranges[mode].max = SANE_FIX(PIX_TO_MM( (m_subdev.max_y[0] << 24) + (m_subdev.max_y[1] << 16) + (m_subdev.max_y[2] << 8) + m_subdev.max_y[3] - 1, dev->info.mud)); else /* The manual for the JX250 states on page 62 that the maximum value for tl_y in FSU mode is 13199, while the max value for br_y is 13900, which is (probably -- I don't have a FSU) returned by mode sense/subdevice page. Therefore, we cannot simply decrement that value and store it as max(tl_y). */ dev->info.tl_y_ranges[mode].max = 13199; dev->info.tl_y_ranges[mode].quant = 0; dev->info.br_y_ranges[mode].min = SANE_FIX(PIX_TO_MM(1, dev->info.mud)); dev->info.br_y_ranges[mode].max = SANE_FIX(PIX_TO_MM( (m_subdev.max_y[0] << 24) + (m_subdev.max_y[1] << 16) + (m_subdev.max_y[2] << 8) + m_subdev.max_y[3], dev->info.mud)); dev->info.br_y_ranges[mode].quant = 0; return SANE_STATUS_GOOD; } static SANE_Status attach (const char *devnam, SHARP_Device ** devp) { SANE_Status status; SHARP_Device *dev; SHARP_Sense_Data sensedat; int fd; char inquiry_data[INQUIRY_LEN]; const char *model_name; mode_sense_param msp; mode_sense_subdevice m_subdev; size_t buf_size; DBG (10, "<< attach "); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } sensedat.model = unknown; sensedat.complain_on_errors = 0; DBG (3, "attach: opening %s\n", devnam); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED { int bufsize = 4096; status = sanei_scsi_open_extended (devnam, &fd, &sense_handler, &sensedat, &bufsize); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } if (bufsize < 4096) { DBG(1, "attach: open failed. no memory\n"); sanei_scsi_close(fd); return SANE_STATUS_NO_MEM; } } #else status = sanei_scsi_open (devnam, &fd, &sense_handler, &sensedat); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } #endif DBG (3, "attach: sending INQUIRY\n"); memset (inquiry_data, 0, sizeof (inquiry_data)); buf_size = sizeof (inquiry_data); status = inquiry (fd, inquiry_data, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } if (inquiry_data[0] == 6 && strncmp (inquiry_data + 8, "SHARP", 5) == 0) { if (strncmp (inquiry_data + 16, "JX610", 5) == 0) sensedat.model = JX610; else if (strncmp (inquiry_data + 16, "JX250", 5) == 0) sensedat.model = JX250; else if (strncmp (inquiry_data + 16, "JX350", 5) == 0) sensedat.model = JX350; else if ( strncmp (inquiry_data + 16, "JX320", 5) == 0 || strncmp (inquiry_data + 16, "JX325", 5) == 0) sensedat.model = JX320; else if (strncmp (inquiry_data + 16, "JX330", 5) == 0) sensedat.model = JX330; } if (sensedat.model == unknown) { DBG (1, "attach: device doesn't look like a Sharp scanner\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } DBG (3, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } DBG (3, "attach: sending MODE SELECT\n"); /* JX-610 probably supports only 25 MUD size JX-320 only supports 25 MUD size */ if (strncmp (inquiry_data + 16, "JX610", 5) == 0) status = mode_select_mud (fd, DEFAULT_MUD_JX610); else if (strncmp (inquiry_data + 16, "JX320", 5) == 0) status = mode_select_mud (fd, DEFAULT_MUD_JX320); else status = mode_select_mud (fd, DEFAULT_MUD_JX330); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT6 failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } DBG (3, "attach: sending MODE SENSE/MUP page\n"); memset (&msp, 0, sizeof (msp)); buf_size = sizeof (msp); status = mode_sense (fd, &msp, &buf_size, 3); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SENSE/MUP page failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } dev = malloc (sizeof (*dev)); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devnam); dev->sane.vendor = "SHARP"; model_name = (char*) inquiry_data + 16; dev->sane.model = strndup (model_name, 10); dev->sane.type = "flatbed scanner"; dev->sensedat.model = sensedat.model; DBG (5, "dev->sane.name = %s\n", dev->sane.name); DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor); DBG (5, "dev->sane.model = %s\n", dev->sane.model); DBG (5, "dev->sane.type = %s\n", dev->sane.type); dev->info.xres_range.quant = 0; dev->info.yres_range.quant = 0; dev->info.tl_x_ranges[SCAN_SIMPLE].min = SANE_FIX(0); dev->info.br_x_ranges[SCAN_SIMPLE].min = SANE_FIX(1); dev->info.tl_y_ranges[SCAN_SIMPLE].min = SANE_FIX(0); dev->info.br_y_ranges[SCAN_SIMPLE].min = SANE_FIX(1); dev->info.tl_x_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); dev->info.br_x_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); dev->info.tl_y_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); dev->info.br_y_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); dev->info.xres_default = 150; dev->info.yres_default = 150; dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(209); dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(210); dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(296); dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(297); dev->info.bmu = msp.bmu; dev->info.mud = (msp.mud[0] << 8) + msp.mud[1]; dev->info.adf_fsu_installed = 0; if (dev->sensedat.model == JX610) { dev->info.xres_range.max = 600; dev->info.xres_range.min = 30; dev->info.yres_range.max = 600; dev->info.yres_range.min = 30; dev->info.x_default = SANE_FIX(210); dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(303); /* 304.8mm is the real max */ dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(304); /* 304.8mm is the real max */ dev->info.y_default = SANE_FIX(297); dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(430); /* 431.8 is the real max */ dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(431); /* 431.8 is the real max */ } else if (dev->sensedat.model == JX320) { dev->info.xres_range.max = 600; dev->info.xres_range.min = 30; dev->info.yres_range.max = 600; dev->info.yres_range.min = 30; dev->info.x_default = SANE_FIX(210); dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(212); dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(213); dev->info.y_default = SANE_FIX(297); dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(292); dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(293); } else { /* ask the scanner, if ADF or FSU are installed, and ask for the maximum scan sizes with/without ADF and FSU. */ DBG (3, "attach: sending MODE SENSE/subdevice page\n"); memset (&m_subdev, 0, sizeof (m_subdev)); buf_size = sizeof (m_subdev); status = mode_sense (fd, &m_subdev, &buf_size, 0x20); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SENSE/subdevice page failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } /* The JX330 manual is not very clear about the ADF- und FSU-Bits returned by a JX320 and JX325 for the mode sense command: Are these bits set to zero or not? To be on the safe side, let's clear them. */ if ( strncmp(inquiry_data + 16, "JX320", 5) == 0 || strncmp(inquiry_data + 16, "JX325", 5) == 0) { m_subdev.f_mode_type = 0; m_subdev.a_mode_type = 0; } get_max_scan_size(fd, dev, SCAN_SIMPLE); if (m_subdev.a_mode_type & 0x03) { dev->info.adf_fsu_installed = HAVE_ADF; get_max_scan_size(fd, dev, SCAN_WITH_ADF); } if (m_subdev.f_mode_type & 0x07) { dev->info.adf_fsu_installed |= HAVE_FSU; get_max_scan_size(fd, dev, SCAN_WITH_FSU); } if ( dev->sensedat.model == JX320 || dev->sensedat.model == JX330 || dev->sensedat.model == JX350) { dev->info.xres_range.max = 600; dev->info.xres_range.min = 30; dev->info.yres_range.max = 600; dev->info.yres_range.min = 30; dev->info.x_default = SANE_FIX(210); dev->info.y_default = SANE_FIX(297); } else if (dev->sensedat.model == JX250) { dev->info.xres_range.max = 400; dev->info.xres_range.min = 30; dev->info.yres_range.max = 400; dev->info.yres_range.min = 30; dev->info.x_default = SANE_FIX(210); dev->info.y_default = SANE_FIX(297); } } sanei_scsi_close (fd); dev->info.threshold_range.min = 1; dev->info.threshold_range.max = 255; dev->info.threshold_range.quant = 0; DBG (5, "xres_default=%d\n", dev->info.xres_default); DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max); DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min); DBG (5, "xres_range.quant=%d\n", dev->info.xres_range.quant); DBG (5, "yres_default=%d\n", dev->info.yres_default); DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max); DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min); DBG (5, "xres_range.quant=%d\n", dev->info.xres_range.quant); DBG (5, "x_default=%f\n", SANE_UNFIX(dev->info.x_default)); DBG (5, "tl_x_range[0].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_SIMPLE].max)); DBG (5, "tl_x_range[0].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_SIMPLE].min)); DBG (5, "tl_x_range[0].quant=%d\n", dev->info.tl_x_ranges[SCAN_SIMPLE].quant); DBG (5, "br_x_range[0].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_SIMPLE].max)); DBG (5, "br_x_range[0].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_SIMPLE].min)); DBG (5, "br_x_range[0].quant=%d\n", dev->info.br_x_ranges[SCAN_SIMPLE].quant); DBG (5, "y_default=%f\n", SANE_UNFIX(dev->info.y_default)); DBG (5, "tl_y_range[0].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_SIMPLE].max)); DBG (5, "tl_y_range[0].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_SIMPLE].min)); DBG (5, "tl_y_range[0].quant=%d\n", dev->info.tl_y_ranges[SCAN_SIMPLE].quant); DBG (5, "br_y_range[0].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_SIMPLE].max)); DBG (5, "br_y_range[0].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_SIMPLE].min)); DBG (5, "br_y_range[0].quant=%d\n", dev->info.br_y_ranges[SCAN_SIMPLE].quant); if (dev->info.adf_fsu_installed & HAVE_FSU) { DBG (5, "tl_x_range[1].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_FSU].max)); DBG (5, "tl_x_range[1].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_FSU].min)); DBG (5, "tl_x_range[1].quant=%d\n", dev->info.tl_x_ranges[SCAN_WITH_FSU].quant); DBG (5, "br_x_range[1].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_FSU].max)); DBG (5, "br_x_range[1].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_FSU].min)); DBG (5, "br_x_range[1].quant=%d\n", dev->info.br_x_ranges[SCAN_WITH_FSU].quant); DBG (5, "tl_y_range[1].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_FSU].max)); DBG (5, "tl_y_range[1].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_FSU].min)); DBG (5, "tl_y_range[1].quant=%d\n", dev->info.tl_y_ranges[SCAN_WITH_FSU].quant); DBG (5, "br_y_range[1].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_FSU].max)); DBG (5, "br_y_range[1].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_FSU].min)); DBG (5, "br_y_range[1].quant=%d\n", dev->info.br_y_ranges[SCAN_WITH_FSU].quant); } if (dev->info.adf_fsu_installed & HAVE_ADF) { DBG (5, "tl_x_range[2].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_ADF].max)); DBG (5, "tl_x_range[2].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_ADF].min)); DBG (5, "tl_x_range[2].quant=%d\n", dev->info.tl_x_ranges[SCAN_WITH_ADF].quant); DBG (5, "br_x_range[2].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_ADF].max)); DBG (5, "br_x_range[2].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_ADF].min)); DBG (5, "br_x_range[2].quant=%d\n", dev->info.br_x_ranges[SCAN_WITH_ADF].quant); DBG (5, "tl_y_range[2].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_ADF].max)); DBG (5, "tl_y_range[2].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_ADF].min)); DBG (5, "tl_y_range[2].quant=%d\n", dev->info.tl_y_ranges[SCAN_WITH_ADF].quant); DBG (5, "br_y_range[2].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_ADF].max)); DBG (5, "br_y_range[2].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_ADF].min)); DBG (5, "br_y_range[2].quant=%d\n", dev->info.br_y_ranges[SCAN_WITH_ADF].quant); } DBG (5, "bmu=%d\n", dev->info.bmu); DBG (5, "mud=%d\n", dev->info.mud); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } /* Enabling / disabling of gamma options. Depends on many user settable options, so lets put it into one function to be called by init_options and by sane_control_option */ #ifdef USE_CUSTOM_GAMMA static void set_gamma_caps(SHARP_Scanner *s) { /* neither fixed nor custom gamma for line art modes */ if ( strcmp(s->val[OPT_MODE].s, M_LINEART) == 0 || strcmp(s->val[OPT_MODE].s, M_LINEART_COLOR) == 0) { s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else if (strcmp(s->val[OPT_MODE].s, M_GRAY) == 0) { s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) { s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { /* color mode */ s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) { s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } } #endif /* USE_CUSTOM_GAMMA */ /* The next function is a slightly modified version of sanei_constrain_value Instead of returning status information like STATUS_INVAL, it adjusts an invaild value to the nearest allowed one. */ static void clip_value (const SANE_Option_Descriptor * opt, void * value) { const SANE_String_Const * string_list; const SANE_Word * word_list; int i, num_matches, match; const SANE_Range * range; SANE_Word w, v; size_t len; switch (opt->constraint_type) { case SANE_CONSTRAINT_RANGE: w = *(SANE_Word *) value; range = opt->constraint.range; if (w < range->min) w = range->min; else if (w > range->max) w = range->max; if (range->quant) { v = (w - range->min + range->quant/2) / range->quant; w = v * range->quant + range->min; *(SANE_Word*) value = w; } break; case SANE_CONSTRAINT_WORD_LIST: w = *(SANE_Word *) value; word_list = opt->constraint.word_list; for (i = 1; w != word_list[i]; ++i) if (i >= word_list[0]) /* somewhat arbitrary... Would be better to have a default value explicitly defined. */ *(SANE_Word*) value = word_list[1]; break; case SANE_CONSTRAINT_STRING_LIST: /* Matching algorithm: take the longest unique match ignoring case. If there is an exact match, it is admissible even if the same string is a prefix of a longer option name. */ string_list = opt->constraint.string_list; len = strlen (value); /* count how many matches of length LEN characters we have: */ num_matches = 0; match = -1; for (i = 0; string_list[i]; ++i) if (strncasecmp (value, string_list[i], len) == 0 && len <= strlen (string_list[i])) { match = i; if (len == strlen (string_list[i])) { /* exact match... */ if (strcmp (value, string_list[i]) != 0) /* ...but case differs */ strcpy (value, string_list[match]); } ++num_matches; } if (num_matches > 1) /* xxx quite arbitrary... We could also choose the first match */ strcpy(value, string_list[match]); else if (num_matches == 1) strcpy (value, string_list[match]); else strcpy (value, string_list[0]); default: break; } } /* make sure that enough memory is allocated for each string, so that the strcpy in sane_control_option / set value cannot write behind the end of the allocated memory. */ static SANE_Status init_string_option(SHARP_Scanner *s, SANE_String_Const name, SANE_String_Const title, SANE_String_Const desc, const SANE_String_Const *string_list, int option, int default_index) { int i; s->opt[option].name = name; s->opt[option].title = title; s->opt[option].desc = desc; s->opt[option].type = SANE_TYPE_STRING; s->opt[option].size = max_string_size (string_list); s->opt[option].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[option].constraint.string_list = string_list; s->val[option].s = malloc(s->opt[option].size); if (s->val[option].s == 0) { for (i = 1; i < NUM_OPTIONS; i++) { if (s->val[i].s && s->opt[i].type == SANE_TYPE_STRING) free(s->val[i].s); } return SANE_STATUS_NO_MEM; } strcpy(s->val[option].s, string_list[default_index]); return SANE_STATUS_GOOD; } static SANE_Status init_options (SHARP_Scanner * s) { int i, default_source, sourcename_index = 0; SANE_Word scalar; DBG (10, "<< init_options "); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->val[i].s = 0; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* Mode group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ #if 0 s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[3]); /* color scan */ #endif init_string_option(s, SANE_NAME_SCAN_MODE, SANE_TITLE_SCAN_MODE, SANE_DESC_SCAN_MODE, mode_list, OPT_MODE, 3); /* half tone */ #if 0 s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE_PATTERN; s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE_PATTERN; s->opt[OPT_HALFTONE].desc = SANE_DESC_HALFTONE " (JX-330 only)"; s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE].size = max_string_size (halftone_list); s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_HALFTONE].constraint.string_list = halftone_list; s->val[OPT_HALFTONE].s = strdup (halftone_list[0]); #endif init_string_option(s, SANE_NAME_HALFTONE_PATTERN, SANE_TITLE_HALFTONE_PATTERN, SANE_DESC_HALFTONE " (JX-330 only)", halftone_list, OPT_HALFTONE, 0); if (s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350 || s->dev->sensedat.model == JX610 || s->dev->sensedat.model == JX320) s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; i = 0; default_source = s->dev->info.default_scan_mode; #ifdef ALLOW_AUTO_SELECT_ADF /* The JX330, but nut not the JX250 supports auto selection of ADF/FSU: */ if (s->dev->info.adf_fsu_installed && (s->dev->sensedat.model == JX330)) s->dev->info->scansources[i++] = use_auto; #endif if (s->dev->info.adf_fsu_installed & HAVE_ADF) { if (default_source == -1) default_source = SCAN_WITH_ADF; if (default_source == SCAN_WITH_ADF) sourcename_index = i; s->dev->info.scansources[i++] = use_adf; } else { if (default_source == SCAN_WITH_ADF) default_source = SCAN_SIMPLE; } if (s->dev->info.adf_fsu_installed & HAVE_FSU) { if (default_source == -1) default_source = SCAN_WITH_FSU; if (default_source == SCAN_WITH_FSU) sourcename_index = i; s->dev->info.scansources[i++] = use_fsu; } else { if (default_source == SCAN_WITH_FSU) default_source = SCAN_SIMPLE; } if (default_source < 0) default_source = SCAN_SIMPLE; if (default_source == SCAN_SIMPLE) sourcename_index = i; s->dev->info.scansources[i++] = use_simple; s->dev->info.scansources[i] = 0; #if 0 s->opt[OPT_SCANSOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SCANSOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SCANSOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SCANSOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SCANSOURCE].size = max_string_size (s->dev->info.scansources); s->opt[OPT_SCANSOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SCANSOURCE].constraint.string_list = (SANE_String_Const*)s->dev->info.scansources; s->val[OPT_SCANSOURCE].s = strdup (s->dev->info.scansources[0]); #endif init_string_option(s, SANE_NAME_SCAN_SOURCE, SANE_TITLE_SCAN_SOURCE, SANE_DESC_SCAN_SOURCE, (SANE_String_Const*)s->dev->info.scansources, OPT_SCANSOURCE, sourcename_index); if (i < 2) s->opt[OPT_SCANSOURCE].cap |= SANE_CAP_INACTIVE; #if 0 s->opt[OPT_PAPER].name = "Paper size"; s->opt[OPT_PAPER].title = "Paper size"; s->opt[OPT_PAPER].desc = "Paper size"; s->opt[OPT_PAPER].type = SANE_TYPE_STRING; /* xxx the possible values for the paper size should be changeable, to reflect the different maximum scan sizes with/without ADF and FSU */ if (s->dev->sensedat.model == JX610) { s->opt[OPT_PAPER].size = max_string_size (paper_list_jx610); s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_PAPER].constraint.string_list = paper_list_jx610; s->val[OPT_PAPER].s = strdup (paper_list_jx610[1]); } else { s->opt[OPT_PAPER].size = max_string_size (paper_list_jx330); s->opt[OPT_PAPER].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_PAPER].constraint.string_list = paper_list_jx330; s->val[OPT_PAPER].s = strdup (paper_list_jx330[0]); } #endif if (s->dev->sensedat.model == JX610) init_string_option(s, "Paper size", "Paper size", "Paper size", paper_list_jx610, OPT_PAPER, 1); else init_string_option(s, "Paper size", "Paper size", "Paper size", paper_list_jx330, OPT_PAPER, 0); /* gamma */ #if 0 s->opt[OPT_GAMMA].name = "Gamma"; s->opt[OPT_GAMMA].title = "Gamma"; s->opt[OPT_GAMMA].desc = "Gamma"; s->opt[OPT_GAMMA].type = SANE_TYPE_STRING; s->opt[OPT_GAMMA].size = max_string_size (gamma_list); s->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_GAMMA].constraint.string_list = gamma_list; s->val[OPT_GAMMA].s = strdup (gamma_list[1]); #endif init_string_option(s, "Gamma", "Gamma", "Gamma", gamma_list, OPT_GAMMA, 1); /* scan speed */ s->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; s->opt[OPT_SPEED].title = "Scan speed [fast]"; s->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; s->opt[OPT_SPEED].type = SANE_TYPE_BOOL; s->val[OPT_SPEED].w = SANE_TRUE; /* Resolution Group */ s->opt[OPT_RESOLUTION_GROUP].title = "Resolution"; s->opt[OPT_RESOLUTION_GROUP].desc = ""; s->opt[OPT_RESOLUTION_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_RESOLUTION_GROUP].cap = 0; s->opt[OPT_RESOLUTION_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* select resolution */ #ifdef USE_RESOLUTION_LIST if (s->dev->sensedat.model == JX610 || s->dev->sensedat.model == JX330 || s->dev->sensedat.model == JX350 || s->dev->sensedat.model == JX320) init_string_option(s, "ResolutionList", "ResolutionList", "ResolutionList", resolution_list_jx610, OPT_RESOLUTION_LIST, RESOLUTION_MAX_JX610); else init_string_option(s, "ResolutionList", "ResolutionList", "ResolutionList", resolution_list_jx250, OPT_RESOLUTION_LIST, RESOLUTION_MAX_JX250); #endif /* x resolution */ s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_X_RESOLUTION].constraint.range = &s->dev->info.xres_range; s->val[OPT_X_RESOLUTION].w = s->dev->info.xres_default; #ifdef USE_SEPARATE_Y_RESOLUTION /* y resolution */ s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_Y_RESOLUTION].constraint.range = &s->dev->info.yres_range; s->val[OPT_Y_RESOLUTION].w = s->dev->info.yres_default; #endif /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->dev->info.tl_x_ranges[default_source]; s->val[OPT_TL_X].w = s->dev->info.tl_x_ranges[default_source].min; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->dev->info.tl_y_ranges[default_source]; s->val[OPT_TL_Y].w = s->dev->info.tl_y_ranges[default_source].min; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->dev->info.br_x_ranges[default_source]; scalar = s->dev->info.x_default; clip_value (&s->opt[OPT_BR_X], &scalar); s->val[OPT_BR_X].w = scalar; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->dev->info.br_y_ranges[default_source]; /* The FSU for JX250 allows a maximum scan length of 11.5 inch, which is less than the default value of 297 mm */ scalar = s->dev->info.y_default; clip_value (&s->opt[OPT_BR_X], &scalar); s->val[OPT_BR_Y].w = scalar; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* edge emphasis */ #if 0 s->opt[OPT_EDGE_EMPHASIS].name = "Edge emphasis"; s->opt[OPT_EDGE_EMPHASIS].title = "Edge emphasis"; s->opt[OPT_EDGE_EMPHASIS].desc = "Edge emphasis"; s->opt[OPT_EDGE_EMPHASIS].type = SANE_TYPE_STRING; s->opt[OPT_EDGE_EMPHASIS].size = max_string_size (edge_emphasis_list); s->opt[OPT_EDGE_EMPHASIS].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_EDGE_EMPHASIS].constraint.string_list = edge_emphasis_list; s->val[OPT_EDGE_EMPHASIS].s = strdup (edge_emphasis_list[0]); #endif init_string_option(s, "Edge emphasis", "Edge emphasis", "Edge emphasis", edge_emphasis_list, OPT_EDGE_EMPHASIS, 0); if ( s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350 || s->dev->sensedat.model == JX320) s->opt[OPT_EDGE_EMPHASIS].cap |= SANE_CAP_INACTIVE; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &s->dev->info.threshold_range; s->val[OPT_THRESHOLD].w = 128; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].name = SANE_NAME_THRESHOLD "-red"; /* xxx the titles and decriptions are confusing: "set white point (red)" Any idea? maybe "threshold to get the red component on" */ s->opt[OPT_THRESHOLD_R].title = SANE_TITLE_THRESHOLD " (red)"; s->opt[OPT_THRESHOLD_R].desc = SANE_DESC_THRESHOLD " (red)"; s->opt[OPT_THRESHOLD_R].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD_R].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD_R].constraint.range = &s->dev->info.threshold_range; s->val[OPT_THRESHOLD_R].w = 128; s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].name = SANE_NAME_THRESHOLD "-green"; s->opt[OPT_THRESHOLD_G].title = SANE_TITLE_THRESHOLD " (green)"; s->opt[OPT_THRESHOLD_G].desc = SANE_DESC_THRESHOLD " (green)"; s->opt[OPT_THRESHOLD_G].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD_G].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD_G].constraint.range = &s->dev->info.threshold_range; s->val[OPT_THRESHOLD_G].w = 128; s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].name = SANE_NAME_THRESHOLD "-blue"; s->opt[OPT_THRESHOLD_B].title = SANE_TITLE_THRESHOLD " (blue)"; s->opt[OPT_THRESHOLD_B].desc = SANE_DESC_THRESHOLD " (blue)"; s->opt[OPT_THRESHOLD_B].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD_B].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD_B].constraint.range = &s->dev->info.threshold_range; s->val[OPT_THRESHOLD_B].w = 128; s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; #endif /* light color (for gray scale and line art scans) */ #if 0 s->opt[OPT_LIGHTCOLOR].name = "LightColor"; s->opt[OPT_LIGHTCOLOR].title = "Light Color"; s->opt[OPT_LIGHTCOLOR].desc = "Light Color"; s->opt[OPT_LIGHTCOLOR].type = SANE_TYPE_STRING; s->opt[OPT_LIGHTCOLOR].size = max_string_size (light_color_list); s->opt[OPT_LIGHTCOLOR].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_LIGHTCOLOR].constraint.string_list = light_color_list; s->val[OPT_LIGHTCOLOR].s = strdup (light_color_list[3]); s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; #endif init_string_option(s, "LightColor", "LightColor", "LightColor", light_color_list, OPT_LIGHTCOLOR, 3); s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = SANE_FALSE; #ifdef USE_CUSTOM_GAMMA /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; #if 0 s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; #if 0 s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; #if 0 s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; #if 0 s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; set_gamma_caps(s); #endif DBG (10, ">>\n"); return SANE_STATUS_GOOD; } static SANE_Status do_cancel (SHARP_Scanner * s) { static u_char cmd[] = {READ, 0, 0, 0, 0, 2, 0, 0, 0, 0}; DBG (10, "<< do_cancel "); #ifdef USE_FORK if (s->reader_pid > 0) { int exit_status; int count = 0; /* ensure child knows it's time to stop: */ DBG(11, "stopping reader process\n"); s->rdr_ctl->cancel = 1; while(reader_running(s) && count < 100) { usleep(100000); count++; }; if (reader_running(s)) { /* be brutal... !! The waiting time of 10 seconds might be far too short !! if the resolution limit of the JX 250 is increased to !! to more than 400 dpi: for these (interpolated) resolutions, !! the JX 250 is awfully slow. */ kill(s->reader_pid, SIGKILL); } wait(&exit_status); DBG(11, "reader process stopped\n"); s->reader_pid = 0; } #endif if (s->scanning == SANE_TRUE) { wait_ready(s->fd); sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0); /* if (s->adf_scan) */ if ( s->dev->sensedat.model != JX610 && s->dev->sensedat.model != JX320) object_position(s->fd, UNLOAD_PAPER); } s->scanning = SANE_FALSE; if (s->fd >= 0) { sanei_scsi_close (s->fd); s->fd = -1; } #ifdef USE_FORK { struct shmid_ds ds; if (s->shmid != -1) shmctl(s->shmid, IPC_RMID, &ds); s->shmid = -1; } #endif if (s->buffer) free(s->buffer); s->buffer = 0; DBG (10, ">>\n"); return (SANE_STATUS_CANCELLED); } static SHARP_New_Device *new_devs = 0; static SHARP_New_Device *new_dev_pool = 0; static SANE_Status attach_and_list(const char *devnam) { SANE_Status res; SHARP_Device *devp; SHARP_New_Device *np; res = attach(devnam, &devp); if (res == SANE_STATUS_GOOD) { if (new_dev_pool) { np = new_dev_pool; new_dev_pool = np->next; } else { np = malloc(sizeof(SHARP_New_Device)); if (np == 0) return SANE_STATUS_NO_MEM; } np->next =new_devs; np->dev = devp; new_devs = np; } return res; } static int buffers[2] = {DEFAULT_BUFFERS, DEFAULT_BUFFERS}; static int bufsize[2] = {DEFAULT_BUFSIZE, DEFAULT_BUFSIZE}; static int queued_reads[2] = {DEFAULT_QUEUED_READS, DEFAULT_QUEUED_READS}; static int stop_on_fsu_error[2] = {COMPLAIN_ON_FSU_ERROR | COMPLAIN_ON_ADF_ERROR, COMPLAIN_ON_FSU_ERROR | COMPLAIN_ON_ADF_ERROR}; static int default_scan_mode[2] = {-1, -1}; SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { char devnam[PATH_MAX] = "/dev/scanner"; char line[PATH_MAX]; const char *lp; char *word; char *end; FILE *fp; int opt_index = 0; int linecount = 0; #if 1 SHARP_Device sd; SHARP_Device *dp = &sd; #else SHARP_Device *dp; #endif SHARP_New_Device *np; int i; DBG_INIT (); DBG (10, "<< sane_init "); #if defined PACKAGE && defined VERSION DBG (2, "sane_init: " PACKAGE " " VERSION "\n"); #endif if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (SHARP_CONFIG_FILE); if (!fp) { /* use "/dev/scanner" as the default device name if no config file is available */ attach (devnam, &dp); /* make sure that there are at least two buffers */ if (DEFAULT_BUFFERS < 2) dp->info.buffers = DEFAULT_BUFFERS; else dp->info.buffers = 2; dp->info.wanted_bufsize = DEFAULT_BUFSIZE; dp->info.queued_reads = DEFAULT_QUEUED_READS; dp->info.complain_on_errors = COMPLAIN_ON_ADF_ERROR | COMPLAIN_ON_FSU_ERROR; dp->info.default_scan_mode = -1; return SANE_STATUS_GOOD; } while (fgets(line, PATH_MAX, fp)) { linecount++; word = 0; lp = sanei_config_get_string(line, &word); if (word) { if (word[0] != '#') { if (strcmp(word, "option") == 0) { free(word); word = 0; lp = sanei_config_get_string(lp, &word); if (strcmp(word, "buffers") == 0) { free(word); word = 0; sanei_config_get_string(lp, &word); i = strtol(word, &end, 0); if (end == word) { DBG(1, "error in config file, line %i: number expected:\n", linecount); DBG(1, "%s\n", line); } else if (i > 2) buffers[opt_index] = i; else buffers[opt_index] = 2; } else if (strcmp(word, "buffersize") == 0) { free(word); word = 0; sanei_config_get_string(lp, &word); i = strtol(word, &end, 0); if (word == end) { DBG(1, "error in config file, line %i: number expected:\n", linecount); DBG(1, "%s\n", line); } else bufsize[opt_index] = i; } else if (strcmp(word, "readqueue") == 0) { free(word); word = 0; sanei_config_get_string(lp, &word); i = strtol(word, &end, 0); if (word == end) { DBG(1, "error in config file, line %i: number expected:\n", linecount); DBG(1, "%s\n", line); } else queued_reads[opt_index] = i; } else if (strcmp(word, "stop_on_fsu_error") == 0) { free(word); word = 0; sanei_config_get_string(lp, &word); i = strtol(word, &end, 0); if (word == end) { DBG(1, "error in config file, line %i: number expected:\n", linecount); DBG(1, "%s\n", line); } else stop_on_fsu_error[opt_index] = i ? COMPLAIN_ON_FSU_ERROR : 0; } else if (strcmp(word, "default_scan_source") == 0) { free(word); word = 0; sanei_config_get_string(lp, &word); if (strcmp(word, "auto") == 0) default_scan_mode[opt_index] = -1; else if (strcmp(word, "fsu") == 0) default_scan_mode[opt_index] = SCAN_WITH_FSU; else if (strcmp(word, "adf") == 0) default_scan_mode[opt_index] = SCAN_WITH_ADF; else if (strcmp(word, "flatbed") == 0) default_scan_mode[opt_index] = SCAN_SIMPLE; else { DBG(1, "error in config file, line %i: number expected:\n", linecount); DBG(1, "%s\n", line); } } else { DBG(1, "error in config file, line %i: unknown option\n", linecount); DBG(1, "%s\n", line); } } else { while (new_devs) { if (buffers[1] >= 2) new_devs->dev->info.buffers = buffers[1]; else new_devs->dev->info.buffers = 2; if (bufsize[1] > 0) new_devs->dev->info.wanted_bufsize = bufsize[1]; else new_devs->dev->info.wanted_bufsize = DEFAULT_BUFSIZE; if (queued_reads[1] >= 0) new_devs->dev->info.queued_reads = queued_reads[1]; else new_devs->dev->info.queued_reads = 0; new_devs->dev->info.complain_on_errors = stop_on_fsu_error[1]; new_devs->dev->info.default_scan_mode = default_scan_mode[1]; np = new_devs->next; new_devs->next = new_dev_pool; new_dev_pool = new_devs; new_devs = np; } if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0; sanei_config_attach_matching_devices(line, &attach_and_list); buffers[1] = buffers[0]; bufsize[1] = bufsize[0]; queued_reads[1] = queued_reads[0]; stop_on_fsu_error[1] = stop_on_fsu_error[0]; default_scan_mode[1] = default_scan_mode[0]; opt_index = 1; } } if (word) free(word); } } while (new_devs) { if (buffers[1] >= 2) new_devs->dev->info.buffers = buffers[1]; else new_devs->dev->info.buffers = 2; if (bufsize[1] > 0) new_devs->dev->info.wanted_bufsize = bufsize[1]; else new_devs->dev->info.wanted_bufsize = DEFAULT_BUFSIZE; if (queued_reads[1] >= 0) new_devs->dev->info.queued_reads = queued_reads[1]; else new_devs->dev->info.queued_reads = 0; new_devs->dev->info.complain_on_errors = stop_on_fsu_error[1]; new_devs->dev->info.default_scan_mode = default_scan_mode[1]; if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0; np = new_devs->next; free(new_devs); new_devs = np; } while (new_dev_pool) { np = new_dev_pool->next; free(new_dev_pool); new_dev_pool = np; } fclose(fp); DBG (10, "sane_init >>\n"); return (SANE_STATUS_GOOD); } static const SANE_Device **devlist = 0; void sane_exit (void) { SHARP_Device *dev, *next; DBG (10, "<< sane_exit "); for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free (dev); } if (devlist) free(devlist); devlist = 0; first_dev = 0; DBG (10, ">>\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { SHARP_Device *dev; int i; DBG (10, "<< sane_get_devices "); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return (SANE_STATUS_NO_MEM); i = 0; for (dev = first_dev; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (10, ">>\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devnam, SANE_Handle * handle) { SANE_Status status; SHARP_Device *dev; SHARP_Scanner *s; #ifdef USE_CUSTOM_GAMMA int i, j; #endif DBG (10, "<< sane_open "); if (devnam[0]) { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) break; } if (!dev) { status = attach (devnam, &dev); if (status != SANE_STATUS_GOOD) return (status); dev->info.buffers = buffers[0]; dev->info.wanted_bufsize = bufsize[0]; dev->info.queued_reads = queued_reads[0]; } } else { dev = first_dev; } if (!dev) return (SANE_STATUS_INVAL); s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->dev = dev; s->buffer = 0; #ifdef USE_CUSTOM_GAMMA for (i = 0; i < 4; ++i) for (j = 0; j < 256; ++j) s->gamma_table[i][j] = j; #endif status = init_options (s); if (status != SANE_STATUS_GOOD) { /* xxx clean up mallocs */ return status; } s->next = first_handle; first_handle = s; *handle = s; DBG (10, ">>\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { SHARP_Scanner *s = (SHARP_Scanner *) handle; DBG (10, "<< sane_close "); if (s->fd != -1) sanei_scsi_close (s->fd); #ifdef USE_FORK { struct shmid_ds ds; if (s->shmid != -1) shmctl(s->shmid, IPC_RMID, &ds); } #endif if (s->buffer) free(s->buffer); free (s); DBG (10, ">>\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { SHARP_Scanner *s = handle; DBG (10, "<< sane_get_option_descriptor "); if ((unsigned) option >= NUM_OPTIONS) return (0); DBG (10, ">>\n"); return (s->opt + option); } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { SHARP_Scanner *s = handle; SANE_Status status; #ifdef USE_CUSTOM_GAMMA SANE_Word w, cap; #else SANE_Word cap; #endif #ifdef USE_RESOLUTION_LIST int i; #endif int range_index; DBG (10, "<< sane_control_option %i", option); if (info) *info = 0; if (s->scanning) return (SANE_STATUS_DEVICE_BUSY); if (option >= NUM_OPTIONS) return (SANE_STATUS_INVAL); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return (SANE_STATUS_INVAL); if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_X_RESOLUTION: #ifdef USE_SEPARATE_Y_RESOLUTION case OPT_Y_RESOLUTION: #endif case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_THRESHOLD: #ifdef USE_COLOR_THRESHOLD case OPT_THRESHOLD_R: case OPT_THRESHOLD_G: case OPT_THRESHOLD_B: #endif case OPT_SPEED: case OPT_PREVIEW: #ifdef USE_CUSTOM_GAMMA case OPT_CUSTOM_GAMMA: #endif *(SANE_Word *) val = s->val[option].w; #if 0 /* here, values are read; reload should not be necessary */ if (info) *info |= SANE_INFO_RELOAD_PARAMS; #endif return (SANE_STATUS_GOOD); #ifdef USE_CUSTOM_GAMMA /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); return SANE_STATUS_GOOD; #endif /* string options: */ case OPT_MODE: case OPT_HALFTONE: case OPT_PAPER: case OPT_GAMMA: #ifdef USE_RESOLUTION_LIST case OPT_RESOLUTION_LIST: #endif case OPT_EDGE_EMPHASIS: case OPT_LIGHTCOLOR: case OPT_SCANSOURCE: strcpy (val, s->val[option].s); #if 0 if (info) *info |= SANE_INFO_RELOAD_PARAMS; #endif return (SANE_STATUS_GOOD); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_X_RESOLUTION: #ifdef USE_SEPARATE_Y_RESOLUTION case OPT_Y_RESOLUTION: #endif case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; case OPT_NUM_OPTS: case OPT_THRESHOLD: /* xxx theoretically, we could use OPT_THRESHOLD in bi-level color mode to adjust all three other threshold together. But this would require to set the bit SANE_INFO_RELOAD_OPTIONS in *info, and that would unfortunately cause a crash in both xscanimage and xsane... Therefore, OPT_THRESHOLD is disabled for bi-level color scan right now. */ #ifdef USE_COLOR_THRESHOLD case OPT_THRESHOLD_R: case OPT_THRESHOLD_G: case OPT_THRESHOLD_B: #endif case OPT_SPEED: case OPT_PREVIEW: s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_MODE: if (strcmp (val, M_LINEART) == 0) { s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; #endif if (s->dev->sensedat.model == JX330) s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (val, M_LINEART_COLOR) == 0) { s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].cap &= ~SANE_CAP_INACTIVE; #endif if (s->dev->sensedat.model == JX330) s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; } if ( strcmp (val, M_LINEART) == 0 || strcmp (val, M_GRAY) == 0) { s->opt[OPT_LIGHTCOLOR].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; } strcpy(s->val[option].s, val); #ifdef USE_CUSTOM_GAMMA set_gamma_caps(s); #endif if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return (SANE_STATUS_GOOD); case OPT_GAMMA: case OPT_HALFTONE: case OPT_EDGE_EMPHASIS: case OPT_LIGHTCOLOR: #if 0 if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); #endif strcpy(s->val[option].s, val); return (SANE_STATUS_GOOD); case OPT_SCANSOURCE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; #if 0 if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); #endif strcpy(s->val[option].s, val); if (strcmp(val, use_fsu) == 0) range_index = SCAN_WITH_FSU; else if (strcmp(val, use_adf) == 0) range_index = SCAN_WITH_ADF; else range_index = SCAN_SIMPLE; s->opt[OPT_TL_X].constraint.range = &s->dev->info.tl_x_ranges[range_index]; clip_value (&s->opt[OPT_TL_X], &s->val[OPT_TL_X].w); s->opt[OPT_TL_Y].constraint.range = &s->dev->info.tl_y_ranges[range_index]; clip_value (&s->opt[OPT_TL_Y], &s->val[OPT_TL_Y].w); s->opt[OPT_BR_X].constraint.range = &s->dev->info.br_x_ranges[range_index]; clip_value (&s->opt[OPT_BR_X], &s->val[OPT_BR_X].w); s->opt[OPT_BR_Y].constraint.range = &s->dev->info.br_y_ranges[range_index]; clip_value (&s->opt[OPT_BR_Y], &s->val[OPT_BR_Y].w); return (SANE_STATUS_GOOD); case OPT_PAPER: if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; #if 0 if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); #endif strcpy(s->val[option].s, val); s->val[OPT_TL_X].w = SANE_FIX(0); s->val[OPT_TL_Y].w = SANE_FIX(0); if (strcmp (s->val[option].s, "A3") == 0){ s->val[OPT_BR_X].w = SANE_FIX(297); s->val[OPT_BR_Y].w = SANE_FIX(420); }else if (strcmp (s->val[option].s, "A4") == 0){ s->val[OPT_BR_X].w = SANE_FIX(210); s->val[OPT_BR_Y].w = SANE_FIX(297); }else if (strcmp (s->val[option].s, "A5") == 0){ s->val[OPT_BR_X].w = SANE_FIX(148.5); s->val[OPT_BR_Y].w = SANE_FIX(210); }else if (strcmp (s->val[option].s, "A6") == 0){ s->val[OPT_BR_X].w = SANE_FIX(105); s->val[OPT_BR_Y].w = SANE_FIX(148.5); }else if (strcmp (s->val[option].s, "B4") == 0){ s->val[OPT_BR_X].w = SANE_FIX(250); s->val[OPT_BR_Y].w = SANE_FIX(353); }else if (strcmp (s->val[option].s, "B5") == 0){ s->val[OPT_BR_X].w = SANE_FIX(182); s->val[OPT_BR_Y].w = SANE_FIX(257); }else if (strcmp (s->val[option].s, W_LETTER) == 0){ s->val[OPT_BR_X].w = SANE_FIX(279.4); s->val[OPT_BR_Y].w = SANE_FIX(431.8); }else if (strcmp (s->val[option].s, "Legal") == 0){ s->val[OPT_BR_X].w = SANE_FIX(215.9); s->val[OPT_BR_Y].w = SANE_FIX(355.6); }else if (strcmp (s->val[option].s, "Letter") == 0){ s->val[OPT_BR_X].w = SANE_FIX(215.9); s->val[OPT_BR_Y].w = SANE_FIX(279.4); }else if (strcmp (s->val[option].s, INVOICE) == 0){ s->val[OPT_BR_X].w = SANE_FIX(215.9); s->val[OPT_BR_Y].w = SANE_FIX(139.7); }else{ } return (SANE_STATUS_GOOD); #ifdef USE_RESOLUTION_LIST case OPT_RESOLUTION_LIST: if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; for (i = 0; s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]; i++) { if (strcmp (val, s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]) == 0){ s->val[OPT_X_RESOLUTION].w = atoi(s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]); s->val[OPT_Y_RESOLUTION].w = atoi(s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]); if (info) *info |= SANE_INFO_RELOAD_PARAMS; break; } } return (SANE_STATUS_GOOD); #endif #ifdef USE_CUSTOM_GAMMA /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == s->val[OPT_CUSTOM_GAMMA].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[OPT_CUSTOM_GAMMA].w = w; set_gamma_caps(s); return SANE_STATUS_GOOD; #endif } } DBG (10, ">>\n"); return (SANE_STATUS_INVAL); } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int width, length, xres, yres; const char *mode; SHARP_Scanner *s = handle; DBG (10, "<< sane_get_parameters "); xres = s->val[OPT_X_RESOLUTION].w; #ifdef USE_SEPARATE_Y_RESOLUTION yres = s->val[OPT_Y_RESOLUTION].w; #else yres = xres; #endif if (!s->scanning) { /* make best-effort guess at what parameters will look like once scanning starts. */ memset (&s->params, 0, sizeof (s->params)); width = MM_TO_PIX( SANE_UNFIX(s->val[OPT_BR_X].w) - SANE_UNFIX(s->val[OPT_TL_X].w), s->dev->info.mud); length = MM_TO_PIX( SANE_UNFIX(s->val[OPT_BR_Y].w) - SANE_UNFIX(s->val[OPT_TL_Y].w), s->dev->info.mud); s->width = width; s->length = length; s->params.pixels_per_line = width * xres / s->dev->info.mud; s->params.lines = length * yres / s->dev->info.mud; s->unscanned_lines = s->params.lines; } else { static u_char cmd[] = {READ, 0, 0x81, 0, 0, 0, 0, 0, 4, 0}; static u_char buf[4]; size_t len = 4; SANE_Status status; /* if async reads are used, )ie. if USE_FORK is defined, this command may only be issued immediately after the "start scan" command. Later calls will confuse the read queue. */ if (!s->get_params_called) { wait_ready(s->fd); status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), buf, &len); if (status != SANE_STATUS_GOOD) { do_cancel(s); return (status); } s->params.pixels_per_line = (buf[1] << 8) + buf[0]; s->params.lines = (buf[3] << 8) + buf[2]; s->get_params_called = 1; } } xres = s->val[OPT_X_RESOLUTION].w; #ifdef USE_SEPARATE_Y_RESOLUTION yres = s->val[OPT_Y_RESOLUTION].w; #else yres = xres; #endif mode = s->val[OPT_MODE].s; if (strcmp (mode, M_LINEART) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; s->params.depth = 1; s->modes = MODES_LINEART; } else if (strcmp (mode, M_GRAY) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; s->modes = MODES_GRAY; } else { s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line; s->params.depth = 8; s->modes = MODES_COLOR; } s->params.last_frame = SANE_TRUE; if (params) *params = s->params; DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } #ifdef USE_CUSTOM_GAMMA static int sprint_gamma(Option_Value val, SANE_Byte *dst) { int i; SANE_Byte *p = dst; p += sprintf((char *) p, "%i", val.wa[0] > 255 ? 255 : val.wa[0]); /* val.wa[i] is over 255, so val.wa[i] is limitied to 255 */ for (i = 1; i < 256; i++) p += sprintf((char *) p, ",%i", val.wa[i] > 255 ? 255 : val.wa[i]); return p - dst; } static SANE_Status send_ascii_gamma_tables (SHARP_Scanner *s) { SANE_Status status; int i; DBG(11, "<< send_ascii_gamma_tables "); /* we need: 4 bytes for each gamma value (3 digits + delimiter) + 10 bytes for the command header i.e. 4 * 4 * 256 + 10 = 4106 bytes */ if (s->dev->info.bufsize < 4106) return SANE_STATUS_NO_MEM; memset(s->buffer, 0, 4106); i = sprint_gamma(s->val[OPT_GAMMA_VECTOR_R], &s->buffer[10]); s->buffer[10+i++] = '/'; i += sprint_gamma(s->val[OPT_GAMMA_VECTOR_G], &s->buffer[10+i]); s->buffer[10+i++] = '/'; i += sprint_gamma(s->val[OPT_GAMMA_VECTOR_B], &s->buffer[10+i]); s->buffer[10+i++] = '/'; i += sprint_gamma(s->val[OPT_GAMMA_VECTOR], &s->buffer[10+i]); DBG(11, "%s\n", &s->buffer[10]); s->buffer[0] = SEND; s->buffer[2] = 0x03; s->buffer[7] = i >> 8; s->buffer[8] = i & 0xff; wait_ready(s->fd); status = sanei_scsi_cmd (s->fd, s->buffer, i+10, 0, 0); DBG(11, ">>\n"); return status; } #endif static SANE_Status send_binary_g_table(SHARP_Scanner *s, SANE_Word *a, int dtq) { SANE_Status status; int i; DBG(11, "<< send_binary_g_table\n"); memset(s->buffer, 0, 522); s->buffer[0] = SEND; s->buffer[2] = 0x03; s->buffer[5] = dtq; s->buffer[7] = 2; s->buffer[8] = 0; for (i = 0; i < 256; i++) { s->buffer[2*i+11] = a[i] > 255 ? 255 : a[i]; } for (i = 0; i < 256; i += 16) { DBG(11, "%02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", a[i ], a[i+1], a[i+2], a[i+3], a[i+4], a[i+5], a[i+6], a[i+7], a[i+8], a[i+9], a[i+10], a[i+11], a[i+12], a[i+13], a[i+14], a[i+15]); } wait_ready(s->fd); status = sanei_scsi_cmd (s->fd, s->buffer, 2*i+10, 0, 0); DBG(11, ">>\n"); return status; } #ifdef USE_CUSTOM_GAMMA static SANE_Status send_binary_gamma_tables (SHARP_Scanner *s) { SANE_Status status; status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR].wa, 0x10); if (status != SANE_STATUS_GOOD) return status; status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_R].wa, 0x11); if (status != SANE_STATUS_GOOD) return status; status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_G].wa, 0x12); if (status != SANE_STATUS_GOOD) return status; status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_B].wa, 0x13); return status; } static SANE_Status send_gamma_tables (SHARP_Scanner *s) { if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350) { return send_ascii_gamma_tables(s); } else { return send_binary_gamma_tables(s); } } #endif #ifdef USE_COLOR_THRESHOLD static SANE_Status send_threshold_data(SHARP_Scanner *s) { SANE_Status status; SANE_Byte cmd[26] = {SEND, 0, 0x82, 0, 0, 0, 0, 0, 0, 0}; int len; memset(cmd, 0, sizeof(cmd)); /* maximum string length: 3 bytes for each number (they are restricted to the range 0..255), 3 '/' and the null-byte, total: 16 bytes. */ len = sprintf((char *) &cmd[10], "%i/%i/%i/%i", s->val[OPT_THRESHOLD_R].w, s->val[OPT_THRESHOLD_G].w, s->val[OPT_THRESHOLD_B].w, s->val[OPT_THRESHOLD].w); cmd[8] = len; wait_ready(s->fd); status = sanei_scsi_cmd(s->fd, cmd, len + 10, 0, 0); return status; } #endif SANE_Status sane_start (SANE_Handle handle) { char *mode, *halftone, *gamma, *edge, *lightcolor, *adf_fsu; SHARP_Scanner *s = handle; SANE_Status status; size_t buf_size; SHARP_Send ss; window_param wp; mode_sense_subdevice m_subdev; DBG (10, "<< sane_start "); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; s->dev->sensedat.complain_on_errors = COMPLAIN_ON_ADF_ERROR | s->dev->info.complain_on_errors; #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED s->dev->info.bufsize = s->dev->info.wanted_bufsize; if (s->dev->info.bufsize < 32 * 1024) s->dev->info.bufsize = 32 * 1024; { int bsize = s->dev->info.bufsize; status = sanei_scsi_open_extended (s->dev->sane.name, &s->fd, &sense_handler, &s->dev->sensedat, &bsize); s->dev->info.bufsize = bsize; } if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->dev->sane.name, sane_strstatus (status)); return (status); } /* make sure that we got at least 32 kB. Even then, the scan will be awfully slow. NOTE: If you need to decrease this value, remember that s->buffer is used in send_ascii_gamma_tables (JX330/JX610) and in send_binary_g_table (JX250/JX350). send_ascii_gamma_tables needs 4106 bytes, and send_binary_g_table needs 522 bytes. */ if (s->dev->info.bufsize < 32 * 1024) { sanei_scsi_close(s->fd); s->fd = -1; return SANE_STATUS_NO_MEM; } #else status = sanei_scsi_open(s->dev->sane.name, &s->fd, &sense_handler, &s->dev->sensedat); if (s->dev->info.wanted_bufsize < sanei_scsi_max_request_size) s->dev->info.bufsize = s->dev->info.wanted_bufsize; else s->dev->info.bufsize = sanei_scsi_max_request_size; if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->dev->sane.name, sane_strstatus (status)); return (status); } #endif s->buffer = malloc(s->dev->info.bufsize); if (!s->buffer) { sanei_scsi_close(s->fd); s->fd = -1; free(s); return SANE_STATUS_NO_MEM; } #ifdef USE_FORK { struct shmid_ds ds; size_t n; s->shmid = shmget(IPC_PRIVATE, sizeof(SHARP_rdr_ctl) + s->dev->info.buffers * (sizeof(SHARP_shmem_ctl) + s->dev->info.bufsize), IPC_CREAT | 0600); if (s->shmid == -1) { free(s->buffer); s->buffer = 0; sanei_scsi_close(s->fd); s->fd = -1; return SANE_STATUS_NO_MEM; } s->rdr_ctl = (SHARP_rdr_ctl*) shmat(s->shmid, 0, 0); if (s->rdr_ctl == (void *) -1) { shmctl(s->shmid, IPC_RMID, &ds); free(s->buffer); s->buffer = 0; sanei_scsi_close(s->fd); s->fd = -1; return SANE_STATUS_NO_MEM; } s->rdr_ctl->buf_ctl = (SHARP_shmem_ctl*) &s->rdr_ctl[1]; for (n = 0; n < s->dev->info.buffers; n++) { s->rdr_ctl->buf_ctl[n].buffer = (SANE_Byte*) &s->rdr_ctl->buf_ctl[s->dev->info.buffers] + n * s->dev->info.bufsize; } } #endif /* USE_FORK */ DBG (5, "start: TEST_UNIT_READY\n"); status = test_unit_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "TEST UNIT READY failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (3, "start: sending MODE SELECT\n"); status = mode_select_mud (s->fd, s->dev->info.mud); if (status != SANE_STATUS_GOOD) { DBG (1, "start: MODE_SELECT6 failed\n"); sanei_scsi_close (s->fd); s->fd = -1; return (status); } mode = s->val[OPT_MODE].s; halftone = s->val[OPT_HALFTONE].s; gamma = s->val[OPT_GAMMA].s; edge = s->val[OPT_EDGE_EMPHASIS].s; lightcolor = s->val[OPT_LIGHTCOLOR].s; adf_fsu = s->val[OPT_SCANSOURCE].s; s->speed = s->val[OPT_SPEED].w; s->xres = s->val[OPT_X_RESOLUTION].w; if (s->val[OPT_PREVIEW].w == SANE_FALSE) { #ifdef USE_SEPARATE_Y_RESOLUTION s->yres = s->val[OPT_Y_RESOLUTION].w; #else s->yres = s->val[OPT_X_RESOLUTION].w; #endif s->speed = s->val[OPT_SPEED].w; } else { s->yres = s->val[OPT_X_RESOLUTION].w; s->speed = SANE_TRUE; } s->ulx = MM_TO_PIX(SANE_UNFIX(s->val[OPT_TL_X].w), s->dev->info.mud); s->uly = MM_TO_PIX(SANE_UNFIX(s->val[OPT_TL_Y].w), s->dev->info.mud); s->threshold = s->val[OPT_THRESHOLD].w; s->bpp = s->params.depth; s->adf_fsu_mode = SCAN_SIMPLE; /* default: scan without ADF and FSU */ #ifdef ALLOW_AUTO_SELECT_ADF if (strcmp (adf_fsu, use_auto) == 0) s->adf_fsu_mode = SCAN_ADF_FSU_AUTO; else #endif if (strcmp(adf_fsu, use_fsu) == 0) s->adf_fsu_mode = SCAN_WITH_FSU; else if (strcmp(adf_fsu, use_adf) == 0) s->adf_fsu_mode = SCAN_WITH_ADF; else if (strcmp(adf_fsu, use_adf) == 0) s->adf_fsu_mode = SCAN_SIMPLE; if (strcmp (mode, M_LINEART) == 0) { s->reverse = 0; if (strcmp(halftone, M_BILEVEL) == 0) { s->halftone = 1; s->image_composition = 0; } else if (strcmp(halftone, M_BAYER) == 0) { s->halftone = 2; s->image_composition = 1; } else if (strcmp(halftone, M_SPIRAL) == 0) { s->halftone = 3; s->image_composition = 1; } else if (strcmp(halftone, M_DISPERSED) == 0) { s->halftone = 4; s->image_composition = 1; } else if (strcmp(halftone, M_ERRDIFFUSION) == 0) { s->halftone = 5; s->image_composition = 1; } } else if (strcmp (mode, M_GRAY) == 0) { s->image_composition = 2; s->reverse = 1; } else if (strcmp (mode, M_LINEART_COLOR) == 0) { s->reverse = 1; if (strcmp(halftone, M_BILEVEL) == 0) { s->halftone = 1; s->image_composition = 3; } else if (strcmp(halftone, M_BAYER) == 0) { s->halftone = 2; s->image_composition = 4; } else if (strcmp(halftone, M_SPIRAL) == 0) { s->halftone = 3; s->image_composition = 4; } else if (strcmp(halftone, M_DISPERSED) == 0) { s->halftone = 4; s->image_composition = 4; } else if (strcmp(halftone, M_ERRDIFFUSION) == 0) { s->halftone = 5; s->image_composition = 4; } } else if (strcmp (mode, M_COLOR) == 0) { s->image_composition = 5; s->reverse = 1; } if (strcmp (edge, EDGE_NONE) == 0) { DBG (11, "EDGE EMPHASIS NONE\n"); s->edge = 0; } else if (strcmp (edge, EDGE_MIDDLE) == 0) { DBG (11, "EDGE EMPHASIS MIDDLE\n"); s->edge = 1; } else if (strcmp (edge, EDGE_STRONG) == 0) { DBG (11, "EDGE EMPHASIS STRONG\n"); s->edge = 2; } else if (strcmp (edge, EDGE_BLUR) == 0) { DBG (11, "EDGE EMPHASIS BLUR\n"); s->edge = 3; } s->lightcolor = 3; if (strcmp(lightcolor, LIGHT_GREEN) == 0) s->lightcolor = 0; else if (strcmp(lightcolor, LIGHT_RED) == 0) s->lightcolor = 1; else if (strcmp(lightcolor, LIGHT_BLUE) == 0) s->lightcolor = 2; else if (strcmp(lightcolor, LIGHT_WHITE) == 0) s->lightcolor = 3; s->adf_scan = 0; if ( s->dev->sensedat.model != JX610 && s->dev->sensedat.model != JX320) { status = mode_select_adf_fsu(s->fd, s->adf_fsu_mode); if (status != SANE_STATUS_GOOD) { DBG (10, "sane_start: mode_select_adf_fsu failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } /* if the ADF is selected, check if it is ready */ memset (&m_subdev, 0, sizeof (m_subdev)); buf_size = sizeof (m_subdev); status = mode_sense (s->fd, &m_subdev, &buf_size, 0x20); DBG(11, "mode sense result a_mode: %x f_mode: %x\n", m_subdev.a_mode_type, m_subdev.f_mode_type); if (status != SANE_STATUS_GOOD) { DBG (10, "sane_start: MODE_SENSE/subdevice page failed\n"); sanei_scsi_close (s->fd); s->fd = -1; return (status); } if (s->adf_fsu_mode == SCAN_WITH_ADF) s->adf_scan = 1; #ifdef ALLOW_AUTO_SELECT_ADF else if (s->adf_fsu_mode == SCAN_ADF_FSU_AUTO) { if (m_subdev.a_mode_type & 0x80) s->adf_scan = 1; } #endif } #ifdef USE_CUSTOM_GAMMA if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) { #endif if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350) { ss.dtc = 0x03; if (strcmp (gamma, GAMMA10) == 0) { ss.dtq = 0x01; }else{ ss.dtq = 0x02; } ss.length = 0; DBG (5, "start: SEND\n"); status = send (s->fd, &ss); if (status != SANE_STATUS_GOOD) { DBG (1, "send failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } } else { /* the JX250 does not support the "fixed gamma selection", therefore, lets calculate & send gamma values */ int i; SANE_Word gtbl[256]; if (strcmp (gamma, GAMMA10) == 0) for (i = 0; i < 256; i++) gtbl[i] = i; else { gtbl[0] = 0; for (i = 1; i < 256; i++) gtbl[i] = 255 * exp(0.45 * log(i/255.0)); } send_binary_g_table(s, gtbl, 0x10); send_binary_g_table(s, gtbl, 0x11); send_binary_g_table(s, gtbl, 0x12); send_binary_g_table(s, gtbl, 0x13); } #ifdef USE_CUSTOM_GAMMA } else status = send_gamma_tables(s); if (status != SANE_STATUS_GOOD) { sanei_scsi_close (s->fd); s->fd = -1; return (status); } #endif if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350) { ss.dtc = 0x86; ss.dtq = 0x05; ss.length = 0; DBG (5, "start: SEND\n"); status = send (s->fd, &ss); if (status != SANE_STATUS_GOOD) { DBG (1, "send failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } #ifdef USE_COLOR_THRESHOLD status = send_threshold_data(s); if (status != SANE_STATUS_GOOD) { DBG (1, "send threshold data failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } #endif } memset (&wp, 0, sizeof (wp)); /* every Sharp scanner seems to have a different window descriptor block... */ if ( s->dev->sensedat.model == JX610 || s->dev->sensedat.model == JX320) { buf_size = sizeof(WDB); } else if (s->dev->sensedat.model == JX330) { buf_size = sizeof (WDB) + sizeof(WDBX330); } else { buf_size = sizeof (WDB) + sizeof(WDBX330) + sizeof(WDBX250); } wp.wpdh.wdl[0] = buf_size >> 8; wp.wpdh.wdl[1] = buf_size; wp.wdb.x_res[0] = s->xres >> 8; wp.wdb.x_res[1] = s->xres; wp.wdb.y_res[0] = s->yres >> 8; wp.wdb.y_res[1] = s->yres; wp.wdb.x_ul[0] = s->ulx >> 24; wp.wdb.x_ul[1] = s->ulx >> 16; wp.wdb.x_ul[2] = s->ulx >> 8; wp.wdb.x_ul[3] = s->ulx; wp.wdb.y_ul[0] = s->uly >> 24; wp.wdb.y_ul[1] = s->uly >> 16; wp.wdb.y_ul[2] = s->uly >> 8; wp.wdb.y_ul[3] = s->uly; wp.wdb.width[0] = s->width >> 24; wp.wdb.width[1] = s->width >> 16; wp.wdb.width[2] = s->width >> 8; wp.wdb.width[3] = s->width; wp.wdb.length[0] = s->length >> 24; wp.wdb.length[1] = s->length >> 16; wp.wdb.length[2] = s->length >> 8; wp.wdb.length[3] = s->length; wp.wdb.brightness = 0; wp.wdb.threshold = s->threshold; wp.wdb.image_composition = s->image_composition; if (s->image_composition <= 2 || s->image_composition >= 5) wp.wdb.bpp = s->bpp; else wp.wdb.bpp = 1; wp.wdb.ht_pattern[0] = 0; if ( s->dev->sensedat.model == JX610 || s->dev->sensedat.model == JX320) { wp.wdb.ht_pattern[1] = 0; }else{ wp.wdb.ht_pattern[1] = s->halftone; } wp.wdb.rif_padding = (s->reverse * 128) + 0; wp.wdb.eletu = (!s->speed << 2) + (s->edge << 6) + (s->lightcolor << 4); if (s->dev->sensedat.model == JX250 || s->dev->sensedat.model == JX350) { wp.wdbx250.threshold_red = s->val[OPT_THRESHOLD_R].w; wp.wdbx250.threshold_green = s->val[OPT_THRESHOLD_G].w; wp.wdbx250.threshold_blue = s->val[OPT_THRESHOLD_B].w; } DBG (5, "wdl=%d\n", (wp.wpdh.wdl[0] << 8) + wp.wpdh.wdl[1]); DBG (5, "xres=%d\n", (wp.wdb.x_res[0] << 8) + wp.wdb.x_res[1]); DBG (5, "yres=%d\n", (wp.wdb.y_res[0] << 8) + wp.wdb.y_res[1]); DBG (5, "ulx=%d\n", (wp.wdb.x_ul[0] << 24) + (wp.wdb.x_ul[1] << 16) + (wp.wdb.x_ul[2] << 8) + wp.wdb.x_ul[3]); DBG (5, "uly=%d\n", (wp.wdb.y_ul[0] << 24) + (wp.wdb.y_ul[1] << 16) + (wp.wdb.y_ul[2] << 8) + wp.wdb.y_ul[3]); DBG (5, "width=%d\n", (wp.wdb.width[0] << 8) + (wp.wdb.width[1] << 16) + (wp.wdb.width[2] << 8) + wp.wdb.width[3]); DBG (5, "length=%d\n", (wp.wdb.length[0] << 16) + (wp.wdb.length[1] << 16) + (wp.wdb.length[2] << 8) + wp.wdb.length[3]); DBG (5, "threshold=%d\n", wp.wdb.threshold); DBG (5, "image_composition=%d\n", wp.wdb.image_composition); DBG (5, "bpp=%d\n", wp.wdb.bpp); DBG (5, "rif_padding=%d\n", wp.wdb.rif_padding); DBG (5, "eletu=%d\n", wp.wdb.eletu); #if 0 { unsigned char *p = (unsigned char*) &wp.wdb; int i; DBG(11, "set window:\n"); for (i = 0; i < sizeof(wp.wdb) + + sizeof(wp.wdbx330) + sizeof(wp.wdbx250); i += 16) { DBG(1, "%2x %2x %2x %2x %2x %2x %2x %2x - %2x %2x %2x %2x %2x %2x %2x %2x\n", p[i], p[i+1], p[i+2], p[i+3], p[i+4], p[i+5], p[i+6], p[i+7], p[i+8], p[i+9], p[i+10], p[i+11], p[i+12], p[i+13], p[i+14], p[i+15]); } } #endif buf_size += sizeof(WPDH); DBG (5, "start: SET WINDOW\n"); status = set_window (s->fd, &wp, buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } memset (&wp, 0, buf_size); DBG (5, "start: GET WINDOW\n"); status = get_window (s->fd, &wp, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (5, "xres=%d\n", (wp.wdb.x_res[0] << 8) + wp.wdb.x_res[1]); DBG (5, "yres=%d\n", (wp.wdb.y_res[0] << 8) + wp.wdb.y_res[1]); DBG (5, "ulx=%d\n", (wp.wdb.x_ul[0] << 24) + (wp.wdb.x_ul[1] << 16) + (wp.wdb.x_ul[2] << 8) + wp.wdb.x_ul[3]); DBG (5, "uly=%d\n", (wp.wdb.y_ul[0] << 24) + (wp.wdb.y_ul[1] << 16) + (wp.wdb.y_ul[2] << 8) + wp.wdb.y_ul[3]); DBG (5, "width=%d\n", (wp.wdb.width[0] << 24) + (wp.wdb.width[1] << 16) + (wp.wdb.width[2] << 8) + wp.wdb.width[3]); DBG (5, "length=%d\n", (wp.wdb.length[0] << 24) + (wp.wdb.length[1] << 16) + (wp.wdb.length[2] << 8) + wp.wdb.length[3]); if (s->adf_scan) { status = object_position(s->fd, LOAD_PAPER); if (status != SANE_STATUS_GOOD) { sanei_scsi_close (s->fd); s->fd = -1; s->busy = SANE_FALSE; s->cancel = SANE_FALSE; return (status); } } DBG (5, "start: SCAN\n"); s->scanning = SANE_TRUE; s->busy = SANE_TRUE; s->cancel = SANE_FALSE; s->get_params_called = 0; wait_ready(s->fd); status = scan (s->fd); #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: scan started %li.%06li\n", t.tv_sec, t.tv_usec); } #endif if (status != SANE_STATUS_GOOD) { DBG (1, "start of scan failed: %s\n", sane_strstatus (status)); do_cancel(s); return (status); } /* ask the scanner for the scan size */ /* wait_ready(s->fd); */ #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: wait_ready ok %li.%06li\n", t.tv_sec, t.tv_usec); } #endif sane_get_parameters(s, 0); #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: get_params ok %li.%06li\n", t.tv_sec, t.tv_usec); } #endif if (strcmp (mode, M_LINEART_COLOR) != 0) s->bytes_to_read = s->params.bytes_per_line * s->params.lines; else { s->bytes_to_read = (s->params.pixels_per_line+7) / 8; s->bytes_to_read *= 3 * s->params.lines; } #ifdef USE_FORK { size_t i; for (i = 0; i < s->dev->info.buffers; i++) s->rdr_ctl->buf_ctl[i].shm_status = SHM_EMPTY; s->read_buff = 0; s->rdr_ctl->cancel = 0; s->rdr_ctl->running = 0; s->rdr_ctl->status = SANE_STATUS_GOOD; } s->reader_pid = fork(); #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: forked %li.%06li %i\n", t.tv_sec, t.tv_usec, s->reader_pid); } #endif if (s->reader_pid == 0) { sigset_t ignore_set; struct SIGACTION act; sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); /* don't use exit() since that would run the atexit() handlers... */ _exit (reader_process (s)); } else if (s->reader_pid == -1) { s->busy = SANE_FALSE; do_cancel(s); return SANE_STATUS_NO_MEM; } #endif /* USE_FORK */ DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_X_RESOLUTION].w); s->busy = SANE_FALSE; s->buf_used = 0; s->buf_pos = 0; if (s->cancel == SANE_TRUE) { do_cancel(s); DBG (10, ">>\n"); return(SANE_STATUS_CANCELLED); } DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } static SANE_Status sane_read_direct (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, SANE_Int * len) { SHARP_Scanner *s = handle; SANE_Status status; size_t nread; DBG (10, "<< sane_read_direct "); DBG (20, "remaining: %lu ", (u_long) s->bytes_to_read); *len = 0; if (s->bytes_to_read == 0) { do_cancel (s); return (SANE_STATUS_EOF); } if (!s->scanning) return (do_cancel (s)); nread = max_len; if (nread > s->bytes_to_read) nread = s->bytes_to_read; if (nread > s->dev->info.bufsize) nread = s->dev->info.bufsize; #ifdef USE_FORK status = read_data(s, dst_buf, &nread); #else wait_ready(s->fd); status = read_data (s, dst_buf, &nread); #endif if (status != SANE_STATUS_GOOD) { do_cancel (s); return (SANE_STATUS_IO_ERROR); } *len = nread; s->bytes_to_read -= nread; DBG (20, "remaining: %lu ", (u_long) s->bytes_to_read); DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } static SANE_Status sane_read_shuffled (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, SANE_Int * len, int eight_bit_data) { SHARP_Scanner *s = handle; SANE_Status status; SANE_Byte *dest, *red, *green, *blue, mask; SANE_Int transfer; size_t nread, ntest, pixel, max_pixel, line, max_line; size_t start_input, bytes_per_line_in; DBG (10, "<< sane_read_shuffled "); *len = 0; if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used) { do_cancel (s); DBG (10, ">>\n"); return (SANE_STATUS_EOF); } if (!s->scanning) { DBG (10, ">>\n"); return(do_cancel(s)); } if (s->buf_pos < s->buf_used) { transfer = s->buf_used - s->buf_pos; if (transfer > max_len) transfer = max_len; memcpy(dst_buf, &(s->buffer[s->buf_pos]), transfer); s->buf_pos += transfer; max_len -= transfer; *len = transfer; } while (max_len > 0 && s->bytes_to_read > 0) { if (eight_bit_data) { nread = s->dev->info.bufsize / s->params.bytes_per_line - 1; nread *= s->params.bytes_per_line; if (nread > s->bytes_to_read) nread = s->bytes_to_read; max_line = nread / s->params.bytes_per_line; start_input = s->params.bytes_per_line; bytes_per_line_in = s->params.bytes_per_line; } else { bytes_per_line_in = (s->params.pixels_per_line + 7) / 8; bytes_per_line_in *= 3; max_line = s->params.bytes_per_line + bytes_per_line_in; max_line = s->dev->info.bufsize / max_line; nread = max_line * bytes_per_line_in; if (nread > s->bytes_to_read) { nread = s->bytes_to_read; max_line = nread / bytes_per_line_in; } start_input = s->dev->info.bufsize - nread; } ntest = nread; #ifdef USE_FORK status = read_data (s, &(s->buffer[start_input]), &nread); #else wait_ready(s->fd); status = read_data (s, &(s->buffer[start_input]), &nread); #endif if (status != SANE_STATUS_GOOD) { do_cancel (s); DBG (10, ">>\n"); return (SANE_STATUS_IO_ERROR); } if (nread != ntest) { /* if this happens, something is wrong in the input buffer management... */ DBG(1, "Warning: could not read an integral number of scan lines\n"); DBG(1, " image will be scrambled\n"); } s->buf_used = max_line * s->params.bytes_per_line; s->buf_pos = 0; s->bytes_to_read -= nread; dest = s->buffer; max_pixel = s->params.pixels_per_line; if (eight_bit_data) for (line = 1; line <= max_line; line++) { red = &(s->buffer[line * s->params.bytes_per_line]); green = &(red[max_pixel]); blue = &(green[max_pixel]); for (pixel = 0; pixel < max_pixel; pixel++) { *dest++ = *red++; *dest++ = *green++; *dest++ = *blue++; } } else for (line = 0; line < max_line; line++) { red = &(s->buffer[start_input + line * bytes_per_line_in]); green = &(red[(max_pixel+7)/8]); blue = &(green[(max_pixel+7)/8]); mask = 0x80; for (pixel = 0; pixel < max_pixel; pixel++) { *dest++ = (*red & mask) ? 0xff : 0; *dest++ = (*green & mask) ? 0xff : 0; *dest++ = (*blue & mask) ? 0xff : 0; mask = mask >> 1; if (mask == 0) { mask = 0x80; red++; green++; blue++; } } } transfer = max_len; if (transfer > s->buf_used) transfer = s->buf_used; memcpy(&(dst_buf[*len]), s->buffer, transfer); max_len -= transfer; s->buf_pos += transfer; *len += transfer; } if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used) do_cancel (s); DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, SANE_Int * len) { SHARP_Scanner *s = handle; SANE_Status status; s->busy = SANE_TRUE; if (s->cancel == SANE_TRUE) { do_cancel(s); *len = 0; return (SANE_STATUS_CANCELLED); } /* RGB scans with a JX 250 and bi-level color scans must be handled differently: */ if (s->image_composition <= 2) status = sane_read_direct(handle, dst_buf, max_len, len); else if (s->image_composition <= 4) status = sane_read_shuffled(handle, dst_buf, max_len, len, 0); else if (s->dev->sensedat.model != JX250 && s->dev->sensedat.model != JX350 ) status = sane_read_direct(handle, dst_buf, max_len, len); else status = sane_read_shuffled(handle, dst_buf, max_len, len, 1); s->busy = SANE_FALSE; if (s->cancel == SANE_TRUE) { do_cancel(s); return (SANE_STATUS_CANCELLED); } return (status); } void sane_cancel (SANE_Handle handle) { SHARP_Scanner *s = handle; DBG (10, "<< sane_cancel "); s->cancel = SANE_TRUE; if (s->busy == SANE_FALSE) do_cancel(s); DBG (10, ">>\n"); } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { DBG (10, "<< sane_set_io_mode"); DBG (10, ">>\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { DBG (10, "<< sane_get_select_fd"); DBG (10, ">>\n"); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/kvs40xx.h0000664000175000017500000001454612775312261014331 00000000000000#ifndef __KVS40XX_H #define __KVS40XX_H /* Copyright (C) 2009, Panasonic Russia Ltd. */ /* Panasonic KV-S40xx USB-SCSI scanner driver. */ #include "../include/sane/config.h" #include #ifdef HAVE_SYS_TYPES_H #include #endif #undef BACKEND_NAME #define BACKEND_NAME kvs40xx #define DBG_ERR 1 #define DBG_WARN 2 #define DBG_MSG 3 #define DBG_INFO 4 #define DBG_DBG 5 #define PANASONIC_ID 0x04da #define KV_S4085C 0x100c #define KV_S4065C 0x100d #define KV_S7075C 0x100e #define KV_S4085CL (KV_S4085C|0x10000) #define KV_S4085CW (KV_S4085C|0x20000) #define KV_S4065CL (KV_S4065C|0x10000) #define KV_S4065CW (KV_S4065C|0x20000) #define USB 1 #define SCSI 2 #define BULK_HEADER_SIZE 12 #define MAX_READ_DATA_SIZE (0x10000-0x100) #define BUF_SIZE MAX_READ_DATA_SIZE #define INCORRECT_LENGTH 0xfafafafa typedef unsigned char u8; typedef unsigned u32; typedef unsigned short u16; #define SIDE_FRONT 0x00 #define SIDE_BACK 0x80 /* options */ typedef enum { NUM_OPTS = 0, /* General options */ MODE_GROUP, MODE, /* scanner modes */ RESOLUTION, /* X and Y resolution */ SOURCE, DUPLEX, /* Duplex mode */ FEEDER_MODE, /* Feeder mode, fixed to Continous */ LENGTHCTL, /* Length control mode */ LONG_PAPER, MANUALFEED, /* Manual feed mode */ FEED_TIMEOUT, /* Feed timeout */ DBLFEED, /* Double feed detection mode */ DFEED_SENCE, DFSTOP, DFEED_L, DFEED_C, DFEED_R, STAPELED_DOC, /* Detect stapled document */ FIT_TO_PAGE, /* Scanner shrinks image to fit scanned page */ /* Geometry group */ GEOMETRY_GROUP, PAPER_SIZE, /* Paper size */ LANDSCAPE, /* true if landscape */ TL_X, /* upper left X */ TL_Y, /* upper left Y */ BR_X, /* bottom right X */ BR_Y, /* bottom right Y */ ADVANCED_GROUP, BRIGHTNESS, /* Brightness */ CONTRAST, /* Contrast */ THRESHOLD, /* Binary threshold */ AUTOMATIC_THRESHOLD, WHITE_LEVEL, NOISE_REDUCTION, INVERSE, /* Monochrome reversing */ IMAGE_EMPHASIS, /* Image emphasis */ GAMMA_CORRECTION, /* Gamma correction */ LAMP, /* Lamp -- color drop out */ RED_CHROMA, BLUE_CHROMA, HALFTONE_PATTERN, /* Halftone pattern */ COMPRESSION, /* JPEG Compression */ COMPRESSION_PAR, /* Compression parameter */ DESKEW, STOP_SKEW, CROP, MIRROR, BTMPOS, TOPPOS, /* must come last: */ NUM_OPTIONS } KV_OPTION; struct buf { u8 **buf; volatile int head; volatile int tail; volatile unsigned size; volatile int sem; volatile SANE_Status st; pthread_mutex_t mu; pthread_cond_t cond; }; struct scanner { char name[128]; unsigned id; volatile int scanning; int page; int side; int bus; SANE_Int file; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; u8 *buffer; struct buf buf[2]; u8 *data; unsigned side_size; unsigned read; pthread_t thread; }; struct window { u8 reserved[6]; u8 window_descriptor_block_length[2]; u8 window_identifier; u8 reserved2; u8 x_resolution[2]; u8 y_resolution[2]; u8 upper_left_x[4]; u8 upper_left_y[4]; u8 width[4]; u8 length[4]; u8 brightness; u8 threshold; u8 contrast; u8 image_composition; u8 bit_per_pixel; u8 halftone_pattern[2]; u8 rif_padding; /*RIF*/ u8 bit_ordering[2]; u8 compression_type; u8 compression_argument; u8 reserved4[6]; u8 vendor_unique_identifier; u8 nobuf_fstspeed_dfstop; u8 mirror_image; u8 image_emphasis; u8 gamma_correction; u8 mcd_lamp_dfeed_sens; u8 reserved5; /*rmoir*/ u8 document_size; u8 document_width[4]; u8 document_length[4]; u8 ahead_deskew_dfeed_scan_area_fspeed_rshad; u8 continuous_scanning_pages; u8 automatic_threshold_mode; u8 automatic_separation_mode; u8 standard_white_level_mode; u8 b_wnr_noise_reduction; u8 mfeed_toppos_btmpos_dsepa_hsepa_dcont_rstkr; u8 stop_mode; u8 red_chroma; u8 blue_chroma; }; struct support_info { /*TODO: */ unsigned char data[32]; }; void kvs40xx_init_options (struct scanner *); SANE_Status kvs40xx_test_unit_ready (struct scanner *s); SANE_Status kvs40xx_set_timeout (struct scanner *s, int timeout); void kvs40xx_init_window (struct scanner *s, struct window *wnd, int wnd_id); SANE_Status kvs40xx_set_window (struct scanner *s, int wnd_id); SANE_Status kvs40xx_reset_window (struct scanner *s); SANE_Status kvs40xx_read_picture_element (struct scanner *s, unsigned side, SANE_Parameters * p); SANE_Status read_support_info (struct scanner *s, struct support_info *inf); SANE_Status kvs40xx_read_image_data (struct scanner *s, unsigned page, unsigned side, void *buf, unsigned max_size, unsigned *size); SANE_Status kvs40xx_document_exist (struct scanner *s); SANE_Status get_buffer_status (struct scanner *s, unsigned *data_avalible); SANE_Status kvs40xx_scan (struct scanner *s); SANE_Status kvs40xx_sense_handler (int fd, u_char * sense_buffer, void *arg); SANE_Status stop_adf (struct scanner *s); SANE_Status hopper_down (struct scanner *s); SANE_Status inquiry (struct scanner *s, char *id); static inline u16 swap_bytes16 (u16 x) { return x << 8 | x >> 8; } static inline u32 swap_bytes32 (u32 x) { return x << 24 | x >> 24 | (x & (u32) 0x0000ff00UL) << 8 | (x & (u32) 0x00ff0000UL) >> 8; } static inline void copy16 (u8 * p, u16 x) { memcpy (p, (u8 *) &x, sizeof (x)); } static inline void copy32 (u8 * p, u32 x) { memcpy (p, (u8 *) &x, sizeof (x)); } #if WORDS_BIGENDIAN static inline void set24 (u8 * p, u32 x) { p[2] = x >> 16; p[1] = x >> 8; p[0] = x >> 0; } #define cpu2be16(x) (x) #define cpu2be32(x) (x) #define cpu2le16(x) swap_bytes16(x) #define cpu2le32(x) swap_bytes32(x) #define le2cpu16(x) swap_bytes16(x) #define le2cpu32(x) swap_bytes32(x) #define be2cpu16(x) (x) #define be2cpu32(x) (x) #define BIT_ORDERING 0 #elif __BYTE_ORDER == __LITTLE_ENDIAN static inline void set24 (u8 * p, u32 x) { p[0] = x >> 16; p[1] = x >> 8; p[2] = x >> 0; } #define cpu2le16(x) (x) #define cpu2le32(x) (x) #define cpu2be16(x) swap_bytes16(x) #define cpu2be32(x) swap_bytes32(x) #define le2cpu16(x) (x) #define le2cpu32(x) (x) #define be2cpu16(x) swap_bytes16(x) #define be2cpu32(x) swap_bytes32(x) #define BIT_ORDERING 1 #else #error __BYTE_ORDER not defined #endif static inline u32 get24 (u8 * p) { u32 x = (((u32) p[0]) << 16) | (((u32) p[1]) << 8) | (((u32) p[0]) << 0); return x; } #endif /*__KVS40XX_H*/ sane-backends-1.0.27/backend/stv680.h0000664000175000017500000002371712775312261014054 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2004 -2006 Gerard Klaver (gerard at gkall dot hobby dot nl) The teco2 and gl646 backend (Frank Zago) are used as a template for this backend. For the usb commands and bayer decoding parts of the following program are used: The pencam2 program (GNU GPL license 2) For the usb commands parts of the following programs are used: The libgphoto2 (camlib stv0680) (GNU GPL license 2) The stv680.c/.h kernel module (GNU GPL license 2) For the stv680_add_text routine the add_text routine and font_6x11.h file are taken from the webcam.c file, part of xawtv program, (c) 1998-2002 Gerd Knorr (GNU GPL license 2). This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --------------------------------------------------------------------- */ /* $Id$ update 20-04-2006*/ /* Commands supported by the vidcam. */ /*--------------------------------------------------------------------------*/ static inline int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /*--------------------------------------------------------------------------*/ #include #define LIBUSB_TIMEOUT 1000 /* ms */ typedef unsigned char byte; /*--------------------------------------------------------------------------*/ /* Black magic for color adjustment. */ struct dpi_color_adjust { int resolution_x; /* x-resolution */ int resolution_y; /* y-resolution */ int z1_color_0; /* 0, 1 or 2 */ int z1_color_1; /* idem */ int z1_color_2; /* idem */ }; /*--------------------------------------------------------------------------*/ enum Stv680_Option { /* Must come first */ OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* vidcam modes */ OPT_RESOLUTION, /* X and Y resolution */ OPT_BRIGHTNESS, /* brightness */ OPT_ENHANCEMENT_GROUP, OPT_WHITE_LEVEL_R, /*white level red correction */ OPT_WHITE_LEVEL_G, /*white level green correction */ OPT_WHITE_LEVEL_B, /*white level blue correction */ /* must come last: */ OPT_NUM_OPTIONS }; /*--------------------------------------------------------------------------*/ /* * Video Camera supported by this backend. */ struct vidcam_hardware { /* USB stuff */ SANE_Word vendor; SANE_Word product; SANE_Word class; /* Readable names */ const char *vendor_name; /* brand on the box */ const char *product_name; /* name on the box */ /* Resolutions supported in color mode. */ const struct dpi_color_adjust *color_adjust; }; #define COLOR_RAW_STR SANE_I18N("Color RAW") #define COLOR_RGB_STR SANE_I18N("Color RGB") #define COLOR_RGB_TEXT_STR SANE_I18N("Color RGB TEXT") /*--------------------------------------------------------------------------*/ /* Define a vidcam occurence. */ typedef struct Stv680_Vidcam { struct Stv680_Vidcam *next; SANE_Device sane; char *devicename; SANE_Int fd; /* device handle */ /* USB handling */ size_t buffer_size; /* size of the buffer */ SANE_Byte *buffer; /* for USB transfer. */ /* Bayer handling */ size_t output_size; /* size of the output */ SANE_Byte *output; /* for bayer conversion */ size_t image_size; /* allocated size of image */ size_t image_begin; /* first significant byte in image */ size_t image_end; /* first free byte in image */ SANE_Byte *image; /* keep the raw image here */ /* USB control messages handling */ size_t windoww_size; /* size of window write */ size_t windowr_size; /* size of window read */ SANE_Byte *windoww; /* for window write */ SANE_Byte *windowr; /* for window read */ /* Scanner infos. */ const struct vidcam_hardware *hw; /* default options for that vidcam */ SANE_Word *resolutions_list; SANE_Word *color_sequence_list; /* Scanning handling. */ SANE_Bool scanning; /* TRUE if a scan is running. */ SANE_Bool deliver_eof; int x_resolution; /* X resolution */ int y_resolution; /* Y resolution */ int depth; /* depth per color */ unsigned int colour; int red_s; int green_s; int blue_s; SANE_Parameters s_params; enum { STV680_COLOR_RGB, STV680_COLOR_RGB_TEXT, STV680_COLOR, STV680_COLOR_RAW } scan_mode; size_t bytes_left; /* number of bytes left to give to the backend */ size_t real_bytes_left; /* number of bytes left the vidcam will return. */ int bytes_pixel; const struct dpi_color_adjust *color_adjust; SANE_Parameters params; /* Options */ SANE_Option_Descriptor opt[OPT_NUM_OPTIONS]; Option_Value val[OPT_NUM_OPTIONS]; unsigned int video_mode; /* 0x0100 = VGA, 0x0000 = CIF, * 0x0300 = QVGA, 0x0200 = QCIF*/ unsigned int video_status; /* 0x01=start, 0x02=video, 0x04=busy, 0x08=idle */ int SupportedModes; int HardwareConfig; int QSIF; int CIF; int VGA; int QVGA; int QCIF; int cwidth; /* camera width */ int cheight; int subsample; int framecount; char picmsg_ps[50]; } Stv680_Vidcam; /*--------------------------------------------------------------------------*/ /* Debug levels. * Should be common to all backends. */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /*--------------------------------------------------------*/ static SANE_Byte red_g[256] = { 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42, 44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69, 71, 71, 73, 75, 77, 78, 80, 81, 82, 84, 85, 87, 88, 89, 90, 91, 93, 94, 95, 97, 98, 98, 99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 143, 143, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151, 152, 152, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159, 159, 160, 161, 161, 161, 162, 163, 163, 164, 165, 165, 166, 167, 167, 168, 168, 169, 170, 170, 170, 171, 171, 172, 173, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 179, 179, 180, 180, 181, 181, 182, 183, 183, 184, 184, 185, 185, 186, 187, 187, 188, 188, 188, 188, 189, 190, 190, 191, 191, 192, 192, 193, 193, 194, 195, 195, 196, 196, 197, 197, 197, 197, 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 206, 206, 206, 207, 207, 208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, 215, 215, 215, 216, 216, 217, 217, 218, 218, 218, 219, 219, 220, 220, 221, 221 }; static SANE_Byte green_g[256] = { 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47, 50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77, 79, 80, 82, 84, 86, 87, 89, 91, 92, 94, 95, 97, 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 111, 113, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 172, 173, 174, 175, 175, 176, 177, 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185, 186, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244, 245, 245, 246, 246 }; static SANE_Byte blue_g[256] = { 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51, 55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84, 86, 88, 90, 92, 94, 95, 97, 100, 101, 103, 104, 106, 107, 110, 111, 112, 114, 115, 116, 118, 119, 121, 122, 124, 125, 126, 127, 128, 129, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, 165, 166, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 176, 176, 177, 178, 179, 180, 180, 181, 182, 183, 183, 184, 185, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 194, 195, 196, 196, 198, 199, 200, 200, 201, 202, 202, 203, 204, 204, 205, 205, 206, 207, 207, 209, 210, 210, 211, 212, 212, 213, 213, 214, 215, 215, 216, 217, 217, 218, 218, 220, 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 228, 228, 229, 229, 231, 231, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 238, 238, 239, 239, 240, 240, 242, 242, 243, 243, 244, 244, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; sane-backends-1.0.27/backend/umax-uc630.c0000664000175000017500000001026012775312261014572 00000000000000/* ------------------------------------------------------------------------- */ /* umax-uc630.c: inquiry for UMAX scanner uc630 (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------- */ #include "umax-scanner.h" /* ------------------------------------------------------------------------- */ static unsigned char UC630_INQUIRY[] = { #define UC630_INQUIRY_LEN 0x94 /* 24 F/W support function */ 0x00, /* ? */ /* 25 -27 exposure-times */ 0x00, 0x00, 0x00, /* 28 - 29 reserved */ 0x00, 0x00, /* 2a - 35 exposure times */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 37 reserved */ 0x00, 0x00, /* 38 - 5f scsi reserved */ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, /* 60 -62 scanner capability */ 0xfd, 0x80, 0x03, /* 63 reserved */ 0x00, /* 64 gamma */ 0x00, /* 65 reserved */ 0x00, /* 66 GIB */ 0x01, /* 67 reserved */ 0x00, /* 68 GOB */ 0x01, /* 69 - 6a halftone */ 0x08, 0x2f, /* 6b - 6c reserved */ 0x00, 0x00, /* 6d color sequence */ 0xe5, /* 6e - 71 video memory */ 0x00, 0x04, 0x00, 0x00, /* 72 reserved */ 0x00, /* 73 max optical res in 100 dpi */ 0x03, /* 74 max x_res in 100 dpi */ 0x03, /* 75 max y_res in 100 dpi */ 0x06, /* 76-77 fb max scan width in 0.01 inch */ 0x03, 0x52, /* 78-79 fb max scan length in 0.01 inch */ 0x04, 0x9c, /* 7a-7b uta x original point, may be 0x05, 0x89 */ 0x00, 0x76, /* 7c-7d uta y original point, may be 0x06, 0x75 */ 0x00, 0x89, /* 7e-7f uta max scan width in 0.01 inch */ 0x02, 0x4e, /* 80-81 uta max scan length in 0.01 inch */ 0x03, 0x65, /* 82-85 reserved */ 00, 00, 00, 00, /* 86-87 dor x original point */ 0x00, 0x00, /* 88-89 dor x original point */ 0x00, 0x00, /* 8a-8b dor max scan width in 0.01 inch */ 0x00, 0x00, /* 8c-8d dor max scan length in 0.01 inch */ 0x00, 0x00, /* 8e reserved */ 0x00, /* 8f last calibration lamp density */ 0x00, /* 90 reserved */ 0x00, /* 91 lamp warmup max time */ 0x00, /* 92-93 window descriptor block length */ 0x00, 0x31, /* 94 optical resolution residue (1dpi) */ 0x00, /* 95 x_resolution residue (1dpi) */ 0x00, /* 96 y_resolution residue (1dpi) */ 0x00, /* 97 analog gamma table */ 0x00, /* 98-99 reserved */ 0x00, 0x00, /* 9a max calibration data lines */ 0x00 }; static inquiry_blk inquiry_uc630 = { "UC630 ", UC630_INQUIRY, UC630_INQUIRY_LEN }; sane-backends-1.0.27/backend/test.h0000664000175000017500000000746512112021330013736 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002-2006 Henning Meier-Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This backend is for testing frontends. */ #ifndef test_h #define test_h typedef enum { param_none = 0, param_bool, param_int, param_fixed, param_string } parameter_type; typedef enum { opt_num_opts = 0, opt_mode_group, opt_mode, opt_depth, opt_hand_scanner, opt_three_pass, /* 5 */ opt_three_pass_order, opt_resolution, opt_scan_source, opt_special_group, opt_test_picture, opt_invert_endianess, opt_read_limit, opt_read_limit_size, opt_read_delay, opt_read_delay_duration, opt_read_status_code, opt_ppl_loss, opt_fuzzy_parameters, opt_non_blocking, opt_select_fd, opt_enable_test_options, opt_print_options, opt_geometry_group, opt_tl_x, opt_tl_y, opt_br_x, opt_br_y, opt_bool_group, opt_bool_soft_select_soft_detect, opt_bool_hard_select_soft_detect, opt_bool_hard_select, opt_bool_soft_detect, opt_bool_soft_select_soft_detect_emulated, opt_bool_soft_select_soft_detect_auto, opt_int_group, opt_int, opt_int_constraint_range, opt_int_constraint_word_list, opt_int_array, opt_int_array_constraint_range, opt_int_array_constraint_word_list, opt_fixed_group, opt_fixed, opt_fixed_constraint_range, opt_fixed_constraint_word_list, opt_string_group, opt_string, opt_string_constraint_string_list, opt_string_constraint_long_string_list, opt_button_group, opt_button, /* must come last: */ num_options } test_opts; typedef struct Test_Device { struct Test_Device *next; SANE_Device sane; SANE_Option_Descriptor opt[num_options]; Option_Value val[num_options]; SANE_Bool loaded[num_options]; SANE_Parameters params; SANE_String name; SANE_Pid reader_pid; SANE_Int reader_fds; SANE_Int pipe; FILE *pipe_handle; SANE_Word pass; SANE_Word bytes_per_line; SANE_Word pixels_per_line; SANE_Word lines; SANE_Int bytes_total; SANE_Bool open; SANE_Bool scanning; SANE_Bool cancelled; SANE_Bool eof; SANE_Int number_of_scans; } Test_Device; #endif /* test_h */ sane-backends-1.0.27/backend/pixma_mp150.c0000664000175000017500000017157213106201017015021 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2007-2009 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* test cases 1. short USB packet (must be no -ETIMEDOUT) 2. cancel using button on the printer (look for abort command) 3. start scan while busy (status 0x1414) 4. cancel using ctrl-c (must send abort command) */ #define TPU_48 /* uncomment to activate TPU scan at 48 bits */ /*#define DEBUG_TPU_48*/ /* uncomment to debug 48 bits TPU on a non TPU device */ /*#define DEBUG_TPU_24*/ /* uncomment to debug 24 bits TPU on a non TPU device */ #include "../include/sane/config.h" #include #include #include #include /* localtime(C90) */ #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" /* Some macro code to enhance readability */ #define RET_IF_ERR(x) do { \ if ((error = (x)) < 0) \ return error; \ } while(0) #define WAIT_INTERRUPT(x) do { \ error = handle_interrupt (s, x); \ if (s->cancel) \ return PIXMA_ECANCELED; \ if (error != PIXMA_ECANCELED && error < 0) \ return error; \ } while(0) #ifdef __GNUC__ # define UNUSED(v) (void) v #else # define UNUSED(v) #endif /* Size of the command buffer should be multiple of wMaxPacketLength and greater than 4096+24. 4096 = size of gamma table. 24 = header + checksum */ #define IMAGE_BLOCK_SIZE (512*1024) #define CMDBUF_SIZE (4096 + 24) #define DEFAULT_GAMMA 2.0 /***** Gamma different from 1.0 is potentially impacting color profile generation *****/ #define UNKNOWN_PID 0xffff #define CANON_VID 0x04a9 /* Generation 1 */ #define MP150_PID 0x1709 #define MP170_PID 0x170a #define MP450_PID 0x170b #define MP500_PID 0x170c #define MP530_PID 0x1712 #define MP800_PID 0x170d #define MP800R_PID 0x170e #define MP830_PID 0x1713 /* Generation 2 */ #define MP160_PID 0x1714 #define MP180_PID 0x1715 #define MP460_PID 0x1716 #define MP510_PID 0x1717 #define MP600_PID 0x1718 #define MP600R_PID 0x1719 #define MP140_PID 0x172b /* Generation 3 */ /* PIXMA 2007 vintage */ #define MX7600_PID 0x171c #define MP210_PID 0x1721 #define MP220_PID 0x1722 #define MP470_PID 0x1723 #define MP520_PID 0x1724 #define MP610_PID 0x1725 #define MX300_PID 0x1727 #define MX310_PID 0x1728 #define MX700_PID 0x1729 #define MX850_PID 0x172c /* PIXMA 2008 vintage */ #define MP630_PID 0x172e #define MP620_PID 0x172f #define MP540_PID 0x1730 #define MP480_PID 0x1731 #define MP240_PID 0x1732 #define MP260_PID 0x1733 #define MP190_PID 0x1734 /* PIXMA 2009 vintage */ #define MX860_PID 0x1735 #define MX320_PID 0x1736 /* untested */ #define MX330_PID 0x1737 /* Generation 4 */ #define MP250_PID 0x173a #define MP270_PID 0x173b #define MP490_PID 0x173c #define MP550_PID 0x173d #define MP560_PID 0x173e #define MP640_PID 0x173f /* PIXMA 2010 vintage */ #define MX340_PID 0x1741 #define MX350_PID 0x1742 #define MX870_PID 0x1743 /* 2010 new devices (untested) */ #define MP280_PID 0x1746 #define MP495_PID 0x1747 #define MG5100_PID 0x1748 #define MG5200_PID 0x1749 #define MG6100_PID 0x174a /* PIXMA 2011 vintage */ #define MX360_PID 0x174d #define MX410_PID 0x174e #define MX420_PID 0x174f #define MX880_PID 0x1750 /* 2011 new devices (untested) */ #define MG2100_PID 0x1751 #define MG3100_PID 0x1752 #define MG4100_PID 0x1753 #define MG5300_PID 0x1754 #define MG6200_PID 0x1755 #define MP493_PID 0x1757 #define E500_PID 0x1758 /* 2012 new devices (untested) */ #define MX370_PID 0x1759 #define MX430_PID 0x175B #define MX510_PID 0x175C #define MX710_PID 0x175D #define MX890_PID 0x175E #define E600_PID 0x175A #define MG4200_PID 0x1763 /* 2013 new devices */ #define MP230_PID 0x175F #define MG6300_PID 0x1765 /* 2013 new devices (untested) */ #define MG2200_PID 0x1760 #define E510_PID 0x1761 #define MG3200_PID 0x1762 #define MG5400_PID 0x1764 #define MX390_PID 0x1766 #define E610_PID 0x1767 #define MX450_PID 0x1768 #define MX520_PID 0x1769 #define MX720_PID 0x176a #define MX920_PID 0x176b #define MG2400_PID 0x176c #define MG2500_PID 0x176d #define MG3500_PID 0x176e #define MG6500_PID 0x176f #define MG6400_PID 0x1770 #define MG5500_PID 0x1771 #define MG7100_PID 0x1772 /* 2014 new devices (untested) */ #define MX470_PID 0x1774 #define MX530_PID 0x1775 #define MB5000_PID 0x1776 #define MB5300_PID 0x1777 #define MB2000_PID 0x1778 #define MB2300_PID 0x1779 #define E400_PID 0x177a #define E560_PID 0x177b #define MG7500_PID 0x177c #define MG6600_PID 0x177e #define MG5600_PID 0x177f #define MG2900_PID 0x1780 #define E460_PID 0x1788 /* 2015 new devices (untested) */ #define MX490_PID 0x1787 #define E480_PID 0x1789 #define MG3600_PID 0x178a #define MG7700_PID 0x178b #define MG6900_PID 0x178c #define MG6800_PID 0x178d #define MG5700_PID 0x178e /* 2016 new devices (untested) */ #define TS9000_PID 0x179f #define TS8000_PID 0x1800 #define TS6000_PID 0x1801 #define TS5000_PID 0x1802 #define MG3000_PID 0x180b #define E470_PID 0x180c #define G3000_PID 0x181d /* Generation 4 XML messages that encapsulates the Pixma protocol messages */ #define XML_START_1 \ "\ \ StartJob\ 00000001\ 1" #define XML_START_2 \ "\ \ VendorCmd\ 00000001\ ModeShift1\ " #define XML_END \ "\ \ EndJob\ 00000001\ " #define XML_OK "OK" enum mp150_state_t { state_idle, state_warmup, state_scanning, state_transfering, state_finished }; enum mp150_cmd_t { cmd_start_session = 0xdb20, cmd_select_source = 0xdd20, cmd_gamma = 0xee20, cmd_scan_param = 0xde20, cmd_status = 0xf320, cmd_abort_session = 0xef20, cmd_time = 0xeb80, cmd_read_image = 0xd420, cmd_error_info = 0xff20, cmd_start_calibrate_ccd_3 = 0xd520, cmd_end_calibrate_ccd_3 = 0xd720, cmd_scan_param_3 = 0xd820, cmd_scan_start_3 = 0xd920, cmd_status_3 = 0xda20, cmd_get_tpu_info_3 = 0xf520, cmd_set_tpu_info_3 = 0xea20, cmd_e920 = 0xe920 /* seen in MP800 */ }; typedef struct mp150_t { enum mp150_state_t state; pixma_cmdbuf_t cb; uint8_t *imgbuf; uint8_t current_status[16]; unsigned last_block; uint8_t generation; /* for Generation 3 and CCD shift */ uint8_t *linebuf; uint8_t *data_left_ofs; unsigned data_left_len; int shift[3]; unsigned color_shift; unsigned stripe_shift; uint8_t tpu_datalen; uint8_t tpu_data[0x40]; uint8_t adf_state; /* handle adf scanning */ } mp150_t; /* STAT: 0x0606 = ok, 0x1515 = failed (PIXMA_ECANCELED), 0x1414 = busy (PIXMA_EBUSY) Transaction scheme 1. command_header/data | result_header 2. command_header | result_header/data 3. command_header | result_header/image_data - data has checksum in the last byte. - image_data has no checksum. - data and image_data begins in the same USB packet as command_header or result_header. command format #1: u16be cmd u8[6] 0 u8[4] 0 u32be PLEN parameter length u8[PLEN-1] parameter u8 parameter check sum result: u16be STAT u8 0 u8 0 or 0x21 if STAT == 0x1414 u8[4] 0 command format #2: u16be cmd u8[6] 0 u8[4] 0 u32be RLEN result length result: u16be STAT u8[6] 0 u8[RLEN-1] result u8 result check sum command format #3: (only used by read_image_block) u16be 0xd420 u8[6] 0 u8[4] 0 u32be max. block size + 8 result: u16be STAT u8[6] 0 u8 block info bitfield: 0x8 = end of scan, 0x10 = no more paper, 0x20 = no more data u8[3] 0 u32be ILEN image data size u8[ILEN] image data */ static void mp150_finish_scan (pixma_t * s); static int is_scanning_from_adf (pixma_t * s) { return (s->param->source == PIXMA_SOURCE_ADF || s->param->source == PIXMA_SOURCE_ADFDUP); } static int is_scanning_from_adfdup (pixma_t * s) { return (s->param->source == PIXMA_SOURCE_ADFDUP); } static int is_scanning_from_tpu (pixma_t * s) { return (s->param->source == PIXMA_SOURCE_TPU); } static int send_xml_dialog (pixma_t * s, const char * xml_message) { mp150_t *mp = (mp150_t *) s->subdriver; int datalen; datalen = pixma_cmd_transaction (s, xml_message, strlen (xml_message), mp->cb.buf, 1024); if (datalen < 0) return datalen; mp->cb.buf[datalen] = 0; PDBG (pixma_dbg (10, "XML message sent to scanner:\n%s\n", xml_message)); PDBG (pixma_dbg (10, "XML response back from scanner:\n%s\n", mp->cb.buf)); return (strcasestr ((const char *) mp->cb.buf, XML_OK) != NULL); } static void new_cmd_tpu_msg (pixma_t *s, pixma_cmdbuf_t * cb, uint16_t cmd) { pixma_newcmd (cb, cmd, 0, 0); cb->buf[3] = (is_scanning_from_tpu (s)) ? 0x01 : 0x00; } static int start_session (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; new_cmd_tpu_msg (s, &mp->cb, cmd_start_session); return pixma_exec (s, &mp->cb); } static int start_scan_3 (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; new_cmd_tpu_msg (s, &mp->cb, cmd_scan_start_3); return pixma_exec (s, &mp->cb); } static int send_cmd_start_calibrate_ccd_3 (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; pixma_newcmd (&mp->cb, cmd_start_calibrate_ccd_3, 0, 0); mp->cb.buf[3] = 0x01; return pixma_exec (s, &mp->cb); } static int is_calibrated (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; if (mp->generation >= 3) { return ((mp->current_status[0] & 0x01) == 1 || (mp->current_status[0] & 0x02) == 2); } if (mp->generation == 1) { return (mp->current_status[8] == 1); } else { return (mp->current_status[9] == 1); } } static int has_paper (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; if (is_scanning_from_adfdup (s)) return (mp->current_status[1] == 0 || mp->current_status[2] == 0); else return (mp->current_status[1] == 0); } static void drain_bulk_in (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; while (pixma_read (s->io, mp->imgbuf, IMAGE_BLOCK_SIZE) >= 0); } static int abort_session (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; mp->adf_state = state_idle; /* reset adf scanning */ return pixma_exec_short_cmd (s, &mp->cb, cmd_abort_session); } static int send_cmd_e920 (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_e920); } static int select_source (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; uint8_t *data; data = pixma_newcmd (&mp->cb, cmd_select_source, 12, 0); data[5] = ((mp->generation == 2) ? 1 : 0); switch (s->param->source) { case PIXMA_SOURCE_FLATBED: data[0] = 1; data[1] = 1; break; case PIXMA_SOURCE_ADF: data[0] = 2; data[5] = 1; data[6] = 1; break; case PIXMA_SOURCE_ADFDUP: data[0] = 2; data[5] = 3; data[6] = 3; break; case PIXMA_SOURCE_TPU: data[0] = 4; data[1] = 2; break; } return pixma_exec (s, &mp->cb); } static int send_get_tpu_info_3 (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_get_tpu_info_3, 0, 0x34); RET_IF_ERR (pixma_exec (s, &mp->cb)); memcpy (mp->tpu_data, data, 0x34); return error; } static int send_set_tpu_info (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; uint8_t *data; if (mp->tpu_datalen == 0) return 0; data = pixma_newcmd (&mp->cb, cmd_set_tpu_info_3, 0x34, 0); memcpy (data, mp->tpu_data, 0x34); return pixma_exec (s, &mp->cb); } static int send_gamma_table (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; const uint8_t *lut = s->param->gamma_table; uint8_t *data; if (mp->generation == 1) { data = pixma_newcmd (&mp->cb, cmd_gamma, 4096 + 8, 0); data[0] = (s->param->channels == 3) ? 0x10 : 0x01; pixma_set_be16 (0x1004, data + 2); if (lut) memcpy (data + 4, lut, 4096); else pixma_fill_gamma_table (DEFAULT_GAMMA, data + 4, 4096); } else { /* FIXME: Gamma table for 2nd generation: 1024 * uint16_le */ data = pixma_newcmd (&mp->cb, cmd_gamma, 2048 + 8, 0); data[0] = 0x10; pixma_set_be16 (0x0804, data + 2); if (lut) { int i; for (i = 0; i < 1024; i++) { int j = (i << 2) + (i >> 8); data[4 + 2 * i + 0] = lut[j]; data[4 + 2 * i + 1] = lut[j]; } } else { int i; pixma_fill_gamma_table (DEFAULT_GAMMA, data + 4, 2048); for (i = 0; i < 1024; i++) { int j = (i << 1) + (i >> 9); data[4 + 2 * i + 0] = data[4 + j]; data[4 + 2 * i + 1] = data[4 + j]; } } } return pixma_exec (s, &mp->cb); } static unsigned calc_raw_width (const mp150_t * mp, const pixma_scan_param_t * param) { unsigned raw_width; /* NOTE: Actually, we can send arbitary width to MP150. Lines returned are always padded to multiple of 4 or 12 pixels. Is this valid for other models, too? */ if (mp->generation >= 2) { raw_width = ALIGN_SUP (param->w + param->xs, 32); /* PDBG (pixma_dbg (4, "*calc_raw_width***** width %i extended by %i and rounded to %i *****\n", param->w, param->xs, raw_width)); */ } else if (param->channels == 1) { raw_width = ALIGN_SUP (param->w + param->xs, 12); } else { raw_width = ALIGN_SUP (param->w + param->xs, 4); } return raw_width; } static int has_ccd_sensor (pixma_t * s) { return ((s->cfg->cap & PIXMA_CAP_CCD) != 0); } static int is_ccd_grayscale (pixma_t * s) { return (has_ccd_sensor (s) && (s->param->channels == 1) && !s->param->software_lineart); } static int is_ccd_lineart (pixma_t * s) { return (has_ccd_sensor (s) && s->param->software_lineart); } /* CCD sensors don't have neither a Grayscale mode nor a Lineart mode, * but use color mode instead */ static unsigned get_cis_ccd_line_size (pixma_t * s) { return ((s->param->wx ? s->param->line_size / s->param->w * s->param->wx : s->param->line_size) * ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : 1)); } static unsigned calc_shifting (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; /* If stripes shift needed (CCD devices), how many pixels shift */ mp->stripe_shift = 0; /* If color plane shift (CCD devices), how many pixels shift */ mp->color_shift = mp->shift[0] = mp->shift[1] = mp->shift[2] = 0; switch (s->cfg->pid) { case MP800_PID: case MP800R_PID: case MP830_PID: if (s->param->xdpi == 2400) { if (is_scanning_from_tpu(s)) mp->stripe_shift = 6; else mp->stripe_shift = 3; } if (s->param->ydpi > 75) { mp->color_shift = s->param->ydpi / ((s->param->ydpi < 1200) ? 150 : 75); if (is_scanning_from_tpu (s)) mp->color_shift = s->param->ydpi / 75; /* If you're trying to decipher this color-shifting code, the following line is where the magic is revealed. */ mp->shift[1] = mp->color_shift * get_cis_ccd_line_size (s); if (is_scanning_from_adf (s)) { /* ADF */ mp->shift[0] = 0; mp->shift[2] = 2 * mp->shift[1]; } else { /* Flatbed or TPU */ mp->shift[0] = 2 * mp->shift[1]; mp->shift[2] = 0; } } break; default: /* Default, and all CIS devices */ break; } return (2 * mp->color_shift + mp->stripe_shift); } static int send_scan_param (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; uint8_t *data; unsigned raw_width = calc_raw_width (mp, s->param); unsigned h = MIN (s->param->h + calc_shifting (s), s->cfg->height * s->param->ydpi / 75); /* TPU scan does not support lineart */ if (is_scanning_from_tpu (s) && is_ccd_lineart (s)) { return PIXMA_ENOTSUP; } if (mp->generation <= 2) { /*PDBG (pixma_dbg (4, "*send_scan_param gen. 1-2 ***** Setting: xdpi=%hi ydpi=%hi x=%i y=%i w=%i ***** \n", s->param->xdpi,s->param->ydpi,(s->param->x)-(s->param->xs),s->param->y,raw_width));*/ data = pixma_newcmd (&mp->cb, cmd_scan_param, 0x30, 0); pixma_set_be16 (s->param->xdpi | 0x8000, data + 0x04); pixma_set_be16 (s->param->ydpi | 0x8000, data + 0x06); pixma_set_be32 (s->param->x, data + 0x08); if (mp->generation == 2) pixma_set_be32 (s->param->x - s->param->xs, data + 0x08); pixma_set_be32 (s->param->y, data + 0x0c); pixma_set_be32 (raw_width, data + 0x10); pixma_set_be32 (h, data + 0x14); data[0x18] = ((s->param->channels != 1) || is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 0x08 : 0x04; data[0x19] = ((s->param->software_lineart) ? 8 : s->param->depth) * ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels); /* bits per pixel */ data[0x1a] = (is_scanning_from_tpu (s) ? 1 : 0); data[0x20] = 0xff; data[0x23] = 0x81; data[0x26] = 0x02; data[0x27] = 0x01; } else { data = pixma_newcmd (&mp->cb, cmd_scan_param_3, 0x38, 0); data[0x00] = (is_scanning_from_adf (s)) ? 0x02 : 0x01; data[0x01] = 0x01; if (is_scanning_from_tpu (s)) { data[0x00] = 0x04; data[0x01] = 0x02; data[0x1e] = 0x02; } data[0x02] = 0x01; if (is_scanning_from_adfdup (s)) { data[0x02] = 0x03; data[0x03] = 0x03; } data[0x05] = 0x01; /* This one also seen at 0. Don't know yet what's used for */ pixma_set_be16 (s->param->xdpi | 0x8000, data + 0x08); pixma_set_be16 (s->param->ydpi | 0x8000, data + 0x0a); /*PDBG (pixma_dbg (4, "*send_scan_param gen. 3+ ***** Setting: xdpi=%hi ydpi=%hi x=%i y=%i w=%i ***** \n", s->param->xdpi,s->param->ydpi,(s->param->x)-(s->param->xs),s->param->y,raw_width));*/ pixma_set_be32 (s->param->x - s->param->xs, data + 0x0c); pixma_set_be32 (s->param->y, data + 0x10); pixma_set_be32 (raw_width, data + 0x14); pixma_set_be32 (h, data + 0x18); data[0x1c] = ((s->param->channels != 1) || is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 0x08 : 0x04; #ifdef DEBUG_TPU_48 data[0x1d] = 24; #else data[0x1d] = (is_scanning_from_tpu (s)) ? 48 : (((s->param->software_lineart) ? 8 : s->param->depth) * ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels)); /* bits per pixel */ #endif data[0x1f] = 0x01; /* This one also seen at 0. Don't know yet what's used for */ data[0x20] = 0xff; data[0x21] = 0x81; data[0x23] = 0x02; data[0x24] = 0x01; switch (s->cfg->pid) { case MG5300_PID: /* unknown values (perhaps counter) for MG5300 series---values must be 0x30-0x39: decimal 0-9 */ data[0x26] = 0x32; /* using example values from a real scan here */ data[0x27] = 0x31; data[0x28] = 0x34; data[0x29] = 0x35; break; default: break; } data[0x30] = 0x01; } return pixma_exec (s, &mp->cb); } static int query_status_3 (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; uint8_t *data; int error, status_len; status_len = 8; data = pixma_newcmd (&mp->cb, cmd_status_3, 0, status_len); RET_IF_ERR (pixma_exec (s, &mp->cb)); memcpy (mp->current_status, data, status_len); return error; } static int query_status (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; uint8_t *data; int error, status_len; status_len = (mp->generation == 1) ? 12 : 16; data = pixma_newcmd (&mp->cb, cmd_status, 0, status_len); RET_IF_ERR (pixma_exec (s, &mp->cb)); memcpy (mp->current_status, data, status_len); PDBG (pixma_dbg (3, "Current status: paper=%u cal=%u lamp=%u busy=%u\n", data[1], data[8], data[7], data[9])); return error; } #if 0 static int send_time (pixma_t * s) { /* Why does a scanner need a time? */ time_t now; struct tm *t; uint8_t *data; mp150_t *mp = (mp150_t *) s->subdriver; data = pixma_newcmd (&mp->cb, cmd_time, 20, 0); pixma_get_time (&now, NULL); t = localtime (&now); snprintf ((char *) data, 16, "%02d/%02d/%02d %02d:%02d", t->tm_year % 100, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min); PDBG (pixma_dbg (3, "Sending time: '%s'\n", (char *) data)); return pixma_exec (s, &mp->cb); } #endif /* TODO: Simplify this function. Read the whole data packet in one shot. */ static int read_image_block (pixma_t * s, uint8_t * header, uint8_t * data) { uint8_t cmd[16]; mp150_t *mp = (mp150_t *) s->subdriver; const int hlen = 8 + 8; int error, datalen; memset (cmd, 0, sizeof (cmd)); pixma_set_be16 (cmd_read_image, cmd); if ((mp->last_block & 0x20) == 0) pixma_set_be32 ((IMAGE_BLOCK_SIZE / 65536) * 65536 + 8, cmd + 0xc); else pixma_set_be32 (32 + 8, cmd + 0xc); mp->state = state_transfering; mp->cb.reslen = pixma_cmd_transaction (s, cmd, sizeof (cmd), mp->cb.buf, 512); datalen = mp->cb.reslen; if (datalen < 0) return datalen; memcpy (header, mp->cb.buf, hlen); if (datalen >= hlen) { datalen -= hlen; memcpy (data, mp->cb.buf + hlen, datalen); data += datalen; if (mp->cb.reslen == 512) { error = pixma_read (s->io, data, IMAGE_BLOCK_SIZE - 512 + hlen); RET_IF_ERR (error); datalen += error; } } mp->state = state_scanning; mp->cb.expected_reslen = 0; RET_IF_ERR (pixma_check_result (&mp->cb)); if (mp->cb.reslen < hlen) return PIXMA_EPROTO; return datalen; } static int read_error_info (pixma_t * s, void *buf, unsigned size) { unsigned len = 16; mp150_t *mp = (mp150_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_error_info, 0, len); RET_IF_ERR (pixma_exec (s, &mp->cb)); if (buf && len < size) { size = len; /* NOTE: I've absolutely no idea what the returned data mean. */ memcpy (buf, data, size); error = len; } return error; } /* handle_interrupt() waits until it receives an interrupt packet or times out. It calls send_time() and query_status() if necessary. Therefore, make sure that handle_interrupt() is only called from a safe context for send_time() and query_status(). Returns: 0 timed out 1 an interrupt packet received PIXMA_ECANCELED interrupted by signal <0 error */ static int handle_interrupt (pixma_t * s, int timeout) { uint8_t buf[64]; int len; len = pixma_wait_interrupt (s->io, buf, sizeof (buf), timeout); if (len == PIXMA_ETIMEDOUT) return 0; if (len < 0) return len; if (len%16) /* len must be a multiple of 16 bytes */ { PDBG (pixma_dbg (1, "WARNING:unexpected interrupt packet length %d\n", len)); return PIXMA_EPROTO; } /* s->event = 0x0brroott * b: button * oo: original * tt: target * rr: scan resolution * poll event with 'scanimage -A' */ if (s->cfg->pid == MG5400_PID || s->cfg->pid == MG6200_PID || s->cfg->pid == MG6300_PID || s->cfg->pid == MX520_PID || s->cfg->pid == MX720_PID || s->cfg->pid == MX920_PID || s->cfg->pid == MB5000_PID) /* button no. in buf[7] * size in buf[10] 01=A4; 02=Letter; 08=10x15; 09=13x18; 0b=auto * format in buf[11] 01=JPEG; 02=TIFF; 03=PDF; 04=Kompakt-PDF * dpi in buf[12] 01=75; 02=150; 03=300; 04=600 * target = format; original = size; scan-resolution = dpi */ { if (buf[7] & 1) s->events = PIXMA_EV_BUTTON1 | buf[11] | buf[10]<<8 | buf[12]<<16; /* color scan */ if (buf[7] & 2) s->events = PIXMA_EV_BUTTON2 | buf[11] | buf[10]<<8 | buf[12]<<16; /* b/w scan */ } else /* button no. in buf[0] * original in buf[0] * target in buf[1] */ { /* More than one event can be reported at the same time. */ if (buf[3] & 1) /* FIXME: This function makes trouble with a lot of scanners send_time (s); */ PDBG (pixma_dbg (1, "WARNING:send_time() disabled!\n")); if (buf[9] & 2) query_status (s); if (buf[0] & 2) s->events = PIXMA_EV_BUTTON2 | buf[1] | ((buf[0] & 0xf0) << 4); /* b/w scan */ if (buf[0] & 1) s->events = PIXMA_EV_BUTTON1 | buf[1] | ((buf[0] & 0xf0) << 4); /* color scan */ } return 1; } static int init_ccd_lamp_3 (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; uint8_t *data; int error, status_len, tmo; status_len = 8; RET_IF_ERR (query_status (s)); RET_IF_ERR (query_status (s)); RET_IF_ERR (send_cmd_start_calibrate_ccd_3 (s)); RET_IF_ERR (query_status (s)); tmo = 20; /* like Windows driver, CCD lamp adjustment */ while (--tmo >= 0) { data = pixma_newcmd (&mp->cb, cmd_end_calibrate_ccd_3, 0, status_len); RET_IF_ERR (pixma_exec (s, &mp->cb)); memcpy (mp->current_status, data, status_len); PDBG (pixma_dbg (3, "Lamp status: %u , timeout in: %u\n", data[0], tmo)); if (mp->current_status[0] == 3 || !is_scanning_from_tpu (s)) break; WAIT_INTERRUPT (1000); } return error; } static int wait_until_ready (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; int error, tmo = 120; /* some scanners need a long timeout */ RET_IF_ERR ((mp->generation >= 3) ? query_status_3 (s) : query_status (s)); while (!is_calibrated (s)) { WAIT_INTERRUPT (1000); if (mp->generation >= 3) RET_IF_ERR (query_status_3 (s)); else if (s->cfg->pid == MP600_PID || s->cfg->pid == MP600R_PID || s->cfg->pid == MP800R_PID) RET_IF_ERR (query_status (s)); if (--tmo == 0) { PDBG (pixma_dbg (1, "WARNING:Timed out in wait_until_ready()\n")); PDBG (query_status (s)); return PIXMA_ETIMEDOUT; } } return 0; } static uint8_t * shift_colors (uint8_t * dptr, uint8_t * sptr, unsigned w, unsigned dpi, unsigned pid, unsigned c, int * colshft, unsigned strshft) { unsigned i, sr, sg, sb, st; UNUSED(dpi); UNUSED(pid); sr = colshft[0]; sg = colshft[1]; sb = colshft[2]; for (i = 0; i < w; i++) { /* stripes shift for MP800, MP800R at 2400 dpi */ st = (i % 2 == 0) ? strshft : 0; *sptr++ = *(dptr++ + sr + st); if (c == 6) *sptr++ = *(dptr++ + sr + st); *sptr++ = *(dptr++ + sg + st); if (c == 6) *sptr++ = *(dptr++ + sg + st); *sptr++ = *(dptr++ + sb + st); if (c == 6) *sptr++ = *(dptr++ + sb + st); } return dptr; } static void reorder_pixels (uint8_t * linebuf, uint8_t * sptr, unsigned c, unsigned n, unsigned m, unsigned w, unsigned line_size) { unsigned i; for (i = 0; i < w; i++) { memcpy (linebuf + c * (n * (i % m) + i / m), sptr + c * i, c); } memcpy (sptr, linebuf, line_size); } #ifndef TPU_48 static unsigned pack_48_24_bpc (uint8_t * sptr, unsigned n) { unsigned i; uint8_t *cptr, lsb; static uint8_t offset = 0; cptr = sptr; if (n % 2 != 0) PDBG (pixma_dbg (3, "WARNING: misaligned image.\n")); for (i = 0; i < n; i += 2) { /* offset = 1 + (offset % 3); */ lsb = *sptr++; *cptr++ = ((*sptr++) << offset) | lsb >> (8 - offset); } return (n / 2); } #endif /* This function deals both with PIXMA CCD sensors producing shifted color * planes images, Grayscale CCD scan and Generation >= 3 high dpi images. * Each complete line in mp->imgbuf is processed for shifting CCD sensor * color planes, reordering pixels above 600 dpi for Generation >= 3, and * converting to Grayscale for CCD sensors. */ static unsigned post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib) { mp150_t *mp = (mp150_t *) s->subdriver; unsigned c, lines, line_size, n, m, cw, cx; uint8_t *sptr, *dptr, *gptr, *cptr; c = ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels) * ((s->param->software_lineart) ? 8 : s->param->depth) / 8; cw = c * s->param->w; cx = c * s->param->xs; if (mp->generation >= 3) n = s->param->xdpi / 600; else /* FIXME: maybe need different values for CIS and CCD sensors */ n = s->param->xdpi / 2400; if (s->cfg->pid == MP600_PID || s->cfg->pid == MP600R_PID) n = s->param->xdpi / 1200; m = (n > 0) ? s->param->wx / n : 1; sptr = dptr = gptr = cptr = mp->imgbuf; line_size = get_cis_ccd_line_size (s); /*PDBG (pixma_dbg (4, "*post_process_image_data***** ----- Set n=%u, m=%u, line_size=%u ----- ***** \n", n, m, line_size));*/ lines = (mp->data_left_ofs - mp->imgbuf) / line_size; /*PDBG (pixma_dbg (4, "*post_process_image_data***** lines = %i > 2 * mp->color_shift + mp->stripe_shift = %i ***** \n", lines, 2 * mp->color_shift + mp->stripe_shift));*/ if (lines > 2 * mp->color_shift + mp->stripe_shift) { unsigned i; lines -= 2 * mp->color_shift + mp->stripe_shift; for (i = 0; i < lines; i++, sptr += line_size) { /* Color plane and stripes shift needed by e.g. CCD */ /*PDBG (pixma_dbg (4, "*post_process_image_data***** Processing with c=%u, n=%u, m=%u, w=%i, line_size=%u ***** \n", c, n, m, s->param->wx, line_size));*/ if (s->cfg->pid != MG5300_PID && s->cfg->pid != MG6300_PID && c >= 3) dptr = shift_colors (dptr, sptr, s->param->wx, s->param->xdpi, s->cfg->pid, c, mp->shift, mp->stripe_shift); /* special image format for *most* devices at high dpi. * MP220, MX360, MX370, MX890, MG5300 are exceptions */ if (n > 0 && s->cfg->pid != MP220_PID && s->cfg->pid != MX360_PID && s->cfg->pid != MX370_PID && s->cfg->pid != MX530_PID && s->cfg->pid != MX890_PID && s->cfg->pid != MX720_PID && s->cfg->pid != MX920_PID && s->cfg->pid != MG3100_PID && s->cfg->pid != MG3500_PID && s->cfg->pid != MG3600_PID && s->cfg->pid != MG2100_PID && s->cfg->pid != MG5300_PID && s->cfg->pid != MG5400_PID && s->cfg->pid != MG5500_PID && s->cfg->pid != MG6300_PID && s->cfg->pid != MG6400_PID && s->cfg->pid != MG7100_PID && s->cfg->pid != MG7500_PID && s->cfg->pid != MG7700_PID && s->cfg->pid != MB5000_PID) reorder_pixels (mp->linebuf, sptr, c, n, m, s->param->wx, line_size); /* Crop line to selected borders */ memmove(cptr, sptr + cx, cw); /* Color / Gray to Lineart convert */ if (s->param->software_lineart) cptr = gptr = pixma_binarize_line (s->param, gptr, cptr, s->param->w, c); /* Color to Grayscale convert for CCD sensor */ else if (is_ccd_grayscale (s)) cptr = gptr = pixma_rgb_to_gray (gptr, cptr, s->param->w, c); else cptr += cw; } } ib->rptr = mp->imgbuf; ib->rend = cptr; return mp->data_left_ofs - sptr; /* # of non processed bytes */ } static int mp150_open (pixma_t * s) { mp150_t *mp; uint8_t *buf; mp = (mp150_t *) calloc (1, sizeof (*mp)); if (!mp) return PIXMA_ENOMEM; buf = (uint8_t *) malloc (CMDBUF_SIZE + IMAGE_BLOCK_SIZE); if (!buf) { free (mp); return PIXMA_ENOMEM; } s->subdriver = mp; mp->state = state_idle; mp->cb.buf = buf; mp->cb.size = CMDBUF_SIZE; mp->cb.res_header_len = 8; mp->cb.cmd_header_len = 16; mp->cb.cmd_len_field_ofs = 14; mp->imgbuf = buf + CMDBUF_SIZE; /* General rules for setting Pixma protocol generation # */ mp->generation = (s->cfg->pid >= MP160_PID) ? 2 : 1; if (s->cfg->pid >= MX7600_PID) mp->generation = 3; if (s->cfg->pid >= MP250_PID) mp->generation = 4; /* And exceptions to be added here */ if (s->cfg->pid == MP140_PID) mp->generation = 2; PDBG (pixma_dbg (3, "*mp150_open***** This is a generation %d scanner. *****\n", mp->generation)); /* TPU info data setup */ mp->tpu_datalen = 0; /* adf scanning */ mp->adf_state = state_idle; if (mp->generation < 4) { query_status (s); handle_interrupt (s, 200); if (mp->generation == 3 && has_ccd_sensor (s)) send_cmd_start_calibrate_ccd_3 (s); } return 0; } static void mp150_close (pixma_t * s) { mp150_t *mp = (mp150_t *) s->subdriver; mp150_finish_scan (s); free (mp->cb.buf); free (mp); s->subdriver = NULL; } static int mp150_check_param (pixma_t * s, pixma_scan_param_t * sp) { mp150_t *mp = (mp150_t *) s->subdriver; /* PDBG (pixma_dbg (4, "*mp150_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u *****\n", sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx)); */ /* MP150 only supports 8 bit per channel in color and grayscale mode */ if (sp->depth != 1) { sp->software_lineart = 0; sp->depth = 8; #ifdef TPU_48 #ifndef DEBUG_TPU_48 if (sp->source == PIXMA_SOURCE_TPU) #endif sp->depth = 16; /* TPU in 16 bits mode */ #endif } else { /* software lineart */ sp->software_lineart = 1; sp->depth = 1; sp->channels = 1; } /* for software lineart w must be a multiple of 8 */ if (sp->software_lineart == 1 && sp->w % 8) { unsigned w_max; sp->w += 8 - (sp->w % 8); /* do not exceed the scanner capability */ w_max = s->cfg->width * s->cfg->xdpi / 75; w_max -= w_max % 8; if (sp->w > w_max) sp->w = w_max; } if (mp->generation >= 2) { /* mod 32 and expansion of the X scan limits */ /*PDBG (pixma_dbg (4, "*mp150_check_param***** ----- Initially: x=%i, y=%i, w=%i, h=%i *****\n", sp->x, sp->y, sp->w, sp->h));*/ sp->xs = (sp->x) % 32; } else sp->xs = 0; /*PDBG (pixma_dbg (4, "*mp150_check_param***** Selected origin, origin shift: %i, %i *****\n", sp->x, sp->xs));*/ sp->wx = calc_raw_width (mp, sp); sp->line_size = sp->w * sp->channels * (((sp->software_lineart) ? 8 : sp->depth) / 8); /* bytes per line per color after cropping */ /*PDBG (pixma_dbg (4, "*mp150_check_param***** Final scan width and line-size: %i, %i *****\n", sp->wx, sp->line_size));*/ /* Some exceptions here for particular devices */ /* Those devices can scan up to legal 14" with ADF, but A4 11.7" in flatbed */ /* PIXMA_CAP_ADF also works for PIXMA_CAP_ADFDUP */ if ((s->cfg->cap & PIXMA_CAP_ADF) && sp->source == PIXMA_SOURCE_FLATBED) sp->h = MIN (sp->h, 877 * sp->xdpi / 75); if (sp->source == PIXMA_SOURCE_TPU) { uint8_t k; /* TPU mode: lowest res is 150 or 300 dpi */ if (mp->generation >= 3) k = MAX (sp->xdpi, 300) / sp->xdpi; else k = MAX (sp->xdpi, 150) / sp->xdpi; sp->x *= k; sp->xs *= k; sp->y *= k; sp->w *= k; sp->wx *= k; sp->h *= k; sp->xdpi *= k; sp->ydpi = sp->xdpi; } if (sp->source == PIXMA_SOURCE_ADF || sp->source == PIXMA_SOURCE_ADFDUP) { uint8_t k = 1; /* ADF/ADF duplex mode: max scan res is 600 dpi, at least for generation 4 */ if (mp->generation >= 4) k = sp->xdpi / MIN (sp->xdpi, 600); sp->x /= k; sp->xs /= k; sp->y /= k; sp->w /= k; sp->wx /= k; sp->h /= k; sp->xdpi /= k; sp->ydpi = sp->xdpi; } /*PDBG (pixma_dbg (4, "*mp150_check_param***** Finally: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u *****\n", sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx));*/ return 0; } static int mp150_scan (pixma_t * s) { int error = 0, tmo; mp150_t *mp = (mp150_t *) s->subdriver; if (mp->state != state_idle) return PIXMA_EBUSY; /* Generation 4: send XML dialog */ /* adf: first page or idle */ if (mp->generation == 4 && mp->adf_state == state_idle) { if (!send_xml_dialog (s, XML_START_1)) return PIXMA_EPROTO; if (!send_xml_dialog (s, XML_START_2)) return PIXMA_EPROTO; } /* clear interrupt packets buffer */ while (handle_interrupt (s, 0) > 0) { } /* FIXME: Duplex ADF: check paper status only before odd pages (1,3,5,...). */ if (is_scanning_from_adf (s)) { if ((error = query_status (s)) < 0) return error; /* wait for inserted paper * timeout: 10 sec */ tmo = 10; while (!has_paper (s) && --tmo >= 0) { if ((error = query_status (s)) < 0) return error; WAIT_INTERRUPT (1000); PDBG (pixma_dbg (2, "No paper in ADF. Timed out in %d sec.\n", tmo)); } /* no paper inserted * => abort session */ if (!has_paper (s)) { PDBG (pixma_dbg (4, "*mp150_scan***** no paper in ADF *****\n")); error = abort_session (s); if (error < 0) return error; /* Generation 4: send XML dialog */ /* adf: first page or idle */ if (mp->generation == 4 && mp->adf_state == state_idle) { if (!send_xml_dialog (s, XML_END)) return PIXMA_EPROTO; } return PIXMA_ENO_PAPER; } } if (has_ccd_sensor (s) && (mp->generation <= 2)) { error = send_cmd_e920 (s); switch (error) { case PIXMA_ECANCELED: case PIXMA_EBUSY: PDBG (pixma_dbg (2, "cmd e920 or d520 returned %s\n", pixma_strerror (error))); /* fall through */ case 0: query_status (s); break; default: PDBG (pixma_dbg (1, "WARNING:cmd e920 or d520 failed %s\n", pixma_strerror (error))); return error; } tmo = 3; /* like Windows driver, CCD calibration ? */ while (--tmo >= 0) { WAIT_INTERRUPT (1000); PDBG (pixma_dbg (2, "CCD Calibration ends in %d sec.\n", tmo)); } /* pixma_sleep(2000000); */ } tmo = 10; /* adf: first page or idle */ if (mp->generation <= 2 || mp->adf_state == state_idle) { /* single sheet or first sheet from ADF */ PDBG (pixma_dbg (4, "*mp150_scan***** start scanning *****\n")); error = start_session (s); while (error == PIXMA_EBUSY && --tmo >= 0) { if (s->cancel) { error = PIXMA_ECANCELED; break; } PDBG (pixma_dbg (2, "Scanner is busy. Timed out in %d sec.\n", tmo + 1)); pixma_sleep (1000000); error = start_session (s); } if (error == PIXMA_EBUSY || error == PIXMA_ETIMEDOUT) { /* The scanner maybe hangs. We try to empty output buffer of the * scanner and issue the cancel command. */ PDBG (pixma_dbg (2, "Scanner hangs? Sending abort_session command.\n")); drain_bulk_in (s); abort_session (s); pixma_sleep (500000); error = start_session (s); } if ((error >= 0) || (mp->generation >= 3)) mp->state = state_warmup; if ((error >= 0) && (mp->generation <= 2)) error = select_source (s); if ((error >= 0) && (mp->generation >= 3) && has_ccd_sensor (s)) error = init_ccd_lamp_3 (s); if ((error >= 0) && !is_scanning_from_tpu (s)) { int i; for (i = (mp->generation >= 3) ? 3 : 1 ; i > 0 && error >= 0; i--) error = send_gamma_table (s); } else if (error >= 0) /* in TPU mode, for gen 1, 2, and 3 */ error = send_set_tpu_info (s); } else /* ADF pageid != 0 and gen3 or above */ { /* next sheet from ADF */ PDBG (pixma_dbg (4, "*mp150_scan***** scan next sheet from ADF *****\n")); pixma_sleep (1000000); } if ((error >= 0) || (mp->generation >= 3)) mp->state = state_warmup; if (error >= 0) error = send_scan_param (s); if ((error >= 0) && (mp->generation >= 3)) error = start_scan_3 (s); if (error < 0) { mp->last_block = 0x38; /* Force abort session if ADF scan */ mp150_finish_scan (s); return error; } /* ADF scanning active */ if (is_scanning_from_adf (s)) mp->adf_state = state_scanning; return 0; } static int mp150_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { int error; mp150_t *mp = (mp150_t *) s->subdriver; unsigned block_size, bytes_received, proc_buf_size, line_size; uint8_t header[16]; if (mp->state == state_warmup) { RET_IF_ERR (wait_until_ready (s)); pixma_sleep (1000000); /* No need to sleep, actually, but Window's driver * sleep 1.5 sec. */ mp->state = state_scanning; mp->last_block = 0; line_size = get_cis_ccd_line_size (s); proc_buf_size = (2 * calc_shifting (s) + 2) * line_size; mp->cb.buf = realloc (mp->cb.buf, CMDBUF_SIZE + IMAGE_BLOCK_SIZE + proc_buf_size); if (!mp->cb.buf) return PIXMA_ENOMEM; mp->linebuf = mp->cb.buf + CMDBUF_SIZE; mp->imgbuf = mp->data_left_ofs = mp->linebuf + line_size; mp->data_left_len = 0; } do { if (s->cancel) { PDBG (pixma_dbg (4, "*mp150_fill_buffer***** s->cancel *****\n")); return PIXMA_ECANCELED; } if ((mp->last_block & 0x28) == 0x28) { /* end of image */ PDBG (pixma_dbg (4, "*mp150_fill_buffer***** end of image *****\n")); mp->state = state_finished; return 0; } /*PDBG (pixma_dbg (4, "*mp150_fill_buffer***** moving %u bytes into buffer *****\n", mp->data_left_len));*/ memmove (mp->imgbuf, mp->data_left_ofs, mp->data_left_len); error = read_image_block (s, header, mp->imgbuf + mp->data_left_len); if (error < 0) { PDBG (pixma_dbg (4, "*mp150_fill_buffer***** scanner error (%d): end scan *****\n", error)); mp->last_block = 0x38; /* end scan in mp150_finish_scan() */ if (error == PIXMA_ECANCELED) { /* NOTE: I see this in traffic logs but I don't know its meaning. */ read_error_info (s, NULL, 0); } return error; } bytes_received = error; /*PDBG (pixma_dbg (4, "*mp150_fill_buffer***** %u bytes received by read_image_block *****\n", bytes_received));*/ block_size = pixma_get_be32 (header + 12); mp->last_block = header[8] & 0x38; if ((header[8] & ~0x38) != 0) { PDBG (pixma_dbg (1, "WARNING: Unexpected result header\n")); PDBG (pixma_hexdump (1, header, 16)); } PASSERT (bytes_received == block_size); if (block_size == 0) { /* no image data at this moment. */ pixma_sleep (10000); } /* For TPU at 48 bits/pixel to output at 24 bits/pixel */ #ifndef DEBUG_TPU_48 #ifndef TPU_48 #ifndef DEBUG_TPU_24 if (is_scanning_from_tpu (s)) #endif bytes_received = pack_48_24_bpc (mp->imgbuf + mp->data_left_len, bytes_received); #endif #endif /* Post-process the image data */ mp->data_left_ofs = mp->imgbuf + mp->data_left_len + bytes_received; mp->data_left_len = post_process_image_data (s, ib); mp->data_left_ofs -= mp->data_left_len; } while (ib->rend == ib->rptr); return ib->rend - ib->rptr; } static void mp150_finish_scan (pixma_t * s) { int error; mp150_t *mp = (mp150_t *) s->subdriver; switch (mp->state) { case state_transfering: drain_bulk_in (s); /* fall through */ case state_scanning: case state_warmup: case state_finished: /* Send the get TPU info message */ if (is_scanning_from_tpu (s) && mp->tpu_datalen == 0) send_get_tpu_info_3 (s); /* FIXME: to process several pages ADF scan, must not send * abort_session and start_session between pages (last_block=0x28) */ if (mp->generation <= 2 || !is_scanning_from_adf (s) || mp->last_block == 0x38) { PDBG (pixma_dbg (4, "*mp150_finish_scan***** abort session *****\n")); error = abort_session (s); /* FIXME: it probably doesn't work in duplex mode! */ if (error < 0) PDBG (pixma_dbg (1, "WARNING:abort_session() failed %d\n", error)); /* Generation 4: send XML end of scan dialog */ if (mp->generation == 4) { if (!send_xml_dialog (s, XML_END)) PDBG (pixma_dbg (1, "WARNING:XML_END dialog failed \n")); } } else PDBG (pixma_dbg (4, "*mp150_finish_scan***** wait for next page from ADF *****\n")); mp->state = state_idle; /* fall through */ case state_idle: break; } } static void mp150_wait_event (pixma_t * s, int timeout) { /* FIXME: timeout is not correct. See usbGetCompleteUrbNoIntr() for * instance. */ while (s->events == 0 && handle_interrupt (s, timeout) > 0) { } } static int mp150_get_status (pixma_t * s, pixma_device_status_t * status) { int error; RET_IF_ERR (query_status (s)); status->hardware = PIXMA_HARDWARE_OK; status->adf = (has_paper (s)) ? PIXMA_ADF_OK : PIXMA_ADF_NO_PAPER; status->cal = (is_calibrated (s)) ? PIXMA_CALIBRATION_OK : PIXMA_CALIBRATION_OFF; return 0; } static const pixma_scan_ops_t pixma_mp150_ops = { mp150_open, mp150_close, mp150_scan, mp150_fill_buffer, mp150_finish_scan, mp150_wait_event, mp150_check_param, mp150_get_status }; #define DEVICE(name, model, pid, dpi, adftpu_min_dpi, adftpu_max_dpi, w, h, cap) { \ name, /* name */ \ model, /* model */ \ CANON_VID, pid, /* vid pid */ \ 0, /* iface */ \ &pixma_mp150_ops, /* ops */ \ dpi, 2*(dpi), /* xdpi, ydpi */ \ adftpu_min_dpi, adftpu_max_dpi, /* adftpu_min_dpi, adftpu_max_dpi */ \ 0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \ w, h, /* width, height */ \ PIXMA_CAP_EASY_RGB| \ PIXMA_CAP_GRAY| /* CIS with native grayscale and CCD with software grayscale */ \ PIXMA_CAP_LINEART| /* all scanners with software lineart */ \ PIXMA_CAP_GAMMA_TABLE|PIXMA_CAP_EVENTS|cap \ } #define END_OF_DEVICE_LIST DEVICE(NULL, NULL, 0, 0, 0, 0, 0, 0, 0) const pixma_config_t pixma_mp150_devices[] = { /* Generation 1: CIS */ DEVICE ("Canon PIXMA MP150", "MP150", MP150_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP170", "MP170", MP170_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP450", "MP450", MP450_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP500", "MP500", MP500_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP530", "MP530", MP530_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), /* Generation 1: CCD */ DEVICE ("Canon PIXMA MP800", "MP800", MP800_PID, 2400, 150, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), DEVICE ("Canon PIXMA MP800R", "MP800R", MP800R_PID, 2400, 150, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), DEVICE ("Canon PIXMA MP830", "MP830", MP830_PID, 2400, 150, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_ADFDUP), /* Generation 2: CIS */ DEVICE ("Canon PIXMA MP140", "MP140", MP140_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP160", "MP160", MP160_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP180", "MP180", MP180_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP460", "MP460", MP460_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP510", "MP510", MP510_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP600", "MP600", MP600_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP600R", "MP600R", MP600R_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Generation 3: CIS */ DEVICE ("Canon PIXMA MP210", "MP210", MP210_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP220", "MP220", MP220_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP470", "MP470", MP470_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP520", "MP520", MP520_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP610", "MP610", MP610_PID, 4800, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MX300", "MX300", MX300_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MX310", "MX310", MX310_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX700", "MX700", MX700_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX850", "MX850", MX850_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA MX7600", "MX7600", MX7600_PID, 4800, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA MP630", "MP630", MP630_PID, 4800, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP620", "MP620", MP620_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP540", "MP540", MP540_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP480", "MP480", MP480_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP240", "MP240", MP240_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP260", "MP260", MP260_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP190", "MP190", MP190_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), /* PIXMA 2009 vintage */ DEVICE ("Canon PIXMA MX320", "MX320", MX320_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX330", "MX330", MX330_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX860", "MX860", MX860_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), /* width and height adjusted to flatbed size 21.8 x 30.2 cm^2 respective * Not sure if anything's going wrong here, leaving as is DEVICE ("Canon PIXMA MX860", "MX860", MX860_PID, 2400, 0, 0, 638, 880, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP),*/ /* PIXMA 2010 vintage */ DEVICE ("Canon PIXMA MX340", "MX340", MX340_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX350", "MX350", MX350_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX870", "MX870", MX870_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), /* PIXMA 2011 vintage */ DEVICE ("Canon PIXMA MX360", "MX360", MX360_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX410", "MX410", MX410_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX420", "MX420", MX420_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX880 Series", "MX880", MX880_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), /* Generation 4: CIS */ DEVICE ("Canon PIXMA MP640", "MP640", MP640_PID, 4800, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP560", "MP560", MP560_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP550", "MP550", MP550_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP490", "MP490", MP490_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP250", "MP250", MP250_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP270", "MP270", MP270_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2010) Generation 4 CIS/CCD */ DEVICE ("Canon PIXMA MP280", "MP280", MP280_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), /* TODO: 1200dpi doesn't work yet */ DEVICE ("Canon PIXMA MP495", "MP495", MP495_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG5100", "MG5100", MG5100_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG5200", "MG5200", MG5200_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6100", "MG6100", MG6100_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2011) Generation 4 CIS/CCD */ DEVICE ("Canon PIXMA MG2100", "MG2100", MG2100_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG3100", "MG3100", MG3100_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG4100", "MG4100", MG4100_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG5300", "MG5300", MG5300_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6200", "MG6200", MG6200_PID, 4800, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MP493", "MP493", MP493_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA E500", "E500", E500_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2012) Generation 4 CIS */ DEVICE ("Canon PIXMA MX370 Series", "MX370", MX370_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX430 Series", "MX430", MX430_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX510 Series", "MX510", MX510_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX710 Series", "MX710", MX710_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA MX890 Series", "MX890", MX890_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA E600 Series", "E600", E600_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MG4200", "MG4200", MG4200_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2013) Generation 4 CIS */ DEVICE ("Canon PIXMA E510", "E510", E510_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA E610", "E610", E610_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MP230", "MP230", MP230_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG2200 Series", "MG2200", MG2200_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG3200 Series", "MG3200", MG3200_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG5400 Series", "MG5400", MG5400_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6300 Series", "MG6300", MG6300_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MX390 Series", "MX390", MX390_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX450 Series", "MX450", MX450_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX520 Series", "MX520", MX520_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX720 Series", "MX720", MX720_PID, 2400, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA MX920 Series", "MX920", MX920_PID, 2400, 0, 600, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA MG2400 Series", "MG2400", MG2400_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG2500 Series", "MG2500", MG2500_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG3500 Series", "MG3500", MG3500_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG5500 Series", "MG5500", MG5500_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6400 Series", "MG6400", MG6400_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6500 Series", "MG6500", MG6500_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG7100 Series", "MG7100", MG7100_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2014) Generation 4 CIS */ DEVICE ("Canon PIXMA MX470 Series", "MX470", MX470_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MX530 Series", "MX530", MX530_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon MAXIFY MB5000 Series", "MB5000", MB5000_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon MAXIFY MB5300 Series", "MB5300", MB5300_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon MAXIFY MB2000 Series", "MB2000", MB2000_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon MAXIFY MB2300 Series", "MB2300", MB2300_PID, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP), DEVICE ("Canon PIXMA E400", "E400", E400_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA E560", "E560", E560_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG7500 Series", "MG7500", MG7500_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6600 Series", "MG6600", MG6600_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG5600 Series", "MG5600", MG5600_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG2900 Series", "MG2900", MG2900_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA E460 Series", "E460", E460_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2015) Generation 4 CIS */ DEVICE ("Canon PIXMA MX490 Series", "MX490", MX490_PID, 600, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA E480 Series", "E480", E480_PID, 600, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MG3600 Series", "MG3600", MG3600_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG7700 Series", "MG7700", MG7700_PID, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6900 Series", "MG6900", MG6900_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG6800 Series", "MG6800", MG6800_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG5700 Series", "MG5700", MG5700_PID, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS), /* Latest devices (2016) Generation 4 CIS */ DEVICE ("Canon PIXMA TS9000 Series", "TS9000", TS9000_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA TS8000 Series", "TS8000", TS8000_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA TS6000 Series", "TS6000", TS6000_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA TS5000 Series", "TS5000", TS5000_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA MG3000 Series", "MG3000", MG3000_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA E470 Series", "E470", E470_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), DEVICE ("Canon PIXMA G4000 Series", "G3000", G3000_PID, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), END_OF_DEVICE_LIST }; sane-backends-1.0.27/backend/dc240.conf.in0000664000175000017500000000173012112021330014663 00000000000000# Serial port where the camera is connected ## Linux port=/dev/ttyS0 ## IRIX #port=/dev/ttyd1 ## Solaris #port=/dev/term/a ## HP-UX #port=/dev/tty0p0 ## Digital UNIX #port=/dev/tty01 # Max baud rate for download. Camera always starts at 9600 baud, then # switches to the higher rate ## This works for Linux. Also works for IRIX (6.3 or higher), providing that ## the host is an O2, OCTANE, Origin2000/200, Onyx2, Origin3000/300, Onyx3 or ## a newer SGI hardware [see serial(7)]. #baud=115200 ## This works for most UNIX's baud=38400 # Prints some extra information during the init phase. This can be # handy, but note that printing anything to stderr breaks the saned # network scanning. #dumpinquiry # How many usec (1,000,000ths of a) between writing the command and reading the # result. 125000 seems to be the lowest I could go reliably. cmdrespause=125000 # How many usec (1,000,000ths of a) between sending the "back to default" break # sending commands. breakpause=1000000; sane-backends-1.0.27/backend/plustek-pp_ptdrv.c0000664000175000017500000013460312775277260016326 00000000000000/* @file plustek-pp_ptdrv.c * @brief this is the driver interface * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - Added some comments * - added claiming/release of parallel port resources for this driver * - added scaling function for high resolution modes where dpix < dpiy * - 0.32 - Revised lamp-off behaviour * - removed function ptdrvIsLampOn * - fixed misbehaviour when using cat /dev/pt_drv * - moved parport-functions to module misc.c * - 0.33 - added parameter lOffonEnd * - revised parport concurrency * - removed calls to ps->PositionLamp * - 0.34 - no changes * - 0.35 - removed _PTDRV_PUT_SCANNER_MODEL from ioctl interface * - added Kevins' changes (MiscRestorePort) * - added parameter legal and function PtDrvLegalRequested() * - 0.36 - removed a bug in the shutdown function * - removed all OP600P specific stuff because of the Primax tests * - added version code to ioctl interface * - added new parameter mov - model override * - removed parameter legal * - removed function PtDrvLegalRequested * - changes, due to define renaming * - patch for OpticPro 4800P * - added multiple device support * - added proc fs support/also for Kernel2.4 * - 0.37 - cleanup work, moved the procfs stuff to file procfs.c * - and some definitions to plustek_scan.h * - moved MODELSTR to misc.c * - output of the error-code after initialization * - 0.38 - added P12 stuff * - removed function ptdrvIdleMode * - moved function ptdrvP96Calibration() to p48xxCalibration * - moved function ptdrvP98Calibration() to p9636Calibration * - added devfs support (patch by Gordon Heydon ) * - 0.39 - added schedule stuff after reading one line to have a better * system response in SPP modes * - added forceMode switch * - 0.40 - added MODULE_LICENSE stuff * - 0.41 - added _PTDRV_ADJUST functionality * - changed ioctl call to PutImage * - 0.42 - added _PTDRV_SETMAP functionality * - improved the cancel functionality * - 0.43 - added LINUX_26 stuff * - changed include names * - changed version string stuff * - 0.44 - added support for more recent kernels * - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifdef __KERNEL__ # include # include # ifdef CONFIG_DEVFS_FS # include # if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,69)) # define DEVFS_26_STYLE # endif # endif #endif #include "plustek-pp_scan.h" #ifdef __KERNEL__ # include #endif /****************************** static vars **********************************/ /* default port is at 0x378 */ static int port[_MAX_PTDEVS] = { 0x378, 0, 0, 0 }; #ifdef __KERNEL__ static pScanData PtDrvDevices[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = NULL}; /* default is 180 secs for lamp switch off */ static int lampoff[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = 180 }; /* warmup period for lamp (30 secs) */ static int warmup[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = 30 }; /* switch lamp off on unload (default = no)*/ static int lOffonEnd[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = 0 }; /* model override (0-->none) */ static UShort mov[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = 0 }; /* forceMode (0--> auto, 1: SPP, 2:EPP, others: auto) */ static UShort forceMode[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = 0 }; /* to use delayed I/O for each device */ static Bool slowIO[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = _FALSE }; #else static pScanData PtDrvDevices[_MAX_PTDEVS]= { NULL, NULL, NULL, NULL }; static int lampoff[_MAX_PTDEVS] = { 180, 180, 180, 180 }; static int warmup[_MAX_PTDEVS] = { 30, 30, 30, 30 }; static int lOffonEnd[_MAX_PTDEVS] = { 0, 0, 0, 0 }; static UShort mov[_MAX_PTDEVS] = { 0, 0, 0, 0 }; static UShort forceMode[_MAX_PTDEVS] = { 0, 0, 0, 0 }; #endif /* timers for warmup checks */ static TimerDef toTimer[_MAX_PTDEVS]; #ifndef __KERNEL__ static Bool PtDrvInitialized = _FALSE; #ifdef HAVE_SETITIMER static struct itimerval saveSettings; #endif #else static Bool deviceScanning = _FALSE; static struct timer_list tl[_MAX_PTDEVS]; /* for calculation of the timer expiration */ extern volatile unsigned long jiffies; /* the parameter interface */ #if ((LINUX_VERSION_CODE > 0x020111) && defined(MODULE)) MODULE_AUTHOR("Gerhard Jaeger "); MODULE_DESCRIPTION("Plustek parallelport-scanner driver"); /* addresses this 'new' license feature... */ #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)) MODULE_PARM(port, "1-" __MODULE_STRING(_MAX_PTDEVS) "i"); MODULE_PARM(lampoff, "1-" __MODULE_STRING(_MAX_PTDEVS) "i"); MODULE_PARM(warmup,"1-" __MODULE_STRING(_MAX_PTDEVS) "i"); MODULE_PARM(lOffonEnd, "1-" __MODULE_STRING(_MAX_PTDEVS) "i"); MODULE_PARM(mov, "1-" __MODULE_STRING(_MAX_PTDEVS) "i"); MODULE_PARM(slowIO,"1-" __MODULE_STRING(_MAX_PTDEVS) "i"); MODULE_PARM(forceMode,"1-" __MODULE_STRING(_MAX_PTDEVS) "i"); #else static int array_len = _MAX_PTDEVS; module_param_array(port, int, &array_len, 0); module_param_array(lampoff, int, &array_len, 0); module_param_array(warmup, int, &array_len, 0); module_param_array(lOffonEnd, int, &array_len, 0); module_param_array(mov, ushort, &array_len, 0); module_param_array(slowIO, int, &array_len, 0); module_param_array(forceMode, ushort, &array_len, 0); #endif MODULE_PARM_DESC(port, "I/O base address of parport"); MODULE_PARM_DESC(lampoff, "Lamp-Off timer preset in seconds"); MODULE_PARM_DESC(warmup, "Minimum warmup time in seconds"); MODULE_PARM_DESC(lOffonEnd, "1 - switchoff lamp on unload"); MODULE_PARM_DESC(mov, "Modell-override switch"); MODULE_PARM_DESC(slowIO, "0 = Fast I/O, 1 = Delayed I/O"); MODULE_PARM_DESC(forceMode, "0 = use auto detection, " "1 = use SPP mode, 2 = use EPP mode"); #endif #if defined (CONFIG_DEVFS_FS) # ifndef (DEVFS_26_STYLE) static devfs_handle_t devfs_handle = NULL; # endif #else # ifdef LINUX_26 static class_t *ptdrv_class; # endif #endif /* * the module interface */ static int pt_drv_open ( struct inode *, struct file *); static CLOSETYPE pt_drv_close( struct inode *, struct file *); #ifdef LINUX_20 static int pt_drv_read( struct inode*, struct file*, char*, int ); static int pt_drv_write( struct inode*, struct file*, const char*, int ); #else static ssize_t pt_drv_read ( struct file *file, char *buffer, size_t count, loff_t *); static ssize_t pt_drv_write( struct file *file, const char *buffer, size_t tmp,loff_t *count); #endif #ifdef NOLOCK_IOCTL static long pt_drv_ioctl( struct file *, UInt, unsigned long ); #else static int pt_drv_ioctl( struct inode *, struct file *, UInt, unsigned long ); #endif /* * the driver interface */ #ifdef LINUX_20 static struct file_operations pt_drv_fops = { NULL, /* seek */ pt_drv_read, /* read */ pt_drv_write, /* write */ NULL, /* readdir */ NULL, /* select */ pt_drv_ioctl, /* ioctl */ NULL, /* mmap */ pt_drv_open, /* open */ pt_drv_close, /* release */ NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ NULL /* revalidate */ }; #else /* 2.2.x and higher stuff */ static struct file_operations pt_drv_fops = { #ifdef LINUX_24 owner: THIS_MODULE, #endif read: pt_drv_read, write: pt_drv_write, IOCTL: pt_drv_ioctl, open: pt_drv_open, release: pt_drv_close, }; #endif #endif /* guard __KERNEL */ /****************************** some prototypes ******************************/ static void ptdrvStartLampTimer( pScanData ps ); /****************************** local functions ******************************/ #ifdef __KERNEL__ /** depending on the device, return the data structure */ static pScanData get_pt_from_inode(struct inode *ip) { int minor = _MINOR(ip); /* * unit out of range */ if (minor >= _MAX_PTDEVS ) return NULL; return( PtDrvDevices[minor] ); } #endif /** copy user-space data into kernel memory */ static int getUserPtr(const pVoid useraddr, pVoid where, UInt size ) { int err = _OK; /* do parameter checks */ if((NULL == useraddr) || ( 0 == size)) return _E_INVALID; #ifdef __KERNEL__ if ((err = verify_area_20(VERIFY_READ, useraddr, size))) return err; #endif switch (size) { #ifdef __KERNEL__ case sizeof(u_char): GET_USER_RET(*(u_char *)where, (u_char *) useraddr, -EFAULT); break; case sizeof(u_short): GET_USER_RET(*(u_short *)where, (u_short *) useraddr, -EFAULT); break; case sizeof(u_long): GET_USER_RET(*(u_long *)where, (u_long *) useraddr, -EFAULT); break; default: if (copy_from_user(where, useraddr, size)) return -EFAULT; #else default: memcpy( where, useraddr, size ); #endif } return err; } /** copy kernel data into user mode address space */ static int putUserPtr( const pVoid ptr, pVoid useraddr, UInt size ) { int err = _OK; if (NULL == useraddr) return _E_INVALID; #ifdef __KERNEL__ if ((err = verify_area_20(VERIFY_WRITE, useraddr, size))) return err; if (copy_to_user(useraddr, ptr, size )) return -EFAULT; #else memcpy( useraddr, ptr, size ); #endif return err; } #ifndef __KERNEL__ static unsigned long copy_from_user( pVoid dest, pVoid src, unsigned long len ) { memcpy( dest, src, len ); return 0; } static unsigned long copy_to_user( pVoid dest, pVoid src, unsigned long len ) { memcpy( dest, src, len ); return 0; } #endif /** */ static int putUserVal(const ULong value, pVoid useraddr, UInt size) { #ifdef __KERNEL__ int err; #endif if (NULL == useraddr) return _E_INVALID; #ifdef __KERNEL__ if ((err = verify_area_20(VERIFY_WRITE, useraddr, size))) return err; #endif switch (size) { #ifdef __KERNEL__ case sizeof(u_char): PUT_USER_RET((u_char)value, (u_char *) useraddr, -EFAULT); break; case sizeof(u_short): PUT_USER_RET((u_short)value, (u_short *) useraddr, -EFAULT); break; case sizeof(u_long): PUT_USER_RET((u_long)value, (u_long *) useraddr, -EFAULT); break; #else case sizeof(UChar): *(pUChar)useraddr = (UChar)value; break; case sizeof(UShort): *(pUShort)useraddr = (UShort)value; break; case sizeof(ULong): *(pULong)useraddr = (ULong)value; break; #endif default: return _E_INVALID; } return 0; } /** switch lamp 0 on */ static void ptDrvSwitchLampOn( pScanData ps ) { DBG( DBG_LOW, "Switching lamp 0 on.\n" ); if( _IS_ASIC98(ps->sCaps.AsicID)) { ps->AsicReg.RD_ScanControl |= _SCAN_NORMALLAMP_ON; ps->bLastLampStatus = _SCAN_NORMALLAMP_ON; } else { ps->AsicReg.RD_ScanControl |= ps->bLampOn; ps->bLastLampStatus = ps->bLampOn; } IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); } /** check the lamp warmup */ static void ptdrvLampWarmup( pScanData ps ) { Bool warmupNeeded; TimerDef timer; if( 0 == ps->warmup ) return; warmupNeeded = _FALSE; /* * do we have to warmup again ? Timer has not elapsed... */ if( _OK == MiscCheckTimer( &toTimer[ps->devno] )) { DBG( DBG_LOW, "Startup warmup needed!\n" ); warmupNeeded = _TRUE; } else { warmupNeeded = ps->fWarmupNeeded; } if( warmupNeeded ) { /* * correct lamp should have been switched on but * before doing anything else wait until warmup has been done */ DBG( DBG_LOW, "Waiting on warmup - %u s\n", ps->warmup ); MiscStartTimer( &timer, _SECOND * ps->warmup ); while( !MiscCheckTimer( &timer )) { /* on break, we setup the initial timer again... */ if( _FALSE == ps->fScanningStatus ) { MiscStartTimer( &toTimer[ps->devno], (_SECOND * ps->warmup)); return; } }; } #ifdef DEBUG else { DBG( DBG_LOW, "No warm-up needed \n" ); } #endif /* * start a timer here again with only a second timeout * because we need this one only for startup (Force timeout!!) */ MiscStartTimer( &toTimer[ps->devno], _SECOND ); } /** */ #ifdef __KERNEL__ static void ptdrvLampTimerIrq( unsigned long ptr ) #else static void ptdrvLampTimerIrq( int sig_num ) #endif { pScanData ps; DBG( DBG_HIGH, "!! IRQ !! Lamp-Timer stopped.\n" ); #ifdef __KERNEL__ ps = (pScanData)ptr; #else _VAR_NOT_USED( sig_num ); ps = PtDrvDevices[0]; #endif /* * paranoia check! */ if( NULL == ps ) return; if( _NO_BASE == ps->sCaps.wIOBase ) return; if( _IS_ASIC98(ps->sCaps.AsicID)) { ps->AsicReg.RD_ScanControl &= ~_SCAN_LAMPS_ON; } else { ps->AsicReg.RD_ScanControl &= ~_SCAN_LAMP_ON; } /* force warmup... */ ps->bLastLampStatus = 0xFF; /* * claim parallel port if necessary... * if the port is busy, restart the timer */ if( _OK != MiscClaimPort(ps)) { ptdrvStartLampTimer( ps ); return; } IOCmdRegisterToScanner( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); MiscReleasePort(ps); } /** */ static void ptdrvStartLampTimer( pScanData ps ) { #ifndef __KERNEL__ sigset_t block, pause_mask; struct sigaction s; #ifdef HAVE_SETITIMER struct itimerval interval; #endif /* block SIGALRM */ sigemptyset( &block ); sigaddset ( &block, SIGALRM ); sigprocmask( SIG_BLOCK, &block, &pause_mask ); /* setup handler */ sigemptyset( &s.sa_mask ); sigaddset ( &s.sa_mask, SIGINT ); s.sa_flags = 0; s.sa_handler = ptdrvLampTimerIrq; if( sigaction( SIGALRM, &s, NULL ) < 0 ) { DBG(DBG_HIGH,"pt_drv%u: Can't setup timer-irq handler\n",ps->devno); } sigprocmask( SIG_UNBLOCK, &block, &pause_mask ); #ifdef HAVE_SETITIMER /* * define a one-shot timer */ interval.it_value.tv_usec = 0; interval.it_value.tv_sec = ps->lampoff; interval.it_interval.tv_usec = 0; interval.it_interval.tv_sec = 0; if( 0 != ps->lampoff ) setitimer( ITIMER_REAL, &interval, &saveSettings ); #else alarm( ps->lampoff ); #endif #else init_timer( &tl[ps->devno] ); /* timeout val in seconds */ tl[ps->devno].expires = jiffies + ps->lampoff * HZ; tl[ps->devno].data = (unsigned long)ps; tl[ps->devno].function = ptdrvLampTimerIrq; if( 0 != ps->lampoff ) add_timer( &tl[ps->devno] ); #endif DBG( DBG_HIGH, "Lamp-Timer started!\n" ); } /** */ static void ptdrvStopLampTimer( pScanData ps ) { #ifndef __KERNEL__ sigset_t block, pause_mask; /* block SIGALRM */ sigemptyset( &block ); sigaddset ( &block, SIGALRM ); sigprocmask( SIG_BLOCK, &block, &pause_mask ); #ifdef HAVE_SETITIMER if( 0 != ps->lampoff ) setitimer( ITIMER_REAL, &saveSettings, NULL ); #else _VAR_NOT_USED( ps ); alarm(0); #endif #else if( 0 != ps->lampoff ) del_timer( &tl[ps->devno] ); #endif DBG( DBG_HIGH, "Lamp-Timer stopped!\n" ); } /** claim and initialize the requested port */ static int ptdrvOpen( pScanData ps, int portBase ) { int retval; DBG( DBG_HIGH, "ptdrvOpen(port=0x%x)\n", (int32_t)portBase ); if( NULL == ps ) return _E_NULLPTR; /* * claim port resources... */ retval = MiscClaimPort(ps); if( _OK != retval ) return retval; return MiscInitPorts( ps, portBase ); } /** free used memory (if necessary) * restore the parallel port settings and release the port */ static int ptdrvClose( pScanData ps ) { DBG( DBG_HIGH, "ptdrvClose()\n" ); if( NULL == ps ) return _E_NULLPTR; /* * should be cleared by ioctl(close) */ if ( NULL != ps->driverbuf ) { DBG( DBG_LOW, "*** cleanup buffers ***\n" ); _VFREE( ps->driverbuf ); ps->driverbuf = NULL; } if ( NULL != ps->Shade.pHilight ) { _VFREE( ps->Shade.pHilight ); ps->Shade.pHilight = NULL; } /* * restore/release port resources... */ MiscRestorePort( ps ); MiscReleasePort( ps ); return _OK; } /** will be called during OPEN_DEVICE ioctl call */ static int ptdrvOpenDevice( pScanData ps ) { int retval, iobase; UShort asic; UChar lastStat; UShort lastMode; ULong devno; #ifdef __KERNEL__ UShort flags; struct pardevice *pd; struct parport *pp; ProcDirDef procDir; #else int pd; #endif /* * push some values from the struct */ #ifdef __KERNEL__ flags = ps->flags; pp = ps->pp; procDir = ps->procDir; #endif pd = ps->pardev; iobase = ps->sCaps.wIOBase; asic = ps->sCaps.AsicID; lastStat = ps->bLastLampStatus; lastMode = ps->IO.lastPortMode; devno = ps->devno; /* * reinit the show */ ptdrvStopLampTimer( ps ); MiscReinitStruct ( ps ); /* * pop the val(s) */ #ifdef __KERNEL__ ps->flags = flags; ps->pp = pp; ps->procDir = procDir; #endif ps->pardev = pd; ps->bLastLampStatus = lastStat; ps->IO.lastPortMode = lastMode; ps->devno = devno; #ifdef __KERNEL__ if( _TRUE == slowIO[devno] ) { DBG( DBG_LOW, "Using slow I/O\n" ); ps->IO.slowIO = _TRUE; ps->IO.fnOut = IOOutDelayed; ps->IO.fnIn = IOInDelayed; } else { DBG( DBG_LOW, "Using fast I/O\n" ); ps->IO.slowIO = _FALSE; ps->IO.fnOut = IOOut; ps->IO.fnIn = IOIn; } #endif ps->ModelOverride = mov[devno]; ps->warmup = warmup[devno]; ps->lampoff = lampoff[devno]; ps->lOffonEnd = lOffonEnd[devno]; ps->IO.forceMode = forceMode[devno]; /* * try to find scanner again */ retval = ptdrvOpen( ps, iobase ); if( _OK == retval ) retval = DetectScanner( ps, asic ); else ptdrvStartLampTimer( ps ); return retval; } /*............................................................................. * initialize the driver * allocate memory for the ScanData structure and do some presets */ static int ptdrvInit( int devno ) { int retval; pScanData ps; DBG( DBG_HIGH, "ptdrvInit(%u)\n", devno ); if( devno >= _MAX_PTDEVS ) return _E_NO_DEV; /* * allocate memory for our large ScanData-structure */ ps = MiscAllocAndInitStruct(); if( NULL == ps ) { return _E_ALLOC; } #ifdef __KERNEL__ if( _TRUE == slowIO[devno] ) { DBG( DBG_LOW, "Using slow I/O\n" ); ps->IO.slowIO = _TRUE; ps->IO.fnOut = IOOutDelayed; ps->IO.fnIn = IOInDelayed; } else { DBG( DBG_LOW, "Using fast I/O\n" ); ps->IO.slowIO = _FALSE; ps->IO.fnOut = IOOut; ps->IO.fnIn = IOIn; } #endif ps->ModelOverride = mov[devno]; ps->warmup = warmup[devno]; ps->lampoff = lampoff[devno]; ps->lOffonEnd = lOffonEnd[devno]; ps->IO.forceMode = forceMode[devno]; ps->devno = devno; /* assign it right here, to allow correct shutdown */ PtDrvDevices[devno] = ps; /* * try to register the port */ retval = MiscRegisterPort( ps, port[devno] ); if( _OK == retval ) { retval = ptdrvOpen( ps, port[devno] ); } /* * try to detect a scanner... */ if( _OK == retval ) { retval = DetectScanner( ps, 0 ); /* do this here before releasing the port */ if( _OK == retval ) { ptDrvSwitchLampOn( ps ); } ptdrvClose( ps ); } if( _OK == retval ) { #ifdef __KERNEL__ _PRINT( "pt_drv%u: %s found on port 0x%04x\n", devno, MiscGetModelName(ps->sCaps.Model), ps->IO.pbSppDataPort ); #else DBG( DBG_LOW, "pt_drv%u: %s found\n", devno, MiscGetModelName(ps->sCaps.Model)); #endif /* * initialize the timespan timer */ MiscStartTimer( &toTimer[ps->devno], (_SECOND * ps->warmup)); if( 0 == ps->lampoff ) #ifdef __KERNEL__ _PRINT( #else DBG( DBG_LOW, #endif "pt_drv%u: Lamp-Timer switched off.\n", devno ); else { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_LOW, #endif "pt_drv%u: Lamp-Timer set to %u seconds.\n", devno, ps->lampoff ); } #ifdef __KERNEL__ _PRINT( #else DBG( DBG_LOW, #endif "pt_drv%u: WarmUp period set to %u seconds.\n", devno, ps->warmup ); if( 0 == ps->lOffonEnd ) { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_LOW, #endif "pt_drv%u: Lamp untouched on driver unload.\n", devno ); } else { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_LOW, #endif "pt_drv%u: Lamp switch-off on driver unload.\n", devno ); } ptdrvStartLampTimer( ps ); } return retval; } /*............................................................................. * shutdown the driver: * switch the lights out * stop the motor * free memory */ static int ptdrvShutdown( pScanData ps ) { int devno; DBG( DBG_HIGH, "ptdrvShutdown()\n" ); if( NULL == ps ) return _E_NULLPTR; devno = ps->devno; DBG( DBG_HIGH, "cleanup device %u\n", devno ); if( _NO_BASE != ps->sCaps.wIOBase ) { ptdrvStopLampTimer( ps ); if( _OK == MiscClaimPort(ps)) { ps->PutToIdleMode( ps ); if( 0 != ps->lOffonEnd ) { if( _IS_ASIC98(ps->sCaps.AsicID)) { ps->AsicReg.RD_ScanControl &= ~_SCAN_LAMPS_ON; } else { ps->AsicReg.RD_ScanControl &= ~_SCAN_LAMP_ON; } IOCmdRegisterToScanner( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); } } MiscReleasePort( ps ); } /* unregister the driver */ MiscUnregisterPort( ps ); _KFREE( ps ); if( devno < _MAX_PTDEVS ) PtDrvDevices[devno] = NULL; return _OK; } /*............................................................................. * the IOCTL interface */ static int ptdrvIoctl( pScanData ps, UInt cmd, pVoid arg ) { UShort dir; UShort version; UInt size; ULong argVal; int cancel; int retval; /* * do the preliminary stuff here */ if( NULL == ps ) return _E_NULLPTR; retval = _OK; dir = _IOC_DIR(cmd); size = _IOC_SIZE(cmd); if ((_IOC_WRITE == dir) && size && (size <= sizeof(ULong))) { if (( retval = getUserPtr( arg, &argVal, size))) { DBG( DBG_HIGH, "ioctl() failed - result = %i\n", retval ); return retval; } } switch( cmd ) { /* open */ case _PTDRV_OPEN_DEVICE: DBG( DBG_LOW, "ioctl(_PTDRV_OPEN_DEVICE)\n" ); if (copy_from_user(&version, arg, sizeof(UShort))) return _E_FAULT; if( _PTDRV_IOCTL_VERSION != version ) { DBG( DBG_HIGH, "Version mismatch: Backend=0x%04X(0x%04X)", version, _PTDRV_IOCTL_VERSION ); return _E_VERSION; } retval = ptdrvOpenDevice( ps ); break; /* close */ case _PTDRV_CLOSE_DEVICE: DBG( DBG_LOW, "ioctl(_PTDRV_CLOSE_DEVICE)\n" ); if ( NULL != ps->driverbuf ) { DBG( DBG_LOW, "*** cleanup buffers ***\n" ); _VFREE( ps->driverbuf ); ps->driverbuf = NULL; } if ( NULL != ps->Shade.pHilight ) { _VFREE( ps->Shade.pHilight ); ps->Shade.pHilight = NULL; } ps->PutToIdleMode( ps ); ptdrvStartLampTimer( ps ); break; /* get caps - no scanner connection necessary */ case _PTDRV_GET_CAPABILITIES: DBG( DBG_LOW, "ioctl(_PTDRV_GET_CAPABILITES)\n" ); return putUserPtr( &ps->sCaps, arg, size); break; /* get lens-info - no scanner connection necessary */ case _PTDRV_GET_LENSINFO: DBG( DBG_LOW, "ioctl(_PTDRV_GET_LENSINFO)\n" ); return putUserPtr( &ps->LensInf, arg, size); break; /* put the image info - no scanner connection necessary */ case _PTDRV_PUT_IMAGEINFO: { short tmpcx, tmpcy; ImgDef img; DBG( DBG_LOW, "ioctl(_PTDRV_PUT_IMAGEINFO)\n" ); if (copy_from_user( &img, (pImgDef)arg, size)) return _E_FAULT; tmpcx = (short)img.crArea.cx; tmpcy = (short)img.crArea.cy; if(( 0 >= tmpcx ) || ( 0 >= tmpcy )) { DBG( DBG_LOW, "CX or CY <= 0!!\n" ); return _E_INVALID; } _ASSERT( ps->GetImageInfo ); ps->GetImageInfo( ps, &img ); } break; /* get crop area - no scanner connection necessary */ case _PTDRV_GET_CROPINFO: { CropInfo outBuffer; pCropInfo pcInf = &outBuffer; DBG( DBG_LOW, "ioctl(_PTDRV_GET_CROPINFO)\n" ); memset( pcInf, 0, sizeof(CropInfo)); pcInf->dwPixelsPerLine = ps->DataInf.dwAppPixelsPerLine; pcInf->dwBytesPerLine = ps->DataInf.dwAppBytesPerLine; pcInf->dwLinesPerArea = ps->DataInf.dwAppLinesPerArea; return putUserPtr( pcInf, arg, size ); } break; /* adjust the driver settings */ case _PTDRV_ADJUST: { PPAdjDef adj; DBG( DBG_LOW, "ioctl(_PTDRV_ADJUST)\n" ); if (copy_from_user(&adj, (pPPAdjDef)arg, sizeof(PPAdjDef))) return _E_FAULT; DBG( DBG_LOW, "Adjusting device %u\n", ps->devno ); DBG( DBG_LOW, "warmup: %i\n", adj.warmup ); DBG( DBG_LOW, "lampOff: %i\n", adj.lampOff ); DBG( DBG_LOW, "lampOffOnEnd: %i\n", adj.lampOffOnEnd ); if( ps->devno < _MAX_PTDEVS ) { if( adj.warmup >= 0 ) { warmup[ps->devno] = adj.warmup; ps->warmup = adj.warmup; } if( adj.lampOff >= 0 ) { lampoff[ps->devno] = adj.lampOff; ps->lampoff = adj.lampOff; } if( adj.lampOffOnEnd >= 0 ) { lOffonEnd[ps->devno] = adj.lampOffOnEnd; ps->lOffonEnd = adj.lampOffOnEnd; } } } break; /* set a specific map (r,g,b or gray) */ case _PTDRV_SETMAP: { int i, x_len; MapDef map; DBG( DBG_LOW, "ioctl(_PTDRV_SETMAP)\n" ); if (copy_from_user( &map, (pMapDef)arg, sizeof(MapDef))) return _E_FAULT; DBG( DBG_LOW, "maplen=%u, mapid=%u, addr=0x%08lx\n", map.len, map.map_id, (u_long)map.map ); x_len = 256; if( _IS_ASIC98(ps->sCaps.AsicID)) x_len = 4096; /* check for 0 pointer and len */ if((NULL == map.map) || (x_len != map.len)) { DBG( DBG_LOW, "map pointer == 0, or map len invalid!!\n" ); return _E_INVALID; } if( _MAP_MASTER == map.map_id ) { for( i = 0; i < 3; i++ ) { if (copy_from_user((pVoid)&ps->a_bMapTable[x_len * i], map.map, x_len )) { return _E_FAULT; } } } else { u_long idx = 0; if( map.map_id == _MAP_GREEN ) idx = 1; if( map.map_id == _MAP_BLUE ) idx = 2; if (copy_from_user((pVoid)&ps->a_bMapTable[x_len * idx], map.map, x_len )) { return _E_FAULT; } } /* here we adjust the maps according to * the brightness and contrast settings */ MapAdjust( ps, map.map_id ); } break; /* set environment - no scanner connection necessary */ case _PTDRV_SET_ENV: { ScanInfo sInf; DBG( DBG_LOW, "ioctl(_PTDRV_SET_ENV)\n" ); if (copy_from_user(&sInf, (pScanInfo)arg, sizeof(ScanInfo))) return _E_FAULT; /* * to make the OpticPro 4800P work, we need to invert the * Inverse flag */ if( _ASIC_IS_96001 == ps->sCaps.AsicID ) { if( SCANDEF_Inverse & sInf.ImgDef.dwFlag ) sInf.ImgDef.dwFlag &= ~SCANDEF_Inverse; else sInf.ImgDef.dwFlag |= SCANDEF_Inverse; } _ASSERT( ps->SetupScanSettings ); retval = ps->SetupScanSettings( ps, &sInf ); /* CHANGE preset map here */ if( _OK == retval ) { MapInitialize ( ps ); MapSetupDither( ps ); ps->DataInf.dwVxdFlag |= _VF_ENVIRONMENT_READY; if (copy_to_user((pScanInfo)arg, &sInf, sizeof(ScanInfo))) return _E_FAULT; } } break; /* start scan */ case _PTDRV_START_SCAN: { StartScan outBuffer; pStartScan pstart = (pStartScan)&outBuffer; DBG( DBG_LOW, "ioctl(_PTDRV_START_SCAN)\n" ); retval = IOIsReadyForScan( ps ); if( _OK == retval ) { ps->dwDitherIndex = 0; ps->fScanningStatus = _TRUE; pstart->dwBytesPerLine = ps->DataInf.dwAppBytesPerLine; pstart->dwLinesPerScan = ps->DataInf.dwAppLinesPerArea; pstart->dwFlag = ps->DataInf.dwScanFlag; ps->DataInf.dwVxdFlag |= _VF_FIRSTSCANLINE; ps->DataInf.dwScanFlag&=~(_SCANNER_SCANNING|_SCANNER_PAPEROUT); if (copy_to_user((pStartScan)arg, pstart, sizeof(StartScan))) return _E_FAULT; } } break; /* stop scan */ case _PTDRV_STOP_SCAN: DBG( DBG_LOW, "ioctl(_PTDRV_STOP_SCAN)\n" ); if (copy_from_user(&cancel, arg, sizeof(short))) return _E_FAULT; /* we may use this to abort scanning! */ ps->fScanningStatus = _FALSE; /* when using this to cancel, then that's all */ if( _FALSE == cancel ) { MotorToHomePosition( ps ); ps->DataInf.dwAppLinesPerArea = 0; ps->DataInf.dwScanFlag &= ~_SCANNER_SCANNING; /* if environment was never set */ if (!(ps->DataInf.dwVxdFlag & _VF_ENVIRONMENT_READY)) retval = _E_SEQUENCE; ps->DataInf.dwVxdFlag &= ~_VF_ENVIRONMENT_READY; } else { DBG( DBG_LOW, "CANCEL Mode set\n" ); } retval = putUserVal(retval, arg, size); break; /* read the flag status register, when reading the action button, you must * only do this call and none of the other ioctl's * like open, etc or it will always show up as "1" */ case _PTDRV_ACTION_BUTTON: DBG( DBG_LOW, "ioctl(_PTDRV_ACTION_BUTTON)\n" ); IODataRegisterFromScanner( ps, ps->RegStatus ); retval = putUserVal( argVal, arg, size ); break; default: retval = _E_NOSUPP; break; } return retval; } /*............................................................................. * read the data */ static int ptdrvRead( pScanData ps, pUChar buffer, int count ) { pUChar scaleBuf; ULong dwLinesRead = 0; int retval = _OK; #ifdef _ASIC_98001_SIM #ifdef __KERNEL__ _PRINT( #else DBG( DBG_LOW, #endif "pt_drv : Software-Emulation active, can't read!\n" ); return _E_INVALID; #endif if((NULL == buffer) || (NULL == ps)) { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "pt_drv : Internal NULL-pointer!\n" ); return _E_NULLPTR; } if( 0 == count ) { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "pt_drv%u: reading 0 bytes makes no sense!\n", ps->devno ); return _E_INVALID; } if( _FALSE == ps->fScanningStatus ) return _E_ABORT; /* * has the environment been set ? * this should prevent the driver from causing a seg-fault * when using the cat /dev/pt_drv command! */ if (!(ps->DataInf.dwVxdFlag & _VF_ENVIRONMENT_READY)) { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "pt_drv%u: Cannot read, driver not initialized!\n",ps->devno); return _E_SEQUENCE; } /* * get some memory */ ps->Scan.bp.pMonoBuf = _KALLOC( ps->DataInf.dwAppPhyBytesPerLine, GFP_KERNEL); if ( NULL == ps->Scan.bp.pMonoBuf ) { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "pt_drv%u: Not enough memory available!\n", ps->devno ); return _E_ALLOC; } /* if we have to do some scaling, we need another buffer... */ if( ps->DataInf.XYRatio > 1000 ) { scaleBuf = _KALLOC( ps->DataInf.dwAppPhyBytesPerLine, GFP_KERNEL); if ( NULL == scaleBuf ) { _KFREE( ps->Scan.bp.pMonoBuf ); #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "pt_drv%u: Not enough memory available!\n", ps->devno ); return _E_ALLOC; } } else { scaleBuf = NULL; } DBG( DBG_LOW, "PtDrvRead(%u bytes)*****************\n", count ); DBG( DBG_LOW, "MonoBuf = 0x%08lx[%u], scaleBuf = 0x%lx\n", (unsigned long)ps->Scan.bp.pMonoBuf, ps->DataInf.dwAppPhyBytesPerLine, (unsigned long)scaleBuf ); /* * in case of a previous problem, move the sensor back home */ MotorToHomePosition( ps ); if( _FALSE == ps->fScanningStatus ) { retval = _E_ABORT; goto ReadFinished; } dwLinesRead = 0; /* * first of all calibrate the show */ ps->bMoveDataOutFlag = _DataInNormalState; ps->fHalfStepTableFlag = _FALSE; ps->fReshaded = _FALSE; ps->fScanningStatus = _TRUE; if( _ASIC_IS_98003 == ps->sCaps.AsicID ) ps->Scan.fRefreshState = _FALSE; else ps->Scan.fRefreshState = _TRUE; ptdrvLampWarmup( ps ); if( _FALSE == ps->fScanningStatus ) { retval = _E_ABORT; goto ReadFinished; } retval = ps->Calibration( ps ); if( _OK != retval ) { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "pt_drv%u: calibration failed, result = %i\n", ps->devno, retval ); goto ReadFinished; } if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->OpenScanPath( ps ); MotorP98003ForceToLeaveHomePos( ps ); } _ASSERT(ps->SetupScanningCondition); ps->SetupScanningCondition(ps); if( _ASIC_IS_98003 != ps->sCaps.AsicID ) { ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE ); IOSetToMotorRegister( ps ); } else { ps->WaitForPositionY( ps ); _DODELAY( 70 ); ps->Scan.bOldScanState = IOGetScanState( ps, _TRUE ) & _SCANSTATE_MASK; } ps->DataInf.dwScanFlag |= _SCANNER_SCANNING; if( _FALSE == ps->fScanningStatus ) { DBG( DBG_HIGH, "read aborted!\n" ); retval = _E_ABORT; goto ReadFinished; } /* * now get the picture data */ DBG( DBG_HIGH, "dwAppLinesPerArea = %d\n", ps->DataInf.dwAppLinesPerArea); DBG( DBG_HIGH, "dwAppBytesPerLine = %d\n", ps->DataInf.dwAppBytesPerLine); /* HEINER: A3I ps->bMoveDataOutFlag = _DataFromStopState; */ if ( 0 != ps->DataInf.dwAppLinesPerArea ) { ps->Scan.dwLinesToRead = count / ps->DataInf.dwAppBytesPerLine; if( ps->Scan.dwLinesToRead ) { DBG( DBG_HIGH, "dwLinesToRead = %d\n", ps->Scan.dwLinesToRead ); if( ps->Scan.dwLinesToRead > ps->DataInf.dwAppLinesPerArea ) ps->Scan.dwLinesToRead = ps->DataInf.dwAppLinesPerArea; ps->DataInf.dwAppLinesPerArea -= ps->Scan.dwLinesToRead; if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) buffer += ((ps->Scan.dwLinesToRead - 1) * ps->DataInf.dwAppBytesPerLine); if (ps->DataInf.dwVxdFlag & _VF_DATATOUSERBUFFER) ps->DataInf.pCurrentBuffer = ps->Scan.bp.pMonoBuf; while(ps->fScanningStatus && ps->Scan.dwLinesToRead) { _ASSERT(ps->ReadOneImageLine); if (!ps->ReadOneImageLine(ps)) { ps->fScanningStatus = _FALSE; DBG( DBG_HIGH, "ReadOneImageLine() failed at line %u!\n", dwLinesRead ); break; } /* * as we might scan images that exceed the CCD-capabilities * in x-resolution, we have to enlarge the line data * i.e.: scanning at 1200dpi generates on a P9636 600 dpi in * x-direction but 1200dpi in y-direction... */ if( NULL != scaleBuf ) { ScaleX( ps, ps->Scan.bp.pMonoBuf, scaleBuf ); if (copy_to_user( buffer, scaleBuf, ps->DataInf.dwAppPhyBytesPerLine)) { return _E_FAULT; } } else { if (copy_to_user( buffer, ps->Scan.bp.pMonoBuf, ps->DataInf.dwAppPhyBytesPerLine)) { return _E_FAULT; } } buffer += ps->Scan.lBufferAdjust; dwLinesRead++; ps->Scan.dwLinesToRead--; /* needed, esp. to avoid freezing the system in SPP mode */ #ifdef __KERNEL__ schedule(); /*#else sched_yield(); */ #endif } if (ps->fScanningStatus) { if( _IS_ASIC96(ps->sCaps.AsicID)) MotorP96SetSpeedToStopProc(ps); } else { if (ps->DataInf.dwScanFlag & (SCANDEF_StopWhenPaperOut | SCANDEF_UnlimitLength)) { ps->DataInf.dwAppLinesPerArea = 0; } else { if (ps->DataInf.dwScanFlag & SCANDEF_BmpStyle) buffer -= (ps->DataInf.dwAppBytesPerLine * (ps->Scan.dwLinesToRead - 1)); memset( buffer, 0xff, ps->Scan.dwLinesToRead * ps->DataInf.dwAppBytesPerLine ); dwLinesRead += ps->Scan.dwLinesToRead; } } } else { retval = _E_INTERNAL; } } if( _FALSE == ps->fScanningStatus ) { DBG( DBG_HIGH, "read aborted!\n" ); retval = _E_ABORT; } ReadFinished: if( _ASIC_IS_98003 == ps->sCaps.AsicID ) ps->CloseScanPath( ps ); if( NULL != ps->Scan.bp.pMonoBuf ) _KFREE( ps->Scan.bp.pMonoBuf ); if( NULL != scaleBuf ) _KFREE( scaleBuf ); /* * on success return number of bytes red */ if ( _OK == retval ) return (ps->DataInf.dwAppPhyBytesPerLine * dwLinesRead); return retval; } /*************************** the module interface ****************************/ #ifdef __KERNEL__ /* the kernel module interface */ /* Designed to be used as a module */ #ifdef MODULE /*............................................................................. * gets called upon module initialization */ #ifdef LINUX_26 static int __init ptdrv_init( void ) #else int init_module( void ) #endif { UInt devCount; UInt i; int retval = _OK; int result = _OK; #if (defined(CONFIG_DEVFS_FS) && !defined(DEVFS_26_STYLE)) char controlname[24]; #endif # ifdef LINUX_26 char devname[20]; #endif DBG( DBG_HIGH, "*********************************************\n" ); DBG( DBG_HIGH, "pt_drv: init_module()\n" ); #if (defined(CONFIG_DEVFS_FS) && !defined(DEVFS_26_STYLE)) devfs_handle = devfs_mk_dir(NULL, "scanner", NULL); if( devfs_register_chrdev(_PTDRV_MAJOR, _DRV_NAME, &pt_drv_fops)) { #else if( register_chrdev(_PTDRV_MAJOR, _DRV_NAME, &pt_drv_fops)) { #endif _PRINT(KERN_INFO "pt_drv: unable to get major %d for pt_drv devices\n", _PTDRV_MAJOR); return -EIO; } printk( KERN_INFO "pt_drv : driver version "_PTDRV_VERSTR"\n" ); #if !defined (CONFIG_DEVFS_FS) && defined (LINUX_26) ptdrv_class = class_create(THIS_MODULE, "scanner"); if (IS_ERR(ptdrv_class)) goto out_devfs; #endif /* register the proc_fs */ ProcFsInitialize(); /* go through the list of defined ports and try to find a device */ devCount = 0; for( i = 0; i < _MAX_PTDEVS; i++ ) { if( 0 != port[i] ) { result = ptdrvInit( i ); if ( _OK == result ) { PtDrvDevices[i]->flags |= _PTDRV_INITALIZED; #ifdef CONFIG_DEVFS_FS # ifndef DEVFS_26_STYLE sprintf( controlname, "scanner/pt_drv%d", devCount ); devfs_register( NULL, controlname, DEVFS_FL_DEFAULT, _PTDRV_MAJOR, 0, (S_IFCHR | S_IRUGO | S_IWUGO | S_IFCHR), &pt_drv_fops, NULL ); # else /* DEVFS_26_STYLE */ devfs_mk_cdev(MKDEV(_PTDRV_MAJOR, devCount), (S_IFCHR | S_IRUGO | S_IWUGO | S_IFCHR), "scanner/pt_drv%d", devCount); # endif #else # ifdef LINUX_26 sprintf(devname, "pt_drv%d", devCount); CLASS_DEV_CREATE(ptdrv_class, MKDEV(_PTDRV_MAJOR, devCount), NULL, devname); # endif /* LINUX_26 */ #endif /* CONFIG_DEVFS_FS */ ProcFsRegisterDevice( PtDrvDevices[i] ); devCount++; } else { retval = result; ptdrvShutdown( PtDrvDevices[i] ); PtDrvDevices[i] = NULL; } } } /* * if something went wrong, shutdown all... */ if( devCount == 0 ) { #if !defined (CONFIG_DEVFS_FS) && defined (LINUX_26) out_devfs: class_destroy(ptdrv_class); #endif #if (defined(CONFIG_DEVFS_FS) && !defined(DEVFS_26_STYLE)) devfs_unregister_chrdev( _PTDRV_MAJOR, _DRV_NAME ); #else unregister_chrdev( _PTDRV_MAJOR, _DRV_NAME ); #endif ProcFsShutdown(); #ifdef __KERNEL__ _PRINT( KERN_INFO "pt_drv : no device(s) detected, (%i)\n", retval ); #endif } else { DBG( DBG_HIGH, "pt_drv : init done, %u device(s) found\n", devCount ); retval = _OK; } DBG( DBG_HIGH, "---------------------------------------------\n" ); deviceScanning = _FALSE; return retval; } /*............................................................................. * cleanup the show */ #ifdef LINUX_26 static void __exit ptdrv_exit( void ) #else void cleanup_module( void ) #endif { UInt i; pScanData ps; #if (defined(CONFIG_DEVFS_FS) && !defined(DEVFS_26_STYLE)) char controlname[24]; devfs_handle_t master; #endif DBG( DBG_HIGH, "pt_drv: cleanup_module()\n" ); for ( i = 0; i < _MAX_PTDEVS; i++ ) { ps = PtDrvDevices[i]; PtDrvDevices[i] = NULL; if ( NULL != ps ) { #ifdef CONFIG_DEVFS_FS # ifndef DEVFS_26_STYLE sprintf( controlname, "scanner/pt_drv%d", i ); master = devfs_find_handle( NULL,controlname, 0, 0, DEVFS_SPECIAL_CHR, 0 ); devfs_unregister( master ); # else devfs_remove("scanner/pt_drv%d", i); # endif #else # ifdef LINUX_26 CLASS_DEV_DESTROY(ptdrv_class, MKDEV(_PTDRV_MAJOR, i)); # endif /* LINUX_26 */ #endif /* CONFIG_DEVFS_FS */ ptdrvShutdown( ps ); ProcFsUnregisterDevice( ps ); } } #if (defined(CONFIG_DEVFS_FS) && !defined(DEVFS_26_STYLE)) devfs_unregister_chrdev( _PTDRV_MAJOR, _DRV_NAME ); #else unregister_chrdev( _PTDRV_MAJOR, _DRV_NAME ); #endif ProcFsShutdown(); #if !defined (CONFIG_DEVFS_FS) && defined (LINUX_26) class_destroy(ptdrv_class); #endif DBG( DBG_HIGH, "pt_drv: cleanup done.\n" ); DBG( DBG_HIGH, "*********************************************\n" ); } #ifdef LINUX_26 module_init(ptdrv_init); module_exit(ptdrv_exit); #endif #endif /*MODULE*/ /*............................................................................. * device open... */ static int pt_drv_open(struct inode *inode, struct file *file) { pScanData ps; DBG( DBG_HIGH, "pt_drv_open()\n" ); ps = get_pt_from_inode(inode); if ( NULL == ps ) { return(-ENXIO); } /* device not found ? */ if (!(ps->flags & _PTDRV_INITALIZED)) { return(-ENXIO); } /* device is busy ? */ if (ps->flags & _PTDRV_OPEN) { return(-EBUSY); } #ifdef LINUX_26 if (!try_module_get(THIS_MODULE)) return -EAGAIN; #else MOD_INC_USE_COUNT; #endif ps->flags |= _PTDRV_OPEN; return _OK; } /*............................................................................. * device close... */ static CLOSETYPE pt_drv_close(struct inode * inode, struct file * file) { pScanData ps; DBG( DBG_HIGH, "pt_drv_close()\n" ); if ((ps = get_pt_from_inode(inode)) ) { ptdrvClose( ps ); ps->flags &= ~_PTDRV_OPEN; #ifdef LINUX_26 module_put(THIS_MODULE); #else MOD_DEC_USE_COUNT; #endif CLOSERETURN(0); } else { DBG( DBG_HIGH, "pt_drv: - close failed!\n" ); CLOSERETURN(-ENXIO); } } /*............................................................................. * read data from device */ #ifdef LINUX_20 static int pt_drv_read(struct inode *inode, struct file *file, char *buffer, int count) { int result; pScanData ps; if ( !(ps = get_pt_from_inode(inode))) return(-ENXIO); #else static ssize_t pt_drv_read( struct file *file, char *buffer, size_t count, loff_t *tmp ) { int result; pScanData ps; if ( !(ps = get_pt_from_inode(file->f_dentry->d_inode)) ) return(-ENXIO); #endif if ((result = verify_area_20(VERIFY_WRITE, buffer, count))) return result; /* * as the driver contains some global vars, it is not * possible to scan simultaenously with two or more devices */ if( _TRUE == deviceScanning ) { printk( KERN_INFO "pt_drv: device %u busy!!!\n", ps->devno ); return(-EBUSY); } deviceScanning = _TRUE; result = ptdrvRead( ps, buffer, count ); deviceScanning = _FALSE; return result; } /*............................................................................. * writing makes no sense */ #ifdef LINUX_20 static int pt_drv_write(struct inode * inode, struct file * file, const char * buffer, int count) { return -EPERM; } #else static ssize_t pt_drv_write( struct file * file,const char * buffer, size_t tmp,loff_t* count) { return -EPERM; } #endif /*............................................................................. * the ioctl interface */ #ifdef NOLOCK_IOCTL static long pt_drv_ioctl( struct file *file, UInt cmd, unsigned long arg ) { pScanData ps; if ( !(ps = get_pt_from_inode(file->f_dentry->d_inode)) ) return(-ENXIO); return ptdrvIoctl( ps, cmd, (pVoid)arg); } #else static int pt_drv_ioctl( struct inode *inode, struct file *file, UInt cmd, unsigned long arg ) { pScanData ps; if ( !(ps = get_pt_from_inode(inode)) ) return(-ENXIO); return ptdrvIoctl( ps, cmd, (pVoid)arg); } #endif #else /* the user-mode interface */ /*............................................................................. * here we only have wrapper functions */ static int PtDrvInit( const char *dev_name, UShort model_override ) { int fd; int result = _OK; if( _TRUE == PtDrvInitialized ) return _OK; result = sanei_pp_open( dev_name, &fd ); if( SANE_STATUS_GOOD != result ) return result; port[0] = fd; mov[0] = model_override; result = ptdrvInit( 0 ); if( _OK == result ) { PtDrvInitialized = _TRUE; } else { ptdrvShutdown( PtDrvDevices[0] ); } return result; } static int PtDrvShutdown( void ) { int result; if( _FALSE == PtDrvInitialized ) return _E_NOT_INIT; result = ptdrvShutdown( PtDrvDevices[0] ); PtDrvInitialized = _FALSE; return result; } static int PtDrvOpen( void ) { if( _FALSE == PtDrvInitialized ) return _E_NOT_INIT; return _OK; } static int PtDrvClose( void ) { if( _FALSE == PtDrvInitialized ) return _E_NOT_INIT; return ptdrvClose( PtDrvDevices[0] ); } static int PtDrvIoctl( UInt cmd, pVoid arg ) { if( _FALSE == PtDrvInitialized ) return _E_NOT_INIT; return ptdrvIoctl( PtDrvDevices[0], cmd, arg); } static int PtDrvRead ( pUChar buffer, int count ) { if( _FALSE == PtDrvInitialized ) return _E_NOT_INIT; return ptdrvRead( PtDrvDevices[0], buffer, count ); } #endif /* guard __KERNEL__ */ /* END PLUSTEK-PP_PTDRV.C ...................................................*/ sane-backends-1.0.27/backend/kvs1025_opt.c0000664000175000017500000013215612617742237014775 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. */ /* sane - Scanner Access Now Easy. Panasonic KV-S1020C / KV-S1025C USB scanners. */ #define DEBUG_DECLARE_ONLY #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "kvs1025.h" #include "kvs1025_low.h" #include "../include/sane/sanei_debug.h" /* Option lists */ static SANE_String_Const go_scan_mode_list[] = { SANE_I18N ("bw"), SANE_I18N ("halftone"), SANE_I18N ("gray"), SANE_I18N ("color"), NULL }; /* static int go_scan_mode_val[] = { 0x00, 0x01, 0x02, 0x05 };*/ static const SANE_Word go_resolutions_list[] = { 11, /* list size */ 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600 }; /* List of scan sources */ static SANE_String_Const go_scan_source_list[] = { SANE_I18N ("adf"), SANE_I18N ("fb"), NULL }; static const int go_scan_source_val[] = { 0, 0x1 }; /* List of feeder modes */ static SANE_String_Const go_feeder_mode_list[] = { SANE_I18N ("single"), SANE_I18N ("continuous"), NULL }; static const int go_feeder_mode_val[] = { 0x00, 0xff }; /* List of manual feed mode */ static SANE_String_Const go_manual_feed_list[] = { SANE_I18N ("off"), SANE_I18N ("wait_doc"), SANE_I18N ("wait_key"), NULL }; static const int go_manual_feed_val[] = { 0x00, 0x01, 0x02 }; /* List of paper sizes */ static SANE_String_Const go_paper_list[] = { SANE_I18N ("user_def"), SANE_I18N ("business_card"), SANE_I18N ("Check"), /*SANE_I18N ("A3"), */ SANE_I18N ("A4"), SANE_I18N ("A5"), SANE_I18N ("A6"), SANE_I18N ("Letter"), /*SANE_I18N ("Double letter 11x17 in"), SANE_I18N ("B4"), */ SANE_I18N ("B5"), SANE_I18N ("B6"), SANE_I18N ("Legal"), NULL }; static const int go_paper_val[] = { 0x00, 0x01, 0x02, /*0x03, *//* A3 : not supported */ 0x04, 0x05, 0x06, 0x07, /*0x09, 0x0C, *//* Dbl letter and B4 : not supported */ 0x0D, 0x0E, 0x0F }; static const KV_PAPER_SIZE go_paper_sizes[] = { {210, 297}, /* User defined, default=A4 */ {54, 90}, /* Business card */ {80, 170}, /* Check (China business) */ /*{297, 420}, *//* A3 */ {210, 297}, /* A4 */ {148, 210}, /* A5 */ {105, 148}, /* A6 */ {216, 280}, /* US Letter 8.5 x 11 in */ /*{280, 432}, *//* Double Letter 11 x 17 in */ /*{250, 353}, *//* B4 */ {176, 250}, /* B5 */ {125, 176}, /* B6 */ {216, 356} /* US Legal */ }; static const int default_paper_size_idx = 3; /* A4 */ static const int go_paper_max_width = 216; /* US letter */ /* Lists of supported halftone. They are only valid with * for the Black&White mode. */ static SANE_String_Const go_halftone_pattern_list[] = { SANE_I18N ("bayer_64"), SANE_I18N ("bayer_16"), SANE_I18N ("halftone_32"), SANE_I18N ("halftone_64"), SANE_I18N ("diffusion"), NULL }; static const int go_halftone_pattern_val[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; /* List of automatic threshold options */ static SANE_String_Const go_automatic_threshold_list[] = { SANE_I18N ("normal"), SANE_I18N ("light"), SANE_I18N ("dark"), NULL }; static const int go_automatic_threshold_val[] = { 0, 0x11, 0x1f }; /* List of white level base. */ static SANE_String_Const go_white_level_list[] = { SANE_I18N ("From scanner"), SANE_I18N ("From paper"), SANE_I18N ("Automatic"), NULL }; static const int go_white_level_val[] = { 0x00, 0x80, 0x81 }; /* List of noise reduction options. */ static SANE_String_Const go_noise_reduction_list[] = { SANE_I18N ("default"), "1x1", "2x2", "3x3", "4x4", "5x5", NULL }; static const int go_noise_reduction_val[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; /* List of image emphasis options, 5 steps */ static SANE_String_Const go_image_emphasis_list[] = { SANE_I18N ("smooth"), SANE_I18N ("none"), SANE_I18N ("low"), SANE_I18N ("medium"), /* default */ SANE_I18N ("high"), NULL }; static const int go_image_emphasis_val[] = { 0x14, 0x00, 0x11, 0x12, 0x13 }; /* List of gamma */ static SANE_String_Const go_gamma_list[] = { SANE_I18N ("normal"), SANE_I18N ("crt"), SANE_I18N ("linier"), NULL }; static const int go_gamma_val[] = { 0x00, 0x01, 0x02 }; /* List of lamp color dropout */ static SANE_String_Const go_lamp_list[] = { SANE_I18N ("normal"), SANE_I18N ("red"), SANE_I18N ("green"), SANE_I18N ("blue"), NULL }; static const int go_lamp_val[] = { 0x00, 0x01, 0x02, 0x03 }; static SANE_Range go_value_range = { 0, 255, 0 }; static SANE_Range go_jpeg_compression_range = { 0, 0x64, 0 }; static SANE_Range go_rotate_range = { 0, 270, 90 }; static SANE_Range go_swdespeck_range = { 0, 9, 1 }; static SANE_Range go_swskip_range = { SANE_FIX(0), SANE_FIX(100), 1 }; static const char *go_option_name[] = { "OPT_NUM_OPTS", /* General options */ "OPT_MODE_GROUP", "OPT_MODE", /* scanner modes */ "OPT_RESOLUTION", /* X and Y resolution */ "OPT_DUPLEX", /* Duplex mode */ "OPT_SCAN_SOURCE", /* Scan source, fixed to ADF */ "OPT_FEEDER_MODE", /* Feeder mode, fixed to Continous */ "OPT_LONGPAPER", /* Long paper mode */ "OPT_LENGTHCTL", /* Length control mode */ "OPT_MANUALFEED", /* Manual feed mode */ "OPT_FEED_TIMEOUT", /* Feed timeout */ "OPT_DBLFEED", /* Double feed detection mode */ "OPT_FIT_TO_PAGE", /* Scanner shrinks image to fit scanned page */ /* Geometry group */ "OPT_GEOMETRY_GROUP", "OPT_PAPER_SIZE", /* Paper size */ "OPT_LANDSCAPE", /* true if landscape */ "OPT_TL_X", /* upper left X */ "OPT_TL_Y", /* upper left Y */ "OPT_BR_X", /* bottom right X */ "OPT_BR_Y", /* bottom right Y */ "OPT_ENHANCEMENT_GROUP", "OPT_BRIGHTNESS", /* Brightness */ "OPT_CONTRAST", /* Contrast */ "OPT_AUTOMATIC_THRESHOLD", /* Binary threshold */ "OPT_HALFTONE_PATTERN", /* Halftone pattern */ "OPT_AUTOMATIC_SEPARATION", /* Automatic separation */ "OPT_WHITE_LEVEL", /* White level */ "OPT_NOISE_REDUCTION", /* Noise reduction */ "OPT_IMAGE_EMPHASIS", /* Image emphasis */ "OPT_GAMMA", /* Gamma */ "OPT_LAMP", /* Lamp -- color drop out */ "OPT_INVERSE", /* Inverse image */ "OPT_MIRROR", /* Mirror image */ "OPT_JPEG", /* JPEG Compression */ "OPT_ROTATE", /* Rotate image */ "OPT_SWDESKEW", /* Software deskew */ "OPT_SWDESPECK", /* Software despeckle */ "OPT_SWDEROTATE", /* Software detect/correct 90 deg. rotation */ "OPT_SWCROP", /* Software autocrop */ "OPT_SWSKIP", /* Software blank page skip */ /* must come last: */ "OPT_NUM_OPTIONS" }; /* Round to boundry, return 1 if value modified */ static int round_to_boundry (SANE_Word * pval, SANE_Word boundry, SANE_Word minv, SANE_Word maxv) { SANE_Word lower, upper, k, v; v = *pval; k = v / boundry; lower = k * boundry; upper = (k + 1) * boundry; if (v - lower <= upper - v) { *pval = lower; } else { *pval = upper; } if ((*pval) < minv) *pval = minv; if ((*pval) > maxv) *pval = maxv; return ((*pval) != v); } /* Returns the length of the longest string, including the terminating * character. */ static size_t max_string_size (SANE_String_Const * strings) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* Lookup a string list from one array and return its index. */ static int get_string_list_index (const SANE_String_Const * list, SANE_String_Const name) { int index; index = 0; while (list[index] != NULL) { if (strcmp (list[index], name) == 0) { return (index); } index++; } DBG (DBG_error, "System bug: option %s not found in list\n", name); return (-1); /* not found */ } /* Lookup a string list from one array and return the correnpond value. */ int get_optval_list (const PKV_DEV dev, int idx, const SANE_String_Const * str_list, const int *val_list) { int index; index = get_string_list_index (str_list, dev->val[idx].s); if (index < 0) index = 0; return val_list[index]; } /* Get device mode from device options */ KV_SCAN_MODE kv_get_mode (const PKV_DEV dev) { int i; i = get_string_list_index (go_scan_mode_list, dev->val[OPT_MODE].s); switch (i) { case 0: return SM_BINARY; case 1: return SM_DITHER; case 2: return SM_GRAYSCALE; case 3: return SM_COLOR; default: assert (0 == 1); return 0; } } void kv_calc_paper_size (const PKV_DEV dev, int *w, int *h) { int i = get_string_list_index (go_paper_list, dev->val[OPT_PAPER_SIZE].s); if (i == 0) { /* Non-standard document */ int x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); int y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); int x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); int y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); *w = x_br - x_tl; *h = y_br - y_tl; } else { if (dev->val[OPT_LANDSCAPE].s) { *h = mmToIlu (go_paper_sizes[i].width); *w = mmToIlu (go_paper_sizes[i].height); } else { *w = mmToIlu (go_paper_sizes[i].width); *h = mmToIlu (go_paper_sizes[i].height); } } } /* Get bit depth from scan mode */ int kv_get_depth (KV_SCAN_MODE mode) { switch (mode) { case SM_BINARY: case SM_DITHER: return 1; case SM_GRAYSCALE: return 8; case SM_COLOR: return 24; default: assert (0 == 1); return 0; } } const SANE_Option_Descriptor * kv_get_option_descriptor (PKV_DEV dev, SANE_Int option) { DBG (DBG_proc, "sane_get_option_descriptor: enter, option %s\n", go_option_name[option]); if ((unsigned) option >= OPT_NUM_OPTIONS) { return NULL; } DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return dev->opt + option; } /* Reset the options for that scanner. */ void kv_init_options (PKV_DEV dev) { int i; if (dev->option_set) return; DBG (DBG_proc, "kv_init_options: enter\n"); /* Pre-initialize the options. */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < OPT_NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options. */ dev->opt[OPT_NUM_OPTS].name = ""; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; /* Mode group */ dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].cap = 0; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scanner supported modes */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = max_string_size (go_scan_mode_list); dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = go_scan_mode_list; dev->val[OPT_MODE].s = strdup (""); /* will be set later */ /* X and Y resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_RESOLUTION].constraint.word_list = go_resolutions_list; dev->val[OPT_RESOLUTION].w = go_resolutions_list[3]; /* Duplex */ dev->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX; dev->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX; dev->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX; dev->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL; dev->opt[OPT_DUPLEX].unit = SANE_UNIT_NONE; dev->val[OPT_DUPLEX].w = SANE_FALSE; if (!dev->support_info.support_duplex) dev->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE; /* Scan source */ dev->opt[OPT_SCAN_SOURCE].name = SANE_NAME_SCAN_SOURCE; dev->opt[OPT_SCAN_SOURCE].title = SANE_TITLE_SCAN_SOURCE; dev->opt[OPT_SCAN_SOURCE].desc = SANE_I18N ("Sets the scan source"); dev->opt[OPT_SCAN_SOURCE].type = SANE_TYPE_STRING; dev->opt[OPT_SCAN_SOURCE].size = max_string_size (go_scan_source_list); dev->opt[OPT_SCAN_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_SCAN_SOURCE].constraint.string_list = go_scan_source_list; dev->val[OPT_SCAN_SOURCE].s = strdup (go_scan_source_list[0]); dev->opt[OPT_SCAN_SOURCE].cap &= ~SANE_CAP_SOFT_SELECT; /* for KV-S1020C / KV-S1025C, scan source is fixed to ADF */ /* Feeder mode */ dev->opt[OPT_FEEDER_MODE].name = "feeder-mode"; dev->opt[OPT_FEEDER_MODE].title = SANE_I18N ("Feeder mode"); dev->opt[OPT_FEEDER_MODE].desc = SANE_I18N ("Sets the feeding mode"); dev->opt[OPT_FEEDER_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_FEEDER_MODE].size = max_string_size (go_feeder_mode_list); dev->opt[OPT_FEEDER_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_FEEDER_MODE].constraint.string_list = go_feeder_mode_list; dev->val[OPT_FEEDER_MODE].s = strdup (go_feeder_mode_list[1]); /* Long paper */ dev->opt[OPT_LONGPAPER].name = SANE_NAME_LONGPAPER; dev->opt[OPT_LONGPAPER].title = SANE_TITLE_LONGPAPER; dev->opt[OPT_LONGPAPER].desc = SANE_I18N ("Enable/Disable long paper mode"); dev->opt[OPT_LONGPAPER].type = SANE_TYPE_BOOL; dev->opt[OPT_LONGPAPER].unit = SANE_UNIT_NONE; dev->val[OPT_LONGPAPER].w = SANE_FALSE; /* Length control */ dev->opt[OPT_LENGTHCTL].name = SANE_NAME_LENGTHCTL; dev->opt[OPT_LENGTHCTL].title = SANE_TITLE_LENGTHCTL; dev->opt[OPT_LENGTHCTL].desc = SANE_I18N ("Enable/Disable length control mode"); dev->opt[OPT_LENGTHCTL].type = SANE_TYPE_BOOL; dev->opt[OPT_LENGTHCTL].unit = SANE_UNIT_NONE; dev->val[OPT_LENGTHCTL].w = SANE_TRUE; /* Manual feed */ dev->opt[OPT_MANUALFEED].name = SANE_NAME_MANUALFEED; dev->opt[OPT_MANUALFEED].title = SANE_TITLE_MANUALFEED; dev->opt[OPT_MANUALFEED].desc = SANE_I18N ("Sets the manual feed mode"); dev->opt[OPT_MANUALFEED].type = SANE_TYPE_STRING; dev->opt[OPT_MANUALFEED].size = max_string_size (go_manual_feed_list); dev->opt[OPT_MANUALFEED].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MANUALFEED].constraint.string_list = go_manual_feed_list; dev->val[OPT_MANUALFEED].s = strdup (go_manual_feed_list[0]); /*Manual feed timeout */ dev->opt[OPT_FEED_TIMEOUT].name = SANE_NAME_FEED_TIMEOUT; dev->opt[OPT_FEED_TIMEOUT].title = SANE_TITLE_FEED_TIMEOUT; dev->opt[OPT_FEED_TIMEOUT].desc = SANE_I18N ("Sets the manual feed timeout in seconds"); dev->opt[OPT_FEED_TIMEOUT].type = SANE_TYPE_INT; dev->opt[OPT_FEED_TIMEOUT].unit = SANE_UNIT_NONE; dev->opt[OPT_FEED_TIMEOUT].size = sizeof (SANE_Int); dev->opt[OPT_FEED_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_FEED_TIMEOUT].constraint.range = &(go_value_range); dev->opt[OPT_FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE; dev->val[OPT_FEED_TIMEOUT].w = 30; /* Double feed */ dev->opt[OPT_DBLFEED].name = SANE_NAME_DBLFEED; dev->opt[OPT_DBLFEED].title = SANE_TITLE_DBLFEED; dev->opt[OPT_DBLFEED].desc = SANE_I18N ("Enable/Disable double feed detection"); dev->opt[OPT_DBLFEED].type = SANE_TYPE_BOOL; dev->opt[OPT_DBLFEED].unit = SANE_UNIT_NONE; dev->val[OPT_DBLFEED].w = SANE_FALSE; /* Fit to page */ dev->opt[OPT_FIT_TO_PAGE].name = SANE_I18N ("fit-to-page"); dev->opt[OPT_FIT_TO_PAGE].title = SANE_I18N ("Fit to page"); dev->opt[OPT_FIT_TO_PAGE].desc = SANE_I18N ("Scanner shrinks image to fit scanned page"); dev->opt[OPT_FIT_TO_PAGE].type = SANE_TYPE_BOOL; dev->opt[OPT_FIT_TO_PAGE].unit = SANE_UNIT_NONE; dev->val[OPT_FIT_TO_PAGE].w = SANE_FALSE; /* Geometry group */ dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_GEOMETRY_GROUP].cap = 0; dev->opt[OPT_GEOMETRY_GROUP].size = 0; dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Paper sizes list */ dev->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE; dev->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE; dev->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE; dev->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING; dev->opt[OPT_PAPER_SIZE].size = max_string_size (go_paper_list); dev->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_PAPER_SIZE].constraint.string_list = go_paper_list; dev->val[OPT_PAPER_SIZE].s = strdup (""); /* will be set later */ /* Landscape */ dev->opt[OPT_LANDSCAPE].name = SANE_NAME_LANDSCAPE; dev->opt[OPT_LANDSCAPE].title = SANE_TITLE_LANDSCAPE; dev->opt[OPT_LANDSCAPE].desc = SANE_I18N ("Set paper position : " "true for landscape, false for portrait"); dev->opt[OPT_LANDSCAPE].type = SANE_TYPE_BOOL; dev->opt[OPT_LANDSCAPE].unit = SANE_UNIT_NONE; dev->val[OPT_LANDSCAPE].w = SANE_FALSE; /* Upper left X */ dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &(dev->x_range); /* Upper left Y */ dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &(dev->y_range); /* Bottom-right x */ dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &(dev->x_range); /* Bottom-right y */ dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &(dev->y_range); /* Enhancement group */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Brightness */ dev->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; dev->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; dev->opt[OPT_BRIGHTNESS].size = sizeof (SANE_Int); dev->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BRIGHTNESS].constraint.range = &(go_value_range); dev->val[OPT_BRIGHTNESS].w = 128; /* Contrast */ dev->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; dev->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; dev->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; dev->opt[OPT_CONTRAST].type = SANE_TYPE_INT; dev->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; dev->opt[OPT_CONTRAST].size = sizeof (SANE_Int); dev->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_CONTRAST].constraint.range = &(go_value_range); dev->val[OPT_CONTRAST].w = 128; /* Automatic threshold */ dev->opt[OPT_AUTOMATIC_THRESHOLD].name = "automatic-threshold"; dev->opt[OPT_AUTOMATIC_THRESHOLD].title = SANE_I18N ("Automatic threshold"); dev->opt[OPT_AUTOMATIC_THRESHOLD].desc = SANE_I18N ("Automatically sets brightness, contrast, white level, " "gamma, noise reduction and image emphasis"); dev->opt[OPT_AUTOMATIC_THRESHOLD].type = SANE_TYPE_STRING; dev->opt[OPT_AUTOMATIC_THRESHOLD].size = max_string_size (go_automatic_threshold_list); dev->opt[OPT_AUTOMATIC_THRESHOLD].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_AUTOMATIC_THRESHOLD].constraint.string_list = go_automatic_threshold_list; dev->val[OPT_AUTOMATIC_THRESHOLD].s = strdup (go_automatic_threshold_list[0]); /* Halftone pattern */ dev->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; dev->opt[OPT_HALFTONE_PATTERN].size = max_string_size (go_halftone_pattern_list); dev->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_HALFTONE_PATTERN].constraint.string_list = go_halftone_pattern_list; dev->val[OPT_HALFTONE_PATTERN].s = strdup (go_halftone_pattern_list[0]); /* Automatic separation */ dev->opt[OPT_AUTOMATIC_SEPARATION].name = SANE_NAME_AUTOSEP; dev->opt[OPT_AUTOMATIC_SEPARATION].title = SANE_TITLE_AUTOSEP; dev->opt[OPT_AUTOMATIC_SEPARATION].desc = SANE_DESC_AUTOSEP; dev->opt[OPT_AUTOMATIC_SEPARATION].type = SANE_TYPE_BOOL; dev->opt[OPT_AUTOMATIC_SEPARATION].unit = SANE_UNIT_NONE; dev->val[OPT_AUTOMATIC_SEPARATION].w = SANE_FALSE; /* White level base */ dev->opt[OPT_WHITE_LEVEL].name = SANE_NAME_WHITE_LEVEL; dev->opt[OPT_WHITE_LEVEL].title = SANE_TITLE_WHITE_LEVEL; dev->opt[OPT_WHITE_LEVEL].desc = SANE_DESC_WHITE_LEVEL; dev->opt[OPT_WHITE_LEVEL].type = SANE_TYPE_STRING; dev->opt[OPT_WHITE_LEVEL].size = max_string_size (go_white_level_list); dev->opt[OPT_WHITE_LEVEL].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_WHITE_LEVEL].constraint.string_list = go_white_level_list; dev->val[OPT_WHITE_LEVEL].s = strdup (go_white_level_list[0]); /* Noise reduction */ dev->opt[OPT_NOISE_REDUCTION].name = "noise-reduction"; dev->opt[OPT_NOISE_REDUCTION].title = SANE_I18N ("Noise reduction"); dev->opt[OPT_NOISE_REDUCTION].desc = SANE_I18N ("Reduce the isolated dot noise"); dev->opt[OPT_NOISE_REDUCTION].type = SANE_TYPE_STRING; dev->opt[OPT_NOISE_REDUCTION].size = max_string_size (go_noise_reduction_list); dev->opt[OPT_NOISE_REDUCTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_NOISE_REDUCTION].constraint.string_list = go_noise_reduction_list; dev->val[OPT_NOISE_REDUCTION].s = strdup (go_noise_reduction_list[0]); /* Image emphasis */ dev->opt[OPT_IMAGE_EMPHASIS].name = "image-emphasis"; dev->opt[OPT_IMAGE_EMPHASIS].title = SANE_I18N ("Image emphasis"); dev->opt[OPT_IMAGE_EMPHASIS].desc = SANE_I18N ("Sets the image emphasis"); dev->opt[OPT_IMAGE_EMPHASIS].type = SANE_TYPE_STRING; dev->opt[OPT_IMAGE_EMPHASIS].size = max_string_size (go_image_emphasis_list); dev->opt[OPT_IMAGE_EMPHASIS].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_IMAGE_EMPHASIS].constraint.string_list = go_image_emphasis_list; dev->val[OPT_IMAGE_EMPHASIS].s = strdup (SANE_I18N ("medium")); /* Gamma */ dev->opt[OPT_GAMMA].name = "gamma"; dev->opt[OPT_GAMMA].title = SANE_I18N ("Gamma"); dev->opt[OPT_GAMMA].desc = SANE_I18N ("Gamma"); dev->opt[OPT_GAMMA].type = SANE_TYPE_STRING; dev->opt[OPT_GAMMA].size = max_string_size (go_gamma_list); dev->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_GAMMA].constraint.string_list = go_gamma_list; dev->val[OPT_GAMMA].s = strdup (go_gamma_list[0]); /* Lamp color dropout */ dev->opt[OPT_LAMP].name = "lamp-color"; dev->opt[OPT_LAMP].title = SANE_I18N ("Lamp color"); dev->opt[OPT_LAMP].desc = SANE_I18N ("Sets the lamp color (color dropout)"); dev->opt[OPT_LAMP].type = SANE_TYPE_STRING; dev->opt[OPT_LAMP].size = max_string_size (go_lamp_list); dev->opt[OPT_LAMP].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_LAMP].constraint.string_list = go_lamp_list; dev->val[OPT_LAMP].s = strdup (go_lamp_list[0]); if (!dev->support_info.support_lamp) dev->opt[OPT_LAMP].cap |= SANE_CAP_INACTIVE; /* Inverse image */ dev->opt[OPT_INVERSE].name = SANE_NAME_INVERSE; dev->opt[OPT_INVERSE].title = SANE_TITLE_INVERSE; dev->opt[OPT_INVERSE].desc = SANE_I18N ("Inverse image in B/W or halftone mode"); dev->opt[OPT_INVERSE].type = SANE_TYPE_BOOL; dev->opt[OPT_INVERSE].unit = SANE_UNIT_NONE; dev->val[OPT_INVERSE].w = SANE_FALSE; /* Mirror image (left/right flip) */ dev->opt[OPT_MIRROR].name = SANE_NAME_MIRROR; dev->opt[OPT_MIRROR].title = SANE_TITLE_MIRROR; dev->opt[OPT_MIRROR].desc = SANE_I18N ("Mirror image (left/right flip)"); dev->opt[OPT_MIRROR].type = SANE_TYPE_BOOL; dev->opt[OPT_MIRROR].unit = SANE_UNIT_NONE; dev->val[OPT_MIRROR].w = SANE_FALSE; /* JPEG Image Compression */ dev->opt[OPT_JPEG].name = "jpeg"; dev->opt[OPT_JPEG].title = SANE_I18N ("jpeg compression"); dev->opt[OPT_JPEG].desc = SANE_I18N ("JPEG Image Compression with Q parameter, '0' - no compression"); dev->opt[OPT_JPEG].type = SANE_TYPE_INT; dev->opt[OPT_JPEG].unit = SANE_UNIT_NONE; dev->opt[OPT_JPEG].size = sizeof (SANE_Int); dev->opt[OPT_JPEG].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_JPEG].constraint.range = &(go_jpeg_compression_range); dev->val[OPT_JPEG].w = 0; /* Image Rotation */ dev->opt[OPT_ROTATE].name = "rotate"; dev->opt[OPT_ROTATE].title = SANE_I18N ("Rotate image clockwise"); dev->opt[OPT_ROTATE].desc = SANE_I18N("Request driver to rotate pages by a fixed amount"); dev->opt[OPT_ROTATE].type = SANE_TYPE_INT; dev->opt[OPT_ROTATE].unit = SANE_UNIT_NONE; dev->opt[OPT_ROTATE].size = sizeof (SANE_Int); dev->opt[OPT_ROTATE].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_ROTATE].constraint.range = &(go_rotate_range); dev->val[OPT_ROTATE].w = 0; /* Software Deskew */ dev->opt[OPT_SWDESKEW].name = "swdeskew"; dev->opt[OPT_SWDESKEW].title = SANE_I18N ("Software deskew"); dev->opt[OPT_SWDESKEW].desc = SANE_I18N("Request driver to rotate skewed pages digitally"); dev->opt[OPT_SWDESKEW].type = SANE_TYPE_BOOL; dev->opt[OPT_SWDESKEW].unit = SANE_UNIT_NONE; dev->val[OPT_SWDESKEW].w = SANE_FALSE; /* Software Despeckle */ dev->opt[OPT_SWDESPECK].name = "swdespeck"; dev->opt[OPT_SWDESPECK].title = SANE_I18N ("Software despeckle diameter"); dev->opt[OPT_SWDESPECK].desc = SANE_I18N("Maximum diameter of lone dots to remove from scan"); dev->opt[OPT_SWDESPECK].type = SANE_TYPE_INT; dev->opt[OPT_SWDESPECK].unit = SANE_UNIT_NONE; dev->opt[OPT_SWDESPECK].size = sizeof (SANE_Int); dev->opt[OPT_SWDESPECK].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_SWDESPECK].constraint.range = &(go_swdespeck_range); dev->val[OPT_SWDESPECK].w = 0; /* Software Derotate */ dev->opt[OPT_SWDEROTATE].name = "swderotate"; dev->opt[OPT_SWDEROTATE].title = SANE_I18N ("Software derotate"); dev->opt[OPT_SWDEROTATE].desc = SANE_I18N("Request driver to detect and correct 90 degree image rotation"); dev->opt[OPT_SWDEROTATE].type = SANE_TYPE_BOOL; dev->opt[OPT_SWDEROTATE].unit = SANE_UNIT_NONE; dev->val[OPT_SWDEROTATE].w = SANE_FALSE; /* Software Autocrop*/ dev->opt[OPT_SWCROP].name = "swcrop"; dev->opt[OPT_SWCROP].title = SANE_I18N ("Software automatic cropping"); dev->opt[OPT_SWCROP].desc = SANE_I18N("Request driver to remove border from pages digitally"); dev->opt[OPT_SWCROP].type = SANE_TYPE_BOOL; dev->opt[OPT_SWCROP].unit = SANE_UNIT_NONE; dev->val[OPT_SWCROP].w = SANE_FALSE; /* Software blank page skip */ dev->opt[OPT_SWSKIP].name = "swskip"; dev->opt[OPT_SWSKIP].title = SANE_I18N ("Software blank skip percentage"); dev->opt[OPT_SWSKIP].desc = SANE_I18N("Request driver to discard pages with low numbers of dark pixels"); dev->opt[OPT_SWSKIP].type = SANE_TYPE_FIXED; dev->opt[OPT_SWSKIP].unit = SANE_UNIT_PERCENT; dev->opt[OPT_SWSKIP].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_SWSKIP].constraint.range = &(go_swskip_range); /* Lastly, set the default scan mode. This might change some * values previously set here. */ sane_control_option (dev, OPT_PAPER_SIZE, SANE_ACTION_SET_VALUE, (void *) go_paper_list[default_paper_size_idx], NULL); sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, (void *) go_scan_mode_list[0], NULL); DBG (DBG_proc, "kv_init_options: exit\n"); dev->option_set = 1; } SANE_Status kv_control_option (PKV_DEV dev, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { SANE_Status status; SANE_Word cap; SANE_String_Const name; int i; SANE_Word value; DBG (DBG_proc, "sane_control_option: enter, option %s, action %s\n", go_option_name[option], action == SANE_ACTION_GET_VALUE ? "R" : "W"); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_UNSUPPORTED; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_UNSUPPORTED; } name = dev->opt[option].name; if (!name) { name = "(no name)"; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_LONGPAPER: case OPT_LENGTHCTL: case OPT_DBLFEED: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_DUPLEX: case OPT_LANDSCAPE: case OPT_AUTOMATIC_SEPARATION: case OPT_INVERSE: case OPT_MIRROR: case OPT_FEED_TIMEOUT: case OPT_JPEG: case OPT_ROTATE: case OPT_SWDESKEW: case OPT_SWDESPECK: case OPT_SWDEROTATE: case OPT_SWCROP: case OPT_SWSKIP: case OPT_FIT_TO_PAGE: *(SANE_Word *) val = dev->val[option].w; DBG (DBG_error, "opt value = %d\n", *(SANE_Word *) val); return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_FEEDER_MODE: case OPT_SCAN_SOURCE: case OPT_MANUALFEED: case OPT_HALFTONE_PATTERN: case OPT_PAPER_SIZE: case OPT_AUTOMATIC_THRESHOLD: case OPT_WHITE_LEVEL: case OPT_NOISE_REDUCTION: case OPT_IMAGE_EMPHASIS: case OPT_GAMMA: case OPT_LAMP: strcpy (val, dev->val[option].s); DBG (DBG_error, "opt value = %s\n", (char *) val); return SANE_STATUS_GOOD; default: return SANE_STATUS_UNSUPPORTED; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option %s, not settable\n", go_option_name[option]); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; if (option == OPT_RESOLUTION) { if (round_to_boundry (&(dev->val[option].w), dev->support_info. step_resolution, 100, 600)) { if (info) { *info |= SANE_INFO_INEXACT; } } } else if (option == OPT_TL_Y) { if (dev->val[option].w > dev->val[OPT_BR_Y].w) { dev->val[option].w = dev->val[OPT_BR_Y].w; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } else { if (dev->val[option].w < dev->val[OPT_TL_Y].w) { dev->val[option].w = dev->val[OPT_TL_Y].w; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } DBG (DBG_error, "option %s, input = %d, value = %d\n", go_option_name[option], (*(SANE_Word *) val), dev->val[option].w); return SANE_STATUS_GOOD; /* The length of X must be rounded (up). */ case OPT_TL_X: case OPT_BR_X: { SANE_Word xr = dev->val[OPT_RESOLUTION].w; SANE_Word tl_x = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)) * xr; SANE_Word br_x = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)) * xr; value = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)) * xr; /* XR * W */ if (option == OPT_TL_X) { SANE_Word max = KV_PIXEL_MAX * xr - KV_PIXEL_ROUND; if (br_x < max) max = br_x; if (round_to_boundry (&value, KV_PIXEL_ROUND, 0, max)) { if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } else { if (round_to_boundry (&value, KV_PIXEL_ROUND, tl_x, KV_PIXEL_MAX * xr)) { if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } dev->val[option].w = SANE_FIX (iluToMm ((double) value / xr)); if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } DBG (DBG_error, "option %s, input = %d, value = %d\n", go_option_name[option], (*(SANE_Word *) val), dev->val[option].w); return SANE_STATUS_GOOD; } case OPT_LANDSCAPE: dev->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; /* Side-effect free options */ case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_DUPLEX: case OPT_LONGPAPER: case OPT_LENGTHCTL: case OPT_DBLFEED: case OPT_INVERSE: case OPT_MIRROR: case OPT_AUTOMATIC_SEPARATION: case OPT_JPEG: case OPT_ROTATE: case OPT_SWDESKEW: case OPT_SWDESPECK: case OPT_SWDEROTATE: case OPT_SWCROP: case OPT_SWSKIP: case OPT_FIT_TO_PAGE: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_FEED_TIMEOUT: dev->val[option].w = *(SANE_Word *) val; return CMD_set_timeout (dev, *(SANE_Word *) val); /* String mode */ case OPT_SCAN_SOURCE: case OPT_WHITE_LEVEL: case OPT_NOISE_REDUCTION: case OPT_IMAGE_EMPHASIS: case OPT_GAMMA: case OPT_LAMP: case OPT_HALFTONE_PATTERN: case OPT_FEEDER_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); if (option == OPT_FEEDER_MODE && get_string_list_index (go_feeder_mode_list, dev->val[option].s) == 1) /* continuous mode */ { free (dev->val[OPT_SCAN_SOURCE].s); dev->val[OPT_SCAN_SOURCE].s = strdup (go_scan_source_list[0]); dev->opt[OPT_LONGPAPER].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } else { dev->opt[OPT_LONGPAPER].cap |= SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } if (option == OPT_SCAN_SOURCE && get_string_list_index (go_scan_source_list, dev->val[option].s) == 1) /* flatbed */ { free (dev->val[OPT_FEEDER_MODE].s); dev->val[OPT_FEEDER_MODE].s = strdup (go_feeder_mode_list[0]); } return SANE_STATUS_GOOD; case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_String) strdup (val); /* Set default options for the scan modes. */ dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap &= ~SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[0]) == 0) /* binary */ { dev->opt[OPT_AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap |= SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[1]) == 0) /* halftone */ { dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap |= SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[2]) == 0) /* grayscale */ { dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_MANUALFEED: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); if (strcmp (dev->val[option].s, go_manual_feed_list[0]) == 0) /* off */ dev->opt[OPT_FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE; else dev->opt[OPT_FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_PAPER_SIZE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_PAPER_SIZE].s); dev->val[OPT_PAPER_SIZE].s = (SANE_Char *) strdup (val); i = get_string_list_index (go_paper_list, dev->val[OPT_PAPER_SIZE].s); if (i == 0) { /*user def */ dev->opt[OPT_TL_X].cap &= dev->opt[OPT_TL_Y].cap &= dev->opt[OPT_BR_X].cap &= dev->opt[OPT_BR_Y].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_LANDSCAPE].cap |= SANE_CAP_INACTIVE; dev->val[OPT_LANDSCAPE].w = 0; } else { dev->opt[OPT_TL_X].cap |= dev->opt[OPT_TL_Y].cap |= dev->opt[OPT_BR_X].cap |= dev->opt[OPT_BR_Y].cap |= SANE_CAP_INACTIVE; if (i == 4 || i == 5 || i == 7) { /*A5, A6 or B6 */ dev->opt[OPT_LANDSCAPE].cap &= ~SANE_CAP_INACTIVE; } else { dev->opt[OPT_LANDSCAPE].cap |= SANE_CAP_INACTIVE; dev->val[OPT_LANDSCAPE].w = 0; } } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_AUTOMATIC_THRESHOLD: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_Char *) strdup (val); /* If the threshold is not set to none, some option must * disappear. */ dev->opt[OPT_WHITE_LEVEL].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_IMAGE_EMPHASIS].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (strcmp (val, go_automatic_threshold_list[0]) == 0) { dev->opt[OPT_WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_IMAGE_EMPHASIS].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[1]) == 0) { dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; } /* Display a buffer in the log. */ void hexdump (int level, const char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; DBG (level, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { *ptr = '\0'; DBG (level, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3d:", i); ptr += 4; } sprintf (ptr, " %2.2x", *p); ptr += 3; } *ptr = '\0'; DBG (level, "%s\n", line); } /* Set window data */ void kv_set_window_data (PKV_DEV dev, KV_SCAN_MODE scan_mode, int side, unsigned char *windowdata) { int paper = go_paper_val[get_string_list_index (go_paper_list, dev->val[OPT_PAPER_SIZE]. s)]; /* Page side */ windowdata[0] = side; /* X and Y resolution */ Ito16 (dev->val[OPT_RESOLUTION].w, &windowdata[2]); Ito16 (dev->val[OPT_RESOLUTION].w, &windowdata[4]); /* Width and length */ if (paper == 0) { /* Non-standard document */ int x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); int y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); int x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); int y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); int width = x_br - x_tl; int length = y_br - y_tl; /* Upper Left (X,Y) */ Ito32 (x_tl, &windowdata[6]); Ito32 (y_tl, &windowdata[10]); Ito32 (width, &windowdata[14]); Ito32 (length, &windowdata[18]); Ito32 (width, &windowdata[48]); /* device specific */ Ito32 (length, &windowdata[52]); /* device specific */ } /* Brightness */ windowdata[22] = 255 - GET_OPT_VAL_W (dev, OPT_BRIGHTNESS); windowdata[23] = windowdata[22]; /* threshold, same as brightness. */ /* Contrast */ windowdata[24] = GET_OPT_VAL_W (dev, OPT_CONTRAST); /* Image Composition */ windowdata[25] = (unsigned char) scan_mode; /* Depth */ windowdata[26] = kv_get_depth (scan_mode); /* Halftone pattern. */ if (scan_mode == SM_DITHER) { windowdata[28] = GET_OPT_VAL_L (dev, OPT_HALFTONE_PATTERN, halftone_pattern); } /* Inverse */ if (scan_mode == SM_BINARY || scan_mode == SM_DITHER) { windowdata[29] = GET_OPT_VAL_W (dev, OPT_INVERSE); } /* Bit ordering */ windowdata[31] = 1; /*Compression Type */ if (!(dev->opt[OPT_JPEG].cap & SANE_CAP_INACTIVE) && GET_OPT_VAL_W (dev, OPT_JPEG)) { windowdata[32] = 0x81; /*jpeg */ /*Compression Argument */ windowdata[33] = GET_OPT_VAL_W (dev, OPT_JPEG); } /* Gamma */ if (scan_mode == SM_DITHER || scan_mode == SM_GRAYSCALE) { windowdata[44] = GET_OPT_VAL_L (dev, OPT_GAMMA, gamma); } /* Feeder mode */ windowdata[57] = GET_OPT_VAL_L (dev, OPT_FEEDER_MODE, feeder_mode); /* Stop skew -- disabled */ windowdata[41] = 0; /* Scan source */ if (GET_OPT_VAL_L (dev, OPT_SCAN_SOURCE, scan_source)) { /* flatbed */ windowdata[41] |= 0x80; } else { windowdata[41] &= 0x7f; } /* Paper size */ windowdata[47] = paper; if (paper) /* Standard Document */ windowdata[47] |= 1 << 7; /* Long paper */ if (GET_OPT_VAL_W (dev, OPT_LONGPAPER)) { windowdata[47] |= 0x20; } /* Length control */ if (GET_OPT_VAL_W (dev, OPT_LENGTHCTL)) { windowdata[47] |= 0x40; } /* Landscape */ if (GET_OPT_VAL_W (dev, OPT_LANDSCAPE)) { windowdata[47] |= 1 << 4; } /* Double feed */ if (GET_OPT_VAL_W (dev, OPT_DBLFEED)) { windowdata[56] = 0x10; } /* Fit to page */ if (GET_OPT_VAL_W (dev, OPT_FIT_TO_PAGE)) { windowdata[56] |= 1 << 2; } /* Manual feed */ windowdata[62] = GET_OPT_VAL_L (dev, OPT_MANUALFEED, manual_feed) << 6; /* Mirror image */ if (GET_OPT_VAL_W (dev, OPT_MIRROR)) { windowdata[42] = 0x80; } /* Image emphasis */ windowdata[43] = GET_OPT_VAL_L (dev, OPT_IMAGE_EMPHASIS, image_emphasis); /* White level */ windowdata[60] = GET_OPT_VAL_L (dev, OPT_WHITE_LEVEL, white_level); if (scan_mode == SM_BINARY || scan_mode == SM_DITHER) { /* Noise reduction */ windowdata[61] = GET_OPT_VAL_L (dev, OPT_NOISE_REDUCTION, noise_reduction); /* Automatic separation */ if (scan_mode == SM_DITHER && GET_OPT_VAL_W (dev, OPT_AUTOMATIC_SEPARATION)) { windowdata[59] = 0x80; } } /* Automatic threshold. Must be last because it may override * some previous options. */ if (scan_mode == SM_BINARY) { windowdata[58] = GET_OPT_VAL_L (dev, OPT_AUTOMATIC_THRESHOLD, automatic_threshold); } if (windowdata[58] != 0) { /* Automatic threshold is enabled. */ windowdata[22] = 0; /* brightness. */ windowdata[23] = 0; /* threshold, same as brightness. */ windowdata[24] = 0; /* contrast */ windowdata[27] = windowdata[28] = 0; /* Halftone pattern. */ windowdata[43] = 0; /* Image emphasis */ windowdata[59] = 0; /* Automatic separation */ windowdata[60] = 0; /* White level */ windowdata[61] = 0; /* Noise reduction */ } /* lamp -- color dropout */ windowdata[45] = GET_OPT_VAL_L (dev, OPT_LAMP, lamp) << 4; /*Stop Mode: After 1 page */ windowdata[63] = 1; } sane-backends-1.0.27/backend/gphoto2.h0000664000175000017500000001155712775312261014363 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. gphoto2.h 03/12/01 - Peter Fales Based on the dc210 driver, (C) 1998 Brian J. Murrell (which is based on dc25 driver (C) 1998 by Peter Fales) This file (C) 2001 by Peter Fales This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for the Kodak DC-240 digital camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! (feedback to: gphoto2-devel@fales-lorenz.net) This backend is based somewhat on the dc25 backend included in this package by Peter Fales, and the dc210 backend by Brian J. Murrell ***************************************************************************/ #include #include #include #include #include #include #ifndef TRUE #define TRUE (1==1) #endif #ifndef FALSE #define FALSE (!TRUE) #endif #ifndef NULL #define NULL 0L #endif typedef struct picture_info { int low_res; int size; } PictureInfo; typedef struct GPHOTO2_s { SANE_String port; /* the port name it's on */ SANE_Int speed; /* current port speed */ SANE_String camera_name; SANE_Bool scanning; /* currently scanning an image? */ SANE_Byte model; SANE_Byte ver_major; SANE_Byte ver_minor; SANE_Int pic_taken; SANE_Int pic_left; struct { unsigned int low_res:1; unsigned int low_batt:1; } flags; PictureInfo *Pictures; /* array of pictures */ SANE_Int current_picture_number; /* picture being operated on */ } GPHOTO2; typedef struct gphoto2_info_s { SANE_Byte model; SANE_Byte ver_major; SANE_Byte ver_minor; SANE_Int pic_taken; SANE_Int pic_left; struct { SANE_Int low_res:1; SANE_Int low_batt:1; } flags; } Gphoto2Info, *Gphoto2InfoPtr; static SANE_Int get_info (void); #define HIGH_RES 0 #define LOW_RES 1 #define HIGHRES_WIDTH highres_width #define HIGHRES_HEIGHT highres_height #define LOWRES_WIDTH lowres_width #define LOWRES_HEIGHT lowres_height #define THUMB_WIDTH thumb_width #define THUMB_HEIGHT thumb_height /* * External definitions */ extern char *__progname; /* Defined in /usr/lib/crt0.o */ struct cam_dirent { SANE_Char name[11]; SANE_Byte attr; SANE_Byte create_time[2]; SANE_Byte creat_date[2]; long size; }; struct cam_dirlist { SANE_Char name[48]; struct cam_dirlist *next; }; #include FILE *sanei_config_open (const char *filename); static SANE_Int init_gphoto2 (void); static void close_gphoto2 (void); static PictureInfo *get_pictures_info (void); static SANE_Int get_picture_info (PictureInfo * pic, SANE_Int p); static SANE_Status snap_pic (void); char *sanei_config_read (char *str, int n, FILE * stream); static SANE_Int read_dir (SANE_String dir, SANE_Bool read_files); static void set_res (SANE_Int lowres); static SANE_Int read_info (SANE_String_Const fname); static SANE_Status converter_do_scan_complete_cleanup (void); static SANE_Int converter_fill_buffer (void); static SANE_Bool converter_scan_complete (void); static SANE_Status converter_init (SANE_Handle handle); sane-backends-1.0.27/backend/v4l-frequencies.h0000664000175000017500000001070512112021330015762 00000000000000/* * Worldwide channel/frequency list * * Nathan Laredo (laredo@broked.net) * * Frequencies are given in kHz */ #define NTSC_AUDIO_CARRIER 4500 #define PAL_AUDIO_CARRIER_I 6000 #define PAL_AUDIO_CARRIER_BGHN 5500 #define PAL_AUDIO_CARRIER_MN 4500 #define PAL_AUDIO_CARRIER_D 6500 #define SEACAM_AUDIO_DKK1L 6500 #define SEACAM_AUDIO_BG 5500 /* NICAM 728 32-kHz, 14-bit digital stereo audio is transmitted in 1ms frames containing 8 bits frame sync, 5 bits control, 11 bits additional data, and 704 bits audio data. The bit rate is reduced by transmitting only 10 bits plus parity of each 14 bit sample, the largest sample in a frame determines which 10 bits are transmitted. The parity bits for audio samples also specify the scaling factor used for that channel during that frame. The companeded audio data is interleaved to reduce the influence of dropouts and the whole frame except for sync bits is scrambled for spectrum shaping. Data is modulated using QPSK, at below following subcarrier freqs */ #define NICAM728_PAL_BGH 5850 #define NICAM728_PAL_I 6552 /* COMPREHENSIVE LIST OF FORMAT BY COUNTRY (M) NTSC used in: Antigua, Aruba, Bahamas, Barbados, Belize, Bermuda, Bolivia, Burma, Canada, Chile, Colombia, Costa Rica, Cuba, Curacao, Dominican Republic, Ecuador, El Salvador, Guam Guatemala, Honduras, Jamaica, Japan, South Korea, Mexico, Montserrat, Myanmar, Nicaragua, Panama, Peru, Philippines, Puerto Rico, St Christopher and Nevis, Samoa, Suriname, Taiwan, Trinidad/Tobago, United States, Venezuela, Virgin Islands (B) PAL used in: Albania, Algeria, Australia, Austria, Bahrain, Bangladesh, Belgium, Bosnia-Herzegovinia, Brunei Darussalam, Cambodia, Cameroon, Croatia, Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea, Finland, Germany, Ghana, Gibraltar, Greenland, Iceland, India, Indonesia, Israel, Italy, Jordan, Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysa, Maldives, Malta, Nepal, Netherlands, New Zeland, Nigeria, Norway, Oman, Pakistan, Papua New Guinea, Portugal, Qatar, Sao Tome and Principe, Saudi Arabia, Seychelles, Sierra Leone, Singapore, Slovenia, Somali, Spain, Sri Lanka, Sudan, Swaziland, Sweden, Switzeland, Syria, Thailand, Tunisia, Turkey, Uganda, United Arab Emirates, Yemen (N) PAL used in: (Combination N = 4.5MHz audio carrier, 3.58MHz burst) Argentina (Combination N), Paraguay, Uruguay (M) PAL (525/60, 3.57MHz burst) used in: Brazil (G) PAL used in: Albania, Algeria, Austria, Bahrain, Bosnia/Herzegovinia, Cambodia, Cameroon, Croatia, Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea, Finland, Germany, Gibraltar, Greenland, Iceland, Israel, Italy, Jordan, Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysia, Monaco, Mozambique, Netherlands, New Zealand, Norway, Oman, Pakistan, Papa New Guinea, Portugal, Qatar, Romania, Sierra Leone, Singapore, Slovenia, Somalia, Spain, Sri Lanka, Sudan, Swaziland, Sweeden, Switzerland, Syria, Thailand, Tunisia, Turkey, United Arab Emirates, Yemen, Zambia, Zimbabwe (D) PAL used in: China, North Korea, Romania, Czech Republic (H) PAL used in: Belgium (I) PAL used in: Angola, Botswana, Gambia, Guinea-Bissau, Hong Kong, Ireland, Lesotho, Malawi, Nambia, Nigeria, South Africa, Tanzania, United Kingdom, Zanzibar (B) SECAM used in: Djibouti, Greece, Iran, Iraq, Lebanon, Mali, Mauritania, Mauritus, Morocco (D) SECAM used in: Afghanistan, Armenia, Azerbaijan, Belarus, Bulgaria, Estonia, Georgia, Hungary, Zazakhstan, Lithuania, Mongolia, Moldova, Poland, Russia, Slovak Republic, Ukraine, Vietnam (G) SECAM used in: Greecem Iran, Iraq, Mali, Mauritus, Morocco, Saudi Arabia (K) SECAM used in: Armenia, Azerbaijan, Bulgaria, Estonia, Georgia, Hungary, Kazakhstan, Lithuania, Madagascar, Moldova, Poland, Russia, Slovak Republic, Ukraine, Vietnam (K1) SECAM used in: Benin, Burkina Faso, Burundi, Chad, Cape Verde, Central African Republic, Comoros, Congo, Gabon, Madagascar, Niger, Rwanda, Senegal, Togo, Zaire (L) SECAM used in: France */ /* --------------------------------------------------------------------- */ struct CHANLIST { char *name; int freq; }; struct CHANLISTS { char *name; struct CHANLIST *list; int count; }; #define CHAN_COUNT(x) (sizeof(x)/sizeof(struct CHANLIST)) /* --------------------------------------------------------------------- */ extern struct CHANLISTS chanlists[]; extern struct STRTAB chanlist_names[]; extern int chantab; extern struct CHANLIST *chanlist; extern int chancount; sane-backends-1.0.27/backend/canon_pp-io.c0000664000175000017500000003603512112021330015147 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2002 Matthew C. Duggan and Simon Krix This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. ----- This file is part of the canon_pp backend, supporting Canon CanoScan Parallel scanners and also distributed as part of the stand-alone driver. canon_pp-io.c: $Revision$ Low Level Function library for Canon CanoScan Parallel Scanners by Simon Krix */ #ifndef NOSANE #include "../include/sane/config.h" #endif #include #include #include #include "canon_pp-io.h" #include "canon_pp-dev.h" #ifdef NOSANE /* No SANE, Things that only apply to stand-alone */ #include #include static void DBG(int level, const char *format, ...) { va_list args; va_start(args, format); if (level < 50) vfprintf(stderr, format, args); va_end(args); } #else /* Definitions which only apply to SANE compiles */ #ifndef VERSION #define VERSION "$Revision$" #endif /* Fix problem with DBG macro definition having a - in the name */ #define DEBUG_DECLARE_ONLY #include "canon_pp.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_config.h" #endif /* 0x00 = Nibble Mode (M1284_NIBBLE) 0x10 = ECP Mode (M1284_ECP) The scanner driver seems not to support ECP RLE mode (which is a huge bummer because compression would be ace) nor EPP mode. */ static int ieee_mode = M1284_NIBBLE; /* For super-verbose debugging */ /* #define DUMP_PACKETS 1 */ /* Some sort of initialisation command */ static unsigned char cmd_init[10] = { 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0 }; /************* Local Prototypes ******************/ /* Used by wake_scanner */ static int scanner_reset(struct parport *port); static void scanner_chessboard_control(struct parport *port); static void scanner_chessboard_data(struct parport *port, int mode); /* Used by read_data */ static int ieee_transfer(struct parport *port, int length, unsigned char *data); /* Low level functions */ static int readstatus(struct parport *port); static int expect(struct parport *port, const char *step, int s, int mask, unsigned int delay); /* Port-level functions */ static void outdata(struct parport *port, int d); static void outcont(struct parport *port, int d, int mask); static void outboth(struct parport *port, int d, int c); /************************************/ /* * IEEE 1284 defines many values for m, * but these scanners only support 2: nibble and ECP modes. * And no data compression either (argh!) * 0 = Nibble-mode reverse channel transfer * 16 = ECP-mode */ void sanei_canon_pp_set_ieee1284_mode(int m) { ieee_mode = m; } int sanei_canon_pp_wake_scanner(struct parport *port, int mode) { /* The scanner tristates the printer's control lines (essentially disabling the passthrough port) and exits from Transparent Mode ready for communication. */ int i = 0; int tmp; int max_cycles = 3; tmp = readstatus(port); /* Reset only works on 30/40 models */ if (mode != INITMODE_20P) { if ((tmp != READY)) { DBG(40, "Scanner not ready (0x%x). Attempting to " "reset...\n", tmp); scanner_reset(port); /* give it more of a chance to reset in this case */ max_cycles = 5; } } else { DBG(0, "WARNING: Don't know how to reset an FBx20P, you may " "have to power cycle\n"); } do { i++; /* Send the wakeup sequence */ scanner_chessboard_control(port); scanner_chessboard_data(port, mode); if (expect(port, NULL, 0x03, 0x1f, 800000) && (mode == INITMODE_AUTO)) { /* 630 Style init failed, try 620 style */ scanner_chessboard_control(port); scanner_chessboard_data(port, INITMODE_20P); } if (expect(port, "Scanner wakeup reply 1", 0x03, 0x1f, 50000)) { outboth(port, 0x04, 0x0d); usleep(100000); outcont(port, 0x07, 0x0f); usleep(100000); } } while ((i < max_cycles) && (!expect(port,"Scanner wakeup reply 2", 0x03, 0x1f, 100000) == 0)); /* Block just after chessboarding Reply 1 (S3 and S4 on, S5 and S7 off) */ outcont(port, 0, HOSTBUSY); /* C1 off */ /* Reply 2 - If it ain't happening by now, it ain't gonna happen. */ if (expect(port, "Reply 2", 0xc, 0x1f, 800000)) return -1; outcont(port, HOSTBUSY, HOSTBUSY); /* C1 on */ if (expect(port, "Reply 3", 0x0b, 0x1f, 800000)) return -1; outboth(port, 0, NSELECTIN | NINIT | HOSTCLK); /* Clear D, C3+, C1- */ /* If we had to try the wakeup cycle more than once, we should wait * here for 10 seconds to let the scanner pull itself together - * it can actually take longer, but I can't wait that long! */ if (i > 1) { DBG(10, "Had to reset scanner, waiting for the " "head to get back.\n"); usleep(10000000); } return 0; } int sanei_canon_pp_write(struct parport *port, int length, unsigned char *data) { #ifdef DUMP_PACKETS ssize_t count; DBG(10,"Sending: "); for (count = 0; count < length; count++) { DBG(10,"%02x ", data[count]); if (count % 20 == 19) DBG(10,"\n "); } if (count % 20 != 19) DBG(10,"\n"); #endif DBG(100, "NEW Send Command (length %i):\n", length); switch (ieee_mode) { case M1284_BECP: case M1284_ECPRLE: case M1284_ECPSWE: case M1284_ECP: ieee1284_negotiate(port, ieee_mode); if (ieee1284_ecp_write_data(port, 0, (char *)data, length) != length) return -1; break; case M1284_NIBBLE: if (ieee1284_compat_write(port, 0, (char *)data, length) != length) return -1; break; default: DBG(0, "Invalid mode in write!\n"); } DBG(100, "<< write"); return 0; } int sanei_canon_pp_read(struct parport *port, int length, unsigned char *data) { int count, offset; DBG(200, "NEW read_data (%i bytes):\n", length); ieee1284_negotiate(port, ieee_mode); /* This is special; Nibble mode needs a little extra help from us. */ if (ieee_mode == M1284_NIBBLE) { /* Interrupt phase */ outcont(port, NSELECTIN, HOSTBUSY | NSELECTIN); if (expect(port, "Read Data 1", 0, NDATAAVAIL, 6000000)) { DBG(10,"Error 1\n"); ieee1284_terminate(port); return 1; } outcont(port, HOSTBUSY, HOSTBUSY); if (expect(port, "Read Data 2", NACK, NACK, 1000000)) { DBG(1,"Error 2\n"); ieee1284_terminate(port); return 1; } if (expect(port, "Read Data 3 (Ready?)", 0, PERROR, 1000000)) { DBG(1,"Error 3\n"); ieee1284_terminate(port); return 1; } /* Host-Busy Data Available phase */ if ((readstatus(port) & NDATAAVAIL) == NDATAAVAIL) { DBG(1,"No data to read.\n"); ieee1284_terminate(port); return 1; } } offset = 0; DBG(100, "-> ieee_transfer(%d) *\n", length); count = ieee_transfer(port, length, data); DBG(100, "<- (%d)\n", count); /* Early-out if it was not implemented */ if (count == E1284_NOTIMPL) return 2; length -= count; offset+= count; while (length > 0) { /* If 0 bytes were transferred, it's a legal "No data" condition (I think). Otherwise, it may have run out of buffer.. keep reading*/ if (count < 0) { DBG(10, "Couldn't read enough data (need %d more " "of %d)\n", length+count,length+offset); ieee1284_terminate(port); return 1; } DBG(100, "-> ieee_transfer(%d)\n", length); count = ieee_transfer(port, length, data+offset); DBG(100, "<- (%d)\n", count); length-=count; offset+= count; } #ifdef DUMP_PACKETS if (length <= 60) { DBG(10,"Read: "); for (count = 0; count < length; count++) { DBG(10,"%02x ", data[count]); if (count % 20 == 19) DBG(10,"\n "); } if (count % 20 != 19) DBG(10,"\n"); } else { DBG(10,"Read: %i bytes\n", length); } #endif if (ieee_mode == M1284_NIBBLE) ieee1284_terminate(port); return 0; } static int ieee_transfer(struct parport *port, int length, unsigned char *data) { int result = 0; DBG(100, "IEEE transfer (%i bytes)\n", length); switch (ieee_mode) { case M1284_BECP: case M1284_ECP: case M1284_ECPRLE: case M1284_ECPSWE: result = ieee1284_ecp_read_data(port, 0, (char *)data, length); break; case M1284_NIBBLE: result = ieee1284_nibble_read(port, 0, (char *)data, length); break; default: DBG(1, "Internal error: Wrong mode for transfer.\n" "Please email stauff1@users.sourceforge.net\n" "or kinsei@users.sourceforge.net\n"); } return result; } int sanei_canon_pp_check_status(struct parport *port) { int status; unsigned char data[2]; DBG(200, "* Check Status:\n"); if (sanei_canon_pp_read(port, 2, data)) return -1; status = data[0] | (data[1] << 8); switch(status) { case 0x0606: DBG(200, "Ready - 0x0606\n"); return 0; break; case 0x1414: DBG(200, "Busy - 0x1414\n"); return 1; break; case 0x0805: DBG(200, "Resetting - 0x0805\n"); return 3; break; case 0x1515: DBG(1, "!! Invalid Command - 0x1515\n"); return 2; break; case 0x0000: DBG(200, "Nothing - 0x0000"); return 4; break; default: DBG(1, "!! Unknown status - %04x\n", status); return 100; } } /* Send a raw byte to the printer port */ static void outdata(struct parport *port, int d) { ieee1284_write_data(port, d & 0xff); } /* Send the low nibble of d to the control port. The mask affects which bits are changed. */ static void outcont(struct parport *port, int d, int mask) { static int control_port_status = 0; control_port_status = (control_port_status & ~mask) | (d & mask); ieee1284_write_control(port, (control_port_status & 0x0f)); } /* Send a byte to both ports */ static void outboth(struct parport *port, int d, int c) { ieee1284_write_data(port, d & 0xff); outcont(port, c, 0x0f); } /* readstatus(): Returns the LOGIC value of the S register (ie: all input lines) shifted right to to make it easier to read. Note: S5 is inverted by ieee1284_read_status so we don't need to */ static int readstatus(struct parport *port) { return (ieee1284_read_status(port) & 0xf8) >> 3; } static void scanner_chessboard_control(struct parport *port) { /* Wiggle C1 and C3 (twice) */ outboth(port, 0x0, 13); usleep(10); outcont(port, 7, 0xf); usleep(10); outcont(port, 13, 0xf); usleep(10); outcont(port, 7, 0xf); usleep(10); } static void scanner_chessboard_data(struct parport *port, int mode) { int count; /* initial weirdness here for 620P - seems to go quite fast, * just ignore it! */ for (count = 0; count < 2; count++) { /* Wiggle data lines (4 times) while strobing C1 */ /* 33 here for *30P, 55 for *20P */ if (mode == INITMODE_20P) outdata(port, 0x55); else outdata(port, 0x33); outcont(port, HOSTBUSY, HOSTBUSY); usleep(10); outcont(port, 0, HOSTBUSY); usleep(10); outcont(port, HOSTBUSY, HOSTBUSY); usleep(10); if (mode == INITMODE_20P) outdata(port, 0xaa); else outdata(port, 0xcc); outcont(port, HOSTBUSY, HOSTBUSY); usleep(10); outcont(port, 0, HOSTBUSY); usleep(10); outcont(port, HOSTBUSY, HOSTBUSY); usleep(10); } } /* Reset the scanner. At least, it works 50% of the time. */ static int scanner_reset(struct parport *port) { /* Resetting only works for the *30Ps, sorry */ if (readstatus(port) == 0x0b) { /* Init Block 1 - composed of a 0-byte IEEE read */ ieee1284_negotiate(port, 0x0); ieee1284_terminate(port); ieee1284_negotiate(port, 0x0); ieee1284_terminate(port); scanner_chessboard_data(port, 1); scanner_chessboard_data(port, 1); scanner_chessboard_data(port, 1); scanner_chessboard_data(port, 1); scanner_chessboard_data(port, 0); scanner_chessboard_data(port, 0); scanner_chessboard_data(port, 0); scanner_chessboard_data(port, 0); } /* Reset Block 2 =============== */ outboth(port, 0x04, 0x0d); /* Specifically, we want this: 00111 on S */ if (expect(port, "Reset 2 response 1", 0x7, 0x1f, 500000)) return 1; outcont(port, 0, HOSTCLK); usleep(5); outcont(port, 0x0f, 0xf); /* All lines must be 1. */ /* All lines 1 */ if (expect(port, "Reset 2 response 2 (READY)", 0x1f, 0x1f, 500000)) return 1; outcont(port, 0, HOSTBUSY); usleep(100000); /* a short pause */ outcont(port, HOSTBUSY, HOSTBUSY | NSELECTIN); return 0; } /* A timed version of expect, which will wait for delay before erroring This is the one and only one we should be using */ static int expect(struct parport *port, const char *msg, int s, int mask, unsigned int delay) { struct timeval tv; tv.tv_sec = delay / 1000000; tv.tv_usec = delay % 1000000; if (ieee1284_wait_status(port, mask << 3, s << 3, &tv)) { if (msg) DBG(10, "Timeout: %s (0x%02x in 0x%02x) - Status " "= 0x%02x\n", msg, s, mask, readstatus(port)); return 1; } return 0; } int sanei_canon_pp_scanner_init(struct parport *port) { int tries = 0; int tmp = 0; /* Put the scanner in nibble mode */ ieee1284_negotiate(port, 0x0); /* No data to read yet - return to idle mode */ ieee1284_terminate(port); /* In Windows, this is always ECP (or an attempt at it) */ if (sanei_canon_pp_write(port, 10, cmd_init)) return -1; /* Note that we don't really mind what the status was as long as it * wasn't a read error (returns -1) */ /* In fact, the 620P gives an error on that last command, but they * keep going anyway */ if (sanei_canon_pp_check_status(port) < 0) return -1; /* Try until it's ready */ sanei_canon_pp_write(port, 10, cmd_init); while ((tries < 3) && (tmp = sanei_canon_pp_check_status(port))) { if (tmp < 0) return -1; DBG(10, "scanner_init: Giving the scanner a snooze...\n"); usleep(500000); tries++; sanei_canon_pp_write(port, 10, cmd_init); } if (tries == 3) return 1; return 0; } sane-backends-1.0.27/backend/pnm.c0000664000175000017500000010311312775312261013554 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 Andreas Beck Copyright (C) 2000, 2001 Michael Herder Copyright (C) 2001, 2002 Henning Meier-Geinitz Copyright (C) 2008 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #define BUILD 9 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME pnm #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define MAGIC (void *)0xab730324 static int is_open = 0; static int rgb_comp = 0; static int three_pass = 0; static int hand_scanner = 0; static int pass = 0; static char filename[PATH_MAX] = "/tmp/input.ppm"; static SANE_Word status_none = SANE_TRUE; static SANE_Word status_eof = SANE_FALSE; static SANE_Word status_jammed = SANE_FALSE; static SANE_Word status_nodocs = SANE_FALSE; static SANE_Word status_coveropen = SANE_FALSE; static SANE_Word status_ioerror = SANE_FALSE; static SANE_Word status_nomem = SANE_FALSE; static SANE_Word status_accessdenied = SANE_FALSE; static SANE_Word test_option = 0; #ifdef SANE_STATUS_WARMING_UP static SANE_Word warming_up = SANE_FALSE; static struct timeval start; #endif static SANE_Fixed bright = 0; static SANE_Word res = 75; static SANE_Fixed contr = 0; static SANE_Bool gray = SANE_FALSE; static SANE_Bool usegamma = SANE_FALSE; static SANE_Word gamma[4][256]; static enum { ppm_bitmap, ppm_greyscale, ppm_color } ppm_type = ppm_color; static FILE *infile = NULL; static const SANE_Word resbit_list[] = { 17, 75, 90, 100, 120, 135, 150, 165, 180, 195, 200, 210, 225, 240, 255, 270, 285, 300 }; static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 0 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static const SANE_Range gamma_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; typedef enum { opt_num_opts = 0, opt_source_group, opt_filename, opt_resolution, opt_enhancement_group, opt_brightness, opt_contrast, opt_grayify, opt_three_pass, opt_hand_scanner, opt_default_enhancements, opt_read_only, opt_gamma_group, opt_custom_gamma, opt_gamma, opt_gamma_r, opt_gamma_g, opt_gamma_b, opt_status_group, opt_status, opt_status_eof, opt_status_jammed, opt_status_nodocs, opt_status_coveropen, opt_status_ioerror, opt_status_nomem, opt_status_accessdenied, /* must come last: */ num_options } pnm_opts; static SANE_Option_Descriptor sod[] = { { /* opt_num_opts */ SANE_NAME_NUM_OPTIONS, SANE_TITLE_NUM_OPTIONS, SANE_DESC_NUM_OPTIONS, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_source_group */ "", SANE_I18N ("Source Selection"), "", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0, 0, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_filename */ SANE_NAME_FILE, SANE_TITLE_FILE, SANE_DESC_FILE, SANE_TYPE_STRING, SANE_UNIT_NONE, sizeof (filename), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_resolution */ SANE_NAME_SCAN_RESOLUTION, SANE_TITLE_SCAN_RESOLUTION, SANE_DESC_SCAN_RESOLUTION, SANE_TYPE_INT, SANE_UNIT_DPI, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC, SANE_CONSTRAINT_WORD_LIST, {(SANE_String_Const *) resbit_list} } , { /* opt_enhancement_group */ "", SANE_I18N ("Image Enhancement"), "", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0, 0, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_brightness */ SANE_NAME_BRIGHTNESS, SANE_TITLE_BRIGHTNESS, SANE_DESC_BRIGHTNESS, SANE_TYPE_FIXED, SANE_UNIT_PERCENT, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(SANE_String_Const *) & percentage_range} /* this is ANSI conformant! */ } , { /* opt_contrast */ SANE_NAME_CONTRAST, SANE_TITLE_CONTRAST, SANE_DESC_CONTRAST, SANE_TYPE_FIXED, SANE_UNIT_PERCENT, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(SANE_String_Const *) & percentage_range} /* this is ANSI conformant! */ } , { /* opt_grayify */ "grayify", SANE_I18N ("Grayify"), SANE_I18N ("Load the image as grayscale."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_three_pass */ "three-pass", SANE_I18N ("Three-Pass Simulation"), SANE_I18N ("Simulate a three-pass scanner by returning 3 separate frames. " "For kicks, it returns green, then blue, then red."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_hand_scanner */ "hand-scanner", SANE_I18N ("Hand-Scanner Simulation"), SANE_I18N ("Simulate a hand-scanner. Hand-scanners often do not know the " "image height a priori. Instead, they return a height of -1. " "Setting this option allows one to test whether a frontend can " "handle this correctly."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_default_enhancements */ "default-enhancements", SANE_I18N ("Defaults"), SANE_I18N ("Set default values for enhancement controls (brightness & " "contrast)."), SANE_TYPE_BUTTON, SANE_UNIT_NONE, 0, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_read_only */ "read-only", SANE_I18N ("Read only test-option"), SANE_I18N ("Let's see whether frontends can treat this right"), SANE_TYPE_INT, SANE_UNIT_PERCENT, sizeof (SANE_Word), SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_gamma_group */ "", SANE_I18N ("Gamma Tables"), "", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0, 0, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_custom_gamma */ SANE_NAME_CUSTOM_GAMMA, SANE_TITLE_CUSTOM_GAMMA, SANE_DESC_CUSTOM_GAMMA, SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_gamma */ SANE_NAME_GAMMA_VECTOR, SANE_TITLE_GAMMA_VECTOR, SANE_DESC_GAMMA_VECTOR, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word) * 256, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE, SANE_CONSTRAINT_RANGE, {(SANE_String_Const *) & gamma_range} } , { /* opt_gamma_r */ SANE_NAME_GAMMA_VECTOR_R, SANE_TITLE_GAMMA_VECTOR_R, SANE_DESC_GAMMA_VECTOR_R, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word) * 256, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE, SANE_CONSTRAINT_RANGE, {(SANE_String_Const *) & gamma_range} } , { /* opt_gamma_g */ SANE_NAME_GAMMA_VECTOR_G, SANE_TITLE_GAMMA_VECTOR_G, SANE_DESC_GAMMA_VECTOR_G, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word) * 256, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE, SANE_CONSTRAINT_RANGE, {(SANE_String_Const *) & gamma_range} } , { /* opt_gamma_b */ SANE_NAME_GAMMA_VECTOR_B, SANE_TITLE_GAMMA_VECTOR_B, SANE_DESC_GAMMA_VECTOR_B, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word) * 256, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE, SANE_CONSTRAINT_RANGE, {(SANE_String_Const *) & gamma_range} } , { /* opt_status_group */ "", SANE_I18N ("Status Code Simulation"), "", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0, SANE_CAP_ADVANCED, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_status */ "status", SANE_I18N ("Do not force status code"), SANE_I18N ("Do not force the backend to return a status code."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Bool), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_status_eof */ "status-eof", SANE_I18N ("Return SANE_STATUS_EOF"), SANE_I18N ("Force the backend to return the status code SANE_STATUS_EOF " "after sane_read() has been called."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Bool), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_status_jammed */ "status-jammed", SANE_I18N ("Return SANE_STATUS_JAMMED"), SANE_I18N ("Force the backend to return the status code SANE_STATUS_JAMMED " "after sane_read() has been called."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Bool), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_status_nodocs */ "status-nodocs", SANE_I18N ("Return SANE_STATUS_NO_DOCS"), SANE_I18N ("Force the backend to return the status code " "SANE_STATUS_NO_DOCS after sane_read() has been called."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Bool), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_status_coveropen */ "status-coveropen", SANE_I18N ("Return SANE_STATUS_COVER_OPEN"), SANE_I18N ("Force the backend to return the status code " "SANE_STATUS_COVER_OPEN after sane_read() has been called."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Bool), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_status_ioerror */ "status-ioerror", SANE_I18N ("Return SANE_STATUS_IO_ERROR"), SANE_I18N ("Force the backend to return the status code " "SANE_STATUS_IO_ERROR after sane_read() has been called."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Bool), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_status_nomem */ "status-nomem", SANE_I18N ("Return SANE_STATUS_NO_MEM"), SANE_I18N ("Force the backend to return the status code SANE_STATUS_NO_MEM " "after sane_read() has been called."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Bool), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , { /* opt_status_accessdenied */ "status-accessdenied", SANE_I18N ("Return SANE_STATUS_ACCESS_DENIED"), SANE_I18N ("Force the backend to return the status code " "SANE_STATUS_ACCESS_DENIED after sane_read() has been called."), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Bool), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } }; static SANE_Parameters parms = { SANE_FRAME_RGB, 0, 0, /* Number of bytes returned per scan line: */ 0, /* Number of pixels per scan line. */ 0, /* Number of lines for the current scan. */ 8, /* Number of bits per sample. */ }; /* This library is a demo implementation of a SANE backend. It implements a virtual device, a PNM file-filter. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { DBG_INIT (); DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); DBG (1, "sane_init: SANE pnm backend version %d.%d.%d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); return SANE_STATUS_GOOD; } void sane_exit (void) { DBG (2, "sane_exit\n"); return; } /* Device select/open/close */ static const SANE_Device dev[] = { { "0", "Noname", "PNM file reader", "virtual device"}, { "1", "Noname", "PNM file reader", "virtual device"}, #ifdef SANE_STATUS_HW_LOCKED { "locked", "Noname", "Hardware locked", "virtual device"}, #endif #ifdef SANE_STATUS_WARMING_UP { "warmup", "Noname", "Always warming up", "virtual device"}, #endif }; SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { static const SANE_Device *devlist[] = { dev + 0, dev + 1, #ifdef SANE_STATUS_HW_LOCKED dev + 2, #endif #ifdef SANE_STATUS_WARMING_UP dev + 3, #endif 0 }; DBG (2, "sane_get_devices: local_only = %d\n", local_only); *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { int i; if (!devicename) return SANE_STATUS_INVAL; DBG (2, "sane_open: devicename = \"%s\"\n", devicename); if (!devicename[0]) i = 0; else for (i = 0; i < NELEMS (dev); ++i) if (strcmp (devicename, dev[i].name) == 0) break; if (i >= NELEMS (dev)) return SANE_STATUS_INVAL; if (is_open) return SANE_STATUS_DEVICE_BUSY; is_open = 1; *handle = MAGIC; for (i = 0; i < 256; i++) { gamma[0][i] = i; gamma[1][i] = i; gamma[2][i] = i; gamma[3][i] = i; } #ifdef SANE_STATUS_HW_LOCKED if(strncmp(devicename,"locked",6)==0) return SANE_STATUS_HW_LOCKED; #endif #ifdef SANE_STATUS_WARMING_UP if(strncmp(devicename,"warmup",6)==0) { warming_up = SANE_TRUE; start.tv_sec = 0; } #endif return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { DBG (2, "sane_close\n"); if (handle == MAGIC) is_open = 0; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { DBG (2, "sane_get_option_descriptor: option = %d\n", option); if (handle != MAGIC || !is_open) return NULL; /* wrong device */ if (option < 0 || option >= NELEMS (sod)) return NULL; return &sod[option]; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { SANE_Int myinfo = 0; SANE_Status status; int v; v = 75; DBG (2, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", handle, option, action, value, (void *) info); if (handle != MAGIC || !is_open) { DBG (1, "sane_control_option: unknown handle or not open\n"); return SANE_STATUS_INVAL; /* Unknown handle ... */ } if (option < 0 || option >= NELEMS (sod)) { DBG (1, "sane_control_option: option %d < 0 or >= number of options\n", option); return SANE_STATUS_INVAL; /* Unknown option ... */ } if (!SANE_OPTION_IS_ACTIVE (sod[option].cap)) { DBG (4, "sane_control_option: option is inactive\n"); return SANE_STATUS_INVAL; } switch (action) { case SANE_ACTION_SET_AUTO: if (!SANE_OPTION_IS_SETTABLE (sod[option].cap)) { DBG (4, "sane_control_option: option is not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (sod + option, (void *) &v, &myinfo); if (status != SANE_STATUS_GOOD) return status; switch (option) { case opt_resolution: res = 75; myinfo |= SANE_INFO_RELOAD_PARAMS; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE (sod[option].cap)) { DBG (4, "sane_control_option: option is not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (sod + option, value, &myinfo); if (status != SANE_STATUS_GOOD) return status; switch (option) { case opt_filename: if ((strlen (value) + 1) > sizeof (filename)) return SANE_STATUS_NO_MEM; strcpy (filename, value); myinfo |= SANE_INFO_RELOAD_PARAMS; break; case opt_resolution: res = *(SANE_Word *) value; break; case opt_brightness: bright = *(SANE_Word *) value; break; case opt_contrast: contr = *(SANE_Word *) value; break; case opt_grayify: gray = !!*(SANE_Word *) value; if (usegamma) { if (gray) { sod[opt_gamma].cap &= ~SANE_CAP_INACTIVE; sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE; } else { sod[opt_gamma].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_r].cap &= ~SANE_CAP_INACTIVE; sod[opt_gamma_g].cap &= ~SANE_CAP_INACTIVE; sod[opt_gamma_b].cap &= ~SANE_CAP_INACTIVE; } } else { sod[opt_gamma].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE; } myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case opt_three_pass: three_pass = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; break; case opt_hand_scanner: hand_scanner = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; break; case opt_default_enhancements: bright = contr = 0; myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_custom_gamma: usegamma = *(SANE_Word *) value; /* activate/deactivate gamma */ if (usegamma) { test_option = 100; if (gray) { sod[opt_gamma].cap &= ~SANE_CAP_INACTIVE; sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE; } else { sod[opt_gamma].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_r].cap &= ~SANE_CAP_INACTIVE; sod[opt_gamma_g].cap &= ~SANE_CAP_INACTIVE; sod[opt_gamma_b].cap &= ~SANE_CAP_INACTIVE; } } else { test_option = 0; sod[opt_gamma].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_r].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_g].cap |= SANE_CAP_INACTIVE; sod[opt_gamma_b].cap |= SANE_CAP_INACTIVE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_gamma: memcpy (&gamma[0][0], (SANE_Word *) value, 256 * sizeof (SANE_Word)); myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_gamma_r: memcpy (&gamma[1][0], (SANE_Word *) value, 256 * sizeof (SANE_Word)); myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_gamma_g: memcpy (&gamma[2][0], (SANE_Word *) value, 256 * sizeof (SANE_Word)); myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_gamma_b: memcpy (&gamma[3][0], (SANE_Word *) value, 256 * sizeof (SANE_Word)); myinfo |= SANE_INFO_RELOAD_OPTIONS; break; /* status */ case opt_status: status_none = *(SANE_Word *) value; if (status_none) { status_eof = SANE_FALSE; status_jammed = SANE_FALSE; status_nodocs = SANE_FALSE; status_coveropen = SANE_FALSE; status_ioerror = SANE_FALSE; status_nomem = SANE_FALSE; status_accessdenied = SANE_FALSE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_status_eof: status_eof = *(SANE_Word *) value; if (status_eof) { status_none = SANE_FALSE; status_jammed = SANE_FALSE; status_nodocs = SANE_FALSE; status_coveropen = SANE_FALSE; status_ioerror = SANE_FALSE; status_nomem = SANE_FALSE; status_accessdenied = SANE_FALSE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_status_jammed: status_jammed = *(SANE_Word *) value; if (status_jammed) { status_eof = SANE_FALSE; status_none = SANE_FALSE; status_nodocs = SANE_FALSE; status_coveropen = SANE_FALSE; status_ioerror = SANE_FALSE; status_nomem = SANE_FALSE; status_accessdenied = SANE_FALSE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_status_nodocs: status_nodocs = *(SANE_Word *) value; if (status_nodocs) { status_eof = SANE_FALSE; status_jammed = SANE_FALSE; status_none = SANE_FALSE; status_coveropen = SANE_FALSE; status_ioerror = SANE_FALSE; status_nomem = SANE_FALSE; status_accessdenied = SANE_FALSE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_status_coveropen: status_coveropen = *(SANE_Word *) value; if (status_coveropen) { status_eof = SANE_FALSE; status_jammed = SANE_FALSE; status_nodocs = SANE_FALSE; status_none = SANE_FALSE; status_ioerror = SANE_FALSE; status_nomem = SANE_FALSE; status_accessdenied = SANE_FALSE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_status_ioerror: status_ioerror = *(SANE_Word *) value; if (status_ioerror) { status_eof = SANE_FALSE; status_jammed = SANE_FALSE; status_nodocs = SANE_FALSE; status_coveropen = SANE_FALSE; status_none = SANE_FALSE; status_nomem = SANE_FALSE; status_accessdenied = SANE_FALSE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_status_nomem: status_nomem = *(SANE_Word *) value; if (status_nomem) { status_eof = SANE_FALSE; status_jammed = SANE_FALSE; status_nodocs = SANE_FALSE; status_coveropen = SANE_FALSE; status_ioerror = SANE_FALSE; status_none = SANE_FALSE; status_accessdenied = SANE_FALSE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case opt_status_accessdenied: status_accessdenied = *(SANE_Word *) value; if (status_accessdenied) { status_eof = SANE_FALSE; status_jammed = SANE_FALSE; status_nodocs = SANE_FALSE; status_coveropen = SANE_FALSE; status_ioerror = SANE_FALSE; status_nomem = SANE_FALSE; status_none = SANE_FALSE; } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_GET_VALUE: switch (option) { case opt_num_opts: *(SANE_Word *) value = NELEMS (sod); break; case opt_filename: strcpy (value, filename); break; case opt_resolution: *(SANE_Word *) value = res; break; case opt_brightness: *(SANE_Word *) value = bright; break; case opt_contrast: *(SANE_Word *) value = contr; break; case opt_grayify: *(SANE_Word *) value = gray; break; case opt_three_pass: *(SANE_Word *) value = three_pass; break; case opt_hand_scanner: *(SANE_Word *) value = hand_scanner; break; case opt_read_only: *(SANE_Word *) value = test_option; break; case opt_custom_gamma: *(SANE_Word *) value = usegamma; break; case opt_gamma: memcpy ((SANE_Word *) value, &gamma[0][0], 256 * sizeof (SANE_Word)); break; case opt_gamma_r: memcpy ((SANE_Word *) value, &gamma[1][0], 256 * sizeof (SANE_Word)); break; case opt_gamma_g: memcpy ((SANE_Word *) value, &gamma[2][0], 256 * sizeof (SANE_Word)); break; case opt_gamma_b: memcpy ((SANE_Word *) value, &gamma[3][0], 256 * sizeof (SANE_Word)); break; case opt_status: *(SANE_Word *) value = status_none; break; case opt_status_eof: *(SANE_Word *) value = status_eof; break; case opt_status_jammed: *(SANE_Word *) value = status_jammed; break; case opt_status_nodocs: *(SANE_Word *) value = status_nodocs; break; case opt_status_coveropen: *(SANE_Word *) value = status_coveropen; break; case opt_status_ioerror: *(SANE_Word *) value = status_ioerror; break; case opt_status_nomem: *(SANE_Word *) value = status_nomem; break; case opt_status_accessdenied: *(SANE_Word *) value = status_accessdenied; break; default: return SANE_STATUS_INVAL; } break; } if (info) *info = myinfo; return SANE_STATUS_GOOD; } static void get_line (char *buf, int len, FILE * f) { do fgets (buf, len, f); while (*buf == '#'); } static int getparmfromfile (void) { FILE *fn; int x, y; char buf[1024]; parms.depth = 8; parms.bytes_per_line = parms.pixels_per_line = parms.lines = 0; if ((fn = fopen (filename, "rb")) == NULL) { DBG (1, "getparmfromfile: unable to open file \"%s\"\n", filename); return -1; } /* Skip comments. */ do get_line (buf, sizeof (buf), fn); while (*buf == '#'); if (!strncmp (buf, "P4", 2)) { /* Binary monochrome. */ parms.depth = 1; ppm_type = ppm_bitmap; } else if (!strncmp (buf, "P5", 2)) { /* Grayscale. */ parms.depth = 8; ppm_type = ppm_greyscale; } else if (!strncmp (buf, "P6", 2)) { /* Color. */ parms.depth = 8; ppm_type = ppm_color; } else { DBG (1, "getparmfromfile: %s is not a recognized PPM\n", filename); fclose (fn); return -1; } /* Skip comments. */ do get_line (buf, sizeof (buf), fn); while (*buf == '#'); sscanf (buf, "%d %d", &x, &y); parms.last_frame = SANE_TRUE; parms.bytes_per_line = (ppm_type == ppm_bitmap) ? (x + 7) / 8 : x; parms.pixels_per_line = x; if (hand_scanner) parms.lines = -1; else parms.lines = y; if ((ppm_type == ppm_greyscale) || (ppm_type == ppm_bitmap) || gray) parms.format = SANE_FRAME_GRAY; else { if (three_pass) { parms.format = SANE_FRAME_RED + (pass + 1) % 3; parms.last_frame = (pass >= 2); } else { parms.format = SANE_FRAME_RGB; parms.bytes_per_line *= 3; } } fclose (fn); return 0; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int rc = SANE_STATUS_GOOD; DBG (2, "sane_get_parameters\n"); if (handle != MAGIC || !is_open) rc = SANE_STATUS_INVAL; /* Unknown handle ... */ else if (getparmfromfile ()) rc = SANE_STATUS_INVAL; *params = parms; return rc; } SANE_Status sane_start (SANE_Handle handle) { char buf[1024]; int nlines; #ifdef SANE_STATUS_WARMING_UP struct timeval current; #endif DBG (2, "sane_start\n"); rgb_comp = 0; if (handle != MAGIC || !is_open) return SANE_STATUS_INVAL; /* Unknown handle ... */ #ifdef SANE_STATUS_WARMING_UP if(warming_up == SANE_TRUE) { gettimeofday(¤t,NULL); if(current.tv_sec-start.tv_sec>5) { start.tv_sec = current.tv_sec; return SANE_STATUS_WARMING_UP; } if(current.tv_sec-start.tv_sec<5) return SANE_STATUS_WARMING_UP; } #endif if (infile != NULL) { fclose (infile); infile = NULL; if (!three_pass || ++pass >= 3) return SANE_STATUS_EOF; } if (getparmfromfile ()) return SANE_STATUS_INVAL; if ((infile = fopen (filename, "rb")) == NULL) { DBG (1, "sane_start: unable to open file \"%s\"\n", filename); return SANE_STATUS_INVAL; } /* Skip the header (only two lines for a bitmap). */ nlines = (ppm_type == ppm_bitmap) ? 1 : 0; while (nlines < 3) { /* Skip comments. */ get_line (buf, sizeof (buf), infile); if (*buf != '#') nlines++; } return SANE_STATUS_GOOD; } static SANE_Int rgblength = 0; static SANE_Byte *rgbbuf = 0; static SANE_Byte rgbleftover[3] = { 0, 0, 0 }; SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { int len, x, hlp; DBG (2, "sane_read: max_length = %d, rgbleftover = {%d, %d, %d}\n", max_length, rgbleftover[0], rgbleftover[1], rgbleftover[2]); if (!length) { DBG (1, "sane_read: length == NULL\n"); return SANE_STATUS_INVAL; } *length = 0; if (!data) { DBG (1, "sane_read: data == NULL\n"); return SANE_STATUS_INVAL; } if (handle != MAGIC) { DBG (1, "sane_read: unknown handle\n"); return SANE_STATUS_INVAL; } if (!is_open) { DBG (1, "sane_read: call sane_open first\n"); return SANE_STATUS_INVAL; } if (!infile) { DBG (1, "sane_read: scan was cancelled\n"); return SANE_STATUS_CANCELLED; } if (feof (infile)) { DBG (2, "sane_read: EOF reached\n"); return SANE_STATUS_EOF; } if (status_jammed == SANE_TRUE) return SANE_STATUS_JAMMED; if (status_eof == SANE_TRUE) return SANE_STATUS_EOF; if (status_nodocs == SANE_TRUE) return SANE_STATUS_NO_DOCS; if (status_coveropen == SANE_TRUE) return SANE_STATUS_COVER_OPEN; if (status_ioerror == SANE_TRUE) return SANE_STATUS_IO_ERROR; if (status_nomem == SANE_TRUE) return SANE_STATUS_NO_MEM; if (status_accessdenied == SANE_TRUE) return SANE_STATUS_ACCESS_DENIED; /* Allocate a buffer for the RGB values. */ if (ppm_type == ppm_color && (gray || three_pass)) { SANE_Byte *p, *q, *rgbend; if (rgbbuf == 0 || rgblength < 3 * max_length) { /* Allocate a new rgbbuf. */ free (rgbbuf); rgblength = 3 * max_length; rgbbuf = malloc (rgblength); if (rgbbuf == 0) return SANE_STATUS_NO_MEM; } else rgblength = 3 * max_length; /* Copy any leftovers into the buffer. */ q = rgbbuf; p = rgbleftover + 1; while (p - rgbleftover <= rgbleftover[0]) *q++ = *p++; /* Slurp in the RGB buffer. */ len = fread (q, 1, rgblength - rgbleftover[0], infile); rgbend = rgbbuf + len; q = data; if (gray) { /* Zip through the buffer, converting color data to grayscale. */ for (p = rgbbuf; p < rgbend; p += 3) *q++ = ((long) p[0] + p[1] + p[2]) / 3; } else { /* Zip through the buffer, extracting data for this pass. */ for (p = (rgbbuf + (pass + 1) % 3); p < rgbend; p += 3) *q++ = *p; } /* Save any leftovers in the array. */ rgbleftover[0] = len % 3; p = rgbbuf + (len - rgbleftover[0]); q = rgbleftover + 1; while (p < rgbend) *q++ = *p++; len /= 3; } else /* Suck in as much of the file as possible, since it's already in the correct format. */ len = fread (data, 1, max_length, infile); if (len == 0) { if (feof (infile)) { DBG (2, "sane_read: EOF reached\n"); return SANE_STATUS_EOF; } else { DBG (1, "sane_read: error while reading file (%s)\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } } if (parms.depth == 8) { /* Do the transformations ... DEMO ONLY ! THIS MAKES NO SENSE ! */ for (x = 0; x < len; x++) { hlp = *((unsigned char *) data + x) - 128; hlp *= (contr + (100 << SANE_FIXED_SCALE_SHIFT)); hlp /= 100 << SANE_FIXED_SCALE_SHIFT; hlp += (bright >> SANE_FIXED_SCALE_SHIFT) + 128; if (hlp < 0) hlp = 0; if (hlp > 255) hlp = 255; *(data + x) = hlp; } /*gamma */ if (usegamma) { unsigned char uc; if (gray) { for (x = 0; x < len; x++) { uc = *((unsigned char *) data + x); uc = gamma[0][uc]; *(data + x) = uc; } } else { for (x = 0; x < len; x++) { if (parms.format == SANE_FRAME_RGB) { uc = *((unsigned char *) (data + x)); uc = (unsigned char) gamma[rgb_comp + 1][(int) uc]; *((unsigned char *) data + x) = uc; rgb_comp += 1; if (rgb_comp > 2) rgb_comp = 0; } else { int f = 0; if (parms.format == SANE_FRAME_RED) f = 1; if (parms.format == SANE_FRAME_GREEN) f = 2; if (parms.format == SANE_FRAME_BLUE) f = 3; if (f) { uc = *((unsigned char *) (data + x)); uc = (unsigned char) gamma[f][(int) uc]; *((unsigned char *) data + x) = uc; } } } } } } *length = len; DBG (2, "sane_read: read %d bytes\n", len); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { DBG (2, "sane_cancel: handle = %p\n", handle); pass = 0; if (infile != NULL) { fclose (infile); infile = NULL; } return; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, non_blocking); if (!infile) { DBG (1, "sane_set_io_mode: not scanning\n"); return SANE_STATUS_INVAL; } if (non_blocking) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", handle, fd ? "!=" : "="); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/umax_pp_mid.c0000664000175000017500000002473212775277260015306 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2012 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Umax PP flatbed scanners. */ #define DEBUG_DECLARE_ONLY #undef BACKEND_NAME #define BACKEND_NAME umax_pp #include "../include/sane/config.h" #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include "../include/sane/sanei_debug.h" #define __MAIN__ #include "umax_pp_mid.h" /* this function locks the parallel port so that other devices */ /* won't interfere. Returns UMAX1220P_BUSY is port cannot be */ /* lock or UMAX1220P_OK if it is locked */ static int locked = 0; #ifdef HAVE_LINUX_PPDEV_H static int exmode = IEEE1284_MODE_COMPAT; static int exflags = 0; #endif static int lock_parport (void) { #ifdef HAVE_LINUX_PPDEV_H int mode, fd; #endif DBG_INIT (); DBG (3, "lock_parport\n"); #ifdef HAVE_LINUX_PPDEV_H fd = sanei_umax_pp_getparport (); if ((fd > 0) && (!locked)) { if (ioctl (sanei_umax_pp_getparport (), PPCLAIM)) { return UMAX1220P_BUSY; } #ifdef PPGETMODE if (ioctl (fd, PPGETMODE, &exmode)) exmode = IEEE1284_MODE_COMPAT; if (ioctl (fd, PPGETFLAGS, &exflags)) exflags = 0; #endif mode = IEEE1284_MODE_EPP; ioctl (fd, PPNEGOT, &mode); ioctl (fd, PPSETMODE, &mode); locked = 1; } #else locked = 1; #endif return UMAX1220P_OK; } /* this function release parport */ static int unlock_parport (void) { #ifdef HAVE_LINUX_PPDEV_H int fd, mode; fd = sanei_umax_pp_getparport (); if ((fd > 0) && (locked)) { mode = IEEE1284_MODE_COMPAT; ioctl (fd, PPNEGOT, &mode); ioctl (fd, PPSETMODE, &exmode); #ifdef PPSETFLAGS ioctl (fd, PPSETFLAGS, &exflags); #endif ioctl (fd, PPRELEASE); locked = 1; } #endif DBG (3, "unlock_parport\n"); locked = 0; return UMAX1220P_OK; } /* * * This function recognize the scanner model by sending an image * filter command. 1220P will use it as is, but 2000P will return * it back modified. * */ int sanei_umax_pp_model (int port, int *model) { int recover = 0, rc; /* set up port */ DBG (3, "sanei_umax_pp_model\n"); sanei_umax_pp_setport (port); if (lock_parport () == UMAX1220P_BUSY) return UMAX1220P_BUSY; /* init transport layer */ /* 0: failed 1: success 2: retry 3: busy */ do { rc = sanei_umax_pp_initTransport (recover); } while (rc == 2); if (rc == 3) { unlock_parport (); return UMAX1220P_BUSY; } if (rc != 1) { DBG (0, "sanei_umax_pp_initTransport() failed (%s:%d)\n", __FILE__, __LINE__); unlock_parport (); return UMAX1220P_TRANSPORT_FAILED; } /* check model only, and if only none given in conf file */ if (!sanei_umax_pp_getastra ()) { rc = sanei_umax_pp_checkModel (); } else { rc = sanei_umax_pp_getastra (); } sanei_umax_pp_endSession (); unlock_parport (); if (rc < 600) { DBG (0, "sanei_umax_pp_CheckModel() failed (%s:%d)\n", __FILE__, __LINE__); return UMAX1220P_PROBE_FAILED; } *model = rc; /* OK */ return UMAX1220P_OK; } int sanei_umax_pp_attach (int port, char *name) { int recover = 0; /* set up port */ if (name == NULL) { DBG (3, "sanei_umax_pp_attach(%d,NULL)\n", port); } else { DBG (3, "sanei_umax_pp_attach(%d,%s)\n", port, name); } sanei_umax_pp_setport (port); if (sanei_umax_pp_initPort (port, name) != 1) return UMAX1220P_PROBE_FAILED; /* init port locks the port, so we flag that */ locked = 1; if (sanei_umax_pp_probeScanner (recover) != 1) { if (recover) { sanei_umax_pp_initTransport (recover); sanei_umax_pp_endSession (); if (sanei_umax_pp_probeScanner (recover) != 1) { DBG (0, "Recover failed ....\n"); unlock_parport (); return UMAX1220P_PROBE_FAILED; } } else { unlock_parport (); return UMAX1220P_PROBE_FAILED; } } sanei_umax_pp_endSession (); unlock_parport (); /* OK */ return UMAX1220P_OK; } int sanei_umax_pp_open (int port, char *name) { int rc; int recover = 0; /* set up port */ DBG (3, "sanei_umax_pp_open\n"); if (name == NULL) sanei_umax_pp_setport (port); if (lock_parport () == UMAX1220P_BUSY) return UMAX1220P_BUSY; /* init transport layer */ /* 0: failed 1: success 2: retry 3: scanner busy */ do { rc = sanei_umax_pp_initTransport (recover); } while (rc == 2); if (rc == 3) { unlock_parport (); return UMAX1220P_BUSY; } if (rc != 1) { DBG (0, "sanei_umax_pp_initTransport() failed (%s:%d)\n", __FILE__, __LINE__); unlock_parport (); return UMAX1220P_TRANSPORT_FAILED; } /* init scanner */ if (sanei_umax_pp_initScanner (recover) == 0) { DBG (0, "sanei_umax_pp_initScanner() failed (%s:%d)\n", __FILE__, __LINE__); sanei_umax_pp_endSession (); unlock_parport (); return UMAX1220P_SCANNER_FAILED; } /* OK */ unlock_parport (); return UMAX1220P_OK; } int sanei_umax_pp_cancel (void) { DBG (3, "sanei_umax_pp_cancel\n"); if (lock_parport () == UMAX1220P_BUSY) return UMAX1220P_BUSY; /* maybe EPAT reset here if exists */ sanei_umax_pp_cmdSync (0xC2); sanei_umax_pp_cmdSync (0x00); sanei_umax_pp_cmdSync (0x00); if (sanei_umax_pp_park () == 0) { DBG (0, "sanei_umax_pp_park failed !!! (%s:%d)\n", __FILE__, __LINE__); unlock_parport (); return UMAX1220P_PARK_FAILED; } /* endSession() cancels any pending command */ /* such as parking ...., so we only return */ unlock_parport (); return UMAX1220P_OK; } int sanei_umax_pp_start (int x, int y, int width, int height, int dpi, int color, int autoset, int gain, int offset, int *rbpp, int *rtw, int *rth) { int col = BW_MODE; DBG (3, "sanei_umax_pp_start\n"); if (lock_parport () == UMAX1220P_BUSY) return UMAX1220P_BUSY; /* end session isn't done by cancel any more */ sanei_umax_pp_endSession (); if (autoset) sanei_umax_pp_setauto (1); else sanei_umax_pp_setauto (0); switch (color) { case 0: col = BW2_MODE; break; case 1: col = BW_MODE; break; case 2: col = RGB_MODE; break; } if (sanei_umax_pp_startScan (x + sanei_umax_pp_getLeft (), y, width, height, dpi, col, gain, offset, rbpp, rtw, rth) != 1) { sanei_umax_pp_endSession (); unlock_parport (); return UMAX1220P_START_FAILED; } unlock_parport (); return UMAX1220P_OK; } int sanei_umax_pp_read (long len, int window, int dpi, int last, unsigned char *buffer) { int read = 0; int bytes; DBG (3, "sanei_umax_pp_read\n"); if (lock_parport () == UMAX1220P_BUSY) return UMAX1220P_BUSY; /* since 610P may override len and last to meet its */ /* hardware requirements, we have to loop until we */ /* have all the data */ while (read < len) { bytes = sanei_umax_pp_readBlock (len - read, window, dpi, last, buffer + read); if (bytes == 0) { sanei_umax_pp_endSession (); return UMAX1220P_READ_FAILED; } read += bytes; } unlock_parport (); return UMAX1220P_OK; } int sanei_umax_pp_lamp (int on) { /* init transport layer */ DBG (3, "sanei_umax_pp_lamp\n"); /* no lamp support for 610P ... */ if (sanei_umax_pp_getastra () < 1210) return UMAX1220P_OK; if (lock_parport () == UMAX1220P_BUSY) return UMAX1220P_BUSY; if (sanei_umax_pp_setLamp (on) == 0) { DBG (0, "Setting lamp state failed!\n"); } unlock_parport (); return UMAX1220P_OK; } int sanei_umax_pp_status (void) { int status; DBG (3, "sanei_umax_pp_status\n"); if (lock_parport () == UMAX1220P_BUSY) return UMAX1220P_BUSY; /* check if head is at home */ sanei_umax_pp_cmdSync (0x40); status = sanei_umax_pp_scannerStatus (); unlock_parport (); DBG (8, "sanei_umax_pp_status=0x%02X\n", status); if (((status & ASIC_BIT) != 0x00)||((status & MOTOR_BIT) == 0x00)) return UMAX1220P_BUSY; return UMAX1220P_OK; } int sanei_umax_pp_close () { #ifdef HAVE_LINUX_PPDEV_H int fd; #endif DBG (3, "sanei_umax_pp_close\n"); lock_parport (); sanei_umax_pp_endSession (); unlock_parport (); #ifdef HAVE_LINUX_PPDEV_H fd = sanei_umax_pp_getparport (); if (fd > 0) { close (fd); sanei_umax_pp_setparport (0); } #endif return UMAX1220P_OK; } sane-backends-1.0.27/backend/hp-scsi.h0000664000175000017500000000664512112021330014324 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ #ifndef HP_SCSI_INCLUDED #define HP_SCSI_INCLUDED #define HP_SCSI_MAX_WRITE (2048) SANE_Status sanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect); SANE_Status sanei_hp_scsi_new (HpScsi * newp, const char * devname); void sanei_hp_scsi_destroy (HpScsi this,int completely); hp_byte_t * sanei_hp_scsi_inq (HpScsi this); const char *sanei_hp_scsi_model (HpScsi this); const char *sanei_hp_scsi_vendor (HpScsi this); const char *sanei_hp_scsi_devicename (HpScsi this); SANE_Status sanei_hp_scsi_pipeout (HpScsi this, int outfd, HpProcessData *pdescr); SANE_Status sanei_hp_scl_calibrate (HpScsi scsi); SANE_Status sanei_hp_scl_startScan (HpScsi scsi, HpScl scl); SANE_Status sanei_hp_scl_reset (HpScsi scsi); SANE_Status sanei_hp_scl_clearErrors (HpScsi scsi); SANE_Status sanei_hp_scl_errcheck (HpScsi scsi); SANE_Status sanei_hp_scl_upload_binary (HpScsi scsi, HpScl scl, size_t *lengthhp, char **bufhp); SANE_Status sanei_hp_scl_set (HpScsi scsi, HpScl scl, int val); SANE_Status sanei_hp_scl_inquire(HpScsi scsi, HpScl scl, int * valp, int * minp, int * maxp); SANE_Status sanei_hp_scl_upload (HpScsi scsi, HpScl scl, void * buf, size_t sz); SANE_Status sanei_hp_scl_download (HpScsi scsi, HpScl scl, const void * buf, size_t sz); #endif /* HP_SCSI_INCLUDED */ sane-backends-1.0.27/backend/teco2.h0000664000175000017500000003303112112021330013757 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) Copyright (C) 2003-2005 Gerard Klaver (gerard at gkall dot hobby dot nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ */ /* Commands supported by the scanner. */ #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_REQUEST_SENSE 0x03 #define SCSI_VENDOR_06 0x06 #define SCSI_VENDOR_09 0x09 #define SCSI_VENDOR_0C 0x0C #define SCSI_VENDOR_0E 0x0E #define SCSI_INQUIRY 0x12 #define SCSI_SCAN 0x1b #define SCSI_VENDOR_1C 0x1C #define SCSI_SET_WINDOW 0x24 #define SCSI_SEND_10 0x2a #define SCSI_READ_10 0x28 #define SCSI_OBJECT_POSITION 0x31 #define SCSI_GET_DATA_BUFFER_STATUS 0x34 typedef struct { unsigned char data[16]; int len; } CDB; /* Set a specific bit depending on a boolean. * MKSCSI_BIT(TRUE, 3) will generate 0x08. */ #define MKSCSI_BIT(bit, pos) ((bit)? 1<<(pos): 0) /* Set a value in a range of bits. * MKSCSI_I2B(5, 3, 5) will generate 0x28 */ #define MKSCSI_I2B(bits, pos_b, pos_e) ((bits) << (pos_b) & ((1<<((pos_e)-(pos_b)+1))-1)) /* Store an integer in 2, 3 or 4 byte in an array. */ #define Ito16(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 0) & 0xff; \ } #define Ito24(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 0) & 0xff; \ } #define Ito32(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 24) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[3] = ((val) >> 0) & 0xff; \ } #define MKSCSI_GET_DATA_BUFFER_STATUS(cdb, wait, buflen) \ cdb.data[0] = SCSI_GET_DATA_BUFFER_STATUS; \ cdb.data[1] = MKSCSI_BIT(wait, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = 0; \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_INQUIRY(cdb, buflen) \ cdb.data[0] = SCSI_INQUIRY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_MODE_SELECT(cdb, pf, sp, buflen) \ cdb.data[0] = SCSI_MODE_SELECT; \ cdb.data[1] = MKSCSI_BIT(pf, 4) | MKSCSI_BIT(sp, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_OBJECT_POSITION(cdb, position) \ cdb.data[0] = SCSI_OBJECT_POSITION; \ cdb.data[1] = 0; \ cdb.data[2] = (((position) >> 16) & 0xff); \ cdb.data[3] = (((position) >> 8) & 0xff); \ cdb.data[4] = (((position) >> 0) & 0xff); \ cdb.data[5] = 0; \ cdb.data[6] = 0; \ cdb.data[7] = 0; \ cdb.data[8] = 0; \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_SET_WINDOW(cdb, buflen) \ cdb.data[0] = SCSI_SET_WINDOW; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_READ_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_READ_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_REQUEST_SENSE(cdb, buflen) \ cdb.data[0] = SCSI_REQUEST_SENSE; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = (buflen); \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SCAN(cdb) \ cdb.data[0] = SCSI_SCAN; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SEND_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_SEND_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_TEST_UNIT_READY(cdb) \ cdb.data[0] = SCSI_TEST_UNIT_READY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_VENDOR_SPEC(cdb, command, length) { \ assert(length == 6 || length == 10 || length == 12 || length == 16); \ memset(cdb.data, 0, length); \ cdb.data[0] = command; \ cdb.len = length; \ } /*--------------------------------------------------------------------------*/ static inline int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /*--------------------------------------------------------------------------*/ #define mmToIlu(mm) (((mm) * dev->def->x_resolution_max) / MM_PER_INCH) #define iluToMm(ilu) (((ilu) * MM_PER_INCH) / dev->def->x_resolution_max) /*--------------------------------------------------------------------------*/ #define GAMMA_LENGTH 0x400 /* number of value per color */ /*--------------------------------------------------------------------------*/ /* Black magic for color adjustment. Used only for VM3575. */ struct dpi_color_adjust { int resolution; /* in dpi. 0 means all resolution supported. */ #if 0 int z1_color_0; /* 0, 1 or 2 */ int z1_color_1; /* idem */ int z1_color_2; /* idem */ #endif int z3_color_0; /* 0, 1 or 2 */ int z3_color_1; /* idem */ int z3_color_2; /* idem */ int factor_x; int color_shift; /* color plane shift in pixel. If a * negative shift seems necessary, set * factor_x to 1 */ }; /*--------------------------------------------------------------------------*/ enum Teco_Option { /* Must come first */ OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* scanner modes */ OPT_RESOLUTION, /* X and Y resolution */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* upper left X */ OPT_TL_Y, /* upper left Y */ OPT_BR_X, /* bottom right X */ OPT_BR_Y, /* bottom right Y */ OPT_ENHANCEMENT_GROUP, OPT_CUSTOM_GAMMA, /* Use the custom gamma tables */ OPT_GAMMA_VECTOR_R, /* Custom Red gamma table */ OPT_GAMMA_VECTOR_G, /* Custom Green Gamma table */ OPT_GAMMA_VECTOR_B, /* Custom Blue Gamma table */ OPT_GAMMA_VECTOR_GRAY, /* Custom Grayscale Gamma table */ OPT_DITHER, OPT_FILTER_COLOR, /* which color to filter */ OPT_THRESHOLD, /* Threshold */ OPT_WHITE_LEVEL_R, /* white level correction RED */ OPT_WHITE_LEVEL_G, /* white level correction GREEN */ OPT_WHITE_LEVEL_B, /* white level correction BLUE */ OPT_PREVIEW, /* must come last: */ OPT_NUM_OPTIONS }; /*--------------------------------------------------------------------------*/ /* * Scanner supported by this backend. */ struct scanners_supported { int scsi_type; char scsi_teco_name[12]; /* real name of the scanner */ enum { TECO_VM3564, TECO_VM356A, TECO_VM3575, TECO_VM6575, TECO_VM656A, TECO_VM6586 } tecoref; char *real_vendor; /* brand on the box */ char *real_product; /* name on the box */ SANE_Range res_range; int x_resolution_max; /* maximum X dpi */ int y_resolution_max; /* maximum Y dpi */ int cal_length; /* size of a calibration line in pixels */ int cal_lines; /* number of calibration lines to read */ int cal_col_len; /* number of byte to code one color */ int cal_algo; /* default algo to use to compute calibration line */ /* Minimum and maximum width and length supported. */ SANE_Range x_range; SANE_Range y_range; /* Resolutions supported in color mode. */ const struct dpi_color_adjust *color_adjust; }; /*--------------------------------------------------------------------------*/ /* Define a scanner occurence. */ typedef struct Teco_Scanner { struct Teco_Scanner *next; SANE_Device sane; char *devicename; int sfd; /* device handle */ /* Infos from inquiry. */ char scsi_type; char scsi_vendor[9]; char scsi_product[17]; char scsi_version[5]; char scsi_teco_name[12]; /* real name of the scanner */ /* SCSI handling */ size_t buffer_size; /* size of the buffer */ SANE_Byte *buffer; /* for SCSI transfer. */ /* Scanner infos. */ const struct scanners_supported *def; /* default options for that scanner */ SANE_Word *resolutions_list; /* Scanning handling. */ int scanning; /* TRUE if a scan is running. */ int x_resolution; /* X resolution in DPI */ int y_resolution; /* Y resolution in DPI */ int x_tl; /* X top left */ int y_tl; /* Y top left */ int x_br; /* X bottom right */ int y_br; /* Y bottom right */ int width; /* width of the scan area in mm */ int length; /* length of the scan area in mm */ int depth; /* depth per color */ enum { TECO_BW, TECO_GRAYSCALE, TECO_COLOR } scan_mode; size_t bytes_left; /* number of bytes left to give to the backend */ size_t real_bytes_left; /* number of bytes left the scanner will return. */ SANE_Byte *image; /* keep the raw image here */ size_t image_size; /* allocated size of image */ size_t image_begin; /* first significant byte in image */ size_t image_end; /* first free byte in image */ const struct dpi_color_adjust *color_adjust; size_t bytes_per_raster; /* bytes per raster. In B&W and Gray, that the same as param.bytes_per_lines. In Color, it's a third. */ int raster_size; /* size of a raster */ int raster_num; /* for color scan, current raster read */ int raster_real; /* real number of raster in the * scan. This is necessary since I * don't know how to reliably compute * the number of lines */ int raster_ahead; /* max size of the incomplete lines */ int line; /* current line of the scan */ SANE_Parameters params; /* Options */ SANE_Option_Descriptor opt[OPT_NUM_OPTIONS]; Option_Value val[OPT_NUM_OPTIONS]; /* Gamma table. 1 array per color. */ SANE_Word gamma_GRAY[GAMMA_LENGTH]; SANE_Word gamma_R[GAMMA_LENGTH]; SANE_Word gamma_G[GAMMA_LENGTH]; SANE_Word gamma_B[GAMMA_LENGTH]; } Teco_Scanner; /*--------------------------------------------------------------------------*/ /* Debug levels. * Should be common to all backends. */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /*--------------------------------------------------------------------------*/ /* 32 bits from an array to an integer (eg ntohl). */ #define B32TOI(buf) \ ((((unsigned char *)buf)[0] << 24) | \ (((unsigned char *)buf)[1] << 16) | \ (((unsigned char *)buf)[2] << 8) | \ (((unsigned char *)buf)[3] << 0)) #define B16TOI(buf) \ ((((unsigned char *)buf)[0] << 8) | \ (((unsigned char *)buf)[1] << 0)) sane-backends-1.0.27/backend/kodak.c0000664000175000017500000023702612775312261014066 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package, and implements a SANE backend for various large Kodak scanners. Copyright (C) 2008-2010 m. allan noah -------------------------------------------------------------------------- This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. -------------------------------------------------------------------------- The source code is divided in sections which you can easily find by searching for the tag "@@". Section 1 - Init & static stuff Section 2 - sane_init, _get_devices, _open & friends Section 3 - sane_*_option functions Section 4 - sane_start, _get_param, _read & friends Section 5 - sane_close functions Section 6 - misc functions Changes: v0 through v5 2008-01-15, MAN - development versions v6 2009-06-22, MAN - improved set_window() to build desciptor from scratch - initial release v7 2010-02-10, MAN - add SANE_I18N to static strings - don't fail if scsi buffer is too small SANE FLOW DIAGRAM - sane_init() : initialize backend . - sane_get_devices() : query list of scanner devices . - sane_open() : open a particular scanner device . . - sane_set_io_mode : set blocking mode . . - sane_get_select_fd : get scanner fd . . . . - sane_get_option_descriptor() : get option information . . - sane_control_option() : change option values . . - sane_get_parameters() : returns estimated scan parameters . . - (repeat previous 3 functions) . . . . - sane_start() : start image acquisition . . - sane_get_parameters() : returns actual scan parameters . . - sane_read() : read image data (from pipe) . . (sane_read called multiple times; after sane_read returns EOF, . . loop may continue with sane_start which may return a 2nd page . . when doing duplex scans, or load the next page from the ADF) . . . . - sane_cancel() : cancel operation . - sane_close() : close opened scanner device - sane_exit() : terminate use of backend */ /* * @@ Section 1 - Init */ #include "sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBC_H # include /* NeXTStep/OpenStep */ #endif #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "kodak-cmd.h" #include "kodak.h" #define DEBUG 1 #define BUILD 7 /* values for SANE_DEBUG_KODAK env var: - errors 5 - function trace 10 - function detail 15 - get/setopt cmds 20 - scsi cmd trace 25 - scsi cmd detail 30 - useless noise 35 */ /* ------------------------------------------------------------------------- */ #define STRING_ADFFRONT SANE_I18N("ADF Front") #define STRING_ADFBACK SANE_I18N("ADF Back") #define STRING_ADFDUPLEX SANE_I18N("ADF Duplex") #define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART #define STRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE #define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY #define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR /* Also set via config file. */ static int global_buffer_size = DEFAULT_BUFFER_SIZE; /* * used by attach* and sane_get_devices * a ptr to a null term array of ptrs to SANE_Device structs * a ptr to a single-linked list of scanner structs */ static const SANE_Device **sane_devArray = NULL; static struct scanner *scanner_devList = NULL; /* * @@ Section 2 - SANE & scanner init code */ /* * Called by SANE initially. * * From the SANE spec: * This function must be called before any other SANE function can be * called. The behavior of a SANE backend is undefined if this * function is not called first. The version code of the backend is * returned in the value pointed to by version_code. If that pointer * is NULL, no version code is returned. Argument authorize is either * a pointer to a function that is invoked when the backend requires * authentication for a specific resource or NULL if the frontend does * not support authentication. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { authorize = authorize; /* get rid of compiler warning */ DBG_INIT (); DBG (10, "sane_init: start\n"); if (version_code) *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD); DBG (5, "sane_init: kodak backend %d.%d.%d, from %s\n", V_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); DBG (10, "sane_init: finish\n"); return SANE_STATUS_GOOD; } /* * Called by SANE to find out about supported devices. * * From the SANE spec: * This function can be used to query the list of devices that are * available. If the function executes successfully, it stores a * pointer to a NULL terminated array of pointers to SANE_Device * structures in *device_list. The returned list is guaranteed to * remain unchanged and valid until (a) another call to this function * is performed or (b) a call to sane_exit() is performed. This * function can be called repeatedly to detect when new devices become * available. If argument local_only is true, only local devices are * returned (devices directly attached to the machine that SANE is * running on). If it is false, the device list includes all remote * devices that are accessible to the SANE library. * * SANE does not require that this function is called before a * sane_open() call is performed. A device name may be specified * explicitly by a user which would make it unnecessary and * undesirable to call this function first. */ /* Read the config file, find scanners with help from sanei_* * store in two global lists of device structs */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { struct scanner *dev; char line[PATH_MAX]; const char *lp; FILE *fp; int num_devices=0; int i=0; local_only = local_only; /* get rid of compiler warning */ DBG (10, "sane_get_devices: start\n"); /* set this to default before reading the file */ global_buffer_size = DEFAULT_BUFFER_SIZE; fp = sanei_config_open (KODAK_CONFIG_FILE); if (fp) { DBG (15, "sane_get_devices: reading config file %s\n", KODAK_CONFIG_FILE); while (sanei_config_read (line, PATH_MAX, fp)) { lp = line; /* ignore comments */ if (*lp == '#') continue; /* skip empty lines */ if (*lp == 0) continue; if ((strncmp ("option", lp, 6) == 0) && isspace (lp[6])) { lp += 6; lp = sanei_config_skip_whitespace (lp); /* we allow setting buffersize too big */ if ((strncmp (lp, "buffer-size", 11) == 0) && isspace (lp[11])) { int buf; lp += 11; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); if (buf < 4096) { DBG (5, "sane_get_devices: config option \"buffer-size\" \ (%d) is < 4096, ignoring!\n", buf); continue; } if (buf > DEFAULT_BUFFER_SIZE) { DBG (5, "sane_get_devices: config option \"buffer-size\" \ (%d) is > %d, warning!\n", buf, DEFAULT_BUFFER_SIZE); } DBG (15, "sane_get_devices: setting \"buffer-size\" to %d\n", buf); global_buffer_size = buf; } else { DBG (5, "sane_get_devices: config option \"%s\" \ unrecognized\n", lp); } } else if ((strncmp ("scsi", lp, 4) == 0) && isspace (lp[4])) { DBG (15, "sane_get_devices: looking for '%s'\n", lp); sanei_config_attach_matching_devices (lp, attach_one); } else{ DBG (5, "sane_get_devices: config line \"%s\" unrecognized\n", lp); } } fclose (fp); } else { DBG (5, "sane_get_devices: no config file '%s', using defaults\n", KODAK_CONFIG_FILE); DBG (15, "sane_get_devices: looking for 'scsi KODAK'\n"); sanei_config_attach_matching_devices ("scsi KODAK", attach_one); } for (dev = scanner_devList; dev; dev=dev->next) { DBG (15, "sane_get_devices: found scanner %s\n",dev->device_name); num_devices++; } DBG (15, "sane_get_devices: found %d scanner(s)\n",num_devices); sane_devArray = calloc (num_devices + 1, sizeof (SANE_Device*)); if (!sane_devArray) return SANE_STATUS_NO_MEM; for (dev = scanner_devList; dev; dev=dev->next) { sane_devArray[i++] = (SANE_Device *)&dev->sane; } sane_devArray[i] = 0; if(device_list){ *device_list = sane_devArray; } DBG (10, "sane_get_devices: finish\n"); return SANE_STATUS_GOOD; } /* build the scanner struct and link to global list * unless struct is already loaded, then pretend */ static SANE_Status attach_one (const char *device_name) { struct scanner *s; int ret; DBG (10, "attach_one: start\n"); DBG (15, "attach_one: looking for '%s'\n", device_name); for (s = scanner_devList; s; s = s->next) { if (strcmp (s->sane.name, device_name) == 0) { DBG (10, "attach_one: already attached!\n"); return SANE_STATUS_GOOD; } } /* build a struct to hold it */ if ((s = calloc (sizeof (*s), 1)) == NULL) return SANE_STATUS_NO_MEM; /* scsi command/data buffer */ s->buffer_size = global_buffer_size; /* copy the device name */ s->device_name = strdup (device_name); if (!s->device_name){ free (s); return SANE_STATUS_NO_MEM; } /* connect the fd */ s->fd = -1; ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ free (s->device_name); free (s); return ret; } /* Now query the device to load its vendor/model/version */ ret = init_inquire (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s->device_name); free (s); DBG (5, "attach_one: inquiry failed\n"); return ret; } /* clean up the scanner struct based on model */ /* this is the only piece of model specific code */ ret = init_model (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s->device_name); free (s); DBG (5, "attach_one: model failed\n"); return ret; } /* sets user 'values' to good defaults */ ret = init_user (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s->device_name); free (s); DBG (5, "attach_one: user failed\n"); return ret; } /* sets SANE option 'values' to good defaults */ ret = init_options (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s->device_name); free (s); DBG (5, "attach_one: options failed\n"); return ret; } /* we close the connection, so that another backend can talk to scanner */ disconnect_fd(s); /* load info into sane_device struct */ s->sane.name = s->device_name; s->sane.vendor = s->vendor_name; s->sane.model = s->product_name; s->sane.type = "scanner"; s->next = scanner_devList; scanner_devList = s; DBG (10, "attach_one: finish\n"); return SANE_STATUS_GOOD; } /* * connect the fd in the scanner struct */ static SANE_Status connect_fd (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int buffer_size = s->buffer_size; DBG (10, "connect_fd: start\n"); if(s->fd > -1){ DBG (5, "connect_fd: already open\n"); ret = SANE_STATUS_GOOD; } else { ret = sanei_scsi_open_extended (s->device_name, &(s->fd), sense_handler, s, &s->buffer_size); if(!ret && buffer_size != s->buffer_size){ DBG (5, "connect_fd: cannot get requested buffer size (%d/%d)\n", buffer_size, s->buffer_size); } else{ DBG (15, "connect_fd: opened SCSI device\n"); } } DBG (10, "connect_fd: finish %d\n", ret); return ret; } /* * This routine will check if a certain device is a Kodak scanner * It also copies interesting data from INQUIRY into the handle structure */ static SANE_Status init_inquire (struct scanner *s) { int i; SANE_Status ret; unsigned char cmd[INQUIRY_len]; size_t cmdLen = INQUIRY_len; unsigned char in[I_data_len]; size_t inLen = I_data_len; DBG (10, "init_inquire: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, INQUIRY_code); set_I_evpd (cmd, 0); set_I_page_code (cmd, I_page_code_default); set_I_data_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret != SANE_STATUS_GOOD){ return ret; } if (get_I_periph_qual(in) != I_periph_qual_valid){ DBG (5, "The device at '%s' has invalid periph_qual.\n", s->device_name); return SANE_STATUS_INVAL; } if (get_I_periph_devtype(in) != I_periph_devtype_scanner){ DBG (5, "The device at '%s' is not a scanner.\n", s->device_name); return SANE_STATUS_INVAL; } get_I_vendor (in, s->vendor_name); get_I_product (in, s->product_name); get_I_version (in, s->version_name); get_I_build (in, s->build_name); s->vendor_name[8] = 0; s->product_name[16] = 0; s->version_name[4] = 0; s->build_name[2] = 0; /* gobble trailing spaces */ for (i = 7; s->vendor_name[i] == ' ' && i >= 0; i--) s->vendor_name[i] = 0; for (i = 15; s->product_name[i] == ' ' && i >= 0; i--) s->product_name[i] = 0; for (i = 3; s->version_name[i] == ' ' && i >= 0; i--) s->version_name[i] = 0; for (i = 2; s->build_name[i] == ' ' && i >= 0; i--) s->build_name[i] = 0; if (strcmp ("KODAK", s->vendor_name)) { DBG (5, "The device at '%s' is reported to be made by '%s'\n", s->device_name, s->vendor_name); DBG (5, "This backend only supports Kodak products.\n"); return SANE_STATUS_INVAL; } DBG (15, "init_inquire: Found '%s' '%s' '%s' '%s' at '%s'\n", s->vendor_name, s->product_name, s->version_name, s->build_name, s->device_name); /*defined in SCSI spec*/ DBG (15, "standard inquiry options\n"); /*FIXME: do we need to save these?*/ DBG (15, " PQ: %d\n",get_I_periph_qual(in)); DBG (15, " PDT: %d\n",get_I_periph_devtype(in)); DBG (15, " RMB: %d\n",get_I_rmb(in)); DBG (15, " DTQ: %d\n",get_I_devtype_qual(in)); DBG (15, " ISO: %d\n",get_I_iso_version(in)); DBG (15, " ECMA: %d\n",get_I_ecma_version(in)); DBG (15, " ANSI: %d\n",get_I_ansi_version(in)); DBG (15, " AENC: %d\n",get_I_aenc(in)); DBG (15, " TrmIOP: %d\n",get_I_trmiop(in)); DBG (15, " RDF: %d\n",get_I_resonse_format(in)); DBG (15, " Length: %d\n",get_I_length(in)); DBG (15, " RelAdr: %d\n",get_I_reladr(in)); DBG (15, " WBus32: %d\n",get_I_wbus32(in)); DBG (15, " WBus16: %d\n",get_I_wbus16(in)); DBG (15, " Sync: %d\n",get_I_sync(in)); DBG (15, " Linked: %d\n",get_I_linked(in)); DBG (15, " CmdQue: %d\n",get_I_cmdque(in)); DBG (15, " SftRe: %d\n",get_I_sftre(in)); /*kodak specific*/ DBG (15, "vendor inquiry options\n"); DBG (15, " MF Disable: %d\n",get_I_mf_disable(in)); DBG (15, " Checkdigit: %d\n",get_I_checkdigit(in)); DBG (15, " Front Prism: %d\n",get_I_front_prism(in)); DBG (15, " Comp Gray: %d\n",get_I_compressed_gray(in)); DBG (15, " Front Toggle: %d\n",get_I_front_toggle(in)); DBG (15, " Front DP1: %d\n",get_I_front_dp1(in)); DBG (15, " Front Color: %d\n",get_I_front_color(in)); DBG (15, " Front ATP: %d\n",get_I_front_atp(in)); DBG (15, " DP1 180: %d\n",get_I_dp1_180(in)); DBG (15, " MF Pause: %d\n",get_I_mf_pause(in)); DBG (15, " Rear Prism: %d\n",get_I_rear_prism(in)); DBG (15, " Uncomp Gray: %d\n",get_I_uncompressed_gray(in)); DBG (15, " Rear Toggle: %d\n",get_I_rear_toggle(in)); DBG (15, " Rear DP1: %d\n",get_I_rear_dp1(in)); DBG (15, " Rear Color: %d\n",get_I_rear_color(in)); DBG (15, " Rear ATP: %d\n",get_I_rear_atp(in)); /* we actually care about these */ DBG (15, " Min Binary Res: %d\n",get_I_min_bin_res(in)); s->s_res_min[MODE_LINEART] = get_I_min_bin_res(in); DBG (15, " Max Binary Res: %d\n",get_I_max_bin_res(in)); s->s_res_max[MODE_LINEART] = get_I_max_bin_res(in); DBG (15, " Min Color Res: %d\n",get_I_min_col_res(in)); s->s_res_min[MODE_COLOR] = get_I_min_col_res(in); DBG (15, " Max Color Res: %d\n",get_I_max_col_res(in)); s->s_res_max[MODE_COLOR] = get_I_max_col_res(in); DBG (15, " Max Width: %d\n",get_I_max_image_width(in)); s->s_width_max = get_I_max_image_width(in); DBG (15, " Max Length: %d\n",get_I_max_image_length(in)); s->s_length_max = get_I_max_image_length(in); /*FIXME: do we need to save these?*/ DBG (15, " Finecrop: %d\n",get_I_finecrop(in)); DBG (15, " iThresh: %d\n",get_I_ithresh(in)); DBG (15, " ECD: %d\n",get_I_ecd(in)); DBG (15, " VBLR: %d\n",get_I_vblr(in)); DBG (15, " Elevator: %d\n",get_I_elevator(in)); DBG (15, " RelCrop: %d\n",get_I_relcrop(in)); DBG (15, " CDeskew: %d\n",get_I_cdeskew(in)); DBG (15, " IA: %d\n",get_I_ia(in)); DBG (15, " Patch: %d\n",get_I_patch(in)); DBG (15, " Null Mode: %d\n",get_I_nullmode(in)); DBG (15, " SABRE: %d\n",get_I_sabre(in)); DBG (15, " LDDDS: %d\n",get_I_lddds(in)); DBG (15, " UDDDS: %d\n",get_I_uddds(in)); DBG (15, " Fixed Gap: %d\n",get_I_fixedgap(in)); DBG (15, " HR Printer: %d\n",get_I_hr_printer(in)); DBG (15, " Elev 100/250: %d\n",get_I_elev_100_250(in)); DBG (15, " UDDS Individual: %d\n",get_I_udds_individual(in)); DBG (15, " Auto Color: %d\n",get_I_auto_color(in)); DBG (15, " WB: %d\n",get_I_wb(in)); DBG (15, " ES: %d\n",get_I_es(in)); DBG (15, " FC: %d\n",get_I_fc(in)); DBG (15, " Max Rate: %d\n",get_I_max_rate(in)); DBG (15, " Buffer Size: %d\n",get_I_buffer_size(in)); DBG (10, "init_inquire: finish\n"); return SANE_STATUS_GOOD; } /* * get model specific info that is not in vpd, and correct * errors in vpd data. struct is already initialized to 0. */ static SANE_Status init_model (struct scanner *s) { DBG (10, "init_model: start\n"); s->s_mode[MODE_LINEART] = 1; s->s_mode[MODE_HALFTONE] = 1; s->s_mode[MODE_GRAYSCALE] = 1; s->s_mode[MODE_COLOR] = 1; /* scanner did not tell us these */ s->s_res_min[MODE_HALFTONE] = s->s_res_min[MODE_LINEART]; s->s_res_max[MODE_HALFTONE] = s->s_res_max[MODE_LINEART]; s->s_res_min[MODE_GRAYSCALE] = s->s_res_min[MODE_COLOR]; s->s_res_max[MODE_GRAYSCALE] = s->s_res_max[MODE_COLOR]; s->s_width_min = 96; s->s_length_min = 96; s->s_brightness_steps = 0; s->s_contrast_steps = 255; s->s_threshold_steps = 255; s->s_rif = 1; DBG (10, "init_model: finish\n"); return SANE_STATUS_GOOD; } /* * set good default user values. * struct is already initialized to 0. */ static SANE_Status init_user (struct scanner *s) { DBG (10, "init_user: start\n"); /* source */ s->u_source = SOURCE_ADF_FRONT; /* scan mode */ s->u_mode = MODE_LINEART; /*res, minimum for this mode*/ s->u_res = s->s_res_min[s->u_mode]; /* page width US-Letter */ s->u_page_width = 8.5 * 1200; if(s->u_page_width > s->s_width_max){ s->u_page_width = s->s_width_max; } /* page height US-Letter */ s->u_page_height = 11 * 1200; if(s->u_page_height > s->s_length_max){ s->u_page_height = s->s_length_max; } /* bottom-right x */ s->u_br_x = s->u_page_width; /* bottom-right y */ s->u_br_y = s->u_page_height; DBG (10, "init_user: finish\n"); return SANE_STATUS_GOOD; } /* * This function presets the "option" array to blank */ static SANE_Status init_options (struct scanner *s) { int i; DBG (10, "init_options: start\n"); memset (s->opt, 0, sizeof (s->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].name = "filler"; s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_INACTIVE; } /* go ahead and setup the first opt, because * frontend may call control_option on it * before calling get_option_descriptor */ s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; DBG (10, "init_options: finish\n"); return SANE_STATUS_GOOD; } /* * From the SANE spec: * This function is used to establish a connection to a particular * device. The name of the device to be opened is passed in argument * name. If the call completes successfully, a handle for the device * is returned in *h. As a special case, specifying a zero-length * string as the device requests opening the first available device * (if there is such a device). */ SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle) { struct scanner *dev = NULL; struct scanner *s = NULL; SANE_Status ret; unsigned char cmd[SEND_len]; size_t cmdLen = SEND_len; unsigned char out[SR_len_time]; /*longest used in this function*/ int try=0; time_t gmt_tt; struct tm * gmt_tm_p; struct tm * local_tm_p; DBG (10, "sane_open: start\n"); if(scanner_devList){ DBG (15, "sane_open: searching currently attached scanners\n"); } else{ DBG (15, "sane_open: no scanners currently attached, attaching\n"); ret = sane_get_devices(NULL,0); if(ret != SANE_STATUS_GOOD){ return ret; } } if(name[0] == 0){ DBG (15, "sane_open: no device requested, using default\n"); s = scanner_devList; } else{ DBG (15, "sane_open: device %s requested\n", name); for (dev = scanner_devList; dev; dev = dev->next) { if (strcmp (dev->sane.name, name) == 0) { s = dev; break; } } } if (!s) { DBG (5, "sane_open: no device found\n"); return SANE_STATUS_INVAL; } DBG (15, "sane_open: device %s found\n", s->sane.name); *handle = s; /* connect the fd so we can talk to scanner */ ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ return ret; } /*send the end batch (GX) command*/ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,SEND_code); set_SR_datatype_code(cmd,SR_datatype_random); set_SR_datatype_qual(cmd,SR_qual_end); set_SR_xfer_length(cmd,SR_len_end); /*start the following loop*/ ret = SANE_STATUS_DEVICE_BUSY; s->rs_info = 0; /*loop until scanner is ready*/ while(ret == SANE_STATUS_DEVICE_BUSY){ DBG (15, "sane_open: GX, try %d, sleep %lu\n", try, (unsigned long)s->rs_info); try++; sleep(s->rs_info); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, NULL, NULL ); if(try > 5){ break; } } if(ret){ DBG (5, "sane_open: GX error %d\n",ret); return ret; } /*send the clear buffer (CB) command*/ DBG (15, "sane_open: CB\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,SEND_code); set_SR_datatype_code(cmd,SR_datatype_random); set_SR_datatype_qual(cmd,SR_qual_clear); set_SR_xfer_length(cmd,SR_len_clear); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, NULL, NULL ); if(ret){ DBG (5, "sane_open: CB error %d\n",ret); return ret; } /*send the GT command*/ DBG (15, "sane_open: GT\n"); gmt_tt = time(NULL); gmt_tm_p = gmtime(&gmt_tt); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,SEND_code); set_SR_datatype_code(cmd,SR_datatype_random); set_SR_datatype_qual(cmd,SR_qual_gmt); set_SR_xfer_length(cmd,SR_len_time); memset(out,0,SR_len_time); set_SR_payload_len(out,SR_len_time); set_SR_time_hour(out,gmt_tm_p->tm_hour); set_SR_time_min(out,gmt_tm_p->tm_min); set_SR_time_mon(out,gmt_tm_p->tm_mon); set_SR_time_day(out,gmt_tm_p->tm_mday); set_SR_time_year(out,gmt_tm_p->tm_year+1900); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, SR_len_time, NULL, NULL ); if(ret){ DBG (5, "sane_open: GT error %d\n",ret); return ret; } /*FIXME: read the LC command? */ /*send the LC command*/ DBG (15, "sane_open: LC\n"); gmt_tt = time(NULL); local_tm_p = localtime(&gmt_tt); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,SEND_code); set_SR_datatype_code(cmd,SR_datatype_random); set_SR_datatype_qual(cmd,SR_qual_clock); set_SR_xfer_length(cmd,SR_len_time); memset(out,0,SR_len_time); set_SR_payload_len(out,SR_len_time); set_SR_time_hour(out,local_tm_p->tm_hour); set_SR_time_min(out,local_tm_p->tm_min); set_SR_time_mon(out,local_tm_p->tm_mon); set_SR_time_day(out,local_tm_p->tm_mday); set_SR_time_year(out,local_tm_p->tm_year+1900); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, SR_len_time, NULL, NULL ); if(ret){ DBG (5, "sane_open: LC error %d\n",ret); return ret; } DBG (10, "sane_open: finish\n"); return SANE_STATUS_GOOD; } /* * @@ Section 3 - SANE Options functions */ /* * Returns the options we know. * * From the SANE spec: * This function is used to access option descriptors. The function * returns the option descriptor for option number n of the device * represented by handle h. Option number 0 is guaranteed to be a * valid option. Its value is an integer that specifies the number of * options that are available for device handle h (the count includes * option 0). If n is not a valid option index, the function returns * NULL. The returned option descriptor is guaranteed to remain valid * (and at the returned address) until the device is closed. */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct scanner *s = handle; int i; SANE_Option_Descriptor *opt = &s->opt[option]; DBG (20, "sane_get_option_descriptor: %d\n", option); if ((unsigned) option >= NUM_OPTIONS) return NULL; /* "Mode" group -------------------------------------------------------- */ if(option==OPT_MODE_GROUP){ opt->title = "Scan Mode"; opt->desc = ""; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* source */ if(option==OPT_SOURCE){ i=0; s->o_source_list[i++]=STRING_ADFFRONT; s->o_source_list[i++]=STRING_ADFBACK; s->o_source_list[i++]=STRING_ADFDUPLEX; s->o_source_list[i]=NULL; opt->name = SANE_NAME_SCAN_SOURCE; opt->title = SANE_TITLE_SCAN_SOURCE; opt->desc = SANE_DESC_SCAN_SOURCE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->o_source_list; opt->size = maxStringSize (opt->constraint.string_list); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* scan mode */ if(option==OPT_MODE){ i=0; if(s->s_mode[MODE_LINEART]){ s->o_mode_list[i++]=STRING_LINEART; } if(s->s_mode[MODE_HALFTONE]){ s->o_mode_list[i++]=STRING_HALFTONE; } if(s->s_mode[MODE_GRAYSCALE]){ s->o_mode_list[i++]=STRING_GRAYSCALE; } if(s->s_mode[MODE_COLOR]){ s->o_mode_list[i++]=STRING_COLOR; } s->o_mode_list[i]=NULL; opt->name = SANE_NAME_SCAN_MODE; opt->title = SANE_TITLE_SCAN_MODE; opt->desc = SANE_DESC_SCAN_MODE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->o_mode_list; opt->size = maxStringSize (opt->constraint.string_list); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* resolution */ /* build a list of possible choices for current mode */ if(option==OPT_RES){ int reslist[]={100,150,200,240,300,400}; int j; i=0; for(j=0;j<6;j++){ if(reslist[j] >= s->s_res_min[s->u_mode] && reslist[j] <= s->s_res_max[s->u_mode]){ s->o_res_list[s->u_mode][++i] = reslist[j]; } } s->o_res_list[s->u_mode][0] = i; opt->name = SANE_NAME_SCAN_RESOLUTION; opt->title = SANE_TITLE_SCAN_RESOLUTION; opt->desc = SANE_DESC_SCAN_RESOLUTION; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_DPI; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opt->constraint_type = SANE_CONSTRAINT_WORD_LIST; opt->constraint.word_list = s->o_res_list[s->u_mode]; } /* "Geometry" group ---------------------------------------------------- */ if(option==OPT_GEOMETRY_GROUP){ opt->title = "Geometry"; opt->desc = ""; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* top-left x */ if(option==OPT_TL_X){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->o_tl_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->s_width_min); s->o_tl_x_range.max = SCANNER_UNIT_TO_FIXED_MM(s->s_width_max); s->o_tl_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_TL_X; opt->title = SANE_TITLE_SCAN_TL_X; opt->desc = SANE_DESC_SCAN_TL_X; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->o_tl_x_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* top-left y */ if(option==OPT_TL_Y){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->o_tl_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->s_length_min); s->o_tl_y_range.max = SCANNER_UNIT_TO_FIXED_MM(s->s_length_max); s->o_tl_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_TL_Y; opt->title = SANE_TITLE_SCAN_TL_Y; opt->desc = SANE_DESC_SCAN_TL_Y; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->o_tl_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* bottom-right x */ if(option==OPT_BR_X){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->o_br_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->s_width_min); s->o_br_x_range.max = SCANNER_UNIT_TO_FIXED_MM(s->s_width_max); s->o_br_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_BR_X; opt->title = SANE_TITLE_SCAN_BR_X; opt->desc = SANE_DESC_SCAN_BR_X; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->o_br_x_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* bottom-right y */ if(option==OPT_BR_Y){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->o_br_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->s_length_min); s->o_br_y_range.max = SCANNER_UNIT_TO_FIXED_MM(s->s_length_max); s->o_br_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_BR_Y; opt->title = SANE_TITLE_SCAN_BR_Y; opt->desc = SANE_DESC_SCAN_BR_Y; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->o_br_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* page width */ if(option==OPT_PAGE_WIDTH){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->o_page_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->s_width_min); s->o_page_x_range.max = SCANNER_UNIT_TO_FIXED_MM(s->s_width_max); s->o_page_x_range.quant = MM_PER_UNIT_FIX; opt->name = "pagewidth"; opt->title = "ADF paper width"; opt->desc = "Must be set properly to align scanning window"; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->o_page_x_range; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* page height */ if(option==OPT_PAGE_HEIGHT){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->o_page_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->s_length_min); s->o_page_y_range.max = SCANNER_UNIT_TO_FIXED_MM(s->s_length_max); s->o_page_y_range.quant = MM_PER_UNIT_FIX; opt->name = "pageheight"; opt->title = "ADF paper length"; opt->desc = "Must be set properly to eject pages"; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->o_page_y_range; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* "Enhancement" group ------------------------------------------------- */ if(option==OPT_ENHANCEMENT_GROUP){ opt->title = "Enhancement"; opt->desc = ""; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* brightness */ if(option==OPT_BRIGHTNESS){ opt->name = SANE_NAME_BRIGHTNESS; opt->title = SANE_TITLE_BRIGHTNESS; opt->desc = SANE_DESC_BRIGHTNESS; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->o_brightness_range; s->o_brightness_range.quant=1; s->o_brightness_range.min=-(s->s_brightness_steps/2); s->o_brightness_range.max=s->s_brightness_steps/2; if(opt->constraint.range->max > opt->constraint.range->min){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else{ opt->cap = SANE_CAP_INACTIVE; } } /* contrast */ if(option==OPT_CONTRAST){ opt->name = SANE_NAME_CONTRAST; opt->title = SANE_TITLE_CONTRAST; opt->desc = SANE_DESC_CONTRAST; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->o_contrast_range; s->o_contrast_range.quant=1; s->o_contrast_range.min=-(s->s_contrast_steps/2); s->o_contrast_range.max=s->s_contrast_steps/2; if(opt->constraint.range->max > opt->constraint.range->min){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else{ opt->cap = SANE_CAP_INACTIVE; } } /*threshold*/ if(option==OPT_THRESHOLD){ opt->name = SANE_NAME_THRESHOLD; opt->title = SANE_TITLE_THRESHOLD; opt->desc = SANE_DESC_THRESHOLD; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->o_threshold_range; s->o_threshold_range.min=0; s->o_threshold_range.max=s->s_threshold_steps; s->o_threshold_range.quant=1; if(opt->constraint.range->max > opt->constraint.range->min){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else{ opt->cap = SANE_CAP_INACTIVE; } } /*rif*/ if(option==OPT_RIF){ opt->name = "rif"; opt->title = "RIF"; opt->desc = "Reverse image format"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->s_rif) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; else opt->cap = SANE_CAP_INACTIVE; } return opt; } /** * Gets or sets an option value. * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which * the option is controlled is specified by parameter action. The * possible values of this parameter are described in more detail * below. The value of the option is passed through argument val. It * is a pointer to the memory that holds the option value. The memory * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon * encountering the first NUL terminator in the string. If argument i * is not NULL, the value of *i will be set to provide details on how * well the request has been met. */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { struct scanner *s = (struct scanner *) handle; SANE_Int dummy = 0; /* Make sure that all those statements involving *info cannot break (better * than having to do "if (info) ..." everywhere!) */ if (info == 0) info = &dummy; if (option >= NUM_OPTIONS) { DBG (5, "sane_control_option: %d too big\n", option); return SANE_STATUS_INVAL; } if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) { DBG (5, "sane_control_option: %d inactive\n", option); return SANE_STATUS_INVAL; } /* * SANE_ACTION_GET_VALUE: We have to find out the current setting and * return it in a human-readable form (often, text). */ if (action == SANE_ACTION_GET_VALUE) { SANE_Word * val_p = (SANE_Word *) val; DBG (20, "sane_control_option: get value for '%s' (%d)\n", s->opt[option].name,option); switch (option) { case OPT_NUM_OPTS: *val_p = NUM_OPTIONS; return SANE_STATUS_GOOD; case OPT_SOURCE: if(s->u_source == SOURCE_ADF_FRONT){ strcpy (val, STRING_ADFFRONT); } else if(s->u_source == SOURCE_ADF_BACK){ strcpy (val, STRING_ADFBACK); } else if(s->u_source == SOURCE_ADF_DUPLEX){ strcpy (val, STRING_ADFDUPLEX); } else{ DBG(5,"missing option val for source\n"); } return SANE_STATUS_GOOD; case OPT_MODE: if(s->u_mode == MODE_LINEART){ strcpy (val, STRING_LINEART); } else if(s->u_mode == MODE_HALFTONE){ strcpy (val, STRING_HALFTONE); } else if(s->u_mode == MODE_GRAYSCALE){ strcpy (val, STRING_GRAYSCALE); } else if(s->u_mode == MODE_COLOR){ strcpy (val, STRING_COLOR); } return SANE_STATUS_GOOD; case OPT_RES: *val_p = s->u_res; return SANE_STATUS_GOOD; case OPT_TL_X: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u_tl_x); return SANE_STATUS_GOOD; case OPT_TL_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u_tl_y); return SANE_STATUS_GOOD; case OPT_BR_X: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u_br_x); return SANE_STATUS_GOOD; case OPT_BR_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u_br_y); return SANE_STATUS_GOOD; case OPT_PAGE_WIDTH: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u_page_width); return SANE_STATUS_GOOD; case OPT_PAGE_HEIGHT: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u_page_height); return SANE_STATUS_GOOD; case OPT_BRIGHTNESS: *val_p = s->u_brightness; return SANE_STATUS_GOOD; case OPT_CONTRAST: *val_p = s->u_contrast; return SANE_STATUS_GOOD; case OPT_THRESHOLD: *val_p = s->u_threshold; return SANE_STATUS_GOOD; case OPT_RIF: *val_p = s->u_rif; return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { int tmp; SANE_Word val_c; SANE_Status status; DBG (20, "sane_control_option: set value for '%s' (%d)\n", s->opt[option].name,option); if ( s->started ) { DBG (5, "sane_control_option: cant set, device busy\n"); return SANE_STATUS_DEVICE_BUSY; } if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) { DBG (5, "sane_control_option: not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (5, "sane_control_option: bad value\n"); return status; } /* may have been changed by constrain, so dont copy until now */ val_c = *(SANE_Word *)val; /* * Note - for those options which can assume one of a list of * valid values, we can safely assume that they will have * exactly one of those values because that's what * sanei_constrain_value does. Hence no "else: invalid" branches * below. */ switch (option) { /* Mode Group */ case OPT_SOURCE: if (!strcmp (val, STRING_ADFFRONT)) { tmp = SOURCE_ADF_FRONT; } else if (!strcmp (val, STRING_ADFBACK)) { tmp = SOURCE_ADF_BACK; } else{ tmp = SOURCE_ADF_DUPLEX; } if (s->u_source != tmp) { s->u_source = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_MODE: if (!strcmp (val, STRING_LINEART)) { tmp = MODE_LINEART; } else if (!strcmp (val, STRING_HALFTONE)) { tmp = MODE_HALFTONE; } else if (!strcmp (val, STRING_GRAYSCALE)) { tmp = MODE_GRAYSCALE; } else{ tmp = MODE_COLOR; } if (tmp != s->u_mode){ s->u_mode = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_RES: if (s->u_res != val_c) { s->u_res = val_c; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; /* Geometry Group */ case OPT_TL_X: if (s->u_tl_x != FIXED_MM_TO_SCANNER_UNIT(val_c)){ s->u_tl_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_TL_Y: if (s->u_tl_y != FIXED_MM_TO_SCANNER_UNIT(val_c)){ s->u_tl_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_BR_X: if (s->u_br_x != FIXED_MM_TO_SCANNER_UNIT(val_c)){ s->u_br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_BR_Y: if (s->u_br_y != FIXED_MM_TO_SCANNER_UNIT(val_c)){ s->u_br_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_PAGE_WIDTH: if (s->u_page_width != FIXED_MM_TO_SCANNER_UNIT(val_c)){ s->u_page_width = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_PAGE_HEIGHT: if (s->u_page_height != FIXED_MM_TO_SCANNER_UNIT(val_c)){ s->u_page_height = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; /* Enhancement Group */ case OPT_BRIGHTNESS: if (s->u_brightness != val_c){ s->u_brightness = val_c; } return SANE_STATUS_GOOD; case OPT_CONTRAST: if (s->u_contrast != val_c){ s->u_contrast = val_c; } return SANE_STATUS_GOOD; case OPT_THRESHOLD: if (s->u_threshold != val_c){ s->u_threshold = val_c; } return SANE_STATUS_GOOD; case OPT_RIF: if (s->u_rif != val_c){ s->u_rif = val_c; } return SANE_STATUS_GOOD; } /* switch */ } /* else */ return SANE_STATUS_INVAL; } /* * @@ Section 4 - SANE scanning functions */ /* * Called by SANE to retrieve information about the type of data * that the current scan will return. * * From the SANE spec: * This function is used to obtain the current scan parameters. The * returned parameters are guaranteed to be accurate between the time * a scan has been started (sane_start() has been called) and the * completion of that request. Outside of that window, the returned * values are best-effort estimates of what the parameters will be * when sane_start() gets invoked. * * Calling this function before a scan has actually started allows, * for example, to get an estimate of how big the scanned image will * be. The parameters passed to this function are the handle h of the * device for which the parameters should be obtained and a pointer p * to a parameter structure. */ /* SANE_Parameters is defined as a struct containing: SANE_Frame format; SANE_Bool last_frame; SANE_Int lines; SANE_Int depth; ( binary=1, gray=8, color=8 (!24) ) SANE_Int pixels_per_line; SANE_Int bytes_per_line; */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { SANE_Status ret = SANE_STATUS_GOOD; struct scanner *s = (struct scanner *) handle; DBG (10, "sane_get_parameters: start\n"); /* started? get param data from image header */ if(s->started){ DBG (15, "sane_get_parameters: image settings:\n"); DBG (15, " tlx=%d, brx=%d, iw=%d, maxx=%d\n", s->i_tlx, (s->i_tlx+s->i_width), s->i_width, s->s_width_max/1200); DBG (15, " tly=%d, bry=%d, il=%d, maxy=%d\n", s->i_tly, (s->i_tly+s->i_length), s->i_length, s->s_length_max/1200); DBG (15, " res=%d, id=%d, bytes=%d\n", s->i_dpi, s->i_id, s->i_bytes); params->last_frame = 1; params->lines = s->i_length; params->pixels_per_line = s->i_width; /* bitonal */ if (s->i_bpp == 1) { params->format = SANE_FRAME_GRAY; params->depth = 1; params->bytes_per_line = params->pixels_per_line / 8; #ifdef SANE_FRAME_G42D /*G4 fax compression*/ if (s->i_compr) { params->format = SANE_FRAME_G42D; } #endif } /* gray */ else if (s->i_bpp == 8) { params->format = SANE_FRAME_GRAY; params->depth = 8; params->bytes_per_line = params->pixels_per_line; #ifdef SANE_FRAME_JPEG /*jpeg compression*/ if (s->i_compr) { params->format = SANE_FRAME_JPEG; } #endif } /* color */ else if (s->i_bpp == 24 || s->i_bpp == 96) { params->format = SANE_FRAME_RGB; params->depth = 8; params->bytes_per_line = params->pixels_per_line * 3; #ifdef SANE_FRAME_JPEG /*jpeg compression*/ if (s->i_compr) { params->format = SANE_FRAME_JPEG; } #endif } else{ DBG(5,"sane_get_parameters: unsupported depth %d\n", s->i_bpp); return SANE_STATUS_INVAL; } } /* not started? get param data from user input */ else{ DBG (15, "sane_get_parameters: user settings:\n"); DBG (15, " tlx=%d, brx=%d, pw=%d, maxx=%d\n", s->u_tl_x, s->u_br_x, s->u_page_width, s->s_width_max); DBG (15, " tly=%d, bry=%d, ph=%d, maxy=%d\n", s->u_tl_y, s->u_br_y, s->u_page_height, s->s_length_max); DBG (15, " res=%d, user_x=%d, user_y=%d\n", s->u_res, (s->u_res * (s->u_br_x - s->u_tl_x) / 1200), (s->u_res * (s->u_br_y - s->u_tl_y) / 1200)); if (s->u_mode == MODE_COLOR) { params->format = SANE_FRAME_RGB; params->depth = 8; } else if (s->u_mode == MODE_GRAYSCALE) { params->format = SANE_FRAME_GRAY; params->depth = 8; } else { params->format = SANE_FRAME_GRAY; params->depth = 1; } params->last_frame = 1; params->lines = s->u_res * (s->u_br_y - s->u_tl_y) / 1200; params->pixels_per_line = s->u_res * (s->u_br_x - s->u_tl_x) / 1200; /* bytes per line differs by mode */ if (s->u_mode == MODE_COLOR) { params->bytes_per_line = params->pixels_per_line * 3; } else if (s->u_mode == MODE_GRAYSCALE) { params->bytes_per_line = params->pixels_per_line; } else { params->bytes_per_line = params->pixels_per_line / 8; } } DBG (15, "sane_get_parameters: returning:\n"); DBG (15, " scan_x=%d, Bpl=%d, depth=%d\n", params->pixels_per_line, params->bytes_per_line, params->depth ); DBG (15, " scan_y=%d, frame=%d, last=%d\n", params->lines, params->format, params->last_frame ); DBG (10, "sane_get_parameters: finish\n"); return ret; } /* * Called by SANE when a page acquisition operation is to be started. * commands: scanner control (lampon), send (lut), send (dither), * set window, object pos, and scan * * this will be called before each image, including duplex backsides, * and at the start of adf batch. * hence, we spend alot of time playing with s->started, etc. */ SANE_Status sane_start (SANE_Handle handle) { struct scanner *s = handle; SANE_Status ret; DBG (10, "sane_start: start\n"); DBG (15, "started=%d, source=%d\n", s->started, s->u_source); /* batch already running */ if(s->started){ /* not finished with current image, error */ if (s->bytes_tx != s->i_bytes) { DBG(5,"sane_start: previous transfer not finished?"); return do_cancel(s); } } /* first page of batch */ else{ unsigned char cmd[SCAN_len]; unsigned char pay[SR_len_startstop]; /* set window command */ ret = set_window(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot set window\n"); do_cancel(s); return ret; } /* read/send JQ command */ /* read/send SC command */ ret = send_sc(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot send SC\n"); do_cancel(s); return ret; } /* read/send CT command */ DBG (15, "sane_start: send SCAN\n"); memset(cmd, 0, SCAN_len); set_SCSI_opcode(cmd, SCAN_code); ret = do_cmd ( s, 1, 0, cmd, SCAN_len, NULL, 0, NULL, NULL ); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR sending SCAN\n"); do_cancel(s); return ret; } /* send SS command */ DBG (15, "sane_start: send SS\n"); memset(cmd,0,SEND_len); set_SCSI_opcode(cmd,SEND_code); set_SR_datatype_code(cmd,SR_datatype_random); set_SR_datatype_qual(cmd,SR_qual_startstop); set_SR_xfer_length(cmd,SR_len_startstop); memset(pay,0,SR_len_startstop); set_SR_payload_len(pay,SR_len_startstop); set_SR_startstop_cmd(pay,1); ret = do_cmd ( s, 1, 0, cmd, SEND_len, pay, SR_len_startstop, NULL, NULL ); if(ret){ DBG (5, "sane_open: SS error %d\n",ret); return ret; } DBG (15, "sane_start: sleeping\n"); sleep(2); s->started=1; } ret = read_imageheader(s); if(ret){ DBG (5, "sane_open: error reading imageheader %d\n",ret); return ret; } /* set clean defaults */ s->bytes_rx = 0; s->bytes_tx = 0; /* make large buffer to hold the images */ DBG (15, "sane_start: setup buffer\n"); /* free current buffer if too small */ if (s->buffer && s->bytes_buf < s->i_bytes) { DBG (15, "sane_start: free buffer.\n"); free(s->buffer); s->buffer = NULL; s->bytes_buf = 0; } /* grab new buffer if dont have one */ if (!s->buffer) { DBG (15, "sane_start: calloc buffer.\n"); s->buffer = calloc (1,s->i_bytes); if (!s->buffer) { DBG (5, "sane_start: Error, no buffer\n"); do_cancel(s); return SANE_STATUS_NO_MEM; } } DBG (15, "started=%d, source=%d\n", s->started, s->u_source); DBG (10, "sane_start: finish\n"); return SANE_STATUS_GOOD; } /* * This routine issues a SCSI SET WINDOW command to the scanner, using the * values currently in the scanner data structure. * the scanner has 4 separate windows, and all must be set similarly, * even if you dont intend to aquire images from all of them. */ static SANE_Status set_window (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[SET_WINDOW_len]; size_t cmdLen = SET_WINDOW_len; /* the data phase has a header, followed by a window desc block * the header specifies the number of bytes in 1 window desc block */ unsigned char pay[WINDOW_HEADER_len + WINDOW_DESCRIPTOR_len]; size_t payLen = WINDOW_HEADER_len + WINDOW_DESCRIPTOR_len; unsigned char * desc = pay + WINDOW_HEADER_len; int width = (s->u_br_x - s->u_tl_x) * s->u_res/1200; int length = (s->u_br_y - s->u_tl_y) * s->u_res/1200; DBG (10, "set_window: start\n"); /* binary window settings */ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,SET_WINDOW_code); set_SW_xferlen(cmd,payLen); memset(pay,0,payLen); set_WH_desc_len(pay,WINDOW_DESCRIPTOR_len); set_WD_wid(desc,WD_wid_front_binary); /* common settings */ set_WD_Xres (desc, s->u_res); set_WD_Yres (desc, s->u_res); set_WD_ULX (desc, s->u_tl_x); set_WD_ULY (desc, s->u_tl_y); /* width % 32 == 0 && length % 1 == 0 */ width -= width % 32; width = width*1200/s->u_res; length = length*1200/s->u_res; set_WD_width (desc, width); set_WD_length (desc, length); /* brightness not supported? */ set_WD_brightness (desc, 0); set_WD_threshold (desc, s->u_threshold); set_WD_contrast (desc, 0); if(s->s_contrast_steps){ /*convert our common -127 to +127 range into HW's range *FIXME: this code assumes hardware range of 1-255 */ set_WD_contrast (desc, s->u_contrast+128); } if(s->u_mode == MODE_HALFTONE){ set_WD_composition (desc, WD_compo_HALFTONE); set_WD_bitsperpixel (desc, 1); } else{ set_WD_composition (desc, WD_compo_LINEART); set_WD_bitsperpixel (desc, 1); } /* FIXME ht pattern */ set_WD_rif (desc, s->u_rif); set_WD_bitorder (desc, 1); /* compression options */ if(s->u_compr) set_WD_compress_type (desc, WD_compr_FAXG4); /*FIXME: noise filter */ set_WD_allow_zero(desc,1); set_WD_cropping (desc, WD_crop_RELATIVE); /*FIXME: more settings here*/ hexdump(15, "front binary window:", desc, WINDOW_DESCRIPTOR_len); DBG (15, "set_window: set window binary back\n"); ret = do_cmd ( s, 1, 0, cmd, cmdLen, pay, payLen, NULL, NULL ); if(ret){ DBG (5, "set_window: error setting binary front window %d\n",ret); return ret; } /*send the window for backside too*/ set_WD_wid(desc,WD_wid_back_binary); DBG (15, "set_window: set window binary back\n"); ret = do_cmd ( s, 1, 0, cmd, cmdLen, pay, payLen, NULL, NULL ); if(ret){ DBG (5, "set_window: error setting binary back window %d\n",ret); return ret; } #if 0 memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,GET_WINDOW_code); set_GW_single(cmd,1); set_GW_wid(cmd,WD_wid_front_color); set_GW_xferlen(cmd,payLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, pay, &payLen ); if(ret){ DBG (5, "set_window: error getting window %d\n",ret); return ret; } hexdump(15,"foo",pay,payLen); #endif /* color window settings */ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,SET_WINDOW_code); set_SW_xferlen(cmd,payLen); memset(pay,0,payLen); set_WH_desc_len(pay,WINDOW_DESCRIPTOR_len); set_WD_wid(desc,WD_wid_front_color); /* common settings */ set_WD_Xres (desc, s->u_res); set_WD_Yres (desc, s->u_res); set_WD_ULX (desc, s->u_tl_x); set_WD_ULY (desc, s->u_tl_y); set_WD_width (desc, width); set_WD_length (desc, length); /*gray mode*/ if(s->u_mode == MODE_GRAYSCALE){ /* gamma width % 8 == 0 && length % 8 == 0 */ set_WD_composition (desc, WD_compo_MULTILEVEL); set_WD_bitsperpixel (desc, 8); } /*color mode or color window in binary mode*/ else{ /* width % 16 == 0 && length % 8 == 0 */ set_WD_composition (desc, WD_compo_MULTILEVEL); set_WD_bitsperpixel (desc, 24); /* compression options */ if(s->u_compr) set_WD_compress_type (desc, WD_compr_JPEG); } set_WD_bitorder (desc, 1); /*FIXME: noise filter */ set_WD_allow_zero(desc,1); set_WD_cropping (desc, WD_crop_RELATIVE); /*FIXME: more settings here*/ DBG (15, "set_window: set window color front\n"); ret = do_cmd ( s, 1, 0, cmd, cmdLen, pay, payLen, NULL, NULL ); if(ret){ DBG (5, "set_window: error setting color front window %d\n",ret); return ret; } /*send the window for backside too*/ set_WD_wid(desc,WD_wid_back_color); DBG (15, "set_window: set window color back\n"); ret = do_cmd ( s, 1, 0, cmd, cmdLen, pay, payLen, NULL, NULL ); if(ret){ DBG (5, "set_window: error setting color back window %d\n",ret); return ret; } DBG (10, "set_window: finish\n"); return ret; } /* * This routine reads the SC (scanner config) data from the scanner * modifies a few params based on user data, and sends it back */ static SANE_Status send_sc(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char pay[SR_len_config]; size_t payLen = SR_len_config; /* send SC command */ DBG (10, "send_sc: start\n"); DBG (15, "send_sc: reading config\n"); memset(cmd,0,READ_len); set_SCSI_opcode(cmd,READ_code); set_SR_datatype_code(cmd,SR_datatype_random); set_SR_datatype_qual(cmd,SR_qual_config); set_SR_xfer_length(cmd,SR_len_config); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, pay, &payLen ); if(ret || !payLen){ DBG (5, "send_sc: error reading: %d\n",ret); return ret; } memset(cmd,0,SEND_len); set_SCSI_opcode(cmd,SEND_code); set_SR_datatype_code(cmd,SR_datatype_random); set_SR_datatype_qual(cmd,SR_qual_config); set_SR_xfer_length(cmd,payLen); if(s->u_source == SOURCE_ADF_FRONT){ if(s->u_mode == MODE_COLOR || s->u_mode == MODE_GRAYSCALE){ set_SR_sc_io1(pay,SR_sc_io_front_color); } else{ set_SR_sc_io1(pay,SR_sc_io_front_binary); } set_SR_sc_io2(pay,SR_sc_io_none); set_SR_sc_io3(pay,SR_sc_io_none); set_SR_sc_io4(pay,SR_sc_io_none); } else if(s->u_source == SOURCE_ADF_BACK){ if(s->u_mode == MODE_COLOR || s->u_mode == MODE_GRAYSCALE){ set_SR_sc_io1(pay,SR_sc_io_rear_color); } else{ set_SR_sc_io1(pay,SR_sc_io_rear_binary); } set_SR_sc_io2(pay,SR_sc_io_none); set_SR_sc_io3(pay,SR_sc_io_none); set_SR_sc_io4(pay,SR_sc_io_none); } else{ if(s->u_mode == MODE_COLOR || s->u_mode == MODE_GRAYSCALE){ set_SR_sc_io1(pay,SR_sc_io_front_color); set_SR_sc_io2(pay,SR_sc_io_rear_color); } else{ set_SR_sc_io1(pay,SR_sc_io_front_binary); set_SR_sc_io2(pay,SR_sc_io_rear_binary); } set_SR_sc_io3(pay,SR_sc_io_none); set_SR_sc_io4(pay,SR_sc_io_none); } /*FIXME: there are hundreds of other settings in this payload*/ ret = do_cmd ( s, 1, 0, cmd, cmdLen, pay, payLen, NULL, NULL ); DBG (10, "send_sc: finish %d\n",ret); return ret; } /* * This routine reads the image header from the scanner, and updates * values currently in the scanner data structure. */ static SANE_Status read_imageheader (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[READ_len]; unsigned char pay[SR_len_imageheader]; size_t payLen = SR_len_imageheader; int pass = 0; /* read img header */ DBG (10, "read_imageheader: start\n"); memset(cmd,0,READ_len); set_SCSI_opcode(cmd,READ_code); set_SR_datatype_code(cmd,SR_datatype_imageheader); set_SR_xfer_length(cmd,SR_len_imageheader); while (pass++ < 1000){ DBG (15, "read_imageheader: pass %d\n", pass); payLen = SR_len_imageheader; ret = do_cmd ( s, 1, 0, cmd, READ_len, NULL, 0, pay, &payLen ); DBG (15, "read_imageheader: pass status %d\n", ret); if(ret != SANE_STATUS_DEVICE_BUSY){ break; } usleep(50000); } if (ret == SANE_STATUS_GOOD){ DBG (15, "image header:\n"); DBG (15, " bytes: %d\n",get_SR_ih_image_length(pay)); s->i_bytes = get_SR_ih_image_length(pay); DBG (15, " id: %d\n",get_SR_ih_image_id(pay)); s->i_id = get_SR_ih_image_id(pay); DBG (15, " dpi: %d\n",get_SR_ih_resolution(pay)); s->i_dpi = get_SR_ih_resolution(pay); DBG (15, " tlx: %d\n",get_SR_ih_ulx(pay)); s->i_tlx = get_SR_ih_ulx(pay); DBG (15, " tly: %d\n",get_SR_ih_uly(pay)); s->i_tly = get_SR_ih_uly(pay); DBG (15, " width: %d\n",get_SR_ih_width(pay)); s->i_width = get_SR_ih_width(pay); DBG (15, " length: %d\n",get_SR_ih_length(pay)); s->i_length = get_SR_ih_length(pay); DBG (15, " bpp: %d\n",get_SR_ih_bpp(pay)); s->i_bpp = get_SR_ih_bpp(pay); DBG (15, " comp: %d\n",get_SR_ih_comp_type(pay)); s->i_compr = get_SR_ih_comp_type(pay); /*FIXME: there are alot more of these?*/ } DBG (10, "read_imageheader: finish %d\n", ret); return ret; } /* * Called by SANE to read data. * * From the SANE spec: * This function is used to read image data from the device * represented by handle h. Argument buf is a pointer to a memory * area that is at least maxlen bytes long. The number of bytes * returned is stored in *len. A backend must set this to zero when * the call fails (i.e., when a status other than SANE_STATUS_GOOD is * returned). * * When the call succeeds, the number of bytes returned can be * anywhere in the range from 0 to maxlen bytes. */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct scanner *s = (struct scanner *) handle; SANE_Status ret=0; DBG (10, "sane_read: start\n"); *len=0; /* maybe cancelled? */ if(!s->started){ DBG (5, "sane_read: not started, call sane_start\n"); return SANE_STATUS_CANCELLED; } /* sane_start required between images */ if(s->bytes_tx == s->i_bytes){ DBG (15, "sane_read: returning eof\n"); return SANE_STATUS_EOF; } if(s->i_bytes > s->bytes_rx ){ ret = read_from_scanner(s); if(ret){ DBG(5,"sane_read: returning %d\n",ret); return ret; } } /* copy a block from buffer to frontend */ ret = read_from_buffer(s,buf,max_len,len); DBG (10, "sane_read: finish\n"); return ret; } static SANE_Status read_from_scanner(struct scanner *s) { SANE_Status ret=SANE_STATUS_GOOD; int bytes = s->buffer_size; int remain = s->i_bytes - s->bytes_rx; unsigned char * buf; size_t inLen = 0; unsigned char cmd[READ_len]; int cmdLen=READ_len; DBG (10, "read_from_scanner: start\n"); memset(cmd, 0, cmdLen); set_SCSI_opcode(cmd, READ_code); /* figure out the max amount to transfer */ if(bytes > remain){ bytes = remain; } DBG(15, "read_from_scanner: to:%d rx:%d re:%d bu:%d pa:%d\n", s->i_bytes, s->bytes_rx, remain, s->buffer_size, bytes); if(ret){ return ret; } inLen = bytes; buf = malloc(bytes); if(!buf){ DBG(5, "read_from_scanner: not enough mem for buffer: %d\n",bytes); return SANE_STATUS_NO_MEM; } set_SR_datatype_code (cmd, SR_datatype_imagedata); set_SR_xfer_length (cmd, bytes); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, buf, &inLen ); if (ret == SANE_STATUS_GOOD) { DBG(15, "read_from_scanner: got GOOD, returning GOOD\n"); } else if (ret == SANE_STATUS_EOF) { DBG(15, "read_from_scanner: got EOF, finishing\n"); } else if (ret == SANE_STATUS_DEVICE_BUSY) { DBG(5, "read_from_scanner: got BUSY, returning GOOD\n"); inLen = 0; ret = SANE_STATUS_GOOD; } else { DBG(5, "read_from_scanner: error reading data block status = %d\n",ret); inLen = 0; } if(inLen){ copy_buffer (s, buf, inLen); } free(buf); if(ret == SANE_STATUS_EOF){ DBG (5, "read_from_scanner: unexpected EOF, shortening image\n"); s->i_bytes = s->bytes_rx; ret = SANE_STATUS_GOOD; } DBG (10, "read_from_scanner: finish\n"); return ret; } static SANE_Status copy_buffer(struct scanner *s, unsigned char * buf, int len) { SANE_Status ret=SANE_STATUS_GOOD; DBG (10, "copy_buffer: start\n"); memcpy(s->buffer+s->bytes_rx,buf,len); s->bytes_rx += len; DBG (10, "copy_buffer: finish\n"); return ret; } static SANE_Status read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status ret=SANE_STATUS_GOOD; int bytes = max_len; int remain = s->bytes_rx - s->bytes_tx; DBG (10, "read_from_buffer: start\n"); /* figure out the max amount to transfer */ if(bytes > remain){ bytes = remain; } *len = bytes; DBG(15, "read_from_buffer: to:%d tx:%d re:%d bu:%d pa:%d\n", s->i_bytes, s->bytes_tx, remain, max_len, bytes); /*FIXME this needs to timeout eventually */ if(!bytes){ DBG(5,"read_from_buffer: nothing to do\n"); return SANE_STATUS_GOOD; } memcpy(buf,s->buffer+s->bytes_tx,bytes); s->bytes_tx += *len; DBG (10, "read_from_buffer: finish\n"); return ret; } /* * @@ Section 4 - SANE cleanup functions */ /* * Cancels a scan. * * It has been said on the mailing list that sane_cancel is a bit of a * misnomer because it is routinely called to signal the end of a * batch - quoting David Mosberger-Tang: * * > In other words, the idea is to have sane_start() be called, and * > collect as many images as the frontend wants (which could in turn * > consist of multiple frames each as indicated by frame-type) and * > when the frontend is done, it should call sane_cancel(). * > Sometimes it's better to think of sane_cancel() as "sane_stop()" * > but that name would have had some misleading connotations as * > well, that's why we stuck with "cancel". * * The current consensus regarding duplex and ADF scans seems to be * the following call sequence: sane_start; sane_read (repeat until * EOF); sane_start; sane_read... and then call sane_cancel if the * batch is at an end. I.e. do not call sane_cancel during the run but * as soon as you get a SANE_STATUS_NO_DOCS. * * From the SANE spec: * This function is used to immediately or as quickly as possible * cancel the currently pending operation of the device represented by * handle h. This function can be called at any time (as long as * handle h is a valid handle) but usually affects long-running * operations only (such as image is acquisition). It is safe to call * this function asynchronously (e.g., from within a signal handler). * It is important to note that completion of this operaton does not * imply that the currently pending operation has been cancelled. It * only guarantees that cancellation has been initiated. Cancellation * completes only when the cancelled call returns (typically with a * status value of SANE_STATUS_CANCELLED). Since the SANE API does * not require any other operations to be re-entrant, this implies * that a frontend must not call any other operation until the * cancelled operation has returned. */ void sane_cancel (SANE_Handle handle) { DBG (10, "sane_cancel: start\n"); do_cancel ((struct scanner *) handle); DBG (10, "sane_cancel: finish\n"); } /* * Performs cleanup. * FIXME: do better cleanup if scanning is ongoing... */ static SANE_Status do_cancel (struct scanner *s) { DBG (10, "do_cancel: start\n"); s->started = 0; DBG (10, "do_cancel: finish\n"); return SANE_STATUS_CANCELLED; } /* * Ends use of the scanner. * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is * presently active, a call to sane_cancel() is performed first. After * this function returns, handle h must not be used anymore. */ void sane_close (SANE_Handle handle) { DBG (10, "sane_close: start\n"); do_cancel((struct scanner *) handle); disconnect_fd((struct scanner *) handle); DBG (10, "sane_close: finish\n"); } static SANE_Status disconnect_fd (struct scanner *s) { DBG (10, "disconnect_fd: start\n"); if(s->fd > -1){ DBG (15, "disconnecting scsi device\n"); sanei_scsi_close (s->fd); s->fd = -1; } DBG (10, "disconnect_fd: finish\n"); return SANE_STATUS_GOOD; } /* * Terminates the backend. * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be * open (it is recommended to close device handles explicitly through * a call to sane_close(), but backends are required to release all * resources upon a call to this function). After this function * returns, no function other than sane_init() may be called * (regardless of the status value returned by sane_exit(). Neglecting * to call this function may result in some resources not being * released properly. */ void sane_exit (void) { struct scanner *dev, *next; DBG (10, "sane_exit: start\n"); for (dev = scanner_devList; dev; dev = next) { disconnect_fd(dev); next = dev->next; free (dev->device_name); free (dev); } if (sane_devArray) free (sane_devArray); scanner_devList = NULL; sane_devArray = NULL; DBG (10, "sane_exit: finish\n"); } /* * @@ Section 5 - misc helper functions */ /* * Called by the SANE SCSI core on device errors * parses the request sense return data buffer, * decides the best SANE_Status for the problem * and produces debug msgs */ static SANE_Status sense_handler (int fd, unsigned char * sensed_data, void *arg) { struct scanner *s = arg; unsigned int ili = get_RS_ILI (sensed_data); unsigned int sk = get_RS_sense_key (sensed_data); unsigned int asc = get_RS_ASC (sensed_data); unsigned int ascq = get_RS_ASCQ (sensed_data); DBG (5, "sense_handler: start\n"); /* kill compiler warning */ fd = fd; /* save for later */ s->rs_info = get_RS_information (sensed_data); DBG (5, "SK=%#02x, ASC=%#02x, ASCQ=%#02x, ILI=%d, info=%#08lx\n", sk, asc, ascq, ili, (unsigned long)s->rs_info); switch (sk) { /* no sense */ case 0x0: if (0x00 != asc) { DBG (5, "No sense: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if (0x00 != ascq) { DBG (5, "No sense: unknown ascq\n"); return SANE_STATUS_IO_ERROR; } if (ili) { DBG (5, "No sense: ILI set\n"); return SANE_STATUS_EOF; } DBG (5, "No sense: ready\n"); return SANE_STATUS_GOOD; /* not ready */ case 0x2: if (0x80 != asc) { DBG (5, "Not ready: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if (0x00 != ascq) { DBG (5, "Not ready: unknown ascq\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "Not ready: end of job\n"); return SANE_STATUS_NO_DOCS; break; /* hardware error */ case 0x4: if (0x3b != asc) { DBG (5, "Hardware error: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if (0x05 == ascq) { DBG (5, "Hardware error: paper jam\n"); return SANE_STATUS_JAMMED; } if (0x80 == ascq) { DBG (5, "Hardware error: multi-feed\n"); return SANE_STATUS_JAMMED; } DBG (5, "Hardware error: unknown ascq\n"); return SANE_STATUS_IO_ERROR; break; /* illegal request */ case 0x5: if (asc != 0x20 && asc != 0x24 && asc != 0x25 && asc != 0x26 && asc != 0x83 && asc != 0x8f) { DBG (5, "Illegal request: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if (0x20 == asc && 0x00 == ascq) { DBG (5, "Illegal request: invalid opcode\n"); return SANE_STATUS_INVAL; } if (0x24 == asc && 0x00 == ascq) { DBG (5, "Illegal request: invalid field in CDB\n"); return SANE_STATUS_INVAL; } if (0x25 == asc && 0x00 == ascq) { DBG (5, "Illegal request: invalid LUN\n"); return SANE_STATUS_INVAL; } if (0x26 == asc && 0x00 == ascq) { DBG (5, "Illegal request: invalid field in params\n"); return SANE_STATUS_INVAL; } if (0x83 == asc && 0x00 == ascq) { DBG (5, "Illegal request: command failed, check log\n"); return SANE_STATUS_INVAL; } if (0x83 == asc && 0x01 == ascq) { DBG (5, "Illegal request: command failed, invalid state\n"); return SANE_STATUS_INVAL; } if (0x83 == asc && 0x02 == ascq) { DBG (5, "Illegal request: command failed, critical error\n"); return SANE_STATUS_INVAL; } if (0x8f == asc && 0x00 == ascq) { DBG (5, "Illegal request: no image\n"); return SANE_STATUS_DEVICE_BUSY; } DBG (5, "Illegal request: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; /* unit attention */ case 0x6: if (asc != 0x29 && asc != 0x80) { DBG (5, "Unit attention: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if (0x29 == asc && 0x60 == ascq) { DBG (5, "Unit attention: device reset\n"); return SANE_STATUS_GOOD; } if (0x80 == asc && 0x00 == ascq) { DBG (5, "Unit attention: Energy Star warm up\n"); return SANE_STATUS_DEVICE_BUSY; } if (0x80 == asc && 0x01 == ascq) { DBG (5, "Unit attention: lamp warm up for scan\n"); return SANE_STATUS_DEVICE_BUSY; } if (0x80 == asc && 0x02 == ascq) { DBG (5, "Unit attention: lamp warm up for cal\n"); return SANE_STATUS_DEVICE_BUSY; } if (0x80 == asc && 0x04 == ascq) { DBG (5, "Unit attention: calibration failed\n"); return SANE_STATUS_INVAL; } DBG (5, "Unit attention: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; /* ia overflow */ case 0x9: if (0x80 == asc && 0x00 == ascq) { DBG (5, "IA overflow: IA field overflow\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "IA overflow: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; /* volume overflow */ case 0xd: if (0x80 == asc && 0x00 == ascq) { DBG (5, "Volume overflow: Image buffer full\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "Volume overflow: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; default: DBG (5, "Unknown Sense Code\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "sense_handler: should never happen!\n"); return SANE_STATUS_IO_ERROR; } /* SANE_Status do_rs(scanner * s) { SANE_Status ret; unsigned char cmd[REQUEST_SENSE_len]; size_t cmdLen = REQUEST_SENSE_len; DBG (10, "do_rs: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,REQUEST_SENSE_code); set_SR_datatype_code(cmd,SR_datatype_random); set_SR_datatype_qual(cmd,SR_qual_end); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, NULL, NULL ); while(ret == SANE_STATUS_DEVICE_BUSY){ ret = run_rs(s); } DBG (10, "do_rs: finish\n"); return SANE_STATUS_GOOD; } */ SANE_Status do_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { SANE_Status ret = SANE_STATUS_GOOD; /*shut up compiler*/ runRS=runRS; shortTime=shortTime; DBG(10, "do_cmd: start\n"); DBG(25, "cmd: writing %d bytes\n", (int)cmdLen); hexdump(30, "cmd: >>", cmdBuff, cmdLen); if(outBuff && outLen){ DBG(25, "out: writing %d bytes\n", (int)outLen); hexdump(30, "out: >>", outBuff, outLen); } if (inBuff && inLen){ DBG(25, "in: reading %d bytes\n", (int)*inLen); } ret = sanei_scsi_cmd2(s->fd, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen); if(ret != SANE_STATUS_GOOD && ret != SANE_STATUS_EOF){ DBG(5,"do_cmd: return '%s'\n",sane_strstatus(ret)); return ret; } /* FIXME: should we look at s->rs_info here? */ if (inBuff && inLen){ hexdump(30, "in: <<", inBuff, *inLen); DBG(25, "in: read %d bytes\n", (int)*inLen); } DBG(10, "do_cmd: finish\n"); return ret; } #if 0 /* unused */ static SANE_Status wait_scanner(struct scanner *s) { int ret; unsigned char cmd[TEST_UNIT_READY_len]; size_t cmdLen = TEST_UNIT_READY_len; DBG (10, "wait_scanner: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,TEST_UNIT_READY_code); ret = do_cmd ( s, 0, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); if (ret != SANE_STATUS_GOOD) { DBG(5,"WARNING: Brain-dead scanner. Hitting with stick\n"); ret = do_cmd ( s, 0, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); } if (ret != SANE_STATUS_GOOD) { DBG(5,"WARNING: Brain-dead scanner. Hitting with stick again\n"); ret = do_cmd ( s, 0, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); } if (ret != SANE_STATUS_GOOD) { DBG (5, "wait_scanner: error '%s'\n", sane_strstatus (ret)); } DBG (10, "wait_scanner: finish\n"); return ret; } #endif /* 0 - unused */ /** * Convenience method to determine longest string size in a list. */ static size_t maxStringSize (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /** * Prints a hex dump of the given buffer onto the debug output stream. */ static void hexdump (int level, char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; if(DBG_LEVEL < level) return; DBG (level, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { *ptr = '\0'; DBG (level, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3x:", i); ptr += 4; } sprintf (ptr, " %2.2x", *p); ptr += 3; } *ptr = '\0'; DBG (level, "%s\n", line); } /** * An advanced method we don't support but have to define. */ SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) { DBG (10, "sane_set_io_mode\n"); DBG (15, "%d %p\n", non_blocking, h); return SANE_STATUS_UNSUPPORTED; } /** * An advanced method we don't support but have to define. */ SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) { DBG (10, "sane_get_select_fd\n"); DBG (15, "%p %d\n", h, *fdp); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/pixma_io_sanei.c0000664000175000017500000003555012775312261015757 00000000000000/* SANE - Scanner Access Now Easy. * For limitations, see function sanei_usb_get_vendor_product(). Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include /* INT_MAX */ #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" #include "pixma_bjnp.h" #include "../include/sane/sanei_usb.h" #ifdef __GNUC__ # define UNUSED(v) (void) v #else # define UNUSED(v) #endif /* MAC OS X does not support timeouts in darwin/libusb interrupt reads * This is a very basic turnaround for MAC OS X * Button scan will not work with this wrapper */ #ifdef __APPLE__ # define sanei_usb_read_int sanei_usb_read_bulk #endif struct pixma_io_t { pixma_io_t *next; int interface; SANE_Int dev; }; typedef struct scanner_info_t { struct scanner_info_t *next; char *devname; int interface; const pixma_config_t *cfg; char serial[PIXMA_MAX_ID_LEN + 1]; /* "xxxxyyyy_zzzzzzz..." x = vid, y = pid, z = serial */ } scanner_info_t; #define INT_USB 0 #define INT_BJNP 1 static scanner_info_t *first_scanner = NULL; static pixma_io_t *first_io = NULL; static unsigned nscanners; static scanner_info_t * get_scanner_info (unsigned devnr) { scanner_info_t *si; for (si = first_scanner; si && devnr != 0; --devnr, si = si->next) { } return si; } static const struct pixma_config_t *lookup_scanner(const char *makemodel, const struct pixma_config_t *const pixma_devices[]) { int i; const struct pixma_config_t *cfg; char *match; for (i = 0; pixma_devices[i]; i++) { /* loop through the device classes (mp150, mp730 etc) */ for (cfg = pixma_devices[i]; cfg->name; cfg++) { /* loop through devices in class */ if ((match = strcasestr (makemodel, cfg->model)) != NULL) { /* possible match found, make sure it is not a partial match */ /* MP600 and MP600R are different models! */ /* some models contain ranges, so check for a '-' too */ if ((match[strlen(cfg->model)] == ' ') || (match[strlen(cfg->model)] == '\0') || (match[strlen(cfg->model)] == '-')) { pixma_dbg (3, "Scanner model found: Name %s(%s) matches %s\n", cfg->model, cfg->name, makemodel); return cfg; } } pixma_dbg (20, "Scanner model %s(%s) not found, giving up! %s\n", cfg->model, cfg->name, makemodel); } } return NULL; } static SANE_Status attach (SANE_String_Const devname) { scanner_info_t *si; si = (scanner_info_t *) calloc (1, sizeof (*si)); if (!si) return SANE_STATUS_NO_MEM; si->devname = strdup (devname); if (!si->devname) return SANE_STATUS_NO_MEM; si -> interface = INT_USB; si->next = first_scanner; first_scanner = si; nscanners++; return SANE_STATUS_GOOD; } static SANE_Status attach_bjnp (SANE_String_Const devname, SANE_String_Const makemodel, SANE_String_Const serial, const struct pixma_config_t *const pixma_devices[]) { scanner_info_t *si; const pixma_config_t *cfg; SANE_Status error; si = (scanner_info_t *) calloc (1, sizeof (*si)); if (!si) return SANE_STATUS_NO_MEM; si->devname = strdup (devname); if (!si->devname) return SANE_STATUS_NO_MEM; if ((cfg = lookup_scanner(makemodel, pixma_devices)) == (struct pixma_config_t *)NULL) error = SANE_STATUS_INVAL; else { si->cfg = cfg; sprintf(si->serial, "%s_%s", cfg->model, serial); si -> interface = INT_BJNP; si->next = first_scanner; first_scanner = si; nscanners++; error = SANE_STATUS_GOOD; } return error; } static void clear_scanner_list (void) { scanner_info_t *si = first_scanner; while (si) { scanner_info_t *temp = si; free (si->devname); si = si->next; free (temp); } nscanners = 0; first_scanner = NULL; } static SANE_Status get_descriptor (SANE_Int dn, SANE_Int type, SANE_Int descidx, SANE_Int index, SANE_Int length, SANE_Byte * data) { return sanei_usb_control_msg (dn, 0x80, USB_REQ_GET_DESCRIPTOR, ((type & 0xff) << 8) | (descidx & 0xff), index, length, data); } static SANE_Status get_string_descriptor (SANE_Int dn, SANE_Int index, SANE_Int lang, SANE_Int length, SANE_Byte * data) { return get_descriptor (dn, USB_DT_STRING, index, lang, length, data); } static void u16tohex (uint16_t x, char *str) { static const char hdigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; str[0] = hdigit[(x >> 12) & 0xf]; str[1] = hdigit[(x >> 8) & 0xf]; str[2] = hdigit[(x >> 4) & 0xf]; str[3] = hdigit[x & 0xf]; str[4] = '\0'; } static void read_serial_number (scanner_info_t * si) { uint8_t unicode[2 * (PIXMA_MAX_ID_LEN - 9) + 2]; uint8_t ddesc[18]; int iSerialNumber; SANE_Int usb; char *serial = si->serial; u16tohex (si->cfg->vid, serial); u16tohex (si->cfg->pid, serial + 4); if (SANE_STATUS_GOOD != sanei_usb_open (si->devname, &usb)) return; if (get_descriptor (usb, USB_DT_DEVICE, 0, 0, 18, ddesc) != SANE_STATUS_GOOD) goto done; iSerialNumber = ddesc[16]; if (iSerialNumber != 0) { int i, len; SANE_Status status; /*int iSerialNumber = ddesc[16];*/ /* Read the first language code. Assumed that there is at least one. */ if (get_string_descriptor (usb, 0, 0, 4, unicode) != SANE_STATUS_GOOD) goto done; /* Read the serial number string. */ status = get_string_descriptor (usb, iSerialNumber, unicode[3] * 256 + unicode[2], sizeof (unicode), unicode); if (status != SANE_STATUS_GOOD) goto done; /* Assumed charset: Latin1 */ len = unicode[0]; if (len > (int) sizeof (unicode)) { len = sizeof (unicode); PDBG (pixma_dbg (1, "WARNING:Truncated serial number\n")); } serial[8] = '_'; for (i = 2; i < len; i += 2) { serial[9 + i / 2 - 1] = unicode[i]; } serial[9 + i / 2 - 1] = '\0'; } else { PDBG (pixma_dbg (1, "WARNING:No serial number\n")); } done: sanei_usb_close (usb); } static int map_error (SANE_Status ss) { switch (ss) { case SANE_STATUS_GOOD: return 0; case SANE_STATUS_UNSUPPORTED: return PIXMA_ENODEV; case SANE_STATUS_DEVICE_BUSY: return PIXMA_EBUSY; case SANE_STATUS_INVAL: return PIXMA_EINVAL; case SANE_STATUS_IO_ERROR: return PIXMA_EIO; case SANE_STATUS_NO_MEM: return PIXMA_ENOMEM; case SANE_STATUS_ACCESS_DENIED: return PIXMA_EACCES; case SANE_STATUS_CANCELLED: return PIXMA_ECANCELED; case SANE_STATUS_JAMMED: return PIXMA_EPAPER_JAMMED; case SANE_STATUS_COVER_OPEN: return PIXMA_ECOVER_OPEN; case SANE_STATUS_NO_DOCS: return PIXMA_ENO_PAPER; case SANE_STATUS_EOF: return PIXMA_EOF; #ifdef SANE_STATUS_HW_LOCKED case SANE_STATUS_HW_LOCKED: /* unused by pixma */ #endif #ifdef SANE_STATUS_WARMING_UP case SANE_STATUS_WARMING_UP: /* unused by pixma */ #endif break; } PDBG (pixma_dbg (1, "BUG:Unmapped SANE Status code %d\n", ss)); return PIXMA_EIO; /* should not happen */ } int pixma_io_init (void) { sanei_usb_init (); sanei_bjnp_init(); nscanners = 0; return 0; } void pixma_io_cleanup (void) { while (first_io) pixma_disconnect (first_io); clear_scanner_list (); } unsigned pixma_collect_devices (const char **conf_devices, const struct pixma_config_t *const pixma_devices[]) { unsigned i, j; struct scanner_info_t *si; const struct pixma_config_t *cfg; clear_scanner_list (); j = 0; for (i = 0; pixma_devices[i]; i++) { for (cfg = pixma_devices[i]; cfg->name; cfg++) { sanei_usb_find_devices (cfg->vid, cfg->pid, attach); si = first_scanner; while (j < nscanners) { PDBG (pixma_dbg (3, "pixma_collect_devices() found %s at %s\n", cfg->name, si->devname)); si->cfg = cfg; read_serial_number (si); si = si->next; j++; } } } sanei_bjnp_find_devices(conf_devices, attach_bjnp, pixma_devices); si = first_scanner; while (j < nscanners) { PDBG (pixma_dbg (3, "pixma_collect_devices() found %s at %s\n", si->cfg->name, si->devname)); si = si->next; j++; } return nscanners; } const pixma_config_t * pixma_get_device_config (unsigned devnr) { const scanner_info_t *si = get_scanner_info (devnr); return (si) ? si->cfg : NULL; } const char * pixma_get_device_id (unsigned devnr) { const scanner_info_t *si = get_scanner_info (devnr); return (si) ? si->serial : NULL; } int pixma_connect (unsigned devnr, pixma_io_t ** handle) { pixma_io_t *io; SANE_Int dev; const scanner_info_t *si; int error; *handle = NULL; si = get_scanner_info (devnr); if (!si) return PIXMA_EINVAL; if (si-> interface == INT_BJNP) error = map_error (sanei_bjnp_open (si->devname, &dev)); else error = map_error (sanei_usb_open (si->devname, &dev)); if (error < 0) return error; io = (pixma_io_t *) calloc (1, sizeof (*io)); if (!io) { if (si -> interface == INT_BJNP) sanei_bjnp_close (dev); else sanei_usb_close (dev); return PIXMA_ENOMEM; } io->next = first_io; first_io = io; io->dev = dev; io->interface = si->interface; *handle = io; return 0; } void pixma_disconnect (pixma_io_t * io) { pixma_io_t **p; if (!io) return; for (p = &first_io; *p && *p != io; p = &((*p)->next)) { } PASSERT (*p); if (!(*p)) return; if (io-> interface == INT_BJNP) sanei_bjnp_close (io->dev); else sanei_usb_close (io->dev); *p = io->next; free (io); } int pixma_activate (pixma_io_t * io) { int error; if (io->interface == INT_BJNP) { error = map_error(sanei_bjnp_activate (io->dev)); } else /* noop for USB interface */ error = 0; return error; } int pixma_deactivate (pixma_io_t * io) { int error; if (io->interface == INT_BJNP) { error = map_error(sanei_bjnp_deactivate (io->dev)); } else /* noop for USB interface */ error = 0; return error; } int pixma_reset_device (pixma_io_t * io) { UNUSED (io); return PIXMA_ENOTSUP; } int pixma_write (pixma_io_t * io, const void *cmd, unsigned len) { size_t count = len; int error; if (io->interface == INT_BJNP) { sanei_bjnp_set_timeout (io->dev, PIXMA_BULKOUT_TIMEOUT); error = map_error (sanei_bjnp_write_bulk (io->dev, cmd, &count)); } else { #ifdef HAVE_SANEI_USB_SET_TIMEOUT sanei_usb_set_timeout (PIXMA_BULKOUT_TIMEOUT); #endif error = map_error (sanei_usb_write_bulk (io->dev, cmd, &count)); } if (error == PIXMA_EIO) error = PIXMA_ETIMEDOUT; /* FIXME: SANE doesn't have ETIMEDOUT!! */ if (count != len) { PDBG (pixma_dbg (1, "WARNING:pixma_write(): count(%u) != len(%u)\n", (unsigned) count, len)); error = PIXMA_EIO; } if (error >= 0) error = count; PDBG (pixma_dump (10, "OUT ", cmd, error, len, 128)); return error; } int pixma_read (pixma_io_t * io, void *buf, unsigned size) { size_t count = size; int error; if (io-> interface == INT_BJNP) { sanei_bjnp_set_timeout (io->dev, PIXMA_BULKIN_TIMEOUT); error = map_error (sanei_bjnp_read_bulk (io->dev, buf, &count)); } else { #ifdef HAVE_SANEI_USB_SET_TIMEOUT sanei_usb_set_timeout (PIXMA_BULKIN_TIMEOUT); #endif error = map_error (sanei_usb_read_bulk (io->dev, buf, &count)); } if (error == PIXMA_EIO) error = PIXMA_ETIMEDOUT; /* FIXME: SANE doesn't have ETIMEDOUT!! */ if (error >= 0) error = count; PDBG (pixma_dump (10, "IN ", buf, error, -1, 128)); return error; } int pixma_wait_interrupt (pixma_io_t * io, void *buf, unsigned size, int timeout) { size_t count = size; int error; /* FIXME: What is the meaning of "timeout" in sanei_usb? */ if (timeout < 0) timeout = INT_MAX; else if (timeout < 100) timeout = 100; if (io-> interface == INT_BJNP) { sanei_bjnp_set_timeout (io->dev, timeout); error = map_error (sanei_bjnp_read_int (io->dev, buf, &count)); } else { #ifdef HAVE_SANEI_USB_SET_TIMEOUT sanei_usb_set_timeout (timeout); #endif error = map_error (sanei_usb_read_int (io->dev, buf, &count)); } if (error == PIXMA_EIO || (io->interface == INT_BJNP && error == PIXMA_EOF)) /* EOF is a bjnp timeout error! */ error = PIXMA_ETIMEDOUT; /* FIXME: SANE doesn't have ETIMEDOUT!! */ if (error == 0) error = count; if (error != PIXMA_ETIMEDOUT) PDBG (pixma_dump (10, "INTR", buf, error, -1, -1)); return error; } int pixma_set_interrupt_mode (pixma_io_t * s, int background) { UNUSED (s); return (background) ? PIXMA_ENOTSUP : 0; } sane-backends-1.0.27/backend/gt68xx_shm_channel.h0000664000175000017500000000676612112021330016471 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GT68XX_SHM_CHANNEL_H #define GT68XX_SHM_CHANNEL_H /** @file * @brief Shared memory channel support. */ #include "../include/sane/sane.h" typedef struct Shm_Channel Shm_Channel; static SANE_Status shm_channel_new (SANE_Int buf_size, SANE_Int buf_count, Shm_Channel ** shm_channel_return); static SANE_Status shm_channel_free (Shm_Channel * shm_channel); static SANE_Status shm_channel_writer_init (Shm_Channel * shm_channel); static SANE_Status shm_channel_writer_get_buffer (Shm_Channel * shm_channel, SANE_Int * buffer_id_return, SANE_Byte ** buffer_addr_return); static SANE_Status shm_channel_writer_put_buffer (Shm_Channel * shm_channel, SANE_Int buffer_id, SANE_Int buffer_bytes); static SANE_Status shm_channel_writer_close (Shm_Channel * shm_channel); static SANE_Status shm_channel_reader_init (Shm_Channel * shm_channel); #if 0 static SANE_Status shm_channel_reader_set_io_mode (Shm_Channel * shm_channel, SANE_Bool non_blocking); static SANE_Status shm_channel_reader_get_select_fd (Shm_Channel * shm_channel, SANE_Int * fd_return); #endif static SANE_Status shm_channel_reader_start (Shm_Channel * shm_channel); static SANE_Status shm_channel_reader_get_buffer (Shm_Channel * shm_channel, SANE_Int * buffer_id_return, SANE_Byte ** buffer_addr_return, SANE_Int * buffer_bytes_return); static SANE_Status shm_channel_reader_put_buffer (Shm_Channel * shm_channel, SANE_Int buffer_id); #if 0 static SANE_Status shm_channel_reader_close (Shm_Channel * shm_channel); #endif #endif /* not GT68XX_SHM_CHANNEL_H */ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/epson_usb.c0000664000175000017500000000275112775312261014765 00000000000000#include #include "../include/sane/sanei_usb.h" #include "epson_usb.h" /* generated with epson2usb.pl doc/descriptions/epson.desc */ SANE_Word sanei_epson_usb_product_ids[] = { 0x101, /* Perfection 636U */ 0x103, /* Perfection 610 */ 0x104, /* Perfection 1200U, Perfection 1200Photo */ 0x107, /* Expression 1600 */ 0x10a, /* Perfection 1640 */ 0x10b, /* Perfection 1240 */ 0x10c, /* Perfection 640 */ 0x10e, /* Expression 1680 */ 0x110, /* Perfection 1650 */ 0x112, /* Perfection 2450 */ 0x11b, /* Perfection 2400 */ 0x11c, /* Perfection 3200 */ 0x11e, /* Perfection 1660 */ 0x128, /* Perfection 4870 */ 0x12a, /* Perfection 4990 */ 0x12c, /* V700, V750 */ 0x801, /* CX-5200, CX-5400 */ 0x802, /* CX-3200 */ 0x805, /* CX-6300, CX-6400 */ 0x806, /* RX-600 */ 0x807, /* RX-500 */ 0x808, /* CX-5400 */ 0x80d, /* CX-4600 */ 0x80e, /* CX-3600, CX-3650 */ 0x80f, /* RX-425 */ 0x810, /* RX-700 */ 0x811, /* RX-620 */ 0x813, /* CX-6500, CX-6600 */ 0x815, /* AcuLaser CX11, AcuLaser CX11NF */ 0x818, /* DX-3850, CX-3700, CX-3800, DX-3800 */ 0x819, /* CX-4800 */ 0x820, /* CX-4200 */ 0x82b, /* CX-5000, DX-5000, DX-5050 */ 0x82e, /* DX-6000 */ 0x82f, /* DX-4050 */ 0x838, /* DX-7400 */ 0 /* last entry - this is used for devices that are specified in the config file as "usb " */ }; int sanei_epson_getNumberOfUSBProductIds (void) { return sizeof (sanei_epson_usb_product_ids) / sizeof (SANE_Word); } sane-backends-1.0.27/backend/stv680.c0000664000175000017500000015725012775312261014047 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2004 - 2006 Gerard Klaver The teco2 and gl646 backend (Frank Zago) are used as a template for this backend. For the usb commands and bayer decoding parts of the following program are used: The pencam2 program (GNU GPL license 2) For the usb commands parts of the following programs are used: The libgphoto2 (camlib stv0680) (GNU GPL license 2) The stv680.c/.h kernel module (GNU GPL license 2) For the stv680_add_text routine the add_text routine and font_6x11.h file are taken from the webcam.c file, part of xawtv program, (c) 1998-2002 Gerd Knorr (GNU GPL license 2). This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ------------------------------------------------------------------ */ /* $Id$ stv680 vidcam driver Gerard Klaver */ /*SANE FLOW DIAGRAM - sane_init() : initialize backend, attach vidcams . - sane_get_devices() : query list of vidcam devices . - sane_open() : open a particular vidcam device . . - sane_set_io_mode : set blocking mode . . - sane_get_select_fd : get vidcam fd . . - sane_get_option_descriptor() : get option information . . - sane_control_option() : change option values . . . . - sane_start() : start image acquisition . . - sane_get_parameters() : returns actual scan parameters . . - sane_read() : read image data (from pipe) . . (sane_read called multiple times; . . after sane_read returns EOF) . . go back to sane_start() if more frames desired . . - sane_cancel() : cancel operation . - sane_close() : close opened vidcam device - sane_exit() : terminate use of backend */ /*--------------------------------------------------------------------------*/ #define BUILD 1 /* 2004/09/09 update 20-04-2006 */ #define BACKEND_NAME stv680 #define STV680_CONFIG_FILE "stv680.conf" /* --------------------- SANE INTERNATIONALISATION ------------------------ */ /* must be first include */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" /* for add-text routine */ #include #include "../include/font_6x11.h" /*-----------------------*/ #include "stv680.h" #define TIMEOUT 1000 /*--------------------------------------------------------------------------*/ /* Lists of possible scan modes. */ static SANE_String_Const scan_mode_list[] = { COLOR_RGB_STR, COLOR_RGB_TEXT_STR, SANE_VALUE_SCAN_MODE_COLOR, COLOR_RAW_STR, NULL }; /*-----------------------------------------minium, maximum, quantization----*/ static const SANE_Range brightness_range = { -128, 128, 1 }; static const SANE_Range red_level_range = { -32, 32, 1 }; static const SANE_Range green_level_range = { -32, 32, 1 }; static const SANE_Range blue_level_range = { -32, 32, 1 }; /*--------------------------------------------------------------------------*/ static const struct dpi_color_adjust stv680_dpi_color_adjust[] = { /*dpi, y, x, color sequence R G or B */ {176, 144, 0, 1, 2}, /* QCIF selected by dev->CIF */ {352, 288, 0, 1, 2}, /* CIF ,, */ {160, 120, 0, 1, 2}, /* QSIF ,, dev->VGA */ {320, 240, 0, 1, 2}, /* QVGA (SIF) ,, */ {640, 480, 0, 1, 2}, /* VGA ,, */ /* must be the last entry */ {0, 0, 0, 0, 0} }; static const struct vidcam_hardware vidcams[] = { {0x0553, 0x0202, USB_CLASS_VENDOR_SPEC, "AIPTEK", "PENCAM STV0680", stv680_dpi_color_adjust}, {0x04c8, 0x0722, USB_CLASS_VENDOR_SPEC, "Konica", "e-mini", stv680_dpi_color_adjust}, {0x1183, 0x0001, USB_CLASS_VENDOR_SPEC, "DigitalDream", "l'espion XS", stv680_dpi_color_adjust}, {0x041e, 0x4007, USB_CLASS_VENDOR_SPEC, "Creative", "WebCam Go mini", stv680_dpi_color_adjust} }; /* List of vidcams attached. */ static Stv680_Vidcam *first_dev = NULL; static int num_devices = 0; /* used by sane_get_devices */ static const SANE_Device **devlist = NULL; /*----------------------------------------------------------- */ /* Local functions. */ /* Display a buffer in the log. Display by lines of 16 bytes. */ static void hexdump (int level, const char *comment, unsigned char *buf, const int length) { int i; char line[128]; char *ptr; char asc_buf[17]; char *asc_ptr; DBG (level, " %s\n", comment); i = 0; goto start; do { if (i < length) { ptr += sprintf (ptr, " %2.2x", *buf); if (*buf >= 32 && *buf <= 127) { asc_ptr += sprintf (asc_ptr, "%c", *buf); } else { asc_ptr += sprintf (asc_ptr, "."); } } else { /* After the length; do nothing. */ ptr += sprintf (ptr, " "); } i++; buf++; if ((i % 16) == 0) { /* It's a new line */ DBG (level, " %s %s\n", line, asc_buf); start: ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; ptr += sprintf (ptr, " %3.3d:", i); } } while (i < ((length + 15) & ~15)); } /* Returns the length of the longest string, including the terminating * character. */ static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* Initialize a vidcam entry. Return an allocated vidcam with some * */ static Stv680_Vidcam * stv680_init (void) { Stv680_Vidcam *dev; DBG (DBG_proc, "stv680_init: enter\n"); /* Allocate a new vidcam entry. */ dev = malloc (sizeof (Stv680_Vidcam)); if (dev == NULL) { return NULL; } memset (dev, 0, sizeof (Stv680_Vidcam)); /* Allocate the windoww buffer*/ dev->windoww_size = 0x20; dev->windoww = malloc (dev->windoww_size); if (dev->windoww == NULL) { free (dev); return NULL; } /* Allocate the windowr buffer*/ dev->windowr_size = 0x20; dev->windowr = malloc (dev->windowr_size); if (dev->windowr == NULL) { free (dev->windoww); free (dev); return NULL; } dev->fd = -1; DBG (DBG_proc, "stv680_init: exit\n"); return (dev); } static SANE_Status stv680_init_2 (Stv680_Vidcam * dev) { SANE_Status status; DBG (DBG_proc, "stv680_init_2: enter\n"); /* Allocate the buffer used to transfer the USB data */ /* Check for max. format image size so buffer size can * be adjusted, format from camera is bayer 422 */ if (dev->CIF) dev->buffer_size = 356 * 292; if (dev->VGA) dev->buffer_size = 644 * 484; DBG (DBG_proc, "stv680_init_2: dev->bufffer = 0x%lx\n", (unsigned long) (size_t) dev->buffer_size); dev->buffer = malloc (dev->buffer_size); if (dev->buffer == NULL) { free (dev->windowr); free (dev->windoww); free (dev); return SANE_STATUS_NO_MEM; } /* Allocate the output buffer used for bayer conversion */ dev->output_size = dev->buffer_size * 3; dev->output = malloc (dev->output_size); if (dev->output == NULL) { free (dev->windowr); free (dev->windoww); free (dev->buffer); free (dev); return SANE_STATUS_NO_MEM; } dev->image_size = dev->buffer_size; dev->image = malloc (dev->image_size); if (dev->image == NULL) { free (dev->windowr); free (dev->windoww); free (dev->buffer); free (dev->output); free (dev); return SANE_STATUS_NO_MEM; } DBG (DBG_proc, "stv680_init_2: exit\n"); status = SANE_STATUS_GOOD; return status; } /* Closes an open vidcams. */ static void stv680_close (Stv680_Vidcam * dev) { DBG (DBG_proc, "stv680_close: enter \n"); if (dev->fd != -1) { DBG (DBG_proc, "stv680_close: fd !=-1 \n"); sanei_usb_close (dev->fd); dev->fd = -1; } DBG (DBG_proc, "stv680_close: exit\n"); } /* Frees the memory used by a vidcam. */ static void stv680_free (Stv680_Vidcam * dev) { int i; DBG (DBG_proc, "stv680_free: enter\n"); if (dev == NULL) return; stv680_close (dev); if (dev->devicename) { free (dev->devicename); } if (dev->buffer) { free (dev->buffer); } if (dev->output) { free (dev->output); } if (dev->image) { free (dev->image); } if (dev->windoww) { free (dev->windoww); } if (dev->windowr) { free (dev->windowr); } for (i = 1; i < OPT_NUM_OPTIONS; i++) { if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) { free (dev->val[i].s); } } if (dev->resolutions_list) free (dev->resolutions_list); free (dev); DBG (DBG_proc, "stv680_free: exit\n"); } static SANE_Status stv680_set_config (Stv680_Vidcam * dev, int configuration, int interface, int alternate) { SANE_Status status; DBG (DBG_proc, "stv680_set_config: open\n"); /* seems a problem on some systems (Debian amd64 unstable 19042006) * not calling usb_set_configuration seems to help reason ? status = sanei_usb_set_configuration (dev->fd, configuration); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_set_config: STV680 FAILED to set configuration %d\n", configuration); return status; } */ status = sanei_usb_claim_interface (dev->fd, interface); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_set_config: STV0680 FAILED to claim interface\n"); return status; } status = sanei_usb_set_altinterface (dev->fd, alternate); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_set_config: STV0680 FAILED to set alternate interface %d\n", alternate); return status; } DBG (DBG_proc, "stv680_set_config: configuration=%d, interface=%d, alternate=%d\n", configuration, interface, alternate); DBG (DBG_proc, "stv680_set_config: exit\n"); return status; } /* Reset vidcam */ static SANE_Status stv680_reset_vidcam (Stv680_Vidcam * dev) { SANE_Status status; size_t sizew; /* significant size of window */ size_t sizer; DBG (DBG_proc, "stv680_reset_vidcam: enter\n"); sizew = dev->windoww_size; sizer = dev->windowr_size; memset (dev->windoww, 0, sizew); memset (dev->windowr, 0, sizer); sizew = 0x00; /* was 0 ? */ status = sanei_usb_control_msg (dev->fd, 0x41, 0x0a, 0x0000, 0, sizew, dev->windoww); if (status != SANE_STATUS_GOOD) { return status; } DBG (DBG_proc, "stv680_reset_vidcam: CMDID_STOP_VIDEO end\n"); /* this is a high priority command; it stops all lower order commands */ sizew = 0x00; /* was 0 */ status = sanei_usb_control_msg (dev->fd, 0x41, 0x04, 0x0000, 0, sizew, dev->windoww); if (status != SANE_STATUS_GOOD) { return status; } DBG (DBG_proc, "stv680_reset_vidcam: CMDID_CANCEL_TRANSACTION end\n"); sizer = 0x02; DBG (DBG_proc, "stv680_reset_vidcam: CMDID_GET_LAST_ERROR begin\n"); status = sanei_usb_control_msg (dev->fd, 0xc1, 0x80, 0x0000, 0, sizer, dev->windowr); if (status != SANE_STATUS_GOOD) { /* Get Last Error; 2 = busy */ DBG (DBG_proc, "stv680_reset_vidcam: last error: %i, command = 0x%x\n", dev->windowr[0], dev->windowr[1]); return status; } else { DBG (DBG_proc, "stv680_reset_vidcam: Camera reset to idle mode.\n"); } hexdump (DBG_info2, "stv680_reset_vidcam: CMDID_GET_LAST_ERROR", dev->windowr, sizer); /* configuration = 1, interface = 0, alternate = 0 */ /* status = stv680_set_config (dev, 1, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_reset_vidcam: STV680 FAILED to set configure\n"); return status; } */ status = SANE_STATUS_GOOD; DBG (DBG_proc, "stv680_reset_vidcam: exit\n"); return status; } /* Inquiry a device and returns TRUE if is supported. */ static int stv680_identify_vidcam (Stv680_Vidcam * dev) { SANE_Status status; SANE_Word vendor; SANE_Word product; int i; size_t sizer; DBG (DBG_info, "stv680_identify_vidcam: open\n"); status = sanei_usb_get_vendor_product (dev->fd, &vendor, &product); /* Loop through our list to make sure this scanner is supported. */ for (i = 0; i < NELEMS (vidcams); i++) { if (vidcams[i].vendor == vendor && vidcams[i].product == product) { DBG (DBG_info, "stv680_identify_vidcam: vidcam %x:%x is in list\n", vendor, product); dev->hw = &(vidcams[i]); sizer = dev->windowr_size; memset (dev->windowr, 0, sizer); /* configuration = 1, interface = 0, alternate = 0 */ /* status = stv680_set_config (dev, 1, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_vidcam_init: STV680 FAILED to set configure\n"); return status; } */ sizer = 0x02; status = sanei_usb_control_msg (dev->fd, 0xc1, 0x88, 0x5678, 0, sizer, dev->windowr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_identify_vidcam: this is not a STV680 (idVendor = %d, bProduct = %d) writing register failed with %s\n", vendor, product, sane_strstatus (status)); return SANE_FALSE; } if ((dev->windowr[0] != 0x56) || (dev->windowr[1] != 0x78)) { DBG (DBG_proc, "STV(e): camera ping failed!!, checkvalue !=0x5678\n"); sizer = 0x02; hexdump (DBG_info2, "urb12 window", dev->windowr, sizer); return SANE_FALSE; } sizer = 0x02; hexdump (DBG_info2, "urb12 ping data", dev->windowr, sizer); sizer = 0x10; status = sanei_usb_control_msg (dev->fd, 0xc1, 0x85, 0x0000, 0, sizer, dev->windowr); if (status != SANE_STATUS_GOOD) return SANE_FALSE; hexdump (DBG_info2, "urbxx CMDID_GET_CAMERA_INFO", dev->windowr, sizer); dev->SupportedModes = dev->windowr[7]; i = dev->SupportedModes; dev->QSIF = 0; dev->CIF = 0; dev->QCIF = 0; dev->VGA = 0; dev->QVGA = 0; if (i & 1) dev->CIF = 1; if (i & 2) dev->VGA = 1; if (i & 8) dev->QVGA = 1; if (i & 4) dev->QCIF = 1; dev->QSIF = dev->QVGA; /* for software subsample */ if (dev->SupportedModes == 0) { DBG (DBG_proc, "STV(e): There are NO supported STV680 modes!!\n"); i = -1; return SANE_FALSE; } else { if (dev->VGA) DBG (DBG_proc, "STV(i): VGA is supported\n"); if (dev->CIF) DBG (DBG_proc, "STV(i): CIF is supported\n"); if (dev->QVGA) DBG (DBG_proc, "STV(i): QVGA is supported\n"); if (dev->QCIF) DBG (DBG_proc, "STV(i): QCIF is supported\n"); } /* FW rev, ASIC rev, sensor ID */ DBG (DBG_proc, "STV(i): Firmware rev is %i.%i\n", dev->windowr[0], dev->windowr[1]); DBG (DBG_proc, "STV(i): ASIC rev is %i.%i\n", dev->windowr[2], dev->windowr[3]); DBG (DBG_proc, "STV(i): Sensor ID is %i.%i\n", (dev->windowr[4]), (dev->windowr[5])); /* Hardware config */ dev->HardwareConfig = dev->windowr[6]; i = dev->HardwareConfig; /* Comms link, Flicker freq, Mem size */ if (i & 1) DBG (DBG_proc, "STV(i): Comms link is serial\n"); else DBG (DBG_proc, "STV(i): Comms link is USB\n"); if (i & 2) DBG (DBG_proc, "STV(i): Flicker freq = 60 Hz\n"); else DBG (DBG_proc, "STV(i): Flicker freq = 50 Hz\n"); if (i & 4) DBG (DBG_proc, "STV(i): Mem size = 16Mbit\n"); else DBG (DBG_proc, "STV(i): Mem size = 64Mbit\n"); if (i & 8) DBG (DBG_proc, "STV(i): Thumbnails supported\n"); else DBG (DBG_proc, "STV(i): Thumbnails N/A\n"); if (i & 16) DBG (DBG_proc, "STV(i): Video supported\n"); else DBG (DBG_proc, "STV(i): Video N/A\n"); if (i & 32) DBG (DBG_proc, "STV(i): Startup Complete\n"); else DBG (DBG_proc, "STV(i): Startup Not Complete\n"); if (i & 64) DBG (DBG_proc, "STV(i): Monochrome\n"); else DBG (DBG_proc, "STV(i): Color\n"); if (i & 128) DBG (DBG_proc, "STV(i): Mem fitted\n"); else DBG (DBG_proc, "STV(i): Mem not fitted\n"); DBG (DBG_proc, "urb 25 CMDID_GET_IMAGE_INFO\n"); sizer = 0x10; status = sanei_usb_control_msg (dev->fd, 0xc1, 0x86, 0x0000, 0, sizer, dev->windowr); if (status != SANE_STATUS_GOOD) { return SANE_FALSE; } hexdump (DBG_info2, "urb25 CMDID_GET_IMAGE_INFO", dev->windowr, sizer); DBG (DBG_proc, "STV(i): Current image index %d\n", ((dev->windowr[0] << 8) + (dev->windowr[1]))); DBG (DBG_proc, "If images are stored in camera, they will be lost when captering images is started!!!!!\n"); DBG (DBG_proc, "STV(i): Max images %d\n", ((dev->windowr[2] << 8) + (dev->windowr[3]))); DBG (DBG_proc, "STV(i): Image width (pix) %d\n", ((dev->windowr[4] << 8) + (dev->windowr[5]))); DBG (DBG_proc, "STV(i): Image height (pix) %d\n", ((dev->windowr[6] << 8) + (dev->windowr[7]))); DBG (DBG_proc, "STV(i): Image size camera %d bytes\n", ((dev->windowr[8] << 24) + (dev->windowr[9] << 16) + (dev->windowr[10] << 8) + (dev->windowr[11]))); /* configuration = 1, interface = 0, alternate = 1 */ status = stv680_set_config (dev, 1, 0, 1); /* if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_vidcam_init: STV680 FAILED to set configure\n"); return status; } DBG (DBG_info, "stv680_identify_vidcam: exit vidcam supported\n"); */ return SANE_TRUE; } } DBG (DBG_error, "stv680_identify_vidcam: exit this is not a STV680 exit\n"); return SANE_FALSE; } static SANE_Status stv680_vidcam_init (Stv680_Vidcam * dev) { SANE_Status status; SANE_Byte i = 0; SANE_Byte val = 0; size_t sizer; size_t sizew; DBG (DBG_proc, "stv680_vidcam_init: open\n"); sizew = dev->windoww_size; sizer = dev->windowr_size; memset (dev->windoww, 0, sizew); memset (dev->windowr, 0, sizer); DBG (DBG_proc, "stv680_vidcam_init: urb 13 CMDID_GET_USER_INFO\n"); dev->video_status = 0x04; /* dummy value busy */ while (dev->video_status == 0x04) { sizer = 0x08; status = sanei_usb_control_msg (dev->fd, 0xc1, 0x8d, 0x0000, 0, sizer, dev->windowr); if (status != SANE_STATUS_GOOD) return status; hexdump (DBG_info2, "stv680_vidcam_init: urb13 CMDID_GET_USER_INFO", dev->windowr, sizer); dev->video_status = dev->windowr[1]; if (dev->video_status == 0x02) { DBG (DBG_proc, "stv680_vidcam_init: status = video\n"); } else if ((dev->video_status == 0x01) || (dev->video_status == 0x08)) { DBG (DBG_proc, "stv680_vidcam_init: status=%d\n", dev->video_status); } else if (dev->video_status != 0x04) { DBG (DBG_proc, "stv680_vidcam_init: status = busy\n"); /* CMDID_CANCEL_TRANSACTION */ status = sanei_usb_control_msg (dev->fd, 0x41, 0x04, 0x0000, 0, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_info, "stv680_vidcam_init: urb13 CMDID_CANCEL_TRANSACTION NOK\n"); return status; } } } if (dev->video_status == 0x01 || dev->video_status == 0x08) { DBG (DBG_proc, "stv680_vidcam_init: urb 21 CMDID_GET_COLDATA_SIZE\n"); sizer = 0x02; status = sanei_usb_control_msg (dev->fd, 0xc1, 0x8a, 0x0000, 0, sizer, dev->windowr); if (status != SANE_STATUS_GOOD) return status; val = dev->windowr[0]; hexdump (DBG_info2, "stv680_vidcam_init: urb21 CMDID_GET_COLDATA_SIZE", dev->windowr, sizer); if (dev->windowr[0] &= 0x00) DBG (DBG_info, "stv680_vidcam_init: no camera defaults, must be downloaded?\n"); sizer = 0x10; for (i = 0; i < val; i += 0x10) { DBG (DBG_proc, "stv680_vidcam_init: urb 22, 23, 24 CMDID_GET_COLDATA i=0x%x, val=0x%x\n", i, val); status = sanei_usb_control_msg (dev->fd, 0xc1, 0x8b, (i << 8), 0, sizer, dev->windowr); if (status != SANE_STATUS_GOOD) return status; hexdump (DBG_info2, "stv680_vidcam_init: urb22, 23, 24 CMDID_GET_COLDATA", dev->windowr, sizer); } sizer = 0x12; status = sanei_usb_control_msg (dev->fd, 0x80, 0x06, 0x0100, 0, sizer, dev->windowr); if (status != SANE_STATUS_GOOD) return status; /* if (!(i > 0) && (dev->windowr[8] == 0x53) && (dev->windowr[9] == 0x05)) { DBG (DBG_proc, "STV(e): Could not get descriptor 0100."); *//* return status; *//* } */ sizer = 0x12; hexdump (DBG_info2, "stv680_vidcam_init: CMDID_SET_IMAGE_INDEX", dev->windowr, sizer); /* configuration = 1, interface = 0, alternate = 1 */ status = stv680_set_config (dev, 1, 0, 1); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_vidcam_init: STV680 FAILED to set configure\n"); return status; } } /* Switch to Video mode: 0x0000 = CIF (352x288), 0x0200 = QCIF (176x144) */ /* Switch to Video mode: 0x0100 = VGA (640x480), 0x0300 = QVGA (320x240) */ sizew = 0x0; status = sanei_usb_control_msg (dev->fd, 0x41, 0x09, dev->video_mode, 0, sizew, dev->windoww); if (status != SANE_STATUS_GOOD) { DBG (DBG_proc, "stv680_vidcam_init: video_mode = 0x%x\n", dev->video_mode); return status; } DBG (DBG_proc, "stv680_vidcam_init: CMDID_START_VIDEO: video_mode=0x%x\n", dev->video_mode); if (dev->x_resolution == 176) { usleep (1000); /* delay time needed */ } status = SANE_STATUS_GOOD; if (status) { DBG (DBG_error, "stv680_vidcam_init failed : %s\n", sane_strstatus (status)); return status; } DBG (DBG_proc, "stv680_vidcam_init: exit\n"); return status; } /* Attach a vidcam to this backend. */ static SANE_Status attach_vidcam (SANE_String_Const devicename, Stv680_Vidcam ** devp) { Stv680_Vidcam *dev; int fd; SANE_Status status; DBG (DBG_proc, "attach_vidcam: %s\n", devicename); if (devp) *devp = NULL; /* Check if we know this device name. */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (DBG_info, "device is already known\n"); return SANE_STATUS_GOOD; } } /* Allocate a new vidcam entry. */ dev = stv680_init (); if (dev == NULL) { DBG (DBG_error, "stv680_init ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_vidcam: opening USB device %s\n", devicename); if (sanei_usb_open (devicename, &fd) != 0) { DBG (DBG_error, "ERROR: attach_vidcam: open failed\n"); stv680_free (dev); return SANE_STATUS_INVAL; } /* Fill some scanner specific values. */ dev->devicename = strdup (devicename); dev->fd = fd; /* Now, check that it is a vidcam we support. */ if (stv680_identify_vidcam (dev) == SANE_FALSE) { DBG (DBG_error, "ERROR: attach_vidcam: vidcam-identification failed\n"); stv680_free (dev); return SANE_STATUS_INVAL; } /* Allocate a buffer memory. */ status = stv680_init_2 (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "stv680_initi_2, ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } stv680_close (dev); DBG (DBG_info, "attach_vidcam: opening USB device %s\n", devicename); /* Build list of vidcam supported resolutions. */ DBG (DBG_proc, "attach_vidcam: build resolution list\n"); if (dev->hw->color_adjust[0].resolution_x != 0) { int num_entries; int i; num_entries = 0; while (dev->hw->color_adjust[num_entries].resolution_x != 0) num_entries++; dev->resolutions_list = malloc (sizeof (SANE_Word) * (num_entries + 1)); if (dev->resolutions_list == NULL) { DBG (DBG_error, "ERROR: attach_vidcam: vidcam resolution list failed\n"); stv680_free (dev); return SANE_STATUS_NO_MEM; } /* for CIF or VGA sensor different resolutions */ if (dev->CIF) num_entries = 2; if (dev->VGA) num_entries = 3; dev->resolutions_list[0] = num_entries; DBG (DBG_proc, "attach_vidcam: make color resolution table \n"); for (i = 0; i < num_entries; i++) { dev->resolutions_list[i + 1 + dev->VGA + dev->QVGA] = dev->hw->color_adjust[i].resolution_x; } } else { dev->resolutions_list = NULL; } /* Set the default options for that vidcam. */ dev->sane.name = dev->devicename; dev->sane.vendor = dev->hw->vendor_name; dev->sane.model = dev->hw->product_name; dev->sane.type = SANE_I18N ("webcam"); /* Link the vidcam with the others. */ dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } num_devices++; DBG (DBG_proc, "attach_vidcam: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { DBG (DBG_proc, "attach_one: open \n"); attach_vidcam (dev, NULL); DBG (DBG_proc, "attach_one: exit \n"); return SANE_STATUS_GOOD; } /* Reset the options for that vidcam. */ static void stv680_init_options (Stv680_Vidcam * dev) { int i; DBG (DBG_proc, "stv680_init_options: open\n"); /* Pre-initialize the options. */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < OPT_NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } DBG (DBG_proc, "stv680_init_options: done loop opt_num_options=%d, i=%d \n", OPT_NUM_OPTIONS, i); /* Number of options. */ dev->opt[OPT_NUM_OPTS].name = ""; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; /* Mode group */ dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].cap = 0; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Vidcam supported modes */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = max_string_size (scan_mode_list); dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = scan_mode_list; dev->val[OPT_MODE].s = (SANE_Char *) strdup (""); /* will be set later */ /* X and Y resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; dev->val[OPT_RESOLUTION].w = dev->resolutions_list[dev->CIF + dev->QCIF + dev->VGA + dev->QVGA + dev->QSIF]; /* value will be 2 or 3 */ /* brightness */ dev->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; dev->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; dev->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BRIGHTNESS].constraint.range = &brightness_range; dev->val[OPT_BRIGHTNESS].w = 0; /* to get middle value */ /* Enhancement group */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* red level calibration manual correction */ dev->opt[OPT_WHITE_LEVEL_R].name = SANE_NAME_WHITE_LEVEL_R; dev->opt[OPT_WHITE_LEVEL_R].title = SANE_TITLE_WHITE_LEVEL_R; dev->opt[OPT_WHITE_LEVEL_R].desc = SANE_DESC_WHITE_LEVEL_R; dev->opt[OPT_WHITE_LEVEL_R].type = SANE_TYPE_INT; dev->opt[OPT_WHITE_LEVEL_R].unit = SANE_UNIT_NONE; dev->opt[OPT_WHITE_LEVEL_R].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_WHITE_LEVEL_R].constraint.range = &red_level_range; dev->val[OPT_WHITE_LEVEL_R].w = 00; /* to get middle value */ /* green level calibration manual correction */ dev->opt[OPT_WHITE_LEVEL_G].name = SANE_NAME_WHITE_LEVEL_G; dev->opt[OPT_WHITE_LEVEL_G].title = SANE_TITLE_WHITE_LEVEL_G; dev->opt[OPT_WHITE_LEVEL_G].desc = SANE_DESC_WHITE_LEVEL_G; dev->opt[OPT_WHITE_LEVEL_G].type = SANE_TYPE_INT; dev->opt[OPT_WHITE_LEVEL_G].unit = SANE_UNIT_NONE; dev->opt[OPT_WHITE_LEVEL_G].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_WHITE_LEVEL_G].constraint.range = &green_level_range; dev->val[OPT_WHITE_LEVEL_G].w = 00; /* to get middle value */ /* blue level calibration manual correction */ dev->opt[OPT_WHITE_LEVEL_B].name = SANE_NAME_WHITE_LEVEL_B; dev->opt[OPT_WHITE_LEVEL_B].title = SANE_TITLE_WHITE_LEVEL_B; dev->opt[OPT_WHITE_LEVEL_B].desc = SANE_DESC_WHITE_LEVEL_B; dev->opt[OPT_WHITE_LEVEL_B].type = SANE_TYPE_INT; dev->opt[OPT_WHITE_LEVEL_B].unit = SANE_UNIT_NONE; dev->opt[OPT_WHITE_LEVEL_B].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_WHITE_LEVEL_B].constraint.range = &blue_level_range; dev->val[OPT_WHITE_LEVEL_B].w = 00; /* to get middle value */ DBG (DBG_proc, "stv680_init_options: after blue level\n"); /* Lastly, set the default scan mode. This might change some * values previously set here. */ sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, (SANE_String_Const *) scan_mode_list[0], NULL); DBG (DBG_proc, "stv680_init_options: exit\n"); } /* Read the image from the vidcam and fill the temporary buffer with it. */ static SANE_Status stv680_fill_image (Stv680_Vidcam * dev) { SANE_Status status; size_t size; size_t bulk_size_read; assert (dev->image_begin == dev->image_end); assert (dev->real_bytes_left > 0); DBG (DBG_proc, "stv680_fill_image: enter\n"); DBG (DBG_proc, "stv680_fill_image: real dev bytes left=0x%lx \n", (unsigned long) (size_t) dev->real_bytes_left); bulk_size_read = dev->real_bytes_left; while (dev->real_bytes_left) { /* Try to read the maximum number of bytes. */ DBG (DBG_proc, "stv680_fill_image: real dev bytes left, while loop=0x%lx \n", (unsigned long) (size_t) dev->real_bytes_left); size = dev->real_bytes_left; if (size < bulk_size_read) { size = bulk_size_read; /* it seems size can not be smaller then read by bulk */ } if (size == 0) { /* Probably reached the end of the buffer. Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } /* Do the transfer */ DBG (DBG_proc, "stv680_fill_image: dev->real_bytes_left: 0x%lx size: 0x%lx\n", (unsigned long) (size_t) dev->real_bytes_left, (unsigned long) (size_t) size); usleep (3000); /* urb 44 first read bulk */ status = sanei_usb_read_bulk (dev->fd, dev->buffer, &size); if (status != SANE_STATUS_GOOD) { return status; } DBG (DBG_info, "stv680_fill_image: size (read) = 0x%lx bytes (bpl=0x%lx)\n", (unsigned long) (size_t) size, (unsigned long) (size_t) dev->params.bytes_per_line); memcpy (dev->image + dev->image_end, dev->buffer, size); dev->image_end += size; bulk_size_read = size; if (dev->real_bytes_left > size) dev->real_bytes_left -= size; else if (dev->real_bytes_left <= size) /* last loop */ dev->real_bytes_left = 0; DBG (DBG_info, "stv680_fill_image: real bytes left = 0x%lx\n", (unsigned long) (size_t) dev->real_bytes_left); } /* i = stv_sndctrl (0, dev, 0x80, 0, &window, 0x02); *//* Get Last Error */ /* DBG (DBG_proc, "STV(i): last error: %i, command = 0x%x", window[0], window[1]); return -1; */ /* } return 0; */ DBG (DBG_proc, "stv680_fill_image: exit\n"); return (SANE_STATUS_GOOD); /* unreachable */ } #define MSG_MAXLEN 45 #define CHAR_HEIGHT 11 #define CHAR_WIDTH 6 #define CHAR_START 4 static SANE_Status stv680_add_text (SANE_Byte * image, int width, int height, char *txt) { SANE_Status status; time_t t; struct tm *tm; char line[MSG_MAXLEN + 1]; SANE_Byte *ptr; int i, x, y, f, len; char fmtstring[25] = " %Y-%m-%d %H:%M:%S"; char fmttxt[46]; DBG (DBG_proc, "stv680_add_text: enter\n"); time (&t); tm = localtime (&t); if (strlen (txt) > (MSG_MAXLEN - 23)) strncpy (fmttxt, txt, (MSG_MAXLEN - 23)); else strcpy (fmttxt, txt); strcat (fmttxt, fmtstring); len = strftime (line, MSG_MAXLEN, fmttxt, tm); for (y = 0; y < CHAR_HEIGHT; y++) { ptr = image + 3 * width * (height - CHAR_HEIGHT - 2 + y) + 12; for (x = 0; x < len; x++) { f = fontdata[line[x] * CHAR_HEIGHT + y]; for (i = CHAR_WIDTH - 1; i >= 0; i--) { if (f & (CHAR_START << i)) { ptr[0] = 255; ptr[1] = 255; ptr[2] = 255; } ptr += 3; } /* for i */ } /* for x */ } /* for y */ DBG (DBG_proc, "stv680_add_text: exit vw=%d, vh=%d\n", width, height); status = (SANE_STATUS_GOOD); return status; } /* ************************** Video Decoding ********************* */ static SANE_Status stv680_bayer_unshuffle (Stv680_Vidcam * dev, SANE_Byte * buf, size_t * size) { SANE_Status status; int x, y; int i = 0; int RED, GREEN, BLUE; int w = dev->cwidth; int vw = dev->x_resolution; int vh = dev->y_resolution; SANE_Byte p = 0; int colour = 0, bayer = 0; int bright_red; int bright_green; int bright_blue; int count; RED = dev->red_s; GREEN = dev->green_s; BLUE = dev->blue_s; DBG (DBG_proc, "stv680_bayer_unshuffle: enter\n"); #define AD(x, y, w) (((y)*(w)+(x))*3) DBG (DBG_proc, "stv680_bayer_unshuffle: color read RED=%d, GREEN=%d, BLUE=%d\n", RED, GREEN, BLUE); DBG (DBG_proc, "stv680_bayer_unshuffle: w=%d, vw=%d, vh=%d, len=0x%lx\n", w, vw, vh, (unsigned long) (size_t) size); for (y = 0; y < vh; y++) { for (x = 0; x < vw; x++) { if (x & 1) { p = dev->image[y * w + (x >> 1)]; } else { p = dev->image[y * w + (x >> 1) + (w >> 1)]; } if (y & 1) bayer = 2; else bayer = 0; if (x & 1) bayer++; switch (bayer) { case 0: case 3: colour = 1; break; case 1: colour = 0; break; case 2: colour = 2; break; } i = (y * vw + x) * 3; *(dev->output + i + colour) = (SANE_Byte) p; } /* for x */ } /* for y */ /****** gamma correction plus hardcoded white balance */ /* Correction values red[], green[], blue[], are generated by (pow(i/256.0, GAMMA)*255.0)*white balanceRGB where GAMMA=0.55, 1scan_mode == STV680_COLOR_RGB || dev->scan_mode == STV680_COLOR_RGB_TEXT) { for (y = 0; y < vh; y++) { for (x = 0; x < vw; x++) { i = (y * vw + x) * 3; *(dev->output + i) = red_g[*(dev->output + i)]; *(dev->output + i + 1) = green_g[*(dev->output + i + 1)]; *(dev->output + i + 2) = blue_g[*(dev->output + i + 2)]; } } } DBG (DBG_proc, "stv680_bayer_unshuffle: gamma correction done\n"); if (dev->scan_mode != STV680_COLOR_RAW) { /****** bayer demosaic ******/ for (y = 1; y < (vh - 1); y++) { for (x = 1; x < (vw - 1); x++) { /* work out pixel type */ if (y & 1) bayer = 0; else bayer = 2; if (!(x & 1)) bayer++; switch (bayer) { case 0: /* green. blue lr, red tb */ *(dev->output + AD (x, y, vw) + BLUE) = ((int) *(dev->output + AD (x - 1, y, vw) + BLUE) + (int) *(dev->output + AD (x + 1, y, vw) + BLUE)) >> 1; *(dev->output + AD (x, y, vw) + RED) = ((int) *(dev->output + AD (x, y - 1, vw) + RED) + (int) *(dev->output + AD (x, y + 1, vw) + RED)) >> 1; break; case 1: /* blue. green lrtb, red diagonals */ *(dev->output + AD (x, y, vw) + GREEN) = ((int) *(dev->output + AD (x - 1, y, vw) + GREEN) + (int) *(dev->output + AD (x + 1, y, vw) + GREEN) + (int) *(dev->output + AD (x, y - 1, vw) + GREEN) + (int) *(dev->output + AD (x, y + 1, vw) + GREEN)) >> 2; *(dev->output + AD (x, y, vw) + RED) = ((int) *(dev->output + AD (x - 1, y - 1, vw) + RED) + (int) *(dev->output + AD (x - 1, y + 1, vw) + RED) + (int) *(dev->output + AD (x + 1, y - 1, vw) + RED) + (int) *(dev->output + AD (x + 1, y + 1, vw) + RED)) >> 2; break; case 2: /* red. green lrtb, blue diagonals */ *(dev->output + AD (x, y, vw) + GREEN) = ((int) *(dev->output + AD (x - 1, y, vw) + GREEN) + (int) *(dev->output + AD (x + 1, y, vw) + GREEN) + (int) *(dev->output + AD (x, y - 1, vw) + GREEN) + (int) *(dev->output + AD (x, y + 1, vw) + GREEN)) >> 2; *(dev->output + AD (x, y, vw) + BLUE) = ((int) *(dev->output + AD (x - 1, y - 1, vw) + BLUE) + (int) *(dev->output + AD (x + 1, y - 1, vw) + BLUE) + (int) *(dev->output + AD (x - 1, y + 1, vw) + BLUE) + (int) *(dev->output + AD (x + 1, y + 1, vw) + BLUE)) >> 2; break; case 3: /* green. red lr, blue tb */ *(dev->output + AD (x, y, vw) + RED) = ((int) *(dev->output + AD (x - 1, y, vw) + RED) + (int) *(dev->output + AD (x + 1, y, vw) + RED)) >> 1; *(dev->output + AD (x, y, vw) + BLUE) = ((int) *(dev->output + AD (x, y - 1, vw) + BLUE) + (int) *(dev->output + AD (x, y + 1, vw) + BLUE)) >> 1; break; } /* switch */ } /* for x */ } /* for y - end demosaic */ } /* no bayer demosaic */ DBG (DBG_proc, "stv680_bayer_unshuffle: bayer demosaic done\n"); /* fix top and bottom row, left and right side */ i = vw * 3; memcpy (dev->output, (dev->output + i), i); memcpy ((dev->output + (vh * i)), (dev->output + ((vh - 1) * i)), i); for (y = 0; y < vh; y++) { i = y * vw * 3; memcpy ((dev->output + i), (dev->output + i + 3), 3); memcpy ((dev->output + i + (vw * 3)), (dev->output + i + (vw - 1) * 3), 3); } /* process all raw data, then trim to size if necessary */ if (dev->subsample == 160) { i = 0; for (y = 0; y < vh; y++) { if (!(y & 1)) { for (x = 0; x < vw; x++) { p = (y * vw + x) * 3; if (!(x & 1)) { *(dev->output + i) = *(dev->output + p); *(dev->output + i + 1) = *(dev->output + p + 1); *(dev->output + i + 2) = *(dev->output + p + 2); i += 3; } } /* for x */ } } /* for y */ DBG (DBG_proc, "stv680_bayer_unshuffle: if needed, trim to size 160 done\n"); } /* reset to proper width */ if ((dev->subsample == 160)) { vw = 160; vh = 120; } /* brightness adjustment */ count = vw * vh * 3; bright_red = (dev->val[OPT_BRIGHTNESS].w) + (dev->val[OPT_WHITE_LEVEL_R].w); bright_green = (dev->val[OPT_BRIGHTNESS].w) + (dev->val[OPT_WHITE_LEVEL_G].w); bright_blue = (dev->val[OPT_BRIGHTNESS].w) + (dev->val[OPT_WHITE_LEVEL_B].w); for (x = 0; x < count; x++) { y = x + 1; i = x + 2; if ((*(dev->output + x) + bright_red) >= 255) *(buf + x) = 255; else if ((*(dev->output + x) + bright_red) <= 0) *(buf + x) = 0; else *(buf + x) = (*(dev->output + x) + bright_red); if ((*(dev->output + y) + bright_green) >= 255) *(buf + y) = 255; else if ((*(dev->output + y) + bright_green) <= 0) *(buf + y) = 0; else *(buf + y) = (*(dev->output + y) + bright_green); if ((*(dev->output + i) + bright_blue) >= 255) *(buf + i) = 255; else if ((*(dev->output + i) + bright_blue) <= 0) *(buf + i) = 0; else *(buf + i) = (*(dev->output + i) + bright_blue); x += 2; } if (dev->scan_mode == STV680_COLOR_RGB_TEXT) { strcpy (dev->picmsg_ps, "STVcam "); status = stv680_add_text (buf, vw, vh, dev->picmsg_ps); if (status != SANE_STATUS_GOOD) { DBG (DBG_info, "stv680_bayer_unshuffle status NOK\n"); return (status); } } DBG (DBG_proc, "stv680_bayer_unshuffle: exit vw=%d, vh=%d\n", vw, vh); status = (SANE_STATUS_GOOD); return status; } /* Sane entry points */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { FILE *fp; char line[PATH_MAX]; size_t len; num_devices = 0; devlist = NULL; first_dev = NULL; DBG_INIT (); DBG (DBG_sane_init, "sane_init\n"); authorize = authorize; /* silence gcc */ DBG (DBG_error, "This is sane-stv680 version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_error, "(C) 2004-2006 by Gerard Klaver\n"); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); } DBG (DBG_proc, "sane_init: authorize %s null\n", authorize ? "!=" : "=="); sanei_usb_init (); fp = sanei_config_open (STV680_CONFIG_FILE); if (!fp) { /* No default vidcam? */ DBG (DBG_warning, "configuration file not found (%s)\n", STV680_CONFIG_FILE); return SANE_STATUS_GOOD; } while (sanei_config_read (line, sizeof (line), fp)) { SANE_Word vendor; SANE_Word product; if (line[0] == '#') /* ignore line comments */ continue; len = strlen (line); if (!len) continue; /* ignore empty lines */ if (sscanf (line, "usb %i %i", &vendor, &product) == 2) { sanei_usb_attach_matching_devices (line, attach_one); } else { /* Garbage. Ignore. */ DBG (DBG_warning, "bad configuration line: \"%s\" - ignoring.\n", line); } } fclose (fp); DBG (DBG_proc, "sane_init: leave\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Stv680_Vidcam *dev; int i; DBG (DBG_proc, "sane_get_devices: enter\n"); local_only = local_only; /* silence gcc */ if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Stv680_Vidcam *dev; SANE_Status status; DBG (DBG_proc, "sane_open: enter\n"); /* search for devicename */ if (devicename[0]) { DBG (DBG_info, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_vidcam (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); dev = first_dev; /* empty devicename -> use first device */ } if (!dev) { DBG (DBG_error, "No vidcam found\n"); return SANE_STATUS_INVAL; } stv680_init_options (dev); *handle = dev; DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Stv680_Vidcam *dev = handle; DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); if ((unsigned) option >= OPT_NUM_OPTIONS) { return NULL; } DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return dev->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Stv680_Vidcam *dev = handle; SANE_Status status; SANE_Word cap; DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", option, action); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_BRIGHTNESS: case OPT_WHITE_LEVEL_R: case OPT_WHITE_LEVEL_G: case OPT_WHITE_LEVEL_B: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; case OPT_MODE: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Numeric side-effect options */ case OPT_RESOLUTION: case OPT_BRIGHTNESS: case OPT_WHITE_LEVEL_R: case OPT_WHITE_LEVEL_G: case OPT_WHITE_LEVEL_B: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* String side-effect options */ case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); dev->opt[OPT_WHITE_LEVEL_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_B].cap &= ~SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, COLOR_RAW_STR) == 0) { dev->scan_mode = STV680_COLOR_RAW; } else if (strcmp (dev->val[OPT_MODE].s, COLOR_RGB_STR) == 0) { dev->scan_mode = STV680_COLOR_RGB; } else if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dev->scan_mode = STV680_COLOR; } else if (strcmp (dev->val[OPT_MODE].s, COLOR_RGB_TEXT_STR) == 0) { dev->scan_mode = STV680_COLOR_RGB_TEXT; } /* The STV680 supports only a handful of resolution. */ /* This the default resolution range for the STV680 */ dev->depth = 8; if (dev->resolutions_list != NULL) { int i; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_RESOLUTION].constraint.word_list = dev->resolutions_list; /* If the resolution isn't in the list, set a default. */ for (i = 1; i <= dev->resolutions_list[0]; i++) { if (dev->resolutions_list[i] >= dev->val[OPT_RESOLUTION].w) break; } if (i > dev->resolutions_list[0]) { /* Too big. Take lowest. */ dev->val[OPT_RESOLUTION].w = dev->resolutions_list[1]; } else { /* Take immediate superioir value. */ dev->val[OPT_RESOLUTION].w = dev->resolutions_list[i]; } } /* String side-effect options */ if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Stv680_Vidcam *dev = handle; int i; DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { dev->x_resolution = dev->val[OPT_RESOLUTION].w; /* Prepare the parameters for the caller. */ memset (&dev->params, 0, sizeof (SANE_Parameters)); dev->params.last_frame = SANE_TRUE; switch (dev->scan_mode) { case STV680_COLOR_RAW: dev->bytes_pixel = 1; /* raw image is 422 code, 1 byte/pixel */ break; case STV680_COLOR_RGB: case STV680_COLOR_RGB_TEXT: case STV680_COLOR: dev->bytes_pixel = 3; break; } dev->params.format = SANE_FRAME_RGB; dev->params.pixels_per_line = dev->x_resolution; dev->params.bytes_per_line = dev->params.pixels_per_line * dev->bytes_pixel; dev->params.depth = 8; if (dev->resolutions_list != NULL) { /* This vidcam has a fixed number of supported * resolutions. Find the color sequence for that * resolution. */ for (i = 0; dev->hw->color_adjust[i].resolution_x != dev->x_resolution; i++); dev->red_s = dev->hw->color_adjust[i].z1_color_0; dev->green_s = dev->hw->color_adjust[i].z1_color_1; dev->blue_s = dev->hw->color_adjust[i].z1_color_2; dev->y_resolution = dev->hw->color_adjust[i].resolution_y; } dev->subsample = 0; switch (dev->val[OPT_RESOLUTION].w) { case 176: dev->video_mode = 0x0200; dev->cwidth = dev->x_resolution + 2; dev->cheight = dev->y_resolution + 2; break; case 160: /* 160x120 subsampled */ dev->x_resolution = 320; dev->y_resolution = 240; dev->video_mode = 0x0300; dev->cwidth = dev->x_resolution + 2; dev->cheight = dev->y_resolution + 2; dev->subsample = 160; break; case 320: dev->video_mode = 0x0300; dev->cwidth = dev->x_resolution + 2; dev->cheight = dev->y_resolution + 2; break; case 352: dev->video_mode = 0x0000; dev->cwidth = dev->x_resolution + 4; dev->cheight = dev->y_resolution + 4; break; case 640: dev->video_mode = 0x0100; dev->cwidth = dev->x_resolution + 4; dev->cheight = dev->y_resolution + 4; break; } dev->params.pixels_per_line = dev->x_resolution; dev->params.lines = dev->y_resolution; DBG (DBG_info, "sane_get_parameters: x=%d, y=%d\n", dev->x_resolution, dev->y_resolution); } /* Return the current values. */ if (params) { *params = (dev->params); } DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Stv680_Vidcam *dev = handle; SANE_Status status; DBG (DBG_proc, "sane_start: enter\n"); if (!(dev->scanning)) { sane_get_parameters (dev, NULL); /* Open again the vidcam */ if (sanei_usb_open (dev->devicename, &(dev->fd)) != 0) { DBG (DBG_error, "ERROR: sane_start: open failed\n"); return SANE_STATUS_INVAL; } /* Initialize the vidcam. */ status = stv680_vidcam_init (dev); if (status) { DBG (DBG_error, "ERROR: failed to init the vidcam\n"); stv680_close (dev); return status; } } dev->image_end = 0; dev->image_begin = 0; /* real_byte_left is bulk read bytes, bytes_left is frontend buffer bytes */ dev->real_bytes_left = dev->cwidth * dev->cheight; dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->scanning = SANE_TRUE; DBG (DBG_proc, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status status; Stv680_Vidcam *dev = handle; size_t size; DBG (DBG_proc, "sane_read: enter\n"); *len = 0; if (dev->deliver_eof) { dev->deliver_eof = 0; return SANE_STATUS_EOF; } if (!(dev->scanning)) { /* OOPS, not scanning, stop a scan. */ stv680_reset_vidcam (dev); stv680_close (dev); dev->scanning = SANE_FALSE; return SANE_STATUS_CANCELLED; } if (dev->bytes_left <= 0) { return (SANE_STATUS_EOF); } if (dev->image_begin == dev->image_end) { /* Fill image */ status = stv680_fill_image (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_info, "sane_read: stv680_fill_image status NOK\n"); return (status); } } /* Something must have been read */ if (dev->image_begin == dev->image_end) { DBG (DBG_info, "sane_read: nothing read\n"); return SANE_STATUS_IO_ERROR; } size = dev->bytes_left; if (((unsigned int) max_len) < size) { DBG (DBG_error, "sane_read: max_len < size\n"); return (SANE_FALSE); } if ((dev->image_end - dev->image_begin) > size) { size = dev->image_end - dev->image_begin; DBG (DBG_proc, "sane_read: size < dev->image_end - dev->image_begin\n"); } /* diff between size an dev->bytes_left because of 356/352 and 292/288 */ DBG (DBG_info, "sane_read: size =0x%lx bytes, max_len=0x%lx bytes\n", (unsigned long) (size_t) size, (unsigned long) (size_t) max_len); *len = dev->bytes_left; /* needed */ size = dev->bytes_left; dev->bytes_left = 0; /* needed for frontend or ? */ if (dev->scan_mode != STV680_COLOR_RAW) { /* do bayer unshuffle after complete frame is read */ status = stv680_bayer_unshuffle (dev, buf, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_info, "sane_read: stv680_bayer_unshuffle status NOK\n"); return (status); } } else { /* Copy the raw data to the frontend buffer. */ memcpy (buf, dev->image, size); DBG (DBG_info, "sane_read: raw mode\n"); } DBG (DBG_info, "sane_read: exit\n"); status = SANE_STATUS_GOOD; return status; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (DBG_proc, "sane_set_io_mode: enter\n"); handle = handle; /* silence gcc */ non_blocking = non_blocking; /* silence gcc */ DBG (DBG_proc, "sane_set_io_mode: exit\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (DBG_proc, "sane_get_select_fd: enter\n"); handle = handle; /* silence gcc */ fd = fd; /* silence gcc */ DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } void sane_cancel (SANE_Handle handle) { Stv680_Vidcam *dev = handle; DBG (DBG_proc, "sane_cancel: enter\n"); /* Stop a scan. */ if (dev->scanning == SANE_TRUE) { /* Reset the vidcam */ stv680_reset_vidcam (dev); stv680_close (dev); } dev->scanning = SANE_FALSE; dev->deliver_eof = 0; /* return SANE_STATUS_CANCELLED; */ DBG (DBG_proc, "sane_cancel: exit\n"); } void sane_close (SANE_Handle handle) { Stv680_Vidcam *dev = handle; Stv680_Vidcam *dev_tmp; DBG (DBG_proc, "sane_close: enter\n"); /* Stop a scan. */ if (dev->scanning == SANE_TRUE) { stv680_reset_vidcam (dev); stv680_close (dev); } dev->scanning = SANE_FALSE; /* Unlink dev. */ if (first_dev == dev) { first_dev = dev->next; } else { dev_tmp = first_dev; while (dev_tmp->next && dev_tmp->next != dev) { dev_tmp = dev_tmp->next; } if (dev_tmp->next != NULL) { dev_tmp->next = dev_tmp->next->next; } } stv680_free (dev); num_devices--; DBG (DBG_proc, "sane_close: exit\n"); } void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); while (first_dev) { sane_close (first_dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); } sane-backends-1.0.27/backend/teco3.h0000664000175000017500000003074312112021330013767 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ */ /* Commands supported by the scanner. */ #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_REQUEST_SENSE 0x03 #define SCSI_VENDOR_09 0x09 #define SCSI_VENDOR_0E 0x0E #define SCSI_INQUIRY 0x12 #define SCSI_MODE_SELECT 0x15 #define SCSI_SCAN 0x1b #define SCSI_SET_WINDOW 0x24 #define SCSI_SEND_10 0x2a #define SCSI_READ_10 0x28 #define SCSI_OBJECT_POSITION 0x31 #define SCSI_GET_DATA_BUFFER_STATUS 0x34 typedef struct { unsigned char data[16]; int len; } CDB; /* Set a specific bit depending on a boolean. * MKSCSI_BIT(TRUE, 3) will generate 0x08. */ #define MKSCSI_BIT(bit, pos) ((bit)? 1<<(pos): 0) /* Set a value in a range of bits. * MKSCSI_I2B(5, 3, 5) will generate 0x28 */ #define MKSCSI_I2B(bits, pos_b, pos_e) ((bits) << (pos_b) & ((1<<((pos_e)-(pos_b)+1))-1)) /* Store an integer in 2, 3 or 4 byte in an array. */ #define Ito16(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 0) & 0xff; \ } #define Ito24(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 0) & 0xff; \ } #define Ito32(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 24) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[3] = ((val) >> 0) & 0xff; \ } #define MKSCSI_GET_DATA_BUFFER_STATUS(cdb, wait, buflen) \ cdb.data[0] = SCSI_GET_DATA_BUFFER_STATUS; \ cdb.data[1] = MKSCSI_BIT(wait, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = 0; \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_INQUIRY(cdb, buflen) \ cdb.data[0] = SCSI_INQUIRY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_MODE_SELECT(cdb, pf, sp, buflen) \ cdb.data[0] = SCSI_MODE_SELECT; \ cdb.data[1] = MKSCSI_BIT(pf, 4) | MKSCSI_BIT(sp, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_OBJECT_POSITION(cdb, position) \ cdb.data[0] = SCSI_OBJECT_POSITION; \ cdb.data[1] = 0; \ cdb.data[2] = (((position) >> 16) & 0xff); \ cdb.data[3] = (((position) >> 8) & 0xff); \ cdb.data[4] = (((position) >> 0) & 0xff); \ cdb.data[5] = 0; \ cdb.data[6] = 0; \ cdb.data[7] = 0; \ cdb.data[8] = 0; \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_SET_WINDOW(cdb, buflen) \ cdb.data[0] = SCSI_SET_WINDOW; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_READ_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_READ_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_REQUEST_SENSE(cdb, buflen) \ cdb.data[0] = SCSI_REQUEST_SENSE; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = (buflen); \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SCAN(cdb) \ cdb.data[0] = SCSI_SCAN; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SEND_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_SEND_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_TEST_UNIT_READY(cdb) \ cdb.data[0] = SCSI_TEST_UNIT_READY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; /*--------------------------------------------------------------------------*/ static inline int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /*--------------------------------------------------------------------------*/ #define mmToIlu(mm) (((mm) * 300) / MM_PER_INCH) #define iluToMm(ilu) (((ilu) * MM_PER_INCH) / 300) /*--------------------------------------------------------------------------*/ #define GAMMA_LENGTH 0x400 /* number of value per color */ /*--------------------------------------------------------------------------*/ enum Teco_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* scanner modes */ OPT_RESOLUTION, /* X and Y resolution */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* upper left X */ OPT_TL_Y, /* upper left Y */ OPT_BR_X, /* bottom right X */ OPT_BR_Y, /* bottom right Y */ OPT_ENHANCEMENT_GROUP, OPT_CUSTOM_GAMMA, /* Use the custom gamma tables */ OPT_GAMMA_VECTOR_R, /* Custom Red gamma table */ OPT_GAMMA_VECTOR_G, /* Custom Green Gamma table */ OPT_GAMMA_VECTOR_B, /* Custom Blue Gamma table */ OPT_GAMMA_VECTOR_GRAY, /* Custom Grayscale Gamma table */ OPT_THRESHOLD, /* Threshold */ OPT_DITHER, OPT_PREVIEW, /* must come last: */ OPT_NUM_OPTIONS }; /*--------------------------------------------------------------------------*/ /* * Scanner supported by this backend. */ struct scanners_supported { int scsi_type; char scsi_teco_name[12]; /* real name of the scanner */ enum { TECO_VM3552 } tecoref; char *real_vendor; /* brand on the box */ char *real_product; /* name on the box */ SANE_Range res_range; int x_resolution_max; /* maximum X dpi */ int y_resolution_max; /* maximum Y dpi */ }; /*--------------------------------------------------------------------------*/ #define BLACK_WHITE_STR SANE_VALUE_SCAN_MODE_LINEART #define GRAY_STR SANE_VALUE_SCAN_MODE_GRAY #define COLOR_STR SANE_VALUE_SCAN_MODE_COLOR /*--------------------------------------------------------------------------*/ /* Define a scanner occurence. */ typedef struct Teco_Scanner { struct Teco_Scanner *next; SANE_Device sane; char *devicename; int sfd; /* device handle */ /* Infos from inquiry. */ char scsi_type; char scsi_vendor[9]; char scsi_product[17]; char scsi_version[5]; char scsi_teco_name[12]; /* real name of the scanner */ /* SCSI handling */ size_t buffer_size; /* size of the buffer */ SANE_Byte *buffer; /* for SCSI transfer. */ /* Scanner infos. */ const struct scanners_supported *def; /* default options for that scanner */ /* Scanning handling. */ int scanning; /* TRUE if a scan is running. */ int x_resolution; /* X resolution in DPI */ int y_resolution; /* Y resolution in DPI */ int x_tl; /* X top left */ int y_tl; /* Y top left */ int x_br; /* X bottom right */ int y_br; /* Y bottom right */ int width; /* width of the scan area in mm */ int length; /* length of the scan area in mm */ enum { TECO_BW, TECO_GRAYSCALE, TECO_COLOR } scan_mode; int depth; /* depth per color */ size_t bytes_left; /* number of bytes left to give to the backend */ size_t real_bytes_left; /* number of bytes left the scanner will return. */ size_t bytes_per_raster; /* bytes per raster. In B&W and Gray, that the same as param.bytes_per_lines. In Color, it's a third. */ SANE_Byte *image; /* keep the raw image here */ size_t image_size; /* allocated size of image */ size_t image_begin; /* first significant byte in image */ size_t image_end; /* first free byte in image */ int does_color_shift; /* in color mode only, do we need to * apply the color shifting algorithm? * It is necessary for the VM3552 * without a RAM extension. With the * RAM extension, the scanner does * it. */ int color_shift; /* for color scan: number of lines to * shift the colors. The higher the * resolution, the higher this * number. */ int raster_size; /* size of a raster */ int raster_num; /* for color scan, current raster read */ int raster_real; /* real number of raster in the * scan. This is necessary since I * don't know how to reliably compute * the number of lines */ int raster_ahead; /* max size of the incomplete lines */ int line; /* current line of the scan */ SANE_Parameters params; /* Options */ SANE_Option_Descriptor opt[OPT_NUM_OPTIONS]; Option_Value val[OPT_NUM_OPTIONS]; /* Gamma table. 1 array per colour. */ SANE_Word gamma_GRAY[GAMMA_LENGTH]; SANE_Word gamma_R[GAMMA_LENGTH]; SANE_Word gamma_G[GAMMA_LENGTH]; SANE_Word gamma_B[GAMMA_LENGTH]; } Teco_Scanner; /*--------------------------------------------------------------------------*/ /* Debug levels. * Should be common to all backends. */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /*--------------------------------------------------------------------------*/ /* 32 bits from an array to an integer (eg ntohl). */ #define B32TOI(buf) \ ((((unsigned char *)buf)[0] << 24) | \ (((unsigned char *)buf)[1] << 16) | \ (((unsigned char *)buf)[2] << 8) | \ (((unsigned char *)buf)[3] << 0)) #define B24TOI(buf) \ ((((unsigned char *)buf)[0] << 16) | \ (((unsigned char *)buf)[1] << 8) | \ (((unsigned char *)buf)[2] << 0)) #define B16TOI(buf) \ ((((unsigned char *)buf)[0] << 8) | \ (((unsigned char *)buf)[1] << 0)) sane-backends-1.0.27/backend/p5_device.c0000664000175000017500000011273712775312261014641 00000000000000/** * Description of the Primax PagePartner model */ static P5_Model pagepartner_model = { "Primax PagePartner", "Primax", "PagePartner", SANE_I18N ("sheetfed scanner"), {300, 200, 150, 100, 0}, /* 500 seems also possible */ {600, 400, 300, 200, 150, 100, 0}, 300, 600, 100, 100, 16, SANE_FIX (0.0), SANE_FIX (0.0), SANE_FIX (215.9), SANE_FIX (300.0), }; #ifdef HAVE_LINUX_PPDEV_H static char * addr_name (uint16_t addr) { switch (addr) { case DATA: return "DATA"; break; case STATUS: return "STATUS"; break; case CONTROL: return "CONTROL"; break; case EPPADR: return "EPPADR"; break; case EPPDATA: return "EPPDATA"; break; default: return "*ERROR*"; } } #endif /** @brief low level hardware access functions * @{ */ static uint8_t inb (int fd, uint16_t addr) { #ifdef HAVE_LINUX_PPDEV_H uint8_t val = 0xff; int rc, mode = 0xff; switch (addr) { case DATA: rc = ioctl (fd, PPRDATA, &val); break; case STATUS: rc = ioctl (fd, PPRSTATUS, &val); break; case CONTROL: rc = ioctl (fd, PPRCONTROL, &val); break; case EPPDATA: mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); #ifdef PPSETFLAGS mode = PP_FASTREAD; rc = ioctl (fd, PPSETFLAGS, &mode); #endif rc = read (fd, &val, 1); break; default: DBG (DBG_error, "inb(%s) escaped ppdev\n", addr_name (addr)); return 0xFF; } if (rc < 0) { DBG (DBG_error, "ppdev ioctl returned <%s>\n", strerror (errno)); } return val; #else if(fd && addr) return 0; return 0; #endif } static void outb (int fd, uint16_t addr, uint8_t value) { #ifdef HAVE_LINUX_PPDEV_H int rc = 0, mode = 0xff; switch (addr) { case DATA: rc = ioctl (fd, PPWDATA, &value); break; case CONTROL: mode = value & 0x20; rc = ioctl (fd, PPDATADIR, &mode); if (!rc) { value = value & 0xDF; rc = ioctl (fd, PPWCONTROL, &value); } break; case EPPDATA: mode = 0; /* data forward */ rc = ioctl (fd, PPDATADIR, &mode); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); rc = write (fd, &value, 1); break; case EPPADR: mode = 0; /* data forward */ rc = ioctl (fd, PPDATADIR, &mode); mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); rc = write (fd, &value, 1); break; default: DBG (DBG_error, "outb(%s,0x%02x) escaped ppdev\n", addr_name (addr), value); break; } if (rc < 0) { DBG (DBG_error, "ppdev ioctl returned <%s>\n", strerror (errno)); } #else if(fd && addr && value) return; #endif /* HAVE_LINUX_PPDEV_H */ } static void write_reg (int fd, uint8_t index, uint8_t value) { uint8_t idx; /* both nibbles hold the same value */ idx = index & 0x0F; DBG (DBG_io2, "write_reg(REG%X,0x%x)\n", idx, value); idx = idx << 4 | idx; outb (fd, EPPADR, idx); outb (fd, EPPDATA, value); } static uint8_t read_reg (int fd, uint8_t index) { uint8_t idx; /* both nibbles hold the same value */ idx = index & 0x0F; idx = idx << 4 | idx; outb (fd, EPPADR, idx); return inb (fd, EPPDATA); } #ifdef HAVE_LINUX_PPDEV_H static int read_data (int fd, uint8_t * data, int length) { int mode, rc, nb; unsigned char bval; bval = REG8; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); rc = write (fd, &bval, 1); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); #ifdef PPSETFLAGS mode = PP_FASTREAD; rc = ioctl (fd, PPSETFLAGS, &mode); #endif mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); nb = 0; while (nb < length) { rc = read (fd, data + nb, length - nb); if (rc < 0) { DBG (DBG_error, "memtest: error reading data back!\n"); return 0; } else { nb += rc; } } return 1; } static void index_write_data (int fd, uint8_t index, uint8_t * data, int length) { int mode; unsigned char bval; bval = index; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; ioctl (fd, PPSETMODE, &mode); write (fd, &bval, 1); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; ioctl (fd, PPSETMODE, &mode); mode = 0; /* data forward */ ioctl (fd, PPDATADIR, &mode); write (fd, data, length); return; } static void write_data (int fd, uint8_t * data, int length) { index_write_data (fd, REG8, data, length); } static void write_reg2 (int fd, uint8_t index, uint16_t value) { uint8_t data2[2]; data2[0] = value & 0xff; data2[1] = value >> 8; index_write_data (fd, index, data2, 2); } #else static int read_data (int fd, uint8_t * data, int length) { if(fd && data && length) return -1; return -1; } static void write_data (int fd, uint8_t * data, int length) { if(fd && data && length) return; } static void write_reg2 (int fd, uint8_t index, uint16_t value) { if(fd && index && value) return; } #endif /** * @} */ /** @brief This function checks a memory buffer. * This function writes at the given memory address then read it back * to check the scanner is correctly working. * @param fd file descriptor used to access hardware * @param addr address where to write and read * @return SANE_TRUE on succes, SANE_FALSE otherwise */ static int memtest (int fd, uint16_t addr) { uint8_t sent[256]; uint8_t back[256]; int i; write_reg2 (fd, REG1, addr); for (i = 0; i < 256; i++) { sent[i] = (uint8_t) i; back[i] = 0; } write_data (fd, sent, 256); read_data (fd, back, 256); /* check if data read back is the same that the one sent */ for (i = 0; i < 256; i++) { if (back[i] != sent[i]) { return SANE_FALSE; } } return SANE_TRUE; } #define INB(k,y,z) val=inb(k,y); if(val!=z) { DBG(DBG_error,"expected 0x%02x, got 0x%02x\n",z, val); return SANE_FALSE; } /** @brief connect to scanner * This function sends the connect sequence for the scanner. * @param fd filedescriptor of the parallel port communication channel * @return SANE_TRUE in case of success, SANE_FALSE otherwise */ static int connect (int fd) { uint8_t val; inb (fd, CONTROL); outb (fd, CONTROL, 0x04); outb (fd, DATA, 0x02); INB (fd, DATA, 0x02); outb (fd, DATA, 0x03); INB (fd, DATA, 0x03); outb (fd, DATA, 0x03); outb (fd, DATA, 0x83); outb (fd, DATA, 0x03); outb (fd, DATA, 0x83); INB (fd, DATA, 0x83); outb (fd, DATA, 0x82); INB (fd, DATA, 0x82); outb (fd, DATA, 0x02); outb (fd, DATA, 0x82); outb (fd, DATA, 0x02); outb (fd, DATA, 0x82); INB (fd, DATA, 0x82); outb (fd, DATA, 0x82); INB (fd, DATA, 0x82); outb (fd, DATA, 0x02); outb (fd, DATA, 0x82); outb (fd, DATA, 0x02); outb (fd, DATA, 0x82); INB (fd, DATA, 0x82); outb (fd, DATA, 0x83); INB (fd, DATA, 0x83); outb (fd, DATA, 0x03); outb (fd, DATA, 0x83); outb (fd, DATA, 0x03); outb (fd, DATA, 0x83); INB (fd, DATA, 0x83); outb (fd, DATA, 0x82); INB (fd, DATA, 0x82); outb (fd, DATA, 0x02); outb (fd, DATA, 0x82); outb (fd, DATA, 0x02); outb (fd, DATA, 0x82); INB (fd, DATA, 0x82); outb (fd, DATA, 0x83); INB (fd, DATA, 0x83); outb (fd, DATA, 0x03); outb (fd, DATA, 0x83); outb (fd, DATA, 0x03); outb (fd, DATA, 0x83); INB (fd, DATA, 0x83); outb (fd, DATA, 0x83); INB (fd, DATA, 0x83); outb (fd, DATA, 0x03); outb (fd, DATA, 0x83); outb (fd, DATA, 0x03); outb (fd, DATA, 0x83); INB (fd, DATA, 0x83); outb (fd, DATA, 0x82); INB (fd, DATA, 0x82); outb (fd, DATA, 0x02); outb (fd, DATA, 0x82); outb (fd, DATA, 0x02); outb (fd, DATA, 0x82); outb (fd, DATA, 0xFF); DBG (DBG_info, "connect() OK...\n"); return SANE_TRUE; } static int disconnect (int fd) { uint8_t val; outb (fd, CONTROL, 0x04); outb (fd, DATA, 0x00); INB (fd, DATA, 0x00); outb (fd, DATA, 0x01); INB (fd, DATA, 0x01); outb (fd, DATA, 0x01); outb (fd, DATA, 0x81); outb (fd, DATA, 0x01); outb (fd, DATA, 0x81); INB (fd, DATA, 0x81); outb (fd, DATA, 0x80); INB (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); INB (fd, DATA, 0x80); outb (fd, DATA, 0x80); INB (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); INB (fd, DATA, 0x80); outb (fd, DATA, 0x81); INB (fd, DATA, 0x81); outb (fd, DATA, 0x01); outb (fd, DATA, 0x81); outb (fd, DATA, 0x01); outb (fd, DATA, 0x81); INB (fd, DATA, 0x81); outb (fd, DATA, 0x80); INB (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); INB (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); INB (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); INB (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); outb (fd, DATA, 0x00); outb (fd, DATA, 0x80); inb (fd, CONTROL); outb (fd, CONTROL, 0x0C); return SANE_STATUS_GOOD; } static void setadresses (int fd, uint16_t start, uint16_t end) { write_reg (fd, REG3, start & 0xff); write_reg (fd, REG4, start >> 8); write_reg (fd, REG5, end & 0xff); write_reg (fd, REG6, end >> 8); DBG (DBG_io, "setadresses(0x%x,0x%x); OK...\n", start, end); } #ifdef HAVE_LINUX_PPDEV_H /** @brief open parallel port device * opens parallel port's low level device in EPP mode * @param devicename nam of the real device or the special value 'auto' * @return file descriptor in cas of successn -1 otherwise */ static int open_pp (const char *devicename) { int fd, mode = 0; char *name; DBG (DBG_proc, "open_pp: start, devicename=%s\n", devicename); /* TODO improve auto device finding */ if (strncmp (devicename, "auto", 4) == 0) { name = strdup("/dev/parport0"); } else { name = strdup(devicename); } /* open device */ fd = open (name, O_RDWR); if (fd < 0) { switch (errno) { case ENOENT: #ifdef ENIO case ENXIO: #endif #ifdef ENODEV case ENODEV: #endif DBG (DBG_error, "open_pp: no %s device ...\n", name); break; case EACCES: DBG (DBG_error, "open_pp: current user cannot use existing %s device ...\n", name); break; default: DBG (DBG_error, "open_pp: %s while opening %s\n", strerror (errno), name); } return -1; } free(name); /* claim device and set it to EPP */ ioctl (fd, PPCLAIM); ioctl (fd, PPGETMODES, &mode); if (mode & PARPORT_MODE_PCSPP) DBG (DBG_io, "PARPORT_MODE_PCSPP\n"); if (mode & PARPORT_MODE_TRISTATE) DBG (DBG_io, "PARPORT_MODE_TRISTATE\n"); if (mode & PARPORT_MODE_EPP) DBG (DBG_io, "PARPORT_MODE_EPP\n"); if (mode & PARPORT_MODE_ECP) DBG (DBG_io, "PARPORT_MODE_ECP\n"); if (mode & PARPORT_MODE_COMPAT) DBG (DBG_io, "PARPORT_MODE_COMPAT\n"); if (mode & PARPORT_MODE_DMA) DBG (DBG_io, "PARPORT_MODE_DMA\n"); if (mode & PARPORT_MODE_EPP) { mode = IEEE1284_MODE_EPP; } else { /* if (mode & PARPORT_MODE_ECP) { mode = IEEE1284_MODE_ECP; } else */ { mode = -1; } } if (mode == -1) { DBG (DBG_error, "open_pp: no EPP mode, giving up ...\n"); ioctl (fd, PPRELEASE); close (fd); return -1; } ioctl (fd, PPNEGOT, &mode); ioctl (fd, PPSETMODE, &mode); DBG (DBG_proc, "open_pp: exit\n"); return fd; } /** close low level device * release and close low level hardware device */ static void close_pp (int fd) { int mode = IEEE1284_MODE_COMPAT; if (fd > 2) { ioctl (fd, PPNEGOT, &mode); ioctl (fd, PPRELEASE); close (fd); } } #else /* HAVE_LINUX_PPDEV_H */ static int open_pp (const char *devicename) { if(devicename) return -1; return -1; } static void close_pp (int fd) { if(fd) return; } #endif /* HAVE_LINUX_PPDEV_H */ /** @brief test if a document is inserted * Test if a document is inserted by reading register E * @param fd file descriptor to access scanner * @return SANE_STATUS_NO_DOCS if no document or SANE_STATUS_GOOD * if something is present. */ static SANE_Status test_document (int fd) { int detector; /* check for document presence 0xC6: present, 0xC3 no document */ detector = read_reg (fd, REGE); DBG (DBG_io, "test_document: detector=0x%02X\n", detector); /* document inserted */ if (detector & 0x04) return SANE_STATUS_GOOD; return SANE_STATUS_NO_DOCS; } /** * return the amount of scanned data available * @param fd file descriptor to access scanner * @return avaible byte number */ static int available_bytes (int fd) { int counter; /* read the number of 256 bytes block of scanned data */ counter = read_reg (fd, REG9); DBG (DBG_io, "available_bytes: available_bytes=0x%02X\n", counter); return 256 * counter; } static SANE_Status build_correction (P5_Device * dev, unsigned int dpi, unsigned int mode, unsigned int start, unsigned int width) { unsigned int i, j, shift, step; DBG (DBG_proc, "build_correction: start=%d, width=%d\n", start, width); DBG (DBG_trace, "build_correction: dpi=%d, mode=%d\n", dpi, mode); /* loop on calibration data to find the matching one */ j = 0; while (dev->calibration_data[j]->dpi != dpi) { j++; if (j > MAX_RESOLUTIONS) { DBG (DBG_error, "build_correction: couldn't find calibration!\n"); return SANE_STATUS_INVAL; } } if (dev->gain != NULL) { free (dev->gain); dev->gain = NULL; } if (dev->offset != NULL) { free (dev->offset); dev->offset = NULL; } dev->gain = (float *) malloc (width * sizeof (float)); if (dev->gain == NULL) { DBG (DBG_error, "build_correction: failed to allocate memory for gain!\n"); return SANE_STATUS_NO_MEM; } dev->offset = (uint8_t *) malloc (width); if (dev->offset == NULL) { DBG (DBG_error, "build_correction: failed to allocate memory for offset!\n"); return SANE_STATUS_NO_MEM; } /* compute starting point of calibration data to use */ shift = start; step = 1; if (mode == MODE_GRAY) { /* we use green data */ shift += 1; step = 3; } for (i = 0; i < width; i += step) { if (dev->calibration_data[j]->white_data[shift + i] - dev->calibration_data[0]->black_data[shift + i] > BLACK_LEVEL) { dev->gain[i] = WHITE_TARGET / ((float) (dev->calibration_data[j]->white_data[shift + i] - dev->calibration_data[j]->black_data[shift + i])); dev->offset[i] = dev->calibration_data[j]->black_data[shift + i]; } else { dev->gain[i] = 1.0; dev->offset[i] = 0; } } return SANE_STATUS_GOOD; DBG (DBG_proc, "build_correction: end\n"); } /** @brief start up a real scan * This function starts the scan with the given parameters. * @param dev device describing hardware * @param mode color, gray level or lineart. * @param dpi desired scan resolution. * @param startx coordinate of the first pixel to scan in * scan's resolution coordinate * @param width width of the scanned area * scanner's physical scan aread. * @return SANE_STATUS_GOOD if scan is successfully started */ static SANE_Status start_scan (P5_Device * dev, int mode, unsigned int dpi, unsigned int startx, unsigned int width) { uint8_t reg0=0; uint8_t reg2=0; uint8_t regF=0; uint16_t addr=0; uint16_t start, end; unsigned int xdpi; DBG (DBG_proc, "start_scan: start \n"); DBG (DBG_io, "start_scan: startx=%d, width=%d, dpi=%d\n", startx, width, dpi); /** @brief register values * - reg2 : reg2 seems related to x dpi and provides only 100, * 150, 200 and 300 resolutions. * - regF : lower nibble gives y dpi resolution ranging from 150 * to 1200 dpi. */ xdpi = dpi; switch (dpi) { case 100: reg2 = 0x90; regF = 0xA2; break; case 150: reg2 = 0x10; regF = 0xA4; break; case 200: reg2 = 0x80; regF = 0xA6; break; case 300: reg2 = 0x00; regF = 0xA8; break; case 400: reg2 = 0x80; /* xdpi=200 */ regF = 0xAA; xdpi = 200; break; case 500: reg2 = 0x00; regF = 0xAC; xdpi = 300; break; case 600: reg2 = 0x00; regF = 0xAE; xdpi = 300; break; } switch (mode) { case MODE_COLOR: reg0 = 0x00; addr = 0x0100; break; case MODE_GRAY: /* green channel only */ reg0 = 0x20; addr = 0x0100; break; case MODE_LINEART: reg0 = 0x40; addr = 0x0908; break; } write_reg (dev->fd, REG1, 0x01); write_reg (dev->fd, REG7, 0x00); write_reg (dev->fd, REG0, reg0); write_reg (dev->fd, REG1, 0x00); write_reg (dev->fd, REGF, regF); /* the memory addr used to test need not to be related * to resolution, 0x0100 could be always used */ /* TODO get rid of it */ memtest (dev->fd, addr); /* handle case where dpi>xdpi */ start = startx; if (dpi > xdpi) { width = (width * xdpi) / dpi; start = (startx * xdpi) / dpi; } /* compute and set start addr */ if (mode == MODE_COLOR) { start = start * 3; width = width * 3; } end = start + width + 1; /* build calibration data for the scan */ if (dev->calibrated) { build_correction (dev, xdpi, mode, start, width); } setadresses (dev->fd, start, end); write_reg (dev->fd, REG1, addr >> 8); write_reg (dev->fd, REG2, reg2); regF = (regF & 0x0F) | 0x80; write_reg (dev->fd, REGF, regF); write_reg (dev->fd, REG0, reg0); if (mode == MODE_LINEART) { write_reg (dev->fd, 0x07, 0x04); } else { write_reg (dev->fd, 0x07, 0x00); } write_reg (dev->fd, REG1, addr >> 8); write_reg2 (dev->fd, REG1, addr); write_reg (dev->fd, REGF, regF | 0x01); write_reg (dev->fd, REG0, reg0 | 0x0C); if (mode == MODE_LINEART) { write_reg (dev->fd, REG1, 0x19); } else { write_reg (dev->fd, REG1, 0x11); } DBG (DBG_proc, "start_scan: exit\n"); return SANE_STATUS_GOOD; } /** read a line of scan data * @param dev device to read * @param data pointer where to store data * @param length total bytes to read on one line * @param ltr total number of lines to read * @param retry signals that the function must read as much lines it can * @param x2 tells that lines must be enlarged by a 2 factor * @param mode COLOR_MODE if color mode * @returns number of data lines read, -1 in case of error */ static int read_line (P5_Device * dev, uint8_t * data, size_t length, int ltr, SANE_Bool retry, SANE_Bool x2, int mode, SANE_Bool correction) { uint8_t counter, read, cnt; uint8_t inbuffer[MAX_SENSOR_PIXELS * 2 * 3 + 2]; unsigned int i, factor; float val; DBG (DBG_proc, "read_line: trying to read %d lines of %lu bytes\n", ltr, (unsigned long)length); counter = read_reg (dev->fd, REG9); DBG (DBG_io, "read_line: %d bytes available\n", counter * 256); read = 0; if (x2 == SANE_FALSE) { factor = 1; } else { factor = 2; } /* in retry mode we read until not enough data, but in no retry * read only one line , counter give us 256 bytes block available * and we want an number multiple of color channels */ cnt = (255 + length / factor) / 256; while ((counter > cnt && retry == 1) || (counter > cnt && read == 0)) { /* read data from scanner, first and last byte aren't picture data */ read_data (dev->fd, inbuffer, length / factor + 2); /* image correction */ if (correction == SANE_TRUE) { for (i = 0; i < length / factor; i++) { val = inbuffer[i + 1] - dev->offset[i]; if (val > 0) { val = val * dev->gain[i]; if (val < 255) inbuffer[i + 1] = val; else inbuffer[i + 1] = 255; } else { inbuffer[i + 1] = 0; } } } /* handle horizontal data doubling */ if (x2 == SANE_FALSE) { memcpy (data + read * length, inbuffer + 1, length); } else { if (mode == MODE_COLOR) { for (i = 0; i < length / factor; i += 3) { data[read * length + i * factor] = inbuffer[i + 1]; data[read * length + i * factor + 1] = inbuffer[i + 2]; data[read * length + i * factor + 2] = inbuffer[i + 3]; data[read * length + i * factor + 3] = inbuffer[i + 1]; data[read * length + i * factor + 4] = inbuffer[i + 2]; data[read * length + i * factor + 5] = inbuffer[i + 3]; } } else { for (i = 0; i < length / factor; i++) { data[read * length + i * factor] = inbuffer[i + 1]; data[read * length + i * factor + 1] = inbuffer[i + 1]; } } } read++; if (retry == SANE_TRUE) { read_reg (dev->fd, REGF); read_reg (dev->fd, REGA); read_reg (dev->fd, REG9); counter = read_reg (dev->fd, REG9); read_reg (dev->fd, REGA); if (read >= ltr) { DBG (DBG_io, "read_line returning %d lines\n", read); return read; } counter = read_reg (dev->fd, REG9); } } read_reg (dev->fd, REGF); read_reg (dev->fd, REGA); read_reg (dev->fd, REG9); counter = read_reg (dev->fd, REG9); read_reg (dev->fd, REGA); DBG (DBG_io, "read_line returning %d lines\n", read); return read; } static SANE_Status eject (int fd) { int detector; DBG (DBG_proc, "eject: start ...\n"); do { write_reg2 (fd, REG1, 0x1110); detector = read_reg (fd, REGE); detector = read_reg (fd, REGE); } while ((detector & 0x04) != 0); write_reg (fd, REG0, 0x00); write_reg (fd, REG1, 0x00); write_reg (fd, REGF, 0x82); write_reg (fd, REG7, 0x00); DBG (DBG_proc, "eject: end.\n"); return SANE_STATUS_GOOD; } /** @brief wait for document to be present in feeder * Polls document sensor until something is present. Give up after 20 seconds * @param fd file descriptor of the physical device */ /* static int wait_document (int fd, uint8_t detector) { int count = 0; uint8_t val; write_reg (fd, REG1, 0x00); write_reg (fd, REG7, 0x00); detector = read_reg (fd, REGE); while (detector == 0xc3 && count < 20) { sleep (1); count++; detector = read_reg (fd, REGE); } setadresses (fd, 0x002d, 0x09c7); write_reg (fd, REG1, 0x00); write_reg (fd, REG2, 0x90); write_reg (fd, REGF, 0x82); write_reg (fd, REG0, 0x00); val = inb (fd, STATUS) & 0xf8; if (val != 0xf8) { DBG (DBG_error, "wait_document: unexpected STATUS value 0x%02x instead of 0xf8", val); } if (count >= 20) { DBG (DBG_error, "wait_document: failed to detect document!\n"); return 0; } return 1; } */ /** @brief move at 150 dpi * move the paper at 150 dpi motor speed by the amount specified * @params dev pointer to the device structure */ static SANE_Status move (P5_Device * dev) { int skip, done, read, count; SANE_Status status = SANE_STATUS_GOOD; unsigned char buffer[256]; DBG (DBG_proc, "move: start\n"); /* compute number of lines to skip */ skip = dev->ystart; /* works, but remains to be explained ... */ if (dev->ydpi > 300) skip = skip / 2; DBG (DBG_io, "move: skipping %d lines at %d dpi\n", skip, dev->ydpi); /* we do a real scan of small width, discarding data */ done = 0; status = start_scan (dev, MODE_GRAY, dev->ydpi, 0, 256); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "move: failed to start scan\n"); return SANE_STATUS_INVAL; } do { /* test if document left the feeder */ status = test_document (dev->fd); if (status == SANE_STATUS_NO_DOCS) { DBG (DBG_info, "move: document was shorter than the required move\n"); return SANE_STATUS_INVAL; } /* test if data is available */ count = available_bytes (dev->fd); if (count) { read = read_line (dev, buffer, 256, 1, SANE_FALSE, SANE_FALSE, MODE_GRAY, SANE_FALSE); if (read == -1) { DBG (DBG_error, "move: failed to read data\n"); return SANE_STATUS_INVAL; } done += read; } } while (done < skip); /* reset scanner */ write_reg2 (dev->fd, REG1, 0x1110); count = read_reg (dev->fd, REGE); count = read_reg (dev->fd, REGE); write_reg (dev->fd, REG0, 0x00); write_reg (dev->fd, REG1, 0x00); write_reg (dev->fd, REGF, 0x82); write_reg (dev->fd, REG7, 0x00); DBG (DBG_proc, "move: exit\n"); return status; } /** clean up calibration data * @param dev device to clean up */ static void cleanup_calibration (P5_Device * dev) { int i; for (i = 0; i < MAX_RESOLUTIONS * 2; i++) { if (dev->calibration_data[i] != NULL) { free (dev->calibration_data[i]); dev->calibration_data[i] = NULL; } } dev->calibrated = SANE_FALSE; } /** detect a black scan line * parses the given buffer and retrun SANE_TRUE if the line is an * acceptable black line for calibration * @param buffer data line to parse * @param pixels number of pixels * @param mode MODE_COLOR or MODE_GRAY * @returns SANE_TRUE if it is considered as a white line */ static SANE_Bool is_black_line (uint8_t * buffer, unsigned int pixels, int mode) { unsigned int i, start, end, count, width; /* compute width in bytes */ if (mode == MODE_COLOR) { width = pixels * 3; } else { width = pixels; } /* we allow the calibration target to be narrower than full width, ie * black margin at both ends of the line */ start = (5 * width) / 100; end = (95 * width) / 100; count = 0; /* count number of black bytes */ for (i = start; i < end; i++) { if (buffer[i] > BLACK_LEVEL) { count++; } } /* we allow 3% black pixels maximum */ if (count > (3 * width) / 100) { DBG (DBG_io, "is_black_line=SANE_FALSE\n"); return SANE_FALSE; } DBG (DBG_io, "is_black_line=SANE_TRUE\n"); return SANE_TRUE; } /** detect a white scan line * parses the given buffer and retrun SANE_TRUE if the line is an * acceptable white line for calibration * @param buffer data line to parse * @param pixels number of pixels * @param mode MODE_COLOR or MODE_GRAY * @returns SANE_TRUE if it is considered as a white line */ static SANE_Bool is_white_line (uint8_t * buffer, unsigned int pixels, int mode) { unsigned int i, start, end, count, width; /* compute width in bytes */ if (mode == MODE_COLOR) { width = pixels * 3; } else { width = pixels; } /* we allow the calibration target to be narrower than full width, ie * black margin at both ends of the line */ start = (5 * width) / 100; end = (95 * width) / 100; count = 0; /* count number of black bytes */ for (i = start; i < end; i++) { if (buffer[i] < BLACK_LEVEL) { count++; } } /* we allow 3% black pixels maximum */ if (count > (3 * width) / 100) { DBG (DBG_io, "is_white_line=SANE_FALSE\n"); return SANE_FALSE; } DBG (DBG_io, "is_white_line=SANE_TRUE\n"); return SANE_TRUE; } /* ------------------------------------------------------------------------- */ /* writes gray data to a pnm file */ /* static void write_gray_data (unsigned char *image, char *name, SANE_Int width, SANE_Int height) { FILE *fdbg = NULL; fdbg = fopen (name, "wb"); if (fdbg == NULL) return; fprintf (fdbg, "P5\n%d %d\n255\n", width, height); fwrite (image, width, height, fdbg); fclose (fdbg); } */ /* ------------------------------------------------------------------------- */ /* writes rgb data to a pnm file */ static void write_rgb_data (char *name, unsigned char *image, SANE_Int width, SANE_Int height) { FILE *fdbg = NULL; fdbg = fopen (name, "wb"); if (fdbg == NULL) return; fprintf (fdbg, "P6\n%d %d\n255\n", width, height); fwrite (image, width * 3, height, fdbg); fclose (fdbg); } /** give calibration file name * computes the calibration file name to use based on the * backend name and device */ static char * calibration_file (const char *devicename) { char *ptr = NULL; char tmp_str[PATH_MAX]; ptr = getenv ("HOME"); if (ptr != NULL) { sprintf (tmp_str, "%s/.sane/p5-%s.cal", ptr, devicename); } else { ptr = getenv ("TMPDIR"); if (ptr != NULL) { sprintf (tmp_str, "%s/p5-%s.cal", ptr, devicename); } else { sprintf (tmp_str, "/tmp/p5-%s.cal", devicename); } } DBG (DBG_trace, "calibration_file: using >%s< for calibration file name\n", tmp_str); return strdup (tmp_str); } /** restore calibration data * restore calibration data by loading previously saved calibration data * @param dev device to restore * @return SANE_STATUS_GOOD on success, otherwise error code */ static SANE_Status restore_calibration (P5_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; char *fname = NULL; FILE *fcalib = NULL; size_t size; int i; DBG (DBG_proc, "restore_calibration: start\n"); cleanup_calibration (dev); fname = calibration_file (dev->model->name); fcalib = fopen (fname, "rb"); if (fcalib == NULL) { DBG (DBG_error, "restore_calibration: failed to open %s!\n", fname); free (fname); return SANE_STATUS_IO_ERROR; } /* loop filling calibration data until EOF reached */ i = 0; while (!feof (fcalib) && (i < 2 * MAX_RESOLUTIONS)) { dev->calibration_data[i] = malloc (sizeof (P5_Calibration_Data)); if (dev->calibration_data[i] == NULL) { cleanup_calibration (dev); free (fname); fclose (fcalib); DBG (DBG_error, "restore_calibration: failed to allocate memory for calibration\n"); return SANE_STATUS_NO_MEM; } size = fread (dev->calibration_data[i], 1, sizeof (P5_Calibration_Data), fcalib); if (feof (fcalib)) { free (dev->calibration_data[i]); dev->calibration_data[i] = NULL; } else if (size != sizeof (P5_Calibration_Data)) { cleanup_calibration (dev); free (fname); fclose (fcalib); DBG (DBG_error, "restore_calibration: failed to read from file\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_trace, "restore_calibration: read 1 calibration structure from file\n"); i++; } dev->calibrated = SANE_TRUE; fclose (fcalib); free (fname); DBG (DBG_proc, "restore_calibration: end\n"); return status; } /** save calibration data * save calibration data from memory to file * @param dev device calibration to save * @return SANE_STATUS_GOOD on success, otherwise error code */ static SANE_Status save_calibration (P5_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; char *fname = NULL; FILE *fcalib = NULL; int i; size_t size; DBG (DBG_proc, "save_calibration: start\n"); fname = calibration_file (dev->model->name); fcalib = fopen (fname, "wb"); if (fcalib == NULL) { DBG (DBG_error, "save_calibration: failed to open %s!\n", fname); free (fname); return SANE_STATUS_IO_ERROR; } /* loop filling calibration data until EOF reached */ i = 0; while (dev->calibration_data[i] != NULL && (i < 2 * MAX_RESOLUTIONS)) { size = fwrite (dev->calibration_data[i], sizeof (P5_Calibration_Data), 1, fcalib); if (size != sizeof (P5_Calibration_Data)) { free (fname); fclose (fcalib); DBG (DBG_error, "save_calibration: failed to write to file\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_trace, "save_calibration: wrote 1 calibration structure to file\n"); i++; } fclose (fcalib); free (fname); DBG (DBG_proc, "save_calibration: end\n"); return status; } /** calibrate scanner * calibrates scanner by scanning a white sheet to get * reference data. The black reference data is extracted from the lines * that precede the physical document. * Calibration is done at 300 color, then data is built for other modes * and resolutions. * @param dev device to calibrate */ static SANE_Status sheetfed_calibration (P5_Device * dev) { uint8_t buffer[MAX_SENSOR_PIXELS * 3]; uint16_t white_data[MAX_SENSOR_PIXELS * 3]; uint16_t black_data[MAX_SENSOR_PIXELS * 3]; unsigned int i, j, k, dpi, pixels, read, black, white; float coeff; unsigned int red, green, blue; int line; SANE_Status status; char title[40]; FILE *dbg = fopen ("debug.pnm", "wb"); fprintf (dbg, "P6\n%d %d\n255\n", MAX_SENSOR_PIXELS, CALIBRATION_SKIP_LINES * 4); DBG (DBG_proc, "sheetfed_calibration: start\n"); /* check calibration target has been loaded in ADF */ status = test_document (dev->fd); if (status == SANE_STATUS_NO_DOCS) { DBG (DBG_error, "sheetfed_calibration: no calibration target present!\n"); return SANE_STATUS_NO_DOCS; } /* clean up calibration data */ cleanup_calibration (dev); /* a RGB scan to get reference data */ /* initialize calibration slot for the resolution */ i = 0; dpi = dev->model->max_xdpi; pixels = MAX_SENSOR_PIXELS; dev->calibration_data[i] = (P5_Calibration_Data *) malloc (sizeof (P5_Calibration_Data)); if (dev->calibration_data[i] == NULL) { cleanup_calibration (dev); DBG (DBG_error, "sheetfed_calibration: failed to allocate memory for calibration\n"); return SANE_STATUS_NO_MEM; } dev->calibration_data[i]->dpi = dpi; /* start scan */ status = start_scan (dev, MODE_COLOR, dpi, 0, pixels); if (status != SANE_STATUS_GOOD) { cleanup_calibration (dev); DBG (DBG_error, "sheetfed_calibration: failed to start scan at %d dpi\n", dpi); return SANE_STATUS_INVAL; } white = 0; black = 0; read = 0; for (j = 0; j < pixels * 3; j++) { black_data[j] = 0; white_data[j] = 0; } /* read lines and gather black and white ones until enough for sensor's * native resolution */ do { status = test_document (dev->fd); if (status == SANE_STATUS_NO_DOCS && (white < 10 || black < 10)) { cleanup_calibration (dev); DBG (DBG_error, "sheetfed_calibration: calibration sheet too short!\n"); return SANE_STATUS_INVAL; } memset (buffer, 0x00, MAX_SENSOR_PIXELS * 3); line = read_line (dev, buffer, pixels * 3, 1, SANE_FALSE, SANE_FALSE, MODE_COLOR, SANE_FALSE); if (line == -1) { DBG (DBG_error, "sheetfed_calibration: failed to read data\n"); return SANE_STATUS_INVAL; } /* if a data line has been read, add it to reference data */ if (line) { read++; fwrite (buffer, pixels * 3, 1, dbg); if (is_white_line (buffer, pixels, MODE_COLOR) && white < 256) { white++; /* first calibration lines are skipped */ for (j = 0; j < pixels * 3 && read > CALIBRATION_SKIP_LINES; j++) { white_data[j] += buffer[j]; } } if (is_black_line (buffer, pixels, MODE_COLOR) && black < 256) { black++; for (j = 0; j < pixels * 3; j++) { black_data[j] += buffer[j]; } } } } while (test_document (dev->fd) != SANE_STATUS_NO_DOCS); DBG (DBG_trace, "sheetfed_calibration: white lines=%d, black lines=%d\n", white, black); /* average pixels and store in per dpi calibration data */ for (j = 0; j < pixels * 3; j++) { dev->calibration_data[i]->white_data[j] = white_data[j] / white; dev->calibration_data[i]->black_data[j] = black_data[j] / black; } /* we average red, green and blue offset on the full sensor */ red = 0; green = 0; blue = 0; for (j = 0; j < pixels * 3; j += 3) { red += dev->calibration_data[i]->black_data[j]; green += dev->calibration_data[i]->black_data[j + 1]; blue += dev->calibration_data[i]->black_data[j + 2]; } for (j = 0; j < pixels * 3; j += 3) { dev->calibration_data[i]->black_data[j] = red / pixels; dev->calibration_data[i]->black_data[j + 1] = green / pixels; dev->calibration_data[i]->black_data[j + 2] = blue / pixels; } /* trace calibration data for debug */ if (DBG_LEVEL > DBG_data) { sprintf (title, "calibration-white-%d.pnm", dev->calibration_data[i]->dpi); write_rgb_data (title, dev->calibration_data[i]->white_data, pixels, 1); sprintf (title, "calibration-black-%d.pnm", dev->calibration_data[i]->dpi); write_rgb_data (title, dev->calibration_data[i]->black_data, pixels, 1); } /* loop on all remaining resolution and compute calibration data from it */ for (i = 1; i < MAX_RESOLUTIONS && dev->model->xdpi_values[i] > 0; i++) { dev->calibration_data[i] = (P5_Calibration_Data *) malloc (sizeof (P5_Calibration_Data)); if (dev->calibration_data[i] == NULL) { cleanup_calibration (dev); DBG (DBG_error, "sheetfed_calibration: failed to allocate memory for calibration\n"); return SANE_STATUS_INVAL; } dev->calibration_data[i]->dpi = dev->model->xdpi_values[i]; coeff = ((float) dev->model->xdpi_values[i]) / (float) dpi; /* generate data by decimation */ for (j = 0; j < pixels / coeff; j++) { k = j * coeff; dev->calibration_data[i]->white_data[j] = dev->calibration_data[0]->white_data[k]; dev->calibration_data[i]->white_data[j + 1] = dev->calibration_data[0]->white_data[k + 1]; dev->calibration_data[i]->white_data[j + 2] = dev->calibration_data[0]->white_data[k + 2]; dev->calibration_data[i]->black_data[j] = dev->calibration_data[0]->black_data[k]; dev->calibration_data[i]->black_data[j + 1] = dev->calibration_data[0]->black_data[k + 1]; dev->calibration_data[i]->black_data[j + 2] = dev->calibration_data[0]->black_data[k + 2]; } } fclose (dbg); dev->calibrated = SANE_TRUE; /* eject calibration target */ eject (dev->fd); DBG (DBG_proc, "sheetfed_calibration: end\n"); return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/microtek.h0000664000175000017500000003133312112021330014563 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. microtek.h This file Copyright 2002 Matthew Marjanovic This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for Microtek scanners. (feedback to: mtek-bugs@mir.com) (for latest info: http://www.mir.com/mtek/) ***************************************************************************/ #ifndef microtek_h #define microtek_h #include /*******************************************************************/ /***** enumeration of Option Descriptors *****/ /*******************************************************************/ enum Mtek_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* -a,b,c,g */ OPT_HALFTONE_PATTERN, /* -H */ OPT_RESOLUTION, /* -r */ OPT_EXP_RES, OPT_NEGATIVE, /* -n */ OPT_SPEED, /* -v */ OPT_SOURCE, /* -t */ OPT_PREVIEW, OPT_CALIB_ONCE, OPT_GEOMETRY_GROUP, /* -f .... */ OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_EXPOSURE, OPT_BRIGHTNESS, /* -d */ OPT_CONTRAST, /* -k */ OPT_HIGHLIGHT, /* -l */ OPT_SHADOW, /* -s */ OPT_MIDTONE, /* -m */ OPT_GAMMA_GROUP, OPT_CUSTOM_GAMMA, OPT_ANALOG_GAMMA, OPT_ANALOG_GAMMA_R, OPT_ANALOG_GAMMA_G, OPT_ANALOG_GAMMA_B, /* "The gamma vectors MUST appear in the order gray, red, green, blue." */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_GAMMA_BIND, NUM_OPTIONS, OPT_BACKTRACK, /* -B */ /* must come last: */ RNUM_OPTIONS }; /*******************************************************************/ /***** scanner hardware information (as discovered by INQUIRY) *****/ /*******************************************************************/ typedef struct Microtek_Info { char vendor_id[9]; char model_name[17]; char revision_num[5]; char vendor_string[21]; SANE_Byte device_type; SANE_Byte SCSI_firmware_ver_major; SANE_Byte SCSI_firmware_ver_minor; SANE_Byte scanner_firmware_ver_major; SANE_Byte scanner_firmware_ver_minor; SANE_Byte response_data_format; #define MI_RESSTEP_1PER 0x01 #define MI_RESSTEP_5PER 0x02 SANE_Byte res_step; #define MI_MODES_LINEART 0x01 #define MI_MODES_HALFTONE 0x02 #define MI_MODES_GRAY 0x04 /* ??????? or "MultiBit"??? XXXXX*/ #define MI_MODES_COLOR 0x08 #define MI_MODES_TRANSMSV 0x20 #define MI_MODES_ONEPASS 0x40 #define MI_MODES_NEGATIVE 0x80 SANE_Byte modes; SANE_Int pattern_count; SANE_Byte pattern_dwnld; #define MI_FEED_FLATBED 0x01 #define MI_FEED_EDGEFEED 0x02 #define MI_FEED_AUTOSUPP 0x04 SANE_Byte feed_type; #define MI_COMPRSS_HUFF 0x10 #define MI_COMPRSS_RD 0x20 SANE_Byte compress_type; #define MI_UNIT_8TH_INCH 0x40 #define MI_UNIT_PIXELS 0x80 SANE_Byte unit_type; SANE_Byte doc_size_code; SANE_Int max_x; /* pixels */ SANE_Int max_y; /* pixels */ SANE_Range doc_x_range; /* mm */ SANE_Range doc_y_range; /* mm */ SANE_Int cont_settings; SANE_Int exp_settings; SANE_Byte model_code; SANE_Int base_resolution; /* dpi, guessed by backend, per model code */ #define MI_SRC_FEED_SUPP 0x01 /* support for feeder */ #define MI_SRC_FEED_BT 0x02 /* support for feed backtracking control */ #define MI_SRC_HAS_FEED 0x04 /* feeder installed */ #define MI_SRC_FEED_RDY 0x08 /* feeder ready */ #define MI_SRC_GET_FEED 0x10 /* if opaque: get from feeder */ #define MI_SRC_GET_TRANS 0x20 /* get transparency (not opaque) */ #define MI_SRC_HAS_TRANS 0x40 /* transparency adapter installed */ SANE_Byte source_options; SANE_Byte expanded_resolution; #define MI_ENH_CAP_SHADOW 0x01 /* can adjust shadow/highlight */ #define MI_ENH_CAP_MIDTONE 0x02 /* can adjust midtone */ SANE_Byte enhance_cap; SANE_Int max_lookup_size; /* max. size of gamma LUT */ SANE_Int max_gamma_bit_depth; /* max. bits of a gamma LUT element */ SANE_Int gamma_size; /* size (bytes) of each LUT element */ SANE_Byte fast_color_preview; /* allows fast color preview? */ SANE_Byte xfer_format_select; /* allows select of transfer format? */ #define MI_COLSEQ_PLANE 0x00 #define MI_COLSEQ_PIXEL 0x01 #define MI_COLSEQ_RGB 0x02 #define MI_COLSEQ_NONRGB 0x03 #define MI_COLSEQ_2PIXEL 0x11 /* Agfa StudioStar */ SANE_Byte color_sequence; /* color sequence spec. code */ SANE_Byte does_3pass; /* allows 3-pass scanning? */ SANE_Byte does_mode1; /* allows MODE1 sense/select comm's? */ #define MI_FMT_CAP_4BPP 0x01 #define MI_FMT_CAP_10BPP 0x02 #define MI_FMT_CAP_12BPP 0x04 #define MI_FMT_CAP_16BPP 0x08 SANE_Byte bit_formats; /* output bit formats capabilities */ #define MI_EXCAP_OFF_CTL 0x01 #define MI_EXCAP_DIS_LNTBL 0x02 #define MI_EXCAP_DIS_RECAL 0x04 SANE_Byte extra_cap; /* SANE_Int contrast_vals; rolled into cont_settings */ SANE_Int min_contrast; SANE_Int max_contrast; /* SANE_Int exposure_vals; rolled into exp_settings */ SANE_Int min_exposure; SANE_Int max_exposure; SANE_Byte does_expansion; /* does expanded-mode expansion internally? */ } Microtek_Info; /*******************************************************************/ /***** device structure (one for each device discovered) *****/ /*******************************************************************/ typedef struct Microtek_Device { struct Microtek_Device *next; /* next, for linked list */ SANE_Device sane; /* SANE generic device block */ Microtek_Info info; /* detailed scanner spec */ } Microtek_Device; /*******************************************************************/ /***** ring buffer structure *****/ /***** ....image workspace during scan *****/ /*******************************************************************/ typedef struct ring_buffer { size_t bpl; /* bytes per line */ size_t ppl; /* pixels per line */ uint8_t *base; /* base address of buffer */ size_t size; /* size (bytes) of ring buffer */ size_t initial_size; /* initial size of ring buffer */ size_t tail_blue; /* byte index, next blue line */ size_t tail_green; /* byte index, next green line */ size_t tail_red; /* byte index, next red line */ size_t blue_extra; /* unmatched blue bytes */ size_t green_extra; /* unmatched green bytes */ size_t red_extra; /* unmatched red bytes */ size_t complete_count; size_t head_complete; } ring_buffer; /*******************************************************************/ /***** scanner structure (one for each device in use) *****/ /***** ....all the state needed to define a scan request *****/ /*******************************************************************/ typedef struct Microtek_Scanner { struct Microtek_Scanner *next; /* for linked list */ Microtek_Device *dev; /* raw device info */ SANE_Option_Descriptor sod[RNUM_OPTIONS]; /* option list for session */ Option_Value val[RNUM_OPTIONS]; /* option values for session */ /* SANE_Int gamma_table[4][256];*/ SANE_Int *gray_lut; SANE_Int *red_lut; SANE_Int *green_lut; SANE_Int *blue_lut; SANE_Range res_range; /* range desc. for resolution */ SANE_Range exp_res_range; /* range desc. for exp. resolution */ /* scan parameters, ready to toss to SCSI commands*/ /* ...set by sane_open (i.e. general/default scanner parameters) */ #define MS_UNIT_PIXELS 0 #define MS_UNIT_18INCH 1 SANE_Byte unit_type; /* pixels or 1/8" */ #define MS_RES_1PER 0 #define MS_RES_5PER 1 SANE_Byte res_type; /* 1% or 5% */ SANE_Bool midtone_support; SANE_Int paper_length; /* whatever unit */ SANE_Bool do_clever_precal; /* calibrate scanner once, via fake scan */ SANE_Bool do_real_calib; /* calibrate via magic commands */ SANE_Bool calib_once; /* ...only calibrate magically once */ SANE_Bool allow_calibrate; SANE_Bool onepass; SANE_Bool prescan, allowbacktrack; SANE_Bool reversecolors; SANE_Bool fastprescan; SANE_Int bits_per_color; SANE_Int gamma_entries; SANE_Int gamma_entry_size; SANE_Int gamma_bit_depth; /* SANE_Int gamma_max_entry;*/ SANE_Range gamma_entry_range; SANE_Range contrast_range; SANE_Range exposure_range; /* ...set by sane_get_parameters (i.e. parameters specified by options) */ SANE_Parameters params; /* format, lastframe, lines, depth, ppl, bpl */ SANE_Int x1; /* in 'units' */ SANE_Int y1; SANE_Int x2; SANE_Int y2; #define MS_MODE_LINEART 0 #define MS_MODE_HALFTONE 1 #define MS_MODE_GRAY 2 #define MS_MODE_COLOR 3 SANE_Int mode; #define MS_FILT_CLEAR 0 #define MS_FILT_RED 1 #define MS_FILT_GREEN 2 #define MS_FILT_BLUE 3 SANE_Byte filter; SANE_Bool onepasscolor, transparency, useADF; SANE_Bool threepasscolor, expandedresolution; SANE_Int resolution; SANE_Byte resolution_code; SANE_Byte exposure, contrast; SANE_Byte pattern; SANE_Byte velocity; SANE_Byte shadow, highlight, midtone; SANE_Byte bright_r, bright_g, bright_b; /* ??? XXXXXXXX signed char */ SANE_Bool multibit; SANE_Byte color_seq; /* ...stuff needed while in mid-scan */ #define MS_LNFMT_FLAT 0 #define MS_LNFMT_SEQ_RGB 1 #define MS_LNFMT_GOOFY_RGB 2 #define MS_LNFMT_SEQ_2R2G2B 3 SANE_Int line_format; /* specify how we need to repackage scanlines */ SANE_Int pixel_bpl; /* bytes per line, pixels */ SANE_Int header_bpl; /* bytes per line, headers */ SANE_Int ppl; /* pixels per line */ SANE_Int planes; /* color planes */ SANE_Bool doexpansion; double exp_aspect; SANE_Int dest_pixel_bpl; SANE_Int dest_ppl; SANE_Int unscanned_lines; /* lines still to be read from scanner */ SANE_Int undelivered_bytes; /* bytes still to be returned to frontend */ SANE_Int max_scsi_lines; /* max number of lines that fit in SCSI buffer */ int sfd; /* SCSI device file descriptor, -1 when not opened */ int scanning; /* true == mid-pass (between sane_start & sane_read=EOF) */ int scan_started; /* true == start_scan has scanner going... */ int woe; /* Woe! */ int this_pass; /* non-zero => in midst of a multipass scan (1,2,3) */ int cancel; /* we cleverly compare mode_sense results between scans to detect if the scanner may have been reset/power-cycled in the meantime */ SANE_Byte mode_sense_cache[10]; #define MS_PRECAL_NONE 0 #define MS_PRECAL_GRAY 1 #define MS_PRECAL_COLOR 2 #define MS_PRECAL_EXP_COLOR 3 SANE_Byte precal_record; /* record what precalibrations have been done */ #define MS_SENSE_IGNORE 1 int sense_flags; /* flags passed to the sense handler */ uint8_t *scsi_buffer; ring_buffer *rb; } Microtek_Scanner; #endif /* microtek_h */ sane-backends-1.0.27/backend/pixma_common.c0000664000175000017500000007312413072310420015442 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2007-2008 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include /* pow(C90) */ #include /* gettimeofday(4.3BSD) */ #include /* usleep */ #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" #include "../include/sane/sanei_usb.h" #ifdef __GNUC__ # define UNUSED(v) (void) v #else # define UNUSED(v) #endif extern const pixma_config_t pixma_mp150_devices[]; extern const pixma_config_t pixma_mp750_devices[]; extern const pixma_config_t pixma_mp730_devices[]; extern const pixma_config_t pixma_mp810_devices[]; extern const pixma_config_t pixma_iclass_devices[]; static const pixma_config_t *const pixma_devices[] = { pixma_mp150_devices, pixma_mp750_devices, pixma_mp730_devices, pixma_mp810_devices, pixma_iclass_devices, NULL }; static pixma_t *first_pixma = NULL; static time_t tstart_sec = 0; static uint32_t tstart_usec = 0; static int debug_level = 1; #ifndef NDEBUG static void u8tohex (uint8_t x, char *str) { static const char hdigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; str[0] = hdigit[(x >> 4) & 0xf]; str[1] = hdigit[x & 0xf]; str[2] = '\0'; } static void u32tohex (uint32_t x, char *str) { u8tohex (x >> 24, str); u8tohex (x >> 16, str + 2); u8tohex (x >> 8, str + 4); u8tohex (x, str + 6); } void pixma_hexdump (int level, const void *d_, unsigned len) { const uint8_t *d = (const uint8_t *) (d_); unsigned ofs, c, plen; char line[100]; /* actually only 1+8+1+8*3+1+8*3+1 = 61 bytes needed */ if (level > debug_level) return; if (level == debug_level) /* if debuglevel == exact match and buffer contains more than 3 lines, print 2 lines + .... */ plen = (len > 64) ? 32: len; else plen = len; ofs = 0; while (ofs < plen) { char *p; line[0] = ' '; u32tohex (ofs, line + 1); line[9] = ':'; p = line + 10; for (c = 0; c != 16 && (ofs + c) < plen; c++) { u8tohex (d[ofs + c], p); p[2] = ' '; p += 3; if (c == 7) { p[0] = ' '; p++; } } p[0] = '\0'; pixma_dbg (level, "%s\n", line); ofs += c; } if (len > plen) pixma_dbg(level, "......\n"); } static void time2str (char *buf, unsigned size) { time_t sec; uint32_t usec; pixma_get_time (&sec, &usec); sec -= tstart_sec; if (usec >= tstart_usec) { usec -= tstart_usec; } else { usec = 1000000 + usec - tstart_usec; sec--; } snprintf (buf, size, "%lu.%03u", (unsigned long) sec, (unsigned) (usec / 1000)); } void pixma_dump (int level, const char *type, const void *data, int len, int size, int max) { int actual_len, print_len; char buf[20]; if (level > debug_level) return; if (debug_level >= 20) max = -1; /* dump every bytes */ time2str (buf, sizeof (buf)); pixma_dbg (level, "%s T=%s len=%d\n", type, buf, len); actual_len = (size >= 0) ? size : len; print_len = (max >= 0 && max < actual_len) ? max : actual_len; if (print_len >= 0) { pixma_hexdump (level, data, print_len); if (print_len < actual_len) pixma_dbg (level, " ...\n"); } if (len < 0) pixma_dbg (level, " ERROR: %s\n", pixma_strerror (len)); pixma_dbg (level, "\n"); } #endif /* NDEBUG */ /* NOTE: non-reentrant */ const char * pixma_strerror (int error) { static char buf[50]; /* TODO: more human friendly messages */ switch (error) { case PIXMA_EIO: return "EIO"; case PIXMA_ENODEV: return "ENODEV"; case PIXMA_EACCES: return "EACCES"; case PIXMA_ENOMEM: return "ENOMEM"; case PIXMA_EINVAL: return "EINVAL"; case PIXMA_EBUSY: return "EBUSY"; case PIXMA_ECANCELED: return "ECANCELED"; case PIXMA_ENOTSUP: return "ENOTSUP"; case PIXMA_ETIMEDOUT: return "ETIMEDOUT"; case PIXMA_EPROTO: return "EPROTO"; case PIXMA_EPAPER_JAMMED: return "EPAPER_JAMMED"; case PIXMA_ECOVER_OPEN: return "ECOVER_OPEN"; case PIXMA_ENO_PAPER: return "ENO_PAPER"; case PIXMA_EOF: return "EEOF"; } snprintf (buf, sizeof (buf), "EUNKNOWN:%d", error); return buf; } void pixma_set_debug_level (int level) { debug_level = level; } void pixma_set_be16 (uint16_t x, uint8_t * buf) { buf[0] = x >> 8; buf[1] = x; } void pixma_set_be32 (uint32_t x, uint8_t * buf) { buf[0] = x >> 24; buf[1] = x >> 16; buf[2] = x >> 8; buf[3] = x; } uint16_t pixma_get_be16 (const uint8_t * buf) { return ((uint16_t) buf[0] << 8) | buf[1]; } uint32_t pixma_get_be32 (const uint8_t * buf) { return ((uint32_t) buf[0] << 24) + ((uint32_t) buf[1] << 16) + ((uint32_t) buf[2] << 8) + buf[3]; } uint8_t pixma_sum_bytes (const void *data, unsigned len) { const uint8_t *d = (const uint8_t *) data; unsigned i, sum = 0; for (i = 0; i != len; i++) sum += d[i]; return sum; } void pixma_sleep (unsigned long usec) { usleep (usec); } void pixma_get_time (time_t * sec, uint32_t * usec) { struct timeval tv; gettimeofday (&tv, NULL); if (sec) *sec = tv.tv_sec; if (usec) *usec = tv.tv_usec; } /* convert 24/48 bit RGB to 8/16 bit ir * * Formular: g = R * drop G + B * * sptr: source color scale buffer * gptr: destination gray scale buffer * c == 3: 24 bit RGB -> 8 bit ir * c == 6: 48 bit RGB -> 16 bit ir */ uint8_t * pixma_r_to_ir (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c) { unsigned i; /* PDBG (pixma_dbg (4, "*pixma_rgb_to_ir*****\n")); */ for (i = 0; i < w; i++) { *gptr++ = *sptr++; if (c == 6) *gptr++ = *sptr++; /* 48 bit RGB: high byte */ sptr += (c == 6) ? 4 : 2; /* drop G + B */ } return gptr; } /* convert 24/48 bit RGB to 8/16 bit grayscale * * Formular: g = (R + G + B) / 3 * * sptr: source color scale buffer * gptr: destination gray scale buffer * c == 3: 24 bit RGB -> 8 bit gray * c == 6: 48 bit RGB -> 16 bit gray */ uint8_t * pixma_rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c) { unsigned i, j, g; /* PDBG (pixma_dbg (4, "*pixma_rgb_to_gray*****\n")); */ for (i = 0; i < w; i++) { for (j = 0, g = 0; j < 3; j++) { g += *sptr++; if (c == 6) g += (*sptr++ << 8); /* 48 bit RGB: high byte */ } g /= 3; /* 8 or 16 bit gray */ *gptr++ = g; if (c == 6) *gptr++ = (g >> 8); /* 16 bit gray: high byte */ } return gptr; } /** * This code was taken from the genesys backend * uses threshold and threshold_curve to control software binarization * @param sp device set up for the scan * @param dst pointer where to store result * @param src pointer to raw data * @param width width of the processed line * @param c 1 for 1-channel single-byte data, * 3 for 3-channel single-byte data, * 6 for double-byte data * */ uint8_t * pixma_binarize_line(pixma_scan_param_t * sp, uint8_t * dst, uint8_t * src, unsigned width, unsigned c) { unsigned j, x, windowX, sum = 0; unsigned threshold; unsigned offset, addCol; int dropCol, offsetX; unsigned char mask; uint8_t min, max; /* PDBG (pixma_dbg (4, "*pixma_binarize_line***** src = %u, dst = %u, width = %u, c = %u, threshold = %u, threshold_curve = %u *****\n", src, dst, width, c, sp->threshold, sp->threshold_curve)); */ /* 16 bit grayscale not supported */ if (c == 6) { PDBG (pixma_dbg (1, "*pixma_binarize_line***** Error: 16 bit grayscale not supported\n")); return dst; } /* first, color convert to grayscale */ if (c != 1) pixma_rgb_to_gray(dst, src, width, c); /* second, normalize line */ min = 255; max = 0; for (x = 0; x < width; x++) { if (src[x] > max) { max = src[x]; } if (src[x] < min) { min = src[x]; } } /* safeguard against dark or white areas */ if(min>80) min=0; if(max<80) max=255; for (x = 0; x < width; x++) { src[x] = ((src[x] - min) * 255) / (max - min); } /* third, create sliding window, prefill the sliding sum */ /* ~1mm works best, but the window needs to have odd # of pixels */ windowX = (6 * sp->xdpi) / 150; if (!(windowX % 2)) windowX++; /* to avoid conflicts with *dst start with offset */ offsetX = 1 + (windowX / 2) / 8; for (j = offsetX; j <= windowX; j++) sum += src[j]; /* PDBG (pixma_dbg (4, " *pixma_binarize_line***** windowX = %u, startX = %u, sum = %u\n", windowX, startX, sum)); */ /* fourth, walk the input buffer, output bits */ for (j = 0; j < width; j++) { /* output image location */ offset = j % 8; mask = 0x80 >> offset; threshold = sp->threshold; /* move sum/update threshold only if there is a curve */ if (sp->threshold_curve) { addCol = j + windowX / 2; dropCol = addCol - windowX; if (dropCol >= offsetX && addCol < width) { sum += src[addCol]; sum -= (sum < src[dropCol] ? sum : src[dropCol]); /* no negative sum */ } threshold = sp->lineart_lut[sum / windowX]; /* PDBG (pixma_dbg (4, " *pixma_binarize_line***** addCol = %u, dropCol = %d, sum = %u, windowX = %u, lut-element = %d, threshold = %u\n", addCol, dropCol, sum, windowX, sum/windowX, threshold)); */ } /* lookup threshold */ if (src[j] > threshold) *dst &= ~mask; /* white */ else *dst |= mask; /* black */ if (offset == 7) dst++; } /* PDBG (pixma_dbg (4, " *pixma_binarize_line***** ready: src = %u, dst = %u *****\n", src, dst)); */ return dst; } /** This code was taken from the genesys backend Function to build a lookup table (LUT), often used by scanners to implement brightness/contrast/gamma or by backends to speed binarization/thresholding offset and slope inputs are -127 to +127 slope rotates line around central input/output val, 0 makes horizontal line pos zero neg . x . . x . x . . x out . x .xxxxxxxxxxx . x . x . . x ....x....... ............ .......x.... in in in offset moves line vertically, and clamps to output range 0 keeps the line crossing the center of the table high low . xxxxxxxx . . x . out x . x . . x ............ xxxxxxxx.... in in out_min/max provide bounds on output values, useful when building thresholding lut. 0 and 255 are good defaults otherwise. * */ static SANE_Status load_lut (unsigned char * lut, int in_bits, int out_bits, int out_min, int out_max, int slope, int offset) { int i, j; double shift, rise; int max_in_val = (1 << in_bits) - 1; int max_out_val = (1 << out_bits) - 1; unsigned char * lut_p = lut; /* PDBG (pixma_dbg (4, "*load_lut***** start %d %d *****\n", slope, offset)); */ /* slope is converted to rise per unit run: * first [-127,127] to [-1,1] * then multiply by PI/2 to convert to radians * then take the tangent (T.O.A) * then multiply by the normal linear slope * because the table may not be square, i.e. 1024x256*/ rise = tan((double)slope/127 * M_PI/2) * max_out_val / max_in_val; /* line must stay vertically centered, so figure * out vertical offset at central input value */ shift = (double)max_out_val/2 - (rise*max_in_val/2); /* convert the user offset setting to scale of output * first [-127,127] to [-1,1] * then to [-max_out_val/2,max_out_val/2]*/ shift += (double)offset / 127 * max_out_val / 2; for(i=0;i<=max_in_val;i++){ j = rise*i + shift; if(jout_max){ j=out_max; } *lut_p=j; lut_p++; } /* PDBG (pixma_dbg (4, "*load_lut***** finish *****\n")); */ /* PDBG (pixma_hexdump (4, lut, max_in_val+1)); */ return SANE_STATUS_GOOD; } int pixma_map_status_errno (unsigned status) { switch (status) { case PIXMA_STATUS_OK: return 0; case PIXMA_STATUS_FAILED: return PIXMA_ECANCELED; case PIXMA_STATUS_BUSY: return PIXMA_EBUSY; default: return PIXMA_EPROTO; } } int pixma_check_result (pixma_cmdbuf_t * cb) { const uint8_t *r = cb->buf; unsigned header_len = cb->res_header_len; unsigned expected_reslen = cb->expected_reslen; int error; unsigned len; if (cb->reslen < 0) return cb->reslen; len = (unsigned) cb->reslen; if (len >= header_len) { error = pixma_map_status_errno (pixma_get_be16 (r)); if (expected_reslen != 0) { if (len == expected_reslen) { if (pixma_sum_bytes (r + header_len, len - header_len) != 0) error = PIXMA_EPROTO; } else { /* This case will happen when a command cannot be completely executed, e.g. because you press the cancel button. The device will return only a header with PIXMA_STATUS_FAILED. */ if (len != header_len) error = PIXMA_EPROTO; } } } else error = PIXMA_EPROTO; #ifndef NDEBUG if (error == PIXMA_EPROTO) { pixma_dbg (1, "WARNING: result len=%d expected %d\n", len, cb->expected_reslen); pixma_hexdump (1, r, MIN (len, 64)); } #endif return error; } int pixma_cmd_transaction (pixma_t * s, const void *cmd, unsigned cmdlen, void *data, unsigned expected_len) { int error, tmo; error = pixma_write (s->io, cmd, cmdlen); if (error != (int) cmdlen) { if (error >= 0) { /* Write timeout is too low? */ PDBG (pixma_dbg (1, "ERROR: incomplete write, %u out of %u written\n", (unsigned) error, cmdlen)); error = PIXMA_ETIMEDOUT; } return error; } /* When you send the start_session command while the scanner optic is going back to the home position after the last scan session has been cancelled, you won't get the response before it arrives home. This takes about 5 seconds. If the last session was succeeded, the scanner will immediatly answer with PIXMA_STATUS_BUSY. Is 8 seconds timeout enough? This affects ALL commands that use pixma_cmd_transaction(). Default value set in pixma_open(). */ tmo = s->rec_tmo; do { error = pixma_read (s->io, data, expected_len); if (error == PIXMA_ETIMEDOUT) { PDBG (pixma_dbg (2, "No response yet. Timed out in %d sec.\n", tmo)); #ifndef HAVE_SANEI_USB_SET_TIMEOUT /* 1s timeout Only needed, if sanei_usb_set_timeout() isn't available. pixma_read() has an internal timeout of 1 sec. */ pixma_sleep (1000000); #endif } } while (error == PIXMA_ETIMEDOUT && --tmo != 0); if (error < 0) { PDBG (pixma_dbg (1, "WARNING: Error in response phase. cmd:%02x%02x\n", ((const uint8_t *) cmd)[0], ((const uint8_t *) cmd)[1])); PDBG (pixma_dbg (1," If the scanner hangs, reset it and/or unplug the " "USB cable.\n")); } return error; /* length of the result packet or error */ } uint8_t * pixma_newcmd (pixma_cmdbuf_t * cb, unsigned cmd, unsigned dataout, unsigned datain) { unsigned cmdlen = cb->cmd_header_len + dataout; unsigned reslen = cb->res_header_len + datain; if (cmdlen > cb->size || reslen > cb->size) return NULL; memset (cb->buf, 0, cmdlen); cb->cmdlen = cmdlen; cb->expected_reslen = reslen; pixma_set_be16 (cmd, cb->buf); pixma_set_be16 (dataout + datain, cb->buf + cb->cmd_len_field_ofs); if (dataout != 0) return cb->buf + cb->cmd_header_len; else return cb->buf + cb->res_header_len; } int pixma_exec (pixma_t * s, pixma_cmdbuf_t * cb) { if (cb->cmdlen > cb->cmd_header_len) pixma_fill_checksum (cb->buf + cb->cmd_header_len, cb->buf + cb->cmdlen - 1); cb->reslen = pixma_cmd_transaction (s, cb->buf, cb->cmdlen, cb->buf, cb->expected_reslen); return pixma_check_result (cb); } int pixma_exec_short_cmd (pixma_t * s, pixma_cmdbuf_t * cb, unsigned cmd) { pixma_newcmd (cb, cmd, 0, 0); return pixma_exec (s, cb); } int pixma_check_dpi (unsigned dpi, unsigned max) { /* valid dpi = 75 * 2^n */ unsigned temp = dpi / 75; if (dpi > max || dpi < 75 || 75 * temp != dpi || (temp & (temp - 1)) != 0) return PIXMA_EINVAL; return 0; } int pixma_init (void) { PDBG (pixma_dbg (2, "pixma version %d.%d.%d\n", PIXMA_VERSION_MAJOR, PIXMA_VERSION_MINOR, PIXMA_VERSION_BUILD)); PASSERT (first_pixma == NULL); if (tstart_sec == 0) pixma_get_time (&tstart_sec, &tstart_usec); return pixma_io_init (); } void pixma_cleanup (void) { while (first_pixma) pixma_close (first_pixma); pixma_io_cleanup (); } int pixma_open (unsigned devnr, pixma_t ** handle) { int error; pixma_t *s; const pixma_config_t *cfg; *handle = NULL; cfg = pixma_get_device_config (devnr); if (!cfg) return PIXMA_EINVAL; /* invalid devnr */ PDBG (pixma_dbg (2, "pixma_open(): %s\n", cfg->name)); s = (pixma_t *) calloc (1, sizeof (s[0])); if (!s) return PIXMA_ENOMEM; s->next = first_pixma; first_pixma = s; s->cfg = cfg; s->rec_tmo = 8; /* set receive timeout to 8 seconds */ error = pixma_connect (devnr, &s->io); if (error < 0) { PDBG (pixma_dbg (2, "pixma_connect() failed %s\n", pixma_strerror (error))); goto rollback; } strncpy (s->id, pixma_get_device_id (devnr), sizeof (s->id) - 1); s->ops = s->cfg->ops; s->scanning = 0; error = s->ops->open (s); if (error < 0) goto rollback; error = pixma_deactivate (s->io); if (error < 0) goto rollback; *handle = s; return 0; rollback: PDBG (pixma_dbg (2, "pixma_open() failed %s\n", pixma_strerror (error))); pixma_close (s); return error; } void pixma_close (pixma_t * s) { pixma_t **p; if (!s) return; for (p = &first_pixma; *p && *p != s; p = &((*p)->next)) { } PASSERT (*p); if (!(*p)) return; PDBG (pixma_dbg (2, "pixma_close(): %s\n", s->cfg->name)); if (s->io) { if (s->scanning) { PDBG (pixma_dbg (3, "pixma_close(): scanning in progress, call" " finish_scan()\n")); s->ops->finish_scan (s); } s->ops->close (s); pixma_disconnect (s->io); } *p = s->next; free (s); } int pixma_scan (pixma_t * s, pixma_scan_param_t * sp) { int error; error = pixma_check_scan_param (s, sp); if (error < 0) return error; if (sp->mode == PIXMA_SCAN_MODE_LINEART) { load_lut(sp->lineart_lut, 8, 8, 50, 205, sp->threshold_curve, sp->threshold-127); } #ifndef NDEBUG pixma_dbg (3, "\n"); pixma_dbg (3, "pixma_scan(): start\n"); pixma_dbg (3, " line_size=%"PRIu64" image_size=%"PRIu64" channels=%u depth=%u\n", sp->line_size, sp->image_size, sp->channels, sp->depth); pixma_dbg (3, " dpi=%ux%u offset=(%u,%u) dimension=%ux%u\n", sp->xdpi, sp->ydpi, sp->x, sp->y, sp->w, sp->h); pixma_dbg (3, " gamma_table=%p source=%d\n", sp->gamma_table, sp->source); pixma_dbg (3, " threshold=%d threshold_curve=%d\n", sp->threshold, sp->threshold_curve); pixma_dbg (3, " adf-wait=%d\n", sp->adf_wait); pixma_dbg (3, " ADF page count: %d\n", sp->adf_pageid); #endif s->param = sp; s->cancel = 0; s->cur_image_size = 0; s->imagebuf.wptr = NULL; s->imagebuf.wend = NULL; s->imagebuf.rptr = NULL; s->imagebuf.rend = NULL; s->underrun = 0; error = s->ops->scan (s); if (error >= 0) { s->scanning = 1; } else { PDBG (pixma_dbg (3, "pixma_scan() failed %s\n", pixma_strerror (error))); } return error; } static uint8_t * fill_pixels (pixma_t * s, uint8_t * ptr, uint8_t * end, uint8_t value) { if (s->cur_image_size < s->param->image_size) { long n = s->param->image_size - s->cur_image_size; if (n > (end - ptr)) n = end - ptr; memset (ptr, value, n); s->cur_image_size += n; ptr += n; } return ptr; } int pixma_read_image (pixma_t * s, void *buf, unsigned len) { int result; pixma_imagebuf_t ib; if (!s->scanning) return 0; if (s->cancel) { result = PIXMA_ECANCELED; goto cancel; } ib = s->imagebuf; /* get rptr and rend */ ib.wptr = (uint8_t *) buf; ib.wend = ib.wptr + len; if (s->underrun) { if (s->cur_image_size < s->param->image_size) { ib.wptr = fill_pixels (s, ib.wptr, ib.wend, 0xff); } else { PDBG (pixma_dbg (3, "pixma_read_image(): completed (underrun detected)\n")); s->scanning = 0; } return ib.wptr - (uint8_t *) buf; } while (ib.wptr != ib.wend) { if (ib.rptr == ib.rend) { ib.rptr = ib.rend = NULL; result = s->ops->fill_buffer (s, &ib); if (result < 0) goto cancel; if (result == 0) { /* end of image? */ s->ops->finish_scan (s); if (s->cur_image_size != s->param->image_size) { pixma_dbg (1, "WARNING:image size mismatches\n"); pixma_dbg (1, " %"PRIu64" expected (%d lines) but %"PRIu64" received (%"PRIu64" lines)\n", s->param->image_size, s->param->h, s->cur_image_size, s->cur_image_size / s->param->line_size); if ((s->cur_image_size % s->param->line_size) != 0) { pixma_dbg (1, "BUG:received data not multiple of line_size\n"); } } if (s->cur_image_size < s->param->image_size) { s->underrun = 1; ib.wptr = fill_pixels (s, ib.wptr, ib.wend, 0xff); } else { PDBG (pixma_dbg (3, "pixma_read_image():completed\n")); s->scanning = 0; } break; } s->cur_image_size += result; PASSERT (s->cur_image_size <= s->param->image_size); } if (ib.rptr) { unsigned count = MIN (ib.rend - ib.rptr, ib.wend - ib.wptr); memcpy (ib.wptr, ib.rptr, count); ib.rptr += count; ib.wptr += count; } } s->imagebuf = ib; /* store rptr and rend */ return ib.wptr - (uint8_t *) buf; cancel: s->ops->finish_scan (s); s->scanning = 0; if (result == PIXMA_ECANCELED) { PDBG (pixma_dbg (3, "pixma_read_image(): cancelled by %sware\n", (s->cancel) ? "soft" : "hard")); } else { PDBG (pixma_dbg (3, "pixma_read_image() failed %s\n", pixma_strerror (result))); } return result; } void pixma_cancel (pixma_t * s) { s->cancel = 1; } int pixma_enable_background (pixma_t * s, int enabled) { return pixma_set_interrupt_mode (s->io, enabled); } int pixma_activate_connection(pixma_t * s) { return pixma_activate (s->io); } int pixma_deactivate_connection(pixma_t * s) { return pixma_deactivate (s->io); } uint32_t pixma_wait_event (pixma_t * s, int timeout /*ms */ ) { unsigned events; if (s->events == PIXMA_EV_NONE && s->ops->wait_event) s->ops->wait_event (s, timeout); events = s->events; s->events = PIXMA_EV_NONE; return events; } #define CLAMP2(x,w,min,max,dpi) do { \ unsigned m = (max) * (dpi) / 75; \ x = MIN(x, m - min); \ w = MIN(w, m - x); \ if (w < min) w = min; \ } while(0) int pixma_check_scan_param (pixma_t * s, pixma_scan_param_t * sp) { unsigned cfg_xdpi; if (!(sp->channels == 3 || (sp->channels == 1 && (s->cfg->cap & PIXMA_CAP_GRAY) != 0))) return PIXMA_EINVAL; /* flatbed: use s->cfg->xdpi * TPU/ADF: use s->cfg->adftpu_max_dpi, if configured with dpi value */ cfg_xdpi = ((sp->source == PIXMA_SOURCE_FLATBED || s->cfg->adftpu_max_dpi == 0) ? s->cfg->xdpi : s->cfg->adftpu_max_dpi); if (pixma_check_dpi (sp->xdpi, cfg_xdpi) < 0 || pixma_check_dpi (sp->ydpi, s->cfg->ydpi) < 0) return PIXMA_EINVAL; /* xdpi must be equal to ydpi except that xdpi = max_xdpi and ydpi = max_ydpi. */ if (!(sp->xdpi == sp->ydpi || (sp->xdpi == cfg_xdpi && sp->ydpi == s->cfg->ydpi))) return PIXMA_EINVAL; if (s->ops->check_param (s, sp) < 0) return PIXMA_EINVAL; /* FIXME: I assume the same minimum width and height for every model. * new scanners need minimum 16 px height * minimum image size: 16 px x 16 px */ CLAMP2 (sp->x, sp->w, 16, s->cfg->width, sp->xdpi); CLAMP2 (sp->y, sp->h, 16, s->cfg->height, sp->ydpi); switch (sp->source) { case PIXMA_SOURCE_FLATBED: break; case PIXMA_SOURCE_TPU: if ((s->cfg->cap & PIXMA_CAP_TPU) != PIXMA_CAP_TPU) { sp->source = PIXMA_SOURCE_FLATBED; PDBG (pixma_dbg (1, "WARNING: TPU unsupported, fallback to flatbed.\n")); } break; case PIXMA_SOURCE_ADF: if ((s->cfg->cap & PIXMA_CAP_ADF) != PIXMA_CAP_ADF) { sp->source = PIXMA_SOURCE_FLATBED; PDBG (pixma_dbg (1, "WARNING: ADF unsupported, fallback to flatbed.\n")); } break; case PIXMA_SOURCE_ADFDUP: if ((s->cfg->cap & PIXMA_CAP_ADFDUP) != PIXMA_CAP_ADFDUP) { if (s->cfg->cap & PIXMA_CAP_ADF) { sp->source = PIXMA_SOURCE_ADF; } else { sp->source = PIXMA_SOURCE_FLATBED; } PDBG (pixma_dbg (1, "WARNING: ADF duplex unsupported, fallback to %d.\n", sp->source)); } break; } if (sp->depth == 0) sp->depth = 8; if ((sp->depth % 8) != 0 && sp->depth != 1) return PIXMA_EINVAL; sp->line_size = 0; if (s->ops->check_param (s, sp) < 0) return PIXMA_EINVAL; if (sp->line_size == 0) sp->line_size = sp->depth / 8 * sp->channels * sp->w; sp->image_size = sp->line_size * sp->h; /* image_size for software lineart is counted in bits */ if (sp->software_lineart == 1) sp->image_size /= 8; return 0; } const char * pixma_get_string (pixma_t * s, pixma_string_index_t i) { switch (i) { case PIXMA_STRING_MODEL: return s->cfg->name; case PIXMA_STRING_ID: return s->id; case PIXMA_STRING_LAST: return NULL; } return NULL; } const pixma_config_t * pixma_get_config (pixma_t * s) { return s->cfg; } void pixma_fill_gamma_table (double gamma, uint8_t * table, unsigned n) { int i; double r_gamma = 1.0 / gamma; double out_scale = 255.0; double in_scale = 1.0 / (n - 1); for (i = 0; (unsigned) i != n; i++) { table[i] = (int) (out_scale * pow (i * in_scale, r_gamma) + 0.5); } } int pixma_find_scanners (const char **conf_devices) { return pixma_collect_devices (conf_devices, pixma_devices); } const char * pixma_get_device_model (unsigned devnr) { const pixma_config_t *cfg = pixma_get_device_config (devnr); return (cfg) ? cfg->name : NULL; } int pixma_get_device_status (pixma_t * s, pixma_device_status_t * status) { if (!status) return PIXMA_EINVAL; memset (status, 0, sizeof (*status)); return s->ops->get_status (s, status); } sane-backends-1.0.27/backend/genesys.h0000664000175000017500000001126612775312261014453 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2005-2013 Stephane Voltz Copyright (C) 2006 Laurent Charpentier Copyright (C) 2009 Pierre Willenbrock This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GENESYS_H #define GENESYS_H #include "genesys_low.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #if defined(_WIN32) || defined(HAVE_OS2_H) # define PATH_SEP '\\' #else # define PATH_SEP '/' #endif #define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE #define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE #define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) #define GENESYS_CONFIG_FILE "genesys.conf" /* Maximum time for lamp warm-up */ #define WARMUP_TIME 65 #define FLATBED "Flatbed" #define TRANSPARENCY_ADAPTER "Transparency Adapter" #ifndef SANE_I18N #define SANE_I18N(text) text #endif /** List of SANE options */ enum Genesys_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_SOURCE, OPT_PREVIEW, OPT_BIT_DEPTH, OPT_RESOLUTION, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ /* advanced image enhancement options */ OPT_ENHANCEMENT_GROUP, OPT_CUSTOM_GAMMA, /* toggle to enable custom gamma tables */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_SWDESKEW, OPT_SWCROP, OPT_SWDESPECK, OPT_DESPECK, OPT_SWSKIP, OPT_SWDEROTATE, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_EXTRAS_GROUP, OPT_LAMP_OFF_TIME, OPT_LAMP_OFF, OPT_THRESHOLD, OPT_THRESHOLD_CURVE, OPT_DISABLE_DYNAMIC_LINEART, OPT_DISABLE_INTERPOLATION, OPT_COLOR_FILTER, OPT_CALIBRATION_FILE, OPT_EXPIRATION_TIME, OPT_SENSOR_GROUP, OPT_SCAN_SW, OPT_FILE_SW, OPT_EMAIL_SW, OPT_COPY_SW, OPT_PAGE_LOADED_SW, OPT_OCR_SW, OPT_POWER_SW, OPT_EXTRA_SW, OPT_NEED_CALIBRATION_SW, OPT_BUTTON_GROUP, OPT_CALIBRATE, OPT_CLEAR_CALIBRATION, /* must come last: */ NUM_OPTIONS }; /** Scanner object. Should have better be called Session than Scanner */ typedef struct Genesys_Scanner { struct Genesys_Scanner *next; /**< Next scanner in list */ Genesys_Device *dev; /**< Low-level device object */ /* SANE data */ SANE_Bool scanning; /**< We are currently scanning */ SANE_Option_Descriptor opt[NUM_OPTIONS]; /**< Option descriptors */ Option_Value val[NUM_OPTIONS]; /**< Option values */ Option_Value last_val[NUM_OPTIONS]; /**< Option values as read by the frontend. used for sensors. */ SANE_Parameters params; /**< SANE Parameters */ SANE_Int bpp_list[5]; /**< */ } Genesys_Scanner; #ifdef UNIT_TESTING SANE_Status genesys_dark_white_shading_calibration (Genesys_Device * dev); char *calibration_filename(Genesys_Device *currdev); void add_device(Genesys_Device *dev); #endif #endif /* not GENESYS_H */ sane-backends-1.0.27/backend/sm3600-homerun.c0000664000175000017500000003701712112021330015351 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) Marian Eichholz 2001 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ====================================================================== Userspace scan tool for the Microtek 3600 scanner slider movement (C) Marian Eichholz 2001 ====================================================================== */ #include "sm3600-scantool.h" #include /* tuning constants for DoOriginate */ #define CCH_BONSAI 60 #define BLACK_HOLE_GRAY 30 #define BLACK_BED_LEVEL 10 /* changed by user request from 100, there are probably darker stripes */ #define CHASSIS_GRAY_LEVEL 75 typedef enum { ltHome, ltUnknown, ltBed, ltError } TLineType; #define INST_ASSERT2() { if (this->nErrorState) return ltError; } static unsigned char auchRegsSingleLine[]={ 0x00 /*0x01*/, 0x00 /*0x02*/, 0x3F /*0x03*/, 0xB4 /*!!0x04!!*/, 0x14 /*!!0x05!!*/, 0,0, 0x00 /*0x08*/, 0x3F /*!!0x09!!*/, 1,0, 0x6D /*0x0C*/, 0x70 /*0x0D*/, 0x69 /*0x0E*/, 0xD0 /*0x0F*/, 0x00 /*0x10*/, 0x00 /*0x11*/, 0x40 /*0x12*/, 0x15 /*0x13*/, 0x80 /*0x14*/, 0x2A /*0x15*/, 0xC0 /*0x16*/, 0x40 /*0x17*/, 0xC0 /*0x18*/, 0x40 /*0x19*/, 0xFF /*0x1A*/, 0x01 /*0x1B*/, 0x88 /*0x1C*/, 0x40 /*0x1D*/, 0x4C /*0x1E*/, 0x50 /*0x1F*/, 0x00 /*0x20*/, 0x0C /*0x21*/, 0x21 /*0x22*/, 0xF0 /*0x23*/, 0x40 /*0x24*/, 0x00 /*0x25*/, 0x0A /*0x26*/, 0xF0 /*0x27*/, 0x00 /*0x28*/, 0x00 /*0x29*/, 0x4E /*0x2A*/, 0xF0 /*0x2B*/, 0x00 /*0x2C*/, 0x00 /*0x2D*/, 0x4E /*0x2E*/, 0x88 /*R_CCAL*/, 0x88 /*R_CCAL2*/, 0x84 /*R_CCAL3*/, 0xEA /*R_LEN*/, 0x24 /*R_LENH*/, 0x63 /*0x34*/, 0x29 /*0x35*/, 0x00 /*0x36*/, 0x00 /*0x37*/, 0x00 /*0x38*/, 0x00 /*0x39*/, 0x00 /*0x3A*/, 0x00 /*0x3B*/, 0xFF /*0x3C*/, 0x0F /*0x3D*/, 0x00 /*0x3E*/, 0x00 /*0x3F*/, 0x01 /*0x40*/, 0x00 /*0x41*/, 0x00 /*R_CSTAT*/, 0x03 /*R_SPD*/, 0x01 /*0x44*/, 0x00 /*0x45*/, 0x59 /*!!R_CTL!!*/, 0xC0 /*0x47*/, 0x40 /*0x48*/, 0x96 /*!!0x49!!*/, 0xD8 /*0x4A*/ }; /* ====================================================================== GetLineType() Reads a scan line at the actual position and classifies it as "on the flatbed area" or "at home position" or "elsewhere". This can be used to calculate the proper stepping width ====================================================================== */ static TLineType GetLineType(TInstance *this) { unsigned char achLine[CCH_BONSAI+1]; unsigned char *puchBuffer; int cchBulk,i,iHole; int axHoles[3]; long lSum; TBool bHolesOk; int lMedian; bHolesOk=false; RegWriteArray(this,R_ALL, 74, auchRegsSingleLine); INST_ASSERT2(); /* dprintf(DEBUG_SCAN,"originate-%d...",iStripe); */ RegWrite(this,R_CTL, 1, 0x59); /* #2496[062.5] */ RegWrite(this,R_CTL, 1, 0xD9); /* #2497[062.5] */ i=WaitWhileScanning(this,5); if (i) return i; cchBulk=MAX_PIXEL_PER_SCANLINE; /* cchBulk=RegRead(this,R_STAT, 2); if (cchBulk!=MAX_PIXEL_PER_SCANLINE) return SetError(this,SANE_STATUS_INVAL, "illegal scan line width reported (%d)",cchBulk); */ puchBuffer=(unsigned char*)calloc(1,cchBulk); CHECK_POINTER(puchBuffer); if (BulkReadBuffer(this,puchBuffer, cchBulk)!=cchBulk) { free(puchBuffer); return SetError(this,SANE_STATUS_IO_ERROR,"truncated bulk"); } lSum=0; for (i=0; iBLACK_HOLE_GRAY) i++; /* not very black */ c=0; dprintf(DEBUG_ORIG,"~ i=%d",i); while (i90) /* 90% of min hole diameter */ { axHoles[iHole]=i-c/2; /* store the middle of the hole */ dprintf(DEBUG_ORIG,"~ #%d=%d",iHole,axHoles[iHole]); iHole++; i+=10; /* some hysteresis */ } } if (iHole==3) { bHolesOk=true; for (i=0; i<2; i++) { int xDistance=axHoles[i+1]-axHoles[i]; if (xDistance<1050 || xDistance>1400) bHolesOk=false; } if (axHoles[0]<350 || axHoles[0]>900) /* >2 cm tolerance */ bHolesOk=false; } else bHolesOk=false; lMedian=lSum/cchBulk; /* this is *definitly* dirty style. We should pass the information by other means... */ if (bHolesOk) { /* black reference */ this->calibration.nHoleGray=puchBuffer[axHoles[0]]; switch (this->model) { case sm3600: /* bed corner */ this->calibration.xMargin=axHoles[0]-480; this->calibration.yMargin=413; break; case sm3700: case sm3750: /* basically unknown sub-brand */ default: this->calibration.xMargin=axHoles[0]-462; this->calibration.yMargin=330; break; } /* switch */ } dprintf(DEBUG_ORIG,"~ %s - %d\n", achLine, lMedian); free(puchBuffer); i=WaitWhileBusy(this,2); if (i) return i; if (bHolesOk && lMedian>CHASSIS_GRAY_LEVEL) return ltHome; if (lMedian<=BLACK_BED_LEVEL) return ltBed; return ltUnknown; } #ifdef INSANE_VERSION /* ********************************************************************** FakeCalibration() If DoOriginate() and this Calibration code is skipped, we should at least provide for some fake measurements. Thus a test scan of the scanner's inside is possible. ********************************************************************** */ __SM3600EXPORT__ TState FakeCalibration(TInstance *this) { if (this->calibration.bCalibrated) return SANE_STATUS_GOOD; this->calibration.bCalibrated=true; if (!this->calibration.achStripeY) { this->calibration.achStripeY=calloc(1,MAX_PIXEL_PER_SCANLINE); if (!this->calibration.achStripeY) return SetError(this,SANE_STATUS_NO_MEM,"no memory for calib Y"); } memset(this->calibration.achStripeY,0xC0,MAX_PIXEL_PER_SCANLINE); /* scan *every* nonsense */ this->calibration.xMargin=this->calibration.yMargin=0; return SANE_STATUS_GOOD; } #endif /* ********************************************************************** DoCalibration() and friends ********************************************************************** */ #define SM3600_CALIB_USE_MEDIAN #define SM3600_CALIB_APPLY_HANNING_WINDOW #ifdef SM3600_CALIB_USE_MEDIAN typedef int (*TQSortProc)(const void *, const void *); static int CompareProc(const unsigned char *p1, const unsigned char *p2) { return *p1 - *p2; } #endif #define MAX_CALIB_STRIPES 8 __SM3600EXPORT__ TState DoCalibration(TInstance *this) { #ifdef SM3600_CALIB_USE_RMS long aulSum[MAX_PIXEL_PER_SCANLINE]; #endif #ifdef SM3600_CALIB_USE_MEDIAN unsigned char aauchY[MAX_CALIB_STRIPES][MAX_PIXEL_PER_SCANLINE]; unsigned char auchRow[MAX_CALIB_STRIPES]; #endif #ifdef SM3600_CALIB_APPLY_HANNING_WINDOW unsigned char auchHanning[MAX_PIXEL_PER_SCANLINE]; #endif int iLine,i; int yStart,cStripes,cyGap; TState rc; if (this->calibration.bCalibrated) return SANE_STATUS_GOOD; switch (this->model) { case sm3600: yStart=200; cStripes=MAX_CALIB_STRIPES; cyGap=10; break; case sm3700: /* in fact, the 3600 calibration should do!!! */ case sm3750: default: yStart=100; /* 54 is perimeter */ cStripes=MAX_CALIB_STRIPES; cyGap=10; break; } /* switch */ DoJog(this,yStart); /* scan a gray line at 600 DPI */ if (!this->calibration.achStripeY) { this->calibration.achStripeY=calloc(1,MAX_PIXEL_PER_SCANLINE); if (!this->calibration.achStripeY) return SetError(this,SANE_STATUS_NO_MEM,"no memory for calib Y"); } #ifdef SM3600_CALIB_USE_RMS memset(aulSum,0,sizeof(aulSum)); #endif for (iLine=0; iLinecalibration.achStripeY, #endif #ifdef SM3600_CALIB_USE_MEDIAN aauchY[iLine], #endif MAX_PIXEL_PER_SCANLINE) !=MAX_PIXEL_PER_SCANLINE) return SetError(this,SANE_STATUS_IO_ERROR,"truncated bulk"); #ifdef SM3600_CALIB_USE_RMS for (i=0; icalibration.achStripeY[i]* (long)this->calibration.achStripeY[i]; #endif DoJog(this,cyGap); } #ifdef SM3600_CALIB_USE_RMS for (i=0; icalibration.achStripeY[i]=(unsigned char)(int)sqrt(aulSum[i]/cStripes); #endif #ifdef SM3600_CALIB_USE_MEDIAN /* process the collected lines rowwise. Use intermediate buffer for qsort */ for (i=0; icalibration.achStripeY[i]=auchRow[(cStripes-1)/2]; } #endif #ifdef SM3600_CALIB_APPLY_HANNING_WINDOW memcpy(auchHanning,this->calibration.achStripeY,sizeof(auchHanning)); for (i=1; icalibration.achStripeY[i]=(unsigned char) ((2*(int)auchHanning[i]+auchHanning[i-1]+auchHanning[i+1])/4); #endif DoJog(this,-yStart-cStripes*cyGap); INST_ASSERT(); this->calibration.bCalibrated=true; return SANE_STATUS_GOOD; } /* ********************************************************************** DoOriginate() *shall* one time move the slider safely back to its origin. No idea, hoiw to achieve this, for now... ********************************************************************** */ __SM3600EXPORT__ TState DoOriginate(TInstance *this, TBool bStepOut) { TLineType lt; if (this->bVerbose) fprintf(stderr,"carriage return...\n"); DBG(DEBUG_INFO,"DoOriginate()\n"); INST_ASSERT(); lt=GetLineType(this); /* if we are already at home, fine. If not, first jump a bit forward */ DBG(DEBUG_JUNK,"lt1=%d\n",(int)lt); if (lt!=ltHome && bStepOut) DoJog(this,150); while (lt!=ltHome && !this->state.bCanceled) { lt=GetLineType(this); DBG(DEBUG_JUNK,"lt2=%d\n",(int)lt); INST_ASSERT(); switch (lt) { case ltHome: continue; case ltBed: DoJog(this,-240); break; /* worst case: 1 cm */ default: DoJog(this,-15); break; /* 0.X mm */ } } DoJog(this,1); INST_ASSERT(); /* Correction for 1 check line */ DBG(DEBUG_JUNK,"lt3=%d\n",(int)lt); if (this->state.bCanceled) return SANE_STATUS_CANCELLED; return DoCalibration(this); } /* ********************************************************************** DoJog(nDistance) The distance is given in 600 DPI. ********************************************************************** */ __SM3600EXPORT__ TState DoJog(TInstance *this, int nDistance) { int cSteps; int nSpeed,nRest; dprintf(DEBUG_SCAN,"jogging %d units...\n",nDistance); if (!nDistance) return 0; RegWrite(this,0x34, 1, 0x63); RegWrite(this,0x49, 1, 0x96); WaitWhileBusy(this,2); RegWrite(this,0x34, 1, 0x63); RegWrite(this,0x49, 1, 0x9E); /* that is a difference! */ INST_ASSERT(); cSteps=(nDistance>0) ? nDistance : -nDistance; { unsigned char uchRegs2587[]={ 0x00 /*0x01*/, 0x00 /*0x02*/, 0x3F /*0x03*/, 0x40 /*!!0x04!!*/, 0x00 /*!!0x05!!*/, 0,0, /* steps */ 0x00 /*0x08*/, 0x00 /*!!0x09!!*/, 0,0, /* y count */ 0x6D /*0x0C*/, 0x70 /*0x0D*/, 0x69 /*0x0E*/, 0xD0 /*0x0F*/, 0x00 /*0x10*/, 0x00 /*0x11*/, 0x40 /*0x12*/, 0x15 /*0x13*/, 0x80 /*0x14*/, 0x2A /*0x15*/, 0xC0 /*0x16*/, 0x40 /*0x17*/, 0xC0 /*0x18*/, 0x40 /*0x19*/, 0xFF /*0x1A*/, 0x01 /*0x1B*/, 0x88 /*0x1C*/, 0x40 /*0x1D*/, 0x4C /*0x1E*/, 0x50 /*0x1F*/, 0x00 /*0x20*/, 0x0C /*0x21*/, 0x21 /*0x22*/, 0xF0 /*0x23*/, 0x40 /*0x24*/, 0x00 /*0x25*/, 0x0A /*0x26*/, 0xF0 /*0x27*/, 0x00 /*0x28*/, 0x00 /*0x29*/, 0x4E /*0x2A*/, 0xF0 /*0x2B*/, 0x00 /*0x2C*/, 0x00 /*0x2D*/, 0x4E /*0x2E*/, 0x88 /*R_CCAL*/, 0x88 /*R_CCAL2*/, 0x84 /*R_CCAL3*/, 0xEA /*R_LEN*/, 0x24 /*R_LENH*/, 0x63 /*0x34*/, 0x29 /*0x35*/, 0x00 /*0x36*/, 0x00 /*0x37*/, 0x00 /*0x38*/, 0x00 /*0x39*/, 0x00 /*0x3A*/, 0x00 /*0x3B*/, 0xFF /*0x3C*/, 0x0F /*0x3D*/, 0x00 /*0x3E*/, 0x00 /*0x3F*/, 0x01 /*0x40*/, 0x00 /*0x41*/, 0x80 /*R_CSTAT*/, 0x03 /*R_SPD*/, 0x01 /*0x44*/, 0x00 /*0x45*/, 0x79 /*!!R_CTL!!*/, 0xC0 /*0x47*/, 0x40 /*0x48*/, 0x9E /*!!0x49!!*/, 0xD8 /*0x4A*/ }; RegWriteArray(this,R_ALL, 74, uchRegs2587); } /* #2587[065.4] */ INST_ASSERT(); RegWrite(this,R_STPS,2,cSteps); /* do some magic for slider acceleration */ if (cSteps>600) /* only large movements are accelerated */ { RegWrite(this,0x34, 1, 0xC3); RegWrite(this,0x47, 2, 0xA000); /* initial speed */ } /* start back or forth movement */ if (nDistance>0) { RegWrite(this,R_CTL, 1, 0x39); /* #2588[065.4] */ RegWrite(this,R_CTL, 1, 0x79); /* #2589[065.4] */ RegWrite(this,R_CTL, 1, 0xF9); /* #2590[065.4] */ } else { RegWrite(this,R_CTL, 1, 0x59); RegWrite(this,R_CTL, 1, 0xD9); } INST_ASSERT(); /* accelerate the slider each 100 us */ if (cSteps>600) { nRest=cSteps; for (nSpeed=0x9800; nRest>600 && nSpeed>=0x4000; nSpeed-=0x800) { nRest=RegRead(this,R_POS, 2); usleep(100); /* perhaps 40C0 is the fastest possible value */ RegWrite(this,0x47, 2, nSpeed>0x4000 ? nSpeed : 0x40C0); } } INST_ASSERT(); usleep(100); return WaitWhileBusy(this,1000); /* thanks Mattias Ellert */ } sane-backends-1.0.27/backend/canon_pp-io.h0000664000175000017500000000477112112021330015156 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2002 Matthew C. Duggan and Simon Krix This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. ----- canon_pp-io.h: $Revision$ This file is part of the canon_pp backend, supporting Canon FBX30P and NX40P scanners and also distributed as part of the stand-alone driver. Low-level scanner interface */ #ifndef CANON_PP_IO_H #define CANON_PP_IO_H /* Actual Interface */ void sanei_canon_pp_set_ieee1284_mode(int m); int sanei_canon_pp_wake_scanner(struct parport *port, int mode); int sanei_canon_pp_write(struct parport *port, int length, unsigned char *data); int sanei_canon_pp_read(struct parport *port, int length, unsigned char *data); int sanei_canon_pp_check_status(struct parport *port); int sanei_canon_pp_scanner_init(struct parport *port); #endif sane-backends-1.0.27/backend/pieusb.conf.in0000664000175000017500000000105213106201017015341 00000000000000# pieusb.conf: Configuration file for PIE/Reflecta USB scanner # Read man sane-pieusb for documentation # Format # usb # # Autodetect (built-in) # Reflecta DigitDia 6000 Multiple Slide Scanner # usb 0x05e3 0x0142 0x3a 0x01 # Reflecta CrystalScan 7200 # usb 0x05e3 0x0145 0x30 0x00 # Reflecta ProScan 7200 # usb 0x05e3 0x0145 0x36 0x00 # Reflecta ProScan 10T usb 0x05e3 0x0145 0x47 0x00 # Reflecta CrystalScan 3600 usb 0x05e3 0x0145 0x2e 0x00 # Reflecta DigitDia 4000 usb 0x05e3 0x0142 0x2f 0x00 sane-backends-1.0.27/backend/plustek-pp_p48xx.c0000664000175000017500000006115412775277260016162 00000000000000/* @file plustek-pp_p48xx.c * @brief here we have all functionality according to the ASIC96001/3 based * models. * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - fixed a bug for the return value in p48xxDoTest * - added additional debug messages * - added function p48xxCheck4800Memory * - 0.32 - added debug messages * - fixed a bug in p48xxDoTest * - disabled RD_WatchDogControl, lamp will be controlled by driver * - 0.33 - added function p48xxSetAsicRegisters() * - fixed a bug in p48xxDoTest (reset the ASIC registers) * - removed p48xxPositionLamp * - 0.34 - added some comments * - 0.35 - added some comments * - 0.36 - added function p48xxInitAllModules() to allow reinit of the modules * - switching from Full- to Halfstep at ps->PhysicalDpi now in * - p48xxSetGeneralRegister * - fixed the color-inverse problem for model OP4800 * - 0.37 - move p48xxOpenScanPath, p48xxCloseScanPath * and p48xxRegisterToScanner to io.c * - removed // comments * - added override for A3I scanner * - 0.38 - added function p48xxPutToIdleMode() * - added function p48xxCalibration * - 0.39 - added A3I stuff * - 0.40 - disabled A3I stuff * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - no changes * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** some definitions ********************************/ #define _TEST_SZ 2048 /* always use 2048 for mem size (= one bank) */ #define _START_VAL 0x12345678 /* pick a non-zero starting value for our long */ #define _BankAndSizeForTest _MemBankSize2k /* always use 2k for mem test */ /*************************** local functions *********************************/ /*............................................................................. * 1) Set asic to PROGRAM mode * 2) Select the memory bank and size * 3) Initiate data fifo */ static void p48xxSetMemoryBankForProgram( pScanData ps , Byte bBankAndSize ) { /* enter program mode */ IODataToRegister( ps, ps->RegModeControl, _ModeProgram ); /* bank and size */ IODataToRegister( ps, ps->RegMemAccessControl, bBankAndSize ); /* initiate data fifo */ IORegisterToScanner( ps, ps->RegInitDataFifo ); } /*............................................................................. * use the internal memory of a scanner to find the model */ static int p48xxDoTest( pScanData ps ) { UChar tmpByte; int retval; ULong adder, ul, cntr; pULong buffer; DBG( DBG_LOW, "p48xxDoTest()\n" ); buffer = _KALLOC( sizeof(UChar) * _TEST_SZ, GFP_KERNEL ); if( NULL == buffer ) return _E_ALLOC; retval = _E_NO_DEV; /* * do a memory test to determine how much memory this unit has, in the * process we can figure out if it's a 4830 or a 9630. NOTE: the ram * seems to be mirrored such that if you have a unit with only 32k it's * mirrored 4 times to fill the 128k (2k * (_MemBankMask + 1)) space, * so we will run a 32 bit incrementing pattern over the entire 128k and * look for the 1st page (2k) to fail */ adder = 0; for (cntr = _BankAndSizeForTest; cntr < _BankAndSizeForTest + _MemBanks; cntr++) { ps->OpenScanPath( ps ); p48xxSetMemoryBankForProgram( ps, cntr ); /* prepare content, incrementing 32 val */ for (ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++) buffer[ul] = ul + adder + _START_VAL; /* fill to buffer */ IOMoveDataToScanner( ps, (pUChar)buffer, _TEST_SZ ); /* * now check bank 0 to see if it got overwritten * bank 0, size 2k */ p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest ); ps->CloseScanPath( ps ); /* read data back */ IOReadScannerImageData( ps, (pUChar)buffer, _TEST_SZ ); /* check */ for (ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++) { if (buffer[ul] != ul + _START_VAL) { break; } } /* if fail */ if (ul != _TEST_SZ / sizeof (ULong)) { DBG( DBG_LOW, "Bank 0 overwritten\n" ); break; } /* now check current bank */ ps->OpenScanPath( ps ); p48xxSetMemoryBankForProgram( ps, cntr ); ps->CloseScanPath( ps ); /* read data back */ IOReadScannerImageData( ps, (pUChar)buffer, _TEST_SZ); /* check if fail */ for( ul = 0; ul < _TEST_SZ / sizeof(ULong); ul++ ) { if( buffer[ul] != ul + adder + _START_VAL ) break; } /* check if fail */ if (ul != _TEST_SZ / sizeof(ULong)) { DBG( DBG_LOW, "Bank not present, error at pos %u (%u)\n", ul, (ULong)(_TEST_SZ / sizeof(ULong))); break; } adder += _TEST_SZ / sizeof(ULong); } _KFREE( buffer ); DBG( DBG_LOW, "found %d bytes of memory\n", _TEST_SZ * (cntr - _BankAndSizeForTest)); if( cntr == _BankAndSizeForTest ) { DBG( DBG_LOW, "No memory ! No scanner...\n" ); return retval; } #ifdef DEBUG tmpByte = IODataRegisterFromScanner( ps, 0x18 ); DBG( DBG_LOW, "tmpByte[0x18] = 0x%02x\n",tmpByte ); #endif tmpByte = IODataRegisterFromScanner( ps, 0x0e ); DBG( DBG_LOW, "tmpByte = 0x%02x, cntr = %u, AsicId = 0x%02x\n", tmpByte, cntr, ps->sCaps.AsicID ); /* 128k */ if ((_TEST_SZ * (cntr - _BankAndSizeForTest) == 1 << 17) && (ps->sCaps.AsicID == _ASIC_IS_96003)) { /* * if 128k then must be a 9630 or above * hack, test for 12000P, The 9630 returns an 0x08 */ if ( tmpByte == 0x02 ) { /* * as we currently can't automagically detect an A3I we have to * use the override switch */ if( _OVR_PLUSTEK_A3I == ps->ModelOverride ) { DBG( DBG_LOW, "Model Override --> A3I\n" ); ModelSetA3I( ps ); } else { ModelSet12000( ps ); DBG( DBG_LOW, "It seems we have a 12000P/96000P\n" ); } } else { ModelSet9630( ps ); DBG( DBG_LOW, "It seems we have a 9630\n" ); } retval = _OK; } else { DBG( DBG_LOW, "Scanner is not a 9630 or above\n"); if ( tmpByte != 0x0f ) { DBG( DBG_LOW, "Looks like a 600!\n" ); if (( 0x08 == tmpByte ) && ((_TEST_SZ * (cntr - _BankAndSizeForTest)) == 32768 )) { DBG( DBG_LOW, "But it is a 4830P!!! " "(by mkochano@ee.pw.edu.pl)\n" ); ModelSet4830( ps ); } else { ModelSet600( ps ); } } #ifdef DEBUG else DBG( DBG_LOW, "It seems we have a 4830\n" ); #endif retval = _OK; } return retval; } /*............................................................................. * setup ASIC registers and clear all scan states (no stepping) */ static void p48xxSetAsicRegisters( pScanData ps ) { memset( &ps->AsicReg, 0, sizeof(ps->AsicReg)); memset( &ps->Asic96Reg, 0, sizeof(ps->Asic96Reg)); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->AsicReg.RD_LineControl = ps->TimePerLine; ps->AsicReg.RD_ScanControl = _SCAN_LAMP_ON; ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; ps->AsicReg.RD_Origin = 0; ps->AsicReg.RD_Pixels = 5110; /*ps->RdPix;*/ ps->Asic96Reg.RD_MotorControl = 0; ps->Asic96Reg.RD_WatchDogControl = 0; /* org. val = 0x8f; */ IOPutOnAllRegisters( ps ); } /*............................................................................. * use the internal memory of a scanner to find the model */ static int p48xxCheck4800Memory( pScanData ps ) { int retval; ULong ul; pUChar buffer; DBG( DBG_LOW, "p48xxCheck4800Memory()\n" ); buffer = _KALLOC( 2560, GFP_KERNEL ); /* 1280: Read,1280:Write */ if( NULL == buffer ) return _E_ALLOC; retval = _OK; /* bank 0, size 2k */ ps->OpenScanPath( ps ); p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest ); for (ul = 0; ul < 1280; ul++) buffer[ul] = (UChar)ul; /* prepare content */ IOMoveDataToScanner( ps, buffer, 1280 ); /* fill to buffer */ p48xxSetMemoryBankForProgram( ps, _BankAndSizeForTest ); ps->CloseScanPath( ps ); /* read data back */ IOReadScannerImageData( ps, buffer + 1280, 1280 ); for( ul = 0; ul < 1280; ul++ ) { if( buffer[ul] != buffer[ul+1280] ) { DBG( DBG_HIGH, "Error in memory test at pos %u (%u != %u)\n", ul, buffer[ul], buffer[ul+1280] ); retval = _E_NO_DEV; break; } } _KFREE(buffer); return retval; } /*............................................................................. * call all other modules, to initialize themselves */ static int p48xxInitAllModules( pScanData ps ) { int result; result = DacInitialize( ps ); if( _OK != result ) return result; result = ImageInitialize( ps ); if( _OK != result ) return result; result = IOFuncInitialize( ps ); if( _OK != result ) return result; result = IOInitialize( ps ); if( _OK != result ) return result; result = MotorInitialize( ps ); if( _OK != result ) return result; /* * in debug version, check all function pointers */ #ifdef DEBUG if( _FALSE == MiscAllPointersSet( ps )) return _E_INTERNAL; #endif return _OK; } /*............................................................................. * */ static int p48xxReadWriteTest( pScanData ps ) { int retval; DBG( DBG_LOW, "p48xxReadWriteTest()\n" ); /* * determine the model by the ASIC type (except for 4830/9630) * might want to make a SetModelCommon() someday for this... */ ps->RedDataReady = 0x01; /* normal for Red and Green */ ps->GreenDataReady = 0x02; ps->AsicRedColor = 0x01; ps->AsicGreenColor = 0x03; /* * if not already set, try to find ASIC type (96001 or 96003) */ if ( _NO_BASE == ps->sCaps.wIOBase ) { /* get copy of asic id */ ps->sCaps.AsicID = IODataRegisterFromScanner( ps, ps->RegAsicID ); if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) { /* actually either a 4830, 9630, 12000, find out later */ DBG( DBG_LOW, "Found a 96003 ASIC at Reg 0x%x\n", ps->RegAsicID ); ModelSet4830( ps ); } else { if ( _ASIC_IS_96001 == ps->sCaps.AsicID ) { DBG( DBG_LOW, "Found a 96001 ASIC at Reg 0x%x\n", ps->RegAsicID ); ModelSet4800( ps ); } else { DBG( DBG_LOW, "Can't find your model, asic = 0x%x\n", ps->sCaps.AsicID ); return _E_NO_ASIC; } } } /* * set the registers according to the assumptions above */ p48xxSetAsicRegisters( ps ); if ( _ASIC_IS_96003 == ps->sCaps.AsicID ) { retval = p48xxDoTest( ps ); /* * as we may now have detected another model, we have to set * the registers to their new values... * and maybe the modules have to be reset as well */ if( _OK == retval ) { p48xxSetAsicRegisters( ps ); retval = p48xxInitAllModules( ps ); } return retval; } /* * this part will be reached only for the 4800 - ASIC 96001 * we check only the memory as the original driver does */ return p48xxCheck4800Memory( ps ); } /*............................................................................. * 1) Setup the registers of asic. * 2) Determine which type of CCD we are using * 3) According to the CCD, prepare the CCD dependent veriables * SONY CCD: * The color exposure sequence: Red, Green (after 11 red lines), * Blue (after 8 green lines) * TOSHIBA CCD: * The color exposure sequence: Red, Blue (after 11 red lines), * Green (after 8 blue lines) */ static void p48xxSetupScannerVariables( pScanData ps ) { UChar tmp; TimerDef timer; DBG( DBG_LOW, "p48xxSetupScannerVariables()\n" ); ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegModelControl2, _Model2ChannelMult ); if( 2 == IODataFromRegister( ps, ps->RegWriteIOBusDecode1 )) { DBG( DBG_LOW, "Scanner has 97003 ASIC too.\n" ); ps->f97003 = _TRUE; ps->b97003DarkR = 8; ps->b97003DarkG = 8; ps->b97003DarkB = 8; ps->Asic96Reg.u26.RD_ModelControl2 = _Model2ChannelMult; } else { DBG( DBG_LOW, "No ASIC 97003 found.\n" ); ps->f97003 = _FALSE; ps->Asic96Reg.u26.RD_ModelControl2 = _Model2DirectOutPort; } IODataToRegister( ps, ps->RegModelControl2, ps->Asic96Reg.u26.RD_ModelControl2 ); tmp = IODataFromRegister( ps, ps->RegStatus ); DBG( DBG_LOW, "Status-Register = 0x%02X\n", tmp ); #ifdef DEBUG if( tmp & _FLAG_P96_MOTORTYPE ) { DBG( DBG_LOW, "Scanner has Full/Half Stepping drive\n" ); } else { DBG( DBG_LOW, "Scanner has Micro Stepping drive\n" ); } #endif if( tmp & _FLAG_P96_CCDTYPE) { ps->fSonyCCD = _FALSE; DBG( DBG_LOW, "CCD is NEC/TOSHIBA Type\n" ); } else { ps->fSonyCCD = _TRUE; DBG( DBG_LOW, "CCD is SONY Type\n" ); } ps->CloseScanPath( ps ); ps->b1stColorByte = ps->AsicRedColor; ps->b1stColor = ps->RedDataReady; if (ps->fSonyCCD) { ps->b2ndColorByte = ps->AsicGreenColor; ps->b2ndColor = ps->GreenDataReady; ps->b3rdColorByte = _ASIC_BLUECOLOR; ps->b3rdColor = _BLUE_DATA_READY; } else { /* NEC/Toshiba CCD */ ps->b2ndColorByte = _ASIC_BLUECOLOR; ps->b2ndColor = _BLUE_DATA_READY; ps->b3rdColorByte = ps->AsicGreenColor; ps->b3rdColor = ps->GreenDataReady; } ps->b1stMask = (Byte)~ps->b1stColor; ps->b2ndMask = (Byte)~ps->b2ndColor; ps->b3rdMask = (Byte)~ps->b3rdColor; ps->b1stLinesOffset = 17; ps->b2ndLinesOffset = 9; /* * calculate I/O Timer * if we cannot read 200 lines within 1 second, the I/O time has to add 2 * CalculateIOTime () */ if( _PORT_SPP != ps->IO.portMode ) { UShort wLines = 200; pUChar pBuf; pBuf = _KALLOC((_BUF_SIZE_BASE_CONST * 2), GFP_KERNEL ); if ( NULL != pBuf ) { MiscStartTimer( &timer, _SECOND ); do { IOReadScannerImageData( ps, pBuf, (_BUF_SIZE_BASE_CONST * 2)); wLines--; } while (!MiscCheckTimer( &timer) && wLines); if( !wLines ) ps->bExtraAdd = 0; else ps->bExtraAdd = 2; _KFREE( pBuf ); } else { ps->bExtraAdd = 2; /* poor resource */ } } else { ps->bExtraAdd = 0; } } /*............................................................................. * */ static void p48xxSetGeneralRegister( pScanData ps ) { if( MODEL_OP_A3I == ps->sCaps.Model ) { ps->AsicReg.RD_ModelControl = _ModelDpi400 | _ModelWhiteIs0 | _ModelMemSize128k4; } ps->AsicReg.RD_ModeControl = _ModeScan; /* WORK: ps->PhysicalDpi should be correct, but the we have to work * on motor.c again to use other running-tables * if ( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) { */ if ( ps->DataInf.xyAppDpi.y <= 300 ) { /* HEINER:A3I if ( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) { */ ps->Asic96Reg.RD_MotorControl = (ps->FullStep | ps->IgnorePF | ps->MotorOn | _MotorDirForward); } else { ps->Asic96Reg.RD_MotorControl = (ps->IgnorePF | ps->MotorOn | _MotorDirForward); } if ( ps->DataInf.wPhyDataType == COLOR_BW ) { ps->AsicReg.RD_ScanControl = ps->bLampOn; if (!(ps->DataInf.dwScanFlag & SCANDEF_Inverse)) ps->AsicReg.RD_ScanControl |= _P96_SCANDATA_INVERT; } else { ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; if (ps->DataInf.dwScanFlag & SCANDEF_Inverse) ps->AsicReg.RD_ScanControl |= _P96_SCANDATA_INVERT; } if (ps->DataInf.xyPhyDpi.x <= 200) ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE; DBG( DBG_LOW, "RD_ModeControl = 0x%02x\n", ps->AsicReg.RD_ModeControl ); DBG( DBG_LOW, "RD_MotorControl = 0x%02x\n", ps->Asic96Reg.RD_MotorControl ); DBG( DBG_LOW, "RD_ScanControl = 0x%02x\n", ps->AsicReg.RD_ScanControl ); } /*............................................................................. * */ static void p48xxSetupScanningCondition( pScanData ps ) { DBG( DBG_LOW, "p48xxSetupScanningCondition()\n" ); IORegisterDirectToScanner( ps, ps->RegInitDataFifo ); /* Cal64kTime (); */ if( MODEL_OP_A3I == ps->sCaps.Model ) ps->wLinesPer64kTime = (UShort)(65555UL / ps->DataInf.dwAsicBytesPerPlane * 5UL); else ps->wLinesPer64kTime = (UShort)(65555UL / ps->DataInf.dwAsicBytesPerPlane * 10UL / 3UL); DBG( DBG_LOW, "wLinesPer64kTime = %u\n", ps->wLinesPer64kTime ); ps->InitialSetCurrentSpeed( ps ); DBG( DBG_LOW, "Current Speed = %u\n", ps->bCurrentSpeed ); ps->bMinReadFifo = (Byte)((ps->DataInf.dwAsicBytesPerPlane + 511) / 512); DBG( DBG_LOW, "MinReadFifo = %u\n", ps->bMinReadFifo ); p48xxSetGeneralRegister( ps ); /* * if speed is not the fastest and DPI is less than 400, do half steps */ if( ps->DataInf.wPhyDataType >= COLOR_256GRAY && !(ps->bCurrentSpeed & 1) && (ps->DataInf.xyAppDpi.y <= 300)) { /* HEINER:A3I if( !(ps->bCurrentSpeed & 1) && (ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi)) { */ ps->fHalfStepTableFlag = _TRUE; ps->Asic96Reg.RD_MotorControl &= ps->StepMask; } ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x; DBG( DBG_LOW, "RD_Dpi = %u\n", ps->AsicReg.RD_Dpi ); /* SetStartStopRegister (ps) */ ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + ps->Device.DataOriginX + ps->DataInf.crImage.x); if (ps->DataInf.wPhyDataType < COLOR_256GRAY) { ps->AsicReg.RD_Pixels = (UShort)(ps->DataInf.dwAsicPixelsPerPlane + 7) & 0xfff8; } else { ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicPixelsPerPlane; } DBG( DBG_LOW, "RD_Pixels = %u\n", ps->AsicReg.RD_Pixels ); /* SetupMotorStart () */ IORegisterDirectToScanner( ps, ps->RegInitDataFifo); ps->SetupMotorRunTable( ps ); IOSetToMotorRegister( ps ); ps->pCurrentColorRunTable = ps->pColorRunTable; ps->bCurrentLineCount = 0; IOPutOnAllRegisters( ps ); ps->OpenScanPath( ps ); /* * when using the full-step speed on 600 dpi models, then set * the motor into half-step mode, to avoid that the scanner hits * the back of its cover */ if((600 == ps->PhysicalDpi) && (1 == ps->bCurrentSpeed)) { ps->Asic96Reg.RD_MotorControl &= ~ps->FullStep; } IODataToRegister( ps, ps->RegMotorControl, (Byte)(ps->Asic96Reg.RD_MotorControl & ~ps->MotorOn)); IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl); IORegisterToScanner( ps, ps->RegInitDataFifo ); ps->CloseScanPath( ps ); } /*............................................................................. * switch the motor off and put the scanner into idle mode */ static void p48xxPutToIdleMode( pScanData ps ) { DBG( DBG_LOW, "Putting Scanner (ASIC 96001/3) into Idle-Mode\n" ); /* * turn off motor */ ps->Asic96Reg.RD_MotorControl = 0; IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); } /*............................................................................. * for P96001/3 ASIC * do all the preliminary stuff here (calibrate the scanner and move the * sensor to it´s start position, also setup the driver for the * current run) */ static int p48xxCalibration( pScanData ps ) { DBG( DBG_LOW, "p48xxCalibration()\n" ); ps->Scan.bFifoSelect = ps->RegGFifoOffset; while (_TRUE) { _ASSERT(ps->WaitForShading); if (ps->WaitForShading( ps )) { if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) { /* HEINER:A3I disable !! */ MotorP96AheadToDarkArea( ps ); if( ps->Scan.fRefreshState ) { ps->Scan.fRefreshState = _FALSE; if (!ps->fReshaded) { ps->fReshaded = _TRUE; if (ps->fColorMoreRedFlag || ps->fColorMoreBlueFlag) { continue; } } } } break; } else { ps->fScanningStatus = _FALSE; ps->DataInf.dwAppLinesPerArea = 0; return _E_TIMEOUT; } } if((ps->sCaps.AsicID != _ASIC_IS_96001) && (ps->DataInf.wPhyDataType != COLOR_BW)) { DacP96WriteBackToGammaShadingRAM(ps); } if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { ps->bExtraMotorCtrl = 0; ps->Scan.fMotorBackward = _TRUE; MotorP96ConstantMoveProc( ps, 4000 ); } /* * move sensor and setup scanner for grabbing the picture */ _ASSERT(ps->WaitForPositionY); ps->WaitForPositionY(ps); return _OK; } /************************ exported functions *********************************/ /*............................................................................. * initialize the register values and function calls for the 96001/3 asic */ _LOC int P48xxInitAsic( pScanData ps ) { DBG( DBG_LOW, "P48xxInitAsic()\n" ); ps->IO.bOpenCount = 0; ps->RegSwitchBus = 0; ps->RegReadDataMode = 1; ps->RegWriteDataMode = 2; ps->RegEPPEnable = 3; ps->RegInitDataFifo = 4; ps->RegForceStep = 5; ps->RegInitScanState = 6; ps->RegRefreshScanState = 7; ps->RegStatus = 0x10; ps->RegFifoOffset = 0x11; ps->RegGetScanState = 0x12; ps->RegAsicID = 0x13; /* Determine the asic */ ps->RegReadIOBufBus = 0x17; ps->RegModeControl = 0x18; ps->RegLineControl = 0x19; ps->RegScanControl = 0x1a; ps->RegMotorControl = 0x1b; ps->RegModelControl = 0x1c; ps->RegMemAccessControl = 0x1d; ps->RegDpiLow = 0x1e; ps->RegDpiHigh = 0x1f; ps->RegScanPosLow = 0x20; ps->RegScanPosHigh = 0x21; ps->RegWidthPixelsLow = 0x22; ps->RegWidthPixelsHigh = 0x23; ps->RegThresholdControl = 0x24; ps->RegWatchDogControl = 0x25; ps->RegModelControl2 = 0x26; ps->RegThresholdGapControl = 0x27; ps->RegRedChShadingOffset = 0x28; ps->RegGreenChShadingOffset = 0x29; ps->RegRedDCAdjust = 0x27; /* not sure why these are dup's */ ps->RegGreenDCAdjust = 0x28; ps->RegBlueDCAdjust = 0x29; ps->RegBlueChShadingOffset = 0x2a; ps->RegRedChDarkOffset = 0x2b; ps->RegGreenChDarkOffset = 0x2c; ps->RegBlueChDarkOffset = 0x2d; ps->RegWriteIOBusDecode1 = 0x2e; ps->RegWriteIOBusDecode2 = 0x2f; ps->RegScanStateControl = 0x30; ps->RegRedChEvenOffset = 0x31; ps->RegGreenChEvenOffset = 0x32; ps->RegBlueChEvenOffset = 0x33; ps->RegRedChOddOffset = 0x34; ps->RegGreenChOddOffset = 0x35; ps->RegBlueChOddOffset = 0x36; ps->RegRedGainOutDirect = 0x37; ps->RegGreenGainOutDirect = 0x38; ps->RegBlueGainOutDirect = 0x39; ps->RegLedControl = 0x3a; ps->RegShadingCorrectCtrl = 0x3b; ps->RegScanStateBegin = 0x40; /* (0, 1) */ ps->RegScanStateEnd = 0x5f; /* (62, 63) */ /* * setup function calls */ ps->ReadWriteTest = p48xxReadWriteTest; ps->SetupScannerVariables = p48xxSetupScannerVariables; ps->SetupScanningCondition = p48xxSetupScanningCondition; ps->PutToIdleMode = p48xxPutToIdleMode; ps->Calibration = p48xxCalibration; /* * setup misc */ ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF; ps->CtrlReadLowNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE; ps->MotorFreeRun = 0x80; ps->bLampOn = _SCAN_LAMP_ON; ps->f97003 = _FALSE; /* * initialize the other modules */ return p48xxInitAllModules( ps ); } /* END PLUSTEK-PP_P48xx.C ...................................................*/ sane-backends-1.0.27/backend/sm3840_lib.h0000664000175000017500000001246112775312261014560 00000000000000/* sane - Scanner Access Now Easy. ScanMaker 3840 Backend Copyright (C) 2005-7 Earle F. Philhower, III earle@ziplabel.com - http://www.ziplabel.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include #include #ifndef BACKENDNAME #include #include #ifndef DEFINED_USB_HANDLE #define DEFINED_USB_HANDLE typedef usb_dev_handle *p_usb_dev_handle; #endif static p_usb_dev_handle find_device (unsigned int idVendor, unsigned int idProduct); #else #include "../include/sane/sanei_usb.h" #ifndef USBWRAPPER #define USBWRAPPER typedef SANE_Int p_usb_dev_handle; #define usb_control_msg my_usb_control_msg #define usb_bulk_read my_usb_bulk_read #define usb_bulk_write my_usb_bulk_write static int my_usb_bulk_write (p_usb_dev_handle dev, int ep, unsigned char *bytes, int size, int timeout); static int my_usb_bulk_read (p_usb_dev_handle dev, int ep, unsigned char *bytes, int size, int timeout); static int my_usb_control_msg (p_usb_dev_handle dev, int requesttype, int request, int value, int index, unsigned char *bytes, int size, int timeout); #endif /* USBWRAPPER */ #endif #include "sm3840_params.h" static void idle_ab (p_usb_dev_handle udev); static void write_regs (p_usb_dev_handle udev, int regs, unsigned char reg1, unsigned char val1, ... /*unsigned char reg, unsigned char val, ... */ ); static int write_vctl (p_usb_dev_handle udev, int request, int value, int index, unsigned char byte); static int read_vctl (p_usb_dev_handle udev, int request, int value, int index, unsigned char *byte); #ifndef BACKENDNAME static void record (p_usb_dev_handle udev, char *fname, int bytes); static void record_image (p_usb_dev_handle udev, char *fname, int dpi, int scanpix, int scanlines, int gray, char *head, int bpp16); static void check_buttons (p_usb_dev_handle udev, int *scan, int *print, int *mail); static void record_head (p_usb_dev_handle udev, char *fname, int bytes, char *header); #endif static void poll1 (p_usb_dev_handle udev); static void poll2 (p_usb_dev_handle udev); static void reset_scanner (p_usb_dev_handle udev); static void set_lightmap_white (unsigned short *map, int dpi, int color); static void calc_lightmap (unsigned short *buff, unsigned short *storage, int index, int dpi, double gain, int offset); static void select_pixels (unsigned short *map, int dpi, int start, int end); static void record_mem (p_usb_dev_handle udev, unsigned char **dest, int bytes); static void set_lamp_timer (p_usb_dev_handle udev, int timeout_in_mins); static void set_gain_black (p_usb_dev_handle udev, int r_gain, int g_gain, int b_gain, int r_black, int g_black, int b_black); static void idle_ab (p_usb_dev_handle udev); static void write_regs (p_usb_dev_handle udev, int regs, unsigned char reg1, unsigned char val1, ... /*unsigned char reg, unsigned char val, ... */ ); static int write_vctl (p_usb_dev_handle udev, int request, int value, int index, unsigned char byte); static int read_vctl (p_usb_dev_handle udev, int request, int value, int index, unsigned char *byte); static void download_lut8 (p_usb_dev_handle udev, int dpi, int incolor); static void record_line (int reset, p_usb_dev_handle udev, unsigned char *storeline, int dpi, int scanpix, int gray, int bpp16, int *save_i, unsigned char **save_scan_line, unsigned char **save_dpi1200_remap, unsigned char **save_color_remap); static void prepare_params (SM3840_Params * params); static void fix_endian_short (unsigned short *data, int count); #define rd_timeout 10000 #define wr_timeout 10000 sane-backends-1.0.27/backend/avision.c0000664000175000017500000100156013063340150014423 00000000000000/******************************************************************************* * SANE - Scanner Access Now Easy. avision.c This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. ***************************************************************************** This file implements a SANE backend for the Avision SCSI Scanners (like the AV 630 / 620 (CS) ...) and some Avision (OEM) USB scanners (like the HP 53xx, 74xx, Minolta FS-V1 ...) or Fujitsu ScanPartner with the AVISION SCSI-2/3 or USB command set and written by René Rebe and Meino Cramer. Copyright 2002 - 2015 by "Ren Rebe" Copyright 1999, 2000, 2001 by "René Rebe" "Meino Christian Cramer" Copyright 2002 by "Jose Paulo Moitinho de Almeida" Copyright 2010, 2011 by "Mike Kelly" Additional Contributers: "Gunter Wagner" (some fixes and the transparency option) "Martin Jelínek" nice attach debug output "Marcin Siennicki" found some typos and contributed fixes for the HP 7400 "Frank Zago" Mitsubishi IDs and report Avision INC example code to handle calibration and C5 ASIC specifics "Franz Bakan" OS/2 threading support "Falk Rohsiepe" Spelling and whitespace as well as HP5370 quirks Many additional special thanks to: Avision INC for providing protocol documentation. Avision INC for sponsoring an AV 8000S with ADF. Avision Europe and BHS Binkert for sponsoring several more scanners. Archivista GmbH, Switzerland, for sponsoring several features Roberto Di Cosmo who sponsored a HP 5370 scanner. Oliver Neukum who sponsored a HP 5300 USB scanner. Matthias Wiedemann for lending his HP 7450C for some weeks. Compusoft, C.A. Caracas / Venezuela for sponsoring a HP 7450 scanner and so enhanced ADF support. Chris Komatsu for the nice ADF scanning observation. All the many other beta-tester and debug-log sender! Thanks to all the people and companies above. Without you the Avision backend would not be in the shape it is today! ;-) ********************************************************************************/ /* SANE-FLOW-DIAGRAMM (from umax.c) * * - sane_init() : initialize backend, attach scanners(devicename,0) * . - sane_get_devices() : query list of scanner-devices * . - sane_open() : open a particular scanner-device and attach_scanner(devicename,&dev) * . . - sane_set_io_mode : set blocking-mode * . . - sane_get_select_fd : get scanner-fd * . . - sane_get_option_descriptor() : get option information * . . - sane_control_option() : change option values * . . * . . - sane_start() : start image acquisition * . . - sane_get_parameters() : returns actual scan-parameters * . . - sane_read() : read image-data (from pipe) * * in ADF mode this is done often: * . . - sane_start() : start image acquisition * . . - sane_get_parameters() : returns actual scan-parameters * . . - sane_read() : read image-data (from pipe) * * . . - sane_cancel() : cancel operation, kill reader_process * * . - sane_close() : close opened scanner-device, do_cancel, free buffer and handle * - sane_exit() : terminate use of backend, free devicename and device-structure */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #define BACKEND_NAME avision #define BACKEND_BUILD 297 /* avision backend BUILD version */ #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_thread.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" #include /* For timeval... */ #ifdef DEBUG #include #endif /* Attention: The comments must stay as they are - they are automatically parsed to generate the SANE avision.desc file, as well as HTML online content! */ /* Attention2: This device table is part of the source code and as such licensed under the terms of the license as listed above (GPL2+). By using this data you obviously create derived work! -ReneR */ static Avision_HWEntry Avision_Device_List [] = { { "AVISION", "AV100CS", 0, 0, "Avision", "AV100CS", 0}, /* status="untested" */ { "AVISION", "AV100IIICS", 0, 0, "Avision", "AV100IIICS", 0}, /* status="untested" */ { "AVISION", "AV100S", 0, 0, "Avision", "AV100S", 0}, /* status="untested" */ { NULL, NULL, 0x0638, 0x0A27, "Avision", "AV120", AV_INT_STATUS}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A3C, "Avision", "AV121", AV_INT_BUTTON | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA}, /* comment="sheetfed scanner" */ /* status="good" */ { NULL, NULL, 0x0638, 0x0A33, "Avision", "AV122", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET}, /* comment="sheetfed duplex scanner" */ /* status="good" */ { NULL, NULL, 0x0638, 0x0A93, "Avision", "AV122 C2", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_NOT_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET}, /* comment="sheetfed duplex scanner" */ /* status="good" */ { NULL, NULL, 0x0638, 0x0A24, "Avision", "AV210", AV_INT_BUTTON | AV_ACCEL_TABLE}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A25, "Avision", "AV210", AV_INT_BUTTON | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A3A, "Avision", "AV210C2", AV_INT_BUTTON | AV_GRAY_MODES}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A2F, "Avision", "AV210C2-G", AV_INT_BUTTON | AV_GRAY_MODES}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x1A35, "Avision", "AV210D2+", AV_INT_BUTTON | AV_USE_GRAY_FILTER}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A23, "Avision", "AV220", AV_INT_BUTTON | AV_GRAY_MODES}, /* comment="duplex! sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A2A, "Avision", "AV220C2", AV_INT_BUTTON | AV_CANCEL_BUTTON}, /* comment="duplex! sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A2B, "Avision", "AV220D2", AV_INT_BUTTON | AV_CANCEL_BUTTON}, /* comment="duplex! sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x1A31, "Avision", "AV220D2+", AV_INT_BUTTON | AV_CANCEL_BUTTON | AV_USE_GRAY_FILTER}, /* comment="duplex! sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A2C, "Avision", "AV220+", AV_INT_BUTTON | AV_CANCEL_BUTTON}, /* comment="duplex! sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A2D, "Avision", "AV220C2-G", AV_INT_BUTTON | AV_CANCEL_BUTTON}, /* comment="duplex! sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A2E, "Avision", "AV220C2-B", AV_INT_BUTTON | AV_CANCEL_BUTTON}, /* comment="duplex! sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A94, "Avision", "AV220-G", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_FIRMWARE}, /* comment="duplex! sheetfed scanner" */ /* status="complete" */ { "AVISION", "AV240SC", 0, 0, "Avision", "AV240SC", 0}, /* status="untested" */ { "AVISION", "AV260CS", 0, 0, "Avision", "AV260CS", 0}, /* status="untested" */ { "AVISION", "AV360CS", 0, 0, "Avision", "AV360CS", 0}, /* status="untested" */ { "AVISION", "AV363CS", 0, 0, "Avision", "AV363CS", 0}, /* status="untested" */ { "AVISION", "AV420CS", 0, 0, "Avision", "AV420CS", 0}, /* status="untested" */ { "AVISION", "AV6120", 0, 0, "Avision", "AV6120", 0}, /* status="untested" */ { NULL, "AV610", 0x0638, 0x0a18, "Avision", "AV610", AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x0638, 0x0a18, "Avision", "AV600U Plus", /* 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) */ AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | /* AV_INT_STATUS | */ AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x0638, 0x0a5e, "Avision", "AV610C2", AV_NO_BACKGROUND | AV_INT_BUTTON}, /* cancel button -> sense abort! */ /* status="good" */ { NULL, NULL, 0x0638, 0x0a41, "Avision", "AM3000 Series", 0}, /* comment="MFD" */ /* status="basic" */ { NULL, NULL, 0x0638, 0x0a16, "Avision", "DS610CU Scancopier", AV_INT_STATUS}, /* comment="1 pass, 600 dpi, A4" */ /* status="good" */ { "AVISION", "AV620CS", 0, 0, "Avision", "AV620CS", 0}, /* comment="1 pass, 600 dpi" */ /* status="complete" */ { "AVISION", "AV620CS Plus", 0, 0, "Avision", "AV620CS Plus", 0}, /* comment="1 pass, 1200 dpi" */ /* status="complete" */ { "AVISION", "AV630CS", 0, 0, "Avision", "AV630CS", 0}, /* comment="1 pass, 1200 dpi" */ /* status="complete" */ { "AVISION", "AV630CSL", 0, 0, "Avision", "AV630CSL", 0}, /* comment="1 pass, 1200 dpi" */ /* status="untested" */ { "AVISION", "AV6240", 0, 0, "Avision", "AV6240", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A13, "Avision", "AV600U", AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_SOFT_SCALE | AV_INT_STATUS | AV_NO_BUTTON}, /* comment="1 pass, 600 dpi" */ /* status="good" */ { "AVISION", "AV660S", 0, 0, "Avision", "AV660S", 0}, /* comment="1 pass, ??? dpi" */ /* status="untested" */ { "AVISION", "AV680S", 0, 0, "Avision", "AV680S", 0}, /* comment="1 pass, ??? dpi" */ /* status="untested" */ { "AVISION", "AV690U", 0, 0, "Avision", "AV690U", 0}, /* comment="1 pass, 2400 dpi" */ /* status="untested" */ { "AVISION", "AV800S", 0, 0, "Avision", "AV800S", 0}, /* comment="1 pass, ??? dpi" */ /* status="untested" */ { "AVISION", "AV810C", 0, 0, "Avision", "AV810C", 0}, /* comment="1 pass, ??? dpi" */ /* status="untested" */ { "AVISION", "AV820", 0, 0, "Avision", "AV820", 0}, /* comment="1 pass, ??? dpi" */ /* status="untested" */ { "AVISION", "AV820C", 0, 0, "Avision", "AV820C", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "AV820C Plus", 0, 0, "Avision", "AV820C Plus", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "AV830C", 0, 0, "Avision", "AV830C", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "AV830C Plus", 0, 0, "Avision", "AV830C Plus", 0}, /* comment="1 pass, ??? dpi" */ /* status="untested" */ { "AVISION", "AV880", 0, 0, "Avision", "AV880", 0}, /* comment="1 pass, ??? dpi" */ /* status="untested" */ { "AVISION", "AV880C", 0, 0, "Avision", "AV880C", 0}, /* comment="1 pass, ??? dpi" */ /* status="untested" */ { "AVISION", "AV3200C", 0, 0, "Avision", "AV3200C", AV_NON_INTERLACED_DUPLEX_300 | AV_FASTER_WITH_FILTER}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "AV3200SU", 0x0638, 0x0A4E, "Avision", "AV3200SU", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "AV3730SU", 0x0638, 0x0A4F, "Avision", "AV3730SU", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "AV3750SU", 0x0638, 0x0A65, "Avision", "AV3750SU", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "AV3800C", 0, 0, "Avision", "AV3800C", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "AV3850SU", 0x0638, 0x0a66, "Avision", "AV3850SU", 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ { "AVISION", "FB6000E", 0, 0, "Avision", "FB6000E", AV_NON_INTERLACED_DUPLEX_300}, /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0a82, "Avision", "FB6080E", AV_NON_INTERLACED_DUPLEX_300}, /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0a84, "Avision", "FB2080E", 0}, /* comment="1 pass, 600 dpi, zero-edge" ASIC 7 */ /* status="basic" */ { "AVISION", "AV8000S", 0, 0, "Avision", "AV8000S", AV_DOES_NOT_KEEP_WINDOW}, /* comment="1 pass, 1200 dpi, A3" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0a4d, "Avision", "AV8050U", AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA}, /* comment="1 pass, 1200 dpi, A3 - duplex!" */ /* status="complete" */ { "AVISION", "AV8300", 0x0638, 0x0A40, "Avision", "AV8300", AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA}, /* comment="1 pass, 1200 dpi, A3 - duplex!" */ /* status="complete" */ { "AVISION", "AV8350", 0x0638, 0x0A68, "Avision", "AV8350", AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA}, /* comment="1 pass, 1200 dpi, A3 - duplex!" */ /* status="complete" */ { NULL, NULL, 0x0638, 0x0A61, "Avision", "IT8300", AV_NON_INTERLACED_DUPLEX_300 | AV_ACCEL_TABLE}, /* comment="1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" */ /* status="good" */ { NULL, NULL, 0x0638, 0x0AA1, "Avision", "@V2500", 0}, /* comment="" */ /* status="untested" */ { NULL, NULL, 0x0638, 0x0A45, "Avision", "@V5100", 0}, /* comment="1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" */ /* status="good" */ { "AVISION", "AVA3", 0, 0, "Avision", "AVA3", AV_FORCE_A3}, /* comment="1 pass, 600 dpi, A3" */ /* status="basic" */ /* and possibly more avisions ;-) */ { "HP", "ScanJet 5300C", 0x03f0, 0x0701, "Hewlett-Packard", "ScanJet 5300C", AV_INT_STATUS}, /* comment="1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" */ /* status="complete" */ { "HP", "ScanJet 5370C", 0x03f0, 0x0701, "Hewlett-Packard", "ScanJet 5370C", AV_MULTI_CALIB_CMD | AV_INT_STATUS}, /* comment="1 pass, 2400 dpi - some FW revisions have x-axis image scaling problems over 1200 dpi" */ /* status="good" */ { "hp", "scanjet 7400c", 0x03f0, 0x0801, "Hewlett-Packard", "ScanJet 7400c", AV_LIGHT_CHECK_BOGUS | AV_NO_64BYTE_ALIGN | AV_INT_STATUS}, /* comment="1 pass, 2400 dpi - dual USB/SCSI interface" */ /* status="good" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { "hp", "scanjet 7450c", 0x03f0, 0x0801, "Hewlett-Packard", "ScanJet 7450c", AV_NO_64BYTE_ALIGN | AV_INT_STATUS}, /* comment="1 pass, 2400 dpi - dual USB/SCSI interface" */ /* status="good" */ { "hp", "scanjet 7490c", 0x03f0, 0x0801, "Hewlett-Packard", "ScanJet 7490c", AV_NO_64BYTE_ALIGN | AV_INT_STATUS}, /* comment="1 pass, 1200 dpi - dual USB/SCSI interface" */ /* status="good" */ #endif { "HP", "C9930A", 0x03f0, 0x0b01, "Hewlett-Packard", "ScanJet 8200", AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE}, /* comment="1 pass, 4800 (?) dpi - USB 2.0" */ /* status="good" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { "HP", "C9930A", 0x03f0, 0x0b01, "Hewlett-Packard", "ScanJet 8250", AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE}, /* comment="1 pass, 4800 (?) dpi - USB 2.0" */ /* status="good" */ #endif { "HP", "C9930A", 0x03f0, 0x3905, "Hewlett-Packard", "ScanJet 8270", AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE}, /* comment="1 pass, 4800 (?) dpi - USB 2.0" */ /* status="good" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { "HP", "C9930A", 0x03f0, 0x0b01, "Hewlett-Packard", "ScanJet 8290", AV_ADF_FLIPPING_DUPLEX | AV_FIRMWARE}, /* comment="1 pass, 4800 (?) dpi - USB 2.0 and SCSI - only SCSI tested so far" */ /* status="good" */ #endif { "HP", "C9930A", 0x03f0, 0x3805, "Hewlett-Packard", "ScanJet 8300", 0}, /* comment="1 pass, 4800 (?) dpi - USB 2.0" */ /* status="good" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { "HP", "C9930A", 0x03f0, 0x3805, "Hewlett-Packard", "ScanJet 8350", 0}, /* comment="1 pass, 4800 (?) dpi - USB 2.0" */ /* status="good" */ { "HP", "C9930A", 0x03f0, 0x3805, "Hewlett-Packard", "ScanJet 8390", 0}, /* comment="1 pass, 4800 (?) dpi - USB 2.0" */ /* status="good" */ #endif { "Minolta", "#2882", 0, 0, "Minolta", "Dimage Scan Dual I", AV_FORCE_FILM | AV_NO_START_SCAN}, /* not AV_FILMSCANNER (no frame control) */ /* status="basic" */ { "Minolta", "#2887", 0, 0, "Minolta", "Scan Multi Pro", AV_FORCE_FILM | AV_NO_START_SCAN}, /* AV_FILMSCANNER (frame control)? */ /* status="untested" */ { "MINOLTA", "FS-V1", 0x0638, 0x026a, "Minolta", "Dimage Scan Dual II", AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_12_BIT_MODE}, /* comment="1 pass, film-scanner" */ /* status="good" */ { "MINOLTA", "Elite II", 0x0686, 0x4004, "Minolta", "Elite II", AV_FILMSCANNER | AV_ONE_CALIB_CMD}, /* comment="1 pass, film-scanner" */ /* status="untested" */ { "MINOLTA", "FS-V3", 0x0686, 0x400d, "Minolta", "Dimage Scan Dual III", AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_ACCEL_TABLE}, /* comment="1 pass, film-scanner" */ /* status="good" */ { "MINOLTA", "FS-V4", 0x0686, 0x400e, "Minolta", "Dimage Scan Elite 5400", AV_FILMSCANNER | AV_ONE_CALIB_CMD | /*AV_ACCEL_TABLE |*/ AV_NO_START_SCAN}, /* comment="1 pass, film-scanner" */ /* status="good" */ { "QMS", "SC-110", 0x0638, 0x0a15, "Minolta-QMS", "SC-110", 0}, /* comment="" */ /* status="untested" */ { "QMS", "SC-215", 0x0638, 0x0a16, "Minolta-QMS", "SC-215", 0}, /* comment="" */ /* status="good" */ { "MITSBISH", "MCA-ADFC", 0, 0, "Mitsubishi", "MCA-ADFC", 0}, /* status="untested" */ { "MITSBISH", "MCA-S1200C", 0, 0, "Mitsubishi", "S1200C", 0}, /* status="untested" */ { "MITSBISH", "MCA-S600C", 0, 0, "Mitsubishi", "S600C", 0}, /* status="untested" */ { "MITSBISH", "SS600", 0, 0, "Mitsubishi", "SS600", 0}, /* status="good" */ /* The next are all untested ... */ { "FCPA", "ScanPartner", 0, 0, "Fujitsu", "ScanPartner", AV_FUJITSU}, /* status="untested" */ { "FCPA", "ScanPartner 10", 0, 0, "Fujitsu", "ScanPartner 10", AV_FUJITSU}, /* status="untested" */ { "FCPA", "ScanPartner 10C", 0, 0, "Fujitsu", "ScanPartner 10C", AV_FUJITSU}, /* status="untested" */ { "FCPA", "ScanPartner 15C", 0, 0, "Fujitsu", "ScanPartner 15C", AV_FUJITSU}, /* status="untested" */ { "FCPA", "ScanPartner 300C", 0, 0, "Fujitsu", "ScanPartner 300C", 0}, /* status="untested" */ { "FCPA", "ScanPartner 600C", 0, 0, "Fujitsu", "ScanPartner 600C", 0}, /* status="untested" */ { "FCPA", "ScanPartner 620C", 0, 0, "Fujitsu", "ScanPartner 620C", AV_LIGHT_CHECK_BOGUS}, /* status="good" */ { "FCPA", "ScanPartner Jr", 0, 0, "Fujitsu", "ScanPartner Jr", 0}, /* status="untested" */ { "FCPA", "ScanStation", 0, 0, "Fujitsu", "ScanStation", 0}, /* status="untested" */ { NULL, NULL, 0x04c5, 0x1029, "Fujitsu", "fi-4010CU", 0}, /* status="untested" */ { NULL, NULL, 0x04c5, 0x10ef, "Fujitsu", "fi-5015C", 0}, /* status="good" */ { NULL, NULL, 0x040a, 0x6001, "Kodak", "i30", AV_INT_BUTTON | AV_GRAY_MODES}, /* status="untested" */ { NULL, NULL, 0x040a, 0x6002, "Kodak", "i40", AV_INT_BUTTON | AV_GRAY_MODES}, /* status="basic" */ { NULL, NULL, 0x040a, 0x6003, "Kodak", "i50", AV_INT_BUTTON}, /* status="untested" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { NULL, NULL, 0x040a, 0x6003, "Kodak", "i55", AV_INT_BUTTON}, /* status="untested" */ #endif { NULL, NULL, 0x040a, 0x6004, "Kodak", "i60", AV_INT_BUTTON}, /* status="untested" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { NULL, NULL, 0x040a, 0x6004, "Kodak", "i65", AV_INT_BUTTON}, /* status="untested" */ #endif { NULL, NULL, 0x040a, 0x6005, "Kodak", "i80", AV_INT_BUTTON}, /* status="good" */ { "iVina", "1200U", 0x0638, 0x0268, "iVina", "1200U", 0}, /* status="untested" */ { NULL, NULL, 0x04a7, 0x0424, "Visioneer", "Strobe XP 450", AV_INT_BUTTON | AV_ACCEL_TABLE}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0491, "Visioneer", "Strobe XP 450-G", AV_INT_BUTTON | AV_ACCEL_TABLE}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0479, "Visioneer", "Strobe XP 470", AV_INT_BUTTON | AV_ACCEL_TABLE}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x048F, "Visioneer", "Strobe XP 470-G", AV_INT_BUTTON | AV_ACCEL_TABLE}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0420, "Visioneer", "9320", 0}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0421, "Visioneer", "9450", AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_NO_BUTTON | AV_NO_TUNE_SCAN_LENGTH}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x047A, "Visioneer", "9450-G", 0}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0422, "Visioneer", "9550", 0}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0390, "Visioneer", "9650", 0}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x047B, "Visioneer", "9650-G", 0}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0423, "Visioneer", "9750", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0493, "Visioneer", "9750-G", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0497, "Visioneer", "Patriot 430", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET}, /* comment="sheetfed scanner" */ /* status="complete" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { NULL, NULL, 0x04a7, 0x048F, "Visioneer", "Patriot 470", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ #endif { NULL, NULL, 0x04a7, 0x0498, "Visioneer", "Patriot 680", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x0499, "Visioneer", "Patriot 780", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ { NULL, NULL, 0x04a7, 0x049C, "Xerox", "DocuMate150", AV_INT_BUTTON | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK}, /* status="good" */ { NULL, NULL, 0x04a7, 0x0477, "Xerox", "DocuMate152", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK}, /* status="good" */ { NULL, NULL, 0x04a7, 0x049D, "Xerox", "DocuMate162", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK}, /* status="good" */ { NULL, NULL, 0x04a7, 0x0448, "Xerox", "DocuMate250", AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x04a7, 0x0490, "Xerox", "DocuMate250-G", AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x04a7, 0x0449, "Xerox", "DocuMate252", AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x04a7, 0x048C, "Xerox", "DocuMate252-G", AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x04a7, 0x0476, "Xerox", "DocuMate232", AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x04a7, 0x044c, "Xerox", "DocuMate262", AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x04a7, 0x048D, "Xerox", "DocuMate262-G", AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x04a7, 0x04a7, "Xerox", "DocuMate262i", AV_INT_BUTTON}, /* status="good" */ { NULL, NULL, 0x04a7, 0x0475, "Xerox", "DocuMate272", AV_INT_BUTTON}, /* status="untested" */ { NULL, NULL, 0x04a7, 0x048E, "Xerox", "DocuMate272-G", AV_INT_BUTTON}, /* status="untested" */ { NULL, NULL, 0x04a7, 0x0446, "Xerox", "DocuMate510", AV_INT_BUTTON}, /* status="untested" */ { NULL, NULL, 0x04a7, 0x0495, "Xerox", "DocuMate512", AV_INT_BUTTON}, /* status="untested" */ { NULL, NULL, 0x04a7, 0x047c, "Xerox", "DocuMate510-G", AV_INT_BUTTON}, /* status="untested" */ { NULL, NULL, 0x04a7, 0x0447, "Xerox", "DocuMate520", AV_INT_BUTTON}, /* status="untested" */ { NULL, NULL, 0x04a7, 0x0492, "Xerox", "DocuMate520-G", AV_INT_BUTTON}, /* status="untested" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { NULL, NULL, 0x04a7, 0x0498, "Xerox", "DocuMate632", AV_INT_BUTTON}, /* status="untested" */ #endif { NULL, NULL, 0x04a7, 0x0478, "Xerox", "DocuMate752", AV_INT_BUTTON}, /* status="untested" */ { NULL, NULL, 0x04a7, 0x049A, "Xerox", "DocuMate752", AV_INT_BUTTON}, /* status="untested" */ #ifdef FAKE_ENTRIES_FOR_DESC_GENERATION { NULL, NULL, 0x0638, 0x0a16, "OKI", "S700 Scancopier", 0}, /* comment="1 pass, 600 dpi, A4" */ /* status="good" */ #endif { "B+H", "2000F", 0, 0, "Bell+Howell", "2000F", 0}, /* comment="1 pass, ??? dpi, A4" */ /* status="basic" */ { NULL, NULL, 0x0482, 0x0335, "Kyocera", "FS-1016MFP", 0}, /* comment="1 pass, ??? dpi, A4" */ /* status="untested" */ /* More IDs from the Avision dll: ArtiScan ProA3 FB1065 FB1265 PHI860S PSDC SCSI SCSI Scan 19200 V6240 */ /* Possibly: Lexmark 4600 MFP Option MFP Options Lexmark 4600 MFP Option (C772n) MFP Options Lexmark X215 Lexmark Optra Image X242 Lexmark X443 Lexmark 3100 Lexmark 3200 Lexmark X340 MFP Multifunction Lexmark X342n MFP Multifunction Lexmark X522 Lexmark X630 Lexmark X632E Lexmark X642e MFP Multifunction Lexmark X644e MFP Multifunction Lexmark X646dte MFP Multifunction Lexmark X646e MFP Multifunction Lexmark X646ef MFP Multifunction Lexmark X772e Multifunction Lexmark X850e MFP Multifunction Lexmark X852e MFP Multifunction Lexmark X854e MFP Multifunction Lexmark X4500 MFP */ /* last entry detection */ { NULL, NULL, 0, 0, NULL, NULL, 0} }; #if 0 struct timeval tv; #define TIMING(txt) gettimeofday (&tv, NULL); \ DBG (4, "%lu: " txt "\n", tv.tv_sec * 1000000 + tv.tv_usec) #else #define TIMING(txt) #endif /* used when scanner returns invalid range fields ... */ #define A4_X_RANGE 8.5 /* or 8.25 ? */ #define A4_Y_RANGE 11.8 #define A3_X_RANGE 11.8 #define A3_Y_RANGE 16.5 /* or 17 ? */ #define FILM_X_RANGE 1.0 /* really ? */ #define FILM_Y_RANGE 1.0 #define SHEETFEED_Y_RANGE 14.0 #define AVISION_CONFIG_FILE "avision.conf" #define STD_INQUIRY_SIZE 0x24 #define AVISION_INQUIRY_SIZE_V1 0x60 #define AVISION_INQUIRY_SIZE_V2 0x88 #define AVISION_INQUIRY_SIZE_MAX AVISION_INQUIRY_SIZE_V2 #define AVISION_BASE_RES 300 /* calibration (shading) defines */ #define INVALID_WHITE_SHADING 0x0000 #define DEFAULT_WHITE_SHADING 0xFFF0 #define MAX_WHITE_SHADING 0xFFFF /* originally the WHITE_MAP_RANGE was 0x4000 - but this always * resulted in slightly too dark images - thus I have chosen * 0x4FFF ... */ #define WHITE_MAP_RANGE 0x4FFF #define INVALID_DARK_SHADING 0xFFFF #define DEFAULT_DARK_SHADING 0x0000 #define read_constrains(s,var) {\ if (s->hw->hw->feature_type & AV_NO_64BYTE_ALIGN) {\ if (var % 64 == 0) var /= 2;\ if (var % 64 == 0) var += 2;\ }\ }\ static int num_devices; static Avision_Device* first_dev; static Avision_Scanner* first_handle; static const SANE_Device** devlist = 0; /* this is a bit hacky to get extra information in the attach callback */ static Avision_HWEntry* attaching_hw = 0; /* disable the usage of a custom gamma-table */ static SANE_Bool disable_gamma_table = SANE_FALSE; /* disable the calibration */ static SANE_Bool disable_calibration = SANE_FALSE; static SANE_Bool force_calibration = SANE_FALSE; /* force scanable areas to ISO(DIN) A4/A3 */ static SANE_Bool force_a4 = SANE_FALSE; static SANE_Bool force_a3 = SANE_FALSE; /* trust ADF-presence flag, even if ADF model is nonzero */ static SANE_Bool skip_adf = SANE_FALSE; /* hardware resolutions to interpolate from */ static const int hw_res_list_c5[] = { /* tested on AV600U */ 75, 150, 300, 600, 1200, 2400, 4800, /* ... */ 0 }; static const int hw_res_list_generic[] = { 50, /* slower than 150 on the AV122/DM152, left for USB 1 host's preview */ 75, /* slower than 150 on the AV122/DM152, left for USB 1 host's */ 150, 200, 300, /* 400,*/ /* AV122 simplex y-scaling and duplex interlacing corrupt */ 600, 1200, 2400, 4800, /* ... */ 0 }; static SANE_Bool static_calib_list[3] = { SANE_FALSE, SANE_FALSE, SANE_FALSE }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const SANE_Range percentage_range = { SANE_FIX (-100), /* minimum */ SANE_FIX (100), /* maximum */ SANE_FIX (1) /* quantization */ }; static const SANE_Range abs_percentage_range = { SANE_FIX (0), /* minimum */ SANE_FIX (100), /* maximum */ SANE_FIX (1) /* quantization */ }; static const SANE_Range exposure_range = { 0, /* minimum */ 1000, /* maximum */ 1 /* quantization */ }; static const SANE_Range overscan_range = { SANE_FIX (0), /* minimum */ SANE_FIX (4), /* maximum */ /* 4mm, measured on AV122, AV220C2, i40 */ 0 /* quantization */ }; /* The 0x32 is a random guess based on USB logs. Might need a per-device value in the future - 0x32 was tested on the AV122, DM152, AV220. */ static const SANE_Range background_range = { 0, /* minimum */ 0x32, /* maximum */ 0 /* quantization */ }; static const uint8_t test_unit_ready[] = { AVISION_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t get_status[] = { AVISION_SCSI_GET_DATA_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00 }; static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; DBG (3, "max_string_size:\n"); for (i = 0; strings[i]; ++ i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status constrain_value (Avision_Scanner* s, SANE_Int option, void* value, SANE_Int* info) { DBG (3, "constrain_value:\n"); return sanei_constrain_value (s->opt + option, value, info); } static void debug_print_raw (int dbg_level, char* info, const uint8_t* data, size_t count) { size_t i; DBG (dbg_level, "%s", info); for (i = 0; i < count; ++ i) { DBG (dbg_level, " [%lu] %1d%1d%1d%1d%1d%1d%1d%1db %3oo %3dd %2xx\n", (u_long) i, BIT(data[i],7), BIT(data[i],6), BIT(data[i],5), BIT(data[i],4), BIT(data[i],3), BIT(data[i],2), BIT(data[i],1), BIT(data[i],0), data[i], data[i], data[i]); } } static void debug_print_hex_raw (int dbg_level, char* info, const uint8_t* data, size_t count) { int address = 0; char text [16*3+1]; DBG (dbg_level, "%s", info); while (count) { char* t = text; int i = 0; while (i < 16 && count) { t += sprintf (t, "%02x ", *data++); count--; i++; } *--t = 0; DBG (dbg_level, " [%08x] %s\n", address, text); address += 16; } } static void debug_print_nvram_data (int dbg_level, char* func, nvram_data* nvram) { DBG (dbg_level, "%s: pad scans: %d\n", func, get_quad(nvram->pad_scans)); DBG (dbg_level, "%s: ADF simplex scans: %d\n", func, get_quad(nvram->adf_simplex_scans)); DBG (dbg_level, "%s: ADF duplex scans: %d\n", func, get_quad(nvram->adf_duplex_scans)); DBG (dbg_level, "%s: flatbed scans: %d\n", func, get_quad(nvram->flatbed_scans)); DBG (dbg_level, "%s: flatbed leading edge: %d\n", func, (int16_t)get_double(nvram->flatbed_leading_edge)); DBG (dbg_level, "%s: flatbed side edge: %d\n", func, (int16_t)get_double(nvram->flatbed_side_edge)); DBG (dbg_level, "%s: ADF leading edge: %d\n", func, (int16_t)get_double(nvram->adf_leading_edge)); DBG (dbg_level, "%s: ADF side edge: %d\n", func, (int16_t)get_double(nvram->adf_side_edge)); DBG (dbg_level, "%s: ADF rear leading edge: %d\n", func, (int16_t)get_double(nvram->adf_rear_leading_edge)); DBG (dbg_level, "%s: ADF rear side edge: %d\n", func, (int16_t)get_double(nvram->adf_rear_side_edge)); DBG (dbg_level, "%s: born month: %d\n", func, get_double(nvram->born_month)); DBG (dbg_level, "%s: born day: %d\n", func, get_double(nvram->born_day)); DBG (dbg_level, "%s: born year: %d\n", func, get_double(nvram->born_year)); DBG (dbg_level, "%s: first scan month: %d\n", func, get_double(nvram->first_scan_month)); DBG (dbg_level, "%s: first scan day: %d\n", func, get_double(nvram->first_scan_day)); DBG (dbg_level, "%s: first scan year: %d\n", func, get_double(nvram->first_scan_year)); DBG (dbg_level, "%s: vert. magnification: %d\n", func, get_double(nvram->vertical_magnification)); DBG (dbg_level, "%s: horiz. magnification: %d\n", func, get_double(nvram->horizontal_magnification)); DBG (dbg_level, "%s: CCD type: %d\n", func, nvram->ccd_type); DBG (dbg_level, "%s: scan speed: %d\n", func, nvram->scan_speed); DBG (dbg_level, "%s: serial: '%.24s'\n", /* 24 chars max */ func, nvram->serial); DBG (dbg_level, "%s: power saving time: %d\n", func, get_double(nvram->power_saving_time)); DBG (dbg_level, "%s: auto feed: %d\n", func, nvram->auto_feed); DBG (dbg_level, "%s: roller count: %d\n", func, get_quad(nvram->roller_count)); DBG (dbg_level, "%s: multifeed count: %d\n", func, get_quad(nvram->multifeed_count)); DBG (dbg_level, "%s: jam count: %d\n", func, get_quad(nvram->jam_count)); DBG (dbg_level, "%s: identify info: '%.16s'\n", /* 16 chars max */ func, nvram->identify_info); DBG (dbg_level, "%s: formal_name: '%.16s'\n", /* 16 chars max */ func, nvram->formal_name); } static void debug_print_avdimen (int dbg_level, char* func, Avision_Dimensions* avdimen) { DBG (dbg_level, "%s: hw_xres: %d, hw_yres: %d, line_difference: %d\n", func, avdimen->hw_xres, avdimen->hw_yres, avdimen->line_difference); DBG (dbg_level, "%s: tlx: %ld, tly: %ld, brx: %ld, bry: %ld\n", func, avdimen->tlx, avdimen->tly, avdimen->brx, avdimen->bry); DBG (dbg_level, "%s: hw_pixel_per_line: %d, hw_lines: %d, hw_bytes_per_line: %d\n", func, avdimen->hw_pixels_per_line, avdimen->hw_lines, avdimen->hw_bytes_per_line); DBG (dbg_level, "%s: xres: %d, yres: %d\n", func, avdimen->xres, avdimen->yres); } static void debug_print_params (int dbg_level, char* func, SANE_Parameters* params) { DBG (dbg_level, "%s: pixel_per_line: %d, lines: %d\n", func, params->pixels_per_line, params->lines); DBG (dbg_level, "%s: depth: %d, bytes_per_line: %d\n", func, params->depth, params->bytes_per_line); } static void debug_print_calib_format (int dbg_level, char* func, uint8_t* result) { debug_print_raw (dbg_level + 2, "debug_print_calib_format:\n", result, 32); DBG (dbg_level, "%s: [0-1] pixels per line: %d\n", func, get_double ( &(result[0]) )); DBG (dbg_level, "%s: [2] bytes per channel: %d\n", func, result[2]); DBG (dbg_level, "%s: [3] line count: %d\n", func, result[3]); DBG (dbg_level, "%s: [4] FLAG:%s%s%s\n", func, result[4] == 1?" MUST_DO_CALIBRATION":"", result[4] == 2?" SCAN_IMAGE_DOES_CALIBRATION":"", result[4] == 3?" NEEDS_NO_CALIBRATION":""); DBG (dbg_level, "%s: [5] Ability1:%s%s%s%s%s%s%s%s\n", func, BIT(result[5],7)?" NONE_PACKED":" PACKED", BIT(result[5],6)?" INTERPOLATED":"", BIT(result[5],5)?" SEND_REVERSED":"", BIT(result[5],4)?" PACKED_DATA":"", BIT(result[5],3)?" COLOR_CALIB":"", BIT(result[5],2)?" DARK_CALIB":"", BIT(result[5],1)?" NEEDS_WHITE_BLACK_SHADING_DATA":"", BIT(result[5],0)?" NEEDS_CALIB_TABLE_CHANNEL_BY_CHANNEL":""); DBG (dbg_level, "%s: [6] R gain: %d\n", func, result[6]); DBG (dbg_level, "%s: [7] G gain: %d\n", func, result[7]); DBG (dbg_level, "%s: [8] B gain: %d\n", func, result[8]); DBG (dbg_level, "%s: [9-10] R shading target: %x\n", func, get_double ( &(result[9]) ) ); DBG (dbg_level, "%s: [11-12] G shading target: %x\n", func, get_double ( &(result[11]) ) ); DBG (dbg_level, "%s: [13-14] B shading target: %x\n", func, get_double ( &(result[13]) ) ); DBG (dbg_level, "%s: [15-16] R dark shading target: %x\n", func, get_double ( &(result[15]) ) ); DBG (dbg_level, "%s: [17-18] G dark shading target: %x\n", func, get_double ( &(result[17]) ) ); DBG (dbg_level, "%s: [19-20] B dark shading target: %x\n", func, get_double ( &(result[19]) ) ); DBG (dbg_level, "%s: [21] true-gray gain: %d\n", func, result[21]); DBG (dbg_level, "%s: [22-23] true-gray shading target: %x\n", func, get_double ( &(result[22]) ) ); DBG (dbg_level, "%s: [24-25] true-gray dark shading target: %x\n", func, get_double ( &(result[24]) ) ); } static void debug_print_accel_info (int dbg_level, char* func, uint8_t* result) { debug_print_raw (dbg_level + 2, "debug_print_accel_info:\n", result, 24); DBG (dbg_level, "%s: [0-1] acceleration step count: %d\n", func, get_double ( &(result[0]) )); DBG (dbg_level, "%s: [2-3] stable step count: %d\n", func, get_double ( &(result[2]) )); DBG (dbg_level, "%s: [4-7] table units: %d\n", func, get_quad ( &(result[4]) )); DBG (dbg_level, "%s: [8-11] base units: %d\n", func, get_quad ( &(result[8]) )); DBG (dbg_level, "%s: [12-13] start speed: %d\n", func, get_double ( &(result[12]) )); DBG (dbg_level, "%s: [14-15] target speed: %d\n", func, get_double ( &(result[14]) )); DBG (dbg_level, "%s: [16] ability:%s%s\n", func, BIT(result[16],0)?" TWO_BYTES_PER_ELEM":" SINGLE_BYTE_PER_ELEM", BIT(result[16],1)?" LOW_HIGH_ORDER":" HIGH_LOW_ORDER"); DBG (dbg_level, "%s: [17] table count: %d\n", func, result[17]); } static void debug_print_window_descriptor (int dbg_level, char* func, command_set_window_window* window) { debug_print_raw (dbg_level + 1, "window_data_header: \n", (uint8_t*)(&window->header), sizeof(window->header)); debug_print_raw (dbg_level + 1, "window_descriptor: \n", (uint8_t*)(&window->descriptor), sizeof(*window) - sizeof(window->header)); DBG (dbg_level, "%s: [0] window_id: %d\n", func, window->descriptor.winid); DBG (dbg_level, "%s: [2-3] x-axis res: %d\n", func, get_double (window->descriptor.xres)); DBG (dbg_level, "%s: [4-5] y-axis res: %d\n", func, get_double (window->descriptor.yres)); DBG (dbg_level, "%s: [6-9] x-axis upper left: %d\n", func, get_quad (window->descriptor.ulx)); DBG (dbg_level, "%s: [10-13] y-axis upper left: %d\n", func, get_quad (window->descriptor.uly)); DBG (dbg_level, "%s: [14-17] window width: %d\n", func, get_quad (window->descriptor.width)); DBG (dbg_level, "%s: [18-21] window length: %d\n", func, get_quad (window->descriptor.length)); DBG (dbg_level, "%s: [22] brightness: %d\n", func, window->descriptor.brightness); DBG (dbg_level, "%s: [23] threshold: %d\n", func, window->descriptor.threshold); DBG (dbg_level, "%s: [24] contrast: %d\n", func, window->descriptor.contrast); DBG (dbg_level, "%s: [25] image composition: %x\n", func, window->descriptor.image_comp); DBG (dbg_level, "%s: [26] bits per channel: %d\n", func, window->descriptor.bpc); DBG (dbg_level, "%s: [27-28] halftone pattern: %x\n", func, get_double (window->descriptor.halftone)); DBG (dbg_level, "%s: [29] padding_and_bitset: %x\n", func, window->descriptor.padding_and_bitset); DBG (dbg_level, "%s: [30-31] bit ordering: %x\n", func, get_double (window->descriptor.bitordering)); DBG (dbg_level, "%s: [32] compression type: %x\n", func, window->descriptor.compr_type); DBG (dbg_level, "%s: [33] compression argument: %x\n", func, window->descriptor.compr_arg); DBG (dbg_level, "%s: [34-35] paper length: %x\n", func, get_double (window->descriptor.paper_length) ); DBG (dbg_level, "%s: [40] vendor id: %x\n", func, window->descriptor.vendor_specific); DBG (dbg_level, "%s: [41] param length: %d\n", func, window->descriptor.paralen); DBG (dbg_level, "%s: [42] bitset1: %x\n", func, window->avision.bitset1); DBG (dbg_level, "%s: [43] highlight: %d\n", func, window->avision.highlight); DBG (dbg_level, "%s: [44] shadow: %d\n", func, window->avision.shadow); DBG (dbg_level, "%s: [45-46] line-width: %d\n", func, get_double (window->avision.line_width)); DBG (dbg_level, "%s: [47-48] line-count: %d\n", func, get_double (window->avision.line_count)); DBG (dbg_level, "%s: [49] bitset2: %x\n", func, window->avision.type.normal.bitset2); DBG (dbg_level, "%s: [50] ir exposure time: %x\n", func, window->avision.type.normal.ir_exposure_time); DBG (dbg_level, "%s: [51-52] r exposure: %x\n", func, get_double (window->avision.type.normal.r_exposure_time)); DBG (dbg_level, "%s: [53-54] g exposure: %x\n", func, get_double (window->avision.type.normal.g_exposure_time)); DBG (dbg_level, "%s: [55-56] b exposure: %x\n", func, get_double (window->avision.type.normal.b_exposure_time)); DBG (dbg_level, "%s: [57] bitset3: %x\n", func, window->avision.type.normal.bitset3); DBG (dbg_level, "%s: [58] auto focus: %d\n", func, window->avision.type.normal.auto_focus); DBG (dbg_level, "%s: [59] line-width (MSB): %d\n", func, window->avision.type.normal.line_width_msb); DBG (dbg_level, "%s: [60] line-count (MSB): %d\n", func, window->avision.type.normal.line_count_msb); DBG (dbg_level, "%s: [61] background lines: %d\n", func, window->avision.type.normal.background_lines); } static int write_pnm_header (FILE* f, color_mode m, int depth, int width, int height) { int maxval = (1 << depth) - 1; const char* hdr_str = NULL; /* construct PNM header */ switch (m) { case AV_THRESHOLDED: case AV_DITHERED: hdr_str = "P4\n%d %d\n"; break; case AV_GRAYSCALE: case AV_GRAYSCALE12: case AV_GRAYSCALE16: hdr_str = "P5\n%d %d\n%d\n"; break; case AV_TRUECOLOR: case AV_TRUECOLOR12: case AV_TRUECOLOR16: hdr_str = "P6\n%d %d\n%d\n"; break; case AV_COLOR_MODE_LAST: ; /* silence compiler warning */ } return fprintf (f, hdr_str, width, height, maxval); } static SANE_Status sense_handler (int fd, u_char* sense, void* arg) { SANE_Status status = SANE_STATUS_IO_ERROR; /* default case */ char* text; char textbuf[64]; uint8_t error_code = sense[0] & 0x7f; uint8_t sense_key = sense[2] & 0xf; uint8_t additional_sense = sense[7]; fd = fd; /* silence gcc */ arg = arg; /* silence gcc */ DBG (3, "sense_handler:\n"); switch (error_code) { case 0x70: text = "standard sense"; break; case 0x7f: text = "Avision-specific sense"; break; default: text = "unknown sense"; } debug_print_raw (1, "sense_handler: data:\n", sense, 8 + additional_sense); /* request valid? */ if (! (sense[0] & (1<<7))) { DBG (1, "sense_handler: sense not valid ...\n"); return status; } switch (sense_key) { case 0x00: status = SANE_STATUS_GOOD; text = "ok ?!?"; break; case 0x02: text = "NOT READY"; break; case 0x03: text = "MEDIUM ERROR (mostly ADF)"; status = SANE_STATUS_JAMMED; break; case 0x04: text = "HARDWARE ERROR"; break; case 0x05: text = "ILLEGAL REQUEST"; break; case 0x06: text = "UNIT ATTENTION"; break; case 0x09: text = "VENDOR SPECIFIC"; break; case 0x0b: text = "ABORTED COMMAND"; status = SANE_STATUS_CANCELLED; /* AV610C2 cancel button */ break; default: sprintf (textbuf, "got unknown sense code 0x%02x", (int)sense_key); text = textbuf; } DBG (1, "sense_handler: sense code: %s\n", text); if (sense[2] & (1<<6)) DBG (1, "sense_handler: end of scan\n"); else DBG (1, "sense_handler: scan has not yet been completed\n"); if (sense[2] & (1<<5)) DBG (1, "sense_handler: incorrect logical length\n"); else DBG (1, "sense_handler: correct logical length\n"); { uint8_t asc = sense[12]; uint8_t ascq = sense[13]; #define ADDITIONAL_SENSE(asc,ascq,txt) \ case ( (asc << 8) + ascq): text = txt; break switch ( (asc << 8) + ascq ) { /* normal */ ADDITIONAL_SENSE (0x00,0x00, "No additional sense information"); ADDITIONAL_SENSE (0x00,0x06, "I/O process terminated"); ADDITIONAL_SENSE (0x15,0x01, "Mechanical positioning error"); ADDITIONAL_SENSE (0x15,0x02, "Flatbed Home Sensor Error (OKI only"); ADDITIONAL_SENSE (0x15,0x03, "ADF Home Sensor Error (OKI only)"); ADDITIONAL_SENSE (0x15,0x04, "Lock Error (OKI only)"); ADDITIONAL_SENSE (0x1a,0x00, "parameter list length error"); ADDITIONAL_SENSE (0x20,0x00, "Invalid command"); ADDITIONAL_SENSE (0x24,0x00, "Invalid field in CDB"); ADDITIONAL_SENSE (0x25,0x00, "Logical unit not supported"); ADDITIONAL_SENSE (0x26,0x00, "Invalid field in parameter list"); ADDITIONAL_SENSE (0x26,0x01, "parameter not supported"); ADDITIONAL_SENSE (0x26,0x02, "parameter value invalid"); ADDITIONAL_SENSE (0x29,0x00, "Power-on, reset or bus device reset occurred"); ADDITIONAL_SENSE (0x2c,0x02, "Invalid combination of window specified"); ADDITIONAL_SENSE (0x2f,0x00, "Command cleared by another initiator"); ADDITIONAL_SENSE (0x3D,0x00, "Invalid Bit in Identify Message"); ADDITIONAL_SENSE (0x43,0x00, "Message error"); ADDITIONAL_SENSE (0x44,0x00, "Internal target failure"); ADDITIONAL_SENSE (0x44,0x01, "Flatbed DRAM Error(OKI only)"); ADDITIONAL_SENSE (0x44,0x02, "ADF DRAM Error(OKI only)"); ADDITIONAL_SENSE (0x44,0x03, "Write NVRAM Error"); ADDITIONAL_SENSE (0x47,0x00, "SCSI parity error"); ADDITIONAL_SENSE (0x49,0x00, "Invalid message error"); ADDITIONAL_SENSE (0x60,0x00, "Lamp failure"); ADDITIONAL_SENSE (0x60,0x01, "Flatbed Lamp error (Oki only)"); ADDITIONAL_SENSE (0x60,0x02, "ADF lamp error (Oki only)"); ADDITIONAL_SENSE (0x62,0x00, "Scan head positioning error"); ADDITIONAL_SENSE (0x80,0x01, "ADF paper jam"; status = SANE_STATUS_JAMMED); ADDITIONAL_SENSE (0x80,0x02, "ADF cover open"; status = SANE_STATUS_COVER_OPEN); ADDITIONAL_SENSE (0x80,0x03, "ADF chute empty"; status = SANE_STATUS_NO_DOCS); ADDITIONAL_SENSE (0x80,0x04, "ADF paper end"; status = SANE_STATUS_EOF); ADDITIONAL_SENSE (0x80,0x05, "Multi-feed (AV220,Kodak)"); ADDITIONAL_SENSE (0x80,0x06, "ADF prefeeding (OKI only)"); ADDITIONAL_SENSE (0x80,0x07, "Flatbed cover open (OKI only)"; status = SANE_STATUS_COVER_OPEN); ADDITIONAL_SENSE (0x80,0x08, "FW module doesn't match with scanner"); ADDITIONAL_SENSE (0x80,0x09, "Papers fed from multiple trays (DM272)"); ADDITIONAL_SENSE (0x80,0x0A, "ADF Paper Start"); ADDITIONAL_SENSE (0x80,0x0B, "Multiple ADF paper End and Start"); ADDITIONAL_SENSE (0x80,0x0C, "Multiple ADF paper End"); /* film scanner */ ADDITIONAL_SENSE (0x81,0x00, "ADF/MFP front door open"; status = SANE_STATUS_COVER_OPEN); ADDITIONAL_SENSE (0x81,0x01, "ADF holder cartridge open"; status = SANE_STATUS_COVER_OPEN); ADDITIONAL_SENSE (0x81,0x02, "ADF no film inside"; status = SANE_STATUS_NO_DOCS); ADDITIONAL_SENSE (0x81,0x03, "ADF initial load fail"); ADDITIONAL_SENSE (0x81,0x04, "ADF film end"; status = SANE_STATUS_NO_DOCS); ADDITIONAL_SENSE (0x81,0x05, "ADF forward feed error"); ADDITIONAL_SENSE (0x81,0x06, "ADF rewind error"); ADDITIONAL_SENSE (0x81,0x07, "ADF set unload"); ADDITIONAL_SENSE (0x81,0x08, "ADF adapter error"); ADDITIONAL_SENSE (0xA0,0x01, "Filter Positioning Error"); ADDITIONAL_SENSE (0x90,0x00, "Scanner busy (FW busy)"); default: sprintf (textbuf, "Unknown sense code asc: 0x%02x, ascq: 0x%02x", (int)asc, (int)ascq); text = textbuf; } #undef ADDITIONAL_SENSE DBG (1, "sense_handler: sense code: %s\n", text); /* sense code specific for invalid request * it is possible to get a detailed error location here ;-)*/ if (sense_key == 0x05) { if (sense[15] & (1<<7) ) { if (sense[15] & (1<<6) ) DBG (1, "sense_handler: error in command parameter\n"); else DBG (1, "sense_handler: error in data parameter\n"); DBG (1, "sense_handler: error in parameter byte: %d, %x\n", get_double(&(sense[16])), get_double(&(sense[16]))); /* bit pointer valid ?*/ if (sense[15] & (1<<3) ) DBG (1, "sense_handler: error in command parameter\n"); else DBG (1, "sense_handler: bit pointer invalid\n"); } } } return status; } /* * Avision scsi/usb multiplexers - to keep the code clean: */ static SANE_Status avision_usb_status (Avision_Connection* av_con, int retry, int timeout) { SANE_Status status = 0; uint8_t usb_status[1] = {0}; size_t count = 0; int t_retry = retry; #define valid_status(status,a) (status == SANE_STATUS_GOOD ? a : 0) DBG (4, "avision_usb_status: timeout %d, %d retries\n", timeout, retry); #ifndef HAVE_SANEI_USB_SET_TIMEOUT #error "You must update include/sane/sanei_usb.h and sanei/sanei_usb.c accordingly!" #endif sanei_usb_set_timeout (timeout); /* 1st try bulk transfers - they are more lightweight ... */ for (; count == 0 && (av_con->usb_status == AVISION_USB_BULK_STATUS || av_con->usb_status == AVISION_USB_UNTESTED_STATUS) && retry > 0; --retry) { count = sizeof (usb_status); DBG (5, "==> (bulk read) going down ...\n"); status = sanei_usb_read_bulk (av_con->usb_dn, usb_status, &count); DBG (5, "<== (bulk read) got: %ld, status: %d\n", (u_long)count, valid_status(status, usb_status[0])); if (count > 0) { av_con->usb_status = AVISION_USB_BULK_STATUS; } } /* reset retry count ... */ retry = t_retry; /* 2nd try interrupt status read - if not yet disabled */ for (; count == 0 && (av_con->usb_status == AVISION_USB_INT_STATUS || av_con->usb_status == AVISION_USB_UNTESTED_STATUS) && retry > 0; --retry) { count = sizeof (usb_status); DBG (5, "==> (interrupt read) going down ...\n"); status = sanei_usb_read_int (av_con->usb_dn, usb_status, &count); DBG (5, "<== (interrupt read) got: %ld, status: %d\n", (u_long)count, valid_status(status, usb_status[0])); if (count > 0) av_con->usb_status = AVISION_USB_INT_STATUS; } if (status != SANE_STATUS_GOOD) return status; if (count == 0) return SANE_STATUS_IO_ERROR; /* 0 = ok, 2 => request sense, 8 ==> busy, else error */ switch (usb_status[0]) { case AVISION_USB_GOOD: return SANE_STATUS_GOOD; case AVISION_USB_REQUEST_SENSE: DBG (2, "avision_usb_status: Needs to request sense!\n"); return SANE_STATUS_INVAL; case AVISION_USB_BUSY: DBG (2, "avision_usb_status: Busy!\n"); return SANE_STATUS_DEVICE_BUSY; default: DBG (1, "avision_usb_status: Unknown!\n"); return SANE_STATUS_INVAL; } } static SANE_Status avision_open (const char* device_name, Avision_Connection* av_con, SANEI_SCSI_Sense_Handler sense_handler, void *sense_arg) { if (av_con->connection_type == AV_SCSI) { return sanei_scsi_open (device_name, &(av_con->scsi_fd), sense_handler, sense_arg); } else { SANE_Status status; status = sanei_usb_open (device_name, &(av_con->usb_dn)); return status; } } static SANE_Status avision_open_extended (const char* device_name, Avision_Connection* av_con, SANEI_SCSI_Sense_Handler sense_handler, void *sense_arg, int *buffersize) { if (av_con->connection_type == AV_SCSI) { return sanei_scsi_open_extended (device_name, &(av_con->scsi_fd), sense_handler, sense_arg, buffersize); } else { SANE_Status status; status = sanei_usb_open (device_name, &(av_con->usb_dn)); return status; } } static void avision_close (Avision_Connection* av_con) { if (av_con->connection_type == AV_SCSI) { sanei_scsi_close (av_con->scsi_fd); av_con->scsi_fd = -1; } else { sanei_usb_close (av_con->usb_dn); av_con->usb_dn = -1; } } static SANE_Bool avision_is_open (Avision_Connection* av_con) { if (av_con->connection_type == AV_SCSI) { return av_con->scsi_fd >= 0; } else { return av_con->usb_dn >= 0; } } static SANE_Status 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) { if (av_con->connection_type == AV_SCSI) { return sanei_scsi_cmd2 (av_con->scsi_fd, cmd, cmd_size, src, src_size, dst, dst_size); } else { SANE_Status status = SANE_STATUS_GOOD; size_t i, count, out_count; /* some commands on some devices need a rather long time to respond */ #define STD_TIMEOUT 30000 #define STD_STATUS_TIMEOUT 10000 int retry = 4; int write_timeout = STD_TIMEOUT; int read_timeout = STD_TIMEOUT; int status_timeout = STD_STATUS_TIMEOUT; /* simply to allow nicer code below */ const uint8_t* m_cmd = (const uint8_t*)cmd; const uint8_t* m_src = (const uint8_t*)src; uint8_t* m_dst = (uint8_t*)dst; /* may I vote for the possibility to use C99 ... */ #define min_usb_size 10 #define max_usb_size 256 * 1024 /* or 0x10000, used by AV Windows driver during background raster read, ... ? */ /* 1st send command data - at least 10 Bytes for USB scanners */ uint8_t enlarged_cmd [min_usb_size]; if (cmd_size < min_usb_size) { DBG (1, "filling command to have a length of 10, was: %lu\n", (u_long) cmd_size); memcpy (enlarged_cmd, m_cmd, cmd_size); memset (enlarged_cmd + cmd_size, 0, min_usb_size - cmd_size); m_cmd = enlarged_cmd; cmd_size = min_usb_size; } /* per command class timeout tweaks */ switch (m_cmd[0]) { case AVISION_SCSI_INQUIRY: read_timeout = 1000; /* quickly timeout on initial detection */ status_timeout = 1000; break; case AVISION_SCSI_TEST_UNIT_READY: read_timeout = 15000; /* quickly timeout on initial detection */ status_timeout = 15000; break; } DBG (7, "Timeouts: write: %d, read: %d, status: %d\n", write_timeout, read_timeout, status_timeout); write_usb_cmd: if (--retry == 0) { DBG (1, "Max retry count reached: I/O error\n"); return SANE_STATUS_IO_ERROR; } count = cmd_size; sanei_usb_set_timeout (write_timeout); DBG (8, "try to write cmd, count: %lu.\n", (u_long) count); status = sanei_usb_write_bulk (av_con->usb_dn, m_cmd, &count); DBG (8, "wrote %lu bytes\n", (u_long) count); if (status != SANE_STATUS_GOOD || count != cmd_size) { DBG (3, "=== Got error %d trying to write, wrote: %ld. ===\n", status, (long)count); if (status != SANE_STATUS_GOOD) /* == SANE_STATUS_EOF) */ { DBG (3, "try to read status to clear the FIFO\n"); status = avision_usb_status (av_con, 1, 500); if (status != SANE_STATUS_GOOD) { DBG (3, "=== Got error %d trying to read status. ===\n", status); return SANE_STATUS_IO_ERROR; } else goto write_usb_cmd; } else { DBG (3, "Retrying to send command\n"); goto write_usb_cmd; } return SANE_STATUS_IO_ERROR; } /* 2nd send command data (if any) */ for (i = 0; i < src_size; ) { count = src_size - i; /* if (count > max_usb_size) count = max_usb_size; */ DBG (8, "try to write src, count: %lu.\n", (u_long) count); sanei_usb_set_timeout (write_timeout); status = sanei_usb_write_bulk (av_con->usb_dn, &(m_src[i]), &count); DBG (8, "wrote %lu bytes\n", (u_long) count); if (status == SANE_STATUS_GOOD) { i += count; } else { goto write_usb_cmd; } } /* 3rd: read the resulting data (payload) (if any) */ if (status == SANE_STATUS_GOOD && dst != NULL && *dst_size > 0) { out_count = 0; sanei_usb_set_timeout (read_timeout); while (out_count < *dst_size) { count = (*dst_size - out_count); DBG (8, "try to read %lu bytes\n", (u_long) count); status = sanei_usb_read_bulk(av_con->usb_dn, &(m_dst[out_count]), &count); DBG (8, "read %lu bytes\n", (u_long) count); if (count == 1 && (*dst_size - out_count > 1)) { DBG (1, "Got 1 byte - status? (%d) Resending.\n", m_dst[out_count]); goto write_usb_cmd; } else if (count > 0) { out_count += count; } else { DBG (1, "No data arrived.\n"); goto write_usb_cmd; } } } /* last: read the device status via a pseudo interrupt transfer * this is needed - otherwise the scanner will hang ... */ sanei_usb_set_timeout (status_timeout); status = avision_usb_status (av_con, /*retry*/ 1, status_timeout); /* next i/o hardening attempt - and yes this gets ugly ... */ if (status != SANE_STATUS_GOOD && status != SANE_STATUS_INVAL) goto write_usb_cmd; if (status == SANE_STATUS_INVAL) { struct { command_header header; uint8_t pad[4]; } sense_cmd; uint8_t sense_buffer[22]; DBG (3, "Error during status read!\n"); DBG (3, "=== Try to request sense ===\n"); /* we can not call avision_cmd recursively - we might ending in an endless recursion requesting sense for failing request sense transfers ...*/ memset (&sense_cmd, 0, sizeof (sense_cmd) ); memset (&sense_buffer, 0, sizeof (sense_buffer) ); sense_cmd.header.opc = AVISION_SCSI_REQUEST_SENSE; sense_cmd.header.len = sizeof (sense_buffer); count = sizeof(sense_cmd); DBG (8, "try to write %lu bytes\n", (u_long) count); sanei_usb_set_timeout (write_timeout); status = sanei_usb_write_bulk (av_con->usb_dn, (uint8_t*) &sense_cmd, &count); DBG (8, "wrote %lu bytes\n", (u_long) count); if (status != SANE_STATUS_GOOD) { DBG (3, "=== Got error %d trying to request sense! ===\n", status); } else { count = sizeof (sense_buffer); DBG (8, "try to read %lu bytes sense data\n", (u_long) count); sanei_usb_set_timeout (read_timeout); status = sanei_usb_read_bulk(av_con->usb_dn, sense_buffer, &count); DBG (8, "read %lu bytes sense data\n", (u_long) count); /* we need to read out the status from the scanner i/o buffer */ status = avision_usb_status (av_con, 1, status_timeout); /* some scanner return NEED_SENSE even after reading it */ if (status != SANE_STATUS_GOOD && status != SANE_STATUS_INVAL) DBG (3, "=== Got error %d trying to read sense! ===\n", status); else { /* read complete -> call our sense handler */ status = sense_handler (-1, sense_buffer, 0); } } /* end read sense data */ } /* end request sense */ return status; } /* end cmd usb */ } /* A bubble sort for the calibration. It only sorts the first third * and returns an average of the top 2/3 values. The input data is * 16bit big endian and the count is the count of the words - not * bytes! */ static uint16_t bubble_sort (uint8_t* sort_data, size_t count) { size_t i, j, limit, k; double sum = 0.0; limit = count / 3; for (i = 0; i < limit; ++i) { uint16_t ti = 0; uint16_t tj = 0; for (j = (i + 1); j < count; ++j) { ti = get_double ((sort_data + i*2)); tj = get_double ((sort_data + j*2)); if (ti > tj) { set_double ((sort_data + i*2), tj); set_double ((sort_data + j*2), ti); } } } for (k = 0, i = limit; i < count; ++i) { sum += get_double ((sort_data + i*2)); ++ k; } /* DBG (7, "bubble_sort: %d values for average\n", k); */ if (k > 0) /* if avg to compute */ return (uint16_t) (sum / k); else return (uint16_t) (sum); /* always zero? */ } static SANE_Status add_color_mode (Avision_Device* dev, color_mode mode, SANE_String name) { int i; DBG (3, "add_color_mode: %d %s\n", mode, name); for (i = 0; i < AV_COLOR_MODE_LAST; ++i) { if (dev->color_list [i] == 0) { dev->color_list [i] = strdup (name); dev->color_list_num [i] = mode; return SANE_STATUS_GOOD; } else if (strcmp (dev->color_list [i], name) == 0) { /* already in list */ return SANE_STATUS_GOOD; } } DBG (3, "add_color_mode: failed\n"); return SANE_STATUS_NO_MEM; } static int last_color_mode (Avision_Device* dev) { int i = 1; while (dev->color_list [i] != 0 && i < AV_COLOR_MODE_LAST) ++i; /* we are off by one */ --i; return i; } static color_mode match_color_mode (Avision_Device* dev, SANE_String name) { int i; DBG (3, "match_color_mode:\n"); for (i = 0; i < AV_COLOR_MODE_LAST; ++i) { if (dev->color_list [i] != 0 && strcmp (dev->color_list [i], name) == 0) { DBG (3, "match_color_mode: found at %d mode: %d\n", i, dev->color_list_num [i]); return dev->color_list_num [i]; } } DBG (3, "match_color_mode: source mode invalid\n"); return AV_GRAYSCALE; } static SANE_Bool color_mode_is_shaded (color_mode mode) { return mode >= AV_GRAYSCALE; } static SANE_Bool color_mode_is_color (color_mode mode) { return mode >= AV_TRUECOLOR; } static SANE_Bool is_adf_scan (Avision_Scanner* s) { return s->hw->scanner_type == AV_SHEETFEED || (s->hw->scanner_type == AV_FLATBED && s->source_mode_dim == AV_ADF_DIM); } static SANE_Status add_source_mode (Avision_Device* dev, source_mode mode, SANE_String name) { int i; for (i = 0; i < AV_SOURCE_MODE_LAST; ++i) { if (dev->source_list [i] == 0) { dev->source_list [i] = strdup (name); dev->source_list_num [i] = mode; return SANE_STATUS_GOOD; } else if (strcmp (dev->source_list [i], name) == 0) { /* already in list */ return SANE_STATUS_GOOD; } } return SANE_STATUS_NO_MEM; } static source_mode match_source_mode (Avision_Device* dev, SANE_String name) { int i; DBG (3, "match_source_mode: \"%s\"\n", name); for (i = 0; i < AV_SOURCE_MODE_LAST; ++i) { if (dev->source_list [i] != 0 && strcmp (dev->source_list [i], name) == 0) { DBG (3, "match_source_mode: found at %d mode: %d\n", i, dev->source_list_num [i]); return dev->source_list_num [i]; } } DBG (3, "match_source_mode: source mode invalid\n"); return AV_NORMAL; } static source_mode_dim match_source_mode_dim (source_mode sm) { DBG (3, "match_source_mode_dim: %d\n", sm); switch (sm) { case AV_NORMAL: return AV_NORMAL_DIM; case AV_TRANSPARENT: return AV_TRANSPARENT_DIM; case AV_ADF: case AV_ADF_REAR: case AV_ADF_DUPLEX: return AV_ADF_DIM; default: DBG (3, "match_source_mode_dim: source mode invalid\n"); return AV_NORMAL_DIM; } } static int get_pixel_boundary (Avision_Scanner* s) { Avision_Device* dev = s->hw; int boundary; switch (s->c_mode) { case AV_TRUECOLOR: case AV_TRUECOLOR12: case AV_TRUECOLOR16: boundary = dev->inquiry_color_boundary; break; case AV_GRAYSCALE: case AV_GRAYSCALE12: case AV_GRAYSCALE16: boundary = dev->inquiry_gray_boundary; break; case AV_DITHERED: if (dev->inquiry_asic_type != AV_ASIC_C5) boundary = 32; else boundary = dev->inquiry_dithered_boundary; break; case AV_THRESHOLDED: if (dev->inquiry_asic_type != AV_ASIC_C5) boundary = 32; else boundary = dev->inquiry_thresholded_boundary; break; default: boundary = 8; } return boundary; } static SANE_Status compute_parameters (Avision_Scanner* s) { Avision_Device* dev = s->hw; int boundary = get_pixel_boundary (s); SANE_Bool gray_mode = color_mode_is_shaded (s->c_mode); /* interlaced duplex (higher end) or flipping paper (HP8xxx)? */ s->avdimen.interlaced_duplex = s->source_mode == AV_ADF_DUPLEX && dev->inquiry_duplex_interlaced; /* for infra-red we use the same code path es for interlaced duplex */ if (s->val[OPT_IR].w) s->avdimen.interlaced_duplex = 1; #ifdef AVISION_ENHANCED_SANE /* quick fix for Microsoft Office Products ... */ switch (s->c_mode) { case AV_THRESHOLDED: case AV_DITHERED: /* our backend already has this restriction - so this line is for documentation purposes only */ boundary = boundary > 32 ? boundary : 32; break; case AV_GRAYSCALE: case AV_GRAYSCALE12: case AV_GRAYSCALE16: boundary = boundary > 4 ? boundary : 4; break; case AV_TRUECOLOR: case AV_TRUECOLOR12: case AV_TRUECOLOR16: /* 12 bytes for 24bit color - 48bit is untested w/ Office */ boundary = boundary > 4 ? boundary : 4; break; } #endif DBG (3, "sane_compute_parameters:\n"); DBG (3, "sane_compute_parameters: boundary %d, gray_mode: %d, \n", boundary, gray_mode); /* TODO: Implement different x/y resolutions support */ s->avdimen.xres = s->val[OPT_RESOLUTION].w; s->avdimen.yres = s->val[OPT_RESOLUTION].w; /* soft scale ? */ if (dev->hw->feature_type & AV_SOFT_SCALE) { /* find supported hardware resolution */ const int* hw_res; const int* hw_res_list = dev->inquiry_asic_type == AV_ASIC_C5 ? hw_res_list_c5 : hw_res_list_generic; for (hw_res = hw_res_list; *hw_res && *hw_res < s->avdimen.xres; ++hw_res) /* just iterate */; s->avdimen.hw_xres = *hw_res; for (hw_res = hw_res_list; *hw_res && *hw_res < s->avdimen.yres; ++hw_res) /* just iterate */; s->avdimen.hw_yres = *hw_res; DBG (3, "sane_compute_parameters: soft scale, hw res: %dx%d\n", s->avdimen.hw_xres, s->avdimen.hw_yres); if (!s->avdimen.hw_xres || ! s->avdimen.hw_yres) { DBG (1, "sane_compute_parameters: no matching HW res for: %dx%d\n", s->avdimen.xres, s->avdimen.yres); return SANE_STATUS_INVAL; } } else { s->avdimen.hw_xres = s->val[OPT_RESOLUTION].w; s->avdimen.hw_yres = s->val[OPT_RESOLUTION].w; } DBG (3, "sane_compute_parameters: tlx: %f, tly: %f, brx: %f, bry: %f\n", SANE_UNFIX (s->val[OPT_TL_X].w), SANE_UNFIX (s->val[OPT_TL_Y].w), SANE_UNFIX (s->val[OPT_BR_X].w), SANE_UNFIX (s->val[OPT_BR_Y].w)); /* window parameter in pixel */ s->avdimen.tlx = s->avdimen.hw_xres * SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH; s->avdimen.tly = s->avdimen.hw_yres * SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH; s->avdimen.brx = s->avdimen.hw_xres * SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH; s->avdimen.bry = s->avdimen.hw_yres * SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH; /* line difference */ if (color_mode_is_color (s->c_mode) && dev->inquiry_needs_software_colorpack && dev->inquiry_line_difference) { s->avdimen.line_difference = (dev->inquiry_line_difference * s->avdimen.hw_yres) / dev->inquiry_optical_res; s->avdimen.bry += 2 * s->avdimen.line_difference; /* limit bry + line_difference to real scan boundary */ { long y_max = dev->inquiry_y_ranges[s->source_mode_dim] * s->avdimen.hw_yres / MM_PER_INCH; DBG (3, "sane_compute_parameters: y_max: %ld, bry: %ld, line_difference: %d\n", y_max, s->avdimen.bry, s->avdimen.line_difference); if (s->avdimen.bry + 2 * s->avdimen.line_difference > y_max) { DBG (1, "sane_compute_parameters: bry limited!\n"); s->avdimen.bry = y_max - 2 * s->avdimen.line_difference; } } } /* end if needs software colorpack */ else { s->avdimen.line_difference = 0; } /* add overscan */ if (dev->inquiry_tune_scan_length && is_adf_scan (s)) { /* some extra effort for precise rounding ... */ int overscan = (s->avdimen.hw_yres * (SANE_UNFIX (s->val[OPT_OVERSCAN_TOP].w) + SANE_UNFIX (s->val[OPT_OVERSCAN_BOTTOM].w)) + (MM_PER_INCH - 1) ) / MM_PER_INCH; DBG (3, "sane_compute_parameters: overscan lines: %d\n", overscan); s->avdimen.bry += overscan; } /* rear offset compensation */ if (s->avdimen.interlaced_duplex && dev->hw->feature_type & AV_REAR_OFFSET) { const double offset = 0.5; /* in current affected models 1/2 inch */ s->avdimen.rear_offset = (int) (offset * s->avdimen.hw_yres); DBG (1, "sane_compute_parameters: rear_offset: %d!\n", s->avdimen.rear_offset); /* we do not limit against the bottom-y here, as rear offset always applies to ADF scans, only */ } else { s->avdimen.rear_offset = 0; } memset (&s->params, 0, sizeof (s->params)); s->avdimen.hw_pixels_per_line = (s->avdimen.brx - s->avdimen.tlx); s->avdimen.hw_pixels_per_line -= s->avdimen.hw_pixels_per_line % boundary; s->avdimen.hw_lines = (s->avdimen.bry - s->avdimen.tly - 2 * s->avdimen.line_difference); if (s->avdimen.interlaced_duplex && dev->scanner_type != AV_FILM) s->avdimen.hw_lines -= s->avdimen.hw_lines % dev->read_stripe_size; s->params.pixels_per_line = s->avdimen.hw_pixels_per_line * s->avdimen.xres / s->avdimen.hw_xres; s->params.lines = s->avdimen.hw_lines * s->avdimen.xres / s->avdimen.hw_xres; if (is_adf_scan (s)) /* we can't know how many lines we'll see with an ADF because that depends on the paper length */ s->params.lines = -1; if (s->c_mode == AV_THRESHOLDED || s->c_mode == AV_DITHERED) s->params.pixels_per_line -= s->params.pixels_per_line % 8; debug_print_avdimen (1, "sane_compute_parameters", &s->avdimen); switch (s->c_mode) { case AV_THRESHOLDED: s->params.format = SANE_FRAME_GRAY; s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line / 8; s->params.bytes_per_line = s->params.pixels_per_line / 8; s->params.depth = 1; break; case AV_DITHERED: s->params.format = SANE_FRAME_GRAY; s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line / 8; s->params.bytes_per_line = s->params.pixels_per_line / 8; s->params.depth = 1; break; case AV_GRAYSCALE: s->params.format = SANE_FRAME_GRAY; s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; break; case AV_GRAYSCALE12: case AV_GRAYSCALE16: s->params.format = SANE_FRAME_GRAY; s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line * 2; s->params.bytes_per_line = s->params.pixels_per_line * 2; s->params.depth = 16; break; case AV_TRUECOLOR: s->params.format = SANE_FRAME_RGB; s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line * 3; s->params.bytes_per_line = s->params.pixels_per_line * 3; s->params.depth = 8; break; case AV_TRUECOLOR12: case AV_TRUECOLOR16: s->params.format = SANE_FRAME_RGB; s->avdimen.hw_bytes_per_line = s->avdimen.hw_pixels_per_line * 3 * 2; s->params.bytes_per_line = s->params.pixels_per_line * 3 * 2; s->params.depth = 16; break; default: DBG (1, "Invalid mode. %d\n", s->c_mode); return SANE_STATUS_INVAL; } /* end switch */ s->params.last_frame = SANE_TRUE; debug_print_params (1, "sane_compute_parameters", &s->params); return SANE_STATUS_GOOD; } static SANE_Status inquiry (Avision_Connection av_con, uint8_t* data, size_t len) { SANE_Status status; command_header inquiry; int try = 2; DBG (3, "inquiry: length: %ld\n", (long)len); memset (&inquiry, 0, sizeof(inquiry)); inquiry.opc = AVISION_SCSI_INQUIRY; inquiry.len = len; do { size_t size = inquiry.len; DBG (3, "inquiry: inquiring ...\n"); status = avision_cmd (&av_con, &inquiry, sizeof (inquiry), 0, 0, data, &size); if (status == SANE_STATUS_GOOD && size == inquiry.len) break; DBG (1, "inquiry: inquiry failed (%s)\n", sane_strstatus (status)); --try; } while (try > 0); return status; } static SANE_Status wait_ready (Avision_Connection* av_con, int delay) { SANE_Status status; int try; for (try = 0; try < 10; ++ try) { DBG (3, "wait_ready: sending TEST_UNIT_READY\n"); status = avision_cmd (av_con, test_unit_ready, sizeof (test_unit_ready), 0, 0, 0, 0); sleep (delay); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG (1, "wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: break; case SANE_STATUS_GOOD: return status; } } DBG (1, "wait_ready: timed out after %d attempts\n", try); return SANE_STATUS_INVAL; } static SANE_Status wait_4_light (Avision_Scanner* s) { Avision_Device* dev = s->hw; /* read stuff */ struct command_read rcmd; char* light_status[] = { "off", "on", "warming up", "needs warm up test", "light check error", "backlight on", "RESERVED" }; SANE_Status status; uint8_t result; int try; size_t size = 1; DBG (3, "wait_4_light: getting light status.\n"); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0xa0; /* get light status */ set_double (rcmd.datatypequal, dev->data_dq); set_triple (rcmd.transferlen, size); for (try = 0; try < 90; ++ try) { if (s->cancelled) { DBG (3, "wait_4_light: cancelled\n"); return SANE_STATUS_CANCELLED; } DBG (5, "wait_4_light: read bytes %lu\n", (u_long) size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, &result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result)) { DBG (1, "wait_4_light: read failed (%s)\n", sane_strstatus (status)); return status; } DBG (3, "wait_4_light: command is %d. Result is %d (%s)\n", status, result, light_status[(result>5)?6:result]); if (result == 1 || result == 5) { return SANE_STATUS_GOOD; } else if (dev->hw->feature_type & AV_LIGHT_CHECK_BOGUS) { DBG (3, "wait_4_light: scanner marked as returning bogus values in device-list!!\n"); return SANE_STATUS_GOOD; } else { struct command_send scmd; uint8_t light_on = 1; /* turn on the light */ DBG (3, "wait_4_light: setting light status.\n"); memset (&scmd, 0, sizeof (scmd)); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = 0xa0; /* send light status */ set_double (scmd.datatypequal, dev->data_dq); set_triple (scmd.transferlen, size); status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), &light_on, sizeof (light_on), 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "wait_4_light: send failed (%s)\n", sane_strstatus (status)); return status; } } sleep (1); } DBG (1, "wait_4_light: timed out after %d attempts\n", try); return SANE_STATUS_DEVICE_BUSY; } static SANE_Status set_power_save_time (Avision_Scanner* s, int time) { struct { struct command_send cmd; uint8_t time[2]; } scmd; Avision_Device* dev = s->hw; SANE_Status status; DBG (3, "set_power_save_time: time %d\n", time); memset (&scmd, 0, sizeof (scmd)); scmd.cmd.opc = AVISION_SCSI_SEND; scmd.cmd.datatypecode = 0xA2; /* power-saving timer */ set_double (scmd.cmd.datatypequal, dev->data_dq); set_triple (scmd.cmd.transferlen, sizeof (scmd.time) ); set_double (scmd.time, time); status = avision_cmd (&s->av_con, &scmd.cmd, sizeof (scmd.cmd), &scmd.time, sizeof (scmd.time), 0, 0); if (status != SANE_STATUS_GOOD) DBG (1, "set_power_save_time: send_data (%s)\n", sane_strstatus (status)); return status; } static SANE_Status get_firmware_status (Avision_Connection* av_con) { /* read stuff */ struct command_read rcmd; size_t size; SANE_Status status; firmware_status result; DBG (3, "get_firmware_status\n"); size = sizeof (result); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x90; /* firmware status */ set_double (rcmd.datatypequal, 0); /* dev->data_dq not available */ set_triple (rcmd.transferlen, size); status = avision_cmd (av_con, &rcmd, sizeof (rcmd), 0, 0, &result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result)) { DBG (1, "get_firmware_status: read failed (%s)\n", sane_strstatus (status)); return (status); } debug_print_raw (6, "get_firmware_status: raw data:\n", (uint8_t*)&result, size); DBG (3, "get_firmware_status: [0] needs firmware %x\n", result.download_firmware); DBG (3, "get_firmware_status: [1] side edge: %d\n", get_double ( result.first_effective_pixel_flatbed )); DBG (3, "get_firmware_status: [3] side edge: %d\n", get_double ( result.first_effective_pixel_adf_front )); DBG (3, "get_firmware_status: [5] side edge: %d\n", get_double ( result.first_effective_pixel_adf_rear )); return SANE_STATUS_GOOD; } static SANE_Status get_flash_ram_info (Avision_Connection* av_con) { /* read stuff */ struct command_read rcmd; size_t size; SANE_Status status; uint8_t result[40]; DBG (3, "get_flash_ram_info\n"); size = sizeof (result); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x6a; /* flash ram information */ set_double (rcmd.datatypequal, 0); /* dev->data_dq not available */ set_triple (rcmd.transferlen, size); status = avision_cmd (av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result)) { DBG (1, "get_flash_ram_info: read failed (%s)\n", sane_strstatus (status)); return (status); } debug_print_raw (6, "get_flash_ram_info: raw data:\n", result, size); DBG (3, "get_flash_ram_info: [0] data type %x\n", result [0]); DBG (3, "get_flash_ram_info: [1] Ability1:%s%s%s%s%s%s%s%s\n", BIT(result[1],7)?" RESERVED_BIT7":"", BIT(result[1],6)?" RESERVED_BIT6":"", BIT(result[1],5)?" FONT(r/w)":"", BIT(result[1],4)?" FPGA(w)":"", BIT(result[1],3)?" FMDBG(r)":"", BIT(result[1],2)?" RAWLINE(r)":"", BIT(result[1],1)?" FIRMWARE(r/w)":"", BIT(result[1],0)?" CTAB(r/w)":""); DBG (3, "get_flash_ram_info: [2-5] size CTAB: %d\n", get_quad ( &(result[2]) ) ); DBG (3, "get_flash_ram_info: [6-9] size FIRMWARE: %d\n", get_quad ( &(result[6]) ) ); DBG (3, "get_flash_ram_info: [10-13] size RAWLINE: %d\n", get_quad ( &(result[10]) ) ); DBG (3, "get_flash_ram_info: [14-17] size FMDBG: %d\n", get_quad ( &(result[14]) ) ); DBG (3, "get_flash_ram_info: [18-21] size FPGA: %d\n", get_quad ( &(result[18]) ) ); DBG (3, "get_flash_ram_info: [22-25] size FONT: %d\n", get_quad ( &(result[22]) ) ); DBG (3, "get_flash_ram_info: [26-29] size RESERVED: %d\n", get_quad ( &(result[26]) ) ); DBG (3, "get_flash_ram_info: [30-33] size RESERVED: %d\n", get_quad ( &(result[30]) ) ); return SANE_STATUS_GOOD; } static SANE_Status get_nvram_data (Avision_Scanner* s, nvram_data* nvram) { /* read stuff */ struct command_send rcmd; size_t size; SANE_Status status; DBG (3, "get_nvram_data\n"); size = sizeof (*nvram); memset (&rcmd, 0, sizeof (rcmd)); memset (nvram, 0, size); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x69; /* Read NVM RAM data */ set_double (rcmd.datatypequal, 0); /* dev->data_dq not available */ set_triple (rcmd.transferlen, size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, nvram, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "get_nvram_data: read failed (%s)\n", sane_strstatus (status)); return (status); } debug_print_nvram_data (5, "get_nvram_data", nvram); return SANE_STATUS_GOOD; } static SANE_Status get_and_parse_nvram (Avision_Scanner* s, char* str, int n) { SANE_Status status; int i = 0; int x; nvram_data nvram; uint8_t inquiry_result [AVISION_INQUIRY_SIZE_V1]; status = inquiry (s->av_con, inquiry_result, sizeof(inquiry_result)); if (status == SANE_STATUS_GOOD) { i += snprintf (str+i, n-i, "Vendor: %.8s", inquiry_result+8); i += snprintf (str+i, n-i, "\nModel: %.16s", inquiry_result+16); i += snprintf (str+i, n-i, "\nFirmware: %.4s", inquiry_result+32); } if (!s->hw->inquiry_nvram_read) return SANE_STATUS_GOOD; status = get_nvram_data (s, &nvram); if (status == SANE_STATUS_GOOD) { if (nvram.serial[0]) i += snprintf (str+i, n-i, "\nSerial: %.24s", nvram.serial); if (nvram.born_year) i += snprintf (str+i, n-i, "\nManufacturing date: %d-%d-%d", get_double(nvram.born_year), get_double(nvram.born_month), get_double(nvram.born_day)); if (nvram.first_scan_year) i += snprintf (str+i, n-i, "\nFirst scan date: %d-%d-%d", get_double(nvram.first_scan_year), get_double(nvram.first_scan_month), get_double(nvram.first_scan_day)); x = get_quad (nvram.flatbed_scans); if (x) i += snprintf (str+i, n-i, "\nFlatbed scans: %d", x); x = get_quad (nvram.pad_scans); if (x) i += snprintf (str+i, n-i, "\nPad scans: %d", x); x = get_quad (nvram.adf_simplex_scans); if (x) i += snprintf (str+i, n-i, "\nADF simplex scans: %d", x); x = get_quad (nvram.adf_duplex_scans); if (x) i += snprintf (str+i, n-i, "\nADF duplex scans: %d", x); } return status; } static SANE_Status get_power_save_time (Avision_Scanner* s, SANE_Word* time) { SANE_Status status; nvram_data nvram; DBG (3, "get_power_save_time\n"); if (!s->hw->inquiry_nvram_read) return SANE_STATUS_INVAL; status = get_nvram_data (s, &nvram); if (status != SANE_STATUS_GOOD) { DBG (1, "get_power_save_time: read nvram failed (%s)\n", sane_strstatus (status)); return status; } *time = get_double (nvram.power_saving_time); return SANE_STATUS_GOOD; } #ifdef NEEDED static SANE_Status send_nvram_data (Avision_Connection* av_con) { /* read stuff */ struct command_send scmd; size_t size; SANE_Status status; DBG (3, "send_nvram_data\n"); size = sizeof (c7_nvram); memset (&scmd, 0, sizeof (scmd)); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = 0x85; /* nvram data */ set_double (scmd.datatypequal, 0); /* dev->data_dq not available */ set_triple (scmd.transferlen, size); status = avision_cmd (av_con, &scmd, sizeof (scmd), &c7_nvram, size, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "send_nvram_data: send failed (%s)\n", sane_strstatus (status)); return (status); } return SANE_STATUS_GOOD; } static SANE_Status send_flash_ram_data (Avision_Connection* av_con) { /* read stuff */ struct command_send scmd; size_t size; SANE_Status status; DBG (3, "send_flash_ram_data\n"); size = sizeof (c7_flash_ram); memset (&scmd, 0, sizeof (scmd)); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = 0x86; /* flash data */ set_double (scmd.datatypequal, 0); set_triple (scmd.transferlen, size); status = avision_cmd (av_con, &scmd, sizeof (scmd), &c7_flash_ram, size, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "send_flash_ram_data: send failed (%s)\n", sane_strstatus (status)); return (status); } return SANE_STATUS_GOOD; } #endif static SANE_Status adf_reset (Avision_Scanner* s) { SANE_Status status; Avision_Device* dev = s->hw; struct command_send scmd; struct command_read rcmd; uint8_t payload[4]; size_t size; size_t n; int i; DBG (3, "adf_reset\n"); /* loop twice */ for (i=1; i >= 0; i--) { n=i; memset (&scmd, 0, sizeof (scmd)); memset (&payload, 0, sizeof (payload)); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = 0xD0; /* unknown */ set_double (scmd.datatypequal, 0); size = 2; set_triple (scmd.transferlen, size); payload[1] = 0x10 * i; /* write 0x10 the first time, 0x00 the second */ status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), payload, size, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "adf_reset: write %d failed (%s)\n", (2-i), sane_strstatus (status)); return (status); } DBG (3, "adf_reset: write %d complete.\n", (2-i)); memset (&rcmd, 0, sizeof (rcmd)); memset (&payload, 0, sizeof (payload)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x69; /* Read NVRAM data */ set_double (rcmd.datatypequal, dev->data_dq); size = 4 - i; /* read 3 bytes the first time, 4 the second */ set_triple (rcmd.transferlen, size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, payload, &size); if (status != SANE_STATUS_GOOD || size != (4-n)) { DBG (1, "adf_reset: read %lu failed (%s)\n", (2-n), sane_strstatus (status)); return (status); } debug_print_raw (3, "adf_reset: raw data:\n", payload, size); } return SANE_STATUS_GOOD; } static SANE_Status get_accessories_info (Avision_Scanner* s) { Avision_Device* dev = s->hw; int try = 3; /* read stuff */ struct command_read rcmd; size_t size; SANE_Status status; uint8_t result[8]; char* adf_model[] = { "Origami", "Oodles", "HP9930", "unknown" }; const int adf_models = sizeof (adf_model) / sizeof(char*) - 1; DBG (3, "get_accessories_info\n"); size = sizeof (result); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x64; /* detect accessories */ set_double (rcmd.datatypequal, dev->data_dq); set_triple (rcmd.transferlen, size); /* after resetting the ADF unit, try reprobing it again */ RETRY: status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result)) { DBG (1, "get_accessories_info: read failed (%s)\n", sane_strstatus (status)); return (status); } debug_print_raw (6, "get_accessories_info: raw data:\n", result, size); DBG (3, "get_accessories_info: [0] ADF: %x\n", result[0]); DBG (3, "get_accessories_info: [1] Light Box: %x\n", result[1]); DBG (3, "get_accessories_info: [2] ADF model: %d (%s)\n", result [2], adf_model[ (result[2] < adf_models) ? result[2] : adf_models ]); dev->inquiry_adf |= result [0]; if (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) { if (result[0] == 1) { dev->inquiry_duplex = 1; dev->inquiry_duplex_interlaced = 0; } else if (result[0] == 0 && result[2] != 0 && !skip_adf) { /* Sometimes the scanner will report that there is no ADF attached, yet * an ADF model number will still be reported. This happens on the * HP8200 series and possibly others. In this case we need to reset the * the adf and try reading it again. Skip this if the configuration says * to do so, so that we don't fail out the scanner as being broken and * unsupported if there isn't actually an ADF present. */ DBG (3, "get_accessories_info: Found ADF model number but the ADF-present flag is not set. Trying to recover...\n"); status = adf_reset (s); if (status != SANE_STATUS_GOOD) { DBG (3, "get_accessories_info: Failed to reset ADF: %s\n", sane_strstatus (status)); return status; } DBG (1, "get_accessories_info: Waiting while ADF firmware resets...\n"); sleep(3); status = wait_ready (&s->av_con, 1); if (status != SANE_STATUS_GOOD) { DBG (1, "get_accessories_info: wait_ready() failed: %s\n", sane_strstatus (status)); return status; } if (try) { try--; goto RETRY; } DBG (1, "get_accessories_info: Maximum retries attempted, ADF unresponsive.\n"); return SANE_STATUS_UNSUPPORTED; } } /* only honor a 1, some scanner without adapter set 0xff */ if (result[1] == 1) dev->inquiry_light_box = 1; return SANE_STATUS_GOOD; } /* Returns a pointer to static char* strings or NULL for cancel (we do not want to start memcmp'ing for the cancel case). */ static const char* string_for_button (Avision_Scanner* s, int button) { static char buffer [16]; Avision_Device* dev = s->hw; /* dev->sane.model dev->inquiry_asic_type */ if (dev->inquiry_buttons == 1) goto return_scan; /* simplex / duplex buttons */ if (strcmp (dev->sane.vendor, "Xerox") == 0 || strcmp (dev->sane.vendor, "Visioneer") == 0 || strcmp (dev->sane.model, "AV121") == 0 || strcmp (dev->sane.model, "AV122") == 0 ) { switch (button) { case 1: return "simplex"; case 2: return "duplex"; } } if (strcmp (dev->sane.model, "AV210C2") == 0 || strcmp (dev->sane.model, "AV210D2+") == 0 || strcmp (dev->sane.model, "AV220C2") == 0 || strcmp (dev->sane.model, "AV610C2") == 0 ) { if (button == 1) return NULL; /* cancel */ else goto return_scan; } /* those are unique, right now */ if (strcmp (dev->sane.model, "AV610") == 0) { switch (button) { case 0: return "email"; case 1: return "copy"; case 2: return "scan"; } } /* last resort */ snprintf (buffer, sizeof (buffer), "button%d", button); return buffer; return_scan: return "scan"; } static SANE_Status get_button_status (Avision_Scanner* s) { Avision_Device* dev = s->hw; /* read stuff */ struct command_read rcmd; size_t size; SANE_Status status; /* was only 6 in an old SPEC - maybe we need a feature override :-( -ReneR */ struct { uint8_t press_state; uint8_t buttons[5]; uint8_t display; /* AV220 et.al. 7 segment LED display */ uint8_t reserved[9]; } result; unsigned int i; DBG (3, "get_button_status:\n"); size = sizeof (result); /* AV220 et.al. */ if (! (dev->hw->feature_type & AV_INT_BUTTON)) { memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0xA1; /* button status */ set_double (rcmd.datatypequal, dev->data_dq); set_triple (rcmd.transferlen, size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, (uint8_t*)&result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result)) { DBG (1, "get_button_status: read failed (%s)\n", sane_strstatus (status)); return status; } } else { /* only try to read the first 8 bytes ...*/ size = 8; /* no SCSI equivalent */ /* either there was a button press and this completes quickly or there is no point waiting for a future press */ sanei_usb_set_timeout (100); /* 10th of a second */ DBG (5, "==> (interrupt read) going down ...\n"); status = sanei_usb_read_int (s->av_con.usb_dn, (uint8_t*)&result, &size); DBG (5, "==> (interrupt read) got: %ld\n", (long)size); if (status != SANE_STATUS_GOOD) { DBG (1, "get_button_status: interrupt read failed (%s)\n", sane_strstatus (status)); return SANE_STATUS_GOOD; } if (size < sizeof (result)) memset ((char*)result.buttons + size, 0, sizeof (result) - size); /* hack to fill in meaningful values for the AV 210 / 610 and under some conditions the AV 220 */ if (size == 1) { /* AV 210, AV 610 */ DBG (1, "get_button_status: just one byte, filling the rest\n"); if (result.press_state > 0) { debug_print_raw (6, "get_button_status: raw data\n", (uint8_t*)&result, size); result.buttons[0] = result.press_state; result.press_state = 0x80 | 1; size = 2; } else /* nothing pressed */ return SANE_STATUS_GOOD; } else if (size >= 8 && result.press_state == 0) { /* AV 220 */ debug_print_raw (6, "get_button_status: raw data\n", (uint8_t*)&result, size); DBG (1, "get_button_status: zero buttons - filling values ...\n"); /* simulate button press of the last button ... */ result.press_state = 0x80 | 1; result.buttons[0] = dev->inquiry_buttons; /* 1 based */ } } debug_print_raw (6, "get_button_status: raw data\n", (uint8_t*)&result, size); DBG (3, "get_button_status: [0] Button status: %x\n", result.press_state); for (i = 0; i < 5; ++i) DBG (3, "get_button_status: [%d] Button number %d: %x\n", i+1, i, result.buttons[i]); DBG (3, "get_button_status: [7] Display: %d\n", result.display); { char* message_begin = s->val[OPT_MESSAGE].s; char* message_end = s->val[OPT_MESSAGE].s + s->opt[OPT_MESSAGE].size; char* message = message_begin; #define add_token(format,value) do { \ int n = snprintf (message, message_end - message, "%s" format, \ message == message_begin ? "" : ":", value); \ message += n > 0 ? n : 0; \ } while (0) if (result.display > 0) add_token ("%d", result.display); if (result.press_state >> 7) /* AV220 et.al. bit 6 is long/short press? */ { const unsigned int buttons_pressed = result.press_state & 0x7F; DBG (3, "get_button_status: %d button(s) pressed\n", buttons_pressed); /* reset the hardware button status */ if (! (dev->hw->feature_type & AV_INT_BUTTON)) { struct command_send scmd; uint8_t button_reset = 1; DBG (3, "get_button_status: resetting status\n"); memset (&scmd, 0, sizeof (scmd)); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = 0xA1; /* button control */ set_double (scmd.datatypequal, dev->data_dq); set_triple (scmd.transferlen, size); status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), &button_reset, sizeof (button_reset), 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "get_button_status: send failed (%s)\n", sane_strstatus (status)); return status; } } for (i = 0; i < buttons_pressed; ++i) { const unsigned int button = result.buttons[i] - 1; /* 1 based ... */ DBG (3, "get_button_status: button %d pressed\n", button); if (button >= dev->inquiry_buttons) { DBG (1, "get_button_status: button %d not allocated as not indicated in inquiry\n", button); } else { const char* label = string_for_button (s, button); if (label) add_token ("%s", label); else return SANE_STATUS_CANCELLED; } } } else DBG (3, "get_button_status: no button pressed\n"); } return SANE_STATUS_GOOD; #undef add_token } static SANE_Status get_frame_info (Avision_Scanner* s) { Avision_Device* dev = s->hw; /* read stuff */ struct command_read rcmd; size_t size; SANE_Status status; uint8_t result[8]; size_t i; DBG (3, "get_frame_info:\n"); size = sizeof (result); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x87; /* film holder sense */ set_double (rcmd.datatypequal, dev->data_dq); set_triple (rcmd.transferlen, size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result)) { DBG (1, "get_frame_info: read failed (%s)\n", sane_strstatus (status)); return (status); } debug_print_raw (6, "get_frame_info: raw data\n", result, size); DBG (3, "get_frame_info: [0] Holder type: %s\n", (result[0]==1)?"APS": (result[0]==2)?"Film holder (35mm)": (result[0]==3)?"Slide holder": (result[0]==0xff)?"Empty":"unknown"); DBG (3, "get_frame_info: [1] Current frame number: %d\n", result[1]); DBG (3, "get_frame_info: [2] Frame amount: %d\n", result[2]); DBG (3, "get_frame_info: [3] Mode: %s\n", BIT(result[3],4)?"APS":"Not APS"); DBG (3, "get_frame_info: [3] Exposures (if APS): %s\n", ((i=(BIT(result[3],3)<<1)+BIT(result[2],2))==0)?"Unknown": (i==1)?"15":(i==2)?"25":"40"); DBG (3, "get_frame_info: [3] Film Type (if APS): %s\n", ((i=(BIT(result[1],3)<<1)+BIT(result[0],2))==0)?"Unknown": (i==1)?"B&W Negative":(i==2)?"Color slide":"Color Negative"); dev->holder_type = result[0]; dev->current_frame = result[1]; dev->frame_range.min = 1; dev->frame_range.quant = 1; if (result[0] != 0xff) dev->frame_range.max = result[2]; else dev->frame_range.max = 1; return SANE_STATUS_GOOD; } static SANE_Status get_duplex_info (Avision_Scanner* s) { Avision_Device* dev = s->hw; /* read stuff */ struct command_read rcmd; struct { uint8_t mode; uint8_t color_line_difference[2]; uint8_t gray_line_difference[2]; uint8_t lineart_line_difference[2]; uint8_t image_info; } result; size_t size; SANE_Status status; DBG (3, "get_duplex_info:\n"); size = sizeof (result); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0xB1; /* read duplex info */ set_double (rcmd.datatypequal, dev->data_dq); set_triple (rcmd.transferlen, size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, &result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result)) { DBG (1, "get_duplex_info: read failed (%s)\n", sane_strstatus (status)); return (status); } debug_print_raw (6, "get_duplex_info: raw data\n", (uint8_t*)&result, size); DBG (3, "get_duplex_info: [0] Mode: %s%s\n", BIT(result.mode,0)?"MERGED_PAGES":"", BIT(result.mode,1)?"2ND_PAGE_FOLLOWS":""); DBG (3, "get_duplex_info: [1-2] Color line difference: %d\n", get_double(result.color_line_difference)); DBG (3, "get_duplex_info: [3-4] Gray line difference: %d\n", get_double(result.gray_line_difference)); DBG (3, "get_duplex_info: [5-6] Lineart line difference: %d\n", get_double(result.lineart_line_difference)); /* isn't this supposed to be result.info ?!? */ DBG (3, "get_duplex_info: [7] Mode: %s%s%s%s\n", BIT(result.image_info,0)?" FLATBED_BGR":" FLATBED_RGB", BIT(result.image_info,1)?" ADF_BGR":" ADF_RGB", BIT(result.image_info,2)?" FLATBED_NEEDS_MIRROR_IMAGE":"", BIT(result.image_info,3)?" ADF_NEEDS_MIRROR_IMAGE":""); return SANE_STATUS_GOOD; } static SANE_Status set_frame (Avision_Scanner* s, SANE_Word frame) { struct { struct command_send cmd; uint8_t data[8]; } scmd; Avision_Device* dev = s->hw; SANE_Status status; DBG (3, "set_frame: request frame %d\n", frame); /* Better check the current status of the film holder, because it can be changed between scans. */ status = get_frame_info (s); if (status != SANE_STATUS_GOOD) return status; /* No film holder? */ if (dev->holder_type == 0xff) { DBG (1, "set_frame: No film holder!!\n"); return SANE_STATUS_INVAL; } /* Requesting frame 0xff indicates eject/rewind */ if (frame != 0xff && (frame < 1 || frame > dev->frame_range.max) ) { DBG (1, "set_frame: Illegal frame (%d) requested (min=1, max=%d)\n", frame, dev->frame_range.max); return SANE_STATUS_INVAL; } memset (&scmd, 0, sizeof (scmd)); scmd.cmd.opc = AVISION_SCSI_SEND; scmd.cmd.datatypecode = 0x87; /* send film holder "sense" */ set_double (scmd.cmd.datatypequal, dev->data_dq); set_triple (scmd.cmd.transferlen, sizeof (scmd.data) ); scmd.data[0] = dev->holder_type; scmd.data[1] = frame; status = avision_cmd (&s->av_con, &scmd.cmd, sizeof (scmd.cmd), &scmd.data, sizeof (scmd.data), 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "set_frame: send_data (%s)\n", sane_strstatus (status)); } return status; } static SANE_Status attach (SANE_String_Const devname, Avision_ConnectionType con_type, Avision_Device** devp) { uint8_t result [AVISION_INQUIRY_SIZE_MAX]; int model_num; Avision_Device* dev; SANE_Status status; Avision_Connection av_con; char mfg [9]; char model [17]; char rev [5]; unsigned int i; char* s; SANE_Bool found; DBG (3, "attach:\n"); memset (result, 0, sizeof(result)); for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } av_con.connection_type = con_type; if (av_con.connection_type == AV_USB) av_con.usb_status = AVISION_USB_UNTESTED_STATUS; /* set known USB status type */ if (attaching_hw && attaching_hw->feature_type & AV_INT_STATUS) av_con.usb_status = AVISION_USB_INT_STATUS; DBG (3, "attach: opening %s\n", devname); status = avision_open (devname, &av_con, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed (%s)\n", sane_strstatus (status)); return SANE_STATUS_INVAL; } /* first: get the standard inquiry? */ status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V1); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: 1st inquiry failed (%s)\n", sane_strstatus (status)); return status; } /* copy string information - and zero terminate them c-style */ memcpy (&mfg, result + 8, 8); mfg [8] = 0; memcpy (&model, result + 16, 16); model [16] = 0; memcpy (&rev, result + 32, 4); rev [4] = 0; /* shorten strings (-1 for last index -1 for last 0; >0 because one char at least) */ for (i = sizeof (mfg) - 2; i > 0; i--) { if (mfg[i] == 0x20) mfg[i] = 0; else break; } for (i = sizeof (model) - 2; i > 0; i--) { if (model[i] == 0x20) model[i] = 0; else break; } DBG (1, "attach: Inquiry gives mfg=%s, model=%s, product revision=%s.\n", mfg, model, rev); model_num = 0; found = 0; /* while not at at end of list NULL terminator */ while (Avision_Device_List[model_num].real_mfg != NULL || Avision_Device_List[model_num].scsi_mfg != NULL) { int matches = 0, match_count = 0; /* count number of matches */ DBG (1, "attach: Checking model: %d\n", model_num); if (Avision_Device_List[model_num].scsi_mfg) { ++match_count; if (strcmp(mfg, Avision_Device_List[model_num].scsi_mfg) == 0) ++matches; } if (Avision_Device_List[model_num].scsi_model) { ++match_count; if (strcmp(model, Avision_Device_List[model_num].scsi_model) == 0) ++matches; } /* we need 2 matches (mfg, model) for SCSI entries, or the ones available for "we know what we are looking for" USB entries */ if ((attaching_hw == &(Avision_Device_List [model_num]) && matches == match_count) || matches == 2) { DBG (1, "attach: Scanner matched entry: %d: \"%s\", \"%s\", 0x%.4x, 0x%.4x\n", model_num, Avision_Device_List[model_num].scsi_mfg, Avision_Device_List[model_num].scsi_model, Avision_Device_List[model_num].usb_vendor, Avision_Device_List[model_num].usb_product); found = 1; break; } ++model_num; } if (!found) { DBG (0, "attach: \"%s\" - \"%s\" not yet in whitelist!\n", mfg, model); DBG (0, "attach: You might want to report this output.\n"); DBG (0, "attach: To: rene@exactcode.de (the Avision backend author)\n"); status = SANE_STATUS_INVAL; goto close_scanner_and_return; } /* second: maybe ask for the firmware status and flash ram info */ if (Avision_Device_List [model_num].feature_type & AV_FIRMWARE) { DBG (3, "attach: reading firmware status\n"); status = get_firmware_status (&av_con); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: get firmware status failed (%s)\n", sane_strstatus (status)); goto close_scanner_and_return; } DBG (3, "attach: reading flash ram info\n"); status = get_flash_ram_info (&av_con); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: get flash ram info failed (%s)\n", sane_strstatus (status)); goto close_scanner_and_return; } #ifdef FIRMWARE_DATABASE_INCLUDED /* Send new NV-RAM (firmware) data */ status = send_nvram_data (&av_con); if (status != SANE_STATUS_GOOD) goto close_scanner_and_return; #endif } /* third: get the extended Avision inquiry */ status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V1); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: avision v1 inquiry failed (%s)\n", sane_strstatus (status)); goto close_scanner_and_return; } dev = malloc (sizeof (*dev)); if (!dev) { status = SANE_STATUS_NO_MEM; goto close_scanner_and_return; } memset (dev, 0, sizeof (*dev)); dev->hw = &Avision_Device_List[model_num]; dev->sane.name = strdup (devname); dev->sane.vendor = dev->hw->real_mfg ? dev->hw->real_mfg : strdup (mfg); dev->sane.model = dev->hw->real_model ? dev->hw->real_model : strdup (model); dev->connection.connection_type = av_con.connection_type; dev->connection.usb_status = av_con.usb_status; /* and finally Avision even extended this one later on the AV220C2 does not grok this */ dev->inquiry_asic_type = (int) result[91]; if (dev->inquiry_asic_type == AV_ASIC_C6) { status = inquiry (av_con, result, AVISION_INQUIRY_SIZE_V2); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: avision v2 inquiry failed (%s)\n", sane_strstatus (status)); goto close_scanner_and_return; } } debug_print_raw (6, "attach: raw data:\n", result, sizeof (result) ); DBG (3, "attach: [8-15] Vendor id.: '%8.8s'\n", result+8); DBG (3, "attach: [16-31] Product id.: '%16.16s'\n", result+16); DBG (3, "attach: [32-35] Product rev.: '%4.4s'\n", result+32); i = (result[36] >> 4) & 0x7; switch (result[36] & 0x07) { case 0: s = " RGB"; break; case 1: s = " BGR"; break; default: s = " unknown (RESERVED)"; } DBG (3, "attach: [36] Bitfield:%s%s%s%s%s%s%s color plane\n", BIT(result[36],7)?" ADF":"", (i==0)?" B&W only":"", BIT(i, 1)?" 3-pass color":"", BIT(i, 2)?" 1-pass color":"", BIT(i, 2) && BIT(i, 0) ?" 1-pass color (ScanPartner only)":"", BIT(result[36],3)?" IS_NOT_FLATBED":"", s); DBG (3, "attach: [37] Optical res.: %d00 dpi\n", result[37]); DBG (3, "attach: [38] Maximum res.: %d00 dpi\n", result[38]); DBG (3, "attach: [39] Bitfield1:%s%s%s%s%s%s\n", BIT(result[39],7)?" TRANS":"", BIT(result[39],6)?" Q_SCAN":"", BIT(result[39],5)?" EXTENDED_RES":"", BIT(result[39],4)?" SUPPORTS_CALIB":"", BIT(result[39],2)?" NEW_PROTOCOL":"", (result[39] & 0x03) == 0x03 ? " AVISION":" OEM"); DBG (3, "attach: [40-41] X res. in gray: %d dpi\n", get_double ( &(result[40]) )); DBG (3, "attach: [42-43] Y res. in gray: %d dpi\n", get_double ( &(result[42]) )); DBG (3, "attach: [44-45] X res. in color: %d dpi\n", get_double ( &(result[44]) )); DBG (3, "attach: [46-47] Y res. in color: %d dpi\n", get_double ( &(result[46]) )); DBG (3, "attach: [48-49] USB max read: %d\n", get_double ( &(result[48] ) )); DBG (3, "attach: [50] ESA1:%s%s%s%s%s%s%s%s\n", BIT(result[50],7)?" LIGHT_CONTROL":"", BIT(result[50],6)?" BUTTON_CONTROL":"", BIT(result[50],5)?" NEED_SW_COLORPACK":"", BIT(result[50],4)?" SW_CALIB":"", BIT(result[50],3)?" NEED_SW_GAMMA":"", BIT(result[50],2)?" KEEPS_GAMMA":"", BIT(result[50],1)?" KEEPS_WINDOW_CMD":"", BIT(result[50],0)?" XYRES_DIFFERENT":""); DBG (3, "attach: [51] ESA2:%s%s%s%s%s%s%s%s\n", BIT(result[51],7)?" EXPOSURE_CTRL":"", BIT(result[51],6)?" NEED_SW_TRIGGER_CAL":"", BIT(result[51],5)?" NEED_WHITE_PAPER_CALIB":"", BIT(result[51],4)?" SUPPORTS_QUALITY_SPEED_CAL":"", BIT(result[51],3)?" NEED_TRANSP_CAL":"", BIT(result[51],2)?" HAS_PUSH_BUTTON":"", BIT(result[51],1)?" NEW_CAL_METHOD_3x3_MATRIX_(NO_GAMMA_TABLE)":"", BIT(result[51],0)?" ADF_MIRRORS_IMAGE":""); DBG (3, "attach: [52] ESA3:%s%s%s%s%s%s%s%s\n", BIT(result[52],7)?" GRAY_WHITE":"", BIT(result[52],6)?" SUPPORTS_GAIN_CONTROL":"", BIT(result[52],5)?" SUPPORTS_TET":"", /* "Text Enhanced Technology" */ BIT(result[52],4)?" 3x3COL_TABLE":"", BIT(result[52],3)?" 1x3FILTER":"", BIT(result[52],2)?" INDEX_COLOR":"", BIT(result[52],1)?" POWER_SAVING_TIMER":"", BIT(result[52],0)?" NVM_DATA_REC":""); /* print some more scanner features/params */ DBG (3, "attach: [53] line difference (software color pack): %d\n", result[53]); DBG (3, "attach: [54] color mode pixel boundary: %d\n", result[54]); DBG (3, "attach: [55] gray mode pixel boundary: %d\n", result[55]); DBG (3, "attach: [56] 4bit gray mode pixel boundary: %d\n", result[56]); DBG (3, "attach: [57] lineart mode pixel boundary: %d\n", result[57]); DBG (3, "attach: [58] halftone mode pixel boundary: %d\n", result[58]); DBG (3, "attach: [59] error-diffusion mode pixel boundary: %d\n", result[59]); DBG (3, "attach: [60] channels per pixel:%s%s%s\n", BIT(result[60],7)?" 1":"", BIT(result[60],6)?" 3":"", (result[60] & 0x3F) != 0 ? " RESERVED":""); DBG (3, "attach: [61] bits per channel:%s%s%s%s%s%s%s\n", BIT(result[61],7)?" 1":"", BIT(result[61],6)?" 4":"", BIT(result[61],5)?" 6":"", BIT(result[61],4)?" 8":"", BIT(result[61],3)?" 10":"", BIT(result[61],2)?" 12":"", BIT(result[61],1)?" 16":""); DBG (3, "attach: [62] scanner type:%s%s%s%s%s%s\n", BIT(result[62],7)?" Flatbed":"", BIT(result[62],6)?" Roller (ADF)":"", BIT(result[62],5)?" Flatbed (ADF)":"", BIT(result[62],4)?" Roller":"", /* does not feed multiple pages, AV25 */ BIT(result[62],3)?" Film scanner":"", BIT(result[62],2)?" Duplex":""); DBG (3, "attach: [75-76] Max shading target : %x\n", get_double ( &(result[75]) )); DBG (3, "attach: [77-78] Max X of transparency: %d dots * base_dpi\n", get_double ( &(result[77]) )); DBG (3, "attach: [79-80] Max Y of transparency: %d dots * base_dpi\n", get_double ( &(result[79]) )); DBG (3, "attach: [81-82] Max X of flatbed: %d dots * base_dpi\n", get_double ( &(result[81]) )); DBG (3, "attach: [83-84] Max Y of flatbed: %d dots * base_dpi\n", get_double ( &(result[83]) )); DBG (3, "attach: [85-86] Max X of ADF: %d dots * base_dpi\n", get_double ( &(result[85]) )); DBG (3, "attach: [87-88] Max Y of ADF: %d dots * base_dpi\n", get_double ( &(result[87]) )); /* 0xFFFF means unlimited length */ DBG (3, "attach: [89-90] Res. in Ex. mode: %d dpi\n", get_double ( &(result[89]) )); DBG (3, "attach: [91] ASIC: %d\n", result[91]); DBG (3, "attach: [92] Buttons: %d\n", result[92]); DBG (3, "attach: [93] ESA4:%s%s%s%s%s%s%s%s\n", BIT(result[93],7)?" SUPPORTS_ACCESSORIES_DETECT":"", BIT(result[93],6)?" ADF_IS_BGR_ORDERED":"", BIT(result[93],5)?" NO_SINGLE_CHANNEL_GRAY_MODE":"", BIT(result[93],4)?" SUPPORTS_FLASH_UPDATE":"", BIT(result[93],3)?" SUPPORTS_ASIC_UPDATE":"", BIT(result[93],2)?" SUPPORTS_LIGHT_DETECT":"", BIT(result[93],1)?" SUPPORTS_READ_PRNU_DATA":"", BIT(result[93],0)?" FLATBED_MIRRORS_IMAGE":""); DBG (3, "attach: [94] ESA5:%s%s%s%s%s%s%s%s\n", BIT(result[94],7)?" IGNORE_LINE_DIFFERENCE_FOR_ADF":"", BIT(result[94],6)?" NEEDS_SW_LINE_COLOR_PACK":"", BIT(result[94],5)?" SUPPORTS_DUPLEX_SCAN":"", BIT(result[94],4)?" INTERLACED_DUPLEX_SCAN":"", BIT(result[94],3)?" SUPPORTS_TWO_MODE_ADF_SCANS":"", BIT(result[94],2)?" SUPPORTS_TUNE_SCAN_LENGTH":"", BIT(result[94],1)?" SUPPORTS_SWITCH_STRIP_FOR_DESKEW":"", /* Kodak i80 only */ BIT(result[94],0)?" SEARCHES_LEADING_SIDE_EDGE_BY_FIRMWARE":""); DBG (3, "attach: [95] ESA6:%s%s%s%s%s%s%s%s\n", BIT(result[95],7)?" SUPPORTS_PAPER_SIZE_AUTO_DETECTION":"", BIT(result[95],6)?" SUPPORTS_DO_HOUSEKEEPING":"", /* Kodak i80 only */ BIT(result[95],5)?" SUPPORTS_PAPER_LENGTH_SETTING":"", /* AV220, Kodak */ BIT(result[95],4)?" SUPPORTS_PRE_GAMMA_LINEAR_CORRECTION":"", BIT(result[95],3)?" SUPPORTS_PREFEEDING":"", /* OKI S9800 */ BIT(result[95],2)?" SUPPORTS_GET_BACKGROUND_RASTER":"", /* AV220 et.al. */ BIT(result[95],1)?" SUPPORTS_NVRAM_RESET":"", BIT(result[95],0)?" SUPPORTS_BATCH_SCAN":""); DBG (3, "attach: [128] ESA7:%s%s%s%s%s%s%s%s\n", BIT(result[128],7)?" SUPPORTS_ADF_CONTINUOUS":"", BIT(result[128],6)?" SUPPORTS_YCbCr_COLOR":"", BIT(result[128],5)?" SUPPORTS_ADF_3PASS":"", BIT(result[128],4)?" SUPPORTS_TUNE_SCAN_LENGTH_HORIZ":"", BIT(result[128],3)?" SUPPORTS_READ_WRITE_ABILITY_PARAMETER":"", BIT(result[128],2)?" SUPPORTS_JOB_CONTROL":"", BIT(result[128],1)?" SUPPORTS_INF_LENGTH":"", BIT(result[128],0)?" ULTRA_SONIC_DOUBLE_FEED_DETECTION":""); DBG (3, "attach: [129] YCbCr:%s%s%s%s%s%s%s%s\n", BIT(result[129],7)?" YCC4:2:0":"", BIT(result[129],6)?" YCC(profile2)":"", BIT(result[129],5)?" YCC(profile3)":"", BIT(result[129],4)?" YCC(profile4)":"", BIT(result[129],3)?" JPEG(profile1)":"", BIT(result[129],2)?" JPEG(profile2)":"", BIT(result[129],1)?" JPEG(profile3)":"", BIT(result[129],0)?" JPEG(profile4)":""); /* I have no idea how film scanner could reliably be detected -ReneR */ if (dev->hw->feature_type & AV_FILMSCANNER) { dev->scanner_type = AV_FILM; dev->sane.type = "film scanner"; } else if ( BIT(result[62],6) || BIT(result[62],4) ) { dev->scanner_type = AV_SHEETFEED; dev->sane.type = "sheetfed scanner"; } else { dev->scanner_type = AV_FLATBED; dev->sane.type = "flatbed scanner"; } dev->inquiry_new_protocol = BIT (result[39],2); dev->inquiry_asic_type = (int) result[91]; dev->inquiry_nvram_read = BIT(result[52],0); dev->inquiry_power_save_time = BIT(result[52],1); dev->inquiry_adf = BIT (result[62], 5); dev->inquiry_duplex = BIT (result[62], 2) || BIT (result[94], 5); dev->inquiry_duplex_interlaced = BIT(result[62],2) || BIT (result[94], 4); /* the first avision scanners (AV3200) do not set the interlaced bit */ if (dev->inquiry_duplex && dev->inquiry_asic_type < AV_ASIC_C6) dev->inquiry_duplex_interlaced = 1; dev->inquiry_paper_length = BIT (result[95], 5); dev->inquiry_batch_scan = BIT (result[95], 0); /* AV122, DM152 */ dev->inquiry_detect_accessories = BIT (result[93], 7); dev->inquiry_needs_calibration = BIT (result[50], 4); dev->inquiry_keeps_window = BIT (result[50], 1); if (Avision_Device_List [model_num].feature_type & AV_DOES_NOT_KEEP_WINDOW) dev->inquiry_keeps_window = 0; if (Avision_Device_List [model_num].feature_type & AV_DOES_KEEP_WINDOW) dev->inquiry_keeps_window = 1; dev->inquiry_needs_gamma = BIT (result[50], 3); dev->inquiry_keeps_gamma = BIT (result[50], 2); if (Avision_Device_List [model_num].feature_type & AV_DOES_NOT_KEEP_GAMMA) dev->inquiry_keeps_gamma = 0; if (Avision_Device_List [model_num].feature_type & AV_DOES_KEEP_GAMMA) dev->inquiry_keeps_gamma = 1; dev->inquiry_3x3_matrix = BIT (result[51], 1); dev->inquiry_needs_software_colorpack = BIT (result[50],5); dev->inquiry_needs_line_pack = BIT (result[94], 6); dev->inquiry_adf_need_mirror = BIT (result[51], 0); dev->inquiry_adf_bgr_order = BIT (result[93], 6); if (Avision_Device_List [model_num].feature_type & AV_ADF_BGR_ORDER_INVERT) dev->inquiry_adf_bgr_order = ! dev->inquiry_adf_bgr_order; dev->inquiry_light_detect = BIT (result[93], 2); dev->inquiry_light_control = BIT (result[50], 7); dev->inquiry_button_control = BIT (result[50], 6) | BIT (result[51],2); dev->inquiry_exposure_control = BIT(result[51],7); dev->inquiry_max_shading_target = get_double ( &(result[75]) ); dev->inquiry_color_boundary = result[54]; if (dev->inquiry_color_boundary == 0) dev->inquiry_color_boundary = 8; dev->inquiry_gray_boundary = result[55]; if (dev->inquiry_gray_boundary == 0) dev->inquiry_gray_boundary = 8; dev->inquiry_dithered_boundary = result[59]; if (dev->inquiry_dithered_boundary == 0) dev->inquiry_dithered_boundary = 8; dev->inquiry_thresholded_boundary = result[57]; if (dev->inquiry_thresholded_boundary == 0) dev->inquiry_thresholded_boundary = 8; dev->inquiry_line_difference = result[53]; /* compensation according to real world hardware */ switch (dev->inquiry_asic_type) { case AV_ASIC_C2: /* HP 5300 */ case AV_ASIC_C5: /* HP 53xx R2 */ dev->inquiry_line_difference /= 2; /* HP 5300 */ break; case AV_ASIC_C7: dev->inquiry_line_difference *= 2; /* AV610C2 */ break; default: ; } if (dev->inquiry_new_protocol) { dev->inquiry_optical_res = get_double ( &(result[89]) ); dev->inquiry_max_res = get_double ( &(result[44]) ); } else { dev->inquiry_optical_res = result[37] * 100; dev->inquiry_max_res = result[38] * 100; } /* fixup max res */ if (dev->inquiry_optical_res > dev->inquiry_max_res) { DBG (1, "Inquiry optical resolution > max_resolution, adjusting!\n"); dev->inquiry_max_res = dev->inquiry_optical_res; } if (dev->inquiry_optical_res == 0) { DBG (1, "Inquiry optical resolution is invalid!\n"); if (dev->hw->feature_type & AV_FORCE_FILM) dev->inquiry_optical_res = 2438; /* verify */ if (dev->scanner_type == AV_SHEETFEED) dev->inquiry_optical_res = 300; else dev->inquiry_optical_res = 600; } if (dev->inquiry_max_res == 0) { DBG (1, "Inquiry max resolution is invalid, using 1200 dpi!\n"); dev->inquiry_max_res = 1200; } DBG (1, "attach: optical resolution set to: %d dpi\n", dev->inquiry_optical_res); DBG (1, "attach: max resolution set to: %d dpi\n", dev->inquiry_max_res); if (BIT(result[60],6)) dev->inquiry_channels_per_pixel = 3; else if (BIT(result[60],7)) dev->inquiry_channels_per_pixel = 1; else if ( ((result[36] >> 4) & 0x7) > 0) dev->inquiry_channels_per_pixel = 3; else dev->inquiry_channels_per_pixel = 1; if (BIT(result[61],1)) dev->inquiry_bits_per_channel = 16; else if (BIT(result[61],2)) dev->inquiry_bits_per_channel = 12; else if (BIT(result[61],3)) dev->inquiry_bits_per_channel = 10; else if (BIT(result[61],4)) dev->inquiry_bits_per_channel = 8; else if (BIT(result[61],5)) dev->inquiry_bits_per_channel = 6; else if (BIT(result[61],6)) dev->inquiry_bits_per_channel = 4; else if (BIT(result[61],7)) dev->inquiry_bits_per_channel = 1; else dev->inquiry_bits_per_channel = 8; /* default for old scanners */ if (dev->hw->feature_type & AV_12_BIT_MODE) dev->inquiry_bits_per_channel = 12; if (! (dev->hw->feature_type & AV_GRAY_MODES)) dev->inquiry_no_gray_modes = BIT(result[93],5); DBG (1, "attach: max channels per pixel: %d, max bits per channel: %d\n", dev->inquiry_channels_per_pixel, dev->inquiry_bits_per_channel); if (! (dev->hw->feature_type & AV_NO_BUTTON)) dev->inquiry_buttons = result[92]; /* get max x/y ranges for the different modes */ { double base_dpi; /* TODO: make int */ if (dev->scanner_type != AV_FILM) { base_dpi = AVISION_BASE_RES; } else { /* ZP: The right number is 2820, whether it is 40-41, 42-43, 44-45, * 46-47 or 89-90 I don't know but I would bet for the last ! * ReneR: OK. We use it via the optical_res which we need anyway ... */ base_dpi = dev->inquiry_optical_res; } /* .1 to slightly increase the size to match the one of American standard paper formats that would otherwise be .1 mm too large to scan ... */ dev->inquiry_x_ranges [AV_NORMAL_DIM] = (double)get_double (&(result[81])) * MM_PER_INCH / base_dpi + .1; dev->inquiry_y_ranges [AV_NORMAL_DIM] = (double)get_double (&(result[83])) * MM_PER_INCH / base_dpi; dev->inquiry_x_ranges [AV_TRANSPARENT_DIM] = (double)get_double (&(result[77])) * MM_PER_INCH / base_dpi + .1; dev->inquiry_y_ranges [AV_TRANSPARENT_DIM] = (double)get_double (&(result[79])) * MM_PER_INCH / base_dpi; dev->inquiry_x_ranges [AV_ADF_DIM] = (double)get_double (&(result[85])) * MM_PER_INCH / base_dpi + .1; dev->inquiry_y_ranges [AV_ADF_DIM] = (double)get_double (&(result[87])) * MM_PER_INCH / base_dpi; } dev->inquiry_tune_scan_length = BIT(result[94],2); if (Avision_Device_List [model_num].feature_type & AV_NO_TUNE_SCAN_LENGTH) dev->inquiry_tune_scan_length = 0; dev->inquiry_background_raster = BIT(result[95],2); if (dev->hw->feature_type & AV_NO_BACKGROUND) dev->inquiry_background_raster = 0; if (dev->inquiry_background_raster) { dev->inquiry_background_raster_pixel = get_double(&(result[85])) * dev->inquiry_optical_res / AVISION_BASE_RES; } /* check if x/y ranges are valid :-((( */ { source_mode_dim mode; for (mode = AV_NORMAL_DIM; mode < AV_SOURCE_MODE_DIM_LAST; ++ mode) { if (dev->inquiry_x_ranges [mode] != 0 && dev->inquiry_y_ranges [mode] != 0) { DBG (3, "attach: x/y-range for mode %d is valid!\n", mode); if (force_a4) { DBG (1, "attach: \"force_a4\" found! Using default (ISO A4).\n"); dev->inquiry_x_ranges [mode] = A4_X_RANGE * MM_PER_INCH; dev->inquiry_y_ranges [mode] = A4_Y_RANGE * MM_PER_INCH; } else if (force_a3) { DBG (1, "attach: \"force_a3\" found! Using default (ISO A3).\n"); dev->inquiry_x_ranges [mode] = A3_X_RANGE * MM_PER_INCH; dev->inquiry_y_ranges [mode] = A3_Y_RANGE * MM_PER_INCH; } } else /* mode is invalid */ { DBG (1, "attach: x/y-range for mode %d is invalid! Using a default.\n", mode); if (dev->hw->feature_type & AV_FORCE_A3) { dev->inquiry_x_ranges [mode] = A3_X_RANGE * MM_PER_INCH; dev->inquiry_y_ranges [mode] = A3_Y_RANGE * MM_PER_INCH; } else if (dev->hw->feature_type & AV_FORCE_FILM) { dev->inquiry_x_ranges [mode] = FILM_X_RANGE * MM_PER_INCH; dev->inquiry_y_ranges [mode] = FILM_Y_RANGE * MM_PER_INCH; } else { dev->inquiry_x_ranges [mode] = A4_X_RANGE * MM_PER_INCH; if (dev->scanner_type == AV_SHEETFEED) dev->inquiry_y_ranges [mode] = SHEETFEED_Y_RANGE * MM_PER_INCH; else dev->inquiry_y_ranges [mode] = A4_Y_RANGE * MM_PER_INCH; } } DBG (1, "attach: Mode %d range is now: %f x %f mm.\n", mode, dev->inquiry_x_ranges [mode], dev->inquiry_y_ranges [mode]); } /* end for all modes */ } /* We need a bigger buffer for USB devices, since they seem to have a firmware bug and do not support reading the calibration data in tiny chunks */ if (av_con.connection_type == AV_USB) dev->scsi_buffer_size = 1024 * 1024; /* or 0x10000, used by AV Windows driver during background raster read, ... ? */ else dev->scsi_buffer_size = sanei_scsi_max_request_size; if (dev->inquiry_asic_type > AV_ASIC_C7 && dev->inquiry_asic_type < AV_ASIC_OA980) dev->read_stripe_size = 16; else if (dev->inquiry_asic_type >= AV_ASIC_C5) dev->read_stripe_size = 32; else /* tested on AV3200 with it's max of 300dpi @color */ dev->read_stripe_size = 8; /* maybe made dynamic on scan res ... */ /* normally the data_dq is 0x0a0d - but some newer scanner hang with it ... */ if (dev->inquiry_new_protocol) /* TODO: match on ASIC? which model hung? */ dev->data_dq = 0x0a0d; else dev->data_dq = 0; avision_close (&av_con); ++ num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; close_scanner_and_return: avision_close (&av_con); return status; } static SANE_Status get_tune_scan_length (Avision_Scanner* s) { SANE_Status status; int i; struct command_read rcmd; size_t size; struct max_value { uint8_t max [2]; } payload; /* turn on the light */ DBG (3, "get_tune_scan_length:\n"); memset (&rcmd, 0, sizeof (rcmd)); size = sizeof (payload); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0xD2; /* Read General Ability/Parameter */ for (i = 1; i <= 8; ++i) { memset (&payload, 0, sizeof (payload)); set_double (rcmd.datatypequal, i); /* type */ set_triple (rcmd.transferlen, size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, &payload, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "get_tune_scan_length: read %d failed (%s)\n", i, sane_strstatus (status)); return status; } DBG (1, "get_tune_scan_length: %d: %d\n", i, get_double (payload.max)); } return SANE_STATUS_GOOD; } static SANE_Status send_tune_scan_length (Avision_Scanner* s) { int top, bottom; SANE_Status status; size_t size; struct command_send scmd; struct truncate_attach { uint8_t vertical [2]; /* uint8_t horizontal [2]; not send by the Windows driver, yet */ } payload; DBG (3, "send_tune_scan_length:\n"); memset (&scmd, 0, sizeof (scmd)); size = sizeof (payload); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = 0x96; /* Attach/Truncate head(left) of scan length */ set_triple (scmd.transferlen, size); /* the SPEC says optical DPI, but real world measuring suggests it is 1200 as in the window descriptor */ top = 1200 * SANE_UNFIX (s->val[OPT_OVERSCAN_TOP].w) / MM_PER_INCH; DBG (3, "send_tune_scan_length: top: %d\n", top); set_double (scmd.datatypequal, 0x0001); /* attach, 0x000 is shorten */ set_double (payload.vertical, top); /* set_double (payload.horizontal, 0); */ /* we alway send it, even for 0 as the scanner keeps it in RAM and previous runs could already have set something */ status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), &payload, sizeof (payload), 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "send_tune_scan_length: send top/left failed (%s)\n", sane_strstatus (status)); return status; } scmd.datatypecode = 0x95; /* Attach/Truncate tail(right) of scan length */ bottom = 1200 * SANE_UNFIX (s->val[OPT_OVERSCAN_BOTTOM].w) / MM_PER_INCH; DBG (3, "send_tune_scan_length: bottom: %d\n", bottom); set_double (payload.vertical, bottom); /*set_double (payload.horizontal, 0); */ size = sizeof (payload); status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), &payload, sizeof (payload), 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "send_tune_scan_length: send bottom/right failed (%s)\n", sane_strstatus (status)); return status; } return SANE_STATUS_GOOD; } static SANE_Status additional_probe (Avision_Scanner* s) { Avision_Device* dev = s->hw; /* we should wait until the scanner is ready before we perform further actions */ SANE_Status status; /* try to retrieve additional accessory information */ if (dev->inquiry_detect_accessories) { status = get_accessories_info (s); if (status != SANE_STATUS_GOOD) return status; } /* for a film scanner try to retrieve additional frame information */ if (dev->scanner_type == AV_FILM) { status = get_frame_info (s); if (status != SANE_STATUS_GOOD) return status; } /* no scanner did support this so far: tried on AV220, DM152 */ if (0 && dev->inquiry_duplex) { status = get_duplex_info (s); if (status != SANE_STATUS_GOOD) return status; } /* get overscan ("head/tail tune") information: hangs AV220, zeros on AV122 */ if (0 && dev->inquiry_tune_scan_length) { status = get_tune_scan_length (s); if (status != SANE_STATUS_GOOD) return status; } /* create dynamic *-mode entries */ if (!dev->inquiry_no_gray_modes) { if (dev->inquiry_bits_per_channel > 0) { add_color_mode (dev, AV_THRESHOLDED, SANE_VALUE_SCAN_MODE_LINEART); add_color_mode (dev, AV_DITHERED, "Dithered"); } if (dev->inquiry_bits_per_channel >= 8) add_color_mode (dev, AV_GRAYSCALE, SANE_VALUE_SCAN_MODE_GRAY); if (dev->inquiry_bits_per_channel == 12) add_color_mode (dev, AV_GRAYSCALE12, "12bit Gray"); if (dev->inquiry_bits_per_channel >= 16) add_color_mode (dev, AV_GRAYSCALE16, "16bit Gray"); } if (dev->inquiry_channels_per_pixel > 1) { add_color_mode (dev, AV_TRUECOLOR, SANE_VALUE_SCAN_MODE_COLOR); if (dev->inquiry_bits_per_channel == 12) add_color_mode (dev, AV_TRUECOLOR12, "12bit Color"); if (dev->inquiry_bits_per_channel >= 16) add_color_mode (dev, AV_TRUECOLOR16, "16bit Color"); } /* now choose the default mode - avoiding the 12/16 bit modes */ dev->color_list_default = last_color_mode (dev); if (dev->inquiry_bits_per_channel > 8 && dev->color_list_default > 0) { dev->color_list_default--; } if (dev->scanner_type == AV_SHEETFEED) { add_source_mode (dev, AV_ADF, "ADF Front"); } else { add_source_mode (dev, AV_NORMAL, "Normal"); if (dev->inquiry_light_box) add_source_mode (dev, AV_TRANSPARENT, "Transparency"); if (dev->inquiry_adf) add_source_mode (dev, AV_ADF, "ADF Front"); } if (dev->inquiry_duplex) { if (dev->inquiry_duplex_interlaced && !(dev->hw->feature_type & AV_NO_REAR)) add_source_mode (dev, AV_ADF_REAR, "ADF Back"); add_source_mode (dev, AV_ADF_DUPLEX, "ADF Duplex"); } return SANE_STATUS_GOOD; } static SANE_Status get_calib_format (Avision_Scanner* s, struct calibration_format* format) { SANE_Status status; struct command_read rcmd; uint8_t result [32]; size_t size; DBG (3, "get_calib_format:\n"); size = sizeof (result); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x60; /* get calibration format */ set_double (rcmd.datatypequal, s->hw->data_dq); set_triple (rcmd.transferlen, size); DBG (3, "get_calib_format: read_data: %lu bytes\n", (u_long) size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result) ) { DBG (1, "get_calib_format: read calib. info failed (%s)\n", sane_strstatus (status) ); return status; } debug_print_calib_format (3, "get_calib_format", result); format->pixel_per_line = get_double (&(result[0])); format->bytes_per_channel = result[2]; format->lines = result[3]; format->flags = result[4]; format->ability1 = result[5]; format->r_gain = result[6]; format->g_gain = result[7]; format->b_gain = result[8]; format->r_shading_target = get_double (&(result[9])); format->g_shading_target = get_double (&(result[11])); format->b_shading_target = get_double (&(result[13])); format->r_dark_shading_target = get_double (&(result[15])); format->g_dark_shading_target = get_double (&(result[17])); format->b_dark_shading_target = get_double (&(result[19])); /* now translate to normal! */ /* firmware return R--RG--GB--B with 3 line count */ /* software format it as 1 line if true color scan */ /* only line interleave format to be supported */ if (color_mode_is_color (s->c_mode) || BIT(format->ability1, 3)) { format->channels = 3; format->lines /= 3; /* line interleave */ } else format->channels = 1; DBG (3, "get_calib_format: channels: %d\n", format->channels); return SANE_STATUS_GOOD; } static SANE_Status get_calib_data (Avision_Scanner* s, uint8_t data_type, uint8_t* calib_data, size_t calib_size) { SANE_Status status; uint8_t *calib_ptr; size_t get_size, data_size, chunk_size; struct command_read rcmd; chunk_size = calib_size; DBG (3, "get_calib_data: type %x, size %lu, chunk_size: %lu\n", data_type, (u_long) calib_size, (u_long) chunk_size); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = data_type; set_double (rcmd.datatypequal, s->hw->data_dq); calib_ptr = calib_data; get_size = chunk_size; data_size = calib_size; while (data_size) { if (get_size > data_size) get_size = data_size; read_constrains(s, get_size); set_triple (rcmd.transferlen, get_size); DBG (3, "get_calib_data: Reading %ld bytes calibration data\n", (long)get_size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, calib_ptr, &get_size); if (status != SANE_STATUS_GOOD) { DBG (1, "get_calib_data: read data failed (%s)\n", sane_strstatus (status)); return status; } DBG (3, "get_calib_data: Got %ld bytes calibration data\n", (long)get_size); data_size -= get_size; calib_ptr += get_size; } return SANE_STATUS_GOOD; } static SANE_Status set_calib_data (Avision_Scanner* s, struct calibration_format* format, uint8_t* dark_data, uint8_t* white_data) { Avision_Device* dev = s->hw; const int elements_per_line = format->pixel_per_line * format->channels; SANE_Status status; uint8_t send_type; uint16_t send_type_q; struct command_send scmd; int i; DBG (3, "set_calib_data:\n"); send_type = 0x82; /* download calibration data */ /* do we use a color mode? */ if (format->channels > 1) { send_type_q = 0x12; /* color calib data */ } else { if (dev->hw->feature_type & AV_GRAY_CALIB_BLUE) send_type_q = 0x2; /* gray/bw calib data on the blue channel (AV610) */ else send_type_q = 0x11; /* gray/bw calib data */ } memset (&scmd, 0x00, sizeof (scmd)); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = send_type; /* data corrections due to dark calibration data merge */ if (BIT (format->ability1, 2) ) { DBG (3, "set_calib_data: merging dark calibration data\n"); for (i = 0; i < elements_per_line; ++i) { uint16_t value_orig = get_double_le (white_data + i*2); uint16_t value_new = value_orig; value_new &= 0xffc0; value_new |= (get_double_le (dark_data + i*2) >> 10) & 0x3f; DBG (9, "set_calib_data: element %d, dark difference %d\n", i, value_orig - value_new); set_double_le ((white_data + i*2), value_new); } } /* send data in one command? */ /* FR: HP5370 reports one-pass, but needs multi (or other format in single) */ if (format->channels == 1 || ( ( (dev->hw->feature_type & AV_ONE_CALIB_CMD) || ! BIT(format->ability1, 0) ) && ! (dev->hw->feature_type & AV_MULTI_CALIB_CMD) ) ) /* one command (most scanners) */ { size_t send_size = elements_per_line * 2; DBG (3, "set_calib_data: all channels in one command\n"); DBG (3, "set_calib_data: send_size: %lu\n", (u_long) send_size); memset (&scmd, 0, sizeof (scmd) ); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = send_type; set_double (scmd.datatypequal, send_type_q); set_triple (scmd.transferlen, send_size); status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), (char*) white_data, send_size, 0, 0); /* not return immediately to free mem at the end */ } else /* send data channel by channel (some USB ones) */ { int conv_out_size = format->pixel_per_line * 2; uint16_t* conv_out_data; /* here it is save to use 16bit data since we only move whole words around */ DBG (3, "set_calib_data: channels in single commands\n"); conv_out_data = (uint16_t*) malloc (conv_out_size); if (!conv_out_data) { status = SANE_STATUS_NO_MEM; } else { int channel; for (channel = 0; channel < 3; ++ channel) { int i; /* no need for endianness handling since whole word copy */ uint16_t* casted_avg_data = (uint16_t*) white_data; DBG (3, "set_calib_data_calibration: channel: %i\n", channel); for (i = 0; i < format->pixel_per_line; ++ i) conv_out_data [i] = casted_avg_data [i * 3 + channel]; DBG (3, "set_calib_data: sending %i bytes now\n", conv_out_size); memset (&scmd, 0, sizeof (scmd)); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = send_type; /* send calibration data */ set_double (scmd.datatypequal, channel); set_triple (scmd.transferlen, conv_out_size); status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), conv_out_data, conv_out_size, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (3, "set_calib_data: send_data failed (%s)\n", sane_strstatus (status)); /* not return immediately to free mem at the end */ } } /* end for each channel */ free (conv_out_data); } /* end else send calib data*/ } return SANE_STATUS_GOOD; } /* Sort data pixel by pixel and average first 2/3 of the data. The caller has to free return pointer. R,G,B pixels interleave to R,G,B line interleave. The input data data is in 16 bits little endian, always. That is a = b[1] << 8 + b[0] in all system. We convert it to SCSI high-endian (big-endian) since we use it all over the place anyway .... - Sorry for this mess. */ static uint8_t* sort_and_average (struct calibration_format* format, uint8_t* data) { const int elements_per_line = format->pixel_per_line * format->channels; const int stride = format->bytes_per_channel * elements_per_line; int i, line; uint8_t *sort_data, *avg_data; DBG (1, "sort_and_average:\n"); if (!format || !data) return NULL; sort_data = malloc (format->lines * 2); if (!sort_data) return NULL; avg_data = malloc (elements_per_line * 2); if (!avg_data) { free (sort_data); return NULL; } /* for each pixel */ for (i = 0; i < elements_per_line; ++ i) { uint8_t* ptr1 = data + i * format->bytes_per_channel; uint16_t temp; /* copy all lines for pixel i into the linear array sort_data */ for (line = 0; line < format->lines; ++ line) { uint8_t* ptr2 = ptr1 + line * stride; /* pixel */ if (format->bytes_per_channel == 1) temp = 0xffff * *ptr2 / 255; else temp = get_double_le (ptr2); /* little-endian! */ set_double ((sort_data + line*2), temp); /* store big-endian */ /* DBG (7, "ReneR to sort: %x\n", temp); */ } temp = bubble_sort (sort_data, format->lines); /* DBG (7, "ReneR averaged: %x\n", temp); */ set_double ((avg_data + i*2), temp); /* store big-endian */ } free ((void *) sort_data); return avg_data; } /* shading data is 16bits little endian format when send/read from firmware */ static void compute_dark_shading_data (Avision_Scanner* s, struct calibration_format* format, uint8_t* data) { uint16_t map_value = DEFAULT_DARK_SHADING; uint16_t rgb_map_value[3]; int elements_per_line, i; DBG (3, "compute_dark_shading_data:\n"); if (s->hw->inquiry_max_shading_target != INVALID_DARK_SHADING) map_value = s->hw->inquiry_max_shading_target << 8; rgb_map_value[0] = format->r_dark_shading_target; rgb_map_value[1] = format->g_dark_shading_target; rgb_map_value[2] = format->b_dark_shading_target; for (i = 0; i < format->channels; ++i) { if (rgb_map_value[i] == INVALID_DARK_SHADING) rgb_map_value[i] = map_value; } if (format->channels == 1) { /* set to green, TODO: should depend on color drop-out and true-gray -ReneR */ rgb_map_value[0] = rgb_map_value[1] = rgb_map_value[2] = rgb_map_value[1]; } elements_per_line = format->pixel_per_line * format->channels; /* Check line interleave or pixel interleave. */ /* It seems no ASIC use line interleave right now. */ /* Avision SCSI protocol document has bad description. */ for (i = 0; i < elements_per_line; ++i) { uint16_t tmp_data = get_double_le((data + i*2)); if (tmp_data > rgb_map_value[i % 3]) { set_double ((data + i*2), tmp_data - rgb_map_value[i % 3]); } else { set_double ((data + i*2), 0); } } } static void compute_white_shading_data (Avision_Scanner* s, struct calibration_format* format, uint8_t* data) { int i; uint16_t inquiry_mst = DEFAULT_WHITE_SHADING; uint16_t mst[3]; int elements_per_line = format->pixel_per_line * format->channels; /* debug counter */ int values_invalid = 0; int values_limitted = 0; DBG (3, "compute_white_shading_data:\n"); if (s->hw->inquiry_max_shading_target != INVALID_WHITE_SHADING) inquiry_mst = s->hw->inquiry_max_shading_target << 4; mst[0] = format->r_shading_target; mst[1] = format->g_shading_target; mst[2] = format->b_shading_target; for (i = 0; i < 3; ++i) { if (mst[i] == INVALID_WHITE_SHADING) /* mst[i] > MAX_WHITE_SHADING) */ { DBG (3, "compute_white_shading_data: target %d invalid (%x) using inquiry (%x)\n", i, mst[i], inquiry_mst); mst[i] = inquiry_mst; } /* some firmware versions seems to return the bytes swapped? */ else if (mst[i] < 0x110) { uint8_t* swap_mst = (uint8_t*) &mst[i]; uint8_t low_nibble_mst = swap_mst [0]; swap_mst [0] = swap_mst[1]; swap_mst [1] = low_nibble_mst; DBG (3, "compute_white_shading_data: target %d: bytes swapped.\n", i); } if (mst[i] < DEFAULT_WHITE_SHADING / 2) { DBG (3, "compute_white_shading_data: target %d: too low (%d) using default (%d).\n", i, mst[i], DEFAULT_WHITE_SHADING); mst[i] = DEFAULT_WHITE_SHADING; } else DBG (3, "compute_white_shading_data: target %d: %x\n", i, mst[0]); } /* some Avision example code was present here until SANE/Avision * BUILD 57. */ if (format->channels == 1) { /* set to green, TODO: should depend on color drop-out and true-gray -ReneR */ mst[0] = mst[1] = mst[2] = mst[1]; } /* calculate calibration data */ for (i = 0; i < elements_per_line; ++ i) { int result; /* calculate calibration value for pixel i */ uint16_t tmp_data = get_double((data + i*2)); if (tmp_data == INVALID_WHITE_SHADING) { tmp_data = DEFAULT_WHITE_SHADING; ++ values_invalid; } result = ( (int)mst[i % 3] * WHITE_MAP_RANGE / (tmp_data + 0.5)); /* sanity check for over-amplification, clipping */ if (result > MAX_WHITE_SHADING) { result = WHITE_MAP_RANGE; ++ values_limitted; } /* for visual debugging ... */ if (static_calib_list [i % 3] == SANE_TRUE) result = 0xA000; /* the output to the scanner will be 16 bit little endian again */ set_double_le ((data + i*2), result); } DBG (3, "compute_white_shading_data: %d invalid, %d limited\n", values_invalid, values_limitted); } /* old_r_calibration was here until SANE/Avision BUILD 90 */ static SANE_Status normal_calibration (Avision_Scanner* s) { SANE_Status status; struct calibration_format calib_format; int calib_data_size, calib_bytes_per_line; uint8_t read_type; uint8_t *calib_tmp_data; DBG (1, "normal_calibration:\n"); /* get calibration format and data */ status = get_calib_format (s, &calib_format); if (status != SANE_STATUS_GOOD) return status; /* check if need do calibration */ if (calib_format.flags != 1) { DBG (1, "normal_calibration: Scanner claims no calibration needed -> skipped!\n"); return SANE_STATUS_GOOD; } /* calculate calibration data size for read from scanner */ /* size = lines * bytes_per_channel * pixels_per_line * channel */ calib_bytes_per_line = calib_format.bytes_per_channel * calib_format.pixel_per_line * calib_format.channels; calib_data_size = calib_format.lines * calib_bytes_per_line; calib_tmp_data = malloc (calib_data_size); if (!calib_tmp_data) return SANE_STATUS_NO_MEM; /* check if we need to do dark calibration (shading) */ if (BIT(calib_format.ability1, 3)) { DBG (1, "normal_calibration: reading dark data\n"); /* read dark calib data */ status = get_calib_data (s, 0x66, calib_tmp_data, calib_data_size); if (status != SANE_STATUS_GOOD) { free (calib_tmp_data); return status; } /* process dark data: sort and average. */ if (s->dark_avg_data) { free (s->dark_avg_data); s->dark_avg_data = 0; } s->dark_avg_data = sort_and_average (&calib_format, calib_tmp_data); if (!s->dark_avg_data) { free (calib_tmp_data); return SANE_STATUS_NO_MEM; } compute_dark_shading_data (s, &calib_format, s->dark_avg_data); } /* do we use a color mode? */ if (calib_format.channels > 1) { DBG (3, "normal_calibration: using color calibration\n"); read_type = 0x62; /* read color calib data */ } else { DBG (3, "normal_calibration: using gray calibration\n"); read_type = 0x61; /* gray calib data */ } /* do white calibration: read gray or color data */ status = get_calib_data (s, read_type, calib_tmp_data, calib_data_size); if (status != SANE_STATUS_GOOD) { free (calib_tmp_data); return status; } if (0) /* debug */ { FILE* f = NULL; f = fopen ("calibration-white.pnm", "w"); write_pnm_header (f, AV_GRAYSCALE, calib_format.bytes_per_channel * 8, calib_format.pixel_per_line, calib_format.lines * calib_format.channels); fwrite (calib_tmp_data, 1, calib_data_size, f); fclose (f); } if (s->white_avg_data) { free (s->white_avg_data); s->white_avg_data = 0; } s->white_avg_data = sort_and_average (&calib_format, calib_tmp_data); if (!s->white_avg_data) { free (calib_tmp_data); return SANE_STATUS_NO_MEM; } /* decrease white average data (if dark average data is present) */ if (s->dark_avg_data) { int elements_per_line = calib_format.pixel_per_line * calib_format.channels; int i; DBG (1, "normal_calibration: dark data present - decreasing white average data\n"); for (i = 0; i < elements_per_line; ++ i) { s->white_avg_data[i] -= s->dark_avg_data[i]; } } compute_white_shading_data (s, &calib_format, s->white_avg_data); status = set_calib_data (s, &calib_format, s->dark_avg_data, s->white_avg_data); free (calib_tmp_data); return status; } /* next was taken from the GIMP and is a bit modified ... ;-) * original Copyright (C) 1995 Spencer Kimball and Peter Mattis */ static double brightness_contrast_func (double brightness, double contrast, double value) { double nvalue; double power; /* apply brightness */ if (brightness < 0.0) value = value * (1.0 + brightness); else value = value + ((1.0 - value) * brightness); /* apply contrast */ if (contrast < 0.0) { if (value > 0.5) nvalue = 1.0 - value; else nvalue = value; if (nvalue < 0.0) nvalue = 0.0; nvalue = 0.5 * pow (nvalue * 2.0 , (double) (1.0 + contrast)); if (value > 0.5) value = 1.0 - nvalue; else value = nvalue; } else { if (value > 0.5) nvalue = 1.0 - value; else nvalue = value; if (nvalue < 0.0) nvalue = 0.0; power = (contrast == 1.0) ? 127 : 1.0 / (1.0 - contrast); nvalue = 0.5 * pow (2.0 * nvalue, power); if (value > 0.5) value = 1.0 - nvalue; else value = nvalue; } return value; } static SANE_Status send_gamma (Avision_Scanner* s) { Avision_Device* dev = s->hw; SANE_Status status = SANE_STATUS_GOOD; int invert_table = 0; size_t gamma_table_raw_size; size_t gamma_table_size; size_t gamma_values; struct command_send scmd; uint8_t *gamma_data; int color; /* current color */ size_t i; /* big table index */ size_t j; /* little table index */ size_t k; /* big table sub index */ double v1, v2; double brightness; double contrast; if (dev->inquiry_asic_type != AV_ASIC_OA980) invert_table = (s->c_mode == AV_THRESHOLDED) || (s->c_mode == AV_DITHERED); switch (dev->inquiry_asic_type) { case AV_ASIC_Cx: case AV_ASIC_C1: gamma_table_raw_size = 4096; gamma_table_size = 2048; break; case AV_ASIC_C5: gamma_table_raw_size = 256; gamma_table_size = 256; break; break; case AV_ASIC_OA980: gamma_table_raw_size = 4096; gamma_table_size = 4096; break; case AV_ASIC_OA982: gamma_table_raw_size = 256; gamma_table_size = 256; break; default: gamma_table_raw_size = 512; /* SPEC claims: 256 ... ? */ gamma_table_size = 512; } gamma_values = gamma_table_size / 256; DBG (3, "send_gamma: table_raw_size: %lu, table_size: %lu\n", (u_long) gamma_table_raw_size, (u_long) gamma_table_size); DBG (3, "send_gamma: values: %lu, invert_table: %d\n", (u_long) gamma_values, invert_table); /* prepare for emulating contrast, brightness ... via the gamma-table */ brightness = SANE_UNFIX (s->val[OPT_BRIGHTNESS].w); brightness /= 100; contrast = SANE_UNFIX (s->val[OPT_CONTRAST].w); contrast /= 100; DBG (3, "send_gamma: brightness: %f, contrast: %f\n", brightness, contrast); gamma_data = malloc (gamma_table_raw_size); if (!gamma_data) return SANE_STATUS_NO_MEM; memset (&scmd, 0, sizeof (scmd) ); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = 0x81; /* 0x81 for download gamma table */ set_triple (scmd.transferlen, gamma_table_raw_size); for (color = 0; color < 3 && status == SANE_STATUS_GOOD; ++ color) { /* color: 0=red; 1=green; 2=blue */ set_double (scmd.datatypequal, color); i = 0; /* big table index */ for (j = 0; j < 256; ++ j) /* little table index */ { /* calculate mode dependent values v1 and v2 * v1 <- current value for table * v2 <- next value for table (for interpolation) */ switch (s->c_mode) { case AV_TRUECOLOR: case AV_TRUECOLOR12: case AV_TRUECOLOR16: { v1 = (double) s->gamma_table [1 + color][j]; if (j == 255) v2 = (double) v1; else v2 = (double) s->gamma_table [1 + color][j + 1]; } break; default: /* for all other modes: */ { v1 = (double) s->gamma_table [0][j]; if (j == 255) v2 = (double) v1; else v2 = (double) s->gamma_table [0][j + 1]; } } /*end switch */ /* Emulate brightness and contrast (at least the Avision AV6[2,3]0 * as well as many others do not have a hardware implementation, * --$. The function was taken from the GIMP source - maybe I'll * optimize it in the future (when I have spare time). */ v1 /= 255; v2 /= 255; v1 = (brightness_contrast_func (brightness, contrast, v1) ); v2 = (brightness_contrast_func (brightness, contrast, v2) ); v1 *= 255; v2 *= 255; if (invert_table) { v1 = 255 - v1; v2 = 255 - v2; if (v1 <= 0) v1 = 0; if (v2 <= 0) v2 = 0; } for (k = 0; k < gamma_values; ++ k, ++ i) { gamma_data [i] = (uint8_t) (((v1 * (gamma_values - k)) + (v2 * k) ) / (double) gamma_values); } } /* fill the gamma table - (e.g.) if 11bit (old protocol) table */ { size_t t_i = i-1; if (i < gamma_table_raw_size) { DBG (4, "send_gamma: (old protocol) - filling the table.\n"); for ( ; i < gamma_table_raw_size; ++ i) gamma_data [i] = gamma_data [t_i]; } } DBG (4, "send_gamma: sending %lu bytes gamma table.\n", (u_long) gamma_table_raw_size); status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), gamma_data, gamma_table_raw_size, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "send_gamma: gamma table upload failed: %s\n", sane_strstatus (status)); } } free (gamma_data); return status; } static SANE_Status send_3x3_matrix (Avision_Scanner* s) { SANE_Status status; #define SIGN_BIT 0x1000 #define INT_PART 10 struct matrix_cmd { struct command_send scmd; struct matrix_3x3 matrix; } cmd; /* 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 04 00 */ int i, a_i; static const double c5_matrix[] = { 1.000, 0.000, 0.000, 0.000, 1.000, 0.000, 0.000, 0.000, 1.000 }; double a_f, b_f; uint16_t m; DBG (3, "send_3x3_matrix:\n"); memset (&cmd, 0, sizeof (cmd)); for (i = 0; i < 9; i++) { m = 0; a_f = c5_matrix[i]; if (a_f < 0) { m |= SIGN_BIT; a_f = -a_f; } a_i = (int) a_f; /* integer */ b_f = a_f - (double) a_i; /* float */ m |= ((a_i & 0x3) << INT_PART); m |= (uint16_t) (b_f * 1024); set_double (((uint8_t*)(&cmd.matrix.v[i])), m); } cmd.scmd.opc = AVISION_SCSI_SEND; cmd.scmd.datatypecode = 0x83; /* 0x83 for 3x3 color matrix */ set_triple (cmd.scmd.transferlen, sizeof (struct matrix_3x3)); if (1) { DBG (3, "send_3x3_matrix: sending matrix split into two commands\n"); status = avision_cmd (&s->av_con, &cmd.scmd, sizeof (cmd.scmd), &cmd.matrix, sizeof(cmd.matrix), 0, 0); } else { DBG (3, "send_3x3_matrix: sending matrix in one command\n"); status = avision_cmd (&s->av_con, &cmd, sizeof (cmd), 0, 0, 0, 0); } return status; } static SANE_Status get_acceleration_info (Avision_Scanner* s, struct acceleration_info* info) { SANE_Status status; struct command_read rcmd; uint8_t result [24]; size_t size; DBG (3, "get_acceleration_info:\n"); size = sizeof (result); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x6c; /* get acceleration information */ set_double (rcmd.datatypequal, s->hw->data_dq); set_triple (rcmd.transferlen, size); DBG (3, "get_acceleration_info: read_data: %lu bytes\n", (u_long) size); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result) ) { DBG (1, "get_acceleration_info: read accel. info failed (%s)\n", sane_strstatus (status) ); return status; } debug_print_accel_info (3, "get_acceleration_info", result); info->total_steps = get_double (&(result[0])); info->stable_steps = get_double (&(result[2])); info->table_units = get_quad (&(result[4])); info->base_units = get_quad (&(result[8])); info->start_speed = get_double (&(result[12])); info->target_speed = get_double (&(result[14])); info->ability = result[16]; info->table_count = result[17]; return SANE_STATUS_GOOD; } static SANE_Status send_acceleration_table (Avision_Scanner* s) { SANE_Status status; struct command_send scmd; int table = 0; int i; struct acceleration_info accel_info = accel_info; uint8_t* table_data; DBG (3, "send_acceleration_table:\n"); do { status = get_acceleration_info (s, &accel_info); if (accel_info.table_count == 0) { DBG (3, "send_acceleration_table: device does not need tables\n"); return SANE_STATUS_GOOD; } if (accel_info.target_speed > accel_info.start_speed || accel_info.target_speed == 0 || accel_info.total_steps <= accel_info.stable_steps) { DBG (1, "send_acceleration_table: table does not look right.\n"); return SANE_STATUS_INVAL; } if (accel_info.ability != 0) { DBG (1, "send_acceleration_table: ability non-zero - insert code\n"); return SANE_STATUS_INVAL; } /* so far I assume we have one byte tables as used in the C6 ASIC ... */ table_data = malloc (accel_info.total_steps + 1000); memset (&scmd, 0x00, sizeof (scmd)); scmd.opc = AVISION_SCSI_SEND; scmd.datatypecode = 0x6c; /* send acceleration table */ set_double (scmd.datatypequal, table); set_triple (scmd.transferlen, accel_info.total_steps); /* construct the table - Warning: This code is derived from Avision sample code and is a bit scary! I have no idea why the scanner needs such a dumb table and also do not know /why/ it has to be constructed this way. "Works for me" -ReneR */ { float low_lim = 0.001; float up_lim = 1.0; uint16_t accel_steps = accel_info.total_steps - accel_info.stable_steps + 1; /* acceleration ramp */ while ((up_lim - low_lim) > 0.0001) { float mid = (up_lim + low_lim) / 2; /* accel rate */ uint16_t now_count = accel_info.start_speed; uint16_t i = 0; float now_count_f = now_count; table_data [i++] = (uint8_t) accel_info.start_speed; while (now_count != accel_info.target_speed) { now_count_f = now_count_f - (now_count_f - accel_info.target_speed) * mid; now_count = (uint16_t)(now_count_f + 0.5); table_data[i++] = (uint8_t) now_count; } if (i == accel_steps) break; if (i > accel_steps) low_lim = mid; else up_lim = mid; } /* fill stable steps */ for (i = accel_steps; i < accel_info.total_steps; i++) table_data [i] = table_data [i-1]; debug_print_hex_raw (5, "send_acceleration_table: first pass:\n", table_data, accel_info.total_steps); /* maybe post fix-up */ { int add_count; /* count total steps in table */ int table_total = 0; for (i = 0; i < accel_info.total_steps; i++) table_total += table_data [i]; i = 0; if (((table_total * accel_info.table_units) % accel_info.base_units) == 0) add_count = 0; else add_count = (accel_info.base_units - ((table_total*accel_info.table_units) % accel_info.base_units)) / accel_info.table_units; /* add_count should not be bigger than 255 */ if (add_count > 255) { DBG (1, "send_acceleration_table: add_count limited, was: %d\n", add_count); add_count = 255; } for (i = 0; i < accel_info.total_steps - 1 && add_count > 0; i++) { uint16_t temp_count = 255 - table_data [i]; temp_count = temp_count > add_count ? add_count : temp_count; table_data [i] += (uint8_t) temp_count; add_count -= temp_count; } } } debug_print_hex_raw (5, "send_acceleration_table: fixed up:\n", table_data, accel_info.total_steps); /* decrease all by one ... */ for (i = 0; i < accel_info.total_steps; i++) { table_data[i]--; } DBG (1, "send_acceleration_table: sending table %d\n", table); debug_print_hex_raw (5, "send_acceleration_table: final:\n", table_data, accel_info.total_steps); status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), (char*) table_data, accel_info.total_steps, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (3, "send_acceleration_table: send_data failed (%s)\n", sane_strstatus (status)); } free (table_data); table_data = 0; table++; } while (table < accel_info.table_count); return status; } static SANE_Status set_window (Avision_Scanner* s) { Avision_Device* dev = s->hw; SANE_Status status; int base_dpi_abs, base_dpi_rel; int transferlen; int paralen; int bytes_per_line; int line_count; struct { struct command_set_window cmd; struct command_set_window_window window; } cmd; DBG (1, "set_window:\n"); /* plain old scanners, the C3 ASIC HP 53xx and the C6 ASIC HP 74xx and up do use 1200 as base - only the C5 differs */ switch (dev->inquiry_asic_type) { case AV_ASIC_C5: base_dpi_abs = 1200; /* round down to the next multiple of 300 */ base_dpi_rel = s->avdimen.hw_xres - s->avdimen.hw_xres % 300; if (base_dpi_rel > dev->inquiry_optical_res) base_dpi_rel = dev->inquiry_optical_res; else if (s->avdimen.hw_xres <= 150) base_dpi_rel = 150; break; default: base_dpi_abs = 1200; base_dpi_rel = 1200; } DBG (2, "set_window: base_dpi_abs: %d, base_dpi_rel: %d\n", base_dpi_abs, base_dpi_rel); /* wipe out anything */ memset (&cmd, 0, sizeof (cmd) ); cmd.window.descriptor.winid = AV_WINID; /* normally defined to be zero */ /* optional parameter length to use */ paralen = sizeof (cmd.window.avision) - sizeof (cmd.window.avision.type); DBG (2, "set_window: base paralen: %d\n", paralen); if (dev->hw->feature_type & AV_FUJITSU) paralen += sizeof (cmd.window.avision.type.fujitsu); else if (!dev->inquiry_new_protocol) paralen += sizeof (cmd.window.avision.type.old); else paralen += sizeof (cmd.window.avision.type.normal); DBG (2, "set_window: final paralen: %d\n", paralen); transferlen = sizeof (cmd.window) - sizeof (cmd.window.avision) + paralen; DBG (2, "set_window: transferlen: %d\n", transferlen); /* command setup */ cmd.cmd.opc = AVISION_SCSI_SET_WINDOW; set_triple (cmd.cmd.transferlen, transferlen); set_double (cmd.window.header.desclen, sizeof (cmd.window.descriptor) + paralen); /* resolution parameters */ set_double (cmd.window.descriptor.xres, s->avdimen.hw_xres); set_double (cmd.window.descriptor.yres, s->avdimen.hw_yres); /* upper left corner x/y as well as width/length in inch * base_dpi - avdimen are world pixels */ set_quad (cmd.window.descriptor.ulx, s->avdimen.tlx * base_dpi_abs / s->avdimen.hw_xres); set_quad (cmd.window.descriptor.uly, s->avdimen.tly * base_dpi_abs / s->avdimen.hw_yres); set_quad (cmd.window.descriptor.width, s->avdimen.hw_pixels_per_line * base_dpi_rel / s->avdimen.hw_xres + 1); line_count = s->avdimen.hw_lines + 2 * s->avdimen.line_difference + s->avdimen.rear_offset; set_quad (cmd.window.descriptor.length, line_count * base_dpi_rel / s->avdimen.hw_yres + 1); /* interlaced duplex scans are twice as long */ if (s->avdimen.interlaced_duplex && dev->scanner_type != AV_FILM) { DBG (2, "set_window: interlaced duplex scan, doubled line count\n"); line_count *= 2; } bytes_per_line = s->avdimen.hw_bytes_per_line; set_double (cmd.window.avision.line_width, bytes_per_line); set_double (cmd.window.avision.line_count, line_count); /* here go the most significant bits if bigger than 16 bit */ if (dev->inquiry_new_protocol && !(dev->hw->feature_type & AV_FUJITSU) ) { DBG (2, "set_window: large data-transfer support (>16bit)!\n"); cmd.window.avision.type.normal.line_width_msb = bytes_per_line >> 16; cmd.window.avision.type.normal.line_count_msb = line_count >> 16; } if (dev->inquiry_background_raster) cmd.window.avision.type.normal.background_lines = s->val[OPT_BACKGROUND].w; /* scanner should use our line-width and count */ SET_BIT (cmd.window.avision.bitset1, 6); /* set speed */ cmd.window.avision.bitset1 |= s->val[OPT_SPEED].w & 0x07; /* only 3 bit */ /* ADF scan? */ DBG (3, "set_window: source mode %d source mode dim %d\n", s->source_mode, s->source_mode_dim); if (s->source_mode == AV_ADF || s->source_mode == AV_ADF_REAR || s->source_mode == AV_ADF_DUPLEX) { DBG (3, "set_window: filling ADF bits\n"); SET_BIT (cmd.window.avision.bitset1, 7); /* normal, interlaced duplex scanners */ if (dev->inquiry_duplex_interlaced) { DBG (3, "set_window: interlaced duplex type\n"); if (s->source_mode == AV_ADF_REAR) { SET_BIT(cmd.window.avision.type.normal.bitset3, 3); /* 0x08 */ } if (s->source_mode == AV_ADF_DUPLEX) { SET_BIT(cmd.window.avision.type.normal.bitset3, 4); /* 0x10 */ } } else if (s->source_mode == AV_ADF_DUPLEX) /* HP 2-pass duplex */ { DBG (3, "set_window: non-interlaced duplex type (HP)\n"); SET_BIT(cmd.window.avision.type.normal.bitset3, 0); /* DPLX 0x01 */ if (s->val[OPT_ADF_FLIP].w) SET_BIT(cmd.window.avision.type.normal.bitset3, 1); /* FLIP 0x02 */ SET_BIT(cmd.window.avision.type.normal.bitset3, 2); /* MIRR 0x04 */ } } if (s->val[OPT_PAPERLEN].w != SANE_FALSE) { set_double (cmd.window.descriptor.paper_length, (int)((double)30.0*1200)); } if ( !(dev->hw->feature_type & AV_FUJITSU) ) { /* quality scan option switch */ if (s->val[OPT_QSCAN].w == SANE_TRUE) { SET_BIT (cmd.window.avision.type.normal.bitset2, 4); } /* quality calibration option switch (inverted! if set == speed) */ if (s->val[OPT_QCALIB].w == SANE_FALSE) { SET_BIT (cmd.window.avision.type.normal.bitset2, 3); } /* transparency option switch */ if (s->source_mode_dim == AV_TRANSPARENT_DIM) { SET_BIT (cmd.window.avision.type.normal.bitset2, 7); } if (dev->scanner_type == AV_FILM) { /* TODO: wire to IR exposure option? */ cmd.window.avision.type.normal.ir_exposure_time = 100; set_double (cmd.window.avision.type.normal.r_exposure_time, s->val[OPT_EXPOSURE].w); set_double (cmd.window.avision.type.normal.g_exposure_time, s->val[OPT_EXPOSURE].w); set_double (cmd.window.avision.type.normal.b_exposure_time, s->val[OPT_EXPOSURE].w); if (s->val[OPT_IR].w) cmd.window.avision.type.normal.bitset3 |= (1 << 0); if (s->val[OPT_MULTISAMPLE].w) cmd.window.avision.type.normal.bitset3 |= (1 << 1); } } /* fixed values */ cmd.window.descriptor.padding_and_bitset = 3; cmd.window.descriptor.vendor_specific = 0xFF; cmd.window.descriptor.paralen = paralen; /* R² was: 9, later 14 */ /* This is normally unsupported by Avision scanners, and we do this via the gamma table - which works for all devices ... */ cmd.window.descriptor.threshold = 128; cmd.window.descriptor.brightness = 128; cmd.window.descriptor.contrast = 128; cmd.window.avision.highlight = 0xFF; cmd.window.avision.shadow = 0x00; /* mode dependant settings */ switch (s->c_mode) { case AV_THRESHOLDED: cmd.window.descriptor.bpc = 1; cmd.window.descriptor.image_comp = 0; break; case AV_DITHERED: cmd.window.descriptor.bpc = 1; cmd.window.descriptor.image_comp = 1; break; case AV_GRAYSCALE: cmd.window.descriptor.bpc = 8; cmd.window.descriptor.image_comp = 2; break; case AV_GRAYSCALE12: cmd.window.descriptor.bpc = 12; cmd.window.descriptor.image_comp = 2; break; case AV_GRAYSCALE16: cmd.window.descriptor.bpc = 16; cmd.window.descriptor.image_comp = 2; break; case AV_TRUECOLOR: cmd.window.descriptor.bpc = 8; cmd.window.descriptor.image_comp = 5; break; case AV_TRUECOLOR12: cmd.window.descriptor.bpc = 12; cmd.window.descriptor.image_comp = 5; break; case AV_TRUECOLOR16: cmd.window.descriptor.bpc = 16; cmd.window.descriptor.image_comp = 5; break; default: DBG (1, "Invalid mode. %d\n", s->c_mode); return SANE_STATUS_INVAL; } if (color_mode_is_color (s->c_mode)) { cmd.window.avision.bitset1 |= AVISION_FILTER_RGB; } else { if (dev->hw->feature_type & AV_FASTER_WITH_FILTER) cmd.window.avision.bitset1 |= AVISION_FILTER_GREEN; else if (dev->hw->feature_type & AV_USE_GRAY_FILTER) cmd.window.avision.bitset1 |= AVISION_FILTER_GRAY; else cmd.window.avision.bitset1 |= AVISION_FILTER_NONE; } debug_print_window_descriptor (5, "set_window", &(cmd.window)); DBG (3, "set_window: sending command. Bytes: %d\n", transferlen); status = avision_cmd (&s->av_con, &cmd, sizeof (cmd.cmd), &(cmd.window), transferlen, 0, 0); return status; } static SANE_Status get_background_raster (Avision_Scanner* s) { const int debug = 0; Avision_Device* dev = s->hw; SANE_Status status; struct command_read rcmd; size_t size; int bytes_per_line, i; const int bpp = color_mode_is_color (s->c_mode) ? 3 : 1; const int lines = s->val[OPT_BACKGROUND].w * (s->avdimen.interlaced_duplex ? 2 : 1); uint8_t* background = NULL; DBG (1, "get_background_raster:\n"); if (lines == 0) { DBG (1, "get_background_raster: no background requested\n"); return SANE_STATUS_GOOD; } /* full width, always :-(, duplex *2 for front and rear */ bytes_per_line = dev->inquiry_background_raster_pixel * s->avdimen.hw_xres / dev->inquiry_optical_res; bytes_per_line *= bpp; DBG (3, "get_background_raster: native raster pixels: %d, raster bytes_per_line: %d\n", dev->inquiry_background_raster_pixel, bytes_per_line); /* according to spec only 8-bit gray or color, TODO: test for bi-level scans */ size = bytes_per_line * lines; DBG (3, "get_background_raster: buffer size: %ld\n", (long)size); background = s->background_raster = realloc (s->background_raster, size); if (!background) return SANE_STATUS_NO_MEM; memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x9b; /* get background raster */ set_double (rcmd.datatypequal, s->hw->data_dq); /* Ok, well - this part is very messy. The AV122 and DM152 appear to contain differently buggy ASICs. The only combination I found to at least get a correct front raster out of them is to read it line by line and then every second line appears to be valid front data, ... */ /* read the raster data */ for (i = 0; i < lines;) { uint8_t* dst_raster = background + bytes_per_line * i; /* read stripe by stripe, or all in one chunk */ size_t this_read, read_size; int this_lines; if (dev->hw->feature_type & AV_2ND_LINE_INTERLACED) { if (dev->hw->feature_type & AV_BACKGROUND_QUIRK) this_lines = 1; else this_lines = lines; } else { this_lines = s->val[OPT_BACKGROUND].w; } this_read = bytes_per_line * this_lines; DBG (3, "get_background_raster: line: %d, lines: %d, %lu bytes\n", i, this_lines, (u_long) this_read); set_triple (rcmd.transferlen, this_read); read_size = this_read; status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, dst_raster, &read_size); if (status != SANE_STATUS_GOOD || read_size != this_read) { DBG (1, "get_background_raster: read raster failed (%s)\n", sane_strstatus (status) ); return status; } i += this_lines; } /* dump raw result while debugging */ if (debug) { FILE* f = NULL; f = fopen ("background-raw.pnm", "w"); write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8, bytes_per_line / bpp, lines); fwrite (background, 1, bytes_per_line * lines, f); fclose (f); } /* line-pack - move to unified processing flow, later */ if (dev->inquiry_needs_line_pack) { /* TODO: add 16bit per sample code? */ int l, p; uint8_t* tmp_data = malloc (bytes_per_line); for (l = 0; l < lines; ++l) { uint8_t* out_data = tmp_data; uint8_t* r_ptr = background + (bytes_per_line * l); uint8_t* g_ptr = r_ptr + bytes_per_line / bpp; uint8_t* b_ptr = g_ptr + bytes_per_line / bpp; for (p = 0; p < bytes_per_line;) { out_data [p++] = *(r_ptr++); out_data [p++] = *(g_ptr++); out_data [p++] = *(b_ptr++); } memcpy (background + (bytes_per_line * l), tmp_data, bytes_per_line); } free (tmp_data); } /* end line pack */ /* deinterlace? */ if (s->avdimen.interlaced_duplex && dev->hw->feature_type & AV_2ND_LINE_INTERLACED) { uint8_t* deinterlaced = malloc (size * 2); if (!deinterlaced) return SANE_STATUS_NO_MEM; for (i = 0; i < lines; ++i) { int dst_i = i / 2 + (i % 2) * (lines / 2); uint8_t* dst_raster; /* just no C99 in SANE :-( */ uint8_t* src_raster; /* for the quirky devices and some resolutions the interlacing differs */ if (dev->hw->feature_type & AV_BACKGROUND_QUIRK && s->avdimen.hw_xres >= 150) dst_i = i / 2 + ((i+1) % 2) * (lines / 2); dst_raster = deinterlaced + bytes_per_line * dst_i; src_raster = background + bytes_per_line * i; DBG(3, "get_background_raster: deinterlaced %d -> %d\n", i, dst_i); memcpy(dst_raster, src_raster, bytes_per_line); } free (background); background = s->background_raster = deinterlaced; } /* dump raw result while debugging */ for (i = 0; debug && i < (s->avdimen.interlaced_duplex ? 2 : 1); ++i) { FILE* f = NULL; uint8_t* raster = background; if (i == 0) { f = fopen ("background.pnm", "w"); } else { f = fopen ("background-rear.pnm", "w"); raster += bytes_per_line * s->val[OPT_BACKGROUND].w; } write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8, bytes_per_line / bpp, s->val[OPT_BACKGROUND].w); fwrite (raster, 1, bytes_per_line * s->val[OPT_BACKGROUND].w, f); fclose (f); } /* crop from full-width scanlines to scan window */ { uint8_t *dst_ptr, *src_ptr; dst_ptr = background; src_ptr = background + s->avdimen.tlx * bpp; for (i = 0; i < lines; ++i) { memmove (dst_ptr, src_ptr, s->avdimen.hw_bytes_per_line); dst_ptr += s->avdimen.hw_bytes_per_line; src_ptr += bytes_per_line; } } /* soft-scale - move to unified processing flow, later */ if (s->avdimen.hw_xres != s->avdimen.xres) { const uint8_t* out_data = background; uint8_t* dst = background; int l; for (l = 0; l < lines; ++l) { const int hwbpl = s->avdimen.hw_bytes_per_line; const int sy = l; int x; for (x = 0; x < s->params.pixels_per_line; ++x) { const double bx = (-1.0 + s->avdimen.hw_pixels_per_line) * x / s->params.pixels_per_line; const int sx = (int)floor(bx); const int xdist = (int) ((bx - sx) * 256); const int sxx = sx + 1; switch (bpp) { case 1: { uint8_t v = ( out_data [sy*hwbpl + sx ] * (256-xdist) + out_data [sy*hwbpl + sxx] * xdist ) / (256); *dst++ = v; } break; case 3: { int c; for (c = 0; c < 3; ++c) { uint8_t v = ( out_data [sy*hwbpl + sx*3 + c] * (256-xdist) + out_data [sy*hwbpl + sxx*3 + c] * xdist ) / (256); *dst++ = v; } } break; } } } } /* dump final result while debugging */ if (debug) { for (i = 0; i < (s->avdimen.interlaced_duplex ? 2 : 1); ++i) { FILE* f = NULL; uint8_t* raster = background; if (i == 0) { f = fopen ("background-final.pnm", "w"); } else { f = fopen ("background-final-rear.pnm", "w"); raster += s->params.bytes_per_line * s->val[OPT_BACKGROUND].w; } write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8, s->params.bytes_per_line / bpp, s->val[OPT_BACKGROUND].w); fwrite (raster, 1, s->params.bytes_per_line * s->val[OPT_BACKGROUND].w, f); fclose (f); } } return SANE_STATUS_GOOD; } static SANE_Status reserve_unit (Avision_Scanner* s) { char cmd[] = {AVISION_SCSI_RESERVE_UNIT, 0, 0, 0, 0, 0}; SANE_Status status; DBG (1, "reserve_unit:\n"); status = avision_cmd (&s->av_con, cmd, sizeof (cmd), 0, 0, 0, 0); return status; } static SANE_Status release_unit (Avision_Scanner* s, int type) { char cmd[] = {AVISION_SCSI_RELEASE_UNIT, 0, 0, 0, 0, 0}; SANE_Status status; DBG (1, "release unit: type: %d\n", type); cmd[5] = type; /* latest scanners also allow 1: release paper and 2: end job */ status = avision_cmd (&s->av_con, cmd, sizeof (cmd), 0, 0, 0, 0); return status; } /* Check if a sheet is present. */ static SANE_Status media_check (Avision_Scanner* s) { char cmd[] = {AVISION_SCSI_MEDIA_CHECK, 0, 0, 0, 1, 0}; /* 1, 4 */ SANE_Status status; uint8_t result[1]; /* 4 */ size_t size = sizeof(result); status = avision_cmd (&s->av_con, cmd, sizeof (cmd), 0, 0, result, &size); debug_print_raw (5, "media_check: result\n", result, size); if (status == SANE_STATUS_GOOD) { if (!(result[0] & 0x1)) status = SANE_STATUS_NO_DOCS; } return status; } #if 0 /* unused */ static SANE_Status flush_media (Avision_Scanner* s) { Avision_Device* dev = s->hw; SANE_Status status; if (s->source_mode_dim == AV_ADF_DIM && dev->inquiry_batch_scan) { DBG (1, "flush_media: flushing pages out of batch scanner\n"); do { status = media_check (s); if (status == SANE_STATUS_GOOD) { SANE_Status status2 = reserve_unit (s); DBG (1, "flush_media: reserve status: %d\n", status2); status2 = release_unit (s, 0); DBG (1, "flush_media: release status: %d\n", status2); } } while (status == SANE_STATUS_GOOD); } return SANE_STATUS_GOOD; } #endif /* 0 - unused */ static SANE_Status object_position (Avision_Scanner* s, uint8_t position) { SANE_Status status; uint8_t cmd [10]; memset (cmd, 0, sizeof (cmd)); cmd[0] = AVISION_SCSI_OBJECT_POSITION; cmd[1] = position; DBG (1, "object_position: %d\n", position); status = avision_cmd (&s->av_con, cmd, sizeof(cmd), 0, 0, 0, 0); return status; } static SANE_Status start_scan (Avision_Scanner* s) { struct command_scan cmd; size_t size = sizeof (cmd); DBG (3, "start_scan:\n"); memset (&cmd, 0, sizeof (cmd)); cmd.opc = AVISION_SCSI_SCAN; cmd.transferlen = 1; /* AV610C2 in ADF preview mode does not detect the page end (...) */ if (s->val[OPT_PREVIEW].w == SANE_TRUE && s->hw->inquiry_asic_type != AV_ASIC_C7) { SET_BIT(cmd.bitset1,6); } if (s->val[OPT_QSCAN].w == SANE_TRUE) { SET_BIT(cmd.bitset1,7); } DBG (3, "start_scan: sending command. Bytes: %lu\n", (u_long) size); return avision_cmd (&s->av_con, &cmd, size, 0, 0, 0, 0); } static SANE_Status do_eof (Avision_Scanner *s) { int exit_status; DBG (3, "do_eof:\n"); /* we do not scan anymore */ s->prepared = s->scanning = SANE_FALSE; /* we can now mark the rear data as valid */ if (s->avdimen.interlaced_duplex || (s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX)) { DBG (3, "do_eof: toggling duplex rear data valid\n"); s->duplex_rear_valid = !s->duplex_rear_valid; DBG (3, "do_eof: duplex rear data valid: %x\n", s->duplex_rear_valid); } if (s->read_fds >= 0) { close (s->read_fds); s->read_fds = -1; } /* join our processes - without a wait() you will produce zombies (defunct children) */ sanei_thread_waitpid (s->reader_pid, &exit_status); s->reader_pid = -1; DBG (3, "do_eof: returning %d\n", exit_status); return (SANE_Status)exit_status; } static SANE_Status do_cancel (Avision_Scanner* s) { DBG (3, "do_cancel:\n"); s->prepared = s->scanning = SANE_FALSE; s->duplex_rear_valid = SANE_FALSE; s->page = 0; s->cancelled = 1; if (sanei_thread_is_valid (s->reader_pid)) { int exit_status; /* ensure child knows it's time to stop: */ sanei_thread_kill (s->reader_pid); sanei_thread_waitpid (s->reader_pid, &exit_status); s->reader_pid = -1; } return SANE_STATUS_CANCELLED; } static SANE_Status read_data (Avision_Scanner* s, SANE_Byte* buf, size_t* count) { struct command_read rcmd; SANE_Status status; DBG (9, "read_data: %lu\n", (u_long) *count); memset (&rcmd, 0, sizeof (rcmd)); rcmd.opc = AVISION_SCSI_READ; rcmd.datatypecode = 0x00; /* read image data */ set_double (rcmd.datatypequal, s->hw->data_dq); set_triple (rcmd.transferlen, *count); status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, buf, count); return status; } static SANE_Status init_options (Avision_Scanner* s) { Avision_Device* dev = s->hw; int i; DBG (3, "init_options:\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++ i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Init the SANE option from the scanner inquiry data */ switch (dev->inquiry_asic_type) { case AV_ASIC_C2: dev->dpi_range.min = 100; break; case AV_ASIC_C5: dev->dpi_range.min = 80; break; case AV_ASIC_C6: /* TODO: AV610 in ADF mode does not scan less than 180 or so */ dev->dpi_range.min = 50; break; case AV_ASIC_C7: /* AV610C2 empirically tested out */ dev->dpi_range.min = 75; break; default: dev->dpi_range.min = 50; } DBG (1, "init_options: dpi_range.min set to %d\n", dev->dpi_range.min); dev->dpi_range.quant = 1; /* any, including 72, 144, etc. */ dev->dpi_range.max = dev->inquiry_max_res; dev->speed_range.min = (SANE_Int)0; dev->speed_range.max = (SANE_Int)4; dev->speed_range.quant = (SANE_Int)1; s->opt[OPT_NUM_OPTS].name = ""; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = ""; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].size = sizeof(SANE_TYPE_INT); s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE_GROUP].desc = ""; /* for groups only title and type are valid */ s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* color mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (dev->color_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = dev->color_list; s->val[OPT_MODE].s = strdup (dev->color_list[dev->color_list_default]); s->c_mode = match_color_mode (dev, s->val[OPT_MODE].s); /* source mode */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].size = max_string_size(dev->source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = &dev->source_list[0]; s->val[OPT_SOURCE].s = strdup(dev->source_list[0]); s->source_mode = match_source_mode (dev, s->val[OPT_SOURCE].s); s->source_mode_dim = match_source_mode_dim (s->source_mode); dev->x_range.max = SANE_FIX ( (int)dev->inquiry_x_ranges[s->source_mode_dim]); dev->x_range.quant = 0; dev->y_range.max = SANE_FIX ( (int)dev->inquiry_y_ranges[s->source_mode_dim]); dev->y_range.quant = 0; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &dev->dpi_range; s->val[OPT_RESOLUTION].w = OPT_RESOLUTION_DEFAULT; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = 0; /* speed option */ s->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; s->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; s->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; s->opt[OPT_SPEED].type = SANE_TYPE_INT; s->opt[OPT_SPEED].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_SPEED].constraint.range = &dev->speed_range; s->val[OPT_SPEED].w = 0; if (dev->scanner_type == AV_SHEETFEED) s->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; /* for groups only title and type are valid */ s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &dev->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &dev->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &dev->x_range; s->val[OPT_BR_X].w = dev->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &dev->y_range; s->val[OPT_BR_Y].w = dev->y_range.max; /* overscan top */ s->opt[OPT_OVERSCAN_TOP].name = "overscan-top"; s->opt[OPT_OVERSCAN_TOP].title = "Overscan top"; s->opt[OPT_OVERSCAN_TOP].desc = "The top overscan controls the additional area to scan before the paper is detected."; s->opt[OPT_OVERSCAN_TOP].type = SANE_TYPE_FIXED; s->opt[OPT_OVERSCAN_TOP].unit = SANE_UNIT_MM; s->opt[OPT_OVERSCAN_TOP].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVERSCAN_TOP].constraint.range = &overscan_range; s->val[OPT_OVERSCAN_TOP].w = SANE_FIX(0); /* overscan bottom */ s->opt[OPT_OVERSCAN_BOTTOM].name = "overscan-bottom"; s->opt[OPT_OVERSCAN_BOTTOM].title = "Overscan bottom"; s->opt[OPT_OVERSCAN_BOTTOM].desc = "The bottom overscan controls the additional area to scan after the paper end is detected."; s->opt[OPT_OVERSCAN_BOTTOM].type = SANE_TYPE_FIXED; s->opt[OPT_OVERSCAN_BOTTOM].unit = SANE_UNIT_MM; s->opt[OPT_OVERSCAN_BOTTOM].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVERSCAN_BOTTOM].constraint.range = &overscan_range; s->val[OPT_OVERSCAN_BOTTOM].w = SANE_FIX(0); if (!dev->inquiry_tune_scan_length) s->opt[OPT_OVERSCAN_TOP].cap |= SANE_CAP_INACTIVE; if (!dev->inquiry_tune_scan_length) s->opt[OPT_OVERSCAN_BOTTOM].cap |= SANE_CAP_INACTIVE; /* background raster */ s->opt[OPT_BACKGROUND].name = "background-lines"; s->opt[OPT_BACKGROUND].title = "Background raster lines"; s->opt[OPT_BACKGROUND].desc = "The background raster controls the additional background lines to scan before the paper is feed through the scanner."; s->opt[OPT_BACKGROUND].type = SANE_TYPE_INT; s->opt[OPT_BACKGROUND].unit = SANE_UNIT_PIXEL; s->opt[OPT_BACKGROUND].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BACKGROUND].constraint.range = &background_range; s->val[OPT_BACKGROUND].w = 0; if (!dev->inquiry_background_raster) { s->opt[OPT_BACKGROUND].cap |= SANE_CAP_INACTIVE; } /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* for groups only title and type are valid */ s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; if (disable_gamma_table) s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; s->val[OPT_BRIGHTNESS].w = SANE_FIX(0); /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; if (disable_gamma_table) s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; s->val[OPT_CONTRAST].w = SANE_FIX(0); /* Quality Scan */ s->opt[OPT_QSCAN].name = "quality-scan"; s->opt[OPT_QSCAN].title = "Quality scan"; s->opt[OPT_QSCAN].desc = "Turn on quality scanning (slower but better)."; s->opt[OPT_QSCAN].type = SANE_TYPE_BOOL; s->opt[OPT_QSCAN].unit = SANE_UNIT_NONE; s->val[OPT_QSCAN].w = SANE_TRUE; /* Quality Calibration */ s->opt[OPT_QCALIB].name = SANE_NAME_QUALITY_CAL; s->opt[OPT_QCALIB].title = SANE_TITLE_QUALITY_CAL; s->opt[OPT_QCALIB].desc = SANE_DESC_QUALITY_CAL; s->opt[OPT_QCALIB].type = SANE_TYPE_BOOL; s->opt[OPT_QCALIB].unit = SANE_UNIT_NONE; s->val[OPT_QCALIB].w = SANE_TRUE; /* gray scale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; if (!disable_gamma_table) { if (color_mode_is_color (s->c_mode)) { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } } /* exposure */ s->opt[OPT_EXPOSURE].name = "exposure"; s->opt[OPT_EXPOSURE].title = "Exposure"; s->opt[OPT_EXPOSURE].desc = "Manual exposure adjustment."; s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT; s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_EXPOSURE].constraint.range = &exposure_range; s->val[OPT_EXPOSURE].w = 100; if (!dev->inquiry_exposure_control) { s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; } /* Multi sample */ s->opt[OPT_MULTISAMPLE].name = "multi-sample"; s->opt[OPT_MULTISAMPLE].title = "Multi-sample"; s->opt[OPT_MULTISAMPLE].desc = "Enable multi-sample scan mode."; s->opt[OPT_MULTISAMPLE].type = SANE_TYPE_BOOL; s->opt[OPT_MULTISAMPLE].unit = SANE_UNIT_NONE; s->val[OPT_MULTISAMPLE].w = SANE_FALSE; /* TODO: No idea how to detect, assume exposure control devices are new enough to support this, for now. -ReneR */ if (!dev->inquiry_exposure_control) { s->opt[OPT_MULTISAMPLE].cap |= SANE_CAP_INACTIVE; } /* Infra-red */ s->opt[OPT_IR].name = "infra-red"; s->opt[OPT_IR].title = "Infra-red"; s->opt[OPT_IR].desc = "Enable infra-red scan mode."; s->opt[OPT_IR].type = SANE_TYPE_BOOL; s->opt[OPT_IR].unit = SANE_UNIT_NONE; s->val[OPT_IR].w = SANE_FALSE; /* TODO: No idea how to detect, assume exposure control devices are new enough to support this, for now. -ReneR */ if (!dev->inquiry_exposure_control) { s->opt[OPT_IR].cap |= SANE_CAP_INACTIVE; } /* "MISC" group: */ s->opt[OPT_MISC_GROUP].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MISC_GROUP].desc = ""; /* for groups only title and type are valid */ s->opt[OPT_MISC_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MISC_GROUP].cap = 0; s->opt[OPT_MISC_GROUP].size = 0; s->opt[OPT_MISC_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* film holder control */ if (dev->scanner_type != AV_FILM) s->opt[OPT_FRAME].cap |= SANE_CAP_INACTIVE; s->opt[OPT_FRAME].name = SANE_NAME_FRAME; s->opt[OPT_FRAME].title = SANE_TITLE_FRAME; s->opt[OPT_FRAME].desc = SANE_DESC_FRAME; s->opt[OPT_FRAME].type = SANE_TYPE_INT; s->opt[OPT_FRAME].unit = SANE_UNIT_NONE; s->opt[OPT_FRAME].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_FRAME].constraint.range = &dev->frame_range; s->val[OPT_FRAME].w = dev->current_frame; /* power save time */ if (!dev->inquiry_power_save_time) s->opt[OPT_POWER_SAVE_TIME].cap |= SANE_CAP_INACTIVE; s->opt[OPT_POWER_SAVE_TIME].name = "power-save-time"; s->opt[OPT_POWER_SAVE_TIME].title = "Power save timer control"; s->opt[OPT_POWER_SAVE_TIME].desc = "Allows control of the scanner's power save timer, dimming or turning off the light."; s->opt[OPT_POWER_SAVE_TIME].type = SANE_TYPE_INT; s->opt[OPT_POWER_SAVE_TIME].unit = SANE_UNIT_NONE; s->opt[OPT_POWER_SAVE_TIME].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_POWER_SAVE_TIME].w = 0; /* message, like options set on the scanner, LED no. & co */ s->opt[OPT_MESSAGE].name = "message"; s->opt[OPT_MESSAGE].title = "message text from the scanner"; s->opt[OPT_MESSAGE].desc = "This text contains device specific options controlled by the user on the scanner hardware."; s->opt[OPT_MESSAGE].type = SANE_TYPE_STRING; s->opt[OPT_MESSAGE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; s->opt[OPT_MESSAGE].size = 129; s->opt[OPT_MESSAGE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_MESSAGE].s = malloc(s->opt[OPT_MESSAGE].size); s->val[OPT_MESSAGE].s[0] = 0; /* NVRAM */ s->opt[OPT_NVRAM].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if (!dev->inquiry_nvram_read) s->opt[OPT_NVRAM].cap |= SANE_CAP_INACTIVE; s->opt[OPT_NVRAM].name = "nvram-values"; s->opt[OPT_NVRAM].title = "Obtain NVRAM values"; s->opt[OPT_NVRAM].desc = "Allows access obtaining the scanner's NVRAM values as pretty printed text."; s->opt[OPT_NVRAM].type = SANE_TYPE_STRING; s->opt[OPT_NVRAM].unit = SANE_UNIT_NONE; s->opt[OPT_NVRAM].size = 1024; s->opt[OPT_NVRAM].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_NVRAM].s = malloc(s->opt[OPT_NVRAM].size); s->val[OPT_NVRAM].s[0] = 0; /* paper_length */ s->opt[OPT_PAPERLEN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if (!dev->inquiry_paper_length) s->opt[OPT_PAPERLEN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_PAPERLEN].name = "paper-length"; s->opt[OPT_PAPERLEN].title = "Use paper length"; 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."; s->opt[OPT_PAPERLEN].type = SANE_TYPE_BOOL; s->opt[OPT_PAPERLEN].unit = SANE_UNIT_NONE; s->opt[OPT_PAPERLEN].size = sizeof(SANE_Word); s->opt[OPT_PAPERLEN].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_PAPERLEN].w = SANE_FALSE; /* ADF page flipping */ s->opt[OPT_ADF_FLIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; if (!(s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX)) s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ADF_FLIP].name = "flip-page"; s->opt[OPT_ADF_FLIP].title = "Flip document after duplex scanning"; 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."; s->opt[OPT_ADF_FLIP].type = SANE_TYPE_BOOL; s->opt[OPT_ADF_FLIP].unit = SANE_UNIT_NONE; s->opt[OPT_ADF_FLIP].size = sizeof(SANE_Word); s->opt[OPT_ADF_FLIP].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_ADF_FLIP].w = SANE_TRUE; return SANE_STATUS_GOOD; } /* This function is executed as a child process. The reason this is executed as a subprocess is because some (most?) generic SCSI interfaces block a SCSI request until it has completed. With a subprocess, we can let it block waiting for the request to finish while the main process can go about to do more important things (such as recognizing when the user presses a cancel button). WARNING: Since this is executed as a subprocess, it's NOT possible to update any of the variables in the main process (in particular the scanner state cannot be updated). */ static int reader_process (void *data) { struct Avision_Scanner *s = (struct Avision_Scanner *) data; int fd = s->write_fds; Avision_Device* dev = s->hw; SANE_Status status; SANE_Status exit_status = SANE_STATUS_GOOD; sigset_t sigterm_set; sigset_t ignore_set; struct SIGACTION act; FILE* fp; FILE* rear_fp = 0; /* used to store the deinterlaced rear data */ FILE* raw_fp = 0; /* used to write the RAW image data for debugging */ /* the complex params */ unsigned int lines_per_stripe; unsigned int lines_per_output; unsigned int max_bytes_per_read; SANE_Bool gray_mode; /* the simple params for the data reader */ int hw_line = 0; int line = 0; unsigned int stripe_size; unsigned int stripe_fill; unsigned int out_size; size_t total_size; size_t processed_bytes; enum { NONE, /* do not de-interlace at all */ STRIPE, /* every 2nd stripe */ HALF, /* the 2nd half */ LINE /* every 2nd line */ } deinterlace = NONE; /* the fat strip we currently puzzle together to perform software-colorpack and more */ uint8_t* stripe_data; /* the corrected output data */ uint8_t* out_data; /* interpolation output data, one line */ uint8_t* ip_history = 0; uint8_t* ip_data = 0; DBG (3, "reader_process:\n"); if (sanei_thread_is_forked()) close (s->read_fds); sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); #if defined (__APPLE__) && defined (__MACH__) sigdelset (&ignore_set, SIGUSR2); #endif sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); gray_mode = color_mode_is_shaded (s->c_mode); if (s->avdimen.interlaced_duplex) { deinterlace = STRIPE; if ( (dev->hw->feature_type & AV_NON_INTERLACED_DUPLEX_300) && (s->avdimen.hw_xres <= 300 && s->avdimen.hw_yres <= 300) ) deinterlace = HALF; if (dev->hw->feature_type & AV_2ND_LINE_INTERLACED) deinterlace = LINE; if (dev->scanner_type == AV_FILM) deinterlace = LINE; } fp = fdopen (fd, "w"); if (!fp) return SANE_STATUS_NO_MEM; /* start scan ? */ if ((deinterlace == NONE && !((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->duplex_rear_valid)) || (deinterlace != NONE && !s->duplex_rear_valid)) { /* reserve unit - in the past we did this in open - but the windows driver does reserves for each scan and some ADF devices need a release for each sheet anyway ... */ status = reserve_unit (s); if (status != SANE_STATUS_GOOD) { DBG (1, "reader_process: reserve_unit failed: %s\n", sane_strstatus (status)); return status; } if (dev->hw->feature_type & AV_NO_START_SCAN) { DBG (1, "reader_process: start_scan skipped due to device-list!\n"); } else { status = start_scan (s); if (status != SANE_STATUS_GOOD) { DBG (1, "reader_process: start_scan failed: %s\n", sane_strstatus (status)); return status; } } if (dev->hw->feature_type & AV_ACCEL_TABLE) /* (s->hw->inquiry_asic_type == AV_ASIC_C6) */ { status = send_acceleration_table (s); if (status != SANE_STATUS_GOOD) { DBG (1, "reader_process: send_acceleration_table failed: %s\n", sane_strstatus (status)); return status; } } } /* setup file i/o for deinterlacing scans or if we are the back page with a flipping duplexer */ if (deinterlace != NONE || (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2))) { if (!s->duplex_rear_valid) { /* create new file for writing */ DBG (3, "reader_process: opening duplex rear file for writing.\n"); rear_fp = fopen (s->duplex_rear_fname, "w"); if (! rear_fp) { fclose (fp); return SANE_STATUS_NO_MEM; } } else { /* open saved rear data */ DBG (3, "reader_process: opening duplex rear file for reading.\n"); rear_fp = fopen (s->duplex_rear_fname, "r"); if (! rear_fp) { fclose (fp); return SANE_STATUS_IO_ERROR; } } } /* it takes quite a few lines to saturate the (USB) bus */ lines_per_stripe = dev->read_stripe_size; if (s->avdimen.line_difference) lines_per_stripe += 2 * s->avdimen.line_difference; stripe_size = s->avdimen.hw_bytes_per_line * lines_per_stripe; lines_per_output = lines_per_stripe - 2 * s->avdimen.line_difference; if (s->av_con.connection_type == AV_SCSI) /* maybe better not /2 ... */ max_bytes_per_read = dev->scsi_buffer_size / 2; else /* vast buffer size to saturate the bus */ max_bytes_per_read = 0x100000; out_size = s->avdimen.hw_bytes_per_line * lines_per_output; DBG (3, "dev->scsi_buffer_size / 2: %d\n", dev->scsi_buffer_size / 2); DBG (3, "bytes_per_line: %d, pixels_per_line: %d\n", s->avdimen.hw_bytes_per_line, s->avdimen.hw_pixels_per_line); DBG (3, "lines_per_stripe: %d, lines_per_output: %d\n", lines_per_stripe, lines_per_output); DBG (3, "max_bytes_per_read: %d, stripe_size: %d, out_size: %d\n", max_bytes_per_read, stripe_size, out_size); stripe_data = malloc (stripe_size); /* for software scaling we need an additional interpolation line buffer */ if (s->avdimen.hw_xres != s->avdimen.xres || s->avdimen.hw_yres != s->avdimen.yres) { /* layout out_data so that the interpolation history is exactly in front */ ip_history = malloc (s->avdimen.hw_bytes_per_line + out_size); out_data = ip_history + s->avdimen.hw_bytes_per_line; ip_data = malloc (s->params.bytes_per_line); } else { out_data = malloc (out_size); } /* calculate params for the reading loop */ total_size = s->avdimen.hw_bytes_per_line * (s->avdimen.hw_lines + 2 * s->avdimen.line_difference + s->avdimen.rear_offset); if (deinterlace != NONE && !s->duplex_rear_valid) total_size *= 2; DBG (3, "reader_process: total_size: %lu\n", (u_long) total_size); /* write a RAW PNM file for debugging -ReneR */ if (0 /* DEBUG */ && (deinterlace == NONE || (deinterlace != NONE && !s->duplex_rear_valid)) ) { raw_fp = fopen ("/tmp/sane-avision.raw", "w"); write_pnm_header (fp, s->c_mode, s->params.depth, s->avdimen.hw_pixels_per_line, total_size / s->avdimen.hw_bytes_per_line); } processed_bytes = 0; stripe_fill = 0; /* First, dump background raster, bypassing all the other processing. */ if (dev->inquiry_background_raster && s->val[OPT_BACKGROUND].w) { uint8_t* background = s->background_raster; if (s->duplex_rear_valid) background += s->params.bytes_per_line * s->val[OPT_BACKGROUND].w; DBG (5, "reader_process: dumping background raster\n"); fwrite (background, s->params.bytes_per_line, s->val[OPT_BACKGROUND].w, fp); } /* Data read; loop until all data has been processed. Might exit before all lines are transferred for ADF paper end. */ while (exit_status == SANE_STATUS_GOOD && processed_bytes < total_size) { unsigned int useful_bytes; DBG (5, "reader_process: stripe filled: %d\n", stripe_fill); /* fill the stripe buffer with real data */ while (!s->duplex_rear_valid && processed_bytes < total_size && stripe_fill < stripe_size && exit_status == SANE_STATUS_GOOD) { size_t this_read = stripe_size - stripe_fill; /* Limit reads to max_bytes_per_read and global data boundaries. Rounded to the next lower multiple of byte_per_lines, otherwise some scanners freeze. */ if (this_read > max_bytes_per_read) this_read = (max_bytes_per_read - max_bytes_per_read % s->avdimen.hw_bytes_per_line); if (processed_bytes + this_read > total_size) this_read = total_size - processed_bytes; read_constrains(s, this_read); DBG (5, "reader_process: processed_bytes: %lu, total_size: %lu\n", (u_long) processed_bytes, (u_long) total_size); DBG (5, "reader_process: this_read: %lu\n", (u_long) this_read); sigprocmask (SIG_BLOCK, &sigterm_set, 0); status = read_data (s, stripe_data + stripe_fill, &this_read); sigprocmask (SIG_UNBLOCK, &sigterm_set, 0); /* only EOF on the second stripe, as otherwise the rear page is shorter */ if (status == SANE_STATUS_EOF && deinterlace == STRIPE) { if (dev->inquiry_asic_type > AV_ASIC_C7 && dev->inquiry_asic_type < AV_ASIC_OA980) { this_read = 0; } else { static int already_eof = 0; if (!already_eof) { DBG (5, "reader_process: first EOF on stripe interlace: hiding.\n"); status = SANE_STATUS_GOOD; already_eof = 1; } } } /* write RAW data to file for debugging */ if (raw_fp && this_read > 0) fwrite (stripe_data + stripe_fill, this_read, 1, raw_fp); if (status == SANE_STATUS_EOF || this_read == 0) { DBG (1, "reader_process: read_data failed due to EOF\n"); exit_status = SANE_STATUS_EOF; } if (status != SANE_STATUS_GOOD) { DBG (1, "reader_process: read_data failed with status: %d\n", status); exit_status = status; } stripe_fill += this_read; processed_bytes += this_read; } /* fill the stripe buffer with stored, virtual data */ if (s->duplex_rear_valid) { size_t this_read = stripe_size - stripe_fill; size_t got; /* limit reads to max_read and global data boundaries */ if (this_read > max_bytes_per_read) this_read = max_bytes_per_read; if (processed_bytes + this_read > total_size) this_read = total_size - processed_bytes; DBG (5, "reader_process: virtual processed_bytes: %lu, total_size: %lu\n", (u_long) processed_bytes, (u_long) total_size); DBG (5, "reader_process: virtual this_read: %lu\n", (u_long) this_read); got = fread (stripe_data + stripe_fill, 1, this_read, rear_fp); stripe_fill += got; processed_bytes += got; if (got != this_read) exit_status = SANE_STATUS_EOF; } DBG (5, "reader_process: stripe filled: %d\n", stripe_fill); useful_bytes = stripe_fill; if (color_mode_is_color (s->c_mode)) useful_bytes -= 2 * s->avdimen.line_difference * s->avdimen.hw_bytes_per_line; DBG (3, "reader_process: useful_bytes %i\n", useful_bytes); /* Deinterlace, save the rear stripes. For some scanners (AV220) that is every 2nd stripe, the 2nd half of the transferred data ((AV83xx), or every 2nd line (AV122)). */ if (deinterlace != NONE && !s->duplex_rear_valid) { /* for all lines we have in the buffer: */ unsigned int absline = (processed_bytes - stripe_fill) / s->avdimen.hw_bytes_per_line; unsigned int abslines = absline + useful_bytes / s->avdimen.hw_bytes_per_line; uint8_t* ptr = stripe_data; for ( ; absline < abslines; ++absline) { DBG (9, "reader_process: deinterlacing line %d\n", absline); /* interlaced? save the back data to the rear buffer */ if ( (deinterlace == STRIPE && absline % (lines_per_stripe*2) >= lines_per_stripe) || (deinterlace == HALF && absline >= total_size / s->avdimen.hw_bytes_per_line / 2) || (deinterlace == LINE && absline & 0x1) ) /* last bit equals % 2 */ { DBG (9, "reader_process: saving rear line %d to temporary file.\n", absline); fwrite (ptr, s->avdimen.hw_bytes_per_line, 1, rear_fp); if (deinterlace == LINE) memmove (ptr, ptr+s->avdimen.hw_bytes_per_line, stripe_data + stripe_fill - ptr - s->avdimen.hw_bytes_per_line); else ptr += s->avdimen.hw_bytes_per_line; useful_bytes -= s->avdimen.hw_bytes_per_line; stripe_fill -= s->avdimen.hw_bytes_per_line; } else ptr += s->avdimen.hw_bytes_per_line; } DBG (9, "reader_process: after deinterlacing: useful_bytes: %d, stripe_fill: %d\n", useful_bytes, stripe_fill); } if (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && !s->duplex_rear_valid) { /* Here we flip the image by writing the lines from the end of the file to the beginning. */ unsigned int absline = (processed_bytes - stripe_fill) / s->avdimen.hw_bytes_per_line; unsigned int abslines = absline + useful_bytes / s->avdimen.hw_bytes_per_line; uint8_t* ptr = stripe_data; for ( ; absline < abslines; ++absline) { fseek (rear_fp, ((0 - s->params.lines) - absline - 2) * s->avdimen.hw_bytes_per_line, SEEK_SET); fwrite (ptr, s->avdimen.hw_bytes_per_line, 1, rear_fp); useful_bytes -= s->avdimen.hw_bytes_per_line; stripe_fill -= s->avdimen.hw_bytes_per_line; ptr += s->avdimen.hw_bytes_per_line; } DBG (9, "reader_process: after page flip: useful_bytes: %d, stripe_fill: %d\n", useful_bytes, stripe_fill); } else { /* * Perform needed data conversions (packing, ...) and/or copy the * image data. */ if (s->c_mode != AV_TRUECOLOR && s->c_mode != AV_TRUECOLOR16) /* simple copy */ { memcpy (out_data, stripe_data, useful_bytes); } else /* AV_TRUECOLOR* */ { /* WARNING: DO NOT MODIFY MY (HOPEFULLY WELL) OPTIMIZED ALGORITHMS BELOW, WITHOUT UNDERSTANDING THEM FULLY ! */ if (s->avdimen.line_difference > 0) /* color-pack */ { /* TODO: add 16bit per sample code? */ unsigned int i; int c_offset = s->avdimen.line_difference * s->avdimen.hw_bytes_per_line; uint8_t* r_ptr = stripe_data; uint8_t* g_ptr = stripe_data + c_offset + 1; uint8_t* b_ptr = stripe_data + 2 * c_offset + 2; for (i = 0; i < useful_bytes;) { out_data [i++] = *r_ptr; r_ptr += 3; out_data [i++] = *g_ptr; g_ptr += 3; out_data [i++] = *b_ptr; b_ptr += 3; } } /* end color pack */ else if (dev->inquiry_needs_line_pack) /* line-pack */ { /* TODO: add 16bit per sample code? */ int i = 0, l, p; const int lines = useful_bytes / s->avdimen.hw_bytes_per_line; for (l = 0; l < lines; ++l) { uint8_t* r_ptr = stripe_data + (s->avdimen.hw_bytes_per_line * l); uint8_t* g_ptr = r_ptr + s->avdimen.hw_pixels_per_line; uint8_t* b_ptr = g_ptr + s->avdimen.hw_pixels_per_line; for (p = 0; p < s->avdimen.hw_pixels_per_line; ++p) { out_data [i++] = *(r_ptr++); out_data [i++] = *(g_ptr++); out_data [i++] = *(b_ptr++); } } } /* end line pack */ else /* else no packing was required -> simple copy */ { memcpy (out_data, stripe_data, useful_bytes); } } /* end if AV_TRUECOLOR* */ /* FURTHER POST-PROCESSING ON THE FINAL OUTPUT DATA */ /* maybe mirroring in ADF mode */ if (s->source_mode_dim == AV_ADF_DIM && dev->inquiry_adf_need_mirror) { if ( (s->c_mode != AV_TRUECOLOR) || (s->c_mode == AV_TRUECOLOR && dev->inquiry_adf_bgr_order) ) { /* Mirroring with bgr -> rgb conversion: Just mirror the * whole line */ int l; int lines = useful_bytes / s->avdimen.hw_bytes_per_line; for (l = 0; l < lines; ++l) { uint8_t* begin_ptr = out_data + (l * s->avdimen.hw_bytes_per_line); uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line; while (begin_ptr < end_ptr) { uint8_t tmp; tmp = *begin_ptr; *begin_ptr++ = *end_ptr; *end_ptr-- = tmp; } } } else /* non trivial mirroring */ { /* Non-trivial Mirroring with element swapping */ int l; int lines = useful_bytes / s->avdimen.hw_bytes_per_line; for (l = 0; l < lines; ++l) { uint8_t* begin_ptr = out_data + (l * s->avdimen.hw_bytes_per_line); uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line - 3; while (begin_ptr < end_ptr) { uint8_t tmp; /* R */ tmp = *begin_ptr; *begin_ptr++ = *end_ptr; *end_ptr++ = tmp; /* G */ tmp = *begin_ptr; *begin_ptr++ = *end_ptr; *end_ptr++ = tmp; /* B */ tmp = *begin_ptr; *begin_ptr++ = *end_ptr; *end_ptr = tmp; end_ptr -= 5; } } } } /* end if mirroring needed */ /* byte swapping and software calibration 16bit mode */ if (s->c_mode == AV_GRAYSCALE12 || s->c_mode == AV_GRAYSCALE16 || s->c_mode == AV_TRUECOLOR12 || s->c_mode == AV_TRUECOLOR16) { int l; int lines = useful_bytes / s->avdimen.hw_bytes_per_line; uint8_t* dark_avg_data = s->dark_avg_data; uint8_t* white_avg_data = s->white_avg_data; uint8_t* begin_ptr = out_data; uint8_t* end_ptr = begin_ptr + s->avdimen.hw_bytes_per_line; uint8_t* line_ptr; double scale = 1.0; if (s->c_mode == AV_GRAYSCALE12 || s->c_mode == AV_TRUECOLOR12) scale = (double) (1<<4); while (begin_ptr < end_ptr) { uint16_t dark_avg = 0; uint16_t white_avg = WHITE_MAP_RANGE; if (dark_avg_data) dark_avg = get_double_le (dark_avg_data); if (white_avg_data) white_avg = get_double_le (white_avg_data); line_ptr = begin_ptr; for (l = 0; l < lines; ++ l) { double v = (double) get_double_le (line_ptr) * scale; uint16_t v2; if (0) v = (v - dark_avg) * white_avg / WHITE_MAP_RANGE; v2 = v < 0xFFFF ? v : 0xFFFF; /* SANE Standard 3.2.1 "... bytes of each sample value are transmitted in the machine's native byte order." */ *line_ptr = v2; line_ptr += s->avdimen.hw_bytes_per_line; } begin_ptr += 2; if (dark_avg_data) dark_avg_data += 2; if (white_avg_data) white_avg_data += 2; } } /* SOFTWARE SCALING WITH INTERPOLATION (IF NECESSARY) */ if (s->avdimen.hw_xres == s->avdimen.xres && s->avdimen.hw_yres == s->avdimen.yres) /* No scaling */ { int lines, _hw_line = hw_line; uint8_t* src = out_data; /* we support cropping at the beginning and end due to rear offset */ for (lines = useful_bytes / s->avdimen.hw_bytes_per_line; lines > 0; --lines, ++_hw_line, src += s->avdimen.hw_bytes_per_line) { if (deinterlace != NONE) { /* crop rear offset :-( */ if ( (!s->duplex_rear_valid && _hw_line >= s->avdimen.hw_lines) || (s->duplex_rear_valid && _hw_line < s->avdimen.rear_offset) ) { DBG (7, "reader_process: skip due read offset line: %d\n", line); continue; } } fwrite (src, s->avdimen.hw_bytes_per_line, 1, fp); ++line; } } else /* Software scaling - watch out - this code bites back! */ { int x; /* for convenience in the 16bit code path */ uint16_t* out_data16 = (uint16_t*) out_data; const int hw_line_end = hw_line + useful_bytes / s->avdimen.hw_bytes_per_line; /* on-the-fly bi-linear interpolation */ while (1) { 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); int sy = (int)floor(by); int ydist = (int) ((by - sy) * 256); int syy = sy + 1; const int hwbpl = s->avdimen.hw_bytes_per_line; uint8_t* dst = ip_data; uint16_t* dst16 = (uint16_t*) ip_data; unsigned int v; /* accumulator */ /* Break out if we do not have the hw source line - yet, or when we are past the end of wanted data (e.g. on the front page due to rear_offset). Also take the read_offset into account on the rear side */ if (deinterlace != NONE) { if (!s->duplex_rear_valid && syy >= s->avdimen.hw_lines) { DBG (7, "reader_process: skip due past intended front page lines: %d\n", sy); break; } else if (s->duplex_rear_valid) { /* the beginning is to be skipped, accessed thru offset */ DBG (7, "reader_process: rear_offset adjusting source: %d\n", sy); sy += s->avdimen.rear_offset; syy += s->avdimen.rear_offset; } } if (sy >= hw_line_end || syy >= hw_line_end) { DBG (3, "reader_process: source line %d-%d not yet avail\n", sy, syy); break; } /* convert to offset in current stripe */ sy -= hw_line; syy -= hw_line; if (sy < -1) { DBG (1, "reader_process: need more history: %d???\n", sy); sy = -1; } DBG (8, "reader_process: out line: %d <- from: %d-%d\n", line, sy, syy); for (x = 0; x < s->params.pixels_per_line; ++x) { const double bx = (-1.0 + s->avdimen.hw_pixels_per_line) * x / s->params.pixels_per_line; const int sx = (int)floor(bx); const int xdist = (int) ((bx - sx) * 256); const int sxx = sx + 1; if (x == 0 || x == s->params.pixels_per_line - 1) DBG (8, "reader_process: x: %d <- from: %d-%d\n", x, sx, sxx); switch (s->c_mode) { case AV_THRESHOLDED: case AV_DITHERED: { /* Repeating this over and over again is not fast, but as a seldom used code-path we want it readable. x/8 is the byte, and x%8 the bit position. */ v = ( ((out_data [sy*hwbpl + sx/8 ] >> (7-sx%8 )) & 1) * (256-xdist) * (256-ydist) + ((out_data [sy*hwbpl + sxx/8] >> (7-sxx%8)) & 1) * xdist * (256-ydist) + ((out_data [syy*hwbpl + sx/8 ] >> (7-sx%8 )) & 1) * (256-xdist) * ydist + ((out_data [syy*hwbpl + sxx/8] >> (7-sxx%8)) & 1) * xdist * ydist ) / (1 + 1 * 256); /* Shift and or the result together and eventually jump to the next byte. */ *dst = (*dst << 1) | ((v>>7)&1); if (x % 8 == 7) ++dst; } break; case AV_GRAYSCALE: { v = ( out_data [sy*hwbpl + sx ] * (256-xdist) * (256-ydist) + out_data [sy*hwbpl + sxx] * xdist * (256-ydist) + out_data [syy*hwbpl + sx ] * (256-xdist) * ydist + out_data [syy*hwbpl + sxx] * xdist * ydist ) / (256 * 256); *dst++ = v; } break; case AV_GRAYSCALE12: case AV_GRAYSCALE16: { /* TODO: test! */ v = ( out_data16 [sy*hwbpl + sx ] * (256-xdist) * (256-ydist) + out_data16 [sy*hwbpl + sxx] * xdist * (256-ydist) + out_data16 [syy*hwbpl + sx ] * (256-xdist) * ydist + out_data16 [syy*hwbpl + sxx] * xdist * ydist ) / (256 * 256); *dst16++ = v; } break; case AV_TRUECOLOR: { int c; for (c = 0; c < 3; ++c) { v = ( out_data [sy*hwbpl + sx*3 + c] * (256-xdist) * (256-ydist) + out_data [sy*hwbpl + sxx*3 + c] * xdist * (256-ydist) + out_data [syy*hwbpl + sx*3 + c] * (256-xdist) * ydist + out_data [syy*hwbpl + sxx*3 + c] * xdist * ydist ) / (256 * 256); *dst++ = v; } } break; case AV_TRUECOLOR12: case AV_TRUECOLOR16: { /* TODO: test! */ int c; for (c = 0; c < 3; ++c) { v = ( out_data16 [sy*hwbpl + sx*3 + c] * (256-xdist) * (256-ydist) + out_data16 [sy*hwbpl + sxx*3 + c] * xdist * (256-ydist) + out_data16 [syy*hwbpl + sx*3 + c] * (256-xdist) * ydist + out_data16 [syy*hwbpl + sxx*3 + c] * xdist * ydist ) / (256 * 256); *dst16++ = v; } } break; case AV_COLOR_MODE_LAST: ; /* silence compiler warning */ } } fwrite (ip_data, s->params.bytes_per_line, 1, fp); ++line; } /* copy one line of history for the next pass */ memcpy (ip_history, out_data + useful_bytes - s->avdimen.hw_bytes_per_line, s->avdimen.hw_bytes_per_line); } } /* save image date in stripe buffer for next next stripe */ stripe_fill -= useful_bytes; if (stripe_fill > 0) memcpy (stripe_data, stripe_data + useful_bytes, stripe_fill); hw_line += useful_bytes / s->avdimen.hw_bytes_per_line; DBG (3, "reader_process: end of iteration\n"); } /* end while not all lines or inf. mode */ DBG (3, "reader_process: i/o loop finished\n"); if (exit_status == SANE_STATUS_GOOD) exit_status = SANE_STATUS_EOF; if (raw_fp) fclose (raw_fp); /* maybe we need to fill in some white data */ if (exit_status == SANE_STATUS_EOF && line < s->params.lines) { DBG (3, "reader_process: padding with white data\n"); memset (out_data, gray_mode ? 0xff : 0x00, s->params.bytes_per_line); DBG (6, "reader_process: padding line %d - %d\n", line, s->params.lines); while (line < s->params.lines) { fwrite (out_data, s->params.bytes_per_line, 1, fp); ++line; } } /* Eject film holder and/or release_unit - but only for non-duplex-rear / non-virtual scans. */ if ((deinterlace != NONE && s->duplex_rear_valid) || ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && !(s->page % 2) && s->duplex_rear_valid)) { DBG (1, "reader_process: virtual duplex scan - no device cleanup!\n"); } else { /* poll the cancel button if the scanner is marked as having one */ if (dev->hw->feature_type & AV_CANCEL_BUTTON) { if (get_button_status (s) == SANE_STATUS_CANCELLED) exit_status = SANE_STATUS_CANCELLED; } status = release_unit (s, 0); if (status != SANE_STATUS_GOOD) DBG (1, "reader_process: release_unit failed\n"); if (dev->inquiry_new_protocol && dev->scanner_type == AV_FILM) { status = object_position (s, AVISION_SCSI_OP_GO_HOME); if (status != SANE_STATUS_GOOD) DBG (1, "reader_process: object position go-home failed!\n"); } } if ((dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && s->source_mode == AV_ADF_DUPLEX && s->page % 2) { /* front page of flipping duplex */ if (exit_status == SANE_STATUS_EOF) { if (s->val[OPT_ADF_FLIP].w) { /* The page flip bit must be reset after every scan, but if the * user doesn't care, there's no reason to reset. */ status = set_window (s); if (status != SANE_STATUS_GOOD) { DBG (1, "reader_process: set scan window command failed: %s\n", sane_strstatus (status)); return status; } } /* we can set anything here without fear because the process will terminate soon and take our changes with it */ s->page += 1; s->params.lines = -line; exit_status = reader_process (s); } /* TODO: * else { * spit out the page if an error was encountered... * assuming the error won't prevent it. * } */ } else { fclose (fp); } if (rear_fp) fclose (rear_fp); if (ip_data) free (ip_data); if (ip_history) free (ip_history); else free (out_data); /* if we have ip_history out_data is included there */ free (stripe_data); DBG (3, "reader_process: returning success\n"); return exit_status; } /* SANE callback to attach a SCSI device */ static SANE_Status attach_one_scsi (const char* dev) { attach (dev, AV_SCSI, 0); return SANE_STATUS_GOOD; } /* SANE callback to attach a USB device */ static SANE_Status attach_one_usb (const char* dev) { attach (dev, AV_USB, 0); return SANE_STATUS_GOOD; } static SANE_Status sane_reload_devices (void) { FILE* fp; char line[PATH_MAX]; const char* cp = 0; char* word; int linenumber = 0; int model_num = 0; sanei_usb_init (); fp = sanei_config_open (AVISION_CONFIG_FILE); if (fp <= (FILE*)0) { DBG (1, "sane_reload_devices: No config file present!\n"); } else { /* first parse the config file */ while (sanei_config_read (line, sizeof (line), fp)) { attaching_hw = 0; word = NULL; ++ linenumber; DBG (5, "sane_reload_devices: parsing config line \"%s\"\n", line); cp = sanei_config_get_string (line, &word); if (!word || cp == line) { DBG (5, "sane_reload_devices: config file line %d: ignoring empty line\n", linenumber); if (word) { free (word); word = NULL; } continue; } if (!word) { DBG (1, "sane_reload_devices: config file line %d: could not be parsed\n", linenumber); continue; } if (word[0] == '#') { DBG (5, "sane_reload_devices: config file line %d: ignoring comment line\n", linenumber); free (word); word = NULL; continue; } if (strcmp (word, "option") == 0) { free (word); word = NULL; cp = sanei_config_get_string (cp, &word); if (strcmp (word, "disable-gamma-table") == 0) { DBG (3, "sane_reload_devices: config file line %d: disable-gamma-table\n", linenumber); disable_gamma_table = SANE_TRUE; } else if (strcmp (word, "disable-calibration") == 0) { DBG (3, "sane_reload_devices: config file line %d: disable-calibration\n", linenumber); disable_calibration = SANE_TRUE; } else if (strcmp (word, "force-calibration") == 0) { DBG (3, "sane_reload_devices: config file line %d: force-calibration\n", linenumber); force_calibration = SANE_TRUE; } else if (strcmp (word, "force-a4") == 0) { DBG (3, "sane_reload_devices: config file line %d: enabling force-a4\n", linenumber); force_a4 = SANE_TRUE; } else if (strcmp (word, "force-a3") == 0) { DBG (3, "sane_reload_devices: config file line %d: enabling force-a3\n", linenumber); force_a3 = SANE_TRUE; } else if (strcmp (word, "skip-adf") == 0) { DBG (3, "sane_reload_devices: config file line %d: enabling skip-adf\n", linenumber); skip_adf = SANE_TRUE; } else if (strcmp (word, "static-red-calib") == 0) { DBG (3, "sane_reload_devices: config file line %d: static red calibration\n", linenumber); static_calib_list [0] = SANE_TRUE; } else if (strcmp (word, "static-green-calib") == 0) { DBG (3, "sane_reload_devices: config file line %d: static green calibration\n", linenumber); static_calib_list [1] = SANE_TRUE; } else if (strcmp (word, "static-blue-calib") == 0) { DBG (3, "sane_reload_devices: config file line %d: static blue calibration\n", linenumber); static_calib_list [2] = SANE_TRUE; } else DBG (1, "sane_reload_devices: config file line %d: options unknown!\n", linenumber); } else if (strcmp (word, "usb") == 0) { DBG (2, "sane_reload_devices: config file line %d: trying to attach USB:`%s'\n", linenumber, line); /* try to attach USB device */ sanei_usb_attach_matching_devices (line, attach_one_usb); } else if (strcmp (word, "scsi") == 0) { DBG (2, "sane_reload_devices: config file line %d: trying to attach SCSI: %s'\n", linenumber, line); /* the last time I verified (2003-03-18) this function only matches SCSI devices ... */ sanei_config_attach_matching_devices (line, attach_one_scsi); } else { DBG (1, "sane_reload_devices: config file line %d: OBSOLETE !! use the scsi keyword!\n", linenumber); DBG (1, "sane_reload_devices: (see man sane-avision for details): trying to attach SCSI: %s'\n", line); /* the last time I verified (2003-03-18) this function only matched SCSI devices ... */ sanei_config_attach_matching_devices (line, attach_one_scsi); } free (word); word = NULL; } /* end while read */ fclose (fp); if (word) free (word); } /* end if fp */ /* search for all supported SCSI/USB devices */ while (Avision_Device_List [model_num].scsi_mfg != NULL || Avision_Device_List [model_num].real_mfg != NULL) { /* also potentially accessed from the attach_* callbacks */ attaching_hw = &(Avision_Device_List [model_num]); if (attaching_hw->scsi_mfg != NULL) sanei_scsi_find_devices (attaching_hw->scsi_mfg, attaching_hw->scsi_model, NULL, -1, -1, -1, -1, attach_one_scsi); if (attaching_hw->usb_vendor != 0 && attaching_hw->usb_product != 0 ) { DBG (1, "sane_reload_devices: Trying to find USB device %.4x %.4x ...\n", attaching_hw->usb_vendor, attaching_hw->usb_product); /* TODO: check return value */ if (sanei_usb_find_devices (attaching_hw->usb_vendor, attaching_hw->usb_product, attach_one_usb) != SANE_STATUS_GOOD) { DBG (1, "sane_reload_devices: error during USB device detection!\n"); } } ++ model_num; } /* end for all devices in supported list */ attaching_hw = 0; return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int* version_code, SANE_Auth_Callback authorize) { authorize = authorize; /* silence gcc */ DBG_INIT(); #ifdef AVISION_STATIC_DEBUG_LEVEL DBG_LEVEL = AVISION_STATIC_DEBUG_LEVEL; #endif DBG (3, "sane_init:(Version: %i.%i Build: %i)\n", SANE_CURRENT_MAJOR, V_MINOR, BACKEND_BUILD); /* must come first */ sanei_thread_init (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BACKEND_BUILD); sane_reload_devices (); return SANE_STATUS_GOOD; } void sane_exit (void) { Avision_Device* dev; Avision_Device* next; DBG (3, "sane_exit:\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; /* no warning for stripping const - C lacks a const_cast<> */ free ((void*)(size_t) dev->sane.name); free (dev); } first_dev = NULL; free(devlist); devlist = NULL; } SANE_Status sane_get_devices (const SANE_Device*** device_list, SANE_Bool local_only) { Avision_Device* dev; int i; local_only = local_only; /* silence gcc */ DBG (3, "sane_get_devices:\n"); sane_reload_devices (); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle *handle) { Avision_Device* dev; SANE_Status status; Avision_Scanner* s; int i, j; uint8_t inquiry_result[AVISION_INQUIRY_SIZE_V1]; DBG (3, "sane_open:\n"); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (dev) { status = attach (devicename, dev->connection.connection_type, &dev); if (status != SANE_STATUS_GOOD) return status; } } else { /* empty devicename -> use first device */ dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; /* initialize ... */ /* the other states (scanning, ...) rely on this memset (0) */ memset (s, 0, sizeof (*s)); /* initialize connection state */ s->av_con.connection_type = dev->connection.connection_type; s->av_con.usb_status = dev->connection.usb_status; s->av_con.scsi_fd = -1; s->av_con.usb_dn = -1; s->reader_pid = -1; s->read_fds = -1; s->hw = dev; /* We initialize the table to a gamma value of 2.22, since this is what papers about Colorimetry suggest. http://www.poynton.com/GammaFAQ.html Avision's driver defaults to 2.2 though. */ { const double gamma = 2.22; const double one_over_gamma = 1. / gamma; for (i = 0; i < 4; ++ i) for (j = 0; j < 256; ++ j) s->gamma_table[i][j] = pow( (double) j / 255, one_over_gamma) * 255; } /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; /* open the device */ if (! avision_is_open (&s->av_con) ) { #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED DBG (1, "sane_open: using open_extended\n"); status = avision_open_extended (s->hw->sane.name, &s->av_con, sense_handler, 0, &(dev->scsi_buffer_size)); #else status = avision_open (s->hw->sane.name, &s->av_con, sense_handler, 0); #endif if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return status; } DBG (1, "sane_open: got %d scsi_max_request_size\n", dev->scsi_buffer_size); } /* first: re-awake the device with an inquiry, some devices are flunk while initializing the usb connection and like a inquiry to come first ... (AV610 et.al.) */ status = inquiry (s->av_con, inquiry_result, sizeof(inquiry_result)); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: awakening inquiry failed: %s\n", sane_strstatus (status)); return status; } status = wait_ready (&s->av_con, 1); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: wait_ready() failed: %s\n", sane_strstatus (status)); return status; } /* update settings based on additional accessory information */ status = additional_probe (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: additional probe failed: %s\n", sane_strstatus (status)); return status; } /* initialize the options */ init_options (s); if (dev->inquiry_duplex_interlaced || dev->scanner_type == AV_FILM || dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) { /* Might need at least *DOS (Windows flavour and OS/2) portability fix However, I was told Cygwin (et al.) takes care of it. */ strncpy(s->duplex_rear_fname, "/tmp/avision-rear-XXXXXX", PATH_MAX); if (! mktemp(s->duplex_rear_fname) ) { DBG (1, "sane_open: failed to generate temporary fname for duplex scans\n"); return SANE_STATUS_NO_MEM; } else { DBG (1, "sane_open: temporary fname for duplex scans: %s\n", s->duplex_rear_fname); } } /* calibrate film scanners, as this must be done without the film holder and at the full resolution */ if (dev->scanner_type == AV_FILM) { int default_res = s->val[OPT_RESOLUTION].w; s->val[OPT_RESOLUTION].w = dev->inquiry_optical_res; DBG (1, "sane_open: early calibration for film scanner.\n"); compute_parameters (s); status = set_window (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: set scan window command failed: %s\n", sane_strstatus (status)); return status; } if (!(dev->hw->feature_type & AV_NO_CALIB)) { status = normal_calibration (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: perform calibration failed: %s\n", sane_strstatus (status)); return status; } } if (dev->scanner_type == AV_FILM) { status = object_position (s, AVISION_SCSI_OP_GO_HOME); if (status != SANE_STATUS_GOOD) DBG (1, "reader_open: object position go-home failed!\n"); } s->val[OPT_RESOLUTION].w = default_res; } return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Avision_Scanner* prev; Avision_Scanner* s = handle; int i; DBG (3, "sane_close:\n"); /* close the device */ if (avision_is_open (&s->av_con) ) { avision_close (&s->av_con); } /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } /* a handle we know about ? */ if (!s) { DBG (1, "sane_close: invalid handle %p\n", handle); return; } if (s->scanning) do_cancel (handle); if (prev) prev->next = s->next; else first_handle = s->next; for (i = 1; i < NUM_OPTIONS; ++ i) { if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s) { free (s->val[i].s); } } if (s->white_avg_data) free (s->white_avg_data); if (s->dark_avg_data) free (s->dark_avg_data); if (s->background_raster) free (s->background_raster); if (*(s->duplex_rear_fname)) { unlink (s->duplex_rear_fname); *(s->duplex_rear_fname) = 0; } free (handle); } const SANE_Option_Descriptor* sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Avision_Scanner* s = handle; DBG (3, "sane_get_option_descriptor: %d\n", option); if ((unsigned) option >= NUM_OPTIONS) return 0; return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void* val, SANE_Int* info) { Avision_Scanner* s = handle; Avision_Device* dev = s->hw; SANE_Status status; SANE_Word cap; DBG (3, "sane_control_option: option=%d, action=%d\n", (int)option, (int)action); DBG (5, "sane_control_option: option=%s, action=%s\n", s->opt[option].name, action == SANE_ACTION_GET_VALUE ? "GET" : (action == SANE_ACTION_SET_VALUE ? "SET" : (action == SANE_ACTION_SET_AUTO ? "AUTO" : "UNKNOWN") ) ); if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_PREVIEW: case OPT_RESOLUTION: case OPT_SPEED: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_OVERSCAN_TOP: case OPT_OVERSCAN_BOTTOM: case OPT_BACKGROUND: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_EXPOSURE: case OPT_IR: case OPT_MULTISAMPLE: case OPT_QSCAN: case OPT_QCALIB: case OPT_PAPERLEN: case OPT_ADF_FLIP: *(SANE_Word*) val = s->val[option].w; return SANE_STATUS_GOOD; /* specially treated word options */ case OPT_FRAME: status = get_frame_info (s); *(SANE_Word*) val = s->val[option].w; return status; case OPT_POWER_SAVE_TIME: get_power_save_time (s, &(s->val[option].w)); *(SANE_Word*) val = s->val[option].w; return SANE_STATUS_GOOD; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); return SANE_STATUS_GOOD; /* string options: */ case OPT_MODE: case OPT_SOURCE: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; /* specially treated string options */ case OPT_MESSAGE: if (dev->inquiry_button_control || dev->inquiry_buttons) status = get_button_status (s); strcpy (val, s->val[option].s); s->val[option].s[0] = 0; return SANE_STATUS_GOOD; case OPT_NVRAM: get_and_parse_nvram (s, s->val[option].s, 1024); strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; } /* end switch option */ } /* end if GET_ACTION_GET_VALUE */ else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = constrain_value (s, option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* side-effect-free word options: */ case OPT_SPEED: case OPT_PREVIEW: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_EXPOSURE: case OPT_IR: case OPT_MULTISAMPLE: case OPT_QSCAN: case OPT_QCALIB: case OPT_OVERSCAN_TOP: case OPT_OVERSCAN_BOTTOM: case OPT_BACKGROUND: case OPT_PAPERLEN: case OPT_ADF_FLIP: s->val[option].w = *(SANE_Word*) val; return SANE_STATUS_GOOD; /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); return SANE_STATUS_GOOD; /* options with side-effects: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word*) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; /* string options with side-effects: */ case OPT_SOURCE: if (s->val[option].s) { free(s->val[option].s); } s->val[option].s = strdup(val); s->source_mode = match_source_mode (dev, s->val[option].s); s->source_mode_dim = match_source_mode_dim (s->source_mode); /* set side-effects */ dev->x_range.max = SANE_FIX ( dev->inquiry_x_ranges[s->source_mode_dim]); dev->y_range.max = SANE_FIX ( dev->inquiry_y_ranges[s->source_mode_dim]); if (s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX) { s->opt[OPT_ADF_FLIP].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_MODE: { if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); s->c_mode = match_color_mode (dev, s->val[OPT_MODE].s); /* set to mode specific values */ /* the gamma table related */ if (!disable_gamma_table) { if (color_mode_is_color (s->c_mode) ) { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } else /* gray or mono */ { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; } case OPT_FRAME: { SANE_Word frame = *((SANE_Word *) val); status = set_frame (s, frame); if (status == SANE_STATUS_GOOD) { s->val[OPT_FRAME].w = frame; dev->current_frame = frame; } return status; } case OPT_POWER_SAVE_TIME: { SANE_Word time = *((SANE_Word *) val); status = set_power_save_time (s, time); if (status == SANE_STATUS_GOOD) s->val[OPT_POWER_SAVE_TIME].w = time; return status; } } /* end switch option */ } else if (action == SANE_ACTION_SET_AUTO) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; switch (option) { case OPT_ADF_FLIP: s->val[option].w = SANE_TRUE; return SANE_STATUS_GOOD; } /* end switch option */ } /* end else SET_VALUE */ return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters* params) { Avision_Scanner* s = handle; DBG (3, "sane_get_parameters:\n"); /* During an actual scan these parameters will have been computed in sane_start(). Otherwise, the values must be computed on demand. The values cannot be changed during a scan to avoid inconsistency. */ if (!s->scanning) { DBG (3, "sane_get_parameters: computing parameters\n"); compute_parameters (s); } if (params) { *params = s->params; /* add background raster lines */ params->lines += s->val[OPT_BACKGROUND].w; } return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Avision_Scanner* s = handle; Avision_Device* dev = s->hw; SANE_Status status; int fds [2]; DBG (1, "sane_start:\n"); /* Make sure there is no scan running!!! */ if (s->scanning) return SANE_STATUS_DEVICE_BUSY; /* Clear cancellation status */ s->cancelled = 0; /* Make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, &s->params); if (status != SANE_STATUS_GOOD) { return status; } /* for non ADF scans (e.g. scanimage --batch-prompt on a Flatbed scanner) make sure we do not assume it's an ADF scan and optimize something away*/ if (!is_adf_scan (s)) s->page = 0; if (s->page > 0 && s->duplex_rear_valid) { DBG (1, "sane_start: virtual duplex rear data valid.\n"); goto start_scan_end; } /* Check for paper during ADF scans and for sheetfed scanners. */ if (is_adf_scan (s)) { status = media_check (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: media_check failed: %s\n", sane_strstatus (status)); return status; } else DBG (1, "sane_start: media_check ok\n"); } /* Check the light early, to return to the GUI and notify the user. */ if (s->prepared == SANE_FALSE) { if (dev->inquiry_light_control) { status = wait_4_light (s); if (status != SANE_STATUS_GOOD) { return status; } } } if (s->page > 0 && dev->inquiry_keeps_window) { DBG (1, "sane_start: Optimized set_window away.\n"); } else { status = set_window (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: set scan window command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } /* Re-check the light, as setting the window may have changed * which light is to be turned on. */ if (s->prepared == SANE_FALSE && dev->inquiry_light_control) { status = wait_4_light (s); if (status != SANE_STATUS_GOOD) { return status; } } } #ifdef DEBUG_TEST /* debug window size test ... */ if (dev->inquiry_new_protocol) { size_t size = 16; uint8_t result[16]; DBG (5, "sane_start: reading scanner window size\n"); status = simple_read (s, 0x80, 0, &size, result); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: get pixel size command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } debug_print_raw (5, "sane_start: pixel_size:", result, size); DBG (5, "sane_start: x-pixels: %d, y-pixels: %d\n", get_quad (&(result[0])), get_quad (&(result[4]))); } #endif /* no calibration for ADF pages */ if (s->page > 0) { DBG (1, "sane_start: optimized calibration away.\n"); goto calib_end; } /* check whether the user enforces calibration */ if (force_calibration) { DBG (1, "sane_start: calibration enforced in config!\n"); goto calib; } /* Only perform the calibration for newer scanners - it is not needed for my Avision AV 630 - and also does not even work ... */ if (!dev->inquiry_new_protocol) { DBG (1, "sane_start: old protocol no calibration needed!\n"); goto calib_end; } if (!dev->inquiry_needs_calibration) { DBG (1, "sane_start: due to inquiry no calibration needed!\n"); goto calib_end; } /* calibration allowed for this scanner? */ if (dev->hw->feature_type & AV_NO_CALIB) { DBG (1, "sane_start: calibration disabled in device list!!\n"); goto calib_end; } /* Not for film scanners, ... */ if (dev->scanner_type == AV_FILM) { DBG (1, "sane_start: no calibration for film scanner!\n"); goto calib_end; } /* check whether calibration is disabled by the user */ if (disable_calibration) { DBG (1, "sane_start: calibration disabled in config - skipped!\n"); goto calib_end; } /* R² reminder: We must not skip the calibration for ADF scans, some scanner (HP 53xx/74xx ASIC series) rely on a calibration data read (and will hang otherwise) */ calib: status = normal_calibration (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: perform calibration failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } calib_end: if (dev->inquiry_3x3_matrix && dev->inquiry_asic_type >= AV_ASIC_C6 && s->page == 0) { status = send_3x3_matrix (s); if (status != SANE_STATUS_GOOD) { return status; } } /* check whether gamma-table is disabled by the user? */ if (disable_gamma_table) { DBG (1, "sane_start: gamma-table disabled in config - skipped!\n"); goto gamma_end; } if (dev->hw->feature_type & AV_NO_GAMMA) { DBG (1, "sane_start: gamma table skipped due to device-list!!\n"); goto gamma_end; } if (s->page > 0 && dev->inquiry_keeps_gamma) DBG (1, "sane_start: Optimized send_gamma away.\n"); else { status = send_gamma (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: send gamma failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } } gamma_end: if (dev->inquiry_tune_scan_length && is_adf_scan (s)) { status = send_tune_scan_length (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: tune_scan_length command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } } /* if the device supports retrieving background raster data inquire the data no matter if the user/applications asks for it in order to use it for bottom padding */ if (s->page == 0 && dev->inquiry_background_raster) { status = get_background_raster (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: get background raster command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } } /* check film holder */ if (dev->scanner_type == AV_FILM && dev->holder_type == 0xff) { DBG (1, "sane_start: no film holder or APS cassette!\n"); /* Normally "go_home" is executed from the reader process, but as it will not start we have to reset things here */ if (dev->inquiry_new_protocol) { status = object_position (s, AVISION_SCSI_OP_GO_HOME); if (status != SANE_STATUS_GOOD) DBG (1, "sane_start: go home failed: %s\n", sane_strstatus (status)); } goto stop_scanner_and_return; } start_scan_end: s->scanning = SANE_TRUE; s->page += 1; /* processing next page */ if (pipe (fds) < 0) { return SANE_STATUS_IO_ERROR; } s->read_fds = fds[0]; s->write_fds = fds[1]; /* create reader routine as new process or thread */ DBG (3, "sane_start: starting thread\n"); s->reader_pid = sanei_thread_begin (reader_process, (void *) s); if (sanei_thread_is_forked()) close (s->write_fds); return SANE_STATUS_GOOD; stop_scanner_and_return: /* cancel the scan nicely */ do_cancel (s); return status; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte* buf, SANE_Int max_len, SANE_Int* len) { Avision_Scanner* s = handle; ssize_t nread; *len = 0; DBG (8, "sane_read: max_len: %d\n", max_len); nread = read (s->read_fds, buf, max_len); if (nread > 0) { DBG (8, "sane_read: got %ld bytes\n", (long) nread); } else { DBG (3, "sane_read: got %ld bytes, err: %d %s\n", (long) nread, errno, strerror(errno)); } if (!s->scanning) return SANE_STATUS_CANCELLED; if (nread < 0) { if (errno == EAGAIN) { return SANE_STATUS_GOOD; } else { do_cancel (s); return SANE_STATUS_IO_ERROR; } } *len = nread; /* if all data was passed through */ if (nread == 0) return do_eof (s); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Avision_Scanner* s = handle; DBG (3, "sane_cancel:\n"); /* always do the housekeeping, e.g. flush batch scanner pages */ do_cancel (s); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Avision_Scanner* s = handle; DBG (3, "sane_set_io_mode:\n"); if (!s->scanning) { DBG (3, "sane_set_io_mode: not yet scanning\n"); return SANE_STATUS_INVAL; } if (fcntl (s->read_fds, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int* fd) { Avision_Scanner* s = handle; DBG (3, "sane_get_select_fd:\n"); if (!s->scanning) { DBG (3, "sane_get_select_fd: not yet scanning\n"); return SANE_STATUS_INVAL; } *fd = s->read_fds; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/genesys_conv.c0000664000175000017500000003074012775312261015471 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005, 2006 Pierre Willenbrock Copyright (C) 2010-2013 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* * Conversion filters for genesys backend */ /*8 bit*/ #define SINGLE_BYTE #define BYTES_PER_COMPONENT 1 #define COMPONENT_TYPE uint8_t #define FUNC_NAME(f) f ## _8 #include "genesys_conv_hlp.c" #undef FUNC_NAME #undef COMPONENT_TYPE #undef BYTES_PER_COMPONENT #undef SINGLE_BYTE /*16 bit*/ #define DOUBLE_BYTE #define BYTES_PER_COMPONENT 2 #define COMPONENT_TYPE uint16_t #define FUNC_NAME(f) f ## _16 #include "genesys_conv_hlp.c" #undef FUNC_NAME #undef COMPONENT_TYPE #undef BYTES_PER_COMPONENT #undef DOUBLE_BYTE static SANE_Status genesys_reverse_bits( uint8_t *src_data, uint8_t *dst_data, size_t bytes) { size_t i; for(i = 0; i < bytes; i++) { *dst_data++ = ~ *src_data++; } return SANE_STATUS_GOOD; } /** * uses the threshold/threshold_curve to control software binarization * This code was taken from the epjistsu backend by m. allan noah * @param dev device set up for the scan * @param src pointer to raw data * @param dst pointer where to store result * @param width width of the processed line * */ static SANE_Status binarize_line(Genesys_Device * dev, uint8_t *src, uint8_t *dst, int width) { int j, windowX, sum = 0; int thresh; int offset, addCol, dropCol; unsigned char mask; int x; uint8_t min, max; /* normalize line */ min = 255; max = 0; for (x = 0; x < width; x++) { if (src[x] > max) { max = src[x]; } if (src[x] < min) { min = src[x]; } } /* safeguard against dark or white areas */ if(min>80) min=0; if(max<80) max=255; for (x = 0; x < width; x++) { src[x] = ((src[x] - min) * 255) / (max - min); } /* ~1mm works best, but the window needs to have odd # of pixels */ windowX = (6 * dev->settings.xres) / 150; if (!(windowX % 2)) windowX++; /* second, prefill the sliding sum */ for (j = 0; j < windowX; j++) sum += src[j]; /* third, walk the input buffer, update the sliding sum, */ /* determine threshold, output bits */ for (j = 0; j < width; j++) { /* output image location */ offset = j % 8; mask = 0x80 >> offset; thresh = dev->settings.threshold; /* move sum/update threshold only if there is a curve */ if (dev->settings.threshold_curve) { addCol = j + windowX / 2; dropCol = addCol - windowX; if (dropCol >= 0 && addCol < width) { sum -= src[dropCol]; sum += src[addCol]; } thresh = dev->lineart_lut[sum / windowX]; } /* use average to lookup threshold */ if (src[j] > thresh) *dst &= ~mask; /* white */ else *dst |= mask; /* black */ if (offset == 7) dst++; } return SANE_STATUS_GOOD; } /** * software lineart using data from a 8 bit gray scan. We assume true gray * or monochrome scan as input. */ static SANE_Status genesys_gray_lineart( Genesys_Device *dev, uint8_t *src_data, uint8_t *dst_data, size_t pixels, size_t lines, uint8_t threshold) { size_t y; DBG (DBG_io2, "genesys_gray_lineart: converting %lu lines of %lu pixels\n", (unsigned long)lines, (unsigned long)pixels); DBG (DBG_io2, "genesys_gray_lineart: threshold=%d\n",threshold); for (y = 0; y < lines; y++) { binarize_line (dev, src_data + y * pixels, dst_data, pixels); dst_data += pixels / 8; } return SANE_STATUS_GOOD; } /** @brief shrink or grow scanned data to fit the final scan size * This function shrinks the scanned data it the required resolution is lower than the hardware one, * or grows it in case it is the opposite like when motor resolution is higher than * sensor's one. */ static SANE_Status genesys_shrink_lines_1 ( uint8_t *src_data, uint8_t *dst_data, unsigned int lines, unsigned int src_pixels, unsigned int dst_pixels, unsigned int channels) { unsigned int dst_x, src_x, y, c, cnt; unsigned int avg[3], val; uint8_t *src = (uint8_t *) src_data; uint8_t *dst = (uint8_t *) dst_data; /* choose between case where me must reduce or grow the scanned data */ if (src_pixels > dst_pixels) { /* shrink data */ /* TODO action must be taken at bit level, no bytes */ src_pixels /= 8; dst_pixels /= 8; /*take first _byte_ */ for (y = 0; y < lines; y++) { cnt = src_pixels / 2; src_x = 0; for (dst_x = 0; dst_x < dst_pixels; dst_x++) { while (cnt < src_pixels && src_x < src_pixels) { cnt += dst_pixels; for (c = 0; c < channels; c++) avg[c] = *src++; src_x++; } cnt -= src_pixels; for (c = 0; c < channels; c++) *dst++ = avg[c]; } } } else { /* common case where y res is double x res */ for (y = 0; y < lines; y++) { if (2 * src_pixels == dst_pixels) { /* double and interleave on line */ for (c = 0; c < src_pixels/8; c++) { /* first 4 bits */ val = 0; val |= (*src & 0x80) >> 0; /* X___ ____ --> X___ ____ */ val |= (*src & 0x80) >> 1; /* X___ ____ --> _X__ ____ */ val |= (*src & 0x40) >> 1; /* _X__ ____ --> __X_ ____ */ val |= (*src & 0x40) >> 2; /* _X__ ____ --> ___X ____ */ val |= (*src & 0x20) >> 2; /* __X_ ____ --> ____ X___ */ val |= (*src & 0x20) >> 3; /* __X_ ____ --> ____ _X__ */ val |= (*src & 0x10) >> 3; /* ___X ____ --> ____ __X_ */ val |= (*src & 0x10) >> 4; /* ___X ____ --> ____ ___X */ *dst = val; dst++; /* last for bits */ val = 0; val |= (*src & 0x08) << 4; /* ____ X___ --> X___ ____ */ val |= (*src & 0x08) << 3; /* ____ X___ --> _X__ ____ */ val |= (*src & 0x04) << 3; /* ____ _X__ --> __X_ ____ */ val |= (*src & 0x04) << 2; /* ____ _X__ --> ___X ____ */ val |= (*src & 0x02) << 2; /* ____ __X_ --> ____ X___ */ val |= (*src & 0x02) << 1; /* ____ __X_ --> ____ _X__ */ val |= (*src & 0x01) << 1; /* ____ ___X --> ____ __X_ */ val |= (*src & 0x01) << 0; /* ____ ___X --> ____ ___X */ *dst = val; dst++; src++; } } else { /* TODO: since depth is 1, we must interpolate bit within bytes */ DBG (DBG_warn, "%s: inaccurate bit expansion!\n", __func__); cnt = dst_pixels / 2; dst_x = 0; for (src_x = 0; src_x < src_pixels; src_x++) { for (c = 0; c < channels; c++) avg[c] = *src++; while (cnt < dst_pixels && dst_x < dst_pixels) { cnt += src_pixels; for (c = 0; c < channels; c++) *dst++ = avg[c]; dst_x++; } cnt -= dst_pixels; } } } } return SANE_STATUS_GOOD; } /** Look in image for likely left/right/bottom paper edges, then crop image. * Since failing to crop isn't fatal, we always return SANE_STATUS_GOOD . */ static SANE_Status genesys_crop(Genesys_Scanner *s) { SANE_Status status; Genesys_Device *dev = s->dev; int top = 0; int bottom = 0; int left = 0; int right = 0; DBG (DBG_proc, "%s: start\n", __func__); /* first find edges if any */ status = sanei_magic_findEdges (&s->params, dev->img_buffer, dev->settings.xres, dev->settings.yres, &top, &bottom, &left, &right); if (status != SANE_STATUS_GOOD) { DBG (DBG_info, "%s: bad or no edges, bailing\n", __func__); goto cleanup; } DBG (DBG_io, "%s: t:%d b:%d l:%d r:%d\n", __func__, top, bottom, left, right); /* now crop the image */ status = sanei_magic_crop (&(s->params), dev->img_buffer, top, bottom, left, right); if (status) { DBG (DBG_warn, "%s: failed to crop\n", __func__); goto cleanup; } /* update counters to new image size */ dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines; cleanup: DBG (DBG_proc, "%s: completed\n", __func__); return SANE_STATUS_GOOD; } /** Look in image for likely upper and left paper edges, then rotate * image so that upper left corner of paper is upper left of image. * @return since failure doens't prevent scanning, we always return * SANE_STATUS_GOOD */ static SANE_Status genesys_deskew(Genesys_Scanner *s) { SANE_Status status; Genesys_Device *dev = s->dev; int x = 0, y = 0, bg; double slope = 0; DBG (DBG_proc, "%s: start\n", __func__); bg=0; if(s->params.format==SANE_FRAME_GRAY && s->params.depth == 1) { bg=0xff; } status = sanei_magic_findSkew (&s->params, dev->img_buffer, dev->sensor.optical_res, dev->sensor.optical_res, &x, &y, &slope); if (status!=SANE_STATUS_GOOD) { DBG (DBG_error, "%s: bad findSkew, bailing\n", __func__); return SANE_STATUS_GOOD; } DBG(DBG_info, "%s: slope=%f => %f\n",__func__,slope, (slope/M_PI_2)*90); /* rotate image slope is in [-PI/2,PI/2] * positive values rotate trigonometric direction wise */ status = sanei_magic_rotate (&s->params, dev->img_buffer, x, y, slope, bg); if (status!=SANE_STATUS_GOOD) { DBG (DBG_error, "%s: rotate error: %s", __func__, sane_strstatus(status)); } DBG (DBG_proc, "%s: completed\n", __func__); return SANE_STATUS_GOOD; } /** remove lone dots * @return since failure doens't prevent scanning, we always return * SANE_STATUS_GOOD */ static SANE_Status genesys_despeck(Genesys_Scanner *s) { if(sanei_magic_despeck(&s->params, s->dev->img_buffer, s->val[OPT_DESPECK].w)!=SANE_STATUS_GOOD) { DBG (DBG_error, "%s: bad despeck, bailing\n",__func__); } return SANE_STATUS_GOOD; } /** Look if image needs rotation and apply it * */ static SANE_Status genesys_derotate (Genesys_Scanner * s) { SANE_Status status; int angle = 0; int resolution = s->val[OPT_RESOLUTION].w; DBGSTART; status = sanei_magic_findTurn (&s->params, s->dev->img_buffer, resolution, resolution, &angle); if (status) { DBG (DBG_warn, "%s: failed : %d\n", __func__, status); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* apply rotation angle found */ status = sanei_magic_turn (&s->params, s->dev->img_buffer, angle); if (status) { DBG (DBG_warn, "%s: failed : %d\n", __func__, status); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* update counters to new image size */ s->dev->total_bytes_to_read = s->params.bytes_per_line * s->params.lines; DBGCOMPLETED; return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/dll.conf.in0000664000175000017500000000210013106201017014620 00000000000000# dll.conf - Configuration file for the SANE dynamic backend loader # # Backends can also be enabled by configuration snippets under the dll.d/ # directory -- third party backends can drop their configuration file in # this in this directory, named after the backend. # # The next line enables the network backend; comment it out if you don't # need to use a remote SANE scanner over the network -- see sane-net(5) # and saned(8) for details. net abaton agfafocus apple avision artec artec_eplus48u as6e bh canon canon630u canon_dr #canon_pp cardscan coolscan #coolscan2 coolscan3 #dc25 #dc210 #dc240 dell1600n_net dmc epjitsu #epson epson2 epsonds fujitsu #gphoto2 genesys gt68xx hp hp3900 hpsj5s hp3500 hp4200 hp5400 hp5590 hpljm1005 hs2p ibm kodak kodakaio kvs1025 kvs20xx leo lexmark ma1509 magicolor matsushita microtek microtek2 mustek #mustek_pp mustek_usb mustek_usb2 nec niash #p5 pie pint pixma plustek #plustek_pp #pnm qcam ricoh rts8891 s9036 sceptre sharp sm3600 sm3840 snapscan sp15c #st400 #stv680 tamarack teco1 teco2 teco3 #test u12 umax #umax_pp umax1220u v4l xerox_mfp sane-backends-1.0.27/backend/kvs40xx_cmd.c0000664000175000017500000002705212775312261015143 00000000000000/* Copyright (C) 2009, Panasonic Russia Ltd. Copyright (C) 2010,2011, m. allan noah */ /* Panasonic KV-S40xx USB-SCSI scanner driver. */ #include "../include/sane/config.h" #include #define DEBUG_DECLARE_ONLY #define BACKEND_NAME kvs40xx #include "../include/sane/sanei_backend.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_config.h" #include "kvs40xx.h" #include "../include/sane/sanei_debug.h" #define COMMAND_BLOCK 1 #define DATA_BLOCK 2 #define RESPONSE_BLOCK 3 #define COMMAND_CODE 0x9000 #define DATA_CODE 0xb000 #define RESPONSE_CODE 0xa000 #define STATUS_SIZE 4 struct bulk_header { u32 length; u16 type; u16 code; u32 transaction_id; }; #define TEST_UNIT_READY 0x00 #define INQUIRY 0x12 #define SET_WINDOW 0x24 #define SCAN 0x1B #define SEND_10 0x2A #define READ_10 0x28 #define REQUEST_SENSE 0x03 #define GET_BUFFER_STATUS 0x34 #define SET_TIMEOUT 0xE1 #define GET_ADJUST_DATA 0xE0 #define HOPPER_DOWN 0xE1 #define STOP_ADF 0xE1 #define SUPPORT_INFO 0x93 #define GOOD 0 #define CHECK_CONDITION 2 typedef enum { CMD_NONE = 0, CMD_IN = 0x81, /* scanner to pc */ CMD_OUT = 0x02 /* pc to scanner */ } CMD_DIRECTION; /* equals to endpoint address */ #define RESPONSE_SIZE 0x12 #define MAX_CMD_SIZE 12 struct cmd { unsigned char cmd[MAX_CMD_SIZE]; int cmd_size; void *data; int data_size; int dir; }; struct response { int status; unsigned char data[RESPONSE_SIZE]; }; static SANE_Status usb_send_command (struct scanner *s, struct cmd *c, struct response *r, void *buf) { SANE_Status st; struct bulk_header *h = (struct bulk_header *) buf; u8 resp[sizeof (*h) + STATUS_SIZE]; size_t sz = sizeof (*h) + MAX_CMD_SIZE; memset (h, 0, sz); h->length = cpu2be32 (sz); h->type = cpu2be16 (COMMAND_BLOCK); h->code = cpu2be16 (COMMAND_CODE); memcpy (h + 1, c->cmd, c->cmd_size); st = sanei_usb_write_bulk (s->file, (const SANE_Byte *) h, &sz); if (st) return st; if (sz != sizeof (*h) + MAX_CMD_SIZE) return SANE_STATUS_IO_ERROR; if (c->dir == CMD_IN) { unsigned l; sz = sizeof (*h) + c->data_size; c->data_size = 0; st = sanei_usb_read_bulk (s->file, (SANE_Byte *) h, &sz); for (l = sz; !st && l != be2cpu32 (h->length); l += sz) { DBG (DBG_WARN, "usb wrong read (%d instead %d)\n", c->data_size, be2cpu32 (h->length)); sz = be2cpu32 (h->length) - l; st = sanei_usb_read_bulk (s->file, ((SANE_Byte *) h) + l, &sz); } c->data = h + 1; if (st) { st = sanei_usb_release_interface (s->file, 0); if (st) return st; st = sanei_usb_claim_interface (s->file, 0); if (st) return st; r->status = CHECK_CONDITION; return SANE_STATUS_GOOD; } c->data_size = sz - sizeof (*h); } else if (c->dir == CMD_OUT) { sz = sizeof (*h) + c->data_size; memset (h, 0, sizeof (*h)); h->length = cpu2be32 (sizeof (*h) + c->data_size); h->type = cpu2be16 (DATA_BLOCK); h->code = cpu2be16 (DATA_CODE); memcpy (h + 1, c->data, c->data_size); st = sanei_usb_write_bulk (s->file, (const SANE_Byte *) h, &sz); if (st) return st; } sz = sizeof (resp); st = sanei_usb_read_bulk (s->file, resp, &sz); if (st || sz != sizeof (resp)) return SANE_STATUS_IO_ERROR; r->status = be2cpu32 (*((u32 *) (resp + sizeof (*h)))); return st; } #define END_OF_MEDIUM (1<<6) #define INCORRECT_LENGTH_INDICATOR (1<<5) static const struct { unsigned sense, asc, ascq; SANE_Status st; } s_errors[] = { { 2, 0, 0, SANE_STATUS_DEVICE_BUSY}, { 2, 4, 1, SANE_STATUS_DEVICE_BUSY}, { 2, 4, 0x80, SANE_STATUS_COVER_OPEN}, { 2, 4, 0x81, SANE_STATUS_COVER_OPEN}, { 2, 4, 0x82, SANE_STATUS_COVER_OPEN}, { 2, 4, 0x83, SANE_STATUS_COVER_OPEN}, { 2, 4, 0x84, SANE_STATUS_COVER_OPEN}, { 2, 0x80, 1, SANE_STATUS_CANCELLED}, { 2, 0x80, 2, SANE_STATUS_CANCELLED}, { 3, 0x3a, 0, SANE_STATUS_NO_DOCS}, { 3, 0x80, 1, SANE_STATUS_JAMMED}, { 3, 0x80, 2, SANE_STATUS_JAMMED}, { 3, 0x80, 3, SANE_STATUS_JAMMED}, { 3, 0x80, 4, SANE_STATUS_JAMMED}, { 3, 0x80, 5, SANE_STATUS_JAMMED}, { 3, 0x80, 6, SANE_STATUS_JAMMED}, { 3, 0x80, 7, SANE_STATUS_JAMMED}, { 3, 0x80, 8, SANE_STATUS_JAMMED}, { 3, 0x80, 9, SANE_STATUS_JAMMED}, { 3, 0x80, 0xa, SANE_STATUS_JAMMED}, { 3, 0x80, 0xb, SANE_STATUS_JAMMED}, { 3, 0x80, 0xc, SANE_STATUS_JAMMED}, { 3, 0x80, 0xd, SANE_STATUS_JAMMED}, { 3, 0x80, 0xe, SANE_STATUS_JAMMED}, { 3, 0x80, 0xf, SANE_STATUS_JAMMED}, { 3, 0x80, 0x10, SANE_STATUS_JAMMED}, { 3, 0x80, 0x11, SANE_STATUS_JAMMED}, { 5, 0x1a, 0x0, SANE_STATUS_INVAL}, { 5, 0x20, 0x0, SANE_STATUS_INVAL}, { 5, 0x24, 0x0, SANE_STATUS_INVAL}, { 5, 0x25, 0x0, SANE_STATUS_INVAL}, { 5, 0x26, 0x0, SANE_STATUS_INVAL}, { 5, 0x2c, 0x01, SANE_STATUS_INVAL}, { 5, 0x2c, 0x02, SANE_STATUS_INVAL}, { 5, 0x2c, 0x80, SANE_STATUS_INVAL}, { 5, 0x2c, 0x81, SANE_STATUS_INVAL}, { 5, 0x2c, 0x82, SANE_STATUS_INVAL}, { 5, 0x2c, 0x83, SANE_STATUS_INVAL},}; SANE_Status kvs40xx_sense_handler (int __sane_unused__ fd, u_char * sense_buffer, void __sane_unused__ * arg) { unsigned i; SANE_Status st = SANE_STATUS_GOOD; if (sense_buffer[2] & 0xf) { /*error */ for (i = 0; i < sizeof (s_errors) / sizeof (s_errors[0]); i++) { if ((sense_buffer[2] & 0xf) == s_errors[i].sense && sense_buffer[12] == s_errors[i].asc && sense_buffer[13] == s_errors[i].ascq) { st = s_errors[i].st; break; } } if (i == sizeof (s_errors) / sizeof (s_errors[0])) st = SANE_STATUS_IO_ERROR; } else { if (sense_buffer[2] & END_OF_MEDIUM) st = SANE_STATUS_EOF; else if (sense_buffer[2] & INCORRECT_LENGTH_INDICATOR) st = INCORRECT_LENGTH; } DBG (DBG_ERR, "send_command: CHECK_CONDITION: sence:0x%x ASC:0x%x ASCQ:0x%x\n", sense_buffer[2], sense_buffer[12], sense_buffer[13]); return st; } static SANE_Status send_command (struct scanner * s, struct cmd * c) { SANE_Status st = SANE_STATUS_GOOD; if (s->bus == USB) { struct response r; memset (&r, 0, sizeof (r)); st = usb_send_command (s, c, &r, s->buffer); if (st) return st; if (r.status) { u8 b[sizeof (struct bulk_header) + RESPONSE_SIZE]; struct cmd c2 = { {0}, 6, NULL, RESPONSE_SIZE, CMD_IN }; c2.cmd[0] = REQUEST_SENSE; c2.cmd[4] = RESPONSE_SIZE; st = usb_send_command (s, &c2, &r, b); if (st) return st; st = kvs40xx_sense_handler (0, b + sizeof (struct bulk_header), NULL); } } else { if (c->dir == CMD_OUT) { memcpy (s->buffer, c->cmd, c->cmd_size); memcpy (s->buffer + c->cmd_size, c->data, c->data_size); st = sanei_scsi_cmd (s->file, s->buffer, c->cmd_size + c->data_size, NULL, NULL); } else if (c->dir == CMD_IN) { c->data = s->buffer; st = sanei_scsi_cmd (s->file, c->cmd, c->cmd_size, c->data, (size_t *) & c->data_size); } else { st = sanei_scsi_cmd (s->file, c->cmd, c->cmd_size, NULL, NULL); } } return st; } SANE_Status kvs40xx_test_unit_ready (struct scanner * s) { struct cmd c = { {0}, 6, NULL, 0, CMD_NONE }; c.cmd[0] = TEST_UNIT_READY; if (send_command (s, &c)) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_GOOD; } SANE_Status kvs40xx_set_timeout (struct scanner * s, int timeout) { u16 t = cpu2be16 ((u16) timeout); struct cmd c = { {0}, 10, NULL, 0, CMD_OUT }; c.data = &t; c.data_size = sizeof (t); c.cmd[0] = SET_TIMEOUT; c.cmd[2] = 0x8d; copy16 (c.cmd + 7, cpu2be16 (sizeof (t))); if (s->bus == USB) sanei_usb_set_timeout (timeout * 1000); return send_command (s, &c); } SANE_Status kvs40xx_set_window (struct scanner * s, int wnd_id) { struct window wnd; struct cmd c = { {0}, 10, NULL, 0, CMD_OUT }; c.data = &wnd; c.data_size = sizeof (wnd); c.cmd[0] = SET_WINDOW; copy16 (c.cmd + 7, cpu2be16 (sizeof (wnd))); kvs40xx_init_window (s, &wnd, wnd_id); return send_command (s, &c); } SANE_Status kvs40xx_reset_window (struct scanner * s) { struct cmd c = { {0}, 10, NULL, 0, CMD_NONE }; c.cmd[0] = SET_WINDOW; return send_command (s, &c); } SANE_Status kvs40xx_scan (struct scanner * s) { struct cmd c = { {0}, 6, NULL, 0, CMD_NONE }; c.cmd[0] = SCAN; return send_command (s, &c); } SANE_Status hopper_down (struct scanner * s) { struct cmd c = { {0}, 10, NULL, 0, CMD_NONE }; c.cmd[0] = HOPPER_DOWN; c.cmd[2] = 5; if (s->id == KV_S7075C) return SANE_STATUS_GOOD; return send_command (s, &c); } SANE_Status stop_adf (struct scanner * s) { struct cmd c = { {0}, 10, NULL, 0, CMD_NONE }; c.cmd[0] = STOP_ADF; c.cmd[2] = 0x8b; return send_command (s, &c); } SANE_Status kvs40xx_document_exist (struct scanner * s) { SANE_Status status; struct cmd c = { {0}, 10, NULL, 6, CMD_IN }; u8 *d; c.cmd[0] = READ_10; c.cmd[2] = 0x81; set24 (c.cmd + 6, c.data_size); status = send_command (s, &c); if (status) return status; d = c.data; if (d[0] & 0x20) return SANE_STATUS_GOOD; return SANE_STATUS_NO_DOCS; } SANE_Status kvs40xx_read_picture_element (struct scanner * s, unsigned side, SANE_Parameters * p) { SANE_Status status; struct cmd c = { {0}, 10, NULL, 16, CMD_IN }; u32 *data; c.cmd[0] = READ_10; c.cmd[2] = 0x80; c.cmd[5] = side; set24 (c.cmd + 6, c.data_size); status = send_command (s, &c); if (status) return status; data = (u32 *) c.data; p->pixels_per_line = be2cpu32 (data[0]); p->lines = be2cpu32 (data[1]); return SANE_STATUS_GOOD; } SANE_Status get_buffer_status (struct scanner * s, unsigned *data_avalible) { SANE_Status status; struct cmd c = { {0}, 10, NULL, 12, CMD_IN }; c.cmd[0] = GET_BUFFER_STATUS; c.cmd[7] = 12; status = send_command (s, &c); if (status) return status; *data_avalible = get24 ((unsigned char *)c.data + 9); return SANE_STATUS_GOOD; } SANE_Status kvs40xx_read_image_data (struct scanner * s, unsigned page, unsigned side, void *buf, unsigned max_size, unsigned *size) { SANE_Status status; struct cmd c = { {0}, 10, NULL, 0, CMD_IN }; c.data_size = max_size < MAX_READ_DATA_SIZE ? max_size : MAX_READ_DATA_SIZE; c.cmd[0] = READ_10; c.cmd[4] = page; c.cmd[5] = side; set24 (c.cmd + 6, c.data_size); *size = 0; status = send_command (s, &c); if (status && status != SANE_STATUS_EOF && status != INCORRECT_LENGTH) return status; *size = c.data_size; memcpy (buf, c.data, *size); return status; } SANE_Status read_support_info (struct scanner * s, struct support_info * inf) { SANE_Status st; struct cmd c = { {0}, 10, NULL, sizeof (*inf), CMD_IN }; c.cmd[0] = READ_10; c.cmd[2] = SUPPORT_INFO; set24 (c.cmd + 6, c.data_size); st = send_command (s, &c); if (st) return st; memcpy (inf, c.data, sizeof (*inf)); return SANE_STATUS_GOOD; } SANE_Status inquiry (struct scanner * s, char *id) { int i; SANE_Status st; struct cmd c = { {0}, 5, NULL, 0x60, CMD_IN }; c.cmd[0] = INQUIRY; c.cmd[4] = c.data_size; st = send_command (s, &c); if (st) return st; memcpy (id, (unsigned char *)c.data + 16, 16); for (i = 0; i < 15 && id[i] != ' '; i++); id[i] = 0; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/canon_dr.c0000664000175000017500000066047713063340146014564 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package, and implements a SANE backend for various Canon DR-series scanners. Copyright (C) 2008-2016 m. allan noah Yabarana Corp. www.yabarana.com provided significant funding EvriChart, Inc. www.evrichart.com provided funding and loaned equipment Canon, USA. www.usa.canon.com loaned equipment HPrint hprint.com.br provided funding and testing for DR-2510 support Stone-IT www.stone-it.com provided funding for DR-2010 and DR-2050 support -------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. -------------------------------------------------------------------------- The source code is divided in sections which you can easily find by searching for the tag "@@". Section 1 - Init & static stuff Section 2 - sane_init, _get_devices, _open & friends Section 3 - sane_*_option functions Section 4 - sane_start, _get_param, _read & friends Section 5 - calibration functions Section 6 - sane_close functions Section 7 - misc functions Section 8 - image processing functions Changes: v1 2008-10-29, MAN - initial version v2 2008-11-04, MAN - round scanlines to even bytes - spin RS and usb_clear_halt code into new function - update various scsi payloads - calloc out block so it gets set to 0 initially v3 2008-11-07, MAN - back window uses id 1 - add option and functions to read/send page counter - add rif option v4 2008-11-11, MAN - eject document when sane_read() returns EOF v5 2008-11-25, MAN - remove EOF ejection code - add SSM and GSM commands - add dropout, doublefeed, and jpeg compression options - disable adf backside - fix adf duplex - read two extra lines (ignore errors) at end of image - only send scan command at beginning of batch - fix bug in hexdump with 0 length string - DR-7580 support v6 2008-11-29, MAN - fix adf simplex - rename ssm_duplex to ssm_buffer - add --buffer option - reduce inter-page commands when buffering is enabled - improve sense_handler output - enable counter option - drop unused code v7 2008-11-29, MAN - jpeg support (size rounding and header overwrite) - call object_position(load) between pages even if buffering is on - use request sense info bytes on short scsi reads - byte swap color BGR to RGB - round image width down, not up - round image height down to even # of lines - always transfer even # of lines per block - scsi and jpeg don't require reading extra lines to reach EOF - rename buffer option to buffermode to avoid conflict with scanimage - send ssm_do and ssm_df during sane_start - improve sense_handler output v8 2008-12-07, MAN - rename read/send_counter to read/send_panel - enable control panel during init - add options for all buttons - call TUR twice in wait_scanner(), even if first succeeds - disable rif - enable brightness/contrast/threshold options v9 2008-12-07, MAN - add rollerdeskew and stapledetect options - add rollerdeskew and stapledetect bits to ssm_df() v10 2008-12-10, MAN - add all documented request sense codes to sense_handler() - fix color jpeg (remove unneeded BGR to RGB swapping code) - add macros for LUT data v11 2009-01-10, MAN - send_panel() can disable too - add cancel() to send d8 command - call cancel() only after final read from scanner - stop button reqests cancel v12 2009-01-21, MAN - dont export private symbols v13 2009-03-06, MAN - new vendor ID for recent machines - add usb ids for several new machines v14 2009-03-07, MAN - remove HARD_SELECT from counter (Legitimate, but API violation) - attach to CR-series scanners as well v15 2009-03-15, MAN - add byte-oriented duplex interlace code - add RRGGBB color interlace code - add basic support for DR-2580C v16 2009-03-20, MAN - add more unknown setwindow bits - add support for 16 byte status packets - clean do_usb_cmd error handling (call reset more often) - add basic support for DR-2050C, DR-2080C, DR-2510C v17 2009-03-20, MAN - set status packet size from config file v18 2009-03-21, MAN - rewrite config file parsing to reset options after each scanner - add config options for vendor, model, version - dont call inquiry if those 3 options are set - remove default config file from code - add initial gray deinterlacing code for DR-2510C - rename do_usb_reset to do_usb_clear v19 2009-03-22, MAN - pad gray deinterlacing area for DR-2510C - override tl_x and br_x for fixed width scanners v20 2009-03-23, MAN - improved macros for inquiry and set window - shorten inquiry vpd length to match windows driver - remove status-length config option - add padded-read config option - rewrite do_usb_cmd to pad reads and calloc/copy buffers v21 2009-03-24, MAN - correct rgb padding macro - skip send_panel and ssm_df commands for DR-20xx scanners v22 2009-03-25, MAN - add deinterlacing code for DR-2510C in duplex and color v23 2009-03-27, MAN - rewrite all image data processing code - handle more image interlacing formats - re-enable binary mode on some scanners - limit some machines to full-width scanning v24 2009-04-02, MAN - fix DR-2510C duplex deinterlacing code - rewrite sane_read helpers to read until EOF - update sane_start for scanners that dont use object_position - dont call sanei_usb_clear_halt() if device is not open - increase default buffer size to 4 megs - set buffermode on by default - hide modes and resolutions that DR-2510C lies about - read_panel() logs front-end access to sensors instead of timing - rewrite do_usb_cmd() to use remainder from RS info v25 2009-04-12, MAN - disable SANE_FRAME_JPEG v26 2009-04-14, MAN (SANE 1.0.20) - return cmd status for reads on sensors - allow rs to adjust read length for all bad status responses v27 2009-05-08, MAN - bug fix in read_panel() - initialize vars in do_usb_cmd() - set buffermode off by default - clear page counter during init and sane_start() - eject previous page during init and sane_start() - improved SSM_BUFF macros - moved set_window() to after ssm-*() - add coarse calibration (AFE offset/gain & per-channel exposure) - add fine calibration (per-cell offset/gain) - free image and fine cal buffers in sane_close() - compare page counter of small scanners only in non-buffered mode - add back-side gray mirroring code for DR-2580C v28 2009-05-20, MAN - use average instead of min/max for fine offset and gain - rewrite supported resolution list as x and y arrays - merge x and y resolution options into single option - move scan params into two new structs, s->u and s->s - sane_get_parameters() just returns values from s->u - dont call wait_scanner() in object_position() - dont call ssm_*() from option handler - refactor sane_start() - read_from_buffer() can workaround missing res, modes and cropping - set most DR-2xxx machines to use the read_from_buffer workarounds - set default threshold to 90 - add option for button #3 of some machines - don't eject paper during init - add DR-2010 quirks - switch counter to HARD_SELECT, not SOFT v29 2009-06-01, MAN - split coarse and fine cal to run independently - add side option - reset scan params to user request if calibration fails - better handling of sane_cancel - better handling of errors during sane_start and sane_read v30 2009-06-17, MAN - add fine cal support for machines with internal buffer (2050/2080) - support fixed-width machines that require even bytes per scanline - pad end of scan with gray if scanner stops prematurely - better handling of errors during calibration - cleanup canceling debug messages - remove old cancel() prototype - small sleep before clearing usb halt condition v31 2009-06-29, MAN - reduce default buffer size to 2 megs v32 2009-07-21, MAN - crop/resample image data before buffering, not after - shink image buffers to size of output image, not input - correct some debug message - better handling of EOF - add intermediate param struct to existing user and scan versions v33 2009-07-23, MAN - add software brightness/contrast for dumb scanners - add blocking mode to allow full-page manipulation options to run - add swdespeck option and support code - add swdeskew and swcrop options (disabled) v34 2009-07-28, MAN - add simplified Hough transform based deskewing code - add extremity detecting cropping code - use per-model background color to fill corners after deskew - request and chop extra scanlines instead of rounding down - remove padding dumb scanners add to top of front side - sane_get_params uses intermediate struct instead of user struct - if scanner stops, clone the last line until the end of buffer - reset some intermediate params between duplex sides v35 2010-02-09, MAN (SANE 1.0.21) - cleanup #includes and copyright - add SANE_I18N to static strings - don't fail if scsi buffer is too small v36 2011-01-03, MAN - initial support for DR-3080 and DR-5060 - add code to clamp scan width to an arbitrary byte width boundary - add code to prevent setting of brightness/threshold/contrast - don't send dropout color command on non-color scanners - initial support for DR-7090C - update credits v37 2011-01-26, MAN (SANE 1.0.22) - don't center window when using flatbed - improve request sense error messages - enable flatbed for all known models v38 2011-07-06, MAN - initial support for DR-5020 - use ppl_mod instead of Bpl_mod, apply to all modes - invert logic of read_panel tracking - add ability to disable read_panel() - automatically disable read/send_panel if unsupported v39 2011-11-01, MAN - DR-2580C pads the backside of duplex scans v40 2012-11-01, MAN - initial DR-9050C, DR-7550C, DR-6050C and DR-3010C support v41 2013-07-31, MAN (SANE 1.0.24) - initial P-208 and P-215 support - bug fix for calibration of scanners with duplex_offset - allow duplex_offset to be controlled from config file v42 2013-12-09, MAN - initial DR-G1100 support - add support for paper sensors (P-215 & P-208) - add initial support for card reader (P-215) - removed unused var from do_scsi_cmd() v43 2014-03-13, MAN - initial DR-M140 support - add extra_status config and code - split status code into do_usb_status - fix copy_line margin offset - add new color interlacing modes and code - comment out ssm2 - add timestamp to do_usb_cmd v44 2014-03-26, MAN - buffermode support for machines with ssm2 command - DR-M140 needs always_op=0 v45 2014-03-29, MAN - dropout support for machines with ssm2 command - doublefeed support for machines with ssm2 command v46 2014-04-09, MAN - split debug level 30 into two levels - simplify jpeg ifdefs - add support for DR-M160 v47 2014-07-07, MAN - initial DR-G1130 support v48 2014-08-06, MAN - set another unknown byte in buffermode for ssm2 - add another gettimeofday call at end of do_usb_cmd - don't print 0 length line in hexdump v49 2015-03-18, MAN - initial support for DR-C125 v50 2015-08-23, MAN - DR-C125 adds duplex padding on back side - initial support for DR-C225 v51 2015-08-25, MAN (SANE 1.0.25) - DR-C125 does not invert_tly, does need sw_lut v52 2015-11-03, MAN - set can_color=1 by default (recent models dont have 'C' in name) - enable jpeg for DR-6080 - add must_downsample and must_fully_buffer - improve dropout option handling - add software dropout implementation for downsampled modes v53 2015-11-06, MAN - replace image processing methods with sanei_magic - add swskip option - reorder geometry group options - use bg_color to fill missing image data v54 2015-11-21, MAN - br_x and br_y locked to page_width/height until changed v55 2016-03-19, MAN - fixed-width scanners were calculating left-side offset incorrectly in color - initial support for DR-F120 - rename all DUPLEX_INTERLACE_* to indicate start and end of line v56 2016-08-23, MAN - initial support for P-150 SANE FLOW DIAGRAM - sane_init() : initialize backend . - sane_get_devices() : query list of scanner devices . - sane_open() : open a particular scanner device . . - sane_set_io_mode : set blocking mode . . - sane_get_select_fd : get scanner fd . . . . - sane_get_option_descriptor() : get option information . . - sane_control_option() : change option values . . - sane_get_parameters() : returns estimated scan parameters . . - (repeat previous 3 functions) . . . . - sane_start() : start image acquisition . . - sane_get_parameters() : returns actual scan parameters . . - sane_read() : read image data (from pipe) . . (sane_read called multiple times; after sane_read returns EOF, . . loop may continue with sane_start which may return a 2nd page . . when doing duplex scans, or load the next page from the ADF) . . . . - sane_cancel() : cancel operation . - sane_close() : close opened scanner device - sane_exit() : terminate use of backend */ /* * @@ Section 1 - Init */ #include "../include/sane/config.h" #include /*memcpy...*/ #include /*isspace*/ #include /*tan*/ #include /*usleep*/ #include /*gettimeofday*/ #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_magic.h" #include "canon_dr-cmd.h" #include "canon_dr.h" #define DEBUG 1 #define BUILD 56 /* values for SANE_DEBUG_CANON_DR env var: - errors 5 - function trace 10 - function detail 15 - get/setopt cmds 20 - scsi/usb trace 25 - scsi/usb writes 30 - scsi/usb reads 31 - useless noise 35 */ /* ------------------------------------------------------------------------- */ /* if JPEG support is not enabled in sane.h, we setup our own defines */ #ifndef SANE_FRAME_JPEG #define SANE_FRAME_JPEG 0x0B #define SANE_JPEG_DISABLED 1 #endif /* ------------------------------------------------------------------------- */ #define STRING_FLATBED SANE_I18N("Flatbed") #define STRING_ADFFRONT SANE_I18N("ADF Front") #define STRING_ADFBACK SANE_I18N("ADF Back") #define STRING_ADFDUPLEX SANE_I18N("ADF Duplex") #define STRING_CARDFRONT SANE_I18N("Card Front") #define STRING_CARDBACK SANE_I18N("Card Back") #define STRING_CARDDUPLEX SANE_I18N("Card Duplex") #define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART #define STRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE #define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY #define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR #define STRING_RED SANE_I18N("Red") #define STRING_GREEN SANE_I18N("Green") #define STRING_BLUE SANE_I18N("Blue") #define STRING_EN_RED SANE_I18N("Enhance Red") #define STRING_EN_GREEN SANE_I18N("Enhance Green") #define STRING_EN_BLUE SANE_I18N("Enhance Blue") #define STRING_NONE SANE_I18N("None") #define STRING_JPEG SANE_I18N("JPEG") /* Also set via config file. */ static int global_buffer_size; static int global_buffer_size_default = 2 * 1024 * 1024; static int global_padded_read; static int global_padded_read_default = 0; static int global_extra_status; static int global_extra_status_default = 0; static int global_duplex_offset; static int global_duplex_offset_default = 0; static char global_vendor_name[9]; static char global_model_name[17]; static char global_version_name[5]; /* * used by attach* and sane_get_devices * a ptr to a null term array of ptrs to SANE_Device structs * a ptr to a single-linked list of scanner structs */ static const SANE_Device **sane_devArray = NULL; static struct scanner *scanner_devList = NULL; /* * @@ Section 2 - SANE & scanner init code */ /* * Called by SANE initially. * * From the SANE spec: * This function must be called before any other SANE function can be * called. The behavior of a SANE backend is undefined if this * function is not called first. The version code of the backend is * returned in the value pointed to by version_code. If that pointer * is NULL, no version code is returned. Argument authorize is either * a pointer to a function that is invoked when the backend requires * authentication for a specific resource or NULL if the frontend does * not support authentication. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { authorize = authorize; /* get rid of compiler warning */ DBG_INIT (); DBG (10, "sane_init: start\n"); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (5, "sane_init: canon_dr backend %d.%d.%d, from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); DBG (10, "sane_init: finish\n"); return SANE_STATUS_GOOD; } /* * Called by SANE to find out about supported devices. * * From the SANE spec: * This function can be used to query the list of devices that are * available. If the function executes successfully, it stores a * pointer to a NULL terminated array of pointers to SANE_Device * structures in *device_list. The returned list is guaranteed to * remain unchanged and valid until (a) another call to this function * is performed or (b) a call to sane_exit() is performed. This * function can be called repeatedly to detect when new devices become * available. If argument local_only is true, only local devices are * returned (devices directly attached to the machine that SANE is * running on). If it is false, the device list includes all remote * devices that are accessible to the SANE library. * * SANE does not require that this function is called before a * sane_open() call is performed. A device name may be specified * explicitly by a user which would make it unnecessary and * undesirable to call this function first. */ /* * Read the config file, find scanners with help from sanei_* * and store in global device structs */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { SANE_Status ret = SANE_STATUS_GOOD; struct scanner * s; struct scanner * prev = NULL; char line[PATH_MAX]; const char *lp; FILE *fp; int num_devices=0; int i=0; local_only = local_only; /* get rid of compiler warning */ DBG (10, "sane_get_devices: start\n"); /* mark all existing scanners as missing, attach_one will remove mark */ for (s = scanner_devList; s; s = s->next) { s->missing = 1; } sanei_usb_init(); /* reset globals before reading the file */ default_globals(); fp = sanei_config_open (CANON_DR_CONFIG_FILE); if (fp) { DBG (15, "sane_get_devices: reading config file %s\n", CANON_DR_CONFIG_FILE); while (sanei_config_read (line, PATH_MAX, fp)) { lp = line; /* ignore comments */ if (*lp == '#') continue; /* skip empty lines */ if (*lp == 0) continue; if (!strncmp ("option", lp, 6) && isspace (lp[6])) { lp += 6; lp = sanei_config_skip_whitespace (lp); /* BUFFERSIZE: > 4K */ if (!strncmp (lp, "buffer-size", 11) && isspace (lp[11])) { int buf; lp += 11; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); if (buf < 4096) { DBG (5, "sane_get_devices: config option \"buffer-size\" " "(%d) is < 4096, ignoring!\n", buf); continue; } if (buf > global_buffer_size_default) { DBG (5, "sane_get_devices: config option \"buffer-size\" " "(%d) is > %d, scanning problems may result\n", buf, global_buffer_size_default); } DBG (15, "sane_get_devices: setting \"buffer-size\" to %d\n", buf); global_buffer_size = buf; } /* PADDED READ: we clamp to 0 or 1 */ else if (!strncmp (lp, "padded-read", 11) && isspace (lp[11])) { int buf; lp += 11; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); if (buf < 0) { DBG (5, "sane_get_devices: config option \"padded-read\" " "(%d) is < 0, ignoring!\n", buf); continue; } if (buf > 1) { DBG (5, "sane_get_devices: config option \"padded-read\" " "(%d) is > 1, ignoring!\n", buf); continue; } DBG (15, "sane_get_devices: setting \"padded-read\" to %d\n", buf); global_padded_read = buf; } /* EXTRA STATUS: we clamp to 0 or 1 */ else if (!strncmp (lp, "extra-status", 12) && isspace (lp[12])) { int buf; lp += 12; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); if (buf < 0) { DBG (5, "sane_get_devices: config option \"extra-status\" " "(%d) is < 0, ignoring!\n", buf); continue; } if (buf > 1) { DBG (5, "sane_get_devices: config option \"extra-status\" " "(%d) is > 1, ignoring!\n", buf); continue; } DBG (15, "sane_get_devices: setting \"extra-status\" to %d\n", buf); global_extra_status = buf; } /* DUPLEXOFFSET: < 2400 */ else if (!strncmp (lp, "duplex-offset", 13) && isspace (lp[13])) { int buf; lp += 13; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); if (buf > 2400) { DBG (5, "sane_get_devices: config option \"duplex-offset\" " "(%d) is > 2400, ignoring!\n", buf); continue; } if (buf < 0) { DBG (5, "sane_get_devices: config option \"duplex-offset\" " "(%d) is < 0, ignoring!\n", buf); continue; } DBG (15, "sane_get_devices: setting \"duplex-offset\" to %d\n", buf); global_duplex_offset = buf; } /* VENDOR: we ingest up to 8 bytes */ else if (!strncmp (lp, "vendor-name", 11) && isspace (lp[11])) { lp += 11; lp = sanei_config_skip_whitespace (lp); strncpy(global_vendor_name, lp, 8); global_vendor_name[8] = 0; DBG (15, "sane_get_devices: setting \"vendor-name\" to %s\n", global_vendor_name); } /* MODEL: we ingest up to 16 bytes */ else if (!strncmp (lp, "model-name", 10) && isspace (lp[10])) { lp += 10; lp = sanei_config_skip_whitespace (lp); strncpy(global_model_name, lp, 16); global_model_name[16] = 0; DBG (15, "sane_get_devices: setting \"model-name\" to %s\n", global_model_name); } /* VERSION: we ingest up to 4 bytes */ else if (!strncmp (lp, "version-name", 12) && isspace (lp[12])) { lp += 12; lp = sanei_config_skip_whitespace (lp); strncpy(global_version_name, lp, 4); global_version_name[4] = 0; DBG (15, "sane_get_devices: setting \"version-name\" to %s\n", global_version_name); } else { DBG (5, "sane_get_devices: config option \"%s\" unrecognized " "- ignored.\n", lp); } } else if ((strncmp ("usb", lp, 3) == 0) && isspace (lp[3])) { DBG (15, "sane_get_devices: looking for '%s'\n", lp); sanei_usb_attach_matching_devices(lp, attach_one_usb); /* re-default these after reading the usb line */ default_globals(); } else if ((strncmp ("scsi", lp, 4) == 0) && isspace (lp[4])) { DBG (15, "sane_get_devices: looking for '%s'\n", lp); sanei_config_attach_matching_devices (lp, attach_one_scsi); /* re-default these after reading the scsi line */ default_globals(); } else{ DBG (5, "sane_get_devices: config line \"%s\" unrecognized - " "ignored.\n", lp); } } fclose (fp); } else { DBG (5, "sane_get_devices: missing required config file '%s'!\n", CANON_DR_CONFIG_FILE); } /*delete missing scanners from list*/ for (s = scanner_devList; s;) { if(s->missing){ DBG (5, "sane_get_devices: missing scanner %s\n",s->device_name); /*splice s out of list by changing pointer in prev to next*/ if(prev){ prev->next = s->next; free(s); s=prev->next; } /*remove s from head of list, using prev to cache it*/ else{ prev = s; s = s->next; free(prev); prev=NULL; /*reset head to next s*/ scanner_devList = s; } } else{ prev = s; s=prev->next; } } for (s = scanner_devList; s; s=s->next) { DBG (15, "sane_get_devices: found scanner %s\n",s->device_name); num_devices++; } DBG (15, "sane_get_devices: found %d scanner(s)\n",num_devices); if (sane_devArray) free (sane_devArray); sane_devArray = calloc (num_devices + 1, sizeof (SANE_Device*)); if (!sane_devArray) return SANE_STATUS_NO_MEM; for (s = scanner_devList; s; s=s->next) { sane_devArray[i++] = (SANE_Device *)&s->sane; } sane_devArray[i] = 0; if(device_list){ *device_list = sane_devArray; } DBG (10, "sane_get_devices: finish\n"); return ret; } /* callbacks used by sane_get_devices */ static SANE_Status attach_one_scsi (const char *device_name) { return attach_one(device_name,CONNECTION_SCSI); } static SANE_Status attach_one_usb (const char *device_name) { return attach_one(device_name,CONNECTION_USB); } /* build the scanner struct and link to global list * unless struct is already loaded, then pretend */ static SANE_Status attach_one (const char *device_name, int connType) { struct scanner *s; int ret; DBG (10, "attach_one: start\n"); DBG (15, "attach_one: looking for '%s'\n", device_name); for (s = scanner_devList; s; s = s->next) { if (strcmp (s->device_name, device_name) == 0){ DBG (10, "attach_one: already attached!\n"); s->missing = 0; return SANE_STATUS_GOOD; } } /* build a scanner struct to hold it */ if ((s = calloc (sizeof (*s), 1)) == NULL) return SANE_STATUS_NO_MEM; /* config file settings */ s->buffer_size = global_buffer_size; s->padded_read = global_padded_read; s->extra_status = global_extra_status; s->duplex_offset = global_duplex_offset; /* copy the device name */ strcpy (s->device_name, device_name); /* connect the fd */ s->connection = connType; s->fd = -1; ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ free (s); return ret; } /* query the device to load its vendor/model/version, */ /* if config file doesn't give all three */ if ( !strlen(global_vendor_name) || !strlen(global_model_name) || !strlen(global_version_name) ){ ret = init_inquire (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: inquiry failed\n"); return ret; } } /* override any inquiry settings with those from config file */ if(strlen(global_vendor_name)) strcpy(s->vendor_name, global_vendor_name); if(strlen(global_model_name)) strcpy(s->model_name, global_model_name); if(strlen(global_version_name)) strcpy(s->version_name, global_version_name); /* load detailed specs/capabilities from the device */ /* if a model cannot support inquiry vpd, this function will die */ ret = init_vpd (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: vpd failed\n"); return ret; } /* clean up the scanner struct based on model */ /* this is the big piece of model specific code */ ret = init_model (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: model failed\n"); return ret; } /* enable/read the buttons */ ret = init_panel (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: model failed\n"); return ret; } /* sets SANE option 'values' to good defaults */ ret = init_user (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: user failed\n"); return ret; } ret = init_options (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: options failed\n"); return ret; } /* load strings into sane_device struct */ s->sane.name = s->device_name; s->sane.vendor = s->vendor_name; s->sane.model = s->model_name; s->sane.type = "scanner"; /* change name in sane_device struct if scanner has serial number ret = init_serial (s); if (ret == SANE_STATUS_GOOD) { s->sane.name = s->serial_name; } else{ DBG (5, "attach_one: serial number unsupported?\n"); } */ /* we close the connection, so that another backend can talk to scanner */ disconnect_fd(s); /* store this scanner in global vars */ s->next = scanner_devList; scanner_devList = s; DBG (10, "attach_one: finish\n"); return SANE_STATUS_GOOD; } /* * connect the fd in the scanner struct */ static SANE_Status connect_fd (struct scanner *s) { SANE_Status ret; int buffer_size = s->buffer_size; DBG (10, "connect_fd: start\n"); if(s->fd > -1){ DBG (5, "connect_fd: already open\n"); ret = SANE_STATUS_GOOD; } else if (s->connection == CONNECTION_USB) { DBG (15, "connect_fd: opening USB device (%s)\n", s->device_name); ret = sanei_usb_open (s->device_name, &(s->fd)); if(!ret){ ret = sanei_usb_clear_halt(s->fd); } } else { DBG (15, "connect_fd: opening SCSI device (%s)\n", s->device_name); ret = sanei_scsi_open_extended (s->device_name, &(s->fd), sense_handler, s, &s->buffer_size); if(!ret && buffer_size != s->buffer_size){ DBG (5, "connect_fd: cannot get requested buffer size (%d/%d)\n", buffer_size, s->buffer_size); } } if(ret == SANE_STATUS_GOOD){ /* first generation usb scanners can get flaky if not closed * properly after last use. very first commands sent to device * must be prepared to correct this- see wait_scanner() */ ret = wait_scanner(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "connect_fd: could not wait_scanner\n"); disconnect_fd(s); } } else{ DBG (5, "connect_fd: could not open device: %d\n", ret); } DBG (10, "connect_fd: finish\n"); return ret; } /* * This routine will check if a certain device is a Canon scanner * It also copies interesting data from INQUIRY into the handle structure */ static SANE_Status init_inquire (struct scanner *s) { int i; SANE_Status ret; unsigned char cmd[INQUIRY_len]; size_t cmdLen = INQUIRY_len; unsigned char in[INQUIRY_std_len]; size_t inLen = INQUIRY_std_len; DBG (10, "init_inquire: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, INQUIRY_code); set_IN_return_size (cmd, inLen); set_IN_evpd (cmd, 0); set_IN_page_code (cmd, 0); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret != SANE_STATUS_GOOD){ DBG (10, "init_inquire: failed: %d\n", ret); return ret; } if (get_IN_periph_devtype (in) != IN_periph_devtype_scanner){ DBG (5, "The device at '%s' is not a scanner.\n", s->device_name); return SANE_STATUS_INVAL; } get_IN_vendor (in, s->vendor_name); get_IN_product (in, s->model_name); get_IN_version (in, s->version_name); s->vendor_name[8] = 0; s->model_name[16] = 0; s->version_name[4] = 0; /* gobble trailing spaces */ for (i = 7; s->vendor_name[i] == ' ' && i >= 0; i--) s->vendor_name[i] = 0; for (i = 15; s->model_name[i] == ' ' && i >= 0; i--) s->model_name[i] = 0; for (i = 3; s->version_name[i] == ' ' && i >= 0; i--) s->version_name[i] = 0; /*check for vendor name*/ if (strcmp ("CANON", s->vendor_name)) { DBG (5, "The device at '%s' is reported to be made by '%s'\n", s->device_name, s->vendor_name); DBG (5, "This backend only supports Canon products.\n"); return SANE_STATUS_INVAL; } /*check for model name*/ if (strncmp ("DR", s->model_name, 2) && strncmp ("CR", s->model_name, 2) && strncmp ("P-", s->model_name, 2) ) { DBG (5, "The device at '%s' is reported to be a '%s'\n", s->device_name, s->model_name); DBG (5, "This backend only supports Canon P-, CR & DR-series products.\n"); return SANE_STATUS_INVAL; } DBG (15, "init_inquire: Found %s scanner %s version %s at %s\n", s->vendor_name, s->model_name, s->version_name, s->device_name); DBG (10, "init_inquire: finish\n"); return SANE_STATUS_GOOD; } /* * Use INQUIRY VPD to setup more detail about the scanner */ static SANE_Status init_vpd (struct scanner *s) { SANE_Status ret; unsigned char cmd[INQUIRY_len]; size_t cmdLen = INQUIRY_len; unsigned char in[INQUIRY_vpd_len]; size_t inLen = INQUIRY_vpd_len; DBG (10, "init_vpd: start\n"); /* get EVPD */ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, INQUIRY_code); set_IN_return_size (cmd, inLen); set_IN_evpd (cmd, 1); set_IN_page_code (cmd, 0xf0); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); DBG (15, "init_vpd: length=%0x\n",get_IN_page_length (in)); /* This scanner supports vital product data. * Use this data to set dpi-lists etc. */ if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { DBG (15, "standard options\n"); s->basic_x_res = get_IN_basic_x_res (in); DBG (15, " basic x res: %d dpi\n",s->basic_x_res); s->basic_y_res = get_IN_basic_y_res (in); DBG (15, " basic y res: %d dpi\n",s->basic_y_res); s->step_x_res = get_IN_step_x_res (in); DBG (15, " step x res: %d dpi\n", s->step_x_res); s->step_y_res = get_IN_step_y_res (in); DBG (15, " step y res: %d dpi\n", s->step_y_res); s->max_x_res = get_IN_max_x_res (in); DBG (15, " max x res: %d dpi\n", s->max_x_res); s->max_y_res = get_IN_max_y_res (in); DBG (15, " max y res: %d dpi\n", s->max_y_res); s->min_x_res = get_IN_min_x_res (in); DBG (15, " min x res: %d dpi\n", s->min_x_res); s->min_y_res = get_IN_min_y_res (in); DBG (15, " min y res: %d dpi\n", s->min_y_res); /* some scanners list B&W resolutions. */ s->std_res_x[DPI_60] = get_IN_std_res_60 (in); s->std_res_y[DPI_60] = s->std_res_x[DPI_60]; DBG (15, " 60 dpi: %d\n", s->std_res_x[DPI_60]); s->std_res_x[DPI_75] = get_IN_std_res_75 (in); s->std_res_y[DPI_75] = s->std_res_x[DPI_75]; DBG (15, " 75 dpi: %d\n", s->std_res_x[DPI_75]); s->std_res_x[DPI_100] = get_IN_std_res_100 (in); s->std_res_y[DPI_100] = s->std_res_x[DPI_100]; DBG (15, " 100 dpi: %d\n", s->std_res_x[DPI_100]); s->std_res_x[DPI_120] = get_IN_std_res_120 (in); s->std_res_y[DPI_120] = s->std_res_x[DPI_120]; DBG (15, " 120 dpi: %d\n", s->std_res_x[DPI_120]); s->std_res_x[DPI_150] = get_IN_std_res_150 (in); s->std_res_y[DPI_150] = s->std_res_x[DPI_150]; DBG (15, " 150 dpi: %d\n", s->std_res_x[DPI_150]); s->std_res_x[DPI_160] = get_IN_std_res_160 (in); s->std_res_y[DPI_160] = s->std_res_x[DPI_160]; DBG (15, " 160 dpi: %d\n", s->std_res_x[DPI_160]); s->std_res_x[DPI_180] = get_IN_std_res_180 (in); s->std_res_y[DPI_180] = s->std_res_x[DPI_180]; DBG (15, " 180 dpi: %d\n", s->std_res_x[DPI_180]); s->std_res_x[DPI_200] = get_IN_std_res_200 (in); s->std_res_y[DPI_200] = s->std_res_x[DPI_200]; DBG (15, " 200 dpi: %d\n", s->std_res_x[DPI_200]); s->std_res_x[DPI_240] = get_IN_std_res_240 (in); s->std_res_y[DPI_240] = s->std_res_x[DPI_240]; DBG (15, " 240 dpi: %d\n", s->std_res_x[DPI_240]); s->std_res_x[DPI_300] = get_IN_std_res_300 (in); s->std_res_y[DPI_300] = s->std_res_x[DPI_300]; DBG (15, " 300 dpi: %d\n", s->std_res_x[DPI_300]); s->std_res_x[DPI_320] = get_IN_std_res_320 (in); s->std_res_y[DPI_320] = s->std_res_x[DPI_320]; DBG (15, " 320 dpi: %d\n", s->std_res_x[DPI_320]); s->std_res_x[DPI_400] = get_IN_std_res_400 (in); s->std_res_y[DPI_400] = s->std_res_x[DPI_400]; DBG (15, " 400 dpi: %d\n", s->std_res_x[DPI_400]); s->std_res_x[DPI_480] = get_IN_std_res_480 (in); s->std_res_y[DPI_480] = s->std_res_x[DPI_480]; DBG (15, " 480 dpi: %d\n", s->std_res_x[DPI_480]); s->std_res_x[DPI_600] = get_IN_std_res_600 (in); s->std_res_y[DPI_600] = s->std_res_x[DPI_600]; DBG (15, " 600 dpi: %d\n", s->std_res_x[DPI_600]); s->std_res_x[DPI_800] = get_IN_std_res_800 (in); s->std_res_y[DPI_800] = s->std_res_x[DPI_800]; DBG (15, " 800 dpi: %d\n", s->std_res_x[DPI_800]); s->std_res_x[DPI_1200] = get_IN_std_res_1200 (in); s->std_res_y[DPI_1200] = s->std_res_x[DPI_1200]; DBG (15, " 1200 dpi: %d\n", s->std_res_x[DPI_1200]); /* maximum window width and length are reported in basic units.*/ s->max_x = get_IN_window_width(in) * 1200 / s->basic_x_res; DBG(15, " max width: %d (%2.2f in)\n",s->max_x,(float)s->max_x/1200); s->max_y = get_IN_window_length(in) * 1200 / s->basic_y_res; DBG(15, " max length: %d (%2.2f in)\n",s->max_y,(float)s->max_y/1200); DBG (15, " AWD: %d\n", get_IN_awd(in)); DBG (15, " CE Emphasis: %d\n", get_IN_ce_emphasis(in)); DBG (15, " C Emphasis: %d\n", get_IN_c_emphasis(in)); DBG (15, " High quality: %d\n", get_IN_high_quality(in)); /* known modes FIXME more here? */ s->can_grayscale = get_IN_multilevel (in); DBG (15, " grayscale: %d\n", s->can_grayscale); s->can_halftone = get_IN_half_tone (in); DBG (15, " halftone: %d\n", s->can_halftone); s->can_monochrome = get_IN_monochrome (in); DBG (15, " monochrome: %d\n", s->can_monochrome); s->can_overflow = get_IN_overflow(in); DBG (15, " overflow: %d\n", s->can_overflow); } /*FIXME no vpd, set some defaults? */ else{ DBG (5, "init_vpd: Your scanner does not support VPD?\n"); DBG (5, "init_vpd: Please contact kitno455 at gmail dot com\n"); DBG (5, "init_vpd: with details of your scanner model.\n"); } DBG (10, "init_vpd: finish\n"); return ret; } /* * get model specific info that is not in vpd, and correct * errors in vpd data. struct is already initialized to 0. */ static SANE_Status init_model (struct scanner *s) { DBG (10, "init_model: start\n"); s->reverse_by_mode[MODE_LINEART] = 1; s->reverse_by_mode[MODE_HALFTONE] = 1; s->reverse_by_mode[MODE_GRAYSCALE] = 0; s->reverse_by_mode[MODE_COLOR] = 0; s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RGB; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RGB; s->always_op = 1; s->has_df = 1; s->has_btc = 1; s->has_counter = 1; s->has_adf = 1; s->has_duplex = 1; s->has_buffer = 1; s->can_read_panel = 1; s->can_write_panel = 1; s->has_ssm = 1; s->brightness_steps = 255; s->contrast_steps = 255; s->threshold_steps = 255; s->ppl_mod = 1; s->bg_color = 0xee; /* assume these are same as adf, override below */ s->valid_x = s->max_x; s->max_x_fb = s->max_x; s->max_y_fb = s->max_y; /* missing from vpd- we will unset this for b&w machines below */ s->can_color = 1; /* specific settings missing from vpd */ if (strstr (s->model_name,"DR-9080")){ s->has_comp_JPEG = 1; s->rgb_format = 2; } else if (strstr (s->model_name,"DR-6080") || strstr (s->model_name,"DR-7580")){ s->has_comp_JPEG = 1; s->can_color = 0; } else if (strstr (s->model_name,"DR-7090")){ s->has_flatbed = 1; } else if (strstr (s->model_name,"DR-9050") || strstr (s->model_name,"DR-7550") || strstr (s->model_name,"DR-6050") || strstr (s->model_name,"DR-G1100") || strstr (s->model_name,"DR-G1130") ){ /*missing*/ s->std_res_x[DPI_100]=1; s->std_res_y[DPI_100]=1; s->std_res_x[DPI_150]=1; s->std_res_y[DPI_150]=1; s->std_res_x[DPI_200]=1; s->std_res_y[DPI_200]=1; s->std_res_x[DPI_240]=1; s->std_res_y[DPI_240]=1; s->std_res_x[DPI_300]=1; s->std_res_y[DPI_300]=1; s->std_res_x[DPI_400]=1; s->std_res_y[DPI_400]=1; s->std_res_x[DPI_600]=1; s->std_res_y[DPI_600]=1; /*weirdness*/ s->has_ssm = 0; s->has_ssm2 = 1; } else if (strstr (s->model_name,"DR-4080") || strstr (s->model_name,"DR-4580") || strstr (s->model_name,"DR-7080")){ s->has_flatbed = 1; } else if (strstr (s->model_name,"DR-2580")){ s->invert_tly = 1; s->rgb_format = 1; s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_rRgGbB; s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG; s->duplex_interlace = DUPLEX_INTERLACE_FBfb; s->need_ccal = 1; s->need_fcal = 1; /*s->duplex_offset = 432; now set in config file*/ s->duplex_offset_side = SIDE_BACK; /*lies*/ s->can_halftone=0; s->can_monochrome=0; } else if (strstr (s->model_name,"DR-2510") || strstr (s->model_name,"DR-2010") ){ s->rgb_format = 1; s->always_op = 0; s->unknown_byte2 = 0x80; s->fixed_width = 1; s->valid_x = 8.5 * 1200; s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_2510; s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_2510; s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_2510; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_2510; s->duplex_interlace = DUPLEX_INTERLACE_2510; /*s->duplex_offset = 400; now set in config file*/ s->need_ccal = 1; s->need_fcal = 1; s->sw_lut = 1; /*s->invert_tly = 1;*/ /*only in Y direction, so we trash them in X*/ s->std_res_x[DPI_100]=0; s->std_res_x[DPI_150]=0; s->std_res_x[DPI_200]=0; s->std_res_x[DPI_240]=0; s->std_res_x[DPI_400]=0; /*lies*/ s->can_halftone=0; s->can_monochrome=0; } /* copied from 2510, possibly incorrect */ else if (strstr (s->model_name,"DR-3010")){ s->rgb_format = 1; s->always_op = 0; s->unknown_byte2 = 0x80; s->fixed_width = 1; s->valid_x = 8.5 * 1200; s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_2510; s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_2510; s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_2510; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_2510; s->duplex_interlace = DUPLEX_INTERLACE_2510; /*s->duplex_offset = 400; now set in config file*/ s->need_ccal = 1; s->need_fcal = 1; s->sw_lut = 1; s->invert_tly = 1; /*only in Y direction, so we trash them in X*/ s->std_res_x[DPI_100]=0; s->std_res_x[DPI_150]=0; s->std_res_x[DPI_200]=0; s->std_res_x[DPI_240]=0; s->std_res_x[DPI_400]=0; /*lies*/ s->can_halftone=0; s->can_monochrome=0; } else if (strstr (s->model_name,"DR-2050") || strstr (s->model_name,"DR-2080")){ s->can_write_panel = 0; s->has_df = 0; s->fixed_width = 1; s->even_Bpl = 1; s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB; s->duplex_interlace = DUPLEX_INTERLACE_FBfb; s->need_fcal_buffer = 1; s->bg_color = 0x08; /*s->duplex_offset = 840; now set in config file*/ s->sw_lut = 1; /*lies*/ s->can_halftone=0; s->can_monochrome=0; } else if (strstr (s->model_name,"DR-3080")){ s->can_write_panel = 0; s->has_df = 0; s->has_btc = 0; } else if (strstr (s->model_name,"DR-5060F")){ s->can_write_panel = 0; s->has_df = 0; s->has_btc = 0; s->ppl_mod = 32; s->reverse_by_mode[MODE_LINEART] = 0; s->reverse_by_mode[MODE_HALFTONE] = 0; s->can_color = 0; } else if (strstr (s->model_name,"DR-5020")){ s->can_read_panel = 0; s->can_write_panel = 0; s->has_df = 0; s->has_btc = 0; s->ppl_mod = 32; s->reverse_by_mode[MODE_LINEART] = 0; s->reverse_by_mode[MODE_HALFTONE] = 0; s->can_color = 0; } /* all copied from P-215 */ else if (strstr (s->model_name, "P-150")) { s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_rRgGbB; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB; s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_gG; s->duplex_interlace = DUPLEX_INTERLACE_FBfb; s->need_ccal = 1; s->invert_tly = 1; s->unknown_byte2 = 0x88; s->rgb_format = 1; s->has_ssm_pay_head_len = 1; s->ppl_mod = 8; s->ccal_version = 3; s->can_read_sensors = 1; s->has_card = 1; } else if (strstr (s->model_name, "P-208")) { s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_rRgGbB; s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG; s->duplex_interlace = DUPLEX_INTERLACE_FBfb; s->need_ccal = 1; s->invert_tly = 1; s->unknown_byte2 = 0x88; s->rgb_format = 1; s->has_ssm_pay_head_len = 1; s->ppl_mod = 8; s->ccal_version = 3; s->can_read_sensors = 1; } else if (strstr (s->model_name, "P-215")) { s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_rRgGbB; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_RRGGBB; s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_gG; s->duplex_interlace = DUPLEX_INTERLACE_FBfb; s->need_ccal = 1; s->invert_tly = 1; s->unknown_byte2 = 0x88; s->rgb_format = 1; s->has_ssm_pay_head_len = 1; s->ppl_mod = 8; s->ccal_version = 3; s->can_read_sensors = 1; s->has_card = 1; } else if (strstr (s->model_name,"DR-M160")){ /*missing*/ s->std_res_x[DPI_100]=1; s->std_res_y[DPI_100]=1; s->std_res_x[DPI_150]=1; s->std_res_y[DPI_150]=1; s->std_res_x[DPI_200]=1; s->std_res_y[DPI_200]=1; s->std_res_x[DPI_300]=1; s->std_res_y[DPI_300]=1; s->std_res_x[DPI_400]=1; s->std_res_y[DPI_400]=1; s->std_res_x[DPI_600]=1; s->std_res_y[DPI_600]=1; s->has_comp_JPEG = 1; s->rgb_format = 1; s->has_df_ultra = 1; s->color_inter_by_res[DPI_100] = COLOR_INTERLACE_GBR; s->color_inter_by_res[DPI_150] = COLOR_INTERLACE_GBR; s->color_inter_by_res[DPI_200] = COLOR_INTERLACE_BRG; s->color_inter_by_res[DPI_400] = COLOR_INTERLACE_GBR; /*weirdness*/ s->always_op = 0; s->fixed_width = 1; s->invert_tly = 1; s->can_write_panel = 0; s->has_ssm = 0; s->has_ssm2 = 1; s->duplex_interlace = DUPLEX_INTERLACE_FfBb; s->duplex_offset_side = SIDE_FRONT; /*lies*/ s->can_halftone=0; s->can_monochrome=0; } else if (strstr (s->model_name,"DR-M140")){ /*missing*/ s->std_res_x[DPI_100]=1; s->std_res_y[DPI_100]=1; s->std_res_x[DPI_150]=1; s->std_res_y[DPI_150]=1; s->std_res_x[DPI_200]=1; s->std_res_y[DPI_200]=1; s->std_res_x[DPI_300]=1; s->std_res_y[DPI_300]=1; s->std_res_x[DPI_400]=1; s->std_res_y[DPI_400]=1; s->std_res_x[DPI_600]=1; s->std_res_y[DPI_600]=1; s->has_comp_JPEG = 1; s->rgb_format = 1; s->has_df_ultra = 1; s->color_inter_by_res[DPI_100] = COLOR_INTERLACE_GBR; s->color_inter_by_res[DPI_150] = COLOR_INTERLACE_GBR; s->color_inter_by_res[DPI_200] = COLOR_INTERLACE_BRG; s->color_inter_by_res[DPI_400] = COLOR_INTERLACE_GBR; /*weirdness*/ s->always_op = 0; s->fixed_width = 1; s->invert_tly = 1; s->can_write_panel = 0; s->has_ssm = 0; s->has_ssm2 = 1; s->duplex_interlace = DUPLEX_INTERLACE_FfBb; s->duplex_offset_side = SIDE_BACK; /*lies*/ s->can_halftone=0; s->can_monochrome=0; } else if (strstr (s->model_name,"DR-C125")){ /*confirmed settings*/ s->gray_interlace[SIDE_FRONT] = GRAY_INTERLACE_2510; s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_2510; s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_2510; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_2510; s->duplex_interlace = DUPLEX_INTERLACE_2510; s->duplex_offset_side = SIDE_BACK; s->unknown_byte2 = 0x88; s->need_ccal = 1; s->ccal_version = 3; s->need_fcal = 1; s->sw_lut = 1; s->rgb_format = 1; /*s->duplex_offset = 400; now set in config file*/ /*only in Y direction, so we trash them in X*/ s->std_res_x[DPI_100]=0; s->std_res_x[DPI_150]=0; s->std_res_x[DPI_200]=0; s->std_res_x[DPI_240]=0; s->std_res_x[DPI_400]=0; /*suspected settings*/ s->always_op = 0; s->fixed_width = 1; s->valid_x = 8.5 * 1200; } else if (strstr (s->model_name,"DR-C225")){ s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_RRGGBB; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_rRgGbB; s->gray_interlace[SIDE_BACK] = GRAY_INTERLACE_gG; s->duplex_interlace = DUPLEX_INTERLACE_FBfb; s->unknown_byte2 = 0x88; s->need_ccal = 1; s->ccal_version = 3; s->need_fcal = 1; s->invert_tly = 1; s->rgb_format = 1; /*s->duplex_offset = 400; now set in config file*/ /*only in Y direction, so we trash them in X*/ s->std_res_x[DPI_100]=0; s->std_res_x[DPI_150]=0; s->std_res_x[DPI_200]=0; s->std_res_x[DPI_240]=0; s->std_res_x[DPI_400]=0; /*suspected settings*/ s->always_op = 0; s->fixed_width = 1; s->valid_x = 8.5 * 1200; } else if (strstr (s->model_name,"DR-F120")){ /* TODO items: * * has_rif = 0 ? is this correct * * has_comp_JPEG = 0 ? is this correct * * need_ccal = need_fcal = need_fcal_buffer = ccal_version = 0 ? is this correct */ /* Required for USB coms */ s->has_ssm = 0; s->has_ssm2 = 1; /*missing*/ s->std_res_x[DPI_100] = 1; s->std_res_y[DPI_100] = 1; // DPI_150 not supported s->std_res_x[DPI_200] = 1; s->std_res_y[DPI_200] = 1; s->std_res_x[DPI_300] = 1; s->std_res_y[DPI_300] = 1; // DPI_400 not supported s->std_res_x[DPI_600]= 1; s->std_res_y[DPI_600] = 1; // DPI_1200 not supported // NOTE: This scanner supports higher resolutions // in the Y direction, but 600 is maximum in X // This is true however only the ADF is ever selected in hardware // FIXME: What extra option is needed to select this in the USB comms s->has_flatbed = 1; /* duplex */ s->duplex_interlace = DUPLEX_INTERLACE_fFBb; s->color_interlace[SIDE_FRONT] = COLOR_INTERLACE_GBR; s->color_interlace[SIDE_BACK] = COLOR_INTERLACE_GBR; s->color_inter_by_res[DPI_100] = COLOR_INTERLACE_RGB; s->color_inter_by_res[DPI_600] = COLOR_INTERLACE_RGB; s->duplex_offset_side = SIDE_BACK; /* weirdness */ s->fixed_width = 1; /* lies */ s->can_halftone = 0; } DBG (10, "init_model: finish\n"); return SANE_STATUS_GOOD; } /* * This function enables the buttons and preloads the current panel values */ static SANE_Status init_panel (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "init_panel: start\n"); ret = read_panel(s,0); if(ret){ DBG (5, "init_panel: disabling read_panel\n"); s->can_read_panel = 0; ret = SANE_STATUS_GOOD; } s->panel_enable_led = 1; s->panel_counter = 0; ret = send_panel(s); if(ret){ DBG (5, "init_panel: disabling send_panel\n"); s->can_write_panel = 0; ret = SANE_STATUS_GOOD; } DBG (10, "init_panel: finish\n"); return ret; } /* * set good default user values. * struct is already initialized to 0. */ static SANE_Status init_user (struct scanner *s) { DBG (10, "init_user: start\n"); /* source */ if(s->has_flatbed) s->u.source = SOURCE_FLATBED; else if(s->has_adf) s->u.source = SOURCE_ADF_FRONT; else if(s->has_card) s->u.source = SOURCE_CARD_FRONT; /* scan mode */ if(s->can_monochrome) s->u.mode=MODE_LINEART; else if(s->can_halftone) s->u.mode=MODE_HALFTONE; else if(s->can_grayscale) s->u.mode=MODE_GRAYSCALE; else if(s->can_color) s->u.mode=MODE_COLOR; /*x and y res*/ s->u.dpi_x = s->basic_x_res; s->u.dpi_y = s->basic_x_res; /* page width US-Letter */ s->u.page_x = 8.5 * 1200; if(s->u.page_x > s->valid_x){ s->u.page_x = s->valid_x; } /* page height US-Letter */ s->u.page_y = 11 * 1200; if(s->u.page_y > s->max_y){ s->u.page_y = s->max_y; } /* bottom-right x */ s->u.br_x = s->u.page_x; /* bottom-right y */ s->u.br_y = s->u.page_y; s->threshold = 90; s->compress_arg = 50; DBG (10, "init_user: finish\n"); return SANE_STATUS_GOOD; } /* * This function presets the "option" array to blank */ static SANE_Status init_options (struct scanner *s) { int i; DBG (10, "init_options: start\n"); memset (s->opt, 0, sizeof (s->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].name = "filler"; s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_INACTIVE; } /* go ahead and setup the first opt, because * frontend may call control_option on it * before calling get_option_descriptor */ s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; DBG (10, "init_options: finish\n"); return SANE_STATUS_GOOD; } /* * From the SANE spec: * This function is used to establish a connection to a particular * device. The name of the device to be opened is passed in argument * name. If the call completes successfully, a handle for the device * is returned in *h. As a special case, specifying a zero-length * string as the device requests opening the first available device * (if there is such a device). */ SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle) { struct scanner *dev = NULL; struct scanner *s = NULL; SANE_Status ret; DBG (10, "sane_open: start\n"); if(scanner_devList){ DBG (15, "sane_open: searching currently attached scanners\n"); } else{ DBG (15, "sane_open: no scanners currently attached, attaching\n"); ret = sane_get_devices(NULL,0); if(ret != SANE_STATUS_GOOD){ return ret; } } if(name[0] == 0){ DBG (15, "sane_open: no device requested, using default\n"); s = scanner_devList; } else{ DBG (15, "sane_open: device %s requested\n", name); for (dev = scanner_devList; dev; dev = dev->next) { if (strcmp (dev->sane.name, name) == 0 || strcmp (dev->device_name, name) == 0) { /*always allow sanei devname*/ s = dev; break; } } } if (!s) { DBG (5, "sane_open: no device found\n"); return SANE_STATUS_INVAL; } DBG (15, "sane_open: device %s found\n", s->sane.name); *handle = s; /* connect the fd so we can talk to scanner */ ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ return ret; } DBG (10, "sane_open: finish\n"); return SANE_STATUS_GOOD; } /* * @@ Section 3 - SANE Options functions */ /* * Returns the options we know. * * From the SANE spec: * This function is used to access option descriptors. The function * returns the option descriptor for option number n of the device * represented by handle h. Option number 0 is guaranteed to be a * valid option. Its value is an integer that specifies the number of * options that are available for device handle h (the count includes * option 0). If n is not a valid option index, the function returns * NULL. The returned option descriptor is guaranteed to remain valid * (and at the returned address) until the device is closed. */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct scanner *s = handle; int i; SANE_Option_Descriptor *opt = &s->opt[option]; DBG (20, "sane_get_option_descriptor: %d\n", option); if ((unsigned) option >= NUM_OPTIONS) return NULL; /* "Mode" group -------------------------------------------------------- */ if(option==OPT_STANDARD_GROUP){ opt->name = SANE_NAME_STANDARD; opt->title = SANE_TITLE_STANDARD; opt->desc = SANE_DESC_STANDARD; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* source */ if(option==OPT_SOURCE){ i=0; if(s->has_flatbed){ s->source_list[i++]=STRING_FLATBED; } if(s->has_adf){ s->source_list[i++]=STRING_ADFFRONT; if(s->has_back){ s->source_list[i++]=STRING_ADFBACK; } if(s->has_duplex){ s->source_list[i++]=STRING_ADFDUPLEX; } } if(s->has_card){ s->source_list[i++]=STRING_CARDFRONT; if(s->has_back){ s->source_list[i++]=STRING_CARDBACK; } if(s->has_duplex){ s->source_list[i++]=STRING_CARDDUPLEX; } } s->source_list[i]=NULL; opt->name = SANE_NAME_SCAN_SOURCE; opt->title = SANE_TITLE_SCAN_SOURCE; opt->desc = SANE_DESC_SCAN_SOURCE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->source_list; opt->size = maxStringSize (opt->constraint.string_list); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* scan mode */ if(option==OPT_MODE){ i=0; if(s->can_monochrome || s->can_grayscale || s->can_color){ s->mode_list[i++]=STRING_LINEART; } if(s->can_halftone){ s->mode_list[i++]=STRING_HALFTONE; } if(s->can_grayscale || s->can_color){ s->mode_list[i++]=STRING_GRAYSCALE; } if(s->can_color){ s->mode_list[i++]=STRING_COLOR; } s->mode_list[i]=NULL; opt->name = SANE_NAME_SCAN_MODE; opt->title = SANE_TITLE_SCAN_MODE; opt->desc = SANE_DESC_SCAN_MODE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->mode_list; opt->size = maxStringSize (opt->constraint.string_list); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* resolution */ /* some scanners only support fixed res * build a list of possible choices */ /* we actually only look at the y resolution choices, * and interpolate the image data as required for limited x resolutions */ if(option==OPT_RES){ i=0; if(s->std_res_y[DPI_60] && s->max_y_res >= 60 && s->min_y_res <= 60){ s->res_list[++i] = 60; } if(s->std_res_y[DPI_75] && s->max_y_res >= 75 && s->min_y_res <= 75){ s->res_list[++i] = 75; } if(s->std_res_y[DPI_100] && s->max_y_res >= 100 && s->min_y_res <= 100){ s->res_list[++i] = 100; } if(s->std_res_y[DPI_120] && s->max_y_res >= 120 && s->min_y_res <= 120){ s->res_list[++i] = 120; } if(s->std_res_y[DPI_150] && s->max_y_res >= 150 && s->min_y_res <= 150){ s->res_list[++i] = 150; } if(s->std_res_y[DPI_160] && s->max_y_res >= 160 && s->min_y_res <= 160){ s->res_list[++i] = 160; } if(s->std_res_y[DPI_180] && s->max_y_res >= 180 && s->min_y_res <= 180){ s->res_list[++i] = 180; } if(s->std_res_y[DPI_200] && s->max_y_res >= 200 && s->min_y_res <= 200){ s->res_list[++i] = 200; } if(s->std_res_y[DPI_240] && s->max_y_res >= 240 && s->min_y_res <= 240){ s->res_list[++i] = 240; } if(s->std_res_y[DPI_300] && s->max_y_res >= 300 && s->min_y_res <= 300){ s->res_list[++i] = 300; } if(s->std_res_y[DPI_320] && s->max_y_res >= 320 && s->min_y_res <= 320){ s->res_list[++i] = 320; } if(s->std_res_y[DPI_400] && s->max_y_res >= 400 && s->min_y_res <= 400){ s->res_list[++i] = 400; } if(s->std_res_y[DPI_480] && s->max_y_res >= 480 && s->min_y_res <= 480){ s->res_list[++i] = 480; } if(s->std_res_y[DPI_600] && s->max_y_res >= 600 && s->min_y_res <= 600){ s->res_list[++i] = 600; } if(s->std_res_y[DPI_800] && s->max_y_res >= 800 && s->min_y_res <= 800){ s->res_list[++i] = 800; } if(s->std_res_y[DPI_1200] && s->max_y_res >= 1200 && s->min_y_res <= 1200){ s->res_list[++i] = 1200; } s->res_list[0] = i; opt->name = SANE_NAME_SCAN_RESOLUTION; opt->title = SANE_TITLE_SCAN_RESOLUTION; opt->desc = SANE_DESC_SCAN_RESOLUTION; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_DPI; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->step_y_res){ s->res_range.min = s->min_y_res; s->res_range.max = s->max_y_res; s->res_range.quant = s->step_y_res; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->res_range; } else{ opt->constraint_type = SANE_CONSTRAINT_WORD_LIST; opt->constraint.word_list = s->res_list; } } /* "Geometry" group ---------------------------------------------------- */ if(option==OPT_GEOMETRY_GROUP){ opt->name = SANE_NAME_GEOMETRY; opt->title = SANE_TITLE_GEOMETRY; opt->desc = SANE_DESC_GEOMETRY; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* top-left x */ if(option==OPT_TL_X){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->tl_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->tl_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); s->tl_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_TL_X; opt->title = SANE_TITLE_SCAN_TL_X; opt->desc = SANE_DESC_SCAN_TL_X; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->tl_x_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* top-left y */ if(option==OPT_TL_Y){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->tl_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->tl_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); s->tl_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_TL_Y; opt->title = SANE_TITLE_SCAN_TL_Y; opt->desc = SANE_DESC_SCAN_TL_Y; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->tl_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* bottom-right x */ if(option==OPT_BR_X){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->br_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->br_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); s->br_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_BR_X; opt->title = SANE_TITLE_SCAN_BR_X; opt->desc = SANE_DESC_SCAN_BR_X; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->br_x_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* bottom-right y */ if(option==OPT_BR_Y){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->br_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->br_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); s->br_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_BR_Y; opt->title = SANE_TITLE_SCAN_BR_Y; opt->desc = SANE_DESC_SCAN_BR_Y; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->br_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* page width */ if(option==OPT_PAGE_WIDTH){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->paper_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->paper_x_range.max = SCANNER_UNIT_TO_FIXED_MM(s->valid_x); s->paper_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_PAGE_WIDTH; opt->title = SANE_TITLE_PAGE_WIDTH; opt->desc = SANE_DESC_PAGE_WIDTH; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_x_range; if(s->has_adf || s->has_card){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->u.source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; } } else{ opt->cap = SANE_CAP_INACTIVE; } } /* page height */ if(option==OPT_PAGE_HEIGHT){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->paper_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->paper_y_range.max = SCANNER_UNIT_TO_FIXED_MM(s->max_y); s->paper_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_PAGE_HEIGHT; opt->title = SANE_TITLE_PAGE_HEIGHT; opt->desc = SANE_DESC_PAGE_HEIGHT; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_y_range; if(s->has_adf || s->has_card){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->u.source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; } } else{ opt->cap = SANE_CAP_INACTIVE; } } /* "Enhancement" group ------------------------------------------------- */ if(option==OPT_ENHANCEMENT_GROUP){ opt->name = SANE_NAME_ENHANCEMENT; opt->title = SANE_TITLE_ENHANCEMENT; opt->desc = SANE_DESC_ENHANCEMENT; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* brightness */ if(option==OPT_BRIGHTNESS){ opt->name = SANE_NAME_BRIGHTNESS; opt->title = SANE_TITLE_BRIGHTNESS; opt->desc = SANE_DESC_BRIGHTNESS; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->brightness_range; s->brightness_range.quant=1; /* some have hardware brightness (always 0 to 255?) */ /* some use LUT or GT (-127 to +127)*/ if (s->brightness_steps){ s->brightness_range.min=-127; s->brightness_range.max=127; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else{ opt->cap = SANE_CAP_INACTIVE; } } /* contrast */ if(option==OPT_CONTRAST){ opt->name = SANE_NAME_CONTRAST; opt->title = SANE_TITLE_CONTRAST; opt->desc = SANE_DESC_CONTRAST; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->contrast_range; s->contrast_range.quant=1; /* some have hardware contrast (always 0 to 255?) */ /* some use LUT or GT (-127 to +127)*/ if (s->contrast_steps){ s->contrast_range.min=-127; s->contrast_range.max=127; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else { opt->cap = SANE_CAP_INACTIVE; } } /*threshold*/ if(option==OPT_THRESHOLD){ opt->name = SANE_NAME_THRESHOLD; opt->title = SANE_TITLE_THRESHOLD; opt->desc = SANE_DESC_THRESHOLD; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->threshold_range; s->threshold_range.min=0; s->threshold_range.max=s->threshold_steps; s->threshold_range.quant=1; if (s->threshold_steps){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->u.mode != MODE_LINEART){ opt->cap |= SANE_CAP_INACTIVE; } } else { opt->cap = SANE_CAP_INACTIVE; } } if(option==OPT_RIF){ opt->name = "rif"; opt->title = "RIF"; opt->desc = "Reverse image format"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_rif) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; else opt->cap = SANE_CAP_INACTIVE; } /* "Advanced" group ------------------------------------------------------ */ if(option==OPT_ADVANCED_GROUP){ opt->name = SANE_NAME_ADVANCED; opt->title = SANE_TITLE_ADVANCED; opt->desc = SANE_DESC_ADVANCED; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /*image compression*/ if(option==OPT_COMPRESS){ i=0; s->compress_list[i++]=STRING_NONE; if(s->has_comp_JPEG){ #ifndef SANE_JPEG_DISABLED s->compress_list[i++]=STRING_JPEG; #endif } s->compress_list[i]=NULL; opt->name = "compression"; opt->title = "Compression"; opt->desc = "Enable compressed data. May crash your front-end program"; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->compress_list; opt->size = maxStringSize (opt->constraint.string_list); if (i > 1){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if ( must_downsample(s) || s->s.mode < MODE_GRAYSCALE ){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } /*image compression arg*/ if(option==OPT_COMPRESS_ARG){ opt->name = "compression-arg"; opt->title = "Compression argument"; opt->desc = "Level of JPEG compression. 1 is small file, 100 is large file."; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->compress_arg_range; s->compress_arg_range.quant=1; if(s->has_comp_JPEG){ s->compress_arg_range.min=0; s->compress_arg_range.max=100; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->compress != COMP_JPEG){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } /*double feed by length*/ if(option==OPT_DF_LENGTH){ opt->name = "df-length"; opt->title = "DF by length"; opt->desc = "Detect double feeds by comparing document lengths"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_NONE; if (1) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*double feed by thickness */ if(option==OPT_DF_THICKNESS){ opt->name = "df-thickness"; opt->title = "DF by thickness"; opt->desc = "Detect double feeds using thickness sensor"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_NONE; if (1){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; } else opt->cap = SANE_CAP_INACTIVE; } /*deskew by roller*/ if(option==OPT_ROLLERDESKEW){ opt->name = "rollerdeskew"; opt->title = "Roller deskew"; opt->desc = "Request scanner to correct skewed pages mechanically"; opt->type = SANE_TYPE_BOOL; if (1) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*deskew by software*/ if(option==OPT_SWDESKEW){ opt->name = "swdeskew"; opt->title = "Software deskew"; opt->desc = "Request driver to rotate skewed pages digitally"; opt->type = SANE_TYPE_BOOL; if (1) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*software despeckle radius*/ if(option==OPT_SWDESPECK){ opt->name = "swdespeck"; opt->title = "Software despeckle diameter"; opt->desc = "Maximum diameter of lone dots to remove from scan"; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->swdespeck_range; s->swdespeck_range.quant=1; if(1){ s->swdespeck_range.min=0; s->swdespeck_range.max=9; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else opt->cap = SANE_CAP_INACTIVE; } /*crop by software*/ if(option==OPT_SWCROP){ opt->name = "swcrop"; opt->title = "Software crop"; opt->desc = "Request driver to remove border from pages digitally"; opt->type = SANE_TYPE_BOOL; if (1) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /* Software blank page skip */ if(option==OPT_SWSKIP){ opt->name = "swskip"; opt->title = SANE_I18N ("Software blank skip percentage"); opt->desc = SANE_I18N("Request driver to discard pages with low percentage of dark pixels"); opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_PERCENT; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->swskip_range; s->swskip_range.quant=SANE_FIX(0.10001); s->swskip_range.min=SANE_FIX(0); s->swskip_range.max=SANE_FIX(100); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /*staple detection*/ if(option==OPT_STAPLEDETECT){ opt->name = "stapledetect"; opt->title = "Staple detect"; opt->desc = "Request scanner to halt if stapled pages are detected"; opt->type = SANE_TYPE_BOOL; if (1) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*dropout color front*/ if(option==OPT_DROPOUT_COLOR_F){ s->do_color_list[0] = STRING_NONE; s->do_color_list[1] = STRING_RED; s->do_color_list[2] = STRING_GREEN; s->do_color_list[3] = STRING_BLUE; s->do_color_list[4] = STRING_EN_RED; s->do_color_list[5] = STRING_EN_GREEN; s->do_color_list[6] = STRING_EN_BLUE; s->do_color_list[7] = NULL; opt->name = "dropout-front"; opt->title = "Dropout color front"; opt->desc = "One-pass scanners use only one color during gray or binary scanning, useful for colored paper or ink"; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->do_color_list; opt->size = maxStringSize (opt->constraint.string_list); if (1){ opt->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; if(s->u.mode == MODE_COLOR) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; } /*dropout color back*/ if(option==OPT_DROPOUT_COLOR_B){ s->do_color_list[0] = STRING_NONE; s->do_color_list[1] = STRING_RED; s->do_color_list[2] = STRING_GREEN; s->do_color_list[3] = STRING_BLUE; s->do_color_list[4] = STRING_EN_RED; s->do_color_list[5] = STRING_EN_GREEN; s->do_color_list[6] = STRING_EN_BLUE; s->do_color_list[7] = NULL; opt->name = "dropout-back"; opt->title = "Dropout color back"; opt->desc = "One-pass scanners use only one color during gray or binary scanning, useful for colored paper or ink"; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->do_color_list; opt->size = maxStringSize (opt->constraint.string_list); if (1){ opt->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; if(s->u.mode == MODE_COLOR) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; } /*buffer mode*/ if(option==OPT_BUFFERMODE){ opt->name = "buffermode"; opt->title = "Buffer mode"; opt->desc = "Request scanner to read pages async into internal memory"; opt->type = SANE_TYPE_BOOL; if (s->has_buffer) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_SIDE){ opt->name = "side"; opt->title = "Duplex side"; opt->desc = "Tells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return."; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->size = sizeof(SANE_Word); opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* "Sensor" group ------------------------------------------------------ */ if(option==OPT_SENSOR_GROUP){ opt->name = SANE_NAME_SENSORS; opt->title = SANE_TITLE_SENSORS; opt->desc = SANE_DESC_SENSORS; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } if(option==OPT_START){ opt->name = "start"; opt->title = "Start/1 button"; opt->desc = "Big green or small 1 button"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if(!s->can_read_panel) opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_STOP){ opt->name = "stop"; opt->title = "Stop/2 button"; opt->desc = "Small orange or small 2 button"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if(!s->can_read_panel) opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_BUTT3){ opt->name = "button-3"; opt->title = "3 button"; opt->desc = "Small 3 button"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if(!s->can_read_panel) opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_NEWFILE){ opt->name = "newfile"; opt->title = "New File button"; opt->desc = "New File button"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if(!s->can_read_panel) opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_COUNTONLY){ opt->name = "countonly"; opt->title = "Count Only button"; opt->desc = "Count Only button"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if(!s->can_read_panel) opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_BYPASSMODE){ opt->name = "bypassmode"; opt->title = "Bypass Mode button"; opt->desc = "Bypass Mode button"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if(!s->can_read_panel) opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_COUNTER){ opt->name = "counter"; opt->title = "Counter"; opt->desc = "Scan counter"; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->counter_range; s->counter_range.min=0; s->counter_range.max=500; s->counter_range.quant=1; if (s->can_read_panel && s->has_counter) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_ADF_LOADED){ opt->name = "adf-loaded"; opt->title = "ADF Loaded"; opt->desc = "Paper available in ADF input hopper"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if(!s->can_read_sensors) opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_CARD_LOADED){ opt->name = "card-loaded"; opt->title = "Card Loaded"; opt->desc = "Paper available in card reader"; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if(!s->can_read_sensors || !s->has_card) opt->cap = SANE_CAP_INACTIVE; } return opt; } /** * Gets or sets an option value. * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which * the option is controlled is specified by parameter action. The * possible values of this parameter are described in more detail * below. The value of the option is passed through argument val. It * is a pointer to the memory that holds the option value. The memory * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon * encountering the first NUL terminator in the string. If argument i * is not NULL, the value of *i will be set to provide details on how * well the request has been met. */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { struct scanner *s = (struct scanner *) handle; SANE_Int dummy = 0; SANE_Status ret = SANE_STATUS_GOOD; /* Make sure that all those statements involving *info cannot break (better * than having to do "if (info) ..." everywhere!) */ if (info == 0) info = &dummy; if (option >= NUM_OPTIONS) { DBG (5, "sane_control_option: %d too big\n", option); return SANE_STATUS_INVAL; } if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) { DBG (5, "sane_control_option: %d inactive\n", option); return SANE_STATUS_INVAL; } /* * SANE_ACTION_GET_VALUE: We have to find out the current setting and * return it in a human-readable form (often, text). */ if (action == SANE_ACTION_GET_VALUE) { SANE_Word * val_p = (SANE_Word *) val; DBG (20, "sane_control_option: get value for '%s' (%d)\n", s->opt[option].name,option); switch (option) { case OPT_NUM_OPTS: *val_p = NUM_OPTIONS; return SANE_STATUS_GOOD; case OPT_SOURCE: if(s->u.source == SOURCE_FLATBED){ strcpy (val, STRING_FLATBED); } else if(s->u.source == SOURCE_ADF_FRONT){ strcpy (val, STRING_ADFFRONT); } else if(s->u.source == SOURCE_ADF_BACK){ strcpy (val, STRING_ADFBACK); } else if(s->u.source == SOURCE_ADF_DUPLEX){ strcpy (val, STRING_ADFDUPLEX); } else if(s->u.source == SOURCE_CARD_FRONT){ strcpy (val, STRING_CARDFRONT); } else if(s->u.source == SOURCE_CARD_BACK){ strcpy (val, STRING_CARDBACK); } else if(s->u.source == SOURCE_CARD_DUPLEX){ strcpy (val, STRING_CARDDUPLEX); } return SANE_STATUS_GOOD; case OPT_MODE: if(s->u.mode == MODE_LINEART){ strcpy (val, STRING_LINEART); } else if(s->u.mode == MODE_HALFTONE){ strcpy (val, STRING_HALFTONE); } else if(s->u.mode == MODE_GRAYSCALE){ strcpy (val, STRING_GRAYSCALE); } else if(s->u.mode == MODE_COLOR){ strcpy (val, STRING_COLOR); } return SANE_STATUS_GOOD; case OPT_RES: *val_p = s->u.dpi_x; return SANE_STATUS_GOOD; case OPT_TL_X: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u.tl_x); return SANE_STATUS_GOOD; case OPT_TL_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u.tl_y); return SANE_STATUS_GOOD; case OPT_BR_X: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u.br_x); return SANE_STATUS_GOOD; case OPT_BR_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u.br_y); return SANE_STATUS_GOOD; case OPT_PAGE_WIDTH: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u.page_x); return SANE_STATUS_GOOD; case OPT_PAGE_HEIGHT: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u.page_y); return SANE_STATUS_GOOD; case OPT_BRIGHTNESS: *val_p = s->brightness; return SANE_STATUS_GOOD; case OPT_CONTRAST: *val_p = s->contrast; return SANE_STATUS_GOOD; case OPT_THRESHOLD: *val_p = s->threshold; return SANE_STATUS_GOOD; case OPT_RIF: *val_p = s->rif; return SANE_STATUS_GOOD; /* Advanced Group */ case OPT_COMPRESS: if(s->compress == COMP_JPEG){ strcpy (val, STRING_JPEG); } else{ strcpy (val, STRING_NONE); } return SANE_STATUS_GOOD; case OPT_COMPRESS_ARG: *val_p = s->compress_arg; return SANE_STATUS_GOOD; case OPT_DF_LENGTH: *val_p = s->df_length; return SANE_STATUS_GOOD; case OPT_DF_THICKNESS: *val_p = s->df_thickness; return SANE_STATUS_GOOD; case OPT_ROLLERDESKEW: *val_p = s->rollerdeskew; return SANE_STATUS_GOOD; case OPT_SWDESKEW: *val_p = s->swdeskew; return SANE_STATUS_GOOD; case OPT_SWDESPECK: *val_p = s->swdespeck; return SANE_STATUS_GOOD; case OPT_SWCROP: *val_p = s->swcrop; return SANE_STATUS_GOOD; case OPT_SWSKIP: *val_p = SANE_FIX(s->swskip); return SANE_STATUS_GOOD; case OPT_STAPLEDETECT: *val_p = s->stapledetect; return SANE_STATUS_GOOD; case OPT_DROPOUT_COLOR_F: switch (s->dropout_color[SIDE_FRONT]) { case COLOR_NONE: strcpy (val, STRING_NONE); break; case COLOR_RED: strcpy (val, STRING_RED); break; case COLOR_GREEN: strcpy (val, STRING_GREEN); break; case COLOR_BLUE: strcpy (val, STRING_BLUE); break; case COLOR_EN_RED: strcpy (val, STRING_EN_RED); break; case COLOR_EN_GREEN: strcpy (val, STRING_EN_GREEN); break; case COLOR_EN_BLUE: strcpy (val, STRING_EN_BLUE); break; } return SANE_STATUS_GOOD; case OPT_DROPOUT_COLOR_B: switch (s->dropout_color[SIDE_BACK]) { case COLOR_NONE: strcpy (val, STRING_NONE); break; case COLOR_RED: strcpy (val, STRING_RED); break; case COLOR_GREEN: strcpy (val, STRING_GREEN); break; case COLOR_BLUE: strcpy (val, STRING_BLUE); break; case COLOR_EN_RED: strcpy (val, STRING_EN_RED); break; case COLOR_EN_GREEN: strcpy (val, STRING_EN_GREEN); break; case COLOR_EN_BLUE: strcpy (val, STRING_EN_BLUE); break; } return SANE_STATUS_GOOD; case OPT_BUFFERMODE: *val_p = s->buffermode; return SANE_STATUS_GOOD; case OPT_SIDE: *val_p = s->side; return SANE_STATUS_GOOD; /* Sensor Group */ case OPT_START: ret = read_panel(s,OPT_START); *val_p = s->panel_start; return ret; case OPT_STOP: ret = read_panel(s,OPT_STOP); *val_p = s->panel_stop; return ret; case OPT_BUTT3: ret = read_panel(s,OPT_BUTT3); *val_p = s->panel_butt3; return ret; case OPT_NEWFILE: ret = read_panel(s,OPT_NEWFILE); *val_p = s->panel_new_file; return ret; case OPT_COUNTONLY: ret = read_panel(s,OPT_COUNTONLY); *val_p = s->panel_count_only; return ret; case OPT_BYPASSMODE: ret = read_panel(s,OPT_BYPASSMODE); *val_p = s->panel_bypass_mode; return ret; case OPT_COUNTER: ret = read_panel(s,OPT_COUNTER); *val_p = s->panel_counter; return ret; case OPT_ADF_LOADED: ret = read_sensors(s,OPT_ADF_LOADED); *val_p = s->sensor_adf_loaded; return ret; case OPT_CARD_LOADED: ret = read_sensors(s,OPT_CARD_LOADED); *val_p = s->sensor_card_loaded; return ret; } } else if (action == SANE_ACTION_SET_VALUE) { int tmp; SANE_Word val_c; SANE_Status status; DBG (20, "sane_control_option: set value for '%s' (%d)\n", s->opt[option].name,option); if ( s->started ) { DBG (5, "sane_control_option: cant set, device busy\n"); return SANE_STATUS_DEVICE_BUSY; } if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) { DBG (5, "sane_control_option: not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (5, "sane_control_option: bad value\n"); return status; } /* may have been changed by constrain, so dont copy until now */ val_c = *(SANE_Word *)val; /* * Note - for those options which can assume one of a list of * valid values, we can safely assume that they will have * exactly one of those values because that's what * sanei_constrain_value does. Hence no "else: invalid" branches * below. */ switch (option) { /* Mode Group */ case OPT_SOURCE: if (!strcmp (val, STRING_ADFFRONT)) { tmp = SOURCE_ADF_FRONT; } else if (!strcmp (val, STRING_ADFBACK)) { tmp = SOURCE_ADF_BACK; } else if (!strcmp (val, STRING_ADFDUPLEX)) { tmp = SOURCE_ADF_DUPLEX; } else if (!strcmp (val, STRING_CARDFRONT)) { tmp = SOURCE_CARD_FRONT; } else if (!strcmp (val, STRING_CARDBACK)) { tmp = SOURCE_CARD_BACK; } else if (!strcmp (val, STRING_CARDDUPLEX)) { tmp = SOURCE_CARD_DUPLEX; } else{ tmp = SOURCE_FLATBED; } if (s->u.source == tmp) return SANE_STATUS_GOOD; s->u.source = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_MODE: if (!strcmp (val, STRING_LINEART)) { tmp = MODE_LINEART; } else if (!strcmp (val, STRING_HALFTONE)) { tmp = MODE_HALFTONE; } else if (!strcmp (val, STRING_GRAYSCALE)) { tmp = MODE_GRAYSCALE; } else{ tmp = MODE_COLOR; } if (tmp == s->u.mode) return SANE_STATUS_GOOD; s->u.mode = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_RES: if (s->u.dpi_x == val_c && s->u.dpi_y == val_c) return SANE_STATUS_GOOD; s->u.dpi_x = val_c; s->u.dpi_y = val_c; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; /* Geometry Group */ case OPT_TL_X: if (s->u.tl_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->u.tl_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_TL_Y: if (s->u.tl_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->u.tl_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_BR_X: if (s->u.br_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->u.br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_BR_Y: if (s->u.br_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->u.br_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_PAGE_WIDTH: if (s->u.page_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; /* if full width image, and paper size is changed, change the image size to match new paper */ if (s->u.tl_x == 0 && s->u.br_x == s->u.page_x){ DBG (20, "sane_control_option: br_x tracking page_width\n"); s->u.br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS; } s->u.page_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_PAGE_HEIGHT: if (s->u.page_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; /* if full height image, and paper size is changed, change the image size to match new paper */ if (s->u.tl_y == 0 && s->u.br_y == s->u.page_y){ DBG (20, "sane_control_option: br_y tracking page_height\n"); s->u.br_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS; } s->u.page_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; /* Enhancement Group */ case OPT_BRIGHTNESS: s->brightness = val_c; return SANE_STATUS_GOOD; case OPT_CONTRAST: s->contrast = val_c; return SANE_STATUS_GOOD; case OPT_THRESHOLD: s->threshold = val_c; return SANE_STATUS_GOOD; case OPT_RIF: s->rif = val_c; return SANE_STATUS_GOOD; /* Advanced Group */ case OPT_COMPRESS: if (!strcmp (val, STRING_JPEG)) { s->compress = COMP_JPEG; } else{ s->compress = COMP_NONE; } return SANE_STATUS_GOOD; case OPT_COMPRESS_ARG: s->compress_arg = val_c; return SANE_STATUS_GOOD; case OPT_DF_LENGTH: s->df_length = val_c; return SANE_STATUS_GOOD; case OPT_DF_THICKNESS: s->df_thickness = val_c; return SANE_STATUS_GOOD; case OPT_ROLLERDESKEW: s->rollerdeskew = val_c; return SANE_STATUS_GOOD; case OPT_SWDESKEW: s->swdeskew = val_c; return SANE_STATUS_GOOD; case OPT_SWDESPECK: s->swdespeck = val_c; return SANE_STATUS_GOOD; case OPT_SWCROP: s->swcrop = val_c; return SANE_STATUS_GOOD; case OPT_SWSKIP: s->swskip = SANE_UNFIX(val_c); return SANE_STATUS_GOOD; case OPT_STAPLEDETECT: s->stapledetect = val_c; return SANE_STATUS_GOOD; case OPT_DROPOUT_COLOR_F: if (!strcmp(val, STRING_NONE)) s->dropout_color[SIDE_FRONT] = COLOR_NONE; else if (!strcmp(val, STRING_RED)) s->dropout_color[SIDE_FRONT] = COLOR_RED; else if (!strcmp(val, STRING_GREEN)) s->dropout_color[SIDE_FRONT] = COLOR_GREEN; else if (!strcmp(val, STRING_BLUE)) s->dropout_color[SIDE_FRONT] = COLOR_BLUE; else if (!strcmp(val, STRING_EN_RED)) s->dropout_color[SIDE_FRONT] = COLOR_EN_RED; else if (!strcmp(val, STRING_EN_GREEN)) s->dropout_color[SIDE_FRONT] = COLOR_EN_GREEN; else if (!strcmp(val, STRING_EN_BLUE)) s->dropout_color[SIDE_FRONT] = COLOR_EN_BLUE; return SANE_STATUS_GOOD; case OPT_DROPOUT_COLOR_B: if (!strcmp(val, STRING_NONE)) s->dropout_color[SIDE_BACK] = COLOR_NONE; else if (!strcmp(val, STRING_RED)) s->dropout_color[SIDE_BACK] = COLOR_RED; else if (!strcmp(val, STRING_GREEN)) s->dropout_color[SIDE_BACK] = COLOR_GREEN; else if (!strcmp(val, STRING_BLUE)) s->dropout_color[SIDE_BACK] = COLOR_BLUE; else if (!strcmp(val, STRING_EN_RED)) s->dropout_color[SIDE_BACK] = COLOR_EN_RED; else if (!strcmp(val, STRING_EN_GREEN)) s->dropout_color[SIDE_BACK] = COLOR_EN_GREEN; else if (!strcmp(val, STRING_EN_BLUE)) s->dropout_color[SIDE_BACK] = COLOR_EN_BLUE; return SANE_STATUS_GOOD; case OPT_BUFFERMODE: s->buffermode = val_c; return SANE_STATUS_GOOD; } } /* else */ return SANE_STATUS_INVAL; } static SANE_Status ssm_buffer (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "ssm_buffer: start\n"); if(s->has_ssm){ unsigned char cmd[SET_SCAN_MODE_len]; size_t cmdLen = SET_SCAN_MODE_len; unsigned char out[SSM_PAY_len]; size_t outLen = SSM_PAY_len; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE_code); set_SSM_pf(cmd, 1); set_SSM_pay_len(cmd, outLen); memset(out,0,outLen); if(s->has_ssm_pay_head_len){ set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); } set_SSM_page_code(out, SM_pc_buffer); set_SSM_page_len(out, SSM_PAGE_len); if(s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX){ set_SSM_BUFF_duplex(out, 1); } if(s->s.source == SOURCE_FLATBED){ set_SSM_BUFF_fb(out, 1); } else if(s->s.source >= SOURCE_CARD_FRONT){ set_SSM_BUFF_card(out, 1); } if(s->buffermode){ set_SSM_BUFF_async(out, 1); } if(0){ set_SSM_BUFF_ald(out, 1); } if(0){ set_SSM_BUFF_unk(out,1); } ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } else if(s->has_ssm2){ unsigned char cmd[SET_SCAN_MODE2_len]; size_t cmdLen = SET_SCAN_MODE2_len; unsigned char out[SSM2_PAY_len]; size_t outLen = SSM2_PAY_len; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); set_SSM2_page_code(cmd, SM2_pc_buffer); set_SSM2_pay_len(cmd, outLen); memset(out,0,outLen); set_SSM2_BUFF_unk(out, !s->buffermode); set_SSM2_BUFF_unk2(out, 0x40); set_SSM2_BUFF_sync(out, !s->buffermode); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } else{ DBG (10, "ssm_buffer: unsupported\n"); } DBG (10, "ssm_buffer: finish\n"); return ret; } static SANE_Status ssm_df (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "ssm_df: start\n"); if(!s->has_df){ DBG (10, "ssm_df: unsupported, finishing\n"); return ret; } if(s->has_ssm){ unsigned char cmd[SET_SCAN_MODE_len]; size_t cmdLen = SET_SCAN_MODE_len; unsigned char out[SSM_PAY_len]; size_t outLen = SSM_PAY_len; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE_code); set_SSM_pf(cmd, 1); set_SSM_pay_len(cmd, outLen); memset(out,0,outLen); if(s->has_ssm_pay_head_len){ set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); } set_SSM_page_code(out, SM_pc_df); set_SSM_page_len(out, SSM_PAGE_len); /* deskew by roller */ if(s->rollerdeskew){ set_SSM_DF_deskew_roll(out, 1); } /* staple detection */ if(s->stapledetect){ set_SSM_DF_staple(out, 1); } /* thickness */ if(s->df_thickness){ set_SSM_DF_thick(out, 1); } /* length */ if(s->df_length){ set_SSM_DF_len(out, 1); } ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } else if(s->has_ssm2){ unsigned char cmd[SET_SCAN_MODE2_len]; size_t cmdLen = SET_SCAN_MODE2_len; unsigned char out[SSM2_PAY_len]; size_t outLen = SSM2_PAY_len; /* send ultrasonic offsets first */ if(s->df_thickness && s->has_df_ultra){ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); set_SSM2_page_code(cmd, SM2_pc_ultra); set_SSM2_pay_len(cmd, outLen); memset(out,0,outLen); set_SSM2_ULTRA_top(out, 0); set_SSM2_ULTRA_bot(out, 0); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); set_SSM2_page_code(cmd, SM2_pc_df); set_SSM2_pay_len(cmd, outLen); memset(out,0,outLen); /* thickness */ if(s->df_thickness){ set_SSM2_DF_thick(out, 1); } /* length */ if(s->df_length){ set_SSM2_DF_len(out, 1); } ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } else{ DBG (10, "ssm_df: unsupported\n"); } DBG (10, "ssm_df: finish\n"); return ret; } static SANE_Status ssm_do (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "ssm_do: start\n"); if(!s->can_color){ DBG (10, "ssm_do: unsupported, finishing\n"); return ret; } if(s->s.mode == MODE_COLOR){ DBG (10, "ssm_do: unneeded, finishing\n"); return ret; } if(s->has_ssm){ unsigned char cmd[SET_SCAN_MODE_len]; size_t cmdLen = SET_SCAN_MODE_len; unsigned char out[SSM_PAY_len]; size_t outLen = SSM_PAY_len; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE_code); set_SSM_pf(cmd, 1); set_SSM_pay_len(cmd, outLen); memset(out,0,outLen); if(s->has_ssm_pay_head_len){ set_SSM_pay_head_len(out, SSM_PAY_HEAD_len); } set_SSM_page_code(out, SM_pc_dropout); set_SSM_page_len(out, SSM_PAGE_len); set_SSM_DO_unk1(out, 0x03); switch(s->dropout_color[SIDE_FRONT]){ case COLOR_RED: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_f_do(out,SSM_DO_red); break; case COLOR_GREEN: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_f_do(out,SSM_DO_green); break; case COLOR_BLUE: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_f_do(out,SSM_DO_blue); break; case COLOR_EN_RED: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_f_en(out,SSM_DO_red); break; case COLOR_EN_GREEN: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_f_en(out,SSM_DO_green); break; case COLOR_EN_BLUE: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_f_en(out,SSM_DO_blue); break; } switch(s->dropout_color[SIDE_BACK]){ case COLOR_RED: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_b_do(out,SSM_DO_red); break; case COLOR_GREEN: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_b_do(out,SSM_DO_green); break; case COLOR_BLUE: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_b_do(out,SSM_DO_blue); break; case COLOR_EN_RED: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_b_en(out,SSM_DO_red); break; case COLOR_EN_GREEN: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_b_en(out,SSM_DO_green); break; case COLOR_EN_BLUE: set_SSM_DO_unk2(out, 0x05); set_SSM_DO_b_en(out,SSM_DO_blue); break; } ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } else if(s->has_ssm2){ unsigned char cmd[SET_SCAN_MODE2_len]; size_t cmdLen = SET_SCAN_MODE2_len; unsigned char out[SSM2_PAY_len]; size_t outLen = SSM2_PAY_len; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_SCAN_MODE2_code); set_SSM2_page_code(cmd, SM2_pc_dropout); set_SSM2_pay_len(cmd, outLen); memset(out,0,outLen); switch(s->dropout_color[SIDE_FRONT]){ case COLOR_RED: set_SSM2_DO_do(out,SSM_DO_red); break; case COLOR_GREEN: set_SSM2_DO_do(out,SSM_DO_green); break; case COLOR_BLUE: set_SSM2_DO_do(out,SSM_DO_blue); break; case COLOR_EN_RED: set_SSM2_DO_en(out,SSM_DO_red); break; case COLOR_EN_GREEN: set_SSM2_DO_en(out,SSM_DO_green); break; case COLOR_EN_BLUE: set_SSM2_DO_en(out,SSM_DO_blue); break; } ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } else{ DBG (10, "ssm_do: unsupported\n"); } DBG (10, "ssm_do: finish\n"); return ret; } static SANE_Status read_sensors(struct scanner *s,SANE_Int option) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char in[R_SENSORS_len]; size_t inLen = R_SENSORS_len; DBG (10, "read_sensors: start %d\n", option); if(!s->can_read_sensors){ DBG (10, "read_sensors: unsupported, finishing\n"); return ret; } /* only run this if frontend has already read the last time we got it */ /* or if we don't care for such bookkeeping (private use) */ if (!option || !s->sensors_read[option-OPT_ADF_LOADED]) { DBG (15, "read_sensors: running\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, SR_datatype_sensors); set_R_xfer_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { /*set flags indicating there is data to read*/ memset(s->sensors_read,1,sizeof(s->sensors_read)); s->sensor_adf_loaded = get_R_SENSORS_adf(in); s->sensor_card_loaded = get_R_SENSORS_card(in); ret = SANE_STATUS_GOOD; } } if(option) s->sensors_read[option-OPT_ADF_LOADED] = 0; DBG (10, "read_sensors: finish\n"); return ret; } static SANE_Status read_panel(struct scanner *s,SANE_Int option) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char in[R_PANEL_len]; size_t inLen = R_PANEL_len; DBG (10, "read_panel: start %d\n", option); if(!s->can_read_panel){ DBG (10, "read_panel: unsupported, finishing\n"); return ret; } /* only run this if frontend has already read the last time we got it */ /* or if we don't care for such bookkeeping (private use) */ if (!option || !s->panel_read[option-OPT_START]) { DBG (15, "read_panel: running\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, SR_datatype_panel); set_R_xfer_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { /*set flags indicating there is data to read*/ memset(s->panel_read,1,sizeof(s->panel_read)); s->panel_start = get_R_PANEL_start(in); s->panel_stop = get_R_PANEL_stop(in); s->panel_butt3 = get_R_PANEL_butt3(in); s->panel_new_file = get_R_PANEL_new_file(in); s->panel_count_only = get_R_PANEL_count_only(in); s->panel_bypass_mode = get_R_PANEL_bypass_mode(in); s->panel_enable_led = get_R_PANEL_enable_led(in); s->panel_counter = get_R_PANEL_counter(in); ret = SANE_STATUS_GOOD; } } if(option) s->panel_read[option-OPT_START] = 0; DBG (10, "read_panel: finish %d\n",s->panel_counter); return ret; } static SANE_Status send_panel(struct scanner *s) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[SEND_len]; size_t cmdLen = SEND_len; unsigned char out[S_PANEL_len]; size_t outLen = S_PANEL_len; DBG (10, "send_panel: start\n"); if(!s->can_write_panel){ DBG (10, "send_panel: unsupported, finishing\n"); return ret; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SEND_code); set_S_xfer_datatype (cmd, SR_datatype_panel); set_S_xfer_length (cmd, outLen); memset(out,0,outLen); set_S_PANEL_enable_led(out,s->panel_enable_led); set_S_PANEL_counter(out,s->panel_counter); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); if (ret == SANE_STATUS_EOF) { ret = SANE_STATUS_GOOD; } DBG (10, "send_panel: finish %d\n", ret); return ret; } /* * @@ Section 4 - SANE scanning functions */ /* * Called by SANE to retrieve information about the type of data * that the current scan will return. * * From the SANE spec: * This function is used to obtain the current scan parameters. The * returned parameters are guaranteed to be accurate between the time * a scan has been started (sane_start() has been called) and the * completion of that request. Outside of that window, the returned * values are best-effort estimates of what the parameters will be * when sane_start() gets invoked. * * Calling this function before a scan has actually started allows, * for example, to get an estimate of how big the scanned image will * be. The parameters passed to this function are the handle h of the * device for which the parameters should be obtained and a pointer p * to a parameter structure. */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { SANE_Status ret = SANE_STATUS_GOOD; struct scanner *s = (struct scanner *) handle; DBG (10, "sane_get_parameters: start\n"); if(!s->started){ ret = update_params(s,0); if(ret){ DBG (5, "sane_get_parameters: up error, returning %d\n", ret); return ret; } } /* this backend only sends single frame images */ params->last_frame = 1; params->format = s->i.format; params->lines = s->i.height; params->depth = s->i.bpp; if(params->depth == 24) params->depth = 8; params->pixels_per_line = s->i.width; params->bytes_per_line = s->i.Bpl; DBG(15,"sane_get_parameters: x: max=%d, page=%d, gpw=%d, res=%d\n", s->valid_x, s->i.page_x, get_page_width(s), s->i.dpi_x); DBG(15,"sane_get_parameters: y: max=%d, page=%d, gph=%d, res=%d\n", s->max_y, s->i.page_y, get_page_height(s), s->i.dpi_y); DBG(15,"sane_get_parameters: area: tlx=%d, brx=%d, tly=%d, bry=%d\n", s->i.tl_x, s->i.br_x, s->i.tl_y, s->i.br_y); DBG (15, "sane_get_parameters: params: ppl=%d, Bpl=%d, lines=%d\n", params->pixels_per_line, params->bytes_per_line, params->lines); DBG (15, "sane_get_parameters: params: format=%d, depth=%d, last=%d\n", params->format, params->depth, params->last_frame); DBG (10, "sane_get_parameters: finish\n"); return ret; } SANE_Status update_params(struct scanner *s, int calib) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "update_params: start\n"); s->u.width = (s->u.br_x - s->u.tl_x) * s->u.dpi_x / 1200; s->u.height = (s->u.br_y - s->u.tl_y) * s->u.dpi_y / 1200; if (s->u.mode == MODE_COLOR) { s->u.format = SANE_FRAME_RGB; s->u.bpp = 24; } else if (s->u.mode == MODE_GRAYSCALE) { s->u.format = SANE_FRAME_GRAY; s->u.bpp = 8; } else { s->u.format = SANE_FRAME_GRAY; s->u.bpp = 1; /* round down to byte boundary */ s->u.width -= s->u.width % 8; } /* round down to pixel boundary for some scanners */ s->u.width -= s->u.width % s->ppl_mod; /* jpeg requires 8x8 squares */ if(s->compress == COMP_JPEG && s->u.mode >= MODE_GRAYSCALE){ s->u.format = SANE_FRAME_JPEG; s->u.width -= s->u.width % 8; s->u.height -= s->u.height % 8; } s->u.Bpl = s->u.width * s->u.bpp / 8; s->u.valid_Bpl = s->u.Bpl; s->u.valid_width = s->u.width; DBG (15, "update_params: user params: w:%d h:%d m:%d f:%d b:%d\n", s->u.width, s->u.height, s->u.mode, s->u.format, s->u.bpp); DBG (15, "update_params: user params: B:%d vB:%d vw:%d\n", s->u.Bpl, s->u.valid_Bpl, s->u.valid_width); DBG (15, "update_params: user params: x b:%d t:%d d:%d y b:%d t:%d d:%d\n", s->u.br_x, s->u.tl_x, s->u.dpi_x, s->u.br_y, s->u.tl_y, s->u.dpi_y); /* some scanners are limited in their valid scan params * make a second version of the params struct, but * override the user's values with what the scanner can actually do */ memcpy(&s->s,&s->u,sizeof(struct img_params)); /*********** missing modes (move up to valid one) **************/ if(s->s.mode == MODE_LINEART && !s->can_monochrome){ s->s.mode = MODE_GRAYSCALE; s->s.format = SANE_FRAME_GRAY; s->s.bpp = 8; } if(s->s.mode == MODE_GRAYSCALE && !s->can_grayscale){ s->s.mode = MODE_COLOR; s->s.format = SANE_FRAME_RGB; s->s.bpp = 24; } if(s->s.mode == MODE_COLOR && !s->can_color){ DBG (5, "update_params: no valid mode\n"); return SANE_STATUS_INVAL; } /********** missing resolutions (move up to valid one) *********/ if(!s->step_x_res){ int i; for(i=0;is.dpi_x > dpi_list[i] || !s->std_res_x[i]) continue; /* same & valid res, done */ if(s->s.dpi_x == dpi_list[i]) break; /* different & valid res, switch */ s->s.dpi_x = dpi_list[i]; break; } if(i > DPI_1200){ DBG (5, "update_params: no dpi\n"); return SANE_STATUS_INVAL; } } /*********** weird scan area (increase to valid one) *********/ if(s->fixed_width){ s->s.tl_x = 0; s->s.br_x = s->max_x; s->s.page_x = s->max_x; } /*recalculate new params*/ s->s.width = (s->s.br_x - s->s.tl_x) * s->s.dpi_x / 1200; /* round down to byte boundary */ if(s->s.mode < MODE_GRAYSCALE){ s->s.width -= s->s.width % 8; } /* round down to pixel boundary for some scanners */ s->s.width -= s->s.width % s->ppl_mod; s->s.valid_width = s->s.width; s->s.valid_Bpl = s->s.valid_width * s->s.bpp / 8; /* some machines (DR-2050) require even bytes per scanline */ /* increase width and Bpl, but not valid_width and valid_Bpl */ if(s->even_Bpl && (s->s.width % 2)){ s->s.width++; } s->s.Bpl = s->s.width * s->s.bpp / 8; /* figure out how many valid bytes per line (2510 is padded) */ if(s->color_interlace[SIDE_FRONT] == COLOR_INTERLACE_2510){ s->s.valid_Bpl = s->s.Bpl*11/12; s->s.valid_width = s->s.width*11/12; } /* some scanners need longer scans because front/back is offset */ if((s->u.source == SOURCE_ADF_DUPLEX || s->u.source == SOURCE_CARD_DUPLEX) && s->duplex_offset && !calib) s->s.height = (s->u.br_y-s->u.tl_y+s->duplex_offset) * s->u.dpi_y / 1200; /* round lines up to even number */ s->s.height += s->s.height % 2; DBG (15, "update_params: scan params: w:%d h:%d m:%d f:%d b:%d\n", s->s.width, s->s.height, s->s.mode, s->s.format, s->s.bpp); DBG (15, "update_params: scan params: B:%d vB:%d vw:%d\n", s->s.Bpl, s->s.valid_Bpl, s->s.valid_width); DBG (15, "update_params: scan params: x b:%d t:%d d:%d y b:%d t:%d d:%d\n", s->s.br_x, s->s.tl_x, s->s.dpi_x, s->s.br_y, s->s.tl_y, s->s.dpi_y); /* make a third (intermediate) version of the params struct, * currently identical to the user's params. this is what * we actually will send back to the user (though buffer_xxx * functions might change these values after this runs) */ /* calibration code needs the data just as it comes from the scanner */ if(calib) memcpy(&s->i,&s->s,sizeof(struct img_params)); /* normal scans need the data cleaned for presentation to the user */ else{ memcpy(&s->i,&s->u,sizeof(struct img_params)); /*dumb scanners pad the top of front page in duplex*/ if(s->i.source == SOURCE_ADF_DUPLEX || s->i.source == SOURCE_CARD_DUPLEX) s->i.skip_lines[s->duplex_offset_side] = s->duplex_offset * s->i.dpi_y / 1200; } DBG (15, "update_params: i params: w:%d h:%d m:%d f:%d b:%d\n", s->i.width, s->i.height, s->i.mode, s->i.format, s->i.bpp); DBG (15, "update_params: i params: B:%d vB:%d vw:%d\n", s->i.Bpl, s->i.valid_Bpl, s->i.valid_width); DBG (15, "update_params: i params: x b:%d t:%d d:%d y b:%d t:%d d:%d\n", s->i.br_x, s->i.tl_x, s->i.dpi_x, s->i.br_y, s->i.tl_y, s->i.dpi_y); DBG (10, "update_params: finish\n"); return ret; } /* reset image size parameters after buffer_xxx functions changed them */ SANE_Status update_i_params(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "update_i_params: start\n"); s->i.width = s->u.width; s->i.Bpl = s->u.Bpl; DBG (10, "update_i_params: finish\n"); return ret; } /* * Called by SANE when a page acquisition operation is to be started. * commands: set window, object pos, and scan * * this will be called between sides of a duplex scan, * and at the start of each page of an adf batch. * hence, we spend alot of time playing with s->started, etc. */ SANE_Status sane_start (SANE_Handle handle) { struct scanner *s = handle; SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "sane_start: start\n"); DBG (15, "started=%d, side=%d, source=%d\n", s->started, s->side, s->u.source); /* undo any prior sane_cancel calls */ s->cancelled=0; /* protect this block from sane_cancel */ s->reading=1; /* not finished with current side, error */ if (s->started && !s->u.eof[s->side]) { DBG(5,"sane_start: previous transfer not finished?"); return SANE_STATUS_INVAL; } /* batch start? inititalize struct and scanner */ if(!s->started){ /* load side marker */ if(s->u.source == SOURCE_ADF_BACK || s->u.source == SOURCE_CARD_BACK){ s->side = SIDE_BACK; } else{ s->side = SIDE_FRONT; } /* eject paper leftover*/ if(object_position (s, SANE_FALSE)){ DBG (5, "sane_start: ERROR: cannot eject page\n"); } /* wait for scanner to finish eject */ ret = wait_scanner (s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot wait scanner\n"); goto errors; } /* load the brightness/contrast lut with linear slope for calibration */ ret = load_lut (s->lut, 8, 8, 0, 255, 0, 0); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot load lut\n"); goto errors; } /* AFE cal */ if((ret = calibrate_AFE(s))){ DBG (5, "sane_start: ERROR: cannot cal afe\n"); goto errors; } /* fine cal */ if((ret = calibrate_fine(s))){ DBG (5, "sane_start: ERROR: cannot cal fine\n"); goto errors; } if((ret = calibrate_fine_buffer(s))){ DBG (5, "sane_start: ERROR: cannot cal fine from buffer\n"); goto errors; } /* reset the page counter after calibration */ s->panel_counter = 0; s->prev_page = 0; if(send_panel(s)){ DBG (5, "sane_start: ERROR: cannot send panel\n"); } /* load our own private copy of scan params */ ret = update_params(s,0); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot update_params\n"); goto errors; } /* set window command */ ret = set_window(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot set window\n"); goto errors; } /* buffer/duplex/ald/fb/card command */ ret = ssm_buffer(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot ssm buffer\n"); goto errors; } /* dropout color command */ ret = ssm_do(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot ssm do\n"); goto errors; } /* double feed detection command */ ret = ssm_df(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot ssm df\n"); goto errors; } /* clean scan params for new scan */ ret = clean_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot clean_params\n"); goto errors; } /* make large buffers to hold the images */ ret = image_buffers(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot load buffers\n"); goto errors; } /* load the brightness/contrast lut with user choices */ ret = load_lut (s->lut, 8, 8, 0, 255, s->contrast, s->brightness); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot load lut\n"); goto errors; } /* card reader dislikes op? */ if(s->s.source < SOURCE_CARD_FRONT){ /* grab next page */ ret = object_position (s, SANE_TRUE); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot load page\n"); goto errors; } /* wait for scanner to finish load */ ret = wait_scanner (s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot wait scanner\n"); goto errors; } } /* start scanning */ ret = start_scan (s,0); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot start_scan\n"); goto errors; } s->started = 1; } /* stuff done for subsequent images */ else{ /* duplex needs to switch sides */ if(s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX){ s->side = !s->side; } /* reset the intermediate params */ ret = update_i_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot update_i_params\n"); goto errors; } /* set clean defaults with new sheet of paper */ /* dont reset the transfer vars on backside of duplex page */ /* otherwise buffered back page will be lost */ /* ingest paper with adf (no-op for fb) */ /* dont call object pos or scan on back side of duplex scan */ if(s->side == SIDE_FRONT || s->s.source == SOURCE_ADF_BACK || s->s.source == SOURCE_CARD_BACK){ /* clean scan params for new scan */ ret = clean_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot clean_params\n"); goto errors; } /* big scanners and small ones in non-buff mode: OP to detect paper */ if(s->always_op || !s->buffermode){ ret = object_position (s, SANE_TRUE); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot load page\n"); goto errors; } /* user wants unbuffered scans */ /* send scan command */ if(!s->buffermode){ ret = start_scan (s,0); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot start_scan\n"); goto errors; } } } /* small, buffering scanners check for more pages by reading counter */ else{ ret = read_panel (s, OPT_COUNTER); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot load page\n"); goto errors; } if(s->prev_page == s->panel_counter){ DBG (5, "sane_start: same counter (%d) no paper?\n",s->prev_page); ret = SANE_STATUS_NO_DOCS; goto errors; } DBG (5, "sane_start: diff counter (%d/%d)\n", s->prev_page,s->panel_counter); } } } /* reset jpeg params on each page */ s->jpeg_stage=JPEG_STAGE_NONE; s->jpeg_ff_offset=0; DBG (15, "started=%d, side=%d, source=%d\n", s->started, s->side, s->u.source); /* certain options require the entire image to * be collected from the scanner before we can * tell the user the size of the image. the sane * API has no way to inform the frontend of this, * so we block and buffer. yuck */ if(must_fully_buffer(s)){ /* get image */ while(!s->s.eof[s->side] && !ret){ SANE_Int len = 0; ret = sane_read((SANE_Handle)s, NULL, 0, &len); } /* check for errors */ if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot buffer image\n"); goto errors; } DBG (5, "sane_start: OK: done buffering\n"); /* finished buffering, adjust image as required */ if(s->swdeskew){ buffer_deskew(s,s->side); } if(s->swcrop){ buffer_crop(s,s->side); } if(s->swdespeck){ buffer_despeck(s,s->side); } if(s->swskip){ /* Skipping means throwing out this image. * Pretend the user read the whole thing * and call sane_start again. * This assumes we are running in batch mode. */ if(buffer_isblank(s,s->side)){ s->u.eof[s->side] = 1; return sane_start(handle); } } } ret = check_for_cancel(s); s->reading = 0; DBG (10, "sane_start: finish %d\n", ret); return ret; errors: DBG (10, "sane_start: error %d\n", ret); s->started = 0; s->cancelled = 0; s->reading = 0; return ret; } /* * cleans params for new scan */ static SANE_Status clean_params (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "clean_params: start\n"); s->u.eof[0]=0; s->u.eof[1]=0; s->u.bytes_sent[0]=0; s->u.bytes_sent[1]=0; s->u.bytes_tot[0]=0; s->u.bytes_tot[1]=0; s->i.eof[0]=0; s->i.eof[1]=0; s->i.bytes_sent[0]=0; s->i.bytes_sent[1]=0; s->i.bytes_tot[0]=0; s->i.bytes_tot[1]=0; s->s.eof[0]=0; s->s.eof[1]=0; s->s.bytes_sent[0]=0; s->s.bytes_sent[1]=0; s->s.bytes_tot[0]=0; s->s.bytes_tot[1]=0; /* store the number of front bytes */ if ( s->u.source != SOURCE_ADF_BACK && s->u.source != SOURCE_CARD_BACK ) s->u.bytes_tot[SIDE_FRONT] = s->u.Bpl * s->u.height; if ( s->i.source != SOURCE_ADF_BACK && s->i.source != SOURCE_CARD_BACK ) s->i.bytes_tot[SIDE_FRONT] = s->i.Bpl * s->i.height; if ( s->s.source != SOURCE_ADF_BACK && s->s.source != SOURCE_CARD_BACK ) s->s.bytes_tot[SIDE_FRONT] = s->s.Bpl * s->s.height; /* store the number of back bytes */ if ( s->u.source == SOURCE_ADF_DUPLEX || s->u.source == SOURCE_ADF_BACK || s->u.source == SOURCE_CARD_DUPLEX || s->u.source == SOURCE_CARD_BACK ) s->u.bytes_tot[SIDE_BACK] = s->u.Bpl * s->u.height; if ( s->i.source == SOURCE_ADF_DUPLEX || s->i.source == SOURCE_ADF_BACK || s->i.source == SOURCE_CARD_DUPLEX || s->i.source == SOURCE_CARD_BACK ) s->i.bytes_tot[SIDE_BACK] = s->i.Bpl * s->i.height; if ( s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_ADF_BACK || s->s.source == SOURCE_CARD_DUPLEX || s->s.source == SOURCE_CARD_BACK ) s->s.bytes_tot[SIDE_BACK] = s->s.Bpl * s->s.height; DBG (10, "clean_params: finish\n"); return ret; } /* * frees/callocs buffers to hold the scan data */ static SANE_Status image_buffers (struct scanner *s, int setup) { SANE_Status ret = SANE_STATUS_GOOD; int side; DBG (10, "image_buffers: start\n"); for(side=0;side<2;side++){ /* free current buffer */ if (s->buffers[side]) { DBG (15, "image_buffers: free buffer %d.\n",side); free(s->buffers[side]); s->buffers[side] = NULL; } /* build new buffer if asked */ if(s->i.bytes_tot[side] && setup){ s->buffers[side] = calloc (1,s->i.bytes_tot[side]); if (!s->buffers[side]) { DBG (5, "image_buffers: Error, no buffer %d.\n",side); return SANE_STATUS_NO_MEM; } } } DBG (10, "image_buffers: finish\n"); return ret; } /* * This routine issues a SCSI SET WINDOW command to the scanner, using the * values currently in the s->s param structure. */ static SANE_Status set_window (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; /* The command specifies the number of bytes in the data phase * the data phase has a header, followed by 1 window desc block * the header specifies the number of bytes in 1 window desc block */ unsigned char cmd[SET_WINDOW_len]; size_t cmdLen = SET_WINDOW_len; unsigned char out[SW_header_len + SW_desc_len]; size_t outLen = SW_header_len + SW_desc_len; unsigned char * header = out; /*header*/ unsigned char * desc1 = out + SW_header_len; /*descriptor*/ DBG (10, "set_window: start\n"); /*build the payload*/ memset(out,0,outLen); /* set window desc size in header */ set_WPDB_wdblen(header, SW_desc_len); /* init the window block */ if (s->s.source == SOURCE_ADF_BACK || s->s.source == SOURCE_CARD_BACK) { set_WD_wid (desc1, WD_wid_back); } else{ set_WD_wid (desc1, WD_wid_front); } set_WD_Xres (desc1, s->s.dpi_x); set_WD_Yres (desc1, s->s.dpi_y); /* some machines need max width */ if(s->fixed_width){ set_WD_ULX (desc1, 0); set_WD_width (desc1, s->max_x); } /* or they align left */ else if(s->u.source == SOURCE_FLATBED){ set_WD_ULX (desc1, s->s.tl_x); set_WD_width (desc1, s->s.width * 1200/s->s.dpi_x); } /* or we have to center the window ourselves */ else{ set_WD_ULX (desc1, (s->max_x - s->s.page_x) / 2 + s->s.tl_x); set_WD_width (desc1, s->s.width * 1200/s->s.dpi_x); } /* some models require that the tly value be inverted? */ if(s->invert_tly) set_WD_ULY (desc1, ~s->s.tl_y); else set_WD_ULY (desc1, s->s.tl_y); set_WD_length (desc1, s->s.height * 1200/s->s.dpi_y); if(s->has_btc){ /*convert our common -127 to +127 range into HW's range *FIXME: this code assumes hardware range of 0-255 */ set_WD_brightness (desc1, s->brightness+128); set_WD_threshold (desc1, s->threshold); /*convert our common -127 to +127 range into HW's range *FIXME: this code assumes hardware range of 0-255 */ set_WD_contrast (desc1, s->contrast+128); } set_WD_composition (desc1, s->s.mode); if(s->s.bpp == 24) set_WD_bitsperpixel (desc1, 8); else set_WD_bitsperpixel (desc1, s->s.bpp); if(s->s.mode == MODE_HALFTONE){ /*set_WD_ht_type(desc1, s->ht_type); set_WD_ht_pattern(desc1, s->ht_pattern);*/ } set_WD_rif (desc1, s->rif); set_WD_rgb(desc1, s->rgb_format); set_WD_padding(desc1, s->padding); /*FIXME: what is this? */ set_WD_reserved2(desc1, s->unknown_byte2); set_WD_compress_type(desc1, COMP_NONE); set_WD_compress_arg(desc1, 0); /* some scanners support jpeg image compression, for color/gs only */ if(s->s.format == SANE_FRAME_JPEG){ set_WD_compress_type(desc1, COMP_JPEG); set_WD_compress_arg(desc1, s->compress_arg); } /*build the command*/ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_WINDOW_code); set_SW_xferlen(cmd, outLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); if (!ret && (s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX)) { set_WD_wid (desc1, WD_wid_back); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } DBG (10, "set_window: finish\n"); return ret; } /* * Issues the SCSI OBJECT POSITION command if an ADF is in use. */ static SANE_Status object_position (struct scanner *s, int i_load) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[OBJECT_POSITION_len]; size_t cmdLen = OBJECT_POSITION_len; DBG (10, "object_position: start\n"); if (s->u.source == SOURCE_FLATBED) { DBG (10, "object_position: flatbed no-op\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, OBJECT_POSITION_code); if (i_load) { DBG (15, "object_position: load\n"); set_OP_autofeed (cmd, OP_Feed); } else { DBG (15, "object_position: eject\n"); set_OP_autofeed (cmd, OP_Discharge); } ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, NULL, NULL ); if (ret != SANE_STATUS_GOOD) return ret; DBG (10, "object_position: finish\n"); return ret; } /* * Issues SCAN command. * * (This doesn't actually read anything, it just tells the scanner * to start scanning.) */ static SANE_Status start_scan (struct scanner *s, int type) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[SCAN_len]; size_t cmdLen = SCAN_len; unsigned char out[] = {WD_wid_front, WD_wid_back}; size_t outLen = 2; DBG (10, "start_scan: start\n"); /* calibration scans use 0xff or 0xfe */ if(type){ out[0] = type; out[1] = type; } if (s->s.source != SOURCE_ADF_DUPLEX && s->s.source != SOURCE_CARD_DUPLEX) { outLen--; if(s->s.source == SOURCE_ADF_BACK || s->s.source == SOURCE_CARD_BACK) { out[0] = WD_wid_back; } } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SCAN_code); set_SC_xfer_length (cmd, outLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "start_scan: finish\n"); return ret; } /* * Called by SANE to read data. * * From the SANE spec: * This function is used to read image data from the device * represented by handle h. Argument buf is a pointer to a memory * area that is at least maxlen bytes long. The number of bytes * returned is stored in *len. A backend must set this to zero when * the call fails (i.e., when a status other than SANE_STATUS_GOOD is * returned). * * When the call succeeds, the number of bytes returned can be * anywhere in the range from 0 to maxlen bytes. */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct scanner *s = (struct scanner *) handle; SANE_Status ret=SANE_STATUS_GOOD; DBG (10, "sane_read: start\n"); *len=0; /* maybe cancelled? */ if(!s->started){ DBG (5, "sane_read: not started, call sane_start\n"); return SANE_STATUS_CANCELLED; } /* sane_start required between sides */ if(s->u.bytes_sent[s->side] == s->i.bytes_tot[s->side]){ s->u.eof[s->side] = 1; DBG (15, "sane_read: returning eof\n"); return SANE_STATUS_EOF; } s->reading = 1; /* double width pnm interlacing */ if((s->s.source == SOURCE_ADF_DUPLEX || s->s.source == SOURCE_CARD_DUPLEX) && s->s.format <= SANE_FRAME_RGB && s->duplex_interlace != DUPLEX_INTERLACE_NONE ){ /* buffer both sides */ if(!s->s.eof[SIDE_FRONT] || !s->s.eof[SIDE_BACK]){ ret = read_from_scanner_duplex(s, 0); if(ret){ DBG(5,"sane_read: front returning %d\n",ret); goto errors; } /*read last block, update counter*/ if(s->s.eof[SIDE_FRONT] && s->s.eof[SIDE_BACK]){ s->prev_page++; DBG(15,"sane_read: duplex counter %d\n",s->prev_page); } } } /* simplex or non-alternating duplex */ else{ if(!s->s.eof[s->side]){ ret = read_from_scanner(s, s->side, 0); if(ret){ DBG(5,"sane_read: side %d returning %d\n",s->side,ret); goto errors; } /*read last block, update counter*/ if(s->s.eof[s->side]){ s->prev_page++; DBG(15,"sane_read: side %d counter %d\n",s->side,s->prev_page); } } } /* copy a block from buffer to frontend */ ret = read_from_buffer(s,buf,max_len,len,s->side); if(ret) goto errors; ret = check_for_cancel(s); s->reading = 0; DBG (10, "sane_read: finish %d\n", ret); return ret; errors: DBG (10, "sane_read: error %d\n", ret); s->reading = 0; s->cancelled = 0; s->started = 0; return ret; } static SANE_Status read_from_scanner(struct scanner *s, int side, int exact) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char * in; size_t inLen = 0; size_t bytes = s->buffer_size; size_t remain = s->s.bytes_tot[side] - s->s.bytes_sent[side]; DBG (10, "read_from_scanner: start\n"); /* all requests must end on line boundary */ bytes -= (bytes % s->s.Bpl); /* some larger scanners require even bytes per block */ if(bytes % 2){ bytes -= s->s.Bpl; } /* usually (image) we want to read too much data, and get RS */ /* sometimes (calib) we want to do an exact read */ if(exact && bytes > remain){ bytes = remain; } DBG(15, "read_from_scanner: si:%d to:%d rx:%d re:%lu bu:%d pa:%lu ex:%d\n", side, s->s.bytes_tot[side], s->s.bytes_sent[side], (unsigned long)remain, s->buffer_size, (unsigned long)bytes, exact); inLen = bytes; in = malloc(inLen); if(!in){ DBG(5, "read_from_scanner: not enough mem for buffer: %d\n",(int)inLen); return SANE_STATUS_NO_MEM; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, SR_datatype_image); set_R_xfer_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD) { DBG(15, "read_from_scanner: got GOOD, returning GOOD %lu\n", (unsigned long)inLen); } else if (ret == SANE_STATUS_EOF) { DBG(15, "read_from_scanner: got EOF, finishing %lu\n", (unsigned long)inLen); } else if (ret == SANE_STATUS_DEVICE_BUSY) { DBG(5, "read_from_scanner: got BUSY, returning GOOD\n"); inLen = 0; ret = SANE_STATUS_GOOD; } else { DBG(5, "read_from_scanner: error reading data block status = %d\n",ret); inLen = 0; } /* this is jpeg data, we need to fix the missing image size */ if(s->s.format == SANE_FRAME_JPEG){ /* look for the SOF header near the beginning */ if(s->jpeg_stage == JPEG_STAGE_NONE || s->jpeg_ff_offset < 0x0d){ size_t i; for(i=0;ijpeg_stage == JPEG_STAGE_NONE && in[i] == 0xff){ s->jpeg_ff_offset=0; continue; } s->jpeg_ff_offset++; /* last byte was an ff, this byte is SOF */ if(s->jpeg_ff_offset == 1 && in[i] == 0xc0){ s->jpeg_stage = JPEG_STAGE_SOF; continue; } if(s->jpeg_stage == JPEG_STAGE_SOF){ /* lines in start of frame, overwrite it */ if(s->jpeg_ff_offset == 5){ in[i] = (s->s.height >> 8) & 0xff; continue; } if(s->jpeg_ff_offset == 6){ in[i] = s->s.height & 0xff; continue; } /* width in start of frame, overwrite it */ if(s->jpeg_ff_offset == 7){ in[i] = (s->s.width >> 8) & 0xff; continue; } if(s->jpeg_ff_offset == 8){ in[i] = s->s.width & 0xff; continue; } } } } } /*scanner may have sent more data than we asked for, chop it*/ if(inLen > remain){ inLen = remain; } /* we've got some data, descramble and store it */ if(inLen){ copy_simplex(s,in,inLen,side); } free(in); /* we've read all data, but not eof. clear and pretend */ if(exact && inLen == remain){ DBG (10, "read_from_scanner: exact read, clearing\n"); ret = object_position (s,SANE_FALSE); if(ret){ return ret; } ret = SANE_STATUS_EOF; } if(ret == SANE_STATUS_EOF){ /* this is jpeg data, we need to change the total size */ if(s->s.format == SANE_FRAME_JPEG){ s->s.bytes_tot[side] = s->s.bytes_sent[side]; s->i.bytes_tot[side] = s->i.bytes_sent[side]; s->u.bytes_tot[side] = s->i.bytes_sent[side]; } /* this is non-jpeg data, fill remainder, change rx'd size */ else{ fill_image(s,side); } s->i.eof[side] = 1; s->s.eof[side] = 1; ret = SANE_STATUS_GOOD; } DBG(15, "read_from_scanner: sto:%d srx:%d sef:%d uto:%d urx:%d uef:%d\n", s->s.bytes_tot[side], s->s.bytes_sent[side], s->s.eof[side], s->u.bytes_tot[side], s->u.bytes_sent[side], s->u.eof[side]); DBG (10, "read_from_scanner: finish\n"); return ret; } /* cheaper scanners interlace duplex scans on a byte basis * this code requests double width lines from scanner */ static SANE_Status read_from_scanner_duplex(struct scanner *s,int exact) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char * in; size_t inLen = 0; size_t bytes = s->buffer_size; size_t remain = s->s.bytes_tot[SIDE_FRONT] + s->s.bytes_tot[SIDE_BACK] - s->s.bytes_sent[SIDE_FRONT] - s->s.bytes_sent[SIDE_BACK]; DBG (10, "read_from_scanner_duplex: start\n"); /* all requests must end on WIDE line boundary */ bytes -= (bytes % (s->s.Bpl*2)); /* usually (image) we want to read too much data, and get RS */ /* sometimes (calib) we want to do an exact read */ if(exact && bytes > remain){ bytes = remain; } DBG(15, "read_from_scanner_duplex: re:%lu bu:%d pa:%lu ex:%d\n", (unsigned long)remain, s->buffer_size, (unsigned long)bytes, exact); inLen = bytes; in = malloc(inLen); if(!in){ DBG(5, "read_from_scanner_duplex: not enough mem for buffer: %d\n", (int)inLen); return SANE_STATUS_NO_MEM; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, SR_datatype_image); set_R_xfer_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD) { DBG(15, "read_from_scanner_duplex: got GOOD, returning GOOD %lu\n", (unsigned long)inLen); } else if (ret == SANE_STATUS_EOF) { DBG(15, "read_from_scanner_duplex: got EOF, finishing %lu\n", (unsigned long)inLen); } else if (ret == SANE_STATUS_DEVICE_BUSY) { DBG(5, "read_from_scanner_duplex: got BUSY, returning GOOD\n"); inLen = 0; ret = SANE_STATUS_GOOD; } else { DBG(5, "read_from_scanner_duplex: error reading data block status = %d\n", ret); inLen = 0; } /*scanner may have sent more data than we asked for, chop it*/ if(inLen > remain){ inLen = remain; } /* we've got some data, descramble and store it */ if(inLen){ copy_duplex(s,in,inLen); } free(in); /* we've read all data, but not eof. clear and pretend */ if(exact && inLen == remain){ DBG (10, "read_from_scanner_duplex: exact read, clearing\n"); ret = object_position (s,SANE_FALSE); if(ret){ return ret; } ret = SANE_STATUS_EOF; } if(ret == SANE_STATUS_EOF){ /* this is jpeg data, we need to change the total size */ if(s->s.format == SANE_FRAME_JPEG){ s->s.bytes_tot[SIDE_FRONT] = s->s.bytes_sent[SIDE_FRONT]; s->s.bytes_tot[SIDE_BACK] = s->s.bytes_sent[SIDE_BACK]; s->i.bytes_tot[SIDE_FRONT] = s->i.bytes_sent[SIDE_FRONT]; s->i.bytes_tot[SIDE_BACK] = s->i.bytes_sent[SIDE_BACK]; s->u.bytes_tot[SIDE_FRONT] = s->i.bytes_sent[SIDE_FRONT]; s->u.bytes_tot[SIDE_BACK] = s->i.bytes_sent[SIDE_BACK]; } /* this is non-jpeg data, fill remainder, change rx'd size */ else{ fill_image(s,SIDE_FRONT); fill_image(s,SIDE_BACK); } s->i.eof[SIDE_FRONT] = 1; s->i.eof[SIDE_BACK] = 1; s->s.eof[SIDE_FRONT] = 1; s->s.eof[SIDE_BACK] = 1; ret = SANE_STATUS_GOOD; } DBG (10, "read_from_scanner_duplex: finish\n"); return ret; } /* these functions copy image data from input buffer to scanner struct * descrambling it, and putting it in the right side buffer */ /* NOTE: they assume buffer is scanline aligned */ static SANE_Status copy_simplex(struct scanner *s, unsigned char * buf, int len, int side) { SANE_Status ret=SANE_STATUS_GOOD; int i, j; int bwidth = s->s.Bpl; int pwidth = s->s.width; int t = bwidth/3; int f = bwidth/4; int tw = bwidth/12; unsigned char * line = NULL; int line_next = 0; int inter = get_color_inter(s,side,s->s.dpi_x); /* jpeg data should not pass thru this function, so copy and bail out */ if(s->s.format > SANE_FRAME_RGB){ DBG (15, "copy_simplex: jpeg bulk copy\n"); memcpy(s->buffers[side]+s->i.bytes_sent[side], buf, len); s->i.bytes_sent[side] += len; s->s.bytes_sent[side] += len; return ret; } DBG (15, "copy_simplex: per-line copy\n"); line = malloc(bwidth); if(!line) return SANE_STATUS_NO_MEM; /* ingest each line */ for(i=0; is.bytes_sent[side] / bwidth; /*increment number of bytes rx'd from scanner*/ s->s.bytes_sent[side] += bwidth; /*have some padding from scanner to drop*/ if ( lineNum < s->i.skip_lines[side] || lineNum - s->i.skip_lines[side] >= s->i.height ){ continue; } line_next = 0; if(s->s.format == SANE_FRAME_GRAY){ switch (s->gray_interlace[side]) { /* one line has the following format: ggg...GGG * where the 'capital' letters are the beginning of the line */ case GRAY_INTERLACE_gG: DBG (17, "copy_simplex: gray, gG\n"); for (j=bwidth-1; j>=0; j--){ line[line_next++] = buf[i+j]; } break; case GRAY_INTERLACE_2510: DBG (17, "copy_simplex: gray, 2510\n"); /* first read head (third byte of every three) */ for(j=bwidth-1;j>=0;j-=3){ line[line_next++] = buf[i+j]; } /* second read head (first byte of every three) */ for(j=bwidth*3/4-3;j>=0;j-=3){ line[line_next++] = buf[i+j]; } /* third read head (second byte of every three) */ for(j=bwidth-2;j>=0;j-=3){ line[line_next++] = buf[i+j]; } /* padding */ for(j=0;js.format == SANE_FRAME_RGB){ switch (inter) { /* scanner returns color data as bgrbgr... */ case COLOR_INTERLACE_BGR: DBG (17, "copy_simplex: color, BGR\n"); for (j=0; j=0; j--){ line[line_next++] = buf[i+j]; line[line_next++] = buf[i+pwidth+j]; line[line_next++] = buf[i+2*pwidth+j]; } break; case COLOR_INTERLACE_2510: DBG (17, "copy_simplex: color, 2510\n"); /* first read head (third byte of every three) */ for(j=t-1;j>=0;j-=3){ line[line_next++] = buf[i+j]; line[line_next++] = buf[i+t+j]; line[line_next++] = buf[i+2*t+j]; } /* second read head (first byte of every three) */ for(j=f-3;j>=0;j-=3){ line[line_next++] = buf[i+j]; line[line_next++] = buf[i+t+j]; line[line_next++] = buf[i+2*t+j]; } /* third read head (second byte of every three) */ for(j=t-2;j>=0;j-=3){ line[line_next++] = buf[i+j]; line[line_next++] = buf[i+t+j]; line[line_next++] = buf[i+2*t+j]; } /* padding */ for(j=0;jreverse_by_mode[s->s.mode]){ for(j=0; jf_offset[side]){ DBG (17, "copy_simplex: apply offset\n"); for(j=0; js.valid_Bpl; j++){ int curr = line[j] - s->f_offset[side][j]; if(curr < 0) curr = 0; line[j] = curr; } } if(s->f_gain[side]){ DBG (17, "copy_simplex: apply gain\n"); for(j=0; js.valid_Bpl; j++){ int curr = line[j] * 240/s->f_gain[side][j]; if(curr > 255) curr = 255; line[j] = curr; } } /* apply brightness and contrast if hardware cannot do it */ if(s->sw_lut && (s->s.mode == MODE_COLOR || s->s.mode == MODE_GRAYSCALE)){ DBG (17, "copy_simplex: apply brightness/contrast\n"); for(j=0; js.valid_Bpl; j++){ line[j] = s->lut[line[j]]; } } /*copy the line into the buffer*/ ret = copy_line(s,line,side); if(ret){ break; } } free(line); DBG (10, "copy_simplex: finished\n"); return ret; } /* split the data between two buffers, hand them to copy_simplex() * assumes that the buffer aligns to a double-wide line boundary */ static SANE_Status copy_duplex(struct scanner *s, unsigned char * buf, int len) { SANE_Status ret=SANE_STATUS_GOOD; int i,j; int bwidth = s->s.Bpl; int dbwidth = 2*bwidth; unsigned char * front; unsigned char * back; int flen=0, blen=0; DBG (10, "copy_duplex: start\n"); /*split the input into two simplex output buffers*/ front = calloc(1,len/2); if(!front){ DBG (5, "copy_duplex: no front mem\n"); return SANE_STATUS_NO_MEM; } back = calloc(1,len/2); if(!back){ DBG (5, "copy_duplex: no back mem\n"); free(front); return SANE_STATUS_NO_MEM; } if(s->duplex_interlace == DUPLEX_INTERLACE_2510){ DBG (10, "copy_duplex: 2510\n"); for(i=0; i 1st byte */ /* 3rd head: 4th byte -> 2nd byte */ /* 1st head: 5th byte -> 3rd byte */ front[flen++] = buf[i+j+2]; front[flen++] = buf[i+j+4]; front[flen++] = buf[i+j+5]; /* back */ /* 2nd head: 3rd byte -> 1st byte */ /* 3rd head: 0th byte -> 2nd byte */ /* 1st head: 1st byte -> 3rd byte */ back[blen++] = buf[i+j+3]; back[blen++] = buf[i+j]; back[blen++] = buf[i+j+1]; } } } /* full line of front, then full line of back */ else if(s->duplex_interlace == DUPLEX_INTERLACE_FfBb || s->duplex_interlace == DUPLEX_INTERLACE_fFBb){ for(i=0; iduplex_interlace == DUPLEX_INTERLACE_FfBb){ memcpy(front+flen,buf+i,bwidth); }else{ rmemcpy(front+flen,buf+i,bwidth,3); // only 24bit color is supported } flen+=bwidth; memcpy(back+blen,buf+i+bwidth,bwidth); blen+=bwidth; } } /*just alternating bytes, FBfb*/ else { for(i=0; is.width; int sbwidth = s->s.Bpl; int ibwidth = s->i.Bpl; unsigned char * line; int offset = 0; int i, j; DBG (20, "copy_line: start\n"); /* the 'standard' case: non-stupid scan */ if(s->s.width == s->i.width && s->s.dpi_x == s->i.dpi_x && s->s.mode == s->i.mode ){ memcpy(s->buffers[side]+s->i.bytes_sent[side], buff, sbwidth); s->i.bytes_sent[side] += sbwidth; DBG (20, "copy_line: finished smart\n"); return ret; } /* the 'corner' case: stupid scan */ /*setup 24 bit color single line buffer*/ line = malloc(spwidth*3); if(!line) return SANE_STATUS_NO_MEM; /*load single line color buffer*/ switch (s->s.mode) { case MODE_COLOR: if(must_downsample(s) && s->dropout_color[side]){ switch(s->dropout_color[side]){ case COLOR_RED: for(i=0;i> 7) & 1) ?0:255; line[i*24+3] = line[i*24+4] = line[i*24+5] = ((curr >> 6) & 1) ?0:255; line[i*24+6] = line[i*24+7] = line[i*24+8] = ((curr >> 5) & 1) ?0:255; line[i*24+9] = line[i*24+10] = line[i*24+11] = ((curr >> 4) & 1) ?0:255; line[i*24+12] = line[i*24+13] = line[i*24+14] =((curr >> 3) & 1) ?0:255; line[i*24+15] = line[i*24+16] = line[i*24+17] =((curr >> 2) & 1) ?0:255; line[i*24+18] = line[i*24+19] = line[i*24+20] =((curr >> 1) & 1) ?0:255; line[i*24+21] = line[i*24+22] = line[i*24+23] =((curr >> 0) & 1) ?0:255; } break; } /* scan is higher res than user wanted, scale it */ /*FIXME: interpolate instead */ if(s->i.dpi_x != s->s.dpi_x){ for(i=0;is.dpi_x/s->i.dpi_x * 3; if(source+2 >= spwidth*3) break; line[i*3] = line[source]; line[i*3+1] = line[source+1]; line[i*3+2] = line[source+2]; } } /* scan is wider than user wanted, skip some pixels on left side */ if(s->i.width != s->s.width){ offset = ((s->valid_x-s->i.page_x) / 2 + s->i.tl_x) * s->i.dpi_x/1200; } /* change mode, store line in buffer */ switch (s->i.mode) { case MODE_COLOR: memcpy(s->buffers[side]+s->i.bytes_sent[side], line+(offset*3), ibwidth); s->i.bytes_sent[side] += ibwidth; break; case MODE_GRAYSCALE: for(i=0;ibuffers[side][s->i.bytes_sent[side]++] = ((int)line[source] + line[source+1] + line[source+2])/3; } break; default: /*loop over output bytes*/ for(i=0;ithreshold*3; /*loop over output bits*/ for(j=0;j<8;j++){ int source = offset*3 + i*24 + j*3; if( (line[source] + line[source+1] + line[source+2]) < thresh ){ curr |= 1 << (7-j); } } s->buffers[side][s->i.bytes_sent[side]++] = curr; } break; } free(line); DBG (20, "copy_line: finish stupid\n"); return ret; } static SANE_Status read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side) { SANE_Status ret=SANE_STATUS_GOOD; int bytes = max_len; int remain = s->i.bytes_sent[side] - s->u.bytes_sent[side]; DBG (10, "read_from_buffer: start\n"); /* figure out the max amount to transfer */ if(bytes > remain) bytes = remain; *len = bytes; /*FIXME this needs to timeout eventually */ if(!bytes){ DBG(5,"read_from_buffer: nothing to do\n"); return SANE_STATUS_GOOD; } DBG(15, "read_from_buffer: si:%d to:%d tx:%d bu:%d pa:%d\n", side, s->i.bytes_tot[side], s->u.bytes_sent[side], max_len, bytes); /* copy to caller */ memcpy(buf,s->buffers[side]+s->u.bytes_sent[side],bytes); s->u.bytes_sent[side] += bytes; DBG (10, "read_from_buffer: finished\n"); return ret; } /* fill remainder of buffer with background if scanner stops early */ static SANE_Status fill_image(struct scanner *s,int side) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char bg_color = calc_bg_color(s); int fill_bytes = s->i.bytes_tot[side]-s->i.bytes_sent[side]; if(!fill_bytes){ return ret; } DBG (15, "fill_image: side:%d bytes:%d bg_color:%02x\n", side, fill_bytes, bg_color); /* fill the rest with bg_color */ memset(s->buffers[side]+s->i.bytes_sent[side],bg_color,fill_bytes); /* pretend we got all the data from scanner */ s->i.bytes_sent[side] = s->i.bytes_tot[side]; s->s.bytes_sent[side] = s->s.bytes_tot[side]; return ret; } /* return the bg color based on scanner settings */ static unsigned char calc_bg_color(struct scanner *s) { unsigned char bg_color = s->lut[s->bg_color]; if(s->u.mode <= MODE_HALFTONE) bg_color = (bg_colorthreshold)?0xff:0x00; return bg_color; } /* * @@ Section 5 - calibration functions */ #if 0 static SANE_Status foo_AFE(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[] = { 0x3b, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }; size_t cmdLen = 12; unsigned char in[4]; size_t inLen = 4; DBG (10, "foo_AFE: start\n"); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret != SANE_STATUS_GOOD) return ret; DBG (10, "foo_AFE: finish\n"); return ret; } #endif /* * makes several scans, adjusts coarse calibration */ static SANE_Status calibrate_AFE (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int i, j, k; int min, max; int lines = 8; /*buffer these for later*/ int old_tl_y = s->u.tl_y; int old_br_y = s->u.br_y; int old_mode = s->u.mode; int old_source = s->u.source; DBG (10, "calibrate_AFE: start\n"); if(!s->need_ccal){ DBG (10, "calibrate_AFE: not required\n"); return ret; } /* always cal with a short scan in duplex color */ s->u.tl_y = 0; s->u.br_y = lines * 1200 / s->u.dpi_y; s->u.mode = MODE_COLOR; s->u.source = SOURCE_ADF_DUPLEX; /* load our own private copy of scan params */ ret = update_params(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot update_params\n"); goto cleanup; } if(s->c_res == s->s.dpi_x && s->c_mode == s->s.mode){ DBG (10, "calibrate_AFE: already done\n"); goto cleanup; } /* clean scan params for new scan */ ret = clean_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot clean_params\n"); goto cleanup; } /* make buffers to hold the images */ ret = image_buffers(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot load buffers\n"); goto cleanup; } /*blast the existing fine cal data so reading code wont apply it*/ ret = offset_buffers(s,0); ret = gain_buffers(s,0); /* need to tell it we want duplex */ ret = ssm_buffer(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot ssm buffer\n"); goto cleanup; } /* set window command */ ret = set_window(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot set window\n"); goto cleanup; } /* first pass (black offset), lamp off, no offset/gain/exposure */ DBG (15, "calibrate_AFE: offset\n"); /* blast all the existing coarse cal data */ for(i=0;i<2;i++){ s->c_gain[i] = 1; s->c_offset[i] = 1; for(j=0;j<3;j++){ s->c_exposure[i][j] = 0; } } ret = write_AFE(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot write afe\n"); goto cleanup; } ret = calibration_scan(s,0xff); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot make offset cal scan\n"); goto cleanup; } for(i=0;i<2;i++){ min = 255; for(j=0; js.valid_Bpl; j++){ if(s->buffers[i][j] < min) min = s->buffers[i][j]; } s->c_offset[i] = min*3-2; DBG (15, "calibrate_AFE: offset %d %d %02x\n", i, min, s->c_offset[i]); } /*handle second pass (per channel exposure), lamp on, overexposed*/ DBG (15, "calibrate_AFE: exposure\n"); for(i=0;i<2;i++){ for(j=0; j<3; j++){ s->c_exposure[i][j] = 0x320; } } ret = write_AFE(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot write afe\n"); goto cleanup; } ret = calibration_scan(s,0xfe); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot make exposure cal scan\n"); goto cleanup; } for(i=0;i<2;i++){ /*sides*/ for(j=0;j<3;j++){ /*channels*/ max = 0; for(k=j; ks.valid_Bpl; k+=3){ /*bytes*/ if(s->buffers[i][k] > max) max = s->buffers[i][k]; } /*generally we reduce the exposure (smaller number) */ if(old_mode == MODE_COLOR) s->c_exposure[i][j] = s->c_exposure[i][j] * 102/max; else s->c_exposure[i][j] = s->c_exposure[i][j] * 64/max; DBG (15, "calibrate_AFE: exp %d %d %d %02x\n", i, j, max, s->c_exposure[i][j]); } } /*handle third pass (gain), lamp on with current offset/exposure */ DBG (15, "calibrate_AFE: gain\n"); ret = write_AFE(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot write afe\n"); goto cleanup; } ret = calibration_scan(s,0xfe); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot make gain cal scan\n"); goto cleanup; } for(i=0;i<2;i++){ max = 0; for(j=0; js.valid_Bpl; j++){ if(s->buffers[i][j] > max) max = s->buffers[i][j]; } if(old_mode == MODE_COLOR) s->c_gain[i] = (250-max)*4/5; else s->c_gain[i] = (125-max)*4/5; if(s->c_gain[i] < 1) s->c_gain[i] = 1; DBG (15, "calibrate_AFE: gain %d %d %02x\n", i, max, s->c_gain[i]); } /*handle fourth pass (offset again), lamp off*/ #if 0 DBG (15, "calibrate_AFE: offset2\n"); ret = write_AFE(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot write afe\n"); goto cleanup; } ret = calibration_scan(s,0xff); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot make offset2 cal scan\n"); goto cleanup; } for(i=0;i<2;i++){ min = 255; for(j=0; js.valid_Bpl; j++){ if(s->buffers[i][j] < min) min = s->buffers[i][j]; } /*s->c_offset[i] += min*3-2;*/ DBG (15, "calibrate_AFE: offset2 %d %d %02x\n", i, min, s->c_offset[i]); } #endif /*send final afe params to scanner*/ ret = write_AFE(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_AFE: ERROR: cannot write afe\n"); goto cleanup; } /* log current cal type */ s->c_res = s->s.dpi_x; s->c_mode = s->s.mode; cleanup: /* recover user settings */ s->u.tl_y = old_tl_y; s->u.br_y = old_br_y; s->u.mode = old_mode; s->u.source = old_source; DBG (10, "calibrate_AFE: finish %d\n",ret); return ret; } /* alternative version- extracts data from scanner memory */ static SANE_Status calibrate_fine_buffer (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int i, j, k; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char * in = NULL; size_t inLen = 0, reqLen = 0; /*buffer these for later*/ int old_tl_y = s->u.tl_y; int old_br_y = s->u.br_y; int old_source = s->u.source; DBG (10, "calibrate_fine_buffer: start\n"); if(!s->need_fcal_buffer){ DBG (10, "calibrate_fine_buffer: not required\n"); return ret; } /* pretend we are doing a 1 line scan in duplex */ s->u.tl_y = 0; s->u.br_y = 1200 / s->u.dpi_y; s->u.source = SOURCE_ADF_DUPLEX; /* load our own private copy of scan params */ ret = update_params(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine_buffer: ERROR: cannot update_params\n"); goto cleanup; } if(s->f_res == s->s.dpi_x && s->f_mode == s->s.mode){ DBG (10, "calibrate_fine_buffer: already done\n"); goto cleanup; } /* clean scan params for new scan */ ret = clean_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine_buffer: ERROR: cannot clean_params\n"); goto cleanup; } /*calibration buffers in scanner are single color channel, but duplex*/ reqLen = s->s.width*2; in = malloc(reqLen); if (!in) { DBG (5, "calibrate_fine_buffer: ERROR: cannot malloc in\n"); ret = SANE_STATUS_NO_MEM; goto cleanup; } /*fine offset*/ ret = offset_buffers(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine_buffer: ERROR: cannot load offset buffers\n"); goto cleanup; } DBG (5, "calibrate_fine_buffer: %d %x\n", s->s.dpi_x/10, s->s.dpi_x/10); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, SR_datatype_fineoffset); set_R_xfer_lid (cmd, s->s.dpi_x/10); set_R_xfer_length (cmd, reqLen); inLen = reqLen; hexdump(15, "cmd:", cmd, cmdLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret != SANE_STATUS_GOOD) goto cleanup; for(i=0;i<2;i++){ /*color mode, expand offset across all three channels? */ if(s->s.format == SANE_FRAME_RGB){ for(j=0; js.valid_width; j++){ /*red*/ s->f_offset[i][j*3] = in[j*2+i]; if(s->f_offset[i][j*3] < 1) s->f_offset[i][j*3] = 1; /*green and blue, same as red*/ s->f_offset[i][j*3+1] = s->f_offset[i][j*3+2] = s->f_offset[i][j*3]; } } /*gray mode, copy*/ else{ for(j=0; js.valid_width; j++){ s->f_offset[i][j] = in[j*2+i]; if(s->f_offset[i][j] < 1) s->f_offset[i][j] = 1; } } hexdump(15, "off:", s->f_offset[i], s->s.valid_Bpl); } /*fine gain*/ ret = gain_buffers(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine_buffer: ERROR: cannot load gain buffers\n"); goto cleanup; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, SR_datatype_finegain); set_R_xfer_lid (cmd, s->s.dpi_x/10); set_R_xfer_length (cmd, reqLen); /*color gain split into three buffers, grab them and merge*/ if(s->s.format == SANE_FRAME_RGB){ int codes[] = {R_FINE_uid_red,R_FINE_uid_green,R_FINE_uid_blue}; for(k=0;k<3;k++){ set_R_xfer_uid (cmd, codes[k]); inLen = reqLen; hexdump(15, "cmd:", cmd, cmdLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret != SANE_STATUS_GOOD) goto cleanup; for(i=0;i<2;i++){ for(j=0; js.valid_width; j++){ s->f_gain[i][j*3+k] = in[j*2+i]*3/4; if(s->f_gain[i][j*3+k] < 1) s->f_gain[i][j*3+k] = 1; } } } } /*gray gain, copy*/ else{ set_R_xfer_uid (cmd, R_FINE_uid_gray); inLen = reqLen; hexdump(15, "cmd:", cmd, cmdLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret != SANE_STATUS_GOOD) goto cleanup; for(i=0;i<2;i++){ for(j=0; js.valid_width; j++){ s->f_gain[i][j] = in[j*2+i]*3/4; if(s->f_gain[i][j] < 1) s->f_gain[i][j] = 1; } } } for(i=0;i<2;i++){ hexdump(15, "gain:", s->f_gain[i], s->s.valid_Bpl); } /* log current cal type */ s->f_res = s->s.dpi_x; s->f_mode = s->s.mode; cleanup: if(in){ free(in); } /* recover user settings */ s->u.tl_y = old_tl_y; s->u.br_y = old_br_y; s->u.source = old_source; DBG (10, "calibrate_fine_buffer: finish %d\n",ret); return ret; } /* * makes several scans, adjusts fine calibration */ static SANE_Status calibrate_fine (struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; int i, j, k; int min, max; int lines = 8; /*buffer these for later*/ int old_tl_y = s->u.tl_y; int old_br_y = s->u.br_y; int old_source = s->u.source; DBG (10, "calibrate_fine: start\n"); if(!s->need_fcal){ DBG (10, "calibrate_fine: not required\n"); return ret; } /* always cal with a short scan in duplex */ s->u.tl_y = 0; s->u.br_y = lines * 1200 / s->u.dpi_y; s->u.source = SOURCE_ADF_DUPLEX; /* load our own private copy of scan params */ ret = update_params(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine: ERROR: cannot update_params\n"); goto cleanup; } if(s->f_res == s->s.dpi_x && s->f_mode == s->s.mode){ DBG (10, "calibrate_fine: already done\n"); goto cleanup; } /* clean scan params for new scan */ ret = clean_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibration_fine: ERROR: cannot clean_params\n"); goto cleanup; } /* make buffers to hold the images */ ret = image_buffers(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine: ERROR: cannot load buffers\n"); goto cleanup; } /*blast the existing fine cal data so reading code wont apply it*/ ret = offset_buffers(s,0); ret = gain_buffers(s,0); /* need to tell it we want duplex */ ret = ssm_buffer(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine: ERROR: cannot ssm buffer\n"); goto cleanup; } /* set window command */ ret = set_window(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine: ERROR: cannot set window\n"); goto cleanup; } /*handle fifth pass (fine offset), lamp off*/ DBG (15, "calibrate_fine: offset\n"); ret = calibration_scan(s,0xff); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine: ERROR: cannot make offset cal scan\n"); goto cleanup; } ret = offset_buffers(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine: ERROR: cannot load offset buffers\n"); goto cleanup; } for(i=0;i<2;i++){ for(j=0; js.valid_Bpl; j++){ min = 0; for(k=j;ks.Bpl;k+=s->s.Bpl){ min += s->buffers[i][k]; } s->f_offset[i][j] = min/lines; } hexdump(15, "off:", s->f_offset[i], s->s.valid_Bpl); } /*handle sixth pass (fine gain), lamp on*/ DBG (15, "calibrate_fine: gain\n"); ret = calibration_scan(s,0xfe); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine: ERROR: cannot make gain cal scan\n"); goto cleanup; } ret = gain_buffers(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibrate_fine: ERROR: cannot load gain buffers\n"); goto cleanup; } for(i=0;i<2;i++){ for(j=0; js.valid_Bpl; j++){ max = 0; for(k=j;ks.Bpl;k+=s->s.Bpl){ max += s->buffers[i][k]; } s->f_gain[i][j] = max/lines; if(s->f_gain[i][j] < 1) s->f_gain[i][j] = 1; } hexdump(15, "gain:", s->f_gain[i], s->s.valid_Bpl); } /* log current cal type */ s->f_res = s->s.dpi_x; s->f_mode = s->s.mode; cleanup: /* recover user settings */ s->u.tl_y = old_tl_y; s->u.br_y = old_br_y; s->u.source = old_source; DBG (10, "calibrate_fine: finish %d\n",ret); return ret; } /* * sends AFE params, and ingests entire duplex image into buffers */ static SANE_Status calibration_scan (struct scanner *s, int scan) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "calibration_scan: start\n"); /* clean scan params for new scan */ ret = clean_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibration_scan: ERROR: cannot clean_params\n"); return ret; } /* start scanning */ ret = start_scan (s,scan); if (ret != SANE_STATUS_GOOD) { DBG (5, "calibration_scan: ERROR: cannot start_scan\n"); return ret; } while(!s->s.eof[SIDE_FRONT] && !s->s.eof[SIDE_BACK]){ ret = read_from_scanner_duplex(s,1); } DBG (10, "calibration_scan: finished\n"); return ret; } /* * sends AFE and exposure params */ static SANE_Status write_AFE(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[COR_CAL_len]; size_t cmdLen = COR_CAL_len; /*use the longest payload for buffer*/ unsigned char pay[CC3_pay_len]; size_t payLen = CC3_pay_len; DBG (10, "write_AFE: start\n"); /* newer scanners use a longer cc payload */ if(s->ccal_version == 3){ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, COR_CAL_code); set_CC_version(cmd,CC3_pay_ver); set_CC_xferlen(cmd,payLen); memset(pay,0,payLen); set_CC3_gain_f_r(pay,s->c_gain[SIDE_FRONT]); set_CC3_gain_f_g(pay,s->c_gain[SIDE_FRONT]); set_CC3_gain_f_b(pay,s->c_gain[SIDE_FRONT]); set_CC3_off_f_r(pay,s->c_offset[SIDE_FRONT]); set_CC3_off_f_g(pay,s->c_offset[SIDE_FRONT]); set_CC3_off_f_b(pay,s->c_offset[SIDE_FRONT]); set_CC3_exp_f_r(pay,s->c_exposure[SIDE_FRONT][CHAN_RED]); set_CC3_exp_f_g(pay,s->c_exposure[SIDE_FRONT][CHAN_GREEN]); set_CC3_exp_f_b(pay,s->c_exposure[SIDE_FRONT][CHAN_BLUE]); set_CC3_gain_b_r(pay,s->c_gain[SIDE_BACK]); set_CC3_gain_b_g(pay,s->c_gain[SIDE_BACK]); set_CC3_gain_b_b(pay,s->c_gain[SIDE_BACK]); set_CC3_off_b_r(pay,s->c_offset[SIDE_BACK]); set_CC3_off_b_g(pay,s->c_offset[SIDE_BACK]); set_CC3_off_b_b(pay,s->c_offset[SIDE_BACK]); set_CC3_exp_b_r(pay,s->c_exposure[SIDE_BACK][CHAN_RED]); set_CC3_exp_b_g(pay,s->c_exposure[SIDE_BACK][CHAN_GREEN]); set_CC3_exp_b_b(pay,s->c_exposure[SIDE_BACK][CHAN_BLUE]); } else{ payLen = CC_pay_len; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, COR_CAL_code); set_CC_version(cmd,CC_pay_ver); set_CC_xferlen(cmd,payLen); memset(pay,0,payLen); set_CC_f_gain(pay,s->c_gain[SIDE_FRONT]); set_CC_unk1(pay,1); set_CC_f_offset(pay,s->c_offset[SIDE_FRONT]); set_CC_unk2(pay,1); set_CC_exp_f_r1(pay,s->c_exposure[SIDE_FRONT][CHAN_RED]); set_CC_exp_f_g1(pay,s->c_exposure[SIDE_FRONT][CHAN_GREEN]); set_CC_exp_f_b1(pay,s->c_exposure[SIDE_FRONT][CHAN_BLUE]); set_CC_exp_f_r2(pay,s->c_exposure[SIDE_FRONT][CHAN_RED]); set_CC_exp_f_g2(pay,s->c_exposure[SIDE_FRONT][CHAN_GREEN]); set_CC_exp_f_b2(pay,s->c_exposure[SIDE_FRONT][CHAN_BLUE]); set_CC_b_gain(pay,s->c_gain[SIDE_BACK]); set_CC_b_offset(pay,s->c_offset[SIDE_BACK]); set_CC_exp_b_r1(pay,s->c_exposure[SIDE_BACK][CHAN_RED]); set_CC_exp_b_g1(pay,s->c_exposure[SIDE_BACK][CHAN_GREEN]); set_CC_exp_b_b1(pay,s->c_exposure[SIDE_BACK][CHAN_BLUE]); set_CC_exp_b_r2(pay,s->c_exposure[SIDE_BACK][CHAN_RED]); set_CC_exp_b_g2(pay,s->c_exposure[SIDE_BACK][CHAN_GREEN]); set_CC_exp_b_b2(pay,s->c_exposure[SIDE_BACK][CHAN_BLUE]); } ret = do_cmd ( s, 1, 0, cmd, cmdLen, pay, payLen, NULL, NULL ); if (ret != SANE_STATUS_GOOD) return ret; DBG (10, "write_AFE: finish\n"); return ret; } /* * frees/callocs buffers to hold the fine cal offset data */ static SANE_Status offset_buffers (struct scanner *s, int setup) { SANE_Status ret = SANE_STATUS_GOOD; int side; DBG (10, "offset_buffers: start\n"); for(side=0;side<2;side++){ if (s->f_offset[side]) { DBG (15, "offset_buffers: free f_offset %d.\n",side); free(s->f_offset[side]); s->f_offset[side] = NULL; } if(setup){ s->f_offset[side] = calloc (1,s->s.Bpl); if (!s->f_offset[side]) { DBG (5, "offset_buffers: error, no f_offset %d.\n",side); return SANE_STATUS_NO_MEM; } } } DBG (10, "offset_buffers: finish\n"); return ret; } /* * frees/callocs buffers to hold the fine cal gain data */ static SANE_Status gain_buffers (struct scanner *s, int setup) { SANE_Status ret = SANE_STATUS_GOOD; int side; DBG (10, "gain_buffers: start\n"); for(side=0;side<2;side++){ if (s->f_gain[side]) { DBG (15, "gain_buffers: free f_gain %d.\n",side); free(s->f_gain[side]); s->f_gain[side] = NULL; } if(setup){ s->f_gain[side] = calloc (1,s->s.Bpl); if (!s->f_gain[side]) { DBG (5, "gain_buffers: error, no f_gain %d.\n",side); return SANE_STATUS_NO_MEM; } } } DBG (10, "gain_buffers: finish\n"); return ret; } /* * @@ Section 6 - SANE cleanup functions */ /* * Cancels a scan. * * It has been said on the mailing list that sane_cancel is a bit of a * misnomer because it is routinely called to signal the end of a * batch - quoting David Mosberger-Tang: * * > In other words, the idea is to have sane_start() be called, and * > collect as many images as the frontend wants (which could in turn * > consist of multiple frames each as indicated by frame-type) and * > when the frontend is done, it should call sane_cancel(). * > Sometimes it's better to think of sane_cancel() as "sane_stop()" * > but that name would have had some misleading connotations as * > well, that's why we stuck with "cancel". * * The current consensus regarding duplex and ADF scans seems to be * the following call sequence: sane_start; sane_read (repeat until * EOF); sane_start; sane_read... and then call sane_cancel if the * batch is at an end. I.e. do not call sane_cancel during the run but * as soon as you get a SANE_STATUS_NO_DOCS. * * From the SANE spec: * This function is used to immediately or as quickly as possible * cancel the currently pending operation of the device represented by * handle h. This function can be called at any time (as long as * handle h is a valid handle) but usually affects long-running * operations only (such as image acquisition). It is safe to call * this function asynchronously (e.g., from within a signal handler). * It is important to note that completion of this operaton does not * imply that the currently pending operation has been cancelled. It * only guarantees that cancellation has been initiated. Cancellation * completes only when the cancelled call returns (typically with a * status value of SANE_STATUS_CANCELLED). Since the SANE API does * not require any other operations to be re-entrant, this implies * that a frontend must not call any other operation until the * cancelled operation has returned. */ void sane_cancel (SANE_Handle handle) { struct scanner * s = (struct scanner *) handle; DBG (10, "sane_cancel: start\n"); s->cancelled = 1; /* if there is no other running function to check, we do it */ if(!s->reading) check_for_cancel(s); DBG (10, "sane_cancel: finish\n"); } /* checks started and cancelled flags in scanner struct, * sends cancel command to scanner if required. don't call * this function asyncronously, wait for pending operation */ static SANE_Status check_for_cancel(struct scanner *s) { SANE_Status ret=SANE_STATUS_GOOD; DBG (10, "check_for_cancel: start\n"); if(s->started && s->cancelled){ unsigned char cmd[CANCEL_len]; size_t cmdLen = CANCEL_len; DBG (15, "check_for_cancel: cancelling\n"); /* cancel scan */ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, CANCEL_code); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, NULL, NULL ); if(ret){ DBG (5, "check_for_cancel: ignoring bad cancel: %d\n",ret); } ret = object_position(s,SANE_FALSE); if(ret){ DBG (5, "check_for_cancel: ignoring bad eject: %d\n",ret); } s->started = 0; s->cancelled = 0; ret = SANE_STATUS_CANCELLED; } else if(s->cancelled){ DBG (15, "check_for_cancel: already cancelled\n"); s->cancelled = 0; ret = SANE_STATUS_CANCELLED; } DBG (10, "check_for_cancel: finish %d\n",ret); return ret; } /* * Ends use of the scanner. * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is * presently active, a call to sane_cancel() is performed first. After * this function returns, handle h must not be used anymore. */ void sane_close (SANE_Handle handle) { struct scanner * s = (struct scanner *) handle; DBG (10, "sane_close: start\n"); disconnect_fd(s); image_buffers(s,0); offset_buffers(s,0); gain_buffers(s,0); DBG (10, "sane_close: finish\n"); } static SANE_Status disconnect_fd (struct scanner *s) { DBG (10, "disconnect_fd: start\n"); if(s->fd > -1){ if (s->connection == CONNECTION_USB) { DBG (15, "disconnecting usb device\n"); sanei_usb_close (s->fd); } else if (s->connection == CONNECTION_SCSI) { DBG (15, "disconnecting scsi device\n"); sanei_scsi_close (s->fd); } s->fd = -1; } DBG (10, "disconnect_fd: finish\n"); return SANE_STATUS_GOOD; } /* * Terminates the backend. * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be * open (it is recommended to close device handles explicitly through * a call to sane_close(), but backends are required to release all * resources upon a call to this function). After this function * returns, no function other than sane_init() may be called * (regardless of the status value returned by sane_exit(). Neglecting * to call this function may result in some resources not being * released properly. */ void sane_exit (void) { struct scanner *dev, *next; DBG (10, "sane_exit: start\n"); for (dev = scanner_devList; dev; dev = next) { disconnect_fd(dev); next = dev->next; free (dev); } if (sane_devArray) free (sane_devArray); scanner_devList = NULL; sane_devArray = NULL; DBG (10, "sane_exit: finish\n"); } /* * @@ Section 7 - misc helper functions */ static void default_globals(void) { global_buffer_size = global_buffer_size_default; global_padded_read = global_padded_read_default; global_extra_status = global_extra_status_default; global_duplex_offset = global_duplex_offset_default; global_vendor_name[0] = 0; global_model_name[0] = 0; global_version_name[0] = 0; } /* * Called by the SANE SCSI core and our usb code on device errors * parses the request sense return data buffer, * decides the best SANE_Status for the problem, produces debug msgs, * and copies the sense buffer into the scanner struct */ static SANE_Status sense_handler (int fd, unsigned char * sensed_data, void *arg) { struct scanner *s = arg; unsigned int sense = get_RS_sense_key (sensed_data); unsigned int asc = get_RS_ASC (sensed_data); unsigned int ascq = get_RS_ASCQ (sensed_data); unsigned int eom = get_RS_EOM (sensed_data); unsigned int ili = get_RS_ILI (sensed_data); unsigned int info = get_RS_information (sensed_data); DBG (5, "sense_handler: start\n"); /* kill compiler warning */ fd = fd; /* copy the rs return data into the scanner struct so that the caller can use it if he wants memcpy(&s->rs_buffer,sensed_data,RS_return_size); */ DBG (5, "Sense=%#02x, ASC=%#02x, ASCQ=%#02x, EOM=%d, ILI=%d, info=%#08x\n", sense, asc, ascq, eom, ili, info); switch (sense) { case 0: if (ili == 1) { s->rs_info = info; DBG (5, "No sense: EOM remainder:%d\n",info); return SANE_STATUS_EOF; } DBG (5, "No sense: unknown asc/ascq\n"); return SANE_STATUS_GOOD; case 1: if (asc == 0x37 && ascq == 0x00) { DBG (5, "Recovered error: parameter rounded\n"); return SANE_STATUS_GOOD; } DBG (5, "Recovered error: unknown asc/ascq\n"); return SANE_STATUS_GOOD; case 2: if (asc == 0x04 && ascq == 0x01) { DBG (5, "Not ready: previous command unfinished\n"); return SANE_STATUS_DEVICE_BUSY; } DBG (5, "Not ready: unknown asc/ascq\n"); return SANE_STATUS_DEVICE_BUSY; case 3: if (asc == 0x36 && ascq == 0x00) { DBG (5, "Medium error: no cartridge\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x3a && ascq == 0x00) { DBG (5, "Medium error: hopper empty\n"); return SANE_STATUS_NO_DOCS; } if (asc == 0x80 && ascq == 0x00) { DBG (5, "Medium error: paper jam\n"); return SANE_STATUS_JAMMED; } if (asc == 0x80 && ascq == 0x01) { DBG (5, "Medium error: cover open\n"); return SANE_STATUS_COVER_OPEN; } if (asc == 0x81 && ascq == 0x01) { DBG (5, "Medium error: double feed\n"); return SANE_STATUS_JAMMED; } if (asc == 0x81 && ascq == 0x02) { DBG (5, "Medium error: skew detected\n"); return SANE_STATUS_JAMMED; } if (asc == 0x81 && ascq == 0x04) { DBG (5, "Medium error: staple detected\n"); return SANE_STATUS_JAMMED; } DBG (5, "Medium error: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; case 4: if (asc == 0x60 && ascq == 0x00) { DBG (5, "Hardware error: lamp error\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x80 && ascq == 0x01) { DBG (5, "Hardware error: CPU check error\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x80 && ascq == 0x02) { DBG (5, "Hardware error: RAM check error\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x80 && ascq == 0x03) { DBG (5, "Hardware error: ROM check error\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x80 && ascq == 0x04) { DBG (5, "Hardware error: hardware check error\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "Hardware error: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; case 5: if (asc == 0x1a && ascq == 0x00) { DBG (5, "Illegal request: Parameter list error\n"); return SANE_STATUS_INVAL; } if (asc == 0x20 && ascq == 0x00) { DBG (5, "Illegal request: invalid command\n"); return SANE_STATUS_INVAL; } if (asc == 0x24 && ascq == 0x00) { DBG (5, "Illegal request: invalid CDB field\n"); return SANE_STATUS_INVAL; } if (asc == 0x25 && ascq == 0x00) { DBG (5, "Illegal request: unsupported logical unit\n"); return SANE_STATUS_UNSUPPORTED; } if (asc == 0x26 && ascq == 0x00) { DBG (5, "Illegal request: invalid field in parm list\n"); return SANE_STATUS_INVAL; } if (asc == 0x2c && ascq == 0x00) { DBG (5, "Illegal request: command sequence error\n"); return SANE_STATUS_INVAL; } if (asc == 0x2c && ascq == 0x01) { DBG (5, "Illegal request: too many windows\n"); return SANE_STATUS_INVAL; } if (asc == 0x3a && ascq == 0x00) { DBG (5, "Illegal request: no paper\n"); return SANE_STATUS_NO_DOCS; } if (asc == 0x3d && ascq == 0x00) { DBG (5, "Illegal request: invalid IDENTIFY\n"); return SANE_STATUS_INVAL; } if (asc == 0x55 && ascq == 0x00) { DBG (5, "Illegal request: scanner out of memory\n"); return SANE_STATUS_NO_MEM; } DBG (5, "Illegal request: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; case 6: if (asc == 0x29 && ascq == 0x00) { DBG (5, "Unit attention: device reset\n"); return SANE_STATUS_GOOD; } if (asc == 0x2a && ascq == 0x00) { DBG (5, "Unit attention: param changed by 2nd initiator\n"); return SANE_STATUS_GOOD; } DBG (5, "Unit attention: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; case 7: DBG (5, "Data protect: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; case 8: DBG (5, "Blank check: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; case 9: DBG (5, "Vendor defined: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; case 0xa: DBG (5, "Copy aborted: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; case 0xb: if (asc == 0x00 && ascq == 0x00) { DBG (5, "Aborted command: no sense/cancelled\n"); return SANE_STATUS_CANCELLED; } if (asc == 0x45 && ascq == 0x00) { DBG (5, "Aborted command: reselect failure\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x47 && ascq == 0x00) { DBG (5, "Aborted command: SCSI parity error\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x48 && ascq == 0x00) { DBG (5, "Aborted command: initiator error message\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x49 && ascq == 0x00) { DBG (5, "Aborted command: invalid message\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x80 && ascq == 0x00) { DBG (5, "Aborted command: timeout\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "Aborted command: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; case 0xc: DBG (5, "Equal: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; case 0xd: DBG (5, "Volume overflow: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; case 0xe: if (asc == 0x3b && ascq == 0x0d) { DBG (5, "Miscompare: too many docs\n"); return SANE_STATUS_IO_ERROR; } if (asc == 0x3b && ascq == 0x0e) { DBG (5, "Miscompare: too few docs\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "Miscompare: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; default: DBG (5, "Unknown Sense Code\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "sense_handler: should never happen!\n"); return SANE_STATUS_IO_ERROR; } /* * take a bunch of pointers, send commands to scanner */ static SANE_Status do_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { if (s->connection == CONNECTION_SCSI) { return do_scsi_cmd(s, runRS, shortTime, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen ); } if (s->connection == CONNECTION_USB) { return do_usb_cmd(s, runRS, shortTime, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen ); } return SANE_STATUS_INVAL; } static SANE_Status do_scsi_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { int ret; /*shut up compiler*/ runRS=runRS; shortTime=shortTime; DBG(10, "do_scsi_cmd: start\n"); DBG(25, "cmd: writing %d bytes\n", (int)cmdLen); hexdump(30, "cmd: >>", cmdBuff, cmdLen); if(outBuff && outLen){ DBG(25, "out: writing %d bytes\n", (int)outLen); hexdump(30, "out: >>", outBuff, outLen); } if (inBuff && inLen){ DBG(25, "in: reading %d bytes\n", (int)*inLen); memset(inBuff,0,*inLen); } ret = sanei_scsi_cmd2(s->fd, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen); if(ret != SANE_STATUS_GOOD && ret != SANE_STATUS_EOF){ DBG(5,"do_scsi_cmd: return '%s'\n",sane_strstatus(ret)); return ret; } if (inBuff && inLen){ if(ret == SANE_STATUS_EOF){ DBG(25, "in: short read, remainder %lu bytes\n", (u_long)s->rs_info); *inLen -= s->rs_info; } hexdump(31, "in: <<", inBuff, *inLen); DBG(25, "in: read %d bytes\n", (int)*inLen); } DBG(10, "do_scsi_cmd: finish\n"); return ret; } static SANE_Status do_usb_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { size_t cmdOffset = 0; size_t cmdLength = 0; size_t cmdActual = 0; unsigned char * cmdBuffer = NULL; int cmdTimeout = 0; size_t outOffset = 0; size_t outLength = 0; size_t outActual = 0; unsigned char * outBuffer = NULL; int outTimeout = 0; size_t inOffset = 0; size_t inLength = 0; size_t inActual = 0; unsigned char * inBuffer = NULL; int inTimeout = 0; size_t extraLength = 0; int ret = 0; int ret2 = 0; struct timeval timer; gettimeofday(&timer,NULL); DBG (10, "do_usb_cmd: start %lu %lu\n", (long unsigned int)timer.tv_sec, (long unsigned int)timer.tv_usec); /****************************************************************/ /* the command stage */ { cmdOffset = USB_HEADER_LEN; cmdLength = cmdOffset+USB_COMMAND_LEN; cmdActual = cmdLength; cmdTimeout = USB_COMMAND_TIME; /* change timeout */ if(shortTime) cmdTimeout/=60; sanei_usb_set_timeout(cmdTimeout); /* build buffer */ cmdBuffer = calloc(cmdLength,1); if(!cmdBuffer){ DBG(5,"cmd: no mem\n"); return SANE_STATUS_NO_MEM; } /* build a USB packet around the SCSI command */ cmdBuffer[3] = cmdLength-4; cmdBuffer[5] = 1; cmdBuffer[6] = 0x90; memcpy(cmdBuffer+cmdOffset,cmdBuff,cmdLen); /* write the command out */ DBG(25, "cmd: writing %d bytes, timeout %d\n", (int)cmdLength, cmdTimeout); hexdump(30, "cmd: >>", cmdBuffer, cmdLength); ret = sanei_usb_write_bulk(s->fd, cmdBuffer, &cmdActual); DBG(25, "cmd: wrote %d bytes, retVal %d\n", (int)cmdActual, ret); if(cmdLength != cmdActual){ DBG(5,"cmd: wrong size %d/%d\n", (int)cmdLength, (int)cmdActual); free(cmdBuffer); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"cmd: write error '%s'\n",sane_strstatus(ret)); free(cmdBuffer); return ret; } free(cmdBuffer); } /****************************************************************/ /* the extra status stage, used by few scanners */ /* this is like the regular status block, with an additional */ /* length component at the end */ if(s->extra_status){ ret2 = do_usb_status(s,runRS,shortTime,&extraLength); /* bail out on bad RS status */ if(ret2){ DBG(5,"extra: bad RS status, %d\n", ret2); return ret2; } } /****************************************************************/ /* the output stage */ if(outBuff && outLen){ outOffset = USB_HEADER_LEN; outLength = outOffset+outLen; outActual = outLength; outTimeout = USB_DATA_TIME; /* change timeout */ if(shortTime) outTimeout/=60; sanei_usb_set_timeout(outTimeout); /* build outBuffer */ outBuffer = calloc(outLength,1); if(!outBuffer){ DBG(5,"out: no mem\n"); return SANE_STATUS_NO_MEM; } /* build a USB packet around the SCSI command */ outBuffer[3] = outLength-4; outBuffer[5] = 2; outBuffer[6] = 0xb0; memcpy(outBuffer+outOffset,outBuff,outLen); /* write the command out */ DBG(25, "out: writing %d bytes, timeout %d\n", (int)outLength, outTimeout); hexdump(30, "out: >>", outBuffer, outLength); ret = sanei_usb_write_bulk(s->fd, outBuffer, &outActual); DBG(25, "out: wrote %d bytes, retVal %d\n", (int)outActual, ret); if(outLength != outActual){ DBG(5,"out: wrong size %d/%d\n", (int)outLength, (int)outActual); free(outBuffer); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"out: write error '%s'\n",sane_strstatus(ret)); free(outBuffer); return ret; } free(outBuffer); } /****************************************************************/ /* the input stage */ if(inBuff && inLen){ inOffset = 0; if(s->padded_read) inOffset = USB_HEADER_LEN; inLength = inOffset+*inLen; inActual = inLength; /* use the extra length to alter the amount of in we request */ if(s->extra_status && extraLength && *inLen > extraLength){ DBG(5,"in: adjust extra, %d %d\n", (int)*inLen, (int)extraLength); inActual = inOffset+extraLength; } /*blast caller's copy in case we error out*/ *inLen = 0; inTimeout = USB_DATA_TIME; /* change timeout */ if(shortTime) inTimeout/=60; sanei_usb_set_timeout(inTimeout); /* build inBuffer */ inBuffer = calloc(inActual,1); if(!inBuffer){ DBG(5,"in: no mem\n"); return SANE_STATUS_NO_MEM; } DBG(25, "in: reading %d bytes, timeout %d\n", (int)inActual, inTimeout); ret = sanei_usb_read_bulk(s->fd, inBuffer, &inActual); DBG(25, "in: read %d bytes, retval %d\n", (int)inActual, ret); hexdump(31, "in: <<", inBuffer, inActual); if(!inActual){ DBG(5,"in: got no data, clearing\n"); free(inBuffer); return do_usb_clear(s,1,runRS); } if(inActual < inOffset){ DBG(5,"in: read shorter than inOffset\n"); free(inBuffer); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"in: return error '%s'\n",sane_strstatus(ret)); free(inBuffer); return ret; } /* note that inBuffer is not copied and freed here...*/ } /****************************************************************/ /* the normal status stage */ ret2 = do_usb_status(s,runRS,shortTime,&extraLength); /* if status said EOF, adjust input with remainder count */ if(ret2 == SANE_STATUS_EOF && inBuffer){ /* EOF is ok */ ret2 = SANE_STATUS_GOOD; if(inActual < inLength - s->rs_info){ DBG(5,"in: we read < RS, ignoring RS: %d < %d (%d-%d)\n", (int)inActual,(int)(inLength-s->rs_info),(int)inLength,(int)s->rs_info); } else if(inActual > inLength - s->rs_info){ DBG(5,"in: we read > RS, using RS: %d to %d (%d-%d)\n", (int)inActual,(int)(inLength-s->rs_info),(int)inLength,(int)s->rs_info); inActual = inLength - s->rs_info; } } /* bail out on bad RS status */ if(ret2){ if(inBuffer) free(inBuffer); DBG(5,"stat: bad RS status, %d\n", ret2); return ret2; } /* now that we have read status, deal with input buffer */ if(inBuffer){ if(inLength != inActual){ ret = SANE_STATUS_EOF; DBG(5,"in: short read, %d/%d\n", (int)inLength,(int)inActual); } /* ignore the USB packet around the SCSI command */ *inLen = inActual - inOffset; memcpy(inBuff,inBuffer+inOffset,*inLen); free(inBuffer); } gettimeofday(&timer,NULL); DBG (10, "do_usb_cmd: finish %lu %lu\n", (long unsigned int)timer.tv_sec, (long unsigned int)timer.tv_usec); return ret; } static SANE_Status do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength) { #define EXTRA_READ_len 4 size_t statPadding = 0; size_t statOffset = 0; size_t statLength = 0; size_t statActual = 0; unsigned char * statBuffer = NULL; int statTimeout = 0; int ret = 0; if(s->padded_read) statPadding = USB_HEADER_LEN; statLength = statPadding+USB_STATUS_LEN; statOffset = statLength-1; if(s->extra_status) statLength += EXTRA_READ_len; statActual = statLength; statTimeout = USB_STATUS_TIME; /* change timeout */ if(shortTime) statTimeout/=60; sanei_usb_set_timeout(statTimeout); /* build statBuffer */ statBuffer = calloc(statLength,1); if(!statBuffer){ DBG(5,"stat: no mem\n"); return SANE_STATUS_NO_MEM; } DBG(25, "stat: reading %d bytes, timeout %d\n", (int)statLength, statTimeout); ret = sanei_usb_read_bulk(s->fd, statBuffer, &statActual); DBG(25, "stat: read %d bytes, retval %d\n", (int)statActual, ret); hexdump(30, "stat: <<", statBuffer, statActual); /*weird status*/ if(ret != SANE_STATUS_GOOD){ DBG(5,"stat: clearing error '%s'\n",sane_strstatus(ret)); ret = do_usb_clear(s,1,runRS); } /*short read*/ else if(statLength != statActual){ DBG(5,"stat: clearing short %d/%d\n",(int)statLength,(int)statActual); ret = do_usb_clear(s,1,runRS); } /*inspect the status byte of the response*/ else if(statBuffer[statOffset]){ DBG(5,"stat: status %d\n",statBuffer[statLength-1-4]); ret = do_usb_clear(s,0,runRS); } /*extract the extra length byte of the response*/ if(s->extra_status){ *extraLength = get_ES_length(statBuffer); DBG(15,"stat: extra %d\n",(int)*extraLength); } free(statBuffer); return ret; } static SANE_Status do_usb_clear(struct scanner *s, int clear, int runRS) { SANE_Status ret, ret2; DBG (10, "do_usb_clear: start\n"); usleep(100000); if(clear){ DBG (15, "do_usb_clear: clear halt\n"); ret = sanei_usb_clear_halt(s->fd); if(ret != SANE_STATUS_GOOD){ DBG(5,"do_usb_clear: cant clear halt, returning %d\n", ret); return ret; } } /* caller is interested in having RS run on errors */ if(runRS){ unsigned char rs_cmd[REQUEST_SENSE_len]; size_t rs_cmdLen = REQUEST_SENSE_len; unsigned char rs_in[RS_return_size]; size_t rs_inLen = RS_return_size; memset(rs_cmd,0,rs_cmdLen); set_SCSI_opcode(rs_cmd, REQUEST_SENSE_code); set_RS_return_size(rs_cmd, rs_inLen); DBG(25,"rs sub call >>\n"); ret2 = do_cmd( s,0,0, rs_cmd, rs_cmdLen, NULL,0, rs_in, &rs_inLen ); DBG(25,"rs sub call <<\n"); if(ret2 == SANE_STATUS_EOF){ DBG(5,"rs: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret2 != SANE_STATUS_GOOD){ DBG(5,"rs: return error '%s'\n",sane_strstatus(ret2)); return ret2; } /* parse the rs data */ ret2 = sense_handler( 0, rs_in, (void *)s ); DBG (10, "do_usb_clear: finish after RS\n"); return ret2; } DBG (10, "do_usb_clear: finish with io error\n"); return SANE_STATUS_IO_ERROR; } static SANE_Status wait_scanner(struct scanner *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[TEST_UNIT_READY_len]; size_t cmdLen = TEST_UNIT_READY_len; DBG (10, "wait_scanner: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,TEST_UNIT_READY_code); ret = do_cmd ( s, 0, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); // some scanners (such as DR-F120) are OK but will not respond to commands // when in sleep mode. By checking the sense it wakes them up. if (ret != SANE_STATUS_GOOD) { DBG(5,"WARNING: Brain-dead scanner. Hitting with request sense.\n"); ret = do_cmd ( s, 1, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); } if (ret != SANE_STATUS_GOOD) { DBG(5,"WARNING: Brain-dead scanner. Hitting with stick instead.\n"); ret = do_cmd ( s, 0, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); } if (ret != SANE_STATUS_GOOD) { DBG (5, "wait_scanner: error '%s'\n", sane_strstatus (ret)); } DBG (10, "wait_scanner: finish (status=%d)\n", ret); return ret; } /* Some scanners have per-resolution * color interlacing values, but most * don't. This helper can tell the * difference. */ static int get_color_inter(struct scanner *s, int side, int res) { int i; for(i=0;icolor_inter_by_res[i]) return s->color_inter_by_res[i]; return s->color_interlace[side]; } /* s->u.page_x stores the user setting * for the paper width in adf. sometimes, * we need a value that differs from this * due to using FB or overscan. */ static int get_page_width(struct scanner *s) { int width = s->u.page_x; /* scanner max for fb */ if(s->u.source == SOURCE_FLATBED){ return s->max_x_fb; } /* cant overscan larger than scanner max */ if(width > s->valid_x){ return s->valid_x; } /* overscan adds a margin to both sides */ return width; } /* s->u.page_y stores the user setting * for the paper height in adf. sometimes, * we need a value that differs from this * due to using FB or overscan. */ static int get_page_height(struct scanner *s) { int height = s->u.page_y; /* scanner max for fb */ if(s->u.source == SOURCE_FLATBED){ return s->max_y_fb; } /* cant overscan larger than scanner max */ if(height > s->max_y){ return s->max_y; } /* overscan adds a margin to both sides */ return height; } /** * Convenience method to determine longest string size in a list. */ static size_t maxStringSize (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /* * Prints a hex dump of the given buffer onto the debug output stream. */ static void hexdump (int level, char *comment, unsigned char *p, int l) { int i; char line[70]; /* 'xxx: xx xx ... xx xx abc */ char *hex = line+4; char *bin = line+53; if(DBG_LEVEL < level) return; line[0] = 0; DBG (level, "%s\n", comment); for (i = 0; i < l; i++, p++) { /* at start of line */ if ((i % 16) == 0) { /* not at start of first line, print current, reset */ if (i) { DBG (level, "%s\n", line); } memset(line,0x20,69); line[69] = 0; hex = line + 4; bin = line + 53; sprintf (line, "%3.3x:", i); } /* the hex section */ sprintf (hex, " %2.2x", *p); hex += 3; *hex = ' '; /* the char section */ if(*p >= 0x20 && *p <= 0x7e){ *bin=*p; } else{ *bin='.'; } bin++; } /* print last (partial) line */ if (i) DBG (level, "%s\n", line); } /** * An advanced method we don't support but have to define. */ SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) { DBG (10, "sane_set_io_mode\n"); DBG (15, "%d %p\n", non_blocking, h); return SANE_STATUS_UNSUPPORTED; } /** * An advanced method we don't support but have to define. */ SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) { DBG (10, "sane_get_select_fd\n"); DBG (15, "%p %d\n", h, *fdp); return SANE_STATUS_UNSUPPORTED; } /* * @@ Section 8 - Image processing functions */ /* Look in image for likely upper and left paper edges, then rotate * image so that upper left corner of paper is upper left of image. * FIXME: should we do this before we binarize instead of after? */ static SANE_Status buffer_deskew(struct scanner *s, int side) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char bg_color = calc_bg_color(s); DBG (10, "buffer_deskew: start\n"); ret = sane_get_parameters((SANE_Handle) s, &s->s_params); /*only find skew on first image from a page, or if first image had error */ if(s->side == SIDE_FRONT || s->u.source == SOURCE_ADF_BACK || s->deskew_stat){ s->deskew_stat = sanei_magic_findSkew( &s->s_params,s->buffers[side],s->u.dpi_x,s->u.dpi_y, &s->deskew_vals[0],&s->deskew_vals[1],&s->deskew_slope); if(s->deskew_stat){ DBG (5, "buffer_deskew: bad findSkew, bailing\n"); goto cleanup; } } /* backside images can use a 'flipped' version of frontside data */ else{ s->deskew_slope *= -1; s->deskew_vals[0] = s->s_params.pixels_per_line - s->deskew_vals[0]; } ret = sanei_magic_rotate(&s->s_params,s->buffers[side], s->deskew_vals[0],s->deskew_vals[1],s->deskew_slope,bg_color); if(ret){ DBG(5,"buffer_deskew: rotate error: %d",ret); ret = SANE_STATUS_GOOD; goto cleanup; } cleanup: DBG (10, "buffer_deskew: finish\n"); return ret; } /* Look in image for likely left/right/bottom paper edges, then crop * image to match. Does not attempt to rotate the image. * FIXME: should we do this before we binarize instead of after? */ static SANE_Status buffer_crop(struct scanner *s, int side) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "buffer_crop: start\n"); ret = sane_get_parameters((SANE_Handle) s, &s->s_params); ret = sanei_magic_findEdges( &s->s_params,s->buffers[side],s->u.dpi_x,s->u.dpi_y, &s->crop_vals[0],&s->crop_vals[1],&s->crop_vals[2],&s->crop_vals[3]); if(ret){ DBG (5, "buffer_crop: bad edges, bailing\n"); ret = SANE_STATUS_GOOD; goto cleanup; } DBG (15, "buffer_crop: t:%d b:%d l:%d r:%d\n", s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); /* if we will later binarize this image, make sure the width * is a multiple of 8 pixels, by adjusting the right side */ if ( must_downsample(s) && s->u.mode < MODE_GRAYSCALE ){ s->crop_vals[3] -= (s->crop_vals[3]-s->crop_vals[2]) % 8; } /* now crop the image */ ret = sanei_magic_crop(&s->s_params,s->buffers[side], s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); if(ret){ DBG (5, "buffer_crop: bad crop, bailing\n"); ret = SANE_STATUS_GOOD; goto cleanup; } /* need to update user with new size */ s->i.width = s->s_params.pixels_per_line; s->i.height = s->s_params.lines; s->i.Bpl = s->s_params.bytes_per_line; /* update image size counter to new, smaller size */ s->i.bytes_tot[side] = s->s_params.lines * s->s_params.bytes_per_line; s->i.bytes_sent[side] = s->i.bytes_tot[side]; s->u.bytes_sent[side] = 0; cleanup: DBG (10, "buffer_crop: finish\n"); return ret; } /* Look in image for disconnected 'spots' of the requested size. * Replace the spots with the average color of the surrounding pixels. * FIXME: should we do this before we binarize instead of after? */ static SANE_Status buffer_despeck(struct scanner *s, int side) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "buffer_despeck: start\n"); ret = sane_get_parameters((SANE_Handle) s, &s->s_params); ret = sanei_magic_despeck(&s->s_params,s->buffers[side],s->swdespeck); if(ret){ DBG (5, "buffer_despeck: bad despeck, bailing\n"); ret = SANE_STATUS_GOOD; goto cleanup; } cleanup: DBG (10, "buffer_despeck: finish\n"); return ret; } /* Look if image has too few dark pixels.*/ static int buffer_isblank(struct scanner *s, int side) { SANE_Status ret = SANE_STATUS_GOOD; int status = 0; DBG (10, "buffer_isblank: start\n"); ret = sane_get_parameters((SANE_Handle) s, &s->s_params); ret = sanei_magic_isBlank2(&s->s_params, s->buffers[side], s->u.dpi_x, s->u.dpi_y, s->swskip); if(ret == SANE_STATUS_NO_DOCS){ DBG (5, "buffer_isblank: blank!\n"); status = 1; } else if(ret){ DBG (5, "buffer_isblank: error %d\n",ret); } DBG (10, "buffer_isblank: finished\n"); return status; } /* certain options require the entire image to * be collected from the scanner before we can * tell the user the size of the image. */ static int must_fully_buffer(struct scanner *s) { if( (s->swdeskew || s->swdespeck || s->swcrop) && s->s.format != SANE_FRAME_JPEG ){ return 1; } return 0; } /* certain scanners require the mode of the * image to be changed in software. */ static int must_downsample(struct scanner *s) { if(s->s.mode != s->i.mode && s->compress != COMP_JPEG ){ return 1; } return 0; } /* Function to build a lookup table (LUT), often used by scanners to implement brightness/contrast/gamma or by backends to speed binarization/thresholding offset and slope inputs are -127 to +127 slope rotates line around central input/output val, 0 makes horizontal line pos zero neg . x . . x . x . . x out . x .xxxxxxxxxxx . x . x . . x ....x....... ............ .......x.... in in in offset moves line vertically, and clamps to output range 0 keeps the line crossing the center of the table pos zero neg . xxxxxxxx . xx . . x . x . out x . x . x . . x . x ............ xx.......... xxxxxxxx.... in in out_min/max provide bounds on output values, useful when building thresholding lut. 0 and 255 are good defaults otherwise. */ static SANE_Status load_lut (unsigned char * lut, int in_bits, int out_bits, int out_min, int out_max, int slope, int offset) { SANE_Status ret = SANE_STATUS_GOOD; int i, j; double shift, rise; int max_in_val = (1 << in_bits) - 1; int max_out_val = (1 << out_bits) - 1; unsigned char * lut_p = lut; DBG (10, "load_lut: start %d %d\n", slope, offset); /* slope is converted to rise per unit run: * first [-127,127] to [-.999,.999] * then to [-PI/4,PI/4] then [0,PI/2] * then take the tangent (T.O.A) * then multiply by the normal linear slope * because the table may not be square, i.e. 1024x256*/ rise = tan((double)slope/128 * M_PI_4 + M_PI_4) * max_out_val / max_in_val; /* line must stay vertically centered, so figure * out vertical offset at central input value */ shift = (double)max_out_val/2 - (rise*max_in_val/2); /* convert the user offset setting to scale of output * first [-127,127] to [-1,1] * then to [-max_out_val/2,max_out_val/2]*/ shift += (double)offset / 127 * max_out_val / 2; for(i=0;i<=max_in_val;i++){ j = rise*i + shift; if(jout_max){ j=out_max; } *lut_p=j; lut_p++; } hexdump(5, "load_lut: ", lut, max_in_val+1); DBG (10, "load_lut: finish\n"); return ret; } sane-backends-1.0.27/backend/teco1.c0000664000175000017500000015420212112021330013755 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ Some Relisys scanners AVEC and RELI series */ /*--------------------------------------------------------------------------*/ #define BUILD 10 /* 2004/02/08 */ #define BACKEND_NAME teco1 #define TECO_CONFIG_FILE "teco1.conf" /*--------------------------------------------------------------------------*/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "teco1.h" #undef sim #ifdef sim #define sanei_scsi_cmd2(a, b, c, d, e, f, g) SANE_STATUS_GOOD #define sanei_scsi_open(a, b, c, d) 0 #define sanei_scsi_cmd(a, b, c, d, e) SANE_STATUS_GOOD #define sanei_scsi_close(a) SANE_STATUS_GOOD #endif /*--------------------------------------------------------------------------*/ /* Lists of possible scan modes. */ static SANE_String_Const scan_mode_list[] = { BLACK_WHITE_STR, GRAY_STR, COLOR_STR, NULL }; /*--------------------------------------------------------------------------*/ /* Minimum and maximum width and length supported. */ static SANE_Range x_range = { SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0 }; static SANE_Range y_range = { SANE_FIX (0), SANE_FIX (14 * MM_PER_INCH), 0 }; /*--------------------------------------------------------------------------*/ /* Gamma range */ static const SANE_Range gamma_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ /* List of dithering options. */ static SANE_String_Const dither_list[] = { "Line art", "2x2", "3x3", "4x4 bayer", "4x4 smooth", "8x8 bayer", "8x8 smooth", "8x8 horizontal", "8x8 vertical", NULL }; static const int dither_val[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; /*--------------------------------------------------------------------------*/ static const SANE_Range threshold_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ /* Define the supported scanners and their characteristics. */ static const struct scanners_supported scanners[] = { {6, "TECO VM3510", /* *fake id*, see teco_identify_scanner */ TECO_VM3510, "Dextra", "DF-600P", {1, 600, 1}, /* resolution */ 300, 600, /* max x and Y res */ 3, /* color 3 pass */ 256, /* number of bytes per gamma color */ 80 /* number of bytes in a window */ }, {6, "TECO VM353A", TECO_VM353A, "Relisys", "RELI 2412", {1, 1200, 1}, /* resolution */ 300, 1200, /* max x and Y resolution */ 1, /* color 1 pass */ 256, /* number of bytes per gamma color */ 99 /* number of bytes in a window */ }, {6, "TECO VM3520", TECO_VM3520, "Relisys", "AVEC Colour Office 2400", {1, 600, 1}, /* resolution */ 300, 600, /* max x and Y resolution */ 3, /* color 3 pass */ 256, /* number of bytes per gamma color */ 99 /* number of bytes in a window */ }, {6, "TECO VM352A", TECO_VM3520, /* same as AVEC 2400 */ "Relisys", "AVEC Colour 2412", {1, 600, 1}, 300, 600, 3, 256, 99 }, {6, "TECO VM4540", TECO_VM4540, "Relisys", "RELI 4816", {1, 1600, 1}, /* resolution */ 400, 1600, /* max x and Y resolution */ 1, /* color 1 pass */ 256, /* number of bytes per gamma color */ 99 /* number of bytes in a window */ }, {6, "TECO VM4542", TECO_VM4542, "Relisys", "RELI 4830", {1, 400, 1}, /* resolution */ 400, 400, /* max x and Y resolution */ 1, /* color 1 pass */ 1024, /* number of bytes per gamma color */ 99 /* number of bytes in a window */ } }; /*--------------------------------------------------------------------------*/ /* List of scanner attached. */ static Teco_Scanner *first_dev = NULL; static int num_devices = 0; static const SANE_Device **devlist = NULL; /* Local functions. */ /* Display a buffer in the log. */ static void hexdump (int level, const char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; char asc_buf[17]; char *asc_ptr; DBG (level, "%s\n", comment); ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { DBG (level, "%s %s\n", line, asc_buf); ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; } sprintf (ptr, "%3.3d:", i); ptr += 4; } ptr += sprintf (ptr, " %2.2x", *p); if (*p >= 32 && *p <= 127) { asc_ptr += sprintf (asc_ptr, "%c", *p); } else { asc_ptr += sprintf (asc_ptr, "."); } } *ptr = '\0'; DBG (level, "%s %s\n", line, asc_buf); } /* Returns the length of the longest string, including the terminating * character. */ static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* Lookup a string list from one array and return its index. */ static int get_string_list_index (SANE_String_Const list[], SANE_String_Const name) { int index; index = 0; while (list[index] != NULL) { if (strcmp (list[index], name) == 0) { return (index); } index++; } DBG (DBG_error, "name %s not found in list\n", name); assert (0 == 1); /* bug in backend, core dump */ return (-1); } /* Initialize a scanner entry. Return an allocated scanner with some * preset values. */ static Teco_Scanner * teco_init (void) { Teco_Scanner *dev; DBG (DBG_proc, "teco_init: enter\n"); /* Allocate a new scanner entry. */ dev = malloc (sizeof (Teco_Scanner)); if (dev == NULL) { return NULL; } memset (dev, 0, sizeof (Teco_Scanner)); /* Allocate the buffer used to transfer the SCSI data. */ dev->buffer_size = 64 * 1024; dev->buffer = malloc (dev->buffer_size); if (dev->buffer == NULL) { free (dev); return NULL; } /* Allocate a buffer to store the temporary image. */ dev->image_size = 64 * 1024; /* enough for 1 line at max res */ dev->image = malloc (dev->image_size); if (dev->image == NULL) { free (dev->buffer); free (dev); return NULL; } dev->sfd = -1; DBG (DBG_proc, "teco_init: exit\n"); return (dev); } /* Closes an open scanner. */ static void teco_close (Teco_Scanner * dev) { DBG (DBG_proc, "teco_close: enter\n"); if (dev->sfd != -1) { sanei_scsi_close (dev->sfd); dev->sfd = -1; } DBG (DBG_proc, "teco_close: exit\n"); } /* Frees the memory used by a scanner. */ static void teco_free (Teco_Scanner * dev) { int i; DBG (DBG_proc, "teco_free: enter\n"); if (dev == NULL) return; teco_close (dev); if (dev->devicename) { free (dev->devicename); } if (dev->buffer) { free (dev->buffer); } if (dev->image) { free (dev->image); } for (i = 1; i < OPT_NUM_OPTIONS; i++) { if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) { free (dev->val[i].s); } } free (dev); DBG (DBG_proc, "teco_free: exit\n"); } /* Inquiry a device and returns TRUE if is supported. */ static int teco_identify_scanner (Teco_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; int i; DBG (DBG_proc, "teco_identify_scanner: enter\n"); size = 5; MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "teco_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } #ifdef sim { #if 1 /* vm3510 / Dextra DF-600P */ unsigned char table[] = { 0x06, 0x00, 0x02, 0x02, 0x24, 0x00, 0x00, 0x10, 0x44, 0x46, 0x2D, 0x36, 0x30, 0x30, 0x4D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x2E, 0x31, 0x37, 0x31, 0x2E, 0x31, 0x37, 0x02 }; #endif #if 0 /* vm4542 */ unsigned char table[] = { 0x06, 0x00, 0x02, 0x02, 0x30, 0x00, 0x00, 0x10, 0x52, 0x45, 0x4c, 0x49, 0x53, 0x59, 0x53, 0x20, 0x52, 0x45, 0x4c, 0x49, 0x20, 0x34, 0x38, 0x33, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x2e, 0x30, 0x33, 0x31, 0x2e, 0x30, 0x33, 0x02, 0x00, 0x54, 0x45, 0x43, 0x4f, 0x20, 0x56, 0x4d, 0x34, 0x35, 0x34, 0x32 }; #endif memcpy (dev->buffer, table, sizeof (table)); } #endif size = dev->buffer[4] + 5; /* total length of the inquiry data */ MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "teco_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } /* Hack to recognize the dextra as a TECO scanner. */ if (memcmp (dev->buffer + 0x08, "DF-600M ", 8) == 0) { memcpy (dev->buffer + 0x29, "\0TECO VM3510", 12); dev->buffer[4] = 0x30; /* change length */ size = 0x35; } if (size < 53) { DBG (DBG_error, "teco_identify_scanner: not enough data to identify device\n"); return (SANE_FALSE); } hexdump (DBG_info2, "inquiry", dev->buffer, size); dev->scsi_type = dev->buffer[0] & 0x1f; memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); dev->scsi_vendor[0x08] = 0; memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); dev->scsi_product[0x10] = 0; memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); dev->scsi_version[0x04] = 0; memcpy (dev->scsi_teco_name, dev->buffer + 0x2A, 0x0B); dev->scsi_teco_name[0x0B] = 0; DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\" \"%s\"\n", dev->scsi_vendor, dev->scsi_product, dev->scsi_version, dev->scsi_teco_name); /* Lookup through the supported scanners table to find if this * backend supports that one. */ for (i = 0; i < NELEMS (scanners); i++) { if (dev->scsi_type == scanners[i].scsi_type && strcmp (dev->scsi_teco_name, scanners[i].scsi_teco_name) == 0) { DBG (DBG_error, "teco_identify_scanner: scanner supported\n"); dev->def = &(scanners[i]); return (SANE_TRUE); } } DBG (DBG_proc, "teco_identify_scanner: exit, device not supported\n"); return (SANE_FALSE); } /* Get the inquiry page 0x82. */ static int teco_get_inquiry_82 (Teco_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; DBG (DBG_proc, "teco_get_inquiry_82: enter\n"); size = 0x4; MKSCSI_INQUIRY (cdb, size); cdb.data[1] = 1; /* evpd */ cdb.data[2] = 0x82; /* page code number */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "teco_get_inquiry_82: inquiry page 0x82 failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } size = dev->buffer[3] + 4; MKSCSI_INQUIRY (cdb, size); cdb.data[1] = 1; /* evpd */ cdb.data[2] = 0x82; /* page code number */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "teco_get_inquiry_82: inquiry page 0x82 failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } hexdump (DBG_info2, "inquiry page 0x82", dev->buffer, size); DBG (DBG_proc, "teco_get_inquiry_82: leave\n"); return (status); } /* SCSI sense handler. Callback for SANE. * These scanners never set asc or ascq. */ static SANE_Status teco_sense_handler (int __sane_unused__ scsi_fd, unsigned char *result, void __sane_unused__ *arg) { int sensekey; int len; DBG (DBG_proc, "teco_sense_handler: enter\n"); sensekey = get_RS_sense_key (result); len = 7 + get_RS_additional_length (result); hexdump (DBG_info2, "sense", result, len); if (get_RS_error_code (result) != 0x70) { DBG (DBG_error, "teco_sense_handler: invalid sense key error code (%d)\n", get_RS_error_code (result)); return SANE_STATUS_IO_ERROR; } if (len < 14) { DBG (DBG_error, "teco_sense_handler: sense too short, no ASC/ASCQ\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_sense, "teco_sense_handler: sense=%d\n", sensekey); if (sensekey == 0x00) { return SANE_STATUS_GOOD; } return SANE_STATUS_IO_ERROR; } /* Send the mode select to the scanner. */ static int teco_mode_select (Teco_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; unsigned char select[24] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00 }; DBG (DBG_proc, "teco_mode_select: enter\n"); size = 24; MKSCSI_MODE_SELECT (cdb, 1, 0, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, select, size, NULL, NULL); DBG (DBG_proc, "teco_mode_select: exit\n"); return (status); } /* Set a window. */ static SANE_Status teco_set_window (Teco_Scanner * dev) { size_t size; /* significant size of window */ CDB cdb; unsigned char window[99]; SANE_Status status; int i; DBG (DBG_proc, "teco_set_window: enter\n"); size = dev->def->window_size; MKSCSI_SET_WINDOW (cdb, size); memset (window, 0, size); /* size of the windows descriptor block */ window[7] = size - 8; /* X and Y resolution */ Ito16 (dev->x_resolution, &window[10]); Ito16 (dev->y_resolution, &window[12]); /* Upper Left (X,Y) */ Ito32 (dev->x_tl, &window[14]); Ito32 (dev->y_tl, &window[18]); /* Width and length */ Ito32 (dev->width, &window[22]); Ito32 (dev->length, &window[26]); /* Image Composition */ switch (dev->scan_mode) { case TECO_BW: window[33] = 0x00; i = get_string_list_index (dither_list, dev->val[OPT_DITHER].s); window[36] = dither_val[i]; break; case TECO_GRAYSCALE: window[33] = 0x02; break; case TECO_COLOR: window[33] = 0x05; break; } /* Depth */ window[34] = dev->depth; /* Unknown - invariants */ window[31] = 0x80; window[37] = 0x80; window[55] = 0x80; window[57] = 0x80; window[59] = 0x80; window[61] = 0x80; window[65] = 0x80; window[67] = 0x80; window[69] = 0x80; window[71] = 0x80; window[73] = 0x80; window[75] = 0x80; window[77] = 0x80; window[79] = 0x80; window[85] = 0xff; window[89] = 0xff; window[93] = 0xff; window[97] = 0xff; hexdump (DBG_info2, "windows", window, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, window, size, NULL, NULL); DBG (DBG_proc, "teco_set_window: exit, status=%d\n", status); return status; } /* Return the number of byte that can be read. */ static SANE_Status get_filled_data_length (Teco_Scanner * dev, size_t * to_read) { size_t size; CDB cdb; SANE_Status status; DBG (DBG_proc, "get_filled_data_length: enter\n"); *to_read = 0; size = 0x12; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (size < 0x10) { DBG (DBG_error, "get_filled_data_length: not enough data returned (%ld)\n", (long) size); } hexdump (DBG_info2, "get_filled_data_length return", dev->buffer, size); *to_read = B24TOI (&dev->buffer[9]); DBG (DBG_info, "%d %d - %d %d\n", dev->params.lines, B16TOI (&dev->buffer[12]), dev->params.bytes_per_line, B16TOI (&dev->buffer[14])); if (dev->real_bytes_left == 0) { /* Beginning of a scan. */ dev->params.lines = B16TOI (&dev->buffer[12]); switch (dev->scan_mode) { case TECO_BW: dev->params.bytes_per_line = B16TOI (&dev->buffer[14]); dev->params.pixels_per_line = dev->params.bytes_per_line * 8; break; case TECO_GRAYSCALE: dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); dev->params.bytes_per_line = dev->params.pixels_per_line; break; case TECO_COLOR: dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); if (dev->def->pass == 3) { dev->params.bytes_per_line = dev->params.pixels_per_line; } else { dev->params.bytes_per_line = dev->params.pixels_per_line * 3; } break; } } DBG (DBG_info, "get_filled_data_length: to read = %ld\n", (long) *to_read); DBG (DBG_proc, "get_filled_data_length: exit, status=%d\n", status); return (status); } /* Start a scan. */ static SANE_Status teco_scan (Teco_Scanner * dev) { CDB cdb; SANE_Status status; DBG (DBG_proc, "teco_scan: enter\n"); MKSCSI_SCAN (cdb); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "teco_scan: exit, status=%d\n", status); return status; } #if 0 /* Do some vendor specific stuff. */ static SANE_Status teco_vendor_spec (Teco_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; DBG (DBG_proc, "teco_vendor_spec: enter\n"); size = 0x7800; cdb.data[0] = 0x09; cdb.data[1] = 0; cdb.data[2] = 0; cdb.data[3] = (size >> 8) & 0xff; cdb.data[4] = (size >> 0) & 0xff; cdb.data[5] = 0; cdb.len = 6; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); /*hexdump (DBG_info2, "calibration:", dev->buffer, size); */ cdb.data[0] = 0x0E; cdb.data[1] = 0; cdb.data[2] = 0; cdb.data[3] = 0; cdb.data[4] = 0; cdb.data[5] = 0; cdb.len = 6; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); return status; } #endif /* Send the gamma * The order is RGB. The last color is unused. * G is also the gray gamma (if gray scan). * * Some scanner have 4 tables of 256 bytes, and some 4 tables of 1024 bytes. */ static SANE_Status teco_send_gamma (Teco_Scanner * dev) { CDB cdb; SANE_Status status; struct { unsigned char gamma[4 * MAX_GAMMA_LENGTH]; } param; size_t i; size_t size; DBG (DBG_proc, "teco_send_gamma: enter\n"); size = 4 * GAMMA_LENGTH; MKSCSI_SEND_10 (cdb, 0x03, 0x02, size); if (dev->val[OPT_CUSTOM_GAMMA].w) { /* Use the custom gamma. */ if (dev->scan_mode == TECO_GRAYSCALE) { /* Gray */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma[0 * GAMMA_LENGTH + i] = 0; param.gamma[1 * GAMMA_LENGTH + i] = dev->gamma_GRAY[i]; param.gamma[2 * GAMMA_LENGTH + i] = 0; param.gamma[3 * GAMMA_LENGTH + i] = 0; } } else { /* Color */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma[0 * GAMMA_LENGTH + i] = dev->gamma_R[i]; param.gamma[1 * GAMMA_LENGTH + i] = dev->gamma_G[i]; param.gamma[2 * GAMMA_LENGTH + i] = dev->gamma_B[i]; param.gamma[3 * GAMMA_LENGTH + i] = 0; } } } else { if (dev->scan_mode == TECO_BW) { /* Map threshold from a 0..255 scale to a * 0..GAMMA_LENGTH scale. */ unsigned int threshold = dev->val[OPT_THRESHOLD].w * (GAMMA_LENGTH / 256); for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma[0 * GAMMA_LENGTH + i] = 0; if (i < threshold) param.gamma[1 * GAMMA_LENGTH + i] = 0; else param.gamma[1 * GAMMA_LENGTH + i] = 255; param.gamma[2 * GAMMA_LENGTH + i] = 0; param.gamma[3 * GAMMA_LENGTH + i] = 0; } } else { /* * Shift is 1 for GAMMA_LENGTH == 256 * and 4 for GAMMA_LENGTH == 1024 */ int shift = GAMMA_LENGTH >> 8; for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma[0 * GAMMA_LENGTH + i] = i / shift; param.gamma[1 * GAMMA_LENGTH + i] = i / shift; param.gamma[2 * GAMMA_LENGTH + i] = i / shift; param.gamma[3 * GAMMA_LENGTH + i] = 0; } } } hexdump (DBG_info2, "teco_send_gamma:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, ¶m, size, NULL, NULL); DBG (DBG_proc, "teco_send_gamma: exit, status=%d\n", status); return (status); } /* Attach a scanner to this backend. */ static SANE_Status attach_scanner (const char *devicename, Teco_Scanner ** devp) { Teco_Scanner *dev; int sfd; DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); if (devp) *devp = NULL; /* Check if we know this device name. */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (DBG_info, "device is already known\n"); return SANE_STATUS_GOOD; } } /* Allocate a new scanner entry. */ dev = teco_init (); if (dev == NULL) { DBG (DBG_error, "ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_scanner: opening %s\n", devicename); if (sanei_scsi_open (devicename, &sfd, teco_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: attach_scanner: open failed\n"); teco_free (dev); return SANE_STATUS_INVAL; } /* Fill some scanner specific values. */ dev->devicename = strdup (devicename); dev->sfd = sfd; /* Now, check that it is a scanner we support. */ if (teco_identify_scanner (dev) == SANE_FALSE) { DBG (DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); teco_free (dev); return SANE_STATUS_INVAL; } /* Get the page 0x82. It doesn't appear to be usefull yet. */ teco_get_inquiry_82 (dev); teco_close (dev); /* Set the default options for that scanner. */ dev->sane.name = dev->devicename; dev->sane.vendor = dev->def->real_vendor; dev->sane.model = dev->def->real_product; dev->sane.type = "flatbed scanner"; /* Link the scanner with the others. */ dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } num_devices++; DBG (DBG_proc, "attach_scanner: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach_scanner (dev, NULL); return SANE_STATUS_GOOD; } /* Reset the options for that scanner. */ static void teco_init_options (Teco_Scanner * dev) { int i; /* Pre-initialize the options. */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < OPT_NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options. */ dev->opt[OPT_NUM_OPTS].name = ""; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; /* Mode group */ dev->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].cap = 0; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scanner supported modes */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = max_string_size (scan_mode_list); dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = scan_mode_list; dev->val[OPT_MODE].s = (SANE_Char *) strdup (""); /* will be set later */ /* X and Y resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RESOLUTION].constraint.range = &dev->def->res_range; dev->val[OPT_RESOLUTION].w = 100; /* Geometry group */ dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_GEOMETRY_GROUP].cap = 0; dev->opt[OPT_GEOMETRY_GROUP].size = 0; dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Upper left X */ dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &x_range; dev->val[OPT_TL_X].w = x_range.min; /* Upper left Y */ dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &y_range; dev->val[OPT_TL_Y].w = y_range.min; /* Bottom-right x */ dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &x_range; dev->val[OPT_BR_X].w = x_range.max; /* Bottom-right y */ dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &y_range; dev->val[OPT_BR_Y].w = y_range.max; /* Enhancement group */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Halftone pattern */ dev->opt[OPT_DITHER].name = "dither"; dev->opt[OPT_DITHER].title = SANE_I18N ("Dither"); dev->opt[OPT_DITHER].desc = SANE_I18N ("Dither"); dev->opt[OPT_DITHER].type = SANE_TYPE_STRING; dev->opt[OPT_DITHER].size = max_string_size (dither_list); dev->opt[OPT_DITHER].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_DITHER].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_DITHER].constraint.string_list = dither_list; dev->val[OPT_DITHER].s = strdup (dither_list[0]); /* custom-gamma table */ dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* red gamma vector */ dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_R].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_R].wa = dev->gamma_R; /* green and gamma vector */ dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_G].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_G].wa = dev->gamma_G; /* blue gamma vector */ dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_B].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_B].wa = dev->gamma_B; /* grayscale gamma vector */ dev->opt[OPT_GAMMA_VECTOR_GRAY].name = SANE_NAME_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].title = SANE_TITLE_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].desc = SANE_DESC_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_GRAY].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_GRAY].wa = dev->gamma_GRAY; /* Threshold */ dev->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; dev->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; dev->opt[OPT_THRESHOLD].size = sizeof (SANE_Int); dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_THRESHOLD].constraint.range = &threshold_range; dev->val[OPT_THRESHOLD].w = 128; /* preview */ dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; dev->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; dev->val[OPT_PREVIEW].w = SANE_FALSE; /* Lastly, set the default scan mode. This might change some * values previously set here. */ sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, (SANE_String_Const *) scan_mode_list[0], NULL); } /* * Wait until the scanner is ready. */ static SANE_Status teco_wait_scanner (Teco_Scanner * dev) { SANE_Status status; int timeout; CDB cdb; DBG (DBG_proc, "teco_wait_scanner: enter\n"); MKSCSI_TEST_UNIT_READY (cdb); /* Set the timeout to 60 seconds. */ timeout = 60; while (timeout > 0) { /* test unit ready */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); if (status == SANE_STATUS_GOOD) { return SANE_STATUS_GOOD; } sleep (1); }; DBG (DBG_proc, "teco_wait_scanner: scanner not ready\n"); return (SANE_STATUS_IO_ERROR); } /* Read the image from the scanner and fill the temporary buffer with it. */ static SANE_Status teco_fill_image (Teco_Scanner * dev) { SANE_Status status; size_t size; CDB cdb; unsigned char *image; DBG (DBG_proc, "teco_fill_image: enter\n"); assert (dev->image_begin == dev->image_end); assert (dev->real_bytes_left > 0); dev->image_begin = 0; dev->image_end = 0; while (dev->real_bytes_left) { /* * Try to read the maximum number of bytes. */ size = 0; while (size == 0) { status = get_filled_data_length (dev, &size); if (status) return (status); if (size == 0) usleep (100000); /* sleep 1/10th of second */ } if (size > dev->real_bytes_left) size = dev->real_bytes_left; if (size > dev->image_size - dev->image_end) size = dev->image_size - dev->image_end; /* Always read a multiple of a line. */ size = size - (size % dev->params.bytes_per_line); if (size == 0) { /* Probably reached the end of the buffer. * Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } DBG (DBG_info, "teco_fill_image: to read = %ld bytes (bpl=%d)\n", (long) size, dev->params.bytes_per_line); MKSCSI_READ_10 (cdb, 0, 0, size); hexdump (DBG_info2, "teco_fill_image: READ_10 CDB", cdb.data, 10); image = dev->image + dev->image_end; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, image, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "teco_fill_image: cannot read from the scanner\n"); return status; } /* The size this scanner returns is always a multiple of lines. */ assert ((size % dev->params.bytes_per_line) == 0); DBG (DBG_info, "teco_fill_image: real bytes left = %ld\n", (long) dev->real_bytes_left); if (dev->scan_mode == TECO_COLOR) { if (dev->def->pass == 1) { /* Reorder the lines. The scanner gives color by color for * each line. */ unsigned char *src = image; int nb_lines = size / dev->params.bytes_per_line; int i, j; for (i = 0; i < nb_lines; i++) { unsigned char *dest = dev->buffer; for (j = 0; j < dev->params.pixels_per_line; j++) { *dest = src[j + 0 * dev->params.pixels_per_line]; dest++; *dest = src[j + 1 * dev->params.pixels_per_line]; dest++; *dest = src[j + 2 * dev->params.pixels_per_line]; dest++; } /* Copy the line back. */ memcpy (src, dev->buffer, dev->params.bytes_per_line); src += dev->params.bytes_per_line; } } } dev->image_end += size; dev->real_bytes_left -= size; } return (SANE_STATUS_GOOD); /* unreachable */ } /* Copy from the raw buffer to the buffer given by the backend. * * len in input is the maximum length available in buf, and, in * output, is the length written into buf. */ static void teco_copy_raw_to_frontend (Teco_Scanner * dev, SANE_Byte * buf, size_t * len) { size_t size; size = dev->image_end - dev->image_begin; if (size > *len) { size = *len; } *len = size; switch (dev->scan_mode) { case TECO_BW: { /* Invert black and white. */ unsigned char *src = dev->image + dev->image_begin; size_t i; for (i = 0; i < size; i++) { *buf = *src ^ 0xff; src++; buf++; } } break; case TECO_GRAYSCALE: case TECO_COLOR: memcpy (buf, dev->image + dev->image_begin, size); break; } dev->image_begin += size; } /* Stop a scan. */ static SANE_Status do_cancel (Teco_Scanner * dev) { DBG (DBG_sane_proc, "do_cancel enter\n"); if (dev->scanning == SANE_TRUE) { /* Reset the scanner */ dev->x_resolution = 300; dev->y_resolution = 300; dev->x_tl = 0; dev->y_tl = 0; dev->width = 0; dev->length = 0; teco_set_window (dev); teco_scan (dev); teco_close (dev); } dev->scanning = SANE_FALSE; DBG (DBG_sane_proc, "do_cancel exit\n"); return SANE_STATUS_CANCELLED; } /*--------------------------------------------------------------------------*/ /* Sane entry points */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; char dev_name[PATH_MAX]; size_t len; DBG_INIT (); DBG (DBG_sane_init, "sane_init\n"); DBG (DBG_error, "This is sane-teco1 version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_error, "(C) 2002 by Frank Zago\n"); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); } fp = sanei_config_open (TECO_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach_scanner ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); DBG (DBG_proc, "sane_init: leave\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { Teco_Scanner *dev; int i; DBG (DBG_proc, "sane_get_devices: enter\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Teco_Scanner *dev; SANE_Status status; DBG (DBG_proc, "sane_open: enter\n"); /* search for devicename */ if (devicename[0]) { DBG (DBG_info, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); dev = first_dev; /* empty devicename -> use first device */ } if (!dev) { DBG (DBG_error, "No scanner found\n"); return SANE_STATUS_INVAL; } teco_init_options (dev); /* Initialize the gamma table. */ { /* * Shift is 1 for GAMMA_LENGTH == 256 * and 4 for GAMMA_LENGTH == 1024 */ int shift = GAMMA_LENGTH >> 8; size_t i; for (i = 0; i < GAMMA_LENGTH; i++) { dev->gamma_R[i] = i / shift; dev->gamma_G[i] = i / shift; dev->gamma_B[i] = i / shift; dev->gamma_GRAY[i] = i / shift; } } *handle = dev; DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); if ((unsigned) option >= OPT_NUM_OPTIONS) { return NULL; } DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return dev->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Teco_Scanner *dev = handle; SANE_Status status; SANE_Word cap; SANE_String_Const name; DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", option, action); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } name = dev->opt[option].name; if (!name) { name = "(no name)"; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_CUSTOM_GAMMA: case OPT_THRESHOLD: case OPT_PREVIEW: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_DITHER: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; /* Gamma */ case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (val, dev->val[option].wa, dev->opt[option].size); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Numeric side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* Numeric side-effect free options */ case OPT_THRESHOLD: case OPT_PREVIEW: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* String side-effect free options */ case OPT_DITHER: free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); return SANE_STATUS_GOOD; /* String side-effect options */ case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); dev->opt[OPT_DITHER].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, BLACK_WHITE_STR) == 0) { dev->depth = 8; dev->scan_mode = TECO_BW; dev->opt[OPT_DITHER].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, GRAY_STR) == 0) { dev->scan_mode = TECO_GRAYSCALE; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } dev->depth = 8; } else if (strcmp (dev->val[OPT_MODE].s, COLOR_STR) == 0) { dev->scan_mode = TECO_COLOR; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } dev->depth = 8; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (dev->val[option].wa, val, dev->opt[option].size); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: dev->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; if (dev->val[OPT_CUSTOM_GAMMA].w) { /* use custom_gamma_table */ if (dev->scan_mode == TECO_GRAYSCALE) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } else { /* color mode */ dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { /* Setup the parameters for the scan. These values will be re-used * in the SET WINDOWS command. */ if (dev->val[OPT_PREVIEW].w == SANE_TRUE) { dev->x_resolution = 22; dev->y_resolution = 22; dev->x_tl = 0; dev->y_tl = 0; dev->x_br = mmToIlu (SANE_UNFIX (x_range.max)); dev->y_br = mmToIlu (SANE_UNFIX (y_range.max)); } else { dev->x_resolution = dev->val[OPT_RESOLUTION].w; dev->y_resolution = dev->val[OPT_RESOLUTION].w; if (dev->x_resolution > dev->def->x_resolution_max) { dev->x_resolution = dev->def->x_resolution_max; } dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); } /* Check the corners are OK. */ if (dev->x_tl > dev->x_br) { int s; s = dev->x_tl; dev->x_tl = dev->x_br; dev->x_br = s; } if (dev->y_tl > dev->y_br) { int s; s = dev->y_tl; dev->y_tl = dev->y_br; dev->y_br = s; } dev->width = dev->x_br - dev->x_tl; dev->length = dev->y_br - dev->y_tl; /* Prepare the parameters for the caller. */ memset (&dev->params, 0, sizeof (SANE_Parameters)); dev->params.last_frame = SANE_TRUE; switch (dev->scan_mode) { case TECO_BW: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / 300) & ~0x7; dev->params.bytes_per_line = dev->params.pixels_per_line / 8; dev->params.depth = 1; dev->pass = 1; break; case TECO_GRAYSCALE: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / 300); dev->params.bytes_per_line = dev->params.pixels_per_line; dev->params.depth = 8; dev->pass = 1; break; case TECO_COLOR: dev->params.format = SANE_FRAME_RGB; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / 300); dev->pass = dev->def->pass; dev->params.bytes_per_line = dev->params.pixels_per_line * 3; dev->params.depth = 8; break; } dev->params.lines = (dev->length * dev->y_resolution) / 300; } /* Return the current values. */ if (params) { *params = (dev->params); } DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Teco_Scanner *dev = handle; SANE_Status status; size_t size; DBG (DBG_proc, "sane_start: enter\n"); if (!(dev->scanning)) { /* Open again the scanner. */ if (sanei_scsi_open (dev->devicename, &(dev->sfd), teco_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: sane_start: open failed\n"); return SANE_STATUS_INVAL; } /* Set the correct parameters. */ sane_get_parameters (dev, NULL); /* The scanner must be ready. */ status = teco_wait_scanner (dev); if (status) { teco_close (dev); return status; } status = teco_mode_select (dev); if (status) { teco_close (dev); return status; } if (dev->scan_mode == TECO_COLOR) { dev->pass = dev->def->pass; } else { dev->pass = 1; } if (dev->def->tecoref != TECO_VM3510) { status = teco_set_window (dev); if (status) { teco_close (dev); return status; } dev->real_bytes_left = 0; status = get_filled_data_length (dev, &size); if (status) { teco_close (dev); return status; } } #if 0 /* The windows driver does that, but some scanners don't like it. */ teco_vendor_spec (dev); if (status) { teco_close (dev); return status; } #endif status = teco_send_gamma (dev); if (status) { teco_close (dev); return status; } status = teco_set_window (dev); if (status) { teco_close (dev); return status; } status = teco_scan (dev); if (status) { teco_close (dev); return status; } if (dev->def->tecoref == TECO_VM3510) { dev->real_bytes_left = 0; status = get_filled_data_length (dev, &size); if (status) { teco_close (dev); return status; } } } else { /* Scan has already started. */ dev->pass--; } /* Set the frame parameter. */ if (dev->scan_mode == TECO_COLOR && dev->def->pass > 1) { SANE_Frame frames[] = { 0, SANE_FRAME_BLUE, SANE_FRAME_GREEN, SANE_FRAME_RED }; dev->params.format = frames[dev->pass]; } /* Is it the last frame? */ if (dev->pass > 1) { dev->params.last_frame = SANE_FALSE; } else { dev->params.last_frame = SANE_TRUE; } dev->image_end = 0; dev->image_begin = 0; dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->real_bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->scanning = SANE_TRUE; DBG (DBG_proc, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status status; Teco_Scanner *dev = handle; size_t size; int buf_offset; /* offset into buf */ DBG (DBG_proc, "sane_read: enter\n"); *len = 0; if (!(dev->scanning)) { /* OOPS, not scanning */ return do_cancel (dev); } if (dev->bytes_left <= 0) { return (SANE_STATUS_EOF); } buf_offset = 0; do { if (dev->image_begin == dev->image_end) { /* Fill image */ status = teco_fill_image (dev); if (status != SANE_STATUS_GOOD) { return (status); } } /* Something must have been read */ if (dev->image_begin == dev->image_end) { DBG (DBG_info, "sane_read: nothing read\n"); return SANE_STATUS_IO_ERROR; } /* Copy the data to the frontend buffer. */ size = max_len - buf_offset; if (size > dev->bytes_left) { size = dev->bytes_left; } teco_copy_raw_to_frontend (dev, buf + buf_offset, &size); buf_offset += size; dev->bytes_left -= size; *len += size; } while ((buf_offset != max_len) && dev->bytes_left); DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", (long) dev->bytes_left); return SANE_STATUS_GOOD; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { SANE_Status status; Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_set_io_mode: enter\n"); if (dev->scanning == SANE_FALSE) { return SANE_STATUS_INVAL; } if (non_blocking == SANE_FALSE) { status = SANE_STATUS_GOOD; } else { status = SANE_STATUS_UNSUPPORTED; } DBG (DBG_proc, "sane_set_io_mode: exit\n"); return status; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd) { DBG (DBG_proc, "sane_get_select_fd: enter\n"); DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } void sane_cancel (SANE_Handle handle) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_cancel: enter\n"); do_cancel (dev); DBG (DBG_proc, "sane_cancel: exit\n"); } void sane_close (SANE_Handle handle) { Teco_Scanner *dev = handle; Teco_Scanner *dev_tmp; DBG (DBG_proc, "sane_close: enter\n"); do_cancel (dev); teco_close (dev); /* Unlink dev. */ if (first_dev == dev) { first_dev = dev->next; } else { dev_tmp = first_dev; while (dev_tmp->next && dev_tmp->next != dev) { dev_tmp = dev_tmp->next; } if (dev_tmp->next != NULL) { dev_tmp->next = dev_tmp->next->next; } } teco_free (dev); num_devices--; DBG (DBG_proc, "sane_close: exit\n"); } void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); while (first_dev) { sane_close (first_dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); } sane-backends-1.0.27/backend/tamarack.h0000664000175000017500000001330512112021330014530 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang Copyright (C) 1997 R.E.Wolff@BitWizard.nl This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef tamarack_h #define tamarack_h #include #define TAMARACK_FLAG_TA (1 << 3) /* transparency adapter */ enum Tamarack_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, #define OPT_MODE_DEFAULT 2 OPT_RESOLUTION, #define OPT_RESOLUTION_DEFAULT 100 #if 0 OPT_SPEED, OPT_SOURCE, OPT_BACKTRACK, #endif OPT_PREVIEW, OPT_GRAY_PREVIEW, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_TRANS, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_THRESHOLD, #if 0 OPT_CUSTOM_GAMMA, /* use custom gamma tables? */ /* The gamma vectors MUST appear in the order gray, red, green, blue. */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_HALFTONE_DIMENSION, OPT_HALFTONE_PATTERN, #endif /* must come last: */ NUM_OPTIONS }; typedef struct Tamarack_Device { struct Tamarack_Device *next; SANE_Device sane; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; unsigned flags; } Tamarack_Device; typedef struct Tamarack_Scanner { /* all the state needed to define a scan request: */ struct Tamarack_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Int gamma_table[4][256]; #if 0 SANE_Int halftone_pattern[64]; #endif int scanning; int pass; /* pass number */ int line; /* current line number */ SANE_Parameters params; /* Parsed option values and variables that are valid only during actual scanning: */ int mode; #if 0 int one_pass_color_scan; int resolution_code; #endif int fd; /* SCSI filedescriptor */ SANE_Pid reader_pid; /* process id of reader */ int pipe; /* pipe to reader process */ int reader_pipe; /* pipe from reader process */ /* scanner dependent/low-level state: */ Tamarack_Device *hw; #if 0 /* line-distance correction related state: */ struct { int max_value; int peak_res; struct { int dist; /* line distance */ int Qk; } c[3]; /* these are used in the MLD_MFS mode only: */ char *red_buf; char *green_buf; } ld; #endif } Tamarack_Scanner; #define TAM_ADF_ON 0x80 #define TAM_DOUBLE_ON 0x40 #define TAM_TRANS_ON 0x20 #define TAM_INVERSE_ON 0x20 #define THRESHOLDED 0 #define DITHERED 1 #define GREYSCALE 2 #define TRUECOLOR 3 /* Some Tamarack driver internal defines */ #define WINID 0 /* SCSI commands that the Tamarack scanners understand: */ #define TAMARACK_SCSI_TEST_UNIT_READY 0x00 #define TAMARACK_SCSI_INQUIRY 0x12 #define TAMARACK_SCSI_MODE_SELECT 0x15 #define TAMARACK_SCSI_START_STOP 0x1b #define TAMARACK_SCSI_AREA_AND_WINDOWS 0x24 #define TAMARACK_SCSI_READ_SCANNED_DATA 0x28 #define TAMARACK_SCSI_GET_DATA_STATUS 0x34 /* The structures that you have to send to the tamarack to get it to do various stuff... */ struct win_desc_header { unsigned char pad0[6]; unsigned char wpll[2]; }; struct win_desc_block { unsigned char winid; unsigned char pad0; unsigned char xres[2]; unsigned char yres[2]; unsigned char ulx[4]; unsigned char uly[4]; unsigned char width[4]; unsigned char length[4]; unsigned char brightness; unsigned char thresh; unsigned char contrast; unsigned char image_comp; unsigned char bpp; unsigned char halftone[2]; unsigned char pad_type; unsigned char exposure; unsigned char pad3; unsigned char compr_type; unsigned char pad4[5]; }; struct command_header { unsigned char opc; unsigned char pad0[3]; unsigned char len; unsigned char pad1; }; struct command_header_10 { unsigned char opc; unsigned char pad0[5]; unsigned char len[3]; unsigned char pad1; }; struct def_win_par { struct command_header_10 dwph; struct win_desc_header wdh; struct win_desc_block wdb; }; struct page_header{ char pad0[4]; char code; char length; }; struct tamarack_page { char gamma; unsigned char thresh; unsigned char masks; char delay; char features; char pad0; }; /* set SCSI highended variables. Declare them as an array of chars */ /* endianness-safe, int-size safe... */ #define set_double(var,val) var[0] = ((val) >> 8) & 0xff; \ var[1] = ((val) ) & 0xff; #define set_triple(var,val) var[0] = ((val) >> 16) & 0xff; \ var[1] = ((val) >> 8 ) & 0xff; \ var[2] = ((val) ) & 0xff; #define set_quad(var,val) var[0] = ((val) >> 24) & 0xff; \ var[1] = ((val) >> 16) & 0xff; \ var[2] = ((val) >> 8 ) & 0xff; \ var[3] = ((val) ) & 0xff; #endif /* tamarack_h */ sane-backends-1.0.27/backend/abaton.h0000664000175000017500000000705712112021330014220 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998 David Huggins-Daines, heavily based on the Apple scanner driver (since Abaton scanners are very similar to old Apple scanners), which is (C) 1998 Milon Firikis, which is, in turn, based on the Mustek driver, (C) 1996-7 David Mosberger-Tang. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef abaton_h #define abaton_h #include enum Abaton_Modes { ABATON_MODE_LINEART=0, ABATON_MODE_HALFTONE, ABATON_MODE_GRAY }; enum Abaton_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_X_RESOLUTION, OPT_Y_RESOLUTION, OPT_RESOLUTION_BIND, OPT_PREVIEW, OPT_HALFTONE_PATTERN, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_THRESHOLD, OPT_NEGATIVE, OPT_MIRROR, /* must come last: */ NUM_OPTIONS }; enum ScannerModels { ABATON_300GS, ABATON_300S }; typedef struct Abaton_Device { struct Abaton_Device *next; SANE_Int ScannerModel; SANE_Device sane; SANE_Range dpi_range; unsigned flags; } Abaton_Device; typedef struct Abaton_Scanner { /* all the state needed to define a scan request: */ struct Abaton_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Bool scanning; SANE_Bool AbortedByUser; SANE_Parameters params; /* The actual bpp, before "Pseudo-8-bit" fiddling */ SANE_Int bpp; /* window, in pixels */ SANE_Int ULx; SANE_Int ULy; SANE_Int Width; SANE_Int Height; int fd; /* SCSI filedescriptor */ /* scanner dependent/low-level state: */ Abaton_Device *hw; } Abaton_Scanner; #endif /* abaton_h */ sane-backends-1.0.27/backend/sharp.conf.in0000664000175000017500000000267012112021330015170 00000000000000# The options are only meaningful if the backend was # compiled with USE_FORK defined # # option buffersize: size of one buffer allocated as shared # memory for data transfer between the reader process # and the parent process # option buffers: number of these buffers # The minimum is 2 # option readqueue: number of queued read requests. This is # with the current SANE version (1.01) only useful for # Linux, since queued read requests are not supported # for other operating systems. # # For Linux, a value of 2 is recommended, at least if a # JX-250 is used. Bigger values are only a waste of memory. # # For other operationg systems, set this value to zero # # option stop_on_fsu_error: should be 0 or 1. If set to 0, # the "FSU light dispersion error" does not cause the abortion # of a scan. # # option default_scan_source: valid values are "auto", "fsu", "adf" # and "flatbed". For "auto", the backend will enable an ADF or # or FSU, if installed. # # global options: option buffers 4 option buffersize 131072 option readqueue 2 option stop_on_fsu_error 1 option default_scan_source auto # look for all devices with vendor ID "SHARP" and type "Scanner" scsi SHARP * Scanner # no options specific to these devices listed -> use global options /dev/scanner # options specific to /dev/scanner option buffers 6 option buffersize 262144 option readqueue 2 # example for another (Linux) device name: #/dev/sg1 sane-backends-1.0.27/backend/umax-ug80.c0000664000175000017500000001034312112021330014472 00000000000000/* ------------------------------------------------------------------------- */ /* umax-ug80.c: inquiry for UMAX scanner ug80 (C) 1998-2002 Oliver Rauch Thanks to Andreas Hofmeister for his help! This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------- */ #include "umax-scanner.h" /* ------------------------------------------------------------------------- */ static unsigned char UG80_INQUIRY[] = { #define UG80_INQUIRY_LEN 0x94 /* 24 F/W support function */ 0x00, /* 25 -27 exposure-times */ 0x00, 0x00, 0x00, /* 28 - 29 reserved */ 0x00, 0x00, /* 2a - 35 exposure times */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 37 reserved */ 0x00, 0x00, /* 38 - 5f scsi reserved */ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, /* 60 -62 scanner capability */ 0xdc, 0xb4, 0x03, /* ? */ /* 63 reserved */ 0x00, /* 64 gamma */ 0xa1, /* 65 reserved */ 0x00, /* 66 GIB */ 0x01, /* 67 reserved */ 0x00, /* 68 GOB */ 0x01, /* 69 - 6a halftone */ 0x88, 0x21, /* ? */ /* 6b - 6c reserved */ 0x00, 0x00, /* 6d color sequence */ 0x05, /* 6e - 71 video memory */ 0x00, 0x01, 0x00, 0x00, /* 72 reserved */ 0x00, /* 73 max optical res in 100 dpi */ 0x03, /* 74 max x_res in 100 dpi */ 0x03, /* 75 max y_res in 100 dpi */ 0x03, /* 76-77 fb max scan width in 0.01 inch */ 0x03, 0x52, /* 78-79 fb max scan length in 0.01 inch */ 0x05, 0x78, /* 7a-7b uta x original point */ 0x00, 0x76, /* 7c-7d uta y original point */ 0x00, 0x89, /* 7e-7f uta max scan width in 0.01 inch */ 0x02, 0x4e, /* 80-81 uta max scan length in 0.01 inch */ 0x05, 0x78, /* 82-85 reserved */ 00, 00, 00, 00, /* 86-87 dor x original point */ 0x00, 0x00, /* 88-89 dor x original point */ 0x00, 0x00, /* 8a-8b dor max scan width in 0.01 inch */ 0x00, 0x00, /* 8c-8d dor max scan length in 0.01 inch */ 0x00, 0x00, /* 8e reserved */ 0x00, /* 8f last calibration lamp density */ 0x00, /* 90 reserved */ 0x00, /* 91 lamp warmup max time */ 0x00, /* 92-93 window descriptor block length */ 0x00, 0x30, /* 94 optical resolution residue (1dpi) */ 0x00, /* 95 x_resolution residue (1dpi) */ 0x00, /* 96 y_resolution residue (1dpi) */ 0x00, /* 97 analog gamma table */ 0x00, /* 98-99 reserved */ 0x00, 0x00, /* 9a max calibration data lines */ 0x00 }; static inquiry_blk inquiry_ug80 = { "UG80 ",UG80_INQUIRY,UG80_INQUIRY_LEN, }; sane-backends-1.0.27/backend/pie.conf.in0000664000175000017500000000011312112021330014616 00000000000000scsi DEVCOM * Scanner scsi PIE * Scanner scsi AdLib * Scanner /dev/scanner sane-backends-1.0.27/backend/tamarack.c0000664000175000017500000011600412775312261014550 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996 David Mosberger-Tang Copyright (C) 1997 R.E.Wolff@BitWizard.nl This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Note: The exception that is mentioned in the other source files is not here. If a case arises where you need the rights that that exception gives you, Please do contact me, and we'll work something out. R.E.Wolff@BitWizard.nl tel: +31-152137555 fax: +31-152138217 This file implements a SANE backend for Tamarack flatbed scanners. */ /* This driver was written initially by changing all occurances of "mustek" to "tamarack". This actuall worked without modification for the manufacturer detection code! :-) */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_thread.h" #include "../include/sane/sanei_config.h" /* For timeval... */ #ifdef DEBUG #include #endif #define BACKEND_NAME tamarack #include "../include/sane/sanei_backend.h" #include "tamarack.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define TAMARACK_CONFIG_FILE "tamarack.conf" static const SANE_Device **devlist = NULL; static int num_devices; static Tamarack_Device *first_dev; static Tamarack_Scanner *first_handle; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /* David used " 100 << SANE_FIXED_SCALE_SHIFT ". This assumes that * it is implemented that way. I want to hide the datatype. */ static const SANE_Range percentage_range = { SANE_FIX(-100), /* minimum */ SANE_FIX( 100), /* maximum */ SANE_FIX( 1 ) /* quantization */ }; /* David used " 100 << SANE_FIXED_SCALE_SHIFT ". This assumes that * it is implemented that way. I want to hide the datatype. */ static const SANE_Range abs_percentage_range = { SANE_FIX( 0), /* minimum */ SANE_FIX( 100), /* maximum */ SANE_FIX( 1 ) /* quantization */ }; #define INQ_LEN 0x60 static const uint8_t inquiry[] = { TAMARACK_SCSI_INQUIRY, 0x00, 0x00, 0x00, INQ_LEN, 0x00 }; static const uint8_t test_unit_ready[] = { TAMARACK_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t stop[] = { TAMARACK_SCSI_START_STOP, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t get_status[] = { TAMARACK_SCSI_GET_DATA_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00 }; static SANE_Status wait_ready (int fd) { SANE_Status status; int i; for (i = 0; i < 1000; ++i) { DBG(3, "wait_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG(1, "wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; } } DBG(1, "wait_ready: timed out after %d attempts\n", i); return SANE_STATUS_INVAL; } static SANE_Status sense_handler (int scsi_fd, u_char *result, void *arg) { scsi_fd = scsi_fd; arg = arg; /* silence compilation warnings */ switch (result[0]) { case 0x00: break; default: DBG(1, "sense_handler: got unknown sense code %02x\n", result[0]); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* XXX This might leak the memory to a TAMARACK string */ static SANE_Status attach (const char *devname, Tamarack_Device **devp) { char result[INQ_LEN]; int fd; Tamarack_Device *dev; SANE_Status status; size_t size; char *mfg, *model; char *p; for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } DBG(3, "attach: opening %s\n", devname); status = sanei_scsi_open (devname, &fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG(1, "attach: open failed (%s)\n", sane_strstatus (status)); return SANE_STATUS_INVAL; } DBG(3, "attach: sending INQUIRY\n"); size = sizeof (result); status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size); if (status != SANE_STATUS_GOOD || size != INQ_LEN) { DBG(1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } status = wait_ready (fd); sanei_scsi_close (fd); if (status != SANE_STATUS_GOOD) return status; result[33]= '\0'; p = strchr(result+16,' '); if (p) *p = '\0'; model = strdup (result+16); result[16]= '\0'; p = strchr(result+8,' '); if (p) *p = '\0'; mfg = strdup (result+8); DBG(1, "attach: Inquiry gives mfg=%s, model=%s.\n", mfg, model); if (strcmp (mfg, "TAMARACK") != 0) { DBG(1, "attach: device doesn't look like a Tamarack scanner " "(result[0]=%#02x)\n", result[0]); return SANE_STATUS_INVAL; } dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devname); dev->sane.vendor = "Tamarack"; dev->sane.model = model; dev->sane.type = "flatbed scanner"; dev->x_range.min = 0; dev->y_range.min = 0; dev->x_range.quant = 0; dev->y_range.quant = 0; dev->dpi_range.min = SANE_FIX (1); dev->dpi_range.quant = SANE_FIX (1); dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.max = SANE_FIX (11.0 * MM_PER_INCH); dev->dpi_range.max = SANE_FIX (600); DBG(3, "attach: found Tamarack scanner model %s (%s)\n", dev->sane.model, dev->sane.type); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status constrain_value (Tamarack_Scanner *s, SANE_Int option, void *value, SANE_Int *info) { return sanei_constrain_value (s->opt + option, value, info); } static unsigned char sign_mag (double val) { if (val > 100) val = 100; if (val < -100) val = -100; if (val >= 0) return ( val); else return ((unsigned char)(-val)) | 0x80; } static SANE_Status scan_area_and_windows (Tamarack_Scanner *s) { struct def_win_par dwp; memset (&dwp,'\0',sizeof (dwp)); dwp.dwph.opc = TAMARACK_SCSI_AREA_AND_WINDOWS; set_triple (dwp.dwph.len,8 + sizeof (dwp.wdb)); set_double (dwp.wdh.wpll, sizeof (dwp.wdb)); dwp.wdb.winid = WINID; set_double (dwp.wdb.xres, (int) SANE_UNFIX (s->val[OPT_RESOLUTION].w)); set_double (dwp.wdb.yres, (int) SANE_UNFIX (s->val[OPT_RESOLUTION].w)); set_quad (dwp.wdb.ulx, (int) (47.2 * SANE_UNFIX (s->val[OPT_TL_X].w))); set_quad (dwp.wdb.uly, (int) (47.2 * SANE_UNFIX (s->val[OPT_TL_Y].w))); set_quad (dwp.wdb.width, (int) (47.2 * SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w))); set_quad (dwp.wdb.length, (int) (47.2 * SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w))); dwp.wdb.brightness = sign_mag (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)); dwp.wdb.contrast = sign_mag (SANE_UNFIX (s->val[OPT_CONTRAST].w)); dwp.wdb.thresh = 0x80; switch (s->mode) { case THRESHOLDED: dwp.wdb.bpp = 1; dwp.wdb.image_comp = 0; dwp.wdb.thresh = 1 + 2.55 * (SANE_UNFIX (s->val[OPT_THRESHOLD].w)); break; case DITHERED: dwp.wdb.bpp = 1; dwp.wdb.image_comp = 1; break; case GREYSCALE: dwp.wdb.bpp = 8; dwp.wdb.image_comp = 2; break; case TRUECOLOR: dwp.wdb.bpp = 8; dwp.wdb.image_comp = 2; break; default: DBG(1, "Invalid mode. %d\n", s->mode); return SANE_STATUS_INVAL; } DBG(1, "bright, thresh, contrast = %d(%5.1f), %d, %d(%5.1f)\n", dwp.wdb.brightness, SANE_UNFIX (s->val[OPT_BRIGHTNESS].w), dwp.wdb.thresh , dwp.wdb.contrast , SANE_UNFIX (s->val[OPT_CONTRAST].w)); set_double (dwp.wdb.halftone, 1); /* XXX What does this do again ? */ dwp.wdb.pad_type = 3; /* This is the only usable pad-type. */ dwp.wdb.exposure = 0x6f; /* XXX Option? */ dwp.wdb.compr_type = 0; /* XXX Shouldn't this be sizeof (dwp) */ return sanei_scsi_cmd (s->fd, &dwp, (10+8+38), 0, 0); } static SANE_Status mode_select (Tamarack_Scanner *s) { struct { struct command_header cmd; struct page_header hdr; struct tamarack_page page; } c; memset (&c, '\0', sizeof (c)); c.cmd.opc = TAMARACK_SCSI_MODE_SELECT; c.cmd.pad0[0] = 0x10; /* Suddenly the pad bytes are no long pad... */ c.cmd.pad0[1] = 0; c.cmd.len = sizeof (struct page_header) + sizeof (struct tamarack_page); c.hdr.code = 0; c.hdr.length = 6; c.page.gamma = 2; c.page.thresh = 0x80; /* XXX Option? */ switch (s->mode) { case THRESHOLDED: case DITHERED: case GREYSCALE: c.page.masks = 0x80; break; case TRUECOLOR: c.page.masks = 0x40 >> s->pass; break; } c.page.delay = 0x10; /* XXX Option? */ c.page.features = (s->val[OPT_TRANS].w ? TAM_TRANS_ON:0) | 1; return sanei_scsi_cmd (s->fd, &c, sizeof (c), 0, 0); } static SANE_Status start_scan (Tamarack_Scanner *s) { struct { struct command_header cmd; unsigned char winid[1]; } c; memset (&c,'\0',sizeof (c)); c.cmd.opc = TAMARACK_SCSI_START_STOP; c.cmd.len = sizeof (c.winid); c.winid[0] = WINID; return sanei_scsi_cmd (s->fd, &c, sizeof (c), 0, 0); } static SANE_Status stop_scan (Tamarack_Scanner *s) { /* XXX I don't think a TAMARACK can stop in mid-scan. Just stop sending it requests for data.... */ return sanei_scsi_cmd (s->fd, stop, sizeof (stop), 0, 0); } static SANE_Status do_eof (Tamarack_Scanner *s) { if (s->pipe >= 0) { close (s->pipe); s->pipe = -1; } return SANE_STATUS_EOF; } static SANE_Status do_cancel (Tamarack_Scanner *s) { s->scanning = SANE_FALSE; s->pass = 0; do_eof (s); if (sanei_thread_is_valid (s->reader_pid)) { int exit_status; /* ensure child knows it's time to stop: */ sanei_thread_kill (s->reader_pid); sanei_thread_waitpid (s->reader_pid, &exit_status); s->reader_pid = -1; } if (s->fd >= 0) { stop_scan (s); sanei_scsi_close (s->fd); s->fd = -1; } return SANE_STATUS_CANCELLED; } static SANE_Status get_image_status (Tamarack_Scanner *s) { uint8_t result[12]; SANE_Status status; size_t len; int busy; #if 1 do { len = sizeof (result); status = sanei_scsi_cmd (s->fd, get_status, sizeof (get_status), result, &len); if ((status != SANE_STATUS_GOOD) && (status != SANE_STATUS_DEVICE_BUSY)) return status; busy = (result[2] != 8) || (status == SANE_STATUS_DEVICE_BUSY); if (busy) usleep (100000); if (!s->scanning) return do_cancel (s); } while (busy); #else /* XXX Test if this works one day... */ wait_ready (s); #endif len = sizeof (result); status = sanei_scsi_cmd (s->fd, get_status, sizeof (get_status), result, &len); if ((status != SANE_STATUS_GOOD) && (status != SANE_STATUS_DEVICE_BUSY)) return status; s->params.bytes_per_line = result[ 8] | (result[ 7] << 8) | (result[6] << 16); s->params.lines = result[11] | (result[10] << 8) | (result[9] << 16); switch (s->mode) { case DITHERED: case THRESHOLDED: s->params.pixels_per_line = 8 * s->params.bytes_per_line; break; case GREYSCALE: case TRUECOLOR: s->params.pixels_per_line = s->params.bytes_per_line; break; } DBG(1, "get_image_status: bytes_per_line=%d, lines=%d\n", s->params.bytes_per_line, s->params.lines); return SANE_STATUS_GOOD; } static SANE_Status read_data (Tamarack_Scanner *s, SANE_Byte *buf, int lines, int bpl) { struct command_header_10 cmd; size_t nbytes; SANE_Status status; #ifdef DEBUG int dt; struct timeval tv_start,tv_end; #endif nbytes = bpl * lines; memset (&cmd,'\0',sizeof (cmd)); cmd.opc = 0x28; set_triple (cmd.len,nbytes); #ifdef DEBUG if (verbose) DBG (1, "Doing read_data... \n"); gettimeofday (&tv_start,NULL); #endif status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, &nbytes); #ifdef DEBUG gettimeofday (&tv_end,NULL); dt = tv_end.tv_usec - tv_start.tv_usec + (tv_end.tv_sec - tv_start.tv_sec) * 1000000; if (verbose) DBG(1, "Read took %d.%06d seconds.", dt/1000000,dt%1000000); dt = 1000000 * nbytes / dt; if (verbose) DBG(1, "which is %d.%03d bytes per second.\n",dt,0); #endif return status; } static SANE_Status init_options (Tamarack_Scanner *s) { int i; memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = "Select the scan mode"; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[OPT_MODE_DEFAULT]); /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = SANE_FIX (OPT_RESOLUTION_DEFAULT); /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = 0; /* gray preview */ s->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_GRAY_PREVIEW].w = SANE_FALSE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* transparency adapter. */ s->opt[OPT_TRANS].name = "transparency"; s->opt[OPT_TRANS].title = "transparency"; s->opt[OPT_TRANS].desc = "Turn on the transparency adapter."; s->opt[OPT_TRANS].type = SANE_TYPE_BOOL; s->opt[OPT_TRANS].unit = SANE_UNIT_NONE; s->val[OPT_TRANS].w = SANE_FALSE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS " This option is active for lineart/halftone modes only. " "For multibit modes (grey/color) use the gamma-table(s)."; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; s->val[OPT_BRIGHTNESS].w = SANE_FIX(0); /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST " This option is active for lineart/halftone modes only. " "For multibit modes (grey/color) use the gamma-table(s)."; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; s->val[OPT_CONTRAST].w = SANE_FIX(0); /* Threshold */ s->opt[OPT_THRESHOLD].name = "Threshold"; s->opt[OPT_THRESHOLD].title = "Threshold"; s->opt[OPT_THRESHOLD].desc = "Threshold: below this level is black, above is white" " This option is active for bitmap modes only. "; s->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &abs_percentage_range; s->val[OPT_THRESHOLD].w = SANE_FIX(50); s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; #if 0 /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; #endif return SANE_STATUS_GOOD; } /* This function is executed as a child process. The reason this is executed as a subprocess is because some (most?) generic SCSI interfaces block a SCSI request until it has completed. With a subprocess, we can let it block waiting for the request to finish while the main process can go about to do more important things (such as recognizing when the user presses a cancel button). WARNING: Since this is executed as a subprocess, it's NOT possible to update any of the variables in the main process (in particular the scanner state cannot be updated). */ static int reader_process (void *scanner) { Tamarack_Scanner *s = (Tamarack_Scanner *) scanner; int fd = s->reader_pipe; SANE_Byte *data; int lines_per_buffer, bpl; SANE_Status status; sigset_t sigterm_set; sigset_t ignore_set; struct SIGACTION act; FILE *fp; if (sanei_thread_is_forked()) close (s->pipe); sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); #if defined (__APPLE__) && defined (__MACH__) sigdelset (&ignore_set, SIGUSR2); #endif sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); fp = fdopen (fd, "w"); if (!fp) return 1; bpl = s->params.bytes_per_line; lines_per_buffer = sanei_scsi_max_request_size / bpl; if (!lines_per_buffer) return 2; /* resolution is too high */ /* Limit the size of a single transfer to one inch. XXX Add a stripsize option. */ if (lines_per_buffer > SANE_UNFIX (s->val[OPT_RESOLUTION].w)) lines_per_buffer = SANE_UNFIX (s->val[OPT_RESOLUTION].w); DBG(3, "lines_per_buffer=%d, bytes_per_line=%d\n", lines_per_buffer, bpl); data = malloc (lines_per_buffer * bpl); for (s->line = 0; s->line < s->params.lines; s->line += lines_per_buffer) { if (s->line + lines_per_buffer > s->params.lines) /* do the last few lines: */ lines_per_buffer = s->params.lines - s->line; sigprocmask (SIG_BLOCK, &sigterm_set, 0); status = read_data (s, data, lines_per_buffer, bpl); sigprocmask (SIG_UNBLOCK, &sigterm_set, 0); if (status != SANE_STATUS_GOOD) { DBG(1, "reader_process: read_data failed with status=%d\n", status); return 3; } DBG(3, "reader_process: read %d lines\n", lines_per_buffer); if ((s->mode == TRUECOLOR) || (s->mode == GREYSCALE)) { fwrite (data, lines_per_buffer, bpl, fp); } else { /* in singlebit mode, the scanner returns 1 for black. ;-( --DM */ /* Hah! Same for Tamarack... -- REW */ int i; for (i = 0; i < lines_per_buffer * bpl; ++i) fputc (~data[i], fp); } } fclose (fp); return 0; } static SANE_Status attach_one (const char *dev) { attach (dev, 0); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; authorize = authorize; /* silence compilation warnings */ DBG_INIT(); sanei_thread_init(); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (TAMARACK_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { Tamarack_Device *dev, *next; for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free (dev); } if (devlist) free (devlist); } SANE_Status sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) { Tamarack_Device *dev; int i; local_only = local_only; /* silence compilation warnings */ if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle *handle) { Tamarack_Device *dev; SANE_Status status; Tamarack_Scanner *s; int i, j; if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } } else { /* empty devicname -> use first device */ dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->pipe = -1; s->hw = dev; for (i = 0; i < 4; ++i) for (j = 0; j < 256; ++j) s->gamma_table[i][j] = j; init_options (s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Tamarack_Scanner *prev, *s; /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG(1, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (s->scanning) do_cancel (handle); if (prev) prev->next = s->next; else first_handle = s->next; free (handle); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Tamarack_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; return s->opt + option; } static int make_mode (char *mode) { if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) return THRESHOLDED; if (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) return DITHERED; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) return GREYSCALE; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) return TRUECOLOR; return -1; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int *info) { Tamarack_Scanner *s = handle; SANE_Status status; SANE_Word cap; if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_PREVIEW: case OPT_GRAY_PREVIEW: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_TRANS: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: #if 0 case OPT_CUSTOM_GAMMA: #endif *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; #if 0 /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); return SANE_STATUS_GOOD; #endif /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = constrain_value (s, option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_PREVIEW: case OPT_GRAY_PREVIEW: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_TRANS: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; #if 0 /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); return SANE_STATUS_GOOD; /* options with side-effects: */ case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == s->val[OPT_CUSTOM_GAMMA].w) return SANE_STATUS_GOOD; /* no change */ s->val[OPT_CUSTOM_GAMMA].w = w; if (w) { s->mode = make_mode (s->val[OPT_MODE].s); if (s->mode == GREYSCALE) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else if (s->mode == TRUECOLOR) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; #endif case OPT_MODE: { if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); s->mode = make_mode (s->val[OPT_MODE].s); if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; #if 0 s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; #endif if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; else { s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; } #if 0 if (!binary) s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w) { if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } #endif return SANE_STATUS_GOOD; } } } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) { Tamarack_Scanner *s = handle; if (!s->scanning) { double width, height, dpi; memset (&s->params, 0, sizeof (s->params)); width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); dpi = SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->mode = make_mode (s->val[OPT_MODE].s); DBG(1, "got mode '%s' -> %d.\n", s->val[OPT_MODE].s, s->mode); /* make best-effort guess at what parameters will look like once scanning starts. */ if (dpi > 0.0 && width > 0.0 && height > 0.0) { double dots_per_mm = dpi / MM_PER_INCH; s->params.pixels_per_line = width * dots_per_mm; s->params.lines = height * dots_per_mm; } if ((s->mode == THRESHOLDED) || (s->mode == DITHERED)) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; s->params.depth = 1; } else if (s->mode == GREYSCALE) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } else { s->params.format = SANE_FRAME_RED + s->pass; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } s->pass = 0; } else { if (s->mode == TRUECOLOR) s->params.format = SANE_FRAME_RED + s->pass; } s->params.last_frame = (s->mode != TRUECOLOR) || (s->pass == 2); if (params) *params = s->params; DBG(1, "Got parameters: format:%d, ppl: %d, bpl:%d, depth:%d, " "last %d pass %d\n", s->params.format, s->params.pixels_per_line, s->params.bytes_per_line, s->params.depth, s->params.last_frame, s->pass); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Tamarack_Scanner *s = handle; SANE_Status status; int fds[2]; /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; if (s->fd < 0) { /* translate options into s->mode for convenient access: */ s->mode = make_mode (s->val[OPT_MODE].s); if (s->mode == TRUECOLOR) { if (s->val[OPT_PREVIEW].w && s->val[OPT_GRAY_PREVIEW].w) { /* Force gray-scale mode when previewing. */ s->mode = GREYSCALE; s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.last_frame = SANE_TRUE; } } status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG(1, "open: open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return status; } } status = wait_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG(1, "open: wait_ready() failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = scan_area_and_windows (s); if (status != SANE_STATUS_GOOD) { DBG(1, "open: set scan area command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = mode_select (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; s->scanning = SANE_TRUE; status = start_scan (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = get_image_status (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; s->line = 0; if (pipe (fds) < 0) return SANE_STATUS_IO_ERROR; s->pipe = fds[0]; s->reader_pipe = fds[1]; s->reader_pid = sanei_thread_begin (reader_process, (void *) s); if (sanei_thread_is_forked()) close (s->reader_pipe); return SANE_STATUS_GOOD; stop_scanner_and_return: do_cancel (s); return status; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { Tamarack_Scanner *s = handle; ssize_t nread; *len = 0; nread = read (s->pipe, buf, max_len); DBG(3, "read %ld bytes\n", (long) nread); if (!s->scanning) return do_cancel (s); if (nread < 0) { if (errno == EAGAIN) { return SANE_STATUS_GOOD; } else { do_cancel (s); return SANE_STATUS_IO_ERROR; } } *len = nread; if (nread == 0) { s->pass++; return do_eof (s); } return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Tamarack_Scanner *s = handle; if (sanei_thread_is_valid (s->reader_pid)) sanei_thread_kill (s->reader_pid); s->scanning = SANE_FALSE; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Tamarack_Scanner *s = handle; if (!s->scanning) return SANE_STATUS_INVAL; if (fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int *fd) { Tamarack_Scanner *s = handle; if (!s->scanning) return SANE_STATUS_INVAL; *fd = s->pipe; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/Makefile.in0000664000175000017500000165710013110564733014673 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = backend DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/include/sane/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sanelibdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(sanelib_LTLIBRARIES) libabaton_la_LIBADD = am_libabaton_la_OBJECTS = libabaton_la-abaton.lo libabaton_la_OBJECTS = $(am_libabaton_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libagfafocus_la_LIBADD = am_libagfafocus_la_OBJECTS = libagfafocus_la-agfafocus.lo libagfafocus_la_OBJECTS = $(am_libagfafocus_la_OBJECTS) libapple_la_LIBADD = am_libapple_la_OBJECTS = libapple_la-apple.lo libapple_la_OBJECTS = $(am_libapple_la_OBJECTS) libartec_la_LIBADD = am_libartec_la_OBJECTS = libartec_la-artec.lo libartec_la_OBJECTS = $(am_libartec_la_OBJECTS) libartec_eplus48u_la_LIBADD = am_libartec_eplus48u_la_OBJECTS = \ libartec_eplus48u_la-artec_eplus48u.lo libartec_eplus48u_la_OBJECTS = $(am_libartec_eplus48u_la_OBJECTS) libas6e_la_LIBADD = am_libas6e_la_OBJECTS = libas6e_la-as6e.lo libas6e_la_OBJECTS = $(am_libas6e_la_OBJECTS) libavision_la_LIBADD = am_libavision_la_OBJECTS = libavision_la-avision.lo libavision_la_OBJECTS = $(am_libavision_la_OBJECTS) libbh_la_LIBADD = am_libbh_la_OBJECTS = libbh_la-bh.lo libbh_la_OBJECTS = $(am_libbh_la_OBJECTS) libcanon_la_LIBADD = am_libcanon_la_OBJECTS = libcanon_la-canon.lo libcanon_la_OBJECTS = $(am_libcanon_la_OBJECTS) libcanon630u_la_LIBADD = am_libcanon630u_la_OBJECTS = libcanon630u_la-canon630u.lo libcanon630u_la_OBJECTS = $(am_libcanon630u_la_OBJECTS) libcanon_dr_la_LIBADD = am_libcanon_dr_la_OBJECTS = libcanon_dr_la-canon_dr.lo libcanon_dr_la_OBJECTS = $(am_libcanon_dr_la_OBJECTS) libcanon_pp_la_LIBADD = am_libcanon_pp_la_OBJECTS = libcanon_pp_la-canon_pp.lo \ libcanon_pp_la-canon_pp-io.lo libcanon_pp_la-canon_pp-dev.lo libcanon_pp_la_OBJECTS = $(am_libcanon_pp_la_OBJECTS) libcardscan_la_LIBADD = am_libcardscan_la_OBJECTS = libcardscan_la-cardscan.lo libcardscan_la_OBJECTS = $(am_libcardscan_la_OBJECTS) libcoolscan_la_LIBADD = am_libcoolscan_la_OBJECTS = libcoolscan_la-coolscan.lo libcoolscan_la_OBJECTS = $(am_libcoolscan_la_OBJECTS) libcoolscan2_la_LIBADD = am_libcoolscan2_la_OBJECTS = libcoolscan2_la-coolscan2.lo libcoolscan2_la_OBJECTS = $(am_libcoolscan2_la_OBJECTS) libcoolscan3_la_LIBADD = am_libcoolscan3_la_OBJECTS = libcoolscan3_la-coolscan3.lo libcoolscan3_la_OBJECTS = $(am_libcoolscan3_la_OBJECTS) libdc210_la_LIBADD = am_libdc210_la_OBJECTS = libdc210_la-dc210.lo libdc210_la_OBJECTS = $(am_libdc210_la_OBJECTS) libdc240_la_LIBADD = am_libdc240_la_OBJECTS = libdc240_la-dc240.lo libdc240_la_OBJECTS = $(am_libdc240_la_OBJECTS) libdc25_la_LIBADD = am_libdc25_la_OBJECTS = libdc25_la-dc25.lo libdc25_la_OBJECTS = $(am_libdc25_la_OBJECTS) libdell1600n_net_la_LIBADD = am_libdell1600n_net_la_OBJECTS = libdell1600n_net_la-dell1600n_net.lo libdell1600n_net_la_OBJECTS = $(am_libdell1600n_net_la_OBJECTS) libdll_la_LIBADD = am_libdll_la_OBJECTS = libdll_la-dll.lo libdll_la_OBJECTS = $(am_libdll_la_OBJECTS) libdll_preload_la_LIBADD = am_libdll_preload_la_OBJECTS = libdll_preload_la-dll.lo libdll_preload_la_OBJECTS = $(am_libdll_preload_la_OBJECTS) libdmc_la_LIBADD = am_libdmc_la_OBJECTS = libdmc_la-dmc.lo libdmc_la_OBJECTS = $(am_libdmc_la_OBJECTS) libepjitsu_la_LIBADD = am_libepjitsu_la_OBJECTS = libepjitsu_la-epjitsu.lo libepjitsu_la_OBJECTS = $(am_libepjitsu_la_OBJECTS) libepson_la_LIBADD = am_libepson_la_OBJECTS = libepson_la-epson.lo \ libepson_la-epson_scsi.lo libepson_la-epson_usb.lo libepson_la_OBJECTS = $(am_libepson_la_OBJECTS) libepson2_la_LIBADD = am_libepson2_la_OBJECTS = libepson2_la-epson2.lo \ libepson2_la-epson2_scsi.lo libepson2_la-epson2_usb.lo \ libepson2_la-epson2_net.lo libepson2_la-epson2-io.lo \ libepson2_la-epson2-commands.lo libepson2_la-epson2-ops.lo \ libepson2_la-epson2-cct.lo libepson2_la_OBJECTS = $(am_libepson2_la_OBJECTS) libepsonds_la_LIBADD = am_libepsonds_la_OBJECTS = libepsonds_la-epsonds.lo \ libepsonds_la-epsonds-usb.lo libepsonds_la-epsonds-io.lo \ libepsonds_la-epsonds-cmd.lo libepsonds_la-epsonds-ops.lo \ libepsonds_la-epsonds-jpeg.lo libepsonds_la-epsonds-net.lo libepsonds_la_OBJECTS = $(am_libepsonds_la_OBJECTS) libfujitsu_la_LIBADD = am_libfujitsu_la_OBJECTS = libfujitsu_la-fujitsu.lo libfujitsu_la_OBJECTS = $(am_libfujitsu_la_OBJECTS) libgenesys_la_LIBADD = am_libgenesys_la_OBJECTS = libgenesys_la-genesys.lo \ libgenesys_la-genesys_gl646.lo libgenesys_la-genesys_gl841.lo \ libgenesys_la-genesys_gl843.lo libgenesys_la-genesys_gl846.lo \ libgenesys_la-genesys_gl847.lo libgenesys_la-genesys_gl124.lo \ libgenesys_la-genesys_low.lo libgenesys_la_OBJECTS = $(am_libgenesys_la_OBJECTS) libgphoto2_i_la_LIBADD = am_libgphoto2_i_la_OBJECTS = libgphoto2_i_la-gphoto2.lo libgphoto2_i_la_OBJECTS = $(am_libgphoto2_i_la_OBJECTS) libgt68xx_la_LIBADD = am_libgt68xx_la_OBJECTS = libgt68xx_la-gt68xx.lo libgt68xx_la_OBJECTS = $(am_libgt68xx_la_OBJECTS) libhp_la_LIBADD = am_libhp_la_OBJECTS = libhp_la-hp.lo libhp_la-hp-accessor.lo \ libhp_la-hp-device.lo libhp_la-hp-handle.lo \ libhp_la-hp-hpmem.lo libhp_la-hp-option.lo libhp_la-hp-scl.lo libhp_la_OBJECTS = $(am_libhp_la_OBJECTS) libhp3500_la_LIBADD = am_libhp3500_la_OBJECTS = libhp3500_la-hp3500.lo libhp3500_la_OBJECTS = $(am_libhp3500_la_OBJECTS) libhp3900_la_LIBADD = am_libhp3900_la_OBJECTS = libhp3900_la-hp3900.lo libhp3900_la_OBJECTS = $(am_libhp3900_la_OBJECTS) libhp4200_la_LIBADD = am_libhp4200_la_OBJECTS = libhp4200_la-hp4200.lo libhp4200_la_OBJECTS = $(am_libhp4200_la_OBJECTS) libhp5400_la_LIBADD = am_libhp5400_la_OBJECTS = libhp5400_la-hp5400.lo libhp5400_la_OBJECTS = $(am_libhp5400_la_OBJECTS) libhp5590_la_LIBADD = am_libhp5590_la_OBJECTS = libhp5590_la-hp5590.lo libhp5590_la_OBJECTS = $(am_libhp5590_la_OBJECTS) libhpljm1005_la_LIBADD = am_libhpljm1005_la_OBJECTS = libhpljm1005_la-hpljm1005.lo libhpljm1005_la_OBJECTS = $(am_libhpljm1005_la_OBJECTS) libhpsj5s_la_LIBADD = am_libhpsj5s_la_OBJECTS = libhpsj5s_la-hpsj5s.lo libhpsj5s_la_OBJECTS = $(am_libhpsj5s_la_OBJECTS) libhs2p_la_LIBADD = am_libhs2p_la_OBJECTS = libhs2p_la-hs2p.lo libhs2p_la_OBJECTS = $(am_libhs2p_la_OBJECTS) libibm_la_LIBADD = am_libibm_la_OBJECTS = libibm_la-ibm.lo libibm_la_OBJECTS = $(am_libibm_la_OBJECTS) libkodak_la_LIBADD = am_libkodak_la_OBJECTS = libkodak_la-kodak.lo libkodak_la_OBJECTS = $(am_libkodak_la_OBJECTS) libkodakaio_la_LIBADD = am_libkodakaio_la_OBJECTS = libkodakaio_la-kodakaio.lo libkodakaio_la_OBJECTS = $(am_libkodakaio_la_OBJECTS) libkvs1025_la_LIBADD = am_libkvs1025_la_OBJECTS = libkvs1025_la-kvs1025.lo \ libkvs1025_la-kvs1025_low.lo libkvs1025_la-kvs1025_opt.lo \ libkvs1025_la-kvs1025_usb.lo libkvs1025_la_OBJECTS = $(am_libkvs1025_la_OBJECTS) libkvs20xx_la_LIBADD = am_libkvs20xx_la_OBJECTS = libkvs20xx_la-kvs20xx.lo \ libkvs20xx_la-kvs20xx_cmd.lo libkvs20xx_la-kvs20xx_opt.lo libkvs20xx_la_OBJECTS = $(am_libkvs20xx_la_OBJECTS) libkvs40xx_la_LIBADD = am_libkvs40xx_la_OBJECTS = libkvs40xx_la-kvs40xx.lo \ libkvs40xx_la-kvs40xx_cmd.lo libkvs40xx_la-kvs40xx_opt.lo libkvs40xx_la_OBJECTS = $(am_libkvs40xx_la_OBJECTS) libleo_la_LIBADD = am_libleo_la_OBJECTS = libleo_la-leo.lo libleo_la_OBJECTS = $(am_libleo_la_OBJECTS) liblexmark_la_LIBADD = am_liblexmark_la_OBJECTS = liblexmark_la-lexmark.lo \ liblexmark_la-lexmark_low.lo liblexmark_la_OBJECTS = $(am_liblexmark_la_OBJECTS) libma1509_la_LIBADD = am_libma1509_la_OBJECTS = libma1509_la-ma1509.lo libma1509_la_OBJECTS = $(am_libma1509_la_OBJECTS) libmagicolor_la_LIBADD = am_libmagicolor_la_OBJECTS = libmagicolor_la-magicolor.lo libmagicolor_la_OBJECTS = $(am_libmagicolor_la_OBJECTS) libmatsushita_la_LIBADD = am_libmatsushita_la_OBJECTS = libmatsushita_la-matsushita.lo libmatsushita_la_OBJECTS = $(am_libmatsushita_la_OBJECTS) libmicrotek_la_LIBADD = am_libmicrotek_la_OBJECTS = libmicrotek_la-microtek.lo libmicrotek_la_OBJECTS = $(am_libmicrotek_la_OBJECTS) libmicrotek2_la_LIBADD = am_libmicrotek2_la_OBJECTS = libmicrotek2_la-microtek2.lo libmicrotek2_la_OBJECTS = $(am_libmicrotek2_la_OBJECTS) libmustek_la_LIBADD = am_libmustek_la_OBJECTS = libmustek_la-mustek.lo libmustek_la_OBJECTS = $(am_libmustek_la_OBJECTS) libmustek_pp_la_LIBADD = am_libmustek_pp_la_OBJECTS = libmustek_pp_la-mustek_pp.lo libmustek_pp_la_OBJECTS = $(am_libmustek_pp_la_OBJECTS) libmustek_usb_la_LIBADD = am_libmustek_usb_la_OBJECTS = libmustek_usb_la-mustek_usb.lo libmustek_usb_la_OBJECTS = $(am_libmustek_usb_la_OBJECTS) libmustek_usb2_la_LIBADD = am_libmustek_usb2_la_OBJECTS = libmustek_usb2_la-mustek_usb2.lo libmustek_usb2_la_OBJECTS = $(am_libmustek_usb2_la_OBJECTS) libnec_la_LIBADD = am_libnec_la_OBJECTS = libnec_la-nec.lo libnec_la_OBJECTS = $(am_libnec_la_OBJECTS) libnet_la_LIBADD = am_libnet_la_OBJECTS = libnet_la-net.lo libnet_la_OBJECTS = $(am_libnet_la_OBJECTS) libniash_la_LIBADD = am_libniash_la_OBJECTS = libniash_la-niash.lo libniash_la_OBJECTS = $(am_libniash_la_OBJECTS) libp5_la_LIBADD = am_libp5_la_OBJECTS = libp5_la-p5.lo libp5_la_OBJECTS = $(am_libp5_la_OBJECTS) libpie_la_LIBADD = am_libpie_la_OBJECTS = libpie_la-pie.lo libpie_la_OBJECTS = $(am_libpie_la_OBJECTS) libpieusb_la_LIBADD = am_libpieusb_la_OBJECTS = libpieusb_la-pieusb_buffer.lo \ libpieusb_la-pieusb_scancmd.lo libpieusb_la-pieusb_specific.lo \ libpieusb_la-pieusb_usb.lo libpieusb_la-pieusb.lo libpieusb_la_OBJECTS = $(am_libpieusb_la_OBJECTS) libpint_la_LIBADD = am_libpint_la_OBJECTS = libpint_la-pint.lo libpint_la_OBJECTS = $(am_libpint_la_OBJECTS) libpixma_la_LIBADD = am_libpixma_la_OBJECTS = libpixma_la-pixma.lo \ libpixma_la-pixma_io_sanei.lo libpixma_la-pixma_common.lo \ libpixma_la-pixma_mp150.lo libpixma_la-pixma_mp730.lo \ libpixma_la-pixma_mp750.lo libpixma_la-pixma_mp810.lo \ libpixma_la-pixma_imageclass.lo libpixma_la-pixma_bjnp.lo libpixma_la_OBJECTS = $(am_libpixma_la_OBJECTS) libplustek_la_LIBADD = am_libplustek_la_OBJECTS = libplustek_la-plustek.lo libplustek_la_OBJECTS = $(am_libplustek_la_OBJECTS) libplustek_pp_la_LIBADD = am_libplustek_pp_la_OBJECTS = libplustek_pp_la-plustek_pp.lo libplustek_pp_la_OBJECTS = $(am_libplustek_pp_la_OBJECTS) libpnm_la_LIBADD = am_libpnm_la_OBJECTS = libpnm_la-pnm.lo libpnm_la_OBJECTS = $(am_libpnm_la_OBJECTS) libqcam_la_LIBADD = am_libqcam_la_OBJECTS = libqcam_la-qcam.lo libqcam_la_OBJECTS = $(am_libqcam_la_OBJECTS) libricoh_la_LIBADD = am_libricoh_la_OBJECTS = libricoh_la-ricoh.lo libricoh_la_OBJECTS = $(am_libricoh_la_OBJECTS) librts8891_la_LIBADD = am_librts8891_la_OBJECTS = librts8891_la-rts8891.lo \ librts8891_la-rts88xx_lib.lo librts8891_la_OBJECTS = $(am_librts8891_la_OBJECTS) libs9036_la_LIBADD = am_libs9036_la_OBJECTS = libs9036_la-s9036.lo libs9036_la_OBJECTS = $(am_libs9036_la_OBJECTS) am__DEPENDENCIES_1 = libsane_abaton_la_DEPENDENCIES = $(COMMON_LIBS) libabaton.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_abaton_la_OBJECTS = libsane_abaton_la-abaton-s.lo libsane_abaton_la_OBJECTS = $(nodist_libsane_abaton_la_OBJECTS) libsane_abaton_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_abaton_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_agfafocus_la_DEPENDENCIES = $(COMMON_LIBS) libagfafocus.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_thread.lo \ ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_agfafocus_la_OBJECTS = \ libsane_agfafocus_la-agfafocus-s.lo libsane_agfafocus_la_OBJECTS = $(nodist_libsane_agfafocus_la_OBJECTS) libsane_agfafocus_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_agfafocus_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_apple_la_DEPENDENCIES = $(COMMON_LIBS) libapple.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_apple_la_OBJECTS = libsane_apple_la-apple-s.lo libsane_apple_la_OBJECTS = $(nodist_libsane_apple_la_OBJECTS) libsane_apple_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_apple_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_artec_la_DEPENDENCIES = $(COMMON_LIBS) libartec.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_artec_la_OBJECTS = libsane_artec_la-artec-s.lo libsane_artec_la_OBJECTS = $(nodist_libsane_artec_la_OBJECTS) libsane_artec_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_artec_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_artec_eplus48u_la_DEPENDENCIES = $(COMMON_LIBS) \ libartec_eplus48u.la ../sanei/sanei_init_debug.lo \ ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo \ ../sanei/sanei_thread.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_artec_eplus48u_la_OBJECTS = \ libsane_artec_eplus48u_la-artec_eplus48u-s.lo libsane_artec_eplus48u_la_OBJECTS = \ $(nodist_libsane_artec_eplus48u_la_OBJECTS) libsane_artec_eplus48u_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_artec_eplus48u_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_as6e_la_DEPENDENCIES = $(COMMON_LIBS) libas6e.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo nodist_libsane_as6e_la_OBJECTS = libsane_as6e_la-as6e-s.lo libsane_as6e_la_OBJECTS = $(nodist_libsane_as6e_la_OBJECTS) libsane_as6e_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_as6e_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_avision_la_DEPENDENCIES = $(COMMON_LIBS) libavision.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo \ ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_avision_la_OBJECTS = libsane_avision_la-avision-s.lo libsane_avision_la_OBJECTS = $(nodist_libsane_avision_la_OBJECTS) libsane_avision_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_avision_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_bh_la_DEPENDENCIES = $(COMMON_LIBS) libbh.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_bh_la_OBJECTS = libsane_bh_la-bh-s.lo libsane_bh_la_OBJECTS = $(nodist_libsane_bh_la_OBJECTS) libsane_bh_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libsane_bh_la_LDFLAGS) $(LDFLAGS) -o $@ libsane_canon_la_DEPENDENCIES = $(COMMON_LIBS) libcanon.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_canon_la_OBJECTS = libsane_canon_la-canon-s.lo libsane_canon_la_OBJECTS = $(nodist_libsane_canon_la_OBJECTS) libsane_canon_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_canon_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_canon630u_la_DEPENDENCIES = $(COMMON_LIBS) libcanon630u.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_canon630u_la_OBJECTS = \ libsane_canon630u_la-canon630u-s.lo libsane_canon630u_la_OBJECTS = $(nodist_libsane_canon630u_la_OBJECTS) libsane_canon630u_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_canon630u_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_canon_dr_la_DEPENDENCIES = $(COMMON_LIBS) libcanon_dr.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_magic.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_canon_dr_la_OBJECTS = \ libsane_canon_dr_la-canon_dr-s.lo libsane_canon_dr_la_OBJECTS = $(nodist_libsane_canon_dr_la_OBJECTS) libsane_canon_dr_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_canon_dr_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_canon_pp_la_DEPENDENCIES = $(COMMON_LIBS) libcanon_pp.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) nodist_libsane_canon_pp_la_OBJECTS = \ libsane_canon_pp_la-canon_pp-s.lo libsane_canon_pp_la_OBJECTS = $(nodist_libsane_canon_pp_la_OBJECTS) libsane_canon_pp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_canon_pp_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_cardscan_la_DEPENDENCIES = $(COMMON_LIBS) libcardscan.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_cardscan_la_OBJECTS = \ libsane_cardscan_la-cardscan-s.lo libsane_cardscan_la_OBJECTS = $(nodist_libsane_cardscan_la_OBJECTS) libsane_cardscan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_cardscan_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_coolscan_la_DEPENDENCIES = $(COMMON_LIBS) libcoolscan.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_thread.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_coolscan_la_OBJECTS = \ libsane_coolscan_la-coolscan-s.lo libsane_coolscan_la_OBJECTS = $(nodist_libsane_coolscan_la_OBJECTS) libsane_coolscan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_coolscan_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_coolscan2_la_DEPENDENCIES = $(COMMON_LIBS) libcoolscan2.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_coolscan2_la_OBJECTS = \ libsane_coolscan2_la-coolscan2-s.lo libsane_coolscan2_la_OBJECTS = $(nodist_libsane_coolscan2_la_OBJECTS) libsane_coolscan2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_coolscan2_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_coolscan3_la_DEPENDENCIES = $(COMMON_LIBS) libcoolscan3.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_coolscan3_la_OBJECTS = \ libsane_coolscan3_la-coolscan3-s.lo libsane_coolscan3_la_OBJECTS = $(nodist_libsane_coolscan3_la_OBJECTS) libsane_coolscan3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_coolscan3_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_dc210_la_DEPENDENCIES = $(COMMON_LIBS) libdc210.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_dc210_la_OBJECTS = libsane_dc210_la-dc210-s.lo libsane_dc210_la_OBJECTS = $(nodist_libsane_dc210_la_OBJECTS) libsane_dc210_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_dc210_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_dc240_la_DEPENDENCIES = $(COMMON_LIBS) libdc240.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_dc240_la_OBJECTS = libsane_dc240_la-dc240-s.lo libsane_dc240_la_OBJECTS = $(nodist_libsane_dc240_la_OBJECTS) libsane_dc240_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_dc240_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_dc25_la_DEPENDENCIES = $(COMMON_LIBS) libdc25.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) nodist_libsane_dc25_la_OBJECTS = libsane_dc25_la-dc25-s.lo libsane_dc25_la_OBJECTS = $(nodist_libsane_dc25_la_OBJECTS) libsane_dc25_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_dc25_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_dell1600n_net_la_DEPENDENCIES = $(COMMON_LIBS) \ libdell1600n_net.la ../sanei/sanei_init_debug.lo \ ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo \ sane_strstatus.lo $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_dell1600n_net_la_OBJECTS = \ libsane_dell1600n_net_la-dell1600n_net-s.lo libsane_dell1600n_net_la_OBJECTS = \ $(nodist_libsane_dell1600n_net_la_OBJECTS) libsane_dell1600n_net_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_dell1600n_net_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_dll_la_DEPENDENCIES = $(COMMON_LIBS) libdll.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) nodist_libsane_dll_la_OBJECTS = libsane_dll_la-dll-s.lo libsane_dll_la_OBJECTS = $(nodist_libsane_dll_la_OBJECTS) libsane_dll_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_dll_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_dmc_la_DEPENDENCIES = $(COMMON_LIBS) libdmc.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_dmc_la_OBJECTS = libsane_dmc_la-dmc-s.lo libsane_dmc_la_OBJECTS = $(nodist_libsane_dmc_la_OBJECTS) libsane_dmc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_dmc_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_epjitsu_la_DEPENDENCIES = $(COMMON_LIBS) libepjitsu.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_epjitsu_la_OBJECTS = libsane_epjitsu_la-epjitsu-s.lo libsane_epjitsu_la_OBJECTS = $(nodist_libsane_epjitsu_la_OBJECTS) libsane_epjitsu_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_epjitsu_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_epson_la_DEPENDENCIES = $(COMMON_LIBS) libepson.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_pio.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_epson_la_OBJECTS = libsane_epson_la-epson-s.lo libsane_epson_la_OBJECTS = $(nodist_libsane_epson_la_OBJECTS) libsane_epson_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_epson_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_epson2_la_DEPENDENCIES = $(COMMON_LIBS) libepson2.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo \ ../sanei/sanei_udp.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_epson2_la_OBJECTS = libsane_epson2_la-epson2-s.lo libsane_epson2_la_OBJECTS = $(nodist_libsane_epson2_la_OBJECTS) libsane_epson2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_epson2_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_epsonds_la_DEPENDENCIES = $(COMMON_LIBS) libepsonds.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_epsonds_la_OBJECTS = libsane_epsonds_la-epsonds-s.lo libsane_epsonds_la_OBJECTS = $(nodist_libsane_epsonds_la_OBJECTS) libsane_epsonds_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_epsonds_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_fujitsu_la_DEPENDENCIES = $(COMMON_LIBS) libfujitsu.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_magic.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_fujitsu_la_OBJECTS = libsane_fujitsu_la-fujitsu-s.lo libsane_fujitsu_la_OBJECTS = $(nodist_libsane_fujitsu_la_OBJECTS) libsane_fujitsu_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_fujitsu_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_genesys_la_DEPENDENCIES = $(COMMON_LIBS) libgenesys.la \ ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo \ ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_genesys_la_OBJECTS = libsane_genesys_la-genesys-s.lo libsane_genesys_la_OBJECTS = $(nodist_libsane_genesys_la_OBJECTS) libsane_genesys_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_genesys_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_gphoto2_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(COMMON_LIBS) \ libgphoto2_i.la ../sanei/sanei_init_debug.lo \ ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo \ sane_strstatus.lo $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_gphoto2_la_OBJECTS = libsane_gphoto2_la-gphoto2-s.lo libsane_gphoto2_la_OBJECTS = $(nodist_libsane_gphoto2_la_OBJECTS) libsane_gphoto2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_gphoto2_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_gt68xx_la_DEPENDENCIES = $(COMMON_LIBS) libgt68xx.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_gt68xx_la_OBJECTS = libsane_gt68xx_la-gt68xx-s.lo libsane_gt68xx_la_OBJECTS = $(nodist_libsane_gt68xx_la_OBJECTS) libsane_gt68xx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_gt68xx_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_hp_la_DEPENDENCIES = $(COMMON_LIBS) libhp.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_pio.lo ../sanei/sanei_thread.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_hp_la_OBJECTS = libsane_hp_la-hp-s.lo libsane_hp_la_OBJECTS = $(nodist_libsane_hp_la_OBJECTS) libsane_hp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libsane_hp_la_LDFLAGS) $(LDFLAGS) -o $@ libsane_hp3500_la_DEPENDENCIES = $(COMMON_LIBS) libhp3500.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_hp3500_la_OBJECTS = libsane_hp3500_la-hp3500-s.lo libsane_hp3500_la_OBJECTS = $(nodist_libsane_hp3500_la_OBJECTS) libsane_hp3500_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_hp3500_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_hp3900_la_DEPENDENCIES = $(COMMON_LIBS) libhp3900.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_hp3900_la_OBJECTS = libsane_hp3900_la-hp3900-s.lo libsane_hp3900_la_OBJECTS = $(nodist_libsane_hp3900_la_OBJECTS) libsane_hp3900_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_hp3900_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_hp4200_la_DEPENDENCIES = $(COMMON_LIBS) libhp4200.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_pv8630.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_hp4200_la_OBJECTS = libsane_hp4200_la-hp4200-s.lo libsane_hp4200_la_OBJECTS = $(nodist_libsane_hp4200_la_OBJECTS) libsane_hp4200_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_hp4200_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_hp5400_la_DEPENDENCIES = $(COMMON_LIBS) libhp5400.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_hp5400_la_OBJECTS = libsane_hp5400_la-hp5400-s.lo libsane_hp5400_la_OBJECTS = $(nodist_libsane_hp5400_la_OBJECTS) libsane_hp5400_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_hp5400_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_hp5590_la_DEPENDENCIES = $(COMMON_LIBS) libhp5590.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_hp5590_la_OBJECTS = libsane_hp5590_la-hp5590-s.lo libsane_hp5590_la_OBJECTS = $(nodist_libsane_hp5590_la_OBJECTS) libsane_hp5590_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_hp5590_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_hpljm1005_la_DEPENDENCIES = $(COMMON_LIBS) libhpljm1005.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_hpljm1005_la_OBJECTS = \ libsane_hpljm1005_la-hpljm1005-s.lo libsane_hpljm1005_la_OBJECTS = $(nodist_libsane_hpljm1005_la_OBJECTS) libsane_hpljm1005_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_hpljm1005_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_hpsj5s_la_DEPENDENCIES = $(COMMON_LIBS) libhpsj5s.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) nodist_libsane_hpsj5s_la_OBJECTS = libsane_hpsj5s_la-hpsj5s-s.lo libsane_hpsj5s_la_OBJECTS = $(nodist_libsane_hpsj5s_la_OBJECTS) libsane_hpsj5s_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_hpsj5s_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_hs2p_la_DEPENDENCIES = $(COMMON_LIBS) libhs2p.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_hs2p_la_OBJECTS = libsane_hs2p_la-hs2p-s.lo libsane_hs2p_la_OBJECTS = $(nodist_libsane_hs2p_la_OBJECTS) libsane_hs2p_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_hs2p_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_ibm_la_DEPENDENCIES = $(COMMON_LIBS) libibm.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_ibm_la_OBJECTS = libsane_ibm_la-ibm-s.lo libsane_ibm_la_OBJECTS = $(nodist_libsane_ibm_la_OBJECTS) libsane_ibm_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_ibm_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_kodak_la_DEPENDENCIES = $(COMMON_LIBS) libkodak.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_kodak_la_OBJECTS = libsane_kodak_la-kodak-s.lo libsane_kodak_la_OBJECTS = $(nodist_libsane_kodak_la_OBJECTS) libsane_kodak_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_kodak_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_kodakaio_la_DEPENDENCIES = $(COMMON_LIBS) libkodakaio.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_kodakaio_la_OBJECTS = \ libsane_kodakaio_la-kodakaio-s.lo libsane_kodakaio_la_OBJECTS = $(nodist_libsane_kodakaio_la_OBJECTS) libsane_kodakaio_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_kodakaio_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_kvs1025_la_DEPENDENCIES = $(COMMON_LIBS) libkvs1025.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_magic.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_kvs1025_la_OBJECTS = libsane_kvs1025_la-kvs1025-s.lo libsane_kvs1025_la_OBJECTS = $(nodist_libsane_kvs1025_la_OBJECTS) libsane_kvs1025_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_kvs1025_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_kvs20xx_la_DEPENDENCIES = $(COMMON_LIBS) libkvs20xx.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_kvs20xx_la_OBJECTS = libsane_kvs20xx_la-kvs20xx-s.lo libsane_kvs20xx_la_OBJECTS = $(nodist_libsane_kvs20xx_la_OBJECTS) libsane_kvs20xx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_kvs20xx_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_kvs40xx_la_DEPENDENCIES = $(COMMON_LIBS) libkvs40xx.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_kvs40xx_la_OBJECTS = libsane_kvs40xx_la-kvs40xx-s.lo libsane_kvs40xx_la_OBJECTS = $(nodist_libsane_kvs40xx_la_OBJECTS) libsane_kvs40xx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_kvs40xx_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_leo_la_DEPENDENCIES = $(COMMON_LIBS) libleo.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_leo_la_OBJECTS = libsane_leo_la-leo-s.lo libsane_leo_la_OBJECTS = $(nodist_libsane_leo_la_OBJECTS) libsane_leo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_leo_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_lexmark_la_DEPENDENCIES = $(COMMON_LIBS) liblexmark.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_lexmark_la_OBJECTS = libsane_lexmark_la-lexmark-s.lo libsane_lexmark_la_OBJECTS = $(nodist_libsane_lexmark_la_OBJECTS) libsane_lexmark_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_lexmark_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_ma1509_la_DEPENDENCIES = $(COMMON_LIBS) libma1509.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_ma1509_la_OBJECTS = libsane_ma1509_la-ma1509-s.lo libsane_ma1509_la_OBJECTS = $(nodist_libsane_ma1509_la_OBJECTS) libsane_ma1509_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_ma1509_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_magicolor_la_DEPENDENCIES = $(COMMON_LIBS) libmagicolor.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_magicolor_la_OBJECTS = \ libsane_magicolor_la-magicolor-s.lo libsane_magicolor_la_OBJECTS = $(nodist_libsane_magicolor_la_OBJECTS) libsane_magicolor_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_magicolor_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_matsushita_la_DEPENDENCIES = $(COMMON_LIBS) libmatsushita.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_matsushita_la_OBJECTS = \ libsane_matsushita_la-matsushita-s.lo libsane_matsushita_la_OBJECTS = \ $(nodist_libsane_matsushita_la_OBJECTS) libsane_matsushita_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_matsushita_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_microtek_la_DEPENDENCIES = $(COMMON_LIBS) libmicrotek.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_microtek_la_OBJECTS = \ libsane_microtek_la-microtek-s.lo libsane_microtek_la_OBJECTS = $(nodist_libsane_microtek_la_OBJECTS) libsane_microtek_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_microtek_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_microtek2_la_DEPENDENCIES = $(COMMON_LIBS) libmicrotek2.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_thread.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_microtek2_la_OBJECTS = \ libsane_microtek2_la-microtek2-s.lo libsane_microtek2_la_OBJECTS = $(nodist_libsane_microtek2_la_OBJECTS) libsane_microtek2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_microtek2_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_mustek_la_DEPENDENCIES = $(COMMON_LIBS) libmustek.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_thread.lo ../sanei/sanei_ab306.lo \ ../sanei/sanei_pa4s2.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_mustek_la_OBJECTS = libsane_mustek_la-mustek-s.lo libsane_mustek_la_OBJECTS = $(nodist_libsane_mustek_la_OBJECTS) libsane_mustek_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_mustek_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_mustek_pp_la_DEPENDENCIES = $(COMMON_LIBS) libmustek_pp.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_pa4s2.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_mustek_pp_la_OBJECTS = \ libsane_mustek_pp_la-mustek_pp-s.lo libsane_mustek_pp_la_OBJECTS = $(nodist_libsane_mustek_pp_la_OBJECTS) libsane_mustek_pp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_mustek_pp_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_mustek_usb_la_DEPENDENCIES = $(COMMON_LIBS) libmustek_usb.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_mustek_usb_la_OBJECTS = \ libsane_mustek_usb_la-mustek_usb-s.lo libsane_mustek_usb_la_OBJECTS = \ $(nodist_libsane_mustek_usb_la_OBJECTS) libsane_mustek_usb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_mustek_usb_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_mustek_usb2_la_DEPENDENCIES = $(COMMON_LIBS) libmustek_usb2.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_mustek_usb2_la_OBJECTS = \ libsane_mustek_usb2_la-mustek_usb2-s.lo libsane_mustek_usb2_la_OBJECTS = \ $(nodist_libsane_mustek_usb2_la_OBJECTS) libsane_mustek_usb2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_mustek_usb2_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_nec_la_DEPENDENCIES = $(COMMON_LIBS) libnec.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_nec_la_OBJECTS = libsane_nec_la-nec-s.lo libsane_nec_la_OBJECTS = $(nodist_libsane_nec_la_OBJECTS) libsane_nec_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_nec_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_net_la_DEPENDENCIES = $(COMMON_LIBS) libnet.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_net.lo ../sanei/sanei_wire.lo \ ../sanei/sanei_codec_bin.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_net_la_OBJECTS = libsane_net_la-net-s.lo libsane_net_la_OBJECTS = $(nodist_libsane_net_la_OBJECTS) libsane_net_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_net_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_niash_la_DEPENDENCIES = $(COMMON_LIBS) libniash.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_niash_la_OBJECTS = libsane_niash_la-niash-s.lo libsane_niash_la_OBJECTS = $(nodist_libsane_niash_la_OBJECTS) libsane_niash_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_niash_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_p5_la_DEPENDENCIES = $(COMMON_LIBS) libp5.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo nodist_libsane_p5_la_OBJECTS = libsane_p5_la-p5-s.lo libsane_p5_la_OBJECTS = $(nodist_libsane_p5_la_OBJECTS) libsane_p5_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libsane_p5_la_LDFLAGS) $(LDFLAGS) -o $@ libsane_pie_la_DEPENDENCIES = $(COMMON_LIBS) libpie.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_thread.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_pie_la_OBJECTS = libsane_pie_la-pie-s.lo libsane_pie_la_OBJECTS = $(nodist_libsane_pie_la_OBJECTS) libsane_pie_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_pie_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_pieusb_la_DEPENDENCIES = $(COMMON_LIBS) libpieusb.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo \ ../sanei/sanei_ir.lo ../sanei/sanei_magic.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_pieusb_la_OBJECTS = libsane_pieusb_la-pieusb-s.lo libsane_pieusb_la_OBJECTS = $(nodist_libsane_pieusb_la_OBJECTS) libsane_pieusb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_pieusb_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_pint_la_DEPENDENCIES = $(COMMON_LIBS) libpint.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo nodist_libsane_pint_la_OBJECTS = libsane_pint_la-pint-s.lo libsane_pint_la_OBJECTS = $(nodist_libsane_pint_la_OBJECTS) libsane_pint_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_pint_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_pixma_la_DEPENDENCIES = $(COMMON_LIBS) libpixma.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_pixma_la_OBJECTS = libsane_pixma_la-pixma-s.lo libsane_pixma_la_OBJECTS = $(nodist_libsane_pixma_la_OBJECTS) libsane_pixma_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_pixma_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_plustek_la_DEPENDENCIES = $(COMMON_LIBS) libplustek.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo \ ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_plustek_la_OBJECTS = libsane_plustek_la-plustek-s.lo libsane_plustek_la_OBJECTS = $(nodist_libsane_plustek_la_OBJECTS) libsane_plustek_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_plustek_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_plustek_pp_la_DEPENDENCIES = $(COMMON_LIBS) libplustek_pp.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_plustek_pp_la_OBJECTS = \ libsane_plustek_pp_la-plustek_pp-s.lo libsane_plustek_pp_la_OBJECTS = \ $(nodist_libsane_plustek_pp_la_OBJECTS) libsane_plustek_pp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_plustek_pp_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_pnm_la_DEPENDENCIES = $(COMMON_LIBS) libpnm.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo nodist_libsane_pnm_la_OBJECTS = libsane_pnm_la-pnm-s.lo libsane_pnm_la_OBJECTS = $(nodist_libsane_pnm_la_OBJECTS) libsane_pnm_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_pnm_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_qcam_la_DEPENDENCIES = $(COMMON_LIBS) libqcam.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_pio.lo nodist_libsane_qcam_la_OBJECTS = libsane_qcam_la-qcam-s.lo libsane_qcam_la_OBJECTS = $(nodist_libsane_qcam_la_OBJECTS) libsane_qcam_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_qcam_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_ricoh_la_DEPENDENCIES = $(COMMON_LIBS) libricoh.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_ricoh_la_OBJECTS = libsane_ricoh_la-ricoh-s.lo libsane_ricoh_la_OBJECTS = $(nodist_libsane_ricoh_la_OBJECTS) libsane_ricoh_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_ricoh_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_rts8891_la_DEPENDENCIES = $(COMMON_LIBS) librts8891.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_scsi.lo ../sanei/sanei_usb.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_rts8891_la_OBJECTS = libsane_rts8891_la-rts8891-s.lo libsane_rts8891_la_OBJECTS = $(nodist_libsane_rts8891_la_OBJECTS) libsane_rts8891_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_rts8891_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_s9036_la_DEPENDENCIES = $(COMMON_LIBS) libs9036.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_s9036_la_OBJECTS = libsane_s9036_la-s9036-s.lo libsane_s9036_la_OBJECTS = $(nodist_libsane_s9036_la_OBJECTS) libsane_s9036_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_s9036_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_sceptre_la_DEPENDENCIES = $(COMMON_LIBS) libsceptre.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_sceptre_la_OBJECTS = libsane_sceptre_la-sceptre-s.lo libsane_sceptre_la_OBJECTS = $(nodist_libsane_sceptre_la_OBJECTS) libsane_sceptre_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_sceptre_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_sharp_la_DEPENDENCIES = $(COMMON_LIBS) libsharp.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_sharp_la_OBJECTS = libsane_sharp_la-sharp-s.lo libsane_sharp_la_OBJECTS = $(nodist_libsane_sharp_la_OBJECTS) libsane_sharp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_sharp_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_sm3600_la_DEPENDENCIES = $(COMMON_LIBS) libsm3600.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_sm3600_la_OBJECTS = libsane_sm3600_la-sm3600-s.lo libsane_sm3600_la_OBJECTS = $(nodist_libsane_sm3600_la_OBJECTS) libsane_sm3600_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_sm3600_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_sm3840_la_DEPENDENCIES = $(COMMON_LIBS) libsm3840.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_sm3840_la_OBJECTS = libsane_sm3840_la-sm3840-s.lo libsane_sm3840_la_OBJECTS = $(nodist_libsane_sm3840_la_OBJECTS) libsane_sm3840_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_sm3840_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_snapscan_la_DEPENDENCIES = $(COMMON_LIBS) libsnapscan.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo \ ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_snapscan_la_OBJECTS = \ libsane_snapscan_la-snapscan-s.lo libsane_snapscan_la_OBJECTS = $(nodist_libsane_snapscan_la_OBJECTS) libsane_snapscan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_snapscan_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_sp15c_la_DEPENDENCIES = $(COMMON_LIBS) libsp15c.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_thread.lo \ ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_sp15c_la_OBJECTS = libsane_sp15c_la-sp15c-s.lo libsane_sp15c_la_OBJECTS = $(nodist_libsane_sp15c_la_OBJECTS) libsane_sp15c_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_sp15c_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_st400_la_DEPENDENCIES = $(COMMON_LIBS) libst400.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_st400_la_OBJECTS = libsane_st400_la-st400-s.lo libsane_st400_la_OBJECTS = $(nodist_libsane_st400_la_OBJECTS) libsane_st400_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_st400_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_stv680_la_DEPENDENCIES = $(COMMON_LIBS) libstv680.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_stv680_la_OBJECTS = libsane_stv680_la-stv680-s.lo libsane_stv680_la_OBJECTS = $(nodist_libsane_stv680_la_OBJECTS) libsane_stv680_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_stv680_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_tamarack_la_DEPENDENCIES = $(COMMON_LIBS) libtamarack.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_thread.lo \ ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_tamarack_la_OBJECTS = \ libsane_tamarack_la-tamarack-s.lo libsane_tamarack_la_OBJECTS = $(nodist_libsane_tamarack_la_OBJECTS) libsane_tamarack_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_tamarack_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_teco1_la_DEPENDENCIES = $(COMMON_LIBS) libteco1.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_teco1_la_OBJECTS = libsane_teco1_la-teco1-s.lo libsane_teco1_la_OBJECTS = $(nodist_libsane_teco1_la_OBJECTS) libsane_teco1_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_teco1_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_teco2_la_DEPENDENCIES = $(COMMON_LIBS) libteco2.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_teco2_la_OBJECTS = libsane_teco2_la-teco2-s.lo libsane_teco2_la_OBJECTS = $(nodist_libsane_teco2_la_OBJECTS) libsane_teco2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_teco2_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_teco3_la_DEPENDENCIES = $(COMMON_LIBS) libteco3.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_scsi.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_teco3_la_OBJECTS = libsane_teco3_la-teco3-s.lo libsane_teco3_la_OBJECTS = $(nodist_libsane_teco3_la_OBJECTS) libsane_teco3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_teco3_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_test_la_DEPENDENCIES = $(COMMON_LIBS) libtest.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_thread.lo $(am__DEPENDENCIES_1) nodist_libsane_test_la_OBJECTS = libsane_test_la-test-s.lo libsane_test_la_OBJECTS = $(nodist_libsane_test_la_OBJECTS) libsane_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_test_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_u12_la_DEPENDENCIES = $(COMMON_LIBS) libu12.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_u12_la_OBJECTS = libsane_u12_la-u12-s.lo libsane_u12_la_OBJECTS = $(nodist_libsane_u12_la_OBJECTS) libsane_u12_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_u12_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_umax_la_DEPENDENCIES = $(COMMON_LIBS) libumax.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo \ sane_strstatus.lo ../sanei/sanei_usb.lo \ ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_pv8630.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) nodist_libsane_umax_la_OBJECTS = libsane_umax_la-umax-s.lo libsane_umax_la_OBJECTS = $(nodist_libsane_umax_la_OBJECTS) libsane_umax_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_umax_la_LDFLAGS) $(LDFLAGS) \ -o $@ libsane_umax1220u_la_DEPENDENCIES = $(COMMON_LIBS) libumax1220u.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_pv8630.lo \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_umax1220u_la_OBJECTS = \ libsane_umax1220u_la-umax1220u-s.lo libsane_umax1220u_la_OBJECTS = $(nodist_libsane_umax1220u_la_OBJECTS) libsane_umax1220u_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_umax1220u_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_umax_pp_la_DEPENDENCIES = $(COMMON_LIBS) libumax_pp.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) nodist_libsane_umax_pp_la_OBJECTS = libsane_umax_pp_la-umax_pp-s.lo libsane_umax_pp_la_OBJECTS = $(nodist_libsane_umax_pp_la_OBJECTS) libsane_umax_pp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_umax_pp_la_LDFLAGS) \ $(LDFLAGS) -o $@ libsane_v4l_la_DEPENDENCIES = $(COMMON_LIBS) libv4l.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) nodist_libsane_v4l_la_OBJECTS = libsane_v4l_la-v4l-s.lo libsane_v4l_la_OBJECTS = $(nodist_libsane_v4l_la_OBJECTS) libsane_v4l_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_v4l_la_LDFLAGS) $(LDFLAGS) -o \ $@ libsane_xerox_mfp_la_DEPENDENCIES = $(COMMON_LIBS) libxerox_mfp.la \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \ $(am__DEPENDENCIES_1) ../sanei/sanei_usb.lo \ ../sanei/sanei_tcp.lo $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) nodist_libsane_xerox_mfp_la_OBJECTS = \ libsane_xerox_mfp_la-xerox_mfp-s.lo libsane_xerox_mfp_la_OBJECTS = $(nodist_libsane_xerox_mfp_la_OBJECTS) libsane_xerox_mfp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libsane_xerox_mfp_la_LDFLAGS) \ $(LDFLAGS) -o $@ nodist_libsane_la_OBJECTS = libsane_la-dll-s.lo libsane_la_OBJECTS = $(nodist_libsane_la_OBJECTS) libsane_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libsane_la_LDFLAGS) $(LDFLAGS) -o $@ libsceptre_la_LIBADD = am_libsceptre_la_OBJECTS = libsceptre_la-sceptre.lo libsceptre_la_OBJECTS = $(am_libsceptre_la_OBJECTS) libsharp_la_LIBADD = am_libsharp_la_OBJECTS = libsharp_la-sharp.lo libsharp_la_OBJECTS = $(am_libsharp_la_OBJECTS) libsm3600_la_LIBADD = am_libsm3600_la_OBJECTS = libsm3600_la-sm3600.lo libsm3600_la_OBJECTS = $(am_libsm3600_la_OBJECTS) libsm3840_la_LIBADD = am_libsm3840_la_OBJECTS = libsm3840_la-sm3840.lo libsm3840_la_OBJECTS = $(am_libsm3840_la_OBJECTS) libsnapscan_la_LIBADD = am_libsnapscan_la_OBJECTS = libsnapscan_la-snapscan.lo libsnapscan_la_OBJECTS = $(am_libsnapscan_la_OBJECTS) libsp15c_la_LIBADD = am_libsp15c_la_OBJECTS = libsp15c_la-sp15c.lo libsp15c_la_OBJECTS = $(am_libsp15c_la_OBJECTS) libst400_la_LIBADD = am_libst400_la_OBJECTS = libst400_la-st400.lo libst400_la_OBJECTS = $(am_libst400_la_OBJECTS) libstv680_la_LIBADD = am_libstv680_la_OBJECTS = libstv680_la-stv680.lo libstv680_la_OBJECTS = $(am_libstv680_la_OBJECTS) libtamarack_la_LIBADD = am_libtamarack_la_OBJECTS = libtamarack_la-tamarack.lo libtamarack_la_OBJECTS = $(am_libtamarack_la_OBJECTS) libteco1_la_LIBADD = am_libteco1_la_OBJECTS = libteco1_la-teco1.lo libteco1_la_OBJECTS = $(am_libteco1_la_OBJECTS) libteco2_la_LIBADD = am_libteco2_la_OBJECTS = libteco2_la-teco2.lo libteco2_la_OBJECTS = $(am_libteco2_la_OBJECTS) libteco3_la_LIBADD = am_libteco3_la_OBJECTS = libteco3_la-teco3.lo libteco3_la_OBJECTS = $(am_libteco3_la_OBJECTS) libtest_la_LIBADD = am_libtest_la_OBJECTS = libtest_la-test.lo libtest_la_OBJECTS = $(am_libtest_la_OBJECTS) libu12_la_LIBADD = am_libu12_la_OBJECTS = libu12_la-u12.lo libu12_la_OBJECTS = $(am_libu12_la_OBJECTS) libumax_la_LIBADD = am_libumax_la_OBJECTS = libumax_la-umax.lo libumax_la_OBJECTS = $(am_libumax_la_OBJECTS) libumax1220u_la_LIBADD = am_libumax1220u_la_OBJECTS = libumax1220u_la-umax1220u.lo libumax1220u_la_OBJECTS = $(am_libumax1220u_la_OBJECTS) libumax_pp_la_LIBADD = am_libumax_pp_la_OBJECTS = libumax_pp_la-umax_pp.lo \ libumax_pp_la-umax_pp_low.lo libumax_pp_la-umax_pp_mid.lo libumax_pp_la_OBJECTS = $(am_libumax_pp_la_OBJECTS) libv4l_la_LIBADD = am_libv4l_la_OBJECTS = libv4l_la-v4l.lo libv4l_la_OBJECTS = $(am_libv4l_la_OBJECTS) libxerox_mfp_la_LIBADD = am_libxerox_mfp_la_OBJECTS = libxerox_mfp_la-xerox_mfp.lo \ libxerox_mfp_la-xerox_mfp-usb.lo \ libxerox_mfp_la-xerox_mfp-tcp.lo libxerox_mfp_la_OBJECTS = $(am_libxerox_mfp_la_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libabaton_la_SOURCES) $(libagfafocus_la_SOURCES) \ $(libapple_la_SOURCES) $(libartec_la_SOURCES) \ $(libartec_eplus48u_la_SOURCES) $(libas6e_la_SOURCES) \ $(libavision_la_SOURCES) $(libbh_la_SOURCES) \ $(libcanon_la_SOURCES) $(libcanon630u_la_SOURCES) \ $(libcanon_dr_la_SOURCES) $(libcanon_pp_la_SOURCES) \ $(libcardscan_la_SOURCES) $(libcoolscan_la_SOURCES) \ $(libcoolscan2_la_SOURCES) $(libcoolscan3_la_SOURCES) \ $(libdc210_la_SOURCES) $(libdc240_la_SOURCES) \ $(libdc25_la_SOURCES) $(libdell1600n_net_la_SOURCES) \ $(libdll_la_SOURCES) $(libdll_preload_la_SOURCES) \ $(libdmc_la_SOURCES) $(libepjitsu_la_SOURCES) \ $(libepson_la_SOURCES) $(libepson2_la_SOURCES) \ $(libepsonds_la_SOURCES) $(libfujitsu_la_SOURCES) \ $(libgenesys_la_SOURCES) $(libgphoto2_i_la_SOURCES) \ $(libgt68xx_la_SOURCES) $(libhp_la_SOURCES) \ $(libhp3500_la_SOURCES) $(libhp3900_la_SOURCES) \ $(libhp4200_la_SOURCES) $(libhp5400_la_SOURCES) \ $(libhp5590_la_SOURCES) $(libhpljm1005_la_SOURCES) \ $(libhpsj5s_la_SOURCES) $(libhs2p_la_SOURCES) \ $(libibm_la_SOURCES) $(libkodak_la_SOURCES) \ $(libkodakaio_la_SOURCES) $(libkvs1025_la_SOURCES) \ $(libkvs20xx_la_SOURCES) $(libkvs40xx_la_SOURCES) \ $(libleo_la_SOURCES) $(liblexmark_la_SOURCES) \ $(libma1509_la_SOURCES) $(libmagicolor_la_SOURCES) \ $(libmatsushita_la_SOURCES) $(libmicrotek_la_SOURCES) \ $(libmicrotek2_la_SOURCES) $(libmustek_la_SOURCES) \ $(libmustek_pp_la_SOURCES) $(libmustek_usb_la_SOURCES) \ $(libmustek_usb2_la_SOURCES) $(libnec_la_SOURCES) \ $(libnet_la_SOURCES) $(libniash_la_SOURCES) \ $(libp5_la_SOURCES) $(libpie_la_SOURCES) \ $(libpieusb_la_SOURCES) $(libpint_la_SOURCES) \ $(libpixma_la_SOURCES) $(libplustek_la_SOURCES) \ $(libplustek_pp_la_SOURCES) $(libpnm_la_SOURCES) \ $(libqcam_la_SOURCES) $(libricoh_la_SOURCES) \ $(librts8891_la_SOURCES) $(libs9036_la_SOURCES) \ $(nodist_libsane_abaton_la_SOURCES) \ $(nodist_libsane_agfafocus_la_SOURCES) \ $(nodist_libsane_apple_la_SOURCES) \ $(nodist_libsane_artec_la_SOURCES) \ $(nodist_libsane_artec_eplus48u_la_SOURCES) \ $(nodist_libsane_as6e_la_SOURCES) \ $(nodist_libsane_avision_la_SOURCES) \ $(nodist_libsane_bh_la_SOURCES) \ $(nodist_libsane_canon_la_SOURCES) \ $(nodist_libsane_canon630u_la_SOURCES) \ $(nodist_libsane_canon_dr_la_SOURCES) \ $(nodist_libsane_canon_pp_la_SOURCES) \ $(nodist_libsane_cardscan_la_SOURCES) \ $(nodist_libsane_coolscan_la_SOURCES) \ $(nodist_libsane_coolscan2_la_SOURCES) \ $(nodist_libsane_coolscan3_la_SOURCES) \ $(nodist_libsane_dc210_la_SOURCES) \ $(nodist_libsane_dc240_la_SOURCES) \ $(nodist_libsane_dc25_la_SOURCES) \ $(nodist_libsane_dell1600n_net_la_SOURCES) \ $(nodist_libsane_dll_la_SOURCES) \ $(nodist_libsane_dmc_la_SOURCES) \ $(nodist_libsane_epjitsu_la_SOURCES) \ $(nodist_libsane_epson_la_SOURCES) \ $(nodist_libsane_epson2_la_SOURCES) \ $(nodist_libsane_epsonds_la_SOURCES) \ $(nodist_libsane_fujitsu_la_SOURCES) \ $(nodist_libsane_genesys_la_SOURCES) \ $(nodist_libsane_gphoto2_la_SOURCES) \ $(nodist_libsane_gt68xx_la_SOURCES) \ $(nodist_libsane_hp_la_SOURCES) \ $(nodist_libsane_hp3500_la_SOURCES) \ $(nodist_libsane_hp3900_la_SOURCES) \ $(nodist_libsane_hp4200_la_SOURCES) \ $(nodist_libsane_hp5400_la_SOURCES) \ $(nodist_libsane_hp5590_la_SOURCES) \ $(nodist_libsane_hpljm1005_la_SOURCES) \ $(nodist_libsane_hpsj5s_la_SOURCES) \ $(nodist_libsane_hs2p_la_SOURCES) \ $(nodist_libsane_ibm_la_SOURCES) \ $(nodist_libsane_kodak_la_SOURCES) \ $(nodist_libsane_kodakaio_la_SOURCES) \ $(nodist_libsane_kvs1025_la_SOURCES) \ $(nodist_libsane_kvs20xx_la_SOURCES) \ $(nodist_libsane_kvs40xx_la_SOURCES) \ $(nodist_libsane_leo_la_SOURCES) \ $(nodist_libsane_lexmark_la_SOURCES) \ $(nodist_libsane_ma1509_la_SOURCES) \ $(nodist_libsane_magicolor_la_SOURCES) \ $(nodist_libsane_matsushita_la_SOURCES) \ $(nodist_libsane_microtek_la_SOURCES) \ $(nodist_libsane_microtek2_la_SOURCES) \ $(nodist_libsane_mustek_la_SOURCES) \ $(nodist_libsane_mustek_pp_la_SOURCES) \ $(nodist_libsane_mustek_usb_la_SOURCES) \ $(nodist_libsane_mustek_usb2_la_SOURCES) \ $(nodist_libsane_nec_la_SOURCES) \ $(nodist_libsane_net_la_SOURCES) \ $(nodist_libsane_niash_la_SOURCES) \ $(nodist_libsane_p5_la_SOURCES) \ $(nodist_libsane_pie_la_SOURCES) \ $(nodist_libsane_pieusb_la_SOURCES) \ $(nodist_libsane_pint_la_SOURCES) \ $(nodist_libsane_pixma_la_SOURCES) \ $(nodist_libsane_plustek_la_SOURCES) \ $(nodist_libsane_plustek_pp_la_SOURCES) \ $(nodist_libsane_pnm_la_SOURCES) \ $(nodist_libsane_qcam_la_SOURCES) \ $(nodist_libsane_ricoh_la_SOURCES) \ $(nodist_libsane_rts8891_la_SOURCES) \ $(nodist_libsane_s9036_la_SOURCES) \ $(nodist_libsane_sceptre_la_SOURCES) \ $(nodist_libsane_sharp_la_SOURCES) \ $(nodist_libsane_sm3600_la_SOURCES) \ $(nodist_libsane_sm3840_la_SOURCES) \ $(nodist_libsane_snapscan_la_SOURCES) \ $(nodist_libsane_sp15c_la_SOURCES) \ $(nodist_libsane_st400_la_SOURCES) \ $(nodist_libsane_stv680_la_SOURCES) \ $(nodist_libsane_tamarack_la_SOURCES) \ $(nodist_libsane_teco1_la_SOURCES) \ $(nodist_libsane_teco2_la_SOURCES) \ $(nodist_libsane_teco3_la_SOURCES) \ $(nodist_libsane_test_la_SOURCES) \ $(nodist_libsane_u12_la_SOURCES) \ $(nodist_libsane_umax_la_SOURCES) \ $(nodist_libsane_umax1220u_la_SOURCES) \ $(nodist_libsane_umax_pp_la_SOURCES) \ $(nodist_libsane_v4l_la_SOURCES) \ $(nodist_libsane_xerox_mfp_la_SOURCES) \ $(nodist_libsane_la_SOURCES) $(libsceptre_la_SOURCES) \ $(libsharp_la_SOURCES) $(libsm3600_la_SOURCES) \ $(libsm3840_la_SOURCES) $(libsnapscan_la_SOURCES) \ $(libsp15c_la_SOURCES) $(libst400_la_SOURCES) \ $(libstv680_la_SOURCES) $(libtamarack_la_SOURCES) \ $(libteco1_la_SOURCES) $(libteco2_la_SOURCES) \ $(libteco3_la_SOURCES) $(libtest_la_SOURCES) \ $(libu12_la_SOURCES) $(libumax_la_SOURCES) \ $(libumax1220u_la_SOURCES) $(libumax_pp_la_SOURCES) \ $(libv4l_la_SOURCES) $(libxerox_mfp_la_SOURCES) DIST_SOURCES = $(libabaton_la_SOURCES) $(libagfafocus_la_SOURCES) \ $(libapple_la_SOURCES) $(libartec_la_SOURCES) \ $(libartec_eplus48u_la_SOURCES) $(libas6e_la_SOURCES) \ $(libavision_la_SOURCES) $(libbh_la_SOURCES) \ $(libcanon_la_SOURCES) $(libcanon630u_la_SOURCES) \ $(libcanon_dr_la_SOURCES) $(libcanon_pp_la_SOURCES) \ $(libcardscan_la_SOURCES) $(libcoolscan_la_SOURCES) \ $(libcoolscan2_la_SOURCES) $(libcoolscan3_la_SOURCES) \ $(libdc210_la_SOURCES) $(libdc240_la_SOURCES) \ $(libdc25_la_SOURCES) $(libdell1600n_net_la_SOURCES) \ $(libdll_la_SOURCES) $(libdll_preload_la_SOURCES) \ $(libdmc_la_SOURCES) $(libepjitsu_la_SOURCES) \ $(libepson_la_SOURCES) $(libepson2_la_SOURCES) \ $(libepsonds_la_SOURCES) $(libfujitsu_la_SOURCES) \ $(libgenesys_la_SOURCES) $(libgphoto2_i_la_SOURCES) \ $(libgt68xx_la_SOURCES) $(libhp_la_SOURCES) \ $(libhp3500_la_SOURCES) $(libhp3900_la_SOURCES) \ $(libhp4200_la_SOURCES) $(libhp5400_la_SOURCES) \ $(libhp5590_la_SOURCES) $(libhpljm1005_la_SOURCES) \ $(libhpsj5s_la_SOURCES) $(libhs2p_la_SOURCES) \ $(libibm_la_SOURCES) $(libkodak_la_SOURCES) \ $(libkodakaio_la_SOURCES) $(libkvs1025_la_SOURCES) \ $(libkvs20xx_la_SOURCES) $(libkvs40xx_la_SOURCES) \ $(libleo_la_SOURCES) $(liblexmark_la_SOURCES) \ $(libma1509_la_SOURCES) $(libmagicolor_la_SOURCES) \ $(libmatsushita_la_SOURCES) $(libmicrotek_la_SOURCES) \ $(libmicrotek2_la_SOURCES) $(libmustek_la_SOURCES) \ $(libmustek_pp_la_SOURCES) $(libmustek_usb_la_SOURCES) \ $(libmustek_usb2_la_SOURCES) $(libnec_la_SOURCES) \ $(libnet_la_SOURCES) $(libniash_la_SOURCES) \ $(libp5_la_SOURCES) $(libpie_la_SOURCES) \ $(libpieusb_la_SOURCES) $(libpint_la_SOURCES) \ $(libpixma_la_SOURCES) $(libplustek_la_SOURCES) \ $(libplustek_pp_la_SOURCES) $(libpnm_la_SOURCES) \ $(libqcam_la_SOURCES) $(libricoh_la_SOURCES) \ $(librts8891_la_SOURCES) $(libs9036_la_SOURCES) \ $(libsceptre_la_SOURCES) $(libsharp_la_SOURCES) \ $(libsm3600_la_SOURCES) $(libsm3840_la_SOURCES) \ $(libsnapscan_la_SOURCES) $(libsp15c_la_SOURCES) \ $(libst400_la_SOURCES) $(libstv680_la_SOURCES) \ $(libtamarack_la_SOURCES) $(libteco1_la_SOURCES) \ $(libteco2_la_SOURCES) $(libteco3_la_SOURCES) \ $(libtest_la_SOURCES) $(libu12_la_SOURCES) \ $(libumax_la_SOURCES) $(libumax1220u_la_SOURCES) \ $(libumax_pp_la_SOURCES) $(libv4l_la_SOURCES) \ $(libxerox_mfp_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir)/include \ -I$(top_srcdir)/include $(USB_CFLAGS) \ -DLIBDIR="\"$(libdir)/sane\"" AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ $(STRICT_LDFLAGS) AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AVAHI_CFLAGS = @AVAHI_CFLAGS@ AVAHI_LIBS = @AVAHI_LIBS@ AWK = @AWK@ BACKENDS = @BACKENDS@ BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@ BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@ BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLH = @DLH@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ DYNAMIC_FLAG = @DYNAMIC_FLAG@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIG2DEV = @FIG2DEV@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@ GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@ GPHOTO2_LIBS = @GPHOTO2_LIBS@ GREP = @GREP@ GS = @GS@ HAVE_GPHOTO2 = @HAVE_GPHOTO2@ IEEE1284_LIBS = @IEEE1284_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_LOCKPATH = @INSTALL_LOCKPATH@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JPEG_LIBS = @JPEG_LIBS@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ # LIBTOOL install is a little to noisy for my liking. LIBTOOL = @LIBTOOL@ --silent LIBV4L_CFLAGS = @LIBV4L_CFLAGS@ LIBV4L_LIBS = @LIBV4L_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LOCKPATH_GROUP = @LOCKPATH_GROUP@ LTALLOCA = @LTALLOCA@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINDEX = @MAKEINDEX@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MATH_LIB = @MATH_LIB@ MKDIR_P = @MKDIR_P@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PDFLATEX = @PDFLATEX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_LIBS = @PNG_LIBS@ POSUB = @POSUB@ PPMTOGIF = @PPMTOGIF@ PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@ PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ RESMGR_LIBS = @RESMGR_LIBS@ SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@ SANE_CONFIG_PATH = @SANE_CONFIG_PATH@ SCSI_LIBS = @SCSI_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@ SNMP_LIBS = @SNMP_LIBS@ SOCKET_LIBS = @SOCKET_LIBS@ STRICT_LDFLAGS = @STRICT_LDFLAGS@ STRIP = @STRIP@ SYSLOG_LIBS = @SYSLOG_LIBS@ SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ SYSTEMD_LIBS = @SYSTEMD_LIBS@ TIFF_LIBS = @TIFF_LIBS@ USB_CFLAGS = @USB_CFLAGS@ USB_LIBS = @USB_LIBS@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ V_MAJOR = @V_MAJOR@ V_MINOR = @V_MINOR@ V_REV = @V_REV@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ configdir = @configdir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ effective_target = @effective_target@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ locksanedir = @locksanedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # The -rpath option is added because we are creating _LTLIBRARIES based # on configure substitution. This causes automake to not know the # correct $libdir and must be added here. DIST_SANELIBS_LDFLAGS = $(AM_LDFLAGS) -rpath '$(libdir)/sane' -version-number $(V_MAJOR):$(V_MINOR):$(V_REV) $(DYNAMIC_FLAG) DIST_LIBS_LDFLAGS = $(AM_LDFLAGS) -rpath '$(libdir)' -version-number $(V_MAJOR):$(V_MINOR):$(V_REV) FIRMWARE_DIRS = artec_eplus48u gt68xx snapscan epjitsu # TODO: This really belongs together with the saned sources and # should be installed there as well. # TODO: Why are these distributed but not compiled? # TODO: Why are this distributed but not compiled? # TODO: Why are this distributed but not compiled? # TODO: Why are this distributed but not compiled? # TODO: These should be moved to ../docs/hp; don't belong here. # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why are these distributed but not compiled? # TODO: Why is this distributed but not installed? EXTRA_DIST = sane_strstatus.c stubs.c saned.conf.in abaton.conf.in \ agfafocus.conf.in apple.conf.in artec.conf.in \ artec_eplus48u.conf.in avision.conf.in bh.conf.in \ canon.conf.in canon-sane.c canon-scsi.c canon630u.conf.in \ canon630u-common.c lm9830.h canon_dr.conf.in canon_pp.conf.in \ cardscan.conf.in coolscan.conf.in coolscan2.conf.in \ coolscan3.conf.in dc25.conf.in dc210.conf.in dc240.conf.in \ dell1600n_net.conf.in dmc.conf.in epjitsu.conf.in \ epson.conf.in epson2.conf.in epsonds.conf.in fujitsu.conf.in \ genesys.conf.in genesys_conv.c genesys_conv_hlp.c \ genesys_devices.c gphoto2.conf.in gt68xx.conf.in \ gt68xx_devices.c gt68xx_generic.c gt68xx_generic.h \ gt68xx_gt6801.c gt68xx_gt6801.h gt68xx_gt6816.c \ gt68xx_gt6816.h gt68xx_high.c gt68xx_high.h gt68xx_low.c \ gt68xx_low.h gt68xx_mid.c gt68xx_mid.h gt68xx_shm_channel.c \ gt68xx_shm_channel.h hp.conf.in hp.README hp.TODO \ hp3900.conf.in hp3900_config.c hp3900_debug.c hp3900_rts8822.c \ hp3900_sane.c hp3900_types.c hp3900_usb.c hp4200.conf.in \ hp4200_lm9830.c hp4200_lm9830.h hp5400.conf.in hp5400_debug.c \ hp5400_debug.h hp5400_internal.c hp5400_internal.h \ hp5400_sane.c hp5400_sanei.c hp5400_sanei.h hp5400_xfer.h \ hp5590_cmds.c hp5590_cmds.h hp5590_low.c hp5590_low.h \ hpsj5s.conf.in hs2p.conf.in hs2p-scsi.c hs2p-scsi.h \ ibm.conf.in ibm-scsi.c kodak.conf.in kodakaio.conf.in \ kvs1025.conf.in leo.conf.in lexmark.conf.in lexmark_models.c \ lexmark_sensors.c ma1509.conf.in magicolor.conf.in \ matsushita.conf.in microtek.conf.in microtek2.conf.in \ mustek.conf.in mustek_scsi_pp.c mustek_scsi_pp.h \ mustek_pp.conf.in mustek_pp_ccd300.c mustek_pp_ccd300.h \ mustek_pp_cis.c mustek_pp_cis.h mustek_pp_null.c \ mustek_usb.conf.in mustek_usb_high.c mustek_usb_high.h \ mustek_usb_low.c mustek_usb_low.h mustek_usb_mid.c \ mustek_usb_mid.h mustek_usb2_asic.c mustek_usb2_asic.h \ mustek_usb2_high.c mustek_usb2_high.h mustek_usb2_reflective.c \ mustek_usb2_transparent.c nec.conf.in net.conf.in niash_core.c \ niash_core.h niash_xfer.c niash_xfer.h pie.conf.in \ pieusb.conf.in p5.conf.in p5_device.c pixma.conf.in \ pixma_sane_options.c pixma_sane_options.h plustek.conf.in \ plustek-usb.c plustek-usb.h plustek-usbcal.c \ plustek-usbcalfile.c plustek-usbdevs.c plustek-usbhw.c \ plustek-usbimg.c plustek-usbio.c plustek-usbmap.c \ plustek-usbscan.c plustek-usbshading.c plustek_pp.conf.in \ plustek-pp_dac.c plustek-pp_dbg.h plustek-pp_detect.c \ plustek-pp_genericio.c plustek-pp_hwdefs.h plustek-pp_image.c \ plustek-pp_io.c plustek-pp_map.c plustek-pp_misc.c \ plustek-pp_models.c plustek-pp_motor.c plustek-pp_p12.c \ plustek-pp_p12ccd.c plustek-pp_p48xx.c plustek-pp_p9636.c \ plustek-pp_procfs.c plustek-pp_procs.h plustek-pp_ptdrv.c \ plustek-pp_scale.c plustek-pp_scan.h plustek-pp_scandata.h \ plustek-pp_sysdep.h plustek-pp_tpa.c plustek-pp_types.h \ plustek-pp_wrapper.c qcam.conf.in ricoh.conf.in ricoh-scsi.c \ rts8891.conf.in rts8891_devices.c rts8891_low.c rts8891_low.h \ s9036.conf.in sceptre.conf.in sharp.conf.in sm3600-color.c \ sm3600-gray.c sm3600-homerun.c sm3600-scanmtek.c \ sm3600-scantool.h sm3600-scanusb.c sm3600-scanutil.c \ sm3840.conf.in sm3840_lib.c sm3840_lib.h sm3840_scan.c \ snapscan.conf.in snapscan-data.c snapscan-mutex.c \ snapscan-options.c snapscan-scsi.c snapscan-sources.c \ snapscan-sources.h snapscan-usb.c snapscan-usb.h sp15c.conf.in \ st400.conf.in stv680.conf.in tamarack.conf.in test.conf.in \ test-picture.c teco1.conf.in teco2.conf.in teco3.conf.in \ u12.conf.in u12-ccd.c u12-hw.c u12-hwdef.h u12-if.c \ u12-image.c u12-io.c u12-map.c u12-motor.c u12-scanner.h \ u12-shading.c u12-tpa.c umax.conf.in umax-scanner.c \ umax-scanner.h umax-scsidef.h umax-uc1200s.c umax-uc1200se.c \ umax-uc1260.c umax-uc630.c umax-uc840.c umax-ug630.c \ umax-ug80.c umax-usb.c umax1220u.conf.in umax1220u-common.c \ umax_pp.conf.in v4l.conf.in xerox_mfp.conf.in dll.conf.in \ dll.aliases # Backends are not required to have a config file. Any backend # that wants to install a config file should list it here. BACKEND_CONFS = abaton.conf agfafocus.conf apple.conf artec.conf \ artec_eplus48u.conf avision.conf bh.conf \ canon630u.conf canon.conf canon_dr.conf \ canon_pp.conf cardscan.conf coolscan2.conf coolscan3.conf \ coolscan.conf dc210.conf dc240.conf dc25.conf \ dell1600n_net.conf dmc.conf epjitsu.conf epson2.conf \ epson.conf epsonds.conf fujitsu.conf genesys.conf gphoto2.conf \ gt68xx.conf hp3900.conf hp4200.conf hp5400.conf \ hp.conf hpsj5s.conf hs2p.conf ibm.conf kodak.conf kodakaio.conf\ kvs1025.conf \ leo.conf lexmark.conf ma1509.conf magicolor.conf \ matsushita.conf microtek2.conf microtek.conf mustek.conf \ mustek_pp.conf mustek_usb.conf nec.conf net.conf \ p5.conf \ pie.conf pieusb.conf pixma.conf plustek.conf plustek_pp.conf \ qcam.conf ricoh.conf rts8891.conf s9036.conf sceptre.conf \ sharp.conf sm3840.conf snapscan.conf sp15c.conf \ st400.conf stv680.conf tamarack.conf \ teco1.conf teco2.conf teco3.conf test.conf \ u12.conf umax1220u.conf umax.conf umax_pp.conf v4l.conf \ xerox_mfp.conf dll.conf saned.conf SUFFIXES = .conf.in .conf CLEANFILES = $(BACKEND_CONFS) $(be_convenience_libs) dll-preload.h # Backends # # All possible backends should be listed here. As a first step, we create # a convenience library containing all files needed to link a backend # directly into libsane.la. Convenience library should have the # form of lib${backend}.la to match what configure will list to # build. # Occasionally, this approach will have name conflicts with external # libraries that need to be linked in. See libgphoto2_i.la for # example of working around that issue. be_convenience_libs = libabaton.la libagfafocus.la \ libapple.la libartec.la libartec_eplus48u.la \ libas6e.la libavision.la libbh.la \ libcanon.la libcanon630u.la libcanon_dr.la \ libcanon_pp.la libcardscan.la libcoolscan.la \ libcoolscan2.la libcoolscan3.la libdc25.la \ libdc210.la libdc240.la libdell1600n_net.la \ libdmc.la libdll.la libdll_preload.la libepjitsu.la libepson.la \ libepson2.la libepsonds.la libfujitsu.la libgenesys.la \ libgphoto2_i.la libgt68xx.la libhp.la \ libhp3500.la libhp3900.la libhp4200.la \ libhp5400.la libhp5590.la libhpljm1005.la \ libhpsj5s.la libhs2p.la libibm.la libkodak.la libkodakaio.la\ libkvs1025.la libkvs20xx.la libkvs40xx.la \ libleo.la liblexmark.la libma1509.la libmagicolor.la \ libmatsushita.la libmicrotek.la libmicrotek2.la \ libmustek.la libmustek_pp.la libmustek_usb.la \ libmustek_usb2.la libnec.la libnet.la \ libniash.la libp5.la \ libpie.la libpieusb.la libpint.la libpixma.la \ libplustek.la libplustek_pp.la libpnm.la \ libqcam.la libricoh.la librts8891.la \ libs9036.la libsceptre.la libsharp.la \ libsm3600.la libsm3840.la libsnapscan.la \ libsp15c.la libst400.la libstv680.la \ libtamarack.la libtest.la libteco1.la \ libteco2.la libteco3.la libu12.la libumax.la \ libumax1220u.la libumax_pp.la libv4l.la \ libxerox_mfp.la # Each stand alone backend thats possible to be built should be listed # here. There are the libraries that are installed under $(libdir)/sane. # Format is libsane-${backend}.la. be_dlopen_libs = libsane-abaton.la libsane-agfafocus.la \ libsane-apple.la libsane-artec.la libsane-artec_eplus48u.la \ libsane-as6e.la libsane-avision.la libsane-bh.la \ libsane-canon.la libsane-canon630u.la libsane-canon_dr.la \ libsane-canon_pp.la libsane-cardscan.la libsane-coolscan.la \ libsane-coolscan2.la libsane-coolscan3.la libsane-dc25.la \ libsane-dc210.la libsane-dc240.la libsane-dell1600n_net.la \ libsane-dmc.la libsane-epjitsu.la libsane-epson.la \ libsane-epson2.la libsane-epsonds.la libsane-fujitsu.la libsane-genesys.la \ libsane-gphoto2.la libsane-gt68xx.la libsane-hp.la \ libsane-hp3500.la libsane-hp3900.la libsane-hp4200.la \ libsane-hp5400.la libsane-hp5590.la libsane-hpljm1005.la \ libsane-hpsj5s.la libsane-hs2p.la libsane-ibm.la libsane-kodak.la libsane-kodakaio.la\ libsane-kvs1025.la libsane-kvs20xx.la libsane-kvs40xx.la \ libsane-leo.la \ libsane-lexmark.la libsane-ma1509.la libsane-magicolor.la \ libsane-matsushita.la libsane-microtek.la libsane-microtek2.la \ libsane-mustek.la libsane-mustek_pp.la libsane-mustek_usb.la \ libsane-mustek_usb2.la libsane-nec.la libsane-net.la \ libsane-niash.la libsane-p5.la \ libsane-pie.la libsane-pieusb.la libsane-pint.la libsane-pixma.la \ libsane-plustek.la libsane-plustek_pp.la libsane-pnm.la \ libsane-qcam.la libsane-ricoh.la libsane-rts8891.la \ libsane-s9036.la libsane-sceptre.la libsane-sharp.la \ libsane-sm3600.la libsane-sm3840.la libsane-snapscan.la \ libsane-sp15c.la libsane-st400.la libsane-stv680.la \ libsane-tamarack.la libsane-test.la libsane-teco1.la \ libsane-teco2.la libsane-teco3.la libsane-u12.la libsane-umax.la \ libsane-umax1220u.la libsane-umax_pp.la libsane-v4l.la \ libsane-xerox_mfp.la EXTRA_LTLIBRARIES = $(be_convenience_libs) $(be_dlopen_libs) lib_LTLIBRARIES = libsane.la sanelibdir = $(libdir)/sane sanelib_LTLIBRARIES = $(BACKEND_LIBS_ENABLED) libsane-dll.la COMMON_LIBS = ../lib/liblib.la # Each backend should define a convenience library that compiles # all related files within backend directory. General guideline # is to have a ${backend}.c and ${backend}.h. Some backends also # add a few support source files to convience library. # Note: automake doesn't really use header files listed here. # They are indications that they need to be distributed only. libabaton_la_SOURCES = abaton.c abaton.h libabaton_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=abaton # Each backend should define a stand alone library that gets installed. # This will need to link in a special file ${backend}-s.c that allows # the backend to be stand alone and contain all SANE API functions. # Also, it will need to link in related convenience library as well as # any external libraries required to resolve symbols. # # All backends should include $(DIST_SANELIBS_LDFLAGS) so that # library is correctly versioned. # # If a backend has a config file, it must be listed here to get distributed. nodist_libsane_abaton_la_SOURCES = abaton-s.c libsane_abaton_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=abaton libsane_abaton_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_abaton_la_LIBADD = $(COMMON_LIBS) libabaton.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libagfafocus_la_SOURCES = agfafocus.c agfafocus.h libagfafocus_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=agfafocus nodist_libsane_agfafocus_la_SOURCES = agfafocus-s.c libsane_agfafocus_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=agfafocus libsane_agfafocus_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_agfafocus_la_LIBADD = $(COMMON_LIBS) libagfafocus.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libapple_la_SOURCES = apple.c apple.h libapple_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=apple nodist_libsane_apple_la_SOURCES = apple-s.c libsane_apple_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=apple libsane_apple_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_apple_la_LIBADD = $(COMMON_LIBS) libapple.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libartec_la_SOURCES = artec.c artec.h libartec_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec nodist_libsane_artec_la_SOURCES = artec-s.c libsane_artec_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_artec_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec libsane_artec_la_LIBADD = $(COMMON_LIBS) libartec.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libartec_eplus48u_la_SOURCES = artec_eplus48u.c artec_eplus48u.h libartec_eplus48u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec_eplus48u nodist_libsane_artec_eplus48u_la_SOURCES = artec_eplus48u-s.c libsane_artec_eplus48u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec_eplus48u libsane_artec_eplus48u_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_artec_eplus48u_la_LIBADD = $(COMMON_LIBS) libartec_eplus48u.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMEG_LIBS) libas6e_la_SOURCES = as6e.c as6e.h libas6e_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=as6e nodist_libsane_as6e_la_SOURCES = as6e-s.c libsane_as6e_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=as6e libsane_as6e_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_as6e_la_LIBADD = $(COMMON_LIBS) libas6e.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo libavision_la_SOURCES = avision.c avision.h libavision_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=avision nodist_libsane_avision_la_SOURCES = avision-s.c libsane_avision_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=avision libsane_avision_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_avision_la_LIBADD = $(COMMON_LIBS) libavision.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libbh_la_SOURCES = bh.c bh.h libbh_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=bh nodist_libsane_bh_la_SOURCES = bh-s.c libsane_bh_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=bh libsane_bh_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_bh_la_LIBADD = $(COMMON_LIBS) libbh.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libcanon_la_SOURCES = canon.c canon.h libcanon_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon nodist_libsane_canon_la_SOURCES = canon-s.c libsane_canon_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon libsane_canon_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_canon_la_LIBADD = $(COMMON_LIBS) libcanon.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(RESMGR_LIBS) libcanon630u_la_SOURCES = canon630u.c libcanon630u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon630u nodist_libsane_canon630u_la_SOURCES = canon630u-s.c libsane_canon630u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon630u libsane_canon630u_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_canon630u_la_LIBADD = $(COMMON_LIBS) libcanon630u.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libcanon_dr_la_SOURCES = canon_dr.c canon_dr.h canon_dr-cmd.h libcanon_dr_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_dr nodist_libsane_canon_dr_la_SOURCES = canon_dr-s.c libsane_canon_dr_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_dr libsane_canon_dr_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_canon_dr_la_LIBADD = $(COMMON_LIBS) libcanon_dr.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_magic.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libcanon_pp_la_SOURCES = canon_pp.c canon_pp.h canon_pp-io.c canon_pp-io.h canon_pp-dev.c canon_pp-dev.h libcanon_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_pp nodist_libsane_canon_pp_la_SOURCES = canon_pp-s.c libsane_canon_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_pp libsane_canon_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_canon_pp_la_LIBADD = $(COMMON_LIBS) libcanon_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(IEEE1284_LIBS) libcardscan_la_SOURCES = cardscan.c cardscan.h libcardscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=cardscan nodist_libsane_cardscan_la_SOURCES = cardscan-s.c libsane_cardscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=cardscan libsane_cardscan_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_cardscan_la_LIBADD = $(COMMON_LIBS) libcardscan.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) libcoolscan_la_SOURCES = coolscan.c coolscan.h coolscan-scsidef.h libcoolscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan nodist_libsane_coolscan_la_SOURCES = coolscan-s.c libsane_coolscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan libsane_coolscan_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_coolscan_la_LIBADD = $(COMMON_LIBS) libcoolscan.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libcoolscan2_la_SOURCES = coolscan2.c libcoolscan2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan2 nodist_libsane_coolscan2_la_SOURCES = coolscan2-s.c libsane_coolscan2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan2 libsane_coolscan2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_coolscan2_la_LIBADD = $(COMMON_LIBS) libcoolscan2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libcoolscan3_la_SOURCES = coolscan3.c libcoolscan3_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan3 nodist_libsane_coolscan3_la_SOURCES = coolscan3-s.c libsane_coolscan3_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan3 libsane_coolscan3_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_coolscan3_la_LIBADD = $(COMMON_LIBS) libcoolscan3.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libdc25_la_SOURCES = dc25.c dc25.h libdc25_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc25 nodist_libsane_dc25_la_SOURCES = dc25-s.c libsane_dc25_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc25 libsane_dc25_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dc25_la_LIBADD = $(COMMON_LIBS) libdc25.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(MATH_LIB) libdc210_la_SOURCES = dc210.c dc210.h libdc210_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc210 nodist_libsane_dc210_la_SOURCES = dc210-s.c libsane_dc210_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc210 libsane_dc210_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dc210_la_LIBADD = $(COMMON_LIBS) libdc210.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) libdc240_la_SOURCES = dc240.c dc240.h libdc240_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc240 nodist_libsane_dc240_la_SOURCES = dc240-s.c libsane_dc240_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc240 libsane_dc240_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dc240_la_LIBADD = $(COMMON_LIBS) libdc240.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) libdell1600n_net_la_SOURCES = dell1600n_net.c libdell1600n_net_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dell1600n_net nodist_libsane_dell1600n_net_la_SOURCES = dell1600n_net-s.c libsane_dell1600n_net_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dell1600n_net libsane_dell1600n_net_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dell1600n_net_la_LIBADD = $(COMMON_LIBS) libdell1600n_net.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(TIFF_LIBS) $(JPEG_LIBS) $(SOCKET_LIBS) libdmc_la_SOURCES = dmc.c dmc.h libdmc_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dmc nodist_libsane_dmc_la_SOURCES = dmc-s.c libsane_dmc_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dmc libsane_dmc_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dmc_la_LIBADD = $(COMMON_LIBS) libdmc.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libepjitsu_la_SOURCES = epjitsu.c epjitsu.h epjitsu-cmd.h libepjitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epjitsu nodist_libsane_epjitsu_la_SOURCES = epjitsu-s.c libsane_epjitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epjitsu libsane_epjitsu_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_epjitsu_la_LIBADD = $(COMMON_LIBS) libepjitsu.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libepson_la_SOURCES = epson.c epson.h epson_scsi.c epson_scsi.h epson_usb.c epson_usb.h libepson_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson nodist_libsane_epson_la_SOURCES = epson-s.c libsane_epson_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson libsane_epson_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_epson_la_LIBADD = $(COMMON_LIBS) libepson.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libepson2_la_SOURCES = epson2.c epson2.h epson2_scsi.c epson2_scsi.h epson2_usb.c epson2_net.c epson2_net.h epson2-io.c epson2-io.h epson2-commands.c epson2-commands.h epson2-ops.c epson2-ops.h epson2-cct.c libepson2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson2 nodist_libsane_epson2_la_SOURCES = epson2-s.c libsane_epson2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson2 libsane_epson2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_epson2_la_LIBADD = $(COMMON_LIBS) libepson2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(SCSI_LIBS) $(USB_LIBS) $(SOCKET_LIBS) $(MATH_LIB) $(RESMGR_LIBS) libepsonds_la_SOURCES = epsonds.c epsonds.h epsonds-usb.c epsonds-usb.h epsonds-io.c epsonds-io.h \ epsonds-cmd.c epsonds-cmd.h epsonds-ops.c epsonds-ops.h epsonds-jpeg.c epsonds-jpeg.h \ epsonds-net.c epsonds-net.h libepsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds nodist_libsane_epsonds_la_SOURCES = epsonds-s.c libsane_epsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds libsane_epsonds_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_epsonds_la_LIBADD = $(COMMON_LIBS) libepsonds.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo \ $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS) $(SOCKET_LIBS) libfujitsu_la_SOURCES = fujitsu.c fujitsu.h fujitsu-scsi.h libfujitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=fujitsu nodist_libsane_fujitsu_la_SOURCES = fujitsu-s.c libsane_fujitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=fujitsu libsane_fujitsu_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_fujitsu_la_LIBADD = $(COMMON_LIBS) libfujitsu.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_magic.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libgenesys_la_SOURCES = genesys.c genesys.h genesys_gl646.c genesys_gl646.h genesys_gl841.c genesys_gl841.h genesys_gl843.c genesys_gl843.h genesys_gl846.c genesys_gl846.h genesys_gl847.c genesys_gl847.h genesys_gl124.c genesys_gl124.h genesys_low.c genesys_low.h libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys nodist_libsane_genesys_la_SOURCES = genesys-s.c libsane_genesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys libsane_genesys_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libgphoto2_i_la_SOURCES = gphoto2.c gphoto2.h libgphoto2_i_la_CPPFLAGS = $(AM_CPPFLAGS) $(GPHOTO2_CPPFLAGS) -DBACKEND_NAME=gphoto2 nodist_libsane_gphoto2_la_SOURCES = gphoto2-s.c libsane_gphoto2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=gphoto2 libsane_gphoto2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_gphoto2_la_LIBADD = $(GPHOTO2_LDFLAGS) $(COMMON_LIBS) libgphoto2_i.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(SANEI_SANEI_JPEG_LO) $(GPHOTO2_LIBS) $(JPEG_LIBS) libgt68xx_la_SOURCES = gt68xx.c gt68xx.h libgt68xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=gt68xx nodist_libsane_gt68xx_la_SOURCES = gt68xx-s.c libsane_gt68xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=gt68xx libsane_gt68xx_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_gt68xx_la_LIBADD = $(COMMON_LIBS) libgt68xx.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libhp_la_SOURCES = hp.c hp.h hp-accessor.c hp-accessor.h hp-device.c hp-device.h hp-handle.c hp-handle.h hp-hpmem.c hp-option.c hp-option.h hp-scl.c hp-scl.h hp-scsi.h libhp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp nodist_libsane_hp_la_SOURCES = hp-s.c libsane_hp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp libsane_hp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp_la_LIBADD = $(COMMON_LIBS) libhp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libhp3500_la_SOURCES = hp3500.c libhp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500 nodist_libsane_hp3500_la_SOURCES = hp3500-s.c libsane_hp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500 libsane_hp3500_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp3500_la_LIBADD = $(COMMON_LIBS) libhp3500.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libhp3900_la_SOURCES = hp3900.c libhp3900_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3900 nodist_libsane_hp3900_la_SOURCES = hp3900-s.c libsane_hp3900_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3900 libsane_hp3900_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp3900_la_LIBADD = $(COMMON_LIBS) libhp3900.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(TIFF_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libhp4200_la_SOURCES = hp4200.c hp4200.h libhp4200_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp4200 nodist_libsane_hp4200_la_SOURCES = hp4200-s.c libsane_hp4200_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp4200 libsane_hp4200_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp4200_la_LIBADD = $(COMMON_LIBS) libhp4200.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_pv8630.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libhp5400_la_SOURCES = hp5400.c hp5400.h libhp5400_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp5400 nodist_libsane_hp5400_la_SOURCES = hp5400-s.c libsane_hp5400_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp5400 libsane_hp5400_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp5400_la_LIBADD = $(COMMON_LIBS) libhp5400.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) libhp5590_la_SOURCES = hp5590.c libhp5590_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp5590 nodist_libsane_hp5590_la_SOURCES = hp5590-s.c libsane_hp5590_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp5590 libsane_hp5590_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp5590_la_LIBADD = $(COMMON_LIBS) libhp5590.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) libhpljm1005_la_SOURCES = hpljm1005.c libhpljm1005_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hpljm1005 nodist_libsane_hpljm1005_la_SOURCES = hpljm1005-s.c libsane_hpljm1005_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hpljm1005 libsane_hpljm1005_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hpljm1005_la_LIBADD = $(COMMON_LIBS) libhpljm1005.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libhpsj5s_la_SOURCES = hpsj5s.c hpsj5s.h libhpsj5s_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hpsj5s nodist_libsane_hpsj5s_la_SOURCES = hpsj5s-s.c libsane_hpsj5s_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hpsj5s libsane_hpsj5s_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hpsj5s_la_LIBADD = $(COMMON_LIBS) libhpsj5s.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(IEEE1284_LIBS) libhs2p_la_SOURCES = hs2p.c hs2p.h hs2p-saneopts.h libhs2p_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hs2p nodist_libsane_hs2p_la_SOURCES = hs2p-s.c libsane_hs2p_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hs2p libsane_hs2p_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hs2p_la_LIBADD = $(COMMON_LIBS) libhs2p.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libibm_la_SOURCES = ibm.c ibm.h libibm_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ibm nodist_libsane_ibm_la_SOURCES = ibm-s.c libsane_ibm_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ibm libsane_ibm_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_ibm_la_LIBADD = $(COMMON_LIBS) libibm.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libkodak_la_SOURCES = kodak.c kodak.h kodak-cmd.h libkodak_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodak nodist_libsane_kodak_la_SOURCES = kodak-s.c libsane_kodak_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodak libsane_kodak_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kodak_la_LIBADD = $(COMMON_LIBS) libkodak.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libkodakaio_la_SOURCES = kodakaio.c kodakaio.h libkodakaio_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodakaio nodist_libsane_kodakaio_la_SOURCES = kodakaio-s.c libsane_kodakaio_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodakaio libsane_kodakaio_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kodakaio_la_LIBADD = $(COMMON_LIBS) libkodakaio.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(USB_LIBS) $(SOCKET_LIBS) $(AVAHI_LIBS) $(MATH_LIB) $(RESMGR_LIBS) libkvs1025_la_SOURCES = kvs1025.c kvs1025_low.c kvs1025_opt.c kvs1025_usb.c \ kvs1025.h kvs1025_low.h kvs1025_usb.h kvs1025_cmds.h libkvs1025_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs1025 nodist_libsane_kvs1025_la_SOURCES = kvs1025-s.c libsane_kvs1025_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs1025 libsane_kvs1025_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kvs1025_la_LIBADD = $(COMMON_LIBS) libkvs1025.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_magic.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libkvs20xx_la_SOURCES = kvs20xx.c kvs20xx_cmd.c kvs20xx_opt.c \ kvs20xx_cmd.h kvs20xx.h libkvs20xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs20xx nodist_libsane_kvs20xx_la_SOURCES = kvs20xx-s.c libsane_kvs20xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs20xx libsane_kvs20xx_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kvs20xx_la_LIBADD = $(COMMON_LIBS) libkvs20xx.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libkvs40xx_la_SOURCES = kvs40xx.c kvs40xx_cmd.c kvs40xx_opt.c \ kvs40xx.h libkvs40xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs40xx nodist_libsane_kvs40xx_la_SOURCES = kvs40xx-s.c libsane_kvs40xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs40xx libsane_kvs40xx_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kvs40xx_la_LIBADD = $(COMMON_LIBS) libkvs40xx.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libleo_la_SOURCES = leo.c leo.h libleo_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=leo nodist_libsane_leo_la_SOURCES = leo-s.c libsane_leo_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=leo libsane_leo_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_leo_la_LIBADD = $(COMMON_LIBS) libleo.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) liblexmark_la_SOURCES = lexmark.c lexmark.h lexmark_low.c liblexmark_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=lexmark nodist_libsane_lexmark_la_SOURCES = lexmark-s.c libsane_lexmark_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=lexmark libsane_lexmark_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_lexmark_la_LIBADD = $(COMMON_LIBS) liblexmark.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) libma1509_la_SOURCES = ma1509.c ma1509.h libma1509_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ma1509 nodist_libsane_ma1509_la_SOURCES = ma1509-s.c libsane_ma1509_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ma1509 libsane_ma1509_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_ma1509_la_LIBADD = $(COMMON_LIBS) libma1509.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) libmagicolor_la_SOURCES = magicolor.c magicolor.h libmagicolor_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=magicolor $(SNMP_CFLAGS) nodist_libsane_magicolor_la_SOURCES = magicolor-s.c libsane_magicolor_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=magicolor libsane_magicolor_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_magicolor_la_LIBADD = $(COMMON_LIBS) libmagicolor.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(USB_LIBS) $(SOCKET_LIBS) $(MATH_LIB) $(RESMGR_LIBS) $(SNMP_LIBS) libmatsushita_la_SOURCES = matsushita.c matsushita.h libmatsushita_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=matsushita nodist_libsane_matsushita_la_SOURCES = matsushita-s.c libsane_matsushita_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=matsushita libsane_matsushita_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_matsushita_la_LIBADD = $(COMMON_LIBS) libmatsushita.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libmicrotek_la_SOURCES = microtek.c microtek.h libmicrotek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek nodist_libsane_microtek_la_SOURCES = microtek-s.c libsane_microtek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek libsane_microtek_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_microtek_la_LIBADD = $(COMMON_LIBS) libmicrotek.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(RESMGR_LIBS) libmicrotek2_la_SOURCES = microtek2.c microtek2.h libmicrotek2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek2 nodist_libsane_microtek2_la_SOURCES = microtek2-s.c libsane_microtek2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek2 libsane_microtek2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_microtek2_la_LIBADD = $(COMMON_LIBS) libmicrotek2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libmustek_la_SOURCES = mustek.c mustek.h libmustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek nodist_libsane_mustek_la_SOURCES = mustek-s.c libsane_mustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek libsane_mustek_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_mustek_la_LIBADD = $(COMMON_LIBS) libmustek.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pa4s2.lo $(IEEE1284_LIBS) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libmustek_pp_la_SOURCES = mustek_pp.c mustek_pp.h mustek_pp_decl.h mustek_pp_drivers.h libmustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_pp nodist_libsane_mustek_pp_la_SOURCES = mustek_pp-s.c libsane_mustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_pp libsane_mustek_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_mustek_pp_la_LIBADD = $(COMMON_LIBS) libmustek_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_pa4s2.lo $(MATH_LIB) $(IEEE1284_LIBS) libmustek_usb_la_SOURCES = mustek_usb.c mustek_usb.h libmustek_usb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb nodist_libsane_mustek_usb_la_SOURCES = mustek_usb-s.c libsane_mustek_usb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb libsane_mustek_usb_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_mustek_usb_la_LIBADD = $(COMMON_LIBS) libmustek_usb.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) libmustek_usb2_la_SOURCES = mustek_usb2.c mustek_usb2.h libmustek_usb2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb2 nodist_libsane_mustek_usb2_la_SOURCES = mustek_usb2-s.c libsane_mustek_usb2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb2 libsane_mustek_usb2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_mustek_usb2_la_LIBADD = $(COMMON_LIBS) libmustek_usb2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(PTHREAD_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libnec_la_SOURCES = nec.c nec.h libnec_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=nec nodist_libsane_nec_la_SOURCES = nec-s.c libsane_nec_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=nec libsane_nec_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_nec_la_LIBADD = $(COMMON_LIBS) libnec.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(RESMGR_LIBS) libnet_la_SOURCES = net.c net.h libnet_la_CPPFLAGS = $(AM_CPPFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=net nodist_libsane_net_la_SOURCES = net-s.c libsane_net_la_CPPFLAGS = $(AM_CPPFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=net libsane_net_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_net_la_LIBADD = $(COMMON_LIBS) libnet.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo $(AVAHI_LIBS) $(SOCKET_LIBS) libniash_la_SOURCES = niash.c libniash_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=niash nodist_libsane_niash_la_SOURCES = niash-s.c libsane_niash_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=niash libsane_niash_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_niash_la_LIBADD = $(COMMON_LIBS) libniash.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libpie_la_SOURCES = pie.c pie-scsidef.h libpie_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pie nodist_libsane_pie_la_SOURCES = pie-s.c libsane_pie_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pie libsane_pie_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pie_la_LIBADD = $(COMMON_LIBS) libpie.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libpieusb_la_SOURCES = pieusb.h pieusb_buffer.c pieusb_buffer.h pieusb_scancmd.c pieusb_scancmd.h pieusb_specific.c pieusb_specific.h pieusb_usb.c pieusb_usb.h pieusb.c libpieusb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pieusb nodist_libsane_pieusb_la_SOURCES = pieusb-s.c libsane_pieusb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pieusb libsane_pieusb_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pieusb_la_LIBADD = $(COMMON_LIBS) libpieusb.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo ../sanei/sanei_ir.lo ../sanei/sanei_magic.lo $(PTHREAD_LIBS) $(RESMGR_LIBS) $(USB_LIBS) $(MATH_LIB) libp5_la_SOURCES = p5.c p5.h p5_device.h libp5_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=p5 nodist_libsane_p5_la_SOURCES = p5-s.c libsane_p5_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=p5 libsane_p5_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_p5_la_LIBADD = $(COMMON_LIBS) libp5.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo libpint_la_SOURCES = pint.c pint.h libpint_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pint nodist_libsane_pint_la_SOURCES = pint-s.c libsane_pint_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pint libsane_pint_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pint_la_LIBADD = $(COMMON_LIBS) libpint.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo libpixma_la_SOURCES = pixma.c pixma.h pixma_io_sanei.c pixma_io.h pixma_common.c pixma_common.h pixma_mp150.c pixma_mp730.c pixma_mp750.c pixma_mp810.c pixma_imageclass.c pixma_bjnp.c pixma_bjnp.h pixma_bjnp_private.h pixma_rename.h libpixma_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pixma nodist_libsane_pixma_la_SOURCES = pixma-s.c libsane_pixma_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pixma libsane_pixma_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pixma_la_LIBADD = $(COMMON_LIBS) libpixma.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libplustek_la_SOURCES = plustek.c plustek.h libplustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek nodist_libsane_plustek_la_SOURCES = plustek-s.c libsane_plustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek libsane_plustek_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_plustek_la_LIBADD = $(COMMON_LIBS) libplustek.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libplustek_pp_la_SOURCES = plustek_pp.c plustek-pp.h libplustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek_pp nodist_libsane_plustek_pp_la_SOURCES = plustek_pp-s.c libsane_plustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek_pp libsane_plustek_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_plustek_pp_la_LIBADD = $(COMMON_LIBS) libplustek_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(IEEE1284_LIBS) $(PTHREAD_LIBS) libpnm_la_SOURCES = pnm.c libpnm_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pnm nodist_libsane_pnm_la_SOURCES = pnm-s.c libsane_pnm_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pnm libsane_pnm_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pnm_la_LIBADD = $(COMMON_LIBS) libpnm.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo libqcam_la_SOURCES = qcam.c qcam.h libqcam_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=qcam nodist_libsane_qcam_la_SOURCES = qcam-s.c libsane_qcam_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=qcam libsane_qcam_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_qcam_la_LIBADD = $(COMMON_LIBS) libqcam.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_pio.lo libricoh_la_SOURCES = ricoh.c ricoh.h libricoh_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ricoh nodist_libsane_ricoh_la_SOURCES = ricoh-s.c libsane_ricoh_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ricoh libsane_ricoh_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_ricoh_la_LIBADD = $(COMMON_LIBS) libricoh.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) librts8891_la_SOURCES = rts8891.c rts8891.h rts88xx_lib.c rts88xx_lib.h librts8891_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=rts8891 nodist_libsane_rts8891_la_SOURCES = rts8891-s.c libsane_rts8891_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=rts8891 libsane_rts8891_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_rts8891_la_LIBADD = $(COMMON_LIBS) librts8891.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_usb.lo $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) $(RESMGR_LIBS) libs9036_la_SOURCES = s9036.c s9036.h libs9036_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=s9036 nodist_libsane_s9036_la_SOURCES = s9036-s.c libsane_s9036_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=s9036 libsane_s9036_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_s9036_la_LIBADD = $(COMMON_LIBS) libs9036.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libsceptre_la_SOURCES = sceptre.c sceptre.h libsceptre_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sceptre nodist_libsane_sceptre_la_SOURCES = sceptre-s.c libsane_sceptre_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sceptre libsane_sceptre_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sceptre_la_LIBADD = $(COMMON_LIBS) libsceptre.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libsharp_la_SOURCES = sharp.c sharp.h libsharp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sharp nodist_libsane_sharp_la_SOURCES = sharp-s.c libsane_sharp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sharp libsane_sharp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sharp_la_LIBADD = $(COMMON_LIBS) libsharp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(RESMGR_LIBS) libsm3600_la_SOURCES = sm3600.c sm3600.h libsm3600_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sm3600 nodist_libsane_sm3600_la_SOURCES = sm3600-s.c libsane_sm3600_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sm3600 libsane_sm3600_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sm3600_la_LIBADD = $(COMMON_LIBS) libsm3600.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) libsm3840_la_SOURCES = sm3840.c sm3840.h sm3840_params.h libsm3840_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sm3840 nodist_libsane_sm3840_la_SOURCES = sm3840-s.c libsane_sm3840_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sm3840 libsane_sm3840_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sm3840_la_LIBADD = $(COMMON_LIBS) libsm3840.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libsnapscan_la_SOURCES = snapscan.c snapscan.h libsnapscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=snapscan nodist_libsane_snapscan_la_SOURCES = snapscan-s.c libsane_snapscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=snapscan libsane_snapscan_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_snapscan_la_LIBADD = $(COMMON_LIBS) libsnapscan.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libsp15c_la_SOURCES = sp15c.c sp15c.h sp15c-scsi.h libsp15c_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sp15c nodist_libsane_sp15c_la_SOURCES = sp15c-s.c libsane_sp15c_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sp15c libsane_sp15c_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sp15c_la_LIBADD = $(COMMON_LIBS) libsp15c.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libst400_la_SOURCES = st400.c st400.h libst400_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=st400 nodist_libsane_st400_la_SOURCES = st400-s.c ../sanei/sanei_scsi.lo libsane_st400_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=st400 libsane_st400_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_st400_la_LIBADD = $(COMMON_LIBS) libst400.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libstv680_la_SOURCES = stv680.c stv680.h libstv680_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=stv680 nodist_libsane_stv680_la_SOURCES = stv680-s.c libsane_stv680_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=stv680 libsane_stv680_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_stv680_la_LIBADD = $(COMMON_LIBS) libstv680.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) libtamarack_la_SOURCES = tamarack.c tamarack.h libtamarack_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=tamarack nodist_libsane_tamarack_la_SOURCES = tamarack-s.c libsane_tamarack_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=tamarack libsane_tamarack_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_tamarack_la_LIBADD = $(COMMON_LIBS) libtamarack.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libtest_la_SOURCES = test.c test.h libtest_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=test nodist_libsane_test_la_SOURCES = test-s.c libsane_test_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=test libsane_test_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_test_la_LIBADD = $(COMMON_LIBS) libtest.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_thread.lo $(PTHREAD_LIBS) libteco1_la_SOURCES = teco1.c teco1.h libteco1_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco1 nodist_libsane_teco1_la_SOURCES = teco1-s.c libsane_teco1_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco1 libsane_teco1_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_teco1_la_LIBADD = $(COMMON_LIBS) libteco1.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libteco2_la_SOURCES = teco2.c teco2.h libteco2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco2 nodist_libsane_teco2_la_SOURCES = teco2-s.c libsane_teco2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco2 libsane_teco2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_teco2_la_LIBADD = $(COMMON_LIBS) libteco2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libteco3_la_SOURCES = teco3.c teco3.h libteco3_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco3 nodist_libsane_teco3_la_SOURCES = teco3-s.c libsane_teco3_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco3 libsane_teco3_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_teco3_la_LIBADD = $(COMMON_LIBS) libteco3.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) libu12_la_SOURCES = u12.c u12.h libu12_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=u12 nodist_libsane_u12_la_SOURCES = u12-s.c libsane_u12_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=u12 libsane_u12_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_u12_la_LIBADD = $(COMMON_LIBS) libu12.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libumax_la_SOURCES = umax.c umax.h libumax_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax nodist_libsane_umax_la_SOURCES = umax-s.c libsane_umax_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax libsane_umax_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_umax_la_LIBADD = $(COMMON_LIBS) libumax.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libumax1220u_la_SOURCES = umax1220u.c libumax1220u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax1220u nodist_libsane_umax1220u_la_SOURCES = umax1220u-s.c libsane_umax1220u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax1220u libsane_umax1220u_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_umax1220u_la_LIBADD = $(COMMON_LIBS) libumax1220u.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_pv8630.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libumax_pp_la_SOURCES = umax_pp.c umax_pp.h umax_pp_low.c umax_pp_low.h umax_pp_mid.c umax_pp_mid.h libumax_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax_pp nodist_libsane_umax_pp_la_SOURCES = umax_pp-s.c libsane_umax_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax_pp libsane_umax_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_umax_pp_la_LIBADD = $(COMMON_LIBS) libumax_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(MATH_LIB) libv4l_la_SOURCES = v4l.c v4l.h v4l-frequencies.h libv4l_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBV4L_CFLAGS) -DBACKEND_NAME=v4l nodist_libsane_v4l_la_SOURCES = v4l-s.c libsane_v4l_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=v4l libsane_v4l_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_v4l_la_LIBADD = $(COMMON_LIBS) libv4l.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(LIBV4L_LIBS) libxerox_mfp_la_SOURCES = xerox_mfp.c xerox_mfp-usb.c xerox_mfp-tcp.c xerox_mfp.h libxerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp nodist_libsane_xerox_mfp_la_SOURCES = xerox_mfp-s.c libsane_xerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp libsane_xerox_mfp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo @SANEI_SANEI_JPEG_LO@ $(JPEG_LIBS) ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libdll_preload_la_SOURCES = dll.c libdll_preload_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll -DENABLE_PRELOAD libdll_la_SOURCES = dll.c libdll_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll BUILT_SOURCES = dll-preload.h nodist_libsane_dll_la_SOURCES = dll-s.c libsane_dll_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll libsane_dll_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dll_la_LIBADD = $(COMMON_LIBS) libdll.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(DL_LIBS) # libsane.la and libsane-dll.la are the same thing except for # the addition of backends listed by PRELOADABLE_BACKENDS that are # statically linked in. # Also, libsane.la goes into $(libdir) where as all libsane-* # (including libsane-dll.la) go into $(libdir)/sane # FIXME: Since we are throwing in the kitchen sink, might as # well link in ../sanei/libsanei.la instead. But currently, # libsanei.la is linking in sanei_auth which requires md5. # Shipping md5 could cause symbol conflicts with commonly used # md5 external libraries. Either need to prefix md5 with sanei_ # (see liblib.la and snprintf), or move sanei_auth outside # of libsanei. # # FIXME: This is linking in every possible external library because there # is the off chance user is using PRELOADABLE_BACKENDS that may need # them. Since standard mode is to only have the dll backend, its a waste. # Need to update configure to build a list of only what needs to go into # LIBADD based on whats being preloaded. nodist_libsane_la_SOURCES = dll-s.c libsane_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll libsane_la_LDFLAGS = $(DIST_LIBS_LDFLAGS) libsane_la_LIBADD = $(COMMON_LIBS) $(PRELOADABLE_BACKENDS_ENABLED) libdll_preload.la sane_strstatus.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo ../sanei/sanei_pa4s2.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo ../sanei/sanei_magic.lo $(DL_LIBS) $(LIBV4L_LIBS) $(MATH_LIB) $(IEEE1284_LIBS) $(TIFF_LIBS) $(JPEG_LIBS) $(GPHOTO2_LIBS) $(SOCKET_LIBS) $(USB_LIBS) $(AVAHI_LIBS) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) # WARNING: Automake is getting this wrong so have to do it ourselves. libsane_la_DEPENDENCIES = $(COMMON_LIBS) $(PRELOADABLE_BACKENDS_ENABLED) libdll_preload.la sane_strstatus.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo ../sanei/sanei_pa4s2.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo ../sanei/sanei_magic.lo $(SANEI_SANEI_JPEG_LO) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .conf.in .conf .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu backend/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu backend/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-sanelibLTLIBRARIES: $(sanelib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(sanelib_LTLIBRARIES)'; test -n "$(sanelibdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(sanelibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sanelibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(sanelibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(sanelibdir)"; \ } uninstall-sanelibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(sanelib_LTLIBRARIES)'; test -n "$(sanelibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(sanelibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(sanelibdir)/$$f"; \ done clean-sanelibLTLIBRARIES: -test -z "$(sanelib_LTLIBRARIES)" || rm -f $(sanelib_LTLIBRARIES) @list='$(sanelib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libabaton.la: $(libabaton_la_OBJECTS) $(libabaton_la_DEPENDENCIES) $(EXTRA_libabaton_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libabaton_la_OBJECTS) $(libabaton_la_LIBADD) $(LIBS) libagfafocus.la: $(libagfafocus_la_OBJECTS) $(libagfafocus_la_DEPENDENCIES) $(EXTRA_libagfafocus_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libagfafocus_la_OBJECTS) $(libagfafocus_la_LIBADD) $(LIBS) libapple.la: $(libapple_la_OBJECTS) $(libapple_la_DEPENDENCIES) $(EXTRA_libapple_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libapple_la_OBJECTS) $(libapple_la_LIBADD) $(LIBS) libartec.la: $(libartec_la_OBJECTS) $(libartec_la_DEPENDENCIES) $(EXTRA_libartec_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libartec_la_OBJECTS) $(libartec_la_LIBADD) $(LIBS) libartec_eplus48u.la: $(libartec_eplus48u_la_OBJECTS) $(libartec_eplus48u_la_DEPENDENCIES) $(EXTRA_libartec_eplus48u_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libartec_eplus48u_la_OBJECTS) $(libartec_eplus48u_la_LIBADD) $(LIBS) libas6e.la: $(libas6e_la_OBJECTS) $(libas6e_la_DEPENDENCIES) $(EXTRA_libas6e_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libas6e_la_OBJECTS) $(libas6e_la_LIBADD) $(LIBS) libavision.la: $(libavision_la_OBJECTS) $(libavision_la_DEPENDENCIES) $(EXTRA_libavision_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libavision_la_OBJECTS) $(libavision_la_LIBADD) $(LIBS) libbh.la: $(libbh_la_OBJECTS) $(libbh_la_DEPENDENCIES) $(EXTRA_libbh_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libbh_la_OBJECTS) $(libbh_la_LIBADD) $(LIBS) libcanon.la: $(libcanon_la_OBJECTS) $(libcanon_la_DEPENDENCIES) $(EXTRA_libcanon_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcanon_la_OBJECTS) $(libcanon_la_LIBADD) $(LIBS) libcanon630u.la: $(libcanon630u_la_OBJECTS) $(libcanon630u_la_DEPENDENCIES) $(EXTRA_libcanon630u_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcanon630u_la_OBJECTS) $(libcanon630u_la_LIBADD) $(LIBS) libcanon_dr.la: $(libcanon_dr_la_OBJECTS) $(libcanon_dr_la_DEPENDENCIES) $(EXTRA_libcanon_dr_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcanon_dr_la_OBJECTS) $(libcanon_dr_la_LIBADD) $(LIBS) libcanon_pp.la: $(libcanon_pp_la_OBJECTS) $(libcanon_pp_la_DEPENDENCIES) $(EXTRA_libcanon_pp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcanon_pp_la_OBJECTS) $(libcanon_pp_la_LIBADD) $(LIBS) libcardscan.la: $(libcardscan_la_OBJECTS) $(libcardscan_la_DEPENDENCIES) $(EXTRA_libcardscan_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcardscan_la_OBJECTS) $(libcardscan_la_LIBADD) $(LIBS) libcoolscan.la: $(libcoolscan_la_OBJECTS) $(libcoolscan_la_DEPENDENCIES) $(EXTRA_libcoolscan_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcoolscan_la_OBJECTS) $(libcoolscan_la_LIBADD) $(LIBS) libcoolscan2.la: $(libcoolscan2_la_OBJECTS) $(libcoolscan2_la_DEPENDENCIES) $(EXTRA_libcoolscan2_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcoolscan2_la_OBJECTS) $(libcoolscan2_la_LIBADD) $(LIBS) libcoolscan3.la: $(libcoolscan3_la_OBJECTS) $(libcoolscan3_la_DEPENDENCIES) $(EXTRA_libcoolscan3_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcoolscan3_la_OBJECTS) $(libcoolscan3_la_LIBADD) $(LIBS) libdc210.la: $(libdc210_la_OBJECTS) $(libdc210_la_DEPENDENCIES) $(EXTRA_libdc210_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libdc210_la_OBJECTS) $(libdc210_la_LIBADD) $(LIBS) libdc240.la: $(libdc240_la_OBJECTS) $(libdc240_la_DEPENDENCIES) $(EXTRA_libdc240_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libdc240_la_OBJECTS) $(libdc240_la_LIBADD) $(LIBS) libdc25.la: $(libdc25_la_OBJECTS) $(libdc25_la_DEPENDENCIES) $(EXTRA_libdc25_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libdc25_la_OBJECTS) $(libdc25_la_LIBADD) $(LIBS) libdell1600n_net.la: $(libdell1600n_net_la_OBJECTS) $(libdell1600n_net_la_DEPENDENCIES) $(EXTRA_libdell1600n_net_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libdell1600n_net_la_OBJECTS) $(libdell1600n_net_la_LIBADD) $(LIBS) libdll.la: $(libdll_la_OBJECTS) $(libdll_la_DEPENDENCIES) $(EXTRA_libdll_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libdll_la_OBJECTS) $(libdll_la_LIBADD) $(LIBS) libdll_preload.la: $(libdll_preload_la_OBJECTS) $(libdll_preload_la_DEPENDENCIES) $(EXTRA_libdll_preload_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libdll_preload_la_OBJECTS) $(libdll_preload_la_LIBADD) $(LIBS) libdmc.la: $(libdmc_la_OBJECTS) $(libdmc_la_DEPENDENCIES) $(EXTRA_libdmc_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libdmc_la_OBJECTS) $(libdmc_la_LIBADD) $(LIBS) libepjitsu.la: $(libepjitsu_la_OBJECTS) $(libepjitsu_la_DEPENDENCIES) $(EXTRA_libepjitsu_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libepjitsu_la_OBJECTS) $(libepjitsu_la_LIBADD) $(LIBS) libepson.la: $(libepson_la_OBJECTS) $(libepson_la_DEPENDENCIES) $(EXTRA_libepson_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libepson_la_OBJECTS) $(libepson_la_LIBADD) $(LIBS) libepson2.la: $(libepson2_la_OBJECTS) $(libepson2_la_DEPENDENCIES) $(EXTRA_libepson2_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libepson2_la_OBJECTS) $(libepson2_la_LIBADD) $(LIBS) libepsonds.la: $(libepsonds_la_OBJECTS) $(libepsonds_la_DEPENDENCIES) $(EXTRA_libepsonds_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libepsonds_la_OBJECTS) $(libepsonds_la_LIBADD) $(LIBS) libfujitsu.la: $(libfujitsu_la_OBJECTS) $(libfujitsu_la_DEPENDENCIES) $(EXTRA_libfujitsu_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libfujitsu_la_OBJECTS) $(libfujitsu_la_LIBADD) $(LIBS) libgenesys.la: $(libgenesys_la_OBJECTS) $(libgenesys_la_DEPENDENCIES) $(EXTRA_libgenesys_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libgenesys_la_OBJECTS) $(libgenesys_la_LIBADD) $(LIBS) libgphoto2_i.la: $(libgphoto2_i_la_OBJECTS) $(libgphoto2_i_la_DEPENDENCIES) $(EXTRA_libgphoto2_i_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libgphoto2_i_la_OBJECTS) $(libgphoto2_i_la_LIBADD) $(LIBS) libgt68xx.la: $(libgt68xx_la_OBJECTS) $(libgt68xx_la_DEPENDENCIES) $(EXTRA_libgt68xx_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libgt68xx_la_OBJECTS) $(libgt68xx_la_LIBADD) $(LIBS) libhp.la: $(libhp_la_OBJECTS) $(libhp_la_DEPENDENCIES) $(EXTRA_libhp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhp_la_OBJECTS) $(libhp_la_LIBADD) $(LIBS) libhp3500.la: $(libhp3500_la_OBJECTS) $(libhp3500_la_DEPENDENCIES) $(EXTRA_libhp3500_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhp3500_la_OBJECTS) $(libhp3500_la_LIBADD) $(LIBS) libhp3900.la: $(libhp3900_la_OBJECTS) $(libhp3900_la_DEPENDENCIES) $(EXTRA_libhp3900_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhp3900_la_OBJECTS) $(libhp3900_la_LIBADD) $(LIBS) libhp4200.la: $(libhp4200_la_OBJECTS) $(libhp4200_la_DEPENDENCIES) $(EXTRA_libhp4200_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhp4200_la_OBJECTS) $(libhp4200_la_LIBADD) $(LIBS) libhp5400.la: $(libhp5400_la_OBJECTS) $(libhp5400_la_DEPENDENCIES) $(EXTRA_libhp5400_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhp5400_la_OBJECTS) $(libhp5400_la_LIBADD) $(LIBS) libhp5590.la: $(libhp5590_la_OBJECTS) $(libhp5590_la_DEPENDENCIES) $(EXTRA_libhp5590_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhp5590_la_OBJECTS) $(libhp5590_la_LIBADD) $(LIBS) libhpljm1005.la: $(libhpljm1005_la_OBJECTS) $(libhpljm1005_la_DEPENDENCIES) $(EXTRA_libhpljm1005_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhpljm1005_la_OBJECTS) $(libhpljm1005_la_LIBADD) $(LIBS) libhpsj5s.la: $(libhpsj5s_la_OBJECTS) $(libhpsj5s_la_DEPENDENCIES) $(EXTRA_libhpsj5s_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhpsj5s_la_OBJECTS) $(libhpsj5s_la_LIBADD) $(LIBS) libhs2p.la: $(libhs2p_la_OBJECTS) $(libhs2p_la_DEPENDENCIES) $(EXTRA_libhs2p_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libhs2p_la_OBJECTS) $(libhs2p_la_LIBADD) $(LIBS) libibm.la: $(libibm_la_OBJECTS) $(libibm_la_DEPENDENCIES) $(EXTRA_libibm_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libibm_la_OBJECTS) $(libibm_la_LIBADD) $(LIBS) libkodak.la: $(libkodak_la_OBJECTS) $(libkodak_la_DEPENDENCIES) $(EXTRA_libkodak_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libkodak_la_OBJECTS) $(libkodak_la_LIBADD) $(LIBS) libkodakaio.la: $(libkodakaio_la_OBJECTS) $(libkodakaio_la_DEPENDENCIES) $(EXTRA_libkodakaio_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libkodakaio_la_OBJECTS) $(libkodakaio_la_LIBADD) $(LIBS) libkvs1025.la: $(libkvs1025_la_OBJECTS) $(libkvs1025_la_DEPENDENCIES) $(EXTRA_libkvs1025_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libkvs1025_la_OBJECTS) $(libkvs1025_la_LIBADD) $(LIBS) libkvs20xx.la: $(libkvs20xx_la_OBJECTS) $(libkvs20xx_la_DEPENDENCIES) $(EXTRA_libkvs20xx_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libkvs20xx_la_OBJECTS) $(libkvs20xx_la_LIBADD) $(LIBS) libkvs40xx.la: $(libkvs40xx_la_OBJECTS) $(libkvs40xx_la_DEPENDENCIES) $(EXTRA_libkvs40xx_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libkvs40xx_la_OBJECTS) $(libkvs40xx_la_LIBADD) $(LIBS) libleo.la: $(libleo_la_OBJECTS) $(libleo_la_DEPENDENCIES) $(EXTRA_libleo_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libleo_la_OBJECTS) $(libleo_la_LIBADD) $(LIBS) liblexmark.la: $(liblexmark_la_OBJECTS) $(liblexmark_la_DEPENDENCIES) $(EXTRA_liblexmark_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(liblexmark_la_OBJECTS) $(liblexmark_la_LIBADD) $(LIBS) libma1509.la: $(libma1509_la_OBJECTS) $(libma1509_la_DEPENDENCIES) $(EXTRA_libma1509_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libma1509_la_OBJECTS) $(libma1509_la_LIBADD) $(LIBS) libmagicolor.la: $(libmagicolor_la_OBJECTS) $(libmagicolor_la_DEPENDENCIES) $(EXTRA_libmagicolor_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmagicolor_la_OBJECTS) $(libmagicolor_la_LIBADD) $(LIBS) libmatsushita.la: $(libmatsushita_la_OBJECTS) $(libmatsushita_la_DEPENDENCIES) $(EXTRA_libmatsushita_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmatsushita_la_OBJECTS) $(libmatsushita_la_LIBADD) $(LIBS) libmicrotek.la: $(libmicrotek_la_OBJECTS) $(libmicrotek_la_DEPENDENCIES) $(EXTRA_libmicrotek_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmicrotek_la_OBJECTS) $(libmicrotek_la_LIBADD) $(LIBS) libmicrotek2.la: $(libmicrotek2_la_OBJECTS) $(libmicrotek2_la_DEPENDENCIES) $(EXTRA_libmicrotek2_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmicrotek2_la_OBJECTS) $(libmicrotek2_la_LIBADD) $(LIBS) libmustek.la: $(libmustek_la_OBJECTS) $(libmustek_la_DEPENDENCIES) $(EXTRA_libmustek_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmustek_la_OBJECTS) $(libmustek_la_LIBADD) $(LIBS) libmustek_pp.la: $(libmustek_pp_la_OBJECTS) $(libmustek_pp_la_DEPENDENCIES) $(EXTRA_libmustek_pp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmustek_pp_la_OBJECTS) $(libmustek_pp_la_LIBADD) $(LIBS) libmustek_usb.la: $(libmustek_usb_la_OBJECTS) $(libmustek_usb_la_DEPENDENCIES) $(EXTRA_libmustek_usb_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmustek_usb_la_OBJECTS) $(libmustek_usb_la_LIBADD) $(LIBS) libmustek_usb2.la: $(libmustek_usb2_la_OBJECTS) $(libmustek_usb2_la_DEPENDENCIES) $(EXTRA_libmustek_usb2_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmustek_usb2_la_OBJECTS) $(libmustek_usb2_la_LIBADD) $(LIBS) libnec.la: $(libnec_la_OBJECTS) $(libnec_la_DEPENDENCIES) $(EXTRA_libnec_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libnec_la_OBJECTS) $(libnec_la_LIBADD) $(LIBS) libnet.la: $(libnet_la_OBJECTS) $(libnet_la_DEPENDENCIES) $(EXTRA_libnet_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libnet_la_OBJECTS) $(libnet_la_LIBADD) $(LIBS) libniash.la: $(libniash_la_OBJECTS) $(libniash_la_DEPENDENCIES) $(EXTRA_libniash_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libniash_la_OBJECTS) $(libniash_la_LIBADD) $(LIBS) libp5.la: $(libp5_la_OBJECTS) $(libp5_la_DEPENDENCIES) $(EXTRA_libp5_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libp5_la_OBJECTS) $(libp5_la_LIBADD) $(LIBS) libpie.la: $(libpie_la_OBJECTS) $(libpie_la_DEPENDENCIES) $(EXTRA_libpie_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libpie_la_OBJECTS) $(libpie_la_LIBADD) $(LIBS) libpieusb.la: $(libpieusb_la_OBJECTS) $(libpieusb_la_DEPENDENCIES) $(EXTRA_libpieusb_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libpieusb_la_OBJECTS) $(libpieusb_la_LIBADD) $(LIBS) libpint.la: $(libpint_la_OBJECTS) $(libpint_la_DEPENDENCIES) $(EXTRA_libpint_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libpint_la_OBJECTS) $(libpint_la_LIBADD) $(LIBS) libpixma.la: $(libpixma_la_OBJECTS) $(libpixma_la_DEPENDENCIES) $(EXTRA_libpixma_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libpixma_la_OBJECTS) $(libpixma_la_LIBADD) $(LIBS) libplustek.la: $(libplustek_la_OBJECTS) $(libplustek_la_DEPENDENCIES) $(EXTRA_libplustek_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libplustek_la_OBJECTS) $(libplustek_la_LIBADD) $(LIBS) libplustek_pp.la: $(libplustek_pp_la_OBJECTS) $(libplustek_pp_la_DEPENDENCIES) $(EXTRA_libplustek_pp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libplustek_pp_la_OBJECTS) $(libplustek_pp_la_LIBADD) $(LIBS) libpnm.la: $(libpnm_la_OBJECTS) $(libpnm_la_DEPENDENCIES) $(EXTRA_libpnm_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libpnm_la_OBJECTS) $(libpnm_la_LIBADD) $(LIBS) libqcam.la: $(libqcam_la_OBJECTS) $(libqcam_la_DEPENDENCIES) $(EXTRA_libqcam_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libqcam_la_OBJECTS) $(libqcam_la_LIBADD) $(LIBS) libricoh.la: $(libricoh_la_OBJECTS) $(libricoh_la_DEPENDENCIES) $(EXTRA_libricoh_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libricoh_la_OBJECTS) $(libricoh_la_LIBADD) $(LIBS) librts8891.la: $(librts8891_la_OBJECTS) $(librts8891_la_DEPENDENCIES) $(EXTRA_librts8891_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(librts8891_la_OBJECTS) $(librts8891_la_LIBADD) $(LIBS) libs9036.la: $(libs9036_la_OBJECTS) $(libs9036_la_DEPENDENCIES) $(EXTRA_libs9036_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libs9036_la_OBJECTS) $(libs9036_la_LIBADD) $(LIBS) libsane-abaton.la: $(libsane_abaton_la_OBJECTS) $(libsane_abaton_la_DEPENDENCIES) $(EXTRA_libsane_abaton_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_abaton_la_LINK) $(libsane_abaton_la_OBJECTS) $(libsane_abaton_la_LIBADD) $(LIBS) libsane-agfafocus.la: $(libsane_agfafocus_la_OBJECTS) $(libsane_agfafocus_la_DEPENDENCIES) $(EXTRA_libsane_agfafocus_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_agfafocus_la_LINK) $(libsane_agfafocus_la_OBJECTS) $(libsane_agfafocus_la_LIBADD) $(LIBS) libsane-apple.la: $(libsane_apple_la_OBJECTS) $(libsane_apple_la_DEPENDENCIES) $(EXTRA_libsane_apple_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_apple_la_LINK) $(libsane_apple_la_OBJECTS) $(libsane_apple_la_LIBADD) $(LIBS) libsane-artec.la: $(libsane_artec_la_OBJECTS) $(libsane_artec_la_DEPENDENCIES) $(EXTRA_libsane_artec_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_artec_la_LINK) $(libsane_artec_la_OBJECTS) $(libsane_artec_la_LIBADD) $(LIBS) libsane-artec_eplus48u.la: $(libsane_artec_eplus48u_la_OBJECTS) $(libsane_artec_eplus48u_la_DEPENDENCIES) $(EXTRA_libsane_artec_eplus48u_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_artec_eplus48u_la_LINK) $(libsane_artec_eplus48u_la_OBJECTS) $(libsane_artec_eplus48u_la_LIBADD) $(LIBS) libsane-as6e.la: $(libsane_as6e_la_OBJECTS) $(libsane_as6e_la_DEPENDENCIES) $(EXTRA_libsane_as6e_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_as6e_la_LINK) $(libsane_as6e_la_OBJECTS) $(libsane_as6e_la_LIBADD) $(LIBS) libsane-avision.la: $(libsane_avision_la_OBJECTS) $(libsane_avision_la_DEPENDENCIES) $(EXTRA_libsane_avision_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_avision_la_LINK) $(libsane_avision_la_OBJECTS) $(libsane_avision_la_LIBADD) $(LIBS) libsane-bh.la: $(libsane_bh_la_OBJECTS) $(libsane_bh_la_DEPENDENCIES) $(EXTRA_libsane_bh_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_bh_la_LINK) $(libsane_bh_la_OBJECTS) $(libsane_bh_la_LIBADD) $(LIBS) libsane-canon.la: $(libsane_canon_la_OBJECTS) $(libsane_canon_la_DEPENDENCIES) $(EXTRA_libsane_canon_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_canon_la_LINK) $(libsane_canon_la_OBJECTS) $(libsane_canon_la_LIBADD) $(LIBS) libsane-canon630u.la: $(libsane_canon630u_la_OBJECTS) $(libsane_canon630u_la_DEPENDENCIES) $(EXTRA_libsane_canon630u_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_canon630u_la_LINK) $(libsane_canon630u_la_OBJECTS) $(libsane_canon630u_la_LIBADD) $(LIBS) libsane-canon_dr.la: $(libsane_canon_dr_la_OBJECTS) $(libsane_canon_dr_la_DEPENDENCIES) $(EXTRA_libsane_canon_dr_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_canon_dr_la_LINK) $(libsane_canon_dr_la_OBJECTS) $(libsane_canon_dr_la_LIBADD) $(LIBS) libsane-canon_pp.la: $(libsane_canon_pp_la_OBJECTS) $(libsane_canon_pp_la_DEPENDENCIES) $(EXTRA_libsane_canon_pp_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_canon_pp_la_LINK) $(libsane_canon_pp_la_OBJECTS) $(libsane_canon_pp_la_LIBADD) $(LIBS) libsane-cardscan.la: $(libsane_cardscan_la_OBJECTS) $(libsane_cardscan_la_DEPENDENCIES) $(EXTRA_libsane_cardscan_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_cardscan_la_LINK) $(libsane_cardscan_la_OBJECTS) $(libsane_cardscan_la_LIBADD) $(LIBS) libsane-coolscan.la: $(libsane_coolscan_la_OBJECTS) $(libsane_coolscan_la_DEPENDENCIES) $(EXTRA_libsane_coolscan_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_coolscan_la_LINK) $(libsane_coolscan_la_OBJECTS) $(libsane_coolscan_la_LIBADD) $(LIBS) libsane-coolscan2.la: $(libsane_coolscan2_la_OBJECTS) $(libsane_coolscan2_la_DEPENDENCIES) $(EXTRA_libsane_coolscan2_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_coolscan2_la_LINK) $(libsane_coolscan2_la_OBJECTS) $(libsane_coolscan2_la_LIBADD) $(LIBS) libsane-coolscan3.la: $(libsane_coolscan3_la_OBJECTS) $(libsane_coolscan3_la_DEPENDENCIES) $(EXTRA_libsane_coolscan3_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_coolscan3_la_LINK) $(libsane_coolscan3_la_OBJECTS) $(libsane_coolscan3_la_LIBADD) $(LIBS) libsane-dc210.la: $(libsane_dc210_la_OBJECTS) $(libsane_dc210_la_DEPENDENCIES) $(EXTRA_libsane_dc210_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_dc210_la_LINK) $(libsane_dc210_la_OBJECTS) $(libsane_dc210_la_LIBADD) $(LIBS) libsane-dc240.la: $(libsane_dc240_la_OBJECTS) $(libsane_dc240_la_DEPENDENCIES) $(EXTRA_libsane_dc240_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_dc240_la_LINK) $(libsane_dc240_la_OBJECTS) $(libsane_dc240_la_LIBADD) $(LIBS) libsane-dc25.la: $(libsane_dc25_la_OBJECTS) $(libsane_dc25_la_DEPENDENCIES) $(EXTRA_libsane_dc25_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_dc25_la_LINK) $(libsane_dc25_la_OBJECTS) $(libsane_dc25_la_LIBADD) $(LIBS) libsane-dell1600n_net.la: $(libsane_dell1600n_net_la_OBJECTS) $(libsane_dell1600n_net_la_DEPENDENCIES) $(EXTRA_libsane_dell1600n_net_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_dell1600n_net_la_LINK) $(libsane_dell1600n_net_la_OBJECTS) $(libsane_dell1600n_net_la_LIBADD) $(LIBS) libsane-dll.la: $(libsane_dll_la_OBJECTS) $(libsane_dll_la_DEPENDENCIES) $(EXTRA_libsane_dll_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_dll_la_LINK) -rpath $(sanelibdir) $(libsane_dll_la_OBJECTS) $(libsane_dll_la_LIBADD) $(LIBS) libsane-dmc.la: $(libsane_dmc_la_OBJECTS) $(libsane_dmc_la_DEPENDENCIES) $(EXTRA_libsane_dmc_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_dmc_la_LINK) $(libsane_dmc_la_OBJECTS) $(libsane_dmc_la_LIBADD) $(LIBS) libsane-epjitsu.la: $(libsane_epjitsu_la_OBJECTS) $(libsane_epjitsu_la_DEPENDENCIES) $(EXTRA_libsane_epjitsu_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_epjitsu_la_LINK) $(libsane_epjitsu_la_OBJECTS) $(libsane_epjitsu_la_LIBADD) $(LIBS) libsane-epson.la: $(libsane_epson_la_OBJECTS) $(libsane_epson_la_DEPENDENCIES) $(EXTRA_libsane_epson_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_epson_la_LINK) $(libsane_epson_la_OBJECTS) $(libsane_epson_la_LIBADD) $(LIBS) libsane-epson2.la: $(libsane_epson2_la_OBJECTS) $(libsane_epson2_la_DEPENDENCIES) $(EXTRA_libsane_epson2_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_epson2_la_LINK) $(libsane_epson2_la_OBJECTS) $(libsane_epson2_la_LIBADD) $(LIBS) libsane-epsonds.la: $(libsane_epsonds_la_OBJECTS) $(libsane_epsonds_la_DEPENDENCIES) $(EXTRA_libsane_epsonds_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_epsonds_la_LINK) $(libsane_epsonds_la_OBJECTS) $(libsane_epsonds_la_LIBADD) $(LIBS) libsane-fujitsu.la: $(libsane_fujitsu_la_OBJECTS) $(libsane_fujitsu_la_DEPENDENCIES) $(EXTRA_libsane_fujitsu_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_fujitsu_la_LINK) $(libsane_fujitsu_la_OBJECTS) $(libsane_fujitsu_la_LIBADD) $(LIBS) libsane-genesys.la: $(libsane_genesys_la_OBJECTS) $(libsane_genesys_la_DEPENDENCIES) $(EXTRA_libsane_genesys_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_genesys_la_LINK) $(libsane_genesys_la_OBJECTS) $(libsane_genesys_la_LIBADD) $(LIBS) libsane-gphoto2.la: $(libsane_gphoto2_la_OBJECTS) $(libsane_gphoto2_la_DEPENDENCIES) $(EXTRA_libsane_gphoto2_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_gphoto2_la_LINK) $(libsane_gphoto2_la_OBJECTS) $(libsane_gphoto2_la_LIBADD) $(LIBS) libsane-gt68xx.la: $(libsane_gt68xx_la_OBJECTS) $(libsane_gt68xx_la_DEPENDENCIES) $(EXTRA_libsane_gt68xx_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_gt68xx_la_LINK) $(libsane_gt68xx_la_OBJECTS) $(libsane_gt68xx_la_LIBADD) $(LIBS) libsane-hp.la: $(libsane_hp_la_OBJECTS) $(libsane_hp_la_DEPENDENCIES) $(EXTRA_libsane_hp_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hp_la_LINK) $(libsane_hp_la_OBJECTS) $(libsane_hp_la_LIBADD) $(LIBS) libsane-hp3500.la: $(libsane_hp3500_la_OBJECTS) $(libsane_hp3500_la_DEPENDENCIES) $(EXTRA_libsane_hp3500_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hp3500_la_LINK) $(libsane_hp3500_la_OBJECTS) $(libsane_hp3500_la_LIBADD) $(LIBS) libsane-hp3900.la: $(libsane_hp3900_la_OBJECTS) $(libsane_hp3900_la_DEPENDENCIES) $(EXTRA_libsane_hp3900_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hp3900_la_LINK) $(libsane_hp3900_la_OBJECTS) $(libsane_hp3900_la_LIBADD) $(LIBS) libsane-hp4200.la: $(libsane_hp4200_la_OBJECTS) $(libsane_hp4200_la_DEPENDENCIES) $(EXTRA_libsane_hp4200_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hp4200_la_LINK) $(libsane_hp4200_la_OBJECTS) $(libsane_hp4200_la_LIBADD) $(LIBS) libsane-hp5400.la: $(libsane_hp5400_la_OBJECTS) $(libsane_hp5400_la_DEPENDENCIES) $(EXTRA_libsane_hp5400_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hp5400_la_LINK) $(libsane_hp5400_la_OBJECTS) $(libsane_hp5400_la_LIBADD) $(LIBS) libsane-hp5590.la: $(libsane_hp5590_la_OBJECTS) $(libsane_hp5590_la_DEPENDENCIES) $(EXTRA_libsane_hp5590_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hp5590_la_LINK) $(libsane_hp5590_la_OBJECTS) $(libsane_hp5590_la_LIBADD) $(LIBS) libsane-hpljm1005.la: $(libsane_hpljm1005_la_OBJECTS) $(libsane_hpljm1005_la_DEPENDENCIES) $(EXTRA_libsane_hpljm1005_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hpljm1005_la_LINK) $(libsane_hpljm1005_la_OBJECTS) $(libsane_hpljm1005_la_LIBADD) $(LIBS) libsane-hpsj5s.la: $(libsane_hpsj5s_la_OBJECTS) $(libsane_hpsj5s_la_DEPENDENCIES) $(EXTRA_libsane_hpsj5s_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hpsj5s_la_LINK) $(libsane_hpsj5s_la_OBJECTS) $(libsane_hpsj5s_la_LIBADD) $(LIBS) libsane-hs2p.la: $(libsane_hs2p_la_OBJECTS) $(libsane_hs2p_la_DEPENDENCIES) $(EXTRA_libsane_hs2p_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_hs2p_la_LINK) $(libsane_hs2p_la_OBJECTS) $(libsane_hs2p_la_LIBADD) $(LIBS) libsane-ibm.la: $(libsane_ibm_la_OBJECTS) $(libsane_ibm_la_DEPENDENCIES) $(EXTRA_libsane_ibm_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_ibm_la_LINK) $(libsane_ibm_la_OBJECTS) $(libsane_ibm_la_LIBADD) $(LIBS) libsane-kodak.la: $(libsane_kodak_la_OBJECTS) $(libsane_kodak_la_DEPENDENCIES) $(EXTRA_libsane_kodak_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_kodak_la_LINK) $(libsane_kodak_la_OBJECTS) $(libsane_kodak_la_LIBADD) $(LIBS) libsane-kodakaio.la: $(libsane_kodakaio_la_OBJECTS) $(libsane_kodakaio_la_DEPENDENCIES) $(EXTRA_libsane_kodakaio_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_kodakaio_la_LINK) $(libsane_kodakaio_la_OBJECTS) $(libsane_kodakaio_la_LIBADD) $(LIBS) libsane-kvs1025.la: $(libsane_kvs1025_la_OBJECTS) $(libsane_kvs1025_la_DEPENDENCIES) $(EXTRA_libsane_kvs1025_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_kvs1025_la_LINK) $(libsane_kvs1025_la_OBJECTS) $(libsane_kvs1025_la_LIBADD) $(LIBS) libsane-kvs20xx.la: $(libsane_kvs20xx_la_OBJECTS) $(libsane_kvs20xx_la_DEPENDENCIES) $(EXTRA_libsane_kvs20xx_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_kvs20xx_la_LINK) $(libsane_kvs20xx_la_OBJECTS) $(libsane_kvs20xx_la_LIBADD) $(LIBS) libsane-kvs40xx.la: $(libsane_kvs40xx_la_OBJECTS) $(libsane_kvs40xx_la_DEPENDENCIES) $(EXTRA_libsane_kvs40xx_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_kvs40xx_la_LINK) $(libsane_kvs40xx_la_OBJECTS) $(libsane_kvs40xx_la_LIBADD) $(LIBS) libsane-leo.la: $(libsane_leo_la_OBJECTS) $(libsane_leo_la_DEPENDENCIES) $(EXTRA_libsane_leo_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_leo_la_LINK) $(libsane_leo_la_OBJECTS) $(libsane_leo_la_LIBADD) $(LIBS) libsane-lexmark.la: $(libsane_lexmark_la_OBJECTS) $(libsane_lexmark_la_DEPENDENCIES) $(EXTRA_libsane_lexmark_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_lexmark_la_LINK) $(libsane_lexmark_la_OBJECTS) $(libsane_lexmark_la_LIBADD) $(LIBS) libsane-ma1509.la: $(libsane_ma1509_la_OBJECTS) $(libsane_ma1509_la_DEPENDENCIES) $(EXTRA_libsane_ma1509_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_ma1509_la_LINK) $(libsane_ma1509_la_OBJECTS) $(libsane_ma1509_la_LIBADD) $(LIBS) libsane-magicolor.la: $(libsane_magicolor_la_OBJECTS) $(libsane_magicolor_la_DEPENDENCIES) $(EXTRA_libsane_magicolor_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_magicolor_la_LINK) $(libsane_magicolor_la_OBJECTS) $(libsane_magicolor_la_LIBADD) $(LIBS) libsane-matsushita.la: $(libsane_matsushita_la_OBJECTS) $(libsane_matsushita_la_DEPENDENCIES) $(EXTRA_libsane_matsushita_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_matsushita_la_LINK) $(libsane_matsushita_la_OBJECTS) $(libsane_matsushita_la_LIBADD) $(LIBS) libsane-microtek.la: $(libsane_microtek_la_OBJECTS) $(libsane_microtek_la_DEPENDENCIES) $(EXTRA_libsane_microtek_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_microtek_la_LINK) $(libsane_microtek_la_OBJECTS) $(libsane_microtek_la_LIBADD) $(LIBS) libsane-microtek2.la: $(libsane_microtek2_la_OBJECTS) $(libsane_microtek2_la_DEPENDENCIES) $(EXTRA_libsane_microtek2_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_microtek2_la_LINK) $(libsane_microtek2_la_OBJECTS) $(libsane_microtek2_la_LIBADD) $(LIBS) libsane-mustek.la: $(libsane_mustek_la_OBJECTS) $(libsane_mustek_la_DEPENDENCIES) $(EXTRA_libsane_mustek_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_mustek_la_LINK) $(libsane_mustek_la_OBJECTS) $(libsane_mustek_la_LIBADD) $(LIBS) libsane-mustek_pp.la: $(libsane_mustek_pp_la_OBJECTS) $(libsane_mustek_pp_la_DEPENDENCIES) $(EXTRA_libsane_mustek_pp_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_mustek_pp_la_LINK) $(libsane_mustek_pp_la_OBJECTS) $(libsane_mustek_pp_la_LIBADD) $(LIBS) libsane-mustek_usb.la: $(libsane_mustek_usb_la_OBJECTS) $(libsane_mustek_usb_la_DEPENDENCIES) $(EXTRA_libsane_mustek_usb_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_mustek_usb_la_LINK) $(libsane_mustek_usb_la_OBJECTS) $(libsane_mustek_usb_la_LIBADD) $(LIBS) libsane-mustek_usb2.la: $(libsane_mustek_usb2_la_OBJECTS) $(libsane_mustek_usb2_la_DEPENDENCIES) $(EXTRA_libsane_mustek_usb2_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_mustek_usb2_la_LINK) $(libsane_mustek_usb2_la_OBJECTS) $(libsane_mustek_usb2_la_LIBADD) $(LIBS) libsane-nec.la: $(libsane_nec_la_OBJECTS) $(libsane_nec_la_DEPENDENCIES) $(EXTRA_libsane_nec_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_nec_la_LINK) $(libsane_nec_la_OBJECTS) $(libsane_nec_la_LIBADD) $(LIBS) libsane-net.la: $(libsane_net_la_OBJECTS) $(libsane_net_la_DEPENDENCIES) $(EXTRA_libsane_net_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_net_la_LINK) $(libsane_net_la_OBJECTS) $(libsane_net_la_LIBADD) $(LIBS) libsane-niash.la: $(libsane_niash_la_OBJECTS) $(libsane_niash_la_DEPENDENCIES) $(EXTRA_libsane_niash_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_niash_la_LINK) $(libsane_niash_la_OBJECTS) $(libsane_niash_la_LIBADD) $(LIBS) libsane-p5.la: $(libsane_p5_la_OBJECTS) $(libsane_p5_la_DEPENDENCIES) $(EXTRA_libsane_p5_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_p5_la_LINK) $(libsane_p5_la_OBJECTS) $(libsane_p5_la_LIBADD) $(LIBS) libsane-pie.la: $(libsane_pie_la_OBJECTS) $(libsane_pie_la_DEPENDENCIES) $(EXTRA_libsane_pie_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_pie_la_LINK) $(libsane_pie_la_OBJECTS) $(libsane_pie_la_LIBADD) $(LIBS) libsane-pieusb.la: $(libsane_pieusb_la_OBJECTS) $(libsane_pieusb_la_DEPENDENCIES) $(EXTRA_libsane_pieusb_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_pieusb_la_LINK) $(libsane_pieusb_la_OBJECTS) $(libsane_pieusb_la_LIBADD) $(LIBS) libsane-pint.la: $(libsane_pint_la_OBJECTS) $(libsane_pint_la_DEPENDENCIES) $(EXTRA_libsane_pint_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_pint_la_LINK) $(libsane_pint_la_OBJECTS) $(libsane_pint_la_LIBADD) $(LIBS) libsane-pixma.la: $(libsane_pixma_la_OBJECTS) $(libsane_pixma_la_DEPENDENCIES) $(EXTRA_libsane_pixma_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_pixma_la_LINK) $(libsane_pixma_la_OBJECTS) $(libsane_pixma_la_LIBADD) $(LIBS) libsane-plustek.la: $(libsane_plustek_la_OBJECTS) $(libsane_plustek_la_DEPENDENCIES) $(EXTRA_libsane_plustek_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_plustek_la_LINK) $(libsane_plustek_la_OBJECTS) $(libsane_plustek_la_LIBADD) $(LIBS) libsane-plustek_pp.la: $(libsane_plustek_pp_la_OBJECTS) $(libsane_plustek_pp_la_DEPENDENCIES) $(EXTRA_libsane_plustek_pp_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_plustek_pp_la_LINK) $(libsane_plustek_pp_la_OBJECTS) $(libsane_plustek_pp_la_LIBADD) $(LIBS) libsane-pnm.la: $(libsane_pnm_la_OBJECTS) $(libsane_pnm_la_DEPENDENCIES) $(EXTRA_libsane_pnm_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_pnm_la_LINK) $(libsane_pnm_la_OBJECTS) $(libsane_pnm_la_LIBADD) $(LIBS) libsane-qcam.la: $(libsane_qcam_la_OBJECTS) $(libsane_qcam_la_DEPENDENCIES) $(EXTRA_libsane_qcam_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_qcam_la_LINK) $(libsane_qcam_la_OBJECTS) $(libsane_qcam_la_LIBADD) $(LIBS) libsane-ricoh.la: $(libsane_ricoh_la_OBJECTS) $(libsane_ricoh_la_DEPENDENCIES) $(EXTRA_libsane_ricoh_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_ricoh_la_LINK) $(libsane_ricoh_la_OBJECTS) $(libsane_ricoh_la_LIBADD) $(LIBS) libsane-rts8891.la: $(libsane_rts8891_la_OBJECTS) $(libsane_rts8891_la_DEPENDENCIES) $(EXTRA_libsane_rts8891_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_rts8891_la_LINK) $(libsane_rts8891_la_OBJECTS) $(libsane_rts8891_la_LIBADD) $(LIBS) libsane-s9036.la: $(libsane_s9036_la_OBJECTS) $(libsane_s9036_la_DEPENDENCIES) $(EXTRA_libsane_s9036_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_s9036_la_LINK) $(libsane_s9036_la_OBJECTS) $(libsane_s9036_la_LIBADD) $(LIBS) libsane-sceptre.la: $(libsane_sceptre_la_OBJECTS) $(libsane_sceptre_la_DEPENDENCIES) $(EXTRA_libsane_sceptre_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_sceptre_la_LINK) $(libsane_sceptre_la_OBJECTS) $(libsane_sceptre_la_LIBADD) $(LIBS) libsane-sharp.la: $(libsane_sharp_la_OBJECTS) $(libsane_sharp_la_DEPENDENCIES) $(EXTRA_libsane_sharp_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_sharp_la_LINK) $(libsane_sharp_la_OBJECTS) $(libsane_sharp_la_LIBADD) $(LIBS) libsane-sm3600.la: $(libsane_sm3600_la_OBJECTS) $(libsane_sm3600_la_DEPENDENCIES) $(EXTRA_libsane_sm3600_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_sm3600_la_LINK) $(libsane_sm3600_la_OBJECTS) $(libsane_sm3600_la_LIBADD) $(LIBS) libsane-sm3840.la: $(libsane_sm3840_la_OBJECTS) $(libsane_sm3840_la_DEPENDENCIES) $(EXTRA_libsane_sm3840_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_sm3840_la_LINK) $(libsane_sm3840_la_OBJECTS) $(libsane_sm3840_la_LIBADD) $(LIBS) libsane-snapscan.la: $(libsane_snapscan_la_OBJECTS) $(libsane_snapscan_la_DEPENDENCIES) $(EXTRA_libsane_snapscan_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_snapscan_la_LINK) $(libsane_snapscan_la_OBJECTS) $(libsane_snapscan_la_LIBADD) $(LIBS) libsane-sp15c.la: $(libsane_sp15c_la_OBJECTS) $(libsane_sp15c_la_DEPENDENCIES) $(EXTRA_libsane_sp15c_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_sp15c_la_LINK) $(libsane_sp15c_la_OBJECTS) $(libsane_sp15c_la_LIBADD) $(LIBS) libsane-st400.la: $(libsane_st400_la_OBJECTS) $(libsane_st400_la_DEPENDENCIES) $(EXTRA_libsane_st400_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_st400_la_LINK) $(libsane_st400_la_OBJECTS) $(libsane_st400_la_LIBADD) $(LIBS) libsane-stv680.la: $(libsane_stv680_la_OBJECTS) $(libsane_stv680_la_DEPENDENCIES) $(EXTRA_libsane_stv680_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_stv680_la_LINK) $(libsane_stv680_la_OBJECTS) $(libsane_stv680_la_LIBADD) $(LIBS) libsane-tamarack.la: $(libsane_tamarack_la_OBJECTS) $(libsane_tamarack_la_DEPENDENCIES) $(EXTRA_libsane_tamarack_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_tamarack_la_LINK) $(libsane_tamarack_la_OBJECTS) $(libsane_tamarack_la_LIBADD) $(LIBS) libsane-teco1.la: $(libsane_teco1_la_OBJECTS) $(libsane_teco1_la_DEPENDENCIES) $(EXTRA_libsane_teco1_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_teco1_la_LINK) $(libsane_teco1_la_OBJECTS) $(libsane_teco1_la_LIBADD) $(LIBS) libsane-teco2.la: $(libsane_teco2_la_OBJECTS) $(libsane_teco2_la_DEPENDENCIES) $(EXTRA_libsane_teco2_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_teco2_la_LINK) $(libsane_teco2_la_OBJECTS) $(libsane_teco2_la_LIBADD) $(LIBS) libsane-teco3.la: $(libsane_teco3_la_OBJECTS) $(libsane_teco3_la_DEPENDENCIES) $(EXTRA_libsane_teco3_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_teco3_la_LINK) $(libsane_teco3_la_OBJECTS) $(libsane_teco3_la_LIBADD) $(LIBS) libsane-test.la: $(libsane_test_la_OBJECTS) $(libsane_test_la_DEPENDENCIES) $(EXTRA_libsane_test_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_test_la_LINK) $(libsane_test_la_OBJECTS) $(libsane_test_la_LIBADD) $(LIBS) libsane-u12.la: $(libsane_u12_la_OBJECTS) $(libsane_u12_la_DEPENDENCIES) $(EXTRA_libsane_u12_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_u12_la_LINK) $(libsane_u12_la_OBJECTS) $(libsane_u12_la_LIBADD) $(LIBS) libsane-umax.la: $(libsane_umax_la_OBJECTS) $(libsane_umax_la_DEPENDENCIES) $(EXTRA_libsane_umax_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_umax_la_LINK) $(libsane_umax_la_OBJECTS) $(libsane_umax_la_LIBADD) $(LIBS) libsane-umax1220u.la: $(libsane_umax1220u_la_OBJECTS) $(libsane_umax1220u_la_DEPENDENCIES) $(EXTRA_libsane_umax1220u_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_umax1220u_la_LINK) $(libsane_umax1220u_la_OBJECTS) $(libsane_umax1220u_la_LIBADD) $(LIBS) libsane-umax_pp.la: $(libsane_umax_pp_la_OBJECTS) $(libsane_umax_pp_la_DEPENDENCIES) $(EXTRA_libsane_umax_pp_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_umax_pp_la_LINK) $(libsane_umax_pp_la_OBJECTS) $(libsane_umax_pp_la_LIBADD) $(LIBS) libsane-v4l.la: $(libsane_v4l_la_OBJECTS) $(libsane_v4l_la_DEPENDENCIES) $(EXTRA_libsane_v4l_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_v4l_la_LINK) $(libsane_v4l_la_OBJECTS) $(libsane_v4l_la_LIBADD) $(LIBS) libsane-xerox_mfp.la: $(libsane_xerox_mfp_la_OBJECTS) $(libsane_xerox_mfp_la_DEPENDENCIES) $(EXTRA_libsane_xerox_mfp_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_xerox_mfp_la_LINK) $(libsane_xerox_mfp_la_OBJECTS) $(libsane_xerox_mfp_la_LIBADD) $(LIBS) libsane.la: $(libsane_la_OBJECTS) $(libsane_la_DEPENDENCIES) $(EXTRA_libsane_la_DEPENDENCIES) $(AM_V_CCLD)$(libsane_la_LINK) -rpath $(libdir) $(libsane_la_OBJECTS) $(libsane_la_LIBADD) $(LIBS) libsceptre.la: $(libsceptre_la_OBJECTS) $(libsceptre_la_DEPENDENCIES) $(EXTRA_libsceptre_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsceptre_la_OBJECTS) $(libsceptre_la_LIBADD) $(LIBS) libsharp.la: $(libsharp_la_OBJECTS) $(libsharp_la_DEPENDENCIES) $(EXTRA_libsharp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsharp_la_OBJECTS) $(libsharp_la_LIBADD) $(LIBS) libsm3600.la: $(libsm3600_la_OBJECTS) $(libsm3600_la_DEPENDENCIES) $(EXTRA_libsm3600_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsm3600_la_OBJECTS) $(libsm3600_la_LIBADD) $(LIBS) libsm3840.la: $(libsm3840_la_OBJECTS) $(libsm3840_la_DEPENDENCIES) $(EXTRA_libsm3840_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsm3840_la_OBJECTS) $(libsm3840_la_LIBADD) $(LIBS) libsnapscan.la: $(libsnapscan_la_OBJECTS) $(libsnapscan_la_DEPENDENCIES) $(EXTRA_libsnapscan_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsnapscan_la_OBJECTS) $(libsnapscan_la_LIBADD) $(LIBS) libsp15c.la: $(libsp15c_la_OBJECTS) $(libsp15c_la_DEPENDENCIES) $(EXTRA_libsp15c_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libsp15c_la_OBJECTS) $(libsp15c_la_LIBADD) $(LIBS) libst400.la: $(libst400_la_OBJECTS) $(libst400_la_DEPENDENCIES) $(EXTRA_libst400_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libst400_la_OBJECTS) $(libst400_la_LIBADD) $(LIBS) libstv680.la: $(libstv680_la_OBJECTS) $(libstv680_la_DEPENDENCIES) $(EXTRA_libstv680_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libstv680_la_OBJECTS) $(libstv680_la_LIBADD) $(LIBS) libtamarack.la: $(libtamarack_la_OBJECTS) $(libtamarack_la_DEPENDENCIES) $(EXTRA_libtamarack_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libtamarack_la_OBJECTS) $(libtamarack_la_LIBADD) $(LIBS) libteco1.la: $(libteco1_la_OBJECTS) $(libteco1_la_DEPENDENCIES) $(EXTRA_libteco1_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libteco1_la_OBJECTS) $(libteco1_la_LIBADD) $(LIBS) libteco2.la: $(libteco2_la_OBJECTS) $(libteco2_la_DEPENDENCIES) $(EXTRA_libteco2_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libteco2_la_OBJECTS) $(libteco2_la_LIBADD) $(LIBS) libteco3.la: $(libteco3_la_OBJECTS) $(libteco3_la_DEPENDENCIES) $(EXTRA_libteco3_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libteco3_la_OBJECTS) $(libteco3_la_LIBADD) $(LIBS) libtest.la: $(libtest_la_OBJECTS) $(libtest_la_DEPENDENCIES) $(EXTRA_libtest_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libtest_la_OBJECTS) $(libtest_la_LIBADD) $(LIBS) libu12.la: $(libu12_la_OBJECTS) $(libu12_la_DEPENDENCIES) $(EXTRA_libu12_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libu12_la_OBJECTS) $(libu12_la_LIBADD) $(LIBS) libumax.la: $(libumax_la_OBJECTS) $(libumax_la_DEPENDENCIES) $(EXTRA_libumax_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libumax_la_OBJECTS) $(libumax_la_LIBADD) $(LIBS) libumax1220u.la: $(libumax1220u_la_OBJECTS) $(libumax1220u_la_DEPENDENCIES) $(EXTRA_libumax1220u_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libumax1220u_la_OBJECTS) $(libumax1220u_la_LIBADD) $(LIBS) libumax_pp.la: $(libumax_pp_la_OBJECTS) $(libumax_pp_la_DEPENDENCIES) $(EXTRA_libumax_pp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libumax_pp_la_OBJECTS) $(libumax_pp_la_LIBADD) $(LIBS) libv4l.la: $(libv4l_la_OBJECTS) $(libv4l_la_DEPENDENCIES) $(EXTRA_libv4l_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libv4l_la_OBJECTS) $(libv4l_la_LIBADD) $(LIBS) libxerox_mfp.la: $(libxerox_mfp_la_OBJECTS) $(libxerox_mfp_la_DEPENDENCIES) $(EXTRA_libxerox_mfp_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libxerox_mfp_la_OBJECTS) $(libxerox_mfp_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libabaton_la-abaton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libagfafocus_la-agfafocus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libapple_la-apple.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libartec_eplus48u_la-artec_eplus48u.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libartec_la-artec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libas6e_la-as6e.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libavision_la-avision.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libbh_la-bh.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcanon630u_la-canon630u.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcanon_dr_la-canon_dr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcanon_la-canon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcanon_pp_la-canon_pp-dev.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcanon_pp_la-canon_pp-io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcanon_pp_la-canon_pp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcardscan_la-cardscan.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolscan2_la-coolscan2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolscan3_la-coolscan3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcoolscan_la-coolscan.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdc210_la-dc210.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdc240_la-dc240.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdc25_la-dc25.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdell1600n_net_la-dell1600n_net.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdll_la-dll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdll_preload_la-dll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdmc_la-dmc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepjitsu_la-epjitsu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson2_la-epson2-cct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson2_la-epson2-commands.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson2_la-epson2-io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson2_la-epson2-ops.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson2_la-epson2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson2_la-epson2_net.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson2_la-epson2_scsi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson2_la-epson2_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson_la-epson.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson_la-epson_scsi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepson_la-epson_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-cmd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-jpeg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-net.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-ops.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds-usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libepsonds_la-epsonds.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libfujitsu_la-fujitsu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys_gl124.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys_gl646.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys_gl841.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys_gl843.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys_gl846.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys_gl847.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenesys_la-genesys_low.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgphoto2_i_la-gphoto2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgt68xx_la-gt68xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp3500_la-hp3500.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp3900_la-hp3900.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp4200_la-hp4200.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp5400_la-hp5400.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp5590_la-hp5590.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp_la-hp-accessor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp_la-hp-device.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp_la-hp-handle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp_la-hp-hpmem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp_la-hp-option.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp_la-hp-scl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhp_la-hp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhpljm1005_la-hpljm1005.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhpsj5s_la-hpsj5s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhs2p_la-hs2p.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libibm_la-ibm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkodak_la-kodak.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkodakaio_la-kodakaio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs1025_la-kvs1025.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs1025_la-kvs1025_low.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs1025_la-kvs1025_opt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs1025_la-kvs1025_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs20xx_la-kvs20xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs20xx_la-kvs20xx_cmd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs20xx_la-kvs20xx_opt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs40xx_la-kvs40xx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs40xx_la-kvs40xx_cmd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libkvs40xx_la-kvs40xx_opt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libleo_la-leo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblexmark_la-lexmark.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblexmark_la-lexmark_low.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libma1509_la-ma1509.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmagicolor_la-magicolor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmatsushita_la-matsushita.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmicrotek2_la-microtek2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmicrotek_la-microtek.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmustek_la-mustek.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmustek_pp_la-mustek_pp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmustek_usb2_la-mustek_usb2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmustek_usb_la-mustek_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnec_la-nec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnet_la-net.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libniash_la-niash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libp5_la-p5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpie_la-pie.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpieusb_la-pieusb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpieusb_la-pieusb_buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpieusb_la-pieusb_scancmd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpieusb_la-pieusb_specific.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpieusb_la-pieusb_usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpint_la-pint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma_bjnp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma_imageclass.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma_io_sanei.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma_mp150.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma_mp730.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma_mp750.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpixma_la-pixma_mp810.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libplustek_la-plustek.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libplustek_pp_la-plustek_pp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpnm_la-pnm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqcam_la-qcam.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libricoh_la-ricoh.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librts8891_la-rts8891.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librts8891_la-rts88xx_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libs9036_la-s9036.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_abaton_la-abaton-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_agfafocus_la-agfafocus-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_apple_la-apple-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_artec_eplus48u_la-artec_eplus48u-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_artec_la-artec-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_as6e_la-as6e-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_avision_la-avision-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_bh_la-bh-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_canon630u_la-canon630u-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_canon_dr_la-canon_dr-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_canon_la-canon-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_canon_pp_la-canon_pp-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_cardscan_la-cardscan-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_coolscan2_la-coolscan2-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_coolscan3_la-coolscan3-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_coolscan_la-coolscan-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_dc210_la-dc210-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_dc240_la-dc240-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_dc25_la-dc25-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_dell1600n_net_la-dell1600n_net-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_dll_la-dll-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_dmc_la-dmc-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_epjitsu_la-epjitsu-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_epson2_la-epson2-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_epson_la-epson-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_epsonds_la-epsonds-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_fujitsu_la-fujitsu-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_genesys_la-genesys-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_gphoto2_la-gphoto2-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_gt68xx_la-gt68xx-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hp3500_la-hp3500-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hp3900_la-hp3900-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hp4200_la-hp4200-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hp5400_la-hp5400-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hp5590_la-hp5590-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hp_la-hp-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hpljm1005_la-hpljm1005-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hpsj5s_la-hpsj5s-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_hs2p_la-hs2p-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_ibm_la-ibm-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_kodak_la-kodak-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_kodakaio_la-kodakaio-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_kvs1025_la-kvs1025-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_kvs20xx_la-kvs20xx-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_kvs40xx_la-kvs40xx-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_la-dll-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_leo_la-leo-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_lexmark_la-lexmark-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_ma1509_la-ma1509-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_magicolor_la-magicolor-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_matsushita_la-matsushita-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_microtek2_la-microtek2-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_microtek_la-microtek-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_mustek_la-mustek-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_mustek_pp_la-mustek_pp-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_mustek_usb2_la-mustek_usb2-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_mustek_usb_la-mustek_usb-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_nec_la-nec-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_net_la-net-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_niash_la-niash-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_p5_la-p5-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_pie_la-pie-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_pieusb_la-pieusb-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_pint_la-pint-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_pixma_la-pixma-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_plustek_la-plustek-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_plustek_pp_la-plustek_pp-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_pnm_la-pnm-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_qcam_la-qcam-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_ricoh_la-ricoh-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_rts8891_la-rts8891-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_s9036_la-s9036-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_sceptre_la-sceptre-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_sharp_la-sharp-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_sm3600_la-sm3600-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_sm3840_la-sm3840-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_snapscan_la-snapscan-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_sp15c_la-sp15c-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_st400_la-st400-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_stv680_la-stv680-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_tamarack_la-tamarack-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_teco1_la-teco1-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_teco2_la-teco2-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_teco3_la-teco3-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_test_la-test-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_u12_la-u12-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_umax1220u_la-umax1220u-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_umax_la-umax-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_umax_pp_la-umax_pp-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_v4l_la-v4l-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsane_xerox_mfp_la-xerox_mfp-s.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsceptre_la-sceptre.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsharp_la-sharp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsm3600_la-sm3600.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsm3840_la-sm3840.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsnapscan_la-snapscan.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsp15c_la-sp15c.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libst400_la-st400.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstv680_la-stv680.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtamarack_la-tamarack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libteco1_la-teco1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libteco2_la-teco2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libteco3_la-teco3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_la-test.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libu12_la-u12.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libumax1220u_la-umax1220u.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libumax_la-umax.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libumax_pp_la-umax_pp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libumax_pp_la-umax_pp_low.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libumax_pp_la-umax_pp_mid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libv4l_la-v4l.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxerox_mfp_la-xerox_mfp-tcp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxerox_mfp_la-xerox_mfp-usb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libxerox_mfp_la-xerox_mfp.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libabaton_la-abaton.lo: abaton.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libabaton_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libabaton_la-abaton.lo -MD -MP -MF $(DEPDIR)/libabaton_la-abaton.Tpo -c -o libabaton_la-abaton.lo `test -f 'abaton.c' || echo '$(srcdir)/'`abaton.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libabaton_la-abaton.Tpo $(DEPDIR)/libabaton_la-abaton.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='abaton.c' object='libabaton_la-abaton.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libabaton_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libabaton_la-abaton.lo `test -f 'abaton.c' || echo '$(srcdir)/'`abaton.c libagfafocus_la-agfafocus.lo: agfafocus.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libagfafocus_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libagfafocus_la-agfafocus.lo -MD -MP -MF $(DEPDIR)/libagfafocus_la-agfafocus.Tpo -c -o libagfafocus_la-agfafocus.lo `test -f 'agfafocus.c' || echo '$(srcdir)/'`agfafocus.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libagfafocus_la-agfafocus.Tpo $(DEPDIR)/libagfafocus_la-agfafocus.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='agfafocus.c' object='libagfafocus_la-agfafocus.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libagfafocus_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libagfafocus_la-agfafocus.lo `test -f 'agfafocus.c' || echo '$(srcdir)/'`agfafocus.c libapple_la-apple.lo: apple.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libapple_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libapple_la-apple.lo -MD -MP -MF $(DEPDIR)/libapple_la-apple.Tpo -c -o libapple_la-apple.lo `test -f 'apple.c' || echo '$(srcdir)/'`apple.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libapple_la-apple.Tpo $(DEPDIR)/libapple_la-apple.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='apple.c' object='libapple_la-apple.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libapple_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libapple_la-apple.lo `test -f 'apple.c' || echo '$(srcdir)/'`apple.c libartec_la-artec.lo: artec.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libartec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libartec_la-artec.lo -MD -MP -MF $(DEPDIR)/libartec_la-artec.Tpo -c -o libartec_la-artec.lo `test -f 'artec.c' || echo '$(srcdir)/'`artec.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libartec_la-artec.Tpo $(DEPDIR)/libartec_la-artec.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='artec.c' object='libartec_la-artec.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libartec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libartec_la-artec.lo `test -f 'artec.c' || echo '$(srcdir)/'`artec.c libartec_eplus48u_la-artec_eplus48u.lo: artec_eplus48u.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libartec_eplus48u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libartec_eplus48u_la-artec_eplus48u.lo -MD -MP -MF $(DEPDIR)/libartec_eplus48u_la-artec_eplus48u.Tpo -c -o libartec_eplus48u_la-artec_eplus48u.lo `test -f 'artec_eplus48u.c' || echo '$(srcdir)/'`artec_eplus48u.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libartec_eplus48u_la-artec_eplus48u.Tpo $(DEPDIR)/libartec_eplus48u_la-artec_eplus48u.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='artec_eplus48u.c' object='libartec_eplus48u_la-artec_eplus48u.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libartec_eplus48u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libartec_eplus48u_la-artec_eplus48u.lo `test -f 'artec_eplus48u.c' || echo '$(srcdir)/'`artec_eplus48u.c libas6e_la-as6e.lo: as6e.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libas6e_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libas6e_la-as6e.lo -MD -MP -MF $(DEPDIR)/libas6e_la-as6e.Tpo -c -o libas6e_la-as6e.lo `test -f 'as6e.c' || echo '$(srcdir)/'`as6e.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libas6e_la-as6e.Tpo $(DEPDIR)/libas6e_la-as6e.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='as6e.c' object='libas6e_la-as6e.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libas6e_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libas6e_la-as6e.lo `test -f 'as6e.c' || echo '$(srcdir)/'`as6e.c libavision_la-avision.lo: avision.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libavision_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libavision_la-avision.lo -MD -MP -MF $(DEPDIR)/libavision_la-avision.Tpo -c -o libavision_la-avision.lo `test -f 'avision.c' || echo '$(srcdir)/'`avision.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libavision_la-avision.Tpo $(DEPDIR)/libavision_la-avision.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='avision.c' object='libavision_la-avision.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libavision_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libavision_la-avision.lo `test -f 'avision.c' || echo '$(srcdir)/'`avision.c libbh_la-bh.lo: bh.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbh_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libbh_la-bh.lo -MD -MP -MF $(DEPDIR)/libbh_la-bh.Tpo -c -o libbh_la-bh.lo `test -f 'bh.c' || echo '$(srcdir)/'`bh.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libbh_la-bh.Tpo $(DEPDIR)/libbh_la-bh.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bh.c' object='libbh_la-bh.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libbh_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libbh_la-bh.lo `test -f 'bh.c' || echo '$(srcdir)/'`bh.c libcanon_la-canon.lo: canon.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcanon_la-canon.lo -MD -MP -MF $(DEPDIR)/libcanon_la-canon.Tpo -c -o libcanon_la-canon.lo `test -f 'canon.c' || echo '$(srcdir)/'`canon.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcanon_la-canon.Tpo $(DEPDIR)/libcanon_la-canon.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon.c' object='libcanon_la-canon.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcanon_la-canon.lo `test -f 'canon.c' || echo '$(srcdir)/'`canon.c libcanon630u_la-canon630u.lo: canon630u.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon630u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcanon630u_la-canon630u.lo -MD -MP -MF $(DEPDIR)/libcanon630u_la-canon630u.Tpo -c -o libcanon630u_la-canon630u.lo `test -f 'canon630u.c' || echo '$(srcdir)/'`canon630u.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcanon630u_la-canon630u.Tpo $(DEPDIR)/libcanon630u_la-canon630u.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon630u.c' object='libcanon630u_la-canon630u.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon630u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcanon630u_la-canon630u.lo `test -f 'canon630u.c' || echo '$(srcdir)/'`canon630u.c libcanon_dr_la-canon_dr.lo: canon_dr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_dr_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcanon_dr_la-canon_dr.lo -MD -MP -MF $(DEPDIR)/libcanon_dr_la-canon_dr.Tpo -c -o libcanon_dr_la-canon_dr.lo `test -f 'canon_dr.c' || echo '$(srcdir)/'`canon_dr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcanon_dr_la-canon_dr.Tpo $(DEPDIR)/libcanon_dr_la-canon_dr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon_dr.c' object='libcanon_dr_la-canon_dr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_dr_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcanon_dr_la-canon_dr.lo `test -f 'canon_dr.c' || echo '$(srcdir)/'`canon_dr.c libcanon_pp_la-canon_pp.lo: canon_pp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcanon_pp_la-canon_pp.lo -MD -MP -MF $(DEPDIR)/libcanon_pp_la-canon_pp.Tpo -c -o libcanon_pp_la-canon_pp.lo `test -f 'canon_pp.c' || echo '$(srcdir)/'`canon_pp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcanon_pp_la-canon_pp.Tpo $(DEPDIR)/libcanon_pp_la-canon_pp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon_pp.c' object='libcanon_pp_la-canon_pp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcanon_pp_la-canon_pp.lo `test -f 'canon_pp.c' || echo '$(srcdir)/'`canon_pp.c libcanon_pp_la-canon_pp-io.lo: canon_pp-io.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcanon_pp_la-canon_pp-io.lo -MD -MP -MF $(DEPDIR)/libcanon_pp_la-canon_pp-io.Tpo -c -o libcanon_pp_la-canon_pp-io.lo `test -f 'canon_pp-io.c' || echo '$(srcdir)/'`canon_pp-io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcanon_pp_la-canon_pp-io.Tpo $(DEPDIR)/libcanon_pp_la-canon_pp-io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon_pp-io.c' object='libcanon_pp_la-canon_pp-io.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcanon_pp_la-canon_pp-io.lo `test -f 'canon_pp-io.c' || echo '$(srcdir)/'`canon_pp-io.c libcanon_pp_la-canon_pp-dev.lo: canon_pp-dev.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcanon_pp_la-canon_pp-dev.lo -MD -MP -MF $(DEPDIR)/libcanon_pp_la-canon_pp-dev.Tpo -c -o libcanon_pp_la-canon_pp-dev.lo `test -f 'canon_pp-dev.c' || echo '$(srcdir)/'`canon_pp-dev.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcanon_pp_la-canon_pp-dev.Tpo $(DEPDIR)/libcanon_pp_la-canon_pp-dev.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon_pp-dev.c' object='libcanon_pp_la-canon_pp-dev.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcanon_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcanon_pp_la-canon_pp-dev.lo `test -f 'canon_pp-dev.c' || echo '$(srcdir)/'`canon_pp-dev.c libcardscan_la-cardscan.lo: cardscan.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcardscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcardscan_la-cardscan.lo -MD -MP -MF $(DEPDIR)/libcardscan_la-cardscan.Tpo -c -o libcardscan_la-cardscan.lo `test -f 'cardscan.c' || echo '$(srcdir)/'`cardscan.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcardscan_la-cardscan.Tpo $(DEPDIR)/libcardscan_la-cardscan.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cardscan.c' object='libcardscan_la-cardscan.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcardscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcardscan_la-cardscan.lo `test -f 'cardscan.c' || echo '$(srcdir)/'`cardscan.c libcoolscan_la-coolscan.lo: coolscan.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcoolscan_la-coolscan.lo -MD -MP -MF $(DEPDIR)/libcoolscan_la-coolscan.Tpo -c -o libcoolscan_la-coolscan.lo `test -f 'coolscan.c' || echo '$(srcdir)/'`coolscan.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcoolscan_la-coolscan.Tpo $(DEPDIR)/libcoolscan_la-coolscan.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='coolscan.c' object='libcoolscan_la-coolscan.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcoolscan_la-coolscan.lo `test -f 'coolscan.c' || echo '$(srcdir)/'`coolscan.c libcoolscan2_la-coolscan2.lo: coolscan2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolscan2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcoolscan2_la-coolscan2.lo -MD -MP -MF $(DEPDIR)/libcoolscan2_la-coolscan2.Tpo -c -o libcoolscan2_la-coolscan2.lo `test -f 'coolscan2.c' || echo '$(srcdir)/'`coolscan2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcoolscan2_la-coolscan2.Tpo $(DEPDIR)/libcoolscan2_la-coolscan2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='coolscan2.c' object='libcoolscan2_la-coolscan2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolscan2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcoolscan2_la-coolscan2.lo `test -f 'coolscan2.c' || echo '$(srcdir)/'`coolscan2.c libcoolscan3_la-coolscan3.lo: coolscan3.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolscan3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcoolscan3_la-coolscan3.lo -MD -MP -MF $(DEPDIR)/libcoolscan3_la-coolscan3.Tpo -c -o libcoolscan3_la-coolscan3.lo `test -f 'coolscan3.c' || echo '$(srcdir)/'`coolscan3.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcoolscan3_la-coolscan3.Tpo $(DEPDIR)/libcoolscan3_la-coolscan3.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='coolscan3.c' object='libcoolscan3_la-coolscan3.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoolscan3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcoolscan3_la-coolscan3.lo `test -f 'coolscan3.c' || echo '$(srcdir)/'`coolscan3.c libdc210_la-dc210.lo: dc210.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdc210_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdc210_la-dc210.lo -MD -MP -MF $(DEPDIR)/libdc210_la-dc210.Tpo -c -o libdc210_la-dc210.lo `test -f 'dc210.c' || echo '$(srcdir)/'`dc210.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdc210_la-dc210.Tpo $(DEPDIR)/libdc210_la-dc210.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dc210.c' object='libdc210_la-dc210.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdc210_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdc210_la-dc210.lo `test -f 'dc210.c' || echo '$(srcdir)/'`dc210.c libdc240_la-dc240.lo: dc240.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdc240_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdc240_la-dc240.lo -MD -MP -MF $(DEPDIR)/libdc240_la-dc240.Tpo -c -o libdc240_la-dc240.lo `test -f 'dc240.c' || echo '$(srcdir)/'`dc240.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdc240_la-dc240.Tpo $(DEPDIR)/libdc240_la-dc240.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dc240.c' object='libdc240_la-dc240.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdc240_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdc240_la-dc240.lo `test -f 'dc240.c' || echo '$(srcdir)/'`dc240.c libdc25_la-dc25.lo: dc25.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdc25_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdc25_la-dc25.lo -MD -MP -MF $(DEPDIR)/libdc25_la-dc25.Tpo -c -o libdc25_la-dc25.lo `test -f 'dc25.c' || echo '$(srcdir)/'`dc25.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdc25_la-dc25.Tpo $(DEPDIR)/libdc25_la-dc25.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dc25.c' object='libdc25_la-dc25.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdc25_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdc25_la-dc25.lo `test -f 'dc25.c' || echo '$(srcdir)/'`dc25.c libdell1600n_net_la-dell1600n_net.lo: dell1600n_net.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdell1600n_net_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdell1600n_net_la-dell1600n_net.lo -MD -MP -MF $(DEPDIR)/libdell1600n_net_la-dell1600n_net.Tpo -c -o libdell1600n_net_la-dell1600n_net.lo `test -f 'dell1600n_net.c' || echo '$(srcdir)/'`dell1600n_net.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdell1600n_net_la-dell1600n_net.Tpo $(DEPDIR)/libdell1600n_net_la-dell1600n_net.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dell1600n_net.c' object='libdell1600n_net_la-dell1600n_net.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdell1600n_net_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdell1600n_net_la-dell1600n_net.lo `test -f 'dell1600n_net.c' || echo '$(srcdir)/'`dell1600n_net.c libdll_la-dll.lo: dll.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdll_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdll_la-dll.lo -MD -MP -MF $(DEPDIR)/libdll_la-dll.Tpo -c -o libdll_la-dll.lo `test -f 'dll.c' || echo '$(srcdir)/'`dll.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdll_la-dll.Tpo $(DEPDIR)/libdll_la-dll.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dll.c' object='libdll_la-dll.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdll_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdll_la-dll.lo `test -f 'dll.c' || echo '$(srcdir)/'`dll.c libdll_preload_la-dll.lo: dll.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdll_preload_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdll_preload_la-dll.lo -MD -MP -MF $(DEPDIR)/libdll_preload_la-dll.Tpo -c -o libdll_preload_la-dll.lo `test -f 'dll.c' || echo '$(srcdir)/'`dll.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdll_preload_la-dll.Tpo $(DEPDIR)/libdll_preload_la-dll.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dll.c' object='libdll_preload_la-dll.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdll_preload_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdll_preload_la-dll.lo `test -f 'dll.c' || echo '$(srcdir)/'`dll.c libdmc_la-dmc.lo: dmc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdmc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libdmc_la-dmc.lo -MD -MP -MF $(DEPDIR)/libdmc_la-dmc.Tpo -c -o libdmc_la-dmc.lo `test -f 'dmc.c' || echo '$(srcdir)/'`dmc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdmc_la-dmc.Tpo $(DEPDIR)/libdmc_la-dmc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dmc.c' object='libdmc_la-dmc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libdmc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libdmc_la-dmc.lo `test -f 'dmc.c' || echo '$(srcdir)/'`dmc.c libepjitsu_la-epjitsu.lo: epjitsu.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepjitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepjitsu_la-epjitsu.lo -MD -MP -MF $(DEPDIR)/libepjitsu_la-epjitsu.Tpo -c -o libepjitsu_la-epjitsu.lo `test -f 'epjitsu.c' || echo '$(srcdir)/'`epjitsu.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepjitsu_la-epjitsu.Tpo $(DEPDIR)/libepjitsu_la-epjitsu.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epjitsu.c' object='libepjitsu_la-epjitsu.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepjitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepjitsu_la-epjitsu.lo `test -f 'epjitsu.c' || echo '$(srcdir)/'`epjitsu.c libepson_la-epson.lo: epson.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson_la-epson.lo -MD -MP -MF $(DEPDIR)/libepson_la-epson.Tpo -c -o libepson_la-epson.lo `test -f 'epson.c' || echo '$(srcdir)/'`epson.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson_la-epson.Tpo $(DEPDIR)/libepson_la-epson.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson.c' object='libepson_la-epson.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson_la-epson.lo `test -f 'epson.c' || echo '$(srcdir)/'`epson.c libepson_la-epson_scsi.lo: epson_scsi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson_la-epson_scsi.lo -MD -MP -MF $(DEPDIR)/libepson_la-epson_scsi.Tpo -c -o libepson_la-epson_scsi.lo `test -f 'epson_scsi.c' || echo '$(srcdir)/'`epson_scsi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson_la-epson_scsi.Tpo $(DEPDIR)/libepson_la-epson_scsi.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson_scsi.c' object='libepson_la-epson_scsi.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson_la-epson_scsi.lo `test -f 'epson_scsi.c' || echo '$(srcdir)/'`epson_scsi.c libepson_la-epson_usb.lo: epson_usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson_la-epson_usb.lo -MD -MP -MF $(DEPDIR)/libepson_la-epson_usb.Tpo -c -o libepson_la-epson_usb.lo `test -f 'epson_usb.c' || echo '$(srcdir)/'`epson_usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson_la-epson_usb.Tpo $(DEPDIR)/libepson_la-epson_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson_usb.c' object='libepson_la-epson_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson_la-epson_usb.lo `test -f 'epson_usb.c' || echo '$(srcdir)/'`epson_usb.c libepson2_la-epson2.lo: epson2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson2.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson2.Tpo -c -o libepson2_la-epson2.lo `test -f 'epson2.c' || echo '$(srcdir)/'`epson2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson2.Tpo $(DEPDIR)/libepson2_la-epson2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2.c' object='libepson2_la-epson2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2.lo `test -f 'epson2.c' || echo '$(srcdir)/'`epson2.c libepson2_la-epson2_scsi.lo: epson2_scsi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson2_scsi.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson2_scsi.Tpo -c -o libepson2_la-epson2_scsi.lo `test -f 'epson2_scsi.c' || echo '$(srcdir)/'`epson2_scsi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson2_scsi.Tpo $(DEPDIR)/libepson2_la-epson2_scsi.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2_scsi.c' object='libepson2_la-epson2_scsi.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2_scsi.lo `test -f 'epson2_scsi.c' || echo '$(srcdir)/'`epson2_scsi.c libepson2_la-epson2_usb.lo: epson2_usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson2_usb.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson2_usb.Tpo -c -o libepson2_la-epson2_usb.lo `test -f 'epson2_usb.c' || echo '$(srcdir)/'`epson2_usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson2_usb.Tpo $(DEPDIR)/libepson2_la-epson2_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2_usb.c' object='libepson2_la-epson2_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2_usb.lo `test -f 'epson2_usb.c' || echo '$(srcdir)/'`epson2_usb.c libepson2_la-epson2_net.lo: epson2_net.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson2_net.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson2_net.Tpo -c -o libepson2_la-epson2_net.lo `test -f 'epson2_net.c' || echo '$(srcdir)/'`epson2_net.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson2_net.Tpo $(DEPDIR)/libepson2_la-epson2_net.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2_net.c' object='libepson2_la-epson2_net.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2_net.lo `test -f 'epson2_net.c' || echo '$(srcdir)/'`epson2_net.c libepson2_la-epson2-io.lo: epson2-io.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson2-io.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson2-io.Tpo -c -o libepson2_la-epson2-io.lo `test -f 'epson2-io.c' || echo '$(srcdir)/'`epson2-io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson2-io.Tpo $(DEPDIR)/libepson2_la-epson2-io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2-io.c' object='libepson2_la-epson2-io.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2-io.lo `test -f 'epson2-io.c' || echo '$(srcdir)/'`epson2-io.c libepson2_la-epson2-commands.lo: epson2-commands.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson2-commands.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson2-commands.Tpo -c -o libepson2_la-epson2-commands.lo `test -f 'epson2-commands.c' || echo '$(srcdir)/'`epson2-commands.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson2-commands.Tpo $(DEPDIR)/libepson2_la-epson2-commands.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2-commands.c' object='libepson2_la-epson2-commands.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2-commands.lo `test -f 'epson2-commands.c' || echo '$(srcdir)/'`epson2-commands.c libepson2_la-epson2-ops.lo: epson2-ops.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson2-ops.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson2-ops.Tpo -c -o libepson2_la-epson2-ops.lo `test -f 'epson2-ops.c' || echo '$(srcdir)/'`epson2-ops.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson2-ops.Tpo $(DEPDIR)/libepson2_la-epson2-ops.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2-ops.c' object='libepson2_la-epson2-ops.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2-ops.lo `test -f 'epson2-ops.c' || echo '$(srcdir)/'`epson2-ops.c libepson2_la-epson2-cct.lo: epson2-cct.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepson2_la-epson2-cct.lo -MD -MP -MF $(DEPDIR)/libepson2_la-epson2-cct.Tpo -c -o libepson2_la-epson2-cct.lo `test -f 'epson2-cct.c' || echo '$(srcdir)/'`epson2-cct.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepson2_la-epson2-cct.Tpo $(DEPDIR)/libepson2_la-epson2-cct.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2-cct.c' object='libepson2_la-epson2-cct.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepson2_la-epson2-cct.lo `test -f 'epson2-cct.c' || echo '$(srcdir)/'`epson2-cct.c libepsonds_la-epsonds.lo: epsonds.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds.Tpo -c -o libepsonds_la-epsonds.lo `test -f 'epsonds.c' || echo '$(srcdir)/'`epsonds.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds.Tpo $(DEPDIR)/libepsonds_la-epsonds.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds.c' object='libepsonds_la-epsonds.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds.lo `test -f 'epsonds.c' || echo '$(srcdir)/'`epsonds.c libepsonds_la-epsonds-usb.lo: epsonds-usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-usb.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-usb.Tpo -c -o libepsonds_la-epsonds-usb.lo `test -f 'epsonds-usb.c' || echo '$(srcdir)/'`epsonds-usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-usb.Tpo $(DEPDIR)/libepsonds_la-epsonds-usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-usb.c' object='libepsonds_la-epsonds-usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-usb.lo `test -f 'epsonds-usb.c' || echo '$(srcdir)/'`epsonds-usb.c libepsonds_la-epsonds-io.lo: epsonds-io.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-io.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-io.Tpo -c -o libepsonds_la-epsonds-io.lo `test -f 'epsonds-io.c' || echo '$(srcdir)/'`epsonds-io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-io.Tpo $(DEPDIR)/libepsonds_la-epsonds-io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-io.c' object='libepsonds_la-epsonds-io.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-io.lo `test -f 'epsonds-io.c' || echo '$(srcdir)/'`epsonds-io.c libepsonds_la-epsonds-cmd.lo: epsonds-cmd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-cmd.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-cmd.Tpo -c -o libepsonds_la-epsonds-cmd.lo `test -f 'epsonds-cmd.c' || echo '$(srcdir)/'`epsonds-cmd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-cmd.Tpo $(DEPDIR)/libepsonds_la-epsonds-cmd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-cmd.c' object='libepsonds_la-epsonds-cmd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-cmd.lo `test -f 'epsonds-cmd.c' || echo '$(srcdir)/'`epsonds-cmd.c libepsonds_la-epsonds-ops.lo: epsonds-ops.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-ops.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-ops.Tpo -c -o libepsonds_la-epsonds-ops.lo `test -f 'epsonds-ops.c' || echo '$(srcdir)/'`epsonds-ops.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-ops.Tpo $(DEPDIR)/libepsonds_la-epsonds-ops.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-ops.c' object='libepsonds_la-epsonds-ops.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-ops.lo `test -f 'epsonds-ops.c' || echo '$(srcdir)/'`epsonds-ops.c libepsonds_la-epsonds-jpeg.lo: epsonds-jpeg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-jpeg.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-jpeg.Tpo -c -o libepsonds_la-epsonds-jpeg.lo `test -f 'epsonds-jpeg.c' || echo '$(srcdir)/'`epsonds-jpeg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-jpeg.Tpo $(DEPDIR)/libepsonds_la-epsonds-jpeg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-jpeg.c' object='libepsonds_la-epsonds-jpeg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-jpeg.lo `test -f 'epsonds-jpeg.c' || echo '$(srcdir)/'`epsonds-jpeg.c libepsonds_la-epsonds-net.lo: epsonds-net.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libepsonds_la-epsonds-net.lo -MD -MP -MF $(DEPDIR)/libepsonds_la-epsonds-net.Tpo -c -o libepsonds_la-epsonds-net.lo `test -f 'epsonds-net.c' || echo '$(srcdir)/'`epsonds-net.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libepsonds_la-epsonds-net.Tpo $(DEPDIR)/libepsonds_la-epsonds-net.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-net.c' object='libepsonds_la-epsonds-net.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libepsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libepsonds_la-epsonds-net.lo `test -f 'epsonds-net.c' || echo '$(srcdir)/'`epsonds-net.c libfujitsu_la-fujitsu.lo: fujitsu.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfujitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libfujitsu_la-fujitsu.lo -MD -MP -MF $(DEPDIR)/libfujitsu_la-fujitsu.Tpo -c -o libfujitsu_la-fujitsu.lo `test -f 'fujitsu.c' || echo '$(srcdir)/'`fujitsu.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libfujitsu_la-fujitsu.Tpo $(DEPDIR)/libfujitsu_la-fujitsu.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fujitsu.c' object='libfujitsu_la-fujitsu.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libfujitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libfujitsu_la-fujitsu.lo `test -f 'fujitsu.c' || echo '$(srcdir)/'`fujitsu.c libgenesys_la-genesys.lo: genesys.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgenesys_la-genesys.lo -MD -MP -MF $(DEPDIR)/libgenesys_la-genesys.Tpo -c -o libgenesys_la-genesys.lo `test -f 'genesys.c' || echo '$(srcdir)/'`genesys.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenesys_la-genesys.Tpo $(DEPDIR)/libgenesys_la-genesys.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys.c' object='libgenesys_la-genesys.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgenesys_la-genesys.lo `test -f 'genesys.c' || echo '$(srcdir)/'`genesys.c libgenesys_la-genesys_gl646.lo: genesys_gl646.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgenesys_la-genesys_gl646.lo -MD -MP -MF $(DEPDIR)/libgenesys_la-genesys_gl646.Tpo -c -o libgenesys_la-genesys_gl646.lo `test -f 'genesys_gl646.c' || echo '$(srcdir)/'`genesys_gl646.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenesys_la-genesys_gl646.Tpo $(DEPDIR)/libgenesys_la-genesys_gl646.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys_gl646.c' object='libgenesys_la-genesys_gl646.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgenesys_la-genesys_gl646.lo `test -f 'genesys_gl646.c' || echo '$(srcdir)/'`genesys_gl646.c libgenesys_la-genesys_gl841.lo: genesys_gl841.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgenesys_la-genesys_gl841.lo -MD -MP -MF $(DEPDIR)/libgenesys_la-genesys_gl841.Tpo -c -o libgenesys_la-genesys_gl841.lo `test -f 'genesys_gl841.c' || echo '$(srcdir)/'`genesys_gl841.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenesys_la-genesys_gl841.Tpo $(DEPDIR)/libgenesys_la-genesys_gl841.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys_gl841.c' object='libgenesys_la-genesys_gl841.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgenesys_la-genesys_gl841.lo `test -f 'genesys_gl841.c' || echo '$(srcdir)/'`genesys_gl841.c libgenesys_la-genesys_gl843.lo: genesys_gl843.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgenesys_la-genesys_gl843.lo -MD -MP -MF $(DEPDIR)/libgenesys_la-genesys_gl843.Tpo -c -o libgenesys_la-genesys_gl843.lo `test -f 'genesys_gl843.c' || echo '$(srcdir)/'`genesys_gl843.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenesys_la-genesys_gl843.Tpo $(DEPDIR)/libgenesys_la-genesys_gl843.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys_gl843.c' object='libgenesys_la-genesys_gl843.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgenesys_la-genesys_gl843.lo `test -f 'genesys_gl843.c' || echo '$(srcdir)/'`genesys_gl843.c libgenesys_la-genesys_gl846.lo: genesys_gl846.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgenesys_la-genesys_gl846.lo -MD -MP -MF $(DEPDIR)/libgenesys_la-genesys_gl846.Tpo -c -o libgenesys_la-genesys_gl846.lo `test -f 'genesys_gl846.c' || echo '$(srcdir)/'`genesys_gl846.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenesys_la-genesys_gl846.Tpo $(DEPDIR)/libgenesys_la-genesys_gl846.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys_gl846.c' object='libgenesys_la-genesys_gl846.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgenesys_la-genesys_gl846.lo `test -f 'genesys_gl846.c' || echo '$(srcdir)/'`genesys_gl846.c libgenesys_la-genesys_gl847.lo: genesys_gl847.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgenesys_la-genesys_gl847.lo -MD -MP -MF $(DEPDIR)/libgenesys_la-genesys_gl847.Tpo -c -o libgenesys_la-genesys_gl847.lo `test -f 'genesys_gl847.c' || echo '$(srcdir)/'`genesys_gl847.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenesys_la-genesys_gl847.Tpo $(DEPDIR)/libgenesys_la-genesys_gl847.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys_gl847.c' object='libgenesys_la-genesys_gl847.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgenesys_la-genesys_gl847.lo `test -f 'genesys_gl847.c' || echo '$(srcdir)/'`genesys_gl847.c libgenesys_la-genesys_gl124.lo: genesys_gl124.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgenesys_la-genesys_gl124.lo -MD -MP -MF $(DEPDIR)/libgenesys_la-genesys_gl124.Tpo -c -o libgenesys_la-genesys_gl124.lo `test -f 'genesys_gl124.c' || echo '$(srcdir)/'`genesys_gl124.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenesys_la-genesys_gl124.Tpo $(DEPDIR)/libgenesys_la-genesys_gl124.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys_gl124.c' object='libgenesys_la-genesys_gl124.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgenesys_la-genesys_gl124.lo `test -f 'genesys_gl124.c' || echo '$(srcdir)/'`genesys_gl124.c libgenesys_la-genesys_low.lo: genesys_low.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgenesys_la-genesys_low.lo -MD -MP -MF $(DEPDIR)/libgenesys_la-genesys_low.Tpo -c -o libgenesys_la-genesys_low.lo `test -f 'genesys_low.c' || echo '$(srcdir)/'`genesys_low.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenesys_la-genesys_low.Tpo $(DEPDIR)/libgenesys_la-genesys_low.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys_low.c' object='libgenesys_la-genesys_low.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgenesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgenesys_la-genesys_low.lo `test -f 'genesys_low.c' || echo '$(srcdir)/'`genesys_low.c libgphoto2_i_la-gphoto2.lo: gphoto2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgphoto2_i_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgphoto2_i_la-gphoto2.lo -MD -MP -MF $(DEPDIR)/libgphoto2_i_la-gphoto2.Tpo -c -o libgphoto2_i_la-gphoto2.lo `test -f 'gphoto2.c' || echo '$(srcdir)/'`gphoto2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgphoto2_i_la-gphoto2.Tpo $(DEPDIR)/libgphoto2_i_la-gphoto2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gphoto2.c' object='libgphoto2_i_la-gphoto2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgphoto2_i_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgphoto2_i_la-gphoto2.lo `test -f 'gphoto2.c' || echo '$(srcdir)/'`gphoto2.c libgt68xx_la-gt68xx.lo: gt68xx.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgt68xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgt68xx_la-gt68xx.lo -MD -MP -MF $(DEPDIR)/libgt68xx_la-gt68xx.Tpo -c -o libgt68xx_la-gt68xx.lo `test -f 'gt68xx.c' || echo '$(srcdir)/'`gt68xx.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgt68xx_la-gt68xx.Tpo $(DEPDIR)/libgt68xx_la-gt68xx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gt68xx.c' object='libgt68xx_la-gt68xx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgt68xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgt68xx_la-gt68xx.lo `test -f 'gt68xx.c' || echo '$(srcdir)/'`gt68xx.c libhp_la-hp.lo: hp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp_la-hp.lo -MD -MP -MF $(DEPDIR)/libhp_la-hp.Tpo -c -o libhp_la-hp.lo `test -f 'hp.c' || echo '$(srcdir)/'`hp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp_la-hp.Tpo $(DEPDIR)/libhp_la-hp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp.c' object='libhp_la-hp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp_la-hp.lo `test -f 'hp.c' || echo '$(srcdir)/'`hp.c libhp_la-hp-accessor.lo: hp-accessor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp_la-hp-accessor.lo -MD -MP -MF $(DEPDIR)/libhp_la-hp-accessor.Tpo -c -o libhp_la-hp-accessor.lo `test -f 'hp-accessor.c' || echo '$(srcdir)/'`hp-accessor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp_la-hp-accessor.Tpo $(DEPDIR)/libhp_la-hp-accessor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp-accessor.c' object='libhp_la-hp-accessor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp_la-hp-accessor.lo `test -f 'hp-accessor.c' || echo '$(srcdir)/'`hp-accessor.c libhp_la-hp-device.lo: hp-device.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp_la-hp-device.lo -MD -MP -MF $(DEPDIR)/libhp_la-hp-device.Tpo -c -o libhp_la-hp-device.lo `test -f 'hp-device.c' || echo '$(srcdir)/'`hp-device.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp_la-hp-device.Tpo $(DEPDIR)/libhp_la-hp-device.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp-device.c' object='libhp_la-hp-device.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp_la-hp-device.lo `test -f 'hp-device.c' || echo '$(srcdir)/'`hp-device.c libhp_la-hp-handle.lo: hp-handle.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp_la-hp-handle.lo -MD -MP -MF $(DEPDIR)/libhp_la-hp-handle.Tpo -c -o libhp_la-hp-handle.lo `test -f 'hp-handle.c' || echo '$(srcdir)/'`hp-handle.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp_la-hp-handle.Tpo $(DEPDIR)/libhp_la-hp-handle.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp-handle.c' object='libhp_la-hp-handle.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp_la-hp-handle.lo `test -f 'hp-handle.c' || echo '$(srcdir)/'`hp-handle.c libhp_la-hp-hpmem.lo: hp-hpmem.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp_la-hp-hpmem.lo -MD -MP -MF $(DEPDIR)/libhp_la-hp-hpmem.Tpo -c -o libhp_la-hp-hpmem.lo `test -f 'hp-hpmem.c' || echo '$(srcdir)/'`hp-hpmem.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp_la-hp-hpmem.Tpo $(DEPDIR)/libhp_la-hp-hpmem.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp-hpmem.c' object='libhp_la-hp-hpmem.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp_la-hp-hpmem.lo `test -f 'hp-hpmem.c' || echo '$(srcdir)/'`hp-hpmem.c libhp_la-hp-option.lo: hp-option.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp_la-hp-option.lo -MD -MP -MF $(DEPDIR)/libhp_la-hp-option.Tpo -c -o libhp_la-hp-option.lo `test -f 'hp-option.c' || echo '$(srcdir)/'`hp-option.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp_la-hp-option.Tpo $(DEPDIR)/libhp_la-hp-option.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp-option.c' object='libhp_la-hp-option.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp_la-hp-option.lo `test -f 'hp-option.c' || echo '$(srcdir)/'`hp-option.c libhp_la-hp-scl.lo: hp-scl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp_la-hp-scl.lo -MD -MP -MF $(DEPDIR)/libhp_la-hp-scl.Tpo -c -o libhp_la-hp-scl.lo `test -f 'hp-scl.c' || echo '$(srcdir)/'`hp-scl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp_la-hp-scl.Tpo $(DEPDIR)/libhp_la-hp-scl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp-scl.c' object='libhp_la-hp-scl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp_la-hp-scl.lo `test -f 'hp-scl.c' || echo '$(srcdir)/'`hp-scl.c libhp3500_la-hp3500.lo: hp3500.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp3500_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp3500_la-hp3500.lo -MD -MP -MF $(DEPDIR)/libhp3500_la-hp3500.Tpo -c -o libhp3500_la-hp3500.lo `test -f 'hp3500.c' || echo '$(srcdir)/'`hp3500.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp3500_la-hp3500.Tpo $(DEPDIR)/libhp3500_la-hp3500.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp3500.c' object='libhp3500_la-hp3500.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp3500_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp3500_la-hp3500.lo `test -f 'hp3500.c' || echo '$(srcdir)/'`hp3500.c libhp3900_la-hp3900.lo: hp3900.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp3900_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp3900_la-hp3900.lo -MD -MP -MF $(DEPDIR)/libhp3900_la-hp3900.Tpo -c -o libhp3900_la-hp3900.lo `test -f 'hp3900.c' || echo '$(srcdir)/'`hp3900.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp3900_la-hp3900.Tpo $(DEPDIR)/libhp3900_la-hp3900.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp3900.c' object='libhp3900_la-hp3900.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp3900_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp3900_la-hp3900.lo `test -f 'hp3900.c' || echo '$(srcdir)/'`hp3900.c libhp4200_la-hp4200.lo: hp4200.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp4200_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp4200_la-hp4200.lo -MD -MP -MF $(DEPDIR)/libhp4200_la-hp4200.Tpo -c -o libhp4200_la-hp4200.lo `test -f 'hp4200.c' || echo '$(srcdir)/'`hp4200.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp4200_la-hp4200.Tpo $(DEPDIR)/libhp4200_la-hp4200.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp4200.c' object='libhp4200_la-hp4200.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp4200_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp4200_la-hp4200.lo `test -f 'hp4200.c' || echo '$(srcdir)/'`hp4200.c libhp5400_la-hp5400.lo: hp5400.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp5400_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp5400_la-hp5400.lo -MD -MP -MF $(DEPDIR)/libhp5400_la-hp5400.Tpo -c -o libhp5400_la-hp5400.lo `test -f 'hp5400.c' || echo '$(srcdir)/'`hp5400.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp5400_la-hp5400.Tpo $(DEPDIR)/libhp5400_la-hp5400.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp5400.c' object='libhp5400_la-hp5400.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp5400_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp5400_la-hp5400.lo `test -f 'hp5400.c' || echo '$(srcdir)/'`hp5400.c libhp5590_la-hp5590.lo: hp5590.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp5590_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhp5590_la-hp5590.lo -MD -MP -MF $(DEPDIR)/libhp5590_la-hp5590.Tpo -c -o libhp5590_la-hp5590.lo `test -f 'hp5590.c' || echo '$(srcdir)/'`hp5590.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhp5590_la-hp5590.Tpo $(DEPDIR)/libhp5590_la-hp5590.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp5590.c' object='libhp5590_la-hp5590.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhp5590_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhp5590_la-hp5590.lo `test -f 'hp5590.c' || echo '$(srcdir)/'`hp5590.c libhpljm1005_la-hpljm1005.lo: hpljm1005.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpljm1005_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhpljm1005_la-hpljm1005.lo -MD -MP -MF $(DEPDIR)/libhpljm1005_la-hpljm1005.Tpo -c -o libhpljm1005_la-hpljm1005.lo `test -f 'hpljm1005.c' || echo '$(srcdir)/'`hpljm1005.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhpljm1005_la-hpljm1005.Tpo $(DEPDIR)/libhpljm1005_la-hpljm1005.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hpljm1005.c' object='libhpljm1005_la-hpljm1005.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpljm1005_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhpljm1005_la-hpljm1005.lo `test -f 'hpljm1005.c' || echo '$(srcdir)/'`hpljm1005.c libhpsj5s_la-hpsj5s.lo: hpsj5s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpsj5s_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhpsj5s_la-hpsj5s.lo -MD -MP -MF $(DEPDIR)/libhpsj5s_la-hpsj5s.Tpo -c -o libhpsj5s_la-hpsj5s.lo `test -f 'hpsj5s.c' || echo '$(srcdir)/'`hpsj5s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhpsj5s_la-hpsj5s.Tpo $(DEPDIR)/libhpsj5s_la-hpsj5s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hpsj5s.c' object='libhpsj5s_la-hpsj5s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhpsj5s_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhpsj5s_la-hpsj5s.lo `test -f 'hpsj5s.c' || echo '$(srcdir)/'`hpsj5s.c libhs2p_la-hs2p.lo: hs2p.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhs2p_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libhs2p_la-hs2p.lo -MD -MP -MF $(DEPDIR)/libhs2p_la-hs2p.Tpo -c -o libhs2p_la-hs2p.lo `test -f 'hs2p.c' || echo '$(srcdir)/'`hs2p.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhs2p_la-hs2p.Tpo $(DEPDIR)/libhs2p_la-hs2p.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hs2p.c' object='libhs2p_la-hs2p.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhs2p_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libhs2p_la-hs2p.lo `test -f 'hs2p.c' || echo '$(srcdir)/'`hs2p.c libibm_la-ibm.lo: ibm.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libibm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libibm_la-ibm.lo -MD -MP -MF $(DEPDIR)/libibm_la-ibm.Tpo -c -o libibm_la-ibm.lo `test -f 'ibm.c' || echo '$(srcdir)/'`ibm.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libibm_la-ibm.Tpo $(DEPDIR)/libibm_la-ibm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ibm.c' object='libibm_la-ibm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libibm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libibm_la-ibm.lo `test -f 'ibm.c' || echo '$(srcdir)/'`ibm.c libkodak_la-kodak.lo: kodak.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkodak_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkodak_la-kodak.lo -MD -MP -MF $(DEPDIR)/libkodak_la-kodak.Tpo -c -o libkodak_la-kodak.lo `test -f 'kodak.c' || echo '$(srcdir)/'`kodak.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkodak_la-kodak.Tpo $(DEPDIR)/libkodak_la-kodak.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kodak.c' object='libkodak_la-kodak.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkodak_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkodak_la-kodak.lo `test -f 'kodak.c' || echo '$(srcdir)/'`kodak.c libkodakaio_la-kodakaio.lo: kodakaio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkodakaio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkodakaio_la-kodakaio.lo -MD -MP -MF $(DEPDIR)/libkodakaio_la-kodakaio.Tpo -c -o libkodakaio_la-kodakaio.lo `test -f 'kodakaio.c' || echo '$(srcdir)/'`kodakaio.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkodakaio_la-kodakaio.Tpo $(DEPDIR)/libkodakaio_la-kodakaio.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kodakaio.c' object='libkodakaio_la-kodakaio.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkodakaio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkodakaio_la-kodakaio.lo `test -f 'kodakaio.c' || echo '$(srcdir)/'`kodakaio.c libkvs1025_la-kvs1025.lo: kvs1025.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs1025_la-kvs1025.lo -MD -MP -MF $(DEPDIR)/libkvs1025_la-kvs1025.Tpo -c -o libkvs1025_la-kvs1025.lo `test -f 'kvs1025.c' || echo '$(srcdir)/'`kvs1025.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs1025_la-kvs1025.Tpo $(DEPDIR)/libkvs1025_la-kvs1025.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs1025.c' object='libkvs1025_la-kvs1025.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs1025_la-kvs1025.lo `test -f 'kvs1025.c' || echo '$(srcdir)/'`kvs1025.c libkvs1025_la-kvs1025_low.lo: kvs1025_low.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs1025_la-kvs1025_low.lo -MD -MP -MF $(DEPDIR)/libkvs1025_la-kvs1025_low.Tpo -c -o libkvs1025_la-kvs1025_low.lo `test -f 'kvs1025_low.c' || echo '$(srcdir)/'`kvs1025_low.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs1025_la-kvs1025_low.Tpo $(DEPDIR)/libkvs1025_la-kvs1025_low.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs1025_low.c' object='libkvs1025_la-kvs1025_low.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs1025_la-kvs1025_low.lo `test -f 'kvs1025_low.c' || echo '$(srcdir)/'`kvs1025_low.c libkvs1025_la-kvs1025_opt.lo: kvs1025_opt.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs1025_la-kvs1025_opt.lo -MD -MP -MF $(DEPDIR)/libkvs1025_la-kvs1025_opt.Tpo -c -o libkvs1025_la-kvs1025_opt.lo `test -f 'kvs1025_opt.c' || echo '$(srcdir)/'`kvs1025_opt.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs1025_la-kvs1025_opt.Tpo $(DEPDIR)/libkvs1025_la-kvs1025_opt.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs1025_opt.c' object='libkvs1025_la-kvs1025_opt.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs1025_la-kvs1025_opt.lo `test -f 'kvs1025_opt.c' || echo '$(srcdir)/'`kvs1025_opt.c libkvs1025_la-kvs1025_usb.lo: kvs1025_usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs1025_la-kvs1025_usb.lo -MD -MP -MF $(DEPDIR)/libkvs1025_la-kvs1025_usb.Tpo -c -o libkvs1025_la-kvs1025_usb.lo `test -f 'kvs1025_usb.c' || echo '$(srcdir)/'`kvs1025_usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs1025_la-kvs1025_usb.Tpo $(DEPDIR)/libkvs1025_la-kvs1025_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs1025_usb.c' object='libkvs1025_la-kvs1025_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs1025_la-kvs1025_usb.lo `test -f 'kvs1025_usb.c' || echo '$(srcdir)/'`kvs1025_usb.c libkvs20xx_la-kvs20xx.lo: kvs20xx.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs20xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs20xx_la-kvs20xx.lo -MD -MP -MF $(DEPDIR)/libkvs20xx_la-kvs20xx.Tpo -c -o libkvs20xx_la-kvs20xx.lo `test -f 'kvs20xx.c' || echo '$(srcdir)/'`kvs20xx.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs20xx_la-kvs20xx.Tpo $(DEPDIR)/libkvs20xx_la-kvs20xx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs20xx.c' object='libkvs20xx_la-kvs20xx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs20xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs20xx_la-kvs20xx.lo `test -f 'kvs20xx.c' || echo '$(srcdir)/'`kvs20xx.c libkvs20xx_la-kvs20xx_cmd.lo: kvs20xx_cmd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs20xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs20xx_la-kvs20xx_cmd.lo -MD -MP -MF $(DEPDIR)/libkvs20xx_la-kvs20xx_cmd.Tpo -c -o libkvs20xx_la-kvs20xx_cmd.lo `test -f 'kvs20xx_cmd.c' || echo '$(srcdir)/'`kvs20xx_cmd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs20xx_la-kvs20xx_cmd.Tpo $(DEPDIR)/libkvs20xx_la-kvs20xx_cmd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs20xx_cmd.c' object='libkvs20xx_la-kvs20xx_cmd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs20xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs20xx_la-kvs20xx_cmd.lo `test -f 'kvs20xx_cmd.c' || echo '$(srcdir)/'`kvs20xx_cmd.c libkvs20xx_la-kvs20xx_opt.lo: kvs20xx_opt.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs20xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs20xx_la-kvs20xx_opt.lo -MD -MP -MF $(DEPDIR)/libkvs20xx_la-kvs20xx_opt.Tpo -c -o libkvs20xx_la-kvs20xx_opt.lo `test -f 'kvs20xx_opt.c' || echo '$(srcdir)/'`kvs20xx_opt.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs20xx_la-kvs20xx_opt.Tpo $(DEPDIR)/libkvs20xx_la-kvs20xx_opt.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs20xx_opt.c' object='libkvs20xx_la-kvs20xx_opt.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs20xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs20xx_la-kvs20xx_opt.lo `test -f 'kvs20xx_opt.c' || echo '$(srcdir)/'`kvs20xx_opt.c libkvs40xx_la-kvs40xx.lo: kvs40xx.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs40xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs40xx_la-kvs40xx.lo -MD -MP -MF $(DEPDIR)/libkvs40xx_la-kvs40xx.Tpo -c -o libkvs40xx_la-kvs40xx.lo `test -f 'kvs40xx.c' || echo '$(srcdir)/'`kvs40xx.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs40xx_la-kvs40xx.Tpo $(DEPDIR)/libkvs40xx_la-kvs40xx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs40xx.c' object='libkvs40xx_la-kvs40xx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs40xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs40xx_la-kvs40xx.lo `test -f 'kvs40xx.c' || echo '$(srcdir)/'`kvs40xx.c libkvs40xx_la-kvs40xx_cmd.lo: kvs40xx_cmd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs40xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs40xx_la-kvs40xx_cmd.lo -MD -MP -MF $(DEPDIR)/libkvs40xx_la-kvs40xx_cmd.Tpo -c -o libkvs40xx_la-kvs40xx_cmd.lo `test -f 'kvs40xx_cmd.c' || echo '$(srcdir)/'`kvs40xx_cmd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs40xx_la-kvs40xx_cmd.Tpo $(DEPDIR)/libkvs40xx_la-kvs40xx_cmd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs40xx_cmd.c' object='libkvs40xx_la-kvs40xx_cmd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs40xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs40xx_la-kvs40xx_cmd.lo `test -f 'kvs40xx_cmd.c' || echo '$(srcdir)/'`kvs40xx_cmd.c libkvs40xx_la-kvs40xx_opt.lo: kvs40xx_opt.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs40xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libkvs40xx_la-kvs40xx_opt.lo -MD -MP -MF $(DEPDIR)/libkvs40xx_la-kvs40xx_opt.Tpo -c -o libkvs40xx_la-kvs40xx_opt.lo `test -f 'kvs40xx_opt.c' || echo '$(srcdir)/'`kvs40xx_opt.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libkvs40xx_la-kvs40xx_opt.Tpo $(DEPDIR)/libkvs40xx_la-kvs40xx_opt.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs40xx_opt.c' object='libkvs40xx_la-kvs40xx_opt.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkvs40xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkvs40xx_la-kvs40xx_opt.lo `test -f 'kvs40xx_opt.c' || echo '$(srcdir)/'`kvs40xx_opt.c libleo_la-leo.lo: leo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libleo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libleo_la-leo.lo -MD -MP -MF $(DEPDIR)/libleo_la-leo.Tpo -c -o libleo_la-leo.lo `test -f 'leo.c' || echo '$(srcdir)/'`leo.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libleo_la-leo.Tpo $(DEPDIR)/libleo_la-leo.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='leo.c' object='libleo_la-leo.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libleo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libleo_la-leo.lo `test -f 'leo.c' || echo '$(srcdir)/'`leo.c liblexmark_la-lexmark.lo: lexmark.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblexmark_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblexmark_la-lexmark.lo -MD -MP -MF $(DEPDIR)/liblexmark_la-lexmark.Tpo -c -o liblexmark_la-lexmark.lo `test -f 'lexmark.c' || echo '$(srcdir)/'`lexmark.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liblexmark_la-lexmark.Tpo $(DEPDIR)/liblexmark_la-lexmark.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lexmark.c' object='liblexmark_la-lexmark.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblexmark_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblexmark_la-lexmark.lo `test -f 'lexmark.c' || echo '$(srcdir)/'`lexmark.c liblexmark_la-lexmark_low.lo: lexmark_low.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblexmark_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT liblexmark_la-lexmark_low.lo -MD -MP -MF $(DEPDIR)/liblexmark_la-lexmark_low.Tpo -c -o liblexmark_la-lexmark_low.lo `test -f 'lexmark_low.c' || echo '$(srcdir)/'`lexmark_low.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liblexmark_la-lexmark_low.Tpo $(DEPDIR)/liblexmark_la-lexmark_low.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lexmark_low.c' object='liblexmark_la-lexmark_low.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liblexmark_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o liblexmark_la-lexmark_low.lo `test -f 'lexmark_low.c' || echo '$(srcdir)/'`lexmark_low.c libma1509_la-ma1509.lo: ma1509.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libma1509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libma1509_la-ma1509.lo -MD -MP -MF $(DEPDIR)/libma1509_la-ma1509.Tpo -c -o libma1509_la-ma1509.lo `test -f 'ma1509.c' || echo '$(srcdir)/'`ma1509.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libma1509_la-ma1509.Tpo $(DEPDIR)/libma1509_la-ma1509.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ma1509.c' object='libma1509_la-ma1509.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libma1509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libma1509_la-ma1509.lo `test -f 'ma1509.c' || echo '$(srcdir)/'`ma1509.c libmagicolor_la-magicolor.lo: magicolor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmagicolor_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmagicolor_la-magicolor.lo -MD -MP -MF $(DEPDIR)/libmagicolor_la-magicolor.Tpo -c -o libmagicolor_la-magicolor.lo `test -f 'magicolor.c' || echo '$(srcdir)/'`magicolor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmagicolor_la-magicolor.Tpo $(DEPDIR)/libmagicolor_la-magicolor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='magicolor.c' object='libmagicolor_la-magicolor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmagicolor_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmagicolor_la-magicolor.lo `test -f 'magicolor.c' || echo '$(srcdir)/'`magicolor.c libmatsushita_la-matsushita.lo: matsushita.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmatsushita_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmatsushita_la-matsushita.lo -MD -MP -MF $(DEPDIR)/libmatsushita_la-matsushita.Tpo -c -o libmatsushita_la-matsushita.lo `test -f 'matsushita.c' || echo '$(srcdir)/'`matsushita.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmatsushita_la-matsushita.Tpo $(DEPDIR)/libmatsushita_la-matsushita.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='matsushita.c' object='libmatsushita_la-matsushita.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmatsushita_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmatsushita_la-matsushita.lo `test -f 'matsushita.c' || echo '$(srcdir)/'`matsushita.c libmicrotek_la-microtek.lo: microtek.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmicrotek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmicrotek_la-microtek.lo -MD -MP -MF $(DEPDIR)/libmicrotek_la-microtek.Tpo -c -o libmicrotek_la-microtek.lo `test -f 'microtek.c' || echo '$(srcdir)/'`microtek.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmicrotek_la-microtek.Tpo $(DEPDIR)/libmicrotek_la-microtek.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='microtek.c' object='libmicrotek_la-microtek.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmicrotek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmicrotek_la-microtek.lo `test -f 'microtek.c' || echo '$(srcdir)/'`microtek.c libmicrotek2_la-microtek2.lo: microtek2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmicrotek2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmicrotek2_la-microtek2.lo -MD -MP -MF $(DEPDIR)/libmicrotek2_la-microtek2.Tpo -c -o libmicrotek2_la-microtek2.lo `test -f 'microtek2.c' || echo '$(srcdir)/'`microtek2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmicrotek2_la-microtek2.Tpo $(DEPDIR)/libmicrotek2_la-microtek2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='microtek2.c' object='libmicrotek2_la-microtek2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmicrotek2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmicrotek2_la-microtek2.lo `test -f 'microtek2.c' || echo '$(srcdir)/'`microtek2.c libmustek_la-mustek.lo: mustek.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmustek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmustek_la-mustek.lo -MD -MP -MF $(DEPDIR)/libmustek_la-mustek.Tpo -c -o libmustek_la-mustek.lo `test -f 'mustek.c' || echo '$(srcdir)/'`mustek.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmustek_la-mustek.Tpo $(DEPDIR)/libmustek_la-mustek.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mustek.c' object='libmustek_la-mustek.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmustek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmustek_la-mustek.lo `test -f 'mustek.c' || echo '$(srcdir)/'`mustek.c libmustek_pp_la-mustek_pp.lo: mustek_pp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmustek_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmustek_pp_la-mustek_pp.lo -MD -MP -MF $(DEPDIR)/libmustek_pp_la-mustek_pp.Tpo -c -o libmustek_pp_la-mustek_pp.lo `test -f 'mustek_pp.c' || echo '$(srcdir)/'`mustek_pp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmustek_pp_la-mustek_pp.Tpo $(DEPDIR)/libmustek_pp_la-mustek_pp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mustek_pp.c' object='libmustek_pp_la-mustek_pp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmustek_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmustek_pp_la-mustek_pp.lo `test -f 'mustek_pp.c' || echo '$(srcdir)/'`mustek_pp.c libmustek_usb_la-mustek_usb.lo: mustek_usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmustek_usb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmustek_usb_la-mustek_usb.lo -MD -MP -MF $(DEPDIR)/libmustek_usb_la-mustek_usb.Tpo -c -o libmustek_usb_la-mustek_usb.lo `test -f 'mustek_usb.c' || echo '$(srcdir)/'`mustek_usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmustek_usb_la-mustek_usb.Tpo $(DEPDIR)/libmustek_usb_la-mustek_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mustek_usb.c' object='libmustek_usb_la-mustek_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmustek_usb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmustek_usb_la-mustek_usb.lo `test -f 'mustek_usb.c' || echo '$(srcdir)/'`mustek_usb.c libmustek_usb2_la-mustek_usb2.lo: mustek_usb2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmustek_usb2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmustek_usb2_la-mustek_usb2.lo -MD -MP -MF $(DEPDIR)/libmustek_usb2_la-mustek_usb2.Tpo -c -o libmustek_usb2_la-mustek_usb2.lo `test -f 'mustek_usb2.c' || echo '$(srcdir)/'`mustek_usb2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmustek_usb2_la-mustek_usb2.Tpo $(DEPDIR)/libmustek_usb2_la-mustek_usb2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mustek_usb2.c' object='libmustek_usb2_la-mustek_usb2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmustek_usb2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmustek_usb2_la-mustek_usb2.lo `test -f 'mustek_usb2.c' || echo '$(srcdir)/'`mustek_usb2.c libnec_la-nec.lo: nec.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnec_la-nec.lo -MD -MP -MF $(DEPDIR)/libnec_la-nec.Tpo -c -o libnec_la-nec.lo `test -f 'nec.c' || echo '$(srcdir)/'`nec.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnec_la-nec.Tpo $(DEPDIR)/libnec_la-nec.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nec.c' object='libnec_la-nec.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnec_la-nec.lo `test -f 'nec.c' || echo '$(srcdir)/'`nec.c libnet_la-net.lo: net.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnet_la-net.lo -MD -MP -MF $(DEPDIR)/libnet_la-net.Tpo -c -o libnet_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnet_la-net.Tpo $(DEPDIR)/libnet_la-net.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='net.c' object='libnet_la-net.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnet_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c libniash_la-niash.lo: niash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libniash_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libniash_la-niash.lo -MD -MP -MF $(DEPDIR)/libniash_la-niash.Tpo -c -o libniash_la-niash.lo `test -f 'niash.c' || echo '$(srcdir)/'`niash.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libniash_la-niash.Tpo $(DEPDIR)/libniash_la-niash.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='niash.c' object='libniash_la-niash.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libniash_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libniash_la-niash.lo `test -f 'niash.c' || echo '$(srcdir)/'`niash.c libp5_la-p5.lo: p5.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libp5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libp5_la-p5.lo -MD -MP -MF $(DEPDIR)/libp5_la-p5.Tpo -c -o libp5_la-p5.lo `test -f 'p5.c' || echo '$(srcdir)/'`p5.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libp5_la-p5.Tpo $(DEPDIR)/libp5_la-p5.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='p5.c' object='libp5_la-p5.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libp5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libp5_la-p5.lo `test -f 'p5.c' || echo '$(srcdir)/'`p5.c libpie_la-pie.lo: pie.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpie_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpie_la-pie.lo -MD -MP -MF $(DEPDIR)/libpie_la-pie.Tpo -c -o libpie_la-pie.lo `test -f 'pie.c' || echo '$(srcdir)/'`pie.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpie_la-pie.Tpo $(DEPDIR)/libpie_la-pie.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pie.c' object='libpie_la-pie.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpie_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpie_la-pie.lo `test -f 'pie.c' || echo '$(srcdir)/'`pie.c libpieusb_la-pieusb_buffer.lo: pieusb_buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpieusb_la-pieusb_buffer.lo -MD -MP -MF $(DEPDIR)/libpieusb_la-pieusb_buffer.Tpo -c -o libpieusb_la-pieusb_buffer.lo `test -f 'pieusb_buffer.c' || echo '$(srcdir)/'`pieusb_buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpieusb_la-pieusb_buffer.Tpo $(DEPDIR)/libpieusb_la-pieusb_buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pieusb_buffer.c' object='libpieusb_la-pieusb_buffer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpieusb_la-pieusb_buffer.lo `test -f 'pieusb_buffer.c' || echo '$(srcdir)/'`pieusb_buffer.c libpieusb_la-pieusb_scancmd.lo: pieusb_scancmd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpieusb_la-pieusb_scancmd.lo -MD -MP -MF $(DEPDIR)/libpieusb_la-pieusb_scancmd.Tpo -c -o libpieusb_la-pieusb_scancmd.lo `test -f 'pieusb_scancmd.c' || echo '$(srcdir)/'`pieusb_scancmd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpieusb_la-pieusb_scancmd.Tpo $(DEPDIR)/libpieusb_la-pieusb_scancmd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pieusb_scancmd.c' object='libpieusb_la-pieusb_scancmd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpieusb_la-pieusb_scancmd.lo `test -f 'pieusb_scancmd.c' || echo '$(srcdir)/'`pieusb_scancmd.c libpieusb_la-pieusb_specific.lo: pieusb_specific.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpieusb_la-pieusb_specific.lo -MD -MP -MF $(DEPDIR)/libpieusb_la-pieusb_specific.Tpo -c -o libpieusb_la-pieusb_specific.lo `test -f 'pieusb_specific.c' || echo '$(srcdir)/'`pieusb_specific.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpieusb_la-pieusb_specific.Tpo $(DEPDIR)/libpieusb_la-pieusb_specific.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pieusb_specific.c' object='libpieusb_la-pieusb_specific.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpieusb_la-pieusb_specific.lo `test -f 'pieusb_specific.c' || echo '$(srcdir)/'`pieusb_specific.c libpieusb_la-pieusb_usb.lo: pieusb_usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpieusb_la-pieusb_usb.lo -MD -MP -MF $(DEPDIR)/libpieusb_la-pieusb_usb.Tpo -c -o libpieusb_la-pieusb_usb.lo `test -f 'pieusb_usb.c' || echo '$(srcdir)/'`pieusb_usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpieusb_la-pieusb_usb.Tpo $(DEPDIR)/libpieusb_la-pieusb_usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pieusb_usb.c' object='libpieusb_la-pieusb_usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpieusb_la-pieusb_usb.lo `test -f 'pieusb_usb.c' || echo '$(srcdir)/'`pieusb_usb.c libpieusb_la-pieusb.lo: pieusb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpieusb_la-pieusb.lo -MD -MP -MF $(DEPDIR)/libpieusb_la-pieusb.Tpo -c -o libpieusb_la-pieusb.lo `test -f 'pieusb.c' || echo '$(srcdir)/'`pieusb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpieusb_la-pieusb.Tpo $(DEPDIR)/libpieusb_la-pieusb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pieusb.c' object='libpieusb_la-pieusb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpieusb_la-pieusb.lo `test -f 'pieusb.c' || echo '$(srcdir)/'`pieusb.c libpint_la-pint.lo: pint.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpint_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpint_la-pint.lo -MD -MP -MF $(DEPDIR)/libpint_la-pint.Tpo -c -o libpint_la-pint.lo `test -f 'pint.c' || echo '$(srcdir)/'`pint.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpint_la-pint.Tpo $(DEPDIR)/libpint_la-pint.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pint.c' object='libpint_la-pint.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpint_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpint_la-pint.lo `test -f 'pint.c' || echo '$(srcdir)/'`pint.c libpixma_la-pixma.lo: pixma.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma.Tpo -c -o libpixma_la-pixma.lo `test -f 'pixma.c' || echo '$(srcdir)/'`pixma.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma.Tpo $(DEPDIR)/libpixma_la-pixma.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma.c' object='libpixma_la-pixma.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma.lo `test -f 'pixma.c' || echo '$(srcdir)/'`pixma.c libpixma_la-pixma_io_sanei.lo: pixma_io_sanei.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma_io_sanei.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma_io_sanei.Tpo -c -o libpixma_la-pixma_io_sanei.lo `test -f 'pixma_io_sanei.c' || echo '$(srcdir)/'`pixma_io_sanei.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma_io_sanei.Tpo $(DEPDIR)/libpixma_la-pixma_io_sanei.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma_io_sanei.c' object='libpixma_la-pixma_io_sanei.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma_io_sanei.lo `test -f 'pixma_io_sanei.c' || echo '$(srcdir)/'`pixma_io_sanei.c libpixma_la-pixma_common.lo: pixma_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma_common.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma_common.Tpo -c -o libpixma_la-pixma_common.lo `test -f 'pixma_common.c' || echo '$(srcdir)/'`pixma_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma_common.Tpo $(DEPDIR)/libpixma_la-pixma_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma_common.c' object='libpixma_la-pixma_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma_common.lo `test -f 'pixma_common.c' || echo '$(srcdir)/'`pixma_common.c libpixma_la-pixma_mp150.lo: pixma_mp150.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma_mp150.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma_mp150.Tpo -c -o libpixma_la-pixma_mp150.lo `test -f 'pixma_mp150.c' || echo '$(srcdir)/'`pixma_mp150.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma_mp150.Tpo $(DEPDIR)/libpixma_la-pixma_mp150.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma_mp150.c' object='libpixma_la-pixma_mp150.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma_mp150.lo `test -f 'pixma_mp150.c' || echo '$(srcdir)/'`pixma_mp150.c libpixma_la-pixma_mp730.lo: pixma_mp730.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma_mp730.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma_mp730.Tpo -c -o libpixma_la-pixma_mp730.lo `test -f 'pixma_mp730.c' || echo '$(srcdir)/'`pixma_mp730.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma_mp730.Tpo $(DEPDIR)/libpixma_la-pixma_mp730.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma_mp730.c' object='libpixma_la-pixma_mp730.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma_mp730.lo `test -f 'pixma_mp730.c' || echo '$(srcdir)/'`pixma_mp730.c libpixma_la-pixma_mp750.lo: pixma_mp750.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma_mp750.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma_mp750.Tpo -c -o libpixma_la-pixma_mp750.lo `test -f 'pixma_mp750.c' || echo '$(srcdir)/'`pixma_mp750.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma_mp750.Tpo $(DEPDIR)/libpixma_la-pixma_mp750.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma_mp750.c' object='libpixma_la-pixma_mp750.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma_mp750.lo `test -f 'pixma_mp750.c' || echo '$(srcdir)/'`pixma_mp750.c libpixma_la-pixma_mp810.lo: pixma_mp810.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma_mp810.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma_mp810.Tpo -c -o libpixma_la-pixma_mp810.lo `test -f 'pixma_mp810.c' || echo '$(srcdir)/'`pixma_mp810.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma_mp810.Tpo $(DEPDIR)/libpixma_la-pixma_mp810.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma_mp810.c' object='libpixma_la-pixma_mp810.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma_mp810.lo `test -f 'pixma_mp810.c' || echo '$(srcdir)/'`pixma_mp810.c libpixma_la-pixma_imageclass.lo: pixma_imageclass.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma_imageclass.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma_imageclass.Tpo -c -o libpixma_la-pixma_imageclass.lo `test -f 'pixma_imageclass.c' || echo '$(srcdir)/'`pixma_imageclass.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma_imageclass.Tpo $(DEPDIR)/libpixma_la-pixma_imageclass.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma_imageclass.c' object='libpixma_la-pixma_imageclass.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma_imageclass.lo `test -f 'pixma_imageclass.c' || echo '$(srcdir)/'`pixma_imageclass.c libpixma_la-pixma_bjnp.lo: pixma_bjnp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpixma_la-pixma_bjnp.lo -MD -MP -MF $(DEPDIR)/libpixma_la-pixma_bjnp.Tpo -c -o libpixma_la-pixma_bjnp.lo `test -f 'pixma_bjnp.c' || echo '$(srcdir)/'`pixma_bjnp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpixma_la-pixma_bjnp.Tpo $(DEPDIR)/libpixma_la-pixma_bjnp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma_bjnp.c' object='libpixma_la-pixma_bjnp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpixma_la-pixma_bjnp.lo `test -f 'pixma_bjnp.c' || echo '$(srcdir)/'`pixma_bjnp.c libplustek_la-plustek.lo: plustek.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplustek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libplustek_la-plustek.lo -MD -MP -MF $(DEPDIR)/libplustek_la-plustek.Tpo -c -o libplustek_la-plustek.lo `test -f 'plustek.c' || echo '$(srcdir)/'`plustek.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libplustek_la-plustek.Tpo $(DEPDIR)/libplustek_la-plustek.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plustek.c' object='libplustek_la-plustek.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplustek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libplustek_la-plustek.lo `test -f 'plustek.c' || echo '$(srcdir)/'`plustek.c libplustek_pp_la-plustek_pp.lo: plustek_pp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplustek_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libplustek_pp_la-plustek_pp.lo -MD -MP -MF $(DEPDIR)/libplustek_pp_la-plustek_pp.Tpo -c -o libplustek_pp_la-plustek_pp.lo `test -f 'plustek_pp.c' || echo '$(srcdir)/'`plustek_pp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libplustek_pp_la-plustek_pp.Tpo $(DEPDIR)/libplustek_pp_la-plustek_pp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plustek_pp.c' object='libplustek_pp_la-plustek_pp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libplustek_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libplustek_pp_la-plustek_pp.lo `test -f 'plustek_pp.c' || echo '$(srcdir)/'`plustek_pp.c libpnm_la-pnm.lo: pnm.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpnm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpnm_la-pnm.lo -MD -MP -MF $(DEPDIR)/libpnm_la-pnm.Tpo -c -o libpnm_la-pnm.lo `test -f 'pnm.c' || echo '$(srcdir)/'`pnm.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libpnm_la-pnm.Tpo $(DEPDIR)/libpnm_la-pnm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pnm.c' object='libpnm_la-pnm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpnm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpnm_la-pnm.lo `test -f 'pnm.c' || echo '$(srcdir)/'`pnm.c libqcam_la-qcam.lo: qcam.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libqcam_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libqcam_la-qcam.lo -MD -MP -MF $(DEPDIR)/libqcam_la-qcam.Tpo -c -o libqcam_la-qcam.lo `test -f 'qcam.c' || echo '$(srcdir)/'`qcam.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqcam_la-qcam.Tpo $(DEPDIR)/libqcam_la-qcam.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='qcam.c' object='libqcam_la-qcam.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libqcam_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libqcam_la-qcam.lo `test -f 'qcam.c' || echo '$(srcdir)/'`qcam.c libricoh_la-ricoh.lo: ricoh.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libricoh_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libricoh_la-ricoh.lo -MD -MP -MF $(DEPDIR)/libricoh_la-ricoh.Tpo -c -o libricoh_la-ricoh.lo `test -f 'ricoh.c' || echo '$(srcdir)/'`ricoh.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libricoh_la-ricoh.Tpo $(DEPDIR)/libricoh_la-ricoh.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ricoh.c' object='libricoh_la-ricoh.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libricoh_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libricoh_la-ricoh.lo `test -f 'ricoh.c' || echo '$(srcdir)/'`ricoh.c librts8891_la-rts8891.lo: rts8891.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librts8891_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librts8891_la-rts8891.lo -MD -MP -MF $(DEPDIR)/librts8891_la-rts8891.Tpo -c -o librts8891_la-rts8891.lo `test -f 'rts8891.c' || echo '$(srcdir)/'`rts8891.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librts8891_la-rts8891.Tpo $(DEPDIR)/librts8891_la-rts8891.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rts8891.c' object='librts8891_la-rts8891.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librts8891_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librts8891_la-rts8891.lo `test -f 'rts8891.c' || echo '$(srcdir)/'`rts8891.c librts8891_la-rts88xx_lib.lo: rts88xx_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librts8891_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librts8891_la-rts88xx_lib.lo -MD -MP -MF $(DEPDIR)/librts8891_la-rts88xx_lib.Tpo -c -o librts8891_la-rts88xx_lib.lo `test -f 'rts88xx_lib.c' || echo '$(srcdir)/'`rts88xx_lib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librts8891_la-rts88xx_lib.Tpo $(DEPDIR)/librts8891_la-rts88xx_lib.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rts88xx_lib.c' object='librts8891_la-rts88xx_lib.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librts8891_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librts8891_la-rts88xx_lib.lo `test -f 'rts88xx_lib.c' || echo '$(srcdir)/'`rts88xx_lib.c libs9036_la-s9036.lo: s9036.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs9036_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libs9036_la-s9036.lo -MD -MP -MF $(DEPDIR)/libs9036_la-s9036.Tpo -c -o libs9036_la-s9036.lo `test -f 's9036.c' || echo '$(srcdir)/'`s9036.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libs9036_la-s9036.Tpo $(DEPDIR)/libs9036_la-s9036.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='s9036.c' object='libs9036_la-s9036.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libs9036_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libs9036_la-s9036.lo `test -f 's9036.c' || echo '$(srcdir)/'`s9036.c libsane_abaton_la-abaton-s.lo: abaton-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_abaton_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_abaton_la-abaton-s.lo -MD -MP -MF $(DEPDIR)/libsane_abaton_la-abaton-s.Tpo -c -o libsane_abaton_la-abaton-s.lo `test -f 'abaton-s.c' || echo '$(srcdir)/'`abaton-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_abaton_la-abaton-s.Tpo $(DEPDIR)/libsane_abaton_la-abaton-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='abaton-s.c' object='libsane_abaton_la-abaton-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_abaton_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_abaton_la-abaton-s.lo `test -f 'abaton-s.c' || echo '$(srcdir)/'`abaton-s.c libsane_agfafocus_la-agfafocus-s.lo: agfafocus-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_agfafocus_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_agfafocus_la-agfafocus-s.lo -MD -MP -MF $(DEPDIR)/libsane_agfafocus_la-agfafocus-s.Tpo -c -o libsane_agfafocus_la-agfafocus-s.lo `test -f 'agfafocus-s.c' || echo '$(srcdir)/'`agfafocus-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_agfafocus_la-agfafocus-s.Tpo $(DEPDIR)/libsane_agfafocus_la-agfafocus-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='agfafocus-s.c' object='libsane_agfafocus_la-agfafocus-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_agfafocus_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_agfafocus_la-agfafocus-s.lo `test -f 'agfafocus-s.c' || echo '$(srcdir)/'`agfafocus-s.c libsane_apple_la-apple-s.lo: apple-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_apple_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_apple_la-apple-s.lo -MD -MP -MF $(DEPDIR)/libsane_apple_la-apple-s.Tpo -c -o libsane_apple_la-apple-s.lo `test -f 'apple-s.c' || echo '$(srcdir)/'`apple-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_apple_la-apple-s.Tpo $(DEPDIR)/libsane_apple_la-apple-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='apple-s.c' object='libsane_apple_la-apple-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_apple_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_apple_la-apple-s.lo `test -f 'apple-s.c' || echo '$(srcdir)/'`apple-s.c libsane_artec_la-artec-s.lo: artec-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_artec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_artec_la-artec-s.lo -MD -MP -MF $(DEPDIR)/libsane_artec_la-artec-s.Tpo -c -o libsane_artec_la-artec-s.lo `test -f 'artec-s.c' || echo '$(srcdir)/'`artec-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_artec_la-artec-s.Tpo $(DEPDIR)/libsane_artec_la-artec-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='artec-s.c' object='libsane_artec_la-artec-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_artec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_artec_la-artec-s.lo `test -f 'artec-s.c' || echo '$(srcdir)/'`artec-s.c libsane_artec_eplus48u_la-artec_eplus48u-s.lo: artec_eplus48u-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_artec_eplus48u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_artec_eplus48u_la-artec_eplus48u-s.lo -MD -MP -MF $(DEPDIR)/libsane_artec_eplus48u_la-artec_eplus48u-s.Tpo -c -o libsane_artec_eplus48u_la-artec_eplus48u-s.lo `test -f 'artec_eplus48u-s.c' || echo '$(srcdir)/'`artec_eplus48u-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_artec_eplus48u_la-artec_eplus48u-s.Tpo $(DEPDIR)/libsane_artec_eplus48u_la-artec_eplus48u-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='artec_eplus48u-s.c' object='libsane_artec_eplus48u_la-artec_eplus48u-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_artec_eplus48u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_artec_eplus48u_la-artec_eplus48u-s.lo `test -f 'artec_eplus48u-s.c' || echo '$(srcdir)/'`artec_eplus48u-s.c libsane_as6e_la-as6e-s.lo: as6e-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_as6e_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_as6e_la-as6e-s.lo -MD -MP -MF $(DEPDIR)/libsane_as6e_la-as6e-s.Tpo -c -o libsane_as6e_la-as6e-s.lo `test -f 'as6e-s.c' || echo '$(srcdir)/'`as6e-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_as6e_la-as6e-s.Tpo $(DEPDIR)/libsane_as6e_la-as6e-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='as6e-s.c' object='libsane_as6e_la-as6e-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_as6e_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_as6e_la-as6e-s.lo `test -f 'as6e-s.c' || echo '$(srcdir)/'`as6e-s.c libsane_avision_la-avision-s.lo: avision-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_avision_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_avision_la-avision-s.lo -MD -MP -MF $(DEPDIR)/libsane_avision_la-avision-s.Tpo -c -o libsane_avision_la-avision-s.lo `test -f 'avision-s.c' || echo '$(srcdir)/'`avision-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_avision_la-avision-s.Tpo $(DEPDIR)/libsane_avision_la-avision-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='avision-s.c' object='libsane_avision_la-avision-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_avision_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_avision_la-avision-s.lo `test -f 'avision-s.c' || echo '$(srcdir)/'`avision-s.c libsane_bh_la-bh-s.lo: bh-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_bh_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_bh_la-bh-s.lo -MD -MP -MF $(DEPDIR)/libsane_bh_la-bh-s.Tpo -c -o libsane_bh_la-bh-s.lo `test -f 'bh-s.c' || echo '$(srcdir)/'`bh-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_bh_la-bh-s.Tpo $(DEPDIR)/libsane_bh_la-bh-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bh-s.c' object='libsane_bh_la-bh-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_bh_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_bh_la-bh-s.lo `test -f 'bh-s.c' || echo '$(srcdir)/'`bh-s.c libsane_canon_la-canon-s.lo: canon-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_canon_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_canon_la-canon-s.lo -MD -MP -MF $(DEPDIR)/libsane_canon_la-canon-s.Tpo -c -o libsane_canon_la-canon-s.lo `test -f 'canon-s.c' || echo '$(srcdir)/'`canon-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_canon_la-canon-s.Tpo $(DEPDIR)/libsane_canon_la-canon-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon-s.c' object='libsane_canon_la-canon-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_canon_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_canon_la-canon-s.lo `test -f 'canon-s.c' || echo '$(srcdir)/'`canon-s.c libsane_canon630u_la-canon630u-s.lo: canon630u-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_canon630u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_canon630u_la-canon630u-s.lo -MD -MP -MF $(DEPDIR)/libsane_canon630u_la-canon630u-s.Tpo -c -o libsane_canon630u_la-canon630u-s.lo `test -f 'canon630u-s.c' || echo '$(srcdir)/'`canon630u-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_canon630u_la-canon630u-s.Tpo $(DEPDIR)/libsane_canon630u_la-canon630u-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon630u-s.c' object='libsane_canon630u_la-canon630u-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_canon630u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_canon630u_la-canon630u-s.lo `test -f 'canon630u-s.c' || echo '$(srcdir)/'`canon630u-s.c libsane_canon_dr_la-canon_dr-s.lo: canon_dr-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_canon_dr_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_canon_dr_la-canon_dr-s.lo -MD -MP -MF $(DEPDIR)/libsane_canon_dr_la-canon_dr-s.Tpo -c -o libsane_canon_dr_la-canon_dr-s.lo `test -f 'canon_dr-s.c' || echo '$(srcdir)/'`canon_dr-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_canon_dr_la-canon_dr-s.Tpo $(DEPDIR)/libsane_canon_dr_la-canon_dr-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon_dr-s.c' object='libsane_canon_dr_la-canon_dr-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_canon_dr_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_canon_dr_la-canon_dr-s.lo `test -f 'canon_dr-s.c' || echo '$(srcdir)/'`canon_dr-s.c libsane_canon_pp_la-canon_pp-s.lo: canon_pp-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_canon_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_canon_pp_la-canon_pp-s.lo -MD -MP -MF $(DEPDIR)/libsane_canon_pp_la-canon_pp-s.Tpo -c -o libsane_canon_pp_la-canon_pp-s.lo `test -f 'canon_pp-s.c' || echo '$(srcdir)/'`canon_pp-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_canon_pp_la-canon_pp-s.Tpo $(DEPDIR)/libsane_canon_pp_la-canon_pp-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='canon_pp-s.c' object='libsane_canon_pp_la-canon_pp-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_canon_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_canon_pp_la-canon_pp-s.lo `test -f 'canon_pp-s.c' || echo '$(srcdir)/'`canon_pp-s.c libsane_cardscan_la-cardscan-s.lo: cardscan-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_cardscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_cardscan_la-cardscan-s.lo -MD -MP -MF $(DEPDIR)/libsane_cardscan_la-cardscan-s.Tpo -c -o libsane_cardscan_la-cardscan-s.lo `test -f 'cardscan-s.c' || echo '$(srcdir)/'`cardscan-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_cardscan_la-cardscan-s.Tpo $(DEPDIR)/libsane_cardscan_la-cardscan-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cardscan-s.c' object='libsane_cardscan_la-cardscan-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_cardscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_cardscan_la-cardscan-s.lo `test -f 'cardscan-s.c' || echo '$(srcdir)/'`cardscan-s.c libsane_coolscan_la-coolscan-s.lo: coolscan-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_coolscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_coolscan_la-coolscan-s.lo -MD -MP -MF $(DEPDIR)/libsane_coolscan_la-coolscan-s.Tpo -c -o libsane_coolscan_la-coolscan-s.lo `test -f 'coolscan-s.c' || echo '$(srcdir)/'`coolscan-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_coolscan_la-coolscan-s.Tpo $(DEPDIR)/libsane_coolscan_la-coolscan-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='coolscan-s.c' object='libsane_coolscan_la-coolscan-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_coolscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_coolscan_la-coolscan-s.lo `test -f 'coolscan-s.c' || echo '$(srcdir)/'`coolscan-s.c libsane_coolscan2_la-coolscan2-s.lo: coolscan2-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_coolscan2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_coolscan2_la-coolscan2-s.lo -MD -MP -MF $(DEPDIR)/libsane_coolscan2_la-coolscan2-s.Tpo -c -o libsane_coolscan2_la-coolscan2-s.lo `test -f 'coolscan2-s.c' || echo '$(srcdir)/'`coolscan2-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_coolscan2_la-coolscan2-s.Tpo $(DEPDIR)/libsane_coolscan2_la-coolscan2-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='coolscan2-s.c' object='libsane_coolscan2_la-coolscan2-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_coolscan2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_coolscan2_la-coolscan2-s.lo `test -f 'coolscan2-s.c' || echo '$(srcdir)/'`coolscan2-s.c libsane_coolscan3_la-coolscan3-s.lo: coolscan3-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_coolscan3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_coolscan3_la-coolscan3-s.lo -MD -MP -MF $(DEPDIR)/libsane_coolscan3_la-coolscan3-s.Tpo -c -o libsane_coolscan3_la-coolscan3-s.lo `test -f 'coolscan3-s.c' || echo '$(srcdir)/'`coolscan3-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_coolscan3_la-coolscan3-s.Tpo $(DEPDIR)/libsane_coolscan3_la-coolscan3-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='coolscan3-s.c' object='libsane_coolscan3_la-coolscan3-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_coolscan3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_coolscan3_la-coolscan3-s.lo `test -f 'coolscan3-s.c' || echo '$(srcdir)/'`coolscan3-s.c libsane_dc210_la-dc210-s.lo: dc210-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dc210_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_dc210_la-dc210-s.lo -MD -MP -MF $(DEPDIR)/libsane_dc210_la-dc210-s.Tpo -c -o libsane_dc210_la-dc210-s.lo `test -f 'dc210-s.c' || echo '$(srcdir)/'`dc210-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_dc210_la-dc210-s.Tpo $(DEPDIR)/libsane_dc210_la-dc210-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dc210-s.c' object='libsane_dc210_la-dc210-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dc210_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_dc210_la-dc210-s.lo `test -f 'dc210-s.c' || echo '$(srcdir)/'`dc210-s.c libsane_dc240_la-dc240-s.lo: dc240-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dc240_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_dc240_la-dc240-s.lo -MD -MP -MF $(DEPDIR)/libsane_dc240_la-dc240-s.Tpo -c -o libsane_dc240_la-dc240-s.lo `test -f 'dc240-s.c' || echo '$(srcdir)/'`dc240-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_dc240_la-dc240-s.Tpo $(DEPDIR)/libsane_dc240_la-dc240-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dc240-s.c' object='libsane_dc240_la-dc240-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dc240_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_dc240_la-dc240-s.lo `test -f 'dc240-s.c' || echo '$(srcdir)/'`dc240-s.c libsane_dc25_la-dc25-s.lo: dc25-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dc25_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_dc25_la-dc25-s.lo -MD -MP -MF $(DEPDIR)/libsane_dc25_la-dc25-s.Tpo -c -o libsane_dc25_la-dc25-s.lo `test -f 'dc25-s.c' || echo '$(srcdir)/'`dc25-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_dc25_la-dc25-s.Tpo $(DEPDIR)/libsane_dc25_la-dc25-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dc25-s.c' object='libsane_dc25_la-dc25-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dc25_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_dc25_la-dc25-s.lo `test -f 'dc25-s.c' || echo '$(srcdir)/'`dc25-s.c libsane_dell1600n_net_la-dell1600n_net-s.lo: dell1600n_net-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dell1600n_net_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_dell1600n_net_la-dell1600n_net-s.lo -MD -MP -MF $(DEPDIR)/libsane_dell1600n_net_la-dell1600n_net-s.Tpo -c -o libsane_dell1600n_net_la-dell1600n_net-s.lo `test -f 'dell1600n_net-s.c' || echo '$(srcdir)/'`dell1600n_net-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_dell1600n_net_la-dell1600n_net-s.Tpo $(DEPDIR)/libsane_dell1600n_net_la-dell1600n_net-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dell1600n_net-s.c' object='libsane_dell1600n_net_la-dell1600n_net-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dell1600n_net_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_dell1600n_net_la-dell1600n_net-s.lo `test -f 'dell1600n_net-s.c' || echo '$(srcdir)/'`dell1600n_net-s.c libsane_dll_la-dll-s.lo: dll-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dll_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_dll_la-dll-s.lo -MD -MP -MF $(DEPDIR)/libsane_dll_la-dll-s.Tpo -c -o libsane_dll_la-dll-s.lo `test -f 'dll-s.c' || echo '$(srcdir)/'`dll-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_dll_la-dll-s.Tpo $(DEPDIR)/libsane_dll_la-dll-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dll-s.c' object='libsane_dll_la-dll-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dll_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_dll_la-dll-s.lo `test -f 'dll-s.c' || echo '$(srcdir)/'`dll-s.c libsane_dmc_la-dmc-s.lo: dmc-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dmc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_dmc_la-dmc-s.lo -MD -MP -MF $(DEPDIR)/libsane_dmc_la-dmc-s.Tpo -c -o libsane_dmc_la-dmc-s.lo `test -f 'dmc-s.c' || echo '$(srcdir)/'`dmc-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_dmc_la-dmc-s.Tpo $(DEPDIR)/libsane_dmc_la-dmc-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dmc-s.c' object='libsane_dmc_la-dmc-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_dmc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_dmc_la-dmc-s.lo `test -f 'dmc-s.c' || echo '$(srcdir)/'`dmc-s.c libsane_epjitsu_la-epjitsu-s.lo: epjitsu-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epjitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_epjitsu_la-epjitsu-s.lo -MD -MP -MF $(DEPDIR)/libsane_epjitsu_la-epjitsu-s.Tpo -c -o libsane_epjitsu_la-epjitsu-s.lo `test -f 'epjitsu-s.c' || echo '$(srcdir)/'`epjitsu-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_epjitsu_la-epjitsu-s.Tpo $(DEPDIR)/libsane_epjitsu_la-epjitsu-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epjitsu-s.c' object='libsane_epjitsu_la-epjitsu-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epjitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_epjitsu_la-epjitsu-s.lo `test -f 'epjitsu-s.c' || echo '$(srcdir)/'`epjitsu-s.c libsane_epson_la-epson-s.lo: epson-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epson_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_epson_la-epson-s.lo -MD -MP -MF $(DEPDIR)/libsane_epson_la-epson-s.Tpo -c -o libsane_epson_la-epson-s.lo `test -f 'epson-s.c' || echo '$(srcdir)/'`epson-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_epson_la-epson-s.Tpo $(DEPDIR)/libsane_epson_la-epson-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson-s.c' object='libsane_epson_la-epson-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epson_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_epson_la-epson-s.lo `test -f 'epson-s.c' || echo '$(srcdir)/'`epson-s.c libsane_epson2_la-epson2-s.lo: epson2-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_epson2_la-epson2-s.lo -MD -MP -MF $(DEPDIR)/libsane_epson2_la-epson2-s.Tpo -c -o libsane_epson2_la-epson2-s.lo `test -f 'epson2-s.c' || echo '$(srcdir)/'`epson2-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_epson2_la-epson2-s.Tpo $(DEPDIR)/libsane_epson2_la-epson2-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epson2-s.c' object='libsane_epson2_la-epson2-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epson2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_epson2_la-epson2-s.lo `test -f 'epson2-s.c' || echo '$(srcdir)/'`epson2-s.c libsane_epsonds_la-epsonds-s.lo: epsonds-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_epsonds_la-epsonds-s.lo -MD -MP -MF $(DEPDIR)/libsane_epsonds_la-epsonds-s.Tpo -c -o libsane_epsonds_la-epsonds-s.lo `test -f 'epsonds-s.c' || echo '$(srcdir)/'`epsonds-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_epsonds_la-epsonds-s.Tpo $(DEPDIR)/libsane_epsonds_la-epsonds-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epsonds-s.c' object='libsane_epsonds_la-epsonds-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_epsonds_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_epsonds_la-epsonds-s.lo `test -f 'epsonds-s.c' || echo '$(srcdir)/'`epsonds-s.c libsane_fujitsu_la-fujitsu-s.lo: fujitsu-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_fujitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_fujitsu_la-fujitsu-s.lo -MD -MP -MF $(DEPDIR)/libsane_fujitsu_la-fujitsu-s.Tpo -c -o libsane_fujitsu_la-fujitsu-s.lo `test -f 'fujitsu-s.c' || echo '$(srcdir)/'`fujitsu-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_fujitsu_la-fujitsu-s.Tpo $(DEPDIR)/libsane_fujitsu_la-fujitsu-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fujitsu-s.c' object='libsane_fujitsu_la-fujitsu-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_fujitsu_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_fujitsu_la-fujitsu-s.lo `test -f 'fujitsu-s.c' || echo '$(srcdir)/'`fujitsu-s.c libsane_genesys_la-genesys-s.lo: genesys-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_genesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_genesys_la-genesys-s.lo -MD -MP -MF $(DEPDIR)/libsane_genesys_la-genesys-s.Tpo -c -o libsane_genesys_la-genesys-s.lo `test -f 'genesys-s.c' || echo '$(srcdir)/'`genesys-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_genesys_la-genesys-s.Tpo $(DEPDIR)/libsane_genesys_la-genesys-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='genesys-s.c' object='libsane_genesys_la-genesys-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_genesys_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_genesys_la-genesys-s.lo `test -f 'genesys-s.c' || echo '$(srcdir)/'`genesys-s.c libsane_gphoto2_la-gphoto2-s.lo: gphoto2-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_gphoto2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_gphoto2_la-gphoto2-s.lo -MD -MP -MF $(DEPDIR)/libsane_gphoto2_la-gphoto2-s.Tpo -c -o libsane_gphoto2_la-gphoto2-s.lo `test -f 'gphoto2-s.c' || echo '$(srcdir)/'`gphoto2-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_gphoto2_la-gphoto2-s.Tpo $(DEPDIR)/libsane_gphoto2_la-gphoto2-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gphoto2-s.c' object='libsane_gphoto2_la-gphoto2-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_gphoto2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_gphoto2_la-gphoto2-s.lo `test -f 'gphoto2-s.c' || echo '$(srcdir)/'`gphoto2-s.c libsane_gt68xx_la-gt68xx-s.lo: gt68xx-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_gt68xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_gt68xx_la-gt68xx-s.lo -MD -MP -MF $(DEPDIR)/libsane_gt68xx_la-gt68xx-s.Tpo -c -o libsane_gt68xx_la-gt68xx-s.lo `test -f 'gt68xx-s.c' || echo '$(srcdir)/'`gt68xx-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_gt68xx_la-gt68xx-s.Tpo $(DEPDIR)/libsane_gt68xx_la-gt68xx-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gt68xx-s.c' object='libsane_gt68xx_la-gt68xx-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_gt68xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_gt68xx_la-gt68xx-s.lo `test -f 'gt68xx-s.c' || echo '$(srcdir)/'`gt68xx-s.c libsane_hp_la-hp-s.lo: hp-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hp_la-hp-s.lo -MD -MP -MF $(DEPDIR)/libsane_hp_la-hp-s.Tpo -c -o libsane_hp_la-hp-s.lo `test -f 'hp-s.c' || echo '$(srcdir)/'`hp-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hp_la-hp-s.Tpo $(DEPDIR)/libsane_hp_la-hp-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp-s.c' object='libsane_hp_la-hp-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hp_la-hp-s.lo `test -f 'hp-s.c' || echo '$(srcdir)/'`hp-s.c libsane_hp3500_la-hp3500-s.lo: hp3500-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp3500_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hp3500_la-hp3500-s.lo -MD -MP -MF $(DEPDIR)/libsane_hp3500_la-hp3500-s.Tpo -c -o libsane_hp3500_la-hp3500-s.lo `test -f 'hp3500-s.c' || echo '$(srcdir)/'`hp3500-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hp3500_la-hp3500-s.Tpo $(DEPDIR)/libsane_hp3500_la-hp3500-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp3500-s.c' object='libsane_hp3500_la-hp3500-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp3500_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hp3500_la-hp3500-s.lo `test -f 'hp3500-s.c' || echo '$(srcdir)/'`hp3500-s.c libsane_hp3900_la-hp3900-s.lo: hp3900-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp3900_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hp3900_la-hp3900-s.lo -MD -MP -MF $(DEPDIR)/libsane_hp3900_la-hp3900-s.Tpo -c -o libsane_hp3900_la-hp3900-s.lo `test -f 'hp3900-s.c' || echo '$(srcdir)/'`hp3900-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hp3900_la-hp3900-s.Tpo $(DEPDIR)/libsane_hp3900_la-hp3900-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp3900-s.c' object='libsane_hp3900_la-hp3900-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp3900_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hp3900_la-hp3900-s.lo `test -f 'hp3900-s.c' || echo '$(srcdir)/'`hp3900-s.c libsane_hp4200_la-hp4200-s.lo: hp4200-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp4200_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hp4200_la-hp4200-s.lo -MD -MP -MF $(DEPDIR)/libsane_hp4200_la-hp4200-s.Tpo -c -o libsane_hp4200_la-hp4200-s.lo `test -f 'hp4200-s.c' || echo '$(srcdir)/'`hp4200-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hp4200_la-hp4200-s.Tpo $(DEPDIR)/libsane_hp4200_la-hp4200-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp4200-s.c' object='libsane_hp4200_la-hp4200-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp4200_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hp4200_la-hp4200-s.lo `test -f 'hp4200-s.c' || echo '$(srcdir)/'`hp4200-s.c libsane_hp5400_la-hp5400-s.lo: hp5400-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp5400_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hp5400_la-hp5400-s.lo -MD -MP -MF $(DEPDIR)/libsane_hp5400_la-hp5400-s.Tpo -c -o libsane_hp5400_la-hp5400-s.lo `test -f 'hp5400-s.c' || echo '$(srcdir)/'`hp5400-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hp5400_la-hp5400-s.Tpo $(DEPDIR)/libsane_hp5400_la-hp5400-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp5400-s.c' object='libsane_hp5400_la-hp5400-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp5400_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hp5400_la-hp5400-s.lo `test -f 'hp5400-s.c' || echo '$(srcdir)/'`hp5400-s.c libsane_hp5590_la-hp5590-s.lo: hp5590-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp5590_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hp5590_la-hp5590-s.lo -MD -MP -MF $(DEPDIR)/libsane_hp5590_la-hp5590-s.Tpo -c -o libsane_hp5590_la-hp5590-s.lo `test -f 'hp5590-s.c' || echo '$(srcdir)/'`hp5590-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hp5590_la-hp5590-s.Tpo $(DEPDIR)/libsane_hp5590_la-hp5590-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hp5590-s.c' object='libsane_hp5590_la-hp5590-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hp5590_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hp5590_la-hp5590-s.lo `test -f 'hp5590-s.c' || echo '$(srcdir)/'`hp5590-s.c libsane_hpljm1005_la-hpljm1005-s.lo: hpljm1005-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hpljm1005_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hpljm1005_la-hpljm1005-s.lo -MD -MP -MF $(DEPDIR)/libsane_hpljm1005_la-hpljm1005-s.Tpo -c -o libsane_hpljm1005_la-hpljm1005-s.lo `test -f 'hpljm1005-s.c' || echo '$(srcdir)/'`hpljm1005-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hpljm1005_la-hpljm1005-s.Tpo $(DEPDIR)/libsane_hpljm1005_la-hpljm1005-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hpljm1005-s.c' object='libsane_hpljm1005_la-hpljm1005-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hpljm1005_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hpljm1005_la-hpljm1005-s.lo `test -f 'hpljm1005-s.c' || echo '$(srcdir)/'`hpljm1005-s.c libsane_hpsj5s_la-hpsj5s-s.lo: hpsj5s-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hpsj5s_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hpsj5s_la-hpsj5s-s.lo -MD -MP -MF $(DEPDIR)/libsane_hpsj5s_la-hpsj5s-s.Tpo -c -o libsane_hpsj5s_la-hpsj5s-s.lo `test -f 'hpsj5s-s.c' || echo '$(srcdir)/'`hpsj5s-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hpsj5s_la-hpsj5s-s.Tpo $(DEPDIR)/libsane_hpsj5s_la-hpsj5s-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hpsj5s-s.c' object='libsane_hpsj5s_la-hpsj5s-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hpsj5s_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hpsj5s_la-hpsj5s-s.lo `test -f 'hpsj5s-s.c' || echo '$(srcdir)/'`hpsj5s-s.c libsane_hs2p_la-hs2p-s.lo: hs2p-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hs2p_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_hs2p_la-hs2p-s.lo -MD -MP -MF $(DEPDIR)/libsane_hs2p_la-hs2p-s.Tpo -c -o libsane_hs2p_la-hs2p-s.lo `test -f 'hs2p-s.c' || echo '$(srcdir)/'`hs2p-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_hs2p_la-hs2p-s.Tpo $(DEPDIR)/libsane_hs2p_la-hs2p-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hs2p-s.c' object='libsane_hs2p_la-hs2p-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_hs2p_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_hs2p_la-hs2p-s.lo `test -f 'hs2p-s.c' || echo '$(srcdir)/'`hs2p-s.c libsane_ibm_la-ibm-s.lo: ibm-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_ibm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_ibm_la-ibm-s.lo -MD -MP -MF $(DEPDIR)/libsane_ibm_la-ibm-s.Tpo -c -o libsane_ibm_la-ibm-s.lo `test -f 'ibm-s.c' || echo '$(srcdir)/'`ibm-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_ibm_la-ibm-s.Tpo $(DEPDIR)/libsane_ibm_la-ibm-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ibm-s.c' object='libsane_ibm_la-ibm-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_ibm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_ibm_la-ibm-s.lo `test -f 'ibm-s.c' || echo '$(srcdir)/'`ibm-s.c libsane_kodak_la-kodak-s.lo: kodak-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kodak_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_kodak_la-kodak-s.lo -MD -MP -MF $(DEPDIR)/libsane_kodak_la-kodak-s.Tpo -c -o libsane_kodak_la-kodak-s.lo `test -f 'kodak-s.c' || echo '$(srcdir)/'`kodak-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_kodak_la-kodak-s.Tpo $(DEPDIR)/libsane_kodak_la-kodak-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kodak-s.c' object='libsane_kodak_la-kodak-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kodak_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_kodak_la-kodak-s.lo `test -f 'kodak-s.c' || echo '$(srcdir)/'`kodak-s.c libsane_kodakaio_la-kodakaio-s.lo: kodakaio-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kodakaio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_kodakaio_la-kodakaio-s.lo -MD -MP -MF $(DEPDIR)/libsane_kodakaio_la-kodakaio-s.Tpo -c -o libsane_kodakaio_la-kodakaio-s.lo `test -f 'kodakaio-s.c' || echo '$(srcdir)/'`kodakaio-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_kodakaio_la-kodakaio-s.Tpo $(DEPDIR)/libsane_kodakaio_la-kodakaio-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kodakaio-s.c' object='libsane_kodakaio_la-kodakaio-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kodakaio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_kodakaio_la-kodakaio-s.lo `test -f 'kodakaio-s.c' || echo '$(srcdir)/'`kodakaio-s.c libsane_kvs1025_la-kvs1025-s.lo: kvs1025-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_kvs1025_la-kvs1025-s.lo -MD -MP -MF $(DEPDIR)/libsane_kvs1025_la-kvs1025-s.Tpo -c -o libsane_kvs1025_la-kvs1025-s.lo `test -f 'kvs1025-s.c' || echo '$(srcdir)/'`kvs1025-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_kvs1025_la-kvs1025-s.Tpo $(DEPDIR)/libsane_kvs1025_la-kvs1025-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs1025-s.c' object='libsane_kvs1025_la-kvs1025-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kvs1025_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_kvs1025_la-kvs1025-s.lo `test -f 'kvs1025-s.c' || echo '$(srcdir)/'`kvs1025-s.c libsane_kvs20xx_la-kvs20xx-s.lo: kvs20xx-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kvs20xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_kvs20xx_la-kvs20xx-s.lo -MD -MP -MF $(DEPDIR)/libsane_kvs20xx_la-kvs20xx-s.Tpo -c -o libsane_kvs20xx_la-kvs20xx-s.lo `test -f 'kvs20xx-s.c' || echo '$(srcdir)/'`kvs20xx-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_kvs20xx_la-kvs20xx-s.Tpo $(DEPDIR)/libsane_kvs20xx_la-kvs20xx-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs20xx-s.c' object='libsane_kvs20xx_la-kvs20xx-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kvs20xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_kvs20xx_la-kvs20xx-s.lo `test -f 'kvs20xx-s.c' || echo '$(srcdir)/'`kvs20xx-s.c libsane_kvs40xx_la-kvs40xx-s.lo: kvs40xx-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kvs40xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_kvs40xx_la-kvs40xx-s.lo -MD -MP -MF $(DEPDIR)/libsane_kvs40xx_la-kvs40xx-s.Tpo -c -o libsane_kvs40xx_la-kvs40xx-s.lo `test -f 'kvs40xx-s.c' || echo '$(srcdir)/'`kvs40xx-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_kvs40xx_la-kvs40xx-s.Tpo $(DEPDIR)/libsane_kvs40xx_la-kvs40xx-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kvs40xx-s.c' object='libsane_kvs40xx_la-kvs40xx-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_kvs40xx_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_kvs40xx_la-kvs40xx-s.lo `test -f 'kvs40xx-s.c' || echo '$(srcdir)/'`kvs40xx-s.c libsane_leo_la-leo-s.lo: leo-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_leo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_leo_la-leo-s.lo -MD -MP -MF $(DEPDIR)/libsane_leo_la-leo-s.Tpo -c -o libsane_leo_la-leo-s.lo `test -f 'leo-s.c' || echo '$(srcdir)/'`leo-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_leo_la-leo-s.Tpo $(DEPDIR)/libsane_leo_la-leo-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='leo-s.c' object='libsane_leo_la-leo-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_leo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_leo_la-leo-s.lo `test -f 'leo-s.c' || echo '$(srcdir)/'`leo-s.c libsane_lexmark_la-lexmark-s.lo: lexmark-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_lexmark_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_lexmark_la-lexmark-s.lo -MD -MP -MF $(DEPDIR)/libsane_lexmark_la-lexmark-s.Tpo -c -o libsane_lexmark_la-lexmark-s.lo `test -f 'lexmark-s.c' || echo '$(srcdir)/'`lexmark-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_lexmark_la-lexmark-s.Tpo $(DEPDIR)/libsane_lexmark_la-lexmark-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lexmark-s.c' object='libsane_lexmark_la-lexmark-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_lexmark_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_lexmark_la-lexmark-s.lo `test -f 'lexmark-s.c' || echo '$(srcdir)/'`lexmark-s.c libsane_ma1509_la-ma1509-s.lo: ma1509-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_ma1509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_ma1509_la-ma1509-s.lo -MD -MP -MF $(DEPDIR)/libsane_ma1509_la-ma1509-s.Tpo -c -o libsane_ma1509_la-ma1509-s.lo `test -f 'ma1509-s.c' || echo '$(srcdir)/'`ma1509-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_ma1509_la-ma1509-s.Tpo $(DEPDIR)/libsane_ma1509_la-ma1509-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ma1509-s.c' object='libsane_ma1509_la-ma1509-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_ma1509_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_ma1509_la-ma1509-s.lo `test -f 'ma1509-s.c' || echo '$(srcdir)/'`ma1509-s.c libsane_magicolor_la-magicolor-s.lo: magicolor-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_magicolor_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_magicolor_la-magicolor-s.lo -MD -MP -MF $(DEPDIR)/libsane_magicolor_la-magicolor-s.Tpo -c -o libsane_magicolor_la-magicolor-s.lo `test -f 'magicolor-s.c' || echo '$(srcdir)/'`magicolor-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_magicolor_la-magicolor-s.Tpo $(DEPDIR)/libsane_magicolor_la-magicolor-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='magicolor-s.c' object='libsane_magicolor_la-magicolor-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_magicolor_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_magicolor_la-magicolor-s.lo `test -f 'magicolor-s.c' || echo '$(srcdir)/'`magicolor-s.c libsane_matsushita_la-matsushita-s.lo: matsushita-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_matsushita_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_matsushita_la-matsushita-s.lo -MD -MP -MF $(DEPDIR)/libsane_matsushita_la-matsushita-s.Tpo -c -o libsane_matsushita_la-matsushita-s.lo `test -f 'matsushita-s.c' || echo '$(srcdir)/'`matsushita-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_matsushita_la-matsushita-s.Tpo $(DEPDIR)/libsane_matsushita_la-matsushita-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='matsushita-s.c' object='libsane_matsushita_la-matsushita-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_matsushita_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_matsushita_la-matsushita-s.lo `test -f 'matsushita-s.c' || echo '$(srcdir)/'`matsushita-s.c libsane_microtek_la-microtek-s.lo: microtek-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_microtek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_microtek_la-microtek-s.lo -MD -MP -MF $(DEPDIR)/libsane_microtek_la-microtek-s.Tpo -c -o libsane_microtek_la-microtek-s.lo `test -f 'microtek-s.c' || echo '$(srcdir)/'`microtek-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_microtek_la-microtek-s.Tpo $(DEPDIR)/libsane_microtek_la-microtek-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='microtek-s.c' object='libsane_microtek_la-microtek-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_microtek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_microtek_la-microtek-s.lo `test -f 'microtek-s.c' || echo '$(srcdir)/'`microtek-s.c libsane_microtek2_la-microtek2-s.lo: microtek2-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_microtek2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_microtek2_la-microtek2-s.lo -MD -MP -MF $(DEPDIR)/libsane_microtek2_la-microtek2-s.Tpo -c -o libsane_microtek2_la-microtek2-s.lo `test -f 'microtek2-s.c' || echo '$(srcdir)/'`microtek2-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_microtek2_la-microtek2-s.Tpo $(DEPDIR)/libsane_microtek2_la-microtek2-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='microtek2-s.c' object='libsane_microtek2_la-microtek2-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_microtek2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_microtek2_la-microtek2-s.lo `test -f 'microtek2-s.c' || echo '$(srcdir)/'`microtek2-s.c libsane_mustek_la-mustek-s.lo: mustek-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_mustek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_mustek_la-mustek-s.lo -MD -MP -MF $(DEPDIR)/libsane_mustek_la-mustek-s.Tpo -c -o libsane_mustek_la-mustek-s.lo `test -f 'mustek-s.c' || echo '$(srcdir)/'`mustek-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_mustek_la-mustek-s.Tpo $(DEPDIR)/libsane_mustek_la-mustek-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mustek-s.c' object='libsane_mustek_la-mustek-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_mustek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_mustek_la-mustek-s.lo `test -f 'mustek-s.c' || echo '$(srcdir)/'`mustek-s.c libsane_mustek_pp_la-mustek_pp-s.lo: mustek_pp-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_mustek_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_mustek_pp_la-mustek_pp-s.lo -MD -MP -MF $(DEPDIR)/libsane_mustek_pp_la-mustek_pp-s.Tpo -c -o libsane_mustek_pp_la-mustek_pp-s.lo `test -f 'mustek_pp-s.c' || echo '$(srcdir)/'`mustek_pp-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_mustek_pp_la-mustek_pp-s.Tpo $(DEPDIR)/libsane_mustek_pp_la-mustek_pp-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mustek_pp-s.c' object='libsane_mustek_pp_la-mustek_pp-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_mustek_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_mustek_pp_la-mustek_pp-s.lo `test -f 'mustek_pp-s.c' || echo '$(srcdir)/'`mustek_pp-s.c libsane_mustek_usb_la-mustek_usb-s.lo: mustek_usb-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_mustek_usb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_mustek_usb_la-mustek_usb-s.lo -MD -MP -MF $(DEPDIR)/libsane_mustek_usb_la-mustek_usb-s.Tpo -c -o libsane_mustek_usb_la-mustek_usb-s.lo `test -f 'mustek_usb-s.c' || echo '$(srcdir)/'`mustek_usb-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_mustek_usb_la-mustek_usb-s.Tpo $(DEPDIR)/libsane_mustek_usb_la-mustek_usb-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mustek_usb-s.c' object='libsane_mustek_usb_la-mustek_usb-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_mustek_usb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_mustek_usb_la-mustek_usb-s.lo `test -f 'mustek_usb-s.c' || echo '$(srcdir)/'`mustek_usb-s.c libsane_mustek_usb2_la-mustek_usb2-s.lo: mustek_usb2-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_mustek_usb2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_mustek_usb2_la-mustek_usb2-s.lo -MD -MP -MF $(DEPDIR)/libsane_mustek_usb2_la-mustek_usb2-s.Tpo -c -o libsane_mustek_usb2_la-mustek_usb2-s.lo `test -f 'mustek_usb2-s.c' || echo '$(srcdir)/'`mustek_usb2-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_mustek_usb2_la-mustek_usb2-s.Tpo $(DEPDIR)/libsane_mustek_usb2_la-mustek_usb2-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mustek_usb2-s.c' object='libsane_mustek_usb2_la-mustek_usb2-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_mustek_usb2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_mustek_usb2_la-mustek_usb2-s.lo `test -f 'mustek_usb2-s.c' || echo '$(srcdir)/'`mustek_usb2-s.c libsane_nec_la-nec-s.lo: nec-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_nec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_nec_la-nec-s.lo -MD -MP -MF $(DEPDIR)/libsane_nec_la-nec-s.Tpo -c -o libsane_nec_la-nec-s.lo `test -f 'nec-s.c' || echo '$(srcdir)/'`nec-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_nec_la-nec-s.Tpo $(DEPDIR)/libsane_nec_la-nec-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nec-s.c' object='libsane_nec_la-nec-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_nec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_nec_la-nec-s.lo `test -f 'nec-s.c' || echo '$(srcdir)/'`nec-s.c libsane_net_la-net-s.lo: net-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_net_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_net_la-net-s.lo -MD -MP -MF $(DEPDIR)/libsane_net_la-net-s.Tpo -c -o libsane_net_la-net-s.lo `test -f 'net-s.c' || echo '$(srcdir)/'`net-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_net_la-net-s.Tpo $(DEPDIR)/libsane_net_la-net-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='net-s.c' object='libsane_net_la-net-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_net_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_net_la-net-s.lo `test -f 'net-s.c' || echo '$(srcdir)/'`net-s.c libsane_niash_la-niash-s.lo: niash-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_niash_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_niash_la-niash-s.lo -MD -MP -MF $(DEPDIR)/libsane_niash_la-niash-s.Tpo -c -o libsane_niash_la-niash-s.lo `test -f 'niash-s.c' || echo '$(srcdir)/'`niash-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_niash_la-niash-s.Tpo $(DEPDIR)/libsane_niash_la-niash-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='niash-s.c' object='libsane_niash_la-niash-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_niash_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_niash_la-niash-s.lo `test -f 'niash-s.c' || echo '$(srcdir)/'`niash-s.c libsane_p5_la-p5-s.lo: p5-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_p5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_p5_la-p5-s.lo -MD -MP -MF $(DEPDIR)/libsane_p5_la-p5-s.Tpo -c -o libsane_p5_la-p5-s.lo `test -f 'p5-s.c' || echo '$(srcdir)/'`p5-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_p5_la-p5-s.Tpo $(DEPDIR)/libsane_p5_la-p5-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='p5-s.c' object='libsane_p5_la-p5-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_p5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_p5_la-p5-s.lo `test -f 'p5-s.c' || echo '$(srcdir)/'`p5-s.c libsane_pie_la-pie-s.lo: pie-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pie_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_pie_la-pie-s.lo -MD -MP -MF $(DEPDIR)/libsane_pie_la-pie-s.Tpo -c -o libsane_pie_la-pie-s.lo `test -f 'pie-s.c' || echo '$(srcdir)/'`pie-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_pie_la-pie-s.Tpo $(DEPDIR)/libsane_pie_la-pie-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pie-s.c' object='libsane_pie_la-pie-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pie_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_pie_la-pie-s.lo `test -f 'pie-s.c' || echo '$(srcdir)/'`pie-s.c libsane_pieusb_la-pieusb-s.lo: pieusb-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_pieusb_la-pieusb-s.lo -MD -MP -MF $(DEPDIR)/libsane_pieusb_la-pieusb-s.Tpo -c -o libsane_pieusb_la-pieusb-s.lo `test -f 'pieusb-s.c' || echo '$(srcdir)/'`pieusb-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_pieusb_la-pieusb-s.Tpo $(DEPDIR)/libsane_pieusb_la-pieusb-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pieusb-s.c' object='libsane_pieusb_la-pieusb-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pieusb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_pieusb_la-pieusb-s.lo `test -f 'pieusb-s.c' || echo '$(srcdir)/'`pieusb-s.c libsane_pint_la-pint-s.lo: pint-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pint_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_pint_la-pint-s.lo -MD -MP -MF $(DEPDIR)/libsane_pint_la-pint-s.Tpo -c -o libsane_pint_la-pint-s.lo `test -f 'pint-s.c' || echo '$(srcdir)/'`pint-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_pint_la-pint-s.Tpo $(DEPDIR)/libsane_pint_la-pint-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pint-s.c' object='libsane_pint_la-pint-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pint_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_pint_la-pint-s.lo `test -f 'pint-s.c' || echo '$(srcdir)/'`pint-s.c libsane_pixma_la-pixma-s.lo: pixma-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_pixma_la-pixma-s.lo -MD -MP -MF $(DEPDIR)/libsane_pixma_la-pixma-s.Tpo -c -o libsane_pixma_la-pixma-s.lo `test -f 'pixma-s.c' || echo '$(srcdir)/'`pixma-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_pixma_la-pixma-s.Tpo $(DEPDIR)/libsane_pixma_la-pixma-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pixma-s.c' object='libsane_pixma_la-pixma-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pixma_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_pixma_la-pixma-s.lo `test -f 'pixma-s.c' || echo '$(srcdir)/'`pixma-s.c libsane_plustek_la-plustek-s.lo: plustek-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_plustek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_plustek_la-plustek-s.lo -MD -MP -MF $(DEPDIR)/libsane_plustek_la-plustek-s.Tpo -c -o libsane_plustek_la-plustek-s.lo `test -f 'plustek-s.c' || echo '$(srcdir)/'`plustek-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_plustek_la-plustek-s.Tpo $(DEPDIR)/libsane_plustek_la-plustek-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plustek-s.c' object='libsane_plustek_la-plustek-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_plustek_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_plustek_la-plustek-s.lo `test -f 'plustek-s.c' || echo '$(srcdir)/'`plustek-s.c libsane_plustek_pp_la-plustek_pp-s.lo: plustek_pp-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_plustek_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_plustek_pp_la-plustek_pp-s.lo -MD -MP -MF $(DEPDIR)/libsane_plustek_pp_la-plustek_pp-s.Tpo -c -o libsane_plustek_pp_la-plustek_pp-s.lo `test -f 'plustek_pp-s.c' || echo '$(srcdir)/'`plustek_pp-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_plustek_pp_la-plustek_pp-s.Tpo $(DEPDIR)/libsane_plustek_pp_la-plustek_pp-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plustek_pp-s.c' object='libsane_plustek_pp_la-plustek_pp-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_plustek_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_plustek_pp_la-plustek_pp-s.lo `test -f 'plustek_pp-s.c' || echo '$(srcdir)/'`plustek_pp-s.c libsane_pnm_la-pnm-s.lo: pnm-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pnm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_pnm_la-pnm-s.lo -MD -MP -MF $(DEPDIR)/libsane_pnm_la-pnm-s.Tpo -c -o libsane_pnm_la-pnm-s.lo `test -f 'pnm-s.c' || echo '$(srcdir)/'`pnm-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_pnm_la-pnm-s.Tpo $(DEPDIR)/libsane_pnm_la-pnm-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pnm-s.c' object='libsane_pnm_la-pnm-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_pnm_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_pnm_la-pnm-s.lo `test -f 'pnm-s.c' || echo '$(srcdir)/'`pnm-s.c libsane_qcam_la-qcam-s.lo: qcam-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_qcam_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_qcam_la-qcam-s.lo -MD -MP -MF $(DEPDIR)/libsane_qcam_la-qcam-s.Tpo -c -o libsane_qcam_la-qcam-s.lo `test -f 'qcam-s.c' || echo '$(srcdir)/'`qcam-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_qcam_la-qcam-s.Tpo $(DEPDIR)/libsane_qcam_la-qcam-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='qcam-s.c' object='libsane_qcam_la-qcam-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_qcam_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_qcam_la-qcam-s.lo `test -f 'qcam-s.c' || echo '$(srcdir)/'`qcam-s.c libsane_ricoh_la-ricoh-s.lo: ricoh-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_ricoh_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_ricoh_la-ricoh-s.lo -MD -MP -MF $(DEPDIR)/libsane_ricoh_la-ricoh-s.Tpo -c -o libsane_ricoh_la-ricoh-s.lo `test -f 'ricoh-s.c' || echo '$(srcdir)/'`ricoh-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_ricoh_la-ricoh-s.Tpo $(DEPDIR)/libsane_ricoh_la-ricoh-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ricoh-s.c' object='libsane_ricoh_la-ricoh-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_ricoh_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_ricoh_la-ricoh-s.lo `test -f 'ricoh-s.c' || echo '$(srcdir)/'`ricoh-s.c libsane_rts8891_la-rts8891-s.lo: rts8891-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_rts8891_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_rts8891_la-rts8891-s.lo -MD -MP -MF $(DEPDIR)/libsane_rts8891_la-rts8891-s.Tpo -c -o libsane_rts8891_la-rts8891-s.lo `test -f 'rts8891-s.c' || echo '$(srcdir)/'`rts8891-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_rts8891_la-rts8891-s.Tpo $(DEPDIR)/libsane_rts8891_la-rts8891-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rts8891-s.c' object='libsane_rts8891_la-rts8891-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_rts8891_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_rts8891_la-rts8891-s.lo `test -f 'rts8891-s.c' || echo '$(srcdir)/'`rts8891-s.c libsane_s9036_la-s9036-s.lo: s9036-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_s9036_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_s9036_la-s9036-s.lo -MD -MP -MF $(DEPDIR)/libsane_s9036_la-s9036-s.Tpo -c -o libsane_s9036_la-s9036-s.lo `test -f 's9036-s.c' || echo '$(srcdir)/'`s9036-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_s9036_la-s9036-s.Tpo $(DEPDIR)/libsane_s9036_la-s9036-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='s9036-s.c' object='libsane_s9036_la-s9036-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_s9036_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_s9036_la-s9036-s.lo `test -f 's9036-s.c' || echo '$(srcdir)/'`s9036-s.c libsane_sceptre_la-sceptre-s.lo: sceptre-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sceptre_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_sceptre_la-sceptre-s.lo -MD -MP -MF $(DEPDIR)/libsane_sceptre_la-sceptre-s.Tpo -c -o libsane_sceptre_la-sceptre-s.lo `test -f 'sceptre-s.c' || echo '$(srcdir)/'`sceptre-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_sceptre_la-sceptre-s.Tpo $(DEPDIR)/libsane_sceptre_la-sceptre-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sceptre-s.c' object='libsane_sceptre_la-sceptre-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sceptre_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_sceptre_la-sceptre-s.lo `test -f 'sceptre-s.c' || echo '$(srcdir)/'`sceptre-s.c libsane_sharp_la-sharp-s.lo: sharp-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sharp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_sharp_la-sharp-s.lo -MD -MP -MF $(DEPDIR)/libsane_sharp_la-sharp-s.Tpo -c -o libsane_sharp_la-sharp-s.lo `test -f 'sharp-s.c' || echo '$(srcdir)/'`sharp-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_sharp_la-sharp-s.Tpo $(DEPDIR)/libsane_sharp_la-sharp-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sharp-s.c' object='libsane_sharp_la-sharp-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sharp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_sharp_la-sharp-s.lo `test -f 'sharp-s.c' || echo '$(srcdir)/'`sharp-s.c libsane_sm3600_la-sm3600-s.lo: sm3600-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sm3600_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_sm3600_la-sm3600-s.lo -MD -MP -MF $(DEPDIR)/libsane_sm3600_la-sm3600-s.Tpo -c -o libsane_sm3600_la-sm3600-s.lo `test -f 'sm3600-s.c' || echo '$(srcdir)/'`sm3600-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_sm3600_la-sm3600-s.Tpo $(DEPDIR)/libsane_sm3600_la-sm3600-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sm3600-s.c' object='libsane_sm3600_la-sm3600-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sm3600_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_sm3600_la-sm3600-s.lo `test -f 'sm3600-s.c' || echo '$(srcdir)/'`sm3600-s.c libsane_sm3840_la-sm3840-s.lo: sm3840-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sm3840_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_sm3840_la-sm3840-s.lo -MD -MP -MF $(DEPDIR)/libsane_sm3840_la-sm3840-s.Tpo -c -o libsane_sm3840_la-sm3840-s.lo `test -f 'sm3840-s.c' || echo '$(srcdir)/'`sm3840-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_sm3840_la-sm3840-s.Tpo $(DEPDIR)/libsane_sm3840_la-sm3840-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sm3840-s.c' object='libsane_sm3840_la-sm3840-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sm3840_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_sm3840_la-sm3840-s.lo `test -f 'sm3840-s.c' || echo '$(srcdir)/'`sm3840-s.c libsane_snapscan_la-snapscan-s.lo: snapscan-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_snapscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_snapscan_la-snapscan-s.lo -MD -MP -MF $(DEPDIR)/libsane_snapscan_la-snapscan-s.Tpo -c -o libsane_snapscan_la-snapscan-s.lo `test -f 'snapscan-s.c' || echo '$(srcdir)/'`snapscan-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_snapscan_la-snapscan-s.Tpo $(DEPDIR)/libsane_snapscan_la-snapscan-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='snapscan-s.c' object='libsane_snapscan_la-snapscan-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_snapscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_snapscan_la-snapscan-s.lo `test -f 'snapscan-s.c' || echo '$(srcdir)/'`snapscan-s.c libsane_sp15c_la-sp15c-s.lo: sp15c-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sp15c_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_sp15c_la-sp15c-s.lo -MD -MP -MF $(DEPDIR)/libsane_sp15c_la-sp15c-s.Tpo -c -o libsane_sp15c_la-sp15c-s.lo `test -f 'sp15c-s.c' || echo '$(srcdir)/'`sp15c-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_sp15c_la-sp15c-s.Tpo $(DEPDIR)/libsane_sp15c_la-sp15c-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sp15c-s.c' object='libsane_sp15c_la-sp15c-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_sp15c_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_sp15c_la-sp15c-s.lo `test -f 'sp15c-s.c' || echo '$(srcdir)/'`sp15c-s.c libsane_st400_la-st400-s.lo: st400-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_st400_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_st400_la-st400-s.lo -MD -MP -MF $(DEPDIR)/libsane_st400_la-st400-s.Tpo -c -o libsane_st400_la-st400-s.lo `test -f 'st400-s.c' || echo '$(srcdir)/'`st400-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_st400_la-st400-s.Tpo $(DEPDIR)/libsane_st400_la-st400-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='st400-s.c' object='libsane_st400_la-st400-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_st400_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_st400_la-st400-s.lo `test -f 'st400-s.c' || echo '$(srcdir)/'`st400-s.c libsane_stv680_la-stv680-s.lo: stv680-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_stv680_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_stv680_la-stv680-s.lo -MD -MP -MF $(DEPDIR)/libsane_stv680_la-stv680-s.Tpo -c -o libsane_stv680_la-stv680-s.lo `test -f 'stv680-s.c' || echo '$(srcdir)/'`stv680-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_stv680_la-stv680-s.Tpo $(DEPDIR)/libsane_stv680_la-stv680-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stv680-s.c' object='libsane_stv680_la-stv680-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_stv680_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_stv680_la-stv680-s.lo `test -f 'stv680-s.c' || echo '$(srcdir)/'`stv680-s.c libsane_tamarack_la-tamarack-s.lo: tamarack-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_tamarack_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_tamarack_la-tamarack-s.lo -MD -MP -MF $(DEPDIR)/libsane_tamarack_la-tamarack-s.Tpo -c -o libsane_tamarack_la-tamarack-s.lo `test -f 'tamarack-s.c' || echo '$(srcdir)/'`tamarack-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_tamarack_la-tamarack-s.Tpo $(DEPDIR)/libsane_tamarack_la-tamarack-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tamarack-s.c' object='libsane_tamarack_la-tamarack-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_tamarack_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_tamarack_la-tamarack-s.lo `test -f 'tamarack-s.c' || echo '$(srcdir)/'`tamarack-s.c libsane_teco1_la-teco1-s.lo: teco1-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_teco1_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_teco1_la-teco1-s.lo -MD -MP -MF $(DEPDIR)/libsane_teco1_la-teco1-s.Tpo -c -o libsane_teco1_la-teco1-s.lo `test -f 'teco1-s.c' || echo '$(srcdir)/'`teco1-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_teco1_la-teco1-s.Tpo $(DEPDIR)/libsane_teco1_la-teco1-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='teco1-s.c' object='libsane_teco1_la-teco1-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_teco1_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_teco1_la-teco1-s.lo `test -f 'teco1-s.c' || echo '$(srcdir)/'`teco1-s.c libsane_teco2_la-teco2-s.lo: teco2-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_teco2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_teco2_la-teco2-s.lo -MD -MP -MF $(DEPDIR)/libsane_teco2_la-teco2-s.Tpo -c -o libsane_teco2_la-teco2-s.lo `test -f 'teco2-s.c' || echo '$(srcdir)/'`teco2-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_teco2_la-teco2-s.Tpo $(DEPDIR)/libsane_teco2_la-teco2-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='teco2-s.c' object='libsane_teco2_la-teco2-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_teco2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_teco2_la-teco2-s.lo `test -f 'teco2-s.c' || echo '$(srcdir)/'`teco2-s.c libsane_teco3_la-teco3-s.lo: teco3-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_teco3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_teco3_la-teco3-s.lo -MD -MP -MF $(DEPDIR)/libsane_teco3_la-teco3-s.Tpo -c -o libsane_teco3_la-teco3-s.lo `test -f 'teco3-s.c' || echo '$(srcdir)/'`teco3-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_teco3_la-teco3-s.Tpo $(DEPDIR)/libsane_teco3_la-teco3-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='teco3-s.c' object='libsane_teco3_la-teco3-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_teco3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_teco3_la-teco3-s.lo `test -f 'teco3-s.c' || echo '$(srcdir)/'`teco3-s.c libsane_test_la-test-s.lo: test-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_test_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_test_la-test-s.lo -MD -MP -MF $(DEPDIR)/libsane_test_la-test-s.Tpo -c -o libsane_test_la-test-s.lo `test -f 'test-s.c' || echo '$(srcdir)/'`test-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_test_la-test-s.Tpo $(DEPDIR)/libsane_test_la-test-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-s.c' object='libsane_test_la-test-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_test_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_test_la-test-s.lo `test -f 'test-s.c' || echo '$(srcdir)/'`test-s.c libsane_u12_la-u12-s.lo: u12-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_u12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_u12_la-u12-s.lo -MD -MP -MF $(DEPDIR)/libsane_u12_la-u12-s.Tpo -c -o libsane_u12_la-u12-s.lo `test -f 'u12-s.c' || echo '$(srcdir)/'`u12-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_u12_la-u12-s.Tpo $(DEPDIR)/libsane_u12_la-u12-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='u12-s.c' object='libsane_u12_la-u12-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_u12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_u12_la-u12-s.lo `test -f 'u12-s.c' || echo '$(srcdir)/'`u12-s.c libsane_umax_la-umax-s.lo: umax-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_umax_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_umax_la-umax-s.lo -MD -MP -MF $(DEPDIR)/libsane_umax_la-umax-s.Tpo -c -o libsane_umax_la-umax-s.lo `test -f 'umax-s.c' || echo '$(srcdir)/'`umax-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_umax_la-umax-s.Tpo $(DEPDIR)/libsane_umax_la-umax-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='umax-s.c' object='libsane_umax_la-umax-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_umax_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_umax_la-umax-s.lo `test -f 'umax-s.c' || echo '$(srcdir)/'`umax-s.c libsane_umax1220u_la-umax1220u-s.lo: umax1220u-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_umax1220u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_umax1220u_la-umax1220u-s.lo -MD -MP -MF $(DEPDIR)/libsane_umax1220u_la-umax1220u-s.Tpo -c -o libsane_umax1220u_la-umax1220u-s.lo `test -f 'umax1220u-s.c' || echo '$(srcdir)/'`umax1220u-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_umax1220u_la-umax1220u-s.Tpo $(DEPDIR)/libsane_umax1220u_la-umax1220u-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='umax1220u-s.c' object='libsane_umax1220u_la-umax1220u-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_umax1220u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_umax1220u_la-umax1220u-s.lo `test -f 'umax1220u-s.c' || echo '$(srcdir)/'`umax1220u-s.c libsane_umax_pp_la-umax_pp-s.lo: umax_pp-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_umax_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_umax_pp_la-umax_pp-s.lo -MD -MP -MF $(DEPDIR)/libsane_umax_pp_la-umax_pp-s.Tpo -c -o libsane_umax_pp_la-umax_pp-s.lo `test -f 'umax_pp-s.c' || echo '$(srcdir)/'`umax_pp-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_umax_pp_la-umax_pp-s.Tpo $(DEPDIR)/libsane_umax_pp_la-umax_pp-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='umax_pp-s.c' object='libsane_umax_pp_la-umax_pp-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_umax_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_umax_pp_la-umax_pp-s.lo `test -f 'umax_pp-s.c' || echo '$(srcdir)/'`umax_pp-s.c libsane_v4l_la-v4l-s.lo: v4l-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_v4l_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_v4l_la-v4l-s.lo -MD -MP -MF $(DEPDIR)/libsane_v4l_la-v4l-s.Tpo -c -o libsane_v4l_la-v4l-s.lo `test -f 'v4l-s.c' || echo '$(srcdir)/'`v4l-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_v4l_la-v4l-s.Tpo $(DEPDIR)/libsane_v4l_la-v4l-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='v4l-s.c' object='libsane_v4l_la-v4l-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_v4l_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_v4l_la-v4l-s.lo `test -f 'v4l-s.c' || echo '$(srcdir)/'`v4l-s.c libsane_xerox_mfp_la-xerox_mfp-s.lo: xerox_mfp-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_xerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_xerox_mfp_la-xerox_mfp-s.lo -MD -MP -MF $(DEPDIR)/libsane_xerox_mfp_la-xerox_mfp-s.Tpo -c -o libsane_xerox_mfp_la-xerox_mfp-s.lo `test -f 'xerox_mfp-s.c' || echo '$(srcdir)/'`xerox_mfp-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_xerox_mfp_la-xerox_mfp-s.Tpo $(DEPDIR)/libsane_xerox_mfp_la-xerox_mfp-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xerox_mfp-s.c' object='libsane_xerox_mfp_la-xerox_mfp-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_xerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_xerox_mfp_la-xerox_mfp-s.lo `test -f 'xerox_mfp-s.c' || echo '$(srcdir)/'`xerox_mfp-s.c libsane_la-dll-s.lo: dll-s.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsane_la-dll-s.lo -MD -MP -MF $(DEPDIR)/libsane_la-dll-s.Tpo -c -o libsane_la-dll-s.lo `test -f 'dll-s.c' || echo '$(srcdir)/'`dll-s.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsane_la-dll-s.Tpo $(DEPDIR)/libsane_la-dll-s.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dll-s.c' object='libsane_la-dll-s.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsane_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsane_la-dll-s.lo `test -f 'dll-s.c' || echo '$(srcdir)/'`dll-s.c libsceptre_la-sceptre.lo: sceptre.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsceptre_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsceptre_la-sceptre.lo -MD -MP -MF $(DEPDIR)/libsceptre_la-sceptre.Tpo -c -o libsceptre_la-sceptre.lo `test -f 'sceptre.c' || echo '$(srcdir)/'`sceptre.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsceptre_la-sceptre.Tpo $(DEPDIR)/libsceptre_la-sceptre.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sceptre.c' object='libsceptre_la-sceptre.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsceptre_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsceptre_la-sceptre.lo `test -f 'sceptre.c' || echo '$(srcdir)/'`sceptre.c libsharp_la-sharp.lo: sharp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsharp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsharp_la-sharp.lo -MD -MP -MF $(DEPDIR)/libsharp_la-sharp.Tpo -c -o libsharp_la-sharp.lo `test -f 'sharp.c' || echo '$(srcdir)/'`sharp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsharp_la-sharp.Tpo $(DEPDIR)/libsharp_la-sharp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sharp.c' object='libsharp_la-sharp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsharp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsharp_la-sharp.lo `test -f 'sharp.c' || echo '$(srcdir)/'`sharp.c libsm3600_la-sm3600.lo: sm3600.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsm3600_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsm3600_la-sm3600.lo -MD -MP -MF $(DEPDIR)/libsm3600_la-sm3600.Tpo -c -o libsm3600_la-sm3600.lo `test -f 'sm3600.c' || echo '$(srcdir)/'`sm3600.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsm3600_la-sm3600.Tpo $(DEPDIR)/libsm3600_la-sm3600.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sm3600.c' object='libsm3600_la-sm3600.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsm3600_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsm3600_la-sm3600.lo `test -f 'sm3600.c' || echo '$(srcdir)/'`sm3600.c libsm3840_la-sm3840.lo: sm3840.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsm3840_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsm3840_la-sm3840.lo -MD -MP -MF $(DEPDIR)/libsm3840_la-sm3840.Tpo -c -o libsm3840_la-sm3840.lo `test -f 'sm3840.c' || echo '$(srcdir)/'`sm3840.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsm3840_la-sm3840.Tpo $(DEPDIR)/libsm3840_la-sm3840.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sm3840.c' object='libsm3840_la-sm3840.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsm3840_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsm3840_la-sm3840.lo `test -f 'sm3840.c' || echo '$(srcdir)/'`sm3840.c libsnapscan_la-snapscan.lo: snapscan.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsnapscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsnapscan_la-snapscan.lo -MD -MP -MF $(DEPDIR)/libsnapscan_la-snapscan.Tpo -c -o libsnapscan_la-snapscan.lo `test -f 'snapscan.c' || echo '$(srcdir)/'`snapscan.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsnapscan_la-snapscan.Tpo $(DEPDIR)/libsnapscan_la-snapscan.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='snapscan.c' object='libsnapscan_la-snapscan.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsnapscan_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsnapscan_la-snapscan.lo `test -f 'snapscan.c' || echo '$(srcdir)/'`snapscan.c libsp15c_la-sp15c.lo: sp15c.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsp15c_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsp15c_la-sp15c.lo -MD -MP -MF $(DEPDIR)/libsp15c_la-sp15c.Tpo -c -o libsp15c_la-sp15c.lo `test -f 'sp15c.c' || echo '$(srcdir)/'`sp15c.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsp15c_la-sp15c.Tpo $(DEPDIR)/libsp15c_la-sp15c.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sp15c.c' object='libsp15c_la-sp15c.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsp15c_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsp15c_la-sp15c.lo `test -f 'sp15c.c' || echo '$(srcdir)/'`sp15c.c libst400_la-st400.lo: st400.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libst400_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libst400_la-st400.lo -MD -MP -MF $(DEPDIR)/libst400_la-st400.Tpo -c -o libst400_la-st400.lo `test -f 'st400.c' || echo '$(srcdir)/'`st400.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libst400_la-st400.Tpo $(DEPDIR)/libst400_la-st400.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='st400.c' object='libst400_la-st400.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libst400_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libst400_la-st400.lo `test -f 'st400.c' || echo '$(srcdir)/'`st400.c libstv680_la-stv680.lo: stv680.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstv680_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libstv680_la-stv680.lo -MD -MP -MF $(DEPDIR)/libstv680_la-stv680.Tpo -c -o libstv680_la-stv680.lo `test -f 'stv680.c' || echo '$(srcdir)/'`stv680.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libstv680_la-stv680.Tpo $(DEPDIR)/libstv680_la-stv680.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stv680.c' object='libstv680_la-stv680.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstv680_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libstv680_la-stv680.lo `test -f 'stv680.c' || echo '$(srcdir)/'`stv680.c libtamarack_la-tamarack.lo: tamarack.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtamarack_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtamarack_la-tamarack.lo -MD -MP -MF $(DEPDIR)/libtamarack_la-tamarack.Tpo -c -o libtamarack_la-tamarack.lo `test -f 'tamarack.c' || echo '$(srcdir)/'`tamarack.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtamarack_la-tamarack.Tpo $(DEPDIR)/libtamarack_la-tamarack.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tamarack.c' object='libtamarack_la-tamarack.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtamarack_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtamarack_la-tamarack.lo `test -f 'tamarack.c' || echo '$(srcdir)/'`tamarack.c libteco1_la-teco1.lo: teco1.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libteco1_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libteco1_la-teco1.lo -MD -MP -MF $(DEPDIR)/libteco1_la-teco1.Tpo -c -o libteco1_la-teco1.lo `test -f 'teco1.c' || echo '$(srcdir)/'`teco1.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libteco1_la-teco1.Tpo $(DEPDIR)/libteco1_la-teco1.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='teco1.c' object='libteco1_la-teco1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libteco1_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libteco1_la-teco1.lo `test -f 'teco1.c' || echo '$(srcdir)/'`teco1.c libteco2_la-teco2.lo: teco2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libteco2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libteco2_la-teco2.lo -MD -MP -MF $(DEPDIR)/libteco2_la-teco2.Tpo -c -o libteco2_la-teco2.lo `test -f 'teco2.c' || echo '$(srcdir)/'`teco2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libteco2_la-teco2.Tpo $(DEPDIR)/libteco2_la-teco2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='teco2.c' object='libteco2_la-teco2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libteco2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libteco2_la-teco2.lo `test -f 'teco2.c' || echo '$(srcdir)/'`teco2.c libteco3_la-teco3.lo: teco3.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libteco3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libteco3_la-teco3.lo -MD -MP -MF $(DEPDIR)/libteco3_la-teco3.Tpo -c -o libteco3_la-teco3.lo `test -f 'teco3.c' || echo '$(srcdir)/'`teco3.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libteco3_la-teco3.Tpo $(DEPDIR)/libteco3_la-teco3.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='teco3.c' object='libteco3_la-teco3.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libteco3_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libteco3_la-teco3.lo `test -f 'teco3.c' || echo '$(srcdir)/'`teco3.c libtest_la-test.lo: test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_la-test.lo -MD -MP -MF $(DEPDIR)/libtest_la-test.Tpo -c -o libtest_la-test.lo `test -f 'test.c' || echo '$(srcdir)/'`test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtest_la-test.Tpo $(DEPDIR)/libtest_la-test.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test.c' object='libtest_la-test.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_la-test.lo `test -f 'test.c' || echo '$(srcdir)/'`test.c libu12_la-u12.lo: u12.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libu12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libu12_la-u12.lo -MD -MP -MF $(DEPDIR)/libu12_la-u12.Tpo -c -o libu12_la-u12.lo `test -f 'u12.c' || echo '$(srcdir)/'`u12.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libu12_la-u12.Tpo $(DEPDIR)/libu12_la-u12.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='u12.c' object='libu12_la-u12.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libu12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libu12_la-u12.lo `test -f 'u12.c' || echo '$(srcdir)/'`u12.c libumax_la-umax.lo: umax.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libumax_la-umax.lo -MD -MP -MF $(DEPDIR)/libumax_la-umax.Tpo -c -o libumax_la-umax.lo `test -f 'umax.c' || echo '$(srcdir)/'`umax.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libumax_la-umax.Tpo $(DEPDIR)/libumax_la-umax.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='umax.c' object='libumax_la-umax.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libumax_la-umax.lo `test -f 'umax.c' || echo '$(srcdir)/'`umax.c libumax1220u_la-umax1220u.lo: umax1220u.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax1220u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libumax1220u_la-umax1220u.lo -MD -MP -MF $(DEPDIR)/libumax1220u_la-umax1220u.Tpo -c -o libumax1220u_la-umax1220u.lo `test -f 'umax1220u.c' || echo '$(srcdir)/'`umax1220u.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libumax1220u_la-umax1220u.Tpo $(DEPDIR)/libumax1220u_la-umax1220u.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='umax1220u.c' object='libumax1220u_la-umax1220u.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax1220u_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libumax1220u_la-umax1220u.lo `test -f 'umax1220u.c' || echo '$(srcdir)/'`umax1220u.c libumax_pp_la-umax_pp.lo: umax_pp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libumax_pp_la-umax_pp.lo -MD -MP -MF $(DEPDIR)/libumax_pp_la-umax_pp.Tpo -c -o libumax_pp_la-umax_pp.lo `test -f 'umax_pp.c' || echo '$(srcdir)/'`umax_pp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libumax_pp_la-umax_pp.Tpo $(DEPDIR)/libumax_pp_la-umax_pp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='umax_pp.c' object='libumax_pp_la-umax_pp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libumax_pp_la-umax_pp.lo `test -f 'umax_pp.c' || echo '$(srcdir)/'`umax_pp.c libumax_pp_la-umax_pp_low.lo: umax_pp_low.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libumax_pp_la-umax_pp_low.lo -MD -MP -MF $(DEPDIR)/libumax_pp_la-umax_pp_low.Tpo -c -o libumax_pp_la-umax_pp_low.lo `test -f 'umax_pp_low.c' || echo '$(srcdir)/'`umax_pp_low.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libumax_pp_la-umax_pp_low.Tpo $(DEPDIR)/libumax_pp_la-umax_pp_low.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='umax_pp_low.c' object='libumax_pp_la-umax_pp_low.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libumax_pp_la-umax_pp_low.lo `test -f 'umax_pp_low.c' || echo '$(srcdir)/'`umax_pp_low.c libumax_pp_la-umax_pp_mid.lo: umax_pp_mid.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libumax_pp_la-umax_pp_mid.lo -MD -MP -MF $(DEPDIR)/libumax_pp_la-umax_pp_mid.Tpo -c -o libumax_pp_la-umax_pp_mid.lo `test -f 'umax_pp_mid.c' || echo '$(srcdir)/'`umax_pp_mid.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libumax_pp_la-umax_pp_mid.Tpo $(DEPDIR)/libumax_pp_la-umax_pp_mid.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='umax_pp_mid.c' object='libumax_pp_la-umax_pp_mid.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libumax_pp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libumax_pp_la-umax_pp_mid.lo `test -f 'umax_pp_mid.c' || echo '$(srcdir)/'`umax_pp_mid.c libv4l_la-v4l.lo: v4l.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libv4l_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libv4l_la-v4l.lo -MD -MP -MF $(DEPDIR)/libv4l_la-v4l.Tpo -c -o libv4l_la-v4l.lo `test -f 'v4l.c' || echo '$(srcdir)/'`v4l.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libv4l_la-v4l.Tpo $(DEPDIR)/libv4l_la-v4l.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='v4l.c' object='libv4l_la-v4l.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libv4l_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libv4l_la-v4l.lo `test -f 'v4l.c' || echo '$(srcdir)/'`v4l.c libxerox_mfp_la-xerox_mfp.lo: xerox_mfp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxerox_mfp_la-xerox_mfp.lo -MD -MP -MF $(DEPDIR)/libxerox_mfp_la-xerox_mfp.Tpo -c -o libxerox_mfp_la-xerox_mfp.lo `test -f 'xerox_mfp.c' || echo '$(srcdir)/'`xerox_mfp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxerox_mfp_la-xerox_mfp.Tpo $(DEPDIR)/libxerox_mfp_la-xerox_mfp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xerox_mfp.c' object='libxerox_mfp_la-xerox_mfp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxerox_mfp_la-xerox_mfp.lo `test -f 'xerox_mfp.c' || echo '$(srcdir)/'`xerox_mfp.c libxerox_mfp_la-xerox_mfp-usb.lo: xerox_mfp-usb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxerox_mfp_la-xerox_mfp-usb.lo -MD -MP -MF $(DEPDIR)/libxerox_mfp_la-xerox_mfp-usb.Tpo -c -o libxerox_mfp_la-xerox_mfp-usb.lo `test -f 'xerox_mfp-usb.c' || echo '$(srcdir)/'`xerox_mfp-usb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxerox_mfp_la-xerox_mfp-usb.Tpo $(DEPDIR)/libxerox_mfp_la-xerox_mfp-usb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xerox_mfp-usb.c' object='libxerox_mfp_la-xerox_mfp-usb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxerox_mfp_la-xerox_mfp-usb.lo `test -f 'xerox_mfp-usb.c' || echo '$(srcdir)/'`xerox_mfp-usb.c libxerox_mfp_la-xerox_mfp-tcp.lo: xerox_mfp-tcp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libxerox_mfp_la-xerox_mfp-tcp.lo -MD -MP -MF $(DEPDIR)/libxerox_mfp_la-xerox_mfp-tcp.Tpo -c -o libxerox_mfp_la-xerox_mfp-tcp.lo `test -f 'xerox_mfp-tcp.c' || echo '$(srcdir)/'`xerox_mfp-tcp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libxerox_mfp_la-xerox_mfp-tcp.Tpo $(DEPDIR)/libxerox_mfp_la-xerox_mfp-tcp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xerox_mfp-tcp.c' object='libxerox_mfp_la-xerox_mfp-tcp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libxerox_mfp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libxerox_mfp_la-xerox_mfp-tcp.lo `test -f 'xerox_mfp-tcp.c' || echo '$(srcdir)/'`xerox_mfp-tcp.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sanelibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ clean-sanelibLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-sanelibLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-sanelibLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: all check install install-am install-data-am install-strip \ uninstall-am .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-local \ clean-sanelibLTLIBRARIES cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-hook install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-sanelibLTLIBRARIES install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-hook \ uninstall-libLTLIBRARIES uninstall-sanelibLTLIBRARIES all: becfg # FIXME: % is a GNU extension... This is only thing left requiring # use to use GNU make. %-s.c: $(srcdir)/stubs.c $(AM_V_at)rm -f $@ $(AM_V_at)$(LN_S) $(srcdir)/stubs.c $@ dll-preload.h: $(AM_V_at)rm -f $@ $(AM_V_at)list="$(PRELOADABLE_BACKENDS)"; for be in $$list; do \ echo "PRELOAD_DECL($$be)" >> $@; \ done; \ echo "static struct backend preloaded_backends[] = {" >> $@; \ sep=""; \ list="$(PRELOADABLE_BACKENDS)"; \ if test -z "$${list}"; then \ echo { 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} >> $@; \ else \ for be in $$list; do \ echo "$${sep}PRELOAD_DEFN($$be)" >> $@; \ sep=","; \ done; \ fi; \ echo "};" >> $@ becfg: $(BACKEND_CONFS) .conf.in.conf: @echo Generating $@ from $^ @sed -e 's|@DATADIR@|$(datadir)|g' \ -e 's|@CONFIGDIR@|$(configdir)|g' \ -e 's|@DOCDIR@|$(docdir)|g' \ -e 's|@LIBDIR@|$(libdir)/sane|g' \ -e 's|@BINDIR@|$(bindir)|g' \ -e 's|@SBINDIR@|$(sbindir)|g' \ -e 's|@PACKAGEVERSION@|$(PACKAGE_VERSION)|g' $? > $@ install-data-hook: install-becfg install-firmware-path $(INSTALL_LOCKPATH) # Custom install target to install config files. Do not overwrite # files that have been previously installed so that user modifications # are not lost. install-becfg: @# Libtool has a bug where it will sometimes symlink the last @# installed library in $(sanelibdir) to $(sanelibdir)/libsane.*. @# Having two libsane's can cause issues so get rid of it. -rm -f $(DESTDIR)$(sanelibdir)/libsane.* test -z "$(configdir)" || $(MKDIR_P) "$(DESTDIR)$(configdir)" test -z "$(configdir)/dll.d" || $(MKDIR_P) "$(DESTDIR)$(configdir)/dll.d" @list="$(BACKEND_CONFS_ENABLED) saned.conf dll.conf"; for cfg in $$list; do \ if test ! -r $${cfg}; then continue; fi; \ if test -f $(DESTDIR)$(configdir)/$${cfg}; then \ echo NOT overwriting $${cfg} in $(configdir)...; \ else \ echo installing $${cfg} in $(configdir)/$${cfg}...; \ $(INSTALL_DATA) $${cfg} $(DESTDIR)$(configdir)/$${cfg} \ || exit 1; \ fi; \ done install-firmware-path: for dir in $(FIRMWARE_DIRS) ; do \ $(mkinstalldirs) $(DESTDIR)$(datadir)/sane/$${dir} ; \ done install-lockpath: $(mkinstalldirs) -m 775 $(DESTDIR)$(locksanedir) uninstall-hook: rm -rf $(DESTDIR)$(libdir)/sane $(DESTDIR)$(configdir) $(DESTDIR)$(locksanedir) rm -f $(DESTDIR)$(libdir)/libsane.* -for dir in $(FIRMWARE_DIRS) ; do \ rmdir $(DESTDIR)$(datadir)/sane/$${dir} ; \ done clean-local: find . -type l -name \*-s.c | xargs rm -f # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: sane-backends-1.0.27/backend/artec_eplus48u.c0000664000175000017500000036753712775312260015656 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Michael Herder ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ This backend is based on the "gt68xxtest" program written by the following persons: Sergey Vlasov - Main backend code. Andreas Nowack - Support for GT6801 (Mustek ScanExpress 1200 UB Plus). David Stevenson - Automatic AFE gain and offset setting. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Please note: The calibration code from the gt68xxtest program isn't used here, since I couldn't get it working. I'm using my own calibration code, which is based on wild assumptions based on the USB logs from the windoze driver. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ It also contains code from the plustek backend Copyright (C) 2000-2002 Gerhard Jaeger and from the mustek_usb backend Copyright (C) 2000 Mustek. Maintained by Tom Wang Updates (C) 2001 by Henning Meier-Geinitz. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #define BUILD 12 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME artec_eplus48u #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "artec_eplus48u.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define _DEFAULT_DEVICE "/dev/usbscanner" #define ARTEC48U_CONFIG_FILE "artec_eplus48u.conf" #define _SHADING_FILE_BLACK "artec48ushading_black" #define _SHADING_FILE_WHITE "artec48ushading_white" #define _EXPOSURE_FILE "artec48uexposure" #define _OFFSET_FILE "artec48uoffset" #define _BYTE 3 #define _STRING 2 #define _FLOAT 1 #define _INT 0 /*for calibration*/ #define WHITE_MIN 243*257 #define WHITE_MAX 253*257 #define BLACK_MIN 8*257 #define BLACK_MAX 18*257 #define EXPOSURE_STEP 280 static Artec48U_Device *first_dev = 0; static Artec48U_Scanner *first_handle = 0; static SANE_Int num_devices = 0; static char devName[PATH_MAX]; static char firmwarePath[PATH_MAX]; static char vendor_string[PATH_MAX]; static char model_string[PATH_MAX]; static SANE_Bool cancelRead; static int isEPro; static int eProMult; static SANE_Auth_Callback auth = NULL; static double gamma_master_default = 1.7; static double gamma_r_default = 1.0; static double gamma_g_default = 1.0; static double gamma_b_default = 1.0; static SANE_Word memory_read_value = 0x200c; /**< Memory read - wValue */ static SANE_Word memory_write_value = 0x200b; /**< Memory write - wValue */ static SANE_Word send_cmd_value = 0x2010; /**< Send normal command - wValue */ static SANE_Word send_cmd_index = 0x3f40; /**< Send normal command - wIndex */ static SANE_Word recv_res_value = 0x2011; /**< Receive normal result - wValue */ static SANE_Word recv_res_index = 0x3f00; /**< Receive normal result - wIndex */ static SANE_Word send_small_cmd_value = 0x2012; /**< Send small command - wValue */ static SANE_Word send_small_cmd_index = 0x3f40; /**< Send small command - wIndex */ static SANE_Word recv_small_res_value = 0x2013; /**< Receive small result - wValue */ static SANE_Word recv_small_res_index = 0x3f00; /**< Receive small result - wIndex */ static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; static SANE_Word resbit_list[] = { 6, 50, 100, 200, 300, 600, 1200 }; static SANE_Range brightness_contrast_range = { -127, 127, 0 }; static SANE_Range blacklevel_range = { 20, 240, 1 }; static SANE_Range gamma_range = { 0, /* minimum */ SANE_FIX (4.0), /* maximum */ 0 /* quantization */ }; static SANE_Range scan_range_x = { 0, /* minimum */ SANE_FIX (216.0), /* maximum */ 0 /* quantization */ }; static SANE_Range scan_range_y = { 0, /* minimum */ SANE_FIX (297.0), /* maximum */ 0 /* quantization */ }; static SANE_Word bitdepth_list[] = { 2, 8, 16 }; static SANE_Word bitdepth_list2[] = { 1, 8 }; static Artec48U_Exposure_Parameters exp_params; static Artec48U_Exposure_Parameters default_exp_params = { 0x009f, 0x0109, 0x00cb }; static Artec48U_AFE_Parameters afe_params; static Artec48U_AFE_Parameters default_afe_params = { 0x28, 0x0a, 0x2e, 0x03, 0x2e, 0x03 }; static SANE_Status download_firmware_file (Artec48U_Device * chip) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte *buf = NULL; int size = -1; FILE *f; XDBG ((2, "Try to open firmware file: \"%s\"\n", chip->firmware_path)); f = fopen (chip->firmware_path, "rb"); if (!f) { XDBG ((2, "Cannot open firmware file \"%s\"\n", firmwarePath)); status = SANE_STATUS_INVAL; } if (status == SANE_STATUS_GOOD) { fseek (f, 0, SEEK_END); size = ftell (f); fseek (f, 0, SEEK_SET); if (size == -1) { XDBG ((2, "Error getting size of firmware file \"%s\"\n", chip->firmware_path)); status = SANE_STATUS_INVAL; } } if (status == SANE_STATUS_GOOD) { XDBG ((3, "firmware size: %d\n", size)); buf = (SANE_Byte *) malloc (size); if (!buf) { XDBG ((2, "Cannot allocate %d bytes for firmware\n", size)); status = SANE_STATUS_NO_MEM; } } if (status == SANE_STATUS_GOOD) { int bytes_read = fread (buf, 1, size, f); if (bytes_read != size) { XDBG ((2, "Problem reading firmware file \"%s\"\n", chip->firmware_path)); status = SANE_STATUS_INVAL; } } if (f) fclose (f); if (status == SANE_STATUS_GOOD) { status = artec48u_download_firmware (chip, buf, size); if (status != SANE_STATUS_GOOD) { XDBG ((2, "Firmware download failed\n")); } } if (buf) free (buf); return status; } static SANE_Status init_calibrator (Artec48U_Scanner * s) { XDBG ((2, "Init calibrator size %d\n",30720 * s->dev->epro_mult)); s->shading_buffer_w = (unsigned char *) malloc (30720 * s->dev->epro_mult); /*epro*/ s->shading_buffer_b = (unsigned char *) malloc (30720 * s->dev->epro_mult); /*epro*/ s->shading_buffer_white[0] = (unsigned int *) malloc (5120 * s->dev->epro_mult * sizeof(unsigned int));/*epro*/ s->shading_buffer_black[0] = (unsigned int *) malloc (5120 * s->dev->epro_mult * sizeof (unsigned int));/*epro*/ s->shading_buffer_white[1] = (unsigned int *) malloc (5120 * s->dev->epro_mult * sizeof (unsigned int));/*epro*/ s->shading_buffer_black[1] = (unsigned int *) malloc (5120 * s->dev->epro_mult * sizeof (unsigned int));/*epro*/ s->shading_buffer_white[2] = (unsigned int *) malloc (5120 * s->dev->epro_mult * sizeof (unsigned int));/*epro*/ s->shading_buffer_black[2] = (unsigned int *) malloc (5120 * s->dev->epro_mult * sizeof (unsigned int));/*epro*/ if (!s->shading_buffer_w || !s->shading_buffer_b || !s->shading_buffer_white[0] || !s->shading_buffer_black[0] || !s->shading_buffer_white[1] || !s->shading_buffer_black[1] || !s->shading_buffer_white[2] || !s->shading_buffer_black[2]) { if (s->shading_buffer_w) free (s->shading_buffer_w); if (s->shading_buffer_b) free (s->shading_buffer_b); if (s->shading_buffer_white[0]) free (s->shading_buffer_white[0]); if (s->shading_buffer_black[0]) free (s->shading_buffer_black[0]); if (s->shading_buffer_white[1]) free (s->shading_buffer_white[1]); if (s->shading_buffer_black[1]) free (s->shading_buffer_black[1]); if (s->shading_buffer_white[2]) free (s->shading_buffer_white[2]); if (s->shading_buffer_black[2]) free (s->shading_buffer_black[2]); return SANE_STATUS_NO_MEM; } return SANE_STATUS_GOOD; } static void init_shading_buffer (Artec48U_Scanner * s) { unsigned int i, j; for (i = 0; i < 5120 * s->dev->epro_mult; i++) /*epro*/ { for (j = 0; j < 3; j++) { s->temp_shading_buffer[j][i] = 0; } } } static void add_to_shading_buffer (Artec48U_Scanner * s, unsigned int **buffer_pointers) { unsigned int i, j; for (i = 0; i < 5120 * s->dev->epro_mult; i++) /*epro*/ { for (j = 0; j < 3; j++) { s->temp_shading_buffer[j][i] += buffer_pointers[j][i]; } } } static void finish_shading_buffer (Artec48U_Scanner * s, SANE_Bool white) { unsigned int i, j, cnt, c, div; unsigned long max_r; unsigned long max_g; unsigned long max_b; unsigned char *shading_buffer; cnt = 0; if (white) { shading_buffer = s->shading_buffer_w; div = s->dev->shading_lines_w; } else { shading_buffer = s->shading_buffer_b; div = s->dev->shading_lines_b; } for (i = 0; i < 5120 * s->dev->epro_mult; i++) /*epro*/ { for (j = 0; j < 3; j++) { int value = s->temp_shading_buffer[j][i] / (div); shading_buffer[cnt] = (SANE_Byte) (value & 0xff); ++cnt; shading_buffer[cnt] = (SANE_Byte) ((value >> 8) & 0xff); ++cnt; } } max_r = 0; max_g = 0; max_b = 0; for (c = 0; c < (30720 * s->dev->epro_mult) - 5; c += 6) /*epro*/ { i = (int) shading_buffer[c] + ((int) shading_buffer[c + 1] << 8); max_r += i; i = (int) shading_buffer[c + 2] + ((int) shading_buffer[c + 3] << 8); max_g += i; i = (int) shading_buffer[c + 4] + ((int) shading_buffer[c + 5] << 8); max_b += i; } } static void finish_exposure_buffer (Artec48U_Scanner * s, int *avg_r, int *avg_g, int *avg_b) { unsigned int i, j, cnt, c, div; unsigned int max_r; unsigned int max_g; unsigned int max_b; unsigned char *shading_buffer; cnt = 0; shading_buffer = s->shading_buffer_w; div = s->dev->shading_lines_w; for (i = 0; i < 5120 * s->dev->epro_mult; i++) /*epro*/ { for (j = 0; j < 3; j++) { int value = s->temp_shading_buffer[j][i] / (div); shading_buffer[cnt] = (SANE_Byte) (value & 0xff); ++cnt; shading_buffer[cnt] = (SANE_Byte) ((value >> 8) & 0xff); ++cnt; } } max_r = 0; max_g = 0; max_b = 0; for (c = 0; c < (30720 * s->dev->epro_mult) - 5; c += 6) /*epro*/ { i = (int) shading_buffer[c] + ((int) shading_buffer[c + 1] << 8); if (i > max_r) max_r = i; i = (int) shading_buffer[c + 2] + ((int) shading_buffer[c + 3] << 8); if (i > max_g) max_g = i; i = (int) shading_buffer[c + 4] + ((int) shading_buffer[c + 5] << 8); if (i > max_b) max_b = i; } *avg_r = max_r; *avg_g = max_g; *avg_b = max_b; } static void finish_offset_buffer (Artec48U_Scanner * s, int *avg_r, int *avg_g, int *avg_b) { unsigned int i, j, cnt, c, div; unsigned int min_r; unsigned int min_g; unsigned int min_b; unsigned char *shading_buffer; cnt = 0; shading_buffer = s->shading_buffer_b; div = s->dev->shading_lines_b; for (i = 0; i < 5120 * s->dev->epro_mult; i++) /*epro*/ { for (j = 0; j < 3; j++) { int value = s->temp_shading_buffer[j][i] / (div); shading_buffer[cnt] = (SANE_Byte) (value & 0xff); ++cnt; shading_buffer[cnt] = (SANE_Byte) ((value >> 8) & 0xff); ++cnt; } } min_r = 65535; min_g = 65535; min_b = 65535; for (c = 0; c < (30720 * s->dev->epro_mult) - 5; c += 6) /*epro*/ { i = (int) shading_buffer[c] + ((int) shading_buffer[c + 1] << 8); if (i < min_r) min_r = i; i = (int) shading_buffer[c + 2] + ((int) shading_buffer[c + 3] << 8); if (i < min_g) min_g = i; i = (int) shading_buffer[c + 4] + ((int) shading_buffer[c + 5] << 8); if (i < min_b) min_b = i; } *avg_r = min_r; *avg_g = min_g; *avg_b = min_b; } static SANE_Status artec48u_wait_for_positioning (Artec48U_Device * chip) { SANE_Status status; SANE_Bool moving; while (SANE_TRUE) { status = artec48u_is_moving (chip, &moving); if (status != SANE_STATUS_GOOD) return status; if (!moving) break; usleep (100000); } return SANE_STATUS_GOOD; } static void copy_scan_line (Artec48U_Scanner * s) { /*For resolution of 1200 dpi we have to interpolate horizontally, because the optical horizontal resolution is limited to 600 dpi. We simply use the avarage value of two pixels. */ int cnt, i, j; int xs = s->params.pixel_xs; int interpolate = 0; int value; int value1; int value2; if ((s->reader->params.ydpi == 1200) && (s->dev->is_epro == 0)) /*epro*/ interpolate = 1; cnt = 0; if (s->params.color) { if (s->params.depth > 8) { for (i = xs - 1; i >= 0; i--) { for (j = 0; j < 3; j++) { value = s->buffer_pointers[j][i]; s->line_buffer[cnt] = LOBYTE (value); ++cnt; s->line_buffer[cnt] = HIBYTE (value); ++cnt; } if (interpolate == 1) /*1200 dpi */ cnt += 6; } if (interpolate == 1) { for (i = 0; i < (xs * 12) - 12; i += 12) { value1 = (int) s->line_buffer[i]; value1 += (int) (s->line_buffer[i + 1] << 8); value2 = (int) s->line_buffer[i + 12]; value2 += (int) (s->line_buffer[i + 13] << 8); value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 65535) value = 65535; s->line_buffer[i + 6] = LOBYTE (value); s->line_buffer[i + 7] = HIBYTE (value); value1 = (int) s->line_buffer[i + 2]; value1 += (int) (s->line_buffer[i + 3] << 8); value2 = (int) s->line_buffer[i + 14]; value2 += (int) (s->line_buffer[i + 15] << 8); value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 65535) value = 65535; s->line_buffer[i + 8] = LOBYTE (value); s->line_buffer[i + 9] = HIBYTE (value); value1 = (int) s->line_buffer[i + 4]; value1 += (int) (s->line_buffer[i + 5] << 8); value2 = (int) s->line_buffer[i + 16]; value2 += (int) (s->line_buffer[i + 17] << 8); value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 65535) value = 65535; s->line_buffer[i + 10] = LOBYTE (value); s->line_buffer[i + 11] = HIBYTE (value); } } } else { for (i = xs - 1; i >= 0; i--) { for (j = 0; j < 3; j++) { value = s->buffer_pointers[j][i]; s->line_buffer[cnt] = (SANE_Byte) (value / 257); cnt += 1; } if (interpolate == 1) /*1200 dpi */ cnt += 3; } if (interpolate == 1) { for (i = 0; i < (xs * 6) - 6; i += 6) { value1 = (int) s->line_buffer[i]; value2 = (int) s->line_buffer[i + 6]; value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 255) value = 255; s->line_buffer[i + 3] = (SANE_Byte) (value); value1 = (int) s->line_buffer[i + 1]; value2 = (int) s->line_buffer[i + 7]; value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 255) value = 255; s->line_buffer[i + 4] = (SANE_Byte) (value); value1 = (int) s->line_buffer[i + 2]; value2 = (int) s->line_buffer[i + 8]; value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 255) value = 255; s->line_buffer[i + 5] = (SANE_Byte) (value); } } } } else { if (s->params.depth > 8) { for (i = xs - 1; i >= 0; --i) { value = s->buffer_pointers[0][i]; s->line_buffer[cnt] = LOBYTE (value); ++cnt; s->line_buffer[cnt] = HIBYTE (value); ++cnt; if (interpolate == 1) /*1200 dpi */ cnt += 2; } if (interpolate == 1) { for (i = 0; i < (xs * 4) - 4; i += 4) { value1 = (int) s->line_buffer[i]; value1 += (int) (s->line_buffer[i + 1] << 8); value2 = (int) s->line_buffer[i + 4]; value2 += (int) (s->line_buffer[i + 5] << 8); value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 65535) value = 65535; s->line_buffer[i + 2] = LOBYTE (value); s->line_buffer[i + 3] = HIBYTE (value); } } } else { if (s->params.lineart == SANE_FALSE) { for (i = xs - 1; i >= 0; --i) { value = s->buffer_pointers[0][i]; s->line_buffer[cnt] = (SANE_Byte) (value / 257); ++cnt; if (interpolate == 1) /*1200 dpi */ ++cnt; } if (interpolate == 1) { for (i = 0; i < (xs * 2) - 2; i += 2) { value1 = (int) s->line_buffer[i]; value2 = (int) s->line_buffer[i + 2]; value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 255) value = 255; s->line_buffer[i + 1] = (SANE_Byte) (value); } } } else { int cnt2; int bit_cnt = 0; int black_level = s->val[OPT_BLACK_LEVEL].w; /*copy to lineart_buffer */ for (i = xs - 1; i >= 0; --i) { s->lineart_buffer[cnt] = (SANE_Byte) (s->buffer_pointers[0][i] / 257); ++cnt; if (interpolate == 1) /*1200 dpi */ ++cnt; } cnt2 = cnt - 1; cnt = 0; if (interpolate == 1) { for (i = 0; i < cnt2 - 2; i += 2) { value1 = (int) s->lineart_buffer[i]; value2 = (int) s->lineart_buffer[i + 2]; value = (value1 + value2) / 2; if (value < 0) value = 0; if (value > 255) value = 255; s->lineart_buffer[i + 1] = (SANE_Byte) (value); } } /* in this case, every value in buffer_pointers represents a bit */ for (i = 0; i < cnt2; i++) { SANE_Byte temp; if (bit_cnt == 0) s->line_buffer[cnt] = 0; /*clear */ temp = s->lineart_buffer[i]; if (temp <= black_level) s->line_buffer[cnt] |= 1 << (7 - bit_cnt); ++bit_cnt; if (bit_cnt > 7) { bit_cnt = 0; ++cnt; } } } } } } /*............................................................................. * attach a device to the backend */ static SANE_Status attach (const char *dev_name, Artec48U_Device ** devp) { SANE_Status status; Artec48U_Device *dev; XDBG ((1, "attach (%s, %p)\n", dev_name, (void *) devp)); if (!dev_name) { XDBG ((1, "attach: devname == NULL\n")); return SANE_STATUS_INVAL; } /* already attached ? */ for (dev = first_dev; dev; dev = dev->next) { if (0 == strcmp (dev->name, dev_name)) { if (devp) *devp = dev; XDBG ((3, "attach: device %s already attached\n", dev_name)); return SANE_STATUS_GOOD; } } XDBG ((3, "attach: device %s NOT attached\n", dev_name)); /* allocate some memory for the device */ artec48u_device_new (&dev); if (NULL == dev) return SANE_STATUS_NO_MEM; dev->fd = -1; dev->name = strdup (dev_name); dev->sane.name = strdup (dev_name); /* * go ahead and open the scanner device */ status = artec48u_device_open (dev); if (status != SANE_STATUS_GOOD) { XDBG ((3, "Could not open device!!\n")); artec48u_device_free (dev); return status; } /*limit the size of vendor and model string to 40 */ vendor_string[40] = 0; model_string[40] = 0; /* assign all the stuff we need fo this device... */ dev->sane.vendor = strdup (vendor_string); XDBG ((3, "attach: setting vendor string: %s\n", vendor_string)); dev->sane.model = strdup (model_string); XDBG ((3, "attach: setting model string: %s\n", model_string)); dev->sane.type = "flatbed scanner"; dev->firmware_path = strdup (firmwarePath); dev->epro_mult = eProMult; dev->is_epro = isEPro; XDBG ((1, "attach eProMult %d\n", eProMult)); XDBG ((1, "attach isEPro %d\n", isEPro)); dev->optical_xdpi = 600 * dev->epro_mult; /*epro*/ dev->optical_ydpi = 1200 * dev->epro_mult; /*epro*/ dev->base_ydpi = 600 * dev->epro_mult; /*epro*/ dev->xdpi_offset = 0; /* in optical_xdpi units */ dev->ydpi_offset = 280 * dev->epro_mult; /* in optical_ydpi units */ dev->x_size = 5120 * dev->epro_mult; /*epro*/ /* in optical_xdpi units */ dev->y_size = 14100 * dev->epro_mult; /*epro*/ /* in optical_ydpi units */ dev->shading_offset = 10 * dev->epro_mult; dev->shading_lines_b = 70 * dev->epro_mult; dev->shading_lines_w = 70 * dev->epro_mult; dev->gamma_master = gamma_master_default; dev->gamma_r = gamma_r_default; dev->gamma_g = gamma_g_default; dev->gamma_b = gamma_b_default; dev->afe_params.r_offset = afe_params.r_offset; dev->afe_params.g_offset = afe_params.g_offset; dev->afe_params.b_offset = afe_params.b_offset; dev->afe_params.r_pga = default_afe_params.r_pga; dev->afe_params.g_pga = default_afe_params.g_pga; dev->afe_params.b_pga = default_afe_params.b_pga; dev->exp_params.r_time = exp_params.r_time; dev->exp_params.g_time = exp_params.g_time; dev->exp_params.b_time = exp_params.b_time; ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = first_dev; status = artec48u_device_close (dev); return SANE_STATUS_GOOD; } static SANE_Status attach_one_device (SANE_String_Const devname) { Artec48U_Device *dev; SANE_Status status; status = attach (devname, &dev); if (SANE_STATUS_GOOD != status) return status; return SANE_STATUS_GOOD; } /** * function to decode an value and give it back to the caller. * @param src - pointer to the source string to check * @param opt - string that keeps the option name to check src for * @param what - _FLOAT or _INT * @param result - pointer to the var that should receive our result * @param def - default value that result should be in case of any error * @return The function returns SANE_TRUE if the option has been found, * if not, it returns SANE_FALSE */ static SANE_Bool decodeVal (char *src, char *opt, int what, void *result, void *def) { char *tmp, *tmp2; const char *name; /* skip the option string */ name = (const char *) &src[strlen ("option")]; /* get the name of the option */ name = sanei_config_get_string (name, &tmp); if (tmp) { /* on success, compare wiht the given one */ if (0 == strcmp (tmp, opt)) { XDBG ((1, "Decoding option >%s<\n", opt)); if (_INT == what) { /* assign the default value for this option... */ *((int *) result) = *((int *) def); if (*name) { /* get the configuration value and decode it */ name = sanei_config_get_string (name, &tmp2); if (tmp2) { *((int *) result) = strtol (tmp2, 0, 0); free (tmp2); } } free (tmp); return SANE_TRUE; } else if (_FLOAT == what) { /* assign the default value for this option... */ *((double *) result) = *((double *) def); if (*name) { /* get the configuration value and decode it */ name = sanei_config_get_string (name, &tmp2); if (tmp2) { *((double *) result) = strtod (tmp2, 0); free (tmp2); } } free (tmp); return SANE_TRUE; } else if (_BYTE == what) { /* assign the default value for this option... */ *((SANE_Byte *) result) = *((SANE_Byte *) def); if (*name) { /* get the configuration value and decode it */ name = sanei_config_get_string (name, &tmp2); if (tmp2) { *((SANE_Byte *) result) = (SANE_Byte) strtol (tmp2, 0, 0); free (tmp2); } } free (tmp); return SANE_TRUE; } else if (_STRING == what) { if (*name) { /* get the configuration value and decode it */ sanei_config_get_string (name, &tmp2); if (tmp2) { strcpy ((char *) result, (char *) tmp2); free (tmp2); } } free (tmp); return SANE_TRUE; } } free (tmp); } return SANE_FALSE; } /** * function to retrive the device name of a given string * @param src - string that keeps the option name to check src for * @param dest - pointer to the string, that should receive the detected * devicename * @return The function returns SANE_TRUE if the devicename has been found, * if not, it returns SANE_FALSE */ static SANE_Bool decodeDevName (char *src, char *dest) { char *tmp; const char *name; if (0 == strncmp ("device", src, 6)) { name = (const char *) &src[strlen ("device")]; name = sanei_config_skip_whitespace (name); XDBG ((1, "Decoding device name >%s<\n", name)); if (*name) { name = sanei_config_get_string (name, &tmp); if (tmp) { strcpy (dest, tmp); free (tmp); return SANE_TRUE; } } } return SANE_FALSE; } #ifdef ARTEC48U_USE_BUTTONS static SANE_Status artec48u_check_buttons (Artec48U_Device * dev, SANE_Int * value) { SANE_Status status; Artec48U_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x74; req[1] = 0x01; status = artec48u_device_small_req (dev, req, req); if (status != SANE_STATUS_GOOD) return status; *value = (SANE_Int) req[2]; return SANE_STATUS_GOOD; } #endif #define MAX_DOWNLOAD_BLOCK_SIZE 64 static SANE_Status artec48u_generic_start_scan (Artec48U_Device * dev) { Artec48U_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x43; req[1] = 0x01; return artec48u_device_req (dev, req, req); } static SANE_Status artec48u_generic_read_scanned_data (Artec48U_Device * dev, SANE_Bool * ready) { SANE_Status status; Artec48U_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x35; req[1] = 0x01; status = artec48u_device_req (dev, req, req); if (status != SANE_STATUS_GOOD) return status; if (req[1] == 0x35) { if (req[0] == 0) *ready = SANE_TRUE; else *ready = SANE_FALSE; } else return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } static SANE_Status artec48u_download_firmware (Artec48U_Device * dev, SANE_Byte * data, SANE_Word size) { SANE_Status status; SANE_Byte download_buf[MAX_DOWNLOAD_BLOCK_SIZE]; SANE_Byte check_buf[MAX_DOWNLOAD_BLOCK_SIZE]; SANE_Byte *block; SANE_Word addr, bytes_left; Artec48U_Packet boot_req; SANE_Word block_size = MAX_DOWNLOAD_BLOCK_SIZE; CHECK_DEV_ACTIVE ((Artec48U_Device *) dev, (char *) "artec48u_device_download_firmware"); for (addr = 0; addr < size; addr += block_size) { bytes_left = size - addr; if (bytes_left > block_size) block = data + addr; else { memset (download_buf, 0, block_size); memcpy (download_buf, data + addr, bytes_left); block = download_buf; } status = artec48u_device_memory_write (dev, addr, block_size, block); if (status != SANE_STATUS_GOOD) return status; status = artec48u_device_memory_read (dev, addr, block_size, check_buf); if (status != SANE_STATUS_GOOD) return status; if (memcmp (block, check_buf, block_size) != 0) { XDBG ((3, "artec48u_device_download_firmware: mismatch at block 0x%0x\n", addr)); return SANE_STATUS_IO_ERROR; } } memset (boot_req, 0, sizeof (boot_req)); boot_req[0] = 0x69; boot_req[1] = 0x01; boot_req[2] = LOBYTE (addr); boot_req[3] = HIBYTE (addr); status = artec48u_device_req (dev, boot_req, boot_req); if (status != SANE_STATUS_GOOD) return status; return SANE_STATUS_GOOD; } static SANE_Status artec48u_is_moving (Artec48U_Device * dev, SANE_Bool * moving) { SANE_Status status; Artec48U_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x17; req[1] = 0x01; status = artec48u_device_req (dev, req, req); if (status != SANE_STATUS_GOOD) return status; if (req[0] == 0x00 && req[1] == 0x17) { if (req[2] == 0 && (req[3] == 0 || req[3] == 2)) *moving = SANE_FALSE; else *moving = SANE_TRUE; } else return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } static SANE_Status artec48u_carriage_home (Artec48U_Device * dev) { Artec48U_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x24; req[1] = 0x01; return artec48u_device_req (dev, req, req); } static SANE_Status artec48u_stop_scan (Artec48U_Device * dev) { Artec48U_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x41; req[1] = 0x01; return artec48u_device_small_req (dev, req, req); } static SANE_Status artec48u_setup_scan (Artec48U_Scanner * s, Artec48U_Scan_Request * request, Artec48U_Scan_Action action, SANE_Bool calculate_only, Artec48U_Scan_Parameters * params) { DECLARE_FUNCTION_NAME ("artec48u_setup_scan") SANE_Status status; SANE_Int xdpi, ydpi; SANE_Bool color; SANE_Int depth; SANE_Int pixel_x0, pixel_y0, pixel_xs, pixel_ys; SANE_Int pixel_align; SANE_Int abs_x0, abs_y0, abs_xs, abs_ys, base_xdpi, base_ydpi; SANE_Int scan_xs, scan_ys, scan_bpl; SANE_Int bits_per_line; SANE_Byte color_mode_code; /*If we scan a black line, we use these exposure values */ Artec48U_Exposure_Parameters exp_params_black = { 4, 4, 4 }; XDBG ((6, "%s: enter\n", function_name)); XDBG ((1,"setup scan is_epro %d\n",s->dev->is_epro)); XDBG ((1,"setup scan epro_mult %d\n",s->dev->epro_mult)); xdpi = request->xdpi; ydpi = request->ydpi; color = request->color; depth = request->depth; switch (action) { case SA_CALIBRATE_SCAN_WHITE: { /*move a bit inside scan mark - the value for the offset was found by trial and error */ pixel_y0 = s->dev->shading_offset; pixel_ys = s->dev->shading_lines_w; pixel_x0 = 0; pixel_xs = 5120 * s->dev->epro_mult; /*epro*/ xdpi = ydpi = 600 * s->dev->epro_mult; /*epro*/ color = SANE_TRUE; depth = 8; break; } case SA_CALIBRATE_SCAN_OFFSET_1: case SA_CALIBRATE_SCAN_OFFSET_2: { pixel_y0 = s->dev->shading_offset; pixel_ys = s->dev->shading_lines_b; pixel_x0 = 0; pixel_xs = 5120 * s->dev->epro_mult; /*epro*/ xdpi = ydpi = 600 * s->dev->epro_mult; /*epro*/ color = SANE_TRUE; depth = 8; break; } case SA_CALIBRATE_SCAN_EXPOSURE_1: case SA_CALIBRATE_SCAN_EXPOSURE_2: { pixel_y0 = s->dev->shading_offset; pixel_ys = s->dev->shading_lines_w; pixel_x0 = 0; pixel_xs = 5120 * s->dev->epro_mult; /*epro*/ xdpi = ydpi = 600 * s->dev->epro_mult; /*epro*/ color = SANE_TRUE; depth = 8; break; } case SA_CALIBRATE_SCAN_BLACK: { pixel_y0 = s->dev->shading_offset; pixel_ys = s->dev->shading_lines_w; pixel_x0 = 0; pixel_xs = 5120 * s->dev->epro_mult; /*epro*/ xdpi = ydpi = 600 * s->dev->epro_mult; /*epro*/ color = SANE_TRUE; depth = 8; break; } case SA_SCAN: { SANE_Fixed x0 = request->x0 + s->dev->xdpi_offset; SANE_Fixed y0; /*epro*/ if ((ydpi == 1200) && (s->dev->is_epro == 0)) xdpi = 600; y0 = request->y0 + s->dev->ydpi_offset; pixel_ys = SANE_UNFIX (request->ys) * ydpi / MM_PER_INCH + 0.5; pixel_x0 = SANE_UNFIX (x0) * xdpi / MM_PER_INCH + 0.5; pixel_y0 = SANE_UNFIX (y0) * ydpi / MM_PER_INCH + 0.5; pixel_xs = SANE_UNFIX (request->xs) * xdpi / MM_PER_INCH + 0.5; break; } default: XDBG ((6, "%s: invalid action=%d\n", function_name, (int) action)); return SANE_STATUS_INVAL; } XDBG ((6, "%s: xdpi=%d, ydpi=%d\n", function_name, xdpi, ydpi)); XDBG ((6, "%s: color=%s, depth=%d\n", function_name, color ? "TRUE" : "FALSE", depth)); XDBG ((6, "%s: pixel_x0=%d, pixel_y0=%d\n", function_name, pixel_x0, pixel_y0)); XDBG ((6, "%s: pixel_xs=%d, pixel_ys=%d\n", function_name, pixel_xs, pixel_ys)); switch (depth) { case 8: color_mode_code = color ? 0x84 : 0x82; break; case 16: color_mode_code = color ? 0xa4 : 0xa2; break; default: XDBG ((6, "%s: unsupported depth=%d\n", function_name, depth)); return SANE_STATUS_UNSUPPORTED; } base_xdpi = s->dev->optical_xdpi; base_ydpi = s->dev->base_ydpi; XDBG ((6, "%s: base_xdpi=%d, base_ydpi=%d\n", function_name, base_xdpi, base_ydpi)); abs_x0 = pixel_x0 * base_xdpi / xdpi; abs_y0 = pixel_y0 * base_ydpi / ydpi; /* Calculate minimum number of pixels which span an integral multiple of 64 * bytes. */ pixel_align = 32; /* best case for depth = 16 */ while ((depth * pixel_align) % (64 * 8) != 0) pixel_align *= 2; XDBG ((6, "%s: pixel_align=%d\n", function_name, pixel_align)); if (pixel_xs % pixel_align == 0) scan_xs = pixel_xs; else scan_xs = (pixel_xs / pixel_align + 1) * pixel_align; scan_ys = pixel_ys; XDBG ((6, "%s: scan_xs=%d, scan_ys=%d\n", function_name, scan_xs, scan_ys)); abs_xs = scan_xs * base_xdpi / xdpi; abs_ys = scan_ys * base_ydpi / ydpi; XDBG ((6, "%s: abs_xs=%d, abs_ys=%d\n", function_name, abs_xs, abs_ys)); bits_per_line = depth * scan_xs; if (bits_per_line % 8) /* impossible */ { XDBG ((1, "%s: BUG: unaligned bits_per_line=%d\n", function_name, bits_per_line)); return SANE_STATUS_INVAL; } scan_bpl = bits_per_line / 8; if (scan_bpl % 64) /* impossible */ { XDBG ((1, "%s: BUG: unaligned scan_bpl=%d\n", function_name, scan_bpl)); return SANE_STATUS_INVAL; } if (scan_bpl > 15600) { XDBG ((6, "%s: scan_bpl=%d, too large\n", function_name, scan_bpl)); return SANE_STATUS_INVAL; } XDBG ((6, "%s: scan_bpl=%d\n", function_name, scan_bpl)); if (!calculate_only) { Artec48U_Packet req; char motor_mode_1, motor_mode_2; switch (action) { case SA_CALIBRATE_SCAN_WHITE: motor_mode_1 = 0x01; motor_mode_2 = 0x00; break; case SA_CALIBRATE_SCAN_BLACK: motor_mode_1 = 0x04; motor_mode_2 = 0x00; break; case SA_SCAN: motor_mode_1 = 0x01; motor_mode_2 = 0x00; break; default: XDBG ((6, "%s: invalid action=%d\n", function_name, (int) action)); return SANE_STATUS_INVAL; } /* Fill in the setup command */ memset (req, 0, sizeof (req)); req[0x00] = 0x20; req[0x01] = 0x01; req[0x02] = LOBYTE (abs_y0); req[0x03] = HIBYTE (abs_y0); req[0x04] = LOBYTE (abs_ys); req[0x05] = HIBYTE (abs_ys); req[0x06] = LOBYTE (abs_x0); req[0x07] = HIBYTE (abs_x0); req[0x08] = LOBYTE (abs_xs); req[0x09] = HIBYTE (abs_xs); req[0x0a] = color_mode_code; req[0x0b] = 0x60; req[0x0c] = LOBYTE (xdpi); req[0x0d] = HIBYTE (xdpi); req[0x0e] = 0x12; req[0x0f] = 0x00; req[0x10] = LOBYTE (scan_bpl); req[0x11] = HIBYTE (scan_bpl); req[0x12] = LOBYTE (scan_ys); req[0x13] = HIBYTE (scan_ys); req[0x14] = motor_mode_1; req[0x15] = motor_mode_2; req[0x16] = LOBYTE (ydpi); req[0x17] = HIBYTE (ydpi); req[0x18] = 0x00; status = artec48u_device_req (s->dev, req, req); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: setup request failed: %s\n", function_name, sane_strstatus (status))); return status; } if (action == SA_SCAN) { artec48u_calculate_shading_buffer (s, pixel_x0, pixel_xs + pixel_x0, xdpi, color); artec48u_generic_set_exposure_time (s->dev, &(s->dev-> artec_48u_exposure_params)); artec48u_generic_set_afe (s->dev, &(s->dev->artec_48u_afe_params)); } else if (action == SA_CALIBRATE_SCAN_BLACK) { artec48u_generic_set_exposure_time (s->dev, &exp_params_black); artec48u_generic_set_afe (s->dev, &(s->dev->afe_params)); } else if (action == SA_CALIBRATE_SCAN_WHITE) { artec48u_generic_set_exposure_time (s->dev, &(s->dev->exp_params)); artec48u_generic_set_afe (s->dev, &(s->dev->afe_params)); } } /* Fill in calculated values */ params->xdpi = xdpi; params->ydpi = ydpi; params->depth = depth; params->color = color; params->pixel_xs = pixel_xs; params->pixel_ys = pixel_ys; params->scan_xs = scan_xs; params->scan_ys = scan_ys; params->scan_bpl = scan_bpl; XDBG ((6, "%s: leave: ok\n", function_name)); return SANE_STATUS_GOOD; } static SANE_Status artec48u_generic_set_afe (Artec48U_Device * dev, Artec48U_AFE_Parameters * params) { Artec48U_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x22; req[1] = 0x01; req[2] = params->r_offset; req[3] = params->r_pga; req[4] = params->g_offset; req[5] = params->g_pga; req[6] = params->b_offset; req[7] = params->b_pga; return artec48u_device_req (dev, req, req); } static SANE_Status artec48u_generic_set_exposure_time (Artec48U_Device * dev, Artec48U_Exposure_Parameters * params) { Artec48U_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x76; req[1] = 0x01; req[2] = req[6] = req[10] = 0x04; req[4] = LOBYTE (params->r_time); req[5] = HIBYTE (params->r_time); req[8] = LOBYTE (params->g_time); req[9] = HIBYTE (params->g_time); req[12] = LOBYTE (params->b_time); req[13] = HIBYTE (params->b_time); return artec48u_device_req (dev, req, req); } static SANE_Status artec48u_device_new (Artec48U_Device ** dev_return) { DECLARE_FUNCTION_NAME ("artec48u_device_new") Artec48U_Device *dev; XDBG ((7, "%s: enter\n", function_name)); if (!dev_return) return SANE_STATUS_INVAL; dev = (Artec48U_Device *) malloc (sizeof (Artec48U_Device)); if (!dev) { XDBG ((3, "%s: couldn't malloc %lu bytes for device\n", function_name, (u_long) sizeof (Artec48U_Device))); *dev_return = 0; return SANE_STATUS_NO_MEM; } *dev_return = dev; memset (dev, 0, sizeof (Artec48U_Device)); dev->fd = -1; dev->active = SANE_FALSE; dev->read_buffer = NULL; dev->requested_buffer_size = 32768; XDBG ((7, "%s: leave: ok\n", function_name)); return SANE_STATUS_GOOD; } static SANE_Status artec48u_device_free (Artec48U_Device * dev) { DECLARE_FUNCTION_NAME ("artec48u_device_free") XDBG ((7, "%s: enter: dev=%p\n", function_name, (void *) dev)); if (dev) { if (dev->active) artec48u_device_deactivate (dev); if (dev->fd != -1) artec48u_device_close (dev); XDBG ((7, "%s: freeing dev\n", function_name)); free (dev); } XDBG ((7, "%s: leave: ok\n", function_name)); return SANE_STATUS_GOOD; } static SANE_Status artec48u_device_open (Artec48U_Device * dev) { DECLARE_FUNCTION_NAME ("artec48u_device_open") SANE_Status status; SANE_Int fd; XDBG ((7, "%s: enter: dev=%p\n", function_name, (void *) dev)); CHECK_DEV_NOT_NULL (dev, function_name); if (dev->fd != -1) { XDBG ((3, "%s: device already open\n", function_name)); return SANE_STATUS_INVAL; } status = sanei_usb_open (dev->sane.name, &fd); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: sanei_usb_open failed: %s\n", function_name, sane_strstatus (status))); return status; } dev->fd = fd; XDBG ((7, "%s: leave: ok\n", function_name)); return SANE_STATUS_GOOD; } static SANE_Status artec48u_device_close (Artec48U_Device * dev) { DECLARE_FUNCTION_NAME ("artec48u_device_close") XDBG ((7, "%s: enter: dev=%p\n", function_name, (void *) dev)); CHECK_DEV_OPEN (dev, function_name); if (dev->active) artec48u_device_deactivate (dev); sanei_usb_close (dev->fd); dev->fd = -1; XDBG ((7, "%s: leave: ok\n", function_name)); return SANE_STATUS_GOOD; } static SANE_Status artec48u_device_activate (Artec48U_Device * dev) { DECLARE_FUNCTION_NAME ("artec48u_device_activate") CHECK_DEV_OPEN (dev, function_name); if (dev->active) { XDBG ((3, "%s: device already active\n", function_name)); return SANE_STATUS_INVAL; } XDBG ((7, "%s: model \"%s\"\n", function_name, dev->sane.model)); dev->xdpi_offset = SANE_FIX (dev->xdpi_offset * MM_PER_INCH / dev->optical_xdpi); dev->ydpi_offset = SANE_FIX (dev->ydpi_offset * MM_PER_INCH / dev->optical_ydpi); dev->active = SANE_TRUE; return SANE_STATUS_GOOD; } static SANE_Status artec48u_device_deactivate (Artec48U_Device * dev) { DECLARE_FUNCTION_NAME ("artec48u_device_deactivate") SANE_Status status = SANE_STATUS_GOOD; CHECK_DEV_ACTIVE (dev, function_name); if (dev->read_active) artec48u_device_read_finish (dev); dev->active = SANE_FALSE; return status; } static SANE_Status artec48u_device_memory_write (Artec48U_Device * dev, SANE_Word addr, SANE_Word size, SANE_Byte * data) { DECLARE_FUNCTION_NAME ("artec48u_device_memory_write") SANE_Status status; XDBG ((8, "%s: dev=%p, addr=0x%x, size=0x%x, data=%p\n", function_name, (void *) dev, addr, size, (void *) data)); CHECK_DEV_ACTIVE (dev, function_name); status = sanei_usb_control_msg (dev->fd, 0x40, 0x01, memory_write_value, addr, size, data); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: sanei_usb_control_msg failed: %s\n", function_name, sane_strstatus (status))); } return status; } static SANE_Status artec48u_device_memory_read (Artec48U_Device * dev, SANE_Word addr, SANE_Word size, SANE_Byte * data) { DECLARE_FUNCTION_NAME ("artec48u_device_memory_read") SANE_Status status; XDBG ((8, "%s: dev=%p, addr=0x%x, size=0x%x, data=%p\n", function_name, (void *) dev, addr, size, data)); CHECK_DEV_ACTIVE (dev, function_name); status = sanei_usb_control_msg (dev->fd, 0xc0, 0x01, memory_read_value, addr, size, data); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: sanei_usb_control_msg failed: %s\n", function_name, sane_strstatus (status))); } return status; } static SANE_Status artec48u_device_generic_req (Artec48U_Device * dev, SANE_Word cmd_value, SANE_Word cmd_index, SANE_Word res_value, SANE_Word res_index, Artec48U_Packet cmd, Artec48U_Packet res) { DECLARE_FUNCTION_NAME ("artec48u_device_generic_req") SANE_Status status; XDBG ((7, "%s: command=0x%02x\n", function_name, cmd[0])); CHECK_DEV_ACTIVE (dev, function_name); status = sanei_usb_control_msg (dev->fd, 0x40, 0x01, cmd_value, cmd_index, ARTEC48U_PACKET_SIZE, cmd); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: writing command failed: %s\n", function_name, sane_strstatus (status))); return status; } memset (res, 0, sizeof (Artec48U_Packet)); status = sanei_usb_control_msg (dev->fd, 0xc0, 0x01, res_value, res_index, ARTEC48U_PACKET_SIZE, res); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: reading response failed: %s\n", function_name, sane_strstatus (status))); return status; } return status; } static SANE_Status artec48u_device_req (Artec48U_Device * dev, Artec48U_Packet cmd, Artec48U_Packet res) { return artec48u_device_generic_req (dev, send_cmd_value, send_cmd_index, recv_res_value, recv_res_index, cmd, res); } static SANE_Status artec48u_device_small_req (Artec48U_Device * dev, Artec48U_Packet cmd, Artec48U_Packet res) { Artec48U_Packet fixed_cmd; int i; for (i = 0; i < 8; ++i) memcpy (fixed_cmd + i * 8, cmd, 8); return artec48u_device_generic_req (dev, send_small_cmd_value, send_small_cmd_index, recv_small_res_value, recv_small_res_index, fixed_cmd, res); } static SANE_Status artec48u_device_read_raw (Artec48U_Device * dev, SANE_Byte * buffer, size_t * size) { DECLARE_FUNCTION_NAME ("artec48u_device_read_raw") SANE_Status status; CHECK_DEV_ACTIVE (dev, function_name); XDBG ((7, "%s: enter: size=0x%lx\n", function_name, (unsigned long) *size)); status = sanei_usb_read_bulk (dev->fd, buffer, size); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: bulk read failed: %s\n", function_name, sane_strstatus (status))); return status; } XDBG ((7, "%s: leave: size=0x%lx\n", function_name, (unsigned long) *size)); return SANE_STATUS_GOOD; } static SANE_Status artec48u_device_set_read_buffer_size (Artec48U_Device * dev, size_t buffer_size) { DECLARE_FUNCTION_NAME ("gt68xx_device_set_read_buffer_size") CHECK_DEV_NOT_NULL (dev, function_name); if (dev->read_active) { XDBG ((3, "%s: BUG: read already active\n", function_name)); return SANE_STATUS_INVAL; } buffer_size = (buffer_size + 63UL) & ~63UL; if (buffer_size > 0) { dev->requested_buffer_size = buffer_size; return SANE_STATUS_GOOD; } XDBG ((3, "%s: bad buffer size\n", function_name)); return SANE_STATUS_INVAL; } static SANE_Status artec48u_device_read_prepare (Artec48U_Device * dev, size_t expected_count) { DECLARE_FUNCTION_NAME ("artec48u_device_read_prepare") CHECK_DEV_ACTIVE (dev, function_name); if (dev->read_active) { XDBG ((3, "%s: read already active\n", function_name)); return SANE_STATUS_INVAL; } dev->read_buffer = (SANE_Byte *) malloc (dev->requested_buffer_size); if (!dev->read_buffer) { XDBG ((3, "%s: not enough memory for the read buffer (%lu bytes)\n", function_name, (unsigned long) dev->requested_buffer_size)); return SANE_STATUS_NO_MEM; } dev->read_active = SANE_TRUE; dev->read_pos = dev->read_bytes_in_buffer = 0; dev->read_bytes_left = expected_count; return SANE_STATUS_GOOD; } static void reader_process_sigterm_handler (int signal) { XDBG ((1, "reader_process: terminated by signal %d\n", signal)); _exit (SANE_STATUS_GOOD); } static void usb_reader_process_sigterm_handler (int signal) { XDBG ((1, "reader_process (usb): terminated by signal %d\n", signal)); cancelRead = SANE_TRUE; } static SANE_Status artec48u_device_read_start (Artec48U_Device * dev) { CHECK_DEV_ACTIVE (dev, "artec48u_device_read_start"); return SANE_STATUS_GOOD; } static SANE_Status artec48u_device_read (Artec48U_Device * dev, SANE_Byte * buffer, size_t * size) { DECLARE_FUNCTION_NAME ("artec48u_device_read") SANE_Status status; size_t byte_count = 0; size_t left_to_read = *size; size_t transfer_size, block_size, raw_block_size; CHECK_DEV_ACTIVE (dev, function_name); if (!dev->read_active) { XDBG ((3, "%s: read not active\n", function_name)); return SANE_STATUS_INVAL; } while (left_to_read > 0) { if (dev->read_bytes_in_buffer == 0) { block_size = dev->requested_buffer_size; if (block_size > dev->read_bytes_left) block_size = dev->read_bytes_left; if (block_size == 0) break; raw_block_size = (block_size + 63UL) & ~63UL; status = artec48u_device_read_raw (dev, dev->read_buffer, &raw_block_size); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: read failed\n", function_name)); return status; } dev->read_pos = 0; dev->read_bytes_in_buffer = block_size; dev->read_bytes_left -= block_size; } transfer_size = left_to_read; if (transfer_size > dev->read_bytes_in_buffer) transfer_size = dev->read_bytes_in_buffer; if (transfer_size > 0) { memcpy (buffer, dev->read_buffer + dev->read_pos, transfer_size); dev->read_pos += transfer_size; dev->read_bytes_in_buffer -= transfer_size; byte_count += transfer_size; left_to_read -= transfer_size; buffer += transfer_size; } } *size = byte_count; if (byte_count == 0) return SANE_STATUS_EOF; else return SANE_STATUS_GOOD; } static SANE_Status artec48u_device_read_finish (Artec48U_Device * dev) { DECLARE_FUNCTION_NAME ("artec48u_device_read_finish") CHECK_DEV_ACTIVE (dev, function_name); if (!dev->read_active) { XDBG ((3, "%s: read not active\n", function_name)); return SANE_STATUS_INVAL; } XDBG ((7, "%s: read_bytes_left = %ld\n", function_name, (long) dev->read_bytes_left)); free (dev->read_buffer); dev->read_buffer = NULL; dev->read_active = SANE_FALSE; return SANE_STATUS_GOOD; } static SANE_Status artec48u_delay_buffer_init (Artec48U_Delay_Buffer * delay, SANE_Int pixels_per_line) { DECLARE_FUNCTION_NAME ("artec48u_delay_buffer_init") SANE_Int bytes_per_line; SANE_Int line_count, i; if (pixels_per_line <= 0) { XDBG ((3, "%s: BUG: pixels_per_line=%d\n", function_name, pixels_per_line)); return SANE_STATUS_INVAL; } bytes_per_line = pixels_per_line * sizeof (unsigned int); delay->line_count = line_count = 1; delay->read_index = 0; delay->write_index = 0; delay->mem_block = (SANE_Byte *) malloc (bytes_per_line * line_count); if (!delay->mem_block) { XDBG ((3, "%s: no memory for delay block\n", function_name)); return SANE_STATUS_NO_MEM; } delay->lines = (unsigned int **) malloc (sizeof (unsigned int *) * line_count); if (!delay->lines) { free (delay->mem_block); XDBG ((3, "%s: no memory for delay line pointers\n", function_name)); return SANE_STATUS_NO_MEM; } for (i = 0; i < line_count; ++i) delay->lines[i] = (unsigned int *) (delay->mem_block + i * bytes_per_line); return SANE_STATUS_GOOD; } static SANE_Status artec48u_delay_buffer_done (Artec48U_Delay_Buffer * delay) { if (delay->lines) { free (delay->lines); delay->lines = NULL; } if (delay->mem_block) { free (delay->mem_block); delay->mem_block = NULL; } return SANE_STATUS_GOOD; } #define DELAY_BUFFER_WRITE_PTR(delay) ( (delay)->lines[(delay)->write_index] ) #define DELAY_BUFFER_READ_PTR(delay) ( (delay)->lines[(delay)->read_index ] ) #define DELAY_BUFFER_STEP(delay) \ do { \ (delay)->read_index = ((delay)->read_index + 1) % (delay)->line_count; \ (delay)->write_index = ((delay)->write_index + 1) % (delay)->line_count; \ } while (SANE_FALSE) static inline void unpack_8_mono (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line) { XDBG ((3, "unpack_8_mono\n")); for (; pixels_per_line > 0; ++src, ++dst, --pixels_per_line) { *dst = (((unsigned int) *src) << 8) | *src; } } static inline void unpack_16_le_mono (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line) { XDBG ((3, "unpack_16_le_mono\n")); for (; pixels_per_line > 0; src += 2, dst++, --pixels_per_line) { *dst = (((unsigned int) src[1]) << 8) | src[0]; } } static SANE_Status line_read_gray_8 (Artec48U_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; unsigned int *buffer; XDBG ((3, "line_read_gray_8\n")); size = reader->params.scan_bpl; status = artec48u_device_read (reader->dev, reader->pixel_buffer, &size); if (status != SANE_STATUS_GOOD) return status; buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[0] = buffer; unpack_8_mono (reader->pixel_buffer, buffer, reader->pixels_per_line); return SANE_STATUS_GOOD; } static SANE_Status line_read_gray_16 (Artec48U_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; unsigned int *buffer; XDBG ((3, "line_read_gray_16\n")); size = reader->params.scan_bpl; status = artec48u_device_read (reader->dev, reader->pixel_buffer, &size); if (status != SANE_STATUS_GOOD) return status; buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[0] = buffer; unpack_16_le_mono (reader->pixel_buffer, buffer, reader->pixels_per_line); return SANE_STATUS_GOOD; } static SANE_Status line_read_bgr_8_line_mode (Artec48U_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; XDBG ((3, "line_read_bgr_8_line_mode\n")); size = reader->params.scan_bpl * 3; status = artec48u_device_read (reader->dev, pixel_buffer, &size); if (status != SANE_STATUS_GOOD) return status; pixels_per_line = reader->pixels_per_line; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_bgr_16_line_mode (Artec48U_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; XDBG ((3, "line_read_bgr_16_line_mode\n")); size = reader->params.scan_bpl * 3; status = artec48u_device_read (reader->dev, pixel_buffer, &size); if (status != SANE_STATUS_GOOD) return status; pixels_per_line = reader->pixels_per_line; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status artec48u_line_reader_init_delays (Artec48U_Line_Reader * reader) { SANE_Status status; if (reader->params.color) { status = artec48u_delay_buffer_init (&reader->r_delay, reader->params.pixel_xs); if (status != SANE_STATUS_GOOD) return status; status = artec48u_delay_buffer_init (&reader->g_delay, reader->params.pixel_xs); if (status != SANE_STATUS_GOOD) { artec48u_delay_buffer_done (&reader->r_delay); return status; } status = artec48u_delay_buffer_init (&reader->b_delay, reader->params.pixel_xs); if (status != SANE_STATUS_GOOD) { artec48u_delay_buffer_done (&reader->g_delay); artec48u_delay_buffer_done (&reader->r_delay); return status; } } else { status = artec48u_delay_buffer_init (&reader->g_delay, reader->params.pixel_xs); if (status != SANE_STATUS_GOOD) return status; } reader->delays_initialized = SANE_TRUE; return SANE_STATUS_GOOD; } static void artec48u_line_reader_free_delays (Artec48U_Line_Reader * reader) { if (!reader) { return; } if (reader->delays_initialized) { if (reader->params.color) { artec48u_delay_buffer_done (&reader->b_delay); artec48u_delay_buffer_done (&reader->g_delay); artec48u_delay_buffer_done (&reader->r_delay); } else { artec48u_delay_buffer_done (&reader->g_delay); } reader->delays_initialized = SANE_FALSE; } } static SANE_Status artec48u_line_reader_new (Artec48U_Device * dev, Artec48U_Scan_Parameters * params, Artec48U_Line_Reader ** reader_return) { DECLARE_FUNCTION_NAME ("artec48u_line_reader_new") SANE_Status status; Artec48U_Line_Reader *reader; SANE_Int image_size; SANE_Int scan_bpl_full; XDBG ((6, "%s: enter\n", function_name)); XDBG ((6, "%s: enter params xdpi: %i\n", function_name, params->xdpi)); XDBG ((6, "%s: enter params ydpi: %i\n", function_name, params->ydpi)); XDBG ((6, "%s: enter params depth: %i\n", function_name, params->depth)); XDBG ((6, "%s: enter params color: %i\n", function_name, params->color)); XDBG ((6, "%s: enter params pixel_xs: %i\n", function_name, params->pixel_xs)); XDBG ((6, "%s: enter params pixel_ys: %i\n", function_name, params->pixel_ys)); XDBG ((6, "%s: enter params scan_xs: %i\n", function_name, params->scan_xs)); XDBG ((6, "%s: enter params scan_ys: %i\n", function_name, params->scan_ys)); XDBG ((6, "%s: enter params scan_bpl: %i\n", function_name, params->scan_bpl)); *reader_return = NULL; reader = (Artec48U_Line_Reader *) malloc (sizeof (Artec48U_Line_Reader)); if (!reader) { XDBG ((3, "%s: cannot allocate Artec48U_Line_Reader\n", function_name)); return SANE_STATUS_NO_MEM; } memset (reader, 0, sizeof (Artec48U_Line_Reader)); reader->dev = dev; memcpy (&reader->params, params, sizeof (Artec48U_Scan_Parameters)); reader->pixel_buffer = 0; reader->delays_initialized = SANE_FALSE; reader->read = NULL; status = artec48u_line_reader_init_delays (reader); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: cannot allocate line buffers: %s\n", function_name, sane_strstatus (status))); free (reader); return status; } reader->pixels_per_line = reader->params.pixel_xs; if (!reader->params.color) { XDBG ((2, "!reader->params.color\n")); if (reader->params.depth == 8) reader->read = line_read_gray_8; else if (reader->params.depth == 16) reader->read = line_read_gray_16; } else { XDBG ((2, "reader line mode\n")); if (reader->params.depth == 8) { XDBG ((2, "depth 8\n")); reader->read = line_read_bgr_8_line_mode; } else if (reader->params.depth == 16) { XDBG ((2, "depth 16\n")); reader->read = line_read_bgr_16_line_mode; } } if (reader->read == NULL) { XDBG ((3, "%s: unsupported bit depth (%d)\n", function_name, reader->params.depth)); artec48u_line_reader_free_delays (reader); free (reader); return SANE_STATUS_UNSUPPORTED; } scan_bpl_full = reader->params.scan_bpl; if (reader->params.color) scan_bpl_full *= 3; reader->pixel_buffer = malloc (scan_bpl_full); if (!reader->pixel_buffer) { XDBG ((3, "%s: cannot allocate pixel buffer\n", function_name)); artec48u_line_reader_free_delays (reader); free (reader); return SANE_STATUS_NO_MEM; } artec48u_device_set_read_buffer_size (reader->dev, scan_bpl_full /* 200 */ ); image_size = scan_bpl_full * reader->params.scan_ys; status = artec48u_device_read_prepare (reader->dev, image_size); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: artec48u_device_read_prepare failed: %s\n", function_name, sane_strstatus (status))); free (reader->pixel_buffer); artec48u_line_reader_free_delays (reader); free (reader); return status; } XDBG ((6, "%s: leave: ok\n", function_name)); *reader_return = reader; return SANE_STATUS_GOOD; } static SANE_Status artec48u_line_reader_free (Artec48U_Line_Reader * reader) { DECLARE_FUNCTION_NAME ("artec48u_line_reader_free") SANE_Status status; XDBG ((6, "%s: enter\n", function_name)); if (!reader) { return SANE_STATUS_GOOD; } artec48u_line_reader_free_delays (reader); if (reader->pixel_buffer) { free (reader->pixel_buffer); reader->pixel_buffer = NULL; } status = artec48u_device_read_finish (reader->dev); if (status != SANE_STATUS_GOOD) { XDBG ((3, "%s: artec48u_device_read_finish failed: %s\n", function_name, sane_strstatus (status))); } if (reader) free (reader); XDBG ((6, "%s: leave\n", function_name)); return status; } static SANE_Status artec48u_line_reader_read (Artec48U_Line_Reader * reader, unsigned int **buffer_pointers_return) { return (*reader->read) (reader, buffer_pointers_return); } static SANE_Status artec48u_scanner_new (Artec48U_Device * dev, Artec48U_Scanner ** scanner_return) { DECLARE_FUNCTION_NAME ("artec48u_scanner_new") Artec48U_Scanner *s; *scanner_return = NULL; s = (Artec48U_Scanner *) malloc (sizeof (Artec48U_Scanner)); if (!s) { XDBG ((5, "%s: no memory for Artec48U_Scanner\n", function_name)); return SANE_STATUS_NO_MEM; } s->dev = dev; s->reader = NULL; s->scanning = SANE_FALSE; s->line_buffer = NULL; s->lineart_buffer = NULL; s->next = NULL; s->pipe_handle = NULL; s->buffer_pointers[0] = NULL; s->buffer_pointers[1] = NULL; s->buffer_pointers[2] = NULL; s->shading_buffer_w = NULL; s->shading_buffer_b = NULL; s->shading_buffer_white[0] = NULL; s->shading_buffer_white[1] = NULL; s->shading_buffer_white[2] = NULL; s->shading_buffer_black[0] = NULL; s->shading_buffer_black[1] = NULL; s->shading_buffer_black[2] = NULL; *scanner_return = s; return SANE_STATUS_GOOD; } static SANE_Status artec48u_scanner_read_line (Artec48U_Scanner * s, unsigned int **buffer_pointers, SANE_Bool shading) { DECLARE_FUNCTION_NAME ("artec48u_scanner_read_line") SANE_Status status; int i, j, c; status = artec48u_line_reader_read (s->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { XDBG ((5, "%s: artec48u_line_reader_read failed: %s\n", function_name, sane_strstatus (status))); return status; } if (shading != SANE_TRUE) return status; c = s->reader->pixels_per_line; if (s->reader->params.color == SANE_TRUE) { for (i = c - 1; i >= 0; i--) { for (j = 0; j < 3; j++) { int new_value; unsigned int value = buffer_pointers[j][i]; if (value < s->shading_buffer_black[j][i]) value = s->shading_buffer_black[j][i]; if (value > s->shading_buffer_white[j][i]) value = s->shading_buffer_white[j][i]; new_value = (double) (value - s->shading_buffer_black[j][i]) * 65535.0 / (double) (s->shading_buffer_white[j][i] - s->shading_buffer_black[j][i]); if (new_value < 0) new_value = 0; if (new_value > 65535) new_value = 65535; new_value = s->gamma_array[j + 1][s->contrast_array[s-> brightness_array [new_value]]]; new_value = s->gamma_array[0][new_value]; buffer_pointers[j][i] = new_value; } } } else { for (i = c - 1; i >= 0; i--) { int new_value; unsigned int value = buffer_pointers[0][i]; new_value = (double) (value - s->shading_buffer_black[1][i]) * 65535.0 / (double) (s->shading_buffer_white[1][i] - s->shading_buffer_black[1][i]); if (new_value < 0) new_value = 0; if (new_value > 65535) new_value = 65535; new_value = s->gamma_array[0][s-> contrast_array[s->brightness_array[new_value]]]; buffer_pointers[0][i] = new_value; } } return status; } static SANE_Status artec48u_scanner_free (Artec48U_Scanner * s) { DECLARE_FUNCTION_NAME ("artec48u_scanner_free") if (!s) { XDBG ((5, "%s: scanner==NULL\n", function_name)); return SANE_STATUS_INVAL; } if (s->reader) { artec48u_line_reader_free (s->reader); s->reader = NULL; } free (s->shading_buffer_w); free (s->shading_buffer_b); free (s->shading_buffer_white[0]); free (s->shading_buffer_black[0]); free (s->shading_buffer_white[1]); free (s->shading_buffer_black[1]); free (s->shading_buffer_white[2]); free (s->shading_buffer_black[2]); if (s->line_buffer) free (s->line_buffer); if (s->lineart_buffer) free (s->lineart_buffer); free (s); return SANE_STATUS_GOOD; } static SANE_Status artec48u_scanner_internal_start_scan (Artec48U_Scanner * s) { DECLARE_FUNCTION_NAME ("artec48u_scanner_internal_start_scan") SANE_Status status; SANE_Bool ready; SANE_Int repeat_count; status = artec48u_wait_for_positioning (s->dev); if (status != SANE_STATUS_GOOD) { XDBG ((2, "%s: artec48u_scanner_wait_for_positioning error: %s\n", function_name, sane_strstatus (status))); return status; } status = artec48u_generic_start_scan (s->dev); if (status != SANE_STATUS_GOOD) { XDBG ((2, "%s: artec48u_device_start_scan error: %s\n", function_name, sane_strstatus (status))); return status; } for (repeat_count = 0; repeat_count < 30 * 10; ++repeat_count) { status = artec48u_generic_read_scanned_data (s->dev, &ready); if (status != SANE_STATUS_GOOD) { XDBG ((2, "%s: artec48u_device_read_scanned_data error: %s\n", function_name, sane_strstatus (status))); return status; } if (ready) break; usleep (100000); } if (!ready) { XDBG ((2, "%s: scanner still not ready - giving up\n", function_name)); return SANE_STATUS_DEVICE_BUSY; } status = artec48u_device_read_start (s->dev); if (status != SANE_STATUS_GOOD) { XDBG ((2, "%s: artec48u_device_read_start error: %s\n", function_name, sane_strstatus (status))); return status; } return SANE_STATUS_GOOD; } static SANE_Status artec48u_scanner_start_scan_extended (Artec48U_Scanner * s, Artec48U_Scan_Request * request, Artec48U_Scan_Action action, Artec48U_Scan_Parameters * params) { DECLARE_FUNCTION_NAME ("artec48u_scanner_start_scan_extended") SANE_Status status; status = artec48u_wait_for_positioning (s->dev); if (status != SANE_STATUS_GOOD) { XDBG ((2, "%s: artec48u_scanner_wait_for_positioning error: %s\n", function_name, sane_strstatus (status))); return status; } if (action == SA_SCAN) status = artec48u_setup_scan (s, request, action, SANE_FALSE, params); if (status != SANE_STATUS_GOOD) { XDBG ((2, "%s: artec48u_device_setup_scan failed: %s\n", function_name, sane_strstatus (status))); return status; } status = artec48u_line_reader_new (s->dev, params, &s->reader); if (status != SANE_STATUS_GOOD) { XDBG ((2, "%s: artec48u_line_reader_new failed: %s\n", function_name, sane_strstatus (status))); return status; } status = artec48u_scanner_internal_start_scan (s); if (status != SANE_STATUS_GOOD) { XDBG ((2, "%s: artec48u_scanner_internal_start_scan failed: %s\n", function_name, sane_strstatus (status))); return status; } return SANE_STATUS_GOOD; } static SANE_Status artec48u_scanner_start_scan (Artec48U_Scanner * s, Artec48U_Scan_Request * request, Artec48U_Scan_Parameters * params) { return artec48u_scanner_start_scan_extended (s, request, SA_SCAN, params); } static SANE_Status artec48u_scanner_stop_scan (Artec48U_Scanner * s) { XDBG ((1, "artec48u_scanner_stop_scan begin: \n")); artec48u_line_reader_free (s->reader); s->reader = NULL; return artec48u_stop_scan (s->dev); } static void calculateGamma (Artec48U_Scanner * s) { double d; int gval; unsigned int i; double gamma = SANE_UNFIX (s->val[OPT_GAMMA].w); d = 65536.0 / pow (65536.0, 1.0 / gamma); for (i = 0; i < 65536; i++) { gval = (int) (pow ((double) i, 1.0 / gamma) * d); s->gamma_array[0][i] = gval; } } static void calculateGammaRed (Artec48U_Scanner * s) { double d; int gval; unsigned int i; double gamma = SANE_UNFIX (s->val[OPT_GAMMA_R].w); d = 65536.0 / pow (65536.0, 1.0 / gamma); for (i = 0; i < 65536; i++) { gval = (int) (pow ((double) i, 1.0 / gamma) * d); s->gamma_array[1][i] = gval; } } static void calculateGammaGreen (Artec48U_Scanner * s) { double d; int gval; unsigned int i; double gamma = SANE_UNFIX (s->val[OPT_GAMMA_G].w); d = 65536.0 / pow (65536.0, 1.0 / gamma); for (i = 0; i < 65536; i++) { gval = (int) (pow ((double) i, 1.0 / gamma) * d); s->gamma_array[2][i] = gval; } } static void calculateGammaBlue (Artec48U_Scanner * s) { double d; int gval; unsigned int i; double gamma = SANE_UNFIX (s->val[OPT_GAMMA_B].w); d = 65536.0 / pow (65536.0, 1.0 / gamma); for (i = 0; i < 65536; i++) { gval = (int) (pow ((double) i, 1.0 / gamma) * d); s->gamma_array[3][i] = gval; } } static SANE_Status artec48u_calculate_shading_buffer (Artec48U_Scanner * s, int start, int end, int resolution, SANE_Bool color) { int i; int c; int bpp; c = 0; bpp = 6; switch (resolution) { case 50: bpp = 72; break; case 100: bpp = 36; break; case 200: bpp = 18; break; case 300: bpp = 12; break; case 600: bpp = 6; break; case 1200: if(s->dev->is_epro == 0) bpp = 6; else bpp = 3; } for (i = start * bpp; i < end * bpp; i += bpp) { if (color) { s->shading_buffer_white[0][c] = (unsigned int) s->shading_buffer_w[i] + ((((unsigned int) s->shading_buffer_w[i + 1]) << 8)); s->shading_buffer_white[2][c] = (unsigned int) s->shading_buffer_w[i + 4] + ((((unsigned int) s->shading_buffer_w[i + 5]) << 8)); s->shading_buffer_black[0][c] = (unsigned int) s->shading_buffer_b[i] + ((((unsigned int) s->shading_buffer_b[i + 1]) << 8)); s->shading_buffer_black[2][c] = (unsigned int) s->shading_buffer_b[i + 4] + ((((unsigned int) s->shading_buffer_b[i + 5]) << 8)); } s->shading_buffer_white[1][c] = (unsigned int) s->shading_buffer_w[i + 2] + ((((unsigned int) s->shading_buffer_w[i + 3]) << 8)); s->shading_buffer_black[1][c] = (unsigned int) s->shading_buffer_b[i + 2] + ((((unsigned int) s->shading_buffer_b[i + 3]) << 8)); ++c; } return SANE_STATUS_GOOD; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status init_options (Artec48U_Scanner * s) { int i; XDBG ((5, "init_options: scanner %p\n", (void *) s)); XDBG ((5, "init_options: start\n")); XDBG ((5, "init_options: num options %i\n", NUM_OPTIONS)); memset (s->val, 0, sizeof (s->val)); memset (s->opt, 0, sizeof (s->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; s->opt[OPT_MODE_GROUP].name = "scanmode-group"; s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].unit = SANE_UNIT_NONE; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_SCAN_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_SCAN_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_SCAN_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_SCAN_MODE].type = SANE_TYPE_STRING; s->opt[OPT_SCAN_MODE].size = max_string_size (mode_list); s->opt[OPT_SCAN_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SCAN_MODE].constraint.string_list = mode_list; s->val[OPT_SCAN_MODE].s = strdup (mode_list[1]); s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE; s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_BIT_DEPTH].constraint.word_list = bitdepth_list; s->val[OPT_BIT_DEPTH].w = bitdepth_list[1]; /* black level (lineart only) */ s->opt[OPT_BLACK_LEVEL].name = SANE_NAME_BLACK_LEVEL; s->opt[OPT_BLACK_LEVEL].title = SANE_TITLE_BLACK_LEVEL; s->opt[OPT_BLACK_LEVEL].desc = SANE_DESC_BLACK_LEVEL; s->opt[OPT_BLACK_LEVEL].type = SANE_TYPE_INT; s->opt[OPT_BLACK_LEVEL].unit = SANE_UNIT_NONE; s->opt[OPT_BLACK_LEVEL].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BLACK_LEVEL].constraint.range = &blacklevel_range; s->opt[OPT_BLACK_LEVEL].cap |= SANE_CAP_INACTIVE; s->val[OPT_BLACK_LEVEL].w = 127; s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = resbit_list; s->val[OPT_RESOLUTION].w = resbit_list[1]; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].name = "enhancement-group"; s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &brightness_contrast_range; s->val[OPT_BRIGHTNESS].w = 0; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &brightness_contrast_range; s->val[OPT_CONTRAST].w = 0; /* master analog gamma */ s->opt[OPT_GAMMA].name = SANE_NAME_ANALOG_GAMMA; s->opt[OPT_GAMMA].title = SANE_TITLE_ANALOG_GAMMA; s->opt[OPT_GAMMA].desc = SANE_DESC_ANALOG_GAMMA; s->opt[OPT_GAMMA].type = SANE_TYPE_FIXED; s->opt[OPT_GAMMA].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA].constraint.range = &gamma_range; s->val[OPT_GAMMA].w = SANE_FIX (s->dev->gamma_master); s->opt[OPT_GAMMA].size = sizeof (SANE_Word); /* red analog gamma */ s->opt[OPT_GAMMA_R].name = SANE_NAME_ANALOG_GAMMA_R; s->opt[OPT_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R; s->opt[OPT_GAMMA_R].desc = SANE_DESC_ANALOG_GAMMA_R; s->opt[OPT_GAMMA_R].type = SANE_TYPE_FIXED; s->opt[OPT_GAMMA_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_R].constraint.range = &gamma_range; s->val[OPT_GAMMA_R].w = SANE_FIX (s->dev->gamma_r); /* green analog gamma */ s->opt[OPT_GAMMA_G].name = SANE_NAME_ANALOG_GAMMA_G; s->opt[OPT_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G; s->opt[OPT_GAMMA_G].desc = SANE_DESC_ANALOG_GAMMA_G; s->opt[OPT_GAMMA_G].type = SANE_TYPE_FIXED; s->opt[OPT_GAMMA_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_G].constraint.range = &gamma_range; s->val[OPT_GAMMA_G].w = SANE_FIX (s->dev->gamma_g); /* blue analog gamma */ s->opt[OPT_GAMMA_B].name = SANE_NAME_ANALOG_GAMMA_B; s->opt[OPT_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B; s->opt[OPT_GAMMA_B].desc = SANE_DESC_ANALOG_GAMMA_B; s->opt[OPT_GAMMA_B].type = SANE_TYPE_FIXED; s->opt[OPT_GAMMA_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_B].constraint.range = &gamma_range; s->val[OPT_GAMMA_B].w = SANE_FIX (s->dev->gamma_b); s->opt[OPT_DEFAULT_ENHANCEMENTS].name = "default-enhancements"; s->opt[OPT_DEFAULT_ENHANCEMENTS].title = SANE_I18N ("Defaults"); s->opt[OPT_DEFAULT_ENHANCEMENTS].desc = SANE_I18N ("Set default values for enhancement controls."); s->opt[OPT_DEFAULT_ENHANCEMENTS].size = 0; s->opt[OPT_DEFAULT_ENHANCEMENTS].type = SANE_TYPE_BUTTON; s->opt[OPT_DEFAULT_ENHANCEMENTS].unit = SANE_UNIT_NONE; s->opt[OPT_DEFAULT_ENHANCEMENTS].constraint_type = SANE_CONSTRAINT_NONE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].name = "geometry-group"; s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = 0; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &scan_range_x; s->val[OPT_TL_X].w = SANE_FIX (0.0); /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &scan_range_y; s->val[OPT_TL_Y].w = SANE_FIX (0.0); /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &scan_range_x; s->val[OPT_BR_X].w = SANE_FIX (50.0); /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &scan_range_y; s->val[OPT_BR_Y].w = SANE_FIX (50.0); /* "Calibration" group: */ s->opt[OPT_CALIBRATION_GROUP].name = "calibration-group"; s->opt[OPT_CALIBRATION_GROUP].title = SANE_I18N ("Calibration"); s->opt[OPT_CALIBRATION_GROUP].desc = ""; s->opt[OPT_CALIBRATION_GROUP].size = 0; s->opt[OPT_CALIBRATION_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_CALIBRATION_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_CALIBRATION_GROUP].cap = 0; /* calibrate */ s->opt[OPT_CALIBRATE].name = "calibration"; s->opt[OPT_CALIBRATE].title = SANE_I18N ("Calibrate before next scan"); s->opt[OPT_CALIBRATE].desc = SANE_I18N ("If enabled, the device will be calibrated before the " "next scan. Otherwise, calibration is performed " "only before the first start."); s->opt[OPT_CALIBRATE].type = SANE_TYPE_BOOL; s->opt[OPT_CALIBRATE].unit = SANE_UNIT_NONE; s->opt[OPT_CALIBRATE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_CALIBRATE].w = SANE_FALSE; /* calibrate */ s->opt[OPT_CALIBRATE_SHADING].name = "calibration-shading"; s->opt[OPT_CALIBRATE_SHADING].title = SANE_I18N ("Only perform shading-correction"); s->opt[OPT_CALIBRATE_SHADING].desc = SANE_I18N ("If enabled, only the shading correction is " "performed during calibration. The default values " "for gain, offset and exposure time, " "either build-in or from the configuration file, " "are used."); s->opt[OPT_CALIBRATE_SHADING].type = SANE_TYPE_BOOL; s->opt[OPT_CALIBRATE_SHADING].unit = SANE_UNIT_NONE; s->opt[OPT_CALIBRATE_SHADING].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_CALIBRATE_SHADING].w = SANE_FALSE; #ifdef ARTEC48U_USE_BUTTONS s->opt[OPT_BUTTON_STATE].name = "button-state"; s->opt[OPT_BUTTON_STATE].title = SANE_I18N ("Button state"); s->opt[OPT_BUTTON_STATE].type = SANE_TYPE_INT; s->opt[OPT_BUTTON_STATE].unit = SANE_UNIT_NONE; s->opt[OPT_BUTTON_STATE].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_BUTTON_STATE].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_BUTTON_STATE].w = 0; #endif return SANE_STATUS_GOOD; } static void calculate_brightness (Artec48U_Scanner * s) { long cnt; double bright; bright = (double) s->val[OPT_BRIGHTNESS].w; bright *= 257.0; for (cnt = 0; cnt < 65536; cnt++) { if (bright < 0.0) s->brightness_array[cnt] = (int) (((double) cnt * (65535.0 + bright)) / 65535.0); else s->brightness_array[cnt] = (int) ((double) cnt + ((65535.0 - (double) cnt) * bright) / 65535.0); if (s->brightness_array[cnt] > 65535) s->brightness_array[cnt] = 65535; if (s->brightness_array[cnt] < 0) s->brightness_array[cnt] = 0; } } static void calculate_contrast (Artec48U_Scanner * s) { int val; double p; int cnt; double contr; contr = (double) s->val[OPT_CONTRAST].w; contr *= 257.0; for (cnt = 0; cnt < 65536; cnt++) { if (contr < 0.0) { val = (int) (cnt > 32769) ? (65535 - cnt) : cnt; val = (int) (32769.0 * pow ((double) (val ? val : 1) / 32769.0, (32769.0 + contr) / 32769.0)); s->contrast_array[cnt] = (cnt > 32769) ? (65535 - val) : val; if (s->contrast_array[cnt] > 65535) s->contrast_array[cnt] = 65535; if (s->contrast_array[cnt] < 0) s->contrast_array[cnt] = 0; } else { val = (cnt > 32769) ? (65535 - cnt) : cnt; p = ((int) contr == 32769) ? 32769.0 : 32769.0 / (32769.0 - contr); val = (int) (32769.0 * pow ((double) val / 32769.0, p)); s->contrast_array[cnt] = (cnt > 32639) ? (65535 - val) : val; if (s->contrast_array[cnt] > 65535) s->contrast_array[cnt] = 65535; if (s->contrast_array[cnt] < 0) s->contrast_array[cnt] = 0; } } } /* The calibration function Disclaimer: the following might be complete crap :-) -Gain, offset, exposure time It seems, that the gain values are actually constants. The windows driver always uses the values 0x0a,0x03,0x03, during calibration as well as during a normal scan. The exposure values are set to 0x04 for black calibration. It's not necessary to move the scan head during this stage. Calibration starts with default values for offset/exposure. These values are increased/decreased until the white and black values are within a specific range, defined by WHITE_MIN, WHITE_MAX, BLACK_MIN and BLACK_MAX. -White shading correction The scanning head is moved some lines over the calibration strip. Some lines are scanned at 600dpi/16bit over the full width. The average values are used for the shading buffer. The normal exposure values are used. -Black shading correction Works like the white shading correction, with the difference, that the red-, green- and blue exposure time is set to 0x04 (the value is taken from the windoze driver). -Since we do this over the whole width of the image with the maximal optical resolution, we can use the shading data for every scan, independend of the size, position or resolution, because we have the shading values for every sensor/LED. Note: For a CIS device, it's sufficient to determine those values once. It's not necessary, to repeat the calibration sequence before every new scan. The windoze driver even saves the values to various files to avoid the quite lengthy calibration sequence. This backend can also save the values to files. For this purpose, the user has to create a hidden directory called .artec-eplus48u in his/her home directory. If the user insists on calibration before every new scan, he/she can enable a specific option in the backend. */ static SANE_Status calibrate_scanner (SANE_Handle handle) { Artec48U_Scanner *s = handle; unsigned int *buffer_pointers[3]; int avg_black[3]; int avg_white[3]; int exp_off; int c; int finish = 0; int noloop = 0; if ((s->val[OPT_CALIBRATE].w == SANE_TRUE) && (s->val[OPT_CALIBRATE_SHADING].w == SANE_FALSE)) { while (finish == 0) { finish = 1; /*get black values */ artec48u_carriage_home (s->dev); artec48u_wait_for_positioning (s->dev); s->reader = NULL; s->scanning = SANE_TRUE; init_shading_buffer (s); artec48u_setup_scan (s, &(s->request), SA_CALIBRATE_SCAN_BLACK, SANE_FALSE, &(s->params)); artec48u_scanner_start_scan_extended (s, &(s->request), SA_CALIBRATE_SCAN_OFFSET_1, &(s->params)); for (c = 0; c < s->dev->shading_lines_b; c++) { artec48u_scanner_read_line (s, buffer_pointers, SANE_FALSE); /* we abuse the shading buffer for the offset calculation */ add_to_shading_buffer (s, buffer_pointers); } artec48u_scanner_stop_scan (s); finish_offset_buffer (s, &avg_black[0], &avg_black[1], &avg_black[2]); s->scanning = SANE_FALSE; XDBG ((1, "avg_r: %i, avg_g: %i, avg_b: %i\n", avg_black[0], avg_black[1], avg_black[2])); /*adjust offset */ for (c = 0; c < 3; c++) { if (c == 0) { if (avg_black[c] < BLACK_MIN) { s->dev->afe_params.r_offset -= 1; finish = 0; XDBG ((1, "adjust offset r: -1\n")); } else if (avg_black[c] > BLACK_MAX) { s->dev->afe_params.r_offset += 1; finish = 0; XDBG ((1, "adjust offset r: +1\n")); } } if (c == 1) { if (avg_black[c] < BLACK_MIN) { s->dev->afe_params.g_offset -= 1; finish = 0; XDBG ((1, "adjust offset g: -1\n")); } else if (avg_black[c] > BLACK_MAX) { s->dev->afe_params.g_offset += 1; finish = 0; XDBG ((1, "adjust offset g: +1\n")); } } if (c == 2) { if (avg_black[c] < BLACK_MIN) { s->dev->afe_params.b_offset -= 1; finish = 0; XDBG ((1, "adjust offset b: -1\n")); } else if (avg_black[c] > BLACK_MAX) { s->dev->afe_params.b_offset += 1; finish = 0; XDBG ((1, "adjust offset b: +1\n")); } } } /*adjust exposure */ /*get white values */ artec48u_carriage_home (s->dev); artec48u_wait_for_positioning (s->dev); s->reader = NULL; s->scanning = SANE_TRUE; init_shading_buffer (s); artec48u_setup_scan (s, &(s->request), SA_CALIBRATE_SCAN_WHITE, SANE_FALSE, &(s->params)); artec48u_scanner_start_scan_extended (s, &(s->request), SA_CALIBRATE_SCAN_EXPOSURE_1, &(s->params)); for (c = 0; c < s->dev->shading_lines_w; c++) { artec48u_scanner_read_line (s, buffer_pointers, SANE_FALSE); /* we abuse the shading buffer for the exposure calculation */ add_to_shading_buffer (s, buffer_pointers); } artec48u_scanner_stop_scan (s); finish_exposure_buffer (s, &avg_white[0], &avg_white[1], &avg_white[2]); s->scanning = SANE_FALSE; XDBG ((1, "avg_r: %i, avg_g: %i, avg_b: %i\n", avg_white[0], avg_white[1], avg_white[2])); for (c = 0; c < 3; c++) { if (c == 0) { if (avg_white[c] < WHITE_MIN) { exp_off = ((WHITE_MAX + WHITE_MIN) / 2 - avg_white[c]) / EXPOSURE_STEP; if (exp_off < 1) exp_off = 1; s->dev->exp_params.r_time += exp_off; finish = 0; XDBG ((1, "adjust exposure r: ++\n")); } else if (avg_white[c] > WHITE_MAX) { exp_off = (avg_white[c] - (WHITE_MAX + WHITE_MIN) / 2) / EXPOSURE_STEP; if (exp_off < 1) exp_off = 1; s->dev->exp_params.r_time -= exp_off; finish = 0; XDBG ((1, "adjust exposure r: --\n")); } } else if (c == 1) { if (avg_white[c] < WHITE_MIN) { exp_off = ((WHITE_MAX + WHITE_MIN) / 2 - avg_white[c]) / EXPOSURE_STEP; if (exp_off < 1) exp_off = 1; s->dev->exp_params.g_time += exp_off; finish = 0; XDBG ((1, "adjust exposure g: ++\n")); } else if (avg_white[c] > WHITE_MAX) { exp_off = (avg_white[c] - (WHITE_MAX + WHITE_MIN) / 2) / EXPOSURE_STEP; if (exp_off < 1) exp_off = 1; s->dev->exp_params.g_time -= exp_off; finish = 0; XDBG ((1, "adjust exposure g: --\n")); } } else if (c == 2) { if (avg_white[c] < WHITE_MIN) { exp_off = ((WHITE_MAX + WHITE_MIN) / 2 - avg_white[c]) / EXPOSURE_STEP; if (exp_off < 1) exp_off = 1; s->dev->exp_params.b_time += exp_off; finish = 0; XDBG ((1, "adjust exposure b: ++\n")); } else if (avg_white[c] > WHITE_MAX) { exp_off = (avg_white[c] - (WHITE_MAX + WHITE_MIN) / 2) / EXPOSURE_STEP; if (exp_off < 1) exp_off = 1; s->dev->exp_params.b_time -= exp_off; finish = 0; XDBG ((1, "adjust exposure b: --\n")); } } } XDBG ((1, "time_r: %x, time_g: %x, time_b: %x\n", s->dev->exp_params.r_time, s->dev->exp_params.g_time, s->dev->exp_params.b_time)); XDBG ((1, "offset_r: %x, offset_g: %x, offset_b: %x\n", s->dev->afe_params.r_offset, s->dev->afe_params.g_offset, s->dev->afe_params.b_offset)); ++noloop; if (noloop > 10) break; } } XDBG ((1, "option redOffset 0x%x\n", s->dev->afe_params.r_offset)); XDBG ((1, "option greenOffset 0x%x\n", s->dev->afe_params.g_offset)); XDBG ((1, "option blueOffset 0x%x\n", s->dev->afe_params.b_offset)); XDBG ((1, "option redExposure 0x%x\n", s->dev->exp_params.r_time)); XDBG ((1, "option greenExposure 0x%x\n", s->dev->exp_params.g_time)); XDBG ((1, "option blueExposure 0x%x\n", s->dev->exp_params.b_time)); s->dev->artec_48u_afe_params.r_offset = s->dev->afe_params.r_offset; s->dev->artec_48u_afe_params.g_offset = s->dev->afe_params.g_offset; s->dev->artec_48u_afe_params.b_offset = s->dev->afe_params.b_offset; /*don't forget the gain */ s->dev->artec_48u_afe_params.r_pga = s->dev->afe_params.r_pga; s->dev->artec_48u_afe_params.g_pga = s->dev->afe_params.g_pga; s->dev->artec_48u_afe_params.b_pga = s->dev->afe_params.b_pga; s->dev->artec_48u_exposure_params.r_time = s->dev->exp_params.r_time; s->dev->artec_48u_exposure_params.g_time = s->dev->exp_params.g_time; s->dev->artec_48u_exposure_params.b_time = s->dev->exp_params.b_time; /******************************* *get the black shading values * *******************************/ artec48u_carriage_home (s->dev); artec48u_wait_for_positioning (s->dev); s->reader = NULL; s->scanning = SANE_TRUE; init_shading_buffer (s); artec48u_setup_scan (s, &(s->request), SA_CALIBRATE_SCAN_BLACK, SANE_FALSE, &(s->params)); artec48u_scanner_start_scan_extended (s, &(s->request), SA_CALIBRATE_SCAN_BLACK, &(s->params)); for (c = 0; c < s->dev->shading_lines_b; c++) { artec48u_scanner_read_line (s, buffer_pointers, SANE_FALSE); add_to_shading_buffer (s, buffer_pointers); } artec48u_scanner_stop_scan (s); finish_shading_buffer (s, SANE_FALSE); s->scanning = SANE_FALSE; /******************************* *get the white shading values * *******************************/ artec48u_carriage_home (s->dev); artec48u_wait_for_positioning (s->dev); s->reader = NULL; s->scanning = SANE_TRUE; init_shading_buffer (s); artec48u_setup_scan (s, &(s->request), SA_CALIBRATE_SCAN_WHITE, SANE_FALSE, &(s->params)); artec48u_scanner_start_scan_extended (s, &(s->request), SA_CALIBRATE_SCAN_WHITE, &(s->params)); for (c = 0; c < s->dev->shading_lines_w; c++) { artec48u_scanner_read_line (s, buffer_pointers, SANE_FALSE); add_to_shading_buffer (s, buffer_pointers); } artec48u_scanner_stop_scan (s); finish_shading_buffer (s, SANE_TRUE); s->scanning = SANE_FALSE; save_calibration_data (s); return SANE_STATUS_GOOD; } static SANE_Status close_pipe (Artec48U_Scanner * s) { if (s->pipe >= 0) { XDBG ((1, "close_pipe\n")); close (s->pipe); s->pipe = -1; } return SANE_STATUS_EOF; } static void sigalarm_handler (int __sane_unused__ signal) { XDBG ((1, "ALARM!!!\n")); cancelRead = SANE_TRUE; } static void sig_chldhandler (int signo) { XDBG ((1, "Child is down (signal=%d)\n", signo)); } static int reader_process (void * data) { Artec48U_Scanner * s = (Artec48U_Scanner *) data; int fd = s->reader_pipe; SANE_Status status; struct SIGACTION act; sigset_t ignore_set; ssize_t bytes_written = 0; XDBG ((1, "reader process...\n")); if (sanei_thread_is_forked()) close (s->pipe); sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); sigdelset (&ignore_set, SIGUSR1); #if defined (__APPLE__) && defined (__MACH__) sigdelset (&ignore_set, SIGUSR2); #endif sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); sigaction (SIGUSR1, &act, 0); cancelRead = SANE_FALSE; if (sigemptyset (&(act.sa_mask)) < 0) XDBG ((2, "(child) reader_process: sigemptyset() failed\n")); act.sa_flags = 0; act.sa_handler = reader_process_sigterm_handler; if (sigaction (SIGTERM, &act, 0) < 0) XDBG ((2, "(child) reader_process: sigaction(SIGTERM,...) failed\n")); act.sa_handler = usb_reader_process_sigterm_handler; if (sigaction (SIGUSR1, &act, 0) < 0) XDBG ((2, "(child) reader_process: sigaction(SIGUSR1,...) failed\n")); XDBG ((2, "(child) reader_process: s=%p, fd=%d\n", (void *) s, fd)); /*read line by line into buffer */ /*copy buffer pointers to line_buffer */ XDBG ((2, "(child) reader_process: byte_cnt %d\n", (int) s->byte_cnt)); s->eof = SANE_FALSE; while (s->lines_to_read > 0) { if (cancelRead == SANE_TRUE) { XDBG ((2, "(child) reader_process: cancelRead == SANE_TRUE\n")); s->scanning = SANE_FALSE; s->eof = SANE_FALSE; return SANE_STATUS_CANCELLED; } if (s->scanning != SANE_TRUE) { XDBG ((2, "(child) reader_process: scanning != SANE_TRUE\n")); return SANE_STATUS_CANCELLED; } status = artec48u_scanner_read_line (s, s->buffer_pointers, SANE_TRUE); if (status != SANE_STATUS_GOOD) { XDBG ((2, "(child) reader_process: scanner_read_line failed\n")); return SANE_STATUS_IO_ERROR; } copy_scan_line (s); s->lines_to_read -= 1; bytes_written = write (fd, s->line_buffer, s->sane_params.bytes_per_line); if (bytes_written < 0) { XDBG ((2, "(child) reader_process: write returned %s\n", strerror (errno))); s->eof = SANE_FALSE; return SANE_STATUS_IO_ERROR; } XDBG ((2, "(child) reader_process: lines to read %i\n", s->lines_to_read)); } s->eof = SANE_TRUE; close (fd); return SANE_STATUS_GOOD; } static SANE_Status do_cancel (Artec48U_Scanner * s, SANE_Bool closepipe) { struct SIGACTION act; SANE_Pid res; XDBG ((1, "do_cancel\n")); s->scanning = SANE_FALSE; if (sanei_thread_is_valid (s->reader_pid)) { /*parent */ XDBG ((1, "killing reader_process\n")); /* tell the driver to stop scanning */ sigemptyset (&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = sigalarm_handler; if (sigaction (SIGALRM, &act, 0) == -1) XDBG ((1, "sigaction() failed !\n")); /* kill our child process and wait until done */ alarm (10); if (sanei_thread_kill (s->reader_pid) < 0) XDBG ((1, "sanei_thread_kill() failed !\n")); res = sanei_thread_waitpid (s->reader_pid, 0); alarm (0); if (res != s->reader_pid) { XDBG ((1, "sanei_thread_waitpid() failed !\n")); } s->reader_pid = -1; XDBG ((1, "reader_process killed\n")); } if (SANE_TRUE == closepipe) { close_pipe (s); XDBG ((1, "pipe closed\n")); } artec48u_scanner_stop_scan (s); artec48u_carriage_home (s->dev); if (s->line_buffer) { XDBG ((2, "freeing line_buffer\n")); free (s->line_buffer); s->line_buffer = NULL; } if (s->lineart_buffer) { XDBG ((2, "freeing lineart_buffer\n")); free (s->lineart_buffer); s->lineart_buffer = NULL; } return SANE_STATUS_CANCELLED; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { static const SANE_Device **devlist = 0; Artec48U_Device *dev; SANE_Int dev_num; XDBG ((5, "sane_get_devices: start: local_only = %s\n", local_only == SANE_TRUE ? "true" : "false")); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; dev_num = 0; for (dev = first_dev; dev_num < num_devices; dev = dev->next) { devlist[dev_num] = &dev->sane; XDBG ((3, "sane_get_devices: name %s\n", dev->sane.name)); XDBG ((3, "sane_get_devices: vendor %s\n", dev->sane.vendor)); XDBG ((3, "sane_get_devices: model %s\n", dev->sane.model)); ++dev_num; } devlist[dev_num] = 0; ++dev_num; *device_list = devlist; XDBG ((5, "sane_get_devices: exit\n")); return SANE_STATUS_GOOD; } static SANE_Status load_calibration_data (Artec48U_Scanner * s) { SANE_Status status = SANE_STATUS_GOOD; FILE *f = 0; size_t cnt; char path[PATH_MAX]; char filename[PATH_MAX]; s->calibrated = SANE_FALSE; path[0] = 0; /* return SANE_STATUS_INVAL if HOME environment variable is not set */ if (getenv ("HOME") == NULL) { XDBG ((1, "Environment variable HOME not set\n")); return SANE_STATUS_INVAL; } if (strlen (getenv ("HOME")) < (PATH_MAX - 1)) strcat (path, getenv ("HOME")); else return SANE_STATUS_INVAL; if (strlen (path) < (PATH_MAX - 1 - strlen ("/.artec_eplus48u/"))) strcat (path, "/.artec_eplus48u/"); else return SANE_STATUS_INVAL; /*try to load black shading file */ strcpy (filename, path); if (strlen (filename) < (PATH_MAX - 1 - strlen ("artec48ushading_black"))) strcat (filename, "artec48ushading_black"); else return SANE_STATUS_INVAL; XDBG ((1, "Try to read black shading file: \"%s\"\n", filename)); f = fopen (filename, "rb"); if (!f) return SANE_STATUS_INVAL; /*read values */ cnt = fread (s->shading_buffer_b, sizeof (unsigned char), 30720*s->dev->epro_mult, f); /*epro*/ if (cnt != (30720*s->dev->epro_mult)) /*epro*/ { fclose (f); XDBG ((1, "Could not load black shading file\n")); return SANE_STATUS_INVAL; } fclose (f); /*try to load white shading file */ strcpy (filename, path); if (strlen (filename) < (PATH_MAX - 1 - strlen ("artec48ushading_white"))) strcat (filename, "artec48ushading_white"); else return SANE_STATUS_INVAL; XDBG ((1, "Try to read white shading file: \"%s\"\n", filename)); f = fopen (filename, "rb"); if (!f) return SANE_STATUS_INVAL; /*read values */ cnt = fread (s->shading_buffer_w, sizeof (unsigned char), 30720*s->dev->epro_mult, f);/*epro*/ if (cnt != (30720*s->dev->epro_mult)) /*epro*/ { fclose (f); XDBG ((1, "Could not load white shading file\n")); return SANE_STATUS_INVAL; } fclose (f); /*try to load offset file */ strcpy (filename, path); if (strlen (filename) < (PATH_MAX - 1 - strlen ("artec48uoffset"))) strcat (filename, "artec48uoffset"); else return SANE_STATUS_INVAL; XDBG ((1, "Try to read offset file: \"%s\"\n", filename)); f = fopen (filename, "rb"); if (!f) return SANE_STATUS_INVAL; /*read values */ cnt = fread (&s->dev->artec_48u_afe_params, sizeof (Artec48U_AFE_Parameters), 1, f); if (cnt != 1) { fclose (f); XDBG ((1, "Could not load offset file\n")); return SANE_STATUS_INVAL; } fclose (f); /*load exposure file */ strcpy (filename, path); if (strlen (filename) < (PATH_MAX - 1 - strlen ("artec48uexposure"))) strcat (filename, "artec48uexposure"); else return SANE_STATUS_INVAL; XDBG ((1, "Try to read exposure file: \"%s\"\n", filename)); f = fopen (filename, "rb"); if (!f) return SANE_STATUS_INVAL; /*read values */ cnt = fread (&s->dev->artec_48u_exposure_params, sizeof (Artec48U_Exposure_Parameters), 1, f); if (cnt != 1) { fclose (f); XDBG ((1, "Could not load exposure file\n")); return SANE_STATUS_INVAL; } fclose (f); s->calibrated = SANE_TRUE; return status; } static SANE_Status save_calibration_data (Artec48U_Scanner * s) { SANE_Status status = SANE_STATUS_GOOD; FILE *f = 0; size_t cnt; char path[PATH_MAX]; char filename[PATH_MAX]; mode_t mode = S_IRUSR | S_IWUSR; path[0] = 0; /* return SANE_STATUS_INVAL if HOME environment variable is not set */ if (getenv ("HOME") == NULL) { XDBG ((1, "Environment variable HOME not set\n")); return SANE_STATUS_INVAL; } if (strlen (getenv ("HOME")) < (PATH_MAX - 1)) strcat (path, getenv ("HOME")); else return SANE_STATUS_INVAL; if (strlen (path) < (PATH_MAX - 1 - strlen ("/.artec_eplus48u/"))) strcat (path, "/.artec_eplus48u/"); else return SANE_STATUS_INVAL; /*try to save black shading file */ strcpy (filename, path); if (strlen (filename) < (PATH_MAX - 1 - strlen ("artec48ushading_black"))) strcat (filename, "artec48ushading_black"); else return SANE_STATUS_INVAL; XDBG ((1, "Try to save black shading file: \"%s\"\n", filename)); f = fopen (filename, "w"); if (!f) { XDBG ((1, "Could not save artec48ushading_black\n")); return SANE_STATUS_INVAL; } if (chmod (filename, mode) != 0) return SANE_STATUS_INVAL; /*read values */ cnt = fwrite (s->shading_buffer_b, sizeof (unsigned char), 30720*s->dev->epro_mult, f); /*epro*/ XDBG ((1, "Wrote %li bytes to black shading buffer \n", (u_long) cnt)); if (cnt != (30720*s->dev->epro_mult))/*epro*/ { fclose (f); XDBG ((1, "Could not write black shading buffer\n")); return SANE_STATUS_INVAL; } fclose (f); /*try to save white shading file */ strcpy (filename, path); if (strlen (filename) < (PATH_MAX - 1 - strlen ("artec48ushading_white"))) strcat (filename, "artec48ushading_white"); else return SANE_STATUS_INVAL; XDBG ((1, "Try to save white shading file: \"%s\"\n", filename)); f = fopen (filename, "w"); if (!f) return SANE_STATUS_INVAL; if (chmod (filename, mode) != 0) return SANE_STATUS_INVAL; /*read values */ cnt = fwrite (s->shading_buffer_w, sizeof (unsigned char), 30720*s->dev->epro_mult, f);/*epro*/ if (cnt != (30720*s->dev->epro_mult)) /*epro*/ { fclose (f); XDBG ((1, "Could not write white shading buffer\n")); return SANE_STATUS_INVAL; } fclose (f); /*try to save offset file */ strcpy (filename, path); if (strlen (filename) < (PATH_MAX - 1 - strlen ("artec48uoffset"))) strcat (filename, "artec48uoffset"); else return SANE_STATUS_INVAL; XDBG ((1, "Try to write offset file: \"%s\"\n", filename)); f = fopen (filename, "w"); if (!f) return SANE_STATUS_INVAL; if (chmod (filename, mode) != 0) return SANE_STATUS_INVAL; /*read values */ cnt = fwrite (&s->dev->artec_48u_afe_params, sizeof (Artec48U_AFE_Parameters), 1, f); if (cnt != 1) { fclose (f); XDBG ((1, "Could not write afe values\n")); return SANE_STATUS_INVAL; } fclose (f); /*try to write exposure file */ strcpy (filename, path); if (strlen (filename) < (PATH_MAX - 1 - strlen ("artec48uexposure"))) strcat (filename, "artec48uexposure"); else return SANE_STATUS_INVAL; XDBG ((1, "Try to write exposure file: \"%s\"\n", filename)); f = fopen (filename, "w"); if (!f) return SANE_STATUS_INVAL; if (chmod (filename, mode) != 0) return SANE_STATUS_INVAL; /*read values */ cnt = fwrite (&s->dev->artec_48u_exposure_params, sizeof (Artec48U_Exposure_Parameters), 1, f); if (cnt != 1) { fclose (f); XDBG ((1, "Could not write exposure values\n")); return SANE_STATUS_INVAL; } fclose (f); return status; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { SANE_Status status = SANE_STATUS_INVAL; Artec48U_Device *dev = 0; Artec48U_Scanner *s = 0; if (!devicename) return SANE_STATUS_INVAL; XDBG ((2, "sane_open: devicename = \"%s\"\n", devicename)); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { XDBG ((2, "sane_open: found matching device %s\n", dev->sane.name)); break; } } if (!dev) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) XDBG ((2, "sane_open: attach failed %s\n", devicename)); } } else { /* empty devicename -> use first device */ XDBG ((2, "sane_open: empty devicename\n")); dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; status = artec48u_device_open (dev); if (status != SANE_STATUS_GOOD) { XDBG ((3, "could not open device\n")); return status; } XDBG ((2, "sane_open: opening device `%s', handle = %p\n", dev->sane.name, (void *) dev)); XDBG ((1, "sane_open - %s\n", dev->sane.name)); XDBG ((2, "sane_open: try to open %s\n", dev->sane.name)); status = artec48u_device_activate (dev); if (status != SANE_STATUS_GOOD) { XDBG ((3, "could not activate device\n")); return status; } /* We do not check anymore, whether the firmware is already loaded */ /* because that caused problems after rebooting; furthermore, loading */ /* of the firmware is fast, therefore the test doesn't make much sense */ status = download_firmware_file (dev); if (status != SANE_STATUS_GOOD) { XDBG ((3, "download_firmware_file failed\n")); return status; } /* If a scan is interrupted without sending stop_scan, bad things happen. * Send the stop scan command now just in case. */ artec48u_stop_scan (dev); artec48u_wait_for_positioning (dev); artec48u_scanner_new (dev, &s); init_calibrator (s); s->next = first_handle; first_handle = s; *handle = s; status = init_options (s); if (status != SANE_STATUS_GOOD) return status; /*Try to load the calibration values */ status = load_calibration_data (s); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Artec48U_Scanner *s; XDBG ((5, "sane_close: start\n")); /* remove handle from list of open handles: */ for (s = first_handle; s; s = s->next) { if (s == handle) break; } if (!s) { XDBG ((5, "close: invalid handle %p\n", handle)); return; } artec48u_device_close (s->dev); artec48u_scanner_free (s); XDBG ((5, "sane_close: exit\n")); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Artec48U_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; XDBG ((5, "sane_get_option_descriptor: option = %s (%d)\n", s->opt[option].name, option)); return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { Artec48U_Scanner *s = handle; #ifdef ARTEC48U_USE_BUTTONS SANE_Int button_state; #endif SANE_Status status; XDBG ((8, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", (void *) handle, option, action, (void *) value, (void *) info)); if (info) *info = 0; if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_INVAL; /* Unknown option ... */ if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) return SANE_STATUS_INVAL; switch (action) { case SANE_ACTION_SET_VALUE: if (s->scanning == SANE_TRUE) return SANE_STATUS_INVAL; if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (s->opt + option, value, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { case OPT_RESOLUTION: if(s->dev->is_epro != 0) { if((s->val[option].w == 1200) && (*(SANE_Word *) value < 1200)) { s->opt[OPT_BIT_DEPTH].constraint.word_list = bitdepth_list; *info |= SANE_INFO_RELOAD_OPTIONS; } else if((s->val[option].w < 1200) && (*(SANE_Word *) value == 1200)) { s->opt[OPT_BIT_DEPTH].constraint.word_list = bitdepth_list2; if(s->val[OPT_BIT_DEPTH].w > 8) s->val[OPT_BIT_DEPTH].w = 8; *info |= SANE_INFO_RELOAD_OPTIONS; } } s->val[option].w = *(SANE_Word *) value; if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } break; /* fall through */ case OPT_BIT_DEPTH: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) value; if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; /* fall through */ case OPT_BLACK_LEVEL: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_GAMMA: case OPT_GAMMA_R: case OPT_GAMMA_G: case OPT_GAMMA_B: case OPT_CALIBRATE: case OPT_CALIBRATE_SHADING: s->val[option].w = *(SANE_Word *) value; return SANE_STATUS_GOOD; case OPT_DEFAULT_ENHANCEMENTS: s->val[OPT_GAMMA].w = SANE_FIX (s->dev->gamma_master); if (strcmp (s->val[OPT_SCAN_MODE].s, mode_list[2]) == 0) { s->val[OPT_GAMMA_R].w = SANE_FIX (s->dev->gamma_r); s->val[OPT_GAMMA_G].w = SANE_FIX (s->dev->gamma_g); s->val[OPT_GAMMA_B].w = SANE_FIX (s->dev->gamma_b); } s->val[OPT_BRIGHTNESS].w = 0; s->val[OPT_CONTRAST].w = 0; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; break; case OPT_SCAN_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (value); if (strcmp (s->val[OPT_SCAN_MODE].s, mode_list[0]) == 0) { s->opt[OPT_GAMMA_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BLACK_LEVEL].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; } else if (strcmp (s->val[OPT_SCAN_MODE].s, mode_list[1]) == 0) { s->opt[OPT_GAMMA_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BLACK_LEVEL].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_B].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_BLACK_LEVEL].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; } break; case SANE_ACTION_GET_VALUE: switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_BIT_DEPTH: case OPT_BLACK_LEVEL: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_GAMMA: case OPT_GAMMA_R: case OPT_GAMMA_G: case OPT_GAMMA_B: case OPT_CALIBRATE: case OPT_CALIBRATE_SHADING: *(SANE_Word *) value = (SANE_Word) s->val[option].w; return SANE_STATUS_GOOD; /* string options: */ case OPT_SCAN_MODE: strcpy (value, s->val[option].s); return SANE_STATUS_GOOD; #ifdef ARTEC48U_USE_BUTTONS case OPT_BUTTON_STATE: status = artec48u_check_buttons (s->dev, &button_state); if (status == SANE_STATUS_GOOD) { s->val[option].w = button_state; *(SANE_Int *) value = (SANE_Int) s->val[option].w; } else { s->val[option].w = 0; *(SANE_Int *) value = 0; } return SANE_STATUS_GOOD; #endif } break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Artec48U_Scanner *s = handle; SANE_Status status; SANE_Word resx; /* int scan_mode;*/ SANE_String str = s->val[OPT_SCAN_MODE].s; int tlx; int tly; int brx; int bry; int tmp; XDBG ((2, "sane_get_params: string %s\n", str)); XDBG ((2, "sane_get_params: enter\n")); tlx = s->val[OPT_TL_X].w; tly = s->val[OPT_TL_Y].w; brx = s->val[OPT_BR_X].w; bry = s->val[OPT_BR_Y].w; /*make sure, that tlx < brx and tly < bry this will NOT change the options */ if (tlx > brx) { tmp = tlx; tlx = brx; brx = tmp; } if (tly > bry) { tmp = tly; tly = bry; bry = tmp; } resx = s->val[OPT_RESOLUTION].w; str = s->val[OPT_SCAN_MODE].s; s->request.color = SANE_TRUE; if ((strcmp (str, mode_list[0]) == 0) || (strcmp (str, mode_list[1]) == 0)) s->request.color = SANE_FALSE; else s->request.color = SANE_TRUE; s->request.depth = s->val[OPT_BIT_DEPTH].w; if (strcmp (str, mode_list[0]) == 0) s->request.depth = 8; s->request.y0 = tly; /**< Top boundary */ s->request.x0 = SANE_FIX (216.0) - brx; /**< left boundary */ s->request.xs = brx - tlx; /**< Width */ s->request.ys = bry - tly; /**< Height */ s->request.xdpi = resx; /**< Horizontal resolution */ s->request.ydpi = resx; /**< Vertical resolution */ /*epro*/ if ((resx == 1200) && (s->dev->is_epro == 0)) s->request.xdpi = 600;/**< Vertical resolution */ status = artec48u_setup_scan (s, &(s->request), SA_SCAN, SANE_TRUE, &(s->params)); if (status != SANE_STATUS_GOOD) return SANE_STATUS_INVAL; /*DBG(1, "sane_get_params: scan_mode %i\n",scan_mode);*/ params->depth = s->params.depth; s->params.lineart = SANE_FALSE; if (s->params.color == SANE_TRUE) { params->format = SANE_FRAME_RGB; params->bytes_per_line = s->params.pixel_xs * 3; } else { params->format = SANE_FRAME_GRAY; params->bytes_per_line = s->params.pixel_xs; if (strcmp (str, mode_list[0]) == 0) { params->depth = 1; params->bytes_per_line = (s->params.pixel_xs + 7) / 8; s->params.lineart = SANE_TRUE; } } if ((resx == 1200) && (s->dev->is_epro == 0)) { if (params->depth == 1) params->bytes_per_line = (s->params.pixel_xs * 2 + 7) / 8; else params->bytes_per_line *= 2; } if (params->depth == 16) params->bytes_per_line *= 2; params->last_frame = SANE_TRUE; params->pixels_per_line = s->params.pixel_xs; if ((resx == 1200) && (s->dev->is_epro == 0)) params->pixels_per_line *= 2; params->lines = s->params.pixel_ys; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Artec48U_Scanner *s = handle; SANE_Status status; int fds[2]; if (s->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (sane_get_parameters (handle, &s->sane_params) != SANE_STATUS_GOOD) return SANE_STATUS_INVAL; if ((s->calibrated != SANE_TRUE) || (s->val[OPT_CALIBRATE].w == SANE_TRUE)) { XDBG ((1, "Must calibrate scanner\n")); status = calibrate_scanner (s); if (status != SANE_STATUS_GOOD) return status; s->calibrated = SANE_TRUE; } if (sane_get_parameters (handle, &s->sane_params) != SANE_STATUS_GOOD) return SANE_STATUS_INVAL; calculate_brightness (s); calculate_contrast (s); calculateGamma (s); calculateGammaRed (s); calculateGammaGreen (s); calculateGammaBlue (s); artec48u_carriage_home (s->dev); artec48u_wait_for_positioning (s->dev); s->reader = NULL; s->scanning = SANE_TRUE; s->byte_cnt = 0; s->lines_to_read = s->params.pixel_ys; /*allocate a buffer, that can hold a complete scan line */ /*If resolution is 1200 dpi and we are scanning in lineart mode, then we also allocate a lineart_buffer, which can hold a complete scan line in 8 bit/gray. This makes interpolation easier. */ if ((s->params.ydpi == 1200) && (s->dev->is_epro == 0)) { if (s->request.color == SANE_TRUE) { s->line_buffer = (SANE_Byte *) malloc (s->params.scan_bpl * 8); } else { s->line_buffer = (SANE_Byte *) malloc (s->params.scan_bpl * 4); /*lineart ? */ if (strcmp (s->val[OPT_SCAN_MODE].s, mode_list[0]) == 0) s->lineart_buffer = (SANE_Byte *) malloc (s->params.pixel_xs * 2); } } else { if (s->request.color == SANE_TRUE) s->line_buffer = (SANE_Byte *) malloc (s->params.scan_bpl * 4); else { s->line_buffer = (SANE_Byte *) malloc (s->params.scan_bpl * 2); /*lineart ? */ if (strcmp (s->val[OPT_SCAN_MODE].s, mode_list[0]) == 0) s->lineart_buffer = (SANE_Byte *) malloc (s->params.pixel_xs * 2); } } if (pipe (fds) < 0) { s->scanning = SANE_FALSE; XDBG ((2, "sane_start: pipe failed (%s)\n", strerror (errno))); return SANE_STATUS_IO_ERROR; } status = artec48u_scanner_start_scan (s, &s->request, &s->params); if (status != SANE_STATUS_GOOD) { XDBG ((2, "sane_start: could not start scan\n")); return status; } s->pipe = fds[0]; s->reader_pipe = fds[1]; s->reader_pid = sanei_thread_begin (reader_process, s); cancelRead = SANE_FALSE; if (!sanei_thread_is_valid (s->reader_pid)) { s->scanning = SANE_FALSE; XDBG ((2, "sane_start: sanei_thread_begin failed (%s)\n", strerror (errno))); return SANE_STATUS_NO_MEM; } signal (SIGCHLD, sig_chldhandler); if (sanei_thread_is_forked()) close (s->reader_pipe); XDBG ((1, "sane_start done\n")); return SANE_STATUS_GOOD; /* parent */ } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { Artec48U_Scanner *s = handle; ssize_t nread; *length = 0; /* here we read all data from the driver... */ nread = read (s->pipe, data, max_length); XDBG ((3, "sane_read - read %ld bytes\n", (long) nread)); if (cancelRead == SANE_TRUE) { return do_cancel (s, SANE_TRUE); } if (nread < 0) { if (EAGAIN == errno) { /* if we already had read the picture, so it's okay and stop */ if (s->eof == SANE_TRUE) { sanei_thread_waitpid (s->reader_pid, 0); s->reader_pid = -1; artec48u_scanner_stop_scan (s); artec48u_carriage_home (s->dev); return close_pipe (s); } /* else force the frontend to try again */ return SANE_STATUS_GOOD; } else { XDBG ((4, "ERROR: errno=%d\n", errno)); do_cancel (s, SANE_TRUE); return SANE_STATUS_IO_ERROR; } } *length = nread; s->byte_cnt += nread; /* nothing read means that we're finished OR we had a problem... */ if (0 == nread) { if (0 == s->byte_cnt) { s->exit_code = sanei_thread_get_status (s->reader_pid); if (SANE_STATUS_GOOD != s->exit_code) { close_pipe (s); return s->exit_code; } } return close_pipe (s); } return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Artec48U_Scanner *s = handle; XDBG ((2, "sane_cancel: handle = %p\n", handle)); if (s->scanning) do_cancel (s, SANE_FALSE); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Artec48U_Scanner *s = (Artec48U_Scanner *) handle; XDBG ((1, "sane_set_io_mode: non_blocking=%d\n", non_blocking)); if (!s->scanning) { XDBG ((4, "ERROR: not scanning !\n")); return SANE_STATUS_INVAL; } if (-1 == s->pipe) { XDBG ((4, "ERROR: not supported !\n")); return SANE_STATUS_UNSUPPORTED; } if (fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { XDBG ((4, "ERROR: can?t set to non-blocking mode !\n")); return SANE_STATUS_IO_ERROR; } XDBG ((1, "sane_set_io_mode done\n")); return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Artec48U_Scanner *s = (Artec48U_Scanner *) handle; XDBG ((1, "sane_get_select_fd\n")); if (!s->scanning) { XDBG ((4, "ERROR: not scanning !\n")); return SANE_STATUS_INVAL; } *fd = s->pipe; XDBG ((1, "sane_get_select_fd done\n")); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { Artec48U_Device *device = 0; SANE_Status status; char str[PATH_MAX] = _DEFAULT_DEVICE; char temp[PATH_MAX]; size_t len; FILE *fp; double gamma_m = 1.9; double gamma_r = 1.0; double gamma_g = 1.0; double gamma_b = 1.0; int epro_default = 0; DBG_INIT (); eProMult = 1; isEPro = 0; temp[0] = 0; strcpy (vendor_string, "Artec"); strcpy (model_string, "E+ 48U"); sanei_usb_init (); sanei_thread_init (); /* do some presettings... */ auth = authorize; if (version_code != NULL) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (ARTEC48U_CONFIG_FILE); /* default to _DEFAULT_DEVICE instead of insisting on config file */ if (NULL == fp) { status = attach (_DEFAULT_DEVICE, &device); return status; } while (sanei_config_read (str, sizeof (str), fp)) { XDBG ((1, "sane_init, >%s<\n", str)); /* ignore line comments */ if (str[0] == '#') continue; len = strlen (str); /* ignore empty lines */ if (0 == len) continue; /* check for options */ if (0 == strncmp (str, "option", 6)) { if(decodeVal (str,"ePlusPro",_INT, &isEPro,&epro_default) == SANE_TRUE) { eProMult = 1; if(isEPro != 0) { eProMult = 2; XDBG ((3, "Is Artec E Pro\n")); } else XDBG ((3, "Is Artec E+ 48U\n")); } decodeVal (str, "masterGamma", _FLOAT, &gamma_master_default, &gamma_m); decodeVal (str, "redGamma", _FLOAT, &gamma_r_default, &gamma_r); decodeVal (str, "greenGamma", _FLOAT, &gamma_g_default, &gamma_g); decodeVal (str, "blueGamma", _FLOAT, &gamma_b_default, &gamma_b); decodeVal (str, "redOffset", _BYTE, &afe_params.r_offset, &default_afe_params.r_offset); decodeVal (str, "greenOffset", _BYTE, &afe_params.g_offset, &default_afe_params.g_offset); decodeVal (str, "blueOffset", _BYTE, &afe_params.b_offset, &default_afe_params.b_offset); decodeVal (str, "redExposure", _INT, &exp_params.r_time, &default_exp_params.r_time); decodeVal (str, "greenExposure", _INT, &exp_params.g_time, &default_exp_params.g_time); decodeVal (str, "blueExposure", _INT, &exp_params.b_time, &default_exp_params.b_time); decodeVal (str, "modelString", _STRING, model_string, model_string); decodeVal (str, "vendorString", _STRING, vendor_string, vendor_string); decodeVal (str, "artecFirmwareFile", _STRING, firmwarePath, firmwarePath); } else if (0 == strncmp (str, "usb", 3)) { if (temp[0] != 0) { XDBG ((3, "trying to attach: %s\n", temp)); XDBG ((3, " vendor: %s\n", vendor_string)); XDBG ((3, " model: %s\n", model_string)); sanei_usb_attach_matching_devices (temp, attach_one_device); } /*save config line in temp */ strcpy (temp, str); } else if (0 == strncmp (str, "device", 6)) { if (SANE_TRUE == decodeDevName (str, devName)) { if (devName[0] != 0) sanei_usb_attach_matching_devices (devName, attach_one_device); temp[0] = 0; } } else { /* ignore other stuff... */ XDBG ((1, "ignoring >%s<\n", str)); } } if (temp[0] != 0) { XDBG ((3, "trying to attach: %s\n", temp)); XDBG ((3, " vendor: %s\n", vendor_string)); XDBG ((3, " model: %s\n", model_string)); sanei_usb_attach_matching_devices (temp, attach_one_device); temp[0] = 0; } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { Artec48U_Device *dev, *next; XDBG ((5, "sane_exit: start\n")); for (dev = first_dev; dev; dev = next) { next = dev->next; /*function will check, whether device is really open */ artec48u_device_close (dev); artec48u_device_free (dev); } XDBG ((5, "sane_exit: exit\n")); return; } sane-backends-1.0.27/backend/plustek-pp_hwdefs.h0000664000175000017500000007641212112021330016421 00000000000000/* @file plustek-pp_hwdefs.h * @brief different definitions for describing the scanner hardware * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2004 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * 0.30 - initial version * 0.31 - corrected the values of _GAIN_P98_HIGH, _GAIN_P96_HIGH and _GAIN_LOW * 0.32 - removed _LampDelay defines * removed _MODE_xxx defines * 0.33 - cosmetic changes * removed _PORT_BPP from modelist * 0.34 - no changes * 0.35 - no changes * 0.36 - moved struct ScanState to this header * moved some definitions from scandata.h to this file * 0.37 - some cleanup work * added model override defines here * added _A3 * changed some _ defines to _ defines * 0.38 - added ASIC98003 stuff * removed the _ASIC_xxxxx definitions * 0.39 - major changes: moved a lot of stuff to this file * 0.40 - no changes * 0.41 - added _OVR_PLUSTEK_4800P definition * 0.42 - added _OVR_PRIMAX_4800D30 definition * 0.43 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __HWDEFS_H__ #define __HWDEFS_H__ /* * port modes * (WARNING: never change these defines, as they are used as entries * to jump tables !!!) */ #define _PORT_EPP 0 #define _PORT_SPP 1 #define _PORT_BIDI 2 #define _PORT_ECP 3 #define _PORT_ESP 4 #define _PORT_NONE 5 /* * ScannerSize */ #define _SCANSIZE_A4 0 #define _SCANSIZE_LETTER 1 #define _SCANSIZE_LEGAL 2 #define _SCANSIZE_A3 3 /* * Magic IDs switch printer port to scanner mode */ #define _ID1ST 0x69 #define _ID2ND 0x96 #define _ID3RD 0xa5 #define _ID4TH 0x5a /* * Special IDs used to reset scanner (ASIC98003) */ #define _RESET1ST 0x69 #define _RESET2ND 0x96 #define _RESET3RD 0xaa #define _RESET4TH 0x55 /* * ID switch to printer mode */ #define _ID_TO_PRINTER 0 /* * Flags for internal use */ #define _VF_BUILDMAP 0x0000001 #define _VF_DATATOUSERBUFFER 0x0000002 #define _VF_ENVIRONMENT_READY 0x0000004 #define _VF_FIRSTSCANLINE 0x0000008 #define _VF_PREVIEW 0x0000020 /* * Printer Control Port: Definitions */ #define _CTRL_STROBE 0x01 #define _CTRL_AUTOLF 0x02 #define _CTRL_NOT_INIT 0x04 #define _CTRL_SELECT_IN 0x08 #define _CTRL_ENABLE_IRQ 0x10 #define _CTRL_DIRECTION 0x20 #define _CTRL_RESERVED 0xc0 /* * here are the definitions for the different registers * first the ASIC 96001/3 section */ /* Status Register 0x10 */ #define _FLAG_P96_PAPER 0x01 #define _FLAG_P96_ADF 0x02 #define _FLAG_P96_KEY 0x04 #define _FLAG_P96_EPP 0x08 #define _FLAG_P96_FIFOFULL 0x10 #define _FLAG_P96_FIFOEMPTY 0x20 #define _FLAG_P96_CCDTYPE 0x40 #define _FLAG_P96_MOTORTYPE 0x80 /* * the 98001 section */ #define _DEFAULT_LINESCANTIME 96 /* Status Register (Addr: 0x30) */ #define _FLAG_P98_PAPER 0x01 #define _FLAG_P98_KEY 0x80 /* * some buffer sizes (for ASIC 98001 based devices) */ #define _LINE_BUFSIZE (5500 * 6) #define _LINE_BUFSIZE1 (5500 * 8) #define _PROCESS_BUFSIZE (5120 * 3) /* * generic equates */ #define _DEF_BW_THRESHOLD 111 /* default B/W mode threshold value */ #define _NUMBER_OF_SCANSTEPS 64 /* Asic spec.: up to 64 scan steps */ #define _SCANSTATE_BYTES (_NUMBER_OF_SCANSTEPS/2) /* CHECK: Play around with the P98003/1 * gain values - maybe we get a brighter picture... */ #define _GAIN_P98_HIGH 225 /* Volt. max. value, Asic 98001 */ #define _GAIN_P98003_HIGH 240 /* Volt. max. value, Asic 98003 */ #define _GAIN_P96_HIGH 240 /* Volt. max. value, Asic 96001/3 */ #define _GAIN_LOW 210 /* Volt. min. value */ #define _GAIN_P98003_LOW 220 /* Volt. min. value, Asic 98003 */ #define _MOTOR_ONE_LINE_TIME 4 /* for ASIC 98001/3 shading */ #define _DEF_BRIGHTEST_SKIP 3 #define _DEF_DARKEST_SKIP 5 #define _BUF_SIZE_BASE_CONST 1280 #define _SCANSTATE_TABLE_SIZE 250 /* was 200 for 4830 */ #define _P98_OFFSET70 60 /* for Data channel (BYTE) */ #define _RED_DATA_READY 0x01 #define _GREEN_DATA_READY 0x02 #define _BLUE_DATA_READY 0x04 #define _ASIC_REDCOLOR 0x01 #define _ASIC_GREENCOLOR 0x03 #define _ASIC_BLUECOLOR 0x02 /* * for Asic I/O signal control */ #define _CTRL_GENSIGNAL (_CTRL_RESERVED + _CTRL_NOT_INIT) /* 0xc4 */ #define _CTRL_START_REGWRITE (_CTRL_GENSIGNAL + _CTRL_SELECT_IN) /* 0xcc */ #define _CTRL_END_REGWRITE (_CTRL_GENSIGNAL) /* 0xc4 */ #define _CTRL_START_DATAWRITE (_CTRL_GENSIGNAL + _CTRL_AUTOLF) /* 0xc6 */ #define _CTRL_END_DATAWRITE (_CTRL_GENSIGNAL) /* 0xc4 */ #define _CTRL_EPPSIGNAL_WRITE (_CTRL_GENSIGNAL + _CTRL_STROBE) /* 0xc5 */ #define _CTRL_EPPTRIG_REGWRITE (_CTRL_GENSIGNAL + _CTRL_SELECT_IN + _CTRL_STROBE) #define _CTRL_START_BIDIREAD (_CTRL_GENSIGNAL + _CTRL_DIRECTION + _CTRL_AUTOLF) #define _CTRL_END_BIDIREAD (_CTRL_GENSIGNAL + _CTRL_DIRECTION) /* 0xe4 */ typedef struct { ULong dwFullSpeed; Byte bCurrentSpeed; Byte bStepSpeed; } DiffModeVar, *pDiffModeVar; typedef struct { UShort wHomePos; /* scanner's scanning home position */ UShort wMaxSteps; /* maximum steps for this scan */ Byte bExposureTime; /* exposure time for one line */ Byte bMotorStep; Byte bFlagScanMode; /* see below */ Byte bTimesShading; /* see below */ } ModeTypeVar, *pModeTypeVar; typedef struct { Byte bStep; Byte bStatus; } ScanState, *pScanState; typedef struct { Byte bReg; Byte bParam; } RegDef, *pRegDef; typedef union { RGBByteDef Colors; UChar bColors[3]; } ColorByte, *pColorByte; typedef union { RGBUShortDef Colors; UShort wColors[3]; } ColorWord, *pColorWord; typedef struct { UShort exposureTime; UShort xStepTime; } ExpXStepDef, *pExtXStepDef; typedef struct { UShort thresholdBW; UShort thresholdGray; UShort thresholdColor; } ThreshDef, *pThreshDef; /* for decription of the DAC specific stuff*/ typedef struct { ColorWord GainResize; ColorWord DarkCmpHi; ColorWord DarkCmpLo; ColorWord DarkOffSub; ColorByte DarkDAC; UChar Reserved; } DACTblDef, *pDACTblDef; /* * some function types */ typedef struct scandata *pScanData; typedef void (*pFnDataProcess)(pScanData, pVoid, pVoid, ULong); typedef Bool (*pFnReadData)(pScanData, pUChar, ULong); typedef void (*pFnVoid)(pScanData); typedef Bool (*pFnBool)(pScanData); typedef void (*pFnDACOffs)(pScanData, pDACTblDef, ULong); typedef void (*pFnDACDark)(pScanData, pDACTblDef, ULong, UShort); typedef void (*pFnOut)(Byte,UShort); typedef Byte (*pFnIn)(UShort); /* * For Motor step control */ #define _FullStepStrong 0x10 #define _HalfStep 0x04 #define _QuarterStep 0x08 #define _EightStep 0x0c /* bTimesShading */ #define _Shading_32Times 0 #define _Shading_4Times 1 #define _Shading_16Times 2 /* Scan.bModuleState */ #define _MotorInNormalState 0 #define _MotorGoBackward 1 #define _MotorInStopState 2 #define _MotorAdvancing 3 #define _MotorAdvanced 4 /* bMoveDataOutFlag */ #define _DataInNormalState 0 #define _DataAfterRefreshState 1 #define _DataFromStopState 2 /* bFastMoveFlag */ #define _FastMove_Fast_C50_G100 0 #define _FastMove_Middle_C75_G150 1 #define _FastMove_Low_C75_G150 2 #define _FastMove_Low_C75_G150_Back 4 #define _FastMove_Pos_300 5 #define _FastMove_Film_150 6 /* * ASIC 98003 base models... */ #define _TPA_P98003_SHADINGORG 2172U #define _RFT_SCANNING_ORG 380U #define _POS_SCANNING_ORG 2840U #define _POS_PAGEWIDTH 450U #define _POS_ORG_OFFSETX 0x41C #define _NEG_SCANNING_ORG 3000U #define _NEG_PAGEWIDTH 464U #define _NEG_PAGEWIDTH600 992U #define _NEG_ORG_OFFSETX 0x430 #define _NEG_SHADING_OFFS 1500U #define _NEG_EDGE_VALUE 0x800 #define _SHADING_BEGINX 4U /* home positions */ #define _Home_CE50 0x1f /* 0x1d 1b */ #define _Home_CE100 0x27 /* 0x34 23 */ #define _Home_CE150 0x29 /* 0x23 25 */ #define _Home_CE300 0x34 /* 0x2e 30 */ #define _Home_CE600 0x3a /* 0x35 36 */ #define _Home_CB50 0x20 /* 0x22 1c */ #define _Home_CB100 0x41 /* 0x42 3d */ #define _Home_CB150 0x41 /* 0x3f 3d */ #define _Home_CB300 0x4c /* 0x4a 48 */ #define _Home_CB600 0x53 /* 0x54 4f */ #define _Home_CS50 0x20 /* 0x1b 1c */ #define _Home_CS100 0x41 /* 0x40 3d */ #define _Home_CS150 0x41 /* 0x3e 3d */ #define _Home_CS300 0x4c /* 0x4b 48 */ #define _Home_CS600 0x53 /* 0x4f 4f */ #define _Home_GE75 0x08 /* 7-14-98 00 */ #define _Home_GE150 0x04 /* 0x22 00 */ #define _Home_GE300 0x12 /* 0x2d 0e */ #define _Home_GE600 0x19 /* 0x33 15 */ #define _Home_GB75 0x40 /* 7-14-98 3e */ #define _Home_GB150 0x40 /* 0x3f 3e */ #define _Home_GB300 0x4e /* 0x4c 4a */ #define _Home_GB600 0x53 /* 0x51 4f */ #define _Home_GS75 0x40 /* 7-14-98 3c */ #define _Home_GS150 0x40 /* 0x3f 3c */ #define _Home_GS300 0x4e /* 0x4d 4a */ #define _Home_GS600 0x53 /* 0x51 4f */ #define _Home_BE75 0x30 /* 7-14-98 20 */ #define _Home_BE150 0x30 /* 0x3c 20 */ #define _Home_BE300 0x32 /* 0x48 2e */ #define _Home_BE600 0x37 /* 0x35 33 */ #define _Home_BB75 0x42 /* 7-14-98 3e */ #define _Home_BB150 0x42 /* 0x47 3e */ #define _Home_BB300 0x50 /* 0x51 4c */ #define _Home_BB600 0x53 /* 0x51 4f */ #define _Home_BS75 0x42 /* 7-14-98 3e */ #define _Home_BS150 0x42 /* 0x46 3e */ #define _Home_BS300 0x50 /* 0x4f 4c */ #define _Home_BS600 0x53 /* 0x55 4f */ /* * for ModeTypeVar indexes */ #define _FixParamEppBw 0 #define _FixParamBppBw _FixParamEppBw + 4 #define _FixParamSppBw _FixParamBppBw + 4 #define _FixParamEppGray 0 #define _FixParamBppGray _FixParamEppGray + 4 #define _FixParamSppGray _FixParamBppGray + 4 #define _FixParamEppColor 0 #define _FixParamBppColor _FixParamEppColor + 5 #define _FixParamSppColor _FixParamBppColor + 5 #define _FixParamSppNegative 0 #define _FixParamBppNegative _FixParamSppNegative + 3 #define _FixParamEppNegative _FixParamBppNegative + 3 #define _FixParamSppPositive _FixParamEppNegative + 3 #define _FixParamBppPositive _FixParamSppPositive + 3 #define _FixParamEppPositive _FixParamBppPositive + 3 /* * for DiffModeVar indexes */ #define _BwEpp150 0 #define _BwEpp300 1 #define _BwEpp600 2 #define _BwBpp150 _BwEpp150 #define _BwBpp300 _BwEpp300 #define _BwBpp600 _BwEpp600 #define _BwSpp150 3 #define _BwSpp300 4 #define _BwSpp600 5 #define _GrayEpp150 6 #define _GrayEpp300 7 #define _GrayEpp600 8 #define _GrayEpp600_3000 9 /* > 3000 pixels per channel */ #define _GrayBpp150 10 #define _GrayBpp300 11 #define _GrayBpp300_1600 12 #define _GrayBpp600 13 #define _GrayBpp600_1600 14 #define _GrayBpp600_3200 15 #define _GraySpp150 16 #define _GraySpp150_800 17 #define _GraySpp300 18 #define _GraySpp300_800 19 #define _GraySpp300_1600 20 #define _GraySpp600 21 #define _GraySpp600_800 22 #define _GraySpp600_1600 23 #define _GraySpp600_3200 24 #define _ColorEpp60 25 #define _ColorEpp100 _ColorEpp60 #define _ColorEpp150 26 #define _ColorEpp300 27 #define _ColorEpp300_1200 28 #define _ColorEpp600 29 #define _ColorEpp600_1400 30 #define _ColorEpp600_2800 31 #define _ColorEpp600_4000 32 #define _ColorBpp60 33 #define _ColorBpp100 34 #define _ColorBpp150 35 #define _ColorBpp150_800 36 #define _ColorBpp300 37 #define _ColorBpp300_800 38 #define _ColorBpp300_1600 39 #define _ColorBpp600 40 #define _ColorBpp600_800 41 #define _ColorBpp600_1600 42 #define _ColorBpp600_3200 43 #define _ColorSpp60 _ColorBpp60 #define _ColorSpp100 _ColorBpp100 #define _ColorSpp150 _ColorBpp150 #define _ColorSpp150_800 _ColorBpp150_800 #define _ColorSpp300 44 #define _ColorSpp300_500 45 #define _ColorSpp300_1000 46 #define _ColorSpp300_2000 47 #define _ColorSpp600 48 #define _ColorSpp600_500 49 #define _ColorSpp600_1000 50 #define _ColorSpp600_2000 51 #define _ColorSpp600_4000 52 #define _NegativeSpp150 53 #define _NegativeSpp300 54 #define _NegativeSpp600 55 #define _NegativeBpp150 _NegativeSpp150 #define _NegativeBpp300 _NegativeSpp300 #define _NegativeBpp600 _NegativeSpp600 #define _NegativeEpp150 _NegativeSpp150 #define _NegativeEpp300 _NegativeSpp300 #define _NegativeEpp600 _NegativeSpp600 #define _BwEpp75 56 #define _BwBpp75 56 #define _BwSpp75 56 #define _GrayEpp75 56 #define _GrayBpp75 56 #define _GraySpp75 56 #define _TransparencySpp150 _NegativeSpp150 #define _TransparencySpp300 _NegativeSpp300 #define _TransparencySpp600 _NegativeSpp600 #define _TransparencyBpp150 _NegativeSpp150 #define _TransparencyBpp300 _NegativeSpp300 #define _TransparencyBpp600 _NegativeSpp600 #define _TransparencyEpp150 _NegativeSpp150 #define _TransparencyEpp300 _NegativeSpp300 #define _TransparencyEpp600 _NegativeSpp600 /* for 48 bits color */ #define _ColorEpp100_1400 63 #define _ColorEpp150_1900 64 #define _ColorEpp300_4000 65 #define _ColorEpp600_9600 66 #define _ColorSpp300_3000 67 /* * for mirroring parts of the 98001/3 asic register set */ typedef struct { Byte RD_Motor1Control; /* 0x0b */ Byte RD_StepControl; /* 0x14 */ Byte RD_Motor0Control; /* 0x15 */ Byte RD_XStepTime; /* 0x16 */ Byte RD_ModeControl; /* 0x1b */ Byte RD_LineControl; /* 0x1c */ Byte RD_ScanControl; /* 0x1d, init = 5 */ Byte RD_ModelControl; /* 0x1f */ Byte RD_Model1Control; /* 0x20 */ UShort RD_Dpi; /* 0x21 */ UShort RD_Origin; /* 0x23 */ UShort RD_Pixels; /* 0x25 */ UShort RD_ThresholdControl; /* 0x27 */ Byte RD_ThresholdGapCtrl; /* 0x29 */ UShort RD_RedDarkOff; /* 0x33 */ UShort RD_GreenDarkOff; /* 0x35 */ UShort RD_BlueDarkOff; /* 0x37 */ ULong RD_BufFullSize; /* 0x54, ASIC 98003 */ UShort RD_MotorTotalSteps; /* 0x57, ASIC 98003 */ Byte RD_ScanControl1; /* 0x5b, ASIC 98003 */ Byte RD_MotorDriverType; /* 0x64, ASIC 98003 */ Byte RD_ExtLineControl; /* 0x6d, ASIC 98003 */ Byte RD_ExtXStepTime; /* 0x6e, ASIC 98003 */ } RegData, *pRegData; /* * for registers, that only exist on the 96001/3 */ typedef struct { Byte RD_MotorControl; /* 0x1b, init = 3 */ Byte RD_MemAccessControl; /* 0x1d */ Byte RD_WatchDogControl; /* 0x25, init = 0x8f */ union { Byte RD_ModelControl2; /* 0x26, P96003 */ } u26; union { Byte RD_RedChShadingOff; /* 0x28, P96003 */ } u28; union { Byte RD_GreenChShadingOff; /* 0x29, P96003 */ } u29; Byte RD_BlueChShadingOff; /* 0x2a, P96003 */ Byte RD_RedChDarkOff; /* 0x2b, P96003 */ Byte RD_GreenChDarkOff; /* 0x2c, P96003 */ Byte RD_BlueChDarkOff; /* 0x2d, P96003 */ Byte RD_RedChEvenOff; /* 0x31, P96003 */ Byte RD_GreenChEvenOff; /* 0x32, P96003 */ Byte RD_BlueChEvenOff; /* 0x33, P96003 */ Byte RD_RedChOddOff; /* 0x34, P96003 */ Byte RD_GreenChOddOff; /* 0x35, P96003 */ Byte RD_BlueChOddOff; /* 0x36, P96003 */ Byte RD_RedGainOut; /* 0x37, P96003 */ Byte RD_GreenGainOut; /* 0x38, P96003 */ Byte RD_BlueGainOut; /* 0x39, P96003 */ Byte RD_LedControl; /* 0x3a, P96003 */ Byte RD_ShadingCorrectCtrl; /* 0x3b, P96003 */ } Reg96, *pReg96; /* * model override defines */ #define _OVR_NONE 0 #define _OVR_PLUSTEK_9630PL 1 /* for legal version of the OP9630 */ #define _OVR_PRIMAX_4800D 2 /* for the Primax 4800 Direct */ #define _OVR_PLUSTEK_9636 3 /* for 9636T/P+/Turbo */ #define _OVR_PLUSTEK_9636P 4 /* for 9636P */ #define _OVR_PLUSTEK_A3I 5 /* for A3I */ #define _OVR_PLUSTEK_4800P 6 /* for OpticPro4800 */ #define _OVR_PRIMAX_4800D30 7 /* for the Primax 4800 Direct 30bit */ /* CHECK: THIS has to be changed and merged with the old code */ /* * structure to hold IO port specific stuff */ typedef struct { #ifdef __KERNEL__ pFnOut fnOut; pFnIn fnIn; UShort pbSppDataPort; UShort pbEppDataPort; UShort pbStatusPort; UShort pbControlPort; UShort pbAddrOffsetPort; #endif UShort portBase; UShort portMode; UShort lastPortMode; Byte bOldControlValue; Byte bOldDataValue; Byte bOpenCount; Byte delay; /* to allow various delay on port operations */ Bool slowIO; UShort forceMode; Bool useEPPCmdMode; } IODef, *pIODef; /* * structure to hold device specific stuff */ typedef struct { #if 0 PFNVOID pfnIOWrite; PFNVOID pfnCCDInit; DWORD dwLampOnTicks; DWORD dwLampOnBegin; LONG lLeftPositive; LONG lLeftNegative; UCHAR bLampOnMinutes; DRVBOOL fButton; DRVBOOL fSoftReset; UCHAR bStatusLamp; #endif pFnReadData ReadData; /* read function, portmode specific */ ULong dwModelOriginY; Bool f0_8_16; Bool fTpa; /* transparency adapter ? */ Bool f2003; /* has 2003 motor driver ? */ UChar bMotorID; /* the type of the motor drivers */ UChar bPCBID; /* which version of the PCB */ UChar bCCDID; /* what CCD do we have */ pRegDef pCCDRegisters; /* pointer to the register descr */ UShort wNumCCDRegs; /* number of values to write */ UShort DataOriginX; UChar bDACType; /* what DAC do we have */ pRegDef pDACRegisters; /* pointer to DAC reg descr. */ UShort wNumDACRegs; /* number of values to write */ pFnDACOffs fnDarkOffset; /* func-ptr to func for DAC */ pFnDACDark fnDACDark; /* adjustments */ RGBByteDef RegDACOffset; RGBByteDef RegDACGain; UChar buttons; /* Number of buttons */ UChar ModelCtrl; /* contents of the model control reg*/ UChar Model1Mono; /* for model control 1 in mono mode */ UChar Model1Color; /* for model control 1 in color mode*/ UChar XStepMono; UChar XStepColor; UChar XStepBack; long lUpNormal; /* device specific offsets */ long lUpPositive; long lUpNegative; long lLeftNormal; } DeviceDef, *pDeviceDef; /* * to hold all the shading stuff for calibrating a scanner */ typedef struct { pRGBUShortDef pHilight; ColorByte Hilight; ULong dwDiv; UShort wExposure; UShort wXStep; UChar skipHilight; UChar skipShadow; ULong shadingBytes; pDACTblDef pCcdDac; ColorByte DarkDAC; ColorWord DarkOffset; UShort wDarkLevels; UChar bIntermediate; ColorByte Gain; UChar bGainDouble; UChar bUniGain; Byte bMinGain; Byte bMaxGain; Byte bGainHigh; Byte bGainLow; Bool fStop; } ShadingDef, *pShadingDef; /* * structure to hold scan-specific data */ typedef struct _SCANDEF { #if 0 DWORD dwLinesRead; LONG lBufAdjust; DRVBOOL fBackmove; DRVBOOL fEsc; UCHAR Reserved; #endif pFnBool DoSample; pFnDataProcess DataProcess; /* to convert RGB buffers to RGB pixels */ pFnBool DataRead; /* function to get data from scanner */ ULong dwLinesToRead; /* number of images lines to read */ Long lBufferAdjust; ULong dwScanOrigin; /* where to start the scan */ Bool fRefreshState; /* refresh ? */ Bool fMotorBackward; UChar motorPower; /* how to drive the motor */ ULong dwMinReadFifo; ULong dwMaxReadFifo; Byte bFifoSelect; /* defines which FIFO to use */ UChar bDiscardAll; ULong dwInterval; ULong dwInterlace; /* CHECK: here always 0 - remove ? */ union { UShort wGreenDiscard; UShort wGreenKeep; } gd_gk; union { UShort wBlueDiscard; UShort wRedKeep; } bd_rk; UChar bRefresh; /* for controlling the movement */ UChar bOldScanState; UChar bNowScanState; UChar bModuleState; DataPointer p48BitBuf; /* for handling 48-bit data */ union { pUChar pMonoBuf; DataPointer ColorBuf; } bp; RBGPtrDef BufBegin; /* for reading/writing the scan-data */ RBGPtrDef BufEnd; RBGPtrDef BufGet; RBGPtrDef BufData; RBGPtrDef BufPut; ULong negBegin; /* used while scanning in TPA modes */ ULong posBegin; ULong dpiIdx; /* index to get/set values in the table */ pExtXStepDef negScan; /* reference to exposure/xtep table */ } ScanDef, *pScanDef; /* * structure to hold buffer pointers */ typedef struct { union { pUChar pReadBuf; pUChar pShadingMap; pUChar pRWTestBuffer; pUShort pShadingRam; DataPointer Buf; } b1; union { pUChar pSumBuf; pRGBUShortDef pSumRGB; pUChar pRWTestBuffer1; } b2; DataPointer TpaBuf; } BufferDef, *pBufferDef; /* Register RegBitDepth (Addr: 0x13) - ASIC 9800x */ #define _BIT0_7 0x00 #define _BIT8_15 0x01 #define _BIT16_20 0x02 /* Register RegStepControl (Addr: 0x14) - ASIC 9800x */ #define _MOTOR0_ONESTEP 0x01 #define _MOTOR0_SCANSTATE 0x02 #define _MOTOR_FREERUN 0x40 #define _MOTOR_NOFREERUN 0x00 /* Register RegGetScanState (Addr: 0x17, 0x12 on 9600x) - ASIC 9800x */ #define _SCANSTATE_MASK 0x3f /* bit 0-5 */ #define _SCANSTATE_STOP 0x80 /* Register RegReadIOBufBus (Addr: 0x17) - ASIC 9600x only */ #define _IOBUF_BUSMASK 0x0f /* bit 0-3 */ /* Register RegMemoryLow/High (Addr: 0x19/0x1a) - ASIC 9800x */ #define _MAP_ADDR_RED 0x00 #define _MAP_ADDR_GREEN 0x40 #define _MAP_ADDR_BLUE 0x80 #define _MAP_ADDR_SIZE 0x40 /* 0x4000 */ /* Register RegModeControl (Addr: 0x1b, 0x18 on 9600x) - all ASICs*/ #define _ModeScan 0x00 /* all ASICs */ #define _ModeProgram 0x01 /* 9600x def */ #define _ModeIdle 0x01 /* 9800x defs */ #define _ModeShadingMem 0x02 #define _ModeMappingMem 0x03 #define _ModeReadMappingMem 0x07 #define _ModeFifoRSel 0x00 #define _ModeFifoGSel 0x08 #define _ModeFifoBSel 0x10 #define _ModeFifoClose 0x18 /* Register RegLineControl (Addr: 0x1c, 0x19 on 9600x) - all ASICs*/ #define _LINE_SCANTIME_MASK 0x3f /* bit 0-6 */ #define _LINE_CDSINVERSE 0x80 /* Color Drive Signal */ /* Register RegScanControl (Addr: 0x1d) - all ASICs*/ #define _SCAN_BITMODE 0x00 #define _SCAN_BYTEMODE 0x01 /* Gray/Color mode */ #define _SCAN_1ST_AVERAGE 0x04 /* first pixel is averaged pixel */ #define _SCAN_BITDIRR2L 0x08 /* bit shift from right to left */ /* ASIC 9600x section */ #define _P96_SCANDATA_INVERT 0x02 #define _SCAN_LAMP_ON 0x10 /* ASIC 9800x section */ #define _SCAN_12BITMODE 0x02 #define _SCAN_NORMALLAMP_ON 0x10 /* normal Lamp */ #define _SCAN_TPALAMP_ON 0x20 #define _P98_SCANDATA_INVERT 0x40 #define _BITALIGN_LEFT 0x80 #define _SCAN_LAMPS_ON (_SCAN_NORMALLAMP_ON | _SCAN_TPALAMP_ON) /* Register RegMotor0Control (Addr: 0x15) */ #define _MotorDirForward 0x01 #define _MotorDirBackward 0x00 #define _MotorOn 0x02 #define _MotorHFullStepH 0x00 #define _MotorHHalfStep 0x04 #define _MotorHQuarterStep 0x08 #define _MotorHEightStep 0x08 /* for 2916 driver */ #define _MotorPowerEnable 0x40 /* ASIC 98003 specific */ #define _MotorHHomeStop 0x80 #define _FORWARD_MOTOR (_MotorDirForward + _MotorOn + \ _MotorHQuarterStep + _MotorPowerEnable) /* Register RegConfiguration (Addr: 0x1e), ASIC 9800x */ #define _P98_CCD_TYPE_ID 0x07 #define _P98_NEC_MACHINE 0x08 #define _P98_PCBID 0xF0 #define _CCD_3797 0 #define _CCD_3717 1 #define _CCD_3799 1 /* new for 98003 */ #define _CCD_535 2 #define _CCD_2556 3 #define _CCD_518 4 #define _CCD_539 5 /* default for 98001 */ #define _CCD_3777 6 /* new for 98003 */ #define _CCD_548 7 /* new for 98003 */ /* ASIC 98003 section */ #define _OPTICWORKS2000 0x00 #define _PLUSTEK_SCANNER 0x10 #define _SCANNER_WITH_TPA 0x20 #define _SCANNER4Button 0x30 #define _SCANNER4ButtonTPA 0x40 #define _SCANNER5Button 0x50 #define _SCANNER5ButtonTPA 0x60 #define _SCANNER1Button 0x70 #define _SCANNER1ButtonTPA 0x80 #define _SCANNER2Button 0x90 #define _AGFA_SCANNER 0xf0 #define _AGFA_PCB 0x1f /* Register RegModelControl (Addr: 0x1f), all ASICs */ #define _ModelSampleAndHold 0x01 /* sample and hold */ #define _ModelWhiteIs0 0x02 /* white is 0 */ #define _ModelInvertPF 0x04 /* invert paper flag */ #define _ModelDpi200 0 /* (400 / 2) */ #define _ModelDpi300 0x08 /* (600 / 2) */ #define _ModelDpi400 0x10 /* (800 / 2) */ #define _ModelDpi600 0x18 /* (1200 / 2) */ #define _ModelMemSize32k3 0 /* 32k for 300 dpi color */ #define _ModelMemSize64k3 0x20 /* 64k for 300 dpi color */ #define _ModelMemSize128k3 0x40 /* 128k for 300 dpi color */ #define _ModelMemSize64k4 0x60 /* 64k for 400/600 dpi color */ #define _ModelMemSize128k4 0x80 /* 128k for 400/600 dpi color */ #define _ModelMemSize8k 0 /* for 96001 */ #define _ModelMemSize8k3 0x20 #define _ModelMemSize32k96001 0x40 #define _ModelMemSize128k396001 0x60 #define _ModelMemSize128k696001 0x80 #define _HOME_SENSOR_POLARITY 0x01 /* 9800x */ #define _LED_CONTROL 0x02 #define _LED_ACTIVITY 0x04 #define _MODEL_DPI800 0x20 #define _MODEL_DPI1200 0x28 #define _DUMMY_12BIT 0x40 /* Register RegModel1Control (Addr: 0x20), 9800x */ #define _SCAN_GRAYTYPE 0x01 #define _CCD_SHIFT_GATE 0x02 #define _CCD_SHIFT_PULSE 0x04 #define _BUTTON_MODE 0x08 #define _MOTOR_2003 0x00 #define _MOTOR_2916 0x10 #define _MOTOR_7042 0x20 /* Register RegThresholdGapControl (Addr: 0x29, 0x27 on 9600x ) - all ASICs */ #define _THRESHOLDGAP_MASK 0x0f /* Register RegResetConfig (Addr: 0x2e) */ #define _ADC_MASK 0x07 #define _DA_WOLFSON8143 0x00 #define _DA_ESIC 0x04 #define _DA_SAMSUNG8531 0x05 #define _DA_WOLFSON8141 0x06 #define _DA_SAMSUNG1224 0x07 #define _MOTOR0_MASK 0x18 #define _MOTOR0_2003 0x00 #define _MOTOR0_2916 0x08 #define _MOTOR0_7042 0x10 #define _MOTOR1_MASK 0x60 #define _MOTOR1_2003 0x00 #define _MOTOR1_2916 0x20 #define _MOTOR1_7042 0x40 /* Register RegFifoFullLength (Addr: 0x54) */ #define _RED_FULLSIZE 0x00 #define _GREEN_FULLSIZE 0x08 #define _BLUE_FULLSIZE 0x10 /* Register RegScanControl1 (Addr: 0x5b) */ #define _MTSC_ENABLE 0x01 #define _SCANSTOPONBUFFULL 0x02 #define _MFRC_RUNSCANSTATE 0x04 #define _MFRC_BY_XSTEP 0x08 /* Register RegMotorDriverType (Addr: 0x64) */ #define _MOTORS_MASK 0x33 #define _MOTORR_MASK 0xf3 #define _MOTORR_WEAK 0x04 #define _MOTORR_MEDIUM 0x08 #define _MOTORR_STRONG 0x0c #define _MOTORT_WEAK 0x40 #define _MOTORT_MEDIUM 0x80 #define _MOTORT_STRONG 0xc0 #define _BUTTON_SELECT1 0x40 #define _BUTTON_SELECT2 0x80 #define _BUTTON_DISABLE 0xc0 /* Register RegStatus2 (Addr: 0x66) */ #define _REFLECTIONLAMP_ON 0x01 #define _TPALAMP_ON 0x02 #define _STILL_FREE_RUNNING 0x04 #define _BUFFER_IS_FULL 0x08 /* Register RegTestMode (Addr: 0xf0) */ #define _SW_TESTMODE 0x20 /* other stuff... */ /* CHECK: changes this stuff... */ #define _BytesPerChannel 5500UL #define _SizeDataBuf (ULong)(_BytesPerChannel * 3 * 2) #define _SizeTpaDataBuf (ULong)(_BytesPerChannel * 3 * 2) #define _SizeShadingSumBuf (ULong)(_BytesPerChannel * 3 * 4) #define _SizeTotalBuf (ULong)(_SizeDataBuf + _SizeShadingSumBuf) #define _SizeTotalBufTpa (ULong)(_SizeTotalBuf + _SizeTpaDataBuf) /* for DAC programming (ASIC 98003)*/ #define _VALUE_CONFIG 0x51 #define _DAC_RED (Byte)(_VALUE_CONFIG | 0x00) #define _DAC_GREENCOLOR (Byte)(_VALUE_CONFIG | 0x04) #define _DAC_GREENMONO (Byte)(_VALUE_CONFIG | 0x06) #define _DAC_BLUE (Byte)(_VALUE_CONFIG | 0x08) /* internal FIFO buffers (ASIC 9800x) */ #define _SIZE_REDFIFO 196608UL /* 192k */ #define _SIZE_GREENFIFO 147456UL /* 144k */ #define _SIZE_BLUEFIFO 114688UL /* 112k */ #define _SIZE_COLORFIFO _SIZE_BLUEFIFO #define _SIZE_GRAYFIFO (_SIZE_REDFIFO + _SIZE_GREENFIFO + _SIZE_BLUEFIFO) /* Scan State Definitions */ #define _SS_STEP 0x08 #define _SS_RED 0x04 #define _SS_GREEN 0x02 #define _SS_BLUE 0x01 #define _SS_MONO _SS_GREEN #define _SS_COLOR (_SS_RED | _SS_GREEN | _SS_BLUE) /* for shading */ #define _CHANNEL_RED 0 #define _CHANNEL_GREEN 1 #define _CHANNEL_BLUE 2 #endif /* guard __HWDEFS_H__ */ /* END PLUSTEK-PP_HWDEFS.H ..................................................*/ sane-backends-1.0.27/backend/u12.conf.in0000664000175000017500000000272712112021330014465 00000000000000# U12-SANE Backend configuration file # # each device needs at least two lines: # - [usb] vendor-ID and product-ID # - device devicename # i.e. for Plustek (0x07B3) U1212 (0x0001) # [usb] 0x07B3 0x0001 # device /dev/usbscanner # or # device libusb:bbb:ddd # where bbb is the busnumber and ddd the device number # make sure that your user has access to /proc/bus/usb/bbb/ddd # # additionally you can specify some options # warmup, lOffOnEnd, lampOff # # For autodetection use # [usb] # device /dev/usbscanner # # or simply # [usb] # # or if you want a specific device but you have no idea about the # device node or you use libusb, simply set vendor- and product-ID # [usb] 0x07B3 0x0001 # device auto # # NOTE: autodetection is safe, as it uses the info it got # from the USB subsystem. If you're not using the # autodetection, you MUST have attached that device # at your USB-port, that you have specified... # [usb] # # options for the previous USB entry # # switch lamp off after xxx secs, 0 disables the feature option lampOff 300 # warmup period in seconds, 0 means no warmup option warmup 15 # 0 means leave lamp-status untouched, not 0 means switch off # on sane_close option lOffOnEnd 1 # # for adjusting the default gamma values # #option redGamma 1.5 #option greenGamma 1.5 #option blueGamma 1.5 #option grayGamma 1.5 # # and of course the device-name # device auto # # to define a new device, start with a new section: # [usb] # sane-backends-1.0.27/backend/u12-map.c0000664000175000017500000001323012112021330014117 00000000000000/* @file u12_map.c * @brief functions to create and manipulate gamma lookup tables. * * Copyright (C) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - inverting map when scanning binary images * - changed u12map_Adjust() * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /** * @param s - pointer to the scanner specific structure * @return The function always returns SANE_STATUS_GOOD */ static SANE_Status u12map_InitGammaSettings( U12_Device *dev ) { int i, j, val; double gamma; dev->gamma_length = 4096; dev->gamma_range.min = 0; dev->gamma_range.max = 255; dev->gamma_range.quant = 0; DBG( _DBG_INFO, "Presetting Gamma tables (len=%u)\n", dev->gamma_length ); DBG( _DBG_INFO, "----------------------------------\n" ); /* preset the gamma maps */ for( i = 0; i < 4; i++ ) { switch( i ) { case 1: gamma = dev->adj.rgamma; break; case 2: gamma = dev->adj.ggamma; break; case 3: gamma = dev->adj.bgamma; break; default: gamma = dev->adj.graygamma; break; } for( j = 0; j < dev->gamma_length; j++ ) { val = (dev->gamma_range.max * pow((double) j / ((double)dev->gamma_length - 1.0), 1.0 / gamma )); if( val > dev->gamma_range.max ) val = dev->gamma_range.max; dev->gamma_table[i][j] = val; } } return SANE_STATUS_GOOD; } /** Check the gamma vectors we got back and limit if necessary * @param s - pointer to the scanner specific structure * @return nothing */ static void u12map_CheckGammaSettings( U12_Device *dev ) { int i, j; for( i = 0; i < 4 ; i++ ) { for( j = 0; j < dev->gamma_length; j++ ) { if( dev->gamma_table[i][j] > dev->gamma_range.max ) { dev->gamma_table[i][j] = dev->gamma_range.max; } } } } /** adjust acording to brightness and contrast */ static void u12map_Adjust( U12_Device *dev, int which, SANE_Byte *buf ) { int i; u_long *pdw; double b, c, tmp; DBG( _DBG_INFO, "u12map_Adjust(%u)\n", which ); /* adjust brightness (b) and contrast (c) using the function: * * s'(x,y) = (s(x,y) + b) * c * b = [-127, 127] * c = [0,2] */ /* scale brightness and contrast... */ b = ((double)dev->DataInf.siBrightness * 192.0)/100.0; c = ((double)dev->DataInf.siContrast + 100.0)/100.0; DBG( _DBG_INFO, "* brightness = %i -> %i\n", dev->DataInf.siBrightness, (SANE_Byte)b); DBG( _DBG_INFO, "* contrast*100 = %i -> %i\n", dev->DataInf.siContrast, (int)(c*100)); for( i = 0; i < dev->gamma_length; i++ ) { if((_MAP_MASTER == which) || (_MAP_RED == which)) { tmp = ((double)(dev->gamma_table[0][i] + b)) * c; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; buf[i] = (SANE_Byte)tmp; } if((_MAP_MASTER == which) || (_MAP_GREEN == which)) { tmp = ((double)(dev->gamma_table[1][i] + b)) * c; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; buf[4096+i] = (SANE_Byte)tmp; } if((_MAP_MASTER == which) || (_MAP_BLUE == which)) { tmp = ((double)(dev->gamma_table[2][i] + b)) * c; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; buf[8192+i] = (SANE_Byte)tmp; } } if((dev->DataInf.dwScanFlag & _SCANDEF_Negative) || (dev->DataInf.wPhyDataType == COLOR_BW)) { DBG( _DBG_INFO, "inverting...\n" ); if((_MAP_MASTER == which) || (_MAP_RED == which)) { DBG( _DBG_INFO, "inverting RED map\n" ); pdw = (u_long*)&buf[0]; for( i = dev->gamma_length / 4; i; i--, pdw++ ) *pdw = ~(*pdw); } if((_MAP_MASTER == which) || (_MAP_GREEN == which)) { DBG( _DBG_INFO, "inverting GREEN map\n" ); pdw = (u_long*)&buf[4096]; for( i = dev->gamma_length / 4; i; i--, pdw++ ) *pdw = ~(*pdw); } if((_MAP_MASTER == which) || (_MAP_BLUE == which)) { DBG( _DBG_INFO, "inverting BLUE map\n" ); pdw = (u_long*)&buf[8192]; for( i = dev->gamma_length / 4; i; i--, pdw++ ) *pdw = ~(*pdw); } } } /* END U12-MAP.C ............................................................*/ sane-backends-1.0.27/backend/umax-scanner.c0000664000175000017500000001104712112021330015342 00000000000000/* -------------------------------------------------------------------- */ /* umax-scanner.c: scanner-definiton file for UMAX scanner driver. (C) 1997-2004 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* -------------------------------------------------------------------- */ #include "umax-scanner.h" /* ==================================================================== */ /* scanners that are supported because the driver knows missing */ /* inquiry-data */ /* these umax-*.c files are included and not compiled separately */ /* because this way the symbols are not exported */ #include "umax-uc630.c" #include "umax-uc840.c" #include "umax-ug630.c" #include "umax-ug80.c" #include "umax-uc1200s.c" #include "umax-uc1200se.c" #include "umax-uc1260.c" static inquiry_blk *inquiry_table[] = { &inquiry_uc630, &inquiry_uc840, &inquiry_ug630, &inquiry_ug80, &inquiry_uc1200s, &inquiry_uc1200se, &inquiry_uc1260 }; #define known_inquiry 7 /* ==================================================================== */ /* names of scanners that are supported because */ /* the inquiry_return_block is ok and driver is tested */ static char *scanner_str[] = { "UMAX ", "Vista-T630 ", "UMAX ", "Vista-S6 ", "UMAX ", "Vista-S6E ", "UMAX ", "UMAX S-6E ", "UMAX ", "UMAX S-6EG ", "UMAX ", "Vista-S8 ", "UMAX ", "UMAX S-12 ", "UMAX ", "UMAX S-12G ", "UMAX ", "SuperVista S-12 ", "UMAX ", "PSD ", "UMAX ", "Astra 600S ", "UMAX ", "Astra 610S ", "UMAX ", "Astra 1200S ", "UMAX ", "Astra 1220S ", "UMAX ", "Astra 2100S ", "UMAX ", "Astra 2200 ", "UMAX ", "Astra 2400S ", /* "UMAX ", "Astra 6400 ", */ /* this is a firewire scanner */ /* "UMAX ", "Astra 6450 ", */ /* this is a firewire scanner */ "UMAX ", "Mirage D-16L ", "UMAX ", "Mirage II ", "UMAX ", "Mirage IIse ", "UMAX ", "PL-II ", "UMAX ", "Power Look 2000 ", "UMAX ", "PowerLook 2100XL", "UMAX ", "PowerLook III ", "UMAX ", "PowerLook 3000 ", "UMAX ", "Gemini D-16 ", "UMAX ", "PS-2400X ", /* same as LinoHell SAPHIR */ "LinoHell", "JADE ", /* is a Supervista S-12 */ "LinoHell", "Office ", /* is a Supervista S-12 */ "LinoHell", "Office2 ", "LinoHell", "SAPHIR ", /* same as UMAX PS-2400X */ "LinoHell", "SAPHIR2 ", "LinoHell", "SAPHIR3 ", /* 1000x2000 dpi */ /* "LinoHell", "SAPHIR4 ", */ "Linotype", "SAPHIR4 ", /* Linotype-Hell Saphir Ultra II */ /* "LinoHell", "OPAL ", */ "LinoHell", "OPAL2 ", /* looks like a UMAX Mirage II */ "HDM ", "LS4H1S ", /* Linoscan 1400 */ "Nikon ", "AX-110 ", /* is a Vista S6E */ "Nikon ", "AX-210 ", /* is a Supervista S12 */ "KYE ", "ColorPage-HR5 ", "EPSON ", "Perfection600 ", "ESCORT ", "Galleria 600S ", /* is an Astra 600S */ "EDGE ", "KTX-9600US ", /* may be an Astra 1220S */ "TriGem ", "PowerScanII ", /* is a Supervista S12 */ "END_OF_LIST" }; /* ==================================================================== */ sane-backends-1.0.27/backend/snapscan-usb.c0000664000175000017500000004674512112021330015353 00000000000000/* Snapscan 1212U modifications for the Snapscan SANE backend Copyright (C) 2000 Henrik Johansson Henrik Johansson (henrikjo@post.urfors.se) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements USB equivalents to the SCSI routines used by the Snapscan backend. History 0.1 2000-02-01 First version released 0.2 2000-02-12 The Send Diagnostics SCSI command seems to hang some 1212U scanners. Bypassing this command fixes the problem. This bug was reported by Dmitri (dmitri@advantrix.com). 0.3 2000-02-13 The "Set window" command returns with status "Device busy" when the scanner is busy. One consequence is that some frontends exits with an error message if it's started when the scanner is warming up. A solution was suggested by Dmitri (dmitri@advantrix.com) The idea is that a SCSI command which returns "device busy" is stored in a "TODO" queue. The send command function is modified to first send commands in the queue before the intended command. So far this strategy has worked flawlessly. Thanks Dmitri! */ /* $Id$ SnapScan backend scan data sources */ #include "snapscan-usb.h" #include "snapscan-mutex.c" #ifndef SHM_R #define SHM_R 0 #endif #ifndef SHM_W #define SHM_W 0 #endif /* Global variables */ static snapscan_mutex_t snapscan_mutex; static sense_handler_type usb_sense_handler; static void* usb_pss; struct urb_counters_t { unsigned long read_urbs; unsigned long write_urbs; }; static struct urb_counters_t* urb_counters = NULL; /* Forward declarations */ static SANE_Status usb_request_sense(SnapScan_Scanner *pss); static SANE_Status snapscani_usb_cmd(int fd, const void *src, size_t src_size, void *dst, size_t * dst_size) { static const char me[] = "snapscani_usb_cmd"; int status; DBG (DL_CALL_TRACE, "%s(%d,0x%lx,%lu,0x%lx,0x%lx (%lu))\n", me, fd, (u_long) src,(u_long) src_size,(u_long) dst, (u_long) dst_size,(u_long) (dst_size ? *dst_size : 0)); while(bqhead) { status = atomic_usb_cmd(fd, bqhead->src, bqhead->src_size, NULL, NULL); if(status == SANE_STATUS_DEVICE_BUSY) { if(is_queueable(src)) { enqueue_bq(fd,src,src_size); return SANE_STATUS_GOOD; } else { sleep(1); continue; } } dequeue_bq(); } status = atomic_usb_cmd(fd,src,src_size,dst,dst_size); if ((status == SANE_STATUS_DEVICE_BUSY) && is_queueable(src) ) { enqueue_bq(fd,src,src_size); return SANE_STATUS_GOOD; } return status; } static SANE_Status atomic_usb_cmd(int fd, const void *src, size_t src_size, void *dst, size_t * dst_size) { static const char me[] = "atomic_usb_cmd"; int status; sigset_t all,oldset; DBG (DL_CALL_TRACE, "%s(%d,0x%lx,%lu,0x%lx,0x%lx (%lu))\n", me, fd, (u_long) src,(u_long) src_size,(u_long) dst, (u_long) dst_size,(u_long) (dst_size ? *dst_size : 0)); /* Prevent the calling process from being killed */ sigfillset(&all); sigprocmask(SIG_BLOCK, &all, &oldset); /* Make sure we are alone */ snapscani_mutex_lock(&snapscan_mutex); status = usb_cmd(fd,src,src_size,dst,dst_size); snapscani_mutex_unlock(&snapscan_mutex); /* Now it is ok to be killed */ sigprocmask(SIG_SETMASK, &oldset, NULL); return status; } static SANE_Status snapscani_usb_open(const char *dev, int *fdp, sense_handler_type sense_handler, void* pss) { static const char me[] = "snapscani_usb_open"; DBG (DL_CALL_TRACE, "%s(%s)\n", me, dev); if(!snapscani_mutex_open(&snapscan_mutex, dev)) { DBG (DL_MAJOR_ERROR, "%s: Can't get semaphore\n", me); return SANE_STATUS_INVAL; } usb_sense_handler=sense_handler; usb_pss = pss; urb_counters->read_urbs = 0; urb_counters->write_urbs = 0; return sanei_usb_open(dev, fdp); } static void snapscani_usb_close(int fd) { static const char me[] = "snapscani_usb_close"; SANE_Word vendor_id, product_id; DBG (DL_CALL_TRACE, "%s(%d)\n", me, fd); DBG (DL_DATA_TRACE,"1st read %ld write %ld\n", urb_counters->read_urbs, urb_counters->write_urbs); /* Check if URB counting is needed. If yes, ensure the number of sent and received URBs is even. Odd number of URBs only cause problems with libusb and certain scanner models. On other scanner models, sending additional commands seems to cause problems (e.g. 1212u_2). If sanei_usb_get_vendor_product returns an error there's probably no libusb, so everything's fine. */ if (sanei_usb_get_vendor_product(fd, &vendor_id, &product_id) == SANE_STATUS_GOOD) { /* Exclude 1212u_2 */ if (!((vendor_id == USB_VENDOR_AGFA) && (product_id == USB_PRODUCT_1212U2))) { if ((urb_counters->read_urbs & 0x01) && (urb_counters->write_urbs & 0x01)) { char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0}; snapscani_usb_cmd (fd, cmd, sizeof (cmd), NULL, 0); } else if (urb_counters->read_urbs & 0x01) { size_t read_bytes; char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0}; char cmd2[] = {INQUIRY, 0, 0, 0, 120, 0}; char data[120]; read_bytes = 120; snapscani_usb_cmd (fd, cmd2, sizeof (cmd2), data, &read_bytes); snapscani_usb_cmd (fd, cmd, sizeof (cmd), NULL, 0); } else if (urb_counters->write_urbs & 0x01) { size_t read_bytes; char cmd[] = {INQUIRY, 0, 0, 0, 120, 0}; char data[120]; read_bytes = 120; snapscani_usb_cmd (fd, cmd, sizeof (cmd), data, &read_bytes); } DBG (DL_DATA_TRACE,"2nd read %ld write %ld\n", urb_counters->read_urbs, urb_counters->write_urbs); } } urb_counters->read_urbs = 0; urb_counters->write_urbs = 0; snapscani_mutex_close(&snapscan_mutex); sanei_usb_close(fd); } static int usb_cmdlen(int cmd) { switch(cmd) { case TEST_UNIT_READY: case INQUIRY: case SCAN: case REQUEST_SENSE: case RESERVE_UNIT: case RELEASE_UNIT: case SEND_DIAGNOSTIC: return 6; case SEND: case SET_WINDOW: case READ: case GET_DATA_BUFFER_STATUS: return 10; } return 0; } static char *usb_debug_data(char *str,const char *data, int len) { char tmpstr[10]; int i; str[0]=0; for(i=0; i < (len < 10 ? len : 10); i++) { sprintf(tmpstr," 0x%02x",((int)data[i]) & 0xff); if(i%16 == 0 && i != 0) strcat(str,"\n"); strcat(str,tmpstr); } if(i < len) strcat(str," ..."); return str; } #define RETURN_ON_FAILURE(x) if((status = x) != SANE_STATUS_GOOD) return status; static SANE_Status usb_write(int fd, const void *buf, size_t n) { char dbgmsg[16384]; SANE_Status status; size_t bytes_written = n; static const char me[] = "usb_write"; DBG(DL_DATA_TRACE, "%s: writing: %s\n",me,usb_debug_data(dbgmsg,buf,n)); status = sanei_usb_write_bulk(fd, (const SANE_Byte*)buf, &bytes_written); if(bytes_written != n) { DBG (DL_MAJOR_ERROR, "%s Only %lu bytes written\n",me, (u_long) bytes_written); status = SANE_STATUS_IO_ERROR; } urb_counters->write_urbs += (bytes_written + 7) / 8; DBG (DL_DATA_TRACE, "Written %lu bytes\n", (u_long) bytes_written); return status; } static SANE_Status usb_read(SANE_Int fd, void *buf, size_t n) { char dbgmsg[16384]; static const char me[] = "usb_read"; SANE_Status status; size_t bytes_read = n; status = sanei_usb_read_bulk(fd, (SANE_Byte*)buf, &bytes_read); if (bytes_read != n) { DBG (DL_MAJOR_ERROR, "%s Only %lu bytes read\n",me, (u_long) bytes_read); status = SANE_STATUS_IO_ERROR; } urb_counters->read_urbs += ((63 + bytes_read) / 64); DBG(DL_DATA_TRACE, "%s: reading: %s\n",me,usb_debug_data(dbgmsg,buf,n)); DBG(DL_DATA_TRACE, "Read %lu bytes\n", (u_long) bytes_read); return status; } static SANE_Status usb_read_status(int fd, int *scsistatus, int *transaction_status, char command) { static const char me[] = "usb_read_status"; unsigned char status_buf[8]; int scsistat; int status; RETURN_ON_FAILURE(usb_read(fd,status_buf,8)); if(transaction_status) *transaction_status = status_buf[0]; scsistat = (status_buf[1] & STATUS_MASK) >> 1; if(scsistatus) *scsistatus = scsistat; switch(scsistat) { case GOOD: return SANE_STATUS_GOOD; case CHECK_CONDITION: if (usb_pss != NULL) { if (command != REQUEST_SENSE) { return usb_request_sense(usb_pss); } else { /* Avoid recursive calls of usb_request_sense */ return SANE_STATUS_GOOD; } } else { DBG (DL_MAJOR_ERROR, "%s: scanner structure not set, returning default error\n", me); return SANE_STATUS_DEVICE_BUSY; } break; case BUSY: return SANE_STATUS_DEVICE_BUSY; default: return SANE_STATUS_IO_ERROR; } } static SANE_Status usb_cmd(int fd, const void *src, size_t src_size, void *dst, size_t * dst_size) { static const char me[] = "usb_cmd"; int status,tstatus; int cmdlen,datalen; char command; DBG (DL_CALL_TRACE, "%s(%d,0x%lx,%lu,0x%lx,0x%lx (%lu))\n", me, fd, (u_long) src,(u_long) src_size,(u_long) dst, (u_long) dst_size,(u_long) (dst_size ? *dst_size : 0)); /* Since the "Send Diagnostic" command isn't supported by all Snapscan USB-scanners it's disabled . */ command = ((const char *)src)[0]; if(command == SEND_DIAGNOSTIC) return(SANE_STATUS_GOOD); cmdlen = usb_cmdlen(*((const char *)src)); datalen = src_size - cmdlen; DBG(DL_DATA_TRACE, "%s: cmdlen=%d, datalen=%d\n",me,cmdlen,datalen); /* Send command to scanner */ RETURN_ON_FAILURE( usb_write(fd,src,cmdlen) ); /* Read status */ RETURN_ON_FAILURE( usb_read_status(fd, NULL, &tstatus, command) ); /* Send data only if the scanner is expecting it */ if(datalen > 0 && (tstatus == TRANSACTION_WRITE)) { /* Send data to scanner */ RETURN_ON_FAILURE( usb_write(fd, ((const SANE_Byte *) src) + cmdlen, datalen) ); /* Read status */ RETURN_ON_FAILURE( usb_read_status(fd, NULL, &tstatus, command) ); } /* Receive data only when new data is waiting */ if(dst_size && *dst_size && (tstatus == TRANSACTION_READ)) { RETURN_ON_FAILURE( usb_read(fd,dst,*dst_size) ); /* Read status */ RETURN_ON_FAILURE( usb_read_status(fd, NULL, &tstatus, command) ); } if(tstatus != TRANSACTION_COMPLETED) { if(tstatus == TRANSACTION_WRITE) DBG(DL_MAJOR_ERROR, "%s: The transaction should now be completed, but the scanner is expecting more data" ,me); else DBG(DL_MAJOR_ERROR, "%s: The transaction should now be completed, but the scanner has more data to send" ,me); return SANE_STATUS_IO_ERROR; } return status; } /* Busy queue data structures and function implementations*/ static int is_queueable(const char *src) { switch(src[0]) { case SEND: case SET_WINDOW: case SEND_DIAGNOSTIC: return 1; default: return 0; } } static struct usb_busy_queue *bqhead=NULL,*bqtail=NULL; static int bqelements=0; static int enqueue_bq(int fd,const void *src, size_t src_size) { static const char me[] = "enqueue_bq"; struct usb_busy_queue *bqe; DBG (DL_CALL_TRACE, "%s(%d,%p,%lu)\n", me, fd,src, (u_long) src_size); if((bqe = malloc(sizeof(struct usb_busy_queue))) == NULL) return -1; if((bqe->src = malloc(src_size)) == NULL) return -1; memcpy(bqe->src,src,src_size); bqe->src_size=src_size; bqe->next=NULL; if(bqtail) { bqtail->next=bqe; bqtail = bqe; } else bqhead = bqtail = bqe; bqelements++; DBG(DL_DATA_TRACE, "%s: Busy queue: elements=%d, bqhead=%p, bqtail=%p\n", me,bqelements,(void*)bqhead,(void*)bqtail); return 0; } static void dequeue_bq() { static const char me[] = "dequeue_bq"; struct usb_busy_queue *tbqe; DBG (DL_CALL_TRACE, "%s()\n", me); if(!bqhead) return; tbqe = bqhead; bqhead = bqhead->next; if(!bqhead) bqtail=NULL; if(tbqe->src) free(tbqe->src); free(tbqe); bqelements--; DBG(DL_DATA_TRACE, "%s: Busy queue: elements=%d, bqhead=%p, bqtail=%p\n", me,bqelements,(void*)bqhead,(void*)bqtail); } static SANE_Status usb_request_sense(SnapScan_Scanner *pss) { static const char *me = "usb_request_sense"; size_t read_bytes = 0; u_char cmd[] = {REQUEST_SENSE, 0, 0, 0, 20, 0}; u_char data[20]; SANE_Status status; read_bytes = 20; DBG (DL_CALL_TRACE, "%s\n", me); status = usb_cmd (pss->fd, cmd, sizeof (cmd), data, &read_bytes); if (status != SANE_STATUS_GOOD) { DBG (DL_MAJOR_ERROR, "%s: usb command error: %s\n", me, sane_strstatus (status)); } else { if (usb_sense_handler) { status = usb_sense_handler (pss->fd, data, (void *) pss); } else { DBG (DL_MAJOR_ERROR, "%s: No sense handler for USB\n", me); status = SANE_STATUS_UNSUPPORTED; } } return status; } #if defined USE_PTHREAD || defined HAVE_OS2_H || defined __BEOS__ static SANE_Status snapscani_usb_shm_init(void) { unsigned int shm_size = sizeof(struct urb_counters_t); urb_counters = (struct urb_counters_t*) malloc(shm_size); if (urb_counters == NULL) { return SANE_STATUS_NO_MEM; } memset(urb_counters, 0, shm_size); return SANE_STATUS_GOOD; } static void snapscani_usb_shm_exit(void) { if (urb_counters) { free ((void*)urb_counters); urb_counters = NULL; } } #else #include #include static SANE_Status snapscani_usb_shm_init(void) { unsigned int shm_size = sizeof(struct urb_counters_t); void* shm_area = NULL; int shm_id = shmget (IPC_PRIVATE, shm_size, IPC_CREAT | SHM_R | SHM_W); if (shm_id == -1) { DBG (DL_MAJOR_ERROR, "snapscani_usb_shm_init: cannot create shared memory segment: %s\n", strerror (errno)); return SANE_STATUS_NO_MEM; } shm_area = shmat (shm_id, NULL, 0); if (shm_area == (void *) -1) { DBG (DL_MAJOR_ERROR, "snapscani_usb_shm_init: cannot attach to shared memory segment: %s\n", strerror (errno)); shmctl (shm_id, IPC_RMID, NULL); return SANE_STATUS_NO_MEM; } if (shmctl (shm_id, IPC_RMID, NULL) == -1) { DBG (DL_MAJOR_ERROR, "snapscani_usb_shm_init: cannot remove shared memory segment id: %s\n", strerror (errno)); shmdt (shm_area); shmctl (shm_id, IPC_RMID, NULL); return SANE_STATUS_NO_MEM; } urb_counters = (struct urb_counters_t*) shm_area; memset(urb_counters, 0, shm_size); return SANE_STATUS_GOOD; } static void snapscani_usb_shm_exit(void) { if (urb_counters) { shmdt (urb_counters); urb_counters = NULL; } } #endif /* * $Log$ * Revision 1.22 2006/01/26 17:42:30 hmg-guest * Added #defines for SHM_R/W for cygwin (patch from Philip Aston ). * * Revision 1.21 2005/11/02 19:22:06 oliver-guest * Fixes for Benq 5000 * * Revision 1.20 2005/07/18 17:37:37 oliver-guest * ZETA changes for SnapScan backend * * Revision 1.19 2004/10/03 17:34:36 hmg-guest * 64 bit platform fixes (bug #300799). * * Revision 1.18 2004/06/16 19:52:26 oliver-guest * Don't enforce even number of URB packages on 1212u_2. Fixes bug #300753. * * Revision 1.17 2004/06/06 14:50:36 oliver-guest * Use shared memory functions only when needed * * Revision 1.16 2004/05/26 22:37:01 oliver-guest * Use shared memory for urb counters in snapscan backend * * Revision 1.15 2004/04/09 11:59:02 oliver-guest * Fixes for pthread implementation * * Revision 1.14 2004/04/08 22:48:13 oliver-guest * Use URB counting in snapscan-usb.c (thanks to Jose Alberto Reguero) * * Revision 1.13 2003/11/08 09:50:27 oliver-guest * Fix TPO scanning range for Epson 1670 * * Revision 1.12 2003/07/26 17:16:55 oliverschwartz * Changed licence to GPL + SANE exception for snapscan-usb.[ch] * * Revision 1.11 2002/07/12 23:29:06 oliverschwartz * SnapScan backend 1.4.15 * * Revision 1.21 2002/07/12 22:52:42 oliverschwartz * use sanei_usb_read_bulk() and sanei_usb_write_bulk() * * Revision 1.20 2002/04/27 14:36:25 oliverschwartz * Pass a char as 'proj' argument for ftok() * * Revision 1.19 2002/04/10 21:00:33 oliverschwartz * Make bqelements static * * Revision 1.18 2002/03/24 12:16:09 oliverschwartz * Better error report in usb_read * * Revision 1.17 2002/02/05 19:32:39 oliverschwartz * Only define union semun if not already defined in . Fixes * compilation bugs on Irix and FreeBSD. Fixed by Henning Meier-Geinitz. * * Revision 1.16 2002/01/14 21:11:56 oliverschwartz * Add workaround for bug semctl() call in libc for PPC * * Revision 1.15 2001/12/09 23:06:44 oliverschwartz * - use sense handler for USB if scanner reports CHECK_CONDITION * * Revision 1.14 2001/11/16 20:23:16 oliverschwartz * Merge with sane-1.0.6 * - Check USB vendor IDs to avoid hanging scanners * - fix bug in dither matrix computation * * Revision 1.13 2001/10/09 22:34:23 oliverschwartz * fix compiler warnings * * Revision 1.12 2001/09/18 15:01:07 oliverschwartz * - Read scanner id string again after firmware upload * to indentify correct model * - Make firmware upload work for AGFA scanners * - Change copyright notice * * */ sane-backends-1.0.27/backend/genesys.conf.in0000664000175000017500000000373013106201017015534 00000000000000# genesys.conf: Configuration file for Genesys Logic GL646 and GL841 based scanners # # scanners that are not yet supported # uncomment them only for development purpose # # UMAX Astra 4500 and Avision iVina 1600 #usb 0x0638 0x0a10 # Hewlett Packard ScanJet 2400c usb 0x03f0 0x0a01 # Hewlett Packard ScanJet 3670c/3690c usb 0x03f0 0x1405 # Plustek OpticPro ST24 #usb 0x07b3 0x0601 # Syscan DocketPort 465 #usb 0x0a82 0x4802 # # supported scanners # # Medion MD5345/MD6228/MD6471 usb 0x0461 0x0377 # Hewlett Packard ScanJet 2300c usb 0x03f0 0x0901 # Canon LiDE 35/40/50 usb 0x04a9 0x2213 # Canon LiDE 60 usb 0x04a9 0x221c # Canon LiDE 80 usb 0x04a9 0x2214 # Canon 4400F usb 0x04a9 0x2228 # Canon LiDE 100 usb 0x04a9 0x1904 # Canon LiDE 110 usb 0x04a9 0x1909 # Canon LiDE 200 usb 0x04a9 0x1905 # Canon 5600F usb 0x04a9 0x1906 # Canon LiDE 700F usb 0x04a9 0x1907 # Canon LiDE 210 usb 0x04a9 0x190a # Canon LiDE 120 usb 0x04a9 0x190e # Canon LiDE 220 usb 0x04a9 0x190f # Canon 5600f usb 0x04a9 0x1906 # Visioneer Strobe XP200 usb 0x04a7 0x0426 # Visioneer Strobe XP300 usb 0x04a7 0x0474 # Ambir/Syscan DocketPort 665 usb 0x0a82 0x4803 # Visioneer Roadwarrior usb 0x04a7 0x0494 # Visioneer XP100 rev 3 usb 0x04a7 0x049b #Pentax DSmobile 600 usb 0x0a17 0x3210 usb 0x04f9 0x2038 # Syscan DocketPort 467 usb 0x1dcc 0x4812 # Syscan DocketPort 485 usb 0x0a82 0x4800 # DCT DocketPort 487 usb 0x1dcc 0x4810 # Syscan/Ambir DocketPort 685 usb 0x0a82 0x480c # Visioneer OneTouch 7100 usb 0x04a7 0x0229 # Xerox Travel Scanner 100 usb 0x04a7 0x04ac # Panasonic KV-SS080 usb 0x04da 0x100f # Hewlett Packard ScanJet 4850C usb 0x03f0 0x1b05 # Hewlett Packard ScanJet G4010 usb 0x03f0 0x4505 # Hewlett Packard ScanJet G4050 usb 0x03f0 0x4605 # Plustek OpticBook 3600 usb 0x07b3 0x0900 # Primax Electronics, Ltd Xerox 2400 Onetouch usb 0x0461 0x038b #Hewlett Packard ScanJet N6310 usb 0x03f0 0x4705 # Canon Image Formula 101 usb 0x1803 0x162e # Plustek OpticBook 3800 usb 0x07b3 0x1300 sane-backends-1.0.27/backend/genesys_gl846.h0000664000175000017500000005364312775312261015404 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2012-2013 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "genesys.h" #define REG01 0x01 #define REG01_CISSET 0x80 #define REG01_DOGENB 0x40 #define REG01_DVDSET 0x20 #define REG01_STAGGER 0x10 #define REG01_COMPENB 0x08 #define REG01_TRUEGRAY 0x04 #define REG01_SHDAREA 0x02 #define REG01_SCAN 0x01 #define REG02 0x02 #define REG02_NOTHOME 0x80 #define REG02_ACDCDIS 0x40 #define REG02_AGOHOME 0x20 #define REG02_MTRPWR 0x10 #define REG02_FASTFED 0x08 #define REG02_MTRREV 0x04 #define REG02_HOMENEG 0x02 #define REG02_LONGCURV 0x01 #define REG03 0x03 #define REG03_LAMPDOG 0x80 #define REG03_AVEENB 0x40 #define REG03_XPASEL 0x20 #define REG03_LAMPPWR 0x10 #define REG03_LAMPTIM 0x0f #define REG04 0x04 #define REG04_LINEART 0x80 #define REG04_BITSET 0x40 #define REG04_AFEMOD 0x30 #define REG04_FILTER 0x0c #define REG04_FESET 0x03 #define REG04S_AFEMOD 4 #define REG05 0x05 #define REG05_DPIHW 0xc0 #define REG05_DPIHW_600 0x00 #define REG05_DPIHW_1200 0x40 #define REG05_DPIHW_2400 0x80 #define REG05_DPIHW_4800 0xc0 #define REG05_MTLLAMP 0x30 #define REG05_GMMENB 0x08 #define REG05_MTLBASE 0x03 #define REG06_SCANMOD 0xe0 #define REG06S_SCANMOD 5 #define REG06_PWRBIT 0x10 #define REG06_GAIN4 0x08 #define REG06_OPTEST 0x07 #define REG07_LAMPSIM 0x80 #define REG08_DRAM2X 0x80 #define REG08_MPENB 0x20 #define REG08_CIS_LINE 0x10 #define REG08_IR1ENB 0x08 #define REG08_IR2ENB 0x04 #define REG08_ENB24M 0x01 #define REG09_MCNTSET 0xc0 #define REG09_EVEN1ST 0x20 #define REG09_BLINE1ST 0x10 #define REG09_BACKSCAN 0x08 #define REG09_ENHANCE 0x04 #define REG09_SHORTTG 0x02 #define REG09_NWAIT 0x01 #define REG09S_MCNTSET 6 #define REG09S_CLKSET 4 #define REG0A_LPWMEN 0x10 #define REG0B 0x0b #define REG0B_DRAMSEL 0x07 #define REG0B_ENBDRAM 0x08 #define REG0B_ENBDRAM 0x08 #define REG0B_RFHDIS 0x10 #define REG0B_CLKSET 0xe0 #define REG0B_24MHZ 0x00 #define REG0B_30MHZ 0x20 #define REG0B_40MHZ 0x40 #define REG0B_48MHZ 0x60 #define REG0B_60MHZ 0x80 #define REG0C 0x0c #define REG0C_CCDLMT 0x0f #define REG0D 0x0d #define REG0D_SCSYNC 0x40 #define REG0D_CLRERR 0x20 #define REG0D_FULLSTP 0x10 #define REG0D_SEND 0x80 #define REG0D_CLRMCNT 0x04 #define REG0D_CLRDOCJM 0x02 #define REG0D_CLRLNCNT 0x01 #define REG0F 0x0f #define REG16_CTRLHI 0x80 #define REG16_TOSHIBA 0x40 #define REG16_TGINV 0x20 #define REG16_CK1INV 0x10 #define REG16_CK2INV 0x08 #define REG16_CTRLINV 0x04 #define REG16_CKDIS 0x02 #define REG16_CTRLDIS 0x01 #define REG17_TGMODE 0xc0 #define REG17_TGMODE_NO_DUMMY 0x00 #define REG17_TGMODE_REF 0x40 #define REG17_TGMODE_XPA 0x80 #define REG17_TGW 0x3f #define REG17S_TGW 0 #define REG18 0x18 #define REG18_CNSET 0x80 #define REG18_DCKSEL 0x60 #define REG18_CKTOGGLE 0x10 #define REG18_CKDELAY 0x0c #define REG18_CKSEL 0x03 #define REG1A_SW2SET 0x80 #define REG1A_SW1SET 0x40 #define REG1A_MANUAL3 0x02 #define REG1A_MANUAL1 0x01 #define REG1A_CK4INV 0x08 #define REG1A_CK3INV 0x04 #define REG1A_LINECLP 0x02 #define REG1C 0x1c #define REG1C_TGTIME 0x07 #define REG1D_CK4LOW 0x80 #define REG1D_CK3LOW 0x40 #define REG1D_CK1LOW 0x20 #define REG1D_TGSHLD 0x1f #define REG1DS_TGSHLD 0 #define REG1E_WDTIME 0xf0 #define REG1ES_WDTIME 4 #define REG1E_LINESEL 0x0f #define REG1ES_LINESEL 0 #define REG_FEDCNT 0x1f #define REG24 0x1c #define REG40 0x40 #define REG40_DOCSNR 0x80 #define REG40_ADFSNR 0x40 #define REG40_COVERSNR 0x20 #define REG40_CHKVER 0x10 #define REG40_DOCJAM 0x08 #define REG40_HISPDFLG 0x04 #define REG40_MOTMFLG 0x02 #define REG40_DATAENB 0x01 #define REG41_PWRBIT 0x80 #define REG41_BUFEMPTY 0x40 #define REG41_FEEDFSH 0x20 #define REG41_SCANFSH 0x10 #define REG41_HOMESNR 0x08 #define REG41_LAMPSTS 0x04 #define REG41_FEBUSY 0x02 #define REG41_MOTORENB 0x01 #define REG58_VSMP 0xf8 #define REG58S_VSMP 3 #define REG58_VSMPW 0x07 #define REG58S_VSMPW 0 #define REG59_BSMP 0xf8 #define REG59S_BSMP 3 #define REG59_BSMPW 0x07 #define REG59S_BSMPW 0 #define REG5A_ADCLKINV 0x80 #define REG5A_RLCSEL 0x40 #define REG5A_CDSREF 0x30 #define REG5AS_CDSREF 4 #define REG5A_RLC 0x0f #define REG5AS_RLC 0 #define REG5E_DECSEL 0xe0 #define REG5ES_DECSEL 5 #define REG5E_STOPTIM 0x1f #define REG5ES_STOPTIM 0 #define REG60 0x60 #define REG60_Z1MOD 0x1f #define REG61 0x61 #define REG61_Z1MOD 0xff #define REG62 0x62 #define REG62_Z1MOD 0xff #define REG63 0x63 #define REG63_Z2MOD 0x1f #define REG64 0x64 #define REG64_Z2MOD 0xff #define REG65 0x65 #define REG65_Z2MOD 0xff #define REG60S_STEPSEL 5 #define REG60_STEPSEL 0xe0 #define REG60_FULLSTEP 0x00 #define REG60_HALFSTEP 0x20 #define REG60_EIGHTHSTEP 0x60 #define REG60_16THSTEP 0x80 #define REG63S_FSTPSEL 5 #define REG63_FSTPSEL 0xe0 #define REG63_FULLSTEP 0x00 #define REG63_HALFSTEP 0x20 #define REG63_EIGHTHSTEP 0x60 #define REG63_16THSTEP 0x80 #define REG67 0x67 #define REG67_MTRPWM 0x80 #define REG68 0x68 #define REG68_FASTPWM 0x80 #define REG6B 0x6b #define REG6B_MULTFILM 0x80 #define REG6B_GPOM13 0x40 #define REG6B_GPOM12 0x20 #define REG6B_GPOM11 0x10 #define REG6B_GPO18 0x02 #define REG6B_GPO17 0x01 #define REG6C 0x6c #define REG6C_GPIO16 0x80 #define REG6C_GPIO15 0x40 #define REG6C_GPIO14 0x20 #define REG6C_GPIO13 0x10 #define REG6C_GPIO12 0x08 #define REG6C_GPIO11 0x04 #define REG6C_GPIO10 0x02 #define REG6C_GPIO9 0x01 #define REG6C_GPIOH 0xff #define REG6C_GPIOL 0xff #define REG6D 0x6d #define REG6E 0x6e #define REG6F 0x6f #define REG7E 0x7e #define REG87_ACYCNRLC 0x10 #define REG87_ENOFFSET 0x08 #define REG87_LEDADD 0x04 #define REG87_CK4ADC 0x02 #define REG87_AUTOCONF 0x01 #define REG9E 0x9e #define REG9F 0x9f #define REGA6 0xa6 #define REGA7 0xa7 #define REGA8 0xa8 #define REGA9 0xa9 #define REGAB 0xab #define REG_EXPR 0x10 #define REG_EXPG 0x12 #define REG_EXPB 0x14 #define REG_EXPDMY 0x19 #define REG_STEPNO 0x21 #define REG_FWDSTEP 0x22 #define REG_BWDSTEP 0x23 #define REG_FASTNO 0x24 #define REG_DPISET 0x2c #define REG_STRPIXEL 0x30 #define REG_ENDPIXEL 0x32 #define REG_LINCNT 0x25 #define REG_MAXWD 0x35 #define REG_LPERIOD 0x38 #define REG_FEEDL 0x3d #define REG_FMOVDEC 0x5f #define REG_FSHDEC 0x69 #define REG_FMOVNO 0x6a #define REG_CK1MAP 0x74 #define REG_CK3MAP 0x77 #define REG_CK4MAP 0x7a #define REGF8 0xf8 #define REGF8_MAXSEL 0xf0 #define REGF8_SMAXSEL 4 #define REGF8_MINSEL 0x0f /** * writable scanner registers */ enum { reg_0x01 = 0, reg_0x02, reg_0x03, reg_0x04, reg_0x05, reg_0x06, reg_0x08, reg_0x09, reg_0x0a, reg_0x0b, reg_0x0c, reg_0x0d, reg_0x0e, reg_0x0f, reg_0x10, reg_0x11, reg_0x12, reg_0x13, reg_0x14, reg_0x15, reg_0x16, reg_0x17, reg_0x18, reg_0x19, reg_0x1a, reg_0x1b, reg_0x1c, reg_0x1d, reg_0x1e, reg_0x1f, reg_0x20, reg_0x21, reg_0x22, reg_0x23, reg_0x24, reg_0x25, reg_0x26, reg_0x27, reg_0x2c, reg_0x2d, reg_0x2e, reg_0x2f, reg_0x30, reg_0x31, reg_0x32, reg_0x33, reg_0x34, reg_0x35, reg_0x36, reg_0x37, reg_0x38, reg_0x39, reg_0x3a, reg_0x3b, reg_0x3d, reg_0x3e, reg_0x3f, reg_0x51, reg_0x52, reg_0x53, reg_0x54, reg_0x55, reg_0x56, reg_0x57, reg_0x58, reg_0x59, reg_0x5a, reg_0x5e, reg_0x5f, reg_0x60, reg_0x61, reg_0x62, reg_0x63, reg_0x64, reg_0x65, reg_0x67, reg_0x68, reg_0x69, reg_0x6a, reg_0x6b, reg_0x6c, reg_0x6d, reg_0x6e, reg_0x6f, reg_0x70, reg_0x71, reg_0x72, reg_0x73, reg_0x74, reg_0x75, reg_0x76, reg_0x77, reg_0x78, reg_0x79, reg_0x7a, reg_0x7b, reg_0x7c, reg_0x7d, reg_0x7e, reg_0x7f, reg_0x80, reg_0x87, reg_0x94, reg_0x98, reg_0x99, reg_0x9a, reg_0x9b, reg_0x9d, reg_0x9e, reg_0xa1, reg_0xa2, reg_0xa3, reg_0xa4, reg_0xa5, reg_0xa6, reg_0xa7, reg_0xa8, reg_0xa9, reg_0xab, reg_0xbb, reg_0xbc, reg_0xbd, reg_0xbe, reg_0xc5, reg_0xc6, reg_0xc7, reg_0xc8, reg_0xc9, reg_0xca, reg_0xd0, reg_0xd1, reg_0xd2, reg_0xdb, reg_0xe0, reg_0xe1, reg_0xe2, reg_0xe3, reg_0xe4, reg_0xe5, reg_0xe6, reg_0xe7, reg_0xe8, reg_0xe9, reg_0xea, reg_0xeb, reg_0xec, reg_0xed, reg_0xee, reg_0xef, reg_0xf0, reg_0xf1, reg_0xf2, reg_0xf3, reg_0xf4, reg_0xf5, reg_0xf6, reg_0xf7, reg_0xf8, reg_0xfe, reg_0xff, GENESYS_GL846_MAX_REGS }; #define SETREG(adr,val) {dev->reg[reg_##adr].address=adr;dev->reg[reg_##adr].value=val;} /** set up registers for an actual scan * * this function sets up the scanner to scan in normal or single line mode */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ float yres, /*dpi */ float startx, /*optical_res, from dummy_pixel+1 */ float starty, /*base_ydpi, from home! */ float pixels, float lines, unsigned int depth, unsigned int channels, int color_filter, unsigned int flags); /* Send the low-level scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor); /* Send the stop scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop); #ifndef UNIT_TESTING static #endif SANE_Status gl846_init (Genesys_Device * dev); /** @brief moves the slider to steps at motor base dpi * @param dev device to work on * @param steps number of steps to move * */ #ifndef UNIT_TESTING static #endif SANE_Status gl846_feed (Genesys_Device * dev, unsigned int steps); #ifndef UNIT_TESTING static #endif SANE_Status gl846_stop_action (Genesys_Device * dev); #ifndef UNIT_TESTING static #endif SANE_Status gl846_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home); #ifndef UNIT_TESTING static #endif SANE_Status gl846_boot (Genesys_Device * dev, SANE_Bool cold); typedef struct { uint8_t sensor_id; uint8_t r6b; uint8_t r6c; uint8_t r6d; uint8_t r6e; uint8_t r6f; uint8_t ra6; uint8_t ra7; uint8_t ra8; uint8_t ra9; } Gpio_Profile; static Gpio_Profile gpios[]={ { GPO_IMG101, 0x72, 0x1f, 0xa4, 0x13, 0xa7, 0x11, 0xff, 0x19, 0x05}, { GPO_PLUSTEK3800, 0x30, 0x01, 0x80, 0x2d, 0x80, 0x0c, 0x8f, 0x08, 0x04}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }; typedef struct { char *model; uint8_t dramsel; /* shading data address */ uint8_t rd0; uint8_t rd1; uint8_t rd2; /* scanned data address */ uint8_t rx[24]; } Memory_layout; static Memory_layout layouts[]={ /* Image formula 101 */ { "canon-image-formula-101", 0x8b, 0x0a, 0x1b, 0x00, { /* RED ODD START / RED ODD END */ 0x00, 0xb0, 0x05, 0xe7, /* [0x00b0, 0x05e7] 1336*4000w */ /* RED EVEN START / RED EVEN END */ 0x05, 0xe8, 0x0b, 0x1f, /* [0x05e8, 0x0b1f] */ /* GREEN ODD START / GREEN ODD END */ 0x0b, 0x20, 0x10, 0x57, /* [0x0b20, 0x1057] */ /* GREEN EVEN START / GREEN EVEN END */ 0x10, 0x58, 0x15, 0x8f, /* [0x1058, 0x158f] */ /* BLUE ODD START / BLUE ODD END */ 0x15, 0x90, 0x1a, 0xc7, /* [0x1590,0x1ac7] */ /* BLUE EVEN START / BLUE EVEN END */ 0x1a, 0xc8, 0x1f, 0xff /* [0x1ac8,0x1fff] */ } }, /* OpticBook 3800 */ { "plustek-opticbook-3800", 0x2a, 0x0a, 0x0a, 0x0a, { /* RED ODD START / RED ODD END */ 0x00, 0x68, 0x03, 0x00, /* RED EVEN START / RED EVEN END */ 0x03, 0x01, 0x05, 0x99, /* GREEN ODD START / GREEN ODD END */ 0x05, 0x9a, 0x08, 0x32, /* GREEN EVEN START / GREEN EVEN END */ 0x08, 0x33, 0x0a, 0xcb, /* BLUE ODD START / BLUE ODD END */ 0x0a, 0xcc, 0x0d, 0x64, /* BLUE EVEN START / BLUE EVEN END */ 0x0d, 0x65, 0x0f, 0xfd } }, /* list terminating entry */ { NULL, 0, 0, 0, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} } }; /** @brief structure for sensor settings * this structure describes the sensor settings to use for a given * exposure. */ typedef struct { int sensor_type; /**> sensor id */ int dpi; /**> maximum dpi for which data are valid */ int exposure; /**> exposure */ int ck1map; /**> CK1MAP */ int ck3map; /**> CK3MAP */ int ck4map; /**> CK4MAP */ int segcnt; /**> SEGCNT */ int expdummy; /**> exposure dummy */ int expr; /**> initial red exposure */ int expg; /**> initial green exposure */ int expb; /**> initial blue exposure */ size_t *order; /**> order of sub-segments */ uint8_t r17; /**> TG width */ } Sensor_Profile; /* *INDENT-OFF* */ /** * order of the scanned pixel */ static size_t order_01[]={0,1}; /** * database of sensor profiles */ static Sensor_Profile sensors[]={ {CCD_IMG101, 1200, 11000, 60, 159, 85, 5136, 255, 0, 0, 0, order_01 , 0x13}, {CCD_PLUSTEK3800, 1200, 11000, 60, 159, 85, 5136, 255, 0, 0, 0, order_01 , 0x13}, }; /* *INDENT-ON* */ /* base motor slopes in full step unit */ /* target=((exposure * dpi) / base_dpi)>>step_type; */ static uint32_t img101_high[] = {22000, 22000, 22000, 18450, 15974, 14284, 13054, 12076, 11286, 10660, 10100, 9632, 9224, 8864, 8532, 8250, 7986, 7750, 7530, 7330, 7142, 6972, 6810, 6656, 6518, 6384, 6264, 6150, 6038, 5930, 5834, 5732, 5642, 5560, 5476, 5398, 5324, 5252, 5180, 5112, 5050, 4990, 4926, 4868, 4816, 4760, 4708, 4658, 4608, 4562, 4516, 4472, 4428, 4384, 4344, 4306, 4266, 4230, 4194, 4156, 4122, 4088, 4054, 4022, 3990, 3960, 3930, 3900, 3872, 3842, 3816, 3790, 3762, 3736, 3710, 3686, 3662, 3638, 3614, 3590, 3570, 3548, 3526, 3506, 3484, 3462, 3442, 3424, 3402, 3384, 3366, 3346, 3328, 3310, 3292, 3276, 3258, 3242, 3224, 3208, 3192, 3176, 3162, 3146, 3130, 3114, 3100, 3086, 3072, 3058, 3044, 3030, 3016, 3002, 2990, 2976, 2964, 2950, 2938, 2926, 2914, 2902, 2890, 2878, 2866, 2854, 2844, 2832, 2820, 2810, 2800, 2790, 2778, 2768, 2756, 2748, 2738, 2726, 2716, 2708, 2698, 2688, 2678, 2668, 2660, 2650, 2642, 2632, 2624, 2616, 2606, 2598, 2588, 2580, 2572, 2564, 2556, 2548, 2540, 2530, 2522, 2516, 2508, 2500, 2492, 2486, 2476, 2470, 2462, 2454, 2448, 2440, 2434, 2426, 2420, 2412, 2406, 2400, 2392, 2386, 2378, 2372, 2366, 2360, 2354, 2346, 2340, 2334, 2328, 2322, 2314, 2310, 2304, 2296, 2292, 2286, 2280, 2274, 2268, 2262, 2256, 2252, 2246, 2240, 2234, 2230, 2224, 2218, 2214, 2208, 2202, 2196, 2192, 2188, 2182, 2176, 2172, 2166, 2162, 2156, 2152, 2146, 2142, 2136, 2132, 2128, 2124, 2118, 2114, 2108, 2104, 2100, 2096, 2092, 2086, 2082, 2078, 2072, 2068, 2064, 2060, 2056, 2052, 2048, 2044, 2038, 2034, 2030, 2026, 2022, 2018, 2014, 2010, 2006, 2002, 1998, 1994, 1990, 1988, 1984, 1980, 1976, 1972, 1968, 1964, 1960, 1956, 1952, 1950, 1946, 1942, 1938, 1934, 1932, 1928, 1924, 1920, 1918, 1914, 1910, 1908, 1904, 1900, 1898, 1894, 1890, 1888, 1884, 1880, 1878, 1874, 1870, 1868, 1864, 1862, 1858, 1854, 1852, 1848, 1846, 1842, 1840, 1836, 1834, 1830, 1828, 1824, 1822, 1818, 1816, 1812, 1810, 1806, 1804, 1800, 1798, 1794, 1792, 1790, 1786, 1784, 1780, 1778, 1776, 1772, 1770, 1768, 1764, 1762, 1758, 1756, 1754, 1752, 1748, 1746, 1744, 1740, 1738, 1736, 1734, 1730, 1728, 1726, 1724, 1720, 1718, 1716, 1714, 1710, 1708, 1706, 1704, 1700, 1698, 1696, 1694, 1692, 1688, 1686, 1684, 1682, 1680, 1676, 1674, 1672, 1670, 1668, 1666, 1664, 1662, 1660, 1656, 1654, 1652, 1650, 1648, 1646, 1644, 1642, 1638, 1636, 1634, 1632, 1630, 1628, 1626, 1624, 1622, 1620, 1618, 1616, 1614, 1612, 1610, 1608, 1606, 1604, 1602, 1600, 1598, 1596, 1594, 1592, 1590, 1588, 1586, 1584, 1582, 1580, 1578, 1576, 1574, 1572, 1570, 1568, 1566, 1564, 1562, 1560, 1558, 1556, 1556, 1554, 1552, 1550, 1548, 1546, 1544, 1542, 1540, 1538, 1536, 1536, 1534, 1532, 1530, 1528, 1526, 1524, 1522, 1522, 1520, 1518, 1516, 1514, 1512, 1510, 1510, 1508, 1506, 1504, 1502, 1500, 1500, 1498, 1496, 1494, 1492, 1490, 1490, 1488, 1486, 1484, 1482, 1482, 1480, 1478, 1476, 1474, 1474, 1472, 1470, 1468, 1466, 1466, 1464, 1462, 1460, 1460, 1458, 1456, 1454, 1454, 1452, 1450, 1448, 1448, 1446, 1444, 1442, 1442, 1440, 1438, 1438, 1436, 1434, 1432, 1432, 1430, 1428, 1426, 1426, 1424, 1422, 1422, 1420, 1418, 1418, 1416, 1414, 1412, 1412, 1410, 1408, 1408, 1406, 1404, 1404, 1402, 1400, 1400, 1398, 1396, 1394, 1394, 1392, 1390, 1390, 1388, 1388, 1386, 1384, 1384, 1382, 1380, 1380, 1378, 1376, 1376, 1374, 1374, 1372, 1370, 1370, 1368, 1366, 1366, 1364, 1362, 1362, 1360, 1360, 1358, 1356, 1356, 1354, 1352, 1352, 1350, 1350, 1348, 1348, 1346, 1344, 1344, 1342, 1340, 1340, 1338, 1338, 1336, 1336, 1334, 1332, 1332, 1330, 1330, 1328, 1328, 1326, 1324, 1324, 1322, 1322, 1320, 1318, 1318, 1316, 1316, 1314, 1314, 1312, 1310, 1310, 1308, 1308, 1306, 1306, 1304, 1304, 1302, 1302, 1300, 1300, 1298, 1298, 1296, 1294, 1294, 1292, 1292, 1290, 1290, 1288, 1288, 1286, 1286, 1284, 1284, 1282, 1282, 1280, 1280, 1278, 1278, 1276, 1276, 1274, 1272, 1272, 1270, 1270, 1270, 1268, 1268, 1266, 1264, 1264, 1262, 1262, 1260, 1260, 1260, 1258, 1258, 1256, 1254, 1254, 1254, 1252, 1252, 1250, 1250, 1248, 1248, 1246, 1246, 1244, 1244, 1242, 1242, 1240, 1240, 1238, 1238, 1236, 1236, 1236, 1234, 1234, 1232, 1232, 1230, 1230, 1228, 1228, 1226, 1226, 1226, 1224, 1224, 1222, 1222, 1220, 1220, 1218, 1218, 1218, 1216, 1216, 1214, 1214, 1212, 1212, 1210, 1210, 1210, 1208, 1208, 1206, 1206, 1204, 1204, 1204, 1202, 1202, 1200, 1200, 1198, 1198, 1198, 1196, 1196, 1194, 1194, 1192, 1192, 1192, 1190, 1190, 1188, 1188, 1188, 1186, 1186, 1184, 1184, 1182, 1182, 1182, 1180, 1180, 1180, 1178, 1178, 1176, 1176, 1174, 1174, 1174, 1172, 1172, 1172, 1170, 1170, 1168, 1168, 1168, 1166, 1166, 1164, 1164, 1164, 1162, 1162, 1160, 1160, 1160, 1158, 1158, 1156, 1156, 1156, 1154, 1154, 1154, 1152, 1152, 1152, 1150, 1150, 1148, 1148, 1148, 1146, 1146, 1146, 1144, 1144, 1142, 1142, 1142, 1140, 1140, 1140, 1138, 1138, 1136, 1136, 1136, 1134, 1134, 1134, 1132, 1132, 1132, 1130, 1130, 1130, 1128, 1128, 1126, 1126, 1126, 1124, 1124, 1124, 1122, 1122, 1122, 1120, 1120, 1120, 1118, 1118, 1118, 1116, 1116, 1116, 1114, 1114, 1114, 1112, 1112, 1112, 1110, 1110, 1110, 1108, 1108, 1108, 1106, 1106, 1106, 1104, 1104, 1104, 1102, 1102, 1102, 1100, 1100, 1100, 1098, 1098, 1098, 1096, 1096, 1096, 1094, 1094, 1094, 1092, 1092, 1092, 1090, 1090, 1090, 1088, 1088, 1088, 1086, 1086, 1086, 1086, 1084, 1084, 1084, 1082, 1082, 1082, 1080, 1080, 1080, 1078, 1078, 1078, 1078, 1076, 1076, 1076, 1074, 1074, 1074, 1072, 1072, 1072, 1072, 1070, 1070, 1070, 1068, 1068, 1068, 1066, 1066, 1066, 1064, 1064, 1064, 1064, 1062, 1062, 1062, 1060, 1060, 1060, 1058, 1058, 1058, 1058, 1056, 1056, 1056, 1054, 1054, 1054, 1054, 1052, 1052, 1052, 1050, 1050, 1050, 1050, 1048, 1048, 1048, 1046, 1046, 1046, 1046, 1044, 1044, 1044, 1044, 1042, 1042, 1042, 1040, 1040, 1040, 1040, 1038, 1038, 1038, 1036, 1036, 1036, 1036, 1034, 1034, 1034, 1034, 1032, 1032, 1032, 1030, 1030, 1030, 1030, 1028, 1028, 1028, 1028, 1026, 1026, 1026, 1026, 1024, 1024, 1024, 1022, 1022, 1022, 1022, 1020, 1020, 1020, 1020, 1018, 1018, 1018, 1018, 1016, 1016, 1016, 1016, 1014, 1014, 1014, 1014, 1012, 1012, 1012, 1012, 1010, 1010, 1010, 1010, 1008, 1008, 1008, 1008, 1006, 1006, 1006, 1006, 1004, 1004, 1004, 1004, 1002, 1002, 1002, 1002, 1000, 1000, 1000, 1000, 0 }; /** * database of motor profiles */ /* *INDENT-OFF* */ static Motor_Profile gl846_motors[]={ /* Image Formula 101 */ {MOTOR_IMG101, 11000, HALF_STEP , img101_high}, {MOTOR_PLUSTEK3800, 11000, HALF_STEP , img101_high}, /* end of database entry */ {0, 0, 0, NULL}, }; /* *INDENT-ON* */ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/gphoto2.conf.in0000664000175000017500000000217512112021330015435 00000000000000# Interface port where the camera is connected # This should be one of the values returned by "gphoto2 --list-ports", # such # as serial:/dev/ttyS6 or usb: port=serial:/dev/ttyd1 # Port speed. This should be one of the values returned by # "gphoto2 --abilities" speed=115200 # Name of camera. This should be one of the values returned by # "gphoto2 --list-cameras" camera=Kodak DC240 # Prints some extra information during the init phase. dumpinquiry # The resolution should be the maximum resolution supported by the # camera. It's not really used for much, since the actual size will be # reported by the camera when the download starts. But it may be useful # for the frontend to have a clue prior to the download. (e.g. it # may want to create an image window, or report the maximum file size. # Width x Height. resolution=1280x960 # Thumbnail resolutions - ditto thumb_resolution=160x120 # top-level (fixed) folder directory in camera. Backend assumes # that there is one variable directory under this (e.g. 100DC240) # which will be read from the camera, and all the images in the # camera are under that. topfolder=/DCIM sane-backends-1.0.27/backend/plustek.c0000664000175000017500000024322512775312261014462 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek.c * @brief SANE backend for Plustek scanner * * Based on Kazuhiro Sasayama previous work on * plustek.[ch] file from the SANE package.
* Original code taken from sane-0.71
* Copyright (C) 1997 Hypercore Software Design, Ltd.
* Also based on the work done by Rick Bronson
* Copyright (C) 2000-2007 Gerhard Jaeger
* * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - no changes * - 0.33 - no changes * - 0.34 - moved some definitions and typedefs to plustek.h * - 0.35 - removed Y-correction for 12000P model
* - getting Y-size of scan area from driver * - 0.36 - disabled Dropout, as this does currently not work
* - enabled Halftone selection only for Halftone-mode
* - made the cancel button work by using a child process during read
* - added version code to driver interface
* - cleaned up the code
* - fixed sane compatibility problems
* - added multiple device support
* - 12bit color-depth are now available for scanimage * - 0.37 - removed X/Y autocorrection, now correcting the stuff * before scanning * - applied Michaels' patch to solve the sane_get_parameter problem
* - getting X-size of scan area from driver
* - applied Michaels patch for OPT_RESOLUTION (SANE_INFO_INEXACT stuff) * - 0.38 - now using the information from the driver * - some minor fixes
* - removed dropout stuff
* - removed some warning conditions * - 0.39 - added stuff to use the backend completely in user mode
* - fixed a potential buffer problem
* - removed function attach_one()
* - added USB interface stuff * - 0.40 - USB scanning works now * - 0.41 - added some configuration stuff and also changed .conf file
* - added call to sanei_usb_init() and sanei_lm983x_init() * - 0.42 - added adjustment stuff
* - added custom gamma tables
* - fixed a problem with the "size-sliders"
* - fixed a bug that causes segfault when using the autodetection for * USB devices
* - added OS/2 switch to disable the USB stuff for OS/2 * - 0.43 - added support for PREVIEW flag * - 0.44 - added _DBG_DUMP debug level
* - fixed a bug, that stops our lamp timer * - 0.45 - added additional flags * - added WIFSIGNALED to check result of child termination * - changed readImage interface for USB devices * - homeing of USB scanner is now working correctly * - 0.46 - added plustek-usbcal.c for extra CIS device calibration * based on Montys' great work * - added altCalibration option * - removed parallelport support --> new backend: plustek_pp * - cleanup * - added sanei_thread support * - 0.47 - added mov-option (model override) * - removed drvOpen * - added call to usb_StartLampTimer, when we're using * SIGALRM for lamp timer * - closing now writer pipe, when reader_process is done * - 0.48 - added additional options * split scanmode and bit-depth * - 0.49 - improved multi-device capability * - tweaked some device settings * - added button support * - moved AFE stuff to enhanced options * - 0.50 - cleanup * - activated IPC stuff * - added _DBG_DCALDATA for fine calibration data logging * - added OPT_SPEEDUP handling * - fixed constraint_type for OPT_BUTTON * - 0.51 - added fine calibration caching * - removed #define _PLUSTEK_USB * - 0.52 - added skipDarkStrip and OPT_LOFF4DARK to frontend options * - fixed batch scanning *. *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /** @mainpage * @verbinclude Plustek-USB.txt */ #ifdef _AIX # include "../include/lalloca.h" #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_VERSION "0.52-12" #define BACKEND_NAME plustek #include "../include/sane/sanei_access.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_thread.h" #define USE_IPC #include "plustek-usb.h" #include "plustek.h" /*********************** the debug levels ************************************/ #define _DBG_FATAL 0 #define _DBG_ERROR 1 #define _DBG_WARNING 3 #define _DBG_INFO 5 #define _DBG_PROC 7 #define _DBG_SANE_INIT 10 #define _DBG_INFO2 15 #define _DBG_DREGS 20 #define _DBG_DCALDATA 22 #define _DBG_DPIC 25 #define _DBG_READ 30 /*****************************************************************************/ #define _SECTION "[usb]" #define _DEFAULT_DEVICE "auto" /** to disable the backend... */ /* declare it here, as it's used in plustek-usbscan.c too :-( */ static SANE_Bool cancelRead; static DevList *usbDevs; /* the USB-stuff... I know this is in general no good idea, but it works */ #include "plustek-usbio.c" #include "plustek-usbdevs.c" #include "plustek-usbhw.c" #include "plustek-usbmap.c" #include "plustek-usbscan.c" #include "plustek-usbimg.c" #include "plustek-usbcalfile.c" #include "plustek-usbshading.c" #include "plustek-usbcal.c" #include "plustek-usb.c" /************************** global vars **************************************/ static int num_devices; static Plustek_Device *first_dev; static Plustek_Scanner *first_handle; static const SANE_Device **devlist = 0; static unsigned long tsecs = 0; static Plustek_Scanner *sc = NULL; static const SANE_Int bpp_lm9832_list [] = { 2, 8, 14 }; static const SANE_Int bpp_lm9833_list [] = { 2, 8, 16 }; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; static const SANE_String_Const source_list[] = { SANE_I18N("Normal"), SANE_I18N("Transparency"), SANE_I18N("Negative"), NULL }; static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 1 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static const SANE_Range warmup_range = { -1, 999, 1 }; static const SANE_Range offtimer_range = { 0, 999, 1 }; static const SANE_Range gain_range = { -1, 63, 1 }; static const SANE_Range loff_range = { -1, 16363, 1 }; /* authorization stuff */ static SANE_Auth_Callback auth = NULL; /* prototype... */ static SANE_Status local_sane_start(Plustek_Scanner *, int); /****************************** the backend... *******************************/ #define _YN(x) (x?"yes":"no") /** function to display the configuration options for the current device * @param cnf - pointer to the configuration structure whose content should be * displayed */ static void show_cnf( CnfDef *cnf ) { DBG( _DBG_SANE_INIT,"Device configuration:\n" ); DBG( _DBG_SANE_INIT,"device name : >%s<\n",cnf->devName ); DBG( _DBG_SANE_INIT,"USB-ID : >%s<\n",cnf->usbId ); DBG( _DBG_SANE_INIT,"model ovr. : %d\n", cnf->adj.mov ); DBG( _DBG_SANE_INIT,"warmup : %ds\n", cnf->adj.warmup ); DBG( _DBG_SANE_INIT,"lampOff : %d\n", cnf->adj.lampOff ); DBG( _DBG_SANE_INIT,"lampOffOnEnd : %s\n", _YN(cnf->adj.lampOffOnEnd )); DBG( _DBG_SANE_INIT,"cacheCalData : %s\n", _YN(cnf->adj.cacheCalData )); DBG( _DBG_SANE_INIT,"altCalibrate : %s\n", _YN(cnf->adj.altCalibrate )); DBG( _DBG_SANE_INIT,"skipCalibr. : %s\n", _YN(cnf->adj.skipCalibration)); DBG( _DBG_SANE_INIT,"skipFine : %s\n", _YN(cnf->adj.skipFine )); DBG( _DBG_SANE_INIT,"skipFineWhite: %s\n", _YN(cnf->adj.skipFineWhite )); DBG( _DBG_SANE_INIT,"skipDarkStrip: %s\n", _YN(cnf->adj.skipDarkStrip )); DBG( _DBG_SANE_INIT,"incDarkTarget: %s\n", _YN(cnf->adj.incDarkTgt )); DBG( _DBG_SANE_INIT,"invertNegs. : %s\n", _YN(cnf->adj.invertNegatives)); DBG( _DBG_SANE_INIT,"dis.Speedup : %s\n", _YN(cnf->adj.disableSpeedup )); DBG( _DBG_SANE_INIT,"pos_x : %d\n", cnf->adj.pos.x ); DBG( _DBG_SANE_INIT,"pos_y : %d\n", cnf->adj.pos.y ); DBG( _DBG_SANE_INIT,"pos_shading_y: %d\n", cnf->adj.posShadingY ); DBG( _DBG_SANE_INIT,"neg_x : %d\n", cnf->adj.neg.x ); DBG( _DBG_SANE_INIT,"neg_y : %d\n", cnf->adj.neg.y ); DBG( _DBG_SANE_INIT,"neg_shading_y: %d\n", cnf->adj.negShadingY ); DBG( _DBG_SANE_INIT,"tpa_x : %d\n", cnf->adj.tpa.x ); DBG( _DBG_SANE_INIT,"tpa_y : %d\n", cnf->adj.tpa.y ); DBG( _DBG_SANE_INIT,"tpa_shading_y: %d\n", cnf->adj.tpaShadingY ); DBG( _DBG_SANE_INIT,"red gain : %d\n", cnf->adj.rgain ); DBG( _DBG_SANE_INIT,"green gain : %d\n", cnf->adj.ggain ); DBG( _DBG_SANE_INIT,"blue gain : %d\n", cnf->adj.bgain ); DBG( _DBG_SANE_INIT,"red offset : %d\n", cnf->adj.rofs ); DBG( _DBG_SANE_INIT,"green offset : %d\n", cnf->adj.gofs ); DBG( _DBG_SANE_INIT,"blue offset : %d\n", cnf->adj.bofs ); DBG( _DBG_SANE_INIT,"red lampoff : %d\n", cnf->adj.rlampoff ); DBG( _DBG_SANE_INIT,"green lampoff: %d\n", cnf->adj.glampoff ); DBG( _DBG_SANE_INIT,"blue lampoff : %d\n", cnf->adj.blampoff ); DBG( _DBG_SANE_INIT,"red Gamma : %.2f\n",cnf->adj.rgamma ); DBG( _DBG_SANE_INIT,"green Gamma : %.2f\n",cnf->adj.ggamma ); DBG( _DBG_SANE_INIT,"blue Gamma : %.2f\n",cnf->adj.bgamma ); DBG( _DBG_SANE_INIT,"gray Gamma : %.2f\n",cnf->adj.graygamma ); DBG( _DBG_SANE_INIT,"---------------------\n" ); } /** Calls the device specific stop and close functions. * @param dev - pointer to the device specific structure * @return The function always returns SANE_STATUS_GOOD */ static SANE_Status drvclose( Plustek_Device *dev ) { if( dev->fd >= 0 ) { DBG( _DBG_INFO, "drvclose()\n" ); if( 0 != tsecs ) { DBG( _DBG_INFO, "TIME END 1: %lus\n", time(NULL)-tsecs); } /* don't check the return values, simply do it */ usbDev_stopScan( dev ); usbDev_close ( dev ); sanei_access_unlock( dev->sane.name ); } dev->fd = -1; return SANE_STATUS_GOOD; } /** according to the mode and source we return the corresponding scanmode and * bit-depth per pixel */ static int getScanMode( Plustek_Scanner *scanner ) { int mode; int scanmode; /* are we in TPA-mode? */ mode = scanner->val[OPT_MODE].w; if( scanner->val[OPT_EXT_MODE].w != 0 ) mode += 2; scanner->params.depth = scanner->val[OPT_BIT_DEPTH].w; if( mode == 0 ) { scanmode = COLOR_BW; scanner->params.depth = 1; } else if( scanner->params.depth == 8 ) { if( mode == 1 ) scanmode = COLOR_256GRAY; else scanmode = COLOR_TRUE24; } else { scanner->params.depth = 16; if( mode == 1 ) scanmode = COLOR_GRAY16; else scanmode = COLOR_TRUE48; } return scanmode; } /** return the len of the largest string in the array */ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /** shutdown open pipes */ static SANE_Status close_pipe( Plustek_Scanner *scanner ) { if( scanner->r_pipe >= 0 ) { DBG( _DBG_PROC, "close_pipe (r_pipe)\n" ); close( scanner->r_pipe ); scanner->r_pipe = -1; } if( scanner->w_pipe >= 0 ) { DBG( _DBG_PROC, "close_pipe (w_pipe)\n" ); close( scanner->w_pipe ); scanner->w_pipe = -1; } return SANE_STATUS_EOF; } /** will be called when a child is going down */ static void sig_chldhandler( int signo ) { DBG( _DBG_PROC, "(SIG) Child is down (signal=%d)\n", signo ); if (sc) { sc->calibrating = SANE_FALSE; sc = NULL; } } /** signal handler to kill the child process */ static void reader_process_sigterm_handler( int signo ) { DBG( _DBG_PROC, "(SIG) reader_process: terminated by signal %d\n", signo ); _exit( SANE_STATUS_GOOD ); } static void usb_reader_process_sigterm_handler( int signo ) { DBG( _DBG_PROC, "(SIG) reader_process: terminated by signal %d\n", signo ); cancelRead = SANE_TRUE; } static void sigalarm_handler( int signo ) { _VAR_NOT_USED( signo ); DBG( _DBG_PROC, "ALARM!!!\n" ); } /** */ static void thread_entry(void) { struct SIGACTION act; sigset_t ignore_set; sigfillset ( &ignore_set ); sigdelset ( &ignore_set, SIGTERM ); #if defined (__APPLE__) && defined (__MACH__) sigdelset ( &ignore_set, SIGUSR2 ); #endif sigprocmask( SIG_SETMASK, &ignore_set, 0 ); memset(&act, 0, sizeof (act)); sigaction( SIGTERM, &act, 0 ); cancelRead = SANE_FALSE; /* install the signal handler */ sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = reader_process_sigterm_handler; sigaction( SIGTERM, &act, 0 ); act.sa_handler = usb_reader_process_sigterm_handler; sigaction( SIGUSR1, &act, 0 ); } /** executed as a child process * read the data from the driver and send them to the parent process */ static int reader_process( void *args ) { int line, lerrn; unsigned char *buf; unsigned long status; unsigned long data_length; Plustek_Scanner *scanner = (Plustek_Scanner *)args; Plustek_Device *dev = scanner->hw; #ifdef USE_IPC IPCDef ipc; #endif if( sanei_thread_is_forked()) { DBG( _DBG_PROC, "reader_process started (forked)\n" ); close( scanner->r_pipe ); scanner->r_pipe = -1; } else { DBG( _DBG_PROC, "reader_process started (as thread)\n" ); } thread_entry(); data_length = scanner->params.lines * scanner->params.bytes_per_line; DBG( _DBG_PROC, "reader_process:" "starting to READ data (%lu bytes)\n", data_length ); DBG( _DBG_PROC, "buf = 0x%08lx\n", (unsigned long)scanner->buf ); if( NULL == scanner->buf ) { DBG( _DBG_FATAL, "NULL Pointer !!!!\n" ); return SANE_STATUS_IO_ERROR; } /* prepare for scanning: speed-test, warmup, calibration */ buf = scanner->buf; status = usbDev_Prepare( scanner->hw, buf ); #ifdef USE_IPC /* prepare IPC structure */ memset(&ipc, 0, sizeof(ipc)); ipc.transferRate = DEFAULT_RATE; if( dev->transferRate > 0 && dev->transferRate != DEFAULT_RATE ) ipc.transferRate = dev->transferRate; /* write ipc back to parent in any case... */ write( scanner->w_pipe, &ipc, sizeof(ipc)); #endif /* on success, we read all data from the driver... */ if( 0 == status ) { if( !usb_InCalibrationMode(dev)) { DBG( _DBG_INFO, "reader_process: READING....\n" ); for( line = 0; line < scanner->params.lines; line++ ) { status = usbDev_ReadLine( scanner->hw ); if((int)status < 0 ) { break; } write( scanner->w_pipe, buf, scanner->params.bytes_per_line ); buf += scanner->params.bytes_per_line; } } } /* on error, there's no need to clean up, as this is done by the parent */ lerrn = errno; close( scanner->w_pipe ); scanner->w_pipe = -1; if((int)status < 0 ) { DBG( _DBG_ERROR,"reader_process: read failed, status = %i, errno %i\n", (int)status, lerrn ); if( _E_ABORT == (int)status ) return SANE_STATUS_CANCELLED; if( lerrn == EBUSY ) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_IO_ERROR; } DBG( _DBG_PROC, "reader_process: finished reading data\n" ); return SANE_STATUS_GOOD; } /** stop the current scan process */ static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe ) { struct SIGACTION act; SANE_Pid res; DBG( _DBG_PROC,"do_cancel\n" ); scanner->scanning = SANE_FALSE; if( sanei_thread_is_valid (scanner->reader_pid) ) { DBG( _DBG_PROC, ">>>>>>>> killing reader_process <<<<<<<<\n" ); cancelRead = SANE_TRUE; scanner->calibrating = SANE_FALSE; sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = sigalarm_handler; sigaction( SIGALRM, &act, 0 ); /* kill our child process and wait until done */ sanei_thread_sendsig( scanner->reader_pid, SIGUSR1 ); /* give'em 10 seconds 'til done...*/ alarm(10); res = sanei_thread_waitpid( scanner->reader_pid, 0 ); alarm(0); if( res != scanner->reader_pid ) { DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n"); /* do it the hard way...*/ #ifdef USE_PTHREAD sanei_thread_kill( scanner->reader_pid ); #else sanei_thread_sendsig( scanner->reader_pid, SIGKILL ); #endif } scanner->reader_pid = -1; DBG( _DBG_PROC,"reader_process killed\n"); #ifndef HAVE_SETITIMER usb_StartLampTimer( scanner->hw ); #endif } scanner->calibrating = SANE_FALSE; if( SANE_TRUE == closepipe ) { close_pipe( scanner ); } drvclose( scanner->hw ); if( tsecs != 0 ) { DBG( _DBG_INFO, "TIME END 2: %lus\n", time(NULL)-tsecs); tsecs = 0; } return SANE_STATUS_CANCELLED; } /** As we support only LM9831/2/3 chips we use the same * sizes for each device... * @param s - pointer to the scanner specific structure * @return The function always returns SANE_STATUS_GOOD */ static SANE_Status initGammaSettings( Plustek_Scanner *s ) { int i, j, val; double gamma; s->gamma_length = 4096; s->gamma_range.min = 0; s->gamma_range.max = 255; s->gamma_range.quant = 0; DBG( _DBG_INFO, "Presetting Gamma tables (len=%u)\n", s->gamma_length ); /* preset the gamma maps */ for( i = 0; i < 4; i++ ) { switch( i ) { case 1: gamma = s->hw->adj.rgamma; break; case 2: gamma = s->hw->adj.ggamma; break; case 3: gamma = s->hw->adj.bgamma; break; default: gamma = s->hw->adj.graygamma; break; } DBG( _DBG_INFO, "* Channel[%u], gamma %.3f\n", i, gamma ); for( j = 0; j < s->gamma_length; j++ ) { val = (s->gamma_range.max * pow((double)j / (double)(s->gamma_length-1.0), 1.0 / gamma )); if( val > s->gamma_range.max ) val = s->gamma_range.max; s->gamma_table[i][j] = val; } } DBG( _DBG_INFO, "----------------------------------\n" ); return SANE_STATUS_GOOD; } /** Check the gamma vectors we got back and limit if necessary * @param s - pointer to the scanner specific structure * @return nothing */ static void checkGammaSettings( Plustek_Scanner *s ) { int i, j; DBG( _DBG_INFO, "Maps changed...\n" ); for( i = 0; i < 4 ; i++ ) { for( j = 0; j < s->gamma_length; j++ ) { if( s->gamma_table[i][j] > s->gamma_range.max ) { s->gamma_table[i][j] = s->gamma_range.max; } } } } /** initialize the options for the backend according to the device we have */ static SANE_Status init_options( Plustek_Scanner *s ) { int i; Plustek_Device *dev = s->hw; AdjDef *adj = &dev->adj; DCapsDef *caps = &dev->usbDev.Caps; memset(s->opt, 0, sizeof(s->opt)); for( i = 0; i < NUM_OPTIONS; ++i ) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[i].unit = SANE_UNIT_NONE; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size(mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = 2; /* Color */ /* bit depth */ s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT; s->opt[OPT_BIT_DEPTH].size = sizeof (SANE_Word); s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; if( _LM9833 == dev->usbDev.HwSetting.chip ) s->opt[OPT_BIT_DEPTH].constraint.word_list = bpp_lm9833_list; else s->opt[OPT_BIT_DEPTH].constraint.word_list = bpp_lm9832_list; s->val[OPT_BIT_DEPTH].w = 8; if (caps->workaroundFlag & _WAF_ONLY_8BIT) _DISABLE(OPT_BIT_DEPTH); /* scan source */ s->opt[OPT_EXT_MODE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_EXT_MODE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_EXT_MODE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_EXT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_EXT_MODE].size = max_string_size(source_list); s->opt[OPT_EXT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_EXT_MODE].constraint.string_list = source_list; s->val[OPT_EXT_MODE].w = 0; /* Normal */ /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; s->val[OPT_BRIGHTNESS].w = 0; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; s->val[OPT_CONTRAST].w = 0; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = 0; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TLX); /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TLY); /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_BRX); /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY); /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; initGammaSettings( s ); /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR].wa = &(s->gamma_table[0][0]); s->opt[OPT_GAMMA_VECTOR].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR].size = s->gamma_length * sizeof(SANE_Word); /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_R].wa = &(s->gamma_table[1][0]); s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_R].size = s->gamma_length * sizeof(SANE_Word); /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_G].wa = &(s->gamma_table[2][0]); s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_G].size = s->gamma_length * sizeof(SANE_Word); /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_B].wa = &(s->gamma_table[3][0]); s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_B].size = s->gamma_length * sizeof(SANE_Word); /* GAMMA stuff is disabled per default */ _DISABLE(OPT_GAMMA_VECTOR); _DISABLE(OPT_GAMMA_VECTOR_R); _DISABLE(OPT_GAMMA_VECTOR_G); _DISABLE(OPT_GAMMA_VECTOR_B); /* disable extended mode list for devices without TPA */ if( 0 == (s->hw->caps.dwFlag & SFLAG_TPA)) _DISABLE(OPT_EXT_MODE); /* "Device settings" group: */ s->opt[OPT_DEVICE_GROUP].title = SANE_I18N("Device-Settings"); s->opt[OPT_DEVICE_GROUP].desc = ""; s->opt[OPT_DEVICE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_DEVICE_GROUP].cap = 0; s->opt[OPT_DEVICE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_LAMPSWITCH].name = "lamp-switch"; s->opt[OPT_LAMPSWITCH].title = SANE_I18N("Lampswitch");; s->opt[OPT_LAMPSWITCH].desc = SANE_I18N("Manually switching the lamp(s)."); s->opt[OPT_LAMPSWITCH].type = SANE_TYPE_BOOL; s->val[OPT_LAMPSWITCH].w = SANE_FALSE; s->opt[OPT_LOFF4DARK].name = "lamp-off-during-dcal"; s->opt[OPT_LOFF4DARK].title = SANE_I18N("Lamp off during dark calibration");; s->opt[OPT_LOFF4DARK].desc = SANE_I18N("Always switches lamp off when doing dark calibration."); s->opt[OPT_LOFF4DARK].type = SANE_TYPE_BOOL; s->val[OPT_LOFF4DARK].w = adj->skipDarkStrip; if (dev->usbDev.Caps.Normal.DarkShadOrgY < 0) _DISABLE(OPT_LOFF4DARK); s->opt[OPT_CACHECAL].name = "calibration-cache"; s->opt[OPT_CACHECAL].title = SANE_I18N("Calibration data cache");; s->opt[OPT_CACHECAL].desc = SANE_I18N("Enables or disables calibration data cache."); s->opt[OPT_CACHECAL].type = SANE_TYPE_BOOL; s->val[OPT_CACHECAL].w = adj->cacheCalData; s->opt[OPT_CALIBRATE].name = "calibrate"; s->opt[OPT_CALIBRATE].title = SANE_I18N("Calibrate");; s->opt[OPT_CALIBRATE].desc = SANE_I18N("Performs calibration"); s->opt[OPT_CALIBRATE].type = SANE_TYPE_BUTTON; s->opt[OPT_CALIBRATE].size = sizeof (SANE_Word); s->opt[OPT_CALIBRATE].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_CALIBRATE].constraint.range = 0; s->opt[OPT_CALIBRATE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_AUTOMATIC; _ENABLE(OPT_CALIBRATE); if( !adj->cacheCalData ) _DISABLE(OPT_CALIBRATE); s->val[OPT_CALIBRATE].w = 0; /* it's currently not available for CCD devices */ if( !usb_IsCISDevice(dev) && !dev->adj.altCalibrate) _DISABLE(OPT_CALIBRATE); s->opt[OPT_SPEEDUP].name = "speedup-switch"; s->opt[OPT_SPEEDUP].title = SANE_I18N("Speedup sensor");; s->opt[OPT_SPEEDUP].desc = SANE_I18N("Enables or disables speeding up sensor movement."); s->opt[OPT_SPEEDUP].type = SANE_TYPE_BOOL; s->val[OPT_SPEEDUP].w = !(adj->disableSpeedup); if( s->hw->usbDev.HwSetting.dHighSpeed == 0.0 ) _DISABLE(OPT_SPEEDUP); s->opt[OPT_LAMPOFF_ONEND].name = SANE_NAME_LAMP_OFF_AT_EXIT; s->opt[OPT_LAMPOFF_ONEND].title = SANE_TITLE_LAMP_OFF_AT_EXIT; s->opt[OPT_LAMPOFF_ONEND].desc = SANE_DESC_LAMP_OFF_AT_EXIT; s->opt[OPT_LAMPOFF_ONEND].type = SANE_TYPE_BOOL; s->val[OPT_LAMPOFF_ONEND].w = adj->lampOffOnEnd; s->opt[OPT_WARMUPTIME].name = "warmup-time"; s->opt[OPT_WARMUPTIME].title = SANE_I18N("Warmup-time");; s->opt[OPT_WARMUPTIME].desc = SANE_I18N("Warmup-time in seconds."); s->opt[OPT_WARMUPTIME].type = SANE_TYPE_INT; s->opt[OPT_WARMUPTIME].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_WARMUPTIME].constraint.range = &warmup_range; s->val[OPT_WARMUPTIME].w = adj->warmup; /* only available for CCD devices*/ if( usb_IsCISDevice( dev )) { _DISABLE(OPT_WARMUPTIME); s->val[OPT_WARMUPTIME].w = 0; } s->opt[OPT_LAMPOFF_TIMER].name = "lampoff-time"; s->opt[OPT_LAMPOFF_TIMER].title = SANE_I18N("Lampoff-time");; s->opt[OPT_LAMPOFF_TIMER].desc = SANE_I18N("Lampoff-time in seconds."); s->opt[OPT_LAMPOFF_TIMER].type = SANE_TYPE_INT; s->opt[OPT_LAMPOFF_TIMER].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_LAMPOFF_TIMER].constraint.range = &offtimer_range; s->val[OPT_LAMPOFF_TIMER].w = adj->lampOff; /* "Analog Frontend" group*/ s->opt[OPT_AFE_GROUP].title = SANE_I18N("Analog frontend"); s->opt[OPT_AFE_GROUP].desc = ""; s->opt[OPT_AFE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_AFE_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_OVR_REDGAIN].name = "red-gain"; s->opt[OPT_OVR_REDGAIN].title = SANE_I18N("Red gain"); s->opt[OPT_OVR_REDGAIN].desc = SANE_I18N("Red gain value of the AFE"); s->opt[OPT_OVR_REDGAIN].type = SANE_TYPE_INT; s->opt[OPT_OVR_REDGAIN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_REDGAIN].constraint.range = &gain_range; s->val[OPT_OVR_REDGAIN].w = adj->rgain; s->opt[OPT_OVR_REDOFS].name = "red-offset"; s->opt[OPT_OVR_REDOFS].title = SANE_I18N("Red offset"); s->opt[OPT_OVR_REDOFS].desc = SANE_I18N("Red offset value of the AFE"); s->opt[OPT_OVR_REDOFS].type = SANE_TYPE_INT; s->opt[OPT_OVR_REDOFS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_REDOFS].constraint.range = &gain_range; s->val[OPT_OVR_REDOFS].w = adj->rofs; s->opt[OPT_OVR_GREENGAIN].name = "green-gain"; s->opt[OPT_OVR_GREENGAIN].title = SANE_I18N("Green gain"); s->opt[OPT_OVR_GREENGAIN].desc = SANE_I18N("Green gain value of the AFE"); s->opt[OPT_OVR_GREENGAIN].type = SANE_TYPE_INT; s->opt[OPT_OVR_GREENGAIN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_GREENGAIN].constraint.range = &gain_range; s->val[OPT_OVR_GREENGAIN].w = adj->ggain; s->opt[OPT_OVR_GREENOFS].name = "green-offset"; s->opt[OPT_OVR_GREENOFS].title = SANE_I18N("Green offset"); s->opt[OPT_OVR_GREENOFS].desc = SANE_I18N("Green offset value of the AFE"); s->opt[OPT_OVR_GREENOFS].type = SANE_TYPE_INT; s->opt[OPT_OVR_GREENOFS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_GREENOFS].constraint.range = &gain_range; s->val[OPT_OVR_GREENOFS].w = adj->gofs; s->opt[OPT_OVR_BLUEGAIN].name = "blue-gain"; s->opt[OPT_OVR_BLUEGAIN].title = SANE_I18N("Blue gain"); s->opt[OPT_OVR_BLUEGAIN].desc = SANE_I18N("Blue gain value of the AFE"); s->opt[OPT_OVR_BLUEGAIN].type = SANE_TYPE_INT; s->opt[OPT_OVR_BLUEGAIN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_BLUEGAIN].constraint.range = &gain_range; s->val[OPT_OVR_BLUEGAIN].w = adj->bgain; s->opt[OPT_OVR_BLUEOFS].name = "blue-offset"; s->opt[OPT_OVR_BLUEOFS].title = SANE_I18N("Blue offset"); s->opt[OPT_OVR_BLUEOFS].desc = SANE_I18N("Blue offset value of the AFE"); s->opt[OPT_OVR_BLUEOFS].type = SANE_TYPE_INT; s->opt[OPT_OVR_BLUEOFS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_BLUEOFS].constraint.range = &gain_range; s->val[OPT_OVR_BLUEOFS].w = adj->bofs; s->opt[OPT_OVR_RED_LOFF].name = "redlamp-off"; s->opt[OPT_OVR_RED_LOFF].title = SANE_I18N("Red lamp off"); s->opt[OPT_OVR_RED_LOFF].desc = SANE_I18N("Defines red lamp off parameter"); s->opt[OPT_OVR_RED_LOFF].type = SANE_TYPE_INT; s->opt[OPT_OVR_RED_LOFF].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_RED_LOFF].constraint.range = &loff_range; s->val[OPT_OVR_RED_LOFF].w = adj->rlampoff; s->opt[OPT_OVR_GREEN_LOFF].name = "greenlamp-off"; s->opt[OPT_OVR_GREEN_LOFF].title = SANE_I18N("Green lamp off"); s->opt[OPT_OVR_GREEN_LOFF].desc = SANE_I18N("Defines green lamp off parameter"); s->opt[OPT_OVR_GREEN_LOFF].type = SANE_TYPE_INT; s->opt[OPT_OVR_GREEN_LOFF].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_GREEN_LOFF].constraint.range = &loff_range; s->val[OPT_OVR_GREEN_LOFF].w = adj->glampoff; s->opt[OPT_OVR_BLUE_LOFF].name = "bluelamp-off"; s->opt[OPT_OVR_BLUE_LOFF].title = SANE_I18N("Blue lamp off"); s->opt[OPT_OVR_BLUE_LOFF].desc = SANE_I18N("Defines blue lamp off parameter"); s->opt[OPT_OVR_BLUE_LOFF].type = SANE_TYPE_INT; s->opt[OPT_OVR_BLUE_LOFF].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVR_BLUE_LOFF].constraint.range = &loff_range; s->val[OPT_OVR_BLUE_LOFF].w = adj->blampoff; /* only available for CIS devices*/ if( !usb_IsCISDevice( dev )) { _DISABLE(OPT_OVR_RED_LOFF); _DISABLE(OPT_OVR_GREEN_LOFF); _DISABLE(OPT_OVR_BLUE_LOFF); } /* "Button" group*/ s->opt[OPT_BUTTON_GROUP].title = SANE_I18N("Buttons"); s->opt[OPT_BUTTON_GROUP].desc = ""; s->opt[OPT_BUTTON_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_BUTTON_GROUP].cap = SANE_CAP_ADVANCED; /* scanner buttons */ for( i = OPT_BUTTON_0; i <= OPT_BUTTON_LAST; i++ ) { char name [12]; char title [128]; sprintf (name, "button %d", i - OPT_BUTTON_0); sprintf (title, "Scanner button %d", i - OPT_BUTTON_0); s->opt[i].name = strdup(name); s->opt[i].title = strdup(title); s->opt[i].desc = SANE_I18N("This option reflects the status " "of the scanner buttons."); s->opt[i].type = SANE_TYPE_BOOL; s->opt[i].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if (i - OPT_BUTTON_0 >= dev->usbDev.Caps.bButtons ) _DISABLE(i); s->opt[i].unit = SANE_UNIT_NONE; s->opt[i].size = sizeof (SANE_Word); s->opt[i].constraint_type = SANE_CONSTRAINT_NONE; s->opt[i].constraint.range = 0; s->val[i].w = SANE_FALSE; } usb_UpdateButtonStatus( s ); return SANE_STATUS_GOOD; } /** Function to retrieve the vendor and product id from a given string * @param src - string, that should be investigated * @param dest - pointer to a string to receive the USB ID */ static void decodeUsbIDs( char *src, char **dest ) { const char *name; char *tmp = *dest; int len = strlen(_SECTION); if( isspace(src[len])) { strncpy( tmp, &src[len+1], (strlen(src)-(len+1))); tmp[(strlen(src)-(len+1))] = '\0'; } name = tmp; name = sanei_config_skip_whitespace( name ); if( '\0' == name[0] ) { DBG( _DBG_SANE_INIT, "next device uses autodetection\n" ); } else { u_short pi = 0, vi = 0; if( *name ) { name = sanei_config_get_string( name, &tmp ); if( tmp ) { vi = strtol( tmp, 0, 0 ); free( tmp ); } } name = sanei_config_skip_whitespace( name ); if( *name ) { name = sanei_config_get_string( name, &tmp ); if( tmp ) { pi = strtol( tmp, 0, 0 ); free( tmp ); } } /* create what we need to go through our device list...*/ sprintf( *dest, "0x%04X-0x%04X", vi, pi ); DBG( _DBG_SANE_INIT, "next device is a USB device (%s)\n", *dest ); } } #define _INT 0 #define _FLOAT 1 /** function to decode an value and give it back to the caller. * @param src - pointer to the source string to check * @param opt - string that keeps the option name to check src for * @param what - _FLOAT or _INT * @param result - pointer to the var that should receive our result * @param def - default value that result should be in case of any error * @return The function returns SANE_TRUE if the option has been found, * if not, it returns SANE_FALSE */ static SANE_Bool decodeVal( char *src, char *opt, int what, void *result, void *def ) { char *tmp, *tmp2; const char *name; /* skip the option string */ name = (const char*)&src[strlen("option")]; /* get the name of the option */ name = sanei_config_get_string( name, &tmp ); if( tmp ) { /* on success, compare wiht the given one */ if( 0 == strcmp( tmp, opt )) { DBG( _DBG_SANE_INIT, "Decoding option >%s<\n", opt ); if( _INT == what ) { /* assign the default value for this option... */ *((int*)result) = *((int*)def); if( *name ) { /* get the configuration value and decode it */ name = sanei_config_get_string( name, &tmp2 ); if( tmp2 ) { *((int*)result) = strtol( tmp2, 0, 0 ); free( tmp2 ); } } free( tmp ); return SANE_TRUE; } else if( _FLOAT == what ) { /* assign the default value for this option... */ *((double*)result) = *((double*)def); if( *name ) { /* get the configuration value and decode it */ name = sanei_config_get_string( name, &tmp2 ); if( tmp2 ) { *((double*)result) = strtod( tmp2, 0 ); free( tmp2 ); } } free( tmp ); return SANE_TRUE; } } free( tmp ); } return SANE_FALSE; } /** function to retrive the device name of a given string * @param src - string that keeps the option name to check src for * @param dest - pointer to the string, that should receive the detected * devicename * @return The function returns SANE_TRUE if the devicename has been found, * if not, it returns SANE_FALSE */ static SANE_Bool decodeDevName( char *src, char *dest ) { char *tmp; const char *name; if( 0 == strncmp( "device", src, 6 )) { name = (const char*)&src[strlen("device")]; name = sanei_config_skip_whitespace( name ); DBG( _DBG_SANE_INIT, "Decoding device name >%s<\n", name ); if( *name ) { name = sanei_config_get_string( name, &tmp ); if( tmp ) { strcpy( dest, tmp ); free( tmp ); return SANE_TRUE; } } } return SANE_FALSE; } /** attach a device to the backend */ static SANE_Status attach( const char *dev_name, CnfDef *cnf, Plustek_Device **devp ) { int cntr; int result; int handle; Plustek_Device *dev; DBG( _DBG_SANE_INIT, "attach (%s, %p, %p)\n", dev_name, (void *)cnf, (void *)devp); /* already attached ?*/ for( dev = first_dev; dev; dev = dev->next ) { if( 0 == strcmp( dev->sane.name, dev_name )) { if( devp ) *devp = dev; return SANE_STATUS_GOOD; } } /* allocate some memory for the device */ dev = malloc( sizeof (*dev)); if( NULL == dev ) return SANE_STATUS_NO_MEM; /* assign all the stuff we need fo this device... */ memset(dev, 0, sizeof (*dev)); dev->fd = -1; dev->name = strdup(dev_name); /* hold it double to avoid */ dev->sane.name = dev->name; /* compiler warnings */ dev->sane.vendor = "Plustek"; dev->initialized = -1; /* will be used as index too */ dev->calFile = NULL; dev->transferRate = DEFAULT_RATE; memcpy( &dev->adj, &cnf->adj, sizeof(AdjDef)); show_cnf( cnf ); strncpy( dev->usbId, cnf->usbId, _MAX_ID_LEN ); if( cnf->adj.lampOff >= 0 ) dev->usbDev.dwLampOnPeriod = cnf->adj.lampOff; if( cnf->adj.lampOffOnEnd >= 0 ) dev->usbDev.bLampOffOnEnd = cnf->adj.lampOffOnEnd; /* go ahead and open the scanner device */ handle = usbDev_open( dev, usbDevs, SANE_FALSE ); if( handle < 0 ) { DBG( _DBG_ERROR,"open failed: %d\n", handle ); return SANE_STATUS_IO_ERROR; } /* okay, so assign the handle and the scanner type */ dev->fd = handle; if( usb_IsSheetFedDevice( dev )) dev->sane.type = SANE_I18N("sheetfed scanner"); else dev->sane.type = SANE_I18N("flatbed scanner"); result = usbDev_getCaps( dev ); if( result < 0 ) { DBG( _DBG_ERROR, "usbDev_getCaps() failed(%d)\n", result); usbDev_close(dev); return SANE_STATUS_IO_ERROR; } /* save the info we got from the driver */ DBG( _DBG_INFO, "Scanner information:\n" ); if( NULL != dev->usbDev.ModelStr ) dev->sane.model = dev->usbDev.ModelStr; else dev->sane.model = "USB-Device"; DBG( _DBG_INFO, "Vendor : %s\n", dev->sane.vendor ); DBG( _DBG_INFO, "Model : %s\n", dev->sane.model ); DBG( _DBG_INFO, "Flags : 0x%08lx\n", dev->caps.dwFlag ); dev->max_x = dev->caps.wMaxExtentX*MM_PER_INCH/_MEASURE_BASE; dev->max_y = dev->caps.wMaxExtentY*MM_PER_INCH/_MEASURE_BASE; /* calculate the size of the resolution list + * one more to avoid a buffer overflow, then allocate it... */ dev->res_list = (SANE_Int *) calloc((((dev->usbDev.Caps.OpticDpi.x*16)-_DEF_DPI)/25+1), sizeof (SANE_Int)); if (NULL == dev->res_list) { DBG( _DBG_ERROR, "calloc failed: %s\n", strerror(errno)); usbDev_close(dev); return SANE_STATUS_INVAL; } /* build up the resolution table */ dev->res_list_size = 0; for(cntr = _DEF_DPI; cntr <= (dev->usbDev.Caps.OpticDpi.x*16); cntr += 25){ dev->res_list_size++; dev->res_list[dev->res_list_size - 1] = (SANE_Int)cntr; } /* set the limits */ dev->dpi_range.min = _DEF_DPI; dev->dpi_range.max = dev->usbDev.Caps.OpticDpi.x * 2; dev->x_range.max = SANE_FIX(dev->max_x); dev->y_range.max = SANE_FIX(dev->max_y); dev->fd = handle; drvclose( dev ); DBG( _DBG_SANE_INIT, "attach: model = >%s<\n", dev->sane.model ); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } /** function to preset a configuration structure * @param cnf - pointer to the structure that should be initialized */ static void init_config_struct( CnfDef *cnf ) { memset(cnf, 0, sizeof(CnfDef)); cnf->adj.warmup = -1; cnf->adj.lampOff = -1; cnf->adj.lampOffOnEnd = -1; cnf->adj.posShadingY = -1; cnf->adj.tpaShadingY = -1; cnf->adj.negShadingY = -1; cnf->adj.rgain = -1; cnf->adj.ggain = -1; cnf->adj.bgain = -1; cnf->adj.rofs = -1; cnf->adj.gofs = -1; cnf->adj.bofs = -1; cnf->adj.rlampoff = -1; cnf->adj.glampoff = -1; cnf->adj.blampoff = -1; cnf->adj.incDarkTgt = 1; cnf->adj.graygamma = 1.0; cnf->adj.rgamma = 1.0; cnf->adj.ggamma = 1.0; cnf->adj.bgamma = 1.0; } /** intialize the backend */ SANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize ) { char str[PATH_MAX] = _DEFAULT_DEVICE; CnfDef config; size_t len; FILE *fp; DBG_INIT(); sanei_usb_init(); sanei_lm983x_init(); sanei_thread_init(); sanei_access_init(STRINGIFY(BACKEND_NAME)); #if defined PACKAGE && defined VERSION DBG( _DBG_INFO, "Plustek backend V"BACKEND_VERSION", part of " PACKAGE " " VERSION "\n"); #else DBG( _DBG_INFO, "Plustek backend V"BACKEND_VERSION"\n" ); #endif /* do some presettings... */ auth = authorize; first_dev = NULL; first_handle = NULL; num_devices = 0; usbDevs = NULL; /* initialize the configuration structure */ init_config_struct( &config ); /* try and get a list of all connected AND supported devices */ usbGetList( &usbDevs ); if( version_code != NULL ) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open( PLUSTEK_CONFIG_FILE ); /* default to _DEFAULT_DEVICE instead of insisting on config file */ if( NULL == fp ) { return attach( _DEFAULT_DEVICE, &config, 0 ); } while( sanei_config_read( str, sizeof(str), fp)) { DBG( _DBG_SANE_INIT, ">%s<\n", str ); if( str[0] == '#') /* ignore line comments */ continue; len = strlen(str); if( 0 == len ) continue; /* ignore empty lines */ /* check for options */ if( 0 == strncmp(str, "option", 6)) { int ival; double dval; ival = -1; decodeVal( str, "warmup", _INT, &config.adj.warmup, &ival); decodeVal( str, "lampOff", _INT, &config.adj.lampOff, &ival); decodeVal( str, "lOffOnEnd", _INT, &config.adj.lampOffOnEnd,&ival); decodeVal( str, "posShadingY",_INT, &config.adj.posShadingY,&ival); decodeVal( str, "tpaShadingY",_INT, &config.adj.tpaShadingY,&ival); decodeVal( str, "negShadingY",_INT, &config.adj.negShadingY,&ival); decodeVal( str, "red_gain", _INT, &config.adj.rgain, &ival); decodeVal( str, "green_gain", _INT, &config.adj.ggain, &ival); decodeVal( str, "blue_gain", _INT, &config.adj.bgain, &ival); decodeVal( str, "red_offset", _INT, &config.adj.rofs, &ival); decodeVal( str, "green_offset" , _INT, &config.adj.gofs, &ival); decodeVal( str, "blue_offset", _INT, &config.adj.bofs, &ival); decodeVal( str, "red_lampoff", _INT, &config.adj.rlampoff,&ival); decodeVal( str, "green_lampoff", _INT, &config.adj.glampoff,&ival); decodeVal( str, "blue_lampoff", _INT, &config.adj.blampoff,&ival); ival = 0; decodeVal( str, "enableTPA", _INT, &config.adj.enableTpa, &ival); decodeVal( str, "cacheCalData", _INT, &config.adj.cacheCalData,&ival); decodeVal( str, "altCalibration", _INT, &config.adj.altCalibrate,&ival); decodeVal( str, "skipCalibration", _INT, &config.adj.skipCalibration,&ival); decodeVal( str, "skipFine", _INT, &config.adj.skipFine,&ival); decodeVal( str, "skipFineWhite", _INT, &config.adj.skipFineWhite,&ival); decodeVal( str, "skipDarkStrip", _INT, &config.adj.skipDarkStrip,&ival); decodeVal( str, "incDarkTarget", _INT, &config.adj.incDarkTgt,&ival); decodeVal( str, "invertNegatives", _INT, &config.adj.invertNegatives,&ival); decodeVal( str, "disableSpeedup", _INT, &config.adj.disableSpeedup,&ival); decodeVal( str, "posOffX", _INT, &config.adj.pos.x, &ival ); decodeVal( str, "posOffY", _INT, &config.adj.pos.y, &ival ); decodeVal( str, "negOffX", _INT, &config.adj.neg.x, &ival ); decodeVal( str, "negOffY", _INT, &config.adj.neg.y, &ival ); decodeVal( str, "tpaOffX", _INT, &config.adj.tpa.x, &ival ); decodeVal( str, "tpaOffY", _INT, &config.adj.tpa.y, &ival ); decodeVal( str, "mov", _INT, &config.adj.mov, &ival); dval = 1.0; decodeVal( str, "grayGamma", _FLOAT, &config.adj.graygamma,&dval); decodeVal( str, "redGamma", _FLOAT, &config.adj.rgamma, &dval ); decodeVal( str, "greenGamma", _FLOAT, &config.adj.ggamma, &dval ); decodeVal( str, "blueGamma", _FLOAT, &config.adj.bgamma, &dval ); continue; /* check for sections: */ } else if( 0 == strncmp( str, _SECTION, strlen(_SECTION))) { char *tmp; /* new section, try and attach previous device */ if( config.devName[0] != '\0' ) { attach( config.devName, &config, 0 ); } else { if( first_dev != NULL ) { DBG( _DBG_WARNING, "section contains no device name," " ignored!\n" ); } } /* re-initialize the configuration structure */ init_config_struct( &config ); tmp = config.usbId; decodeUsbIDs( str, &tmp ); DBG( _DBG_SANE_INIT, "... next device\n" ); continue; } else if( SANE_TRUE == decodeDevName( str, config.devName )) { continue; } /* ignore other stuff... */ DBG( _DBG_SANE_INIT, "ignoring >%s<\n", str ); } fclose (fp); /* try to attach the last device in the config file... */ if( config.devName[0] != '\0' ) attach( config.devName, &config, 0 ); return SANE_STATUS_GOOD; } /** cleanup the backend... */ void sane_exit( void ) { DevList *tmp; Plustek_Device *dev, *next; DBG( _DBG_SANE_INIT, "sane_exit\n" ); for( dev = first_dev; dev; ) { next = dev->next; /* call the shutdown function of each device... */ usbDev_shutdown( dev ); /* we're doin' this to avoid compiler warnings as dev->sane.name * is defined as const char* */ if( dev->sane.name ) free( dev->name ); if( dev->calFile ) free( dev->calFile ); if( dev->res_list ) free( dev->res_list ); free( dev ); dev = next; } if( devlist ) free( devlist ); while( usbDevs ) { tmp = usbDevs->next; free( usbDevs ); usbDevs = tmp; } usbDevs = NULL; devlist = NULL; auth = NULL; first_dev = NULL; first_handle = NULL; } /** return a list of all devices */ SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only ) { int i; Plustek_Device *dev; DBG(_DBG_SANE_INIT, "sane_get_devices (%p, %ld)\n", (void *)device_list, (long) local_only); /* already called, so cleanup */ if( devlist ) free( devlist ); devlist = malloc((num_devices + 1) * sizeof (devlist[0])); if ( NULL == devlist ) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } /** open the sane device */ SANE_Status sane_open( SANE_String_Const devicename, SANE_Handle* handle ) { SANE_Status status; Plustek_Device *dev; Plustek_Scanner *s; CnfDef config; DBG( _DBG_SANE_INIT, "sane_open - %s\n", devicename ); if( devicename[0] ) { for( dev = first_dev; dev; dev = dev->next ) { if( strcmp( dev->sane.name, devicename ) == 0 ) break; } if( !dev ) { memset(&config, 0, sizeof(CnfDef)); status = attach( devicename, &config, &dev ); if( SANE_STATUS_GOOD != status ) return status; } } else { /* empty devicename -> use first device */ dev = first_dev; } if( !dev ) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if( NULL == s ) return SANE_STATUS_NO_MEM; memset(s, 0, sizeof (*s)); s->r_pipe = -1; s->w_pipe = -1; s->hw = dev; s->scanning = SANE_FALSE; s->calibrating = SANE_FALSE; init_options(s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return SANE_STATUS_GOOD; } /** */ void sane_close( SANE_Handle handle ) { Plustek_Scanner *prev, *s = handle; DBG( _DBG_SANE_INIT, "sane_close\n" ); if( s->calibrating ) do_cancel( s, SANE_FALSE ); /* remove handle from list of open handles: */ prev = 0; for( s = first_handle; s; s = s->next ) { if( s == handle ) break; prev = s; } if (!s) { DBG( _DBG_ERROR, "close: invalid handle %p\n", handle); return; } close_pipe( s ); if( NULL != s->buf ) free(s->buf); drvclose( s->hw ); if (prev) prev->next = s->next; else first_handle = s->next; free(s); } /** goes through a string list and returns the start-address of the string * that has been found, or NULL on error */ static const SANE_String_Const* search_string_list( const SANE_String_Const *list, SANE_String value ) { while( *list != NULL && strcmp(value, *list) != 0 ) ++list; if( *list == NULL ) return NULL; return list; } /** */ static int do_calibration( void *args ) { Plustek_Scanner *s = (Plustek_Scanner *)args; Plustek_Device *dev = s->hw; DCapsDef *caps = &dev->usbDev.Caps; int scanmode, rc; int modes[] = { COLOR_BW, COLOR_256GRAY, COLOR_GRAY16, COLOR_TRUE24, COLOR_TRUE48 }; thread_entry(); /* if the device does only support color scanning, there's no need * to calibrate the gray modes */ if (caps->workaroundFlag & _WAF_GRAY_FROM_COLOR) scanmode = 3; else scanmode = 0; for ( ; scanmode < 5; scanmode++ ) { if (caps->workaroundFlag & _WAF_ONLY_8BIT) { if ((modes[scanmode] == COLOR_GRAY16) || (modes[scanmode] == COLOR_TRUE48)) { continue; } } dev->scanning.dwFlag |= SCANFLAG_Calibration; if (SANE_STATUS_GOOD == local_sane_start(s, modes[scanmode])) { /* prepare for scanning: speed-test, warmup, calibration */ rc = usbDev_Prepare( dev, s->buf ); if( rc != 0 || scanmode == 4) { if (rc != 0 ) DBG(_DBG_INFO,"Calibration canceled!\n"); m_fStart = SANE_TRUE; m_fAutoPark = SANE_TRUE; } drvclose( dev ); if( rc != 0 ) break; } else { DBG(_DBG_ERROR, "local_sane_start() failed!\n"); break; } } /* restore the settings */ dev->scanning.dwFlag &= ~SCANFLAG_Calibration; s->calibrating = SANE_FALSE; return 0; } /** return or set the parameter values, also do some checks */ SANE_Status sane_control_option( SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info ) { Plustek_Scanner *s = (Plustek_Scanner *)handle; Plustek_Device *dev = s->hw; AdjDef *adj = &dev->adj; DCapsDef *caps = &dev->usbDev.Caps; SANE_Status status; const SANE_String_Const *optval; int scanmode; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; /* in calibration mode, we do not allow setting any value! */ if(s->calibrating) { if (action == SANE_ACTION_SET_VALUE) { if (option == OPT_CALIBRATE) { if( NULL != info ) *info |= SANE_INFO_RELOAD_OPTIONS; do_cancel(s, SANE_TRUE); return SANE_STATUS_GOOD; } /* okay, we need some exceptions */ switch (option) { case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: break; default: return SANE_STATUS_DEVICE_BUSY; } } } if ((option < 0) || (option >= NUM_OPTIONS)) return SANE_STATUS_INVAL; if (NULL != info) *info = 0; switch( action ) { case SANE_ACTION_GET_VALUE: switch (option) { case OPT_PREVIEW: case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_BIT_DEPTH: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_LAMPSWITCH: case OPT_CUSTOM_GAMMA: case OPT_LAMPOFF_ONEND: case OPT_LOFF4DARK: case OPT_CACHECAL: case OPT_SPEEDUP: case OPT_OVR_REDGAIN: case OPT_OVR_GREENGAIN: case OPT_OVR_BLUEGAIN: case OPT_OVR_REDOFS: case OPT_OVR_GREENOFS: case OPT_OVR_BLUEOFS: case OPT_OVR_RED_LOFF: case OPT_OVR_GREEN_LOFF: case OPT_OVR_BLUE_LOFF: case OPT_LAMPOFF_TIMER: case OPT_WARMUPTIME: *(SANE_Word *)value = s->val[option].w; break; case OPT_BUTTON_0: if(!s->calibrating) usb_UpdateButtonStatus(s); case OPT_BUTTON_1: case OPT_BUTTON_2: case OPT_BUTTON_3: case OPT_BUTTON_4: /* copy the button state */ *(SANE_Word*)value = s->val[option].w; /* clear the button state */ s->val[option].w = SANE_FALSE; break; case OPT_CONTRAST: case OPT_BRIGHTNESS: *(SANE_Word *)value = (s->val[option].w << SANE_FIXED_SCALE_SHIFT); break; case OPT_MODE: case OPT_EXT_MODE: strcpy ((char *) value, s->opt[option].constraint.string_list[s->val[option].w]); break; /* word array options: */ case OPT_GAMMA_VECTOR: DBG( _DBG_INFO, "Reading MASTER gamma.\n" ); memcpy( value, s->val[option].wa, s->opt[option].size ); break; case OPT_GAMMA_VECTOR_R: DBG( _DBG_INFO, "Reading RED gamma.\n" ); memcpy( value, s->val[option].wa, s->opt[option].size ); break; case OPT_GAMMA_VECTOR_G: DBG( _DBG_INFO, "Reading GREEN gamma.\n" ); memcpy( value, s->val[option].wa, s->opt[option].size ); break; case OPT_GAMMA_VECTOR_B: DBG( _DBG_INFO, "Reading BLUE gamma.\n" ); memcpy( value, s->val[option].wa, s->opt[option].size ); break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: status = sanei_constrain_value( s->opt + option, value, info ); if( SANE_STATUS_GOOD != status ) return status; optval = NULL; if( SANE_CONSTRAINT_STRING_LIST == s->opt[option].constraint_type ) { optval = search_string_list( s->opt[option].constraint.string_list, (char *) value); if( NULL == optval ) return SANE_STATUS_INVAL; } switch (option) { case OPT_RESOLUTION: { int n; int min_d = dev->res_list[dev->res_list_size - 1]; int v = *(SANE_Word *)value; int best = v; for( n = 0; n < dev->res_list_size; n++ ) { int d = abs(v - dev->res_list[n]); if( d < min_d ) { min_d = d; best = dev->res_list[n]; } } s->val[option].w = (SANE_Word)best; if( v != best ) *(SANE_Word *)value = best; if( NULL != info ) { if( v != best ) *info |= SANE_INFO_INEXACT; *info |= SANE_INFO_RELOAD_PARAMS; } break; } case OPT_PREVIEW: case OPT_BIT_DEPTH: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *)value; if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_CACHECAL: s->val[option].w = *(SANE_Word *)value; dev->adj.cacheCalData = s->val[option].w; if( !dev->adj.cacheCalData ) _DISABLE(OPT_CALIBRATE); else { if( usb_IsCISDevice(dev) || dev->adj.altCalibrate) _ENABLE(OPT_CALIBRATE); } if( NULL != info ) *info |= SANE_INFO_RELOAD_OPTIONS; break; case OPT_CALIBRATE: if (s->calibrating) { do_cancel( s, SANE_FALSE ); s->calibrating = SANE_FALSE; } else { sc = s; s->r_pipe = -1; s->w_pipe = -1; s->reader_pid = sanei_thread_begin(do_calibration, s); s->calibrating = SANE_TRUE; signal( SIGCHLD, sig_chldhandler ); } if (NULL != info) *info |= SANE_INFO_RELOAD_OPTIONS; break; case OPT_SPEEDUP: s->val[option].w = *(SANE_Word *)value; dev->adj.disableSpeedup = !(s->val[option].w); break; case OPT_LOFF4DARK: s->val[option].w = *(SANE_Word *)value; dev->adj.skipDarkStrip = !(s->val[option].w); break; case OPT_LAMPSWITCH: s->val[option].w = *(SANE_Word *)value; usb_LampSwitch( dev, s->val[option].w ); if( s->val[option].w == 0 ) usb_StopLampTimer( dev ); else usb_StartLampTimer( dev ); break; case OPT_LAMPOFF_ONEND: s->val[option].w = *(SANE_Word *)value; dev->adj.lampOffOnEnd = s->val[option].w; usb_CheckAndCopyAdjs( dev ); break; case OPT_CUSTOM_GAMMA: s->val[option].w = *(SANE_Word *)value; if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; scanmode = getScanMode( s ); _DISABLE(OPT_GAMMA_VECTOR); _DISABLE(OPT_GAMMA_VECTOR_R); _DISABLE(OPT_GAMMA_VECTOR_G); _DISABLE(OPT_GAMMA_VECTOR_B); if( SANE_TRUE == s->val[option].w ) { DBG( _DBG_INFO, "Using custom gamma settings.\n" ); if((scanmode == COLOR_256GRAY) || (scanmode == COLOR_GRAY16)) { _ENABLE(OPT_GAMMA_VECTOR); } else { _ENABLE(OPT_GAMMA_VECTOR_R); _ENABLE(OPT_GAMMA_VECTOR_G); _ENABLE(OPT_GAMMA_VECTOR_B); } } else { DBG( _DBG_INFO, "NOT using custom gamma settings.\n" ); initGammaSettings( s ); if((scanmode == COLOR_256GRAY) || (scanmode == COLOR_GRAY16)) { _DISABLE(OPT_GAMMA_VECTOR); } else { _DISABLE(OPT_GAMMA_VECTOR_R); _DISABLE(OPT_GAMMA_VECTOR_G); _DISABLE(OPT_GAMMA_VECTOR_B); } } break; case OPT_LAMPOFF_TIMER: s->val[option].w = (*(SANE_Word *)value); adj->lampOff = (*(SANE_Word *)value); usb_CheckAndCopyAdjs( dev ); break; case OPT_WARMUPTIME: s->val[option].w = (*(SANE_Word *)value); adj->warmup = (*(SANE_Word *)value); usb_CheckAndCopyAdjs( dev ); break; case OPT_OVR_REDGAIN: s->val[option].w = (*(SANE_Word *)value); adj->rgain = (*(SANE_Word *)value); break; case OPT_OVR_GREENGAIN: s->val[option].w = (*(SANE_Word *)value); adj->ggain = (*(SANE_Word *)value); break; case OPT_OVR_BLUEGAIN: s->val[option].w = (*(SANE_Word *)value); adj->bgain = (*(SANE_Word *)value); break; case OPT_OVR_REDOFS: s->val[option].w = (*(SANE_Word *)value); adj->rofs = (*(SANE_Word *)value); break; case OPT_OVR_GREENOFS: s->val[option].w = (*(SANE_Word *)value); adj->gofs = (*(SANE_Word *)value); break; case OPT_OVR_BLUEOFS: s->val[option].w = (*(SANE_Word *)value); adj->bofs = (*(SANE_Word *)value); break; case OPT_OVR_RED_LOFF: s->val[option].w = (*(SANE_Word *)value); adj->rlampoff = (*(SANE_Word *)value); break; case OPT_OVR_GREEN_LOFF: s->val[option].w = (*(SANE_Word *)value); adj->glampoff = (*(SANE_Word *)value); break; case OPT_OVR_BLUE_LOFF: s->val[option].w = (*(SANE_Word *)value); adj->blampoff = (*(SANE_Word *)value); break; case OPT_CONTRAST: case OPT_BRIGHTNESS: s->val[option].w = ((*(SANE_Word *)value) >> SANE_FIXED_SCALE_SHIFT); break; case OPT_MODE: s->val[option].w = optval - s->opt[option].constraint.string_list; scanmode = getScanMode( s ); _ENABLE(OPT_CONTRAST); _ENABLE(OPT_BIT_DEPTH); _ENABLE(OPT_CUSTOM_GAMMA); if (scanmode == COLOR_BW) { _DISABLE(OPT_CONTRAST); _DISABLE(OPT_CUSTOM_GAMMA); _DISABLE(OPT_BIT_DEPTH); } if (caps->workaroundFlag & _WAF_ONLY_8BIT) _DISABLE(OPT_BIT_DEPTH); _DISABLE(OPT_GAMMA_VECTOR); _DISABLE(OPT_GAMMA_VECTOR_R); _DISABLE(OPT_GAMMA_VECTOR_G); _DISABLE(OPT_GAMMA_VECTOR_B); if( s->val[OPT_CUSTOM_GAMMA].w && !(s->opt[OPT_CUSTOM_GAMMA].cap & SANE_CAP_INACTIVE)) { if((scanmode == COLOR_256GRAY) || (scanmode == COLOR_GRAY16)) { _ENABLE(OPT_GAMMA_VECTOR); } else { _ENABLE(OPT_GAMMA_VECTOR_R); _ENABLE(OPT_GAMMA_VECTOR_G); _ENABLE(OPT_GAMMA_VECTOR_B); } } if( NULL != info ) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; case OPT_EXT_MODE: { s->val[option].w = optval - s->opt[option].constraint.string_list; /* change the area and mode_list when changing the source */ if( s->val[option].w == 0 ) { dev->scanning.sParam.bSource = SOURCE_Reflection; dev->dpi_range.min = _DEF_DPI; dev->x_range.max = SANE_FIX(dev->max_x); dev->y_range.max = SANE_FIX(dev->max_y); s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = 2; /* HEINER COLOR_TRUE24;*/ } else { dev->dpi_range.min = _TPAMinDpi; if( s->val[option].w == 1 ) { dev->scanning.sParam.bSource = SOURCE_Transparency; if( dev->usbDev.Caps.wFlags & DEVCAPSFLAG_LargeTPA ) { dev->x_range.max = SANE_FIX(_SCALE(_TPALargePageWidth)); dev->y_range.max = SANE_FIX(_SCALE(_TPALargePageHeight)); } else { dev->x_range.max = SANE_FIX(_SCALE(_TPAPageWidth)); dev->y_range.max = SANE_FIX(_SCALE(_TPAPageHeight)); } s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TP_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TP_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_TP_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_TP_BRY); } else { dev->scanning.sParam.bSource = SOURCE_Negative; if( dev->usbDev.Caps.wFlags & DEVCAPSFLAG_LargeTPA ) { dev->x_range.max = SANE_FIX(_SCALE(_NegLargePageWidth)); dev->y_range.max = SANE_FIX(_SCALE(_NegLargePageHeight)); } else { dev->x_range.max = SANE_FIX(_SCALE(_NegPageWidth)); dev->y_range.max = SANE_FIX(_SCALE(_NegPageHeight)); } s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_NEG_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_NEG_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_NEG_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_NEG_BRY); } s->opt[OPT_MODE].constraint.string_list = &mode_list[2]; s->val[OPT_MODE].w = 0; /* COLOR_24 is the default */ } if( s->val[OPT_LAMPSWITCH].w != 0 ) { usb_LampSwitch( dev, s->val[OPT_LAMPSWITCH].w ); if( s->val[OPT_LAMPSWITCH].w == 0 ) usb_StopLampTimer( dev ); else usb_StartLampTimer( dev ); } _ENABLE(OPT_CONTRAST); if( NULL != info ) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; } case OPT_GAMMA_VECTOR: DBG( _DBG_INFO, "Setting MASTER gamma.\n" ); memcpy( s->val[option].wa, value, s->opt[option].size ); checkGammaSettings(s); if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_GAMMA_VECTOR_R: DBG( _DBG_INFO, "Setting RED gamma.\n" ); memcpy( s->val[option].wa, value, s->opt[option].size ); checkGammaSettings(s); if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_GAMMA_VECTOR_G: DBG( _DBG_INFO, "Setting GREEN gamma.\n" ); memcpy( s->val[option].wa, value, s->opt[option].size ); checkGammaSettings(s); if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_GAMMA_VECTOR_B: DBG( _DBG_INFO, "Setting BLUE gamma.\n" ); memcpy( s->val[option].wa, value, s->opt[option].size ); checkGammaSettings(s); if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; default: return SANE_STATUS_INVAL; } break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /** according to the option number, return a pointer to a descriptor */ const SANE_Option_Descriptor* sane_get_option_descriptor( SANE_Handle handle, SANE_Int option ) { Plustek_Scanner *s = (Plustek_Scanner *)handle; if((option < 0) || (option >= NUM_OPTIONS)) return NULL; return &(s->opt[option]); } /** return the current parameter settings */ SANE_Status sane_get_parameters( SANE_Handle handle, SANE_Parameters *params ) { int ndpi; int scanmode; Plustek_Scanner *s = (Plustek_Scanner *)handle; /* if we're calling from within, calc best guess * do the same, if sane_get_parameters() is called * by a frontend before sane_start() is called */ if((NULL == params) || (s->scanning != SANE_TRUE)) { memset(&s->params, 0, sizeof (SANE_Parameters)); ndpi = s->val[OPT_RESOLUTION].w; s->params.pixels_per_line = SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) / MM_PER_INCH * ndpi; s->params.lines = SANE_UNFIX( s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) / MM_PER_INCH * ndpi; /* pixels_per_line seems to be 8 * n. */ /* s->params.pixels_per_line = s->params.pixels_per_line & ~7; debug only */ s->params.last_frame = SANE_TRUE; scanmode = getScanMode( s ); if( scanmode == COLOR_TRUE24 || scanmode == COLOR_TRUE48 ) { s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line; } else { s->params.format = SANE_FRAME_GRAY; if (s->params.depth == 1) s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; else s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8; } /* if sane_get_parameters() was called before sane_start() */ /* pass new values to the caller */ if ((NULL != params) && (s->scanning != SANE_TRUE)) *params = s->params; } else { *params = s->params; } return SANE_STATUS_GOOD; } /** initiate the scan process */ static SANE_Status local_sane_start(Plustek_Scanner *s, int scanmode ) { Plustek_Device *dev; int result; int ndpi; int left, top; int width, height; double dpi_x, dpi_y; CropInfo crop; ScanInfo sinfo; SANE_Word tmp; /* clear it out just in case */ memset(&crop, 0, sizeof(crop)); dev = s->hw; /* check if we're called from the option dialog! */ if (usb_InCalibrationMode(dev)) crop.ImgDef.dwFlag = SCANFLAG_Calibration; /* open the driver and get some information about the scanner */ dev->fd = usbDev_open( dev, NULL, SANE_TRUE ); if( dev->fd < 0 ) { DBG( _DBG_ERROR, "sane_start: open failed: %d\n", errno); if( errno == EBUSY ) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_IO_ERROR; } result = usbDev_getCaps( dev ); if( result < 0 ) { DBG( _DBG_ERROR, "usbDev_getCaps() failed(%d)\n", result); sanei_access_unlock( dev->sane.name ); usbDev_close( dev ); return SANE_STATUS_IO_ERROR; } /* All ready to go. Set image def and see what the scanner * says for crop info. */ ndpi = s->val[OPT_RESOLUTION].w; /* exchange the values as we can't deal with * negative heights and so on...*/ tmp = s->val[OPT_TL_X].w; if( tmp > s->val[OPT_BR_X].w ) { DBG( _DBG_INFO, "exchanging BR-X - TL-X\n" ); s->val[OPT_TL_X].w = s->val[OPT_BR_X].w; s->val[OPT_BR_X].w = tmp; } tmp = s->val[OPT_TL_Y].w; if( tmp > s->val[OPT_BR_Y].w ) { DBG( _DBG_INFO, "exchanging BR-Y - TL-Y\n" ); s->val[OPT_TL_Y].w = s->val[OPT_BR_Y].w; s->val[OPT_BR_Y].w = tmp; } /* position and extent are always relative to 300 dpi */ dpi_x = (double)dev->usbDev.Caps.OpticDpi.x; dpi_y = (double)dev->usbDev.Caps.OpticDpi.x * 2; left = (int)(SANE_UNFIX (s->val[OPT_TL_X].w)*dpi_x/ (MM_PER_INCH*(dpi_x/300.0))); top = (int)(SANE_UNFIX (s->val[OPT_TL_Y].w)*dpi_y/ (MM_PER_INCH*(dpi_y/300.0))); width = (int)(SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * dpi_x / (MM_PER_INCH *(dpi_x/300.0))); height = (int)(SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) * dpi_y / (MM_PER_INCH *(dpi_y/300.0))); /* adjust mode list according to the model we use and the * source we have */ DBG( _DBG_INFO, "scanmode = %u\n", scanmode ); crop.ImgDef.xyDpi.x = ndpi; crop.ImgDef.xyDpi.y = ndpi; crop.ImgDef.crArea.x = left; /* offset from left edge to area you want to scan */ crop.ImgDef.crArea.y = top; /* offset from top edge to area you want to scan */ crop.ImgDef.crArea.cx = width; /* always relative to 300 dpi */ crop.ImgDef.crArea.cy = height; crop.ImgDef.wDataType = scanmode; crop.ImgDef.dwFlag |= SCANDEF_QualityScan; switch( s->val[OPT_EXT_MODE].w ) { case 1: crop.ImgDef.dwFlag |= SCANDEF_Transparency; break; case 2: crop.ImgDef.dwFlag |= SCANDEF_Negative; break; default: break; } result = usbDev_getCropInfo( dev, &crop ); if( result < 0 ) { DBG( _DBG_ERROR, "usbDev_getCropInfo() failed(%d)\n", result ); usbDev_close( dev ); sanei_access_unlock( dev->sane.name ); return SANE_STATUS_IO_ERROR; } /* DataInf.dwAppPixelsPerLine = crop.dwPixelsPerLine; */ s->params.pixels_per_line = crop.dwPixelsPerLine; s->params.bytes_per_line = crop.dwBytesPerLine; s->params.lines = crop.dwLinesPerArea; /* build a SCANINFO block and get ready to scan it */ crop.ImgDef.dwFlag |= SCANDEF_QualityScan; /* remove that for preview scans */ if( s->val[OPT_PREVIEW].w ) crop.ImgDef.dwFlag &= (~SCANDEF_QualityScan); /* set adjustments for brightness and contrast */ sinfo.siBrightness = s->val[OPT_BRIGHTNESS].w; sinfo.siContrast = s->val[OPT_CONTRAST].w; memcpy( &sinfo.ImgDef, &crop.ImgDef, sizeof(ImgDef)); DBG( _DBG_SANE_INIT, "brightness %i, contrast %i\n", sinfo.siBrightness, sinfo.siContrast ); result = usbDev_setScanEnv( dev, &sinfo ); if( result < 0 ) { DBG( _DBG_ERROR, "usbDev_setScanEnv() failed(%d)\n", result ); usbDev_close( dev ); sanei_access_unlock( dev->sane.name ); return SANE_STATUS_IO_ERROR; } /* download gamma correction tables... */ if( scanmode <= COLOR_GRAY16 ) { usbDev_setMap( dev, s->gamma_table[0], s->gamma_length, _MAP_MASTER); } else { usbDev_setMap( dev, s->gamma_table[1], s->gamma_length, _MAP_RED ); usbDev_setMap( dev, s->gamma_table[2], s->gamma_length, _MAP_GREEN ); usbDev_setMap( dev, s->gamma_table[3], s->gamma_length, _MAP_BLUE ); } tsecs = 0; /* reset timer */ result = usbDev_startScan( dev ); if( result < 0 ) { DBG( _DBG_ERROR, "usbDev_startScan() failed(%d)\n", result ); usbDev_close( dev ); sanei_access_unlock( dev->sane.name ); return SANE_STATUS_IO_ERROR; } DBG( _DBG_SANE_INIT, "dwflag = 0x%lx dwBytesLine = %ld\n", dev->scanning.dwFlag, dev->scanning.dwBytesLine ); DBG( _DBG_SANE_INIT, "Lines = %d\n", s->params.lines); DBG( _DBG_SANE_INIT, "Bytes per Line = %d\n", s->params.bytes_per_line ); DBG( _DBG_SANE_INIT, "Bitdepth = %d\n", s->params.depth ); if (usb_InCalibrationMode(dev)) { if (s->buf) free(s->buf); s->buf = NULL; } else { if (s->params.lines == 0 || s->params.bytes_per_line == 0) { DBG( _DBG_ERROR, "nothing to scan!\n" ); usbDev_close( dev ); sanei_access_unlock( dev->sane.name ); return SANE_STATUS_INVAL; } s->buf = realloc( s->buf, (s->params.lines) * s->params.bytes_per_line ); if( NULL == s->buf ) { DBG( _DBG_ERROR, "realloc failed\n" ); usbDev_close( dev ); sanei_access_unlock( dev->sane.name ); return SANE_STATUS_NO_MEM; } } tsecs = (unsigned long)time(NULL); DBG( _DBG_INFO, "TIME START\n" ); DBG( _DBG_SANE_INIT, "local_sane_start done\n" ); return SANE_STATUS_GOOD; } /** initiate the scan process */ SANE_Status sane_start( SANE_Handle handle ) { Plustek_Scanner *s = (Plustek_Scanner *)handle; Plustek_Device *dev = s->hw; SANE_Status status; int fds[2]; DBG( _DBG_SANE_INIT, "sane_start\n" ); if (s->scanning) return SANE_STATUS_DEVICE_BUSY; /* in the end we wait until the calibration is done... */ if (s->calibrating) { while (s->calibrating) { sleep(1); } /* we have been cancelled? */ if (cancelRead) return SANE_STATUS_CANCELLED; } status = sane_get_parameters (handle, NULL); if (status != SANE_STATUS_GOOD) { DBG( _DBG_ERROR, "sane_get_parameters failed\n" ); return status; } status = local_sane_start(s, getScanMode(s)); if (status != SANE_STATUS_GOOD) { return status; } s->scanning = SANE_TRUE; /* * everything prepared, so start the child process and a pipe to communicate * pipe --> fds[0]=read-fd, fds[1]=write-fd */ if( pipe(fds) < 0 ) { DBG( _DBG_ERROR, "ERROR: could not create pipe\n" ); s->scanning = SANE_FALSE; usbDev_close( dev ); return SANE_STATUS_IO_ERROR; } /* create reader routine as new process */ s->bytes_read = 0; s->r_pipe = fds[0]; s->w_pipe = fds[1]; s->ipc_read_done = SANE_FALSE; s->reader_pid = sanei_thread_begin( reader_process, s ); cancelRead = SANE_FALSE; if( !sanei_thread_is_valid (s->reader_pid) ) { DBG( _DBG_ERROR, "ERROR: could not start reader task\n" ); s->scanning = SANE_FALSE; usbDev_close( dev ); return SANE_STATUS_IO_ERROR; } signal( SIGCHLD, sig_chldhandler ); if( sanei_thread_is_forked()) { close( s->w_pipe ); s->w_pipe = -1; } DBG( _DBG_SANE_INIT, "sane_start done\n" ); return SANE_STATUS_GOOD; } /** function to read the data from our child process */ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length ) { Plustek_Scanner *s = (Plustek_Scanner*)handle; ssize_t nread; #ifdef USE_IPC static IPCDef ipc; unsigned char *buf; static unsigned long c = 0; #endif *length = 0; #ifdef USE_IPC /* first try and read IPC... */ if( !s->ipc_read_done ) { buf = (unsigned char*)&ipc; for( c = 0; c < sizeof(ipc); ) { nread = read( s->r_pipe, buf, sizeof(ipc)); if( nread < 0 ) { if( EAGAIN != errno ) { do_cancel( s, SANE_TRUE ); return SANE_STATUS_IO_ERROR; } else { return SANE_STATUS_GOOD; } } else { c += nread; buf += nread; if( c == sizeof(ipc)) { s->ipc_read_done = SANE_TRUE; break; } } } s->hw->transferRate = ipc.transferRate; DBG( _DBG_INFO, "IPC: Transferrate = %lu Bytes/s\n", ipc.transferRate ); } #endif /* here we read all data from the driver... */ nread = read( s->r_pipe, data, max_length ); DBG( _DBG_READ, "sane_read - read %ld bytes\n", (long)nread ); if (!(s->scanning)) { return do_cancel( s, SANE_TRUE ); } if( nread < 0 ) { if( EAGAIN == errno ) { /* if we already had red the picture, so it's okay and stop */ if( s->bytes_read == (unsigned long)(s->params.lines * s->params.bytes_per_line)) { sanei_thread_waitpid( s->reader_pid, 0 ); s->reader_pid = -1; s->scanning = SANE_FALSE; drvclose( s->hw ); return close_pipe(s); } /* else force the frontend to try again*/ return SANE_STATUS_GOOD; } else { DBG( _DBG_ERROR, "ERROR: errno=%d\n", errno ); do_cancel( s, SANE_TRUE ); return SANE_STATUS_IO_ERROR; } } *length = nread; s->bytes_read += nread; /* nothing red means that we're finished OR we had a problem... */ if( 0 == nread ) { drvclose( s->hw ); s->exit_code = sanei_thread_get_status( s->reader_pid ); if( SANE_STATUS_GOOD != s->exit_code ) { close_pipe(s); return s->exit_code; } s->reader_pid = -1; s->scanning = SANE_FALSE; return close_pipe(s); } return SANE_STATUS_GOOD; } /** cancel the scanning process */ void sane_cancel( SANE_Handle handle ) { Plustek_Scanner *s = (Plustek_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_cancel\n" ); if (s->scanning || s->calibrating) do_cancel( s, SANE_FALSE ); } /** set the pipe to blocking/non blocking mode */ SANE_Status sane_set_io_mode( SANE_Handle handle, SANE_Bool non_blocking ) { Plustek_Scanner *s = (Plustek_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_set_io_mode: non_blocking=%d\n",non_blocking ); if ( !s->scanning ) { DBG( _DBG_ERROR, "ERROR: not scanning !\n" ); return SANE_STATUS_INVAL; } if( -1 == s->r_pipe ) { DBG( _DBG_ERROR, "ERROR: not supported !\n" ); return SANE_STATUS_UNSUPPORTED; } if( fcntl (s->r_pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { DBG( _DBG_ERROR, "ERROR: could not set to non-blocking mode !\n" ); return SANE_STATUS_IO_ERROR; } DBG( _DBG_SANE_INIT, "sane_set_io_mode done\n" ); return SANE_STATUS_GOOD; } /** return the descriptor if available */ SANE_Status sane_get_select_fd( SANE_Handle handle, SANE_Int * fd ) { Plustek_Scanner *s = (Plustek_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_get_select_fd\n" ); if( !s->scanning ) { DBG( _DBG_ERROR, "ERROR: not scanning !\n" ); return SANE_STATUS_INVAL; } *fd = s->r_pipe; DBG( _DBG_SANE_INIT, "sane_get_select_fd done\n" ); return SANE_STATUS_GOOD; } /* END PLUSTEK.C ............................................................*/ sane-backends-1.0.27/backend/u12-hw.c0000664000175000017500000007112212775312261014011 00000000000000/** @file u12-hw.c * @brief The HW-access functions to the U12 backend stuff. * * Copyright (c) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - cleanup * - added lampTimer stuff * - fixed issue for Genius device - reported by * Jose Alberto Reguero * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #define _TEST_SIZE 1000 /*************************** some local vars *********************************/ static RegDef u12CcdStop[] = { /* this was the original sequence from parport backend*/ #if 0 #define _STOP_LEN 13 {0x41, 0xff}, {0x42, 0xff}, {0x60, 0xff}, {0x61, 0xff}, {0x4b, 0xff}, {0x4c, 0xff}, {0x4d, 0xff}, {0x4e, 0xff}, {0x2a, 0x01}, {0x2b, 0x00}, {0x2d, 0x00}, {0x1b, 0x19}, {0x15, 0x00} #else #define _STOP_LEN 29 /* this is what we see from usb-snoop... */ {0x60, 0xff}, {0x61, 0xff}, {0x1b, 0x19}, {0x15, 0x00}, {0x20, 0x14}, {0x2c, 0x02}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00}, {0x3c, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00}, {0x44, 0x00}, {0x45, 0x01}, {0x46, 0x00}, {0x47, 0x00}, {0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x09}, {0x4b, 0x00}, {0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x01}, {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x01}, {0x67, 0x00} #endif }; /** */ static void u12hw_SelectLampSource( U12_Device *dev ) { dev->regs.RD_ScanControl &= (~_SCAN_LAMPS_ON); if( dev->DataInf.dwScanFlag & (_SCANDEF_TPA)) { dev->regs.RD_ScanControl |= _SCAN_TPALAMP_ON; } else { dev->regs.RD_ScanControl |= _SCAN_NORMALLAMP_ON; } } /** as the function name says */ static void u12hw_PutToIdleMode( U12_Device *dev ) { DBG( _DBG_INFO, "CCD-Stop\n" ); u12io_DataToRegs( dev, (SANE_Byte*)u12CcdStop, _STOP_LEN ); } /** program the CCD relevant stuff */ static void u12hw_ProgramCCD( U12_Device *dev ) { SANE_Byte *reg_val; DBG( _DBG_INFO, "u12hw_ProgramCCD: 0x%08lx[%lu]\n", (u_long)dev->CCDRegs, ((u_long)dev->numCCDRegs * dev->shade.intermediate)); DBG( _DBG_INFO, " * %u regs * %u (intermediate)\n", dev->numCCDRegs, dev->shade.intermediate ); reg_val = (SANE_Byte*)(dev->CCDRegs + (u_long)dev->numCCDRegs * dev->shade.intermediate); u12io_DataToRegs( dev, reg_val, dev->numCCDRegs ); } /** init the stuff according to the buttons */ static void u12hw_ButtonSetup( U12_Device *dev, SANE_Byte numButtons ) { dev->Buttons = numButtons; dev->regs.RD_MotorDriverType |= _BUTTON_DISABLE; dev->MotorPower |= _BUTTON_DISABLE; } /** According to what we have detected, set the other stuff */ static void u12hw_InitiateComponentModel( U12_Device *dev ) { /* preset some stuff and do the differences later */ dev->Buttons = 0; dev->ModelOriginY = 64; dev->Tpa = SANE_FALSE; dev->ModelCtrl = (_LED_ACTIVITY | _LED_CONTROL); switch( dev->PCBID ) { /* typical for Plustek OpticPro U12 and 1212U */ case _PLUSTEK_SCANNER: DBG( _DBG_INFO, "We have a Plustek Scanner ;-)\n" ); break; case _SCANNER_WITH_TPA: DBG( _DBG_INFO, "Scanner has TPA\n" ); dev->Tpa = SANE_TRUE; break; case _SCANNER4Button: DBG( _DBG_INFO, "Scanner has 4 Buttons\n" ); u12hw_ButtonSetup( dev, 4 ); break; /* typical for Plustek OpticPro UT12 */ case _SCANNER4ButtonTPA: DBG( _DBG_INFO, "Scanner has 4 Buttons & TPA\n" ); dev->Tpa = SANE_TRUE; u12hw_ButtonSetup( dev, 4 ); break; case _SCANNER5Button: DBG( _DBG_INFO, "Scanner has 5 Buttons\n" ); dev->ModelOriginY += 20; u12hw_ButtonSetup( dev, 5 ); break; /* typical for Genius Colorpage HR6 */ case _SCANNER5ButtonTPA: DBG( _DBG_INFO, "Scanner has 5 Buttons & TPA\n" ); dev->ModelOriginY += 20; dev->Tpa = SANE_TRUE; u12hw_ButtonSetup( dev, 5 ); break; case _SCANNER1Button: DBG( _DBG_INFO, "Scanner has 1 Button\n" ); u12hw_ButtonSetup( dev, 1 ); break; case _SCANNER1ButtonTPA: DBG( _DBG_INFO, "Scanner has 1 Button & TPA\n" ); dev->Tpa = SANE_TRUE; u12hw_ButtonSetup( dev, 1 ); break; case _AGFA_SCANNER: DBG( _DBG_INFO, "Agfa Scanner\n" ); dev->ModelOriginY = 24; /* 1200 dpi */ break; case _SCANNER2Button: DBG( _DBG_INFO, "Scanner has 2 Buttons\n" ); dev->ModelOriginY -= 33; u12hw_ButtonSetup( dev, 2 ); break; default: DBG( _DBG_INFO, "Default Model: U12\n" ); break; } #if 0 if( _MOTOR0_2003 == dev->MotorID ) { dev->f2003 = SANE_TRUE; dev->XStepMono = 10; dev->XStepColor = 6; dev->XStepBack = 5; dev->regs.RD_MotorDriverType |= _MOTORR_STRONG; } else { #endif dev->f2003 = SANE_FALSE; dev->XStepMono = 8; dev->XStepColor = 4; dev->XStepBack = 5; dev->regs.RD_MotorDriverType |= _MOTORR_WEAK; /* } */ } /** */ static SANE_Status u12hw_InitAsic( U12_Device *dev, SANE_Bool shading ) { SANE_Byte rb[6]; int c; DBG( _DBG_INFO, "u12hw_InitAsic(%d)\n", shading ); /* get DAC and motor stuff */ dev->DACType = u12io_DataFromRegister( dev, REG_RESETCONFIG ); dev->MotorID = (SANE_Byte)(dev->DACType & _MOTOR0_MASK); dev->regs.RD_MotorDriverType = (SANE_Byte)((dev->DACType & _MOTOR0_MASK) >> 3); dev->regs.RD_MotorDriverType |= (SANE_Byte)((dev->DACType & _MOTOR1_MASK) >> 1); dev->DACType &= _ADC_MASK; dev->MotorPower = dev->regs.RD_MotorDriverType | _MOTORR_STRONG; /*get CCD and PCB ID */ dev->PCBID = u12io_DataFromRegister( dev, REG_CONFIG ); dev->CCDID = dev->PCBID & 0x07; dev->PCBID &= 0xf0; if( _AGFA_SCANNER == dev->PCBID ) dev->DACType = _DA_WOLFSON8141; DBG( _DBG_INFO, "* PCB-ID=0x%02x, CCD-ID=0x%02x, DAC-TYPE=0x%02x\n", dev->PCBID, dev->CCDID, dev->DACType ); u12hw_InitiateComponentModel( dev ); u12ccd_InitCCDandDAC( dev, shading ); dev->regs.RD_Model1Control = _CCD_SHIFT_GATE; if( dev->Buttons != 0 ) dev->regs.RD_Model1Control += _BUTTON_MODE; if( dev->shade.intermediate & _ScanMode_Mono ) dev->regs.RD_Model1Control += _SCAN_GRAYTYPE; DBG( _DBG_INFO, "* MotorDrvType = 0x%02x\n", dev->regs.RD_MotorDriverType); DBG( _DBG_INFO, "* Model1Cntrl = 0x%02x\n", dev->regs.RD_Model1Control ); #if 0 u12io_DataToRegister( dev, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType); u12io_DataToRegister( dev, REG_WAITSTATEINSERT, 4 ); u12io_DataToRegister( dev, REG_MODEL1CONTROL, dev->regs.RD_Model1Control ); #else c = 0; _SET_REG( rb, c, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType); _SET_REG( rb, c, REG_WAITSTATEINSERT, 4 ); _SET_REG( rb, c, REG_MODEL1CONTROL, dev->regs.RD_Model1Control ); u12io_DataToRegs( dev, rb, c ); #endif u12hw_ProgramCCD( dev ); DBG( _DBG_INFO, "u12hw_InitAsic done.\n" ); return SANE_STATUS_GOOD; } /** */ static void u12hw_ControlLampOnOff( U12_Device *dev ) { SANE_Byte lampStatus; dev->warmupNeeded = SANE_TRUE; lampStatus = dev->regs.RD_ScanControl & _SCAN_LAMPS_ON; if ( dev->lastLampStatus != lampStatus ) { DBG( _DBG_INFO, "* Using OTHER Lamp --> warmup needed\n" ); dev->lastLampStatus = lampStatus; u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl ); return; } dev->warmupNeeded = SANE_FALSE; DBG( _DBG_INFO, "* Using SAME Lamp --> no warmup needed\n" ); } /** set all necessary register contents */ static void u12hw_SetGeneralRegister( U12_Device *dev ) { DBG( _DBG_INFO, "u12hw_SetGeneralRegister()\n" ); dev->scan.motorBackward = SANE_FALSE; dev->scan.refreshState = SANE_FALSE; if( COLOR_BW == dev->DataInf.wPhyDataType ) dev->regs.RD_ScanControl = _SCAN_BITMODE; else { if( dev->DataInf.wPhyDataType <= COLOR_TRUE24 ) dev->regs.RD_ScanControl = _SCAN_BYTEMODE; else dev->regs.RD_ScanControl = _SCAN_12BITMODE; } u12hw_SelectLampSource( dev ); dev->regs.RD_ModelControl = (_LED_CONTROL | _LED_ACTIVITY); if( dev->shade.intermediate & _ScanMode_AverageOut ) dev->regs.RD_ModelControl |= _MODEL_DPI300; else dev->regs.RD_ModelControl |= _MODEL_DPI600; dev->regs.RD_Motor0Control = _MotorOn | _MotorHQuarterStep | _MotorPowerEnable; dev->regs.RD_ScanControl1 = _SCANSTOPONBUFFULL | _MFRC_BY_XSTEP; dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; } /** */ static void u12hw_SetupPreviewCondition( U12_Device *dev ) { int i, c; SANE_Byte rb[100]; DBG( _DBG_INFO, "u12_SetupPreviewCondition()\n" ); u12hw_SetGeneralRegister( dev ); u12io_RegisterToScanner( dev, REG_RESETMTSC ); _DODELAY(250); /* ------- Set the max. read fifo to Asic ------- */ memset( dev->scanStates, 0, _SCANSTATE_BYTES ); if( dev->DataInf.xyAppDpi.x >= 38 ) { /* 38 <= x <= 75 */ for(i = 0; i < _SCANSTATE_BYTES; i++ ) dev->scanStates[i] = 0xad; } else if( dev->DataInf.xyAppDpi.x >= 19 ) { /* 19 <= x <= 30(37) */ u_short *pState = (u_short*)dev->scanStates; for( i = 0; i < (_SCANSTATE_BYTES / 2); i++ ) pState[i] = 0x89ac; } else { /* 16 <= x <= 18 */ u_long *pState = (u_long*)dev->scanStates; for(i = 0; i < (_SCANSTATE_BYTES / 4); i++) pState[i] = 0x888889ac; } dev->regs.RD_BufFullSize = dev->DataInf.dwAppPixelsPerLine * ((dev->DataInf.xyPhyDpi.y * dev->max_y + 299) / 300) + 1; if( dev->regs.RD_BufFullSize > _SIZE_BLUEFIFO ) dev->regs.RD_BufFullSize = _SIZE_BLUEFIFO - dev->DataInf.dwAppPixelsPerLine - 1; dev->scan.dwMaxReadFifo = dev->scan.dwMinReadFifo = dev->DataInf.dwAppPixelsPerLine *2 ; if( dev->scan.dwMinReadFifo < 1024) dev->scan.dwMinReadFifo = dev->scan.dwMaxReadFifo = 1024; dev->scan.dwMaxReadFifo += (dev->DataInf.dwAsicBytesPerPlane / 2); if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) dev->scan.bFifoSelect = REG_BFIFOOFFSET; else dev->scan.bFifoSelect = REG_GFIFOOFFSET; dev->regs.RD_BufFullSize = _SIZE_BLUEFIFO; dev->regs.RD_LineControl = _LOBYTE(dev->shade.wExposure); dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure); dev->regs.RD_XStepTime = _LOBYTE(dev->shade.wXStep); dev->regs.RD_ExtXStepTime = _HIBYTE(dev->shade.wXStep); dev->regs.RD_Motor0Control = _FORWARD_MOTOR; dev->regs.RD_StepControl = _MOTOR0_SCANSTATE | _MOTOR_FREERUN; dev->regs.RD_ModeControl = _ModeScan; if( dev->DataInf.wPhyDataType == COLOR_BW ) { dev->regs.RD_ScanControl = _SCAN_BITMODE; } else if( dev->DataInf.wPhyDataType <= COLOR_TRUE24 ) dev->regs.RD_ScanControl = _SCAN_BYTEMODE; else { dev->regs.RD_ScanControl = _SCAN_12BITMODE; } dev->regs.RD_ScanControl |= _SCAN_1ST_AVERAGE; u12hw_SelectLampSource( dev ); dev->regs.RD_MotorTotalSteps = (dev->DataInf.crImage.cy * 4) + (dev->f0_8_16 ? 32 : 16) + (dev->scan.bDiscardAll ? 32 : 0); DBG( _DBG_INFO, "* RD_MotorTotalSteps = 0x%04x\n", dev->regs.RD_MotorTotalSteps); dev->regs.RD_ScanControl1 = (_MTSC_ENABLE | _SCANSTOPONBUFFULL | _MFRC_RUNSCANSTATE | _MFRC_BY_XSTEP); DBG( _DBG_INFO, "* RD_ScanControl1 = 0x%02x\n", dev->regs.RD_ScanControl1); dev->regs.RD_Dpi = dev->DataInf.xyPhyDpi.x; dev->regs.RD_Origin = (u_short)(dev->adj.leftNormal*2+_DATA_ORIGIN_X); dev->regs.RD_Origin += dev->DataInf.crImage.x; if( dev->shade.intermediate & _ScanMode_AverageOut ) dev->regs.RD_Origin >>= 1; if( dev->DataInf.wPhyDataType == COLOR_BW ) dev->regs.RD_Pixels = dev->DataInf.dwAsicBytesPerPlane; else dev->regs.RD_Pixels = dev->DataInf.dwAppPixelsPerLine; /* ------- Wait for scan state stop ------- */ u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle ); u12io_DownloadScanStates( dev ); c = 0; _SET_REG( rb, c, REG_LINECONTROL, dev->regs.RD_LineControl ); _SET_REG( rb, c, REG_EXTENDEDLINECONTROL, dev->regs.RD_ExtLineControl); _SET_REG( rb, c, REG_XSTEPTIME, dev->regs.RD_XStepTime ); _SET_REG( rb, c, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime ); _SET_REG( rb, c, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType ); _SET_REG( rb, c, REG_STEPCONTROL, dev->regs.RD_StepControl ); _SET_REG( rb, c, REG_MOTOR0CONTROL, dev->regs.RD_Motor0Control ); _SET_REG( rb, c, REG_MODELCONTROL, dev->regs.RD_ModelControl ); _SET_REG( rb, c, REG_DPILO, (_LOBYTE(dev->regs.RD_Dpi))); _SET_REG( rb, c, REG_DPIHI, (_HIBYTE(dev->regs.RD_Dpi))); _SET_REG( rb, c, REG_SCANPOSLO, (_LOBYTE(dev->regs.RD_Origin))); _SET_REG( rb, c, REG_SCANPOSHI,(_HIBYTE(dev->regs.RD_Origin))); _SET_REG( rb, c, REG_WIDTHPIXELLO,(_LOBYTE(dev->regs.RD_Pixels))); _SET_REG( rb, c, REG_WIDTHPIXELHI,(_HIBYTE(dev->regs.RD_Pixels))); _SET_REG( rb, c, REG_THRESHOLDLO, (_LOBYTE(dev->regs.RD_ThresholdControl))); _SET_REG( rb, c, REG_THRESHOLDHI, (_HIBYTE(dev->regs.RD_ThresholdControl))); _SET_REG( rb, c, REG_MOTORTOTALSTEP0, (_LOBYTE(dev->regs.RD_MotorTotalSteps))); _SET_REG( rb, c, REG_MOTORTOTALSTEP1, (_HIBYTE(dev->regs.RD_MotorTotalSteps))); _SET_REG( rb, c, REG_SCANCONTROL, dev->regs.RD_ScanControl); u12io_DataToRegs( dev, rb, c ); _DODELAY(100); u12io_RegisterToScanner( dev, REG_INITDATAFIFO ); } /** */ static void u12hw_SetupScanningCondition( U12_Device *dev ) { TimerDef timer; u_long channel; int c; SANE_Byte state; SANE_Byte rb[100]; SANE_Byte *pState; DBG( _DBG_INFO, "u12_SetupScanningCondition()\n" ); u12hw_SetGeneralRegister( dev ); u12io_RegisterToScanner( dev, REG_RESETMTSC ); _DODELAY(250); /* ------- Setup MinRead/MaxRead Fifo size ------- */ if( dev->DataInf.wPhyDataType <= COLOR_TRUE24 ) { dev->scan.dwMaxReadFifo = dev->scan.dwMinReadFifo = dev->DataInf.dwAsicBytesPerPlane * 2; } else { dev->scan.dwMaxReadFifo = dev->scan.dwMinReadFifo = dev->DataInf.dwAppPixelsPerLine << 1; } if( dev->scan.dwMinReadFifo < 1024) dev->scan.dwMinReadFifo = dev->scan.dwMaxReadFifo = 1024; dev->scan.dwMaxReadFifo += (dev->DataInf.dwAsicBytesPerPlane / 2); DBG( _DBG_INFO, "* MinReadFifo=%lu, MaxReadFifo=%lu\n", dev->scan.dwMinReadFifo, dev->scan.dwMaxReadFifo ); /* ------- Set the max. read fifo to asic ------- */ if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { dev->scan.bFifoSelect = REG_BFIFOOFFSET; if( !dev->scan.p48BitBuf.pb ) { long lRed, lGreen; lRed = (_SIZE_REDFIFO - _SIZE_BLUEFIFO) / dev->DataInf.dwAsicBytesPerPlane - dev->scan.bd_rk.wRedKeep; lGreen = (_SIZE_GREENFIFO - _SIZE_BLUEFIFO) / dev->DataInf.dwAsicBytesPerPlane - dev->scan.gd_gk.wGreenKeep; if((lRed < 0) || (lGreen < 0)) { if( lRed < lGreen ) { channel = _RED_FULLSIZE << 16; dev->regs.RD_BufFullSize = _SIZE_REDFIFO; lGreen = lRed; } else { channel = _GREEN_FULLSIZE << 16; dev->regs.RD_BufFullSize = _SIZE_GREENFIFO; } lGreen = (u_long)(-lGreen * dev->DataInf.dwAsicBytesPerPlane); if( dev->DataInf.wPhyDataType > COLOR_TRUE24 ) lGreen >>= 1; dev->scan.dwMinReadFifo += (u_long)lGreen; dev->scan.dwMaxReadFifo += (u_long)lGreen; } else { channel = _BLUE_FULLSIZE << 16; dev->regs.RD_BufFullSize = _SIZE_BLUEFIFO; } } else { channel = _BLUE_FULLSIZE << 16; dev->regs.RD_BufFullSize = _SIZE_BLUEFIFO; } } else { dev->scan.bFifoSelect = REG_GFIFOOFFSET; channel = _GREEN_FULLSIZE << 16; dev->regs.RD_BufFullSize = _SIZE_GRAYFIFO; } dev->regs.RD_BufFullSize -= (dev->DataInf.dwAsicBytesPerPlane << 1); if( dev->DataInf.wPhyDataType > COLOR_TRUE24 ) dev->regs.RD_BufFullSize >>= 1; dev->regs.RD_BufFullSize |= channel; dev->scan.bRefresh = (SANE_Byte)(dev->scan.dwInterval << 1); dev->regs.RD_LineControl = _LOBYTE(dev->shade.wExposure); dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure); dev->regs.RD_XStepTime = _LOBYTE(dev->shade.wXStep); dev->regs.RD_ExtXStepTime = _HIBYTE(dev->shade.wXStep); dev->regs.RD_Motor0Control = _FORWARD_MOTOR; dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; dev->regs.RD_ModeControl = _ModeScan/*(_ModeScan | _ModeFifoGSel)*/; DBG( _DBG_INFO, "* bRefresh = %i\n", dev->scan.bRefresh ); if( dev->DataInf.wPhyDataType == COLOR_BW ) { dev->regs.RD_ScanControl = _SCAN_BITMODE; } else if( dev->DataInf.wPhyDataType <= COLOR_TRUE24 ) dev->regs.RD_ScanControl = _SCAN_BYTEMODE; else { dev->regs.RD_ScanControl = _SCAN_12BITMODE; } dev->regs.RD_ScanControl |= _SCAN_1ST_AVERAGE; u12hw_SelectLampSource( dev ); DBG( _DBG_INFO, "* RD_ScanControl = 0x%02x\n", dev->regs.RD_ScanControl ); DBG( _DBG_INFO, "* ImageInfo: x=%u,y=%u,dx=%u,dy=%u\n", dev->DataInf.crImage.x, dev->DataInf.crImage.y, dev->DataInf.crImage.cx, dev->DataInf.crImage.cy ); dev->regs.RD_MotorTotalSteps = (dev->DataInf.crImage.cy * 4) + (dev->f0_8_16 ? 32 : 16) + (dev->scan.bDiscardAll ? 32 : 0); DBG( _DBG_INFO, "* RD_MotorTotalSteps = 0x%04x\n", dev->regs.RD_MotorTotalSteps); dev->regs.RD_ScanControl1 = (_MTSC_ENABLE | _SCANSTOPONBUFFULL | _MFRC_RUNSCANSTATE | _MFRC_BY_XSTEP); DBG( _DBG_INFO, "* RD_ScanControl1 = 0x%02x\n", dev->regs.RD_ScanControl1); dev->regs.RD_Dpi = dev->DataInf.xyPhyDpi.x; if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA )) { dev->regs.RD_Origin = (u_short)(dev->adj.leftNormal*2+_DATA_ORIGIN_X); } else if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency ) { dev->regs.RD_Origin = (u_short)dev->scan.posBegin; } else { dev->regs.RD_Origin = (u_short)dev->scan.negBegin; } dev->regs.RD_Origin += dev->DataInf.crImage.x; if( dev->shade.intermediate & _ScanMode_AverageOut ) dev->regs.RD_Origin >>= 1; if( dev->DataInf.wPhyDataType == COLOR_BW ) dev->regs.RD_Pixels = (u_short)dev->DataInf.dwAsicBytesPerPlane; else dev->regs.RD_Pixels = (u_short)dev->DataInf.dwAppPixelsPerLine; DBG( _DBG_INFO, "* RD_Origin = %u, RD_Pixels = %u\n", dev->regs.RD_Origin, dev->regs.RD_Pixels ); /* ------- Prepare scan states ------- */ memset( dev->scanStates, 0, _SCANSTATE_BYTES ); memset( dev->bufs.b1.pReadBuf, 0, _NUMBER_OF_SCANSTEPS ); if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) state = (_SS_MONO | _SS_STEP); else state = (_SS_COLOR | _SS_STEP); for( channel = _NUMBER_OF_SCANSTEPS, pState = dev->bufs.b1.pReadBuf; channel; channel -= dev->scan.dwInterval ) { *pState = state; pState += dev->scan.dwInterval; } for( channel = 0, pState = dev->bufs.b1.pReadBuf; channel < _SCANSTATE_BYTES; channel++) { dev->scanStates[channel] = pState[0] | (pState[1] << 4); pState += 2; } /* ------- Wait for scan state stop ------- */ u12io_StartTimer( &timer, _SECOND * 2 ); u12io_ResetFifoLen(); while(!(u12io_GetScanState( dev ) & _SCANSTATE_STOP) && !u12io_CheckTimer(&timer)); u12io_DownloadScanStates( dev ); c = 0; _SET_REG( rb, c, REG_LINECONTROL, dev->regs.RD_LineControl ); _SET_REG( rb, c, REG_EXTENDEDLINECONTROL, dev->regs.RD_ExtLineControl); _SET_REG( rb, c, REG_XSTEPTIME, dev->regs.RD_XStepTime ); _SET_REG( rb, c, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime ); _SET_REG( rb, c, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType ); _SET_REG( rb, c, REG_STEPCONTROL, dev->regs.RD_StepControl ); _SET_REG( rb, c, REG_MOTOR0CONTROL, dev->regs.RD_Motor0Control ); _SET_REG( rb, c, REG_MODELCONTROL, dev->regs.RD_ModelControl ); _SET_REG( rb, c, REG_DPILO, (_LOBYTE(dev->regs.RD_Dpi))); _SET_REG( rb, c, REG_DPIHI, (_HIBYTE(dev->regs.RD_Dpi))); _SET_REG( rb, c, REG_SCANPOSLO, (_LOBYTE(dev->regs.RD_Origin))); _SET_REG( rb, c, REG_SCANPOSHI,(_HIBYTE(dev->regs.RD_Origin))); _SET_REG( rb, c, REG_WIDTHPIXELLO,(_LOBYTE(dev->regs.RD_Pixels))); _SET_REG( rb, c, REG_WIDTHPIXELHI,(_HIBYTE(dev->regs.RD_Pixels))); _SET_REG( rb, c, REG_THRESHOLDLO, (_LOBYTE(dev->regs.RD_ThresholdControl))); _SET_REG( rb, c, REG_THRESHOLDHI, (_HIBYTE(dev->regs.RD_ThresholdControl))); _SET_REG( rb, c, REG_MOTORTOTALSTEP0, (_LOBYTE(dev->regs.RD_MotorTotalSteps))); _SET_REG( rb, c, REG_MOTORTOTALSTEP1, (_HIBYTE(dev->regs.RD_MotorTotalSteps))); _SET_REG( rb, c, REG_SCANCONTROL, dev->regs.RD_ScanControl); u12io_DataToRegs( dev, rb, c ); _DODELAY(100); u12io_RegisterToScanner( dev, REG_INITDATAFIFO ); } /** */ static SANE_Status u12hw_Memtest( U12_Device *dev ) { SANE_Byte tmp; SANE_Byte buf[_TEST_SIZE]; int i; DBG( _DBG_INFO, "u12hw_Memtest()\n" ); /* prepare buffer */ for( i = 0; i < _TEST_SIZE; i++ ) { buf[i] = (SANE_Byte)((i * 3) & 0xff); } /* avoid switching to Lamp0, when previously scanned in transp./neg mode */ tmp = dev->lastLampStatus + _SCAN_BYTEMODE; u12io_DataToRegister( dev, REG_SCANCONTROL, tmp ); u12io_DataToRegister( dev, REG_MODECONTROL, _ModeMappingMem ); u12io_DataToRegister( dev, REG_MEMORYLO, 0 ); u12io_DataToRegister( dev, REG_MEMORYHI, 0 ); /* fill to buffer */ u12io_MoveDataToScanner( dev, buf, _TEST_SIZE ); u12io_DataToRegister( dev, REG_MODECONTROL, _ModeMappingMem ); u12io_DataToRegister( dev, REG_MEMORYLO, 0 ); u12io_DataToRegister( dev, REG_MEMORYHI, 0 ); u12io_DataToRegister( dev, REG_WIDTHPIXELLO, 0 ); u12io_DataToRegister( dev, REG_WIDTHPIXELHI, 5 ); memset( buf, 0, _TEST_SIZE ); dev->regs.RD_ModeControl = _ModeReadMappingMem; u12io_ReadData( dev, buf, _TEST_SIZE ); for( i = 0; i < _TEST_SIZE; i++ ) { if((SANE_Byte)((i * 3) & 0xff) != buf[i] ) { DBG( _DBG_ERROR, "* Memtest failed at pos %u: %u != %u\n", i+1, buf[i], (SANE_Byte)((i * 3) & 0xff) ); return SANE_STATUS_INVAL; } } DBG( _DBG_INFO, "* Memtest passed.\n" ); return SANE_STATUS_GOOD; } /** check if ASIC can be accessed, if the version is supported and the memory * is also accessible... */ static SANE_Status u12hw_CheckDevice( U12_Device *dev ) { #ifndef _FAKE_DEVICE SANE_Byte tmp; SANE_Byte rb[8]; int c; #if 1 if( !u12io_IsConnected( dev )) { if( !u12io_OpenScanPath( dev )) return SANE_STATUS_IO_ERROR; } #else /* u12io_IsConnected( dev ); */ if( !u12io_OpenScanPath( dev )) return SANE_STATUS_IO_ERROR; #endif /* some setup stuff... */ tmp = u12io_GetExtendedStatus( dev ); DBG( _DBG_INFO, "* REG_STATUS2 = 0x%02x\n", tmp ); if( tmp & _REFLECTIONLAMP_ON ) { DBG( _DBG_INFO, "* Normal lamp is ON\n" ); dev->lastLampStatus = _SCAN_NORMALLAMP_ON; } else if( tmp & _TPALAMP_ON ) { dev->lastLampStatus = _SCAN_TPALAMP_ON; DBG( _DBG_INFO, "* TPA lamp is ON\n" ); } c = 0; _SET_REG( rb, c, REG_PLLPREDIV, 1 ); _SET_REG( rb, c, REG_PLLMAINDIV, 0x20 ); _SET_REG( rb, c, REG_PLLPOSTDIV, 2 ); _SET_REG( rb, c, REG_CLOCKSELECTOR, 2 ); u12io_DataToRegs( dev, rb, c ); #if 0 return u12hw_Memtest( dev ); #else if( !dev->initialized ) return u12hw_Memtest( dev ); else return SANE_STATUS_GOOD; #endif #else _VAR_NOT_USED( dev ); return SANE_STATUS_GOOD; #endif } /* prototypes... */ static void u12motor_PositionModuleToHome( U12_Device *); static void u12motor_ToHomePosition( U12_Device *, SANE_Bool ); /** */ static void u12hw_CancelSequence( U12_Device *dev ) { int c = 0; SANE_Byte rb[6]; DBG( _DBG_INFO, "u12hw_CancelSequence()\n" ); u12motor_PositionModuleToHome( dev ); u12motor_ToHomePosition( dev, SANE_TRUE ); u12io_DataToRegister( dev, REG_MOTOR0CONTROL, 0 ); u12io_DataToRegister( dev, REG_MODELCONTROL, 0x1a ); u12hw_PutToIdleMode( dev ); if( strcmp( dev->usbId, "0x0458-0x2004" )) u12io_SoftwareReset( dev ); u12motor_PositionModuleToHome( dev ); u12io_DataToRegister( dev, REG_SCANCONTROL, 0x05 ); u12io_DataToRegister( dev, REG_MODELCONTROL, 0x1f ); u12hw_PutToIdleMode( dev ); u12io_DataToRegister( dev, REG_MODELCONTROL, 0x00 ); u12io_DataToRegister( dev, REG_ADCADDR, 0x01 ); u12io_DataToRegister( dev, REG_ADCDATA, 0x00 ); u12io_DataToRegister( dev, REG_ADCSERIALOUT, 0x00 ); _SET_REG( rb, c, REG_MODECONTROL, 0x19 ); _SET_REG( rb, c, REG_STEPCONTROL, 0xff ); _SET_REG( rb, c, REG_MOTOR0CONTROL, 0 ); u12io_DataToRegs( dev, rb, c ); u12io_CloseScanPath( dev ); } /** */ static SANE_Status u12hw_WarmupLamp( U12_Device *dev ) { TimerDef timer; DBG( _DBG_INFO, "u12hw_WarmupLamp()\n" ); if( dev->warmupNeeded ) { DBG( _DBG_INFO, "* warming up...\n" ); u12io_StartTimer( &timer, _SECOND * dev->adj.warmup ); while( !u12io_CheckTimer( &timer )) { if( u12io_IsEscPressed()) { DBG( _DBG_INFO, "* CANCEL detected!\n" ); return SANE_STATUS_CANCELLED; } } } else { DBG( _DBG_INFO, "* skipped\n" ); } return SANE_STATUS_GOOD; } /* FIXME: replace!!! */ static U12_Device *dev_xxx = NULL; /** ISR to switch lamp off after time has elapsed */ static void usb_LampTimerIrq( int sig ) { SANE_Byte tmp; int handle = -1; if( NULL == dev_xxx ) return; _VAR_NOT_USED( sig ); DBG( _DBG_INFO, "*** LAMP OFF!!! ***\n" ); if( -1 == dev_xxx->fd ) { if( SANE_STATUS_GOOD == sanei_usb_open(dev_xxx->sane.name, &handle)) { dev_xxx->fd = handle; } } if( -1 != dev_xxx->fd ) { if( !u12io_IsConnected( dev_xxx )) { if( u12io_OpenScanPath( dev_xxx )) { /* some setup stuff... */ tmp = u12io_GetExtendedStatus( dev_xxx ); if( tmp & _REFLECTIONLAMP_ON ) { DBG( _DBG_INFO, "* Normal lamp is ON\n" ); } else if( tmp & _TPALAMP_ON ) { DBG( _DBG_INFO, "* TPA lamp is ON\n" ); } u12io_DataToRegister( dev_xxx, REG_SCANCONTROL, 0 ); u12io_CloseScanPath( dev_xxx ); } } } if( -1 != handle ) { dev_xxx->fd = -1; sanei_usb_close( handle ); } } /** */ static void u12hw_StartLampTimer( U12_Device *dev ) { sigset_t block, pause_mask; struct sigaction s; #ifdef HAVE_SETITIMER struct itimerval interval; #endif /* block SIGALRM */ sigemptyset( &block ); sigaddset ( &block, SIGALRM ); sigprocmask( SIG_BLOCK, &block, &pause_mask ); /* setup handler */ sigemptyset( &s.sa_mask ); sigaddset ( &s.sa_mask, SIGALRM ); s.sa_flags = 0; s.sa_handler = usb_LampTimerIrq; if( sigaction( SIGALRM, &s, NULL ) < 0 ) DBG( _DBG_ERROR, "Can't setup timer-irq handler\n" ); sigprocmask( SIG_UNBLOCK, &block, &pause_mask ); #ifdef HAVE_SETITIMER /* * define a one-shot timer */ interval.it_value.tv_usec = 0; interval.it_value.tv_sec = dev->adj.lampOff; interval.it_interval.tv_usec = 0; interval.it_interval.tv_sec = 0; if( 0 != dev->adj.lampOff ) { dev_xxx = dev; setitimer( ITIMER_REAL, &interval, &dev->saveSettings ); DBG( _DBG_INFO, "Lamp-Timer started (using ITIMER)\n" ); } #else if( 0 != dev->adj.lampOff ) { dev_xxx = dev; alarm( dev->adj.lampOff ); DBG( _DBG_INFO, "Lamp-Timer started (using ALARM)\n" ); } #endif } /** */ static void u12hw_StopLampTimer( U12_Device *dev ) { sigset_t block, pause_mask; /* block SIGALRM */ sigemptyset( &block ); sigaddset ( &block, SIGALRM ); sigprocmask( SIG_BLOCK, &block, &pause_mask ); dev_xxx = NULL; #ifdef HAVE_SETITIMER if( 0 != dev->adj.lampOff ) setitimer( ITIMER_REAL, &dev->saveSettings, NULL ); #else _VAR_NOT_USED( dev ); alarm( 0 ); #endif DBG( _DBG_INFO, "Lamp-Timer stopped\n" ); } /* END U12-HW.C .............................................................*/ sane-backends-1.0.27/backend/epson2_scsi.c0000664000175000017500000000403312775312261015212 00000000000000#undef BACKEND_NAME #define BACKEND_NAME epson2_scsi #include "../include/sane/config.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_scsi.h" #include "epson2_scsi.h" #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include /* for memset and memcpy */ #include /* sense handler for the sanei_scsi_xxx comands */ SANE_Status sanei_epson2_scsi_sense_handler(int scsi_fd, unsigned char *result, void *arg) { /* to get rid of warnings */ scsi_fd = scsi_fd; arg = arg; if (result[0] && result[0] != 0x70) { DBG(2, "%s: sense code = 0x%02x\n", __func__, result[0]); return SANE_STATUS_IO_ERROR; } else { return SANE_STATUS_GOOD; } } SANE_Status sanei_epson2_scsi_inquiry(int fd, void *buf, size_t *buf_size) { unsigned char cmd[6]; int status; memset(cmd, 0, 6); cmd[0] = INQUIRY_COMMAND; cmd[4] = *buf_size > 255 ? 255 : *buf_size; status = sanei_scsi_cmd(fd, cmd, sizeof cmd, buf, buf_size); return status; } SANE_Status sanei_epson2_scsi_test_unit_ready(int fd) { unsigned char cmd[6]; memset(cmd, 0, 6); cmd[0] = TEST_UNIT_READY_COMMAND; return sanei_scsi_cmd2(fd, cmd, sizeof(cmd), NULL, 0, NULL, NULL); } int sanei_epson2_scsi_read(int fd, void *buf, size_t buf_size, SANE_Status *status) { unsigned char cmd[6]; memset(cmd, 0, 6); cmd[0] = READ_6_COMMAND; cmd[2] = buf_size >> 16; cmd[3] = buf_size >> 8; cmd[4] = buf_size; *status = sanei_scsi_cmd2(fd, cmd, sizeof(cmd), NULL, 0, buf, &buf_size); if (*status == SANE_STATUS_GOOD) return buf_size; return 0; } int sanei_epson2_scsi_write(int fd, const void *buf, size_t buf_size, SANE_Status *status) { unsigned char cmd[6]; memset(cmd, 0, sizeof(cmd)); cmd[0] = WRITE_6_COMMAND; cmd[2] = buf_size >> 16; cmd[3] = buf_size >> 8; cmd[4] = buf_size; *status = sanei_scsi_cmd2(fd, cmd, sizeof(cmd), buf, buf_size, NULL, NULL); if (*status == SANE_STATUS_GOOD) return buf_size; return 0; } sane-backends-1.0.27/backend/kvs1025.c0000664000175000017500000002436212617742237014112 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. Copyright (C) 2010-2011, m. allan noah */ /* sane - Scanner Access Now Easy. Panasonic KV-S1020C / KV-S1025C USB scanners. */ #define DEBUG_NOT_STATIC #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "kvs1025.h" #include "kvs1025_low.h" #include "../include/sane/sanei_debug.h" /* SANE backend operations, see Sane standard 1.04 documents (sane_dev.pdf) for details */ /* Init the KV-S1025 SANE backend. This function must be called before any other SANE function can be called. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { SANE_Status status; DBG_INIT (); DBG (DBG_sane_init, "sane_init\n"); DBG (DBG_error, "This is panasonic KV-S1020C / KV-S1025C version %d.%d build %d\n", V_MAJOR, V_MINOR, V_BUILD); if (version_code) { *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, V_BUILD); } /* Initialize USB */ sanei_usb_init (); status = kv_enum_devices (); if (status) return status; DBG (DBG_proc, "sane_init: leave\n"); return SANE_STATUS_GOOD; } /* Terminate the KV-S1025 SANE backend */ void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); kv_exit (); DBG (DBG_proc, "sane_exit: exit\n"); } /* Get device list */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { DBG (DBG_proc, "sane_get_devices: enter\n"); kv_get_devices_list (device_list); DBG (DBG_proc, "sane_get_devices: leave\n"); return SANE_STATUS_GOOD; } /* Open device, return the device handle */ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { return kv_open_by_name (devicename, handle); } /* Close device */ void sane_close (SANE_Handle handle) { DBG (DBG_proc, "sane_close: enter\n"); kv_close ((PKV_DEV) handle); DBG (DBG_proc, "sane_close: leave\n"); } /* Get option descriptor */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { return kv_get_option_descriptor ((PKV_DEV) handle, option); } /* Control option */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { return kv_control_option ((PKV_DEV) handle, option, action, val, info); } /* Get scan parameters */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { PKV_DEV dev = (PKV_DEV) handle; int side = dev->current_side == SIDE_FRONT ? 0 : 1; DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { /* Setup the parameters for the scan. (guessed value) */ int resolution = dev->val[OPT_RESOLUTION].w; int width, length, depth = kv_get_depth (kv_get_mode (dev));; DBG (DBG_proc, "sane_get_parameters: initial settings\n"); kv_calc_paper_size (dev, &width, &length); DBG (DBG_error, "Resolution = %d\n", resolution); DBG (DBG_error, "Paper width = %d, height = %d\n", width, length); /* Prepare the parameters for the caller. */ dev->params[0].format = kv_get_mode (dev) == SM_COLOR ? SANE_FRAME_RGB : SANE_FRAME_GRAY; dev->params[0].last_frame = SANE_TRUE; dev->params[0].pixels_per_line = ((width * resolution) / 1200) & (~0xf); dev->params[0].depth = depth > 8 ? 8 : depth; dev->params[0].bytes_per_line = (dev->params[0].pixels_per_line / 8) * depth; dev->params[0].lines = (length * resolution) / 1200; memcpy (&dev->params[1], &dev->params[0], sizeof (SANE_Parameters)); } /* Return the current values. */ if (params) *params = (dev->params[side]); DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } /* Start scanning */ SANE_Status sane_start (SANE_Handle handle) { SANE_Status status; PKV_DEV dev = (PKV_DEV) handle; SANE_Bool dev_ready; KV_CMD_RESPONSE rs; DBG (DBG_proc, "sane_start: enter\n"); if (!dev->scanning) { /* open device */ if (!kv_already_open (dev)) { DBG (DBG_proc, "sane_start: need to open device\n"); status = kv_open (dev); if (status) { return status; } } /* Begin scan */ DBG (DBG_proc, "sane_start: begin scan\n"); /* Get necessary parameters */ sane_get_parameters (dev, NULL); dev->current_page = 0; dev->current_side = SIDE_FRONT; /* The scanner must be ready. */ status = CMD_test_unit_ready (dev, &dev_ready); if (status || !dev_ready) { return SANE_STATUS_DEVICE_BUSY; } if (!strcmp (dev->val[OPT_MANUALFEED].s, "off")) { status = CMD_get_document_existanse (dev); if (status) { DBG (DBG_proc, "sane_start: exit with no more docs\n"); return status; } } /* Set window */ status = CMD_reset_window (dev); if (status) { return status; } status = CMD_set_window (dev, SIDE_FRONT, &rs); if (status) { DBG (DBG_proc, "sane_start: error setting window\n"); return status; } if (rs.status) { DBG (DBG_proc, "sane_start: error setting window\n"); DBG (DBG_proc, "sane_start: sense_key=0x%x, ASC=0x%x, ASCQ=0x%x\n", get_RS_sense_key (rs.sense), get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense)); return SANE_STATUS_DEVICE_BUSY; } if (IS_DUPLEX (dev)) { status = CMD_set_window (dev, SIDE_BACK, &rs); if (status) { DBG (DBG_proc, "sane_start: error setting window\n"); return status; } if (rs.status) { DBG (DBG_proc, "sane_start: error setting window\n"); DBG (DBG_proc, "sane_start: sense_key=0x%x, " "ASC=0x%x, ASCQ=0x%x\n", get_RS_sense_key (rs.sense), get_RS_ASC (rs.sense), get_RS_ASCQ (rs.sense)); return SANE_STATUS_INVAL; } } /* Scan */ status = CMD_scan (dev); if (status) { return status; } status = AllocateImageBuffer (dev); if (status) { return status; } dev->scanning = 1; } else { /* renew page */ if (IS_DUPLEX (dev)) { if (dev->current_side == SIDE_FRONT) { /* back image data already read, so just return */ dev->current_side = SIDE_BACK; DBG (DBG_proc, "sane_start: duplex back\n"); status = SANE_STATUS_GOOD; goto cleanup; } else { dev->current_side = SIDE_FRONT; dev->current_page++; } } else { dev->current_page++; } } DBG (DBG_proc, "sane_start: NOW SCANNING page\n"); /* Read image data */ status = ReadImageData (dev, dev->current_page); if (status) { dev->scanning = 0; return status; } /* Get picture element size */ { int width, height; status = CMD_read_pic_elements (dev, dev->current_page, SIDE_FRONT, &width, &height); if (status) return status; } if (IS_DUPLEX (dev)) { int width, height; status = CMD_read_pic_elements (dev, dev->current_page, SIDE_BACK, &width, &height); if (status) return status; } /* software based enhancement functions from sanei_magic */ /* these will modify the image, and adjust the params */ /* at this point, we are only looking at the front image */ /* of simplex or duplex data, back side has already exited */ /* so, we do both sides now, if required */ if (dev->val[OPT_SWDESKEW].w){ buffer_deskew(dev,SIDE_FRONT); } if (dev->val[OPT_SWCROP].w){ buffer_crop(dev,SIDE_FRONT); } if (dev->val[OPT_SWDESPECK].w){ buffer_despeck(dev,SIDE_FRONT); } if (dev->val[OPT_SWDEROTATE].w || dev->val[OPT_ROTATE].w){ buffer_rotate(dev,SIDE_FRONT); } if (IS_DUPLEX (dev)){ if (dev->val[OPT_SWDESKEW].w){ buffer_deskew(dev,SIDE_BACK); } if (dev->val[OPT_SWCROP].w){ buffer_crop(dev,SIDE_BACK); } if (dev->val[OPT_SWDESPECK].w){ buffer_despeck(dev,SIDE_BACK); } if (dev->val[OPT_SWDEROTATE].w || dev->val[OPT_ROTATE].w){ buffer_rotate(dev,SIDE_BACK); } } cleanup: /* check if we need to skip this page */ if (dev->val[OPT_SWSKIP].w && buffer_isblank(dev,dev->current_side)){ DBG (DBG_proc, "sane_start: blank page, recurse\n"); return sane_start(handle); } DBG (DBG_proc, "sane_start: exit\n"); return status; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { PKV_DEV dev = (PKV_DEV) handle; int side = dev->current_side == SIDE_FRONT ? 0 : 1; int size = max_len; if (!dev->scanning) return SANE_STATUS_EOF; if (size > dev->img_size[side]) size = dev->img_size[side]; if (size == 0) { *len = size; return SANE_STATUS_EOF; } if (dev->val[OPT_INVERSE].w && (kv_get_mode (dev) == SM_BINARY || kv_get_mode (dev) == SM_DITHER)) { int i; unsigned char *p = dev->img_pt[side]; for (i = 0; i < size; i++) { buf[i] = ~p[i]; } } else { memcpy (buf, dev->img_pt[side], size); } /*hexdump(DBG_error, "img data", buf, 128); */ dev->img_pt[side] += size; dev->img_size[side] -= size; DBG (DBG_proc, "sane_read: %d bytes to read, " "%d bytes read, EOF=%s %d\n", max_len, size, dev->img_size[side] == 0 ? "True" : "False", side); if (len) { *len = size; } if (dev->img_size[side] == 0) { if (!strcmp (dev->val[OPT_FEEDER_MODE].s, "single")) if ((IS_DUPLEX (dev) && side) || !IS_DUPLEX (dev)) dev->scanning = 0; } return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { PKV_DEV dev = (PKV_DEV) handle; DBG (DBG_proc, "sane_cancel: scan canceled.\n"); dev->scanning = 0; kv_close (dev); } SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool m) { h=h; m=m; return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fd) { h=h; fd=fd; return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/artec.c0000664000175000017500000031052412775312260014065 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Artec/Ultima scanners. Copyright (C) 1998-2000 Chris Pinkham Released under the terms of the GPL. *NO WARRANTY* Portions contributed by: David Leadbetter - A6000C (3-pass) Dick Bruijn - AT12 ********************************************************************* For feedback/information: cpinkham@corp.infi.net http://www4.infi.net/~cpinkham/sane/sane-artec-doc.html ********************************************************************* */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include #define BACKEND_NAME artec #define ARTEC_MAJOR 0 #define ARTEC_MINOR 5 #define ARTEC_SUB 16 #define ARTEC_LAST_MOD "05/26/2001 17:28 EST" #ifndef PATH_MAX #define PATH_MAX 1024 #endif #define ARTEC_CONFIG_FILE "artec.conf" #define ARTEC_MAX_READ_SIZE 32768 static int num_devices; static const SANE_Device **devlist = 0; static ARTEC_Device *first_dev; static ARTEC_Scanner *first_handle; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static const SANE_String_Const filter_type_list[] = { "Mono", "Red", "Green", "Blue", 0 }; static const SANE_String_Const halftone_pattern_list[] = { "User defined (unsupported)", "4x4 Spiral", "4x4 Bayer", "8x8 Spiral", "8x8 Bayer", 0 }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; #define INQ_LEN 0x60 static const uint8_t inquiry[] = { 0x12, 0x00, 0x00, 0x00, INQ_LEN, 0x00 }; static const uint8_t test_unit_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static struct { SANE_String model; /* product model */ SANE_String type; /* type of scanner */ double width; /* width in inches */ double height; /* height in inches */ SANE_Word adc_bits; /* Analog-to-Digital Converter Bits */ SANE_Word setwindow_cmd_size; /* Set-Window command size */ SANE_Word max_read_size; /* Max Read size in bytes */ long flags; /* flags */ SANE_String horz_resolution_str; /* Horizontal resolution list */ SANE_String vert_resolution_str; /* Vertical resolution list */ } cap_data[] = { { "AT3", "flatbed", 8.3, 11, 8, 55, 32768, ARTEC_FLAG_CALIBRATE_RGB | ARTEC_FLAG_RGB_LINE_OFFSET | ARTEC_FLAG_RGB_CHAR_SHIFT | ARTEC_FLAG_OPT_CONTRAST | ARTEC_FLAG_GAMMA_SINGLE | ARTEC_FLAG_SEPARATE_RES | ARTEC_FLAG_SENSE_HANDLER | ARTEC_FLAG_SENSE_BYTE_19 | ARTEC_FLAG_ADF | ARTEC_FLAG_HALFTONE_PATTERN | ARTEC_FLAG_MBPP_NEGATIVE | ARTEC_FLAG_ONE_PASS_SCANNER, "50,100,200,300", "50,100,200,300,600" } , { "A6000C", "flatbed", 8.3, 14, 8, 55, 8192, /* some have reported that Calibration does not work the same as AT3 & A6000C+ ARTEC_FLAG_CALIBRATE_RGB | */ ARTEC_FLAG_OPT_CONTRAST | ARTEC_FLAG_OPT_BRIGHTNESS | ARTEC_FLAG_SEPARATE_RES | ARTEC_FLAG_SENSE_HANDLER | ARTEC_FLAG_ADF | ARTEC_FLAG_HALFTONE_PATTERN, "50,100,200,300", "50,100,200,300,600" } , { "A6000C PLUS", "flatbed", 8.3, 14, 8, 55, 8192, ARTEC_FLAG_CALIBRATE_RGB | ARTEC_FLAG_RGB_LINE_OFFSET | ARTEC_FLAG_RGB_CHAR_SHIFT | ARTEC_FLAG_OPT_CONTRAST | ARTEC_FLAG_GAMMA_SINGLE | ARTEC_FLAG_SEPARATE_RES | ARTEC_FLAG_SENSE_HANDLER | ARTEC_FLAG_SENSE_BYTE_19 | ARTEC_FLAG_ADF | ARTEC_FLAG_HALFTONE_PATTERN | ARTEC_FLAG_MBPP_NEGATIVE | ARTEC_FLAG_ONE_PASS_SCANNER, "50,100,200,300", "50,100,200,300,600" } , { "AT6", "flatbed", 8.3, 11, 10, 55, 32768, ARTEC_FLAG_CALIBRATE_RGB | ARTEC_FLAG_RGB_LINE_OFFSET | ARTEC_FLAG_RGB_CHAR_SHIFT | ARTEC_FLAG_OPT_CONTRAST | /* gamma not working totally correct yet. ARTEC_FLAG_GAMMA_SINGLE | */ ARTEC_FLAG_SEPARATE_RES | ARTEC_FLAG_SENSE_HANDLER | ARTEC_FLAG_ADF | ARTEC_FLAG_HALFTONE_PATTERN | ARTEC_FLAG_MBPP_NEGATIVE | ARTEC_FLAG_ONE_PASS_SCANNER, "50,100,200,300", "50,100,200,300,600" } , { "AT12", "flatbed", 8.5, 11, 12, 67, 32768, /* calibration works slower so disabled ARTEC_CALIBRATE_DARK_WHITE | */ /* gamma not working totally correct yet. ARTEC_FLAG_GAMMA | */ ARTEC_FLAG_OPT_CONTRAST | ARTEC_FLAG_SEPARATE_RES | ARTEC_FLAG_SENSE_HANDLER | ARTEC_FLAG_SENSE_ENH_18 | ARTEC_FLAG_SENSE_BYTE_22 | ARTEC_FLAG_SC_BUFFERS_LINES | ARTEC_FLAG_SC_HANDLES_OFFSET | ARTEC_FLAG_PIXEL_AVERAGING | ARTEC_FLAG_ENHANCE_LINE_EDGE | ARTEC_FLAG_ADF | ARTEC_FLAG_HALFTONE_PATTERN | ARTEC_FLAG_MBPP_NEGATIVE | ARTEC_FLAG_ONE_PASS_SCANNER, "25,50,100,200,300,400,500,600", "25,50,100,200,300,400,500,600,700,800,900,1000,1100,1200" } , { "AM12S", "flatbed", 8.26, 11.7, 12, 67, ARTEC_MAX_READ_SIZE, /* calibration works slower so disabled ARTEC_CALIBRATE_DARK_WHITE | */ /* gamma not working totally correct yet. ARTEC_FLAG_GAMMA | */ ARTEC_FLAG_RGB_LINE_OFFSET | ARTEC_FLAG_SEPARATE_RES | ARTEC_FLAG_IMAGE_REV_LR | ARTEC_FLAG_REVERSE_WINDOW | ARTEC_FLAG_SENSE_HANDLER | ARTEC_FLAG_SENSE_ENH_18 | ARTEC_FLAG_MBPP_NEGATIVE | ARTEC_FLAG_ONE_PASS_SCANNER, "50,100,300,600", "50,100,300,600,1200" } , }; /* store vendor and model if hardcoded in artec.conf */ static char artec_vendor[9] = ""; static char artec_model[17] = ""; /* file descriptor for debug data output */ static int debug_fd = -1; static char *artec_skip_whitespace (char *str) { while (isspace (*str)) ++str; return str; } static SANE_Status artec_str_list_to_word_list (SANE_Word ** word_list_ptr, SANE_String str) { SANE_Word *word_list; char *start; char *end; char temp_str[1024]; int comma_count = 1; if ((str == NULL) || (strlen (str) == 0)) { /* alloc space for word which stores length (0 in this case) */ word_list = (SANE_Word *) malloc (sizeof (SANE_Word)); if (word_list == NULL) return (SANE_STATUS_NO_MEM); word_list[0] = 0; *word_list_ptr = word_list; return (SANE_STATUS_GOOD); } /* make temp copy of input string (only hold 1024 for now) */ strncpy (temp_str, str, 1023); temp_str[1023] = '\0'; end = strchr (temp_str, ','); while (end != NULL) { comma_count++; start = end + 1; end = strchr (start, ','); } word_list = (SANE_Word *) calloc (comma_count + 1, sizeof (SANE_Word)); if (word_list == NULL) return (SANE_STATUS_NO_MEM); word_list[0] = comma_count; comma_count = 1; start = temp_str; end = strchr (temp_str, ','); while (end != NULL) { *end = '\0'; word_list[comma_count] = atol (start); start = end + 1; comma_count++; end = strchr (start, ','); } word_list[comma_count] = atol (start); *word_list_ptr = word_list; return (SANE_STATUS_GOOD); } static size_t artec_get_str_index (const SANE_String_Const strings[], char *str) { size_t index; index = 0; while ((strings[index]) && strcmp (strings[index], str)) { index++; } if (!strings[index]) { index = 0; } return (index); } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return (max_size); } /* DB added a sense handler */ /* last argument is expected to be a pointer to a Artec_Scanner structure */ static SANE_Status sense_handler (int fd, u_char * sense, void *arg) { ARTEC_Scanner *s = (ARTEC_Scanner *)arg; int err; err = 0; DBG(2, "sense fd: %d, data: %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", fd, sense[0], sense[1], sense[2], sense[3], sense[4], sense[5], sense[6], sense[7], sense[8], sense[9], sense[10], sense[11], sense[12], sense[13], sense[14], sense[15]); /* byte 18 info pertaining to ADF */ if ((s) && (s->hw->flags & ARTEC_FLAG_ADF)) { if (sense[18] & 0x01) { DBG (2, "sense: ADF PAPER JAM\n"); err++; } if (sense[18] & 0x02) { DBG (2, "sense: ADF NO DOCUMENT IN BIN\n"); err++; } if (sense[18] & 0x04) { DBG (2, "sense: ADF SWITCH COVER OPEN\n"); err++; } /* DB : next is, i think no failure, so no incrementing s */ if (sense[18] & 0x08) { DBG (2, "sense: ADF SET CORRECTLY ON TARGET\n"); } /* The following only for AT12, its reserved (zero?) on other models, */ if (sense[18] & 0x10) { DBG (2, "sense: ADF LENGTH TOO SHORT\n"); err++; } } /* enhanced byte 18 sense data */ if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_ENH_18)) { if (sense[18] & 0x20) { DBG (2, "sense: LAMP FAIL : NOT WARM \n"); err++; } if (sense[18] & 0x40) { DBG (2, "sense: NOT READY STATE\n"); err++; } } if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_BYTE_19)) { if (sense[19] & 0x01) { DBG (2, "sense: 8031 program ROM checksum Error\n"); err++; } if (sense[19] & 0x02) { DBG (2, "sense: 8031 data RAM R/W Error\n"); err++; } if (sense[19] & 0x04) { DBG (2, "sense: Shadow Correction RAM R/W Error\n"); err++; } if (sense[19] & 0x08) { DBG (2, "sense: Line RAM R/W Error\n"); err++; } if (sense[19] & 0x10) { /* docs say "reserved to '0'" */ DBG (2, "sense: CCD control circuit Error\n"); err++; } if (sense[19] & 0x20) { DBG (2, "sense: Motor End Switch Error\n"); err++; } if (sense[19] & 0x40) { /* docs say "reserved to '0'" */ DBG (2, "sense: Lamp Error\n"); err++; } if (sense[19] & 0x80) { DBG (2, "sense: Optical Calibration/Shading Error\n"); err++; } } /* These are the self test results for tests 0-15 */ if ((s) && (s->hw->flags & ARTEC_FLAG_SENSE_BYTE_22)) { if (sense[22] & 0x01) { DBG (2, "sense: 8031 Internal Memory R/W Error\n"); err++; } if (sense[22] & 0x02) { DBG (2, "sense: EEPROM test pattern R/W Error\n"); err++; } if (sense[22] & 0x04) { DBG (2, "sense: ASIC Test Error\n"); err++; } if (sense[22] & 0x08) { DBG (2, "sense: Line RAM R/W Error\n"); err++; } if (sense[22] & 0x10) { DBG (2, "sense: PSRAM R/W Test Error\n"); err++; } if (sense[22] & 0x20) { DBG (2, "sense: Positioning Error\n"); err++; } if (sense[22] & 0x40) { DBG (2, "sense: Test 6 Error\n"); err++; } if (sense[22] & 0x80) { DBG (2, "sense: Test 7 Error\n"); err++; } if (sense[23] & 0x01) { DBG (2, "sense: Test 8 Error\n"); err++; } if (sense[23] & 0x02) { DBG (2, "sense: Test 9 Error\n"); err++; } if (sense[23] & 0x04) { DBG (2, "sense: Test 10 Error\n"); err++; } if (sense[23] & 0x08) { DBG (2, "sense: Test 11 Error\n"); err++; } if (sense[23] & 0x10) { DBG (2, "sense: Test 12 Error\n"); err++; } if (sense[23] & 0x20) { DBG (2, "sense: Test 13 Error\n"); err++; } if (sense[23] & 0x40) { DBG (2, "sense: Test 14 Error\n"); err++; } if (sense[23] & 0x80) { DBG (2, "sense: Test 15 Error\n"); err++; } } if (err) return SANE_STATUS_IO_ERROR; switch (sense[0]) { case 0x70: /* ALWAYS */ switch (sense[2]) { case 0x00: DBG (2, "sense: Successful command\n"); return SANE_STATUS_GOOD; case 0x02: DBG (2, "sense: Not Ready, target can not be accessed\n"); return SANE_STATUS_IO_ERROR; case 0x03: DBG (2, "sense: Medium Error, paper jam or misfeed during ADF\n"); return SANE_STATUS_IO_ERROR; case 0x04: DBG (2, "sense: Hardware Error, non-recoverable\n"); return SANE_STATUS_IO_ERROR; case 0x05: DBG (2, "sense: Illegal Request, bad parameter in command block\n"); return SANE_STATUS_IO_ERROR; case 0x06: DBG (2, "sense: Unit Attention\n"); return SANE_STATUS_GOOD; default: DBG (2, "sense: SENSE KEY UNKNOWN (%02x)\n", sense[2]); return SANE_STATUS_IO_ERROR; } default: DBG (2, "sense: Unknown Error Code Qualifier (%02x)\n", sense[0]); return SANE_STATUS_IO_ERROR; } DBG (2, "sense: Should not come here!\n"); return SANE_STATUS_IO_ERROR; } /* DB added a wait routine for the scanner to come ready */ static SANE_Status wait_ready (int fd) { SANE_Status status; int retry = 30; /* make this tuneable? */ DBG (7, "wait_ready()\n"); while (retry-- > 0) { status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); if (status == SANE_STATUS_GOOD) return status; if (status == SANE_STATUS_DEVICE_BUSY) { sleep (1); continue; } /* status != GOOD && != BUSY */ DBG (9, "wait_ready: '%s'\n", sane_strstatus (status)); return status; } /* BUSY after n retries */ DBG (9, "wait_ready: '%s'\n", sane_strstatus (status)); return status; } /* DB added a abort routine, executed via mode select */ static SANE_Status abort_scan (SANE_Handle handle) { ARTEC_Scanner *s = handle; uint8_t *data, comm[22]; DBG (7, "abort_scan()\n"); memset (comm, 0, sizeof (comm)); comm[0] = 0x15; comm[1] = 0x10; comm[2] = 0x00; comm[3] = 0x00; comm[4] = 0x10; comm[5] = 0x00; data = comm + 6; data[0] = 0x00; /* mode data length */ data[1] = 0x00; /* medium type */ data[2] = 0x00; /* device specific parameter */ data[3] = 0x00; /* block descriptor length */ data = comm + 10; data[0] = 0x00; /* control page parameters */ data[1] = 0x0a; /* parameter length */ data[2] = 0x02 | ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) | ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01); data[3] = 0x00; /* reserved */ data[4] = 0x00; /* reserved */ DBG (9, "abort: sending abort command\n"); sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0); DBG (9, "abort: wait for scanner to come ready...\n"); wait_ready (s->fd); DBG (9, "abort: resetting abort status\n"); data[2] = ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) | ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01); sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0); DBG (9, "abort: wait for scanner to come ready...\n"); return wait_ready (s->fd); } /* DAL - mode_select: used for transparency and ADF scanning */ /* Based on abort_scan */ static SANE_Status artec_mode_select (SANE_Handle handle) { ARTEC_Scanner *s = handle; uint8_t *data, comm[22]; DBG (7, "artec_mode_select()\n"); memset (comm, 0, sizeof (comm)); comm[0] = 0x15; comm[1] = 0x10; comm[2] = 0x00; comm[3] = 0x00; comm[4] = 0x10; comm[5] = 0x00; data = comm + 6; data[0] = 0x00; /* mode data length */ data[1] = 0x00; /* medium type */ data[2] = 0x00; /* device specific parameter */ data[3] = 0x00; /* block descriptor length */ data = comm + 10; data[0] = 0x00; /* control page parameters */ data[1] = 0x0a; /* parameter length */ data[2] = ((s->val[OPT_TRANSPARENCY].w == SANE_TRUE) ? 0x04 : 0x00) | ((s->val[OPT_ADF].w == SANE_TRUE) ? 0x00 : 0x01); data[3] = 0x00; /* reserved */ data[4] = 0x00; /* reserved */ DBG (9, "artec_mode_select: mode %d\n", data[2]); DBG (9, "artec_mode_select: sending mode command\n"); sanei_scsi_cmd (s->fd, comm, 6 + comm[4], 0, 0); DBG (9, "artec_mode_select: wait for scanner to come ready...\n"); return wait_ready (s->fd); } static SANE_Status read_data (int fd, int data_type_code, u_char * dest, size_t * len) { static u_char read_6[10]; DBG (7, "read_data()\n"); memset (read_6, 0, sizeof (read_6)); read_6[0] = 0x28; read_6[2] = data_type_code; read_6[6] = *len >> 16; read_6[7] = *len >> 8; read_6[8] = *len; return (sanei_scsi_cmd (fd, read_6, sizeof (read_6), dest, len)); } static int artec_get_status (int fd) { u_char write_10[10]; u_char read_12[12]; size_t nread; DBG (7, "artec_get_status()\n"); nread = 12; memset (write_10, 0, 10); write_10[0] = 0x34; write_10[8] = 0x0c; sanei_scsi_cmd (fd, write_10, 10, read_12, &nread); nread = (read_12[9] << 16) + (read_12[10] << 8) + read_12[11]; DBG (9, "artec_status: %lu\n", (u_long) nread); return (nread); } static SANE_Status artec_reverse_line (SANE_Handle handle, SANE_Byte * data) { ARTEC_Scanner *s = handle; SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */ SANE_Byte *to, *from; int len; DBG (8, "artec_reverse_line()\n"); len = s->params.bytes_per_line; memcpy (tmp_buf, data, len); if (s->params.format == SANE_FRAME_RGB) /* RGB format */ { for (from = tmp_buf, to = data + len - 3; to >= data; to -= 3, from += 3) { *(to + 0) = *(from + 0); /* copy the R byte */ *(to + 1) = *(from + 1); /* copy the G byte */ *(to + 2) = *(from + 2); /* copy the B byte */ } } else if (s->params.format == SANE_FRAME_GRAY) { if (s->params.depth == 8) /* 256 color gray-scale */ { for (from = tmp_buf, to = data + len; to >= data; to--, from++) { *to = *from; } } else if (s->params.depth == 1) /* line art or halftone */ { for (from = tmp_buf, to = data + len; to >= data; to--, from++) { *to = (((*from & 0x01) << 7) | ((*from & 0x02) << 5) | ((*from & 0x04) << 3) | ((*from & 0x08) << 1) | ((*from & 0x10) >> 1) | ((*from & 0x20) >> 3) | ((*from & 0x40) >> 5) | ((*from & 0x80) >> 7)); } } } return (SANE_STATUS_GOOD); } #if 0 static SANE_Status artec_byte_rgb_to_line_rgb (SANE_Byte * data, SANE_Int len) { SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */ int count, from; DBG (8, "artec_byte_rgb_to_line_rgb()\n"); /* copy the RGBRGBRGBRGBRGB... formated data to our temp buffer */ memcpy (tmp_buf, data, len * 3); /* now copy back to *data in RRRRRRRGGGGGGGBBBBBBB format */ for (count = 0, from = 0; count < len; count++, from += 3) { data[count] = tmp_buf[from]; /* R byte */ data[count + len] = tmp_buf[from + 1]; /* G byte */ data[count + (len * 2)] = tmp_buf[from + 2]; /* B byte */ } return (SANE_STATUS_GOOD); } #endif static SANE_Status artec_line_rgb_to_byte_rgb (SANE_Byte * data, SANE_Int len) { SANE_Byte tmp_buf[32768]; /* max dpi 1200 * 8.5 inches * 3 = 30600 */ int count, to; DBG (8, "artec_line_rgb_to_byte_rgb()\n"); /* copy the rgb data to our temp buffer */ memcpy (tmp_buf, data, len * 3); /* now copy back to *data in RGB format */ for (count = 0, to = 0; count < len; count++, to += 3) { data[to] = tmp_buf[count]; /* R byte */ data[to + 1] = tmp_buf[count + len]; /* G byte */ data[to + 2] = tmp_buf[count + (len * 2)]; /* B byte */ } return (SANE_STATUS_GOOD); } static SANE_Byte **line_buffer = NULL; static SANE_Byte *tmp_line_buf = NULL; static SANE_Int r_buf_lines; static SANE_Int g_buf_lines; static SANE_Status artec_buffer_line_offset (SANE_Handle handle, SANE_Int line_offset, SANE_Byte * data, size_t * len) { ARTEC_Scanner *s = handle; static SANE_Int width; static SANE_Int cur_line; SANE_Byte *tmp_buf_ptr; SANE_Byte *grn_ptr; SANE_Byte *blu_ptr; SANE_Byte *out_ptr; int count; DBG (8, "artec_buffer_line_offset()\n"); if (*len == 0) return (SANE_STATUS_GOOD); if (tmp_line_buf == NULL) { width = *len / 3; cur_line = 0; DBG (9, "buffer_line_offset: offset = %d, len = %lu\n", line_offset, (u_long) * len); tmp_line_buf = malloc (*len); if (tmp_line_buf == NULL) { DBG (1, "couldn't allocate memory for temp line buffer\n"); return (SANE_STATUS_NO_MEM); } r_buf_lines = line_offset * 2; g_buf_lines = line_offset; line_buffer = malloc (r_buf_lines * sizeof (SANE_Byte *)); if (line_buffer == NULL) { DBG (1, "couldn't allocate memory for line buffer pointers\n"); return (SANE_STATUS_NO_MEM); } for (count = 0; count < r_buf_lines; count++) { line_buffer[count] = malloc ((*len) * sizeof (SANE_Byte)); if (line_buffer[count] == NULL) { DBG (1, "couldn't allocate memory for line buffer %d\n", count); return (SANE_STATUS_NO_MEM); } } DBG (9, "buffer_line_offset: r lines = %d, g lines = %d\n", r_buf_lines, g_buf_lines); } cur_line++; if (r_buf_lines > 0) { if (cur_line > r_buf_lines) { /* copy the Red and Green portions out of the buffer */ /* if scanner returns RRRRRRRRGGGGGGGGGBBBBBBBB format it's easier */ if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT) { /* get the red line info from r_buf_lines ago */ memcpy (tmp_line_buf, line_buffer[0], width); /* get the green line info from g_buf_lines ago */ memcpy (tmp_line_buf + width, &line_buffer[line_offset][width], width); } else { /* get the red line info from r_buf_lines ago as a whole line */ memcpy (tmp_line_buf, line_buffer[0], *len); /* scanner returns RGBRGBRGB format so we do a loop for green */ grn_ptr = &line_buffer[line_offset][1]; out_ptr = tmp_line_buf + 1; for (count = 0; count < width; count++) { *out_ptr = *grn_ptr; /* copy green pixel */ grn_ptr += 3; out_ptr += 3; } } } /* move all the buffered lines down (just move the ptrs for speed) */ tmp_buf_ptr = line_buffer[0]; for (count = 0; count < (r_buf_lines - 1); count++) { line_buffer[count] = line_buffer[count + 1]; } line_buffer[r_buf_lines - 1] = tmp_buf_ptr; /* insert the new line data at the end of our FIFO */ memcpy (line_buffer[r_buf_lines - 1], data, *len); if (cur_line > r_buf_lines) { /* copy the Red and Green portions out of the buffer */ /* if scanner returns RRRRRRRRGGGGGGGGGBBBBBBBB format it's easier */ if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT) { /* copy the red and green data in with the original blue */ memcpy (data, tmp_line_buf, width * 2); } else { /* scanner returns RGBRGBRGB format so we have to do a loop */ /* copy the blue data into our temp buffer then copy full */ /* temp buffer overtop of input data */ if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) { blu_ptr = data; out_ptr = tmp_line_buf; } else { blu_ptr = data + 2; out_ptr = tmp_line_buf + 2; } for (count = 0; count < width; count++) { *out_ptr = *blu_ptr; /* copy blue pixel */ blu_ptr += 3; out_ptr += 3; } /* now just copy tmp_line_buf back over original data */ memcpy (data, tmp_line_buf, *len); } } else { /* if in the first r_buf_lines, then don't return anything */ *len = 0; } } return (SANE_STATUS_GOOD); } static SANE_Status artec_buffer_line_offset_free (void) { int count; DBG (7, "artec_buffer_line_offset_free()\n"); free (tmp_line_buf); tmp_line_buf = NULL; for (count = 0; count < r_buf_lines; count++) { free (line_buffer[count]); } free (line_buffer); line_buffer = NULL; return (SANE_STATUS_GOOD); } #if 0 static SANE_Status artec_read_gamma_table (SANE_Handle handle) { ARTEC_Scanner *s = handle; char write_6[4096 + 20]; /* max gamma table is 4096 + 20 for command data */ char *data; char prt_buf[128]; char tmp_buf[128]; int i; DBG (7, "artec_read_gamma_table()\n"); memset (write_6, 0, sizeof (*write_6)); write_6[0] = 0x28; /* read data code */ /* FIXME: AT12 and AM12S use 0x0E for reading all channels of data */ write_6[2] = 0x03; /* data type code "gamma data" */ write_6[6] = (s->gamma_length + 9) >> 16; write_6[7] = (s->gamma_length + 9) >> 8; write_6[8] = (s->gamma_length + 9); /* FIXME: AT12 and AM12S have one less byte so use 18 */ if ((!strcmp (s->hw->sane.model, "AT12")) || (!strcmp (s->hw->sane.model, "AM12S"))) { data = write_6 + 18; } else { data = write_6 + 19; } /* FIXME: AT12 & AM12S ignore this, it's a reserved field */ write_6[10] = 0x08; /* bitmask, bit 3 means mono type */ if (!s->val[OPT_CUSTOM_GAMMA].w) { write_6[11] = 1; /* internal gamma table #1 (hope this is default) */ } DBG( 9, "Gamma Table\n" ); DBG( 9, "==================================\n" ); prt_buf[0] = '\0'; for (i = 0; i < s->gamma_length; i++) { if (DBG_LEVEL >= 9) { if (!(i % 16)) { if ( prt_buf[0] ) { strcat( prt_buf, "\n" ); DBG( 9, "%s", prt_buf ); } sprintf (prt_buf, "%02x: ", i); } sprintf (tmp_buf, "%02x ", (int) s->gamma_table[0][i]); strcat (prt_buf, tmp_buf ); } data[i] = s->gamma_table[0][i]; } if ( prt_buf[0] ) { strcat( prt_buf, "\n" ); DBG( 9, "%s", prt_buf ); } if ((!strcmp (s->hw->sane.model, "AT12")) || (!strcmp (s->hw->sane.model, "AM12S"))) { return (sanei_scsi_cmd (s->fd, write_6, 10 + 8 + s->gamma_length, 0, 0)); } else { return (sanei_scsi_cmd (s->fd, write_6, 10 + 9 + s->gamma_length, 0, 0)); } } #endif static SANE_Status artec_send_gamma_table (SANE_Handle handle) { ARTEC_Scanner *s = handle; char write_6[4096 + 20]; /* max gamma table is 4096 + 20 for command data */ char *data; char prt_buf[128]; char tmp_buf[128]; int i; DBG (7, "artec_send_gamma_table()\n"); memset (write_6, 0, sizeof (*write_6)); write_6[0] = 0x2a; /* send data code */ if (s->hw->setwindow_cmd_size > 55) { /* newer scanners support sending 3 channels of gamma, or populating all */ /* 3 channels with same data by using code 0x0e */ write_6[2] = 0x0e; } else { /* older scanners only support 1 channel of gamma data using code 0x3 */ write_6[2] = 0x03; } /* FIXME: AT12 & AM!2S ignore this, it's a reserved field */ write_6[10] = 0x08; /* bitmask, bit 3 means mono type */ if (!s->val[OPT_CUSTOM_GAMMA].w) { write_6[6] = 9 >> 16; write_6[7] = 9 >> 8; write_6[8] = 9; write_6[11] = 1; /* internal gamma table #1 (hope this is default) */ return (sanei_scsi_cmd (s->fd, write_6, 10 + 9, 0, 0)); } else { write_6[6] = (s->gamma_length + 9) >> 16; write_6[7] = (s->gamma_length + 9) >> 8; write_6[8] = (s->gamma_length + 9); DBG( 9, "Gamma Table\n" ); DBG( 9, "==================================\n" ); /* FIXME: AT12 and AM12S have one less byte so use 18 */ if ((!strcmp (s->hw->sane.model, "AT12")) || (!strcmp (s->hw->sane.model, "AM12S"))) { data = write_6 + 18; } else { data = write_6 + 19; } prt_buf[0] = '\0'; for (i = 0; i < s->gamma_length; i++) { if (DBG_LEVEL >= 9) { if (!(i % 16)) { if ( prt_buf[0] ) { strcat( prt_buf, "\n" ); DBG( 9, "%s", prt_buf ); } sprintf (prt_buf, "%02x: ", i); } sprintf (tmp_buf, "%02x ", (int) s->gamma_table[0][i]); strcat (prt_buf, tmp_buf ); } data[i] = s->gamma_table[0][i]; } data[s->gamma_length - 1] = 0; if ( prt_buf[0] ) { strcat( prt_buf, "\n" ); DBG( 9, "%s", prt_buf ); } /* FIXME: AT12 and AM12S have one less byte so use 18 */ if ((!strcmp (s->hw->sane.model, "AT12")) || (!strcmp (s->hw->sane.model, "AM12S"))) { return (sanei_scsi_cmd (s->fd, write_6, 10 + 8 + s->gamma_length, 0, 0)); } else { return (sanei_scsi_cmd (s->fd, write_6, 10 + 9 + s->gamma_length, 0, 0)); } } } static SANE_Status artec_set_scan_window (SANE_Handle handle) { ARTEC_Scanner *s = handle; char write_6[4096]; unsigned char *data; int counter; int reversed_x; int max_x; DBG (7, "artec_set_scan_window()\n"); /* * if we can, start before the desired window since we have to throw away * s->line_offset number of rows because of the RGB fixup. */ if ((s->line_offset) && (s->tl_y) && (s->tl_y >= (s->line_offset * 2))) { s->tl_y -= (s->line_offset * 2); } data = (unsigned char *)write_6 + 10; DBG (5, "Scan window info:\n"); DBG (5, " X resolution: %5d (%d-%d)\n", s->x_resolution, ARTEC_MIN_X (s->hw), ARTEC_MAX_X (s->hw)); DBG (5, " Y resolution: %5d (%d-%d)\n", s->y_resolution, ARTEC_MIN_Y (s->hw), ARTEC_MAX_Y (s->hw)); DBG (5, " TL_X (pixel): %5d\n", s->tl_x); DBG (5, " TL_Y (pixel): %5d\n", s->tl_y); DBG (5, " Width : %5d (%d-%d)\n", s->params.pixels_per_line, s->hw->x_range.min, (int) ((SANE_UNFIX (s->hw->x_range.max) / MM_PER_INCH) * s->x_resolution)); DBG (5, " Height : %5d (%d-%d)\n", s->params.lines, s->hw->y_range.min, (int) ((SANE_UNFIX (s->hw->y_range.max) / MM_PER_INCH) * s->y_resolution)); DBG (5, " Image Comp. : %s\n", s->mode); DBG (5, " Line Offset : %lu\n", (u_long) s->line_offset); memset (write_6, 0, 4096); write_6[0] = 0x24; write_6[8] = s->hw->setwindow_cmd_size; /* total size of command */ /* beginning of set window data header */ /* actual SCSI command data byte count */ data[7] = s->hw->setwindow_cmd_size - 8; /* x resolution */ data[10] = s->x_resolution >> 8; data[11] = s->x_resolution; /* y resolution */ data[12] = s->y_resolution >> 8; data[13] = s->y_resolution; if ( s->hw->flags & ARTEC_FLAG_REVERSE_WINDOW ) { /* top left X value */ /* the select area is flipped across the page, so we have to do some */ /* calculation here to get the real starting X value */ max_x = (int) ((SANE_UNFIX (s->hw->x_range.max) / MM_PER_INCH) * s->x_resolution); reversed_x = max_x - s->tl_x - s->params.pixels_per_line; data[14] = reversed_x >> 24; data[15] = reversed_x >> 16; data[16] = reversed_x >> 8; data[17] = reversed_x; } else { /* top left X value */ data[14] = s->tl_x >> 24; data[15] = s->tl_x >> 16; data[16] = s->tl_x >> 8; data[17] = s->tl_x; } /* top left Y value */ data[18] = s->tl_y >> 24; data[19] = s->tl_y >> 16; data[20] = s->tl_y >> 8; data[21] = s->tl_y; /* width */ data[22] = s->params.pixels_per_line >> 24; data[23] = s->params.pixels_per_line >> 16; data[24] = s->params.pixels_per_line >> 8; data[25] = s->params.pixels_per_line; /* height */ data[26] = (s->params.lines + (s->line_offset * 2)) >> 24; data[27] = (s->params.lines + (s->line_offset * 2)) >> 16; data[28] = (s->params.lines + (s->line_offset * 2)) >> 8; data[29] = (s->params.lines + (s->line_offset * 2)); /* misc. single-byte settings */ /* brightness */ if (s->hw->flags & ARTEC_FLAG_OPT_BRIGHTNESS) data[30] = s->val[OPT_BRIGHTNESS].w; data[31] = s->val[OPT_THRESHOLD].w; /* threshold */ /* contrast */ if (s->hw->flags & ARTEC_FLAG_OPT_CONTRAST) data[32] = s->val[OPT_CONTRAST].w; /* * byte 33 is mode * byte 37 bit 7 is "negative" setting */ if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) { data[33] = ARTEC_COMP_LINEART; data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x0 : 0x80; } else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { data[33] = ARTEC_COMP_HALFTONE; data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x0 : 0x80; } else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { data[33] = ARTEC_COMP_GRAY; data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x80 : 0x0; } else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) { data[33] = ARTEC_COMP_COLOR; data[37] = (s->val[OPT_NEGATIVE].w == SANE_TRUE) ? 0x80 : 0x0; } data[34] = s->params.depth; /* bits per pixel */ if (s->hw->flags & ARTEC_FLAG_HALFTONE_PATTERN) { data[35] = artec_get_str_index (halftone_pattern_list, s->val[OPT_HALFTONE_PATTERN].s); /* halftone pattern */ } /* user supplied halftone pattern not supported for now so override with */ /* 8x8 Bayer */ if (data[35] == 0) { data[35] = 4; } /* NOTE: AT12 doesn't support mono according to docs. */ data[48] = artec_get_str_index (filter_type_list, s->val[OPT_FILTER_TYPE].s); /* filter mode */ if (s->hw->setwindow_cmd_size > 55) { data[48] = 0x2; /* DB filter type green for AT12,see above */ if (s->hw->flags & ARTEC_FLAG_SC_BUFFERS_LINES) { /* FIXME: guessing at this value, use formula instead */ data[55] = 0x00; /* buffer full line count */ data[56] = 0x00; /* buffer full line count */ data[57] = 0x00; /* buffer full line count */ data[58] = 0x0a; /* buffer full line count */ /* FIXME: guessing at this value, use formula instead */ data[59] = 0x00; /* access line count */ data[60] = 0x00; /* access line count */ data[61] = 0x00; /* access line count */ data[62] = 0x0a; /* access line count */ } if (s->hw->flags & ARTEC_FLAG_SC_HANDLES_OFFSET) { /* DB : following fields : high order bit (0x80) is enable */ /* scanner handles line offset fixup, 0 = driver handles */ data[63] = 0x80; } if ((s->hw->flags & ARTEC_FLAG_PIXEL_AVERAGING) && (s->val[OPT_PIXEL_AVG].w)) { /* enable pixel average function */ data[64] = 0x80; } else { /* disable pixel average function */ data[64] = 0; } if ((s->hw->flags & ARTEC_FLAG_ENHANCE_LINE_EDGE) && (s->val[OPT_EDGE_ENH].w)) { /* enable lineart edge enhancement function */ data[65] = 0x80; } else { /* disable lineart edge enhancement function */ data[65] = 0; } /* data is R-G-B format, 0x80 = G-B-R format (reversed) */ data[66] = 0; } DBG (50, "Set Window data : \n"); for (counter = 0; counter < s->hw->setwindow_cmd_size; counter++) { DBG (50, " byte %2d = %02x \n", counter, data[counter] & 0xff); /* DB */ } DBG (50, "\n"); /* set the scan window */ return (sanei_scsi_cmd (s->fd, write_6, 10 + s->hw->setwindow_cmd_size, 0, 0)); } static SANE_Status artec_start_scan (SANE_Handle handle) { ARTEC_Scanner *s = handle; char write_7[7]; DBG (7, "artec_start_scan()\n"); /* setup cmd to start scanning */ memset (write_7, 0, 7); write_7[0] = 0x1b; /* code to start scan */ /* FIXME: need to make this a flag */ if (!strcmp (s->hw->sane.model, "AM12S")) { /* start the scan */ return (sanei_scsi_cmd (s->fd, write_7, 6, 0, 0)); } else { write_7[4] = 0x01; /* need to send 1 data byte */ /* start the scan */ return (sanei_scsi_cmd (s->fd, write_7, 7, 0, 0)); } } static SANE_Status artec_software_rgb_calibrate (SANE_Handle handle, SANE_Byte * buf, int lines) { ARTEC_Scanner *s = handle; int line, i, loop, offset; DBG (7, "artec_software_rgb_calibrate()\n"); for (line = 0; line < lines; line++) { i = 0; offset = 0; if (s->x_resolution == 200) { /* skip ever 3rd byte, -= causes us to go down in count */ if ((s->tl_x % 3) == 0) offset -= 1; } else { /* round down to the previous pixel */ offset += ((s->tl_x / (300 / s->x_resolution)) * (300 / s->x_resolution)); } for (loop = 0; loop < s->params.pixels_per_line; loop++) { if ((DBG_LEVEL == 100) && (loop < 100)) { DBG (100, " %2d-%4d R (%4d,%4d): %d * %5.2f = %d\n", line, loop, i, offset, buf[i], s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset], (int) (buf[i] * s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset])); } buf[i] = buf[i] * s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][offset]; i++; if ((DBG_LEVEL == 100) && (loop < 100)) { DBG (100, " G (%4d,%4d): %d * %5.2f = %d\n", i, offset, buf[i], s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset], (int) (buf[i] * s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset])); } buf[i] = buf[i] * s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][offset]; i++; if ((DBG_LEVEL == 100) && (loop < 100)) { DBG (100, " B (%4d,%4d): %d * %5.2f = %d\n", i, offset, buf[i], s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset], (int) (buf[i] * s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset])); } buf[i] = buf[i] * s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][offset]; i++; if (s->x_resolution == 200) { offset += 1; /* skip every 3rd byte */ if (((offset + 1) % 3) == 0) offset += 1; } else { offset += (300 / s->x_resolution); } } } return (SANE_STATUS_GOOD); } static SANE_Status artec_calibrate_shading (SANE_Handle handle) { ARTEC_Scanner *s = handle; SANE_Status status; /* DB added */ u_char buf[76800]; /* should be big enough */ size_t len; SANE_Word save_x_resolution; SANE_Word save_pixels_per_line; int i; DBG (7, "artec_calibrate_shading()\n"); if (s->hw->flags & ARTEC_FLAG_CALIBRATE_RGB) { /* this method scans in 4 lines each of Red, Green, and Blue */ /* after reading line of shading data, generate data for software */ /* calibration so we have it if user requests */ len = 4 * 2592; /* 4 lines of data, 2592 pixels wide */ if ( DBG_LEVEL == 100 ) DBG (100, "RED Software Calibration data\n"); read_data (s->fd, ARTEC_DATA_RED_SHADING, buf, &len); for (i = 0; i < 2592; i++) { s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][i] = 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4); if (DBG_LEVEL == 100) { DBG (100, " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n", i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776], s->soft_calibrate_data[ARTEC_SOFT_CALIB_RED][i]); } } if (DBG_LEVEL == 100) { DBG (100, "GREEN Software Calibration data\n"); } read_data (s->fd, ARTEC_DATA_GREEN_SHADING, buf, &len); for (i = 0; i < 2592; i++) { s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][i] = 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4); if (DBG_LEVEL == 100) { DBG (100, " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n", i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776], s->soft_calibrate_data[ARTEC_SOFT_CALIB_GREEN][i]); } } if (DBG_LEVEL == 100) { DBG (100, "BLUE Software Calibration data\n"); } read_data (s->fd, ARTEC_DATA_BLUE_SHADING, buf, &len); for (i = 0; i < 2592; i++) { s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][i] = 255.0 / ((buf[i] + buf[i + 2592] + buf[i + 5184] + buf[i + 7776]) / 4); if (DBG_LEVEL == 100) { DBG (100, " %4d: 255.0 / (( %3d + %3d + %3d + %3d ) / 4 ) = %5.2f\n", i, buf[i], buf[i + 2592], buf[i + 5184], buf[i + 7776], s->soft_calibrate_data[ARTEC_SOFT_CALIB_BLUE][i]); } } } else if (s->hw->flags & ARTEC_FLAG_CALIBRATE_DARK_WHITE) { /* this method scans black, then white data */ len = 3 * 5100; /* 1 line of data, 5100 pixels wide, RGB data */ read_data (s->fd, ARTEC_DATA_DARK_SHADING, buf, &len); save_x_resolution = s->x_resolution; s->x_resolution = 600; save_pixels_per_line = s->params.pixels_per_line; s->params.pixels_per_line = ARTEC_MAX_X (s->hw); s->params.pixels_per_line = 600 * 8.5; /* ?this? or ?above line? */ /* DB added wait_ready */ status = wait_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "wait for scanner ready failed: %s\n", sane_strstatus (status)); return status; } /* next line should use ARTEC_DATA_WHITE_SHADING_TRANS if using ADF */ read_data (s->fd, ARTEC_DATA_WHITE_SHADING_OPT, buf, &len); s->x_resolution = save_x_resolution; s->params.pixels_per_line = save_pixels_per_line; } return (SANE_STATUS_GOOD); } static SANE_Status end_scan (SANE_Handle handle) { ARTEC_Scanner *s = handle; /* DB uint8_t write_6[6] = {0x1B, 0, 0, 0, 0, 0}; */ DBG (7, "end_scan()\n"); s->scanning = SANE_FALSE; /* if (s->this_pass == 3) */ s->this_pass = 0; if ((s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) && (tmp_line_buf != NULL)) { artec_buffer_line_offset_free (); } /* DB return (sanei_scsi_cmd (s->fd, write_6, 6, 0, 0)); */ return abort_scan (s); } static SANE_Status artec_get_cap_data (ARTEC_Device * dev, int fd) { int cap_model, loop; u_char cap_buf[256]; /* buffer for cap data */ DBG (7, "artec_get_cap_data()\n"); /* DB always use the hard-coded capability info first * if we get cap data from the scanner, we override */ cap_model = -1; for (loop = 0; loop < NELEMS (cap_data); loop++) { if (strcmp (cap_data[loop].model, dev->sane.model) == 0) { cap_model = loop; } } if (cap_model == -1) { DBG (1, "unable to identify Artec model '%s', check artec.c\n", dev->sane.model); return (SANE_STATUS_UNSUPPORTED); } dev->x_range.min = 0; dev->x_range.max = SANE_FIX (cap_data[cap_model].width) * MM_PER_INCH; dev->x_range.quant = 1; dev->width = cap_data[cap_model].width; dev->y_range.min = 0; dev->y_range.max = SANE_FIX (cap_data[cap_model].height) * MM_PER_INCH; dev->y_range.quant = 1; dev->height = cap_data[cap_model].height; artec_str_list_to_word_list (&dev->horz_resolution_list, cap_data[cap_model].horz_resolution_str); artec_str_list_to_word_list (&dev->vert_resolution_list, cap_data[cap_model].vert_resolution_str); dev->contrast_range.min = 0; dev->contrast_range.max = 255; dev->contrast_range.quant = 1; dev->brightness_range.min = 0; dev->brightness_range.max = 255; dev->brightness_range.quant = 1; dev->threshold_range.min = 0; dev->threshold_range.max = 255; dev->threshold_range.quant = 1; dev->sane.type = cap_data[cap_model].type; dev->max_read_size = cap_data[cap_model].max_read_size; dev->flags = cap_data[cap_model].flags; switch (cap_data[cap_model].adc_bits) { case 8: dev->gamma_length = 256; break; case 10: dev->gamma_length = 1024; break; case 12: dev->gamma_length = 4096; break; } dev->setwindow_cmd_size = cap_data[cap_model].setwindow_cmd_size; if (dev->support_cap_data_retrieve) /* DB */ { /* DB added reading capability data from scanner */ char info[80]; /* for printing debugging info */ size_t len = sizeof (cap_buf); /* read the capability data from the scanner */ DBG (9, "reading capability data from scanner...\n"); wait_ready (fd); read_data (fd, ARTEC_DATA_CAPABILITY_DATA, cap_buf, &len); DBG (50, "scanner capability data : \n"); strncpy (info, (const char *) &cap_buf[0], 8); info[8] = '\0'; DBG (50, " Vendor : %s\n", info); strncpy (info, (const char *) &cap_buf[8], 16); info[16] = '\0'; DBG (50, " Device Name : %s\n", info); strncpy (info, (const char *) &cap_buf[24], 4); info[4] = '\0'; DBG (50, " Version Number : %s\n", info); sprintf (info, "%d ", cap_buf[29]); DBG (50, " CCD Type : %s\n", info); sprintf (info, "%d ", cap_buf[30]); DBG (50, " AD Converter Type : %s\n", info); sprintf (info, "%d ", (cap_buf[31] << 8) | cap_buf[32]); DBG (50, " Buffer size : %s\n", info); sprintf (info, "%d ", cap_buf[33]); DBG (50, " Channels of RGB Gamma : %s\n", info); sprintf (info, "%d ", (cap_buf[34] << 8) | cap_buf[35]); DBG (50, " Opt. res. of R channel : %s\n", info); sprintf (info, "%d ", (cap_buf[36] << 8) | cap_buf[37]); DBG (50, " Opt. res. of G channel : %s\n", info); sprintf (info, "%d ", (cap_buf[38] << 8) | cap_buf[39]); DBG (50, " Opt. res. of B channel : %s\n", info); sprintf (info, "%d ", (cap_buf[40] << 8) | cap_buf[41]); DBG (50, " Min. Hor. Resolution : %s\n", info); sprintf (info, "%d ", (cap_buf[42] << 8) | cap_buf[43]); DBG (50, " Max. Vert. Resolution : %s\n", info); sprintf (info, "%d ", (cap_buf[44] << 8) | cap_buf[45]); DBG (50, " Min. Vert. Resolution : %s\n", info); sprintf (info, "%s ", cap_buf[46] == 0x80 ? "yes" : "no"); DBG (50, " Chunky Data Format : %s\n", info); sprintf (info, "%s ", cap_buf[47] == 0x80 ? "yes" : "no"); DBG (50, " RGB Data Format : %s\n", info); sprintf (info, "%s ", cap_buf[48] == 0x80 ? "yes" : "no"); DBG (50, " BGR Data Format : %s\n", info); sprintf (info, "%d ", cap_buf[49]); DBG (50, " Line Offset : %s\n", info); sprintf (info, "%s ", cap_buf[50] == 0x80 ? "yes" : "no"); DBG (50, " Channel Valid Sequence : %s\n", info); sprintf (info, "%s ", cap_buf[51] == 0x80 ? "yes" : "no"); DBG (50, " True Gray : %s\n", info); sprintf (info, "%s ", cap_buf[52] == 0x80 ? "yes" : "no"); DBG (50, " Force Host Not Do Shading : %s\n", info); sprintf (info, "%s ", cap_buf[53] == 0x00 ? "AT006" : "AT010"); DBG (50, " ASIC : %s\n", info); sprintf (info, "%s ", cap_buf[54] == 0x82 ? "SCSI2" : cap_buf[54] == 0x81 ? "SCSI1" : "Parallel"); DBG (50, " Interface : %s\n", info); sprintf (info, "%d ", (cap_buf[55] << 8) | cap_buf[56]); DBG (50, " Phys. Area Width : %s\n", info); sprintf (info, "%d ", (cap_buf[57] << 8) | cap_buf[58]); DBG (50, " Phys. Area Length : %s\n", info); /* fill in the information we've got from the scanner */ dev->width = ((float) ((cap_buf[55] << 8) | cap_buf[56])) / 1000; dev->height = ((float) ((cap_buf[57] << 8) | cap_buf[58])) / 1000; /* DB ----- */ } DBG (9, "Scanner capability info.\n"); DBG (9, " Vendor : %s\n", dev->sane.vendor); DBG (9, " Model : %s\n", dev->sane.model); DBG (9, " Type : %s\n", dev->sane.type); DBG (5, " Width : %.2f inches\n", dev->width); DBG (9, " Height : %.2f inches\n", dev->height); DBG (9, " X Range(mm) : %d-%d\n", dev->x_range.min, (int) (SANE_UNFIX (dev->x_range.max))); DBG (9, " Y Range(mm) : %d-%d\n", dev->y_range.min, (int) (SANE_UNFIX (dev->y_range.max))); DBG (9, " Horz. DPI : %d-%d\n", ARTEC_MIN_X (dev), ARTEC_MAX_X (dev)); DBG (9, " Vert. DPI : %d-%d\n", ARTEC_MIN_Y (dev), ARTEC_MAX_Y (dev)); DBG (9, " Contrast : %d-%d\n", dev->contrast_range.min, dev->contrast_range.max); DBG (9, " REQ Sh. Cal.: %d\n", dev->flags & ARTEC_FLAG_CALIBRATE ? 1 : 0); DBG (9, " REQ Ln. Offs: %d\n", dev->flags & ARTEC_FLAG_RGB_LINE_OFFSET ? 1 : 0); DBG (9, " REQ Ch. Shft: %d\n", dev->flags & ARTEC_FLAG_RGB_CHAR_SHIFT ? 1 : 0); DBG (9, " SetWind Size: %d\n", dev->setwindow_cmd_size); DBG (9, " Calib Method: %s\n", dev->flags & ARTEC_FLAG_CALIBRATE_RGB ? "RGB" : dev->flags & ARTEC_FLAG_CALIBRATE_DARK_WHITE ? "white/black" : "N/A"); return (SANE_STATUS_GOOD); } static SANE_Status dump_inquiry (unsigned char *result) { int i; int j; char prt_buf[129] = ""; char tmp_buf[129]; DBG (4, "dump_inquiry()\n"); DBG (4, " === SANE/Artec backend v%d.%d.%d ===\n", ARTEC_MAJOR, ARTEC_MINOR, ARTEC_SUB); DBG (4, " ===== Scanner Inquiry Block =====\n"); for (i = 0; i < 96; i += 16) { sprintf (prt_buf, "0x%02x: ", i); for (j = 0; j < 16; j++) { sprintf (tmp_buf, "%02x ", (int) result[i + j]); strcat( prt_buf, tmp_buf ); } strcat( prt_buf, " "); for (j = 0; j < 16; j++) { sprintf (tmp_buf, "%c", isprint (result[i + j]) ? result[i + j] : '.'); strcat( prt_buf, tmp_buf ); } strcat( prt_buf, "\n" ); DBG(4, "%s", prt_buf ); } return (SANE_STATUS_GOOD); } static SANE_Status attach (const char *devname, ARTEC_Device ** devp) { char result[INQ_LEN]; char product_revision[5]; char temp_result[33]; char *str, *t; int fd; SANE_Status status; ARTEC_Device *dev; size_t size; DBG (7, "attach()\n"); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } DBG (6, "attach: opening %s\n", devname); status = sanei_scsi_open (devname, &fd, sense_handler, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed (%s)\n", sane_strstatus (status)); return (SANE_STATUS_INVAL); } DBG (6, "attach: sending INQUIRY\n"); size = sizeof (result); status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size); if (status != SANE_STATUS_GOOD || size < 16) { DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } /* * Check to see if this device is a scanner. */ if (result[0] != 0x6) { DBG (1, "attach: device doesn't look like a scanner at all.\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } /* * The BlackWidow BW4800SP is actually a rebadged AT3, with the vendor * string set to 8 spaces and the product to "Flatbed Scanner ". So, * if we have one of these, we'll make it look like an AT3. * * For now, to be on the safe side, we'll also check the version number * since BlackWidow seems to have left that intact as "1.90". * * Check that result[36] == 0x00 so we don't mistake a microtek scanner. */ if ((result[36] == 0x00) && (strncmp (result + 32, "1.90", 4) == 0) && (strncmp (result + 8, " ", 8) == 0) && (strncmp (result + 16, "Flatbed Scanner ", 16) == 0)) { DBG (6, "Found BlackWidow BW4800SP scanner, setting up like AT3\n"); /* setup the vendor and product to mimic the Artec/Ultima AT3 */ strncpy (result + 8, "ULTIMA", 6); strncpy (result + 16, "AT3 ", 16); } /* * The Plustek 19200S is actually a rebadged AM12S, with the vendor string * set to 8 spaces. */ if ((strncmp (result + 8, " ", 8) == 0) && (strncmp (result + 16, "SCAN19200 ", 16) == 0)) { DBG (6, "Found Plustek 19200S scanner, setting up like AM12S\n"); /* setup the vendor and product to mimic the Artec/Ultima AM12S */ strncpy (result + 8, "ULTIMA", 6); strncpy (result + 16, "AM12S ", 16); } /* * Check to see if they have forced a vendor and/or model string and * if so, fudge the inquiry results with that info. We do this right * before we check the inquiry results, otherwise we might not be forcing * anything. */ if (artec_vendor[0] != 0x0) { /* * 1) copy the vendor string to our temp variable * 2) append 8 spaces to make sure we have at least 8 characters * 3) copy our fudged vendor string into the inquiry result. */ strcpy (temp_result, artec_vendor); strcat (temp_result, " "); strncpy (result + 8, temp_result, 8); } if (artec_model[0] != 0x0) { /* * 1) copy the model string to our temp variable * 2) append 16 spaces to make sure we have at least 16 characters * 3) copy our fudged model string into the inquiry result. */ strcpy (temp_result, artec_model); strcat (temp_result, " "); strncpy (result + 16, temp_result, 16); } /* are we really dealing with a scanner by ULTIMA/ARTEC? */ if ((strncmp (result + 8, "ULTIMA", 6) != 0) && (strncmp (result + 8, "ARTEC", 5) != 0)) { DBG (1, "attach: device doesn't look like a Artec/ULTIMA scanner\n"); strncpy (temp_result, result + 8, 8); temp_result[8] = 0x0; DBG (1, "attach: FOUND vendor = '%s'\n", temp_result); strncpy (temp_result, result + 16, 16); temp_result[16] = 0x0; DBG (1, "attach: FOUND model = '%s'\n", temp_result); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } /* turn this wait OFF for now since it appears to cause problems with */ /* AT12 models */ /* turned off by creating an "if" that can never be true */ if ( 1 == 2 ) { DBG (6, "attach: wait for scanner to come ready\n"); status = wait_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } /* This is the end of the "if" that can never be true that in effect */ /* comments out this wait_ready() call */ } /* end of "if( 1 == 2 )" */ dev = malloc (sizeof (*dev)); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); if (DBG_LEVEL >= 4) dump_inquiry ((unsigned char *) result); dev->sane.name = strdup (devname); /* get the model info */ str = malloc (17); memcpy (str, result + 16, 16); str[16] = ' '; t = str + 16; while ((*t == ' ') && (t > str)) { *t = '\0'; t--; } dev->sane.model = str; /* for some reason, the firmware revision is in the model info string on */ /* the A6000C PLUS scanners instead of in it's proper place */ if (strstr (str, "A6000C PLUS") == str) { str[11] = '\0'; strncpy (product_revision, str + 12, 4); } else if (strstr (str, "AT3") == str) { str[3] = '\0'; strncpy (product_revision, str + 8, 4); } else { /* get the product revision from it's normal place */ strncpy (product_revision, result + 32, 4); } product_revision[4] = ' '; t = strchr (product_revision, ' '); if (t) *t = '\0'; else t = "unknown revision"; /* get the vendor info */ str = malloc (9); memcpy (str, result + 8, 8); str[8] = ' '; t = strchr (str, ' '); *t = '\0'; dev->sane.vendor = str; DBG (5, "scanner vendor: '%s', model: '%s', revision: '%s'\n", dev->sane.vendor, dev->sane.model, product_revision); /* Artec docs say if bytes 36-43 = "ULTIMA ", then supports read cap. data */ if (strncmp (result + 36, "ULTIMA ", 8) == 0) { DBG (5, "scanner supports read capability data function\n"); dev->support_cap_data_retrieve = SANE_TRUE; } else { DBG (5, "scanner does NOT support read capability data function\n"); dev->support_cap_data_retrieve = SANE_FALSE; } DBG (6, "attach: getting scanner capability data\n"); status = artec_get_cap_data (dev, fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: artec_get_cap_data failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } sanei_scsi_close (fd); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return (SANE_STATUS_GOOD); } static SANE_Status init_options (ARTEC_Scanner * s) { int i; DBG (7, "init_options()\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[3]); /* horizontal resolution */ s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_X_RESOLUTION].constraint.word_list = s->hw->horz_resolution_list; s->val[OPT_X_RESOLUTION].w = 100; /* vertical resolution */ s->opt[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION; s->opt[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION; s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_Y_RESOLUTION; s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_Y_RESOLUTION].constraint.word_list = s->hw->vert_resolution_list; s->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; s->val[OPT_Y_RESOLUTION].w = 100; /* bind resolution */ s->opt[OPT_RESOLUTION_BIND].name = SANE_NAME_RESOLUTION_BIND; s->opt[OPT_RESOLUTION_BIND].title = SANE_TITLE_RESOLUTION_BIND; s->opt[OPT_RESOLUTION_BIND].desc = SANE_DESC_RESOLUTION_BIND; s->opt[OPT_RESOLUTION_BIND].type = SANE_TYPE_BOOL; s->val[OPT_RESOLUTION_BIND].w = SANE_TRUE; if (!(s->hw->flags & ARTEC_FLAG_SEPARATE_RES)) s->opt[OPT_RESOLUTION_BIND].cap |= SANE_CAP_INACTIVE; /* Preview Mode */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE; s->opt[OPT_PREVIEW].size = sizeof (SANE_Word); s->val[OPT_PREVIEW].w = SANE_FALSE; /* Grayscale Preview Mode */ s->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_GRAY_PREVIEW].unit = SANE_UNIT_NONE; s->opt[OPT_GRAY_PREVIEW].size = sizeof (SANE_Word); s->val[OPT_GRAY_PREVIEW].w = SANE_FALSE; /* negative */ s->opt[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; s->opt[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; s->opt[OPT_NEGATIVE].desc = "Negative Image"; s->opt[OPT_NEGATIVE].type = SANE_TYPE_BOOL; s->val[OPT_NEGATIVE].w = SANE_FALSE; if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE)) { s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; } /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = s->hw->x_range.min; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = s->hw->y_range.min; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range.max; /* Enhancement group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* filter mode */ s->opt[OPT_FILTER_TYPE].name = "filter-type"; s->opt[OPT_FILTER_TYPE].title = "Filter Type"; s->opt[OPT_FILTER_TYPE].desc = "Filter Type for mono scans"; s->opt[OPT_FILTER_TYPE].type = SANE_TYPE_STRING; s->opt[OPT_FILTER_TYPE].size = max_string_size (filter_type_list); s->opt[OPT_FILTER_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_FILTER_TYPE].constraint.string_list = filter_type_list; s->val[OPT_FILTER_TYPE].s = strdup (filter_type_list[0]); s->opt[OPT_FILTER_TYPE].cap |= SANE_CAP_INACTIVE; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &s->hw->brightness_range; s->val[OPT_CONTRAST].w = 0x80; if (!(s->hw->flags & ARTEC_FLAG_OPT_CONTRAST)) { s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; } /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->contrast_range; s->val[OPT_BRIGHTNESS].w = 0x80; if (!(s->hw->flags & ARTEC_FLAG_OPT_BRIGHTNESS)) { s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; } /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &s->hw->threshold_range; s->val[OPT_THRESHOLD].w = 0x80; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* halftone pattern */ s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE_PATTERN].size = max_string_size (halftone_pattern_list); s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_pattern_list; s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[1]); s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; /* pixel averaging */ s->opt[OPT_PIXEL_AVG].name = "pixel-avg"; s->opt[OPT_PIXEL_AVG].title = "Pixel Averaging"; s->opt[OPT_PIXEL_AVG].desc = "Enable HardWare Pixel Averaging function"; s->opt[OPT_PIXEL_AVG].type = SANE_TYPE_BOOL; s->val[OPT_PIXEL_AVG].w = SANE_FALSE; if (!(s->hw->flags & ARTEC_FLAG_PIXEL_AVERAGING)) { s->opt[OPT_PIXEL_AVG].cap |= SANE_CAP_INACTIVE; } /* lineart line edge enhancement */ s->opt[OPT_EDGE_ENH].name = "edge-enh"; s->opt[OPT_EDGE_ENH].title = "Line Edge Enhancement"; s->opt[OPT_EDGE_ENH].desc = "Enable HardWare Lineart Line Edge Enhancement"; s->opt[OPT_EDGE_ENH].type = SANE_TYPE_BOOL; s->val[OPT_EDGE_ENH].w = SANE_FALSE; s->opt[OPT_EDGE_ENH].cap |= SANE_CAP_INACTIVE; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR].wa = &(s->gamma_table[0][0]); s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->opt[OPT_GAMMA_VECTOR].size = s->gamma_length * sizeof (SANE_Word); /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_R].wa = &(s->gamma_table[1][0]); s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_R].size = s->gamma_length * sizeof (SANE_Word); /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_G].wa = &(s->gamma_table[2][0]); s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_G].size = s->gamma_length * sizeof (SANE_Word); /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_B].wa = &(s->gamma_table[3][0]); s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_B].size = s->gamma_length * sizeof (SANE_Word); if (s->hw->flags & ARTEC_FLAG_GAMMA_SINGLE) { s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } if (!(s->hw->flags & ARTEC_FLAG_GAMMA)) { s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; } /* transparency */ s->opt[OPT_TRANSPARENCY].name = "transparency"; s->opt[OPT_TRANSPARENCY].title = "Transparency"; s->opt[OPT_TRANSPARENCY].desc = "Use transparency adaptor"; s->opt[OPT_TRANSPARENCY].type = SANE_TYPE_BOOL; s->val[OPT_TRANSPARENCY].w = SANE_FALSE; /* ADF */ s->opt[OPT_ADF].name = "adf"; s->opt[OPT_ADF].title = "ADF"; s->opt[OPT_ADF].desc = "Use ADF"; s->opt[OPT_ADF].type = SANE_TYPE_BOOL; s->val[OPT_ADF].w = SANE_FALSE; /* Calibration group: */ s->opt[OPT_CALIBRATION_GROUP].title = "Calibration"; s->opt[OPT_CALIBRATION_GROUP].desc = ""; s->opt[OPT_CALIBRATION_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_CALIBRATION_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_CALIBRATION_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Calibrate Every Scan? */ s->opt[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL; s->opt[OPT_QUALITY_CAL].title = "Hardware Calibrate Every Scan"; s->opt[OPT_QUALITY_CAL].desc = "Perform hardware calibration on every scan"; s->opt[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL; s->val[OPT_QUALITY_CAL].w = SANE_FALSE; if (!(s->hw->flags & ARTEC_FLAG_CALIBRATE)) { s->opt[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE; } /* Perform Software Quality Calibration */ s->opt[OPT_SOFTWARE_CAL].name = "software-cal"; s->opt[OPT_SOFTWARE_CAL].title = "Software Color Calibration"; s->opt[OPT_SOFTWARE_CAL].desc = "Perform software quality calibration in " "addition to hardware calibration"; s->opt[OPT_SOFTWARE_CAL].type = SANE_TYPE_BOOL; s->val[OPT_SOFTWARE_CAL].w = SANE_FALSE; /* check for RGB calibration now because we have only implemented software */ /* calibration in conjunction with hardware RGB calibration */ if ((!(s->hw->flags & ARTEC_FLAG_CALIBRATE)) || (!(s->hw->flags & ARTEC_FLAG_CALIBRATE_RGB))) { s->opt[OPT_SOFTWARE_CAL].cap |= SANE_CAP_INACTIVE; } return (SANE_STATUS_GOOD); } static SANE_Status do_cancel (ARTEC_Scanner * s) { DBG (7, "do_cancel()\n"); s->scanning = SANE_FALSE; /* DAL: Terminate a three pass scan properly */ /* if (s->this_pass == 3) */ s->this_pass = 0; if ((s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) && (tmp_line_buf != NULL)) { artec_buffer_line_offset_free (); } if (s->fd >= 0) { sanei_scsi_close (s->fd); s->fd = -1; } return (SANE_STATUS_CANCELLED); } static SANE_Status attach_one (const char *dev) { DBG (7, "attach_one()\n"); attach (dev, 0); return (SANE_STATUS_GOOD); } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX], *cp; size_t len; FILE *fp; DBG_INIT (); DBG (1, "Artec/Ultima backend version %d.%d.%d, last mod: %s\n", ARTEC_MAJOR, ARTEC_MINOR, ARTEC_SUB, ARTEC_LAST_MOD); DBG (1, "http://www4.infi.net/~cpinkham/sane-artec-doc.html\n"); DBG (7, "sane_init()\n" ); devlist = 0; /* make sure these 2 are empty */ strcpy (artec_vendor, ""); strcpy (artec_model, ""); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); if (authorize) DBG (7, "sane_init(), authorize %s null\n", (authorize) ? "!=" : "=="); fp = sanei_config_open (ARTEC_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach ("/dev/scanner", 0); return (SANE_STATUS_GOOD); } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { cp = artec_skip_whitespace (dev_name); /* ignore line comments and blank lines */ if ((!*cp) || (*cp == '#')) continue; len = strlen (cp); /* ignore empty lines */ if (!len) continue; DBG (50, "%s line: '%s', len = %lu\n", ARTEC_CONFIG_FILE, cp, (u_long) len); /* check to see if they forced a vendor string in artec.conf */ if ((strncmp (cp, "vendor", 6) == 0) && isspace (cp[6])) { cp += 7; cp = artec_skip_whitespace (cp); strcpy (artec_vendor, cp); DBG (5, "sane_init: Forced vendor string '%s' in %s.\n", cp, ARTEC_CONFIG_FILE); } /* OK, maybe they forced the model string in artec.conf */ else if ((strncmp (cp, "model", 5) == 0) && isspace (cp[5])) { cp += 6; cp = artec_skip_whitespace (cp); strcpy (artec_model, cp); DBG (5, "sane_init: Forced model string '%s' in %s.\n", cp, ARTEC_CONFIG_FILE); } /* well, nothing else to do but attempt the attach */ else { sanei_config_attach_matching_devices (dev_name, attach_one); strcpy (artec_vendor, ""); strcpy (artec_model, ""); } } fclose (fp); return (SANE_STATUS_GOOD); } void sane_exit (void) { ARTEC_Device *dev, *next; DBG (7, "sane_exit()\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free (dev); } if (devlist) free (devlist); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { ARTEC_Device *dev; int i; DBG (7, "sane_get_devices( device_list, local_only = %d )\n", local_only ); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return (SANE_STATUS_GOOD); } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { SANE_Status status; ARTEC_Device *dev; ARTEC_Scanner *s; int i, j; DBG (7, "sane_open()\n"); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) return (status); } } else { /* empty devicname -> use first device */ dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->hw = dev; s->this_pass = 0; s->gamma_length = s->hw->gamma_length; s->gamma_range.min = 0; s->gamma_range.max = s->gamma_length - 1; s->gamma_range.quant = 0; /* not sure if I need this or not, it was in the umax backend though. :-) */ for (j = 0; j < s->gamma_length; ++j) { s->gamma_table[0][j] = j * (s->gamma_length - 1) / s->gamma_length; } for (i = 1; i < 4; i++) { for (j = 0; j < s->gamma_length; ++j) { s->gamma_table[i][j] = j; } } init_options (s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; if (s->hw->flags & ARTEC_FLAG_CALIBRATE) { status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "error opening scanner for initial calibration: %s\n", sane_strstatus (status)); s->fd = -1; return status; } status = artec_calibrate_shading (s); if (status != SANE_STATUS_GOOD) { DBG (1, "initial shading calibration failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return status; } sanei_scsi_close (s->fd); } return (SANE_STATUS_GOOD); } void sane_close (SANE_Handle handle) { ARTEC_Scanner *prev, *s; DBG (7, "sane_close()\n"); if ((DBG_LEVEL == 101) && (debug_fd > -1)) { close (debug_fd); DBG (101, "closed artec.data.raw output file\n"); } /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (1, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (s->scanning) do_cancel (handle); if (prev) prev->next = s->next; else first_handle = s->next; free (handle); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { ARTEC_Scanner *s = handle; DBG (7, "sane_get_option_descriptor()\n"); if (((unsigned) option >= NUM_OPTIONS) || (option < 0 )) return (0); return (s->opt + option); } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { ARTEC_Scanner *s = handle; SANE_Status status; SANE_Word w, cap; DBG (7, "sane_control_option()\n"); if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (s->this_pass) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { DBG (13, "sane_control_option %d, get value\n", option); switch (option) { /* word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_PREVIEW: case OPT_GRAY_PREVIEW: case OPT_RESOLUTION_BIND: case OPT_NEGATIVE: case OPT_TRANSPARENCY: case OPT_ADF: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_QUALITY_CAL: case OPT_SOFTWARE_CAL: case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_THRESHOLD: case OPT_CUSTOM_GAMMA: case OPT_PIXEL_AVG: case OPT_EDGE_ENH: *(SANE_Word *) val = s->val[option].w; return (SANE_STATUS_GOOD); /* string options: */ case OPT_MODE: case OPT_FILTER_TYPE: case OPT_HALFTONE_PATTERN: strcpy (val, s->val[option].s); return (SANE_STATUS_GOOD); /* word array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); return (SANE_STATUS_GOOD); } } else if (action == SANE_ACTION_SET_VALUE) { DBG (13, "sane_control_option %d, set value\n", option); if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return (status); switch (option) { /* (mostly) side-effect-free word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_BR_X: case OPT_BR_Y: case OPT_TL_X: case OPT_TL_Y: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_PREVIEW: case OPT_GRAY_PREVIEW: case OPT_QUALITY_CAL: case OPT_SOFTWARE_CAL: case OPT_NUM_OPTS: case OPT_NEGATIVE: case OPT_TRANSPARENCY: case OPT_ADF: case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_THRESHOLD: case OPT_PIXEL_AVG: case OPT_EDGE_ENH: s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_MODE: { if (s->val[option].s) free (s->val[option].s); s->val[option].s = (SANE_Char *) strdup (val); if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* options INvisible by default */ s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SOFTWARE_CAL].cap |= SANE_CAP_INACTIVE; s->opt[OPT_EDGE_ENH].cap |= SANE_CAP_INACTIVE; /* options VISIBLE by default */ s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_FILTER_TYPE].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE; if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) { /* Lineart mode */ s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; /* OFF */ s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; if (s->hw->flags & ARTEC_FLAG_ENHANCE_LINE_EDGE) s->opt[OPT_EDGE_ENH].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { /* Halftone mode */ if (s->hw->flags & ARTEC_FLAG_HALFTONE_PATTERN) s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) { /* Grayscale mode */ if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE)) { s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; } } else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) { /* Color mode */ s->opt[OPT_FILTER_TYPE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SOFTWARE_CAL].cap &= ~SANE_CAP_INACTIVE; if (!(s->hw->flags & ARTEC_FLAG_MBPP_NEGATIVE)) { s->opt[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE; } } } return (SANE_STATUS_GOOD); case OPT_FILTER_TYPE: case OPT_HALFTONE_PATTERN: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return (SANE_STATUS_GOOD); case OPT_RESOLUTION_BIND: if (s->val[option].w != *(SANE_Word *) val) { s->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } if (s->val[option].w == SANE_FALSE) { /* don't bind */ s->opt[OPT_Y_RESOLUTION].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_X_RESOLUTION; s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_X_RESOLUTION; } else { /* bind */ s->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; } } return (SANE_STATUS_GOOD); /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); return (SANE_STATUS_GOOD); /* options with side effects: */ case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == s->val[OPT_CUSTOM_GAMMA].w) return (SANE_STATUS_GOOD); s->val[OPT_CUSTOM_GAMMA].w = w; if (w) /* use custom_gamma_table */ { const char *mode = s->val[OPT_MODE].s; if ((strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) || (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) || (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0)) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; if (!(s->hw->flags & ARTEC_FLAG_GAMMA_SINGLE)) { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } } else /* don't use custom_gamma_table */ { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return (SANE_STATUS_GOOD); } } return (SANE_STATUS_INVAL); } static void set_pass_parameters (SANE_Handle handle) { ARTEC_Scanner *s = handle; DBG (7, "set_pass_parameters()\n"); if (s->threepasscolor) { s->this_pass += 1; DBG (9, "set_pass_parameters: three-pass, on %d\n", s->this_pass); switch (s->this_pass) { case 1: s->params.format = SANE_FRAME_RED; s->params.last_frame = SANE_FALSE; break; case 2: s->params.format = SANE_FRAME_GREEN; s->params.last_frame = SANE_FALSE; break; case 3: s->params.format = SANE_FRAME_BLUE; s->params.last_frame = SANE_TRUE; break; default: DBG (9, "set_pass_parameters: What?!? pass %d = filter?\n", s->this_pass); break; } } else s->this_pass = 0; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { ARTEC_Scanner *s = handle; DBG (7, "sane_get_parameters()\n"); if (!s->scanning) { double width, height; memset (&s->params, 0, sizeof (s->params)); s->x_resolution = s->val[OPT_X_RESOLUTION].w; s->y_resolution = s->val[OPT_Y_RESOLUTION].w; if ((s->val[OPT_RESOLUTION_BIND].w == SANE_TRUE) || (s->val[OPT_PREVIEW].w == SANE_TRUE)) { s->y_resolution = s->x_resolution; } s->tl_x = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH * s->x_resolution; s->tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH * s->y_resolution; width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); if ((s->x_resolution > 0.0) && (s->y_resolution > 0.0) && (width > 0.0) && (height > 0.0)) { s->params.pixels_per_line = width * s->x_resolution / MM_PER_INCH + 1; s->params.lines = height * s->y_resolution / MM_PER_INCH + 1; } s->onepasscolor = SANE_FALSE; s->threepasscolor = SANE_FALSE; s->params.last_frame = SANE_TRUE; if ((s->val[OPT_PREVIEW].w == SANE_TRUE) && (s->val[OPT_GRAY_PREVIEW].w == SANE_TRUE)) { s->mode = SANE_VALUE_SCAN_MODE_GRAY; } else { s->mode = s->val[OPT_MODE].s; } if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) || (strcmp (s->mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; s->params.depth = 1; s->line_offset = 0; /* round pixels_per_line up to the next full byte of pixels */ /* this way we don't have to do bit buffering, pixels_per_line is */ /* what is used in the set window command. */ /* SANE expects the last byte in a line to be padded if it's not */ /* full, so this should not affect scans in a negative way */ s->params.pixels_per_line = s->params.bytes_per_line * 8; } else if (strcmp (s->mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; s->line_offset = 0; } else { s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; if (s->hw->flags & ARTEC_FLAG_ONE_PASS_SCANNER) { s->onepasscolor = SANE_TRUE; s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line *= 3; /* * line offsets from documentation. * (I don't yet see a common formula I can easily use) */ /* FIXME: figure out a cleaner way to do this... */ s->line_offset = 0; /* default */ if ((!strcmp (s->hw->sane.model, "AT3")) || (!strcmp (s->hw->sane.model, "A6000C")) || (!strcmp (s->hw->sane.model, "A6000C PLUS")) || (!strcmp (s->hw->sane.model, "AT6"))) { /* formula #1 */ /* ranges from 1 at 50dpi to 16 at 600dpi */ s->line_offset = 8 * (s->y_resolution / 300.0); } else if (!strcmp (s->hw->sane.model, "AT12")) { /* formula #2 */ /* ranges from 0 at 25dpi to 16 at 1200dpi */ /***********************************************************/ /* this should be handled in hardware for now, so leave it */ /* sitting at zero for now. */ /***********************************************************/ /* s->line_offset = 16 * ( s->y_resolution / 1200.0 ); */ } else if (!strcmp (s->hw->sane.model, "AM12S")) { /* formula #3 */ /* ranges from 0 at 50dpi to 8 at 1200dpi */ s->line_offset = 8 * (s->y_resolution / 1200.0); } } else { s->params.last_frame = SANE_FALSE; s->threepasscolor = SANE_TRUE; s->line_offset = 0; } } } if (params) *params = s->params; return (SANE_STATUS_GOOD); } SANE_Status sane_start (SANE_Handle handle) { ARTEC_Scanner *s = handle; SANE_Status status; DBG (7, "sane_start()\n"); if (debug_fd != -1) { close (debug_fd); debug_fd = -1; } if (DBG_LEVEL == 101) { debug_fd = open ("artec.data.raw", O_WRONLY | O_CREAT | O_TRUNC, 0666); if (debug_fd > -1) DBG (101, "opened artec.data.raw output file\n"); } /* First make sure we have a current parameter set. Some of the */ /* parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; /* DAL: For 3 pass colour set the current pass parameters */ if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && s->threepasscolor) set_pass_parameters (s); /* DAL: For single pass scans and the first pass of a 3 pass scan */ if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || (!s->threepasscolor) || ((s->threepasscolor) && (s->this_pass == 1))) { if (s->hw->flags & ARTEC_FLAG_SENSE_HANDLER) { status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, (void *)s); } else { status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0); } if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return status; } /* DB added wait_ready */ status = wait_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "wait for scanner ready failed: %s\n", sane_strstatus (status)); return status; } } s->bytes_to_read = s->params.bytes_per_line * s->params.lines; DBG (9, "%d pixels per line, %d bytes, %d lines high, xdpi = %d, " "ydpi = %d, btr = %lu\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, s->x_resolution, s->y_resolution, (u_long) s->bytes_to_read); /* DAL: For single pass scans and the first pass of a 3 pass scan */ if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || !s->threepasscolor || (s->threepasscolor && s->this_pass == 1)) { /* do a calibrate if scanner requires/recommends it */ if ((s->hw->flags & ARTEC_FLAG_CALIBRATE) && (s->val[OPT_QUALITY_CAL].w == SANE_TRUE)) { status = artec_calibrate_shading (s); if (status != SANE_STATUS_GOOD) { DBG (1, "shading calibration failed: %s\n", sane_strstatus (status)); return status; } } /* DB added wait_ready */ status = wait_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "wait for scanner ready failed: %s\n", sane_strstatus (status)); return status; } /* send the custom gamma table if we have one */ if (s->hw->flags & ARTEC_FLAG_GAMMA) artec_send_gamma_table (s); /* now set our scan window */ status = artec_set_scan_window (s); if (status != SANE_STATUS_GOOD) { DBG (1, "set scan window failed: %s\n", sane_strstatus (status)); return status; } /* DB added wait_ready */ status = wait_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "wait for scanner ready failed: %s\n", sane_strstatus (status)); return status; } } /* now we can start the actual scan */ /* DAL: For single pass scans and the first pass of a 3 pass scan */ if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || (!s->threepasscolor) || (s->this_pass == 1)) { /* DAL - do mode select before each scan */ /* The mode is NOT turned off at the end of the scan */ artec_mode_select (s); status = artec_start_scan (s); if (status != SANE_STATUS_GOOD) { DBG (1, "start scan: %s\n", sane_strstatus (status)); return status; } } s->scanning = SANE_TRUE; return (SANE_STATUS_GOOD); } #if 0 static void binout (SANE_Byte byte) { SANE_Byte b = byte; int bit; for (bit = 0; bit < 8; bit++) { DBG (9, "%d", b & 128 ? 1 : 0); b = b << 1; } } #endif static SANE_Status artec_sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { ARTEC_Scanner *s = handle; SANE_Status status; size_t nread; size_t lread; size_t bytes_read; size_t rows_read; size_t max_read_rows; size_t max_ret_rows; size_t remaining_rows; size_t rows_available; size_t line; SANE_Byte temp_buf[ARTEC_MAX_READ_SIZE]; SANE_Byte line_buf[ARTEC_MAX_READ_SIZE]; DBG (7, "artec_sane_read( %p, %p, %d, %d )\n", handle, buf, max_len, *len); *len = 0; if (s->bytes_to_read == 0) { if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) || !s->threepasscolor || (s->threepasscolor && s->this_pass == 3)) { do_cancel (s); /* without this a 4th pass is attempted, yet do_cancel does this */ s->scanning = SANE_FALSE; } return (SANE_STATUS_EOF); } if (!s->scanning) return do_cancel (s); remaining_rows = (s->bytes_to_read + s->params.bytes_per_line - 1) / s->params.bytes_per_line; max_read_rows = s->hw->max_read_size / s->params.bytes_per_line; max_ret_rows = max_len / s->params.bytes_per_line; while (artec_get_status (s->fd) == 0) { DBG (120, "hokey loop till data available\n"); usleep (50000); /* sleep for .05 second */ } rows_read = 0; bytes_read = 0; while ((rows_read < max_ret_rows) && (rows_read < remaining_rows)) { DBG (50, "top of while loop, rr = %lu, mrr = %lu, rem = %lu\n", (u_long) rows_read, (u_long) max_ret_rows, (u_long) remaining_rows); if (s->bytes_to_read - bytes_read <= s->params.bytes_per_line * max_read_rows) { nread = s->bytes_to_read - bytes_read; } else { nread = s->params.bytes_per_line * max_read_rows; } lread = nread / s->params.bytes_per_line; if ((max_read_rows - rows_read) < lread) { lread = max_read_rows - rows_read; nread = lread * s->params.bytes_per_line; } if ((max_ret_rows - rows_read) < lread) { lread = max_ret_rows - rows_read; nread = lread * s->params.bytes_per_line; } while ((rows_available = artec_get_status (s->fd)) == 0) { DBG (120, "hokey loop till data available\n"); usleep (50000); /* sleep for .05 second */ } if (rows_available < lread) { lread = rows_available; nread = lread * s->params.bytes_per_line; } /* This should never happen, but just in case... */ if (nread > (s->bytes_to_read - bytes_read)) { nread = s->bytes_to_read - bytes_read; lread = 1; } DBG (50, "rows_available = %lu, params.lines = %d, bytes_per_line = %d\n", (u_long) rows_available, s->params.lines, s->params.bytes_per_line); DBG (50, "bytes_to_read = %lu, max_len = %d, max_rows = %lu\n", (u_long) s->bytes_to_read, max_len, (u_long) max_ret_rows); DBG (50, "nread = %lu, lread = %lu, bytes_read = %lu, rows_read = %lu\n", (u_long) nread, (u_long) lread, (u_long) bytes_read, (u_long) rows_read); status = read_data (s->fd, ARTEC_DATA_IMAGE, temp_buf, &nread); if (status != SANE_STATUS_GOOD) { end_scan (s); do_cancel (s); return (SANE_STATUS_IO_ERROR); } if ((DBG_LEVEL == 101) && (debug_fd > -1)) { write (debug_fd, temp_buf, nread); } if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && (s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET)) { for (line = 0; line < lread; line++) { memcpy (line_buf, temp_buf + (line * s->params.bytes_per_line), s->params.bytes_per_line); nread = s->params.bytes_per_line; artec_buffer_line_offset (s, s->line_offset, line_buf, &nread); if (nread > 0) { if (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT) { artec_line_rgb_to_byte_rgb (line_buf, s->params.pixels_per_line); } if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) { artec_reverse_line (s, line_buf); } /* do software calibration if necessary */ if (s->val[OPT_SOFTWARE_CAL].w) { artec_software_rgb_calibrate (s, line_buf, 1); } memcpy (buf + bytes_read, line_buf, s->params.bytes_per_line); bytes_read += nread; rows_read++; } } } else { if ((s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) || ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT))) { for (line = 0; line < lread; line++) { if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) && (s->hw->flags & ARTEC_FLAG_RGB_CHAR_SHIFT)) { artec_line_rgb_to_byte_rgb (temp_buf + (line * s->params.bytes_per_line), s->params.pixels_per_line); } if (s->hw->flags & ARTEC_FLAG_IMAGE_REV_LR) { artec_reverse_line (s, temp_buf + (line * s->params.bytes_per_line)); } } } /* do software calibration if necessary */ if ((s->val[OPT_SOFTWARE_CAL].w) && (strcmp (s->mode, SANE_VALUE_SCAN_MODE_COLOR) == 0)) { artec_software_rgb_calibrate (s, temp_buf, lread); } memcpy (buf + bytes_read, temp_buf, nread); bytes_read += nread; rows_read += lread; } } *len = bytes_read; s->bytes_to_read -= bytes_read; DBG (9, "artec_sane_read() returning, we read %lu bytes, %lu left\n", (u_long) * len, (u_long) s->bytes_to_read); if ((s->bytes_to_read == 0) && (s->hw->flags & ARTEC_FLAG_RGB_LINE_OFFSET) && (tmp_line_buf != NULL)) { artec_buffer_line_offset_free (); } return (SANE_STATUS_GOOD); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { ARTEC_Scanner *s = handle; SANE_Status status; int bytes_to_copy; int loop; static SANE_Byte temp_buf[ARTEC_MAX_READ_SIZE]; static int bytes_in_buf = 0; DBG (7, "sane_read( %p, %p, %d, %d )\n", handle, buf, max_len, *len); DBG (9, "sane_read: bib = %d, ml = %d\n", bytes_in_buf, max_len); if (bytes_in_buf != 0) { bytes_to_copy = max_len < bytes_in_buf ? max_len : bytes_in_buf; } else { status = artec_sane_read (s, temp_buf, s->hw->max_read_size, len); if (status != SANE_STATUS_GOOD) { return (status); } bytes_in_buf = *len; if (*len == 0) { return (SANE_STATUS_GOOD); } bytes_to_copy = max_len < s->hw->max_read_size ? max_len : s->hw->max_read_size; bytes_to_copy = *len < bytes_to_copy ? *len : bytes_to_copy; } memcpy (buf, temp_buf, bytes_to_copy); bytes_in_buf -= bytes_to_copy; *len = bytes_to_copy; DBG (9, "sane_read: btc = %d, bib now = %d\n", bytes_to_copy, bytes_in_buf); for (loop = 0; loop < bytes_in_buf; loop++) { temp_buf[loop] = temp_buf[loop + bytes_to_copy]; } return (SANE_STATUS_GOOD); } void sane_cancel (SANE_Handle handle) { ARTEC_Scanner *s = handle; DBG (7, "sane_cancel()\n"); if (s->scanning) { s->scanning = SANE_FALSE; abort_scan (s); do_cancel (s); } } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (7, "sane_set_io_mode( %p, %d )\n", handle, non_blocking); return (SANE_STATUS_UNSUPPORTED); } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (7, "sane_get_select_fd( %p, %d )\n", handle, *fd ); return (SANE_STATUS_UNSUPPORTED); } sane-backends-1.0.27/backend/canon_dr-cmd.h0000664000175000017500000005246113063340146015316 00000000000000#ifndef CANON_DR_CMD_H #define CANON_DR_CMD_H /* * Part of SANE - Scanner Access Now Easy. * Please see opening comments in canon_dr.c */ /****************************************************/ #define USB_HEADER_LEN 12 #define USB_COMMAND_LEN 12 #define USB_STATUS_LEN 4 #define USB_COMMAND_TIME 30000 #define USB_DATA_TIME 30000 #define USB_STATUS_TIME 30000 /*static inline void */ static void setbitfield (unsigned char *pageaddr, int mask, int shift, int val) { *pageaddr = (*pageaddr & ~(mask << shift)) | ((val & mask) << shift); } /* ------------------------------------------------------------------------- */ /*static inline int */ static int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* ------------------------------------------------------------------------- */ static int getnbyte (unsigned char *pnt, int nbytes) { unsigned int result = 0; int i; #ifdef DEBUG assert (nbytes < 5); #endif for (i = 0; i < nbytes; i++) result = (result << 8) | (pnt[i] & 0xff); return result; } /* ------------------------------------------------------------------------- */ /*static inline void */ static void putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) { int i; #ifdef DEBUG assert (nbytes < 5); #endif for (i = nbytes - 1; i >= 0; i--) { pnt[i] = value & 0xff; value = value >> 8; } } /* ==================================================================== */ /* extended status packet */ #define get_ES_length(b) getnbyte(b+0x04, 4) /* ==================================================================== */ /* SCSI commands */ #define set_SCSI_opcode(out, val) out[0]=val #define set_SCSI_lun(out, val) setbitfield(out + 1, 7, 5, val) /* ==================================================================== */ /* TEST_UNIT_READY */ #define TEST_UNIT_READY_code 0x00 #define TEST_UNIT_READY_len 6 /* ==================================================================== */ /* REQUEST_SENSE */ #define REQUEST_SENSE_code 0x03 #define REQUEST_SENSE_len 6 #define RS_return_size 0x0e #define set_RS_return_size(icb,val) icb[0x04]=val /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) /* normally 0 */ #define get_RS_additional_length(b) b[0x07] /* always 6? */ #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /* valid=0 */ #define get_RS_SKSB(b) getnbyte(b+0x0f, 3) /* when RS is 0x05/0x26 bad bytes listed in sksb */ /* #define get_RS_offending_byte(b) getnbyte(b+0x10, 2) */ /* ==================================================================== */ /* INQUIRY */ #define INQUIRY_code 0x12 #define INQUIRY_len 6 #define INQUIRY_std_len 0x30 #define INQUIRY_vpd_len 0x1e #define set_IN_evpd(icb, val) setbitfield(icb + 1, 1, 0, val) #define set_IN_page_code(icb, val) icb[0x02]=val #define set_IN_return_size(icb,val) icb[0x04]=val #define get_IN_periph_qual(in) getbitfield(in, 0x07, 5) #define IN_periph_qual_lun 0x00 #define IN_periph_qual_nolun 0x03 #define get_IN_periph_devtype(in) getbitfield(in, 0x1f, 0) #define IN_periph_devtype_scanner 0x06 #define IN_periph_devtype_unknown 0x1f #define get_IN_response_format(in) getbitfield(in + 0x03, 0x07, 0) #define IN_recognized 0x02 #define get_IN_vendor(in, buf) strncpy(buf, (char *)in + 0x08, 0x08) #define get_IN_product(in, buf) strncpy(buf, (char *)in + 0x10, 0x010) #define get_IN_version(in, buf) strncpy(buf, (char *)in + 0x20, 0x04) /* the VPD response */ #define get_IN_page_length(in) in[0x04] #define get_IN_basic_x_res(in) getnbyte(in + 0x05, 2) #define get_IN_basic_y_res(in) getnbyte(in + 0x07, 2) #define get_IN_step_x_res(in) getbitfield(in+0x09, 1, 0) #define get_IN_step_y_res(in) getbitfield(in+0x09, 1, 4) #define get_IN_max_x_res(in) getnbyte(in + 0x0a, 2) #define get_IN_max_y_res(in) getnbyte(in + 0x0c, 2) #define get_IN_min_x_res(in) getnbyte(in + 0x0e, 2) #define get_IN_min_y_res(in) getnbyte(in + 0x10, 2) #define get_IN_std_res_60(in) getbitfield(in+ 0x12, 1, 7) #define get_IN_std_res_75(in) getbitfield(in+ 0x12, 1, 6) #define get_IN_std_res_100(in) getbitfield(in+ 0x12, 1, 5) #define get_IN_std_res_120(in) getbitfield(in+ 0x12, 1, 4) #define get_IN_std_res_150(in) getbitfield(in+ 0x12, 1, 3) #define get_IN_std_res_160(in) getbitfield(in+ 0x12, 1, 2) #define get_IN_std_res_180(in) getbitfield(in+ 0x12, 1, 1) #define get_IN_std_res_200(in) getbitfield(in+ 0x12, 1, 0) #define get_IN_std_res_240(in) getbitfield(in+ 0x13, 1, 7) #define get_IN_std_res_300(in) getbitfield(in+ 0x13, 1, 6) #define get_IN_std_res_320(in) getbitfield(in+ 0x13, 1, 5) #define get_IN_std_res_400(in) getbitfield(in+ 0x13, 1, 4) #define get_IN_std_res_480(in) getbitfield(in+ 0x13, 1, 3) #define get_IN_std_res_600(in) getbitfield(in+ 0x13, 1, 2) #define get_IN_std_res_800(in) getbitfield(in+ 0x13, 1, 1) #define get_IN_std_res_1200(in) getbitfield(in+ 0x13, 1, 0) #define get_IN_window_width(in) getnbyte(in + 0x14, 4) #define get_IN_window_length(in) getnbyte(in + 0x18, 4) #define get_IN_awd(in) getbitfield(in+0x1c, 1, 7) #define get_IN_ce_emphasis(in) getbitfield(in+0x1c, 1, 6) #define get_IN_c_emphasis(in) getbitfield(in+0x1c, 1, 5) #define get_IN_high_quality(in) getbitfield(in+0x1c, 1, 4) #define get_IN_multilevel(in) getbitfield(in+0x1c, 1, 3) #define get_IN_half_tone(in) getbitfield(in+0x1c, 1, 2) #define get_IN_monochrome(in) getbitfield(in+0x1c, 1, 1) #define get_IN_overflow(in) getbitfield(in+0x1c, 1, 0) /* some scanners need evpd inquiry data manipulated */ #define set_IN_page_length(in,val) in[0x04]=val /* ==================================================================== */ /* RESERVE_UNIT */ #define RESERVE_UNIT_code 0x16 #define RESERVE_UNIT_len 6 /* ==================================================================== */ /* RELEASE_UNIT */ #define RELEASE_UNIT_code 0x17 #define RELEASE_UNIT_len 6 /* ==================================================================== */ /* SCAN */ #define SCAN_code 0x1b #define SCAN_len 6 #define set_SC_xfer_length(sb, val) sb[0x04] = (unsigned char)val /* ==================================================================== */ /* SET_WINDOW */ #define SET_WINDOW_code 0x24 #define SET_WINDOW_len 10 #define set_SW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) #define SW_header_len 8 #define SW_desc_len 0x2c /* ==================================================================== */ /* GET_WINDOW */ #define GET_WINDOW_code 0x25 #define GET_WINDOW_len 0 /* ==================================================================== */ /* READ/SEND page codes */ #define SR_datatype_image 0x00 #define SR_datatype_lut 0x03 #define SR_datatype_pixelsize 0x80 /*DR-G1130*/ #define SR_datatype_panel 0x84 #define SR_datatype_sensors 0x8b #define SR_datatype_counters 0x8c #define SR_datatype_endorser 0x90 #define SR_datatype_fineoffset 0x90 #define SR_datatype_finegain 0x91 /* ==================================================================== */ /* READ */ #define READ_code 0x28 #define READ_len 10 #define set_R_datatype_code(sb, val) sb[0x02] = val #define set_R_xfer_uid(sb, val) sb[4] = val #define set_R_xfer_lid(sb, val) sb[5] = val #define set_R_xfer_length(sb, val) putnbyte(sb + 0x06, val, 3) /*image needs no macros?*/ /*lut unread?*/ /*panel*/ #define R_PANEL_len 0x08 #define get_R_PANEL_start(in) getbitfield(in, 1, 7) #define get_R_PANEL_stop(in) getbitfield(in, 1, 6) #define get_R_PANEL_butt3(in) getbitfield(in, 1, 2) #define get_R_PANEL_new_file(in) getbitfield(in+1, 1, 0) #define get_R_PANEL_count_only(in) getbitfield(in+1, 1, 1) #define get_R_PANEL_bypass_mode(in) getbitfield(in+1, 1, 2) #define get_R_PANEL_enable_led(in) getbitfield(in+2, 1, 0) #define get_R_PANEL_counter(in) getnbyte(in + 0x04, 4) /*sensors*/ #define R_SENSORS_len 0x01 #define get_R_SENSORS_card(in) getbitfield(in, 1, 3) #define get_R_SENSORS_adf(in) getbitfield(in, 1, 0) /*counters*/ #define R_COUNTERS_len 0x80 #define get_R_COUNTERS_scans(in) getnbyte(in + 0x04, 4) /*endorser unread?*/ /*fine gain*/ #define R_FINE_uid_gray 0x07 #define R_FINE_uid_red 0x0c #define R_FINE_uid_green 0x0a #define R_FINE_uid_blue 0x09 #define R_FINE_uid_unknown 0x14 /* ==================================================================== */ /* SEND */ #define SEND_code 0x2a #define SEND_len 10 #define set_S_xfer_datatype(sb, val) sb[0x02] = (unsigned char)val #define set_S_xfer_id(sb, val) putnbyte(sb + 4, val, 2) #define set_S_xfer_length(sb, val) putnbyte(sb + 6, val, 3) /*lut*/ #define S_LUT_len 0x100 #define S_LUT_id_front 0x82 #define S_LUT_id_unk1 0x84 #define S_LUT_id_unk2 0x88 #define S_LUT_id_unk3 0x90 /*panel*/ #define S_PANEL_len 0x08 #define set_S_PANEL_enable_led(in,val) setbitfield(in+2, 1, 0, val) #define set_S_PANEL_counter(sb,val) putnbyte(sb + 0x04, val, 4) /*counters*/ /*endorser*/ /* ==================================================================== */ /* OBJECT_POSITION */ #define OBJECT_POSITION_code 0x31 #define OBJECT_POSITION_len 10 #define set_OP_autofeed(b,val) setbitfield(b+0x01, 0x07, 0, val) #define OP_Discharge 0x00 #define OP_Feed 0x01 /* ==================================================================== */ /* Page codes used by GET/SET SCAN MODE */ #define SM_pc_adf 0x01 #define SM_pc_tpu 0x02 #define SM_pc_scan_ctl 0x20 #define SM_pc_df 0x30 #define SM_pc_buffer 0x32 #define SM_pc_imprinter 0x34 #define SM_pc_dropout 0x36 #define SM_pc_unknown 0x37 #define SM_pc_all_pc 0x3F /* ==================================================================== */ /* GET SCAN MODE */ #define GET_SCAN_MODE_code 0xd5 #define GET_SCAN_MODE_len 6 #define set_GSM_unknown(sb, val) sb[0x01] = val #define set_GSM_page_code(sb, val) sb[0x02] = val #define set_GSM_len(sb, val) sb[0x04] = val #define GSM_PSIZE_len 0x5a /* ==================================================================== */ /* SET SCAN MODE */ #define SET_SCAN_MODE_code 0xd6 #define SET_SCAN_MODE_len 6 #define set_SSM_pf(sb, val) setbitfield(sb + 1, 1, 4, val) #define set_SSM_pay_len(sb, val) sb[0x04] = val /* the payload */ #define SSM_PAY_len 0x14 #define SSM_PAY_HEAD_len 0x13 #define set_SSM_pay_head_len(sb, val) sb[0x01] = val #define set_SSM_page_code(sb, val) sb[0x04] = val #define SSM_PAGE_len 0x0e #define set_SSM_page_len(sb, val) sb[0x05] = val /* for DF (0x30) page */ #define set_SSM_DF_deskew_roll(sb, val) setbitfield(sb+7, 1, 5, val) #define set_SSM_DF_staple(sb, val) setbitfield(sb+7, 1, 4, val) #define set_SSM_DF_thick(sb, val) setbitfield(sb+7, 1, 2, val) #define set_SSM_DF_len(sb, val) setbitfield(sb+7, 1, 0, val) #define set_SSM_DF_textdir(sb, val) setbitfield(sb+9, 0xf, 0, val) /* for BUFFER (0x32) page */ #define set_SSM_BUFF_duplex(sb, val) setbitfield(sb+6, 1, 1, val) #define set_SSM_BUFF_unk(sb, val) sb[0x07] = val #define set_SSM_BUFF_async(sb, val) setbitfield(sb+0x0a, 1, 6, val) #define set_SSM_BUFF_ald(sb, val) setbitfield(sb+0x0a, 1, 5, val) #define set_SSM_BUFF_fb(sb, val) setbitfield(sb+0x0a, 1, 4, val) #define set_SSM_BUFF_card(sb, val) setbitfield(sb+0x0a, 1, 3, val) /* for DO (0x36) page */ #define SSM_DO_none 0 #define SSM_DO_red 1 #define SSM_DO_green 2 #define SSM_DO_blue 3 #define set_SSM_DO_unk1(sb, val) sb[0x07] = val #define set_SSM_DO_unk2(sb, val) sb[0x09] = val #define set_SSM_DO_f_do(sb, val) sb[0x0b] = val #define set_SSM_DO_b_do(sb, val) sb[0x0c] = val #define set_SSM_DO_f_en(sb, val) sb[0x0d] = val #define set_SSM_DO_b_en(sb, val) sb[0x0e] = val /* ==================================================================== */ /* Cancel */ #define CANCEL_code 0xd8 #define CANCEL_len 6 /* ==================================================================== */ /* Coarse Calibration */ #define COR_CAL_code 0xe1 #define COR_CAL_len 10 #define set_CC_version(sb, val) sb[5] = val #define set_CC_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) /* the payload */ #define CC_pay_len 0x20 #define CC_pay_ver 0x00 #define set_CC_f_gain(sb, val) sb[0] = val #define set_CC_unk1(sb, val) sb[1] = val #define set_CC_f_offset(sb, val) sb[2] = val #define set_CC_unk2(sb, val) sb[3] = val #define set_CC_exp_f_r1(sb, val) putnbyte(sb + 0x04, val, 2) #define set_CC_exp_f_g1(sb, val) putnbyte(sb + 0x06, val, 2) #define set_CC_exp_f_b1(sb, val) putnbyte(sb + 0x08, val, 2) #define set_CC_exp_f_r2(sb, val) putnbyte(sb + 0x0a, val, 2) #define set_CC_exp_f_g2(sb, val) putnbyte(sb + 0x0c, val, 2) #define set_CC_exp_f_b2(sb, val) putnbyte(sb + 0x0e, val, 2) #define set_CC_b_gain(sb, val) sb[0x10] = val #define set_CC_b_offset(sb, val) sb[0x12] = val #define set_CC_exp_b_r1(sb, val) putnbyte(sb + 0x14, val, 2) #define set_CC_exp_b_g1(sb, val) putnbyte(sb + 0x16, val, 2) #define set_CC_exp_b_b1(sb, val) putnbyte(sb + 0x18, val, 2) #define set_CC_exp_b_r2(sb, val) putnbyte(sb + 0x1a, val, 2) #define set_CC_exp_b_g2(sb, val) putnbyte(sb + 0x1c, val, 2) #define set_CC_exp_b_b2(sb, val) putnbyte(sb + 0x1e, val, 2) /* the 'version 3' payload (P-208 and P-215) */ #define CC3_pay_len 0x28 #define CC3_pay_ver 0x03 #define set_CC3_gain_f_r(sb, val) sb[0] = val #define set_CC3_gain_f_g(sb, val) sb[1] = val #define set_CC3_gain_f_b(sb, val) sb[2] = val #define set_CC3_off_f_r(sb, val) sb[4] = val #define set_CC3_off_f_g(sb, val) sb[5] = val #define set_CC3_off_f_b(sb, val) sb[6] = val #define set_CC3_exp_f_r(sb, val) putnbyte(sb + 0x08, val, 2) #define set_CC3_exp_f_g(sb, val) putnbyte(sb + 0x0a, val, 2) #define set_CC3_exp_f_b(sb, val) putnbyte(sb + 0x0c, val, 2) #define set_CC3_gain_b_r(sb, val) sb[0x14] = val #define set_CC3_gain_b_g(sb, val) sb[0x15] = val #define set_CC3_gain_b_b(sb, val) sb[0x16] = val #define set_CC3_off_b_r(sb, val) sb[0x18] = val #define set_CC3_off_b_g(sb, val) sb[0x19] = val #define set_CC3_off_b_b(sb, val) sb[0x1a] = val #define set_CC3_exp_b_r(sb, val) putnbyte(sb + 0x1c, val, 2) #define set_CC3_exp_b_g(sb, val) putnbyte(sb + 0x1e, val, 2) #define set_CC3_exp_b_b(sb, val) putnbyte(sb + 0x20, val, 2) /* ==================================================================== */ /* Page codes used by GET/SET SCAN MODE 2 */ #define SM2_pc_df 0x00 #define SM2_pc_ultra 0x01 #define SM2_pc_buffer 0x02 #define SM2_pc_dropout 0x06 /* ==================================================================== */ /* SET SCAN MODE 2 */ #define SET_SCAN_MODE2_code 0xe5 #define SET_SCAN_MODE2_len 12 #define set_SSM2_page_code(sb, val) sb[0x02] = val #define set_SSM2_pay_len(sb, val) sb[0x08] = val /* the payload */ #define SSM2_PAY_len 0x10 /* for DF (0x00) page */ #define set_SSM2_DF_thick(sb, val) setbitfield(sb+3, 1, 2, val) #define set_SSM2_DF_len(sb, val) setbitfield(sb+3, 1, 0, val) /* for ULTRA (0x01) page */ #define set_SSM2_ULTRA_top(sb, val) putnbyte(sb + 0x07, val, 2) #define set_SSM2_ULTRA_bot(sb, val) putnbyte(sb + 0x09, val, 2) /* for BUFFER (0x02) page */ #define set_SSM2_BUFF_unk(sb, val) sb[0x03] = val #define set_SSM2_BUFF_unk2(sb, val) sb[0x06] = val #define set_SSM2_BUFF_sync(sb, val) sb[0x09] = val /* for DROPOUT (0x06) page */ #define set_SSM2_DO_do(sb, val) sb[0x09] = val #define set_SSM2_DO_en(sb, val) sb[0x0a] = val /* ==================================================================== */ /* window descriptor macros for SET_WINDOW and GET_WINDOW */ #define set_WPDB_wdblen(sb, len) putnbyte(sb + 0x06, len, 2) /* ==================================================================== */ /* 0x00 - Window Identifier */ #define set_WD_wid(sb, val) sb[0] = val #define WD_wid_front 0x00 #define WD_wid_back 0x01 /* 0x01 - Reserved (bits 7-1), AUTO (bit 0) */ #define set_WD_auto(sb, val) setbitfield(sb + 0x01, 1, 0, val) #define get_WD_auto(sb) getbitfield(sb + 0x01, 1, 0) /* 0x02,0x03 - X resolution in dpi */ #define set_WD_Xres(sb, val) putnbyte(sb + 0x02, val, 2) #define get_WD_Xres(sb) getnbyte(sb + 0x02, 2) /* 0x04,0x05 - Y resolution in dpi */ #define set_WD_Yres(sb, val) putnbyte(sb + 0x04, val, 2) #define get_WD_Yres(sb) getnbyte(sb + 0x04, 2) /* 0x06-0x09 - Upper Left X in 1/1200 inch */ #define set_WD_ULX(sb, val) putnbyte(sb + 0x06, val, 4) #define get_WD_ULX(sb) getnbyte(sb + 0x06, 4) /* 0x0a-0x0d - Upper Left Y in 1/1200 inch */ #define set_WD_ULY(sb, val) putnbyte(sb + 0x0a, val, 4) #define get_WD_ULY(sb) getnbyte(sb + 0x0a, 4) /* 0x0e-0x11 - Width in 1/1200 inch */ #define set_WD_width(sb, val) putnbyte(sb + 0x0e, val, 4) #define get_WD_width(sb) getnbyte(sb + 0x0e, 4) /* 0x12-0x15 - Height in 1/1200 inch */ #define set_WD_length(sb, val) putnbyte(sb + 0x12, val, 4) #define get_WD_length(sb) getnbyte(sb + 0x12, 4) /* 0x16 - Brightness */ #define set_WD_brightness(sb, val) sb[0x16] = val #define get_WD_brightness(sb) sb[0x16] /* 0x17 - Threshold */ #define set_WD_threshold(sb, val) sb[0x17] = val #define get_WD_threshold(sb) sb[0x17] /* 0x18 - Contrast */ #define set_WD_contrast(sb, val) sb[0x18] = val #define get_WD_contrast(sb) sb[0x18] /* 0x19 - Image Composition (color mode) */ #define set_WD_composition(sb, val) sb[0x19] = val #define get_WD_composition(sb) sb[0x19] #define WD_comp_LA 0 #define WD_comp_HT 1 #define WD_comp_GS 2 #define WD_comp_CL 3 #define WD_comp_CH 4 #define WD_comp_CG 5 /* 0x1a - Depth */ #define set_WD_bitsperpixel(sb, val) sb[0x1a] = val #define get_WD_bitsperpixel(sb) sb[0x1a] /* 0x1b,0x1c - Halftone Pattern */ #define set_WD_ht_type(sb, val) sb[0x1b] = val #define get_WD_ht_type(sb) sb[0x1b] #define WD_ht_type_DEFAULT 0 #define WD_ht_type_DITHER 1 #define WD_ht_type_DIFFUSION 2 #define set_WD_ht_pattern(sb, val) sb[0x1c] = val #define get_WD_ht_pattern(sb) sb[0x1c] /* 0x1d - Reverse image, reserved area, padding type */ #define set_WD_rif(sb, val) setbitfield(sb + 0x1d, 1, 7, val) #define get_WD_rif(sb) getbitfield(sb + 0x1d, 1, 7) #define set_WD_rgb(sb, val) setbitfield(sb + 0x1d, 7, 4, val) #define get_WD_rgb(sb) getbitfield(sb + 0x1d, 7, 4) #define set_WD_padding(sb, val) setbitfield(sb + 0x1d, 7, 0, val) #define get_WD_padding(sb) getbitfield(sb + 0x1d, 7, 0) /* 0x1e,0x1f - Bit ordering */ #define set_WD_bitorder(sb, val) putnbyte(sb + 0x1e, val, 2) #define get_WD_bitorder(sb) getnbyte(sb + 0x1e, 2) /* 0x20 - compression type */ #define set_WD_compress_type(sb, val) sb[0x20] = val #define get_WD_compress_type(sb) sb[0x20] #define WD_cmp_NONE 0 #define WD_cmp_MH 1 #define WD_cmp_MR 2 #define WD_cmp_MMR 3 #define WD_cmp_JPEG 0x80 /* 0x21 - compression argument * specify "k" parameter with MR compress, * or with JPEG- Q param, 0-7 */ #define set_WD_compress_arg(sb, val) sb[0x21] = val #define get_WD_compress_arg(sb) sb[0x21] /* 0x22-0x27 - reserved */ /* 0x28-0x2c - vendor unique */ /* FIXME: more params here? */ #define set_WD_reserved2(sb, val) sb[0x2a] = val #define get_WD_reserved2(sb) sb[0x2a] /* ==================================================================== */ #endif sane-backends-1.0.27/backend/epson.h0000664000175000017500000002222712112021330014074 00000000000000/* epson.h - SANE library for Epson flatbed scanners. based on Kazuhiro Sasayama previous Work on epson.[ch] file from the SANE package. original code taken from sane-0.71 Copyright (C) 1997 Hypercore Software Design, Ltd. modifications Copyright (C) 1998-1999 Christian Bucher Copyright (C) 1998-1999 Kling & Hautzinger GmbH Copyright (C) 1999 Norihiko Sawa Copyright (C) 2000 Karl Heinz Kremer This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef epson_h #define epson_h #include #include /* some string constants that are used in the config file */ #define SANE_EPSON_CONFIG_USB "usb" #define SANE_EPSON_CONFIG_PIO "pio" /* string constants for GUI elements that are not defined SANE-wide */ #define SANE_NAME_GAMMA_CORRECTION "gamma-correction" #define SANE_TITLE_GAMMA_CORRECTION SANE_I18N("Gamma Correction") #define SANE_DESC_GAMMA_CORRECTION SANE_I18N("Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scanner") #define SANE_EPSON_FOCUS_NAME "focus-position" #define SANE_EPSON_FOCUS_TITLE SANE_I18N("Focus Position") #define SANE_EPSON_FOCUS_DESC SANE_I18N("Sets the focus position to either the glass or 2.5mm above the glass") #define SANE_EPSON_WAIT_FOR_BUTTON_NAME "wait-for-button" #define SANE_EPSON_WAIT_FOR_BUTTON_TITLE SANE_I18N("Wait for Button") #define SANE_EPSON_WAIT_FOR_BUTTON_DESC SANE_I18N("After sending the scan command, wait until the button on the scanner is pressed to actually start the scan process."); #define LINES_SHUFFLE_MAX (17) /* 2 x 8 lines plus 1 */ #define SANE_EPSON_MAX_RETRIES (120) /* how often do we retry during warmup ? */ typedef struct { char *level; unsigned char request_identity; unsigned char request_identity2; /* new request identity command for Dx command level */ unsigned char request_status; unsigned char request_condition; unsigned char set_color_mode; unsigned char start_scanning; unsigned char set_data_format; unsigned char set_resolution; unsigned char set_zoom; unsigned char set_scan_area; unsigned char set_bright; SANE_Range bright_range; unsigned char set_gamma; unsigned char set_halftoning; unsigned char set_color_correction; unsigned char initialize_scanner; unsigned char set_speed; /* B4 and later */ unsigned char set_lcount; unsigned char mirror_image; /* B5 and later */ unsigned char set_gamma_table; /* B4 and later */ unsigned char set_outline_emphasis; /* B4 and later */ unsigned char set_dither; /* B4 and later */ unsigned char set_color_correction_coefficients; /* B3 and later */ unsigned char request_extended_status; /* get extended status from scanner */ unsigned char control_an_extension; /* for extension control */ unsigned char eject; /* for extension control */ unsigned char feed; unsigned char request_push_button_status; unsigned char control_auto_area_segmentation; unsigned char set_film_type; /* for extension control */ unsigned char set_exposure_time; /* F5 only */ unsigned char set_bay; /* F5 only */ unsigned char set_threshold; unsigned char set_focus_position; /* B8 only */ unsigned char request_focus_position; /* B8 only */ } EpsonCmdRec, *EpsonCmd; enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_BIT_DEPTH, OPT_HALFTONE, OPT_DROPOUT, OPT_BRIGHTNESS, OPT_SHARPNESS, OPT_GAMMA_CORRECTION, OPT_COLOR_CORRECTION, OPT_RESOLUTION, OPT_THRESHOLD, OPT_ADVANCED_GROUP, OPT_MIRROR, OPT_SPEED, OPT_AAS, OPT_LIMIT_RESOLUTION, OPT_ZOOM, /* OPT_GAMMA_VECTOR */ OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_WAIT_FOR_BUTTON, OPT_CCT_GROUP, OPT_CCT_1, OPT_CCT_2, OPT_CCT_3, OPT_CCT_4, OPT_CCT_5, OPT_CCT_6, OPT_CCT_7, OPT_CCT_8, OPT_CCT_9, OPT_PREVIEW_GROUP, OPT_PREVIEW, OPT_PREVIEW_SPEED, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_QUICK_FORMAT, OPT_EQU_GROUP, OPT_SOURCE, OPT_AUTO_EJECT, OPT_FILM_TYPE, OPT_FOCUS, OPT_BAY, OPT_EJECT, OPT_ADF_MODE, NUM_OPTIONS }; typedef enum { /* hardware connection to the scanner */ SANE_EPSON_NODEV, /* default, no HW specified yet */ SANE_EPSON_SCSI, /* SCSI interface */ SANE_EPSON_PIO, /* parallel interface */ SANE_EPSON_USB /* USB interface */ } Epson_Connection_Type; typedef struct { u_short opt_resolution; u_char sensor; u_char scan_order; u_char line_dist1; u_char line_dist2; u_short main_res1; u_short main_res2; u_short main_res3; u_short main_res4; u_short main_res5; u_short main_res6; u_short main_res7; u_short sub_res1; u_short sub_res2; u_short sub_res3; u_short sub_res4; u_short sub_res5; u_short sub_res6; } Epson_Identity2; struct Epson_Device { struct Epson_Device *next; SANE_Device sane; SANE_Int level; SANE_Range dpi_range; SANE_Range *x_range; /* x range w/out extension */ SANE_Range *y_range; /* y range w/out extension */ SANE_Range fbf_x_range; /* flattbed x range */ SANE_Range fbf_y_range; /* flattbed y range */ SANE_Range adf_x_range; /* autom. document feeder x range */ SANE_Range adf_y_range; /* autom. document feeder y range */ SANE_Range tpu_x_range; /* transparency unit x range */ SANE_Range tpu_y_range; /* transparency unit y range */ Epson_Connection_Type connection; /* hardware interface type */ SANE_Int *res_list; /* list of resolutions */ SANE_Int res_list_size; /* number of entries in this list */ SANE_Int last_res; /* last selected resolution */ SANE_Int last_res_preview; /* last selected preview resolution */ SANE_Word *resolution_list; /* for display purposes we store a second copy */ SANE_Bool extension; /* extension is installed */ SANE_Int use_extension; /* use the installed extension */ SANE_Bool TPU; /* TPU is installed */ SANE_Bool ADF; /* ADF is installed */ SANE_Bool duplexSupport; /* does the ADF handle duplex scanning */ SANE_Bool focusSupport; /* does this scanner have support for "set focus position" ? */ SANE_Bool color_shuffle; /* does this scanner need color shuffling */ SANE_Int maxDepth; /* max. color depth */ SANE_Int optical_res; /* optical resolution */ SANE_Int max_line_distance; SANE_Bool need_double_vertical; SANE_Bool need_color_reorder; SANE_Bool need_reset_on_source_change; SANE_Bool wait_for_button; /* do we have to wait until the scanner button is pressed? */ SANE_Int fbf_max_x; SANE_Int fbf_max_y; SANE_Int adf_max_x; SANE_Int adf_max_y; SANE_Int devtype; EpsonCmd cmd; }; typedef struct Epson_Device Epson_Device; struct Epson_Scanner { struct Epson_Scanner *next; int fd; Epson_Device *hw; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; SANE_Bool block; SANE_Bool eof; SANE_Byte *buf, *end, *ptr; SANE_Bool canceling; SANE_Bool invert_image; SANE_Bool focusOnGlass; SANE_Byte currentFocusPosition; /* SANE_Word gamma_table [ 4] [ 256]; */ SANE_Word gamma_table[3][256]; SANE_Int retry_count; SANE_Byte *line_buffer[LINES_SHUFFLE_MAX]; /* buffer lines for color shuffling */ SANE_Int color_shuffle_line; /* current line number for color shuffling */ SANE_Int line_distance; /* current line distance */ SANE_Int current_output_line; /* line counter when color shuffling */ SANE_Int lines_written; /* debug variable */ SANE_Bool option_has_changed; /* did one of the options change it's value? */ }; typedef struct Epson_Scanner Epson_Scanner; #endif /* not epson_h */ sane-backends-1.0.27/backend/st400.conf.in0000664000175000017500000000426012112021330014722 00000000000000# the ST400 is fixed to ID 3 scsi SIEMENS "ST 400" Scanner * * 3 * scsi SIEMENS "ST 800" Scanner * * 3 * # The following options are for testing and bug-hunting. If your scanner # needs one of these options to function reliably, please let me know. # Maximum amount of data to read in a single SCSI command. If not set # (or set to 0), the backend will read as much data as allowed by the # scanner model or the OS. WARNING: Using this option overrides the # hardcoded # maxread limits for all scanner models! With more than # 65536 bytes, my ST400 locks up (itself, the SCSI bus, the sg driver, # and the machine). Use with caution. #option maxread 65536 # Use this to switch the scanner lights on with a separate MODE SELECT call # and wait for some time before starting to scan (to allow the lights to go # to full intensity). The time is in 1/10 seconds (i.e. 20 means 2 seconds). # If not set, scanning starts immediately (works with my ST400). #option delay 20 # The following are hacks that affect all scanners of the same model as the # last attached device. Used like this (assume ST800's had 8bit depth and # 4MB internal buffer): # scsi SIEMENS "ST 400" Scanner * * 3 * # option scanner_bufsize 2097152 # option scanner_bits 6 # scsi SIEMENS "ST 800" Scanner * * 3 * # option scanner_bufsize 4194304 # option scanner_bits 8 # Currently, the backend has entries for ST400, ST800 and "everything else". # To add more scanners, you have to add a line in the st400_models array. # Please note that these options are only for testing unknown devices with # this backend. # Internal scanner buffer: #option scanner_bufsize 2097152 # Bit depth: #option scanner_bits 6 # Maximum bytes to read in a single SCSI command (see also maxread above). #option scanner_maxread 65536 # Supported resolutions (upto 15 different values). If you specify an # illegal value here, most likely the scanner will not report an error, # but only scan a small sub-area of the requested area (at least my ST400 # does this). #option scanner_resolutions 200 300 400 # This option causes the SCSI inquiry response to be written to # "$HOME/st400.dump" (as binary data). For debugging purposes. #option dump_inquiry sane-backends-1.0.27/backend/sm3600-scanusb.c0000664000175000017500000003003112112021330015317 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) Marian Eichholz 2001 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ====================================================================== Userspace scan tool for the Microtek 3600 scanner $Id$ (C) Marian Eichholz 2001 26.4.2001: Added an abstraction layer for TransferControlMsg. ====================================================================== */ #include "sm3600-scantool.h" /* ********************************************************************** TransferControlMsg() ********************************************************************** */ static int TransferControlMsg(TInstance *this, int nReqType, int nRequest, int nValue, int nIndex, void *pBuffer, int cchBuffer, int cJiffiesTimeout) { SANE_Status err; cJiffiesTimeout = cJiffiesTimeout; err = sanei_usb_control_msg (this->hScanner, nReqType, nRequest, nValue, nIndex, cchBuffer, pBuffer); if (err) return err; return cchBuffer; } /* ********************************************************************** cch=BulkRead() ********************************************************************** */ static int TransferBulkRead(TInstance *this, int nEndPoint, void *pBuffer, int cchMax, int cJiffiesTimeout) { int err; size_t sz = cchMax; nEndPoint = nEndPoint; cJiffiesTimeout = cJiffiesTimeout; err = sanei_usb_read_bulk(this->hScanner, pBuffer, &sz); if (err) return err; return sz; } /* ********************************************************************** RegWrite(iRegister, cb, ulValue) RegWriteArray(iRegister, cb, unsigned char uchValues) ********************************************************************** */ __SM3600EXPORT__ TState RegWrite(TInstance *this, int iRegister, int cb, unsigned long ulValue) { char *pchBuffer; int i; TBool bOk=true; INST_ASSERT(); /* some rough assertions */ if (cb<1 || cb>4) return SetError(this,SANE_STATUS_INVAL,"unsupported control transfer size %d",cb); pchBuffer=malloc(cb); CHECK_POINTER(pchBuffer); for (i=0; i>8; } if (!bOk) { free(pchBuffer); return SetError(this,SANE_STATUS_IO_ERROR, "error in reg out: %d,%d,%08X",iRegister,cb,ulValue); } i=TransferControlMsg(this, /* handle */ 0x40, /* request type */ 0x08, /* request */ iRegister, /* value */ 0, /* index */ pchBuffer, cb, /* bytes, size */ USB_TIMEOUT_JIFFIES); /* TO, jiffies... */ free(pchBuffer); if (i<0) return SetError(this,SANE_STATUS_IO_ERROR,"error during register write"); return SANE_STATUS_GOOD; } __SM3600EXPORT__ TState RegWriteArray(TInstance *this, int iRegister, int cb, unsigned char *pchBuffer) { int i; INST_ASSERT(); /* some rough assertions */ i=TransferControlMsg(this, /* handle */ 0x40, /* request type */ 0x08, /* request */ iRegister, /* value */ 0, /* index */ pchBuffer, cb, /* bytes, size */ USB_TIMEOUT_JIFFIES); /* TO, jiffies... */ if (i<0) return SetError(this,SANE_STATUS_IO_ERROR,"error during register write"); return SANE_STATUS_GOOD; } /* ********************************************************************** MemWriteArray(iAddress, cb, ulValue) ********************************************************************** */ __SM3600EXPORT__ TState MemWriteArray(TInstance *this, int iAddress, int cb, unsigned char *pchBuffer) { int i; INST_ASSERT(); /* some rough assertions */ i=TransferControlMsg(this, 0x40, /* request type */ 0x09, /* request */ iAddress, /* value */ 0, /* index */ pchBuffer, cb, /* bytes, size */ 10000); /* TO, jiffies... */ if (i<0) return SetError(this,SANE_STATUS_IO_ERROR,"error during memory write"); return SANE_STATUS_GOOD; } /* ********************************************************************** MemReadArray(iRegister, cb, ulValue) ********************************************************************** */ #ifdef INSANE_VERSION __SM3600EXPORT__ TState MemReadArray(TInstance *this, int iAddress, int cb, unsigned char *pchBuffer) { int i; INST_ASSERT(); /* some rough assertions */ i=TransferControlMsg(this, 0xC0, /* request type */ 0x01, /* request */ iAddress, /* value */ 0, /* index */ pchBuffer, cb, /* bytes, size */ USB_TIMEOUT_JIFFIES); /* TO, jiffies... */ if (i<0) return SetError(this,SANE_STATUS_IO_ERROR,"error during memory read"); return SANE_STATUS_GOOD; } /* ********************************************************************** RegCheck(iRegister, cb, ulValue) ********************************************************************** */ __SM3600EXPORT__ TState RegCheck(TInstance *this, int iRegister, int cch, unsigned long ulValue) { char *pchBuffer,*pchTransfer; int i,rcCode; TBool bOk; INST_ASSERT(); if (cch<1 || cch>3) return SetError(this,SANE_STATUS_INVAL,"unsupported control transfer size %d",cch); pchBuffer=malloc(cch); pchTransfer=calloc(1,cch); rcCode=SANE_STATUS_GOOD; if (!pchBuffer || !pchTransfer) { if (pchBuffer) free(pchBuffer); if (pchTransfer) free(pchTransfer); rcCode=SetError(this, SANE_STATUS_NO_MEM, "no memory in RegCheck()"); } bOk=true; for (i=0; !rcCode && i>8); } if (!rcCode) { if (!bOk) rcCode=SetError(this,SANE_STATUS_IO_ERROR, "error in reg out: %d,%d,%08X",iRegister,cch,ulValue); else { i=TransferControlMsg(this, /* handle */ 0xC0, /* request type */ 0x00, /* request */ iRegister, /* value */ 0, /* index */ pchTransfer, cch, /* bytes, size */ USB_TIMEOUT_JIFFIES); /* TO, jiffies... */ if (i<0) rcCode=SetError(this,SANE_STATUS_IO_ERROR, "error during register check"); } } if (!rcCode && memcmp(pchTransfer,pchBuffer,cch)) { DumpBuffer(stdout,pchTransfer,cch); rcCode=SetError(this,SANE_STATUS_IO_ERROR, "check register failed for %d,%d,%08X", iRegister,cch,ulValue); } free(pchTransfer); free(pchBuffer); return rcCode; } /* ********************************************************************** cchRead=BulkRead(fh,cchBulk) ********************************************************************** */ __SM3600EXPORT__ int BulkRead(TInstance *this, FILE *fhOut, unsigned int cchBulk) { int cchRead,rc; char *pchBuffer; INST_ASSERT(); pchBuffer=(char*)malloc(cchBulk); CHECK_POINTER(pchBuffer); cchRead=0; rc=0; while (!rc && cchBulk) { int cchChunk; int cchReal; cchChunk=cchBulk; if (cchChunk>0x1000) cchChunk=0x1000; cchReal=TransferBulkRead(this, 0x82, pchBuffer+cchRead, cchChunk, USB_TIMEOUT_JIFFIES); dprintf(DEBUG_COMM,"bulk read: %d -> %d\n",cchChunk,cchReal); if (cchReal>=0) { cchBulk-=cchReal; cchRead+=cchReal; if (cchReal0x1000) cchChunk=0x1000; cchReal=TransferBulkRead(this, 0x82, pchBuffer+cchRead, cchChunk, USB_TIMEOUT_JIFFIES); dprintf(DEBUG_COMM,"bulk read: %d -> %d\n",cchChunk,cchReal); if (cchReal>=0) { cchBulk-=cchReal; cchRead+=cchReal; if (cchReal4) { SetError(this,SANE_STATUS_INVAL, "unsupported control read size %d",cch); return 0; } pchTransfer=calloc(1,cch); CHECK_POINTER(pchTransfer); i=TransferControlMsg(this, /* handle */ 0xC0, /* request type */ 0x00, /* request */ iRegister, /* value */ 0, /* index */ pchTransfer, cch, /* bytes, size */ USB_TIMEOUT_JIFFIES); /* TO, jiffies... */ if (i>=0) { n=0; for (i=cch-1; i>=0; i--) n=(n<<8)|(unsigned char)pchTransfer[i]; free(pchTransfer); return n; } free(pchTransfer); SetError(this,SANE_STATUS_IO_ERROR,"error during register read"); return 0; } sane-backends-1.0.27/backend/gt68xx_generic.h0000664000175000017500000000550012112021330015607 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GT68XX_GENERIC_H #define GT68XX_GENERIC_H #include "gt68xx_low.h" static SANE_Status gt68xx_generic_move_relative (GT68xx_Device * dev, SANE_Int distance); static SANE_Status gt68xx_generic_start_scan (GT68xx_Device * dev); static SANE_Status gt68xx_generic_read_scanned_data (GT68xx_Device * dev, SANE_Bool * ready); static SANE_Status gt68xx_generic_set_afe (GT68xx_Device * dev, GT68xx_AFE_Parameters * params); static SANE_Status gt68xx_generic_set_exposure_time (GT68xx_Device * dev, GT68xx_Exposure_Parameters * params); static SANE_Status gt68xx_generic_get_id (GT68xx_Device * dev); static SANE_Status gt68xx_generic_paperfeed (GT68xx_Device * dev); static SANE_Status gt68xx_generic_setup_scan (GT68xx_Device * dev, GT68xx_Scan_Request * request, GT68xx_Scan_Action action, GT68xx_Scan_Parameters * params); static SANE_Status gt68xx_generic_move_paper (GT68xx_Device * dev, GT68xx_Scan_Request * request); #endif /* not GT68XX_GENERIC_H */ sane-backends-1.0.27/backend/qcam.conf.in0000664000175000017500000000060712112021330014772 00000000000000# # In order to use the qcam backend, you'll need to enable to line with # the port address for your scanner. You can enable multiple lines if # you really have a QuickCam connect to each port. # #u0x37b # /dev/lp0 forced in unidir mode #u0x378 # /dev/lp1 forced in unidir mode #u0x278 # /dev/lp2 forced in unidir mode #0x37b # /dev/lp0 #0x378 # /dev/lp1 #0x278 # /dev/lp2 0x3bc # /dev/lp0 sane-backends-1.0.27/backend/epsonds-jpeg.c0000664000175000017500000001203412775312261015361 00000000000000/* * epsonds-jpeg.c - Epson ESC/I-2 driver, JPEG support. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #include #include "epsonds.h" #include "epsonds-jpeg.h" #include "epsonds-ops.h" #define min(A,B) (((A)<(B)) ? (A) : (B)) typedef struct { struct jpeg_source_mgr pub; epsonds_scanner *s; JOCTET *buffer; SANE_Byte *linebuffer; SANE_Int linebuffer_size; SANE_Int linebuffer_index; } epsonds_src_mgr; METHODDEF(void) jpeg_init_source(j_decompress_ptr __sane_unused__ cinfo) { } METHODDEF(void) jpeg_term_source(j_decompress_ptr __sane_unused__ cinfo) { } METHODDEF(boolean) jpeg_fill_input_buffer(j_decompress_ptr cinfo) { epsonds_src_mgr *src = (epsonds_src_mgr *)cinfo->src; int avail, size; /* read from the scanner or the ring buffer */ avail = eds_ring_avail(src->s->current); if (avail == 0) { return FALSE; } /* read from scanner if no data? */ size = min(1024, avail); eds_ring_read(src->s->current, src->buffer, size); src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = size; return TRUE; } METHODDEF (void) jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { epsonds_src_mgr *src = (epsonds_src_mgr *)cinfo->src; if (num_bytes > 0) { while (num_bytes > (long)src->pub.bytes_in_buffer) { num_bytes -= (long)src->pub.bytes_in_buffer; jpeg_fill_input_buffer(cinfo); } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; } } SANE_Status eds_jpeg_start(epsonds_scanner *s) { epsonds_src_mgr *src; s->jpeg_cinfo.err = jpeg_std_error(&s->jpeg_err); jpeg_create_decompress(&s->jpeg_cinfo); s->jpeg_cinfo.src = (struct jpeg_source_mgr *)(*s->jpeg_cinfo.mem->alloc_small)((j_common_ptr)&s->jpeg_cinfo, JPOOL_PERMANENT, sizeof(epsonds_src_mgr)); memset(s->jpeg_cinfo.src, 0x00, sizeof(epsonds_src_mgr)); src = (epsonds_src_mgr *)s->jpeg_cinfo.src; src->s = s; src->buffer = (JOCTET *)(*s->jpeg_cinfo.mem->alloc_small)((j_common_ptr)&s->jpeg_cinfo, JPOOL_PERMANENT, 1024 * sizeof(JOCTET)); src->pub.init_source = jpeg_init_source; src->pub.fill_input_buffer = jpeg_fill_input_buffer; src->pub.skip_input_data = jpeg_skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; src->pub.term_source = jpeg_term_source; src->pub.bytes_in_buffer = 0; src->pub.next_input_byte = NULL; s->jpeg_header_seen = 0; return SANE_STATUS_GOOD; } SANE_Status eds_jpeg_read_header(epsonds_scanner *s) { epsonds_src_mgr *src = (epsonds_src_mgr *)s->jpeg_cinfo.src; if (jpeg_read_header(&s->jpeg_cinfo, TRUE)) { s->jdst = sanei_jpeg_jinit_write_ppm(&s->jpeg_cinfo); if (jpeg_start_decompress(&s->jpeg_cinfo)) { int size; DBG(3, "%s: w: %d, h: %d, components: %d\n", __func__, s->jpeg_cinfo.output_width, s->jpeg_cinfo.output_height, s->jpeg_cinfo.output_components); size = s->jpeg_cinfo.output_width * s->jpeg_cinfo.output_components * 1; src->linebuffer = (*s->jpeg_cinfo.mem->alloc_large)((j_common_ptr)&s->jpeg_cinfo, JPOOL_PERMANENT, size); src->linebuffer_size = 0; src->linebuffer_index = 0; s->jpeg_header_seen = 1; return SANE_STATUS_GOOD; } else { DBG(0, "%s: decompression failed\n", __func__); return SANE_STATUS_IO_ERROR; } } else { DBG(0, "%s: cannot read JPEG header\n", __func__); return SANE_STATUS_IO_ERROR; } } void eds_jpeg_finish(epsonds_scanner *s) { jpeg_destroy_decompress(&s->jpeg_cinfo); } void eds_jpeg_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length) { epsonds_scanner *s = handle; struct jpeg_decompress_struct cinfo = s->jpeg_cinfo; epsonds_src_mgr *src = (epsonds_src_mgr *)s->jpeg_cinfo.src; int l; *length = 0; /* copy from line buffer if available */ if (src->linebuffer_size && src->linebuffer_index < src->linebuffer_size) { *length = src->linebuffer_size - src->linebuffer_index; if (*length > max_length) *length = max_length; memcpy(data, src->linebuffer + src->linebuffer_index, *length); src->linebuffer_index += *length; return; } if (cinfo.output_scanline >= cinfo.output_height) { *length = 0; return; } /* scanlines of decompressed data will be in s->jdst->buffer * only one line at time is supported */ l = jpeg_read_scanlines(&cinfo, s->jdst->buffer, 1); if (l == 0) { return; } /* from s->jdst->buffer to linebuffer * linebuffer holds width * bytesperpixel */ (*s->jdst->put_pixel_rows)(&cinfo, s->jdst, 1, (char *)src->linebuffer); *length = cinfo.output_width * cinfo.output_components * 1; src->linebuffer_size = *length; src->linebuffer_index = 0; if (*length > max_length) *length = max_length; memcpy(data, src->linebuffer + src->linebuffer_index, *length); src->linebuffer_index += *length; } sane-backends-1.0.27/backend/umax-scsidef.h0000664000175000017500000012373612112021330015347 00000000000000/* --------------------------------------------------------------------------------------------------------- */ /* umax-scsidef.h: scsi-definiton header file for UMAX scanner driver. Copyright (C) 1996-1997 Michael K. Johnson Copyright (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* --------------------------------------------------------------------------------------------------------- */ #ifndef UMAX_SCSIDEF_H #define UMAX_SCSIDEF_H #include "umax.h" /* --------------------------------------------------------------------------------------------------------- */ /* I'm using functions derived from Eric Youngdale's scsiinfo * program here for dealing with parts of SCSI commands. */ static inline void setbitfield(unsigned char * pageaddr, int mask, int shift, int val) \ { *pageaddr = (*pageaddr & ~(mask << shift)) | ((val & mask) << shift); } static inline void resetbitfield(unsigned char * pageaddr, int mask, int shift, int val) \ { *pageaddr = (*pageaddr & ~(mask << shift)) | (((!val) & mask) << shift); } static inline int getbitfield(unsigned char * pageaddr, int mask, int shift) \ { return ((*pageaddr >> shift) & mask); } /* ------------------------------------------------------------------------- */ static inline int getnbyte(unsigned char * pnt, int nbytes) \ { unsigned int result = 0; int i; for(i=0; i= 0; i--) \ { pnt[i] = value & 0xff; value = value >> 8; } } /* --------------------------------------------------------------------------------------------------------- */ /* Not all of these are defined in scsi.h, so we'll make sure * we agree about them here... */ #define TEST_UNIT_READY 0x00 #define REQUEST_SENSE 0x03 #define INQUIRY 0x12 #define RESERVE_UNIT 0x16 #define RELEASE_UNIT 0x17 #define SCAN 0x1B #define SET_WINDOW 0x24 #define READ 0x28 #define SEND 0x2A #define OBJECT_POSITION 0x31 #define GET_DATA_BUFFER_STATUS 0x34 #undef WRITE_BUFFER /* correct write_buffer for scanner */ #define WRITE_BUFFER 0x3B #define GET_LAMP_STATUS 0x5E #define SET_LAMP_STATUS 0x5F /* --------------------------------------------------------------------------------------------------------- */ #define STD_WDB_LEN 0x28 /* wdb_len if nothing is set by inquiry */ /* --------------------------------------------------------------------------------------------------------- */ /* SCSI commands */ typedef struct { unsigned char *cmd; size_t size; } scsiblk; /* --------------------------------------------------------------------------------------------------------- */ #define set_inquiry_return_size(icb,val) icb[0x04]=val static unsigned char inquiryC[] = { INQUIRY, 0x00, 0x02, 0x00, 0xff, 0x00 }; static scsiblk inquiry = { inquiryC, sizeof(inquiryC) }; /* --------------------------------------------------------------------------------------------------------- */ #define get_inquiry_periph_qual(in) getbitfield(in, 0x07, 5) # define IN_periph_qual_lun 0x00 # define IN_periph_qual_nolun 0x03 #define get_inquiry_periph_devtype(in) getbitfield(in, 0x1f, 0) # define IN_periph_devtype_scanner 0x06 # define IN_periph_devtype_unknown 0x1f #define get_inquiry_rmb(in) getbitfield(in + 0x01, 0x01, 7) #define get_inquiry_0x01_bit6(in) getbitfield(in + 0x01, 0x01, 6) #define get_inquiry_0x01_bit5(in) getbitfield(in + 0x01, 0x01, 5) #define get_inquiry_CBHS(in) getbitfield(in + 0x01, 0x03, 3) #define set_inquiry_CBHS(in, val) setbitfield(in + 0x01, 0x03, 3, val) # define IN_CBHS_50 0x00 # define IN_CBHS_255 0x01 # define IN_CBHS_auto 0x02 #define get_inquiry_translamp(in) getbitfield(in + 0x01, 0x01, 2) #define get_inquiry_transavail(in) getbitfield(in + 0x01, 0x01, 1) #define get_inquiry_scanmode(in) getbitfield(in + 0x01, 0x01, 0) # define IN_flatbed 0x00 # define IN_adf 0x01 #define get_inquiry_iso_version(in) getbitfield(in + 0x02, 0x03, 6) #define get_inquiry_ecma_version(in) getbitfield(in + 0x02, 0x07, 3) #define get_inquiry_ansi_version(in) getbitfield(in + 0x02, 0x07, 0) #define get_inquiry_aenc(in) getbitfield(in + 0x03, 0x01, 7) #define get_inquiry_tmiop(in) getbitfield(in + 0x03, 0x01, 6) #define get_inquiry_0x03_bit5(in) getbitfield(in + 0x03, 0x01, 5) #define get_inquiry_0x03_bit4(in) getbitfield(in + 0x03, 0x01, 4) #define get_inquiry_response_format(in) getbitfield(in + 0x03, 0x0f, 0) # define IN_recognized 0x02 #define get_inquiry_additional_length(in) in[0x04] #define set_inquiry_length(out,n) out[0x04]=n-5 #define get_inquiry_0x05(in) in[0x05] #define get_inquiry_0x06(in) in[0x06] #define get_inquiry_scsi_byte(in) in[0x07] #define get_inquiry_scsi_reladr(in) getbitfield(in + 0x07, 0x01, 7) #define get_inquiry_scsi_wbus32(in) getbitfield(in + 0x07, 0x01, 6) #define get_inquiry_scsi_wbus16(in) getbitfield(in + 0x07, 0x01, 5) #define get_inquiry_scsi_sync(in) getbitfield(in + 0x07, 0x01, 4) #define get_inquiry_scsi_linked(in) getbitfield(in + 0x07, 0x01, 3) #define get_inquiry_scsi_R(in) getbitfield(in + 0x07, 0x01, 2) #define get_inquiry_scsi_cmdqueue(in) getbitfield(in + 0x07, 0x01, 1) #define get_inquiry_scsi_sftre(in) getbitfield(in + 0x07, 0x01, 0) #define get_inquiry_vendor(in, buf) strncpy(buf, in + 0x08, 0x08) #define get_inquiry_product(in, buf) strncpy(buf, in + 0x10, 0x010) #define get_inquiry_version(in, buf) strncpy(buf, in + 0x20, 0x04) #define set_inquiry_fw_quality(in, val) setbitfield(in + 0x24, 1, 0, val) #define get_inquiry_fw_quality(in) getbitfield(in + 0x24, 1, 0) #define get_inquiry_fw_fast_preview(in) getbitfield(in + 0x24, 1, 1) #define get_inquiry_fw_shadow_comp(in) getbitfield(in + 0x24, 1, 2) #define get_inquiry_fw_reselection(in) getbitfield(in + 0x24, 1, 3) #define get_inquiry_fw_lamp_int_cont(in) getbitfield(in + 0x24, 1, 4) #define get_inquiry_fw_batch_scan(in) getbitfield(in + 0x24, 1, 5) #define get_inquiry_fw_calibration(in) getbitfield(in + 0x24, 1, 6) #define get_inquiry_fw_adjust_exposure_tf(in) getbitfield(in + 0x24, 1, 7) #define get_inquiry_exposure_time_step_unit(in) in[0x25] #define get_inquiry_exposure_time_max(in) getnbyte(in + 0x26, 2) #define get_inquiry_exposure_time_lhg_min(in) in[0x2a] #define get_inquiry_exposure_time_color_min(in) in[0x2b] #define get_inquiry_exposure_time_lh_def_fb(in) in[0x2c] #define get_inquiry_exposure_time_lh_def_uta(in) in[0x2d] #define get_inquiry_exposure_time_gray_def_fb(in) in[0x2e] #define get_inquiry_exposure_time_gray_def_uta(in) in[0x2f] #define get_inquiry_exposure_time_def_r_fb(in) in[0x30] #define get_inquiry_exposure_time_def_g_fb(in) in[0x31] #define get_inquiry_exposure_time_def_b_fb(in) in[0x32] #define get_inquiry_exposure_time_def_r_uta(in) in[0x33] #define get_inquiry_exposure_time_def_g_uta(in) in[0x34] #define get_inquiry_exposure_time_def_b_uta(in) in[0x35] #define get_inquiry_0x36(in) in[0x36] #define get_inquiry_0x37(in) in[0x37] /* bytes 0x38 - 0x5f reserved by SCSI */ #define get_inquiry_sc_feature_byte0(in) in[0x60] #define get_inquiry_sc_three_pass_color(in) getbitfield(in + 0x60, 1, 0) #define get_inquiry_sc_one_pass_color(in) getbitfield(in + 0x60, 1, 1) #define get_inquiry_sc_lineart(in) getbitfield(in + 0x60, 1, 2) #define get_inquiry_sc_halftone(in) getbitfield(in + 0x60, 1, 3) #define get_inquiry_sc_gray(in) getbitfield(in + 0x60, 1, 4) #define get_inquiry_sc_color(in) getbitfield(in + 0x60, 1, 5) #define get_inquiry_sc_uta(in) getbitfield(in + 0x60, 1, 6) #define get_inquiry_sc_adf(in) getbitfield(in + 0x60, 1, 7) #define set_inquiry_sc_three_pass_color(in,val) setbitfield(in + 0x60, 1, 0, val) #define set_inquiry_sc_one_pass_color(in,val) setbitfield(in + 0x60, 1, 1, val) #define set_inquiry_sc_lineart(in,val) setbitfield(in + 0x60, 1, 2, val) #define set_inquiry_sc_halftone(in,val) setbitfield(in + 0x60, 1, 3, val) #define set_inquiry_sc_gray(in,val) setbitfield(in + 0x60, 1, 4, val) #define set_inquiry_sc_color(in,val) setbitfield(in + 0x60, 1, 5, val) #define set_inquiry_sc_uta(in,val) setbitfield(in + 0x60, 1, 6, val) #define set_inquiry_sc_adf(in,val) setbitfield(in + 0x60, 1, 7, val) #define get_inquiry_sc_feature_byte1(in) in[0x61] #define get_inquiry_sc_double_res(in) getbitfield(in + 0x61, 1, 0) #define get_inquiry_sc_high_byte_first(in) getbitfield(in + 0x61, 1, 1) #define get_inquiry_sc_bi_image_reverse(in) getbitfield(in + 0x61, 1, 2) #define get_inquiry_sc_multi_image_reverse(in) getbitfield(in + 0x61, 1, 3) #define get_inquiry_sc_no_shadow(in) getbitfield(in + 0x61, 1, 4) #define get_inquiry_sc_no_highlight(in) getbitfield(in + 0x61, 1, 5) #define get_inquiry_sc_downloadable_fw(in) getbitfield(in + 0x61, 1, 6) #define get_inquiry_sc_paper_length_14(in) getbitfield(in + 0x61, 1, 7) #define get_inquiry_sc_feature_byte2(in) in[0x62] #define get_inquiry_sc_uploadable_shade(in) getbitfield(in + 0x62, 1, 0) #define get_inquiry_fw_support_color(in) getbitfield(in + 0x62, 1, 1) #define get_inquiry_analog_gamma(in) getbitfield(in + 0x62, 1, 2) #define get_inquiry_xy_coordinate_base(in) getbitfield(in + 0x62, 1, 3) #define get_inquiry_lineart_order(in) getbitfield(in + 0x62, 1, 4) #define get_inquiry_start_density(in) getbitfield(in + 0x62, 1, 5) #define get_inquiry_hw_x_scaling(in) getbitfield(in + 0x62, 1, 6) #define get_inquiry_hw_y_scaling(in) getbitfield(in + 0x62, 1, 7) #define get_inquiry_sc_feature_byte3(in) in[0x63] #define get_inquiry_ADF_no_paper(in) getbitfield(in + 0x63, 1, 0) #define get_inquiry_ADF_cover_open(in) getbitfield(in + 0x63, 1, 1) #define get_inquiry_ADF_paper_jam(in) getbitfield(in + 0x63, 1, 2) #define get_inquiry_0x63_bit3(in) getbitfield(in + 0x63, 1, 3) #define get_inquiry_0x63_bit4(in) getbitfield(in + 0x63, 1, 4) #define get_inquiry_lens_cal_in_doc_pos(in) getbitfield(in + 0x63, 1, 5) #define get_inquiry_manual_focus(in) getbitfield(in + 0x63, 1, 6) #define get_inquiry_sel_uta_lens_cal_pos(in) getbitfield(in + 0x63, 1, 7) #define get_inquiry_gamma_download_available(in) getbitfield(in + 0x64, 1, 7) #define get_inquiry_0x64_bit6(in) getbitfield(in + 0x64, 1, 6) #define get_inquiry_gamma_type_2(in) getbitfield(in + 0x64, 1, 5) #define get_inquiry_0x64_bit4(in) getbitfield(in + 0x64, 1, 4) #define get_inquiry_0x64_bit3(in) getbitfield(in + 0x64, 1, 3) #define get_inquiry_0x64_bit2(in) getbitfield(in + 0x64, 1, 2) #define get_inquiry_gamma_lines(in) getbitfield(in + 0x64, 0x03, 0) # define IN_3_pass 0x01 # define IN_3_line 0x03 #define get_inquiry_0x65(in) in[0x65] #define get_inquiry_gib(in) in[0x66] #define get_inquiry_gib_8bpp(in) getbitfield(in + 0x66, 1, 0) #define get_inquiry_gib_9bpp(in) getbitfield(in + 0x66, 1, 1) #define get_inquiry_gib_10bpp(in) getbitfield(in + 0x66, 1, 2) #define get_inquiry_gib_12bpp(in) getbitfield(in + 0x66, 1, 3) #define get_inquiry_gib_14bpp(in) getbitfield(in + 0x66, 1, 4) #define get_inquiry_gib_16bpp(in) getbitfield(in + 0x66, 1, 5) #define get_inquiry_0x66_bit6(in) getbitfield(in + 0x66, 1, 6) #define get_inquiry_0x66_bit7(in) getbitfield(in + 0x66, 1, 7) # define IN_gib_8bpp 0x01 # define IN_gib_10bpp 0x04 #define get_inquiry_0x67(in) in[0x67] #define get_inquiry_gob(in) in[0x68] #define get_inquiry_gob_8bpp(in) getbitfield(in + 0x68, 1, 0) #define get_inquiry_gob_9bpp(in) getbitfield(in + 0x68, 1, 1) #define get_inquiry_gob_10bpp(in) getbitfield(in + 0x68, 1, 2) #define get_inquiry_gob_12bpp(in) getbitfield(in + 0x68, 1, 3) #define get_inquiry_gob_14bpp(in) getbitfield(in + 0x68, 1, 4) #define get_inquiry_gob_16bpp(in) getbitfield(in + 0x68, 1, 5) #define get_inquiry_0x68_bit6(in) getbitfield(in + 0x68, 1, 6) #define get_inquiry_0x68_bit7(in) getbitfield(in + 0x68, 1, 7) # define IN_gob_8bpp 0x01 # define IN_gob_10bpp 0x04 #define get_inquiry_hda(in) getbitfield(in + 0x69, 0x01, 7) #define get_inquiry_max_halftone_matrix(in) getbitfield(in + 0x69, 0x7f, 0) #define get_inquiry_halftones_supported(in) in[0x6a] #define get_inquiry_halftones_2x2(in) getbitfield(in + 0x6a, 1, 0) #define get_inquiry_halftones_4x4(in) getbitfield(in + 0x6a, 1, 1) #define get_inquiry_halftones_6x6(in) getbitfield(in + 0x6a, 1, 2) #define get_inquiry_halftones_8x8(in) getbitfield(in + 0x6a, 1, 3) #define get_inquiry_halftones_12x12(in) getbitfield(in + 0x6a, 1, 5) # define IN_halftone_2x2 0x01 # define IN_halftone_4x4 0x02 # define IN_halftone_6x6 0x04 # define IN_halftone_8x8 0x08 # define IN_halftone_12x12 0x20 #define get_inquiry_0x6b(in) in[0x6b] #define get_inquiry_0x6c(in) in[0x6c] #define get_inquiry_colorseq(in) getbitfield(in + 0x6d, 0x07, 5) # define IN_color_sequence_RGB 0x00 # define IN_color_sequence_RBG 0x01 # define IN_color_sequence_GBR 0x02 # define IN_color_sequence_GRB 0x03 # define IN_color_sequence_BRG 0x04 # define IN_color_sequence_BGR 0x05 # define IN_color_sequence_all 0x07 #define get_inquiry_color_order(in) getbitfield(in + 0x6d, 0x1f, 0) #define set_inquiry_color_order(in,val) setbitfield(in + 0x6d, 0x1f, 0, val) #define get_inquiry_color_order_pixel(in) getbitfield(in + 0x6d, 1, 0) #define get_inquiry_color_order_line_no_ccd(in) getbitfield(in + 0x6d, 1, 1) #define get_inquiry_color_order_plane(in) getbitfield(in + 0x6d, 1, 2) #define get_inquiry_color_order_line_w_ccd(in) getbitfield(in + 0x6d, 1, 3) #define get_inquiry_color_order_reserved(in) getbitfield(in + 0x6d, 1, 4) # define IN_color_ordering_pixel 0x01 # define IN_color_ordering_line_no_ccd 0x02 # define IN_color_ordering_plane 0x04 # define IN_color_ordering_line_w_ccd 0x08 #define get_inquiry_max_vidmem(in) getnbyte(in + 0x6e, 4) #define get_inquiry_0x72(in) in[0x72] #define get_inquiry_max_opt_res(in) in[0x73] #define get_inquiry_max_x_res(in) in[0x74] #define get_inquiry_max_y_res(in) in[0x75] #define get_inquiry_fb_max_scan_width(in) getnbyte(in + 0x76, 2) #define get_inquiry_fb_max_scan_length(in) getnbyte(in + 0x78, 2) #define get_inquiry_uta_x_original_point(in) getnbyte(in + 0x7a, 2) #define get_inquiry_uta_y_original_point(in) getnbyte(in + 0x7c, 2) #define get_inquiry_uta_max_scan_width(in) getnbyte(in + 0x7e, 2) #define get_inquiry_uta_max_scan_length(in) getnbyte(in + 0x80, 2) #define get_inquiry_0x82(in) in[0x82] #define get_inquiry_dor_max_opt_res(in) in[0x83] #define get_inquiry_dor_max_x_res(in) in[0x84] #define get_inquiry_dor_max_y_res(in) in[0x85] #define get_inquiry_dor_x_original_point(in) getnbyte(in + 0x86, 2) #define get_inquiry_dor_y_original_point(in) getnbyte(in + 0x88, 2) #define get_inquiry_dor_max_scan_width(in) getnbyte(in + 0x8a, 2) #define get_inquiry_dor_max_scan_length(in) getnbyte(in + 0x8c, 2) #define get_inquiry_0x8e(in) in[0x8e] #define get_inquiry_last_calibration_lamp_density(in) in[0x8f] # define IN_min_lamp_density 0x01 # define IN_max_lamp_density 0xff #define get_inquiry_0x90(in) in[0x90] #define get_inquiry_lamp_warmup_maximum_time(in) in[0x91] #define get_inquiry_wdb_length(in) getnbyte(in + 0x92, 2) #define get_inquiry_optical_resolution_residue(in) in[0x94] #define get_inquiry_x_resolution_residue(in) in[0x95] #define get_inquiry_y_resolution_residue(in) in[0x96] #define get_inquiry_analog_gamma_table(in) in[0x97] #define get_inquiry_0x98(in) in[0x98] #define get_inquiry_0x99(in) in[0x99] #define get_inquiry_max_calibration_data_lines(in) in[0x9a] #define get_inquiry_fb_uta_line_arrangement_mode(in) in[0x9b] #define get_inquiry_adf_line_arrangement_mode(in) in[0x9c] #define get_inquiry_CCD_line_distance(in) in[0x9d] #define set_inquiry_max_calibration_data_lines(out,val) out[0x9a]=val #define set_inquiry_fb_uta_line_arrangement_mode(out,val) out[0x9b]=val #define set_inquiry_adf_line_arrangement_mode(out,val) out[0x9c]=val #define set_inquiry_CCD_line_distance(out,val) out[0x9d]=val #define get_inquiry_0x9e(in) in[0x9e] #define get_inquiry_dor_optical_resolution_residue(in) in[0xa0] #define get_inquiry_dor_x_resolution_residue(in) in[0xa1] #define get_inquiry_dor_y_resolution_residue(in) in[0xa2] /* --------------------------------------------------------------------------------------------------------- */ /* although the command is defined with 6 bytes length in the doc, 10 bytes seems to be the correct length */ static unsigned char get_lamp_statusC[] = { GET_LAMP_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk get_lamp_status = { get_lamp_statusC,sizeof(get_lamp_statusC) }; #define get_lamp_status_lamp_on(in) getbitfield(in, 1, 0) /* --------------------------------------------------------------------------------------------------------- */ /* although the command is defined with 6 bytes length in the doc, 10 bytes seems to be the correct length */ static unsigned char set_lamp_statusC[] = { SET_LAMP_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk set_lamp_status = { set_lamp_statusC,sizeof(set_lamp_statusC) }; #define set_lamp_status_lamp_on(in,val) setbitfield(in + 0x03, 1, 7, val) /* --------------------------------------------------------------------------------------------------------- */ static unsigned char test_unit_readyC[] = { TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk test_unit_ready = { test_unit_readyC,sizeof(test_unit_readyC) }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char reserve_unitC[] = { RESERVE_UNIT, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk reserve_unit = { reserve_unitC, sizeof(reserve_unitC) }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char release_unitC[] = { RELEASE_UNIT, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk release_unit = { release_unitC, sizeof(release_unitC) }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char set_windowC[] = { SET_WINDOW, 0x00, /* opcode, lun */ 0x00, 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00, 0x00, /* transfer length; needs to be set */ 0x00 /* control byte */ }; #define set_SW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) static scsiblk set_window = { set_windowC, sizeof(set_windowC) }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char window_parameter_data_blockC[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00 /* Window Descriptor Length, value must be set by SHORT_WDB define */ }; #define set_WPDB_wdblen(sb, len) putnbyte(sb + 0x06, len, 2) static scsiblk window_parameter_data_block = { window_parameter_data_blockC, sizeof(window_parameter_data_blockC) }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char window_descriptor_blockC[] = { #define max_WDB_size 0xff #define used_WDB_size 0x53 /* 0x00 */ 0x00, /* Window Identifier */ #define set_WD_wid(sb, val) sb[0] = val # define WD_wid_bw 0x00 # define WD_wid_red 0x01 # define WD_wid_green 0x02 # define WD_wid_blue 0x03 # define WD_wid_all 0x00 /* 0x01 */ 0x00, /* reserved, AUTO */ #define set_WD_auto(sb, val) setbitfield(sb + 0x01, 1, 0, val) /* 0x02 */ 0x00, 0x00, /* X Resolution in dpi */ #define set_WD_Xres(sb, val) putnbyte(sb + 0x02, val, 2) /* 0x04 */ 0x00, 0x00, /* Y Resolution in dpi */ #define set_WD_Yres(sb, val) putnbyte(sb + 0x04, val, 2) /* 0x06 */ 0x00, 0x00, 0x00, 0x00, /* Upper Left X in 1200pt/inch */ #define set_WD_ULX(sb, val) putnbyte(sb + 0x06, val, 4) /* 0x0a */ 0x00, 0x00, 0x00, 0x00, /* Upper Left Y in 1200pt/inch */ #define set_WD_ULY(sb, val) putnbyte(sb + 0x0a, val, 4) /* 0x0e */ 0x00, 0x00, 0x00, 0x00, /* Width 1200pt/inch */ #define set_WD_width(sb, val) putnbyte(sb + 0x0e, val, 4) /* 0x12 */ 0x00, 0x00, 0x00, 0x00, /* Length 1200pt/inch */ #define set_WD_length(sb, val) putnbyte(sb + 0x12, val, 4) /* 0x16 */ 0xff, /* Brightness */ #define set_WD_brightness(sb, val) sb[0x16] = val /* 0x17 */ 0x80, /* Threshold */ #define set_WD_threshold(sb, val) sb[0x17] = val /* 0x18 */ 0x80, /* Contrast */ #define set_WD_contrast(sb, val) sb[0x18] = val /* 0x19 */ 0x05, /* Image Composition */ #define set_WD_composition(sb, val) sb[0x19] = val # define WD_comp_lineart 0x00 # define WD_comp_dithered 0x01 # define WD_comp_gray 0x02 # define WD_comp_gray 0x02 # define WD_comp_rgb_bilevel 0x03 # define WD_comp_rgb_dithered 0x04 # define WD_comp_rgb_full 0x05 /* 0x1a */ 0x08, /* Bits/Pixel */ #define set_WD_bitsperpixel(sb, val) sb[0x1a] = val # define WD_bits_1 0x01 # define WD_bits_8 0x08 # define WD_bits_10 0x0a /* 0x1b */ 0x00, 0x03, /* Halftone pattern */ #define set_WD_halftone(sb, val) putnbyte(sb + 0x1b, val, 2) # define WD_halftone_download 0x00 # define WD_halftone_12x12_1 0x01 # define WD_halftone_12x12_2 0x02 # define WD_halftone_8x8_1 0x03 # define WD_halftone_8x8_2 0x04 # define WD_halftone_8x8_3 0x05 # define WD_halftone_8x8_4 0x06 # define WD_halftone_8x8_5 0x07 # define WD_halftone_6x6_1 0x08 # define WD_halftone_6x6_2 0x09 # define WD_halftone_6x6_3 0x0a # define WD_halftone_4x4_1 0x0b # define WD_halftone_4x4_2 0x0c # define WD_halftone_4x4_3 0x0d # define WD_halftone_2x2_1 0x0e # define WD_halftone_2x2_2 0x0f /* 0x1d */ 0x03, /* RIF, reserved, padding type */ #define set_WD_RIF(sb, val) setbitfield(sb + 0x1d, 1, 7, val) #define set_WD_padding_type(sb,val) setbitfield(sb + 0x1d, 0x07, 0, val) # define WD_padding_byte 0x03 # define WD_padding_word 0x07 /* 0x1e */ 0x00, 0x00, /* Bit Ordering (0 = left to right;) */ /* 0x20 */ 0x00, /* Compression Type (reserved) */ /* 0x21 */ 0x00, /* Compr. Argument (reserved) */ /* 0x22 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Reserved */ /* 0x28 */ 0x01, /* Speed */ #define set_WD_speed(sb, val) sb[0x28] = val # define WD_speed_fastsmear 0x81 # define WD_speed_slowsmear 0x82 # define WD_speed_fastclear 0x01 # define WD_speed_slowclear 0x02 # define WD_speed_speedbit 0x03 # define WD_speed_smearbit 0x80 # define WD_speed_fast 0x01 # define WD_speed_slow 0x02 # define WD_speed_smear 0x80 /* 0x29 */ 0x00, /* Select Color */ #define set_WD_select_color(sb,val) setbitfield(sb+0x29, 0x07, 5, val) # define WD_color_gray 0x00 # define WD_color_red 0x04 # define WD_color_green 0x02 # define WD_color_blue 0x01 /* 0x2a */ 0xff, /* Highlight */ #define set_WD_highlight(sb, val) sb[0x2a] = val /* 0x2b */ 0x00, /* Shadow */ #define set_WD_shadow(sb, val) sb[0x2b] = val /* 0x2c */ 0x00, 0x00, /* Paper Length */ #define set_WD_paperlength(sb, val) putnbyte(sb + 0x2c, val, 2) /* 0x2e */ 0x0f, /* Gamma Function */ #define set_WD_gamma(sb, val) sb[0x2e] = val # define WD_gamma_download 0x00 # define WD_gamma_builtin1 0x01 # define WD_gamma_builtin2 0x02 # define WD_gamma_builtin3 0x03 # define WD_gamma_builtin4 0x04 # define WD_gamma_normal 0x0f /* 0x2f */ 0x11, /* Scan Module */ #define set_WD_module(sb, val) sb[0x2f] = val # define WD_module_flatbed 0x11 # define WD_module_transparency 0xff /* 0x30 */ 0x01, /* HBT, DOR, reserved, RMIF, CBHS Type */ /* CBHS = Contrast, Brightness, Highlight, Shadow */ #define set_WD_CBHS(sb, val) setbitfield(sb + 0x30, 1, 0, val) # define WD_CBHS_50 0 # define WD_CBHS_255 1 #define set_WD_FF(sb, val) setbitfield(sb + 0x30, 1, 1, val) /* FF = Fix Focus position */ #define set_WD_RMIF(sb, val) setbitfield(sb + 0x30, 1, 2, val) /* Reverse Multil Image Frmt */ #define set_WD_FDC(sb, val) setbitfield(sb + 0x30, 1, 3, val) /* document calibration */ #define set_WD_PF(sb, val) setbitfield(sb + 0x30, 1, 4, val) /* PF pre focus */ #define set_WD_LCL(sb, val) setbitfield(sb + 0x30, 1, 5, val) /* LCL (focus position) */ #define set_WD_DOR(sb, val) setbitfield(sb + 0x30, 1, 6, val) /* Double Optical Resolution */ #define set_WD_HBT(sb, val) setbitfield(sb + 0x30, 1, 7, val) /* High Byte Transfer */ # define WD_HBT_HBF 0x00 # define WD_HBT_LBF 0x01 /* 0x31 */ 0x00, 0x00, /* scan exposure level */ #define set_WD_scan_exposure_level(sb, val) putnbyte(sb+0x31, val, 2) /* 0x33 */ 0x00, 0x00, /* calibration exposure level */ #define set_WD_calibration_exposure_level(sb, val) putnbyte(sb+0x33, val, 2) /* 0x35 */ 0x00, /* reserved */ /* 0x36 */ 0x00, /* reserved */ /* 0x37 */ 0x00, /* reserved */ /* 0x38 */ 0x00, /* reserved (For Autoexposure) */ /* 0x39 */ 0x00, /* BS, reserved, Calibration Mode */ #define set_WD_batch(sb, val) setbitfield(sb + 0x39, 1, 7, val) #define set_WD_MF(sb, val) setbitfield(sb + 0x39, 1, 6, val) /* manual focus */ #define set_WD_line_arrangement(sb, val) setbitfield(sb + 0x39, 1, 5, val) # define WD_line_arrengement_by_driver 0x01 # define WD_line_arrengement_by_fw 0x00 #define set_WD_warmup(sb, val) setbitfield(sb + 0x39, 1, 4, val) #define set_WD_calibration(sb, val) setbitfield(sb + 0x39, 0x0f, 0, val) # define WD_calibration_image 0x00 # define WD_calibration_lineart 0x0f # define WD_calibration_dither 0x0e # define WD_calibration_gray 0x0d # define WD_calibration_rgb 0x0a # define WD_calibration_ignore 0x09 /* 0x3a */ 0x01, /* Color Sequence, Color Ordering Support */ #define set_WD_color_sequence(sb,val) setbitfield(sb+0x3a,0x07,5, val) # define WD_color_sequence_RGB 0x00 # define WD_color_sequence_RBG 0x01 # define WD_color_sequence_GBR 0x02 # define WD_color_sequence_GRB 0x03 # define WD_color_sequence_BRG 0x04 # define WD_color_sequence_BGR 0x05 #define set_WD_color_ordering(sb,val) setbitfield(sb+0x3a,0x1f,0, val) # define WD_color_ordering_pixel 0x01 # define WD_color_ordering_line_no_ccd 0x02 # define WD_color_ordering_plane 0x04 # define WD_color_ordering_line_w_ccd 0x08 /* 0x3b */ 0x00, /* analog gamma code (set to 1.0) */ #define set_WD_analog_gamma(sb, gamma) sb[0x3b] = gamma /* see analog_gamma_table */ /* 0x3c */ 0x00, /* Reserved */ /* 0x3d */ 0x00, /* Next Calibration Lamp Density */ #define set_WD_lamp_c_density(sb, val) sb[0x3d] = val # define WD_lamp_c_density_auto 0x00 # define WD_lamp_c_density_min 0x01 # define WD_lamp_c_density_max 0xff /* 0x3e */ 0x00, /* Reserved */ /* 0x3f */ 0x00, /* Next Scan Lamp Density */ #define set_WD_lamp_s_density(sb, val) sb[0x3f] = val # define WD_lamp_s_density_auto 0x00 # define WD_lamp_s_density_min 0x01 # define WD_lamp_s_density_max 0xff /* 0x40 */ 0x00, 0x00, 0x00, 0x00, /* Next Upper Left Y in 1200 dpt/inch */ #define set_WD_next_upper_left(sb, val) putnbyte(sb + 0x40, val, 4) /* 0x44 */ 0x00, 0x00, 0x00, 0x00, /* Pixel Count */ #define set_WD_pixel_count(sb, val) putnbyte(sb + 0x44, val, 4) /* 0x48 */ 0x00, 0x00, 0x00, 0x00, /* Line Count */ #define set_WD_line_count(sb, val) putnbyte(sb + 0x48, val, 4) /* 0x4c */ 4, 176, /* x coordiante base 1200 (pts/inch) */ #define set_WD_x_coordinate_base(sb, val) putnbyte(sb + 0x4c, val, 2) /* 0x4e */ 4, 176, /* y coordinate base 1200 (pts/inch) */ #define set_WD_y_coordinate_base(sb, val) putnbyte(sb + 0x4e, val, 2) /* 0x50 */ 0x00, /* reserved */ /* 0x51 */ 0x00, /* driver calibration need image data lines */ #define set_WD_calibration_data_lines(sb, val) sb[0x51] = val /* 0x52 */ 0x00 /* start density */ #define set_WD_start_density(sb, val) sb[0x52] = val /* if somone adds here anything, please change used_WDB_size in this file !! */ }; static scsiblk window_descriptor_block = { window_descriptor_blockC, sizeof(window_descriptor_blockC) }; /* --------------------------------------------------------------------------------------------------------- */ #define set_WDB_length(length) (window_descriptor_block.size = (length)) #define WPDB_OFF(b) (b + set_window.size) #define WDB_OFF(b, n) (b + set_window.size + \ window_parameter_data_block.size + \ ( window_descriptor_block.size * (n - 1) ) ) #define set_WPDB_wdbnum(sb,n) set_WPDB_wdblen(sb,window_descriptor_block.size*n) /* --------------------------------------------------------------------------------------------------------- */ static unsigned char scanC[] = { SCAN, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00 }; static scsiblk scan = { scanC, sizeof(scanC) - 3 }; #define set_SC_xfer_length(sb, val) sb[0x04] = val #define set_SC_quality(sb, val) setbitfield(sb + 0x05, 1, 5, val) #define set_SC_adf(sb, val) setbitfield(sb + 0x05, 1, 6, val) #define set_SC_preview(sb, val) setbitfield(sb + 0x05, 1, 7, val) #define set_SC_wid(sb, n, val) sb[0x05 + n] = val /* --------------------------------------------------------------------------------------------------------- */ /* sread instead of read because read is a libc primitive */ static unsigned char sreadC[] = { READ, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk sread = { sreadC, sizeof(sreadC) }; #define set_R_datatype_code(sb, val) sb[0x02] = val # define R_datatype_imagedata 0x00 # define R_datatype_vendorspecific 0x01 # define R_datatype_halftone 0x02 # define R_datatype_gamma 0x03 # define R_datatype_shading 0x80 # define R_datatype_gain 0x81 #define set_R_datatype_qual_winid(sb, val) sb[0x05] = val #define set_R_xfer_length(sb, val) putnbyte(sb + 0x06, val, 3) /* --------------------------------------------------------------------------------------------------------- */ static unsigned char sendC[] = { SEND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk send = { sendC, sizeof(sendC) }; #define set_S_datatype_code(sb, val) sb[0x02] = val # define S_datatype_imagedata 0x00 # define S_datatype_vendorspecific 0x01 # define S_datatype_halftone 0x02 # define S_datatype_gamma 0x03 # define S_datatype_shading 0x80 # define S_datatype_gain 0x81 #define set_S_datatype_qual_winid(sb, val) sb[0x05] = val #define set_S_xfer_length(sb, val) putnbyte(sb + 0x06, val, 3) # define S_xfer_length_gamma(l) ((l * (1024 + 1)) + 1) # define S_xfer_length_1line 0x0402 # define S_xfer_length_2line 0x0803 # define S_xfer_length_3line 0x0c04 /* FIXME: add Type 0 download curve format */ /* FIXME: add Type 1 download curve format */ static unsigned char gamma_DCF0C[] = { 0x00 }; static scsiblk gamma_DCF0 = { gamma_DCF0C, sizeof(gamma_DCF0C) }; #define set_DCF0_gamma_color(dc,col,val) dc[1 + (1025 * col)] = val # define DCF0_gamma_color_gray 0 # define DCF0_gamma_color_red 1 # define DCF0_gamma_color_green 2 # define DCF0_gamma_color_blue 3 #define set_DCF0_gamma_lines(dc,val) setbitfield(dc + 0x00, 3, 0, val) # define DCF0_gamma_one_line 1 # define DCF0_gamma_three_lines 3 static unsigned char gamma_DCF1C[] = { 0x00, 0x00 }; static scsiblk gamma_DCF1 = { gamma_DCF1C, sizeof(gamma_DCF1C) }; #define set_DCF1_gamma_color(dc,val) dc[1] = val # define DCF1_gamma_color_gray 0 # define DCF1_gamma_color_red 1 # define DCF1_gamma_color_green 2 # define DCF1_gamma_color_blue 3 static unsigned char gamma_DCF2C[] = { 0x21, 0x00, 0x01, 0x00, 0x01, 0x00 }; static scsiblk gamma_DCF2 = { gamma_DCF2C, sizeof(gamma_DCF2C) }; #define set_DCF2_gamma_color(dc,val) setbitfield(dc + 0x00, 3, 2, val) # define DCF2_gamma_color_gray 0 # define DCF2_gamma_color_red 1 # define DCF2_gamma_color_green 2 # define DCF2_gamma_color_blue 3 #define set_DCF2_gamma_lines(dc,val) setbitfield(dc + 0x00, 3, 0, val) # define DCF2_gamma_one_line 1 # define DCF2_gamma_three_lines 3 #define set_DCF2_gamma_input_bits(dc,val) dc[0x02]=val #define set_DCF2_gamma_output_bits(dc,val) dc[0x04]=val # define DCF2_gamma_8_bits 1 # define DCF2_gamma_10_bits 4 /* --------------------------------------------------------------------------------------------------------- */ static unsigned char object_positionC[] = { OBJECT_POSITION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk object_position = { object_positionC, sizeof(object_positionC) }; /* --------------------------------------------------------------------------------------------------------- */ #ifndef UMAX_HIDE_UNUSED static unsigned char get_data_buffer_statusC[] = { GET_DATA_BUFFER_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00 }; #define set_GDBS_wait(sb, val) setbitfield(sb + 0x01, 1, 0, val) #define set_GDBS_len(sb, nwins) putnbyte(sb + 0x07, (4 + (nwins * 8)), 2) static scsiblk get_data_buffer_status = { get_data_buffer_statusC, sizeof(get_data_buffer_statusC) }; /* DBS is Data Buffer Status, the header that is returned */ #define get_DBS_data_buffer_status_length(sb) getnbyte(sb, 3) #define get_DBSD_block_bit(sb) getbitfield(sb + 3, 1, 0) /* DBSD are the Data Buffer Status Descriptors, the records that * are returned following the DBS header. */ /* order is the number of the DBSD, from 1 to (length/8) */ #define get_DBSD_winid(sb, order) sb[4 + ((order - 1) * 8)] #define get_DBSD_available_data_buffer(sb,order) getnbyte(sb+4+((order-1)*8)+2,3) #define get_DBSD_filled_data_buffer(sb,order) getnbyte(sb+4+((order-1)*8)+5,3) #define gdbs_return_block_size 12 #endif /* --------------------------------------------------------------------------------------------------------- */ #ifndef UMAX_HIDE_UNUSED static unsigned char write_bufferC[] = { WRITE_BUFFER, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk write_buffer = { write_bufferC, sizeof(write_bufferC) }; #endif /* --------------------------------------------------------------------------------------------------------- */ static double analog_gamma_table[16]={1.0000, 1.0434, 1.0887, 1.1361, \ 1.1859, 1.2382, 1.2933, 1.3516, \ 1.4134, 1.4792, 1.5495, 1.6251, \ 1.7067, 1.7954, 1.8926, 2.0000 }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char request_senseC[] = { REQUEST_SENSE, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define set_RS_allocation_length(sb,val) sb[0x04]=val #define set_RS_LUN(sb,val) setbitfield(sb + 0x01, 7, 5) /* ??? */ static scsiblk request_sense = { request_senseC, sizeof(request_senseC) }; /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /* valid */ #define get_RS_CD(b) getbitfield(b+0x0f,1,6) /* 1=CDB */ #define get_RS_field_pointer(b) getnbyte(b+0x10, 2) #define get_RS_additional_sense(b) getnbyte(b+0x12, 2) #define get_RS_asb_dim_light(b) getbitfield(b+0x12,1,7) #define get_RS_asb_no_light(b) getbitfield(b+0x12,1,6) #define get_RS_asb_sensor_motor(b) getbitfield(b+0x12,1,5) #define get_RS_asb_too_light(b) getbitfield(b+0x12,1,4) #define get_RS_asb_calibration(b) getbitfield(b+0x12,1,3) #define get_RS_asb_rom(b) getbitfield(b+0x12,1,2) #define get_RS_asb_ram(b) getbitfield(b+0x12,1,1) #define get_RS_asb_cpu(b) getbitfield(b+0x12,1,0) #define get_RS_asb_scsi(b) getbitfield(b+0x13,1,7) #define get_RS_asb_timer(b) getbitfield(b+0x13,1,6) #define get_RS_asb_filter_motor(b) getbitfield(b+0x13,1,5) #define get_RS_asb_dc_adjust(b) getbitfield(b+0x13,1,1) #define get_RS_asb_uta_sensor(b) getbitfield(b+0x13,1,0) #define get_RS_scanner_error_code(b) b[0x15] #define get_RS_SCC_condition_code(b) b[0x17] #define get_RS_SCC_calibration_bytesperline(b) getnbyte(b+0x18, 4) #define get_RS_SCC_calibration_lines(b) getnbyte(b+0x1c, 2) #define get_RS_SCC_calibration_bytespp(b) b[0x1e] #define rs_return_block_size 0x1f /* --------------------------------------------------------------------------------------------------------- */ static char *cbhs_str[] = { "0-50","0-255", "0-255 autoexposure", "reserved" }; static char *scanmode_str[] = { "flatbed (FB)", "automatic document feeder (ADF)" }; static char *gamma_lines_str[]= { "reserved", "one line (gray), three pass (color) download", "reserved", "one line (gray), three lines (color) download" }; static char *color_sequence_str[]= { "R->G->B","R->B->G", "G->B->R","G->R->B", "B->R->G","B->G->R", "reserved","all supported"}; /* --------------------------------------------------------------------------------------------------------- */ static char *sense_str[] = {"NO SENSE", "RECOVERED ERROR", "NOT READY", "MEDIUM ERROR", "HARDWARE ERROR", "ILLEGAL REQUEST", "UNIT ATTENTION", "DATA PROTECT", "BLANK CHECK", "VENDOR SPECIFIC", "COPY ABORTED", "ABORTED COMMAND", "EQUAL", "VOLUME OVERFLOW", "MISCOMPARE", "??? - SENSE 0FH" }; /* --------------------------------------------------------------------------------------------------------- */ static char *scanner_error_str[] = {"no error", /* 0 */ "CPU error", "err 2", "err 3", "ROM error", "err 5", "err 6", "err 7", "err 8", "err 9", "buffer error", /* 10 */ "system buffer error", "shading buffer error", "video buffer error", "stack buffer error", "control buffer error", "gamma buffer error", "err 17", "err 18", "err 19", "lamp error", /* 20 */ "dark error", "dim error", "light error", "lamp adjust control error (by darken)", "err 25", "err 26", "err 27", "err 28", "err 29", "calibration error", /* 30 */ "dc offset error", "gain error", "auto focus error", "err 34", "err 35", "err 36", "err 37", "err 38", "err 39", "scsi error", /* 40 */ "err 41", "asic error", "timer error", "ccd error", "err 45", "err 46", "err 47", "err 48", "err 49", "uta error", /* 50 */ "uta home or motor sensor error", "err 52", "err 53", "err 54", "err 55", "err 56", "err 57", "err 58", "err 59", "adf error", /* 60 */ "adf paper jam", "adf no paper", "adf cover open", "err 64", "err 65", "err 66", "err 67", "err 68", "err 69", "fb sensor error", /* 70 */ "fb home or motor sensor error", "fb filter or motor sensor error", "fb lens or motor sensor error" "first line position error (LER error, vertical)", "first pixel position error (SER error, horizontal)", "first pixel position error for lens 2 (SER2 error, horizontal)", "err 77", "err 78", "err 79", "err", /* 80 */ "err", "err", "err", "err", "err", "err", "err", "err", "err", "err", /* 90 */ "err", "err", "err", "err", "err", "err", "err", "err", "err" /* 99 */ }; /* --------------------------------------------------------------------------------------------------------- */ #endif sane-backends-1.0.27/backend/genesys_gl841.h0000664000175000017500000002402212775312261015364 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2011-2013 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "genesys.h" /* Individual bits */ #define REG01 0x01 #define REG01_CISSET 0x80 #define REG01_DOGENB 0x40 #define REG01_DVDSET 0x20 #define REG01_M16DRAM 0x08 #define REG01_DRAMSEL 0x04 #define REG01_SHDAREA 0x02 #define REG01_SCAN 0x01 #define REG02 0x02 #define REG02_NOTHOME 0x80 #define REG02_ACDCDIS 0x40 #define REG02_AGOHOME 0x20 #define REG02_MTRPWR 0x10 #define REG02_FASTFED 0x08 #define REG02_MTRREV 0x04 #define REG02_HOMENEG 0x02 #define REG02_LONGCURV 0x01 #define REG03_LAMPDOG 0x80 #define REG03_AVEENB 0x40 #define REG03_XPASEL 0x20 #define REG03_LAMPPWR 0x10 #define REG03_LAMPTIM 0x0f #define REG04_LINEART 0x80 #define REG04_BITSET 0x40 #define REG04_AFEMOD 0x30 #define REG04_FILTER 0x0c #define REG04_FESET 0x03 #define REG04S_AFEMOD 4 #define REG05_DPIHW 0xc0 #define REG05_DPIHW_600 0x00 #define REG05_DPIHW_1200 0x40 #define REG05_DPIHW_2400 0x80 #define REG05_MTLLAMP 0x30 #define REG05_GMMENB 0x08 #define REG05_MTLBASE 0x03 #define REG06_SCANMOD 0xe0 #define REG06S_SCANMOD 5 #define REG06_PWRBIT 0x10 #define REG06_GAIN4 0x08 #define REG06_OPTEST 0x07 #define REG07_SRAMSEL 0x08 #define REG07_FASTDMA 0x04 #define REG07_DMASEL 0x02 #define REG07_DMARDWR 0x01 #define REG08_DECFLAG 0x40 #define REG08_GMMFFR 0x20 #define REG08_GMMFFG 0x10 #define REG08_GMMFFB 0x08 #define REG08_GMMZR 0x04 #define REG08_GMMZG 0x02 #define REG08_GMMZB 0x01 #define REG09_MCNTSET 0xc0 #define REG09_CLKSET 0x30 #define REG09_BACKSCAN 0x08 #define REG09_ENHANCE 0x04 #define REG09_SHORTTG 0x02 #define REG09_NWAIT 0x01 #define REG09S_MCNTSET 6 #define REG09S_CLKSET 4 #define REG0A_SRAMBUF 0x01 #define REG0D 0x0d #define REG0D_CLRLNCNT 0x01 #define REG16_CTRLHI 0x80 #define REG16_TOSHIBA 0x40 #define REG16_TGINV 0x20 #define REG16_CK1INV 0x10 #define REG16_CK2INV 0x08 #define REG16_CTRLINV 0x04 #define REG16_CKDIS 0x02 #define REG16_CTRLDIS 0x01 #define REG17_TGMODE 0xc0 #define REG17_TGMODE_NO_DUMMY 0x00 #define REG17_TGMODE_REF 0x40 #define REG17_TGMODE_XPA 0x80 #define REG17_TGW 0x3f #define REG17S_TGW 0 #define REG18_CNSET 0x80 #define REG18_DCKSEL 0x60 #define REG18_CKTOGGLE 0x10 #define REG18_CKDELAY 0x0c #define REG18_CKSEL 0x03 #define REG1A_MANUAL3 0x02 #define REG1A_MANUAL1 0x01 #define REG1A_CK4INV 0x08 #define REG1A_CK3INV 0x04 #define REG1A_LINECLP 0x02 #define REG1C_TGTIME 0x07 #define REG1D_CK4LOW 0x80 #define REG1D_CK3LOW 0x40 #define REG1D_CK1LOW 0x20 #define REG1D_TGSHLD 0x1f #define REG1DS_TGSHLD 0 #define REG1E 0x1e #define REG1E_WDTIME 0xf0 #define REG1ES_WDTIME 4 #define REG1E_LINESEL 0x0f #define REG1ES_LINESEL 0 #define REG_EXPR 0x10 #define REG_EXPG 0x12 #define REG_EXPB 0x14 #define REG_STEPNO 0x21 #define REG_FWDSTEP 0x22 #define REG_BWDSTEP 0x23 #define REG_FASTNO 0x24 #define REG_LINCNT 0x25 #define REG_DPISET 0x2c #define REG_STRPIXEL 0x30 #define REG_ENDPIXEL 0x32 #define REG_LPERIOD 0x38 #define REG40_HISPDFLG 0x04 #define REG40_MOTMFLG 0x02 #define REG40_DATAENB 0x01 #define REG41_PWRBIT 0x80 #define REG41_BUFEMPTY 0x40 #define REG41_FEEDFSH 0x20 #define REG41_SCANFSH 0x10 #define REG41_HOMESNR 0x08 #define REG41_LAMPSTS 0x04 #define REG41_FEBUSY 0x02 #define REG41_MOTORENB 0x01 #define REG58_VSMP 0xf8 #define REG58S_VSMP 3 #define REG58_VSMPW 0x07 #define REG58S_VSMPW 0 #define REG59_BSMP 0xf8 #define REG59S_BSMP 3 #define REG59_BSMPW 0x07 #define REG59S_BSMPW 0 #define REG5A_ADCLKINV 0x80 #define REG5A_RLCSEL 0x40 #define REG5A_CDSREF 0x30 #define REG5AS_CDSREF 4 #define REG5A_RLC 0x0f #define REG5AS_RLC 0 #define REG5E_DECSEL 0xe0 #define REG5ES_DECSEL 5 #define REG5E_STOPTIM 0x1f #define REG5ES_STOPTIM 0 #define REG60_ZIMOD 0x1f #define REG61_Z1MOD 0xff #define REG62_Z1MOD 0xff #define REG63_Z2MOD 0x1f #define REG64_Z2MOD 0xff #define REG65_Z2MOD 0xff #define REG67_STEPSEL 0xc0 #define REG67_FULLSTEP 0x00 #define REG67_HALFSTEP 0x40 #define REG67_QUATERSTEP 0x80 #define REG67_MTRPWM 0x3f #define REG68_FSTPSEL 0xc0 #define REG68_FULLSTEP 0x00 #define REG68_HALFSTEP 0x40 #define REG68_QUATERSTEP 0x80 #define REG68_FASTPWM 0x3f #define REG6B_MULTFILM 0x80 #define REG6B_GPOM13 0x40 #define REG6B_GPOM12 0x20 #define REG6B_GPOM11 0x10 #define REG6B_GPO18 0x02 #define REG6B_GPO17 0x01 #define REG6B 0x6b #define REG6C 0x6c #define REG6C_GPIOH 0xff #define REG6C_GPIOL 0xff #define REG6D 0x6d #define REG6E 0x6e #define REG6F 0x6f #define REG87_LEDADD 0x04 enum { reg_0x01 = 0, reg_0x02, reg_0x03, reg_0x04, reg_0x05, reg_0x06, reg_0x07, reg_0x08, reg_0x09, reg_0x0a, reg_0x10, reg_0x11, reg_0x12, reg_0x13, reg_0x14, reg_0x15, reg_0x16, reg_0x17, reg_0x18, reg_0x19, reg_0x1a, reg_0x1b, reg_0x1c, reg_0x1d, reg_0x1e, reg_0x1f, reg_0x20, reg_0x21, reg_0x22, reg_0x23, reg_0x24, reg_0x25, reg_0x26, reg_0x27, reg_0x29, reg_0x2c, reg_0x2d, reg_0x2e, reg_0x2f, reg_0x30, reg_0x31, reg_0x32, reg_0x33, reg_0x34, reg_0x35, reg_0x36, reg_0x37, reg_0x38, reg_0x39, reg_0x3d, reg_0x3e, reg_0x3f, reg_0x52, reg_0x53, reg_0x54, reg_0x55, reg_0x56, reg_0x57, reg_0x58, reg_0x59, reg_0x5a, reg_0x5d, reg_0x5e, reg_0x5f, reg_0x60, reg_0x61, reg_0x62, reg_0x63, reg_0x64, reg_0x65, reg_0x66, reg_0x67, reg_0x68, reg_0x69, reg_0x6a, reg_0x6b, reg_0x6c, reg_0x6d, reg_0x6e, reg_0x6f, reg_0x70, reg_0x71, reg_0x72, reg_0x73, reg_0x74, reg_0x75, reg_0x76, reg_0x77, reg_0x78, reg_0x79, reg_0x7a, reg_0x7b, reg_0x7c, reg_0x7d, reg_0x7e, reg_0x7f, reg_0x80, reg_0x81, reg_0x82, reg_0x83, reg_0x84, reg_0x85, reg_0x86, reg_0x87, reg_0x88, reg_0x89, GENESYS_GL841_MAX_REGS }; #define INITREG(adr,val) {dev->reg[index].address=adr;dev->reg[index].value=val;index++;} /** * prototypes declaration in case of unit testing */ #ifdef UNIT_TESTING SANE_Status gl841_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, float yres, float startx, float starty, float pixels, float lines, unsigned int depth, unsigned int channels, int color_filter, unsigned int flags); SANE_Status gl841_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor); SANE_Status gl841_end_scan (Genesys_Device * dev, Genesys_Register_Set __sane_unused__ * reg, SANE_Bool check_stop); SANE_Status gl841_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home); SANE_Status sanei_gl841_repark_head (Genesys_Device * dev); SANE_Status gl841_feed (Genesys_Device * dev, int steps); SANE_Status gl841_init_motor_regs_scan(Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int scan_exposure_time, float scan_yres, int scan_step_type, unsigned int scan_lines, unsigned int scan_dummy, unsigned int feed_steps, int scan_power_mode, unsigned int flags) ; SANE_Status gl841_stop_action (Genesys_Device * dev); SANE_Status gl841_start_action (Genesys_Device * dev); SANE_Status gl841_init_motor_regs(Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int feed_steps, unsigned int action, unsigned int flags); SANE_Status gl841_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps); SANE_Status gl841_bulk_write_data_gamma (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len); SANE_Status gl841_offset_calibration (Genesys_Device * dev); SANE_Status gl841_coarse_gain_calibration (Genesys_Device * dev, int dpi); SANE_Status gl841_led_calibration (Genesys_Device * dev); SANE_Status gl841_send_shading_data (Genesys_Device * dev, uint8_t * data, int size); int gl841_scan_step_type(Genesys_Device *dev, int yres); SANE_Status gl841_write_freq(Genesys_Device *dev, unsigned int ydpi); #endif GENESYS_STATIC int gl841_exposure_time(Genesys_Device *dev, float slope_dpi, int scan_step_type, int start, int used_pixels, int *scan_power_mode); sane-backends-1.0.27/backend/kodak-cmd.h0000664000175000017500000006072712112021330014611 00000000000000#ifndef KODAK_CMD_H #define KODAK_CMD_H /* * Part of SANE - Scanner Access Now Easy. * * Please see to opening comments in kodak.c */ /* ==================================================================== */ /* helper char array manipulation functions */ static void setbitfield (unsigned char *pageaddr, int mask, int shift, int val) { *pageaddr = (*pageaddr & ~(mask << shift)) | ((val & mask) << shift); } static int getbitfield (unsigned char *pageaddr, int shift, int mask) { return ((*pageaddr >> shift) & mask); } static int getnbyte (unsigned char *pnt, int nbytes) { unsigned int result = 0; int i; for (i = 0; i < nbytes; i++) result = (result << 8) | (pnt[i] & 0xff); return result; } static void putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) { int i; for (i = nbytes - 1; i >= 0; i--) { pnt[i] = value & 0xff; value = value >> 8; } } /* ==================================================================== */ /* SCSI commands */ #define set_SCSI_opcode(out, val) out[0]=val #define set_SCSI_lun(out, val) setbitfield(out + 1, 7, 5, val) /* ==================================================================== */ /* TEST_UNIT_READY */ #define TEST_UNIT_READY_code 0x00 #define TEST_UNIT_READY_len 6 /* ==================================================================== */ /* REQUEST_SENSE */ /* out */ #define REQUEST_SENSE_code 0x03 #define REQUEST_SENSE_len 6 #define RS_return_size 0x12 /* in */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 7, 1) #define get_RS_error_code(b) getbitfield(b + 0x00, 0, 0x7f) #define RS_error_code_current 0x70 #define RS_error_code_deferred 0x71 #define get_RS_segment_num(b) b[1] #define get_RS_filemark(b) getbitfield(b + 0x02, 7, 1) #define get_RS_EOM(b) getbitfield(b + 0x02, 6, 1) #define get_RS_ILI(b) getbitfield(b + 0x02, 5, 1) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0, 0x0f) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_cmd_info(b) getnbyte(b+8, 4) #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_FRUC(b) b[0x0e] #define get_RS_SKSV(b) getbitfield(b+0x0f,7,1) #define get_RS_SKSB(b) getnbyte(b+0x0f, 3) /* ==================================================================== */ /* INQUIRY */ /* out */ #define INQUIRY_code 0x12 #define INQUIRY_len 6 #define set_I_evpd(out, val) setbitfield(out + 1, 1, 0, val) #define set_I_page_code(out, val) out[0x02]=val #define I_page_code_default 0 #define set_I_data_length(out,n) out[0x04]=n #define I_data_len 128 /* in */ #define get_I_periph_qual(in) getbitfield(in, 5, 7) #define I_periph_qual_valid 0x00 #define I_periph_qual_nolun 0x03 #define get_I_periph_devtype(in) getbitfield(in, 0, 0x1f) #define I_periph_devtype_scanner 0x06 #define I_periph_devtype_unknown 0x1f /* dont use these, until vendor */ #define get_I_rmb(in) getbitfield(in + 1, 7, 1) #define get_I_devtype_qual(in) getbitfield(in + 1, 0, 0x7f) #define get_I_iso_version(in) getbitfield(in + 2, 6, 3) #define get_I_ecma_version(in) getbitfield(in + 2, 3, 7) #define get_I_ansi_version(in) getbitfield(in + 2, 0, 7) #define get_I_aenc(in) getbitfield(in + 3, 7, 1) #define get_I_trmiop(in) getbitfield(in + 3, 6, 1) #define get_I_resonse_format(in) getbitfield(in + 3, 0, 0x0f) #define get_I_length(in) getnbyte(in + 4, 1) #define get_I_reladr(in) getbitfield(in + 7, 7, 1) #define get_I_wbus32(in) getbitfield(in + 7, 6, 1) #define get_I_wbus16(in) getbitfield(in + 7, 5, 1) #define get_I_sync(in) getbitfield(in + 7, 4, 1) #define get_I_linked(in) getbitfield(in + 7, 3, 1) #define get_I_cmdque(in) getbitfield(in + 7, 1, 1) #define get_I_sftre(in) getbitfield(in + 7, 0, 1) #define get_I_vendor(in, buf) strncpy(buf,(char *)in + 0x08, 0x08) #define get_I_product(in, buf) strncpy(buf,(char *)in + 0x10, 0x10) #define get_I_version(in, buf) strncpy(buf,(char *)in + 0x20, 0x04) #define get_I_build(in, buf) strncpy(buf,(char *)in + 0x24, 0x02) #define get_I_mf_disable(in) getbitfield(in + 38, 7, 1) #define get_I_checkdigit(in) getbitfield(in + 38, 6, 1) #define get_I_front_prism(in) getbitfield(in + 38, 5, 1) #define get_I_compressed_gray(in) getbitfield(in + 38, 4, 1) #define get_I_front_toggle(in) getbitfield(in + 38, 3, 1) #define get_I_front_dp1(in) getbitfield(in + 38, 2, 1) #define get_I_front_color(in) getbitfield(in + 38, 1, 1) #define get_I_front_atp(in) getbitfield(in + 38, 0, 1) #define get_I_dp1_180(in) getbitfield(in + 39, 7, 1) #define get_I_mf_pause(in) getbitfield(in + 39, 6, 1) #define get_I_rear_prism(in) getbitfield(in + 39, 5, 1) #define get_I_uncompressed_gray(in) getbitfield(in + 39, 4, 1) #define get_I_rear_toggle(in) getbitfield(in + 39, 3, 1) #define get_I_rear_dp1(in) getbitfield(in + 39, 2, 1) #define get_I_rear_color(in) getbitfield(in + 39, 1, 1) #define get_I_rear_atp(in) getbitfield(in + 39, 0, 1) #define get_I_min_bin_res(in) getnbyte(in + 40, 2) #define get_I_max_bin_res(in) getnbyte(in + 42, 2) #define get_I_min_col_res(in) getnbyte(in + 44, 2) #define get_I_max_col_res(in) getnbyte(in + 46, 2) #define get_I_max_image_width(in) getnbyte(in + 48, 4) #define get_I_max_image_length(in) getnbyte(in + 52, 4) /* 56-95 reserved */ #define get_I_finecrop(in) getbitfield(in + 96, 7, 1) #define get_I_ithresh(in) getbitfield(in + 96, 6, 1) #define get_I_ecd(in) getbitfield(in + 96, 3, 1) #define get_I_vblr(in) getbitfield(in + 96, 2, 1) #define get_I_elevator(in) getbitfield(in + 96, 1, 1) #define get_I_relcrop(in) getbitfield(in + 96, 0, 1) #define get_I_cdeskew(in) getbitfield(in + 97, 7, 1) #define get_I_ia(in) getbitfield(in + 97, 6, 1) #define get_I_patch(in) getbitfield(in + 97, 5, 1) #define get_I_nullmode(in) getbitfield(in + 97, 4, 1) #define get_I_sabre(in) getbitfield(in + 97, 3, 1) #define get_I_lddds(in) getbitfield(in + 97, 2, 1) #define get_I_uddds(in) getbitfield(in + 97, 1, 1) #define get_I_fixedgap(in) getbitfield(in + 97, 0, 1) #define get_I_hr_printer(in) getbitfield(in + 98, 6, 1) #define get_I_elev_100_250(in) getbitfield(in + 98, 5, 1) #define get_I_udds_individual(in) getbitfield(in + 98, 4, 1) #define get_I_auto_color(in) getbitfield(in + 98, 3, 1) #define get_I_wb(in) getbitfield(in + 98, 2, 1) #define get_I_es(in) getbitfield(in + 98, 1, 1) #define get_I_fc(in) getbitfield(in + 98, 0, 1) #define get_I_max_rate(in) getnbyte(in + 99, 2) #define get_I_buffer_size(in) getnbyte(in + 101, 4) /* ==================================================================== */ /* RESERVE UNIT */ #define RESERVE_UNIT_code 0x16 #define RESERVE_UNIT_len 6 /* ==================================================================== */ /* RELEASE UNIT */ #define RELEASE_UNIT_code 0x17 #define RELEASE_UNIT_len 6 /* ==================================================================== */ /* SCAN */ #define SCAN_code 0x1b #define SCAN_len 10 #define set_SC_xfer_length(sb, val) sb[0x04] = (unsigned char)val /* ==================================================================== */ /* SEND DIAGNOSTIC */ #define SEND_DIAGNOSTIC_code 0x1d #define SEND_DIAGNOSTIC_len 6 /* ==================================================================== */ /* SET WINDOW */ #define SET_WINDOW_code 0x24 #define SET_WINDOW_len 10 /* transfer length is header+descriptor (8+64) */ #define set_SW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) /* ==================================================================== */ /* GET WINDOW */ #define GET_WINDOW_code 0x25 #define GET_WINDOW_len 10 #define set_GW_single(sb, val) setbitfield(sb + 1, 1, 0, val) #define set_GW_wid(sb, len) sb[5] = len /* window transfer length is for following header+descriptor (8+64) */ #define set_GW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) /* ==================================================================== */ /* WINDOW HEADER, used by get and set */ #define WINDOW_HEADER_len 8 /* header transfer length is for following descriptor (64) */ #define set_WH_data_len(sb, len) putnbyte(sb, len, 2) #define set_WH_desc_len(sb, len) putnbyte(sb + 0x06, len, 2) /* ==================================================================== */ /* WINDOW descriptor, used by get and set */ #define WINDOW_DESCRIPTOR_len 64 #define set_WD_wid(sb, val) sb[0]=val #define WD_wid_front_binary 0x01 #define WD_wid_back_binary 0x02 #define WD_wid_front_color 0x03 #define WD_wid_back_color 0x04 /* color/gray = 100,150,200,240,300 */ /* binary = 200,240,300,400 */ #define set_WD_Xres(sb, val) putnbyte(sb + 0x02, val, 2) #define get_WD_Xres(sb) getnbyte(sb + 0x02, 2) /* color/gray = 100,150,200,240,300 */ /* binary = 200,240,300,400 */ #define set_WD_Yres(sb, val) putnbyte(sb + 0x04, val, 2) #define get_WD_Yres(sb) getnbyte(sb + 0x04, 2) #define set_WD_ULX(sb, val) putnbyte(sb + 0x06, val, 4) #define get_WD_ULX(sb) getnbyte(sb + 0x06, 4) #define set_WD_ULY(sb, val) putnbyte(sb + 0x0a, val, 4) #define get_WD_ULY(sb) getnbyte(sb + 0x0a, 4) #define set_WD_width(sb, val) putnbyte(sb + 0x0e, val, 4) #define get_WD_width(sb) getnbyte(sb + 0x0e, 4) #define set_WD_length(sb, val) putnbyte(sb + 0x12, val, 4) #define get_WD_length(sb) getnbyte(sb + 0x12, 4) #define set_WD_brightness(sb, val) sb[0x16] = val #define get_WD_brightness(sb) sb[0x16] #define set_WD_threshold(sb, val) sb[0x17] = val #define get_WD_threshold(sb) sb[0x17] #define set_WD_contrast(sb, val) sb[0x18] = val #define get_WD_contrast(sb) sb[0x18] #define set_WD_composition(sb, val) sb[0x19] = val #define get_WD_composition(sb) sb[0x19] #define WD_compo_LINEART 0 #define WD_compo_HALFTONE 1 #define WD_compo_MULTILEVEL 5 /* 1, 8, or 24 */ #define set_WD_bitsperpixel(sb, val) sb[0x1a] = val #define get_WD_bitsperpixel(sb) sb[0x1a] /* not used? */ #define set_WD_halftone(sb, val) putnbyte(sb + 0x1b, val, 2) #define get_WD_halftone(sb) getnbyte(sb + 0x1b, 2) #define set_WD_rif(sb, val) setbitfield(sb + 0x1d, 1, 7, val) #define get_WD_rif(sb) getbitfield(sb + 0x1d, 7, 1) /* always set to 1? */ #define set_WD_bitorder(sb, val) putnbyte(sb + 0x1e, val, 2) #define get_WD_bitorder(sb) getnbyte(sb + 0x1e, 2) #define set_WD_compress_type(sb, val) sb[0x20] = val #define get_WD_compress_type(sb) sb[0x20] #define WD_compr_NONE 0 #define WD_compr_FAXG4 3 #define WD_compr_JPEG 0x80 /* not used? */ #define set_WD_compress_arg(sb, val) sb[0x21] = val #define get_WD_compress_arg(sb) sb[0x21] /* kodak specific stuff starts here */ #define set_WD_noise_filter(sb, val) setbitfield(sb + 40, 7, 2, val) #define WD_nf_NONE 0 #define WD_nf_LONE 1 #define WD_nf_MAJORITY 2 #define get_WD_noise_filter(sb) getbitfield(sb + 40, 7, 1) #define set_WD_allow_zero(sb, val) setbitfield(sb + 40, 1, 1, val) #define get_WD_allow_zero(sb, val) getbitfield(sb + 40, 1, 1) #define set_WD_vblr(sb, val) setbitfield(sb + 40, 1, 0, val) #define get_WD_vblr(sb, val) getbitfield(sb + 40, 0, 1) #define set_WD_image_overscan(sb, val) putnbyte(sb + 41, val, 2) #define set_WD_IS(sb, val) setbitfield(sb + 43, 1, 7, val) #define set_WD_deskew(sb, val) setbitfield(sb + 43, 1, 6, val) #define WD_deskew_DISABLE 0 #define WD_deskew_ENABLE 1 #define set_WD_BR(sb, val) setbitfield(sb + 43, 1, 5, val) #define set_WD_BF(sb, val) setbitfield(sb + 43, 1, 4, val) #define set_WD_ED(sb, val) setbitfield(sb + 43, 1, 3, val) #define set_WD_HR(sb, val) setbitfield(sb + 43, 1, 2, val) #define set_WD_cropping(sb, val) setbitfield(sb + 43, 3, 0, val) #define WD_crop_AUTO 0 #define WD_crop_FIXED 1 #define WD_crop_RELATIVE 2 #define WD_crop_FINE 3 #define set_WD_ithresh(sb, val) setbitfield(sb + 44, 1, 7, val) #define WD_ithresh_DISABLE 0 #define WD_ithresh_ENABLE 1 #define set_WD_dropout_color(sb, val) setbitfield(sb + 44, 7, 0, val) #define set_WD_dropout_bg(sb, val) sb[45] = val #define set_WD_dropout_thresh(sb, val) sb[46] = val #define set_WD_dropout_source(sb, val) sb[47] = val #define set_WD_disable_gamma(sb, val) sb[48] = val #define set_WD_ortho_rotation(sb, val) sb[49] = val #define set_WD_fine_crop_max(sb, val) putnbyte(sb + 50, val, 2) #define set_WD_color_detect_thresh(sb, val) sb[52] = val #define set_WD_color_detect_area(sb, val) sb[53] = val #define set_WD_border_add(sb, val) sb[54] = val #define max_WDB_size 0xc8 /* ==================================================================== */ /* READ */ #define READ_code 0x28 #define READ_len 10 /* ==================================================================== */ /* SEND */ #define SEND_code 0x2a #define SEND_len 10 /* ==================================================================== */ /* READ and SEND are basically the same, so the following 'SR' macros */ /* output */ #define set_SR_datatype_code(sb, val) sb[0x02] = val #define SR_datatype_imagedata 0x00 #define SR_datatype_random 0x80 #define SR_datatype_imageheader 0x81 #define SR_len_imageheader 1088 #define set_SR_datatype_qual(sb, val) memcpy(sb + 4, val, 2) #define set_SR_xfer_length(sb, val) putnbyte(sb + 6, val, 3) /* if the data type is 'imageheader': */ #define get_SR_ih_header_length(in) getnbyte(in + 0x00, 4) #define get_SR_ih_image_length(in) getnbyte(in + 0x04, 4) #define get_SR_ih_image_id(in) in[8] #define get_SR_ih_resolution(in) getnbyte(in + 9, 2) #define get_SR_ih_ulx(in) getnbyte(in + 11, 4) #define get_SR_ih_uly(in) getnbyte(in + 15, 4) #define get_SR_ih_width(in) getnbyte(in + 19, 4) #define get_SR_ih_length(in) getnbyte(in + 23, 4) #define get_SR_ih_bpp(in) in[27] #define get_SR_ih_comp_type(in) in[28] #define get_SR_ih_ACD(in) getbit(in + 29, 1, 5) #define get_SR_ih_MF(in) getbit(in + 29, 1, 4) #define get_SR_ih_RIF(in) getbit(in + 29, 1, 2) #define get_SR_ih_ID(in) getbit(in + 29, 1, 1) #define get_SR_ih_DE(in) getbit(in + 29, 1, 0) #define get_SR_ih_skew_angle(in) getnbyte(in + 30, 2) #define get_SR_ih_ia_level(in) in[32] #define get_SR_ih_ia(in) getnbyte(in + 33, 60) #define get_SR_ih_print_string(in) getnbyte(in + 93, 60) #define get_SR_ih_seqence_counter(in) getnbyte(in + 173, 4) #define get_SR_ih_ia_f1_definition(in) in[177] #define get_SR_ih_ia_f1_value(in) getnbyte(in + 178, 18) #define get_SR_ih_ia_f2_definition(in) in[196] #define get_SR_ih_ia_f2_value(in) getnbyte(in + 197, 18) #define get_SR_ih_ia_f3_definition(in) in[215] #define get_SR_ih_ia_f3_value(in) getnbyte(in + 216, 18) #define get_SR_ih_ia_f4_definition(in) in[234] #define get_SR_ih_ia_f5_value(in) getnbyte(in + 235, 18) #define get_SR_ih_PD(in) getbit(in + 253, 1, 7) #define get_SR_ih_patch_type(in) getbit(in + 253, 0x7f, 0) #define get_SR_ih_deskew_confidence(in) in[255] #define get_SR_ih_bt_contrast_perc(in) in[256] #define get_SR_ih_bt_contrast(in) getnbyte(in + 257, 2) #define get_SR_ih_bt_threshold(in) in[259] #define get_SR_ih_sum_histogram(in) getnbyte(in + 260, 256) #define get_SR_ih_diff_histogram(in) getnbyte(in + 516, 256) #define get_SR_ih_gamma_table(in) getnbyte(in + 772, 256) #define get_SR_ih_auto_color_area(in) in[1028] #define get_SR_ih_auto_color_thresh(in) in[1029] /* ==================================================================== */ /* if the data type is 'random', we have all kinds of 2 byte */ /* qualifiers and oddly sized commands. some are bidirectional */ /* while others are only send or read */ /* all payloads for these seem to start with 4 byte inclusive length? */ #define set_SR_payload_len(sb, val) putnbyte(sb, val, 4) /* */ #define SR_qual_jpeg_quant "JQ" /*both*/ #define SR_len_jpeg_quant 262 /*front and back tables*/ /* */ #define SR_qual_config "SC" /*both*/ #define SR_len_config 512 /*lots of stuff*/ #define set_SR_sc_length(in,val) putnbyte(in, val, 4) #define get_SR_sc_length(in) getnbyte(in, 4) #define set_SR_sc_io1(in,val) putnbyte(in + 4, val, 1) #define get_SR_sc_io1(in) getnbyte(in + 4, 1) #define set_SR_sc_io2(in,val) putnbyte(in + 5, val, 1) #define get_SR_sc_io2(in) getnbyte(in + 5, 1) #define set_SR_sc_io3(in,val) putnbyte(in + 6, val, 1) #define get_SR_sc_io3(in) getnbyte(in + 6, 1) #define set_SR_sc_io4(in,val) putnbyte(in + 7, val, 1) #define get_SR_sc_io4(in) getnbyte(in + 7, 1) #define SR_sc_io_none 0 #define SR_sc_io_front_binary 1 #define SR_sc_io_rear_binary 2 #define SR_sc_io_front_color 3 #define SR_sc_io_rear_color 4 #define set_SR_sc_trans_to(in,val) putnbyte(in + 13, val, 2) #define get_SR_sc_trans_to(in) getnbyte(in + 13, 2) #define set_SR_sc_trans_to_resp(in,val) putnbyte(in + 15, val, 1) #define get_SR_sc_trans_to_resp(in) getnbyte(in + 15, 1) #define get_SR_sc_DLS(in) getbitfield(in + 16, 7, 1) #define set_SR_sc_DLS(in, val) setbitfield(in + 16, 1, 7) #define get_SR_sc_DMS(in) getbitfield(in + 16, 6, 1) #define set_SR_sc_DMS(in, val) setbitfield(in + 16, 1, 6) #define get_SR_sc_DRS(in) getbitfield(in + 16, 5, 1) #define set_SR_sc_DRS(in, val) setbitfield(in + 16, 1, 5) #define get_SR_sc_UD_mode(in) getbitfield(in + 16, 0, 0x1f) #define set_SR_sc_UD_mode(in, val) setbitfield(in + 16, 0x1f, 0) #define get_SR_sc_LD_length(in) getnbyte(in + 17, 2) #define set_SR_sc_LD_length(in, val) setnbyte(in + 17, 2) #define get_SR_sc_DF_resp(in) getnbyte(in + 19, 1) #define set_SR_sc_DF_resp(in, val) setnbyte(in + 19, 1) #define get_SR_sc_TP_mode(in) getnbyte(in + 20, 1) #define get_SR_sc_CPT(in) getbitfield(in + 21, 0, 1) #define get_SR_sc_POD_mode(in) getnbyte(in + 22, 2) #define get_SR_sc_batch_mode(in) getnbyte(in + 24, 2) #define get_SR_sc_batch_level(in) getnbyte(in + 26, 1) #define get_SR_sc_start_batch(in) getnbyte(in + 27, 1) #define get_SR_sc_end_batch(in) getnbyte(in + 28, 1) #define get_SR_sc_patch_conf_tone(in) getnbyte(in + 29, 1) #define get_SR_sc_T6_patch(in) getbitfield(in + 30, 7, 1) #define get_SR_sc_T5_patch(in) getbitfield(in + 30, 6, 1) #define get_SR_sc_T4_patch(in) getbitfield(in + 30, 5, 1) #define get_SR_sc_T3_patch(in) getbitfield(in + 30, 4, 1) #define get_SR_sc_T2_patch(in) getbitfield(in + 30, 3, 1) #define get_SR_sc_T1_patch(in) getbitfield(in + 30, 2, 1) #define get_SR_sc_trans_patch(in) getbitfield(in + 30, 0, 3) #define get_SR_sc_IA_A_start(in) getnbyte(in + 31, 18) #define get_SR_sc_IA_B_start(in) getnbyte(in + 49, 18) #define get_SR_sc_IA_C_start(in) getnbyte(in + 67, 18) #define get_SR_sc_IA_D_start(in) getnbyte(in + 85, 18) #define get_SR_sc_IA_A_def(in) getnbyte(in + 103, 1) #define get_SR_sc_IA_B_def(in) getnbyte(in + 104, 1) #define get_SR_sc_IA_C_def(in) getnbyte(in + 105, 1) #define get_SR_sc_IA_D_def(in) getnbyte(in + 106, 1) #define get_SR_sc_IA_ltf_3(in) getnbyte(in + 107, 1) #define get_SR_sc_IA_ltf_2(in) getnbyte(in + 108, 1) #define get_SR_sc_IA_ltf_1(in) getnbyte(in + 109, 1) #define get_SR_sc_DP1_pos(in) getnbyte(in + 110, 4) #define get_SR_sc_hires_mode(in) getbitfield(in + 114, 4, 0xf) #define get_SR_sc_DP1_font(in) getbitfield(in + 114, 0, 0xf) #define get_SR_sc_DP1_orient(in) getnbyte(in + 115, 1) #define get_SR_sc_DP1_IA_format(in) getnbyte(in + 116, 1) #define get_SR_sc_DP1_date_format(in) getnbyte(in + 117, 1) #define get_SR_sc_DP1_date_delim(in) getnbyte(in + 118, 1) #define get_SR_sc_DP1_start_seq(in) getnbyte(in + 119, 4) #define get_SR_sc_DP1_seq_date_format(in) getnbyte(in + 123, 1) #define get_SR_sc_DP1_seq_print_width(in) getnbyte(in + 124, 1) #define get_SR_sc_DP1_msg1(in) getnbyte(in + 125, 40) #define get_SR_sc_DP1_msg2(in) getnbyte(in + 165, 40) #define get_SR_sc_DP1_msg3(in) getnbyte(in + 205, 40) #define get_SR_sc_DP1_msg4(in) getnbyte(in + 245, 40) #define get_SR_sc_DP1_msg5(in) getnbyte(in + 285, 40) #define get_SR_sc_DP1_msg6(in) getnbyte(in + 325, 40) #define get_SR_sc_DP1_l1_template(in) getnbyte(in + 365, 20) #define get_SR_sc_DP1_l2_template(in) getnbyte(in + 385, 20) #define get_SR_sc_DP1_l3_template(in) getnbyte(in + 405, 20) #define get_SR_sc_UDFK1(in) getnbyte(in + 425, 1) #define get_SR_sc_UDFK2(in) getnbyte(in + 426, 1) #define get_SR_sc_UDFK3(in) getnbyte(in + 427, 1) #define get_SR_sc_MPASS(in) getbitfield(in + 428, 1, 1) #define get_SR_sc_CE(in) getbitfield(in + 428, 0, 1) #define get_SR_sc_elevator_mode(in) getnbyte(in + 429, 1) #define get_SR_sc_stacking_mode(in) getnbyte(in + 430, 1) #define get_SR_sc_energy_star_to(in) getnbyte(in + 433, 1) #define get_SR_sc_PR1(in) getbitfield(in + 435, 3, 1) #define get_SR_sc_PR2(in) getbitfield(in + 435, 2, 1) #define get_SR_sc_PR3(in) getbitfield(in + 435, 1, 1) #define get_SR_sc_PR4(in) getbitfield(in + 435, 0, 1) /* */ #define SR_qual_color_table "CT" /*read*/ #define SR_len_color_table 52 /* */ #define SR_qual_color_table "CT" /*read*/ #define SR_len_color_table 52 /* */ #define SR_qual_clear "CB" /*send*/ #define SR_len_clear 0 /* */ #define SR_qual_end "GX" /*send*/ #define SR_len_end 0 /* local and gmt time commands, same format */ #define SR_qual_clock "LC" /*both*/ #define SR_qual_gmt "GT" /*send*/ #define SR_len_time 10 #define set_SR_time_hour(sb, val) putnbyte(sb+4, val, 1) #define set_SR_time_min(sb, val) putnbyte(sb+5, val, 1) #define set_SR_time_mon(sb, val) putnbyte(sb+6, val, 1) #define set_SR_time_day(sb, val) putnbyte(sb+7, val, 1) #define set_SR_time_year(sb, val) putnbyte(sb+8, val, 2) /* */ #define SR_qual_lamp "LD" /*????*/ #define SR_len_lamp 0 /*????*/ /* */ #define SR_qual_log_en "L0" /*read*/ #define SR_qual_log_fr "L1" /*read*/ #define SR_qual_log_it "L2" /*read*/ #define SR_qual_log_de "L3" /*read*/ #define SR_qual_log_br "L4" /*read*/ #define SR_qual_log_jp "L5" /*read*/ #define SR_qual_log_nl "L6" /*read*/ #define SR_qual_log_es "L7" /*read*/ #define SR_qual_log_cns "L8" /*read*/ #define SR_qual_log_cnt "L9" /*read*/ #define SR_qual_log_ko "LA" /*read*/ #define SR_qual_log_ru "LB" /*read*/ #define SR_qual_log_cz "LE" /*read*/ #define SR_qual_log_tr "LF" /*read*/ /* */ #define SR_qual_startstop "SS" /*send*/ #define SR_len_startstop 5 #define set_SR_startstop_cmd(sb, val) putnbyte(sb+4, val, 1) /* */ #define SR_qual_media "CM" /*read*/ #define SR_len_media 5 #define get_SR_media_status(sb, val) getnbyte(sb+4, 1) /* */ #define SR_qual_img_cal "IC" /*send*/ #define SR_len_img_cal 0 /* */ #define SR_qual_udds_cal "UC" /*send*/ #define SR_len_udds_cal 0 /* ==================================================================== */ /* WRITE BUFFER */ #define WRITE_BUFFER_code 0x3b #define WRITE_BUFFER_len 10 #define set_WB_mode(sb, val) setbitfield(sb + 0x01, 7, 0, val) #define WB_mode_front 6 #define WB_mode_back 7 #define set_WB_buffer_id(sb, val) sb[0x02] = (unsigned char)val #define WB_buffer_id_block(sb, val) 0 #define WB_buffer_id_last(sb, val) 1 #define set_WB_buffer_offset(sb, val) putnbyte(sb + 3, val, 3) #define set_WB_list_length(sb, val) putnbyte(sb + 6, val, 3) #endif sane-backends-1.0.27/backend/xerox_mfp.conf.in0000664000175000017500000000751512775312261016112 00000000000000#xerox_mfp.conf # all entries are sorted in USB IDs numerical order ###################### ### Samsung Models ### ###################### #Samsung X4300 Series usb 0x04e8 0x3324 #Samsung K4350 Series usb 0x04e8 0x3325 #Samsung X7600 Series usb 0x04e8 0x3326 #Samsung K7600 Series usb 0x04e8 0x3327 #Samsung K703 Series usb 0x04e8 0x3331 #Samsung X703 Series usb 0x04e8 0x3332 #Samsung SCX-4x16 Series usb 0x04e8 0x3409 #Samsung SCX-6x20 Series usb 0x04e8 0x340d #Samsung MFP-560 Series usb 0x04e8 0x340e #Samsung MFP-750 Series usb 0x04e8 0x340f #Samsung SCX-4x20 Series usb 0x04e8 0x3412 #Samsung SCX-4100 Series usb 0x04e8 0x3413 #Samsung SCX-4x21 Series usb 0x04e8 0x3419 #Samsung SCX-5x30 Series usb 0x04e8 0x341a #Samsung SCX-4200 Series usb 0x04e8 0x341b #Samsung CLX-3160 Series usb 0x04e8 0x341c #Samsung SCX-6x22 Series usb 0x04e8 0x341d #Samsung SCX-4725 Series, Samsung SCX4725-FN usb 0x04e8 0x341f #Samsung SCX-6x45 Series usb 0x04e8 0x3420 #Samsung CLX-8380 Series usb 0x04e8 0x3421 #Samsung CLX-216x Series usb 0x04e8 0x3425 #Samsung SCX-4500 Series usb 0x04e8 0x3426 #Samsung CLX-6200 Series usb 0x04e8 0x3427 #Samsung CLX-6240 Series usb 0x04e8 0x3428 #Samsung SCX-6x55 Series usb 0x04e8 0x3429 #Samsung CLX-3170 Series: Samsung CLX-3170fn & CLX-3175FW usb 0x04e8 0x342a #Samsung SCX-4500W Series usb 0x04e8 0x342b # Samsung SCX-4500W, network mode # tcp HOST_ADDR PORT # Uncomment and configure: #tcp scx4500 9400 #Samsung SCX-4x24 Series, Samsung SCX-4824 usb 0x04e8 0x342c #Samsung SCX-4x28 Series, Samsung SCX-4828FN usb 0x04e8 0x342d #Samsung SCX-4300 Series usb 0x04e8 0x342e #Samsung SCX-5835_5935 Series usb 0x04e8 0x342f #Samsung SCX-5635 Series usb 0x04e8 0x3430 #Samsung SCX-4x26 Series usb 0x04e8 0x3432 #Samsung SCX-4600 Series usb 0x04e8 0x3433 #Samsung SCX-4623 Series usb 0x04e8 0x3434 #Samsung MFP-65x Series usb 0x04e8 0x3435 #Samsung SCX-6545 Series usb 0x04e8 0x3437 #Samsung CLX-8385 Series usb 0x04e8 0x3439 #Samsung CLX-6220 Series usb 0x04e8 0x343a #Samsung CLX-6250 Series usb 0x04e8 0x343b #Samsung SCX-4x25 Series, Samsung SCX-4825FN usb 0x04e8 0x343c #Samsung CLX-3180 Series: Samsung CLX 3185 usb 0x04e8 0x343d #Samsung CLX-8540 Series usb 0x04e8 0x343f #Samsung SCX-4623FW Series usb 0x04e8 0x3440 #Samsung SCX-3200 Series, Samsung SCX-3205W usb 0x04e8 0x3441 #Samsung SCX-6545X Series usb 0x04e8 0x3442 #Samsung SCX-6x55X Series usb 0x04e8 0x3443 #Samsung CLX-8385X Series usb 0x04e8 0x3444 #Samsung SCX-5835_5935X Series usb 0x04e8 0x3446 #Samsung SCX-483x 5x3x Series, Samsung SCX-4833FD usb 0x04e8 0x344b #Samsung SCX-3400 Series usb 0x04e8 0x344f #Samsung SF-760 Series usb 0x04e8 0x3450 #Samsung SCX-472x Series, Samsung SCX-4729FD usb 0x04e8 0x3453 #Samsung CLX-6260 Series usb 0x04e8 0x3455 # Samsung CLX-3300 Series usb 0x04e8 0x3456 #Samsung SCX-470x Series usb 0x04e8 0x3457 #Samsung CLX-4190 Series usb 0x04e8 0x345a #Samsung SCX-4650 4x21S Series usb 0x04e8 0x345b #Samsung M337x 387x 407x Series usb 0x04e8 0x3460 #Samsung M267x 287x Series usb 0x04e8 0x3461 #Samsung SCX-681x Series usb 0x04e8 0x3466 #Samsung C460 Series usb 0x04e8 0x3468 #Samsung M458x Series usb 0x04e8 0x346f #Samsung M4370 5370 Series usb 0x04e8 0x3471 #Samsung X401 Series usb 0x04e8 0x3477 #Samsung K401 Series usb 0x04e8 0x3478 #Samsung K3250 Series usb 0x04e8 0x3481 #Samsung X3220 Series usb 0x04e8 0x3482 #################### ### Xerox Models ### #################### #Xerox Phaser 6110MFP usb 0x0924 0x3d5d #Xerox Phaser 3200MFP usb 0x0924 0x3da4 #Xerox WorkCentre 4118 Series usb 0x0924 0x420c #Xerox WorkCentre 3119 Series usb 0x0924 0x4265 #Xerox WorkCentre 3210 usb 0x0924 0x4293 #Xerox WorkCentre 3220 usb 0x0924 0x4294 ################### ### Dell Models ### ################### #Dell MFP Laser Printer 1815dn usb 0x413c 0x5124 #Dell 1235cn (clone of Samsung CLX-3175) usb 0x413c 0x5310 sane-backends-1.0.27/backend/genesys_gl847.h0000664000175000017500000005757612775312261015416 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2010-2013 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "genesys.h" #ifdef UNIT_TESTING SANE_Status gl847_stop_action (Genesys_Device * dev); SANE_Status gl847_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home); #endif #define REG01 0x01 #define REG01_CISSET 0x80 #define REG01_DOGENB 0x40 #define REG01_DVDSET 0x20 #define REG01_STAGGER 0x10 #define REG01_COMPENB 0x08 #define REG01_TRUEGRAY 0x04 #define REG01_SHDAREA 0x02 #define REG01_SCAN 0x01 #define REG02 0x02 #define REG02_NOTHOME 0x80 #define REG02_ACDCDIS 0x40 #define REG02_AGOHOME 0x20 #define REG02_MTRPWR 0x10 #define REG02_FASTFED 0x08 #define REG02_MTRREV 0x04 #define REG02_HOMENEG 0x02 #define REG02_LONGCURV 0x01 #define REG03 0x03 #define REG03_LAMPDOG 0x80 #define REG03_AVEENB 0x40 #define REG03_XPASEL 0x20 #define REG03_LAMPPWR 0x10 #define REG03_LAMPTIM 0x0f #define REG04 0x04 #define REG04_LINEART 0x80 #define REG04_BITSET 0x40 #define REG04_AFEMOD 0x30 #define REG04_FILTER 0x0c #define REG04_FESET 0x03 #define REG04S_AFEMOD 4 #define REG05 0x05 #define REG05_DPIHW 0xc0 #define REG05_DPIHW_600 0x00 #define REG05_DPIHW_1200 0x40 #define REG05_DPIHW_2400 0x80 #define REG05_DPIHW_4800 0xc0 #define REG05_MTLLAMP 0x30 #define REG05_GMMENB 0x08 #define REG05_MTLBASE 0x03 #define REG06_SCANMOD 0xe0 #define REG06S_SCANMOD 5 #define REG06_PWRBIT 0x10 #define REG06_GAIN4 0x08 #define REG06_OPTEST 0x07 #define REG07_LAMPSIM 0x80 #define REG08_DRAM2X 0x80 #define REG08_MPENB 0x20 #define REG08_CIS_LINE 0x10 #define REG08_IR1ENB 0x08 #define REG08_IR2ENB 0x04 #define REG08_ENB24M 0x01 #define REG09_MCNTSET 0xc0 #define REG09_EVEN1ST 0x20 #define REG09_BLINE1ST 0x10 #define REG09_BACKSCAN 0x08 #define REG09_ENHANCE 0x04 #define REG09_SHORTTG 0x02 #define REG09_NWAIT 0x01 #define REG09S_MCNTSET 6 #define REG09S_CLKSET 4 #define REG0A_LPWMEN 0x10 #define REG0B 0x0b #define REG0B_DRAMSEL 0x07 #define REG0B_ENBDRAM 0x08 #define REG0B_ENBDRAM 0x08 #define REG0B_RFHDIS 0x10 #define REG0B_CLKSET 0xe0 #define REG0B_24MHZ 0x00 #define REG0B_30MHZ 0x20 #define REG0B_40MHZ 0x40 #define REG0B_48MHZ 0x60 #define REG0B_60MHZ 0x80 #define REG0C 0x0c #define REG0C_CCDLMT 0x0f #define REG0D 0x0d #define REG0D_FULLSTP 0x10 #define REG0D_SEND 0x80 #define REG0D_CLRMCNT 0x04 #define REG0D_CLRDOCJM 0x02 #define REG0D_CLRLNCNT 0x01 #define REG0F 0x0f #define REG16_CTRLHI 0x80 #define REG16_TOSHIBA 0x40 #define REG16_TGINV 0x20 #define REG16_CK1INV 0x10 #define REG16_CK2INV 0x08 #define REG16_CTRLINV 0x04 #define REG16_CKDIS 0x02 #define REG16_CTRLDIS 0x01 #define REG17_TGMODE 0xc0 #define REG17_TGMODE_NO_DUMMY 0x00 #define REG17_TGMODE_REF 0x40 #define REG17_TGMODE_XPA 0x80 #define REG17_TGW 0x3f #define REG17S_TGW 0 #define REG18 0x18 #define REG18_CNSET 0x80 #define REG18_DCKSEL 0x60 #define REG18_CKTOGGLE 0x10 #define REG18_CKDELAY 0x0c #define REG18_CKSEL 0x03 #define REG1A_SW2SET 0x80 #define REG1A_SW1SET 0x40 #define REG1A_MANUAL3 0x02 #define REG1A_MANUAL1 0x01 #define REG1A_CK4INV 0x08 #define REG1A_CK3INV 0x04 #define REG1A_LINECLP 0x02 #define REG1C 0x1c #define REG1C_TGTIME 0x07 #define REG1D_CK4LOW 0x80 #define REG1D_CK3LOW 0x40 #define REG1D_CK1LOW 0x20 #define REG1D_TGSHLD 0x1f #define REG1DS_TGSHLD 0 #define REG1E_WDTIME 0xf0 #define REG1ES_WDTIME 4 #define REG1E_LINESEL 0x0f #define REG1ES_LINESEL 0 #define REG_FEDCNT 0x1f #define REG24 0x1c #define REG40 0x40 #define REG40_CHKVER 0x10 #define REG40_HISPDFLG 0x04 #define REG40_MOTMFLG 0x02 #define REG40_DATAENB 0x01 #define REG41_PWRBIT 0x80 #define REG41_BUFEMPTY 0x40 #define REG41_FEEDFSH 0x20 #define REG41_SCANFSH 0x10 #define REG41_HOMESNR 0x08 #define REG41_LAMPSTS 0x04 #define REG41_FEBUSY 0x02 #define REG41_MOTORENB 0x01 #define REG58_VSMP 0xf8 #define REG58S_VSMP 3 #define REG58_VSMPW 0x07 #define REG58S_VSMPW 0 #define REG59_BSMP 0xf8 #define REG59S_BSMP 3 #define REG59_BSMPW 0x07 #define REG59S_BSMPW 0 #define REG5A_ADCLKINV 0x80 #define REG5A_RLCSEL 0x40 #define REG5A_CDSREF 0x30 #define REG5AS_CDSREF 4 #define REG5A_RLC 0x0f #define REG5AS_RLC 0 #define REG5E_DECSEL 0xe0 #define REG5ES_DECSEL 5 #define REG5E_STOPTIM 0x1f #define REG5ES_STOPTIM 0 #define REG60 0x60 #define REG60_Z1MOD 0x1f #define REG61 0x61 #define REG61_Z1MOD 0xff #define REG62 0x62 #define REG62_Z1MOD 0xff #define REG63 0x63 #define REG63_Z2MOD 0x1f #define REG64 0x64 #define REG64_Z2MOD 0xff #define REG65 0x65 #define REG65_Z2MOD 0xff #define REG60S_STEPSEL 5 #define REG60_STEPSEL 0xe0 #define REG60_FULLSTEP 0x00 #define REG60_HALFSTEP 0x20 #define REG60_EIGHTHSTEP 0x60 #define REG60_16THSTEP 0x80 #define REG63S_FSTPSEL 5 #define REG63_FSTPSEL 0xe0 #define REG63_FULLSTEP 0x00 #define REG63_HALFSTEP 0x20 #define REG63_EIGHTHSTEP 0x60 #define REG63_16THSTEP 0x80 #define REG67 0x67 #define REG67_MTRPWM 0x80 #define REG68 0x68 #define REG68_FASTPWM 0x80 #define REG6B 0x6b #define REG6B_MULTFILM 0x80 #define REG6B_GPOM13 0x40 #define REG6B_GPOM12 0x20 #define REG6B_GPOM11 0x10 #define REG6B_GPO18 0x02 #define REG6B_GPO17 0x01 #define REG6C 0x6c #define REG6C_GPIO16 0x80 #define REG6C_GPIO15 0x40 #define REG6C_GPIO14 0x20 #define REG6C_GPIO13 0x10 #define REG6C_GPIO12 0x08 #define REG6C_GPIO11 0x04 #define REG6C_GPIO10 0x02 #define REG6C_GPIO9 0x01 #define REG6C_GPIOH 0xff #define REG6C_GPIOL 0xff #define REG6D 0x6d #define REG6E 0x6e #define REG6F 0x6f #define REG7E 0x7e #define REG87_LEDADD 0x04 #define REG9E 0x9e #define REG9F 0x9f #define REGA6 0xa6 #define REGA7 0xa7 #define REGA8 0xa8 #define REGA9 0xa9 #define REGAB 0xab #define REG_EXPR 0x10 #define REG_EXPG 0x12 #define REG_EXPB 0x14 #define REG_EXPDMY 0x19 #define REG_STEPNO 0x21 #define REG_FWDSTEP 0x22 #define REG_BWDSTEP 0x23 #define REG_FASTNO 0x24 #define REG_DPISET 0x2c #define REG_STRPIXEL 0x30 #define REG_ENDPIXEL 0x32 #define REG_LINCNT 0x25 #define REG_MAXWD 0x35 #define REG_LPERIOD 0x38 #define REG_FEEDL 0x3d #define REG_FMOVDEC 0x5f #define REG_FSHDEC 0x69 #define REG_FMOVNO 0x6a #define REG_CK1MAP 0x74 #define REG_CK3MAP 0x77 #define REG_CK4MAP 0x7a /** * writable scanner registers */ enum { reg_0x01 = 0, reg_0x02, reg_0x03, reg_0x04, reg_0x05, reg_0x06, reg_0x08, reg_0x09, reg_0x0a, reg_0x0b, reg_0x0c, reg_0x0d, reg_0x0e, reg_0x0f, reg_0x10, reg_0x11, reg_0x12, reg_0x13, reg_0x14, reg_0x15, reg_0x16, reg_0x17, reg_0x18, reg_0x19, reg_0x1a, reg_0x1b, reg_0x1c, reg_0x1d, reg_0x1e, reg_0x1f, reg_0x20, reg_0x21, reg_0x22, reg_0x23, reg_0x24, reg_0x25, reg_0x26, reg_0x27, reg_0x2c, reg_0x2d, reg_0x2e, reg_0x2f, reg_0x30, reg_0x31, reg_0x32, reg_0x33, reg_0x34, reg_0x35, reg_0x36, reg_0x37, reg_0x38, reg_0x39, reg_0x3a, reg_0x3b, reg_0x3d, reg_0x3e, reg_0x3f, reg_0x51, reg_0x52, reg_0x53, reg_0x54, reg_0x55, reg_0x56, reg_0x57, reg_0x58, reg_0x59, reg_0x5a, reg_0x5e, reg_0x5f, reg_0x60, reg_0x61, reg_0x62, reg_0x63, reg_0x64, reg_0x65, reg_0x67, reg_0x68, reg_0x69, reg_0x6a, reg_0x6b, reg_0x6c, reg_0x6d, reg_0x6e, reg_0x6f, reg_0x74, reg_0x75, reg_0x76, reg_0x77, reg_0x78, reg_0x79, reg_0x7a, reg_0x7b, reg_0x7c, reg_0x7d, reg_0x87, reg_0x9d, reg_0xa2, reg_0xa3, reg_0xa4, reg_0xa5, reg_0xa6, reg_0xa7, reg_0xa8, reg_0xa9, reg_0xbd, reg_0xbe, reg_0xc5, reg_0xc6, reg_0xc7, reg_0xc8, reg_0xc9, reg_0xca, reg_0xd0, reg_0xd1, reg_0xd2, reg_0xe0, reg_0xe1, reg_0xe2, reg_0xe3, reg_0xe4, reg_0xe5, reg_0xe6, reg_0xe7, reg_0xe8, reg_0xe9, reg_0xea, reg_0xeb, reg_0xec, reg_0xed, reg_0xee, reg_0xef, reg_0xf0, reg_0xf1, reg_0xf2, reg_0xf3, reg_0xf4, reg_0xf5, reg_0xf6, reg_0xf7, reg_0xf8, reg_0xfe, GENESYS_GL847_MAX_REGS }; #define SETREG(adr,val) {dev->reg[reg_##adr].address=adr;dev->reg[reg_##adr].value=val;} /** set up registers for an actual scan * * this function sets up the scanner to scan in normal or single line mode */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ float yres, /*dpi */ float startx, /*optical_res, from dummy_pixel+1 */ float starty, /*base_ydpi, from home! */ float pixels, float lines, unsigned int depth, unsigned int channels, int color_filter, unsigned int flags); /* Send the low-level scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor); /* Send the stop scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop); #ifndef UNIT_TESTING static #endif SANE_Status gl847_init (Genesys_Device * dev); /** @brief moves the slider to steps at motor base dpi * @param dev device to work on * @param steps number of steps to move * */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_feed (Genesys_Device * dev, unsigned int steps); typedef struct { uint8_t sensor_id; uint8_t r6b; uint8_t r6c; uint8_t r6d; uint8_t r6e; uint8_t r6f; uint8_t ra6; uint8_t ra7; uint8_t ra8; uint8_t ra9; } Gpio_Profile; static Gpio_Profile gpios[]={ { GPO_CANONLIDE200, 0x02, 0xf9, 0x20, 0xff, 0x00, 0x04, 0x04, 0x00, 0x00}, { GPO_CANONLIDE700, 0x06, 0xdb, 0xff, 0xff, 0x80, 0x15, 0x07, 0x20, 0x10}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }; typedef struct { uint8_t dramsel; uint8_t rd0; uint8_t rd1; uint8_t rd2; uint8_t re0; uint8_t re1; uint8_t re2; uint8_t re3; uint8_t re4; uint8_t re5; uint8_t re6; uint8_t re7; } Memory_layout; static Memory_layout layouts[]={ /* LIDE 100 */ { 0x29, 0x0a, 0x15, 0x20, 0x00, 0xac, 0x02, 0x55, 0x02, 0x56, 0x03, 0xff }, /* LIDE 200 */ { 0x29, 0x0a, 0x1f, 0x34, 0x01, 0x24, 0x02, 0x91, 0x02, 0x92, 0x03, 0xff }, /* 5600F */ { 0x29, 0x0a, 0x1f, 0x34, 0x01, 0x24, 0x02, 0x91, 0x02, 0x92, 0x03, 0xff }, /* LIDE 700F */ { 0x2a, 0x0a, 0x33, 0x5c, 0x02, 0x14, 0x09, 0x09, 0x09, 0x0a, 0x0f, 0xff } }; /** @brief structure for sensor settings * this structure describes the sensor settings to use for a given * exposure. */ typedef struct { int sensor_type; /**> sensor id */ int dpi; /**> maximum dpi for which data are valid */ int exposure; /**> exposure */ int ck1map; /**> CK1MAP */ int ck3map; /**> CK3MAP */ int ck4map; /**> CK4MAP */ int segcnt; /**> SEGCNT */ int expdummy; /**> exposure dummy */ int expr; /**> initial red exposure */ int expg; /**> initial green exposure */ int expb; /**> initial blue exposure */ size_t *order; /**> order of sub-segments */ uint8_t r17; /**> TG width */ } Sensor_Profile; /* *INDENT-OFF* */ static size_t order_01[]={0,1}; static size_t order_0213[]={0,2,1,3}; static size_t order_0246[]={0,2,4,6,1,3,5,7}; static size_t new_order[]={0,1,2,3}; static size_t order_0145[]={0,1,4,5,2,3,6,7}; /** * database of sensor profiles */ static Sensor_Profile sensors[]={ {CIS_CANONLIDE100, 200, 2848, 60, 159, 85, 5136, 255, 410, 275, 203, NULL , 0x0a}, {CIS_CANONLIDE100, 300, 1424, 60, 159, 85, 5136, 255, 410, 275, 203, NULL , 0x0a}, {CIS_CANONLIDE100, 600, 1432, 60, 159, 85, 5136, 255, 410, 275, 203, NULL , 0x0a}, {CIS_CANONLIDE100, 1200, 2712, 60, 159, 85, 5136, 255, 746, 478, 353, order_01 , 0x08}, {CIS_CANONLIDE100, 2400, 5280, 60, 159, 85, 5136, 255, 1417, 909, 643, order_0213, 0x06}, /* {CIS_CANONLIDE200, 150, 2848, 240, 636, 340, 5144, 0, 255, 637, 637, 637}, {CIS_CANONLIDE200, 300, 1424, 240, 636, 340, 5144, 0, 255, 637, 637, 637}, */ {CIS_CANONLIDE200, 200, 2848, 60, 159, 85, 5136, 255, 410, 275, 203, NULL , 0x0a}, {CIS_CANONLIDE200, 300, 1424, 60, 159, 85, 5136, 255, 410, 275, 203, NULL , 0x0a}, {CIS_CANONLIDE200, 600, 1432, 60, 159, 85, 5136, 255, 410, 275, 203, NULL , 0x0a}, {CIS_CANONLIDE200, 1200, 2712, 60, 159, 85, 5136, 255, 746, 478, 353, order_01 , 0x08}, {CIS_CANONLIDE200, 2400, 5280, 60, 159, 85, 5136, 255, 1417, 909, 643, order_0213, 0x06}, {CIS_CANONLIDE200, 4800, 10416, 60, 159, 85, 5136, 255, 2692, 1728, 1221, order_0246, 0x04}, /* LiDE 700F */ {CIS_CANONLIDE700, 150, 2848, 135, 249, 85, 5187, 255, 465, 310, 239, NULL , 0x0c}, {CIS_CANONLIDE700, 300, 1424, 135, 249, 85, 5187, 255, 465, 310, 239, NULL , 0x0c}, {CIS_CANONLIDE700, 600, 1504, 135, 249, 85, 5187, 255, 465, 310, 239, NULL , 0x0c}, {CIS_CANONLIDE700, 1200, 2696, 135, 249, 85, 5187, 255, 1464, 844, 555, order_01 , 0x0a}, {CIS_CANONLIDE700, 2400, 10576, 135, 249, 85, 5187, 255, 2798, 1558, 972, new_order , 0x08}, {CIS_CANONLIDE700, 4800, 10576, 135, 249, 85, 5187, 255, 2798, 1558, 972, order_0145, 0x06}, }; /* *INDENT-ON* */ /* base motor sopes in full step unit */ /* target=((exposure * dpi) / base_dpi)>>step_type; */ static uint32_t lide200_base[] = { 46876, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2336, 2329, 2322, 2314, 2307, 2300,2292,2285,2278,2271,2263,2256,2249,2241,2234,2227,2219,2212,2205,2198,2190,2183,2176,2168,2161,2154,2146,2139,2132,2125,2117,2110,2103,2095,2088,2081,2073,2066,2059,2052,2044,2037,2030,2022,2015,2008,2001,1993,1986,1979,1971,1964,1957,1949,1942,1935,1928,1920,1913,1906,1898,1891,1884,1876,1869,1862,1855,1847,1840,1833,1825,1818,1811,1803,1796,1789,1782,1774,1767,1760,1752,1745,1738,1731,1723,1716,1709,1701,1694,1687,1679,1672,1665,1658,1650,1643,1636,1628,1621,1614,1606,1599,1592,1585,1577,1570,1563,1555,1548,1541,1533,1526,1519,1512,1504,1497,1490,1482,1475,1468,1461,1453,1446,1439,1431,1424,1417,1409,1402,1395,1388,1380,1373,1366,1358,1351,1344,1336,1329,1322,1315,1307,1300,1293,1285,1278,1271,1263,1256,1249,1242,1234,1227,1220,1212,1205,1198,1191,1183,1176,1169,1161,1154,1147,1139,1132,1125,1118,1110,1103,1096,1088,1081,1074,1066,1059,1052,1045,1037,1030,1023,1015,1008,1001,993,986,979,972,964,957,950,942,935,928,921,913,906,899,891,884,877,869,862,855,848,840,833,826,818,811,804,796,789,782,775,767,760,753,745,738,731,723,716,709,702,694,687,680,672,665,658,651,643,636,629,621,614,607,599,592,585,578,570,563,556,534,534, 0}; static uint32_t lide200_medium[] = { 46876, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136, 8136,2343, 2336, 2329, 2322, 2314, 2307, 2300,2292,2285,2278,2271,2263,2256,2249,2241,2234,2227,2219,2212,2205,2198,2190,2183,2176,2168,2161,2154,2146,2139,2132,2125,2117,2110,2103,2095,2088,2081,2073,2066,2059,2052,2044,2037,2030,2022,2015,2008,2001,1993,1986,1979,1971,1964,1957,1949,1942,1935,1928,1920,1913,1906,1898,1891,1884,1876,1869,1862,1855,1847,1840,1833,1825,1818,1811,1803,1796,1789,1782,1774,1767,1760,1752,1745,1738,1731,1723,1716,1709,1701,1694,1687,1679,1672,1665,1658,1650,1643,1636,1628,1621,1614,1606,1599,1592,1585,1577,1570,1563,1555,1548,1541,1533,1526,1519,1512,1504,1497,1490,1482,1475,1468,1461,1453,1446,1439,1431,1424,1417,1409,1402,1395,1388,1380,1373,1366,1358,1351,1344,1336,1329,1322,1315,1307,1300,1293,1285,1278,1271,1263,1256,1249,1242,1234,1227,1220,1212,1205,1198,1191,1183,1176,1169,1161,1154,1147,1139,1132,1125,1118,1110,1103,1096,1088,1081,1074,1066,1059,1052,1045,1037,1030,1023,1015,1008,1001,993,986,979,972,964,957,950,942,935,928,921,913,906,899,891,884,877,869,862,855,848,840,833,826,818,811,804,796,789,782,775,767,760,753,745,738,731,723,716,709,702,694,687,680,672,665,658,651,643,636,629,621,614,607,599,592,585,578,570,563,556,534,534, 0}; static uint32_t lide200_high[] = { 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 31680, 2219,2212,2205,2198,2190,2183,2176,2168,2161,2154,2146,2139,2132,2125,2117,2110,2103,2095,2088,2081,2073,2066,2059,2052,2044,2037,2030,2022,2015,2008,2001,1993,1986,1979,1971,1964,1957,1949,1942,1935,1928,1920,1913,1906,1898,1891,1884,1876,1869,1862,1855,1847,1840,1833,1825,1818,1811,1803,1796,1789,1782,1774,1767,1760,1752,1745,1738,1731,1723,1716,1709,1701,1694,1687,1679,1672,1665,1658,1650,1643,1636,1628,1621,1614,1606,1599,1592,1585,1577,1570,1563,1555,1548,1541,1533,1526,1519,1512,1504,1497,1490,1482,1475,1468,1461,1453,1446,1439,1431,1424,1417,1409,1402,1395,1388,1380,1373,1366,1358,1351,1344,1336,1329,1322,1315,1307,1300,1293,1285,1278,1271,1263,1256,1249,1242,1234,1227,1220,1212,1205,1198,1191,1183,1176,1169,1161,1154,1147,1139,1132,1125,1118,1110,1103,1096,1088,1081,1074,1066,1059,1052,1045,1037,1030,1023,1015,1008,1001,993,986,979,972,964,957,950,942,935,928,921,913,906,899,891,884,877,869,862,855,848,840,833,826,818,811,804,796,789,782,775,767,760,753,745,738,731,723,716,709,702,694,687,680,672,665,658,651,643,636,629,621,614,607,599,592,585,578,570,563,556,534,534, 0}; static uint32_t lide700_medium[] = { 46876,2342,2342,2342,2342,2342,2342,2342,2342,2302,2286,2274,2266,2258,2252,2244,2240,2234,2228,2224,2218,2216,2210,2208,2202,2200,2194,2192,2190,2186,2182,2180,2176,2174,2172,2170,2166,2162,2160,2156,2154,2152,2150,2150,2146,2144,2142,2140,2136,2134,2132,2130,2130,2128,2124,2122,2120,2120,2118,2116,2112,2112,2110,2108,2106,2106,2104,2102,2102,2098,2096,2094,2094,2092,2090,2090,2086,2084,2084,2082,2082,2080,2078,2078,2076,2074,2074,2070,2070,2068,2066,2066,2064,2064,2062,2062,2060,2058,2058,2054,2054,2052,2052,2050,2050,2048,2048,2046,2046,2044,2042,2042,2040,2040,2038,2038,2034,2034,2032,2032,2030,2030,2028,2028,2026,2026,2022,2022}; static uint32_t lide700_high[] = { 46876,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864,15864}; /* 5190 trop * 5186 pas assez */ /* static uint32_t lide200_max[] = { 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 124992, 2219,2212,2205,2198,2190,2183,2176,2168,2161,2154,2146,2139,2132,2125,2117,2110,2103,2095,2088,2081,2073,2066,2059,2052,2044,2037,2030,2022,2015,2008,2001,1993,1986,1979,1971,1964,1957,1949,1942,1935,1928,1920,1913,1906,1898,1891,1884,1876,1869,1862,1855,1847,1840,1833,1825,1818,1811,1803,1796,1789,1782,1774,1767,1760,1752,1745,1738,1731,1723,1716,1709,1701,1694,1687,1679,1672,1665,1658,1650,1643,1636,1628,1621,1614,1606,1599,1592,1585,1577,1570,1563,1555,1548,1541,1533,1526,1519,1512,1504,1497,1490,1482,1475,1468,1461,1453,1446,1439,1431,1424,1417,1409,1402,1395,1388,1380,1373,1366,1358,1351,1344,1336,1329,1322,1315,1307,1300,1293,1285,1278,1271,1263,1256,1249,1242,1234,1227,1220,1212,1205,1198,1191,1183,1176,1169,1161,1154,1147,1139,1132,1125,1118,1110,1103,1096,1088,1081,1074,1066,1059,1052,1045,1037,1030,1023,1015,1008,1001,993,986,979,972,964,957,950,942,935,928,921,913,906,899,891,884,877,869,862,855,848,840,833,826,818,811,804,796,789,782,775,767,760,753,745,738,731,723,716,709,702,694,687,680,672,665,658,651,643,636,629,621,614,607,599,592,585,578,570,563,556,534,534, 0}; */ /** * database of motor profiles */ /* *INDENT-OFF* */ static Motor_Profile gl847_motors[]={ /* LiDE 100 */ {MOTOR_CANONLIDE100, 2848, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE100, 1424, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE100, 1432, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE100, 2712, QUARTER_STEP, lide200_medium}, {MOTOR_CANONLIDE100, 5280, EIGHTH_STEP , lide200_high}, /* LiDE 200 */ {MOTOR_CANONLIDE200, 2848, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE200, 1424, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE200, 1432, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE200, 2712, QUARTER_STEP, lide200_medium}, {MOTOR_CANONLIDE200, 5280, EIGHTH_STEP , lide200_high}, {MOTOR_CANONLIDE200, 10416, EIGHTH_STEP , lide200_high}, /* LiDE 700F */ {MOTOR_CANONLIDE700, 2848, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE700, 1424, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE700, 1504, HALF_STEP , lide200_base}, {MOTOR_CANONLIDE700, 2696, HALF_STEP , lide700_medium}, /* 2696 , 2838 */ {MOTOR_CANONLIDE700, 10576, EIGHTH_STEP, lide700_high}, /* end of database entry */ {0, 0, 0, NULL}, }; /* *INDENT-ON* */ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/coolscan.c0000664000175000017500000035012113106201017014547 00000000000000/* ------------------------------------------------------------------------- */ /* sane - Scanner Access Now Easy. coolscan.c , version 0.4.4 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for COOLSCAN flatbed scanners. */ /* ------------------------------------------------------------------------- */ /* SANE-FLOW-DIAGRAMM - sane_init() : initialize backend, attach scanners . - sane_get_devices() : query list of scanner-devices . - sane_open() : open a particular scanner-device . . - sane_set_io_mode : set blocking-mode . . - sane_get_select_fd : get scanner-fd . . - sane_get_option_descriptor() : get option informations . . - sane_control_option() : change option values . . . . - sane_start() : start image aquisition . . - sane_get_parameters() : returns actual scan-parameters . . - sane_read() : read image-data (from pipe) . . . . - sane_cancel() : cancel operation . - sane_close() : close opened scanner-device - sane_exit() : terminate use of backend */ #ifdef _AIX # include "lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "lalloca.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_thread.h" #include "../include/sane/sanei_config.h" #define COOLSCAN_CONFIG_FILE "coolscan.conf" #include "../include/sane/sanei_backend.h" #include "coolscan.h" #include "coolscan-scsidef.h" #ifndef PATH_MAX #define PATH_MAX 1024 #endif /* ------------------------------------------------------------------------- */ static const SANE_Int resolution_list[] = { 25, 2700, 1350, 900, 675, 540, 450, 385, 337, 300, 270, 245, 225, 207, 192, 180, 168, 158, 150, 142, 135, 128, 122, 117, 112, 108 }; #define coolscan_do_scsi_open(dev, fd, handler) sanei_scsi_open(dev, fd, handler) #define coolscan_do_scsi_close(fd) sanei_scsi_close(fd) #define COOLSCAN_MAX_RETRY 25 static SANE_Status sense_handler (int scsi_fd, unsigned char * result, void *arg); static int coolscan_check_values (Coolscan_t * s); static int get_internal_info (Coolscan_t *); static void coolscan_get_inquiry_values (Coolscan_t *); static void hexdump (int level, char *comment, unsigned char *p, int l); static int swap_res (Coolscan_t * s); /* --------------------------- COOLSCAN_DO_SCSI_CMD ----------------------- */ static int do_scsi_cmd (int fd, unsigned char *cmd, int cmd_len, unsigned char *out, size_t out_len) { int ret; size_t ol = out_len; hexdump (20, "", cmd, cmd_len); ret = sanei_scsi_cmd (fd, cmd, cmd_len, out, &ol); if ((out_len != 0) && (out_len != ol)) { DBG (1, "sanei_scsi_cmd: asked %lu bytes, got %lu\n", (u_long) out_len, (u_long) ol); } if (ret) { DBG (1, "sanei_scsi_cmd: returning 0x%08x\n", ret); } DBG (10, "sanei_scsi_cmd: returning %lu bytes:\n", (u_long) ol); if (out != NULL && out_len != 0) hexdump (15, "", out, (out_len > 0x60) ? 0x60 : out_len); return ret; } static int request_sense_parse (unsigned char *sensed_data) { int ret, sense, asc, ascq; sense = get_RS_sense_key (sensed_data); asc = get_RS_ASC (sensed_data); ascq = get_RS_ASCQ (sensed_data); ret = SANE_STATUS_IO_ERROR; switch (sense) { case 0x0: DBG (5, "\t%d/%d/%d: Scanner ready\n", sense, asc, ascq); return SANE_STATUS_GOOD; case 0x1: if ((0x37 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: Rounded Parameter\n", sense, asc, ascq); ret = SANE_STATUS_GOOD; } else if ((0x61 == asc) && (0x02 == ascq)) DBG (1, "\t%d/%d/%d: Out Of Focus\n", sense, asc, ascq); else DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); break; case 0x2: if ((0x4 == asc) && (0x1 == ascq)) { DBG (10, "\t%d/%d/%d: Logical unit is in process of becoming ready\n", sense, asc, ascq); ret = SANE_STATUS_DEVICE_BUSY; } else if ((0x3A == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: No Diapo inserted\n", sense, asc, ascq); ret = SANE_STATUS_GOOD; } else if ((0x60 == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Lamp Failure\n", sense, asc, ascq); else { DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); ret = SANE_STATUS_GOOD; } break; case 0x3: if ((0x3b == asc) && (0xe == ascq)) DBG (1, "\t%d/%d/%d: Medium source element empty\n", sense, asc, ascq); else if ((0x53 == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Media Load of Eject Failed\n", sense, asc, ascq); else DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); break; case 0x4: if ((0x15 == asc) && (0x1 == ascq)) DBG (1, "\t%d/%d/%d: Mechanical Positioning Error\n", sense, asc, ascq); else DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); break; case 0x5: if ((0x00 == asc) && (0x5 == ascq)) DBG (1, "\t%d/%d/%d: End-Of-Data Detected\n", sense, asc, ascq); else if ((0x1a == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Parameter List Length Error\n", sense, asc, ascq); else if ((0x20 == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Invalid Command Operation Code\n", sense, asc, ascq); else if ((0x24 == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Invalid Field In CDB\n", sense, asc, ascq); else if ((0x25 == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Logical Unit Not Supported\n", sense, asc, ascq); else if ((0x26 == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Invalid Field in Parameter List\n", sense, asc, ascq); else if ((0x2c == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Command Sequence Error\n", sense, asc, ascq); else if ((0x39 == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Saving Parameters Not Supported\n", sense, asc, ascq); else if ((0x3d == asc) && (0x00 == ascq)) DBG (1, "\t%d/%d/%d: Invalid Bits In Identify Message\n", sense, asc, ascq); else DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); break; case 0x6: if ((0x29 == asc) && (0x0 == ascq)) DBG (1, "\t%d/%d/%d: Power On, Reset, or Bus Device Reset Occurred\n", sense, asc, ascq); else if ((0x2a == asc) && (0x1 == ascq)) DBG (1, "\t%d/%d/%d: Mode Parameters Changed\n", sense, asc, ascq); else DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); break; case 0xb: if ((0x43 == asc) && (0x0 == ascq)) DBG (1, "\t%d/%d/%d: Message Error\n", sense, asc, ascq); else if ((0x47 == asc) && (0x0 == ascq)) DBG (1, "\t%d/%d/%d: SCSI Parity Error\n", sense, asc, ascq); else if ((0x48 == asc) && (0x0 == ascq)) DBG (1, "\t%d/%d/%d: Initiator Detected Error Message Received\n", sense, asc, ascq); else if ((0x49 == asc) && (0x0 == ascq)) DBG (1, "\t%d/%d/%d: Invalid Message Error\n", sense, asc, ascq); else if ((0x4e == asc) && (0x0 == ascq)) DBG (1, "\t%d/%d/%d: Overlapped Commands Attempted\n", sense, asc, ascq); else DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); break; default: DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); break; } /* switch */ return ret; } /* * wait_scanner should spin until TEST_UNIT_READY returns 0 (GOOD) * returns 0 on success, * returns -1 on error. */ static int wait_scanner (Coolscan_t * s) { int ret = -1; int cnt = 0; DBG (10, "wait_scanner: Testing if scanner is ready\n"); while (ret != 0) { ret = do_scsi_cmd (s->sfd, test_unit_ready.cmd, test_unit_ready.size, 0, 0); if (ret == SANE_STATUS_DEVICE_BUSY) { usleep (500000); /* wait 0.5 seconds */ if (cnt++ > 40) { /* 20 sec. max (prescan takes up to 15 sec. */ DBG (1, "wait_scanner: scanner does NOT get ready\n"); return -1; } } else if (ret == SANE_STATUS_GOOD) { DBG (10, "wait_scanner: scanner is ready\n"); return ret; } else { DBG (1, "wait_scanner: test unit ready failed (%s)\n", sane_strstatus (ret)); } } return 0; } /* ------------------------- COOLSCAN GRAB SCANNER ----------------------------- */ /* coolscan_grab_scanner should go through the following command sequence: * TEST UNIT READY * CHECK CONDITION \ * REQUEST SENSE > These should be handled automagically by * UNIT ATTENTION / the kernel if they happen (powerup/reset) * TEST UNIT READY * GOOD * RESERVE UNIT * GOOD * * It is then responsible for installing appropriate signal handlers * to call emergency_give_scanner() if user aborts. */ static int coolscan_grab_scanner (Coolscan_t * s) { int ret; DBG (10, "grabbing scanner\n"); wait_scanner (s); /* wait for scanner ready, if not print sense and return 1 */ ret = do_scsi_cmd (s->sfd, reserve_unit.cmd, reserve_unit.size, NULL, 0); if (ret) return ret; DBG (10, "scanner reserved\n"); return 0; } /* * Convert a size in ilu to the units expected by the scanner */ static int resDivToVal (int res_div) { if (res_div < 1 || res_div > resolution_list[0]) { DBG (1, "Invalid resolution divisor %d \n", res_div); return 2700; } else { return resolution_list[res_div]; } } static int resValToDiv (int res_val) { int res_div; int max_res = resolution_list[0]; for (res_div = 1; res_div <= max_res; res_div++) { if (resolution_list[res_div] == res_val) break; } if (res_div > max_res) { DBG (1, "Invalid resolution value\n"); return 1; } else { return res_div; } } /* * use mode select to force a mesurement divisor of 2700 */ static unsigned char mode_select[] = { MODE_SELECT, 0x10, 0, 0, 20, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 3, 6, 0, 0, 0xA, 0x8C, 0, 0}; static int select_MUD (Coolscan_t * s) { return do_scsi_cmd (s->sfd, mode_select, 26, NULL, 0); } static int coolscan_autofocus_LS30 (Coolscan_t * s) { int x, y; wait_scanner(s); memcpy(s->buffer, autofocusLS30.cmd, autofocusLS30.size); memcpy(s->buffer+ autofocusLS30.size, autofocuspos, 9); x = s->xmaxpix - (s->brx + s->tlx) / 2; y = (s->bry + s->tly) / 2; DBG (10, "Attempting AutoFocus at x=%d, y=%d\n", x, y); do_scsi_cmd (s->sfd, s->buffer, autofocusLS30.size + 9, NULL, 0); /* Trashes when used in combination with scsi-driver AM53C974.o */ do_scsi_cmd (s->sfd, command_c1.cmd, command_c1.size, NULL, 0); DBG (10, "\tWaiting end of Autofocus\n"); wait_scanner (s); DBG (10, "AutoFocused.\n"); return 0; } static int coolscan_autofocus (Coolscan_t * s) { int x, y; if(s->LS>=2) { return coolscan_autofocus_LS30(s); } wait_scanner(s); memcpy(s->buffer, autofocus.cmd, autofocus.size); x = s->xmaxpix - (s->brx + s->tlx) / 2; y = (s->bry + s->tly) / 2; DBG (10, "Attempting AutoFocus at x=%d, y=%d\n", x, y); set_AF_XPoint (s->buffer, x); set_AF_YPoint (s->buffer, y); set_AF_transferlength (s->buffer, 0); /* should be 8 !*/ do_scsi_cmd (s->sfd, s->buffer, autofocus.size + AF_Point_length, NULL, 0); sleep(5); /* autofocus takes a minimum of 5 sec. */ DBG (10, "\tWaiting end of Autofocus\n"); wait_scanner (s); DBG (10, "AutoFocused.\n"); return 0; } /* static int coolscan_abort_scan (Coolscan_t * s) { int ret; DBG (5, "Aborting scan...\n"); ret = do_scsi_cmd (s->sfd, sabort.cmd, sabort.size, NULL, 0); if (ret) DBG (5, "Scan Aborted\n"); else DBG (5, "Not scanning\n"); return 0; } */ static int coolscan_mode_sense (Coolscan_t * s) { int ret, len; DBG (10, "Mode Sense...\n"); len = 12; set_MS_DBD (mode_sense.cmd, 1); set_MS_len (mode_sense.cmd, len); ret = do_scsi_cmd (s->sfd, mode_sense.cmd, mode_sense.size, s->buffer, len); if (ret == 0) { s->MUD = get_MS_MUD (s->buffer); DBG (10, "\tMode Sensed (MUD is %d)\n", s->MUD); } return ret; } static int coolscan_object_discharge (Coolscan_t * s) { int ret; DBG (10, "Trying to discharge object...\n"); memcpy (s->buffer, object_position.cmd, object_position.size); set_OP_autofeed (s->buffer, OP_Discharge); ret = do_scsi_cmd (s->sfd, s->buffer, object_position.size, NULL, 0); wait_scanner (s); DBG (10, "Object discharged.\n"); return ret; } static int coolscan_object_feed (Coolscan_t * s) { int ret; DBG (10, "Trying to feed object...\n"); if (!s->asf) { DBG (10, "\tAutofeeder not present.\n"); return 0; } memcpy (s->buffer, object_position.cmd, object_position.size); set_OP_autofeed (s->buffer, OP_Feed); ret = do_scsi_cmd (s->sfd, s->buffer, object_position.size, NULL, 0); wait_scanner (s); DBG (10, "Object fed.\n"); return ret; } /* coolscan_give_scanner should go through the following sequence: * OBJECT POSITION DISCHARGE * GOOD * RELEASE UNIT * GOOD */ static int coolscan_give_scanner (Coolscan_t * s) { DBG (10, "trying to release scanner ...\n"); coolscan_object_discharge (s); wait_scanner (s); do_scsi_cmd (s->sfd, release_unit.cmd, release_unit.size, NULL, 0); DBG (10, "scanner released\n"); return 0; } static int coolscan_set_window_param_LS20 (Coolscan_t * s, int prescan) { unsigned char buffer_r[max_WDB_size]; int ret; wait_scanner (s); memset (buffer_r, '\0', max_WDB_size); /* clear buffer */ memcpy (buffer_r, window_descriptor_block.cmd, window_descriptor_block.size); /* copy preset data */ set_WD_wid (buffer_r, WD_wid_all); /* window identifier */ set_WD_auto (buffer_r, s->set_auto); /* 0 or 1: don't know what it is */ set_WD_negative (buffer_r, s->negative); /* Negative/positive slide */ if (prescan) { set_WD_scanmode (buffer_r, WD_Prescan); } else { set_WD_scanmode (buffer_r, WD_Scan); /* geometry */ set_WD_Xres (buffer_r, resDivToVal (s->x_nres)); /* x resolution in dpi */ set_WD_Yres (buffer_r, resDivToVal (s->y_nres)); /* y resolution in dpi */ /* the coolscan uses the upper right corner as the origin of coordinates */ /* xmax and ymax are given in 1200 dpi */ set_WD_ULX (buffer_r, (s->xmaxpix - s->brx)); set_WD_ULY (buffer_r, s->tly); /* upper_edge y */ set_WD_width (buffer_r, (s->brx - s->tlx + 1)); set_WD_length (buffer_r, (s->bry - s->tly + 1)); /* BTC */ if (s->brightness == 128) { set_WD_brightness (buffer_r, 0); } else { set_WD_brightness (buffer_r, s->brightness); /* brightness */ } if (s->contrast == 128) { set_WD_contrast (buffer_r, 0); } else { set_WD_contrast (buffer_r, s->contrast); /* contrast */ } /* scanmode */ if (s->colormode == GREYSCALE) set_WD_composition (buffer_r, WD_comp_grey); /* GRAY composition */ else set_WD_composition (buffer_r, WD_comp_rgb_full); /* RGB composition */ set_WD_dropoutcolor (buffer_r, s->dropoutcolor); /* Which color to scan with when grayscale scan */ set_WD_transfermode (buffer_r, WD_LineSequence); set_WD_gammaselection (buffer_r, s->gammaselection); /* monitor/linear */ set_WD_shading (buffer_r, WD_Shading_ON); /* default for non-manufacturing */ if (1 == s->LS) { /* Analog gamma reserved on LS-1000 */ set_WD_analog_gamma_R (buffer_r, 0); set_WD_analog_gamma_G (buffer_r, 0); set_WD_analog_gamma_R (buffer_r, 0); } else { /* Quote spec: "It is recomended that analog gamma bits 5, 4 and 3 be * set to 1 (OFF) when the object type of byte 48 is positive and the * gamma specificateion of byte 51 is linear, and to 0 (ON) in all * other cases." */ /* int foo; if ((buffer_r[48] == WD_Positive) && (buffer_r[51] == WD_Linear)) foo = WD_Analog_Gamma_OFF; else foo = WD_Analog_Gamma_ON; set_WD_analog_gamma_R (buffer_r, foo); set_WD_analog_gamma_G (buffer_r, foo); set_WD_analog_gamma_B (buffer_r, foo); */ set_WD_analog_gamma_R (buffer_r, s->analog_gamma_r); set_WD_analog_gamma_G (buffer_r, s->analog_gamma_g); set_WD_analog_gamma_B (buffer_r, s->analog_gamma_b); if (s->gamma_bind) { set_WD_LUT_R (buffer_r, 1); set_WD_LUT_G (buffer_r, 1); set_WD_LUT_B (buffer_r, 1); } else { set_WD_LUT_R (buffer_r, 1); set_WD_LUT_G (buffer_r, 2); set_WD_LUT_B (buffer_r, 3); } } set_WD_averaging (buffer_r, s->averaging); set_WD_brightness_R (buffer_r, s->brightness_R); set_WD_brightness_G (buffer_r, s->brightness_G); set_WD_brightness_B (buffer_r, s->brightness_B); set_WD_contrast_R (buffer_r, s->contrast_R); set_WD_contrast_G (buffer_r, s->contrast_G); set_WD_contrast_B (buffer_r, s->contrast_B); set_WD_exposure_R (buffer_r, s->exposure_R); set_WD_exposure_G (buffer_r, s->exposure_G); set_WD_exposure_B (buffer_r, s->exposure_B); set_WD_shift_R (buffer_r, s->shift_R); set_WD_shift_G (buffer_r, s->shift_G); set_WD_shift_B (buffer_r, s->shift_B); /* FIXME: LUT-[RGB] */ /* FIXME: stop on/off */ } DBG (10, "\tx_nres=%d, y_nres=%d, upper left-x=%d, upper left-y=%d\n", s->x_nres, s->y_nres, s->tlx, s->tly); DBG (10, "\twindow width=%d, MUD=%d, brx=%d\n", s->brx - s->tlx, s->MUD, s->brx); DBG (10, "\tcolormode=%d, bits per pixel=%d\n", s->colormode, s->bits_per_color); DBG (10, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n", s->negative, s->dropoutcolor, s->preview, s->transfermode, s->gammaselection); /* prepare SCSI-BUFFER */ memcpy (s->buffer, set_window.cmd, set_window.size); /* SET-WINDOW cmd */ memcpy ((s->buffer + set_window.size), /* add WPDB */ window_parameter_data_block.cmd, window_parameter_data_block.size); set_WPDB_wdblen ((s->buffer + set_window.size), used_WDB_size); /* set WD_len */ memcpy (s->buffer + set_window.size + window_parameter_data_block.size, buffer_r, window_descriptor_block.size); hexdump (15, "Window set", buffer_r, s->wdb_len); set_SW_xferlen (s->buffer, (window_parameter_data_block.size + window_descriptor_block.size)); ret = do_scsi_cmd (s->sfd, s->buffer, set_window.size + window_parameter_data_block.size + window_descriptor_block.size, NULL, 0); DBG (10, "window set.\n"); return ret; } static int coolscan_set_window_param_LS30 (Coolscan_t * s, int wid, int prescan) { unsigned char buffer_r[max_WDB_size]; int ret; wait_scanner (s); memset (buffer_r, '\0', max_WDB_size); /* clear buffer */ memcpy (buffer_r, window_descriptor_block_LS30.cmd, window_descriptor_block_LS30.size); /* copy preset data */ set_WD_wid (buffer_r, wid); /* window identifier */ set_WD_auto (buffer_r, s->set_auto); /* 0 or 1: don't know what it is */ /* geometry */ set_WD_Xres (buffer_r, resDivToVal (s->x_nres)); /* x resolution in dpi */ set_WD_Yres (buffer_r, resDivToVal (s->y_nres)); /* y resolution in dpi */ if (prescan) { set_WD_scanmode_LS30 (buffer_r, WD_Prescan); set_WD_Xres (buffer_r, resDivToVal (1)); /* x res. in dpi */ set_WD_Yres (buffer_r, resDivToVal (1)); /* y res. in dpi */ buffer_r[0x29]=0x81; buffer_r[0x2a]=0x04; buffer_r[0x2b]=0x02; buffer_r[0x2c]=0x01; buffer_r[0x2d]=0xff; buffer_r[0x30]=0x00; buffer_r[0x31]=0x00; buffer_r[0x32]=0x00; buffer_r[0x33]=0x00; set_WD_width (buffer_r,(2592)); set_WD_length (buffer_r,(3894)); } else { set_WD_scanmode_LS30 (buffer_r, WD_Scan); /* the coolscan LS-30 uses the upper left corner as the origin of coordinates */ /* xmax and ymax are given in 1200 dpi */ set_WD_ULX (buffer_r, s->tlx); set_WD_ULY (buffer_r, s->tly); /* upper_edge y */ set_WD_width (buffer_r, (s->brx - s->tlx+1)); set_WD_length (buffer_r, (s->bry - s->tly+1)); /* BTC */ if (s->brightness == 128) { buffer_r[0x32]=0x00; } else { buffer_r[0x32]=s->brightness; /* brightness */ } if (s->contrast == 128) { buffer_r[0x33]=0x00; } else { buffer_r[0x33]=s->contrast; /* contrast */ } /* scanmode */ if (s->colormode == GREYSCALE) set_WD_composition (buffer_r, WD_comp_grey); /* GRAY composition */ else set_WD_composition (buffer_r, WD_comp_rgb_full); /* RGB composition */ set_WD_composition (buffer_r, WD_comp_rgb_full); /* allways RGB composition */ /* Bits per pixel */ set_WD_bitsperpixel(buffer_r, s->bits_per_color); buffer_r[0x29]=0x81; buffer_r[0x2a]=0x01; buffer_r[0x2b]=0x02; buffer_r[0x2c]=0x01; buffer_r[0x2d]=0xff; buffer_r[0x30]=0x00; } set_WD_negative_LS30(buffer_r, s->negative); /* Negative/positive slide */ switch(wid) { case 1: set_gain_LS30(buffer_r,(s->exposure_R*s->pretv_r)/50); break; case 2: set_gain_LS30(buffer_r,(s->exposure_G*s->pretv_g)/50); break; case 3: set_gain_LS30(buffer_r,(s->exposure_B*s->pretv_b)/50); break; } DBG (10, "\texpo_r=%d, expo_g=%d, expob=%d\n", s->exposure_R, s->exposure_G, s->exposure_B); DBG (10, "\tpre_r=%d, pre_g=%d, preb=%d\n", s->pretv_r, s->pretv_g, s->pretv_b); DBG (10, "\tx_nres=%d, y_nres=%d, upper left-x=%d, upper left-y=%d\n", s->x_nres, s->y_nres, s->tlx, s->tly); DBG (10, "\twindow width=%d, MUD=%d, brx=%d\n", s->brx - s->tlx, s->MUD, s->brx); DBG (10, "\tcolormode=%d, bits per pixel=%d\n", s->colormode, s->bits_per_color); DBG (10, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n", s->negative, s->dropoutcolor, s->preview, s->transfermode, s->gammaselection); /* prepare SCSI-BUFFER */ memcpy (s->buffer, set_window.cmd, set_window.size); /* SET-WINDOW cmd */ memcpy ((s->buffer + set_window.size), /* add WPDB */ window_parameter_data_block.cmd, window_parameter_data_block.size); set_WPDB_wdblen ((s->buffer + set_window.size), used_WDB_size_LS30); /* set WD_len */ memcpy (s->buffer + set_window.size + window_parameter_data_block.size, buffer_r, window_descriptor_block_LS30.size); hexdump (15, "Window set", buffer_r, s->wdb_len); set_SW_xferlen (s->buffer, (window_parameter_data_block.size + window_descriptor_block_LS30.size)); ret = do_scsi_cmd (s->sfd, s->buffer, set_window.size + window_parameter_data_block.size + window_descriptor_block_LS30.size, NULL, 0); DBG (10, "window set.\n"); return ret; } static int coolscan_set_window_param (Coolscan_t * s, int prescan) { int ret; ret=0; DBG (10, "set_window_param\n"); if(s->LS<2) /* distinquish between old and new scanners */ { ret=coolscan_set_window_param_LS20 (s,prescan); } else { do_scsi_cmd (s->sfd,commande1.cmd,commande1.size,s->buffer,0x0d); wait_scanner (s); wait_scanner (s); coolscan_set_window_param_LS30(s,1,prescan); ret=coolscan_set_window_param_LS30(s,2,prescan); ret=coolscan_set_window_param_LS30(s,3,prescan); if(s->colormode&0x08) { ret=coolscan_set_window_param_LS30(s,9,prescan); } } return ret; } /* * The only purpose of get_window is debugging. None of the return parameters * is currently used. */ static int coolscan_get_window_param_LS30 (Coolscan_t * s, int wid,int prescanok) { int translen; unsigned char *buf; DBG (10, "GET_WINDOW_PARAM\n"); /* wait_scanner (s); */ translen = window_parameter_data_block.size + window_descriptor_block_LS30.size; /* prepare SCSI-BUFFER */ memset (s->buffer, '\0', max_WDB_size); /* clear buffer */ set_SW_xferlen (get_window.cmd, translen); /* Transfer length */ get_window.cmd[5]= wid; /* window identifier */ hexdump (15, "Get window cmd", get_window.cmd, get_window.size); do_scsi_cmd (s->sfd, get_window.cmd, get_window.size, s->buffer, translen); buf = s->buffer + window_parameter_data_block.size; hexdump (10, "Window get", buf, 117); s->brightness = buf[0x32]; /* brightness */ s->contrast = buf[0x33]; /* contrast */ DBG (10, "\tbrightness=%d, contrast=%d\n", s->brightness, s->contrast); /* Useful? */ s->bits_per_color = get_WD_bitsperpixel (buf); /* bits/pixel (8) */ DBG (10, "\tcolormode=%d, bits per pixel=%d\n", s->colormode, s->bits_per_color); if(prescanok) { switch(wid) { case 1: s->pretv_r = get_gain_LS30(buf); break; case 2: s->pretv_g = get_gain_LS30(buf); break; case 3: s->pretv_b = get_gain_LS30(buf); break; } } /* Should this one be set at all, here? */ s->transfermode = get_WD_transfermode (buf); s->gammaselection = get_WD_gammaselection (buf); /* monitor/linear */ DBG (10, "\tpre_r=%d, pre_g=%d, preb=%d\n", s->pretv_r, s->pretv_g, s->pretv_b); DBG (5, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n", s->negative, s->dropoutcolor, s->preview, s->transfermode, s->gammaselection); DBG (10, "get_window_param - return\n"); return 0; } /* * The only purpose of get_window is debugging. None of the return parameters * is currently used. */ static int coolscan_get_window_param_LS20 (Coolscan_t * s) { int translen; unsigned char *buf; DBG (10, "GET_WINDOW_PARAM\n"); wait_scanner (s); translen = window_parameter_data_block.size + window_descriptor_block.size; /* prepare SCSI-BUFFER */ memset (s->buffer, '\0', max_WDB_size); /* clear buffer */ set_SW_xferlen (get_window.cmd, translen); /* Transfer length */ hexdump (15, "Get window cmd", get_window.cmd, get_window.size); do_scsi_cmd (s->sfd, get_window.cmd, get_window.size, s->buffer, translen); buf = s->buffer + window_parameter_data_block.size; hexdump (10, "Window get", buf, 117); /* BTC */ s->brightness = get_WD_brightness (buf); /* brightness */ s->contrast = get_WD_contrast (buf); /* contrast */ DBG (10, "\tbrightness=%d, contrast=%d\n", s->brightness, s->contrast); if (WD_comp_gray == get_WD_composition (buf)) s->colormode = GREYSCALE; else s->colormode = RGB; /* Useful? */ s->bits_per_color = get_WD_bitsperpixel (buf); /* bits/pixel (8) */ DBG (10, "\tcolormode=%d, bits per pixel=%d\n", s->colormode, s->bits_per_color); s->dropoutcolor = get_WD_dropoutcolor (buf); /* Which color to scan with when grayscale scan */ /* Should this one be set at all, here? */ s->transfermode = get_WD_transfermode (buf); s->gammaselection = get_WD_gammaselection (buf); /* monitor/linear */ DBG (5, "\tnegative=%d, dropoutcolor=%d, preview=%d, transfermode=%d, gammasel=%d\n", s->negative, s->dropoutcolor, s->preview, s->transfermode, s->gammaselection); /* Should this one be set at all? */ s->shading = get_WD_shading (buf); s->averaging = get_WD_averaging (buf); DBG (10, "get_window_param - return\n"); return 0; } /* * The only purpose of get_window is debugging. None of the return parameters * is currently used. */ static int coolscan_get_window_param (Coolscan_t * s, int prescanok) { int ret; DBG (10, "get_window_param\n"); ret=0; if(s->LS<2) /* distinquish between old and new scanners */ { ret=coolscan_get_window_param_LS20 (s); } else { ret=coolscan_get_window_param_LS30(s,1,prescanok); ret=coolscan_get_window_param_LS30(s,2,prescanok); ret=coolscan_get_window_param_LS30(s,3,prescanok); if(s->colormode&0x08) { ret=coolscan_get_window_param_LS30(s,9,prescanok); } } return ret; } static int coolscan_start_scanLS30 (Coolscan_t * s) { int channels; DBG (10, "starting scan\n"); channels=1; memcpy (s->buffer, scan.cmd, scan.size); switch(s->colormode) { case RGB: case GREYSCALE: channels=s->buffer[4]=0x03; /* window 1 */ s->buffer[6]=0x01; /* window 1 */ s->buffer[7]=0x02; /* window 2 */ s->buffer[8]=0x03; /* window 3 */ break; case RGBI: channels=s->buffer[4]=0x04; /* window 1 */ s->buffer[6]=0x01; /* window 1 */ s->buffer[7]=0x02; /* window 2 */ s->buffer[8]=0x03; /* window 3 */ s->buffer[9]=0x09; /* window 3 */ break; case IRED: channels=s->buffer[4]=0x01; /* window 1 */ s->buffer[8]=0x09; /* window 3 */ break; } return do_scsi_cmd (s->sfd, s->buffer, scan.size+channels, NULL, 0); } static int coolscan_start_scan (Coolscan_t * s) { DBG (10, "starting scan\n"); if(s->LS>=2) { return coolscan_start_scanLS30(s); } return do_scsi_cmd (s->sfd, scan.cmd, scan.size, NULL, 0); } static int prescan (Coolscan_t * s) { int ret; DBG (10, "Starting prescan...\n"); if(s->LS<2) { coolscan_set_window_param (s, 1); } else { do_scsi_cmd (s->sfd,commande1.cmd,commande1.size,s->buffer,0x0d); wait_scanner (s); wait_scanner (s); coolscan_set_window_param_LS30 (s,1,1); coolscan_set_window_param_LS30 (s,2,1); coolscan_set_window_param_LS30 (s,3,1); } ret = coolscan_start_scan(s); sleep(8); /* prescan takes a minimum of 10 sec. */ wait_scanner (s); DBG (10, "Prescan done\n"); return ret; } static SANE_Status do_prescan_now (Coolscan_t * scanner) { DBG (10, "do_prescan_now \n"); if (scanner->scanning == SANE_TRUE) return SANE_STATUS_DEVICE_BUSY; if (scanner->sfd < 0) { /* first call */ if (sanei_scsi_open (scanner->sane.name, &(scanner->sfd), sense_handler, 0) != SANE_STATUS_GOOD) { DBG (1, "do_prescan_now: open of %s failed:\n", scanner->sane.name); return SANE_STATUS_INVAL; } } scanner->scanning = SANE_TRUE; if (coolscan_check_values (scanner) != 0) { /* Verify values */ DBG (1, "ERROR: invalid scan-values\n"); scanner->scanning = SANE_FALSE; coolscan_give_scanner (scanner); sanei_scsi_close (scanner->sfd); scanner->sfd = -1; return SANE_STATUS_INVAL; } if (coolscan_grab_scanner (scanner)) { sanei_scsi_close (scanner->sfd); scanner->sfd = -1; DBG (5, "WARNING: unable to reserve scanner: device busy\n"); scanner->scanning = SANE_FALSE; return SANE_STATUS_DEVICE_BUSY; } prescan (scanner); if(scanner->LS<2) { get_internal_info(scanner); } coolscan_get_window_param (scanner,1); scanner->scanning = SANE_FALSE; coolscan_give_scanner (scanner); return SANE_STATUS_GOOD; } static int send_one_LUT (Coolscan_t * s, SANE_Word * LUT, int reg) { int i; short lutval; short bytesperval; unsigned char *gamma, *gamma_p; unsigned short *gamma_s; DBG (10, "send LUT\n"); if(s->LS<2) { set_S_datatype_code (send.cmd, R_user_reg_gamma); bytesperval=1; } else { send.cmd[0x02]=3; send.cmd[0x05]=1; bytesperval=2; } set_S_xfer_length (send.cmd, s->lutlength*bytesperval); set_S_datatype_qual_upper (send.cmd, reg); gamma = alloca (send.size + s->lutlength*2); memcpy (gamma, send.cmd, send.size); if(s->LS<2) { gamma_p = &gamma[send.size]; for (i = 0; i < s->lutlength; i++) { if (LUT[i] > 255) LUT[i] = 255; /* broken gtk */ *gamma_p++ = (unsigned char) LUT[i]; } } else if(s->LS==2) { gamma_s = (unsigned short*)( &gamma[send.size]); for (i = 0; i < s->lutlength; i++) { if(s->negative) { lutval=(unsigned short)(LUT[(s->lutlength-i)]); } else { lutval=(unsigned short)(LUT[i]); } if (LUT[i] >= s->max_lut_val) LUT[i] = s->max_lut_val-1; /* broken gtk */ if(s->low_byte_first) /* if on little endian machine: */ { lutval=((lutval&0x00ff)<<8)+((lutval&0xff00)>>8); /* inverse byteorder */ } *gamma_s++ = lutval; } } else if(s->LS==3) { gamma_s = (unsigned short*)( &gamma[send.size]); for (i = 0; i < s->lutlength; i++) { if(s->negative) { lutval=(unsigned short)(LUT[s->lutlength-i]); } else { lutval=(unsigned short)(LUT[i]); } if (LUT[i] >= s->max_lut_val) LUT[i] = s->max_lut_val-1; /* broken gtk */ if(s->low_byte_first) /* if on little endian machine: */ { lutval=((lutval&0x00ff)<<8)+((lutval&0xff00)>>8); /* inverse byteorder */ } *gamma_s++ = lutval; } } return do_scsi_cmd (s->sfd, gamma, send.size + s->lutlength*bytesperval, NULL, 0); } static int send_LUT (Coolscan_t * s) { wait_scanner (s); if (s->gamma_bind) { send_one_LUT (s, s->gamma, S_DQ_Reg1); if(s->LS>=2) { send_one_LUT (s, s->gamma, S_DQ_Reg2); send_one_LUT (s, s->gamma, S_DQ_Reg3); if(s->colormode&0x08) { send_one_LUT (s, s->gamma, S_DQ_Reg9); } } } else { send_one_LUT (s, s->gamma_r, S_DQ_Reg1); send_one_LUT (s, s->gamma_g, S_DQ_Reg2); send_one_LUT (s, s->gamma_b, S_DQ_Reg3); if(s->colormode&0x08) { send_one_LUT (s, s->gamma_r, S_DQ_Reg9); } } return 0; } static int coolscan_read_data_block (Coolscan_t * s, unsigned int datatype, unsigned int length) { int r; DBG (10, "read_data_block (type= %x length = %d)\n",datatype,length); /*wait_scanner(s); */ set_R_datatype_code (sread.cmd, datatype); sread.cmd[4]=00; sread.cmd[5]=00; set_R_xfer_length (sread.cmd, length); r = do_scsi_cmd (s->sfd, sread.cmd, sread.size, s->buffer, length); return ((r != 0) ? -1 : (int) length); } static void coolscan_do_inquiry (Coolscan_t * s) { int size; DBG (10, "do_inquiry\n"); memset (s->buffer, '\0', 256); /* clear buffer */ size = 36; /* Hardcoded, and as specified by Nikon */ /* then get inquiry with actual size */ set_inquiry_return_size (inquiry.cmd, size); do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size, s->buffer, size); } static int coolscan_identify_scanner (Coolscan_t * s) { unsigned char vendor[9]; unsigned char product[0x11]; unsigned char version[5]; unsigned char *pp; int i; vendor[8] = product[0x10] = version[4] = 0; DBG (10, "identify_scanner\n"); coolscan_do_inquiry (s); /* get inquiry */ if (get_inquiry_periph_devtype (s->buffer) != IN_periph_devtype_scanner) { DBG (5, "identify_scanner: not a scanner\n"); return 1; } /* no, continue searching */ coolscan_get_inquiry_values (s); get_inquiry_vendor ((char *)s->buffer, (char *)vendor); get_inquiry_product ((char *)s->buffer, (char *)product); get_inquiry_version ((char *)s->buffer, (char *)version); if (strncmp ("Nikon ", (char *)vendor, 8)) { DBG (5, "identify_scanner: \"%s\" isn't a Nikon product\n", vendor); return 1; } /* Not a Nikon product */ pp = &vendor[8]; vendor[8] = ' '; while (*pp == ' ') { *pp-- = '\0'; } pp = &product[0x10]; product[0x10] = ' '; while (*(pp - 1) == ' ') { *pp-- = '\0'; } /* leave one blank at the end! */ pp = &version[4]; version[4] = ' '; while (*pp == ' ') { *pp-- = '\0'; } DBG (10, "Found Nikon scanner %sversion %s on device %s\n", product, version, s->devicename); /* look for scanners that do not give all inquiry-informations */ /* and if possible use driver-known inquiry-data */ if (get_inquiry_additional_length (s->buffer) >= 0x1f) { /* Now identify full supported scanners */ for (i = 0; i < known_scanners; i++) { if (!strncmp ((char *)product, scanner_str[i], strlen (scanner_str[i]))) { s->LS = i; return 0; } } if (s->cont) return 0; else return 1; } else return 1; } static int pixels_per_line (Coolscan_t * s) { int pic_dot; if(s->LS<2) { pic_dot = (s->brx - s->tlx + s->x_nres) / s->x_nres; } else { pic_dot = (s->brx - s->tlx + 1) / s->x_nres; } DBG (10, "pic_dot=%d\n", pic_dot); return pic_dot; } static int lines_per_scan (Coolscan_t * s) { int pic_line; if(s->LS<2) { pic_line = (s->bry - s->tly + s->y_nres) / s->y_nres; } else { pic_line = (( s->bry - s->tly + 1.0 ) / s->y_nres); } DBG (10, "pic_line=%d\n", pic_line); return pic_line; } static int scan_bytes_per_line (Coolscan_t * s) { int bpl; switch(s->colormode) { case RGB: case GREYSCALE: bpl=pixels_per_line (s) * 3; if(s->bits_per_color>8) bpl=bpl*2; return bpl; break; case RGBI: case IRED: bpl=pixels_per_line (s) * 4; if(s->bits_per_color>8) bpl=bpl*2; return bpl; break; } return 0; } static int write_bytes_per_line (Coolscan_t * s) { int bpl; switch(s->colormode) { case RGB: bpl=pixels_per_line (s) * 3; if(s->bits_per_color>8) bpl=bpl*2; return bpl; break; case RGBI: bpl=pixels_per_line (s) * 4; if(s->bits_per_color>8) bpl=bpl*2; return bpl; break; case IRED: case GREYSCALE: bpl= pixels_per_line (s) ; if(s->bits_per_color>8) bpl=bpl*2; return bpl; break; } return 0; } static void coolscan_trim_rowbufsize (Coolscan_t * s) { unsigned int row_len; row_len = scan_bytes_per_line (s); s->row_bufsize = (s->row_bufsize < row_len) ? s->row_bufsize : s->row_bufsize - (s->row_bufsize % row_len); DBG (10, "trim_bufsize to %d\n", s->row_bufsize); } static int coolscan_check_values (Coolscan_t * s) { DBG (10, "check_values\n"); /* -------------------------- asf --------------------------------- */ if (s->asf != 0) { if (s->autofeeder == 0) { DBG (1, "ERROR: ASF-MODE NOT SUPPORTED BY SCANNER, ABORTING\n"); return (1); } } return (0); } /* test_little_endian */ static SANE_Bool coolscan_test_little_endian(void) { SANE_Int testvalue = 255; unsigned char *firstbyte = (unsigned char *) &testvalue; if (*firstbyte == 255) { return SANE_TRUE; } return SANE_FALSE; } static int get_inquiery_part_LS30 (Coolscan_t * s, unsigned char part) { int size; /* Get length of reponse */ inquiry.cmd[1]=0x01; inquiry.cmd[2]=part; size=4; set_inquiry_return_size (inquiry.cmd, size); do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size, s->buffer, size); size=get_inquiry_length(s->buffer); size+=4; /* then get inquiry with actual size */ set_inquiry_return_size (inquiry.cmd, size); do_scsi_cmd (s->sfd, inquiry.cmd, inquiry.size, s->buffer, size); return size; } static int coolscan_read_var_data_block (Coolscan_t * s,int datatype) { int r; int size; DBG (10, "read_data_block (type= %x)\n",datatype); /*wait_scanner(s); */ sread.cmd[2]=datatype; sread.cmd[4]=00; sread.cmd[5]=03; size=6; set_R_xfer_length (sread.cmd, size); r = do_scsi_cmd (s->sfd, sread.cmd, sread.size, s->buffer, size); size=s->buffer[5]; set_R_xfer_length (sread.cmd, size); r = do_scsi_cmd (s->sfd, sread.cmd, sread.size, s->buffer, size); return ((r != 0) ? -1 : size); } static int get_inquiery_LS30 (Coolscan_t * s) { unsigned char part; unsigned char parts[5]; int i; /* Get vector of inquiery parts */ get_inquiery_part_LS30(s, (unsigned char) 0); /* Get the parts of inquiery */ for(i=0;i<5;i++) { parts[i]=((unsigned char *)s->buffer)[4+11+i]; } for(i=0;i<5;i++) { part=parts[i]; get_inquiery_part_LS30 (s, part); switch(part) { case 0x0c1:/* max size and resolution */ s->adbits = 8; s->outputbits = 8; s->maxres = getnbyte(s->buffer+0x12,2)-1; s->xmaxpix = getnbyte(s->buffer+0x53,2)-1; s->ymaxpix = getnbyte(s->buffer+0x3c,2)-1; break; case 0x0d1: break; case 0x0e1: break; case 0x0f0: break; case 0x0f8: break; } } /* get windows */ coolscan_get_window_param_LS30 (s,0,0); s->xmax = get_WD_width(s->buffer); s->ymax = get_WD_length(s->buffer); coolscan_get_window_param_LS30 (s,1,0); coolscan_get_window_param_LS30 (s,2,0); coolscan_get_window_param_LS30 (s,3,0); coolscan_get_window_param_LS30 (s,4,0); coolscan_get_window_param_LS30 (s,9,0); s->analoggamma = 0; return 1; } static int get_feeder_type_LS30 (Coolscan_t * s) { int size; unsigned char *ptr; int ima; /* find out about Film-strip-feeder or Mount-Feeder */ size=get_inquiery_part_LS30(s, (unsigned char) 1); if(strncmp((char *)s->buffer+5,"Strip",5)==0) { s->feeder=STRIP_FEEDER; s->autofeeder = 1; } if(strncmp((char *)s->buffer+5,"Mount",5)==0) { s->feeder=MOUNT_FEEDER; } /* find out about Film-strip-feeder positions*/ if(s->feeder==STRIP_FEEDER) { size=coolscan_read_var_data_block (s,(int)0x88); if(size>=4) { s->numima=s->buffer[3]; if(s->numima>6) s->numima=6; /* limit to 6 images for now */ if(s->numima>(size-4)/16) s->numima=(size-4)/16; ptr=s->buffer+4; for(ima=0;imanumima;ima++) { s->ipos[ima].start=getnbyte(ptr,4); s->ipos[ima].offset=getnbyte(ptr+4,4); s->ipos[ima].end=getnbyte(ptr+8,4); s->ipos[ima].height=getnbyte(ptr+12,4); ptr+=16; } } s->posima=0; } return 1; } static int get_internal_info_LS20 (Coolscan_t * s) { int ret; DBG (10, "get_internal_info\n"); wait_scanner (s); memset (s->buffer, '\0', DI_length); /* clear buffer */ set_R_datatype_code (sread.cmd, R_device_internal_info); set_R_datatype_qual_upper (sread.cmd, R_DQ_none); set_R_xfer_length (sread.cmd, DI_length); /* then get inquiry with actual size */ ret = do_scsi_cmd (s->sfd, sread.cmd, sread.size, s->buffer, DI_length); s->adbits = get_DI_ADbits (s->buffer); s->outputbits = get_DI_Outputbits (s->buffer); s->maxres = get_DI_MaxResolution (s->buffer); s->xmax = get_DI_Xmax (s->buffer); s->ymax = get_DI_Ymax (s->buffer); s->xmaxpix = get_DI_Xmaxpixel (s->buffer); s->ymaxpix = get_DI_Ymaxpixel (s->buffer); s->ycurrent = get_DI_currentY (s->buffer); s->currentfocus = get_DI_currentFocus (s->buffer); s->currentscanpitch = get_DI_currentscanpitch (s->buffer); s->autofeeder = get_DI_autofeeder (s->buffer); s->analoggamma = get_DI_analoggamma (s->buffer); s->derr[0] = get_DI_deviceerror0 (s->buffer); s->derr[1] = get_DI_deviceerror1 (s->buffer); s->derr[2] = get_DI_deviceerror2 (s->buffer); s->derr[3] = get_DI_deviceerror3 (s->buffer); s->derr[4] = get_DI_deviceerror4 (s->buffer); s->derr[5] = get_DI_deviceerror5 (s->buffer); s->derr[6] = get_DI_deviceerror6 (s->buffer); s->derr[7] = get_DI_deviceerror7 (s->buffer); s->wbetr_r = get_DI_WBETR_R (s->buffer); s->webtr_g = get_DI_WBETR_G (s->buffer); s->webtr_b = get_DI_WBETR_B (s->buffer); s->pretv_r = get_DI_PRETV_R (s->buffer); s->pretv_g = get_DI_PRETV_G (s->buffer); s->pretv_r = get_DI_PRETV_R (s->buffer); s->cetv_r = get_DI_CETV_R (s->buffer); s->cetv_g = get_DI_CETV_G (s->buffer); s->cetv_b = get_DI_CETV_B (s->buffer); s->ietu_r = get_DI_IETU_R (s->buffer); s->ietu_g = get_DI_IETU_G (s->buffer); s->ietu_b = get_DI_IETU_B (s->buffer); s->limitcondition = get_DI_limitcondition (s->buffer); s->offsetdata_r = get_DI_offsetdata_R (s->buffer); s->offsetdata_g = get_DI_offsetdata_G (s->buffer); s->offsetdata_b = get_DI_offsetdata_B (s->buffer); get_DI_poweron_errors (s->buffer, s->power_on_errors); DBG (10, "\tadbits=%d\toutputbits=%d\tmaxres=%d\txmax=%d\tymax=%d\n" "\txmaxpix=%d\tymaxpix=%d\tycurrent=%d\tcurrentfocus=%d\n" "\tautofeeder=%s\tanaloggamma=%s\tcurrentscanpitch=%d\n", s->adbits, s->outputbits, s->maxres, s->xmax, s->ymax, s->xmaxpix, s->ymaxpix, s->ycurrent, s->currentfocus, s->autofeeder ? "Yes" : "No", s->analoggamma ? "Yes" : "No", s->currentscanpitch); DBG (10, "\tWhite balance exposure time var [RGB]=\t%d %d %d\n" "\tPrescan result exposure time var [RGB]=\t%d %d %d\n" "\tCurrent exposure time var.[RGB]=\t%d %d %d\n" "\tInternal exposure time unit[RGB]=\t%d %d %d\n", s->wbetr_r, s->webtr_g, s->webtr_b, s->pretv_r, s->pretv_g, s->pretv_r, s->cetv_r, s->cetv_g, s->cetv_b, s->ietu_r, s->ietu_g, s->ietu_b); DBG (10, "\toffsetdata_[rgb]=\t0x%x 0x%x 0x%x\n" "\tlimitcondition=0x%x\n" "\tdevice error code = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n" "\tpower-on errors = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", s->offsetdata_r, s->offsetdata_g, s->offsetdata_b, s->limitcondition, s->derr[0], s->derr[1], s->derr[2], s->derr[3], s->derr[4], s->derr[5], s->derr[6], s->derr[7], s->power_on_errors[0], s->power_on_errors[1], s->power_on_errors[2], s->power_on_errors[3], s->power_on_errors[4], s->power_on_errors[5], s->power_on_errors[6], s->power_on_errors[7]); return ret; } static int get_internal_info (Coolscan_t * s) { int ret; DBG (10, "get_internal_info\n"); if(s->LS<2) /* distinquish between old and new scanners */ { ret=get_internal_info_LS20 (s); } else { ret=get_inquiery_LS30 (s); } return ret; } static void coolscan_get_inquiry_values (Coolscan_t * s) { unsigned char *inquiry_block; DBG (10, "get_inquiry_values\n"); inquiry_block = (unsigned char *) s->buffer; s->inquiry_len = 36; get_inquiry_vendor ((char *)inquiry_block, (char *)s->vendor); s->vendor[8] = '\0'; get_inquiry_product ((char *)inquiry_block, (char *)s->product); s->product[16] = '\0'; get_inquiry_version ((char *)inquiry_block, (char *)s->version); s->version[4] = '\0'; if (s->inquiry_len < 36) { DBG (1, "WARNING: inquiry return block is unexpected short (%d instead of 36).\n", s->inquiry_len); } s->inquiry_wdb_len = 117; return; } static void coolscan_initialize_values (Coolscan_t * s) { int i; DBG (10, "initialize_values\n"); /* Initialize us structure */ if(s->LS<2) /* LS-20 or LS-10000 */ { select_MUD (s); /* must be before mode_sense - not for LS-30*/ coolscan_mode_sense (s); /* Obtain MUD (Measurement Unit Divisor) */ get_internal_info (s); /* MUST be called first. */ s->wdb_len = 117; } if(s->LS>=2) /* LS-30 */ { get_inquiery_LS30(s); /* Info about scanner*/ select_MUD (s); /* must be before mode_sense */ get_feeder_type_LS30(s); s->wdb_len = 117; } s->cont = 0; /* do not continue if scanner is unknown */ s->verbose = 2; /* 1=verbose,2=very verbose */ s->x_nres = s->y_nres = 2; /* 2 => 1350 dpi */ s->x_p_nres = s->y_p_nres = 9; /* 9 => 300 dpi */ s->tlx = 0; s->tly = 0; s->brx = s->xmaxpix; /* 2700 / 1200; */ s->bry = s->ymaxpix; /* 2700 / 1200; */ s->set_auto = 0; /* Always 0 on Nikon LS-{100|2}0 */ s->preview = 0; /* 1 for preview */ s->colormode = RGB; /* GREYSCALE or RGB */ s->colormode_p = RGB; /* GREYSCALE or RGB for preview*/ s->asf = 0; /* 1 if asf shall be used */ s->gammaselection = WD_Linear; s->brightness = 128; s->brightness_R = 128; s->brightness_G = 128; s->brightness_B = 128; s->contrast = 128; s->contrast_R = 128; s->contrast_G = 128; s->contrast_B = 128; s->exposure_R = 50; s->exposure_G = 50; s->exposure_B = 50; s->pretv_r=40000; s->pretv_g=40000; s->pretv_b=40000; s->shift_R = 128; s->shift_G = 128; s->shift_B = 128; s->ired_red=60; s->ired_green=1; s->ired_blue=1; s->prescan = 1; s->bits_per_color = 8; s->rgb_control = 0; s->gamma_bind = 1; switch(s->LS) { case 0:s->lutlength=2048; s->max_lut_val=256; break; case 1:s->lutlength=512; s->max_lut_val=512; break; case 2:s->lutlength=1024; s->max_lut_val=1024; break; case 3:s->lutlength=4096; s->max_lut_val=4096; break; } for (i = 0; i < s->lutlength; i++) { s->gamma[i] =((short)((((double)i)/s->lutlength)*s->max_lut_val)); s->gamma_r[i] = s->gamma[i]; s->gamma_g[i] = s->gamma[i]; s->gamma_b[i] = s->gamma[i]; } if (coolscan_test_little_endian() == SANE_TRUE) { s->low_byte_first = 1; /* in 2 byte mode send lowbyte first */ DBG(10,"backend runs on little endian machine\n"); } else { s->low_byte_first = 0; /* in 2 byte mode send highbyte first */ DBG(10,"backend runs on big endian machine\n"); } } static void hexdump (int level, char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; DBG (level, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { *ptr = '\0'; DBG (level, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3d:", i); ptr += 4; } sprintf (ptr, " %2.2x", *p); ptr += 3; } *ptr = '\0'; DBG (level, "%s\n", line); } static SANE_Status sense_handler (int scsi_fd, unsigned char * result, void *arg) { scsi_fd = scsi_fd; arg = arg; if (result[0] != 0x70) { return SANE_STATUS_IO_ERROR; /* we only know about this one */ } return request_sense_parse(result); } /* ------------------------------------------------------------------------- */ /* ilu per mm */ #define length_quant SANE_UNFIX(SANE_FIX(MM_PER_INCH / 2700.0)) #define mmToIlu(mm) ((mm) / length_quant) #define iluToMm(ilu) ((ilu) * length_quant) #define P_200_TO_255(per) SANE_UNFIX((per + 100) * 255/200 ) #define P_100_TO_255(per) SANE_UNFIX(per * 255/100 ) static const char negativeStr[] = "Negative"; static const char positiveStr[] = "Positive"; static SANE_String_Const type_list[] = { positiveStr, negativeStr, 0 }; static const char colorStr[] = SANE_VALUE_SCAN_MODE_COLOR; static const char grayStr[] = SANE_VALUE_SCAN_MODE_GRAY; static const char rgbiStr[] = "RGBI"; static const char iredStr[] = "Infrared"; static SANE_String_Const scan_mode_list_LS20[] = { colorStr, grayStr, NULL }; static SANE_String_Const scan_mode_list_LS30[] = { colorStr, grayStr, #ifdef HAS_IRED rgbiStr, #endif /* HAS_IRED */ NULL }; static SANE_Int bit_depth_list[9]; static const char neverStr[] = "never"; static const char previewStr[] = "before preview"; static const char scanStr[] = "before scan"; static const char preandscanStr[] = "before preview and scan"; static SANE_String_Const autofocus_mode_list[] = { neverStr, previewStr, scanStr, preandscanStr, NULL }; static SANE_String_Const source_list[4] = {NULL, NULL, NULL, NULL}; static const SANE_Range gamma_range_8 = { 0, /* minimum */ 255, /* maximum */ 1 /* quantization */ }; static const SANE_Range gamma_range_9 = { 0, /* minimum */ 511, /* maximum */ 1 /* quantization */ }; static const SANE_Range gamma_range_10 = { 0, /* minimum */ 1023, /* maximum */ 1 /* quantization */ }; static const SANE_Range gamma_range_12 = { 0, /* minimum */ 4096, /* maximum */ 1 /* quantization */ }; static const SANE_Range brightness_range = { -5, +5, 1 }; static const SANE_Range contrast_range = { -5, +5, 0 }; static const SANE_Range exposure_range = { 24, 400, 2 }; static const SANE_Range shift_range = { -15, +15, 0 }; static const SANE_Device **devlist = 0; static int num_devices; static Coolscan_t *first_dev; static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status do_eof (Coolscan_t * scanner) { DBG (10, "do_eof\n"); if (scanner->pipe >= 0) { close (scanner->pipe); scanner->pipe = -1; } return SANE_STATUS_EOF; } static SANE_Status do_cancel (Coolscan_t * scanner) { DBG (10, "do_cancel\n"); swap_res (scanner); scanner->scanning = SANE_FALSE; do_eof (scanner); /* close pipe and reposition scanner */ if (sanei_thread_is_valid (scanner->reader_pid)) { int exit_status; DBG (10, "do_cancel: kill reader_process\n"); /* ensure child knows it's time to stop: */ sanei_thread_kill (scanner->reader_pid); while (sanei_thread_waitpid(scanner->reader_pid, &exit_status) != scanner->reader_pid ); scanner->reader_pid = -1; } if (scanner->sfd >= 0) { coolscan_give_scanner (scanner); DBG (10, "do_cancel: close filedescriptor\n"); sanei_scsi_close (scanner->sfd); scanner->sfd = -1; } return SANE_STATUS_CANCELLED; } static SANE_Status attach_scanner (const char *devicename, Coolscan_t ** devp) { Coolscan_t *dev; int sfd; DBG (10, "attach_scanner: %s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (5, "attach_scanner: scanner already attached (is ok)!\n"); return SANE_STATUS_GOOD; } } DBG (10, "attach_scanner: opening %s\n", devicename); if (sanei_scsi_open (devicename, &sfd, sense_handler, 0) != 0) { DBG (1, "attach_scanner: open failed\n"); return SANE_STATUS_INVAL; } if (NULL == (dev = malloc (sizeof (*dev)))) return SANE_STATUS_NO_MEM; dev->row_bufsize = (sanei_scsi_max_request_size < (64 * 1024)) ? sanei_scsi_max_request_size : 64 * 1024; if ((dev->buffer = malloc (dev->row_bufsize)) == NULL) /* if ((dev->buffer = malloc (sanei_scsi_max_request_size)) == NULL)*/ return SANE_STATUS_NO_MEM; if ((dev->obuffer = malloc (dev->row_bufsize)) == NULL) return SANE_STATUS_NO_MEM; dev->devicename = strdup (devicename); dev->sfd = sfd; /* Nikon manual: Step 1 */ if (coolscan_identify_scanner (dev) != 0) { DBG (1, "attach_scanner: scanner-identification failed\n"); sanei_scsi_close (dev->sfd); free (dev->buffer); free (dev); return SANE_STATUS_INVAL; } /* Get MUD (via mode_sense), internal info (via get_internal_info), and * initialize values */ coolscan_initialize_values (dev); /* Why? */ sanei_scsi_close (dev->sfd); dev->sfd = -1; dev->sane.name = dev->devicename; dev->sane.vendor = dev->vendor; dev->sane.model = dev->product; dev->sane.type = "slide scanner"; dev->x_range.min = SANE_FIX (0); dev->x_range.quant = SANE_FIX (length_quant); dev->x_range.max = SANE_FIX ((double) ((dev->xmaxpix) * length_quant)); dev->y_range.min = SANE_FIX (0.0); dev->y_range.quant = SANE_FIX (length_quant); dev->y_range.max = SANE_FIX ((double) ((dev->ymaxpix) * length_quant)); /* ...and this?? */ dev->dpi_range.min = SANE_FIX (108); dev->dpi_range.quant = SANE_FIX (0); dev->dpi_range.max = SANE_FIX (dev->maxres); DBG (10, "attach: dev->dpi_range.max = %f\n", SANE_UNFIX (dev->dpi_range.max)); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } DBG (10, "attach_scanner done\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *devName) { return attach_scanner(devName, 0); } static void sigterm_handler (int signal) { signal = signal; sanei_scsi_req_flush_all (); /* flush SCSI queue */ _exit (SANE_STATUS_GOOD); } typedef struct Color_correct_s { int sum; /* number of pixels summed so far */ double sumr; /* sum of red pixel values*/ double sumi; /* sum of infrared pixel values*/ double sumri; /* sum of red*ired pixel values*/ double sumii; /* sum of ired*ired pixel values*/ double sumrr; /* sum of ired*ired pixel values*/ int mr; /* factor between red and ired values (*256) */ int br; /* offset of ired values */ } ColorCorrect; /* --------------------------------------------------------------- function: RGBIfix taks: Correct the infrared channel import: unsigned char * rgbimat - RGBI - matrix from scanner int size - number of pixels to correct int *lutr - lookup table for red correction int *lutg - lookup table for red correction int *lutb - lookup table for red correction int *lutr - lookup table for red correction export: unsigned char * orgbimat - RGBI - corrected matrix written by: Andreas RICK 19.6.1999 ----------------------------------------------------------------*/ static int Calc_fix_LUT(Coolscan_t * s) { int uselutr,uselutg,uselutb,useluti; /* static int irmulr= -34*25; */ int irmulr= -64*25; int irmulg= -1*25; int irmulb= -0*25; int irmuli= 256*25; int div; int i; irmulr=s->ired_red*(25); irmulg=s->ired_green*(25); irmulb=s->ired_blue*(25); irmuli=25*256; if(s->LS==2) /* TODO: right conversion factors for 10 and 12 bit */ { div=4; } else if(s->LS==3) { div=16; } else { return 0; } memset(s->lutr, 0,256*4); memset(s->lutg, 0,256*4); memset(s->lutb, 0,256*4); memset(s->luti, 0,256*4); for(i=0;ilutlength;i++) { if(s->gamma_bind) { uselutr=uselutg=uselutb=useluti=s->gamma[i]/div; } else { uselutr=s->gamma_r[i]/div; uselutg=s->gamma_g[i]/div; uselutb=s->gamma_b[i]/div; useluti=s->gamma_r[i]/div; } s->lutr[uselutr]=(int)(irmulr*pow((double)i,(double)0.333333)); s->lutg[uselutg]=(int)(irmulg*pow((double)i,(double)0.333333)); s->lutb[uselutb]=(int)(irmulb*pow((double)i,(double)0.333333)); s->luti[useluti]=(int)(irmuli*pow((double)i,(double)0.333333)); if(uselutr<255) { if(s->lutr[uselutr+1]==0) s->lutr[uselutr+1]=s->lutr[uselutr]; } if(uselutg<255) { if(s->lutg[uselutg+1]==0) s->lutg[uselutg+1]=s->lutg[uselutg]; } if(uselutb<255) { if(s->lutb[uselutb+1]==0) s->lutb[uselutb+1]=s->lutb[uselutb]; } if(useluti<255) { if(s->luti[useluti+1]==0) s->luti[useluti+1]=s->luti[useluti]; } } /* DEBUG for(i=0;i<255;i++) { fprintf(stderr,"%d %d %d %d\n" ,s->lutr[i],s->lutg[i],s->lutb[i],s->luti[i]); } */ return 1; } /* --------------------------------------------------------------- function: RGBIfix taks: Correct the infrared channel import: unsigned char * rgbimat - RGBI - matrix from scanner int size - number of pixels to correct int *lutr - lookup table for red correction int *lutg - lookup table for red correction int *lutb - lookup table for red correction int *lutr - lookup table for red correction export: unsigned char * orgbimat - RGBI - corrected matrix written by: Andreas RICK 19.6.1999 ----------------------------------------------------------------*/ static int RGBIfix(Coolscan_t * scanner, unsigned char* rgbimat, unsigned char* orgbimat, int size, int *lutr, int *lutg, int *lutb, int *luti) { unsigned char *pr,*pg,*pb,*pi; unsigned char *opr,*opg,*opb,*opi; int r,g,b,i; int ii; int x; for(x=0;x255*256)ii=255*256; if(scanner->negative) { (*opi)=(unsigned char)(255-(ii>>8)); } else { (*opi)=(unsigned char)(ii>>8); } } return 1; } /* --------------------------------------------------------------- function: RGBIfix16 taks: Correct the infrared channel for 16 bit images (doesn't do anything for now) import: unsigned char * rgbimat - RGBI - matrix from scanner int size - number of pixels to correct int *lutr - lookup table for red correction int *lutg - lookup table for red correction int *lutb - lookup table for red correction int *lutr - lookup table for red correction export: unsigned char * orgbimat - RGBI - corrected matrix written by: Andreas RICK 19.6.1999 ----------------------------------------------------------------*/ static int RGBIfix16(Coolscan_t * scanner, unsigned short* rgbimat, unsigned short* orgbimat, int size, int *lutr, int *lutg, int *lutb, int *luti) { unsigned short *pr,*pg,*pb,*pi; unsigned short *opr,*opg,*opb,*opi; int x; scanner = scanner; lutr = lutr; lutg = lutg; lutb = lutb; luti = luti; for(x=0;x>8); (*opg)=(((*pg)&0x00ff)<<8)+(((*pg)&0xff00)>>8); (*opb)=(((*pb)&0x00ff)<<8)+(((*pb)&0xff00)>>8); (*opi)=(((*pi)&0x00ff)<<8)+(((*pi)&0xff00)>>8); } return 1; } /* --------------------------------------------------------------- function: rgb2g taks: Convert RGB data to grey import: unsigned char * rgbimat - RGB - matrix from scanner int size - size of input data (num pixel) export: unsigned char * gomat - Grey matrix written by: Andreas RICK 13.7.1999 ----------------------------------------------------------------*/ #define RtoG ((int)(0.27*256)) #define GtoG ((int)(0.54*256)) #define BtoG ((int)(0.19*256)) static int rgb2g(unsigned char* rgbimat,unsigned char* gomat, int size) { unsigned char *pr,*pg,*pb; unsigned char *opg; int g; int x; for(x=0;x>8); } return 1; } /* --------------------------------------------------------------- function: RGBIfix1 taks: Correct the infrared channel. The input image data is the output of scaning with LUT. To calculate the original values the lutr and luti is applied. The infrared values is corrected by: Ir=mr*lutr(r)+luti(i) import: unsigned char * rgbimat - RGBI - matrix from scanner int size - number of pixels to correct ColorCorrect *cc, int *lutr - lookup table for red correction int *luti - lookup table for ired correction export: unsigned char * orgbimat - RGBI - corrected matrix written by: Andreas RICK 3.7.1999 ----------------------------------------------------------------*/ #if 0 static int RGBIfix1(unsigned char* rgbimat,unsigned char* orgbimat, int size, int *lutr, int *lutg, int *lutb, int *luti) { unsigned char *pr,*pg,*pb,*pi; unsigned char *opr,*opg,*opb,*opi; ColorCorrect cc; int r,i; static int thresi=100; int ii; int x; lutg = lutg; lutb = lutb; /* calculate regression between r and ir */ cc.sum=0; cc.sumr=cc.sumii=cc.sumrr=cc.sumi=cc.sumri=0.0; for(x=0;xthresi) { cc.sum++; cc.sumr+=r; cc.sumii+=(i*i); cc.sumrr+=(r*r); cc.sumi+=i; cc.sumri+=(i*r); } } if((cc.sumii!=0)&&(cc.sum!=0)) { double dn,dz,dm; dz=(cc.sumri-cc.sumr*cc.sumi/cc.sum); dn=(cc.sumrr-cc.sumr*cc.sumr/cc.sum); DBG (2, "Reg:dz:%e dn:%e\n",dz,dn); if(dn!=0) { dm=(dz/dn); cc.mr=(int)(dm*1024); } else { cc.mr=0; dm=0; } cc.br=(int)((cc.sumi-dm*cc.sumr)/cc.sum); } else { cc.mr=0; } DBG (2, "Regression: size:%d I=%d/1024*R b:%d s:%d sr:%e si:%e sii:%e sri:%e srr:%e\n", size,cc.mr,cc.br,cc.sum,cc.sumr,cc.sumi,cc.sumii,cc.sumri,cc.sumrr); for(x=0;x>10)-cc.br)>>2) +128; (*opr)=(*pr); (*opg)=(*pg); (*opb)=(*pb); if(ii<0) ii=0; if(ii>255) ii=255; (*opi)=(unsigned char)(ii); } return 1; } #endif /* This function is executed as a child process. */ static int reader_process (void *data ) { int status; unsigned int i; unsigned char h; unsigned int data_left; unsigned int data_to_read; unsigned int data_to_write; FILE *fp; sigset_t sigterm_set, ignore_set; struct SIGACTION act; unsigned int bpl, linesPerBuf, lineOffset; unsigned char r_data, g_data, b_data; unsigned int j, line; Coolscan_t * scanner = (Coolscan_t*)data; if (sanei_thread_is_forked ()) { DBG (10, "reader_process started (forked)\n"); close (scanner->pipe); scanner->pipe = -1; sigfillset ( &ignore_set ); sigdelset ( &ignore_set, SIGTERM ); #if defined (__APPLE__) && defined (__MACH__) sigdelset ( &ignore_set, SIGUSR2 ); #endif sigprocmask( SIG_SETMASK, &ignore_set, 0 ); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); } else { DBG (10, "reader_process started (as thread)\n"); } sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); fp = fdopen ( scanner->reader_fds, "w"); if (!fp) { DBG (1, "reader_process: couldn't open pipe!\n"); return 1; } DBG (10, "reader_process: starting to READ data\n"); data_left = scan_bytes_per_line (scanner) * lines_per_scan (scanner); /*scanner->row_bufsize = sanei_scsi_max_request_size;*/ coolscan_trim_rowbufsize (scanner); /* trim bufsize */ DBG (10, "reader_process: reading %u bytes in blocks of %u bytes\n", data_left, scanner->row_bufsize); memset (&act, 0, sizeof (act)); act.sa_handler = sigterm_handler; sigaction (SIGTERM, &act, 0); /* wait_scanner(scanner); */ do { data_to_read = (data_left < scanner->row_bufsize) ? data_left : scanner->row_bufsize; data_to_write=data_to_read; status = coolscan_read_data_block (scanner ,R_datatype_imagedata,data_to_read); if (status == 0) { continue; } if (status == -1) { DBG (1, "reader_process: unable to get image data from scanner!\n"); fclose (fp); return (-1); } if (scanner->LS == 1) { /* mirror image for LS-1000 */ bpl = scan_bytes_per_line(scanner); linesPerBuf = data_to_read / bpl; for (line = 0, lineOffset = 0; line < linesPerBuf; line++, lineOffset += bpl ) { if (scanner->colormode == RGB) { for (j = 0; j < bpl/2 ; j += 3) { r_data=scanner->buffer[lineOffset + j]; g_data=scanner->buffer[lineOffset + j + 1]; b_data=scanner->buffer[lineOffset + j + 2]; scanner->buffer[lineOffset + j] = scanner->buffer[lineOffset + bpl -1 - j - 2 ]; scanner->buffer[lineOffset + j + 1] = scanner->buffer[lineOffset + bpl -1 - j - 1 ]; scanner->buffer[lineOffset + j + 2] = scanner->buffer[lineOffset + bpl -1 - j ]; scanner->buffer[lineOffset + bpl -1 - j - 2 ] = r_data; scanner->buffer[lineOffset + bpl -1 - j - 1] = g_data; scanner->buffer[lineOffset + bpl -1 - j] = b_data; } } else { for (j = 0; j < bpl/2; j++) { r_data=scanner->buffer[lineOffset + j]; scanner->buffer[lineOffset + j] = scanner->buffer[lineOffset + bpl - 1 - j]; scanner->buffer[lineOffset + bpl - 1 - j] = r_data; } } } } if(scanner->colormode==RGBI) { /* Correct Infrared Channel */ if(scanner->bits_per_color>8) { RGBIfix16(scanner, (unsigned short * ) scanner->buffer, (unsigned short * )scanner->obuffer, data_to_read/8,scanner->lutr, scanner->lutg,scanner->lutb,scanner->luti); } else { RGBIfix(scanner,scanner->buffer,scanner->obuffer, data_to_read/4,scanner->lutr, scanner->lutg,scanner->lutb,scanner->luti); } } else if((scanner->colormode==GREYSCALE)&&(scanner->LS>=2)) { /* Convert to Grey */ data_to_write/=3; rgb2g(scanner->buffer,scanner->obuffer,data_to_write); } else { /* or just copy */ memcpy (scanner->obuffer, scanner->buffer,data_to_read); } if((!scanner->low_byte_first)&&(scanner->bits_per_color>8)) { for(i=0;iobuffer[i]; scanner->obuffer[i]=scanner->obuffer[i+1]; i++; scanner->obuffer[i]=h; } } fwrite (scanner->obuffer, 1, data_to_write, fp); fflush (fp); data_left -= data_to_read; DBG (10, "reader_process: buffer of %d bytes read; %d bytes to go\n", data_to_read, data_left); } while (data_left); fclose (fp); DBG (10, "reader_process: finished reading data\n"); return 0; } static SANE_Status init_options (Coolscan_t * scanner) { int i; int bit_depths; DBG (10, "init_options\n"); memset (scanner->opt, 0, sizeof (scanner->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { scanner->opt[i].size = sizeof (SANE_Word); scanner->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; /* "Mode" group: */ scanner->opt[OPT_MODE_GROUP].title = "Scan Mode"; scanner->opt[OPT_MODE_GROUP].desc = ""; scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_MODE_GROUP].cap = 0; scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; scanner->opt[OPT_MODE].type = SANE_TYPE_STRING; if(scanner->LS<2) { scanner->opt[OPT_MODE].size = max_string_size (scan_mode_list_LS20); scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_MODE].constraint.string_list = scan_mode_list_LS20; } else { scanner->opt[OPT_MODE].size = max_string_size (scan_mode_list_LS30); scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_MODE].constraint.string_list = scan_mode_list_LS30; } /* source */ source_list[0] = "Slide"; source_list[1] = "Automatic Slide Feeder"; source_list[2] = NULL; if (!scanner->autofeeder) { scanner->opt[OPT_SOURCE].cap = SANE_CAP_INACTIVE; } scanner->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; scanner->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; scanner->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; scanner->opt[OPT_SOURCE].type = SANE_TYPE_STRING; scanner->opt[OPT_SOURCE].size = max_string_size (source_list); scanner->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_SOURCE].constraint.string_list = source_list; /* negative */ scanner->opt[OPT_TYPE].name = "type"; scanner->opt[OPT_TYPE].title = "Film type"; scanner->opt[OPT_TYPE].desc = "Select the film type (positive (slide) or negative)"; scanner->opt[OPT_TYPE].type = SANE_TYPE_STRING; scanner->opt[OPT_TYPE].size = max_string_size (type_list); scanner->opt[OPT_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_TYPE].constraint.string_list = type_list; scanner->opt[OPT_PRESCAN].name = "prescan"; scanner->opt[OPT_PRESCAN].title = "Prescan"; scanner->opt[OPT_PRESCAN].desc = "Perform a prescan during preview"; scanner->opt[OPT_PRESCAN].type = SANE_TYPE_BOOL; scanner->opt[OPT_PRESCAN].unit = SANE_UNIT_NONE; scanner->opt[OPT_PRESCAN_NOW].name = "prescan now"; scanner->opt[OPT_PRESCAN_NOW].title = "Prescan now"; scanner->opt[OPT_PRESCAN_NOW].desc = "Perform a prescan now"; scanner->opt[OPT_PRESCAN_NOW].type = SANE_TYPE_BUTTON; scanner->opt[OPT_PRESCAN_NOW].unit = SANE_UNIT_NONE; scanner->opt[OPT_PRESCAN_NOW].size = 0; scanner->opt[OPT_PRESCAN_NOW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; scanner->opt[OPT_PRESCAN_NOW].constraint_type = SANE_CONSTRAINT_NONE; scanner->opt[OPT_PRESCAN_NOW].constraint.string_list = 0; /* bit depth */ bit_depths=0; bit_depth_list[++bit_depths] = 8; if (scanner->LS==2) { bit_depth_list[++bit_depths] = 10; } if (scanner->LS==3) { bit_depth_list[++bit_depths] = 12; } bit_depth_list[0] = bit_depths; scanner->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; scanner->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT; scanner->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_BIT_DEPTH].constraint.word_list = bit_depth_list; /* resolution */ scanner->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; scanner->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; scanner->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_RESOLUTION].constraint.word_list = resolution_list; scanner->opt[OPT_PREVIEW_RESOLUTION].name = "preview-resolution"; scanner->opt[OPT_PREVIEW_RESOLUTION].title = "Preview resolution"; scanner->opt[OPT_PREVIEW_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; scanner->opt[OPT_PREVIEW_RESOLUTION].type = SANE_TYPE_INT; scanner->opt[OPT_PREVIEW_RESOLUTION].unit = SANE_UNIT_DPI; scanner->opt[OPT_PREVIEW_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_PREVIEW_RESOLUTION].constraint.word_list = resolution_list; /* "Geometry" group: */ scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; scanner->opt[OPT_GEOMETRY_GROUP].desc = ""; scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_X].constraint.range = &(scanner->x_range); /* top-left y */ scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_Y].constraint.range = &(scanner->y_range); /* bottom-right x */ scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_X].constraint.range = &(scanner->x_range); /* bottom-right y */ scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_Y].constraint.range = &(scanner->y_range); /* ------------------------------ */ /* "Enhancement" group: */ scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; scanner->opt[OPT_ENHANCEMENT_GROUP].desc = ""; scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ENHANCEMENT_GROUP].cap = 0; scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; scanner->opt[OPT_GAMMA_BIND].name = "gamma-bind"; scanner->opt[OPT_GAMMA_BIND].title = "Gamma bind"; scanner->opt[OPT_GAMMA_BIND].desc = "Use same gamma correction for all colours"; scanner->opt[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL; scanner->opt[OPT_GAMMA_BIND].unit = SANE_UNIT_NONE; scanner->opt[OPT_ANALOG_GAMMA].name = "analog_gamma"; scanner->opt[OPT_ANALOG_GAMMA].title = "Analog Gamma"; scanner->opt[OPT_ANALOG_GAMMA].desc = "Analog Gamma"; scanner->opt[OPT_ANALOG_GAMMA].type = SANE_TYPE_BOOL; scanner->opt[OPT_ANALOG_GAMMA].unit = SANE_UNIT_NONE; if (!scanner->analoggamma) { scanner->opt[OPT_ANALOG_GAMMA].cap = SANE_CAP_INACTIVE; } scanner->opt[OPT_AVERAGING].name = "averaging"; scanner->opt[OPT_AVERAGING].title = "Averaging"; scanner->opt[OPT_AVERAGING].desc = "Averaging"; scanner->opt[OPT_AVERAGING].type = SANE_TYPE_BOOL; scanner->opt[OPT_AVERAGING].unit = SANE_UNIT_NONE; scanner->opt[OPT_RGB_CONTROL].name = "rgb-control"; scanner->opt[OPT_RGB_CONTROL].title = "RGB control"; scanner->opt[OPT_RGB_CONTROL].desc = "toggles brightness/contrast control over individual colours"; scanner->opt[OPT_RGB_CONTROL].type = SANE_TYPE_BOOL; scanner->opt[OPT_RGB_CONTROL].unit = SANE_UNIT_NONE; if(scanner->LS>=2) { scanner->opt[OPT_RGB_CONTROL].cap |= SANE_CAP_INACTIVE; } /* brightness */ scanner->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; scanner->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; scanner->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BRIGHTNESS].constraint.range = &brightness_range; if(scanner->LS>=2) { scanner->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_R_BRIGHTNESS].name = "red-brightness"; scanner->opt[OPT_R_BRIGHTNESS].title = "Red brightness"; scanner->opt[OPT_R_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; scanner->opt[OPT_R_BRIGHTNESS].type = SANE_TYPE_INT; scanner->opt[OPT_R_BRIGHTNESS].unit = SANE_UNIT_NONE; scanner->opt[OPT_R_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_R_BRIGHTNESS].constraint.range = &brightness_range; scanner->opt[OPT_R_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_G_BRIGHTNESS].name = "green-brightness"; scanner->opt[OPT_G_BRIGHTNESS].title = "Green brightness"; scanner->opt[OPT_G_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; scanner->opt[OPT_G_BRIGHTNESS].type = SANE_TYPE_INT; scanner->opt[OPT_G_BRIGHTNESS].unit = SANE_UNIT_NONE; scanner->opt[OPT_G_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_G_BRIGHTNESS].constraint.range = &brightness_range; scanner->opt[OPT_G_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_B_BRIGHTNESS].name = "blue-brightness"; scanner->opt[OPT_B_BRIGHTNESS].title = "Blue brightness"; scanner->opt[OPT_B_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; scanner->opt[OPT_B_BRIGHTNESS].type = SANE_TYPE_INT; scanner->opt[OPT_B_BRIGHTNESS].unit = SANE_UNIT_NONE; scanner->opt[OPT_B_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_B_BRIGHTNESS].constraint.range = &brightness_range; scanner->opt[OPT_B_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; /* contrast */ scanner->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; scanner->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; scanner->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; scanner->opt[OPT_CONTRAST].type = SANE_TYPE_INT; scanner->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; scanner->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_CONTRAST].constraint.range = &contrast_range; if(scanner->LS>=2) { scanner->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_R_CONTRAST].name = "red-contrast"; scanner->opt[OPT_R_CONTRAST].title = "Red contrast"; scanner->opt[OPT_R_CONTRAST].desc = SANE_DESC_CONTRAST; scanner->opt[OPT_R_CONTRAST].type = SANE_TYPE_INT; scanner->opt[OPT_R_CONTRAST].unit = SANE_UNIT_NONE; scanner->opt[OPT_R_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_R_CONTRAST].constraint.range = &contrast_range; scanner->opt[OPT_R_CONTRAST].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_G_CONTRAST].name = "green-contrast"; scanner->opt[OPT_G_CONTRAST].title = "Green contrast"; scanner->opt[OPT_G_CONTRAST].desc = SANE_DESC_CONTRAST; scanner->opt[OPT_G_CONTRAST].type = SANE_TYPE_INT; scanner->opt[OPT_G_CONTRAST].unit = SANE_UNIT_NONE; scanner->opt[OPT_G_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_G_CONTRAST].constraint.range = &contrast_range; scanner->opt[OPT_G_CONTRAST].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_B_CONTRAST].name = "blue-contrast"; scanner->opt[OPT_B_CONTRAST].title = "Blue contrast"; scanner->opt[OPT_B_CONTRAST].desc = SANE_DESC_CONTRAST; scanner->opt[OPT_B_CONTRAST].type = SANE_TYPE_INT; scanner->opt[OPT_B_CONTRAST].unit = SANE_UNIT_NONE; scanner->opt[OPT_B_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_B_CONTRAST].constraint.range = &contrast_range; scanner->opt[OPT_B_CONTRAST].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_EXPOSURE].name = "exposure"; scanner->opt[OPT_EXPOSURE].title = "Exposure"; scanner->opt[OPT_EXPOSURE].desc = ""; scanner->opt[OPT_EXPOSURE].type = SANE_TYPE_INT; scanner->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_EXPOSURE].constraint.range = &exposure_range; scanner->opt[OPT_R_EXPOSURE].name = "red-exposure"; scanner->opt[OPT_R_EXPOSURE].title = "Red exposure"; scanner->opt[OPT_R_EXPOSURE].desc = ""; scanner->opt[OPT_R_EXPOSURE].type = SANE_TYPE_INT; scanner->opt[OPT_R_EXPOSURE].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_R_EXPOSURE].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_R_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_R_EXPOSURE].constraint.range = &exposure_range; scanner->opt[OPT_G_EXPOSURE].name = "green-exposure"; scanner->opt[OPT_G_EXPOSURE].title = "Green exposure"; scanner->opt[OPT_G_EXPOSURE].desc = ""; scanner->opt[OPT_G_EXPOSURE].type = SANE_TYPE_INT; scanner->opt[OPT_G_EXPOSURE].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_G_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_G_EXPOSURE].constraint.range = &exposure_range; scanner->opt[OPT_G_EXPOSURE].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_B_EXPOSURE].name = "blue-exposure"; scanner->opt[OPT_B_EXPOSURE].title = "Blue exposre"; scanner->opt[OPT_B_EXPOSURE].desc = ""; scanner->opt[OPT_B_EXPOSURE].type = SANE_TYPE_INT; scanner->opt[OPT_B_EXPOSURE].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_B_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_B_EXPOSURE].constraint.range = &exposure_range; scanner->opt[OPT_B_EXPOSURE].cap |= SANE_CAP_INACTIVE; if(scanner->LS>=2) { scanner->opt[OPT_R_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_G_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_B_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_R_SHIFT].name = "red-shift"; scanner->opt[OPT_R_SHIFT].title = "Red shift"; scanner->opt[OPT_R_SHIFT].desc = ""; scanner->opt[OPT_R_SHIFT].type = SANE_TYPE_INT; scanner->opt[OPT_R_SHIFT].unit = SANE_UNIT_NONE; scanner->opt[OPT_R_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_R_SHIFT].constraint.range = &shift_range; if(scanner->LS>=2) { scanner->opt[OPT_R_SHIFT].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_G_SHIFT].name = "green-shift"; scanner->opt[OPT_G_SHIFT].title = "Green shift"; scanner->opt[OPT_G_SHIFT].desc = ""; scanner->opt[OPT_G_SHIFT].type = SANE_TYPE_INT; scanner->opt[OPT_G_SHIFT].unit = SANE_UNIT_NONE; scanner->opt[OPT_G_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_G_SHIFT].constraint.range = &shift_range; if(scanner->LS>=2) { scanner->opt[OPT_G_SHIFT].cap |= SANE_CAP_INACTIVE; } scanner->opt[OPT_B_SHIFT].name = "blue-shift"; scanner->opt[OPT_B_SHIFT].title = "Blue shift"; scanner->opt[OPT_B_SHIFT].desc = ""; scanner->opt[OPT_B_SHIFT].type = SANE_TYPE_INT; scanner->opt[OPT_B_SHIFT].unit = SANE_UNIT_NONE; scanner->opt[OPT_B_SHIFT].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_B_SHIFT].constraint.range = &shift_range; if(scanner->LS>=2) { scanner->opt[OPT_B_SHIFT].cap |= SANE_CAP_INACTIVE; } /* R+G+B gamma vector */ scanner->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; if (scanner->LS == 1) { scanner->opt[OPT_GAMMA_VECTOR].cap = SANE_CAP_INACTIVE; } scanner->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; switch(scanner->LS) { case 0: scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_8; scanner->lutlength=2048; break; case 1: scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_9; scanner->lutlength=512; break; case 2: scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_10; scanner->lutlength=1024; break; case 3: scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &gamma_range_12; scanner->lutlength=4096; break; } scanner->opt[OPT_GAMMA_VECTOR].size = scanner->lutlength * sizeof (SANE_Word); scanner->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; /* red gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; switch(scanner->LS) { case 0: scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_8; scanner->lutlength=2048; break; case 1: scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_9; scanner->lutlength=512; break; case 2: scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_10; scanner->lutlength=1024; break; case 3: scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range_12; scanner->lutlength=4096; break; } scanner->opt[OPT_GAMMA_VECTOR_R].size = scanner->lutlength * sizeof (SANE_Word); scanner->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; /* green gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; switch(scanner->LS) { case 0: scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_8; scanner->lutlength=2048; break; case 1: scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_9; scanner->lutlength=512; break; case 2: scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_10; scanner->lutlength=1024; break; case 3: scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range_12; scanner->lutlength=4096; break; } scanner->opt[OPT_GAMMA_VECTOR_G].size = scanner->lutlength * sizeof (SANE_Word); scanner->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; /* blue gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; switch(scanner->LS) { case 0: scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_8; scanner->lutlength=2048; break; case 1: scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_9; scanner->lutlength=512; break; case 2: scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_10; scanner->lutlength=1024; break; case 3: scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range_12; scanner->lutlength=4096; break; } scanner->opt[OPT_GAMMA_VECTOR_B].size = scanner->lutlength * sizeof (SANE_Word); scanner->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; /* ------------------------------ */ /* "Advanced" group: */ scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced"; scanner->opt[OPT_ADVANCED_GROUP].desc = ""; scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* preview */ scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; /* Autofocus */ scanner->opt[OPT_AUTOFOCUS].name = "Autofocus"; scanner->opt[OPT_AUTOFOCUS].title ="Autofocus"; scanner->opt[OPT_AUTOFOCUS].desc = "When to do autofocussing"; scanner->opt[OPT_AUTOFOCUS].type = SANE_TYPE_STRING; scanner->opt[OPT_AUTOFOCUS].size = max_string_size (autofocus_mode_list); scanner->opt[OPT_AUTOFOCUS].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_AUTOFOCUS].constraint.string_list = autofocus_mode_list; scanner->opt[OPT_IRED_RED].name = "IRED cor. red"; scanner->opt[OPT_IRED_RED].title ="IRED cor. red"; scanner->opt[OPT_IRED_RED].desc = "Correction of infrared from red"; scanner->opt[OPT_IRED_RED].type = SANE_TYPE_INT; scanner->opt[OPT_IRED_RED].unit = SANE_UNIT_NONE; scanner->opt[OPT_IRED_RED].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_IRED_RED].constraint.range = &gamma_range_8; scanner->opt[OPT_IRED_RED].cap |= SANE_CAP_ADVANCED; if(scanner->LS<2) { scanner->opt[OPT_IRED_RED].cap |= SANE_CAP_INACTIVE; } /* scanner->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; */ return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; authorize = authorize; DBG_INIT (); sanei_thread_init (); DBG (10, "sane_init\n"); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (COOLSCAN_CONFIG_FILE); if (!fp) { attach_scanner ("/dev/scanner", 0); /* no config-file: /dev/scanner */ return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') continue; /* ignore line comments */ len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); /*attach_scanner (dev_name, 0);*/ } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { Coolscan_t *dev, *next; DBG (10, "sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free (dev->devicename); free (dev->buffer); free (dev->obuffer); free (dev); } if (devlist) free (devlist); } /* ----------------------------- SANE GET DEVICES -------------------------- */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Coolscan_t *dev; int i; local_only = local_only; DBG (10, "sane_get_devices\n"); if (devlist) free (devlist); devlist = calloc (num_devices + 1, sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Coolscan_t *dev; SANE_Status status; DBG (10, "sane_open\n"); if (devicename[0]) { /* search for devicename */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { dev = first_dev; /* empty devicname -> use first device */ } if (!dev) return SANE_STATUS_INVAL; dev->sfd = -1; dev->pipe = -1; dev->scanning = SANE_FALSE; init_options (dev); *handle = dev; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { DBG (10, "sane_close\n"); if (((Coolscan_t *) handle)->scanning) do_cancel (handle); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Coolscan_t *scanner = handle; DBG (10, "sane_get_option_descriptor %d\n", option); if ((unsigned) option >= NUM_OPTIONS) return 0; return &scanner->opt[option]; } /* static void worddump(char *comment, SANE_Word * p, int l) { int i; char line[128]; char *ptr; DBG (5, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 8) == 0) { if (ptr != line) { *ptr = '\0'; DBG (5, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3d:", i); ptr += 4; } sprintf (ptr, " %4.4d", *p); ptr += 5; } *ptr = '\0'; DBG (5, "%s\n", line); } */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Coolscan_t *scanner = handle; SANE_Status status; SANE_Word cap; if (info) *info = 0; if (scanner->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = scanner->opt[option].cap; if (action == SANE_ACTION_GET_VALUE) { DBG (10, "sane_control_option %d, get value\n", option); switch (option) { /* word options: */ case OPT_TL_X: *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tlx)); return SANE_STATUS_GOOD; case OPT_TL_Y: *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tly)); return SANE_STATUS_GOOD; case OPT_BR_X: *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->brx)); return SANE_STATUS_GOOD; case OPT_BR_Y: *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->bry)); return SANE_STATUS_GOOD; case OPT_PREVIEW: *(SANE_Word *) val = scanner->preview; return SANE_STATUS_GOOD; case OPT_AUTOFOCUS: switch(scanner->autofocus) { case AF_NEVER: strcpy (val,neverStr); break; case AF_PREVIEW:strcpy (val,previewStr); break; case AF_SCAN:if(scanner->LS>=2) strcpy (val,scanStr); break; case AF_PREANDSCAN:if(scanner->LS>=2) strcpy (val,preandscanStr); break; } return SANE_STATUS_GOOD; case OPT_NUM_OPTS: *(SANE_Word *) val = NUM_OPTIONS; return SANE_STATUS_GOOD; case OPT_RESOLUTION: *(SANE_Word *) val = resDivToVal (scanner->x_nres); return SANE_STATUS_GOOD; case OPT_PREVIEW_RESOLUTION: *(SANE_Word *) val = resDivToVal (scanner->x_p_nres); return SANE_STATUS_GOOD; case OPT_BIT_DEPTH: *(SANE_Word *) val = scanner->bits_per_color; return SANE_STATUS_GOOD; case OPT_CONTRAST: *(SANE_Word *) val = scanner->contrast - 128; return SANE_STATUS_GOOD; case OPT_R_CONTRAST: *(SANE_Word *) val = scanner->contrast_R - 128; return SANE_STATUS_GOOD; case OPT_G_CONTRAST: *(SANE_Word *) val = scanner->contrast_G - 128; return SANE_STATUS_GOOD; case OPT_B_CONTRAST: *(SANE_Word *) val = scanner->contrast_B - 128; return SANE_STATUS_GOOD; case OPT_BRIGHTNESS: *(SANE_Word *) val = scanner->brightness - 128; return SANE_STATUS_GOOD; case OPT_R_BRIGHTNESS: *(SANE_Word *) val = scanner->brightness_R - 128; return SANE_STATUS_GOOD; case OPT_G_BRIGHTNESS: *(SANE_Word *) val = scanner->brightness_G - 128; return SANE_STATUS_GOOD; case OPT_B_BRIGHTNESS: *(SANE_Word *) val = scanner->brightness_B - 128; return SANE_STATUS_GOOD; case OPT_EXPOSURE: *(SANE_Word *) val = scanner->exposure_R * 2; return SANE_STATUS_GOOD; case OPT_R_EXPOSURE: *(SANE_Word *) val = scanner->exposure_R * 2; return SANE_STATUS_GOOD; case OPT_G_EXPOSURE: *(SANE_Word *) val = scanner->exposure_G * 2; return SANE_STATUS_GOOD; case OPT_B_EXPOSURE: *(SANE_Word *) val = scanner->exposure_B * 2; return SANE_STATUS_GOOD; case OPT_R_SHIFT: *(SANE_Word *) val = scanner->shift_R - 128; return SANE_STATUS_GOOD; case OPT_G_SHIFT: *(SANE_Word *) val = scanner->shift_G - 128; return SANE_STATUS_GOOD; case OPT_B_SHIFT: *(SANE_Word *) val = scanner->shift_B - 128; return SANE_STATUS_GOOD; case OPT_IRED_RED: *(SANE_Word *) val = scanner->ired_red; return SANE_STATUS_GOOD; /* string options: */ case OPT_TYPE: strcpy (val, ((scanner->negative) ? negativeStr : positiveStr)); return SANE_STATUS_GOOD; case OPT_MODE: switch(scanner->colormode) { case RGB: strcpy (val,colorStr); break; case GREYSCALE:strcpy (val,grayStr); break; case RGBI:if(scanner->LS>=2) strcpy (val,rgbiStr); else strcpy (val,colorStr); break; case IRED:if(scanner->LS>=2) strcpy (val,iredStr); else strcpy (val,grayStr); break; } if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_PRESCAN: *(SANE_Word *) val = (scanner->prescan) ? SANE_TRUE : SANE_FALSE; return SANE_STATUS_GOOD; case OPT_PRESCAN_NOW: return SANE_STATUS_GOOD; case OPT_RGB_CONTROL: *(SANE_Word *) val = (scanner->rgb_control) ? SANE_TRUE : SANE_FALSE; return SANE_STATUS_GOOD; case OPT_GAMMA_BIND: *(SANE_Word *) val = (scanner->gamma_bind) ? SANE_TRUE : SANE_FALSE; return SANE_STATUS_GOOD; case OPT_ANALOG_GAMMA: *(SANE_Word *) val = (scanner->analog_gamma_r) ? SANE_TRUE : SANE_FALSE; return SANE_STATUS_GOOD; case OPT_AVERAGING: *(SANE_Word *) val = (scanner->averaging) ? SANE_TRUE : SANE_FALSE; return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR: memcpy (val, scanner->gamma, scanner->opt[option].size); return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: memcpy (val, scanner->gamma_r, scanner->opt[option].size); return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_G: memcpy (val, scanner->gamma_g, scanner->opt[option].size); return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_B: memcpy (val, scanner->gamma_b, scanner->opt[option].size); return SANE_STATUS_GOOD; case OPT_SOURCE: if (strcmp (val, "Automatic Slide Feeder") == 0) { /* Feed/Discharge/update filename/etc */ } else { /* Reset above */ } if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } } } else if (action == SANE_ACTION_SET_VALUE) { DBG (10, "sane_control_option %d, set value\n", option); if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (scanner->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { case OPT_GAMMA_BIND: scanner->gamma_bind = (*(SANE_Word *) val == SANE_TRUE); if (scanner->LS != 1) { if (scanner->gamma_bind) { scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_ANALOG_GAMMA: scanner->analog_gamma_r = scanner->analog_gamma_g = scanner->analog_gamma_b = (*(SANE_Word *) val == SANE_TRUE); return SANE_STATUS_GOOD; case OPT_AVERAGING: scanner->averaging = (*(SANE_Word *) val == SANE_TRUE); return SANE_STATUS_GOOD; case OPT_PRESCAN: scanner->prescan = (*(SANE_Word *) val == SANE_TRUE); return SANE_STATUS_GOOD; case OPT_PRESCAN_NOW: do_prescan_now(scanner); return SANE_STATUS_GOOD; case OPT_BIT_DEPTH: scanner->bits_per_color=(*(SANE_Word *)val); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_RGB_CONTROL: scanner->rgb_control = (*(SANE_Word *) val == SANE_TRUE); if (scanner->rgb_control) { scanner->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_R_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_G_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_B_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_R_CONTRAST].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_G_CONTRAST].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_B_CONTRAST].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_R_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_G_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_B_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; scanner->contrast_R = 128; scanner->contrast_G = 128; scanner->contrast_B = 128; scanner->brightness_R = 128; scanner->brightness_G = 128; scanner->brightness_B = 128; scanner->exposure_R = 50; scanner->exposure_G = 50; scanner->exposure_B = 50; } else { scanner->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; scanner->contrast = 128; scanner->brightness = 128; scanner->exposure_R = 50; scanner->exposure_G = 50; scanner->exposure_B = 50; scanner->opt[OPT_R_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_G_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_B_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_R_CONTRAST].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_G_CONTRAST].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_B_CONTRAST].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_R_EXPOSURE].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_G_EXPOSURE].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_B_EXPOSURE].cap |= SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_RESOLUTION: scanner->y_nres = scanner->x_nres = resValToDiv (*(SANE_Word *) val); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_PREVIEW_RESOLUTION: scanner->y_p_nres = scanner->x_p_nres = resValToDiv (*(SANE_Word *) val); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_TL_X: scanner->tlx = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_TL_Y: scanner->tly = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_BR_X: scanner->brx = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_BR_Y: scanner->bry = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_NUM_OPTS: return SANE_STATUS_GOOD; case OPT_PREVIEW: scanner->preview = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_AUTOFOCUS: if(strcmp(val,neverStr)==0) { scanner->autofocus=AF_NEVER; } if(strcmp(val,previewStr)==0) { scanner->autofocus=AF_PREVIEW; } if(strcmp(val,scanStr)==0) { scanner->autofocus=AF_SCAN; } if(strcmp(val,preandscanStr)==0) { scanner->autofocus=AF_PREANDSCAN;; } return SANE_STATUS_GOOD; case OPT_CONTRAST: scanner->contrast = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_R_CONTRAST: scanner->contrast_R = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_G_CONTRAST: scanner->contrast_G = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_B_CONTRAST: scanner->contrast_B = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_BRIGHTNESS: scanner->brightness = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_R_BRIGHTNESS: scanner->brightness_R = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_G_BRIGHTNESS: scanner->brightness_G = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_B_BRIGHTNESS: scanner->brightness_B = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_EXPOSURE: scanner->exposure_R = *(SANE_Word *) val / 2; scanner->exposure_G = *(SANE_Word *) val / 2; scanner->exposure_B = *(SANE_Word *) val / 2; return SANE_STATUS_GOOD; case OPT_R_EXPOSURE: scanner->exposure_R = *(SANE_Word *) val / 2; return SANE_STATUS_GOOD; case OPT_G_EXPOSURE: scanner->exposure_G = *(SANE_Word *) val / 2; return SANE_STATUS_GOOD; case OPT_B_EXPOSURE: scanner->exposure_B = *(SANE_Word *) val / 2; return SANE_STATUS_GOOD; case OPT_R_SHIFT: scanner->shift_R = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_G_SHIFT: scanner->shift_G = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_B_SHIFT: scanner->shift_B = *(SANE_Word *) val + 128; return SANE_STATUS_GOOD; case OPT_IRED_RED: scanner->ired_red= *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_SOURCE: scanner->asf = (strcmp (val, "Automatic...") == 0); return SANE_STATUS_GOOD; case OPT_TYPE: scanner->negative = (strcmp (val, negativeStr) == 0); if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_MODE: if(strcmp(val,colorStr)==0) { scanner->colormode=RGB; scanner->colormode_p=RGB; } if(strcmp(val,grayStr)==0) { scanner->colormode=GREYSCALE; scanner->colormode_p=GREYSCALE; } if(strcmp(val,rgbiStr)==0) { scanner->colormode=RGBI; scanner->colormode_p=RGB; } if(strcmp(val,iredStr)==0) { scanner->colormode=IRED; scanner->colormode_p=GREYSCALE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR: memcpy (scanner->gamma, val, scanner->opt[option].size); if(scanner->LS>2) Calc_fix_LUT(scanner); return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: memcpy (scanner->gamma_r, val, scanner->opt[option].size); if(scanner->LS>2) Calc_fix_LUT(scanner); return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_G: memcpy (scanner->gamma_g, val, scanner->opt[option].size); if(scanner->LS>2) Calc_fix_LUT(scanner); return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_B: memcpy (scanner->gamma_b, val, scanner->opt[option].size); if(scanner->LS>2) Calc_fix_LUT(scanner); return SANE_STATUS_GOOD; } /* switch */ } /* else */ return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Coolscan_t *scanner = handle; DBG (10, "sane_get_parameters"); switch(scanner->colormode) { case RGB: params->format = SANE_FRAME_RGB; break; #ifdef HAS_IRED case RGBI: params->format = SANE_FRAME_RGBA; break; #endif /* HAS_RGBI */ case GREYSCALE: params->format = SANE_FRAME_GRAY; break; } params->depth = scanner->bits_per_color>8?16:8; params->pixels_per_line = pixels_per_line (scanner); params->lines = lines_per_scan (scanner); params->bytes_per_line = write_bytes_per_line (scanner); params->last_frame = 1; return SANE_STATUS_GOOD; } static int swap_res (Coolscan_t * s) { if (s->preview) { /* swap preview/scan resolutions */ int xres, yres, cmode; xres = s->x_nres; yres = s->y_nres; s->x_nres = s->x_p_nres; s->y_nres = s->y_p_nres; s->x_p_nres = xres; s->y_p_nres = yres; cmode=s->colormode; s->colormode=s->colormode_p; s->colormode_p=cmode; } return 0; } SANE_Status sane_start (SANE_Handle handle) { Coolscan_t *scanner = handle; int fds[2]; DBG (10, "sane_start\n"); if (scanner->scanning == SANE_TRUE) return SANE_STATUS_DEVICE_BUSY; if (scanner->sfd < 0) { /* first call */ if (sanei_scsi_open (scanner->sane.name, &(scanner->sfd), sense_handler, 0) != SANE_STATUS_GOOD) { DBG (1, "sane_start: open of %s failed:\n", scanner->sane.name); return SANE_STATUS_INVAL; } } scanner->scanning = SANE_TRUE; if (coolscan_check_values (scanner) != 0) { /* Verify values */ DBG (1, "ERROR: invalid scan-values\n"); scanner->scanning = SANE_FALSE; coolscan_give_scanner (scanner); sanei_scsi_close (scanner->sfd); scanner->sfd = -1; return SANE_STATUS_INVAL; } if (coolscan_grab_scanner (scanner)) { sanei_scsi_close (scanner->sfd); scanner->sfd = -1; DBG (5, "WARNING: unable to reserve scanner: device busy\n"); scanner->scanning = SANE_FALSE; return SANE_STATUS_DEVICE_BUSY; } /* hoho, step 2c, -perm */ coolscan_object_feed (scanner); swap_res (scanner); if (!scanner->preview) { if(scanner->autofocus & 0x02) { coolscan_autofocus (scanner); } } else { if(scanner->autofocus & 0x01) { coolscan_autofocus (scanner); } if (scanner->prescan) { prescan (scanner); if(scanner->LS<2) { get_internal_info(scanner); } coolscan_get_window_param (scanner,1); } } /*read_LUT(scanner); */ if(scanner->LS<2) { send_LUT (scanner); coolscan_set_window_param (scanner, 0); coolscan_get_window_param (scanner,0); coolscan_start_scan (scanner); } else { coolscan_set_window_param (scanner, 0); send_LUT (scanner); Calc_fix_LUT(scanner); coolscan_start_scan (scanner); wait_scanner (scanner); coolscan_get_window_param (scanner,0); } DBG (10, "bytes per line = %d\n", scan_bytes_per_line (scanner)); DBG (10, "pixels_per_line = %d\n", pixels_per_line (scanner)); DBG (10, "lines = %d\n", lines_per_scan (scanner)); DBG (10, "negative = %d\n", scanner->negative); DBG (10, "brightness (halftone) = %d\n", scanner->brightness); DBG (10, "contrast (halftone) = %d\n", scanner->contrast); DBG (10, "fast preview function = %d\n", scanner->preview); /* create a pipe, fds[0]=read-fd, fds[1]=write-fd */ if (pipe (fds) < 0) { DBG (1, "ERROR: could not create pipe\n"); swap_res (scanner); scanner->scanning = SANE_FALSE; coolscan_give_scanner (scanner); sanei_scsi_close (scanner->sfd); scanner->sfd = -1; return SANE_STATUS_IO_ERROR; } scanner->pipe = fds[0]; scanner->reader_fds = fds[1]; scanner->reader_pid = sanei_thread_begin( reader_process, (void*)scanner ); if (!sanei_thread_is_valid (scanner->reader_pid)) { DBG (1, "sane_start: sanei_thread_begin failed (%s)\n", strerror (errno)); return SANE_STATUS_NO_MEM; } if (sanei_thread_is_forked ()) { close (scanner->reader_fds); scanner->reader_fds = -1; } return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Coolscan_t *scanner = handle; ssize_t nread; *len = 0; nread = read (scanner->pipe, buf, max_len); DBG (10, "sane_read: read %ld bytes\n", (long) nread); if (!(scanner->scanning)) { return do_cancel (scanner); } if (nread < 0) { if (errno == EAGAIN) { return SANE_STATUS_GOOD; } else { do_cancel (scanner); return SANE_STATUS_IO_ERROR; } } *len = nread; if (nread == 0) return do_eof (scanner); /* close pipe */ return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Coolscan_t *s = handle; if (sanei_thread_is_valid (s->reader_pid)) { sanei_thread_kill ( s->reader_pid ); sanei_thread_waitpid( s->reader_pid, NULL ); s->reader_pid = -1; } swap_res (s); s->scanning = SANE_FALSE; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Coolscan_t *scanner = handle; DBG (10, "sane_set_io_mode: non_blocking=%d\n", non_blocking); if (!scanner->scanning) return SANE_STATUS_INVAL; if (fcntl (scanner->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Coolscan_t *scanner = handle; DBG (10, "sane_get_select_fd\n"); if (!scanner->scanning) { return SANE_STATUS_INVAL; } *fd = scanner->pipe; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/as6e.h0000664000175000017500000000630712112021330013607 00000000000000/* sane - Scanner Access Now Easy. Artec AS6E backend. Copyright (C) 2000 Eugene S. Weiss This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a backend for the Artec AS6E by making a bridge to the as6edriver program. The as6edriver program can be found at http://as6edriver.sourceforge.net . */ #ifndef as6e_h #define as6e_h #include #include #include "../include/sane/sane.h" typedef enum { OPT_NUM_OPTS = 0, OPT_MODE, OPT_RESOLUTION, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_BRIGHTNESS, OPT_CONTRAST, /* must come last */ NUM_OPTIONS } AS6E_Option; typedef struct { int color; int resolution; int startpos; int stoppos; int startline; int stopline; int ctloutpipe; int ctlinpipe; int datapipe; } AS6E_Params; typedef struct AS6E_Device { struct AS6E_Device *next; SANE_Device sane; } AS6E_Device; typedef struct AS6E_Scan { struct AS6E_Scan *next; SANE_Option_Descriptor options_list[NUM_OPTIONS]; Option_Value value[NUM_OPTIONS]; SANE_Bool scanning; SANE_Bool cancelled; SANE_Parameters sane_params; AS6E_Params as6e_params; pid_t child_pid; size_t bytes_to_read; SANE_Byte *scan_buffer; SANE_Byte *line_buffer; SANE_Word scan_buffer_count; SANE_Word image_counter; } AS6E_Scan; #ifndef PATH_MAX #define PATH_MAX 1024 #endif #define AS6E_CONFIG_FILE "as6e.conf" #define READPIPE 0 #define WRITEPIPE 1 #define SCAN_BUF_SIZE 32768 #endif /* as6e_h */ sane-backends-1.0.27/backend/pixma_mp730.c0000664000175000017500000005322412776312542015040 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2007-2008 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include /* localtime(C90) */ #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" #ifdef __GNUC__ # define UNUSED(v) (void) v #else # define UNUSED(v) #endif #define IMAGE_BLOCK_SIZE (0xc000) #define CMDBUF_SIZE 512 #define MP10_PID 0x261f #define MP730_PID 0x262f #define MP700_PID 0x2630 #define MP5_PID 0x2635 /* untested */ #define MP360_PID 0x263c #define MP370_PID 0x263d #define MP390_PID 0x263e #define MP375R_PID 0x263f /* untested */ #define MP740_PID 0x264c /* Untested */ #define MP710_PID 0x264d #define MF5730_PID 0x265d /* Untested */ #define MF5750_PID 0x265e /* Untested */ #define MF5770_PID 0x265f #define MF3110_PID 0x2660 #define IR1020_PID 0x26e6 enum mp730_state_t { state_idle, state_warmup, state_scanning, state_transfering, state_finished }; enum mp730_cmd_t { cmd_start_session = 0xdb20, cmd_select_source = 0xdd20, cmd_gamma = 0xee20, cmd_scan_param = 0xde20, cmd_status = 0xf320, cmd_abort_session = 0xef20, cmd_time = 0xeb80, cmd_read_image = 0xd420, cmd_error_info = 0xff20, cmd_activate = 0xcf60, cmd_calibrate = 0xe920 }; typedef struct mp730_t { enum mp730_state_t state; pixma_cmdbuf_t cb; unsigned raw_width; uint8_t current_status[12]; uint8_t *buf, *imgbuf, *lbuf; unsigned imgbuf_len; unsigned last_block:1; } mp730_t; static void mp730_finish_scan (pixma_t * s); static int has_paper (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; return (mp->current_status[1] == 0); } static void drain_bulk_in (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; while (pixma_read (s->io, mp->imgbuf, IMAGE_BLOCK_SIZE) >= 0); } static int abort_session (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_abort_session); } static int query_status (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_status, 0, 12); error = pixma_exec (s, &mp->cb); if (error >= 0) { memcpy (mp->current_status, data, 12); PDBG (pixma_dbg (3, "Current status: paper=%u cal=%u lamp=%u\n", data[1], data[8], data[7])); } return error; } static int activate (pixma_t * s, uint8_t x) { mp730_t *mp = (mp730_t *) s->subdriver; uint8_t *data = pixma_newcmd (&mp->cb, cmd_activate, 10, 0); data[0] = 1; data[3] = x; return pixma_exec (s, &mp->cb); } static int start_session (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_start_session); } static int select_source (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; uint8_t *data = pixma_newcmd (&mp->cb, cmd_select_source, 10, 0); switch (s->param->source) { case PIXMA_SOURCE_ADF: data[0] = 2; break; case PIXMA_SOURCE_ADFDUP: data[0] = 2; data[5] = 3; break; default: data[0] = 1; break; } return pixma_exec (s, &mp->cb); } static int send_scan_param (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; uint8_t *data; data = pixma_newcmd (&mp->cb, cmd_scan_param, 0x2e, 0); pixma_set_be16 (s->param->xdpi | 0x1000, data + 0x04); pixma_set_be16 (s->param->ydpi | 0x1000, data + 0x06); pixma_set_be32 (s->param->x, data + 0x08); pixma_set_be32 (s->param->y, data + 0x0c); pixma_set_be32 (mp->raw_width, data + 0x10); pixma_set_be32 (s->param->h, data + 0x14); if (s->param->channels == 1) { if (s->param->depth == 1) data[0x18] = 0x01; else data[0x18] = 0x04; } else data[0x18] = 0x08; data[0x19] = s->param->channels * s->param->depth; /* bits per pixel, for lineart should be 0x01 */ data[0x1e] = (s->param->depth == 1) ? 0x80 : 0x00; /* modify for lineart: 0x80 NEW */ data[0x1f] = (s->param->depth == 1) ? 0x80 : 0x7f; /* modify for lineart: 0x80 */ data[0x20] = (s->param->depth == 1) ? 0x01 : 0xff; /* modify for lineart: 0x01 */ data[0x23] = 0x81; return pixma_exec (s, &mp->cb); } static int calibrate (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_calibrate); } static int read_image_block (pixma_t * s, uint8_t * header, uint8_t * data) { static const uint8_t cmd[10] = /* 0xd420 cmd */ { 0xd4, 0x20, 0, 0, 0, 0, 0, IMAGE_BLOCK_SIZE / 256, 4, 0 }; mp730_t *mp = (mp730_t *) s->subdriver; const int hlen = 2 + 4; int error, datalen; mp->state = state_transfering; mp->cb.reslen = pixma_cmd_transaction (s, cmd, sizeof (cmd), mp->cb.buf, 512); datalen = mp->cb.reslen; if (datalen < 0) return datalen; memcpy (header, mp->cb.buf, hlen); if (datalen >= hlen) { datalen -= hlen; memcpy (data, mp->cb.buf + hlen, datalen); data += datalen; if (mp->cb.reslen == 512) { error = pixma_read (s->io, data, IMAGE_BLOCK_SIZE - 512 + hlen); if (error < 0) return error; datalen += error; } } mp->state = state_scanning; mp->cb.expected_reslen = 0; error = pixma_check_result (&mp->cb); if (error < 0) return error; if (mp->cb.reslen < hlen) return PIXMA_EPROTO; return datalen; } static int send_time (pixma_t * s) { /* Why does a scanner need a time? */ time_t now; struct tm *t; uint8_t *data; mp730_t *mp = (mp730_t *) s->subdriver; data = pixma_newcmd (&mp->cb, cmd_time, 20, 0); pixma_get_time (&now, NULL); t = localtime (&now); snprintf ((char *) data, 16, "%02d/%02d/%02d %02d:%02d", t->tm_year % 100, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min); PDBG (pixma_dbg (3, "Sending time: '%s'\n", (char *) data)); return pixma_exec (s, &mp->cb); } static int handle_interrupt (pixma_t * s, int timeout) { uint8_t buf[16]; int len; len = pixma_wait_interrupt (s->io, buf, sizeof (buf), timeout); if (len == PIXMA_ETIMEDOUT) return 0; if (len < 0) return len; switch (s->cfg->pid) { case MP360_PID: case MP370_PID: case MP375R_PID: case MP390_PID: case MF5730_PID: case MF5750_PID: case MF5770_PID: case MF3110_PID: case IR1020_PID: if (len != 16) { PDBG (pixma_dbg (1, "WARNING:unexpected interrupt packet length %d\n", len)); return PIXMA_EPROTO; } if (buf[12] & 0x40) query_status (s); if (buf[10] & 0x40) send_time (s); /* FIXME: following is unverified! */ if (buf[15] & 1) s->events = PIXMA_EV_BUTTON2; /* b/w scan */ if (buf[15] & 2) s->events = PIXMA_EV_BUTTON1; /* color scan */ break; case MP5_PID: case MP10_PID: case MP700_PID: case MP730_PID: case MP710_PID: case MP740_PID: if (len != 8) { PDBG (pixma_dbg (1, "WARNING:unexpected interrupt packet length %d\n", len)); return PIXMA_EPROTO; } if (buf[7] & 0x10) s->events = PIXMA_EV_BUTTON1; if (buf[5] & 8) send_time (s); break; default: PDBG (pixma_dbg (1, "WARNING:unknown interrupt, please report!\n")); PDBG (pixma_hexdump (1, buf, len)); } return 1; } static int has_ccd_sensor (pixma_t * s) { return (s->cfg->pid == MP360_PID || s->cfg->pid == MP370_PID || s->cfg->pid == MP375R_PID || s->cfg->pid == MP390_PID || s->cfg->pid == MF5730_PID || s->cfg->pid == MF5750_PID || s->cfg->pid == MF5770_PID); } static int read_error_info (pixma_t * s, void *buf, unsigned size) { unsigned len = 16; mp730_t *mp = (mp730_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_error_info, 0, len); error = pixma_exec (s, &mp->cb); if (error < 0) return error; if (buf && len < size) { size = len; /* NOTE: I've absolutely no idea what the returned data mean. */ memcpy (buf, data, size); error = len; } return error; } static int step1 (pixma_t * s) { int error; error = query_status (s); if (error < 0) return error; if ((s->param->source == PIXMA_SOURCE_ADF || s->param->source == PIXMA_SOURCE_ADFDUP) && !has_paper (s)) return PIXMA_ENO_PAPER; if (has_ccd_sensor (s)) { switch (s->cfg->pid) { case MF5730_PID: case MF5750_PID: case MF5770_PID: /* MF57x0: Wait 10 sec before starting for 1st page only */ if (s->param->adf_pageid == 0) { int tmo = 10; /* like Windows driver, 10 sec CCD calibration ? */ while (--tmo >= 0) { error = handle_interrupt (s, 1000); \ if (s->cancel) \ return PIXMA_ECANCELED; \ if (error != PIXMA_ECANCELED && error < 0) \ return error; PDBG (pixma_dbg (2, "CCD Calibration ends in %d sec.\n", tmo)); } } break; default: break; } activate (s, 0); error = calibrate (s); switch (s->cfg->pid) { case MF5730_PID: case MF5750_PID: case MF5770_PID: /* MF57x0: calibration returns PIXMA_STATUS_FAILED */ if (error == PIXMA_ECANCELED) error = read_error_info (s, NULL, 0); break; default: break; } // ignore result from calibrate() // don't interrupt @ PIXMA_STATUS_BUSY error = 0; } if (error >= 0) error = activate (s, 0); if (error >= 0) error = activate (s, 4); return error; } static void pack_rgb (const uint8_t * src, unsigned nlines, unsigned w, uint8_t * dst) { unsigned w2, stride; w2 = 2 * w; stride = 3 * w; for (; nlines != 0; nlines--) { unsigned x; for (x = 0; x != w; x++) { *dst++ = src[x + 0]; *dst++ = src[x + w]; *dst++ = src[x + w2]; } src += stride; } } static int mp730_open (pixma_t * s) { mp730_t *mp; uint8_t *buf; mp = (mp730_t *) calloc (1, sizeof (*mp)); if (!mp) return PIXMA_ENOMEM; buf = (uint8_t *) malloc (CMDBUF_SIZE); if (!buf) { free (mp); return PIXMA_ENOMEM; } s->subdriver = mp; mp->state = state_idle; mp->cb.buf = buf; mp->cb.size = CMDBUF_SIZE; mp->cb.res_header_len = 2; mp->cb.cmd_header_len = 10; mp->cb.cmd_len_field_ofs = 7; PDBG (pixma_dbg (3, "Trying to clear the interrupt buffer...\n")); if (handle_interrupt (s, 200) == 0) { PDBG (pixma_dbg (3, " no packets in buffer\n")); } return 0; } static void mp730_close (pixma_t * s) { mp730_t *mp = (mp730_t *) s->subdriver; mp730_finish_scan (s); free (mp->cb.buf); free (mp->buf); free (mp); s->subdriver = NULL; } static unsigned calc_raw_width (pixma_t * s, const pixma_scan_param_t * sp) { unsigned raw_width; /* FIXME: Does MP730 need the alignment? */ /* TODO test: MP710/740 */ if (sp->channels == 1) { if (sp->depth == 8) /* grayscale */ { if (s->cfg->pid == MP5_PID || s->cfg->pid == MP10_PID || s->cfg->pid == MP700_PID || s->cfg->pid == MP730_PID || s->cfg->pid == MP360_PID || s->cfg->pid == MP370_PID || s->cfg->pid == MP375R_PID || s->cfg->pid == MP390_PID || s->cfg->pid == IR1020_PID) raw_width = ALIGN_SUP (sp->w, 4); else raw_width = ALIGN_SUP (sp->w, 12); } else /* depth = 1 : LINEART */ raw_width = ALIGN_SUP (sp->w, 16); } else raw_width = ALIGN_SUP (sp->w, 4); return raw_width; } static int mp730_check_param (pixma_t * s, pixma_scan_param_t * sp) { uint8_t k = 1; /* check if channels is 3, or if depth is 1 then channels also 1 else set depth to 8 */ if ((sp->channels==3) || !(sp->channels==1 && sp->depth==1)) { sp->depth=8; } /* for MP5, MP10, MP360/370, MP700/730 in grayscale & lineart modes, max scan res is 600 dpi */ if (s->cfg->pid == MP5_PID || s->cfg->pid == MP10_PID || s->cfg->pid == MP700_PID || s->cfg->pid == MP730_PID || s->cfg->pid == MP360_PID || s->cfg->pid == MP370_PID || s->cfg->pid == MP375R_PID || s->cfg->pid == MP390_PID) { if (sp->channels == 1) k = sp->xdpi / MIN (sp->xdpi, 600); } sp->x /= k; sp->y /= k; sp->h /= k; sp->xdpi /= k; sp->ydpi = sp->xdpi; sp->w = calc_raw_width (s, sp); sp->w /= k; sp->line_size = (calc_raw_width (s, sp) * sp->channels * sp->depth) / 8; return 0; } static int mp730_scan (pixma_t * s) { int error, n; mp730_t *mp = (mp730_t *) s->subdriver; uint8_t *buf; if (mp->state != state_idle) return PIXMA_EBUSY; /* clear interrupt packets buffer */ while (handle_interrupt (s, 0) > 0) { } mp->raw_width = calc_raw_width (s, s->param); PDBG (pixma_dbg (3, "raw_width = %u\n", mp->raw_width)); n = IMAGE_BLOCK_SIZE / s->param->line_size + 1; buf = (uint8_t *) malloc ((n + 1) * s->param->line_size + IMAGE_BLOCK_SIZE); if (!buf) return PIXMA_ENOMEM; mp->buf = buf; mp->lbuf = buf; mp->imgbuf = buf + n * s->param->line_size; mp->imgbuf_len = 0; error = step1 (s); if (error >= 0) error = start_session (s); if (error >= 0) mp->state = state_scanning; if (error >= 0) error = select_source (s); if (error >= 0) error = send_scan_param (s); if (error < 0) { mp730_finish_scan (s); return error; } mp->last_block = 0; return 0; } static int mp730_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { int error, n; mp730_t *mp = (mp730_t *) s->subdriver; unsigned block_size, bytes_received; uint8_t header[16]; do { do { if (s->cancel) return PIXMA_ECANCELED; if (mp->last_block) /* end of image */ return 0; error = read_image_block (s, header, mp->imgbuf + mp->imgbuf_len); if (error < 0) return error; bytes_received = error; block_size = pixma_get_be16 (header + 4); mp->last_block = ((header[2] & 0x28) == 0x28); if (mp->last_block) { /* end of image */ mp->state = state_finished; } if ((header[2] & ~0x38) != 0) { PDBG (pixma_dbg (1, "WARNING: Unexpected result header\n")); PDBG (pixma_hexdump (1, header, 16)); } PASSERT (bytes_received == block_size); if (block_size == 0) { /* no image data at this moment. */ /*pixma_sleep(100000); *//* FIXME: too short, too long? */ handle_interrupt (s, 100); } } while (block_size == 0); /* TODO: simplify! */ mp->imgbuf_len += bytes_received; n = mp->imgbuf_len / s->param->line_size; /* n = number of full lines (rows) we have in the buffer. */ if (n != 0) { if (s->param->channels != 1 && s->cfg->pid != MF5730_PID && s->cfg->pid != MF5750_PID && s->cfg->pid != MF5770_PID && s->cfg->pid != MF3110_PID && s->cfg->pid != IR1020_PID) { /* color, and not an MF57x0 nor MF3110 */ pack_rgb (mp->imgbuf, n, mp->raw_width, mp->lbuf); } else /* grayscale/lineart or MF57x0 or MF3110 */ memcpy (mp->lbuf, mp->imgbuf, n * s->param->line_size); block_size = n * s->param->line_size; mp->imgbuf_len -= block_size; memcpy (mp->imgbuf, mp->imgbuf + block_size, mp->imgbuf_len); } } while (n == 0); ib->rptr = mp->lbuf; ib->rend = mp->lbuf + block_size; return ib->rend - ib->rptr; } static void mp730_finish_scan (pixma_t * s) { int error, aborted = 0; mp730_t *mp = (mp730_t *) s->subdriver; switch (mp->state) { case state_transfering: drain_bulk_in (s); /* fall through */ case state_scanning: case state_warmup: aborted = 1; error = abort_session (s); if (error < 0) PDBG (pixma_dbg (1, "WARNING:abort_session() failed %s\n", pixma_strerror (error))); /* fall through */ case state_finished: query_status (s); query_status (s); activate (s, 0); // MF57x0 devices don't require abort_session() after the last page if (!aborted && (s->param->source == PIXMA_SOURCE_ADF || s->param->source == PIXMA_SOURCE_ADFDUP) && has_paper (s) && (s->cfg->pid == MF5730_PID || s->cfg->pid == MF5750_PID || s->cfg->pid == MF5770_PID || s->cfg->pid == IR1020_PID)) { error = abort_session (s); if (error < 0) PDBG (pixma_dbg (1, "WARNING:abort_session() failed %s\n", pixma_strerror (error))); } mp->buf = mp->lbuf = mp->imgbuf = NULL; mp->state = state_idle; /* fall through */ case state_idle: break; } } static void mp730_wait_event (pixma_t * s, int timeout) { /* FIXME: timeout is not correct. See usbGetCompleteUrbNoIntr() for * instance. */ while (s->events == 0 && handle_interrupt (s, timeout) > 0) { } } static int mp730_get_status (pixma_t * s, pixma_device_status_t * status) { int error; error = query_status (s); if (error < 0) return error; status->hardware = PIXMA_HARDWARE_OK; status->adf = (has_paper (s)) ? PIXMA_ADF_OK : PIXMA_ADF_NO_PAPER; return 0; } static const pixma_scan_ops_t pixma_mp730_ops = { mp730_open, mp730_close, mp730_scan, mp730_fill_buffer, mp730_finish_scan, mp730_wait_event, mp730_check_param, mp730_get_status }; /* TODO: implement adftpu_min_dpi & adftpu_max_dpi for grayscale & lineart */ #define DEVICE(name, model, pid, dpi, w, h, cap) { \ name, /* name */ \ model, /* model */ \ 0x04a9, pid, /* vid pid */ \ 1, /* iface */ \ &pixma_mp730_ops, /* ops */ \ dpi, dpi, /* xdpi, ydpi */ \ 0, 0, /* adftpu_min_dpi & adftpu_max_dpi not used in this subdriver */ \ 0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \ w, h, /* width, height */ \ PIXMA_CAP_GRAY|PIXMA_CAP_EVENTS|cap \ } const pixma_config_t pixma_mp730_devices[] = { /* TODO: check area limits */ DEVICE ("PIXUS MP5/SmartBase MPC190/imageCLASS MPC190","MP5", MP5_PID, 600, 636, 868, PIXMA_CAP_LINEART),/* color scan can do 600x1200 */ DEVICE ("PIXUS MP10/SmartBase MPC200/imageCLASS MPC200","MP10", MP10_PID, 600, 636, 868, PIXMA_CAP_LINEART),/* color scan can do 600x1200 */ DEVICE ("PIXMA MP360", "MP360", MP360_PID, 1200, 636, 868, PIXMA_CAP_LINEART), DEVICE ("PIXMA MP370", "MP370", MP370_PID, 1200, 636, 868, PIXMA_CAP_LINEART), DEVICE ("PIXMA MP375R", "MP375R", MP375R_PID, 1200, 636, 868, PIXMA_CAP_LINEART), DEVICE ("PIXMA MP390", "MP390", MP390_PID, 1200, 636, 868, PIXMA_CAP_LINEART), DEVICE ("PIXMA MP700", "MP700", MP700_PID, 1200, 638, 877 /*1035 */ , PIXMA_CAP_LINEART), DEVICE ("PIXMA MP710", "MP710", MP710_PID, 1200, 637, 868, PIXMA_CAP_LINEART), DEVICE ("PIXMA MP730", "MP730", MP730_PID, 1200, 637, 868, PIXMA_CAP_ADF | PIXMA_CAP_LINEART), DEVICE ("PIXMA MP740", "MP740", MP740_PID, 1200, 637, 868, PIXMA_CAP_ADF | PIXMA_CAP_LINEART), DEVICE ("Canon imageCLASS MF5730", "MF5730", MF5730_PID, 1200, 636, 868, PIXMA_CAP_ADF), DEVICE ("Canon imageCLASS MF5750", "MF5750", MF5750_PID, 1200, 636, 868, PIXMA_CAP_ADF), DEVICE ("Canon imageCLASS MF5770", "MF5770", MF5770_PID, 1200, 636, 868, PIXMA_CAP_ADF), DEVICE ("Canon imageCLASS MF3110", "MF3110", MF3110_PID, 600, 636, 868, 0), DEVICE ("Canon iR 1020/1024/1025", "iR1020", IR1020_PID, 600, 636, 868, PIXMA_CAP_ADFDUP), DEVICE (NULL, NULL, 0, 0, 0, 0, 0) }; sane-backends-1.0.27/backend/p5.conf.in0000664000175000017500000000055512112021330014377 00000000000000# configuration file for the p5 backend. # configuration option to override detected model name #option modelname "Prima PagePartner" # when the parser find this line, it detects it is not an option, # then it calls the attach function with this value. # Currently only user mode parallel port support is possible: # auto, /dev/paraport* (ppdev device name) auto sane-backends-1.0.27/backend/canon-sane.c0000664000175000017500000017124712775312260015020 00000000000000SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { char devnam[PATH_MAX] = "/dev/scanner"; FILE *fp; int i, j; SANE_Byte primary, secondary, inmask, priMask, secMask; DBG_INIT (); DBG (1, ">> sane_init\n"); /****** for lineart mode of FB1200S ******/ for (i = 0; i < 256; i++) { primary = secondary = 0; inmask = 0x80; priMask = 0x40; secMask = 0x80; for (j = 0; j < 4; j++) { if (i & inmask) { primary |= priMask; secondary |= secMask; } priMask = priMask >> 2; secMask = secMask >> 2; inmask = inmask >> 1; } primaryHigh[i] = primary; secondaryHigh[i] = secondary; primary = secondary = 0; priMask = 0x40; secMask = 0x80; for (j = 0; j < 4; j++) { if (i & inmask) { primary |= priMask; secondary |= secMask; } priMask = priMask >> 2; secMask = secMask >> 2; inmask = inmask >> 1; } primaryLow[i] = primary; secondaryLow[i] = secondary; } /******************************************/ #if defined PACKAGE && defined VERSION DBG (2, "sane_init: " PACKAGE " " VERSION "\n"); #endif if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (CANON_CONFIG_FILE); if (fp) { char line[PATH_MAX]; size_t len; /* read config file */ /* while (fgets (line, sizeof (line), fp)) */ while (sanei_config_read (line, sizeof (line), fp)) { if (line[0] == '#') /* ignore line comments */ continue; len = strlen (line); /*if (line[len - 1] == '\n') line[--len] = '\0'; */ if (!len) continue; /* ignore empty lines */ strcpy (devnam, line); } fclose (fp); } sanei_config_attach_matching_devices (devnam, attach_one); DBG (1, "<< sane_init\n"); return SANE_STATUS_GOOD; } /**************************************************************************/ void sane_exit (void) { CANON_Device *dev, *next; DBG (1, ">> sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free ((void *) dev); } DBG (1, "<< sane_exit\n"); } /**************************************************************************/ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { static const SANE_Device **devlist = 0; CANON_Device *dev; int i; DBG (1, ">> sane_get_devices\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return (SANE_STATUS_NO_MEM); i = 0; for (dev = first_dev; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (1, "<< sane_get_devices\n"); return SANE_STATUS_GOOD; } /**************************************************************************/ SANE_Status sane_open (SANE_String_Const devnam, SANE_Handle * handle) { SANE_Status status; CANON_Device *dev; CANON_Scanner *s; int i, j, c; DBG (1, ">> sane_open\n"); if (devnam[0] == '\0') { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) break; } } else dev = first_dev; if (!dev) { status = attach (devnam, &dev); if (status != SANE_STATUS_GOOD) return (status); } if (!dev) return (SANE_STATUS_INVAL); s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->hw = dev; if (s->hw->info.model == FS2710) { for (i = 0; i < 4; i++) { s->gamma_map[i][0] = '\0'; s->gamma_table[i][0] = 0; } for (j = 1; j < 4096; ++j) { /* FS2710 needs inital gamma 2.0 */ c = (int) (256.0 * pow (((double) j) / 4096.0, 0.5)); for (i = 0; i < 4; i++) { s->gamma_map[i][j] = (u_char) c; if ((j & 0xf) == 0) s->gamma_table[i][j >> 4] = c; } } s->colour = 1; s->auxbuf_len = 0; } else { for (i = 0; i < 4; ++i) { for (j = 0; j < 256; ++j) s->gamma_table[i][j] = j; } } init_options (s); if (s->hw->info.model == FB1200) s->inbuffer = malloc (30894); /* modification for FB1200S */ else s->inbuffer = malloc (15312); /* modification for FB620S */ if (!s->inbuffer) return SANE_STATUS_NO_MEM; if (s->hw->info.model == FB1200) s->outbuffer = malloc (30894); /* modification for FB1200S */ else s->outbuffer = malloc (15312); /* modification for FB620S */ if (!s->outbuffer) { free (s->inbuffer); return SANE_STATUS_NO_MEM; } s->next = first_handle; first_handle = s; *handle = s; DBG (1, "<< sane_open\n"); return SANE_STATUS_GOOD; } /**************************************************************************/ void sane_close (SANE_Handle handle) { CANON_Scanner *s = (CANON_Scanner *) handle; SANE_Status status; DBG (1, ">> sane_close\n"); if (s->val[OPT_EJECT_BEFOREEXIT].w) { if (s->fd == -1) sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s->hw); status = medium_position (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_close: MEDIUM POSITION failed\n"); sanei_scsi_close (s->fd); s->fd = -1; } s->AF_NOW = SANE_TRUE; DBG (1, "sane_close AF_NOW = '%d'\n", s->AF_NOW); } if (s->fd != -1) sanei_scsi_close (s->fd); if (s->inbuffer) free (s->inbuffer); /* modification for FB620S */ if (s->outbuffer) free (s->outbuffer); /* modification for FB620S */ if (s->auxbuf_len > 0) free (s->auxbuf); /* modification for FS2710S */ free (s); DBG (1, ">> sane_close\n"); } /**************************************************************************/ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { CANON_Scanner *s = handle; DBG (21, ">> sane_get_option_descriptor option number %d\n", option); if ((unsigned) option >= NUM_OPTIONS) return (0); DBG (21, " sane_get_option_descriptor option name %s\n", option_name[option]); DBG (21, "<< sane_get_option_descriptor option number %d\n", option); return (s->opt + option); } /**************************************************************************/ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { CANON_Scanner *s = handle; SANE_Status status; SANE_Word w, cap; SANE_Byte gbuf[4096]; size_t buf_size; int i, neg, gamma_component, int_t, transfer_data_type; time_t dtime, rt; DBG (21, ">> sane_control_option %s\n", option_name[option]); if (info) *info = 0; if (s->scanning == SANE_TRUE) { DBG (21, ">> sane_control_option: device is busy scanning\n"); return (SANE_STATUS_DEVICE_BUSY); } if (option >= NUM_OPTIONS) return (SANE_STATUS_INVAL); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return (SANE_STATUS_INVAL); if (action == SANE_ACTION_GET_VALUE) { DBG (21, "sane_control_option get value of %s\n", option_name[option]); switch (option) { /* word options: */ case OPT_FLATBED_ONLY: case OPT_TPU_ON: case OPT_TPU_PN: case OPT_TPU_TRANSPARENCY: case OPT_RESOLUTION_BIND: case OPT_HW_RESOLUTION_ONLY: /* 990320, ss */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_CUSTOM_GAMMA: case OPT_CUSTOM_GAMMA_BIND: case OPT_HNEGATIVE: /* case OPT_GRC: */ case OPT_MIRROR: case OPT_AE: case OPT_PREVIEW: case OPT_BIND_HILO: case OPT_HILITE_R: case OPT_SHADOW_R: case OPT_HILITE_G: case OPT_SHADOW_G: case OPT_HILITE_B: case OPT_SHADOW_B: case OPT_EJECT_AFTERSCAN: case OPT_EJECT_BEFOREEXIT: case OPT_THRESHOLD: case OPT_AF: case OPT_AF_ONCE: case OPT_FOCUS: if ((option >= OPT_NEGATIVE) && (option <= OPT_SHADOW_B)) { DBG (21, "GET_VALUE for %s: s->val[%s].w = %d\n", option_name[option], option_name[option], s->val[option].w); } *(SANE_Word *) val = s->val[option].w; DBG (21, "value for option %s: %d\n", option_name[option], s->val[option].w); return (SANE_STATUS_GOOD); case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memset (gbuf, 0, sizeof (gbuf)); buf_size = 256; transfer_data_type = 0x03; DBG (21, "sending GET_DENSITY_CURVE\n"); if (s->val[OPT_CUSTOM_GAMMA_BIND].w == SANE_TRUE) /* If using bind analog gamma, option will be OPT_GAMMA_VECTOR. In this case, use the curve for green */ gamma_component = 2; else /* Else use a different index for each curve */ gamma_component = option - OPT_GAMMA_VECTOR; /* Now get the values from the scanner */ if (s->hw->info.model != FS2710) { sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s->hw); status = get_density_curve (s->fd, gamma_component, gbuf, &buf_size, transfer_data_type); sanei_scsi_close (s->fd); s->fd = -1; if (status != SANE_STATUS_GOOD) { DBG (21, "GET_DENSITY_CURVE\n"); return (SANE_STATUS_INVAL); } } else status = get_density_curve_fs2710 (s, gamma_component, gbuf, &buf_size); neg = (s->hw->info.is_filmscanner) ? strcmp (filmtype_list[1], s->val[OPT_NEGATIVE].s) : s->val[OPT_HNEGATIVE].w; for (i = 0; i < 256; i++) { if (!neg) s->gamma_table[option - OPT_GAMMA_VECTOR][i] = (SANE_Int) gbuf[i]; else s->gamma_table[option - OPT_GAMMA_VECTOR][i] = 255 - (SANE_Int) gbuf[255 - i]; } memcpy (val, s->val[option].wa, s->opt[option].size); DBG (21, "value for option %s: %d\n", option_name[option], s->val[option].w); return (SANE_STATUS_GOOD); /* string options: */ case OPT_TPU_DCM: case OPT_TPU_FILMTYPE: case OPT_MODE: case OPT_NEGATIVE: case OPT_NEGATIVE_TYPE: case OPT_SCANNING_SPEED: strcpy (val, s->val[option].s); DBG (21, "value for option %s: %s\n", option_name[option], s->val[option].s); return (SANE_STATUS_GOOD); default: val = 0; return (SANE_STATUS_GOOD); } } else if (action == SANE_ACTION_SET_VALUE) { DBG (21, "sane_control_option set value for %s\n", option_name[option]); if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_TPU_PN: case OPT_TPU_TRANSPARENCY: case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_HNEGATIVE: /* case OPT_GRC: */ case OPT_MIRROR: case OPT_AE: case OPT_PREVIEW: case OPT_HILITE_R: case OPT_SHADOW_R: case OPT_HILITE_G: case OPT_SHADOW_G: case OPT_HILITE_B: case OPT_SHADOW_B: case OPT_AF_ONCE: case OPT_FOCUS: case OPT_EJECT_AFTERSCAN: case OPT_EJECT_BEFOREEXIT: s->val[option].w = *(SANE_Word *) val; DBG (21, "SET_VALUE for %s: s->val[%s].w = %d\n", option_name[option], option_name[option], s->val[option].w); return (SANE_STATUS_GOOD); case OPT_RESOLUTION_BIND: if (s->val[option].w != *(SANE_Word *) val) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (!s->val[option].w) { /* don't bind */ s->opt[OPT_Y_RESOLUTION].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_X_RESOLUTION; s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_X_RESOLUTION; } else { /* bind */ s->opt[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; s->opt[OPT_X_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; } } return SANE_STATUS_GOOD; /* 990320, ss: switch between slider and option menue for resolution */ case OPT_HW_RESOLUTION_ONLY: if (s->val[option].w != *(SANE_Word *) val) { int iPos, xres, yres; s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (!s->val[option].w) /* use complete range */ { s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_X_RESOLUTION].constraint.range = &s->hw->info.xres_range; s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_Y_RESOLUTION].constraint.range = &s->hw->info.yres_range; } else /* use only hardware resolutions */ { s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_X_RESOLUTION].constraint.word_list = s->xres_word_list; s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_Y_RESOLUTION].constraint.word_list = s->yres_word_list; /* adjust resolutions */ xres = s->xres_word_list[1]; for (iPos = 0; iPos < s->xres_word_list[0]; iPos++) { if (s->val[OPT_X_RESOLUTION].w >= s->xres_word_list[iPos + 1]) xres = s->xres_word_list[iPos + 1]; } s->val[OPT_X_RESOLUTION].w = xres; yres = s->yres_word_list[1]; for (iPos = 0; iPos < s->yres_word_list[0]; iPos++) { if (s->val[OPT_Y_RESOLUTION].w >= s->yres_word_list[iPos + 1]) yres = s->yres_word_list[iPos + 1]; } s->val[OPT_Y_RESOLUTION].w = yres; } } return (SANE_STATUS_GOOD); case OPT_BIND_HILO: if (s->val[option].w != *(SANE_Word *) val) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (!s->val[option].w) { /* don't bind */ s->opt[OPT_HILITE_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_SHADOW_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_HILITE_B].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_SHADOW_B].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_HILITE_G].title = SANE_TITLE_HIGHLIGHT_G; s->opt[OPT_HILITE_G].name = SANE_NAME_HIGHLIGHT_G; s->opt[OPT_HILITE_G].desc = SANE_DESC_HIGHLIGHT_G; s->opt[OPT_SHADOW_G].title = SANE_TITLE_SHADOW_G; s->opt[OPT_SHADOW_G].name = SANE_NAME_SHADOW_G; s->opt[OPT_SHADOW_G].desc = SANE_DESC_SHADOW_G; } else { /* bind */ s->opt[OPT_HILITE_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HILITE_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HILITE_G].title = SANE_TITLE_HIGHLIGHT; s->opt[OPT_HILITE_G].name = SANE_NAME_HIGHLIGHT; s->opt[OPT_HILITE_G].desc = SANE_DESC_HIGHLIGHT; s->opt[OPT_SHADOW_G].title = SANE_TITLE_SHADOW; s->opt[OPT_SHADOW_G].name = SANE_NAME_SHADOW; s->opt[OPT_SHADOW_G].desc = SANE_DESC_SHADOW; } } return SANE_STATUS_GOOD; case OPT_AF: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; s->val[option].w = *(SANE_Word *) val; w = *(SANE_Word *) val; if (w) { s->opt[OPT_AF_ONCE].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_FOCUS].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_AF_ONCE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_FOCUS].cap &= ~SANE_CAP_INACTIVE; } return (SANE_STATUS_GOOD); case OPT_FLATBED_ONLY: s->val[option].w = *(SANE_Word *) val; if (s->hw->adf.Status != ADF_STAT_NONE && s->val[option].w) { /* switch on */ s->hw->adf.Priority |= 0x03; /* flatbed mode */ s->hw->adf.Feeder &= 0x00; /* autofeed off (default) */ s->hw->adf.Status = ADF_STAT_DISABLED; } /* if it isn't connected, don't bother fixing */ return SANE_STATUS_GOOD; case OPT_TPU_ON: s->val[option].w = *(SANE_Word *) val; if (s->val[option].w) /* switch on */ { s->hw->tpu.Status = TPU_STAT_ACTIVE; s->opt[OPT_TPU_TRANSPARENCY].cap &= (s->hw->tpu.ControlMode == 3) ? ~SANE_CAP_INACTIVE : ~0; s->opt[OPT_TPU_FILMTYPE].cap &= (s->hw->tpu.ControlMode == 1) ? ~SANE_CAP_INACTIVE : ~0; } else /* switch off */ { s->hw->tpu.Status = TPU_STAT_INACTIVE; s->opt[OPT_TPU_TRANSPARENCY].cap |= SANE_CAP_INACTIVE; s->opt[OPT_TPU_FILMTYPE].cap |= SANE_CAP_INACTIVE; } s->opt[OPT_TPU_PN].cap ^= SANE_CAP_INACTIVE; s->opt[OPT_TPU_DCM].cap ^= SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_TPU_DCM: if (s->val[OPT_TPU_DCM].s) free (s->val[OPT_TPU_DCM].s); s->val[OPT_TPU_DCM].s = strdup (val); s->opt[OPT_TPU_TRANSPARENCY].cap |= SANE_CAP_INACTIVE; s->opt[OPT_TPU_FILMTYPE].cap |= SANE_CAP_INACTIVE; if (!strcmp (s->val[OPT_TPU_DCM].s, SANE_I18N("Correction according to transparency ratio"))) { s->hw->tpu.ControlMode = 3; s->opt[OPT_TPU_TRANSPARENCY].cap &= ~SANE_CAP_INACTIVE; } else if (!strcmp (s->val[OPT_TPU_DCM].s, SANE_I18N("Correction according to film type"))) { s->hw->tpu.ControlMode = 1; s->opt[OPT_TPU_FILMTYPE].cap &= ~SANE_CAP_INACTIVE; } else s->hw->tpu.ControlMode = 0; if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_TPU_FILMTYPE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return SANE_STATUS_GOOD; case OPT_MODE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) || !strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE)) { /* For Lineart and Halftone: */ /* Enable "threshold" */ s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; /* Disable "custom gamma" and "brightness & contrast" */ s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; } else { /* For Gray and Color modes: */ /* Disable "threshold" */ s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* Enable "custom gamma" and "brightness & contrast" */ s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w) { if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) || !strcmp (val, SANE_I18N("Fine color"))) { s->opt[OPT_CUSTOM_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA_BIND].w == SANE_TRUE) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { s->opt[OPT_CUSTOM_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } } else { s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; } } return (SANE_STATUS_GOOD); case OPT_NEGATIVE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (!strcmp (val, SANE_I18N("Negatives"))) { s->RIF = 0; s->opt[OPT_NEGATIVE_TYPE].cap &= ~SANE_CAP_INACTIVE; if (SANE_OPTION_IS_SETTABLE(s->opt[OPT_SCANNING_SPEED].cap)) s->opt[OPT_SCANNING_SPEED].cap &= ~SANE_CAP_INACTIVE; } else { s->RIF = 1; s->opt[OPT_NEGATIVE_TYPE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SCANNING_SPEED].cap |= SANE_CAP_INACTIVE; } return (SANE_STATUS_GOOD); case OPT_NEGATIVE_TYPE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); for (i = 0; strcmp (val, negative_filmtype_list[i]); i++); s->negative_filmtype = i; return (SANE_STATUS_GOOD); case OPT_SCANNING_SPEED: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); for (i = 0; strcmp (val, scanning_speed_list[i]); i++); s->scanning_speed = i; return (SANE_STATUS_GOOD); /* modification for FB620S */ case OPT_CALIBRATION_NOW: sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s->hw); if (status == SANE_STATUS_GOOD) { status = execute_calibration (s->fd); if (status != SANE_STATUS_GOOD) { DBG (21, "EXECUTE CALIBRATION failed\n"); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } DBG (21, "EXECUTE CALIBRATION\n"); sanei_scsi_close (s->fd); } else DBG (1, "calibration: cannot open device file\n"); s->fd = -1; return status; case OPT_SCANNER_SELF_DIAGNOSTIC: sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s->hw); if (status == SANE_STATUS_GOOD) { status = send_diagnostic (s->fd); { if (status != SANE_STATUS_GOOD) { DBG (21, "SEND DIAGNOSTIC error: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (21, "SEND DIAGNOSTIC result: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); } } else DBG (1, "send diagnostic: cannot open device file\n"); s->fd = -1; return status; case OPT_RESET_SCANNER: sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s->hw); if (status == SANE_STATUS_GOOD) { time (&(s->time1)); DBG (11, "time0 = %ld\n", s->time0); DBG (11, "time1 = %ld\n", s->time1); dtime = (s->time1) - (s->time0); DBG (11, "dtime = %ld\n", dtime); DBG (11, "switch_preview = %d\n", s->switch_preview); if (s->switch_preview == 0) { rt = sqrt (15 * 15 * (SANE_UNFIX (s->val[OPT_BR_Y].w)) / 297) + 0.5; rt = rt + 2; } else rt = 17; DBG (11, "SANE_UNFIX(s->val[OPT_BR_Y].w) = %f\n", SANE_UNFIX (s->val[OPT_BR_Y].w)); DBG (11, "rt = %ld\n", rt); if (dtime < rt) { int_t = (int) (rt - dtime); DBG (11, "int_t = %d\n", int_t); sleep (int_t); } status = reset_scanner (s->fd); { if (status != SANE_STATUS_GOOD) { DBG (21, "RESET SCANNER failed\n"); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (21, "RESET SCANNER\n"); sanei_scsi_close (s->fd); } } else DBG (1, "reset scanner: cannot open device file\n"); s->fd = -1; return status; case OPT_EJECT_NOW: sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s->hw); status = medium_position (s->fd); if (status != SANE_STATUS_GOOD) { DBG (21, "MEDIUM POSITION failed\n"); sanei_scsi_close (s->fd); s->fd = -1; return (SANE_STATUS_INVAL); } DBG (21, "AF_NOW before = '%d'\n", s->AF_NOW); s->AF_NOW = SANE_TRUE; DBG (21, "AF_NOW after = '%d'\n", s->AF_NOW); sanei_scsi_close (s->fd); s->fd = -1; return status; case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == s->val[OPT_CUSTOM_GAMMA].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[OPT_CUSTOM_GAMMA].w = w; if (w) { const char *mode = s->val[OPT_MODE].s; if (!strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY)) s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (!strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) || !strcmp (mode, SANE_I18N("Fine color"))) { s->opt[OPT_CUSTOM_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA_BIND].w) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_CUSTOM_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA_BIND: w = *(SANE_Word *) val; if (w == s->val[OPT_CUSTOM_GAMMA_BIND].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[OPT_CUSTOM_GAMMA_BIND].w = w; if (w) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); DBG (21, "setting gamma vector\n"); /* if (info) */ /* *info |= SANE_INFO_RELOAD_OPTIONS; */ return (SANE_STATUS_GOOD); } } DBG (1, "<< sane_control_option %s\n", option_name[option]); return (SANE_STATUS_INVAL); } /**************************************************************************/ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) { CANON_Scanner *s = handle; DBG (1, ">> sane_get_parameters\n"); if (!s->scanning) { int width, length, xres, yres; const char *mode; memset (&s->params, 0, sizeof (s->params)); width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * s->hw->info.mud / MM_PER_INCH; length = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) * s->hw->info.mud / MM_PER_INCH; xres = s->val[OPT_X_RESOLUTION].w; yres = s->val[OPT_Y_RESOLUTION].w; if (s->val[OPT_RESOLUTION_BIND].w || s->val[OPT_PREVIEW].w) yres = xres; /* make best-effort guess at what parameters will look like once scanning starts. */ if (xres > 0 && yres > 0 && width > 0 && length > 0) { DBG (11, "sane_get_parameters: width='%d', xres='%d', mud='%d'\n", width, xres, s->hw->info.mud); s->params.pixels_per_line = width * xres / s->hw->info.mud; DBG (11, "sane_get_parameters: length='%d', yres='%d', mud='%d'\n", length, yres, s->hw->info.mud); s->params.lines = length * yres / s->hw->info.mud; DBG (11, "sane_get_parameters: pixels_per_line='%d', lines='%d'\n", s->params.pixels_per_line, s->params.lines); } mode = s->val[OPT_MODE].s; if (!strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) || !strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE)) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line / 8; /* workaround rounding problems */ s->params.pixels_per_line = s->params.bytes_per_line * 8; s->params.depth = 1; } else if (!strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY)) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } else if (!strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) || !strcmp (mode, SANE_I18N("Fine color"))) { s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line; s->params.depth = 8; } else { s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 6 * s->params.pixels_per_line; s->params.depth = 16; } s->params.last_frame = SANE_TRUE; } DBG (11, "sane_get_parameters: xres='%d', yres='%d', pixels_per_line='%d', " "bytes_per_line='%d', lines='%d'\n", s->xres, s->yres, s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines); if (params) *params = s->params; DBG (1, "<< sane_get_parameters\n"); return (SANE_STATUS_GOOD); } /**************************************************************************/ SANE_Status sane_start (SANE_Handle handle) { char *mode_str; CANON_Scanner *s = handle; SANE_Status status; u_char wbuf[72], dbuf[28], ebuf[72]; u_char cbuf[2]; /* modification for FB620S */ size_t buf_size, i; char tmpfilename[] = "/tmp/canon.XXXXXX"; /* for FB1200S */ char *thistmpfile; /* for FB1200S */ DBG (1, ">> sane_start\n"); s->tmpfile = -1; /* for FB1200S */ /******* making a tempfile for 1200 dpi scanning of FB1200S ******/ if (s->hw->info.model == FB1200) { thistmpfile = strdup(tmpfilename); if (thistmpfile != NULL) { if (mktemp(thistmpfile) == 0) { DBG(1, "mktemp(thistmpfile) is failed\n"); return (SANE_STATUS_INVAL); } } else { DBG(1, "strdup(thistmpfile) is failed\n"); return (SANE_STATUS_INVAL); } s->tmpfile = open(thistmpfile, O_RDWR | O_CREAT | O_EXCL, 0600); if (s->tmpfile == -1) { DBG(1, "error opening temp file %s\n", thistmpfile); DBG(1, "errno: %i; %s\n", errno, strerror(errno)); errno = 0; return (SANE_STATUS_INVAL); } DBG(1, " ****** tmpfile is opened ****** \n"); unlink(thistmpfile); free (thistmpfile); DBG(1, "free thistmpfile\n"); } /******************************************************************/ s->scanning = SANE_FALSE; if ((s->hw->adf.Status != ADF_STAT_NONE) && (s->val[OPT_FLATBED_ONLY].w != SANE_TRUE) && (s->hw->adf.Problem != 0)) { DBG (3, "SCANNER ADF HAS A PROBLEM\n"); if (s->hw->adf.Problem & 0x08) { status = SANE_STATUS_COVER_OPEN; DBG (3, "ADF Cover Open\n"); } else if (s->hw->adf.Problem & 0x04) { status = SANE_STATUS_JAMMED; DBG (3, "ADF Paper Jam\n"); } else /* adf.Problem = 0x02 */ { status = SANE_STATUS_NO_DOCS; DBG (3, "ADF No More Documents\n"); } return status; } else if ((s->hw->adf.Status != ADF_STAT_NONE) && (s->val[OPT_FLATBED_ONLY].w == SANE_TRUE)) { set_adf_mode (s->fd, s->hw->adf.Priority); /* 2.23 define ADF Mode */ } /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, s->hw); if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return (status); } #if 0 /* code moved after define_scan() calls */ /* Do focus, but not for the preview */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_FOCUS_GROUP].cap) && !s->val[OPT_PREVIEW].w && s->AF_NOW) { if ((status = do_focus (s)) != SANE_STATUS_GOOD) return (status); if (s->val[OPT_AF_ONCE].w) s->AF_NOW = SANE_FALSE; } #endif if (s->val[OPT_CUSTOM_GAMMA].w) { if ((status = do_gamma (s)) != SANE_STATUS_GOOD) return (status); } DBG (3, "attach: sending GET SCAN MODE for scan control conditions\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = 20; status = get_scan_mode (s->fd, (u_char) SCAN_CONTROL_CONDITIONS, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET SCAN MODE for scan control conditions failed\n"); sanei_scsi_close (s->fd); return (SANE_STATUS_INVAL); } for (i = 0; i < buf_size; i++) DBG (3, "scan mode control byte[%d] = %d\n", (int) i, ebuf[i]); if (s->hw->adf.Status != ADF_STAT_NONE) { DBG (3, "attach: sending GET SCAN MODE for transparency unit\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = 12; status = get_scan_mode (s->fd, (u_char) TRANSPARENCY_UNIT, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET SCAN MODE for transparency unit failed\n"); sanei_scsi_close (s->fd); return (SANE_STATUS_INVAL); } for (i = 0; i < buf_size; i++) DBG (3, "scan mode control byte[%d] = %d\n", (int) i, ebuf[i]); } mode_str = s->val[OPT_MODE].s; s->xres = s->val[OPT_X_RESOLUTION].w; s->yres = s->val[OPT_Y_RESOLUTION].w; if (s->val[OPT_RESOLUTION_BIND].w || s->val[OPT_PREVIEW].w) s->yres = s->xres; s->ulx = SANE_UNFIX (s->val[OPT_TL_X].w) * s->hw->info.mud / MM_PER_INCH; s->uly = SANE_UNFIX (s->val[OPT_TL_Y].w) * s->hw->info.mud / MM_PER_INCH; s->width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * s->hw->info.mud / MM_PER_INCH; s->length = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) * s->hw->info.mud / MM_PER_INCH; DBG (11, "s->width='%d', s->length='%d'\n", s->width, s->length); if (s->hw->info.model != CS2700 && s->hw->info.model != FS2710) { if (!strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) || !strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE)) s->RIF = s->val[OPT_HNEGATIVE].w; else s->RIF = !s->val[OPT_HNEGATIVE].w; } s->brightness = s->val[OPT_BRIGHTNESS].w; s->contrast = s->val[OPT_CONTRAST].w; s->threshold = s->val[OPT_THRESHOLD].w; s->bpp = s->params.depth; s->GRC = s->val[OPT_CUSTOM_GAMMA].w; s->Mirror = s->val[OPT_MIRROR].w; s->AE = s->val[OPT_AE].w; s->HiliteG = s->val[OPT_HILITE_G].w; s->ShadowG = s->val[OPT_SHADOW_G].w; if (s->val[OPT_BIND_HILO].w) { s->HiliteR = s->val[OPT_HILITE_G].w; s->ShadowR = s->val[OPT_SHADOW_G].w; s->HiliteB = s->val[OPT_HILITE_G].w; s->ShadowB = s->val[OPT_SHADOW_G].w; } else { s->HiliteR = s->val[OPT_HILITE_R].w; s->ShadowR = s->val[OPT_SHADOW_R].w; s->HiliteB = s->val[OPT_HILITE_B].w; s->ShadowB = s->val[OPT_SHADOW_B].w; } if (!strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART)) { s->image_composition = 0; } else if (!strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE)) { s->image_composition = 1; } else if (!strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY)) { s->image_composition = 2; } else if (!strcmp (mode_str, SANE_VALUE_SCAN_MODE_COLOR) || !strcmp (mode_str, SANE_I18N("Fine color"))) { s->image_composition = 5; } else if (!strcmp (mode_str, SANE_I18N("Raw"))) { s->image_composition = 5; } else { s->image_composition = 5; } memset (wbuf, 0, sizeof (wbuf)); wbuf[7] = 64; wbuf[10] = s->xres >> 8; wbuf[11] = s->xres; wbuf[12] = s->yres >> 8; wbuf[13] = s->yres; wbuf[14] = s->ulx >> 24; wbuf[15] = s->ulx >> 16; wbuf[16] = s->ulx >> 8; wbuf[17] = s->ulx; wbuf[18] = s->uly >> 24; wbuf[19] = s->uly >> 16; wbuf[20] = s->uly >> 8; wbuf[21] = s->uly; wbuf[22] = s->width >> 24; wbuf[23] = s->width >> 16; wbuf[24] = s->width >> 8; wbuf[25] = s->width; wbuf[26] = s->length >> 24; wbuf[27] = s->length >> 16; wbuf[28] = s->length >> 8; wbuf[29] = s->length; wbuf[30] = s->brightness; wbuf[31] = s->threshold; wbuf[32] = s->contrast; wbuf[33] = s->image_composition; wbuf[34] = (s->hw->info.model == FS2710) ? 12 : s->bpp; wbuf[36] = 1; wbuf[37] = (1 << 7) + 0x03; wbuf[50] = (s->GRC << 3) | (s->Mirror << 2); #if 1 wbuf[50] |= s->AE; /* AE also for preview; needed by frontend controls */ #else if (!s->val[OPT_PREVIEW].w) wbuf[50] |= s->AE; /* AE not during preview */ #endif wbuf[54] = 2; wbuf[57] = 1; wbuf[58] = 1; wbuf[59] = s->HiliteR; wbuf[60] = s->ShadowR; wbuf[62] = s->HiliteG; wbuf[64] = s->ShadowG; wbuf[70] = s->HiliteB; wbuf[71] = s->ShadowB; DBG (7, "RIF=%d, GRC=%d, Mirror=%d, AE=%d, Speed=%d\n", s->RIF, s->GRC, s->Mirror, s->AE, s->scanning_speed); DBG (7, "HR=%d, SR=%d, HG=%d, SG=%d, HB=%d, SB=%d\n", s->HiliteR, s->ShadowR, s->HiliteG, s->ShadowG, s->HiliteB, s->ShadowB); if (s->hw->info.model == FB620) /* modification for FB620S */ { wbuf[36] = 0; wbuf[37] = (s->RIF << 7) + 0x3; wbuf[50] = s->GRC << 3; wbuf[54] = 0; wbuf[57] = 0; wbuf[58] = 0; } else if (s->hw->info.model == FB1200) /* modification for FB1200S */ { #if 0 wbuf[34] = (((600 < s->val[OPT_X_RESOLUTION].w) || (600 < s->val[OPT_Y_RESOLUTION].w)) && (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) != 0)) ? 12 : s->bpp; #endif wbuf[36] = 0; wbuf[37] = (s->RIF << 7) + 0x3; wbuf[50] = (1 << 4) | (s->GRC << 3); wbuf[57] = 1; wbuf[58] = 1; } else if (s->hw->info.model == IX4015) /* modification for IX-4015 */ { wbuf[36] = 0; wbuf[37] = (s->RIF << 7); wbuf[57] = 0; wbuf[58] = 0; /* no highlight and shadow control */ wbuf[59] = 0; wbuf[60] = 0; wbuf[62] = 0; wbuf[64] = 0; wbuf[70] = 0; wbuf[71] = 0; } buf_size = sizeof (wbuf); status = set_window (s->fd, wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } if (s->hw->info.model == FS2710) status = set_parameters_fs2710 (s); buf_size = sizeof (wbuf); memset (wbuf, 0, buf_size); status = get_window (s->fd, wbuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (5, "xres=%d\n", (wbuf[10] << 8) + wbuf[11]); DBG (5, "yres=%d\n", (wbuf[12] << 8) + wbuf[13]); DBG (5, "ulx=%d\n", (wbuf[14] << 24) + (wbuf[15] << 16) + (wbuf[16] << 8) + wbuf[17]); DBG (5, "uly=%d\n", (wbuf[18] << 24) + (wbuf[19] << 16) + (wbuf[20] << 8) + wbuf[21]); DBG (5, "width=%d\n", (wbuf[22] << 24) + (wbuf[23] << 16) + (wbuf[24] << 8) + wbuf[25]); DBG (5, "length=%d\n", (wbuf[26] << 24) + (wbuf[27] << 16) + (wbuf[28] << 8) + wbuf[29]); DBG (5, "Highlight Red=%d\n", wbuf[59]); DBG (5, "Shadow Red=%d\n", wbuf[60]); DBG (5, "Highlight (Green)=%d\n", wbuf[62]); DBG (5, "Shadow (Green)=%d\n", wbuf[64]); DBG (5, "Highlight Blue=%d\n", wbuf[70]); DBG (5, "Shadow Blue=%d\n", wbuf[71]); if (s->hw->tpu.Status == TPU_STAT_ACTIVE || s->hw->info.is_filmscanner) { DBG (3, "sane_start: sending DEFINE SCAN MODE for transparency unit, " "NP=%d, Negative film type=%d\n", !s->RIF, s->negative_filmtype); memset (wbuf, 0, sizeof (wbuf)); wbuf[0] = 0x02; wbuf[1] = 6; wbuf[2] = 0x80; wbuf[3] = 0x05; wbuf[4] = 39; wbuf[5] = 16; wbuf[6] = !s->RIF; wbuf[7] = s->negative_filmtype; status = define_scan_mode (s->fd, TRANSPARENCY_UNIT, wbuf); /* note: If we implement a TPU for the FB1200S, we need TRANSPARENCY_UNIT_FB1200 here. */ if (status != SANE_STATUS_GOOD) { DBG (1, "define scan mode failed: %s\n", sane_strstatus (status)); return (status); } } DBG (3, "sane_start: sending DEFINE SCAN MODE for scan control " "conditions\n"); memset (wbuf, 0, sizeof (wbuf)); wbuf[0] = 0x20; if (s->hw->info.model == FB1200) { wbuf[1] = 17; wbuf[16] = 3; wbuf[17] = 8; wbuf[18] = (1 << 7) | (1 << 3); DBG (3, "sane_start: sending DEFINE SCAN MODE for scan control " "conditions of FB1200\n"); status = define_scan_mode (s->fd, SCAN_CONTROL_CON_FB1200, wbuf); } else { wbuf[1] = 14; /* For preview use always normal speed: */ if (!s->val[OPT_PREVIEW].w && s->hw->info.is_filmscanner) wbuf[11] = s->scanning_speed; wbuf[15] = (s->hw->info.model == FB620 && !strcmp (mode_str, SANE_I18N("Fine color")) && !s->val[OPT_PREVIEW].w) ? 1 << 3 : 0; status = define_scan_mode (s->fd, SCAN_CONTROL_CONDITIONS, wbuf); } if (status != SANE_STATUS_GOOD) { DBG (1, "define scan mode failed: %s\n", sane_strstatus (status)); return (status); } DBG (3, "sane_start: sending GET SCAN MODE for scan control conditions\n"); memset (ebuf, 0, sizeof (ebuf)); buf_size = sizeof (ebuf); status = get_scan_mode (s->fd, SCAN_CONTROL_CONDITIONS, ebuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: GET SCAN MODE for scan control conditions " "failed\n"); sanei_scsi_close (s->fd); return (SANE_STATUS_INVAL); } for (i = 0; i < buf_size; i++) DBG (3, "scan mode byte[%d] = %d\n", (int) i, ebuf[i]); /* Focus, but not for previews or negatives with speed control */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_FOCUS_GROUP].cap) && !s->val[OPT_PREVIEW].w && s->AF_NOW && (s->RIF || s->AE || s->scanning_speed == 0)) { if ((status = do_focus (s)) != SANE_STATUS_GOOD) return (status); if (s->val[OPT_AF_ONCE].w) s->AF_NOW = SANE_FALSE; } /* ============= modification for FB620S ============= */ DBG (3, "TEST_UNIT_READY\n"); status = test_unit_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } if (s->hw->info.can_calibrate) { DBG (3, "sane_start: sending GET_CALIBRATION_STATUS\n"); buf_size = sizeof (cbuf); memset (cbuf, 0, buf_size); status = get_calibration_status (s->fd, cbuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: GET_CALIBRATION_STATUS failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (1, "cbuf[0] = %d\n", cbuf[0]); DBG (1, "cbuf[1] = %d\n", cbuf[1]); cbuf[0] &= 3; if (cbuf[0] == 1 || cbuf[0] == 2 || cbuf[0] == 3) { status = execute_calibration (s->fd); DBG (3, "sane_start: EXECUTE_CALIBRATION\n"); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: EXECUTE_CALIBRATION failed\n"); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (3, "after calibration: GET_CALIBRATION_STATUS\n"); buf_size = sizeof (cbuf); memset (cbuf, 0, buf_size); status = get_calibration_status (s->fd, cbuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "after calibration: GET_CALIBRATION_STATUS failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (1, "cbuf[0] = %d\n", cbuf[0]); DBG (1, "cbuf[1] = %d\n", cbuf[1]); } } status = scan (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "start of scan failed: %s\n", sane_strstatus (status)); return (status); } buf_size = sizeof (dbuf); memset (dbuf, 0, buf_size); status = get_data_status (s->fd, dbuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status)); return (status); } DBG (5, ">> GET DATA STATUS\n"); DBG (5, "Scan Data Available=%d\n", (dbuf[9] << 16) + (dbuf[10] << 8) + dbuf[11]); DBG (5, "Magnified Width=%d\n", (dbuf[12] <<24) + (dbuf[13] << 16) + (dbuf[14] << 8) + dbuf[15]); DBG (5, "Magnified Length=%d\n", (dbuf[16] << 24) + (dbuf[17] << 16) + (dbuf[18] << 8) + dbuf[19]); DBG (5, "Rest Data=%d bytes\n", (dbuf[20] << 24) + (dbuf[21] << 16) + (dbuf[22] << 8) + dbuf[23]); DBG (5, "Filled Data Buffer=%d\n", (dbuf[24] << 24) + (dbuf[25] << 16) + (dbuf[26] << 8) + dbuf[27]); DBG (5, "<< GET DATA STATUS\n"); s->bytes_to_read = s->params.bytes_per_line * s->params.lines; if (s->hw->info.model == FB1200) { if (s->bytes_to_read != (((size_t) dbuf[9] << 16) + ((size_t) dbuf[10] << 8) + (size_t) dbuf[11])) { s->params.bytes_per_line = (((size_t) dbuf[12] << 24) + ((size_t) dbuf[13] << 16) + ((size_t) dbuf[14] << 8) + (size_t)dbuf[15]); s->params.lines = (((size_t) dbuf[16] << 24) + ((size_t) dbuf[17] << 16) + ((size_t) dbuf[18] << 8) + (size_t) dbuf[19]); s->bytes_to_read = s->params.bytes_per_line * s->params.lines; mode_str = s->val[OPT_MODE].s; if (!strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART)) { if (((600 < s->val[OPT_X_RESOLUTION].w) || (600 < s->val[OPT_Y_RESOLUTION].w))) { s->params.bytes_per_line *= 2; s->params.lines /= 2; } s->params.pixels_per_line = s->params.bytes_per_line * 8; } else if (!strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY)) s->params.pixels_per_line = s->params.bytes_per_line; else if (!strcmp (mode_str, SANE_VALUE_SCAN_MODE_COLOR) || !strcmp (mode_str, SANE_I18N("Fine color"))) s->params.pixels_per_line = s->params.bytes_per_line / 3; else s->params.pixels_per_line = s->params.bytes_per_line / 6; } } DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_X_RESOLUTION].w); /**************************************************/ /* modification for FB620S and FB1200S */ s->buf_used = 0; s->buf_pos = 0; /**************************************************/ s->scanning = SANE_TRUE; DBG (1, "<< sane_start\n"); return (SANE_STATUS_GOOD); } /**************************************************************************/ static SANE_Status sane_read_direct (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { CANON_Scanner *s = handle; SANE_Status status; size_t nread; DBG (21, ">> sane_read\n"); *len = 0; nread = max_len; DBG (21, " sane_read: nread=%d, bytes_to_read=%d\n", (int) nread, (int) s->bytes_to_read); if (s->bytes_to_read == 0) { do_cancel (s); return (SANE_STATUS_EOF); } if (!s->scanning) return (do_cancel (s)); if (nread > s->bytes_to_read) nread = s->bytes_to_read; status = read_data (s->fd, buf, &nread); if (status != SANE_STATUS_GOOD) { do_cancel (s); return (SANE_STATUS_IO_ERROR); } *len = nread; s->bytes_to_read -= nread; DBG (21, " sane_read: nread=%d, bytes_to_read=%d\n", (int) nread, (int) s->bytes_to_read); DBG (21, "<< sane_read\n"); return (SANE_STATUS_GOOD); } /**************************************************************************/ static SANE_Status read_fs2710 (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { CANON_Scanner *s = handle; SANE_Status status; int c; size_t i, nread, nread2; u_char *p; #if defined(WORDS_BIGENDIAN) u_char b; #endif DBG (21, ">> sane_read\n"); *len = 0; nread = max_len; DBG (21, " sane_read: nread=%d, bytes_to_read=%d\n", (int) nread, (int) s->bytes_to_read); if (nread > s->bytes_to_read) nread = s->bytes_to_read; if (s->bytes_to_read == 0) { do_cancel (s); return (SANE_STATUS_EOF); } if (!s->scanning) return (do_cancel (s)); /* We must receive 2 little-endian bytes per pixel and colour. In raw mode we must swap the bytes if we are running a big-endian architecture (SANE standard 3.2.1), and pass them both. Otherwise the other subroutines expect only 1 byte, so we must set up an intermediate buffer which is twice as large as buf, and then map this buffer to buf. */ if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR)) { if (max_len > s->auxbuf_len) { /* extend buffer? */ if (s->auxbuf_len > 0) free (s->auxbuf); s->auxbuf_len = max_len; if ((s->auxbuf = (u_char *) malloc (2 * max_len)) == NULL) { DBG (1, "sane_read buffer size insufficient\n"); do_cancel (s); return SANE_STATUS_NO_MEM; } } nread2 = 2 * nread; if ((status = read_data (s->fd, s->auxbuf, &nread2)) != SANE_STATUS_GOOD) { do_cancel (s); return (SANE_STATUS_IO_ERROR); } nread = nread2 / 2; for (i = 0, p = s->auxbuf; i < nread; i++) { c = *p++ >> 4; c |= *p++ << 4; *buf++ = s->gamma_map[s->colour++][c]; if (s->colour > 3) s->colour = 1; /* cycle through RGB */ } } else { if ((status = read_data (s->fd, buf, &nread)) != SANE_STATUS_GOOD) { do_cancel (s); return (SANE_STATUS_IO_ERROR); } #if defined(WORDS_BIGENDIAN) for (p = buf; p < buf + nread; p++) { b = *p; *p = *(p + 1); p++; *p = b; } #endif } *len = nread; s->bytes_to_read -= nread; DBG (21, " sane_read: nread=%d, bytes_to_read=%d\n", (int) nread, (int) s->bytes_to_read); DBG (21, "<< sane_read\n"); return (SANE_STATUS_GOOD); } /**************************************************************************/ /* modification for FB620S */ static SANE_Status read_fb620 (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { CANON_Scanner *s = handle; SANE_Status status; SANE_Byte *out, *red, *green, *blue; SANE_Int ncopy; size_t nread = 0, i, pixel_per_line; DBG (21, ">> read_fb620\n"); *len = 0; DBG (21, " read_fb620: nread=%d, bytes_to_read=%d\n", (int) nread, (int) s->bytes_to_read); if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used) { s->reset_flag = 0; /* no reset */ do_cancel (s); DBG (21, "do_cancel(EOF)\n"); DBG (21, "reset_flag = %d\n", s->reset_flag); return (SANE_STATUS_EOF); } else { s->reset_flag = 1; /* do reset */ DBG (21, "reset_flag = %d\n", s->reset_flag); } DBG (21, " read_fb620: buf_pos=%d, buf_used=%d\n", s->buf_pos, s->buf_used); if (!s->scanning) return (do_cancel (s)); if (s->buf_pos < s->buf_used) { ncopy = s->buf_used - s->buf_pos; if (ncopy > max_len) ncopy = max_len; memcpy (buf, &(s->outbuffer[s->buf_pos]), ncopy); max_len -= ncopy; *len += ncopy; buf = &(buf[ncopy]); s->buf_pos += ncopy; } if (s->buf_pos >= s->buf_used && s->bytes_to_read) { /* buffer is empty: read in scan line and sort color data as shown above */ nread = s->params.bytes_per_line; if (nread > s->bytes_to_read) nread = s->bytes_to_read; status = read_data (s->fd, s->inbuffer, &nread); if (status != SANE_STATUS_GOOD) { do_cancel (s); return (SANE_STATUS_IO_ERROR); } s->buf_used = s->params.bytes_per_line; out = s->outbuffer; pixel_per_line = s->params.pixels_per_line; red = s->inbuffer; green = &(s->inbuffer[pixel_per_line]); blue = &(s->inbuffer[2 * pixel_per_line]); for (i = 0; i < pixel_per_line; i++) { *out++ = *red++; *out++ = *green++; *out++ = *blue++; } s->buf_pos = 0; s->bytes_to_read -= s->buf_used; } if (max_len && s->buf_pos < s->buf_used) { ncopy = s->buf_used - s->buf_pos; if (ncopy > max_len) ncopy = max_len; memcpy (buf, &(s->outbuffer[s->buf_pos]), ncopy); *len += ncopy; s->buf_pos += ncopy; } DBG (21, "<< read_fb620\n"); return (SANE_STATUS_GOOD); } /**************************************************************************/ /* modification for FB1200S */ static SANE_Status read_fb1200 (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { CANON_Scanner *s = handle; SANE_Status status; SANE_Byte *firstimage, *secondimage/*, inmask, outmask, outbyte, primaryHigh[256], primaryLow[256], secondaryHigh[256], secondaryLow[256] */; SANE_Int ncopy; u_char dbuf[28]; size_t buf_size, nread, remain, nwritten, nremain, pos, pix, pixel_per_line, byte, byte_per_line/*, bit*/; ssize_t wres, readres; int maxpix; DBG (21, ">> read_fb1200\n"); buf_size = sizeof (dbuf); memset (dbuf, 0, buf_size); status = get_data_status (s->fd, dbuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status)); return (status); } DBG (5, ">> GET DATA STATUS\n"); DBG (5, "Scan Data Available=%d\n", (dbuf[9] << 16) + (dbuf[10] << 8) + dbuf[11]); DBG (5, "Rest Data=%d bytes\n", (dbuf[20] << 24) + (dbuf[21] << 16) + (dbuf[22] << 8) + dbuf[23]); DBG (5, "Filled Data Buffer=%d\n", (dbuf[24] << 24) + (dbuf[25] << 16) + (dbuf[26] << 8) + dbuf[27]); DBG (5, "temp file position:%u\n", (unsigned int) lseek(s->tmpfile, 0, SEEK_CUR)); DBG (5, "<< GET DATA STATUS\n"); *len = 0; DBG (21, " read_fb1200: bytes_to_read=%d\n", (int) s->bytes_to_read); if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used) { do_cancel (s); DBG (21, "do_cancel(EOF)\n"); return (SANE_STATUS_EOF); } DBG (21, " read_fb1200: buf_pos=%d, buf_used=%d\n", s->buf_pos, s->buf_used); if (!s->scanning) return (do_cancel (s)); if (s->buf_pos >= s->buf_used && s->bytes_to_read) { nread = s->params.bytes_per_line / 2; if (nread > s->bytes_to_read) nread = s->bytes_to_read; status = read_data (s->fd, s->inbuffer, &nread); if (status != SANE_STATUS_GOOD) { do_cancel (s); return (SANE_STATUS_IO_ERROR); } /**** save the primary scan data to tmpfile ****/ if ((SANE_Int) s->bytes_to_read > s->params.bytes_per_line * s->params.lines / 2) { remain = nread; nwritten = 0; while (remain) { errno = 0; wres = write (s->tmpfile, &s->inbuffer[nwritten], remain); if (wres == -1) { DBG(1, "error write tmp file: %i, %s\n", errno, strerror(errno)); do_cancel(s); return (SANE_STATUS_NO_MEM); } remain -= wres; nwritten += wres; } s->bytes_to_read -= nread; if ((SANE_Int) s->bytes_to_read <= s->params.bytes_per_line * s->params.lines / 2) { if ((SANE_Int) s->bytes_to_read < s->params.bytes_per_line * s->params.lines / 2) DBG(1, "warning: read more data for the primary scan " "than expected\n"); lseek (s->tmpfile, 0L, SEEK_SET); *len = 0; *buf = 0; return (SANE_STATUS_GOOD); } DBG(1, "writing: the primary data to tmp file\n"); *len = 0; *buf = 0; return (SANE_STATUS_GOOD); } /** the primary scan data from tmpfile and the secondary scan data are merged **/ s->buf_used = s->params.bytes_per_line; byte_per_line = s->params.bytes_per_line; pixel_per_line = s->params.pixels_per_line; /** read an entire scan line from the primary scan **/ remain = nread; pos = 0; firstimage = &(s->inbuffer[byte_per_line/2]); while (remain > 0) { nremain = (remain < SSIZE_MAX)? remain: SSIZE_MAX; errno = 0; readres = read (s->tmpfile, &(firstimage[pos]), nremain); if (readres == -1) { DBG(1, "error reading tmp file: %i %s\n", errno, strerror(errno)); do_cancel(s); return (SANE_STATUS_IO_ERROR); } if (readres == 0) { DBG(1, "0 byte read from temp file. premature EOF?\n"); return (SANE_STATUS_INVAL); /* perhaps an error return? */ } DBG(1, "reading: the primary data from tmp file\n"); remain -= readres; pos += readres; } secondimage = s->inbuffer; if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR)) { maxpix = pixel_per_line / 2; for (pix = 0; (int) pix < maxpix; pix++) { s->outbuffer[6 * pix] = secondimage[3 * pix]; s->outbuffer[6 * pix + 1] = secondimage[3 * pix + 1]; s->outbuffer[6 * pix + 2] = secondimage[3 * pix + 2]; s->outbuffer[6 * pix + 3] = firstimage[3 * pix]; s->outbuffer[6 * pix + 4] = firstimage[3 * pix + 1]; s->outbuffer[6 * pix + 5] = firstimage[3 * pix + 2]; } } else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) { for (pix = 0; pix < pixel_per_line / 2; pix++) { s->outbuffer[2 * pix] = secondimage[pix]; s->outbuffer[2 * pix + 1] = firstimage[pix]; } } else /* for lineart mode */ { maxpix = byte_per_line / 2; for (byte = 0; (int) byte < maxpix; byte++) { s->outbuffer[2 * byte] = primaryHigh[firstimage[byte]] | secondaryHigh[secondimage[byte]]; s->outbuffer[2 * byte + 1] = primaryLow[firstimage[byte]] | secondaryLow[secondimage[byte]]; #if 0 inmask = 128; outmask = 128; outbyte = 0; for (bit = 0; bit < 4; bit++) { if (inmask == (secondimage[byte] & inmask)) outbyte = outbyte | outmask; outmask = outmask >> 1; if (inmask == (firstimage[byte] & inmask)) outbyte = outbyte | outmask; outmask = outmask >> 1; inmask = inmask >> 1; } s->outbuffer[2 * byte] = outbyte; outmask = 128; outbyte = 0; for (bit = 0; bit < 4; bit++) { if (inmask == (secondimage[byte] & inmask)) outbyte = outbyte | outmask; outmask = outmask >> 1; if (inmask == (firstimage[byte] & inmask)) outbyte = outbyte | outmask; outmask = outmask >> 1; inmask = inmask >> 1; } s->outbuffer[2 * byte + 1] = outbyte; #endif } } s->buf_pos = 0; s->bytes_to_read -= nread; } if (max_len && s->buf_pos < s->buf_used) { ncopy = s->buf_used - s->buf_pos; if (ncopy > max_len) ncopy = max_len; memcpy (buf, &(s->outbuffer[s->buf_pos]), ncopy * 2); *len += ncopy; s->buf_pos += ncopy; } DBG (21, "<< read_fb1200\n"); return (SANE_STATUS_GOOD); } /**************************************************************************/ SANE_Status sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { CANON_Scanner *s = handle; SANE_Status status; if (s->hw->info.model == FB620 && s->params.format == SANE_FRAME_RGB) status = read_fb620 (handle, buf, max_len, len); else if (s->hw->info.model == FS2710) status = read_fs2710 (handle, buf, max_len, len); else if (s->hw->info.model == FB1200 && ((600 < s->val[OPT_X_RESOLUTION].w) || (600 < s->val[OPT_Y_RESOLUTION].w))) status = read_fb1200 (handle, buf, max_len, len); else status = sane_read_direct (handle, buf, max_len, len); if (s->time0 == -1) s->time0 = 0; else time (&(s->time0)); DBG (11, "sane_read: time0 = %ld\n", s->time0); s->switch_preview = s->val[OPT_PREVIEW].w; return (status); } /**************************************************************************/ void sane_cancel (SANE_Handle handle) { CANON_Scanner *s = handle; DBG (1, ">> sane_cancel\n"); /******** for FB1200S ************/ if(s->hw->info.model == FB1200) { if (s->tmpfile != -1) { close (s->tmpfile); DBG(1, " ****** tmpfile is closed ****** \n"); } else { DBG(1, "tmpfile is failed\n"); /* return (SANE_STATUS_INVAL);*/ } } /*********************************/ s->scanning = SANE_FALSE; DBG (1, "<< sane_cancel\n"); } /**************************************************************************/ SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { DBG (1, ">> sane_set_io_mode\n"); DBG (1, "<< sane_set_io_mode\n"); return SANE_STATUS_UNSUPPORTED; } /**************************************************************************/ SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { DBG (1, ">> sane_get_select_fd\n"); DBG (1, "<< sane_get_select_fd\n"); return SANE_STATUS_UNSUPPORTED; } /**************************************************************************/ sane-backends-1.0.27/backend/plustek-pp_scale.c0000664000175000017500000000776712112021330016232 00000000000000/* @file plustek-pp_scale.c * @brief Scaling functionality * * Copyright (C) 2000-2004 Gerhard Jaeger * * History: * - 0.32 - initial version * - 0.33 - no changes * - 0.34 - no changes * - 0.35 - no changes * - 0.36 - no changes * - 0.37 - no changes * - 0.38 - no changes * - 0.39 - no changes * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - cleanup, removed floating point stuff * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /************************ exported functions *********************************/ /** scaling picture data in x-direction, using a DDA algo * (digital differential analyzer). */ _LOC void ScaleX( pScanData ps, pUChar inBuf, pUChar outBuf ) { UChar tmp; int step; int izoom; int ddax; register ULong i, j, x; #ifdef DEBUG _VAR_NOT_USED( dbg_level ); #endif /* scale... */ izoom = (int)(1000000/ps->DataInf.XYRatio); switch( ps->DataInf.wAppDataType ) { case COLOR_BW : step = 0; break; case COLOR_HALFTONE: step = 0; break; case COLOR_256GRAY : step = 1; break; case COLOR_TRUE24 : step = 3; break; /*NOTE: COLOR_TRUE32 is the same !*/ case COLOR_TRUE48 : step = 6; break; default : step = 99; break; } /* when not supported, only copy the data */ if( 99 == step ) { memcpy( outBuf, inBuf, ps->DataInf.dwAppBytesPerLine ); return; } /* now scale... */ ddax = 0; x = 0; if( 0 == step ) { /* binary scaling */ memset( outBuf, 0, ps->DataInf.dwAppBytesPerLine ); for( i = 0; i < ps->DataInf.dwPhysBytesPerLine*8; i++ ) { ddax -= 1000; while( ddax < 0 ) { tmp = inBuf[(i>>3)]; if((x>>3) < ps->DataInf.dwAppBytesPerLine ) { if( 0 != (tmp &= (1 << ((~(i & 0x7))&0x7)))) outBuf[x>>3] |= (1 << ((~(x & 0x7))&0x7)); } x++; ddax += izoom; } } } else { /* color and gray scaling */ for( i = 0; i < ps->DataInf.dwPhysBytesPerLine*step; i+=step ) { ddax -= 1000; while( ddax < 0 ) { for( j = 0; j < (ULong)step; j++ ) { if((x+j) < ps->DataInf.dwAppBytesPerLine ) { outBuf[x+j] = inBuf[i+j]; } } x += step; ddax += izoom; } } } } /* END PLUSTEK-PP_SCALE.C ...................................................*/ sane-backends-1.0.27/backend/xerox_mfp.h0000664000175000017500000001574613063340150015001 00000000000000/* * SANE backend for Xerox Phaser 3200MFP et al. * Copyright 2008-2016 ABC * * Network Scanners Support * Copyright 2010 Alexander Kuznetsov * * Color scanning on Samsung M2870 model and Xerox Cognac 3215 & 3225 * models by Laxmeesh Onkar Markod * * This program is licensed under GPL + SANE exception. * More info at http://www.sane-project.org/license.html */ #ifndef xerox_mfp_h #define xerox_mfp_h #ifdef __GNUC__ #define UNUSED(x) x __attribute__((unused)) #else #define UNUSED(x) x #endif #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define UNCONST(ptr) ((void *)(long)(ptr)) #define PNT_PER_MM (1200. / MM_PER_INCH) #define PADDING_SIZE 16 #define SWAP_Word(x, y) { SANE_Word z = x; x = y; y = z; } enum options { OPT_NUMOPTIONS, OPT_GROUP_STD, OPT_RESOLUTION, /* dpi*/ OPT_MODE, /* color */ OPT_THRESHOLD, /* brightness */ OPT_SOURCE, /* affects max window size */ OPT_GROUP_GEO, OPT_SCAN_TL_X, /* for (OPT_SCAN_TL_X to OPT_SCAN_BR_Y) */ OPT_SCAN_TL_Y, OPT_SCAN_BR_X, OPT_SCAN_BR_Y, NUM_OPTIONS }; typedef struct transport transport; struct device { struct device *next; SANE_Device sane; int dn; /* usb file descriptor */ SANE_Byte res[1024]; /* buffer for responses */ size_t reslen; /* response len */ SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters para; SANE_Bool non_blocking; int scanning; /* scanning is started */ int cancel; /* cancel flag */ int state; /* current state */ int reserved; /* CMD_RESERVE_UNIT */ int reading; /* READ_IMAGE is sent */ SANE_Byte *data; /* postprocessing cyclic buffer 64k */ int datalen; /* how data in buffer */ int dataoff; /* offset of data */ int dataindex; /* sequental number */ #define DATAMASK 0xffff /* mask of data buffer */ #define DATASIZE (DATAMASK + 1) /* size of data buffer */ /* 64K will be enough to hold whole line of 2400 dpi of 23cm */ #define DATATAIL(dev) ((dev->dataoff + dev->datalen) & DATAMASK) #define DATAROOM(dev) dataroom(dev) #define POST_DATASIZE 0xFFFFFF SANE_Byte *decData; int decDataSize; int currentDecDataIndex; /* data from CMD_INQUIRY: */ int resolutions; /* supported resolution bitmask */ int compositions; /* supported image compositions bitmask */ int max_len; /* effective max len for current doc source */ int max_win_width; int max_win_len; int max_len_adf; int max_len_fb; int line_order; /* if need post processing */ SANE_Word dpi_list[30]; /* allowed resolutions */ int doc_loaded; SANE_Range win_x_range; SANE_Range win_y_range; /* CMD_SET_WINDOW parameters we set: */ int win_width; /* in 1200dpi points */ int win_len; double win_off_x; /* in inches (byte.byte) */ double win_off_y; int resolution; /* dpi indexed values */ int composition; /* MODE_ */ int doc_source; /* document source */ int threshold; /* brightness */ int compressionTypes; /* CMD_READ data. It is per block only, image could be in many blocks */ int blocklen; /* image data block len (padding incl.) */ int vertical; /* lines in block (padded) */ int horizontal; /* b/w: bytes, gray/color: pixels (padded) */ int final_block; int pixels_per_line; int bytes_per_line; int ulines; /* up to this block including */ int y_off; /* up to this block excluding*/ int blocks; /* stat */ int total_img_size; /* predicted image size */ int total_out_size; /* total we sent to user */ int total_data_size; /* total of what scanner sent us */ /* transport to use */ transport *io; }; /* Transport abstract layer */ struct transport { char *ttype; int (*dev_request)(struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen); SANE_Status(*dev_open)(struct device *dev); void (*dev_close)(struct device *dev); SANE_Status(*configure_device)(const char *devname, SANE_Status(*cb)(SANE_String_Const devname)); }; /* USB transport */ int usb_dev_request(struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen); SANE_Status usb_dev_open(struct device *dev); void usb_dev_close(struct device *dev); SANE_Status usb_configure_device(const char *devname, SANE_Status(*cb)(SANE_String_Const devname)); /* TCP unicast */ int tcp_dev_request(struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen); SANE_Status tcp_dev_open(struct device *dev); void tcp_dev_close(struct device *dev); SANE_Status tcp_configure_device(const char *devname, SANE_Status(*cb)(SANE_String_Const devname)); /* device wants transfer buffer to be multiple of 512 */ #define USB_BLOCK_SIZE 512 #define USB_BLOCK_MASK ~(USB_BLOCK_SIZE - 1) static inline int dataroom(struct device *dev) { int tail = DATATAIL(dev); if (tail < dev->dataoff) return dev->dataoff - tail; else if (dev->datalen == DATASIZE) { return 0; } else return DATASIZE - tail; } /* Functions from original xerox_mfp.c, used in -usb.c and -tcp.c */ SANE_Status ret_cancel(struct device *dev, SANE_Status ret); /* a la SCSI commands. */ /* request len, response len, exception */ #define CMD_ABORT 0x06 /* 4, 32 */ #define CMD_INQUIRY 0x12 /* 4, 70 */ #define CMD_RESERVE_UNIT 0x16 /* 4, 32 */ #define CMD_RELEASE_UNIT 0x17 /* 4, 32 */ #define CMD_SET_WINDOW 0x24 /* 25, 32, specified req len is 22 */ #define CMD_READ 0x28 /* 4, 32 */ #define CMD_READ_IMAGE 0x29 /* 4, var + padding[16] */ #define CMD_OBJECT_POSITION 0x31 /* 4, 32 */ /* Packet Headers */ #define REQ_CODE_A 0x1b #define REQ_CODE_B 0xa8 #define RES_CODE 0xa8 /* Status Codes, going into dev->state */ #define STATUS_GOOD 0x00 #define STATUS_CHECK 0x02 /* MSG_SCANNER_STATE */ #define STATUS_CANCEL 0x04 #define STATUS_BUSY 0x08 /* Message Code */ #define MSG_NO_MESSAGE 0x00 #define MSG_PRODUCT_INFO 0x10 /* CMD_INQUIRY */ #define MSG_SCANNER_STATE 0x20 /* CMD_RESERVE_UNIT, and CMD_READ, CMD_SET_WINDOW, CMD_OBJECT_POSITION */ #define MSG_SCANNING_PARAM 0x30 /* CMD_SET_WINDOW */ #define MSG_PREVIEW_PARAM 0x31 /* CMD_SET_WINDOW */ #define MSG_LINK_BLOCK 0x80 /* CMD_READ */ #define MSG_END_BLOCK 0x81 /* CMD_READ */ /* Scanner State Bits (if MSG_SCANNER_STATE if STATUS_CHECK) */ #define STATE_NO_ERROR 0x001 #define STATE_COMMAND_ERROR 0x002 #define STATE_UNSUPPORTED 0x004 #define STATE_RESET 0x008 #define STATE_NO_DOCUMENT 0x010 #define STATE_DOCUMENT_JAM 0x020 #define STATE_COVER_OPEN 0x040 #define STATE_WARMING 0x080 #define STATE_LOCKING 0x100 #define STATE_INVALID_AREA 0x200 #define STATE_RESOURCE_BUSY 0x400 /* Image Composition */ #define MODE_LINEART 0x00 #define MODE_HALFTONE 0x01 #define MODE_GRAY8 0x03 #define MODE_RGB24 0x05 /* Document Source */ #define DOC_ADF 0x20 #define DOC_FLATBED 0x40 #define DOC_AUTO 0x80 #endif /* xerox_mfp_h */ sane-backends-1.0.27/backend/hp5590_low.h0000664000175000017500000000673012617742237014616 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Ilia Sotnikov This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 Scanners */ #ifndef HP5590_LOW_H #define HP5590_LOW_H #include "../include/sane/sane.h" enum proto_flags { PF_NONE = 0, PF_NO_USB_IN_USB_ACK = 1 << 0 /* Getting acknowledge after USB-in-USB command * will be skipped */ }; /* Flags for hp5590_cmd() */ #define CMD_IN 1 << 0 /* Indicates IN direction, otherwise - OUT */ #define CMD_VERIFY 1 << 1 /* Requests last command verification */ /* Core flags for hp5590_cmd() - they indicate so called CORE commands */ #define CORE_NONE 0 /* No CORE operation */ #define CORE_DATA 1 << 0 /* Operate on CORE data */ #define CORE_BULK_IN 1 << 1 /* CORE bulk operation - prepare for bulk IN * transfer (not used yet) */ #define CORE_BULK_OUT 1 << 2 /* CORE bulk operation - prepare for bulk OUT * transfer */ static SANE_Status hp5590_cmd (SANE_Int dn, enum proto_flags proto_flags, unsigned int flags, unsigned int cmd, unsigned char *data, unsigned int size, unsigned int core_flags); static SANE_Status hp5590_bulk_read (SANE_Int dn, enum proto_flags proto_flags, unsigned char *bytes, unsigned int size, void *state); static SANE_Status hp5590_bulk_write (SANE_Int dn, enum proto_flags proto_flags, int cmd, unsigned char *bytes, unsigned int size); static SANE_Status hp5590_get_status (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_low_init_bulk_read_state (void **state); static SANE_Status hp5590_low_free_bulk_read_state (void **state); #endif /* HP5590_LOW_H */ /* vim: sw=2 ts=8 */ sane-backends-1.0.27/backend/epson_scsi.c0000664000175000017500000000416512112021330015111 00000000000000#ifdef _AIX #include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #undef BACKEND_NAME #define BACKEND_NAME epson_scsi #include "../include/sane/config.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_scsi.h" #include "epson_scsi.h" #include "../include/lalloca.h" #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include /* for memset and memcpy */ #include /* * sense handler for the sanei_scsi_XXX comands */ SANE_Status sanei_epson_scsi_sense_handler (int scsi_fd, u_char * result, void *arg) { /* to get rid of warnings */ scsi_fd = scsi_fd; arg = arg; if (result[0] && result[0] != 0x70) { DBG (2, "sense_handler() : sense code = 0x%02x\n", result[0]); return SANE_STATUS_IO_ERROR; } else { return SANE_STATUS_GOOD; } } /* * * */ SANE_Status sanei_epson_scsi_inquiry (int fd, int page_code, void *buf, size_t * buf_size) { u_char cmd[6]; int status; memset (cmd, 0, 6); cmd[0] = INQUIRY_COMMAND; cmd[2] = page_code; cmd[4] = *buf_size > 255 ? 255 : *buf_size; status = sanei_scsi_cmd (fd, cmd, sizeof cmd, buf, buf_size); return status; } /* * * */ int sanei_epson_scsi_read (int fd, void *buf, size_t buf_size, SANE_Status * status) { u_char cmd[6]; memset (cmd, 0, 6); cmd[0] = READ_6_COMMAND; cmd[2] = buf_size >> 16; cmd[3] = buf_size >> 8; cmd[4] = buf_size; if (SANE_STATUS_GOOD == (*status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, &buf_size))) return buf_size; return 0; } /* * * */ int sanei_epson_scsi_write (int fd, const void *buf, size_t buf_size, SANE_Status * status) { u_char *cmd; cmd = alloca (8 + buf_size); memset (cmd, 0, 8); cmd[0] = WRITE_6_COMMAND; cmd[2] = buf_size >> 16; cmd[3] = buf_size >> 8; cmd[4] = buf_size; memcpy (cmd + 8, buf, buf_size); if (SANE_STATUS_GOOD == (*status = sanei_scsi_cmd2 (fd, cmd, 6, cmd + 8, buf_size, NULL, NULL))) return buf_size; return 0; } sane-backends-1.0.27/backend/bh.conf.in0000664000175000017500000000003512112021330014435 00000000000000scsi "B&H SCSI" /dev/scanner sane-backends-1.0.27/backend/kvs20xx_opt.c0000664000175000017500000005325212775312261015201 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. Copyright (C) 2010, m. allan noah */ /* Panasonic KV-S20xx USB-SCSI scanners. */ #include "../include/sane/config.h" #include #define DEBUG_DECLARE_ONLY #define BACKEND_NAME kvs20xx #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "kvs20xx.h" #include "kvs20xx_cmd.h" #include static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; static const unsigned mode_val[] = { 0, 2, 5 }; static const unsigned bps_val[] = { 1, 8, 24 }; static const SANE_Range resolutions_range = {100,600,10}; /* List of feeder modes */ static SANE_String_Const feeder_mode_list[] = { SANE_I18N ("single"), SANE_I18N ("continuous"), NULL }; /* List of manual feed mode */ static SANE_String_Const manual_feed_list[] = { SANE_I18N ("off"), SANE_I18N ("wait_doc"), SANE_I18N ("wait_key"), NULL }; /* List of paper sizes */ static SANE_String_Const paper_list[] = { SANE_I18N ("user_def"), SANE_I18N ("business_card"), /*SANE_I18N("Check"), */ /*SANE_I18N ("A3"), */ SANE_I18N ("A4"), SANE_I18N ("A5"), SANE_I18N ("A6"), SANE_I18N ("Letter"), /*SANE_I18N ("Double letter 11x17 in"), SANE_I18N ("B4"), */ SANE_I18N ("B5"), SANE_I18N ("B6"), SANE_I18N ("Legal"), NULL }; static const unsigned paper_val[] = { 0, 1, 4, 5, 6, 7, 13, 14, 15 }; struct paper_size { int width; int height; }; static const struct paper_size paper_sizes[] = { {210, 297}, /* User defined, default=A4 */ {54, 90}, /* Business card */ /*{80, 170}, *//* Check (China business) */ /*{297, 420}, *//* A3 */ {210, 297}, /* A4 */ {148, 210}, /* A5 */ {105, 148}, /* A6 */ {215, 280}, /* US Letter 8.5 x 11 in */ /*{280, 432}, *//* Double Letter 11 x 17 in */ /*{250, 353}, *//* B4 */ {176, 250}, /* B5 */ {125, 176}, /* B6 */ {215, 355} /* US Legal */ }; #define MIN_WIDTH 51 #define MAX_WIDTH 215 #define MIN_LENGTH 70 #define MAX_LENGTH 355 static SANE_Range tl_x_range = { 0, MAX_WIDTH - MIN_WIDTH, 0 }; static SANE_Range tl_y_range = { 0, MAX_LENGTH - MIN_LENGTH, 0 }; static SANE_Range br_x_range = { MIN_WIDTH, MAX_WIDTH, 0 }; static SANE_Range br_y_range = { MIN_LENGTH, MAX_LENGTH, 0 }; static SANE_Range byte_value_range = { 0, 255, 0 }; /* List of image emphasis options, 5 steps */ static SANE_String_Const image_emphasis_list[] = { SANE_I18N ("none"), SANE_I18N ("low"), SANE_I18N ("medium"), SANE_I18N ("high"), SANE_I18N ("smooth"), NULL }; /* List of gamma */ static SANE_String_Const gamma_list[] = { SANE_I18N ("normal"), SANE_I18N ("crt"), NULL }; static unsigned gamma_val[] = { 0, 1 }; /* List of lamp color dropout */ static SANE_String_Const lamp_list[] = { SANE_I18N ("normal"), SANE_I18N ("red"), SANE_I18N ("green"), SANE_I18N ("blue"), NULL }; /* Reset the options for that scanner. */ void kvs20xx_init_options (struct scanner *s) { int i; SANE_Option_Descriptor *o; /* Pre-initialize the options. */ memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; i++) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options. */ o = &s->opt[NUM_OPTS]; o->name = ""; o->title = SANE_TITLE_NUM_OPTIONS; o->desc = SANE_DESC_NUM_OPTIONS; o->type = SANE_TYPE_INT; o->cap = SANE_CAP_SOFT_DETECT; s->val[NUM_OPTS].w = NUM_OPTIONS; /* Mode group */ o = &s->opt[MODE_GROUP]; o->title = SANE_I18N ("Scan Mode"); o->desc = ""; /* not valid for a group */ o->type = SANE_TYPE_GROUP; o->cap = 0; o->size = 0; o->constraint_type = SANE_CONSTRAINT_NONE; /* Scanner supported modes */ o = &s->opt[MODE]; o->name = SANE_NAME_SCAN_MODE; o->title = SANE_TITLE_SCAN_MODE; o->desc = SANE_DESC_SCAN_MODE; o->type = SANE_TYPE_STRING; o->size = max_string_size (mode_list); o->constraint_type = SANE_CONSTRAINT_STRING_LIST; o->constraint.string_list = mode_list; s->val[MODE].s = malloc (o->size); strcpy (s->val[MODE].s, mode_list[0]); /* X and Y resolution */ o = &s->opt[RESOLUTION]; o->name = SANE_NAME_SCAN_RESOLUTION; o->title = SANE_TITLE_SCAN_RESOLUTION; o->desc = SANE_DESC_SCAN_RESOLUTION; o->type = SANE_TYPE_INT; o->unit = SANE_UNIT_DPI; o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &resolutions_range; s->val[RESOLUTION].w = 100; /* Duplex */ o = &s->opt[DUPLEX]; o->name = "duplex"; o->title = SANE_I18N ("Duplex"); o->desc = SANE_I18N ("Enable Duplex (Dual-Sided) Scanning"); o->type = SANE_TYPE_BOOL; o->unit = SANE_UNIT_NONE; s->val[DUPLEX].w = SANE_FALSE; /*FIXME if (!s->support_info.support_duplex) o->cap |= SANE_CAP_INACTIVE; */ /* Feeder mode */ o = &s->opt[FEEDER_MODE]; o->name = "feeder-mode"; o->title = SANE_I18N ("Feeder mode"); o->desc = SANE_I18N ("Sets the feeding mode"); o->type = SANE_TYPE_STRING; o->size = max_string_size (feeder_mode_list); o->constraint_type = SANE_CONSTRAINT_STRING_LIST; o->constraint.string_list = feeder_mode_list; s->val[FEEDER_MODE].s = malloc (o->size); strcpy (s->val[FEEDER_MODE].s, feeder_mode_list[0]); /* Length control */ o = &s->opt[LENGTHCTL]; o->name = "length-control"; o->title = SANE_I18N ("Length control mode"); o->desc = SANE_I18N ("Length Control Mode is a mode that the scanner reads up to the shorter length of actual" " paper or logical document length."); o->type = SANE_TYPE_BOOL; o->unit = SANE_UNIT_NONE; s->val[LENGTHCTL].w = SANE_FALSE; /* Manual feed */ o = &s->opt[MANUALFEED]; o->name = "manual-feed"; o->title = SANE_I18N ("Manual feed mode"); o->desc = SANE_I18N ("Sets the manual feed mode"); o->type = SANE_TYPE_STRING; o->size = max_string_size (manual_feed_list); o->constraint_type = SANE_CONSTRAINT_STRING_LIST; o->constraint.string_list = manual_feed_list; s->val[MANUALFEED].s = malloc (o->size); strcpy (s->val[MANUALFEED].s, manual_feed_list[0]); /*Manual feed timeout */ o = &s->opt[FEED_TIMEOUT]; o->name = "feed-timeout"; o->title = SANE_I18N ("Manual feed timeout"); o->desc = SANE_I18N ("Sets the manual feed timeout in seconds"); o->type = SANE_TYPE_INT; o->unit = SANE_UNIT_NONE; o->size = sizeof (SANE_Int); o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &(byte_value_range); o->cap |= SANE_CAP_INACTIVE; s->val[FEED_TIMEOUT].w = 30; /* Double feed */ o = &s->opt[DBLFEED]; o->name = "double-feed"; o->title = SANE_I18N ("Double feed detection"); o->desc = SANE_I18N ("Enable/Disable double feed detection"); o->type = SANE_TYPE_BOOL; o->unit = SANE_UNIT_NONE; s->val[DBLFEED].w = SANE_FALSE; /* Fit to page */ o = &s->opt[FIT_TO_PAGE]; o->name = SANE_I18N ("fit-to-page"); o->title = SANE_I18N ("Fit to page"); o->desc = SANE_I18N ("Scanner shrinks image to fit scanned page"); o->type = SANE_TYPE_BOOL; o->unit = SANE_UNIT_NONE; s->val[FIT_TO_PAGE].w = SANE_FALSE; /* Geometry group */ o = &s->opt[GEOMETRY_GROUP]; o->title = SANE_I18N ("Geometry"); o->desc = ""; /* not valid for a group */ o->type = SANE_TYPE_GROUP; o->cap = 0; o->size = 0; o->constraint_type = SANE_CONSTRAINT_NONE; /* Paper sizes list */ o = &s->opt[PAPER_SIZE]; o->name = "paper-size"; o->title = SANE_I18N ("Paper size"); o->desc = SANE_I18N ("Physical size of the paper in the ADF"); o->type = SANE_TYPE_STRING; o->size = max_string_size (paper_list); o->constraint_type = SANE_CONSTRAINT_STRING_LIST; o->constraint.string_list = paper_list; s->val[PAPER_SIZE].s = malloc (o->size); strcpy (s->val[PAPER_SIZE].s, SANE_I18N ("A4")); /* Landscape */ o = &s->opt[LANDSCAPE]; o->name = "landscape"; o->title = SANE_I18N ("Landscape"); o->desc = SANE_I18N ("Set paper position : " "true for landscape, false for portrait"); o->type = SANE_TYPE_BOOL; o->unit = SANE_UNIT_NONE; s->val[LANDSCAPE].w = SANE_FALSE; o->cap |= SANE_CAP_INACTIVE; /* Upper left X */ o = &s->opt[TL_X]; o->name = SANE_NAME_SCAN_TL_X; o->title = SANE_TITLE_SCAN_TL_X; o->desc = SANE_DESC_SCAN_TL_X; o->type = SANE_TYPE_INT; o->unit = SANE_UNIT_MM; o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &tl_x_range; o->cap |= SANE_CAP_INACTIVE; s->val[TL_X].w = 0; /* Upper left Y */ o = &s->opt[TL_Y]; o->name = SANE_NAME_SCAN_TL_Y; o->title = SANE_TITLE_SCAN_TL_Y; o->desc = SANE_DESC_SCAN_TL_Y; o->type = SANE_TYPE_INT; o->unit = SANE_UNIT_MM; o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &tl_y_range; o->cap |= SANE_CAP_INACTIVE; s->val[TL_Y].w = 0; /* Bottom-right x */ o = &s->opt[BR_X]; o->name = SANE_NAME_SCAN_BR_X; o->title = SANE_TITLE_SCAN_BR_X; o->desc = SANE_DESC_SCAN_BR_X; o->type = SANE_TYPE_INT; o->unit = SANE_UNIT_MM; o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &br_x_range; o->cap |= SANE_CAP_INACTIVE; s->val[BR_X].w = 210; /* Bottom-right y */ o = &s->opt[BR_Y]; o->name = SANE_NAME_SCAN_BR_Y; o->title = SANE_TITLE_SCAN_BR_Y; o->desc = SANE_DESC_SCAN_BR_Y; o->type = SANE_TYPE_INT; o->unit = SANE_UNIT_MM; o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &br_y_range; o->cap |= SANE_CAP_INACTIVE; s->val[BR_Y].w = 297; /* Enhancement group */ o = &s->opt[ADVANCED_GROUP]; o->title = SANE_I18N ("Advanced"); o->desc = ""; /* not valid for a group */ o->type = SANE_TYPE_GROUP; o->cap = SANE_CAP_ADVANCED; o->size = 0; o->constraint_type = SANE_CONSTRAINT_NONE; /* Brightness */ o = &s->opt[BRIGHTNESS]; o->name = SANE_NAME_BRIGHTNESS; o->title = SANE_TITLE_BRIGHTNESS; o->desc = SANE_DESC_BRIGHTNESS; o->type = SANE_TYPE_INT; o->unit = SANE_UNIT_NONE; o->size = sizeof (SANE_Int); o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &(byte_value_range); s->val[BRIGHTNESS].w = 128; /* Contrast */ o = &s->opt[CONTRAST]; o->name = SANE_NAME_CONTRAST; o->title = SANE_TITLE_CONTRAST; o->desc = SANE_DESC_CONTRAST; o->type = SANE_TYPE_INT; o->unit = SANE_UNIT_NONE; o->size = sizeof (SANE_Int); o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &(byte_value_range); s->val[CONTRAST].w = 128; /* threshold */ o = &s->opt[THRESHOLD]; o->name = SANE_NAME_THRESHOLD; o->title = SANE_TITLE_THRESHOLD; o->desc = SANE_DESC_THRESHOLD; o->type = SANE_TYPE_INT; o->size = sizeof (SANE_Int); o->constraint_type = SANE_CONSTRAINT_RANGE; o->constraint.range = &(byte_value_range); s->val[THRESHOLD].w = 128; /* Image emphasis */ o = &s->opt[IMAGE_EMPHASIS]; o->name = "image-emphasis"; o->title = SANE_I18N ("Image emphasis"); o->desc = SANE_I18N ("Sets the image emphasis"); o->type = SANE_TYPE_STRING; o->size = max_string_size (image_emphasis_list); o->constraint_type = SANE_CONSTRAINT_STRING_LIST; o->constraint.string_list = image_emphasis_list; s->val[IMAGE_EMPHASIS].s = malloc (o->size); strcpy (s->val[IMAGE_EMPHASIS].s, image_emphasis_list[0]); /* Gamma */ o = &s->opt[GAMMA_CORRECTION]; o->name = "gamma-cor"; o->title = SANE_I18N ("Gamma correction"); o->desc = SANE_I18N ("Gamma correction"); o->type = SANE_TYPE_STRING; o->size = max_string_size (gamma_list); o->constraint_type = SANE_CONSTRAINT_STRING_LIST; o->constraint.string_list = gamma_list; s->val[GAMMA_CORRECTION].s = malloc (o->size); strcpy (s->val[GAMMA_CORRECTION].s, gamma_list[0]); /* Lamp color dropout */ o = &s->opt[LAMP]; o->name = "lamp-color"; o->title = SANE_I18N ("Lamp color"); o->desc = SANE_I18N ("Sets the lamp color (color dropout)"); o->type = SANE_TYPE_STRING; o->size = max_string_size (lamp_list); o->constraint_type = SANE_CONSTRAINT_STRING_LIST; o->constraint.string_list = lamp_list; s->val[LAMP].s = malloc (o->size); strcpy (s->val[LAMP].s, lamp_list[0]); } /* Lookup a string list from one array and return its index. */ static int str_index (const SANE_String_Const * list, SANE_String_Const name) { int index; index = 0; while (list[index]) { if (!strcmp (list[index], name)) return (index); index++; } return (-1); /* not found */ } /* Control option */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { int i; SANE_Status status; SANE_Word cap; struct scanner *s = (struct scanner *) handle; if (info) *info = 0; if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_UNSUPPORTED; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_UNSUPPORTED; if (action == SANE_ACTION_GET_VALUE) { if (s->opt[option].type == SANE_TYPE_STRING) { DBG (DBG_INFO, "sane_control_option: reading opt[%d] = %s\n", option, s->val[option].s); strcpy (val, s->val[option].s); } else { *(SANE_Word *) val = s->val[option].w; DBG (DBG_INFO, "sane_control_option: reading opt[%d] = %d\n", option, s->val[option].w); } return SANE_STATUS_GOOD; } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; if (s->opt[option].type == SANE_TYPE_STRING) { if (!strcmp (val, s->val[option].s)) return SANE_STATUS_GOOD; DBG (DBG_INFO, "sane_control_option: writing opt[%d] = %s\n", option, (SANE_String_Const) val); } else { if (*(SANE_Word *) val == s->val[option].w) return SANE_STATUS_GOOD; DBG (DBG_INFO, "sane_control_option: writing opt[%d] = %d\n", option, *(SANE_Word *) val); } switch (option) { /* Side-effect options */ case RESOLUTION: s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case TL_Y: if ((*(SANE_Word *) val) + MIN_LENGTH <= s->val[BR_Y].w) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } else if (info) *info |= SANE_INFO_INEXACT; return SANE_STATUS_GOOD; case BR_Y: if ((*(SANE_Word *) val) >= s->val[TL_Y].w + MIN_LENGTH) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } else if (info) *info |= SANE_INFO_INEXACT; return SANE_STATUS_GOOD; case TL_X: if ((*(SANE_Word *) val) + MIN_WIDTH <= s->val[BR_X].w) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } else if (info) *info |= SANE_INFO_INEXACT; return SANE_STATUS_GOOD; case BR_X: if (*(SANE_Word *) val >= s->val[TL_X].w + MIN_WIDTH) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } else if (info) *info |= SANE_INFO_INEXACT; return SANE_STATUS_GOOD; case LANDSCAPE: s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; /* Side-effect free options */ case CONTRAST: case BRIGHTNESS: case DUPLEX: case LENGTHCTL: case DBLFEED: case FIT_TO_PAGE: case THRESHOLD: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case FEED_TIMEOUT: s->val[option].w = *(SANE_Word *) val; return kvs20xx_set_timeout (s, s->val[option].w); /* String mode */ case IMAGE_EMPHASIS: case GAMMA_CORRECTION: case LAMP: case FEEDER_MODE: strcpy (s->val[option].s, val); return SANE_STATUS_GOOD; case MODE: strcpy (s->val[MODE].s, val); if (!strcmp (s->val[MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) { s->opt[THRESHOLD].cap &= ~SANE_CAP_INACTIVE; s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE; s->opt[BRIGHTNESS].cap |= SANE_CAP_INACTIVE; } else { s->opt[THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[GAMMA_CORRECTION].cap &= ~SANE_CAP_INACTIVE; s->opt[BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case MANUALFEED: strcpy (s->val[option].s, val); if (strcmp (s->val[option].s, manual_feed_list[0]) == 0) /* off */ s->opt[FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE; else s->opt[FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case PAPER_SIZE: strcpy (s->val[PAPER_SIZE].s, val); i = str_index (paper_list, s->val[PAPER_SIZE].s); if (i == 0) { /*user def */ s->opt[TL_X].cap &= s->opt[TL_Y].cap &= s->opt[BR_X].cap &= s->opt[BR_Y].cap &= ~SANE_CAP_INACTIVE; s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE; s->val[LANDSCAPE].w = 0; } else { s->opt[TL_X].cap |= s->opt[TL_Y].cap |= s->opt[BR_X].cap |= s->opt[BR_Y].cap |= SANE_CAP_INACTIVE; if (i == 3 || i == 4 || i == 7) { /*A5, A6 or B6 */ s->opt[LANDSCAPE].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE; s->val[LANDSCAPE].w = 0; } } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; } } return SANE_STATUS_UNSUPPORTED; } static inline unsigned mm2scanner_units (unsigned mm) { return mm * 12000 / 254; } static inline unsigned scanner_units2mm (unsigned u) { return u * 254 / 12000; } void kvs20xx_init_window (struct scanner *s, struct window *wnd, int wnd_id) { int paper = str_index (paper_list, s->val[PAPER_SIZE].s); memset (wnd, 0, sizeof (struct window)); wnd->window_descriptor_block_length = cpu2be16 (64); wnd->window_identifier = wnd_id; wnd->x_resolution = cpu2be16 (s->val[RESOLUTION].w); wnd->y_resolution = cpu2be16 (s->val[RESOLUTION].w); if (!paper) { wnd->upper_left_x = cpu2be32 (mm2scanner_units (s->val[TL_X].w)); wnd->upper_left_y = cpu2be32 (mm2scanner_units (s->val[TL_Y].w)); wnd->width = cpu2be32 (mm2scanner_units (s->val[BR_X].w - s->val[TL_X].w)); wnd->length = cpu2be32 (mm2scanner_units (s->val[BR_Y].w - s->val[TL_Y].w)); } else { u32 w = cpu2be32 (mm2scanner_units (paper_sizes[paper].width)); u32 h = cpu2be32 (mm2scanner_units (paper_sizes[paper].height)); wnd->upper_left_x = cpu2be32 (mm2scanner_units (0)); wnd->upper_left_y = cpu2be32 (mm2scanner_units (0)); if (!s->val[LANDSCAPE].b) { wnd->document_width = wnd->width = w; wnd->document_length = wnd->length = h; } else { wnd->document_width = wnd->width = h; wnd->document_length = wnd->length = w; } } wnd->brightness = s->val[BRIGHTNESS].w; wnd->threshold = s->val[THRESHOLD].w; wnd->contrast = s->val[CONTRAST].w; wnd->image_composition = mode_val[str_index (mode_list, s->val[MODE].s)]; wnd->bit_per_pixel = bps_val[str_index (mode_list, s->val[MODE].s)]; wnd->halftone_pattern = 0; /*Does not supported */ wnd->bit_ordering = cpu2be16 (BIT_ORDERING); wnd->compression_type = 0; /*Does not supported */ wnd->compression_argument = 0; /*Does not supported */ wnd->vendor_unique_identifier = 0; wnd->nobuf_fstspeed_dfstop = 0; wnd->mirror_image = 0; wnd->image_emphasis = str_index (image_emphasis_list, s->val[IMAGE_EMPHASIS].s); wnd->gamma_correction = gamma_val[str_index (gamma_list, s->val[GAMMA_CORRECTION].s)]; wnd->mcd_lamp_dfeed_sens = str_index (lamp_list, s->val[LAMP].s) << 4 | 2; wnd->document_size = (paper != 0) << 7 | s->val[LENGTHCTL].b << 6 | s->val[LANDSCAPE].b << 4 | paper_val[paper]; wnd->ahead_deskew_dfeed_scan_area_fspeed_rshad = s->val[DBLFEED].b << 4 | s->val[FIT_TO_PAGE].b << 2; wnd->continuous_scanning_pages = str_index (feeder_mode_list, s->val[FEEDER_MODE]. s) ? 0xff : 0; wnd->automatic_threshold_mode = 0; /*Does not supported */ wnd->automatic_separation_mode = 0; /*Does not supported */ wnd->standard_white_level_mode = 0; /*Does not supported */ wnd->b_wnr_noise_reduction = 0; /*Does not supported */ if (str_index (manual_feed_list, s->val[MANUALFEED].s) == 2) wnd->mfeed_toppos_btmpos_dsepa_hsepa_dcont_rstkr = 2 << 6; wnd->stop_mode = 1; } /* Get scan parameters */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { struct scanner *s = (struct scanner *) handle; SANE_Parameters *p = &s->params; if (!s->scanning) { unsigned w, h, res = s->val[RESOLUTION].w; unsigned i = str_index (paper_list, s->val[PAPER_SIZE].s); if (i) { if (s->val[LANDSCAPE].b) { w = paper_sizes[i].height; h = paper_sizes[i].width; } else { w = paper_sizes[i].width; h = paper_sizes[i].height; } } else { w = s->val[BR_X].w - s->val[TL_X].w; h = s->val[BR_Y].w - s->val[TL_Y].w; } p->pixels_per_line = w * res / 25.4; p->lines = h * res / 25.4; } p->format = (!strcmp(s->val[MODE].s,SANE_VALUE_SCAN_MODE_COLOR)) ? SANE_FRAME_RGB : SANE_FRAME_GRAY; p->last_frame = SANE_TRUE; p->depth = bps_val[str_index (mode_list, s->val[MODE].s)]; p->bytes_per_line = p->depth * p->pixels_per_line / 8; if (p->depth > 8) p->depth = 8; if (params) memcpy (params, p, sizeof (SANE_Parameters)); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/umax-uc1200se.c0000664000175000017500000001052412112021330015152 00000000000000 /* ------------------------------------------------------------------------- */ /* umax-uc1200se.c: inquiry for UMAX scanner uc1200se (C) 1998-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------- */ #include "umax-scanner.h" /* ------------------------------------------------------------------------- */ static unsigned char UC1200SE_INQUIRY[] = { #define UC1200SE_INQUIRY_LEN 0x9d /* 24 F/W support function */ 0x03, /* 25 -27 exposure-times */ 0x00, 0x00, 0x00, /* 28 - 29 reserved */ 0x00, 0x00, /* 2a - 35 exposure times */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 37 reserved */ 0x00, 0x00, /* 38 - 5f scsi reserved */ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, /* 60 -62 scanner capability*/ 0x3e, 0x0c, 0x03, /* 63 reserved */ 0x00, /* 64 gamma */ 0x83, /* 65 reserved */ 0x00, /* 66 GIB */ 0x04, /* 67 reserved */ 0x00, /* 68 GOB */ 0x01, /* 69 - 6a halftone */ 0x00, 0x2f, /* 6b - 6c reserved */ 0x00, 0x00, /* 6d color sequence */ 0xe1, /* 0xe8, 0xe9 or 0xe1 ? */ /* 6e - 71 video memory */ 0x00, 0x20, 0x00, 0x00, /* 72 reserved */ 0x00, /* 73 max optical res in 100 dpi */ 0x06, /* 74 max x_res in 100 dpi */ 0x06, /* 75 max y_res in 100 dpi */ 0x0c, /* 76-77 fb max scan width in 0.01 inch */ 0x03, 0x20, /* 78-79 fb max scan length in 0.01 inch */ 0x04, 0x4c, /* 7a-7b uta x original point, may be 0x05, 0x89 */ 0x00, 0x76, /* 7c-7d uta y original point, may be 0x06, 0x75 */ 0x00, 0x89, /* 7e-7f uta max scan width in 0.01 inch */ 0x02, 0x4e, /* 80-81 uta max scan length in 0.01 inch */ 0x03, 0x65, /* 82-85 reserved */ 00, 00, 00, 00, /* 86-87 dor x original point */ 0x00, 0x00, /* 88-89 dor x original point */ 0x00, 0x00, /* 8a-8b dor max scan width in 0.01 inch */ 0x00, 0x00, /* 8c-8d dor max scan length in 0.01 inch */ 0x00, 0x00, /* 8e reserved */ 0x00, /* 8f last calibration lamp density */ 0x00, /* 90 reserved */ 0x00, /* 91 lamp warmup max time */ 0x00, /* 92-93 window descriptor block length */ 0x00, 0x31, /* 94 optical resolution residue (1dpi) */ 0x00, /* 95 x_resolution residue (1dpi) */ 0x00, /* 96 y_resolution residue (1dpi) */ 0x00, /* 97 analog gamma table */ 0x00, /* 98-99 reserved */ 0x00, 0x00, /* 9a max calibration data lines */ 0x00, /* 9b fb/uta colour-sequnce-mode */ 0x01, /* 9c adf colour-sequnce-mode */ 0x01, /* 9d line-distance of ccd */ 0x08 }; static inquiry_blk inquiry_uc1200se = { "UC1200SE ",UC1200SE_INQUIRY, UC1200SE_INQUIRY_LEN }; sane-backends-1.0.27/backend/canon630u-common.c0000664000175000017500000013256112775312260015774 00000000000000/* (c) 2001,2002 Nathan Rutman nathan@gordian.com 10/17/01 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* Communication, calibration, and scanning with the Canon CanoScan FB630U flatbed scanner under linux. Reworked into SANE-compatible format. The usb-parallel port interface chip is GL640usb, on the far side of which is an LM9830 parallel-port scanner-on-a-chip. This code has not been tested on anything other than Linux/i386. */ #include #include /* open */ #include #include #include #include /* usleep */ #include #include /* exp() */ #ifdef HAVE_OS2_H #include /* mode_t */ #endif #include #include "lm9830.h" #define USB_TYPE_VENDOR (0x02 << 5) #define USB_RECIP_DEVICE 0x00 #define USB_DIR_OUT 0x00 #define USB_DIR_IN 0x80 /* Assign status and verify a good return code */ #define CHK(A) {if( (status = A) != SANE_STATUS_GOOD ) { \ DBG( 1, "Failure on line of %s: %d\n", __FILE__, \ __LINE__ ); return A; }} typedef SANE_Byte byte; /***************************************************** GL640 communication primitives Provides I/O routines to Genesys Logic GL640USB USB-IEEE1284 parallel port bridge. Used in HP3300c, Canon FB630u. ******************************************************/ /* Register codes for the bridge. These are NOT the registers for the scanner chip on the other side of the bridge. */ typedef enum { GL640_BULK_SETUP = 0x82, GL640_EPP_ADDR = 0x83, GL640_EPP_DATA_READ = 0x84, GL640_EPP_DATA_WRITE = 0x85, GL640_SPP_STATUS = 0x86, GL640_SPP_CONTROL = 0x87, GL640_SPP_DATA = 0x88, GL640_GPIO_OE = 0x89, GL640_GPIO_READ = 0x8a, GL640_GPIO_WRITE = 0x8b } GL640_Request; /* Write to the usb-parallel port bridge. */ static SANE_Status gl640WriteControl (int fd, GL640_Request req, byte * data, unsigned int size) { SANE_Status status; status = sanei_usb_control_msg (fd, /* rqttype */ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT /*0x40? */ , /* rqt */ (size > 1) ? 0x04 : 0x0C, /* val */ (SANE_Int) req, /* ind */ 0, /* len */ size, /* dat */ data); if (status != SANE_STATUS_GOOD) DBG (1, "gl640WriteControl error\n"); return status; } /* Read from the usb-parallel port bridge. */ static SANE_Status gl640ReadControl (int fd, GL640_Request req, byte * data, unsigned int size) { SANE_Status status; status = sanei_usb_control_msg (fd, /* rqttype */ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN /*0xc0? */ , /* rqt */ (size > 1) ? 0x04 : 0x0C, /* val */ (SANE_Int) req, /* ind */ 0, /* len */ size, /* dat */ data); if (status != SANE_STATUS_GOOD) DBG (1, "gl640ReadControl error\n"); return status; } /* Wrappers to read or write a single byte to the bridge */ static inline SANE_Status gl640WriteReq (int fd, GL640_Request req, byte data) { return gl640WriteControl (fd, req, &data, 1); } static inline SANE_Status gl640ReadReq (int fd, GL640_Request req, byte * data) { return gl640ReadControl (fd, req, data, 1); } /* Write USB bulk data setup is an apparently scanner-specific sequence: {(0=read, 1=write), 0x00, 0x00, 0x00, sizelo, sizehi, 0x00, 0x00} hp3400: setup[1] = 0x01 fb630u: setup[2] = 0x80 */ static SANE_Status gl640WriteBulk (int fd, byte * setup, byte * data, size_t size) { SANE_Status status; setup[0] = 1; setup[4] = (size) & 0xFF; setup[5] = (size >> 8) & 0xFF; CHK (gl640WriteControl (fd, GL640_BULK_SETUP, setup, 8)); status = sanei_usb_write_bulk (fd, data, &size); if (status != SANE_STATUS_GOOD) DBG (1, "gl640WriteBulk error\n"); return status; } /* Read USB bulk data setup is an apparently scanner-specific sequence: {(0=read, 1=write), 0x00, 0x00, 0x00, sizelo, sizehi, 0x00, 0x00} fb630u: setup[2] = 0x80 */ static SANE_Status gl640ReadBulk (int fd, byte * setup, byte * data, size_t size) { SANE_Status status; setup[0] = 0; setup[4] = (size) & 0xFF; setup[5] = (size >> 8) & 0xFF; CHK (gl640WriteControl (fd, GL640_BULK_SETUP, setup, 8)); status = sanei_usb_read_bulk (fd, data, &size); if (status != SANE_STATUS_GOOD) DBG (1, "gl640ReadBulk error\n"); return status; } /***************************************************** LM9830 communication primitives parallel-port scanner-on-a-chip. ******************************************************/ /* write 1 byte to a LM9830 register address */ static SANE_Status write_byte (int fd, byte addr, byte val) { SANE_Status status; DBG (14, "write_byte(fd, 0x%02x, 0x%02x);\n", addr, val); CHK (gl640WriteReq (fd, GL640_EPP_ADDR, addr)); CHK (gl640WriteReq (fd, GL640_EPP_DATA_WRITE, val)); return status; } /* read 1 byte from a LM9830 register address */ static SANE_Status read_byte (int fd, byte addr, byte * val) { SANE_Status status; CHK (gl640WriteReq (fd, GL640_EPP_ADDR, addr)); CHK (gl640ReadReq (fd, GL640_EPP_DATA_READ, val)); DBG (14, "read_byte(fd, 0x%02x, &result); /* got %02x */\n", addr, *val); return status; } static byte bulk_setup_data[] = { 0, 0, 0x80, 0, 0, 0, 0, 0 }; /* Bulk write */ static SANE_Status write_bulk (int fd, unsigned int addr, void *src, size_t count) { SANE_Status status; DBG (13, "write_bulk(fd, 0x%02x, buf, 0x%04lx);\n", addr, (u_long) count); if (!src) { DBG (1, "write_bulk: bad src\n"); return SANE_STATUS_INVAL; } /* destination address */ CHK (gl640WriteReq (fd, GL640_EPP_ADDR, addr)); /* write */ CHK (gl640WriteBulk (fd, bulk_setup_data, src, count)); return status; } /* Bulk read */ static SANE_Status read_bulk (int fd, unsigned int addr, void *dst, size_t count) { SANE_Status status; DBG (13, "read_bulk(fd, 0x%02x, buf, 0x%04lx);\n", addr, (u_long) count); if (!dst) { DBG (1, "read_bulk: bad dest\n"); return SANE_STATUS_INVAL; } /* destination address */ CHK (gl640WriteReq (fd, GL640_EPP_ADDR, addr)); /* read */ CHK (gl640ReadBulk (fd, bulk_setup_data, dst, count)); return status; } /***************************************************** useful macro routines ******************************************************/ /* write a 16-bit int to two sequential registers */ static SANE_Status write_word (int fd, unsigned int addr, unsigned int data) { SANE_Status status; /* MSB */ CHK (write_byte (fd, addr, (data >> 8) & 0xff)); /* LSB */ CHK (write_byte (fd, addr + 1, data & 0xff)); return status; } /* write multiple bytes, one at a time (non-bulk) */ static SANE_Status write_many (int fd, unsigned int addr, const byte *src, size_t count) { SANE_Status status; size_t i; DBG (14, "multi write %lu\n", (u_long) count); for (i = 0; i < count; i++) { DBG (15, " %04lx:%02x", (u_long) (addr + i), src[i]); status = write_byte (fd, addr + i, src[i]); if (status != SANE_STATUS_GOOD) { DBG (15, "\n"); return status; } } DBG (15, "\n"); return SANE_STATUS_GOOD; } /* read multiple bytes, one at a time (non-bulk) */ static SANE_Status read_many (int fd, unsigned int addr, void *dst, size_t count) { SANE_Status status; size_t i; byte val; DBG (14, "multi read %lu\n", (u_long) count); for (i = 0; i < count; i++) { status = read_byte (fd, addr + i, &val); ((byte *) dst)[i] = val; DBG (15, " %04lx:%02x", (u_long) (addr + i), ((byte *) dst)[i]); /* on err, return number of success */ if (status != SANE_STATUS_GOOD) { DBG (15, "\n"); return status; } } DBG (15, "\n"); return SANE_STATUS_GOOD; } /* Poll addr until result & mask = val */ static int read_poll_flag (int fd, unsigned int addr, unsigned int mask, unsigned int val) { SANE_Status status; byte result = 0; time_t start_time = time (NULL); DBG (12, "read_poll_flag...\n"); do { status = read_byte (fd, addr, &result); if (status != SANE_STATUS_GOOD) return -1; /* Give it a minute */ if ((time (NULL) - start_time) > 60) { DBG (1, "read_poll_flag: timed out (%d)\n", result); return -1; } usleep (100000); } while ((result & mask) != val); return result; } /* Keep reading addr until results >= min */ static int read_poll_min (int fd, unsigned int addr, unsigned int min) { SANE_Status status; byte result; time_t start_time = time (NULL); DBG (12, "waiting...\n"); do { status = read_byte (fd, addr, &result); if (status != SANE_STATUS_GOOD) return -1; /* Give it a minute */ if ((time (NULL) - start_time) > 60) { DBG (1, "read_poll_min: timed out (%d < %d)\n", result, min); return -1; } /* no sleep here, or calibration gets unhappy. */ } while (result < min); return result; } /* Bulk read "ks" kilobytes + "remainder" bytes of data, to a buffer if the buffer is valid. */ static int read_bulk_size (int fd, int ks, int remainder, byte * dest, int destsize) { byte *buf; int bytes = (ks - 1) * 1024 + remainder; int dropdata = ((dest == 0) || (destsize < bytes)); if (bytes < 0) { DBG (1, "read_bulk_size: invalid size %02x (%d)\n", ks, bytes); return -1; } if (destsize && (destsize < bytes)) { DBG (3, "read_bulk_size: more data than buffer (%d/%d)\n", destsize, bytes); bytes = destsize; } if (bytes == 0) return 0; if (dropdata) { buf = malloc (bytes); DBG (3, " ignoring data "); } else buf = dest; read_bulk (fd, 0x00, buf, bytes); if (dropdata) free (buf); return bytes; } /***************************************************** fb630u calibration and scan ******************************************************/ /* data structures and constants */ typedef struct CANON_Handle { int fd; /* scanner fd */ int x1, x2, y1, y2; /* in pixels, 600 dpi */ int width, height; /* at scan resolution */ int resolution; /* dpi */ char *fname; /* output file name */ FILE *fp; /* output file pointer (for reading) */ char *buf, *ptr; /* data buffer */ unsigned char gain; /* static analog gain, 0 - 31 */ double gamma; /* gamma correction */ int flags; #define FLG_GRAY 0x01 /* grayscale */ #define FLG_FORCE_CAL 0x02 /* force calibration */ #define FLG_BUF 0x04 /* save scan to buffer instead of file */ #define FLG_NO_INTERLEAVE 0x08 /* don't interleave r,g,b pixels; leave them in row format */ #define FLG_PPM_HEADER 0x10 /* include PPM header in scan file */ } CANON_Handle; /* offset/gain calibration file name */ #define CAL_FILE_OGN "/tmp/canon.cal" /* at 600 dpi */ #define CANON_MAX_WIDTH 5100 /* 8.5in */ /* this may not be right */ #define CANON_MAX_HEIGHT 7000 /* 11.66in */ /* scanline end-of-line data byte, returned after each r,g,b segment, specific to the FB630u */ #define SCANLINE_END 0x0c static const byte seq002[] = { /*r08 */ 0x04, /*300 dpi */ 0x1a, 0x00, 0x0d, 0x4c, 0x2f, 0x00, 0x01, /*r10 */ 0x07, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x25, 0x00, 0x4b, /*r20 */ 0x15, 0xe0, /*data px start */ 0x00, 0x4b, /*data px end */ 0x14, 0x37, 0x15, 0x00 }; static const byte seq003[] = { 0x02, 0x00, 0x00, /*lights out */ 0x03, 0xff, 0x00, 0x01, 0x03, 0xff, 0x00, 0x01, 0x03, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1d, 0x00, 0x13, 0x04, 0x1a, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x57, 0x02, 0x00, 0x3c, 0x35, 0x94, 0x00, 0x10, 0x08, 0x3f, 0x2b, 0x91, 0x00, 0x00, 0x01, 0x00, 0x80, 0x00 }; /* Scanner init, called at calibration and scan time. Returns 1 if this was the first time the scanner was plugged in, 0 afterward, and -1 on error. */ static int init (int fd) { byte result, rv; if (gl640WriteReq (fd, GL640_GPIO_OE, 0x71) != SANE_STATUS_GOOD) { DBG(1, "Initial write request failed.\n"); return -1; } /* Gets 0x04 or 0x05 first run, gets 0x64 subsequent runs. */ if (gl640ReadReq (fd, GL640_GPIO_READ, &rv) != SANE_STATUS_GOOD) { DBG(1, "Initial read request failed.\n"); return -1; } gl640WriteReq (fd, GL640_GPIO_OE, 0x70); DBG (2, "init query: %x\n", rv); if (rv != 0x64) { gl640WriteReq (fd, GL640_GPIO_WRITE, 0x00); gl640WriteReq (fd, GL640_GPIO_WRITE, 0x40); } gl640WriteReq (fd, GL640_SPP_DATA, 0x99); gl640WriteReq (fd, GL640_SPP_DATA, 0x66); gl640WriteReq (fd, GL640_SPP_DATA, 0xcc); gl640WriteReq (fd, GL640_SPP_DATA, 0x33); /* parallel port setting */ write_byte (fd, PARALLEL_PORT, 0x06); /* sensor control settings */ write_byte (fd, 0x0b, 0x0d); write_byte (fd, 0x0c, 0x4c); write_byte (fd, 0x0d, 0x2f); read_byte (fd, 0x0b, &result); /* wants 0d */ read_byte (fd, 0x0c, &result); /* wants 4c */ read_byte (fd, 0x0d, &result); /* wants 2f */ /* parallel port noise filter */ write_byte (fd, 0x70, 0x73); DBG (2, "init post-reset: %x\n", rv); /* Returns 1 if this was the first time the scanner was plugged in. */ return (rv != 0x64); } /* Turn off the lamps */ static void lights_out (int fd) { write_word (fd, LAMP_R_ON, 0x3fff); write_word (fd, LAMP_R_OFF, 0x0001); write_word (fd, LAMP_G_ON, 0x3fff); write_word (fd, LAMP_G_OFF, 0x0001); write_word (fd, LAMP_B_ON, 0x3fff); write_word (fd, LAMP_B_OFF, 0x0001); } /* Do the scan and save the resulting image as r,g,b interleaved PPM file. */ static SANE_Status do_scan (CANON_Handle * s) { SANE_Status status = SANE_STATUS_GOOD; int numbytes, datasize, level = 0, line = 0, pixel = 0; byte *buf, *ptr, *redptr; FILE *fp; #define BUFSIZE 0xf000 buf = malloc (BUFSIZE); if (!buf) return SANE_STATUS_NO_MEM; if (s->flags & FLG_BUF) { /* read the whole thing into buf */ if (!s->buf) return SANE_STATUS_NO_MEM; s->ptr = s->buf; fp = NULL; } else { fp = fopen (s->fname, "w"); if (!fp) { free (buf); DBG (1, "err:%s when opening %s\n", strerror (errno), s->fname); return SANE_STATUS_IO_ERROR; } } if (fp && (s->flags & FLG_PPM_HEADER)) /* PPM format header */ fprintf (fp, "P6\n%d %d\n255\n", s->width, s->height); /* lights off */ write_byte (s->fd, COMMAND, 0x08); /* lights on */ write_byte (s->fd, COMMAND, 0x00); /* begin scan */ write_byte (s->fd, COMMAND, 0x03); ptr = redptr = buf; while (line < s->height) { datasize = read_poll_min (s->fd, IMAGE_DATA_AVAIL, 2); if (datasize < 0) { DBG (1, "no data\n"); break; } DBG (12, "scan line %d %dk\n", line, datasize - 1); /* Read may cause scan head to move */ numbytes = read_bulk_size (s->fd, datasize, 0, ptr, BUFSIZE - level); if (numbytes < 0) { status = SANE_STATUS_INVAL; break; } /* Data coming back is "width" bytes Red data followed by 0x0c, width bytes Green, 0x0c, width bytes Blue, 0x0c, repeat for "height" lines. */ if (s->flags & FLG_NO_INTERLEAVE) { /* number of full lines */ line += (numbytes + level) / (s->width * 3); /* remainder (partial line) */ level = (numbytes + level) % (s->width * 3); /* but if last line, don't store extra */ if (line >= s->height) numbytes -= (line - s->height) * s->width * 3 + level; if (fp) fwrite (buf, 1, numbytes, fp); else { memcpy (s->ptr, buf, numbytes); s->ptr += numbytes; } } else { /* Contorsions to convert data from line-by-line RGB to byte-by-byte RGB, without reading in the whole buffer first. We use the sliding window redptr with the temp buffer buf. */ ptr += numbytes; /* point to the end of data */ /* while we have RGB triple data */ while (redptr + s->width + s->width <= ptr) { if (*redptr == SCANLINE_END) DBG (13, "-%d- ", pixel); if (fp) { /* for PPM binary (P6), 3-byte RGB pixel */ fwrite (redptr, 1, 1, fp); /* Red */ fwrite (redptr + s->width, 1, 1, fp); /* Green */ fwrite (redptr + s->width + s->width, 1, 1, fp); /* Blue */ /* for PPM ascii (P3) fprintf(fp, "%3d %3d %3d\n", *redptr, *(redptr + s->width), *(redptr + s->width + s->width)); */ } else { /* R */ *s->ptr = *redptr; s->ptr++; /* G */ *s->ptr = *(redptr + s->width); s->ptr++; /* B */ *s->ptr = *(redptr + s->width + s->width); s->ptr++; } redptr++; pixel++; if (pixel && !(pixel % s->width)) { /* end of a line, move redptr to the next Red section */ line++; redptr += s->width + s->width; #if 0 /* progress */ printf ("%2d%%\r", line * 100 / s->height); fflush (stdout); #endif /* don't record any extra */ if (line >= s->height) break; } } /* keep the extra around for next time */ level = ptr - redptr; if (level < 0) level = 0; memmove (buf, redptr, level); ptr = buf + level; redptr = buf; } } if (fp) { fclose (fp); DBG (6, "created scan file %s\n", s->fname); } free (buf); DBG (6, "%d lines, %d pixels, %d extra bytes\n", line, pixel, level); /* motor off */ write_byte (s->fd, COMMAND, 0x00); return status; } static int wait_for_return (int fd) { return read_poll_flag (fd, STATUS, STATUS_HOME, STATUS_HOME); } static SANE_Status compute_ogn (char *calfilename); /* This is the calibration rountine Win2k goes through when the scanner is first plugged in. Original usb trace from Win2k with USBSnoopy ("usb sniffer for w2k" http://benoit.papillault.free.fr/speedtouch/sniff-2000.en.php3) */ static int plugin_cal (CANON_Handle * s) { SANE_Status status; unsigned int temp; byte result; byte *buf; int fd = s->fd; DBG (6, "Calibrating\n"); /* reserved? */ read_byte (fd, 0x69, &result); /* wants 02 */ /* parallel port setting */ write_byte (fd, PARALLEL_PORT, 0x06); write_many (fd, 0x08, seq002, sizeof (seq002)); /* addr 0x28 isn't written */ write_many (fd, 0x29, seq003, sizeof (seq003)); /* Verification */ buf = malloc (0x400); read_many (fd, 0x08, buf, sizeof (seq002)); if (memcmp (seq002, buf, sizeof (seq002))) DBG (1, "seq002 verification error\n"); /* addr 0x28 isn't read */ read_many (fd, 0x29, buf, sizeof (seq003)); if (memcmp (seq003, buf, sizeof (seq003))) DBG (1, "seq003 verification error\n"); /* parallel port noise filter */ write_byte (fd, 0x70, 0x73); lights_out (fd); /* Home motor */ read_byte (fd, STATUS, &result); /* wants 2f or 2d */ if (!(result & STATUS_HOME) /*0x2d */ ) write_byte (fd, COMMAND, 0x02); wait_for_return (fd); /* Motor forward */ write_byte (fd, COMMAND, 0x01); usleep (600000); read_byte (fd, STATUS, &result); /* wants 0c or 2c */ read_byte (fd, STATUS, &result); /* wants 0c */ /* Return home */ write_byte (fd, COMMAND, 0x02); /* Gamma tables */ /* Linear gamma */ for (temp = 0; temp < 0x0400; temp++) buf[temp] = temp / 4; /* Gamma Red */ write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 0x0400); /* Gamma Green */ write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 0x0400); /* Gamma Blue */ write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 0x0400); /* Read back gamma tables. I suppose I should check results... */ /* Gamma Red */ write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_READ); read_bulk (fd, DATAPORT, buf, 0x0400); /* Gamma Green */ write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_READ); read_bulk (fd, DATAPORT, buf, 0x0400); /* Gamma Blue */ write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_READ); read_bulk (fd, DATAPORT, buf, 0x0400); free (buf); /* Make sure STATUS_HOME */ read_byte (fd, STATUS, &result); /* wants 0e */ /* stepper forward */ write_byte (fd, COMMAND, 0x01); read_byte (fd, STATUS, &result); /* wants 0c */ /* not sure if this rigid read/write pattern is required */ read_byte (fd, CLOCK_DIV, &result); /* wants 04 */ write_byte (fd, CLOCK_DIV, 0x04); read_byte (fd, STEP_SIZE, &result); /* wants 04 */ write_byte (fd, STEP_SIZE, 0x3f); read_byte (fd, 0x47, &result); /* wants 1a */ write_byte (fd, 0x47, 0xff); read_byte (fd, FAST_STEP, &result); /* wants 01 */ write_byte (fd, FAST_STEP, 0x01); read_byte (fd, 0x49, &result); /* wants 04 */ write_byte (fd, 0x49, 0x04); read_byte (fd, SKIP_STEPS, &result); /* wants 00 */ write_byte (fd, SKIP_STEPS, 0x00); read_byte (fd, 0x4b, &result); /* wants 00 */ write_byte (fd, 0x4b, 0xc8); read_byte (fd, BUFFER_LIMIT, &result); /* wants 57 */ write_byte (fd, BUFFER_LIMIT, 0x04); read_byte (fd, BUFFER_RESUME, &result); /* wants 02 */ write_byte (fd, BUFFER_RESUME, 0x02); read_byte (fd, REVERSE_STEPS, &result); /* wants 00 */ write_byte (fd, REVERSE_STEPS, 0x00); write_byte (fd, STEP_PWM, 0x1f); /* Reset motor */ write_byte (fd, COMMAND, 0x08); write_byte (fd, COMMAND, 0x00); /* Scan */ write_byte (fd, COMMAND, 0x03); /* Wants 02 or 03, gets a bunch of 0's first */ read_poll_min (fd, IMAGE_DATA_AVAIL, 2); write_byte (fd, COMMAND, 0x00); write_byte (fd, STEP_PWM, 0x3f); write_byte (fd, CLOCK_DIV, 0x04); /* 300 dpi */ write_word (fd, STEP_SIZE, 0x041a); write_word (fd, FAST_STEP, 0x0104); /* Don't skip the black/white calibration area at the bottom of the scanner. */ write_word (fd, SKIP_STEPS, 0x0000); write_byte (fd, BUFFER_LIMIT, 0x57); write_byte (fd, BUFFER_RESUME, 0x02); write_byte (fd, REVERSE_STEPS, 0x00); write_byte (fd, BUFFER_LIMIT, 0x09); write_byte (fd, STEP_PWM, 0x1f); read_byte (fd, MICROSTEP, &result); /* wants 13, active */ write_byte (fd, MICROSTEP, 0x03 /* tristate */ ); /* Calibration data taken under 3 different lighting conditions */ /* dark */ write_word (fd, LAMP_R_ON, 0x0017); write_word (fd, LAMP_R_OFF, 0x0100); write_word (fd, LAMP_G_ON, 0x0017); write_word (fd, LAMP_G_OFF, 0x0100); write_word (fd, LAMP_B_ON, 0x0017); write_word (fd, LAMP_B_OFF, 0x0100); /* coming in, we've got 300dpi, data px start : 0x004b data px end : 0x1437 for a total of 5100(13ec) 600-dpi pixels, (8.5 inches) or 2550 300-dpi pixels (7653 bytes). Interestingly, the scan head never moves, no matter how many rows are read. */ s->width = 2551; s->height = 1; s->flags = FLG_BUF | FLG_NO_INTERLEAVE; s->buf = malloc (s->width * s->height * 3); /* FIXME do something with this data */ CHK (do_scan (s)); /* Lighting */ /* medium */ write_word (fd, LAMP_R_ON, 0x0017); write_word (fd, LAMP_R_OFF, 0x0200); write_word (fd, LAMP_G_ON, 0x0017); write_word (fd, LAMP_G_OFF, 0x01d7 /* also 01db */ ); write_word (fd, LAMP_B_ON, 0x0017); write_word (fd, LAMP_B_OFF, 0x01af /* also 01b2 */ ); /* FIXME do something with this data */ CHK (do_scan (s)); /* Lighting */ /* bright */ write_word (fd, LAMP_R_ON, 0x0017); write_word (fd, LAMP_R_OFF, 0x0e8e /* also 1040 */ ); write_word (fd, LAMP_G_ON, 0x0017); write_word (fd, LAMP_G_OFF, 0x0753 /* also 0718 */ ); write_word (fd, LAMP_B_ON, 0x0017); write_word (fd, LAMP_B_OFF, 0x03f8 /* also 040d */ ); /* FIXME do something with this data */ CHK (do_scan (s)); free (s->buf); s->buf = NULL; /* The trace gets a little iffy from here on out since the log files are missing different urb's. This is kind of a puzzled-out compilation. */ write_byte (fd, MICROSTEP, 0x13 /* pins active */ ); write_byte (fd, STEP_PWM, 0x3f); read_byte (fd, STATUS, &result); /* wants 0c */ /* Stepper home */ write_byte (fd, COMMAND, 0x02); /* Step size */ write_word (fd, STEP_SIZE, 0x041a /* 300 dpi */ ); /* Skip steps */ write_word (fd, SKIP_STEPS, 0x0000); /* Pause buffer levels */ write_byte (fd, BUFFER_LIMIT, 0x57); /* Resume buffer levels */ write_byte (fd, BUFFER_RESUME, 0x02); wait_for_return (fd); /* stepper forward small */ write_byte (fd, COMMAND, 0x01); read_byte (fd, STATUS, &result); /* wants 0c */ usleep (200000); write_byte (fd, STEP_PWM, 0x1f); /* Read in cal strip at bottom of scanner (to adjust gain/offset tables. Note that this isn't the brightest lighting condition.) At 300 dpi: black rows 0-25; white rows 30-75; beginning of glass 90. This produces 574k of data, so save it to a temp file. */ if (!s->fname) { DBG (1, "No temp filename!\n"); s->fname = strdup ("/tmp/cal.XXXXXX"); mktemp (s->fname); } s->width = 2551; s->height = 75; s->flags = FLG_PPM_HEADER | FLG_NO_INTERLEAVE; CHK (do_scan (s)); compute_ogn (s->fname); unlink (s->fname); write_byte (fd, STEP_PWM, 0x3f); /* stepper home */ write_byte (fd, COMMAND, 0x02); /* discard the remaining data */ read_byte (fd, IMAGE_DATA_AVAIL, &result); /* wants 42,4c */ if (result > 1) { read_bulk_size (fd, result, 0, 0, 0); DBG (11, "read %dk extra\n", result); } read_byte (fd, 0x69, &result); /* wants 02 */ write_byte (fd, 0x69, 0x0a); lights_out (fd); init (fd); #if 0 /* Repeatedly send this every 1 second. Button scan? FIXME */ gl640ReadReq (fd, GL640_GPIO_READ, &result); /* wants 00 */ #endif return 0; } /* The number of regions in the calibration strip (black & white). */ #define NREGIONS 2 /* Compute the offset/gain table from the calibration strip. This is somewhat more complicated than necessary because I don't hard-code the strip widths; I try to figure out the regions based on the scan data. Theoretically, the region-finder should work for any number of distinct regions (but there are only 2 on this scanner.) This produces the CAL_FILE_OGN file, the final offset/gain table. */ static SANE_Status compute_ogn (char *calfilename) { byte *linebuf, *oldline, *newline; mode_t oldmask; FILE *fp; int width, height, nlines = 0, region = -1, i, transition = 1, badcnt; int pct; int reglines[NREGIONS]; float *avg; float max_range[3], tmp1, tmp2; fp = fopen (calfilename, "r"); if (!fp) { DBG (1, "open %s\n", calfilename); return SANE_STATUS_EOF; } fscanf (fp, "P6 %d %d %*d ", &width, &height); DBG (12, "cal file %s %dx%d\n", calfilename, width, height); width = width * 3; /* 1 byte each of r, g, b */ /* make a buffer holding 2 lines of data */ linebuf = calloc (width * 2, sizeof (linebuf[0])); /* first line is data read buffer */ newline = linebuf; /* second line is a temporary holding spot in case the next line read is the black/white transition, in which case we'll disregard this one. */ oldline = linebuf + width; /* column averages per region */ avg = calloc (width * NREGIONS, sizeof (avg[0])); while (nlines < height) { if (fread (newline, 1, width, fp) != (size_t) width) break; nlines++; /* Check if new line is majorly different than old. Criteria is 10 pixels differing by more than 10%. */ badcnt = 0; for (i = 0; i < width; i++) { pct = newline[i] - oldline[i]; /* Fix by M.Reinelt * do NOT use 10% (think of a dark area with * oldline=4 and newline=5, which is a change of 20% !! * Use an absolute difference of 10 as criteria */ if (pct < -10 || pct > 10) { badcnt++; DBG (16, "pix%d[%d/%d] ", i, newline[i], oldline[i]); } } DBG (13, "line %d changed %d\n", nlines, badcnt); if ((badcnt > 10) || (nlines == height)) { /* End of region. Lines are different or end of data. */ transition++; if (transition == 1) DBG (12, "Region %d lines %d-%d\n", region, nlines - reglines[region], nlines - 1); } else { /* Lines are similar, so still in region. */ if (transition) { /* There was just a transition, so this is the start of a new region. */ region++; if (region >= NREGIONS) /* Too many regions detected. Err below. */ break; transition = 0; reglines[region] = 0; } /* Add oldline to the current region's average */ for (i = 0; i < width; i++) avg[i + region * width] += oldline[i]; reglines[region]++; } /* And newline becomes old */ memcpy (oldline, newline, width); } fclose (fp); free (linebuf); region++; /* now call it number of regions instead of index */ DBG (11, "read %d lines as %d regions\n", nlines, region); /* Check to see if we screwed up */ if (region != NREGIONS) { DBG (1, "Warning: gain/offset compute failed.\n" "Found %d regions instead of %d.\n", region, NREGIONS); for (i = 0; i < region; i++) DBG (1, " Region %d: %d lines\n", i, (i >= NREGIONS) ? -1 : reglines[i]); free (avg); return SANE_STATUS_UNSUPPORTED; } /* Now we've got regions and sums. Find averages and range. */ max_range[0] = max_range[1] = max_range[2] = 0.0; for (i = 0; i < width; i++) { /* Convert sums to averages */ /* black region */ tmp1 = avg[i] /= reglines[0]; /* white region */ tmp2 = avg[i + width] /= reglines[1]; /* Track largest range for each color. If image is interleaved, use 'i%3', if not, 'i/(width/3)' */ if ((tmp2 - tmp1) > max_range[i / (width / 3)]) { max_range[i / (width / 3)] = tmp2 - tmp1; DBG (14, "max %d@%d %f-%f=%f\n", i / (width / 3), i, tmp2, tmp1, tmp2 - tmp1); } } DBG (13, "max range r %f\n", max_range[0]); DBG (13, "max range g %f\n", max_range[1]); DBG (13, "max range b %f\n", max_range[2]); /* Set umask to world r/w so other users can overwrite common cal... */ oldmask = umask (0); fp = fopen (CAL_FILE_OGN, "w"); /* ... and set it back. */ umask (oldmask); if (!fp) { DBG (1, "open " CAL_FILE_OGN); free (avg); return SANE_STATUS_IO_ERROR; } /* Finally, compute offset and gain */ for (i = 0; i < width; i++) { int gain, offset; byte ogn[2]; /* skip line termination flags */ if (!((i + 1) % (width / 3))) { DBG (13, "skip scanline EOL %d/%d\n", i, width); continue; } /* Gain multiplier: 255 : 1.5 times brighter 511 : 2 times brighter 1023: 3 times brighter */ #if 1 /* Original gain/offset */ gain = 512 * ((max_range[i / (width / 3)] / (avg[i + width] - avg[i])) - 1); offset = avg[i]; #else /* This doesn't work for some people. For instance, a negative offset would be bad. */ /* Enhanced offset and gain calculation by M.Reinelt * These expressions were found by an iterative calibration process, * by changing gain and offset values for every pixel until the desired * values for black and white were reached, and finding an approximation * formula. * Note that offset is linear, but gain isn't! */ offset = (double)3.53 * avg[i] - 125; gain = (double)3861.0 * exp(-0.0168 * (avg[i + width] - avg[i])); #endif DBG (14, "%d wht=%f blk=%f diff=%f gain=%d offset=%d\n", i, avg[i + width], avg[i], avg[i + width] - avg[i], gain, offset); /* 10-bit gain, 6-bit offset (subtractor) in two bytes */ ogn[0] = (byte) (((offset << 2) + (gain >> 8)) & 0xFF); ogn[1] = (byte) (gain & 0xFF); fwrite (ogn, sizeof (byte), 2, fp); /* Annoyingly, we seem to use ogn data at 600dpi, while we scanned at 300, so double our file. Much easier than doubling at the read. */ fwrite (ogn, sizeof (byte), 2, fp); } fclose (fp); free (avg); return SANE_STATUS_GOOD; } static int check_ogn_file (void) { FILE *fp; fp = fopen (CAL_FILE_OGN, "r"); if (fp) { fclose (fp); return 1; } return 0; } /* Load or fake the offset/gain table */ static void install_ogn (int fd) { int temp; byte *buf; FILE *fp; /* 8.5in at 600dpi = 5104 pixels in scan head 10-bit gain + 6-bit offset = 2 bytes per pixel, so 10208 bytes */ buf = malloc (10208); fp = fopen (CAL_FILE_OGN, "r"); if (fp) { fread (buf, 2, 5100, fp); /* screw the last 4 pixels */ } else { /* Make up the gain/offset data. */ #define GAIN 256 /* 1.5x */ #define OFFSET 0 for (temp = 0; temp < 10208; temp += 2) { buf[temp] = (byte) ((OFFSET << 2) + (GAIN >> 8)); buf[temp + 1] = (byte) (GAIN & 0xFF); } } /* Gain/offset table (r,g,b) */ write_byte (fd, DATAPORT_TARGET, DP_R | DP_OFFSET); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 10208); if (fp) fread (buf, 2, 5100, fp); write_byte (fd, DATAPORT_TARGET, DP_G | DP_OFFSET); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 10208); if (fp) { fread (buf, 2, 5100, fp); fclose (fp); } write_byte (fd, DATAPORT_TARGET, DP_B | DP_OFFSET); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 10208); free (buf); return; } /* Scan sequence */ /* resolution is 75,150,300,600,1200 scan coordinates in 600-dpi pixels */ static SANE_Status scan (CANON_Handle * opt) { SANE_Status status; const int left_edge = 0x004b; /* Just for my scanner, or is this universal? Calibrate? */ int temp; int fd = opt->fd; byte result; byte *buf; /* Check status. (not in w2k driver) */ read_byte (fd, STATUS, &result); /* wants 2f or 2d */ if (!(result & STATUS_HOME) /*0x2d */ ) return SANE_STATUS_DEVICE_BUSY; /* or force it to return? write_byte(fd, COMMAND, 0x02); wait_for_return(fd); */ /* reserved? */ read_byte (fd, 0x69, &result); /* wants 0a */ read_byte (fd, STATUS, &result); /* wants 0e */ read_byte (fd, PAPER_SENSOR, &result); /* wants 2b */ write_byte (fd, PAPER_SENSOR, 0x2b); /* Color mode: 1-Channel Line Rate Color 0x15. 1-Channel Grayscale 0x14 (and we skip some of these tables) */ write_byte (fd, COLOR_MODE, 0x15); /* install the offset/gain table */ install_ogn (fd); read_byte (fd, STATUS, &result); /* wants 0e */ /* move forward to "glass 0" */ write_byte (fd, COMMAND, 0x01); read_byte (fd, STATUS, &result); /* wants 0c */ /* create gamma table */ buf = malloc (0x400); for (temp = 0; temp < 0x0400; temp++) /* gamma calculation by M.Reinelt */ buf[temp] = (double) 255.0 * exp(log((temp + 0.5) / 1023.0) / opt->gamma) + 0.5; /* Gamma R, write and verify */ write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 0x0400); write_byte (fd, DATAPORT_TARGET, DP_R | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_READ); read_bulk (fd, DATAPORT, buf, 0x0400); /* Gamma G */ write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 0x0400); write_byte (fd, DATAPORT_TARGET, DP_G | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_READ); read_bulk (fd, DATAPORT, buf, 0x0400); /* Gamma B */ write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_WRITE); write_bulk (fd, DATAPORT, buf, 0x0400); write_byte (fd, DATAPORT_TARGET, DP_B | DP_GAMMA); write_word (fd, DATAPORT_ADDR, DP_READ); read_bulk (fd, DATAPORT, buf, 0x0400); free (buf); write_byte (fd, CLOCK_DIV, 0x04); /* Resolution: dpi 75(ie) 100,150(1c) 200,300(1a) 600,1200(18) */ switch (opt->resolution) { case 150: write_byte (fd, 0x09, 0x1c); break; case 300: write_byte (fd, 0x09, 0x1a); break; case 600: case 1200: /* actually 600 dpi horiz max */ write_byte (fd, 0x09, 0x18); break; default: /* 75 */ write_byte (fd, 0x09, 0x1e); opt->resolution = 75; } write_word (fd, ACTIVE_PX_START, left_edge); /* Data pixel start. Measured at 600dpi regardless of scan resolution. 0-position is 0x004b */ write_word (fd, DATA_PX_START, left_edge + opt->x1); /* Data pixel end. Measured at 600dpi regardless of scan resolution. */ write_word (fd, DATA_PX_END, left_edge + opt->x2); /* greyscale has 14,03, different lights */ write_byte (fd, COLOR_MODE, 0x15); write_byte (fd, 0x29, 0x02); /* Lights */ write_word (fd, LAMP_R_ON, 0x0017); /* "Hi-low color" selection from windows driver. low(1437) hi(1481) */ write_word (fd, LAMP_R_OFF, 0x1437); write_word (fd, LAMP_G_ON, 0x0017); write_word (fd, LAMP_G_OFF, 0x094e); write_word (fd, LAMP_B_ON, 0x0017); write_word (fd, LAMP_B_OFF, 0x0543); /* Analog static offset R,G,B. Greyscale has 0,0,0 */ write_byte (fd, 0x38, 0x3f); write_byte (fd, 0x39, 0x3f); write_byte (fd, 0x3a, 0x3f); /* Analog static gain R,G,B (normally 0x01) */ write_byte (fd, 0x3b, opt->gain); write_byte (fd, 0x3c, opt->gain); write_byte (fd, 0x3d, opt->gain); /* Digital gain/offset settings. Greyscale has 0 */ write_byte (fd, 0x3e, 0x1a); { /* Stepper motion setup. */ int stepsize, faststep = 0x0104, reverse = 0x28, phase, pwm = 0x1f; switch (opt->resolution) { case 75: stepsize = 0x0106; faststep = 0x0106; reverse = 0; phase = 0x39a8; pwm = 0x3f; break; case 150: stepsize = 0x020d; phase = 0x3198; break; case 300: stepsize = 0x041a; phase = 0x2184; break; case 600: stepsize = 0x0835; phase = 0x0074; break; case 1200: /* 1200 dpi y only, x is 600 dpi */ stepsize = 0x106b; phase = 0x41ac; break; default: DBG (1, "BAD RESOLUTION"); return SANE_STATUS_UNSUPPORTED; } write_word (fd, STEP_SIZE, stepsize); write_word (fd, FAST_STEP, faststep); /* There sounds like a weird step disjoint at the end of skipsteps at 75dpi, so I think that's why skipsteps=0 at 75dpi in the Windows driver. It still works at the normal 0x017a though. */ /* cal strip is 0x17a steps, plus 2 300dpi microsteps per pixel */ write_word (fd, SKIP_STEPS, 0x017a /* cal strip */ + opt->y1 * 2); /* FIXME could be 0x57, why not? */ write_byte (fd, BUFFER_LIMIT, 0x20); write_byte (fd, BUFFER_RESUME, 0x02); write_byte (fd, REVERSE_STEPS, reverse); /* motor resume phasing */ write_word (fd, 0x52, phase); write_byte (fd, STEP_PWM, pwm); } read_byte (fd, PAPER_SENSOR, &result); /* wants 2b */ write_byte (fd, PAPER_SENSOR, 0x0b); opt->width = (opt->x2 - opt->x1) * opt->resolution / 600 + 1; opt->height = (opt->y2 - opt->y1) * opt->resolution / 600; opt->flags = 0; DBG (1, "width=%d height=%d dpi=%d\n", opt->width, opt->height, opt->resolution); CHK (do_scan (opt)); read_byte (fd, PAPER_SENSOR, &result); /* wants 0b */ write_byte (fd, PAPER_SENSOR, 0x2b); write_byte (fd, STEP_PWM, 0x3f); lights_out (fd); /* home */ write_byte (fd, COMMAND, 0x02); return status; } static SANE_Status CANON_set_scan_parameters (CANON_Handle * scan, const int forceCal, const int gray, const int left, const int top, const int right, const int bottom, const int res, const int gain, const double gamma) { DBG (2, "CANON_set_scan_parameters:\n"); DBG (2, "cal = %d\n", forceCal); DBG (2, "gray = %d (ignored)\n", gray); DBG (2, "res = %d\n", res); DBG (2, "gain = %d\n", gain); DBG (2, "gamma = %f\n", gamma); DBG (2, "in 600dpi pixels:\n"); DBG (2, "left = %d, top = %d\n", left, top); DBG (2, "right = %d, bottom = %d\n", right, bottom); /* Validate the input parameters */ if ((left < 0) || (right > CANON_MAX_WIDTH)) return SANE_STATUS_INVAL; if ((top < 0) || (bottom > CANON_MAX_HEIGHT)) return SANE_STATUS_INVAL; if (((right - left) < 10) || ((bottom - top) < 10)) return SANE_STATUS_INVAL; if ((res != 75) && (res != 150) && (res != 300) && (res != 600) && (res != 1200)) return SANE_STATUS_INVAL; if ((gain < 0) || (gain > 64)) return SANE_STATUS_INVAL; if (gamma <= 0.0) return SANE_STATUS_INVAL; /* Store params */ scan->resolution = res; scan->x1 = left; scan->x2 = right - /* subtract 1 pixel */ 600 / scan->resolution; scan->y1 = top; scan->y2 = bottom; scan->gain = gain; scan->gamma = gamma; scan->flags = forceCal ? FLG_FORCE_CAL : 0; return SANE_STATUS_GOOD; } static SANE_Status CANON_close_device (CANON_Handle * scan) { DBG (3, "CANON_close_device:\n"); sanei_usb_close (scan->fd); return SANE_STATUS_GOOD; } static SANE_Status CANON_open_device (CANON_Handle * scan, const char *dev) { SANE_Word vendor; SANE_Word product; SANE_Status res; DBG (3, "CANON_open_device: `%s'\n", dev); scan->fname = NULL; scan->fp = NULL; scan->flags = 0; res = sanei_usb_open (dev, &scan->fd); if (res != SANE_STATUS_GOOD) { DBG (1, "CANON_open_device: couldn't open device `%s': %s\n", dev, sane_strstatus (res)); return res; } #ifndef NO_AUTODETECT /* We have opened the device. Check that it is a USB scanner. */ if (sanei_usb_get_vendor_product (scan->fd, &vendor, &product) != SANE_STATUS_GOOD) { DBG (1, "CANON_open_device: sanei_usb_get_vendor_product failed\n"); /* This is not a USB scanner, or SANE or the OS doesn't support it. */ sanei_usb_close (scan->fd); scan->fd = -1; return SANE_STATUS_UNSUPPORTED; } /* Make sure we have a CANON scanner */ if ((vendor != 0x04a9) || (product != 0x2204)) { DBG (1, "CANON_open_device: incorrect vendor/product (0x%x/0x%x)\n", vendor, product); sanei_usb_close (scan->fd); scan->fd = -1; return SANE_STATUS_UNSUPPORTED; } #endif return SANE_STATUS_GOOD; } static const char * CANON_get_device_name (CANON_Handle * scanner) { scanner = scanner; /* Eliminate warning about unused parameters */ return "Canoscan FB630U"; } static SANE_Status CANON_finish_scan (CANON_Handle * scanner) { DBG (3, "CANON_finish_scan:\n"); if (scanner->fp) fclose (scanner->fp); scanner->fp = NULL; /* remove temp file */ if (scanner->fname) { DBG (4, "removing temp file %s\n", scanner->fname); unlink (scanner->fname); free (scanner->fname); } scanner->fname = NULL; return SANE_STATUS_GOOD; } static SANE_Status CANON_start_scan (CANON_Handle * scanner) { int rv; SANE_Status status; DBG (3, "CANON_start_scan called\n"); /* choose a temp file name for scan data */ scanner->fname = strdup ("/tmp/scan.XXXXXX"); if (!mktemp (scanner->fname)) return SANE_STATUS_IO_ERROR; /* calibrate if needed */ rv = init (scanner->fd); if (rv < 0) { DBG(1, "Can't talk on USB.\n"); return SANE_STATUS_IO_ERROR; } if ((rv == 1) || !check_ogn_file () || (scanner->flags & FLG_FORCE_CAL)) { plugin_cal (scanner); wait_for_return (scanner->fd); } /* scan */ if ((status = scan (scanner)) != SANE_STATUS_GOOD) { CANON_finish_scan (scanner); return status; } /* read the temp file back out */ scanner->fp = fopen (scanner->fname, "r"); DBG (4, "reading %s\n", scanner->fname); if (!scanner->fp) { DBG (1, "open %s", scanner->fname); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } static SANE_Status CANON_read (CANON_Handle * scanner, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { SANE_Status status; int red_len; DBG (5, "CANON_read called\n"); if (!scanner->fp) return SANE_STATUS_INVAL; red_len = fread (data, 1, max_length, scanner->fp); /* return some data */ if (red_len > 0) { *length = red_len; DBG (5, "CANON_read returned (%d/%d)\n", *length, max_length); return SANE_STATUS_GOOD; } /* EOF or file err */ *length = 0; if (feof (scanner->fp)) { DBG (4, "EOF\n"); status = SANE_STATUS_EOF; } else { DBG (4, "IO ERR\n"); status = SANE_STATUS_IO_ERROR; } CANON_finish_scan (scanner); DBG (5, "CANON_read returned (%d/%d)\n", *length, max_length); return status; } sane-backends-1.0.27/backend/hp-scl.c0000664000175000017500000015105713106201017014143 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ /* $Log$ Revision 1.15 2008/03/28 14:37:36 kitno-guest add usleep to improve usb performance, from jim a t meyering d o t net Revision 1.14 2004-10-04 18:09:05 kig-guest Rename global function hp_init_openfd to sanei_hp_init_openfd Revision 1.13 2004/03/27 13:52:39 kig-guest Keep USB-connection open (was problem with Linux 2.6.x) Revision 1.12 2003/10/09 19:34:57 kig-guest Redo when TEST UNIT READY failed Redo when read returns with 0 bytes (non-SCSI only) */ /* #define STUBS extern int sanei_debug_hp;*/ #define DEBUG_DECLARE_ONLY #include "../include/sane/config.h" #include "../include/lalloca.h" /* Must be first */ #ifdef HAVE_UNISTD_H # include #endif #include #include #include #include #include #include "../include/lassert.h" #include #include #include #include #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_pio.h" #include "hp.h" #include "../include/sane/sanei_backend.h" #include "hp-option.h" #include "hp-scsi.h" #include "hp-scl.h" #include "hp-device.h" #define HP_SCSI_INQ_LEN (36) #define HP_SCSI_CMD_LEN (6) #define HP_SCSI_BUFSIZ (HP_SCSI_MAX_WRITE + HP_SCSI_CMD_LEN) #define HP_MAX_OPEN_FD 16 static struct hp_open_fd_s /* structure to save info about open file descriptor */ { char *devname; HpConnect connect; int fd; } asHpOpenFd[HP_MAX_OPEN_FD]; /* * */ struct hp_scsi_s { int fd; char * devname; /* Output buffering */ hp_byte_t buf[HP_SCSI_BUFSIZ]; hp_byte_t * bufp; hp_byte_t inq_data[HP_SCSI_INQ_LEN]; }; #define HP_TMP_BUF_SIZE (1024*4) #define HP_WR_BUF_SIZE (1024*4) typedef struct { HpProcessData procdata; int outfd; const unsigned char *map; unsigned char *image_buf; /* Buffer to store complete image (if req.) */ unsigned char *image_ptr; int image_buf_size; unsigned char *tmp_buf; /* Buffer for scan data to get even number of bytes */ int tmp_buf_size; int tmp_buf_len; unsigned char wr_buf[HP_WR_BUF_SIZE]; unsigned char *wr_ptr; int wr_buf_size; int wr_left; } PROCDATA_HANDLE; /* Initialize structure where we remember out open file descriptors */ void sanei_hp_init_openfd () {int iCount; memset (asHpOpenFd, 0, sizeof (asHpOpenFd)); for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) asHpOpenFd[iCount].fd = -1; } /* Look if the device is still open */ static SANE_Status hp_GetOpenDevice (const char *devname, HpConnect connect, int *pfd) {int iCount; for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) { if (!asHpOpenFd[iCount].devname) continue; if ( (strcmp (asHpOpenFd[iCount].devname, devname) == 0) && (asHpOpenFd[iCount].connect == connect) ) { if (pfd) *pfd = asHpOpenFd[iCount].fd; DBG(3, "hp_GetOpenDevice: device %s is open with fd=%d\n", devname, asHpOpenFd[iCount].fd); return SANE_STATUS_GOOD; } } DBG(3, "hp_GetOpenDevice: device %s not open\n", devname); return SANE_STATUS_INVAL; } /* Add an open file descriptor. This also decides */ /* if we keep a connection open or not. */ static SANE_Status hp_AddOpenDevice (const char *devname, HpConnect connect, int fd) {int iCount, iKeepOpen; static int iInitKeepFlags = 1; /* The default values which connections to keep open or not */ static int iKeepOpenSCSI = 0; static int iKeepOpenUSB = 1; static int iKeepOpenDevice = 0; static int iKeepOpenPIO = 0; if (iInitKeepFlags) /* Change the defaults by environment */ {char *eptr; iInitKeepFlags = 0; eptr = getenv ("SANE_HP_KEEPOPEN_SCSI"); if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) iKeepOpenSCSI = (*eptr == '1'); eptr = getenv ("SANE_HP_KEEPOPEN_USB"); if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) iKeepOpenUSB = (*eptr == '1'); eptr = getenv ("SANE_HP_KEEPOPEN_DEVICE"); if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) iKeepOpenDevice = (*eptr == '1'); eptr = getenv ("SANE_HP_KEEPOPEN_PIO"); if ( (eptr != NULL) && ((*eptr == '0') || (*eptr == '1')) ) iKeepOpenPIO = (*eptr == '1'); } /* Look if we should keep it open or not */ iKeepOpen = 0; switch (connect) { case HP_CONNECT_SCSI: iKeepOpen = iKeepOpenSCSI; break; case HP_CONNECT_PIO : iKeepOpen = iKeepOpenPIO; break; case HP_CONNECT_USB : iKeepOpen = iKeepOpenUSB; break; case HP_CONNECT_DEVICE : iKeepOpen = iKeepOpenDevice; break; case HP_CONNECT_RESERVE: break; } if (!iKeepOpen) { DBG(3, "hp_AddOpenDevice: %s should not be kept open\n", devname); return SANE_STATUS_INVAL; } for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) { if (!asHpOpenFd[iCount].devname) /* Is this entry free ? */ { asHpOpenFd[iCount].devname = sanei_hp_strdup (devname); if (!asHpOpenFd[iCount].devname) return SANE_STATUS_NO_MEM; DBG(3, "hp_AddOpenDevice: added device %s with fd=%d\n", devname, fd); asHpOpenFd[iCount].connect = connect; asHpOpenFd[iCount].fd = fd; return SANE_STATUS_GOOD; } } DBG(3, "hp_AddOpenDevice: %s not added\n", devname); return SANE_STATUS_NO_MEM; } /* Check if we have remembered an open file descriptor */ static SANE_Status hp_IsOpenFd (int fd, HpConnect connect) {int iCount; for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) { if ( (asHpOpenFd[iCount].devname != NULL) && (asHpOpenFd[iCount].fd == fd) && (asHpOpenFd[iCount].connect == connect) ) { DBG(3, "hp_IsOpenFd: %d is open\n", fd); return SANE_STATUS_GOOD; } } DBG(3, "hp_IsOpenFd: %d not open\n", fd); return SANE_STATUS_INVAL; } static SANE_Status hp_RemoveOpenFd (int fd, HpConnect connect) {int iCount; for (iCount = 0; iCount < HP_MAX_OPEN_FD; iCount++) { if ( (asHpOpenFd[iCount].devname != NULL) && (asHpOpenFd[iCount].fd == fd) && (asHpOpenFd[iCount].connect == connect) ) { sanei_hp_free (asHpOpenFd[iCount].devname); asHpOpenFd[iCount].devname = NULL; DBG(3, "hp_RemoveOpenFd: removed %d\n", asHpOpenFd[iCount].fd); asHpOpenFd[iCount].fd = -1; return SANE_STATUS_GOOD; } } DBG(3, "hp_RemoveOpenFd: %d not removed\n", fd); return SANE_STATUS_INVAL; } static SANE_Status hp_nonscsi_write (HpScsi this, hp_byte_t *data, size_t len, HpConnect connect) {int n = -1; size_t loc_len; SANE_Status status = SANE_STATUS_GOOD; if (len <= 0) return SANE_STATUS_GOOD; switch (connect) { case HP_CONNECT_DEVICE: /* direct device-io */ n = write (this->fd, data, len); break; case HP_CONNECT_PIO: /* Use sanepio interface */ n = sanei_pio_write (this->fd, data, len); break; case HP_CONNECT_USB: /* Not supported */ loc_len = len; status = sanei_usb_write_bulk ((SANE_Int)this->fd, data, &loc_len); n = loc_len; break; case HP_CONNECT_RESERVE: n = -1; break; default: n = -1; break; } if (n == 0) return SANE_STATUS_EOF; else if (n < 0) return SANE_STATUS_IO_ERROR; return status; } static SANE_Status hp_nonscsi_read (HpScsi this, hp_byte_t *data, size_t *len, HpConnect connect, int __sane_unused__ isResponse) {int n = -1; static int retries = -1; size_t save_len = *len; SANE_Status status = SANE_STATUS_GOOD; if (*len <= 0) return SANE_STATUS_GOOD; if (retries < 0) /* Read environment */ {char *eptr = getenv ("SANE_HP_RDREDO"); retries = 1; /* Set default value */ if (eptr != NULL) { if (sscanf (eptr, "%d", &retries) != 1) retries = 1; /* Restore default */ else if (retries < 0) retries = 0; /* Allow no retries here */ } } for (;;) /* Retry on EOF */ { switch (connect) { case HP_CONNECT_DEVICE: n = read (this->fd, data, *len); break; case HP_CONNECT_PIO: n = sanei_pio_read (this->fd, data, *len); break; case HP_CONNECT_USB: status = sanei_usb_read_bulk((SANE_Int)this->fd, (SANE_Byte *)data, len); n = *len; break; case HP_CONNECT_RESERVE: n = -1; break; default: n = -1; break; } if ((n != 0) || (retries <= 0)) break; retries--; usleep (100*1000); /* sleep 0.1 seconds */ *len = save_len; /* Restore value */ } if (n == 0) return SANE_STATUS_EOF; else if (n < 0) return SANE_STATUS_IO_ERROR; *len = n; return status; } static SANE_Status hp_nonscsi_open (const char *devname, int *fd, HpConnect connect) {int lfd, flags; SANE_Int dn; SANE_Status status = SANE_STATUS_INVAL; #ifdef _O_RDWR flags = _O_RDWR; #else flags = O_RDWR; #endif #ifdef _O_EXCL flags |= _O_EXCL; #else flags |= O_EXCL; #endif #ifdef _O_BINARY flags |= _O_BINARY; #endif #ifdef O_BINARY flags |= O_BINARY; #endif switch (connect) { case HP_CONNECT_DEVICE: lfd = open (devname, flags); if (lfd < 0) { DBG(1, "hp_nonscsi_open: open device %s failed (%s)\n", devname, strerror (errno) ); status = (errno == EACCES) ? SANE_STATUS_ACCESS_DENIED : SANE_STATUS_INVAL; } else status = SANE_STATUS_GOOD; break; case HP_CONNECT_PIO: status = sanei_pio_open (devname, &lfd); break; case HP_CONNECT_USB: DBG(17, "hp_nonscsi_open: open usb with \"%s\"\n", devname); status = sanei_usb_open (devname, &dn); lfd = (int)dn; break; case HP_CONNECT_RESERVE: status = SANE_STATUS_INVAL; break; default: status = SANE_STATUS_INVAL; break; } if (status != SANE_STATUS_GOOD) { DBG(1, "hp_nonscsi_open: open device %s failed\n", devname); } else { DBG(17,"hp_nonscsi_open: device %s opened, fd=%d\n", devname, lfd); } if (fd) *fd = lfd; return status; } static void hp_nonscsi_close (int fd, HpConnect connect) { switch (connect) { case HP_CONNECT_DEVICE: close (fd); break; case HP_CONNECT_PIO: sanei_pio_close (fd); break; case HP_CONNECT_USB: sanei_usb_close (fd); break; case HP_CONNECT_RESERVE: break; default: break; } DBG(17,"hp_nonscsi_close: closed fd=%d\n", fd); } SANE_Status sanei_hp_nonscsi_new (HpScsi * newp, const char * devname, HpConnect connect) { HpScsi new; SANE_Status status; int iAlreadyOpen = 0; new = sanei_hp_allocz(sizeof(*new)); if (!new) return SANE_STATUS_NO_MEM; /* Is the device already open ? */ if ( hp_GetOpenDevice (devname, connect, &new->fd) == SANE_STATUS_GOOD ) { iAlreadyOpen = 1; } else { status = hp_nonscsi_open(devname, &new->fd, connect); if (FAILED(status)) { DBG(1, "nonscsi_new: open failed (%s)\n", sane_strstatus(status)); sanei_hp_free(new); return SANE_STATUS_IO_ERROR; } } /* For SCSI-devices we would have the inquire command here */ strncpy ((char *)new->inq_data, "\003zzzzzzzHP ------ R000", sizeof (new->inq_data)); new->bufp = new->buf + HP_SCSI_CMD_LEN; new->devname = sanei_hp_alloc ( strlen ( devname ) + 1 ); if ( new->devname ) strcpy (new->devname, devname); *newp = new; /* Remember the open device */ if (!iAlreadyOpen) hp_AddOpenDevice (devname, connect, new->fd); return SANE_STATUS_GOOD; } static void hp_scsi_close (HpScsi this, int completely) {HpConnect connect; DBG(3, "scsi_close: closing fd %ld\n", (long)this->fd); connect = sanei_hp_scsi_get_connect (this); if (!completely) /* May we keep the device open ? */ { if ( hp_IsOpenFd (this->fd, connect) == SANE_STATUS_GOOD ) { DBG(3, "scsi_close: not closing. Keep open\n"); return; } } assert(this->fd >= 0); if (connect != HP_CONNECT_SCSI) hp_nonscsi_close (this->fd, connect); else sanei_scsi_close (this->fd); DBG(3,"scsi_close: really closed\n"); /* Remove a remembered open device */ hp_RemoveOpenFd (this->fd, connect); } SANE_Status sanei_hp_scsi_new (HpScsi * newp, const char * devname) { static hp_byte_t inq_cmd[] = { 0x12, 0, 0, 0, HP_SCSI_INQ_LEN, 0}; static hp_byte_t tur_cmd[] = { 0x00, 0, 0, 0, 0, 0}; size_t inq_len = HP_SCSI_INQ_LEN; HpScsi new; HpConnect connect; SANE_Status status; int iAlreadyOpen = 0; connect = sanei_hp_get_connect (devname); if (connect != HP_CONNECT_SCSI) return sanei_hp_nonscsi_new (newp, devname, connect); new = sanei_hp_allocz(sizeof(*new)); if (!new) return SANE_STATUS_NO_MEM; /* Is the device still open ? */ if ( hp_GetOpenDevice (devname, connect, &new->fd) == SANE_STATUS_GOOD ) { iAlreadyOpen = 1; } else { status = sanei_scsi_open(devname, &new->fd, 0, 0); if (FAILED(status)) { DBG(1, "scsi_new: open failed (%s)\n", sane_strstatus(status)); sanei_hp_free(new); return SANE_STATUS_IO_ERROR; } } DBG(3, "scsi_inquire: sending INQUIRE\n"); status = sanei_scsi_cmd(new->fd, inq_cmd, 6, new->inq_data, &inq_len); if (FAILED(status)) { DBG(1, "scsi_inquire: inquiry failed: %s\n", sane_strstatus(status)); sanei_scsi_close(new->fd); sanei_hp_free(new); return status; } {char vendor[9], model[17], rev[5]; memset (vendor, 0, sizeof (vendor)); memset (model, 0, sizeof (model)); memset (rev, 0, sizeof (rev)); memcpy (vendor, new->inq_data + 8, 8); memcpy (model, new->inq_data + 16, 16); memcpy (rev, new->inq_data + 32, 4); DBG(3, "vendor=%s, model=%s, rev=%s\n", vendor, model, rev); } DBG(3, "scsi_new: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd(new->fd, tur_cmd, 6, 0, 0); if (FAILED(status)) { DBG(1, "hp_scsi_open: test unit ready failed (%s)\n", sane_strstatus(status)); usleep (500*1000); /* Wait 0.5 seconds */ DBG(3, "scsi_new: sending TEST_UNIT_READY second time\n"); status = sanei_scsi_cmd(new->fd, tur_cmd, 6, 0, 0); } if (FAILED(status)) { DBG(1, "hp_scsi_open: test unit ready failed (%s)\n", sane_strstatus(status)); sanei_scsi_close(new->fd); sanei_hp_free(new); return status; /* Fix problem with non-scanner devices */ } new->bufp = new->buf + HP_SCSI_CMD_LEN; new->devname = sanei_hp_alloc ( strlen ( devname ) + 1 ); if ( new->devname ) strcpy (new->devname, devname); *newp = new; /* Remember the open device */ if (!iAlreadyOpen) hp_AddOpenDevice (devname, connect, new->fd); return SANE_STATUS_GOOD; } /* The "completely" parameter was added for OfficeJet support. * For JetDirect connections, closing and re-opening the scan * channel is very time consuming. Also, the OfficeJet G85 * unloads a loaded document in the ADF when the scan channel * gets closed. The solution is to "completely" destroy the * connection, including closing and deallocating the PTAL * channel, when initially probing the device in hp-device.c, * but leave it open while the frontend is actually using the * device (from hp-handle.c), and "completely" destroy it when * the frontend closes its handle. */ void sanei_hp_scsi_destroy (HpScsi this,int completely) { /* Moved to hp_scsi_close(): * assert(this->fd >= 0); * DBG(3, "scsi_close: closing fd %d\n", this->fd); */ hp_scsi_close (this, completely); if ( this->devname ) sanei_hp_free (this->devname); sanei_hp_free(this); } hp_byte_t * sanei_hp_scsi_inq (HpScsi this) { return this->inq_data; } const char * sanei_hp_scsi_vendor (HpScsi this) { static char buf[9]; memcpy(buf, sanei_hp_scsi_inq(this) + 8, 8); buf[8] = '\0'; return buf; } const char * sanei_hp_scsi_model (HpScsi this) { static char buf[17]; memcpy(buf, sanei_hp_scsi_inq(this) + 16, 16); buf[16] = '\0'; return buf; } const char * sanei_hp_scsi_devicename (HpScsi this) { return this->devname; } hp_bool_t sanei_hp_is_active_xpa (HpScsi scsi) {HpDeviceInfo *info; int model_num; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); if (info->active_xpa < 0) { model_num = sanei_hp_get_max_model (scsi); info->active_xpa = (model_num >= 17); DBG(5,"sanei_hp_is_active_xpa: model=%d, active_xpa=%d\n", model_num, info->active_xpa); } return info->active_xpa; } int sanei_hp_get_max_model (HpScsi scsi) {HpDeviceInfo *info; info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); if (info->max_model < 0) {enum hp_device_compat_e compat; int model_num; if ( sanei_hp_device_probe_model ( &compat, scsi, &model_num, 0) == SANE_STATUS_GOOD ) info->max_model = model_num; } return info->max_model; } int sanei_hp_is_flatbed_adf (HpScsi scsi) {int model = sanei_hp_get_max_model (scsi); return ((model == 2) || (model == 4) || (model == 5) || (model == 8)); } HpConnect sanei_hp_get_connect (const char *devname) {const HpDeviceInfo *info; HpConnect connect = HP_CONNECT_SCSI; int got_connect_type = 0; info = sanei_hp_device_info_get (devname); if (!info) { DBG(1, "sanei_hp_get_connect: Could not get info for %s. Assume SCSI\n", devname); connect = HP_CONNECT_SCSI; } else if ( !(info->config_is_up) ) { DBG(1, "sanei_hp_get_connect: Config not initialized for %s. Assume SCSI\n", devname); connect = HP_CONNECT_SCSI; } else { connect = info->config.connect; got_connect_type = info->config.got_connect_type; } /* Beware of using a USB-device as a SCSI-device (not 100% perfect) */ if ((connect == HP_CONNECT_SCSI) && !got_connect_type) {int maybe_usb; maybe_usb = ( strstr (devname, "usb") || strstr (devname, "uscanner") || strstr (devname, "ugen")); if (maybe_usb) {static int print_warning = 1; if (print_warning) { print_warning = 0; DBG(1,"sanei_hp_get_connect: WARNING\n"); DBG(1," Device %s assumed to be SCSI, but device name\n",devname); DBG(1," looks like USB. Will continue with USB.\n"); DBG(1," If you really want it as SCSI, add the following\n"); DBG(1," to your file .../etc/sane.d/hp.conf:\n"); DBG(1," %s\n", devname); DBG(1," option connect-scsi\n"); DBG(1," The same warning applies to other device names containing\n"); DBG(1," \"usb\", \"uscanner\" or \"ugen\".\n"); } connect = HP_CONNECT_DEVICE; } } return connect; } HpConnect sanei_hp_scsi_get_connect (HpScsi this) { return sanei_hp_get_connect (sanei_hp_scsi_devicename (this)); } static SANE_Status hp_scsi_flush (HpScsi this) { hp_byte_t * data = this->buf + HP_SCSI_CMD_LEN; size_t len = this->bufp - data; HpConnect connect; assert(len < HP_SCSI_MAX_WRITE); if (len == 0) return SANE_STATUS_GOOD; this->bufp = this->buf; DBG(16, "scsi_flush: writing %lu bytes:\n", (unsigned long) len); DBGDUMP(16, data, len); *this->bufp++ = 0x0A; *this->bufp++ = 0; *this->bufp++ = len >> 16; *this->bufp++ = len >> 8; *this->bufp++ = len; *this->bufp++ = 0; connect = sanei_hp_scsi_get_connect (this); if (connect == HP_CONNECT_SCSI) return sanei_scsi_cmd (this->fd, this->buf, HP_SCSI_CMD_LEN + len, 0, 0); else return hp_nonscsi_write (this, this->buf+HP_SCSI_CMD_LEN, len, connect); } static size_t hp_scsi_room (HpScsi this) { return this->buf + HP_SCSI_BUFSIZ - this->bufp; } static SANE_Status hp_scsi_need (HpScsi this, size_t need) { assert(need < HP_SCSI_MAX_WRITE); if (need > hp_scsi_room(this)) RETURN_IF_FAIL( hp_scsi_flush(this) ); return SANE_STATUS_GOOD; } static SANE_Status hp_scsi_write (HpScsi this, const void *data, size_t len) { if ( len < HP_SCSI_MAX_WRITE ) { RETURN_IF_FAIL( hp_scsi_need(this, len) ); memcpy(this->bufp, data, len); this->bufp += len; } else {size_t maxwrite = HP_SCSI_MAX_WRITE - 16; const char *c_data = (const char *)data; while ( len > 0 ) { if ( maxwrite > len ) maxwrite = len; RETURN_IF_FAIL( hp_scsi_write(this, c_data, maxwrite) ); c_data += maxwrite; len -= maxwrite; } } return SANE_STATUS_GOOD; } static SANE_Status hp_scsi_scl(HpScsi this, HpScl scl, int val) { char group = tolower(SCL_GROUP_CHAR(scl)); char param = toupper(SCL_PARAM_CHAR(scl)); int count; assert(IS_SCL_CONTROL(scl) || IS_SCL_COMMAND(scl)); assert(isprint(group) && isprint(param)); RETURN_IF_FAIL( hp_scsi_need(this, 10) ); /* Don't try to optimize SCL-commands like using *a1b0c5T */ /* Some scanners have problems with it (e.g. HP Photosmart Photoscanner */ /* with window position/extent, resolution) */ count = sprintf((char *)this->bufp, "\033*%c%d%c", group, val, param); this->bufp += count; assert(count > 0 && this->bufp < this->buf + HP_SCSI_BUFSIZ); return hp_scsi_flush(this); } /* Read it bytewise */ static SANE_Status hp_scsi_read_slow (HpScsi this, void * dest, size_t *len) {static hp_byte_t read_cmd[6] = { 0x08, 0, 0, 0, 0, 0 }; size_t leftover = *len; SANE_Status status = SANE_STATUS_GOOD; unsigned char *start_dest = (unsigned char *)dest; unsigned char *next_dest = start_dest; DBG(16, "hp_scsi_read_slow: Start reading %d bytes bytewise\n", (int)*len); while (leftover > 0) /* Until we got all the bytes */ {size_t one = 1; read_cmd[2] = 0; read_cmd[3] = 0; read_cmd[4] = 1; /* Read one byte */ status = sanei_scsi_cmd (this->fd, read_cmd, sizeof(read_cmd), next_dest, &one); if ((status != SANE_STATUS_GOOD) || (one != 1)) { DBG(250,"hp_scsi_read_slow: Reading byte %d: status=%s, len=%d\n", (int)(next_dest-start_dest), sane_strstatus(status), (int)one); } if (status != SANE_STATUS_GOOD) break; /* Finish on error */ next_dest++; leftover--; } *len = next_dest-start_dest; /* This is the number of bytes we got */ DBG(16, "hp_scsi_read_slow: Got %d bytes\n", (int)*len); if ((status != SANE_STATUS_GOOD) && (*len > 0)) { DBG(16, "We got some data. Ignore the error \"%s\"\n", sane_strstatus(status)); status = SANE_STATUS_GOOD; } return status; } /* The OfficeJets tend to return inquiry responses containing array * data in two packets. The added "isResponse" parameter tells * whether we should keep reading until we get * a well-formed response. Naturally, this parameter would be zero * when reading scan data. */ static SANE_Status hp_scsi_read (HpScsi this, void * dest, size_t *len, int isResponse) { HpConnect connect; RETURN_IF_FAIL( hp_scsi_flush(this) ); connect = sanei_hp_scsi_get_connect (this); if (connect == HP_CONNECT_SCSI) {int read_bytewise = 0; if (*len <= 32) /* Is it a candidate for reading bytewise ? */ {const HpDeviceInfo *info; info = sanei_hp_device_info_get (sanei_hp_scsi_devicename (this)); if ((info != NULL) && (info->config_is_up) && info->config.dumb_read) read_bytewise = 1; } if ( ! read_bytewise ) {static hp_byte_t read_cmd[6] = { 0x08, 0, 0, 0, 0, 0 }; read_cmd[2] = *len >> 16; read_cmd[3] = *len >> 8; read_cmd[4] = *len; RETURN_IF_FAIL( sanei_scsi_cmd (this->fd, read_cmd, sizeof(read_cmd), dest, len) ); } else { RETURN_IF_FAIL (hp_scsi_read_slow (this, dest, len)); } } else { RETURN_IF_FAIL( hp_nonscsi_read (this, dest, len, connect, isResponse) ); } DBG(16, "scsi_read: %lu bytes:\n", (unsigned long) *len); DBGDUMP(16, dest, *len); return SANE_STATUS_GOOD; } static int signal_caught = 0; static void signal_catcher (int sig) { DBG(1,"signal_catcher(sig=%d): old signal_caught=%d\n",sig,signal_caught); if (!signal_caught) signal_caught = sig; } static void hp_data_map (register const unsigned char *map, register int count, register unsigned char *data) { if (count <= 0) return; while (count--) { *data = map[*data]; data++; } } static const unsigned char * hp_get_simulation_map (const char *devname, const HpDeviceInfo *info) { hp_bool_t sim_gamma, sim_brightness, sim_contrast; int k, ind; const unsigned char *map = NULL; static unsigned char map8x8[256]; sim_gamma = info->simulate.gamma_simulate; sim_brightness = sanei_hp_device_simulate_get (devname, SCL_BRIGHTNESS); sim_contrast = sanei_hp_device_simulate_get (devname, SCL_CONTRAST); if ( sim_gamma ) { map = &(info->simulate.gamma_map[0]); } else if ( sim_brightness && sim_contrast ) { for (k = 0; k < 256; k++) { ind = info->simulate.contrast_map[k]; map8x8[k] = info->simulate.brightness_map[ind]; } map = &(map8x8[0]); } else if ( sim_brightness ) map = &(info->simulate.brightness_map[0]); else if ( sim_contrast ) map = &(info->simulate.contrast_map[0]); return map; } /* Check the native byte order on the local machine */ static hp_bool_t is_lowbyte_first_byteorder (void) {unsigned short testvar = 1; unsigned char *testptr = (unsigned char *)&testvar; if (sizeof (unsigned short) == 2) return (testptr[0] == 1); else if (sizeof (unsigned short) == 4) return ((testptr[0] == 1) || (testptr[2] == 1)); else return ( (testptr[0] == 1) || (testptr[2] == 1) || (testptr[4] == 1) || (testptr[6] == 1)); } /* The SANE standard defines that 2-byte data must use the full 16 bit range. * Byte order returned by the backend must be native byte order. * Scaling to 16 bit and byte order is achived by hp_scale_to_16bit. * for >8 bits data, take the two data bytes and scale their content * to the full 16 bit range, using * scaled = unscaled << (newlen - oldlen) + * unscaled >> (oldlen - (newlen - oldlen)), * with newlen=16 and oldlen the original bit depth. */ static void hp_scale_to_16bit(int count, register unsigned char *data, int depth, hp_bool_t invert) { register unsigned int tmp; register unsigned int mask; register hp_bool_t lowbyte_first = is_lowbyte_first_byteorder (); unsigned int shift1 = 16 - depth; unsigned int shift2 = 2*depth - 16; int k; if (count <= 0) return; mask = 1; for (k = 1; k < depth; k++) mask |= (1 << k); if (lowbyte_first) { while (count--) { tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask; tmp = (tmp << shift1) + (tmp >> shift2); if (invert) tmp = ~tmp; *data++ = tmp & 255U; *data++ = (tmp >> 8) & 255U; } } else /* Highbyte first */ { while (count--) { tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask; tmp = (tmp << shift1) + (tmp >> shift2); if (invert) tmp = ~tmp; *data++ = (tmp >> 8) & 255U; *data++ = tmp & 255U; } } } static void hp_scale_to_8bit(int count, register unsigned char *data, int depth, hp_bool_t invert) { register unsigned int tmp, mask; register hp_bool_t lowbyte_first = is_lowbyte_first_byteorder (); unsigned int shift1 = depth-8; int k; unsigned char *dataout = data; if ((count <= 0) || (shift1 <= 0)) return; mask = 1; for (k = 1; k < depth; k++) mask |= (1 << k); if (lowbyte_first) { while (count--) { tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask; tmp >>= shift1; if (invert) tmp = ~tmp; *(dataout++) = tmp & 255U; data += 2; } } else /* Highbyte first */ { while (count--) { tmp = ((((unsigned int)data[0])<<8) | ((unsigned int)data[1])) & mask; tmp >>= shift1; if (invert) tmp = ~tmp; *(dataout++) = tmp & 255U; data += 2; } } } static void hp_soft_invert(int count, register unsigned char *data) { while (count>0) { *data = ~(*data); data++; count--; } } static PROCDATA_HANDLE * process_data_init (HpProcessData *procdata, const unsigned char *map, int outfd, hp_bool_t use_imgbuf) {PROCDATA_HANDLE *ph = sanei_hp_alloc (sizeof (PROCDATA_HANDLE)); int tsz; if (ph == NULL) return NULL; memset (ph, 0, sizeof (*ph)); memcpy (&(ph->procdata), procdata, sizeof (*procdata)); procdata = &(ph->procdata); tsz = (HP_TMP_BUF_SIZE <= 0) ? procdata->bytes_per_line : HP_TMP_BUF_SIZE; ph->tmp_buf = sanei_hp_alloc (tsz); if (ph->tmp_buf == NULL) { sanei_hp_free (ph); return NULL; } ph->tmp_buf_size = tsz; ph->tmp_buf_len = 0; ph->map = map; ph->outfd = outfd; if ( procdata->mirror_vertical || use_imgbuf) { tsz = procdata->lines*procdata->bytes_per_line; if (procdata->out8) tsz /= 2; ph->image_ptr = ph->image_buf = sanei_hp_alloc (tsz); if ( !ph->image_buf ) { procdata->mirror_vertical = 0; ph->image_buf_size = 0; DBG(1, "process_scanline_init: Not enough memory to mirror image\n"); } else ph->image_buf_size = tsz; } ph->wr_ptr = ph->wr_buf; ph->wr_buf_size = ph->wr_left = sizeof (ph->wr_buf); return ph; } static SANE_Status process_data_write (PROCDATA_HANDLE *ph, unsigned char *data, int nbytes) {int ncopy; if (ph == NULL) return SANE_STATUS_INVAL; /* Fill up write buffer */ ncopy = ph->wr_left; if (ncopy > nbytes) ncopy = nbytes; memcpy (ph->wr_ptr, data, ncopy); ph->wr_ptr += ncopy; ph->wr_left -= ncopy; data += ncopy; nbytes -= ncopy; if ( ph->wr_left > 0 ) /* Did not fill up the write buffer ? Finished */ return SANE_STATUS_GOOD; DBG(12, "process_data_write: write %d bytes\n", ph->wr_buf_size); /* Don't write data if we got a signal in the meantime */ if ( signal_caught || (write (ph->outfd, ph->wr_buf, ph->wr_buf_size) != ph->wr_buf_size)) { DBG(1, "process_data_write: write failed: %s\n", signal_caught ? "signal caught" : strerror(errno)); return SANE_STATUS_IO_ERROR; } ph->wr_ptr = ph->wr_buf; ph->wr_left = ph->wr_buf_size; /* For large amount of data write it from data-buffer */ while ( nbytes > ph->wr_buf_size ) { if ( signal_caught || (write (ph->outfd, data, ph->wr_buf_size) != ph->wr_buf_size)) { DBG(1, "process_data_write: write failed: %s\n", signal_caught ? "signal caught" : strerror(errno)); return SANE_STATUS_IO_ERROR; } nbytes -= ph->wr_buf_size; data += ph->wr_buf_size; } if ( nbytes > 0 ) /* Something left ? Save it to (empty) write buffer */ { memcpy (ph->wr_ptr, data, nbytes); ph->wr_ptr += nbytes; ph->wr_left -= nbytes; } return SANE_STATUS_GOOD; } static SANE_Status process_scanline (PROCDATA_HANDLE *ph, unsigned char *linebuf, int bytes_per_line) {int out_bytes_per_line = bytes_per_line; HpProcessData *procdata; if (ph == NULL) return SANE_STATUS_INVAL; procdata = &(ph->procdata); if ( ph->map ) hp_data_map (ph->map, bytes_per_line, linebuf); if (procdata->bits_per_channel > 8) { if (procdata->out8) { hp_scale_to_8bit( bytes_per_line/2, linebuf, procdata->bits_per_channel, procdata->invert); out_bytes_per_line /= 2; } else { hp_scale_to_16bit( bytes_per_line/2, linebuf, procdata->bits_per_channel, procdata->invert); } } else if (procdata->invert) { hp_soft_invert(bytes_per_line,linebuf); } if ( ph->image_buf ) { DBG(5, "process_scanline: save in memory\n"); if ( ph->image_ptr+out_bytes_per_line-1 <= ph->image_buf+ph->image_buf_size-1 ) { memcpy(ph->image_ptr, linebuf, out_bytes_per_line); ph->image_ptr += out_bytes_per_line; } else { DBG(1, "process_scanline: would exceed image buffer\n"); } } else /* Save scanlines in a bigger buffer. */ { /* Otherwise we will get performance problems */ RETURN_IF_FAIL ( process_data_write (ph, linebuf, out_bytes_per_line) ); } return SANE_STATUS_GOOD; } static SANE_Status process_data (PROCDATA_HANDLE *ph, unsigned char *read_ptr, int nread) {int bytes_left; if (nread <= 0) return SANE_STATUS_GOOD; if (ph == NULL) return SANE_STATUS_INVAL; if ( ph->tmp_buf_len > 0 ) /* Something left ? */ { bytes_left = ph->tmp_buf_size - ph->tmp_buf_len; if (nread < bytes_left) /* All to buffer ? */ { memcpy (ph->tmp_buf+ph->tmp_buf_len, read_ptr, nread); ph->tmp_buf_len += nread; return SANE_STATUS_GOOD; } memcpy (ph->tmp_buf+ph->tmp_buf_len, read_ptr, bytes_left); read_ptr += bytes_left; nread -= bytes_left; RETURN_IF_FAIL ( process_scanline (ph, ph->tmp_buf, ph->tmp_buf_size) ); ph->tmp_buf_len = 0; } while (nread > 0) { if (nread >= ph->tmp_buf_size) { RETURN_IF_FAIL ( process_scanline (ph, read_ptr, ph->tmp_buf_size) ); read_ptr += ph->tmp_buf_size; nread -= ph->tmp_buf_size; } else { memcpy (ph->tmp_buf, read_ptr, nread); ph->tmp_buf_len = nread; nread = 0; } } return SANE_STATUS_GOOD; } static SANE_Status process_data_flush (PROCDATA_HANDLE *ph) {SANE_Status status = SANE_STATUS_GOOD; HpProcessData *procdata; unsigned char *image_data; size_t image_len; int num_lines, bytes_per_line; int nbytes; if (ph == NULL) return SANE_STATUS_INVAL; if ( ph->tmp_buf_len > 0 ) process_scanline (ph, ph->tmp_buf, ph->tmp_buf_len); if ( ph->wr_left != ph->wr_buf_size ) /* Something in write buffer ? */ { nbytes = ph->wr_buf_size - ph->wr_left; if ( signal_caught || (write (ph->outfd, ph->wr_buf, nbytes) != nbytes)) { DBG(1, "process_data_flush: write failed: %s\n", signal_caught ? "signal caught" : strerror(errno)); return SANE_STATUS_IO_ERROR; } ph->wr_ptr = ph->wr_buf; ph->wr_left = ph->wr_buf_size; } procdata = &(ph->procdata); if ( ph->image_buf ) { bytes_per_line = procdata->bytes_per_line; if (procdata->out8) bytes_per_line /= 2; image_len = (size_t) (ph->image_ptr - ph->image_buf); num_lines = ((int)(image_len + bytes_per_line-1)) / bytes_per_line; DBG(3, "process_data_finish: write %d bytes from memory...\n", (int)image_len); if ( procdata->mirror_vertical ) { image_data = ph->image_buf + (num_lines-1) * bytes_per_line; while (num_lines > 0 ) { if ( signal_caught || (write(ph->outfd, image_data, bytes_per_line) != bytes_per_line)) { DBG(1,"process_data_finish: write from memory failed: %s\n", signal_caught ? "signal caught" : strerror(errno)); status = SANE_STATUS_IO_ERROR; break; } num_lines--; image_data -= bytes_per_line; } } else { image_data = ph->image_buf; while (num_lines > 0 ) { if ( signal_caught || (write(ph->outfd, image_data, bytes_per_line) != bytes_per_line)) { DBG(1,"process_data_finish: write from memory failed: %s\n", signal_caught ? "signal caught" : strerror(errno)); status = SANE_STATUS_IO_ERROR; break; } num_lines--; image_data += bytes_per_line; } } } return status; } static void process_data_finish (PROCDATA_HANDLE *ph) { DBG(12, "process_data_finish called\n"); if (ph == NULL) return; if (ph->image_buf != NULL) sanei_hp_free (ph->image_buf); sanei_hp_free (ph->tmp_buf); sanei_hp_free (ph); } SANE_Status sanei_hp_scsi_pipeout (HpScsi this, int outfd, HpProcessData *procdata) { /* We will catch these signals, and rethrow them after cleaning up, * anything not in this list, we will ignore. */ static int kill_sig[] = { SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, SIGUSR2, SIGBUS, #ifdef SIGSTKFLT SIGSTKFLT, #endif #ifdef SIGIO SIGIO, #else # ifdef SIGPOLL SIGPOLL, # endif #endif #ifdef SIGXCPU SIGXCPU, #endif #ifdef SIGXFSZ SIGXFSZ, #endif #ifdef SIGVTALRM SIGVTALRM, #endif #ifdef SIGPWR SIGPWR, #endif }; #define HP_NSIGS (sizeof(kill_sig)/sizeof(kill_sig[0])) struct SIGACTION old_handler[HP_NSIGS]; struct SIGACTION sa; sigset_t old_set, sig_set; int i; int bits_per_channel = procdata->bits_per_channel; #define HP_PIPEBUF 32768 SANE_Status status = SANE_STATUS_GOOD; struct { size_t len; void * id; hp_byte_t cmd[6]; hp_byte_t data[HP_PIPEBUF]; } buf[2], *req = NULL; int reqs_completed = 0; int reqs_issued = 0; char *image_buf = 0; char *read_buf = 0; const HpDeviceInfo *info; const char *devname = sanei_hp_scsi_devicename (this); int enable_requests = 1; int enable_image_buffering = 0; const unsigned char *map = NULL; HpConnect connect; PROCDATA_HANDLE *ph = NULL; size_t count = procdata->lines * procdata->bytes_per_line; RETURN_IF_FAIL( hp_scsi_flush(this) ); connect = sanei_hp_get_connect (devname); info = sanei_hp_device_info_get (devname); assert (info); if ( info->config_is_up ) { enable_requests = info->config.use_scsi_request; enable_image_buffering = info->config.use_image_buffering; } else { enable_requests = 0; } if (connect != HP_CONNECT_SCSI) enable_requests = 0; /* Currently we can only simulate 8 bits mapping */ if (bits_per_channel == 8) map = hp_get_simulation_map (devname, info); sigfillset(&sig_set); sigprocmask(SIG_BLOCK, &sig_set, &old_set); memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_catcher; sigfillset(&sa.sa_mask); sigemptyset(&sig_set); for (i = 0; i < (int)(HP_NSIGS); i++) { sigaction(kill_sig[i], &sa, &old_handler[i]); sigaddset(&sig_set, kill_sig[i]); } signal_caught = 0; sigprocmask(SIG_UNBLOCK, &sig_set, 0); /* Wait for front button push ? */ if ( procdata->startscan ) { for (;;) {int val = 0; if (signal_caught) goto quit; sanei_hp_scl_inquire (this, SCL_FRONT_BUTTON, &val, 0, 0); if (val) break; usleep ((unsigned long)333*1000); /* Wait 1/3 second */ } status = sanei_hp_scl_startScan (this, procdata->startscan); if (status != SANE_STATUS_GOOD ) { DBG(1, "do_read: Error starting scan in reader process\n"); goto quit; } } ph = process_data_init (procdata, map, outfd, enable_image_buffering); if ( ph == NULL ) { DBG(1, "do_read: Error with process_data_init()\n"); goto quit; } DBG(1, "do_read: Start reading data from scanner\n"); if (enable_requests) /* Issue SCSI-requests ? */ { while (count > 0 || reqs_completed < reqs_issued) { while (count > 0 && reqs_issued < reqs_completed + 2) { req = buf + (reqs_issued++ % 2); req->len = HP_PIPEBUF; if (count < req->len) req->len = count; count -= req->len; req->cmd[0] = 0x08; req->cmd[1] = 0; req->cmd[2] = req->len >> 16; req->cmd[3] = req->len >> 8; req->cmd[4] = req->len; req->cmd[5] = 0; DBG(3, "do_read: entering request to read %lu bytes\n", (unsigned long) req->len); status = sanei_scsi_req_enter(this->fd, req->cmd, 6, req->data, &req->len, &req->id); if (status != SANE_STATUS_GOOD) { DBG(1, "do_read: Error from scsi_req_enter: %s\n", sane_strstatus(status)); goto quit; } if (signal_caught) goto quit; } if (signal_caught) goto quit; assert(reqs_completed < reqs_issued); req = buf + (reqs_completed++ % 2); DBG(3, "do_read: waiting for data\n"); status = sanei_scsi_req_wait(req->id); if (status != SANE_STATUS_GOOD) { DBG(1, "do_read: Error from scsi_req_wait: %s\n", sane_strstatus(status)); goto quit; } if (signal_caught) goto quit; status = process_data (ph, (unsigned char *)req->data, (int)req->len); if ( status != SANE_STATUS_GOOD ) { DBG(1,"do_read: Error in process_data\n"); goto quit; } } } else /* Read directly */ { read_buf = sanei_hp_alloc ( HP_PIPEBUF ); if (!read_buf) { DBG(1, "do_read: not enough memory for read buffer\n"); goto quit; } while (count > 0) {size_t nread; if (signal_caught) goto quit; DBG(5, "do_read: %lu bytes left to read\n", (unsigned long)count); nread = HP_PIPEBUF; if (nread > count) nread = count; DBG(3, "do_read: try to read data (%lu bytes)\n", (unsigned long)nread); status = hp_scsi_read (this, read_buf, &nread, 0); if (status != SANE_STATUS_GOOD) { DBG(1, "do_read: Error from scsi_read: %s\n",sane_strstatus(status)); goto quit; } DBG(3, "do_read: got %lu bytes\n", (unsigned long)nread); if (nread <= 0) { DBG(1, "do_read: Nothing read\n"); continue; } status = process_data (ph, (unsigned char *)read_buf, (int)nread); if ( status != SANE_STATUS_GOOD ) { DBG(1,"do_read: Error in process_data\n"); goto quit; } count -= nread; } } process_data_flush (ph); quit: process_data_finish (ph); if ( image_buf ) sanei_hp_free ( image_buf ); if ( read_buf ) sanei_hp_free ( read_buf ); if (enable_requests && (reqs_completed < reqs_issued)) { DBG(1, "do_read: cleaning up leftover requests\n"); while (reqs_completed < reqs_issued) { req = buf + (reqs_completed++ % 2); sanei_scsi_req_wait(req->id); } } sigfillset(&sig_set); sigprocmask(SIG_BLOCK, &sig_set, 0); for (i = 0; i < (int)(HP_NSIGS); i++) sigaction(kill_sig[i], &old_handler[i], 0); sigprocmask(SIG_SETMASK, &old_set, 0); if (signal_caught) { DBG(1, "do_read: caught signal %d\n", signal_caught); raise(signal_caught); return SANE_STATUS_CANCELLED; } return status; } /* * */ static SANE_Status _hp_scl_inq (HpScsi scsi, HpScl scl, HpScl inq_cmnd, void *valp, size_t *lengthp) { size_t bufsize = 16 + (lengthp ? *lengthp: 0); char * buf = alloca(bufsize); char expect[16], expect_char; int val, count; SANE_Status status; if (!buf) return SANE_STATUS_NO_MEM; /* Flush data before sending inquiry. */ /* Otherwise scanner might not generate a response. */ RETURN_IF_FAIL( hp_scsi_flush (scsi)) ; RETURN_IF_FAIL( hp_scsi_scl(scsi, inq_cmnd, SCL_INQ_ID(scl)) ); usleep (1000); /* 500 works, too, but not 100 */ status = hp_scsi_read(scsi, buf, &bufsize, 1); if (FAILED(status)) { DBG(1, "scl_inq: read failed (%s)\n", sane_strstatus(status)); return status; } if (SCL_PARAM_CHAR(inq_cmnd) == 'R') expect_char = 'p'; else expect_char = tolower(SCL_PARAM_CHAR(inq_cmnd) - 1); count = sprintf(expect, "\033*s%d%c", SCL_INQ_ID(scl), expect_char); if (memcmp(buf, expect, count) != 0) { DBG(1, "scl_inq: malformed response: expected '%s', got '%.*s'\n", expect, count, buf); return SANE_STATUS_IO_ERROR; } buf += count; if (buf[0] == 'N') { /* null response */ DBG(3, "scl_inq: parameter %d unsupported\n", SCL_INQ_ID(scl)); return SANE_STATUS_UNSUPPORTED; } if (sscanf(buf, "%d%n", &val, &count) != 1) { DBG(1, "scl_inq: malformed response: expected int, got '%.8s'\n", buf); return SANE_STATUS_IO_ERROR; } buf += count; expect_char = lengthp ? 'W' : 'V'; if (*buf++ != expect_char) { DBG(1, "scl_inq: malformed response: expected '%c', got '%.4s'\n", expect_char, buf - 1); return SANE_STATUS_IO_ERROR; } if (!lengthp) *(int *)valp = val; /* Get integer value */ else { if (val > (int)*lengthp) { DBG(1, "scl_inq: inquiry returned %d bytes, expected <= %lu\n", val, (unsigned long) *lengthp); return SANE_STATUS_IO_ERROR; } *lengthp = val; memcpy(valp, buf , *lengthp); /* Get binary data */ } return SANE_STATUS_GOOD; } SANE_Status sanei_hp_scl_upload_binary (HpScsi scsi, HpScl scl, size_t *lengthhp, char **bufhp) { size_t bufsize = 16, sv; char * buf = alloca(bufsize); char * bufstart = buf; char * hpdata; char expect[16], expect_char; int n, val, count; SANE_Status status; if (!buf) return SANE_STATUS_NO_MEM; assert ( IS_SCL_DATA_TYPE (scl) ); /* Flush data before sending inquiry. */ /* Otherwise scanner might not generate a response. */ RETURN_IF_FAIL( hp_scsi_flush (scsi)) ; RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_UPLOAD_BINARY_DATA, SCL_INQ_ID(scl)) ); status = hp_scsi_read(scsi, buf, &bufsize, 0); if (FAILED(status)) { DBG(1, "scl_upload_binary: read failed (%s)\n", sane_strstatus(status)); return status; } expect_char = 't'; count = sprintf(expect, "\033*s%d%c", SCL_INQ_ID(scl), expect_char); if (memcmp(buf, expect, count) != 0) { DBG(1, "scl_upload_binary: malformed response: expected '%s', got '%.*s'\n", expect, count, buf); return SANE_STATUS_IO_ERROR; } buf += count; if (buf[0] == 'N') { /* null response */ DBG(1, "scl_upload_binary: parameter %d unsupported\n", SCL_INQ_ID(scl)); return SANE_STATUS_UNSUPPORTED; } if (sscanf(buf, "%d%n", &val, &count) != 1) { DBG(1, "scl_inq: malformed response: expected int, got '%.8s'\n", buf); return SANE_STATUS_IO_ERROR; } buf += count; expect_char = 'W'; if (*buf++ != expect_char) { DBG(1, "scl_inq: malformed response: expected '%c', got '%.4s'\n", expect_char, buf - 1); return SANE_STATUS_IO_ERROR; } *lengthhp = val; *bufhp = hpdata = sanei_hp_alloc ( val ); if (!hpdata) return SANE_STATUS_NO_MEM; if (buf < bufstart + bufsize) { n = bufsize - (buf - bufstart); if (n > val) n = val; memcpy (hpdata, buf, n); hpdata += n; val -= n; } status = SANE_STATUS_GOOD; if ( val > 0 ) { sv = val; status = hp_scsi_read(scsi, hpdata, &sv, 0); if (status != SANE_STATUS_GOOD) sanei_hp_free ( *bufhp ); } return status; } SANE_Status sanei_hp_scl_set(HpScsi scsi, HpScl scl, int val) { RETURN_IF_FAIL( hp_scsi_scl(scsi, scl, val) ); #ifdef PARANOID RETURN_IF_FAIL( sanei_hp_scl_errcheck(scsi) ); #endif return SANE_STATUS_GOOD; } SANE_Status sanei_hp_scl_inquire(HpScsi scsi, HpScl scl, int * valp, int * minp, int * maxp) { HpScl inquiry = ( IS_SCL_CONTROL(scl) ? SCL_INQUIRE_PRESENT_VALUE : SCL_INQUIRE_DEVICE_PARAMETER ); assert(IS_SCL_CONTROL(scl) || IS_SCL_PARAMETER(scl)); assert(IS_SCL_CONTROL(scl) || (!minp && !maxp)); if (valp) RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, inquiry, valp, 0) ); if (minp) RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, SCL_INQUIRE_MINIMUM_VALUE, minp, 0) ); if (maxp) RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, SCL_INQUIRE_MAXIMUM_VALUE, maxp, 0) ); return SANE_STATUS_GOOD; } #ifdef _HP_NOT_USED static SANE_Status hp_scl_get_bounds(HpScsi scsi, HpScl scl, int * minp, int * maxp) { assert(IS_SCL_CONTROL(scl)); RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, SCL_INQUIRE_MINIMUM_VALUE, minp, 0) ); return _hp_scl_inq(scsi, scl, SCL_INQUIRE_MAXIMUM_VALUE, maxp, 0); } #endif #ifdef _HP_NOT_USED static SANE_Status hp_scl_get_bounds_and_val(HpScsi scsi, HpScl scl, int * minp, int * maxp, int * valp) { assert(IS_SCL_CONTROL(scl)); RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, SCL_INQUIRE_MINIMUM_VALUE, minp, 0) ); RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, SCL_INQUIRE_MAXIMUM_VALUE, maxp, 0) ); return _hp_scl_inq(scsi, scl, SCL_INQUIRE_PRESENT_VALUE, valp, 0); } #endif SANE_Status sanei_hp_scl_download(HpScsi scsi, HpScl scl, const void * valp, size_t len) { assert(IS_SCL_DATA_TYPE(scl)); sanei_hp_scl_clearErrors ( scsi ); RETURN_IF_FAIL( hp_scsi_need(scsi, 16) ); RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_DOWNLOAD_TYPE, SCL_INQ_ID(scl)) ); /* Download type not supported ? */ RETURN_IF_FAIL( sanei_hp_scl_errcheck(scsi) ); RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_DOWNLOAD_LENGTH, len) ); RETURN_IF_FAIL( hp_scsi_write(scsi, valp, len) ); #ifdef PARANOID RETURN_IF_FAIL( sanei_hp_scl_errcheck(scsi) ); #endif return SANE_STATUS_GOOD; } SANE_Status sanei_hp_scl_upload(HpScsi scsi, HpScl scl, void * valp, size_t len) { size_t nread = len; HpScl inquiry = ( IS_SCL_DATA_TYPE(scl) ? SCL_UPLOAD_BINARY_DATA : SCL_INQUIRE_DEVICE_PARAMETER ); assert(IS_SCL_DATA_TYPE(scl) || IS_SCL_PARAMETER(scl)); RETURN_IF_FAIL( _hp_scl_inq(scsi, scl, inquiry, valp, &nread) ); if (IS_SCL_PARAMETER(scl) && nread < len) ((char *)valp)[nread] = '\0'; else if (len != nread) { DBG(1, "scl_upload: requested %lu bytes, got %lu\n", (unsigned long) len, (unsigned long) nread); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } SANE_Status sanei_hp_scl_calibrate(HpScsi scsi) { RETURN_IF_FAIL( hp_scsi_scl(scsi, SCL_CALIBRATE, 0) ); return hp_scsi_flush(scsi); } SANE_Status sanei_hp_scl_startScan(HpScsi scsi, HpScl scl) { char *msg = ""; if (scl == SCL_ADF_SCAN) msg = " (ADF)"; else if (scl == SCL_XPA_SCAN) msg = " (XPA)"; else scl = SCL_START_SCAN; DBG(1, "sanei_hp_scl_startScan: Start scan%s\n", msg); /* For active XPA we must not use XPA scan */ if ((scl == SCL_XPA_SCAN) && sanei_hp_is_active_xpa (scsi)) { DBG(3,"Map XPA scan to scan because of active XPA\n"); scl = SCL_START_SCAN; } RETURN_IF_FAIL( hp_scsi_scl(scsi, scl, 0) ); return hp_scsi_flush(scsi); } SANE_Status sanei_hp_scl_reset(HpScsi scsi) { RETURN_IF_FAIL( hp_scsi_write(scsi, "\033E", 2) ); RETURN_IF_FAIL( hp_scsi_flush(scsi) ); return sanei_hp_scl_errcheck(scsi); } SANE_Status sanei_hp_scl_clearErrors(HpScsi scsi) { RETURN_IF_FAIL( hp_scsi_flush(scsi) ); RETURN_IF_FAIL( hp_scsi_write(scsi, "\033*oE", 4) ); return hp_scsi_flush(scsi); } static const char * hp_scl_strerror (int errnum) { static const char * errlist[] = { "Command Format Error", "Unrecognized Command", "Parameter Error", "Illegal Window", "Scaling Error", "Dither ID Error", "Tone Map ID Error", "Lamp Error", "Matrix ID Error", "Cal Strip Param Error", "Gross Calibration Error" }; if (errnum >= 0 && errnum < (int)(sizeof(errlist)/sizeof(errlist[0]))) return errlist[errnum]; else switch(errnum) { case 1024: return "ADF Paper Jam"; case 1025: return "Home Position Missing"; case 1026: return "Paper Not Loaded"; default: return "??Unknown Error??"; } } /* Check for SCL errors */ SANE_Status sanei_hp_scl_errcheck (HpScsi scsi) { int errnum; int nerrors; SANE_Status status; status = sanei_hp_scl_inquire(scsi, SCL_CURRENT_ERROR_STACK, &nerrors,0,0); if (!FAILED(status) && nerrors) status = sanei_hp_scl_inquire(scsi, SCL_OLDEST_ERROR, &errnum,0,0); if (FAILED(status)) { DBG(1, "scl_errcheck: Can't read SCL error stack: %s\n", sane_strstatus(status)); return SANE_STATUS_IO_ERROR; } if (nerrors) { DBG(1, "Scanner issued SCL error: (%d) %s\n", errnum, hp_scl_strerror(errnum)); sanei_hp_scl_clearErrors (scsi); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/plustek-usbhw.c0000664000175000017500000013455612775277260015627 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbhw.c * @brief Functions to control the scanner hardware. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2013 Gerhard Jaeger * * History: * - 0.40 - starting version of the USB support * - 0.41 - added EPSON1250 specific stuff * - added alternative usb_IsScannerReady function * - 0.42 - added warmup stuff * - added UMAX 3400 stuff * - fixed problem with minimum wait time... * - 0.43 - added usb_switchLamp for non-Plustek devices * - 0.44 - added bStepsToReverse and active Pixelstart values * - to resetRegister function * - modified getLampStatus function for CIS devices * - added usb_Wait4Warmup() * - moved usb_IsEscPressed to this file * - added usb_switchLampX * - do now not reinitialized MISC I/O pins upon reset registers * - 0.45 - added function usb_AdjustLamps() to tweak CIS lamp settings * - fixed NULL pointer problem in lamp-off ISR * - added usb_AdjustCISLampSettings() * - skipping warmup for CIS devices * - 0.46 - fixed problem in usb_GetLampStatus for CIS devices, as we * read back reg[0x29] to wrong position * made it compile without itimer definitions * - 0.47 - moved usb_HostSwap() and usb_Swap() to this file. * - fixed lampOff timer for systems w/o setitimer * - added lamp off adjustment for CIS devices * - 0.48 - added usb_IsCISDevice() * - added usb_HasTPA() * - changed usb_Wait4Warmup() * - added usb_WaitPos() * - added usb_FillLampRegs() - sets also PWMDutyCylce now * - added UMAX3450 TPA autodetection * - 0.49 - a_bRegs is now part of the device structure * - fixed problem in backtracking, when speedup is enabled * - added usb_UpdateButtonStatus() * - 0.50 - added button support for Plustek/Genius devices * - changed behaviour of usb_IsScannerReady * - added special misc I/O setup for CIS devices (usb_ResetRegisters) * - 0.51 - change usb_AdjustLamps() and use it now in usb_switchLamp() * - added usb_Wait4ScanSample() and usb_InCalibrationMode() * - tweaked EjectPaper to work correctly with the supported sheet-fed * devices * - fixed button handling for Plustek/Genius devices and added * some more debug output to that code path * - 0.52 - changed DCapsDef, lamp -> misc_io * - hammer in output bit, when using misc io pins for lamp switching * - increased wait time for sheet-fed scanner (needed for Q-SCAN A6, * patch by Hiroshi Miura) * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifdef HAVE_SYS_TIME_H #include #endif #define DEV_LampReflection 1 #define DEV_LampTPA 2 #define DEV_LampAll 3 #define DEV_LampPositive 4 #define DEV_LampNegative 5 #define WAIT_TIME_FOR_SCAN_SAMPLE 20 /* 20 seconds maximum wait time */ /** the NatSemi 983x is a big endian chip, and the line protocol data all * arrives big-endian. This determines if we need to swap to host-order */ static SANE_Bool usb_HostSwap( void ) { u_short pattern = 0xfeed; /* deadbeef */ unsigned char *bytewise = (unsigned char *)&pattern; if ( bytewise[0] == 0xfe ) { DBG( _DBG_READ, "We're big-endian! No need to swap!\n" ); return 0; } DBG( _DBG_READ, "We're little-endian! NatSemi LM983x is big!\n" ); DBG( _DBG_READ, "--> Must swap data!\n" ); return 1; } /** as the name says.. */ static void usb_Swap( u_short *pw, u_long dwBytes ) { for( dwBytes /= 2; dwBytes--; pw++ ) _SWAP(((u_char*) pw)[0], ((u_char*)pw)[1]); } /** * This function is used to detect a cancel condition, * our ESC key is the SIGUSR1 signal. It is sent by the backend when the * cancel button has been pressed * * @param - none * @return the function returns SANE_TRUE if a cancel condition has been * detected, if not, it returns SANE_FALSE */ static SANE_Bool usb_IsEscPressed( void ) { sigset_t sigs; sigpending( &sigs ); if( sigismember( &sigs, SIGUSR1 )) { DBG( _DBG_INFO, "SIGUSR1 is pending --> Cancel detected\n" ); return SANE_TRUE; } return SANE_FALSE; } /** usb_GetMotorSet * according to the model, the function returns the address of * the corresponding entry of the Motor table */ static ClkMotorDef* usb_GetMotorSet( eModelDef model ) { int i; for( i = 0; i < MODEL_LAST; i++ ) { if( model == Motors[i].motorModel ) { return &(Motors[i]); } } return NULL; } /** switch motor on or off * @param handle - handle to open USB device * @param fOn - SANE_TRUE means motor on, SANE_FALSE means motor off * @return always SANE_TRUE */ static SANE_Bool usb_MotorOn( Plustek_Device *dev, SANE_Bool fOn ) { if( fOn ) dev->usbDev.a_bRegs[0x45] |= 0x10; else dev->usbDev.a_bRegs[0x45] &= ~0x10; usbio_WriteReg( dev->fd, 0x45, dev->usbDev.a_bRegs[0x45] ); return SANE_TRUE; } /** */ static SANE_Bool usb_IsCISDevice( Plustek_Device *dev ) { return ( dev->usbDev.HwSetting.bReg_0x26 & _ONE_CH_COLOR ); } /** */ static SANE_Bool usb_IsSheetFedDevice( Plustek_Device *dev ) { return ( dev->usbDev.Caps.wFlags & DEVCAPSFLAG_SheetFed ); } /** */ static SANE_Bool usb_InCalibrationMode( Plustek_Device *dev ) { if((dev->scanning.dwFlag & SCANFLAG_Calibration) == 0) return SANE_FALSE; return SANE_TRUE; } /** check if scanner is ready */ static SANE_Bool usb_IsScannerReady( Plustek_Device *dev ) { u_char value; double len; long timeout; struct timeval t; SANE_Status res; /* time in s = 1000*scanner length in inches/max step speed/in */ len = (dev->usbDev.Caps.Normal.Size.y/(double)_MEASURE_BASE) + 5; len = (1000.0 * len)/dev->usbDev.HwSetting.dMaxMoveSpeed; len /= 1000.0; /* wait at least 10 seconds... */ if( len < 10 ) len = 10; gettimeofday( &t, NULL); timeout = t.tv_sec + len; do { res = usbio_ReadReg( dev->fd, 7, &value); if( res != SANE_STATUS_GOOD ) { sleep(1); } else { if( value == 0 ) { _UIO( usbio_ResetLM983x( dev )); return SANE_TRUE; } if((value == 0) || (value >= 0x20) || (value == 0x03)) { if( !usbio_WriteReg( dev->fd, 0x07, 0 )) { DBG( _DBG_ERROR, "Scanner not ready!!!\n" ); return SANE_FALSE; } else { return SANE_TRUE; } } } gettimeofday( &t, NULL); } while( t.tv_sec < timeout ); DBG( _DBG_ERROR, "Scanner not ready!!!\n" ); return SANE_FALSE; } /** */ static SANE_Bool usb_SensorAdf( Plustek_Device *dev ) { u_char value; if( usb_IsSheetFedDevice(dev)) return SANE_FALSE; usbio_ReadReg( dev->fd, 0x02, &value ); return (value & 0x20); } /** */ static SANE_Bool usb_SensorPaper( Plustek_Device *dev ) { DCapsDef *sc = &dev->usbDev.Caps; u_char val, mask = 0x02; usbio_ReadReg( dev->fd, 0x02, &val ); if( usb_IsSheetFedDevice(dev)) mask = _GET_PAPERSENSE_PORT(sc->misc_io); return (val & mask); } /** function for sheet-fed devices, to make sure, that there's * something to scan */ static SANE_Bool usb_Wait4ScanSample( Plustek_Device *dev ) { struct timeval start_time, t2; if( !usb_IsSheetFedDevice(dev)) return SANE_TRUE; DBG( _DBG_INFO2, "Waiting for something to scan...\n" ); gettimeofday( &start_time, NULL ); do { gettimeofday( &t2, NULL ); if( t2.tv_sec > start_time.tv_sec + WAIT_TIME_FOR_SCAN_SAMPLE ) { DBG( _DBG_ERROR, "Nothing to scan!!!\n" ); return SANE_FALSE; } if( usb_IsEscPressed()) return SANE_FALSE; } while( !usb_SensorPaper( dev )); /* just a little delay, to make sure the paper is taken by the scanner */ usleep(100* 1000); DBG( _DBG_INFO2, "... okay, scanning now!\n" ); return SANE_TRUE; } /** function to move the sensor and to speed it up to a certain speed until * the position is reached */ static SANE_Bool usb_WaitPos( Plustek_Device *dev, u_long to, SANE_Bool stay ) { SANE_Bool retval; u_char value, mclk_div, mch; u_char r[2]; u_short ffs, step, min_ffs; long dwTicks; double maxf, fac, speed; struct timeval start_time, t2; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; /* get current master clock divider */ usbio_ReadReg( dev->fd, 0x08, &value ); mclk_div = (value >> 1) + 1; /* get current channel mode */ usbio_ReadReg( dev->fd, 0x26, &value ); mch = ((value & 0x07) > 1) ? 1:3; /* calculate the current speed */ ffs = regs[0x48] * 256 + regs[0x49]; speed = ((double)CRYSTAL_FREQ) /(double)((u_long)mclk_div * 32UL * (u_long)mch * (u_long)ffs * hw->wMotorDpi); /* disabled ? */ if((hw->dHighSpeed == 0.0) || (dev->adj.disableSpeedup != 0)) { min_ffs = 0xffff; maxf = 0.0; if( !stay ) return SANE_TRUE; } else { min_ffs = (u_short)(CRYSTAL_FREQ /((u_long)mclk_div * 32UL * (u_long)mch * hw->dHighSpeed * hw->wMotorDpi)); maxf = (ffs - min_ffs)/4; if( maxf > 100.0 ) maxf = 100.0; if( maxf < 5.0 ) maxf = 5.0; DBG( _DBG_INFO2, ">>>> CURRENT MCLK_DIV = %u\n", mclk_div ); DBG( _DBG_INFO2, ">>>> MCH = %u\n", mch ); DBG( _DBG_INFO2, ">>>> FFS = %u\n", ffs ); DBG( _DBG_INFO2, ">>>> HIGH-SPEED = %.3f (%.3f)\n", speed, hw->dHighSpeed); DBG( _DBG_INFO2, ">>>> MIN_FFS = %u (%.3f)\n", min_ffs, maxf); } gettimeofday( &start_time, NULL ); dwTicks = start_time.tv_sec + to; step = 1; retval = SANE_FALSE; for(;;) { usleep( 1000 ); _UIO( usbio_ReadReg( dev->fd, 0x07, &value )); if (!value) return SANE_TRUE; gettimeofday(&t2, NULL); if( t2.tv_sec > dwTicks ) break; if( min_ffs != 0xffff ) { fac = maxf/step; if( ffs ) { if((u_short)fac < ffs ) { ffs -= fac; if( ffs < min_ffs ) ffs = min_ffs; } else { if(ffs != min_ffs ) ffs = min_ffs; else ffs = 0; } } if( ffs >= min_ffs ) { if((int)fac > 25 ) usleep( 150 * 1000 ); r[0] = (u_char)(ffs >> 8); r[1] = (u_char)(ffs & 0xFF); sanei_lm983x_write(dev->fd, 0x48, r, 2, SANE_TRUE); if(ffs == min_ffs ) ffs = 0; } else { if( !stay ) { retval = SANE_TRUE; break; } } step++; } } return retval; } /** function to move the sensor or if sheet-fed device, to move the paper. * In moving backward-mode, the home sensor is always turned on. * @param action - what to do * @param steps - steps to move, based on 300dpi, 0 means move forever */ static SANE_Bool usb_ModuleMove( Plustek_Device *dev, u_char action, u_long dwStep ) { SANE_Bool retval, ejected; u_char bReg2, reg7, mclk_div; u_short wFastFeedStepSize; double dMaxMoveSpeed; ClkMotorDef *clk; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; if( action != MOVE_ToPaperSensor && action != MOVE_EjectAllPapers && action != MOVE_SkipPaperSensor && action != MOVE_ToShading && !dwStep ) { return SANE_TRUE; } if( !usb_IsScannerReady( dev )) { DBG( _DBG_ERROR, "Sensor-position NOT reached\n" ); return SANE_FALSE; } if( action == MOVE_EjectAllPapers ) { double d = hw->dMaxMoveSpeed; /* FIXME */ if (hw->motorModel == MODEL_QSCAN_A6){ DBG( _DBG_INFO2, "Q-SCAN-A6 may not be able to detect ejected papers\n"); return SANE_TRUE; } hw->dMaxMoveSpeed += 0.8; /* was 0.6 */ DBG( _DBG_INFO2, "Ejecting paper...\n" ); retval = SANE_TRUE; ejected = SANE_FALSE; do { if( usb_SensorPaper(dev)) { if (!usb_ModuleMove(dev,MOVE_SkipPaperSensor, 0 )) { hw->dMaxMoveSpeed = d; return SANE_FALSE; } ejected = SANE_TRUE; } if( usb_SensorAdf(dev) && !usb_ModuleMove(dev,MOVE_ToPaperSensor, 0 )) { hw->dMaxMoveSpeed = d; return SANE_FALSE; } if( usb_IsEscPressed()) { retval = SANE_FALSE; break; } } while( usb_SensorPaper(dev)); /* when the paper is beyond the sensor, we move another 300 steps * to make sure, that the scanned sheet is out of the scanner * BUT: not at startup */ if (dev->initialized >= 0 || ejected) { DBG(_DBG_INFO2, "... MORE EJECT...\n"); if(!usb_ModuleMove( dev, MOVE_Forward, 300 /* *3 */)) { hw->dMaxMoveSpeed = d; return SANE_FALSE; } } usbio_WriteReg( dev->fd, 0x07, 0); usbio_WriteReg( dev->fd, 0x58, regs[0x58]); usbio_ReadReg( dev->fd, 0x02, &bReg2 ); hw->dMaxMoveSpeed = d; DBG( _DBG_INFO2, "...done\n" ); return retval; } usbio_WriteReg( dev->fd, 0x0a, 0 ); /* Compute fast feed step size, use equation 3 and equation 8 */ dMaxMoveSpeed = hw->dMaxMoveSpeed; if( action == MOVE_ToShading ) { if( hw->dMaxMoveSpeed > 0.5 ) dMaxMoveSpeed = hw->dMaxMoveSpeed - 0.5; } clk = usb_GetMotorSet( hw->motorModel ); mclk_div = clk->mclk_fast; wFastFeedStepSize = (u_short)(CRYSTAL_FREQ / ((u_long)mclk_div * 8UL * 1 * dMaxMoveSpeed * 4 * hw->wMotorDpi)); regs[0x48] = (u_char)(wFastFeedStepSize >> 8); regs[0x49] = (u_char)(wFastFeedStepSize & 0xFF); dwStep = dwStep * hw->wMotorDpi / 300UL; regs[0x4a] = _HIBYTE(_LOWORD(dwStep)); regs[0x4b] = _LOBYTE(_LOWORD(dwStep)); regs[0x45] |= 0x10; DBG( _DBG_INFO2,"MotorDPI=%u, MaxMoveSpeed=%.3f, " "FFStepSize=%u, Steps=%lu\n", hw->wMotorDpi, hw->dMaxMoveSpeed, wFastFeedStepSize, dwStep ); DBG( _DBG_INFO2, "MOTOR: " "PWM=0x%02x, PWM_DUTY=0x%02x 0x45=0x%02x " "0x48=0x%02x, 0x49=0x%02x \n", regs[0x56], regs[0x57], regs[0x45], regs[0x48], regs[0x49] ); DBG( _DBG_INFO2,"MCLK_FFW = %u --> 0x%02x\n", mclk_div, (mclk_div-1)*2 ); /* The setting for chassis moving is: * MCLK divider = 6, 8 bits/pixel, HDPI divider = 12, * no integration time adjustment and 1 channel grayscale */ /* MCLK divider = 6 */ if( !usbio_WriteReg(dev->fd, 0x08, (mclk_div-1)*2 /*0x0A*/)) return SANE_FALSE; /* 8 bits/pixel, HDPI divider = 12 */ if( !usbio_WriteReg(dev->fd, 0x09, 0x1F)) return SANE_FALSE; /* Turn off integration time adjustment */ if( !usbio_WriteReg(dev->fd, 0x19, 0)) return SANE_FALSE; /* 1 channel grayscale, green channel */ if( !usbio_WriteReg(dev->fd, 0x26, 0x0C)) return SANE_FALSE; _UIO(sanei_lm983x_write(dev->fd, 0x48, ®s[0x48], 2, SANE_TRUE)); _UIO(sanei_lm983x_write(dev->fd, 0x4A, ®s[0x4A], 2, SANE_TRUE)); /* disable home */ if( !usbio_WriteReg(dev->fd, 0x58, regs[0x58] & ~7)) return SANE_FALSE; if( !usbio_WriteReg(dev->fd, 0x45, regs[0x45] )) return SANE_FALSE; if( action == MOVE_Forward || action == MOVE_ToShading ) reg7 = 5; else if( action == MOVE_Backward ) reg7 = 6; else if( action == MOVE_ToPaperSensor || action == MOVE_EjectAllPapers || action == MOVE_SkipPaperSensor ) { reg7 = 1; } else { return SANE_TRUE; } retval = SANE_FALSE; /* start the sensor... */ if( usbio_WriteReg( dev->fd, 0x07, reg7 )) { long secs; struct timeval start_time, t2; /* at least we move 20 seconds before timeout... */ gettimeofday( &start_time, NULL ); secs = start_time.tv_sec + 20; if( action == MOVE_ToPaperSensor ) { for(;;) { if( usb_SensorPaper( dev )) { usbio_WriteReg( dev->fd, 0x07, 0 ); usbio_WriteReg( dev->fd, 0x58, regs[0x58] ); usbio_ReadReg ( dev->fd, 0x02, &bReg2 ); return SANE_TRUE; } gettimeofday(&t2, NULL); if( t2.tv_sec > secs ) break; } } else if( action == MOVE_SkipPaperSensor ) { for(;;) { if( !usb_SensorPaper( dev )) { usbio_WriteReg( dev->fd, 0x07, 0 ); usbio_WriteReg( dev->fd, 0x58, regs[0x58] ); usbio_ReadReg ( dev->fd, 0x02, &bReg2 ); return SANE_TRUE; } gettimeofday(&t2, NULL); if( t2.tv_sec > secs ) break; } } else { retval = usb_WaitPos( dev, 200, SANE_TRUE ); } usbio_WriteReg( dev->fd, 0x58, regs[0x58] ); usbio_ReadReg ( dev->fd, 0x02, &bReg2 ); } if( !retval ) DBG( _DBG_ERROR, "Position NOT reached\n" ); return retval; } /** */ static SANE_Bool usb_ModuleToHome( Plustek_Device *dev, SANE_Bool fWait ) { u_char mclk_div; u_char value; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; if( usb_IsSheetFedDevice(dev)) { return usb_ModuleMove( dev, MOVE_EjectAllPapers, 0 ); } /* Check if merlin is ready for setting command */ usbio_WriteReg( dev->fd, 0x58, hw->bReg_0x58 ); usbio_ReadReg ( dev->fd, 2, &value ); if( value & 1 ) { dev->usbDev.fModFirstHome = SANE_FALSE; return SANE_TRUE; } _UIO( usbio_ReadReg( dev->fd, 0x07, &value )); if( dev->usbDev.fModFirstHome ) { dev->usbDev.fModFirstHome = SANE_FALSE; if( hw->motorModel != MODEL_Tokyo600 ) usb_ModuleMove( dev, MOVE_Forward, hw->wMotorDpi / 2); } /* if not homing, do it... */ if( value != 2 ) { u_short wFastFeedStepSize; if( hw->motorModel == MODEL_Tokyo600 ) { usbio_WriteReg( dev->fd, 0x07, 0 ); } else { _UIO( usbio_ResetLM983x( dev )); usleep(200*1000); } if(!_IS_PLUSTEKMOTOR(hw->motorModel)) { ClkMotorDef *clk; clk = usb_GetMotorSet( hw->motorModel ); regs[0x56] = clk->pwm_fast; regs[0x57] = clk->pwm_duty_fast; mclk_div = clk->mclk_fast; } else { mclk_div = 6; if( scaps->OpticDpi.x == 1200 || scaps->bPCB == 2) { switch( hw->motorModel ) { case MODEL_KaoHsiung: case MODEL_HuaLien: default: regs[0x56] = 1; regs[0x57] = 63; break; } } else { /* if(Device.Caps.OpticDpi.x == 600) */ switch( hw->motorModel ) { case MODEL_Tokyo600: regs[0x56] = 4; regs[0x57] = 4; /* 2; */ break; case MODEL_HuaLien: if( dev->caps.dwFlag & SFLAG_ADF ) { regs[0x56] = 64; /* 32; */ regs[0x57] = 4; /* 16; */ } else { regs[0x56] = 32; regs[0x57] = 16; } break; case MODEL_KaoHsiung: default: regs[0x56] = 64; regs[0x57] = 20; break; } } } /* Compute fast feed step size, use equation 3 and equation 8 * assumptions: MCLK = 6, Lineratemode (CM=1) */ wFastFeedStepSize = (u_short)(CRYSTAL_FREQ / (mclk_div * 8 * 1 * hw->dMaxMotorSpeed * 4 * hw->wMotorDpi)); regs[0x48] = (u_char)(wFastFeedStepSize >> 8); regs[0x49] = (u_char)(wFastFeedStepSize & 0xFF); regs[0x4a] = 0; regs[0x4b] = 0; regs[0x45] |= 0x10; DBG( _DBG_INFO2,"MotorDPI=%u, MaxMotorSpeed=%.3f, FFStepSize=%u\n", hw->wMotorDpi, hw->dMaxMotorSpeed, wFastFeedStepSize ); DBG( _DBG_INFO, "MOTOR: " "PWM=0x%02x, PWM_DUTY=0x%02x 0x45=0x%02x " "0x48=0x%02x, 0x49=0x%02x\n", regs[0x56], regs[0x57], regs[0x45], regs[0x48], regs[0x49] ); /* The setting for chassis moving is: * MCLK divider = 6, 8 bits/pixel, HDPI divider = 12, * no integration time adjustment and 1 channel grayscale */ /* MCLK divider = 6 */ value = (u_char)((mclk_div-1) * 2); DBG( _DBG_INFO, "MCLK_FFW = %u --> 0x%02x\n", mclk_div, value ); if( !usbio_WriteReg(dev->fd, 0x08, value)) return SANE_FALSE; /* 8 bits/pixel, HDPI divider = 12 */ if( !usbio_WriteReg(dev->fd, 0x09, 0x1F)) return SANE_FALSE; /* Turn off integration time adjustment */ if( !usbio_WriteReg(dev->fd, 0x19, 0)) return SANE_FALSE; /* 1 channel grayscale, green channel */ if( !usbio_WriteReg(dev->fd, 0x26, 0x8C)) return SANE_FALSE; _UIO(sanei_lm983x_write(dev->fd, 0x48, ®s[0x48], 4, SANE_TRUE)); _UIO(sanei_lm983x_write(dev->fd, 0x56, ®s[0x56], 3, SANE_TRUE)); if( !usbio_WriteReg(dev->fd, 0x45, regs[0x45])) return SANE_FALSE; usbio_WriteReg(dev->fd, 0x0a, 0); if( hw->motorModel == MODEL_HuaLien && scaps->OpticDpi.x == 600 ) usleep(100 * 1000); if( !usbio_WriteReg(dev->fd, 0x07, 2)) return SANE_FALSE; #if 0 if( hw->motorModel == MODEL_Tokyo600) { u_long dwSpeedUp = GetTickCount () + 250; /* while(GetTickCount () < dwSpeedUp) */ while((int)(dwSpeedUp - GetTickCount ()) > 0) { Sleep (10); if (!ReadRegister (0x07, &value)) return FALSE; if (!value) return TRUE; } wFastFeedStepSize = (WORD)(CRYSTAL_FREQ / (6UL * 8UL * 1 * Device.HwSetting.dMaxMotorSpeed * 4 * Device.HwSetting.wMotorDpi) * 60 / 78); regs[0x48] = (u_char)(wFastFeedStepSize >> 8); regs[0x49] = (u_char)(wFastFeedStepSize & 0xFF); WriteRegisters(0x48, ®s[0x48], 2); } #endif } return usb_WaitPos( dev, 150, fWait ); } /** */ static SANE_Bool usb_MotorSelect( Plustek_Device *dev, SANE_Bool fADF ) { DCapsDef *sCaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; if(!_IS_PLUSTEKMOTOR(hw->motorModel)) { return SANE_TRUE; } if( fADF ) { if( sCaps->bCCD == kNEC3778 ) { hw->wMotorDpi = 300; hw->dMaxMotorSpeed = 1.5; hw->dMaxMoveSpeed = 1.5; sCaps->OpticDpi.y = 600; } regs[0x5b] |= 0x80; } else { if( sCaps->bCCD == kNEC3778 ) { hw->wMotorDpi = 600; hw->dMaxMotorSpeed = 1.1; hw->dMaxMoveSpeed = 0.9; sCaps->OpticDpi.y = 1200; } regs[0x5b] &= ~0x80; } /* To stop the motor moving */ usbio_WriteReg( dev->fd, 0x07, 0 ); usleep(10 * 1000); usbio_WriteReg( dev->fd, 0x5b, regs[0x5b] ); return SANE_TRUE; } /** function to adjust the lamp settings of a CIS device without tweaking * the driver-device settings * @param dev - our almitghty device structure * @param on - switch the lamp on or off */ static SANE_Bool usb_AdjustLamps( Plustek_Device *dev, SANE_Bool on ) { HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; if( !usb_IsCISDevice(dev)) return SANE_TRUE; DBG(_DBG_INFO2, "usb_AdjustLamps(%u)\n", on ); if( on ) { regs[0x2c] = _HIBYTE(hw->red_lamp_on); regs[0x2d] = _LOBYTE(hw->red_lamp_on); regs[0x2e] = _HIBYTE(hw->red_lamp_off); regs[0x2f] = _LOBYTE(hw->red_lamp_off); regs[0x30] = _HIBYTE(hw->green_lamp_on); regs[0x31] = _LOBYTE(hw->green_lamp_on); regs[0x32] = _HIBYTE(hw->green_lamp_off); regs[0x33] = _LOBYTE(hw->green_lamp_off); regs[0x34] = _HIBYTE(hw->blue_lamp_on); regs[0x35] = _LOBYTE(hw->blue_lamp_on); regs[0x36] = _HIBYTE(hw->blue_lamp_off); regs[0x37] = _LOBYTE(hw->blue_lamp_off); } else { memset( ®s[0x2c], 0, 12 ); regs[0x2c] = 0x3f; regs[0x2d] = 0xff; regs[0x30] = 0x3f; regs[0x31] = 0xff; regs[0x34] = 0x3f; regs[0x35] = 0xff; } return sanei_lm983x_write( dev->fd, 0x2c, ®s[0x2c], 0x37-0x2c+1, SANE_TRUE ); } /** */ static void usb_AdjustCISLampSettings( Plustek_Device *dev, SANE_Bool on ) { HWDef *hw = &dev->usbDev.HwSetting; if( !usb_IsCISDevice(dev)) return; DBG( _DBG_INFO2, "AdjustCISLamps(%u)\n", on ); if((dev->scanning.sParam.bDataType == SCANDATATYPE_Gray) || (dev->scanning.sParam.bDataType == SCANDATATYPE_BW)) { DBG( _DBG_INFO2, " * setting mono mode\n" ); hw->bReg_0x29 = hw->illu_mono.mode; memcpy( &hw->red_lamp_on, &hw->illu_mono.red_lamp_on, sizeof(u_short) * 6 ); } else { DBG( _DBG_INFO2, " * setting color mode\n" ); hw->bReg_0x29 = hw->illu_color.mode; memcpy( &hw->red_lamp_on, &hw->illu_color.red_lamp_on, sizeof(u_short) * 6 ); } if( !on ) { hw->red_lamp_on = 0x3fff; hw->red_lamp_off = 0; hw->green_lamp_on = 0x3fff; hw->green_lamp_off = 0; hw->blue_lamp_on = 0x3fff; hw->blue_lamp_off = 0; } else { if( dev->adj.rlampoff > 0 ) { hw->red_lamp_off = dev->adj.rlampoff; if( hw->red_lamp_off > 0x3fff ) hw->red_lamp_off = 0x3fff; DBG( _DBG_INFO2, " * red_lamp_off adjusted: %u\n", hw->red_lamp_off ); } if( dev->adj.glampoff > 0 ) { hw->green_lamp_off = dev->adj.glampoff; if( hw->green_lamp_off > 0x3fff ) hw->green_lamp_off = 0x3fff; DBG( _DBG_INFO2, " * green_lamp_off adjusted: %u\n", hw->green_lamp_off ); } if( dev->adj.blampoff > 0 ) { hw->blue_lamp_off = dev->adj.blampoff; if( hw->blue_lamp_off > 0x3fff ) hw->blue_lamp_off = 0x3fff; DBG( _DBG_INFO2, " * blue_lamp_off adjusted: %u\n", hw->blue_lamp_off ); } } dev->usbDev.a_bRegs[0x29] = hw->bReg_0x29; usb_AdjustLamps( dev, on ); } /** according to the flag field, we return the register and * it's mask to turn on/off the lamp. * @param flag - field to check * @param reg - pointer to a var to receive the register value * @param msk - pointer to a var to receive the mask value * @return Nothing */ static void usb_GetLampRegAndMask( u_long flag, SANE_Byte *reg, SANE_Byte *msk ) { if( _MIO6 == ( _MIO6 & flag )) { *reg = 0x5b; *msk = 0x80; } else if( _MIO5 == ( _MIO5 & flag )) { *reg = 0x5b; *msk = 0x08; } else if( _MIO4 == ( _MIO4 & flag )) { *reg = 0x5a; *msk = 0x80; } else if( _MIO3 == ( _MIO3 & flag )) { *reg = 0x5a; *msk = 0x08; } else if( _MIO2 == ( _MIO2 & flag )) { *reg = 0x59; *msk = 0x80; } else if( _MIO1 == ( _MIO1 & flag )) { *reg = 0x59; *msk = 0x08; } else { *reg = 0; *msk = 0; } } /** usb_GetLampStatus * This function returns the current lamp in use. * For non Plustek devices, it always returns DEV_LampReflection. * @param dev - pointer to our device structure, * it should contain all we need * @return - 0 if the scanner hasn't been used before, DEV_LampReflection * for the normal lamp, or DEV_LampTPA for negative/transparency * lamp */ static int usb_GetLampStatus( Plustek_Device *dev ) { int iLampStatus = 0; u_char *regs = dev->usbDev.a_bRegs; HWDef *hw = &dev->usbDev.HwSetting; DCapsDef *sc = &dev->usbDev.Caps; SANE_Byte reg, msk, val; if( NULL == hw ) { DBG( _DBG_ERROR, "NULL-Pointer detected: usb_GetLampStatus()\n" ); return -1; } /* do we use the misc I/O pins for switching the lamp ? */ if( _WAF_MISC_IO_LAMPS & sc->workaroundFlag ) { usb_GetLampRegAndMask( sc->misc_io, ®, &msk ); if( 0 == reg ) { usbio_ReadReg( dev->fd, 0x29, ® ); if( reg & 3 ) iLampStatus |= DEV_LampReflection; } else { /* check if the lamp is on */ usbio_ReadReg( dev->fd, reg, &val ); DBG( _DBG_INFO2, "LAMP-REG[0x%02x] = 0x%02x (msk=0x%02x)\n", reg,val,msk); if( val & msk ) iLampStatus |= DEV_LampReflection; /* if the device supports a TPA, we check this here */ if( sc->wFlags & DEVCAPSFLAG_TPA ) { usb_GetLampRegAndMask( _GET_TPALAMP(sc->misc_io), ®, &msk ); if (reg) { usbio_ReadReg( dev->fd, reg, &val ); DBG( _DBG_INFO2, "TPA-REG[0x%02x] = 0x%02x (msk=0x%02x)\n", reg,val,msk); if( val & msk ) iLampStatus |= DEV_LampTPA; } } /* CanoScan D660U extra vaganza... */ if((dev->usbDev.vendor == 0x04A9) && (dev->usbDev.product==0x2208)) { sanei_lm983x_read( dev->fd, 0x29, ®s[0x29], 3, SANE_TRUE ); DBG( _DBG_INFO, "[29]=0x%02x, [2A]=0x%02x, [2B]=0x%02x\n", regs[0x29], regs[0x2a], regs[0x2b] ); } } } else { sanei_lm983x_read(dev->fd, 0x29,®s[0x29],0x37-0x29+1,SANE_TRUE); if((regs[0x29] & 3) == 1) { /* HEINER: BETTER define register to check ! */ if(!_IS_PLUSTEKMOTOR(hw->motorModel)) { iLampStatus |= DEV_LampReflection; } else { if((regs[0x2e] * 256 + regs[0x2f]) > hw->wLineEnd ) iLampStatus |= DEV_LampReflection; if((regs[0x36] * 256 + regs[0x37]) > hw->wLineEnd ) iLampStatus |= DEV_LampTPA; } } } DBG( _DBG_INFO, "LAMP-STATUS: 0x%08x (%s)\n", iLampStatus, iLampStatus?"on":"off" ); return iLampStatus; } /** usb_switchLampX * used for all devices that use some misc I/O pins to switch the lamp */ static SANE_Bool usb_switchLampX( Plustek_Device *dev, SANE_Bool on, SANE_Bool tpa ) { SANE_Byte reg, msk; DCapsDef *sc = &dev->usbDev.Caps; u_char *regs = dev->usbDev.a_bRegs; if( tpa ) usb_GetLampRegAndMask( _GET_TPALAMP(sc->misc_io), ®, &msk ); else usb_GetLampRegAndMask( sc->misc_io, ®, &msk ); if( 0 == reg ) return SANE_FALSE; /* no need to switch something */ DBG( _DBG_INFO, "usb_switchLampX(ON=%u,TPA=%u)\n", on, tpa ); if( on ) { /* in fact the output bit should be set by the default settings * but we make sure, that it is set anyway... */ if (msk & 0x08) msk |= 0x01; else msk |= 0x10; regs[reg] |= msk; } else { regs[reg] &= ~msk; } DBG( _DBG_INFO, "Switch Lamp: %u, regs[0x%02x] = 0x%02x\n", on, reg, regs[reg] ); usbio_WriteReg( dev->fd, reg, regs[reg] ); return SANE_TRUE; } /** usb_switchLamp * used for all devices that use some misc I/O pins to switch the lamp */ static SANE_Bool usb_switchLamp( Plustek_Device *dev, SANE_Bool on ) { SANE_Bool result; if((dev->scanning.sParam.bSource == SOURCE_Negative) || (dev->scanning.sParam.bSource == SOURCE_Transparency)) { result = usb_switchLampX( dev, on, SANE_TRUE ); } else { result = usb_switchLampX( dev, on, SANE_FALSE ); } /* to switch off CIS, we need to tweak the lampoff/on regs */ usb_AdjustLamps( dev, on ); return result; } /** usb_LedOn */ static void usb_LedOn( Plustek_Device *dev, SANE_Bool fOn ) { u_char value; if( dev->usbDev.HwSetting.motorModel != MODEL_HuaLien ) return; value = dev->usbDev.a_bRegs[0x0d]; if( fOn ) value |= 0x10; else value &= ~0x10; dev->usbDev.a_bRegs[0x0d] = value; usbio_WriteReg( dev->fd, 0x0d, value ); } /** usb_FillLampRegs * set all the registers controlling the lamps */ static void usb_FillLampRegs( Plustek_Device *dev ) { HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; regs[0x2a] = _HIBYTE( hw->wGreenPWMDutyCycleLow ); regs[0x2b] = _LOBYTE( hw->wGreenPWMDutyCycleLow ); regs[0x2c] = _HIBYTE( hw->red_lamp_on ); regs[0x2d] = _LOBYTE( hw->red_lamp_on ); regs[0x2e] = _HIBYTE( hw->red_lamp_off); regs[0x2f] = _LOBYTE( hw->red_lamp_off); regs[0x30] = _HIBYTE( hw->green_lamp_on ); regs[0x31] = _LOBYTE( hw->green_lamp_on ); regs[0x32] = _HIBYTE( hw->green_lamp_off); regs[0x33] = _LOBYTE( hw->green_lamp_off); regs[0x34] = _HIBYTE( hw->blue_lamp_on ); regs[0x35] = _LOBYTE( hw->blue_lamp_on ); regs[0x36] = _HIBYTE( hw->blue_lamp_off); regs[0x37] = _LOBYTE( hw->blue_lamp_off); } /** usb_LampOn */ static SANE_Bool usb_LampOn( Plustek_Device *dev, SANE_Bool fOn, SANE_Bool fResetTimer ) { DCapsDef *sc = &dev->usbDev.Caps; ScanDef *scanning = &dev->scanning; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; int iLampStatus = usb_GetLampStatus( dev ); int lampId = -1; struct timeval t; if( NULL == scanning ) { DBG( _DBG_ERROR, "NULL-Pointer detected: usb_LampOn()\n" ); return SANE_FALSE; } switch( scanning->sParam.bSource ) { case SOURCE_Reflection: case SOURCE_ADF: lampId = DEV_LampReflection; break; case SOURCE_Transparency: case SOURCE_Negative: lampId = DEV_LampTPA; break; } if( fOn ) { if( iLampStatus != lampId ) { DBG( _DBG_INFO, "Switching Lamp on\n" ); /* here we might have to switch off the TPA/Main lamp before * using the other one */ if( lampId != dev->usbDev.currentLamp ) { if( dev->usbDev.currentLamp == DEV_LampReflection ) usb_switchLampX( dev, SANE_FALSE, SANE_FALSE ); else usb_switchLampX( dev, SANE_FALSE, SANE_TRUE ); } memset( ®s[0x29], 0, (0x37-0x29+1)); regs[0x29] = hw->bReg_0x29; if( !usb_switchLamp(dev, SANE_TRUE )) { if( lampId == DEV_LampReflection ) { regs[0x2e] = 16383 / 256; regs[0x2f] = 16383 % 256; } if( lampId == DEV_LampTPA ) { regs[0x36] = 16383 / 256; regs[0x37] = 16383 % 256; } } if( _WAF_MISC_IO_LAMPS & sc->workaroundFlag ) usb_FillLampRegs( dev ); sanei_lm983x_write( dev->fd, 0x29, ®s[0x29], 0x37-0x29+1, SANE_TRUE ); if( lampId != dev->usbDev.currentLamp ) { dev->usbDev.currentLamp = lampId; if( fResetTimer ) { gettimeofday( &t, NULL ); dev->usbDev.dwTicksLampOn = t.tv_sec; DBG( _DBG_INFO, "Warmup-Timer started\n" ); } } } } else { int iStatusChange = iLampStatus & ~lampId; if( iStatusChange != iLampStatus ) { DBG( _DBG_INFO, "Switching Lamp off\n" ); memset( ®s[0x29], 0, 0x37-0x29+1 ); if( !usb_switchLamp(dev, SANE_FALSE )) { if( iStatusChange & DEV_LampReflection ) { regs[0x2e] = 16383 / 256; regs[0x2f] = 16383 % 256; } if( iStatusChange & DEV_LampTPA ) { regs[0x36] = 16383 / 256; regs[0x37] = 16383 % 256; } } if( _WAF_MISC_IO_LAMPS & sc->workaroundFlag ) usb_FillLampRegs( dev ); sanei_lm983x_write( dev->fd, 0x29, ®s[0x29], 0x37-0x29+1, SANE_TRUE ); } } if( usb_GetLampStatus(dev)) usb_LedOn( dev, SANE_TRUE ); else usb_LedOn( dev, SANE_FALSE ); return SANE_TRUE; } /** Function to preset the registers for the specific device, which * should never change during the whole operation * Affected registers:
* 0x0b - 0x0e - Sensor settings - directly from the HWDef
* 0x0f - 0x18 - Sensor Configuration - directly from the HwDef
* 0x1a - 0x1b - Stepper Phase Correction
* 0x20 - 0x21 - Line End
* 0x21 - 0x22 - Data Pixel start
* 0x23 - 0x24 - Data Pixel end
* 0x45 - Stepper Motor Mode
* 0x4c - 0x4d - Full Steps to Scan after PAPER SENSE 2 trips
* 0x50 - Steps to reverse when buffer is full
* 0x51 - Acceleration Profile
* 0x54 - 0x5e - Motor Settings, Paper-Sense Settings and Misc I/O
* * @param dev - pointer to our device structure, * it should contain all we need * @return - Nothing */ static void usb_ResetRegisters( Plustek_Device *dev ) { int linend; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; DBG( _DBG_INFO, "RESETTING REGISTERS(%i) - 0x%02x\n", dev->initialized, (int) sizeof(dev->usbDev.a_bRegs)); memset( regs, 0, sizeof(dev->usbDev.a_bRegs)); memcpy( regs+0x0b, &hw->bSensorConfiguration, 4 ); memcpy( regs+0x0f, &hw->bReg_0x0f_Color, 10 ); regs[0x1a] = _HIBYTE( hw->StepperPhaseCorrection ); regs[0x1b] = _LOBYTE( hw->StepperPhaseCorrection ); /* HEINER: CHECK WHY THIS has been disabled*/ #if 0 regs[0x1c] = hw->bOpticBlackStart; regs[0x1d] = hw->bOpticBlackEnd; regs[0x1e] = _HIBYTE( hw->wActivePixelsStart ); regs[0x1f] = _LOBYTE( hw->wActivePixelsStart ); #endif regs[0x20] = _HIBYTE( hw->wLineEnd ); regs[0x21] = _LOBYTE( hw->wLineEnd ); regs[0x22] = _HIBYTE( hw->bOpticBlackStart ); regs[0x23] = _LOBYTE( hw->bOpticBlackStart ); linend = hw->bOpticBlackStart + hw->wLineEnd; if( linend < (hw->wLineEnd-20)) linend = hw->wLineEnd-20; regs[0x24] = _HIBYTE( linend ); regs[0x25] = _LOBYTE( linend ); regs[0x2a] = _HIBYTE( hw->wGreenPWMDutyCycleHigh ); regs[0x2b] = _LOBYTE( hw->wGreenPWMDutyCycleHigh ); regs[0x45] = hw->bReg_0x45; regs[0x4c] = _HIBYTE( hw->wStepsAfterPaperSensor2 ); regs[0x4d] = _LOBYTE( hw->wStepsAfterPaperSensor2 ); regs[0x50] = hw->bStepsToReverse; regs[0x51] = hw->bReg_0x51; /* if already initialized, we ignore the MISC I/O settings as * they are used to determine the current lamp settings... */ if( dev->initialized >= 0 ) { DBG( _DBG_INFO2, "USING MISC I/O settings\n" ); memcpy( regs+0x54, &hw->bReg_0x54, 0x58 - 0x54 + 1 ); regs[0x5c] = hw->bReg_0x5c; regs[0x5d] = hw->bReg_0x5d; regs[0x5e] = hw->bReg_0x5e; sanei_lm983x_read( dev->fd, 0x59, ®s[0x59], 3, SANE_TRUE ); } else { DBG( _DBG_INFO2, "SETTING THE MISC I/Os\n" ); memcpy( regs+0x54, &hw->bReg_0x54, 0x5e - 0x54 + 1 ); if( usb_IsCISDevice( dev )) { /* this sequence seems to be needed at least for the * CanoScan devices to work properly after power-up */ sanei_lm983x_write_byte( dev->fd, 0x5b, regs[0x5b] ); sanei_lm983x_write_byte( dev->fd, 0x59, regs[0x59] ); sanei_lm983x_write_byte( dev->fd, 0x5a, regs[0x5a] ); } else { sanei_lm983x_write( dev->fd, 0x59, ®s[0x59], 3, SANE_TRUE ); } } DBG( _DBG_INFO, "MISC I/O after RESET: 0x%02x, 0x%02x, 0x%02x\n", regs[0x59], regs[0x5a], regs[0x5b] ); } /** function which checks if we are already in home position or not. * */ static SANE_Bool usb_SensorStatus( Plustek_Device *dev ) { u_char value; HWDef *hw = &dev->usbDev.HwSetting; /* HEINER: Maybe needed to avoid recalibration!!! */ #if 0 if( dev->scanning.fCalibrated ) return SANE_TRUE; #endif /* read the status register */ _UIO( usbio_ReadReg( dev->fd, 2, &value )); if( value & 1 ) { _UIO( usbio_ReadReg( dev->fd, 0x7, &value)); if( value ) { usbio_WriteReg( dev->fd, 0x07, 0 ); usbio_WriteReg( dev->fd, 0x07, 0x20 ); usbio_WriteReg( dev->fd, 0x07, 0 ); sanei_lm983x_write( dev->fd, 0x58, &hw->bReg_0x58, 0x5b-0x58+1, SANE_TRUE ); usbio_ReadReg( dev->fd, 2, &value ); usbio_ReadReg( dev->fd, 2, &value ); } usb_MotorOn( dev, SANE_FALSE ); return SANE_TRUE; } _UIO( usbio_ReadReg( dev->fd, 0x7, &value )); if( !(value & 2)) { usb_ModuleToHome( dev, SANE_FALSE ); } return SANE_FALSE; } /** */ static void usb_LampSwitch( Plustek_Device *dev, SANE_Bool sw ) { int handle = -1; if( -1 == dev->fd ) { if( SANE_STATUS_GOOD == sanei_usb_open(dev->sane.name, &handle)) { dev->fd = handle; } } /* needs to be recalibrated */ dev->scanning.fCalibrated = SANE_FALSE; if( -1 != dev->fd ) usb_LampOn( dev, sw, SANE_FALSE ); if( -1 != handle ) { dev->fd = -1; sanei_usb_close( handle ); } } /* HEINER: replace!!! */ static Plustek_Device *dev_xxx = NULL; /** ISR to switch lamp off after time has elapsed */ static void usb_LampTimerIrq( int sig ) { if( NULL == dev_xxx ) return; _VAR_NOT_USED( sig ); DBG( _DBG_INFO, "LAMP OFF!!!\n" ); usb_LampSwitch( dev_xxx, SANE_FALSE ); } /** usb_StartLampTimer */ static void usb_StartLampTimer( Plustek_Device *dev ) { sigset_t block, pause_mask; struct sigaction s; #ifdef HAVE_SETITIMER struct itimerval interval; #endif /* block SIGALRM */ sigemptyset( &block ); sigaddset ( &block, SIGALRM ); sigprocmask( SIG_BLOCK, &block, &pause_mask ); /* setup handler */ sigemptyset( &s.sa_mask ); sigaddset ( &s.sa_mask, SIGALRM ); s.sa_flags = 0; s.sa_handler = usb_LampTimerIrq; if( sigaction( SIGALRM, &s, NULL ) < 0 ) DBG( _DBG_ERROR, "Can't setup timer-irq handler\n" ); sigprocmask( SIG_UNBLOCK, &block, &pause_mask ); #ifdef HAVE_SETITIMER /* define a one-shot timer */ interval.it_value.tv_usec = 0; interval.it_value.tv_sec = dev->usbDev.dwLampOnPeriod; interval.it_interval.tv_usec = 0; interval.it_interval.tv_sec = 0; if( 0 != dev->usbDev.dwLampOnPeriod ) { dev_xxx = dev; setitimer( ITIMER_REAL, &interval, &dev->saveSettings ); DBG( _DBG_INFO, "Lamp-Timer started (using ITIMER)\n" ); } #else if( 0 != dev->usbDev.dwLampOnPeriod ) { dev_xxx = dev; alarm( dev->usbDev.dwLampOnPeriod ); DBG( _DBG_INFO, "Lamp-Timer started (using ALARM)\n" ); } #endif } /** usb_StopLampTimer */ static void usb_StopLampTimer( Plustek_Device *dev ) { sigset_t block, pause_mask; /* block SIGALRM */ sigemptyset( &block ); sigaddset ( &block, SIGALRM ); sigprocmask( SIG_BLOCK, &block, &pause_mask ); dev_xxx = NULL; #ifdef HAVE_SETITIMER if( 0 != dev->usbDev.dwLampOnPeriod ) setitimer( ITIMER_REAL, &dev->saveSettings, NULL ); #else _VAR_NOT_USED( dev ); alarm( 0 ); #endif DBG( _DBG_INFO, "Lamp-Timer stopped\n" ); } /** wait until warmup has been done */ static SANE_Bool usb_Wait4Warmup( Plustek_Device *dev ) { u_long dw; struct timeval t; if( usb_IsCISDevice(dev)) { DBG(_DBG_INFO,"Warmup: skipped for CIS devices\n" ); return SANE_TRUE; } if( dev->adj.warmup < 0 ) return SANE_TRUE; /* * wait until warmup period has been elapsed */ gettimeofday( &t, NULL); dw = t.tv_sec - dev->usbDev.dwTicksLampOn; if( dw < (u_long)dev->adj.warmup ) DBG(_DBG_INFO,"Warmup: Waiting %d seconds\n", dev->adj.warmup ); do { gettimeofday( &t, NULL); dw = t.tv_sec - dev->usbDev.dwTicksLampOn; if( usb_IsEscPressed()) { return SANE_FALSE; } } while( dw < (u_long)dev->adj.warmup ); return SANE_TRUE; } /** function for TPA autodection (EPSON & UMAX devices) */ static SANE_Bool usb_HasTPA( Plustek_Device *dev ) { static char model[] = { "3450" }; u_char val; if( dev->usbDev.vendor == 0x04B8 ) { /* the EPSON section */ usb_switchLampX( dev, SANE_FALSE, SANE_TRUE ); usbio_WriteReg ( dev->fd, 0x58, 0x1d ); usbio_WriteReg ( dev->fd, 0x59, 0x49 ); usbio_ReadReg ( dev->fd, 0x02, &val ); usbio_WriteReg ( dev->fd, 0x58, dev->usbDev.HwSetting.bReg_0x58 ); usbio_WriteReg ( dev->fd, 0x59, dev->usbDev.HwSetting.bReg_0x59 ); DBG( _DBG_INFO, "REG[0x02] = 0x%02x\n", val ); if( val & 0x02 ) { DBG( _DBG_INFO, "EPSON-TPA detected\n" ); return SANE_TRUE; } else DBG( _DBG_INFO, "EPSON-TPA NOT detected\n" ); if( dev->adj.enableTpa ) { DBG( _DBG_INFO, "EPSON-TPA usage forced\n" ); return SANE_TRUE; } } else if( dev->usbDev.vendor == 0x1606 ) { /* the UMAX section */ if((dev->usbDev.product == 0x0050) || (dev->usbDev.product == 0x0060)) { usbio_ReadReg ( dev->fd, 0x02, &val ); DBG( _DBG_INFO, "REG[0x02] = 0x%02x\n", val ); usbio_WriteReg ( dev->fd, 0x58, dev->usbDev.HwSetting.bReg_0x58 ); usbio_WriteReg ( dev->fd, 0x5a, dev->usbDev.HwSetting.bReg_0x5a ); usbio_WriteReg ( dev->fd, 0x5b, dev->usbDev.HwSetting.bReg_0x5b ); usbio_ReadReg ( dev->fd, 0x02, &val ); DBG( _DBG_INFO, "REG[0x02] = 0x%02x\n", val ); if( val & 0x02 ) { DBG( _DBG_INFO, "UMAX-TPA detected\n" ); dev->usbDev.ModelStr = model; return SANE_TRUE; } else DBG( _DBG_INFO, "UMAX-TPA NOT detected\n" ); if( dev->adj.enableTpa ) { DBG( _DBG_INFO, "UMAX-TPA usage forced\n" ); dev->usbDev.ModelStr = model; return SANE_TRUE; } } } return SANE_FALSE; } /** function for reading the button states */ static SANE_Bool usb_UpdateButtonStatus( Plustek_Scanner *s ) { u_char mio[3]; SANE_Byte val, mask; int i, j, bc; int handle = -1; SANE_Status status; Plustek_Device *dev = s->hw; DCapsDef *caps = &dev->usbDev.Caps; if (caps->bButtons == 0) return SANE_FALSE; status = sanei_access_lock( dev->sane.name, 3 ); if( SANE_STATUS_GOOD != status ) return SANE_FALSE; if( -1 == dev->fd ) { status = sanei_usb_open(dev->sane.name, &handle); if( SANE_STATUS_GOOD != status ) { sanei_access_unlock( dev->sane.name ); return SANE_FALSE; } dev->fd = handle; } /* we have to check all 6 misc I/O ports for input configuration*/ mio[0] = dev->usbDev.HwSetting.bReg_0x59; mio[1] = dev->usbDev.HwSetting.bReg_0x5a; mio[2] = dev->usbDev.HwSetting.bReg_0x5b; usbio_ReadReg( dev->fd, 0x07, &val ); if( val == 0 ) { /* first read clears the status... */ usbio_ReadReg( dev->fd, 0x02, &val ); /* Plustek and KYE/Genius use altnernative button handling */ if((dev->usbDev.vendor == 0x07B3) || (dev->usbDev.vendor == 0x0458)) { DBG( _DBG_INFO2, "Button Value=0x%02x\n", val ); /* no button pressed so far */ for( i = 0; i < caps->bButtons; i++ ) s->val[OPT_BUTTON_0 + i].w = 0; if (caps->bButtons == 2 || caps->bButtons == 5) { val >>= 2; val &= 0x07; DBG( _DBG_INFO2, "Button Value=0x%02x (2/5)\n", val ); switch( val ) { case 1: s->val[OPT_BUTTON_1].w = 1; break; case 2: s->val[OPT_BUTTON_0].w = 1; break; case 3: s->val[OPT_BUTTON_2].w = 1; break; case 4: s->val[OPT_BUTTON_3].w = 1; break; case 6: s->val[OPT_BUTTON_4].w = 1; break; } } else if (caps->bButtons == 4 ) { val >>= 5; val &= 0x07; DBG( _DBG_INFO2, "Button Value=0x%02x (4)\n", val ); switch( val ) { case 1: s->val[OPT_BUTTON_0].w = 1; break; case 2: s->val[OPT_BUTTON_1].w = 1; break; case 4: s->val[OPT_BUTTON_2].w = 1; break; case 6: s->val[OPT_BUTTON_3].w = 1; break; } } else { DBG( _DBG_INFO2, "Hmm, could not handle this!\n" ); } } else { /* the generic section... */ val >>= 2; bc = 0; /* only use the "valid" ports, that reflect a button */ if( _WAF_MISC_IO_BUTTONS & caps->workaroundFlag ) { if((caps->misc_io & _PORT0) == 0) mio[0] = 0xff; if((caps->misc_io & _PORT1) == 0) mio[1] = 0xff; if((caps->misc_io & _PORT2) == 0) mio[2] = 0xff; } for( i = 0; i < 3; i++ ) { DBG( _DBG_INFO2, "Checking MISC IO[%u]=0x%02x\n", i, mio[i] ); mask = 0x01; for( j = 0; j < 2; j++ ) { if((mio[i] & mask) == 0) { DBG( _DBG_INFO2, "* port %u configured as input," " status: %s (%u)\n", (i*2)+j+1, ((val & 1)?"PRESSED":"RELEASED"), (OPT_BUTTON_0 + bc)); s->val[OPT_BUTTON_0 + bc].w = val & 1; bc++; } val >>= 1; mask <<= 4; } } } } else { DBG( _DBG_INFO2, "Scanner NOT idle: 0x%02x\n", val ); } if( -1 != handle ) { dev->fd = -1; sanei_usb_close( handle ); } sanei_access_unlock( dev->sane.name ); return SANE_TRUE; } /* END PLUSTEK-USBHW.C ......................................................*/ sane-backends-1.0.27/backend/sm3600-color.c0000664000175000017500000002726612112021330015017 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) Marian Eichholz 2001 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ====================================================================== Userspace scan tool for the Microtek 3600 scanner color scan routine (C) Marian Eichholz 2001 ====================================================================== */ #include "sm3600-scantool.h" #define ORDER_RGB "012" #define ORDER_BRG "120" /* ********************************************************************** ReadNextColorLine() ********************************************************************** */ static TState ReadNextColorLine(PTInstance this) { int iWrite,i; int iRead; /* read position in raw line */ int nInterpolator; int iOffsetR,iOffsetG,iOffsetB; short *pchLineSwap; TBool bVisible; bVisible=false; do { iWrite=0; while (iWrite<3*this->state.cxMax) /* max 1 time in reality */ { while (iWrite<3*this->state.cxMax && this->state.iBulkReadPosstate.cchBulk) this->state.ppchLines[0][iWrite++] = this->state.pchBuf[this->state.iBulkReadPos++]; if (iWrite<3*this->state.cxMax) /* we need an additional chunk */ { if (this->state.bLastBulk) return SANE_STATUS_EOF; this->state.cchBulk=BulkReadBuffer(this,this->state.pchBuf, USB_CHUNK_SIZE); dprintf(DEBUG_SCAN,"bulk read: %d byte(s), line #%d\n", this->state.cchBulk, this->state.iLine); if (this->bWriteRaw) fwrite(this->state.pchBuf,1,this->state.cchBulk,this->fhScan); INST_ASSERT(); if (this->state.cchBulk!=USB_CHUNK_SIZE) this->state.bLastBulk=true; this->state.iBulkReadPos=0; } } /* while raw line buffer acquiring */ this->state.iLine++; if (this->state.iLine>2*this->state.ySensorSkew) { bVisible=true; iOffsetR=(this->state.szOrder[0]-'0')*this->state.cxMax; iOffsetG=(this->state.szOrder[1]-'0')*this->state.cxMax; iOffsetB=(this->state.szOrder[2]-'0')*this->state.cxMax; for (nInterpolator=100, iWrite=0, iRead=0; iRead<3*this->state.cxMax && iWritestate.cchLineOut; iRead++) { nInterpolator+=this->state.nFixAspect; if (nInterpolator<100) continue; /* res. reduction */ nInterpolator-=100; /* dprintf(DEBUG_SCAN," i=%d",iTo); */ /* the first scan lines only fill the line backlog buffer */ { /* dprintf(DEBUG_SCAN,"assembling line %d\n",++this->state.iLine); */ this->state.pchLineOut[iWrite++]= this->state.ppchLines[2*this->state.ySensorSkew][iRead+iOffsetR]; this->state.pchLineOut[iWrite++]= this->state.ppchLines[1*this->state.ySensorSkew][iRead+iOffsetG]; this->state.pchLineOut[iWrite++]= this->state.ppchLines[0*this->state.ySensorSkew][iRead+iOffsetB]; } } } /* if visible line */ /* cycle backlog buffers */ pchLineSwap=this->state.ppchLines[this->state.cBacklog-1]; for (i=this->state.cBacklog-2; i>=0; i--) this->state.ppchLines[i+1]=this->state.ppchLines[i]; this->state.ppchLines[0]=pchLineSwap; } while (!bVisible); return SANE_STATUS_GOOD; } /* ====================================================================== StartScanColor() ====================================================================== */ /* Parameter are in resolution units! */ __SM3600EXPORT__ TState StartScanColor(TInstance *this) { /* live could be easy: Simple calculate a window, start the scan, get the data and get off. It dimply does not work. We have to deal with the fact, that the pixels are reported with color scan line by color scan line, and have to be rearranged to RGB triples. They even ar enot always in RGB order, but mostly in BRG order. And they have a skew of 2/300 inch , given by the slider construction. Thus, we have to deal with several buffers, some interpolation, and related management stuff. */ int i; if (this->state.bScanning) return SetError(this,SANE_STATUS_DEVICE_BUSY,"scan active"); memset(&(this->state),0,sizeof(this->state)); this->state.ReadProc =ReadNextColorLine; this->state.ySensorSkew=0; GetAreaSize(this); switch (this->param.res) { case 200: this->state.ySensorSkew=1; break; case 300: this->state.ySensorSkew=2; break; case 600: this->state.ySensorSkew=4; break; default: break; } /* since we need 2*this->state.ySensorSkew additional scan lines for de-skewing of the sensor lines, we enlarge the window and shorten the initial movement accordingly */ this->state.cyTotalPath = this->param.y/2-(2*this->state.ySensorSkew)*600/this->param.res; DoJog(this,this->state.cyTotalPath); INST_ASSERT(); this->state.cyTotalPath += (this->state.cyPixel+2*this->state.ySensorSkew) *600/this->param.res; /* for jogging back */ /* regular scan is asynchronously, that is, the scanning is issued, and the driver does bulk reads, until there are no data left. Each line has a full R, G and B subline, 8bit each sample. */ { unsigned char uchRegs[]={ 0xFC /*!!R_SPOS!!*/, 0x00 /*R_SPOSH*/, 0x24 /*!!0x03!!*/, 0xB0 /*!!R_SWID!!*/, 0xC4 /*!!R_SWIDH!!*/, 1,0, 0xFF /*!!0x08!!*/, 0xFF /*!!0x09!!*/, 0x22 /*!!R_LEN!!*/, 0x07 /*!!R_LENH!!*/, 0x6D /*0x0C*/, 0x70 /*0x0D*/, 0x69 /*0x0E*/, 0xD0 /*0x0F*/, 0x00 /*0x10*/, 0x00 /*0x11*/, 0x42 /*!!0x12!!*/, 0x15 /*0x13*/, 0x84 /*!!0x14!!*/, 0x2A /*0x15*/, 0xC5 /*!!0x16!!*/, 0x40 /*0x17*/, 0xC5 /*!!0x18!!*/, 0x40 /*0x19*/, 0xFF /*0x1A*/, 0x01 /*0x1B*/, 0x88 /*0x1C*/, 0x40 /*0x1D*/, 0x4C /*0x1E*/, 0x50 /*0x1F*/, 0x00 /*0x20*/, 0x0C /*0x21*/, 0x21 /*0x22*/, 0xF0 /*0x23*/, 0x40 /*0x24*/, 0x00 /*0x25*/, 0x0A /*0x26*/, 0xF0 /*0x27*/, 0x00 /*0x28*/, 0x00 /*0x29*/, 0x4E /*0x2A*/, 0xF0 /*0x2B*/, 0x00 /*0x2C*/, 0x00 /*0x2D*/, 0x4E /*0x2E*/, 0x80 /*R_CCAL*/, 0x80 /*R_CCAL2*/, 0x80 /*R_CCAL3*/, 0x0B /*0x32*/, 0x2D /*0x33*/, 0x43 /*!!0x34!!*/, 0x29 /*0x35*/, 0x00 /*0x36*/, 0x00 /*0x37*/, 0x00 /*0x38*/, 0x00 /*0x39*/, 0x00 /*0x3A*/, 0x00 /*0x3B*/, 0xFF /*0x3C*/, 0x0F /*0x3D*/, 0x00 /*0x3E*/, 0x00 /*0x3F*/, 0x01 /*0x40*/, 0x00 /*0x41*/, 0x80 /*R_CSTAT*/, 0x03 /*0x43*/, 0x01 /*R_LMP*/, 0x00 /*0x45*/, 0x39 /*R_CTL*/, 0xC5 /*!!0x47!!*/, 0x40 /*0x48*/, 0x9E /*0x49*/, 0x8C /*0x4A*/ }; RegWriteArray(this,R_ALL, NUM_SCANREGS, uchRegs); RegWrite(this,R_SPOS, 2, this->param.x/2 + this->calibration.xMargin); RegWrite(this,R_SLEN, 2, this->state.cyWindow+ (2*this->state.ySensorSkew)*600/this->param.res); this->state.szOrder=ORDER_BRG; RegWrite(this,R_CCAL, 3, this->calibration.rgbBias); INST_ASSERT(); /* 0xBBGGRR */ switch (this->param.res) { case 75: RegWrite(this,R_XRES,1, 0x20); /* ups, can do only 100 dpi horizontal */ RegWrite(this,R_SWID, 2, 0xC000 | this->state.cxWindow); RegWrite(this,0x34, 1, 0x83); /* halfs the vertical resolution */ RegWrite(this,0x47,1,0xC0); /* reduces the speed a bit */ break; case 100: RegWrite(this,R_XRES,1, 0x20); RegWrite(this,R_SWID, 2, 0xC000 | this->state.cxWindow); RegWrite(this,0x34, 1, 0x63); /* halfs the vertical resolution */ RegWrite(this,0x47,1,0xC0); /* reduces the speed a bit */ /* I have no idea, what these differences are good for. The seem to produce a slight blue presence. RegWrite(this,0x16, 1, 0xC0); RegWrite(this,0x18, 1, 0xC0); RegWrite(this,0x12, 1, 0x40); RegWrite(this,0x10, 2, 0x0728); RegWrite(this,0x14, 1, 0x80); */ break; case 200: RegWrite(this,R_XRES,1, 0x24); RegWrite(this,R_SWID, 2, 0xC000 | this->state.cxWindow); break; case 300: RegWrite(this,0x08,2, 0x6A6A); RegWrite(this,R_XRES,1, 0x2A); RegWrite(this,R_SWID, 2, 0x4000 | this->state.cxWindow); RegWrite(this,0x34, 1, 0x03); /* halfs the vertical resolution */ RegWrite(this,0x47,1,0xC0); /* reduces the speed a bit */ this->state.szOrder=ORDER_RGB; break; case 600: RegWrite(this,R_XRES,1, 0x3F); RegWrite(this,R_SWID, 2, 0xC000 | this->state.cxWindow); RegWrite(this,0x34, 1, 0x03); /* halfs the vertical resolution */ RegWrite(this,0x47,1,0xC2); /* reduces the speed a bit */ break; case 1200: /* not supported, since the driver supports only 600 dpi in color */ break; } } /* setup gamma tables */ RegWrite(this,0x41,1,0x03); /* gamma, RGB */ RegWrite(this,0x40,1,0x28); /* offset FIFO 8*3 (GAMMA)+16 KB(gain) spared */ /* hey, surprise: Although the color lines are sent in a strange order, the gamma tables are mapped constantly to the sensors (i.e. RGB) */ UploadGammaTable(this,0x0000,this->agammaR); UploadGammaTable(this,0x2000,this->agammaG); UploadGammaTable(this,0x4000,this->agammaB); INST_ASSERT(); UploadGainCorrection(this,0x6000); INST_ASSERT(); /* enough for 1/100 inch sensor distance */ this->state.cBacklog=1+2*this->state.ySensorSkew; /* allocate raw line buffers */ this->state.ppchLines=calloc(this->state.cBacklog,sizeof(short*)); this->state.pchBuf=malloc(0x8000); if (!this->state.ppchLines || !this->state.pchBuf) return FreeState(this,SetError(this, SANE_STATUS_NO_MEM,"no buffers available")); for (i=0; istate.cBacklog; i++) { this->state.ppchLines[i]=calloc(1,3*this->state.cxMax*sizeof(short)); /* must be less than 0x8000 */ if (!this->state.ppchLines[i]) return FreeState(this, SetError(this,SANE_STATUS_NO_MEM, "no line buffer available")); } /* calculate and prepare intermediate line transfer buffer */ this->state.cchLineOut=3*this->state.cxPixel; this->state.pchLineOut = malloc(this->state.cchLineOut); if (!this->state.pchLineOut) return FreeState(this,SetError(this, SANE_STATUS_NO_MEM, "no buffers available")); RegWrite(this,R_CTL, 1, 0x39); /* #1532[005.0] */ RegWrite(this,R_CTL, 1, 0x79); /* #1533[005.0] */ RegWrite(this,R_CTL, 1, 0xF9); /* #1534[005.0] */ INST_ASSERT(); this->state.bScanning = true; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/epson2_net.h0000664000175000017500000000102712775312261015044 00000000000000#ifndef _EPSON2_NET_H_ #define _EPSON2_NET_H_ #include #include "../include/sane/sane.h" extern int sanei_epson_net_read(struct Epson_Scanner *s, unsigned char *buf, ssize_t buf_size, SANE_Status *status); extern int sanei_epson_net_write(struct Epson_Scanner *s, unsigned int cmd, const unsigned char *buf, size_t buf_size, size_t reply_len, SANE_Status *status); extern SANE_Status sanei_epson_net_lock(struct Epson_Scanner *s); extern SANE_Status sanei_epson_net_unlock(struct Epson_Scanner *s); #endif sane-backends-1.0.27/backend/umax.conf.in0000664000175000017500000000602612112021330015024 00000000000000# # Options for the umax backend # # define scsi queueing depth #option scsi-maxqueue 2 # define scsi buffer size in bytes #option scsi-buffer-size-min 65536 #option scsi-buffer-size-max 262144 # define scan lines that shall be read in one block #option scan-lines 100 #option preview-lines 20 # define how to handle bad sense codes # 0 = handle as device busy # 1 = handle as ok # 2 = handle as i/o error # 3 = ignore bad error code - continue sense handler, #option handle-bad-sense-error 0 # define if a request sense command shall be executed #option execute-request-sense 0 # define if the preview bit shall be set when scanning in rgb mode #option force-preview-bit-rgb 0 # define if slow speed flag shall be set # BE CAREFUL WITH THIS OPTION, IT MAY DESTROY YOUR SCANNER WHEN SET FALSE # -1 = automatically set by driver - if known # 0 = disabled # 1 = enabled #option slow-speed 0 # define if care-about-smeraring flag shall be set # BE CAREFUL WITH THIS OPTION, IT MAY DESTROY YOUR SCANNER WHEN SET FALSE # -1 = automatically set by driver - if known # 0 = disabled # 1 = enabled #option care-about-smearing 0 # define if the calibration shall be done for selected scanarea or for each ccd pixel # -1 = automatically set by driver - if known # 0 = disabled # 1 = enabled #option calibration-full-ccd 1 # define if an offset of the calculate calibration with has to be used # -99999 = auto #option calibration-width-offset -99999 # define the number of pixels that is used for calibration # -1 = disabled # 0 = not set # 1 = 1 byte/pixel, # 2 = 2 bytes/pixel #option calibration-bytes-pixel -1 # define if scanner uses the same exposure times for red, green and blue # -1 = automatically set by driver - if known # 0 = disabled (own selection for red, green and blue) # 1 = enabled (same values for red, green and blue) #options exposure-time-rgb-bind 0 # define if shading data shall be inverted befor sending it back to the scanner # -1 = automatically set by driver - if known # 0 = disabled # 1 = enabled #option invert-shading-data 0 # define if the scanner supports lamp control commands # 0 = automatically set by driver - if known # 1 = enabled #option lamp-control-available 0 # define how 16 bit gamma data is padded # -1 = automatically set by driver - if known # 0 = gamma data is msb padded # 1 = gamma data is lsb padded #option gamma-lsb-padded 0 # define connection type of following devices # 1 = scsi # 2 = usb #option connection-type 1 # linux device identification: #scsi vendor model type bus channel id lun scsi UMAX * Scanner scsi LinoHell JADE scsi LinoHell Office scsi LinoHell Office2 scsi LinoHell SAPHIR2 scsi LinoHell SAPHIR3 scsi Linotype SAPHIR4 scsi LinoHell OPAL2 scsi HDM LS4H1S scsi Nikon AX-110 scsi Nikon AX-210 scsi KYE ColorPage-HR5 scsi EPSON Perfection600 scsi ESCORT "Galleria 600S" scsi TriGem PowerScanII # Umax Astra 2200 via USB: # usb vendor product usb 0x1606 0x0230 # scsi device list option connection-type 1 /dev/scanner # usb device list option connection-type 2 /dev/usbscanner sane-backends-1.0.27/backend/dmc.c0000664000175000017500000012256612775312260013541 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998 David F. Skoll Heavily based on "hp.c" driver for HP Scanners, by David Mosberger-Tang. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Polaroid Digital Microscope Camera. */ /* $Id$ */ #include "../include/sane/config.h" #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #define BACKEND_NAME dmc #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define DMC_CONFIG_FILE "dmc.conf" #include "dmc.h" /* A linked-list of attached devices and handles */ static DMC_Device *FirstDevice = NULL; static DMC_Camera *FirstHandle = NULL; static int NumDevices = 0; static SANE_Device const **devlist = NULL; static SANE_String_Const ValidModes[] = { "Full frame", "Viewfinder", "Raw", "Thumbnail", "Super-Resolution", NULL }; static SANE_String_Const ValidBalances[] = { "Daylight", "Incandescent", "Fluorescent", NULL }; static SANE_Word ValidASAs[] = { 3, 25, 50, 100 }; /* Convert between 32-us ticks and milliseconds */ #define MS_TO_TICKS(x) (((x) * 1000 + 16) / 32) #define TICKS_TO_MS(x) (((x) * 32) / 1000) /* Macros for stepping along the raw lines for super-resolution mode They are very ugly because they handle boundary conditions at the edges of the image. Yuck... */ #define PREV_RED(i) (((i)/3)*3) #define NEXT_RED(i) (((i) >= BYTES_PER_RAW_LINE-3) ? BYTES_PER_RAW_LINE-3 : \ PREV_RED(i)+3) #define PREV_GREEN(i) ((i)<1 ? 1 : PREV_RED((i)-1)+1) #define NEXT_GREEN(i) ((i)<1 ? 1 : ((i) >= BYTES_PER_RAW_LINE-2) ? \ BYTES_PER_RAW_LINE-2 : PREV_GREEN(i)+3) #define PREV_BLUE(i) ((i)<2 ? 2 : PREV_RED((i)-2)+2) #define NEXT_BLUE(i) ((i)<2 ? 2 : ((i) >= BYTES_PER_RAW_LINE-1) ? \ BYTES_PER_RAW_LINE-1 : PREV_BLUE(i)+3) #define ADVANCE_COEFF(i) (((i)==1) ? 3 : (i)-1); /********************************************************************** //%FUNCTION: DMCRead //%ARGUMENTS: // fd -- file descriptor // typecode -- data type code // qualifier -- data type qualifier // maxlen -- tranfer length // buf -- buffer to store data in // len -- set to actual length of data //%RETURNS: // A SANE status code //%DESCRIPTION: // Reads the particular data selected by typecode and qualifier // *********************************************************************/ static SANE_Status DMCRead(int fd, unsigned int typecode, unsigned int qualifier, SANE_Byte *buf, size_t maxlen, size_t *len) { uint8_t readCmd[10]; SANE_Status status; readCmd[0] = 0x28; readCmd[1] = 0; readCmd[2] = typecode; readCmd[3] = 0; readCmd[4] = (qualifier >> 8) & 0xFF; readCmd[5] = qualifier & 0xFF; readCmd[6] = (maxlen >> 16) & 0xFF; readCmd[7] = (maxlen >> 8) & 0xFF; readCmd[8] = maxlen & 0xFF; readCmd[9] = 0; DBG(3, "DMCRead: typecode=%x, qualifier=%x, maxlen=%lu\n", typecode, qualifier, (u_long) maxlen); *len = maxlen; status = sanei_scsi_cmd(fd, readCmd, sizeof(readCmd), buf, len); DBG(3, "DMCRead: Read %lu bytes\n", (u_long) *len); return status; } /********************************************************************** //%FUNCTION: DMCWrite //%ARGUMENTS: // fd -- file descriptor // typecode -- data type code // qualifier -- data type qualifier // maxlen -- tranfer length // buf -- buffer to store data in //%RETURNS: // A SANE status code //%DESCRIPTION: // Writes the particular data selected by typecode and qualifier // *********************************************************************/ static SANE_Status DMCWrite(int fd, unsigned int typecode, unsigned int qualifier, SANE_Byte *buf, size_t maxlen) { uint8_t *writeCmd; SANE_Status status; writeCmd = malloc(maxlen + 10); if (!writeCmd) return SANE_STATUS_NO_MEM; writeCmd[0] = 0x2A; writeCmd[1] = 0; writeCmd[2] = typecode; writeCmd[3] = 0; writeCmd[4] = (qualifier >> 8) & 0xFF; writeCmd[5] = qualifier & 0xFF; writeCmd[6] = (maxlen >> 16) & 0xFF; writeCmd[7] = (maxlen >> 8) & 0xFF; writeCmd[8] = maxlen & 0xFF; writeCmd[9] = 0; memcpy(writeCmd+10, buf, maxlen); DBG(3, "DMCWrite: typecode=%x, qualifier=%x, maxlen=%lu\n", typecode, qualifier, (u_long) maxlen); status = sanei_scsi_cmd(fd, writeCmd, 10+maxlen, NULL, NULL); free(writeCmd); return status; } /********************************************************************** //%FUNCTION: DMCAttach //%ARGUMENTS: // devname -- name of device file to open // devp -- a DMC_Device structure which we fill in if it's not NULL. //%RETURNS: // SANE_STATUS_GOOD -- We have a Polaroid DMC attached and all looks good. // SANE_STATUS_INVAL -- There's a problem. //%DESCRIPTION: // Verifies that a Polaroid DMC is attached. Sets up device options in // DMC_Device structure. // *********************************************************************/ #define INQ_LEN 255 static SANE_Status DMCAttach(char const *devname, DMC_Device **devp) { DMC_Device *dev; SANE_Status status; int fd; size_t size; char result[INQ_LEN]; uint8_t exposureCalculationResults[16]; uint8_t userInterfaceSettings[16]; static uint8_t const inquiry[] = { 0x12, 0x00, 0x00, 0x00, INQ_LEN, 0x00 }; static uint8_t const test_unit_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t const no_viewfinder[] = { 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* If we're already attached, do nothing */ for (dev = FirstDevice; dev; dev = dev->next) { if (!strcmp(dev->sane.name, devname)) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } } DBG(3, "DMCAttach: opening `%s'\n", devname); status = sanei_scsi_open(devname, &fd, 0, 0); if (status != SANE_STATUS_GOOD) { DBG(1, "DMCAttach: open failed (%s)\n", sane_strstatus(status)); return status; } DBG(3, "DMCAttach: sending INQUIRY\n"); size = sizeof(result); status = sanei_scsi_cmd(fd, inquiry, sizeof(inquiry), result, &size); if (status != SANE_STATUS_GOOD || size < 32) { if (status == SANE_STATUS_GOOD) status = SANE_STATUS_INVAL; DBG(1, "DMCAttach: inquiry failed (%s)\n", sane_strstatus(status)); sanei_scsi_close(fd); return status; } /* Verify that we have a Polaroid DMC */ if (result[0] != 6 || strncmp(result+8, "POLAROID", 8) || strncmp(result+16, "DMC ", 8)) { sanei_scsi_close(fd); DBG(1, "DMCAttach: Device does not look like a Polaroid DMC\n"); return SANE_STATUS_INVAL; } DBG(3, "DMCAttach: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd(fd, test_unit_ready, sizeof(test_unit_ready), NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG(1, "DMCAttach: test unit ready failed (%s)\n", sane_strstatus(status)); sanei_scsi_close(fd); return status; } /* Read current ASA and shutter speed settings */ status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults, sizeof(exposureCalculationResults), &size); if (status != SANE_STATUS_GOOD || size < sizeof(exposureCalculationResults)) { DBG(1, "DMCAttach: Couldn't read exposure calculation results (%s)\n", sane_strstatus(status)); sanei_scsi_close(fd); if (status == SANE_STATUS_GOOD) status = SANE_STATUS_IO_ERROR; return status; } /* Read current white balance settings */ status = DMCRead(fd, 0x82, 0x0, userInterfaceSettings, sizeof(userInterfaceSettings), &size); if (status != SANE_STATUS_GOOD || size < sizeof(userInterfaceSettings)) { DBG(1, "DMCAttach: Couldn't read user interface settings (%s)\n", sane_strstatus(status)); sanei_scsi_close(fd); if (status == SANE_STATUS_GOOD) status = SANE_STATUS_IO_ERROR; return status; } /* Shut off viewfinder mode */ status = sanei_scsi_cmd(fd, no_viewfinder, sizeof(no_viewfinder), NULL, NULL); if (status != SANE_STATUS_GOOD) { sanei_scsi_close(fd); return status; } sanei_scsi_close(fd); DBG(3, "DMCAttach: Looks like we have a Polaroid DMC\n"); dev = malloc(sizeof(*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset(dev, 0, sizeof(*dev)); dev->sane.name = strdup(devname); dev->sane.vendor = "Polaroid"; dev->sane.model = "DMC"; dev->sane.type = "still camera"; dev->next = FirstDevice; dev->whiteBalance = userInterfaceSettings[5]; if (dev->whiteBalance > WHITE_BALANCE_FLUORESCENT) { dev->whiteBalance = WHITE_BALANCE_FLUORESCENT; } /* Bright Eyes documentation gives these as shutter speed ranges (ms) */ /* dev->shutterSpeedRange.min = 8; */ /* dev->shutterSpeedRange.max = 320; */ /* User's manual says these are shutter speed ranges (ms) */ dev->shutterSpeedRange.min = 8; dev->shutterSpeedRange.max = 1000; dev->shutterSpeedRange.quant = 2; dev->shutterSpeed = (exposureCalculationResults[10] << 8) + exposureCalculationResults[11]; /* Convert from ticks to ms */ dev->shutterSpeed = TICKS_TO_MS(dev->shutterSpeed); dev->asa = exposureCalculationResults[13]; if (dev->asa > ASA_100) dev->asa = ASA_100; dev->asa = ValidASAs[dev->asa + 1]; FirstDevice = dev; NumDevices++; if (devp) *devp = dev; return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: ValidateHandle //%ARGUMENTS: // handle -- a handle for an opened camera //%RETURNS: // A validated pointer to the camera or NULL if handle is not valid. // *********************************************************************/ static DMC_Camera * ValidateHandle(SANE_Handle handle) { DMC_Camera *c; for (c = FirstHandle; c; c = c->next) { if (c == handle) return c; } DBG(1, "ValidateHandle: invalid handle %p\n", handle); return NULL; } /********************************************************************** //%FUNCTION: DMCInitOptions //%ARGUMENTS: // c -- a DMC camera device //%RETURNS: // SANE_STATUS_GOOD -- OK // SANE_STATUS_INVAL -- There's a problem. //%DESCRIPTION: // Initializes the options in the DMC_Camera structure // *********************************************************************/ static SANE_Status DMCInitOptions(DMC_Camera *c) { int i; /* Image is initially 801x600 */ c->tl_x_range.min = 0; c->tl_x_range.max = c->tl_x_range.min; c->tl_x_range.quant = 1; c->tl_y_range.min = 0; c->tl_y_range.max = c->tl_y_range.min; c->tl_y_range.quant = 1; c->br_x_range.min = 800; c->br_x_range.max = c->br_x_range.min; c->br_x_range.quant = 1; c->br_y_range.min = 599; c->br_y_range.max = c->br_y_range.min; c->br_y_range.quant = 1; memset(c->opt, 0, sizeof(c->opt)); memset(c->val, 0, sizeof(c->val)); for (i=0; iopt[i].type = SANE_TYPE_INT; c->opt[i].size = sizeof(SANE_Word); c->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; c->opt[i].unit = SANE_UNIT_NONE; } c->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; c->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; c->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; c->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; c->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; c->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; c->val[OPT_NUM_OPTS].w = NUM_OPTIONS; c->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; c->opt[OPT_GEOMETRY_GROUP].name = ""; c->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; c->opt[OPT_GEOMETRY_GROUP].desc = ""; c->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; c->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ c->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; c->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; c->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; c->opt[OPT_TL_X].type = SANE_TYPE_INT; c->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL; c->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; c->opt[OPT_TL_X].constraint.range = &c->tl_x_range; c->val[OPT_TL_X].w = c->tl_x_range.min; /* top-left y */ c->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; c->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; c->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; c->opt[OPT_TL_Y].type = SANE_TYPE_INT; c->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL; c->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; c->opt[OPT_TL_Y].constraint.range = &c->tl_y_range; c->val[OPT_TL_Y].w = c->tl_y_range.min; /* bottom-right x */ c->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; c->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; c->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; c->opt[OPT_BR_X].type = SANE_TYPE_INT; c->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL; c->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; c->opt[OPT_BR_X].constraint.range = &c->br_x_range; c->val[OPT_BR_X].w = c->br_x_range.min; /* bottom-right y */ c->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; c->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; c->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; c->opt[OPT_BR_Y].type = SANE_TYPE_INT; c->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL; c->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; c->opt[OPT_BR_Y].constraint.range = &c->br_y_range; c->val[OPT_BR_Y].w = c->br_y_range.min; c->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; c->opt[OPT_MODE_GROUP].name = ""; c->opt[OPT_MODE_GROUP].title = "Imaging Mode"; c->opt[OPT_MODE_GROUP].desc = ""; c->opt[OPT_MODE_GROUP].cap = SANE_CAP_ADVANCED; c->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; c->opt[OPT_IMAGE_MODE].name = "imagemode"; c->opt[OPT_IMAGE_MODE].title = "Image Mode"; c->opt[OPT_IMAGE_MODE].desc = "Selects image mode: 800x600 full frame, 270x201 viewfinder mode, 1599x600 \"raw\" image, 80x60 thumbnail image or 1599x1200 \"super-resolution\" image"; c->opt[OPT_IMAGE_MODE].type = SANE_TYPE_STRING; c->opt[OPT_IMAGE_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; c->opt[OPT_IMAGE_MODE].constraint.string_list = ValidModes; c->opt[OPT_IMAGE_MODE].size = 16; c->val[OPT_IMAGE_MODE].s = "Full frame"; c->opt[OPT_ASA].name = "asa"; c->opt[OPT_ASA].title = "ASA Setting"; c->opt[OPT_ASA].desc = "Equivalent ASA setting"; c->opt[OPT_ASA].constraint_type = SANE_CONSTRAINT_WORD_LIST; c->opt[OPT_ASA].constraint.word_list = ValidASAs; c->val[OPT_ASA].w = c->hw->asa; c->opt[OPT_SHUTTER_SPEED].name = "shutterspeed"; c->opt[OPT_SHUTTER_SPEED].title = "Shutter Speed (ms)"; c->opt[OPT_SHUTTER_SPEED].desc = "Shutter Speed in milliseconds"; c->opt[OPT_SHUTTER_SPEED].constraint_type = SANE_CONSTRAINT_RANGE; c->opt[OPT_SHUTTER_SPEED].constraint.range = &c->hw->shutterSpeedRange; c->val[OPT_SHUTTER_SPEED].w = c->hw->shutterSpeed; c->opt[OPT_WHITE_BALANCE].name = "whitebalance"; c->opt[OPT_WHITE_BALANCE].title = "White Balance"; c->opt[OPT_WHITE_BALANCE].desc = "Selects white balance"; c->opt[OPT_WHITE_BALANCE].type = SANE_TYPE_STRING; c->opt[OPT_WHITE_BALANCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; c->opt[OPT_WHITE_BALANCE].constraint.string_list = ValidBalances; c->opt[OPT_WHITE_BALANCE].size = 16; c->val[OPT_WHITE_BALANCE].s = (SANE_String) ValidBalances[c->hw->whiteBalance]; return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: DMCSetMode //%ARGUMENTS: // c -- a DMC camera device // mode -- Imaging mode //%RETURNS: // SANE_STATUS_GOOD -- OK // SANE_STATUS_INVAL -- There's a problem. //%DESCRIPTION: // Sets the camera's imaging mode. // *********************************************************************/ static SANE_Status DMCSetMode(DMC_Camera *c, int mode) { switch(mode) { case IMAGE_MFI: c->tl_x_range.min = 0; c->tl_x_range.max = c->tl_x_range.max; c->tl_y_range.min = 0; c->tl_y_range.max = c->tl_y_range.max; c->br_x_range.min = 800; c->br_x_range.max = c->br_x_range.max; c->br_y_range.min = 599; c->br_y_range.max = c->br_y_range.max; break; case IMAGE_VIEWFINDER: c->tl_x_range.min = 0; c->tl_x_range.max = c->tl_x_range.max; c->tl_y_range.min = 0; c->tl_y_range.max = c->tl_y_range.max; c->br_x_range.min = 269; c->br_x_range.max = c->br_x_range.max; c->br_y_range.min = 200; c->br_y_range.max = c->br_y_range.max; break; case IMAGE_RAW: c->tl_x_range.min = 0; c->tl_x_range.max = c->tl_x_range.max; c->tl_y_range.min = 0; c->tl_y_range.max = c->tl_y_range.max; c->br_x_range.min = 1598; c->br_x_range.max = c->br_x_range.max; c->br_y_range.min = 599; c->br_y_range.max = c->br_y_range.max; break; case IMAGE_THUMB: c->tl_x_range.min = 0; c->tl_x_range.max = c->tl_x_range.max; c->tl_y_range.min = 0; c->tl_y_range.max = c->tl_y_range.max; c->br_x_range.min = 79; c->br_x_range.max = c->br_x_range.max; c->br_y_range.min = 59; c->br_y_range.max = c->br_y_range.max; break; case IMAGE_SUPER_RES: c->tl_x_range.min = 0; c->tl_x_range.max = c->tl_x_range.max; c->tl_y_range.min = 0; c->tl_y_range.max = c->tl_y_range.max; c->br_x_range.min = 1598; c->br_x_range.max = c->br_x_range.max; c->br_y_range.min = 1199; c->br_y_range.max = c->br_y_range.max; break; default: return SANE_STATUS_INVAL; } c->imageMode = mode; c->val[OPT_TL_X].w = c->tl_x_range.min; c->val[OPT_TL_Y].w = c->tl_y_range.min; c->val[OPT_BR_X].w = c->br_x_range.min; c->val[OPT_BR_Y].w = c->br_y_range.min; return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: DMCCancel //%ARGUMENTS: // c -- a DMC camera device //%RETURNS: // SANE_STATUS_CANCELLED //%DESCRIPTION: // Cancels DMC image acquisition // *********************************************************************/ static SANE_Status DMCCancel(DMC_Camera *c) { if (c->fd >= 0) { sanei_scsi_close(c->fd); c->fd = -1; } return SANE_STATUS_CANCELLED; } /********************************************************************** //%FUNCTION: DMCSetASA //%ARGUMENTS: // fd -- SCSI file descriptor // asa -- the ASA to set //%RETURNS: // A sane status value //%DESCRIPTION: // Sets the equivalent ASA setting of the camera. // *********************************************************************/ static SANE_Status DMCSetASA(int fd, unsigned int asa) { uint8_t exposureCalculationResults[16]; SANE_Status status; size_t len; int i; DBG(3, "DMCSetAsa: %d\n", asa); for (i=1; i<=ASA_100+1; i++) { if (asa == (unsigned int) ValidASAs[i]) break; } if (i > ASA_100+1) return SANE_STATUS_INVAL; status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults, sizeof(exposureCalculationResults), &len); if (status != SANE_STATUS_GOOD) return status; if (len < sizeof(exposureCalculationResults)) return SANE_STATUS_IO_ERROR; exposureCalculationResults[13] = (uint8_t) i - 1; return DMCWrite(fd, 0x87, 0x4, exposureCalculationResults, sizeof(exposureCalculationResults)); } /********************************************************************** //%FUNCTION: DMCSetWhiteBalance //%ARGUMENTS: // fd -- SCSI file descriptor // mode -- white balance mode //%RETURNS: // A sane status value //%DESCRIPTION: // Sets the equivalent ASA setting of the camera. // *********************************************************************/ static SANE_Status DMCSetWhiteBalance(int fd, int mode) { uint8_t userInterfaceSettings[16]; SANE_Status status; size_t len; DBG(3, "DMCSetWhiteBalance: %d\n", mode); status = DMCRead(fd, 0x82, 0x0, userInterfaceSettings, sizeof(userInterfaceSettings), &len); if (status != SANE_STATUS_GOOD) return status; if (len < sizeof(userInterfaceSettings)) return SANE_STATUS_IO_ERROR; userInterfaceSettings[5] = (uint8_t) mode; return DMCWrite(fd, 0x82, 0x0, userInterfaceSettings, sizeof(userInterfaceSettings)); } /********************************************************************** //%FUNCTION: DMCSetShutterSpeed //%ARGUMENTS: // fd -- SCSI file descriptor // speed -- shutter speed in ms //%RETURNS: // A sane status value //%DESCRIPTION: // Sets the shutter speed of the camera // *********************************************************************/ static SANE_Status DMCSetShutterSpeed(int fd, unsigned int speed) { uint8_t exposureCalculationResults[16]; SANE_Status status; size_t len; DBG(3, "DMCSetShutterSpeed: %u\n", speed); /* Convert from ms to ticks */ speed = MS_TO_TICKS(speed); status = DMCRead(fd, 0x87, 0x4, exposureCalculationResults, sizeof(exposureCalculationResults), &len); if (status != SANE_STATUS_GOOD) return status; if (len < sizeof(exposureCalculationResults)) return SANE_STATUS_IO_ERROR; exposureCalculationResults[10] = (speed >> 8) & 0xFF; exposureCalculationResults[11] = speed & 0xFF; return DMCWrite(fd, 0x87, 0x4, exposureCalculationResults, sizeof(exposureCalculationResults)); } /********************************************************************** //%FUNCTION: DMCReadTwoSuperResolutionLines //%ARGUMENTS: // c -- DMC Camera // buf -- where to put output. // lastLine -- if true, these are the last two lines in the super-resolution // image to read. //%RETURNS: // Nothing //%DESCRIPTION: // Reads a single "raw" line from the camera (if needed) and constructs // two "super-resolution" output lines in "buf" // *********************************************************************/ static SANE_Status DMCReadTwoSuperResolutionLines(DMC_Camera *c, SANE_Byte *buf, int lastLine) { SANE_Status status; size_t len; SANE_Byte *output, *prev; int redCoeff, greenCoeff, blueCoeff; int red, green, blue; int i; if (c->nextRawLineValid) { memcpy(c->currentRawLine, c->nextRawLine, BYTES_PER_RAW_LINE); } else { status = DMCRead(c->fd, 0x00, IMAGE_RAW, c->currentRawLine, BYTES_PER_RAW_LINE, &len); if (status != SANE_STATUS_GOOD) return status; } if (!lastLine) { status = DMCRead(c->fd, 0x00, IMAGE_RAW, c->nextRawLine, BYTES_PER_RAW_LINE, &len); if (status != SANE_STATUS_GOOD) return status; c->nextRawLineValid = 1; } redCoeff = 3; greenCoeff = 1; blueCoeff = 2; /* Do the first super-resolution line */ output = buf; for (i=0; icurrentRawLine[PREV_RED(i)] + (3-redCoeff) * c->currentRawLine[NEXT_RED(i)]; green = greenCoeff * c->currentRawLine[PREV_GREEN(i)] + (3-greenCoeff) * c->currentRawLine[NEXT_GREEN(i)]; blue = blueCoeff * c->currentRawLine[PREV_BLUE(i)] + (3-blueCoeff) * c->currentRawLine[NEXT_BLUE(i)]; *output++ = red/3; *output++ = green/3; *output++ = blue/3; redCoeff = ADVANCE_COEFF(redCoeff); greenCoeff = ADVANCE_COEFF(greenCoeff); blueCoeff = ADVANCE_COEFF(blueCoeff); } /* Do the next super-resolution line and interpolate vertically */ if (lastLine) { memcpy(buf+BYTES_PER_RAW_LINE*3, buf, BYTES_PER_RAW_LINE*3); return SANE_STATUS_GOOD; } redCoeff = 3; greenCoeff = 1; blueCoeff = 2; prev = buf; for (i=0; inextRawLine[PREV_RED(i)] + (3-redCoeff) * c->nextRawLine[NEXT_RED(i)]; green = greenCoeff * c->nextRawLine[PREV_GREEN(i)] + (3-greenCoeff) * c->nextRawLine[NEXT_GREEN(i)]; blue = blueCoeff * c->nextRawLine[PREV_BLUE(i)] + (3-blueCoeff) * c->nextRawLine[NEXT_BLUE(i)]; *output++ = (red/3 + *prev++) / 2; *output++ = (green/3 + *prev++) / 2; *output++ = (blue/3 + *prev++) / 2; redCoeff = ADVANCE_COEFF(redCoeff); greenCoeff = ADVANCE_COEFF(greenCoeff); blueCoeff = ADVANCE_COEFF(blueCoeff); } return SANE_STATUS_GOOD; } /*********************************************************************** //%FUNCTION: attach_one (static function) //%ARGUMENTS: // dev -- device to attach //%RETURNS: // SANE_STATUS_GOOD //%DESCRIPTION: // tries to attach a device found by sanei_config_attach_matching_devices // *********************************************************************/ static SANE_Status attach_one (const char *dev) { DMCAttach (dev, 0); return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: sane_init //%ARGUMENTS: // version_code -- pointer to where we stick our version code // authorize -- authorization function //%RETURNS: // A sane status value //%DESCRIPTION: // Initializes DMC sane system. // *********************************************************************/ SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; authorize = authorize; DBG_INIT(); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); } fp = sanei_config_open(DMC_CONFIG_FILE); if (!fp) { /* default to /dev/camera instead of insisting on config file */ if (DMCAttach ("/dev/camera", NULL) != SANE_STATUS_GOOD) { /* OK, try /dev/scanner */ DMCAttach("/dev/scanner", NULL); } return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') { /* ignore line comments */ continue; } len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices(dev_name, attach_one); } fclose (fp); return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: sane_exit //%ARGUMENTS: // None //%RETURNS: // Nothing //%DESCRIPTION: // Cleans up all the SANE information // *********************************************************************/ void sane_exit(void) { DMC_Device *dev, *next; /* Close all handles */ while(FirstHandle) { sane_close(FirstHandle); } /* Free all devices */ dev = FirstDevice; while(dev) { next = dev->next; free((char *) dev->sane.model); free(dev); dev = next; } if (devlist) free (devlist); } /********************************************************************** //%FUNCTION: sane_get_devices //%ARGUMENTS: // device_list -- set to allocated list of devices // local_only -- ignored //%RETURNS: // A SANE status //%DESCRIPTION: // Returns a list of all known DMC devices // *********************************************************************/ SANE_Status sane_get_devices(SANE_Device const ***device_list, SANE_Bool local_only) { DMC_Device *dev; int i = 0; local_only = local_only; if (devlist) free(devlist); devlist = malloc((NumDevices+1) * sizeof(devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; for (dev=FirstDevice; dev; dev = dev->next) { devlist[i++] = &dev->sane; } devlist[i] = NULL; if (device_list) *device_list = devlist; return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: sane_open //%ARGUMENTS: // name -- name of device to open // handle -- set to a handle for the opened device //%RETURNS: // A SANE status //%DESCRIPTION: // Opens a DMC camera device // *********************************************************************/ SANE_Status sane_open(SANE_String_Const name, SANE_Handle *handle) { SANE_Status status; DMC_Device *dev; DMC_Camera *c; /* If we're given a device name, search for it */ if (*name) { for (dev = FirstDevice; dev; dev = dev->next) { if (!strcmp(dev->sane.name, name)) { break; } } if (!dev) { status = DMCAttach(name, &dev); if (status != SANE_STATUS_GOOD) return status; } } else { dev = FirstDevice; } if (!dev) return SANE_STATUS_INVAL; c = malloc(sizeof(*c)); if (!c) return SANE_STATUS_NO_MEM; memset(c, 0, sizeof(*c)); c->fd = -1; c->hw = dev; c->readBuffer = NULL; c->readPtr = NULL; c->imageMode = IMAGE_MFI; c->inViewfinderMode = 0; c->nextRawLineValid = 0; DMCInitOptions(c); c->next = FirstHandle; FirstHandle = c; if (handle) *handle = c; return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: sane_close //%ARGUMENTS: // handle -- handle of device to close //%RETURNS: // A SANE status //%DESCRIPTION: // Closes a DMC camera device // *********************************************************************/ void sane_close(SANE_Handle handle) { DMC_Camera *prev, *c; prev = NULL; for (c = FirstHandle; c; c = c->next) { if (c == handle) break; prev = c; } if (!c) { DBG(1, "close: invalid handle %p\n", handle); return; } DMCCancel(c); if (prev) prev->next = c->next; else FirstHandle = c->next; if (c->readBuffer) { free(c->readBuffer); } free(c); } /********************************************************************** //%FUNCTION: sane_get_option_descriptor //%ARGUMENTS: // handle -- handle of device // option -- option number to retrieve //%RETURNS: // An option descriptor or NULL on error // *********************************************************************/ SANE_Option_Descriptor const * sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) { DMC_Camera *c = ValidateHandle(handle); if (!c) return NULL; if ((unsigned) option >= NUM_OPTIONS) return NULL; return c->opt + option; } /********************************************************************** //%FUNCTION: sane_control_option //%ARGUMENTS: // handle -- handle of device // option -- option number to retrieve // action -- what to do with the option // val -- value to set option to // info -- returned info flags //%RETURNS: // SANE status //%DESCRIPTION: // Sets or queries option values // *********************************************************************/ SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int *info) { DMC_Camera *c; SANE_Word cap; int i; if (info) *info = 0; c = ValidateHandle(handle); if (!c) return SANE_STATUS_INVAL; if (c->fd >= 0) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = c->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE(cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { switch(c->opt[option].type) { case SANE_TYPE_INT: * (SANE_Int *) val = c->val[option].w; return SANE_STATUS_GOOD; case SANE_TYPE_STRING: strcpy(val, c->val[option].s); return SANE_STATUS_GOOD; default: DBG(3, "impossible option type!\n"); return SANE_STATUS_INVAL; } } if (action == SANE_ACTION_SET_AUTO) { return SANE_STATUS_UNSUPPORTED; } switch(option) { case OPT_IMAGE_MODE: for (i=0; ival[OPT_IMAGE_MODE].s = (SANE_String) ValidModes[i]; if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; } } break; case OPT_WHITE_BALANCE: for (i=0; i<=WHITE_BALANCE_FLUORESCENT; i++) { if (!strcmp(val, ValidBalances[i])) { c->val[OPT_WHITE_BALANCE].s = (SANE_String) ValidBalances[i]; return SANE_STATUS_GOOD; } } break; case OPT_ASA: for (i=1; i<= ASA_100+1; i++) { if (* ((SANE_Int *) val) == ValidASAs[i]) { c->val[OPT_ASA].w = ValidASAs[i]; return SANE_STATUS_GOOD; } } break; case OPT_SHUTTER_SPEED: if (* (SANE_Int *) val < c->hw->shutterSpeedRange.min || * (SANE_Int *) val > c->hw->shutterSpeedRange.max) { return SANE_STATUS_INVAL; } c->val[OPT_SHUTTER_SPEED].w = * (SANE_Int *) val; /* Do any roundoff */ c->val[OPT_SHUTTER_SPEED].w = TICKS_TO_MS(MS_TO_TICKS(c->val[OPT_SHUTTER_SPEED].w)); if (c->val[OPT_SHUTTER_SPEED].w != * (SANE_Int *) val) { if (info) *info |= SANE_INFO_INEXACT; } return SANE_STATUS_GOOD; default: /* Should really be INVAL, but just bit-bucket set requests... */ return SANE_STATUS_GOOD; } return SANE_STATUS_INVAL; } /********************************************************************** //%FUNCTION: sane_get_parameters //%ARGUMENTS: // handle -- handle of device // params -- set to device parameters //%RETURNS: // SANE status //%DESCRIPTION: // Returns parameters for current or next image. // *********************************************************************/ SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters *params) { DMC_Camera *c = ValidateHandle(handle); if (!c) return SANE_STATUS_INVAL; if (c->fd < 0) { int width, height; memset(&c->params, 0, sizeof(c->params)); width = c->val[OPT_BR_X].w - c->val[OPT_TL_X].w; height = c->val[OPT_BR_Y].w - c->val[OPT_TL_Y].w; c->params.pixels_per_line = width + 1; c->params.lines = height+1; c->params.depth = 8; c->params.last_frame = SANE_TRUE; switch(c->imageMode) { case IMAGE_SUPER_RES: case IMAGE_MFI: case IMAGE_THUMB: c->params.format = SANE_FRAME_RGB; c->params.bytes_per_line = c->params.pixels_per_line * 3; break; case IMAGE_RAW: case IMAGE_VIEWFINDER: c->params.format = SANE_FRAME_GRAY; c->params.bytes_per_line = c->params.pixels_per_line; break; } } if (params) *params = c->params; return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: sane_start //%ARGUMENTS: // handle -- handle of device //%RETURNS: // SANE status //%DESCRIPTION: // Starts acquisition // *********************************************************************/ SANE_Status sane_start(SANE_Handle handle) { static uint8_t const acquire[] = { 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t const viewfinder[] = { 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t const no_viewfinder[] = { 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; DMC_Camera *c = ValidateHandle(handle); SANE_Status status; int i; if (!c) return SANE_STATUS_INVAL; /* If we're already open, barf -- not sure this is the best status */ if (c->fd >= 0) return SANE_STATUS_DEVICE_BUSY; /* Get rid of old read buffers */ if (c->readBuffer) { free(c->readBuffer); c->readBuffer = NULL; c->readPtr = NULL; } c->nextRawLineValid = 0; /* Refresh parameter list */ status = sane_get_parameters(c, NULL); if (status != SANE_STATUS_GOOD) return status; status = sanei_scsi_open(c->hw->sane.name, &c->fd, NULL, NULL); if (status != SANE_STATUS_GOOD) { c->fd = -1; DBG(1, "DMC: Open of `%s' failed: %s\n", c->hw->sane.name, sane_strstatus(status)); return status; } /* Set ASA and shutter speed if they're no longer current */ if (c->val[OPT_ASA].w != c->hw->asa) { status = DMCSetASA(c->fd, c->val[OPT_ASA].w); if (status != SANE_STATUS_GOOD) { DMCCancel(c); return status; } c->hw->asa = c->val[OPT_ASA].w; } if ((unsigned int) c->val[OPT_SHUTTER_SPEED].w != c->hw->shutterSpeed) { status = DMCSetShutterSpeed(c->fd, c->val[OPT_SHUTTER_SPEED].w); if (status != SANE_STATUS_GOOD) { DMCCancel(c); return status; } c->hw->shutterSpeed = c->val[OPT_SHUTTER_SPEED].w; } /* Set white balance mode if needed */ for (i=0; i<=WHITE_BALANCE_FLUORESCENT; i++) { if (!strcmp(ValidBalances[i], c->val[OPT_WHITE_BALANCE].s)) { if (i != c->hw->whiteBalance) { status = DMCSetWhiteBalance(c->fd, i); if (status != SANE_STATUS_GOOD) { DMCCancel(c); return status; } c->hw->whiteBalance = i; } } } /* Flip into viewfinder mode if needed */ if (c->imageMode == IMAGE_VIEWFINDER && !c->inViewfinderMode) { status = sanei_scsi_cmd(c->fd, viewfinder, sizeof(viewfinder), NULL, NULL); if (status != SANE_STATUS_GOOD) { DMCCancel(c); return status; } c->inViewfinderMode = 1; } /* Flip out of viewfinder mode if needed */ if (c->imageMode != IMAGE_VIEWFINDER && c->inViewfinderMode) { status = sanei_scsi_cmd(c->fd, no_viewfinder, sizeof(no_viewfinder), NULL, NULL); if (status != SANE_STATUS_GOOD) { DMCCancel(c); return status; } c->inViewfinderMode = 0; } status = sanei_scsi_cmd(c->fd, acquire, sizeof(acquire), NULL, NULL); if (status != SANE_STATUS_GOOD) { DMCCancel(c); return status; } c->bytes_to_read = c->params.bytes_per_line * c->params.lines; return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: sane_read //%ARGUMENTS: // handle -- handle of device // buf -- destination for data // max_len -- maximum amount of data to store // len -- set to actual amount of data stored. //%RETURNS: // SANE status //%DESCRIPTION: // Reads image data from the camera // *********************************************************************/ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { SANE_Status status; DMC_Camera *c = ValidateHandle(handle); size_t size; SANE_Int i; if (!c) return SANE_STATUS_INVAL; if (c->fd < 0) return SANE_STATUS_INVAL; if (c->bytes_to_read == 0) { if (c->readBuffer) { free(c->readBuffer); c->readBuffer = NULL; c->readPtr = NULL; } DMCCancel(c); return SANE_STATUS_EOF; } if (max_len == 0) { return SANE_STATUS_GOOD; } if (c->imageMode == IMAGE_SUPER_RES) { /* We have to read *two* complete rows... */ max_len = (max_len / (2*c->params.bytes_per_line)) * (2*c->params.bytes_per_line); /* If user is trying to read less than two complete lines, fail */ if (max_len == 0) return SANE_STATUS_INVAL; if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read; for (i=0; iparams.bytes_per_line) { c->bytes_to_read -= 2*c->params.bytes_per_line; status = DMCReadTwoSuperResolutionLines(c, buf+i, !c->bytes_to_read); if (status != SANE_STATUS_GOOD) return status; } *len = max_len; return SANE_STATUS_GOOD; } if (c->imageMode == IMAGE_MFI || c->imageMode == IMAGE_RAW) { /* We have to read complete rows... */ max_len = (max_len / c->params.bytes_per_line) * c->params.bytes_per_line; /* If user is trying to read less than one complete row, fail */ if (max_len == 0) return SANE_STATUS_INVAL; if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read; c->bytes_to_read -= (unsigned int) max_len; status = DMCRead(c->fd, 0x00, c->imageMode, buf, max_len, &size); *len = size; return status; } if ((unsigned int) max_len > c->bytes_to_read) max_len = c->bytes_to_read; if (c->readPtr) { *len = max_len; memcpy(buf, c->readPtr, max_len); c->readPtr += max_len; c->bytes_to_read -= max_len; return SANE_STATUS_GOOD; } /* Fill the read buffer completely */ c->readBuffer = malloc(c->bytes_to_read); if (!c->readBuffer) return SANE_STATUS_NO_MEM; c->readPtr = c->readBuffer; status = DMCRead(c->fd, 0x00, c->imageMode, (SANE_Byte *) c->readBuffer, c->bytes_to_read, &size); *len = size; if (status != SANE_STATUS_GOOD) return status; if ((unsigned int) *len != c->bytes_to_read) return SANE_STATUS_IO_ERROR; /* Now copy */ *len = max_len; memcpy(buf, c->readPtr, max_len); c->readPtr += max_len; c->bytes_to_read -= max_len; return SANE_STATUS_GOOD; } /********************************************************************** //%FUNCTION: sane_cancel //%ARGUMENTS: // handle -- handle of device //%RETURNS: // Nothing //%DESCRIPTION: // A quick cancellation of the scane // *********************************************************************/ void sane_cancel (SANE_Handle handle) { DMC_Camera *c = ValidateHandle(handle); if (!c) return; DMCCancel(c); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { handle = handle; non_blocking = non_blocking; return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int *fd) { handle = handle; fd = fd; return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/sm3600.h0000664000175000017500000002441612112021330013702 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) Marian Matthias Eichholz 2001 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef _H_SM3600 #define _H_SM3600 /* ====================================================================== sm3600.h SANE backend master module. Definitions ported from "scantool.h" 5.4.2001. (C) Marian Matthias Eichholz 2001 Start: 2.4.2001 ====================================================================== */ #define DEBUG_SCAN 0x0001 #define DEBUG_COMM 0x0002 #define DEBUG_ORIG 0x0004 #define DEBUG_BASE 0x0011 #define DEBUG_DEVSCAN 0x0012 #define DEBUG_REPLAY 0x0014 #define DEBUG_BUFFER 0x0018 #define DEBUG_SIGNALS 0x0020 #define DEBUG_CALIB 0x0040 #define DEBUG_CRITICAL 1 #define DEBUG_VERBOSE 2 #define DEBUG_INFO 3 #define DEBUG_JUNK 5 #define USB_TIMEOUT_JIFFIES 2000 #define SCANNER_VENDOR 0x05DA #define MAX_PIXEL_PER_SCANLINE 5300 /* ====================================================================== */ typedef enum { false, true } TBool; typedef SANE_Status TState; typedef enum { unknown, sm3600, sm3700, sm3750 } TModel; typedef struct { TBool bCalibrated; int xMargin; /* in 1/600 inch */ int yMargin; /* in 1/600 inch */ unsigned char nHoleGray; unsigned char nBarGray; long rgbBias; unsigned char *achStripeY; unsigned char *achStripeR; unsigned char *achStripeG; unsigned char *achStripeB; } TCalibration; typedef struct { int x; int y; int cx; int cy; int res; /* like all parameters in 1/1200 inch */ int nBrightness; /* -255 ... 255 */ int nContrast; /* -128 ... 127 */ } TScanParam; typedef enum { fast, high, best } TQuality; typedef enum { color, gray, line, halftone } TMode; #define INST_ASSERT() { if (this->nErrorState) return this->nErrorState; } #define CHECK_ASSERTION(a) if (!(a)) return SetError(this,SANE_STATUS_INVAL,"assertion failed in %s %d",__FILE__,__LINE__) #define CHECK_POINTER(p) \ if (!(p)) return SetError(this,SANE_STATUS_NO_MEM,"memory failed in %s %d",__FILE__,__LINE__) #define dprintf debug_printf typedef struct TInstance *PTInstance; typedef TState (*TReadLineCB)(PTInstance); typedef struct TScanState { TBool bEOF; /* EOF marker for sane_read */ TBool bCanceled; TBool bScanning; /* block is active? */ TBool bLastBulk; /* EOF announced */ int iReadPos; /* read() interface */ int iBulkReadPos; /* bulk read pos */ int iLine; /* log no. line */ int cchBulk; /* available bytes in bulk buffer */ int cchLineOut; /* buffer size */ int cxPixel,cyPixel; /* real pixel */ int cxMax; /* uninterpolated in real pixels */ int cxWindow; /* Window with in 600 DPI */ int cyWindow; /* Path length in 600 DPI */ int cyTotalPath; /* from bed start to window end in 600 dpi */ int nFixAspect; /* aspect ratio in percent, 75-100 */ int cBacklog; /* depth of ppchLines */ int ySensorSkew; /* distance in pixel between sensors */ char *szOrder; /* 123 or 231 or whatever */ unsigned char *pchBuf; /* bulk transfer buffer */ short **ppchLines; /* for error diffusion and color corr. */ unsigned char *pchLineOut; /* read() interface */ TReadLineCB ReadProc; /* line getter callback */ } TScanState; #ifndef INSANE_VERSION #ifdef SM3600_SUPPORT_EXPOSURE #define NUM_OPTIONS 18 #else #define NUM_OPTIONS 16 #endif typedef struct TDevice { struct TDevice *pNext; struct usb_device *pdev; TModel model; SANE_Device sane; char *szSaneName; } TDevice; #endif typedef struct TInstance { #ifndef INSANE_VERSION struct TInstance *pNext; SANE_Option_Descriptor aoptDesc[NUM_OPTIONS]; Option_Value aoptVal[NUM_OPTIONS]; #endif SANE_Int agammaY[4096]; SANE_Int agammaR[4096]; SANE_Int agammaG[4096]; SANE_Int agammaB[4096]; TScanState state; TCalibration calibration; TState nErrorState; char *szErrorReason; TBool bSANE; TScanParam param; TBool bWriteRaw; TBool bVerbose; TBool bOptSkipOriginate; TQuality quality; TMode mode; TModel model; int hScanner; FILE *fhLog; FILE *fhScan; int ichPageBuffer; /* write position in full page buffer */ int cchPageBuffer; /* total size of '' */ unsigned char *pchPageBuffer; /* the humble buffer */ } TInstance; #define TRUE 1 #define FALSE 0 /* ====================================================================== */ #define ERR_FAILED -1 #define OK 0 #define NUM_SCANREGS 74 /* ====================================================================== */ /* note: The first register has address 0x01 */ #define R_ALL 0x01 /* have to become an enumeration */ typedef enum { none, hpos, hposH, hres } TRegIndex; /* WORD */ #define R_SPOS 0x01 #define R_XRES 0x03 /* WORD */ #define R_SWID 0x04 /* WORD */ #define R_STPS 0x06 /* WORD */ #define R_YRES 0x08 /* WORD */ #define R_SLEN 0x0A /* WORD*/ #define R_INIT 0x12 #define RVAL_INIT 0x1540 /* RGB */ #define R_CCAL 0x2F /* WORD */ #define R_CSTAT 0x42 #define R_CTL 0x46 /* WORD */ #define R_POS 0x52 /* WORD */ #define R_LMP 0x44 #define R_QLTY 0x4A #define R_STAT 0x54 #define LEN_MAGIC 0x24EA /* ====================================================================== */ #define USB_CHUNK_SIZE 0x8000 /* sm3600-scanutil.c */ __SM3600EXPORT__ int SetError(TInstance *this, int nError, const char *szFormat, ...); __SM3600EXPORT__ void debug_printf(unsigned long ulType, const char *szFormat, ...); __SM3600EXPORT__ TState FreeState(TInstance *this, TState nReturn); __SM3600EXPORT__ TState EndScan(TInstance *this); __SM3600EXPORT__ TState ReadChunk(TInstance *this, unsigned char *achOut, int cchMax, int *pcchRead); #ifdef INSANE_VERSION __SM3600EXPORT__ void DumpBuffer(FILE *fh, const char *pch, int cch); __SM3600EXPORT__ TState DoScanFile(TInstance *this); #endif __SM3600EXPORT__ void GetAreaSize(TInstance *this); __SM3600EXPORT__ void ResetCalibration(TInstance *this); __SM3600EXPORT__ TState InitGammaTables(TInstance *this, int nBrightness, int nContrast); __SM3600EXPORT__ TState CancelScan(TInstance *this); /* sm3600-scanmtek.c */ extern unsigned short aidProduct[]; __SM3600EXPORT__ TState DoInit(TInstance *this); __SM3600EXPORT__ TState DoReset(TInstance *this); __SM3600EXPORT__ TState WaitWhileBusy(TInstance *this,int cSecs); __SM3600EXPORT__ TState WaitWhileScanning(TInstance *this,int cSecs); __SM3600EXPORT__ TModel GetScannerModel(unsigned short idVendor, unsigned short idProduct); #ifdef INSANE_VERSION __SM3600EXPORT__ TState DoLampSwitch(TInstance *this,int nPattern); #endif __SM3600EXPORT__ TState DoCalibration(TInstance *this); __SM3600EXPORT__ TState UploadGammaTable(TInstance *this, int iByteAddress, SANE_Int *pnGamma); __SM3600EXPORT__ TState UploadGainCorrection(TInstance *this, int iTableOffset); /* sm3600-scanusb.c */ __SM3600EXPORT__ TState RegWrite(TInstance *this,int iRegister, int cb, unsigned long ulValue); __SM3600EXPORT__ TState RegWriteArray(TInstance *this,int iRegister, int cb, unsigned char *pchBuffer); #ifdef INSANE_VERSIONx __SM3600EXPORT__ TState RegCheck(TInstance *this,int iRegister, int cch, unsigned long ulValue); __SM3600EXPORT__ int BulkRead(TInstance *this,FILE *fhOut, unsigned int cchBulk); __SM3600EXPORT__ TState MemReadArray(TInstance *this, int iAddress, int cb, unsigned char *pchBuffer); #endif __SM3600EXPORT__ int BulkReadBuffer(TInstance *this,unsigned char *puchBufferOut, unsigned int cchBulk); /* gives count */ __SM3600EXPORT__ unsigned int RegRead(TInstance *this,int iRegister, int cch); __SM3600EXPORT__ TState MemWriteArray(TInstance *this, int iAddress, int cb, unsigned char *pchBuffer); /* sm3600-gray.c */ __SM3600EXPORT__ TState StartScanGray(TInstance *this); /* sm3600-color.c */ __SM3600EXPORT__ TState StartScanColor(TInstance *this); /* sm3600-homerun.c */ #ifdef INSANE_VERSION __SM3600EXPORT__ TState FakeCalibration(TInstance *this); #endif __SM3600EXPORT__ TState DoOriginate(TInstance *this, TBool bStepOut); __SM3600EXPORT__ TState DoJog(TInstance *this,int nDistance); /* ====================================================================== */ #endif sane-backends-1.0.27/backend/v4l.conf.in0000664000175000017500000000031412112021330014551 00000000000000# # In order to use the v4linux backend you have to give the device # You can enable multiple lines if # you really have multible v4l devices. # /dev/bttv0 /dev/video0 /dev/video1 /dev/video2 /dev/video3 sane-backends-1.0.27/backend/genesys_gl124.c0000664000175000017500000032540112775312261015356 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2010-2016 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME #define BACKEND_NAME genesys_gl124 #include "genesys_gl124.h" /**************************************************************************** Low level function ****************************************************************************/ /* ------------------------------------------------------------------------ */ /* Read and write RAM, registers and AFE */ /* ------------------------------------------------------------------------ */ /** @brief read scanned data * Read in 0xeff0 maximum sized blocks. This read is done in 2 * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the * remainder. Read addr is always 0x10000000 with the memory layout setup. * @param dev device to read data from * @param addr address within ASIC emory space * @param data pointer where to store the read data * @param len size to read */ static SANE_Status gl124_bulk_read_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size, target, read, done; uint8_t outdata[8], *buffer; DBG (DBG_io, "gl124_bulk_read_data: requesting %lu bytes (unused addr=0x%02x)\n", (u_long) len,addr); if (len == 0) return SANE_STATUS_GOOD; target = len; buffer = data; /* loop until computed data size is read */ while (target) { if (target > 0xeff0) { size = 0xeff0; } else { size = target; } /* hard coded 0x10000000 addr */ outdata[0] = 0; outdata[1] = 0; outdata[2] = 0; outdata[3] = 0x10; /* data size to transfer */ outdata[4] = (size & 0xff); outdata[5] = ((size >> 8) & 0xff); outdata[6] = ((size >> 16) & 0xff); outdata[7] = ((size >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, 0x00, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s failed while writing command: %s\n", __func__, sane_strstatus (status)); return status; } /* blocks must be multiple of 512 but not last block */ read = size; read /= 512; read *= 512; if(read>0) { DBG (DBG_io2, "gl124_bulk_read_data: trying to read %lu bytes of data\n", (u_long) read); status = sanei_usb_read_bulk (dev->dn, data, &read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } } /* read less than 512 bytes remainder */ if (read < size) { done = read; read = size - read; DBG (DBG_io2, "gl124_bulk_read_data: trying to read remaining %lu bytes of data\n", (u_long) read); status = sanei_usb_read_bulk (dev->dn, data+done, &read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } } DBG (DBG_io2, "%s: read %lu bytes, %lu remaining\n", __func__, (u_long) size, (u_long) (target - size)); target -= size; data += size; } if (DBG_LEVEL >= DBG_data && dev->binary!=NULL) { fwrite(buffer, len, 1, dev->binary); } DBGCOMPLETED; return SANE_STATUS_GOOD; } /**************************************************************************** Mid level functions ****************************************************************************/ static SANE_Bool gl124_get_fast_feed_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG02); if (r && (r->value & REG02_FASTFED)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl124_get_filter_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_FILTER)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl124_get_lineart_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_LINEART)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl124_get_bitset_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_BITSET)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl124_get_gain4_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG06); if (r && (r->value & REG06_GAIN4)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl124_test_buffer_empty_bit (SANE_Byte val) { if (val & BUFEMPTY) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl124_test_motor_flag_bit (SANE_Byte val) { if (val & MOTORENB) return SANE_TRUE; return SANE_FALSE; } /** @brief sensor profile * search for the database of motor profiles and get the best one. Each * profile is at a specific dpihw. Use LiDE 110 table by default. * @param sensor_type sensor id * @param dpi hardware dpi for the scan * @param half_ccd flag to signal half ccd mode * @return a pointer to a Sensor_Profile struct */ static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi, int half_ccd) { unsigned int i; int idx; i=0; idx=-1; while(i=dpi && sensors[i].dpiflags & GENESYS_FLAG_HALF_CCD_MODE)) { return SANE_TRUE; } return SANE_FALSE; } /** @brief set all registers to default values . * This function is called only once at the beginning and * fills register startup values for registers reused across scans. * Those that are rarely modified or not modified are written * individually. * @param dev device structure holding register set to initialize */ static void gl124_init_registers (Genesys_Device * dev) { DBGSTART; memset (dev->reg, 0, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); /* default to LiDE 110 */ SETREG (0x01,0xa2); /* + REG01_SHDAREA */ SETREG (0x02,0x90); SETREG (0x03,0x50); SETREG (0x04,0x03); SETREG (0x05,0x00); if(dev->model->ccd_type==CIS_CANONLIDE120) { SETREG (0x06,0x50); SETREG (0x07,0x00); } else { SETREG (0x03,0x50 & ~REG03_AVEENB); SETREG (0x06,0x50 | REG06_GAIN4); } SETREG (0x09,0x00); SETREG (0x0a,0xc0); SETREG (0x0b,0x2a); SETREG (0x0c,0x12); SETREG (0x11,0x00); SETREG (0x12,0x00); SETREG (0x13,0x0f); SETREG (0x14,0x00); SETREG (0x15,0x80); SETREG (0x16,0x10); SETREG (0x17,0x04); SETREG (0x18,0x00); SETREG (0x19,0x01); SETREG (0x1a,0x30); SETREG (0x1b,0x00); SETREG (0x1c,0x00); SETREG (0x1d,0x01); SETREG (0x1e,0x10); SETREG (0x1f,0x00); SETREG (0x20,0x15); SETREG (0x21,0x00); if(dev->model->ccd_type!=CIS_CANONLIDE120) { SETREG (0x22,0x02); } else { SETREG (0x22,0x14); } SETREG (0x23,0x00); SETREG (0x24,0x00); SETREG (0x25,0x00); SETREG (0x26,0x0d); SETREG (0x27,0x48); SETREG (0x28,0x00); SETREG (0x29,0x56); SETREG (0x2a,0x5e); SETREG (0x2b,0x02); SETREG (0x2c,0x02); SETREG (0x2d,0x58); SETREG (0x3b,0x00); SETREG (0x3c,0x00); SETREG (0x3d,0x00); SETREG (0x3e,0x00); SETREG (0x3f,0x02); SETREG (0x40,0x00); SETREG (0x41,0x00); SETREG (0x42,0x00); SETREG (0x43,0x00); SETREG (0x44,0x00); SETREG (0x45,0x00); SETREG (0x46,0x00); SETREG (0x47,0x00); SETREG (0x48,0x00); SETREG (0x49,0x00); SETREG (0x4f,0x00); SETREG (0x52,0x00); SETREG (0x53,0x02); SETREG (0x54,0x04); SETREG (0x55,0x06); SETREG (0x56,0x04); SETREG (0x57,0x04); SETREG (0x58,0x04); SETREG (0x59,0x04); SETREG (0x5a,0x1a); SETREG (0x5b,0x00); SETREG (0x5c,0xc0); SETREG (0x5f,0x00); SETREG (0x60,0x02); SETREG (0x61,0x00); SETREG (0x62,0x00); SETREG (0x63,0x00); SETREG (0x64,0x00); SETREG (0x65,0x00); SETREG (0x66,0x00); SETREG (0x67,0x00); SETREG (0x68,0x00); SETREG (0x69,0x00); SETREG (0x6a,0x00); SETREG (0x6b,0x00); SETREG (0x6c,0x00); SETREG (0x6e,0x00); SETREG (0x6f,0x00); if(dev->model->ccd_type!=CIS_CANONLIDE120) { SETREG (0x6d,0xd0); SETREG (0x71,0x08); } else { SETREG (0x6d,0x00); SETREG (0x71,0x1f); } SETREG (0x70,0x00); SETREG (0x72,0x08); SETREG (0x73,0x0a); /* CKxMAP */ SETREG (0x74,0x00); SETREG (0x75,0x00); SETREG (0x76,0x3c); SETREG (0x77,0x00); SETREG (0x78,0x00); SETREG (0x79,0x9f); SETREG (0x7a,0x00); SETREG (0x7b,0x00); SETREG (0x7c,0x55); SETREG (0x7d,0x00); SETREG (0x7e,0x08); SETREG (0x7f,0x58); if(dev->model->ccd_type!=CIS_CANONLIDE120) { SETREG (0x80,0x00); SETREG (0x81,0x14); } else { SETREG (0x80,0x00); SETREG (0x81,0x10); } /* STRPIXEL */ SETREG (0x82,0x00); SETREG (0x83,0x00); SETREG (0x84,0x00); /* ENDPIXEL */ SETREG (0x85,0x00); SETREG (0x86,0x00); SETREG (0x87,0x00); SETREG (0x88,0x00); SETREG (0x89,0x65); SETREG (0x8a,0x00); SETREG (0x8b,0x00); SETREG (0x8c,0x00); SETREG (0x8d,0x00); SETREG (0x8e,0x00); SETREG (0x8f,0x00); SETREG (0x90,0x00); SETREG (0x91,0x00); SETREG (0x92,0x00); SETREG (0x93,0x00); SETREG (0x94,0x14); SETREG (0x95,0x30); SETREG (0x96,0x00); SETREG (0x97,0x90); SETREG (0x98,0x01); SETREG (0x99,0x1f); SETREG (0x9a,0x00); SETREG (0x9b,0x80); SETREG (0x9c,0x80); SETREG (0x9d,0x3f); SETREG (0x9e,0x00); SETREG (0x9f,0x00); SETREG (0xa0,0x20); SETREG (0xa1,0x30); SETREG (0xa2,0x00); SETREG (0xa3,0x20); SETREG (0xa4,0x01); SETREG (0xa5,0x00); SETREG (0xa6,0x00); SETREG (0xa7,0x08); SETREG (0xa8,0x00); SETREG (0xa9,0x08); SETREG (0xaa,0x01); SETREG (0xab,0x00); SETREG (0xac,0x00); SETREG (0xad,0x40); SETREG (0xae,0x01); SETREG (0xaf,0x00); SETREG (0xb0,0x00); SETREG (0xb1,0x40); SETREG (0xb2,0x00); SETREG (0xb3,0x09); SETREG (0xb4,0x5b); SETREG (0xb5,0x00); SETREG (0xb6,0x10); SETREG (0xb7,0x3f); SETREG (0xb8,0x00); SETREG (0xbb,0x00); SETREG (0xbc,0xff); SETREG (0xbd,0x00); SETREG (0xbe,0x07); SETREG (0xc3,0x00); SETREG (0xc4,0x00); /* gamma SETREG (0xc5,0x00); SETREG (0xc6,0x00); SETREG (0xc7,0x00); SETREG (0xc8,0x00); SETREG (0xc9,0x00); SETREG (0xca,0x00); SETREG (0xcb,0x00); SETREG (0xcc,0x00); SETREG (0xcd,0x00); SETREG (0xce,0x00); */ if(dev->model->ccd_type==CIS_CANONLIDE120) { SETREG (0xc5,0x20); SETREG (0xc6,0xeb); SETREG (0xc7,0x20); SETREG (0xc8,0xeb); SETREG (0xc9,0x20); SETREG (0xca,0xeb); } /* memory layout SETREG (0xd0,0x0a); SETREG (0xd1,0x1f); SETREG (0xd2,0x34); */ SETREG (0xd3,0x00); SETREG (0xd4,0x00); SETREG (0xd5,0x00); SETREG (0xd6,0x00); SETREG (0xd7,0x00); SETREG (0xd8,0x00); SETREG (0xd9,0x00); /* memory layout SETREG (0xe0,0x00); SETREG (0xe1,0x48); SETREG (0xe2,0x15); SETREG (0xe3,0x90); SETREG (0xe4,0x15); SETREG (0xe5,0x91); SETREG (0xe6,0x2a); SETREG (0xe7,0xd9); SETREG (0xe8,0x2a); SETREG (0xe9,0xad); SETREG (0xea,0x40); SETREG (0xeb,0x22); SETREG (0xec,0x40); SETREG (0xed,0x23); SETREG (0xee,0x55); SETREG (0xef,0x6b); SETREG (0xf0,0x55); SETREG (0xf1,0x6c); SETREG (0xf2,0x6a); SETREG (0xf3,0xb4); SETREG (0xf4,0x6a); SETREG (0xf5,0xb5); SETREG (0xf6,0x7f); SETREG (0xf7,0xfd);*/ SETREG (0xf8,0x01); /* other value is 0x05 */ SETREG (0xf9,0x00); SETREG (0xfa,0x00); SETREG (0xfb,0x00); SETREG (0xfc,0x00); SETREG (0xff,0x00); /* fine tune upon device description */ dev->reg[reg_0x05].value &= ~REG05_DPIHW; switch (dev->sensor.optical_res) { case 600: dev->reg[reg_0x05].value |= REG05_DPIHW_600; break; case 1200: dev->reg[reg_0x05].value |= REG05_DPIHW_1200; break; case 2400: dev->reg[reg_0x05].value |= REG05_DPIHW_2400; break; case 4800: dev->reg[reg_0x05].value |= REG05_DPIHW_4800; break; } /* initalize calibration reg */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); DBGCOMPLETED; } /**@brief send slope table for motor movement * Send slope_table in machine byte order * @param dev device to send slope table * @param table_nr index of the slope table in ASIC memory * Must be in the [0-4] range. * @param slope_table pointer to 16 bit values array of the slope table * @param steps number of elemnts in the slope table */ GENESYS_STATIC SANE_Status gl124_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps) { SANE_Status status; uint8_t *table; int i; char msg[10000]; DBG (DBG_proc, "%s (table_nr = %d, steps = %d)\n", __func__, table_nr, steps); /* sanity check */ if(table_nr<0 || table_nr>4) { DBG (DBG_error, "%s: invalid table number %d!\n", __func__, table_nr); return SANE_STATUS_INVAL; } table = (uint8_t *) malloc (steps * 2); for (i = 0; i < steps; i++) { table[i * 2] = slope_table[i] & 0xff; table[i * 2 + 1] = slope_table[i] >> 8; } if (DBG_LEVEL >= DBG_io) { sprintf (msg, "write slope %d (%d)=", table_nr, steps); for (i = 0; i < steps; i++) { sprintf (msg+strlen(msg), ",%d", slope_table[i]); } DBG (DBG_io, "%s: %s\n", __func__, msg); } /* slope table addresses are fixed */ status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, 0x10000000 + 0x4000 * table_nr, steps * 2, table); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: write to AHB failed writing slope table %d (%s)\n", __func__, table_nr, sane_strstatus (status)); } free (table); DBGCOMPLETED; return status; } /** @brief * Set register values of 'special' ti type frontend * Registers value are taken from the frontend register data * set. * @param dev device owning the AFE * @param set flag AFE_INIT to specify the AFE must be reset before writing data * */ static SANE_Status gl124_set_ti_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status = SANE_STATUS_GOOD; int i; uint16_t val; DBGSTART; if (set == AFE_INIT) { DBG (DBG_proc, "%s: setting DAC %u\n", __func__, dev->model->dac_type); /* sets to default values */ sanei_genesys_init_fe (dev); } /* start writing to DAC */ status = sanei_genesys_fe_write_data (dev, 0x00, 0x80); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write reg0: %s\n", __func__, sane_strstatus (status)); return status; } /* write values to analog frontend */ for (i = 1; i < 4; i++) { val = dev->frontend.reg[i]; status = sanei_genesys_fe_write_data (dev, i, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write reg %d: %s\n", __func__, i, sane_strstatus (status)); return status; } } status = sanei_genesys_fe_write_data (dev, 0x04, 0x00); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write reg4: %s\n", __func__, sane_strstatus (status)); return status; } /* these are not really sign for this AFE */ for (i = 0; i < 3; i++) { val = dev->frontend.sign[i]; status = sanei_genesys_fe_write_data (dev, 0x05 + i, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write reg %d: %s\n", __func__, i+5, sane_strstatus (status)); return status; } } /* close writing to DAC */ if(dev->model->dac_type == DAC_CANONLIDE120) { status = sanei_genesys_fe_write_data (dev, 0x00, 0x01); } else { status = sanei_genesys_fe_write_data (dev, 0x00, 0x11); } if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write reg0: %s\n", __func__, sane_strstatus (status)); return status; } DBGCOMPLETED; return status; } /* Set values of analog frontend */ static SANE_Status gl124_set_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status; uint8_t val; DBG (DBG_proc, "gl124_set_fe (%s)\n", set == AFE_INIT ? "init" : set == AFE_SET ? "set" : set == AFE_POWER_SAVE ? "powersave" : "huh?"); if (set == AFE_INIT) { DBG (DBG_proc, "gl124_set_fe(): setting DAC %u\n", dev->model->dac_type); sanei_genesys_init_fe (dev); } RIE (sanei_genesys_read_register (dev, REG0A, &val)); if(dev->usb_mode<0) { val=3<>REG0AS_SIFSEL) { case 3: status=gl124_set_ti_fe (dev, set); break; case 0: case 1: case 2: default: DBG (DBG_error, "%s: unsupported analog FE 0x%02x\n",__func__,val); status=SANE_STATUS_INVAL; break; } DBGCOMPLETED; return status; } /**@brief compute exposure to use * compute the sensor exposure based on target resolution * @param dev pointer to device description * @param xres sensor's required resolution * @param half_ccd flag for half ccd mode */ static int gl124_compute_exposure(Genesys_Device *dev, int xres, int half_ccd) { Sensor_Profile *sensor; sensor=get_sensor_profile(dev->model->ccd_type, xres, half_ccd); return sensor->exposure; } static SANE_Status gl124_init_motor_regs_scan (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int scan_exposure_time, float scan_yres, int scan_step_type, unsigned int scan_lines, unsigned int scan_dummy, unsigned int feed_steps, int scan_mode, unsigned int flags) { SANE_Status status; int use_fast_fed; unsigned int lincnt, fast_dpi; uint16_t scan_table[SLOPE_TABLE_SIZE]; uint16_t fast_table[SLOPE_TABLE_SIZE]; int scan_steps,fast_steps,factor; unsigned int feedl,dist; Genesys_Register_Set *r; uint32_t z1, z2; float yres; int min_speed; unsigned int linesel; DBGSTART; DBG (DBG_info, "gl124_init_motor_regs_scan : scan_exposure_time=%d, " "scan_yres=%g, scan_step_type=%d, scan_lines=%d, scan_dummy=%d, " "feed_steps=%d, scan_mode=%d, flags=%x\n", scan_exposure_time, scan_yres, scan_step_type, scan_lines, scan_dummy, feed_steps, scan_mode, flags); /* we never use fast fed since we do manual feed for the scans */ use_fast_fed=0; factor=1; /* enforce motor minimal scan speed * @TODO extend motor struct for this value */ if (scan_mode == SCAN_MODE_COLOR) { min_speed = 900; } else { switch(dev->model->motor_type) { case MOTOR_CANONLIDE110: min_speed = 600; break; case MOTOR_CANONLIDE120: min_speed = 900; break; default: min_speed = 900; break; } } /* compute min_speed and linesel */ if(scan_yres 0 */ if(linesel==0) { linesel=1; yres=scan_yres*2; } } else { yres=scan_yres; linesel=0; } DBG (DBG_io2, "%s: final yres=%f, linesel=%d\n", __func__, yres, linesel); lincnt=scan_lines*(linesel+1); sanei_genesys_set_triple(reg,REG_LINCNT,lincnt); DBG (DBG_io, "%s: lincnt=%d\n", __func__, lincnt); /* compute register 02 value */ r = sanei_genesys_get_address (reg, REG02); r->value = REG02_NOTHOME; r->value |= REG02_MTRPWR; if (use_fast_fed) r->value |= REG02_FASTFED; else r->value &= ~REG02_FASTFED; if (flags & MOTOR_FLAG_AUTO_GO_HOME) r->value |= REG02_AGOHOME; if ((flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE) ||(yres>=dev->sensor.optical_res)) r->value |= REG02_ACDCDIS; /* SCANFED */ sanei_genesys_set_double(reg,REG_SCANFED,4); /* scan and backtracking slope table */ sanei_genesys_slope_table(scan_table, &scan_steps, yres, scan_exposure_time, dev->motor.base_ydpi, scan_step_type, factor, dev->model->motor_type, motors); RIE(gl124_send_slope_table (dev, SCAN_TABLE, scan_table, scan_steps)); RIE(gl124_send_slope_table (dev, BACKTRACK_TABLE, scan_table, scan_steps)); /* STEPNO */ sanei_genesys_set_double(reg,REG_STEPNO,scan_steps); /* fast table */ fast_dpi=yres; /* if (scan_mode != SCAN_MODE_COLOR) { fast_dpi*=3; } */ sanei_genesys_slope_table(fast_table, &fast_steps, fast_dpi, scan_exposure_time, dev->motor.base_ydpi, scan_step_type, factor, dev->model->motor_type, motors); RIE(gl124_send_slope_table (dev, STOP_TABLE, fast_table, fast_steps)); RIE(gl124_send_slope_table (dev, FAST_TABLE, fast_table, fast_steps)); /* FASTNO */ sanei_genesys_set_double(reg,REG_FASTNO,fast_steps); /* FSHDEC */ sanei_genesys_set_double(reg,REG_FSHDEC,fast_steps); /* FMOVNO */ sanei_genesys_set_double(reg,REG_FMOVNO,fast_steps); /* substract acceleration distance from feedl */ feedl=feed_steps; feedl<<=scan_step_type; dist = scan_steps; if (flags & MOTOR_FLAG_FEED) dist *=2; if (use_fast_fed) { dist += fast_steps*2; } DBG (DBG_io2, "%s: acceleration distance=%d\n", __func__, dist); /* get sure we don't use insane value */ if(distvalue = (r->value & ~REG1D_LINESEL) | linesel; r = sanei_genesys_get_address (reg, REGA0); r->value = (scan_step_type << REGA0S_STEPSEL) | (scan_step_type << REGA0S_FSTPSEL); /* FMOVDEC */ sanei_genesys_set_double(reg,REG_FMOVDEC,fast_steps); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief copy sensor specific settings * Set up register set for the given sensor resolution. Values are from the device table * in genesys_devices.c for registers: * [0x16 ... 0x1d] * [0x52 ... 0x5e] * Other come from the specific device sensor table in genesys_gl124.h: * 0x18, 0x20, 0x61, 0x98 and * @param dev device to set up * @param regs register set to modify * @param dpi resolution of the sensor during scan * @param half_ccd flag for half ccd mode * */ static void gl124_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs, int dpi, int half_ccd) { Genesys_Register_Set *r; int i; Sensor_Profile *sensor; int dpihw; uint32_t exp; DBGSTART; /* we start at 6, 0-5 is a 16 bits cache for exposure */ for (i = 0x06; i < 0x0e; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); if (r) { r->value = dev->sensor.regs_0x10_0x1d[i]; } } /* skip writing 5d,5e which is AFE address because * they are not deifned in register set */ for (i = 0; i < 11; i++) { r = sanei_genesys_get_address (regs, 0x52 + i); if (r) { r->value = dev->sensor.regs_0x52_0x5e[i]; } } /* set EXPDUMMY and CKxMAP */ dpihw=sanei_genesys_compute_dpihw(dev,dpi); sensor=get_sensor_profile(dev->model->ccd_type, dpihw, half_ccd); r = sanei_genesys_get_address (regs, 0x18); if (r) { r->value = sensor->reg18; } r = sanei_genesys_get_address (regs, 0x20); if (r) { r->value = sensor->reg20; } r = sanei_genesys_get_address (regs, 0x61); if (r) { r->value = sensor->reg61; } r = sanei_genesys_get_address (regs, 0x98); if (r) { r->value = sensor->reg98; } if(sensor->reg16!=0) { r = sanei_genesys_get_address (regs, 0x16); if (r) { r->value = sensor->reg16; } } if(sensor->reg70!=0) { r = sanei_genesys_get_address (regs, 0x70); if (r) { r->value = sensor->reg70; } } sanei_genesys_set_triple(regs,REG_SEGCNT,sensor->segcnt); sanei_genesys_set_double(regs,REG_TG0CNT,sensor->tg0cnt); sanei_genesys_set_double(regs,REG_EXPDMY,sensor->expdummy); /* if no calibration has been done, set default values for exposures */ exp=dev->sensor.regs_0x10_0x1d[0]*256+dev->sensor.regs_0x10_0x1d[1]; if(exp==0) { exp=sensor->expr; } sanei_genesys_set_triple(regs,REG_EXPR,exp); exp=dev->sensor.regs_0x10_0x1d[2]*256+dev->sensor.regs_0x10_0x1d[3]; if(exp==0) { exp=sensor->expg; } sanei_genesys_set_triple(regs,REG_EXPG,exp); exp=dev->sensor.regs_0x10_0x1d[4]*256+dev->sensor.regs_0x10_0x1d[5]; if(exp==0) { exp=sensor->expb; } sanei_genesys_set_triple(regs,REG_EXPB,exp); sanei_genesys_set_triple(regs,REG_CK1MAP,sensor->ck1map); sanei_genesys_set_triple(regs,REG_CK3MAP,sensor->ck3map); sanei_genesys_set_triple(regs,REG_CK4MAP,sensor->ck4map); /* order of the sub-segments */ dev->order=sensor->order; DBGCOMPLETED; } /** @brief setup optical related registers * start and pixels are expressed in optical sensor resolution coordinate * space. * @param dev scanner device to use * @param reg registers to set up * @param exposure_time exposure time to use * @param used_res scanning resolution used, may differ from * scan's one * @param start logical start pixel coordinate * @param pixels logical number of pixels to use * @param channels number of color channels (currently 1 or 3) * @param depth bit depth of the scan (1, 8 or 16) * @param half_ccd SANE_TRUE if sensor's timings are such that x coordinates * must be halved * @param color_filter color channel to use as gray data * @param flags optical flags (@see ) * @return SANE_STATUS_GOOD if OK */ static SANE_Status gl124_init_optical_regs_scan (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int exposure_time, int used_res, unsigned int start, unsigned int pixels, int channels, int depth, SANE_Bool half_ccd, int color_filter, int flags) { unsigned int words_per_line, segcnt; unsigned int startx, endx, used_pixels, segnb; unsigned int dpiset, cksel, dpihw, factor; unsigned int bytes; Genesys_Register_Set *r; SANE_Status status; uint32_t expmax, exp; DBG (DBG_proc, "%s : exposure_time=%d, " "used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, " "half_ccd=%d, flags=%x\n", __func__, exposure_time, used_res, start, pixels, channels, depth, half_ccd, flags); /* resolution is divided according to CKSEL */ r = sanei_genesys_get_address (reg, REG18); cksel= (r->value & REG18_CKSEL)+1; DBG (DBG_io2, "%s: cksel=%d\n", __func__, cksel); /* to manage high resolution device while keeping good * low resolution scanning speed, we make hardware dpi vary */ dpihw=sanei_genesys_compute_dpihw(dev, used_res * cksel); factor=dev->sensor.optical_res/dpihw; DBG (DBG_io2, "%s: dpihw=%d (factor=%d)\n", __func__, dpihw, factor); /* sensor parameters */ gl124_setup_sensor (dev, reg, dpihw, half_ccd); dpiset = used_res * cksel; /* start and end coordinate in optical dpi coordinates */ /* startx = start/cksel + dev->sensor.dummy_pixel; XXX STEF XXX */ startx = start/cksel; used_pixels=pixels/cksel; endx = startx + used_pixels; /* pixel coordinate factor correction when used dpihw is not maximal one */ startx/=factor; endx/=factor; used_pixels=endx-startx; status = gl124_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to set frontend: %s\n", __func__, sane_strstatus (status)); return status; } /* enable shading */ r = sanei_genesys_get_address (reg, REG01); r->value &= ~REG01_SCAN; if ((flags & OPTICAL_FLAG_DISABLE_SHADING) || (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) { r->value &= ~REG01_DVDSET; } else { r->value |= REG01_DVDSET; } r->value &= ~REG01_SCAN; r = sanei_genesys_get_address (reg, REG03); if((dev->model->ccd_type!=CIS_CANONLIDE120)&&(used_res>=600)) { r->value &= ~REG03_AVEENB; DBG (DBG_io, "%s: disabling AVEENB\n", __func__); } else { r->value |= ~REG03_AVEENB; DBG (DBG_io, "%s: enabling AVEENB\n", __func__); } if (flags & OPTICAL_FLAG_DISABLE_LAMP) r->value &= ~REG03_LAMPPWR; else r->value |= REG03_LAMPPWR; /* BW threshold */ RIE (sanei_genesys_write_register (dev, REG114, dev->settings.threshold)); RIE (sanei_genesys_write_register (dev, REG115, dev->settings.threshold)); /* monochrome / color scan */ r = sanei_genesys_get_address (reg, REG04); switch (depth) { case 1: r->value &= ~REG04_BITSET; r->value |= REG04_LINEART; break; case 8: r->value &= ~(REG04_LINEART | REG04_BITSET); break; case 16: r->value &= ~REG04_LINEART; r->value |= REG04_BITSET; break; } r->value &= ~REG04_FILTER; if (channels == 1) { switch (color_filter) { case 0: r->value |= 0x10; /* red filter */ break; case 2: r->value |= 0x30; /* blue filter */ break; default: r->value |= 0x20; /* green filter */ break; } } /* register 05 */ r = sanei_genesys_get_address (reg, REG05); /* set up dpihw */ r->value &= ~REG05_DPIHW; switch(dpihw) { case 600: r->value |= REG05_DPIHW_600; break; case 1200: r->value |= REG05_DPIHW_1200; break; case 2400: r->value |= REG05_DPIHW_2400; break; case 4800: r->value |= REG05_DPIHW_4800; break; } /* enable gamma tables */ if (flags & OPTICAL_FLAG_DISABLE_GAMMA) r->value &= ~REG05_GMMENB; else r->value |= REG05_GMMENB; if(half_ccd) { sanei_genesys_set_double(reg,REG_DPISET,dpiset*2); DBG (DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset*2); } else { sanei_genesys_set_double(reg,REG_DPISET,dpiset); DBG (DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset); } r = sanei_genesys_get_address (reg, REG06); r->value |= REG06_GAIN4; /* CIS scanners can do true gray by setting LEDADD */ /* we set up LEDADD only when asked */ if (dev->model->is_cis == SANE_TRUE) { r = sanei_genesys_get_address (reg, REG60); r->value &= ~REG60_LEDADD; if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) { r->value |= REG60_LEDADD; sanei_genesys_get_triple(reg,REG_EXPR,&expmax); sanei_genesys_get_triple(reg,REG_EXPG,&exp); if(exp>expmax) { expmax=exp; } sanei_genesys_get_triple(reg,REG_EXPB,&exp); if(exp>expmax) { expmax=exp; } sanei_genesys_set_triple(dev->reg,REG_EXPR,expmax); sanei_genesys_set_triple(dev->reg,REG_EXPG,expmax); sanei_genesys_set_triple(dev->reg,REG_EXPB,expmax); } /* RGB weighting, REG_TRUER,G and B are to be set */ r = sanei_genesys_get_address (reg, 0x01); r->value &= ~REG01_TRUEGRAY; if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) { r->value |= REG01_TRUEGRAY; sanei_genesys_write_register (dev, REG_TRUER, 0x80); sanei_genesys_write_register (dev, REG_TRUEG, 0x80); sanei_genesys_write_register (dev, REG_TRUEB, 0x80); } } /* segment number */ r = sanei_genesys_get_address (reg, 0x98); segnb = r->value & 0x0f; sanei_genesys_set_triple(reg,REG_STRPIXEL,startx/segnb); DBG (DBG_io2, "%s: strpixel used=%d\n", __func__, startx/segnb); sanei_genesys_get_triple(reg,REG_SEGCNT,&segcnt); if(endx/segnb==segcnt) { endx=0; } sanei_genesys_set_triple(reg,REG_ENDPIXEL,endx/segnb); DBG (DBG_io2, "%s: endpixel used=%d\n", __func__, endx/segnb); /* words(16bit) before gamma, conversion to 8 bit or lineart */ words_per_line = (used_pixels * dpiset) / dpihw; bytes = depth / 8; if (depth == 1) { words_per_line = (words_per_line >> 3) + ((words_per_line & 7) ? 1 : 0); } else { words_per_line *= bytes; } dev->bpl = words_per_line; dev->cur = 0; dev->skip = 0; dev->len = dev->bpl/segnb; dev->dist = dev->bpl/segnb; dev->segnb = segnb; dev->line_count = 0; dev->line_interp = 0; DBG (DBG_io2, "%s: used_pixels =%d\n", __func__, used_pixels); DBG (DBG_io2, "%s: pixels =%d\n", __func__, pixels); DBG (DBG_io2, "%s: depth =%d\n", __func__, depth); DBG (DBG_io2, "%s: dev->bpl =%lu\n", __func__, (unsigned long)dev->bpl); DBG (DBG_io2, "%s: dev->len =%lu\n", __func__, (unsigned long)dev->len); DBG (DBG_io2, "%s: dev->dist =%lu\n", __func__, (unsigned long)dev->dist); DBG (DBG_io2, "%s: dev->line_interp=%lu\n", __func__, (unsigned long)dev->line_interp); words_per_line *= channels; dev->wpl = words_per_line; /* allocate buffer for odd/even pixels handling */ if(dev->oe_buffer.buffer!=NULL) { sanei_genesys_buffer_free (&(dev->oe_buffer)); } RIE (sanei_genesys_buffer_alloc (&(dev->oe_buffer), dev->wpl)); /* MAXWD is expressed in 2 words unit */ sanei_genesys_set_triple(reg,REG_MAXWD,(words_per_line)); DBG (DBG_io2, "%s: words_per_line used=%d\n", __func__, words_per_line); sanei_genesys_set_triple(reg,REG_LPERIOD,exposure_time); DBG (DBG_io2, "%s: exposure_time used=%d\n", __func__, exposure_time); sanei_genesys_set_double(reg,REG_DUMMY,dev->sensor.dummy_pixel); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** set up registers for an actual scan * * this function sets up the scanner to scan in normal or single line mode */ GENESYS_STATIC SANE_Status gl124_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ float yres, /*dpi */ float startx, /*optical_res, from dummy_pixel+1 */ float starty, /*base_ydpi, from home! */ float pixels, float lines, unsigned int depth, unsigned int channels, __sane_unused__ int scan_method, int scan_mode, int color_filter, unsigned int flags) { int used_res; int start, used_pixels; int bytes_per_line; int move; unsigned int lincnt; unsigned int oflags, mflags; /**> optical and motor flags */ int exposure_time; int stagger; int dummy = 0; int slope_dpi = 0; int scan_step_type = 1; int max_shift; size_t requested_buffer_size, read_buffer_size; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; SANE_Status status; DBG (DBG_info, "gl124_init_scan_regs settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g/%g\n" "Depth/Channels: %u/%u\n" "Flags : %x\n\n", xres, yres, lines, pixels, startx, starty, depth, channels, flags); half_ccd=compute_half_ccd(dev->model, xres); /* optical_res */ optical_res = dev->sensor.optical_res; if (half_ccd) optical_res /= 2; DBG (DBG_info, "%s: optical_res=%d\n", __func__, optical_res); /* stagger */ if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "gl124_init_scan_regs : stagger=%d lines\n", stagger); /** @brief compute used resolution */ if (flags & SCAN_FLAG_USE_OPTICAL_RES) { used_res = optical_res; } else { /* resolution is choosen from a fixed list and can be used directly, * unless we have ydpi higher than sensor's maximum one */ if(xres>optical_res) used_res=optical_res; else used_res = xres; } /* compute scan parameters values */ /* pixels are allways given at full optical resolution */ /* use detected left margin and fixed value */ /* start */ /* add x coordinates */ start = startx; if (stagger > 0) start |= 1; /* compute correct pixels number */ used_pixels = (pixels * optical_res) / xres; DBG (DBG_info, "%s: used_pixels=%d\n", __func__, used_pixels); /* round up pixels number if needed */ if (used_pixels * xres < pixels * optical_res) used_pixels++; /* we want even number of pixels here */ if(used_pixels & 1) used_pixels++; /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ if (dev->model->is_cis) slope_dpi = yres * channels; else slope_dpi = yres; /* scan_step_type */ if(flags & SCAN_FLAG_FEEDING) { scan_step_type=0; exposure_time=MOVE_EXPOSURE; } else { exposure_time = gl124_compute_exposure (dev, used_res, half_ccd); scan_step_type = sanei_genesys_compute_step_type(motors, dev->model->motor_type, exposure_time); } DBG (DBG_info, "gl124_init_scan_regs : exposure_time=%d pixels\n", exposure_time); DBG (DBG_info, "gl124_init_scan_regs : scan_step_type=%d\n", scan_step_type); /*** optical parameters ***/ /* in case of dynamic lineart, we use an internal 8 bit gray scan * to generate 1 lineart data */ if ((flags & SCAN_FLAG_DYNAMIC_LINEART) && (scan_mode == SCAN_MODE_LINEART)) { depth = 8; } /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ oflags = 0; if (flags & SCAN_FLAG_DISABLE_SHADING) oflags |= OPTICAL_FLAG_DISABLE_SHADING; if (flags & SCAN_FLAG_DISABLE_GAMMA) oflags |= OPTICAL_FLAG_DISABLE_GAMMA; if (flags & SCAN_FLAG_DISABLE_LAMP) oflags |= OPTICAL_FLAG_DISABLE_LAMP; if (flags & SCAN_FLAG_CALIBRATION) oflags |= OPTICAL_FLAG_DISABLE_DOUBLE; if (dev->model->is_cis && dev->settings.true_gray) { oflags |= OPTICAL_FLAG_ENABLE_LEDADD; } /* now _LOGICAL_ optical values used are known, setup registers */ status = gl124_init_optical_regs_scan (dev, reg, exposure_time, used_res, start, used_pixels, channels, depth, half_ccd, color_filter, oflags); if (status != SANE_STATUS_GOOD) return status; /*** motor parameters ***/ /* max_shift */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,flags); /* lines to scan */ lincnt = lines + max_shift + stagger; /* add tl_y to base movement */ move = starty; DBG (DBG_info, "gl124_init_scan_regs: move=%d steps\n", move); mflags=0; if(flags & SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE) mflags|=MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE; if(flags & SCAN_FLAG_FEEDING) mflags|=MOTOR_FLAG_FEED; status = gl124_init_motor_regs_scan (dev, reg, exposure_time, slope_dpi, scan_step_type, dev->model->is_cis ? lincnt * channels : lincnt, dummy, move, scan_mode, mflags); if (status != SANE_STATUS_GOOD) return status; /*** prepares data reordering ***/ /* words_per_line */ bytes_per_line = (used_pixels * used_res) / optical_res; bytes_per_line = (bytes_per_line * channels * depth) / 8; /* since we don't have sheetfed scanners to handle, * use huge read buffer */ /* TODO find the best size according to settings */ requested_buffer_size = 16 * bytes_per_line; read_buffer_size = 2 * requested_buffer_size + ((max_shift + stagger) * used_pixels * channels * depth) / 8; RIE (sanei_genesys_buffer_free (&(dev->read_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->lines_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer), requested_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->out_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer), (8 * dev->settings.pixels * channels * depth) / 8)); dev->read_bytes_left = bytes_per_line * lincnt; DBG (DBG_info, "gl124_init_scan_regs: physical bytes to read = %lu\n", (u_long) dev->read_bytes_left); dev->read_active = SANE_TRUE; dev->current_setup.pixels = (used_pixels * used_res) / optical_res; DBG (DBG_info, "%s: current_setup.pixels=%d\n", __func__, dev->current_setup.pixels); dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure_time; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; dev->total_bytes_read = 0; if (depth == 1) dev->total_bytes_to_read = ((dev->settings.pixels * dev->settings.lines) / 8 + (((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) * channels; else dev->total_bytes_to_read = dev->settings.pixels * dev->settings.lines * channels * (depth / 8); DBG (DBG_info, "gl124_init_scan_regs: total bytes to send = %lu\n", (u_long) dev->total_bytes_to_read); DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl124_calculate_current_setup (Genesys_Device * dev) { int channels; int depth; int start; float xres; /*dpi */ float yres; /*dpi */ float startx; /*optical_res, from dummy_pixel+1 */ float pixels; float lines; int used_res; int used_pixels; unsigned int lincnt; int exposure_time; int stagger; SANE_Bool half_ccd; int max_shift, dpihw; Sensor_Profile *sensor; int optical_res; DBG (DBG_info, "gl124_calculate_current_setup settings:\n" "Resolution: %ux%uDPI\n" "Lines : %u\n" "PPL : %u\n" "Startpos : %.3f/%.3f\n" "Scan mode : %d\n\n", dev->settings.xres, dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* channels */ if (dev->settings.scan_mode == 4) /* single pass color */ channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == 0) depth = 1; /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; xres = dev->settings.xres; yres = dev->settings.yres; startx = start; pixels = dev->settings.pixels; lines = dev->settings.lines; half_ccd=compute_half_ccd(dev->model, xres); DBG (DBG_info, "gl124_calculate_current_setup settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g\n" "Half ccd : %d\n" "Depth/Channels: %u/%u\n\n", xres, yres, lines, pixels, startx, depth, half_ccd, channels); /* optical_res */ optical_res = dev->sensor.optical_res; if(xres<=optical_res) used_res = xres; else used_res=optical_res; /* compute scan parameters values */ /* pixels are allways given at half or full CCD optical resolution */ /* use detected left margin and fixed value */ /* compute correct pixels number */ used_pixels = (pixels * optical_res) / xres; DBG (DBG_info, "%s: used_pixels=%d\n", __func__, used_pixels); /* exposure */ exposure_time = gl124_compute_exposure (dev, xres, half_ccd); DBG (DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time); /* max_shift */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0); /* compute hw dpi for sensor */ dpihw=sanei_genesys_compute_dpihw(dev,used_res); sensor=get_sensor_profile(dev->model->ccd_type, dpihw, half_ccd); dev->segnb=sensor->reg98 & 0x0f; /* stagger */ if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "%s: stagger=%d lines\n", __func__, stagger); /* lincnt */ lincnt = lines + max_shift + stagger; dev->current_setup.pixels = (used_pixels * used_res) / optical_res; DBG (DBG_info, "%s: current_setup.pixels=%d\n", __func__, dev->current_setup.pixels); dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure_time; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; DBGCOMPLETED; return SANE_STATUS_GOOD; } static void gl124_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set) { DBG (DBG_proc, "gl124_set_motor_power\n"); if (set) { sanei_genesys_set_reg_from_set (regs, REG02, sanei_genesys_read_reg_from_set (regs, REG02) | REG02_MTRPWR); } else { sanei_genesys_set_reg_from_set (regs, REG02, sanei_genesys_read_reg_from_set (regs, REG02) & ~REG02_MTRPWR); } } static void gl124_set_lamp_power (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool set) { if (dev == NULL || regs==NULL) return; if (set) { sanei_genesys_set_reg_from_set (regs, 0x03, sanei_genesys_read_reg_from_set (regs, 0x03) | REG03_LAMPPWR); } else { sanei_genesys_set_reg_from_set (regs, 0x03, sanei_genesys_read_reg_from_set (regs, 0x03) & ~REG03_LAMPPWR); } } /** * for fast power saving methods only, like disabling certain amplifiers * @param dev device to use * @param enable true to set inot powersaving * */ static SANE_Status gl124_save_power (Genesys_Device * dev, SANE_Bool enable) { DBG (DBG_proc, "gl124_save_power: enable = %d\n", enable); if (dev == NULL) return SANE_STATUS_INVAL; DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl124_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ ) { Genesys_Register_Set *r; DBG (DBG_proc, "gl124_set_powersaving (delay = %d)\n", delay); r = sanei_genesys_get_address (dev->reg, REG03); r->value &= ~0xf0; if(delay<15) { r->value |= delay; } else { r->value |= 0x0f; } DBGCOMPLETED; return SANE_STATUS_GOOD; } #ifndef UNIT_TESTING static #endif SANE_Status gl124_start_action (Genesys_Device * dev) { return sanei_genesys_write_register (dev, 0x0f, 0x01); } #ifndef UNIT_TESTING static #endif SANE_Status gl124_stop_action (Genesys_Device * dev) { SANE_Status status; uint8_t val40, val; unsigned int loop; DBGSTART; /* post scan gpio : without that HOMSNR is unreliable */ gl124_homsnr_gpio(dev); status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } status = sanei_genesys_read_register (dev, REG100, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read reg100: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* only stop action if needed */ if (!(val40 & REG100_DATAENB) && !(val40 & REG100_MOTMFLG)) { DBG (DBG_info, "%s: already stopped\n", __func__); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* ends scan */ val = sanei_genesys_read_reg_from_set (dev->reg, REG01); val &= ~REG01_SCAN; sanei_genesys_set_reg_from_set (dev->reg, REG01, val); status = sanei_genesys_write_register (dev, REG01, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write register 01: %s\n", __func__, sane_strstatus (status)); return status; } usleep (100 * 1000); loop = 10; while (loop > 0) { status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } status = sanei_genesys_read_register (dev, REG100, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* if scanner is in command mode, we are done */ if (!(val40 & REG100_DATAENB) && !(val40 & REG100_MOTMFLG) && !(val & MOTORENB)) { DBGCOMPLETED; return SANE_STATUS_GOOD; } usleep (100 * 1000); loop--; } DBGCOMPLETED; return SANE_STATUS_IO_ERROR; } /** @brief setup GPIOs for scan * Setup GPIO values to drive motor (or light) needed for the * target resolution * @param *dev device to set up * @param resolution dpi of the target scan * @return SANE_STATUS_GOOD unless REG32 cannot be read */ static SANE_Status gl124_setup_scan_gpio(Genesys_Device *dev, int resolution) { SANE_Status status; uint8_t val; DBGSTART; RIE (sanei_genesys_read_register (dev, REG32, &val)); /* LiDE 110, 210 and 220 cases */ if(dev->model->gpo_type != GPO_CANONLIDE120) { if(resolution>=dev->motor.base_ydpi/2) { val &= 0xf7; } else if(resolution>=dev->motor.base_ydpi/4) { val &= 0xef; } else { val |= 0x10; } } /* 120 : <=300 => 0x53 */ else { /* base_ydpi is 4800 */ if(resolution<=300) { val &= 0xf7; } else if(resolution<=600) { val |= 0x08; } else if(resolution<=1200) { val &= 0xef; val |= 0x08; } else { val &= 0xf7; } } val |= 0x02; RIE (sanei_genesys_write_register (dev, REG32, val)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* Send the low-level scan command */ /* todo : is this that useful ? */ #ifndef UNIT_TESTING static #endif SANE_Status gl124_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor) { SANE_Status status; uint8_t val; DBGSTART; if (reg == NULL) return SANE_STATUS_INVAL; /* set up GPIO for scan */ RIE(gl124_setup_scan_gpio(dev,dev->settings.yres)); /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); /* enable scan and motor */ RIE (sanei_genesys_read_register (dev, REG01, &val)); val |= REG01_SCAN; RIE (sanei_genesys_write_register (dev, REG01, val)); if (start_motor) { RIE (sanei_genesys_write_register (dev, REG0F, 1)); } else { RIE (sanei_genesys_write_register (dev, REG0F, 0)); } DBGCOMPLETED; return status; } /* Send the stop scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl124_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop) { SANE_Status status; DBG (DBG_proc, "gl124_end_scan (check_stop = %d)\n", check_stop); if (reg == NULL) return SANE_STATUS_INVAL; if (dev->model->is_sheetfed == SANE_TRUE) { status = SANE_STATUS_GOOD; } else /* flat bed scanners */ { status = gl124_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_end_scan: failed to stop: %s\n", sane_strstatus (status)); return status; } } DBGCOMPLETED; return status; } /** rewind scan * Move back by the same amount of distance than previous scan. * @param dev device to rewind * @returns SANE_STATUS_GOOD on success */ GENESYS_STATIC SANE_Status gl124_rewind(Genesys_Device * dev) { SANE_Status status; uint8_t byte; DBGSTART; /* set motor reverse */ RIE (sanei_genesys_read_register (dev, 0x02, &byte)); byte |= 0x04; RIE (sanei_genesys_write_register(dev, 0x02, byte)); /* and start scan, then wait completion */ RIE (gl124_begin_scan (dev, dev->reg, SANE_TRUE)); do { usleep(100*1000); RIE (sanei_genesys_read_register (dev, REG100, &byte)); } while(byte & REG100_MOTMFLG); RIE (gl124_end_scan (dev, dev->reg, SANE_TRUE)); /* restore direction */ RIE (sanei_genesys_read_register (dev, 0x02, &byte)); byte &= 0xfb; RIE (sanei_genesys_write_register(dev, 0x02, byte)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** Park head * Moves the slider to the home (top) position slowly * @param dev device to park * @param wait_until_home true to make the function waiting for head * to be home before returning, if fals returne immediately * @returns SANE_STATUS_GOO on success */ GENESYS_STATIC SANE_Status gl124_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) { Genesys_Register_Set local_reg[GENESYS_GL124_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; uint8_t val; float resolution; int loop = 0; DBG (DBG_proc, "gl124_slow_back_home (wait_until_home = %d)\n", wait_until_home); if(dev->usb_mode<0) { DBGCOMPLETED; return SANE_STATUS_GOOD; } /* post scan gpio : without that HOMSNR is unreliable */ gl124_homsnr_gpio(dev); /* first read gives HOME_SENSOR true */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } usleep (100000); /* sleep 100 ms */ /* second is reliable */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } /* is sensor at home? */ if (val & HOMESNR) { DBG (DBG_info, "%s: already at home, completed\n", __func__); dev->scanhead_position_in_steps = 0; DBGCOMPLETED; return SANE_STATUS_GOOD; } /* feed a little first */ if (strcmp (dev->model->name, "canon-lide-210") == 0) { status = gl124_feed (dev, 20, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to do initial feed: %s\n", __func__, sane_strstatus (status)); return status; } } memcpy (local_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_dpi(dev); status = gl124_init_scan_regs (dev, local_reg, resolution, resolution, 100, 30000, 100, 100, 8, 1, dev->settings.scan_method, SCAN_MODE_GRAY, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_slow_back_home: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); /* set up for reverse and no scan */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL124_MAX_REGS)); RIE(gl124_setup_scan_gpio(dev,resolution)); status = gl124_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_slow_back_home: failed to start motor: %s\n", sane_strstatus (status)); gl124_stop_action (dev); /* restore original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL124_MAX_REGS); return status; } /* post scan gpio : without that HOMSNR is unreliable */ gl124_homsnr_gpio(dev); if (wait_until_home) { while (loop < 300) /* do not wait longer then 30 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (val & HOMESNR) /* home sensor */ { DBG (DBG_info, "gl124_slow_back_home: reached home position\n"); DBGCOMPLETED; dev->scanhead_position_in_steps = 0; return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ ++loop; } /* when we come here then the scanner needed too much time for this, so we better stop the motor */ gl124_stop_action (dev); DBG (DBG_error, "gl124_slow_back_home: timeout while waiting for scanhead to go home\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_info, "gl124_slow_back_home: scanhead is still moving\n"); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief moves the slider to steps at motor base dpi * @param dev device to work on * @param steps number of steps to move * @param reverse true is moving backward * */ #ifndef UNIT_TESTING static #endif SANE_Status gl124_feed (Genesys_Device * dev, unsigned int steps, int reverse) { Genesys_Register_Set local_reg[GENESYS_GL124_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; float resolution; uint8_t val; DBGSTART; DBG (DBG_io, "%s: steps=%d\n", __func__, steps); /* prepare local registers */ memcpy (local_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); status = gl124_init_scan_regs (dev, local_reg, resolution, resolution, 0, steps, 100, 3, 8, 3, dev->settings.scan_method, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_FEEDING | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to set up registers: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* set exposure to zero */ sanei_genesys_set_triple(local_reg,REG_EXPR,0); sanei_genesys_set_triple(local_reg,REG_EXPG,0); sanei_genesys_set_triple(local_reg,REG_EXPB,0); /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT)); RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT)); /* set up for no scan */ r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; /* set up for reverse if needed */ if(reverse) { r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; } /* send registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL124_MAX_REGS)); status = gl124_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to start motor: %s\n", __func__, sane_strstatus (status)); gl124_stop_action (dev); /* restore original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL124_MAX_REGS); return status; } /* wait until feed count reaches the required value, but do not * exceed 30s */ do { status = sanei_genesys_get_status (dev, &val); } while (status == SANE_STATUS_GOOD && !(val & FEEDFSH)); /* then stop scanning */ RIE(gl124_stop_action (dev)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi from very top of scanner */ static SANE_Status gl124_search_start_position (Genesys_Device * dev) { int size; SANE_Status status; uint8_t *data; Genesys_Register_Set local_reg[GENESYS_GL124_MAX_REGS]; int steps; int pixels = 600; int dpi = 300; DBGSTART; memcpy (local_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); /* sets for a 200 lines * 600 pixels */ /* normal scan with no shading */ status = gl124_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, /*we should give a small offset here~60 steps */ 600, dev->model->search_lines, 8, 1, dev->settings.scan_method, SCAN_MODE_GRAY, 1, /*green */ SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE); if (status!=SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to init scan registers: %s\n", __func__, sane_strstatus (status)); return status; } /* send to scanner */ status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL124_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_search_start_position: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } size = pixels * dev->model->search_lines; data = malloc (size); if (!data) { DBG (DBG_error, "gl124_search_start_position: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } status = gl124_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl124_search_start_position: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl124_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, pixels, dev->model->search_lines); status = gl124_end_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl124_search_start_position: failed to end scan: %s\n", sane_strstatus (status)); return status; } /* update regs to copy ASIC internal state */ memcpy (dev->reg, local_reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); status = sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels, dev->model->search_lines); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl124_search_start_position: failed to set search reference point: %s\n", sane_strstatus (status)); return status; } free (data); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status gl124_init_regs_for_coarse_calibration (Genesys_Device * dev) { SANE_Status status; uint8_t channels; uint8_t cksel; DBGSTART; cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */ /* set line size */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; status = gl124_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, dev->sensor.optical_res / cksel, 20, 16, channels, dev->settings.scan_method, dev->settings.scan_mode, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_FEEDING | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_init_register_for_coarse_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } gl124_set_motor_power (dev->calib_reg, SANE_FALSE); DBG (DBG_info, "gl124_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n", dev->sensor.optical_res / cksel, dev->settings.xres); status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL124_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_init_register_for_coarse_calibration: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /* init registers for shading calibration */ /* shading calibration is done at dpihw */ static SANE_Status gl124_init_regs_for_shading (Genesys_Device * dev) { SANE_Status status; int move, resolution, dpihw, factor; DBGSTART; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); dev->calib_channels = 3; dev->calib_lines = dev->model->shading_lines; dpihw=sanei_genesys_compute_dpihw(dev,dev->settings.xres); if(dpihw>=2400) { dev->calib_lines *= 2; } resolution=dpihw; /* if half CCD mode, use half resolution */ if(compute_half_ccd(dev->model, dev->settings.xres)==SANE_TRUE) { resolution /= 2; dev->calib_lines /= 2; } dev->calib_resolution = resolution; factor=dev->sensor.optical_res/resolution; dev->calib_pixels = dev->sensor.sensor_pixels/factor; /* distance to move to reach white target at high resolution */ move=0; if(dev->settings.yres>=1200) { move = SANE_UNFIX (dev->model->y_offset_calib); move = (move * (dev->motor.base_ydpi/4)) / MM_PER_INCH; } DBG (DBG_io, "%s: move=%d steps\n", __func__, move); status = gl124_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, move, dev->calib_pixels, dev->calib_lines, 16, dev->calib_channels, dev->settings.scan_method, SCAN_MODE_COLOR, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | SCAN_FLAG_IGNORE_LINE_DISTANCE); gl124_set_motor_power (dev->calib_reg, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } dev->scanhead_position_in_steps += dev->calib_lines + move; status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL124_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __func__, sane_strstatus (status)); return status; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief set up registers for the actual scan */ static SANE_Status gl124_init_regs_for_scan (Genesys_Device * dev) { int channels; int flags; int depth; float move; int move_dpi; float start; uint8_t val40,val; SANE_Status status; DBG (DBG_info, "gl124_init_regs_for_scan settings:\nResolution: %ux%uDPI\n" "Lines : %u\npixels : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n", dev->settings.xres, dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* wait for motor to stop first */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read status: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } status = sanei_genesys_read_register (dev, REG100, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read reg100: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } if((val & MOTORENB) || (val40 & REG100_MOTMFLG)) { do { usleep(10000); status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read status: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } status = sanei_genesys_read_register (dev, REG100, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read reg100: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } } while ((val & MOTORENB) || (val40 & REG100_MOTMFLG)); usleep(50000); } /* ensure head is parked in case of calibration */ RIE (gl124_slow_back_home (dev, SANE_TRUE)); /* channels */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == SCAN_MODE_LINEART) depth = 1; /* y (motor) distance to move to reach scanned area */ move_dpi = dev->motor.base_ydpi/4; move = SANE_UNFIX (dev->model->y_offset); move += dev->settings.tl_y; move = (move * move_dpi) / MM_PER_INCH; DBG (DBG_info, "%s: move=%f steps\n", __func__, move); if(channels*dev->settings.yres>=600 && move>700) { status = gl124_feed (dev, move-500, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to move to scan area\n",__func__); return status; } move=500; } DBG (DBG_info, "gl124_init_regs_for_scan: move=%f steps\n", move); /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; if(compute_half_ccd(dev->model, dev->settings.xres)==SANE_TRUE) { start /=2; } start = (start * dev->sensor.optical_res) / MM_PER_INCH; flags = 0; /* enable emulated lineart from gray data */ if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; } status = gl124_init_scan_regs (dev, dev->reg, dev->settings.xres, dev->settings.yres, start, move, dev->settings.pixels, dev->settings.lines, depth, channels, dev->settings.scan_method, dev->settings.scan_mode, dev->settings.color_filter, flags); if (status != SANE_STATUS_GOOD) return status; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * Send shading calibration data. The buffer is considered to always hold values * for all the channels. */ #ifndef UNIT_TESTING static #endif SANE_Status gl124_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) { SANE_Status status = SANE_STATUS_GOOD; uint32_t addr, length, strpixel ,endpixel, x, factor, segcnt, pixels, i; uint32_t lines, channels; uint16_t dpiset,dpihw; uint8_t val,*buffer,*ptr,*src; DBGSTART; DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__func__,size); /* logical size of a color as seen by generic code of the frontend */ length = (uint32_t) (size / 3); sanei_genesys_get_triple(dev->reg,REG_STRPIXEL,&strpixel); sanei_genesys_get_triple(dev->reg,REG_ENDPIXEL,&endpixel); sanei_genesys_get_triple(dev->reg,REG_SEGCNT,&segcnt); if(endpixel==0) { endpixel=segcnt; } DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d, PIXELS=%d, SEGCNT=%d\n",__func__,strpixel,endpixel,endpixel-strpixel,segcnt); /* compute deletion factor */ sanei_genesys_get_double(dev->reg,REG_DPISET,&dpiset); dpihw=sanei_genesys_compute_dpihw(dev,dpiset); factor=dpihw/dpiset; DBG( DBG_io2, "%s: factor=%d\n",__func__,factor); /* binary data logging */ if(DBG_LEVEL>=DBG_data) { dev->binary=fopen("binary.pnm","wb"); sanei_genesys_get_triple(dev->reg, REG_LINCNT, &lines); channels=dev->current_setup.channels; if(dev->binary!=NULL) { fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels*dev->segnb,lines/channels,255); } } /* turn pixel value into bytes 2x16 bits words */ strpixel*=2*2; /* 2 words of 2 bytes */ endpixel*=2*2; segcnt*=2*2; pixels=endpixel-strpixel; DBG( DBG_io2, "%s: using chunks of %d bytes (%d shading data pixels)\n",__func__,length, length/4); buffer=(uint8_t *)malloc(pixels*dev->segnb); memset(buffer,0,pixels*dev->segnb); /* write actual red data */ for(i=0;i<3;i++) { /* copy data to work buffer and process it */ /* coefficent destination */ ptr=buffer; /* iterate on both sensor segment */ for(x=0;xsegnb) { case 1: ptr[0+pixels*0]=src[0+segcnt*0]; ptr[1+pixels*0]=src[1+segcnt*0]; ptr[2+pixels*0]=src[2+segcnt*0]; ptr[3+pixels*0]=src[3+segcnt*0]; break; case 2: ptr[0+pixels*0]=src[0+segcnt*0]; ptr[1+pixels*0]=src[1+segcnt*0]; ptr[2+pixels*0]=src[2+segcnt*0]; ptr[3+pixels*0]=src[3+segcnt*0]; ptr[0+pixels*1]=src[0+segcnt*1]; ptr[1+pixels*1]=src[1+segcnt*1]; ptr[2+pixels*1]=src[2+segcnt*1]; ptr[3+pixels*1]=src[3+segcnt*1]; break; case 4: ptr[0+pixels*0]=src[0+segcnt*0]; ptr[1+pixels*0]=src[1+segcnt*0]; ptr[2+pixels*0]=src[2+segcnt*0]; ptr[3+pixels*0]=src[3+segcnt*0]; ptr[0+pixels*1]=src[0+segcnt*2]; ptr[1+pixels*1]=src[1+segcnt*2]; ptr[2+pixels*1]=src[2+segcnt*2]; ptr[3+pixels*1]=src[3+segcnt*2]; ptr[0+pixels*2]=src[0+segcnt*1]; ptr[1+pixels*2]=src[1+segcnt*1]; ptr[2+pixels*2]=src[2+segcnt*1]; ptr[3+pixels*2]=src[3+segcnt*1]; ptr[0+pixels*3]=src[0+segcnt*3]; ptr[1+pixels*3]=src[1+segcnt*3]; ptr[2+pixels*3]=src[2+segcnt*3]; ptr[3+pixels*3]=src[3+segcnt*3]; break; } /* next shading coefficient */ ptr+=4; } RIE (sanei_genesys_read_register (dev, 0xd0+i, &val)); addr = val * 8192 + 0x10000000; status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, addr, pixels*dev->segnb, buffer); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_send_shading_data; write to AHB failed (%s)\n", sane_strstatus (status)); return status; } } free(buffer); DBGCOMPLETED; return status; } /** @brief move to calibration area * This functions moves scanning head to calibration area * by doing a 600 dpi scan * @param dev scanner device * @return SANE_STATUS_GOOD on success, else the error code */ static SANE_Status move_to_calibration_area (Genesys_Device * dev) { int pixels; int size; uint8_t *line; SANE_Status status = SANE_STATUS_GOOD; DBGSTART; pixels = (dev->sensor.sensor_pixels*600)/dev->sensor.optical_res; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); /* set up for the calibration scan */ status = gl124_init_scan_regs (dev, dev->calib_reg, 600, 600, 0, 0, pixels, 1, 8, 3, dev->settings.scan_method, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } size = pixels * 3; line = malloc (size); if (!line) return SANE_STATUS_NO_MEM; /* write registers and scan data */ RIEF (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL124_MAX_REGS), line); DBG (DBG_info, "%s: starting line reading\n", __func__); RIEF (gl124_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, size), line); /* stop scanning */ RIE (gl124_stop_action (dev)); if (DBG_LEVEL >= DBG_data) { sanei_genesys_write_pnm_file ("movetocalarea.pnm", line, 8, 3, pixels, 1); } /* cleanup before return */ free (line); DBGCOMPLETED; return status; } /* this function does the led calibration by scanning one line of the calibration area below scanner's top on white strip. -needs working coarse/gain */ static SANE_Status gl124_led_calibration (Genesys_Device * dev) { int num_pixels; int total_size; int resolution; int dpihw; uint8_t *line; int i, j; SANE_Status status = SANE_STATUS_GOOD; int val; int channels, depth; int avg[3]; int turn; char fn[20]; uint16_t exp[3],target; Sensor_Profile *sensor; SANE_Bool acceptable; SANE_Bool half_ccd; DBGSTART; /* move to calibration area */ move_to_calibration_area(dev); /* offset calibration is always done in 16 bit depth color mode */ channels = 3; depth=16; dpihw=sanei_genesys_compute_dpihw(dev, dev->settings.xres); half_ccd=compute_half_ccd(dev->model, dev->settings.xres); if(half_ccd==SANE_TRUE) { resolution = dpihw/2; } else { resolution = dpihw; } sensor=get_sensor_profile(dev->model->ccd_type, dpihw, half_ccd); num_pixels = (dev->sensor.sensor_pixels*resolution)/dev->sensor.optical_res; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL124_MAX_REGS * sizeof (Genesys_Register_Set)); /* set up for the calibration scan */ status = gl124_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, num_pixels, 1, depth, channels, dev->settings.scan_method, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } total_size = num_pixels * channels * (depth/8) * 1; /* colors * bytes_per_color * scan lines */ line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; /* initial loop values and boundaries */ exp[0]=sensor->expr; exp[1]=sensor->expg; exp[2]=sensor->expb; target=dev->sensor.gain_white_ref*256; turn = 0; /* no move during led calibration */ gl124_set_motor_power (dev->calib_reg, SANE_FALSE); do { /* set up exposure */ sanei_genesys_set_triple(dev->calib_reg,REG_EXPR,exp[0]); sanei_genesys_set_triple(dev->calib_reg,REG_EXPG,exp[1]); sanei_genesys_set_triple(dev->calib_reg,REG_EXPB,exp[2]); /* write registers and scan data */ RIEF (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL124_MAX_REGS), line); DBG (DBG_info, "gl124_led_calibration: starting line reading\n"); RIEF (gl124_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); /* stop scanning */ RIEF (gl124_stop_action (dev), line); if (DBG_LEVEL >= DBG_data) { snprintf (fn, 20, "led_%02d.pnm", turn); sanei_genesys_write_pnm_file (fn, line, depth, channels, num_pixels, 1); } /* compute average */ for (j = 0; j < channels; j++) { avg[j] = 0; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * num_pixels + 1] * 256 + line[i * 2 + j * 2 * num_pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; avg[j] += val; } avg[j] /= num_pixels; } DBG (DBG_info, "gl124_led_calibration: average: %d,%d,%d\n", avg[0], avg[1], avg[2]); /* check if exposure gives average within the boundaries */ acceptable = SANE_TRUE; for(i=0;i<3;i++) { /* we accept +- 2% delta from target */ if(abs(avg[i]-target)>target/50) { exp[i]=(exp[i]*target)/avg[i]; acceptable = SANE_FALSE; } } turn++; } while (!acceptable && turn < 100); DBG (DBG_info, "gl124_led_calibration: acceptable exposure: %d,%d,%d\n", exp[0], exp[1], exp[2]); /* set these values as final ones for scan */ sanei_genesys_set_triple(dev->reg,REG_EXPR,exp[0]); sanei_genesys_set_triple(dev->reg,REG_EXPG,exp[1]); sanei_genesys_set_triple(dev->reg,REG_EXPB,exp[2]); /* store in this struct since it is the one used by cache calibration */ dev->sensor.regs_0x10_0x1d[0] = (exp[0] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[1] = exp[0] & 0xff; dev->sensor.regs_0x10_0x1d[2] = (exp[1] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[3] = exp[1] & 0xff; dev->sensor.regs_0x10_0x1d[4] = (exp[2] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[5] = exp[2] & 0xff; /* cleanup before return */ free (line); DBGCOMPLETED; return status; } /** * average dark pixels of a 8 bits scan */ static int dark_average (uint8_t * data, unsigned int pixels, unsigned int lines, unsigned int channels, unsigned int black) { unsigned int i, j, k, average, count; unsigned int avg[3]; uint8_t val; /* computes average value on black margin */ for (k = 0; k < channels; k++) { avg[k] = 0; count = 0; for (i = 0; i < lines; i++) { for (j = 0; j < black; j++) { val = data[i * channels * pixels + j + k]; avg[k] += val; count++; } } if (count) avg[k] /= count; DBG (DBG_info, "dark_average: avg[%d] = %d\n", k, avg[k]); } average = 0; for (i = 0; i < channels; i++) average += avg[i]; average /= channels; DBG (DBG_info, "dark_average: average = %d\n", average); return average; } static SANE_Status gl124_offset_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; uint8_t *first_line, *second_line, reg0a; unsigned int channels, bpp; char title[32]; int pass = 0, avg, total_size; int topavg, bottomavg, resolution, lines; int top, bottom, black_pixels, pixels; DBGSTART; /* no gain nor offset for TI AFE */ RIE (sanei_genesys_read_register (dev, REG0A, ®0a)); if(((reg0a & REG0A_SIFSEL)>>REG0AS_SIFSEL)==3) { DBGCOMPLETED; return status; } /* offset calibration is always done in color mode */ channels = 3; resolution=dev->sensor.optical_res; dev->calib_pixels = dev->sensor.sensor_pixels; lines=1; bpp=8; pixels= (dev->sensor.sensor_pixels*resolution) / dev->sensor.optical_res; black_pixels = (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res; DBG (DBG_io2, "gl124_offset_calibration: black_pixels=%d\n", black_pixels); status = gl124_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, pixels, lines, bpp, channels, dev->settings.scan_method, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_offset_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } gl124_set_motor_power (dev->calib_reg, SANE_FALSE); /* allocate memory for scans */ total_size = pixels * channels * lines * (bpp/8); /* colors * bytes_per_color * scan lines */ first_line = malloc (total_size); if (!first_line) return SANE_STATUS_NO_MEM; second_line = malloc (total_size); if (!second_line) { free (first_line); return SANE_STATUS_NO_MEM; } /* init gain */ dev->frontend.gain[0] = 0; dev->frontend.gain[1] = 0; dev->frontend.gain[2] = 0; /* scan with no move */ bottom = 10; dev->frontend.offset[0] = bottom; dev->frontend.offset[1] = bottom; dev->frontend.offset[2] = bottom; RIEF2 (gl124_set_fe(dev, AFE_SET), first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL124_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl124_offset_calibration: starting first line reading\n"); RIEF2 (gl124_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size), first_line, second_line); if (DBG_LEVEL >= DBG_data) { snprintf(title,20,"offset%03d.pnm",bottom); sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines); } bottomavg = dark_average (first_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl124_offset_calibration: bottom avg=%d\n", bottomavg); /* now top value */ top = 255; dev->frontend.offset[0] = top; dev->frontend.offset[1] = top; dev->frontend.offset[2] = top; RIEF2 (gl124_set_fe(dev, AFE_SET), first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL124_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl124_offset_calibration: starting second line reading\n"); RIEF2 (gl124_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); topavg = dark_average (second_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl124_offset_calibration: top avg=%d\n", topavg); /* loop until acceptable level */ while ((pass < 32) && (top - bottom > 1)) { pass++; /* settings for new scan */ dev->frontend.offset[0] = (top + bottom) / 2; dev->frontend.offset[1] = (top + bottom) / 2; dev->frontend.offset[2] = (top + bottom) / 2; /* scan with no move */ RIEF2 (gl124_set_fe(dev, AFE_SET), first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL124_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl124_offset_calibration: starting second line reading\n"); RIEF2 (gl124_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); if (DBG_LEVEL >= DBG_data) { sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]); sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines); } avg = dark_average (second_line, pixels, lines, channels, black_pixels); DBG (DBG_info, "gl124_offset_calibration: avg=%d offset=%d\n", avg, dev->frontend.offset[1]); /* compute new boundaries */ if (topavg == avg) { topavg = avg; top = dev->frontend.offset[1]; } else { bottomavg = avg; bottom = dev->frontend.offset[1]; } } DBG (DBG_info, "gl124_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); /* cleanup before return */ free (first_line); free (second_line); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* alternative coarse gain calibration this on uses the settings from offset_calibration and uses only one scanline */ /* with offset and coarse calibration we only want to get our input range into a reasonable shape. the fine calibration of the upper and lower bounds will be done with shading. */ static SANE_Status gl124_coarse_gain_calibration (Genesys_Device * dev, int dpi) { int pixels; int total_size; uint8_t *line, reg0a; int i, j, channels; SANE_Status status = SANE_STATUS_GOOD; int max[3]; float gain[3],coeff; int val, code, lines; int resolution; int bpp; DBG (DBG_proc, "gl124_coarse_gain_calibration: dpi = %d\n", dpi); /* no gain nor offset for TI AFE */ RIE (sanei_genesys_read_register (dev, REG0A, ®0a)); if(((reg0a & REG0A_SIFSEL)>>REG0AS_SIFSEL)==3) { DBGCOMPLETED; return status; } /* coarse gain calibration is always done in color mode */ channels = 3; /* follow CKSEL */ if(dev->settings.xressensor.optical_res) { coeff=0.9; /*resolution=dev->sensor.optical_res/2;*/ resolution=dev->sensor.optical_res; } else { resolution=dev->sensor.optical_res; coeff=1.0; } lines=10; bpp=8; pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; status = gl124_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, pixels, lines, bpp, channels, dev->settings.scan_method, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); gl124_set_motor_power (dev->calib_reg, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_coarse_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } RIE (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL124_MAX_REGS)); total_size = pixels * channels * (16/bpp) * lines; line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; RIEF (gl124_set_fe(dev, AFE_SET), line); RIEF (gl124_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("coarse.pnm", line, bpp, channels, pixels, lines); /* average value on each channel */ for (j = 0; j < channels; j++) { max[j] = 0; for (i = pixels/4; i < (pixels*3/4); i++) { if(bpp==16) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * pixels + 1] * 256 + line[i * 2 + j * 2 * pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; } else { if (dev->model->is_cis) val = line[i + j * pixels]; else val = line[i * channels + j]; } max[j] += val; } max[j] = max[j] / (pixels/2); gain[j] = ((float) dev->sensor.gain_white_ref*coeff) / max[j]; /* turn logical gain value into gain code, checking for overflow */ code = 283 - 208 / gain[j]; if (code > 255) code = 255; else if (code < 0) code = 0; dev->frontend.gain[j] = code; DBG (DBG_proc, "gl124_coarse_gain_calibration: channel %d, max=%d, gain = %f, setting:%d\n", j, max[j], gain[j], dev->frontend.gain[j]); } if (dev->model->is_cis) { if (dev->frontend.gain[0] > dev->frontend.gain[1]) dev->frontend.gain[0] = dev->frontend.gain[1]; if (dev->frontend.gain[0] > dev->frontend.gain[2]) dev->frontend.gain[0] = dev->frontend.gain[2]; dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0]; } if (channels == 1) { dev->frontend.gain[0] = dev->frontend.gain[1]; dev->frontend.gain[2] = dev->frontend.gain[1]; } free (line); RIE (gl124_stop_action (dev)); status = gl124_slow_back_home (dev, SANE_TRUE); DBGCOMPLETED; return status; } /* * wait for lamp warmup by scanning the same line until difference * between 2 scans is below a threshold */ static SANE_Status gl124_init_regs_for_warmup (Genesys_Device * dev, Genesys_Register_Set * reg, int *channels, int *total_size) { int num_pixels; SANE_Status status = SANE_STATUS_GOOD; DBGSTART; if (dev == NULL || reg == NULL || channels == NULL || total_size == NULL) return SANE_STATUS_INVAL; *channels=3; memcpy (reg, dev->reg, (GENESYS_GL124_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); status = gl124_init_scan_regs (dev, reg, dev->sensor.optical_res, dev->motor.base_ydpi, dev->sensor.sensor_pixels/4, 0, dev->sensor.sensor_pixels/2, 1, 8, *channels, dev->settings.scan_method, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl124_init_regs_for_warmup: failed to setup scan: %s\n", sane_strstatus (status)); return status; } num_pixels = dev->current_setup.pixels; *total_size = num_pixels * 3 * 1; /* colors * bytes_per_color * scan lines */ gl124_set_motor_power (reg, SANE_FALSE); RIE (dev->model->cmd_set->bulk_write_register (dev, reg, GENESYS_GL124_MAX_REGS)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief default GPIO values * set up GPIO/GPOE for idle state * @param dev device to set up * @return SANE_STATUS_GOOD unless a GPIO register cannot be written */ static SANE_Status gl124_init_gpio (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; int idx; DBGSTART; /* per model GPIO layout */ if (strcmp (dev->model->name, "canon-lide-110") == 0) { idx = 0; } else if (strcmp (dev->model->name, "canon-lide-110") == 0) { idx = 2; } else { /* canon LiDE 210 and 220 case */ idx = 1; } RIE (sanei_genesys_write_register (dev, REG31, gpios[idx].r31)); RIE (sanei_genesys_write_register (dev, REG32, gpios[idx].r32)); RIE (sanei_genesys_write_register (dev, REG33, gpios[idx].r33)); RIE (sanei_genesys_write_register (dev, REG34, gpios[idx].r34)); RIE (sanei_genesys_write_register (dev, REG35, gpios[idx].r35)); RIE (sanei_genesys_write_register (dev, REG36, gpios[idx].r36)); RIE (sanei_genesys_write_register (dev, REG38, gpios[idx].r38)); DBGCOMPLETED; return status; } /** * set memory layout by filling values in dedicated registers */ static SANE_Status gl124_init_memory_layout (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; int idx = 0; DBGSTART; /* point to per model memory layout */ if ((strcmp (dev->model->name, "canon-lide-110") == 0) ||(strcmp (dev->model->name, "canon-lide-120") == 0)) { idx = 0; } else { /* canon LiDE 210 and 220 case */ idx = 1; } /* setup base address for shading data. */ /* values must be multiplied by 8192=0x4000 to give address on AHB */ /* R-Channel shading bank0 address setting for CIS */ sanei_genesys_write_register (dev, 0xd0, layouts[idx].rd0); /* G-Channel shading bank0 address setting for CIS */ sanei_genesys_write_register (dev, 0xd1, layouts[idx].rd1); /* B-Channel shading bank0 address setting for CIS */ sanei_genesys_write_register (dev, 0xd2, layouts[idx].rd2); /* setup base address for scanned data. */ /* values must be multiplied by 1024*2=0x0800 to give address on AHB */ /* R-Channel ODD image buffer 0x0124->0x92000 */ /* size for each buffer is 0x16d*1k word */ sanei_genesys_write_register (dev, 0xe0, layouts[idx].re0); sanei_genesys_write_register (dev, 0xe1, layouts[idx].re1); /* R-Channel ODD image buffer end-address 0x0291->0x148800 => size=0xB6800*/ sanei_genesys_write_register (dev, 0xe2, layouts[idx].re2); sanei_genesys_write_register (dev, 0xe3, layouts[idx].re3); /* R-Channel EVEN image buffer 0x0292 */ sanei_genesys_write_register (dev, 0xe4, layouts[idx].re4); sanei_genesys_write_register (dev, 0xe5, layouts[idx].re5); /* R-Channel EVEN image buffer end-address 0x03ff*/ sanei_genesys_write_register (dev, 0xe6, layouts[idx].re6); sanei_genesys_write_register (dev, 0xe7, layouts[idx].re7); /* same for green, since CIS, same addresses */ sanei_genesys_write_register (dev, 0xe8, layouts[idx].re0); sanei_genesys_write_register (dev, 0xe9, layouts[idx].re1); sanei_genesys_write_register (dev, 0xea, layouts[idx].re2); sanei_genesys_write_register (dev, 0xeb, layouts[idx].re3); sanei_genesys_write_register (dev, 0xec, layouts[idx].re4); sanei_genesys_write_register (dev, 0xed, layouts[idx].re5); sanei_genesys_write_register (dev, 0xee, layouts[idx].re6); sanei_genesys_write_register (dev, 0xef, layouts[idx].re7); /* same for blue, since CIS, same addresses */ sanei_genesys_write_register (dev, 0xf0, layouts[idx].re0); sanei_genesys_write_register (dev, 0xf1, layouts[idx].re1); sanei_genesys_write_register (dev, 0xf2, layouts[idx].re2); sanei_genesys_write_register (dev, 0xf3, layouts[idx].re3); sanei_genesys_write_register (dev, 0xf4, layouts[idx].re4); sanei_genesys_write_register (dev, 0xf5, layouts[idx].re5); sanei_genesys_write_register (dev, 0xf6, layouts[idx].re6); sanei_genesys_write_register (dev, 0xf7, layouts[idx].re7); DBGCOMPLETED; return status; } /** * initialize backend and ASIC : registers, motor tables, and gamma tables * then ensure scanner's head is at home */ #ifndef UNIT_TESTING static #endif SANE_Status gl124_init (Genesys_Device * dev) { SANE_Status status; DBG_INIT (); DBGSTART; status=sanei_genesys_asic_init(dev, GENESYS_GL124_MAX_REGS); DBGCOMPLETED; return status; } /* * * initialize ASIC from power on condition */ static SANE_Status gl124_boot (Genesys_Device * dev, SANE_Bool cold) { SANE_Status status; uint8_t val; DBGSTART; /* reset ASIC in case of cold boot */ if(cold) { RIE (sanei_genesys_write_register (dev, 0x0e, 0x01)); RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); } /* enable GPOE 17 */ RIE (sanei_genesys_write_register (dev, 0x36, 0x01)); /* set GPIO 17 */ RIE (sanei_genesys_read_register (dev, 0x33, &val)); val |= 0x01; RIE (sanei_genesys_write_register (dev, 0x33, val)); /* test CHKVER */ RIE (sanei_genesys_read_register (dev, REG100, &val)); if (val & REG100_CHKVER) { RIE (sanei_genesys_read_register (dev, 0x00, &val)); DBG (DBG_info, "gl124_cold_boot: reported version for genesys chip is 0x%02x\n", val); } /* Set default values for registers */ gl124_init_registers (dev); /* Write initial registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL124_MAX_REGS)); /* tune reg 0B */ val = REG0B_30MHZ | REG0B_ENBDRAM | REG0B_64M; RIE (sanei_genesys_write_register (dev, REG0B, val)); dev->reg[reg_0x0b].address = 0x00; /* set up end access */ RIE (sanei_genesys_write_0x8c (dev, 0x10, 0x0b)); RIE (sanei_genesys_write_0x8c (dev, 0x13, 0x0e)); /* CIS_LINE */ SETREG (0x08, REG08_CIS_LINE); RIE (sanei_genesys_write_register (dev, 0x08, dev->reg[reg_0x08].value)); /* setup gpio */ RIE (gl124_init_gpio (dev)); /* setup internal memory layout */ RIE (gl124_init_memory_layout (dev)); DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl124_update_hardware_sensors (Genesys_Scanner * s) { /* do what is needed to get a new set of events, but try to not loose any of them. */ SANE_Status status = SANE_STATUS_GOOD; uint8_t val=0; RIE (sanei_genesys_read_register (s->dev, REG31, &val)); /* TODO : for the next scanner special case, * add another per scanner button profile struct to avoid growing * hard-coded button mapping here. */ if((s->dev->model->gpo_type == GPO_CANONLIDE110) ||(s->dev->model->gpo_type == GPO_CANONLIDE120)) { if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b) s->val[OPT_SCAN_SW].b = (val & 0x01) == 0; if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b) s->val[OPT_FILE_SW].b = (val & 0x08) == 0; if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b) s->val[OPT_EMAIL_SW].b = (val & 0x04) == 0; if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b) s->val[OPT_COPY_SW].b = (val & 0x02) == 0; } else { /* LiDE 210 case */ if (s->val[OPT_EXTRA_SW].b == s->last_val[OPT_EXTRA_SW].b) s->val[OPT_EXTRA_SW].b = (val & 0x01) == 0; if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b) s->val[OPT_SCAN_SW].b = (val & 0x02) == 0; if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b) s->val[OPT_COPY_SW].b = (val & 0x04) == 0; if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b) s->val[OPT_EMAIL_SW].b = (val & 0x08) == 0; if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b) s->val[OPT_FILE_SW].b = (val & 0x10) == 0; } return status; } /** the gl124 command set */ static Genesys_Command_Set gl124_cmd_set = { "gl124-generic", /* the name of this set */ gl124_init, gl124_init_regs_for_warmup, gl124_init_regs_for_coarse_calibration, gl124_init_regs_for_shading, gl124_init_regs_for_scan, gl124_get_filter_bit, gl124_get_lineart_bit, gl124_get_bitset_bit, gl124_get_gain4_bit, gl124_get_fast_feed_bit, gl124_test_buffer_empty_bit, gl124_test_motor_flag_bit, gl124_bulk_full_size, gl124_set_fe, gl124_set_powersaving, gl124_save_power, gl124_set_motor_power, gl124_set_lamp_power, gl124_begin_scan, gl124_end_scan, sanei_genesys_send_gamma_table, gl124_search_start_position, gl124_offset_calibration, gl124_coarse_gain_calibration, gl124_led_calibration, gl124_slow_back_home, gl124_rewind, sanei_genesys_bulk_write_register, NULL, gl124_bulk_read_data, gl124_update_hardware_sensors, /* no sheetfed support for now */ NULL, NULL, NULL, NULL, sanei_genesys_is_compatible_calibration, NULL, gl124_send_shading_data, gl124_calculate_current_setup, gl124_boot, gl124_init_scan_regs }; SANE_Status sanei_gl124_init_cmd_set (Genesys_Device * dev) { dev->model->cmd_set = &gl124_cmd_set; return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/epson2_net.c0000664000175000017500000001207512775312261015044 00000000000000/* * epson2_net.c - SANE library for Epson scanners. * * Copyright (C) 2006 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #ifdef HAVE_SYS_SELECT_H #include #endif #include "sane/sane.h" #include "sane/saneopts.h" #include "sane/sanei_tcp.h" #include "sane/sanei_config.h" #include "sane/sanei_backend.h" #include "epson2.h" #include "epson2_net.h" #include "byteorder.h" #include "sane/sanei_debug.h" static int sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, SANE_Status *status) { int ready, read = -1; fd_set readable; struct timeval tv; tv.tv_sec = 10; tv.tv_usec = 0; FD_ZERO(&readable); FD_SET(s->fd, &readable); ready = select(s->fd + 1, &readable, NULL, NULL, &tv); if (ready > 0) { read = sanei_tcp_read(s->fd, buf, wanted); } else { DBG(15, "%s: select failed: %d\n", __func__, ready); } *status = SANE_STATUS_GOOD; if (read < wanted) { *status = SANE_STATUS_IO_ERROR; } return read; } int sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, SANE_Status * status) { ssize_t size; ssize_t read = 0; unsigned char header[12]; /* read from buffer, if available */ if (s->netptr != s->netbuf) { DBG(23, "reading %lu from buffer at %p, %lu available\n", (u_long) wanted, s->netptr, (u_long) s->netlen); memcpy(buf, s->netptr, wanted); read = wanted; s->netlen -= wanted; if (s->netlen == 0) { DBG(23, "%s: freeing %p\n", __func__, s->netbuf); free(s->netbuf); s->netbuf = s->netptr = NULL; s->netlen = 0; } return read; } /* receive net header */ size = sanei_epson_net_read_raw(s, header, 12, status); if (size != 12) { return 0; } if (header[0] != 'I' || header[1] != 'S') { DBG(1, "header mismatch: %02X %02x\n", header[0], header[1]); *status = SANE_STATUS_IO_ERROR; return 0; } size = be32atoh(&header[6]); DBG(23, "%s: wanted = %lu, available = %lu\n", __func__, (u_long) wanted, (u_long) size); *status = SANE_STATUS_GOOD; if (size == wanted) { DBG(15, "%s: full read\n", __func__); read = sanei_epson_net_read_raw(s, buf, size, status); if (s->netbuf) { free(s->netbuf); s->netbuf = NULL; s->netlen = 0; } if (read < 0) { return 0; } /* } else if (wanted < size && s->netlen == size) { */ } else { DBG(23, "%s: partial read\n", __func__); read = sanei_epson_net_read_raw(s, s->netbuf, size, status); if (read != size) { return 0; } s->netlen = size - wanted; s->netptr += wanted; read = wanted; DBG(23, "0,4 %02x %02x\n", s->netbuf[0], s->netbuf[4]); DBG(23, "storing %lu to buffer at %p, next read at %p, %lu bytes left\n", (u_long) size, s->netbuf, s->netptr, (u_long) s->netlen); memcpy(buf, s->netbuf, wanted); } return read; } int sanei_epson_net_write(Epson_Scanner *s, unsigned int cmd, const unsigned char *buf, size_t buf_size, size_t reply_len, SANE_Status *status) { unsigned char *h1, *h2, *payload; unsigned char *packet = malloc(12 + 8 + buf_size); /* XXX check allocation failure */ h1 = packet; h2 = packet + 12; payload = packet + 12 + 8; if (reply_len) { s->netbuf = s->netptr = malloc(reply_len); s->netlen = reply_len; DBG(24, "allocated %lu bytes at %p\n", (u_long) reply_len, s->netbuf); } DBG(24, "%s: cmd = %04x, buf = %p, buf_size = %lu, reply_len = %lu\n", __func__, cmd, buf, (u_long) buf_size, (u_long) reply_len); memset(h1, 0x00, 12); memset(h2, 0x00, 8); h1[0] = 'I'; h1[1] = 'S'; h1[2] = cmd >> 8; h1[3] = cmd; h1[4] = 0x00; h1[5] = 0x0C; /* Don't know what's that */ DBG(24, "H1[0]: %02x %02x %02x %02x\n", h1[0], h1[1], h1[2], h1[3]); if((cmd >> 8) == 0x20) { htobe32a(&h1[6], buf_size + 8); htobe32a(&h2[0], buf_size); htobe32a(&h2[4], reply_len); DBG(24, "H1[6]: %02x %02x %02x %02x (%lu)\n", h1[6], h1[7], h1[8], h1[9], (u_long) (buf_size + 8)); DBG(24, "H2[0]: %02x %02x %02x %02x (%lu)\n", h2[0], h2[1], h2[2], h2[3], (u_long) buf_size); DBG(24, "H2[4]: %02x %02x %02x %02x (%lu)\n", h2[4], h2[5], h2[6], h2[7], (u_long) reply_len); } if ((cmd >> 8) == 0x20 && (buf_size || reply_len)) { if (buf_size) memcpy(payload, buf, buf_size); sanei_tcp_write(s->fd, packet, 12 + 8 + buf_size); } else sanei_tcp_write(s->fd, packet, 12); free(packet); *status = SANE_STATUS_GOOD; return buf_size; } SANE_Status sanei_epson_net_lock(struct Epson_Scanner *s) { SANE_Status status; unsigned char buf[1]; DBG(1, "%s\n", __func__); sanei_epson_net_write(s, 0x2100, NULL, 0, 0, &status); sanei_epson_net_read(s, buf, 1, &status); return status; } SANE_Status sanei_epson_net_unlock(struct Epson_Scanner *s) { SANE_Status status; DBG(1, "%s\n", __func__); sanei_epson_net_write(s, 0x2101, NULL, 0, 0, &status); /* sanei_epson_net_read(s, buf, 1, &status); */ return status; } sane-backends-1.0.27/backend/fujitsu.conf.in0000664000175000017500000000651413072310726015565 00000000000000# NOTE: any 'option' lines only apply to # scanners discovered later in this file # to set data buffer size, in bytes # the value ranges from 4096 - infinity # but old scanners may have scanning problems # with a value larger than 65536 (the default) # NOTE: this option is set to a larger value # later in this file, for more recent scanners option buffer-size 65536 # To search for all FUJITSU scsi devices scsi FUJITSU # To use a specific scsi device #scsi /dev/sg1 # For Fujitsu scanners connected via USB on a known device (kernel driver): #usb /dev/usb/scanner0 # For Fujitsu scanners connected via USB using vendor and device ids (libusb): #usb VENDORID PRODUCTID # NOTE: if you have to add your device here- please send the id and model # to the author via email, so it can be included in next version. kitno455 at # gmail dot com - with Fujitsu in the subject line #fi-4x20C usb 0x04c5 0x1041 usb 0x04c5 0x1042 #fi-4530C usb 0x04c5 0x1078 #fi-5750C usb 0x04c5 0x1095 #fi-5110eox/2 usb 0x04c5 0x1096 #fi-5110C usb 0x04c5 0x1097 #fi-5650C usb 0x04c5 0x10ad #fi-4x20C2 usb 0x04c5 0x10ae usb 0x04c5 0x10af #fi-4340C usb 0x04c5 0x10cf #fi-5x20C usb 0x04c5 0x10e0 usb 0x04c5 0x10e1 #fi-5530C usb 0x04c5 0x10e2 #fi-5110eox3 usb 0x04c5 0x10e6 #fi-5900C usb 0x04c5 0x10e7 #fi-5110EOXM usb 0x04c5 0x10f2 #ScanSnap S500 usb 0x04c5 0x10fe #ScanSnap S500M usb 0x04c5 0x1135 #fi-5530C2 usb 0x04c5 0x114a # More recent scanners need a larger buffer for maximum speed option buffer-size 262144 #fi-6140 usb 0x04c5 0x114d #fi-6240 usb 0x04c5 0x114e #fi-6130 usb 0x04c5 0x114f #fi-6230 usb 0x04c5 0x1150 #ScanSnap S510 usb 0x04c5 0x1155 #ScanSnap S510M usb 0x04c5 0x116f #fi-6770 usb 0x04c5 0x1174 #fi-6770A usb 0x04c5 0x1175 #fi-6670 usb 0x04c5 0x1176 #fi-6670A usb 0x04c5 0x1177 #fi-6750S usb 0x04c5 0x1178 #fi-6800 usb 0x04c5 0x119d #fi-6800-CGA usb 0x04c5 0x119e #S1500 & S1500M usb 0x04c5 0x11a2 #fi-6125 usb 0x04c5 0x11ee #fi-6225 usb 0x04c5 0x11ef #fi-6140Z/fi-6160ZLA usb 0x04c5 0x11f1 #fi-6240Z usb 0x04c5 0x11f2 #fi-6130Z usb 0x04c5 0x11f3 #fi-6230Z usb 0x04c5 0x11f4 #fi-6110 usb 0x04c5 0x11fc #fi-5950 usb 0x04c5 0x1213 #ScanSnap SV600 usb 0x04c5 0x128e #ScanSnap iX500 usb 0x04c5 0x132b #fi-7180 usb 0x04c5 0x132c #fi-7280 usb 0x04c5 0x132d #fi-7160 usb 0x04c5 0x132e #fi-7260 usb 0x04c5 0x132f #ScanSnap iX500EE usb 0x04c5 0x13f3 #ScanSnap iX100 usb 0x04c5 0x13f4 #ScanPartner SP25 usb 0x04c5 0x1409 #ScanPartner SP30 usb 0x04c5 0x140a #ScanPartner SP30F usb 0x04c5 0x140c #fi-6140ZLA usb 0x04c5 0x145f #fi-6240ZLA usb 0x04c5 0x1460 #fi-6130ZLA usb 0x04c5 0x1461 #fi-6230ZLA usb 0x04c5 0x1462 #fi-6125ZLA usb 0x04c5 0x1463 #fi-6225ZLA usb 0x04c5 0x1464 #fi-6135ZLA usb 0x04c5 0x146b #fi-6235ZLA usb 0x04c5 0x146c #fi-6120ZLA usb 0x04c5 0x146d #fi-6220ZLA usb 0x04c5 0x146e #N7100 usb 0x04c5 0x146f #fi-6400 usb 0x04c5 0x14ac #fi-7480 usb 0x04c5 0x14b8 #fi-6420 usb 0x04c5 0x14bd #fi-7460 usb 0x04c5 0x14be #fi-7140 usb 0x04c5 0x14df #fi-7240 usb 0x04c5 0x14e0 #fi-7135 usb 0x04c5 0x14e1 #fi-7235 usb 0x04c5 0x14e2 #fi-7130 usb 0x04c5 0x14e3 #fi-7230 usb 0x04c5 0x14e4 #fi-7125 usb 0x04c5 0x14e5 #fi-7225 usb 0x04c5 0x14e6 #fi-7120 usb 0x04c5 0x14e7 #fi-7220 usb 0x04c5 0x14e8 #fi-400F usb 0x04c5 0x151e #fi-7030 usb 0x04c5 0x151f #fi-7700 usb 0x04c5 0x1520 #fi-7600 usb 0x04c5 0x1521 #fi-7700S usb 0x04c5 0x1522 sane-backends-1.0.27/backend/nec.h0000664000175000017500000002632312112021330013516 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Kazuya Fukuda This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef nec_h #define nec_h 1 #include /* default values for configurable options. Though these options are only meaningful if USE_FORK is defined, they are DEFAULT_BUFFERS: number of buffers allocated as shared memory for the data transfer from reader_process to read_data. The minimum value is 2 DEFAULT_BUFSIZE: default size of one buffer. Must be greater than zero. DEFAULT_QUEUED_READS: number of read requests queued by sanei_scsi_req_enter. Since queued read requests are currently only supported for Linux and DomainOS, this value should automatically be set dependent on the target OS... For Linux, 2 is the optimum; for DomainOS, I don't have any recommendation; other OS should use the value zero. The value for DEFAULT_BUFSIZE is probably too Linux-oriented... */ #define DEFAULT_BUFFERS 12 #define DEFAULT_BUFSIZE 128 * 1024 #define DEFAULT_QUEUED_READS 2 #define NEC_MAJOR 0 #define NEC_MINOR 12 typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_HALFTONE, OPT_PAPER, OPT_SCANSOURCE, OPT_GAMMA, #ifdef USE_CUSTOM_GAMMA OPT_CUSTOM_GAMMA, #endif OPT_RESOLUTION_GROUP, #ifdef USE_RESOLUTION_LIST OPT_RESOLUTION_LIST, #endif OPT_RESOLUTION, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_EDGE_EMPHASIS, OPT_OR, OPT_NR, OPT_EDGE, OPT_THRESHOLD, #ifdef USE_COLOR_THRESHOLD OPT_THRESHOLD_R, OPT_THRESHOLD_G, OPT_THRESHOLD_B, #endif OPT_LIGHTCOLOR, OPT_TINT, OPT_COLOR, OPT_PREVIEW, #ifdef USE_CUSTOM_GAMMA OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, #endif /* must come last: */ NUM_OPTIONS } NEC_Option; #ifdef USE_FORK /* status defines for a buffer: buffer not used / read request queued / buffer contains data */ #define SHM_EMPTY 0 #define SHM_BUSY 1 #define SHM_FULL 2 typedef struct NEC_shmem_ctl { int shm_status; /* can be SHM_EMPTY, SHM_BUSY, SHM_FULL */ size_t used; /* number of bytes successfully read from scanner */ size_t nreq; /* number of bytes requested from scanner */ size_t start; /* index of the begin of used area of the buffer */ void *qid; SANE_Byte *buffer; } NEC_shmem_ctl; typedef struct NEC_rdr_ctl { int cancel; /* 1 = flag for the reader process to cancel */ int running; /* 1 indicates that the reader process is alive */ SANE_Status status; /* return status of the reader process */ NEC_shmem_ctl *buf_ctl; } NEC_rdr_ctl; #endif /* USE_FORK */ typedef enum { /* PCIN500, PCINXXX are used as array indices, so the corresponding numbers should start at 0 */ unknown = -1, PCIN500, PCINXXX } NEC_Model; typedef struct NEC_Info { SANE_Range res_range; SANE_Range tl_x_ranges[3]; /* normal / FSU / ADF */ SANE_Range br_x_ranges[3]; /* normal / FSU / ADF */ SANE_Range tl_y_ranges[3]; /* normal / FSU / ADF */ SANE_Range br_y_ranges[3]; /* normal / FSU / ADF */ SANE_Range threshold_range; SANE_Range tint_range; SANE_Range color_range; SANE_Int res_default; SANE_Int x_default; SANE_Int y_default; SANE_Int bmu; SANE_Int mud; SANE_Int adf_fsu_installed; SANE_String_Const scansources[5]; size_t buffers; size_t bufsize; int wanted_bufsize; size_t queued_reads; } NEC_Info; typedef struct NEC_Sense_Data { NEC_Model model; /* flag, if conditions like "paper jam" or "cover open" are considered as an error. Should be 0 for attach, else a frontend might refuse to start, if the scanner returns these errors. */ int complain_on_adf_error; /* Linux returns only 16 bytes of sense data... */ u_char sb[16]; } NEC_Sense_Data; typedef struct NEC_Device { struct NEC_Device *next; SANE_Device sane; NEC_Info info; /* xxx now part of sense data NEC_Model model; */ NEC_Sense_Data sensedat; } NEC_Device; typedef struct NEC_New_Device { struct NEC_Device *dev; struct NEC_New_Device *next; } NEC_New_Device; typedef struct NEC_Scanner { struct NEC_Scanner *next; int fd; NEC_Device *dev; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; int get_params_called; SANE_Byte *buffer; /* for color data re-ordering */ SANE_Int buf_used; SANE_Int buf_pos; SANE_Int modes; SANE_Int res; SANE_Int ulx; SANE_Int uly; SANE_Int width; SANE_Int length; SANE_Int threshold; SANE_Int image_composition; SANE_Int bpp; SANE_Int halftone; SANE_Bool reverse; SANE_Bool or; SANE_Bool nr; SANE_Int gamma; SANE_Int edge; SANE_Int lightcolor; SANE_Int adf_fsu_mode; /* mode selected by user */ SANE_Int adf_scan; /* flag, if the actual scan is an ADF scan */ SANE_Int tint; SANE_Int color; size_t bytes_to_read; size_t max_lines_to_read; size_t unscanned_lines; SANE_Bool scanning; SANE_Bool busy; SANE_Bool cancel; #ifdef USE_CUSTOM_GAMMA SANE_Int gamma_table[4][256]; #endif #ifdef USE_FORK pid_t reader_pid; NEC_rdr_ctl *rdr_ctl; int shmid; size_t read_buff; /* index of the buffer actually used by read_data */ #endif /* USE_FORK */ } NEC_Scanner; typedef struct NEC_Send { SANE_Int dtc; SANE_Int dtq; SANE_Int length; SANE_Byte *data; } NEC_Send; typedef struct WPDH { u_char wpdh[6]; u_char wdl[2]; } WPDH; typedef struct WDB { SANE_Byte wid; SANE_Byte autobit; SANE_Byte x_res[2]; SANE_Byte y_res[2]; SANE_Byte x_ul[4]; SANE_Byte y_ul[4]; SANE_Byte width[4]; SANE_Byte length[4]; SANE_Byte brightness; SANE_Byte threshold; SANE_Byte contrast; SANE_Byte image_composition; SANE_Byte bpp; SANE_Byte ht_pattern[2]; SANE_Byte rif_padding; SANE_Byte bit_ordering[2]; SANE_Byte compression_type; SANE_Byte compression_argument; SANE_Byte reserved[6]; } WDB; /* "extension" of the window descriptor block for the PC-IN500 */ typedef struct XWDBX500 { SANE_Byte data_length; SANE_Byte control; SANE_Byte format; SANE_Byte gamma; SANE_Byte tint; SANE_Byte color; SANE_Byte reserved1; SANE_Byte reserved2; } WDBX500; typedef struct window_param { WPDH wpdh; WDB wdb; WDBX500 wdbx500; } window_param; typedef struct mode_sense_param { SANE_Byte mode_data_length; SANE_Byte mode_param_header2; SANE_Byte mode_param_header3; SANE_Byte mode_desciptor_length; SANE_Byte page_code; SANE_Byte page_length; /* 6 */ SANE_Byte bmu; SANE_Byte res2; SANE_Byte mud[2]; SANE_Byte res3; SANE_Byte res4; } mode_sense_param; typedef struct mode_sense_subdevice { SANE_Byte mode_data_length; SANE_Byte mode_param_header2; SANE_Byte mode_param_header3; SANE_Byte mode_desciptor_length; SANE_Byte res1[5]; SANE_Byte blocklength[3]; SANE_Byte page_code; SANE_Byte page_length; /* 0x1a */ SANE_Byte a_mode_type; SANE_Byte f_mode_type; SANE_Byte res2; SANE_Byte max_x[4]; SANE_Byte max_y[4]; SANE_Byte res3[2]; SANE_Byte x_basic_resolution[2]; SANE_Byte y_basic_resolution[2]; SANE_Byte x_max_resolution[2]; SANE_Byte y_max_resolution[2]; SANE_Byte x_min_resolution[2]; SANE_Byte y_min_resolution[2]; SANE_Byte res4; } mode_sense_subdevice; typedef struct mode_select_param { SANE_Byte mode_param_header1; SANE_Byte mode_param_header2; SANE_Byte mode_param_header3; SANE_Byte mode_param_header4; SANE_Byte page_code; SANE_Byte page_length; /* 6 */ SANE_Byte res1; SANE_Byte res2; SANE_Byte mud[2]; SANE_Byte res3; SANE_Byte res4; } mode_select_param; typedef struct mode_select_subdevice { SANE_Byte mode_param_header1; SANE_Byte mode_param_header2; SANE_Byte mode_param_header3; SANE_Byte mode_param_header4; SANE_Byte page_code; SANE_Byte page_length; /* 0x1A */ SANE_Byte a_mode; SANE_Byte f_mode; SANE_Byte res[24]; } mode_select_subdevice; typedef struct buffer_status { SANE_Byte data_length[3]; SANE_Byte block; SANE_Byte window_id; SANE_Byte reserved; SANE_Byte bsa[3]; /* buffer space available */ SANE_Byte fdb[3]; /* filled data buffer */ } buffer_status; /* SCSI commands */ #define TEST_UNIT_READY 0x00 #define REQUEST_SENSE 0x03 #define INQUIRY 0x12 #define MODE_SELECT6 0x15 #define RESERVE_UNIT 0x16 #define RELEASE_UNIT 0x17 #define MODE_SENSE6 0x1a #define SCAN 0x1b #define SEND_DIAGNOSTIC 0x1d #define SET_WINDOW 0x24 #define GET_WINDOW 0x25 #define READ 0x28 #define SEND 0x2a #define GET_DATA_BUFFER_STATUS 0x34 #define SENSE_LEN 18 #define INQUIRY_LEN 36 #define MODEPARAM_LEN 12 #define MODE_SUBDEV_LEN 32 #define WINDOW_LEN 76 #define BUFFERSTATUS_LEN 12 #endif /* not nec_h */ sane-backends-1.0.27/backend/dc25.c0000664000175000017500000017541112775312260013530 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. dc25.c $Id$ This file (C) 1998 Peter Fales This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for the Kodak DC-25 (and probably the DC-20) digital cameras. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! (feedback to: dc25-devel@fales-lorenz.net) This backend is based heavily on the dc20ctrl package by Ugo Paternostro . I've attached his header below: *************************************************************************** * Copyright (C) 1998 Ugo Paternostro * * This file is part of the dc20ctrl package. The complete package can be * downloaded from: * http://aguirre.dsi.unifi.it/~paterno/binaries/dc20ctrl.tar.gz * * This package is derived from the dc20 package, built by Karl Hakimian * that you can find it at ftp.eecs.wsu.edu in the * /pub/hakimian directory. The complete URL is: * ftp://ftp.eecs.wsu.edu/pub/hakimian/dc20.tar.gz * * This package also includes a sligthly modified version of the Comet to ppm * conversion routine written by YOSHIDA Hideki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ***************************************************************************/ #include "../include/sane/config.h" #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME dc25 #include "../include/sane/sanei_backend.h" #include "dc25.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define MAGIC (void *)0xab730324 #define DC25_CONFIG_FILE "dc25.conf" #define THUMBSIZE ( (CameraInfo.model == 0x25 ) ? 14400 : 5120 ) static SANE_Bool is_open = 0; static SANE_Byte dc25_opt_image_number = 1; /* Image to load */ static SANE_Bool dc25_opt_thumbnails; /* Load thumbnails */ static SANE_Bool dc25_opt_snap; /* Take new picture */ static SANE_Bool dc25_opt_lowres; /* Use low resoluiton */ #define DC25_OPT_CONTRAST_DEFAULT 1.6 /* Contrast enhancement */ static SANE_Fixed dc25_opt_contrast = SANE_FIX (DC25_OPT_CONTRAST_DEFAULT); #define DC25_OPT_GAMMA_DEFAULT 4.5 /* Gamma correction (10x) */ static SANE_Fixed dc25_opt_gamma = SANE_FIX (DC25_OPT_GAMMA_DEFAULT); static SANE_Bool dc25_opt_erase; /* Erase all after download */ static SANE_Bool dc25_opt_erase_one; /* Erase one after download */ static SANE_Bool dumpinquiry; static SANE_Int info_flags; static int tfd; /* Camera File Descriptor */ static char tty_name[PATH_MAX]; #define DEF_TTY_NAME "/dev/ttyS0" static speed_t tty_baud = DEFAULT_TTY_BAUD; static char *tmpname; static char tmpnamebuf[] = "/tmp/dc25XXXXXX"; static Dc20Info *dc20_info; static Dc20Info CameraInfo; static SANE_Byte contrast_table[256]; static struct pixmap *pp; static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 0 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static const SANE_Range contrast_range = { 0 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 3 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 16384 /* quantization ~ 0.025 */ }; static const SANE_Range gamma_range = { 0 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 10 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 16384 /* quantization ~ 0.025 */ }; static SANE_Range image_range = { 0, 14, 0 }; static SANE_Option_Descriptor sod[] = { { SANE_NAME_NUM_OPTIONS, SANE_TITLE_NUM_OPTIONS, SANE_DESC_NUM_OPTIONS, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define D25_OPT_IMAGE_SELECTION 1 { "", "Image Selection", "Selection of the image to load.", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0, 0, SANE_CONSTRAINT_NONE, {NULL} } , #define DC25_OPT_IMAGE_NUMBER 2 { "image", "Image Number", "Select Image Number to load from camera", SANE_TYPE_INT, SANE_UNIT_NONE, 4, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(SANE_String_Const *) & image_range} /* this is ANSI conformant! */ } , #define DC25_OPT_THUMBS 3 { "thumbs", "Load Thumbnail", "Load the image as thumbnail.", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC25_OPT_SNAP 4 { "snap", "Snap new picture", "Take new picture and download it", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED, SANE_CONSTRAINT_NONE, {NULL} } , #define DC25_OPT_LOWRES 5 { "lowres", "Low Resolution", "New pictures taken in low resolution", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED, SANE_CONSTRAINT_NONE, {NULL} } , #define DC25_OPT_ERASE 6 { "erase", "Erase", "Erase all pictures after downloading", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC25_OPT_ERASE_ONE 7 { "erase-one", "Erase One", "Erase downloaded picture after downloading", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC25_OPT_ENHANCE 8 { "", "Image Parameters", "Modifications to image parameters", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0, 0, SANE_CONSTRAINT_NONE, {NULL} } , #define DC25_OPT_CONTRAST 9 { "contrast", "Contrast Adjustment", "Values > 1 enhance contrast", SANE_TYPE_FIXED, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) &contrast_range} /* this is ANSI conformant! */ }, #define DC25_OPT_GAMMA 10 { "gamma", "Gamma Adjustment", "Larger values make image darker", SANE_TYPE_FIXED, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) &gamma_range} /* this is ANSI conformant! */ }, #define DC25_OPT_DEFAULT 11 { "default-enhancements", "Defaults", "Set default values for enhancement controls (i.e. contrast).", SANE_TYPE_BUTTON, SANE_UNIT_NONE, 0, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } }; static SANE_Parameters parms = { SANE_FRAME_RGB, 1, 500, /* Number of bytes returned per scan line: */ 500, /* Number of pixels per scan line. */ 373, /* Number of lines for the current scan. */ 8, /* Number of bits per sample. */ }; static unsigned char init_pck[] = INIT_PCK; /* * List of speeds to try to establish connection with the camera. * Check 9600 first, as it's the speed the camera comes up in, then * 115200, as that is the one most likely to be configured from a * previous run */ static struct pkt_speed speeds[] = { {B9600, {0x96, 0x00}}, #ifdef B115200 {B115200, {0x11, 0x52}}, #endif #ifdef B57600 {B57600, {0x57, 0x60}}, #endif {B38400, {0x38, 0x40}}, {B19200, {0x19, 0x20}}, }; #define NUM_OF_SPEEDS ((int)(sizeof(speeds) / sizeof(struct pkt_speed))) static struct termios tty_orig; static int send_pck (int fd, unsigned char *pck) { int n; unsigned char r; /* * Not quite sure why we need this, but the program works a whole * lot better (at least on the DC25) with this short delay. */ #ifdef HAVE_USLEEP usleep (10); #else sleep (1); #endif if (write (fd, (char *) pck, 8) != 8) { DBG (2, "send_pck: error: write returned -1\n"); return -1; } if ((n = read (fd, (char *) &r, 1)) != 1) { DBG (2, "send_pck: error: read returned -1\n"); return -1; } return (r == 0xd1) ? 0 : -1; } static int init_dc20 (char *device, speed_t speed) { struct termios tty_new; int speed_index; DBG (1, "DC-20/25 Backend 05/07/01\n"); for (speed_index = 0; speed_index < NUM_OF_SPEEDS; speed_index++) { if (speeds[speed_index].baud == speed) { init_pck[2] = speeds[speed_index].pkt_code[0]; init_pck[3] = speeds[speed_index].pkt_code[1]; break; } } if (init_pck[2] == 0) { DBG (2, "unsupported baud rate.\n"); return -1; } /* Open device file. */ if ((tfd = open (device, O_RDWR)) == -1) { DBG (2, "init_dc20: error: could not open %s for read/write\n", device); return -1; } /* Save old device information to restore when we are done. */ if (tcgetattr (tfd, &tty_orig) == -1) { DBG (2, "init_dc20: error: could not get attributes\n"); return -1; } memcpy ((char *) &tty_new, (char *) &tty_orig, sizeof (struct termios)); /* We need the device to be raw. 8 bits even parity on 9600 baud to start. */ #ifdef HAVE_CFMAKERAW cfmakeraw (&tty_new); #else tty_new.c_lflag &= ~(ICANON | ECHO | ISIG); #endif tty_new.c_oflag &= ~CSTOPB; tty_new.c_cflag |= PARENB; tty_new.c_cflag &= ~PARODD; tty_new.c_cc[VMIN] = 0; tty_new.c_cc[VTIME] = 50; cfsetospeed (&tty_new, B9600); cfsetispeed (&tty_new, B9600); if (tcsetattr (tfd, TCSANOW, &tty_new) == -1) { DBG (2, "init_dc20: error: could not set attributes\n"); return -1; } if (send_pck (tfd, init_pck) == -1) { /* * The camera always powers up at 9600, so we try * that first. However, it may be already set to * a different speed. Try the entries in the table: */ for (speed_index = NUM_OF_SPEEDS - 1; speed_index > 0; speed_index--) { DBG (3, "init_dc20: changing speed to %d\n", (int) speeds[speed_index].baud); cfsetospeed (&tty_new, speeds[speed_index].baud); cfsetispeed (&tty_new, speeds[speed_index].baud); if (tcsetattr (tfd, TCSANOW, &tty_new) == -1) { DBG (2, "init_dc20: error: could not set attributes\n"); return -1; } if (send_pck (tfd, init_pck) != -1) break; } if (speed_index == 0) { tcsetattr (tfd, TCSANOW, &tty_orig); DBG (2, "init_dc20: error: no suitable baud rate\n"); return -1; } } /* Set speed to requested speed. Also, make a long timeout (we need this for erase and shoot operations) */ tty_new.c_cc[VTIME] = 150; cfsetospeed (&tty_new, speed); cfsetispeed (&tty_new, speed); if (tcsetattr (tfd, TCSANOW, &tty_new) == -1) { DBG (2, "init_dc20: error: could not set attributes\n"); return -1; } return tfd; } static void close_dc20 (int fd) { DBG (127, "close_dc20() called\n"); /* * Put the camera back to 9600 baud */ init_pck[2] = speeds[0].pkt_code[0]; init_pck[3] = speeds[0].pkt_code[1]; if (send_pck (fd, init_pck) == -1) { DBG (4, "close_dc20: error: could not set attributes\n"); } /* Restore original device settings. */ if (tcsetattr (fd, TCSANOW, &tty_orig) == -1) { DBG (4, "close_dc20: error: could not set attributes\n"); } if (close (fd) == -1) { DBG (4, "close_dc20: error: could not close device\n"); } } static unsigned char info_pck[] = INFO_PCK; static Dc20Info * get_info (int fd) { unsigned char buf[256]; if (send_pck (fd, info_pck) == -1) { DBG (2, "get_info: error: send_pck returned -1\n"); return NULL; } DBG (9, "get_info: read info packet\n"); if (read_data (fd, buf, 256) == -1) { DBG (2, "get_info: error: read_data returned -1\n"); return NULL; } if (end_of_data (fd) == -1) { DBG (2, "get_info: error: end_of_data returned -1\n"); return NULL; } CameraInfo.model = buf[1]; CameraInfo.ver_major = buf[2]; CameraInfo.ver_minor = buf[3]; CameraInfo.pic_taken = buf[8] << 8 | buf[9]; if (CameraInfo.model == 0x25) { /* Not sure where the previous line came from. All the * information I have says that even on the DC20 the number of * standard res pics is in byte 17 and the number of high res pics * is in byte 19. This is definitely true on my DC25. */ CameraInfo.pic_taken = buf[17] + buf[19]; } image_range.max = CameraInfo.pic_taken; image_range.min = CameraInfo.pic_taken ? 1 : 0; CameraInfo.pic_left = buf[10] << 8 | buf[11]; if (CameraInfo.model == 0x25) { /* Not sure where the previous line came from. All the * information I have says that even on the DC20 the number of * standard res pics left is in byte 23 and the number of high res * pics left is in byte 21. It seems to me that the conservative * approach is to report the number of high res pics left. */ CameraInfo.pic_left = buf[21]; } CameraInfo.flags.low_res = buf[23]; if (CameraInfo.model == 0x25) { /* Not sure where the previous line came from. All the * information I have says that even on the DC20 the low_res * byte is 11. */ CameraInfo.flags.low_res = buf[11]; } CameraInfo.flags.low_batt = buf[29]; return &CameraInfo; } static int read_data (int fd, unsigned char *buf, int sz) { unsigned char ccsum; unsigned char rcsum; unsigned char c; int retries = 0; int n; int r = 0; int i; while (retries++ < 5) { /* * If this is not the first time through, then it must be * a retry - signal the camera that we didn't like what * we got. In either case, start filling the packet */ if (retries != 1) { DBG (2, "Attempt retry %d\n", retries); c = 0xe3; if (write (fd, (char *) &c, 1) != 1) { DBG (2, "read_data: error: write ack\n"); return -1; } } for (n = 0; n < sz && (r = read (fd, (char *) &buf[n], sz - n)) > 0; n += r) ; if (r <= 0) { DBG (2, "read_data: error: read returned -1\n"); continue; } if (n < sz || read (fd, &rcsum, 1) != 1) { DBG (2, "read_data: error: buffer underrun or no checksum\n"); continue; } for (i = 0, ccsum = 0; i < n; i++) ccsum ^= buf[i]; if (ccsum != rcsum) { DBG (2, "read_data: error: bad checksum (%02x != %02x)\n", rcsum, ccsum); continue; } /* If we got this far, then the packet is OK */ break; } c = 0xd2; if (write (fd, (char *) &c, 1) != 1) { DBG (2, "read_data: error: write ack\n"); return -1; } return 0; } static int end_of_data (int fd) { char c; if (read (fd, &c, 1) != 1) { DBG (2, "end_of_data: error: read returned -1\n"); return -1; } if (c != 0) { DBG (2, "end_of_data: error: bad EOD from camera (%02x)\n", (unsigned) c); return -1; } return 0; } #include #define BIDIM_ARRAY(name, x, y, width) (name[((x) + ((y) * (width)))]) /* * These definitions depend on the resolution of the image */ #define MY_LOW_RIGHT_MARGIN 6 /* * These definitions are constant with resolution */ #define MY_LEFT_MARGIN 2 #define NET_COLUMNS (columns - MY_LEFT_MARGIN - right_margin) #define NET_LINES (HEIGHT - TOP_MARGIN - BOTTOM_MARGIN) #define NET_PIXELS (NET_COLUMNS * NET_LINES) #define SCALE 64 #define SMAX (256 * SCALE - 1) #define HORIZONTAL_INTERPOLATIONS 3 #define HISTOGRAM_STEPS 4096 #define RFACTOR 0.64 #define GFACTOR 0.58 #define BFACTOR 1.00 #define RINTENSITY 0.476 #define GINTENSITY 0.299 #define BINTENSITY 0.175 #define SATURATION 1.0 #define NORM_PERCENTAGE 3 static int columns = HIGH_WIDTH, right_margin = HIGH_RIGHT_MARGIN, camera_header_size = HIGH_CAMERA_HEADER; static int low_i = -1, high_i = -1, norm_percentage = NORM_PERCENTAGE; static float saturation = SATURATION, rfactor = RFACTOR, gfactor = GFACTOR, bfactor = BFACTOR; static void set_initial_interpolation (const unsigned char ccd[], short horizontal_interpolation[]) { int column, line; for (line = 0; line < HEIGHT; line++) { BIDIM_ARRAY (horizontal_interpolation, MY_LEFT_MARGIN, line, columns) = BIDIM_ARRAY (ccd, MY_LEFT_MARGIN + 1, line, columns) * SCALE; BIDIM_ARRAY (horizontal_interpolation, columns - right_margin - 1, line, columns) = BIDIM_ARRAY (ccd, columns - right_margin - 2, line, columns) * SCALE; for (column = MY_LEFT_MARGIN + 1; column < columns - right_margin - 1; column++) { BIDIM_ARRAY (horizontal_interpolation, column, line, columns) = (BIDIM_ARRAY (ccd, column - 1, line, columns) + BIDIM_ARRAY (ccd, column + 1, line, columns)) * (SCALE / 2); } } } static void interpolate_horizontally (const unsigned char ccd[], short horizontal_interpolation[]) { int column, line, i, initial_column; for (line = TOP_MARGIN - 1; line < HEIGHT - BOTTOM_MARGIN + 1; line++) { for (i = 0; i < HORIZONTAL_INTERPOLATIONS; i++) { for (initial_column = MY_LEFT_MARGIN + 1; initial_column <= MY_LEFT_MARGIN + 2; initial_column++) { for (column = initial_column; column < columns - right_margin - 1; column += 2) { BIDIM_ARRAY (horizontal_interpolation, column, line, columns) = ((float) BIDIM_ARRAY (ccd, column - 1, line, columns) / BIDIM_ARRAY (horizontal_interpolation, column - 1, line, columns) + (float) BIDIM_ARRAY (ccd, column + 1, line, columns) / BIDIM_ARRAY (horizontal_interpolation, column + 1, line, columns)) * BIDIM_ARRAY (ccd, column, line, columns) * (SCALE * SCALE / 2) + 0.5; } } } } } static void interpolate_vertically (const unsigned char ccd[], const short horizontal_interpolation[], short red[], short green[], short blue[]) { int column, line; for (line = TOP_MARGIN; line < HEIGHT - BOTTOM_MARGIN; line++) { for (column = MY_LEFT_MARGIN; column < columns - right_margin; column++) { int r2gb, g2b, rg2, rgb2, r, g, b; int this_ccd = BIDIM_ARRAY (ccd, column, line, columns) * SCALE; int up_ccd = BIDIM_ARRAY (ccd, column, line - 1, columns) * SCALE; int down_ccd = BIDIM_ARRAY (ccd, column, line + 1, columns) * SCALE; int this_horizontal_interpolation = BIDIM_ARRAY (horizontal_interpolation, column, line, columns); int this_intensity = this_ccd + this_horizontal_interpolation; int up_intensity = BIDIM_ARRAY (horizontal_interpolation, column, line - 1, columns) + up_ccd; int down_intensity = BIDIM_ARRAY (horizontal_interpolation, column, line + 1, columns) + down_ccd; int this_vertical_interpolation; /* * PSF: I don't understand all this code, but I've found pictures * where up_intensity or down_intensity are zero, resulting in a * divide by zero error. It looks like this only happens when * up_ccd or down_ccd are also zero, so we just set the intensity * value to non-zero to prevent the error. */ if (down_ccd == 0) DBG (10, "down_ccd==0 at %d,%d\n", line, column); if (up_ccd == 0) DBG (10, "up_ccd==0 at %d,%d\n", line, column); if (down_intensity == 0) { DBG (9, "Found down_intensity==0 at %d,%d down_ccd=%d\n", line, column, down_ccd); down_intensity = 1; } if (up_intensity == 0) { DBG (9, "Found up_intensity==0 at %d,%d up_ccd=%d\n", line, column, up_ccd); up_intensity = 1; } if (line == TOP_MARGIN) { this_vertical_interpolation = (float) down_ccd / down_intensity * this_intensity + 0.5; } else if (line == HEIGHT - BOTTOM_MARGIN - 1) { this_vertical_interpolation = (float) up_ccd / up_intensity * this_intensity + 0.5; } else { this_vertical_interpolation = ((float) up_ccd / up_intensity + (float) down_ccd / down_intensity) * this_intensity / 2.0 + 0.5; } if (line & 1) { if (column & 1) { r2gb = this_ccd; g2b = this_horizontal_interpolation; rg2 = this_vertical_interpolation; r = (2 * (r2gb - g2b) + rg2) / 5; g = (rg2 - r) / 2; b = g2b - 2 * g; } else { g2b = this_ccd; r2gb = this_horizontal_interpolation; rgb2 = this_vertical_interpolation; r = (3 * r2gb - g2b - rgb2) / 5; g = 2 * r - r2gb + g2b; b = g2b - 2 * g; } } else { if (column & 1) { rg2 = this_ccd; rgb2 = this_horizontal_interpolation; r2gb = this_vertical_interpolation; b = (3 * rgb2 - r2gb - rg2) / 5; g = (rgb2 - r2gb + rg2 - b) / 2; r = rg2 - 2 * g; } else { rgb2 = this_ccd; rg2 = this_horizontal_interpolation; g2b = this_vertical_interpolation; b = (g2b - 2 * (rg2 - rgb2)) / 5; g = (g2b - b) / 2; r = rg2 - 2 * g; } } if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; BIDIM_ARRAY (red, column, line, columns) = r; BIDIM_ARRAY (green, column, line, columns) = g; BIDIM_ARRAY (blue, column, line, columns) = b; } } } static void adjust_color_and_saturation (short red[], short green[], short blue[]) { int line, column; int r_min = SMAX, g_min = SMAX, b_min = SMAX; int r_max = 0, g_max = 0, b_max = 0; int r_sum = 0, g_sum = 0, b_sum = 0; float sqr_saturation = sqrt (saturation); for (line = TOP_MARGIN; line < HEIGHT - BOTTOM_MARGIN; line++) { for (column = MY_LEFT_MARGIN; column < columns - right_margin; column++) { float r = BIDIM_ARRAY (red, column, line, columns) * rfactor; float g = BIDIM_ARRAY (green, column, line, columns) * gfactor; float b = BIDIM_ARRAY (blue, column, line, columns) * bfactor; if (saturation != 1.0) { float *min, *mid, *max, new_intensity; float intensity = r * RINTENSITY + g * GINTENSITY + b * BINTENSITY; if (r > g) { if (r > b) { max = &r; if (g > b) { min = &b; mid = &g; } else { min = &g; mid = &b; } } else { min = &g; mid = &r; max = &b; } } else { if (g > b) { max = &g; if (r > b) { min = &b; mid = &r; } else { min = &r; mid = &b; } } else { min = &r; mid = &g; max = &b; } } *mid = *min + sqr_saturation * (*mid - *min); *max = *min + saturation * (*max - *min); new_intensity = r * RINTENSITY + g * GINTENSITY + b * BINTENSITY; r *= intensity / new_intensity; g *= intensity / new_intensity; b *= intensity / new_intensity; } r += 0.5; g += 0.5; b += 0.5; if (r_min > r) r_min = r; if (g_min > g) g_min = g; if (b_min > b) b_min = b; if (r_max < r) r_max = r; if (g_max < g) g_max = g; if (b_max < b) b_max = b; r_sum += r; g_sum += g; b_sum += b; BIDIM_ARRAY (red, column, line, columns) = r; BIDIM_ARRAY (green, column, line, columns) = g; BIDIM_ARRAY (blue, column, line, columns) = b; } } } static int min3 (int x, int y, int z) { return (x < y ? (x < z ? x : z) : (y < z ? y : z)); } static int max3 (int x, int y, int z) { return (x > y ? (x > z ? x : z) : (y > z ? y : z)); } static void determine_limits (const short red[], const short green[], const short blue[], int *low_i_ptr, int *high_i_ptr) { unsigned int histogram[HISTOGRAM_STEPS + 1]; int column, line, i, s; int low_i = *low_i_ptr, high_i = *high_i_ptr; int max_i = 0; for (line = TOP_MARGIN; line < HEIGHT - BOTTOM_MARGIN; line++) { for (column = MY_LEFT_MARGIN; column < columns - right_margin; column++) { i = max3 (BIDIM_ARRAY (red, column, line, columns), BIDIM_ARRAY (green, column, line, columns), BIDIM_ARRAY (blue, column, line, columns)); if (i > max_i) max_i = i; } } if (low_i == -1) { for (i = 0; i <= HISTOGRAM_STEPS; i++) histogram[i] = 0; for (line = TOP_MARGIN; line < HEIGHT - BOTTOM_MARGIN; line++) { for (column = MY_LEFT_MARGIN; column < columns - right_margin; column++) { i = min3 (BIDIM_ARRAY (red, column, line, columns), BIDIM_ARRAY (green, column, line, columns), BIDIM_ARRAY (blue, column, line, columns)); histogram[i * HISTOGRAM_STEPS / max_i]++; } } for (low_i = 0, s = 0; low_i <= HISTOGRAM_STEPS && s < NET_PIXELS * norm_percentage / 100; low_i++) { s += histogram[low_i]; } low_i = (low_i * max_i + HISTOGRAM_STEPS / 2) / HISTOGRAM_STEPS; *low_i_ptr = low_i; } if (high_i == -1) { for (i = 0; i <= HISTOGRAM_STEPS; i++) histogram[i] = 0; for (line = TOP_MARGIN; line < HEIGHT - BOTTOM_MARGIN; line++) { for (column = MY_LEFT_MARGIN; column < columns - right_margin; column++) { i = max3 (BIDIM_ARRAY (red, column, line, columns), BIDIM_ARRAY (green, column, line, columns), BIDIM_ARRAY (blue, column, line, columns)); histogram[i * HISTOGRAM_STEPS / max_i]++; } } for (high_i = HISTOGRAM_STEPS, s = 0; high_i >= 0 && s < NET_PIXELS * norm_percentage / 100; high_i--) { s += histogram[high_i]; } high_i = (high_i * max_i + HISTOGRAM_STEPS / 2) / HISTOGRAM_STEPS; *high_i_ptr = high_i; } /* if (verbose) printf ("%s: determine_limits: low_i = %d, high_i = %d\n", __progname, low_i, high_i); */ } /* * The original dc20ctrl program used a default gamma of 0.35, but I thougt * 0.45 looks better. In addition, since xscanimage seems to always force * a resolution of 0.1, I multiply everything by 10 and make the default * 4.5. */ static unsigned char * make_gamma_table (int range) { int i; double factor = pow (256.0, 1.0 / (SANE_UNFIX (dc25_opt_gamma) / 10.0)) / range; unsigned char *gamma_table; if ((gamma_table = malloc (range * sizeof (unsigned char))) == NULL) { DBG (1, "make_gamma_table: can't allocate memory for gamma table\n"); return NULL; } for (i = 0; i < range; i++) { int g = pow ((double) i * factor, (SANE_UNFIX (dc25_opt_gamma) / 10.0)) + 0.5; /* if (verbose) fprintf (stderr, "%s: make_gamma_table: gamma[%4d] = %3d\n", __progname, i, g); */ if (g > 255) g = 255; gamma_table[i] = g; } return gamma_table; } static int lookup_gamma_table (int i, int low_i, int high_i, const unsigned char gamma_table[]) { if (i <= low_i) return 0; if (i >= high_i) return 255; return gamma_table[i - low_i]; } static int output_rgb (const short red[], const short green[], const short blue[], int low_i, int high_i, struct pixmap *pp) { int r_min = 255, g_min = 255, b_min = 255; int r_max = 0, g_max = 0, b_max = 0; int r_sum = 0, g_sum = 0, b_sum = 0; int column, line; unsigned char *gamma_table = make_gamma_table (high_i - low_i); if (gamma_table == NULL) { DBG (10, "output_rgb: error: cannot make gamma table\n"); return -1; } for (line = TOP_MARGIN; line < HEIGHT - BOTTOM_MARGIN; line++) { for (column = MY_LEFT_MARGIN; column < columns - right_margin; column++) { int r = lookup_gamma_table (BIDIM_ARRAY (red, column, line, columns), low_i, high_i, gamma_table); int g = lookup_gamma_table (BIDIM_ARRAY (green, column, line, columns), low_i, high_i, gamma_table); int b = lookup_gamma_table (BIDIM_ARRAY (blue, column, line, columns), low_i, high_i, gamma_table); if (r > 255) r = 255; else if (r < 0) r = 0; if (g > 255) g = 255; else if (g < 0) g = 0; if (b > 255) b = 255; else if (b < 0) b = 0; set_pixel_rgb (pp, column - MY_LEFT_MARGIN, line - TOP_MARGIN, r, g, b); if (r_min > r) r_min = r; if (g_min > g) g_min = g; if (b_min > b) b_min = b; if (r_max < r) r_max = r; if (g_max < g) g_max = g; if (b_max < b) b_max = b; r_sum += r; g_sum += g; b_sum += b; } } free (gamma_table); /* { fprintf (stderr, "%s: output_rgb: r: min = %d, max = %d, ave = %d\n", __progname, r_min, r_max, r_sum / NET_PIXELS); fprintf (stderr, "%s: output_rgb: g: min = %d, max = %d, ave = %d\n", __progname, g_min, g_max, g_sum / NET_PIXELS); fprintf (stderr, "%s: output_rgb: b: min = %d, max = %d, ave = %d\n", __progname, b_min, b_max, b_sum / NET_PIXELS); } */ return 0; } static int comet_to_pixmap (unsigned char *pic, struct pixmap *pp) { unsigned char *ccd; short *horizontal_interpolation, *red, *green, *blue; int retval = 0; if (pic == NULL) { DBG (1, "cmttoppm: error: no input image\n"); return -1; } if (pic[4] == 0x01) { /* Low resolution mode */ columns = LOW_WIDTH; right_margin = MY_LOW_RIGHT_MARGIN; camera_header_size = LOW_CAMERA_HEADER; } else { /* High resolution mode */ columns = HIGH_WIDTH; right_margin = HIGH_RIGHT_MARGIN; camera_header_size = HIGH_CAMERA_HEADER; } ccd = pic + camera_header_size; if ((horizontal_interpolation = malloc (sizeof (short) * HEIGHT * columns)) == NULL) { DBG (1, "cmttoppm: error: not enough memory for horizontal_interpolation\n"); return -1; } if ((red = malloc (sizeof (short) * HEIGHT * columns)) == NULL) { DBG (1, "error: not enough memory for red\n"); return -1; } if ((green = malloc (sizeof (short) * HEIGHT * columns)) == NULL) { DBG (1, "error: not enough memory for green\n"); return -1; } if ((blue = malloc (sizeof (short) * HEIGHT * columns)) == NULL) { DBG (1, "error: not enough memory for blue\n"); return -1; } /* Decode raw CCD data to RGB */ set_initial_interpolation (ccd, horizontal_interpolation); interpolate_horizontally (ccd, horizontal_interpolation); interpolate_vertically (ccd, horizontal_interpolation, red, green, blue); adjust_color_and_saturation (red, green, blue); /* Determine lower and upper limit using histogram */ if (low_i == -1 || high_i == -1) { determine_limits (red, green, blue, &low_i, &high_i); } /* Output pixmap structure */ retval = output_rgb (red, green, blue, low_i, high_i, pp); return retval; } static int convert_pic (char *base_name, int format) { FILE *ifp; unsigned char pic[MAX_IMAGE_SIZE]; int res, image_width, net_width, components; struct pixmap *pp2; DBG (127, "convert_pic() called\n"); /* * Read the image in memory */ if ((ifp = fopen (base_name, "rb")) == NULL) { DBG (10, "convert_pic: error: cannot open %s for reading\n", base_name); return -1; } if (fread (pic, COMET_HEADER_SIZE, 1, ifp) != 1) { DBG (10, "convert_pic: error: cannot read COMET header\n"); fclose (ifp); return -1; } if (strncmp ((char *) pic, COMET_MAGIC, sizeof (COMET_MAGIC)) != 0) { DBG (10, "convert_pic: error: file %s is not in COMET format\n", base_name); fclose (ifp); return -1; } if (fread (pic, LOW_CAMERA_HEADER, 1, ifp) != 1) { DBG (10, "convert_pic: error: cannot read camera header\n"); fclose (ifp); return -1; } res = pic[4]; if (res == 0) { /* * We just read a LOW_CAMERA_HEADER block, so resync with the * HIGH_CAMERA_HEADER length by reading once more one of this. */ if (fread (pic + LOW_CAMERA_HEADER, LOW_CAMERA_HEADER, 1, ifp) != 1) { DBG (10, "convert_pic: error: cannot resync with high resolution header\n"); fclose (ifp); return -1; } } if (fread (pic + CAMERA_HEADER (res), WIDTH (res), HEIGHT, ifp) != HEIGHT) { DBG (9, "convert_pic: error: cannot read picture\n"); fclose (ifp); return -1; } fclose (ifp); /* * Setup image size with resolution */ image_width = WIDTH (res); net_width = image_width - LEFT_MARGIN - RIGHT_MARGIN (res); components = (format & SAVE_24BITS) ? 3 : 1; /* * Convert the image to 24 bits */ if ((pp = alloc_pixmap (net_width - 1, HEIGHT - BOTTOM_MARGIN - 1, components)) == NULL) { DBG (1, "convert_pic: error: alloc_pixmap\n"); return -1; } comet_to_pixmap (pic, pp); if (format & SAVE_ADJASPECT) { /* * Strech image */ if (res) pp2 = alloc_pixmap (320, HEIGHT - BOTTOM_MARGIN - 1, components); else pp2 = alloc_pixmap (net_width - 1, 373, components); if (pp2 == NULL) { DBG (2, "convert_pic: error: alloc_pixmap\n"); free_pixmap (pp); return -1; } if (res) zoom_x (pp, pp2); else zoom_y (pp, pp2); free_pixmap (pp); pp = pp2; pp2 = NULL; } return 0; } #define PGM_EXT "pgm" #define PPM_EXT "ppm" #define RED 0.30 #define GREEN 0.59 #define BLUE 0.11 #define RED_OFFSET 0 #define GREEN_OFFSET 1 #define BLUE_OFFSET 2 #define GET_COMP(pp, x, y, c) (pp->planes[((x) + (y)*pp->width)*pp->components + (c)]) #define GET_R(pp, x, y) (GET_COMP(pp, x, y, RED_OFFSET)) #define GET_G(pp, x, y) (GET_COMP(pp, x, y, GREEN_OFFSET)) #define GET_B(pp, x, y) (GET_COMP(pp, x, y, BLUE_OFFSET)) static struct pixmap * alloc_pixmap (int x, int y, int d) { struct pixmap *result = NULL; if (d == 1 || d == 3) { if (x > 0) { if (y > 0) { if ((result = malloc (sizeof (struct pixmap))) != NULL) { result->width = x; result->height = y; result->components = d; if (!(result->planes = malloc (x * y * d))) { DBG (10, "alloc_pixmap: error: not enough memory for bitplanes\n"); free (result); result = NULL; } } else DBG (10, "alloc_pixmap: error: not enough memory for pixmap\n"); } else DBG (10, "alloc_pixmap: error: y is out of range\n"); } else DBG (10, "alloc_pixmap: error: x is out of range\n"); } else DBG (10, "alloc_pixmap: error: cannot handle %d components\n", d); return result; } static void free_pixmap (struct pixmap *p) { if (p) { free (p->planes); free (p); } } static int set_pixel_rgb (struct pixmap *p, int x, int y, unsigned char r, unsigned char g, unsigned char b) { int result = 0; if (p) { if (x >= 0 && x < p->width) { if (y >= 0 && y < p->height) { if (p->components == 1) { GET_R (p, x, y) = RED * r + GREEN * g + BLUE * b; } else { GET_R (p, x, y) = r; GET_G (p, x, y) = g; GET_B (p, x, y) = b; } } else { DBG (10, "set_pixel_rgb: error: y out of range\n"); result = -1; } } else { DBG (10, "set_pixel_rgb: error: x out of range\n"); result = -1; } } return result; } static int zoom_x (struct pixmap *source, struct pixmap *dest) { int result = 0, dest_col, row, component, src_index; float ratio, src_ptr, delta; unsigned char src_component; if (source && dest) { /* * We could think of resizing a pixmap and changing the number of * components at the same time. Maybe this will be implemented later. */ if (source->height == dest->height && source->components == dest->components) { if (source->width < dest->width) { ratio = ((float) source->width / (float) dest->width); for (src_ptr = 0, dest_col = 0; dest_col < dest->width; src_ptr += ratio, dest_col++) { /* * dest[dest_col] = source[(int)src_ptr] + * (source[((int)src_ptr) + 1] - source[(int)src_ptr]) * * (src_ptr - (int)src_ptr); */ src_index = (int) src_ptr; delta = src_ptr - src_index; for (row = 0; row < source->height; row++) { for (component = 0; component < source->components; component++) { src_component = GET_COMP (source, src_index, row, component); GET_COMP (dest, dest_col, row, component) = src_component + (GET_COMP (source, src_index + 1, row, component) - src_component) * delta; } } } } else { DBG (10, "zoom_x: error: can only zoom out\n"); result = -1; } } else { DBG (10, "zoom_x: error: incompatible pixmaps\n"); result = -1; } } return result; } static int zoom_y (struct pixmap *source, struct pixmap *dest) { int result = 0, dest_row, column, component, src_index; float ratio, src_ptr, delta; unsigned char src_component; if (source && dest) { /* * We could think of resizing a pixmap and changing the number of * components at the same time. Maybe this will be implemented later. */ if (source->width == dest->width && source->components == dest->components) { if (source->height < dest->height) { ratio = ((float) source->height / (float) dest->height); for (src_ptr = 0, dest_row = 0; dest_row < dest->height; src_ptr += ratio, dest_row++) { /* * dest[dest_row] = source[(int)src_ptr] + * (source[((int)src_ptr) + 1] - source[(int)src_ptr]) * * (src_ptr - (int)src_ptr); */ src_index = (int) src_ptr; delta = src_ptr - src_index; for (column = 0; column < source->width; column++) { for (component = 0; component < source->components; component++) { src_component = GET_COMP (source, column, src_index, component); GET_COMP (dest, column, dest_row, component) = src_component + (GET_COMP (source, column, src_index + 1, component) - src_component) * delta; } } } } else { DBG (10, "zoom_y: error: can only zoom out\n"); result = -1; } } else { DBG (10, "zoom_y: error: incompatible pixmaps\n"); result = -1; } } return result; } static unsigned char shoot_pck[] = SHOOT_PCK; static int shoot (int fd) { struct termios tty_temp, tty_old; int result = 0; DBG (127, "shoot() called\n"); if (write (fd, (char *) shoot_pck, 8) != 8) { DBG (3, "shoot: error: write error\n"); return -1; } if (CameraInfo.model != 0x25) { /* * WARNING: now we set the serial port to 9600 baud! */ if (tcgetattr (fd, &tty_old) == -1) { DBG (3, "shoot: error: could not get attributes\n"); return -1; } memcpy ((char *) &tty_temp, (char *) &tty_old, sizeof (struct termios)); cfsetispeed (&tty_temp, B9600); cfsetospeed (&tty_temp, B9600); /* * Apparently there is a bug in the DC20 where the response to * the shoot request is always at 9600. The DC25 does not have * this bug, so we skip this block. */ if (tcsetattr (fd, TCSANOW, &tty_temp) == -1) { DBG (3, "shoot: error: could not set attributes\n"); return -1; } } if (read (fd, (char *) &result, 1) != 1) { DBG (3, "shoot: error: read returned -1\n"); result = -1; } else { result = (result == 0xD1) ? 0 : -1; } if (CameraInfo.model != 0x25) { /* * We reset the serial to its original speed. * We can skip this on the DC25 also. */ if (tcsetattr (fd, TCSANOW, &tty_old) == -1) { DBG (3, "shoot: error: could not reset attributes\n"); result = -1; } } if (result == 0) { if (CameraInfo.model == 0x25) { /* * If we don't put this in, the next read will time out * and return failure. Does the DC-20 need it too? */ sleep (3); } if (end_of_data (fd) == -1) { DBG (3, "shoot: error: end_of_data returned -1\n"); result = -1; } } return result; } static unsigned char erase_pck[] = ERASE_PCK; static int erase (int fd) { int count = 0; DBG (127, "erase() called for image %d\n", dc25_opt_image_number); erase_pck[3] = dc25_opt_image_number; if (dc25_opt_erase) { erase_pck[3] = 0; } if (send_pck (fd, erase_pck) == -1) { DBG (3, "erase: error: send_pck returned -1\n"); return -1; } if (CameraInfo.model == 0x25) { /* * This block may really apply to the DC20 also, but since I * don't have one, it's hard to say for sure. On the DC25, erase * takes long enought that the read may timeout without returning * any data before the erase is complete. We let this happen * up to 4 times, then give up. */ while (count < 4) { if (end_of_data (fd) == -1) { count++; } else { break; } } if (count == 4) { DBG (3, "erase: error: end_of_data returned -1\n"); return -1; } } else { /* Assume DC-20 */ if (end_of_data (fd) == -1) { DBG (3, "erase: error: end_of_data returned -1\n"); return -1; } } return 0; } static unsigned char res_pck[] = RES_PCK; static int change_res (int fd, unsigned char res) { DBG (127, "change_res called\n"); if (res != 0 && res != 1) { DBG (3, "change_res: error: unsupported resolution\n"); return -1; } res_pck[2] = res; if (send_pck (fd, res_pck) == -1) { DBG (4, "change_res: error: send_pck returned -1\n"); } if (end_of_data (fd) == -1) { DBG (4, "change_res: error: end_of_data returned -1\n"); } return 0; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { char dev_name[PATH_MAX], *p; size_t len; FILE *fp; int baud; strcpy (tty_name, DEF_TTY_NAME); DBG_INIT (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (DC25_CONFIG_FILE); DBG (127, "sane_init() $Id$\n"); if (!fp) { /* default to /dev/ttyS0 instead of insisting on config file */ DBG (1, "sane_init: missing config file '%s'\n", DC25_CONFIG_FILE); } else { while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { dev_name[sizeof (dev_name) - 1] = '\0'; DBG (20, "sane_init: config- %s", dev_name); if (dev_name[0] == '#') continue; /* ignore line comments */ len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ if (strncmp (dev_name, "port=", 5) == 0) { p = strchr (dev_name, '/'); if (p) { strcpy (tty_name, p); } DBG (20, "Config file port=%s\n", tty_name); } else if (strncmp (dev_name, "baud=", 5) == 0) { baud = atoi (&dev_name[5]); switch (baud) { case 9600: tty_baud = B9600; break; case 19200: tty_baud = B19200; break; case 38400: tty_baud = B38400; break; #ifdef B57600 case 57600: tty_baud = B57600; break; #endif #ifdef B115200 case 115200: tty_baud = B115200; break; #endif default: DBG (20, "Unknown baud=%d\n", baud); tty_baud = DEFAULT_TTY_BAUD; break; } DBG (20, "Config file baud=%lu\n", (u_long) tty_baud); } else if (strcmp (dev_name, "dumpinquiry") == 0) { dumpinquiry = SANE_TRUE; } } fclose (fp); } if ((tfd = init_dc20 (tty_name, tty_baud)) == -1) { return SANE_STATUS_INVAL; } if ((dc20_info = get_info (tfd)) == NULL) { DBG (2, "error: could not get info\n"); close_dc20 (tfd); return SANE_STATUS_INVAL; } if (dumpinquiry) { DBG (0, "\nCamera information:\n~~~~~~~~~~~~~~~~~\n\n"); DBG (0, "Model...........: DC%x\n", dc20_info->model); DBG (0, "Firmware version: %d.%d\n", dc20_info->ver_major, dc20_info->ver_minor); DBG (0, "Pictures........: %d/%d\n", dc20_info->pic_taken, dc20_info->pic_taken + dc20_info->pic_left); DBG (0, "Resolution......: %s\n", dc20_info->flags.low_res ? "low" : "high"); DBG (0, "Battery state...: %s\n", dc20_info->flags.low_batt ? "low" : "good"); } if (CameraInfo.pic_taken == 0) { /* sod[DC25_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; */ image_range.min = 0; dc25_opt_image_number = 0; } else { /* sod[DC25_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; */ image_range.min = 1; } return SANE_STATUS_GOOD; } void sane_exit (void) { } /* Device select/open/close */ static const SANE_Device dev[] = { { "0", "Kodak", "DC-25", "still camera"}, }; SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { static const SANE_Device *devlist[] = { dev + 0, 0 }; DBG (127, "sane_get_devices called\n"); if (dc20_info == NULL) { return SANE_STATUS_INVAL; } *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { int i; DBG (127, "sane_open for device %s\n", devicename); if (!devicename[0]) { i = 0; } else { for (i = 0; i < NELEMS (dev); ++i) { if (strcmp (devicename, dev[i].name) == 0) { break; } } } if (i >= NELEMS (dev)) { return SANE_STATUS_INVAL; } if (is_open) { return SANE_STATUS_DEVICE_BUSY; } is_open = 1; *handle = MAGIC; if (dc20_info == NULL) { DBG (1, "No device info\n"); } if (tmpname == NULL) { tmpname = tmpnamebuf; if (mktemp (tmpname) == NULL) { DBG (1, "Unable to make temp file %s\n", tmpname); return SANE_STATUS_INVAL; } } DBG (3, "sane_open: pictures taken=%d\n", dc20_info->pic_taken); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { DBG (127, "sane_close called\n"); if (handle == MAGIC) is_open = 0; if (pp) { free_pixmap (pp); pp = NULL; } close_dc20 (tfd); DBG (127, "sane_close returning\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { if (handle != MAGIC || !is_open) return NULL; /* wrong device */ if (option < 0 || option >= NELEMS (sod)) return NULL; return &sod[option]; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { SANE_Int myinfo = info_flags; SANE_Status status; info_flags = 0; DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n", handle, sod[option].title, (action == SANE_ACTION_SET_VALUE ? "SET" : (action == SANE_ACTION_GET_VALUE ? "GET" : "SETAUTO")), value, (void *)info); if (handle != MAGIC || !is_open) return SANE_STATUS_INVAL; /* Unknown handle ... */ if (option < 0 || option >= NELEMS (sod)) return SANE_STATUS_INVAL; /* Unknown option ... */ switch (action) { case SANE_ACTION_SET_VALUE: status = sanei_constrain_value (sod + option, value, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (1, "Constraint error in control_option\n"); return status; } switch (option) { case DC25_OPT_IMAGE_NUMBER: dc25_opt_image_number = *(SANE_Word *) value; /* myinfo |= SANE_INFO_RELOAD_OPTIONS; */ break; case DC25_OPT_THUMBS: dc25_opt_thumbnails = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; if (dc25_opt_thumbnails) { /* * DC20 thumbnail are 80x60 grayscale, DC25 * thumbnails are color. */ parms.format = (CameraInfo.model == 0x25) ? SANE_FRAME_RGB : SANE_FRAME_GRAY; parms.bytes_per_line = 80 * 3; parms.pixels_per_line = 80; parms.lines = 60; } else { parms.format = SANE_FRAME_RGB; if (dc20_info->flags.low_res) { parms.bytes_per_line = 320 * 3; parms.pixels_per_line = 320; parms.lines = 243; } else { parms.bytes_per_line = 500 * 3; parms.pixels_per_line = 500; parms.lines = 373; } } break; case DC25_OPT_SNAP: dc25_opt_snap = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; if (dc25_opt_snap) { sod[DC25_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE; } else { sod[DC25_OPT_LOWRES].cap |= SANE_CAP_INACTIVE; } break; case DC25_OPT_LOWRES: dc25_opt_lowres = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; if (!dc25_opt_thumbnails) { parms.format = SANE_FRAME_RGB; if (dc20_info->flags.low_res) { parms.bytes_per_line = 320 * 3; parms.pixels_per_line = 320; parms.lines = 243; } else { parms.bytes_per_line = 500 * 3; parms.pixels_per_line = 500; parms.lines = 373; } } break; case DC25_OPT_CONTRAST: dc25_opt_contrast = *(SANE_Word *) value; break; case DC25_OPT_GAMMA: dc25_opt_gamma = *(SANE_Word *) value; break; case DC25_OPT_ERASE: dc25_opt_erase = !!*(SANE_Word *) value; /* * erase and erase_one are mutually exclusive. If * this one is turned on, the other must be off */ if (dc25_opt_erase && dc25_opt_erase_one) { dc25_opt_erase_one = SANE_FALSE; myinfo |= SANE_INFO_RELOAD_OPTIONS; } break; case DC25_OPT_ERASE_ONE: dc25_opt_erase_one = !!*(SANE_Word *) value; /* * erase and erase_one are mutually exclusive. If * this one is turned on, the other must be off */ if (dc25_opt_erase_one && dc25_opt_erase) { dc25_opt_erase = SANE_FALSE; myinfo |= SANE_INFO_RELOAD_OPTIONS; } break; case DC25_OPT_DEFAULT: dc25_opt_contrast = SANE_FIX (DC25_OPT_CONTRAST_DEFAULT); dc25_opt_gamma = SANE_FIX (DC25_OPT_GAMMA_DEFAULT); myinfo |= SANE_INFO_RELOAD_OPTIONS; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_GET_VALUE: switch (option) { case 0: *(SANE_Word *) value = NELEMS (sod); break; case DC25_OPT_IMAGE_NUMBER: *(SANE_Word *) value = dc25_opt_image_number; break; case DC25_OPT_THUMBS: *(SANE_Word *) value = dc25_opt_thumbnails; break; case DC25_OPT_SNAP: *(SANE_Word *) value = dc25_opt_snap; break; case DC25_OPT_LOWRES: *(SANE_Word *) value = dc25_opt_lowres; break; case DC25_OPT_CONTRAST: *(SANE_Word *) value = dc25_opt_contrast; break; case DC25_OPT_GAMMA: *(SANE_Word *) value = dc25_opt_gamma; break; case DC25_OPT_ERASE: *(SANE_Word *) value = dc25_opt_erase; break; case DC25_OPT_ERASE_ONE: *(SANE_Word *) value = dc25_opt_erase_one; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_AUTO: switch (option) { #if 0 case DC25_OPT_CONTRAST: dc25_opt_contrast = SANE_FIX (DC25_OPT_CONTRAST_DEFAULT); break; case DC25_OPT_GAMMA: dc25_opt_gamma = SANE_FIX (DC25_OPT_GAMMA_DEFAULT); break; #endif default: return SANE_STATUS_UNSUPPORTED; /* We are DUMB */ } } if (info) *info = myinfo; return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int rc = SANE_STATUS_GOOD; DBG (127, "sane_get_params called\n"); if (handle != MAGIC || !is_open) rc = SANE_STATUS_INVAL; /* Unknown handle ... */ *params = parms; return rc; } static unsigned char thumb_pck[] = THUMBS_PCK; static unsigned char pic_pck[] = PICS_PCK; static int bytes_in_buffer; static int bytes_read_from_buffer; static SANE_Byte buffer[1024]; static int total_bytes_read; static SANE_Bool started = SANE_FALSE; static int outbytes; SANE_Status sane_start (SANE_Handle handle) { int n, i; FILE *f; DBG (127, "sane_start called, handle=%lx\n", (u_long) handle); if (handle != MAGIC || !is_open || (dc25_opt_image_number == 0 && dc25_opt_snap == SANE_FALSE)) return SANE_STATUS_INVAL; /* Unknown handle ... */ if (started) { return SANE_STATUS_EOF; } if (dc25_opt_snap) { /* * Don't allow picture unless there is room in the * camera. */ if (CameraInfo.pic_left == 0) { DBG (3, "No room to store new picture\n"); return SANE_STATUS_INVAL; } /* * DC-20 can only change resolution when camer is empty. * DC-25 can do it any time. */ if (CameraInfo.model != 0x20 || CameraInfo.pic_taken == 0) { if (change_res (tfd, dc25_opt_lowres) == -1) { DBG (1, "Failed to set resolution\n"); return SANE_STATUS_INVAL; } } /* * Not sure why this delay is needed, but it seems to help: */ #ifdef HAVE_USLEEP usleep (10); #else sleep (1); #endif if (shoot (tfd) == -1) { DBG (1, "Failed to snap new picture\n"); return SANE_STATUS_INVAL; } else { info_flags |= SANE_INFO_RELOAD_OPTIONS; CameraInfo.pic_taken++; CameraInfo.pic_left--; dc25_opt_image_number = CameraInfo.pic_taken; if (image_range.min == 0) image_range.min = 1; image_range.max++; sod[DC25_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; } } if (dc25_opt_thumbnails) { /* * For thumbnails, we can do things right where we * start the download, and grab the first block * from the camera. The reamining blocks will be * fetched as necessary by sane_read(). */ thumb_pck[3] = (unsigned char) dc25_opt_image_number; if (send_pck (tfd, thumb_pck) == -1) { DBG (4, "sane_start: error: send_pck returned -1\n"); return SANE_STATUS_INVAL; } if (read_data (tfd, buffer, 1024) == -1) { DBG (4, "sane_start: read_data failed\n"); return SANE_STATUS_INVAL; } /* * DC20 thumbnail are 80x60 grayscale, DC25 * thumbnails are color. */ parms.format = (CameraInfo.model == 0x25) ? SANE_FRAME_RGB : SANE_FRAME_GRAY; parms.bytes_per_line = 80 * 3; /* 80 pixels, 3 colors */ parms.pixels_per_line = 80; parms.lines = 60; bytes_in_buffer = 1024; bytes_read_from_buffer = 0; } else { /* * We do something a little messy, and violates the SANE * philosophy. However, since it is fairly tricky to * convert the DC2x "comet" files on the fly, we read in * the entire data stream in sane_open(), and use convert_pic * to convert it to an in-memory pixpmap. Then when * sane_read() is called, we fill the requests from * memory. A good project for me (or some kind volunteer) * would be to rewrite this and move the actual download * to sane_read(). However, one argument for keeping it * this way is that the data comes down pretty fast, and * it helps to dedicate the processor to this task. We * might get serial port overruns if we try to do other * things at the same time. * * Also, as a side note, I was constantly getting serial * port overruns on a 90MHz pentium until I used hdparm * to set the "-u1" flag on the system drives. */ int fd; fd = open (tmpname, O_CREAT | O_EXCL | O_WRONLY, 0600); if (fd == -1) { DBG (0, "Unable to open tmp file\n"); return SANE_STATUS_INVAL; } f = fdopen (fd, "wb"); if (f == NULL) { DBG (0, "Unable to fdopen tmp file\n"); return SANE_STATUS_INVAL; } strcpy ((char *) buffer, COMET_MAGIC); fwrite (buffer, 1, COMET_HEADER_SIZE, f); pic_pck[3] = (unsigned char) dc25_opt_image_number; if (send_pck (tfd, pic_pck) == -1) { DBG (4, "sane_start: error: send_pck returned -1\n"); return SANE_STATUS_INVAL; } if (read_data (tfd, buffer, 1024) == -1) { DBG (5, "sane_start: read_data failed\n"); return SANE_STATUS_INVAL; } if (buffer[4] == 0) { /* hi-res image */ DBG (5, "sane_start: hi-res image\n"); n = 122; parms.bytes_per_line = 500 * 3; /* 3 colors */ parms.pixels_per_line = 500; parms.lines = 373; bytes_in_buffer = 1024; bytes_read_from_buffer = 0; } else { n = 61; DBG (5, "sane_start: low-res image\n"); parms.bytes_per_line = 320 * 3; /* 3 Colors */ parms.pixels_per_line = 320; parms.lines = 243; bytes_in_buffer = 1024; bytes_read_from_buffer = 0; } fwrite (buffer, 1, 1024, f); for (i = 1; i < n; i++) { if (read_data (tfd, buffer, 1024) == -1) { DBG (5, "sane_start: read_data failed\n"); return SANE_STATUS_INVAL; } fwrite (buffer, 1, 1024, f); } if (end_of_data (tfd) == -1) { fclose (f); DBG (4, "sane_open: end_of_data error\n"); return SANE_STATUS_INVAL; } else { fclose (f); if (convert_pic (tmpname, SAVE_ADJASPECT | SAVE_24BITS) == -1) { DBG (3, "sane_open: unable to convert\n"); return SANE_STATUS_INVAL; } unlink (tmpname); outbytes = 0; } } started = SANE_TRUE; total_bytes_read = 0; return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle __sane_unused__ handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { DBG (127, "sane_read called, maxlen=%d\n", max_length); if ( ! started ) { return SANE_STATUS_INVAL; } if (dc25_opt_thumbnails) { if (total_bytes_read == THUMBSIZE) { if (dc25_opt_erase || dc25_opt_erase_one) { if (erase (tfd) == -1) { DBG (1, "Failed to erase memory\n"); return SANE_STATUS_INVAL; } dc25_opt_erase = SANE_FALSE; dc25_opt_erase_one = SANE_FALSE; info_flags |= SANE_INFO_RELOAD_OPTIONS; if (get_info (tfd) == NULL) { DBG (2, "error: could not get info\n"); close_dc20 (tfd); return SANE_STATUS_INVAL; } DBG (10, "Call get_info!, image range=%d,%d\n", image_range.min, image_range.max); } return SANE_STATUS_EOF; } *length = 0; if (!(bytes_in_buffer - bytes_read_from_buffer)) { if (read_data (tfd, buffer, 1024) == -1) { DBG (5, "sane_read: read_data failed\n"); return SANE_STATUS_INVAL; } bytes_in_buffer = 1024; bytes_read_from_buffer = 0; } while (bytes_read_from_buffer < bytes_in_buffer && max_length && total_bytes_read < THUMBSIZE) { *data++ = buffer[bytes_read_from_buffer++]; (*length)++; max_length--; total_bytes_read++; } if (total_bytes_read == THUMBSIZE) { if (end_of_data (tfd) == -1) { DBG (4, "sane_read: end_of_data error\n"); return SANE_STATUS_INVAL; } else { return SANE_STATUS_GOOD; } } else { return SANE_STATUS_GOOD; } } else { int i; int filesize = parms.bytes_per_line * parms.lines; /* * If outbytes is zero, then this is the first time * we've been called, so update the contrast table. * The formula is something I came up with that has the * following prooperties: * 1) It's a smooth curve that provides the effect I wanted * (bright pixels are made brighter, dim pixels are made * dimmer) * 2) The contrast parameter can be adjusted to provide * different amounts of contrast. * 3) A parameter of 1.0 can be used to pass the data * through unchanged (but values around 1.75 look * a lot better */ if (outbytes == 0) { double d; double cont = SANE_UNFIX (dc25_opt_contrast); for (i = 0; i < 256; i++) { d = (i * 2.0) / 255 - 1.0; d = ((-pow (1 - d, cont)) + 1) * (d >= 0) + (((pow (d + 1, cont)) - 1)) * (d < 0); contrast_table[i] = (d * 127.5) + 127.5; /* fprintf (stderr,"%03d %03d\n",i,contrast_table[i]); */ } } /* We're done, so return EOF */ if (outbytes >= filesize) { free_pixmap (pp); pp = NULL; if (dc25_opt_erase || dc25_opt_erase_one) { if (erase (tfd) == -1) { DBG (1, "Failed to erase memory\n"); return SANE_STATUS_INVAL; } } if (get_info (tfd) == NULL) { DBG (2, "error: could not get info\n"); close_dc20 (tfd); return SANE_STATUS_INVAL; } DBG (10, "Call get_info!, image range=%d,%d\n", image_range.min, image_range.max); get_info (tfd); *length=0; return SANE_STATUS_EOF; } if (max_length > filesize - outbytes) { *length = filesize - outbytes; } else { *length = max_length; } memcpy (data, pp->planes + outbytes, *length); outbytes += *length; for (i = 0; i < *length; i++) { data[i] = contrast_table[data[i]]; } return SANE_STATUS_GOOD; } } void sane_cancel (SANE_Handle __sane_unused__ handle) { DBG (127, "sane_cancel() called\n"); started = SANE_FALSE; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { /* sane_set_io_mode() is only valid during a scan */ if (started) { if (non_blocking == SANE_FALSE) { return SANE_STATUS_GOOD; } else { return SANE_STATUS_UNSUPPORTED; } } else { /* We aren't currently scanning */ return SANE_STATUS_INVAL; } } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/microtek2.h0000664000175000017500000015551712775312261014705 00000000000000/******************************************************************************* * SANE - Scanner Access Now Easy. microtek2.h This file (C) 1998, 1999 Bernd Schroeder 2000, 2001 Karsten Festag This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software fOUNDATIOn, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *******************************************************************************/ #ifndef microtek2_h #define microtek2_h #include /******************************************************************************/ /* Miscellaneous defines */ /******************************************************************************/ #ifndef PATH_MAX # define PATH_MAX 1024 #endif #ifdef HAVE_AUTHORIZATION #ifndef PATH_SEP #if defined(_WIN32) || defined(HAVE_OS2_H) # define PATH_SEP "\\" #else # define PATH_SEP "/" #endif #endif #define MAX_LINE_LEN 512 /* max length of entry in password file */ #define PASSWD_FILE STRINGIFY(PATH_SANE_CONFIG_DIR) PATH_SEP "auth" #define SEPARATOR ':' /* separator in that file */ #define SALT "ab" /* used by crypt() */ #endif /* HAVE_AUTHORIZATION */ #define ENDIAN_TYPE(d) { unsigned i, test = 0; \ for (i=0; i < sizeof(int); i++ ) \ test += i << (8 * i); \ d = ((char *) &test)[0] == 0 ? 0 : 1; } #define MIN(a,b) ((a) < (b)) ? (a) : (b) #define MAX(a,b) ((a) > (b)) ? (a) : (b) #define MICROTEK2_MAJOR 0 #define MICROTEK2_MINOR 96 #define MICROTEK2_BUILD "200410042220" #define MICROTEK2_CONFIG_FILE "microtek2.conf" /******************************************************************************/ /* defines that are common to all devices */ /******************************************************************************/ #define MD_RESOLUTION_DEFAULT 72 << SANE_FIXED_SCALE_SHIFT #define MD_BRIGHTNESS_DEFAULT 100 << SANE_FIXED_SCALE_SHIFT #define MD_CONTRAST_DEFAULT 100 << SANE_FIXED_SCALE_SHIFT #define MD_THRESHOLD_DEFAULT 128 #define MD_GAMMA_DEFAULT SANE_FIX(2.2) #define MD_SHADOW_DEFAULT 0 #define MD_MIDTONE_DEFAULT 128 #define MD_HIGHLIGHT_DEFAULT 255 #define MD_EXPOSURE_DEFAULT 0 #define M_BRIGHTNESS_DEFAULT 128 #define M_CONTRAST_DEFAULT 128 #define M_SHADOW_DEFAULT 0 #define M_MIDTONE_DEFAULT 128 #define M_HIGHLIGHT_DEFAULT 255 #define M_EXPOSURE_DEFAULT 0 #define M_THRESHOLD_DEFAULT 128 /******************************************************************************/ /* SCSI commands used by the scanner */ /******************************************************************************/ /* INQUIRY */ #define INQ_CMD(d) d[0] = 0x12; d[1] = 0x00; d[2] = 0x00; \ d[3] = 0x00; d[4] = 0x00; d[5] = 0x00 #define INQ_CMD_L 6 #define INQ_ALLOC_L 5 /* first get 5 bytes */ #define INQ_ALLOC_P 4 #define INQ_SET_ALLOC(d,s) (d)[4] = (s) #define INQ_GET_INQLEN(d,s) d = (s)[4] #define INQ_GET_QUAL(d,s) d = ((s)[0] >> 5) & 0x07 #define INQ_GET_DEVT(d,s) d = (s)[0] & 0x1f #define INQ_GET_VERSION(d,s) d = (s)[2] & 0x02 #define INQ_VENDOR_L 8 #define INQ_GET_VENDOR(d,s) strncpy(d, &(s)[8], INQ_VENDOR_L); \ d[INQ_VENDOR_L] = '\0' #define INQ_MODEL_L 16 #define INQ_GET_MODEL(d,s) strncpy(d, &(s)[16], INQ_MODEL_L); \ d[INQ_MODEL_L] = '\0' #define INQ_REV_L 4 #define INQ_GET_REV(d,s) strncpy(d, &(s)[32], INQ_REV_L); \ d[INQ_REV_L] = '\0' #define INQ_GET_MODELCODE(d,s) d = (s)[36] /* TEST_UNIT_READY */ #define TUR_CMD(d) d[0]=0x00; d[1]=0x00; d[2]=0x00; \ d[3]=0x00; d[4]=0x00; d[5]=0x00 #define TUR_CMD_L 6 /* READ GAMMA TABLE */ #define RG_CMD(d) (d)[0] = 0x28; (d)[1] = 0x00; (d)[2] = 0x03; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x00; \ (d)[9] = 0x00 #define RG_CMD_L 10 #define RG_PCORMAC(d,p) (d)[5] |= (((p) << 7) & 0x80) #define RG_COLOR(d,p) (d)[5] |= (((p) << 5) & 0x60) #define RG_WORD(d,p) (d)[5] |= ((p) & 0x01) #define RG_TRANSFERLENGTH(d,p) (d)[7] = (((p) >> 8) & 0xff); \ (d)[8] = ((p) & 0xff) /* SEND GAMMA TABLE */ #define SG_SET_CMD(d) (d)[0] = 0x2a; (d)[1] = 0x00; (d)[2] = 0x03; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x00; \ (d)[9] = 0x00 #define SG_CMD_L 10 #define SG_SET_PCORMAC(d,p) (d)[5] |= (((p) << 7) & 0x80) #define SG_SET_COLOR(d,p) (d)[5] |= (((p) << 5) & 0x60) #define SG_SET_WORD(d,p) (d)[5] |= ((p) & 0x01) #define SG_SET_TRANSFERLENGTH(d,p) (d)[7] = (((p) >> 8) & 0xff); \ (d)[8] = ((p) & 0xff) #define SG_DATA_P SG_CMD_L /* READ CONTROL BITS */ #define RCB_SET_CMD(d) (d)[0] = 0x28; (d)[1] = 0x00; (d)[2] = 0x90; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x00; \ (d)[9] = 0x00 #define RCB_CMD_L 10 #define RCB_SET_LENGTH(d,s) (d)[6] = (((s) >> 16) & 0xff); \ (d)[7] = (((s) >> 8) & 0xff); \ (d)[8] = ((s) & 0xff); /* READ_SCANNER_ATTRIBUTES */ #define RSA_CMD(d) d[0]=0x28; d[1]=0x00; d[2]=0x82; d[3]=0x00; \ d[4]=0x00; d[5]=0x00; d[6]=0x00; d[7]=0x00; \ d[8]=0x28; d[9]=0x00 #define RSA_CMD_L 10 #define RSA_SETMEDIA(d,p) d[5] |= ((p) & 0x77) #define RSA_TRANSFERLENGTH 40 #define RSA_COLOR(d,s) d = (((s)[0] >> 7) & 0x01) #define RSA_ONEPASS(d,s) d = (((s)[0] >> 6) & 0x01) #define RSA_SCANNERTYPE(d,s) d = (((s)[0] >> 4) & 0x03) #define RSA_FEPROM(d,s) d = (((s)[0] >> 3) & 0x01) #define RSA_DATAFORMAT(d,s) d = ((s)[0] & 0x07) #define RSA_COLORSEQUENCE_L 3 #define RSA_COLORSEQUENCE(d,s) { \ d[0] = (((s)[1] >> 6) & 0x03); \ d[1] = (((s)[1] >> 4) & 0x03); \ d[2] = (((s)[1] >> 2) & 0x03); \ } #define RSA_NIS(d,s) d = ((s)[1] & 0x02) #define RSA_DATSEQ(d,s) d = ((s)[1] & 0x01) #define RSA_CCDGAP(d,s) d = (s)[2] #define RSA_MAX_XRESOLUTION(d,s) d = ((s)[3] << 8) + (s)[4] #define RSA_MAX_YRESOLUTION(d,s) d = ((s)[5] << 8) + (s)[6] #define RSA_GEOWIDTH(d,s) d = ((s)[7] << 8) + (s)[8] #define RSA_GEOHEIGHT(d,s) d = ((s)[9] << 8) + (s)[10] #define RSA_OPTRESOLUTION(d,s) d = ((s)[11] << 8) + (s)[12] #define RSA_DEPTH(d,s) d = (((s)[13] >> 4) & 0x0f) #define RSA_SCANMODE(d,s) d = (s)[13] & 0x0f #define RSA_CCDPIXELS(d,s) d = ((s)[14] << 8) + (s)[15] #define RSA_LUTCAP(d,s) d = (s)[16] #define RSA_DNLDPTRN(d,s) d = (((s)[17] >> 7) & 0x01) #define RSA_GRAINSLCT(d,s) d = (s)[17] & 0x7f #define RSA_SUPPOPT(d,s) d = (s)[18] & 0xf3 #define RSA_CALIBWHITE(d,s) d = ((s)[19] << 24) + ((s)[20] << 16) \ + ((s)[21] << 8) + (s)[22] #define RSA_CALIBSPACE(d,s) d = ((s)[23] << 24) + ((s)[24] << 16) \ + ((s)[25] << 8) + (s)[26] #define RSA_NLENS(d,s) d = (s)[27] #define RSA_NWINDOWS(d,s) d = (s)[28] #define RSA_SHTRNSFEREQU(d,s) d = (((s)[29] >> 2) & 0x3f) #define RSA_SCNBTTN(d,s) d = (((s)[29] >> 1) & 0x01) #define RSA_BUFTYPE(d,s) d = (s)[29] & 0x01 #define RSA_REDBALANCE(d,s) d = ((s)[30] << 8) | (s)[31] #define RSA_GREENBALANCE(d,s) d = ((s)[32] << 8) | (s)[33] #define RSA_BLUEBALANCE(d,s) d = ((s)[34] << 8) | (s)[35] #define RSA_APSMAXFRAMES(d,s) d = (s)[36] /* READ IMAGE INFORMATION */ #define RII_SET_CMD(d) (d)[0] = 0x28; (d)[1] = 0x00; (d)[2] = 0x80; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x10; \ (d)[9] = 0x00 #define RII_CMD_L 10 #define RII_RESULT_L 16 #define RII_GET_WIDTHPIXEL(d,s) d = ((s)[0] << 24) + ((s)[1] << 16) \ + ((s)[2] << 8) + (s)[3] #define RII_GET_WIDTHBYTES(d,s) d = ((s)[4] << 24) + ((s)[5] << 16) \ + ((s)[6] << 8) + (s)[7] #define RII_GET_HEIGHTLINES(d,s) d = ((s)[8] << 24) + ((s)[9] << 16) \ + ((s)[10] << 8) + (s)[11] #define RII_GET_REMAINBYTES(d,s) d = ((s)[12] << 24) + ((s)[13] << 16) \ + ((s)[14] << 8) + (s)[15] /* The V300 returns some values in only two bytes */ #define RII_GET_V300_WIDTHPIXEL(d,s) d = ((s)[0] << 8) + (s)[1] #define RII_GET_V300_WIDTHBYTES(d,s) d = ((s)[2] << 8) + (s)[3] #define RII_GET_V300_HEIGHTLINES(d,s) d = ((s)[4] << 8) + (s)[5] #define RII_GET_V300_REMAINBYTES(d,s) d = ((s)[6] << 24) + ((s)[7] << 16) \ + ((s)[8] << 8) + (s)[9] /* READ SHADING INFORMATION */ #define RSI_SET_CMD(d) (d)[0] = 0x28; (d)[1] = 0x00; (d)[2] = 0x01; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x10; \ (d)[9] = 0x00 #define RSI_CMD_L 10 #define RSI_SET_PCORMAC(d,s) (d)[5] |= (((s) << 7) & 0x80) #define RSI_SET_COLOR(d,s) (d)[5] |= (((s) << 5) & 0x60) #define RSI_SET_DARK(d,s) (d)[5] |= (((s) << 1) & 0x02) /*(KF)*/ /* RSI_SET_DARK was missing*/ #define RSI_SET_WORD(d,s) (d)[5] |= ((s) & 0x01) #define RSI_SET_TRANSFERLENGTH(d,s) (d)[6] = (((s) >> 16) & 0xff); \ (d)[7] = (((s) >> 8) & 0xff); \ (d)[8] = ((s) & 0xff); /* SEND SHADING INFORMATION */ #define SSI_SET_CMD(d) (d)[0] = 0x2a; (d)[1] = 0x00; (d)[2] = 0x01; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x00; \ (d)[9] = 0x00 #define SSI_CMD_L 10 #define SSI_SET_PCORMAC(d,s) (d)[5] |= (((s) << 7) & 0x80) #define SSI_SET_COLOR(d,s) (d)[5] |= (((s) << 5) & 0x60) #define SSI_SET_DARK(d,s) (d)[5] |= (((s) << 1) & 0x02) #define SSI_SET_WORD(d,s) (d)[5] |= ((s) & 0x01) #define SSI_SET_TRANSFERLENGTH(d,s) (d)[6] = (((s) >> 16) & 0xff); \ (d)[7] = (((s) >> 8) & 0xff); \ (d)[8] = ((s) & 0xff); /* READ IMAGE */ /* READ IMAGE */ #define RI_SET_CMD(d) (d)[0] = 0x28; (d)[1] = 0x00; (d)[2] = 0x00; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x00; \ (d)[9] = 0x00 #define RI_CMD_L 10 #define RI_SET_PCORMAC(d,s) (d)[4] |= (((s) << 7) & 0x80) #define RI_SET_COLOR(d,s) (d)[4] |= (((s) << 5) & 0x60) #define RI_SET_TRANSFERLENGTH(d,s) (d)[6] = (((s) >> 16) & 0xff); \ (d)[7] = (((s) >> 8) & 0xff); \ (d)[8] = ((s) & 0xff); /* READ SYSTEM_STATUS */ #define RSS_CMD(d) (d)[0] = 0x28; (d)[1] = 0x00; (d)[2] = 0x81; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x09; \ (d)[9] = 0x00 #define RSS_CMD_L 10 #define RSS_RESULT_L 9 #define RSS_FIRSTSCAN(s) (s)[0] & 0x80 #define RSS_AFOCUS(s) (s)[0] & 0x40 #define RSS_SSKIP(s) (s)[0] & 0x20 #define RSS_STICK(s) (s)[0] & 0x10 #define RSS_NTRACK(s) (s)[0] & 0x08 #define RSS_NCALIB(s) (s)[0] & 0x04 #define RSS_TLAMP(s) (s)[0] & 0x02 #define RSS_FLAMP(s) (s)[0] & 0x01 #define RSS_FSH(s) (s)[1] & 0x20 #define RSS_TEFLAG(s) (s)[1] & 0x10 #define RSS_WHITESTRIE(s) (s)[1] & 0x08 #define RSS_RDYMAN(s) (s)[1] & 0x04 #define RSS_TRDY(s) (s)[1] & 0x02 #define RSS_FRDY(s) (s)[1] & 0x01 #define RSS_ADP(s) (s)[2] & 0x80 #define RSS_DETECT(s) (s)[2] & 0x40 #define RSS_ADPTIME(s) (s)[2] & 0x3f #define RSS_LENSSTATUS(s) (s)[3] #define RSS_ALOFF(s) (s)[4] & 0x80 #define RSS_TIMEREMAIN(s) (s)[4] & 0x7f #define RSS_MTMACNT(s) (s)[5] & 0x40 #define RSS_MOVE(s) (s)[5] & 0x20 #define RSS_LAMP(s) (s)[5] & 0x10 #define RSS_EJECT(s) (s)[5] & 0x08 #define RSS_TMACNT(s) (s)[5] & 0x04 #define RSS_PAPER(s) (s)[5] & 0x02 #define RSS_ADFCNT(s) (s)[5] & 0x01 #define RSS_CANCELBTN(s) (s)[6] & 0x80 #define RSS_COPYBTN(s) (s)[6] & 0x40 #define RSS_EMAILBTN(s) (s)[6] & 0x20 #define RSS_GOBTN(s) (s)[6] & 0x10 #define RSS_TURBOBTN(s) (s)[6] & 0x08 #define RSS_CURRENTMODE(s) (s)[6] & 0x07 #define RSS_BUTTONCOUNT(s) (s)[7] #define RSS_MFOCUS(s) (s)[9] /* SEND SYSTEM STATUS */ #define SSS_CMD(d) (d)[0] = 0x2a; (d)[1] = 0x00; (d)[2] = 0x81; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x09; \ (d)[9] = 0x00 #define SSS_CMD_L 10 #define SSS_DATA_L 9 #define SSS_AFOCUS(d,p) d[0] |= (p) & 0x40 #define SSS_STICK(d,p) d[0] |= (p) & 0x10 #define SSS_NTRACK(d,p) d[0] |= (p) & 0x08 #define SSS_NCALIB(d,p) d[0] |= (p) & 0x04 #define SSS_TLAMP(d,p) d[0] |= (p) & 0x02 #define SSS_FLAMP(d,p) d[0] |= (p) & 0x01 #define SSS_RESERVED17(d,p) d[1] |= (p) & 0x80 #define SSS_FSH(d,p) d[1] |= (p) & 0x40 #define SSS_RDYMAN(d,p) d[1] |= (p) & 0x04 #define SSS_TRDY(d,p) d[1] |= (p) & 0x02 #define SSS_FRDY(d,p) d[1] |= (p) & 0x01 #define SSS_ADP(d,p) d[2] |= (p) & 0x80 #define SSS_DETECT(d,p) d[2] |= (p) & 0x40 #define SSS_ADPTIME(d,p) d[2] |= (p) & 0x3f #define SSS_LENSSTATUS(d,p) d[3] |= (p) #define SSS_ALOFF(d,p) d[4] |= (p) & 0x80 #define SSS_TIMEREMAIN(d,p) d[4] |= (p) & 0x7f #define SSS_TMACNT(d,p) d[5] |= (p) & 0x04 #define SSS_PAPER(d,p) d[5] |= (p) & 0x02 #define SSS_ADFCNT(d,p) d[5] |= (p) & 0x01 #define SSS_CURRENTMODE(d,p) d[6] |= (p) & 0x07 #define SSS_BUTTONCOUNT(d,p) d[6] |= (p) #define SSS_MFOCUS(s) d[9] |= (p) /* SET WINDOW */ #define SW_CMD(d) d[0]=0x24; d[1]=0x00; d[2]=0x00; d[3]=0x00; \ d[4]=0x00; d[5]=0x00; d[6]=0x00; d[7]=0x00;\ d[8]=0x00; d[9]=0x00 #define SW_CMD_L 10 #define SW_HEADER_L 8 #define SW_BODY_L 61 #define SW_CMD_P 0 /* command at postion 0 */ #define SW_HEADER_P SW_CMD_L #define SW_BODY_P(n) SW_CMD_L + SW_HEADER_L + (n) * SW_BODY_L /* d: SW_CMD_P, SW_HEADER_P, SW_BODY_P(n) */ #define SW_PARAM_LENGTH(d,p) (d)[6] = ((p) >> 16) & 0xff; \ (d)[7] = ((p) >> 8) & 0xff;\ (d)[8] = (p) & 0xff #define SW_WNDDESCVAL SW_BODY_L #define SW_WNDDESCLEN(d,p) (d)[6] = ((p) >> 8) & 0xff; \ (d)[7] = (p) & 0xff #define SW_WNDID(d,p) (d)[0] = (p) #define SW_XRESDPI(d,p) (d)[2] = ((p) >> 8) & 0xff; \ (d)[3] = (p) & 0xff #define SW_YRESDPI(d,p) (d)[4] = ((p) >> 8) & 0xff; \ (d)[5] = (p) & 0xff #define SW_XPOSTL(d,p) (d)[6] = ((p) >> 24) & 0xff; \ (d)[7] = ((p) >> 16) & 0xff; \ (d)[8] = ((p) >> 8) & 0xff; \ (d)[9] = ((p)) & 0xff #define SW_YPOSTL(d,p) (d)[10] = ((p) >> 24) & 0xff; \ (d)[11] = ((p) >> 16) & 0xff; \ (d)[12] = ((p) >> 8) & 0xff; \ (d)[13] = (p) & 0xff #define SW_WNDWIDTH(d,p) (d)[14] = ((p) >> 24) & 0xff; \ (d)[15] = ((p) >> 16) & 0xff; \ (d)[16] = ((p) >> 8) & 0xff; \ (d)[17] = (p) & 0xff #define SW_WNDHEIGHT(d,p) (d)[18] = ((p) >> 24) & 0xff; \ (d)[19] = ((p) >> 16) & 0xff; \ (d)[20] = ((p) >> 8) & 0xff; \ (d)[21] = (p) & 0xff #define SW_BRIGHTNESS_M(d,p) (d)[22] = (p) #define SW_THRESHOLD(d,p) (d)[23] = (p) #define SW_CONTRAST_M(d,p) (d)[24] = (p) #define SW_IMGCOMP(d,p) (d)[25] = (p) & 0x0f /* take lineartfake */ /* into account */ #define SW_BITSPERPIXEL(d,p) (d)[26] = (p) #define SW_EXPOSURE_M(d,p) (d)[27] = (p) #define SW_EXTHT(d,p) (d)[28] |= (((p) << 7) & 0x80) #define SW_INTHTINDEX(d,p) (d)[28] |= ((p) & 0x7f) #define SW_RIF(d,p) (d)[29] |= (((p) << 7) & 0x80) #define SW_NOGAMMA(d,p) (d)[29] |= (((p) << 6) & 0x40) #define SW_SLOWSCAN(d,p) (d)[29] |= (((p) << 5) & 0x20) #define SW_LENS(d,p) (d)[30] = (p) #define SW_INFINITE(d,p) (d)[31] |= (((p) << 7) & 0x80) #define SW_STAY(d,p) (d)[31] |= (((p) << 6) & 0x40) #define SW_RAWDAT(d,p) (d)[31] |= (((p) << 5) & 0x20) #define SW_QUALITY(d,p) (d)[31] |= (((p) << 4) & 0x10) #define SW_FASTSCAN(d,p) (d)[31] |= (((p) << 3) & 0x08) #define SW_MEDIA(d,p) (d)[31] |= ((p) & 0x07) #define SW_JPEGENABLE(d,p) (d)[34] |= (((p) << 7) & 0x80) #define SW_JPEGALGOR(d,p) (d)[34] |= (((p) << 5) & 0x60) #define SW_JPEGMODE(d,p) (d)[34] |= (((p) << 3) & 0x18) #define SW_SHADOW_M(d,p) (d)[40] = (p) #define SW_MIDTONE_M(d,p) (d)[41] = (p) #define SW_HIGHLIGHT_M(d,p) (d)[42] = (p) #define SW_BRIGHTNESS_R(d,p) (d)[43] = (p) #define SW_CONTRAST_R(d,p) (d)[44] = (p) #define SW_EXPOSURE_R(d,p) (d)[45] = (p) #define SW_SHADOW_R(d,p) (d)[46] = (p) #define SW_MIDTONE_R(d,p) (d)[47] = (p) #define SW_HIGHLIGHT_R(d,p) (d)[48] = (p) #define SW_BRIGHTNESS_G(d,p) (d)[49] = (p) #define SW_CONTRAST_G(d,p) (d)[50] = (p) #define SW_EXPOSURE_G(d,p) (d)[51] = (p) #define SW_SHADOW_G(d,p) (d)[52] = (p) #define SW_MIDTONE_G(d,p) (d)[53] = (p) #define SW_HIGHLIGHT_G(d,p) (d)[54] = (p) #define SW_BRIGHTNESS_B(d,p) (d)[55] = (p) #define SW_CONTRAST_B(d,p) (d)[56] = (p) #define SW_EXPOSURE_B(d,p) (d)[57] = (p) #define SW_SHADOW_B(d,p) (d)[58] = (p) #define SW_MIDTONE_B(d,p) (d)[59] = (p) #define SW_HIGHLIGHT_B(d,p) (d)[60] = (p) /* READ IMAGE STATUS */ #define RIS_SET_CMD(d) (d)[0] = 0x28; (d)[1] = 0x00; (d)[2] = 0x83; \ (d)[3] = 0x00; (d)[4] = 0x00; (d)[5] = 0x00; \ (d)[6] = 0x00; (d)[7] = 0x00; (d)[8] = 0x00; \ (d)[9] = 0x00 #define RIS_CMD_L 10 #define RIS_SET_PCORMAC(d,p) (d)[4] |= (((p) << 7) & 0x80) #define RIS_SET_COLOR(d,p) (d)[4] |= (((p) << 5) & 0x60) /* REQUEST SENSE */ #define RQS_CMD(d) (d)[0] = 0x03; (d)[1] = 0x00; (d)[2] = 0x00; \ (d)[3] = 0x00; (d)[5] = 0x00 #define RQS_CMD_L 6 #define RQS_ALLOCLENGTH(d,p) (d)[4] = (p) #define RQS_LENGTH(s) (s)[7] + 7 #define RQS_SENSEKEY_NOSENSE 0x00 #define RQS_SENSEKEY_HWERR 0x04 #define RQS_SENSEKEY_ILLEGAL 0x05 #define RQS_SENSEKEY_VENDOR 0x09 #define RQS_SENSEKEY(s) ((s)[2] & 0x0f) #define RQS_INFO(s) ((s)[3] << 24) + ((s)[4] << 16) \ + ((s)[5] << 8) + ((s)[6]) #define RQS_ASL(s) (s)[7] #define RQS_REMAINBYTES(s) ((s)[8] << 24) + ((s)[9] << 16) \ + ((s)[10] << 8) + ((s)[11]) #define RQS_ASC(s) (s)[12] /* ASC == 0x40 */ #define RQS_ASCQ_CPUERR 0x81 #define RQS_ASCQ_SRAMERR 0x82 #define RQS_ASCQ_DRAMERR 0x84 #define RQS_ASCQ_DCOFF 0x88 #define RQS_ASCQ_GAIN 0x90 #define RQS_ASCQ_POS 0xa0 #define RQS_ASCQ(s) (s)[13] #define RQS_ASINFO(s) &((s)[18]) #define RQS_ASINFOLENGTH(s) (s)[7] - 11 /******************************************************************************/ /* enumeration of Option Descriptors */ /******************************************************************************/ enum Microtek2_Option { /*0*/ OPT_NUM_OPTS = 0, /*1*/OPT_MODE_GROUP, OPT_SOURCE, OPT_MODE, OPT_BITDEPTH, OPT_RESOLUTION, OPT_Y_RESOLUTION, OPT_PREVIEW, /*9*/ OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ /*14*/ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_THRESHOLD, OPT_HALFTONE, OPT_AUTOADJUST, /*20*/ OPT_GAMMA_GROUP, OPT_GAMMA_MODE, OPT_GAMMA_SCALAR, OPT_GAMMA_SCALAR_R, OPT_GAMMA_SCALAR_G, OPT_GAMMA_SCALAR_B, OPT_GAMMA_CUSTOM, OPT_GAMMA_CUSTOM_R, OPT_GAMMA_CUSTOM_G, OPT_GAMMA_CUSTOM_B, OPT_GAMMA_BIND, /*31*/ OPT_SMH_GROUP, /* these options must appear in exactly this order, */ /* sane_control_option relies on it */ OPT_CHANNEL, OPT_SHADOW, OPT_MIDTONE, OPT_HIGHLIGHT, OPT_SHADOW_R, OPT_MIDTONE_R, OPT_HIGHLIGHT_R, OPT_SHADOW_G, OPT_MIDTONE_G, OPT_HIGHLIGHT_G, OPT_SHADOW_B, OPT_MIDTONE_B, OPT_HIGHLIGHT_B, OPT_EXPOSURE, OPT_EXPOSURE_R, OPT_EXPOSURE_G, OPT_EXPOSURE_B, /*49*/ OPT_SPECIAL, OPT_RESOLUTION_BIND, OPT_DISABLE_BACKTRACK, OPT_CALIB_BACKEND, OPT_LIGHTLID35, OPT_TOGGLELAMP, /*55*/ OPT_COLORBALANCE, OPT_BALANCE_R, OPT_BALANCE_G, OPT_BALANCE_B, OPT_BALANCE_FW, /*60*/ NUM_OPTIONS }; /******************************************************************************/ /* Description of options not included in saneopts.h */ /******************************************************************************/ #define M_TITLE_SCANMODEGRP SANE_I18N("Scan Mode") #define M_TITLE_GEOMGRP SANE_I18N("Geometry") #define M_TITLE_ENHANCEGRP SANE_I18N("Enhancement") #define M_TITLE_SMHGRP SANE_I18N("Shadow, midtone, highlight,"\ " exposure time"); #define M_TITLE_SPECIALGRP SANE_I18N("Special options") #define M_TITLE_COLBALANCEGRP SANE_I18N("Color balance") #define M_NAME_NOBACKTRACK "no-backtracking" #define M_TITLE_NOBACKTRACK SANE_I18N("Disable backtracking") #define M_DESC_NOBACKTRACK SANE_I18N("If checked the scanner does not" \ " perform backtracking") #define M_NAME_TOGGLELAMP "toggle-lamp" #define M_TITLE_TOGGLELAMP SANE_I18N("Toggle lamp of flatbed") #define M_DESC_TOGGLELAMP SANE_I18N("Toggles the lamp of the flatbed") #define M_NAME_CALIBBACKEND "backend-calibration" #define M_TITLE_CALIBBACKEND SANE_I18N("Calibration by backend") #define M_DESC_CALIBBACKEND SANE_I18N("If checked the color calibration" \ " before a scan is done by the backend") #define M_NAME_LIGHTLID35 "lightlid35" #define M_TITLE_LIGHTLID35 SANE_I18N("Use the lightlid-35mm adapter") #define M_DESC_LIGHTLID35 SANE_I18N("This option turns off the lamp of" \ " the flatbed during a scan") #define M_NAME_QUALITY_SCAN "quality-scan" #define M_TITLE_QUALITY_SCAN SANE_I18N("Quality scan") #define M_DESC_QUALITY_SCAN SANE_I18N("Highest quality but lower speed") #define M_NAME_FAST_SCAN "fast-scan" #define M_TITLE_FAST_SCAN SANE_I18N("Fast scan") #define M_DESC_FAST_SCAN SANE_I18N("Highest speed but lower quality") #define M_NAME_AUTOADJUST "lineart-auto-adjust" #define M_TITLE_AUTOADJUST SANE_I18N("Automatic adjustment of threshold") #define M_DESC_AUTOADJUST SANE_I18N("If checked the backend automatically"\ " tries to determine an optimal value for the" \ " threshold.") #define M_NAME_GAMMA_MODE "gamma-correction" #define M_TITLE_GAMMA_MODE SANE_I18N("Gamma correction") #define M_DESC_GAMMA_MODE SANE_I18N("Selects the gamma correction mode.") #define M_NAME_GAMMA_BIND "bind-gamma" #define M_TITLE_GAMMA_BIND SANE_I18N("Bind gamma") #define M_DESC_GAMMA_BIND SANE_I18N("Use same gamma values for all" \ " colour channels.") #define M_NAME_GAMMA_SCALAR "scalar-gamma" #define M_TITLE_GAMMA_SCALAR SANE_I18N("Scalar gamma") #define M_DESC_GAMMA_SCALAR SANE_I18N("Selects a value for scalar" \ " gamma correction.") #define M_NAME_GAMMA_SCALAR_R "scalar-gamma-r" #define M_TITLE_GAMMA_SCALAR_R SANE_I18N("Scalar gamma red") #define M_DESC_GAMMA_SCALAR_R SANE_I18N("Selects a value for scalar gamma" \ " correction (red channel)") #define M_NAME_GAMMA_SCALAR_G "scalar-gamma-g" #define M_TITLE_GAMMA_SCALAR_G SANE_I18N("Scalar gamma green") #define M_DESC_GAMMA_SCALAR_G SANE_I18N("Selects a value for scalar gamma" \ " correction (green channel)") #define M_NAME_GAMMA_SCALAR_B "scalar-gamma-b" #define M_TITLE_GAMMA_SCALAR_B SANE_I18N("Scalar gamma blue") #define M_DESC_GAMMA_SCALAR_B SANE_I18N("Selects a value for scalar gamma" \ " correction (blue channel)") #define M_NAME_CHANNEL "channel" #define M_TITLE_CHANNEL SANE_I18N("Channel") #define M_DESC_CHANNEL SANE_I18N("Selects the colour band, \"Master\"" \ " means that all colours are affected.") #define M_NAME_MIDTONE "midtone" #define M_TITLE_MIDTONE SANE_I18N("Midtone") #define M_DESC_MIDTONE SANE_I18N("Selects which radiance level should" \ " be considered \"50 % gray\".") #define M_NAME_MIDTONE_R "midtone-r" #define M_TITLE_MIDTONE_R SANE_I18N("Midtone for red") #define M_DESC_MIDTONE_R SANE_I18N("Selects which radiance level should" \ " be considered \"50 % red\".") #define M_NAME_MIDTONE_G "midtone-g" #define M_TITLE_MIDTONE_G SANE_I18N("Midtone for green") #define M_DESC_MIDTONE_G SANE_I18N("Selects which radiance level should" \ " be considered \"50 % green\".") #define M_NAME_MIDTONE_B "midtone-b" #define M_TITLE_MIDTONE_B SANE_I18N("Midtone for blue") #define M_DESC_MIDTONE_B SANE_I18N("Selects which radiance level should" \ " be considered \"50 % blue\".") #define M_NAME_BALANCE_R "balance-r" #define M_TITLE_BALANCE_R SANE_I18N("Red balance") #define M_DESC_BALANCE_R SANE_I18N("Balance factor for red. A value of" \ " 100% means no correction.") #define M_NAME_BALANCE_G "balance-g" #define M_TITLE_BALANCE_G SANE_I18N("Green balance") #define M_DESC_BALANCE_G SANE_I18N("Balance factor for green. A value of"\ " 100% means no correction.") #define M_NAME_BALANCE_B "balance-b" #define M_TITLE_BALANCE_B SANE_I18N("Blue balance") #define M_DESC_BALANCE_B SANE_I18N("Balance factor for blue. A value of" \ " 100% means no correction.") #define M_NAME_BALANCE_FW "balance-fw" #define M_TITLE_BALANCE_FW SANE_I18N("Firmware balance") #define M_DESC_BALANCE_FW SANE_I18N("Sets the color balance values to"\ " the firmware provided values.") /******************************************************************************/ /* Structure that contains global options */ /******************************************************************************/ typedef struct Config_Options { double strip_height; /* inch */ char *no_backtracking; /* enable/disable option for */ /* backtracking */ char *lightlid35; /* enable/disable lightlid35 option */ char *toggle_lamp; /* enable/disable lightlid35 option */ char *backend_calibration; /* calibration by backend */ char *auto_adjust; /* automatically choose threshold */ char *colorbalance_adjust; /* color balance can be modified */ } Config_Options; /******************************************************************************/ /* Structure that is temporarily used, when the config file is parsed */ /******************************************************************************/ typedef struct Config_Temp { struct Config_Temp *next; char *device; /* possible device name */ Config_Options opts; /* options belonging to this device name */ } Config_Temp; /******************************************************************************/ /* scanner hardware info (as discovered by INQUIRY and READ ATTRIBUTES) */ /******************************************************************************/ typedef struct Microtek2_Info { /* from inquiry */ SANE_Byte device_qualifier; #define MI_DEVTYPE_SCANNER 0x06 SANE_Byte device_type; #define MI_SCSI_II_VERSION 0x02 SANE_Byte scsi_version; SANE_Char vendor[INQ_VENDOR_L + 1]; SANE_Char model[INQ_MODEL_L + 1]; SANE_Char revision[INQ_REV_L + 1]; SANE_Byte model_code; /* from read scanner attributes */ SANE_Bool color; #define MI_HAS_ONEPASS SANE_TRUE SANE_Bool onepass; /* the following 3 defines must correspond to byte 31 of SET WINDOW cmd */ #define MI_TYPE_FLATBED 0x01 #define MI_TYPE_SHEEDFEED 0x02 #define MI_TYPE_TRANSPARENCY 0x03 SANE_Byte scanner_type; #define MI_HAS_FEPROM SANE_TRUE SANE_Bool feprom; /* MI_DATAFMT_X must correspond to Byte 0 in READ SCANNER ATTRIBUTE */ #define MI_DATAFMT_CHUNKY 1 #define MI_DATAFMT_LPLCONCAT 2 #define MI_DATAFMT_LPLSEGREG 3 #define MI_DATAFMT_9800 4 #define MI_DATAFMT_WORDCHUNKY 5 SANE_Byte data_format; #define MI_COLSEQ_RED 0 #define MI_COLSEQ_GREEN 1 #define MI_COLSEQ_BLUE 2 #define MI_COLSEQ_ILLEGAL 3 uint8_t color_sequence[RSA_COLORSEQUENCE_L]; SANE_Bool new_image_status; #define MI_DATSEQ_RTOL 1 uint8_t direction; SANE_Byte ccd_gap; SANE_Int max_xresolution; SANE_Int max_yresolution; SANE_Int geo_width; SANE_Int geo_height; SANE_Int opt_resolution; #define MI_HASDEPTH_NIBBLE 1 #define MI_HASDEPTH_10 2 #define MI_HASDEPTH_12 4 #define MI_HASDEPTH_16 8 #define MI_HASDEPTH_14 16 /*This is not in Byte 13 of scanner attributes but in byte 48-bit0*/ SANE_Byte depth; #define MI_LINEART_NONE(d) (((d) & 0x01) == 0) #define MI_HASMODE_LINEART 1 #define MI_HASMODE_HALFTONE 2 #define MI_HASMODE_GRAY 4 #define MI_HASMODE_COLOR 8 SANE_Byte scanmode; SANE_Int ccd_pixels; #define MI_LUTCAP_NONE(d) ((d) == 0) #define MI_LUTCAP_256B 1 #define MI_LUTCAP_1024B 2 #define MI_LUTCAP_1024W 4 #define MI_LUTCAP_4096B 8 #define MI_LUTCAP_4096W 16 #define MI_LUTCAP_64k_W 32 #define MI_LUTCAP_16k_W 64 #define MI_LUTCAP_UNKNOWN 128 SANE_Byte lut_cap; #define MI_HAS_DNLDPTRN SANE_TRUE SANE_Bool has_dnldptrn; SANE_Byte grain_slct; #define MI_OPTDEV_ADF 0x01 #define MI_OPTDEV_TMA 0x02 #define MI_OPTDEV_ADP 0x10 #define MI_OPTDEV_APS 0x20 #define MI_OPTDEV_STRIPE 0x40 #define MI_OPTDEV_SLIDE 0x80 SANE_Byte option_device; SANE_Int calib_white; SANE_Int calib_space; SANE_Byte nlens; SANE_Byte nwindows; SANE_Byte shtrnsferequ; #define MI_WHITE_SHADING_ONLY(x) ((x) & 0x20) == 0 #define MI_HAS_SCNBTTN SANE_TRUE SANE_Bool scnbuttn; #define MI_HAS_PIPOBUF SANE_TRUE SANE_Bool buftype; uint16_t balance[3]; /* balance factor for red, green */ /* and blue data */ uint16_t aps_maxframes; SANE_Int calib_divisor; /* e.g. the X12USL reads and sends */ /* shading at 1/2 * opt_resolution */ } Microtek2_Info; /******************************************************************************/ /* device structure (one for each device in config file) */ /******************************************************************************/ typedef struct Microtek2_Device { struct Microtek2_Device *next; /* next, for linked list */ #define MD_SOURCE_FLATBED 0 #define MD_SOURCE_ADF 1 #define MD_SOURCE_TMA 2 #define MD_SOURCE_SLIDE 3 #define MD_SOURCE_STRIPE 4 Microtek2_Info info[5]; /* detailed scanner spec */ SANE_Device sane; /* SANE generic device block */ char name[PATH_MAX]; /* name from config file */ SANE_Int *custom_gamma_table[4]; /* used for the custom gamma */ /* values before a scan starts */ /* the following two are derived from lut_cap */ int max_lut_size; /* in bytes */ int lut_entry_size; /* word or byte transfer in LUT */ uint8_t scan_source; double revision; /* basically the following two variables should go into the */ /* Microtek2_Scanner structure, but their values must be retained */ /* over several scans, and would be lost, if the application issues */ /* a sane_close. */ uint8_t *shading_table_w; /* shading table white */ uint8_t *shading_table_d; /* shading table dark */ uint8_t shading_table_contents; /* values like ms->mode */ /* the following structure describes the device status */ #define MD_TLAMP_ON 2 #define MD_FLAMP_ON 1 #define MD_NCALIB_ON 4 #define MD_NTRACK_ON 8 #define MD_STICK_ON 16 #define MD_RESERVED17_ON 128 #define MD_CURRENT_MODE_FLATBED 0 struct { uint8_t sskip; uint8_t stick; uint8_t ntrack; uint8_t ncalib; uint8_t tlamp; uint8_t flamp; uint8_t reserved17; uint8_t rdyman; uint8_t trdy; uint8_t frdy; uint8_t adp; uint8_t detect; uint8_t adptime; uint8_t lensstatus; uint8_t aloff; uint8_t timeremain; uint8_t tmacnt; uint8_t paper; uint8_t adfcnt; uint8_t currentmode; uint8_t buttoncount; } status; /* The following defines are related to the model. Some models have */ /* more or less subtle deviations from the spec, which are indicated */ /* by these defines */ uint32_t model_flags; #define MD_NO_SLIDE_MODE 1 /* indicates that it has slide */ /* mode, but it does not */ #define MD_DATA_FORMAT_WRONG 2 /* X6 indicates wrong mode for TMA */ #define MD_NO_ENHANCEMENTS 4 /* image enhancements do not work */ /* (Brightness, contrast, .....) */ #define MD_RII_TWO_BYTES 8 /* return some image information */ /* in two byte */ #define MD_NO_GAMMA 16 /* if device does not accept */ /* gamma tables */ #define MD_PHANTOM336CX_TYPE_SHADING 32 /* Phantom 336cx type shading */ #define MD_READ_CONTROL_BIT 64 /* uses "read control bit" */ #define MD_PHANTOM_C6 128 /* It is a Phantom C6 */ #define MD_OFFSET_2 256 /* Image data starts 2 bytes */ /* from the beginning of a */ /* scanline */ #define MD_X6_SHORT_TRANSFER 512 /* X6 USB crashes if you read too much */ #define MD_NO_RIS_COMMAND 1024 /* doesn't like read_image_status */ #define MD_16BIT_TRANSFER 2048 /* transfers 10/12/14bit scans as */ /* 16bit data */ #define MD_CALIB_DIVISOR_600 4096 /* uses mi->calib_divisor=2 below 600dpi */ size_t n_control_bytes; /* for read_control_bits; the */ /* number is model dependent */ /* and can not be inquired */ uint32_t shading_length; /* length of the shading image */ /* Phantom 336cx, C6, ... */ uint8_t shading_depth; /* bit depth of shading image */ uint8_t controlbit_offset; /* first relevant control bit */ #define MD_MODESTRING_NUMS 4 #define MD_MODESTRING_COLOR SANE_VALUE_SCAN_MODE_COLOR #define MD_MODESTRING_GRAY SANE_VALUE_SCAN_MODE_GRAY #define MD_MODESTRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE #define MD_MODESTRING_LINEART SANE_VALUE_SCAN_MODE_LINEART SANE_String_Const scanmode_list[MD_MODESTRING_NUMS + 1]; #define MD_DEPTHVAL_NUMS 6 #define MD_DEPTHVAL_16 16 #define MD_DEPTHVAL_14 14 #define MD_DEPTHVAL_12 12 #define MD_DEPTHVAL_10 10 #define MD_DEPTHVAL_8 8 #define MD_DEPTHVAL_4 4 SANE_Int bitdepth_list[MD_DEPTHVAL_NUMS + 1]; #define MD_SOURCESTRING_NUMS 5 #define MD_SOURCESTRING_FLATBED "Flatbed" #define MD_SOURCESTRING_ADF "ADF" #define MD_SOURCESTRING_TMA "TMA" #define MD_SOURCESTRING_STRIPE "Filmstrip" #define MD_SOURCESTRING_SLIDE "Slide" SANE_String_Const scansource_list[MD_SOURCESTRING_NUMS + 1]; #define MD_HALFTONE_NUMS 12 #define MD_HALFTONE0 "53-dot screen (53 gray levels)" #define MD_HALFTONE1 "Horiz. screen (65 gray levels)" #define MD_HALFTONE2 "Vert. screen (65 gray levels)" #define MD_HALFTONE3 "Mixed page (33 gray levels)" #define MD_HALFTONE4 "71-dot screen (29 gray levels)" #define MD_HALFTONE5 "60-dot #1 (26 gray levels)" #define MD_HALFTONE6 "60-dot #2 (26 gray levels)" #define MD_HALFTONE7 "Fine detail #1 (17 gray levels)" #define MD_HALFTONE8 "Fine detail #2 (17 gray levels)" #define MD_HALFTONE9 "Slant line (17 gray levels)" #define MD_HALFTONE10 "Posterizing (10 gray levels)" #define MD_HALFTONE11 "High Contrast (5 gray levels)" SANE_String_Const halftone_mode_list[MD_HALFTONE_NUMS + 1]; #define MD_CHANNEL_NUMS 4 #define MD_CHANNEL_MASTER "Master" #define MD_CHANNEL_RED "Red" #define MD_CHANNEL_GREEN "Green" #define MD_CHANNEL_BLUE "Blue" SANE_String_Const channel_list[MD_CHANNEL_NUMS + 1]; #define MD_GAMMAMODE_NUMS 3 #define MD_GAMMAMODE_LINEAR "None" #define MD_GAMMAMODE_SCALAR "Scalar" #define MD_GAMMAMODE_CUSTOM "Custom" SANE_String_Const gammamode_list[MD_GAMMAMODE_NUMS + 1]; SANE_Range x_res_range_dpi; /* X resolution in dpi */ SANE_Range y_res_range_dpi; /* Y resolution in dpi */ SANE_Range x_range_mm; /* scan width in mm */ SANE_Range y_range_mm; /* scan height in mm */ SANE_Range percentage_range; /* for brightness, shadow, ... */ SANE_Range custom_gamma_range; /* for custom gamma values */ SANE_Range scalar_gamma_range; /* for scalar gamma values */ SANE_Range shadow_range; /* shadow of blue channel */ SANE_Range midtone_range; /* midtone shadow of blue channel */ SANE_Range exposure_range; /* for lengthening exposure time */ SANE_Range highlight_range; /* highlight of master channel */ SANE_Range threshold_range; /* 1 - 255 */ SANE_Range balance_range; /* for user provided color balance */ Config_Options opts; /* options from the config file */ SANE_Word opt_backend_calib_default; /* corresponds to scanner model */ SANE_Word opt_no_backtrack_default; /* corresponds to scanner model */ } Microtek2_Device; /******************************************************************************/ /* scanner structure (one for each device in use) */ /* ....all the state needed to define a scan request */ /******************************************************************************/ typedef struct Microtek2_Scanner { struct Microtek2_Scanner *next; /* for linked list */ Microtek2_Device *dev; /* raw device info */ Option_Value val[NUM_OPTIONS + 1]; /* option values for session */ SANE_Parameters params; /* format, lastframe, lines, depth, ppl, bpl */ SANE_Option_Descriptor sod[NUM_OPTIONS + 1]; /* option list for session */ uint8_t *gamma_table; uint8_t *shading_image; /* used for shading image */ uint8_t *condensed_shading_w; /* used when a model uses "read */ uint8_t *condensed_shading_d; /* control bit", stores the relevant */ /* shading pixels for each color */ uint8_t *temporary_buffer; /* used when automatic adjustment */ /* is selected */ char *gamma_mode; /* none, linear or custom */ /* the following defines must correspond to byte 25 of SET WINDOW body */ #define MS_MODE_LINEART 0x00 #define MS_MODE_HALFTONE 0x01 #define MS_MODE_GRAY 0x02 #define MS_MODE_LINEARTFAKE 0x12 /* no real mode */ #define MS_MODE_COLOR 0x05 /* the following defines must correspond to byte 31 of SET WINDOW body */ #define MS_SOURCE_FLATBED 0x00 #define MS_SOURCE_ADF 0x01 #define MS_SOURCE_TMA 0x02 #define MS_SOURCE_STRIPE 0x05 #define MS_SOURCE_SLIDE 0x06 SANE_Int mode; SANE_Int depth; SANE_Int x_resolution_dpi; SANE_Int y_resolution_dpi; SANE_Int x1_dots; /* x-position in units of optical resolution */ SANE_Int y1_dots; /* same for y-position */ SANE_Int width_dots; /* scan width in units of optical resolution */ SANE_Int height_dots; /* same for height */ uint8_t brightness_m; uint8_t contrast_m; uint8_t exposure_m; uint8_t shadow_m; uint8_t midtone_m; uint8_t highlight_m; uint8_t brightness_r; uint8_t contrast_r; uint8_t exposure_r; uint8_t shadow_r; uint8_t midtone_r; uint8_t highlight_r; uint8_t brightness_g; uint8_t contrast_g; uint8_t exposure_g; uint8_t shadow_g; uint8_t midtone_g; uint8_t highlight_g; uint8_t brightness_b; uint8_t contrast_b; uint8_t exposure_b; uint8_t shadow_b; uint8_t midtone_b; uint8_t highlight_b; uint8_t threshold; SANE_Bool use_external_ht; SANE_Byte internal_ht_index; uint8_t stay; uint8_t rawdat; SANE_Bool quality; SANE_Bool fastscan; SANE_Byte scan_source; uint8_t no_backtracking; uint8_t lightlid35; uint8_t auto_adjust; uint8_t calib_backend; uint8_t colorbalance_adjust; int current_pass; /* current pass if 3-pass scan */ int lut_size; /* size of gamma lookup table */ int lut_entry_size; /* size of one entry in lookup table */ uint32_t lut_size_bytes; /* size of LUT in bytes */ uint8_t word; /* word transfer, used in some read cmds */ /* MS_COLOR_X must correspond to color field in READ IMAGE STATUS */ #define MS_COLOR_RED 0 #define MS_COLOR_GREEN 1 #define MS_COLOR_BLUE 2 #define MS_COLOR_ALL 3 uint8_t current_color; /* for gamma calc. and 3-pass scanners */ uint8_t current_read_color; /* dto, for RI and RIS */ uint8_t dark; /* is 1 for reading dark shading */ uint32_t ppl; /* pixels per line as returned by RII */ uint32_t bpl; /* bytes per line as returned by RII */ uint32_t remaining_bytes; /* remaining bytes as returned by RII */ uint32_t real_remaining_bytes;/* bytes to transfer to the frontend */ uint32_t real_bpl; /* bpl to transfer to the frontend */ SANE_Int src_remaining_lines; /* remaining lines to read */ SANE_Int src_lines_to_read; /* actual number of lines read */ SANE_Int src_max_lines; /* maximum number of lines that fit */ /* into the scsi buffer */ /* sent to the frontend */ int bits_per_pixel_in; /* bits per pixel transferred from scanner */ int bits_per_pixel_out; /* bits per pixel transf. to frontend */ uint32_t src_buffer_size; /* size of the buffer */ int transfer_length; /* transfer length for RI command */ uint8_t balance[3]; /* user provided balance factor for */ /* red, green and blue data */ struct { uint8_t *src_buffer[2]; /* two buffers because of CCD gap */ uint8_t *src_buf; int current_src; SANE_Int free_lines; SANE_Int free_max_lines; uint8_t *current_pos[3]; /* actual position in the source buffer */ int planes[2][3]; /* # of red, green, blue planes in the */ /* current source buffer and leftover */ /* planes from previous "read image" */ } buf; SANE_Bool onepass; size_t n_control_bytes; /* for READ CONTROL BITS */ uint8_t *control_bytes; /* pointer to the result */ int scanning; /* true == between sane_start & sane_read=EOF */ int cancelled; int sfd; /* SCSI filedescriptor */ int fd[2]; /* file descriptors for pipe */ SANE_Pid pid; /* pid of child process */ FILE *fp; } Microtek2_Scanner; /******************************************************************************/ /* Function prototypes */ /******************************************************************************/ static SANE_Status add_device_list(SANE_String_Const, Microtek2_Device **); static SANE_Status attach(Microtek2_Device *); static SANE_Status attach_one (const char *); static SANE_Status auto_adjust_proc_data (Microtek2_Scanner *, uint8_t **); static SANE_Status calc_cx_shading_line(Microtek2_Scanner *); /* (KF) new */ static SANE_Status calculate_gamma(Microtek2_Scanner *, uint8_t *, int, char *); static SANE_Status calculate_sane_params(Microtek2_Scanner *); static SANE_Status cancel_scan(Microtek2_Scanner *); static SANE_Status check_inquiry(Microtek2_Device *, SANE_String *); static void check_option(const char *, Config_Options *); static SANE_Status chunky_copy_pixels(Microtek2_Scanner *, uint8_t *); static SANE_Status chunky_proc_data(Microtek2_Scanner *); #if 0 static void chunky_set_exposure(uint8_t *, uint32_t, uint8_t, uint8_t, int); #endif static void cleanup_scanner(Microtek2_Scanner *); static SANE_Status condense_shading(Microtek2_Scanner *); #ifdef HAVE_AUTHORIZATION static SANE_Status do_authorization(char *); #endif static SANE_Status read_shading_image(Microtek2_Scanner *); static SANE_Status dump_area(uint8_t *, int, char *); static SANE_Status dump_area2(uint8_t *, int, char *); /* currently not used */ #if 0 static SANE_Status dump_to_file(uint8_t *, int, char *, char *); #endif static SANE_Status dump_attributes(Microtek2_Info *); static void get_calib_params(Microtek2_Scanner *); static SANE_Status get_cshading_values(Microtek2_Scanner *,uint8_t, uint32_t, float, int, float *, float *); /* (KF) new */ static SANE_Status get_scan_mode_and_depth(Microtek2_Scanner *, int *, SANE_Int *, int *, int *); static SANE_Status get_scan_parameters(Microtek2_Scanner *); static SANE_Status get_lut_size(Microtek2_Info *, int *, int *); static SANE_Status gray_copy_pixels(Microtek2_Scanner *ms, uint8_t *, int, int); static SANE_Status gray_proc_data(Microtek2_Scanner *); #if 0 static void gray_set_exposure(uint8_t *, uint32_t, uint8_t, uint8_t); #endif static SANE_Status init_options(Microtek2_Scanner *, uint8_t); static SANE_Status lineartfake_copy_pixels(Microtek2_Scanner *, uint8_t *, uint32_t, uint8_t, int, FILE *); static SANE_Status lineartfake_proc_data(Microtek2_Scanner *); static SANE_Status lplconcat_copy_pixels(Microtek2_Scanner *, uint8_t **, int, int); static SANE_Status lplconcat_proc_data(Microtek2_Scanner *ms); static size_t max_string_size (const SANE_String_Const * /* strings[] */); static void parse_config_file(FILE *, Config_Temp **); static SANE_Status prepare_buffers(Microtek2_Scanner *); static SANE_Status prepare_shading_data(Microtek2_Scanner *, uint32_t, uint8_t **); static SANE_Status proc_onebit_data(Microtek2_Scanner *); static SANE_Status read_cx_shading_image(Microtek2_Scanner *); static SANE_Status read_cx_shading(Microtek2_Scanner *); static int reader_process(void *); static SANE_Status restore_gamma_options(SANE_Option_Descriptor *, Option_Value *); static SANE_Status segreg_copy_pixels(Microtek2_Scanner *); static SANE_Status segreg_proc_data(Microtek2_Scanner *ms); static void set_exposure(Microtek2_Scanner *); static SANE_Status set_option_dependencies(Microtek2_Scanner *, SANE_Option_Descriptor *, Option_Value *); static SANE_Status shading_function(Microtek2_Scanner *, uint8_t *); static void signal_handler (int); static SANE_Status wordchunky_copy_pixels(uint8_t *, uint32_t, int, FILE *); static SANE_Status wordchunky_proc_data(Microtek2_Scanner *); typedef int (*qsortfunc)(const void *, const void *); static int compare_func_16(const uint16_t *p1, uint16_t *p2) { return ( *p1 - *p2 ); } /******************************************************************************/ /* Function prototypes for basic SCSI commands */ /******************************************************************************/ static SANE_Status scsi_inquiry(Microtek2_Info *, char *); static SANE_Status scsi_read_attributes(Microtek2_Info *, char *, uint8_t); static SANE_Status scsi_read_control_bits(Microtek2_Scanner *); /* currently not used */ /* static SANE_Status scsi_read_gamma(Microtek2_Scanner *); */ static SANE_Status scsi_read_image(Microtek2_Scanner *, uint8_t *, int); static SANE_Status scsi_read_image_info(Microtek2_Scanner *); static SANE_Status scsi_read_image_status(Microtek2_Scanner *); static SANE_Status scsi_read_system_status(Microtek2_Device *, int); /* currently not used */ /* static SANE_Status scsi_request_sense(Microtek2_Scanner *); */ static SANE_Status scsi_send_gamma(Microtek2_Scanner *); static SANE_Status scsi_send_shading(Microtek2_Scanner *, uint8_t *, uint32_t, uint8_t); static SANE_Status scsi_read_shading(Microtek2_Scanner *, uint8_t *, uint32_t); static SANE_Status scsi_send_system_status(Microtek2_Device *, int); static SANE_Status scsi_sense_handler (int, u_char *, void *); static SANE_Status scsi_test_unit_ready(Microtek2_Device *); static SANE_Status scsi_set_window(Microtek2_Scanner *, int); static SANE_Status scsi_wait_for_image(Microtek2_Scanner *); #endif sane-backends-1.0.27/backend/teco1.h0000664000175000017500000002703612112021330013766 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ */ /* Commands supported by the scanner. */ #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_REQUEST_SENSE 0x03 #define SCSI_VENDOR_09 0x09 #define SCSI_VENDOR_0E 0x0E #define SCSI_INQUIRY 0x12 #define SCSI_MODE_SELECT 0x15 #define SCSI_SCAN 0x1b #define SCSI_SET_WINDOW 0x24 #define SCSI_SEND_10 0x2a #define SCSI_READ_10 0x28 #define SCSI_GET_DATA_BUFFER_STATUS 0x34 typedef struct { unsigned char data[16]; int len; } CDB; /* Set a specific bit depending on a boolean. * MKSCSI_BIT(TRUE, 3) will generate 0x08. */ #define MKSCSI_BIT(bit, pos) ((bit)? 1<<(pos): 0) /* Set a value in a range of bits. * MKSCSI_I2B(5, 3, 5) will generate 0x28 */ #define MKSCSI_I2B(bits, pos_b, pos_e) ((bits) << (pos_b) & ((1<<((pos_e)-(pos_b)+1))-1)) /* Store an integer in 2, 3 or 4 byte in an array. */ #define Ito16(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 0) & 0xff; \ } #define Ito24(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 0) & 0xff; \ } #define Ito32(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 24) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[3] = ((val) >> 0) & 0xff; \ } #define MKSCSI_GET_DATA_BUFFER_STATUS(cdb, wait, buflen) \ cdb.data[0] = SCSI_GET_DATA_BUFFER_STATUS; \ cdb.data[1] = MKSCSI_BIT(wait, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = 0; \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_INQUIRY(cdb, buflen) \ cdb.data[0] = SCSI_INQUIRY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_MODE_SELECT(cdb, pf, sp, buflen) \ cdb.data[0] = SCSI_MODE_SELECT; \ cdb.data[1] = MKSCSI_BIT(pf, 4) | MKSCSI_BIT(sp, 0); \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SET_WINDOW(cdb, buflen) \ cdb.data[0] = SCSI_SET_WINDOW; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_READ_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_READ_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_REQUEST_SENSE(cdb, buflen) \ cdb.data[0] = SCSI_REQUEST_SENSE; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = (buflen); \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SCAN(cdb) \ cdb.data[0] = SCSI_SCAN; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SEND_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_SEND_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_TEST_UNIT_READY(cdb) \ cdb.data[0] = SCSI_TEST_UNIT_READY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; /*--------------------------------------------------------------------------*/ static inline int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /*--------------------------------------------------------------------------*/ #define mmToIlu(mm) (((mm) * dev->def->x_resolution_max) / MM_PER_INCH) #define iluToMm(ilu) (((ilu) * MM_PER_INCH) / dev->def->x_resolution_max) /*--------------------------------------------------------------------------*/ #define MAX_GAMMA_LENGTH 0x400 /* maximum number of value per color */ #define GAMMA_LENGTH (dev->def->num_gamma_color) /* number of value per color */ /*--------------------------------------------------------------------------*/ enum Teco_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* scanner modes */ OPT_RESOLUTION, /* X and Y resolution */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* upper left X */ OPT_TL_Y, /* upper left Y */ OPT_BR_X, /* bottom right X */ OPT_BR_Y, /* bottom right Y */ OPT_ENHANCEMENT_GROUP, OPT_CUSTOM_GAMMA, /* Use the custom gamma tables */ OPT_GAMMA_VECTOR_R, /* Custom Red gamma table */ OPT_GAMMA_VECTOR_G, /* Custom Green Gamma table */ OPT_GAMMA_VECTOR_B, /* Custom Blue Gamma table */ OPT_GAMMA_VECTOR_GRAY, /* Custom Grayscale Gamma table */ OPT_DITHER, OPT_THRESHOLD, OPT_PREVIEW, /* must come last: */ OPT_NUM_OPTIONS }; /*--------------------------------------------------------------------------*/ /* * Scanner supported by this backend. */ struct scanners_supported { int scsi_type; char scsi_teco_name[12]; /* real name of the scanner */ enum { TECO_VM3510, TECO_VM3520, TECO_VM353A, TECO_VM4540, TECO_VM4542 } tecoref; char *real_vendor; /* brand on the box */ char *real_product; /* name on the box */ SANE_Range res_range; int x_resolution_max; /* maximum X dpi */ int y_resolution_max; /* maximum Y dpi */ int pass; /* number of passes in color mode */ size_t num_gamma_color; /* number of value per color */ int window_size; /* size of the SCAN window */ }; /*--------------------------------------------------------------------------*/ #define BLACK_WHITE_STR SANE_VALUE_SCAN_MODE_LINEART #define GRAY_STR SANE_VALUE_SCAN_MODE_GRAY #define COLOR_STR SANE_VALUE_SCAN_MODE_COLOR /*--------------------------------------------------------------------------*/ /* Define a scanner occurence. */ typedef struct Teco_Scanner { struct Teco_Scanner *next; SANE_Device sane; char *devicename; int sfd; /* device handle */ /* Infos from inquiry. */ char scsi_type; char scsi_vendor[9]; char scsi_product[17]; char scsi_version[5]; char scsi_teco_name[12]; /* real name of the scanner */ /* SCSI handling */ size_t buffer_size; /* size of the buffer */ SANE_Byte *buffer; /* for SCSI transfer. */ /* Scanner infos. */ const struct scanners_supported *def; /* default options for that scanner */ /* Scanning handling. */ int scanning; /* TRUE if a scan is running. */ int x_resolution; /* X resolution in DPI */ int y_resolution; /* Y resolution in DPI */ int x_tl; /* X top left */ int y_tl; /* Y top left */ int x_br; /* X bottom right */ int y_br; /* Y bottom right */ int width; /* width of the scan area in mm */ int length; /* length of the scan area in mm */ int pass; /* current pass number */ enum { TECO_BW, TECO_GRAYSCALE, TECO_COLOR } scan_mode; int depth; /* depth per color */ size_t bytes_left; /* number of bytes left to give to the backend */ size_t real_bytes_left; /* number of bytes left the scanner will return. */ SANE_Byte *image; /* keep the raw image here */ size_t image_size; /* allocated size of image */ size_t image_begin; /* first significant byte in image */ size_t image_end; /* first free byte in image */ SANE_Parameters params; /* Options */ SANE_Option_Descriptor opt[OPT_NUM_OPTIONS]; Option_Value val[OPT_NUM_OPTIONS]; /* Gamma table. 1 array per colour. */ SANE_Word gamma_GRAY[MAX_GAMMA_LENGTH]; SANE_Word gamma_R[MAX_GAMMA_LENGTH]; SANE_Word gamma_G[MAX_GAMMA_LENGTH]; SANE_Word gamma_B[MAX_GAMMA_LENGTH]; } Teco_Scanner; /*--------------------------------------------------------------------------*/ /* Debug levels. * Should be common to all backends. */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /*--------------------------------------------------------------------------*/ /* 32 bits from an array to an integer (eg ntohl). */ #define B32TOI(buf) \ ((((unsigned char *)buf)[0] << 24) | \ (((unsigned char *)buf)[1] << 16) | \ (((unsigned char *)buf)[2] << 8) | \ (((unsigned char *)buf)[3] << 0)) #define B24TOI(buf) \ ((((unsigned char *)buf)[0] << 16) | \ (((unsigned char *)buf)[1] << 8) | \ (((unsigned char *)buf)[2] << 0)) #define B16TOI(buf) \ ((((unsigned char *)buf)[0] << 8) | \ (((unsigned char *)buf)[1] << 0)) sane-backends-1.0.27/backend/avision.h0000664000175000017500000005335613063340150014441 00000000000000/******************************************************************************* * SANE - Scanner Access Now Easy. avision.h This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. ***************************************************************************** This backend is based upon the Tamarack backend and adapted to the Avision scanners by René Rebe and Meino Cramer. Check the avision.c file for detailed copyright and change-log information. ********************************************************************************/ #ifndef avision_h #define avision_h #ifdef HAVE_STDINT_H # include /* available in ISO C99 */ #else # include typedef uint8_t uint8_t; typedef uint16_t uint16_t; typedef uint32_t uint32_t; #endif /* HAVE_STDINT_H */ #ifndef PATH_MAX # define PATH_MAX 1024 #endif typedef enum Avision_ConnectionType { AV_SCSI, AV_USB } Avision_ConnectionType; /* information needed for device access */ typedef struct Avision_Connection { Avision_ConnectionType connection_type; int scsi_fd; /* SCSI filedescriptor */ SANE_Int usb_dn; /* USB (libusb or scanner.c) device number */ enum { AVISION_USB_UNTESTED_STATUS, /* status type untested */ AVISION_USB_INT_STATUS, /* interrupt endp. (USB 1.x device) status */ AVISION_USB_BULK_STATUS /* bulk endp. (USB 2.0 device) status */ } usb_status; } Avision_Connection; typedef struct Avision_HWEntry { const char* scsi_mfg; const char* scsi_model; int usb_vendor; int usb_product; const char* real_mfg; const char* real_model; /* feature overwrites - as embedded CPUs have 16bit enums - this would need a change ... */ /* force no calibration */ #define AV_NO_CALIB ((uint64_t)1<<0) /* force all in one command calibration */ #define AV_ONE_CALIB_CMD ((uint64_t)1<<1) /* no gamma table */ #define AV_NO_GAMMA ((uint64_t)1<<2) /* light check is bogus */ #define AV_LIGHT_CHECK_BOGUS ((uint64_t)1<<3) /* no button though the device advertise it */ #define AV_NO_BUTTON ((uint64_t)1<<4) /* if the scan area needs to be forced to A3 */ #define AV_FORCE_A3 ((uint64_t)1<<5) /* if the scan area and resolution needs to be forced for films */ #define AV_FORCE_FILM ((uint64_t)1<<6) /* does not suport, or very broken background (added for AV610C2) */ #define AV_NO_BACKGROUND ((uint64_t)1<<7) /* is film scanner - no detection yet */ #define AV_FILMSCANNER ((uint64_t)1<<8) /* fujitsu adaption */ #define AV_FUJITSU ((uint64_t)1<<9) /* gray calibration data has to be uploaded on the blue channel ... ? */ #define AV_GRAY_CALIB_BLUE ((uint64_t)1<<10) /* Interrupt endpoint button readout (so far AV220) */ #define AV_INT_BUTTON ((uint64_t)1<<11) /* send acceleration table ... */ #define AV_ACCEL_TABLE ((uint64_t)1<<12) /* non-interlaced scanns up to 300 dpi (AV32xx / AV83xx) */ #define AV_NON_INTERLACED_DUPLEX_300 ((uint64_t)1<<13) /* do not read multiples of 64 bytes - stalls the USB chip */ #define AV_NO_64BYTE_ALIGN ((uint64_t)1<<14) /* force channel-by-channel calibration */ #define AV_MULTI_CALIB_CMD ((uint64_t)1<<15) /* non color scans are faster with a filter applied (AV32xx) */ #define AV_FASTER_WITH_FILTER ((uint64_t)1<<16) /* interlaced data with 1 line distance */ #define AV_2ND_LINE_INTERLACED ((uint64_t)1<<17) /* does not keep the window though it advertices so */ #define AV_DOES_NOT_KEEP_WINDOW ((uint64_t)1<<18) /* does not keep the gamma though it advertices so */ #define AV_DOES_NOT_KEEP_GAMMA ((uint64_t)1<<19) /* advertises ADF is BGR order, but isn't (or vice versa) */ #define AV_ADF_BGR_ORDER_INVERT ((uint64_t)1<<20) /* allows 12bit mode, though not flagged */ #define AV_12_BIT_MODE ((uint64_t)1<<21) /* very broken background raster */ #define AV_BACKGROUND_QUIRK ((uint64_t)1<<22) /* though marked as GRAY only the scanner can do GRAY modes */ #define AV_GRAY_MODES ((uint64_t)1<<23) /* no seperate, single REAR scan (AV122, DM152, ...) */ #define AV_NO_REAR ((uint64_t)1<<24) /* only scan with some known good hardware resolutions, as the scanner fails to properly interpoloate in between (e.g. AV121, DM152 on duplex scans - but also the AV600), software scale and interpolate to all the others */ #define AV_SOFT_SCALE ((uint64_t)1<<25) /* does keep window though it does not advertice it - the AV122/DM152 mess up image data if window is resend between ADF pages */ #define AV_DOES_KEEP_WINDOW ((uint64_t)1<<26) /* does keep gamma though it does not advertice it */ #define AV_DOES_KEEP_GAMMA ((uint64_t)1<<27) /* does the scanner contain a Cancel button? */ #define AV_CANCEL_BUTTON ((uint64_t)1<<28) /* is the rear image offset? */ #define AV_REAR_OFFSET ((uint64_t)1<<29) /* some devices do not need a START_SCAN, even hang with it */ #define AV_NO_START_SCAN ((uint64_t)1<<30) #define AV_INT_STATUS ((uint64_t)1<<31) /* force no calibration */ #define AV_NO_TUNE_SCAN_LENGTH ((uint64_t)1<<32) /* for gray scans, set grey filter */ #define AV_USE_GRAY_FILTER ((uint64_t)1<<33) /* For (HP) scanners with flipping duplexers */ #define AV_ADF_FLIPPING_DUPLEX ((uint64_t)1<<34) /* For scanners which need to have their firmware read to properly function. */ #define AV_FIRMWARE ((uint64_t)1<<35) /* maybe more ...*/ uint64_t feature_type; } Avision_HWEntry; typedef enum { AV_ASIC_Cx = 0, AV_ASIC_C1 = 1, AV_ASIC_W1 = 2, AV_ASIC_C2 = 3, AV_ASIC_C5 = 5, AV_ASIC_C6 = 6, AV_ASIC_C7 = 7, AV_ASIC_OA980 = 128, AV_ASIC_OA982 = 129 } asic_type; typedef enum { AV_THRESHOLDED, AV_DITHERED, AV_GRAYSCALE, /* all gray needs to be before color for is_color() */ AV_GRAYSCALE12, AV_GRAYSCALE16, AV_TRUECOLOR, AV_TRUECOLOR12, AV_TRUECOLOR16, AV_COLOR_MODE_LAST } color_mode; typedef enum { AV_NORMAL, AV_TRANSPARENT, AV_ADF, AV_ADF_REAR, AV_ADF_DUPLEX, AV_SOURCE_MODE_LAST } source_mode; typedef enum { AV_NORMAL_DIM, AV_TRANSPARENT_DIM, AV_ADF_DIM, AV_SOURCE_MODE_DIM_LAST } source_mode_dim; enum Avision_Option { OPT_NUM_OPTS = 0, /* must come first */ OPT_MODE_GROUP, OPT_MODE, OPT_RESOLUTION, #define OPT_RESOLUTION_DEFAULT 150 OPT_SPEED, OPT_PREVIEW, OPT_SOURCE, /* scan source normal, transparency, ADF */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_OVERSCAN_TOP, /* overscan for auto-crop/deskew, if supported */ OPT_OVERSCAN_BOTTOM, OPT_BACKGROUND, /* background raster lines to read out */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_QSCAN, OPT_QCALIB, OPT_GAMMA_VECTOR, /* first must be gray */ OPT_GAMMA_VECTOR_R, /* then r g b vector */ OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_EXPOSURE, /* film exposure adjustment */ OPT_IR, /* infra-red */ OPT_MULTISAMPLE, /* multi-sample */ OPT_MISC_GROUP, OPT_FRAME, /* Film holder control */ OPT_POWER_SAVE_TIME, /* set power save time to the scanner */ OPT_MESSAGE, /* optional message from the scanner display */ OPT_NVRAM, /* retrieve NVRAM values as pretty printed text */ OPT_PAPERLEN, /* Use paper_length field to detect double feeds */ OPT_ADF_FLIP, /* For flipping duplex, reflip the document */ NUM_OPTIONS /* must come last */ }; typedef struct Avision_Dimensions { /* in dpi */ int xres; int yres; /* in pixels */ long tlx; long tly; long brx; long bry; /* in pixels */ int line_difference; int rear_offset; /* in pixels of HW res */ /* interlaced duplex scan */ SANE_Bool interlaced_duplex; /* in dpi, likewise - different if software scaling required */ int hw_xres; int hw_yres; int hw_pixels_per_line; int hw_bytes_per_line; int hw_lines; } Avision_Dimensions; /* this contains our low-level info - not relevant for the SANE interface */ typedef struct Avision_Device { struct Avision_Device* next; SANE_Device sane; Avision_Connection connection; /* structs used to store config options */ SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; SANE_Range speed_range; asic_type inquiry_asic_type; SANE_Bool inquiry_new_protocol; SANE_Bool inquiry_nvram_read; SANE_Bool inquiry_power_save_time; SANE_Bool inquiry_light_box; SANE_Bool inquiry_adf; SANE_Bool inquiry_duplex; SANE_Bool inquiry_duplex_interlaced; SANE_Bool inquiry_paper_length; SANE_Bool inquiry_batch_scan; SANE_Bool inquiry_detect_accessories; SANE_Bool inquiry_needs_calibration; SANE_Bool inquiry_needs_gamma; SANE_Bool inquiry_keeps_gamma; SANE_Bool inquiry_keeps_window; SANE_Bool inquiry_calibration; SANE_Bool inquiry_3x3_matrix; SANE_Bool inquiry_needs_software_colorpack; SANE_Bool inquiry_needs_line_pack; SANE_Bool inquiry_adf_need_mirror; SANE_Bool inquiry_adf_bgr_order; SANE_Bool inquiry_light_detect; SANE_Bool inquiry_light_control; SANE_Bool inquiry_exposure_control; int inquiry_max_shading_target; SANE_Bool inquiry_button_control; unsigned int inquiry_buttons; SANE_Bool inquiry_tune_scan_length; SANE_Bool inquiry_background_raster; int inquiry_background_raster_pixel; enum {AV_FLATBED, AV_FILM, AV_SHEETFEED } scanner_type; /* the list of available color modes */ SANE_String_Const color_list[AV_COLOR_MODE_LAST + 1]; color_mode color_list_num[AV_COLOR_MODE_LAST]; color_mode color_list_default; /* the list of available source modes */ SANE_String_Const source_list[AV_SOURCE_MODE_LAST + 1]; source_mode source_list_num[AV_SOURCE_MODE_LAST]; int inquiry_optical_res; /* in dpi */ int inquiry_max_res; /* in dpi */ double inquiry_x_ranges [AV_SOURCE_MODE_DIM_LAST]; /* in mm */ double inquiry_y_ranges [AV_SOURCE_MODE_DIM_LAST]; /* in mm */ int inquiry_color_boundary; int inquiry_gray_boundary; int inquiry_dithered_boundary; int inquiry_thresholded_boundary; int inquiry_line_difference; /* software color pack */ int inquiry_channels_per_pixel; int inquiry_bits_per_channel; int inquiry_no_gray_modes; int scsi_buffer_size; /* nice to have SCSI buffer size */ int read_stripe_size; /* stripes to be read at-a-time */ /* film scanner atributes - maybe these should be in the scanner struct? */ SANE_Range frame_range; SANE_Word current_frame; SANE_Word holder_type; /* some versin corrections */ uint16_t data_dq; /* was ox0A0D - but hangs some new scanners */ Avision_HWEntry* hw; } Avision_Device; /* all the state relevant for the SANE interface */ typedef struct Avision_Scanner { struct Avision_Scanner* next; Avision_Device* hw; SANE_Option_Descriptor opt [NUM_OPTIONS]; Option_Value val [NUM_OPTIONS]; SANE_Int gamma_table [4][256]; /* we now save the calib data because we might need it for 16bit software calibration :-( */ uint8_t* dark_avg_data; uint8_t* white_avg_data; /* background raster data, if duplex first front, then rear */ uint8_t* background_raster; /* Parsed option values and variables that are valid only during the actual scan: */ SANE_Bool prepared; /* first page marker */ SANE_Bool scanning; /* scan in progress */ unsigned int page; /* page counter, 0: uninitialized, 1: scanning 1st page, ... */ int cancelled; SANE_Parameters params; /* scan window */ Avision_Dimensions avdimen; /* scan window - detailed internals */ /* Internal data for duplex scans */ char duplex_rear_fname [PATH_MAX]; SANE_Bool duplex_rear_valid; color_mode c_mode; source_mode source_mode; source_mode_dim source_mode_dim; /* Avision HW Access Connection (SCSI/USB abstraction) */ Avision_Connection av_con; SANE_Pid reader_pid; /* process id of reader */ int read_fds; /* pipe reading end */ int write_fds; /* pipe writing end */ } Avision_Scanner; /* Some Avision driver internal defines */ #define AV_WINID 0 /* Avision SCSI over USB error codes */ #define AVISION_USB_GOOD 0x00 #define AVISION_USB_REQUEST_SENSE 0x02 #define AVISION_USB_BUSY 0x08 /* SCSI commands that the Avision scanners understand: */ #define AVISION_SCSI_TEST_UNIT_READY 0x00 #define AVISION_SCSI_REQUEST_SENSE 0x03 #define AVISION_SCSI_MEDIA_CHECK 0x08 #define AVISION_SCSI_INQUIRY 0x12 #define AVISION_SCSI_MODE_SELECT 0x15 #define AVISION_SCSI_RESERVE_UNIT 0x16 #define AVISION_SCSI_RELEASE_UNIT 0x17 #define AVISION_SCSI_SCAN 0x1b #define AVISION_SCSI_SET_WINDOW 0x24 #define AVISION_SCSI_READ 0x28 #define AVISION_SCSI_SEND 0x2a #define AVISION_SCSI_OBJECT_POSITION 0x31 #define AVISION_SCSI_GET_DATA_STATUS 0x34 #define AVISION_SCSI_OP_REJECT_PAPER 0x00 #define AVISION_SCSI_OP_LOAD_PAPER 0x01 #define AVISION_SCSI_OP_GO_HOME 0x02 #define AVISION_SCSI_OP_TRANS_CALIB_GRAY 0x04 #define AVISION_SCSI_OP_TRANS_CALIB_COLOR 0x05 /* These apply to bitset1. The values are 0 to 6, shifted 3 bits to the left */ #define AVISION_FILTER_NONE 0x00 #define AVISION_FILTER_RED 0x08 #define AVISION_FILTER_GREEN 0x10 #define AVISION_FILTER_BLUE 0x18 #define AVISION_FILTER_RGB 0x20 #define AVISION_FILTER_CMYK 0x28 #define AVISION_FILTER_GRAY 0x30 /* The SCSI structures that we have to send to an avision to get it to do various stuff... */ typedef struct command_header { uint8_t opc; uint8_t pad0 [3]; uint8_t len; uint8_t pad1; } command_header; typedef struct command_set_window { uint8_t opc; uint8_t reserved0 [5]; uint8_t transferlen [3]; uint8_t control; } command_set_window; typedef struct command_read { uint8_t opc; uint8_t bitset1; uint8_t datatypecode; uint8_t readtype; uint8_t datatypequal [2]; uint8_t transferlen [3]; uint8_t control; } command_read; typedef struct command_scan { uint8_t opc; uint8_t bitset0; uint8_t reserved0 [2]; uint8_t transferlen; uint8_t bitset1; } command_scan; typedef struct command_send { uint8_t opc; uint8_t bitset1; uint8_t datatypecode; uint8_t reserved0; uint8_t datatypequal [2]; uint8_t transferlen [3]; uint8_t reserved1; } command_send; typedef struct firmware_status { uint8_t download_firmware; uint8_t first_effective_pixel_flatbed [2]; uint8_t first_effective_pixel_adf_front [2]; uint8_t first_effective_pixel_adf_rear [2]; uint8_t reserved; } firmware_status; typedef struct nvram_data { uint8_t pad_scans [4]; uint8_t adf_simplex_scans [4]; uint8_t adf_duplex_scans [4]; uint8_t flatbed_scans [4]; uint8_t flatbed_leading_edge [2]; uint8_t flatbed_side_edge [2]; uint8_t adf_leading_edge [2]; uint8_t adf_side_edge [2]; uint8_t adf_rear_leading_edge [2]; uint8_t adf_rear_side_edge [2]; uint8_t born_month [2]; uint8_t born_day [2]; uint8_t born_year [2]; uint8_t first_scan_month [2]; uint8_t first_scan_day [2]; uint8_t first_scan_year [2]; uint8_t vertical_magnification [2]; uint8_t horizontal_magnification [2]; uint8_t ccd_type; uint8_t scan_speed; char serial [24]; uint8_t power_saving_time [2]; uint8_t auto_feed; uint8_t roller_count [4]; uint8_t multifeed_count [4]; uint8_t jam_count [4]; uint8_t reserved; char identify_info[16]; char formal_name[16]; uint8_t reserved2 [10]; } nvram_data; typedef struct command_set_window_window { struct { uint8_t reserved0 [6]; uint8_t desclen [2]; } header; struct { uint8_t winid; uint8_t reserved0; uint8_t xres [2]; uint8_t yres [2]; uint8_t ulx [4]; uint8_t uly [4]; uint8_t width [4]; uint8_t length [4]; uint8_t brightness; uint8_t threshold; uint8_t contrast; uint8_t image_comp; uint8_t bpc; uint8_t halftone [2]; uint8_t padding_and_bitset; uint8_t bitordering [2]; uint8_t compr_type; uint8_t compr_arg; uint8_t paper_length[2]; uint8_t reserved1 [4]; /* Avision specific parameters */ uint8_t vendor_specific; uint8_t paralen; /* bytes following after this byte */ } descriptor; struct { uint8_t bitset1; uint8_t highlight; uint8_t shadow; uint8_t line_width [2]; uint8_t line_count [2]; /* the tail is quite version and model specific */ union { struct { uint8_t bitset2; uint8_t reserved; } old; struct { uint8_t bitset2; uint8_t ir_exposure_time; /* optional */ uint8_t r_exposure_time [2]; uint8_t g_exposure_time [2]; uint8_t b_exposure_time [2]; uint8_t bitset3; /* reserved in the v2 */ uint8_t auto_focus; uint8_t line_width_msb; uint8_t line_count_msb; uint8_t background_lines; } normal; struct { uint8_t reserved0 [4]; uint8_t paper_size; uint8_t paperx [4]; uint8_t papery [4]; uint8_t reserved1 [2]; } fujitsu; } type; } avision; } command_set_window_window; typedef struct page_header { uint8_t pad0 [4]; uint8_t code; uint8_t length; } page_header; typedef struct avision_page { uint8_t gamma; uint8_t thresh; uint8_t masks; uint8_t delay; uint8_t features; uint8_t pad0; } avision_page; typedef struct calibration_format { uint16_t pixel_per_line; uint8_t bytes_per_channel; uint8_t lines; uint8_t flags; uint8_t ability1; uint8_t r_gain; uint8_t g_gain; uint8_t b_gain; uint16_t r_shading_target; uint16_t g_shading_target; uint16_t b_shading_target; uint16_t r_dark_shading_target; uint16_t g_dark_shading_target; uint16_t b_dark_shading_target; /* not returned but usefull in some places */ uint8_t channels; } calibration_format; typedef struct matrix_3x3 { uint16_t v[9]; } matrix_3x3; typedef struct acceleration_info { uint16_t total_steps; uint16_t stable_steps; uint32_t table_units; uint32_t base_units; uint16_t start_speed; uint16_t target_speed; uint8_t ability; uint8_t table_count; uint8_t reserved[6]; } acceleration_info; /* set/get SCSI highended (big-endian) variables. Declare them as an array * of chars endianness-safe, int-size safe ... */ #define set_double(var,val) var[0] = ((val) >> 8) & 0xff; \ var[1] = ((val) ) & 0xff #define set_triple(var,val) var[0] = ((val) >> 16) & 0xff; \ var[1] = ((val) >> 8 ) & 0xff; \ var[2] = ((val) ) & 0xff #define set_quad(var,val) var[0] = ((val) >> 24) & 0xff; \ var[1] = ((val) >> 16) & 0xff; \ var[2] = ((val) >> 8 ) & 0xff; \ var[3] = ((val) ) & 0xff #define get_double(var) ((*var << 8) + *(var + 1)) #define get_triple(var) ((*var << 16) + \ (*(var + 1) << 8) + *(var + 2)) #define get_quad(var) ((*var << 24) + \ (*(var + 1) << 16) + \ (*(var + 2) << 8) + *(var + 3)) /* set/get Avision lowended (little-endian) shading data */ #define set_double_le(var,val) var[0] = ((val) ) & 0xff; \ var[1] = ((val) >> 8) & 0xff #define get_double_le(var) ((*(var + 1) << 8) + *var) #define BIT(n, p) ((n & (1 << p)) ? 1 : 0) #define SET_BIT(n, p) (n |= (1 << p)) #define CLEAR_BIT(n, p) (n &= ~(1 << p)) /* These should be in saneopts.h */ #define SANE_NAME_FRAME "frame" #define SANE_TITLE_FRAME SANE_I18N("Number of the frame to scan") #define SANE_DESC_FRAME SANE_I18N("Selects the number of the frame to scan") #define SANE_NAME_DUPLEX "duplex" #define SANE_TITLE_DUPLEX SANE_I18N("Duplex scan") #define SANE_DESC_DUPLEX SANE_I18N("Duplex scan provide a scan of the front and back side of the document") #ifdef AVISION_ENHANCED_SANE #warning "Compiled Avision backend will violate the SANE standard" /* Some Avision SANE extensions */ typedef enum { SANE_STATUS_LAMP_WARMING = SANE_STATUS_ACCESS_DENIED + 1 /* lamp is warming up */ } SANE_Avision_Status; /* public API extension */ extern SANE_Status ENTRY(media_check) (SANE_Handle handle); #endif #endif /* avision_h */ sane-backends-1.0.27/backend/apple.conf.in0000664000175000017500000000003012112021330015140 00000000000000scsi APPLE /dev/scanner sane-backends-1.0.27/backend/epson_usb.h0000664000175000017500000000030412112021330014735 00000000000000#ifndef _EPSON_USB_H_ #define _EPSON_USB_H_ #define SANE_EPSON_VENDOR_ID (0x4b8) extern SANE_Word sanei_epson_usb_product_ids[]; extern int sanei_epson_getNumberOfUSBProductIds (void); #endif sane-backends-1.0.27/backend/hp5400_sanei.c0000664000175000017500000002347612112021330015051 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Martijn van Oosterhout Copyright (C) 2003 Thomas Soumarmon Copyright (c) 2003 Henning Meier-Geinitz, Originally copied from HP3300 testtools. Original notice follows: Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Transport layer for communication with HP5400/5470 scanner. Implementation using sanei_usb Additions to support bulk data transport. Added debugging info - 19/02/2003 Martijn Changed to use sanei_usb instead of direct /dev/usb/scanner access - 15/04/2003 Henning */ #include "hp5400_xfer.h" #include "hp5400_debug.h" #include #include "../include/sane/sanei_usb.h" #define CMD_INITBULK1 0x0087 /* send 0x14 */ #define CMD_INITBULK2 0x0083 /* send 0x24 */ #define CMD_INITBULK3 0x0082 /* transfer length 0xf000 */ static void _UsbWriteControl (int fd, int iValue, int iIndex, void *pabData, int iSize) { int requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT; int request = (iSize > 1) ? 0x04 : 0x0C; HP5400_DBG (DBG_MSG, "Write: reqtype = 0x%02X, req = 0x%02X, value = %04X, len = %d\n", requesttype, request, iValue, iSize); if (iSize > 0) { int i; HP5400_DBG (DBG_MSG, " Data: "); for (i = 0; i < iSize && i < 8; i++) HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) pabData)[i]); if (iSize > 8) HP5400_DBG (DBG_MSG, "..."); HP5400_DBG (DBG_MSG, "\n"); } if (fd != -1) { sanei_usb_control_msg (fd, requesttype, request, iValue, iIndex, iSize, pabData); } /* No error checking? */ } void hp5400_command_write_noverify (int fd, int iValue, void *pabData, int iSize) { _UsbWriteControl (fd, iValue, 0, pabData, iSize); } static void _UsbReadControl (int fd, int iValue, int iIndex, void *pabData, int iSize) { int requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN; int request = (iSize > 1) ? 0x04 : 0x0C; HP5400_DBG (DBG_MSG, "Read: reqtype = 0x%02X, req = 0x%02X, value = %04X\n", requesttype, request, iValue); if (fd != -1) { sanei_usb_control_msg (fd, requesttype, request, iValue, iIndex, iSize, pabData); } } HP5400_SANE_STATIC int hp5400_open (const char *filename) { int fd, iVendor, iProduct; SANE_Status status; if (!filename) filename = "/dev/usb/scanner0"; status = sanei_usb_open (filename, &fd); if (status != SANE_STATUS_GOOD) { HP5400_DBG (DBG_MSG, "hp5400_open: open returned %s\n", sane_strstatus (status)); return -1; } status = sanei_usb_get_vendor_product (fd, &iVendor, &iProduct); if (status != SANE_STATUS_GOOD) { HP5400_DBG (DBG_MSG, "hp5400_open: can't get vendor/product ids: %s\n", sane_strstatus (status)); sanei_usb_close (fd); return -1; } if ((iVendor != 0x03F0) || ((iProduct != 0x1005) && (iProduct != 0x1105))) { HP5400_DBG (DBG_MSG, "hp5400_open: vendor/product 0x%04X-0x%04X is not " "supported\n", iVendor, iProduct); sanei_usb_close (fd); return -1; } HP5400_DBG (DBG_MSG, "vendor/product 0x%04X-0x%04X opened\n", iVendor, iProduct); return fd; } void hp5400_close (int iHandle) { sanei_usb_close (iHandle); } /* returns value > 0 if verify ok */ int hp5400_command_verify (int iHandle, int iCmd) { unsigned char abData[4]; int fd; if (iHandle < 0) { HP5400_DBG (DBG_ERR, "hp5400_command_verify: invalid handle\n"); return -1; } fd = iHandle; /* command 0xc500: read back previous command */ _UsbReadControl (fd, 0xc500, 0, (char *) abData, 2); if (abData[0] != (iCmd >> 8)) { HP5400_DBG (DBG_ERR, "hp5400_command_verify failed, expected 0x%02X%02X, got 0x%02X%02X\n", (int) (iCmd >> 8), (int) (iCmd & 0xff), (int) abData[0], (int) abData[1]); return -1; } if (abData[1] != 0) /* Error code non-zero */ { _UsbReadControl (fd, 0x0300, 0, (char *) abData, 3); HP5400_DBG (DBG_ERR, " error response is: %02X %02X %02X\n", abData[0], abData[1], abData[2]); return -1; } HP5400_DBG (DBG_MSG, "Command %02X verified\n", abData[0]); return 1; } /* returns > 0 if command OK */ int hp5400_command_read_noverify (int iHandle, int iCmd, int iLen, void *pbData) { int fd; if (iHandle < 0) { HP5400_DBG (DBG_ERR, "hp5400_command_read: invalid handle\n"); return -1; } fd = iHandle; _UsbReadControl (fd, iCmd, 0, pbData, iLen); return 1; } /* returns > 0 if command OK */ int hp5400_command_read (int iHandle, int iCmd, int iLen, void *pbData) { hp5400_command_read_noverify (iHandle, iCmd, iLen, pbData); return hp5400_command_verify (iHandle, iCmd); } /* returns >0 if command OK */ int hp5400_command_write (int iHandle, int iCmd, int iLen, void *pbData) { int fd; if (iHandle < 0) { HP5400_DBG (DBG_ERR, "hp5400_command_write: invalid handle\n"); return -1; } fd = iHandle; _UsbWriteControl (fd, iCmd, 0, (char *) pbData, iLen); return hp5400_command_verify (iHandle, iCmd); } #ifdef STANDALONE /* returns >0 if command OK */ int hp5400_bulk_read (int iHandle, size_t len, int block, FILE * file) { SANE_Int fd; char x1 = 0x14, x2 = 0x24; short buf[4] = { 0, 0, 0, 0 }; SANE_Byte *buffer; size_t res = 0; buf[2] = block; if (iHandle < 0) { HP5400_DBG (DBG_ERR, "hp5400_command_read: invalid handle\n"); return -1; } fd = iHandle; buffer = (unsigned char*) malloc (block); _UsbWriteControl (fd, CMD_INITBULK1, 0, &x1, 1); _UsbWriteControl (fd, CMD_INITBULK2, 0, &x2, 1); while (len > 0) { _UsbWriteControl (fd, CMD_INITBULK3, 0, (unsigned char *) &buf, sizeof (buf)); res = block; sanei_usb_read_bulk (fd, buffer, &res); HP5400_DBG (DBG_MSG, "Read bulk returned %lu, %lu remain\n", (u_long) res, (u_long) len); if (res > 0) { fwrite (buffer, (len < res) ? len : res, 1, file); } len -= block; } /* error handling? */ return 0; } #endif /* returns >0 if command OK */ int hp5400_bulk_read_block (int iHandle, int iCmd, void *cmd, int cmdlen, void *buffer, int len) { SANE_Int fd; size_t res = 0; if (iHandle < 0) { HP5400_DBG (DBG_ERR, "hp5400_command_read_block: invalid handle\n"); return -1; } fd = iHandle; _UsbWriteControl (fd, iCmd, 0, cmd, cmdlen); res = len; sanei_usb_read_bulk (fd, (SANE_Byte *) buffer, &res); HP5400_DBG (DBG_MSG, "Read block returned %lu when reading %d\n", (u_long) res, len); return res; } /* returns >0 if command OK */ int hp5400_bulk_command_write (int iHandle, int iCmd, void *cmd, int cmdlen, int datalen, int block, char *data) { SANE_Int fd; size_t res = 0, offset = 0; if (iHandle < 0) { HP5400_DBG (DBG_ERR, "hp5400_bulk_command_write: invalid handle\n"); return -1; } fd = iHandle; HP5400_DBG (DBG_MSG, "bulk_command_write(%04X,<%d bytes>,<%d bytes>)\n", iCmd, cmdlen, datalen); _UsbWriteControl (fd, iCmd, 0, cmd, cmdlen); while (datalen > 0) { { int i; HP5400_DBG (DBG_MSG, " Data: "); for (i = 0; i < datalen && i < block && i < 8; i++) HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) data + offset)[i]); if (i >= 8) HP5400_DBG (DBG_MSG, "..."); HP5400_DBG (DBG_MSG, "\n"); } res = (datalen < block) ? datalen : block; sanei_usb_write_bulk (fd, (SANE_Byte *) (data + offset), &res); HP5400_DBG (DBG_MSG, "Write returned %lu, %d remain\n", (u_long) res, datalen); datalen -= block; offset += block; } return hp5400_command_verify (iHandle, iCmd); } #ifdef STANDALONE /** ScannerIsOn retrieve on/off status from scanner @return 1 if is on 0 if is off -1 if is not reachable */ int hp5400_isOn (int iHandle) { unsigned char text2400[3]; hp5400_command_read (iHandle, 0x2400, 0x03, text2400); /* byte 0 indicates if is on or off if 0x02 */ /* byte 1 indicates time since is on */ /* byte 2 indicates time since is power plugged */ if (text2400[0] & 0x02) { return 1; /* is on */ } return 0; /* is off */ } #endif sane-backends-1.0.27/backend/coolscan3.c0000664000175000017500000022703612775312260014660 00000000000000/* * SANE - Scanner Access Now Easy. * coolscan3.c * * This file implements a SANE backend for Nikon Coolscan film scanners. * * coolscan3.c is based on coolscan2.c, a work of András Major, Ariel Garcia * and Giuseppe Sacco. * * Copyright (C) 2007-08 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. * */ /* ========================================================================= */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_config.h" #define BACKEND_NAME coolscan3 #include "../include/sane/sanei_backend.h" /* must be last */ #define CS3_VERSION_MAJOR 1 #define CS3_VERSION_MINOR 0 #define CS3_REVISION 0 #define CS3_CONFIG_FILE "coolscan3.conf" #define WSIZE (sizeof (SANE_Word)) /* ========================================================================= */ /* typedefs */ typedef enum { CS3_TYPE_UNKOWN, CS3_TYPE_LS30, CS3_TYPE_LS40, CS3_TYPE_LS50, CS3_TYPE_LS2000, CS3_TYPE_LS4000, CS3_TYPE_LS5000, CS3_TYPE_LS8000 } cs3_type_t; typedef enum { CS3_INTERFACE_UNKNOWN, CS3_INTERFACE_SCSI, /* includes IEEE1394 via SBP2 */ CS3_INTERFACE_USB } cs3_interface_t; typedef enum { CS3_PHASE_NONE = 0x00, CS3_PHASE_STATUS = 0x01, CS3_PHASE_OUT = 0x02, CS3_PHASE_IN = 0x03, CS3_PHASE_BUSY = 0x04 } cs3_phase_t; typedef enum { CS3_SCAN_NORMAL, CS3_SCAN_AE, CS3_SCAN_AE_WB } cs3_scan_t; typedef enum { CS3_STATUS_READY = 0, CS3_STATUS_BUSY = 1, CS3_STATUS_NO_DOCS = 2, CS3_STATUS_PROCESSING = 4, CS3_STATUS_ERROR = 8, CS3_STATUS_REISSUE = 16, CS3_STATUS_ALL = 31 /* sum of all others */ } cs3_status_t; typedef enum { CS3_OPTION_NUM = 0, CS3_OPTION_PREVIEW, CS3_OPTION_NEGATIVE, CS3_OPTION_INFRARED, CS3_OPTION_SAMPLES_PER_SCAN, CS3_OPTION_DEPTH, CS3_OPTION_EXPOSURE, CS3_OPTION_EXPOSURE_R, CS3_OPTION_EXPOSURE_G, CS3_OPTION_EXPOSURE_B, CS3_OPTION_SCAN_AE, CS3_OPTION_SCAN_AE_WB, CS3_OPTION_LUT_R, CS3_OPTION_LUT_G, CS3_OPTION_LUT_B, CS3_OPTION_RES, CS3_OPTION_RESX, CS3_OPTION_RESY, CS3_OPTION_RES_INDEPENDENT, CS3_OPTION_PREVIEW_RESOLUTION, CS3_OPTION_FRAME, CS3_OPTION_FRAME_COUNT, CS3_OPTION_SUBFRAME, CS3_OPTION_XMIN, CS3_OPTION_XMAX, CS3_OPTION_YMIN, CS3_OPTION_YMAX, CS3_OPTION_LOAD, CS3_OPTION_AUTOLOAD, CS3_OPTION_EJECT, CS3_OPTION_RESET, CS3_OPTION_FOCUS_ON_CENTRE, CS3_OPTION_FOCUS, CS3_OPTION_AUTOFOCUS, CS3_OPTION_FOCUSX, CS3_OPTION_FOCUSY, CS3_N_OPTIONS /* must be last -- counts number of enum items */ } cs3_option_t; typedef unsigned int cs3_pixel_t; #define CS3_COLOR_MAX 10 /* 9 + 1, see cs3_colors */ /* Given that there is no way to give scanner vendor * and model to the calling software, I have to use * an ugly hack here. :( That's very sad. Suggestions * that can provide the same features are appreciated. */ #ifndef SANE_COOKIE #define SANE_COOKIE 0x0BADCAFE struct SANE_Cookie { uint16_t version; const char *vendor; const char *model; const char *revision; }; #endif typedef struct { /* magic bits :( */ uint32_t magic; struct SANE_Cookie *cookie_ptr; struct SANE_Cookie cookie; /* interface */ cs3_interface_t interface; int fd; SANE_Byte *send_buf, *recv_buf; size_t send_buf_size, recv_buf_size; size_t n_cmd, n_send, n_recv; /* device characteristics */ char vendor_string[9], product_string[17], revision_string[5]; cs3_type_t type; int maxbits; unsigned int resx_optical, resx_min, resx_max, *resx_list, resx_n_list; unsigned int resy_optical, resy_min, resy_max, *resy_list, resy_n_list; unsigned long boundaryx, boundaryy; unsigned long frame_offset; unsigned int unit_dpi; double unit_mm; int n_frames; int focus_min, focus_max; /* settings */ SANE_Bool preview, negative, infrared, autoload, autofocus, ae, aewb; int samples_per_scan, depth, real_depth, bytes_per_pixel, shift_bits, n_colors; cs3_pixel_t n_lut; cs3_pixel_t *lut_r, *lut_g, *lut_b, *lut_neutral; unsigned long resx, resy, res, res_independent, res_preview; unsigned long xmin, xmax, ymin, ymax; int i_frame, frame_count; double subframe; unsigned int real_resx, real_resy, real_pitchx, real_pitchy; unsigned long real_xoffset, real_yoffset, real_width, real_height, logical_width, logical_height; int odd_padding; int block_padding; double exposure, exposure_r, exposure_g, exposure_b; unsigned long real_exposure[CS3_COLOR_MAX]; SANE_Bool focus_on_centre; unsigned long focusx, focusy, real_focusx, real_focusy; int focus; /* status */ SANE_Bool scanning; SANE_Byte *line_buf; ssize_t n_line_buf, i_line_buf; unsigned long sense_key, sense_asc, sense_ascq, sense_info; unsigned long sense_code; cs3_status_t status; size_t xfer_position, xfer_bytes_total; /* SANE stuff */ SANE_Option_Descriptor option_list[CS3_N_OPTIONS]; } cs3_t; /* ========================================================================= */ /* prototypes */ static SANE_Status cs3_open(const char *device, cs3_interface_t interface, cs3_t ** sp); static void cs3_close(cs3_t * s); static SANE_Status cs3_attach(const char *dev); static SANE_Status cs3_scsi_sense_handler(int fd, u_char * sense_buffer, void *arg); static SANE_Status cs3_parse_sense_data(cs3_t * s); static void cs3_init_buffer(cs3_t * s); static SANE_Status cs3_pack_byte(cs3_t * s, SANE_Byte byte); static void cs3_pack_long(cs3_t * s, unsigned long val); static void cs3_pack_word(cs3_t * s, unsigned long val); static SANE_Status cs3_parse_cmd(cs3_t * s, char *text); static SANE_Status cs3_grow_send_buffer(cs3_t * s); static SANE_Status cs3_issue_cmd(cs3_t * s); static cs3_phase_t cs3_phase_check(cs3_t * s); static SANE_Status cs3_set_boundary(cs3_t * s); static SANE_Status cs3_scanner_ready(cs3_t * s, int flags); static SANE_Status cs3_page_inquiry(cs3_t * s, int page); static SANE_Status cs3_full_inquiry(cs3_t * s); static SANE_Status cs3_mode_select(cs3_t * s); static SANE_Status cs3_reserve_unit(cs3_t * s); static SANE_Status cs3_release_unit(cs3_t * s); static SANE_Status cs3_execute(cs3_t * s); static SANE_Status cs3_load(cs3_t * s); static SANE_Status cs3_eject(cs3_t * s); static SANE_Status cs3_reset(cs3_t * s); static SANE_Status cs3_set_focus(cs3_t * s); static SANE_Status cs3_autofocus(cs3_t * s); static SANE_Status cs3_autoexposure(cs3_t * s, int wb); static SANE_Status cs3_get_exposure(cs3_t * s); static SANE_Status cs3_set_window(cs3_t * s, cs3_scan_t type); static SANE_Status cs3_convert_options(cs3_t * s); static SANE_Status cs3_scan(cs3_t * s, cs3_scan_t type); static void *cs3_xmalloc(size_t size); static void *cs3_xrealloc(void *p, size_t size); static void cs3_xfree(void *p); /* ========================================================================= */ /* global variables */ static int cs3_colors[] = { 1, 2, 3, 9 }; static SANE_Device **device_list = NULL; static int n_device_list = 0; static cs3_interface_t try_interface = CS3_INTERFACE_UNKNOWN; static int open_devices = 0; /* ========================================================================= */ /* SANE entry points */ SANE_Status sane_init(SANE_Int * version_code, SANE_Auth_Callback authorize) { DBG_INIT(); DBG(1, "coolscan3 backend, version %i.%i.%i initializing.\n", CS3_VERSION_MAJOR, CS3_VERSION_MINOR, CS3_REVISION); authorize = authorize; /* to shut up compiler */ if (version_code) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, 0); sanei_usb_init(); return SANE_STATUS_GOOD; } void sane_exit(void) { int i; DBG(10, "%s\n", __func__); for (i = 0; i < n_device_list; i++) { cs3_xfree((void *)device_list[i]->name); cs3_xfree((void *)device_list[i]->vendor); cs3_xfree((void *)device_list[i]->model); cs3_xfree(device_list[i]); } cs3_xfree(device_list); } SANE_Status sane_get_devices(const SANE_Device *** list, SANE_Bool local_only) { char line[PATH_MAX], *p; FILE *config; local_only = local_only; /* to shut up compiler */ DBG(10, "%s\n", __func__); if (device_list) DBG(6, "sane_get_devices(): Device list already populated, not probing again.\n"); else { if (open_devices) { DBG(4, "sane_get_devices(): Devices open, not scanning for scanners.\n"); return SANE_STATUS_IO_ERROR; } config = sanei_config_open(CS3_CONFIG_FILE); if (config) { DBG(4, "sane_get_devices(): Reading config file.\n"); while (sanei_config_read(line, sizeof(line), config)) { p = line; p += strspn(line, " \t"); if (strlen(p) && (p[0] != '\n') && (p[0] != '#')) cs3_open(line, CS3_INTERFACE_UNKNOWN, NULL); } fclose(config); } else { DBG(4, "sane_get_devices(): No config file found.\n"); cs3_open("auto", CS3_INTERFACE_UNKNOWN, NULL); } DBG(6, "%s: %i device(s) detected.\n", __func__, n_device_list); } *list = (const SANE_Device **) device_list; return SANE_STATUS_GOOD; } SANE_Status sane_open(SANE_String_Const name, SANE_Handle * h) { SANE_Status status; cs3_t *s; int i_option; unsigned int i_list; SANE_Option_Descriptor o; SANE_Word *word_list; SANE_Range *range = NULL; int alloc_failed = 0; DBG(10, "%s\n", __func__); status = cs3_open(name, CS3_INTERFACE_UNKNOWN, &s); if (status != SANE_STATUS_GOOD) return status; *h = (SANE_Handle) s; /* get device properties */ s->lut_r = s->lut_g = s->lut_b = s->lut_neutral = NULL; s->resx_list = s->resy_list = NULL; s->resx_n_list = s->resy_n_list = 0; status = cs3_full_inquiry(s); if (status != SANE_STATUS_GOOD) return status; status = cs3_mode_select(s); if (status != SANE_STATUS_GOOD) return status; /* option descriptors */ for (i_option = 0; i_option < CS3_N_OPTIONS; i_option++) { o.name = o.title = o.desc = NULL; o.type = o.unit = o.cap = o.constraint_type = o.size = 0; o.constraint.range = NULL; /* only one union member needs to be NULLed */ switch (i_option) { case CS3_OPTION_NUM: o.name = ""; o.title = SANE_TITLE_NUM_OPTIONS; o.desc = SANE_DESC_NUM_OPTIONS; o.type = SANE_TYPE_INT; o.size = WSIZE; o.cap = SANE_CAP_SOFT_DETECT; break; case CS3_OPTION_PREVIEW: o.name = "preview"; o.title = "Preview mode"; o.desc = "Preview mode"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; break; case CS3_OPTION_NEGATIVE: o.name = "negative"; o.title = "Negative"; o.desc = "Negative film: make scanner invert colors"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /*o.cap |= SANE_CAP_INACTIVE; */ break; case CS3_OPTION_INFRARED: o.name = "infrared"; o.title = "Read infrared channel"; o.desc = "Read infrared channel in addition to scan colors"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; #ifndef SANE_FRAME_RGBI o.cap |= SANE_CAP_INACTIVE; #endif break; case CS3_OPTION_SAMPLES_PER_SCAN: o.name = "samples-per-scan"; o.title = "Samples per Scan"; o.desc = "Number of samples per scan"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (s->type != CS3_TYPE_LS2000 && s->type != CS3_TYPE_LS4000 && s->type != CS3_TYPE_LS5000 && s->type != CS3_TYPE_LS8000) o.cap |= SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc (sizeof (SANE_Range)); if (! range) alloc_failed = 1; else { range->min = 1; range->max = 16; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_DEPTH: o.name = "depth"; o.title = "Bit depth per channel"; o.desc = "Number of bits output by scanner for each channel"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_WORD_LIST; word_list = (SANE_Word *) cs3_xmalloc(2 * sizeof(SANE_Word)); if (!word_list) alloc_failed = 1; else { word_list[1] = 8; word_list[2] = s->maxbits; word_list[0] = 2; o.constraint.word_list = word_list; } break; case CS3_OPTION_EXPOSURE: o.name = "exposure"; o.title = "Exposure multiplier"; o.desc = "Exposure multiplier for all channels"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX(0.); range->max = SANE_FIX(10.); range->quant = SANE_FIX(0.1); o.constraint.range = range; } break; case CS3_OPTION_EXPOSURE_R: o.name = "red-exposure"; o.title = "Red exposure time"; o.desc = "Exposure time for red channel"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_MICROSECOND; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX(50.); range->max = SANE_FIX(20000.); range->quant = SANE_FIX(10.); o.constraint.range = range; } break; case CS3_OPTION_EXPOSURE_G: o.name = "green-exposure"; o.title = "Green exposure time"; o.desc = "Exposure time for green channel"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_MICROSECOND; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX(50.); range->max = SANE_FIX(20000.); range->quant = SANE_FIX(10.); o.constraint.range = range; } break; case CS3_OPTION_EXPOSURE_B: o.name = "blue-exposure"; o.title = "Blue exposure time"; o.desc = "Exposure time for blue channel"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_MICROSECOND; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX(50.); range->max = SANE_FIX(20000.); range->quant = SANE_FIX(10.); o.constraint.range = range; } break; case CS3_OPTION_LUT_R: o.name = "red-gamma-table"; o.title = "LUT for red channel"; o.desc = "LUT for red channel"; o.type = SANE_TYPE_INT; o.size = s->n_lut * WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->n_lut - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_LUT_G: o.name = "green-gamma-table"; o.title = "LUT for green channel"; o.desc = "LUT for green channel"; o.type = SANE_TYPE_INT; o.size = s->n_lut * WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->n_lut - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_LUT_B: o.name = "blue-gamma-table"; o.title = "LUT for blue channel"; o.desc = "LUT for blue channel"; o.type = SANE_TYPE_INT; o.size = s->n_lut * WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->n_lut - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_LOAD: o.name = "load"; o.title = "Load"; o.desc = "Load next slide"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (s->n_frames > 1) o.cap |= SANE_CAP_INACTIVE; break; case CS3_OPTION_AUTOLOAD: o.name = "autoload"; o.title = "Autoload"; o.desc = "Autoload slide before each scan"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (s->n_frames > 1) o.cap |= SANE_CAP_INACTIVE; break; case CS3_OPTION_EJECT: o.name = "eject"; o.title = "Eject"; o.desc = "Eject loaded medium"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS3_OPTION_RESET: o.name = "reset"; o.title = "Reset scanner"; o.desc = "Initialize scanner"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS3_OPTION_RESX: case CS3_OPTION_RES: case CS3_OPTION_PREVIEW_RESOLUTION: if (i_option == CS3_OPTION_PREVIEW_RESOLUTION) { o.name = "preview-resolution"; o.title = "Preview resolution"; o.desc = "Scanning resolution for preview mode in dpi, affecting both x and y directions"; } else if (i_option == CS3_OPTION_RES) { o.name = "resolution"; o.title = "Resolution"; o.desc = "Scanning resolution in dpi, affecting both x and y directions"; } else { o.name = "x-resolution"; o.title = "X resolution"; o.desc = "Scanning resolution in dpi, affecting x direction only"; } o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_DPI; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (i_option == CS3_OPTION_RESX) o.cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; if (i_option == CS3_OPTION_PREVIEW_RESOLUTION) o.cap |= SANE_CAP_ADVANCED; o.constraint_type = SANE_CONSTRAINT_WORD_LIST; word_list = (SANE_Word *) cs3_xmalloc((s->resx_n_list + 1) * sizeof(SANE_Word)); if (!word_list) alloc_failed = 1; else { for (i_list = 0; i_list < s->resx_n_list; i_list++) word_list[i_list + 1] = s->resx_list[i_list]; word_list[0] = s->resx_n_list; o.constraint.word_list = word_list; } break; case CS3_OPTION_RESY: o.name = "y-resolution"; o.title = "Y resolution"; o.desc = "Scanning resolution in dpi, affecting y direction only"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_DPI; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; o.constraint_type = SANE_CONSTRAINT_WORD_LIST; word_list = (SANE_Word *) cs3_xmalloc((s->resy_n_list + 1) * sizeof(SANE_Word)); if (!word_list) alloc_failed = 1; else { for (i_list = 0; i_list < s->resy_n_list; i_list++) word_list[i_list + 1] = s->resy_list[i_list]; word_list[0] = s->resy_n_list; o.constraint.word_list = word_list; } break; case CS3_OPTION_RES_INDEPENDENT: o.name = "independent-res"; o.title = "Independent x/y resolutions"; o.desc = "Enable independent controls for scanning resolution in x and y direction"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; break; case CS3_OPTION_FRAME: o.name = "frame"; o.title = "Frame number"; o.desc = "Number of frame to be scanned, starting with 1"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (s->n_frames <= 1) o.cap |= SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 1; range->max = s->n_frames; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_FRAME_COUNT: o.name = "frame-count"; o.title = "Frame count"; o.desc = "Amount of frames to scan"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (s->n_frames <= 1) o.cap |= SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 1; range->max = s->n_frames - s->i_frame + 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_SUBFRAME: o.name = "subframe"; o.title = "Frame shift"; o.desc = "Fine position within the selected frame"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_MM; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX(0.); range->max = SANE_FIX((s->boundaryy - 1) * s->unit_mm); range->quant = SANE_FIX(0.); o.constraint.range = range; } break; case CS3_OPTION_XMIN: o.name = "tl-x"; o.title = "Left x value of scan area"; o.desc = "Left x value of scan area"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; if (!range) alloc_failed = 1; else { range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); range->min = 0; range->max = s->boundaryx - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_XMAX: o.name = "br-x"; o.title = "Right x value of scan area"; o.desc = "Right x value of scan area"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryx - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_YMIN: o.name = "tl-y"; o.title = "Top y value of scan area"; o.desc = "Top y value of scan area"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryy - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_YMAX: o.name = "br-y"; o.title = "Bottom y value of scan area"; o.desc = "Bottom y value of scan area"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryy - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_FOCUS_ON_CENTRE: o.name = "focus-on-centre"; o.title = "Use centre of scan area as AF point"; o.desc = "Use centre of scan area as AF point instead of manual AF point selection"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS3_OPTION_FOCUS: o.name = "focus"; o.title = "Focus position"; o.desc = "Focus position for manual focus"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = s->focus_min; range->max = s->focus_max; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_AUTOFOCUS: o.name = "autofocus"; o.title = "Autofocus"; o.desc = "Perform autofocus before scan"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS3_OPTION_FOCUSX: o.name = "focusx"; o.title = "X coordinate of AF point"; o.desc = "X coordinate of AF point"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryx - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_FOCUSY: o.name = "focusy"; o.title = "Y coordinate of AF point"; o.desc = "Y coordinate of AF point"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs3_xmalloc(sizeof(SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryy - 1; range->quant = 1; o.constraint.range = range; } break; case CS3_OPTION_SCAN_AE: o.name = "ae"; o.title = "Auto-exposure"; o.desc = "Perform auto-exposure before scan"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS3_OPTION_SCAN_AE_WB: o.name = "ae-wb"; o.title = "Auto-exposure with white balance"; o.desc = "Perform auto-exposure with white balance before scan"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; default: DBG(1, "BUG: sane_open(): Unknown option number: %d\n", i_option); break; } s->option_list[i_option] = o; } s->scanning = SANE_FALSE; s->preview = SANE_FALSE; s->negative = SANE_FALSE; s->autoload = SANE_FALSE; s->infrared = SANE_FALSE; s->ae = SANE_FALSE; s->aewb = SANE_FALSE; s->samples_per_scan = 1; s->depth = 8; s->i_frame = 1; s->frame_count = 1; s->subframe = 0.; s->res = s->resx = s->resx_max; s->resy = s->resy_max; s->res_independent = SANE_FALSE; s->res_preview = s->resx_max / 10; if (s->res_preview < s->resx_min) s->res_preview = s->resx_min; s->xmin = 0; s->xmax = s->boundaryx - 1; s->ymin = 0; s->ymax = s->boundaryy - 1; s->focus_on_centre = SANE_TRUE; s->focus = 0; s->focusx = 0; s->focusy = 0; s->exposure = 1.; s->exposure_r = 1200.; s->exposure_g = 1200.; s->exposure_b = 1000.; s->line_buf = NULL; s->n_line_buf = 0; if (alloc_failed) { cs3_close(s); return SANE_STATUS_NO_MEM; } return cs3_reserve_unit(s); } void sane_close(SANE_Handle h) { cs3_t *s = (cs3_t *) h; DBG(10, "%s\n", __func__); cs3_release_unit(s); cs3_close(s); } const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle h, SANE_Int n) { cs3_t *s = (cs3_t *) h; DBG(24, "%s, option %i\n", __func__, n); if ((n >= 0) && (n < CS3_N_OPTIONS)) return &s->option_list[n]; else return NULL; } SANE_Status sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int * i) { cs3_t *s = (cs3_t *) h; SANE_Int flags = 0; cs3_pixel_t pixel; SANE_Option_Descriptor o = s->option_list[n]; DBG(24, "%s, option %i, action %i.\n", __func__, n, a); switch (a) { case SANE_ACTION_GET_VALUE: switch (n) { case CS3_OPTION_NUM: *(SANE_Word *) v = CS3_N_OPTIONS; break; case CS3_OPTION_NEGATIVE: *(SANE_Word *) v = s->negative; break; case CS3_OPTION_INFRARED: *(SANE_Word *) v = s->infrared; break; case CS3_OPTION_SAMPLES_PER_SCAN: *(SANE_Word *) v = s->samples_per_scan; break; case CS3_OPTION_DEPTH: *(SANE_Word *) v = s->depth; break; case CS3_OPTION_PREVIEW: *(SANE_Word *) v = s->preview; break; case CS3_OPTION_AUTOLOAD: *(SANE_Word *) v = s->autoload; break; case CS3_OPTION_EXPOSURE: *(SANE_Word *) v = SANE_FIX(s->exposure); break; case CS3_OPTION_EXPOSURE_R: *(SANE_Word *) v = SANE_FIX(s->exposure_r); break; case CS3_OPTION_EXPOSURE_G: *(SANE_Word *) v = SANE_FIX(s->exposure_g); break; case CS3_OPTION_EXPOSURE_B: *(SANE_Word *) v = SANE_FIX(s->exposure_b); break; case CS3_OPTION_LUT_R: if (!(s->lut_r)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) ((SANE_Word *) v)[pixel] = s->lut_r[pixel]; break; case CS3_OPTION_LUT_G: if (!(s->lut_g)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) ((SANE_Word *) v)[pixel] = s->lut_g[pixel]; break; case CS3_OPTION_LUT_B: if (!(s->lut_b)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) ((SANE_Word *) v)[pixel] = s->lut_b[pixel]; break; case CS3_OPTION_EJECT: break; case CS3_OPTION_LOAD: break; case CS3_OPTION_RESET: break; case CS3_OPTION_FRAME: *(SANE_Word *) v = s->i_frame; break; case CS3_OPTION_FRAME_COUNT: *(SANE_Word *) v = s->frame_count; break; case CS3_OPTION_SUBFRAME: *(SANE_Word *) v = SANE_FIX(s->subframe); break; case CS3_OPTION_RES: *(SANE_Word *) v = s->res; break; case CS3_OPTION_RESX: *(SANE_Word *) v = s->resx; break; case CS3_OPTION_RESY: *(SANE_Word *) v = s->resy; break; case CS3_OPTION_RES_INDEPENDENT: *(SANE_Word *) v = s->res_independent; break; case CS3_OPTION_PREVIEW_RESOLUTION: *(SANE_Word *) v = s->res_preview; break; case CS3_OPTION_XMIN: *(SANE_Word *) v = s->xmin; break; case CS3_OPTION_XMAX: *(SANE_Word *) v = s->xmax; break; case CS3_OPTION_YMIN: *(SANE_Word *) v = s->ymin; break; case CS3_OPTION_YMAX: *(SANE_Word *) v = s->ymax; break; case CS3_OPTION_FOCUS_ON_CENTRE: *(SANE_Word *) v = s->focus_on_centre; break; case CS3_OPTION_FOCUS: *(SANE_Word *) v = s->focus; break; case CS3_OPTION_AUTOFOCUS: *(SANE_Word *) v = s->autofocus; break; case CS3_OPTION_FOCUSX: *(SANE_Word *) v = s->focusx; break; case CS3_OPTION_FOCUSY: *(SANE_Word *) v = s->focusy; break; case CS3_OPTION_SCAN_AE: *(SANE_Word *) v = s->ae; break; case CS3_OPTION_SCAN_AE_WB: *(SANE_Word *) v = s->aewb; break; default: DBG(4, "%s: Unknown option (bug?).\n", __func__); return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: if (s->scanning) return SANE_STATUS_INVAL; /* XXX do this for all elements of arrays */ switch (o.type) { case SANE_TYPE_BOOL: if ((*(SANE_Word *) v != SANE_TRUE) && (*(SANE_Word *) v != SANE_FALSE)) return SANE_STATUS_INVAL; break; case SANE_TYPE_INT: case SANE_TYPE_FIXED: switch (o.constraint_type) { case SANE_CONSTRAINT_RANGE: if (*(SANE_Word *) v < o.constraint.range->min) { *(SANE_Word *) v = o.constraint.range->min; flags |= SANE_INFO_INEXACT; } else if (*(SANE_Word *) v > o.constraint.range->max) { *(SANE_Word *) v = o.constraint.range->max; flags |= SANE_INFO_INEXACT; } break; case SANE_CONSTRAINT_WORD_LIST: break; default: break; } break; case SANE_TYPE_STRING: break; case SANE_TYPE_BUTTON: break; case SANE_TYPE_GROUP: break; } switch (n) { case CS3_OPTION_NUM: return SANE_STATUS_INVAL; break; case CS3_OPTION_NEGATIVE: s->negative = *(SANE_Word *) v; break; case CS3_OPTION_INFRARED: s->infrared = *(SANE_Word *) v; /* flags |= SANE_INFO_RELOAD_PARAMS; XXX */ break; case CS3_OPTION_SAMPLES_PER_SCAN: s->samples_per_scan = *(SANE_Word *) v; break; case CS3_OPTION_DEPTH: if (*(SANE_Word *) v > s->maxbits) return SANE_STATUS_INVAL; s->depth = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_PREVIEW: s->preview = *(SANE_Word *) v; break; case CS3_OPTION_AUTOLOAD: s->autoload = *(SANE_Word *) v; break; case CS3_OPTION_EXPOSURE: s->exposure = SANE_UNFIX(*(SANE_Word *) v); break; case CS3_OPTION_EXPOSURE_R: s->exposure_r = SANE_UNFIX(*(SANE_Word *) v); break; case CS3_OPTION_EXPOSURE_G: s->exposure_g = SANE_UNFIX(*(SANE_Word *) v); break; case CS3_OPTION_EXPOSURE_B: s->exposure_b = SANE_UNFIX(*(SANE_Word *) v); break; case CS3_OPTION_LUT_R: if (!(s->lut_r)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) s->lut_r[pixel] = ((SANE_Word *) v)[pixel]; break; case CS3_OPTION_LUT_G: if (!(s->lut_g)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) s->lut_g[pixel] = ((SANE_Word *) v)[pixel]; break; case CS3_OPTION_LUT_B: if (!(s->lut_b)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) s->lut_b[pixel] = ((SANE_Word *) v)[pixel]; break; case CS3_OPTION_LOAD: cs3_load(s); break; case CS3_OPTION_EJECT: cs3_eject(s); break; case CS3_OPTION_RESET: cs3_reset(s); break; case CS3_OPTION_FRAME: s->i_frame = *(SANE_Word *) v; break; case CS3_OPTION_FRAME_COUNT: if (*(SANE_Word *) v > (s->n_frames - s->i_frame + 1)) return SANE_STATUS_INVAL; s->frame_count = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_SUBFRAME: s->subframe = SANE_UNFIX(*(SANE_Word *) v); break; case CS3_OPTION_RES: s->res = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_RESX: s->resx = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_RESY: s->resy = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_RES_INDEPENDENT: s->res_independent = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_PREVIEW_RESOLUTION: s->res_preview = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_XMIN: s->xmin = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_XMAX: s->xmax = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_YMIN: s->ymin = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_YMAX: s->ymax = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS3_OPTION_FOCUS_ON_CENTRE: s->focus_on_centre = *(SANE_Word *) v; if (s->focus_on_centre) { s->option_list[CS3_OPTION_FOCUSX].cap |= SANE_CAP_INACTIVE; s->option_list[CS3_OPTION_FOCUSY].cap |= SANE_CAP_INACTIVE; } else { s->option_list[CS3_OPTION_FOCUSX].cap &= ~SANE_CAP_INACTIVE; s->option_list[CS3_OPTION_FOCUSY].cap &= ~SANE_CAP_INACTIVE; } flags |= SANE_INFO_RELOAD_OPTIONS; break; case CS3_OPTION_FOCUS: s->focus = *(SANE_Word *) v; break; case CS3_OPTION_AUTOFOCUS: s->autofocus = *(SANE_Word *) v; break; case CS3_OPTION_FOCUSX: s->focusx = *(SANE_Word *) v; break; case CS3_OPTION_FOCUSY: s->focusy = *(SANE_Word *) v; break; case CS3_OPTION_SCAN_AE: s->ae = *(SANE_Word *) v; break; case CS3_OPTION_SCAN_AE_WB: s->aewb = *(SANE_Word *) v; break; default: DBG(4, "Error: sane_control_option(): Unknown option number (bug?).\n"); return SANE_STATUS_INVAL; break; } break; default: DBG(1, "BUG: sane_control_option(): Unknown action number.\n"); return SANE_STATUS_INVAL; break; } if (i) *i = flags; return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters(SANE_Handle h, SANE_Parameters * p) { cs3_t *s = (cs3_t *) h; SANE_Status status; DBG(10, "%s\n", __func__); if (!s->scanning) { /* only recalculate when not scanning */ status = cs3_convert_options(s); if (status != SANE_STATUS_GOOD) return status; } p->bytes_per_line = s->n_colors * s->logical_width * s->bytes_per_pixel; #ifdef SANE_FRAME_RGBI if (s->infrared) { p->format = SANE_FRAME_RGBI; } else { #endif p->format = SANE_FRAME_RGB; /* XXXXXXXX CCCCCCCCCC */ #ifdef SANE_FRAME_RGBI } #endif p->last_frame = SANE_TRUE; p->lines = s->logical_height; p->depth = 8 * s->bytes_per_pixel; p->pixels_per_line = s->logical_width; return SANE_STATUS_GOOD; } SANE_Status sane_start(SANE_Handle h) { cs3_t *s = (cs3_t *) h; SANE_Status status; DBG(10, "%s\n", __func__); if (s->scanning) return SANE_STATUS_INVAL; if (s->n_frames > 1 && s->frame_count == 0) { DBG(4, "%s: no more frames\n", __func__); return SANE_STATUS_NO_DOCS; } if (s->n_frames > 1) { DBG(4, "%s: scanning frame at position %d, %d to go\n", __func__, s->i_frame, s->frame_count); } status = cs3_convert_options(s); if (status != SANE_STATUS_GOOD) return status; s->i_line_buf = 0; s->xfer_position = 0; s->scanning = SANE_TRUE; /* load if appropriate */ if (s->autoload) { status = cs3_load(s); if (status != SANE_STATUS_GOOD) return status; } /* check for documents */ status = cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); if (status != SANE_STATUS_GOOD) return status; if (s->status & CS3_STATUS_NO_DOCS) return SANE_STATUS_NO_DOCS; if (s->autofocus) { status = cs3_autofocus(s); if (status != SANE_STATUS_GOOD) return status; } if (s->aewb) { status = cs3_autoexposure(s, 1); if (status != SANE_STATUS_GOOD) return status; } else if (s->ae) { status = cs3_autoexposure(s, 0); if (status != SANE_STATUS_GOOD) return status; } return cs3_scan(s, CS3_SCAN_NORMAL); } SANE_Status sane_read(SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) { cs3_t *s = (cs3_t *) h; SANE_Status status; ssize_t xfer_len_in, xfer_len_line, xfer_len_out; unsigned long index; int color, sample_pass; uint8_t *s8 = NULL; uint16_t *s16 = NULL; double m_avg_sum; SANE_Byte *line_buf_new; DBG(32, "%s, maxlen = %i.\n", __func__, maxlen); if (!s->scanning) { *len = 0; return SANE_STATUS_CANCELLED; } /* transfer from buffer */ if (s->i_line_buf > 0) { xfer_len_out = s->n_line_buf - s->i_line_buf; if (xfer_len_out > maxlen) xfer_len_out = maxlen; memcpy(buf, &(s->line_buf[s->i_line_buf]), xfer_len_out); s->i_line_buf += xfer_len_out; if (s->i_line_buf >= s->n_line_buf) s->i_line_buf = 0; *len = xfer_len_out; return SANE_STATUS_GOOD; } xfer_len_line = s->n_colors * s->logical_width * s->bytes_per_pixel; xfer_len_in = xfer_len_line + (s->n_colors * s->odd_padding); if ((xfer_len_in & 0x3f)) { int d = ((xfer_len_in / 512) * 512) + 512; s->block_padding = d - xfer_len_in; } DBG(22, "%s: block_padding = %d, odd_padding = %d\n", __func__, s->block_padding, s->odd_padding); DBG(22, "%s: colors = %d, logical_width = %ld, bytes_per_pixel = %d\n", __func__, s->n_colors, s->logical_width, s->bytes_per_pixel); /* Do not change the behaviour of older models, pad to 512 */ if ((s->type == CS3_TYPE_LS50) || (s->type == CS3_TYPE_LS5000)) { xfer_len_in += s->block_padding; if (xfer_len_in & 0x3f) DBG(1, "BUG: %s, not a multiple of 64. (0x%06lx)\n", __func__, (long) xfer_len_in); } if (s->xfer_position + xfer_len_line > s->xfer_bytes_total) xfer_len_line = s->xfer_bytes_total - s->xfer_position; /* just in case */ if (xfer_len_line == 0) { /* no more data */ *len = 0; /* increment frame number if appropriate */ if (s->n_frames > 1 && --s->frame_count) { s->i_frame++; } s->scanning = SANE_FALSE; return SANE_STATUS_EOF; } if (xfer_len_line != s->n_line_buf) { line_buf_new = (SANE_Byte *) cs3_xrealloc(s->line_buf, xfer_len_line * sizeof(SANE_Byte)); if (!line_buf_new) { *len = 0; return SANE_STATUS_NO_MEM; } s->line_buf = line_buf_new; s->n_line_buf = xfer_len_line; } /* adapt for multi-sampling */ xfer_len_in *= s->samples_per_scan; cs3_scanner_ready(s, CS3_STATUS_READY); cs3_init_buffer(s); cs3_parse_cmd(s, "28 00 00 00 00 00"); cs3_pack_byte(s, (xfer_len_in >> 16) & 0xff); cs3_pack_byte(s, (xfer_len_in >> 8) & 0xff); cs3_pack_byte(s, xfer_len_in & 0xff); cs3_parse_cmd(s, "00"); s->n_recv = xfer_len_in; status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) { *len = 0; return status; } for (index = 0; index < s->logical_width; index++) { for (color = 0; color < s->n_colors; color++) { int where = s->bytes_per_pixel * (s->n_colors * index + color); m_avg_sum = 0.0; switch (s->bytes_per_pixel) { case 1: { /* target address */ s8 = (uint8_t *) & (s->line_buf[where]); if (s->samples_per_scan > 1) { /* calculate average of multi samples */ for (sample_pass = 0; sample_pass < s->samples_per_scan; sample_pass++) { /* source index */ int p8 = (sample_pass * s->n_colors + color) * s->logical_width + (color + 1) * s->odd_padding + index; m_avg_sum += (double) s->recv_buf[p8]; } *s8 = (uint8_t) (m_avg_sum / s->samples_per_scan + 0.5); } else { /* shortcut for single sample */ int p8 = s->logical_width * color + (color + 1) * s->odd_padding + index; *s8 = s->recv_buf[p8]; } } break; case 2: { /* target address */ s16 = (uint16_t *) & (s->line_buf[where]); if (s->samples_per_scan > 1) { /* calculate average of multi samples */ for (sample_pass = 0; sample_pass < s->samples_per_scan; sample_pass++) { /* source index */ int p16 = 2 * ((sample_pass * s->n_colors + color) * s->logical_width + index); m_avg_sum += (double) ((s->recv_buf[p16] << 8) + s->recv_buf[p16 + 1]); } *s16 = (uint16_t) (m_avg_sum / s->samples_per_scan + 0.5); } else { /* shortcut for single sample */ int p16 = 2 * (color * s->logical_width + index); *s16 = (s->recv_buf[p16] << 8) + s->recv_buf[p16 + 1]; } *s16 <<= s->shift_bits; } break; default: DBG(1, "BUG: sane_read(): Unknown number of bytes per pixel.\n"); *len = 0; return SANE_STATUS_INVAL; break; } } } s->xfer_position += xfer_len_line; xfer_len_out = xfer_len_line; if (xfer_len_out > maxlen) xfer_len_out = maxlen; memcpy(buf, s->line_buf, xfer_len_out); if (xfer_len_out < xfer_len_line) s->i_line_buf = xfer_len_out; /* data left in the line buffer, read out next time */ *len = xfer_len_out; return SANE_STATUS_GOOD; } void sane_cancel(SANE_Handle h) { cs3_t *s = (cs3_t *) h; DBG(10, "%s, scanning = %d.\n", __func__, s->scanning); if (s->scanning) { cs3_init_buffer(s); cs3_parse_cmd(s, "c0 00 00 00 00 00"); cs3_issue_cmd(s); } s->scanning = SANE_FALSE; } SANE_Status sane_set_io_mode(SANE_Handle h, SANE_Bool m) { cs3_t *s = (cs3_t *) h; DBG(10, "%s\n", __func__); if (!s->scanning) return SANE_STATUS_INVAL; if (m == SANE_FALSE) return SANE_STATUS_GOOD; else return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd(SANE_Handle h, SANE_Int * fd) { cs3_t *s = (cs3_t *) h; DBG(10, "%s\n", __func__); fd = fd; /* to shut up compiler */ s = s; /* to shut up compiler */ return SANE_STATUS_UNSUPPORTED; } /* ========================================================================= */ /* private functions */ static void cs3_trim(char *s) { int i, l = strlen(s); for (i = l - 1; i > 0; i--) { if (s[i] == ' ') s[i] = '\0'; else break; } } static SANE_Status cs3_open(const char *device, cs3_interface_t interface, cs3_t ** sp) { SANE_Status status; cs3_t *s; char *prefix = NULL, *line; int i; int alloc_failed = 0; SANE_Device **device_list_new; DBG(6, "%s, device = %s, interface = %i\n", __func__, device, interface); if (!strncmp(device, "auto", 5)) { try_interface = CS3_INTERFACE_SCSI; sanei_config_attach_matching_devices("scsi Nikon *", cs3_attach); try_interface = CS3_INTERFACE_USB; sanei_usb_attach_matching_devices("usb 0x04b0 0x4000", cs3_attach); sanei_usb_attach_matching_devices("usb 0x04b0 0x4001", cs3_attach); sanei_usb_attach_matching_devices("usb 0x04b0 0x4002", cs3_attach); return SANE_STATUS_GOOD; } if ((s = (cs3_t *) cs3_xmalloc(sizeof(cs3_t))) == NULL) return SANE_STATUS_NO_MEM; memset(s, 0, sizeof(cs3_t)); /* fill magic bits */ s->magic = SANE_COOKIE; s->cookie_ptr = &s->cookie; s->cookie.version = 0x01; s->cookie.vendor = s->vendor_string; s->cookie.model = s->product_string; s->cookie.revision = s->revision_string; s->send_buf = s->recv_buf = NULL; s->send_buf_size = s->recv_buf_size = 0; switch (interface) { case CS3_INTERFACE_UNKNOWN: for (i = 0; i < 2; i++) { switch (i) { case 1: prefix = "usb:"; try_interface = CS3_INTERFACE_USB; break; default: prefix = "scsi:"; try_interface = CS3_INTERFACE_SCSI; break; } if (!strncmp(device, prefix, strlen(prefix))) { const void *p = device + strlen(prefix); cs3_xfree(s); return cs3_open(p, try_interface, sp); } } cs3_xfree(s); return SANE_STATUS_INVAL; break; case CS3_INTERFACE_SCSI: s->interface = CS3_INTERFACE_SCSI; DBG(6, "%s, trying to open %s, assuming SCSI or SBP2 interface\n", __func__, device); status = sanei_scsi_open(device, &s->fd, cs3_scsi_sense_handler, s); if (status != SANE_STATUS_GOOD) { DBG(6, " ...failed: %s.\n", sane_strstatus(status)); cs3_xfree(s); return status; } break; case CS3_INTERFACE_USB: s->interface = CS3_INTERFACE_USB; DBG(6, "%s, trying to open %s, assuming USB interface\n", __func__, device); status = sanei_usb_open(device, &s->fd); if (status != SANE_STATUS_GOOD) { DBG(6, " ...failed: %s.\n", sane_strstatus(status)); cs3_xfree(s); return status; } break; } open_devices++; DBG(6, "%s, trying to identify device.\n", __func__); /* identify scanner */ status = cs3_page_inquiry(s, -1); if (status != SANE_STATUS_GOOD) { cs3_close(s); return status; } strncpy(s->vendor_string, (char *) s->recv_buf + 8, 8); s->vendor_string[8] = '\0'; strncpy(s->product_string, (char *) s->recv_buf + 16, 16); s->product_string[16] = '\0'; strncpy(s->revision_string, (char *) s->recv_buf + 32, 4); s->revision_string[4] = '\0'; DBG(10, "%s, vendor = '%s', product = '%s', revision = '%s'.\n", __func__, s->vendor_string, s->product_string, s->revision_string); if (!strncmp(s->product_string, "COOLSCANIII ", 16)) s->type = CS3_TYPE_LS30; else if (!strncmp(s->product_string, "LS-40 ED ", 16)) s->type = CS3_TYPE_LS40; else if (!strncmp(s->product_string, "LS-50 ED ", 16)) s->type = CS3_TYPE_LS50; else if (!strncmp(s->product_string, "LS-2000 ", 16)) s->type = CS3_TYPE_LS2000; else if (!strncmp(s->product_string, "LS-4000 ED ", 16)) s->type = CS3_TYPE_LS4000; else if (!strncmp(s->product_string, "LS-5000 ED ", 16)) s->type = CS3_TYPE_LS5000; else if (!strncmp(s->product_string, "LS-8000 ED ", 16)) s->type = CS3_TYPE_LS8000; if (s->type != CS3_TYPE_UNKOWN) DBG(10, "%s, device identified as coolscan3 type #%i.\n", __func__, s->type); else { DBG(10, "%s, device not identified.\n", __func__); cs3_close(s); return SANE_STATUS_UNSUPPORTED; } cs3_trim(s->vendor_string); cs3_trim(s->product_string); cs3_trim(s->revision_string); if (sp) *sp = s; else { device_list_new = (SANE_Device **) cs3_xrealloc(device_list, (n_device_list + 2) * sizeof(SANE_Device *)); if (!device_list_new) return SANE_STATUS_NO_MEM; device_list = device_list_new; device_list[n_device_list] = (SANE_Device *) cs3_xmalloc(sizeof(SANE_Device)); if (!device_list[n_device_list]) return SANE_STATUS_NO_MEM; switch (interface) { case CS3_INTERFACE_UNKNOWN: DBG(1, "BUG: cs3_open(): unknown interface.\n"); cs3_close(s); return SANE_STATUS_UNSUPPORTED; break; case CS3_INTERFACE_SCSI: prefix = "scsi:"; break; case CS3_INTERFACE_USB: prefix = "usb:"; break; } line = (char *) cs3_xmalloc(strlen(device) + strlen(prefix) + 1); if (!line) alloc_failed = 1; else { strcpy(line, prefix); strcat(line, device); device_list[n_device_list]->name = line; } line = (char *) cs3_xmalloc(strlen(s->vendor_string) + 1); if (!line) alloc_failed = 1; else { strcpy(line, s->vendor_string); device_list[n_device_list]->vendor = line; } line = (char *) cs3_xmalloc(strlen(s->product_string) + 1); if (!line) alloc_failed = 1; else { strcpy(line, s->product_string); device_list[n_device_list]->model = line; } device_list[n_device_list]->type = "film scanner"; if (alloc_failed) { cs3_xfree((void *)device_list[n_device_list]->name); cs3_xfree((void *)device_list[n_device_list]->vendor); cs3_xfree((void *)device_list[n_device_list]->model); cs3_xfree(device_list[n_device_list]); } else n_device_list++; device_list[n_device_list] = NULL; cs3_close(s); } return SANE_STATUS_GOOD; } void cs3_close(cs3_t * s) { cs3_xfree(s->lut_r); cs3_xfree(s->lut_g); cs3_xfree(s->lut_b); cs3_xfree(s->lut_neutral); cs3_xfree(s->line_buf); switch (s->interface) { case CS3_INTERFACE_UNKNOWN: DBG(0, "BUG: %s: Unknown interface number.\n", __func__); break; case CS3_INTERFACE_SCSI: sanei_scsi_close(s->fd); open_devices--; break; case CS3_INTERFACE_USB: sanei_usb_close(s->fd); open_devices--; break; } cs3_xfree(s); } static SANE_Status cs3_attach(const char *dev) { SANE_Status status; if (try_interface == CS3_INTERFACE_UNKNOWN) return SANE_STATUS_UNSUPPORTED; status = cs3_open(dev, try_interface, NULL); return status; } static SANE_Status cs3_scsi_sense_handler(int fd, u_char * sense_buffer, void *arg) { cs3_t *s = (cs3_t *) arg; fd = fd; /* to shut up compiler */ /* sort this out ! XXX */ s->sense_key = sense_buffer[2] & 0x0f; s->sense_asc = sense_buffer[12]; s->sense_ascq = sense_buffer[13]; s->sense_info = sense_buffer[3]; return cs3_parse_sense_data(s); } static SANE_Status cs3_parse_sense_data(cs3_t * s) { SANE_Status status = SANE_STATUS_GOOD; s->sense_code = (s->sense_key << 24) + (s->sense_asc << 16) + (s->sense_ascq << 8) + s->sense_info; if (s->sense_key) DBG(14, "sense code: %02lx-%02lx-%02lx-%02lx\n", s->sense_key, s->sense_asc, s->sense_ascq, s->sense_info); switch (s->sense_key) { case 0x00: s->status = CS3_STATUS_READY; break; case 0x02: switch (s->sense_asc) { case 0x04: DBG(15, " processing\n"); s->status = CS3_STATUS_PROCESSING; break; case 0x3a: DBG(15, " no docs\n"); s->status = CS3_STATUS_NO_DOCS; break; default: DBG(15, " default\n"); s->status = CS3_STATUS_ERROR; status = SANE_STATUS_IO_ERROR; break; } break; case 0x09: if ((s->sense_code == 0x09800600) || (s->sense_code == 0x09800601)) s->status = CS3_STATUS_REISSUE; break; default: s->status = CS3_STATUS_ERROR; status = SANE_STATUS_IO_ERROR; break; } return status; } static void cs3_init_buffer(cs3_t * s) { s->n_cmd = 0; s->n_send = 0; s->n_recv = 0; } static SANE_Status cs3_pack_byte(cs3_t * s, SANE_Byte byte) { while (s->send_buf_size <= s->n_send) { s->send_buf_size += 16; s->send_buf = (SANE_Byte *) cs3_xrealloc(s->send_buf, s->send_buf_size); if (!s->send_buf) return SANE_STATUS_NO_MEM; } s->send_buf[s->n_send++] = byte; return SANE_STATUS_GOOD; } static void cs3_pack_long(cs3_t * s, unsigned long val) { cs3_pack_byte(s, (val >> 24) & 0xff); cs3_pack_byte(s, (val >> 16) & 0xff); cs3_pack_byte(s, (val >> 8) & 0xff); cs3_pack_byte(s, val & 0xff); } static void cs3_pack_word(cs3_t * s, unsigned long val) { cs3_pack_byte(s, (val >> 8) & 0xff); cs3_pack_byte(s, val & 0xff); } static SANE_Status cs3_parse_cmd(cs3_t * s, char *text) { size_t i, j; char c, h; SANE_Status status; for (i = 0; i < strlen(text); i += 2) if (text[i] == ' ') i--; /* a bit dirty... advance by -1+2=1 */ else { if ((!isxdigit(text[i])) || (!isxdigit(text[i + 1]))) DBG(1, "BUG: cs3_parse_cmd(): Parser got invalid character.\n"); c = 0; for (j = 0; j < 2; j++) { h = tolower(text[i + j]); if ((h >= 'a') && (h <= 'f')) c += 10 + h - 'a'; else c += h - '0'; if (j == 0) c <<= 4; } status = cs3_pack_byte(s, c); if (status != SANE_STATUS_GOOD) return status; } return SANE_STATUS_GOOD; } static SANE_Status cs3_grow_send_buffer(cs3_t * s) { if (s->n_send > s->send_buf_size) { s->send_buf_size = s->n_send; s->send_buf = (SANE_Byte *) cs3_xrealloc(s->send_buf, s->send_buf_size); if (!s->send_buf) return SANE_STATUS_NO_MEM; } return SANE_STATUS_GOOD; } static SANE_Status cs3_issue_cmd(cs3_t * s) { SANE_Status status = SANE_STATUS_INVAL; size_t n_data, n_status; static SANE_Byte status_buf[8]; int status_only = 0; DBG(20, "cs3_issue_cmd(): opcode = 0x%02x, n_send = %lu, n_recv = %lu.\n", s->send_buf[0], (unsigned long) s->n_send, (unsigned long) s->n_recv); s->status = CS3_STATUS_READY; if (!s->n_cmd) switch (s->send_buf[0]) { case 0x00: case 0x12: case 0x15: case 0x16: case 0x17: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0xc0: case 0xc1: s->n_cmd = 6; break; case 0x24: case 0x25: case 0x28: case 0x2a: case 0xe0: case 0xe1: s->n_cmd = 10; break; default: DBG(1, "BUG: cs3_issue_cmd(): Unknown command opcode 0x%02x.\n", s->send_buf[0]); break; } if (s->n_send < s->n_cmd) { DBG(1, "BUG: cs3_issue_cmd(): Negative number of data out bytes requested.\n"); return SANE_STATUS_INVAL; } n_data = s->n_send - s->n_cmd; if (s->n_recv > 0) { if (n_data > 0) { DBG(1, "BUG: cs3_issue_cmd(): Both data in and data out requested.\n"); return SANE_STATUS_INVAL; } else { n_data = s->n_recv; } } s->recv_buf = (SANE_Byte *) cs3_xrealloc(s->recv_buf, s->n_recv); if (!s->recv_buf) return SANE_STATUS_NO_MEM; switch (s->interface) { case CS3_INTERFACE_UNKNOWN: DBG(1, "BUG: cs3_issue_cmd(): Unknown or uninitialized interface number.\n"); break; case CS3_INTERFACE_SCSI: sanei_scsi_cmd2(s->fd, s->send_buf, s->n_cmd, s->send_buf + s->n_cmd, s->n_send - s->n_cmd, s->recv_buf, &s->n_recv); status = SANE_STATUS_GOOD; break; case CS3_INTERFACE_USB: status = sanei_usb_write_bulk(s->fd, s->send_buf, &s->n_cmd); if (status != SANE_STATUS_GOOD) { DBG(1, "Error: cs3_issue_cmd(): Could not write command.\n"); return SANE_STATUS_IO_ERROR; } switch (cs3_phase_check(s)) { case CS3_PHASE_OUT: if (s->n_send - s->n_cmd < n_data || !n_data) { DBG(4, "Error: cs3_issue_cmd(): Unexpected data out phase.\n"); return SANE_STATUS_IO_ERROR; } status = sanei_usb_write_bulk(s->fd, s->send_buf + s->n_cmd, &n_data); break; case CS3_PHASE_IN: if (s->n_recv < n_data || !n_data) { DBG(4, "Error: cs3_issue_cmd(): Unexpected data in phase.\n"); return SANE_STATUS_IO_ERROR; } status = sanei_usb_read_bulk(s->fd, s->recv_buf, &n_data); s->n_recv = n_data; break; case CS3_PHASE_NONE: DBG(4, "%s: No command received!\n", __func__); return SANE_STATUS_IO_ERROR; default: if (n_data) { DBG(4, "%s: Unexpected non-data phase, but n_data != 0 (%lu).\n", __func__, (u_long) n_data); status_only = 1; } break; } n_status = 8; status = sanei_usb_read_bulk(s->fd, status_buf, &n_status); if (n_status != 8) { DBG(4, "Error: cs3_issue_cmd(): Failed to read 8 status bytes from USB.\n"); return SANE_STATUS_IO_ERROR; } s->sense_key = status_buf[1] & 0x0f; s->sense_asc = status_buf[2] & 0xff; s->sense_ascq = status_buf[3] & 0xff; s->sense_info = status_buf[4] & 0xff; status = cs3_parse_sense_data(s); break; } if (status_only) return SANE_STATUS_IO_ERROR; else return status; } static cs3_phase_t cs3_phase_check(cs3_t * s) { static SANE_Byte phase_send_buf[1] = { 0xd0 }, phase_recv_buf[1]; SANE_Status status = 0; size_t n = 1; status = sanei_usb_write_bulk(s->fd, phase_send_buf, &n); status |= sanei_usb_read_bulk(s->fd, phase_recv_buf, &n); DBG(40, "%s: returned phase = 0x%02x.\n", __func__, phase_recv_buf[0]); if (status != SANE_STATUS_GOOD) return -1; else return phase_recv_buf[0]; } static SANE_Status cs3_scanner_ready(cs3_t * s, int flags) { SANE_Status status = SANE_STATUS_GOOD; int i = -1; unsigned long count = 0; int retry = 3; do { if (i >= 0) /* dirty !!! */ usleep(1000000); /* test unit ready */ cs3_init_buffer(s); for (i = 0; i < 6; i++) cs3_pack_byte(s, 0x00); status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) if (--retry < 0) return status; if (++count > 120) { /* 120s timeout */ DBG(4, "Error: %s: Timeout expired.\n", __func__); status = SANE_STATUS_IO_ERROR; break; } } while (s->status & ~flags); /* until all relevant bits are 0 */ return status; } static SANE_Status cs3_page_inquiry(cs3_t * s, int page) { SANE_Status status; size_t n; if (page >= 0) { cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); cs3_init_buffer(s); cs3_parse_cmd(s, "12 01"); cs3_pack_byte(s, page); cs3_parse_cmd(s, "00 04 00"); s->n_recv = 4; status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) { DBG(4, "Error: cs3_page_inquiry(): Inquiry of page size failed: %s.\n", sane_strstatus(status)); return status; } n = s->recv_buf[3] + 4; } else n = 36; cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); cs3_init_buffer(s); if (page >= 0) { cs3_parse_cmd(s, "12 01"); cs3_pack_byte(s, page); cs3_parse_cmd(s, "00"); } else cs3_parse_cmd(s, "12 00 00 00"); cs3_pack_byte(s, n); cs3_parse_cmd(s, "00"); s->n_recv = n; status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) { DBG(4, "Error: %s: inquiry of page failed: %s.\n", __func__, sane_strstatus(status)); return status; } return SANE_STATUS_GOOD; } static SANE_Status cs3_full_inquiry(cs3_t * s) { SANE_Status status; int pitch, pitch_max; cs3_pixel_t pixel; DBG(4, "%s\n", __func__); status = cs3_page_inquiry(s, 0xc1); if (status != SANE_STATUS_GOOD) return status; s->maxbits = s->recv_buf[82]; if (s->type == CS3_TYPE_LS30) /* must be overridden, LS-30 claims to have 12 bits */ s->maxbits = 10; s->n_lut = 1; s->n_lut <<= s->maxbits; s->lut_r = (cs3_pixel_t *) cs3_xrealloc(s->lut_r, s->n_lut * sizeof(cs3_pixel_t)); s->lut_g = (cs3_pixel_t *) cs3_xrealloc(s->lut_g, s->n_lut * sizeof(cs3_pixel_t)); s->lut_b = (cs3_pixel_t *) cs3_xrealloc(s->lut_b, s->n_lut * sizeof(cs3_pixel_t)); s->lut_neutral = (cs3_pixel_t *) cs3_xrealloc(s->lut_neutral, s->n_lut * sizeof(cs3_pixel_t)); if (!s->lut_r || !s->lut_g || !s->lut_b || !s->lut_neutral) { cs3_xfree(s->lut_r); cs3_xfree(s->lut_g); cs3_xfree(s->lut_b); cs3_xfree(s->lut_neutral); return SANE_STATUS_NO_MEM; } for (pixel = 0; pixel < s->n_lut; pixel++) { s->lut_r[pixel] = s->lut_g[pixel] = s->lut_b[pixel] = s->lut_neutral[pixel] = pixel; } s->resx_optical = 256 * s->recv_buf[18] + s->recv_buf[19]; s->resx_max = 256 * s->recv_buf[20] + s->recv_buf[21]; s->resx_min = 256 * s->recv_buf[22] + s->recv_buf[23]; s->boundaryx = 65536 * (256 * s->recv_buf[36] + s->recv_buf[37]) + 256 * s->recv_buf[38] + s->recv_buf[39]; s->resy_optical = 256 * s->recv_buf[40] + s->recv_buf[41]; s->resy_max = 256 * s->recv_buf[42] + s->recv_buf[43]; s->resy_min = 256 * s->recv_buf[44] + s->recv_buf[45]; s->boundaryy = 65536 * (256 * s->recv_buf[58] + s->recv_buf[59]) + 256 * s->recv_buf[60] + s->recv_buf[61]; s->focus_min = 256 * s->recv_buf[76] + s->recv_buf[77]; s->focus_max = 256 * s->recv_buf[78] + s->recv_buf[79]; s->n_frames = s->recv_buf[75]; s->frame_offset = s->resy_max * 1.5 + 1; /* works for LS-30, maybe not for others */ /* generate resolution list for x */ s->resx_n_list = pitch_max = floor(s->resx_max / (double) s->resx_min); s->resx_list = (unsigned int *) cs3_xrealloc(s->resx_list, pitch_max * sizeof(unsigned int)); for (pitch = 1; pitch <= pitch_max; pitch++) s->resx_list[pitch - 1] = s->resx_max / pitch; /* generate resolution list for y */ s->resy_n_list = pitch_max = floor(s->resy_max / (double) s->resy_min); s->resy_list = (unsigned int *) cs3_xrealloc(s->resy_list, pitch_max * sizeof(unsigned int)); for (pitch = 1; pitch <= pitch_max; pitch++) s->resy_list[pitch - 1] = s->resy_max / pitch; s->unit_dpi = s->resx_max; s->unit_mm = 25.4 / s->unit_dpi; DBG(4, " maximum depth: %d\n", s->maxbits); DBG(4, " focus: %d/%d\n", s->focus_min, s->focus_max); DBG(4, " resolution (x): %d (%d-%d)\n", s->resx_optical, s->resx_min, s->resx_max); DBG(4, " resolution (y): %d (%d-%d)\n", s->resy_optical, s->resy_min, s->resy_max); DBG(4, " frames: %d\n", s->n_frames); DBG(4, " frame offset: %ld\n", s->frame_offset); return SANE_STATUS_GOOD; } static SANE_Status cs3_execute(cs3_t * s) { DBG(16, "%s\n", __func__); cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); cs3_init_buffer(s); cs3_parse_cmd(s, "c1 00 00 00 00 00"); return cs3_issue_cmd(s); } static SANE_Status cs3_issue_and_execute(cs3_t * s) { SANE_Status status; DBG(10, "%s, opcode = %02x\n", __func__, s->send_buf[0]); status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) return status; return cs3_execute(s); } static SANE_Status cs3_mode_select(cs3_t * s) { DBG(4, "%s\n", __func__); cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); cs3_init_buffer(s); cs3_parse_cmd(s, "15 10 00 00 14 00 00 00 00 08 00 00 00 00 00 00 00 01 03 06 00 00"); cs3_pack_word(s, s->unit_dpi); cs3_parse_cmd(s, "00 00"); return cs3_issue_cmd(s); } static SANE_Status cs3_load(cs3_t * s) { SANE_Status status; DBG(6, "%s\n", __func__); cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); cs3_init_buffer(s); cs3_parse_cmd(s, "e0 00 d1 00 00 00 00 00 0d 00"); s->n_send += 13; status = cs3_grow_send_buffer(s); if (status != SANE_STATUS_GOOD) return status; return cs3_issue_and_execute(s); } static SANE_Status cs3_eject(cs3_t * s) { SANE_Status status; cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); cs3_init_buffer(s); cs3_parse_cmd(s, "e0 00 d0 00 00 00 00 00 0d 00"); s->n_send += 13; status = cs3_grow_send_buffer(s); if (status != SANE_STATUS_GOOD) return status; return cs3_issue_and_execute(s); } static SANE_Status cs3_reset(cs3_t * s) { SANE_Status status; cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); cs3_init_buffer(s); cs3_parse_cmd(s, "e0 00 80 00 00 00 00 00 0d 00"); s->n_send += 13; status = cs3_grow_send_buffer(s); if (status != SANE_STATUS_GOOD) return status; return cs3_issue_and_execute(s); } static SANE_Status cs3_reserve_unit(cs3_t * s) { DBG(10, "%s\n", __func__); cs3_init_buffer(s); cs3_parse_cmd(s, "16 00 00 00 00 00"); return cs3_issue_cmd(s); } static SANE_Status cs3_release_unit(cs3_t * s) { DBG(10, "%s\n", __func__); cs3_init_buffer(s); cs3_parse_cmd(s, "17 00 00 00 00 00"); return cs3_issue_cmd(s); } static SANE_Status cs3_set_focus(cs3_t * s) { DBG(6, "%s: setting focus to %d\n", __func__, s->focus); cs3_scanner_ready(s, CS3_STATUS_READY); cs3_init_buffer(s); cs3_parse_cmd(s, "e0 00 c1 00 00 00 00 00 09 00 00"); cs3_pack_long(s, s->focus); cs3_parse_cmd(s, "00 00 00 00"); return cs3_issue_and_execute(s); } static SANE_Status cs3_read_focus(cs3_t * s) { SANE_Status status; cs3_scanner_ready(s, CS3_STATUS_READY); cs3_init_buffer(s); cs3_parse_cmd(s, "e1 00 c1 00 00 00 00 00 0d 00"); s->n_recv = 13; status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) return status; s->focus = 65536 * (256 * s->recv_buf[1] + s->recv_buf[2]) + 256 * s->recv_buf[3] + s->recv_buf[4]; DBG(4, "%s: focus at %d\n", __func__, s->focus); return status; } static SANE_Status cs3_autofocus(cs3_t * s) { SANE_Status status; DBG(6, "%s: focusing at %ld,%ld\n", __func__, s->real_focusx, s->real_focusy); cs3_convert_options(s); status = cs3_read_focus(s); if (status != SANE_STATUS_GOOD) return status; /* set parameter, autofocus */ cs3_scanner_ready(s, CS3_STATUS_READY); cs3_init_buffer(s); cs3_parse_cmd(s, "e0 00 a0 00 00 00 00 00 09 00 00"); cs3_pack_long(s, s->real_focusx); cs3_pack_long(s, s->real_focusy); /*cs3_parse_cmd(s, "00 00 00 00"); */ status = cs3_issue_and_execute(s); if (status != SANE_STATUS_GOOD) return status; return cs3_read_focus(s); } static SANE_Status cs3_autoexposure(cs3_t * s, int wb) { SANE_Status status; DBG(6, "%s, wb = %d\n", __func__, wb); cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); status = cs3_scan(s, wb ? CS3_SCAN_AE_WB : CS3_SCAN_AE); if (status != SANE_STATUS_GOOD) return status; status = cs3_get_exposure(s); if (status != SANE_STATUS_GOOD) return status; s->exposure = 1.; s->exposure_r = s->real_exposure[1] / 100.; s->exposure_g = s->real_exposure[2] / 100.; s->exposure_b = s->real_exposure[3] / 100.; return status; } static SANE_Status cs3_get_exposure(cs3_t * s) { SANE_Status status; int i_color, colors = s->n_colors; DBG(6, "%s\n", __func__); if ((s->type == CS3_TYPE_LS50) || (s->type == CS3_TYPE_LS5000)) colors = 3; cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); /* GET WINDOW */ for (i_color = 0; i_color < colors; i_color++) { /* XXXXXXXXXXXXX CCCCCCCCCCCCC */ cs3_init_buffer(s); cs3_parse_cmd(s, "25 01 00 00 00"); cs3_pack_byte(s, cs3_colors[i_color]); cs3_parse_cmd(s, "00 00 3a 00"); s->n_recv = 58; status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) return status; s->real_exposure[cs3_colors[i_color]] = 65536 * (256 * s->recv_buf[54] + s->recv_buf[55]) + 256 * s->recv_buf[56] + s->recv_buf[57]; DBG(6, "%s, exposure for color %i: %li * 10ns\n", __func__, cs3_colors[i_color], s->real_exposure[cs3_colors[i_color]]); DBG(6, "%02x %02x %02x %02x\n", s->recv_buf[48], s->recv_buf[49], s->recv_buf[50], s->recv_buf[51]); } return SANE_STATUS_GOOD; } static SANE_Status cs3_convert_options(cs3_t * s) { int i_color; unsigned long xmin, xmax, ymin, ymax; DBG(4, "%s\n", __func__); s->real_depth = (s->preview ? 8 : s->depth); s->bytes_per_pixel = (s->real_depth > 8 ? 2 : 1); s->shift_bits = 8 * s->bytes_per_pixel - s->real_depth; DBG(12, " depth = %d, bpp = %d, shift = %d\n", s->real_depth, s->bytes_per_pixel, s->shift_bits); if (s->preview) { s->real_resx = s->res_preview; s->real_resy = s->res_preview; } else if (s->res_independent) { s->real_resx = s->resx; s->real_resy = s->resy; } else { s->real_resx = s->res; s->real_resy = s->res; } s->real_pitchx = s->resx_max / s->real_resx; s->real_pitchy = s->resy_max / s->real_resy; s->real_resx = s->resx_max / s->real_pitchx; s->real_resy = s->resy_max / s->real_pitchy; DBG(12, " resx = %d, resy = %d, pitchx = %d, pitchy = %d\n", s->real_resx, s->real_resy, s->real_pitchx, s->real_pitchy); /* The prefix "real_" refers to data in device units (1/maxdpi), * "logical_" refers to resolution-dependent data. */ if (s->xmin < s->xmax) { xmin = s->xmin; xmax = s->xmax; } else { xmin = s->xmax; xmax = s->xmin; } if (s->ymin < s->ymax) { ymin = s->ymin; ymax = s->ymax; } else { ymin = s->ymax; ymax = s->ymin; } DBG(12, " xmin = %ld, xmax = %ld\n", xmin, xmax); DBG(12, " ymin = %ld, ymax = %ld\n", ymin, ymax); s->real_xoffset = xmin; s->real_yoffset = ymin + (s->i_frame - 1) * s->frame_offset + s->subframe / s->unit_mm; DBG(12, " xoffset = %ld, yoffset = %ld\n", s->real_xoffset, s->real_yoffset); s->logical_width = (xmax - xmin + 1) / s->real_pitchx; /* XXX use mm units */ s->logical_height = (ymax - ymin + 1) / s->real_pitchy; s->real_width = s->logical_width * s->real_pitchx; s->real_height = s->logical_height * s->real_pitchy; DBG(12, " lw = %ld, lh = %ld, rw = %ld, rh = %ld\n", s->logical_width, s->logical_height, s->real_width, s->real_height); s->odd_padding = 0; if ((s->bytes_per_pixel == 1) && (s->logical_width & 0x01) && (s->type != CS3_TYPE_LS30) && (s->type != CS3_TYPE_LS2000)) s->odd_padding = 1; if (s->focus_on_centre) { s->real_focusx = s->real_xoffset + s->real_width / 2; s->real_focusy = s->real_yoffset + s->real_height / 2; } else { s->real_focusx = s->focusx; s->real_focusy = s->focusy + (s->i_frame - 1) * s->frame_offset + s->subframe / s->unit_mm; } DBG(12, " focusx = %ld, focusy = %ld\n", s->real_focusx, s->real_focusy); s->real_exposure[1] = s->exposure * s->exposure_r * 100.; s->real_exposure[2] = s->exposure * s->exposure_g * 100.; s->real_exposure[3] = s->exposure * s->exposure_b * 100.; /* XXX IR? */ for (i_color = 0; i_color < 3; i_color++) if (s->real_exposure[cs3_colors[i_color]] < 1) s->real_exposure[cs3_colors[i_color]] = 1; s->n_colors = 3; /* XXXXXXXXXXXXXX CCCCCCCCCCCCCC */ if (s->infrared) s->n_colors = 4; s->xfer_bytes_total = s->bytes_per_pixel * s->n_colors * s->logical_width * s->logical_height; if (s->preview) s->infrared = SANE_FALSE; return SANE_STATUS_GOOD; } static SANE_Status cs3_set_boundary(cs3_t * s) { SANE_Status status; int i_boundary; /* Ariel - Check this function */ cs3_scanner_ready(s, CS3_STATUS_READY); cs3_init_buffer(s); cs3_parse_cmd(s, "2a 00 88 00 00 03"); cs3_pack_byte(s, ((4 + s->n_frames * 16) >> 16) & 0xff); cs3_pack_byte(s, ((4 + s->n_frames * 16) >> 8) & 0xff); cs3_pack_byte(s, (4 + s->n_frames * 16) & 0xff); cs3_parse_cmd(s, "00"); cs3_pack_byte(s, ((4 + s->n_frames * 16) >> 8) & 0xff); cs3_pack_byte(s, (4 + s->n_frames * 16) & 0xff); cs3_pack_byte(s, s->n_frames); cs3_pack_byte(s, s->n_frames); for (i_boundary = 0; i_boundary < s->n_frames; i_boundary++) { unsigned long lvalue = s->frame_offset * i_boundary + s->subframe / s->unit_mm; cs3_pack_long(s, lvalue); cs3_pack_long(s, 0); lvalue = s->frame_offset * i_boundary + s->subframe / s->unit_mm + s->frame_offset - 1; cs3_pack_long(s, lvalue); cs3_pack_long(s, s->boundaryx - 1); } status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) return status; return SANE_STATUS_GOOD; } static SANE_Status cs3_send_lut(cs3_t * s) { int color; SANE_Status status; cs3_pixel_t *lut, pixel; DBG(6, "%s\n", __func__); for (color = 0; color < s->n_colors; color++) { /*cs3_scanner_ready(s, CS3_STATUS_READY); */ switch (color) { case 0: lut = s->lut_r; break; case 1: lut = s->lut_g; break; case 2: lut = s->lut_b; break; case 3: lut = s->lut_neutral; break; default: DBG(1, "BUG: %s: Unknown color number for LUT download.\n", __func__); return SANE_STATUS_INVAL; break; } cs3_init_buffer(s); cs3_parse_cmd(s, "2a 00 03 00"); cs3_pack_byte(s, cs3_colors[color]); cs3_pack_byte(s, 2 - 1); /* XXX number of bytes per data point - 1 */ cs3_pack_byte(s, ((2 * s->n_lut) >> 16) & 0xff); /* XXX 2 bytes per point */ cs3_pack_byte(s, ((2 * s->n_lut) >> 8) & 0xff); /* XXX 2 bytes per point */ cs3_pack_byte(s, (2 * s->n_lut) & 0xff); /* XXX 2 bytes per point */ cs3_pack_byte(s, 0x00); for (pixel = 0; pixel < s->n_lut; pixel++) { /* XXX 2 bytes per point */ cs3_pack_word(s, lut[pixel]); } status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) return status; } return status; } static SANE_Status cs3_set_window(cs3_t * s, cs3_scan_t type) { int color; SANE_Status status = SANE_STATUS_INVAL; /* SET WINDOW */ for (color = 0; color < s->n_colors; color++) { DBG(8, "%s: color %d\n", __func__, cs3_colors[color]); cs3_scanner_ready(s, CS3_STATUS_READY); cs3_init_buffer(s); if ((s->type == CS3_TYPE_LS40) || (s->type == CS3_TYPE_LS4000) || (s->type == CS3_TYPE_LS50) || (s->type == CS3_TYPE_LS5000)) cs3_parse_cmd(s, "24 00 00 00 00 00 00 00 3a 80"); else cs3_parse_cmd(s, "24 00 00 00 00 00 00 00 3a 00"); cs3_parse_cmd(s, "00 00 00 00 00 00 00 32"); cs3_pack_byte(s, cs3_colors[color]); cs3_pack_byte(s, 0x00); cs3_pack_word(s, s->real_resx); cs3_pack_word(s, s->real_resy); cs3_pack_long(s, s->real_xoffset); cs3_pack_long(s, s->real_yoffset); cs3_pack_long(s, s->real_width); cs3_pack_long(s, s->real_height); cs3_pack_byte(s, 0x00); /* brightness, etc. */ cs3_pack_byte(s, 0x00); cs3_pack_byte(s, 0x00); cs3_pack_byte(s, 0x05); /* image composition CCCCCCC */ cs3_pack_byte(s, s->real_depth); /* pixel composition */ cs3_parse_cmd(s, "00 00 00 00 00 00 00 00 00 00 00 00 00"); cs3_pack_byte(s, ((s->samples_per_scan - 1) << 4) | 0x00); /* multiread, ordering */ cs3_pack_byte(s, 0x80 | (s->negative ? 0 : 1)); /* averaging, pos/neg */ switch (type) { /* scanning kind */ case CS3_SCAN_NORMAL: cs3_pack_byte(s, 0x01); break; case CS3_SCAN_AE: cs3_pack_byte(s, 0x20); break; case CS3_SCAN_AE_WB: cs3_pack_byte(s, 0x40); break; default: DBG(1, "BUG: cs3_scan(): Unknown scanning type.\n"); return SANE_STATUS_INVAL; } if (s->samples_per_scan == 1) cs3_pack_byte(s, 0x02); /* scanning mode single */ else cs3_pack_byte(s, 0x10); /* scanning mode multi */ cs3_pack_byte(s, 0x02); /* color interleaving */ cs3_pack_byte(s, 0xff); /* (ae) */ if (color == 3) /* infrared */ cs3_parse_cmd(s, "00 00 00 00"); /* automatic */ else { DBG(4, "%s: exposure = %ld * 10ns\n", __func__, s->real_exposure[cs3_colors[color]]); cs3_pack_long(s, s->real_exposure[cs3_colors[color]]); } status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) return status; } return status; } static SANE_Status cs3_scan(cs3_t * s, cs3_scan_t type) { SANE_Status status; s->block_padding = 0; DBG(6, "%s, type = %d, colors = %d\n", __func__, type, s->n_colors); switch (type) { case CS3_SCAN_NORMAL: DBG(16, "%s: normal scan\n", __func__); break; case CS3_SCAN_AE: DBG(16, "%s: ae scan\n", __func__); break; case CS3_SCAN_AE_WB: DBG(16, "%s: ae wb scan\n", __func__); break; } /* wait for device to be ready with document, and set device unit */ status = cs3_scanner_ready(s, CS3_STATUS_NO_DOCS); if (status != SANE_STATUS_GOOD) return status; if (s->status & CS3_STATUS_NO_DOCS) return SANE_STATUS_NO_DOCS; status = cs3_convert_options(s); if (status != SANE_STATUS_GOOD) return status; status = cs3_set_boundary(s); if (status != SANE_STATUS_GOOD) return status; cs3_set_focus(s); cs3_scanner_ready(s, CS3_STATUS_READY); if (type == CS3_SCAN_NORMAL) cs3_send_lut(s); status = cs3_set_window(s, type); if (status != SANE_STATUS_GOOD) return status; status = cs3_get_exposure(s); if (status != SANE_STATUS_GOOD) return status; /* cs3_scanner_ready(s, CS3_STATUS_READY); */ cs3_init_buffer(s); switch (s->n_colors) { case 3: cs3_parse_cmd(s, "1b 00 00 00 03 00 01 02 03"); break; case 4: cs3_parse_cmd(s, "1b 00 00 00 04 00 01 02 03 09"); break; default: DBG(0, "BUG: %s: Unknown number of input colors.\n", __func__); break; } status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) { DBG(6, "scan setup failed\n"); return status; } if (s->status == CS3_STATUS_REISSUE) { status = cs3_issue_cmd(s); if (status != SANE_STATUS_GOOD) return status; } return SANE_STATUS_GOOD; } static void * cs3_xmalloc(size_t size) { register void *value = malloc(size); if (value == NULL) { DBG(0, "error: %s: failed to malloc() %lu bytes.\n", __func__, (unsigned long) size); } return value; } static void * cs3_xrealloc(void *p, size_t size) { register void *value; if (!size) return p; value = realloc(p, size); if (value == NULL) { DBG(0, "error: %s: failed to realloc() %lu bytes.\n", __func__, (unsigned long) size); } return value; } static void cs3_xfree(void *p) { if (p) free(p); } sane-backends-1.0.27/backend/rts8891.h0000664000175000017500000001103612775277260014144 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007-2012 stef.dev@free.fr This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef RTS8891_H #define RTS8891_H #define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE #define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE #define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) #define RTS8891_CONFIG_FILE "rts8891.conf" #ifndef SANE_I18N #define SANE_I18N(text) text #endif /* */ #define COLOR_MODE SANE_VALUE_SCAN_MODE_COLOR #define GRAY_MODE SANE_VALUE_SCAN_MODE_GRAY #define LINEART_MODE SANE_VALUE_SCAN_MODE_LINEART /* preferred number of bytes to keep in buffer */ #define PREFERED_BUFFER_SIZE 2097152 /* all scanner memory */ /** List of SANE options */ enum Rts8891_Option { OPT_NUM_OPTS = 0, OPT_STANDARD_GROUP, OPT_MODE, OPT_PREVIEW, OPT_RESOLUTION, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ /* advanced image enhancement options */ OPT_ENHANCEMENT_GROUP, OPT_THRESHOLD, OPT_CUSTOM_GAMMA, /* toggle to enable custom gamma tables */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, /* advanced options */ OPT_ADVANCED_GROUP, OPT_LAMP_ON, OPT_LAMP_OFF, /* button group */ OPT_SENSOR_GROUP, OPT_BUTTON_1, OPT_BUTTON_2, OPT_BUTTON_3, OPT_BUTTON_4, OPT_BUTTON_5, OPT_BUTTON_6, OPT_BUTTON_7, OPT_BUTTON_8, OPT_BUTTON_9, OPT_BUTTON_10, OPT_BUTTON_11, /* must come last: */ NUM_OPTIONS }; /** * enumeration of configuration options */ enum Rts8891_Configure_Option { CFG_MODEL_NUMBER = 0, /* first option number must be zero */ CFG_SENSOR_NUMBER, CFG_ALLOW_SHARING, NUM_CFG_OPTIONS /* MUST be last */ }; /** Scanner object. This struct holds informations usefull for * the functions defined in SANE's standard. Informations closer * to the hardware are in the Rts8891_Device structure. There is * as many session structure than frontends using the scanner. */ typedef struct Rts8891_Session { /**< Next handle in linked list */ struct Rts8891_Session *next; /**< Low-level device object */ struct Rts8891_Device *dev; /* SANE data */ /**< We are currently scanning */ SANE_Bool scanning; /**< Data read is in non blocking mode */ SANE_Bool non_blocking; /**< Gray scans are emulated */ SANE_Bool emulated_gray; SANE_Option_Descriptor opt[NUM_OPTIONS]; /**< Option descriptors */ Option_Value val[NUM_OPTIONS]; /**< Option values */ SANE_Parameters params; /**< SANE Parameters */ /**< bytes to send to frontend for the scan */ SANE_Int to_send; /**< bytes currently sent to frontend during the scan */ SANE_Int sent; } Rts8891_Session; #endif /* not RTS8891_H */ sane-backends-1.0.27/backend/umax_pp.h0000664000175000017500000001132112775312261014437 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2012 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Umax PP flatbed scanners. */ #ifndef umax_pp_h #define umax_pp_h #include #include #include <../include/sane/sanei_debug.h> enum Umax_PP_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_RESOLUTION, OPT_PREVIEW, OPT_GRAY_PREVIEW, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_LAMP_CONTROL, OPT_UTA_CONTROL, OPT_CUSTOM_GAMMA, /* use custom gamma tables? */ /* The gamma vectors MUST appear in the order gray, red, green, blue. */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_MANUAL_GAIN, OPT_GRAY_GAIN, OPT_RED_GAIN, OPT_GREEN_GAIN, OPT_BLUE_GAIN, OPT_MANUAL_OFFSET, OPT_GRAY_OFFSET, OPT_RED_OFFSET, OPT_GREEN_OFFSET, OPT_BLUE_OFFSET, /* must come last: */ NUM_OPTIONS }; typedef struct Umax_PP_Descriptor { SANE_Device sane; SANE_String port; SANE_String ppdevice; SANE_Int max_res; SANE_Int ccd_res; SANE_Int max_h_size; SANE_Int max_v_size; long int buf_size; u_char revision; /* default values */ SANE_Int gray_gain; SANE_Int red_gain; SANE_Int blue_gain; SANE_Int green_gain; SANE_Int gray_offset; SANE_Int red_offset; SANE_Int blue_offset; SANE_Int green_offset; } Umax_PP_Descriptor; typedef struct Umax_PP_Device { struct Umax_PP_Device *next; Umax_PP_Descriptor *desc; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Int gamma_table[4][256]; int state; int mode; int TopX; int TopY; int BottomX; int BottomY; int dpi; int gain; int color; int bpp; /* bytes per pixel */ int tw; /* target width in pixels */ int th; /* target height in pixels */ SANE_Byte *calibration; SANE_Byte *buf; long int bufsize; /* size of read buffer */ long int buflen; /* size of data length in buffer */ long int bufread; /* number of bytes read in the buffer */ long int read; /* bytes read from previous start scan */ SANE_Parameters params; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; SANE_Int gray_gain; SANE_Int red_gain; SANE_Int blue_gain; SANE_Int green_gain; SANE_Int gray_offset; SANE_Int red_offset; SANE_Int blue_offset; SANE_Int green_offset; } Umax_PP_Device; /** * enumeration of configuration options */ enum Umax_PP_Configure_Option { CFG_BUFFER = 0, CFG_RED_GAIN, CFG_GREEN_GAIN, CFG_BLUE_GAIN, CFG_RED_OFFSET, CFG_GREEN_OFFSET, CFG_BLUE_OFFSET, CFG_VENDOR, CFG_NAME, CFG_MODEL, CFG_ASTRA, NUM_CFG_OPTIONS }; #define DEBUG() DBG(4, "%s(v%d.%d.%d-%s): line %d: debug exception\n", \ __func__, SANE_CURRENT_MAJOR, V_MINOR, \ UMAX_PP_BUILD, UMAX_PP_STATE, __LINE__) #endif /* umax_pp_h */ sane-backends-1.0.27/backend/canon_pp-dev.c0000664000175000017500000011347012112021330015315 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2002 Matthew C. Duggan and Simon Krix This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. ----- This file is part of the canon_pp backend, supporting Canon CanoScan Parallel scanners and also distributed as part of the stand-alone driver. canon_pp-dev.c: $Revision$ Misc constants for Canon CanoScan Parallel scanners and high-level scan functions. Simon Krix */ #ifdef _AIX #include #endif #ifndef NOSANE #include "../include/sane/config.h" #endif #include #include #include #include #include #include #include #include "canon_pp-io.h" #include "canon_pp-dev.h" #ifdef NOSANE /* No SANE, Things that only apply to stand-alone */ #include #include static void DBG(int level, const char *format, ...) { va_list args; va_start(args, format); if (level < 50) vfprintf(stderr, format, args); va_end(args); } #else /* Definitions which only apply to SANE compiles */ #ifndef VERSION #define VERSION "$Revision$" #endif #define DEBUG_DECLARE_ONLY #include "canon_pp.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" #endif struct scanner_hardware_desc { char *name; unsigned int natural_xresolution; unsigned int natural_yresolution; unsigned int scanbedlength; unsigned int scanheadwidth; /* 0 means provided by scanner */ unsigned int type; }; static const struct scanner_hardware_desc /* The known scanner types */ hw_fb320p = { "FB320P", 2, 2, 3508, 2552, 0 }, hw_fb330p = { "FB330P", 2, 2, 3508, 0, 1 }, hw_fb620p = { "FB620P", 3, 3, 7016, 5104, 0 }, hw_fb630p = { "FB630P", 3, 3, 7016, 0, 1 }, hw_n640p = { "N640P", 3, 3, 7016, 0, 1 }, hw_n340p = { "N340P", 2, 2, 3508, 0, 1 }, /* A few generic scanner descriptions for aliens */ hw_alien600 = { "Unknown 600dpi", 3, 3, 7016, 0, 1 }, hw_alien300 = { "Unknown 300dpi", 2, 2, 3508, 0, 1 }, hw_alien = { "Unknown (600dpi?)", 3, 3, 7016, 0, 1 }; /* ID table linking ID strings with hardware descriptions */ struct scanner_id { char *id; const struct scanner_hardware_desc *hw; }; static const struct scanner_id scanner_id_table[] = { { "CANON IX-03055C", &hw_fb320p }, { "CANON IX-06025C", &hw_fb620p }, { "CANON IX-03075E", &hw_fb330p }, { "CANON IX-06075E", &hw_fb630p }, { "CANON IX-03095G", &hw_n340p }, { "CANON IX-06115G", &hw_n640p }, { NULL, NULL } }; /*const int scanline_count = 6;*/ static const char *header = "#CANONPP"; static const int fileversion = 3; /* Internal functions */ static unsigned long column_sum(image_segment *image, int x); static int adjust_output(image_segment *image, scan_parameters *scanp, scanner_parameters *scannerp); static int check8(unsigned char *p, int s); /* Converts from weird scanner format -> sequential data */ static void convdata(unsigned char *srcbuffer, unsigned char *dstbuffer, int width, int mode); /* Sets up the scan command. This could use a better name (and a rewrite). */ static int scanner_setup_params(unsigned char *buf, scanner_parameters *sp, scan_parameters *scanp); /* file reading and writing helpers */ static int safe_write(int fd, const char *p, unsigned long len); static int safe_read(int fd, char *p, unsigned long len); /* Command sending loop (waiting for ready status) */ static int send_command(struct parport *port, unsigned char *buf, int bufsize, int delay, int timeout); /* Commands ================================================ */ /* Command_1[] moved to canon_pp-io.c for neatness */ /* Read device ID command */ /* after this 0x26 (38) bytes are read */ static unsigned char cmd_readid[] = { 0xfe, 0x20, 0, 0, 0, 0, 0, 0, 0x26, 0 }; /* Reads 12 bytes of unknown information */ static unsigned char cmd_readinfo[] = { 0xf3, 0x20, 0, 0, 0, 0, 0, 0, 0x0c, 0 }; /* Scan init command: Always followed immediately by command cmd_scan */ static unsigned char cmd_initscan[] = { 0xde, 0x20, 0, 0, 0, 0, 0, 0, 0x2e, 0 }; /* Scan information block */ static unsigned char cmd_scan[45] = { 0x11, 0x2c, 0x11, 0x2c, 0x10, 0x4b, 0x10, 0x4b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x01, 0x01, 0x80, 0x01, 0x80, 0x80, 0x02, 0, 0, 0xc1, 0, 0x08, 0x01, 0x01, 0, 0, 0, 0, 0 }; /* Read 6 byte buffer status block */ static unsigned char cmd_buf_status[] = { 0xf3, 0x21, 0, 0, 0, 0, 0, 0, 0x06, 0 }; /* Request a block of image data */ static unsigned char cmd_packet_req[] = {0xd4, 0x20, 0, 0, 0, 0, 0, 0x09, 0x64, 0}; /* "*SCANEND" command - returns the scanner to transparent mode */ static unsigned char cmd_scanend[] = { 0x1b, 0x2a, 0x53, 0x43, 0x41, 0x4e, 0x45, 0x4e, 0x44, 0x0d }; /* Reads BLACK calibration image */ static unsigned char cmd_calblack[] ={0xf8, 0x20, 0, 0, 0, 0, 0, 0x4a, 0xc4, 0}; /* Clear the existing gamma table and create a new one */ static unsigned char cmd_cleargamma[] = {0xc5, 0x20, 0, 0, 0, 0, 0, 0, 0, 0}; /* Read back the gamma table values */ static unsigned char cmd_readgamma[] = {0xf6, 0x20, 0, 0, 0, 0, 0, 0, 0x20, 0}; /* Reads COLOUR (R,G or B) calibration image */ static unsigned char cmd_calcolour[]={0xf9, 0x20, 0, 0, 0, 0, 0, 0x4a, 0xc4, 0}; /* Abort scan */ static unsigned char cmd_abort[] = {0xef, 0x20, 0, 0, 0, 0, 0, 0, 0, 0}; /* Upload the gamma table (followed by 32 byte write) */ static unsigned char cmd_setgamma[] = {0xe6, 0x20, 0, 0, 0, 0, 0, 0, 0x20, 0}; #if 0 /* Something about RGB gamma/gain values? Not currently used by this code */ static unsigned char command_14[32] = { 0x2, 0x0, 0x3, 0x7f, 0x2, 0x0, 0x3, 0x7f, 0x2, 0x0, 0x3, 0x7f, 0, 0, 0, 0, 0x12, 0xd1, 0x14, 0x82, 0, 0, 0, 0, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0xff, 0, 0 }; #endif /* Misc functions =================================== */ /* * safe_write(): a small wrapper which ensures all the data is written in calls * to write(), since the POSIX call doesn't ensure it. */ static int safe_write(int fd, const char *p, unsigned long len) { int diff; unsigned long total = 0; do { diff = write(fd, p+total, len-total); if (diff < 0) { if (errno == EINTR) continue; return -1; } total += diff; } while (len > total); return 0; } /* same dealie for read, except in the case of read the return of 0 bytes with * no INTR error indicates EOF */ static int safe_read(int fd, char *p, unsigned long len) { int diff; unsigned long total = 0; do { diff = read(fd, p+total, len-total); if (diff <= 0) { if (errno == EINTR) continue; if (diff == 0) return -2; return -1; } total += diff; } while (len > total); return 0; } /* Scan-related functions =================================== */ int sanei_canon_pp_init_scan(scanner_parameters *sp, scan_parameters *scanp) { /* Command for: Initialise and begin the scan procedure */ unsigned char command_b[56]; /* Buffer for buffer info block */ unsigned char buffer_info_block[6]; /* The image size the scanner says we asked for (based on the scanner's replies) */ int true_scanline_size, true_scanline_count; /* The image size we expect to get (based on *scanp) */ int expected_scanline_size, expected_scanline_count; /* Set up the default scan command packet */ memcpy(command_b, cmd_initscan, 10); memcpy(command_b+10, cmd_scan, 45); /* Load the proper settings into it */ scanner_setup_params(command_b+10, sp, scanp); /* Add checksum byte */ command_b[55] = check8(command_b+10, 45); if (send_command(sp->port, command_b, 56, 50000, 1000000)) return -1; /* Ask the scanner about the buffer */ if (send_command(sp->port, cmd_buf_status, 10, 50000, 1000000)) return -1; /* Read buffer information block */ sanei_canon_pp_read(sp->port, 6, buffer_info_block); if (check8(buffer_info_block, 6)) DBG(1, "init_scan: ** Warning: Checksum error reading buffer " "info block.\n"); expected_scanline_count = scanp->height; switch(scanp->mode) { case 0: /* greyscale; 10 bits per pixel */ expected_scanline_size = scanp->width * 1.25; break; case 1: /* true-colour; 30 bits per pixel */ expected_scanline_size = scanp->width * 3.75; break; default: DBG(1, "init_scan: Illegal mode %i requested in " "init_scan().\n", scanp->mode); DBG(1, "This is a bug. Please report it.\n"); return -1; } /* The scanner's idea of the length of each scanline in bytes */ true_scanline_size = (buffer_info_block[0]<<8) | buffer_info_block[1]; /* The scanner's idea of the number of scanlines in total */ true_scanline_count = (buffer_info_block[2]<<8) | buffer_info_block[3]; if ((expected_scanline_size != true_scanline_size) || (expected_scanline_count != true_scanline_count)) { DBG(10, "init_scan: Warning: Scanner is producing an image " "of unexpected size:\n"); DBG(10, "expected: %i bytes wide, %i scanlines tall.\n", expected_scanline_size, expected_scanline_count); DBG(10, "true: %i bytes wide, %i scanlines tall.\n", true_scanline_size, true_scanline_count); if (scanp->mode == 0) scanp->width = true_scanline_size / 1.25; else scanp->width = true_scanline_size / 3.75; scanp->height = true_scanline_count; } return 0; } /* Wake the scanner, detect it, and fill sp with stuff */ int sanei_canon_pp_initialise(scanner_parameters *sp, int mode) { unsigned char scanner_info[12]; const struct scanner_id *cur_id; const struct scanner_hardware_desc *hw; /* Hopefully take the scanner out of transparent mode */ if (sanei_canon_pp_wake_scanner(sp->port, mode)) { DBG(10, "initialise: could not wake scanner\n"); return 1; } /* This block of code does something unknown but necessary */ DBG(50, "initialise: >> scanner_init\n"); if (sanei_canon_pp_scanner_init(sp->port)) { /* If we're using an unsupported ieee1284 mode here, this is * where it will fail, so fall back to nibble. */ sanei_canon_pp_set_ieee1284_mode(M1284_NIBBLE); if (sanei_canon_pp_scanner_init(sp->port)) { DBG(10, "initialise: Could not init scanner.\n"); return 1; } } DBG(50, "initialise: << scanner_init\n"); /* Read Device ID */ memset(sp->id_string, 0, sizeof sp->id_string); if (send_command(sp->port, cmd_readid, 10, 10000, 100000)) return -1; sanei_canon_pp_read(sp->port, 38, (unsigned char *)(sp->id_string)); /* Read partially unknown data */ if (send_command(sp->port, cmd_readinfo, 10, 10000, 100000)) return -1; sanei_canon_pp_read(sp->port, 12, scanner_info); if (check8(scanner_info, 12)) { DBG(10, "initialise: Checksum error reading Info Block.\n"); return 2; } sp->scanheadwidth = (scanner_info[2] << 8) | scanner_info[3]; /* Set up various known values */ cur_id = scanner_id_table; while (cur_id->id) { if (!strncmp(sp->id_string+8, cur_id->id, strlen(cur_id->id))) break; cur_id++; } if (cur_id->id) { hw = cur_id->hw; } else if (sp->scanheadwidth == 5104) { /* Guess 600dpi scanner */ hw = &hw_alien600; } else if (sp->scanheadwidth == 2552) { /* Guess 300dpi scanner */ hw = &hw_alien300; } else { /* Guinea Pigs :) */ hw = &hw_alien; } strcpy(sp->name, hw->name); sp->natural_xresolution = hw->natural_xresolution; sp->natural_yresolution = hw->natural_yresolution; sp->scanbedlength = hw->scanbedlength; if (hw->scanheadwidth) sp->scanheadwidth = hw->scanheadwidth; sp->type = hw->type; return 0; } /* Shut scanner down */ int sanei_canon_pp_close_scanner(scanner_parameters *sp) { /* Put scanner in transparent mode */ sanei_canon_pp_sleep_scanner(sp->port); /* Free memory (with purchase of memory of equal or greater value) */ if (sp->blackweight != NULL) { free(sp->blackweight); sp->blackweight = NULL; } if (sp->redweight != NULL) { free(sp->redweight); sp->redweight = NULL; } if (sp->greenweight != NULL) { free(sp->greenweight); sp->greenweight = NULL; } if (sp->blueweight != NULL) { free(sp->blueweight); sp->blueweight = NULL; } return 0; } /* Read the calibration information from file */ int sanei_canon_pp_load_weights(const char *filename, scanner_parameters *sp) { int fd; int cal_data_size = sp->scanheadwidth * sizeof(unsigned long); int cal_file_size; char buffer[10]; int temp, ret; /* Open file */ if ((fd = open(filename, O_RDONLY)) == -1) return -1; /* Read header and check it's right */ ret = safe_read(fd, buffer, strlen(header) + 1); if ((ret < 0) || strcmp(buffer, header) != 0) { DBG(1,"Calibration file header is wrong, recalibrate please\n"); close(fd); return -2; } /* Read and check file version (the calibrate file format changes from time to time) */ ret = safe_read(fd, (char *)&temp, sizeof(int)); if ((ret < 0) || (temp != fileversion)) { DBG(1,"Calibration file is wrong version, recalibrate please\n"); close(fd); return -3; } /* Allocate memory for calibration values */ if (((sp->blueweight = malloc(cal_data_size)) == NULL) || ((sp->redweight = malloc(cal_data_size)) == NULL) || ((sp->greenweight = malloc(cal_data_size)) == NULL) || ((sp->blackweight = malloc(cal_data_size)) == NULL)) return -4; /* Read width of calibration data */ ret = safe_read(fd, (char *)&cal_file_size, sizeof(cal_file_size)); if ((ret < 0) || (cal_file_size != sp->scanheadwidth)) { DBG(1, "Calibration doesn't match scanner, recalibrate?\n"); close(fd); return -5; } /* Read calibration data */ if (safe_read(fd, (char *)(sp->blackweight), cal_data_size) < 0) { DBG(1, "Error reading black calibration data, recalibrate?\n"); close(fd); return -6; } if (safe_read(fd, (char *)sp->redweight, cal_data_size) < 0) { DBG(1, "Error reading red calibration data, recalibrate?\n"); close(fd); return -7; } if (safe_read(fd, (char *)sp->greenweight, cal_data_size) < 0) { DBG(1, "Error reading green calibration data, recalibrate?\n"); close(fd); return -8; } if (safe_read(fd, (char *)sp->blueweight, cal_data_size) < 0) { DBG(1, "Error reading blue calibration data, recalibrate?\n"); close(fd); return -9; } /* Read white-balance/gamma data */ if (safe_read(fd, (char *)&(sp->gamma), 32) < 0) { close(fd); return -10; } close(fd); return 0; } /* Mode is 0 for greyscale source data or 1 for RGB */ static void convert_to_rgb(image_segment *dest, unsigned char *src, int width, int scanlines, int mode) { int curline; const int colour_size = width * 1.25; const int scanline_size = (mode == 0 ? colour_size : colour_size * 3); for (curline = 0; curline < scanlines; curline++) { if (mode == 0) /* Grey */ { convdata(src + (curline * scanline_size), dest->image_data + (curline * width * 2), width, 1); } else if (mode == 1) /* Truecolour */ { /* Red */ convdata(src + (curline * scanline_size), dest->image_data + (curline * width *3*2) + 4, width, 2); /* Green */ convdata(src + (curline * scanline_size) + colour_size, dest->image_data + (curline * width *3*2) + 2, width, 2); /* Blue */ convdata(src + (curline * scanline_size) + (2 * colour_size), dest->image_data + (curline * width *3*2), width, 2); } } /* End of scanline loop */ } int sanei_canon_pp_read_segment(image_segment **dest, scanner_parameters *sp, scan_parameters *scanp, int scanline_number, int do_adjust, int scanlines_left) { unsigned char *input_buffer = NULL; image_segment *output_image = NULL; unsigned char packet_header[4]; unsigned char packet_req_command[10]; int read_data_size; int scanline_size; if (scanp->mode == 1) /* RGB */ scanline_size = scanp->width * 3.75; else /* Greyscale */ scanline_size = scanp->width * 1.25; read_data_size = scanline_size * scanline_number; /* Allocate output_image struct */ if ((output_image = malloc(sizeof(*output_image))) == NULL) { DBG(1, "read_segment: Error: Not enough memory for scanner " "input buffer\n"); goto error_out; } /* Allocate memory for input buffer */ if ((input_buffer = malloc(scanline_size * scanline_number)) == NULL) { DBG(1, "read_segment: Error: Not enough memory for scanner " "input buffer\n"); goto error_out; } output_image->width = scanp->width; output_image->height = scanline_number; /* Allocate memory for dest image segment */ output_image->image_data = malloc(output_image->width * output_image->height * (scanp->mode ? 3 : 1) * 2); if (output_image->image_data == NULL) { DBG(1, "read_segment: Error: Not enough memory for " "image data\n"); goto error_out; } /* Set up packet request command */ memcpy(packet_req_command, cmd_packet_req, 10); packet_req_command[7] = ((read_data_size + 4) & 0xFF00) >> 8; packet_req_command[8] = (read_data_size + 4) & 0xFF; /* Send packet req. and wait for the scanner's READY signal */ if (send_command(sp->port, packet_req_command, 10, 9000, 2000000)) { DBG(1, "read_segment: Error: didn't get response within 2s " "of sending request"); goto error_out; } /* Read packet header */ if (sanei_canon_pp_read(sp->port, 4, packet_header)) { DBG(1, "read_segment: Error reading packet header\n"); goto error_out; } if ((packet_header[2]<<8) + packet_header[3] != read_data_size) { DBG(1, "read_segment: Error: Expected data size: %i bytes.\n", read_data_size); DBG(1, "read_segment: Expecting %i bytes times %i " "scanlines.\n", scanline_size, scanline_number); DBG(1, "read_segment: Actual data size: %i bytes.\n", (packet_header[2] << 8) + packet_header[3]); goto error_out; } /* Read scanlines_this_packet scanlines into the input buf */ if (sanei_canon_pp_read(sp->port, read_data_size, input_buffer)) { DBG(1, "read_segment: Segment read incorrectly, and we don't " "know how to recover.\n"); goto error_out; } /* This is the only place we can abort safely - * between reading one segment and requesting the next one. */ if (sp->abort_now) goto error_out; if (scanlines_left >= (scanline_number * 2)) { DBG(100, "read_segment: Speculatively starting more scanning " "(%d left)\n", scanlines_left); sanei_canon_pp_write(sp->port, 10, packet_req_command); /* Don't read status, it's unlikely to be ready *just* yet */ } DBG(100, "read_segment: Convert to RGB\n"); /* Convert data */ convert_to_rgb(output_image, input_buffer, scanp->width, scanline_number, scanp->mode); /* Adjust pixel readings according to calibration data */ if (do_adjust) { DBG(100, "read_segment: Adjust output\n"); adjust_output(output_image, scanp, sp); } /* output */ *dest = output_image; /* finished with this now */ free(input_buffer); return 0; error_out: if (output_image && output_image->image_data) free(output_image->image_data); if (output_image) free(output_image); if (input_buffer) free(input_buffer); sp->abort_now = 0; return -1; } /* check8: Calculates the checksum-8 for s bytes pointed to by p. For messages from the scanner, this should normally end up returning 0, since the last byte of most packets is the value that makes the total up to 0 (or 256 if you're left-handed). Hence, usage: if (check8(buffer, size)) {DBG(10, "checksum error!\n");} Can also be used to generate valid checksums for sending to the scanner. */ static int check8(unsigned char *p, int s) { int total=0,i; for(i=0;i linear width is in pixels, not bytes. */ /* This function could use a rewrite */ static void convdata(unsigned char *srcbuffer, unsigned char *dstbuffer, int width, int mode) /* This is a tricky (read: crap) function (read: hack) which is why I probably spent more time commenting it than programming it. The thing to remember here is that the scanner uses interpolated scanlines, so it's RRRRRRRGGGGGGBBBBBB not RGBRGBRGBRGBRGB. So, the calling function just increments the destination pointer slightly to handle green, then a bit more for blue. If you don't understand, tough. */ { int count; int i, j, k; for (count = 0; count < width; count++) { /* The scanner stores data in a bizzare butchered 10-bit format. I'll try to explain it in 100 words or less: Scanlines are made up of groups of 4 pixels. Each group of 4 is stored inside 5 bytes. The first 4 bytes of the group contain the lowest 8 bits of one pixel each (in the right order). The 5th byte contains the most significant 2 bits of each pixel in the same order. */ i = srcbuffer[count + (count >> 2)]; /* Low byte for pixel */ j = srcbuffer[(((count / 4) + 1) * 5) - 1]; /* "5th" byte */ j = j >> ((count % 4) * 2); /* Get upper 2 bits of intensity */ j = j & 0x03; /* Can't hurt */ /* And the final 10-bit pixel value is: */ k = (j << 8) | i; /* now we return this as a 16 bit value */ k = k << 6; if (mode == 1) /* Scanner -> Grey */ { dstbuffer[count * 2] = HIGH_BYTE(k); dstbuffer[(count * 2) + 1] = LOW_BYTE(k); } else if (mode == 2) /* Scanner -> RGB */ { dstbuffer[count * 3 * 2] = HIGH_BYTE(k); dstbuffer[(count * 3 * 2) + 1] = LOW_BYTE(k); } } } static int adjust_output(image_segment *image, scan_parameters *scanp, scanner_parameters *scannerp) /* Needing a good cleanup */ { /* light and dark points for the CCD sensor in question * (stored in file as 0-1024, scaled to 0-65536) */ unsigned long hi, lo; /* The result of our calculations */ unsigned long result; unsigned long temp; /* The CCD sensor which read the current pixel - this is a tricky value to get right. */ int ccd, scaled_xoff; /* Loop variables */ unsigned int scanline, pixelnum, colour; unsigned long int pixel_address; unsigned int cols = scanp->mode ? 3 : 1; for (scanline = 0; scanline < image->height; scanline++) { for (pixelnum = 0; pixelnum < image->width; pixelnum++) { /* Figure out CCD sensor number */ /* MAGIC FORMULA ALERT! */ ccd = (pixelnum << (scannerp->natural_xresolution - scanp->xresolution)) + (1 << (scannerp->natural_xresolution - scanp->xresolution)) - 1; scaled_xoff = scanp->xoffset << (scannerp->natural_xresolution - scanp->xresolution); ccd += scaled_xoff; for (colour = 0; colour < cols; colour++) { /* Address of pixel under scrutiny */ pixel_address = (scanline * image->width * cols * 2) + (pixelnum * cols * 2) + (colour * 2); /* Dark value is easy * Range of lo is 0-18k */ lo = (scannerp->blackweight[ccd]) * 3; /* Light value depends on the colour, * and is an average in greyscale mode. */ if (scanp->mode == 1) /* RGB */ { switch (colour) { case 0: hi = scannerp->redweight[ccd] * 3; break; case 1: hi = scannerp->greenweight[ccd] * 3; break; default: hi = scannerp->blueweight[ccd] * 3; break; } } else /* Grey - scanned using green */ { hi = scannerp->greenweight[ccd] * 3; } /* Check for bad calibration data as it can cause a divide-by-0 error */ if (hi <= lo) { DBG(1, "adjust_output: Bad cal data!" " hi: %ld lo: %ld\n" "Recalibrate, that " "should fix it.\n", hi, lo); return -1; } /* Start with the pixel value in result */ result = MAKE_SHORT(*(image->image_data + pixel_address), *(image->image_data + pixel_address + 1)); result = result >> 6; /* Range now = 0-1023 */ /* if (scanline == 10) DBG(200, "adjust_output: Initial pixel" " value: %ld\n", result); */ result *= 54; /* Range now = 0-54k */ /* Clip to dark and light values */ if (result < lo) result = lo; if (result > hi) result = hi; /* result = (base-lo) * max_value / (hi-lo) */ temp = result - lo; temp *= 65536; temp /= (hi - lo); /* Clip output result has been clipped to lo, * and hi >= lo, so temp can't be < 0 */ if (temp > 65535) temp = 65535; /* if (scanline == 10) { DBG(200, "adjust_output: %d: base = " "%lu, result %lu (%lu " "- %lu)\n", pixelnum, result, temp, lo, hi); } */ result = temp; /* Store the value back where it came * from (always bigendian) */ *(image->image_data + pixel_address) = HIGH_BYTE(result); *(image->image_data + pixel_address+1) = LOW_BYTE(result); } } } /*DBG(100, "Finished adjusting output\n");*/ return 0; } /* Calibration run. Aborting allowed at "safe" points where the scanner won't * be left in a crap state. */ int sanei_canon_pp_calibrate(scanner_parameters *sp, char *cal_file) { int count, readnum, colournum, scanlinenum; int outfile; int scanline_size; int scanline_count = 6; /* Don't change this unless you also want to change do_adjust */ const int calibration_reads = 3; unsigned char command_buffer[10]; image_segment image; unsigned char *databuf; char colours[3][6] = {"Red", "Green", "Blue"}; /* Calibration data is monochromatic (greyscale format) */ scanline_size = sp->scanheadwidth * 1.25; /* 620P has to be difficult here... */ if (!(sp->type) ) scanline_count = 8; /* Probably shouldn't have to abort *just* yet, but may as well check */ if (sp->abort_now) return -1; DBG(40, "Calibrating %ix%i pixels calibration image " "(%i bytes each scan).\n", sp->scanheadwidth, scanline_count, scanline_size * scanline_count); /* Allocate memory for calibration data */ sp->blackweight = (unsigned long *) calloc(sizeof(unsigned long), sp->scanheadwidth); sp->redweight = (unsigned long *) calloc(sizeof(unsigned long), sp->scanheadwidth); sp->greenweight = (unsigned long *) calloc(sizeof(unsigned long), sp->scanheadwidth); sp->blueweight = (unsigned long *) calloc(sizeof(unsigned long), sp->scanheadwidth); /* The data buffer needs to hold a number of images (calibration_reads) * per colour, each sp->scanheadwidth x scanline_count */ databuf = malloc(scanline_size * scanline_count * calibration_reads*3); /* And allocate space for converted image data in this image_segment */ image.image_data = malloc(scanline_count * sp->scanheadwidth * 2 * calibration_reads); image.width = sp->scanheadwidth; image.height = scanline_count * calibration_reads; /* Sending the "dark calibration" command */ memcpy(command_buffer, cmd_calblack, 10); /* Which includes the size of data we expect the scanner to return */ command_buffer[7] = ((scanline_size * scanline_count) & 0xff00) >> 8; command_buffer[8] = (scanline_size * scanline_count) & 0xff; DBG(40, "Step 1/3: Calibrating black level...\n"); for (readnum = 0; readnum < calibration_reads; readnum++) { DBG(40, " * Black scan number %d/%d.\n", readnum + 1, calibration_reads); if (sp->abort_now) return -1; if (send_command(sp->port, command_buffer, 10, 100000, 5000000)) { DBG(1, "Error reading black level!\n"); free (image.image_data); free(databuf); return -1; } /* Black reference data */ sanei_canon_pp_read(sp->port, scanline_size * scanline_count, databuf + (readnum * scanline_size * scanline_count)); } /* Convert scanner format to a greyscale 16bpp image */ for (scanlinenum = 0; scanlinenum < scanline_count * calibration_reads; scanlinenum++) { convdata(databuf + (scanlinenum * scanline_size), image.image_data + (scanlinenum * sp->scanheadwidth*2), sp->scanheadwidth, 1); } /* Take column totals */ for (count = 0; count < sp->scanheadwidth; count++) { /* Value is normalised as if we took 6 scanlines, even if we * didn't (620P I'm looking at you!) */ sp->blackweight[count] = (column_sum(&image, count) * 6) / scanline_count >> 6; } /* 620P has to be difficult here... */ if (!(sp->type) ) { scanline_count = 6; image.height = scanline_count * calibration_reads; } DBG(40, "Step 2/3: Gamma tables...\n"); DBG(40, " * Requesting creation of new of gamma tables...\n"); if (sp->abort_now) return -1; if (send_command(sp->port, cmd_cleargamma, 10, 100000, 5000000)) { DBG(1,"Error sending gamma command!\n"); free (image.image_data); free(databuf); return -1; } DBG(20, " * Snoozing for 15 seconds while the scanner calibrates..."); usleep(15000000); DBG(40, "done.\n"); DBG(40, " * Requesting gamma table values..."); if (send_command(sp->port, cmd_readgamma, 10, 100000, 10000000)) { DBG(1,"Error sending gamma table request!\n"); free (image.image_data); free(databuf); return -1; } DBG(40, "done.\n"); DBG(40, " * Reading white-balance/gamma data... "); sanei_canon_pp_read(sp->port, 32, sp->gamma); DBG(40, "done.\n"); if (sp->abort_now) return -1; memcpy(command_buffer, cmd_calcolour, 10); /* Set up returned data size */ command_buffer[7] = ((scanline_size * scanline_count) & 0xff00) >> 8; command_buffer[8] = (scanline_size * scanline_count) & 0xff; DBG(40, "Step 3/3: Calibrating sensors...\n"); /* Now for the RGB high-points */ for (colournum = 1; colournum < 4; colournum++) { /* Set the colour we want to read */ command_buffer[3] = colournum; for (readnum = 0; readnum < 3; readnum++) { DBG(10, " * %s sensors, scan number %d/%d.\n", colours[colournum-1], readnum + 1, calibration_reads); if (sp->abort_now) return -1; if (send_command(sp->port, command_buffer, 10, 100000, 5000000)) { DBG(1,"Error sending scan request!"); free (image.image_data); free(databuf); return -1; } sanei_canon_pp_read(sp->port, scanline_size * scanline_count, databuf + (readnum * scanline_size * scanline_count)); } /* Convert colour data from scanner format to RGB data */ for (scanlinenum = 0; scanlinenum < scanline_count * calibration_reads; scanlinenum++) { convdata(databuf + (scanlinenum * scanline_size), image.image_data + (scanlinenum * sp->scanheadwidth * 2), sp->scanheadwidth, 1); } /* Sum each column of the image and store the results in sp */ for (count = 0; count < sp->scanheadwidth; count++) { if (colournum == 1) sp->redweight[count] = column_sum(&image, count) >> 6; else if (colournum == 2) sp->greenweight[count] = column_sum(&image, count) >> 6; else sp->blueweight[count] = column_sum(&image, count) >> 6; } } if (sp->abort_now) return -1; /* cal_file == NUL indicates we want an in-memory scan only */ if (cal_file != NULL) { DBG(40, "Writing calibration to %s\n", cal_file); outfile = open(cal_file, O_WRONLY | O_TRUNC | O_CREAT, 0600); if (outfile < 0) { DBG(10, "Error opening cal file for writing\n"); } /* Header */ if (safe_write(outfile, header, strlen(header) + 1) < 0) DBG(10, "Write error on calibration file %s", cal_file); if (safe_write(outfile, (const char *)&fileversion, sizeof(int)) < 0) DBG(10, "Write error on calibration file %s", cal_file); /* Data */ if (safe_write(outfile, (char *)&(sp->scanheadwidth), sizeof(sp->scanheadwidth)) < 0) DBG(10, "Write error on calibration file %s", cal_file); if (safe_write(outfile, (char *)(sp->blackweight), sp->scanheadwidth * sizeof(long)) < 0) DBG(10, "Write error on calibration file %s", cal_file); if (safe_write(outfile, (char *)(sp->redweight), sp->scanheadwidth * sizeof(long)) < 0) DBG(10, "Write error on calibration file %s", cal_file); if (safe_write(outfile, (char *)(sp->greenweight), sp->scanheadwidth * sizeof(long)) < 0) DBG(10, "Write error on calibration file %s", cal_file); if (safe_write(outfile, (char *)(sp->blueweight), sp->scanheadwidth * sizeof(long)) < 0) DBG(10, "Write error on calibration file %s", cal_file); if (safe_write(outfile, (char *)(sp->gamma), 32) < 0) DBG(10, "Write error on calibration file %s", cal_file); close(outfile); } free(databuf); free(image.image_data); return 0; } static unsigned long column_sum(image_segment *image, int x) /* This gives us a number from 0-n*65535 where n is the height of the image */ { unsigned int row, p; unsigned long total = 0; p = x; for (row = 0; row < image->height; row++) { total+= MAKE_SHORT(image->image_data[2*p], image->image_data[2*p+1]); p += image->width; } return total; } static int scanner_setup_params(unsigned char *buf, scanner_parameters *sp, scan_parameters *scanp) { int scaled_width, scaled_height; int scaled_xoff, scaled_yoff; /* Natural resolution (I think) */ if (sp->scanheadwidth == 2552) { buf[0] = 0x11; /* 300 | 0x1000 */ buf[1] = 0x2c; buf[2] = 0x11; buf[3] = 0x2c; } else { buf[0] = 0x12; /* 600 | 0x1000*/ buf[1] = 0x58; buf[2] = 0x12; buf[3] = 0x58; } scaled_width = scanp->width << (sp->natural_xresolution - scanp->xresolution); /* YO! This needs fixing if we ever use yresolution! */ scaled_height = scanp->height << (sp->natural_xresolution - scanp->xresolution); scaled_xoff = scanp->xoffset << (sp->natural_xresolution - scanp->xresolution); scaled_yoff = scanp->yoffset << (sp->natural_xresolution - scanp->xresolution); /* Input resolution */ buf[4] = (((75 << scanp->xresolution) & 0xff00) >> 8) | 0x10; buf[5] = (75 << scanp->xresolution) & 0xff; /* Interpolated resolution */ buf[6] = (((75 << scanp->xresolution) & 0xff00) >> 8) | 0x10;; buf[7] = (75 << scanp->xresolution) & 0xff; /* X offset */ buf[8] = (scaled_xoff & 0xff000000) >> 24; buf[9] = (scaled_xoff & 0xff0000) >> 16; buf[10] = (scaled_xoff & 0xff00) >> 8; buf[11] = scaled_xoff & 0xff; /* Y offset */ buf[12] = (scaled_yoff & 0xff000000) >> 24; buf[13] = (scaled_yoff & 0xff0000) >> 16; buf[14] = (scaled_yoff & 0xff00) >> 8; buf[15] = scaled_yoff & 0xff; /* Width of image to be scanned */ buf[16] = (scaled_width & 0xff000000) >> 24; buf[17] = (scaled_width & 0xff0000) >> 16; buf[18] = (scaled_width & 0xff00) >> 8; buf[19] = scaled_width & 0xff; /* Height of image to be scanned */ buf[20] = (scaled_height & 0xff000000) >> 24; buf[21] = (scaled_height & 0xff0000) >> 16; buf[22] = (scaled_height & 0xff00) >> 8; buf[23] = scaled_height & 0xff; /* These appear to be the only two colour mode possibilities. Pure black-and-white mode probably just uses greyscale and then gets its contrast adjusted by the driver. I forget. */ if (scanp->mode == 1) /* Truecolour */ buf[24] = 0x08; else /* Greyscale */ buf[24] = 0x04; return 0; } int sanei_canon_pp_abort_scan(scanner_parameters *sp) { /* The abort command (hopefully) */ sanei_canon_pp_write(sp->port, 10, cmd_abort); sanei_canon_pp_check_status(sp->port); return 0; } /* adjust_gamma: Upload a gamma profile to the scanner */ int sanei_canon_pp_adjust_gamma(scanner_parameters *sp) { sp->gamma[31] = check8(sp->gamma, 31); if (sanei_canon_pp_write(sp->port, 10, cmd_setgamma)) return -1; if (sanei_canon_pp_write(sp->port, 32, sp->gamma)) return -1; return 0; } int sanei_canon_pp_sleep_scanner(struct parport *port) { /* *SCANEND Command - puts scanner to sleep */ sanei_canon_pp_write(port, 10, cmd_scanend); sanei_canon_pp_check_status(port); ieee1284_terminate(port); return 0; /* FIXME: I murdered Simon's code here */ /* expect(port, "Enter Transparent Mode", 0x1f, 0x1f, 1000000); */ } int sanei_canon_pp_detect(struct parport *port, int mode) { /*int caps;*/ /* This code needs to detect whether or not a scanner is present on * the port, quickly and reliably. Fast version of * sanei_canon_pp_initialise() * * If this detect returns true, a more comprehensive check will * be conducted * Return values: * 0 = scanner present * anything else = scanner not present * PRE: port is open/unclaimed * POST: port is closed/unclaimed */ /* port is already open, just need to claim it */ if (ieee1284_claim(port) != E1284_OK) { DBG(0,"detect: Unable to claim port\n"); return 2; } if (sanei_canon_pp_wake_scanner(port, mode)) { DBG(10, "detect: could not wake scanner\n"); ieee1284_release(port); return 3; } /* Goodo, sleep (snaps fingers) */ sanei_canon_pp_sleep_scanner(port); ieee1284_release(port); /* ieee1284_close(port); */ return 0; } static int send_command(struct parport *port, unsigned char *buf, int bufsize, int delay, int timeout) /* Sends a command until the scanner says it is ready. * sleeps for delay microsecs between reads * returns -1 on error, -2 on timeout */ { int retries = 0; do { /* Send command */ if (sanei_canon_pp_write(port, bufsize, buf)) return -1; /* sleep a bit */ usleep(delay); } while (sanei_canon_pp_check_status(port) && retries++ < (timeout/delay)); if (retries >= (timeout/delay)) return -2; return 0; } sane-backends-1.0.27/backend/ma1509.conf.in0000664000175000017500000000027312112021330014764 00000000000000#ma1509.conf: see sane-ma1509(5) #Warm-up time for the lamp in seconds option warmup-time 30 #Mustek BearPaw 1200F usb 0x055f 0x0010 #Manual setting (e.g. for FreeBSD) #/dev/uscanner0 sane-backends-1.0.27/backend/teco3.c0000664000175000017500000015377412112021330013774 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ VM3552 (and maybe VM4552 and VM6552) */ /*--------------------------------------------------------------------------*/ #define BUILD 1 /* 2002/08/06 */ #define BACKEND_NAME teco3 #define TECO_CONFIG_FILE "teco3.conf" /*--------------------------------------------------------------------------*/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "teco3.h" /*--------------------------------------------------------------------------*/ /* Lists of possible scan modes. */ static SANE_String_Const scan_mode_list[] = { BLACK_WHITE_STR, GRAY_STR, COLOR_STR, NULL }; /*--------------------------------------------------------------------------*/ /* Minimum and maximum width and length supported. */ static SANE_Range x_range = { SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0 }; static SANE_Range y_range = { SANE_FIX (0), SANE_FIX (14 * MM_PER_INCH), 0 }; /*--------------------------------------------------------------------------*/ /* Gamma range */ static const SANE_Range gamma_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ /* List of dithering options. */ static SANE_String_Const dither_list[] = { "Line art", "2x2", "3x3", "4x4 bayer", "4x4 smooth", "8x8 bayer", "8x8 smooth", "8x8 horizontal", "8x8 vertical", NULL }; static const int dither_val[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; /*--------------------------------------------------------------------------*/ static const SANE_Range threshold_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ /* Define the supported scanners and their characteristics. */ static const struct scanners_supported scanners[] = { { 6, "TECO VM3552", TECO_VM3552, "Relisys", "Scorpio", {1, 1200, 1}, /* resolution range */ 300, 1200 /* max x and Y resolution */ } }; /*--------------------------------------------------------------------------*/ /* List of scanner attached. */ static Teco_Scanner *first_dev = NULL; static int num_devices = 0; static const SANE_Device **devlist = NULL; /* Local functions. */ /* Display a buffer in the log. */ static void hexdump (int level, const char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; char asc_buf[17]; char *asc_ptr; DBG (level, "%s\n", comment); ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { DBG (level, "%s %s\n", line, asc_buf); ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; } sprintf (ptr, "%3.3d:", i); ptr += 4; } ptr += sprintf (ptr, " %2.2x", *p); if (*p >= 32 && *p <= 127) { asc_ptr += sprintf (asc_ptr, "%c", *p); } else { asc_ptr += sprintf (asc_ptr, "."); } } *ptr = '\0'; DBG (level, "%s %s\n", line, asc_buf); } /* Returns the length of the longest string, including the terminating * character. */ static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* Lookup a string list from one array and return its index. */ static int get_string_list_index (SANE_String_Const list[], SANE_String_Const name) { int index; index = 0; while (list[index] != NULL) { if (strcmp (list[index], name) == 0) { return (index); } index++; } DBG (DBG_error, "name %s not found in list\n", name); assert (0 == 1); /* bug in backend, core dump */ return (-1); } /* Initialize a scanner entry. Return an allocated scanner with some * preset values. */ static Teco_Scanner * teco_init (void) { Teco_Scanner *dev; DBG (DBG_proc, "teco_init: enter\n"); /* Allocate a new scanner entry. */ dev = malloc (sizeof (Teco_Scanner)); if (dev == NULL) { return NULL; } memset (dev, 0, sizeof (Teco_Scanner)); /* Allocate the buffer used to transfer the SCSI data. */ dev->buffer_size = 64 * 1024; dev->buffer = malloc (dev->buffer_size); if (dev->buffer == NULL) { free (dev); return NULL; } dev->sfd = -1; DBG (DBG_proc, "teco_init: exit\n"); return (dev); } /* Closes an open scanner. */ static void teco_close (Teco_Scanner * dev) { DBG (DBG_proc, "teco_close: enter\n"); if (dev->sfd != -1) { sanei_scsi_close (dev->sfd); dev->sfd = -1; } DBG (DBG_proc, "teco_close: exit\n"); } /* Frees the memory used by a scanner. */ static void teco_free (Teco_Scanner * dev) { int i; DBG (DBG_proc, "teco_free: enter\n"); if (dev == NULL) return; teco_close (dev); if (dev->devicename) { free (dev->devicename); } if (dev->buffer) { free (dev->buffer); } if (dev->image) { free (dev->image); } for (i = 1; i < OPT_NUM_OPTIONS; i++) { if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) { free (dev->val[i].s); } } free (dev); DBG (DBG_proc, "teco_free: exit\n"); } /* Inquiry a device and returns TRUE if is supported. */ static int teco_identify_scanner (Teco_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; int i; DBG (DBG_proc, "teco_identify_scanner: enter\n"); size = 5; MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "teco_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } size = dev->buffer[4] + 5; /* total length of the inquiry data */ if (size < 53) { DBG (DBG_error, "teco_identify_scanner: not enough data to identify device\n"); return (SANE_FALSE); } MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "teco_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } hexdump (DBG_info2, "inquiry", dev->buffer, size); dev->scsi_type = dev->buffer[0] & 0x1f; memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); dev->scsi_vendor[0x08] = 0; memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); dev->scsi_product[0x10] = 0; memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); dev->scsi_version[0x04] = 0; memcpy (dev->scsi_teco_name, dev->buffer + 0x2A, 0x0B); dev->scsi_teco_name[0x0B] = 0; DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\" \"%s\"\n", dev->scsi_vendor, dev->scsi_product, dev->scsi_version, dev->scsi_teco_name); /* Lookup through the supported scanners table to find if this * backend supports that one. */ for (i = 0; i < NELEMS (scanners); i++) { if (dev->scsi_type == scanners[i].scsi_type && strcmp (dev->scsi_teco_name, scanners[i].scsi_teco_name) == 0) { DBG (DBG_error, "teco_identify_scanner: scanner supported\n"); dev->def = &(scanners[i]); return (SANE_TRUE); } } DBG (DBG_proc, "teco_identify_scanner: exit, device not supported\n"); return (SANE_FALSE); } /* SCSI sense handler. Callback for SANE. * These scanners never set asc or ascq. */ static SANE_Status teco_sense_handler (int __sane_unused__ scsi_fd, unsigned char *result, void __sane_unused__ *arg) { int sensekey; int len; DBG (DBG_proc, "teco_sense_handler: enter\n"); sensekey = get_RS_sense_key (result); len = 7 + get_RS_additional_length (result); hexdump (DBG_info2, "sense", result, len); if (get_RS_error_code (result) != 0x70) { DBG (DBG_error, "teco_sense_handler: invalid sense key error code (%d)\n", get_RS_error_code (result)); return SANE_STATUS_IO_ERROR; } if (len < 14) { DBG (DBG_error, "teco_sense_handler: sense too short, no ASC/ASCQ\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_sense, "teco_sense_handler: sense=%d\n", sensekey); if (sensekey == 0x00) { return SANE_STATUS_GOOD; } return SANE_STATUS_IO_ERROR; } /* Set a window. */ static SANE_Status teco_set_window (Teco_Scanner * dev) { size_t window_size; CDB cdb; unsigned char window[255]; SANE_Status status; int i; DBG (DBG_proc, "teco_set_window: enter\n"); /* size of the whole windows block */ switch (dev->def->tecoref) { case TECO_VM3552: window_size = 69; break; default: assert(0); } MKSCSI_SET_WINDOW (cdb, window_size); memset (window, 0, window_size); /* size of the windows descriptor block */ window[7] = window_size - 8; /* X and Y resolution */ Ito16 (dev->x_resolution, &window[10]); Ito16 (dev->y_resolution, &window[12]); /* Upper Left (X,Y) */ Ito32 (dev->x_tl, &window[14]); Ito32 (dev->y_tl, &window[18]); /* Width and length */ Ito32 (dev->width, &window[22]); Ito32 (dev->length, &window[26]); /* Image Composition */ switch (dev->scan_mode) { case TECO_BW: window[31] = dev->val[OPT_THRESHOLD].w; window[33] = 0x00; i = get_string_list_index (dither_list, dev->val[OPT_DITHER].s); window[36] = dither_val[i]; break; case TECO_GRAYSCALE: window[31] = 0x80; window[33] = 0x02; break; case TECO_COLOR: window[31] = 0x80; window[33] = 0x05; break; } /* Depth */ window[34] = dev->depth; /* Unknown - invariants */ window[37] = 0x80; switch (dev->def->tecoref) { case TECO_VM3552: window[48] = 0x01; window[50] = 0x02; window[53] = 0xff; window[57] = 0xff; window[61] = 0xff; window[65] = 0xff; break; } hexdump (DBG_info2, "windows", window, window_size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, window, window_size, NULL, NULL); DBG (DBG_proc, "teco_set_window: exit, status=%d\n", status); return status; } /* Park the CCD */ static SANE_Status teco_reset_window (Teco_Scanner * dev) { SANE_Status status; CDB cdb; DBG (DBG_proc, "teco_reset_window: enter\n"); MKSCSI_OBJECT_POSITION (cdb, 0); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "teco_reset_window: leave, status=%d\n", status); return status; } /* Return the number of byte that can be read. */ static SANE_Status get_filled_data_length (Teco_Scanner * dev, size_t * to_read) { size_t size; CDB cdb; SANE_Status status; DBG (DBG_proc, "get_filled_data_length: enter\n"); *to_read = 0; size = 0x12; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (size < 0x10) { DBG (DBG_error, "get_filled_data_length: not enough data returned (%ld)\n", (long) size); } hexdump (DBG_info2, "get_filled_data_length return", dev->buffer, size); *to_read = B24TOI (&dev->buffer[9]); DBG (DBG_info, "%d %d - %d %d\n", dev->params.lines, B16TOI (&dev->buffer[12]), dev->params.bytes_per_line, B16TOI (&dev->buffer[14])); if (dev->real_bytes_left == 0) { DBG (DBG_error, "get_filled_data_length: internal scanner buffer size is %d bytes\n", B24TOI (&dev->buffer[6])); /* Beginning of a scan. */ dev->params.lines = B16TOI (&dev->buffer[12]); dev->bytes_per_raster = B16TOI (&dev->buffer[14]); switch (dev->scan_mode) { case TECO_BW: dev->params.bytes_per_line = B16TOI (&dev->buffer[14]); dev->params.pixels_per_line = dev->params.bytes_per_line * 8; break; case TECO_GRAYSCALE: dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); dev->params.bytes_per_line = dev->params.pixels_per_line; break; case TECO_COLOR: dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); dev->params.bytes_per_line = dev->params.pixels_per_line * 3; if (dev->buffer[17] == 0x07) { /* There is no RAM extension present. The colors will * be shifted and the backend will need to fix that. */ dev->does_color_shift = 1; } else { dev->does_color_shift = 0; } break; } } DBG (DBG_info, "get_filled_data_length: to read = %ld\n", (long) *to_read); DBG (DBG_proc, "get_filled_data_length: exit, status=%d\n", status); return (status); } /* Start a scan. */ static SANE_Status teco_scan (Teco_Scanner * dev) { CDB cdb; SANE_Status status; DBG (DBG_proc, "teco_scan: enter\n"); MKSCSI_SCAN (cdb); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "teco_scan: exit, status=%d\n", status); return status; } /* Do some vendor specific stuff. */ static SANE_Status teco_vendor_spec (Teco_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; DBG (DBG_proc, "teco_vendor_spec: enter\n"); size = 0x7800; cdb.data[0] = 0x09; cdb.data[1] = 0; cdb.data[2] = 0; cdb.data[3] = (size >> 8) & 0xff; cdb.data[4] = (size >> 0) & 0xff; cdb.data[5] = 0; cdb.len = 6; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); /*hexdump (DBG_info2, "calibration:", dev->buffer, size); */ cdb.data[0] = 0x0E; cdb.data[1] = 0; cdb.data[2] = 0; cdb.data[3] = 0; cdb.data[4] = 0; cdb.data[5] = 0; cdb.len = 6; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); return status; } /* Send the gamma */ static SANE_Status teco_send_gamma (Teco_Scanner * dev) { CDB cdb; SANE_Status status; struct { unsigned char gamma_R[GAMMA_LENGTH]; unsigned char gamma_G[GAMMA_LENGTH]; /* also gray */ unsigned char gamma_B[GAMMA_LENGTH]; unsigned char gamma_unused[GAMMA_LENGTH]; } param; size_t i; size_t size; DBG (DBG_proc, "teco_send_gamma: enter\n"); size = sizeof (param); assert (size == 4 * GAMMA_LENGTH); MKSCSI_SEND_10 (cdb, 0x03, 0x02, size); if (dev->val[OPT_CUSTOM_GAMMA].w) { /* Use the custom gamma. */ if (dev->scan_mode == TECO_GRAYSCALE) { /* Gray */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = 0; param.gamma_G[i] = dev->gamma_GRAY[i]; param.gamma_B[i] = 0; param.gamma_unused[i] = 0; } } else { /* Color */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = dev->gamma_R[i]; param.gamma_G[i] = dev->gamma_G[i]; param.gamma_B[i] = dev->gamma_B[i]; param.gamma_unused[i] = 0; } } } else { for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = i / 4; param.gamma_G[i] = i / 4; param.gamma_B[i] = i / 4; param.gamma_unused[i] = 0; } } hexdump (DBG_info2, "teco_send_gamma:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, ¶m, size, NULL, NULL); DBG (DBG_proc, "teco_send_gamma: exit, status=%d\n", status); return (status); } /* Attach a scanner to this backend. */ static SANE_Status attach_scanner (const char *devicename, Teco_Scanner ** devp) { Teco_Scanner *dev; SANE_Status status; int sfd; DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); if (devp) *devp = NULL; /* Check if we know this device name. */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (DBG_info, "device is already known\n"); return SANE_STATUS_GOOD; } } /* Allocate a new scanner entry. */ dev = teco_init (); if (dev == NULL) { DBG (DBG_error, "ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_scanner: opening %s\n", devicename); status = sanei_scsi_open (devicename, &sfd, teco_sense_handler, dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "ERROR: attach_scanner: open failed (%s)\n", sane_strstatus (status)); teco_free (dev); return SANE_STATUS_INVAL; } /* Fill some scanner specific values. */ dev->devicename = strdup (devicename); dev->sfd = sfd; /* Now, check that it is a scanner we support. */ if (teco_identify_scanner (dev) == SANE_FALSE) { DBG (DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); teco_free (dev); return SANE_STATUS_INVAL; } teco_close (dev); /* Set the default options for that scanner. */ dev->sane.name = dev->devicename; dev->sane.vendor = dev->def->real_vendor; dev->sane.model = dev->def->real_product; dev->sane.type = "flatbed scanner"; /* Link the scanner with the others. */ dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } num_devices++; DBG (DBG_proc, "attach_scanner: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach_scanner (dev, NULL); return SANE_STATUS_GOOD; } /* Reset the options for that scanner. */ static void teco_init_options (Teco_Scanner * dev) { int i; /* Pre-initialize the options. */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < OPT_NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options. */ dev->opt[OPT_NUM_OPTS].name = ""; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; /* Mode group */ dev->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].cap = 0; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scanner supported modes */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = max_string_size (scan_mode_list); dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = scan_mode_list; dev->val[OPT_MODE].s = (SANE_Char *) strdup (""); /* will be set later */ /* X and Y resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RESOLUTION].constraint.range = &dev->def->res_range; dev->val[OPT_RESOLUTION].w = 100; /* Geometry group */ dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_GEOMETRY_GROUP].cap = 0; dev->opt[OPT_GEOMETRY_GROUP].size = 0; dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Upper left X */ dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &x_range; dev->val[OPT_TL_X].w = x_range.min; /* Upper left Y */ dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &y_range; dev->val[OPT_TL_Y].w = y_range.min; /* Bottom-right x */ dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &x_range; dev->val[OPT_BR_X].w = x_range.max; /* Bottom-right y */ dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &y_range; dev->val[OPT_BR_Y].w = y_range.max; /* Enhancement group */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Halftone pattern */ dev->opt[OPT_DITHER].name = "dither"; dev->opt[OPT_DITHER].title = SANE_I18N ("Dither"); dev->opt[OPT_DITHER].desc = SANE_I18N ("Dither"); dev->opt[OPT_DITHER].type = SANE_TYPE_STRING; dev->opt[OPT_DITHER].size = max_string_size (dither_list); dev->opt[OPT_DITHER].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_DITHER].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_DITHER].constraint.string_list = dither_list; dev->val[OPT_DITHER].s = strdup (dither_list[0]); /* custom-gamma table */ dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* red gamma vector */ dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_R].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_R].wa = dev->gamma_R; /* green and gamma vector */ dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_G].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_G].wa = dev->gamma_G; /* blue gamma vector */ dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_B].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_B].wa = dev->gamma_B; /* grayscale gamma vector */ dev->opt[OPT_GAMMA_VECTOR_GRAY].name = SANE_NAME_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].title = SANE_TITLE_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].desc = SANE_DESC_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_GRAY].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_GRAY].wa = dev->gamma_GRAY; /* Threshold */ dev->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; dev->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; dev->opt[OPT_THRESHOLD].size = sizeof (SANE_Int); dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_THRESHOLD].constraint.range = &threshold_range; dev->val[OPT_THRESHOLD].w = 128; /* preview */ dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; dev->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; dev->val[OPT_PREVIEW].w = SANE_FALSE; /* Lastly, set the default scan mode. This might change some * values previously set here. */ sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, (SANE_String_Const *) scan_mode_list[0], NULL); } /* * Wait until the scanner is ready. */ static SANE_Status teco_wait_scanner (Teco_Scanner * dev) { SANE_Status status; int timeout; CDB cdb; DBG (DBG_proc, "teco_wait_scanner: enter\n"); MKSCSI_TEST_UNIT_READY (cdb); /* Set the timeout to 60 seconds. */ timeout = 60; while (timeout > 0) { /* test unit ready */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); if (status == SANE_STATUS_GOOD) { return SANE_STATUS_GOOD; } sleep (1); }; DBG (DBG_proc, "teco_wait_scanner: scanner not ready\n"); return (SANE_STATUS_IO_ERROR); } /* * Get the sense */ static SANE_Status teco_query_sense (Teco_Scanner * dev) { SANE_Status status; unsigned char buf[255]; CDB cdb; size_t size; DBG (DBG_proc, "teco_wait_scanner: enter\n"); size = sizeof (buf); MKSCSI_REQUEST_SENSE (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, buf, &size); hexdump (DBG_info2, "sense", buf, size); DBG (DBG_error, "teco_query_sense: return (%s)\n", sane_strstatus (status)); return (status); } /* * Adjust the rasters. This function is used during a color scan, * because the scanner does not present a format sane can interpret * directly. * * The scanner sends the colors by rasters (B then G then R), whereas * sane is waiting for a group of 3 bytes per color. To make things * funnier, the rasters are shifted. The format of those raster is: * BGR...BGR * * For a proper scan, the first 2 R and 1 G, and the last 1 G and 2 B * must be ignored. (TODO) * * So this function reorders all that mess. It gets the input from * dev->buffer and write the output in dev->image. size_in the the * length of the valid data in dev->buffer. */ /* 0=red, 1=green, 2=blue */ #define COLOR_0 2 #define COLOR_1 1 #define COLOR_2 0 #define line_shift ( - dev->color_shift) static void teco_adjust_raster (Teco_Scanner * dev, size_t size_in) { int nb_rasters; /* number of rasters in dev->buffer */ int raster; /* current raster number in buffer */ int line; /* line number for that raster */ int color = -1; /* color for that raster */ size_t offset; DBG (DBG_proc, "teco_adjust_raster: enter\n"); assert (dev->scan_mode == TECO_COLOR); assert ((size_in % dev->bytes_per_raster) == 0); if (size_in == 0) { return; } /* * The color coding is one line for each color (in the RGB order). * Recombine that stuff to create a RGB value for each pixel. */ nb_rasters = size_in / dev->raster_size; for (raster = 0; raster < nb_rasters; raster++) { /* * Find the color to which this raster belongs to. */ line = 0; if (dev->raster_num < dev->color_shift) { color = COLOR_0; line = dev->raster_num; } else if (dev->raster_num < (3 * dev->color_shift)) { if ((dev->raster_num - line_shift) % 2) { color = COLOR_1; line = (dev->raster_num + line_shift) / 2; } else { color = COLOR_0; line = (dev->raster_num - line_shift) / 2; } } else if (dev->raster_num >= dev->raster_real - dev->color_shift) { color = COLOR_2; line = dev->line; } else if (dev->raster_num >= dev->raster_real - 3 * dev->color_shift) { if ((dev->raster_real - dev->raster_num - line_shift) % 2) { color = COLOR_2; line = dev->line; } else { color = COLOR_1; line = dev->line - line_shift; } } else { switch ((dev->raster_num - 3 * line_shift) % 3) { case 0: color = COLOR_0; line = (dev->raster_num - 3 * line_shift) / 3; break; case 1: color = COLOR_1; line = dev->raster_num / 3; break; case 2: color = COLOR_2; line = (dev->raster_num + 3 * line_shift) / 3; break; } } /* Adjust the line number relative to the image. */ line -= dev->line; offset = dev->image_end + line * dev->params.bytes_per_line; assert (offset <= (dev->image_size - dev->params.bytes_per_line)); /* Copy the raster to the temporary image. */ { int i; unsigned char *src = dev->buffer + raster * dev->raster_size; unsigned char *dest = dev->image + offset + color; for (i = 0; i < dev->raster_size; i++) { *dest = *src; src++; dest += 3; } assert (dest <= (dev->image + dev->image_size + 2)); } DBG (DBG_info, "raster=%d, line=%d, color=%d\n", dev->raster_num, dev->line + line, color); if (color == COLOR_2) { /* This raster completes a new line */ dev->line++; dev->image_end += dev->params.bytes_per_line; } dev->raster_num++; } DBG (DBG_proc, "teco_adjust_raster: exit\n"); } /* Read the image from the scanner and fill the temporary buffer with it. */ static SANE_Status teco_fill_image (Teco_Scanner * dev) { SANE_Status status; size_t size; CDB cdb; unsigned char *image; DBG (DBG_proc, "teco_fill_image: enter\n"); assert (dev->image_begin == dev->image_end); assert (dev->real_bytes_left > 0); /* Copy the complete lines, plus the incompletes * ones. We don't keep the real end of data used * in image, so we copy the biggest possible. */ if (dev->scan_mode == TECO_COLOR) { memmove (dev->image, dev->image + dev->image_begin, dev->raster_ahead); } dev->image_begin = 0; dev->image_end = 0; while (dev->real_bytes_left) { /* todo: teco2 too */ /* Check that we can at least one line. */ if (dev->raster_ahead + dev->image_end + dev->params.bytes_per_line > dev->image_size) { /* Probably reached the end of the buffer. * Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } /* * Try to read the maximum number of bytes. */ size = 0; while (size == 0) { status = get_filled_data_length (dev, &size); if (status) return (status); if (size == 0) usleep (100000); /* sleep 1/10th of second */ } if (size > dev->real_bytes_left) size = dev->real_bytes_left; if (size > dev->image_size - dev->raster_ahead - dev->image_end) size = dev->image_size - dev->raster_ahead - dev->image_end; if (size > dev->buffer_size) { size = dev->buffer_size; } /* Always read a multiple of a raster. */ size = size - (size % dev->bytes_per_raster); if (size == 0) { /* Probably reached the end of the buffer. * Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } DBG (DBG_info, "teco_fill_image: to read = %ld bytes (bpl=%d)\n", (long) size, dev->params.bytes_per_line); MKSCSI_READ_10 (cdb, 0, 0, size); hexdump (DBG_info2, "teco_fill_image: READ_10 CDB", cdb.data, 10); DBG (DBG_info, " image_end=%lu\n", (u_long) dev->image_end); if (dev->scan_mode == TECO_COLOR && dev->does_color_shift) { image = dev->buffer; } else { image = dev->image + dev->image_end; } status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, image, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "teco_fill_image: cannot read from the scanner\n"); return status; } /* The size this scanner returns is always a multiple of a * raster size. */ assert ((size % dev->bytes_per_raster) == 0); DBG (DBG_info, "teco_fill_image: real bytes left = %ld\n", (long) dev->real_bytes_left); if (dev->scan_mode == TECO_COLOR && dev->does_color_shift) { teco_adjust_raster (dev, size); } else { /* Already in dev->image. */ dev->image_end += size; } dev->real_bytes_left -= size; } return (SANE_STATUS_GOOD); /* unreachable */ } /* Copy from the raw buffer to the buffer given by the backend. * * len in input is the maximum length available in buf, and, in * output, is the length written into buf. */ static void teco_copy_raw_to_frontend (Teco_Scanner * dev, SANE_Byte * buf, size_t * len) { size_t size; size = dev->image_end - dev->image_begin; if (size > *len) { size = *len; } *len = size; switch (dev->scan_mode) { case TECO_BW: { /* For Black & White, the bits in every bytes are mirrored. * for instance 11010001 is coded as 10001011 */ unsigned char *src = dev->image + dev->image_begin; size_t i; unsigned char s; unsigned char d; for (i = 0; i < size; i++) { s = *src ^ 0xff; d = 0; if (s & 0x01) d |= 0x80; if (s & 0x02) d |= 0x40; if (s & 0x04) d |= 0x20; if (s & 0x08) d |= 0x10; if (s & 0x10) d |= 0x08; if (s & 0x20) d |= 0x04; if (s & 0x40) d |= 0x02; if (s & 0x80) d |= 0x01; *buf = d; src++; buf++; } } break; case TECO_GRAYSCALE: case TECO_COLOR: memcpy (buf, dev->image + dev->image_begin, size); break; } dev->image_begin += size; } /* Stop a scan. */ static SANE_Status do_cancel (Teco_Scanner * dev) { DBG (DBG_sane_proc, "do_cancel enter\n"); if (dev->scanning == SANE_TRUE) { teco_reset_window (dev); teco_close (dev); } dev->scanning = SANE_FALSE; DBG (DBG_sane_proc, "do_cancel exit\n"); return SANE_STATUS_CANCELLED; } /*--------------------------------------------------------------------------*/ /* Sane entry points */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; char dev_name[PATH_MAX]; size_t len; DBG_INIT (); DBG (DBG_sane_init, "sane_init\n"); DBG (DBG_error, "This is sane-teco3 version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_error, "(C) 2002 by Frank Zago\n"); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); } fp = sanei_config_open (TECO_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach_scanner ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); DBG (DBG_proc, "sane_init: leave\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { Teco_Scanner *dev; int i; DBG (DBG_proc, "sane_get_devices: enter\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Teco_Scanner *dev; SANE_Status status; int i; DBG (DBG_proc, "sane_open: enter\n"); /* search for devicename */ if (devicename[0]) { DBG (DBG_info, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); dev = first_dev; /* empty devicename -> use first device */ } if (!dev) { DBG (DBG_error, "No scanner found\n"); return SANE_STATUS_INVAL; } teco_init_options (dev); /* Initialize the gamma table. */ for (i = 0; i < GAMMA_LENGTH; i++) { dev->gamma_R[i] = i / 4; dev->gamma_G[i] = i / 4; dev->gamma_B[i] = i / 4; dev->gamma_GRAY[i] = i / 4; } *handle = dev; DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); if ((unsigned) option >= OPT_NUM_OPTIONS) { return NULL; } DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return dev->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Teco_Scanner *dev = handle; SANE_Status status; SANE_Word cap; SANE_String_Const name; DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", option, action); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } name = dev->opt[option].name; if (!name) { name = "(no name)"; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_CUSTOM_GAMMA: case OPT_THRESHOLD: case OPT_PREVIEW: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_DITHER: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; /* Gamma */ case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (val, dev->val[option].wa, dev->opt[option].size); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Numeric side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_THRESHOLD: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* Numeric side-effect free options */ case OPT_PREVIEW: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* String side-effect free options */ case OPT_DITHER: free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); return SANE_STATUS_GOOD; /* String side-effect options */ case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); dev->opt[OPT_DITHER].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, BLACK_WHITE_STR) == 0) { dev->depth = 8; dev->scan_mode = TECO_BW; dev->opt[OPT_DITHER].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, GRAY_STR) == 0) { dev->scan_mode = TECO_GRAYSCALE; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } dev->depth = 8; } else if (strcmp (dev->val[OPT_MODE].s, COLOR_STR) == 0) { dev->scan_mode = TECO_COLOR; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } dev->depth = 8; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (dev->val[option].wa, val, dev->opt[option].size); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: dev->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; if (dev->val[OPT_CUSTOM_GAMMA].w) { /* use custom_gamma_table */ if (dev->scan_mode == TECO_GRAYSCALE) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } else { /* color mode */ dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { /* Setup the parameters for the scan. These values will be re-used * in the SET WINDOWS command. */ if (dev->val[OPT_PREVIEW].w == SANE_TRUE) { dev->x_resolution = 50; dev->y_resolution = 50; dev->x_tl = 0; dev->y_tl = 0; dev->x_br = mmToIlu (SANE_UNFIX (x_range.max)); dev->y_br = mmToIlu (SANE_UNFIX (y_range.max)); } else { dev->x_resolution = dev->val[OPT_RESOLUTION].w; dev->y_resolution = dev->val[OPT_RESOLUTION].w; if (dev->x_resolution > dev->def->x_resolution_max) { dev->x_resolution = dev->def->x_resolution_max; } dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); } /* Check the corners are OK. */ if (dev->x_tl > dev->x_br) { int s; s = dev->x_tl; dev->x_tl = dev->x_br; dev->x_br = s; } if (dev->y_tl > dev->y_br) { int s; s = dev->y_tl; dev->y_tl = dev->y_br; dev->y_br = s; } dev->width = dev->x_br - dev->x_tl; dev->length = dev->y_br - dev->y_tl; /* Prepare the parameters for the caller. */ memset (&dev->params, 0, sizeof (SANE_Parameters)); dev->params.last_frame = SANE_TRUE; switch (dev->scan_mode) { case TECO_BW: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / 300) & ~0x7; dev->params.bytes_per_line = dev->params.pixels_per_line / 8; dev->params.depth = 1; dev->color_shift = 0; break; case TECO_GRAYSCALE: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / 300); dev->params.bytes_per_line = dev->params.pixels_per_line; dev->params.depth = 8; dev->color_shift = 0; break; case TECO_COLOR: dev->params.format = SANE_FRAME_RGB; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / 300); dev->params.bytes_per_line = dev->params.pixels_per_line * 3; dev->params.depth = 8; /* If the scanner does not have enough memory, it will * send the raw rasters instead of returning a full * interleaved line. Unfortunatly this does not work well, * because I don't know how to compute the color * shifting. So here is the result of some trial and error * process. This is ignored if the scanner has a RAM * module. */ dev->color_shift = dev->x_resolution / 75; break; } dev->params.lines = (dev->length * dev->y_resolution) / 300; } /* Return the current values. */ if (params) { *params = (dev->params); } DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Teco_Scanner *dev = handle; SANE_Status status; size_t size; DBG (DBG_proc, "sane_start: enter\n"); if (!(dev->scanning)) { /* Open again the scanner. */ if (sanei_scsi_open (dev->devicename, &(dev->sfd), teco_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: sane_start: open failed\n"); return SANE_STATUS_INVAL; } /* Set the correct parameters. */ sane_get_parameters (dev, NULL); /* The scanner must be ready. */ status = teco_wait_scanner (dev); if (status) { teco_close (dev); return status; } teco_query_sense (dev); teco_reset_window (dev); status = teco_set_window (dev); if (status) { teco_close (dev); return status; } dev->real_bytes_left = 0; status = get_filled_data_length (dev, &size); if (status) { teco_close (dev); return status; } /* Compute the length necessary in image. The first part will store * the complete lines, and the rest is used to stored ahead * rasters. * Align image_size to a multiple of lines. (important) */ dev->raster_ahead = (2 * dev->color_shift + 1) * dev->params.bytes_per_line; dev->image_size = dev->buffer_size + dev->raster_ahead; dev->image_size = dev->image_size - (dev->image_size % dev->params.bytes_per_line); dev->image = malloc (dev->image_size); if (dev->image == NULL) { return SANE_STATUS_NO_MEM; } /* Rasters are meaningfull only in color mode. */ dev->raster_size = dev->params.pixels_per_line; dev->raster_real = dev->params.lines * 3; dev->raster_num = 0; dev->line = 0; teco_vendor_spec (dev); if (status) { teco_close (dev); return status; } status = teco_send_gamma (dev); if (status) { teco_close (dev); return status; } status = teco_set_window (dev); if (status) { teco_close (dev); return status; } status = teco_scan (dev); if (status) { teco_close (dev); return status; } } dev->image_end = 0; dev->image_begin = 0; dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->real_bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->scanning = SANE_TRUE; DBG (DBG_proc, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status status; Teco_Scanner *dev = handle; size_t size; int buf_offset; /* offset into buf */ DBG (DBG_proc, "sane_read: enter\n"); *len = 0; if (!(dev->scanning)) { /* OOPS, not scanning */ return do_cancel (dev); } if (dev->bytes_left <= 0) { return (SANE_STATUS_EOF); } buf_offset = 0; do { if (dev->image_begin == dev->image_end) { /* Fill image */ status = teco_fill_image (dev); if (status != SANE_STATUS_GOOD) { return (status); } } /* Something must have been read */ if (dev->image_begin == dev->image_end) { DBG (DBG_info, "sane_read: nothing read\n"); return SANE_STATUS_IO_ERROR; } /* Copy the data to the frontend buffer. */ size = max_len - buf_offset; if (size > dev->bytes_left) { size = dev->bytes_left; } teco_copy_raw_to_frontend (dev, buf + buf_offset, &size); buf_offset += size; dev->bytes_left -= size; *len += size; } while ((buf_offset != max_len) && dev->bytes_left); DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", (long) dev->bytes_left); return SANE_STATUS_GOOD; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { SANE_Status status; Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_set_io_mode: enter\n"); if (dev->scanning == SANE_FALSE) { return SANE_STATUS_INVAL; } if (non_blocking == SANE_FALSE) { status = SANE_STATUS_GOOD; } else { status = SANE_STATUS_UNSUPPORTED; } DBG (DBG_proc, "sane_set_io_mode: exit\n"); return status; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { DBG (DBG_proc, "sane_get_select_fd: enter\n"); DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } void sane_cancel (SANE_Handle handle) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_cancel: enter\n"); do_cancel (dev); DBG (DBG_proc, "sane_cancel: exit\n"); } void sane_close (SANE_Handle handle) { Teco_Scanner *dev = handle; Teco_Scanner *dev_tmp; DBG (DBG_proc, "sane_close: enter\n"); do_cancel (dev); teco_close (dev); /* Unlink dev. */ if (first_dev == dev) { first_dev = dev->next; } else { dev_tmp = first_dev; while (dev_tmp->next && dev_tmp->next != dev) { dev_tmp = dev_tmp->next; } if (dev_tmp->next != NULL) { dev_tmp->next = dev_tmp->next->next; } } teco_free (dev); num_devices--; DBG (DBG_proc, "sane_close: exit\n"); } void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); while (first_dev) { sane_close (first_dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); } sane-backends-1.0.27/backend/genesys_gl843.h0000664000175000017500000014113512775312261015373 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2010-2013 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "genesys.h" #ifdef UNIT_TESTING SANE_Status gl843_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps); SANE_Status gl843_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ float yres, /*dpi */ float startx, /*optical_res, from dummy_pixel+1 */ float starty, /*base_ydpi, from home! */ float pixels, float lines, unsigned int depth, unsigned int channels, int scan_mode, int color_filter, unsigned int flags); SANE_Status gl843_start_action (Genesys_Device * dev); SANE_Status gl843_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor); SANE_Status gl843_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop); SANE_Status gl843_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home); SANE_Status gl843_feed (Genesys_Device * dev, unsigned int steps); SANE_Status gl843_init (Genesys_Device * dev); SANE_Status gl843_boot (Genesys_Device * dev, SANE_Bool cold); SANE_Status gl843_send_shading_data (Genesys_Device * dev, uint8_t * data, int size); SANE_Status gl843_bulk_write_register (Genesys_Device * dev, Genesys_Register_Set * reg, size_t elems); SANE_Status gl843_xpa_lamp_on (Genesys_Device * dev); SANE_Status gl843_xpa_motor_on (Genesys_Device * dev); SANE_Status gl843_xpa_motor_off (Genesys_Device * dev); SANE_Status gl843_move_to_ta (Genesys_Device * dev); #endif #define DBGSTART DBG (DBG_proc, "%s start\n", __func__); #define DBGCOMPLETED DBG (DBG_proc, "%s completed\n", __func__); #define REG01 0x01 #define REG01_CISSET 0x80 #define REG01_DOGENB 0x40 #define REG01_DVDSET 0x20 #define REG01_STAGGER 0x10 #define REG01_COMPENB 0x08 #define REG01_TRUEGRAY 0x04 #define REG01_SHDAREA 0x02 #define REG01_SCAN 0x01 #define REG02 0x02 #define REG02_NOTHOME 0x80 #define REG02_ACDCDIS 0x40 #define REG02_AGOHOME 0x20 #define REG02_MTRPWR 0x10 #define REG02_FASTFED 0x08 #define REG02_MTRREV 0x04 #define REG02_HOMENEG 0x02 #define REG02_LONGCURV 0x01 #define REG03 0x03 #define REG03_LAMPDOG 0x80 #define REG03_AVEENB 0x40 #define REG03_XPASEL 0x20 #define REG03_LAMPPWR 0x10 #define REG03_LAMPTIM 0x0f #define REG04 0x04 #define REG04_LINEART 0x80 #define REG04_BITSET 0x40 #define REG04_AFEMOD 0x30 #define REG04_FILTER 0x0c #define REG04_FESET 0x03 #define REG04S_AFEMOD 4 #define REG05 0x05 #define REG05_DPIHW 0xc0 #define REG05_DPIHW_600 0x00 #define REG05_DPIHW_1200 0x40 #define REG05_DPIHW_2400 0x80 #define REG05_DPIHW_4800 0xc0 #define REG05_MTLLAMP 0x30 #define REG05_GMMENB 0x08 #define REG05_MTLBASE 0x03 #define REG06 0x06 #define REG06_SCANMOD 0xe0 #define REG06S_SCANMOD 5 #define REG06_PWRBIT 0x10 #define REG06_GAIN4 0x08 #define REG06_OPTEST 0x07 #define REG07_LAMPSIM 0x80 #define REG08_DECFLAG 0x40 #define REG08_GMMFFR 0x20 #define REG08_GMMFFG 0x10 #define REG08_GMMFFB 0x08 #define REG08_GMMZR 0x04 #define REG08_GMMZG 0x02 #define REG08_GMMZB 0x01 #define REG09_MCNTSET 0xc0 #define REG09_EVEN1ST 0x20 #define REG09_BLINE1ST 0x10 #define REG09_BACKSCAN 0x08 #define REG09_ENHANCE 0x04 #define REG09_SHORTTG 0x02 #define REG09_NWAIT 0x01 #define REG09S_MCNTSET 6 #define REG09S_CLKSET 4 #define REG0B 0x0b #define REG0B_DRAMSEL 0x07 #define REG0B_ENBDRAM 0x08 #define REG0B_ENBDRAM 0x08 #define REG0B_RFHDIS 0x10 #define REG0B_CLKSET 0xe0 #define REG0B_24MHZ 0x00 #define REG0B_30MHZ 0x20 #define REG0B_40MHZ 0x40 #define REG0B_48MHZ 0x60 #define REG0B_60MHZ 0x80 #define REG0D 0x0d #define REG0D_JAMPCMD 0x80 #define REG0D_DOCCMD 0x40 #define REG0D_CCDCMD 0x20 #define REG0D_FULLSTP 0x10 #define REG0D_SEND 0x08 #define REG0D_CLRMCNT 0x04 #define REG0D_CLRDOCJM 0x02 #define REG0D_CLRLNCNT 0x01 #define REG0F 0x0f #define REG_EXPR 0x10 #define REG_EXPG 0x12 #define REG_EXPB 0x14 #define REG16_CTRLHI 0x80 #define REG16_TOSHIBA 0x40 #define REG16_TGINV 0x20 #define REG16_CK1INV 0x10 #define REG16_CK2INV 0x08 #define REG16_CTRLINV 0x04 #define REG16_CKDIS 0x02 #define REG16_CTRLDIS 0x01 #define REG17_TGMODE 0xc0 #define REG17_TGMODE_NO_DUMMY 0x00 #define REG17_TGMODE_REF 0x40 #define REG17_TGMODE_XPA 0x80 #define REG17_TGW 0x3f #define REG17S_TGW 0 #define REG18 0x18 #define REG18_CNSET 0x80 #define REG18_DCKSEL 0x60 #define REG18_CKTOGGLE 0x10 #define REG18_CKDELAY 0x0c #define REG18_CKSEL 0x03 #define REG_EXPDMY 0x19 #define REG1A_TGLSW2 0x80 #define REG1A_TGLSW1 0x40 #define REG1A_MANUAL3 0x02 #define REG1A_MANUAL1 0x01 #define REG1A_CK4INV 0x08 #define REG1A_CK3INV 0x04 #define REG1A_LINECLP 0x02 #define REG1C 0x1c #define REG1C_TGTIME 0x07 #define REG1D_CK4LOW 0x80 #define REG1D_CK3LOW 0x40 #define REG1D_CK1LOW 0x20 #define REG1D_TGSHLD 0x1f #define REG1DS_TGSHLD 0 #define REG1E 0x1e #define REG1E_WDTIME 0xf0 #define REG1ES_WDTIME 4 #define REG1E_LINESEL 0x0f #define REG1ES_LINESEL 0 #define REG21 0x21 #define REG_STEPNO 0x21 #define REG_FWDSTEP 0x22 #define REG_BWDSTEP 0x23 #define REG_FASTNO 0x24 #define REG_LINCNT 0x25 #define REG29 0x29 #define REG2A 0x2a #define REG2B 0x2b #define REG_DPISET 0x2c #define REG2E 0x2e #define REG2F 0x2f #define REG_STRPIXEL 0x30 #define REG_ENDPIXEL 0x32 #define REG_DUMMY 0x34 #define REG_MAXWD 0x35 #define REG_LPERIOD 0x38 #define REG_FEEDL 0x3d #define REG40 0x40 #define REG40_DOCSNR 0x80 #define REG40_ADFSNR 0x40 #define REG40_COVERSNR 0x20 #define REG40_CHKVER 0x10 #define REG40_DOCJAM 0x08 #define REG40_HISPDFLG 0x04 #define REG40_MOTMFLG 0x02 #define REG40_DATAENB 0x01 #define REG41_PWRBIT 0x80 #define REG41_BUFEMPTY 0x40 #define REG41_FEEDFSH 0x20 #define REG41_SCANFSH 0x10 #define REG41_HOMESNR 0x08 #define REG41_LAMPSTS 0x04 #define REG41_FEBUSY 0x02 #define REG41_MOTORENB 0x01 #define REG58_VSMP 0xf8 #define REG58S_VSMP 3 #define REG58_VSMPW 0x07 #define REG58S_VSMPW 0 #define REG59_BSMP 0xf8 #define REG59S_BSMP 3 #define REG59_BSMPW 0x07 #define REG59S_BSMPW 0 #define REG5A_ADCLKINV 0x80 #define REG5A_RLCSEL 0x40 #define REG5A_CDSREF 0x30 #define REG5AS_CDSREF 4 #define REG5A_RLC 0x0f #define REG5AS_RLC 0 #define REG5E 0x5e #define REG5E_DECSEL 0xe0 #define REG5ES_DECSEL 5 #define REG5E_STOPTIM 0x1f #define REG5ES_STOPTIM 0 #define REG_FMOVDEC 0x5f #define REG60 0x60 #define REG60_Z1MOD 0x1f #define REG61 0x61 #define REG61_Z1MOD 0xff #define REG62 0x62 #define REG62_Z1MOD 0xff #define REG63 0x63 #define REG63_Z2MOD 0x1f #define REG64 0x64 #define REG64_Z2MOD 0xff #define REG65 0x65 #define REG65_Z2MOD 0xff #define REG67 0x67 #define REG68 0x68 #define REG67S_STEPSEL 6 #define REG67_STEPSEL 0xc0 #define REG67_FULLSTEP 0x00 #define REG67_HALFSTEP 0x20 #define REG67_EIGHTHSTEP 0x60 #define REG67_16THSTEP 0x80 #define REG68S_FSTPSEL 6 #define REG68_FSTPSEL 0xc0 #define REG68_FULLSTEP 0x00 #define REG68_HALFSTEP 0x20 #define REG68_EIGHTHSTEP 0x60 #define REG68_16THSTEP 0x80 #define REG_FSHDEC 0x69 #define REG_FMOVNO 0x6a #define REG6B 0x6b #define REG6B_MULTFILM 0x80 #define REG6B_GPOM13 0x40 #define REG6B_GPOM12 0x20 #define REG6B_GPOM11 0x10 #define REG6B_GPOCK4 0x08 #define REG6B_GPOCP 0x04 #define REG6B_GPOLEDB 0x02 #define REG6B_GPOADF 0x01 #define REG6C 0x6c #define REG6C_GPIO16 0x80 #define REG6C_GPIO15 0x40 #define REG6C_GPIO14 0x20 #define REG6C_GPIO13 0x10 #define REG6C_GPIO12 0x08 #define REG6C_GPIO11 0x04 #define REG6C_GPIO10 0x02 #define REG6C_GPIO9 0x01 #define REG6C_GPIOH 0xff #define REG6C_GPIOL 0xff #define REG_Z1MOD 0x60 #define REG_Z2MOD 0x63 #define REG6D 0x6d #define REG6E 0x6e #define REG6F 0x6f #define REG_CK1MAP 0x74 #define REG_CK3MAP 0x77 #define REG_CK4MAP 0x7a #define REG7E 0x7e #define REG9D 0x9d #define REG9DS_STEPTIM 2 #define REG87_LEDADD 0x04 #define REGA6 0xa6 #define REGA6_GPIO24 0x80 #define REGA6_GPIO23 0x40 #define REGA6_GPIO22 0x20 #define REGA6_GPIO21 0x10 #define REGA6_GPIO20 0x08 #define REGA6_GPIO19 0x04 #define REGA6_GPIO18 0x02 #define REGA6_GPIO17 0x01 #define REGA7 0xa7 #define REGA7_GPOE24 0x80 #define REGA7_GPOE23 0x40 #define REGA7_GPOE22 0x20 #define REGA7_GPOE21 0x10 #define REGA7_GPOE20 0x08 #define REGA7_GPOE19 0x04 #define REGA7_GPOE18 0x02 #define REGA7_GPOE17 0x01 #define REGA8 0xa8 #define REGA8_GPOE27 0x20 #define REGA8_GPOE26 0x10 #define REGA8_GPOE25 0x08 #define REGA8_GPO27 0x04 #define REGA8_GPO26 0x02 #define REGA8_GPO25 0x01 #define REGA9 0xa9 #define REGA9_GPO33 0x20 #define REGA9_GPO32 0x10 #define REGA9_GPO31 0x08 #define REGA9_GPO30 0x04 #define REGA9_GPO29 0x02 #define REGA9_GPO28 0x01 #define SCAN_TABLE 0 /* table 1 at 0x4000 */ #define BACKTRACK_TABLE 1 /* table 2 at 0x4800 */ #define STOP_TABLE 2 /* table 3 at 0x5000 */ #define FAST_TABLE 3 /* table 4 at 0x5800 */ #define HOME_TABLE 4 /* table 5 at 0x6000 */ #define SCAN_FLAG_SINGLE_LINE 0x001 #define SCAN_FLAG_DISABLE_SHADING 0x002 #define SCAN_FLAG_DISABLE_GAMMA 0x004 #define SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE 0x008 #define SCAN_FLAG_IGNORE_LINE_DISTANCE 0x010 #define SCAN_FLAG_USE_OPTICAL_RES 0x020 #define SCAN_FLAG_DISABLE_LAMP 0x040 #define SCAN_FLAG_DYNAMIC_LINEART 0x080 /** * writable scanner registers */ enum { reg_0x01 = 0, reg_0x02, reg_0x03, reg_0x04, reg_0x05, reg_0x06, reg_0x08, reg_0x09, reg_0x0a, reg_0x0b, reg_0x0c, reg_0x0f, reg_0x10, reg_0x11, reg_0x12, reg_0x13, reg_0x14, reg_0x15, reg_0x16, reg_0x17, reg_0x18, reg_0x19, reg_0x1a, reg_0x1b, reg_0x1c, reg_0x1d, reg_0x1e, reg_0x1f, reg_0x20, reg_0x21, reg_0x22, reg_0x23, reg_0x24, reg_0x25, reg_0x26, reg_0x27, reg_0x28, reg_0x2c, reg_0x2d, reg_0x2e, reg_0x2f, reg_0x30, reg_0x31, reg_0x32, reg_0x33, reg_0x34, reg_0x35, reg_0x36, reg_0x37, reg_0x38, reg_0x39, reg_0x3a, reg_0x3b, reg_0x3c, reg_0x3d, reg_0x3e, reg_0x3f, reg_0x51, reg_0x52, reg_0x53, reg_0x54, reg_0x55, reg_0x56, reg_0x57, reg_0x58, reg_0x59, reg_0x5a, reg_0x5d, reg_0x5e, reg_0x5f, reg_0x60, reg_0x61, reg_0x62, reg_0x63, reg_0x64, reg_0x65, reg_0x67, reg_0x68, reg_0x69, reg_0x6a, reg_0x6b, reg_0x70, reg_0x71, reg_0x72, reg_0x73, reg_0x74, reg_0x75, reg_0x76, reg_0x77, reg_0x78, reg_0x79, reg_0x7a, reg_0x7b, reg_0x7c, reg_0x7d, reg_0x7e, reg_0x7f, reg_0x80, reg_0x81, reg_0x82, reg_0x83, reg_0x84, reg_0x85, reg_0x86, reg_0x87, reg_0x88, reg_0x89, reg_0x8a, reg_0x8b, reg_0x8c, reg_0x8d, reg_0x8e, reg_0x8f, reg_0x90, reg_0x91, reg_0x92, reg_0x93, reg_0x94, reg_0x95, reg_0x96, reg_0x97, reg_0x98, reg_0x99, reg_0x9a, reg_0x9b, reg_0x9c, reg_0x9d, reg_0x9e, reg_0xa0, reg_0xa1, reg_0xa2, reg_0xa3, reg_0xa4, reg_0xa5, reg_0xaa, reg_0xab, reg_0xac, reg_0xad, reg_0xae, reg_0xaf, GENESYS_GL843_MAX_REGS }; #define SETREG(adr,val) {dev->reg[reg_##adr].address=adr;dev->reg[reg_##adr].value=val;} typedef struct { SANE_Int gpo_type; uint8_t ra6; uint8_t ra7; uint8_t ra8; uint8_t ra9; } Gpio_layout; static Gpio_layout gpios[]={ /* G4050 */ { GPO_G4050, 0x08, 0x1e, 0x3e, 0x06 }, /* KV-SS080 */ { GPO_KVSS080, 0x06, 0x0f, 0x00, 0x08 }, /* 4400F */ { GPO_CS4400F, 0x00, 0xff, 0x07, 0x00 }, /* 8400F */ { GPO_CS8400F, 0x00, 0x03, 0x00, 0x02 }, /* end marker */ { 0, 0, 0, 0, 0 }, }; /** @brief structure for sensor settings * this structure describes the sensor settings to use for a given * exposure. */ typedef struct { int sensor_type; /**> sensor id */ int dpi; /**> maximum dpi for which data are valid */ int exposure; /**> exposure */ int ck1map; /**> CK1MAP */ int ck3map; /**> CK2MAP */ int ck4map; /**> CK3MAP */ int segcnt; /**> SEGCNT */ int tg0cnt; /**> TG0CNT */ int expdummy; /**> exposure dummy */ int expr; /**> initial red exposure */ int expg; /**> initial green exposure */ int expb; /**> initial blue exposure */ uint8_t reg0c; /**> register 0x0c value */ uint8_t reg70; /**> register 0x70 value */ uint8_t reg71; /**> register 0x71 value */ uint8_t reg9e; /**> register 0x9e value */ uint8_t regaa; /**> either undocumented or mapping to somewhere else */ uint8_t regs_0x10_0x1d[14]; uint8_t regs_0x52_0x5e[13]; } Sensor_Profile; /** * database of sensor profiles */ static Sensor_Profile xpa_sensors[]={ {CCD_G4050 , 600, 15624, 0x001c7f, 0x03ffff, 0x03ffff, 5168, 0, 0x2a, 0, 0, 0, 0x00, 0x00, 0x02, 0x00, 0x00, {0x2c, 0x09, 0x22, 0xb8, 0x10, 0xf0, 0x33, 0x4c, 0x01, 0x2a, 0x30, 0x00, 0x00, 0x08} , {0x0e, 0x11, 0x02, 0x05, 0x08, 0x0b, 0x6b, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x6f}, }, }; static Sensor_Profile sensors[]={ /* 0c 70 71 9e aa*/ {CCD_KVSS080, 600, 8000, 0x000000, 0x00ffff, 0x03ffff, 5168, 0, 0x2a, 0, 0, 0, 0x00, 0x01, 0x03, 0x00, 0x00, /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x1c, 0x00, 0x2a, 0x2c, 0x00, 0x20, 0x04} , /* 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e */ {0x0c, 0x0f, 0x00, 0x03, 0x06, 0x09, 0x6b, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x23}, }, {CCD_G4050 , 600, 8016, 0x0001ff, 0x03ffff, 0x03ffff, 5168, 0, 0x2a, 0, 0, 0, 0x00, 0x00, 0x02, 0x00, 0x00, {0x2c, 0x09, 0x22, 0xb8, 0x10, 0xf0, 0x33, 0x0c, 0x00, 0x2a, 0x30, 0x00, 0x00, 0x08} , {0x0b, 0x0e, 0x11, 0x02, 0x05, 0x08, 0x63, 0x00, 0x40, 0x00, 0x00, 0x00, 0x63}, }, {CCD_G4050 , 1200, 56064, 0x0fffff, 0x0001ff, 0x0001ff, 5168, 0, 0x2a, 0, 0, 0, 0x20, 0x08, 0x0c, 0xc0, 0x05, {0x2c, 0x09, 0x22, 0xb8, 0x10, 0xf0, 0x3b, 0x0c, 0x10, 0x2a, 0x38, 0x10, 0x00, 0x08} , {0x02, 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x1b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x63}, }, {CCD_G4050 , 2400, 56064, 0x0fffff, 0x000000, 0x000000, 5168, 0, 0x2a, 0, 0, 0, 0x20, 0x08, 0x0a, 0xc0, 0x05, {0x2c, 0x09, 0x22, 0xb8, 0x10, 0xf0, 0x3b, 0x0c, 0x10, 0x2a, 0x38, 0x10, 0xc0, 0x08} , {0x02, 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x1b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x63}, }, {CCD_G4050 , 4800, 42752, 0x0fffff, 0x000000, 0x000000, 5168, 0, 0x2a, 0, 0, 0, 0x21, 0x08, 0x0a, 0xc0, 0x07, {0x2c, 0x09, 0x22, 0xb8, 0x10, 0xf0, 0x3b, 0x0c, 0x10, 0x2a, 0x38, 0x10, 0xc1, 0x08} , {0x02, 0x05, 0x08, 0x0b, 0x0e, 0x11, 0x1b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x63}, }, {CCD_CS4400F, 600, 11640, 0xf838, 0xfc00, 0x92a4, 5168, 0, 0x2a, 0x9c40, 0x9c40, 0x9c40, 0x00, 0x00, 0x02, 0x2d, 0x00, {0x9c, 0x40, 0x9c, 0x40, 0x9c, 0x40, 0x13, 0x0a, 0x10, 0x2a, 0x30, 0x00, 0x00, 0x6b}, {0x0a, 0x0d, 0x00, 0x03, 0x06, 0x08, 0x5b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f}, }, {CCD_CS8400F, 600, 7200, 0x0e3f, 0x0000, 0x1b6db, 5168, 0, 0x2a, 0x0, 0x0, 0x0, 0x00, 0x01, 0x02, 0x00, 0x00, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x0c, 0x13, 0x2a, 0x30, 0x00, 0x00, 0x84}, {0x0d, 0x10, 0x01, 0x04, 0x07, 0x0a, 0x6b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x85}, } }; static uint32_t kvss080[]={44444, 34188, 32520, 29630, 26666, 24242, 22222, 19048, 16666, 15686, 14814, 14034, 12402, 11110, 8888, 7618, 6666, 5926, 5228, 4678, 4172, 3682, 3336, 3074, 2866, 2702, 2566, 2450, 2352, 2266, 2188, 2118, 2056, 2002, 1950, 1904, 1860, 1820, 1784, 1748, 1716, 1684, 1656, 1628, 1600, 1576, 1552, 1528, 1506, 1486, 1466, 1446, 1428, 1410, 1394, 1376, 1360, 1346, 1330, 1316, 1302, 1288, 1276, 1264, 1250, 1238, 1228, 1216, 1206, 1194, 1184, 1174, 1164, 1154, 1146, 1136, 1128, 1120, 1110, 1102, 1094, 1088, 1080, 1072, 1064, 1058, 1050, 1044, 1038, 1030, 1024, 1018, 1012, 1006, 1000, 994, 988, 984, 978, 972, 968, 962, 958, 952, 948, 942, 938, 934, 928, 924, 920, 916, 912, 908, 904, 900, 896, 892, 888, 884, 882, 878, 874, 870, 868, 864, 860, 858, 854, 850, 848, 844, 842, 838, 836, 832, 830, 826, 824, 822, 820, 816, 814, 812, 808, 806, 804, 802, 800, 796, 794, 792, 790, 788, 786, 784, 782, 778, 776, 774, 772, 770, 768, 766, 764, 762, 760, 758, 756, 754, 752, 750, 750, 748, 746, 744, 742, 740, 738, 736, 734, 734, 732, 730, 728, 726, 724, 724, 722, 720, 718, 716, 716, 714, 712, 710, 710, 708, 706, 704, 704, 702, 700, 698, 698, 696, 694, 694, 692, 690, 690, 688, 686, 686, 684, 682, 682, 680, 678, 678, 676, 674, 674, 672, 672, 670, 668, 668, 666, 666, 664, 662, 662, 660, 660, 658, 656, 656, 654, 654, 652, 652, 650, 650, 648, 646, 646, 644, 644, 642, 642, 640, 640, 638, 638, 636, 636, 636, 634, 634, 632, 632, 630, 630, 628, 628, 626, 626, 624, 624, 624, 622, 622, 620, 620, 618, 618, 618, 616, 616, 614, 614, 612, 612, 612, 610, 610, 608, 608, 608, 606, 606, 606, 604, 604, 602, 602, 602, 600, 600, 600, 598, 598, 596, 596, 596, 594, 594, 594, 592, 592, 592, 590, 590, 590, 588, 588, 588, 586, 586, 586, 584, 584, 584, 582, 582, 582, 590, 590, 590, 588, 588, 588, 586, 586, 586, 584, 584, 584, 582, 582, 582, 580, 580, 580, 578, 578, 578, 576, 576, 576, 576, 574, 574, 574, 572, 572, 572, 570, 570, 570, 568, 568, 568, 568, 566, 566, 566, 564, 564, 564, 562, 562, 562, 562, 560, 560, 560, 558, 558, 558, 558, 556, 556, 556, 554, 554, 554, 552, 552, 552, 552, 550, 550, 550, 548, 548, 548, 548, 546, 546, 546, 546, 544, 544, 544, 542, 542, 542, 542, 540, 540, 540, 538, 538, 538, 538, 536, 536, 536, 536, 534, 534, 534, 534, 532, 532, 532, 530, 530, 530, 530, 528, 528, 528, 528, 526, 526, 526, 526, 524, 524, 524, 524, 522, 522, 522, 522, 520, 520, 520, 520, 518, 518, 518, 516, 516, 516, 516, 514, 514, 514, 514, 514, 512, 512, 512, 512, 510, 510, 510, 510, 508, 508, 508, 508, 506, 506, 506, 506, 504, 504, 504, 504, 502, 502, 502, 502, 500, 500, 500, 500, 0}; static uint32_t g4050_fast[]={7842,5898,4384,4258,4152,4052,3956,3864,3786,3714,3632,3564,3498,3444,3384,3324,3276,3228,3174,3128,3086,3044,3002,2968,2930,2892,2860,2824,2794,2760,2732,2704,2676,2650,2618,2594,2568,2548,2524,2500,2478,2454,2436,2414,2392,2376,2354,2338,2318,2302,2282,2266,2252,2232,2218,2202,2188,2174,2160,2142,2128,2116,2102,2088,2076,2062,2054,2040,2028,2020,2014,2008,2004,2002,2002,2002,1946,1882,1826,1770,1716,1662,1612,1568,1526,1488,1454,1422,1390,1362,1336,1310,1288,1264,1242,1222,1204,1184,1166,1150,1134,1118,1104,1090,1076,1064,1050,1038,1026,1016,1004,994,984,972,964,954,944,936,928,920,910,902,896,888,880,874,866,860,854,848,840,834,828,822,816,812,806,800,796,790,784,780,776,770,766,760,756,752,748,744,740,736,732,728,724,720,716,712,708,704,702,698,694,690,688,684,682,678,674,672,668,666,662,660,656,654,650,648,646,644,640,638,636,632,630,628,624,622,620,618,616,614,610,608,606,604,602,600,598,596,594,592,590,588,586,584,582,580,578,576,574,572,570,568,566,564,564,562,560,558,556,554,552,552,550,548,546,546,544,542,540,538,538,536,534,532,532,530,528,528,526,524,522,522,520,518,518,516,514,514,512,512,510,508,508,506,504,504,502,502,500,498,498,496,496,494,494,492,490,490,488,488,486,486,484,484,482,480,480,478,478,476,476,474,474,472,472,470,470,468,468,468,466,466,464,464,462,462,460,460,458,458,456,456,456,454,454,452,452,450,450,450,448,448,446,446,444,444,444,442,442,440,440,440,438,438,438,436,436,434,434,434,432,432,432,430,430,428,428,428,426,426,426,424,424,424,422,422,422,420,420,420,418,418,418,416,416,416,414,414,414,412,412,412,410,410,410,408,408,408,406,406,406,404,404,404,404,402,402,402,400,400,400,400,398,398,398,396,396,396,396,394,394,394,392,392,392,392,390,390,390,388,388,388,388,386,386,386,386,384,384,384,384,382,382,382,382,380,380,380,380,378,378,378,378,376,376,376,376,376,374,374,374,374,374,372,372,372,372,372,370,370,370,370,370,368,368,368,368,368,366,366,366,366,366,364,364,364,364,364,364,362,362,362,362,362,360,360,360,360,360,360,358,358,358,358,358,358,356,356,356,356,356,356,354,354,354,354,354,352,352,352,352,352,352,350,350,350,350,350,350,350,348,348,348,348,348,348,346,346,346,346,346,346,344,344,344,344,344,344,344,342,342,342,342,342,342,340,340,340,340,340,340,340,338,338,338,338,338,338,338,336,336,336,336,336,336,336,334,334,334,334,334,334,334,332,332,332,332,332,332,332,332,330,330,330,330,330,330,330,328,328,328,328,328,328,328,328,326,326,326,326,326,326,326,324,324,324,324,324,324,324,324,322,322,322,322,322,322,322,322,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320, 0}; static uint32_t g4050_high[]={28032,28032,28032,28032,28032,28032,28032,28032, 27668,27024,26479,25975,25402,24926,24465,24087,23667,23248,22912,22576,22198,21877,21583,21289,20996,20758,20492,20226,20002,19751,19541,19303,19107,18911,18715,18534,18310,18142,17960,17820,17652,17485,17331,17163,17037,16883,16729,16617,16463,16352,16212,16100,15960,15848,15750,15610,15512,15400,15302,15204,15107,14981,14883,14799,14701,14603,14519,14421,14365,14267,14183,14127,14085,14043,14016,14002,14002,14002,13610,13162,12771,12379,12001,11624,11274,10966,10672,10407,10169,9945,9721,9525,9344,9162,9008,8840,8686,8546,8420,8280,8155,8043,7931,7819,7721,7623,7525,7441,7343,7259,7175,7105,7021,6952,6882,6798,6742,6672,6602,6546,6490,6434,6364,6308,6266,6210,6154,6112,6056,6014,5972,5930,5874,5833,5791,5749,5707,5679,5637,5595,5567,5525,5483,5455,5427,5385,5357,5315,5287,5259,5231,5203,5175,5147,5119,5091,5063,5035,5007,4979,4951,4923,4909,4881,4853,4825,4811,4783,4769,4741,4713,4699,4672,4658,4630,4616,4588,4574,4546,4532,4518,4504,4476,4462,4448,4420,4406,4392,4364,4350,4336,4322,4308,4294,4266,4252,4238,4224,4210,4196,4182,4168,4154,4140,4126,4112,4098,4084,4070,4056,4042,4028,4014,4000,3986,3972,3958,3944,3944,3930,3916,3902,3888,3874,3860,3860,3846,3832,3818,3818,3804,3790,3776,3762,3762,3748,3734,3720,3720,3706,3692,3692,3678,3664,3650,3650,3636,3622,3622,3608,3594,3594,3580,3580,3566,3552,3552,3538,3524,3524,3510,3510,3497,3483,3483,3469,3469,3455,3455,3441,3427,3427,3413,3413,3399,3399,3385,3385,3371,3357,3357,3343,3343,3329,3329,3315,3315,3301,3301,3287,3287,3273,3273,3273,3259,3259,3245,3245,3231,3231,3217,3217,3203,3203,3189,3189,3189,3175,3175,3161,3161,3147,3147,3147,3133,3133,3119,3119,3105,3105,3105,3091,3091,3077,3077,3077,3063,3063,3063,3049,3049,3035,3035,3035,3021,3021,3021,3007,3007,2993,2993,2993,2979,2979,2979,2965,2965,2965,2951,2951,2951,2937,2937,2937,2923,2923,2923,2909,2909,2909,2895,2895,2895,2881,2881,2881,2867,2867,2867,2853,2853,2853,2839,2839,2839,2825,2825,2825,2825,2811,2811,2811,2797,2797,2797,2797,2783,2783,2783,2769,2769,2769,2769,2755,2755,2755,2741,2741,2741,2741,2727,2727,2727,2713,2713,2713,2713,2699,2699,2699,2699,2685,2685,2685,2685,2671,2671,2671,2671,2657,2657,2657,2657,2643,2643,2643,2643,2629,2629,2629,2629,2629,2615,2615,2615,2615,2615,2601,2601,2601,2601,2601,2587,2587,2587,2587,2587,2573,2573,2573,2573,2573,2559,2559,2559,2559,2559,2545,2545,2545,2545,2545,2545,2531,2531,2531,2531,2531,2517,2517,2517,2517,2517,2517,2503,2503,2503,2503,2503,2503,2489,2489,2489,2489,2489,2489,2475,2475,2475,2475,2475,2461,2461,2461,2461,2461,2461,2447,2447,2447,2447,2447,2447,2447,2433,2433,2433,2433,2433,2433,2419,2419,2419,2419,2419,2419,2405,2405,2405,2405,2405,2405,2405,2391,2391,2391,2391,2391,2391,2377,2377,2377,2377,2377,2377,2377,2363,2363,2363,2363,2363,2363,2363,2349,2349,2349,2349,2349,2349,2349,2336,2336,2336,2336,2336,2336,2336,2322,2322,2322,2322,2322,2322,2322,2322,2308,2308,2308,2308,2308,2308,2308,2294,2294,2294,2294,2294,2294,2294,2294,2280,2280,2280,2280,2280,2280,2280,2266,2266,2266,2266,2266,2266,2266,2266,2252,2252,2252,2252,2252,2252,2252,2252,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238,2238, 0}; static uint32_t g4050_max[]={42752,42752,42752,42752,42752,42752,42752,42752, 41824,31456,23381,22709,22144,21610,21098,20608,20192,19808,19370,19008,18656,18368,18048,17728,17472,17216,16928,16682,16458,16234,16010,15829,15626,15424,15253,15061,14901,14720,14570,14421,14272,14133,13962,13834,13696,13589,13461,13333,13216,13088,12992,12874,12757,12672,12554,12469,12362,12277,12170,12085,12010,11904,11829,11744,11669,11594,11520,11424,11349,11285,11210,11136,11072,10997,10954,10880,10816,10773,10741,10709,10688,10677,10677,10677,10378,10037,9738,9440,9152,8864,8597,8362,8138,7936,7754,7584,7413,7264,7125,6986,6869,6741,6624,6517,6421,6314,6218,6133,6048,5962,5888,5813,5738,5674,5600,5536,5472,5418,5354,5301,5248,5184,5141,5088,5034,4992,4949,4906,4853,4810,4778,4736,4693,4661,4618,4586,4554,4522,4480,4448,4416,4384,4352,4330,4298,4266,4245,4213,4181,4160,4138,4106,4085,4053,4032,4010,3989,3968,3946,3925,3904,3882,3861,3840,3818,3797,3776,3754,3744,3722,3701,3680,3669,3648,3637,3616,3594,3584,3562,3552,3530,3520,3498,3488,3466,3456,3445,3434,3413,3402,3392,3370,3360,3349,3328,3317,3306,3296,3285,3274,3253,3242,3232,3221,3210,3200,3189,3178,3168,3157,3146,3136,3125,3114,3104,3093,3082,3072,3061,3050,3040,3029,3018,3008,3008,2997,2986,2976,2965,2954,2944,2944,2933,2922,2912,2912,2901,2890,2880,2869,2869,2858,2848,2837,2837,2826,2816,2816,2805,2794,2784,2784,2773,2762,2762,2752,2741,2741,2730,2730,2720,2709,2709,2698,2688,2688,2677,2677,2666,2656,2656,2645,2645,2634,2634,2624,2613,2613,2602,2602,2592,2592,2581,2581,2570,2560,2560,2549,2549,2538,2538,2528,2528,2517,2517,2506,2506,2496,2496,2496,2485,2485,2474,2474,2464,2464,2453,2453,2442,2442,2432,2432,2432,2421,2421,2410,2410,2400,2400,2400,2389,2389,2378,2378,2368,2368,2368,2357,2357,2346,2346,2346,2336,2336,2336,2325,2325,2314,2314,2314,2304,2304,2304,2293,2293,2282,2282,2282,2272,2272,2272,2261,2261,2261,2250,2250,2250,2240,2240,2240,2229,2229,2229,2218,2218,2218,2208,2208,2208,2197,2197,2197,2186,2186,2186,2176,2176,2176,2165,2165,2165,2154,2154,2154,2154,2144,2144,2144,2133,2133,2133,2133,2122,2122,2122,2112,2112,2112,2112,2101,2101,2101,2090,2090,2090,2090,2080,2080,2080,2069,2069,2069,2069,2058,2058,2058,2058,2048,2048,2048,2048,2037,2037,2037,2037,2026,2026,2026,2026,2016,2016,2016,2016,2005,2005,2005,2005,2005,1994,1994,1994,1994,1994,1984,1984,1984,1984,1984,1973,1973,1973,1973,1973,1962,1962,1962,1962,1962,1952,1952,1952,1952,1952,1941,1941,1941,1941,1941,1941,1930,1930,1930,1930,1930,1920,1920,1920,1920,1920,1920,1909,1909,1909,1909,1909,1909,1898,1898,1898,1898,1898,1898,1888,1888,1888,1888,1888,1877,1877,1877,1877,1877,1877,1866,1866,1866,1866,1866,1866,1866,1856,1856,1856,1856,1856,1856,1845,1845,1845,1845,1845,1845,1834,1834,1834,1834,1834,1834,1834,1824,1824,1824,1824,1824,1824,1813,1813,1813,1813,1813,1813,1813,1802,1802,1802,1802,1802,1802,1802,1792,1792,1792,1792,1792,1792,1792,1781,1781,1781,1781,1781,1781,1781,1770,1770,1770,1770,1770,1770,1770,1770,1760,1760,1760,1760,1760,1760,1760,1749,1749,1749,1749,1749,1749,1749,1749,1738,1738,1738,1738,1738,1738,1738,1728,1728,1728,1728,1728,1728,1728,1728,1717,1717,1717,1717,1717,1717,1717,1717,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,1706,0}; static uint32_t g4050_xpa[]={9422,5978,4736,4028,3560,3220,2914,2756,2588,2448,2328,2224,2132,2052,1978,1914,1854,1800,1752,1706,1664,1626,1588,1554,1522,1492,1464,1438,1412,1388,1366,1344,1324,1304,1284,1268,1250,1232,1218,1202,1188,1172,1160,1146,1134,1120,1110,1098,1086,1076,1066,1056,1046,1036,1026,1018,1008,1000,992,984,976,968,960,952,946,938,932,924,918,912,906,898,892,888,882,876,870,864,860,854,848,844,838,834,828,824,820,814,810,806,802,798,794,790,786,782,778,774,770,766,762,758,754,752,748,744,740,738,734,730,728,724,722,718,716,712,710,706,704,700,698,696,692,690,686,684,682,678,676,674,672,668,666,664,662,660,656,654,652,650,648,646,644,642,638,636,634,632,630,628,626,624,622,620,618,616,614,612,612,610,608,606,604,602,600,598,596,594,594,592,590,588,586,584,584,582,580,578,576,576,574,572,570,570,568,566,564,564,562,560,560,558,556,554,554,552,550,550,548,546,546,544,542,542,540,540,538,536,536,534,532,532,530,530,528,526,526,524,524,522,522,520,518,518,516,516,514,514,512,512,510,508,508,506,506,504,504,502,502,500,500,498,498,496,496,494,494,492,492,492,490,490,488,488,486,486,484,484,482,482,480,480,480,478,478,476,476,474,474,474,472,472,470,470,468,468,468,466,466,464,464,464,462,462,462,460,460,458,458,458,456,456,454,454,454,452,452,452,450,450,450,448,448,446,446,446,444,444,444,442,442,442,440,440,440,438,438,438,436,436,436,434,434,434,432,432,432,430,430,430,430,428,428,428,426,426,426,424,424,424,424,422,422,422,420,420,420,418,418,418,418,416,416,416,414,414,414,414,412,412,412,412,410,410,410,408,408,408,408,406,406,406,406,404,404,404,404,402,402,402,402,400,400,400,400,398,398,398,398,396,396,396,396,394,394,394,394,392,392,392,392,392,390,390,390,390,388,388,388,388,386,386,386,386,386,384,384,384,384,384,382,382,382,382,380,380,380,380,380,378,378,378,378,378,376,376,376,376,376,374,374,374,374,374,372,372,372,372,372,370,370,370,370,370,368,368,368,368,368,366,366,366,366,366,364,364,364,364,364,364,362,362,362,362,362,360,360,360,360,360,360,358,358,358,358,358,358,356,356,356,356,356,354,354,354,354,354,354,352,352,352,352,352,352,350,350,350,350,350,350,350,348,348,348,348,348,348,346,346,346,346,346,346,344,344,344,344,344,344,344,342,342,342,342,342,342,340,340,340,340,340,340,340,338,338,338,338,338,338,338,336,336,336,336,336,336,336,334,334,334,334,334,334,334,332,332,332,332,332,332,332,330,330,330,330,330,330,330,330,328,328,328,328,328,328,328,326,326,326,326,326,326,326,326,324,324,324,324,324,324,324,324,322,322,322,322,322,322,322,322,320,320,320,320,320,320,320,320,318,318,318,318,318,318,318,318,318,316,316,316,316,316,316,316,316,314,314,314,314,314,314,314,314,314,312,312,312,312,312,312,312,312,312,310,310,310,310,310,310,310,310,310,308,308,308,308,308,308,308,308,308,306,306,306,306,306,306,306,306,306,306,304,304,304,304,304,304,304,304,304,302,302,302,302,302,302,302,302,302,302,300,300,300,300,300,300,300,300,300,300,298,298,298,298,298,298,298,298,298,298,298,296,296,296,296,296,296,296,296,296,296,294,294,294,294,294,294,294,294,294,294,294,292,292,292,292,292,292,292,292,292,292,292,290,290,290,290,290,290,290,290,290,290,290,288,288,288,288,288,288,288,288,288,288,288,288,286,286,286,286,286,286,286,286,286,286,286,286,284,284,284,284,284,284,284,284,284,284,284,284,282,282,282,282,282,282,282,282,282,282,282,282,280,280,280,280,280,280,280,280,280,280,280,280,280,278,278,278,278,278,278,278,278,278,278,278,278,278,276,276,276,276,276,276,276,276,276,276,276,276,276,274,274,274,274,274,274,274,274,274,274,274,274,274,274,272,272,272,272,272,272,272,272,272,272,272,272,272,272,270,270,270,270,270,270,270,270,270,270,270,270,270,270,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,0}; static uint32_t cs4400f_fast[]={49152, 49152, 31144, 23652, 19538, 16822, 14908, 13442, 12288, 11356, 10590, 9922, 9362, 8886, 8456, 8064, 7728, 7418, 7148, 6882, 6664, 6446, 6252, 6060, 5890, 5740, 5586, 5450, 5322, 5198, 5080, 4968, 4868, 4766, 4674, 4584, 4500, 4418, 4338, 4262, 4194, 4122, 4058, 3996, 3932, 3874, 3816, 3766, 3712, 3662, 3610, 3566, 3518, 3474, 3430, 3388, 3350, 3310, 3272, 3236, 3200, 3164, 3130, 3096, 3062, 3032, 3000, 2972, 2942, 2914, 2884, 2858, 2832, 2806, 2780, 2756, 2732, 2708, 2686, 2662, 2640, 2618, 2596, 2576, 2554, 2536, 2516, 2496, 2478, 2458, 2440, 2422, 2404, 2388, 2370, 2354, 2338, 2320, 2306, 2290, 2276, 2258, 2244, 2230, 2216, 2202, 2188, 2174, 2162, 2148, 2134, 2122, 2108, 2096, 2084, 2072, 2060, 2048, 2036, 2026, 2014, 2002, 1992, 1982, 1970, 1960, 1950, 1940, 1928, 1920, 1908, 1900, 1890, 1880, 1872, 1862, 1852, 1844, 1834, 1826, 1818, 1808, 1800, 1792, 1784, 1776, 1768, 1760, 1752, 1742, 1736, 1728, 1720, 1712, 1704, 1698, 1690, 1684, 1676, 1670, 1662, 1656, 1648, 1642, 1634, 1628, 1622, 1616, 1608, 1602, 1596, 1590, 1584, 1578, 1572, 1566, 1560, 1554, 1548, 1542, 1536, 1532, 1526, 1520, 1514, 1508, 1504, 1498, 1492, 1488, 1482, 1478, 1472, 1466, 1462, 1456, 1452, 1446, 1442, 1438, 1432, 1428, 1424, 1418, 1414, 1410, 1404, 1400, 1396, 1390, 1386, 1382, 1378, 1374, 1370, 1364, 1360, 1356, 1352, 1348, 1344, 1340, 1336, 1332, 1328, 1324, 1320, 1316, 1312, 1308, 1304, 1302, 1298, 1294, 1290, 1286, 1282, 1278, 1276, 1272, 1268, 1264, 1262, 1258, 1254, 1250, 1248, 1244, 1240, 1238, 1234, 1230, 1228, 1224, 1222, 1218, 1214, 1212, 1208, 1206, 1202, 1200, 1196, 1194, 1190, 1186, 1184, 1182, 1178, 1176, 1172, 1170, 1166, 1164, 1162, 1158, 1156, 1152, 1150, 1148, 1144, 1142, 1138, 1136, 1134, 1130, 1128, 1126, 1122, 1120, 1118, 1116, 1112, 1110, 1108, 1106, 1102, 1100, 1098, 1096, 1092, 1090, 1088, 1086, 1082, 1080, 1078, 1076, 1074, 1072, 1068, 1066, 1064, 1062, 1060, 1058, 1056, 1054, 1052, 1048, 1046, 1044, 1042, 1040, 1038, 1036, 1034, 1032, 1030, 1028, 1026, 1024, 1022, 1020, 1018, 1016, 1014, 1012, 1010, 1008, 1006, 1004, 1002, 1000, 998, 996, 994, 992, 990, 988, 986, 984, 982, 980, 978, 976, 974, 972, 972, 970, 968, 966, 964, 962, 960, 958, 956, 956, 954, 952, 950, 948, 946, 944, 944, 942, 940, 938, 936, 934, 934, 932, 930, 928, 926, 926, 924, 922, 920, 918, 918, 916, 914, 912, 912, 910, 908, 906, 904, 904, 902, 900, 898, 898, 896, 894, 892, 892, 890, 888, 888, 886, 884, 882, 882, 880, 878, 878, 876, 874, 874, 872, 870, 868, 868, 866, 864, 864, 862, 860, 860, 858, 856, 856, 854, 852, 852, 850, 848, 848, 846, 846, 844, 842, 842, 840, 838, 838, 836, 834, 834, 832, 832, 830, 828, 828, 826, 826, 824, 822, 822, 820, 820, 818, 816, 816, 814, 814, 812, 812, 810, 808, 808, 806, 806, 804, 802, 802, 800, 800, 798, 798, 796, 796, 794, 792, 792, 790, 790, 788, 788, 786, 786, 784, 784, 782, 782, 780, 780, 778, 778, 776, 774, 774, 772, 772, 770, 770, 768, 768, 766, 766, 764, 764, 762, 762, 760, 760, 758, 758, 758, 756, 756, 754, 754, 752, 752, 750, 750, 748, 748, 746, 746, 744, 744, 742, 742, 740, 740, 738, 738, 738, 736, 736, 734, 734, 732, 732, 730, 730, 730, 728, 728, 726, 726, 724, 724, 722, 722, 722, 720, 720, 718, 718, 718, 716, 716, 714, 714, 712, 712, 712, 710, 710, 708, 708, 708, 706, 706, 704, 704, 702, 702, 702, 700, 700, 698, 698, 698, 696, 696, 694, 694, 694, 692, 692, 692, 690, 690, 688, 688, 688, 686, 686, 684, 684, 684, 682, 682, 682, 680, 680, 680, 678, 678, 676, 676, 676, 674, 674, 674, 672, 672, 670, 670, 670, 668, 668, 668, 666, 666, 666, 664, 664, 664, 662, 662, 660, 660, 660, 658, 658, 658, 656, 656, 656, 654, 654, 654, 652, 652, 652, 650, 650, 650, 648, 648, 648, 646, 646, 646, 644, 644, 644, 642, 642, 642, 640, 640, 640, 640, 638, 638, 638, 636, 636, 636, 634, 634, 634, 632, 632, 632, 630, 630, 630, 630, 628, 628, 628, 626, 626, 626, 624, 624, 624, 624, 622, 622, 622, 620, 620, 620, 618, 618, 618, 618, 616, 616, 616, 614, 614, 614, 614, 612, 612, 612, 610, 610, 610, 610, 608, 608, 608, 606, 606, 606, 606, 604, 604, 604, 604, 602, 602, 602, 600, 600, 600, 600, 598, 598, 598, 598, 596, 596, 596, 594, 594, 594, 594, 592, 592, 592, 592, 590, 590, 590, 590, 588, 588, 588, 586, 586, 586, 586, 584, 584, 584, 584, 582, 582, 582, 582, 580, 580, 580, 580, 578, 578, 578, 578, 576, 576, 576, 576, 574, 574, 574, 574, 574, 572, 572, 572, 572, 570, 570, 570, 570, 568, 568, 568, 568, 566, 566, 566, 566, 564, 564, 564, 564, 564, 562, 562, 562, 562, 560, 560, 560, 560, 558, 558, 558, 558, 558, 556, 556, 556, 556, 554, 554, 554, 554, 554, 552, 552, 552, 552, 550, 550, 550, 550, 550, 548, 548, 548, 548, 546, 546, 546, 546, 546, 544, 544, 544, 544, 544, 542, 542, 542, 542, 540, 540, 540, 540, 540, 538, 538, 538, 538, 538, 536, 536, 536, 536, 536, 534, 534, 534, 534, 534, 532, 532, 532, 532, 532, 530, 530, 530, 530, 530, 528, 528, 528, 528, 528, 526, 526, 526, 526, 526, 524, 524, 524, 524, 524, 522, 522, 522, 522, 522, 520, 520, 520, 520, 520, 520, 518, 518, 518, 518, 518, 516, 516, 516, 516, 516, 514, 514, 514, 514, 514, 514, 512, 512, 512, 512, 512, 510, 510, 510, 510, 510, 510, 508, 508, 508, 508, 508, 506, 506, 506, 506, 506, 506, 504, 504, 504, 504, 504, 502, 502, 502, 502, 502, 502, 500, 500, 500, 500, 500, 500, 498, 498, 498, 498, 498, 498, 496, 496, 496, 496, 496, 496, 494, 494, 494, 494, 494, 494, 492, 492, 492, 492, 492, 492, 490, 490, 490, 490, 490, 490, 488, 488, 488, 488, 488, 488, 486, 486, 486, 486, 486, 486, 484, 484, 484, 484, 484, 484, 484, 0, 0, 0, 0, 0}; static uint32_t cs8400f_fast[]={8743, 8205, 7017, 6201, 4938, 4016, 3371, 2966, 2682, 2469, 2296, 2159, 2041, 1942, 1857, 1782, 1716, 1656, 1602, 1554, 1510, 1470, 1432, 1398, 1366, 1336, 1309, 1282, 1258, 1235, 1213, 1193, 1173, 1154, 1137, 1120, 1104, 1089, 1074, 1060, 1047, 1034, 1022, 1010, 998, 987, 976, 966, 956, 946, 937, 928, 919, 911, 902, 894, 887, 879, 872, 864, 858, 851, 844, 838, 832, 825, 819, 814, 808, 802, 797, 792, 786, 781, 776, 771, 766, 762, 757, 753, 748, 744, 740, 736, 731, 728, 724, 720, 716, 712, 709, 705, 701, 698, 695, 691, 688, 685, 682, 679, 675, 672, 669, 666, 664, 661, 658, 655, 652, 650, 647, 644, 642, 639, 637, 634, 632, 629, 627, 625, 622, 620, 618, 616, 613, 611, 609, 607, 605, 603, 601, 599, 597, 595, 593, 591, 589, 587, 585, 583, 581, 580, 578, 576, 574, 573, 571, 569, 567, 566, 564, 563, 561, 559, 558, 556, 555, 553, 552, 550, 549, 547, 546, 544, 543, 542, 540, 539, 537, 536, 535, 533, 532, 531, 529, 528, 527, 526, 524, 523, 522, 521, 519, 518, 517, 516, 515, 514, 512, 511, 510, 509, 508, 507, 506, 505, 504, 502, 501, 500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 490, 489, 488, 488, 487, 486, 485, 484, 483, 482, 481, 480, 479, 478, 477, 477, 476, 475, 474, 473, 472, 472, 471, 470, 469, 468, 467, 467, 466, 465, 464, 464, 463, 462, 461, 460, 460, 459, 458, 457, 457, 456, 455, 454, 454, 453, 452, 452, 451, 450, 449, 449, 448, 448, 447, 446, 446, 445, 444, 444, 443, 442, 442, 441, 440, 440, 439, 438, 438, 437, 437, 436, 435, 435, 434, 434, 433, 432, 432, 431, 431, 430, 429, 429, 428, 428, 427, 427, 426, 425, 425, 424, 424, 423, 423, 422, 422, 421, 421, 420, 420, 419, 419, 418, 417, 417, 416, 416, 416, 415, 414, 414, 414, 413, 412, 412, 412, 411, 411, 410, 410, 409, 409, 408, 408, 407, 407, 406, 406, 406, 405, 405, 404, 404, 403, 403, 402, 402, 402, 401, 401, 400, 400, 399, 399, 398, 398, 398, 397, 397, 396, 396, 396, 395, 395, 394, 394, 394, 393, 393, 392, 392, 392, 391, 391, 391, 390, 390, 389, 389, 389, 388, 388, 387, 387, 387, 386, 386, 385, 385, 385, 384, 384, 384, 383, 383, 383, 382, 382, 382, 381, 381, 381, 380, 380, 380, 379, 379, 379, 378, 378, 378, 377, 377, 377, 376, 376, 376, 375, 375, 375, 374, 374, 374, 373, 373, 373, 372, 372, 372, 371, 371, 371, 370, 370, 370, 370, 369, 369, 369, 368, 368, 368, 368, 367, 367, 367, 367, 366, 366, 366, 365, 365, 365, 365, 364, 364, 364, 363, 363, 363, 363, 362, 362, 362, 362, 361, 361, 361, 360, 360, 360, 360, 359, 359, 359, 358, 358, 358, 358, 357, 357, 357, 356, 356, 356, 356, 355, 355, 355, 355, 354, 354, 354, 354, 354, 353, 353, 353, 353, 352, 352, 352, 352, 352, 351, 351, 351, 351, 350, 350, 350, 350, 350, 349, 349, 349, 349, 348, 348, 348, 348, 348, 347, 347, 347, 347, 346, 346, 346, 346, 346, 345, 345, 345, 345, 344, 344, 344, 344, 344, 343, 343, 343, 343, 342, 342, 342, 342, 342, 341, 341, 341, 341, 340, 340, 340, 340, 340, 339, 339, 339, 339, 338, 338, 338, 338, 338, 337, 337, 337, 337, 337, 337, 336, 336, 336, 336, 336, 336, 335, 335, 335, 335, 335, 335, 334, 334, 334, 334, 334, 334, 333, 333, 333, 333, 333, 333, 332, 332, 332, 332, 332, 332, 331, 331, 331, 331, 331, 331, 330, 330, 330, 330, 330, 330, 329, 329, 329, 329, 329, 329, 328, 328, 328, 328, 328, 328, 327, 327, 327, 327, 327, 327, 326, 326, 326, 326, 326, 326, 325, 325, 325, 325, 325, 325, 324, 324, 324, 324, 324, 324, 323, 323, 323, 323, 323, 323, 322, 322, 322, 322, 322, 322, 321, 321, 321, 321, 321, 321, 320, 320, 320, 320, 320, 320, 319, 319, 319, 319, 319, 319, 318, 318, 318, 318, 318, 318, 317, 317, 317, 317, 317, 317, 316, 316, 316, 316, 316, 316, 315, 315, 315, 315, 315, 315, 314, 314, 314, 314, 314, 314, 313, 313, 313, 313, 313, 313, 312, 312, 312, 312, 312, 312, 311, 311, 311, 311, 311, 311, 310, 310, 310, 310, 310, 310, 309, 309, 309, 309, 309, 309, 308, 308, 308, 308, 308, 308, 307, 307, 307, 307, 307, 307, 306, 306, 306, 306, 306, 306, 305, 305, 305, 305, 305, 305, 304, 304, 304, 304, 304, 304, 303, 303, 303, 303, 303, 303, 302, 302, 302, 302, 302, 302, 302, 301, 301, 301, 301, 301, 301, 301, 301, 301, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 0, 0, 0, 0, 0 }; /** * database of motor profiles */ /* *INDENT-OFF* */ static Motor_Profile gl843_motors[]={ /* KV-SS080 */ {MOTOR_KVSS080, 8000, 1, kvss080}, /* G4010/G4050/CS4400F */ {MOTOR_G4050, 8016, 1, g4050_fast}, {MOTOR_G4050, 11640, 1, cs4400f_fast}, {MOTOR_G4050, 15624, 1, g4050_xpa}, {MOTOR_G4050, 42752, 2, g4050_max}, {MOTOR_G4050, 56064, 1, g4050_high}, /* CS8400F */ {MOTOR_CS8400F, 7200, 0, cs8400f_fast}, {0, 0, 0, NULL}, }; /* *INDENT-ON* */ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/plustek_pp.c0000664000175000017500000016742412775312261015167 00000000000000/** @file plustek_pp.c * @brief SANE backend for Plustek parallelport scanner * * Based on Kazuhiro Sasayama previous work on * plustek.[ch] file from the SANE package.
* Original code taken from sane-0.71
* Copyright (C) 1997 Hypercore Software Design, Ltd.
* Also based on the work done by Rick Bronson
* Copyright (C) 2000-2013 Gerhard Jaeger
* * History: * - 0.01 - initial version, imported from the kernel-module 0.42-11 * - 0.43 - bumped up version to reflect the former module code version * - 0.44 - bumped up version to reflect the recent changes * - minor cleanup *. *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /** @mainpage * @verbinclude Plustek-PARPORT.txt */ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_VERSION "0.44-1" #define BACKEND_NAME plustek_pp #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_thread.h" #include "../include/sane/sanei_pp.h" #define _BACKEND_ENABLED #define _USER_MODE #include "plustek-pp.h" /*********************** the debug levels ************************************/ #define _DBG_FATAL 0 #define _DBG_ERROR 1 #define _DBG_WARNING 3 #define _DBG_INFO 5 #define _DBG_PROC 7 #define _DBG_SANE_INIT 10 #define _DBG_INFO2 13 #define _DBG_DUMP 20 #define _DBG_READ 25 /*****************************************************************************/ /* * see plustek-share.h */ MODELSTR; #ifdef _BACKEND_ENABLED #ifndef NDEBUG # define DEBUG #endif /* I know this is in general no good idea, but it works */ # include "plustek-pp_io.c" # include "plustek-pp_dac.c" # include "plustek-pp_detect.c" # include "plustek-pp_genericio.c" # include "plustek-pp_image.c" # include "plustek-pp_map.c" # include "plustek-pp_misc.c" # include "plustek-pp_models.c" # include "plustek-pp_motor.c" # include "plustek-pp_p12.c" # include "plustek-pp_p12ccd.c" # include "plustek-pp_p48xx.c" # include "plustek-pp_p9636.c" # include "plustek-pp_procfs.c" # include "plustek-pp_scale.c" # include "plustek-pp_tpa.c" #define _DEFAULT_DEVICE "0x378" #else #define _DEFAULT_DEVICE "/dev/pt_drv" #endif #ifdef _BACKEND_ENABLED # include "plustek-pp_ptdrv.c" #endif #include "plustek-pp_wrapper.c" /************************** global vars **************************************/ static int num_devices; static Plustek_Device *first_dev; static Plustek_Scanner *first_handle; static const SANE_Device **devlist = 0; static unsigned long tsecs = 0; static ModeParam mode_params[] = { {0, 1, COLOR_BW}, {0, 1, COLOR_HALFTONE}, {0, 8, COLOR_256GRAY}, {1, 8, COLOR_TRUE24}, {1, 16, COLOR_TRUE32}, {1, 16, COLOR_TRUE36} }; static ModeParam mode_9800x_params[] = { {0, 1, COLOR_BW}, {0, 1, COLOR_HALFTONE}, {0, 8, COLOR_256GRAY}, {1, 8, COLOR_TRUE24}, {1, 16, COLOR_TRUE48} }; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; static const SANE_String_Const mode_9800x_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, SANE_I18N("Color36"), NULL }; static const SANE_String_Const ext_mode_list[] = { SANE_I18N("Normal"), SANE_I18N("Transparency"), SANE_I18N("Negative"), NULL }; static const SANE_String_Const halftone_list[] = { SANE_I18N("Dithermap 1"), SANE_I18N("Dithermap 2"), SANE_I18N("Randomize"), NULL }; static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 1 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; /* * lens info */ static LensInfo lens = {{0,0,0,0,},{0,0,0,0,},{0,0,0,0,},{0,0,0,0,},0,0}; /* authorization stuff */ static SANE_Auth_Callback auth = NULL; /****************************** the backend... *******************************/ #define _YN(x) (x?"yes":"no") /** * function to display the configuration options for the current device * @param cnf - pointer to the configuration structure whose content should be * displayed */ static void show_cnf( pCnfDef cnf ) { DBG( _DBG_SANE_INIT,"Device configuration:\n" ); DBG( _DBG_SANE_INIT,"device name : >%s<\n", cnf->devName ); DBG( _DBG_SANE_INIT,"direct I/O : %s\n", _YN(cnf->adj.direct_io )); DBG( _DBG_SANE_INIT,"warmup : %ds\n", cnf->adj.warmup ); DBG( _DBG_SANE_INIT,"lampOff : %d\n", cnf->adj.lampOff ); DBG( _DBG_SANE_INIT,"lampOffOnEnd : %s\n", _YN(cnf->adj.lampOffOnEnd )); DBG( _DBG_SANE_INIT,"model override: %d\n", cnf->adj.mov ); DBG( _DBG_SANE_INIT,"---------------------\n" ); } /** open the device specific driver and reset the internal timing stuff * @param dev - pointer to the device specific structure * @return the function returns the result of the open call, on success * of course the handle */ static int drvopen( Plustek_Device *dev ) { int handle; DBG( _DBG_INFO, "drvopen()\n" ); handle = dev->open((const char*)dev->name, (void *)dev ); tsecs = 0; return handle; } /** Calls the device specific stop and close functions. * @param dev - pointer to the device specific structure * @return The function always returns SANE_STATUS_GOOD */ static SANE_Status drvclose( Plustek_Device *dev ) { short int_cnt; if( dev->fd >= 0 ) { DBG( _DBG_INFO, "drvclose()\n" ); if( 0 != tsecs ) { DBG( _DBG_INFO, "TIME END 1: %lus\n", time(NULL)-tsecs); } /* * don't check the return values, simply do it and close the driver */ int_cnt = 0; dev->stopScan( dev, &int_cnt ); dev->close( dev ); } dev->fd = -1; return SANE_STATUS_GOOD; } /** according to the mode and source we return the corresponding mode list */ static pModeParam getModeList( Plustek_Scanner *scanner ) { pModeParam mp; if((_ASIC_IS_98003 == scanner->hw->caps.AsicID) || (_ASIC_IS_98001 == scanner->hw->caps.AsicID)) { mp = mode_9800x_params; } else { mp = mode_params; } /* * the transparency/negative mode supports only GRAY/COLOR/COLOR32/COLOR48 */ if( 0 != scanner->val[OPT_EXT_MODE].w ) { mp = &mp[_TPAModeSupportMin]; } return mp; } /** */ static SANE_Status close_pipe( Plustek_Scanner *scanner ) { if( scanner->r_pipe >= 0 ) { DBG( _DBG_PROC, "close r_pipe\n" ); close( scanner->r_pipe ); scanner->r_pipe = -1; } if( scanner->w_pipe >= 0 ) { DBG( _DBG_PROC, "close w_pipe\n" ); close( scanner->w_pipe ); scanner->w_pipe = -1; } return SANE_STATUS_EOF; } /** */ static void sig_chldhandler( int signo ) { DBG( _DBG_PROC, "Child is down (signal=%d)\n", signo ); } /** signal handler to kill the child process */ static void reader_process_sigterm_handler( int signo ) { DBG( _DBG_PROC, "reader_process: terminated by signal %d\n", signo ); _exit( SANE_STATUS_GOOD ); } static void sigalarm_handler( int signo ) { _VAR_NOT_USED( signo ); DBG( _DBG_PROC, "ALARM!!!\n" ); } /** executed as a child process * read the data from the driver and send them to the parent process */ static int reader_process( void *args ) { int line; unsigned long status; unsigned long data_length; struct SIGACTION act; sigset_t ignore_set; Plustek_Scanner *scanner = (Plustek_Scanner *)args; if( sanei_thread_is_forked()) { DBG( _DBG_PROC, "reader_process started (forked)\n" ); close( scanner->r_pipe ); scanner->r_pipe = -1; } else { DBG( _DBG_PROC, "reader_process started (as thread)\n" ); } sigfillset ( &ignore_set ); sigdelset ( &ignore_set, SIGTERM ); #if defined (__APPLE__) && defined (__MACH__) sigdelset ( &ignore_set, SIGUSR2 ); #endif sigprocmask( SIG_SETMASK, &ignore_set, 0 ); memset ( &act, 0, sizeof (act)); sigaction( SIGTERM, &act, 0 ); /* install the signal handler */ sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = reader_process_sigterm_handler; sigaction( SIGTERM, &act, 0 ); data_length = scanner->params.lines * scanner->params.bytes_per_line; DBG( _DBG_PROC, "reader_process:" "starting to READ data (%lu bytes)\n", data_length ); DBG( _DBG_PROC, "buf = 0x%08lx\n", (unsigned long)scanner->buf ); if( NULL == scanner->buf ) { DBG( _DBG_FATAL, "NULL Pointer !!!!\n" ); return SANE_STATUS_IO_ERROR; } /* here we read all data from the driver... */ if( scanner->hw->readImage ) { status = (unsigned long)scanner->hw->readImage( scanner->hw, scanner->buf, data_length); } else { unsigned char *buf = scanner->buf; status = scanner->hw->prepare( scanner->hw, buf ); if( 0 == status ) { for( line = 0; line < scanner->params.lines; line++ ) { status = scanner->hw->readLine( scanner->hw ); if((int)status < 0 ) { break; } write( scanner->w_pipe, buf, scanner->params.bytes_per_line ); buf += scanner->params.bytes_per_line; } } } /* on error, there's no need to clean up, as this is done by the parent */ if((int)status < 0 ) { DBG( _DBG_ERROR, "read failed, status = %i, errno %i\n", (int)status, errno ); if( -9009 == (int)status ) return SANE_STATUS_CANCELLED; if( errno == EBUSY ) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_IO_ERROR; } /* send to parent */ if( scanner->hw->readImage ) { DBG( _DBG_PROC, "sending %lu bytes to parent\n", status ); write( scanner->w_pipe, scanner->buf, status ); } DBG( _DBG_PROC, "reader_process: finished reading data\n" ); return SANE_STATUS_GOOD; } /** stop the current scan process */ static SANE_Status do_cancel( Plustek_Scanner *scanner, SANE_Bool closepipe ) { struct SIGACTION act; SANE_Pid res; short int_cnt; DBG( _DBG_PROC,"do_cancel\n" ); scanner->scanning = SANE_FALSE; if( sanei_thread_is_valid( scanner->reader_pid )) { DBG( _DBG_PROC, ">>>>>>>> killing reader_process <<<<<<<<\n" ); /* tell the driver to stop scanning */ if( -1 != scanner->hw->fd ) { int_cnt = 1; scanner->hw->stopScan( scanner->hw, &int_cnt ); } sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = sigalarm_handler; sigaction( SIGALRM, &act, 0 ); /* kill our child process and wait until done */ sanei_thread_kill( scanner->reader_pid ); /* give'em 10 seconds 'til done...*/ alarm(10); res = sanei_thread_waitpid( scanner->reader_pid, 0 ); alarm(0); if( res != scanner->reader_pid ) { DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n"); /* do it the hard way...*/ #ifdef USE_PTHREAD sanei_thread_kill( scanner->reader_pid ); #else sanei_thread_sendsig( scanner->reader_pid, SIGKILL ); #endif } scanner->reader_pid = -1; DBG( _DBG_PROC,"reader_process killed\n"); } if( SANE_TRUE == closepipe ) { close_pipe( scanner ); } drvclose( scanner->hw ); if( tsecs != 0 ) { DBG( _DBG_INFO, "TIME END 2: %lus\n", time(NULL)-tsecs); tsecs = 0; } return SANE_STATUS_CANCELLED; } /** because of some internal problems (inside the parport driver), we have to * limit the max resolution to optical resolution. This is done by this * function * @param dev - pointer to the device specific structure * @return The function always returns SANE_STATUS_GOOD */ static void limitResolution( Plustek_Device *dev ) { dev->dpi_range.min = _DEF_DPI; if( dev->dpi_range.min < _DEF_DPI ) dev->dpi_range.min = _DEF_DPI; /* * CHANGE: limit resolution to max. physical available one * Note: the resolution for the Asic 96001/3 models is limited to * the X-Resolution */ if((_ASIC_IS_96003 == dev->caps.AsicID) || (_ASIC_IS_96001 == dev->caps.AsicID)) { dev->dpi_range.max = lens.rDpiX.wPhyMax; } else { dev->dpi_range.max = lens.rDpiY.wPhyMax; } dev->dpi_range.quant = 0; dev->x_range.min = 0; dev->x_range.max = SANE_FIX(dev->max_x); dev->x_range.quant = 0; dev->y_range.min = 0; dev->y_range.max = SANE_FIX(dev->max_y); dev->y_range.quant = 0; } /** Currently we support only LM9831/2/3 chips and these use the same * sizes... * @param s - pointer to the scanner specific structure * @return The function always returns SANE_STATUS_GOOD */ static SANE_Status initGammaSettings( Plustek_Scanner *s ) { int i, j, val; double gamma; /* * this setting is common to the ASIC98001/3 and * LM9831/2/3 based devices * older parallelport devices use 256 entries */ s->gamma_length = 4096; s->gamma_range.min = 0; s->gamma_range.max = 255; s->gamma_range.quant = 0; if((_ASIC_IS_96003 == s->hw->caps.AsicID) || (_ASIC_IS_96001 == s->hw->caps.AsicID)) { s->gamma_length = 256; } DBG( _DBG_INFO, "Presetting Gamma tables (len=%u)\n", s->gamma_length ); DBG( _DBG_INFO, "----------------------------------\n" ); /* * preset the gamma maps */ for( i = 0; i < 4; i++ ) { switch( i ) { case 1: gamma = s->hw->adj.rgamma; break; case 2: gamma = s->hw->adj.ggamma; break; case 3: gamma = s->hw->adj.bgamma; break; default: gamma = s->hw->adj.graygamma; break; } for( j = 0; j < s->gamma_length; j++ ) { val = (s->gamma_range.max * pow((double) j / ((double)s->gamma_length - 1.0), 1.0 / gamma )); if( val > s->gamma_range.max ) val = s->gamma_range.max; s->gamma_table[i][j] = val; } } return SANE_STATUS_GOOD; } /** Check the gamma vectors we got back and limit if necessary * @param s - pointer to the scanner specific structure * @return nothing */ static void checkGammaSettings( Plustek_Scanner *s ) { int i, j; for( i = 0; i < 4 ; i++ ) { for( j = 0; j < s->gamma_length; j++ ) { if( s->gamma_table[i][j] > s->gamma_range.max ) { s->gamma_table[i][j] = s->gamma_range.max; } } } } /** initialize the options for the backend according to the device we have */ static SANE_Status init_options( Plustek_Scanner *s ) { int i; memset( s->opt, 0, sizeof(s->opt)); for( i = 0; i < NUM_OPTIONS; ++i ) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_MODE_GROUP].name = "scanmode-group"; s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = 32; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; if((_ASIC_IS_98001 == s->hw->caps.AsicID) || (_ASIC_IS_98003 == s->hw->caps.AsicID)) { s->opt[OPT_MODE].constraint.string_list = mode_9800x_list; } else { s->opt[OPT_MODE].constraint.string_list = mode_list; } s->val[OPT_MODE].w = 3; /* Color */ /* scan source */ s->opt[OPT_EXT_MODE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_EXT_MODE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_EXT_MODE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_EXT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_EXT_MODE].size = 32; s->opt[OPT_EXT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_EXT_MODE].constraint.string_list = ext_mode_list; s->val[OPT_EXT_MODE].w = 0; /* Normal */ /* halftone */ s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE_PATTERN; s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE; s->opt[OPT_HALFTONE].desc = SANE_DESC_HALFTONE_PATTERN; s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE].size = 32; s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_HALFTONE].constraint.string_list = halftone_list; s->val[OPT_HALFTONE].w = 0; /* Standard dithermap */ s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; s->val[OPT_BRIGHTNESS].w = 0; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; s->val[OPT_CONTRAST].w = 0; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = 0; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].name = "geometry-group"; s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TLX); /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TLY); /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_BRX); /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY); /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; initGammaSettings( s ); /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR].wa = &(s->gamma_table[0][0]); s->opt[OPT_GAMMA_VECTOR].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR].size = s->gamma_length * sizeof(SANE_Word); /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_R].wa = &(s->gamma_table[1][0]); s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_R].size = s->gamma_length * sizeof(SANE_Word); /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_G].wa = &(s->gamma_table[2][0]); s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_G].size = s->gamma_length * sizeof(SANE_Word); /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_B].wa = &(s->gamma_table[3][0]); s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(s->gamma_range); s->opt[OPT_GAMMA_VECTOR_B].size = s->gamma_length * sizeof(SANE_Word); /* GAMMA stuff is disabled per default */ s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; /* disable extended mode list for devices without TPA */ if( 0 == (s->hw->caps.dwFlag & SFLAG_TPA)) { s->opt[OPT_EXT_MODE].cap |= SANE_CAP_INACTIVE; } /* disable custom gamma, if not supported by the driver... */ if( 0 == (s->hw->caps.dwFlag & SFLAG_CUSTOM_GAMMA)) { s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; } #define _INT 0 #define _FLOAT 1 /** function to decode an value and give it back to the caller. * @param src - pointer to the source string to check * @param opt - string that keeps the option name to check src for * @param what - _FLOAT or _INT * @param result - pointer to the var that should receive our result * @param def - default value that result should be in case of any error * @return The function returns SANE_TRUE if the option has been found, * if not, it returns SANE_FALSE */ static SANE_Bool decodeVal( char *src, char *opt, int what, void *result, void *def ) { char *tmp, *tmp2; const char *name; /* skip the option string */ name = (const char*)&src[strlen("option")]; /* get the name of the option */ name = sanei_config_get_string( name, &tmp ); if( tmp ) { /* on success, compare wiht the given one */ if( 0 == strcmp( tmp, opt )) { DBG( _DBG_SANE_INIT, "Decoding option >%s<\n", opt ); if( _INT == what ) { /* assign the default value for this option... */ *((int*)result) = *((int*)def); if( *name ) { /* get the configuration value and decode it */ name = sanei_config_get_string( name, &tmp2 ); if( tmp2 ) { *((int*)result) = strtol( tmp2, 0, 0 ); free( tmp2 ); } } free( tmp ); return SANE_TRUE; } else if( _FLOAT == what ) { /* assign the default value for this option... */ *((double*)result) = *((double*)def); if( *name ) { /* get the configuration value and decode it */ name = sanei_config_get_string( name, &tmp2 ); if( tmp2 ) { *((double*)result) = strtod( tmp2, 0 ); free( tmp2 ); } } free( tmp ); return SANE_TRUE; } } free( tmp ); } return SANE_FALSE; } /** function to retrive the device name of a given string * @param src - string that keeps the option name to check src for * @param dest - pointer to the string, that should receive the detected * devicename * @return The function returns SANE_TRUE if the devicename has been found, * if not, it returns SANE_FALSE */ static SANE_Bool decodeDevName( char *src, char *dest ) { char *tmp; const char *name; if( 0 == strncmp( "device", src, 6 )) { name = (const char*)&src[strlen("device")]; name = sanei_config_skip_whitespace( name ); DBG( _DBG_SANE_INIT, "Decoding device name >%s<\n", name ); if( *name ) { name = sanei_config_get_string( name, &tmp ); if( tmp ) { strcpy( dest, tmp ); free( tmp ); return SANE_TRUE; } } } return SANE_FALSE; } /** attach a device to the backend */ static SANE_Status attach( const char *dev_name, pCnfDef cnf, Plustek_Device **devp ) { int cntr; int result; int handle; Plustek_Device *dev; DBG( _DBG_SANE_INIT, "attach (%s, %p, %p)\n", dev_name, (void *)cnf, (void *)devp); /* already attached ?*/ for( dev = first_dev; dev; dev = dev->next ) { if( 0 == strcmp( dev->sane.name, dev_name )) { if( devp ) *devp = dev; return SANE_STATUS_GOOD; } } /* allocate some memory for the device */ dev = malloc( sizeof (*dev)); if( NULL == dev ) return SANE_STATUS_NO_MEM; /* assign all the stuff we need fo this device... */ memset(dev, 0, sizeof (*dev)); dev->fd = -1; dev->name = strdup(dev_name); /* hold it double to avoid */ dev->sane.name = dev->name; /* compiler warnings */ dev->sane.vendor = "Plustek"; dev->initialized = -1; /* will be used as index too */ memcpy( &dev->adj, &cnf->adj, sizeof(AdjDef)); show_cnf( cnf ); dev->sane.type = SANE_I18N ("flatbed scanner"); dev->open = ppDev_open; dev->close = ppDev_close; dev->getCaps = ppDev_getCaps; dev->getLensInfo = ppDev_getLensInfo; dev->getCropInfo = ppDev_getCropInfo; dev->putImgInfo = ppDev_putImgInfo; dev->setScanEnv = ppDev_setScanEnv; dev->startScan = ppDev_startScan; dev->stopScan = ppDev_stopScan; dev->setMap = ppDev_setMap; dev->readImage = ppDev_readImage; dev->shutdown = NULL; dev->readLine = NULL; dev->prepare = NULL; /* * go ahead and open the scanner device */ handle = drvopen( dev ); if( handle < 0 ) { DBG( _DBG_ERROR,"open failed: %d\n", handle ); return SANE_STATUS_IO_ERROR; } /* okay, so assign the handle... */ dev->fd = handle; result = dev->getCaps( dev ); if( result < 0 ) { DBG( _DBG_ERROR, "dev->getCaps() failed(%d)\n", result); dev->close(dev); return SANE_STATUS_IO_ERROR; } result = dev->getLensInfo( dev, &lens ); if( result < 0 ) { DBG( _DBG_ERROR, "dev->getLensInfo() failed(%d)\n", result ); dev->close(dev); return SANE_STATUS_IO_ERROR; } /* did we fail on connection? */ if( _NO_BASE == dev->caps.wIOBase ) { DBG( _DBG_ERROR, "failed to find Plustek scanner\n" ); dev->close(dev); return SANE_STATUS_INVAL; } /* save the info we got from the driver */ DBG( _DBG_INFO, "Scanner information:\n" ); if( dev->caps.Model < MODEL_UNKNOWN ) { dev->sane.model = ModelStr[dev->caps.Model]; } else { dev->sane.model = ModelStr[0]; } DBG( _DBG_INFO, "Vendor : %s\n", dev->sane.vendor ); DBG( _DBG_INFO, "Model : %s\n", dev->sane.model ); DBG( _DBG_INFO, "Asic : 0x%02x\n", dev->caps.AsicID ); DBG( _DBG_INFO, "Flags : 0x%08lx\n", dev->caps.dwFlag ); dev->max_x = dev->caps.wMaxExtentX*MM_PER_INCH/_MEASURE_BASE; dev->max_y = dev->caps.wMaxExtentY*MM_PER_INCH/_MEASURE_BASE; dev->res_list = (SANE_Int *)calloc(((lens.rDpiX.wMax -_DEF_DPI)/25 + 1), sizeof (SANE_Int)); /* one more to avoid a buffer overflow */ if (NULL == dev->res_list) { DBG( _DBG_ERROR, "alloc fail, resolution problem\n" ); dev->close(dev); return SANE_STATUS_INVAL; } /* build up the resolution table */ dev->res_list_size = 0; for( cntr = _DEF_DPI; cntr <= lens.rDpiX.wMax; cntr += 25 ) { dev->res_list_size++; dev->res_list[dev->res_list_size - 1] = (SANE_Int)cntr; } limitResolution( dev ); dev->fd = handle; drvclose( dev ); DBG( _DBG_SANE_INIT, "attach: model = >%s<\n", dev->sane.model ); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } /** function to preset a configuration structure * @param cnf - pointer to the structure that should be initialized */ static void init_config_struct( pCnfDef cnf, SANE_Bool direct_io ) { memset( cnf, 0, sizeof(CnfDef)); cnf->adj.direct_io = direct_io; cnf->adj.warmup = -1; cnf->adj.lampOff = -1; cnf->adj.lampOffOnEnd = -1; cnf->adj.graygamma = 1.0; cnf->adj.rgamma = 1.0; cnf->adj.ggamma = 1.0; cnf->adj.bgamma = 1.0; } /** intialize the backend */ SANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize ) { char str[PATH_MAX] = _DEFAULT_DEVICE; CnfDef config; size_t len; FILE *fp; SANE_Status res; DBG_INIT(); sanei_thread_init(); res = sanei_pp_init(); if( SANE_STATUS_GOOD != res ) { DBG( _DBG_ERROR, "Could not initialize Parport library!\n" ); return res; } #if defined PACKAGE && defined VERSION DBG( _DBG_SANE_INIT, "PlustekPP backend V"BACKEND_VERSION", part of " PACKAGE " " VERSION "\n"); #else DBG( _DBG_INFO, "PlustekPP backend V"BACKEND_VERSION"\n" ); #endif /* do some presettings... */ auth = authorize; first_dev = NULL; first_handle = NULL; num_devices = 0; /* initialize the configuration structure */ #ifdef _BACKEND_ENABLED init_config_struct( &config, SANE_TRUE ); #else init_config_struct( &config, SANE_FALSE ); #endif if( version_code != NULL ) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open( PLUSTEK_CONFIG_FILE ); /* default to _DEFAULT_DEVICE instead of insisting on config file */ if( NULL == fp ) { return attach( _DEFAULT_DEVICE, &config, 0 ); } while( sanei_config_read( str, sizeof(str), fp)) { DBG( _DBG_SANE_INIT, ">%s<\n", str ); if( str[0] == '#') /* ignore line comments */ continue; len = strlen(str); if( 0 == len ) continue; /* ignore empty lines */ /* check for options */ if( 0 == strncmp(str, "option", 6)) { int ival; ival = -1; decodeVal( str, "warmup", _INT, &config.adj.warmup, &ival); decodeVal( str, "lampOff", _INT, &config.adj.lampOff, &ival); decodeVal( str, "lOffOnEnd", _INT, &config.adj.lampOffOnEnd,&ival); ival = 0; decodeVal( str, "mov", _INT, &config.adj.mov, &ival ); continue; /* check for sections: */ } else if( 0 == strncmp( str, "[direct]", 8)) { /* new section, try and attach previous device */ if( config.devName[0] != '\0' ) attach( config.devName, &config, 0 ); /* re-initialize the configuration structure */ init_config_struct( &config, SANE_TRUE ); continue; } else if( 0 == strncmp( str, "[kernel]", 8 )) { /* new section, try and attach previous device */ if( config.devName[0] != '\0' ) attach( config.devName, &config, 0 ); /* re-initialize the configuration structure */ init_config_struct( &config, SANE_FALSE ); continue; } else if( SANE_TRUE == decodeDevName( str, config.devName )) { continue; } /* ignore other stuff... */ DBG( _DBG_SANE_INIT, "ignoring >%s<\n", str ); } fclose (fp); /* try to attach the last device in the config file... */ if( config.devName[0] != '\0' ) attach( config.devName, &config, 0 ); return SANE_STATUS_GOOD; } /** cleanup the backend... */ void sane_exit( void ) { Plustek_Device *dev, *next; DBG( _DBG_SANE_INIT, "sane_exit\n" ); for( dev = first_dev; dev; ) { next = dev->next; /* call the shutdown function of each device... */ if( dev->shutdown ) dev->shutdown( dev ); /* * we're doin' this to avoid compiler warnings as dev->sane.name * is defined as const char* */ if( dev->sane.name ) free( dev->name ); if( dev->res_list ) free( dev->res_list ); free( dev ); dev = next; } if( devlist ) free( devlist ); /* call driver specific shutdown function... */ PtDrvShutdown(); devlist = NULL; auth = NULL; first_dev = NULL; first_handle = NULL; } /** return a list of all devices */ SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only ) { int i; Plustek_Device *dev; DBG(_DBG_SANE_INIT, "sane_get_devices (%p, %ld)\n", (void *)device_list, (long) local_only); /* already called, so cleanup */ if( devlist ) free( devlist ); devlist = malloc((num_devices + 1) * sizeof (devlist[0])); if ( NULL == devlist ) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } /** open the sane device */ SANE_Status sane_open( SANE_String_Const devicename, SANE_Handle* handle ) { SANE_Status status; Plustek_Device *dev; Plustek_Scanner *s; CnfDef config; DBG( _DBG_SANE_INIT, "sane_open - %s\n", devicename ); if( devicename[0] ) { for( dev = first_dev; dev; dev = dev->next ) { if( strcmp( dev->sane.name, devicename ) == 0 ) break; } if( !dev ) { memset( &config, 0, sizeof(CnfDef)); /* check if a valid parport-device is meant... */ status = attach( devicename, &config, &dev ); if( SANE_STATUS_GOOD != status ) return status; } } else { /* empty devicename -> use first device */ dev = first_dev; } if( !dev ) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if( NULL == s ) return SANE_STATUS_NO_MEM; memset(s, 0, sizeof (*s)); s->r_pipe = -1; s->w_pipe = -1; s->hw = dev; s->scanning = SANE_FALSE; init_options(s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return SANE_STATUS_GOOD; } /** */ void sane_close (SANE_Handle handle) { Plustek_Scanner *prev, *s; DBG( _DBG_SANE_INIT, "sane_close\n" ); /* remove handle from list of open handles: */ prev = 0; for( s = first_handle; s; s = s->next ) { if( s == handle ) break; prev = s; } if (!s) { DBG( _DBG_ERROR, "close: invalid handle %p\n", handle); return; } close_pipe( s ); if( NULL != s->buf ) free(s->buf); drvclose( s->hw ); if (prev) prev->next = s->next; else first_handle = s->next; free(s); } /** goes through a string list and returns the start-address of the string * that has been found, or NULL on error */ static const SANE_String_Const *search_string_list( const SANE_String_Const *list, SANE_String value ) { while( *list != NULL && strcmp(value, *list) != 0 ) ++list; if( *list == NULL ) return NULL; return list; } /** return or set the parameter values, also do some checks */ SANE_Status sane_control_option( SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { Plustek_Scanner *s = (Plustek_Scanner *)handle; SANE_Status status; const SANE_String_Const *optval; pModeParam mp; int scanmode; if ( s->scanning ) return SANE_STATUS_DEVICE_BUSY; if((option < 0) || (option >= NUM_OPTIONS)) return SANE_STATUS_INVAL; if( NULL != info ) *info = 0; switch( action ) { case SANE_ACTION_GET_VALUE: switch (option) { case OPT_PREVIEW: case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_CUSTOM_GAMMA: *(SANE_Word *)value = s->val[option].w; break; case OPT_CONTRAST: case OPT_BRIGHTNESS: *(SANE_Word *)value = (s->val[option].w << SANE_FIXED_SCALE_SHIFT); break; case OPT_MODE: case OPT_EXT_MODE: case OPT_HALFTONE: strcpy ((char *) value, s->opt[option].constraint.string_list[s->val[option].w]); break; /* word array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy( value, s->val[option].wa, s->opt[option].size ); break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: status = sanei_constrain_value( s->opt + option, value, info ); if( SANE_STATUS_GOOD != status ) return status; optval = NULL; if( SANE_CONSTRAINT_STRING_LIST == s->opt[option].constraint_type ) { optval = search_string_list( s->opt[option].constraint.string_list, (char *) value); if( NULL == optval ) return SANE_STATUS_INVAL; } switch (option) { case OPT_RESOLUTION: { int n; int min_d = s->hw->res_list[s->hw->res_list_size - 1]; int v = *(SANE_Word *)value; int best = v; for( n = 0; n < s->hw->res_list_size; n++ ) { int d = abs(v - s->hw->res_list[n]); if( d < min_d ) { min_d = d; best = s->hw->res_list[n]; } } s->val[option].w = (SANE_Word)best; if( v != best ) *(SANE_Word *)value = best; if( NULL != info ) { if( v != best ) *info |= SANE_INFO_INEXACT; *info |= SANE_INFO_RELOAD_PARAMS; } break; } case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *)value; if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_CUSTOM_GAMMA: s->val[option].w = *(SANE_Word *)value; if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; mp = getModeList( s ); scanmode = mp[s->val[OPT_MODE].w].scanmode; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; if( SANE_TRUE == s->val[option].w ) { if((scanmode == COLOR_256GRAY) || (scanmode == COLOR_GRAY16)) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { initGammaSettings( s ); if((scanmode == COLOR_256GRAY) || (scanmode == COLOR_GRAY16)) { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } } break; case OPT_CONTRAST: case OPT_BRIGHTNESS: s->val[option].w = ((*(SANE_Word *)value) >> SANE_FIXED_SCALE_SHIFT); break; case OPT_MODE: { int idx = (optval - mode_list); if((_ASIC_IS_98001 == s->hw->caps.AsicID) || (_ASIC_IS_98003 == s->hw->caps.AsicID)) { idx = optval - mode_9800x_list; } mp = getModeList( s ); if( mp[idx].scanmode != COLOR_HALFTONE ){ s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; } if( mp[idx].scanmode == COLOR_BW ) { s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; } s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; if( s->val[OPT_CUSTOM_GAMMA].w && !(s->opt[OPT_CUSTOM_GAMMA].cap & SANE_CAP_INACTIVE)) { if((mp[idx].scanmode == COLOR_256GRAY) || (mp[idx].scanmode == COLOR_GRAY16)) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } if( NULL != info ) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } /* fall through to OPT_HALFTONE */ case OPT_HALFTONE: s->val[option].w = optval - s->opt[option].constraint.string_list; break; case OPT_EXT_MODE: { s->val[option].w = optval - s->opt[option].constraint.string_list; /* * change the area and mode_list when changing the source */ if( s->val[option].w == 0 ) { s->hw->dpi_range.min = _DEF_DPI; s->hw->x_range.max = SANE_FIX(s->hw->max_x); s->hw->y_range.max = SANE_FIX(s->hw->max_y); s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY); s->val[OPT_MODE].w = 3; /* COLOR_TRUE24 */ if((_ASIC_IS_98001 == s->hw->caps.AsicID) || (_ASIC_IS_98003 == s->hw->caps.AsicID)) { s->opt[OPT_MODE].constraint.string_list = mode_9800x_list; } else { s->opt[OPT_MODE].constraint.string_list = mode_list; } } else { s->hw->dpi_range.min = _TPAMinDpi; if( s->val[option].w == 1 ) { s->hw->x_range.max = SANE_FIX(_TP_X); s->hw->y_range.max = SANE_FIX(_TP_Y); s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TP_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TP_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_TP_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_TP_BRY); } else { s->hw->x_range.max = SANE_FIX(_NEG_X); s->hw->y_range.max = SANE_FIX(_NEG_Y); s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_NEG_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_NEG_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_NEG_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_NEG_BRY); } if( s->hw->caps.dwFlag & SFLAG_TPA ) { s->opt[OPT_MODE].constraint.string_list = &mode_9800x_list[_TPAModeSupportMin]; } else { s->opt[OPT_MODE].constraint.string_list = &mode_list[_TPAModeSupportMin]; } s->val[OPT_MODE].w = 0; /* COLOR_24 is the default */ } s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; if( NULL != info ) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; } case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy( s->val[option].wa, value, s->opt[option].size ); checkGammaSettings(s); if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; default: return SANE_STATUS_INVAL; } break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /** according to the option number, return a pointer to a descriptor */ const SANE_Option_Descriptor * sane_get_option_descriptor( SANE_Handle handle, SANE_Int option ) { Plustek_Scanner *s = (Plustek_Scanner *)handle; if((option < 0) || (option >= NUM_OPTIONS)) return NULL; return &(s->opt[option]); } /** return the current parameter settings */ SANE_Status sane_get_parameters( SANE_Handle handle, SANE_Parameters *params ) { int ndpi; pModeParam mp; Plustek_Scanner *s = (Plustek_Scanner *)handle; /* if we're calling from within, calc best guess * do the same, if sane_get_parameters() is called * by a frontend before sane_start() is called */ if((NULL == params) || (s->scanning != SANE_TRUE)) { mp = getModeList( s ); memset( &s->params, 0, sizeof (SANE_Parameters)); ndpi = s->val[OPT_RESOLUTION].w; s->params.pixels_per_line = SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) / MM_PER_INCH * ndpi; s->params.lines = SANE_UNFIX( s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) / MM_PER_INCH * ndpi; /* pixels_per_line seems to be 8 * n. */ /* s->params.pixels_per_line = s->params.pixels_per_line & ~7; debug only */ s->params.last_frame = SANE_TRUE; s->params.depth = mp[s->val[OPT_MODE].w].depth; if( mp[s->val[OPT_MODE].w].color ) { s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line; } else { s->params.format = SANE_FRAME_GRAY; if (s->params.depth == 1) s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; else s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8; } /* if sane_get_parameters() was called before sane_start() */ /* pass new values to the caller */ if ((NULL != params) && (s->scanning != SANE_TRUE)) *params = s->params; } else *params = s->params; return SANE_STATUS_GOOD; } /** initiate the scan process */ SANE_Status sane_start( SANE_Handle handle ) { Plustek_Scanner *s = (Plustek_Scanner *) handle; pModeParam mp; int result; int ndpi; int left, top; int width, height; int scanmode; int fds[2]; StartScan start; CropInfo crop; ScanInfo sinfo; SANE_Status status; SANE_Word tmp; DBG( _DBG_SANE_INIT, "sane_start\n" ); if( s->scanning ) { return SANE_STATUS_DEVICE_BUSY; } status = sane_get_parameters (handle, NULL); if (status != SANE_STATUS_GOOD) { DBG( _DBG_ERROR, "sane_get_parameters failed\n" ); return status; } /* * open the driver and get some information about the scanner */ s->hw->fd = drvopen( s->hw ); if( s->hw->fd < 0 ) { DBG( _DBG_ERROR,"sane_start: open failed: %d\n", errno ); if( errno == EBUSY ) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_IO_ERROR; } result = s->hw->getCaps( s->hw ); if( result < 0 ) { DBG( _DBG_ERROR, "dev->getCaps() failed(%d)\n", result); s->hw->close( s->hw ); return SANE_STATUS_IO_ERROR; } result = s->hw->getLensInfo( s->hw, &lens ); if( result < 0 ) { DBG( _DBG_ERROR, "dev->getLensInfo() failed(%d)\n", result ); s->hw->close( s->hw ); return SANE_STATUS_IO_ERROR; } /* did we fail on connection? */ if ( s->hw->caps.wIOBase == _NO_BASE ) { DBG( _DBG_ERROR, "failed to find Plustek scanner\n" ); s->hw->close( s->hw ); return SANE_STATUS_INVAL; } /* All ready to go. Set image def and see what the scanner * says for crop info. */ ndpi = s->val[OPT_RESOLUTION].w; /* exchange the values as we can't deal with negative heights and so on...*/ tmp = s->val[OPT_TL_X].w; if( tmp > s->val[OPT_BR_X].w ) { DBG( _DBG_INFO, "exchanging BR-X - TL-X\n" ); s->val[OPT_TL_X].w = s->val[OPT_BR_X].w; s->val[OPT_BR_X].w = tmp; } tmp = s->val[OPT_TL_Y].w; if( tmp > s->val[OPT_BR_Y].w ) { DBG( _DBG_INFO, "exchanging BR-Y - TL-Y\n" ); s->val[OPT_TL_Y].w = s->val[OPT_BR_Y].w; s->val[OPT_BR_Y].w = tmp; } /* position and extent are always relative to 300 dpi */ left = (int)(SANE_UNFIX (s->val[OPT_TL_X].w)*(double)lens.rDpiX.wPhyMax/ (MM_PER_INCH*((double)lens.rDpiX.wPhyMax/300.0))); top = (int)(SANE_UNFIX (s->val[OPT_TL_Y].w)*(double)lens.rDpiY.wPhyMax/ (MM_PER_INCH*((double)lens.rDpiY.wPhyMax/300.0))); width = (int)(SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * (double)lens.rDpiX.wPhyMax / (MM_PER_INCH *((double)lens.rDpiX.wPhyMax/300.0))); height = (int)(SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) * (double)lens.rDpiY.wPhyMax / (MM_PER_INCH *((double)lens.rDpiY.wPhyMax/300.0))); /* * adjust mode list according to the model we use and the * source we have */ mp = getModeList( s ); scanmode = mp[s->val[OPT_MODE].w].scanmode; DBG( _DBG_INFO, "scanmode = %u\n", scanmode ); /* clear it out just in case */ memset (&sinfo, 0, sizeof(sinfo)); sinfo.ImgDef.xyDpi.x = ndpi; sinfo.ImgDef.xyDpi.y = ndpi; sinfo.ImgDef.crArea.x = left; /* offset from left edge to area you want to scan */ sinfo.ImgDef.crArea.y = top; /* offset from top edge to area you want to scan */ sinfo.ImgDef.crArea.cx = width; /* always relative to 300 dpi */ sinfo.ImgDef.crArea.cy = height; sinfo.ImgDef.wDataType = scanmode; /* * CHECK: what about the 10 bit mode? */ #if 0 if( COLOR_TRUE48 == scanmode ) sinfo.ImgDef.wBits = OUTPUT_12Bits; else if( COLOR_TRUE32 == scanmode ) sinfo.ImgDef.wBits = OUTPUT_10Bits; else sinfo.ImgDef.wBits = OUTPUT_8Bits; #endif sinfo.ImgDef.dwFlag = SCANDEF_QualityScan; switch( s->val[OPT_EXT_MODE].w ) { case 1: sinfo.ImgDef.dwFlag |= SCANDEF_Transparency; break; case 2: sinfo.ImgDef.dwFlag |= SCANDEF_Negative; break; default: break; } /* only for parallel-port devices */ if( s->hw->putImgInfo ) { result = s->hw->putImgInfo( s->hw, &sinfo.ImgDef ); if( result < 0 ) { DBG( _DBG_ERROR, "dev->putImgInfo failed(%d)\n", result ); s->hw->close( s->hw ); return SANE_STATUS_IO_ERROR; } } else { memcpy( &(crop.ImgDef), &sinfo.ImgDef, sizeof(ImgDef)); } result = s->hw->getCropInfo( s->hw, &crop ); if( result < 0 ) { DBG( _DBG_ERROR, "dev->getCropInfo() failed(%d)\n", result ); s->hw->close( s->hw ); return SANE_STATUS_IO_ERROR; } /* DataInf.dwAppPixelsPerLine = crop.dwPixelsPerLine; */ s->params.pixels_per_line = crop.dwPixelsPerLine; s->params.bytes_per_line = crop.dwBytesPerLine; s->params.lines = crop.dwLinesPerArea; /* build a SCANINFO block and get ready to scan it */ sinfo.ImgDef.dwFlag |= (SCANDEF_BuildBwMap | SCANDEF_QualityScan); /* set adjustments for brightness and contrast */ sinfo.siBrightness = s->val[OPT_BRIGHTNESS].w; sinfo.siContrast = s->val[OPT_CONTRAST].w; sinfo.wDither = s->val[OPT_HALFTONE].w; DBG( _DBG_SANE_INIT, "bright %i contrast %i\n", sinfo.siBrightness, sinfo.siContrast); result = s->hw->setScanEnv( s->hw, &sinfo ); if( result < 0 ) { DBG( _DBG_ERROR, "dev->setEnv() failed(%d)\n", result ); s->hw->close( s->hw ); return SANE_STATUS_IO_ERROR; } /* download gamma correction tables... */ if( scanmode <= COLOR_256GRAY || scanmode == COLOR_GRAY16 ) { s->hw->setMap( s->hw, s->gamma_table[0], s->gamma_length, _MAP_MASTER); } else { s->hw->setMap( s->hw, s->gamma_table[1], s->gamma_length, _MAP_RED ); s->hw->setMap( s->hw, s->gamma_table[2], s->gamma_length, _MAP_GREEN ); s->hw->setMap( s->hw, s->gamma_table[3], s->gamma_length, _MAP_BLUE ); } /* work-around for USB... */ start.dwLinesPerScan = s->params.lines; result = s->hw->startScan( s->hw, &start ); if( result < 0 ) { DBG( _DBG_ERROR, "dev->startScan() failed(%d)\n", result ); s->hw->close( s->hw ); return SANE_STATUS_IO_ERROR; } DBG( _DBG_SANE_INIT, "dwflag = 0x%lx dwBytesPerLine = %ld, " "dwLinesPerScan = %ld\n", start.dwFlag, start.dwBytesPerLine, start.dwLinesPerScan); s->buf = realloc( s->buf, (s->params.lines) * s->params.bytes_per_line ); if( NULL == s->buf ) { DBG( _DBG_ERROR, "realloc failed\n" ); s->hw->close( s->hw ); return SANE_STATUS_NO_MEM; } s->scanning = SANE_TRUE; tsecs = (unsigned long)time(NULL); DBG( _DBG_INFO, "TIME START\n" ); /* * everything prepared, so start the child process and a pipe to communicate * pipe --> fds[0]=read-fd, fds[1]=write-fd */ if( pipe(fds) < 0 ) { DBG( _DBG_ERROR, "ERROR: could not create pipe\n" ); s->scanning = SANE_FALSE; s->hw->close( s->hw ); return SANE_STATUS_IO_ERROR; } /* create reader routine as new process */ s->bytes_read = 0; s->r_pipe = fds[0]; s->w_pipe = fds[1]; s->reader_pid = sanei_thread_begin( reader_process, s ); if(!sanei_thread_is_valid( s->reader_pid )) { DBG( _DBG_ERROR, "ERROR: could not create child process\n" ); s->scanning = SANE_FALSE; s->hw->close( s->hw ); return SANE_STATUS_IO_ERROR; } /* reader_pid = 0 ===> child process */ #if 0 if( 0 == s->reader_pid ) { sigset_t ignore_set; struct SIGACTION act; DBG( _DBG_SANE_INIT, "reader process...\n" ); close(fds[0]); sigfillset ( &ignore_set ); sigdelset ( &ignore_set, SIGTERM ); sigprocmask( SIG_SETMASK, &ignore_set, 0 ); memset ( &act, 0, sizeof (act)); sigaction( SIGTERM, &act, 0 ); status = reader_process( s, fds[1] ); DBG( _DBG_SANE_INIT, "reader process done, status = %i\n", status ); /* don't use exit() since that would run the atexit() handlers */ _exit( status ); } #endif signal( SIGCHLD, sig_chldhandler ); if( sanei_thread_is_forked()) { close( s->w_pipe ); s->w_pipe = -1; } DBG( _DBG_SANE_INIT, "sane_start done\n" ); return SANE_STATUS_GOOD; } /** function to read the data from our child process */ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length ) { Plustek_Scanner *s = (Plustek_Scanner*)handle; ssize_t nread; *length = 0; /* here we read all data from the driver... */ nread = read( s->r_pipe, data, max_length ); DBG( _DBG_READ, "sane_read - read %ld bytes\n", (long)nread ); if (!(s->scanning)) { return do_cancel( s, SANE_TRUE ); } if( nread < 0 ) { if( EAGAIN == errno ) { /* if we had already red the picture, so it's okay and stop */ if( s->bytes_read == (unsigned long)(s->params.lines * s->params.bytes_per_line)) { sanei_thread_waitpid( s->reader_pid, 0 ); s->reader_pid = -1; drvclose( s->hw ); return close_pipe(s); } /* else force the frontend to try again*/ return SANE_STATUS_GOOD; } else { DBG( _DBG_ERROR, "ERROR: errno=%d\n", errno ); do_cancel( s, SANE_TRUE ); return SANE_STATUS_IO_ERROR; } } *length = nread; s->bytes_read += nread; /* nothing red means that we're finished OR we had a problem...*/ if( 0 == nread ) { drvclose( s->hw ); s->exit_code = sanei_thread_get_status( s->reader_pid ); if( SANE_STATUS_GOOD != s->exit_code ) { close_pipe(s); return s->exit_code; } s->reader_pid = -1; return close_pipe(s); } return SANE_STATUS_GOOD; } /** cancel the scanning process */ void sane_cancel (SANE_Handle handle) { Plustek_Scanner *s = (Plustek_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_cancel\n" ); if( s->scanning ) do_cancel( s, SANE_FALSE ); } /** set the pipe to blocking/non blocking mode */ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Plustek_Scanner *s = (Plustek_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_set_io_mode: non_blocking=%d\n",non_blocking ); if ( !s->scanning ) { DBG( _DBG_ERROR, "ERROR: not scanning !\n" ); return SANE_STATUS_INVAL; } if( -1 == s->r_pipe ) { DBG( _DBG_ERROR, "ERROR: not supported !\n" ); return SANE_STATUS_UNSUPPORTED; } if( fcntl (s->r_pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { DBG( _DBG_ERROR, "ERROR: can´t set to non-blocking mode !\n" ); return SANE_STATUS_IO_ERROR; } DBG( _DBG_SANE_INIT, "sane_set_io_mode done\n" ); return SANE_STATUS_GOOD; } /** return the descriptor if available */ SANE_Status sane_get_select_fd( SANE_Handle handle, SANE_Int * fd ) { Plustek_Scanner *s = (Plustek_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_get_select_fd\n" ); if( !s->scanning ) { DBG( _DBG_ERROR, "ERROR: not scanning !\n" ); return SANE_STATUS_INVAL; } *fd = s->r_pipe; DBG( _DBG_SANE_INIT, "sane_get_select_fd done\n" ); return SANE_STATUS_GOOD; } /* END PLUSTEK_PP.C .........................................................*/ sane-backends-1.0.27/backend/plustek-usbmap.c0000664000175000017500000001434612112021330015722 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbmap.c * @brief Creating and manipulating lookup tables. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2007 Gerhard Jaeger * * History: * - 0.40 - starting version of the USB support * - 0.41 - fixed brightness problem for lineart mode * - 0.42 - removed preset of linear gamma tables * - 0.43 - no changes * - 0.44 - map inversion for negatatives now only upon user request * - 0.45 - no changes * - 0.46 - no changes * - 0.47 - cleanup work * - 0.48 - added support for binary from color scans * - 0.49 - changed usb_MapDownload * - 0.50 - cleanup * - 0.51 - no changes * - 0.52 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #define _MAP_SIZE 4096 static SANE_Byte a_bMap[_MAP_SIZE * 3]; /** adjust acording to brightness and contrast */ static void usb_MapAdjust( Plustek_Device *dev ) { int i, tabLen; double b, c, tmp; tabLen = _MAP_SIZE; /* adjust brightness (b) and contrast (c) using the function: * * s(x,y) = (s(x,y) + b) * c * b = [-127, 127] * c = [0,2] */ b = ((double)dev->scanning.sParam.brightness * 192.0)/100.0; c = ((double)dev->scanning.sParam.contrast + 100.0)/100.0; DBG( _DBG_INFO, "* brightness = %i -> %i\n", dev->scanning.sParam.brightness, (u_char)b); DBG( _DBG_INFO, "* contrast = %i -> %.3f\n", dev->scanning.sParam.contrast, c); if( dev->scanning.sParam.brightness == 0 && dev->scanning.sParam.contrast ) return; for( i = 0; i < tabLen; i++ ) { tmp = ((double)(a_bMap[i] + b)) * c; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; a_bMap[i] = (u_char)tmp; tmp = ((double)(a_bMap[tabLen+i] + b)) * c; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; a_bMap[tabLen+i] = (u_char)tmp; tmp = ((double)(a_bMap[tabLen*2+i] + b)) * c; if( tmp < 0 ) tmp = 0; if( tmp > 255 ) tmp = 255; a_bMap[tabLen*2+i] = (u_char)tmp; } } /** */ static SANE_Bool usb_MapDownload( Plustek_Device *dev ) { ScanDef *scanning = &dev->scanning; DCapsDef *sc = &dev->usbDev.Caps; int color; int i, threshold; SANE_Byte value; SANE_Bool fInverse = 0; DBG( _DBG_INFO, "usb_MapDownload()\n" ); /* the maps are have been already set */ /* do the brightness and contrast adjustment ... */ if( scanning->sParam.bDataType != SCANDATATYPE_BW ) usb_MapAdjust( dev ); if( !usbio_WriteReg( dev->fd, 7, 0)) return SANE_FALSE; /* we download all the time all three color maps, as we run * into trouble elsewhere on CanoScan models using gray mode */ for( color = 0; color < 3; color++) { /* select color */ value = (color << 2)+2; /* set gamma color selector */ usbio_WriteReg( dev->fd, 0x03, value ); usbio_WriteReg( dev->fd, 0x04, 0 ); usbio_WriteReg( dev->fd, 0x05, 0 ); /* write the gamma table entry to merlin */ if((scanning->sParam.bDataType == SCANDATATYPE_BW) || (scanning->fGrayFromColor > 7 )) { threshold = (int)((double)scanning->sParam.brightness * (_MAP_SIZE/200.0)) + (_MAP_SIZE/2); threshold = _MAP_SIZE - threshold; if(threshold < 0) threshold = 0; if(threshold > (int)_MAP_SIZE) threshold = _MAP_SIZE; DBG(_DBG_INFO, "* Threshold is at %u brightness=%i\n", threshold, scanning->sParam.brightness ); for(i = 0; i < threshold; i++) a_bMap[color*_MAP_SIZE + i] = 0; for(i = threshold; i < _MAP_SIZE; i++) a_bMap[color*_MAP_SIZE + i] = 255; fInverse = 1; } else { fInverse = 0; } if( /*scanning->dwFlag & SCANFLAG_Pseudo48 && */ (scanning->sParam.bSource == SOURCE_Negative) && (sc->workaroundFlag &_WAF_INV_NEGATIVE_MAP)) { fInverse ^= 1; } if( fInverse ) { u_char map[_MAP_SIZE]; u_char *pMap = a_bMap+color*_MAP_SIZE; DBG( _DBG_INFO, "* Inverting Map\n" ); for( i = 0; i < _MAP_SIZE; i++, pMap++ ) map[i] = ~*pMap; sanei_lm983x_write( dev->fd, 0x06, map, _MAP_SIZE, SANE_FALSE ); } else { DBG( _DBG_INFO, "* downloading map %u...\n", color ); sanei_lm983x_write( dev->fd, 0x06, a_bMap+color*_MAP_SIZE, _MAP_SIZE, SANE_FALSE ); } } /* for each color */ DBG( _DBG_INFO, "usb_MapDownload() done.\n" ); return SANE_TRUE; } /* END PLUSTEK-USBMAP.C .....................................................*/ sane-backends-1.0.27/backend/hp5590_cmds.h0000664000175000017500000001372612617742237014746 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Ilia Sotnikov HP ScanJet 4570c support by Markham Thomas This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 Scanners */ #ifndef HP5590_H #define HP5590_H #include "hp5590_low.h" #define TMA_MAX_X_INCHES 1.69 #define TMA_MAX_Y_INCHES 6 #define ADF_MAX_Y_INCHES 14 enum hp_scanner_types { SCANNER_NONE = 0, SCANNER_HP4570, SCANNER_HP5550, SCANNER_HP5590, SCANNER_HP7650 }; enum scan_sources { SOURCE_NONE = 1, SOURCE_FLATBED, SOURCE_ADF, SOURCE_ADF_DUPLEX, SOURCE_TMA_NEGATIVES, SOURCE_TMA_SLIDES }; enum scan_modes { MODE_NORMAL = 1, MODE_PREVIEW }; enum color_depths { DEPTH_BW = 1, DEPTH_GRAY, DEPTH_COLOR_24, DEPTH_COLOR_48 }; enum button_status { BUTTON_NONE = 1, BUTTON_POWER, BUTTON_SCAN, BUTTON_COLLECT, BUTTON_FILE, BUTTON_EMAIL, BUTTON_COPY, BUTTON_UP, BUTTON_DOWN, BUTTON_MODE, BUTTON_CANCEL }; enum hp5590_lamp_state { LAMP_STATE_TURNOFF = 1, LAMP_STATE_TURNON, LAMP_STATE_SET_TURNOFF_TIME, LAMP_STATE_SET_TURNOFF_TIME_LONG }; struct hp5590_model { enum hp_scanner_types scanner_type; unsigned int usb_vendor_id; unsigned int usb_product_id; const char *vendor_id; const char *model; const char *kind; enum proto_flags proto_flags; }; #define FEATURE_NONE 0 #define FEATURE_ADF 1 << 0 #define FEATURE_TMA 1 << 1 #define FEATURE_LCD 1 << 2 struct scanner_info { const char *model; const char *kind; unsigned int features; const char *fw_version; unsigned int max_dpi_x; unsigned int max_dpi_y; unsigned int max_pixels_x; unsigned int max_pixels_y; float max_size_x; float max_size_y; unsigned int max_motor_param; unsigned int normal_motor_param; }; static SANE_Status hp5590_model_def (enum hp_scanner_types scanner_type, const struct hp5590_model ** model); static SANE_Status hp5590_vendor_product_id (enum hp_scanner_types scanner_type, SANE_Word * vendor_id, SANE_Word * product_id); static SANE_Status hp5590_init_scanner (SANE_Int dn, enum proto_flags proto_flags, struct scanner_info **info, enum hp_scanner_types scanner_type); static SANE_Status hp5590_power_status (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_read_max_scan_count (SANE_Int dn, enum proto_flags proto_flags, unsigned int *max_count); static SANE_Status hp5590_select_source_and_wakeup (SANE_Int dn, enum proto_flags proto_flags, enum scan_sources source, SANE_Bool extend_lamp_timeout); static SANE_Status hp5590_stop_scan (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_read_scan_count (SANE_Int dn, enum proto_flags proto_flags, unsigned int *count); static SANE_Status hp5590_set_scan_params (SANE_Int dn, enum proto_flags proto_flags, struct scanner_info *scanner_info, unsigned int top_x, unsigned int top_y, unsigned int width, unsigned int height, unsigned int dpi, enum color_depths color_depth, enum scan_modes scan_mode, enum scan_sources scan_source); static SANE_Status hp5590_send_forward_calibration_maps (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_send_reverse_calibration_map (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_inc_scan_count (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_start_scan (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_read (SANE_Int dn, enum proto_flags proto_flags, unsigned char *bytes, unsigned int size, void *state); static SANE_Status hp5590_read_buttons (SANE_Int dn, enum proto_flags proto_flags, enum button_status *status); static SANE_Status hp5590_read_part_number (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_calc_pixel_bits (unsigned int dpi, enum color_depths color_depth, unsigned int *pixel_bits); static SANE_Status hp5590_is_data_available (SANE_Int dn, enum proto_flags proto_flags); static SANE_Status hp5590_reset_scan_head (SANE_Int dn, enum proto_flags proto_flags); #endif /* HP5590_H */ /* vim: sw=2 ts=8 */ sane-backends-1.0.27/backend/mustek_pp_ccd300.c0000664000175000017500000012626412775312261016041 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2003 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements the hardware driver scanners using a 300dpi CCD */ #include "mustek_pp_ccd300.h" #define MUSTEK_PP_CCD300 4 static void config_ccd_101x (Mustek_pp_Handle * dev); static void config_ccd (Mustek_pp_Handle * dev); static void lamp (Mustek_pp_Handle * dev, int lamp_on); #define CCD300_ASIC1013 0xa8 #define CCD300_ASIC1015 0xa5 #define CCD300_CHANNEL_RED 0 #define CCD300_CHANNEL_GREEN 1 #define CCD300_CHANNEL_BLUE 2 #define CCD300_CHANNEL_GRAY 1 #define CCD300_MAXHSIZE 2600 #define CCD300_MAXVSIZE 3500 /* * Here starts the driver code for the different chipsets * * The 1013 & 1015 chipsets share large portions of the code. This * shared functions end with _101x. */ static const u_char chan_codes_1013[] = { 0x82, 0x42, 0xC2 }; static const u_char chan_codes_1015[] = { 0x80, 0x40, 0xC0 }; static const u_char fullstep[] = { 0x09, 0x0C, 0x06, 0x03 }; static const u_char halfstep[] = { 0x02, 0x03, 0x01, 0x09, 0x08, 0x0C, 0x04, 0x06 }; static const u_char voltages[4][3] = { {0x5C, 0x5A, 0x63}, {0xE6, 0xB4, 0xBE}, {0xB4, 0xB4, 0xB4}, {0x64, 0x50, 0x64} }; /* Forward declarations of 1013/1015 functions */ static void set_ccd_channel_1013 (Mustek_pp_Handle * dev, int channel); static void motor_backward_1013 (Mustek_pp_Handle * dev); static void return_home_1013 (Mustek_pp_Handle * dev); static void motor_forward_1013 (Mustek_pp_Handle * dev); static void config_ccd_1013 (Mustek_pp_Handle * dev); static void set_ccd_channel_1015 (Mustek_pp_Handle * dev, int channel); /* static void motor_backward_1015 (Mustek_pp_Handle * dev); */ static void return_home_1015 (Mustek_pp_Handle * dev, SANE_Bool nowait); static void motor_forward_1015 (Mustek_pp_Handle * dev); static void config_ccd_1015 (Mustek_pp_Handle * dev); /* These functions are common to all 1013/1015 chipsets */ static void set_led (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; sanei_pa4s2_writebyte (dev->fd, 6, (priv->motor_step % 5 == 0 ? 0x03 : 0x13)); } static void set_sti (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; sanei_pa4s2_writebyte (dev->fd, 3, 0); priv->bank_count++; priv->bank_count &= 7; } static void get_bank_count (Mustek_pp_Handle * dev) { u_char val; mustek_pp_ccd300_priv *priv = dev->priv; sanei_pa4s2_readbegin (dev->fd, 3); sanei_pa4s2_readbyte (dev->fd, &val); sanei_pa4s2_readend (dev->fd); priv->bank_count = (val & 0x07); } static void reset_bank_count (Mustek_pp_Handle * dev) { sanei_pa4s2_writebyte (dev->fd, 6, 7); } static void wait_bank_change (Mustek_pp_Handle * dev, int bankcount, int niceload) { struct timeval start, end; unsigned long diff; mustek_pp_ccd300_priv *priv = dev->priv; int first_time = 1; gettimeofday (&start, NULL); do { if ((niceload == 0) && (first_time == 0)) { usleep (1); /* could be as well sched_yield */ first_time = 0; } get_bank_count (dev); gettimeofday (&end, NULL); diff = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); } while ((priv->bank_count != bankcount) && (diff < priv->wait_bank)); } static void set_dpi_value (Mustek_pp_Handle * dev) { u_char val = 0; mustek_pp_ccd300_priv *priv = dev->priv; sanei_pa4s2_writebyte (dev->fd, 6, 0x80); switch (priv->hwres) { case 100: val = 0x00; break; case 200: val = 0x10; break; case 300: val = 0x20; break; } if (priv->ccd_type == 1) val |= 0x01; sanei_pa4s2_writebyte (dev->fd, 5, val); sanei_pa4s2_writebyte (dev->fd, 6, 0x00); DBG (5, "set_dpi_value: value 0x%02x\n", val); } static void set_line_adjust (Mustek_pp_Handle * dev) { int adjustline; mustek_pp_ccd300_priv *priv = dev->priv; adjustline = (dev->bottomX - dev->topX) * priv->hwres / 300; priv->adjustskip = priv->adjustskip * priv->hwres / 300; DBG (5, "set_line_adjust: ppl %u (%u), adjust %u, skip %u\n", dev->params.pixels_per_line, (dev->bottomX - dev->topX), adjustline, priv->adjustskip); sanei_pa4s2_writebyte (dev->fd, 6, 0x11); sanei_pa4s2_writebyte (dev->fd, 5, (adjustline + priv->adjustskip) >> 8); sanei_pa4s2_writebyte (dev->fd, 6, 0x21); sanei_pa4s2_writebyte (dev->fd, 5, (adjustline + priv->adjustskip) & 0xFF); sanei_pa4s2_writebyte (dev->fd, 6, 0x01); } static void set_lamp (Mustek_pp_Handle * dev, int lamp_on) { int ctr; mustek_pp_ccd300_priv *priv = dev->priv; sanei_pa4s2_writebyte (dev->fd, 6, 0xC3); for (ctr = 0; ctr < 3; ctr++) { sanei_pa4s2_writebyte (dev->fd, 6, (lamp_on ? 0x47 : 0x57)); sanei_pa4s2_writebyte (dev->fd, 6, 0x77); } priv->motor_step = lamp_on; set_led (dev); } static void send_voltages (Mustek_pp_Handle * dev) { int voltage, sel = 8, ctr; mustek_pp_ccd300_priv *priv = dev->priv; switch (priv->ccd_type) { case 0: voltage = 0; break; case 1: voltage = 1; break; default: voltage = 2; break; } for (ctr = 0; ctr < 3; ctr++) { sel <<= 1; sanei_pa4s2_writebyte (dev->fd, 6, sel); sanei_pa4s2_writebyte (dev->fd, 5, voltages[voltage][ctr]); } sanei_pa4s2_writebyte (dev->fd, 6, 0x00); } static int compar (const void *a, const void *b) { return (signed int) (*(const SANE_Byte *) a) - (signed int) (*(const SANE_Byte *) b); } static void set_ccd_channel_101x (Mustek_pp_Handle * dev, int channel) { mustek_pp_ccd300_priv *priv = dev->priv; switch (priv->asic) { case CCD300_ASIC1013: set_ccd_channel_1013 (dev, channel); break; case CCD300_ASIC1015: set_ccd_channel_1015 (dev, channel); break; } } static void motor_forward_101x (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; switch (priv->asic) { case CCD300_ASIC1013: motor_forward_1013 (dev); break; case CCD300_ASIC1015: motor_forward_1015 (dev); break; } } static void motor_backward_101x (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; switch (priv->asic) { case CCD300_ASIC1013: motor_backward_1013 (dev); break; case CCD300_ASIC1015: /* motor_backward_1015 (dev); */ break; } } static void move_motor_101x (Mustek_pp_Handle * dev, int forward) { mustek_pp_ccd300_priv *priv = dev->priv; if (forward == SANE_TRUE) motor_forward_101x (dev); else motor_backward_101x (dev); wait_bank_change (dev, priv->bank_count, 1); reset_bank_count (dev); } static void config_ccd_101x (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; switch (priv->asic) { case CCD300_ASIC1013: config_ccd_1013 (dev); break; case CCD300_ASIC1015: config_ccd_1015 (dev); break; } } static void read_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf, SANE_Int pixel, SANE_Int RefBlack, SANE_Byte * calib, SANE_Int * gamma) { SANE_Byte *cal = calib; u_char color; mustek_pp_ccd300_priv *priv = dev->priv; int ctr, skips = priv->adjustskip + 1, cval; if (pixel <= 0) return; sanei_pa4s2_readbegin (dev->fd, 1); if (priv->hwres == dev->res) { while (skips--) sanei_pa4s2_readbyte (dev->fd, &color); for (ctr = 0; ctr < pixel; ctr++) { sanei_pa4s2_readbyte (dev->fd, &color); cval = color; if (cval < RefBlack) cval = 0; else cval -= RefBlack; if (cal) { if (cval >= cal[ctr]) cval = 0xFF; else { cval <<= 8; cval /= (int) cal[ctr]; } } if (gamma) cval = gamma[cval]; buf[ctr] = cval; } } else { int pos = 0, bpos = 0; while (skips--) sanei_pa4s2_readbyte (dev->fd, &color); ctr = 0; do { sanei_pa4s2_readbyte (dev->fd, &color); cval = color; if (ctr < (pos >> SANE_FIXED_SCALE_SHIFT)) { ctr++; continue; } ctr++; pos += priv->res_step; if (cval < RefBlack) cval = 0; else cval -= RefBlack; if (cal) { if (cval >= cal[bpos]) cval = 0xFF; else { cval <<= 8; cval /= (int) cal[bpos]; } } if (gamma) cval = gamma[cval]; buf[bpos++] = cval; } while (bpos < pixel); } sanei_pa4s2_readend (dev->fd); } static void read_average_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf, int pixel, int RefBlack) { SANE_Byte lbuf[4][CCD300_MAXHSIZE * 2]; int ctr, sum; mustek_pp_ccd300_priv *priv = dev->priv; for (ctr = 0; ctr < 4; ctr++) { wait_bank_change (dev, priv->bank_count, 1); read_line_101x (dev, lbuf[ctr], pixel, RefBlack, NULL, NULL); reset_bank_count (dev); if (ctr < 3) set_sti (dev); } for (ctr = 0; ctr < pixel; ctr++) { sum = lbuf[0][ctr] + lbuf[1][ctr] + lbuf[2][ctr] + lbuf[3][ctr]; buf[ctr] = (sum / 4); } } static void find_black_side_edge_101x (Mustek_pp_Handle * dev) { SANE_Byte buf[CCD300_MAXHSIZE * 2]; SANE_Byte blackposition[5]; int pos = 0, ctr, blackpos; mustek_pp_ccd300_priv *priv = dev->priv; for (ctr = 0; ctr < 20; ctr++) { motor_forward_101x (dev); wait_bank_change (dev, priv->bank_count, 1); read_line_101x (dev, buf, CCD300_MAXHSIZE, 0, NULL, NULL); reset_bank_count (dev); priv->ref_black = priv->ref_red = priv->ref_green = priv->ref_blue = buf[0]; blackpos = CCD300_MAXHSIZE / 4; while ((abs (buf[blackpos] - buf[0]) >= 15) && (blackpos > 0)) blackpos--; if (blackpos > 1) blackposition[pos++] = blackpos; if (pos == 5) break; } blackpos = 0; for (ctr = 0; ctr < pos; ctr++) if (blackposition[ctr] > blackpos) blackpos = blackposition[ctr]; if (blackpos < 0x66) blackpos = 0x6A; priv->blackpos = blackpos; priv->saved_skipcount = (blackpos + 12) & 0xFF; } static void min_color_levels_101x (Mustek_pp_Handle * dev) { SANE_Byte buf[CCD300_MAXHSIZE * 2]; int ctr, sum = 0; mustek_pp_ccd300_priv *priv = dev->priv; for (ctr = 0; ctr < 8; ctr++) { set_ccd_channel_101x (dev, CCD300_CHANNEL_RED); set_sti (dev); wait_bank_change (dev, priv->bank_count, 1); read_line_101x (dev, buf, CCD300_MAXHSIZE, 0, NULL, NULL); reset_bank_count (dev); sum += buf[3]; } priv->ref_red = sum / 8; sum = 0; for (ctr = 0; ctr < 8; ctr++) { set_ccd_channel_101x (dev, CCD300_CHANNEL_GREEN); set_sti (dev); wait_bank_change (dev, priv->bank_count, 1); read_line_101x (dev, buf, CCD300_MAXHSIZE, 0, NULL, NULL); reset_bank_count (dev); sum += buf[3]; } priv->ref_green = sum / 8; sum = 0; for (ctr = 0; ctr < 8; ctr++) { set_ccd_channel_101x (dev, CCD300_CHANNEL_BLUE); set_sti (dev); wait_bank_change (dev, priv->bank_count, 1); read_line_101x (dev, buf, CCD300_MAXHSIZE, 0, NULL, NULL); reset_bank_count (dev); sum += buf[3]; } priv->ref_blue = sum / 8; } static void max_color_levels_101x (Mustek_pp_Handle * dev) { int ctr, line, sum; SANE_Byte rbuf[32][CCD300_MAXHSIZE * 2]; SANE_Byte gbuf[32][CCD300_MAXHSIZE * 2]; SANE_Byte bbuf[32][CCD300_MAXHSIZE * 2]; mustek_pp_ccd300_priv *priv = dev->priv; SANE_Byte maxbuf[32]; for (ctr = 0; ctr < 32; ctr++) { if (dev->mode == MODE_COLOR) { set_ccd_channel_101x (dev, CCD300_CHANNEL_RED); motor_forward_101x (dev); read_average_line_101x (dev, rbuf[ctr], dev->params.pixels_per_line, priv->ref_red); set_ccd_channel_101x (dev, CCD300_CHANNEL_GREEN); set_sti (dev); read_average_line_101x (dev, gbuf[ctr], dev->params.pixels_per_line, priv->ref_green); set_ccd_channel_101x (dev, CCD300_CHANNEL_BLUE); set_sti (dev); read_average_line_101x (dev, bbuf[ctr], dev->params.pixels_per_line, priv->ref_blue); } else { priv->channel = CCD300_CHANNEL_GRAY; motor_forward_101x (dev); read_average_line_101x (dev, gbuf[ctr], dev->params.pixels_per_line, priv->ref_black); } } for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++) { for (line = 0; line < 32; line++) maxbuf[line] = gbuf[line][ctr]; qsort (maxbuf, 32, sizeof (maxbuf[0]), compar); sum = maxbuf[4] + maxbuf[5] + maxbuf[6] + maxbuf[7]; priv->calib_g[ctr] = sum / 4; } if (dev->mode == MODE_COLOR) { for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++) { for (line = 0; line < 32; line++) maxbuf[line] = rbuf[line][ctr]; qsort (maxbuf, 32, sizeof (maxbuf[0]), compar); sum = maxbuf[4] + maxbuf[5] + maxbuf[6] + maxbuf[7]; priv->calib_r[ctr] = sum / 4; } for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++) { for (line = 0; line < 32; line++) maxbuf[line] = bbuf[line][ctr]; qsort (maxbuf, 32, sizeof (maxbuf[0]), compar); sum = maxbuf[4] + maxbuf[5] + maxbuf[6] + maxbuf[7]; priv->calib_b[ctr] = sum / 4; } } } static void find_black_top_edge_101x (Mustek_pp_Handle * dev) { int lines = 0, ctr, pos; SANE_Byte buf[CCD300_MAXHSIZE * 2]; mustek_pp_ccd300_priv *priv = dev->priv; priv->channel = CCD300_CHANNEL_GRAY; do { motor_forward_101x (dev); wait_bank_change (dev, priv->bank_count, 1); read_line_101x (dev, buf, CCD300_MAXHSIZE, priv->ref_black, NULL, NULL); reset_bank_count (dev); pos = 0; for (ctr = priv->blackpos; ctr > priv->blackpos - 10; ctr--) if (buf[ctr] <= 15) pos++; } while ((pos >= 8) && (lines++ < 67)); } static void calibrate_device_101x (Mustek_pp_Handle * dev) { int saved_ppl = dev->params.pixels_per_line, ctr; mustek_pp_ccd300_priv *priv = dev->priv; priv->saved_mode = dev->mode; priv->saved_invert = dev->invert; priv->saved_skipcount = priv->skipcount; priv->saved_skipimagebyte = priv->skipimagebytes; priv->saved_adjustskip = priv->adjustskip; priv->saved_res = dev->res; priv->saved_hwres = priv->hwres; priv->saved_res_step = priv->res_step; priv->saved_line_step = priv->line_step; priv->saved_channel = priv->channel; dev->params.pixels_per_line = CCD300_MAXHSIZE; priv->hwres = dev->res = 300; dev->mode = MODE_GRAYSCALE; priv->skipcount = priv->skipimagebytes = 0; dev->invert = SANE_FALSE; priv->channel = CCD300_CHANNEL_GRAY; config_ccd_101x (dev); get_bank_count (dev); find_black_side_edge_101x (dev); for (ctr = 0; ctr < 4; ctr++) move_motor_101x (dev, SANE_TRUE); dev->mode = priv->saved_mode; dev->invert = priv->saved_invert; priv->skipcount = priv->saved_skipcount; priv->skipimagebytes = priv->saved_skipimagebyte; priv->adjustskip = priv->saved_adjustskip; dev->res = priv->saved_res; priv->hwres = priv->saved_hwres; priv->res_step = priv->saved_res_step; priv->line_step = priv->saved_line_step; priv->channel = priv->saved_channel; priv->hwres = dev->res = 300; priv->skipcount = priv->skipimagebytes = 0; dev->invert = SANE_FALSE; config_ccd_101x (dev); get_bank_count (dev); if ((dev->mode == MODE_COLOR) && (priv->ccd_type != 0)) min_color_levels_101x (dev); dev->mode = priv->saved_mode; dev->invert = priv->saved_invert; priv->skipcount = priv->saved_skipcount; priv->skipimagebytes = priv->saved_skipimagebyte; priv->adjustskip = priv->saved_adjustskip; dev->res = priv->saved_res; priv->hwres = priv->saved_hwres; priv->res_step = priv->saved_res_step; priv->line_step = priv->saved_line_step; priv->channel = priv->saved_channel; dev->params.pixels_per_line = saved_ppl; dev->invert = SANE_FALSE; config_ccd_101x (dev); get_bank_count (dev); max_color_levels_101x (dev); dev->params.pixels_per_line = CCD300_MAXHSIZE; dev->mode = MODE_GRAYSCALE; priv->hwres = dev->res = 300; priv->skipcount = priv->skipimagebytes = 0; dev->invert = SANE_FALSE; config_ccd_101x (dev); get_bank_count (dev); find_black_top_edge_101x (dev); dev->mode = priv->saved_mode; dev->invert = priv->saved_invert; priv->skipcount = priv->saved_skipcount; priv->skipimagebytes = priv->saved_skipimagebyte; priv->adjustskip = priv->saved_adjustskip; dev->res = priv->saved_res; priv->hwres = priv->saved_hwres; priv->res_step = priv->saved_res_step; priv->line_step = priv->saved_line_step; priv->channel = priv->saved_channel; dev->params.pixels_per_line = saved_ppl; config_ccd_101x (dev); get_bank_count (dev); } static void get_grayscale_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf) { int skips; mustek_pp_ccd300_priv *priv = dev->priv; priv->line_diff += SANE_FIX (300.0 / (float) dev->res); skips = (priv->line_diff >> SANE_FIXED_SCALE_SHIFT); while (--skips) { motor_forward_101x (dev); wait_bank_change (dev, priv->bank_count, 1); reset_bank_count (dev); } priv->line_diff &= 0xFFFF; motor_forward_101x (dev); wait_bank_change (dev, priv->bank_count, 1); read_line_101x (dev, buf, dev->params.pixels_per_line, priv->ref_black, priv->calib_g, NULL); reset_bank_count (dev); } static void get_lineart_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf) { int ctr; SANE_Byte gbuf[CCD300_MAXHSIZE * 2]; mustek_pp_ccd300_priv *priv = dev->priv; get_grayscale_line_101x (dev, gbuf); memset (buf, 0xFF, dev->params.bytes_per_line); for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++) buf[ctr >> 3] ^= ((gbuf[ctr] > priv->bw) ? (1 << (7 - ctr % 8)) : 0); } static void get_color_line_101x (Mustek_pp_Handle * dev, SANE_Byte * buf) { SANE_Byte *red, *blue, *src, *dest; int gotline = 0, ctr; int gored, goblue, gogreen; mustek_pp_ccd300_priv *priv = dev->priv; int step = priv->line_step; do { red = priv->red[priv->redline]; blue = priv->blue[priv->blueline]; priv->ccd_line++; if ((priv->rdiff >> SANE_FIXED_SCALE_SHIFT) == priv->ccd_line) { gored = 1; priv->rdiff += step; } else gored = 0; if ((priv->bdiff >> SANE_FIXED_SCALE_SHIFT) == priv->ccd_line) { goblue = 1; priv->bdiff += step; } else goblue = 0; if ((priv->gdiff >> SANE_FIXED_SCALE_SHIFT) == priv->ccd_line) { gogreen = 1; priv->gdiff += step; } else gogreen = 0; if (!gored && !goblue && !gogreen) { motor_forward_101x (dev); wait_bank_change (dev, priv->bank_count, 1); reset_bank_count (dev); if (priv->ccd_line >= (priv->line_step >> SANE_FIXED_SCALE_SHIFT)) priv->redline = (priv->redline + 1) % priv->green_offs; if (priv->ccd_line >= priv->blue_offs + (priv->line_step >> SANE_FIXED_SCALE_SHIFT)) priv->blueline = (priv->blueline + 1) % priv->blue_offs; continue; } if (gored) priv->channel = CCD300_CHANNEL_RED; else if (goblue) priv->channel = CCD300_CHANNEL_BLUE; else priv->channel = CCD300_CHANNEL_GREEN; motor_forward_101x (dev); wait_bank_change (dev, priv->bank_count, 1); if (priv->ccd_line >= priv->green_offs && gogreen) { src = red; dest = buf; for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++) { *dest = *src++; dest += 3; } } if (gored) { read_line_101x (dev, red, dev->params.pixels_per_line, priv->ref_red, priv->calib_r, NULL); reset_bank_count (dev); } priv->redline = (priv->redline + 1) % priv->green_offs; if (priv->ccd_line >= priv->green_offs && gogreen) { src = blue; dest = buf + 2; for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++) { *dest = *src++; dest += 3; } } if (goblue) { if (gored) { set_ccd_channel_101x (dev, CCD300_CHANNEL_BLUE); set_sti (dev); wait_bank_change (dev, priv->bank_count, 1); } read_line_101x (dev, blue, dev->params.pixels_per_line, priv->ref_blue, priv->calib_b, NULL); reset_bank_count (dev); } if (priv->ccd_line >= priv->blue_offs + (priv->line_step >> SANE_FIXED_SCALE_SHIFT)) priv->blueline = (priv->blueline + 1) % priv->blue_offs; if (gogreen) { if (gored || goblue) { set_ccd_channel_101x (dev, CCD300_CHANNEL_GREEN); set_sti (dev); wait_bank_change (dev, priv->bank_count, 1); } read_line_101x (dev, priv->green, dev->params.pixels_per_line, priv->ref_green, priv->calib_g, NULL); reset_bank_count (dev); src = priv->green; dest = buf + 1; for (ctr = 0; ctr < dev->params.pixels_per_line; ctr++) { *dest = *src++; dest += 3; } gotline = 1; } } while (!gotline); } /* these functions are for the 1013 chipset */ static void set_ccd_channel_1013 (Mustek_pp_Handle * dev, int channel) { mustek_pp_ccd300_priv *priv = dev->priv; priv->channel = channel; sanei_pa4s2_writebyte (dev->fd, 6, chan_codes_1013[channel]); } static void motor_backward_1013 (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; priv->motor_step++; set_led (dev); if (priv->motor_phase > 3) priv->motor_phase = 3; sanei_pa4s2_writebyte (dev->fd, 6, 0x62); sanei_pa4s2_writebyte (dev->fd, 5, fullstep[priv->motor_phase]); priv->motor_phase = (priv->motor_phase == 0 ? 3 : priv->motor_phase - 1); set_ccd_channel_1013 (dev, priv->channel); set_sti (dev); } static void return_home_1013 (Mustek_pp_Handle * dev) { u_char ishome; int ctr; mustek_pp_ccd300_priv *priv = dev->priv; /* 1013 can't return home all alone, nowait ignored */ for (ctr = 0; ctr < 4500; ctr++) { /* check_is_home_1013 */ sanei_pa4s2_readbegin (dev->fd, 2); sanei_pa4s2_readbyte (dev->fd, &ishome); sanei_pa4s2_readend (dev->fd); /* yes, it should be is_not_home */ if ((ishome & 1) == 0) break; motor_backward_1013 (dev); wait_bank_change (dev, priv->bank_count, 0); reset_bank_count (dev); } } static void motor_forward_1013 (Mustek_pp_Handle * dev) { int ctr; mustek_pp_ccd300_priv *priv = dev->priv; priv->motor_step++; set_led (dev); for (ctr = 0; ctr < 2; ctr++) { sanei_pa4s2_writebyte (dev->fd, 6, 0x62); sanei_pa4s2_writebyte (dev->fd, 5, halfstep[priv->motor_phase]); priv->motor_phase = (priv->motor_phase == 7 ? 0 : priv->motor_phase + 1); } set_ccd_channel_1013 (dev, priv->channel); set_sti (dev); } static void config_ccd_1013 (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; if (dev->res != 0) priv->res_step = SANE_FIX ((float) priv->hwres / (float) dev->res); set_dpi_value (dev); /* set_start_channel_1013 (dev); */ sanei_pa4s2_writebyte (dev->fd, 6, 0x05); switch (dev->mode) { case MODE_BW: case MODE_GRAYSCALE: priv->channel = CCD300_CHANNEL_GRAY; break; case MODE_COLOR: priv->channel = CCD300_CHANNEL_RED; break; } set_ccd_channel_1013 (dev, priv->channel); /* set_invert_1013 (dev); */ sanei_pa4s2_writebyte (dev->fd, 6, (dev->invert == SANE_TRUE ? 0x04 : 0x14)); sanei_pa4s2_writebyte (dev->fd, 6, 0x37); reset_bank_count (dev); sanei_pa4s2_writebyte (dev->fd, 6, 0x27); sanei_pa4s2_writebyte (dev->fd, 6, 0x67); sanei_pa4s2_writebyte (dev->fd, 6, 0x17); sanei_pa4s2_writebyte (dev->fd, 6, 0x77); /* set_initial_skip_1013 (dev); */ sanei_pa4s2_writebyte (dev->fd, 6, 0x41); priv->adjustskip = priv->skipcount + priv->skipimagebytes; DBG (5, "config_ccd_1013: adjustskip %u\n", priv->adjustskip); sanei_pa4s2_writebyte (dev->fd, 5, priv->adjustskip / 16 + 2); priv->adjustskip %= 16; sanei_pa4s2_writebyte (dev->fd, 6, 0x81); sanei_pa4s2_writebyte (dev->fd, 5, 0x70); sanei_pa4s2_writebyte (dev->fd, 6, 0x01); set_line_adjust (dev); get_bank_count (dev); } /* these functions are for the 1015 chipset */ static void motor_control_1015 (Mustek_pp_Handle * dev, u_char control) { u_char val; DBG (5, "motor_controll_1015: control code 0x%02x\n", (unsigned int) control); sanei_pa4s2_writebyte (dev->fd, 6, 0xF6); sanei_pa4s2_writebyte (dev->fd, 6, 0x22); sanei_pa4s2_writebyte (dev->fd, 5, control); sanei_pa4s2_writebyte (dev->fd, 6, 0x02); do { sanei_pa4s2_readbegin (dev->fd, 2); sanei_pa4s2_readbyte (dev->fd, &val); sanei_pa4s2_readend (dev->fd); } while ((val & 0x08) != 0); } static void return_home_1015 (Mustek_pp_Handle * dev, SANE_Bool nowait) { u_char ishome, control = 0xC3; motor_control_1015 (dev, control); do { /* check_is_home_1015 */ sanei_pa4s2_readbegin (dev->fd, 2); sanei_pa4s2_readbyte (dev->fd, &ishome); sanei_pa4s2_readend (dev->fd); if (nowait) break; usleep (1000); /* much nicer load */ } while ((ishome & 2) == 0); } static void motor_forward_1015 (Mustek_pp_Handle * dev) { u_char control = 0x1B; mustek_pp_ccd300_priv *priv = dev->priv; priv->motor_step++; set_led (dev); motor_control_1015 (dev, control); set_ccd_channel_1015 (dev, priv->channel); set_sti (dev); } /* static void motor_backward_1015 (Mustek_pp_Handle * dev) { u_char control = 0x43; mustek_pp_ccd300_priv *priv = dev->priv; priv->motor_step++; set_led (dev); switch (priv->ccd_type) { case 1: control = 0x1B; break; default: control = 0x43; break; } motor_control_1015 (dev, control); set_ccd_channel_1015 (dev, priv->channel); set_sti (dev); } */ static void set_ccd_channel_1015 (Mustek_pp_Handle * dev, int channel) { u_char chancode = chan_codes_1015[channel]; mustek_pp_ccd300_priv *priv = dev->priv; priv->channel = channel; priv->image_control &= 0x34; chancode |= priv->image_control; priv->image_control = chancode; sanei_pa4s2_writebyte (dev->fd, 6, chancode); } static void config_ccd_1015 (Mustek_pp_Handle * dev) { u_char val; mustek_pp_ccd300_priv *priv = dev->priv; if (dev->res != 0) priv->res_step = SANE_FIX ((float) priv->hwres / (float) dev->res); set_dpi_value (dev); priv->image_control = 4; /* set_start_channel_1015 (dev); */ switch (dev->mode) { case MODE_BW: case MODE_GRAYSCALE: priv->channel = CCD300_CHANNEL_GRAY; break; case MODE_COLOR: priv->channel = CCD300_CHANNEL_RED; break; } set_ccd_channel_1015 (dev, priv->channel); /* set_invert_1015 (dev); */ priv->image_control &= 0xE4; if (dev->invert == SANE_FALSE) priv->image_control |= 0x10; sanei_pa4s2_writebyte (dev->fd, 6, priv->image_control); sanei_pa4s2_writebyte (dev->fd, 6, 0x23); sanei_pa4s2_writebyte (dev->fd, 5, 0x00); sanei_pa4s2_writebyte (dev->fd, 6, 0x43); switch (priv->ccd_type) { case 1: val = 0x6B; break; case 4: val = 0x9F; break; default: val = 0x92; break; } sanei_pa4s2_writebyte (dev->fd, 5, val); sanei_pa4s2_writebyte (dev->fd, 6, 0x03); sanei_pa4s2_writebyte (dev->fd, 6, 0x37); reset_bank_count (dev); sanei_pa4s2_writebyte (dev->fd, 6, 0x27); sanei_pa4s2_writebyte (dev->fd, 6, 0x67); sanei_pa4s2_writebyte (dev->fd, 6, 0x17); sanei_pa4s2_writebyte (dev->fd, 6, 0x77); /* set_initial_skip_1015 (dev); */ sanei_pa4s2_writebyte (dev->fd, 6, 0x41); priv->adjustskip = priv->skipcount + priv->skipimagebytes; /* if (dev->CCD.mode == MODE_COLOR) dev->CCD.adjustskip <<= 3; */ sanei_pa4s2_writebyte (dev->fd, 5, priv->adjustskip / 32 + 1); priv->adjustskip %= 32; sanei_pa4s2_writebyte (dev->fd, 6, 0x81); /* expose time */ switch (priv->ccd_type) { case 1: val = 0xA8; break; case 0: val = 0x8A; break; default: val = 0xA8; break; } sanei_pa4s2_writebyte (dev->fd, 5, val); sanei_pa4s2_writebyte (dev->fd, 6, 0x01); set_line_adjust (dev); get_bank_count (dev); } /* these functions are interfaces only */ static void config_ccd (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; DBG (5, "config_ccd: %d dpi, mode %d, invert %d, size %d\n", priv->hwres, dev->mode, dev->invert, dev->params.pixels_per_line); switch (priv->asic) { case CCD300_ASIC1013: config_ccd_1013 (dev); break; case CCD300_ASIC1015: config_ccd_1015 (dev); break; } } static void return_home (Mustek_pp_Handle * dev, SANE_Bool nowait) { mustek_pp_ccd300_priv *priv = dev->priv; priv->saved_mode = dev->mode; priv->saved_invert = dev->invert; priv->saved_skipcount = priv->skipcount; priv->saved_skipimagebyte = priv->skipimagebytes; priv->saved_adjustskip = priv->adjustskip; priv->saved_res = dev->res; priv->saved_hwres = priv->hwres; priv->saved_res_step = priv->res_step; priv->saved_line_step = priv->line_step; priv->saved_channel = priv->channel; priv->hwres = dev->res = 100; dev->mode = MODE_GRAYSCALE; priv->skipcount = priv->skipimagebytes = 0; config_ccd (dev); switch (priv->asic) { case CCD300_ASIC1013: return_home_1013 (dev); break; case CCD300_ASIC1015: return_home_1015 (dev, nowait); break; } dev->mode = priv->saved_mode; dev->invert = priv->saved_invert; priv->skipcount = priv->saved_skipcount; priv->skipimagebytes = priv->saved_skipimagebyte; priv->adjustskip = priv->saved_adjustskip; dev->res = priv->saved_res; priv->hwres = priv->saved_hwres; priv->res_step = priv->saved_res_step; priv->line_step = priv->saved_line_step; priv->channel = priv->saved_channel; priv->motor_step = 0; config_ccd (dev); } static void lamp (Mustek_pp_Handle * dev, int lamp_on) { set_lamp (dev, lamp_on); } static void set_voltages (Mustek_pp_Handle * dev) { send_voltages (dev); } static void move_motor (Mustek_pp_Handle * dev, int count, int forward) { int ctr; DBG (5, "move_motor: %u steps (%s)\n", count, (forward == SANE_TRUE ? "forward" : "backward")); for (ctr = 0; ctr < count; ctr++) { move_motor_101x (dev, forward); } } static void calibrate (Mustek_pp_Handle * dev) { mustek_pp_ccd300_priv *priv = dev->priv; DBG (5, "calibrate entered (asic = 0x%02x)\n", priv->asic); calibrate_device_101x (dev); DBG (5, "calibrate: ref_black %d, blackpos %d\n", priv->ref_black, priv->blackpos); } static void get_lineart_line (Mustek_pp_Handle * dev, SANE_Byte * buf) { get_lineart_line_101x (dev, buf); } static void get_grayscale_line (Mustek_pp_Handle * dev, SANE_Byte * buf) { get_grayscale_line_101x (dev, buf); } static void get_color_line (Mustek_pp_Handle * dev, SANE_Byte * buf) { get_color_line_101x (dev, buf); } static SANE_Status ccd300_init (SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach) { SANE_Status status; unsigned char asic, ccd; int fd; if (options != CAP_NOTHING) { DBG (1, "ccd300_init: called with unknown options (%#02x)\n", options); return SANE_STATUS_INVAL; } /* try to attach to he supplied port */ status = sanei_pa4s2_open (port, &fd); if (status != SANE_STATUS_GOOD) { DBG (2, "ccd300_init: couldn't attach to port ``%s'' (%s)\n", port, sane_strstatus (status)); return status; } sanei_pa4s2_enable (fd, SANE_TRUE); sanei_pa4s2_readbegin (fd, 0); sanei_pa4s2_readbyte (fd, &asic); sanei_pa4s2_readend (fd); sanei_pa4s2_readbegin (fd, 2); sanei_pa4s2_readbyte (fd, &ccd); sanei_pa4s2_readend (fd); sanei_pa4s2_enable (fd, SANE_FALSE); sanei_pa4s2_close (fd); if (asic != CCD300_ASIC1013 && asic != CCD300_ASIC1015) { DBG (2, "ccd300_init: scanner not recognized (unknown ASIC id %#02x)\n", asic); return SANE_STATUS_INVAL; } ccd &= (asic == CCD300_ASIC1013 ? 0x04 : 0x05); DBG (3, "ccd_init: found scanner on port ``%s'' (ASIC id %#02x, CCD %d)\n", port, asic, ccd); return attach (port, name, MUSTEK_PP_CCD300, options); } static void ccd300_capabilities (SANE_Int info, SANE_String * model, SANE_String * vendor, SANE_String * type, SANE_Int * maxres, SANE_Int * minres, SANE_Int * maxhsize, SANE_Int * maxvsize, SANE_Int * caps) { *model = strdup ("600 III EP Plus"); *vendor = strdup ("Mustek"); *type = strdup ("flatbed (CCD 300 dpi)"); DBG (3, "ccd300_capabilities: 600 III EP Plus flatbed CCD (300 dpi) scanner\n"); *maxres = 300; *minres = 50; *maxhsize = CCD300_MAXHSIZE; *maxvsize = CCD300_MAXVSIZE; *caps = info | CAP_INVERT | CAP_LAMP_OFF; } static SANE_Status ccd300_open (SANE_String port, SANE_Int caps, SANE_Int * fd) { SANE_Status status; if (caps & ~(CAP_NOTHING | CAP_INVERT | CAP_LAMP_OFF)) { DBG (1, "ccd300_open: called with unknown capabilities (%#02x)\n", caps); return SANE_STATUS_INVAL; } DBG (3, "ccd300_open: called for port ``%s''\n", port); status = sanei_pa4s2_open (port, fd); if (status != SANE_STATUS_GOOD) DBG (2, "ccd300_open: open failed (%s)\n", sane_strstatus (status)); return status; } static void ccd300_setup (SANE_Handle handle) { Mustek_pp_Handle *dev = handle; mustek_pp_ccd300_priv *priv; unsigned char asic, ccd; DBG (3, "ccd300_setup: called for port ``%s''\n", dev->dev->port); if ((priv = malloc (sizeof (mustek_pp_ccd300_priv))) == NULL) { DBG (1, "ccd300_setup: not enough memory\n"); return; /* can you here the shit hitting the fan? */ } dev->priv = priv; memset (priv, 0, sizeof (mustek_pp_ccd300_priv)); priv->bw = 128; priv->wait_bank = 700; priv->top = 47; sanei_pa4s2_enable (dev->fd, SANE_TRUE); sanei_pa4s2_readbegin (dev->fd, 0); sanei_pa4s2_readbyte (dev->fd, &asic); sanei_pa4s2_readend (dev->fd); sanei_pa4s2_readbegin (dev->fd, 2); sanei_pa4s2_readbyte (dev->fd, &ccd); sanei_pa4s2_readend (dev->fd); ccd &= (asic == CCD300_ASIC1013 ? 0x04 : 0x05); priv->asic = asic; priv->ccd_type = ccd; return_home (dev, SANE_TRUE); lamp (dev, SANE_TRUE); sanei_pa4s2_enable (dev->fd, SANE_FALSE); dev->lamp_on = time (NULL); dev->res = priv->hwres = 300; dev->mode = MODE_COLOR; } static void ccd300_close (SANE_Handle handle) { Mustek_pp_Handle *dev = handle; mustek_pp_ccd300_priv *priv = dev->priv; DBG (3, "ccd300_close: called for port ``%s''\n", dev->dev->port); sanei_pa4s2_enable (dev->fd, SANE_TRUE); lamp (dev, SANE_FALSE); return_home (dev, SANE_FALSE); sanei_pa4s2_enable (dev->fd, SANE_FALSE); sanei_pa4s2_close (dev->fd); free (priv); DBG (3, "ccd300_close: device shut down and all buffers freed\n"); } static SANE_Status ccd300_config (SANE_Handle handle, SANE_String_Const optname, SANE_String_Const optval) { Mustek_pp_Handle *dev = handle; mustek_pp_ccd300_priv *priv = dev->priv; int value = -1; DBG (3, "ccd300_config: called for port ``%s'' (%s%s%s)\n", dev->dev->port, optname, (optval ? " = " : ""), (optval ? optval : "")); if (!strcmp (optname, "bw")) { if (!optval) { DBG (1, "ccd300_config: missing value for option ``bw''\n"); return SANE_STATUS_INVAL; } /* ok, ok, should be strtol... know what? send me a patch. */ value = atoi (optval); if ((value < 0) || (value > 255)) { DBG (1, "ccd300_config: value ``%s'' for option ``bw'' is out of range (0 <= bw <= 255)\n", optval); return SANE_STATUS_INVAL; } priv->bw = value; } else if (!strcmp (optname, "waitbank")) { if (!optval) { DBG (1, "ccd300_config: missing value for option ``waitbank''\n"); return SANE_STATUS_INVAL; } value = atoi (optval); if (value < 0) { DBG (1, "ccd300_config: value ``%s'' for option ``waitbank'' is out of range (>= 0)\n", optval); return SANE_STATUS_INVAL; } priv->wait_bank = value; } else if (!strcmp (optname, "top")) { if (!optval) { DBG (1, "ccd300_config: missing value for option ``top''\n"); return SANE_STATUS_INVAL; } value = atoi (optval); if (value < 0) { DBG (1, "ccd300_config: value ``%s'' for option ``top'' is out of range (>= 0)\n", optval); return SANE_STATUS_INVAL; } priv->top = value; } else { DBG (1, "ccd300_config: unknown option ``%s''", optname); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } static void ccd300_stop (SANE_Handle handle) { Mustek_pp_Handle *dev = handle; mustek_pp_ccd300_priv *priv = dev->priv; int cnt; DBG (3, "ccd300_stop: stopping scan operating on port ``%s''\n", dev->dev->port); sanei_pa4s2_enable (dev->fd, SANE_TRUE); return_home (dev, SANE_TRUE); sanei_pa4s2_enable (dev->fd, SANE_FALSE); free (priv->calib_r); free (priv->calib_g); free (priv->calib_b); if (priv->red) { for (cnt = 0; cnt < priv->green_offs; cnt++) free (priv->red[cnt]); free (priv->red); } if (priv->blue) { for (cnt = 0; cnt < priv->blue_offs; cnt++) free (priv->blue[cnt]); free (priv->blue); } free (priv->green); priv->calib_r = priv->calib_g = priv->calib_b = NULL; priv->red = priv->blue = NULL; priv->green = NULL; } static SANE_Status ccd300_start (SANE_Handle handle) { Mustek_pp_Handle *dev = handle; mustek_pp_ccd300_priv *priv = dev->priv; DBG (3, "ccd300_start: called for port ``%s''\n", dev->dev->port); if (dev->res <= 100) priv->hwres = 100; else if (dev->res <= 200) priv->hwres = 200; else if (dev->res <= 300) priv->hwres = 300; DBG (4, "ccd300_start: setting hardware resolution to %d dpi\n", priv->hwres); priv->skipimagebytes = dev->topX; sanei_pa4s2_enable (dev->fd, SANE_TRUE); config_ccd (dev); set_voltages (dev); get_bank_count (dev); if (priv->bank_count != 0) { DBG (2, "ccd300_start: bank count is not zero...\n"); } return_home (dev, SANE_FALSE); priv->motor_step = 0; /* allocate memory for calibration */ if ((priv->calib_g = malloc (dev->params.pixels_per_line)) == NULL) { sanei_pa4s2_enable (dev->fd, SANE_FALSE); DBG (1, "ccd300_start: not enough memory\n"); return SANE_STATUS_NO_MEM; } if (dev->mode == MODE_COLOR) { priv->calib_r = malloc (dev->params.pixels_per_line); priv->calib_b = malloc (dev->params.pixels_per_line); if ((priv->calib_r == NULL) || (priv->calib_b == NULL)) { free (priv->calib_g); free (priv->calib_r); free (priv->calib_b); priv->calib_r = priv->calib_g = priv->calib_b = NULL; sanei_pa4s2_enable (dev->fd, SANE_FALSE); DBG (1, "ccd300_start: not enough memory\n"); return SANE_STATUS_NO_MEM; } } calibrate (dev); if (priv->ccd_type == 1) { priv->blue_offs = 4; priv->green_offs = 8; } else { priv->blue_offs = 8; priv->green_offs = 16; } move_motor (dev, priv->top + dev->topY - (dev->mode == MODE_COLOR ? priv->green_offs : 0), SANE_TRUE); if (priv->ccd_type == 1) sanei_pa4s2_writebyte (dev->fd, 6, 0x15); sanei_pa4s2_enable (dev->fd, SANE_FALSE); if (dev->mode == MODE_COLOR) { int failed = SANE_FALSE, cnt; priv->line_step = SANE_FIX (300.0 / (float) dev->res); priv->rdiff = priv->line_step; priv->bdiff = priv->rdiff + (priv->blue_offs << SANE_FIXED_SCALE_SHIFT); priv->gdiff = priv->rdiff + (priv->green_offs << SANE_FIXED_SCALE_SHIFT); priv->red = malloc (sizeof (SANE_Byte *) * priv->green_offs); priv->blue = malloc (sizeof (SANE_Byte *) * priv->blue_offs); priv->green = malloc (dev->params.pixels_per_line); if ((priv->red == NULL) || (priv->blue == NULL) || (priv->green == NULL)) { free (priv->calib_r); free (priv->calib_g); free (priv->calib_b); priv->calib_r = priv->calib_g = priv->calib_b = NULL; free (priv->red); free (priv->green); free (priv->blue); priv->red = priv->blue = NULL; priv->green = NULL; DBG (1, "ccd300_start: not enough memory for ld buffers\n"); return SANE_STATUS_NO_MEM; } /* note to myself: better allocate one huge chunk of memory and set pointers */ for (cnt = 0; cnt < priv->green_offs; cnt++) if ((priv->red[cnt] = malloc (dev->params.pixels_per_line)) == NULL) failed = SANE_TRUE; for (cnt = 0; cnt < priv->blue_offs; cnt++) if ((priv->blue[cnt] = malloc (dev->params.pixels_per_line)) == NULL) failed = SANE_TRUE; if (failed == SANE_TRUE) { free (priv->calib_r); free (priv->calib_g); free (priv->calib_b); priv->calib_r = priv->calib_g = priv->calib_b = NULL; for (cnt = 0; cnt < priv->green_offs; cnt++) free (priv->red[cnt]); for (cnt = 0; cnt < priv->blue_offs; cnt++) free (priv->blue[cnt]); free (priv->red); free (priv->green); free (priv->blue); priv->red = priv->blue = NULL; priv->green = NULL; DBG (1, "ccd300_start: not enough memory for ld buffers\n"); return SANE_STATUS_NO_MEM; } priv->redline = priv->blueline = priv->ccd_line = 0; } priv->lines = 0; priv->lines_left = dev->params.lines; DBG (3, "ccd300_start: device ready for scanning\n"); return SANE_STATUS_GOOD; } static void ccd300_read (SANE_Handle handle, SANE_Byte * buffer) { Mustek_pp_Handle *dev = handle; mustek_pp_ccd300_priv *priv = dev->priv; DBG (3, "ccd300_read: receiving one line from port ``%s''\n", dev->dev->port); sanei_pa4s2_enable (dev->fd, SANE_TRUE); switch (dev->mode) { case MODE_BW: get_lineart_line (dev, buffer); break; case MODE_GRAYSCALE: get_grayscale_line (dev, buffer); break; case MODE_COLOR: get_color_line (dev, buffer); break; } priv->lines_left--; priv->lines++; DBG (4, "ccd300_read: %d lines read (%d to go)\n", priv->lines, priv->lines_left); if (priv->lines_left == 0) { DBG (3, "ccd300_read: scan finished\n"); return_home (dev, SANE_TRUE); } sanei_pa4s2_enable (dev->fd, SANE_FALSE); } sane-backends-1.0.27/backend/gt68xx_devices.c0000664000175000017500000023527212112021330015623 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov Copyright (C) 2002 - 2007 Henning Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* Scanner-specific data */ #include "gt68xx_low.h" #include "gt68xx_generic.c" #include "gt68xx_gt6801.c" #include "gt68xx_gt6816.c" static GT68xx_Command_Set mustek_gt6816_command_set = { "mustek-gt6816", /* Name of this command set */ 0x40, /* Request type */ 0x01, /* Request */ 0x200c, /* Memory read - wValue */ 0x200b, /* Memory write - wValue */ 0x2010, /* Send normal command - wValue */ 0x3f40, /* Send normal command - wIndex */ 0x2011, /* Receive normal result - wValue */ 0x3f00, /* Receive normal result - wIndex */ 0x2012, /* Send small command - wValue */ 0x3f40, /* Send small command - wIndex */ 0x2013, /* Receive small result - wValue */ 0x3f00, /* Receive small result - wIndex */ /* activate */ NULL, /* deactivate */ NULL, gt6816_check_firmware, gt6816_download_firmware, gt6816_get_power_status, gt6816_get_ta_status, gt6816_lamp_control, gt6816_is_moving, gt68xx_generic_move_relative, gt6816_carriage_home, /* gt68xx_generic_paperfeed */ NULL, gt68xx_generic_start_scan, gt68xx_generic_read_scanned_data, gt6816_stop_scan, gt68xx_generic_setup_scan, gt68xx_generic_set_afe, gt68xx_generic_set_exposure_time, gt68xx_generic_get_id, /* gt68xx_generic_move_paper */ NULL, /* gt6816_document_present */ NULL }; static GT68xx_Command_Set mustek_gt6816_sheetfed_command_set = { "mustek-gt6816", /* Name of this command set */ 0x40, /* Request type */ 0x01, /* Request */ 0x200c, /* Memory read - wValue */ 0x200b, /* Memory write - wValue */ 0x2010, /* Send normal command - wValue */ 0x3f40, /* Send normal command - wIndex */ 0x2011, /* Receive normal result - wValue */ 0x3f00, /* Receive normal result - wIndex */ 0x2012, /* Send small command - wValue */ 0x3f40, /* Send small command - wIndex */ 0x2013, /* Receive small result - wValue */ 0x3f00, /* Receive small result - wIndex */ /* activate */ NULL, /* deactivate */ NULL, gt6816_check_firmware, gt6816_download_firmware, gt6816_get_power_status, gt6816_get_ta_status, gt6816_lamp_control, gt6816_is_moving, gt68xx_generic_move_relative, /* gt6816_carriage_home */ NULL, gt68xx_generic_paperfeed, gt68xx_generic_start_scan, gt68xx_generic_read_scanned_data, gt6801_stop_scan, gt68xx_generic_setup_scan, gt68xx_generic_set_afe, gt68xx_generic_set_exposure_time, gt68xx_generic_get_id, gt68xx_generic_move_paper, gt6816_document_present }; static GT68xx_Command_Set mustek_gt6801_command_set = { "mustek-gt6801", 0x40, /* Request type */ 0x01, /* Request */ 0x200a, /* Memory read - wValue */ 0x2009, /* Memory write - wValue */ 0x2010, /* Send normal command - wValue */ 0x3f40, /* Send normal command - wIndex */ 0x2011, /* Receive normal result - wValue */ 0x3f00, /* Receive normal result - wIndex */ 0x2012, /* Send small command - wValue */ 0x3f40, /* Send small command - wIndex */ 0x2013, /* Receive small result - wValue */ 0x3f00, /* Receive small result - wIndex */ /* activate */ NULL, /* deactivate */ NULL, gt6801_check_firmware, gt6801_download_firmware, gt6801_get_power_status, /* get_ta_status (FIXME: implement this) */ NULL, gt6801_lamp_control, gt6801_is_moving, /* gt68xx_generic_move_relative *** to be tested */ NULL, gt6801_carriage_home, /* gt68xx_generic_paperfeed */ NULL, gt68xx_generic_start_scan, gt68xx_generic_read_scanned_data, gt6801_stop_scan, gt68xx_generic_setup_scan, gt68xx_generic_set_afe, gt68xx_generic_set_exposure_time, gt68xx_generic_get_id, /* gt68xx_generic_move_paper */ NULL, /* gt6816_document_present */ NULL }; static GT68xx_Command_Set plustek_gt6801_command_set = { "plustek-gt6801", 0x40, /* Request type */ 0x04, /* Request */ 0x200a, /* Memory read - wValue */ 0x2009, /* Memory write - wValue */ 0x2010, /* Send normal command - wValue */ 0x3f40, /* Send normal command - wIndex */ 0x2011, /* Receive normal result - wValue */ 0x3f00, /* Receive normal result - wIndex */ 0x2012, /* Send small command - wValue */ 0x3f40, /* Send small command - wIndex */ 0x2013, /* Receive small result - wValue */ 0x3f00, /* Receive small result - wIndex */ /* activate */ NULL, /* deactivate */ NULL, gt6801_check_plustek_firmware, gt6801_download_firmware, gt6801_get_power_status, /* get_ta_status (FIXME: implement this) */ NULL, gt6801_lamp_control, gt6801_is_moving, /* gt68xx_generic_move_relative *** to be tested */ NULL, gt6801_carriage_home, /* gt68xx_generic_paperfeed */ NULL, gt68xx_generic_start_scan, gt68xx_generic_read_scanned_data, gt6801_stop_scan, gt68xx_generic_setup_scan, gt68xx_generic_set_afe, /* set_exposure_time */ NULL, gt68xx_generic_get_id, /* gt68xx_generic_move_paper */ NULL, /* gt6816_document_present */ NULL }; static GT68xx_Model unknown_model = { "unknown-scanner", /* Name */ "unknown manufacturer", /* Device vendor string */ "unknown device -- use override to select", /* Device model name */ "unknown", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {8, 0}, /* possible depths in gray mode */ {8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (13.0), /* Start of scan area in mm (y) */ SANE_FIX (200.0), /* Size of scan area in mm (x) */ SANE_FIX (280.0), /* Size of scan area in mm (y) */ SANE_FIX (9.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x14, 0x07, 0x14, 0x07, 0x14, 0x07}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_STOP /* Which flags are needed for this scanner? */ /* Standard values for unknown scanner */ }; static GT68xx_Model mustek_2400ta_model = { "mustek-bearpaw-2400-ta", /* Name */ "Mustek", /* Device vendor string */ "BearPaw 2400 TA", /* Device model name */ "A2fw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 2400, /* maximum motor resolution */ 1200, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {1200, 600, 300, 200, 100, 50, 0}, /* possible x-resolutions */ {2400, 1200, 600, 300, 200, 100, 50, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.67), /* Start of scan area in mm (x) */ SANE_FIX (7.4), /* Start of scan area in mm (y) */ SANE_FIX (219.0), /* Size of scan area in mm (x) */ SANE_FIX (298.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.635), /* Start of black mark in mm (x) */ SANE_FIX (94.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (107.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (37.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (165.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (95.0), /* Start of white strip in TA mode in mm (y) */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x2a, 0x0c, 0x2e, 0x06, 0x2d, 0x07}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_SCAN_FROM_HOME /* Which flags are needed for this scanner? */ /* flatbed values tested */ }; static GT68xx_Model mustek_2400taplus_model = { "mustek-bearpaw-2400-ta-plus", /* Name */ "Mustek", /* Device vendor string */ "BearPaw 2400 TA Plus", /* Device model name */ "A2Dfw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 2400, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {1200, 600, 300, 100, 50, 0}, /* possible x-resolutions */ {2400, 1200, 600, 300, 100, 50, 0}, /* possible y-resolutions */ {8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (7.41), /* Start of scan area in mm (x) */ SANE_FIX (7.4), /* Start of scan area in mm (y) */ SANE_FIX (217.5), /* Size of scan area in mm (x) */ SANE_FIX (298.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (5.0), /* Start of black mark in mm (x) */ SANE_FIX (94.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (107.0) /* Start of scan area in TA mode in mm (y) */ , SANE_FIX (37.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (165.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (95.0), /* Start of white strip in TA mode in mm (y) */ 0, 48, 96, /* RGB CCD Line-distance correction in pixel */ 8, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x2a, 0x0c, 0x2e, 0x06, 0x2d, 0x07}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_USE_OPTICAL_X | GT68XX_FLAG_SCAN_FROM_HOME /* Which flags are needed for this scanner? */ /* Setup and tested */ }; static GT68xx_Model mustek_2448taplus_model = { "mustek-bearpaw-2448-ta-plus", /* Name */ "Mustek", /* Device vendor string */ "BearPaw 2448 TA Plus", /* Device model name */ "A2Nfw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 2400, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {1200, 600, 300, 200, 100, 0}, /* possible x-resolutions */ {2400, 1200, 600, 300, 200, 100, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (7.41), /* Start of scan area in mm (x) */ SANE_FIX (7.4), /* Start of scan area in mm (y) */ SANE_FIX (216.3), /* Size of scan area in mm (x) */ SANE_FIX (297.5), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (4.0), /* Start of black mark in mm (x) */ SANE_FIX (94.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (105.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (36.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (165.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (95.0), /* Start of white strip in TA mode in mm (y) */ 0, 48, 96, /* RGB CCD Line-distance correction in pixel */ 8, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x2a, 0x0c, 0x2e, 0x06, 0x2d, 0x07}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_STOP /* Which flags are needed for this scanner? */ /* Based on data from Jakub Dvo?ák . */ }; static GT68xx_Model mustek_1200ta_model = { "mustek-bearpaw-1200-ta", /* Name */ "Mustek", /* Device vendor string */ "BearPaw 1200 TA", /* Device model name */ "A1fw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (8.4), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (6.9), /* Start of black mark in mm (x) */ SANE_FIX (98.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (108.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (37.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (163.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (95.0), /* Start of white strip in TA mode in mm (y) */ 32, 16, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x2a, 0x0c, 0x2e, 0x06, 0x2d, 0x07}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ 0 /* Which flags are needed for this scanner? */ /* Setup for 1200 TA */ }; static GT68xx_Model mustek_1200cuplus_model = { "mustek-bearpaw-1200-cu-plus", /* Name */ "Mustek", /* Device vendor string */ "Bearpaw 1200 CU Plus", /* Device model name */ "PS1Dfw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (13.0), /* Start of scan area in mm (y) */ SANE_FIX (217.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (9.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x14, 0x07, 0x14, 0x07, 0x14, 0x07}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_STOP /* Which flags are needed for this scanner? */ /* Tested by Hamersky Robert r.hamersky at utanet.at */ }; static GT68xx_Model mustek_1200cuplus2_model = { "mustek-bearpaw-1200-cu-plus-2", /* Name */ "Mustek", /* Device vendor string */ "Bearpaw 1200 CU Plus", /* Device model name */ "PS1Gfw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (4.0), /* Start of scan area in mm (x) */ SANE_FIX (13.0), /* Start of scan area in mm (y) */ SANE_FIX (217.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (5.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x19, 0x03, 0x1b, 0x05, 0x19, 0x03}, /* Default offset/gain */ {0xb0, 0xb0, 0xb0}, /* Default exposure parameters */ SANE_FIX (1.5), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_STOP /* Which flags are needed for this scanner? */ /* Tested by hmg */ }; static GT68xx_Model mustek_2400cuplus_model = { "mustek-bearpaw-2400-cu-plus", /* Name */ "Mustek", /* Device vendor string */ "BearPaw 2400 CU Plus", /* Device model name */ "PS2Dfw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 2400, /* maximum motor resolution */ 1200, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {1200, 600, 300, 200, 150, 100, 50, 0}, /* possible x-resolutions */ {2400, 1200, 600, 300, 200, 150, 100, 50, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (2.0), /* Start of scan area in mm (x) */ SANE_FIX (13.0), /* Start of scan area in mm (y) */ SANE_FIX (217.0), /* Size of scan area in mm (x) */ SANE_FIX (300.0), /* Size of scan area in mm (y) */ SANE_FIX (4.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x15, 0x08, 0x12, 0x05, 0x12, 0x05}, /* Default offset/gain */ {0x2a0, 0x1ab, 0x10d}, /* Default exposure parameters */ SANE_FIX (1.5), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_STOP /* Which flags are needed for this scanner? */ /* Setup and tested */ }; /* Seems that Mustek ScanExpress 1200 UB Plus, the Mustek BearPaw 1200 CU * and lots of other scanners have the same USB identifier. */ static GT68xx_Model mustek_1200cu_model = { "mustek-bearpaw-1200-cu", /* Name */ "Mustek", /* Device vendor string */ "BearPaw 1200 CU", /* Device model name */ "PS1fw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6801_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 600, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (13.0), /* Start of scan area in mm (y) */ SANE_FIX (217.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (4.2), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x13, 0x04, 0x15, 0x06, 0x0f, 0x02}, /* Default offset/gain */ {0x150, 0x150, 0x150}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ 0 /* Which flags are needed for this scanner? */ /* Setup and tested */ }; static GT68xx_Model mustek_scanexpress1200ubplus_model = { "mustek-scanexpress-1200-ub-plus", /* Name */ "Mustek", /* Device vendor string */ "ScanExpress 1200 UB Plus", /* Device model name */ "SBfw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6801_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (15.5), /* Start of scan area in mm (y) */ SANE_FIX (217.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (6.5), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x0f, 0x01, 0x15, 0x06, 0x13, 0x04}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ 0 /* Which flags are needed for this scanner? */ /* Setup and tested */ }; static GT68xx_Model mustek_scanexpress1248ub_model = { "mustek-scanexpress-1248-ub", /* Name */ "Mustek", /* Device vendor string */ "ScanExpress 1248 UB", /* Device model name */ "SBSfw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (4.0), /* Start of scan area in mm (x) */ SANE_FIX (14.5), /* Start of scan area in mm (y) */ SANE_FIX (217.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (9.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x1e, 0x08, 0x21, 0x0d, 0x1b, 0x05}, /* Default offset/gain */ {0x50, 0x50, 0x50}, /* Default exposure parameters */ SANE_FIX (1.5), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_STOP /* Which flags are needed for this scanner? */ /* tested by hmg */ }; static GT68xx_Model artec_ultima2000_model = { "artec-ultima-2000", /* Name */ "Artec", /* Device vendor string */ "Ultima 2000", /* Device model name */ "Gt680xfw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6801_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 200, 150, 100, 75, 50, 0}, /* possible x-resolutions */ {600, 300, 200, 150, 100, 75, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (2.0), /* Start of scan area in mm (x) */ SANE_FIX (7.0), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x0f, 0x01, 0x15, 0x06, 0x13, 0x04}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_MIRROR_X | GT68XX_FLAG_MOTOR_HOME | GT68XX_FLAG_OFFSET_INV /* Which flags are needed for this scanner? */ /* Setup for Cytron TCM MD 9385 */ }; static GT68xx_Model mustek_2400cu_model = { "mustek-bearpaw-2400-cu", /* Name */ "Mustek", /* Device vendor string */ "BearPaw 2400 CU", /* Device model name */ "PS2fw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6801_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 2400, /* maximum motor resolution */ 1200, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {1200, 600, 300, 150, 100, 50, 0}, /* possible x-resolutions */ {2400, 1200, 600, 300, 150, 100, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (13.5), /* Start of scan area in mm (y) */ SANE_FIX (215.0), /* Size of scan area in mm (x) */ SANE_FIX (296.9), /* Size of scan area in mm (y) */ SANE_FIX (5.5), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.9), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x0f, 0x01, 0x15, 0x06, 0x13, 0x04}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ 0 /* Which flags are needed for this scanner? */ /* basically tested, details may need tweaking */ }; static GT68xx_Model mustek_scanexpress2400usb_model = { "mustek-scanexpress-2400-usb", /* Name */ "Mustek", /* Device vendor string */ "ScanExpress 2400 USB", /* Device model name */ "P9fw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6801_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 1200, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 100, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (5.0), /* Start of scan area in mm (x) */ SANE_FIX (12.0), /* Start of scan area in mm (y) */ SANE_FIX (224.0), /* Size of scan area in mm (x) */ SANE_FIX (300.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (7.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 24, 12, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x12, 0x06, 0x0e, 0x03, 0x19, 0x25}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_UNTESTED | GT68XX_FLAG_SE_2400 /* Which flags are needed for this scanner? */ /* only partly tested, from "Fan Dan" */ }; static GT68xx_Model mustek_a3usb_model = { "mustek-scanexpress-a3-usb", /* Name */ "Mustek", /* Device vendor string */ "ScanExpress A3 USB", /* Device model name */ "A32fw.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 300, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 300, /* base x-res used to calculate geometry */ 300, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {300, 150, 75, 50, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (7.0), /* Start of scan area in mm (x) */ SANE_FIX (11.5), /* Start of scan area in mm (y) */ SANE_FIX (297.0), /* Size of scan area in mm (x) */ SANE_FIX (433.0), /* Size of scan area in mm (y) */ SANE_FIX (2.4), /* Start of white strip in mm (y) */ SANE_FIX (0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 5, 5, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x14, 0x05, 0x12, 0x05, 0x17, 0x0c}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (1.5), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_CIS_LAMP /* Which flags are needed for this scanner? */ /* Tested by hmg. This scanner is a bit strange as it uses a CIS sensor but it also has a lamp. So the lamp needs to be heated but CIS mode must be used for scanning and calibration. There is no TA for that scanner */ }; static GT68xx_Model lexmark_x73_model = { "lexmark-x73", /* Name */ "Lexmark", /* Device vendor string */ "X73", /* Device model name */ "OSLO3071b2.usb", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (6.519), /* Start of scan area in mm (x) */ SANE_FIX (12.615), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (297.0), /* Size of scan area in mm (y) */ SANE_FIX (1.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 32, 16, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x14, 0x07, 0x14, 0x07, 0x14, 0x07}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ 0 /* Which flags are needed for this scanner? */ /* When using automatic gain pictures are too dark. Only some ad hoc tests for lexmark x70 were done so far. WARNING: Don't use the Full scan option with the above settings, otherwise the sensor may bump at the end of the sledge and the scanner may be damaged! */ }; static GT68xx_Model plustek_op1248u_model = { "plustek-op1248u", /* Name */ "Plustek", /* Device vendor string */ "OpticPro 1248U", /* Device model name */ "ccd548.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &plustek_gt6801_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (216.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x1e, 0x24, 0x1d, 0x1f, 0x1d, 0x20}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* tested */ }; static GT68xx_Model plustek_u16b_model = { "plustek-u16b", /* Name */ "Plustek", /* Device vendor string */ "OpticPro U16B", /* Device model name */ "ccd68861.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (5.5), /* Start of scan area in mm (x) */ SANE_FIX (8.5), /* Start of scan area in mm (y) */ SANE_FIX (216.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x18, 0x16, 0x16, 0x0f, 0x17, 0x11}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_NO_POWER_STATUS | GT68XX_FLAG_NO_LINEMODE /* Which flags are needed for this scanner? */ /* Tested with a U16B by Henning Meier-Geinitz. 600 dpi is maximum vertically. Line mode does not work. That's a hardware/firmware issue. */ }; static GT68xx_Model plustek_ops12_model = { "plustek-opticpro-s12", /* Name */ "Plustek", /* Device vendor string */ "OpticPro S12", /* Device model name */ "ccd548.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x1c, 0x29, 0x1c, 0x2c, 0x1c, 0x2b}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* Seems to work */ }; static GT68xx_Model plustek_ops24_model = { "plustek-opticpro-s24", /* Name */ "Plustek", /* Device vendor string */ "OpticPro S24", /* Device model name */ "ccd569.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 200, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 200, 100, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (4.5), /* Start of scan area in mm (x) */ SANE_FIX (8.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x18, 0x1c, 0x16, 0x12, 0x18, 0x1c}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* Works (tested by Filip Kaluza). Based on genius Colorpage Vivid 1200 X. */ }; static GT68xx_Model genius_vivid4_model = { "genius-colorpage-vivid4", /* Name */ "Genius", /* Device vendor string */ "ColorPage Vivid 4", /* Device model name */ "ccd68861.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (5.5), /* Start of scan area in mm (x) */ SANE_FIX (8.5), /* Start of scan area in mm (y) */ SANE_FIX (216.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x18, 0x16, 0x16, 0x0f, 0x17, 0x11}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_NO_POWER_STATUS | GT68XX_FLAG_NO_LINEMODE /* Which flags are needed for this scanner? */ /* This scanner seems to be very similar to Plustelk U16B and is reported to work. */ }; static GT68xx_Model genius_vivid3x_model = { "genius-colorpage-vivid3x", /* Name */ "Genius", /* Device vendor string */ "Colorpage Vivid3x", /* Device model name */ "ccd548.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &plustek_gt6801_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x1c, 0x29, 0x1c, 0x2c, 0x1c, 0x2b}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* Tested to some degree, based on the Plustek OpticPro 1248U */ }; static GT68xx_Model genius_vivid4x_model = { "genius-colorpage-vivid4x", /* Name */ "Genius", /* Device vendor string */ "Colorpage Vivid4x", /* Device model name */ "ccd548.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x1c, 0x29, 0x1c, 0x2c, 0x1c, 0x2b}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* Is reported to work, copied from 3x, some values from Claudio Filho */ }; static GT68xx_Model genius_vivid4xe_model = { "genius-colorpage-vivid4xe", /* Name */ "Genius", /* Device vendor string */ "Colorpage Vivid4xe", /* Device model name */ "ccd548.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x1c, 0x29, 0x1c, 0x2c, 0x1c, 0x2b}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* tested a bit */ }; static GT68xx_Model genius_vivid3xe_model = { "genius-colorpage-vivid3xe", /* Name */ "Genius", /* Device vendor string */ "Colorpage Vivid3xe", /* Device model name */ "ccd548.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &plustek_gt6801_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 600, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x1c, 0x29, 0x1c, 0x2c, 0x1c, 0x2b}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* mostly untested, based on the Genius Vivid3x */ }; static GT68xx_Model genius_vivid1200x_model = { "genius-colorpage-vivid-1200-x", /* Name */ "Genius", /* Device vendor string */ "Colorpage Vivid 1200 X", /* Device model name */ "ccd569.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 200, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 200, 100, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (4.5), /* Start of scan area in mm (x) */ SANE_FIX (8.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x18, 0x1c, 0x16, 0x12, 0x18, 0x1c}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* Tested. */ }; static GT68xx_Model genius_vivid1200xe_model = { "genius-colorpage-vivid-1200-xe", /* Name */ "Genius", /* Device vendor string */ "Colorpage Vivid 1200 XE", /* Device model name */ "ccd569.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_TRUE, /* Use base_ydpi for all resolutions */ {600, 300, 200, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 200, 100, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (4.5), /* Start of scan area in mm (x) */ SANE_FIX (8.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x18, 0x1c, 0x16, 0x12, 0x18, 0x1c}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_ALWAYS_LINEMODE /* Which flags are needed for this scanner? */ /* Tested by hmg */ }; static GT68xx_Model iriscan_express_2_model = { "iriscan-express-2", /* Name */ "Iris", /* Device vendor string */ "Iriscan Express 2", /* Device model name */ "cism216.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_sheetfed_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ /* values based on analyze of the firmware */ {600, 400, 300, 200, 150, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 400, 300, 200, 150, 100, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (1.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (18.0), /* Start of white strip in mm (y) */ SANE_FIX (21.72), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x22, 0x0c, 0x22, 0x0a, 0x24, 0x09}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_POWER_STATUS | GT68XX_FLAG_SHEET_FED | GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_HAS_CALIBRATE }; static GT68xx_Model plustek_opticslim_m12_model = { "plustek-opticslim-m12", /* Name */ "Plustek", /* Device vendor string */ "OpticSlim M12", /* Device model name */ "cism216.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_sheetfed_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {600, 400, 300, 200, 150, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 400, 300, 200, 150, 100, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (1.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (18.0), /* Start of white strip in mm (y) */ SANE_FIX (21.72), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x24, 0x0a, 0x23, 0x0f, 0x23, 0x0b}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_POWER_STATUS | GT68XX_FLAG_SHEET_FED | GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_HAS_CALIBRATE }; static GT68xx_Model genius_sf600_model = { "genius-SF600", /* Name */ "Genius", /* Device vendor string */ "ColorPage SF600", /* Device model name */ "cism216.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_sheetfed_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {600, 300, 200, 150, 100, 0}, /* possible x-resolutions */ {600, 300, 200, 150, 100, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (1.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (18.0), /* Start of white strip in mm (y) */ SANE_FIX (21.72), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ {0x24, 0x0a, 0x23, 0x0f, 0x23, 0x0b}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_NO_POWER_STATUS | GT68XX_FLAG_UNTESTED | GT68XX_FLAG_SHEET_FED | GT68XX_FLAG_OFFSET_INV | GT68XX_FLAG_HAS_CALIBRATE | GT68XX_FLAG_NO_STOP }; /* Untested but should work according to Ryan Reading . Based on Plustek M12 */ static GT68xx_Model plustek_opticslim1200_model = { "plustek-opticslim-1200", /* Name */ "Plustek", /* Device vendor string */ "OpticSlim 1200", /* Device model name */ "cism216.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 600, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 600, /* base x-res used to calculate geometry */ 600, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {600, 300, 150, 75, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (1.0), /* Start of scan area in mm (x) */ SANE_FIX (9.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (140.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x15, 0x09, 0x18, 0x11, 0x16, 0x0c}, /* Default offset/gain */ {0x157, 0x157, 0x157}, /* Default exposure parameters */ SANE_FIX (2.0), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ 0 }; static GT68xx_Model plustek_opticslim2400_model = { "plustek-opticslim-2400", /* Name */ "Plustek", /* Device vendor string */ "OpticSlim 2400", /* Device model name */ "cis3R5B1.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 2400, /* maximum motor resolution */ 1200, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {1200, 600, 300, 150, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 100, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (1.0), /* Start of scan area in mm (x) */ SANE_FIX (9.5), /* Start of scan area in mm (y) */ SANE_FIX (217.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x15, 0x09, 0x18, 0x11, 0x16, 0x0c}, /* Default offset/gain */ {0x300, 0x300, 0x300}, /* Default exposure parameters */ SANE_FIX (1.5), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ 0 /* By Detlef Gausepohl . Fixed and tested by hmg. */ }; static GT68xx_Model visioneer_onetouch_7300_model = { "visioneer-onetouch-7300", /* Name */ "Visioneer", /* Device vendor string */ "OneTouch 7300", /* Device model name */ "Cis3r5b1.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 1200, /* maximum motor resolution */ 1200, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {1200, 600, 300, 150, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 100, 50, 0}, /* possible y-resolutions */ {12, 8, 0}, /* possible depths in gray mode */ {12, 8, 0}, /* possible depths in color mode */ SANE_FIX (1.0), /* Start of scan area in mm (x) */ SANE_FIX (9.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (140.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x15, 0x09, 0x18, 0x11, 0x16, 0x0c}, /* Default offset/gain */ {0x80, 0x80, 0x80}, /* Default exposure parameters */ SANE_FIX (1.5), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ 0 }; /* Tested by Jason Novek. Based on Plustek OpticSlim 2400. */ static GT68xx_Model genius_colorpageslim_1200_model = { "genius-colorpageslim-1200", /* Name */ "Genius", /* Device vendor string */ "ColorPage Slim 1200", /* Device model name */ "Cis3r5b1.fw", /* Name of the firmware file */ SANE_FALSE, /* Dynamic allocation flag */ &mustek_gt6816_command_set, /* Command set used by this scanner */ 1200, /* maximum optical sensor resolution */ 2400, /* maximum motor resolution */ 1200, /* base x-res used to calculate geometry */ 1200, /* base y-res used to calculate geometry */ 1200, /* if ydpi is equal or higher, disable backtracking */ SANE_FALSE, /* Use base_ydpi for all resolutions */ {1200, 600, 300, 150, 100, 50, 0}, /* possible x-resolutions */ {2400,1200, 600, 300, 150, 100, 50, 0}, /* possible y-resolutions */ {16, 12, 8, 0}, /* possible depths in gray mode */ {16, 12, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.5), /* Start of scan area in mm (x) */ SANE_FIX (8.0), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (9.5), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ 0, /* CCD distcance for CCD with 6 lines) */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ {0x19, 0x1a, 0x18, 0x14, 0x18, 0x12}, /* Default offset/gain */ {0x548, 0x513, 0x48d}, /* Default exposure parameters */ SANE_FIX (1.5), /* Default gamma value */ SANE_TRUE, /* Is this a CIS scanner? */ GT68XX_FLAG_ALWAYS_LINEMODE | GT68XX_FLAG_SE_2400 }; /* tested by Aleksey Nedorezov */ static GT68xx_USB_Device_Entry gt68xx_usb_device_list[] = { {0x10000, 0x10000, &unknown_model}, /* used for yet unknown scanners */ {0x055f, 0x0218, &mustek_2400ta_model}, {0x055f, 0x0219, &mustek_2400taplus_model}, {0x055f, 0x021c, &mustek_1200cuplus_model}, {0x055f, 0x021b, &mustek_1200cuplus2_model}, {0x055f, 0x021d, &mustek_2400cuplus_model}, {0x055f, 0x021e, &mustek_1200ta_model}, {0x055f, 0x021f, &mustek_scanexpress1248ub_model}, {0x05d8, 0x4002, &mustek_1200cu_model}, {0x05d8, 0x4002, &mustek_scanexpress1200ubplus_model}, /* manual override */ {0x05d8, 0x4002, &artec_ultima2000_model}, /* manual override */ {0x05d8, 0x4002, &mustek_2400cu_model}, /* manual override */ {0x05d8, 0x4002, &mustek_scanexpress2400usb_model}, /* manual override */ {0x055f, 0x0210, &mustek_a3usb_model}, {0x055f, 0x021a, &mustek_2448taplus_model}, {0x043d, 0x002d, &lexmark_x73_model}, {0x07b3, 0x0400, &plustek_op1248u_model}, {0x07b3, 0x0401, &plustek_op1248u_model}, /* Same scanner, different id? */ {0x07b3, 0x0402, &plustek_u16b_model}, {0x07b3, 0x0403, &plustek_u16b_model}, /* two ids? 403 seems to be more common */ {0x07b3, 0x040b, &plustek_ops12_model}, {0x07b3, 0x040e, &plustek_ops24_model}, {0x07b3, 0x0412, &plustek_opticslim_m12_model}, {0x07b3, 0x0413, &plustek_opticslim1200_model}, {0x07b3, 0x0422, &plustek_opticslim2400_model}, {0x07b3, 0x045f, &iriscan_express_2_model}, {0x0458, 0x2011, &genius_vivid3x_model}, {0x0458, 0x2014, &genius_vivid4_model}, {0x0458, 0x2017, &genius_vivid3xe_model}, {0x0458, 0x201a, &genius_vivid4xe_model}, {0x0458, 0x201b, &genius_vivid4x_model}, {0x0458, 0x201d, &genius_vivid1200x_model}, {0x0458, 0x201f, &genius_vivid1200xe_model}, {0x0458, 0x2021, &genius_sf600_model}, {0x04a7, 0x0444, &visioneer_onetouch_7300_model}, {0x0458, 0x201E, &genius_colorpageslim_1200_model}, {0, 0, NULL} }; sane-backends-1.0.27/backend/mustek.h0000664000175000017500000002374012112021330014261 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang, 1998 Andreas Bolsch for extension to ScanExpress models version 0.5, 2000 - 2005 Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek and some Trust flatbed scanners with SCSI or proprietary interface. */ #ifndef mustek_h #define mustek_h #include "../include/sane/config.h" #include /* Some constants */ #define INQ_LEN 0x60 /* Length of SCSI inquiry */ #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define MUSTEK_CONFIG_FILE "mustek.conf" #define MAX_WAITING_TIME 60 /* How long to wait for scanner to become ready */ #define MAX_LINE_DIST 40 /* Extra lines needed for LD correction */ /* Flag values */ /* Scanner types */ #define MUSTEK_FLAG_THREE_PASS (1 << 0) /* three pass scanner */ #define MUSTEK_FLAG_PARAGON_1 (1 << 1) /* Paragon series I scanner */ #define MUSTEK_FLAG_PARAGON_2 (1 << 2) /* Paragon series II(A4) scanner */ #define MUSTEK_FLAG_SE (1 << 3) /* ScanExpress scanner */ #define MUSTEK_FLAG_SE_PLUS (1 << 4) /* ScanExpress Plus scanner */ #define MUSTEK_FLAG_PRO (1 << 5) /* Professional series scanner */ #define MUSTEK_FLAG_N (1 << 6) /* N-type scanner (non SCSI) */ #define MUSTEK_FLAG_SCSI_PP (1 << 22) /* SCSI over parallel (e.g. 600 II EP) */ /* Additional equipment */ #define MUSTEK_FLAG_ADF (1 << 7) /* automatic document feeder */ #define MUSTEK_FLAG_ADF_READY (1 << 8) /* paper present */ #define MUSTEK_FLAG_TA (1 << 9) /* transparency adapter */ /* Line-distance correction */ #define MUSTEK_FLAG_LD_NONE (1 << 10) /* no line-distance corr */ #define MUSTEK_FLAG_LD_BLOCK (1 << 11) /* blockwise LD corr */ #define MUSTEK_FLAG_LD_N1 (1 << 12) /* LD corr for N-type v1 */ #define MUSTEK_FLAG_LD_N2 (1 << 13) /* LD corr for N-type v2 */ /* Manual fixes */ #define MUSTEK_FLAG_LD_FIX (1 << 14) /* need line-distance fix? */ #define MUSTEK_FLAG_LINEART_FIX (1 << 15) /* lineart fix/hack */ #define MUSTEK_FLAG_USE_EIGHTS (1 << 16) /* use 1/8" lengths */ #define MUSTEK_FLAG_FORCE_GAMMA (1 << 17) /* force gamma table upload */ #define MUSTEK_FLAG_ENLARGE_X (1 << 18) /* need to enlarge x-res */ #define MUSTEK_FLAG_COVER_SENSOR (1 << 19) /* scanner can detect open cover */ #define MUSTEK_FLAG_USE_BLOCK (1 << 20) /* use blockmode */ #define MUSTEK_FLAG_LEGAL_SIZE (1 << 21) /* scanner has legal size */ #define MUSTEK_FLAG_NO_BACKTRACK (1 << 21) /* scanner has legal size */ /* Source values: */ #define MUSTEK_SOURCE_FLATBED 0 #define MUSTEK_SOURCE_ADF 1 #define MUSTEK_SOURCE_TA 2 /* Mode values: */ #define MUSTEK_MODE_LINEART (1 << 0) /* grayscale 1 bit / pixel */ #define MUSTEK_MODE_GRAY (1 << 1) /* grayscale 8 bits / pixel */ #define MUSTEK_MODE_COLOR (1 << 2) /* color 24 bits / pixel */ #define MUSTEK_MODE_HALFTONE (1 << 3) /* use dithering */ /* Color band codes: */ #define MUSTEK_CODE_GRAY 0 #define MUSTEK_CODE_RED 1 #define MUSTEK_CODE_GREEN 2 #define MUSTEK_CODE_BLUE 3 /* SCSI commands that the Mustek scanners understand (or not): */ #define MUSTEK_SCSI_TEST_UNIT_READY 0x00 #define MUSTEK_SCSI_REQUEST_SENSE 0x03 #define MUSTEK_SCSI_AREA_AND_WINDOWS 0x04 #define MUSTEK_SCSI_READ_SCANNED_DATA 0x08 #define MUSTEK_SCSI_GET_IMAGE_STATUS 0x0f #define MUSTEK_SCSI_ADF_AND_BACKTRACK 0x10 #define MUSTEK_SCSI_CCD_DISTANCE 0x11 #define MUSTEK_SCSI_INQUIRY 0x12 #define MUSTEK_SCSI_MODE_SELECT 0x15 #define MUSTEK_SCSI_START_STOP 0x1b #define MUSTEK_SCSI_SET_WINDOW 0x24 #define MUSTEK_SCSI_GET_WINDOW 0x25 #define MUSTEK_SCSI_READ_DATA 0x28 #define MUSTEK_SCSI_SEND_DATA 0x2a #define MUSTEK_SCSI_LOOKUP_TABLE 0x55 /* Convenience macros */ #if defined(MIN) #undef MIN #endif #if defined(MAX) #undef MAX #endif #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /* Copy values to memory ('L' = little endian, 'B' = big endian */ #define STORE16L(cp,v) \ do { \ int value = (v); \ \ *(cp)++ = (value >> 0) & 0xff; \ *(cp)++ = (value >> 8) & 0xff; \ } while (0) #define STORE16B(cp,v) \ do { \ int value = (v); \ \ *(cp)++ = (value >> 8) & 0xff; \ *(cp)++ = (value >> 0) & 0xff; \ } while (0) #define STORE32B(cp,v) \ do { \ long int value = (v); \ \ *(cp)++ = (value >> 24) & 0xff; \ *(cp)++ = (value >> 16) & 0xff; \ *(cp)++ = (value >> 8) & 0xff; \ *(cp)++ = (value >> 0) & 0xff; \ } while (0) /* declarations */ enum Mustek_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_FAST_GRAY_MODE, OPT_RESOLUTION, OPT_BIT_DEPTH, OPT_SPEED, OPT_SOURCE, OPT_PREVIEW, OPT_FAST_PREVIEW, OPT_LAMP_OFF_TIME, OPT_LAMP_OFF_BUTTON, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_BRIGHTNESS_R, OPT_BRIGHTNESS_G, OPT_BRIGHTNESS_B, OPT_CONTRAST, OPT_CONTRAST_R, OPT_CONTRAST_G, OPT_CONTRAST_B, OPT_CUSTOM_GAMMA, /* use custom gamma tables? */ /* The gamma vectors MUST appear in the order gray, red, green, blue. */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_QUALITY_CAL, OPT_HALFTONE_DIMENSION, OPT_HALFTONE_PATTERN, /* must come last: */ NUM_OPTIONS }; typedef struct Mustek_Device { struct Mustek_Device *next; SANE_String name; SANE_Device sane; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; /* scan area when transparency adapter is used: */ SANE_Range x_trans_range; SANE_Range y_trans_range; SANE_Word flags; /* length of gamma table, probably always <= 4096 for the SE */ SANE_Int gamma_length; /* values actually used by scanner, not necessarily the desired! */ SANE_Int bpl, lines; /* what is needed for calibration (ScanExpress and Pro series) */ struct { SANE_Int bytes; SANE_Int lines; SANE_Byte *buffer; SANE_Word *line_buffer[3]; } cal; /* current and maximum buffer size used by the backend */ /* the buffer sent to the scanner is actually half of this size */ SANE_Int buffer_size; SANE_Int max_buffer_size; /* maximum size scanned in one block and corresponding lines */ SANE_Int max_block_buffer_size; SANE_Int lines_per_block; SANE_Byte *block_buffer; /* firmware format: 0 = old, MUSTEK at pos 8; 1 = new, MUSTEK at pos 36 */ SANE_Int firmware_format; /* firmware revision system: 0 = old, x.yz; 1 = new, Vxyz */ SANE_Int firmware_revision_system; } Mustek_Device; typedef struct Mustek_Scanner { /* all the state needed to define a scan request: */ struct Mustek_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Int gamma_table[4][256]; SANE_Int *halftone_pattern; SANE_Bool custom_halftone_pattern; SANE_Int halftone_pattern_type; SANE_Bool scanning; SANE_Bool cancelled; SANE_Int pass; /* pass number */ SANE_Int line; /* current line number */ SANE_Parameters params; /* Parsed option values and variables that are valid only during actual scanning: */ SANE_Word mode; SANE_Bool one_pass_color_scan; SANE_Int resolution_code; int fd; /* SCSI filedescriptor */ SANE_Pid reader_pid; /* process id of reader */ int reader_fds; /* OS/2: pipe write handler for reader */ int pipe; /* pipe to reader process */ long start_time; /* at this time the scan started */ SANE_Word total_bytes; /* bytes transmitted by sane_read */ SANE_Word total_lines; /* lines transmitted to sane_read pipe */ /* scanner dependent/low-level state: */ Mustek_Device *hw; /* line-distance correction related state: */ struct { SANE_Int color; /* first color appearing in read data */ SANE_Int max_value; SANE_Int peak_res; SANE_Int dist[3]; /* line distance */ SANE_Int index[3]; /* index for R/G/B color assignment */ SANE_Int quant[3]; /* for resolution correction */ SANE_Int saved[3]; /* number of saved color lines */ /* these are used for SE, MFS and N line-distance correction: */ SANE_Byte *buf[3]; /* these are used for N line-distance correction only: */ SANE_Int ld_line; /* line # currently processed in ld-correction */ SANE_Int lmod3; /* line # modulo 3 */ } ld; } Mustek_Scanner; #endif /* mustek_h */ sane-backends-1.0.27/backend/sp15c.conf.in0000664000175000017500000000001212112021330014772 00000000000000scsi FCPA sane-backends-1.0.27/backend/ibm.h0000664000175000017500000002264412112021330013522 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef ibm_h #define ibm_h 1 #include #include "../include/sane/config.h" /* defines for scan_image_mode field */ #define IBM_BINARY_MONOCHROME 0 #define IBM_DITHERED_MONOCHROME 1 #define IBM_GRAYSCALE 2 /* defines for paper field */ #define IBM_PAPER_USER_DEFINED 0 #define IBM_PAPER_A3 1 #define IBM_PAPER_A4 2 #define IBM_PAPER_A4L 3 #define IBM_PAPER_A5 4 #define IBM_PAPER_A5L 5 #define IBM_PAPER_A6 6 #define IBM_PAPER_B4 7 #define IBM_PAPER_B5 8 #define IBM_PAPER_LEGAL 9 #define IBM_PAPER_LETTER 10 /* sizes for mode parameter's base_measurement_unit */ #define INCHES 0 #define MILLIMETERS 1 #define POINTS 2 #define DEFAULT_MUD 1200 #define MEASUREMENTS_PAGE (SANE_Byte)(0x03) /* Mode Page Control */ #define PC_CURRENT 0x00 #define PC_CHANGE 0x40 #define PC_DEFAULT 0x80 #define PC_SAVED 0xc0 static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, 0 }; static const SANE_String_Const paper_list[] = { "User", "A3", "A4", "A4R", "A5", "A5R", "A6", "B4", "B5", "Legal", "Letter", 0 }; #define PAPER_A3_W 14032 #define PAPER_A3_H 19842 #define PAPER_A4_W 9921 #define PAPER_A4_H 14032 #define PAPER_A4R_W 14032 #define PAPER_A4R_H 9921 #define PAPER_A5_W 7016 #define PAPER_A5_H 9921 #define PAPER_A5R_W 9921 #define PAPER_A5R_H 7016 #define PAPER_A6_W 4960 #define PAPER_A6_H 7016 #define PAPER_B4_W 11811 #define PAPER_B4_H 16677 #define PAPER_B5_W 8598 #define PAPER_B5_H 12142 #define PAPER_LEGAL_W 10200 #define PAPER_LEGAL_H 16800 #define PAPER_LETTER_W 10200 #define PAPER_LETTER_H 13200 static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const SANE_Range ibm2456_res_range = { 100, /* minimum */ 600, /* maximum */ 0 /* quantization */ }; static const SANE_Range default_x_range = { 0, /* minimum */ /* (SANE_Word) ( * DEFAULT_MUD), maximum */ 14032, /* maximum (found empirically for Gray mode) */ /* in Lineart mode it works till 14062 */ 2 /* quantization */ }; static const SANE_Range default_y_range = { 0, /* minimum */ /* (SANE_Word) (14 * DEFAULT_MUD), maximum */ 20410, /* maximum (found empirically) */ 2 /* quantization */ }; static inline void _lto2b(SANE_Int val, SANE_Byte *bytes) { bytes[0] = (val >> 8) & 0xff; bytes[1] = val & 0xff; } static inline void _lto3b(SANE_Int val, SANE_Byte *bytes) { bytes[0] = (val >> 16) & 0xff; bytes[1] = (val >> 8) & 0xff; bytes[2] = val & 0xff; } static inline void _lto4b(SANE_Int val, SANE_Byte *bytes) { bytes[0] = (val >> 24) & 0xff; bytes[1] = (val >> 16) & 0xff; bytes[2] = (val >> 8) & 0xff; bytes[3] = val & 0xff; } static inline SANE_Int _2btol(SANE_Byte *bytes) { SANE_Int rv; rv = (bytes[0] << 8) | bytes[1]; return (rv); } static inline SANE_Int _3btol(SANE_Byte *bytes) { SANE_Int rv; rv = (bytes[0] << 16) | (bytes[1] << 8) | bytes[2]; return (rv); } static inline SANE_Int _4btol(SANE_Byte *bytes) { SANE_Int rv; rv = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; return (rv); } typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_X_RESOLUTION, OPT_Y_RESOLUTION, OPT_ADF, OPT_GEOMETRY_GROUP, OPT_PAPER, /* predefined formats */ OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, /* must come last: */ NUM_OPTIONS } Ibm_Option; typedef struct Ibm_Info { SANE_Range xres_range; SANE_Range yres_range; SANE_Range x_range; SANE_Range y_range; SANE_Range brightness_range; SANE_Range contrast_range; SANE_Int xres_default; SANE_Int yres_default; SANE_Int image_mode_default; SANE_Int paper_default; SANE_Int brightness_default; SANE_Int contrast_default; SANE_Int adf_default; SANE_Int bmu; SANE_Int mud; } Ibm_Info; typedef struct Ibm_Device { struct Ibm_Device *next; SANE_Device sane; Ibm_Info info; } Ibm_Device; typedef struct Ibm_Scanner { /* all the state needed to define a scan request: */ struct Ibm_Scanner *next; int fd; /* SCSI filedescriptor */ SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; /* scanner dependent/low-level state: */ Ibm_Device *hw; SANE_Int xres; SANE_Int yres; SANE_Int ulx; SANE_Int uly; SANE_Int width; SANE_Int length; SANE_Int brightness; SANE_Int contrast; SANE_Int image_composition; SANE_Int bpp; SANE_Bool reverse; /* next lines by mf */ SANE_Int adf_state; #define ADF_UNUSED 0 /* scan from flatbed, not ADF */ #define ADF_ARMED 1 /* scan from ADF, everything's set up */ #define ADF_CLEANUP 2 /* eject paper from ADF on close */ /* end lines by mf */ size_t bytes_to_read; int scanning; } Ibm_Scanner; struct inquiry_data { SANE_Byte devtype; SANE_Byte byte2; SANE_Byte byte3; SANE_Byte byte4; SANE_Byte byte5; SANE_Byte res1[2]; SANE_Byte flags; SANE_Byte vendor[8]; SANE_Byte product[8]; SANE_Byte revision[4]; SANE_Byte byte[60]; }; #define IBM_WINDOW_DATA_SIZE 320 struct ibm_window_data { /* header */ SANE_Byte reserved[6]; SANE_Byte len[2]; /* data */ SANE_Byte window_id; /* must be zero */ SANE_Byte reserved0; SANE_Byte x_res[2]; SANE_Byte y_res[2]; SANE_Byte x_org[4]; SANE_Byte y_org[4]; SANE_Byte width[4]; SANE_Byte length[4]; SANE_Byte brightness; SANE_Byte threshold; SANE_Byte contrast; SANE_Byte image_comp; /* image composition (data type) */ SANE_Byte bits_per_pixel; SANE_Byte halftone_code; /* halftone_pattern[0] in ricoh.h */ SANE_Byte halftone_id; /* halftone_pattern[1] in ricoh.h */ SANE_Byte pad_type; SANE_Byte bit_ordering[2]; SANE_Byte compression_type; SANE_Byte compression_arg; SANE_Byte res3[6]; /* Vendor Specific parameter byte(s) */ /* Ricoh specific, follow the scsi2 standard ones */ SANE_Byte byte1; SANE_Byte byte2; SANE_Byte mrif_filtering_gamma_id; SANE_Byte byte3; SANE_Byte byte4; SANE_Byte binary_filter; SANE_Byte reserved2[18]; SANE_Byte reserved3[256]; }; struct measurements_units_page { SANE_Byte page_code; /* 0x03 */ SANE_Byte parameter_length; /* 0x06 */ SANE_Byte bmu; SANE_Byte res1; SANE_Byte mud[2]; SANE_Byte res2[2]; /* anybody know what `COH' may mean ??? */ /* next 4 lines by mf */ SANE_Byte adf_page_code; SANE_Byte adf_parameter_length; SANE_Byte adf_control; SANE_Byte res3[5]; }; struct mode_pages { SANE_Byte page_code; SANE_Byte parameter_length; SANE_Byte rest[14]; /* modified by mf; it was 6; see above */ #if 0 SANE_Byte more_pages[243]; /* maximum size 255 bytes (incl header) */ #endif }; #endif /* ibm_h */ sane-backends-1.0.27/backend/s9036.c0000664000175000017500000010140212775312261013545 00000000000000/* sane - Scanner Access Now Easy. This file (C) 1997 Ingo Schneider This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. This file implements a SANE backend for Siemens 9036 flatbed scanners. */ #include "../include/sane/config.h" #include #include #include #include #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "s9036.h" #define BACKEND_NAME s9036 #include "../include/sane/sanei_backend.h" #undef Byte #define Byte SANE_Byte static const SANE_Device **devlist = NULL; static int num_devices; static S9036_Device *s9036_devices; /* sets loc_s bytes long value at offset loc in scsi command to value size */ static void set_size (Byte * loc, int loc_s, size_t size) { int i; for (i = 0; i < loc_s; i++) { loc[loc_s - i - 1] = (size >> (i * 8)) & 0xff; } } static long reserve_unit (int fd) { const Byte scsi_reserve[] = { 0x16, 0x00, 0x00, 0x00, 0x00, 0x00 }; DBG (3, "reserve_unit()\n"); return sanei_scsi_cmd (fd, scsi_reserve, sizeof (scsi_reserve), 0, 0); } static long release_unit (int fd) { const Byte scsi_release[] = { 0x17, 0x00, 0x00, 0x00, 0x00, 0x00 }; DBG (3, "release_unit()\n"); return sanei_scsi_cmd (fd, scsi_release, sizeof (scsi_release), 0, 0); } static SANE_Status test_ready (int fd) { static const Byte scsi_test_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; SANE_Status status; int try; for (try = 0; try < 1000; ++try) { DBG (3, "test_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, scsi_test_ready, sizeof (scsi_test_ready), 0, 0); switch (status) { case SANE_STATUS_DEVICE_BUSY: usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; default: DBG (1, "test_ready: test unit ready failed (%s)\n", sane_strstatus (status)); return status; } } DBG (1, "test_ready: timed out after %d attempts\n", try); return SANE_STATUS_IO_ERROR; } static SANE_Status sense_handler (int scsi_fd, u_char *result, void *arg) { scsi_fd = scsi_fd; arg = arg; /* silence compilation warnings */ if (result[0]) { DBG (0, "sense_handler() : sense code = %02x\n", result[0]); return SANE_STATUS_IO_ERROR; } else { return SANE_STATUS_GOOD; } } static SANE_Status stop_scan (int fd) { fd = fd; /* silence compilation warnings */ /* XXX don't know how to stop the scanner. To be tested ! */ #if 0 const Byte scsi_rewind[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; DBG (1, "Trying to stop scanner...\n"); return sanei_scsi_cmd (fd, scsi_rewind, sizeof (scsi_rewind), 0, 0); #else return SANE_STATUS_GOOD; #endif } static SANE_Status start_scan (int fd, SANE_Bool cont) { struct { /* Command */ Byte cmd; Byte lun; Byte res[2]; Byte tr_len; Byte ctrl; /* Data */ Byte wid; } scsi_start_scan; memset (&scsi_start_scan, 0, sizeof (scsi_start_scan)); scsi_start_scan.cmd = 0x1b; scsi_start_scan.tr_len = 1; scsi_start_scan.wid = 0; scsi_start_scan.ctrl = (cont == SANE_TRUE) ? 0x80 : 0x00; DBG (1, "Starting scanner ...\n"); return sanei_scsi_cmd (fd, &scsi_start_scan, sizeof (scsi_start_scan), 0, 0); } static void wait_ready (int fd) { # define WAIT_READY_READ_SIZE 4 const Byte scsi_read[] = { 0x28, 0x00, /* opcode, lun */ 0x80, /* data type 80 == read time left */ 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00, WAIT_READY_READ_SIZE, /* transfer length */ 0x00, /* control byte */ }; Byte result[WAIT_READY_READ_SIZE]; size_t size = WAIT_READY_READ_SIZE; SANE_Status status; while (1) { status = sanei_scsi_cmd (fd, scsi_read, sizeof (scsi_read), result, &size); if (status != SANE_STATUS_GOOD || size != WAIT_READY_READ_SIZE) { /* Command failed, the assembler code of the windows scan library ignores this condition, and so do I */ break; } else { /* left is the amount of seconds left till the scanner is ready * 100 */ int left = result[2] * 256 + result[3]; DBG (1, "wait_ready() : %d left...\n", left); if (!left) break; /* We delay only for half the given time */ else if (left < 200) usleep (left * 5000); else sleep (left / 200); } } return; } static SANE_Status get_read_sizes (int fd, int *lines_available, int *bpl, int *total_lines) { # define GET_READ_SIZES_READ_SIZE 24 const Byte scsi_read[] = { 0x28, 0x00, /* opcode, lun */ 0x81, /* data type 81 == read time left */ 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00, GET_READ_SIZES_READ_SIZE, /* transfer length */ 0x00, /* control byte */ }; Byte result[GET_READ_SIZES_READ_SIZE]; size_t size = GET_READ_SIZES_READ_SIZE; SANE_Status status; status = sanei_scsi_cmd (fd, scsi_read, sizeof (scsi_read), result, &size); if (status != SANE_STATUS_GOOD || size != GET_READ_SIZES_READ_SIZE) { /* Command failed */ return SANE_STATUS_IO_ERROR; } else { *lines_available = result[14] * 256 + result[15]; *bpl = result[12] * 256 + result[13]; if (total_lines) *total_lines = result[10] * 256 + result[11]; } DBG (1, "get_read_sizes() : %d of %d, %d\n", *lines_available, total_lines ? *total_lines : -1, *bpl); return SANE_STATUS_GOOD; } static SANE_Status set_window (S9036_Scanner * s) /* This function sets and sends the window for scanning */ { double pixels_per_mm = (double) s->val[OPT_RESOLUTION] / MM_PER_INCH; SANE_Bool auto_bright = !(s->opt[OPT_BRIGHT_ADJUST].cap & SANE_CAP_INACTIVE); SANE_Bool auto_contr = !(s->opt[OPT_CONTR_ADJUST].cap & SANE_CAP_INACTIVE); /* ranges down 255 (dark) down to 1(bright) */ int brightness = auto_bright ? 0 : (SANE_UNFIX (s->val[OPT_BRIGHTNESS]) * -1.27 + 128.5); /* ranges from 1 (little contrast) up to 255 (much contrast) */ int contrast = auto_contr ? 0 : (SANE_UNFIX (s->val[OPT_CONTRAST]) * 1.27 + 128.5); /* ranges from 40 (dark) down to 0 (bright) */ int bright_adjust = auto_bright ? 20 - s->val[OPT_BRIGHT_ADJUST] : 0; /* ranges from 20 (little contrast) down to -20 = 235 (much contrast) */ int contr_adjust = auto_contr ? (256 - s->val[OPT_CONTR_ADJUST]) % 256 : 0; /* Warning ! The following structur SEEMS to be an valid SCSI-2 SET_WINDOW command. But e.g. the limits for the window are only 2 Bytes instead of 4. The scanner was built at about 1990, so SCSI-2 wasn't available for development... */ struct { Byte cmd; Byte lun; Byte re1[4]; Byte tr_len[3]; Byte ctrl; Byte re2[6]; Byte wd_len[2]; struct { Byte wid; Byte autobit; Byte x_axis_res[2]; Byte y_axis_res[2]; Byte x_axis_ul[2]; Byte y_axis_ul[2]; Byte wwidth[2]; Byte wlength[2]; Byte contrast; Byte threshold; Byte brightness; Byte image_comp; Byte bpp; Byte ht_pattern; Byte rif_padding; Byte three; Byte null1[2]; Byte null2[8]; Byte null_eins; Byte eins_null; Byte contr_adjust; Byte bright_adjust; Byte null3; } wd; } cmd; DBG (3, "Setting parameters: bpp %d, res %d, bri %d, con %d, bad %d, cad %d\n", s->val[OPT_DEPTH], s->val[OPT_RESOLUTION], brightness, contrast, bright_adjust, contr_adjust); memset (&cmd, 0, sizeof (cmd)); /* Commands and sizes. Original comment in German: Kommando und Groessen. */ cmd.cmd = 0x24; set_size (cmd.tr_len, 3, 37 + 8); set_size (cmd.wd_len, 2, 37); /* Resolution. Original comment in German: Aufloesung */ set_size (cmd.wd.x_axis_res, 2, s->val[OPT_RESOLUTION]); set_size (cmd.wd.y_axis_res, 2, s->val[OPT_RESOLUTION]); /* Scan window position/size. Original comment in German: Fensterposition / Groesse */ set_size (cmd.wd.x_axis_ul, 2, SANE_UNFIX (s->val[OPT_TL_X]) * pixels_per_mm + 0.5); set_size (cmd.wd.y_axis_ul, 2, SANE_UNFIX (s->val[OPT_TL_Y]) * pixels_per_mm + 0.5); set_size (cmd.wd.wwidth, 2, SANE_UNFIX (s->val[OPT_BR_X] - s->val[OPT_TL_X]) * pixels_per_mm + 0.5); set_size (cmd.wd.wlength, 2, SANE_UNFIX (s->val[OPT_BR_Y] - s->val[OPT_TL_Y]) * pixels_per_mm + 0.5); cmd.wd.contrast = contrast; cmd.wd.threshold = 0x00; cmd.wd.brightness = brightness; cmd.wd.image_comp = (s->val[OPT_DEPTH] == 1) ? 0 : 2; cmd.wd.bpp = s->val[OPT_DEPTH]; cmd.wd.ht_pattern = 0; cmd.wd.rif_padding = 0x00; cmd.wd.three = 3; cmd.wd.null_eins = (s->val[OPT_DEPTH] == 1) ? 0 : 1; cmd.wd.eins_null = (s->val[OPT_DEPTH] == 1) ? 1 : 0; cmd.wd.contr_adjust = contr_adjust; cmd.wd.bright_adjust = bright_adjust; return sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); } /* Tell scanner to scan more data. Original comment in German: Fordert Scanner auf, weiter zu scannen... */ static SANE_Status request_more_data (S9036_Scanner * s) { SANE_Status status; int lines_available; int bytes_per_line; status = start_scan (s->fd, SANE_TRUE); if (status != SANE_STATUS_GOOD) return status; wait_ready (s->fd); status = get_read_sizes (s->fd, &lines_available, &bytes_per_line, 0); if (!lines_available || bytes_per_line != s->params.bytes_per_line) { return SANE_STATUS_INVAL; } if (s->lines_read + lines_available > s->params.lines) return SANE_STATUS_INVAL; s->lines_in_scanner = lines_available; return SANE_STATUS_GOOD; } /* May only be called when there is at least one row of data to be read. Original comment in German: Darf nur aufgerufen werden, wenn wirklich noch Zeilen zu scannen/lesen sind ! */ static SANE_Status read_more_data (S9036_Scanner * s) { static Byte cmd[] = { 0x28, 0x00, /* opcode, lun */ 0x00, /* data type 80 == read time left */ 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00, 0x00, /* transfer length */ 0x00, /* control byte */ }; SANE_Status status; size_t size; int lines_read; int bpl = s->params.bytes_per_line; unsigned int i; if (s->lines_in_scanner == 0) { /* No lines in scanner ? scan some more */ status = request_more_data (s); if (status != SANE_STATUS_GOOD) return status; } /* We try this 3 times */ while (1) { /* Request as much lines as would fit into the buffer ... */ lines_read = s->bufsize / bpl; /* buffer is too small for one line: we can't handle this */ if (!lines_read) return SANE_STATUS_INVAL; /* We only request as many lines as there are already scanned */ if (lines_read > s->lines_in_scanner) lines_read = s->lines_in_scanner; set_size (&cmd[6], 3, lines_read); size = lines_read * s->params.bytes_per_line; DBG (1, "Requesting %d lines, in scanner: %d, total: %d\n", lines_read, s->lines_in_scanner, s->params.lines); status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), s->buffer, &size); if (status != SANE_STATUS_GOOD) { if (s->bufsize > 4096) { DBG (1, "sanei_scsi_cmd(): using 4k buffer\n"); s->bufsize = 4096; continue; } DBG (1, "sanei_scsi_cmd() = %d\n", status); return SANE_STATUS_IO_ERROR; } if (size != (unsigned int) lines_read * s->params.bytes_per_line) { DBG (1, "sanei_scsi_cmd(): got %lu bytes, expected %d\n", (u_long) size, lines_read * s->params.bytes_per_line); return SANE_STATUS_INVAL; } DBG (1, "Got %lu bytes\n", (u_long) size); break; } /* Reverse: */ if (s->params.depth != 1) for (i = 0; i < size; i++) s->buffer[i] = (255 - s->buffer[i]); s->in_buffer += size; s->lines_in_scanner -= lines_read; s->lines_read += lines_read; return SANE_STATUS_GOOD; } static SANE_Status attach (const char *devname, S9036_Device ** devp) { #define ATTACH_SCSI_INQ_LEN 55 const Byte scsi_inquiry[] = { 0x12, 0x00, 0x00, 0x00, ATTACH_SCSI_INQ_LEN, 0x00 }; Byte result[ATTACH_SCSI_INQ_LEN]; int fd; S9036_Device *dev; SANE_Status status; size_t size; int i; for (dev = s9036_devices; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } DBG (3, "attach: opening %s\n", devname); status = sanei_scsi_open (devname, &fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed (%s)\n", sane_strstatus (status)); return SANE_STATUS_INVAL; } DBG (3, "attach: sending INQUIRY\n"); size = sizeof (result); status = sanei_scsi_cmd (fd, scsi_inquiry, sizeof (scsi_inquiry), result, &size); if (status != SANE_STATUS_GOOD || size != ATTACH_SCSI_INQ_LEN) { DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } status = test_ready (fd); sanei_scsi_close (fd); if (status != SANE_STATUS_GOOD) return status; /* The structure send by the scanner after inquiry is not SCSI-2 compatible. The standard manufacturer/model fields are no ASCII strings, but ? At offset 36 my SIEMENS scanner identifies as an AGFA one ?! */ if (result[0] != 6 || strncmp ((char *)result + 36, "AGFA03", 6)) { DBG (1, "attach: device doesn't look like a Siemens 9036 scanner\n"); return SANE_STATUS_INVAL; } DBG (3, "Inquiry data:\n"); for (i = 5; i < 55; i += 10) DBG (3, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", result[i], result[i + 1], result[i + 2], result[i + 3], result[i + 4], result[i + 5], result[i + 6], result[i + 7], result[i + 8], result[i + 9]); dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devname); dev->sane.vendor = "Siemens"; dev->sane.model = "9036"; dev->sane.type = "flatbed scanner"; dev->handle = 0; DBG (3, "attach: found S9036 scanner model\n"); ++num_devices; dev->next = s9036_devices; s9036_devices = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static SANE_Status do_cancel (S9036_Scanner * s) { s->scanning = SANE_FALSE; if (s->fd >= 0) { stop_scan (s->fd); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; } if (s->buffer) { free (s->buffer); s->buffer = 0; } return SANE_STATUS_CANCELLED; } static SANE_Status init_options (S9036_Scanner * s) { int i; /* Hardware Limitations: must be static ! */ static const SANE_Int depth_list[] = {2, 1, 8}; static const SANE_Int dpi_list[] = {8, 100, 200, 300, 400, 500, 600, 700, 800}; static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 1 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static const SANE_Range automatic_adjust_range = {-20, 20, 1}; static const SANE_Range x_range = {0, SANE_FIX (8.27 * MM_PER_INCH), 0}; static const SANE_Range y_range = {0, SANE_FIX (12.72 * MM_PER_INCH), 0}; /* ------ */ memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS] = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* depth */ s->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_DEPTH].unit = SANE_UNIT_BIT; s->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_DEPTH].constraint.word_list = depth_list; s->val[OPT_DEPTH] = 1; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; s->val[OPT_RESOLUTION] = 100; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &x_range; s->val[OPT_TL_X] = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &y_range; s->val[OPT_TL_Y] = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &x_range; s->val[OPT_BR_X] = x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &y_range; s->val[OPT_BR_Y] = y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_AUTOMATIC; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; s->val[OPT_BRIGHTNESS] = 0; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].cap |= SANE_CAP_AUTOMATIC; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; s->val[OPT_CONTRAST] = 0; /* brightness automatic correct */ s->opt[OPT_BRIGHT_ADJUST].name = "adjust-bright"; s->opt[OPT_BRIGHT_ADJUST].title = "Automatic brightness adjust"; s->opt[OPT_BRIGHT_ADJUST].desc = "Controls the automatic brightness of the " "acquired image. This option is active for automatic brightness only."; s->opt[OPT_BRIGHT_ADJUST].type = SANE_TYPE_INT; s->opt[OPT_BRIGHT_ADJUST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHT_ADJUST].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHT_ADJUST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHT_ADJUST].constraint.range = &automatic_adjust_range; s->val[OPT_BRIGHT_ADJUST] = 0; /* contrast automatic correct */ s->opt[OPT_CONTR_ADJUST].name = "adjust-contr"; s->opt[OPT_CONTR_ADJUST].title = "Automatic contrast adjust"; s->opt[OPT_CONTR_ADJUST].desc = "Controls the automatic contrast of the " " acquired image. This option is active for automatic contrast only."; s->opt[OPT_CONTR_ADJUST].type = SANE_TYPE_INT; s->opt[OPT_CONTR_ADJUST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTR_ADJUST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTR_ADJUST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTR_ADJUST].constraint.range = &automatic_adjust_range; s->val[OPT_CONTR_ADJUST] = 0; return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach (dev, 0); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; authorize = authorize; /* silence compilation warnings */ DBG_INIT (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open ("s9036.conf"); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { S9036_Device *dev, *next; for (dev = s9036_devices; dev; dev = next) { next = dev->next; if (dev->handle) sane_close (dev->handle); free (dev); } if (devlist) free (devlist); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { S9036_Device *dev; int i; local_only = local_only; /* silence compilation warnings */ if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; for (dev = s9036_devices, i = 0; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { S9036_Device *dev; SANE_Status status; S9036_Scanner *s; if (devicename[0]) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } else { /* empty devicname -> use first device */ dev = s9036_devices; } if (!dev) return SANE_STATUS_INVAL; if (dev->handle) return SANE_STATUS_DEVICE_BUSY; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->scanning = SANE_FALSE; s->fd = -1; s->hw = dev; s->hw->handle = s; init_options (s); *handle = s; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { S9036_Scanner *s = handle; if (s->scanning) do_cancel (handle); s->hw->handle = 0; free (handle); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { S9036_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { S9036_Scanner *s = handle; SANE_Status status; if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS || !SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) return SANE_STATUS_UNSUPPORTED; if (action == SANE_ACTION_GET_VALUE) { switch (option) { case OPT_DEPTH: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_BRIGHT_ADJUST: case OPT_CONTR_ADJUST: *(SANE_Word *) val = s->val[option]; break; default: return SANE_STATUS_UNSUPPORTED; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) return SANE_STATUS_UNSUPPORTED; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { case OPT_DEPTH: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info) *info |= SANE_INFO_RELOAD_PARAMS; case OPT_BRIGHT_ADJUST: case OPT_CONTR_ADJUST: s->val[option] = *(SANE_Word *) val; break; case OPT_BRIGHTNESS: if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_BRIGHT_ADJUST].cap)) { s->opt[OPT_BRIGHT_ADJUST].cap |= SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } s->val[option] = *(SANE_Word *) val; break; case OPT_CONTRAST: if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_CONTR_ADJUST].cap)) { s->opt[OPT_CONTR_ADJUST].cap |= SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } s->val[option] = *(SANE_Word *) val; break; default: return SANE_STATUS_UNSUPPORTED; } } else if (action == SANE_ACTION_SET_AUTO) { if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) return SANE_STATUS_UNSUPPORTED; switch (option) { case OPT_BRIGHTNESS: if (!SANE_OPTION_IS_ACTIVE (s->opt[OPT_BRIGHT_ADJUST].cap)) { s->opt[OPT_BRIGHT_ADJUST].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } break; case OPT_CONTRAST: if (!SANE_OPTION_IS_ACTIVE (s->opt[OPT_CONTR_ADJUST].cap)) { s->opt[OPT_CONTR_ADJUST].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } break; default: return SANE_STATUS_UNSUPPORTED; } } else return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { S9036_Scanner *s = handle; if (!s->scanning) { double width, height, dpi; memset (&s->params, 0, sizeof (s->params)); s->params.format = SANE_FRAME_GRAY; s->params.last_frame = SANE_TRUE; s->params.depth = s->val[OPT_DEPTH]; width = SANE_UNFIX (s->val[OPT_BR_X] - s->val[OPT_TL_X]); height = SANE_UNFIX (s->val[OPT_BR_Y] - s->val[OPT_TL_Y]); dpi = s->val[OPT_RESOLUTION]; /* make best-effort guess at what parameters will look like once scanning starts. */ if (dpi > 0.0 && width > 0.0 && height > 0.0) { double dots_per_mm = dpi / MM_PER_INCH; s->params.pixels_per_line = width * dots_per_mm + 0.5; s->params.lines = height * dots_per_mm + 0.5; } s->params.bytes_per_line = (s->params.pixels_per_line + (8 - s->params.depth)) / (8 / s->params.depth); } if (params) *params = s->params; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { S9036_Scanner *s = handle; SANE_Status status; if (s->scanning) do_cancel (s); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; if (s->fd < 0) { status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "open: open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); s->fd = -1; return status; } } status = test_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "open: test_ready() failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return status; } status = reserve_unit (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "open: reserve_unit() failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return status; } status = set_window (s); if (status != SANE_STATUS_GOOD) { DBG (1, "open: set_window() failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return status; } s->scanning = SANE_TRUE; status = start_scan (s->fd, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (1, "open: start_scan() failed: %s\n", sane_strstatus (status)); do_cancel (s); return status; } wait_ready (s->fd); { int lines_available = 0, bytes_per_line = 0, total_lines = 0; status = get_read_sizes (s->fd, &lines_available, &bytes_per_line, &total_lines); if (status != SANE_STATUS_GOOD) { DBG (1, "open: get_read_sizes() failed: %s\n", sane_strstatus (status)); do_cancel (s); return status; } if (!lines_available || !bytes_per_line || !total_lines) { DBG (1, "open: invalid_sizes(): %d, %d, %d\n", lines_available, bytes_per_line, total_lines); do_cancel (s); return SANE_STATUS_INVAL; } s->params.lines = total_lines; s->params.bytes_per_line = bytes_per_line; s->params.pixels_per_line = bytes_per_line * (8 / s->params.depth); s->lines_in_scanner = lines_available; s->lines_read = 0; /* Buffer must be at least 4k */ s->bufsize = (sanei_scsi_max_request_size < 4096) ? 4096 : sanei_scsi_max_request_size; s->buffer = (Byte *) malloc (s->bufsize * sizeof (Byte)); if (!s->buffer) { DBG (1, "open malloc(%lu) failed.\n", (u_long) s->bufsize); do_cancel (s); return SANE_STATUS_NO_MEM; } s->bufstart = s->buffer; s->in_buffer = 0; } return SANE_STATUS_GOOD; } static void copy_buffer (S9036_Scanner * s, SANE_Byte ** buf, SANE_Int * max_len, SANE_Int * len) { if (*max_len > (SANE_Int) s->in_buffer) { memcpy (*buf, s->bufstart, s->in_buffer); *buf += s->in_buffer; *len += s->in_buffer; *max_len -= s->in_buffer; s->bufstart = s->buffer; s->in_buffer = 0; } else { memcpy (*buf, s->bufstart, *max_len); s->bufstart += *max_len; s->in_buffer -= *max_len; *buf += *max_len; *len += *max_len; *max_len = 0; } } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { S9036_Scanner *s = handle; SANE_Status status; if (s->scanning != SANE_TRUE || max_len == 0) return SANE_STATUS_INVAL; *len = 0; DBG (3, "sane_read(%d) : lines_read %d\n", max_len, s->lines_read); while (max_len > (SANE_Int) s->in_buffer && s->lines_read < s->params.lines) { if (s->in_buffer == 0) { status = read_more_data (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_read: read_more_data() failed (%s)\n", sane_strstatus (status)); do_cancel (s); return status; } } copy_buffer (s, &buf, &max_len, len); if (!max_len || s->lines_read >= s->params.lines) return SANE_STATUS_GOOD; } /* If we reached this point, there are either enough bytes in the buffer, or, if the buffer is empty, we already reached the end of the page */ if (s->in_buffer > 0) { copy_buffer (s, &buf, &max_len, len); return SANE_STATUS_GOOD; } else { do_cancel (s); DBG (1, "EOF\n"); return SANE_STATUS_EOF; } } void sane_cancel (SANE_Handle handle) { S9036_Scanner *s = handle; do_cancel (s); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { handle = handle; /* silence compilation warnings */ DBG (1, "sane_set_io_mode(%d)\n", non_blocking); return (non_blocking == SANE_TRUE) ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { handle = handle; fd = fd; /* silence compilation warnings */ return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/canon_pp.h0000664000175000017500000000650312112021330014544 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2002 Matthew C. Duggan and Simon Krix This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. ----- canon_pp.h: $Revision$ This file is part of the canon_pp backend, supporting Canon FBX30P and NX40P scanners */ #ifndef CANON_PARALLEL_H #define CANON_PARALLEL_H #ifdef BACKEND_NAME #undef BACKEND_NAME #define BACKEND_NAME canon_pp #endif #define DEBUG_NOT_STATIC #include "../include/sane/sanei_debug.h" #ifndef PACKAGE #define PACKAGE "Canon Parallel SANE Backend" #endif #define CMODE_COLOUR "Colour" #define CMODE_MONO "Mono" #define CANONP_CONFIG_FILE "canon_pp.conf" /* options: num,res,colour,depth,tl-x,tl-y,br-x,br-y,cal */ /* preview option disabled */ #define NUM_OPTIONS 9 #define BUF_MAX 64000 /* Indexes into options array */ #define OPT_NUM_OPTIONS 0 #define OPT_RESOLUTION 1 #define OPT_COLOUR_MODE 2 #define OPT_DEPTH 3 #define OPT_TL_X 4 #define OPT_TL_Y 5 #define OPT_BR_X 6 #define OPT_BR_Y 7 #define OPT_CAL 8 #define OPT_PREVIEW 9 #if 0 #define OPT_GAMMA_R 10 #define OPT_GAMMA_G 11 #define OPT_GAMMA_B 12 #endif /*#define OPT_GAMMA 13*/ typedef struct CANONP_Scanner_Struct CANONP_Scanner; struct CANONP_Scanner_Struct { CANONP_Scanner *next; SANE_Device hw; SANE_Option_Descriptor opt[NUM_OPTIONS]; SANE_Int vals[NUM_OPTIONS]; SANE_Bool opened; SANE_Bool scanning; SANE_Bool sent_eof; SANE_Bool cancelled; SANE_Bool setup; SANE_Int lines_scanned; SANE_Int bytes_sent; char *weights_file; SANE_Bool cal_readonly; SANE_Bool cal_valid; scanner_parameters params; scan_parameters scan; int ieee1284_mode; int init_mode; SANE_Bool scanner_present; }; #endif sane-backends-1.0.27/backend/sm3840.c0000664000175000017500000005772012775312261013734 00000000000000/* sane - Scanner Access Now Easy. ScanMaker 3840 Backend Copyright (C) 2005-7 Earle F. Philhower, III earle@ziplabel.com - http://www.ziplabel.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #define BACKENDNAME sm3840 #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_config.h" #include "sm3840.h" #include "sm3840_scan.c" #include "sm3840_lib.c" static double sm3840_unit_convert (SANE_Int val); static int num_devices; static SM3840_Device *first_dev; static SM3840_Scan *first_handle; static const SANE_Device **devlist = 0; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, 0 }; static const SANE_Word resolution_list[] = { 4, 1200, 600, 300, 150 }; static const SANE_Word bpp_list[] = { 2, 8, 16 }; static const SANE_Range x_range = { SANE_FIX (0), SANE_FIX (215.91), /* 8.5 inches */ SANE_FIX (0) }; static const SANE_Range y_range = { SANE_FIX (0), SANE_FIX (297.19), /* 11.7 inches */ SANE_FIX (0) }; static const SANE_Range brightness_range = { 1, 4096, 1.0 }; static const SANE_Range contrast_range = { SANE_FIX (0.1), SANE_FIX (9.9), SANE_FIX (0.1) }; static const SANE_Range lamp_range = { 1, 15, 1 }; static const SANE_Range threshold_range = { 0, 255, 1 }; /*--------------------------------------------------------------------------*/ static int min (int a, int b) { if (a < b) return a; else return b; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SM3840_Scan *s = handle; unsigned char c, d; int i; DBG (2, "+sane-read:%p %p %d %p\n", (unsigned char *) s, buf, max_len, (unsigned char *) len); DBG (2, "+sane-read:remain:%lu offset:%lu linesleft:%d linebuff:%p linesread:%d\n", (u_long)s->remaining, (u_long)s->offset, s->linesleft, s->line_buffer, s->linesread); if (!s->scanning) return SANE_STATUS_INVAL; if (!s->remaining) { if (!s->linesleft) { *len = 0; s->scanning = 0; /* Move to home position */ reset_scanner ((p_usb_dev_handle)s->udev); /* Send lamp timeout */ set_lamp_timer ((p_usb_dev_handle)s->udev, s->sm3840_params.lamp); /* Free memory */ if (s->save_scan_line) free (s->save_scan_line); s->save_scan_line = NULL; if (s->save_dpi1200_remap) free (s->save_dpi1200_remap); s->save_dpi1200_remap = NULL; if (s->save_color_remap) free (s->save_color_remap); s->save_color_remap = NULL; return SANE_STATUS_EOF; } record_line ((s->linesread == 0) ? 1 : 0, (p_usb_dev_handle) s->udev, s->line_buffer, s->sm3840_params.dpi, s->sm3840_params.scanpix, s->sm3840_params.gray, (s->sm3840_params.bpp == 16) ? 1 : 0, &s->save_i, &s->save_scan_line, &s->save_dpi1200_remap, &s->save_color_remap); s->remaining = s->sm3840_params.linelen; s->offset = 0; s->linesread++; s->linesleft--; } /* Need to software emulate 1-bpp modes, simple threshold and error */ /* diffusion dither implemented. */ if (s->sm3840_params.lineart || s->sm3840_params.halftone) { d = 0; for (i = 0; i < min (max_len * 8, s->remaining); i++) { d = d << 1; if (s->sm3840_params.halftone) { c = (*(unsigned char *) (s->offset + s->line_buffer + i)); if (c + s->save_dither_err < 128) { d |= 1; s->save_dither_err += c; } else { s->save_dither_err += c - 255; } } else { if ((*(unsigned char *) (s->offset + s->line_buffer + i)) < s->threshold ) d |= 1; } if (i % 8 == 7) *(buf++) = d; } *len = i / 8; s->offset += i; s->remaining -= i; } else { memcpy (buf, s->offset + s->line_buffer, min (max_len, s->remaining)); *len = min (max_len, s->remaining); s->offset += min (max_len, s->remaining); s->remaining -= min (max_len, s->remaining); } DBG (2, "-sane_read\n"); return SANE_STATUS_GOOD; } /*--------------------------------------------------------------------------*/ void sane_cancel (SANE_Handle h) { SM3840_Scan *s = h; DBG (2, "trying to cancel...\n"); if (s->scanning) { if (!s->cancelled) { /* Move to home position */ reset_scanner ((p_usb_dev_handle) s->udev); /* Send lamp timeout */ set_lamp_timer ((p_usb_dev_handle) s->udev, s->sm3840_params.lamp); /* Free memory */ if (s->save_scan_line) free (s->save_scan_line); s->save_scan_line = NULL; if (s->save_dpi1200_remap) free (s->save_dpi1200_remap); s->save_dpi1200_remap = NULL; if (s->save_color_remap) free (s->save_color_remap); s->save_color_remap = NULL; s->scanning = 0; s->cancelled = SANE_TRUE; } } } /*--------------------------------------------------------------------------*/ SANE_Status sane_start (SANE_Handle handle) { SM3840_Scan *s = handle; SANE_Status status; /* First make sure we have a current parameter set. Some of the * parameters will be overwritten below, but that's OK. */ DBG (2, "sane_start\n"); status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; DBG (1, "Got params again...\n"); s->scanning = SANE_TRUE; s->cancelled = 0; s->line_buffer = malloc (s->sm3840_params.linelen); s->remaining = 0; s->offset = 0; s->linesleft = s->sm3840_params.scanlines; s->linesread = 0; s->save_i = 0; s->save_scan_line = NULL; s->save_dpi1200_remap = NULL; s->save_color_remap = NULL; s->save_dither_err = 0; s->threshold = s->sm3840_params.threshold; setup_scan ((p_usb_dev_handle) s->udev, &(s->sm3840_params)); return (SANE_STATUS_GOOD); } static double sm3840_unit_convert (SANE_Int val) { double d; d = SANE_UNFIX (val); d /= MM_PER_INCH; return d; } /*--------------------------------------------------------------------------*/ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { SM3840_Scan *s = handle; DBG (2, "sane_get_parameters\n"); if (!s->scanning) { memset (&s->sane_params, 0, sizeof (s->sane_params)); /* Copy from options to sm3840_params */ s->sm3840_params.gray = (!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) ? 1 : 0; s->sm3840_params.halftone = (!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_HALFTONE)) ? 1 : 0; s->sm3840_params.lineart = (!strcasecmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) ? 1 : 0; s->sm3840_params.dpi = s->value[OPT_RESOLUTION].w; s->sm3840_params.bpp = s->value[OPT_BIT_DEPTH].w; s->sm3840_params.gain = SANE_UNFIX (s->value[OPT_CONTRAST].w); s->sm3840_params.offset = s->value[OPT_BRIGHTNESS].w; s->sm3840_params.lamp = s->value[OPT_LAMP_TIMEOUT].w; s->sm3840_params.threshold = s->value[OPT_THRESHOLD].w; if (s->sm3840_params.lineart || s->sm3840_params.halftone) { s->sm3840_params.gray = 1; s->sm3840_params.bpp = 8; } s->sm3840_params.top = sm3840_unit_convert (s->value[OPT_TL_Y].w); s->sm3840_params.left = sm3840_unit_convert (s->value[OPT_TL_X].w); s->sm3840_params.width = sm3840_unit_convert (s->value[OPT_BR_X].w) - s->sm3840_params.left; s->sm3840_params.height = sm3840_unit_convert (s->value[OPT_BR_Y].w) - s->sm3840_params.top; /* Legalize and calculate pixel sizes */ prepare_params (&(s->sm3840_params)); /* Copy into sane_params */ s->sane_params.pixels_per_line = s->sm3840_params.scanpix; s->sane_params.lines = s->sm3840_params.scanlines; s->sane_params.format = s->sm3840_params.gray ? SANE_FRAME_GRAY : SANE_FRAME_RGB; s->sane_params.bytes_per_line = s->sm3840_params.linelen; s->sane_params.depth = s->sm3840_params.bpp; if (s->sm3840_params.lineart || s->sm3840_params.halftone) { s->sane_params.bytes_per_line += 7; s->sane_params.bytes_per_line /= 8; s->sane_params.depth = 1; s->sane_params.pixels_per_line = s->sane_params.bytes_per_line * 8; } s->sane_params.last_frame = SANE_TRUE; } /*!scanning */ if (params) *params = s->sane_params; return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { SM3840_Scan *s = handle; SANE_Status status = 0; SANE_Word cap; DBG (2, "sane_control_option\n"); if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->options_list[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { DBG (1, "sane_control_option %d, get value\n", option); switch (option) { /* word options: */ case OPT_RESOLUTION: case OPT_BIT_DEPTH: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_LAMP_TIMEOUT: case OPT_THRESHOLD: *(SANE_Word *) val = s->value[option].w; return (SANE_STATUS_GOOD); /* string options: */ case OPT_MODE: strcpy (val, s->value[option].s); return (SANE_STATUS_GOOD); } } else if (action == SANE_ACTION_SET_VALUE) { DBG (1, "sane_control_option %d, set value\n", option); if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); if (status != SANE_STATUS_GOOD) return (status); status = sanei_constrain_value (s->options_list + option, val, info); switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_BIT_DEPTH: case OPT_BR_X: case OPT_BR_Y: case OPT_TL_X: case OPT_TL_Y: if (info) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_NUM_OPTS: case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_LAMP_TIMEOUT: case OPT_THRESHOLD: s->value[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_MODE: if (s->value[option].s) free (s->value[option].s); s->value[option].s = strdup (val); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return (SANE_STATUS_GOOD); } } return (SANE_STATUS_INVAL); } /*--------------------------------------------------------------------------*/ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { SM3840_Scan *s = handle; DBG (2, "sane_get_option_descriptor\n"); if ((unsigned) option >= NUM_OPTIONS) return (0); return (&s->options_list[option]); } /*--------------------------------------------------------------------------*/ void sane_close (SANE_Handle handle) { SM3840_Scan *prev, *s; DBG (2, "sane_close\n"); /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (1, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (s->scanning) { sane_cancel (handle); } sanei_usb_close (s->udev); if (s->line_buffer) free (s->line_buffer); if (s->save_scan_line) free (s->save_scan_line); if (s->save_dpi1200_remap) free (s->save_dpi1200_remap); if (s->save_color_remap) free (s->save_color_remap); if (prev) prev->next = s->next; else first_handle = s; free (handle); } /*--------------------------------------------------------------------------*/ void sane_exit (void) { SM3840_Device *next; DBG (2, "sane_exit\n"); while (first_dev != NULL) { next = first_dev->next; free (first_dev); first_dev = next; } if (devlist) free (devlist); } /*--------------------------------------------------------------------------*/ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { DBG_INIT (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); if (authorize) DBG (2, "Unused authorize\n"); sanei_usb_init (); return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ static SANE_Status add_sm_device (SANE_String_Const devname, SANE_String_Const modname) { SM3840_Device *dev; dev = calloc (sizeof (*dev), 1); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devname); dev->sane.model = modname; dev->sane.vendor = "Microtek"; dev->sane.type = "flatbed scanner"; ++num_devices; dev->next = first_dev; first_dev = dev; return (SANE_STATUS_GOOD); } static SANE_Status add_sm3840_device (SANE_String_Const devname) { return add_sm_device (devname, "ScanMaker 3840"); } static SANE_Status add_sm4800_device (SANE_String_Const devname) { return add_sm_device (devname, "ScanMaker 4800"); } /*--------------------------------------------------------------------------*/ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { static const SANE_Device **devlist = 0; SM3840_Device *dev; int i; DBG (3, "sane_get_devices (local_only = %d)\n", local_only); while (first_dev) { dev = first_dev->next; free (first_dev); first_dev = dev; } first_dev = NULL; num_devices = 0; /* If we get enough scanners should use an array, but for now */ /* do it one-by-one... */ sanei_usb_find_devices (0x05da, 0x30d4, add_sm3840_device); sanei_usb_find_devices (0x05da, 0x30cf, add_sm4800_device); if (devlist) free (devlist); devlist = calloc ((num_devices + 1) * sizeof (devlist[0]), 1); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; if (device_list) *device_list = devlist; return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return (max_size); } /*--------------------------------------------------------------------------*/ static void initialize_options_list (SM3840_Scan * s) { SANE_Int option; DBG (2, "initialize_options_list\n"); for (option = 0; option < NUM_OPTIONS; ++option) { s->options_list[option].size = sizeof (SANE_Word); s->options_list[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->options_list[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->options_list[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->options_list[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->options_list[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->options_list[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; s->options_list[OPT_NUM_OPTS].size = sizeof (SANE_Word); s->options_list[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->options_list[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; s->value[OPT_NUM_OPTS].w = NUM_OPTIONS; s->options_list[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->options_list[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->options_list[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->options_list[OPT_MODE].type = SANE_TYPE_STRING; s->options_list[OPT_MODE].size = max_string_size (mode_list); s->options_list[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->options_list[OPT_MODE].constraint.string_list = mode_list; s->value[OPT_MODE].s = strdup (mode_list[1]); s->options_list[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->options_list[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->options_list[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->options_list[OPT_RESOLUTION].type = SANE_TYPE_INT; s->options_list[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->options_list[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->options_list[OPT_RESOLUTION].constraint.word_list = resolution_list; s->value[OPT_RESOLUTION].w = 300; s->options_list[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->options_list[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->options_list[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->options_list[OPT_BIT_DEPTH].type = SANE_TYPE_INT; s->options_list[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE; s->options_list[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->options_list[OPT_BIT_DEPTH].constraint.word_list = bpp_list; s->value[OPT_BIT_DEPTH].w = 8; s->options_list[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->options_list[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->options_list[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->options_list[OPT_TL_X].type = SANE_TYPE_FIXED; s->options_list[OPT_TL_X].unit = SANE_UNIT_MM; s->options_list[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_TL_X].constraint.range = &x_range; s->value[OPT_TL_X].w = s->options_list[OPT_TL_X].constraint.range->min; s->options_list[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->options_list[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->options_list[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->options_list[OPT_TL_Y].type = SANE_TYPE_FIXED; s->options_list[OPT_TL_Y].unit = SANE_UNIT_MM; s->options_list[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_TL_Y].constraint.range = &y_range; s->value[OPT_TL_Y].w = s->options_list[OPT_TL_Y].constraint.range->min; s->options_list[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->options_list[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->options_list[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->options_list[OPT_BR_X].type = SANE_TYPE_FIXED; s->options_list[OPT_BR_X].unit = SANE_UNIT_MM; s->options_list[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_BR_X].constraint.range = &x_range; s->value[OPT_BR_X].w = s->options_list[OPT_BR_X].constraint.range->max; s->options_list[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->options_list[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->options_list[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->options_list[OPT_BR_Y].type = SANE_TYPE_FIXED; s->options_list[OPT_BR_Y].unit = SANE_UNIT_MM; s->options_list[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_BR_Y].constraint.range = &y_range; s->value[OPT_BR_Y].w = s->options_list[OPT_BR_Y].constraint.range->max; s->options_list[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->options_list[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->options_list[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->options_list[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->options_list[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->options_list[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_CONTRAST].constraint.range = &contrast_range; s->value[OPT_CONTRAST].w = SANE_FIX (3.5); s->options_list[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->options_list[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->options_list[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->options_list[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->options_list[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->options_list[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_BRIGHTNESS].constraint.range = &brightness_range; s->value[OPT_BRIGHTNESS].w = 1800; s->options_list[OPT_LAMP_TIMEOUT].name = "lamp-timeout"; s->options_list[OPT_LAMP_TIMEOUT].title = SANE_I18N ("Lamp timeout"); s->options_list[OPT_LAMP_TIMEOUT].desc = SANE_I18N ("Minutes until lamp is turned off after scan"); s->options_list[OPT_LAMP_TIMEOUT].type = SANE_TYPE_INT; s->options_list[OPT_LAMP_TIMEOUT].unit = SANE_UNIT_NONE; s->options_list[OPT_LAMP_TIMEOUT].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_LAMP_TIMEOUT].constraint.range = &lamp_range; s->value[OPT_LAMP_TIMEOUT].w = 15; s->options_list[OPT_THRESHOLD].name = "threshold"; s->options_list[OPT_THRESHOLD].title = SANE_I18N ("Threshold"); s->options_list[OPT_THRESHOLD].desc = SANE_I18N ("Threshold value for lineart mode"); s->options_list[OPT_THRESHOLD].type = SANE_TYPE_INT; s->options_list[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->options_list[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_THRESHOLD].constraint.range = &threshold_range; s->value[OPT_THRESHOLD].w = 128; } /*--------------------------------------------------------------------------*/ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { SANE_Status status; SM3840_Device *dev; SM3840_Scan *s; DBG (2, "sane_open\n"); /* Make sure we have first_dev */ sane_get_devices (NULL, 0); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; } else { /* empty devicename -> use first device */ dev = first_dev; } DBG (2, "using device: %s %p\n", dev->sane.name, (unsigned char *) dev); if (!dev) return SANE_STATUS_INVAL; s = calloc (sizeof (*s), 1); if (!s) return SANE_STATUS_NO_MEM; status = sanei_usb_open (dev->sane.name, &(s->udev)); if (status != SANE_STATUS_GOOD) return status; initialize_options_list (s); s->scanning = 0; /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { SM3840_Scan *s = handle; DBG (2, "sane_set_io_mode( %p, %d )\n", handle, non_blocking); if (s->scanning) { if (non_blocking == SANE_FALSE) return SANE_STATUS_GOOD; else return (SANE_STATUS_UNSUPPORTED); } else return SANE_STATUS_INVAL; } /*---------------------------------------------------------------------------*/ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (2, "sane_get_select_fd( %p, %p )\n", (void *) handle, (void *) fd); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/epsonds.conf.in0000664000175000017500000000041712775312261015550 00000000000000# epsonds.conf # # here are some examples for how to configure the epsonds backend # USB usb # For libusb support for unknown scanners use the following command # usb # e.g.: # usb 0x4b8 0x14c # Network # # net 192.168.1.123 net autodiscovery sane-backends-1.0.27/backend/canon_pp-dev.h0000664000175000017500000001267012112021330015322 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2002 Matthew C. Duggan and Simon Krix This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. ----- canon_pp-dev.h: $Revision$ This file is part of the canon_pp backend, supporting Canon FBX30P and NX40P scanners and also part of the stand-alone driver. Simon Krix */ #ifndef CANON_PP_DEV_H #define CANON_PP_DEV_H /* Signal names */ /* C port */ #define READY 0x1f #define NSELECTIN 0x08 #define NINIT 0x04 #define HOSTBUSY 0x02 #define HOSTCLK 0x01 /* S port */ #define BUSY 0x10 #define NACK 0x08 #define PTRCLK 0x08 #define PERROR 0x04 #define ACKDATAREQ 0x04 #define XFLAG 0x02 #define SELECT 0x02 #define NERROR 0x01 #define NFAULT 0x01 #define NDATAAVAIL 0x01 /* Scanner things */ #define CALSIZE 18 /* Lines per calibration */ /* Init modes */ #define INITMODE_20P 1 #define INITMODE_30P 2 #define INITMODE_AUTO 3 /* Misc things */ #define T_SCAN 1 #define T_CALIBRATE 2 /* Macros */ #define MAKE_SHORT(a,b) (((short)a)*0x100+(short)b) #define LOW_BYTE(a) (a%0x100) #define HIGH_BYTE(a) (a/0x100) typedef struct scanner_parameter_struct { /* This is the port the scanner is on, in libieee1284-readable form */ struct parport *port; /* Width of the scanning head in pixels */ int scanheadwidth; int scanbedlength; /* Resolution of the scan head where dpi = 75 << natural_resolution */ int natural_xresolution; int natural_yresolution; int max_xresolution; int max_yresolution; /* ID String. Should only be 38(?) bytes long, so we can reduce the size later. */ char id_string[80]; /* Short, readable scanner name, such as "FB330P" */ char name[40]; /* Pixel weight values from calibration, one per pixel on the scan head. These must be allocated before any scanning can be done. */ unsigned long *blackweight; unsigned long *redweight; unsigned long *greenweight; unsigned long *blueweight; /* Not understood white-balance/gain values */ unsigned char gamma[32]; /* Type of scanner ( 0 = *20P, 1 = [*30P|*40P] ) */ unsigned char type; /* Are we aborting this scanner now */ unsigned char abort_now; } scanner_parameters; typedef struct scan_parameter_struct { /* Size of image */ unsigned int width, height; /* Position of image on the scanner bed */ unsigned int xoffset, yoffset; /* Resolution at which to scan (remember it's 75 << resolution) */ int xresolution, yresolution; /* Mode of image. 0 = greyscale, 1 = truecolour */ int mode; } scan_parameters; typedef struct image_segment_struct { /* Size of image segment */ unsigned int width, height; /* Which part of the image this is */ unsigned int start_scanline; /* Pointer to image data */ unsigned char *image_data; } image_segment; /* Scan-related functions ========================= */ /* Brings the scanner in and out of transparent mode and detects model information */ int sanei_canon_pp_initialise(scanner_parameters *sp, int mode); int sanei_canon_pp_close_scanner(scanner_parameters *sp); /* Image scanning functions */ int sanei_canon_pp_init_scan(scanner_parameters *sp, scan_parameters *scanp); int sanei_canon_pp_read_segment(image_segment **dest, scanner_parameters *sp, scan_parameters *scanp, int scanline_count, int do_adjust, int scanlines_left); int sanei_canon_pp_abort_scan(scanner_parameters *sp); /* Loads the gain offset values. Needs a new name. */ int sanei_canon_pp_load_weights(const char *filename, scanner_parameters *sp); int sanei_canon_pp_calibrate(scanner_parameters *sp, char *cal_file); int sanei_canon_pp_adjust_gamma(scanner_parameters *sp); /* Detect if a scanner is present on a given port */ int sanei_canon_pp_detect(struct parport *port, int mode); /* Put a scanner to sleep */ int sanei_canon_pp_sleep_scanner(struct parport *port); #endif sane-backends-1.0.27/backend/hp-accessor.c0000664000175000017500000005206712775312261015204 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ /* #define STUBS extern int sanei_debug_hp; */ #define DEBUG_DECLARE_ONLY #include "../include/sane/config.h" #include "../include/sane/sanei_backend.h" #include "../include/lassert.h" #include #include #include "hp.h" #include "hp-option.h" #include "hp-accessor.h" #include "hp-device.h" #define DATA_SIZE_INCREMENT (1024) /* * class HpData */ struct hp_data_s { hp_byte_t * buf; size_t bufsiz; size_t length; hp_bool_t frozen; }; static void hp_data_resize (HpData this, size_t newsize) { if (this->bufsiz != newsize) { assert(!this->frozen); this->buf = sanei_hp_realloc(this->buf, newsize); assert(this->buf); this->bufsiz = newsize; } } static void hp_data_freeze (HpData this) { hp_data_resize(this, this->length); this->frozen = 1; } static size_t hp_data_alloc (HpData this, size_t sz) { size_t newsize = this->bufsiz; size_t offset = this->length; /* * mike@easysw.com: * * The following code is REQUIRED so that pointers, etc. aren't * misaligned. This causes MAJOR problems on all SPARC, ALPHA, * and MIPS processors, and possibly others. * * The workaround is to ensure that all allocations are in multiples * of 8 bytes. */ sz = (sz + sizeof (long) - 1) & ~(sizeof (long) - 1); while (newsize < this->length + sz) newsize += DATA_SIZE_INCREMENT; hp_data_resize(this, newsize); this->length += sz; return offset; } static void * hp_data_data (HpData this, size_t offset) { assert(offset < this->length); return (char *)this->buf + offset; } HpData sanei_hp_data_new (void) { return sanei_hp_allocz(sizeof(struct hp_data_s)); } HpData sanei_hp_data_dup (HpData orig) { HpData new; hp_data_freeze(orig); if (!( new = sanei_hp_memdup(orig, sizeof(*orig)) )) return 0; if (!(new->buf = sanei_hp_memdup(orig->buf, orig->bufsiz))) { sanei_hp_free(new); return 0; } return new; } void sanei_hp_data_destroy (HpData this) { sanei_hp_free(this->buf); sanei_hp_free(this); } /* * class HpAccessor */ typedef const struct hp_accessor_type_s * HpAccessorType; typedef struct hp_accessor_s * _HpAccessor; struct hp_accessor_s { HpAccessorType type; size_t data_offset; size_t data_size; }; struct hp_accessor_type_s { SANE_Status (*get)(HpAccessor this, HpData data, void * valp); SANE_Status (*set)(HpAccessor this, HpData data, void * valp); int (*getint)(HpAccessor this, HpData data); void (*setint)(HpAccessor this, HpData data, int val); }; SANE_Status sanei_hp_accessor_get (HpAccessor this, HpData data, void * valp) { if (!this->type->get) return SANE_STATUS_INVAL; return (*this->type->get)(this, data, valp); } SANE_Status sanei_hp_accessor_set (HpAccessor this, HpData data, void * valp) { if (!this->type->set) return SANE_STATUS_INVAL; return (*this->type->set)(this, data, valp); } int sanei_hp_accessor_getint (HpAccessor this, HpData data) { assert (this->type->getint); return (*this->type->getint)(this, data); } void sanei_hp_accessor_setint (HpAccessor this, HpData data, int val) { assert (this->type->setint); (*this->type->setint)(this, data, val); } const void * sanei_hp_accessor_data (HpAccessor this, HpData data) { return hp_data_data(data, this->data_offset); } void * sanei__hp_accessor_data (HpAccessor this, HpData data) { return hp_data_data(data, this->data_offset); } size_t sanei_hp_accessor_size (HpAccessor this) { return this->data_size; } HpAccessor sanei_hp_accessor_new (HpData data, size_t sz) { static const struct hp_accessor_type_s type = { 0, 0, 0, 0 }; _HpAccessor new = sanei_hp_alloc(sizeof(*new)); new->type = &type; new->data_offset = hp_data_alloc(data, new->data_size = sz); return new; } /* * class HpAccessorInt */ #define hp_accessor_int_s hp_accessor_s typedef const struct hp_accessor_int_s * HpAccessorInt; typedef struct hp_accessor_int_s * _HpAccessorInt; static SANE_Status hp_accessor_int_get (HpAccessor this, HpData data, void * valp) { *(SANE_Int*)valp = *(int *)hp_data_data(data, this->data_offset); return SANE_STATUS_GOOD; } static SANE_Status hp_accessor_int_set (HpAccessor this, HpData data, void * valp) { *(int *)hp_data_data(data, this->data_offset) = *(SANE_Int*)valp; return SANE_STATUS_GOOD; } static int hp_accessor_int_getint (HpAccessor this, HpData data) { return *(int *)hp_data_data(data, this->data_offset); } static void hp_accessor_int_setint (HpAccessor this, HpData data, int val) { *(int *)hp_data_data(data, this->data_offset) = val; } HpAccessor sanei_hp_accessor_int_new (HpData data) { static const struct hp_accessor_type_s type = { hp_accessor_int_get, hp_accessor_int_set, hp_accessor_int_getint, hp_accessor_int_setint }; _HpAccessorInt new = sanei_hp_alloc(sizeof(*new)); new->type = &type; new->data_offset = hp_data_alloc(data, new->data_size = sizeof(int)); return (HpAccessor)new; } /* * class HpAccessorBool */ #define hp_accessor_bool_s hp_accessor_s typedef const struct hp_accessor_bool_s * HpAccessorBool; typedef struct hp_accessor_bool_s * _HpAccessorBool; static SANE_Status hp_accessor_bool_get (HpAccessor this, HpData data, void * valp) { int val = *(int *)hp_data_data(data, this->data_offset); *(SANE_Bool*)valp = val ? SANE_TRUE : SANE_FALSE; return SANE_STATUS_GOOD; } static SANE_Status hp_accessor_bool_set (HpAccessor this, HpData data, void * valp) { int * datap = hp_data_data(data, this->data_offset); *datap = *(SANE_Bool*)valp == SANE_FALSE ? 0 : 1; return SANE_STATUS_GOOD; } HpAccessor sanei_hp_accessor_bool_new (HpData data) { static const struct hp_accessor_type_s type = { hp_accessor_bool_get, hp_accessor_bool_set, hp_accessor_int_getint, hp_accessor_int_setint }; _HpAccessorBool new = sanei_hp_alloc(sizeof(*new)); new->type = &type; new->data_offset = hp_data_alloc(data, new->data_size = sizeof(int)); return (HpAccessor)new; } /* * class HpAccessorFixed */ #define hp_accessor_fixed_s hp_accessor_s typedef const struct hp_accessor_fixed_s * HpAccessorFixed; typedef struct hp_accessor_fixed_s * _HpAccessorFixed; static SANE_Status hp_accessor_fixed_get (HpAccessor this, HpData data, void * valp) { *(SANE_Fixed*)valp = *(SANE_Fixed *)hp_data_data(data, this->data_offset); return SANE_STATUS_GOOD; } static SANE_Status hp_accessor_fixed_set (HpAccessor this, HpData data, void * valp) { *(SANE_Fixed *)hp_data_data(data, this->data_offset) = *(SANE_Fixed*)valp; return SANE_STATUS_GOOD; } HpAccessor sanei_hp_accessor_fixed_new (HpData data) { static const struct hp_accessor_type_s type = { hp_accessor_fixed_get, hp_accessor_fixed_set, 0, 0 }; _HpAccessorFixed new = sanei_hp_alloc(sizeof(*new)); new->type = &type; new->data_offset = hp_data_alloc(data, new->data_size = sizeof(SANE_Fixed)); return (HpAccessor)new; } /* * class HpAccessorChoice */ typedef struct hp_accessor_choice_s * _HpAccessorChoice; struct hp_accessor_choice_s { HpAccessorType type; size_t data_offset; size_t data_size; HpChoice choices; SANE_String_Const * strlist; }; static SANE_Status hp_accessor_choice_get (HpAccessor this, HpData data, void * valp) { HpChoice choice = *(HpChoice *)hp_data_data(data, this->data_offset); strcpy(valp, choice->name); return SANE_STATUS_GOOD; } static SANE_Status hp_accessor_choice_set (HpAccessor _this, HpData data, void * valp) { HpAccessorChoice this = (HpAccessorChoice)_this; HpChoice choice; SANE_String_Const * strlist = this->strlist; for (choice = this->choices; choice; choice = choice->next) { /* Skip choices which aren't in strlist. */ if (!*strlist || strcmp(*strlist, choice->name) != 0) continue; strlist++; if (strcmp((const char *)valp, choice->name) == 0) { *(HpChoice *)hp_data_data(data, this->data_offset) = choice; return SANE_STATUS_GOOD; } } return SANE_STATUS_INVAL; } static int hp_accessor_choice_getint (HpAccessor this, HpData data) { HpChoice choice = *(HpChoice *)hp_data_data(data, this->data_offset); return choice->val; } static void hp_accessor_choice_setint (HpAccessor _this, HpData data, int val) { HpAccessorChoice this = (HpAccessorChoice)_this; HpChoice choice; HpChoice first_choice = 0; SANE_String_Const * strlist = this->strlist; for (choice = this->choices; choice; choice = choice->next) { /* Skip choices which aren't in strlist. */ if (!*strlist || strcmp(*strlist, choice->name) != 0) continue; strlist++; if (!first_choice) first_choice = choice; /* First enabled choice */ if (choice->val == val) { *(HpChoice *)hp_data_data(data, this->data_offset) = choice; return; } } if (first_choice) *(HpChoice *)hp_data_data(data, this->data_offset) = first_choice; else assert(!"No choices to choose from?"); } SANE_Int sanei_hp_accessor_choice_maxsize (HpAccessorChoice this) { HpChoice choice; SANE_Int size = 0; for (choice = this->choices; choice; choice = choice->next) if ((SANE_Int)strlen(choice->name) >= size) size = strlen(choice->name) + 1; return size; } SANE_String_Const * sanei_hp_accessor_choice_strlist (HpAccessorChoice this, HpOptSet optset, HpData data, const HpDeviceInfo *info) { if (optset) { int old_val = hp_accessor_choice_getint((HpAccessor)this, data); HpChoice choice; size_t count = 0; for (choice = this->choices; choice; choice = choice->next) if (sanei_hp_choice_isEnabled(choice, optset, data, info)) this->strlist[count++] = choice->name; this->strlist[count] = 0; hp_accessor_choice_setint((HpAccessor)this, data, old_val); } return this->strlist; } HpAccessor sanei_hp_accessor_choice_new (HpData data, HpChoice choices, hp_bool_t may_change) { static const struct hp_accessor_type_s type = { hp_accessor_choice_get, hp_accessor_choice_set, hp_accessor_choice_getint, hp_accessor_choice_setint }; HpChoice choice; size_t count = 0; _HpAccessorChoice this; if ( may_change ) data->frozen = 0; for (choice = choices; choice; choice = choice->next) count++; this = sanei_hp_alloc(sizeof(*this) + (count+1) * sizeof(*this->strlist)); if (!this) return 0; this->type = &type; this->data_offset = hp_data_alloc(data, this->data_size = sizeof(HpChoice)); this->choices = choices; this->strlist = (SANE_String_Const *)(this + 1); count = 0; for (choice = this->choices; choice; choice = choice->next) this->strlist[count++] = choice->name; this->strlist[count] = 0; return (HpAccessor)this; } /* * class HpAccessorVector */ typedef struct hp_accessor_vector_s * _HpAccessorVector; struct hp_accessor_vector_s { HpAccessorType type; size_t data_offset; size_t data_size; unsigned short mask; unsigned short length; unsigned short offset; short stride; unsigned short (*unscale)(HpAccessorVector this, SANE_Fixed fval); SANE_Fixed (*scale)(HpAccessorVector this, unsigned short val); SANE_Fixed fmin; SANE_Fixed fmax; }; unsigned sanei_hp_accessor_vector_length (HpAccessorVector this) { return this->length; } SANE_Fixed sanei_hp_accessor_vector_minval (HpAccessorVector this) { return this->fmin; } SANE_Fixed sanei_hp_accessor_vector_maxval (HpAccessorVector this) { return this->fmax; } static unsigned short _v_get (HpAccessorVector this, const unsigned char * data) { unsigned short val; if (this->mask <= 255) val = data[0]; else #ifndef NotOrig val = (data[0] << 8) + data[1]; #else val = (data[1] << 8) + data[0]; #endif return val & this->mask; } static void _v_set (HpAccessorVector this, unsigned char * data, unsigned short val) { val &= this->mask; if (this->mask <= 255) { data[0] = (unsigned char)val; } else { #ifndef NotOrig data[1] = (unsigned char)val; data[0] = (unsigned char)(val >> 8); #else data[0] = (unsigned char)val; data[1] = (unsigned char)(val >> 8); #endif } } static SANE_Status hp_accessor_vector_get (HpAccessor _this, HpData d, void * valp) { HpAccessorVector this = (HpAccessorVector)_this; SANE_Fixed * ptr = valp; const SANE_Fixed * end = ptr + this->length; const unsigned char * data = hp_data_data(d, this->data_offset); data += this->offset; while (ptr < end) { *ptr++ = (*this->scale)(this, _v_get(this, data)); data += this->stride; } return SANE_STATUS_GOOD; } static SANE_Status hp_accessor_vector_set (HpAccessor _this, HpData d, void * valp) { HpAccessorVector this = (HpAccessorVector)_this; SANE_Fixed * ptr = valp; const SANE_Fixed * end = ptr + this->length; unsigned char * data = hp_data_data(d, this->data_offset); data += this->offset; while (ptr < end) { if (*ptr < this->fmin) *ptr = this->fmin; if (*ptr > this->fmax) *ptr = this->fmax; _v_set(this, data, (*this->unscale)(this, *ptr++)); data += this->stride; } return SANE_STATUS_GOOD; } static unsigned short _vector_unscale (HpAccessorVector this, SANE_Fixed fval) { unsigned short max_val = this->mask; return (fval * max_val + SANE_FIX(0.5)) / SANE_FIX(1.0); } static SANE_Fixed _vector_scale (HpAccessorVector this, unsigned short val) { unsigned short max_val = this->mask; return (SANE_FIX(1.0) * val + max_val / 2) / max_val; } HpAccessor sanei_hp_accessor_vector_new (HpData data, unsigned length, unsigned depth) { static const struct hp_accessor_type_s type = { hp_accessor_vector_get, hp_accessor_vector_set, 0, 0 }; unsigned width = depth > 8 ? 2 : 1; _HpAccessorVector new = sanei_hp_alloc(sizeof(*new)); if (!new) return 0; assert(depth > 0 && depth <= 16); assert(length > 0); new->type = &type; new->data_size = length * width; new->data_offset = hp_data_alloc(data, new->data_size); new->mask = ((unsigned)1 << depth) - 1; new->length = length; new->offset = 0; new->stride = width; new->scale = _vector_scale; new->unscale = _vector_unscale; new->fmin = SANE_FIX(0.0); new->fmax = SANE_FIX(1.0); return (HpAccessor)new; } static unsigned short _gamma_vector_unscale (HpAccessorVector __sane_unused__ this, SANE_Fixed fval) { unsigned short unscaled = fval / SANE_FIX(1.0); if (unscaled > 255) unscaled = 255; unscaled = 255 - unscaled; /* Don't know why. But this is how it works. */ return unscaled; } static SANE_Fixed _gamma_vector_scale (HpAccessorVector __sane_unused__ this, unsigned short val) { SANE_Fixed scaled; val = 255-val; /* Don't know why. But this is how it works. */ scaled = val * SANE_FIX(1.0); return scaled; } HpAccessor sanei_hp_accessor_gamma_vector_new (HpData data, unsigned length, unsigned depth) { _HpAccessorVector this = ( (_HpAccessorVector) sanei_hp_accessor_vector_new(data, length, depth) ); if (!this) return 0; this->offset += this->stride * (this->length - 1); this->stride = -this->stride; this->scale = _gamma_vector_scale; this->unscale = _gamma_vector_unscale; this->fmin = SANE_FIX(0.0); this->fmax = SANE_FIX(255.0); return (HpAccessor)this; } static unsigned short _matrix_vector_unscale (HpAccessorVector this, SANE_Fixed fval) { unsigned short max_val = this->mask >> 1; unsigned short sign_bit = this->mask & ~max_val; unsigned short sign = 0; if (fval == SANE_FIX(1.0)) return sign_bit; if (fval < 0) { sign = sign_bit; fval = -fval; } return sign | ((fval * max_val + this->fmax / 2) / this->fmax); } static SANE_Fixed _matrix_vector_scale (HpAccessorVector this, unsigned short val) { unsigned short max_val = this->mask >> 1; unsigned short sign_bit = this->mask & ~max_val; SANE_Fixed fval; if (val == sign_bit) return SANE_FIX(1.0); fval = (this->fmax * (val & max_val) + max_val / 2) / max_val; if ((val & sign_bit) != 0) fval = -fval; return fval; } HpAccessor sanei_hp_accessor_matrix_vector_new (HpData data, unsigned length, unsigned depth) { _HpAccessorVector this = ( (_HpAccessorVector) sanei_hp_accessor_vector_new(data, length, depth) ); if (!this) return 0; this->scale = _matrix_vector_scale; this->unscale = _matrix_vector_unscale; this->fmax = depth == 10 ? SANE_FIX(4.0) : SANE_FIX(2.0); this->fmax *= (this->mask >> 1); this->fmax >>= (depth - 1); this->fmin = - this->fmax; return (HpAccessor)this; } HpAccessor sanei_hp_accessor_subvector_new (HpAccessorVector super, unsigned nchan, unsigned chan) { _HpAccessorVector this = sanei_hp_memdup(super, sizeof(*this)); if (!this) return 0; assert(chan < nchan); assert(this->length % nchan == 0); this->length /= nchan; if (this->stride < 0) this->offset += (nchan - chan - 1) * this->stride; else this->offset += chan * this->stride; this->stride *= nchan; return (HpAccessor)this; } /* * class HpAccessorGeometry */ typedef const struct hp_accessor_geometry_s * HpAccessorGeometry; typedef struct hp_accessor_geometry_s * _HpAccessorGeometry; struct hp_accessor_geometry_s { HpAccessorType type; size_t data_offset; size_t data_size; HpAccessor this; HpAccessor other; hp_bool_t is_br; HpAccessor resolution; }; static SANE_Status hp_accessor_geometry_set (HpAccessor _this, HpData data, void * _valp) { HpAccessorGeometry this = (HpAccessorGeometry)_this; SANE_Fixed * valp = _valp; SANE_Fixed limit; sanei_hp_accessor_get(this->other, data, &limit); if (this->is_br ? *valp < limit : *valp > limit) *valp = limit; return sanei_hp_accessor_set(this->this, data, valp); } static int _to_devpixels (SANE_Fixed val_mm, SANE_Fixed mm_per_pix) { assert(val_mm >= 0); return (val_mm + mm_per_pix / 2) / mm_per_pix; } static int hp_accessor_geometry_getint (HpAccessor _this, HpData data) { HpAccessorGeometry this = (HpAccessorGeometry)_this; SANE_Fixed this_val, other_val; int res = sanei_hp_accessor_getint(this->resolution, data); SANE_Fixed mm_per_pix = (SANE_FIX(MM_PER_INCH) + res / 2) / res; assert(res > 0); sanei_hp_accessor_get(this->this, data, &this_val); if (this->is_br) { /* Convert to extent. */ sanei_hp_accessor_get(this->other, data, &other_val); assert(this_val >= other_val && other_val >= 0); return (_to_devpixels(this_val, mm_per_pix) - _to_devpixels(other_val, mm_per_pix) + 1); } return _to_devpixels(this_val, mm_per_pix); } /* * we should implement hp_accessor_geometry_setint, but we don't * need it yet... */ HpAccessor sanei_hp_accessor_geometry_new (HpAccessor val, HpAccessor lim, hp_bool_t is_br, HpAccessor resolution) { static const struct hp_accessor_type_s type = { hp_accessor_fixed_get, hp_accessor_geometry_set, hp_accessor_geometry_getint, 0 }; _HpAccessorGeometry new = sanei_hp_alloc(sizeof(*new)); new->type = &type; new->data_offset = val->data_offset; new->data_size = val->data_size; new->this = val; new->other = lim; new->is_br = is_br; new->resolution = resolution; return (HpAccessor)new; } sane-backends-1.0.27/backend/hp3900.conf.in0000664000175000017500000000061412112021330014772 00000000000000# # Configuration file for the hp3900 backend # # HP Scanjet 3800 usb 0x03f0 0x2605 # HP Scanjet 3970c usb 0x03f0 0x2305 # HP Scanjet 4070 Photosmart usb 0x03f0 0x2405 # HP Scanjet 4370 usb 0x03f0 0x4105 # HP Scanjet G2710 usb 0x03f0 0x2805 # HP Scanjet G3010 usb 0x03f0 0x4205 # HP Scanjet G3110 usb 0x03f0 0x4305 # UMAX Astra 4900/4950 usb 0x06dc 0x0020 # BenQ 5550 usb 0x04a5 0x2211 sane-backends-1.0.27/backend/u12-if.c0000664000175000017500000003552512112021330013753 00000000000000/** @file u12-if.c * @brief The interface functions to the U12 backend stuff. * * Copyright (c) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - added model tweaking * - fixed autodetection bug * - added line-scaling stuff * - removed u12if_setScanEnv() * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #define _DEF_BRIGHTEST_SKIP 3 #define _DEF_DARKEST_SKIP 5 /** useful for description tables */ typedef struct { int id; char *desc; } TabDef; typedef struct { char *vp; char *name; } DevDesc; #define _PLUSTEK_VENID 0x07B3 #define _KYE_VENID 0x0458 /** to allow different vendors... */ static TabDef u12Vendors[] = { { _PLUSTEK_VENID, "Plustek" }, { _KYE_VENID, "KYE/Genius" }, { 0xFFFF, NULL } }; /** list of supported devices */ static DevDesc u12Devices[] = { { "0x07B3-0x0001", "1212U/U12" }, { "0x0458-0x2004", "Colorpage HR6" }, { NULL, NULL } }; /** for autodetection */ static SANE_Char USB_devname[1024]; /********************** the USB scanner interface ****************************/ /** */ static SANE_Status u12_initDev( U12_Device *dev, int handle, int vendor ) { int i; SANE_Status res; TimerDef timer; /* well now we patch the vendor string... * if not found, the default vendor will be Plustek */ for( i = 0; u12Vendors[i].desc != NULL; i++ ) { if( u12Vendors[i].id == vendor ) { dev->sane.vendor = u12Vendors[i].desc; DBG( _DBG_INFO, "Vendor adjusted to: >%s<\n", dev->sane.vendor ); break; } } dev->fd = handle; dev->adj.upNormal = 0; dev->adj.upNegative = 20; dev->adj.upPositive = -30; dev->adj.leftNormal = 51; res = SANE_STATUS_IO_ERROR; if( !(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) { u12motor_PositionModuleToHome( dev ); u12io_StartTimer( &timer, _SECOND * 20); do { if( u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER) { res = SANE_STATUS_GOOD; break; } } while( !u12io_CheckTimer( &timer )); } else { res = u12hw_InitAsic( dev, SANE_FALSE ); } if( res == SANE_STATUS_GOOD ) u12hw_PutToIdleMode( dev ); return res; } /** will be called upon sane_exit */ static void u12if_shutdown( U12_Device *dev ) { SANE_Int handle; TimerDef timer; DBG( _DBG_INFO, "Shutdown called (dev->fd=%d, %s)\n", dev->fd, dev->sane.name ); if( SANE_STATUS_GOOD == sanei_usb_open( dev->sane.name, &handle )) { dev->fd = handle; u12io_OpenScanPath( dev ); u12hw_PutToIdleMode( dev ); if( !(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) { u12motor_PositionModuleToHome( dev ); u12io_StartTimer( &timer, _SECOND * 20); do { if( u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER) { break; } } while( !u12io_CheckTimer( &timer )); } DBG( _DBG_INFO, "* Home position reached.\n" ); if( 0 != dev->adj.lampOffOnEnd ) { DBG( _DBG_INFO, "* Switching lamp off...\n" ); dev->regs.RD_ScanControl &= ~_SCAN_LAMPS_ON; u12io_DataToRegister(dev,REG_SCANCONTROL, dev->regs.RD_ScanControl ); } u12io_CloseScanPath( dev ); dev->fd = -1; sanei_usb_close( handle ); } #if 0 usb_StopLampTimer( dev ); #endif DBG( _DBG_INFO, "Shutdown done.\n" ); } /** This function checks wether a device, described by a given * string(vendor and product ID), is supported by this backend or not * * @param usbIdStr - sting consisting out of product and vendor ID * format: "0xVVVV-0xPPPP" VVVV = Vendor ID, PPP = Product ID * @returns; SANE_TRUE if supported, SANE_FALSE if not */ static SANE_Bool u12if_IsDeviceSupported( U12_Device *dev ) { int i; for( i = 0; NULL != u12Devices[i].name; i++ ) { if( !strcmp( dev->usbId, u12Devices[i].vp )) { dev->sane.model = u12Devices[i].name; return SANE_TRUE; } } return SANE_FALSE; } /** */ static SANE_Status u12if_usbattach( SANE_String_Const dev_name ) { if( USB_devname[0] == '\0' ) { DBG( _DBG_INFO, "Found device at >%s<\n", dev_name ); strncpy( USB_devname, dev_name, 1023 ); USB_devname[1023] = '\0'; } else { DBG( _DBG_INFO, "Device >%s< ignoring\n", dev_name ); } return SANE_STATUS_GOOD; } #ifndef _FAKE_DEVICE /** here we roam through our list of supported devices and * cross check with the ones the system reports... * @param vendor - pointer to receive vendor ID * @param product - pointer to receive product ID * @return SANE_TRUE if a matching device has been found or * SANE_FALSE if nothing supported found... */ static SANE_Bool usbDev_autodetect( SANE_Word *vendor, SANE_Word *product ) { int i; SANE_Word p, v; DBG( _DBG_INFO, "Autodetection...\n" ); for( i = 0; NULL != u12Devices[i].name; i++ ) { v = strtol( &(u12Devices[i].vp)[0], 0, 0 ); p = strtol( &(u12Devices[i].vp)[7], 0, 0 ); DBG( _DBG_INFO, "* checking for 0x%04x-0x%04x\n", v, p ); sanei_usb_find_devices( v, p, u12if_usbattach ); if( USB_devname[0] != '\0' ) { *vendor = v; *product = p; DBG( _DBG_INFO, "* using device >%s<\n", USB_devname ); return SANE_TRUE; } } return SANE_FALSE; } #endif /** */ static int u12if_open( U12_Device *dev ) { char devStr[50]; int result; SANE_Int handle; SANE_Word vendor, product; SANE_Bool was_empty; DBG( _DBG_INFO, "u12if_open(%s,%s)\n", dev->name, dev->usbId ); USB_devname[0] = '\0'; #ifdef _FAKE_DEVICE dev->name = strdup( "auto" ); dev->sane.name = dev->name; was_empty = SANE_FALSE; result = SANE_STATUS_UNSUPPORTED; #else if( !strcmp( dev->name, "auto" )) { if( dev->usbId[0] == '\0' ) { if( !usbDev_autodetect( &vendor, &product )) { DBG( _DBG_ERROR, "No supported device found!\n" ); return -1; } } else { vendor = strtol( &dev->usbId[0], 0, 0 ); product = strtol( &dev->usbId[7], 0, 0 ); sanei_usb_find_devices( vendor, product, u12if_usbattach ); if( USB_devname[0] == '\0' ) { DBG( _DBG_ERROR, "No matching device found!\n" ); return -1; } } if( SANE_STATUS_GOOD != sanei_usb_open( USB_devname, &handle )) { return -1; } /* replace the old devname, so we are able to have multiple * auto-detected devices */ free( dev->name ); dev->name = strdup( USB_devname ); dev->sane.name = dev->name; } else { if( SANE_STATUS_GOOD != sanei_usb_open( dev->name, &handle )) return -1; } was_empty = SANE_FALSE; result = sanei_usb_get_vendor_product( handle, &vendor, &product ); #endif if( SANE_STATUS_GOOD == result ) { sprintf( devStr, "0x%04X-0x%04X", vendor, product ); DBG(_DBG_INFO,"Vendor ID=0x%04X, Product ID=0x%04X\n",vendor,product); if( dev->usbId[0] != '\0' ) { if( 0 != strcmp( dev->usbId, devStr )) { DBG( _DBG_ERROR, "Specified Vendor and Product ID " "doesn't match with the ones\n" "in the config file\n" ); sanei_usb_close( handle ); return -1; } } else { sprintf( dev->usbId, "0x%04X-0x%04X", vendor, product ); was_empty = SANE_TRUE; } } else { DBG( _DBG_INFO, "Can't get vendor & product ID from driver...\n" ); /* if the ioctl stuff is not supported by the kernel and we have * nothing specified, we have to give up... */ if( dev->usbId[0] == '\0' ) { DBG( _DBG_ERROR, "Cannot autodetect Vendor an Product ID, " "please specify in config file.\n" ); sanei_usb_close( handle ); return -1; } vendor = strtol( &dev->usbId[0], 0, 0 ); product = strtol( &dev->usbId[7], 0, 0 ); DBG( _DBG_INFO, "... using the specified: " "0x%04X-0x%04X\n", vendor, product ); } /* before accessing the scanner, check if supported! */ if( !u12if_IsDeviceSupported( dev )) { DBG( _DBG_ERROR, "Device >%s<, is not supported!\n", dev->usbId ); sanei_usb_close( handle ); return -1; } dev->mode = _PP_MODE_SPP; dev->fd = handle; /* is it accessible ? */ if( SANE_STATUS_GOOD != u12hw_CheckDevice( dev )) { dev->fd = -1; sanei_usb_close( handle ); return -1; } DBG( _DBG_INFO, "Detected vendor & product ID: " "0x%04X-0x%04X\n", vendor, product ); if( was_empty ) dev->usbId[0] = '\0'; /* now initialize the device */ if( SANE_STATUS_GOOD != u12_initDev( dev, handle, vendor )) { dev->fd = -1; sanei_usb_close( handle ); return -1; } if( _PLUSTEK_VENID == vendor ) { if( dev->Tpa ) dev->sane.model = "UT12"; } dev->initialized = SANE_TRUE; return handle; } /** */ static int u12if_close( U12_Device *dev ) { DBG( _DBG_INFO, "u12if_close()\n" ); u12io_CloseScanPath( dev ); sanei_usb_close( dev->fd ); dev->fd = -1; return 0; } /** */ static SANE_Status u12if_getCaps( U12_Device *dev ) { int cntr; int res_x = 600 ; /*dev->caps.OpticDpi.x */ DBG( _DBG_INFO, "u12if_getCaps()\n" ); /* FIXME: set dpi_range.max, max_x & max_y on a per model base */ dev->dpi_max_x = 600; dev->dpi_max_y = 1200; /* A4 devices */ dev->max_x = 8.5 * (double)_MM_PER_INCH; dev->max_y = 11.6934 * (double)_MM_PER_INCH; /* limit the range */ dev->dpi_range.min = _DEF_DPI; dev->dpi_range.max = dev->dpi_max_y; dev->dpi_range.quant = 0; dev->x_range.min = 0; dev->x_range.max = SANE_FIX(dev->max_x); dev->x_range.quant = 0; dev->y_range.min = 0; dev->y_range.max = SANE_FIX(dev->max_y); dev->y_range.quant = 0; /* calculate the size of the resolution list + * one more to avoid a buffer overflow, then allocate it... */ dev->res_list = (SANE_Int *) calloc((((res_x * 16)-_DEF_DPI)/25+1), sizeof (SANE_Int)); if (NULL == dev->res_list) { DBG( _DBG_ERROR, "alloc fail, resolution problem\n" ); u12if_close(dev); return SANE_STATUS_INVAL; } /* build up the resolution table */ dev->res_list_size = 0; for( cntr = _DEF_DPI; cntr <= (res_x*16); cntr += 25 ) { dev->res_list_size++; dev->res_list[dev->res_list_size - 1] = (SANE_Int)cntr; } return SANE_STATUS_GOOD; } /** */ static SANE_Status u12if_startScan( U12_Device *dev ) { DBG( _DBG_INFO, "u12if_startScan()\n" ); u12hw_StopLampTimer( dev ); u12hw_SetGeneralRegister( dev ); u12hw_ControlLampOnOff( dev ); return SANE_STATUS_GOOD; } /** */ static SANE_Status u12if_stopScan( U12_Device *dev ) { DBG( _DBG_INFO, "u12if_stopScan()\n" ); #if 0 u12motor_ToHomePosition( dev, SANE_FALSE ); #else #if 0 u12motor_ToHomePosition( dev, SANE_TRUE ); u12io_SoftwareReset( dev ); #endif u12hw_CancelSequence( dev ); #endif u12hw_StartLampTimer( dev ); dev->DataInf.dwAppLinesPerArea = 0; dev->DataInf.dwScanFlag &= ~_SCANDEF_SCANNING; return SANE_STATUS_GOOD; } /** */ static SANE_Status u12if_prepare( U12_Device *dev ) { SANE_Status res; DBG( _DBG_INFO, "u12if_prepare()\n" ); u12motor_ToHomePosition( dev, SANE_TRUE ); res = u12hw_WarmupLamp( dev ); if( res != SANE_STATUS_GOOD ) return res; res = u12shading_DoCalibration( dev ); if( res != SANE_STATUS_GOOD ) return res; u12image_PrepareScaling( dev ); u12motor_ForceToLeaveHomePos( dev ); if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) u12hw_SetupPreviewCondition( dev ); else u12hw_SetupScanningCondition( dev ); res = u12motor_WaitForPositionY( dev ); _DODELAY(100); u12io_ResetFifoLen(); u12io_GetFifoLength(dev); dev->scan.bModuleState = _MotorAdvancing; dev->scan.oldScanState = u12io_GetScanState( dev ); dev->scan.oldScanState &= _SCANSTATE_MASK; dev->DataInf.dwScanFlag |= _SCANDEF_SCANNING; DBG( _DBG_INFO, "* oldScanState = %u\n", dev->scan.oldScanState ); DBG( _DBG_INFO, "u12if_prepare() done.\n" ); return res; } /** */ static SANE_Status u12if_readLine( U12_Device *dev, SANE_Byte *line_buffer ) { SANE_Status res; DBG( _DBG_READ, "u12if_readLine()\n" ); if( u12io_IsEscPressed()) { DBG( _DBG_INFO, "u12if_readLine() - cancel detected!\n" ); return SANE_STATUS_CANCELLED; } if( dev->scaleBuf != NULL ) { res = u12image_ReadOneImageLine( dev, dev->scaleBuf ); if( SANE_STATUS_GOOD != res ) return res; u12image_ScaleX( dev, dev->scaleBuf, line_buffer ); } else { res = u12image_ReadOneImageLine( dev, line_buffer ); if( SANE_STATUS_GOOD != res ) return res; } return SANE_STATUS_GOOD; } /** */ static SANE_Status u12if_SetupBuffer( U12_Device *dev ) { void *buffer; DBG( _DBG_INFO, "u12if_SetupBuffer()\n" ); buffer = malloc(_SIZE_TOTAL_BUF_TPA); if( buffer == NULL ) return SANE_STATUS_NO_MEM; dev->shade.pHilight = NULL; dev->bufs.b1.pReadBuf = buffer; dev->bufs.b2.pSumBuf = dev->bufs.b1.pReadBuf + _SIZE_DATA_BUF; dev->bufs.TpaBuf.pb = &((SANE_Byte*)dev->bufs.b2.pSumBuf)[_SIZE_SHADING_SUM_BUF]; /* CHECK: We might should play around with these values... */ dev->shade.skipHilight = _DEF_BRIGHTEST_SKIP; dev->shade.skipShadow = _DEF_DARKEST_SKIP; if( dev->shade.skipHilight && dev->shade.skipShadow ) { u_long skipSize; skipSize = (u_long)((dev->shade.skipHilight + dev->shade.skipShadow) * _SIZE_DATA_BUF * 3); dev->shade.pHilight = (RGBUShortDef*)malloc( skipSize ); if( NULL != dev->shade.pHilight ) { dev->shade.dwDiv = (u_long)(32UL - dev->shade.skipHilight - dev->shade.skipShadow); } } return SANE_STATUS_GOOD; } /* END U12-IF.C .............................................................*/ sane-backends-1.0.27/backend/gt68xx_mid.c0000664000175000017500000010652312112021330014746 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov Copyright (C) 2002-2007 Henning Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "gt68xx_mid.h" #include "gt68xx_low.c" /** @file * @brief Image data unpacking. */ static SANE_Status gt68xx_delay_buffer_init (GT68xx_Delay_Buffer * delay, SANE_Int pixels_per_line, SANE_Int delay_count) { SANE_Int bytes_per_line; SANE_Int line_count, i; if (pixels_per_line <= 0) { DBG (3, "gt68xx_delay_buffer_init: BUG: pixels_per_line=%d\n", pixels_per_line); return SANE_STATUS_INVAL; } if (delay_count < 0) { DBG (3, "gt68xx_delay_buffer_init: BUG: delay_count=%d\n", delay_count); return SANE_STATUS_INVAL; } bytes_per_line = pixels_per_line * sizeof (unsigned int); delay->line_count = line_count = delay_count + 1; delay->read_index = 0; delay->write_index = delay_count; delay->mem_block = (SANE_Byte *) malloc (bytes_per_line * line_count); if (!delay->mem_block) { DBG (3, "gt68xx_delay_buffer_init: no memory for delay block\n"); return SANE_STATUS_NO_MEM; } /* make sure that we will see if one of the unitialized lines get displayed */ for (i = 0; i < bytes_per_line * line_count; i++) delay->mem_block[i] = i % 256; delay->lines = (unsigned int **) malloc (sizeof (unsigned int *) * line_count); if (!delay->lines) { free (delay->mem_block); DBG (3, "gt68xx_delay_buffer_init: no memory for delay line pointers\n"); return SANE_STATUS_NO_MEM; } for (i = 0; i < line_count; ++i) delay->lines[i] = (unsigned int *) (delay->mem_block + i * bytes_per_line); return SANE_STATUS_GOOD; } static SANE_Status gt68xx_delay_buffer_done (GT68xx_Delay_Buffer * delay) { if (delay->lines) { free (delay->lines); delay->lines = NULL; } if (delay->mem_block) { free (delay->mem_block); delay->mem_block = NULL; } return SANE_STATUS_GOOD; } #define DELAY_BUFFER_WRITE_PTR(delay) ( (delay)->lines[(delay)->write_index] ) #define DELAY_BUFFER_SELECT_PTR(delay,dist) \ ((delay)->lines[((delay)->read_index + (dist)) % (delay)->line_count]) #define DELAY_BUFFER_READ_PTR(delay) ( (delay)->lines[(delay)->read_index ] ) #define DELAY_BUFFER_STEP(delay) \ do \ { \ (delay)->read_index = ((delay)->read_index + 1) % (delay)->line_count; \ (delay)->write_index = ((delay)->write_index + 1) % (delay)->line_count; \ } \ while (SANE_FALSE) static inline void unpack_8_mono (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line) { for (; pixels_per_line > 0; ++src, ++dst, --pixels_per_line) { *dst = (((unsigned int) *src) << 8) | *src; } } static inline void unpack_8_rgb (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line) { for (; pixels_per_line > 0; src += 3, ++dst, --pixels_per_line) { *dst = (((unsigned int) *src) << 8) | *src; } } /* 12-bit routines use the fact that pixels_per_line is aligned */ static inline void unpack_12_le_mono (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line) { for (; pixels_per_line > 0; src += 3, dst += 2, pixels_per_line -= 2) { dst[0] = ((((unsigned int) (src[1] & 0x0f)) << 12) | (((unsigned int) src[0]) << 4) | (src[1] & 0x0f)); dst[1] = ((((unsigned int) src[2]) << 8) | (src[1] & 0xf0) | (((unsigned int) src[2]) >> 0x04)); } } static inline void unpack_12_le_rgb (SANE_Byte * src, unsigned int *dst1, unsigned int *dst2, unsigned int *dst3, SANE_Int pixels_per_line) { for (; pixels_per_line > 0; pixels_per_line -= 2) { *dst1++ = ((((unsigned int) (src[1] & 0x0f)) << 12) | (((unsigned int) src[0]) << 4) | (src[1] & 0x0f)); *dst2++ = ((((unsigned int) src[2]) << 8) | (src[1] & 0xf0) | (((unsigned int) src[2]) >> 0x04)); src += 3; *dst3++ = ((((unsigned int) (src[1] & 0x0f)) << 12) | (((unsigned int) src[0]) << 4) | (src[1] & 0x0f)); *dst1++ = ((((unsigned int) src[2]) << 8) | (src[1] & 0xf0) | (((unsigned int) src[2]) >> 0x04)); src += 3; *dst2++ = ((((unsigned int) (src[1] & 0x0f)) << 12) | (((unsigned int) src[0]) << 4) | (src[1] & 0x0f)); *dst3++ = ((((unsigned int) src[2]) << 8) | (src[1] & 0xf0) | (((unsigned int) src[2]) >> 0x04)); src += 3; } } static inline void unpack_16_le_mono (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line) { for (; pixels_per_line > 0; src += 2, dst++, --pixels_per_line) { *dst = (((unsigned int) src[1]) << 8) | src[0]; } } static inline void unpack_16_le_rgb (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line) { for (; pixels_per_line > 0; src += 6, ++dst, --pixels_per_line) { *dst = (((unsigned int) src[1]) << 8) | src[0]; } } static SANE_Status line_read_gray_8 (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; unsigned int *buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size)); buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[0] = buffer; unpack_8_mono (reader->pixel_buffer, buffer, reader->pixels_per_line); return SANE_STATUS_GOOD; } static SANE_Status line_read_gray_double_8 (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; unsigned int *buffer; int i; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size)); unpack_8_mono (reader->pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), reader->pixels_per_line); buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay); for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2) buffer[i] = DELAY_BUFFER_WRITE_PTR (&reader->g_delay)[i]; buffer_pointers_return[0] = buffer; DELAY_BUFFER_STEP (&reader->g_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_gray_12 (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; unsigned int *buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size)); buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[0] = buffer; unpack_12_le_mono (reader->pixel_buffer, buffer, reader->pixels_per_line); return SANE_STATUS_GOOD; } static SANE_Status line_read_gray_double_12 (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; unsigned int *buffer; int i; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size)); unpack_12_le_mono (reader->pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), reader->pixels_per_line); buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay); for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2) buffer[i] = DELAY_BUFFER_WRITE_PTR (&reader->g_delay)[i]; buffer_pointers_return[0] = buffer; DELAY_BUFFER_STEP (&reader->g_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_gray_16 (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; unsigned int *buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size)); buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[0] = buffer; unpack_16_le_mono (reader->pixel_buffer, buffer, reader->pixels_per_line); return SANE_STATUS_GOOD; } static SANE_Status line_read_gray_double_16 (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; unsigned int *buffer; int i; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size)); unpack_16_le_mono (reader->pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), reader->pixels_per_line); buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay); for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2) buffer[i] = DELAY_BUFFER_WRITE_PTR (&reader->g_delay)[i]; buffer_pointers_return[0] = buffer; DELAY_BUFFER_STEP (&reader->g_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_8_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_double_8_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; int i; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2) { DELAY_BUFFER_READ_PTR (&reader->r_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->r_delay, reader->params.ld_shift_double)[i]; DELAY_BUFFER_READ_PTR (&reader->g_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->g_delay, reader->params.ld_shift_double)[i]; DELAY_BUFFER_READ_PTR (&reader->b_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->b_delay, reader->params.ld_shift_double)[i]; } DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_bgr_8_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_8_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_12_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_double_12_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; int i; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2) { DELAY_BUFFER_READ_PTR (&reader->r_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->r_delay, reader->params.ld_shift_double)[i]; DELAY_BUFFER_READ_PTR (&reader->g_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->g_delay, reader->params.ld_shift_double)[i]; DELAY_BUFFER_READ_PTR (&reader->b_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->b_delay, reader->params.ld_shift_double)[i]; } DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_16_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_double_16_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; int i; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2) { DELAY_BUFFER_READ_PTR (&reader->r_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->r_delay, reader->params.ld_shift_double)[i]; DELAY_BUFFER_READ_PTR (&reader->g_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->g_delay, reader->params.ld_shift_double)[i]; DELAY_BUFFER_READ_PTR (&reader->b_delay)[i] = DELAY_BUFFER_SELECT_PTR (&reader->b_delay, reader->params.ld_shift_double)[i]; } DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_bgr_12_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_12_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_bgr_16_line_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl * 3; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += reader->params.scan_bpl; unpack_16_le_mono (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_8_pixel_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_8_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); ++pixel_buffer; unpack_8_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); ++pixel_buffer; unpack_8_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_12_pixel_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); unpack_12_le_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), DELAY_BUFFER_WRITE_PTR (&reader->g_delay), DELAY_BUFFER_WRITE_PTR (&reader->b_delay), reader->pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_rgb_16_pixel_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_16_le_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); pixel_buffer += 2; unpack_16_le_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += 2; unpack_16_le_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_bgr_8_pixel_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_8_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); ++pixel_buffer; unpack_8_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); ++pixel_buffer; unpack_8_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_bgr_12_pixel_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); unpack_12_le_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), DELAY_BUFFER_WRITE_PTR (&reader->g_delay), DELAY_BUFFER_WRITE_PTR (&reader->r_delay), reader->pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status line_read_bgr_16_pixel_mode (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; size_t size; SANE_Int pixels_per_line; SANE_Byte *pixel_buffer = reader->pixel_buffer; size = reader->params.scan_bpl; RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size)); pixels_per_line = reader->pixels_per_line; unpack_16_le_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line); pixel_buffer += 2; unpack_16_le_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line); pixel_buffer += 2; unpack_16_le_rgb (pixel_buffer, DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line); buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay); buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay); buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay); DELAY_BUFFER_STEP (&reader->r_delay); DELAY_BUFFER_STEP (&reader->g_delay); DELAY_BUFFER_STEP (&reader->b_delay); return SANE_STATUS_GOOD; } static SANE_Status gt68xx_line_reader_init_delays (GT68xx_Line_Reader * reader) { SANE_Status status; if (reader->params.color) { status = gt68xx_delay_buffer_init (&reader->r_delay, reader->params.scan_xs, reader->params.ld_shift_r + reader->params.ld_shift_double); if (status != SANE_STATUS_GOOD) return status; status = gt68xx_delay_buffer_init (&reader->g_delay, reader->params.scan_xs, reader->params.ld_shift_g + reader->params.ld_shift_double); if (status != SANE_STATUS_GOOD) { gt68xx_delay_buffer_done (&reader->r_delay); return status; } status = gt68xx_delay_buffer_init (&reader->b_delay, reader->params.scan_xs, reader->params.ld_shift_b + reader->params.ld_shift_double); if (status != SANE_STATUS_GOOD) { gt68xx_delay_buffer_done (&reader->g_delay); gt68xx_delay_buffer_done (&reader->r_delay); return status; } } else { status = gt68xx_delay_buffer_init (&reader->g_delay, reader->params.scan_xs, reader->params.ld_shift_double); if (status != SANE_STATUS_GOOD) return status; } reader->delays_initialized = SANE_TRUE; return SANE_STATUS_GOOD; } static void gt68xx_line_reader_free_delays (GT68xx_Line_Reader * reader) { if (reader->delays_initialized) { if (reader->params.color) { gt68xx_delay_buffer_done (&reader->b_delay); gt68xx_delay_buffer_done (&reader->g_delay); gt68xx_delay_buffer_done (&reader->r_delay); } else { gt68xx_delay_buffer_done (&reader->g_delay); } reader->delays_initialized = SANE_FALSE; } } SANE_Status gt68xx_line_reader_new (GT68xx_Device * dev, GT68xx_Scan_Parameters * params, SANE_Bool final_scan, GT68xx_Line_Reader ** reader_return) { SANE_Status status; GT68xx_Line_Reader *reader; SANE_Int image_size; SANE_Int scan_bpl_full; DBG (6, "gt68xx_line_reader_new: enter\n"); *reader_return = NULL; reader = (GT68xx_Line_Reader *) malloc (sizeof (GT68xx_Line_Reader)); if (!reader) { DBG (3, "gt68xx_line_reader_new: cannot allocate GT68xx_Line_Reader\n"); return SANE_STATUS_NO_MEM; } memset (reader, 0, sizeof (GT68xx_Line_Reader)); reader->dev = dev; memcpy (&reader->params, params, sizeof (GT68xx_Scan_Parameters)); reader->pixel_buffer = 0; reader->delays_initialized = SANE_FALSE; reader->read = NULL; status = gt68xx_line_reader_init_delays (reader); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_line_reader_new: cannot allocate line buffers: %s\n", sane_strstatus (status)); free (reader); return status; } reader->pixels_per_line = reader->params.pixel_xs; if (!reader->params.color) { if (reader->params.depth == 8) { if (reader->params.ld_shift_double > 0) reader->read = line_read_gray_double_8; else reader->read = line_read_gray_8; } else if (reader->params.depth == 12) { if (reader->params.ld_shift_double > 0) reader->read = line_read_gray_double_12; else reader->read = line_read_gray_12; } else if (reader->params.depth == 16) { if (reader->params.ld_shift_double > 0) reader->read = line_read_gray_double_16; else reader->read = line_read_gray_16; } } else if (reader->params.line_mode) { if (reader->params.depth == 8) { if (dev->model->line_mode_color_order == COLOR_ORDER_RGB) { if (reader->params.ld_shift_double > 0) reader->read = line_read_rgb_double_8_line_mode; else reader->read = line_read_rgb_8_line_mode; } else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR) reader->read = line_read_bgr_8_line_mode; } else if (reader->params.depth == 12) { if (dev->model->line_mode_color_order == COLOR_ORDER_RGB) { if (reader->params.ld_shift_double > 0) reader->read = line_read_rgb_double_12_line_mode; else reader->read = line_read_rgb_12_line_mode; } else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR) reader->read = line_read_bgr_12_line_mode; } else if (reader->params.depth == 16) { if (dev->model->line_mode_color_order == COLOR_ORDER_RGB) { if (reader->params.ld_shift_double > 0) reader->read = line_read_rgb_double_16_line_mode; else reader->read = line_read_rgb_16_line_mode; } else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR) reader->read = line_read_bgr_16_line_mode; } } else { if (reader->params.depth == 8) { if (dev->model->line_mode_color_order == COLOR_ORDER_RGB) reader->read = line_read_rgb_8_pixel_mode; else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR) reader->read = line_read_bgr_8_pixel_mode; } else if (reader->params.depth == 12) { if (dev->model->line_mode_color_order == COLOR_ORDER_RGB) reader->read = line_read_rgb_12_pixel_mode; else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR) reader->read = line_read_bgr_12_pixel_mode; } else if (reader->params.depth == 16) { if (dev->model->line_mode_color_order == COLOR_ORDER_RGB) reader->read = line_read_rgb_16_pixel_mode; else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR) reader->read = line_read_bgr_16_pixel_mode; } } if (reader->read == NULL) { DBG (3, "gt68xx_line_reader_new: unsupported bit depth (%d)\n", reader->params.depth); gt68xx_line_reader_free_delays (reader); free (reader); return SANE_STATUS_UNSUPPORTED; } scan_bpl_full = reader->params.scan_bpl; if (reader->params.color && reader->params.line_mode) scan_bpl_full *= 3; reader->pixel_buffer = malloc (scan_bpl_full); if (!reader->pixel_buffer) { DBG (3, "gt68xx_line_reader_new: cannot allocate pixel buffer\n"); gt68xx_line_reader_free_delays (reader); free (reader); return SANE_STATUS_NO_MEM; } gt68xx_device_set_read_buffer_size (reader->dev, scan_bpl_full /* * 200 */ ); image_size = reader->params.scan_bpl * reader->params.scan_ys; status = gt68xx_device_read_prepare (reader->dev, image_size, final_scan); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_line_reader_new: gt68xx_device_read_prepare failed: %s\n", sane_strstatus (status)); free (reader->pixel_buffer); gt68xx_line_reader_free_delays (reader); free (reader); return status; } DBG (6, "gt68xx_line_reader_new: leave: ok\n"); *reader_return = reader; return SANE_STATUS_GOOD; } SANE_Status gt68xx_line_reader_free (GT68xx_Line_Reader * reader) { SANE_Status status; DBG (6, "gt68xx_line_reader_free: enter\n"); gt68xx_line_reader_free_delays (reader); if (reader->pixel_buffer) { free (reader->pixel_buffer); reader->pixel_buffer = NULL; } status = gt68xx_device_read_finish (reader->dev); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_line_reader_free: gt68xx_device_read_finish failed: %s\n", sane_strstatus (status)); } free (reader); DBG (6, "gt68xx_line_reader_free: leave\n"); return status; } SANE_Status gt68xx_line_reader_read (GT68xx_Line_Reader * reader, unsigned int **buffer_pointers_return) { SANE_Status status; status = (*reader->read) (reader, buffer_pointers_return); return status; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/mustek_pp_ccd300.h0000664000175000017500000000572712112021330016021 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2003 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements the hardware driver scanners using a 300dpi CCD */ #ifndef __MUSTEK_PP_CCD300_H #define __MUSTEK_PP_CCD300_H /* i might sort and comment this struct one day... */ typedef struct { unsigned char asic; unsigned char ccd_type; int top; int motor_stop; int bank_count; unsigned int wait_bank; int hwres; int adjustskip; int ref_black; int ref_red; int ref_green; int ref_blue; int res_step; int blackpos; int motor_step; int saved_skipcount; int channel; int saved_mode; int saved_invert; int skipcount; int saved_skipimagebyte; int skipimagebytes; int saved_adjustskip; int saved_res; int saved_hwres; int saved_res_step; int saved_line_step; int line_step; int saved_channel; unsigned char *calib_g; unsigned char *calib_r; unsigned char *calib_b; int line_diff; int bw; unsigned char **red; unsigned char **blue; unsigned char *green; int redline; int blueline; int ccd_line; int rdiff; int bdiff; int gdiff; int green_offs; int blue_offs; int motor_phase; int image_control; int lines; int lines_left; } mustek_pp_ccd300_priv; #endif sane-backends-1.0.27/backend/plustek-usbscan.c0000664000175000017500000013323312775277260016124 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbscan.c * @brief Scanning... * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2013 Gerhard Jaeger * * History: * - 0.40 - starting version of the USB support * - 0.41 - minor fixes * - 0.42 - added some stuff for CIS devices * - 0.43 - no changes * - 0.44 - added CIS specific settings and calculations * - removed usb_IsEscPressed * - 0.45 - fixed the special setting stuff for CanoScan * - fixed pixel calculation for binary modes * - fixed cancel hang problem * - fixed CIS PhyBytes adjustment * - removed CanoScan specific setting stuff * - 0.46 - fixed problem in usb_SetScanParameters() * - 0.47 - no changes * - 0.48 - minor fixes * - 0.49 - a_bRegs is now part of the device structure * - using now PhyDpi.y as selector for the motor MCLK range * - changed usb_MapDownload prototype * - 0.50 - cleanup * - 0.51 - added usb_get_res() and usb_GetPhyPixels() * - 0.52 - removed stuff, that will most probably never be used * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #define DIVIDER 8 /** array used to get motor-settings and mclk-settings */ static int dpi_ranges[] = { 75,100,150,200,300,400,600,800,1200,2400 }; static u_char bMaxITA; static SANE_Bool m_fAutoPark; static SANE_Bool m_fFirst; static double m_dHDPIDivider; static double m_dMCLKDivider; static ScanParam *m_pParam; static u_char m_bLineRateColor; static u_char m_bCM; static u_char m_bIntTimeAdjust; static u_char m_bOldScanData; static u_short m_wFastFeedStepSize; static u_short m_wLineLength; static u_short m_wStepSize; static u_long m_dwPauseLimit; static SANE_Bool m_fStart = SANE_FALSE; /* Prototype... */ static SANE_Bool usb_DownloadShadingData( Plustek_Device*, u_char ); /** returns the min of the two values val1 and val2 * @param val1 - first parameter * @param val2 - second parameter * @return val1 if val1 < val2, else val1 */ static u_long usb_min( u_long val1, u_long val2 ) { if( val1 > val2 ) return val2; return val1; } /** returns the max of the two values val1 and val2 * @param val1 - first parameter * @param val2 - second parameter * @return val1 if val1 > val2, else val2 */ static u_long usb_max( u_long val1, u_long val2 ) { if( val1 > val2 ) return val1; return val2; } /** function to get the possible resolution for a specific base resolution, * according to the dividers a LM983x offers. * @param base - scanners optical resolution * @param idx - which divider to use */ static u_short usb_get_res( u_short base, u_short idx ) { double div_list[DIVIDER] = { 12.0, 8.0, 6.0, 4.0, 3.0, 2.0, 1.5, 1.0 }; if( idx == 0 || idx > DIVIDER ) return 0; return (u_short)((double)base/div_list[idx-1]); } /** Set the horizontal DPI divider. * Affected registers:
* 0x09 - Horizontal DPI divider HDPI_DIV
* * @param dev - pointer to our device structure, * it should contain all we need * @param xdpi - user specified horizontal resolution * @return - the function returns the "normalized" horizontal resolution. */ static u_short usb_SetAsicDpiX( Plustek_Device *dev, u_short xdpi ) { u_short res; ScanDef *scanning = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; u_char *regs = dev->usbDev.a_bRegs; /* limit xdpi to lower value for certain devices... */ if( scaps->OpticDpi.x == 1200 && scanning->sParam.bDataType != SCANDATATYPE_Color && xdpi < 150 && scanning->sParam.bDataType == SCANDATATYPE_BW ) { xdpi = 150; DBG( _DBG_INFO2, "* LIMIT XDPI to %udpi\n", xdpi ); } m_dHDPIDivider = (double)scaps->OpticDpi.x / xdpi; if (m_dHDPIDivider < 1.5) { m_dHDPIDivider = 1.0; regs[0x09] = 0; } else if (m_dHDPIDivider < 2.0) { m_dHDPIDivider = 1.5; regs[0x09] = 1; } else if (m_dHDPIDivider < 3.0) { m_dHDPIDivider = 2.0; regs[0x09] = 2; } else if (m_dHDPIDivider < 4.0) { m_dHDPIDivider = 3.0; regs[0x09] = 3; } else if (m_dHDPIDivider < 6.0) { m_dHDPIDivider = 4.0; regs[0x09] = 4; } else if (m_dHDPIDivider < 8.0) { m_dHDPIDivider = 6.0; regs[0x09] = 5; } else if (m_dHDPIDivider < 12.0) { m_dHDPIDivider = 8.0; regs[0x09] = 6; } else { m_dHDPIDivider = 12.0; regs[0x09] = 7; } /* adjust, if any turbo/preview mode is set, should be 0 here... */ if( regs[0x0a] ) regs[0x09] -= ((regs[0x0a] >> 2) + 2); DBG( _DBG_INFO2, "* HDPI: %.3f\n", m_dHDPIDivider ); res = (u_short)((double)scaps->OpticDpi.x / m_dHDPIDivider); DBG( _DBG_INFO2, "* XDPI=%u, HDPI=%.3f\n", res, m_dHDPIDivider ); return res; } /** * @param dev - pointer to our device structure, * it should contain all we need * @param ydpi - user specified vertical resolution * @return - */ static u_short usb_SetAsicDpiY( Plustek_Device *dev, u_short ydpi ) { ScanDef *scanning = &dev->scanning; DCapsDef *sCaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_short wMinDpi, wDpi; if(0 != sCaps->bSensorDistance ) wMinDpi = sCaps->OpticDpi.y / sCaps->bSensorDistance; else wMinDpi = 75; /* Here we might have to check against the MinDpi value ! */ wDpi = (ydpi + wMinDpi - 1) / wMinDpi * wMinDpi; /* * HEINER: added '*2' */ if( wDpi > sCaps->OpticDpi.y * 2 ) wDpi = sCaps->OpticDpi.y * 2; if( (hw->motorModel == MODEL_Tokyo600) || !_IS_PLUSTEKMOTOR(hw->motorModel)) { /* return wDpi; */ } else if( sCaps->wFlags & DEVCAPSFLAG_Adf && sCaps->OpticDpi.x == 600 ) { /* for ADF scanner color mode 300 dpi big noise */ if( scanning->sParam.bDataType == SCANDATATYPE_Color && scanning->sParam.bBitDepth > 8 && wDpi < 300 ) { wDpi = 300; } } else if( sCaps->OpticDpi.x == 1200 ) { if( scanning->sParam.bDataType != SCANDATATYPE_Color && wDpi < 200) { wDpi = 200; } } DBG( _DBG_INFO2, "* YDPI=%u, MinDPIY=%u\n", wDpi, wMinDpi ); return wDpi; } /** set color mode and sensor configuration stuff, according to the data mode * Affected registers:
* 0x26 - 0x27 - Color Mode settings
* 0x0f - 0x18 - Sensor Configuration - directly from the HwDefs
* 0x09 - add Data Mode and Pixel Packing
* * @param dev - pointer to our device structure, * it should contain all we need * @param pParam - pointer to the current scan parameters * @return - Nothing */ static void usb_SetColorAndBits( Plustek_Device *dev, ScanParam *pParam ) { HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; /* Set pixel packing, data mode and AFE operation */ switch( pParam->bDataType ) { case SCANDATATYPE_Color: m_bCM = 3; regs[0x26] = hw->bReg_0x26 & 0x7; /* if set to one channel color, we select the blue channel * as input source, this is the default, but I don't know * what happens, if we deselect this */ if( regs[0x26] & _ONE_CH_COLOR ) regs[0x26] |= (_BLUE_CH | 0x01); memcpy( ®s[0x0f], hw->bReg_0x0f_Color, 10 ); break; case SCANDATATYPE_Gray: m_bCM = 1; regs[0x26] = (hw->bReg_0x26 & 0x18) | 0x04; memcpy( ®s[0x0f], hw->bReg_0x0f_Mono, 10 ); break; case SCANDATATYPE_BW: m_bCM = 1; regs[0x26] = (hw->bReg_0x26 & 0x18) | 0x04; memcpy( ®s[0x0f], hw->bReg_0x0f_Mono, 10 ); break; } regs[0x27] = hw->bReg_0x27; if( pParam->bBitDepth > 8 ) { regs[0x09] |= 0x20; /* 14/16bit image data */ } else if( pParam->bBitDepth == 8 ) { regs[0x09] |= 0x18; /* 8bits/per pixel */ } } /** * Data output from NS983X should be times of 2-byte and every line * will append 2 status bytes */ static void usb_GetPhyPixels( Plustek_Device *dev, ScanParam *sp ) { sp->Size.dwValidPixels = sp->Size.dwPixels * sp->PhyDpi.x / sp->UserDpi.x; if (sp->bBitDepth == 1) { /* Pixels should be times of 16 */ sp->Size.dwPhyPixels = (sp->Size.dwValidPixels + 15UL) & 0xfffffff0UL; sp->Size.dwPhyBytes = sp->Size.dwPhyPixels / 8UL + 2UL; } else if (sp->bBitDepth == 8) { /* Pixels should be times of 2 */ sp->Size.dwPhyPixels = (sp->Size.dwValidPixels + 1UL) & 0xfffffffeUL; sp->Size.dwPhyBytes = sp->Size.dwPhyPixels * sp->bChannels + 2UL; /* need to be adjusted fo CIS devices in color mode */ if(usb_IsCISDevice( dev ) && (sp->bDataType == SCANDATATYPE_Color)) { sp->Size.dwPhyBytes *= 3; } } else /* sp->bBitDepth == 16 */ { sp->Size.dwPhyPixels = sp->Size.dwValidPixels; sp->Size.dwPhyBytes = sp->Size.dwPhyPixels * 2 * sp->bChannels + 2UL; /* need to be adjusted fo CIS devices in color mode */ if(usb_IsCISDevice( dev ) && (sp->bDataType == SCANDATATYPE_Color)) { sp->Size.dwPhyBytes *= 3; } } } /** Calculate basic image settings like the number of physical bytes per line * etc... * Affected registers:
* 0x22/0x23 - Data Pixels Start
* 0x24/0x25 - Data Pixels End
* 0x4a/0x4b - Full Steps to Skip at Start of Scan * * @param dev - pointer to our device structure, * it should contain all we need * @param pParam - pointer to the current scan parameters * @return - Nothing */ static void usb_GetScanRect( Plustek_Device *dev, ScanParam *sp ) { u_short wDataPixelStart, wLineEnd; DCapsDef *sCaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; /* Convert pixels to physical dpi based */ usb_GetPhyPixels( dev, sp ); /* Compute data start pixel */ #if 0 /* HEINER: check ADF stuff... */ if(sp->bCalibration != PARAM_Gain && sp->bCalibration != PARAM_Offset && ScanInf.m_fADF) wDataPixelStart = 2550 * sCaps->OpticDpi.x / 300UL - (u_short)(m_dHDPIDivider * sp->Size.dwValidPixels + 0.5); else #endif wDataPixelStart = (u_short)((u_long)sp->Origin.x * sCaps->OpticDpi.x / 300UL); /* during the calibration steps, we read the entire CCD data */ if((sp->bCalibration != PARAM_Gain)&&(sp->bCalibration != PARAM_Offset)) { /* HEINER: check ADF stuff... */ #if 0 if(ScanInf.m_fADF) { wDataPixelStart = 2550 * sCaps->OpticDpi.x / 300UL - (u_short)(m_dHDPIDivider * sp->Size.dwValidPixels + 0.5); } #endif wDataPixelStart += hw->wActivePixelsStart; } wLineEnd = wDataPixelStart + (u_short)(m_dHDPIDivider * sp->Size.dwPhyPixels + 0.5); DBG( _DBG_INFO2, "* DataPixelStart=%u, LineEnd=%u\n", wDataPixelStart, wLineEnd ); if( wDataPixelStart & 1 ) { wDataPixelStart++; wLineEnd++; DBG( _DBG_INFO2, "* DataPixelStart=%u, LineEnd=%u (ADJ)\n", wDataPixelStart, wLineEnd ); } regs[0x22] = _HIBYTE( wDataPixelStart ); regs[0x23] = _LOBYTE( wDataPixelStart ); /* should match: wLineEnd-wDataPixelStart%(m_dHDPIDivider*2) = 0!! */ regs[0x24] = _HIBYTE( wLineEnd ); regs[0x25] = _LOBYTE( wLineEnd ); DBG( _DBG_INFO2, ">> End-Start=%u, HDPI=%.2f\n", wLineEnd-wDataPixelStart, m_dHDPIDivider); /* Y origin */ if( sp->bCalibration == PARAM_Scan ) { if( hw->motorModel == MODEL_Tokyo600 ) { if(sp->PhyDpi.x <= 75) sp->Origin.y += 20; else if(sp->PhyDpi.x <= 100) { if (sp->bDataType == SCANDATATYPE_Color) sp->Origin.y += 0; else sp->Origin.y -= 6; } else if(sp->PhyDpi.x <= 150) { if (sp->bDataType == SCANDATATYPE_Color) sp->Origin.y -= 0; } else if(sp->PhyDpi.x <= 200) { if (sp->bDataType == SCANDATATYPE_Color) sp->Origin.y -= 10; else sp->Origin.y -= 4; } else if(sp->PhyDpi.x <= 300) { if (sp->bDataType == SCANDATATYPE_Color) sp->Origin.y += 16; else sp->Origin.y -= 18; } else if(sp->PhyDpi.x <= 400) { if (sp->bDataType == SCANDATATYPE_Color) sp->Origin.y += 15; else if(sp->bDataType == SCANDATATYPE_BW) sp->Origin.y += 4; } else /* if(sp->PhyDpi.x <= 600) */ { if (sp->bDataType == SCANDATATYPE_Gray) sp->Origin.y += 4; } } /* Add gray mode offset (Green offset, we assume the CCD are * always be RGB or BGR order). */ if (sp->bDataType != SCANDATATYPE_Color) sp->Origin.y += (u_long)(300UL * sCaps->bSensorDistance / sCaps->OpticDpi.y); } sp->Origin.y=(u_short)((u_long)sp->Origin.y * hw->wMotorDpi/300UL); /* Something wrong, but I can not find it. */ if( hw->motorModel == MODEL_HuaLien && sCaps->OpticDpi.x == 600) sp->Origin.y = sp->Origin.y * 297 / 298; DBG(_DBG_INFO2,"* Full Steps to Skip at Start = 0x%04x\n", sp->Origin.y); regs[0x4a] = _HIBYTE( sp->Origin.y ); regs[0x4b] = _LOBYTE( sp->Origin.y ); } /** preset scan stepsize and fastfeed stepsize */ static void usb_PresetStepSize( Plustek_Device *dev, ScanParam *pParam ) { u_short ssize; double mclkdiv = pParam->dMCLK; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; ssize = (u_short)((double)CRYSTAL_FREQ / ( mclkdiv * 8.0 * (double)m_bCM * hw->dMaxMotorSpeed * 4.0 * (double)hw->wMotorDpi)); regs[0x46] = _HIBYTE( ssize ); regs[0x47] = _LOBYTE( ssize ); regs[0x48] = _HIBYTE( ssize ); regs[0x49] = _LOBYTE( ssize ); DBG( _DBG_INFO2, "* StepSize(Preset) = %u (0x%04x)\n", ssize, ssize ); } /** calculate default phase difference DPD */ static void usb_GetDPD( Plustek_Device *dev ) { int qtcnt; /* quarter speed count count reg 51 b2..3 */ int hfcnt; /* half speed count reg 51 b0..1 */ int strev; /* steps to reverse reg 50 */ int dpd; /* calculated dpd reg 52:53 */ int st; /* step size reg 46:47 */ HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; qtcnt = (regs[0x51] & 0x30) >> 4; /* quarter speed count */ hfcnt = (regs[0x51] & 0xc0) >> 6; /* half speed count */ if( _LM9831 == hw->chip ) strev = regs[0x50] & 0x3f; /* steps to reverse */ else /* LM9832/3 */ { if (qtcnt == 3) qtcnt = 8; if (hfcnt == 3) hfcnt = 8; strev = regs[0x50]; /* steps to reverse */ } st = regs[0x46] * 256 + regs[0x47]; /* scan step size */ if (m_wLineLength == 0) dpd = 0; else { dpd = (((qtcnt * 4) + (hfcnt * 2) + strev) * 4 * st) % (m_wLineLength * m_bLineRateColor); DBG( _DBG_INFO2, "* DPD =%u (0x%04x)\n", dpd, dpd ); dpd = m_wLineLength * m_bLineRateColor - dpd; } DBG( _DBG_INFO2, "* DPD =%u (0x%04x), step size=%u, steps2rev=%u\n", dpd, dpd, st, strev); DBG( _DBG_INFO2, "* llen=%u, lineRateColor=%u, qtcnt=%u, hfcnt=%u\n", m_wLineLength, m_bLineRateColor, qtcnt, hfcnt ); regs[0x51] |= (u_char)((dpd >> 16) & 0x03); regs[0x52] = (u_char)(dpd >> 8); regs[0x53] = (u_char)(dpd & 0xFF); } #define MCLKDIV_SCALING 2 #define _MIN(a,b) ((a) < (b) ? (a) : (b)) #define _MAX(a,b) ((a) > (b) ? (a) : (b)) /** */ static int usb_GetMCLKDiv( Plustek_Device *dev ) { int j, pixelbits, pixelsperline, r; int minmclk, maxmclk, mclkdiv; double hdpi, min_int_time; u_char *regs = dev->usbDev.a_bRegs; HWDef *hw = &dev->usbDev.HwSetting; DBG( _DBG_INFO, "usb_GetMCLKDiv()\n" ); r = 8; /* line rate */ if ((regs[0x26] & 7) == 0) r = 24; /* pixel rate */ /* use high or low res min integration time */ min_int_time = ((regs[0x9]&7) > 2 ? hw->dMinIntegrationTimeLowres: hw->dMinIntegrationTimeHighres); minmclk = (int)ceil((double) MCLKDIV_SCALING * CRYSTAL_FREQ * min_int_time /((double)1000. * r * m_wLineLength)); minmclk = _MAX(minmclk,MCLKDIV_SCALING); maxmclk = (int)(32.5*MCLKDIV_SCALING + .5); DBG(_DBG_INFO2,"- lower mclkdiv limit=%f\n",(double)minmclk/MCLKDIV_SCALING); DBG(_DBG_INFO2,"- upper mclkdiv limit=%f\n",(double)maxmclk/MCLKDIV_SCALING); /* get the bits per pixel */ switch (regs[0x9] & 0x38) { case 0: pixelbits=1; break; case 0x8: pixelbits=2; break; case 0x10: pixelbits=4; break; case 0x18: pixelbits=8; break; default: pixelbits=16;break; } /* compute the horizontal dpi (pixels per inch) */ j = regs[0x9] & 0x7; hdpi = ((j&1)*.5+1)*(j&2?2:1)*(j&4?4:1); pixelsperline = (int)((256*regs[0x24]+regs[0x25]-256*regs[0x22]-regs[0x23]) *pixelbits/(hdpi * 8)); mclkdiv = (int)ceil((double)MCLKDIV_SCALING * pixelsperline * CRYSTAL_FREQ /((double) 8. * m_wLineLength * dev->transferRate)); DBG( _DBG_INFO2, "- hdpi = %.3f\n", hdpi ); DBG( _DBG_INFO2, "- pixelbits = %u\n", pixelbits ); DBG( _DBG_INFO2, "- pixelsperline = %u\n", pixelsperline ); DBG( _DBG_INFO2, "- linelen = %u\n", m_wLineLength ); DBG( _DBG_INFO2, "- transferrate = %lu\n", dev->transferRate ); DBG( _DBG_INFO2, "- MCLK Divider = %u\n", mclkdiv/MCLKDIV_SCALING ); mclkdiv = _MAX(mclkdiv,minmclk); mclkdiv = _MIN(mclkdiv,maxmclk); DBG( _DBG_INFO2, "- Current MCLK Divider = %u\n", mclkdiv/MCLKDIV_SCALING ); if( dev->transferRate == 2000000 ) { while (mclkdiv * hdpi < 6.*MCLKDIV_SCALING) { mclkdiv++; } DBG( _DBG_INFO2, "- HIGHSPEED MCLK Divider = %u\n", mclkdiv/MCLKDIV_SCALING ); } return mclkdiv; } /** Plusteks' poor-man MCLK calculation... * at least we give the master clock divider and adjust the step size * and integration time (for 14/16 bit modes) */ static double usb_GetMCLKDivider( Plustek_Device *dev, ScanParam *pParam ) { double dMaxIntegrationTime; double dMaxMCLKDivider; DCapsDef *sCaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; DBG( _DBG_INFO, "usb_GetMCLKDivider()\n" ); if( dev->transferRate == 2000000 ) { int mclkdiv = usb_GetMCLKDiv(dev); pParam->dMCLK = (double)mclkdiv/MCLKDIV_SCALING; } m_dMCLKDivider = pParam->dMCLK; if (m_dHDPIDivider*m_dMCLKDivider >= 5.3/*6*/) m_bIntTimeAdjust = 0; else m_bIntTimeAdjust = ceil( 5.3/*6.0*/ / (m_dHDPIDivider*m_dMCLKDivider)); if( pParam->bCalibration == PARAM_Scan ) { usb_GetMCLKDiv(dev); /* Compare Integration with USB speed to find the best ITA value */ if( pParam->bBitDepth > 8 ) { while( pParam->Size.dwPhyBytes > (m_dMCLKDivider * m_bCM * m_wLineLength / 6 * 9 / 10) * (1 + m_bIntTimeAdjust)) { m_bIntTimeAdjust++; } if( hw->motorModel == MODEL_HuaLien && sCaps->bCCD == kNEC3799 && m_bIntTimeAdjust > bMaxITA) { m_bIntTimeAdjust = bMaxITA; } if(((hw->motorModel == MODEL_HP) && (sCaps->bCCD == kNECSLIM))/* || ( regs[0x26] & _ONE_CH_COLOR )*/) { bMaxITA = (u_char)floor((m_dMCLKDivider + 1) / 2.0); DBG( _DBG_INFO2, "* MaxITA (HP) = %u\n", bMaxITA ); if( m_bIntTimeAdjust > bMaxITA ) { DBG( _DBG_INFO, "* ITA (%u) limited\n", m_bIntTimeAdjust ); m_bIntTimeAdjust = bMaxITA; } } } } DBG( _DBG_INFO2, "* Integration Time Adjust = %u (HDPI=%.3f,MCLKD=%.3f)\n", m_bIntTimeAdjust, m_dHDPIDivider, m_dMCLKDivider ); regs[0x08] = (u_char)((m_dMCLKDivider - 1) * 2); regs[0x19] = m_bIntTimeAdjust; if( m_bIntTimeAdjust != 0 ) { m_wStepSize = (u_short)((u_long) m_wStepSize * (m_bIntTimeAdjust + 1) / m_bIntTimeAdjust); if( m_wStepSize < 2 ) m_wStepSize = 2; regs[0x46] = _HIBYTE(m_wStepSize); regs[0x47] = _LOBYTE(m_wStepSize); DBG( _DBG_INFO2, "* Stepsize = %u, 0x46=0x%02x 0x47=0x%02x\n", m_wStepSize, regs[0x46], regs[0x47] ); usb_GetDPD( dev ); } /* Compute maximum MCLK divider base on maximum integration time for * high lamp PWM, use equation 4 */ dMaxIntegrationTime = hw->dIntegrationTimeHighLamp; dMaxMCLKDivider = (double)CRYSTAL_FREQ * dMaxIntegrationTime / (1000 * 8 * m_bCM * m_wLineLength); /* Determine lamp PWM setting */ if( m_dMCLKDivider > dMaxMCLKDivider ) { DBG( _DBG_INFO2, "* Setting GreenPWMDutyCycleLow\n" ); regs[0x2a] = _HIBYTE( hw->wGreenPWMDutyCycleLow ); regs[0x2b] = _LOBYTE( hw->wGreenPWMDutyCycleLow ); } else { DBG( _DBG_INFO2, "* Setting GreenPWMDutyCycleHigh\n" ); regs[0x2a] = _HIBYTE( hw->wGreenPWMDutyCycleHigh ); regs[0x2b] = _LOBYTE( hw->wGreenPWMDutyCycleHigh ); } DBG( _DBG_INFO2, "* Current MCLK Divider = %f\n", m_dMCLKDivider ); return m_dMCLKDivider; } /** calculate the step size of each scan step */ static void usb_GetStepSize( Plustek_Device *dev, ScanParam *pParam ) { HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; /* Compute step size using equation 1 */ if (m_bIntTimeAdjust != 0) { m_wStepSize = (u_short)(((u_long) pParam->PhyDpi.y * m_wLineLength * m_bLineRateColor * (m_bIntTimeAdjust + 1)) / (4 * hw->wMotorDpi * m_bIntTimeAdjust)); } else { m_wStepSize = (u_short)(((u_long) pParam->PhyDpi.y * m_wLineLength * m_bLineRateColor) / (4 * hw->wMotorDpi)); } if (m_wStepSize < 2) m_wStepSize = 2; m_wStepSize = m_wStepSize * 298 / 297; regs[0x46] = _HIBYTE( m_wStepSize ); regs[0x47] = _LOBYTE( m_wStepSize ); DBG( _DBG_INFO2, "* Stepsize = %u, 0x46=0x%02x 0x47=0x%02x\n", m_wStepSize, regs[0x46], regs[0x47] ); } /** */ static void usb_GetLineLength( Plustek_Device *dev, ScanParam *param ) { /* [note] * The ITA in this moment is always 0, it will be changed later when we * calculate MCLK. This is very strange why this routine will not call * again to get all new value after ITA was changed? If this routine * never call again, maybe we remove all factor with ITA here. */ int tr; int tpspd; /* turbo/preview mode speed reg 0a b2..3 */ int tpsel; /* turbo/preview mode select reg 0a b0..1 */ int gbnd; /* guardband duration reg 0e b4..7 */ int dur; /* pulse duration reg 0e b0..3 */ int ntr; /* number of tr pulses reg 0d b7 */ int afeop; /* scan mode, 0=pixel rate, 1=line rate, */ /* 4=1 channel mode a, 5=1 channel mode b, reg 26 b0..2 */ int ctmode; /* CIS tr timing mode reg 19 b0..1 */ int tp; /* tpspd or 1 if tpsel=0 */ int b; /* if ctmode=0, (ntr+1)*((2*gbnd)+dur+1), otherwise 1 */ int tradj; /* ITA */ int en_tradj; u_short le; HWDef *hw = &dev->usbDev.HwSetting; ClkMotorDef *motor = usb_GetMotorSet( hw->motorModel ); u_char *regs = dev->usbDev.a_bRegs; tpspd = (regs[0x0a] & 0x0c) >> 2; /* turbo/preview mode speed */ tpsel = regs[0x0a] & 3; /* turbo/preview mode select */ gbnd = (regs[0x0e] & 0xf0) >> 4; /* TR fi1 guardband duration */ dur = (regs[0x0e] & 0xf); /* TR pulse duration */ ntr = regs[0x0d] / 128; /* number of tr pulses */ afeop = regs[0x26] & 7; /* afe op - 3 channel or 1 channel */ tradj = regs[0x19] & 0x7f; /* integration time adjust */ en_tradj = (tradj) ? 1 : 0; ctmode = (regs[0x0b] >> 3) & 3; /* cis tr timing mode */ m_bLineRateColor = 1; if (afeop == 1 || afeop == 5) /* if 3 channel line or 1 channel mode b */ m_bLineRateColor = 3; /* according to turbo/preview mode to set value */ if( tpsel == 0 ) { tp = 1; } else { tp = tpspd + 2; if( tp == 5 ) tp++; } b = 1; if( ctmode == 0 ) { /* CCD mode scanner*/ b = (ntr + 1) * ((2 * gbnd) + dur + 1); b += (1 - ntr) * en_tradj; } if( ctmode == 2 ) /* CIS mode scanner */ b = 3; /* it might be necessary to tweak this value, to keep the * MCLK constant - see some sheet-fed devices */ le = hw->wLineEnd; if (motor->dpi_thresh != 0) { if( param->PhyDpi.y <= motor->dpi_thresh) { le = motor->lineend; DBG( _DBG_INFO2, "* Adjusting lineend: %u\n", le); } regs[0x20] = _HIBYTE( le ); regs[0x21] = _LOBYTE( le ); } tr = m_bLineRateColor * (le + tp * (b + 3 - ntr)); if( tradj == 0 ) { if( ctmode == 0 ) tr += m_bLineRateColor; } else { int le_phi, num_byteclk, num_mclkf, tr_fast_pix, extra_pix; /* Line color or gray mode */ if( afeop != 0 ) { le_phi = (tradj + 1) / 2 + 1 + 6; num_byteclk = ((le_phi + 8 * le + 8 * b + 4) / (8 * tradj)) + 1; num_mclkf = 8 * tradj * num_byteclk; tr_fast_pix = num_byteclk; extra_pix = (num_mclkf - le_phi) % 8; } else /* 3 channel pixel rate color */ { le_phi = (tradj + 1) / 2 + 1 + 10 + 12; num_byteclk = ((le_phi + 3 * 8 * le + 3 * 8 * b + 3 * 4) / (3 * 8 * tradj)) + 1; num_mclkf = 3 * 8 * tradj * num_byteclk; tr_fast_pix = num_byteclk; extra_pix = (num_mclkf - le_phi) % (3 * 8); } tr = b + le + 4 + tr_fast_pix; if (extra_pix == 0) tr++; tr *= m_bLineRateColor; } m_wLineLength = tr / m_bLineRateColor; DBG( _DBG_INFO2, "* LineLength=%d, LineRateColor=%u\n", m_wLineLength, m_bLineRateColor ); } /** usb_GetMotorParam * registers 0x56, 0x57 */ static void usb_GetMotorParam( Plustek_Device *dev, ScanParam *pParam ) { int idx, i; ClkMotorDef *clk; MDef *md; DCapsDef *sCaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; if (!_IS_PLUSTEKMOTOR(hw->motorModel)) { clk = usb_GetMotorSet( hw->motorModel ); md = clk->motor_sets; idx = 0; for( i = 0; i < _MAX_CLK; i++ ) { if( pParam->PhyDpi.y <= dpi_ranges[i] ) break; idx++; } if( idx >= _MAX_CLK ) idx = _MAX_CLK - 1; regs[0x56] = md[idx].pwm; regs[0x57] = md[idx].pwm_duty; regs[0x43] = 0; regs[0x44] = 0; if( md[idx].scan_lines_per_line > 1 ) { if((pParam->bBitDepth > 8) && (pParam->bDataType == SCANDATATYPE_Color)) { regs[0x43] = 0xff; regs[0x44] = md[idx].scan_lines_per_line; DBG( _DBG_INFO2, "* Line Skipping : 0x43=0x%02x, 0x44=0x%02x\n", regs[0x43], regs[0x44] ); } } } else { if( sCaps->OpticDpi.x == 1200 ) { switch( hw->motorModel ) { case MODEL_HuaLien: case MODEL_KaoHsiung: default: if(pParam->PhyDpi.x <= 200) { regs[0x56] = 1; regs[0x57] = 48; /* 63; */ } else if(pParam->PhyDpi.x <= 300) { regs[0x56] = 2; /* 8; */ regs[0x57] = 48; /* 56; */ } else if(pParam->PhyDpi.x <= 400) { regs[0x56] = 8; regs[0x57] = 48; } else if(pParam->PhyDpi.x <= 600) { regs[0x56] = 2; /* 10; */ regs[0x57] = 48; /* 56; */ } else /* pParam->PhyDpi.x == 1200) */ { regs[0x56] = 1; /* 8; */ regs[0x57] = 48; /* 56; */ } break; } } else { switch ( hw->motorModel ) { case MODEL_Tokyo600: regs[0x56] = 16; regs[0x57] = 4; /* 2; */ break; case MODEL_HuaLien: { if(pParam->PhyDpi.x <= 200) { regs[0x56] = 64; /* 24; */ regs[0x57] = 4; /* 16; */ } else if(pParam->PhyDpi.x <= 300) { regs[0x56] = 64; /* 16; */ regs[0x57] = 4; /* 16; */ } else if(pParam->PhyDpi.x <= 400) { regs[0x56] = 64; /* 16; */ regs[0x57] = 4; /* 16; */ } else /* if(pParam->PhyDpi.x <= 600) */ { /* HEINER: check ADF stuff... */ #if 0 if(ScanInf.m_fADF) { regs[0x56] = 8; regs[0x57] = 48; } else #endif { regs[0x56] = 64; /* 2; */ regs[0x57] = 4; /* 48; */ } } } break; case MODEL_KaoHsiung: default: if(pParam->PhyDpi.x <= 200) { regs[0x56] = 24; regs[0x57] = 16; } else if(pParam->PhyDpi.x <= 300) { regs[0x56] = 16; regs[0x57] = 16; } else if(pParam->PhyDpi.x <= 400) { regs[0x56] = 16; regs[0x57] = 16; } else /* if(pParam->PhyDpi.x <= 600) */ { regs[0x56] = 2; regs[0x57] = 48; } break; } } } DBG( _DBG_INFO2, "* MOTOR-Settings: PWM=0x%02x, PWM_DUTY=0x%02x\n", regs[0x56], regs[0x57] ); } /** */ static void usb_GetPauseLimit( Plustek_Device *dev, ScanParam *pParam ) { int coeffsize, scaler; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; scaler = 1; if( hw->bReg_0x26 & _ONE_CH_COLOR ) { if( pParam->bDataType == SCANDATATYPE_Color ) { scaler = 3; } } /* compute size of coefficient ram */ coeffsize = 4 + 16 + 16; /* gamma and shading and offset */ /* if 16 bit, then not all is used */ if( regs[0x09] & 0x20 ) { coeffsize = 16 + 16; /* no gamma */ } coeffsize *= (2*3); /* 3 colors and 2 bytes/word */ /* Get available buffer size in KB * for 512kb this will be 296 * for 2Mb this will be 1832 */ m_dwPauseLimit = (u_long)(hw->wDRAMSize - (u_long)(coeffsize)); m_dwPauseLimit -= ((pParam->Size.dwPhyBytes*scaler) / 1024 + 1); /* If not reversing, take into account the steps to reverse */ if( regs[0x50] == 0 ) m_dwPauseLimit -= ((regs[0x54] & 7) * (pParam->Size.dwPhyBytes * scaler) + 1023) / 1024; DBG( _DBG_INFO2, "* PL=%lu, coeffsize=%u, scaler=%u\n", m_dwPauseLimit, coeffsize, scaler ); m_dwPauseLimit = usb_max( usb_min(m_dwPauseLimit, (u_long)ceil(pParam->Size.dwTotalBytes / 1024.0)), 2); regs[0x4e] = (u_char)floor((m_dwPauseLimit*512.0)/(2.0*hw->wDRAMSize)); if( regs[0x4e] > 1 ) { regs[0x4e]--; if(regs[0x4e] > 1) regs[0x4e]--; } else regs[0x4e] = 1; /* resume, when buffer is 2/8 kbytes full (512k/2M memory) */ regs[0x4f] = 1; DBG( _DBG_INFO2, "* PauseLimit = %lu, [0x4e] = 0x%02x, [0x4f] = 0x%02x\n", m_dwPauseLimit, regs[0x4e], regs[0x4f] ); } /** usb_GetScanLinesAndSize */ static void usb_GetScanLinesAndSize( Plustek_Device *dev, ScanParam *pParam ) { DCapsDef *sCaps = &dev->usbDev.Caps; pParam->Size.dwPhyLines = (u_long)ceil((double) pParam->Size.dwLines * pParam->PhyDpi.y / pParam->UserDpi.y); /* Calculate color offset */ if (pParam->bCalibration == PARAM_Scan && pParam->bChannels == 3) { dev->scanning.bLineDistance = sCaps->bSensorDistance * pParam->PhyDpi.y / sCaps->OpticDpi.x; pParam->Size.dwPhyLines += (dev->scanning.bLineDistance << 1); } else dev->scanning.bLineDistance = 0; pParam->Size.dwTotalBytes = pParam->Size.dwPhyBytes * pParam->Size.dwPhyLines; DBG( _DBG_INFO, "* PhyBytes = %lu\n", pParam->Size.dwPhyBytes ); DBG( _DBG_INFO, "* PhyLines = %lu\n", pParam->Size.dwPhyLines ); DBG( _DBG_INFO, "* TotalBytes = %lu\n", pParam->Size.dwTotalBytes ); } /** function to preset/reset the merlin registers */ static SANE_Bool usb_SetScanParameters( Plustek_Device *dev, ScanParam *pParam ) { static u_char reg8, reg38[6], reg48[2]; ScanDef *scan = &dev->scanning; ScanParam *pdParam = &dev->scanning.sParam; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; m_pParam = pParam; DBG( _DBG_INFO, "usb_SetScanParameters()\n" ); if( !usb_IsScannerReady(dev)) return SANE_FALSE; if(pParam->bCalibration == PARAM_Scan && pParam->bSource == SOURCE_ADF) { /* HEINER: dSaveMoveSpeed is only used in func EjectPaper!!! dSaveMoveSpeed = hw->dMaxMoveSpeed; */ hw->dMaxMoveSpeed = 1.0; usb_MotorSelect( dev, SANE_TRUE ); usb_MotorOn( dev, SANE_TRUE ); } /* * calculate the basic settings... */ pParam->PhyDpi.x = usb_SetAsicDpiX( dev, pParam->UserDpi.x ); pParam->PhyDpi.y = usb_SetAsicDpiY( dev, pParam->UserDpi.y ); usb_SetColorAndBits( dev, pParam ); usb_GetScanRect ( dev, pParam ); usb_PresetStepSize( dev, pParam ); if( dev->caps.dwFlag & SFLAG_ADF ) { if( pParam->bCalibration == PARAM_Scan ) { if( pdParam->bSource == SOURCE_ADF ) { regs[0x50] = 0; regs[0x51] = 0x40; if( pParam->PhyDpi.x <= 300) regs[0x54] = (regs[0x54] & ~7) | 4; /* 3; */ else regs[0x54] = (regs[0x54] & ~7) | 5; /* 4; */ } else { regs[0x50] = hw->bStepsToReverse; regs[0x51] = hw->bReg_0x51; regs[0x54] &= ~7; } } else regs[0x50] = 0; } else { if( pParam->bCalibration == PARAM_Scan ) regs[0x50] = hw->bStepsToReverse; else regs[0x50] = 0; } /* Assume we will not use ITA */ regs[0x19] = m_bIntTimeAdjust = 0; /* Get variables from calculation algorithms */ if(!(pParam->bCalibration == PARAM_Scan && pParam->bSource == SOURCE_ADF && dev->usbDev.fLastScanIsAdf )) { DBG( _DBG_INFO2, "* Scan calculations...\n" ); usb_GetLineLength ( dev, pParam ); usb_GetStepSize ( dev, pParam ); usb_GetDPD ( dev ); usb_GetMCLKDivider( dev, pParam ); usb_GetMotorParam ( dev, pParam ); } /* Compute fast feed step size, use equation 3 and equation 8 */ if( m_dMCLKDivider < 1.0) m_dMCLKDivider = 1.0; m_wFastFeedStepSize = (u_short)(CRYSTAL_FREQ / (m_dMCLKDivider * 8 * m_bCM * hw->dMaxMoveSpeed * 4 * hw->wMotorDpi)); /* CIS special ;-) */ if((hw->bReg_0x26 & _ONE_CH_COLOR) && (m_bCM == 1)) { DBG( _DBG_INFO2, "* CIS FFStep-Speedup\n" ); m_wFastFeedStepSize /= 3; } if( m_bIntTimeAdjust != 0 ) m_wFastFeedStepSize /= m_bIntTimeAdjust; if(regs[0x0a]) m_wFastFeedStepSize *= ((regs[0x0a] >> 2) + 2); regs[0x48] = _HIBYTE( m_wFastFeedStepSize ); regs[0x49] = _LOBYTE( m_wFastFeedStepSize ); DBG( _DBG_INFO2, "* FFStepSize = %u, [0x48] = 0x%02x, [0x49] = 0x%02x\n", m_wFastFeedStepSize, regs[0x48], regs[0x49] ); /* Compute the number of lines to scan using actual Y resolution */ usb_GetScanLinesAndSize( dev, pParam ); /* Pause limit should be bounded by total bytes to read * so that the chassis will not move too far. */ usb_GetPauseLimit( dev, pParam ); /* For ADF .... */ if(pParam->bCalibration == PARAM_Scan && pParam->bSource == SOURCE_ADF) { if( dev->usbDev.fLastScanIsAdf ) { regs[0x08] = reg8; memcpy( ®s[0x38], reg38, sizeof(reg38)); memcpy( ®s[0x48], reg48, sizeof(reg48)); } else { reg8 = regs[0x08]; memcpy( reg38, ®s[0x38], sizeof(reg38)); memcpy( reg48, ®s[0x48], sizeof(reg48)); } usb_MotorSelect( dev, SANE_TRUE ); } /* Reset LM983x's state machine before setting register values */ if( !usbio_WriteReg( dev->fd, 0x18, 0x18 )) return SANE_FALSE; usleep(200 * 1000); /* Need to delay at least xxx microseconds */ if( !usbio_WriteReg( dev->fd, 0x07, 0x20 )) return SANE_FALSE; if( !usbio_WriteReg( dev->fd, 0x19, 6 )) return SANE_FALSE; regs[0x07] = 0; regs[0x28] = 0; /* set unused registers to 0 */ memset( ®s[0x03], 0, 3 ); memset( ®s[0x5f], 0, 0x7f-0x5f+1 ); if( !usb_IsSheetFedDevice(dev)) { /* we limit the possible scansteps to avoid, that the sensors bumps * against the scanbed - not necessary for sheet-fed devices */ if(pParam->bCalibration==PARAM_Scan && pParam->bSource!=SOURCE_ADF) { u_long lines = pParam->Size.dwPhyLines + scan->bLinesToSkip + scan->dwLinesDiscard + 5; u_short scansteps = (u_short)ceil((double)lines* hw->wMotorDpi / pParam->PhyDpi.y); DBG( _DBG_INFO, "* Scansteps=%u (%lu*%u/%u)\n", scansteps, lines, hw->wMotorDpi, pParam->PhyDpi.y ); regs[0x4c] = _HIBYTE(scansteps); regs[0x4d] = _LOBYTE(scansteps); } } /* set the merlin registers */ _UIO(sanei_lm983x_write( dev->fd, 0x03, ®s[0x03], 3, SANE_TRUE)); _UIO(sanei_lm983x_write( dev->fd, 0x08, ®s[0x08], 0x7f - 0x08+1, SANE_TRUE)); usleep(100); if( !usbio_WriteReg( dev->fd, 0x07, 0 )) return SANE_FALSE; DBG( _DBG_INFO, "usb_SetScanParameters() done.\n" ); return SANE_TRUE; } /** */ static SANE_Bool usb_ScanBegin( Plustek_Device *dev, SANE_Bool auto_park ) { u_char value; u_short inches; HWDef *hw = &dev->usbDev.HwSetting; DCapsDef *sc = &dev->usbDev.Caps; u_char *regs = dev->usbDev.a_bRegs; DBG( _DBG_INFO, "usb_ScanBegin()\n" ); if( !usb_Wait4ScanSample( dev )) return SANE_FALSE; /* save the request for usb_ScanEnd () */ m_fAutoPark = auto_park; /* Disable home sensor during scan, or the chassis cannot move */ value = ((m_pParam->bCalibration == PARAM_Scan && m_pParam->bSource == SOURCE_ADF)? (regs[0x58] & ~7): 0); if(!usbio_WriteReg( dev->fd, 0x58, value )) return SANE_FALSE; /* Check if scanner is ready for receiving command */ if( !usb_IsScannerReady(dev)) return SANE_FALSE; /* Flush cache - only LM9831 (Source: National Semiconductors) */ if( _LM9831 == hw->chip ) { for(;;) { if( SANE_TRUE == cancelRead ) { DBG( _DBG_INFO, "ScanBegin() - Cancel detected...\n" ); return SANE_FALSE; } _UIO(usbio_ReadReg( dev->fd, 0x01, &m_bOldScanData )); if( m_bOldScanData ) { u_long dwBytesToRead = m_bOldScanData * hw->wDRAMSize * 4; u_char *pBuffer = malloc( sizeof(u_char) * dwBytesToRead ); DBG(_DBG_INFO,"Flushing cache - %lu bytes (bOldScanData=%u)\n", dwBytesToRead, m_bOldScanData ); _UIO(sanei_lm983x_read( dev->fd, 0x00, pBuffer, dwBytesToRead, SANE_FALSE )); free( pBuffer ); } else break; } } /* Download map & Shading data */ if(( m_pParam->bCalibration == PARAM_Scan && !usb_MapDownload( dev )) || !usb_DownloadShadingData( dev, m_pParam->bCalibration )) { return SANE_FALSE; } /* Move chassis and start to read image data */ if (!usbio_WriteReg( dev->fd, 0x07, 3 )) return SANE_FALSE; usbio_ReadReg( dev->fd, 0x01, &m_bOldScanData ); m_bOldScanData = 0; /* No data at all */ m_fStart = m_fFirst = SANE_TRUE; /* Prepare to read */ DBG( _DBG_DREGS, "Register Dump before reading data:\n" ); dumpregs( dev->fd, NULL ); inches = (u_short)((m_pParam->Origin.y *300UL)/hw->wMotorDpi); DBG( _DBG_INFO2, ">>> INCH=%u, DOY=%u\n", inches, sc->Normal.DataOrigin.y ); if( inches > sc->Normal.DataOrigin.y ) usb_WaitPos( dev, 150, SANE_FALSE ); DBG( _DBG_INFO, "usb_ScanBegin() done.\n" ); return SANE_TRUE; } /** usb_ScanEnd * stop all the processing stuff and reposition sensor back home */ static SANE_Bool usb_ScanEnd( Plustek_Device *dev ) { u_char value; DBG( _DBG_INFO, "usbDev_ScanEnd(), start=%u, park=%u\n", m_fStart, m_fAutoPark ); usbio_ReadReg( dev->fd, 0x07, &value ); if( value == 3 || value != 2 ) usbio_WriteReg( dev->fd, 0x07, 0 ); if( m_fStart ) { m_fStart = SANE_FALSE; if( m_fAutoPark ) usb_ModuleToHome( dev, SANE_FALSE ); } else if( SANE_TRUE == cancelRead ) { usb_ModuleToHome( dev, SANE_FALSE ); } return SANE_TRUE; } /** */ static SANE_Bool usb_IsDataAvailableInDRAM( Plustek_Device *dev ) { /* Compute polling timeout * Height (Inches) / MaxScanSpeed (Inches/Second) = Seconds to move the * module from top to bottom. Then convert the seconds to miliseconds * by multiply 1000. We add extra 2 seconds to get some tolerance. */ u_char a_bBand[3]; long dwTicks; struct timeval t; u_char *regs = dev->usbDev.a_bRegs; DBG( _DBG_INFO, "usb_IsDataAvailableInDRAM()\n" ); gettimeofday( &t, NULL); dwTicks = t.tv_sec + 30; for(;;) { _UIO( sanei_lm983x_read( dev->fd, 0x01, a_bBand, 3, SANE_FALSE )); gettimeofday( &t, NULL); if( t.tv_sec > dwTicks ) break; if( usb_IsEscPressed()) { DBG(_DBG_INFO,"usb_IsDataAvailableInDRAM() - Cancel detected...\n"); return SANE_FALSE; } /* It is not stable for read */ if((a_bBand[0] != a_bBand[1]) && (a_bBand[1] != a_bBand[2])) continue; if( a_bBand[0] > m_bOldScanData ) { if( m_pParam->bSource != SOURCE_Reflection ) usleep(1000*(30 * regs[0x08] * dev->usbDev.Caps.OpticDpi.x / 600)); else usleep(1000*(20 * regs[0x08] * dev->usbDev.Caps.OpticDpi.x / 600)); DBG( _DBG_INFO, "Data is available\n" ); return SANE_TRUE; } } DBG( _DBG_INFO, "NO Data available\n" ); return SANE_FALSE; } /** */ static SANE_Bool usb_ScanReadImage( Plustek_Device *dev, void *pBuf, u_long dwSize ) { u_char *regs = dev->usbDev.a_bRegs; SANE_Status res; DBG( _DBG_READ, "usb_ScanReadImage(%lu)\n", dwSize ); if( m_fFirst ) { m_fFirst = SANE_FALSE; /* Wait for data band ready */ if (!usb_IsDataAvailableInDRAM( dev )) { DBG( _DBG_ERROR, "Nothing to read...\n" ); return SANE_FALSE; } /* restore the fast forward stepsize...*/ sanei_lm983x_write(dev->fd, 0x48, ®s[0x48], 2, SANE_TRUE); } res = sanei_lm983x_read(dev->fd, 0x00, (u_char *)pBuf, dwSize, SANE_FALSE); /* check for pressed ESC button, as sanei_lm983x_read() may take some time */ if( usb_IsEscPressed()) { DBG(_DBG_INFO,"usb_ScanReadImage() - Cancel detected...\n"); return SANE_FALSE; } DBG( _DBG_READ, "usb_ScanReadImage() done, result: %d\n", res ); if( SANE_STATUS_GOOD == res ) { return SANE_TRUE; } DBG( _DBG_ERROR, "usb_ScanReadImage() failed\n" ); return SANE_FALSE; } /** calculate the number of pixels per line and lines out of a given * crop-area. The size of the area is given on a 300dpi base! */ static void usb_GetImageInfo( Plustek_Device *dev, ImgDef *pInfo, WinInfo *pSize ) { DBG( _DBG_INFO, "usb_GetImageInfo()\n" ); pSize->dwPixels = (u_long)pInfo->crArea.cx * pInfo->xyDpi.x / 300UL; pSize->dwLines = (u_long)pInfo->crArea.cy * pInfo->xyDpi.y / 300UL; DBG( _DBG_INFO2,"Area: cx=%u, cy=%u\n",pInfo->crArea.cx,pInfo->crArea.cy); switch( pInfo->wDataType ) { case COLOR_TRUE48: pSize->dwBytes = pSize->dwPixels * 6UL; break; case COLOR_TRUE24: if( dev->scanning.fGrayFromColor > 7 ){ pSize->dwBytes = (pSize->dwPixels + 7UL) >> 3; pSize->dwPixels = pSize->dwBytes * 8; } else { pSize->dwBytes = pSize->dwPixels * 3UL; } break; case COLOR_GRAY16: pSize->dwBytes = pSize->dwPixels << 1; break; case COLOR_256GRAY: pSize->dwBytes = pSize->dwPixels; break; default: pSize->dwBytes = (pSize->dwPixels + 7UL) >> 3; pSize->dwPixels = pSize->dwBytes * 8; break; } } /** */ static void usb_SaveImageInfo( Plustek_Device *dev, ImgDef *pInfo ) { HWDef *hw = &dev->usbDev.HwSetting; ScanParam *pParam = &dev->scanning.sParam; DBG( _DBG_INFO, "usb_SaveImageInfo()\n" ); /* Dpi & Origins */ pParam->UserDpi = pInfo->xyDpi; pParam->Origin.x = pInfo->crArea.x; pParam->Origin.y = pInfo->crArea.y; /* Source & Bits */ pParam->bBitDepth = 8; switch( pInfo->wDataType ) { case COLOR_TRUE48: pParam->bBitDepth = 16; /* fall through... */ case COLOR_TRUE24: pParam->bDataType = SCANDATATYPE_Color; /* AFE operation: one or 3 channels ! */ if( hw->bReg_0x26 & _ONE_CH_COLOR ) pParam->bChannels = 1; else pParam->bChannels = 3; break; case COLOR_GRAY16: pParam->bBitDepth = 16; /* fall through... */ case COLOR_256GRAY: pParam->bDataType = SCANDATATYPE_Gray; pParam->bChannels = 1; break; default: pParam->bBitDepth = 1; pParam->bDataType = SCANDATATYPE_BW; pParam->bChannels = 1; } DBG( _DBG_INFO, "* dwFlag = 0x%08lx\n", pInfo->dwFlag ); if( pInfo->dwFlag & SCANDEF_Transparency ) pParam->bSource = SOURCE_Transparency; else if( pInfo->dwFlag & SCANDEF_Negative ) pParam->bSource = SOURCE_Negative; else if( pInfo->dwFlag & SCANDEF_Adf ) pParam->bSource = SOURCE_ADF; else pParam->bSource = SOURCE_Reflection; /* it seems, that we need to adjust the Origin.x when we have a * sheetfed device to avoid stripes in the resulting pictures */ if( usb_IsSheetFedDevice(dev)) { int step, div, org, xdpi; xdpi = usb_SetAsicDpiX( dev, pParam->UserDpi.x ); if ((xdpi * 2) <= 300) div = 300; else if ((xdpi * 2) <= 600) div = 600; else if ((xdpi * 2) <= 1200) div = 1200; else div = 2400; step = div / xdpi; org = pParam->Origin.x; pParam->Origin.x = (pParam->Origin.x / step) * step; if (org != pParam->Origin.x) DBG(_DBG_INFO, "* Origin.x adjusted: %i -> %i\n", org, pParam->Origin.x); } } /* END PLUSTEK-USBSCAN.C ....................................................*/ sane-backends-1.0.27/backend/hp5590_low.c0000664000175000017500000007107312775312261014606 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Ilia Sotnikov This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP ScanJet 4500C/4570C/5500C/5550C/5590/7650 Scanners */ #include "../include/sane/config.h" #include #include #include #ifdef HAVE_NETINET_IN_H # include #endif /* HAVE_NETINET_IN_H */ #include "byteorder.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_usb.h" #include "../include/_stdint.h" #include "hp5590_low.h" /* Debug levels */ #define DBG_err 0 #define DBG_proc 10 #define DBG_usb 50 /* Custom assert() macro */ #define hp5590_low_assert(exp) if(!(exp)) { \ DBG (DBG_err, "Assertion '%s' failed at %s:%u\n", #exp, __FILE__, __LINE__);\ return SANE_STATUS_INVAL; \ } /* Structure describing bulk transfer size */ struct bulk_size { uint16_t size; uint8_t unused; } __attribute__ ((packed)); /* Structure describing bulk URB */ /* FIXME: Verify according to USB standard */ struct usb_in_usb_bulk_setup { uint8_t bRequestType; uint8_t bRequest; uint8_t bEndpoint; uint16_t unknown; uint16_t wLength; /* MSB first */ uint8_t pad; } __attribute__ ((packed)); /* Structure describing control URB */ struct usb_in_usb_ctrl_setup { uint8_t bRequestType; uint8_t bRequest; uint16_t wValue; /* MSB first */ uint16_t wIndex; /* MSB first */ uint16_t wLength; /* LSB first */ } __attribute__ ((packed)); /* CORE status flag - ready or not */ #define CORE_FLAG_NOT_READY 1 << 1 /* Bulk transfers are done in pages, below their respective sizes */ #define BULK_WRITE_PAGE_SIZE 0x0f000 #define BULK_READ_PAGE_SIZE 0x10000 #define ALLOCATE_BULK_READ_PAGES 16 /* 16 * 65536 = 1Mb */ /* Structure describing bulk read state, because bulk reads will be done in * pages, but function caller uses its own buffer, whose size is certainly * different. Also, each bulk read page is ACK'ed by special command * so total pages received should be tracked as well */ struct bulk_read_state { unsigned char *buffer; unsigned int buffer_size; unsigned int bytes_available; unsigned char *buffer_out_ptr; unsigned char *buffer_in_ptr; unsigned int total_pages; unsigned char *buffer_end_ptr; unsigned int initialized; }; /******************************************************************************* * USB-in-USB: get acknowledge for last USB-in-USB operation * * Parameters * dn - sanei_usb device descriptor * * Returns * SANE_STATUS_GOOD - if correct acknowledge was received * SANE_STATUS_DEVICE_BUSY - otherwise */ static SANE_Status hp5590_get_ack (SANE_Int dn, enum proto_flags proto_flags) { uint8_t status; SANE_Status ret; /* Bypass reading acknowledge if the device doesn't need it */ if (proto_flags & PF_NO_USB_IN_USB_ACK) return SANE_STATUS_GOOD; DBG (DBG_proc, "%s\n", __func__); /* Check if USB-in-USB operation was accepted */ ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR, 0x0c, 0x8e, 0x20, sizeof (status), &status); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error getting acknowledge\n", __func__); return ret; } DBG (DBG_usb, "%s: USB-in-USB: accepted\n", __func__); /* Check if we received correct acknowledgement */ if (status != 0x01) { DBG (DBG_err, "%s: USB-in-USB: not accepted (status %u)\n", __func__, status); return SANE_STATUS_DEVICE_BUSY; } return SANE_STATUS_GOOD; } /******************************************************************************* * USB-in-USB: get device status * * Parameters * dn - sanei_usb device descriptor * * Returns * SANE_STATUS_GOOD - if correct status was received * SANE_STATUS_DEVICE_BUSY - otherwise */ static SANE_Status hp5590_get_status (SANE_Int dn, __sane_unused__ enum proto_flags proto_flags) { uint8_t status; SANE_Status ret; DBG (DBG_proc, "%s\n", __func__); ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR, 0x0c, 0x8e, 0x00, sizeof (status), &status); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error getting device status\n", __func__); return ret; } /* Check if we received correct status */ if (status != 0x00) { DBG (DBG_err, "%s: USB-in-USB: got non-zero device status (status %u)\n", __func__, status); return SANE_STATUS_DEVICE_BUSY; } return SANE_STATUS_GOOD; } /******************************************************************************* * USB-in-USB: sends control message for IN or OUT operation * * Parameters * dn - sanei_usb device descriptor * requesttype, request, value, index - their meaninings are similar to * sanei_control_msg() * bytes - pointer to data buffer * size - size of data * core_flags - * CORE_NONE - no CORE operation will be performed * CORE_DATA - operation on CORE data will be performed * CORE_BULK_IN - preparation for bulk IN transfer (not used yet) * CORE_BULK_OUT - preparation for bulk OUT trasfer * * Returns * SANE_STATUS_GOOD - control message was sent w/o any errors * all other SANE_Status values - otherwise */ static SANE_Status hp5590_control_msg (SANE_Int dn, enum proto_flags proto_flags, int requesttype, int request, int value, int index, unsigned char *bytes, int size, int core_flags) { struct usb_in_usb_ctrl_setup ctrl; SANE_Status ret; unsigned int len; unsigned char *ptr; uint8_t ack; uint8_t response; unsigned int needed_response; DBG (DBG_proc, "%s: USB-in-USB: core data: %s\n", __func__, core_flags & CORE_DATA ? "yes" : "no"); hp5590_low_assert (bytes != NULL); /* IN (read) operation will be performed */ if (requesttype & USB_DIR_IN) { /* Prepare USB-in-USB control message */ memset (&ctrl, 0, sizeof (ctrl)); ctrl.bRequestType = 0xc0; ctrl.bRequest = request; ctrl.wValue = htons (value); ctrl.wIndex = htons (index); ctrl.wLength = htole16 (size); DBG (DBG_usb, "%s: USB-in-USB: sending control msg\n", __func__); /* Send USB-in-USB control message */ ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR, 0x04, 0x8f, 0x00, sizeof (ctrl), (unsigned char *) &ctrl); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error sending control message\n", __func__); return ret; } /* USB-in-USB: checking acknowledge for control message */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; len = size; ptr = bytes; /* Data is read in 8 byte portions */ while (len) { unsigned int next_packet_size; next_packet_size = 8; if (len < 8) next_packet_size = len; /* Read USB-in-USB data */ ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR, core_flags & CORE_DATA ? 0x0c : 0x04, 0x90, 0x00, next_packet_size, ptr); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error reading data\n", __func__); return ret; } ptr += next_packet_size; len -= next_packet_size; } /* Confirm data reception */ ack = 0; ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR, 0x0c, 0x8f, 0x00, sizeof (ack), &ack); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error confirming data reception\n", __func__); return -1; } /* USB-in-USB: checking if confirmation was acknowledged */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; } /* OUT (write) operation will be performed */ if (!(requesttype & USB_DIR_IN)) { /* Prepare USB-in-USB control message */ memset (&ctrl, 0, sizeof (ctrl)); ctrl.bRequestType = 0x40; ctrl.bRequest = request; ctrl.wValue = htons (value); ctrl.wIndex = htons (index); ctrl.wLength = htole16 (size); DBG (DBG_usb, "%s: USB-in-USB: sending control msg\n", __func__); /* Send USB-in-USB control message */ ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR, 0x04, 0x8f, 0x00, sizeof (ctrl), (unsigned char *) &ctrl); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error sending control message\n", __func__); return ret; } /* USB-in-USB: checking acknowledge for control message */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; len = size; ptr = bytes; /* Data is sent in 8 byte portions */ while (len) { unsigned int next_packet_size; next_packet_size = 8; if (len < 8) next_packet_size = len; /* Send USB-in-USB data */ ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR, core_flags & CORE_DATA ? 0x04 : 0x0c, 0x8f, 0x00, next_packet_size, ptr); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error sending data\n", __func__); return ret; } /* CORE data is acknowledged packet by packet */ if (core_flags & CORE_DATA) { /* USB-in-USB: checking if data was accepted */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; } ptr += next_packet_size; len -= next_packet_size; } /* Normal (non-CORE) data is acknowledged after its full transmission */ if (!(core_flags & CORE_DATA)) { /* USB-in-USB: checking if data was accepted */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; } /* Getting response after data transmission */ DBG (DBG_usb, "%s: USB-in-USB: getting response\n", __func__); ret = sanei_usb_control_msg (dn, USB_DIR_IN | USB_TYPE_VENDOR, 0x0c, 0x90, 0x00, sizeof (response), &response); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error getting response\n", __func__); return ret; } /* Necessary response after normal (non-CORE) data is 0x00, * after bulk OUT preparation - 0x24 */ needed_response = core_flags & CORE_BULK_OUT ? 0x24 : 0x00; if (response == needed_response) DBG (DBG_usb, "%s: USB-in-USB: got correct response\n", __func__); if (response != needed_response) { DBG (DBG_err, "%s: USB-in-USB: invalid response received " "(needed %04x, got %04x)\n", __func__, needed_response, response); return SANE_STATUS_IO_ERROR; } /* Send bulk OUT flags is bulk OUT preparation is performed */ if (core_flags & CORE_BULK_OUT) { uint8_t bulk_flags = 0x24; DBG (DBG_usb, "%s: USB-in-USB: sending bulk flags\n", __func__); ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR, 0x0c, 0x83, 0x00, sizeof (bulk_flags), &bulk_flags); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error sending bulk flags\n", __func__); return ret; } /* USB-in-USB: checking confirmation for bulk flags */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; } } return SANE_STATUS_GOOD; } /******************************************************************************* * USB-in-USB: verifies last command * * Parameters * dn - sanei_usb device descriptor * cmd - command to verify * * Returns * SANE_STATUS_GOOD - command verified successfully and CORE is ready * SANE_STATUS_IO_ERROR - command verification failed * SANE_STATUS_DEVICE_BUSY - command verified successfully but CORE isn't ready * all other SANE_Status values - otherwise */ static SANE_Status hp5590_verify_last_cmd (SANE_Int dn, enum proto_flags proto_flags, unsigned int cmd) { uint16_t verify_cmd; unsigned int last_cmd; unsigned int core_status; SANE_Status ret; DBG (3, "%s: USB-in-USB: command verification requested\n", __func__); /* Read last command along with CORE status */ ret = hp5590_control_msg (dn, proto_flags, USB_DIR_IN, 0x04, 0xc5, 0x00, (unsigned char *) &verify_cmd, sizeof (verify_cmd), CORE_NONE); if (ret != SANE_STATUS_GOOD) return ret; verify_cmd = le16toh (verify_cmd); /* Response is LSB first */ /* Last command - minor byte */ last_cmd = verify_cmd & 0xff; /* CORE status - major byte */ core_status = (verify_cmd & 0xff00) >> 8; /* Verify last command */ DBG (DBG_usb, "%s: USB-in-USB: command verification %04x, " "last command: %04x, core status: %04x\n", __func__, verify_cmd, last_cmd, core_status); if ((cmd & 0x00ff) != last_cmd) { DBG (DBG_err, "%s: USB-in-USB: command verification failed: " "expected 0x%04x, got 0x%04x\n", __func__, cmd, last_cmd); return SANE_STATUS_IO_ERROR; } DBG (DBG_usb, "%s: USB-in-USB: command verified successfully\n", __func__); /* Return value depends on CORE status */ return core_status & CORE_FLAG_NOT_READY ? SANE_STATUS_DEVICE_BUSY : SANE_STATUS_GOOD; } /******************************************************************************* * USB-in-USB: send command (convenience wrapper around hp5590_control_msg()) * * Parameters * dn - sanei_usb device descriptor * requesttype, request, value, index - their meaninings are similar to * sanei_control_msg() * bytes - pointer to data buffer * size - size of data * core_flags - * CORE_NONE - no CORE operation will be performed * CORE_DATA - operation on CORE data will be performed * CORE_BULK_IN - preparation for bulk IN transfer (not used yet) * CORE_BULK_OUT - preparation for bulk OUT trasfer * * Returns * SANE_STATUS_GOOD - command was sent (and possible verified) w/o any errors * all other SANE_Status values - otherwise */ static SANE_Status hp5590_cmd (SANE_Int dn, enum proto_flags proto_flags, unsigned int flags, unsigned int cmd, unsigned char *data, unsigned int size, unsigned int core_flags) { SANE_Status ret; DBG (3, "%s: USB-in-USB: command : %04x\n", __func__, cmd); ret = hp5590_control_msg (dn, proto_flags, flags & CMD_IN ? USB_DIR_IN : USB_DIR_OUT, 0x04, cmd, 0x00, data, size, core_flags); if (ret != SANE_STATUS_GOOD) return ret; ret = SANE_STATUS_GOOD; /* Verify last command if requested */ if (flags & CMD_VERIFY) { ret = hp5590_verify_last_cmd (dn, proto_flags, cmd); } return ret; } /******************************************************************************* * USB-in-USB: initialized bulk read state * * Parameters * state - pointer to a pointer for initialized state * * Returns * SANE_STATUS_GOOD - if state was initialized successfully * SANE_STATUS_NO_MEM - memory allocation failed */ static SANE_Status hp5590_low_init_bulk_read_state (void **state) { struct bulk_read_state *bulk_read_state; DBG (3, "%s: USB-in-USB: initializing bulk read state\n", __func__); hp5590_low_assert (state != NULL); bulk_read_state = malloc (sizeof (struct bulk_read_state)); if (!bulk_read_state) return SANE_STATUS_NO_MEM; memset (bulk_read_state, 0, sizeof (struct bulk_read_state)); bulk_read_state->buffer = malloc (ALLOCATE_BULK_READ_PAGES * BULK_READ_PAGE_SIZE); if (!bulk_read_state->buffer) { DBG (DBG_err, "%s: Memory allocation failed for %u bytes\n", __func__, ALLOCATE_BULK_READ_PAGES * BULK_READ_PAGE_SIZE); return SANE_STATUS_NO_MEM; } bulk_read_state->buffer_size = ALLOCATE_BULK_READ_PAGES * BULK_READ_PAGE_SIZE; bulk_read_state->bytes_available = 0; bulk_read_state->buffer_out_ptr = bulk_read_state->buffer; bulk_read_state->buffer_in_ptr = bulk_read_state->buffer; bulk_read_state->total_pages = 0; bulk_read_state->buffer_end_ptr = bulk_read_state->buffer + bulk_read_state->buffer_size; bulk_read_state->initialized = 1; *state = bulk_read_state; return SANE_STATUS_GOOD; } /******************************************************************************* * USB-in-USB: free bulk read state * * Parameters * state - pointer to a pointer to bulk read state * * Returns * SANE_STATUS_GOOD - bulk read state freed successfully */ static SANE_Status hp5590_low_free_bulk_read_state (void **state) { struct bulk_read_state *bulk_read_state; DBG (3, "%s\n", __func__); hp5590_low_assert (state != NULL); /* Just return if NULL bulk read state was given */ if (*state == NULL) return SANE_STATUS_GOOD; bulk_read_state = *state; DBG (3, "%s: USB-in-USB: freeing bulk read state\n", __func__); free (bulk_read_state->buffer); bulk_read_state->buffer = NULL; free (bulk_read_state); *state = NULL; return SANE_STATUS_GOOD; } /* FIXME: perhaps needs to be converted to use hp5590_control_msg() */ /******************************************************************************* * USB-in-USB: bulk read * * Parameters * dn - sanei_usb device descriptor * bytes - pointer to data buffer * size - size of data to read * state - pointer to initialized bulk read state structure */ static SANE_Status hp5590_bulk_read (SANE_Int dn, enum proto_flags proto_flags, unsigned char *bytes, unsigned int size, void *state) { struct usb_in_usb_bulk_setup ctrl; SANE_Status ret; unsigned int next_pages; uint8_t bulk_flags; size_t next_portion; struct bulk_read_state *bulk_read_state; unsigned int bytes_until_buffer_end; DBG (3, "%s\n", __func__); hp5590_low_assert (state != NULL); hp5590_low_assert (bytes != NULL); bulk_read_state = state; if (bulk_read_state->initialized == 0) { DBG (DBG_err, "%s: USB-in-USB: bulk read state not initialized\n", __func__); return SANE_STATUS_INVAL; } memset (bytes, 0, size); /* Check if requested data would fit into the buffer */ if (size > bulk_read_state->buffer_size) { DBG (DBG_err, "Data requested won't fit in the bulk read buffer " "(requested: %u, buffer size: %u\n", size, bulk_read_state->buffer_size); return SANE_STATUS_NO_MEM; } /* Read data until requested size of data will be received */ while (bulk_read_state->bytes_available < size) { DBG (DBG_usb, "%s: USB-in-USB: not enough data in buffer available " "(available: %u, requested: %u)\n", __func__, bulk_read_state->bytes_available, size); /* IMPORTANT! 'next_pages' means 'request and receive next_pages pages in * one bulk transfer request '. Windows driver uses 4 pages between each * request. The more pages are received between requests the less the * scanner does scan head re-positioning thus improving scanning speed. * On the other hand, scanner expects that all of the requested pages * will be received immediately after the request. In case when a * frontend will have a delay between reads we will get bulk transfer * timeout sooner or later. * Having next_pages = 1 is the most safe case. */ next_pages = 1; /* Count all received pages to calculate when we will need to send * another bulk request */ bulk_read_state->total_pages++; DBG (DBG_usb, "%s: USB-in-USB: total pages done: %u\n", __func__, bulk_read_state->total_pages); /* Send another bulk request for 'next_pages' before first * page or next necessary one */ if ( bulk_read_state->total_pages == 1 || bulk_read_state->total_pages % next_pages == 0) { /* Send bulk flags */ DBG (DBG_usb, "%s: USB-in-USB: sending USB-in-USB bulk flags\n", __func__); bulk_flags = 0x24; ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR, 0x0c, 0x83, 0x00, sizeof (bulk_flags), &bulk_flags); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error sending bulk flags\n", __func__); return ret; } /* USB-in-USB: checking confirmation for bulk flags\n" */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; /* Prepare bulk read request */ memset (&ctrl, 0, sizeof (ctrl)); ctrl.bRequestType = 0x00; ctrl.bEndpoint = 0x82; ctrl.wLength = htons (next_pages); /* Send bulk read request */ DBG (DBG_usb, "%s: USB-in-USB: sending control msg for bulk\n", __func__); ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR, 0x04, 0x82, 0x00, sizeof (ctrl), (unsigned char *) &ctrl); if (ret != SANE_STATUS_GOOD) { DBG (DBG_err, "%s: USB-in-USB: error sending control msg\n", __func__); return ret; } /* USB-in-USB: checking if control msg was accepted */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; } next_portion = BULK_READ_PAGE_SIZE; /* Check if next page will fit into the buffer */ if (bulk_read_state->buffer_size - bulk_read_state->bytes_available < next_portion) { DBG (DBG_err, "%s: USB-in-USB: buffer too small\n", __func__); return SANE_STATUS_NO_MEM; } /* Bulk read next page */ DBG (DBG_usb, "%s: USB-in-USB: bulk reading %lu bytes\n", __func__, (u_long) next_portion); ret = sanei_usb_read_bulk (dn, bulk_read_state->buffer_in_ptr, &next_portion); if (ret != SANE_STATUS_GOOD) { if (ret == SANE_STATUS_EOF) return ret; DBG (DBG_err, "%s: USB-in-USB: error during bulk read: %s\n", __func__, sane_strstatus (ret)); return ret; } /* Check if we received the same amount of data as requsted */ if (next_portion != BULK_READ_PAGE_SIZE) { DBG (DBG_err, "%s: USB-in-USB: incomplete bulk read " "(requested %u bytes, got %lu bytes)\n", __func__, BULK_READ_PAGE_SIZE, (u_long) next_portion); return SANE_STATUS_IO_ERROR; } /* Move pointers to the next position */ bulk_read_state->buffer_in_ptr += next_portion; /* Check for the end of the buffer */ if (bulk_read_state->buffer_in_ptr > bulk_read_state->buffer_end_ptr) { DBG (DBG_err, "%s: USB-in-USB: attempted to access over the end of buffer " "(in_ptr: %p, end_ptr: %p, ptr: %p, buffer size: %u\n", __func__, bulk_read_state->buffer_in_ptr, bulk_read_state->buffer_end_ptr, bulk_read_state->buffer, bulk_read_state->buffer_size); return SANE_STATUS_NO_MEM; } /* Check for buffer pointer wrapping */ if (bulk_read_state->buffer_in_ptr == bulk_read_state->buffer_end_ptr) { DBG (DBG_usb, "%s: USB-in-USB: buffer wrapped while writing\n", __func__); bulk_read_state->buffer_in_ptr = bulk_read_state->buffer; } /* Count the amount of data we read */ bulk_read_state->bytes_available += next_portion; } /* Transfer requested amount of data to the caller */ DBG (DBG_usb, "%s: USB-in-USB: data in bulk buffer is available " "(requested %u bytes, available %u bytes)\n", __func__, size, bulk_read_state->bytes_available); /* Check for buffer pointer wrapping */ bytes_until_buffer_end = bulk_read_state->buffer_end_ptr - bulk_read_state->buffer_out_ptr; if (bytes_until_buffer_end <= size) { /* First buffer part */ DBG (DBG_usb, "%s: USB-in-USB: reached bulk read buffer end\n", __func__); memcpy (bytes, bulk_read_state->buffer_out_ptr, bytes_until_buffer_end); bulk_read_state->buffer_out_ptr = bulk_read_state->buffer; /* And second part (if any) */ if (bytes_until_buffer_end < size) { DBG (DBG_usb, "%s: USB-in-USB: giving 2nd buffer part\n", __func__); memcpy (bytes + bytes_until_buffer_end, bulk_read_state->buffer_out_ptr, size - bytes_until_buffer_end); bulk_read_state->buffer_out_ptr += size - bytes_until_buffer_end; } } else { /* The data is in one buffer part (w/o wrapping) */ memcpy (bytes, bulk_read_state->buffer_out_ptr, size); bulk_read_state->buffer_out_ptr += size; if (bulk_read_state->buffer_out_ptr == bulk_read_state->buffer_end_ptr) { DBG (DBG_usb, "%s: USB-in-USB: buffer wrapped while reading\n", __func__); bulk_read_state->buffer_out_ptr = bulk_read_state->buffer; } } /* Count the amount of data transferred to the caller */ bulk_read_state->bytes_available -= size; return SANE_STATUS_GOOD; } /******************************************************************************* * USB-in-USB: bulk write * * Parameters * dn - sanei_usb device descriptor * cmd - command for bulk write operation * bytes - pointer to data buffer * size - size of data * * Returns * SANE_STATUS_GOOD - all data transferred successfully * all other SANE_Status value - otherwise */ static SANE_Status hp5590_bulk_write (SANE_Int dn, enum proto_flags proto_flags, int cmd, unsigned char *bytes, unsigned int size) { struct usb_in_usb_bulk_setup ctrl; SANE_Status ret; struct bulk_size bulk_size; unsigned int len; unsigned char *ptr; size_t next_portion; DBG (3, "%s: USB-in-USB: command: %04x, size %u\n", __func__, cmd, size); hp5590_low_assert (bytes != NULL); /* Prepare bulk write request */ memset (&bulk_size, 0, sizeof (bulk_size)); /* Counted in page size */ bulk_size.size = size / BULK_WRITE_PAGE_SIZE; /* Send bulk write request */ DBG (3, "%s: USB-in-USB: total %u pages (each of %u bytes)\n", __func__, bulk_size.size, BULK_WRITE_PAGE_SIZE); ret = hp5590_control_msg (dn, proto_flags, USB_DIR_OUT, 0x04, cmd, 0, (unsigned char *) &bulk_size, sizeof (bulk_size), CORE_DATA | CORE_BULK_OUT); if (ret != SANE_STATUS_GOOD) return ret; len = size; ptr = bytes; /* Send all data in pages */ while (len) { next_portion = BULK_WRITE_PAGE_SIZE; if (len < next_portion) next_portion = len; DBG (3, "%s: USB-in-USB: next portion %lu bytes\n", __func__, (u_long) next_portion); /* Prepare bulk write request */ memset (&ctrl, 0, sizeof (ctrl)); ctrl.bRequestType = 0x01; ctrl.bEndpoint = 0x82; ctrl.wLength = htons (next_portion); /* Send bulk write request */ ret = sanei_usb_control_msg (dn, USB_DIR_OUT | USB_TYPE_VENDOR, 0x04, 0x82, 0, sizeof (ctrl), (unsigned char *) &ctrl); if (ret != SANE_STATUS_GOOD) return ret; /* USB-in-USB: checking if command was accepted */ ret = hp5590_get_ack (dn, proto_flags); if (ret != SANE_STATUS_GOOD) return ret; /* Write bulk data */ DBG (3, "%s: USB-in-USB: bulk writing %lu bytes\n", __func__, (u_long) next_portion); ret = sanei_usb_write_bulk (dn, ptr, &next_portion); if (ret != SANE_STATUS_GOOD) { /* Treast EOF as successful result */ if (ret == SANE_STATUS_EOF) break; DBG (DBG_err, "%s: USB-in-USB: error during bulk write: %s\n", __func__, sane_strstatus (ret)); return ret; } /* Move to the next page */ len -= next_portion; ptr += next_portion; } /* Verify bulk command */ return hp5590_verify_last_cmd (dn, proto_flags, cmd); } /* vim: sw=2 ts=8 */ sane-backends-1.0.27/backend/lexmark_sensors.c0000664000175000017500000001007312112021330016156 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2006-2010 Stéphane Voltz Copyright (C) 2010 "Torsten Houwaart" X74 support This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ static Lexmark_Sensor sensor_list[] = { { X1100_B2_SENSOR, /* start x, end x and target average for offset calibration */ 48, 80, 6, /* usable pixel sensor startx */ 106, /* default gain */ 16, /* gain calibration targets */ 180, 180, 180, 180, /* shading correction targets */ 260, 260, 260, 260, /* offset and gain fallback */ 0x70, 17}, { X1100_2C_SENSOR, /* start x, end x and target average for offset calibration */ 48, 80, 12, /* usable pixel sensor startx */ 106, /* default gain */ 10, /* gain calibration */ 140, 150, 150, 150, /* shading correction */ 260, 260, 260, 260, /* offset and gain fallback */ 0x70, 11}, { /* USB 1.1 settings */ X1200_SENSOR, /* start x, end x and target average for offset calibration */ 32, 64, 15, /* usable pixel sensor startx */ 136, /* default gain */ 16, /* gain calibration */ 180, 180, 180, 180, /* shading correction */ 260, 260, 260, 260, /* offset and gain fallback */ 0x86, 16}, { /* this one is a 1200 on USB2.0 */ X1200_USB2_SENSOR, /* start x, end x and target average for offset calibration */ 32, 64, 12, /* usable pixel sensor startx */ 136, /* default gain */ 16, /* gain calibration */ 180, 180, 180, 180, /* shading correction */ 260, 260, 260, 260, /* offset and gain fallback */ 0x86, 16}, { A920_SENSOR, /* start x, end x and target average for offset calibration */ 48, 80, 6, /* usable pixel sensor startx */ 106, /* default gain */ 12, /* gain calibration target */ 130, 145, 150, 145, /* gain calibration target */ 260, 260, 260, 260, /* offset and gain fallback */ 0x70, 13}, { X74_SENSOR, /* start x TDONE, end x and target average for offset calibration */ /*36,68,12, */ 20, 52, 12, /* usable pixel sensor startx */ /*104, */ 104, /* default gain */ 10, /* gain calibration target */ 130, 145, 150, 145, /* gain calibration target */ 260, 260, 260, 260, /* offset and gain fallback */ 0x70, 13}, /* termination list sensor, must be last */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; sane-backends-1.0.27/backend/plustek-pp_tpa.c0000664000175000017500000011402512775277260015747 00000000000000/* @file plustek-pp_tpa.c * @brief Here we find some adjustments according to the scan source. * This file is ASIC P9800x specific * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - Added some comments * - 0.32 - no changes * - 0.33 - new header * - 0.34 - no changes * - 0.35 - no changes * - 0.36 - no changes * - 0.37 - cosmetic changes * - 0.38 - Replaced AllPointer by DataPointer * - renamed this file from transform.c tpa.c * - 0.39 - no changes * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - no changes * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /***************************** local vars ************************************/ static UShort a_wGainString [] = { 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400, 425, 450, 475, 500, 525, 550, 575, 600, 625, 650, 675, 700, 725, 750, 775, 800, 825 }; /*************************** local functions *********************************/ /*............................................................................. * */ static void tpaP98SubNoise( pScanData ps, pULong pdwSum, pUShort pwShading, ULong dwHilightOff, ULong dwShadowOff ) { ULong dwPixels, dwLines, dwSum; pUShort pw; for (dwPixels = 4; dwPixels--; pdwSum++, pwShading++) *pwShading = (UShort)(*pdwSum >> 5); for (dwPixels = 0; dwPixels < (ps->dwShadingPixels - 4); dwPixels++, pdwSum++, pwShading++) { pw = (pUShort)ps->Shade.pHilight + dwHilightOff + dwPixels; dwSum = 0; for (dwLines = _DEF_BRIGHTEST_SKIP; dwLines--; pw += 5400UL) dwSum += (ULong) *pw; pw = ps->pwShadow + dwShadowOff + dwPixels; for (dwLines = _DEF_DARKEST_SKIP; dwLines--; pw += 5400UL) dwSum += (ULong) *pw; *pwShading = (UShort)((*pdwSum - dwSum) / ps->Shade.dwDiv); } if (ps->dwShadingPixels != 5400UL) { for (dwPixels = 2700UL; dwPixels--; pdwSum++, pwShading++) *pwShading = (UShort)(*pdwSum >> 5); } } /*............................................................................. * */ static void tpaP98ShadingWaveformSum( pScanData ps ) { DataPointer pd, pt; ULong dw; pd.pdw = (pULong)ps->pScanBuffer1; pt.pw = (pUShort)ps->pScanBuffer1; if ((ps->DataInf.dwScanFlag & SCANDEF_TPA ) || (0 == ps->bShadingTimeFlag)) { if( ps->Shade.pHilight ) { tpaP98SubNoise( ps, (pULong)ps->pScanBuffer1, (pUShort)ps->pScanBuffer1, 0, 0); tpaP98SubNoise( ps ,(pULong)ps->pScanBuffer1 + 5400UL, (pUShort)ps->pScanBuffer1 + 5400UL, ps->dwHilightCh, ps->dwShadowCh); tpaP98SubNoise( ps, (pULong)ps->pScanBuffer1 + 5400UL * 2UL, (pUShort)ps->pScanBuffer1 + 5400UL * 2UL, ps->dwHilightCh * 2, ps->dwShadowCh * 2); } else { for (dw = 5400 * 3; dw; dw--, pt.pw++, pd.pdw++) *pt.pw = (UShort)(*pd.pdw / 32); /* shift 5 bits */ } } else { if (02 == ps->bShadingTimeFlag ) { for (dw = 5400 * 3; dw; dw--, pt.pw++, pd.pdw++) *pt.pw = (UShort)(*pd.pdw / 16); /* shift 4 bits */ } else { for (dw = 5400 * 3; dw; dw--, pt.pw++, pd.pdw++) *pt.pw = (UShort)(*pd.pdw / 4); /* shift 2 bits */ } } } /*............................................................................. * get wReduceRedFactor, wReduceGreenFactor, wReduceBlueFactor */ static void tpaP98GetNegativeTempRamData( pScanData ps ) { UShort wRedTemp, wGreenTemp, wBlueTemp; UShort wRedShadingTemp, wGreenShadingTemp, wBlueShadingTemp; ULong dw, dw1; DataPointer p; pULong pdwNegativeSumTemp; pUShort pNegativeTempRam, pNegativeTempRam2; ps->bFastMoveFlag = _FastMove_Low_C75_G150; MotorP98GoFullStep( ps ,80 ); pNegativeTempRam = (pUShort)(ps->pScanBuffer1 + 5400 * 6); pdwNegativeSumTemp = (pULong)(pNegativeTempRam + 960 * 3 * 2); pNegativeTempRam2 = (pUShort)(pdwNegativeSumTemp + 960 * 3 * 4); /* ClearNegativeSumBuffer() */ memset( pdwNegativeSumTemp, 0, (960 * 3 * 4)); /* SetReadNegativeTempRegister() */ ps->AsicReg.RD_Motor0Control = 0; IOCmdRegisterToScanner( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward; ps->AsicReg.RD_ModelControl = _ModelDpi600 + _LED_CONTROL + _LED_ACTIVITY; ps->AsicReg.RD_Dpi = ps->PhysicalDpi; if (!ps->wNegAdjustX) { ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX + _Negative96OriginOffsetX * 2); } else { ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX + ps->wNegAdjustX); } ps->AsicReg.RD_Pixels = 960; ps->AsicReg.RD_XStepTime = 32; IOPutOnAllRegisters( ps ); /* NegativeMotorRunLoop() */ p.pb = ps->a_nbNewAdrPointer; for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) *p.pdw = 0x87808780; IOSetToMotorRegister( ps ); for (dw1 = 16; dw1; dw1--) { TimerDef timer; MiscStartTimer( &timer, _SECOND ); while((IOReadFifoLength( ps ) < 960) && !MiscCheckTimer( &timer )) { _DO_UDELAY(1); } /* ReadColorDataIn() - Read 1 RGB line */ ps->AsicReg.RD_ModeControl = _ModeFifoRSel; IOReadScannerImageData( ps, (pUChar)pNegativeTempRam, 960 ); ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, (pUChar)(pNegativeTempRam + 960), 960 ); ps->AsicReg.RD_ModeControl = _ModeFifoBSel; IOReadScannerImageData( ps, (pUChar)(pNegativeTempRam + 960 * 2), 960 ); /* fillNegativeSum() */ for (dw = 0; dw < 960 * 3; dw++) pdwNegativeSumTemp[dw] += ((pUShort) pNegativeTempRam)[dw]; /* one line */ if (IOReadFifoLength( ps ) <= (960 * 2)) IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); } /* AverageAndShift() */ for( dw = 0, dw1 = 0; dw < 240 * 3; dw++, dw1+=4 ) { pNegativeTempRam[dw] = (UShort)((pdwNegativeSumTemp[dw1] + pdwNegativeSumTemp[dw1+1] + pdwNegativeSumTemp[dw1+2] + pdwNegativeSumTemp[dw1+3]) / 128); /* shift 6 bits */ } /* NegativeAdd1() */ if (!ps->wNegAdjustX) { dw1 = (ps->dwOffsetNegative + _Negative96OriginOffsetX * 2 * 2) / 2; } else { dw1 = (ps->dwOffsetNegative + ps->wNegAdjustX * 2) / 2; } /* do R shading average */ for (dw = 0; dw < 240; dw++, dw1 += 4) { pNegativeTempRam2[dw] = (UShort)( (((pUShort)ps->pScanBuffer1)[dw1] + ((pUShort)ps->pScanBuffer1)[dw1+1] + ((pUShort)ps->pScanBuffer1)[dw1+2] + ((pUShort)ps->pScanBuffer1)[dw1+3]) / 4); } /* NegativeAdd1() */ if (!ps->wNegAdjustX) dw1 = (ps->dwOffsetNegative + 5400 * 2 + _Negative96OriginOffsetX * 2 * 2) / 2; else dw1 = (ps->dwOffsetNegative + 5400 * 2 + ps->wNegAdjustX * 2) / 2; /* do G shading average */ for (; dw < 240 * 2; dw++, dw1 += 4) { pNegativeTempRam2[dw] = (UShort)( (((pUShort)ps->pScanBuffer1)[dw1] + ((pUShort)ps->pScanBuffer1)[dw1+1] + ((pUShort)ps->pScanBuffer1)[dw1+2] + ((pUShort)ps->pScanBuffer1)[dw1+3]) / 4); } /* NegativeAdd1() */ if (!ps->wNegAdjustX) dw1 = (ps->dwOffsetNegative + 5400 * 4 + _Negative96OriginOffsetX * 2 * 2) / 2; else dw1 = (ps->dwOffsetNegative + 5400 * 4 + ps->wNegAdjustX * 2) / 2; /* do B shading average */ for (; dw < 240 * 3; dw++, dw1 += 4) { pNegativeTempRam2 [dw] = (UShort)( (((pUShort)ps->pScanBuffer1)[dw1] + ((pUShort)ps->pScanBuffer1)[dw1+1] + ((pUShort)ps->pScanBuffer1)[dw1+2] + ((pUShort)ps->pScanBuffer1)[dw1+3]) / 4); } wRedTemp = wGreenTemp = wBlueTemp = 0; wRedShadingTemp = wGreenShadingTemp = wBlueShadingTemp = 0; /* FindMaxNegValue -- find R */ for (dw = 0; dw < 240; dw++) { if (pNegativeTempRam[dw] >= wRedTemp && pNegativeTempRam[dw + 240] >= wGreenTemp && pNegativeTempRam[dw + 480] > wBlueTemp) { wRedTemp = pNegativeTempRam[dw]; wGreenTemp = pNegativeTempRam[dw + 240]; wBlueTemp = pNegativeTempRam[dw + 480]; wRedShadingTemp = pNegativeTempRam2[dw]; wGreenShadingTemp = pNegativeTempRam2[dw + 240]; wBlueShadingTemp = pNegativeTempRam2[dw + 480]; } } /* GainAddX = (1/4)*DoubleX + 1/ 2 */ if ((ps->bRedGainIndex += (Byte)((wRedShadingTemp / wRedTemp) * 100 - 50) / 25) > 32) ps->bRedGainIndex = 31; if ((ps->bGreenGainIndex += (Byte)((wGreenShadingTemp / wGreenTemp) * 100 - 50) / 25) > 32) ps->bGreenGainIndex = 31; if ((ps->bBlueGainIndex += (Byte)((wBlueShadingTemp / wBlueTemp) * 100 - 50) / 25) > 32) ps->bBlueGainIndex = 31; } /*............................................................................. * */ static void tpaP98RecalculateNegativeShadingGain( pScanData ps ) { Byte b[3]; UShort wSum, counter; UShort w, w1, w2; ULong dw, dw1; pUChar pDest, pSrce, pNegativeTempRam; pUChar pbReg[3]; TimerDef timer; DataPointer p; pNegativeTempRam = (pUChar)(ps->pScanBuffer1 + 5400 * 6); /* AdjustDarkCondition () */ ps->Shade.pCcdDac->DarkDAC.Colors.Red = ps->bsPreRedDAC; ps->Shade.pCcdDac->DarkDAC.Colors.Green = ps->bsPreGreenDAC; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = ps->bsPreBlueDAC; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = ps->wsDACCompareHighRed; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = ps->wsDACCompareLowRed; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = ps->wsDACCompareHighGreen; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = ps->wsDACCompareLowGreen; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = ps->wsDACCompareHighBlue; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = ps->wsDACCompareLowBlue; DacP98FillGainOutDirectPort( ps ); /* ClearNegativeTempBuffer () */ memset( pNegativeTempRam, 0, (960 * 3 * 4)); /* GetNegGainValue () */ ps->PauseColorMotorRunStates( ps ); /* SetScanMode () set scan mode to Byte mode */ ps->AsicReg.RD_ScanControl |= _SCAN_BYTEMODE; ps->AsicReg.RD_ScanControl &= 0xfd; IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); DacP98FillGainOutDirectPort( ps ); /* SetReadNegativeTempRegister() */ ps->AsicReg.RD_Motor0Control = 0; IOCmdRegisterToScanner( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward; ps->AsicReg.RD_ModelControl = _ModelDpi600 + _LED_CONTROL + _LED_ACTIVITY; ps->AsicReg.RD_Dpi = ps->PhysicalDpi; if (!ps->wNegAdjustX) { ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX + _Negative96OriginOffsetX * 2); } else { ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX + ps->wNegAdjustX); } ps->AsicReg.RD_Pixels = 960; ps->AsicReg.RD_XStepTime = 32; IOPutOnAllRegisters( ps ); /* ReReadNegativeTemp */ MiscStartTimer( &timer, _SECOND ); while((IOReadFifoLength( ps) < 960) && !MiscCheckTimer( &timer )) { _DO_UDELAY(1); /* 1 us delay */ } /* ReadColorDataIn() - Read 1 RGB line */ ps->AsicReg.RD_ModeControl = _ModeFifoRSel; IOReadScannerImageData( ps, pNegativeTempRam, 960); ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, pNegativeTempRam + 960, 960); ps->AsicReg.RD_ModeControl = _ModeFifoBSel; IOReadScannerImageData( ps, pNegativeTempRam + 960 * 2, 960); /* FindRGBGainValue(); */ pDest = pSrce = pNegativeTempRam; /* ReAdjustGainAverage() */ for (dw1 = 0; dw1 < (960 * 3) / 16; dw1++, pDest++) { for (dw = 0, wSum = 0; dw < 16; dw++, pSrce++) wSum += *pSrce; *pDest = wSum / 16; } /* FindTheMaxGainValue */ for (w = 0, p.pb = pNegativeTempRam; w < 3; w++) { for (dw = 960 / 16, b[w] = 0; dw; dw--, p.pb++) { if (b[w] < *p.pb) b[w] = *p.pb; } } ps->bRedHigh = b[0]; ps->bGreenHigh = b[1]; ps->bBlueHigh = b[2]; /* ModifyExposureTime () */ if ((ps->bRedHigh < _GAIN_LOW) || (ps->bGreenHigh < _GAIN_LOW) || (ps->bBlueHigh < _GAIN_LOW)) { ps->AsicReg.RD_LineControl = 192; } IOCmdRegisterToScanner( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); counter = 0; /* ReAdjustRGBGain () */ for (w1 = 0; w1 < 16; w1++) { ps->PauseColorMotorRunStates( ps ); DacP98FillGainOutDirectPort( ps ); /* SetReadNegativeTempRegister () */ ps->AsicReg.RD_Motor0Control = 0; IOCmdRegisterToScanner( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward; ps->AsicReg.RD_ModelControl = _ModelDpi600 + _LED_CONTROL + _LED_ACTIVITY; ps->AsicReg.RD_Dpi = ps->PhysicalDpi; if (!ps->wNegAdjustX) { ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX + _Negative96OriginOffsetX * 2); } else { ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX + ps->wNegAdjustX); } ps->AsicReg.RD_Pixels = 960; ps->AsicReg.RD_XStepTime = 32; IOPutOnAllRegisters( ps ); /* ReReadNegativeTemp () */ MiscStartTimer( &timer, _SECOND ); while((IOReadFifoLength( ps ) < 960) && !MiscCheckTimer( &timer)) { _DO_UDELAY(1); } /* ReadColorDataIn() - Read 1 RGB line */ ps->AsicReg.RD_ModeControl = _ModeFifoRSel; IOReadScannerImageData( ps, pNegativeTempRam, 960 ); ps->AsicReg.RD_ModeControl = _ModeFifoGSel; IOReadScannerImageData( ps, pNegativeTempRam + 960, 960); ps->AsicReg.RD_ModeControl = _ModeFifoBSel; IOReadScannerImageData( ps ,pNegativeTempRam + 960 * 2, 960); /* ReAdjustGainAverage() */ pDest = pSrce = pNegativeTempRam; for( dw1 = 0; dw1 < (960 * 3) / 16; dw1++, pDest++ ) { for( dw = 0, wSum = 0; dw < 16; dw++, pSrce++ ) wSum += *pSrce; *pDest = wSum / 16; } /* FindTheMaxGainValue */ pbReg[0] = &ps->bRedGainIndex; pbReg[1] = &ps->bGreenGainIndex; pbReg[2] = &ps->bBlueGainIndex; for (w = 0, p.pb = pNegativeTempRam; w < 3; w++) { for (dw = 960 / 16, b [w] = 0; dw; dw--, p.pb++) { if (b[w] < *p.pb) b[w] = *p.pb; } if (b [w] < _GAIN_LOW) { if (( _GAIN_P98_HIGH - b [w]) < b [w]) *(pbReg [w]) += 1; else *(pbReg [w]) += 4; } else { if (b [w] > _GAIN_P98_HIGH) *(pbReg [w]) -= 1; } } for (w2 = 0; w2 < 3; w2++) { if (*(pbReg[w2]) > 31) (*(pbReg[w2])) = 31; } if ((b[0] == 0) || (b[1] == 0) || (b[2] == 0)) { counter++; if (counter < 16) { w1--; ps->bRedGainIndex -= 4; ps->bGreenGainIndex -= 4; ps->bBlueGainIndex -= 4; } } } DacP98FillGainOutDirectPort( ps ); ps->Shade.DarkOffset.Colors.Red = 0; ps->Shade.DarkOffset.Colors.Green = 0; ps->Shade.DarkOffset.Colors.Blue = 0; ps->OpenScanPath( ps ); DacP98FillShadingDarkToShadingRegister( ps ); ps->CloseScanPath( ps ); DacP98AdjustDark( ps ); } /*............................................................................. * */ static void tpaP98RecalculateShadingGainandData( pScanData ps ) { DataPointer p; ULong dw; UShort filmAdjustX; UShort wOldRedGain, wOldGreenGain, wOldBlueGain; UShort wNewRedGain, wNewGreenGain, wNewBlueGain; /* AdjustDarkCondition () */ ps->Shade.pCcdDac->DarkDAC.Colors.Red = ps->bsPreRedDAC; ps->Shade.pCcdDac->DarkDAC.Colors.Green = ps->bsPreGreenDAC; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = ps->bsPreBlueDAC; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = ps->wsDACCompareHighRed; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = ps->wsDACCompareLowRed; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = ps->wsDACCompareHighGreen; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = ps->wsDACCompareLowGreen; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = ps->wsDACCompareHighBlue; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = ps->wsDACCompareLowBlue; wOldRedGain = a_wGainString[ps->bRedGainIndex] * 100/ps->wReduceRedFactor; /* SearchNewGain() */ for (ps->bRedGainIndex = 0; ps->bRedGainIndex < 32; ps->bRedGainIndex++) { if (wOldRedGain < a_wGainString[ps->bRedGainIndex]) break; } if (0 == ps->bRedGainIndex) ps->bRedGainIndex ++; wNewRedGain = a_wGainString[--ps->bRedGainIndex]; wOldGreenGain = a_wGainString[ps->bGreenGainIndex]*100/ ps->wReduceGreenFactor; /* SearchNewGain() */ for (ps->bGreenGainIndex = 0; ps->bGreenGainIndex < 32; ps->bGreenGainIndex++) { if (wOldGreenGain < a_wGainString[ps->bGreenGainIndex]) break; } if (0 == ps->bGreenGainIndex) ps->bGreenGainIndex ++; wNewGreenGain = a_wGainString[--ps->bGreenGainIndex]; wOldBlueGain = a_wGainString[ps->bBlueGainIndex]*100/ps->wReduceBlueFactor; /* SearchNewGain() */ for (ps->bBlueGainIndex = 0;ps->bBlueGainIndex < 32;ps->bBlueGainIndex++) { if (wOldBlueGain < a_wGainString[ps->bBlueGainIndex]) break; } if (0 == ps->bBlueGainIndex) ps->bBlueGainIndex ++; wNewBlueGain = a_wGainString[--ps->bBlueGainIndex]; DacP98FillGainOutDirectPort( ps ); ps->Shade.DarkOffset.Colors.Red = 0; ps->Shade.DarkOffset.Colors.Green = 0; ps->Shade.DarkOffset.Colors.Blue = 0; ps->OpenScanPath( ps ); DacP98FillShadingDarkToShadingRegister( ps ); ps->CloseScanPath( ps ); DacP98AdjustDark( ps ); /* RecalculateTransparencyImage() */ if (ps->DataInf.dwScanFlag & SCANDEF_Transparency) { filmAdjustX = ps->wPosAdjustX; } else { filmAdjustX = ps->wNegAdjustX; } if (!filmAdjustX) { p.pw = (pUShort)(ps->pScanBuffer1 + ps->dwOffsetNegative + _Negative96OriginOffsetX * 2); } else { p.pw = (pUShort)(ps->pScanBuffer1 + ps->dwOffsetNegative + filmAdjustX); } /* RecalculateData() */ for (dw= 0; dw < _NegativePageWidth * 2 + 132; dw++, p.pw++) *p.pw = *p.pw * wNewRedGain / wOldRedGain; if (!ps->wNegAdjustX) { p.pw = (pUShort)(ps->pScanBuffer1 + 5400 * 2 + ps->dwOffsetNegative + _Negative96OriginOffsetX * 2); } else { p.pw = (pUShort)(ps->pScanBuffer1 + 5400 * 2 + ps->dwOffsetNegative + ps->wNegAdjustX); } /* RecalculateData() */ for (dw= 0; dw < _NegativePageWidth * 2 + 132; dw++, p.pw++) *p.pw = *p.pw * wNewGreenGain / wOldGreenGain; if (!ps->wNegAdjustX) { p.pw = (pUShort)(ps->pScanBuffer1 + 5400 * 4 + ps->dwOffsetNegative + _Negative96OriginOffsetX * 2); } else { p.pw = (pUShort)(ps->pScanBuffer1 + 5400 * 4 + ps->dwOffsetNegative + ps->wNegAdjustX); } /* RecalculateData() - 64 + dwoffset70 */ for (dw= 0; dw < _NegativePageWidth * 2 + 132; dw++, p.pw++) *p.pw = *p.pw * wNewBlueGain / wOldBlueGain; } /************************ exported functions *********************************/ /*............................................................................. * perform some adjustments according to the source (normal, transparency etc) */ _LOC void TPAP98001AverageShadingData( pScanData ps ) { DBG( DBG_LOW, "TPAP98001AverageShadingData()\n" ); ps->wNegAdjustX = 0; ps->wPosAdjustX = 0; ps->dwOffsetNegative = 0; tpaP98ShadingWaveformSum( ps ); /* * CHANGE: to support Grayscale images in transparency and negative mode * original code: if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) && */ if((ps->DataInf.wPhyDataType >= COLOR_256GRAY) && (ps->DataInf.dwScanFlag & SCANDEF_TPA)) { if (((ps->DataInf.dwScanFlag & SCANDEF_Negative) && !ps->wNegAdjustX) || ((ps->DataInf.dwScanFlag & SCANDEF_Transparency) && !ps->wPosAdjustX)) { Long dwLeft, dwRight; pUShort pw = (pUShort)ps->pScanBuffer1; for (dwLeft = 0; dwLeft < 5400; dwLeft++) if (pw[dwLeft] >= 600) break; for (dwRight = 4600; dwRight; dwRight--) if (pw[dwRight] >= 600) break; DBG( DBG_LOW, "_TPAPageWidth = %u, _NegativePageWidth = %u\n" "right = %d, left = %d --> right = %d\n", _TPAPageWidth, _NegativePageWidth, dwRight, dwLeft, (((Long)dwRight-(Long)dwLeft)/2)); dwRight = (dwRight - dwLeft) / 2; if (ps->DataInf.dwScanFlag & SCANDEF_Negative) { if (dwRight >= (Long)_NegativePageWidth) { ps->wNegAdjustX = (UShort)(dwRight - _NegativePageWidth + dwLeft - ps->dwOffset70 - ps->Device.DataOriginX + 4U); if( ps->wNegAdjustX > (_Negative96OriginOffsetX * 2U)) ps->wNegAdjustX = (_Negative96OriginOffsetX * 2U); ps->DataInf.crImage.x += ps->wNegAdjustX; } else { ps->DataInf.crImage.x += (_Negative96OriginOffsetX * 2U); } } else { if (dwRight >= (Long)_TPAPageWidth) { ps->wPosAdjustX = (UShort)(dwRight - _TPAPageWidth + dwLeft - ps->dwOffset70 - ps->Device.DataOriginX + 4U); if( ps->wPosAdjustX > (_Transparency96OriginOffsetX * 2U)) ps->wPosAdjustX = (_Transparency96OriginOffsetX * 2U); ps->DataInf.crImage.x += ps->wPosAdjustX; } else { ps->DataInf.crImage.x += (_Transparency96OriginOffsetX * 2U); } } } #if 0 else { /* CHANGE: as we always reset the values, we can ignore this code..*/ if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) ps->DataInf.crImage.x += ps->wNegAdjustX; else ps->DataInf.crImage.x += ps->wPosAdjustX; } #endif if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) { ps->dwOffsetNegative = (ps->dwOffset70 + 64+4) * 2; tpaP98GetNegativeTempRamData( ps ); tpaP98RecalculateNegativeShadingGain( ps ); } else { ps->wReduceRedFactor = 0x3e; ps->wReduceGreenFactor = 0x39; ps->wReduceBlueFactor = 0x42; if( ps->Device.bCCDID == _CCD_518 ) { ps->wReduceRedFactor = 55; ps->wReduceGreenFactor = 55; ps->wReduceBlueFactor = 55; } if( ps->Device.bCCDID == _CCD_3797 ) { ps->wReduceRedFactor = 42; ps->wReduceGreenFactor = 50; ps->wReduceBlueFactor = 50; } tpaP98RecalculateShadingGainandData( ps ); } } } /*............................................................................. * perform some adjustments according to the source (normal, transparency etc) */ _LOC void TPAP98003FindCenterPointer( pScanData ps ) { ULong i; ULong width; ULong left; ULong right; pRGBUShortDef pwSum = ps->Bufs.b2.pSumRGB; if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) width = _NEG_PAGEWIDTH600; else width = _NEG_PAGEWIDTH600 - 94; /* 2.54 cm tolerance */ left = ps->Device.DataOriginX + _NEG_ORG_OFFSETX * 2 - 600; right = ps->Device.DataOriginX + _NEG_ORG_OFFSETX * 2 + _NEG_PAGEWIDTH600 + 600; for( i = 5400UL - left, pwSum = ps->Bufs.b2.pSumRGB; i--; left++) if( pwSum[left].Red > _NEG_EDGE_VALUE && pwSum[left].Green > _NEG_EDGE_VALUE && pwSum[left].Blue > _NEG_EDGE_VALUE) break; for( i = 5400UL - left, pwSum = ps->Bufs.b2.pSumRGB; i--; right--) if( pwSum[right].Red > _NEG_EDGE_VALUE && pwSum[right].Green > _NEG_EDGE_VALUE && pwSum[right].Blue > _NEG_EDGE_VALUE) break; if((right <= left) || ((right - left) < width)) { if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) ps->Scan.negBegin = ps->Device.DataOriginX + _NEG_ORG_OFFSETX * 2; else ps->Scan.posBegin = ps->Device.DataOriginX + _POS_ORG_OFFSETX * 2; } else { if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) ps->Scan.negBegin = (right + left) / 2UL - _NEG_PAGEWIDTH; else ps->Scan.posBegin = (right + left) / 2UL - _POS_PAGEWIDTH; } } /*............................................................................. * this function does some reshading, when scanning negatives on an ASIC 98003 * based scanner */ _LOC void TPAP98003Reshading( pScanData ps ) { Byte bHi[3], bHiLeft[3], bHiRight[3]; ULong i, dwR, dwG, dwB, dwSum; ULong dwIndex, dwIndexRight, dwIndexLeft; DataPointer RedPtr, GreenPtr, BluePtr; TimerDef timer; bHi[0] = bHi[1] = bHi[2] = 0; /* CHECK: Why this ??? */ #if 1 ps->Scan.negScan[1].exposureTime = 144; ps->Scan.negScan[1].xStepTime = 18; ps->Scan.negScan[2].exposureTime = 144; ps->Scan.negScan[2].xStepTime = 36; ps->Scan.negScan[3].exposureTime = 144; ps->Scan.negScan[3].xStepTime = 72; ps->Scan.negScan[4].exposureTime = 144; ps->Scan.negScan[4].xStepTime = 144; #endif ps->Shade.wExposure = ps->Scan.negScan[ps->Scan.dpiIdx].exposureTime; ps->Shade.wXStep = ps->Scan.negScan[ps->Scan.dpiIdx].xStepTime; MiscStartTimer( &timer, _SECOND ); while(!(IOGetScanState(ps, _TRUE) & _SCANSTATE_STOP) && (_OK == MiscCheckTimer(&timer))); IODataToRegister( ps, ps->RegXStepTime, (Byte)(ps->AsicReg.RD_LineControl >> 4)); _DODELAY( 12 ); MotorP98003PositionYProc( ps, _NEG_SHADING_OFFS ); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime ); ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; IOSelectLampSource( ps ); IODataToRegister( ps, ps->RegLineControl, _LOBYTE(ps->Shade.wExposure)); IODataToRegister( ps, ps->RegXStepTime, _LOBYTE(ps->Shade.wXStep)); ps->AsicReg.RD_LineControl = _LOBYTE(ps->Shade.wExposure); ps->AsicReg.RD_ExtLineControl = _HIBYTE(ps->Shade.wExposure); ps->AsicReg.RD_XStepTime = (Byte)(ps->Shade.wExposure); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; ps->AsicReg.RD_Origin = (UShort)ps->Scan.negBegin; ps->AsicReg.RD_Pixels = _NEG_PAGEWIDTH600; memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); /* put 9 scan states to make sure there are 8 lines available at least */ for( i = 0; i <= 12; i++) ps->a_nbNewAdrPointer[i] = 0x8f; IOPutOnAllRegisters( ps ); _DODELAY( 70 ); /* prepare the buffers... */ memset( ps->Bufs.TpaBuf.pb, 0, _SizeTpaDataBuf ); RedPtr.pb = ps->Bufs.b1.pShadingMap; GreenPtr.pb = RedPtr.pb + _NEG_PAGEWIDTH600; BluePtr.pb = GreenPtr.pb + _NEG_PAGEWIDTH600; for( dwSum = 8; dwSum--; ) { IOReadOneShadingLine( ps, ps->Bufs.b1.pShadingMap, _NEG_PAGEWIDTH600 ); for( i = 0; i < _NEG_PAGEWIDTH600; i++) { ps->Bufs.TpaBuf.pusrgb[i].Red += RedPtr.pb[i]; ps->Bufs.TpaBuf.pusrgb[i].Green += GreenPtr.pb[i]; ps->Bufs.TpaBuf.pusrgb[i].Blue += BluePtr.pb[i]; } } for( i = 0; i < (_NEG_PAGEWIDTH600 * 3UL); i++ ) ps->Bufs.TpaBuf.pb[i] = ps->Bufs.TpaBuf.pw[i] >> 3; RedPtr.pb = ps->Bufs.TpaBuf.pb; /* Convert RGB to gray scale (Brightness), and average 16 pixels */ for( bHiRight[1] = 0, i = dwIndexRight = 0; i < _NEG_PAGEWIDTH600 / 2; i += 16 ) { bHiRight [0] = (Byte)(((((ULong) RedPtr.pbrgb [i].Red + (ULong) RedPtr.pbrgb[i + 1].Red + (ULong) RedPtr.pbrgb[i + 2].Red + (ULong) RedPtr.pbrgb[i + 3].Red + (ULong) RedPtr.pbrgb[i + 4].Red + (ULong) RedPtr.pbrgb[i + 5].Red + (ULong) RedPtr.pbrgb[i + 6].Red + (ULong) RedPtr.pbrgb[i + 7].Red + (ULong) RedPtr.pbrgb[i + 8].Red + (ULong) RedPtr.pbrgb[i + 9].Red + (ULong) RedPtr.pbrgb[i + 10].Red + (ULong) RedPtr.pbrgb[i + 11].Red + (ULong) RedPtr.pbrgb[i + 12].Red + (ULong) RedPtr.pbrgb[i + 13].Red + (ULong) RedPtr.pbrgb[i + 14].Red + (ULong) RedPtr.pbrgb[i + 15].Red) >> 4) * 30UL + (((ULong) RedPtr.pbrgb[i].Green + (ULong) RedPtr.pbrgb[i + 1].Green + (ULong) RedPtr.pbrgb[i + 2].Green + (ULong) RedPtr.pbrgb[i + 3].Green + (ULong) RedPtr.pbrgb[i + 4].Green + (ULong) RedPtr.pbrgb[i + 5].Green + (ULong) RedPtr.pbrgb[i + 6].Green + (ULong) RedPtr.pbrgb[i + 7].Green + (ULong) RedPtr.pbrgb[i + 8].Green + (ULong) RedPtr.pbrgb[i + 9].Green + (ULong) RedPtr.pbrgb[i + 10].Green + (ULong) RedPtr.pbrgb[i + 11].Green + (ULong) RedPtr.pbrgb[i + 12].Green + (ULong) RedPtr.pbrgb[i + 13].Green + (ULong) RedPtr.pbrgb[i + 14].Green + (ULong) RedPtr.pbrgb[i + 15].Green) >> 4) * 59UL + (((ULong) RedPtr.pbrgb[i].Blue + (ULong) RedPtr.pbrgb[i + 1].Blue + (ULong) RedPtr.pbrgb[i + 2].Blue + (ULong) RedPtr.pbrgb[i + 3].Blue + (ULong) RedPtr.pbrgb[i + 4].Blue + (ULong) RedPtr.pbrgb[i + 5].Blue + (ULong) RedPtr.pbrgb[i + 6].Blue + (ULong) RedPtr.pbrgb[i + 7].Blue + (ULong) RedPtr.pbrgb[i + 8].Blue + (ULong) RedPtr.pbrgb[i + 9].Blue + (ULong) RedPtr.pbrgb[i + 10].Blue + (ULong) RedPtr.pbrgb[i + 11].Blue + (ULong) RedPtr.pbrgb[i + 12].Blue + (ULong) RedPtr.pbrgb[i + 13].Blue + (ULong) RedPtr.pbrgb[i + 14].Blue + (ULong) RedPtr.pbrgb[i + 15].Blue) >> 4) * 11UL) / 100UL); if( bHiRight[1] < bHiRight[0] ) { bHiRight[1] = bHiRight[0]; dwIndexRight = i; } } /* Convert RGB to gray scale (Brightness), and average 16 pixels */ for( bHiLeft[1] = 0, i = dwIndexLeft = _NEG_PAGEWIDTH / 2; i < _NEG_PAGEWIDTH600; i += 16 ) { bHiLeft [0] = (Byte)(((((ULong) RedPtr.pbrgb[i].Red + (ULong) RedPtr.pbrgb[i + 1].Red + (ULong) RedPtr.pbrgb[i + 2].Red + (ULong) RedPtr.pbrgb[i + 3].Red + (ULong) RedPtr.pbrgb[i + 4].Red + (ULong) RedPtr.pbrgb[i + 5].Red + (ULong) RedPtr.pbrgb[i + 6].Red + (ULong) RedPtr.pbrgb[i + 7].Red + (ULong) RedPtr.pbrgb[i + 8].Red + (ULong) RedPtr.pbrgb[i + 9].Red + (ULong) RedPtr.pbrgb[i + 10].Red + (ULong) RedPtr.pbrgb[i + 11].Red + (ULong) RedPtr.pbrgb[i + 12].Red + (ULong) RedPtr.pbrgb[i + 13].Red + (ULong) RedPtr.pbrgb[i + 14].Red + (ULong) RedPtr.pbrgb[i + 15].Red) >> 4) * 30UL + (((ULong) RedPtr.pbrgb[i].Green + (ULong) RedPtr.pbrgb[i + 1].Green + (ULong) RedPtr.pbrgb[i + 2].Green + (ULong) RedPtr.pbrgb[i + 3].Green + (ULong) RedPtr.pbrgb[i + 4].Green + (ULong) RedPtr.pbrgb[i + 5].Green + (ULong) RedPtr.pbrgb[i + 6].Green + (ULong) RedPtr.pbrgb[i + 7].Green + (ULong) RedPtr.pbrgb[i + 8].Green + (ULong) RedPtr.pbrgb[i + 9].Green + (ULong) RedPtr.pbrgb[i + 10].Green + (ULong) RedPtr.pbrgb[i + 11].Green + (ULong) RedPtr.pbrgb[i + 12].Green + (ULong) RedPtr.pbrgb[i + 13].Green + (ULong) RedPtr.pbrgb[i + 14].Green + (ULong) RedPtr.pbrgb[i + 15].Green) >> 4) * 59UL + (((ULong) RedPtr.pbrgb[i].Blue + (ULong) RedPtr.pbrgb[i + 1].Blue + (ULong) RedPtr.pbrgb[i + 2].Blue + (ULong) RedPtr.pbrgb[i + 3].Blue + (ULong) RedPtr.pbrgb[i + 4].Blue + (ULong) RedPtr.pbrgb[i + 5].Blue + (ULong) RedPtr.pbrgb[i + 6].Blue + (ULong) RedPtr.pbrgb[i + 7].Blue + (ULong) RedPtr.pbrgb[i + 8].Blue + (ULong) RedPtr.pbrgb[i + 9].Blue + (ULong) RedPtr.pbrgb[i + 10].Blue + (ULong) RedPtr.pbrgb[i + 11].Blue + (ULong) RedPtr.pbrgb[i + 12].Blue + (ULong) RedPtr.pbrgb[i + 13].Blue + (ULong) RedPtr.pbrgb[i + 14].Blue + (ULong) RedPtr.pbrgb[i + 15].Blue) >> 4) * 11UL) / 100UL); if( bHiLeft[1] < bHiLeft[0] ) { bHiLeft[1] = bHiLeft[0]; dwIndexLeft = i; } } if((bHiLeft[1] < 200) && (bHiRight[1] < 200)) { if( bHiLeft[1] < bHiRight[1] ) dwIndex = dwIndexRight; else dwIndex = dwIndexLeft; } else { if( bHiLeft[1] > 200 ) dwIndex = dwIndexRight; else dwIndex = dwIndexLeft; } /* Get the hilight */ RedPtr.pusrgb = ps->Bufs.b2.pSumRGB + dwIndex + ps->AsicReg.RD_Origin + _SHADING_BEGINX; for( dwR = dwG = dwB = 0, i = 16; i--; RedPtr.pusrgb++ ) { dwR += RedPtr.pusrgb->Red; dwG += RedPtr.pusrgb->Green; dwB += RedPtr.pusrgb->Blue; } dwR >>= 8; dwG >>= 8; dwB >>= 8; if( dwR > dwG && dwR > dwB ) ps->Shade.bGainHigh = (Byte)dwR; /* >> 4 for average, >> 4 to 8-bit */ else { if( dwG > dwR && dwG > dwB ) ps->Shade.bGainHigh = (Byte)dwG; else ps->Shade.bGainHigh = (Byte)dwB; } ps->Shade.bGainHigh = (Byte)(ps->Shade.bGainHigh - 0x18); ps->Shade.bGainLow = (Byte)(ps->Shade.bGainHigh - 0x10); /* Reshading to get the new gain */ ps->Shade.Hilight.Colors.Red = 0; ps->Shade.Hilight.Colors.Green = 0; ps->Shade.Hilight.Colors.Blue = 0; ps->Shade.Gain.Colors.Red++; ps->Shade.Gain.Colors.Green++; ps->Shade.Gain.Colors.Blue++; ps->Shade.fStop = _FALSE; RedPtr.pb = ps->Bufs.b1.pShadingMap + dwIndex; GreenPtr.pb = RedPtr.pb + _NEG_PAGEWIDTH600; BluePtr.pb = GreenPtr.pb + _NEG_PAGEWIDTH600; for( i = 16; i-- && !ps->Shade.fStop;) { ps->Shade.fStop = _TRUE; DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain ); IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; IOSelectLampSource( ps ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->a_nbNewAdrPointer[1] = 0x77; IOPutOnAllRegisters( ps ); _DODELAY( 50 ); if(IOReadOneShadingLine(ps,ps->Bufs.b1.pShadingMap,_NEG_PAGEWIDTH600)) { bHi[0] = DacP98003SumGains( RedPtr.pb, 32 ); bHi[1] = DacP98003SumGains( GreenPtr.pb, 32 ); bHi[2] = DacP98003SumGains( BluePtr.pb, 32 ); if( !bHi[0] || !bHi[1] || !bHi[2]) { ps->Shade.fStop = _FALSE; } else { DacP98003AdjustGain( ps, _CHANNEL_RED, bHi[0] ); DacP98003AdjustGain( ps, _CHANNEL_GREEN, bHi[1] ); DacP98003AdjustGain( ps, _CHANNEL_BLUE, bHi[2] ); } } else ps->Shade.fStop = _FALSE; } DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain ); /* Set RGB Gain */ if( dwR && dwG && dwB ) { if(ps->Device.bCCDID == _CCD_3797 || ps->Device.bDACType == _DA_ESIC) { ps->Shade.pCcdDac->GainResize.Colors.Red = (UShort)((ULong)bHi[0] * 100UL / dwR); ps->Shade.pCcdDac->GainResize.Colors.Green = (UShort)((ULong)bHi[1] * 100UL / dwG); ps->Shade.pCcdDac->GainResize.Colors.Blue = (UShort)((ULong)bHi[2] * 100UL / dwB); } else { ps->Shade.pCcdDac->GainResize.Colors.Red = (UShort)((ULong)bHi[0] * 90UL / dwR); ps->Shade.pCcdDac->GainResize.Colors.Green = (UShort)((ULong)bHi[1] * 77UL / dwG); ps->Shade.pCcdDac->GainResize.Colors.Blue = (UShort)((ULong)bHi[2] * 73UL / dwB); } ps->Shade.DarkOffset.Colors.Red += (UShort)((dwR > bHi[0]) ? dwR - bHi[0] : 0); ps->Shade.DarkOffset.Colors.Green += (UShort)((dwG > bHi[1]) ? dwG - bHi[1] : 0); ps->Shade.DarkOffset.Colors.Blue += (UShort)((dwB > bHi[2]) ? dwB - bHi[2] : 0); if( ps->Device.bDACType != _DA_ESIC && ps->Device.bCCDID != _CCD_3799 ) { ps->Shade.DarkOffset.Colors.Red = (UShort)(ps->Shade.DarkOffset.Colors.Red * ps->Shade.pCcdDac->GainResize.Colors.Red / 100UL); ps->Shade.DarkOffset.Colors.Green = (UShort)(ps->Shade.DarkOffset.Colors.Green * ps->Shade.pCcdDac->GainResize.Colors.Green / 100UL); ps->Shade.DarkOffset.Colors.Blue = (UShort)(ps->Shade.DarkOffset.Colors.Blue * ps->Shade.pCcdDac->GainResize.Colors.Blue / 100UL); } } /* AdjustDark () */ ps->AsicReg.RD_Origin = _SHADING_BEGINX; ps->AsicReg.RD_Pixels = 5400; } /* END PLUSTEK-PP_TPA.C .....................................................*/ sane-backends-1.0.27/backend/kvs1025.h0000664000175000017500000000756212775277260014126 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. */ /* sane - Scanner Access Now Easy. Panasonic KV-S1020C / KV-S1025C USB scanners. */ #ifndef __KVS1025_H #define __KVS1025_H /* SANE backend name */ #ifdef BACKEND_NAME #undef BACKEND_NAME #endif #define BACKEND_NAME kvs1025 /* Build version */ #define V_BUILD 5 /* Paper range supported -- MAX scanner limits */ #define KV_MAX_X_RANGE 216 #define KV_MAX_Y_RANGE 2540 /* Round ULX, ULY, Width and Height to 16 Pixels */ #define KV_PIXEL_ROUND 19200 /* (XR * W / 1200) % 16 == 0 i.e. (XR * W) % 19200 == 0 */ /* MAX IULs per LINE */ #define KV_PIXEL_MAX 14064 /* Max 14064 pixels per line, 1/1200 inch each */ #define MM_PER_INCH 25.4 #define mmToIlu(mm) (((mm) * 1200) / MM_PER_INCH) #define iluToMm(ilu) (((ilu) * MM_PER_INCH) / 1200) /* Vendor defined options */ #define SANE_NAME_DUPLEX "duplex" #define SANE_NAME_PAPER_SIZE "paper-size" #define SANE_NAME_AUTOSEP "autoseparation" #define SANE_NAME_LANDSCAPE "landscape" #define SANE_NAME_INVERSE "inverse" #define SANE_NAME_MIRROR "mirror" #define SANE_NAME_LONGPAPER "longpaper" #define SANE_NAME_LENGTHCTL "length-control" #define SANE_NAME_MANUALFEED "manual-feed" #define SANE_NAME_FEED_TIMEOUT "feed-timeout" #define SANE_NAME_DBLFEED "double-feed" #define SANE_TITLE_DUPLEX SANE_I18N("Duplex") #define SANE_TITLE_PAPER_SIZE SANE_I18N("Paper size") #define SANE_TITLE_AUTOSEP SANE_I18N("Automatic separation") #define SANE_TITLE_LANDSCAPE SANE_I18N("Landscape") #define SANE_TITLE_INVERSE SANE_I18N("Inverse Image") #define SANE_TITLE_MIRROR SANE_I18N("Mirror image") #define SANE_TITLE_LONGPAPER SANE_I18N("Long paper mode") #define SANE_TITLE_LENGTHCTL SANE_I18N("Length control mode") #define SANE_TITLE_MANUALFEED SANE_I18N("Manual feed mode") #define SANE_TITLE_FEED_TIMEOUT SANE_I18N("Manual feed timeout") #define SANE_TITLE_DBLFEED SANE_I18N("Double feed detection") #define SANE_DESC_DUPLEX \ SANE_I18N("Enable Duplex (Dual-Sided) Scanning") #define SANE_DESC_PAPER_SIZE \ SANE_I18N("Physical size of the paper in the ADF"); #define SANE_DESC_AUTOSEP \ SANE_I18N("Automatic separation") #define SIDE_FRONT 0x00 #define SIDE_BACK 0x80 /* Debug levels. * Should be common to all backends. */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 #define DBG_shortread 101 /* Prototypes of SANE backend functions, see kvs1025.c */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback /* __sane_unused__ authorize */ ); void sane_exit (void); SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool /*__sane_unused__ local_only*/ ); SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle); void sane_close (SANE_Handle handle); const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info); SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); SANE_Status sane_start (SANE_Handle handle); SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len); void sane_cancel (SANE_Handle handle); SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool m); SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fd); SANE_String_Const sane_strstatus (SANE_Status status); #endif /* #ifndef __KVS1025_H */ sane-backends-1.0.27/backend/artec_eplus48u.h0000664000175000017500000004543212112021330015622 00000000000000#ifndef ARTEC48U_H #define ARTEC48U_H #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include #ifdef HAVE_SYS_IPC_H #include #endif #include #include #include #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_thread.h" #define _MAX_ID_LEN 20 /*Uncomment next line for button support. This actually isn't supported by the frontends. */ /*#define ARTEC48U_USE_BUTTONS 1*/ #define ARTEC48U_PACKET_SIZE 64 #define DECLARE_FUNCTION_NAME(name) \ IF_DBG ( static const char function_name[] = name; ) typedef SANE_Byte Artec48U_Packet[ARTEC48U_PACKET_SIZE]; #define XDBG(args) do { IF_DBG ( DBG args ); } while (0) /* calculate the minimum/maximum values */ #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) /* return the lower/upper 8 bits of a 16 bit word */ #define HIBYTE(w) ((SANE_Byte)(((SANE_Word)(w) >> 8) & 0xFF)) #define LOBYTE(w) ((SANE_Byte)(w)) #define CHECK_DEV_NOT_NULL(dev, func_name) \ do { \ if (!(dev)) \ { \ XDBG ((3, "%s: BUG: NULL device\n", (func_name))); \ return SANE_STATUS_INVAL; \ } \ } while (SANE_FALSE) /** Check that the device is open. * * @param dev Pointer to the device object (Artec48U_Device). * @param func_name Function name (for use in debug messages). */ #define CHECK_DEV_OPEN(dev, func_name) \ do { \ CHECK_DEV_NOT_NULL ((dev), (func_name)); \ if ((dev)->fd == -1) \ { \ XDBG ((3, "%s: BUG: device %p not open\n", (func_name), (void*)(dev)));\ return SANE_STATUS_INVAL; \ } \ } while (SANE_FALSE) #define CHECK_DEV_ACTIVE(dev,func_name) \ do { \ CHECK_DEV_OPEN ((dev), (func_name)); \ if (!(dev)->active) \ { \ XDBG ((3, "%s: BUG: device %p not active\n", \ (func_name), (void*)(dev))); \ return SANE_STATUS_INVAL; \ } \ } while (SANE_FALSE) typedef struct Artec48U_Device Artec48U_Device; typedef struct Artec48U_Scan_Request Artec48U_Scan_Request; typedef struct Artec48U_Scanner Artec48U_Scanner; typedef struct Artec48U_Scan_Parameters Artec48U_Scan_Parameters; typedef struct Artec48U_AFE_Parameters Artec48U_AFE_Parameters; typedef struct Artec48U_Exposure_Parameters Artec48U_Exposure_Parameters; typedef struct Artec48U_Line_Reader Artec48U_Line_Reader; typedef struct Artec48U_Delay_Buffer Artec48U_Delay_Buffer; enum artec_options { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_SCAN_MODE, OPT_BIT_DEPTH, OPT_BLACK_LEVEL, OPT_RESOLUTION, OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_GAMMA, OPT_GAMMA_R, OPT_GAMMA_G, OPT_GAMMA_B, OPT_DEFAULT_ENHANCEMENTS, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_CALIBRATION_GROUP, OPT_CALIBRATE, OPT_CALIBRATE_SHADING, #ifdef ARTEC48U_USE_BUTTONS OPT_BUTTON_STATE, #endif /* must come last: */ NUM_OPTIONS }; /** Artec48U analog front-end (AFE) parameters. */ struct Artec48U_AFE_Parameters { SANE_Byte r_offset; /**< Red channel offset */ SANE_Byte r_pga; /**< Red channel PGA gain */ SANE_Byte g_offset; /**< Green channel offset (also used for mono) */ SANE_Byte g_pga; /**< Green channel PGA gain (also used for mono) */ SANE_Byte b_offset; /**< Blue channel offset */ SANE_Byte b_pga; /**< Blue channel PGA gain */ }; /** TV9693 exposure time parameters. */ struct Artec48U_Exposure_Parameters { SANE_Int r_time; /**< Red exposure time */ SANE_Int g_time; /**< Red exposure time */ SANE_Int b_time; /**< Red exposure time */ }; struct Artec48U_Device { Artec48U_Device *next; /** Device file descriptor. */ int fd; /** Device activation flag. */ SANE_Bool active; SANE_String_Const name; SANE_Device sane; /** Scanner model data. */ SANE_String_Const firmware_path; double gamma_master; double gamma_r; double gamma_g; double gamma_b; Artec48U_Exposure_Parameters exp_params; Artec48U_AFE_Parameters afe_params; Artec48U_AFE_Parameters artec_48u_afe_params; Artec48U_Exposure_Parameters artec_48u_exposure_params; SANE_Int optical_xdpi; SANE_Int optical_ydpi; SANE_Int base_ydpi; SANE_Int xdpi_offset; /* in optical_xdpi units */ SANE_Int ydpi_offset; /* in optical_ydpi units */ SANE_Int x_size; /* in optical_xdpi units */ SANE_Int y_size; /* in optical_ydpi units */ /* the number of lines, that we move forward before we start reading the shading lines */ int shading_offset; /* the number of lines we read for the black shading buffer */ int shading_lines_b; /* the number of lines we read for the white shading buffer */ int shading_lines_w; SANE_Fixed x_offset, y_offset; SANE_Bool read_active; SANE_Byte *read_buffer; size_t requested_buffer_size; size_t read_pos; size_t read_bytes_in_buffer; size_t read_bytes_left; unsigned int is_epro; unsigned int epro_mult; }; /** Scan parameters for artec48u_device_setup_scan(). * * These parameters describe a low-level scan request; many such requests are * executed during calibration, and they need to have parameters separate from * the main request (Artec48U_Scan_Request). E.g., on the BearPaw 2400 TA the * scan to find the home position is always done at 300dpi 8-bit mono with * fixed width and height, regardless of the high-level scan parameters. */ struct Artec48U_Scan_Parameters { SANE_Int xdpi; /**< Horizontal resolution */ SANE_Int ydpi; /**< Vertical resolution */ SANE_Int depth; /**< Number of bits per channel */ SANE_Bool color; /**< Color mode flag */ SANE_Int pixel_xs; /**< Logical width in pixels */ SANE_Int pixel_ys; /**< Logical height in pixels */ SANE_Int scan_xs; /**< Physical width in pixels */ SANE_Int scan_ys; /**< Physical height in pixels */ SANE_Int scan_bpl; /**< Number of bytes per scan line */ SANE_Bool lineart; /** #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define ARTEC_MIN_X( hw ) ( hw->horz_resolution_list[ 0 ] ? \ hw->horz_resolution_list[ 1 ] : 0 ) #define ARTEC_MAX_X( hw ) ( hw->horz_resolution_list[ 0 ] ? \ hw->horz_resolution_list[ \ hw->horz_resolution_list[ 0 ] ] : 0 ) #define ARTEC_MIN_Y( hw ) ( hw->vert_resolution_list[ 0 ] ? \ hw->vert_resolution_list[ 1 ] : 0 ) #define ARTEC_MAX_Y( hw ) ( hw->vert_resolution_list[ 0 ] ? \ hw->vert_resolution_list[ \ hw->vert_resolution_list[ 0 ] ] : 0 ) typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_X_RESOLUTION, OPT_Y_RESOLUTION, OPT_RESOLUTION_BIND, OPT_PREVIEW, OPT_GRAY_PREVIEW, OPT_NEGATIVE, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_CONTRAST, OPT_BRIGHTNESS, OPT_THRESHOLD, OPT_HALFTONE_PATTERN, OPT_FILTER_TYPE, OPT_PIXEL_AVG, OPT_EDGE_ENH, OPT_CUSTOM_GAMMA, /* use custom gamma table */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_TRANSPARENCY, OPT_ADF, OPT_CALIBRATION_GROUP, OPT_QUALITY_CAL, OPT_SOFTWARE_CAL, /* must come last */ NUM_OPTIONS } ARTEC_Option; /* Some FLAGS */ #define ARTEC_FLAG_CALIBRATE 0x00000001 /* supports hardware calib */ #define ARTEC_FLAG_CALIBRATE_RGB 0x00000003 /* yes 3, set CALIB. also */ #define ARTEC_FLAG_CALIBRATE_DARK_WHITE 0x00000005 /* yes 5, set CALIB. also */ #define ARTEC_FLAG_RGB_LINE_OFFSET 0x00000008 /* need line offset buffer */ #define ARTEC_FLAG_RGB_CHAR_SHIFT 0x00000010 /* RRRRGGGGBBBB line fmt */ #define ARTEC_FLAG_OPT_CONTRAST 0x00000020 /* supports set contrast */ #define ARTEC_FLAG_ONE_PASS_SCANNER 0x00000040 /* single pass scanner */ #define ARTEC_FLAG_GAMMA 0x00000080 /* supports set gamma */ #define ARTEC_FLAG_GAMMA_SINGLE 0x00000180 /* yes 180, implies GAMMA */ #define ARTEC_FLAG_SEPARATE_RES 0x00000200 /* separate x & y scan res */ #define ARTEC_FLAG_IMAGE_REV_LR 0x00000400 /* reversed left-right */ #define ARTEC_FLAG_ENHANCE_LINE_EDGE 0x00000800 /* line edge enhancement */ #define ARTEC_FLAG_HALFTONE_PATTERN 0x00001000 /* > 1 halftone pattern */ #define ARTEC_FLAG_REVERSE_WINDOW 0x00002000 /* reverse selected area */ #define ARTEC_FLAG_SC_BUFFERS_LINES 0x00004000 /* scanner has line buffer */ #define ARTEC_FLAG_SC_HANDLES_OFFSET 0x00008000 /* sc. handles line offset */ #define ARTEC_FLAG_SENSE_HANDLER 0x00010000 /* supports sense handler */ #define ARTEC_FLAG_SENSE_ENH_18 0x00020000 /* supports enh. byte 18 */ #define ARTEC_FLAG_SENSE_BYTE_19 0x00040000 /* supports sense byte 19 */ #define ARTEC_FLAG_SENSE_BYTE_22 0x00080000 /* supports sense byte 22 */ #define ARTEC_FLAG_PIXEL_AVERAGING 0x00100000 /* supports pixel avg-ing */ #define ARTEC_FLAG_ADF 0x00200000 /* auto document feeder */ #define ARTEC_FLAG_OPT_BRIGHTNESS 0x00400000 /* supports set brightness */ #define ARTEC_FLAG_MBPP_NEGATIVE 0x00800000 /* can negate > 1bpp modes */ typedef enum { ARTEC_COMP_LINEART = 0, ARTEC_COMP_HALFTONE, ARTEC_COMP_GRAY, ARTEC_COMP_UNSUPP1, ARTEC_COMP_UNSUPP2, ARTEC_COMP_COLOR } ARTEC_Image_Composition; typedef enum { ARTEC_DATA_IMAGE = 0, ARTEC_DATA_UNSUPP1, ARTEC_DATA_HALFTONE_PATTERN, /* 2 */ ARTEC_DATA_UNSUPP3, ARTEC_DATA_RED_SHADING, /* 4 */ ARTEC_DATA_GREEN_SHADING, /* 5 */ ARTEC_DATA_BLUE_SHADING, /* 6 */ ARTEC_DATA_WHITE_SHADING_OPT, /* 7 */ ARTEC_DATA_WHITE_SHADING_TRANS, /* 8 */ ARTEC_DATA_CAPABILITY_DATA, /* 9 */ ARTEC_DATA_DARK_SHADING, /* 10, 0xA */ ARTEC_DATA_RED_GAMMA_CURVE, /* 11, 0xB */ ARTEC_DATA_GREEN_GAMMA_CURVE, /* 12, 0xC */ ARTEC_DATA_BLUE_GAMMA_CURVE, /* 13, 0xD */ ARTEC_DATA_ALL_GAMMA_CURVE /* 14, 0xE */ } ARTEC_Read_Data_Type; typedef enum { ARTEC_CALIB_RGB = 0, ARTEC_CALIB_DARK_WHITE } ARTEC_Calibrate_Method; typedef enum { ARTEC_FILTER_MONO = 0, ARTEC_FILTER_RED, ARTEC_FILTER_GREEN, ARTEC_FILTER_BLUE } ARTEC_Filter_Type; typedef enum { ARTEC_SOFT_CALIB_RED = 0, ARTEC_SOFT_CALIB_GREEN, ARTEC_SOFT_CALIB_BLUE } ARTEC_Software_Calibrate; typedef struct ARTEC_Device { struct ARTEC_Device *next; SANE_Device sane; double width; SANE_Range x_range; SANE_Word *horz_resolution_list; double height; SANE_Range y_range; SANE_Word *vert_resolution_list; SANE_Range threshold_range; SANE_Range contrast_range; SANE_Range brightness_range; SANE_Word setwindow_cmd_size; SANE_Word calibrate_method; SANE_Word max_read_size; long flags; SANE_Bool support_cap_data_retrieve; SANE_Bool req_shading_calibrate; SANE_Bool req_rgb_line_offset; SANE_Bool req_rgb_char_shift; /* info for 1-pass vs. 3-pass */ SANE_Bool onepass; SANE_Bool support_gamma; SANE_Bool single_gamma; SANE_Int gamma_length; } ARTEC_Device; typedef struct ARTEC_Scanner { /* all the state needed to define a scan request: */ struct ARTEC_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Int gamma_table[4][4096]; double soft_calibrate_data[3][2592]; SANE_Int halftone_pattern[64]; SANE_Range gamma_range; int gamma_length; int scanning; SANE_Parameters params; size_t bytes_to_read; SANE_Int line_offset; /* scan parameters */ char *mode; SANE_Int x_resolution; SANE_Int y_resolution; SANE_Int tl_x; SANE_Int tl_y; /* info for 1-pass vs. 3-pass */ int this_pass; SANE_Bool onepasscolor; SANE_Bool threepasscolor; int fd; /* SCSI filedescriptor */ /* scanner dependent/low-level state: */ ARTEC_Device *hw; } ARTEC_Scanner; #endif /* artec_h */ sane-backends-1.0.27/backend/hs2p-saneopts.h0000664000175000017500000003225013106201017015461 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Jeremy Johnson This file is part of a SANE backend for Ricoh IS450 and IS420 family of HS2P Scanners using the SCSI controller. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #define SANE_NAME_INQUIRY "inquiry" #define SANE_TITLE_INQUIRY "Inquiry Data" #define SANE_DESC_INQUIRY "Displays scanner inquiry data" #define SANE_TITLE_SCAN_MODE_GROUP "Scan Mode" #define SANE_TITLE_GEOMETRY_GROUP "Geometry" #define SANE_TITLE_FEEDER_GROUP "Feeder" #define SANE_TITLE_ENHANCEMENT_GROUP "Enhancement" #define SANE_TITLE_ICON_GROUP "Icon" #define SANE_TITLE_BARCODE_GROUP "Barcode" #define SANE_TITLE_MISCELLANEOUS_GROUP "Miscellaneous" #define SANE_NAME_AUTOBORDER "autoborder" #define SANE_TITLE_AUTOBORDER "Autoborder" #define SANE_DESC_AUTOBORDER "Enable Automatic Border Detection" #define SANE_NAME_COMPRESSION "compression" #define SANE_TITLE_COMPRESSION "Data Compression" #define SANE_DESC_COMPRESSION "Sets the compression mode of the scanner" #define SANE_NAME_ROTATION "rotation" #define SANE_TITLE_ROTATION "Page Rotation" #define SANE_DESC_ROTATION "Sets the page rotation mode of the scanner" #define SANE_NAME_DESKEW "deskew" #define SANE_TITLE_DESKEW "Page Deskew" #define SANE_DESC_DESKEW "Enable Deskew Mode" #define SANE_NAME_TIMEOUT_ADF "timeout-adf" #define SANE_TITLE_TIMEOUT_ADF "ADF Timeout" #define SANE_DESC_TIMEOUT_ADF "Sets the timeout in seconds for the ADF" #define SANE_NAME_TIMEOUT_MANUAL "timeout-manual" #define SANE_TITLE_TIMEOUT_MANUAL "Manual Timeout" #define SANE_DESC_TIMEOUT_MANUAL "Sets the timeout in seconds for manual feeder" #define SANE_NAME_BATCH "batch" #define SANE_TITLE_BATCH "Batch" #define SANE_DESC_BATCH "Enable Batch Mode" #define SANE_NAME_CHECK_ADF "check-adf" #define SANE_TITLE_CHECK_ADF "Check ADF" #define SANE_DESC_CHECK_ADF "Check ADF Status prior to starting scan" #define SANE_NAME_PREFEED "prefeed" #define SANE_TITLE_PREFEED "Prefeed" #define SANE_DESC_PREFEED "Prefeed" #define SANE_NAME_DUPLEX "duplex" #define SANE_TITLE_DUPLEX "Duplex" #define SANE_DESC_DUPLEX "Enable Duplex (Dual-Sided) Scanning" #define SANE_NAME_ENDORSER "endorser" #define SANE_TITLE_ENDORSER "Endorser" #define SANE_DESC_ENDORSER "Print up to 19 character string on each sheet" #define SANE_NAME_ENDORSER_STRING "endorser-string" #define SANE_TITLE_ENDORSER_STRING "Endorser String" #define SANE_DESC_ENDORSER_STRING "valid characters: [0-9][ :#`'-./][A-Z][a-z]" #define SANE_NAME_BARCODE_SEARCH_COUNT "barcode-search-count" #define SANE_TITLE_BARCODE_SEARCH_COUNT "Barcode Search Count" #define SANE_DESC_BARCODE_SEARCH_COUNT "Number of barcodes to search for in the scanned image" #define SANE_NAME_BARCODE_HMIN "barcode-hmin" #define SANE_TITLE_BARCODE_HMIN "Barcode Minimum Height" #define SANE_DESC_BARCODE_HMIN "Sets the Barcode Minimum Height (larger values increase recognition speed)" #define SANE_NAME_BARCODE_SEARCH_MODE "barcode-search-mode" #define SANE_TITLE_BARCODE_SEARCH_MODE "Barcode Search Mode" #define SANE_DESC_BARCODE_SEARCH_MODE "Chooses the orientation of barcodes to be searched" #define SANE_NAME_BARCODE_SEARCH_TIMEOUT "barcode-search-timeout" #define SANE_TITLE_BARCODE_SEARCH_TIMEOUT "Barcode Search Timeout" #define SANE_DESC_BARCODE_SEARCH_TIMEOUT "Sets the timeout for barcode searching" #define SANE_NAME_BARCODE_SEARCH_BAR "barcode-search-bar" #define SANE_TITLE_BARCODE_SEARCH_BAR "Barcode Search Bar" #define SANE_DESC_BARCODE_SEARCH_BAR "Specifies the barcode type to search for" #define SANE_NAME_SECTION "section" #define SANE_TITLE_SECTION "Image/Barcode Search Sections" #define SANE_DESC_SECTION "Specifies an image section and/or a barcode search region" #define SANE_NAME_BARCODE_RELMAX "barcode-relmax" #define SANE_TITLE_BARCODE_RELMAX "Barcode RelMax" #define SANE_DESC_BARCODE_RELMAX "Specifies the maximum relation from the widest to the smallest bar" #define SANE_NAME_BARCODE_BARMIN "barcode-barmin" #define SANE_TITLE_BARCODE_BARMIN "Barcode Bar Minimum" #define SANE_DESC_BARCODE_BARMIN "Specifies the minimum number of bars in Bar/Patch code" #define SANE_NAME_BARCODE_BARMAX "barcode-barmax" #define SANE_TITLE_BARCODE_BARMAX "Barcode Bar Maximum" #define SANE_DESC_BARCODE_BARMAX "Specifies the maximum number of bars in a Bar/Patch code" #define SANE_NAME_BARCODE_CONTRAST "barcode-contrast" #define SANE_TITLE_BARCODE_CONTRAST "Barcode Contrast" #define SANE_DESC_BARCODE_CONTRAST "Specifies the image contrast used in decoding. Use higher values when " \ "there are more white pixels in the code" #define SANE_NAME_BARCODE_PATCHMODE "barcode-patchmode" #define SANE_TITLE_BARCODE_PATCHMODE "Barcode Patch Mode" #define SANE_DESC_BARCODE_PATCHMODE "Controls Patch Code detection." #define SANE_NAME_SCAN_WAIT_MODE "scan-wait-mode" #define SANE_TITLE_SCAN_WAIT_MODE "Scan Wait Mode " #define SANE_DESC_SCAN_WAIT_MODE "Enables the scanner's start button" #define SANE_NAME_ACE_FUNCTION "ace-function" #define SANE_TITLE_ACE_FUNCTION "ACE Function" #define SANE_DESC_ACE_FUNCTION "ACE Function" #define SANE_NAME_ACE_SENSITIVITY "ace-sensitivity" #define SANE_TITLE_ACE_SENSITIVITY "ACE Sensitivity" #define SANE_DESC_ACE_SENSITIVITY "ACE Sensitivity" #define SANE_NAME_ICON_WIDTH "icon-width" #define SANE_TITLE_ICON_WIDTH "Icon Width" #define SANE_DESC_ICON_WIDTH "Width of icon (thumbnail) image in pixels" #define SANE_NAME_ICON_LENGTH "icon-length" #define SANE_TITLE_ICON_LENGTH "Icon Length" #define SANE_DESC_ICON_LENGTH "Length of icon (thumbnail) image in pixels" #define SANE_NAME_ORIENTATION "orientation" #define SANE_TITLE_ORIENTATION "Paper Orientation" #define SANE_DESC_ORIENTATION "[Portrait]/Landscape" \ #define SANE_NAME_PAPER_SIZE "paper-size" #define SANE_TITLE_PAPER_SIZE "Paper Size" #define SANE_DESC_PAPER_SIZE "Specify the scan window geometry by specifying the paper size " \ "of the documents to be scanned" #define SANE_NAME_PADDING "padding" #define SANE_TITLE_PADDING "Padding" #define SANE_DESC_PADDING "Pad if media length is less than requested" #define SANE_NAME_AUTO_SIZE "auto-size" #define SANE_TITLE_AUTO_SIZE "Auto Size" #define SANE_DESC_AUTO_SIZE "Automatic Paper Size Determination" #define SANE_NAME_BINARYFILTER "binary-filter" #define SANE_TITLE_BINARYFILTER "Binary Filter" #define SANE_DESC_BINARYFILTER "Binary Filter" #define SANE_NAME_SMOOTHING "smoothing" #define SANE_TITLE_SMOOTHING "Smoothing" #define SANE_DESC_SMOOTHING "Binary Smoothing Filter" #define SANE_NAME_NOISEREMOVAL "noise-removal" #define SANE_TITLE_NOISEREMOVAL "Noise Removal" #define SANE_DESC_NOISEREMOVAL "Binary Noise Removal Filter" #define SANE_NAME_NOISEMATRIX "noise-removal-matrix" #define SANE_TITLE_NOISEMATRIX "Noise Removal Matrix" #define SANE_DESC_NOISEMATRIX "Noise Removal Matrix" #define SANE_NAME_GRAYFILTER "gray-filter" #define SANE_TITLE_GRAYFILTER "Gray Filter" #define SANE_DESC_GRAYFILTER "Gray Filter" #define SANE_NAME_HALFTONE_CODE "halftone-type" #define SANE_TITLE_HALFTONE_CODE "Halftone Type" #define SANE_DESC_HALFTONE_CODE "Dither or Error Diffusion" /* #define SANE_NAME_HALFTONE_PATTERN "pattern" #define SANE_TITLE_HALFTONE_PATTERN "Pattern" #define SANE_DESC_HALFTONE_PATTERN "10 built-in halftone patterns + 2 user patterns" */ #define SANE_NAME_ERRORDIFFUSION "error-diffusion" #define SANE_TITLE_ERRORDIFFUSION "Error Diffusion" #define SANE_DESC_ERRORDIFFUSION "Useful for documents with both text and images" /* #define SANE_NAME_HALFTONE "halftone" #define SANE_TITLE_HALFTONE "Halftone" #define SANE_DESC_HALFTONE "Choose a dither pattern or error diffusion" #define SANE_NAME_NEGATIVE "negative image" #define SANE_TITLE_NEGATIVE "Negative Image" #define SANE_DESC_NEGATIVE "Reverse Image Format" #define SANE_NAME_BRIGHTNESS "brightness" #define SANE_TITLE_BRIGHTNESS "Brightness" #define SANE_DESC_BRIGHTNESS "Brightness" #define SANE_NAME_THRESHOLD "threshold" #define SANE_TITLE_THRESHOLD "Threshold" #define SANE_DESC_THRESHOLD "Threshold" */ #define SANE_NAME_GAMMA "gamma" #define SANE_TITLE_GAMMA "Gamma" #define SANE_DESC_GAMMA "Gamma Correction" #define SANE_NAME_AUTOSEP "auto-separation" #define SANE_TITLE_AUTOSEP "Automatic Separation" #define SANE_DESC_AUTOSEP "Automatic Separation" #define SANE_NAME_AUTOBIN "auto-binarization" #define SANE_TITLE_AUTOBIN "Automatic Binarization" #define SANE_DESC_AUTOBIN "Automatic Binarization" #define SANE_NAME_WHITE_BALANCE "white-balance" #define SANE_TITLE_WHITE_BALANCE "White Balance" #define SANE_DESC_WHITE_BALANCE "White Balance" #define SANE_NAME_PADDING_TYPE "padding-type" #define SANE_TITLE_PADDING_TYPE "Padding Type" #define SANE_DESC_PADDING_TYPE "Padding Type" #define SANE_NAME_BITORDER "bit-order" #define SANE_TITLE_BITORDER "Bit Order" #define SANE_DESC_BITORDER "Bit Order" #define SANE_NAME_SELF_DIAGNOSTICS "self-diagnostics" #define SANE_TITLE_SELF_DIAGNOSTICS "Self Diagnostics" #define SANE_DESC_SELF_DIAGNOSTICS "Self Diagnostics" #define SANE_NAME_OPTICAL_ADJUSTMENT "optical-adjustment" #define SANE_TITLE_OPTICAL_ADJUSTMENT "Optical Adjustment" #define SANE_DESC_OPTICAL_ADJUSTMENT "Optical Adjustment" typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_INQUIRY, /* inquiry string */ OPT_PREVIEW, OPT_SCAN_MODE, /* scan mode */ OPT_RESOLUTION, OPT_X_RESOLUTION, OPT_Y_RESOLUTION, OPT_COMPRESSION, /* hardware compression */ OPT_GEOMETRY_GROUP, /*OPT_AUTOBORDER, automatic border detection */ /*OPT_ROTATION, hardware rotation */ /*OPT_DESKEW, hardware deskew */ OPT_PAGE_ORIENTATION, /* portrait, landscape */ OPT_PAPER_SIZE, /* paper size */ OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_PADDING, /* Pad to requested length */ OPT_AUTO_SIZE, /* Automatic Size Recognition */ OPT_FEEDER_GROUP, OPT_SCAN_SOURCE, /* scan source (eg. Flatbed, ADF) */ OPT_DUPLEX, /* scan both sides of the page */ OPT_SCAN_WAIT_MODE, /* Enables the scanner's Start Button */ OPT_PREFEED, OPT_ENDORSER, /* Endorser (off,on) */ OPT_ENDORSER_STRING, /* Endorser String */ /*OPT_BATCH, scan in batch mode */ /*OPT_TIMEOUT_MANUAL, timeout in seconds with manual feed */ /*OPT_TIMEOUT_ADF, timeout in seconds with ADF */ /*OPT_CHECK_ADF, check for page in ADF before scanning */ OPT_ENHANCEMENT_GROUP, /* OPT_ACE_FUNCTION, OPT_ACE_SENSITIVITY, */ OPT_BRIGHTNESS, /* Brightness */ OPT_THRESHOLD, /* Threshold */ OPT_CONTRAST, /* Contrast */ OPT_NEGATIVE, /* Negative (reverse image) */ OPT_GAMMA, /* Gamma Correction */ OPT_CUSTOM_GAMMA, OPT_GAMMA_VECTOR_GRAY, OPT_HALFTONE_CODE, /* Halftone Code */ OPT_HALFTONE_PATTERN, /* Halftone Pattern */ OPT_GRAYFILTER, /* MRIF */ OPT_SMOOTHING, /* Smoothing */ OPT_NOISEREMOVAL, /* Noise Removal */ OPT_AUTOSEP, /* Auto Separation */ OPT_AUTOBIN, /* Auto Binarization */ OPT_WHITE_BALANCE, OPT_MISCELLANEOUS_GROUP, OPT_PADDING_TYPE, /*OPT_BITORDER, */ OPT_SELF_DIAGNOSTICS, OPT_OPTICAL_ADJUSTMENT, /* OPT_PARITION_FUNCTION OPT_SECTION */ OPT_DATA_GROUP, OPT_UPDATE, OPT_NREGX_ADF, OPT_NREGY_ADF, OPT_NREGX_BOOK, OPT_NREGY_BOOK, OPT_NSCANS_ADF, OPT_NSCANS_BOOK, OPT_LAMP_TIME, OPT_EO_ODD, OPT_EO_EVEN, OPT_BLACK_LEVEL_ODD, OPT_BLACK_LEVEL_EVEN, OPT_WHITE_LEVEL_ODD, OPT_WHITE_LEVEL_EVEN, OPT_DENSITY, OPT_FIRST_ADJ_WHITE_ODD, OPT_FIRST_ADJ_WHITE_EVEN, OPT_NREGX_REVERSE, OPT_NREGY_REVERSE, OPT_NSCANS_REVERSE_ADF, OPT_REVERSE_TIME, OPT_NCHARS, NUM_OPTIONS /* must come last: */ } HS2P_Option; sane-backends-1.0.27/backend/matsushita.conf.in0000664000175000017500000000123212112021330016226 00000000000000# # Panasonic / Matsushita scanners scsi "K.M.E. " "KV-SS25A " scsi "K.M.E. " "KV-SS55EX " scsi "K.M.E. " "KV-S2025C " scsi "K.M.E. " "KV-S2045C " scsi "K.M.E. " "KV-S2065L " # These scanners are untested. # If you have one: # - check that the vendor/product strings are correct # - uncomment the line # - test with a frontend (xscanimage, xsane, ...) #scsi "K.M.E. " "KV-SS25 " #scsi "K.M.E. " "KV-SS25D " #scsi "K.M.E. " "KV-SS50 " #scsi "K.M.E. " "KV-SS55 " #scsi "K.M.E. " "KV-SS50EX " #scsi "K.M.E. " "KV-SS850 " #scsi "K.M.E. " "KV-SS855 " /dev/scanner sane-backends-1.0.27/backend/mustek_pp.c0000664000175000017500000014632212775312261015002 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2003 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek PP flatbed scanners. */ #include "../include/sane/config.h" #if defined(HAVE_STDLIB_H) # include #endif #include #include #include #include #include #if defined(HAVE_STRING_H) # include #elif defined(HAVE_STRINGS_H) # include #endif #if defined(HAVE_UNISTD_H) # include #endif #include #include #include #if defined(HAVE_SYS_TIME_H) # include #endif #if defined(HAVE_SYS_TYPES_H) # include #endif #include #define BACKEND_NAME mustek_pp #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #define MUSTEK_PP_CONFIG_FILE "mustek_pp.conf" #include "../include/sane/sanei_pa4s2.h" #include "mustek_pp.h" #include "mustek_pp_drivers.h" #define MIN(a,b) ((a) < (b) ? (a) : (b)) /* converts millimeter to pixels at a given resolution */ #define MM_TO_PIXEL(mm, dpi) (((float )mm * 5.0 / 127.0) * (float)dpi) /* and back */ #define PIXEL_TO_MM(pixel, dpi) (((float )pixel / (float )dpi) * 127.0 / 5.0) /* if you change the source, please set MUSTEK_PP_STATE to "devel". Do *not* * change the MUSTEK_PP_BUILD. */ #define MUSTEK_PP_BUILD 13 #define MUSTEK_PP_STATE "beta" /* auth callback... since basic user authentication is done by saned, this * callback mechanism isn't used */ SANE_Auth_Callback sane_auth; /* count of present devices */ static int num_devices = 0; /* list of present devices */ static Mustek_pp_Device *devlist = NULL; /* temporary array of configuration options used during device attachment */ static Mustek_pp_config_option *cfgoptions = NULL; static int numcfgoptions = 0; /* list of pointers to the SANE_Device structures of the Mustek_pp_Devices */ static SANE_Device **devarray = NULL; /* currently active Handles */ static Mustek_pp_Handle *first_hndl = NULL; static SANE_String_Const mustek_pp_modes[4] = {SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL}; static SANE_Word mustek_pp_modes_size = 10; static SANE_String_Const mustek_pp_speeds[6] = {"Slowest", "Slower", "Normal", "Faster", "Fastest", NULL}; static SANE_Word mustek_pp_speeds_size = 8; static SANE_Word mustek_pp_depths[5] = {4, 8, 10, 12, 16}; /* prototypes */ static void free_cfg_options(int *numoptions, Mustek_pp_config_option** options); static SANE_Status do_eof(Mustek_pp_Handle *hndl); static SANE_Status do_stop(Mustek_pp_Handle *hndl); static int reader_process (Mustek_pp_Handle * hndl, int pipe); static SANE_Status sane_attach(SANE_String_Const port, SANE_String_Const name, SANE_Int driver, SANE_Int info); static void init_options(Mustek_pp_Handle *hndl); static void attach_device(SANE_String *driver, SANE_String *name, SANE_String *port, SANE_String *option_ta); /* * Auxiliary function for freeing arrays of configuration options, */ static void free_cfg_options(int *numoptions, Mustek_pp_config_option** options) { int i; if (*numoptions) { for (i=0; i<*numoptions; ++i) { free ((*options)[i].name); free ((*options)[i].value); } free (*options); } *options = NULL; *numoptions = 0; } /* do_eof: * closes the pipeline * * ChangeLog: * * Description: * closes the pipe (read-only end) */ static SANE_Status do_eof (Mustek_pp_Handle *hndl) { if (hndl->pipe >= 0) { close (hndl->pipe); hndl->pipe = -1; } return SANE_STATUS_EOF; } /* do_stop: * ends the reader_process and stops the scanner * * ChangeLog: * * Description: * kills the reader process with a SIGTERM and cancels the scanner */ static SANE_Status do_stop(Mustek_pp_Handle *hndl) { int exit_status; do_eof (hndl); if (hndl->reader > 0) { DBG (3, "do_stop: terminating reader process\n"); kill (hndl->reader, SIGTERM); while (wait (&exit_status) != hndl->reader); DBG ((exit_status == SANE_STATUS_GOOD ? 3 : 1), "do_stop: reader_process terminated with status ``%s''\n", sane_strstatus(exit_status)); hndl->reader = 0; hndl->dev->func->stop (hndl); return exit_status; } hndl->dev->func->stop (hndl); return SANE_STATUS_GOOD; } /* sigterm_handler: * cancel scanner when receiving a SIGTERM * * ChangeLog: * * Description: * just exit... reader_process takes care that nothing bad will happen * * EDG - Jan 14, 2004: * Make sure that the parport is released again by the child process * under all circumstances, because otherwise the parent process may no * longer be able to claim it (they share the same file descriptor, and * the kernel doesn't release the child's claim because the file * descriptor isn't cleaned up). If that would happen, the lamp may stay * on and may not return to its home position, unless the scanner * frontend is restarted. * (This happens only when sanei_pa4s2 uses libieee1284 AND * libieee1284 goes via /dev/parportX). * */ static int fd_to_release = 0; /*ARGSUSED*/ static void sigterm_handler (int signal __UNUSED__) { sanei_pa4s2_enable(fd_to_release, SANE_FALSE); _exit (SANE_STATUS_GOOD); } /* reader_process: * receives data from the scanner and stuff it into the pipeline * * ChangeLog: * * Description: * The signal handle for SIGTERM is initialized. * */ static int reader_process (Mustek_pp_Handle * hndl, int pipe) { sigset_t sigterm_set; struct SIGACTION act; FILE *fp; SANE_Status status; int line; int size, elem; SANE_Byte *buffer; sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); if (!(buffer = malloc (hndl->params.bytes_per_line))) return SANE_STATUS_NO_MEM; if (!(fp = fdopen(pipe, "w"))) return SANE_STATUS_IO_ERROR; fd_to_release = hndl->fd; memset (&act, 0, sizeof(act)); act.sa_handler = sigterm_handler; sigaction (SIGTERM, &act, NULL); if ((status = hndl->dev->func->start (hndl)) != SANE_STATUS_GOOD) return status; size = hndl->params.bytes_per_line; elem = 1; for (line=0; lineparams.lines ; line++) { sigprocmask (SIG_BLOCK, &sigterm_set, NULL); hndl->dev->func->read (hndl, buffer); if (getppid() == 1) { /* The parent process has died. Stop the scan (to make sure that the lamp is off and returns home). This is a safety measure to make sure that we don't break the scanner in case the frontend crashes. */ DBG (1, "reader_process: front-end died; aborting.\n"); hndl->dev->func->stop (hndl); return SANE_STATUS_CANCELLED; } sigprocmask (SIG_UNBLOCK, &sigterm_set, NULL); fwrite (buffer, size, elem, fp); } fclose (fp); free (buffer); return SANE_STATUS_GOOD; } /* sane_attach: * adds a new entry to the Mustek_pp_Device *devlist list * * ChangeLog: * * Description: * After memory for a new device entry is allocated, the * parameters for the device are determined by a call to * capabilities(). * * Afterwards the new device entry is inserted into the * devlist * */ static SANE_Status sane_attach (SANE_String_Const port, SANE_String_Const name, SANE_Int driver, SANE_Int info) { Mustek_pp_Device *dev; DBG (3, "sane_attach: attaching device ``%s'' to port %s (driver %s v%s by %s)\n", name, port, Mustek_pp_Drivers[driver].driver, Mustek_pp_Drivers[driver].version, Mustek_pp_Drivers[driver].author); if ((dev = malloc (sizeof (Mustek_pp_Device))) == NULL) { DBG (1, "sane_attach: not enough free memory\n"); return SANE_STATUS_NO_MEM; } memset (dev, 0, sizeof (Mustek_pp_Device)); memset (&dev->sane, 0, sizeof (SANE_Device)); dev->func = &Mustek_pp_Drivers[driver]; dev->sane.name = dev->name = strdup (name); dev->port = strdup (port); dev->info = info; /* Modified by EDG */ /* Transfer the options parsed from the configuration file */ dev->numcfgoptions = numcfgoptions; dev->cfgoptions = cfgoptions; numcfgoptions = 0; cfgoptions = NULL; dev->func->capabilities (info, &dev->model, &dev->vendor, &dev->type, &dev->maxres, &dev->minres, &dev->maxhsize, &dev->maxvsize, &dev->caps); dev->sane.model = dev->model; dev->sane.vendor = dev->vendor; dev->sane.type = dev->type; dev->next = devlist; devlist = dev; num_devices++; return SANE_STATUS_GOOD; } /* init_options: * Sets up the option descriptors for a device * * ChangeLog: * * Description: */ static void init_options(Mustek_pp_Handle *hndl) { int i; memset (hndl->opt, 0, sizeof (hndl->opt)); memset (hndl->val, 0, sizeof (hndl->val)); for (i = 0; i < NUM_OPTIONS; ++i) { hndl->opt[i].size = sizeof (SANE_Word); hndl->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } hndl->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; hndl->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; hndl->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; hndl->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; hndl->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; hndl->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ hndl->opt[OPT_MODE_GROUP].title = "Scan Mode"; hndl->opt[OPT_MODE_GROUP].desc = ""; hndl->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; hndl->opt[OPT_MODE_GROUP].cap = 0; hndl->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; hndl->opt[OPT_MODE_GROUP].size = 0; /* scan mode */ hndl->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; hndl->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; hndl->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; hndl->opt[OPT_MODE].type = SANE_TYPE_STRING; hndl->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; hndl->opt[OPT_MODE].size = mustek_pp_modes_size; hndl->opt[OPT_MODE].constraint.string_list = mustek_pp_modes; hndl->val[OPT_MODE].s = strdup (mustek_pp_modes[2]); /* resolution */ hndl->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; hndl->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; hndl->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; hndl->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; hndl->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; hndl->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_RESOLUTION].constraint.range = &hndl->dpi_range; hndl->val[OPT_RESOLUTION].w = SANE_FIX (hndl->dev->minres); hndl->dpi_range.min = SANE_FIX (hndl->dev->minres); hndl->dpi_range.max = SANE_FIX (hndl->dev->maxres); hndl->dpi_range.quant = SANE_FIX (1); /* speed */ hndl->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; hndl->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; hndl->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; hndl->opt[OPT_SPEED].type = SANE_TYPE_STRING; hndl->opt[OPT_SPEED].size = mustek_pp_speeds_size; hndl->opt[OPT_SPEED].constraint_type = SANE_CONSTRAINT_STRING_LIST; hndl->opt[OPT_SPEED].constraint.string_list = mustek_pp_speeds; hndl->val[OPT_SPEED].s = strdup (mustek_pp_speeds[2]); if (! (hndl->dev->caps & CAP_SPEED_SELECT)) hndl->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE; /* preview */ hndl->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; hndl->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; hndl->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; hndl->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; hndl->val[OPT_PREVIEW].w = SANE_FALSE; /* gray preview */ hndl->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW; hndl->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW; hndl->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW; hndl->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL; hndl->val[OPT_GRAY_PREVIEW].w = SANE_FALSE; /* color dept */ hndl->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH; hndl->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH; hndl->opt[OPT_DEPTH].desc = "Number of bits per sample for color scans, typical values are 8 for truecolor (24bpp)" "up to 16 for far-to-many-color (48bpp)."; hndl->opt[OPT_DEPTH].type = SANE_TYPE_INT; hndl->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; hndl->opt[OPT_DEPTH].constraint.word_list = mustek_pp_depths; hndl->opt[OPT_DEPTH].unit = SANE_UNIT_BIT; hndl->opt[OPT_DEPTH].size = sizeof(SANE_Word); hndl->val[OPT_DEPTH].w = 8; if ( !(hndl->dev->caps & CAP_DEPTH)) hndl->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; /* "Geometry" group: */ hndl->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; hndl->opt[OPT_GEOMETRY_GROUP].desc = ""; hndl->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; hndl->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; hndl->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; hndl->opt[OPT_GEOMETRY_GROUP].size = 0; /* top-left x */ hndl->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; hndl->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; hndl->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; hndl->opt[OPT_TL_X].type = SANE_TYPE_FIXED; hndl->opt[OPT_TL_X].unit = SANE_UNIT_MM; hndl->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_TL_X].constraint.range = &hndl->x_range; hndl->x_range.min = SANE_FIX (0); hndl->x_range.max = SANE_FIX (PIXEL_TO_MM(hndl->dev->maxhsize,hndl->dev->maxres)); hndl->x_range.quant = 0; hndl->val[OPT_TL_X].w = hndl->x_range.min; /* top-left y */ hndl->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; hndl->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; hndl->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; hndl->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; hndl->opt[OPT_TL_Y].unit = SANE_UNIT_MM; hndl->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_TL_Y].constraint.range = &hndl->y_range; hndl->y_range.min = SANE_FIX(0); hndl->y_range.max = SANE_FIX(PIXEL_TO_MM(hndl->dev->maxvsize,hndl->dev->maxres)); hndl->y_range.quant = 0; hndl->val[OPT_TL_Y].w = hndl->y_range.min; /* bottom-right x */ hndl->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; hndl->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; hndl->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; hndl->opt[OPT_BR_X].type = SANE_TYPE_FIXED; hndl->opt[OPT_BR_X].unit = SANE_UNIT_MM; hndl->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_BR_X].constraint.range = &hndl->x_range; hndl->val[OPT_BR_X].w = hndl->x_range.max; /* bottom-right y */ hndl->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; hndl->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; hndl->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; hndl->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; hndl->opt[OPT_BR_Y].unit = SANE_UNIT_MM; hndl->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_BR_Y].constraint.range = &hndl->y_range; hndl->val[OPT_BR_Y].w = hndl->y_range.max; /* "Enhancement" group: */ hndl->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; hndl->opt[OPT_ENHANCEMENT_GROUP].desc = ""; hndl->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; hndl->opt[OPT_ENHANCEMENT_GROUP].cap = 0; hndl->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; hndl->opt[OPT_ENHANCEMENT_GROUP].size = 0; /* custom-gamma table */ hndl->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; hndl->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; hndl->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; hndl->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; hndl->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; if ( !(hndl->dev->caps & CAP_GAMMA_CORRECT)) hndl->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; /* grayscale gamma vector */ hndl->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; hndl->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; hndl->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; hndl->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; hndl->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; hndl->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); hndl->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_GAMMA_VECTOR].constraint.range = &hndl->gamma_range; hndl->val[OPT_GAMMA_VECTOR].wa = &hndl->gamma_table[0][0]; /* red gamma vector */ hndl->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; hndl->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; hndl->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; hndl->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; hndl->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; hndl->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); hndl->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_GAMMA_VECTOR_R].constraint.range = &hndl->gamma_range; hndl->val[OPT_GAMMA_VECTOR_R].wa = &hndl->gamma_table[1][0]; /* green gamma vector */ hndl->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; hndl->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; hndl->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; hndl->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; hndl->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; hndl->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); hndl->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_GAMMA_VECTOR_G].constraint.range = &hndl->gamma_range; hndl->val[OPT_GAMMA_VECTOR_G].wa = &hndl->gamma_table[2][0]; /* blue gamma vector */ hndl->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; hndl->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; hndl->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; hndl->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; hndl->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; hndl->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); hndl->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; hndl->opt[OPT_GAMMA_VECTOR_B].constraint.range = &hndl->gamma_range; hndl->val[OPT_GAMMA_VECTOR_B].wa = &hndl->gamma_table[3][0]; hndl->gamma_range.min = 0; hndl->gamma_range.max = 255; hndl->gamma_range.quant = 1; hndl->opt[OPT_INVERT].name = SANE_NAME_NEGATIVE; hndl->opt[OPT_INVERT].title = SANE_TITLE_NEGATIVE; hndl->opt[OPT_INVERT].desc = SANE_DESC_NEGATIVE; hndl->opt[OPT_INVERT].type = SANE_TYPE_BOOL; hndl->val[OPT_INVERT].w = SANE_FALSE; if (! (hndl->dev->caps & CAP_INVERT)) hndl->opt[OPT_INVERT].cap |= SANE_CAP_INACTIVE; } /* attach_device: * Attempts to attach a device to the list after parsing of a section * of the configuration file. * * ChangeLog: * * Description: * After parsing a scanner section of the config file, this function * is called to look for a driver with a matching name. When found, * this driver is called to initialize the device. */ static void attach_device(SANE_String *driver, SANE_String *name, SANE_String *port, SANE_String *option_ta) { int found = 0, driver_no, port_no; const char **ports; if (!strcmp (*port, "*")) { ports = sanei_pa4s2_devices(); DBG (3, "sanei_init: auto probing port\n"); } else { ports = malloc (sizeof(char *) * 2); ports[0] = *port; ports[1] = NULL; } for (port_no=0; ports[port_no] != NULL; port_no++) { for (driver_no=0 ; driver_no [] * * where is a arbitrary name to identify this entry * is the port where the scanner is attached to * is the name of the driver to use * * if the optional argument "option_ta" is present the driver uses special * parameters fitting for a trasparency adapter. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { FILE *fp; char config_line[1024]; const char *config_line_ptr; int line=0, driver_no; char *driver = 0, *port = 0, *name = 0, *option_ta = 0; DBG_INIT (); DBG (3, "sane-mustek_pp, version 0.%d-%s. build for SANE %s\n", MUSTEK_PP_BUILD, MUSTEK_PP_STATE, VERSION); DBG (3, "backend by Jochen Eisinger \n"); if (version_code != NULL) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, MUSTEK_PP_BUILD); sane_auth = authorize; fp = sanei_config_open (MUSTEK_PP_CONFIG_FILE); if (fp == NULL) { char driver_name[64]; const char **devices = sanei_pa4s2_devices(); int device_no; DBG (2, "sane_init: could not open configuration file\n"); for (device_no = 0; devices[device_no] != NULL; device_no++) { DBG (3, "sane_init: trying ``%s''\n", devices[device_no]); for (driver_no=0 ; driver_no [] Note that the value is optional. */ char *optname, *optval = 0; Mustek_pp_config_option *tmpoptions; config_line_ptr += 6; config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); if (!*config_line_ptr) { DBG (1, "sane_init: parse error in line %d after ``option''\n", line); continue; } config_line_ptr = sanei_config_get_string (config_line_ptr, &optname); if ((optname == NULL) || (!*optname)) { DBG (1, "sane_init: parse error in line %d after ``option''\n", line); if (optname != NULL) free (optname); continue; } config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); if (*config_line_ptr) { /* The option has a value. No need to check the value; that's up to the backend */ config_line_ptr = sanei_config_get_string (config_line_ptr, &optval); config_line_ptr = sanei_config_skip_whitespace (config_line_ptr); } if (*config_line_ptr) { DBG (1, "sane_init: parse error in line %d after " "``option %s %s''\n", line, optname, (optval == 0 ? "" : optval)); free (optname); if (optval) free (optval); continue; } if (!strcmp (optname, "no_epp")) { u_int pa4s2_options; if (name) DBG (2, "sane_init: global option found in local scope, " "executing anyway\n"); free (optname); if (optval) { DBG (1, "sane_init: unexpected value for option no_epp\n"); free (optval); continue; } DBG (3, "sane_init: disabling mode EPP\n"); sanei_pa4s2_options (&pa4s2_options, SANE_FALSE); pa4s2_options |= SANEI_PA4S2_OPT_NO_EPP; sanei_pa4s2_options (&pa4s2_options, SANE_TRUE); continue; } else if (!name) { DBG (1, "sane_init: parse error in line %d: unexpected " " ``option''\n", line); free (optname); if (optval) free (optval); continue; } /* Extend the (global) array of options */ tmpoptions = realloc(cfgoptions, (numcfgoptions+1)*sizeof(cfgoptions[0])); if (!tmpoptions) { DBG (1, "sane_init: not enough memory for device options\n"); free_cfg_options(&numcfgoptions, &cfgoptions); return SANE_STATUS_NO_MEM; } cfgoptions = tmpoptions; cfgoptions[numcfgoptions].name = optname; cfgoptions[numcfgoptions].value = optval; ++numcfgoptions; } else { DBG (1, "sane_init: parse error at beginning of line %d\n", line); continue; } } /* If we hit the end of the file, we still may have to process the last driver */ if (name) attach_device(&driver, &name, &port, &option_ta); fclose(fp); return SANE_STATUS_GOOD; } /* sane_exit: * Unloads all drivers and frees allocated memory * * ChangeLog: * * Description: * All open devices are closed first. Then all registered devices * are removed. * */ void sane_exit (void) { Mustek_pp_Handle *hndl; Mustek_pp_Device *dev; if (first_hndl) DBG (3, "sane_exit: closing open devices\n"); while (first_hndl) { hndl = first_hndl; sane_close (hndl); } dev = devlist; num_devices = 0; devlist = NULL; while (dev) { free (dev->port); free (dev->name); free (dev->vendor); free (dev->model); free (dev->type); free_cfg_options (&dev->numcfgoptions, &dev->cfgoptions); dev = dev->next; } if (devarray != NULL) free (devarray); devarray = NULL; DBG (3, "sane_exit: all drivers unloaded\n"); } /* sane_get_devices: * Returns a list of registered devices * * ChangeLog: * * Description: * A possible present old device_list is removed first. A new * devarray is allocated and filled with pointers to the * SANE_Device structures of the Mustek_pp_Devices */ /*ARGSUSED*/ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only __UNUSED__) { int ctr; Mustek_pp_Device *dev; if (devarray != NULL) free (devarray); devarray = malloc ((num_devices + 1) * sizeof (devarray[0])); if (devarray == NULL) { DBG (1, "sane_get_devices: not enough memory for device list\n"); return SANE_STATUS_NO_MEM; } dev = devlist; for (ctr=0 ; ctrsane; dev = dev->next; } devarray[num_devices] = NULL; *device_list = (const SANE_Device **)devarray; return SANE_STATUS_GOOD; } /* sane_open: * opens a device and prepares it for operation * * ChangeLog: * * Description: * The device identified by ``devicename'' is looked * up in the list, or if devicename is zero, the * first device from the list is taken. * * open is called for the selected device. * * The handel is set up with default values, and the * option descriptors are initialized */ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Mustek_pp_Handle *hndl; Mustek_pp_Device *dev; SANE_Status status; int fd, i; if (devicename[0]) { dev = devlist; while (dev) { if (strcmp (dev->name, devicename) == 0) break; dev = dev->next; } if (!dev) { DBG (1, "sane_open: unknown devicename ``%s''\n", devicename); return SANE_STATUS_INVAL; } } else dev = devlist; if (!dev) { DBG (1, "sane_open: no devices present...\n"); return SANE_STATUS_INVAL; } DBG (3, "sane_open: Using device ``%s'' (driver %s v%s by %s)\n", dev->name, dev->func->driver, dev->func->version, dev->func->author); if ((hndl = malloc (sizeof (Mustek_pp_Handle))) == NULL) { DBG (1, "sane_open: not enough free memory for the handle\n"); return SANE_STATUS_NO_MEM; } if ((status = dev->func->open (dev->port, dev->caps, &fd)) != SANE_STATUS_GOOD) { DBG (1, "sane_open: could not open device (%s)\n", sane_strstatus (status)); return status; } hndl->next = first_hndl; hndl->dev = dev; hndl->fd = fd; hndl->state = STATE_IDLE; hndl->pipe = -1; init_options (hndl); dev->func->setup (hndl); /* Initialize driver-specific configuration options. This must be done after calling the setup() function because only then the driver is guaranteed to be fully initialized */ for (i = 0; inumcfgoptions; ++i) { status = dev->func->config (hndl, dev->cfgoptions[i].name, dev->cfgoptions[i].value); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: could not set option %s for device (%s)\n", dev->cfgoptions[i].name, sane_strstatus (status)); /* Question: should the initialization be aborted when an option cannot be handled ? The driver should have reasonable built-in defaults, so an illegal option value or an unknown option should not be fatal. Therefore, it's probably ok to ignore the error. */ } } first_hndl = hndl; *handle = hndl; return SANE_STATUS_GOOD; } /* sane_close: * closes a given device and frees all resources * * ChangeLog: * * Description: * The handle is searched in the list of active handles. * If it's found, the handle is removed. * * If the associated device is still scanning, the process * is cancelled. * * Then the backend makes sure, the lamp was at least * 2 seconds on. * * Afterwards the selected handel is closed */ void sane_close (SANE_Handle handle) { Mustek_pp_Handle *prev, *hndl; prev = NULL; for (hndl = first_hndl; hndl; hndl = hndl->next) { if (hndl == handle) break; prev = hndl; } if (hndl == NULL) { DBG (2, "sane_close: unknown device handle\n"); return; } if (hndl->state == STATE_SCANNING) { sane_cancel (handle); do_eof (handle); } if (prev != NULL) prev->next = hndl->next; else first_hndl = hndl->next; DBG (3, "sane_close: maybe waiting for lamp...\n"); if (hndl->lamp_on) while (time (NULL) - hndl->lamp_on < 2) sleep (1); hndl->dev->func->close (hndl); DBG (3, "sane_close: device closed\n"); free (handle); } /* sane_get_option_descriptor: * does what it says * * ChangeLog: * * Description: * */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Mustek_pp_Handle *hndl = handle; if ((unsigned) option >= NUM_OPTIONS) { DBG (2, "sane_get_option_descriptor: option %d doesn't exist\n", option); return NULL; } return hndl->opt + option; } /* sane_control_option: * Reads or writes an option * * ChangeLog: * * Desription: * If a pointer to info is given, the value is initialized to zero * while scanning options cannot be read or written. next a basic * check whether the request is valid is done. * * Depending on ``action'' the value of the option is either read * (in the first block) or written (in the second block). auto * values aren't supported. * * before a value is written, some checks are performed. Depending * on the option, that is written, other options also change * */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Mustek_pp_Handle *hndl = handle; SANE_Status status; SANE_Word w, cap; if (info) *info = 0; if (hndl->state == STATE_SCANNING) { DBG (2, "sane_control_option: device is scanning\n"); return SANE_STATUS_DEVICE_BUSY; } if ((unsigned int) option >= NUM_OPTIONS) { DBG (2, "sane_control_option: option %d doesn't exist\n", option); return SANE_STATUS_INVAL; } cap = hndl->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (2, "sane_control_option: option %d isn't active\n", option); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_PREVIEW: case OPT_GRAY_PREVIEW: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_CUSTOM_GAMMA: case OPT_INVERT: case OPT_DEPTH: *(SANE_Word *) val = hndl->val[option].w; return SANE_STATUS_GOOD; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, hndl->val[option].wa, hndl->opt[option].size); return SANE_STATUS_GOOD; /* string options: */ case OPT_MODE: case OPT_SPEED: strcpy (val, hndl->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (2, "sane_control_option: option can't be set (%s)\n", hndl->opt[option].name); return SANE_STATUS_INVAL; } status = sanei_constrain_value (hndl->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (2, "sane_control_option: constrain_value failed (%s)\n", sane_strstatus (status)); return status; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_BR_X: case OPT_TL_Y: case OPT_BR_Y: case OPT_PREVIEW: case OPT_GRAY_PREVIEW: case OPT_INVERT: case OPT_DEPTH: if (info) *info |= SANE_INFO_RELOAD_PARAMS; hndl->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (hndl->val[option].wa, val, hndl->opt[option].size); return SANE_STATUS_GOOD; /* side-effect-free string options: */ case OPT_SPEED: if (hndl->val[option].s) free (hndl->val[option].s); hndl->val[option].s = strdup (val); return SANE_STATUS_GOOD; /* options with side-effects: */ case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == hndl->val[OPT_CUSTOM_GAMMA].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; hndl->val[OPT_CUSTOM_GAMMA].w = w; if (w == SANE_TRUE) { const char *mode = hndl->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) hndl->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) { hndl->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { hndl->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; case OPT_MODE: { char *old_val = hndl->val[option].s; if (old_val) { if (strcmp (old_val, val) == 0) return SANE_STATUS_GOOD; /* no change */ free (old_val); } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; hndl->val[option].s = strdup (val); hndl->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; hndl->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; if ((hndl->dev->caps & CAP_DEPTH) && (strcmp(val, SANE_VALUE_SCAN_MODE_COLOR) == 0)) hndl->opt[OPT_DEPTH].cap &= ~SANE_CAP_INACTIVE; if (!(hndl->dev->caps & CAP_GAMMA_CORRECT)) return SANE_STATUS_GOOD; if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) != 0) hndl->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (hndl->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) hndl->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) { hndl->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; hndl->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } return SANE_STATUS_GOOD; } } } DBG (2, "sane_control_option: unknown action\n"); return SANE_STATUS_INVAL; } /* sane_get_parameters: * returns the set of parameters, that is used for the next scan * * ChangeLog: * * Description: * * First of all it is impossible to change the parameter set * while scanning. * * sane_get_parameters not only returns the parameters for * the next scan, it also sets them, i.e. converts the * options in actuall parameters. * * The following parameters are set: * * scanmode: according to the option SCANMODE, but * 24bit color, if PREVIEW is selected and * grayscale if GRAY_PREVIEW is selected * depth: the bit depth for color modes (if * supported) or 24bit by default * (ignored in bw/grayscale or if not * supported) * dpi: resolution * invert: if supported else defaults to false * gamma: if supported and selected * ta: if supported by the device * speed: selected speed (or fastest if not * supported) * scanarea: the scanarea is calculated from the * selections the user has mode. note * that the area may slightly differ from * the scanarea selected due to rounding * note also, that a scanarea of * (0,0)-(100,100) will include all pixels * where 0 <= x < 100 and 0 <= y < 100 * afterwards, all values are copied into the SANE_Parameters * structure. */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Mustek_pp_Handle *hndl = handle; char *mode; int dpi, ctr; if (hndl->state != STATE_SCANNING) { memset (&hndl->params, 0, sizeof (hndl->params)); if ((hndl->dev->caps & CAP_DEPTH) && (hndl->mode == MODE_COLOR)) hndl->depth = hndl->val[OPT_DEPTH].w; else hndl->depth = 8; dpi = (int) (SANE_UNFIX (hndl->val[OPT_RESOLUTION].w) + 0.5); hndl->res = dpi; if (hndl->dev->caps & CAP_INVERT) hndl->invert = hndl->val[OPT_INVERT].w; else hndl->invert = SANE_FALSE; if (hndl->dev->caps & CAP_TA) hndl->use_ta = SANE_TRUE; else hndl->use_ta = SANE_FALSE; if ((hndl->dev->caps & CAP_GAMMA_CORRECT) && (hndl->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE)) hndl->do_gamma = SANE_TRUE; else hndl->do_gamma = SANE_FALSE; if (hndl->dev->caps & CAP_SPEED_SELECT) { for (ctr=SPEED_SLOWEST; ctr<=SPEED_FASTEST; ctr++) if (strcmp(mustek_pp_speeds[ctr], hndl->val[OPT_SPEED].s) == 0) hndl->speed = ctr; } else hndl->speed = SPEED_NORMAL; mode = hndl->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) hndl->mode = MODE_BW; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) hndl->mode = MODE_GRAYSCALE; else hndl->mode = MODE_COLOR; if (hndl->val[OPT_PREVIEW].w == SANE_TRUE) { hndl->speed = SPEED_FASTEST; hndl->depth = 8; if (! hndl->use_ta) hndl->invert = SANE_FALSE; hndl->do_gamma = SANE_FALSE; if (hndl->val[OPT_GRAY_PREVIEW].w == SANE_TRUE) hndl->mode = MODE_GRAYSCALE; else { hndl->mode = MODE_COLOR; } } hndl->topX = MIN ((int) (MM_TO_PIXEL (SANE_UNFIX(hndl->val[OPT_TL_X].w), hndl->dev->maxres) + 0.5), hndl->dev->maxhsize); hndl->topY = MIN ((int) (MM_TO_PIXEL (SANE_UNFIX(hndl->val[OPT_TL_Y].w), hndl->dev->maxres) + 0.5), hndl->dev->maxvsize); hndl->bottomX = MIN ((int) (MM_TO_PIXEL (SANE_UNFIX(hndl->val[OPT_BR_X].w), hndl->dev->maxres) + 0.5), hndl->dev->maxhsize); hndl->bottomY = MIN ((int) (MM_TO_PIXEL (SANE_UNFIX(hndl->val[OPT_BR_Y].w), hndl->dev->maxres) + 0.5), hndl->dev->maxvsize); /* If necessary, swap the upper and lower boundaries to avoid negative distances. */ if (hndl->topX > hndl->bottomX) { SANE_Int tmp = hndl->topX; hndl->topX = hndl->bottomX; hndl->bottomX = tmp; } if (hndl->topY > hndl->bottomY) { SANE_Int tmp = hndl->topY; hndl->topY = hndl->bottomY; hndl->bottomY = tmp; } hndl->params.pixels_per_line = (hndl->bottomX - hndl->topX) * hndl->res / hndl->dev->maxres; hndl->params.bytes_per_line = hndl->params.pixels_per_line; switch (hndl->mode) { case MODE_BW: hndl->params.bytes_per_line /= 8; if ((hndl->params.pixels_per_line % 8) != 0) hndl->params.bytes_per_line++; hndl->params.depth = 1; break; case MODE_GRAYSCALE: hndl->params.depth = 8; hndl->params.format = SANE_FRAME_GRAY; break; case MODE_COLOR: hndl->params.depth = hndl->depth; hndl->params.bytes_per_line *= 3; if (hndl->depth > 8) hndl->params.bytes_per_line *= 2; hndl->params.format = SANE_FRAME_RGB; break; } hndl->params.last_frame = SANE_TRUE; hndl->params.lines = (hndl->bottomY - hndl->topY) * hndl->res / hndl->dev->maxres; } else DBG (2, "sane_get_parameters: can't set parameters while scanning\n"); if (params != NULL) *params = hndl->params; return SANE_STATUS_GOOD; } /* sane_start: * starts the scan. data aquisition will start immedially * * ChangeLog: * * Description: * */ SANE_Status sane_start (SANE_Handle handle) { Mustek_pp_Handle *hndl = handle; int pipeline[2]; if (hndl->state == STATE_SCANNING) { DBG (2, "sane_start: device is already scanning\n"); return SANE_STATUS_DEVICE_BUSY; } sane_get_parameters (hndl, NULL); if (pipe(pipeline) < 0) { DBG (1, "sane_start: could not initialize pipe (%s)\n", strerror(errno)); return SANE_STATUS_IO_ERROR; } hndl->reader = fork(); if (hndl->reader == 0) { sigset_t ignore_set; struct SIGACTION act; close (pipeline[0]); sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); sigprocmask (SIG_SETMASK, &ignore_set, NULL); memset (&act, 0, sizeof(act)); sigaction (SIGTERM, &act, NULL); _exit (reader_process (hndl, pipeline[1])); } close (pipeline[1]); hndl->pipe = pipeline[0]; hndl->state = STATE_SCANNING; return SANE_STATUS_GOOD; } /* sane_read: * receives data from pipeline and passes it to the caller * * ChangeLog: * * Description: * ditto */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Mustek_pp_Handle *hndl = handle; SANE_Int nread; if (hndl->state == STATE_CANCELLED) { DBG (2, "sane_read: device already cancelled\n"); do_eof (hndl); hndl->state = STATE_IDLE; return SANE_STATUS_CANCELLED; } if (hndl->state != STATE_SCANNING) { DBG (1, "sane_read: device isn't scanning\n"); return SANE_STATUS_INVAL; } *len = nread = 0; while (*len < max_len) { nread = read(hndl->pipe, buf + *len, max_len - *len); if (hndl->state == STATE_CANCELLED) { *len = 0; DBG(3, "sane_read: scan was cancelled\n"); do_eof (hndl); hndl->state = STATE_IDLE; return SANE_STATUS_CANCELLED; } if (nread < 0) { if (errno == EAGAIN) { if (*len == 0) DBG(3, "sane_read: no data at the moment\n"); else DBG(3, "sane_read: %d bytes read\n", *len); return SANE_STATUS_GOOD; } else { DBG(1, "sane_read: IO error (%s)\n", strerror(errno)); hndl->state = STATE_IDLE; do_stop(hndl); do_eof (hndl); *len = 0; return SANE_STATUS_IO_ERROR; } } *len += nread; if (nread == 0) { if (*len == 0) { DBG (3, "sane_read: read finished\n"); do_stop(hndl); hndl->state = STATE_IDLE; return do_eof(hndl); } DBG(3, "sane_read: read last buffer of %d bytes\n", *len); return SANE_STATUS_GOOD; } } DBG(3, "sane_read: read full buffer of %d bytes\n", *len); return SANE_STATUS_GOOD; } /* sane_cancel: * stops a scan and ends the reader process * * ChangeLog: * * Description: * */ void sane_cancel (SANE_Handle handle) { Mustek_pp_Handle *hndl = handle; if (hndl->state != STATE_SCANNING) return; hndl->state = STATE_CANCELLED; do_stop (hndl); } /* sane_set_io_mode: * toggles between blocking and non-blocking reading * * ChangeLog: * * Description: * */ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Mustek_pp_Handle *hndl=handle; if (hndl->state != STATE_SCANNING) return SANE_STATUS_INVAL; if (fcntl (hndl->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { DBG(1, "sane_set_io_mode: can't set io mode\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* sane_get_select_fd: * returns the pipeline fd for direct reading * * ChangeLog: * * Description: * to allow the frontend to receive the data directly it * can read from the pipeline itself */ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Mustek_pp_Handle *hndl=handle; if (hndl->state != STATE_SCANNING) return SANE_STATUS_INVAL; *fd = hndl->pipe; return SANE_STATUS_GOOD; } /* include drivers */ #include "mustek_pp_decl.h" #include "mustek_pp_null.c" #include "mustek_pp_cis.h" #include "mustek_pp_cis.c" #include "mustek_pp_ccd300.h" #include "mustek_pp_ccd300.c" sane-backends-1.0.27/backend/agfafocus.conf.in0000664000175000017500000000001612112021330016001 00000000000000/dev/scanner sane-backends-1.0.27/backend/plustek-usb.c0000664000175000017500000012327312112021330015224 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usb.c * @brief The interface functions to the USB driver stuff. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2007 Gerhard Jaeger * * History: * - 0.40 - starting version of the USB support * - 0.41 - removed CHECK * - added Canon to the manufacturer list * - 0.42 - added warmup stuff * - added setmap function * - changed detection stuff, so we first check whether * - the vendor and product Ids match with the ones in our list * - 0.43 - cleanup * - 0.44 - changes to integration CIS based devices * - 0.45 - added skipFine assignment * - added auto device name detection if only product and vendor id
* has been specified * - made 16-bit gray mode work * - added special handling for Genius devices * - added TPA autodetection for EPSON Photo * - fixed bug that causes warmup each time autodetected
* TPA on EPSON is used * - removed Genius from PCB-Id check * - added Compaq to the list * - removed the scaler stuff for CIS devices * - removed homeing stuff from readline function * - fixed flag setting in usbDev_startScan() * - 0.46 - added additional branch to support alternate calibration * - 0.47 - added special handling with 0x400 vendor ID and model override * - removed PATH_MAX * - change usbDev_stopScan and usbDev_open prototype * - cleanup * - 0.48 - added function usb_CheckAndCopyAdjs() * - 0.49 - changed autodetection * - added support for LiDE25 (pid 0x2220) * - 0.50 - minor fix for startup reset * removed unnecessary calls to usbio_ResetLM983x() * 1200DPI CIS devices don't use GrayFromColor any longer * - 0.51 - added Syscan to the vendor list * - added SCANFLAG_Calibration handling * - 0.52 - added _WAF_LOFF_ON_START and _WAF_INC_DARKTGT * handling in usbDev_startScan() * added Visioneer * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /** useful for description tables */ typedef struct { int id; char *desc; char *desc_alt; } TabDef, *pTabDef; /** to allow different vendors... */ static TabDef usbVendors[] = { { 0x07B3, "Plustek", NULL }, { 0x0400, "NSC", "Mustek" }, { 0x0458, "KYE/Genius", NULL }, { 0x03F0, "Hewlett-Packard", NULL }, { 0x04B8, "Epson", NULL }, { 0x04A7, "Visioneer", NULL }, { 0x04A9, "Canon", NULL }, { 0x1606, "UMAX", NULL }, { 0x049F, "Compaq", NULL }, { 0x0A82, "Syscan", NULL }, { 0x0A53, "PandP Co., Ltd.", NULL }, { 0xFFFF, NULL, NULL } }; /** we use at least 8 megs for scanning... */ #define _SCANBUF_SIZE (8 * 1024 * 1024) /********************** the USB scanner interface ****************************/ /** remove the slash out of the model-name to obtain a valid filename */ static SANE_Bool usb_normFileName( char *fname, char* buffer, u_long max_len ) { char *src, *dst; if( NULL == fname ) return SANE_FALSE; if( strlen( fname ) >= max_len ) return SANE_FALSE; src = fname; dst = buffer; while( *src != '\0' ) { if((*src == '/') || isspace(*src) || ispunct(*src)) *dst = '_'; else *dst = *src; dst++; src++; } *dst = '\0'; return SANE_TRUE; } /** do some range checking and copy the adjustment values from the * frontend to our internal structures, so that the backend can take * care of them. */ static void usb_CheckAndCopyAdjs( Plustek_Device *dev ) { if( dev->adj.lampOff >= 0 ) dev->usbDev.dwLampOnPeriod = dev->adj.lampOff; if( dev->adj.lampOffOnEnd >= 0 ) dev->usbDev.bLampOffOnEnd = dev->adj.lampOffOnEnd; if( dev->adj.skipCalibration > 0 ) dev->usbDev.Caps.workaroundFlag |= _WAF_BYPASS_CALIBRATION; if( dev->adj.skipFine > 0 ) dev->usbDev.Caps.workaroundFlag |= _WAF_SKIP_FINE; if( dev->adj.skipFineWhite > 0 ) dev->usbDev.Caps.workaroundFlag |= _WAF_SKIP_WHITEFINE; if( dev->adj.incDarkTgt > 0 ) dev->usbDev.Caps.workaroundFlag |= _WAF_INC_DARKTGT; if( dev->adj.skipDarkStrip > 0 ) dev->usbDev.Caps.Normal.DarkShadOrgY = -1; if( dev->adj.invertNegatives > 0 ) dev->usbDev.Caps.workaroundFlag |= _WAF_INV_NEGATIVE_MAP; } /** * assign the values to the structures used by the currently found scanner */ static void usb_initDev( Plustek_Device *dev, int idx, int handle, int vendor ) { char *ptr; char tmp_str1[PATH_MAX]; char tmp_str2[PATH_MAX]; int i; ScanParam sParam; u_short tmp = 0; DBG( _DBG_INFO, "usb_initDev(%d,0x%04x,%i)\n", idx, vendor, dev->initialized ); /* save capability flags... */ if( dev->initialized >= 0 ) { tmp = DEVCAPSFLAG_TPA; } /* copy the original values... */ memcpy( &dev->usbDev.Caps, Settings[idx].pDevCaps, sizeof(DCapsDef)); memcpy( &dev->usbDev.HwSetting, Settings[idx].pHwDef, sizeof(HWDef)); /* restore capability flags... */ if( dev->initialized >= 0 ) { dev->usbDev.Caps.wFlags |= tmp; } usb_CheckAndCopyAdjs( dev ); DBG( _DBG_INFO, "Device WAF : 0x%08lx\n", dev->usbDev.Caps.workaroundFlag ); DBG( _DBG_INFO, "Transferrate: %lu Bytes/s\n", dev->transferRate ); /* adjust data origin */ dev->usbDev.Caps.Positive.DataOrigin.x -= dev->adj.tpa.x; dev->usbDev.Caps.Positive.DataOrigin.y -= dev->adj.tpa.y; dev->usbDev.Caps.Negative.DataOrigin.x -= dev->adj.neg.x; dev->usbDev.Caps.Negative.DataOrigin.y -= dev->adj.neg.y; dev->usbDev.Caps.Normal.DataOrigin.x -= dev->adj.pos.x; dev->usbDev.Caps.Normal.DataOrigin.y -= dev->adj.pos.y; /** adjust shading position */ if( dev->adj.posShadingY >= 0 ) dev->usbDev.Caps.Normal.ShadingOriginY = dev->adj.posShadingY; if( dev->adj.tpaShadingY >= 0 ) dev->usbDev.Caps.Positive.ShadingOriginY = dev->adj.tpaShadingY; if( dev->adj.negShadingY >= 0 ) dev->usbDev.Caps.Negative.ShadingOriginY = dev->adj.negShadingY; /* adjust the gamma settings... */ if( dev->adj.rgamma == 1.0 ) dev->adj.rgamma = dev->usbDev.HwSetting.gamma; if( dev->adj.ggamma == 1.0 ) dev->adj.ggamma = dev->usbDev.HwSetting.gamma; if( dev->adj.bgamma == 1.0 ) dev->adj.bgamma = dev->usbDev.HwSetting.gamma; if( dev->adj.graygamma == 1.0 ) dev->adj.graygamma = dev->usbDev.HwSetting.gamma; /* the following you normally get from the registry... */ bMaxITA = 0; /* Maximum integration time adjust */ dev->usbDev.ModelStr = Settings[idx].pModelString; dev->fd = handle; if( dev->initialized < 0 ) { if( usb_HasTPA( dev )) dev->usbDev.Caps.wFlags |= DEVCAPSFLAG_TPA; } DBG( _DBG_INFO, "Device Flags: 0x%08x\n", dev->usbDev.Caps.wFlags ); /* well now we patch the vendor string... * if not found, the default vendor will be Plustek */ for( i = 0; usbVendors[i].desc != NULL; i++ ) { if( usbVendors[i].id == vendor ) { dev->sane.vendor = usbVendors[i].desc; if (dev->usbDev.Caps.workaroundFlag & _WAF_USE_ALT_DESC ) if (usbVendors[i].desc_alt ) dev->sane.vendor = usbVendors[i].desc_alt; DBG( _DBG_INFO, "Vendor adjusted to: >%s<\n", dev->sane.vendor ); break; } } dev->usbDev.dwTicksLampOn = 0; dev->usbDev.currentLamp = usb_GetLampStatus( dev ); usb_ResetRegisters( dev ); if( dev->initialized >= 0 ) return; usb_IsScannerReady( dev ); sParam.bBitDepth = 8; sParam.bCalibration = PARAM_Scan; sParam.bChannels = 3; sParam.bDataType = SCANDATATYPE_Color; sParam.bSource = SOURCE_Reflection; sParam.Origin.x = 0; sParam.Origin.y = 0; sParam.UserDpi.x = 150; sParam.UserDpi.y = 150; sParam.dMCLK = 4; sParam.Size.dwPixels = 0; /* create calibration-filename */ sprintf( tmp_str2, "%s-%s", dev->sane.vendor, dev->usbDev.ModelStr ); if( !usb_normFileName( tmp_str2, tmp_str1, PATH_MAX )) { strcpy( tmp_str1, "plustek-default" ); } ptr = getenv ("HOME"); if( NULL == ptr ) { sprintf( tmp_str2, "/tmp/%s", tmp_str1 ); } else { sprintf( tmp_str2, "%s/.sane/%s", ptr, tmp_str1 ); } dev->calFile = strdup( tmp_str2 ); DBG( _DBG_INFO, "Calibration file-names set to:\n" ); DBG( _DBG_INFO, ">%s-coarse.cal<\n", dev->calFile ); DBG( _DBG_INFO, ">%s-fine.cal<\n", dev->calFile ); /* initialize the ASIC registers */ usb_SetScanParameters( dev, &sParam ); /* check and move sensor to its home position */ usb_ModuleToHome( dev, SANE_FALSE ); /* set the global flag, that we are initialized so far */ dev->initialized = idx; } /** * will be used for retrieving a Plustek device */ static int usb_CheckForPlustekDevice( int handle, Plustek_Device *dev ) { char tmp[50]; char pcbStr[10]; u_char reg59[3], reg59s[3], pcbID; int i, result; /* * Plustek uses the misc IO 12 to get the PCB ID * (PCB = printed circuit board), so it's possible to have one * product ID and up to 7 different devices... */ DBG( _DBG_INFO, "Trying to get the pcbID of a Plustek device...\n" ); /* get the PCB-ID */ result = sanei_lm983x_read( handle, 0x59, reg59s, 3, SANE_TRUE ); if( SANE_STATUS_GOOD != result ) { sanei_usb_close( handle ); return -1; } reg59[0] = 0x22; /* PIO1: Input, PIO2: Input */ reg59[1] = 0x02; /* PIO3: Input, PIO4: Output as low */ reg59[2] = 0x03; result = sanei_lm983x_write( handle, 0x59, reg59, 3, SANE_TRUE ); if( SANE_STATUS_GOOD != result ) { sanei_usb_close( handle ); return -1; } result = sanei_lm983x_read ( handle, 0x02, &pcbID, 1, SANE_TRUE ); if( SANE_STATUS_GOOD != result ) { sanei_usb_close( handle ); return -1; } pcbID = (u_char)((pcbID >> 2) & 0x07); result = sanei_lm983x_read( handle, 0x59, reg59s, 3, SANE_TRUE ); if( SANE_STATUS_GOOD != result ) { sanei_usb_close( handle ); return -1; } DBG( _DBG_INFO, "pcbID=0x%02x\n", pcbID ); /* now roam through the setting list... */ strncpy( tmp, dev->usbId, 13 ); tmp[13] = '\0'; sprintf( pcbStr, "-%u", pcbID ); strcat ( tmp, pcbStr ); DBG( _DBG_INFO, "Checking for device >%s<\n", tmp ); for( i = 0; NULL != Settings[i].pIDString; i++ ) { if( 0 == strcmp( Settings[i].pIDString, tmp )) { DBG(_DBG_INFO, "Device description for >%s< found.\n", tmp ); usb_initDev( dev, i, handle, dev->usbDev.vendor ); return handle; } } return -1; } /** * will be called upon sane_exit */ static void usbDev_shutdown( Plustek_Device *dev ) { SANE_Int handle; DBG( _DBG_INFO, "Shutdown called (dev->fd=%d, %s)\n", dev->fd, dev->sane.name ); if( NULL == dev->usbDev.ModelStr ) { DBG( _DBG_INFO, "Function ignored!\n" ); return; } if( SANE_STATUS_GOOD == sanei_usb_open( dev->sane.name, &handle )) { dev->fd = handle; DBG( _DBG_INFO, "Waiting for scanner-ready...\n" ); usb_IsScannerReady( dev ); if( 0 != dev->usbDev.bLampOffOnEnd ) { DBG( _DBG_INFO, "Switching lamp off...\n" ); usb_LampOn( dev, SANE_FALSE, SANE_FALSE ); } dev->fd = -1; sanei_usb_close( handle ); } usb_StopLampTimer( dev ); } /** * This function checks wether a device, described by a given * string(vendor and product ID), is support by this backend or not * * @param usbIdStr - sting consisting out of product and vendor ID * format: "0xVVVVx0xPPPP" VVVV = Vendor ID, PPP = Product ID * @returns; SANE_TRUE if supported, SANE_FALSE if not */ static SANE_Bool usb_IsDeviceInList( char *usbIdStr ) { int i; for( i = 0; NULL != Settings[i].pIDString; i++ ) { if( 0 == strncmp( Settings[i].pIDString, usbIdStr, 13 )) return SANE_TRUE; } return SANE_FALSE; } /** get last valid entry of a list */ static DevList* getLast( DevList *l ) { if( l == NULL ) return NULL; while( l->next != NULL ) l = l->next; return l; } /** add a new entry to our internal device list, when a device is detected */ static SANE_Status usb_attach( SANE_String_Const dev_name ) { int len; DevList *tmp, *last; /* get some memory for the entry... */ len = sizeof(DevList) + strlen(dev_name) + 1; tmp = (DevList*)malloc(len); /* initialize and set the values */ memset(tmp, 0, len ); /* the device name is part of our structure space */ tmp->dev_name = &((char*)tmp)[sizeof(DevList)]; strcpy( tmp->dev_name, dev_name ); tmp->attached = SANE_FALSE; /* root set ? */ if( usbDevs == NULL ) { usbDevs = tmp; } else { last = getLast(usbDevs); /* append... */ last->next = tmp; } return SANE_STATUS_GOOD; } /** */ static void usbGetList( DevList **devs ) { int i; SANE_Bool il; SANE_Word v, p; DevList *tmp; DBG( _DBG_INFO, "Retrieving all supported and conntected devices\n" ); for( i = 0; NULL != Settings[i].pIDString; i++ ) { v = strtol( &(Settings[i].pIDString)[0], 0, 0 ); p = strtol( &(Settings[i].pIDString)[7], 0, 0 ); /* check if this vendor- and product-ID has already been added, needed * for Plustek devices - here one product-ID is used for more than one * device type... */ il = SANE_FALSE; for( tmp = *devs; tmp ; tmp = tmp->next ) { if( tmp->device_id == p && tmp->vendor_id == v ) { il = SANE_TRUE; break; } } if( il ) { DBG( _DBG_INFO2, "Already in list: 0x%04x-0x%04x\n", v, p ); continue; } /* get the last entry... */ tmp = getLast(*devs); DBG( _DBG_INFO2, "Checking for 0x%04x-0x%04x\n", v, p ); sanei_usb_find_devices( v, p, usb_attach ); if( getLast(*devs) != tmp ) { if( tmp == NULL ) tmp = *devs; else tmp = tmp->next; while( tmp != NULL ) { tmp->vendor_id = v; tmp->device_id = p; tmp = tmp->next; } } } DBG( _DBG_INFO, "Available and supported devices:\n" ); if( *devs == NULL ) DBG( _DBG_INFO, "NONE.\n" ); for( tmp = *devs; tmp; tmp = tmp->next ) { DBG( _DBG_INFO, "Device: >%s< - 0x%04xx0x%04x\n", tmp->dev_name, tmp->vendor_id, tmp->device_id ); } } /** */ static int usbDev_open( Plustek_Device *dev, DevList *devs, int keep_lock ) { char dn[512]; char devStr[50]; int result; int i; int lc; SANE_Int handle; SANE_Byte version; SANE_Word vendor, product; SANE_Bool was_empty; SANE_Status status; DevList *tmp; DBG( _DBG_INFO, "usbDev_open(%s,%s) - %p\n", dev->name, dev->usbId, (void*)devs ); /* preset our internal usb device structure */ memset( &dev->usbDev, 0, sizeof(DeviceDef)); /* devs is NULL, when called from sane_start */ if( devs ) { dn[0] = '\0'; if( !strcmp( dev->name, "auto" )) { /* use the first "unattached"... */ for( tmp = devs; tmp; tmp = tmp->next ) { if( !tmp->attached ) { tmp->attached = SANE_TRUE; strcpy( dn, tmp->dev_name ); break; } } } else { vendor = strtol( &dev->usbId[0], 0, 0 ); product = strtol( &dev->usbId[7], 0, 0 ); /* check the first match... */ for( tmp = devs; tmp; tmp = tmp->next ) { if( tmp->vendor_id == vendor && tmp->device_id == product ) { if( !tmp->attached ) { tmp->attached = SANE_TRUE; strcpy( dn, tmp->dev_name ); break; } } } } if( !dn[0] ) { DBG( _DBG_ERROR, "No supported device found!\n" ); return -1; } status = sanei_access_lock( dn, 5 ); if( SANE_STATUS_GOOD != status ) { DBG( _DBG_ERROR, "sanei_access_lock failed: %d\n", status ); return -1; } status = sanei_usb_open( dn, &handle ); if( SANE_STATUS_GOOD != status ) { DBG( _DBG_ERROR, "sanei_usb_open failed: %s (%d)\n", strerror(errno), errno); sanei_access_unlock( dev->sane.name ); return -1; } /* replace the old devname, so we are able to have multiple * auto-detected devices */ free( dev->name ); dev->name = strdup(dn); dev->sane.name = dev->name; } else { status = sanei_access_lock( dev->sane.name, 5 ); if( SANE_STATUS_GOOD != status ) { DBG( _DBG_ERROR, "sanei_access_lock failed: %d\n", status ); return -1; } status = sanei_usb_open( dev->name, &handle ); if( SANE_STATUS_GOOD != status ) { DBG( _DBG_ERROR, "sanei_usb_open failed: %s (%d)\n", strerror(errno), errno); sanei_access_unlock( dev->sane.name ); return -1; } } was_empty = SANE_FALSE; result = sanei_usb_get_vendor_product( handle, &vendor, &product ); if( SANE_STATUS_GOOD == result ) { sprintf( devStr, "0x%04X-0x%04X", vendor, product ); DBG(_DBG_INFO,"Vendor ID=0x%04X, Product ID=0x%04X\n",vendor,product); if( dev->usbId[0] != '\0' ) { if( 0 != strcmp( dev->usbId, devStr )) { DBG( _DBG_ERROR, "Specified Vendor and Product ID " "doesn't match with the ones\n" "in the config file\n" ); sanei_access_unlock( dev->sane.name ); sanei_usb_close( handle ); return -1; } } else { sprintf( dev->usbId, "0x%04X-0x%04X", vendor, product ); was_empty = SANE_TRUE; } } else { DBG( _DBG_INFO, "Can't get vendor & product ID from driver...\n" ); /* if the ioctl stuff is not supported by the kernel and we have * nothing specified, we have to give up... */ if( dev->usbId[0] == '\0' ) { DBG( _DBG_ERROR, "Cannot autodetect Vendor an Product ID, " "please specify in config file.\n" ); sanei_access_unlock( dev->sane.name ); sanei_usb_close( handle ); return -1; } vendor = strtol( &dev->usbId[0], 0, 0 ); product = strtol( &dev->usbId[7], 0, 0 ); DBG( _DBG_INFO, "... using the specified: " "0x%04X-0x%04X\n", vendor, product ); } /* before accessing the scanner, check if supported! */ if( !usb_IsDeviceInList( dev->usbId )) { DBG( _DBG_ERROR, "Device >%s<, is not supported!\n", dev->usbId ); sanei_access_unlock( dev->sane.name ); sanei_usb_close( handle ); return -1; } status = usbio_DetectLM983x( handle, &version ); if( SANE_STATUS_GOOD != status ) { sanei_usb_close( handle ); sanei_access_unlock( dev->sane.name ); return -1; } if ((version < 3) || (version > 4)) { DBG( _DBG_ERROR, "This is not a LM9831 or LM9832 chip based scanner.\n" ); sanei_usb_close( handle ); sanei_access_unlock( dev->sane.name ); return -1; } /* need to set the handle and the detected chiptype... */ dev->fd = handle; dev->usbDev.HwSetting.chip = (version==3 ? _LM9831:_LM9832); usbio_ResetLM983x( dev ); dev->fd = -1; dev->usbDev.vendor = vendor; dev->usbDev.product = product; DBG( _DBG_INFO, "Detected vendor & product ID: " "0x%04X-0x%04X\n", vendor, product ); /* * Plustek uses the misc IO 1/2 to get the PCB ID * (PCB = printed circuit board), so it's possible to have one * product ID and up to 7 different devices... */ if( 0x07B3 == vendor ) { handle = usb_CheckForPlustekDevice( handle, dev ); if( was_empty ) dev->usbId[0] = '\0'; if( handle >= 0 ) { if( !keep_lock ) sanei_access_unlock( dev->sane.name ); return handle; } } else { /* now roam through the setting list... */ lc = 13; strncpy( devStr, dev->usbId, lc ); devStr[lc] = '\0'; if( 0x400 == vendor ) { if((dev->adj.mov < 0) || (dev->adj.mov > 1)) { DBG(_DBG_INFO, "BearPaw MOV out of range: %d\n", dev->adj.mov); dev->adj.mov = 0; } sprintf( devStr, "%s-%d", dev->usbId, dev->adj.mov ); lc = strlen(devStr); DBG( _DBG_INFO, "BearPaw device: %s (%d)\n", devStr, lc ); } if( was_empty ) dev->usbId[0] = '\0'; /* if we don't use the PCD ID extension... */ for( i = 0; NULL != Settings[i].pIDString; i++ ) { if( 0 == strncmp( Settings[i].pIDString, devStr, lc )) { DBG( _DBG_INFO, "Device description for >%s< found.\n", devStr ); usb_initDev( dev, i, handle, vendor ); if( !keep_lock ) sanei_access_unlock( dev->sane.name ); return handle; } } } sanei_access_unlock( dev->sane.name ); sanei_usb_close( handle ); DBG( _DBG_ERROR, "No matching device found >%s<\n", devStr ); return -1; } /** */ static int usbDev_close( Plustek_Device *dev ) { DBG( _DBG_INFO, "usbDev_close()\n" ); sanei_usb_close( dev->fd ); dev->fd = -1; return 0; } /** convert the stuff */ static int usbDev_getCaps( Plustek_Device *dev ) { DCapsDef *scaps = &dev->usbDev.Caps; DBG( _DBG_INFO, "usbDev_getCaps()\n" ); dev->caps.dwFlag = 0; if(((DEVCAPSFLAG_Positive & scaps->wFlags) && (DEVCAPSFLAG_Negative & scaps->wFlags)) || (DEVCAPSFLAG_TPA & scaps->wFlags)) { dev->caps.dwFlag |= SFLAG_TPA; } dev->caps.wMaxExtentX = scaps->Normal.Size.x; dev->caps.wMaxExtentY = scaps->Normal.Size.y; return 0; } /** usbDev_getCropInfo * function to set the image relevant stuff */ static int usbDev_getCropInfo( Plustek_Device *dev, CropInfo *ci ) { WinInfo size; DBG( _DBG_INFO, "usbDev_getCropInfo()\n" ); usb_GetImageInfo( dev, &ci->ImgDef, &size ); ci->dwPixelsPerLine = size.dwPixels; ci->dwLinesPerArea = size.dwLines; ci->dwBytesPerLine = size.dwBytes; if( ci->ImgDef.dwFlag & SCANFLAG_DWORDBoundary ) ci->dwBytesPerLine = (ci->dwBytesPerLine + 3UL) & 0xfffffffcUL; DBG( _DBG_INFO, "PPL = %lu\n", ci->dwPixelsPerLine ); DBG( _DBG_INFO, "LPA = %lu\n", ci->dwLinesPerArea ); DBG( _DBG_INFO, "BPL = %lu\n", ci->dwBytesPerLine ); return 0; } /** */ static int usbDev_setMap( Plustek_Device *dev, SANE_Word *map, SANE_Word length, SANE_Word channel ) { SANE_Word i, idx; DBG(_DBG_INFO,"Setting map[%u] at 0x%08lx\n",channel,(unsigned long)map); _VAR_NOT_USED( dev ); if( channel == _MAP_MASTER ) { for( i = 0; i < length; i++ ) { a_bMap[i] = (SANE_Byte)map[i]; a_bMap[length +i] = (SANE_Byte)map[i]; a_bMap[(length*2)+i] = (SANE_Byte)map[i]; } } else { idx = 0; if( channel == _MAP_GREEN ) idx = 1; if( channel == _MAP_BLUE ) idx = 2; for( i = 0; i < length; i++ ) { a_bMap[(length * idx)+i] = (SANE_Byte)map[i]; } } return 0; } /** */ static int usbDev_setScanEnv( Plustek_Device *dev, ScanInfo *si ) { ScanDef *scan = &dev->scanning; DCapsDef *caps = &dev->usbDev.Caps; DBG( _DBG_INFO, "usbDev_setScanEnv()\n" ); /* clear all the stuff */ memset( scan, 0, sizeof(ScanDef)); if((si->ImgDef.dwFlag & SCANDEF_Adf) && (si->ImgDef.dwFlag & SCANDEF_ContinuousScan)) { scan->sParam.dMCLK = dMCLK_ADF; } /* Save necessary informations */ scan->fGrayFromColor = 0; /* for some devices and settings, we tweak the physical settings * how to get the image - but not in calibration mode */ if((si->ImgDef.dwFlag & SCANFLAG_Calibration) == 0) { if( si->ImgDef.wDataType == COLOR_256GRAY ) { if( !(si->ImgDef.dwFlag & SCANDEF_Adf) && !usb_IsCISDevice(dev) && (caps->OpticDpi.x == 1200 && si->ImgDef.xyDpi.x <= 300)) { scan->fGrayFromColor = 2; si->ImgDef.wDataType = COLOR_TRUE24; DBG( _DBG_INFO, "* Gray from color set!\n" ); } if( caps->workaroundFlag & _WAF_GRAY_FROM_COLOR ) { DBG( _DBG_INFO, "* Gray(8-bit) from color set!\n" ); scan->fGrayFromColor = 2; si->ImgDef.wDataType = COLOR_TRUE24; } } else if ( si->ImgDef.wDataType == COLOR_GRAY16 ) { if( caps->workaroundFlag & _WAF_GRAY_FROM_COLOR ) { DBG( _DBG_INFO, "* Gray(16-bit) from color set!\n" ); scan->fGrayFromColor = 2; si->ImgDef.wDataType = COLOR_TRUE48; } } else if ( si->ImgDef.wDataType == COLOR_BW ) { if( caps->workaroundFlag & _WAF_BIN_FROM_COLOR ) { DBG( _DBG_INFO, "* Binary from color set!\n" ); scan->fGrayFromColor = 10; si->ImgDef.wDataType = COLOR_TRUE24; } } } usb_SaveImageInfo( dev, &si->ImgDef ); usb_GetImageInfo ( dev, &si->ImgDef, &scan->sParam.Size ); /* mask the flags */ scan->dwFlag = si->ImgDef.dwFlag & (SCANFLAG_bgr | SCANFLAG_BottomUp | SCANFLAG_Calibration | SCANFLAG_DWORDBoundary | SCANFLAG_RightAlign | SCANFLAG_StillModule | SCANDEF_Adf | SCANDEF_ContinuousScan); if( !(SCANDEF_QualityScan & si->ImgDef.dwFlag)) { DBG( _DBG_INFO, "* Preview Mode set!\n" ); } else { DBG( _DBG_INFO, "* Preview Mode NOT set!\n" ); scan->dwFlag |= SCANDEF_QualityScan; } scan->sParam.brightness = si->siBrightness; scan->sParam.contrast = si->siContrast; if( scan->sParam.bBitDepth <= 8 ) scan->dwFlag &= ~SCANFLAG_RightAlign; if( scan->dwFlag & SCANFLAG_DWORDBoundary ) { if( scan->fGrayFromColor && scan->fGrayFromColor < 10) scan->dwBytesLine = (scan->sParam.Size.dwBytes / 3 + 3) & 0xfffffffcUL; else scan->dwBytesLine = (scan->sParam.Size.dwBytes + 3UL) & 0xfffffffcUL; } else { if( scan->fGrayFromColor && scan->fGrayFromColor < 10) scan->dwBytesLine = scan->sParam.Size.dwBytes / 3; else scan->dwBytesLine = scan->sParam.Size.dwBytes; } /* on CIS based devices we have to reconfigure the illumination * settings for the gray modes */ usb_AdjustCISLampSettings( dev, SANE_TRUE ); if( scan->dwFlag & SCANFLAG_BottomUp) scan->lBufAdjust = -(long)scan->dwBytesLine; else scan->lBufAdjust = scan->dwBytesLine; /* LM9831 has a BUG in 16-bit mode, * so we generate pseudo 16-bit data from 8-bit */ if( scan->sParam.bBitDepth > 8 ) { if( _LM9831 == dev->usbDev.HwSetting.chip ) { scan->sParam.bBitDepth = 8; scan->dwFlag |= SCANFLAG_Pseudo48; scan->sParam.Size.dwBytes >>= 1; } } /* Source selection */ if( scan->sParam.bSource == SOURCE_Reflection ) { dev->usbDev.pSource = &caps->Normal; scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x + (u_long)dev->usbDev.Normal.lLeft; scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y + (u_long)dev->usbDev.Normal.lUp; } else if( scan->sParam.bSource == SOURCE_Transparency ) { dev->usbDev.pSource = &caps->Positive; scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x + (u_long)dev->usbDev.Positive.lLeft; scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y + (u_long)dev->usbDev.Positive.lUp; } else if( scan->sParam.bSource == SOURCE_Negative ) { dev->usbDev.pSource = &caps->Negative; scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x + (u_long)dev->usbDev.Negative.lLeft; scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y + (u_long)dev->usbDev.Negative.lUp; } else { dev->usbDev.pSource = &dev->usbDev.Caps.Adf; scan->sParam.Origin.x += dev->usbDev.pSource->DataOrigin.x + (u_long)dev->usbDev.Normal.lLeft; scan->sParam.Origin.y += dev->usbDev.pSource->DataOrigin.y + (u_long)dev->usbDev.Normal.lUp; } if( scan->sParam.bSource == SOURCE_ADF ) { if( scan->dwFlag & SCANDEF_ContinuousScan ) dev->usbDev.fLastScanIsAdf = SANE_TRUE; else dev->usbDev.fLastScanIsAdf = SANE_FALSE; } return 0; } /** */ static int usbDev_stopScan( Plustek_Device *dev ) { DBG( _DBG_INFO, "usbDev_stopScan()\n" ); /* in cancel-mode we first stop the motor */ usb_ScanEnd( dev ); dev->scanning.dwFlag = 0; if( NULL != dev->scanning.pScanBuffer ) { free( dev->scanning.pScanBuffer ); dev->scanning.pScanBuffer = NULL; usb_StartLampTimer( dev ); } return 0; } /** */ static int usbDev_startScan( Plustek_Device *dev ) { ScanDef *scan = &dev->scanning; DBG( _DBG_INFO, "usbDev_startScan()\n" ); /* HEINER: Preview currently not working correctly */ #if 0 if( scan->dwFlag & SCANDEF_QualityScan ) dev->usbDev.a_bRegs[0x0a] = 0; else dev->usbDev.a_bRegs[0x0a] = 1; #endif dev->usbDev.a_bRegs[0x0a] = 0; if((scan->dwFlag & SCANDEF_Adf) && (scan->dwFlag & SCANDEF_ContinuousScan)) { scan->fCalibrated = SANE_TRUE; } else { scan->fCalibrated = SANE_FALSE; } scan->sParam.PhyDpi.x = usb_SetAsicDpiX(dev,scan->sParam.UserDpi.x); scan->sParam.PhyDpi.y = usb_SetAsicDpiY(dev,scan->sParam.UserDpi.y); /* Allocate shading/scan buffer */ scan->pScanBuffer = (u_long*)malloc( _SCANBUF_SIZE ); if( scan->pScanBuffer == NULL ) return _E_ALLOC; scan->dwFlag |= SCANFLAG_StartScan; /* some devices (esp. BearPaw) do need a lamp switch off before * switching it on again. Otherwise it might happen that the lamp * remains off */ if(dev->usbDev.Caps.workaroundFlag & _WAF_LOFF_ON_START) { if (usb_GetLampStatus(dev)) usb_LampOn( dev, SANE_FALSE, SANE_TRUE ); } usb_LampOn( dev, SANE_TRUE, SANE_TRUE ); m_fStart = m_fFirst = SANE_TRUE; m_fAutoPark = (scan->dwFlag&SCANFLAG_StillModule)?SANE_FALSE:SANE_TRUE; if( usb_IsSheetFedDevice(dev)) if(usb_InCalibrationMode(dev)) m_fAutoPark = SANE_FALSE; usb_StopLampTimer( dev ); return 0; } /** * do the reading stuff here... * first we perform the calibration step, and then we read the image * line for line */ static int usbDev_Prepare( Plustek_Device *dev, SANE_Byte *buf ) { int result; SANE_Bool use_alt_cal = SANE_FALSE; ScanDef *scan = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; DBG( _DBG_INFO, "usbDev_PrepareScan()\n" ); /* check the current position of the sensor and move it back * to it's home position if necessary... */ if( !usb_IsSheetFedDevice(dev)) usb_SensorStatus( dev ); /* CIS devices need special handling... */ if( usb_IsCISDevice(dev)) { use_alt_cal = SANE_TRUE; } else { if( dev->adj.altCalibrate ) use_alt_cal = SANE_TRUE; } /* for the skip functionality use the "old" calibration functions */ if( dev->usbDev.Caps.workaroundFlag & _WAF_BYPASS_CALIBRATION ) { use_alt_cal = SANE_FALSE; } if( use_alt_cal ) { result = cano_DoCalibration( dev ); } else { result = usb_DoCalibration( dev ); } if( SANE_TRUE != result ) { DBG( _DBG_ERROR, "calibration failed!!!\n" ); return _E_ABORT; } if( dev->adj.cacheCalData ) usb_SaveCalData( dev ); DBG( _DBG_INFO, "calibration done.\n" ); if( usb_InCalibrationMode(dev)) return 0; if( !(scan->dwFlag & SCANFLAG_Scanning)) { usleep( 10 * 1000 ); /* need to preset that here, as we need it during parameter setting */ scan->bLinesToSkip = (u_char)(scan->sParam.PhyDpi.y / 50); scan->dwLinesDiscard = 0; if( scan->sParam.bChannels == 3 ) { scan->dwLinesDiscard = (u_long)scaps->bSensorDistance * scan->sParam.PhyDpi.y / scaps->OpticDpi.y; scan->dwLinesDiscard <<= 1; } if( !usb_SetScanParameters( dev, &scan->sParam )) { DBG( _DBG_ERROR, "Setting Scan Parameters failed!\n" ); return 0; } /* if we bypass the calibration step, we wait on lamp warmup here... */ if( scaps->workaroundFlag & _WAF_BYPASS_CALIBRATION ) { if( !usb_Wait4Warmup( dev )) { DBG( _DBG_INFO, "usbDev_Prepare() - Cancel detected...\n" ); return 0; } } scan->pbScanBufBegin = (u_char*)scan->pScanBuffer; if((dev->caps.dwFlag & SFLAG_ADF) && (scaps->OpticDpi.x == 600)) scan->dwLinesScanBuf = 8; else scan->dwLinesScanBuf = 32; scan->dwBytesScanBuf = scan->dwLinesScanBuf * scan->sParam.Size.dwPhyBytes; scan->dwNumberOfScanBufs = _SCANBUF_SIZE / scan->dwBytesScanBuf; scan->dwLinesPerScanBufs = scan->dwNumberOfScanBufs * scan->dwLinesScanBuf; scan->pbScanBufEnd = scan->pbScanBufBegin + scan->dwLinesPerScanBufs * scan->sParam.Size.dwPhyBytes; scan->dwRedShift = 0; scan->dwBlueShift = 0; scan->dwGreenShift = 0; /* CCD scanner */ if( scan->sParam.bChannels == 3 ) { scan->dwLinesDiscard = (u_long)scaps->bSensorDistance * scan->sParam.PhyDpi.y / scaps->OpticDpi.y; switch( scaps->bSensorOrder ) { case SENSORORDER_rgb: scan->Red.pb = scan->pbScanBufBegin; scan->Green.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes; scan->Blue.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes * 2UL; break; case SENSORORDER_rbg: scan->Red.pb = scan->pbScanBufBegin; scan->Blue.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes; scan->Green.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes * 2UL; break; case SENSORORDER_gbr: scan->Green.pb = scan->pbScanBufBegin; scan->Blue.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes; scan->Red.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes * 2UL; break; case SENSORORDER_grb: scan->Green.pb = scan->pbScanBufBegin; scan->Red.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes; scan->Blue.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes * 2UL; break; case SENSORORDER_brg: scan->Blue.pb = scan->pbScanBufBegin; scan->Red.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes; scan->Green.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes * 2UL; break; case SENSORORDER_bgr: scan->Blue.pb = scan->pbScanBufBegin; scan->Green.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes; scan->Red.pb = scan->pbScanBufBegin + scan->dwLinesDiscard * scan->sParam.Size.dwPhyBytes * 2UL; } /* double it for last channel */ scan->dwLinesDiscard <<= 1; scan->dwGreenShift = (7UL+scan->sParam.bBitDepth) >> 3; scan->Green.pb += scan->dwGreenShift; scan->Blue.pb += (scan->dwGreenShift * 2); if( scan->dwFlag & SCANFLAG_bgr) { u_char *pb = scan->Blue.pb; scan->Blue.pb = scan->Red.pb; scan->Red.pb = pb; scan->dwBlueShift = 0; scan->dwRedShift = scan->dwGreenShift << 1; } else { scan->dwRedShift = 0; scan->dwBlueShift = scan->dwGreenShift << 1; } } else { /* CIS section */ /* this might be a simple gray operation or AFE 1 channel op */ scan->dwLinesDiscard = 0; scan->Green.pb = scan->pbScanBufBegin; if(( scan->sParam.bDataType == SCANDATATYPE_Color ) && ( hw->bReg_0x26 & _ONE_CH_COLOR )) { u_char so; u_long len = scan->sParam.Size.dwPhyBytes / 3; so = scaps->bSensorOrder; if (_WAF_RESET_SO_TO_RGB & scaps->workaroundFlag) { if (scaps->bPCB != 0) { if (scan->sParam.PhyDpi.x > scaps->bPCB) { so = SENSORORDER_rgb; DBG(_DBG_INFO, "* Resetting sensororder to RGB\n"); } } } switch( so ) { case SENSORORDER_rgb: scan->Red.pb = scan->pbScanBufBegin; scan->Green.pb = scan->pbScanBufBegin + len; scan->Blue.pb = scan->pbScanBufBegin + len * 2UL; break; case SENSORORDER_gbr: scan->Green.pb = scan->pbScanBufBegin; scan->Blue.pb = scan->pbScanBufBegin + len; scan->Red.pb = scan->pbScanBufBegin + len * 2UL; break; default: DBG( _DBG_ERROR, "CIS: This bSensorOrder " "is not defined\n" ); return _E_INTERNAL; } } } /* set a funtion to process the RAW data... */ usb_GetImageProc( dev ); if( scan->sParam.bSource == SOURCE_ADF ) scan->dwFlag |= SCANFLAG_StillModule; DBG( _DBG_INFO, "* scan->dwFlag=0x%08lx\n", scan->dwFlag ); if( !usb_ScanBegin( dev, (scan->dwFlag&SCANFLAG_StillModule) ? SANE_FALSE:SANE_TRUE)) { return _E_INTERNAL; } scan->dwFlag |= SCANFLAG_Scanning; if( scan->sParam.UserDpi.y != scan->sParam.PhyDpi.y ) { if( scan->sParam.UserDpi.y < scan->sParam.PhyDpi.y ) { scan->wSumY = scan->sParam.PhyDpi.y - scan->sParam.UserDpi.y; scan->dwFlag |= SCANFLAG_SampleY; DBG( _DBG_INFO, "SampleY Flag set (%u != %u, wSumY=%u)\n", scan->sParam.UserDpi.y, scan->sParam.PhyDpi.y, scan->wSumY ); } } } dumpPicInit( &scan->sParam, "plustek-pic.raw" ); /* here the NT driver uses an extra reading thread... * as the SANE stuff already forked the driver to read data, I think * we should only read data by using a function... */ scan->dwLinesUser = scan->sParam.Size.dwLines; if( !scan->dwLinesUser ) return _E_BUFFER_TOO_SMALL; if( scan->sParam.Size.dwLines < scan->dwLinesUser ) scan->dwLinesUser = scan->sParam.Size.dwLines; scan->sParam.Size.dwLines -= scan->dwLinesUser; if( scan->dwFlag & SCANFLAG_BottomUp ) scan->UserBuf.pb = buf + (scan->dwLinesUser - 1) * scan->dwBytesLine; else scan->UserBuf.pb = buf; DBG(_DBG_INFO,"Reading the data now!\n" ); DBG(_DBG_INFO,"PhyDpi.x = %u\n", scan->sParam.PhyDpi.x ); DBG(_DBG_INFO,"PhyDpi.y = %u\n", scan->sParam.PhyDpi.y ); DBG(_DBG_INFO,"UserDpi.x = %u\n", scan->sParam.UserDpi.x ); DBG(_DBG_INFO,"UserDpi.y = %u\n", scan->sParam.UserDpi.y ); DBG(_DBG_INFO,"NumberOfScanBufs = %lu\n",scan->dwNumberOfScanBufs); DBG(_DBG_INFO,"LinesPerScanBufs = %lu\n",scan->dwLinesPerScanBufs); DBG(_DBG_INFO,"dwPhyBytes = %lu\n",scan->sParam.Size.dwPhyBytes); DBG(_DBG_INFO,"dwPhyPixels = %lu\n",scan->sParam.Size.dwPhyPixels); DBG(_DBG_INFO,"dwTotalBytes = %lu\n",scan->sParam.Size.dwTotalBytes); DBG(_DBG_INFO,"dwPixels = %lu\n",scan->sParam.Size.dwPixels); DBG(_DBG_INFO,"dwBytes = %lu\n",scan->sParam.Size.dwBytes); DBG(_DBG_INFO,"dwValidPixels = %lu\n",scan->sParam.Size.dwValidPixels); DBG(_DBG_INFO,"dwBytesScanBuf = %lu\n",scan->dwBytesScanBuf ); DBG(_DBG_INFO,"dwLinesDiscard = %lu\n",scan->dwLinesDiscard ); DBG(_DBG_INFO,"dwLinesToSkip = %u\n", scan->bLinesToSkip ); DBG(_DBG_INFO,"dwLinesUser = %lu\n",scan->dwLinesUser ); DBG(_DBG_INFO,"dwBytesLine = %lu\n",scan->dwBytesLine ); scan->pbGetDataBuf = scan->pbScanBufBegin; scan->dwLinesToProcess = usb_ReadData( dev ); if( 0 == scan->dwLinesToProcess ) return _E_DATAREAD; return 0; } /** as the name says, read one line... */ static int usbDev_ReadLine( Plustek_Device *dev ) { int wrap; u_long cur; ScanDef *scan = &dev->scanning; HWDef *hw = &dev->usbDev.HwSetting; cur = scan->dwLinesUser; /* we stay within this sample loop until one line has been processed for * the user... */ while( cur == scan->dwLinesUser ) { if( usb_IsEscPressed()) { DBG( _DBG_INFO, "readLine() - Cancel detected...\n" ); return _E_ABORT; } if( !(scan->dwFlag & SCANFLAG_SampleY)) { scan->pfnProcess( dev ); /* Adjust user buffer pointer */ scan->UserBuf.pb += scan->lBufAdjust; scan->dwLinesUser--; } else { scan->wSumY += scan->sParam.UserDpi.y; if( scan->wSumY >= scan->sParam.PhyDpi.y ) { scan->wSumY -= scan->sParam.PhyDpi.y; scan->pfnProcess( dev ); /* Adjust user buffer pointer */ scan->UserBuf.pb += scan->lBufAdjust; scan->dwLinesUser--; } } /* Adjust get buffer pointers */ wrap = 0; if( scan->sParam.bDataType == SCANDATATYPE_Color ) { scan->Red.pb += scan->sParam.Size.dwPhyBytes; if( scan->Red.pb >= scan->pbScanBufEnd ) { scan->Red.pb = scan->pbScanBufBegin + scan->dwRedShift; wrap = 1; } scan->Green.pb += scan->sParam.Size.dwPhyBytes; if( scan->Green.pb >= scan->pbScanBufEnd ) { scan->Green.pb = scan->pbScanBufBegin + scan->dwGreenShift; wrap = 1; } scan->Blue.pb += scan->sParam.Size.dwPhyBytes; if( scan->Blue.pb >= scan->pbScanBufEnd ) { scan->Blue.pb = scan->pbScanBufBegin + scan->dwBlueShift; wrap = 1; } } else { scan->Green.pb += scan->sParam.Size.dwPhyBytes; if( scan->Green.pb >= scan->pbScanBufEnd ) scan->Green.pb = scan->pbScanBufBegin + scan->dwGreenShift; } /* on any wrap-around of the get pointers in one channel mode * we have to reset them */ if( wrap ) { u_long len = scan->sParam.Size.dwPhyBytes; if( hw->bReg_0x26 & _ONE_CH_COLOR ) { if(scan->sParam.bDataType == SCANDATATYPE_Color) { len /= 3; } scan->Red.pb = scan->pbScanBufBegin; scan->Green.pb = scan->pbScanBufBegin + len; scan->Blue.pb = scan->pbScanBufBegin + len * 2UL; } } /* line processed, check if we have to get more... */ scan->dwLinesToProcess--; if( 0 == scan->dwLinesToProcess ) { scan->dwLinesToProcess = usb_ReadData( dev ); if( 0 == scan->dwLinesToProcess ) { if( usb_IsEscPressed()) return _E_ABORT; } } } return 0; } /* END PLUSTEK-USB.C ........................................................*/ sane-backends-1.0.27/backend/kvs20xx.c0000664000175000017500000002716413106201017014303 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. Copyright (C) 2010, m. allan noah */ /* Panasonic KV-S20xx USB-SCSI scanners. */ #define DEBUG_NOT_STATIC #define BUILD 2 #include "../include/sane/config.h" #include #include #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "kvs20xx.h" #include "kvs20xx_cmd.h" struct known_device { const SANE_Int id; const SANE_Device scanner; }; static const struct known_device known_devices[] = { { KV_S2025C, { "", "MATSHITA", "KV-S2025C", "sheetfed scanner" }, }, { KV_S2045C, { "", "MATSHITA", "KV-S2045C", "sheetfed scanner" }, }, { KV_S2026C, { "", "MATSHITA", "KV-S2026C", "sheetfed scanner" }, }, { KV_S2046C, { "", "MATSHITA", "KV-S2046C", "sheetfed scanner" }, }, { KV_S2028C, { "", "MATSHITA", "KV-S2028C", "sheetfed scanner" }, }, { KV_S2048C, { "", "MATSHITA", "KV-S2048C", "sheetfed scanner" }, }, }; SANE_Status sane_init (SANE_Int __sane_unused__ * version_code, SANE_Auth_Callback __sane_unused__ authorize) { DBG_INIT (); DBG (DBG_INFO, "This is panasonic kvs20xx driver\n"); *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BUILD); /* Initialize USB */ sanei_usb_init (); return SANE_STATUS_GOOD; } /* * List of available devices, allocated by sane_get_devices, released * by sane_exit() */ static SANE_Device **devlist = NULL; static unsigned curr_scan_dev = 0; void sane_exit (void) { if (devlist) { int i; for (i = 0; devlist[i]; i++) { free ((void *) devlist[i]->name); free ((void *) devlist[i]); } free ((void *) devlist); devlist = NULL; } } static SANE_Status attach (SANE_String_Const devname) { int i = 0; if (devlist) { for (; devlist[i]; i++); devlist = realloc (devlist, sizeof (SANE_Device *) * (i + 1)); if (!devlist) return SANE_STATUS_NO_MEM; } else { devlist = malloc (sizeof (SANE_Device *) * 2); if (!devlist) return SANE_STATUS_NO_MEM; } devlist[i] = malloc (sizeof (SANE_Device)); if (!devlist[i]) return SANE_STATUS_NO_MEM; memcpy (devlist[i], &known_devices[curr_scan_dev].scanner, sizeof (SANE_Device)); devlist[i]->name = strdup (devname); /* terminate device list with NULL entry: */ devlist[i + 1] = 0; DBG (DBG_INFO, "%s device attached\n", devname); return SANE_STATUS_GOOD; } /* Get device list */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { if (devlist) { int i; for (i = 0; devlist[i]; i++) { free ((void *) devlist[i]->name); free ((void *) devlist[i]); } free ((void *) devlist); devlist = NULL; } for (curr_scan_dev = 0; curr_scan_dev < sizeof (known_devices) / sizeof (known_devices[0]); curr_scan_dev++) { sanei_usb_find_devices (PANASONIC_ID, known_devices[curr_scan_dev].id, attach); } for (curr_scan_dev = 0; curr_scan_dev < sizeof (known_devices) / sizeof (known_devices[0]); curr_scan_dev++) { sanei_scsi_find_devices (known_devices[curr_scan_dev].scanner.vendor, known_devices[curr_scan_dev].scanner.model, NULL, -1, -1, -1, -1, attach); } if(device_list) *device_list = (const SANE_Device **) devlist; return SANE_STATUS_GOOD; } /* Open device, return the device handle */ SANE_Status sane_open (SANE_String_Const devname, SANE_Handle * handle) { unsigned i, j, id = 0; struct scanner *s; SANE_Int h, bus; SANE_Status st; if (!devlist) { st = sane_get_devices (NULL, 0); if (st) return st; } for (i = 0; devlist[i]; i++) { if (!strcmp (devlist[i]->name, devname)) break; } if (!devlist[i]) return SANE_STATUS_INVAL; for (j = 0; j < sizeof (known_devices) / sizeof (known_devices[0]); j++) { if (!strcmp (devlist[i]->model, known_devices[j].scanner.model)) { id = known_devices[j].id; break; } } st = sanei_usb_open (devname, &h); if (st == SANE_STATUS_ACCESS_DENIED) return st; if (st) { st = sanei_scsi_open (devname, &h, kvs20xx_sense_handler, NULL); if (st) { return st; } bus = SCSI; } else { bus = USB; st = sanei_usb_claim_interface (h, 0); if (st) { sanei_usb_close (h); return st; } } s = malloc (sizeof (struct scanner)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (struct scanner)); s->buffer = malloc (MAX_READ_DATA_SIZE + BULK_HEADER_SIZE); if (!s->buffer) return SANE_STATUS_NO_MEM; s->file = h; s->bus = bus; s->id = id; kvs20xx_init_options (s); *handle = s; for (i = 0; i < 3; i++) { st = kvs20xx_test_unit_ready (s); if (st) { if (s->bus == SCSI) { sanei_scsi_close (s->file); st = sanei_scsi_open (devname, &h, kvs20xx_sense_handler, NULL); if (st) return st; } else { sanei_usb_release_interface (s->file, 0); sanei_usb_close (s->file); st = sanei_usb_open (devname, &h); if (st) return st; st = sanei_usb_claim_interface (h, 0); if (st) { sanei_usb_close (h); return st; } } s->file = h; } else break; } if (i == 3) return SANE_STATUS_DEVICE_BUSY; st = kvs20xx_set_timeout (s, s->val[FEED_TIMEOUT].w); if (st) { sane_close (s); return st; } return SANE_STATUS_GOOD; } /* Close device */ void sane_close (SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; int i; if (s->bus == USB) { sanei_usb_release_interface (s->file, 0); sanei_usb_close (s->file); } else sanei_scsi_close (s->file); for (i = 1; i < NUM_OPTIONS; i++) { if (s->opt[i].type == SANE_TYPE_STRING && s->val[i].s) free (s->val[i].s); } if (s->data) free (s->data); free (s->buffer); free (s); } /* Get option descriptor */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS || option < 0) return NULL; return s->opt + option; } static SANE_Status wait_document (struct scanner *s) { SANE_Status st; int i; if (!strcmp ("off", s->val[MANUALFEED].s)) return kvs20xx_document_exist (s); for (i = 0; i < s->val[FEED_TIMEOUT].w; i++) { st = kvs20xx_document_exist (s); if (st != SANE_STATUS_NO_DOCS) return st; sleep (1); } return SANE_STATUS_NO_DOCS; } /* Start scanning */ SANE_Status sane_start (SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; SANE_Status st; int duplex = s->val[DUPLEX].w; if (!s->scanning) { unsigned dummy_length; st = kvs20xx_test_unit_ready (s); if (st) return st; st = wait_document (s); if (st) return st; st = kvs20xx_reset_window (s); if (st) return st; st = kvs20xx_set_window (s, SIDE_FRONT); if (st) return st; if (duplex) { st = kvs20xx_set_window (s, SIDE_BACK); if (st) return st; } st = kvs20xx_scan (s); if (st) return st; st = kvs20xx_read_picture_element (s, SIDE_FRONT, &s->params); if (st) return st; if (duplex) { st = get_adjust_data (s, &dummy_length); if (st) return st; } else { dummy_length = 0; } s->scanning = 1; s->page = 0; s->read = 0; s->side = SIDE_FRONT; sane_get_parameters (s, NULL); s->saved_dummy_size = s->dummy_size = dummy_length ? (dummy_length * s->val[RESOLUTION].w / 1200 - 1) * s->params.bytes_per_line : 0; s->side_size = s->params.lines * s->params.bytes_per_line; s->data = realloc (s->data, duplex ? s->side_size * 2 : s->side_size); if (!s->data) { s->scanning = 0; return SANE_STATUS_NO_MEM; } } if (duplex) { unsigned side = SIDE_FRONT; unsigned read, mx; if (s->side == SIDE_FRONT && s->read == s->side_size - s->dummy_size) { s->side = SIDE_BACK; s->read = s->dummy_size; s->dummy_size = 0; return SANE_STATUS_GOOD; } s->read = 0; s->dummy_size = s->saved_dummy_size; s->side = SIDE_FRONT; st = kvs20xx_document_exist (s); if (st) return st; for (mx = s->side_size * 2; !st; mx -= read, side ^= SIDE_BACK) st = kvs20xx_read_image_data (s, s->page, side, &s->data[s->side_size * 2 - mx], mx, &read); } else { unsigned read, mx; s->read = 0; st = kvs20xx_document_exist (s); if (st) return st; DBG (DBG_INFO, "start: %d\n", s->page); for (mx = s->side_size; !st; mx -= read) st = kvs20xx_read_image_data (s, s->page, SIDE_FRONT, &s->data[s->side_size - mx], mx, &read); } if (st && st != SANE_STATUS_EOF) { s->scanning = 0; return st; } s->page++; return SANE_STATUS_GOOD; } inline static void memcpy24 (u8 * dest, u8 * src, unsigned size, unsigned ls) { unsigned i; for (i = 0; i < size; i++) { dest[i * 3] = src[i]; dest[i * 3 + 1] = src[i + ls]; dest[i * 3 + 2] = src[i + 2 * ls]; } } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct scanner *s = (struct scanner *) handle; int duplex = s->val[DUPLEX].w; int color = !strcmp (s->val[MODE].s, SANE_VALUE_SCAN_MODE_COLOR); int rest = s->side_size - s->read - s->dummy_size; *len = 0; if (!s->scanning || !rest) { if (strcmp (s->val[FEEDER_MODE].s, SANE_I18N ("continuous"))) { if (!duplex || s->side == SIDE_BACK) s->scanning = 0; } return SANE_STATUS_EOF; } *len = max_len < rest ? max_len : rest; if (duplex && (s->id == KV_S2025C || s->id == KV_S2026C || s->id == KV_S2028C)) { if (color) { unsigned ls = s->params.bytes_per_line; unsigned i, a = s->side == SIDE_FRONT ? 0 : ls / 3; u8 *data; *len = (*len / ls) * ls; for (i = 0, data = s->data + s->read * 2 + a; i < *len / ls; buf += ls, data += 2 * ls, i++) memcpy24 (buf, data, ls / 3, ls * 2 / 3); } else { unsigned ls = s->params.bytes_per_line; unsigned i = s->side == SIDE_FRONT ? 0 : ls; unsigned head = ls - (s->read % ls); unsigned tail = (*len - head) % ls; unsigned lines = (*len - head) / ls; u8 *data = s->data + (s->read / ls) * ls * 2 + i + s->read % ls; assert (data <= s->data + s->side_size * 2); memcpy (buf, data, head); for (i = 0, buf += head, data += head + (head ? ls : 0); i < lines; buf += ls, data += ls * 2, i++) { assert (data <= s->data + s->side_size * 2); memcpy (buf, data, ls); } assert ((data <= s->data + s->side_size * 2) || !tail); memcpy (buf, data, tail); } s->read += *len; } else { if (color) { unsigned i, ls = s->params.bytes_per_line; u8 *data = s->data + s->read; *len = (*len / ls) * ls; for (i = 0; i < *len / ls; buf += ls, data += ls, i++) memcpy24 (buf, data, ls / 3, ls / 3); } else { memcpy (buf, s->data + s->read, *len); } s->read += *len; } return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { struct scanner *s = (struct scanner *) handle; s->scanning = 0; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ h, SANE_Bool __sane_unused__ m) { return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ * fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/genesys_gl124.h0000664000175000017500000005732112775312261015366 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2010-2016 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "genesys.h" #define REG01 0x01 #define REG01_CISSET 0x80 #define REG01_DOGENB 0x40 #define REG01_DVDSET 0x20 #define REG01_STAGGER 0x10 #define REG01_COMPENB 0x08 #define REG01_TRUEGRAY 0x04 #define REG01_SHDAREA 0x02 #define REG01_SCAN 0x01 #define REG02 0x02 #define REG02_NOTHOME 0x80 #define REG02_ACDCDIS 0x40 #define REG02_AGOHOME 0x20 #define REG02_MTRPWR 0x10 #define REG02_FASTFED 0x08 #define REG02_MTRREV 0x04 #define REG02_HOMENEG 0x02 #define REG02_LONGCURV 0x01 #define REG03 0x03 #define REG03_LAMPDOG 0x80 #define REG03_AVEENB 0x40 #define REG03_XPASEL 0x20 #define REG03_LAMPPWR 0x10 #define REG03_LAMPTIM 0x0f #define REG04 0x04 #define REG04_LINEART 0x80 #define REG04_BITSET 0x40 #define REG04_FILTER 0x30 #define REG04_AFEMOD 0x07 #define REG05 0x05 #define REG05_DPIHW 0xc0 #define REG05_DPIHW_600 0x00 #define REG05_DPIHW_1200 0x40 #define REG05_DPIHW_2400 0x80 #define REG05_DPIHW_4800 0xc0 #define REG05_MTLLAMP 0x30 #define REG05_GMMENB 0x08 #define REG05_ENB20M 0x04 #define REG05_MTLBASE 0x03 #define REG06 0x06 #define REG06_SCANMOD 0xe0 #define REG06S_SCANMOD 5 #define REG06_PWRBIT 0x10 #define REG06_GAIN4 0x08 #define REG06_OPTEST 0x07 #define REG07_LAMPSIM 0x80 #define REG08_DRAM2X 0x80 #define REG08_MPENB 0x20 #define REG08_CIS_LINE 0x10 #define REG08_IR2_ENB 0x08 #define REG08_IR1_ENB 0x04 #define REG08_ENB24M 0x01 #define REG09_MCNTSET 0xc0 #define REG09_EVEN1ST 0x20 #define REG09_BLINE1ST 0x10 #define REG09_BACKSCAN 0x08 #define REG09_OUTINV 0x04 #define REG09_SHORTTG 0x02 #define REG09S_MCNTSET 6 #define REG09S_CLKSET 4 #define REG0A 0x0a #define REG0A_SIFSEL 0xc0 #define REG0AS_SIFSEL 6 #define REG0A_SHEETFED 0x20 #define REG0A_LPWMEN 0x10 #define REG0B 0x0b #define REG0B_DRAMSEL 0x07 #define REG0B_16M 0x01 #define REG0B_64M 0x02 #define REG0B_128M 0x03 #define REG0B_256M 0x04 #define REG0B_512M 0x05 #define REG0B_1G 0x06 #define REG0B_ENBDRAM 0x08 #define REG0B_RFHDIS 0x10 #define REG0B_CLKSET 0xe0 #define REG0B_24MHZ 0x00 #define REG0B_30MHZ 0x20 #define REG0B_40MHZ 0x40 #define REG0B_48MHZ 0x60 #define REG0B_60MHZ 0x80 #define REG0D 0x0d #define REG0D_MTRP_RDY 0x80 #define REG0D_FULLSTP 0x10 #define REG0D_CLRMCNT 0x04 #define REG0D_CLRDOCJM 0x02 #define REG0D_CLRLNCNT 0x01 #define REG0F 0x0f #define REG16_CTRLHI 0x80 #define REG16_TOSHIBA 0x40 #define REG16_TGINV 0x20 #define REG16_CK1INV 0x10 #define REG16_CK2INV 0x08 #define REG16_CTRLINV 0x04 #define REG16_CKDIS 0x02 #define REG16_CTRLDIS 0x01 #define REG17_TGMODE 0xc0 #define REG17_SNRSYN 0x0f #define REG18 0x18 #define REG18_CNSET 0x80 #define REG18_DCKSEL 0x60 #define REG18_CKTOGGLE 0x10 #define REG18_CKDELAY 0x0c #define REG18_CKSEL 0x03 #define REG1A_SW2SET 0x80 #define REG1A_SW1SET 0x40 #define REG1A_MANUAL3 0x02 #define REG1A_MANUAL1 0x01 #define REG1A_CK4INV 0x08 #define REG1A_CK3INV 0x04 #define REG1A_LINECLP 0x02 #define REG1C_TBTIME 0x07 #define REG1D 0x1d #define REG1D_CK4LOW 0x80 #define REG1D_CK3LOW 0x40 #define REG1D_CK1LOW 0x20 #define REG1D_LINESEL 0x1f #define REG1DS_LINESEL 0 #define REG1E 0x1e #define REG1E_WDTIME 0xf0 #define REG1ES_WDTIME 4 #define REG1E_WDTIME 0xf0 #define REG30 0x30 #define REG31 0x31 #define REG32 0x32 #define REG32_GPIO16 0x80 #define REG32_GPIO15 0x40 #define REG32_GPIO14 0x20 #define REG32_GPIO13 0x10 #define REG32_GPIO12 0x08 #define REG32_GPIO11 0x04 #define REG32_GPIO10 0x02 #define REG32_GPIO9 0x01 #define REG33 0x33 #define REG34 0x34 #define REG35 0x35 #define REG36 0x36 #define REG37 0x37 #define REG38 0x38 #define REG39 0x39 #define REG60 0x60 #define REG60_LED4TG 0x80 #define REG60_YENB 0x40 #define REG60_YBIT 0x20 #define REG60_ACYNCNRLC 0x10 #define REG60_ENOFFSET 0x08 #define REG60_LEDADD 0x04 #define REG60_CK4ADC 0x02 #define REG60_AUTOCONF 0x01 #define REG80 0x80 #define REG81 0x81 #define REGA0 0xa0 #define REGA0_FSTPSEL 0x28 #define REGA0S_FSTPSEL 3 #define REGA0_STEPSEL 0x03 #define REGA0S_STEPSEL 0 #define REGA1 0xa1 #define REGA2 0xa2 #define REGA3 0xa3 #define REGA4 0xa4 #define REGA5 0xa5 #define REGA6 0xa6 #define REGA7 0xa7 #define REGA8 0xa8 #define REGA9 0xa9 #define REGAA 0xaa #define REGAB 0xab #define REGAC 0xac #define REGAD 0xad #define REGAE 0xae #define REGAF 0xaf #define REGB0 0xb0 #define REGB1 0xb1 #define REGB2 0xb2 #define REGB2_Z1MOD 0x1f #define REGB3 0xb3 #define REGB3_Z1MOD 0xff #define REGB4 0xb4 #define REGB4_Z1MOD 0xff #define REGB5 0xb5 #define REGB5_Z2MOD 0x1f #define REGB6 0xb6 #define REGB6_Z2MOD 0xff #define REGB7 0xb7 #define REGB7_Z2MOD 0xff #define REG100 0x100 #define REG100_DOCSNR 0x80 #define REG100_ADFSNR 0x40 #define REG100_COVERSNR 0x20 #define REG100_CHKVER 0x10 #define REG100_DOCJAM 0x08 #define REG100_HISPDFLG 0x04 #define REG100_MOTMFLG 0x02 #define REG100_DATAENB 0x01 #define REG114 0x114 #define REG115 0x115 #define REG_LINCNT 0x25 #define REG_MAXWD 0x28 #define REG_DPISET 0x2c #define REG_FEEDL 0x3d #define REG_CK1MAP 0x74 #define REG_CK3MAP 0x77 #define REG_CK4MAP 0x7a #define REG_LPERIOD 0x7d #define REG_DUMMY 0x80 #define REG_STRPIXEL 0x82 #define REG_ENDPIXEL 0x85 #define REG_EXPDMY 0x88 #define REG_EXPR 0x8a #define REG_EXPG 0x8d #define REG_EXPB 0x90 #define REG_SEGCNT 0x93 #define REG_TG0CNT 0x96 #define REG_SCANFED 0xa2 #define REG_STEPNO 0xa4 #define REG_FWDSTEP 0xa6 #define REG_BWDSTEP 0xa8 #define REG_FASTNO 0xaa #define REG_FSHDEC 0xac #define REG_FMOVNO 0xae #define REG_FMOVDEC 0xb0 #define REG_Z1MOD 0xb2 #define REG_Z2MOD 0xb5 #define REG_TRUER 0x110 #define REG_TRUEG 0x111 #define REG_TRUEB 0x112 /** * writable scanner registers */ enum { reg_0x01 = 0, reg_0x02, reg_0x03, reg_0x04, reg_0x05, reg_0x06, reg_0x07, reg_0x08, reg_0x09, reg_0x0a, reg_0x0b, reg_0x0c, reg_0x11, reg_0x12, reg_0x13, reg_0x14, reg_0x15, reg_0x16, reg_0x17, reg_0x18, reg_0x19, reg_0x1a, reg_0x1b, reg_0x1c, reg_0x1d, reg_0x1e, reg_0x1f, reg_0x20, reg_0x21, reg_0x22, reg_0x23, reg_0x24, reg_0x25, reg_0x26, reg_0x27, reg_0x28, reg_0x29, reg_0x2a, reg_0x2b, reg_0x2c, reg_0x2d, reg_0x3b, reg_0x3c, reg_0x3d, reg_0x3e, reg_0x3f, reg_0x40, reg_0x41, reg_0x42, reg_0x43, reg_0x44, reg_0x45, reg_0x46, reg_0x47, reg_0x48, reg_0x49, reg_0x4f, reg_0x52, reg_0x53, reg_0x54, reg_0x55, reg_0x56, reg_0x57, reg_0x58, reg_0x59, reg_0x5a, reg_0x5b, reg_0x5c, reg_0x5f, reg_0x60, reg_0x61, reg_0x62, reg_0x63, reg_0x64, reg_0x65, reg_0x66, reg_0x67, reg_0x68, reg_0x69, reg_0x6a, reg_0x6b, reg_0x6c, reg_0x6d, reg_0x6e, reg_0x6f, reg_0x70, reg_0x71, reg_0x72, reg_0x73, reg_0x74, reg_0x75, reg_0x76, reg_0x77, reg_0x78, reg_0x79, reg_0x7a, reg_0x7b, reg_0x7c, reg_0x7d, reg_0x7e, reg_0x7f, reg_0x80, reg_0x81, reg_0x82, reg_0x83, reg_0x84, reg_0x85, reg_0x86, reg_0x87, reg_0x88, reg_0x89, reg_0x8a, reg_0x8b, reg_0x8c, reg_0x8d, reg_0x8e, reg_0x8f, reg_0x90, reg_0x91, reg_0x92, reg_0x93, reg_0x94, reg_0x95, reg_0x96, reg_0x97, reg_0x98, reg_0x99, reg_0x9a, reg_0x9b, reg_0x9c, reg_0x9d, reg_0x9e, reg_0x9f, reg_0xa0, reg_0xa1, reg_0xa2, reg_0xa3, reg_0xa4, reg_0xa5, reg_0xa6, reg_0xa7, reg_0xa8, reg_0xa9, reg_0xaa, reg_0xab, reg_0xac, reg_0xad, reg_0xae, reg_0xaf, reg_0xb0, reg_0xb1, reg_0xb2, reg_0xb3, reg_0xb4, reg_0xb5, reg_0xb6, reg_0xb7, reg_0xb8, reg_0xbb, reg_0xbc, reg_0xbd, reg_0xbe, reg_0xc3, reg_0xc4, reg_0xc5, reg_0xc6, reg_0xc7, reg_0xc8, reg_0xc9, reg_0xca, reg_0xcb, reg_0xcc, reg_0xcd, reg_0xce, reg_0xd0, reg_0xd1, reg_0xd2, reg_0xd3, reg_0xd4, reg_0xd5, reg_0xd6, reg_0xd7, reg_0xd8, reg_0xd9, reg_0xe0, reg_0xe1, reg_0xe2, reg_0xe3, reg_0xe4, reg_0xe5, reg_0xe6, reg_0xe7, reg_0xe8, reg_0xe9, reg_0xea, reg_0xeb, reg_0xec, reg_0xed, reg_0xee, reg_0xef, reg_0xf0, reg_0xf1, reg_0xf2, reg_0xf3, reg_0xf4, reg_0xf5, reg_0xf6, reg_0xf7, reg_0xf8, reg_0xf9, reg_0xfa, reg_0xfb, reg_0xfc, reg_0xff, GENESYS_GL124_MAX_REGS }; #define SETREG(adr,val) {dev->reg[reg_##adr].address=adr;dev->reg[reg_##adr].value=val;} typedef struct { uint8_t r31; uint8_t r32; uint8_t r33; uint8_t r34; uint8_t r35; uint8_t r36; uint8_t r38; } Gpio_layout; /** @brief gpio layout * describes initial gpio settings for a given model * registers 0x31 to 0x38 */ static Gpio_layout gpios[]={ /* LiDE 110 */ { /* 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38 */ 0x9f, 0x59, 0x01, 0x80, 0x5f, 0x01, 0x00 }, /* LiDE 210 */ { 0x9f, 0x59, 0x01, 0x80, 0x5f, 0x01, 0x00 }, /* LiDE 120 */ { 0x9f, 0x53, 0x01, 0x80, 0x5f, 0x01, 0x00 }, }; typedef struct { uint8_t rd0; uint8_t rd1; uint8_t rd2; uint8_t re0; uint8_t re1; uint8_t re2; uint8_t re3; uint8_t re4; uint8_t re5; uint8_t re6; uint8_t re7; } Memory_layout; static Memory_layout layouts[]={ /* LIDE 110, 120 */ { /* 0xd0 0xd1 0xd2 */ 0x0a, 0x15, 0x20, /* 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 */ 0x00, 0xac, 0x08, 0x55, 0x08, 0x56, 0x0f, 0xff }, /* LIDE 210, 220 */ { 0x0a, 0x1f, 0x34, 0x01, 0x24, 0x08, 0x91, 0x08, 0x92, 0x0f, 0xff } }; /** @brief structure for sensor settings * this structure describes the sensor settings to use for a given * exposure. Data settings are identified by * - sensor id * - sensor hardware dpi * - half ccd mode */ typedef struct { int sensor_type; /**> sensor id */ int dpi; /**> maximum dpi for which data are valid */ int half_ccd; /**> half ccd mode */ int exposure; /**> exposure */ int ck1map; /**> CK1MAP */ int ck3map; /**> CK3MAP */ int ck4map; /**> CK4MAP */ int segcnt; /**> SEGCNT */ int tg0cnt; /**> TG0CNT */ int expdummy; /**> exposure dummy */ int expr; /**> initial red exposure */ int expg; /**> initial green exposure */ int expb; /**> initial blue exposure */ size_t *order; /**> order of sub-segments */ uint8_t reg18; /**> register 0x18 value */ uint8_t reg20; /**> register 0x20 value */ uint8_t reg61; /**> register 0x61 value */ uint8_t reg98; /**> register 0x98 value */ uint8_t reg16; /**> register 0x16 value */ uint8_t reg70; /**> register 0x70 value */ } Sensor_Profile; static size_t order_01[]={0,1}; static size_t order_0213[]={0,2,1,3}; /* *INDENT-OFF* */ /** @brief database of sensor profiles * database of sensor profiles giving for each sensor and a given resolution, the period, and timings * to setup the sensor for the scan. */ static Sensor_Profile sensors[]={ /* LiDE 110 */ {CIS_CANONLIDE110, 600, 1, 2768, 0x1e, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21, 0x00, 0x00}, {CIS_CANONLIDE110, 600, 0, 5360, 0x1e, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21, 0x00, 0x00}, {CIS_CANONLIDE110, 1200, 0, 10528, 0x1e, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22, 0x00, 0x00}, {CIS_CANONLIDE110, 2400, 0, 20864, 0x1e, 0x9f, 0x55, 5168, 163, 4679, 6839, 8401, 6859, order_0213, 0x00, 0x06, 0x20, 0x24, 0x00, 0x00}, /* LiDE 120 */ {CIS_CANONLIDE120, 600, 1, 4608, 0x0f, 0x00, 0x55, 2552, 112, 94, 894, 1044, 994, NULL , 0x00, 0x02, 0x20, 0x21, 0x15, 0x00}, {CIS_CANONLIDE120, 600, 0, 5360, 0x0f, 0x00, 0x55, 5104, 139, 94, 1644, 1994, 1844, NULL , 0x00, 0x02, 0x20, 0x21, 0x11, 0x1f}, {CIS_CANONLIDE120, 1200, 0, 10528, 0x0f, 0x00, 0x55,10208, 192, 94, 3194, 3794, 3594, NULL , 0x00, 0x02, 0x20, 0x21, 0x15, 0x1f}, {CIS_CANONLIDE120, 2400, 0, 20864, 0x0f, 0x00, 0x55,20416, 298, 94, 6244, 7544, 7094, NULL , 0x00, 0x02, 0x20, 0x21, 0x11, 0x00}, /* LiDE 210 */ {CIS_CANONLIDE210, 600, 1, 2768, 0x1e, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21, 0x00, 0x00}, {CIS_CANONLIDE210, 600, 0, 5360, 0x1e, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21, 0x00, 0x00}, {CIS_CANONLIDE210, 1200, 0, 10528, 0x1e, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22, 0x00, 0x00}, {CIS_CANONLIDE210, 2400, 0, 20864, 0x1e, 0x9f, 0x55, 5168, 163, 4679, 6839, 8401, 6859, order_0213, 0x00, 0x06, 0x20, 0x24, 0x00, 0x00}, /* LiDE 220 */ {CIS_CANONLIDE220, 600, 1, 2768, 0x0f, 0x9f, 0x55, 2584, 154, 101, 388, 574, 393, NULL , 0x00, 0x0c, 0x20, 0x21, 0x00, 0x00}, {CIS_CANONLIDE220, 600, 0, 5360, 0x0f, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, NULL , 0x00, 0x0a, 0x20, 0x21, 0x00, 0x00}, {CIS_CANONLIDE220, 1200, 0, 10528, 0x0f, 0x9f, 0x55, 5168, 163, 101, 388, 574, 393, order_01 , 0x00, 0x08, 0x20, 0x22, 0x00, 0x00}, {CIS_CANONLIDE220, 2400, 0, 20864, 0x0f, 0x9f, 0x55, 5168, 163, 4679, 6839, 8401, 6859, order_0213, 0x00, 0x06, 0x20, 0x24, 0x00, 0x00}, }; #define MOVE_DPI 200 #define MOVE_EXPOSURE 2304 /** @brief reference slope tables * slope table directly extracted from USB logs, with a 'termination' value of 0. */ static uint32_t lide210_fast[] = { 62496, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2051, 1432, 1372, 1323, 1280, 1246, 1216, 1188, 1163, 1142, 1121, 1101, 1084, 1068, 1051, 1036, 1020, 1007, 995, 983, 971, 959, 949, 938, 929, 917, 908, 900, 891, 882, 874, 866, 857, 849, 843, 835, 829, 821, 816, 808, 802, 795, 789, 784, 778, 773, 765, 760, 755, 749, 744, 739, 734, 731, 726, 721, 716, 711, 707, 702, 698, 693, 690, 685, 682, 677, 672, 669, 665, 662, 657, 654, 650, 647, 644, 639, 637, 632, 629, 626, 622, 619, 617, 614, 610, 607, 604, 601, 599, 595, 592, 589, 587, 584, 581, 579, 576, 572, 570, 567, 564, 562, 559, 557, 554, 552, 549, 547, 544, 542, 539, 538, 536, 533, 531, 529, 526, 524, 522, 519, 518, 516, 513, 511, 509, 506, 505, 503, 501, 498, 497, 495, 493, 491, 490, 487, 485, 483, 482, 480, 477, 476, 474, 472, 470, 469, 467, 465, 464, 462, 460, 458, 456, 455, 453, 451, 450, 448, 447, 445, 444, 442, 440, 439, 437, 436, 434, 433, 431, 430, 428, 427, 425, 423, 422, 420, 419, 417, 417, 415, 414, 413, 411, 410, 408, 407, 405, 404, 402, 401, 400, 399, 398, 396, 395, 393, 392, 391, 390, 389, 387, 386, 385, 383, 382, 381, 380, 379, 377, 376, 375, 374, 373, 371, 370, 369, 368, 367, 366, 364, 363, 363, 361, 360, 359, 358, 357, 356, 355, 353, 352, 352, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 335, 335, 0}; static uint32_t lide110_ok[] = { 62496, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2051, 1961, 1901, 1852, 1809, 1775, 1745, 1717, 1692, 1671, 1650, 1630, 1613, 1597, 1580, 1565, 1549, 1536, 1524, 1512, 1500, 1488, 1478, 1467, 1458, 1446, 1437, 1429, 1420, 1411, 1403, 1395, 1386, 1378, 1372, 1364, 1358, 1350, 1345, 1337, 1331, 1324, 1318, 1313, 1307, 1302, 1294, 1289, 1284, 1278, 1273, 1268, 1263, 1260, 1255, 1250, 1245, 1240, 1236, 1231, 1227, 1222, 1219, 1214, 1211, 1206, 1201, 1198, 1194, 1191, 1186, 1183, 1179, 1176, 1173, 1168, 1166, 1161, 1158, 1155, 1151, 1148, 1146, 1143, 1139, 1136, 1133, 1130, 1128, 1124, 1121, 1118, 1116, 1113, 1110, 1108, 1105, 1101, 1099, 1096, 1093, 1091, 1088, 1086, 1083, 1081, 1078, 1076, 1073, 1071, 1068, 1067, 1065, 1062, 1060, 1058, 1055, 1053, 1051, 1048, 1047, 1045, 1042, 1040, 1038, 1035, 1034, 1032, 1030, 1027, 1026, 1024, 1022, 1020, 1019, 1016, 1014, 1012, 1011, 1009, 1006, 1005, 1003, 1001, 999, 998, 996, 994, 993, 991, 989, 987, 985, 984, 982, 980, 979, 977, 976, 974, 973, 971, 969, 968, 966, 965, 963, 962, 960, 959, 957, 956, 954, 952, 951, 949, 948, 946, 946, 944, 943, 942, 940, 939, 937, 936, 934, 933, 931, 930, 929, 928, 927, 925, 924, 922, 921, 920, 919, 918, 916, 915, 914, 912, 911, 910, 909, 908, 906, 905, 904, 903, 902, 900, 899, 898, 897, 896, 895, 893, 892, 892, 890, 889, 888, 887, 886, 885, 884, 882, 881, 881, 879, 878, 877, 876, 875, 874, 873, 872, 871, 870, 869, 868, 867, 864, 857, 849, 843, 835, 829, 821, 816, 808, 802, 795, 789, 784, 778, 773, 765, 760, 755, 749, 744, 739, 734, 731, 726, 721, 716, 711, 707, 702, 698, 693, 690, 685, 682, 677, 672, 669, 665, 662, 657, 654, 650, 647, 644, 639, 637, 632, 629, 626, 622, 619, 617, 614, 610, 607, 604, 601, 599, 595, 592, 589, 587, 584, 581, 579, 576, 572, 570, 567, 564, 562, 559, 557, 554, 552, 549, 547, 544, 542, 539, 538, 536, 533, 531, 529, 526, 524, 522, 519, 518, 516, 513, 511, 509, 506, 505, 503, 501, 498, 497, 495, 493, 491, 490, 487, 485, 483, 482, 480, 477, 476, 474, 472, 470, 469, 467, 465, 464, 462, 460, 458, 456, 455, 453, 451, 450, 448, 447, 445, 444, 442, 440, 439, 437, 436, 434, 433, 431, 430, 428, 427, 425, 423, 422, 420, 419, 417, 417, 415, 414, 413, 411, 410, 408, 407, 405, 404, 402, 401, 400, 399, 398, 396, 395, 393, 392, 391, 390, 389, 387, 386, 385, 383, 382, 381, 380, 379, 377, 376, 375, 374, 373, 371, 370, 369, 368, 367, 366, 364, 363, 363, 361, 360, 359, 358, 357, 356, 355, 353, 352, 352, 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 335, 335, 0}; static uint32_t lide120_fast[] = { 62496, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 1957, 1845, 1768, 1710, 1665, 1624, 1588, 1557, 1529, 1504, 1481, 1458, 1440, 1420, 1403, 1386, 1370, 1356, 1343, 1329, 1316, 1303, 1293, 1280, 1270, 1260, 1250, 1241, 1231, 1222, 1214, 1206, 1197, 1189, 1182, 1174, 1167, 1160, 1153, 1147, 1140, 1133, 1128, 1121, 1116, 1110, 1104, 1099, 1093, 1088, 1082, 1077, 1072, 1067, 1062, 1058, 1053, 1049, 1045, 1040, 1035, 1032, 1027, 1023, 1020, 1015, 1012, 1008, 1004, 1000, 997, 993, 989, 985, 982, 979, 975, 972, 969, 966, 963, 959, 956, 953, 950, 947, 945, 942, 939, 936, 933, 930, 928, 925, 922, 920, 917, 914, 911, 909, 907, 904, 902, 899, 897, 895, 892, 890, 888, 886, 883, 881, 879, 876, 874, 872, 870, 864, 864, 0}; static uint32_t lide120_ok[] = { 62496, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2343, 2286, 2264, 2248, 2232, 2221, 2211, 2205, 2195, 2190, 2180, 2175, 2170, 2160, 2155, 2150, 2145, 2140, 2135, 2130, 2125, 2121, 2116, 2111, 2106, 2106, 2102, 2097, 2092, 2087, 2087, 2083, 2078, 2074, 2074, 2069, 2064, 2064, 2060, 2055, 2055, 2051, 2051, 2046, 2042, 2042, 2038, 2038, 2033, 2029, 2029, 2024, 2024, 2020, 2010, 2010, 670*2, 0}; static uint32_t lide110_slow[] = { 62496, 7896, 2632, 0}; static uint32_t lide120_slow[] = { 62464, 7896, 2632, 0}; static uint32_t lide110_max[] = { 62496, 31296, 10432, 0}; static uint32_t lide120_max[] = { 62592, 62592, 41728, 31296, 10432, 0}; static uint32_t lide210_max[] = { 62496, 31296, 20864, 10432, 0}; /* NEXT LPERIOD=PREVIOUS*2-192 */ /** @brief database of motor profiles * database of motor profiles, for each exposure deigned for the sensor, gives the reference slope table to use * for scan. */ static Motor_Profile motors[]={ {MOTOR_CANONLIDE110, 2768, 0, lide210_fast}, {MOTOR_CANONLIDE110, 5360, 1, lide110_ok}, {MOTOR_CANONLIDE110, 10528, 1, lide110_slow}, {MOTOR_CANONLIDE110, 20864, 2, lide110_max}, {MOTOR_CANONLIDE120, 4608, 0, lide120_fast}, {MOTOR_CANONLIDE120, 5360, 1, lide120_ok}, {MOTOR_CANONLIDE120, 10528, 2, lide120_slow}, {MOTOR_CANONLIDE120, 20864, 2, lide120_max}, {MOTOR_CANONLIDE210, 2768, 0, lide210_fast}, {MOTOR_CANONLIDE210, 5360, 1, lide110_ok}, {MOTOR_CANONLIDE210, 10528, 1, lide110_slow}, {MOTOR_CANONLIDE210, 20864, 2, lide210_max}, {0, 0, 0, NULL}, }; /* *INDENT-ON* */ GENESYS_STATIC SANE_Status gl124_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ float yres, /*dpi */ float startx, /*optical_res, from dummy_pixel+1 */ float starty, /*base_ydpi, from home! */ float pixels, float lines, unsigned int depth, unsigned int channels, int scan_method, int scan_mode, int color_filter, unsigned int flags); #ifndef UNIT_TESTING static #endif SANE_Status gl124_start_action (Genesys_Device * dev); #ifndef UNIT_TESTING static #endif SANE_Status gl124_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor); #ifndef UNIT_TESTING static #endif SANE_Status gl124_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop); #ifndef UNIT_TESTING static #endif SANE_Status gl124_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home); #ifndef UNIT_TESTING static #endif SANE_Status gl124_init (Genesys_Device * dev); #ifndef UNIT_TESTING static #endif SANE_Status gl124_send_shading_data (Genesys_Device * dev, uint8_t * data, int size); #ifndef UNIT_TESTING static #endif SANE_Status gl124_feed (Genesys_Device * dev, unsigned int steps, int reverse); GENESYS_STATIC SANE_Status gl124_stop_action (Genesys_Device * dev); GENESYS_STATIC SANE_Status gl124_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps); /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/u12-scanner.h0000664000175000017500000001651212112021330015006 00000000000000/** @file u12-scanner.h * @brief Definitions for the devices. * * Copyright (c) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - removed useless stuff * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __U12_SCANNER_H__ #define __U12_SCANNER_H__ /* definitions for the timer functions */ typedef double TimerDef; #define _MSECOND 1000 /* based on 1 us */ #define _SECOND (1000*_MSECOND) #if 1 #define _DO_UDELAY(usecs) u12io_udelay(usecs) #define _DODELAY(msecs) u12io_udelay(1000*msecs) /*{ int i; for( i = msecs; i--; ) _DO_UDELAY(1000); }*/ #else #define _DODELAY(msecs) #endif /* ModuleStates */ #define _MotorInNormalState 0 #define _MotorGoBackward 1 #define _MotorInStopState 2 #define _MotorAdvancing 3 #define _MotorAdvanced 4 /** some function types */ typedef struct u12d *pU12_Device; typedef struct svd *pShadingVarDef; typedef void (*pFnVoid)(pU12_Device); typedef void (*pFnDACOffs)(pU12_Device, pShadingVarDef, u_long); typedef void (*pFnDACDark)(pU12_Device, pShadingVarDef, u_long, u_short); typedef void (*pFnDataProcess)(pU12_Device, void*, void*, u_long); typedef SANE_Bool (*pFnBool)(pU12_Device); /* useful for RGB-values */ typedef struct { SANE_Byte Red; SANE_Byte Green; SANE_Byte Blue; } RGBByteDef; typedef struct { u_short Red; u_short Green; u_short Blue; } RGBUShortDef; typedef struct { u_long Red; u_long Green; u_long Blue; } RGBULongDef; typedef union { RGBByteDef Colors; SANE_Byte bColors[3]; } ColorByte; typedef union { RGBUShortDef Colors; u_short wColors[3]; } ColorWord; typedef union { SANE_Byte *pb; u_short *pw; u_long *pdw; RGBUShortDef *pusrgb; RGBULongDef *pulrgb; RGBByteDef *pbrgb; } DataPointer; typedef struct { union { SANE_Byte *bp; u_short *usp; u_long *ulp; } red; union { SANE_Byte *bp; u_short *usp; u_long *ulp; } green; union { SANE_Byte *bp; u_short *usp; u_long *ulp; } blue; } RBGPtrDef; typedef struct { SANE_Byte b1st; SANE_Byte b2nd; } WordVal; typedef struct { WordVal w1st; WordVal w2nd; } DWordVal; typedef union { WordVal wOverlap; DWordVal dwOverlap; u_long dwValue; u_short wValue; SANE_Byte bValue; } DataType; typedef struct { u_short exposureTime; u_short xStepTime; } ExpXStepDef; typedef struct { SANE_Byte reg; SANE_Byte val; } RegDef; /** for defining a point */ typedef struct { u_short x; u_short y; } XY; /** for defining a crop area, all is 300DPI based */ typedef struct { u_short x; /**< x-pos of top-left corner */ u_short y; /**< y-pos of top-left corner */ u_short cx; /**< width */ u_short cy; /**< height */ } CropRect; /** for defining an image */ typedef struct { u_long dwFlag; /**< i.e. image source */ CropRect crArea; /**< the image size and position */ XY xyDpi; /**< the resolution */ u_short wDataType; /**< and the data type */ } ImgDef; /** */ typedef struct { u_long dwPixelsPerLine; u_long dwBytesPerLine; u_long dwLinesPerArea; ImgDef image; } CropInfo; /** all we need for a scan */ typedef struct { u_long dwScanFlag; double xyRatio; /**< for scaling */ u_short wYSum; XY xyPhyDpi; /**< physical resolution of a scan */ u_long dwPhysBytesPerLine; u_long wPhyDataType; /**< how the scanner should scan */ u_long dwAsicPixelsPerPlane; u_long dwAsicBytesPerPlane; u_long dwAsicBytesPerLine; XY xyAppDpi; u_long dwAppLinesPerArea; u_long dwAppPixelsPerLine; u_long dwAppPhyBytesPerLine; u_long dwAppBytesPerLine; u_short wAppDataType; short siBrightness; short siContrast; CropRect crImage; } DataInfo; /** this will be our global "overkill" structure */ typedef struct { pFnDataProcess DataProcess; /* to convert RGB buffers to RGB pixels */ pFnBool DoSample; pFnBool DataRead; /* function to get data from scanner */ long lBufferAdjust; u_long dwScanOrigin; /* where to start the scan */ u_long negBegin; /* used while scanning in TPA modes */ u_long posBegin; SANE_Byte bDiscardAll; union { u_short wGreenDiscard; u_short wGreenKeep; } gd_gk; union { u_short wBlueDiscard; u_short wRedKeep; } bd_rk; u_long dpiIdx; /* index to get/set values in the table */ ExpXStepDef *negScan; /* reference to exposure/xtep table */ DataPointer p48BitBuf; /* for handling 48-bit data */ RBGPtrDef BufBegin; /* for reading/writing the scan-data */ RBGPtrDef BufEnd; RBGPtrDef BufGet; RBGPtrDef BufData; RBGPtrDef BufPut; /* motor movement stuff */ u_long dwInterval; SANE_Bool refreshState; SANE_Bool motorBackward; SANE_Byte oldScanState; SANE_Byte bRefresh; SANE_Byte bModuleState; SANE_Byte bNowScanState; /* internal FIFO management */ u_long dwMinReadFifo; u_long dwMaxReadFifo; SANE_Byte bFifoSelect; /* defines which FIFO to use */ } ScanInfo; /** structure for accessing one buffer in various ways... */ typedef struct { union { SANE_Byte *pReadBuf; SANE_Byte *pShadingMap; u_short *pShadingRam; DataPointer Buf; } b1; union { SANE_Byte *pSumBuf; RGBUShortDef *pSumRGB; } b2; DataPointer TpaBuf; } BufferDef; #endif /* guard __U12_SCANNER_H__ */ /* END U12-SCANNER.H ........................................................*/ sane-backends-1.0.27/backend/hp3900_sane.c0000664000175000017500000021335613106201017014707 00000000000000/* HP Scanjet 3900 series - SANE Backend controller Copyright (C) 2005-2009 Jonathan Bravo Lopez This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* Backend Code for SANE*/ #define HP3900_CONFIG_FILE "hp3900.conf" #define GAMMA_DEFAULT 1.0 #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_debug.h" #include "hp3900_rts8822.c" struct st_convert { SANE_Int colormode; SANE_Int depth; SANE_Int threshold; SANE_Int negative; SANE_Int real_depth; }; /* options enumerator */ typedef enum { opt_begin = 0, grp_geometry, opt_tlx, opt_tly, opt_brx, opt_bry, opt_resolution, /* gamma tables */ opt_gamma_red, opt_gamma_green, opt_gamma_blue, opt_scantype, opt_colormode, opt_depth, opt_threshold, /* debugging options */ grp_debug, opt_model, opt_negative, opt_nogamma, opt_nowshading, opt_realdepth, opt_emulategray, opt_nowarmup, opt_dbgimages, opt_reset, /* device information */ grp_info, opt_chipname, opt_chipid, opt_scancount, opt_infoupdate, /* supported buttons. RTS8822 supports up to 6 buttons */ grp_sensors, opt_button_0, opt_button_1, opt_button_2, opt_button_3, opt_button_4, opt_button_5, opt_count } EOptionIndex; /* linked list of SANE_Device structures */ typedef struct TDevListEntry { struct TDevListEntry *pNext; SANE_Device dev; char *devname; } TDevListEntry; typedef struct { char *pszVendor; char *pszName; } TScannerModel; typedef union { SANE_Word w; SANE_Word *wa; /* word array */ SANE_String s; } TOptionValue; typedef struct { SANE_Int model; SANE_Option_Descriptor aOptions[opt_count]; TOptionValue aValues[opt_count]; struct params ScanParams; /* lists */ SANE_String_Const *list_colormodes; SANE_Int *list_depths; SANE_String_Const *list_models; SANE_Int *list_resolutions; SANE_String_Const *list_sources; SANE_Word *aGammaTable[3]; /* a 16-to-16 bit color lookup table */ SANE_Range rng_gamma; /* reading image */ SANE_Byte *image; SANE_Byte *rest; SANE_Int rest_amount; SANE_Int mylin; /* convertion settings */ struct st_convert cnv; /* ranges */ SANE_Range rng_threshold; SANE_Range rng_horizontal; SANE_Range rng_vertical; SANE_Int scan_count; SANE_Int fScanning; /* TRUE if actively scanning */ } TScanner; /* functions to manage backend's options */ static void options_init (TScanner * scanner); static void options_free (TScanner * scanner); /* devices listing */ static SANE_Int _ReportDevice (TScannerModel * pModel, const char *pszDeviceName); static SANE_Status attach_one_device (SANE_String_Const devname); /* capabilities */ static SANE_Status bknd_colormodes (TScanner * scanner, SANE_Int model); static void bknd_constrains (TScanner * scanner, SANE_Int source, SANE_Int type); static SANE_Status bknd_depths (TScanner * scanner, SANE_Int model); static SANE_Status bknd_info (TScanner * scanner); static SANE_Status bknd_models (TScanner * scanner); static SANE_Status bknd_resolutions (TScanner * scanner, SANE_Int model); static SANE_Status bknd_sources (TScanner * scanner, SANE_Int model); /* convertions */ static void Color_Negative (SANE_Byte * buffer, SANE_Int size, SANE_Int depth); static void Color_to_Gray (SANE_Byte * buffer, SANE_Int size, SANE_Int depth); static void Gray_to_Lineart (SANE_Byte * buffer, SANE_Int size, SANE_Int threshold); static void Depth_16_to_8 (SANE_Byte * from_buffer, SANE_Int size, SANE_Byte * to_buffer); /* gamma functions */ static void gamma_apply (TScanner * s, SANE_Byte * buffer, SANE_Int size, SANE_Int depth); static SANE_Int gamma_create (TScanner * s, double gamma); static void gamma_free (TScanner * s); static SANE_Int Get_Colormode (SANE_String colormode); static SANE_Int Get_Model (SANE_String model); static SANE_Int Get_Source (SANE_String source); static SANE_Int GetUSB_device_model (SANE_String_Const name); static size_t max_string_size (const SANE_String_Const strings[]); static SANE_Status get_button_status (TScanner * s); /* reading buffers */ static SANE_Status img_buffers_alloc (TScanner * scanner, SANE_Int size); static SANE_Status img_buffers_free (TScanner * scanner); static SANE_Status option_get (TScanner * scanner, SANE_Int optid, void *result); static SANE_Status option_set (TScanner * scanner, SANE_Int optid, void *value, SANE_Int * pInfo); static void Set_Coordinates (SANE_Int scantype, SANE_Int resolution, struct st_coords *coords); static SANE_Int set_ScannerModel (SANE_Int proposed, SANE_Int product, SANE_Int vendor); static void Silent_Compile (void); static SANE_Status Translate_coords (struct st_coords *coords); /* SANE functions */ void sane_cancel (SANE_Handle h); void sane_close (SANE_Handle h); SANE_Status sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, void *pVal, SANE_Int * pInfo); void sane_exit (void); SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle h, SANE_Int n); SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p); SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd); SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h); SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len); SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking); SANE_Status sane_start (SANE_Handle h); /* variables */ static struct st_device *device = NULL; static TDevListEntry *_pFirstSaneDev = 0; static SANE_Int iNumSaneDev = 0; static const SANE_Device **_pSaneDevList = 0; /* Own functions */ static SANE_Status bknd_resolutions (TScanner * scanner, SANE_Int model) { SANE_Status rst = SANE_STATUS_INVAL; DBG (DBG_FNC, "> bknd_resolutions(*scanner, model=%i)\n", model); if (scanner != NULL) { SANE_Int *res = NULL; switch (model) { case BQ5550: case UA4900: { SANE_Int myres[] = { 8, 50, 75, 100, 150, 200, 300, 600, 1200 }; res = (SANE_Int *) malloc (sizeof (myres)); if (res != NULL) memcpy (res, &myres, sizeof (myres)); } break; case HPG2710: case HP3800: { /* 1200 and 2400 dpi are disabled until problems are solved */ SANE_Int myres[] = { 7, 50, 75, 100, 150, 200, 300, 600 }; res = (SANE_Int *) malloc (sizeof (myres)); if (res != NULL) memcpy (res, &myres, sizeof (myres)); } break; case HP4370: case HPG3010: case HPG3110: { SANE_Int myres[] = { 10, 50, 75, 100, 150, 200, 300, 600, 1200, 2400, 4800 }; res = (SANE_Int *) malloc (sizeof (myres)); if (res != NULL) memcpy (res, &myres, sizeof (myres)); } break; default: /* HP3970 & HP4070 & UA4900 */ { SANE_Int myres[] = { 9, 50, 75, 100, 150, 200, 300, 600, 1200, 2400 }; res = (SANE_Int *) malloc (sizeof (myres)); if (res != NULL) memcpy (res, &myres, sizeof (myres)); } break; } if (res != NULL) { if (scanner->list_resolutions != NULL) free (scanner->list_resolutions); scanner->list_resolutions = res; rst = SANE_STATUS_GOOD; } } return rst; } static SANE_Status bknd_models (TScanner * scanner) { SANE_Status rst = SANE_STATUS_INVAL; DBG (DBG_FNC, "> bknd_models:\n"); if (scanner != NULL) { SANE_String_Const *model = NULL; /* at this moment all devices use the same list */ SANE_String_Const mymodel[] = { "HP3800", "HP3970", "HP4070", "HP4370", "UA4900", "HPG3010", "BQ5550", "HPG2710", "HPG3110", 0 }; /* allocate space to save list */ model = (SANE_String_Const *) malloc (sizeof (mymodel)); if (model != NULL) memcpy (model, &mymodel, sizeof (mymodel)); if (model != NULL) { /* free previous list */ if (scanner->list_models != NULL) free (scanner->list_models); /* set new list */ scanner->list_models = model; rst = SANE_STATUS_GOOD; } } return rst; } static SANE_Status bknd_colormodes (TScanner * scanner, SANE_Int model) { SANE_Status rst = SANE_STATUS_INVAL; DBG (DBG_FNC, "> bknd_colormodes(*scanner, model=%i)\n", model); if (scanner != NULL) { SANE_String_Const *colormode = NULL; /* at this moment all devices use the same list */ SANE_String_Const mycolormode[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_LINEART, 0 }; /* silence gcc */ model = model; colormode = (SANE_String_Const *) malloc (sizeof (mycolormode)); if (colormode != NULL) memcpy (colormode, &mycolormode, sizeof (mycolormode)); if (colormode != NULL) { if (scanner->list_colormodes != NULL) free (scanner->list_colormodes); scanner->list_colormodes = colormode; rst = SANE_STATUS_GOOD; } } return rst; } static SANE_Status bknd_sources (TScanner * scanner, SANE_Int model) { SANE_Status rst = SANE_STATUS_INVAL; DBG (DBG_FNC, "> bknd_sources(*scanner, model=%i)\n", model); if (scanner != NULL) { SANE_String_Const *source = NULL; switch (model) { case UA4900: { SANE_String_Const mysource[] = { SANE_I18N ("Flatbed"), 0 }; source = (SANE_String_Const *) malloc (sizeof (mysource)); if (source != NULL) memcpy (source, &mysource, sizeof (mysource)); } break; default: /* hp3970, hp4070, hp4370 and others */ { SANE_String_Const mysource[] = { SANE_I18N ("Flatbed"), SANE_I18N ("Slide"), SANE_I18N ("Negative"), 0 }; source = (SANE_String_Const *) malloc (sizeof (mysource)); if (source != NULL) memcpy (source, &mysource, sizeof (mysource)); } break; } if (source != NULL) { if (scanner->list_sources != NULL) free (scanner->list_sources); scanner->list_sources = source; rst = SANE_STATUS_GOOD; } } return rst; } static SANE_Status bknd_depths (TScanner * scanner, SANE_Int model) { SANE_Status rst = SANE_STATUS_INVAL; DBG (DBG_FNC, "> bknd_depths(*scanner, model=%i\n", model); if (scanner != NULL) { SANE_Int *depth = NULL; /* at this moment all devices use the same list */ SANE_Int mydepth[] = { 2, 8, 16 }; /*{3, 8, 12, 16}; */ /* silence gcc */ model = model; depth = (SANE_Int *) malloc (sizeof (mydepth)); if (depth != NULL) memcpy (depth, &mydepth, sizeof (mydepth)); if (depth != NULL) { if (scanner->list_depths != NULL) free (scanner->list_depths); scanner->list_depths = depth; rst = SANE_STATUS_GOOD; } } return rst; } static SANE_Status bknd_info (TScanner * scanner) { SANE_Status rst = SANE_STATUS_INVAL; DBG (DBG_FNC, "> bknd_info(*scanner)"); if (scanner != NULL) { char data[256]; /* update chipset name */ Chipset_Name (device, data, 255); if (scanner->aValues[opt_chipname].s != NULL) { free (scanner->aValues[opt_chipname].s); scanner->aValues[opt_chipname].s = NULL; } scanner->aValues[opt_chipname].s = strdup (data); scanner->aOptions[opt_chipname].size = strlen (data) + 1; /* update chipset id */ scanner->aValues[opt_chipid].w = Chipset_ID (device); /* update scans counter */ scanner->aValues[opt_scancount].w = RTS_ScanCounter_Get (device); rst = SANE_STATUS_GOOD; } return rst; } static SANE_Int GetUSB_device_model (SANE_String_Const name) { SANE_Int usbid, model; /* default model is unknown */ model = -1; /* open usb device */ if (sanei_usb_open (name, &usbid) == SANE_STATUS_GOOD) { SANE_Int vendor, product; if (sanei_usb_get_vendor_product (usbid, &vendor, &product) == SANE_STATUS_GOOD) model = Device_get (product, vendor); sanei_usb_close (usbid); } return model; } static void Silent_Compile (void) { /* There are some functions in hp3900_rts8822.c that aren't used yet. To avoid compilation warnings we will use them here */ SANE_Byte a = 1; if (a == 0) { Buttons_Status (device); Calib_WriteTable (device, NULL, 0, 0); Gamma_GetTables (device, NULL); } } static void bknd_constrains (TScanner * scanner, SANE_Int source, SANE_Int type) { struct st_coords *coords = Constrains_Get (device, source); if ((coords != NULL) && (scanner != NULL)) { switch (type) { case 1: /* Y */ scanner->rng_vertical.max = coords->height; break; default: /* X */ scanner->rng_horizontal.max = coords->width; break; } } } static SANE_Status img_buffers_free (TScanner * scanner) { if (scanner != NULL) { if (scanner->image != NULL) { free (scanner->image); scanner->image = NULL; } if (scanner->rest != NULL) { free (scanner->rest); scanner->rest = NULL; } scanner->rest_amount = 0; } return SANE_STATUS_GOOD; } static SANE_Status img_buffers_alloc (TScanner * scanner, SANE_Int size) { SANE_Status rst; /* default result at this point */ rst = SANE_STATUS_INVAL; if (scanner != NULL) { /* default result at this point */ rst = SANE_STATUS_NO_MEM; /* free previous allocs */ img_buffers_free (scanner); scanner->image = (SANE_Byte *) malloc (size * sizeof (SANE_Byte)); if (scanner->image != NULL) { scanner->rest = (SANE_Byte *) malloc (size * sizeof (SANE_Byte)); if (scanner->rest != NULL) rst = SANE_STATUS_GOOD; /* ok !! */ } if (rst != SANE_STATUS_GOOD) img_buffers_free (scanner); } return rst; } static SANE_Int set_ScannerModel (SANE_Int proposed, SANE_Int product, SANE_Int vendor) { /* This function will set the device behaviour */ SANE_Int current = Device_get (product, vendor); char *sdevname[10] = { "Unknown", "HP3970", "HP4070", "HP4370", "UA4900", "HP3800", "HPG3010", "BQ5550", "HPG2710", "HPG3110" }; DBG (DBG_FNC, "> set_ScannerModel(proposed=%i, product=%04x, vendor=%04x)\n", proposed, product, vendor); if (proposed < 0) { if ((current < 0) || (current >= DEVSCOUNT)) { DBG (DBG_VRB, " -> Unknown device. Defaulting to HP3970...\n"); RTS_Debug->dev_model = HP3970; } else { RTS_Debug->dev_model = current; DBG (DBG_VRB, " -> Device model is %s\n", sdevname[current + 1]); } } else { if (proposed < DEVSCOUNT) { RTS_Debug->dev_model = proposed; DBG (DBG_VRB, " -> Device %s , treating as %s ...\n", sdevname[current + 1], sdevname[proposed + 1]); } else { if ((current >= 0) && (current < DEVSCOUNT)) { RTS_Debug->dev_model = current; DBG (DBG_VRB, " -> Device not supported. Defaulting to %s ...\n", sdevname[current + 1]); } else { RTS_Debug->dev_model = HP3970; DBG (DBG_VRB, "-> Device not supported. Defaulting to HP3970...\n"); } } } return OK; } static void Set_Coordinates (SANE_Int scantype, SANE_Int resolution, struct st_coords *coords) { struct st_coords *limits = Constrains_Get (device, scantype); DBG (DBG_FNC, "> Set_Coordinates(res=%i, *coords):\n", resolution); if (coords->left == -1) coords->left = 0; if (coords->width == -1) coords->width = limits->width; if (coords->top == -1) coords->top = 0; if (coords->height == -1) coords->height = limits->height; DBG (DBG_FNC, " -> Coords [MM] : xy(%i, %i) wh(%i, %i)\n", coords->left, coords->top, coords->width, coords->height); coords->left = MM_TO_PIXEL (coords->left, resolution); coords->width = MM_TO_PIXEL (coords->width, resolution); coords->top = MM_TO_PIXEL (coords->top, resolution); coords->height = MM_TO_PIXEL (coords->height, resolution); DBG (DBG_FNC, " -> Coords [px] : xy(%i, %i) wh(%i, %i)\n", coords->left, coords->top, coords->width, coords->height); Constrains_Check (device, resolution, scantype, coords); DBG (DBG_FNC, " -> Coords [check]: xy(%i, %i) wh(%i, %i)\n", coords->left, coords->top, coords->width, coords->height); } static void Color_Negative (SANE_Byte * buffer, SANE_Int size, SANE_Int depth) { if (buffer != NULL) { SANE_Int a; SANE_Int max_value = (1 << depth) - 1; if (depth > 8) { USHORT *sColor = (void *) buffer; for (a = 0; a < size / 2; a++) { *sColor = max_value - *sColor; sColor++; } } else { for (a = 0; a < size; a++) *(buffer + a) = max_value - *(buffer + a); } } } static SANE_Status get_button_status (TScanner * s) { if (s != NULL) { SANE_Int a, b, status, btn; b = 1; status = Buttons_Released (device) & 63; for (a = 0; a < 6; a++) { if ((status & b) != 0) { btn = Buttons_Order (device, b); if (btn != -1) s->aValues[opt_button_0 + btn].w = SANE_TRUE; } b <<= 1; } } return SANE_STATUS_GOOD; } static void Depth_16_to_8 (SANE_Byte * from_buffer, SANE_Int size, SANE_Byte * to_buffer) { if ((from_buffer != NULL) && (to_buffer != NULL)) { SANE_Int a, b; a = 1; b = 0; while (a < size) { *(to_buffer + b) = *(from_buffer + a); a += 2; b++; } } } static void Gray_to_Lineart (SANE_Byte * buffer, SANE_Int size, SANE_Int threshold) { /* code provided by tobias leutwein */ if (buffer != NULL) { SANE_Byte toBufferByte; SANE_Int fromBufferPos_i = 0; SANE_Int toBufferPos_i = 0; SANE_Int bitPos_i; while (fromBufferPos_i < size) { toBufferByte = 0; for (bitPos_i = 7; bitPos_i != (-1); bitPos_i--) { if ((fromBufferPos_i < size) && (buffer[fromBufferPos_i] < threshold)) toBufferByte |= (1u << bitPos_i); fromBufferPos_i++; } buffer[toBufferPos_i] = toBufferByte; toBufferPos_i++; } } } static void Color_to_Gray (SANE_Byte * buffer, SANE_Int size, SANE_Int depth) { /* converts 3 color channel into 1 gray channel of specified bit depth */ if (buffer != NULL) { SANE_Int c, chn, chn_size; SANE_Byte *ptr_src = NULL; SANE_Byte *ptr_dst = NULL; float data, chn_data; float coef[3] = { 0.299, 0.587, 0.114 }; /* coefficients per channel */ chn_size = (depth > 8) ? 2 : 1; ptr_src = (void *) buffer; ptr_dst = (void *) buffer; for (c = 0; c < size / (3 * chn_size); c++) { data = 0.; /* get, apply coeffs and sum channels */ for (chn = 0; chn < 3; chn++) { chn_data = data_lsb_get (ptr_src + (chn * chn_size), chn_size); data += (chn_data * coef[chn]); } /* save result */ data_lsb_set (ptr_dst, (SANE_Int) data, chn_size); ptr_src += 3 * chn_size; /* next triplet */ ptr_dst += chn_size; } } } static void gamma_free (TScanner * s) { DBG (DBG_FNC, "> gamma_free()\n"); if (s != NULL) { /* Destroy gamma tables */ SANE_Int a; for (a = CL_RED; a <= CL_BLUE; a++) { if (s->aGammaTable[a] != NULL) { free (s->aGammaTable[a]); s->aGammaTable[a] = NULL; } } } } static SANE_Int gamma_create (TScanner * s, double gamma) { SANE_Int rst = ERROR; /* by default */ DBG (DBG_FNC, "> gamma_create(*s)\n"); if (s != NULL) { SANE_Int a; double value, c; /* default result */ rst = OK; /* destroy previus gamma tables */ gamma_free (s); /* check gamma value */ if (gamma < 0) gamma = GAMMA_DEFAULT; /* allocate space for 16 bit gamma tables */ for (a = CL_RED; a <= CL_BLUE; a++) { s->aGammaTable[a] = malloc (65536 * sizeof (SANE_Word)); if (s->aGammaTable[a] == NULL) { rst = ERROR; break; } } if (rst == OK) { /* fill tables */ for (a = 0; a < 65536; a++) { value = (a / (65536. - 1)); value = pow (value, (1. / gamma)); value = value * (65536. - 1); c = (SANE_Int) value; if (c > (65536. - 1)) c = (65536. - 1); else if (c < 0) c = 0; s->aGammaTable[CL_RED][a] = c; s->aGammaTable[CL_GREEN][a] = c; s->aGammaTable[CL_BLUE][a] = c; } } else gamma_free (s); } return rst; } static void gamma_apply (TScanner * s, SANE_Byte * buffer, SANE_Int size, SANE_Int depth) { if ((s != NULL) && (buffer != NULL)) { SANE_Int c; SANE_Int dot_size = 3 * ((depth > 8) ? 2 : 1); SANE_Byte *pColor = buffer; USHORT *sColor = (void *) buffer; if ((s->aGammaTable[CL_RED] != NULL) && (s->aGammaTable[CL_GREEN] != NULL) && (s->aGammaTable[CL_BLUE] != NULL)) { for (c = 0; c < size / dot_size; c++) { if (depth > 8) { *sColor = s->aGammaTable[CL_RED][*sColor]; *(sColor + 1) = s->aGammaTable[CL_GREEN][*(sColor + 1)]; *(sColor + 2) = s->aGammaTable[CL_BLUE][*(sColor + 2)]; sColor += 3; } else { /* 8 bits gamma */ *pColor = (s->aGammaTable[CL_RED][*pColor * 256] >> 8) & 0xff; *(pColor + 1) = (s-> aGammaTable[CL_GREEN][*(pColor + 1) * 256] >> 8) & 0xff; *(pColor + 2) = (s-> aGammaTable[CL_BLUE][*(pColor + 2) * 256] >> 8) & 0xff; pColor += 3; } } } } } static SANE_Int Get_Model (SANE_String model) { SANE_Int rst; if (strcmp (model, "HP3800") == 0) rst = HP3800; else if (strcmp (model, "HPG2710") == 0) rst = HPG2710; else if (strcmp (model, "HP3970") == 0) rst = HP3970; else if (strcmp (model, "HP4070") == 0) rst = HP4070; else if (strcmp (model, "HP4370") == 0) rst = HP4370; else if (strcmp (model, "HPG3010") == 0) rst = HPG3010; else if (strcmp (model, "HPG3110") == 0) rst = HPG3110; else if (strcmp (model, "UA4900") == 0) rst = UA4900; else if (strcmp (model, "BQ5550") == 0) rst = BQ5550; else rst = HP3970; /* default */ return rst; } static SANE_Int Get_Source (SANE_String source) { SANE_Int rst; if (strcmp (source, SANE_I18N ("Flatbed")) == 0) rst = ST_NORMAL; else if (strcmp (source, SANE_I18N ("Slide")) == 0) rst = ST_TA; else if (strcmp (source, SANE_I18N ("Negative")) == 0) rst = ST_NEG; else rst = ST_NORMAL; /* default */ return rst; } static SANE_Int Get_Colormode (SANE_String colormode) { SANE_Int rst; if (strcmp (colormode, SANE_VALUE_SCAN_MODE_COLOR) == 0) rst = CM_COLOR; else if (strcmp (colormode, SANE_VALUE_SCAN_MODE_GRAY) == 0) rst = CM_GRAY; else if (strcmp (colormode, SANE_VALUE_SCAN_MODE_LINEART) == 0) rst = CM_LINEART; else rst = CM_COLOR; /* default */ return rst; } static SANE_Status Translate_coords (struct st_coords *coords) { SANE_Int data; DBG (DBG_FNC, "> Translate_coords(*coords)\n"); if ((coords->left < 0) || (coords->top < 0) || (coords->width < 0) || (coords->height < 0)) return SANE_STATUS_INVAL; if (coords->width < coords->left) { data = coords->left; coords->left = coords->width; coords->width = data; } if (coords->height < coords->top) { data = coords->top; coords->top = coords->height; coords->height = data; } coords->width -= coords->left; coords->height -= coords->top; if (coords->width == 0) coords->width++; if (coords->height == 0) coords->height++; return SANE_STATUS_GOOD; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; DBG (DBG_FNC, "> max_string_size:\n"); for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static void options_free (TScanner * scanner) { /* frees all information contained in controls */ DBG (DBG_FNC, "> options_free\n"); if (scanner != NULL) { SANE_Int i; SANE_Option_Descriptor *pDesc; TOptionValue *pVal; /* free gamma tables */ gamma_free (scanner); /* free lists */ if (scanner->list_resolutions != NULL) free (scanner->list_resolutions); if (scanner->list_depths != NULL) free (scanner->list_depths); if (scanner->list_sources != NULL) free (scanner->list_sources); if (scanner->list_colormodes != NULL) free (scanner->list_colormodes); if (scanner->list_models != NULL) free (scanner->list_models); /* free values in certain controls */ for (i = opt_begin; i < opt_count; i++) { pDesc = &scanner->aOptions[i]; pVal = &scanner->aValues[i]; if (pDesc->type == SANE_TYPE_STRING) { if (pVal->s != NULL) free (pVal->s); } } } } static void options_init (TScanner * scanner) { /* initializes all controls */ DBG (DBG_FNC, "> options_init\n"); if (scanner != NULL) { SANE_Int i; SANE_Option_Descriptor *pDesc; TOptionValue *pVal; /* set gamma */ gamma_create (scanner, 1.0); /* color convertion */ scanner->cnv.colormode = -1; scanner->cnv.negative = FALSE; scanner->cnv.threshold = 40; scanner->cnv.real_depth = FALSE; scanner->cnv.depth = -1; /* setting threshold */ scanner->rng_threshold.min = 0; scanner->rng_threshold.max = 255; scanner->rng_threshold.quant = 0; /* setting gamma range (16 bits depth) */ scanner->rng_gamma.min = 0; scanner->rng_gamma.max = 65535; scanner->rng_gamma.quant = 0; /* setting default horizontal constrain in milimeters */ scanner->rng_horizontal.min = 0; scanner->rng_horizontal.max = 220; scanner->rng_horizontal.quant = 1; /* setting default vertical constrain in milimeters */ scanner->rng_vertical.min = 0; scanner->rng_vertical.max = 300; scanner->rng_vertical.quant = 1; /* allocate option lists */ bknd_info (scanner); bknd_colormodes (scanner, RTS_Debug->dev_model); bknd_depths (scanner, RTS_Debug->dev_model); bknd_models (scanner); bknd_resolutions (scanner, RTS_Debug->dev_model); bknd_sources (scanner, RTS_Debug->dev_model); /* By default preview scan */ scanner->ScanParams.scantype = ST_NORMAL; scanner->ScanParams.colormode = CM_COLOR; scanner->ScanParams.resolution_x = 75; scanner->ScanParams.resolution_y = 75; scanner->ScanParams.coords.left = 0; scanner->ScanParams.coords.top = 0; scanner->ScanParams.coords.width = 220; scanner->ScanParams.coords.height = 300; scanner->ScanParams.depth = 8; scanner->ScanParams.channel = 0; for (i = opt_begin; i < opt_count; i++) { pDesc = &scanner->aOptions[i]; pVal = &scanner->aValues[i]; /* defaults */ pDesc->name = ""; pDesc->title = ""; pDesc->desc = ""; pDesc->type = SANE_TYPE_INT; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->cap = 0; switch (i) { case opt_begin: pDesc->title = SANE_TITLE_NUM_OPTIONS; pDesc->desc = SANE_DESC_NUM_OPTIONS; pDesc->cap = SANE_CAP_SOFT_DETECT; pVal->w = (SANE_Word) opt_count; break; case grp_geometry: pDesc->name = SANE_NAME_GEOMETRY; pDesc->title = SANE_TITLE_GEOMETRY; pDesc->desc = SANE_DESC_GEOMETRY; pDesc->type = SANE_TYPE_GROUP; pDesc->unit = SANE_UNIT_NONE; pDesc->size = 0; pDesc->cap = 0; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pVal->w = 0; break; case opt_tlx: pDesc->name = SANE_NAME_SCAN_TL_X; pDesc->title = SANE_TITLE_SCAN_TL_X; pDesc->desc = SANE_DESC_SCAN_TL_X; pDesc->unit = SANE_UNIT_MM; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &scanner->rng_horizontal; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = 0; break; case opt_tly: pDesc->name = SANE_NAME_SCAN_TL_Y; pDesc->title = SANE_TITLE_SCAN_TL_Y; pDesc->desc = SANE_DESC_SCAN_TL_Y; pDesc->unit = SANE_UNIT_MM; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &scanner->rng_vertical; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = 0; break; case opt_brx: pDesc->name = SANE_NAME_SCAN_BR_X; pDesc->title = SANE_TITLE_SCAN_BR_X; pDesc->desc = SANE_DESC_SCAN_BR_X; pDesc->unit = SANE_UNIT_MM; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &scanner->rng_horizontal; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = scanner->rng_horizontal.max; break; case opt_bry: pDesc->name = SANE_NAME_SCAN_BR_Y; pDesc->title = SANE_TITLE_SCAN_BR_Y; pDesc->desc = SANE_DESC_SCAN_BR_Y; pDesc->unit = SANE_UNIT_MM; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &scanner->rng_vertical; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = scanner->rng_vertical.max; break; case opt_resolution: pDesc->name = SANE_NAME_SCAN_RESOLUTION; pDesc->title = SANE_TITLE_SCAN_RESOLUTION; pDesc->desc = SANE_DESC_SCAN_RESOLUTION; pDesc->unit = SANE_UNIT_DPI; pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST; pDesc->constraint.word_list = scanner->list_resolutions; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = scanner->list_resolutions[1]; break; case opt_gamma_red: pDesc->name = SANE_NAME_GAMMA_VECTOR_R; pDesc->title = SANE_TITLE_GAMMA_VECTOR_R; pDesc->desc = SANE_DESC_GAMMA_VECTOR_R; pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word); pDesc->unit = SANE_UNIT_NONE; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &scanner->rng_gamma; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->wa = scanner->aGammaTable[CL_RED]; break; case opt_gamma_green: pDesc->name = SANE_NAME_GAMMA_VECTOR_G; pDesc->title = SANE_TITLE_GAMMA_VECTOR_G; pDesc->desc = SANE_DESC_GAMMA_VECTOR_G; pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word); pDesc->unit = SANE_UNIT_NONE; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &scanner->rng_gamma; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->wa = scanner->aGammaTable[CL_GREEN]; break; case opt_gamma_blue: pDesc->name = SANE_NAME_GAMMA_VECTOR_B; pDesc->title = SANE_TITLE_GAMMA_VECTOR_B; pDesc->desc = SANE_DESC_GAMMA_VECTOR_B; pDesc->size = scanner->rng_gamma.max * sizeof (SANE_Word); pDesc->unit = SANE_UNIT_NONE; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &scanner->rng_gamma; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->wa = scanner->aGammaTable[CL_BLUE]; break; case opt_scantype: pDesc->name = SANE_NAME_SCAN_SOURCE; pDesc->title = SANE_TITLE_SCAN_SOURCE; pDesc->desc = SANE_DESC_SCAN_SOURCE; pDesc->type = SANE_TYPE_STRING; pDesc->size = max_string_size (scanner->list_sources); pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; pDesc->constraint.string_list = scanner->list_sources; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->s = strdup (scanner->list_sources[0]); break; case opt_colormode: pDesc->name = SANE_NAME_SCAN_MODE; pDesc->title = SANE_TITLE_SCAN_MODE; pDesc->desc = SANE_DESC_SCAN_MODE; pDesc->type = SANE_TYPE_STRING; pDesc->size = max_string_size (scanner->list_colormodes); pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; pDesc->constraint.string_list = scanner->list_colormodes; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->s = strdup (scanner->list_colormodes[0]); break; case opt_depth: pDesc->name = SANE_NAME_BIT_DEPTH; pDesc->title = SANE_TITLE_BIT_DEPTH; pDesc->desc = SANE_DESC_BIT_DEPTH; pDesc->type = SANE_TYPE_INT; pDesc->unit = SANE_UNIT_BIT; pDesc->constraint_type = SANE_CONSTRAINT_WORD_LIST; pDesc->constraint.word_list = scanner->list_depths; pDesc->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->w = scanner->list_depths[1]; break; case opt_threshold: pDesc->name = SANE_NAME_THRESHOLD; pDesc->title = SANE_TITLE_THRESHOLD; pDesc->desc = SANE_DESC_THRESHOLD; pDesc->type = SANE_TYPE_INT; pDesc->unit = SANE_UNIT_NONE; pDesc->constraint_type = SANE_CONSTRAINT_RANGE; pDesc->constraint.range = &scanner->rng_threshold; pDesc->cap |= SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; pVal->w = 0x80; break; /* debugging options */ case grp_debug: pDesc->name = "grp_debug"; pDesc->title = SANE_I18N ("Debugging Options"); pDesc->desc = ""; pDesc->type = SANE_TYPE_GROUP; pDesc->unit = SANE_UNIT_NONE; pDesc->size = 0; pDesc->cap = SANE_CAP_ADVANCED; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pVal->w = 0; break; case opt_model: pDesc->name = "opt_model"; pDesc->title = SANE_I18N ("Scanner model"); pDesc->desc = SANE_I18N ("Allows one to test device behaviour with other supported models"); pDesc->type = SANE_TYPE_STRING; pDesc->size = max_string_size (scanner->list_models); pDesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; pDesc->constraint.string_list = scanner->list_models; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; pVal->s = strdup (scanner->list_models[0]); break; case opt_negative: pDesc->name = "opt_negative"; pDesc->title = SANE_I18N ("Negative"); pDesc->desc = SANE_I18N ("Image colours will be inverted"); pDesc->type = SANE_TYPE_BOOL; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; pVal->w = SANE_FALSE; break; case opt_nogamma: pDesc->name = "opt_nogamma"; pDesc->title = SANE_I18N ("Disable gamma correction"); pDesc->desc = SANE_I18N ("Gamma correction will be disabled"); pDesc->type = SANE_TYPE_BOOL; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; pVal->w = SANE_FALSE; break; case opt_nowshading: pDesc->name = "opt_nowshading"; pDesc->title = SANE_I18N ("Disable white shading correction"); pDesc->desc = SANE_I18N ("White shading correction will be disabled"); pDesc->type = SANE_TYPE_BOOL; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; pVal->w = SANE_FALSE; break; case opt_nowarmup: pDesc->name = "opt_nowarmup"; pDesc->title = SANE_I18N ("Skip warmup process"); pDesc->desc = SANE_I18N ("Warmup process will be disabled"); pDesc->type = SANE_TYPE_BOOL; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; pVal->w = SANE_FALSE; break; case opt_realdepth: pDesc->name = "opt_realdepth"; pDesc->title = SANE_I18N ("Force real depth"); pDesc->desc = SANE_I18N ("If gamma is enabled, scans are always made in 16 bits depth to improve image quality and then converted to the selected depth. This option avoids depth emulation."); pDesc->type = SANE_TYPE_BOOL; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; pVal->w = SANE_FALSE; break; case opt_emulategray: pDesc->name = "opt_emulategray"; pDesc->title = SANE_I18N ("Emulate Grayscale"); pDesc->desc = SANE_I18N ("If enabled, image will be scanned in color mode and then converted to grayscale by software. This may improve image quality in some circumstances."); pDesc->type = SANE_TYPE_BOOL; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; pVal->w = SANE_FALSE; break; case opt_dbgimages: pDesc->name = "opt_dbgimages"; pDesc->title = SANE_I18N ("Save debugging images"); pDesc->desc = SANE_I18N ("If enabled, some images involved in scanner processing are saved to analyze them."); pDesc->type = SANE_TYPE_BOOL; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; pVal->w = SANE_FALSE; break; case opt_reset: pDesc->name = "opt_reset"; pDesc->title = SANE_I18N ("Reset chipset"); pDesc->desc = SANE_I18N ("Resets chipset data"); pDesc->type = SANE_TYPE_BUTTON; pDesc->unit = SANE_UNIT_NONE; pDesc->size = 0; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.string_list = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT; pVal->w = 0; break; /* device information */ case grp_info: pDesc->name = "grp_info"; pDesc->title = SANE_I18N ("Information"); pDesc->desc = ""; pDesc->type = SANE_TYPE_GROUP; pDesc->unit = SANE_UNIT_NONE; pDesc->size = 0; pDesc->cap = 0; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pVal->w = 0; break; case opt_chipname: pDesc->name = "opt_chipname"; pDesc->title = SANE_I18N ("Chipset name"); pDesc->desc = SANE_I18N ("Shows chipset name used in device."); pDesc->type = SANE_TYPE_STRING; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT; pVal->s = strdup (SANE_I18N ("Unknown")); pDesc->size = strlen(pVal->s) + 1; break; case opt_chipid: pDesc->name = "opt_chipid"; pDesc->title = SANE_I18N ("Chipset ID"); pDesc->desc = SANE_I18N ("Shows the chipset ID"); pDesc->type = SANE_TYPE_INT; pDesc->unit = SANE_UNIT_NONE; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT; pVal->w = -1; break; case opt_scancount: pDesc->name = "opt_scancount"; pDesc->title = SANE_I18N ("Scan counter"); pDesc->desc = SANE_I18N ("Shows the number of scans made by scanner"); pDesc->type = SANE_TYPE_INT; pDesc->unit = SANE_UNIT_NONE; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_DETECT; pVal->w = -1; break; case opt_infoupdate: pDesc->name = "opt_infoupdate"; pDesc->title = SANE_I18N ("Update information"); pDesc->desc = SANE_I18N ("Updates information about device"); pDesc->type = SANE_TYPE_BUTTON; pDesc->unit = SANE_UNIT_NONE; pDesc->size = 0; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.string_list = 0; pDesc->cap = SANE_CAP_ADVANCED | SANE_CAP_SOFT_SELECT; pVal->w = 0; break; /* buttons support */ case grp_sensors: pDesc->name = SANE_NAME_SENSORS; pDesc->title = SANE_TITLE_SENSORS; pDesc->desc = SANE_DESC_SENSORS; pDesc->type = SANE_TYPE_GROUP; pDesc->unit = SANE_UNIT_NONE; pDesc->size = 0; pDesc->cap = 0; pDesc->constraint_type = SANE_CONSTRAINT_NONE; pDesc->constraint.range = 0; pVal->w = 0; break; case opt_button_0: case opt_button_1: case opt_button_2: case opt_button_3: case opt_button_4: case opt_button_5: { char name[12]; char title[128]; sprintf (name, "button %d", i - opt_button_0); sprintf (title, "Scanner button %d", i - opt_button_0); pDesc->name = strdup (name); pDesc->title = strdup (title); pDesc->desc = SANE_I18N ("This option reflects a front panel scanner button"); pDesc->type = SANE_TYPE_BOOL; pDesc->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if (i - opt_button_0 >= Buttons_Count (device)) pDesc->cap |= SANE_CAP_INACTIVE; pDesc->unit = SANE_UNIT_NONE; pDesc->size = sizeof (SANE_Word); pDesc->constraint_type = SANE_CONSTRAINT_NONE; pVal->w = SANE_FALSE; } break; } } } } static SANE_Int _ReportDevice (TScannerModel * pModel, const char *pszDeviceName) { SANE_Int rst = ERROR; TDevListEntry *pNew, *pDev; DBG (DBG_FNC, "> _ReportDevice:\n"); pNew = malloc (sizeof (TDevListEntry)); if (pNew != NULL) { rst = OK; /* add new element to the end of the list */ if (_pFirstSaneDev != NULL) { /* Add at the end of existing list */ for (pDev = _pFirstSaneDev; pDev->pNext; pDev = pDev->pNext); pDev->pNext = pNew; } else _pFirstSaneDev = pNew; /* fill in new element */ pNew->pNext = NULL; pNew->devname = (char *) strdup (pszDeviceName); pNew->dev.name = pNew->devname; pNew->dev.vendor = pModel->pszVendor; pNew->dev.model = pModel->pszName; pNew->dev.type = SANE_I18N ("flatbed scanner"); iNumSaneDev++; } return rst; } static SANE_Status attach_one_device (SANE_String_Const devname) { static TScannerModel sModel; DBG (DBG_FNC, "> attach_one_device(devname=%s)\n", devname); switch (GetUSB_device_model (devname)) { case HP3800: sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); sModel.pszName = (char *) strdup ("Scanjet 3800"); break; case HPG2710: sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); sModel.pszName = (char *) strdup ("Scanjet G2710"); break; case HP3970: sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); sModel.pszName = (char *) strdup ("Scanjet 3970"); break; case HP4070: sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); sModel.pszName = (char *) strdup ("Scanjet 4070 Photosmart"); break; case HP4370: sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); sModel.pszName = (char *) strdup ("Scanjet 4370"); break; case HPG3010: sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); sModel.pszName = (char *) strdup ("Scanjet G3010"); break; case HPG3110: sModel.pszVendor = (char *) strdup ("Hewlett-Packard"); sModel.pszName = (char *) strdup ("Scanjet G3110"); break; case UA4900: sModel.pszVendor = (char *) strdup ("UMAX"); sModel.pszName = (char *) strdup ("Astra 4900"); break; case BQ5550: sModel.pszVendor = (char *) strdup ("BenQ"); sModel.pszName = (char *) strdup ("5550"); break; default: sModel.pszVendor = (char *) strdup ("Unknown"); sModel.pszName = (char *) strdup ("RTS8822 chipset based"); break; } _ReportDevice (&sModel, devname); return SANE_STATUS_GOOD; } /* Sane default functions */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { FILE *conf_fp; /* Config file stream */ SANE_Char line[PATH_MAX]; SANE_Char *str = NULL; SANE_String_Const proper_str; SANE_Int nline = 0; /* Initialize debug */ DBG_INIT (); DBG (DBG_FNC, "> sane_init\n"); /* silence gcc */ authorize = authorize; /* Initialize usb */ sanei_usb_init (); /* Parse config file */ conf_fp = sanei_config_open (HP3900_CONFIG_FILE); if (conf_fp) { while (sanei_config_read (line, sizeof (line), conf_fp)) { nline++; if (str) free (str); proper_str = sanei_config_get_string (line, &str); /* Discards white lines and comments */ if ((str != NULL) && (proper_str != line) && (str[0] != '#')) { /* If line's not blank or a comment, then it's the device * filename or a usb directive. */ sanei_usb_attach_matching_devices (line, attach_one_device); } } fclose (conf_fp); } else { /* default */ DBG (DBG_VRB, "- %s not found. Looking for hardcoded usb ids ...\n", HP3900_CONFIG_FILE); sanei_usb_attach_matching_devices ("usb 0x03f0 0x2605", attach_one_device); /* HP3800 */ sanei_usb_attach_matching_devices ("usb 0x03f0 0x2805", attach_one_device); /* HPG2710 */ sanei_usb_attach_matching_devices ("usb 0x03f0 0x2305", attach_one_device); /* HP3970 */ sanei_usb_attach_matching_devices ("usb 0x03f0 0x2405", attach_one_device); /* HP4070 */ sanei_usb_attach_matching_devices ("usb 0x03f0 0x4105", attach_one_device); /* HP4370 */ sanei_usb_attach_matching_devices ("usb 0x03f0 0x4205", attach_one_device); /* HPG3010 */ sanei_usb_attach_matching_devices ("usb 0x03f0 0x4305", attach_one_device); /* HPG3110 */ sanei_usb_attach_matching_devices ("usb 0x06dc 0x0020", attach_one_device); /* UA4900 */ sanei_usb_attach_matching_devices ("usb 0x04a5 0x2211", attach_one_device); /* BQ5550 */ } /* Return backend version */ if (version_code != NULL) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { SANE_Status rst = SANE_STATUS_GOOD; local_only = local_only; if (_pSaneDevList) free (_pSaneDevList); _pSaneDevList = malloc (sizeof (*_pSaneDevList) * (iNumSaneDev + 1)); if (_pSaneDevList != NULL) { TDevListEntry *pDev; SANE_Int i = 0; for (pDev = _pFirstSaneDev; pDev; pDev = pDev->pNext) _pSaneDevList[i++] = &pDev->dev; _pSaneDevList[i++] = 0; /* last entry is 0 */ *device_list = _pSaneDevList; } else rst = SANE_STATUS_NO_MEM; DBG (DBG_FNC, "> sane_get_devices: %i\n", rst); return rst; } SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h) { TScanner *s; SANE_Status rst; /* check the name */ if (strlen (name) == 0) /* default to first available device */ name = _pFirstSaneDev->dev.name; /* allocate space for RTS environment */ device = RTS_Alloc (); if (device != NULL) { /* Open device */ rst = sanei_usb_open (name, &device->usb_handle); if (rst == SANE_STATUS_GOOD) { /* Allocating memory for device */ s = malloc (sizeof (TScanner)); if (s != NULL) { memset (s, 0, sizeof (TScanner)); /* Initializing RTS */ if (Init_Vars () == OK) { SANE_Int vendor, product; /* Setting device model */ if (sanei_usb_get_vendor_product (device->usb_handle, &vendor, &product) == SANE_STATUS_GOOD) s->model = Device_get (product, vendor); else s->model = HP3970; set_ScannerModel (s->model, product, vendor); /* Initialize device */ if (RTS_Scanner_Init (device) == OK) { /* silencing unused functions */ Silent_Compile (); /* initialize backend options */ options_init (s); *h = s; /* everything went ok */ rst = SANE_STATUS_GOOD; } else { free ((void *) s); rst = SANE_STATUS_INVAL; } } else rst = SANE_STATUS_NO_MEM; } else rst = SANE_STATUS_NO_MEM; } } else rst = SANE_STATUS_NO_MEM; DBG (DBG_FNC, "> sane_open(name=%s): %i\n", name, rst); return rst; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int n) { SANE_Option_Descriptor *rst = NULL; if ((n >= opt_begin) && (n < opt_count)) { TScanner *s = (TScanner *) h; rst = &s->aOptions[n]; } DBG (DBG_FNC, "> SANE_Option_Descriptor(handle, n=%i): %i\n", n, (rst == NULL) ? -1 : 0); return rst; } static SANE_Status option_get (TScanner * scanner, SANE_Int optid, void *result) { /* This function returns value contained in selected option */ DBG (DBG_FNC, "> option_get(optid=%i)\n", optid); if ((scanner != NULL) && (result != NULL)) { switch (optid) { /* SANE_Word */ case opt_begin: /* null */ case opt_reset: /* null */ case opt_negative: case opt_nogamma: case opt_nowshading: case opt_emulategray: case opt_dbgimages: case opt_nowarmup: case opt_realdepth: case opt_depth: case opt_resolution: case opt_threshold: case opt_brx: case opt_tlx: case opt_bry: case opt_tly: *(SANE_Word *) result = scanner->aValues[optid].w; break; /* SANE_Int */ case opt_chipid: case opt_scancount: *(SANE_Int *) result = scanner->aValues[optid].w; break; /* SANE_Word array */ case opt_gamma_red: case opt_gamma_green: case opt_gamma_blue: memcpy (result, scanner->aValues[optid].wa, scanner->aOptions[optid].size); break; /* String */ case opt_colormode: case opt_scantype: case opt_model: case opt_chipname: strncpy (result, scanner->aValues[optid].s, scanner->aOptions[optid].size); ((char*)result)[scanner->aOptions[optid].size-1] = '\0'; break; /* scanner buttons */ case opt_button_0: get_button_status (scanner); case opt_button_1: case opt_button_2: case opt_button_3: case opt_button_4: case opt_button_5: /* copy the button state */ *(SANE_Word *) result = scanner->aValues[optid].w; /* clear the button state */ scanner->aValues[optid].w = SANE_FALSE; break; } } return SANE_STATUS_GOOD; } static SANE_Status option_set (TScanner * scanner, SANE_Int optid, void *value, SANE_Int * pInfo) { SANE_Status rst; DBG (DBG_FNC, "> option_set(optid=%i)\n", optid); rst = SANE_STATUS_INVAL; if (scanner != NULL) { if (scanner->fScanning == FALSE) { SANE_Int info = 0; rst = SANE_STATUS_GOOD; switch (optid) { case opt_brx: case opt_tlx: case opt_bry: case opt_tly: case opt_depth: case opt_nogamma: case opt_nowshading: case opt_nowarmup: case opt_negative: case opt_emulategray: case opt_dbgimages: case opt_threshold: case opt_resolution: info |= SANE_INFO_RELOAD_PARAMS; scanner->aValues[optid].w = *(SANE_Word *) value; break; case opt_gamma_red: case opt_gamma_green: case opt_gamma_blue: memcpy (scanner->aValues[optid].wa, value, scanner->aOptions[optid].size); break; case opt_scantype: if (strcmp (scanner->aValues[optid].s, value) != 0) { struct st_coords *coords; SANE_Int source; if (scanner->aValues[optid].s) free (scanner->aValues[optid].s); scanner->aValues[optid].s = strdup (value); source = Get_Source (scanner->aValues[opt_scantype].s); coords = Constrains_Get (device, source); if (coords != NULL) { bknd_constrains (scanner, source, 0); bknd_constrains (scanner, source, 1); scanner->aValues[opt_tlx].w = 0; scanner->aValues[opt_tly].w = 0; scanner->aValues[opt_brx].w = coords->width; scanner->aValues[opt_bry].w = coords->height; } info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } break; case opt_colormode: if (strcmp (scanner->aValues[optid].s, value) != 0) { if (scanner->aValues[optid].s) free (scanner->aValues[optid].s); scanner->aValues[optid].s = strdup (value); if (Get_Colormode (scanner->aValues[optid].s) == CM_LINEART) scanner->aOptions[opt_threshold].cap &= ~SANE_CAP_INACTIVE; else scanner->aOptions[opt_threshold].cap |= SANE_CAP_INACTIVE; info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } break; case opt_model: if (strcmp (scanner->aValues[optid].s, value) != 0) { SANE_Int model; if (scanner->aValues[optid].s) free (scanner->aValues[optid].s); scanner->aValues[optid].s = strdup (value); model = Get_Model (scanner->aValues[optid].s); if (model != RTS_Debug->dev_model) { SANE_Int source; struct st_coords *coords; /* free configuration of last model */ Free_Config (device); /* set new model */ RTS_Debug->dev_model = model; /* and load configuration of current model */ Load_Config (device); /* update options according to selected device */ bknd_info (scanner); bknd_colormodes (scanner, model); bknd_depths (scanner, model); bknd_resolutions (scanner, model); bknd_sources (scanner, model); /* updating lists */ scanner->aOptions[opt_colormode].size = max_string_size (scanner->list_colormodes); scanner->aOptions[opt_colormode].constraint. string_list = scanner->list_colormodes; scanner->aOptions[opt_depth].constraint.word_list = scanner->list_depths; scanner->aOptions[opt_resolution].constraint.word_list = scanner->list_resolutions; scanner->aOptions[opt_scantype].size = max_string_size (scanner->list_sources); scanner->aOptions[opt_scantype].constraint.string_list = scanner->list_sources; /* default values */ if (scanner->aValues[opt_colormode].s != NULL) free (scanner->aValues[opt_colormode].s); if (scanner->aValues[opt_scantype].s != NULL) free (scanner->aValues[opt_scantype].s); scanner->aValues[opt_colormode].s = strdup (scanner->list_colormodes[0]); scanner->aValues[opt_scantype].s = strdup (scanner->list_sources[0]); scanner->aValues[opt_resolution].w = scanner->list_resolutions[1]; scanner->aValues[opt_depth].w = scanner->list_depths[1]; source = Get_Source (scanner->aValues[opt_scantype].s); coords = Constrains_Get (device, source); if (coords != NULL) { bknd_constrains (scanner, source, 0); bknd_constrains (scanner, source, 1); scanner->aValues[opt_tlx].w = 0; scanner->aValues[opt_tly].w = 0; scanner->aValues[opt_brx].w = coords->width; scanner->aValues[opt_bry].w = coords->height; } } info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } break; case opt_reset: Chipset_Reset (device); break; case opt_realdepth: scanner->aValues[optid].w = (scanner->cnv.real_depth == TRUE) ? SANE_TRUE : SANE_FALSE; break; case opt_infoupdate: if (bknd_info (scanner) == SANE_STATUS_GOOD) info |= SANE_INFO_RELOAD_OPTIONS; break; default: rst = SANE_STATUS_INVAL; break; } if (pInfo != NULL) *pInfo = info; } } return rst; } SANE_Status sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action Action, void *pVal, SANE_Int * pInfo) { TScanner *scanner; SANE_Status rst; DBG (DBG_FNC, "> sane_control_option\n"); scanner = (TScanner *) h; switch (Action) { case SANE_ACTION_GET_VALUE: rst = option_get (scanner, n, pVal); break; case SANE_ACTION_SET_VALUE: rst = option_set (scanner, n, pVal, pInfo); break; case SANE_ACTION_SET_AUTO: rst = SANE_STATUS_UNSUPPORTED; break; default: rst = SANE_STATUS_INVAL; break; } return rst; } SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p) { SANE_Status rst = SANE_STATUS_INVAL; TScanner *s = (TScanner *) h; DBG (DBG_FNC, "+ sane_get_parameters:"); if (s != NULL) { struct st_coords coords; SANE_Int res, source, depth, colormode, frameformat, bpl; /* first do some checks */ /* colormode */ colormode = Get_Colormode (s->aValues[opt_colormode].s); /* frameformat */ frameformat = (colormode == CM_COLOR) ? SANE_FRAME_RGB : SANE_FRAME_GRAY; /* depth */ depth = (colormode == CM_LINEART) ? 1 : s->aValues[opt_depth].w; /* scan type */ source = Get_Source (s->aValues[opt_scantype].s); /* resolution */ res = s->aValues[opt_resolution].w; /* image coordinates in milimeters */ coords.left = s->aValues[opt_tlx].w; coords.top = s->aValues[opt_tly].w; coords.width = s->aValues[opt_brx].w; coords.height = s->aValues[opt_bry].w; /* validate coords */ if (Translate_coords (&coords) == SANE_STATUS_GOOD) { Set_Coordinates (source, res, &coords); if (colormode != CM_LINEART) { bpl = coords.width * ((depth > 8) ? 2 : 1); if (colormode == CM_COLOR) bpl *= 3; /* three channels */ } else bpl = (coords.width + 7) / 8; /* return the data */ p->format = frameformat; p->last_frame = SANE_TRUE; p->depth = depth; p->lines = coords.height; p->pixels_per_line = coords.width; p->bytes_per_line = bpl; DBG (DBG_FNC, " -> Depth : %i\n", depth); DBG (DBG_FNC, " -> Height: %i\n", coords.height); DBG (DBG_FNC, " -> Width : %i\n", coords.width); DBG (DBG_FNC, " -> BPL : %i\n", bpl); rst = SANE_STATUS_GOOD; } } DBG (DBG_FNC, "- sane_get_parameters: %i\n", rst); return rst; } SANE_Status sane_start (SANE_Handle h) { SANE_Status rst = SANE_STATUS_INVAL; TScanner *s; DBG (DBG_FNC, "+ sane_start\n"); s = (TScanner *) h; if (s != NULL) { struct st_coords coords; SANE_Int res, source, colormode, depth, channel; /* first do some checks */ /* Get Scan type */ source = Get_Source (s->aValues[opt_scantype].s); /* Check if scanner supports slides and negatives in case selected source is tma */ if (!((source != ST_NORMAL) && (RTS_isTmaAttached (device) == FALSE))) { /* Get depth */ depth = s->aValues[opt_depth].w; /* Get color mode */ colormode = Get_Colormode (s->aValues[opt_colormode].s); /* Emulating certain color modes */ if (colormode == CM_LINEART) { /* emulate lineart */ s->cnv.colormode = CM_LINEART; colormode = CM_GRAY; depth = 8; } else if ((colormode == CM_GRAY) && (s->aValues[opt_emulategray].w == SANE_TRUE)) { /* emulate grayscale */ s->cnv.colormode = CM_GRAY; colormode = CM_COLOR; } else s->cnv.colormode = -1; /* setting channel for colormodes different than CM_COLOR */ channel = (colormode != CM_COLOR) ? 1 : 0; /* negative colors */ s->cnv.negative = (s->aValues[opt_negative].w == SANE_TRUE) ? TRUE : FALSE; /* Get threshold */ s->cnv.threshold = s->aValues[opt_threshold].w; /* Get resolution */ res = s->aValues[opt_resolution].w; /* set depth emulation */ if (s->cnv.colormode == CM_LINEART) s->cnv.real_depth = TRUE; else s->cnv.real_depth = (s->aValues[opt_realdepth].w == SANE_TRUE) ? TRUE : FALSE; /* use gamma? */ RTS_Debug->EnableGamma = (s->aValues[opt_nogamma].w == SANE_TRUE) ? FALSE : TRUE; /* disable white shading correction? */ RTS_Debug->wshading = (s->aValues[opt_nowshading].w == SANE_TRUE) ? FALSE : TRUE; /* skip warmup process? */ RTS_Debug->warmup = (s->aValues[opt_nowarmup].w == SANE_TRUE) ? FALSE : TRUE; /* save debugging images? */ RTS_Debug->SaveCalibFile = (s->aValues[opt_dbgimages].w == SANE_TRUE) ? TRUE : FALSE; /* Get image coordinates in milimeters */ coords.left = s->aValues[opt_tlx].w; coords.top = s->aValues[opt_tly].w; coords.width = s->aValues[opt_brx].w; coords.height = s->aValues[opt_bry].w; /* Validate coords */ if (Translate_coords (&coords) == SANE_STATUS_GOOD) { /* Stop previusly started scan */ RTS_Scanner_StopScan (device, TRUE); s->ScanParams.scantype = source; s->ScanParams.colormode = colormode; s->ScanParams.resolution_x = res; s->ScanParams.resolution_y = res; s->ScanParams.channel = channel; memcpy (&s->ScanParams.coords, &coords, sizeof (struct st_coords)); Set_Coordinates (source, res, &s->ScanParams.coords); /* emulating depth? */ if ((s->cnv.real_depth == FALSE) && (depth < 16) && (RTS_Debug->EnableGamma == TRUE)) { /* In order to improve image quality, we will scan at 16bits if we are using gamma correction */ s->cnv.depth = depth; s->ScanParams.depth = 16; } else { s->ScanParams.depth = depth; s->cnv.depth = -1; } /* set scanning parameters */ if (RTS_Scanner_SetParams (device, &s->ScanParams) == OK) { /* Start scanning process */ if (RTS_Scanner_StartScan (device) == OK) { /* Allocate buffer to read one line */ s->mylin = 0; rst = img_buffers_alloc (s, bytesperline); } } } } else rst = SANE_STATUS_COVER_OPEN; } DBG (DBG_FNC, "- sane_start: %i\n", rst); return rst; } SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) { SANE_Status rst = SANE_STATUS_GOOD; TScanner *s = (TScanner *) h; DBG (DBG_FNC, "+ sane_read\n"); if ((s != NULL) && (buf != NULL) && (len != NULL)) { /* nothing has been read at the moment */ *len = 0; /* if we read all the lines return EOF */ if ((s->mylin == s->ScanParams.coords.height) || (device->status->cancel == TRUE)) { rst = (device->status->cancel == TRUE) ? SANE_STATUS_CANCELLED : SANE_STATUS_EOF; RTS_Scanner_StopScan (device, FALSE); img_buffers_free (s); } else { SANE_Int emul_len, emul_maxlen; SANE_Int thwidth, transferred, bufflength; SANE_Byte *buffer, *pbuffer; emul_len = 0; if (s->cnv.depth != -1) emul_maxlen = maxlen * (s->ScanParams.depth / s->cnv.depth); else emul_maxlen = maxlen; /* if grayscale emulation is enabled check that retrieved data is multiple of three */ if (s->cnv.colormode == CM_GRAY) { SANE_Int chn_size, rest; chn_size = (s->ScanParams.depth > 8) ? 2 : 1; rest = emul_maxlen % (3 * chn_size); if (rest != 0) emul_maxlen -= rest; } /* this is important to keep lines alignment in lineart mode */ if (s->cnv.colormode == CM_LINEART) emul_maxlen = s->ScanParams.coords.width; /* if we are emulating depth, we scan at 16bit when frontend waits for 8bit data. Next buffer will be used to retrieve data from scanner prior to convert to 8 bits depth */ buffer = (SANE_Byte *) malloc (emul_maxlen * sizeof (SANE_Byte)); if (buffer != NULL) { pbuffer = buffer; /* get bytes per line */ if (s->ScanParams.colormode != CM_LINEART) { thwidth = s->ScanParams.coords.width * ((s->ScanParams.depth > 8) ? 2 : 1); if (s->ScanParams.colormode == CM_COLOR) thwidth *= 3; /* three channels */ } else thwidth = (s->ScanParams.coords.width + 7) / 8; /* read as many lines the buffer may contain and while there are lines to be read */ while ((emul_len < emul_maxlen) && (s->mylin < s->ScanParams.coords.height)) { /* Is there any data waiting for being passed ? */ if (s->rest_amount != 0) { /* copy to buffer as many bytes as we can */ bufflength = min (emul_maxlen - emul_len, s->rest_amount); memcpy (pbuffer, s->rest, bufflength); emul_len += bufflength; pbuffer += bufflength; s->rest_amount -= bufflength; if (s->rest_amount == 0) s->mylin++; } else { /* read from scanner up to one line */ if (Read_Image (device, bytesperline, s->image, &transferred) != OK) { /* error, exit function */ rst = SANE_STATUS_EOF; break; } /* is there any data? */ if (transferred != 0) { /* copy to buffer as many bytes as we can */ bufflength = min (emul_maxlen - emul_len, thwidth); memcpy (pbuffer, s->image, bufflength); emul_len += bufflength; pbuffer += bufflength; /* the rest will be copied to s->rest buffer */ if (bufflength < thwidth) { s->rest_amount = thwidth - bufflength; memcpy (s->rest, s->image + bufflength, s->rest_amount); } else s->mylin++; } else break; } } /* while */ /* process buffer before sending to frontend */ if ((emul_len > 0) && (rst != SANE_STATUS_EOF)) { /* at this point ... buffer : contains retrieved image emul_len: contains size in bytes of retrieved image after this code ... buf : will contain postprocessed image len : will contain size in bytes of postprocessed image */ /* apply gamma if neccesary */ if (RTS_Debug->EnableGamma == TRUE) gamma_apply (s, buffer, emul_len, s->ScanParams.depth); /* if we are scanning negatives, let's invert colors */ if (s->ScanParams.scantype == ST_NEG) { if (s->cnv.negative == FALSE) Color_Negative (buffer, emul_len, s->ScanParams.depth); } else if (s->cnv.negative != FALSE) Color_Negative (buffer, emul_len, s->ScanParams.depth); /* emulating grayscale ? */ if (s->cnv.colormode == CM_GRAY) { Color_to_Gray (buffer, emul_len, s->ScanParams.depth); emul_len /= 3; } /* emulating depth */ if (s->cnv.depth != -1) { switch (s->cnv.depth) { /* case 1: treated separately as lineart */ /*case 12: in the future */ case 8: Depth_16_to_8 (buffer, emul_len, buffer); emul_len /= 2; break; } } /* lineart mode ? */ if (s->cnv.colormode == CM_LINEART) { /* I didn't see any scanner supporting lineart mode. Windows drivers scan in grayscale and then convert image to lineart so let's perform convertion */ SANE_Int rest = emul_len % 8; Gray_to_Lineart (buffer, emul_len, s->cnv.threshold); emul_len /= 8; if (rest > 0) emul_len++; } /* copy postprocessed image */ *len = emul_len; memcpy (buf, buffer, *len); } free (buffer); } } } else rst = SANE_STATUS_EOF; DBG (DBG_FNC, "- sane_read: %s\n", sane_strstatus (rst)); return rst; } void sane_cancel (SANE_Handle h) { DBG (DBG_FNC, "> sane_cancel\n"); /* silence gcc */ h = h; device->status->cancel = TRUE; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (DBG_FNC, "> sane_set_io_mode\n"); /* silence gcc */ handle = handle; non_blocking = non_blocking; return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (DBG_FNC, "> sane_get_select_fd\n"); /* silence gcc */ handle = handle; fd = fd; return SANE_STATUS_UNSUPPORTED; } void sane_close (SANE_Handle h) { TScanner *scanner = (TScanner *) h; DBG (DBG_FNC, "- sane_close...\n"); /* stop previus scans */ RTS_Scanner_StopScan (device, TRUE); /* close usb */ sanei_usb_close (device->usb_handle); /* free scanner internal variables */ RTS_Scanner_End (device); /* free RTS enviroment */ RTS_Free (device); /* free backend variables */ if (scanner != NULL) { options_free (scanner); img_buffers_free (scanner); } } void sane_exit (void) { /* free device list memory */ if (_pSaneDevList) { TDevListEntry *pDev, *pNext; for (pDev = _pFirstSaneDev; pDev; pDev = pNext) { pNext = pDev->pNext; /* pDev->dev.name is the same pointer that pDev->devname */ free (pDev->devname); free (pDev); } _pFirstSaneDev = NULL; free (_pSaneDevList); _pSaneDevList = NULL; } } sane-backends-1.0.27/backend/hp5400_internal.c0000664000175000017500000011077112775312261015606 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Martijn van Oosterhout Copyright (C) 2003 Thomas Soumarmon Copyright (c) 2003 Henning Meier-Geinitz, Originally copied from HP3300 testtools. Original notice follows: Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. HP5400/5470 Test util. Currently is only able to read back the scanner version string, but this basically demonstrates ability to communicate with the scanner. Massively expanded. Can do calibration scan, upload gamma and calibration tables and stores the results of a scan. - 19/02/2003 Martijn */ #include /* for printf */ #include /* for exit */ #include #include #include #include #include #include /* for htons */ #include #include "hp5400.h" #include "hp5400_xfer.h" #include "hp5400_internal.h" #include "hp5400_debug.h" /* debug functions */ #ifndef min #define min(A,B) (((A)<(B)) ? (A) : (B)) #endif #ifndef max #define max(A,B) (((A)>(B)) ? (A) : (B)) #endif #ifndef STRING_VERSION_MATCH #define NO_STRING_VERSION_MATCH 1 #endif #ifdef __GNUC__ #define PACKED __attribute__ ((packed)) #else #define PACKED #endif /* If this is enabled, a copy of the raw data from the scanner will be saved to imagedebug.dat and the attempted conversion to imagedebug.ppm */ /* #define IMAGE_DEBUG */ /* If this is defined you get extra info on the calibration */ /* #define CALIB_DEBUG */ typedef struct versionString { char strVersion[128]; } versionString; const int numVersions = 3; versionString *MatchVersions; static TScannerModel Model_HP54xx = { "Hewlett-Packard", "HP54xx Flatbed Scanner" }; HP5400_SANE_STATIC int InitHp5400_internal() { MatchVersions = malloc( sizeof(versionString) * numVersions ); strcpy( MatchVersions[0].strVersion, "SilitekIBlizd C3 ScannerV0.84"); strcpy( MatchVersions[1].strVersion, "SilitekIBlizd C3 ScannerV0.86"); strcpy( MatchVersions[2].strVersion, "SilitekIBlizd C3 ScannerV0.87"); return 1; } HP5400_SANE_STATIC int FreeHp5400_internal() { free(MatchVersions); MatchVersions = NULL; return 1; } HP5400_SANE_STATIC int WriteByte (int iHandle, int cmd, char data) { if (hp5400_command_write (iHandle, cmd, 1, &data) < 0) { HP5400_DBG (DBG_MSG, "failed to send byte (cmd=%04X)\n", cmd); return -1; } return 0; } HP5400_SANE_STATIC int SetLamp (THWParams * pHWParams, int fLampOn) { if (fLampOn) { if (WriteByte (pHWParams->iXferHandle, 0x0000, 0x01) == 0) return 0; } return -1; } HP5400_SANE_STATIC int WarmupLamp (int iHandle) { int i = 30; /* Max 30 seconds, 15 is typical for cold start? */ int couldRead; unsigned char dataVerify[0x02]; /* Keep writing 01 to 0000 until no error... */ unsigned char data0000[] = { 0x01 }; unsigned char data0300[3]; hp5400_command_write_noverify (iHandle, 0x0000, data0000, 1); do { hp5400_command_read_noverify (iHandle, 0x0300, 3, data0300); hp5400_command_write_noverify (iHandle, 0x0000, data0000, 1); couldRead = hp5400_command_read_noverify (iHandle, 0xc500, 0x02, dataVerify); if ((dataVerify[0] != 0) || (dataVerify[1] != 0)) sleep (1); } while ((i-- > 0) && (couldRead >= 0) && ((dataVerify[0] != 0) || (dataVerify[1] != 0))); if (i > 0) return 0; /* while( i > 0 ) { if( WriteByte( iHandle, 0x0000, 0x01 ) == 0 ) return 0; sleep(1); i--; } */ HP5400_DBG (DBG_MSG, "***WARNING*** Warmup lamp failed...\n"); return -1; } #define CALPIXBYBLOCK 42 HP5400_SANE_STATIC int SetCalibration (int iHandle, int numPixels, unsigned int *low_vals[3], unsigned int *high_vals[3], int dpi) { char cmd[8]; /* unsigned char cmd[8]; */ /* should fix the compilation warning but I don't have a scanner right now to check that the fix does not break calibration */ int i, j, k; struct CalPixel { char highr[2], highg[2], highb[2]; char lowr[2], lowg[2], lowb[2]; }; struct CalBlock { struct CalPixel pixels[CALPIXBYBLOCK]; char pad[8]; } PACKED; struct CalBlock *calinfo; /** we did scan test at 300 dpi, so we don't have all the needed pixels. To fill the gap, we loop */ int numLoop = max (1, dpi / 300); int calBlockSize = CALPIXBYBLOCK * (6 * sizeof (short)) + 8 * sizeof (char); /* = sizeof(calBlock) */ int numCalBlock = ((numPixels / CALPIXBYBLOCK) + ((numPixels % CALPIXBYBLOCK != 0) ? 1 : 0)); int calSize = numLoop * calBlockSize * numCalBlock; calinfo = malloc (calSize); memset (calinfo, 0, calSize); for (j = 0; j < numLoop * numCalBlock * CALPIXBYBLOCK; j++) { struct CalPixel *pixel = &calinfo[j / CALPIXBYBLOCK].pixels[j % CALPIXBYBLOCK]; /* i = ( j % (int)( 0.80 * numPixels ) ) + (int)(0.10 * numPixels ); */ /* better solution : stretch the actual scan size to the calibration size */ i = j / numLoop; /* This is obviously not quite right. The values on * the right are approximatly what windows sends */ k = (high_vals[0][i] > 0x4000) ? 1000000000 / high_vals[0][i] : 0; /* 0x6700 */ pixel->highr[0] = k; pixel->highr[1] = k >> 8; k = (high_vals[1][i] > 0x4000) ? 1000000000 / high_vals[1][i] : 0; /* 0x5e00 */ pixel->highg[0] = k; pixel->highg[1] = k >> 8; k = (high_vals[2][i] > 0x4000) ? 1000000000 / high_vals[2][i] : 0; /* 0x6000 */ pixel->highb[0] = k; pixel->highb[1] = k >> 8; pixel->lowr[0] = low_vals[0][i]; /* 0x0530 */ pixel->lowr[1] = low_vals[0][i] >> 8; pixel->lowg[0] = low_vals[1][i]; /* 0x0530 */ pixel->lowg[1] = low_vals[1][i] >> 8; pixel->lowb[0] = low_vals[2][i]; /* 0x0530 */ pixel->lowb[1] = low_vals[2][i] >> 8; } cmd[0] = 0xff & (calSize >> 16); cmd[1] = 0xff & (calSize >> 8); cmd[2] = 0xff & (calSize >> 0); cmd[3] = 0x00; cmd[4] = 0x54; cmd[5] = 0x02; cmd[6] = -128; // 0x80; fixes compiler warning (for // signed char implementations), see // also comment above cmd[7] = 0x00; hp5400_bulk_command_write (iHandle, 0xE603, cmd, 8, calSize, calSize, (void *) calinfo); free (calinfo); return 0; } /* Write a gamma table */ HP5400_SANE_STATIC void WriteGammaCalibTable (int iHandle, const int *pabGammaR, const int *pabGammaG, const int *pabGammaB) { char cmd[3]; char *buffer; int i, j; /* Setup dummy gamma correction table */ buffer = malloc (2 * 65536); cmd[0] = 2; cmd[1] = 0; cmd[2] = 0; for (i = 0; i < 3; i++) { const int *ptr = (i == 0) ? pabGammaR : (i == 1) ? pabGammaG : pabGammaB; for (j = 0; j < 65536; j++) { buffer[2 * j] = ptr[j]; buffer[2 * j + 1] = ptr[j] >> 8; } hp5400_bulk_command_write (iHandle, 0x2A01 + i, cmd, 3, 2 * 65536, 65536, (void *) buffer); } free (buffer); return; } #ifdef STANDALONE HP5400_SANE_STATIC void SetDefaultGamma (int iHandle) { int *buffer = malloc (sizeof (int) * 65536); int i; for (i = 0; i < 65336; i++) buffer[i] = i; WriteGammaCalibTable (iHandle, buffer, buffer, buffer); } #endif #define BUFFER_SIZE (6*65536) #ifdef IMAGE_DEBUG FILE *temp; #endif /* Bytes per line is the number of pixels. The actual bytes is one more */ HP5400_SANE_STATIC void CircBufferInit (int iHandle, TDataPipe * p, int iBytesPerLine, int bpp, int iMisAlignment, int blksize, int iTransferSize) { iHandle = iHandle; /* to avoid compilation warning */ p->buffersize = max (BUFFER_SIZE, 3 * blksize); if (p->buffer) { free (p->buffer); } /* Allocate a large enough buffer for transfer */ p->buffer = malloc (p->buffersize); p->pixels = (iBytesPerLine / 3) / bpp; /* These three must always be positive */ p->roff = 0; p->goff = p->pixels * bpp + 1; p->boff = 2 * p->pixels * bpp + 2;; p->linelength = iBytesPerLine + 3; /* NUL at end of each row */ p->bpp = bpp; p->bufstart = p->bufend = 0; if (iMisAlignment > 0) { p->roff += 0; p->goff += p->linelength * iMisAlignment; p->boff += p->linelength * iMisAlignment * 2; } if (iMisAlignment < 0) { p->roff -= p->linelength * iMisAlignment * 2; p->goff -= p->linelength * iMisAlignment; p->boff -= 0; } p->blksize = blksize; p->transfersize = iTransferSize; #ifdef IMAGE_DEBUG temp = fopen ("imagedebug.dat", "w+b"); #endif HP5400_DBG (DBG_MSG, "Begin: line=%d (%X), pixels=%d (%X), r=%d (%X), g=%d (%X), b=%d (%X), bpp=%d, step=%d\n", p->linelength, p->linelength, p->pixels, p->pixels, p->roff, p->roff, p->goff, p->goff, p->boff, p->boff, bpp, iMisAlignment); } HP5400_SANE_STATIC int CircBufferGetLine (int iHandle, TDataPipe * p, void *pabLine) { int i; int maxoff = 0; char* buftmp = (char*) (p->buffer); /* HP5400_DBG(DBG_MSG, "CircBufferGetLine:\n"); */ if (p->roff > maxoff) maxoff = p->roff; if (p->goff > maxoff) maxoff = p->goff; if (p->boff > maxoff) maxoff = p->boff; maxoff += p->pixels * p->bpp; if (maxoff < p->linelength) maxoff = p->linelength; /* resize buffer if needed */ if (p->bufstart + maxoff >= p->buffersize + p->blksize) { /* store actual buffer pointer */ void *tmpBuf = p->buffer; /* calculate new size for buffer (oversize a bit) */ int newsize = p->bufstart + maxoff + 2 * p->blksize; p->buffer = malloc (newsize); memcpy (p->buffer, tmpBuf, p->buffersize); p->buffersize = newsize; /* free old buffer */ free (tmpBuf); buftmp = (char*)(p->buffer); } while (p->bufstart + maxoff >= p->bufend) /* Not enough data in buffer */ { int res; unsigned char cmd[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; cmd[4] = p->blksize; cmd[5] = p->blksize >> 8; assert ((p->bufend + p->blksize) <= p->buffersize); HP5400_DBG (DBG_MSG, "Reading block, %d bytes remain\n", p->transfersize); p->transfersize -= p->blksize; res = hp5400_bulk_read_block (iHandle, CMD_INITBULK3, cmd, sizeof (cmd), buftmp + p->bufend, p->blksize); if (res != p->blksize) { HP5400_DBG (DBG_ERR, "*** ERROR: Read returned %d. FATAL.\n", res); return -1; } #ifdef IMAGE_DEBUG fwrite ( buftmp + p->bufend ,p->blksize ,1 ,temp ); #endif p->bufend += p->blksize; } assert (p->bufstart + maxoff < p->bufend); /* Copy a line into the result buffer */ if (p->bpp == 1) { char *itPix = (char *) pabLine; char *itR = (char *) (buftmp + p->bufstart + p->roff); char *itG = (char *) (buftmp + p->bufstart + p->goff); char *itB = (char *) (buftmp + p->bufstart + p->boff); for (i = 0; i < p->pixels; i++) { /* pointer move goes a little bit faster than vector access */ /* Although I wouldn't be surprised if the compiler worked that out anyway. * No matter, this is easier to read :) */ *(itPix++) = *(itR++); *(itPix++) = *(itG++); *(itPix++) = *(itB++); } } else { short *itPix = (short *) pabLine; short *itR = (short *) (buftmp + p->bufstart + p->roff); short *itG = (short *) (buftmp + p->bufstart + p->goff); short *itB = (short *) (buftmp + p->bufstart + p->boff); for (i = 0; i < p->pixels; i++) { #if 0 /* This code, while correct for PBM is not correct for the host and * since we need it correct for calibration, it has to go */ ((short *) pabLine)[3 * i + 0] = *((short *) (p->buffer + p->bufstart + p->roff + 2 * i)); ((short *) pabLine)[3 * i + 1] = *((short *) (p->buffer + p->bufstart + p->goff + 2 * i)); ((short *) pabLine)[3 * i + 2] = *((short *) (p->buffer + p->bufstart + p->boff + 2 * i)); #else /* pointer move goes a little bit faster than vector access */ *(itPix++) = htons (*(itR++)); *(itPix++) = htons (*(itG++)); *(itPix++) = htons (*(itB++)); #endif } } p->bufstart += p->linelength; assert (p->bufstart <= p->bufend); /* If we've used a whole block at the beginning, move it */ if (p->bufstart > p->blksize) { memmove ( buftmp ,buftmp + p->bufstart ,p->bufend - p->bufstart ); p->bufend -= p->bufstart; p->bufstart = 0; } return 0; } HP5400_SANE_STATIC void CircBufferExit (TDataPipe * p) { free (p->buffer); p->buffer = NULL; #ifdef IMAGE_DEBUG fclose (temp); temp = NULL; #endif return; } #ifdef STANDALONE /* bpp is BYTES per pixel */ HP5400_SANE_STATIC void DecodeImage (FILE * file, int planes, int bpp, int xsize, int ysize, const char *filename) { char *in, *buf; char *p[3]; FILE *output; int i, j, k; /* xsize is byte width, not pixel width */ xsize /= planes * bpp; HP5400_DBG (DBG_MSG, "DecodeImage(planes=%d,bpp=%d,xsize=%d,ysize=%d) => %d (file=%s)\n", planes, bpp, xsize, ysize, planes * bpp * xsize * ysize, filename); in = malloc (planes * (xsize * bpp + 1)); for (i = 0; i < planes; i++) p[i] = in + i * (xsize * bpp + 1); buf = malloc (3 * xsize * bpp); output = fopen (filename, "wb"); fprintf (output, "P%d\n%d %d\n", (planes == 3) ? 6 : 5, xsize, ysize); fprintf (output, "%d\n", (bpp == 1) ? 255 : 0xb000); for (i = 0; i < ysize; i++) { fread (in, planes * (xsize * bpp + 1), 1, file); for (j = 0; j < xsize; j++) { for (k = 0; k < planes; k++) { if (bpp == 1) { buf[j * planes + k] = p[k][j]; } else if (bpp == 2) { buf[j * planes * 2 + k * 2 + 0] = p[k][2 * j + 0]; buf[j * planes * 2 + k * 2 + 1] = p[k][2 * j + 1]; } } } fwrite (buf, planes * xsize * bpp, 1, output); } fclose (output); free (in); free (buf); } HP5400_SANE_STATIC int hp5400_test_scan_response (struct ScanResponse *resp, struct ScanRequest *req) { req = req; /* to avoid compilation warning */ HP5400_DBG (DBG_MSG, "Scan response:\n"); HP5400_DBG (DBG_MSG, " transfersize=%d htonl-> %d\n", resp->transfersize, htonl (resp->transfersize)); HP5400_DBG (DBG_MSG, " xsize=%d htonl-> %d\n", resp->xsize, htonl (resp->xsize)); HP5400_DBG (DBG_MSG, " ysize=%d htons-> %d\n", resp->ysize, htons (resp->ysize)); return 1; } #endif /* This is a very specialised scanning function. It does the scan request as * usual but instead of producing an image it returns three arrays of ints. * These are averages of the R,G,B values for each column. * * Note the array argument should point to an array of three NULL. These * will be overwritten with allocated pointers. */ HP5400_SANE_STATIC int DoAverageScan (int iHandle, struct ScanRequest *req, int code, unsigned int **array) { THWParams HWParams; struct ScanResponse res; unsigned short *buffer; int i, j, k, length; memset (&HWParams, 0, sizeof (HWParams)); HWParams.iXferHandle = iHandle; if (InitScan2 (SCAN_TYPE_CALIBRATION, req, &HWParams, &res, 0, code) != 0) return -1; /* No colour offseting, we want raw */ length = htonl (res.xsize) / 6; HP5400_DBG (DBG_MSG, "Calibration scan: %d pixels wide\n", length); for (j = 0; j < 3; j++) { array[j] = malloc (sizeof (int) * length); memset (array[j], 0, sizeof (int) * length); /* Clear array */ } buffer = malloc (htonl (res.xsize) + 1); /* First we just sum them all */ for (i = 0; i < htons (res.ysize); i++) { CircBufferGetLine (iHandle, &HWParams.pipe, buffer); for (j = 0; j < length; j++) for (k = 0; k < 3; k++) array[k][j] += buffer[3 * j + k]; } free (buffer); FinishScan (&HWParams); /* Now divide by the height to get the average */ for (j = 0; j < length; j++) for (k = 0; k < 3; k++) array[k][j] /= htons (res.ysize); return 0; } #ifdef STANDALONE HP5400_SANE_STATIC int DoScan (int iHandle, struct ScanRequest *req, const char *filename, int code, struct ScanResponse *res) { FILE *file; THWParams HWParams; struct ScanResponse res_temp; void *buffer; /* int bpp, planes; */ int i; code = code; /*to avoid compilation warning*/ if (res == NULL) res = &res_temp; memset (&HWParams, 0, sizeof (HWParams)); file = fopen (filename, "w+b"); if (!file) { HP5400_DBG (DBG_MSG, "Couldn't open outputfile (%s)\n", strerror (errno)); return -1; } HWParams.iXferHandle = iHandle; if (InitScan2 (SCAN_TYPE_NORMAL, req, &HWParams, res, 1, 0x40) != 0) return -1; fprintf (file, "P%d\n%d %d\n", 6, htonl (res->xsize) / 3, htons (res->ysize)); fprintf (file, "%d\n", 255); buffer = malloc (htonl (res->xsize) + 1); for (i = 0; i < htons (res->ysize); i++) { CircBufferGetLine (iHandle, &HWParams.pipe, buffer); fwrite (buffer, htonl (res->xsize), 1, file); } free (buffer); FinishScan (&HWParams); fclose (file); return 0; } #endif HP5400_SANE_STATIC int Calibrate (int iHandle, int dpi) { struct ScanRequest req; unsigned int *low_array[3]; unsigned int *high_array[3]; #ifdef CALIB_DEBUG char buffer[512]; int i, j; #endif /* The first calibration scan. Finds maximum of each CCD */ memset(&req, 0, sizeof(req)); req.x1 = 0x08; req.dpix = htons (300); /* = 300 dpi */ req.dpiy = htons (300); /* = 300 dpi */ req.offx = htons (0); /* = 0cm */ req.offy = htons (0); /* = 0cm */ req.lenx = htons (2690); /* = 22.78cm */ req.leny = htons (50); /* = 0.42cm */ req.flags1 = htons (0x0000); req.flags2 = htons (0x0010); req.flags3 = htons (0x3020); /* First calibration scan, 48bpp */ req.gamma[0] = htons (100); req.gamma[1] = htons (100); req.gamma[2] = htons (100); if (DoAverageScan (iHandle, &req, 0x40, high_array) != 0) return -1; #ifdef CALIB_DEBUG for (i = 0; i < 3; i++) { int len; buffer[0] = 0; sprintf (buffer, "Average %d: \n", i); len = strlen (buffer); for (j = 0; j < 24; j++) { sprintf (buffer + len, "%04X ", high_array[i][j]); len += 5; } strcat (buffer, " ... \n"); len += 6; for (j = 1000; j < 1024; j++) { sprintf (buffer + len, "%04X ", high_array[i][j]); len += 5; } strcat (buffer, " ... \n"); len += 6; for (j = 2000; j < 2024; j++) { sprintf (buffer + len, "%04X ", high_array[i][j]); len += 5; } strcat (buffer, " ... \n"); len += 6; HP5400_DBG (DBG_MSG, buffer); } #endif /* The second calibration scan. Finds minimum of each CCD */ memset(&req, 0, sizeof(req)); req.x1 = 0x08; req.dpix = htons (300); /* = 300 dpi */ req.dpiy = htons (300); /* = 300 dpi */ req.offx = htons (0); /* = 0cm */ req.offy = htons (0); /* = 0cm */ req.lenx = htons (2690); /* = 22.78cm */ req.leny = htons (16); /* = 0.14cm */ req.flags1 = htons (0x0000); req.flags2 = htons (0x0010); req.flags3 = htons (0x3024); /* Second calibration scan, 48bpp */ req.gamma[0] = htons (100); req.gamma[1] = htons (100); req.gamma[2] = htons (100); if (DoAverageScan (iHandle, &req, 0x00, low_array) != 0) return -1; #ifdef CALIB_DEBUG for (i = 0; i < 3; i++) { int len; buffer[0] = 0; sprintf (buffer, "Average %d: \n", i); len = strlen (buffer); for (j = 0; j < 24; j++) { sprintf (buffer + len, "%04X ", low_array[i][j]); len += 5; } strcat (buffer, " ... \n"); len += 6; for (j = 1000; j < 1024; j++) { sprintf (buffer + len, "%04X ", low_array[i][j]); len += 5; } strcat (buffer, " ... \n"); len += 6; for (j = 2000; j < 2024; j++) { sprintf (buffer + len, "%04X ", low_array[i][j]); len += 5; } strcat (buffer, " ... \n"); len += 6; HP5400_DBG (DBG_MSG, buffer); } #endif SetCalibration (iHandle, 2690, low_array, high_array, dpi); return 0; } #ifdef STANDALONE HP5400_SANE_STATIC int hp5400_scan (int iHandle, TScanParams * params, THWParams * pHWParams, const char *filename) { struct ScanRequest req; struct ScanResponse res; int result; pHWParams = pHWParams; /*to avoid compilation warning*/ HP5400_DBG (DBG_MSG, "\n"); HP5400_DBG (DBG_MSG, "Scanning :\n"); HP5400_DBG (DBG_MSG, " dpi(x) : %d\n", params->iDpi); HP5400_DBG (DBG_MSG, " dpi(y) : %d\n", params->iLpi); HP5400_DBG (DBG_MSG, " x0 : %d\n", params->iLeft); HP5400_DBG (DBG_MSG, " y0 : %d\n", params->iTop); HP5400_DBG (DBG_MSG, " width : %d\n", params->iWidth); HP5400_DBG (DBG_MSG, " height : %d\n", params->iHeight); HP5400_DBG (DBG_MSG, "\n"); memset(&req, 0, sizeof(req)); req.x1 = 0x08; req.dpix = htons (params->iDpi); req.dpiy = htons (params->iLpi); /* These offsets and lengths should all be in the reference DPI which * is set to HW_LPI */ req.offx = htons (params->iLeft); req.offy = htons (params->iTop); req.lenx = htons (params->iWidth); req.leny = htons (params->iHeight); req.flags1 = htons (0x0080); req.flags2 = htons (0x0000); req.flags3 = htons ((params->iDpi < 2400) ? 0x18E8 : 0x18C0); /* Try preview scan */ req.gamma[0] = htons (100); req.gamma[1] = htons (100); req.gamma[2] = htons (100); if (Calibrate (iHandle, params->iDpi) != 0) return -1; SetDefaultGamma (iHandle); result = DoScan (iHandle, &req, filename, 0x40, &res); /* Pass the results back to the parent */ params->iBytesPerLine = htonl (res.xsize); params->iLines = htons (res.ysize); #if 0 imageFile = fopen ("output.dat", "r+b"); if (imageFile) { int planes = 3; int bpp = 1; fseek (imageFile, 0, SEEK_SET); DecodeImage (imageFile, planes, bpp, planes * bpp * params->iWidth, params->iHeight, filename); fclose (imageFile); } #endif return result; } HP5400_SANE_STATIC int PreviewScan (int iHandle) { TScanParams params; THWParams pHWParams; /* Reference LPI is 300dpi, remember */ params.iDpi = 75; params.iLpi = 75; params.iLeft = 0; params.iTop = 0; params.iWidth = 2552; /* = 21.61cm * 300dpi */ params.iHeight = 3510; /* = 29.72cm * 300dpi */ params.iColourOffset = 1; return hp5400_scan (iHandle, ¶ms, &pHWParams, "output.ppm"); } static char UISetup1[] = { /* Offset 40 */ 0x50, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6E, 0x67, 0x14, 0x00, 0x52, 0x65, 0x61, 0x64, 0x79, 0x00, 0x53, 0x63, 0x61, 0x6E, 0x6E, 0x65, 0x72, 0x20, 0x4C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x00, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x43, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x69, 0x6E, 0x67, 0x14, 0x00, 0x50, 0x6F, 0x77, 0x65, 0x72, 0x53, 0x61, 0x76, 0x65, 0x20, 0x4F, 0x6E, 0x00, 0x53, }; static char UISetup2[] = { 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x14, 0x00, 0x41, 0x44, 0x46, 0x20, 0x70, 0x61, 0x70, 0x65, 0x72, 0x20, 0x6A, 0x61, 0x6D, 0x00, 0x43, 0x6F, 0x70, 0x69, 0x65, 0x73, 0x00, 0x00, }; HP5400_SANE_STATIC int InitScanner (int iHandle) { WarmupLamp (iHandle); if (WriteByte (iHandle, 0xF200, 0x40) < 0) return -1; if (hp5400_command_write (iHandle, 0xF10B, sizeof (UISetup1), UISetup1) < 0) { HP5400_DBG (DBG_MSG, "failed to send UISetup1 (%lu)\n", (u_long) sizeof (UISetup1)); return -1; } if (WriteByte (iHandle, 0xF200, 0x00) < 0) return -1; if (hp5400_command_write (iHandle, 0xF10C, sizeof (UISetup2), UISetup2) < 0) { HP5400_DBG (DBG_MSG, "failed to send UISetup2\n"); return -1; } return 0; } #endif /* Warning! The caller must have configured the gamma tables at this stage */ HP5400_SANE_STATIC int InitScan (enum ScanType scantype, TScanParams * pParams, THWParams * pHWParams) { struct ScanRequest req; struct ScanResponse res; int ret; memset(&req, 0, sizeof(req)); req.x1 = 0x08; req.dpix = htons (pParams->iDpi); /* = 300 dpi */ req.dpiy = htons (pParams->iLpi); /* = 300 dpi */ req.offx = htons (pParams->iLeft); /* = 0cm */ req.offy = htons (pParams->iTop); /* = 0cm */ req.lenx = htons (pParams->iWidth); /* = 22.78cm */ /* Scan a few extra rows so we can colour offset properly. At 300dpi the * difference is 4 lines */ req.leny = htons (pParams->iHeight); /* = 0.42cm */ req.flags1 = htons ((scantype == SCAN_TYPE_CALIBRATION) ? 0x0000 : 0x0080); req.flags2 = htons ((scantype == SCAN_TYPE_CALIBRATION) ? 0x0010 : (scantype == SCAN_TYPE_PREVIEW) ? 0x0000 : /* SCAN_TYPE_NORMAL */ 0x0040); req.flags3 = htons (0x18E8); req.gamma[0] = htons (100); req.gamma[1] = htons (100); req.gamma[2] = htons (100); if (Calibrate (pHWParams->iXferHandle, pParams->iDpi) != 0) return -1; /* SetDefaultGamma( pHWParams->iXferHandle ); ** Must be done by caller */ HP5400_DBG (DBG_MSG, "Calibration complete\n"); ret = InitScan2 (scantype, &req, pHWParams, &res, pParams->iColourOffset, 0x40); HP5400_DBG (DBG_MSG, "InitScan2 returned %d\n", ret); /* Pass the results back to the parent */ pParams->iBytesPerLine = htonl (res.xsize); /* Hide the extra lines we're scanning */ pParams->iLines = htons (res.ysize); return ret; /* 0 is good, -1 is bad */ } /* For want of a better name ... */ HP5400_SANE_STATIC int InitScan2 (enum ScanType scantype, struct ScanRequest *req, THWParams * pHWParams, struct ScanResponse *result, int iColourOffset, int code) { struct ScanResponse res; int iHandle = pHWParams->iXferHandle; memset(&res, 0, sizeof(res)); /* Protect scanner from damage. This stops stpuid errors. It basically * limits you to the scanner glass. Stuff like calibrations which need * more access do it safely by fiddling other paramters. Note you can * still break things by fiddling the ScanOffset, but that is not yet * under user control */ if (scantype != SCAN_TYPE_CALIBRATION) { HP5400_DBG (DBG_MSG, "Off(%d,%d) : Len(%d,%d)\n", htons (req->offx), htons (req->offy), htons (req->lenx), htons (req->leny)); /* Yes, all the htons() is silly but we want this check as late as possible */ if (htons (req->offx) > 0x09F8) req->offx = htons (0x09F8); if (htons (req->offy) > 0x0DB6) req->offy = htons (0x0DB6); /* These tests are meaningless as htons() returns unsigned if( htons( req->offx ) < 0 ) req->offx = 0; if( htons( req->offy ) < 0 ) req->offy = 0; */ if (htons (req->offx) + htons (req->lenx) > 0x09F8) req->lenx = htons (0x09F8 - htons (req->offx)); if (htons (req->offy) + htons (req->leny) > 0x0DB6) req->leny = htons (0x0DB6 - htons (req->offy)); if (htons (req->lenx) <= 1) return -1; if (htons (req->leny) <= 1) return -1; } WarmupLamp (iHandle); { /* Try to set it to make scan succeed, URB 53 *//* 0x1B01 => 0x40 */ /* I think this tries to cancel any existing scan */ char flag = 0x40; if (hp5400_command_write (iHandle, CMD_STOPSCAN, sizeof (flag), &flag) < 0) { HP5400_DBG (DBG_MSG, "failed to cancel scan flag\n"); return -1; } } { /* Try to set it to make scan succeed, URB 55 */ char data[4] = { 0x02, 0x03, 0x03, 0x3C }; if (hp5400_command_write (iHandle, CMD_UNKNOWN3, sizeof (data), data) < 0) { HP5400_DBG (DBG_MSG, "failed to set unknown1\n"); return -1; } } { /* Try to set it to make scan succeed, URB 59 */ char flag = 0x04; if (hp5400_command_write (iHandle, CMD_UNKNOWN2, sizeof (flag), &flag) < 0) { HP5400_DBG (DBG_MSG, "failed to set unknown2\n"); return -1; } } { /* URB 67 *//* Reference DPI = 300 currently */ short dpi = htons (HW_LPI); if (hp5400_command_write (iHandle, CMD_SETDPI, sizeof (dpi), &dpi) < 0) { HP5400_DBG (DBG_MSG, "failed to set dpi\n"); return -1; } } if (scantype != SCAN_TYPE_CALIBRATION) { /* Setup scan offsets - Should only apply to non-calibration scans */ short offsets[2]; offsets [0] = htons (0x0054); offsets [1] = htons (0x0282); if (hp5400_command_write (iHandle, CMD_SETOFFSET, sizeof (offsets), offsets) < 0) { HP5400_DBG (DBG_MSG, "failed to set offsets\n"); return -1; } } HP5400_DBG (DBG_MSG, "Scan request: \n "); { size_t i; for (i = 0; i < sizeof (*req); i++) { HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) req)[i]); } HP5400_DBG (DBG_MSG, "\n"); } if (hp5400_command_write (iHandle, (scantype != SCAN_TYPE_CALIBRATION) ? CMD_SCANREQUEST2 : CMD_SCANREQUEST, sizeof (*req), req) < 0) { HP5400_DBG (DBG_MSG, "failed to send scan request\n"); return -1; } { /* Try to set it to make scan succeed, URB 71 */ char flag = code; /* Start scan with light on or off as requested */ if (hp5400_command_write (iHandle, CMD_STARTSCAN, sizeof (flag), &flag) < 0) { HP5400_DBG (DBG_MSG, "failed to set gamma flag\n"); return -1; } } if (hp5400_command_read (iHandle, CMD_SCANRESPONSE, sizeof (res), &res) < 0) { HP5400_DBG (DBG_MSG, "failed to read scan response\n"); return -1; } HP5400_DBG (DBG_MSG, "Scan response: \n "); { size_t i; for (i = 0; i < sizeof (res); i++) { HP5400_DBG (DBG_MSG, "%02X ", ((unsigned char *) &res)[i]); } HP5400_DBG (DBG_MSG, "\n"); } HP5400_DBG (DBG_MSG, "Bytes to transfer: %d\nBitmap resolution: %d x %d\n", htonl (res.transfersize), htonl (res.xsize), htons (res.ysize)); HP5400_DBG (DBG_MSG, "Proceeding to scan\n"); if (htonl (res.transfersize) == 0) { HP5400_DBG (DBG_MSG, "Hmm, size is zero. Obviously a problem. Aborting...\n"); return -1; } { char x1 = 0x14, x2 = 0x24; float pixels = ((float) htons (req->lenx) * (float) htons (req->leny)) * ((float) htons (req->dpix) * (float) htons (req->dpiy)) / ((float) HW_LPI * (float) HW_LPI); int bpp = (int) ((float) htonl (res.transfersize) / pixels + 0.5); int planes = (bpp == 1) ? 1 : 3; bpp /= planes; HP5400_DBG (DBG_MSG, "bpp = %d / ( (%d * %d) * (%d * %d) / (%d * %d) ) = %d\n", htonl (res.transfersize), htons (req->lenx), htons (req->leny), htons (req->dpix), htons (req->dpiy), HW_LPI, HW_LPI, bpp); hp5400_command_write_noverify (iHandle, CMD_INITBULK1, &x1, 1); hp5400_command_write_noverify (iHandle, CMD_INITBULK2, &x2, 1); if (bpp > 2) /* Bug!! */ bpp = 2; CircBufferInit (pHWParams->iXferHandle, &pHWParams->pipe, htonl (res.xsize), bpp, iColourOffset, 0xF000, htonl (res.transfersize) + 3 * htons (res.ysize)); } if (result) /* copy ScanResult to parent if they asked for it */ memcpy (result, &res, sizeof (*result)); return 0; } HP5400_SANE_STATIC void FinishScan (THWParams * pHWParams) { int iHandle = pHWParams->iXferHandle; CircBufferExit (&pHWParams->pipe); { /* Finish scan request */ char flag = 0x40; if (hp5400_command_write (iHandle, CMD_STOPSCAN, sizeof (flag), &flag) < 0) { HP5400_DBG (DBG_MSG, "failed to set gamma flag\n"); return; } } } HP5400_SANE_STATIC int HP5400Open (THWParams * params, const char *filename) { int iHandle = hp5400_open (filename); char szVersion[32]; int i; #ifndef NO_STRING_VERSION_MATCH int versionMatched; #endif if (iHandle < 0) { HP5400_DBG (DBG_MSG, "hp5400_open failed\n"); return -1; } params->iXferHandle = 0; /* read version info */ if (hp5400_command_read (iHandle, CMD_GETVERSION, sizeof (szVersion), szVersion) < 0) { HP5400_DBG (DBG_MSG, "failed to read version string\n"); goto hp5400_close_exit; } HP5400_DBG (DBG_MSG, "version String :\n"); for (i=0; i < 32; i++) { HP5400_DBG (DBG_MSG, "%c\n", szVersion[i]); } HP5400_DBG (DBG_MSG, "\n"); #ifndef NO_STRING_VERSION_MATCH i = 0; versionMatched = 0; while ( !versionMatched && (i < numVersions) ) { if (!strncmp (szVersion + 1, MatchVersions[i] .strVersion, strlen(MatchVersions[i] .strVersion) - 4)) { versionMatched = 1; } i++; } if ( !versionMatched ) { HP5400_DBG (DBG_MSG, "Sorry, unknown scanner version. Attempted match on :\n"); i = 0; while ( i < numVersions ) { HP5400_DBG (DBG_MSG, "* '%s'\n", MatchVersions[i] .strVersion); i++; } HP5400_DBG (DBG_MSG, "Version is '%s'\n", szVersion); goto hp5400_close_exit; } #else HP5400_DBG (DBG_MSG, "Warning, Version match is disabled. Version is '%s'\n", szVersion); #endif /* NO_STRING_VERSION_MATCH */ params->iXferHandle = iHandle; /* Start the lamp warming up */ /* No point checking the return value, we don't care anyway */ WriteByte (iHandle, 0x0000, 0x01); /* Success */ return 0; hp5400_close_exit: hp5400_close (iHandle); return -1; } HP5400_SANE_STATIC void HP5400Close (THWParams * params) { hp5400_close (params->iXferHandle); } HP5400_SANE_STATIC int HP5400Detect (const char *filename, int (*_ReportDevice) (TScannerModel * pModel, const char *pszDeviceName)) { int iHandle = hp5400_open (filename); char szVersion[32]; int ret = 0; #ifndef NO_STRING_VERSION_MATCH int versionMatched = 0; int i = 0; #endif if (iHandle < 0) { HP5400_DBG (DBG_MSG, "hp5400_open failed\n"); return -1; } /* read version info */ if (hp5400_command_read (iHandle, CMD_GETVERSION, sizeof (szVersion), szVersion) < 0) { HP5400_DBG (DBG_MSG, "failed to read version string\n"); ret = -1; goto hp5400_close_exit; } #ifndef NO_STRING_VERSION_MATCH i = 0; versionMatched = 0; while ( !versionMatched && (i < numVersions) ) { if (!memcmp (szVersion + 1, MatchVersions[i] .strVersion, strlen (MatchVersions[i] .strVersion) - 4)) { versionMatched = 1; } i++; } if ( !versionMatched ) { HP5400_DBG (DBG_MSG, "Sorry, unknown scanner version. Attempted match on :\n"); i = 0; while ( i < numVersions ) { HP5400_DBG (DBG_MSG, "* '%s'\n", MatchVersions[i] .strVersion); i++; } HP5400_DBG (DBG_MSG, "Version is '%s'\n", szVersion); goto hp5400_close_exit; } #else HP5400_DBG (DBG_MSG, "Warning, Version match is disabled. Version is '%s'\n", szVersion); #endif /* NO_STRING_VERSION_MATCH */ if (_ReportDevice) _ReportDevice (&Model_HP54xx, filename); hp5400_close_exit: hp5400_close (iHandle); return ret; } #ifdef STANDALONE int main (int argc, char *argv[]) { THWParams scanner; assert (sizeof (struct ScanRequest) == 32); assert (sizeof (struct ScanResponse) == 16); hp5400_dbg_start(); HP5400_DBG (DBG_MSG, "HP5400/5470C sample scan utility, by Martijn van Oosterhout \n"); HP5400_DBG (DBG_MSG, "Based on the testutils by Bertrik Sikken (bertrik@zonnet.nl)\n"); if ((argc == 6) && (!strcmp (argv[1], "-decode"))) { int width = atoi (argv[3]); int height = atoi (argv[4]); FILE *temp = fopen (argv[2], "r+b"); if (temp) { int planes = 3; int bpp = 1; fseek (temp, 0, SEEK_SET); DecodeImage (temp, planes, bpp, planes * bpp * width, height, argv[5]); fclose (temp); } return 1; } if (HP5400Open (&scanner, NULL) < 0) { return 1; } PreviewScan (scanner.iXferHandle); HP5400Close (&scanner); fprintf (stderr, "Note: output is in output.ppm\n"); return 0; } #endif sane-backends-1.0.27/backend/plustek-pp_detect.c0000664000175000017500000003346712775277260016445 00000000000000/* @file plustek-pp_detect.c * @brief automatic scanner detection * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - no changes * - 0.33 - added portmode check * - 0.34 - no changes * - 0.35 - no changes * - 0.36 - added some debug messages * - replace the old _OUTB/_INB macros * - 0.37 - cosmetic changes * - added speed-test for the parallel-port * - 0.38 - added P12 stuff - replaced detectP9636 by detectAsic9800x * - added detectResetPort() function * - 0.39 - fixed problem in ASIC9800x detection * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - cleanup * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /************************** local definitions ********************************/ /*************************** local functions *********************************/ /** as the name says... */ static void detectResetPort( pScanData ps ) { UChar control; DBG( DBG_HIGH, "ResetPort()\n" ); control = _INB_CTRL( ps ); _DO_UDELAY( 2 ); _OUTB_CTRL( ps, _CTRL_RESERVED ); /* reset, 0xc0 */ _DO_UDELAY( 2 ); _OUTB_CTRL( ps, control ); /* and restore... */ _DO_UDELAY( 2 ); } /** Check: will the status port changed between printer/scanner path changed? * Write out data and read in to compare */ static int detectScannerConnection( pScanData ps ) { UChar data, control, status; int retval = _E_NO_CONN; #ifdef __KERNEL__ DBG( DBG_LOW, "Dataport = 0x%04x\n", ps->IO.pbSppDataPort ); DBG( DBG_LOW, "Ctrlport = 0x%04x\n", ps->IO.pbControlPort ); #endif detectResetPort( ps ); /* * as we're called during InitPorts, we can be sure * to operate in EPP-mode (hopefuly ;-) */ control = _INB_CTRL( ps ); /* * go ahead and do some checks */ _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); _DO_UDELAY( 5 ); _OUTB_DATA( ps, 0x55 ); _DO_UDELAY( 5 ); data = _INB_DATA( ps ); if (0x55 == data) { DBG( DBG_HIGH, "Test 0x55\n" ); _OUTB_DATA( ps, 0xAA ); _DO_UDELAY( 5 ); data = _INB_DATA( ps ); if (0xAA == data) { DBG( DBG_HIGH, "Test 0xAA\n" ); _OUTB_DATA( ps, 0x0 ); _DO_UDELAY( 5 ); data = _INB_STATUS( ps ); ps->OpenScanPath( ps ); _OUTB_DATA( ps, 0x0 ); _DO_UDELAY( 5 ); status = _INB_STATUS( ps ); ps->CloseScanPath( ps ); /* * so we're done 'til now... */ DBG( DBG_HIGH, "Compare data=0x%x and status=0x%x, port=0x%x\n", data, status, ps->IO.portBase ); if( data != status ) { _ASSERT( ps->ReadWriteTest ); /* * here we try to detect the operation speed of our parallel * port if we have tested all the stuff and had no success, * retval will contain the error-code */ for( ps->IO.delay = 0; ps->IO.delay < 5; ps->IO.delay++ ) { retval = ps->ReadWriteTest( ps ); /* break on OK or when the ASIC detection fails */ if((_OK == retval) || (_E_NO_ASIC == retval)) break; } } } } /* work on the result */ if ( _OK == retval ) { #ifdef __KERNEL__ ps->sCaps.wIOBase = ps->IO.pbSppDataPort; #else ps->sCaps.wIOBase = ps->pardev; #endif ps->PutToIdleMode( ps ); } else { ps->sCaps.wIOBase = _NO_BASE; } /* * restore control port value */ _OUTB_CTRL( ps, control ); _DO_UDELAY( 5 ); DBG( DBG_HIGH, "detectScannerConnection() returns %i.\n", retval ); return retval; } /** we need some memory... */ static int detectSetupBuffers( pScanData ps ) { DBG( DBG_LOW, "*** setupBuffers ***\n" ); /* bad news ? */ if ( 0 == ps->TotalBufferRequire ) { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "pt_drv: asic 0x%x probably not supported\n", ps->sCaps.AsicID); return _E_ALLOC; /* Out of memory */ } else { /* * allocate and clear */ DBG(DBG_LOW,"Driverbuf(%u bytes) needed !\n", ps->TotalBufferRequire); ps->driverbuf = (pUChar)_VMALLOC(ps->TotalBufferRequire); if ( NULL == ps->driverbuf ) { #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "pt_drv: Not enough kernel memory %d\n", ps->TotalBufferRequire); return _E_ALLOC; /* Out of memory */ } memset( ps->driverbuf, 0, ps->TotalBufferRequire ); } ps->pPrescan16 = ps->driverbuf; ps->pPrescan8 = ps->pPrescan16 + ps->BufferFor1stColor; ps->pScanBuffer1 = ps->pPrescan8 + ps->BufferFor2ndColor; /* CHECK: Should we adjust that !!! */ ps->pEndBufR = ps->pPrescan8; ps->pEndBufG = ps->pScanBuffer1; ps->pColorRunTable = ps->pScanBuffer1 + ps->BufferForDataRead1; DBG( DBG_LOW, "pColorRunTab = 0x%0lx - 0x%0lx\n", (unsigned long)ps->pColorRunTable, (unsigned long)((pUChar)ps->driverbuf + ps->TotalBufferRequire)); if ( _ASIC_IS_98001 == ps->sCaps.AsicID ) { DBG( DBG_LOW, "Adjust for 98001 ASIC\n" ); ps->pScanBuffer2 = ps->pPrescan16; ps->pScanBuffer1 = ps->pScanBuffer2 + _LINE_BUFSIZE1; ps->pColorRunTable = ps->pScanBuffer1 + _LINE_BUFSIZE * 2UL; ps->pProcessingBuf = ps->pColorRunTable + ps->BufferForColorRunTable; DBG( DBG_LOW, "sb2 = 0x%lx, sb1 = 0x%lx, Color = 0x%lx\n", (unsigned long)ps->pScanBuffer2, (unsigned long)ps->pScanBuffer1, (unsigned long)ps->pColorRunTable ); DBG( DBG_LOW, "Pro = 0x%lx, size = %d\n", (unsigned long)ps->pProcessingBuf, ps->TotalBufferRequire ); ps->dwShadow = (_DEF_BRIGHTEST_SKIP + _DEF_DARKEST_SKIP) * 5400UL * 2UL * 3UL; ps->Shade.pHilight = _VMALLOC( ps->dwShadow ); if ( NULL != ps->Shade.pHilight ) { memset( ps->Shade.pHilight, 0, ps->dwShadow ); ps->dwHilight = _DEF_BRIGHTEST_SKIP * 5400UL * 3UL; ps->dwShadow = _DEF_DARKEST_SKIP * 5400UL * 3UL; ps->pwShadow = (pUShort)ps->Shade.pHilight + ps->dwHilight; ps->Shade.dwDiv = 32UL - _DEF_BRIGHTEST_SKIP - _DEF_DARKEST_SKIP; ps->dwHilightCh = ps->dwHilight / 3UL; ps->dwShadowCh = ps->dwShadow / 3UL; } } else if ( _ASIC_IS_98003 == ps->sCaps.AsicID ) { DBG( DBG_LOW, "Adjust for 98003 ASIC\n" ); ps->Bufs.b1.pReadBuf = ps->driverbuf; ps->Bufs.b2.pSumBuf = ps->Bufs.b1.pReadBuf + _SizeDataBuf; ps->Bufs.TpaBuf.pb = &((pUChar)ps->Bufs.b2.pSumBuf)[_SizeShadingSumBuf]; /* CHECK: We might should play around with these values... */ ps->Shade.skipHilight = _DEF_BRIGHTEST_SKIP; ps->Shade.skipShadow = _DEF_DARKEST_SKIP; if( ps->Shade.skipHilight && ps->Shade.skipShadow ) { ULong skipSize; skipSize = (ULong)((ps->Shade.skipHilight + ps->Shade.skipShadow) * _SizeDataBuf * 3); ps->Shade.pHilight = _VMALLOC( skipSize ); if( NULL != ps->Shade.pHilight ) { ps->Shade.dwDiv = (ULong)(32UL - ps->Shade.skipHilight - ps->Shade.skipShadow); } } else ps->Shade.pHilight = NULL; } return _OK; } /** model 48xx detection or any other model using the 96001/3 ASIC */ static int detectP48xx( pScanData ps ) { int result; DBG( DBG_LOW, "************ DETECTP48xx ************\n" ); /* increase the delay-time */ ps->IO.delay = 4; ModelSet4800( ps ); result = P48xxInitAsic( ps ); if( _OK != result ) return result; return detectScannerConnection( ps ); } /** ASIC 98003 model detection */ static int detectAsic98003( pScanData ps ) { int result; DBG( DBG_LOW, "************* ASIC98003 *************\n" ); /* increase the delay-time */ ps->IO.delay = 4; ModelSetP12( ps ); result = P12InitAsic( ps ); if( _OK != result ) return result; IOSoftwareReset( ps ); return detectScannerConnection( ps ); } /** ASIC 98001 model detection */ static int detectAsic98001( pScanData ps ) { int result; DBG( DBG_LOW, "************* ASIC98001 *************\n" ); /* increase the delay-time */ ps->IO.delay = 4; ModelSet9636( ps ); result = P9636InitAsic( ps ); #ifndef _ASIC_98001_SIM if( _OK != result ) return result; return detectScannerConnection( ps ); #else #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "!!!! WARNING, have a look at function detectAsic98001() !!!!\n" ); ps->sCaps.AsicID = _ASIC_IS_98001; ps->sCaps.wIOBase = ps->IO.pbSppDataPort; return _OK; #endif } /************************ exported functions *********************************/ /** here we try to find the scanner, depending on the mode */ _LOC int DetectScanner( pScanData ps, int mode ) { Byte asic; int result = _E_INTERNAL; /* * before doing anything else, check the port-mode */ if((ps->IO.portMode != _PORT_EPP) && (ps->IO.portMode != _PORT_SPP) && (ps->IO.portMode != _PORT_BIDI)) { DBG( DBG_LOW, "!!! Portmode (%u)not supported !!!\n", ps->IO.portMode ); return _E_INTERNAL; } /* autodetection ? */ if( 0 == mode ) { DBG( DBG_HIGH, "Starting Scanner-Autodetection\n" ); /* try to find a 48xx Scanner * (or even a scanner based on the 96001/3) ASIC */ result = detectP48xx( ps ); if( _OK != result ) { DBG( DBG_LOW, "************* ASIC9800x *************\n" ); /* get the ASIC ID by using the OpenScanPath stuff from Asic9600x based * models - only difference: change the ReadHigh/ReadLow signals before */ ps->CtrlReadHighNibble = _CTRL_GENSIGNAL+_CTRL_AUTOLF+_CTRL_STROBE; ps->CtrlReadLowNibble = _CTRL_GENSIGNAL+_CTRL_AUTOLF; /* read Register 0x18 (AsicID Register) of Asic9800x based devices */ #ifdef _ASIC_98001_SIM #ifdef __KERNEL__ _PRINT( #else DBG( DBG_HIGH, #endif "!!!! WARNING, SW-Emulation active !!!!\n" ); asic = _ASIC_IS_98001; #else detectResetPort( ps ); /* do some presettings to make IODataRegisterFromScanner() work */ ps->RegAsicID = 0x18; ps->IO.useEPPCmdMode = _FALSE; ps->sCaps.AsicID = _ASIC_IS_98001; IOInitialize( ps ); asic = IODataRegisterFromScanner( ps, ps->RegAsicID ); DBG( DBG_HIGH, "ASIC = 0x%02X\n", asic ); #endif /* depending on what we have found, perform some extra tests */ switch( asic ) { case _ASIC_IS_98001: result = detectAsic98001( ps ); break; case _ASIC_IS_98003: /* as the reading of the ASIC ID causes trouble, * we reset the device */ ps->IO.useEPPCmdMode = _FALSE; ps->sCaps.AsicID = _ASIC_IS_98003; IOInitialize( ps ); IOSoftwareReset( ps ); result = detectAsic98003( ps ); break; default: DBG( DBG_HIGH, "Unknown ASIC-ID\n" ); result = _E_NO_DEV; break; } } } else { /* this will be called each time before operating on a previously * detected device, to make sure we are still operating on the same one */ if( _ASIC_IS_98001 == mode ) { DBG( DBG_HIGH, "Starting Scanner-detection (ASIC 98001)\n" ); result = detectAsic98001( ps ); } else if( _ASIC_IS_98003 == mode ) { DBG( DBG_HIGH, "Starting Scanner-detection (ASIC 98003)\n" ); result = detectAsic98003( ps ); } else { DBG( DBG_HIGH, "Starting Scanner-detection (ASIC 96001/3)\n" ); result = detectP48xx( ps ); } } if( _OK == result ) { _ASSERT( ps->SetupScannerVariables ); ps->SetupScannerVariables( ps ); detectSetupBuffers( ps ); } else { /* CHECK - we should not need that anymore - paranoia code ??!!!! */ ps->sCaps.wIOBase = _NO_BASE; } DBG( DBG_LOW, "*** DETECTION DONE, result: %i ***\n", result ); return result; } /* END PLUSTEK-PP_DETECT.C ..................................................*/ sane-backends-1.0.27/backend/canon-scsi.c0000664000175000017500000004252412775312260015026 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 BYTEC GmbH Germany Written by Helmut Koeberle, Email: helmut.koeberle@bytec.de Modified by Manuel Panea and Markus Mertinat This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* This file implements the low-level scsi-commands. */ static SANE_Status test_unit_ready (int fd) { static u_char cmd[6]; int status; DBG (31, ">> test_unit_ready\n"); memset (cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (31, "<< test_unit_ready\n"); return (status); } #ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS static SANE_Status request_sense (int fd, void *buf, size_t *buf_size) { static u_char cmd[6]; int status; DBG (31, ">> request_sense\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x03; cmd[4] = 14; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< request_sense\n"); return (status); } #endif static SANE_Status inquiry (int fd, int evpd, void *buf, size_t *buf_size) { static u_char cmd[6]; int status; DBG (31, ">> inquiry\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x12; cmd[1] = evpd; cmd[2] = evpd ? 0xf0 : 0; cmd[4] = evpd ? 74 : 36; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< inquiry\n"); return (status); } #ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS static SANE_Status mode_select (int fd) { static u_char cmd[6 + 12]; int status; DBG (31, ">> mode_select\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x15; cmd[1] = 16; cmd[4] = 12; cmd[6 + 4] = 3; cmd[6 + 5] = 6; cmd[6 + 8] = 0x02; cmd[6 + 9] = 0x58; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), NULL, NULL); DBG (31, "<< mode_select\n"); return (status); } #endif static SANE_Status reserve_unit (int fd) { static u_char cmd[6]; int status; DBG (31, ">> reserve_unit\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x16; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (31, "<< reserve_unit\n"); return (status); } #ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS static SANE_Status release_unit (int fd) { static u_char cmd[6]; int status; DBG (31, ">> release_unit\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x17; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (31, "<< release_unit\n"); return (status); } #endif static SANE_Status mode_sense (int fd, void *buf, size_t *buf_size) { static u_char cmd[6]; int status; DBG (31, ">> mode_sense\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x1a; cmd[2] = 3; cmd[4] = 12; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< mode_sense\n"); return (status); } static SANE_Status scan (int fd) { static u_char cmd[6 + 1]; int status; DBG (31, ">> scan\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x1b; cmd[4] = 1; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), NULL, NULL); DBG (31, "<< scan\n"); return (status); } static SANE_Status send_diagnostic (int fd) { static u_char cmd[6]; int status; DBG (31, ">> send_diagnostic\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x1d; cmd[1] = 4; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (31, "<< send_diagnostic\n"); return (status); } static SANE_Status set_window (int fd, void *data) { static u_char cmd[10]; int status; DBG (31, ">> set_window\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x24; cmd[8] = 72; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), data, 72, NULL, NULL); DBG (31, "<< set_window\n"); return (status); } static SANE_Status get_window (int fd, void *buf, size_t *buf_size) { static u_char cmd[10]; int status; DBG (31, ">> get_window\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x25; cmd[1] = 1; cmd[8] = 72; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get_window\n"); return (status); } static SANE_Status read_data (int fd, void *buf, size_t *buf_size) { static u_char cmd[10]; int status; DBG (31, ">> read_data\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x28; cmd[6] = *buf_size >> 16; cmd[7] = *buf_size >> 8; cmd[8] = *buf_size; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< read_data\n"); return (status); } static SANE_Status medium_position (int fd) { static u_char cmd[10]; int status; DBG (31, ">> medium_position\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x31; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (31, "<< medium_position\n"); return (status); } #ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS static SANE_Status execute_shading (int fd) { static u_char cmd[10]; int status; DBG (31, ">> execute shading\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xe2; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (31, "<< execute shading\n"); return (status); } #endif static SANE_Status execute_auto_focus (int fd, int AF, int speed, int AE, int count) { static u_char cmd[10]; int status; DBG (7, ">> execute_auto_focus\n"); DBG (7, ">> focus: mode='%d', speed='%d', AE='%d', count='%d'\n", AF, speed, AE, count); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xe0; cmd[1] = (u_char) AF; cmd[2] = (u_char) ((speed << 7) | AE); #if 1 cmd[4] = (u_char) count; /* seems to work, but may be unsafe */ #else /* The Canon software uses this: */ cmd[4] = (u_char) (28 * ((int) (count / 28.5)) + 16); #endif status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (7, "<< execute_auto_focus\n"); return (status); } static SANE_Status set_adf_mode (int fd, u_char priority) { static u_char cmd[6]; int status; memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xd4; cmd[4] = 0x01; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), &priority, 1, NULL, NULL); return (status); } static SANE_Status get_scan_mode (int fd, u_char page, void *buf, size_t *buf_size) { static u_char cmd[6]; int status; int PageLen = 0x00; memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xd5; cmd[2] = page; switch (page) { case AUTO_DOC_FEEDER_UNIT: case TRANSPARENCY_UNIT: cmd[4] = 0x0c + PageLen; break; case SCAN_CONTROL_CONDITIONS: cmd[4] = 0x14 + PageLen; break; case SCAN_CONTROL_CON_FB1200: cmd[2] = 0x20; cmd[4] = 0x17 + PageLen; break; default: cmd[4] = 0x24 + PageLen; break; } DBG (31, "get scan mode: cmd[4]='0x%0X'\n", cmd[4]); status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get scan mode\n"); return (status); } static SANE_Status define_scan_mode (int fd, u_char page, void *data) { static u_char cmd[6]; u_char pdata[36]; size_t i; int status, pdatalen; DBG (31, ">> define scan mode\n"); memset (cmd, 0, sizeof (cmd)); memset (pdata, 0, sizeof (pdata)); cmd[0] = 0xd6; cmd[1] = 0x10; cmd[4] = (page == TRANSPARENCY_UNIT) ? 0x0c : (page == TRANSPARENCY_UNIT_FB1200) ? 0x0c : (page == SCAN_CONTROL_CONDITIONS) ? 0x14 : (page == SCAN_CONTROL_CON_FB1200) ? 0x17 : 0x24; memcpy (pdata + 4, data, (page == TRANSPARENCY_UNIT) ? 8 : (page == TRANSPARENCY_UNIT_FB1200) ? 10 : (page == SCAN_CONTROL_CONDITIONS) ? 16 : (page == SCAN_CONTROL_CON_FB1200) ? 19 : 32); for (i = 0; i < sizeof (cmd); i++) DBG (31, "define scan mode: cmd[%d]='0x%0X'\n", (int) i, cmd[i]); for (i = 0; i < sizeof (pdata); i++) DBG (31, "define scan mode: pdata[%d]='0x%0X'\n", (int) i, pdata[i]); pdatalen = (page == TRANSPARENCY_UNIT) ? 12 : (page == TRANSPARENCY_UNIT_FB1200) ? 14 : (page == SCAN_CONTROL_CONDITIONS) ? 20 : (page == SCAN_CONTROL_CON_FB1200) ? 23 : 36; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), pdata, pdatalen, NULL, NULL); DBG (31, "<< define scan mode\n"); return (status); } static SANE_Status get_density_curve (int fd, int component, void *buf, size_t *buf_size, int transfer_data_type) { static u_char cmd[10]; int status; DBG (31, ">> get_density_curve\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x28; cmd[2] = transfer_data_type; cmd[4] = component; cmd[5] = 0; cmd[6] = ((*buf_size) >> 16) & 0xff; cmd[7] = ((*buf_size) >> 8) & 0xff; cmd[8] = (*buf_size) & 0xff; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get_density_curve\n"); return (status); } #ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS static SANE_Status get_density_curve_data_format (int fd, void *buf, size_t *buf_size) { static u_char cmd[10]; int status; DBG (31, ">> get_density_curve_data_format\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x28; cmd[2] = 0x03; cmd[4] = 0xff; cmd[5] = 0; cmd[6] = 0; cmd[7] = 0; cmd[8] = 14; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get_density_curve_data_format\n"); return (status); } #endif static SANE_Status set_density_curve (int fd, int component, void *buf, size_t *buf_size, int transfer_data_type) { static u_char cmd[10]; int status; DBG (31, ">> set_density_curve\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x2a; cmd[2] = transfer_data_type; cmd[4] = component; cmd[5] = 0; cmd[6] = ((*buf_size) >> 16) & 0xff; cmd[7] = ((*buf_size) >> 8) & 0xff; cmd[8] = (*buf_size) & 0xff; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), buf, *buf_size, NULL, NULL); DBG (31, "<< set_density_curve\n"); return (status); } /* static SANE_Status */ /* set_density_curve_data_format (int fd, void *buf, size_t *buf_size) */ /* { */ /* static u_char cmd[10]; */ /* int status, i; */ /* DBG (31, ">> set_density_curve_data_format\n"); */ /* memset (cmd, 0, sizeof (cmd)); */ /* cmd[0] = 0x2a; */ /* cmd[2] = 0x03; */ /* cmd[4] = 0xff; */ /* cmd[5] = 0; */ /* cmd[6] = 0; */ /* cmd[7] = 0; */ /* cmd[8] = 14; */ /* status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); */ /* DBG (31, "<< set_density_curve_data_format\n"); */ /* return (status); */ /* } */ #ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS static SANE_Status get_power_on_timer (int fd, void *buf, size_t *buf_size) { static u_char cmd[10]; int status; DBG (31, ">> get power on timer\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xe3; cmd[6] = 1; cmd[7] = 0; cmd[8] = 0; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get power on timer\n"); return (status); } #endif static SANE_Status get_film_status (int fd, void *buf, size_t *buf_size) { static u_char cmd[10]; int status; DBG (31, ">> get film status\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xe1; cmd[6] = 0; cmd[7] = 0; cmd[8] = 4; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get film status\n"); return (status); } static SANE_Status get_data_status (int fd, void *buf, size_t *buf_size) { static u_char cmd[10]; int status; DBG (31, ">> get_data_status\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0x34; cmd[8] = 28; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get_data_status\n"); return (status); } /*************** modification for FB620S ***************/ static SANE_Status reset_scanner (int fd) { static u_char cmd[6]; int status; DBG (31, ">> reset_scanner\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xc1; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (31, "<< reset_scanner \n"); return (status); } static SANE_Status execute_calibration (int fd) { static u_char cmd[6]; u_char data[2]; int status; DBG (31, ">> execute_calibration\n"); memset (cmd, 0, sizeof (cmd)); memset (data, 0, sizeof (data)); cmd[0] = 0xc2; cmd[4] = 2; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), data, sizeof (data), NULL, NULL); DBG (31, "<< execute_calibration\n"); return (status); } static SANE_Status get_calibration_status (int fd, void *buf, size_t *buf_size) { static u_char cmd[6]; int status; DBG (31, ">> get_calibration_status\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xc3; cmd[4] = *buf_size; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get_calibration_status\n"); return (status); } #if 0 static SANE_Status get_switch_status (int fd, void *buf, size_t *buf_size) { static u_char cmd[6]; int status; DBG (31, ">> get_switch_status\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xc4; cmd[4] = 2; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size); DBG (31, "<< get_switch_status\n"); return (status); } static SANE_Status wait_ready(int fd) { SANE_Status status; int retry = 0; while ((status = test_unit_ready (fd)) != SANE_STATUS_GOOD) { DBG(5, "wait_ready failed (%d)\n", retry); if (retry++ > 15) return SANE_STATUS_IO_ERROR; sleep(3); } return(status); } #endif /*************** modification for FB1200S ***************/ static SANE_Status cancel (int fd) { static u_char cmd[10]; int status; DBG (31, ">> cancel_FB1200S\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = 0xe4; status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL); DBG (31, "<< cancel_FB1200S \n"); return (status); } /**************************************************************************/ /* As long as we do not know how this scanner stores its density curves, we do the gamma correction with a 8 <--> 12 bit translation table stored in the CANON_Scanner structure. */ static SANE_Status get_density_curve_fs2710 (SANE_Handle handle, int component, u_char *buf, size_t *buf_size) { CANON_Scanner *s = handle; int i; for (i = 0; i < 256; i++) *buf++ = s->gamma_map[component][i << 4]; *buf_size = 256; return (SANE_STATUS_GOOD); } static SANE_Status set_density_curve_fs2710 (SANE_Handle handle, int component, u_char *buf) { CANON_Scanner *s = handle; int i, j, hi, lo; u_char *p; for (i = 1, hi = *buf++, p = &s->gamma_map[component][0]; i <= 256; i++) { lo = hi; hi = (i < 256) ? *buf++ : 2 * *(buf - 1) - *(buf - 2); if (hi > 255) hi = 255; for (j = 0; j < 16; j++) /* do a linear interpolation */ *p++ = (u_char) (lo + ((double) ((hi - lo) * j)) / 16.0 + 0.5); } return (SANE_STATUS_GOOD); } static SANE_Status set_parameters_fs2710 (SANE_Handle handle) { CANON_Scanner *s = handle; int i, j, shadow[4], hilite[4]; double x, b, c; shadow[1] = s->ShadowR << 4; shadow[2] = s->ShadowG << 4; shadow[3] = s->ShadowB << 4; hilite[1] = s->HiliteR << 4; hilite[2] = s->HiliteG << 4; hilite[3] = s->HiliteB << 4; c = ((double) s->contrast) / 128.0; b = ((double) (s->brightness - 128)) / 128.0; for (i = 1; i < 4; i++) { for (j = 0; j < 4096; j++) { if (j <= shadow[i]) s->gamma_map[i][j] = (u_char) ((s->brightness >= 128) ? 2 * s->brightness - 256 : 0); else if (j < hilite[i]) { x = ((double) (j - shadow[i])) / ((double) (hilite[i] - shadow[i])); /* first do the contrast correction */ x = (x <= 0.5) ? 0.5 * pow (2 * x, c) : 1.0 - 0.5 * pow (2 * (1.0 - x), c); x = pow (x, 0.5); /* default gamma correction */ x += b; /* brightness correction */ s->gamma_map[i][j] = (u_char) MAX (0, MIN (255, (int) (255.0 * x))); } else s->gamma_map[i][j] = (u_char) ((s->brightness >= 128) ? 255 : 2 * s->brightness); } } return (SANE_STATUS_GOOD); } /**************************************************************************/ sane-backends-1.0.27/backend/net.h0000664000175000017500000000571212112021330013536 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang Copyright (C) 2003 Julien BLACHE AF-independent code + IPv6 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef net_h #define net_h #include #include #include "../include/sane/sanei_wire.h" #include "../include/sane/config.h" typedef struct Net_Device { struct Net_Device *next; const char *name; #if defined (HAVE_GETADDRINFO) && defined (HAVE_GETNAMEINFO) struct addrinfo *addr; struct addrinfo *addr_used; #else struct sockaddr addr; #endif /* HAVE_GETADDRINFO && HAVE_GETNAMEINFO */ int ctl; /* socket descriptor (or -1) */ Wire wire; int auth_active; } Net_Device; typedef struct Net_Scanner { /* all the state needed to define a scan request: */ struct Net_Scanner *next; int options_valid; /* are the options current? */ SANE_Option_Descriptor_Array opt, local_opt; SANE_Word handle; /* remote handle (it's a word, not a ptr!) */ int data; /* data socket descriptor */ int reclen_buf_offset; u_char reclen_buf[4]; size_t bytes_remaining; /* how many bytes left in this record? */ /* device (host) info: */ Net_Device *hw; } Net_Scanner; #endif /* net_h */ sane-backends-1.0.27/backend/kodak.conf.in0000664000175000017500000000055712112021330015146 00000000000000# NOTE: any 'option' lines only apply to # scanners discovered later in this file # to set data buffer size, in bytes # the value ranges from 4096 - infinity # but you may have scanning problems with # a value larger than 32768 (the default) option buffer-size 32768 # To search for all KODAK scsi devices scsi KODAK # To use a specific scsi device #scsi /dev/sg1 sane-backends-1.0.27/backend/hp-scl.h0000664000175000017500000001656012112021330014141 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ #ifndef HP_SCL_INCLUDED #define HP_SCL_INCLUDED #define HP_SCL_PACK(id, group, char) \ ((SANE_Word)(id) << 16 | ((group) & 0xFF) << 8 | ((char) & 0xFF)) #define SCL_INQ_ID(code) ((code) >> 16) #define SCL_GROUP_CHAR(code) ((char)(((code) >> 8) & 0xFF)) #define SCL_PARAM_CHAR(code) ((char)((code) & 0xFF)) #define HP_SCL_CONTROL(id,g,c) HP_SCL_PACK(id,g,c) #define HP_SCL_COMMAND(g,c) HP_SCL_PACK(0,g,c) #define HP_SCL_PARAMETER(id) HP_SCL_PACK(id, 0, 0) #define HP_SCL_DATA_TYPE(id) HP_SCL_PACK(id, 1, 0) #define IS_SCL_CONTROL(scl) (SCL_INQ_ID(scl) && SCL_PARAM_CHAR(scl)) #define IS_SCL_COMMAND(scl) (!SCL_INQ_ID(scl) && SCL_PARAM_CHAR(scl)) #define IS_SCL_PARAMETER(scl) (SCL_INQ_ID(scl) && !SCL_PARAM_CHAR(scl)) #define IS_SCL_DATA_TYPE(scl) (SCL_GROUP_CHAR(scl) == '\001') #define SCL_AUTO_BKGRND HP_SCL_CONTROL(10307, 'a', 'B') #define SCL_COMPRESSION HP_SCL_CONTROL(10308, 'a', 'C') #define SCL_DOWNLOAD_TYPE HP_SCL_CONTROL(10309, 'a', 'D') #define SCL_X_SCALE HP_SCL_CONTROL(10310, 'a', 'E') #define SCL_Y_SCALE HP_SCL_CONTROL(10311, 'a', 'F') #define SCL_DATA_WIDTH HP_SCL_CONTROL(10312, 'a', 'G') #define SCL_INVERSE_IMAGE HP_SCL_CONTROL(10314, 'a', 'I') #define SCL_BW_DITHER HP_SCL_CONTROL(10315, 'a', 'J') #define SCL_CONTRAST HP_SCL_CONTROL(10316, 'a', 'K') #define SCL_BRIGHTNESS HP_SCL_CONTROL(10317, 'a', 'L') #define SCL_MIRROR_IMAGE HP_SCL_CONTROL(10318, 'a', 'M') #define SCL_SHARPENING HP_SCL_CONTROL(10319, 'a', 'N') #define SCL_RESERVED1 HP_SCL_CONTROL(10320, 'a', 'O') #define SCL_X_RESOLUTION HP_SCL_CONTROL(10323, 'a', 'R') #define SCL_Y_RESOLUTION HP_SCL_CONTROL(10324, 'a', 'S') #define SCL_OUTPUT_DATA_TYPE HP_SCL_CONTROL(10325, 'a', 'T') #define SCL_DOWNLOAD_LENGTH HP_SCL_CONTROL(10328, 'a', 'W') #define SCL_PRELOAD_ADF HP_SCL_CONTROL(10468, 'f', 'C') #define SCL_MEDIA HP_SCL_CONTROL(10469, 'f', 'D') #define SCL_10470 HP_SCL_CONTROL(10470, 'f', 'E') #define SCL_LAMPTEST HP_SCL_CONTROL(10477, 'f', 'L') #define SCL_X_EXTENT HP_SCL_CONTROL(10481, 'f', 'P') #define SCL_Y_EXTENT HP_SCL_CONTROL(10482, 'f', 'Q') #define SCL_START_SCAN HP_SCL_COMMAND('f', 'S') #define SCL_10485 HP_SCL_CONTROL(10485, 'f', 'T') #define SCL_10488 HP_SCL_CONTROL(10488, 'f', 'W') #define SCL_X_POS HP_SCL_CONTROL(10489, 'f', 'X') #define SCL_Y_POS HP_SCL_CONTROL(10490, 'f', 'Y') #define SCL_XPA_SCAN HP_SCL_COMMAND('u', 'D') #define SCL_SPEED HP_SCL_CONTROL(10950, 'u', 'E') #define SCL_FILTER HP_SCL_CONTROL(10951, 'u', 'F') #define SCL_10952 HP_SCL_CONTROL(10952, 'u', 'G') #define SCL_XPA_DISABLE HP_SCL_CONTROL(10953, 'u', 'H') #define SCL_TONE_MAP HP_SCL_CONTROL(10956, 'u', 'K') #define SCL_CALIBRATE HP_SCL_COMMAND('u', 'R') #define SCL_ADF_SCAN HP_SCL_COMMAND('u', 'S') #define SCL_MATRIX HP_SCL_CONTROL(10965, 'u', 'T') #define SCL_UNLOAD HP_SCL_CONTROL(10966, 'u', 'U') #define SCL_10967 HP_SCL_CONTROL(10967, 'u', 'V') #define SCL_CHANGE_DOC HP_SCL_CONTROL(10969, 'u', 'X') #define SCL_ADF_BFEED HP_SCL_CONTROL(10970, 'u', 'Y') /* Clear Errors does not follow command syntax Esc*o0E, it is only Esc*oE */ /* #define SCL_CLEAR_ERRORS HP_SCL_COMMAND('o', 'E') */ #define SCL_INQUIRE_PRESENT_VALUE HP_SCL_COMMAND('s', 'R') #define SCL_INQUIRE_MINIMUM_VALUE HP_SCL_COMMAND('s', 'L') #define SCL_INQUIRE_MAXIMUM_VALUE HP_SCL_COMMAND('s', 'H') #define SCL_INQUIRE_DEVICE_PARAMETER HP_SCL_COMMAND('s', 'E') #define SCL_UPLOAD_BINARY_DATA HP_SCL_COMMAND('s', 'U') #define SCL_HP_MODEL_1 HP_SCL_PARAMETER(3) #define SCL_HP_MODEL_2 HP_SCL_PARAMETER(10) #define SCL_HP_MODEL_3 HP_SCL_PARAMETER(9) #define SCL_HP_MODEL_4 HP_SCL_PARAMETER(11) #define SCL_HP_MODEL_5 HP_SCL_PARAMETER(12) #define SCL_HP_MODEL_6 HP_SCL_PARAMETER(14) #define SCL_HP_MODEL_8 HP_SCL_PARAMETER(15) #define SCL_HP_MODEL_9 HP_SCL_PARAMETER(16) #define SCL_HP_MODEL_10 HP_SCL_PARAMETER(17) #define SCL_HP_MODEL_11 HP_SCL_PARAMETER(18) #define SCL_HP_MODEL_12 HP_SCL_PARAMETER(19) #define SCL_HP_MODEL_14 HP_SCL_PARAMETER(21) #define SCL_HP_MODEL_16 HP_SCL_PARAMETER(31) #define SCL_HP_MODEL_17 HP_SCL_PARAMETER(32) #define SCL_ADF_CAPABILITY HP_SCL_PARAMETER(24) #define SCL_ADF_BIN HP_SCL_PARAMETER(25) #define SCL_ADF_RDY_UNLOAD HP_SCL_PARAMETER(27) #define SCL_CURRENT_ERROR_STACK HP_SCL_PARAMETER(257) #define SCL_CURRENT_ERROR HP_SCL_PARAMETER(259) #define SCL_OLDEST_ERROR HP_SCL_PARAMETER(261) #define SCL_PIXELS_PER_LINE HP_SCL_PARAMETER(1024) #define SCL_BYTES_PER_LINE HP_SCL_PARAMETER(1025) #define SCL_NUMBER_OF_LINES HP_SCL_PARAMETER(1026) #define SCL_ADF_READY HP_SCL_PARAMETER(1027) #define SCL_DEVPIX_RESOLUTION HP_SCL_PARAMETER(1028) #define SCL_AUTO_SPEED HP_SCL_PARAMETER(1040) #define SCL_FRONT_BUTTON HP_SCL_PARAMETER(1044) #define SCL_PRELOADED HP_SCL_PARAMETER(1045) /* The following is not documented */ #define SCL_SECONDARY_SCANDIR HP_SCL_PARAMETER(1047) #define SCL_BW8x8DITHER HP_SCL_DATA_TYPE(0) #define SCL_8x8TONE_MAP HP_SCL_DATA_TYPE(1) #define SCL_8x9MATRIX_COEFF HP_SCL_DATA_TYPE(2) #define SCL_8x8DITHER HP_SCL_DATA_TYPE(3) #define SCL_CAL_STRIP HP_SCL_DATA_TYPE(4) #define SCL_BW16x16DITHER HP_SCL_DATA_TYPE(5) #define SCL_10x8TONE_MAP HP_SCL_DATA_TYPE(6) #define SCL_10x3MATRIX_COEFF HP_SCL_DATA_TYPE(8) #define SCL_10x9MATRIX_COEFF HP_SCL_DATA_TYPE(9) #define SCL_7x12TONE_MAP HP_SCL_DATA_TYPE(10) #define SCL_BW7x12TONE_MAP HP_SCL_DATA_TYPE(11) #define SCL_RGB_GAINS HP_SCL_DATA_TYPE(11) #define SCL_CALIB_MAP HP_SCL_DATA_TYPE(14) #endif /* HP_SCL_INCLUDED */ sane-backends-1.0.27/backend/genesys_gl847.c0000664000175000017500000031330512775312261015372 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2010-2013 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME #define BACKEND_NAME genesys_gl847 #include "genesys_gl847.h" /**************************************************************************** Low level function ****************************************************************************/ /* ------------------------------------------------------------------------ */ /* Read and write RAM, registers and AFE */ /* ------------------------------------------------------------------------ */ /** @brief read scanned data * Read in 0xeff0 maximum sized blocks. This read is done in 2 * parts if not multple of 512. First read is rounded to a multiple of 512 bytes, last read fetches the * remainder. Read addr is always 0x10000000 with the memory layout setup. * @param dev device to read data from * @param addr address within ASIC memory space, unused but kept for API * @param data pointer where to store the read data * @param len size to read */ static SANE_Status gl847_bulk_read_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size, target, read, done; uint8_t outdata[8]; uint8_t *buffer; DBG (DBG_io, "gl847_bulk_read_data: requesting %lu bytes at addr=0x%02x\n", (u_long) len, addr); if (len == 0) return SANE_STATUS_GOOD; target = len; buffer = data; /* loop until computed data size is read */ while (target) { if (target > 0xeff0) { size = 0xeff0; } else { size = target; } /* hard coded 0x10000000 addr */ outdata[0] = 0; outdata[1] = 0; outdata[2] = 0; outdata[3] = 0x10; /* data size to transfer */ outdata[4] = (size & 0xff); outdata[5] = ((size >> 8) & 0xff); outdata[6] = ((size >> 16) & 0xff); outdata[7] = ((size >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, 0x00, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s failed while writing command: %s\n", __func__, sane_strstatus (status)); return status; } /* blocks must be multiple of 512 but not last block */ read = size; if (read >= 512) { read /= 512; read *= 512; } DBG (DBG_io2, "gl847_bulk_read_data: trying to read %lu bytes of data\n", (u_long) read); status = sanei_usb_read_bulk (dev->dn, buffer, &read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } done=read; DBG (DBG_io2, "gl847_bulk_read_data: %lu bytes of data read\n", (u_long) done); /* read less than 512 bytes remainder */ if (read < size) { read = size - read; DBG (DBG_io2, "gl847_bulk_read_data: trying to read %lu bytes of data\n", (u_long) read); status = sanei_usb_read_bulk (dev->dn, buffer+done, &read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } done=read; DBG (DBG_io2, "gl847_bulk_read_data: %lu bytes of data read\n", (u_long) done); } DBG (DBG_io2, "%s: read %lu bytes, %lu remaining\n", __func__, (u_long) size, (u_long) (target - size)); target -= size; buffer += size; } if (DBG_LEVEL >= DBG_data && dev->binary!=NULL) { fwrite(data, len, 1, dev->binary); } DBGCOMPLETED; return SANE_STATUS_GOOD; } /**************************************************************************** Mid level functions ****************************************************************************/ static SANE_Bool gl847_get_fast_feed_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG02); if (r && (r->value & REG02_FASTFED)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl847_get_filter_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_FILTER)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl847_get_lineart_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_LINEART)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl847_get_bitset_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_BITSET)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl847_get_gain4_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, 0x06); if (r && (r->value & REG06_GAIN4)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl847_test_buffer_empty_bit (SANE_Byte val) { if (val & REG41_BUFEMPTY) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl847_test_motor_flag_bit (SANE_Byte val) { if (val & REG41_MOTORENB) return SANE_TRUE; return SANE_FALSE; } /** * compute the step multiplier used */ static int gl847_get_step_multiplier (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; int value = 1; r = sanei_genesys_get_address (regs, 0x9d); if (r != NULL) { value = (r->value & 0x0f)>>1; value = 1 << value; } DBG (DBG_io, "%s: step multiplier is %d\n", __func__, value); return value; } /** @brief sensor profile * search for the database of motor profiles and get the best one. Each * profile is at a specific dpihw. Use LiDE 110 table by default. * @param sensor_type sensor id * @param dpi hardware dpi for the scan * @return a pointer to a Sensor_Profile struct */ static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi) { unsigned int i; int idx; i=0; idx=-1; while(i=dpi && sensors[i].dpimodel->ccd_type, xres); return sensor->exposure; } /** @brief sensor specific settings */ static void gl847_setup_sensor (Genesys_Device * dev, Genesys_Register_Set * regs, int dpi) { Genesys_Register_Set *r; Sensor_Profile *sensor; int dpihw, i; uint16_t exp; DBGSTART; dpihw=sanei_genesys_compute_dpihw(dev,dpi); for (i = 0x06; i < 0x0e; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); if (r) r->value = dev->sensor.regs_0x10_0x1d[i]; } for (i = 0; i < 9; i++) { r = sanei_genesys_get_address (regs, 0x52 + i); if (r) r->value = dev->sensor.regs_0x52_0x5e[i]; } /* set EXPDUMMY and CKxMAP */ dpihw=sanei_genesys_compute_dpihw(dev,dpi); sensor=get_sensor_profile(dev->model->ccd_type, dpihw); sanei_genesys_set_reg_from_set(regs,REG_EXPDMY,(uint8_t)((sensor->expdummy) & 0xff)); /* if no calibration has been done, set default values for exposures */ exp=dev->sensor.regs_0x10_0x1d[0]*256+dev->sensor.regs_0x10_0x1d[1]; if(exp==0) { exp=sensor->expr; } sanei_genesys_set_double(regs,REG_EXPR,exp); exp=dev->sensor.regs_0x10_0x1d[2]*256+dev->sensor.regs_0x10_0x1d[3]; if(exp==0) { exp=sensor->expg; } sanei_genesys_set_double(regs,REG_EXPG,exp); exp=dev->sensor.regs_0x10_0x1d[4]*256+dev->sensor.regs_0x10_0x1d[5]; if(exp==0) { exp=sensor->expb; } sanei_genesys_set_double(regs,REG_EXPB,exp); sanei_genesys_set_triple(regs,REG_CK1MAP,sensor->ck1map); sanei_genesys_set_triple(regs,REG_CK3MAP,sensor->ck3map); sanei_genesys_set_triple(regs,REG_CK4MAP,sensor->ck4map); /* order of the sub-segments */ dev->order=sensor->order; r = sanei_genesys_get_address (regs, 0x17); r->value = sensor->r17; DBGCOMPLETED; } /* returns the max register bulk size */ static int gl847_bulk_full_size (void) { return GENESYS_GL847_MAX_REGS; } /** @brief set all registers to default values . * This function is called only once at the beginning and * fills register startup values for registers reused across scans. * Those that are rarely modified or not modified are written * individually. * @param dev device structure holding register set to initialize */ static void gl847_init_registers (Genesys_Device * dev) { int lide700=0; uint8_t val; DBGSTART; /* 700F class needs some different initial settings */ if (strcmp (dev->model->name, "canon-lide-700f") == 0) { lide700 = 1; } memset (dev->reg, 0, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); SETREG (0x01, 0x82); SETREG (0x02, 0x18); SETREG (0x03, 0x50); SETREG (0x04, 0x12); SETREG (0x05, 0x80); SETREG (0x06, 0x50); /* FASTMODE + POWERBIT */ SETREG (0x08, 0x10); SETREG (0x09, 0x01); SETREG (0x0a, 0x00); SETREG (0x0b, 0x01); SETREG (0x0c, 0x02); /* LED exposures */ SETREG (0x10, 0x00); SETREG (0x11, 0x00); SETREG (0x12, 0x00); SETREG (0x13, 0x00); SETREG (0x14, 0x00); SETREG (0x15, 0x00); SETREG (0x16, 0x10); SETREG (0x17, 0x08); SETREG (0x18, 0x00); /* EXPDMY */ SETREG (0x19, 0x50); SETREG (0x1a, 0x34); SETREG (0x1b, 0x00); SETREG (0x1c, 0x02); SETREG (0x1d, 0x04); SETREG (0x1e, 0x10); SETREG (0x1f, 0x04); SETREG (0x20, 0x02); SETREG (0x21, 0x10); SETREG (0x22, 0x7f); SETREG (0x23, 0x7f); SETREG (0x24, 0x10); SETREG (0x25, 0x00); SETREG (0x26, 0x00); SETREG (0x27, 0x00); SETREG (0x2c, 0x09); SETREG (0x2d, 0x60); SETREG (0x2e, 0x80); SETREG (0x2f, 0x80); SETREG (0x30, 0x00); SETREG (0x31, 0x10); SETREG (0x32, 0x15); SETREG (0x33, 0x0e); SETREG (0x34, 0x40); SETREG (0x35, 0x00); SETREG (0x36, 0x2a); SETREG (0x37, 0x30); SETREG (0x38, 0x2a); SETREG (0x39, 0xf8); SETREG (0x3d, 0x00); SETREG (0x3e, 0x00); SETREG (0x3f, 0x00); SETREG (0x52, 0x03); SETREG (0x53, 0x07); SETREG (0x54, 0x00); SETREG (0x55, 0x00); SETREG (0x56, 0x00); SETREG (0x57, 0x00); SETREG (0x58, 0x2a); SETREG (0x59, 0xe1); SETREG (0x5a, 0x55); SETREG (0x5e, 0x41); SETREG (0x5f, 0x40); SETREG (0x60, 0x00); SETREG (0x61, 0x21); SETREG (0x62, 0x40); SETREG (0x63, 0x00); SETREG (0x64, 0x21); SETREG (0x65, 0x40); SETREG (0x67, 0x80); SETREG (0x68, 0x80); SETREG (0x69, 0x20); SETREG (0x6a, 0x20); /* CK1MAP */ SETREG (0x74, 0x00); SETREG (0x75, 0x00); SETREG (0x76, 0x3c); /* CK3MAP */ SETREG (0x77, 0x00); SETREG (0x78, 0x00); SETREG (0x79, 0x9f); /* CK4MAP */ SETREG (0x7a, 0x00); SETREG (0x7b, 0x00); SETREG (0x7c, 0x55); SETREG (0x7d, 0x00); /* NOTE: autoconf is a non working option */ SETREG (0x87, 0x02); SETREG (0x9d, 0x06); SETREG (0xa2, 0x0f); SETREG (0xbd, 0x18); SETREG (0xfe, 0x08); /* gamma[0] and gamma[256] values */ SETREG (0xbe, 0x00); SETREG (0xc5, 0x00); SETREG (0xc6, 0x00); SETREG (0xc7, 0x00); SETREG (0xc8, 0x00); SETREG (0xc9, 0x00); SETREG (0xca, 0x00); /* LiDE 700 fixups */ if(lide700) { SETREG (0x5f, 0x04); SETREG (0x7d, 0x80); /* we write to these registers only once */ val=0; sanei_genesys_write_register (dev, REG7E, val); sanei_genesys_write_register (dev, REG9E, val); sanei_genesys_write_register (dev, REG9F, val); sanei_genesys_write_register (dev, REGAB, val); } /* fine tune upon device description */ dev->reg[reg_0x05].value &= ~REG05_DPIHW; switch (dev->sensor.optical_res) { case 600: dev->reg[reg_0x05].value |= REG05_DPIHW_600; break; case 1200: dev->reg[reg_0x05].value |= REG05_DPIHW_1200; break; case 2400: dev->reg[reg_0x05].value |= REG05_DPIHW_2400; break; case 4800: dev->reg[reg_0x05].value |= REG05_DPIHW_4800; break; } /* initalize calibration reg */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); DBGCOMPLETED; } /**@brief send slope table for motor movement * Send slope_table in machine byte order * @param dev device to send slope table * @param table_nr index of the slope table in ASIC memory * Must be in the [0-4] range. * @param slope_table pointer to 16 bit values array of the slope table * @param steps number of elements in the slope table */ static SANE_Status gl847_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps) { SANE_Status status; uint8_t *table; int i; char msg[10000]; DBG (DBG_proc, "%s (table_nr = %d, steps = %d)\n", __func__, table_nr, steps); /* sanity check */ if(table_nr<0 || table_nr>4) { DBG (DBG_error, "%s: invalid table number %d!\n", __func__, table_nr); return SANE_STATUS_INVAL; } table = (uint8_t *) malloc (steps * 2); for (i = 0; i < steps; i++) { table[i * 2] = slope_table[i] & 0xff; table[i * 2 + 1] = slope_table[i] >> 8; } if (DBG_LEVEL >= DBG_io) { sprintf (msg, "write slope %d (%d)=", table_nr, steps); for (i = 0; i < steps; i++) { sprintf (msg+strlen(msg), "%d", slope_table[i]); } DBG (DBG_io, "%s: %s\n", __func__, msg); } /* slope table addresses are fixed */ status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, 0x10000000 + 0x4000 * table_nr, steps * 2, table); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: write to AHB failed writing slope table %d (%s)\n", __func__, table_nr, sane_strstatus (status)); } free (table); DBGCOMPLETED; return status; } /** * Set register values of Analog Device type frontend * */ static SANE_Status gl847_set_ad_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status = SANE_STATUS_GOOD; int i; uint16_t val; uint8_t val8; DBGSTART; /* wait for FE to be ready */ status = sanei_genesys_get_status (dev, &val8); while (val8 & REG41_FEBUSY); { usleep (10000); status = sanei_genesys_get_status (dev, &val8); }; if (set == AFE_INIT) { DBG (DBG_proc, "gl847_set_ad_fe(): setting DAC %u\n", dev->model->dac_type); /* sets to default values */ sanei_genesys_init_fe (dev); } /* reset DAC */ status = sanei_genesys_fe_write_data (dev, 0x00, 0x80); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_set_ad_fe: failed to write reg0: %s\n", sane_strstatus (status)); return status; } /* write them to analog frontend */ val = dev->frontend.reg[0]; status = sanei_genesys_fe_write_data (dev, 0x00, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_set_ad_fe: failed to write reg0: %s\n", sane_strstatus (status)); return status; } val = dev->frontend.reg[1]; status = sanei_genesys_fe_write_data (dev, 0x01, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_set_ad_fe: failed to write reg1: %s\n", sane_strstatus (status)); return status; } for (i = 0; i < 3; i++) { val = dev->frontend.gain[i]; status = sanei_genesys_fe_write_data (dev, 0x02 + i, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_set_ad_fe: failed to write gain %d: %s\n", i, sane_strstatus (status)); return status; } } for (i = 0; i < 3; i++) { val = dev->frontend.offset[i]; status = sanei_genesys_fe_write_data (dev, 0x05 + i, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_set_ad_fe: failed to write offset %d: %s\n", i, sane_strstatus (status)); return status; } } DBGCOMPLETED; return status; } static SANE_Status gl847_homsnr_gpio(Genesys_Device *dev) { uint8_t val; SANE_Status status=SANE_STATUS_GOOD; if (dev->model->gpo_type == GPO_CANONLIDE700) { RIE (sanei_genesys_read_register (dev, REG6C, &val)); val &= ~REG6C_GPIO10; RIE (sanei_genesys_write_register (dev, REG6C, val)); } else { RIE (sanei_genesys_read_register (dev, REG6C, &val)); val |= REG6C_GPIO10; RIE (sanei_genesys_write_register (dev, REG6C, val)); } return status; } /* Set values of analog frontend */ static SANE_Status gl847_set_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status; uint8_t val; DBG (DBG_proc, "gl847_set_fe (%s)\n", set == AFE_INIT ? "init" : set == AFE_SET ? "set" : set == AFE_POWER_SAVE ? "powersave" : "huh?"); RIE (sanei_genesys_read_register (dev, REG04, &val)); /* route to AD devices */ if ((val & REG04_FESET) == 0x02) { return gl847_set_ad_fe (dev, set); } /* for now there is no support yet for wolfson fe */ DBG (DBG_proc, "gl847_set_fe(): unsupported frontend type %d\n", dev->reg[reg_0x04].value & REG04_FESET); DBGCOMPLETED; return SANE_STATUS_UNSUPPORTED; } /** @brief set up motor related register for scan */ static SANE_Status gl847_init_motor_regs_scan (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int scan_exposure_time, float scan_yres, int scan_step_type, unsigned int scan_lines, unsigned int scan_dummy, unsigned int feed_steps, int scan_power_mode, unsigned int flags) { SANE_Status status; int use_fast_fed; unsigned int fast_dpi; uint16_t scan_table[SLOPE_TABLE_SIZE]; uint16_t fast_table[SLOPE_TABLE_SIZE]; int scan_steps, fast_steps, factor; unsigned int feedl, dist; Genesys_Register_Set *r; uint32_t z1, z2; unsigned int min_restep = 0x20; uint8_t val, effective; int fast_step_type; unsigned int ccdlmt,tgtime; DBGSTART; DBG (DBG_proc, "gl847_init_motor_regs_scan : scan_exposure_time=%d, " "scan_yres=%g, scan_step_type=%d, scan_lines=%d, scan_dummy=%d, " "feed_steps=%d, scan_power_mode=%d, flags=%x\n", scan_exposure_time, scan_yres, scan_step_type, scan_lines, scan_dummy, feed_steps, scan_power_mode, flags); /* get step multiplier */ factor = gl847_get_step_multiplier (reg); use_fast_fed=0; /* no fast fed since feed works well */ if(dev->settings.yres==4444 && feed_steps>100 && ((flags & MOTOR_FLAG_FEED)==0)) { use_fast_fed=1; } DBG (DBG_io, "%s: use_fast_fed=%d\n", __func__, use_fast_fed); sanei_genesys_set_triple(reg, REG_LINCNT, scan_lines); DBG (DBG_io, "%s: lincnt=%d\n", __func__, scan_lines); /* compute register 02 value */ r = sanei_genesys_get_address (reg, REG02); r->value = 0x00; r->value |= REG02_MTRPWR; if (use_fast_fed) r->value |= REG02_FASTFED; else r->value &= ~REG02_FASTFED; if (flags & MOTOR_FLAG_AUTO_GO_HOME) r->value |= REG02_AGOHOME | REG02_NOTHOME; if ((flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE) ||(scan_yres>=dev->sensor.optical_res)) { r->value |= REG02_ACDCDIS; } /* scan and backtracking slope table */ sanei_genesys_slope_table(scan_table, &scan_steps, scan_yres, scan_exposure_time, dev->motor.base_ydpi, scan_step_type, factor, dev->model->motor_type, gl847_motors); RIE(gl847_send_slope_table (dev, SCAN_TABLE, scan_table, scan_steps*factor)); RIE(gl847_send_slope_table (dev, BACKTRACK_TABLE, scan_table, scan_steps*factor)); /* fast table */ fast_dpi=sanei_genesys_get_lowest_ydpi(dev); fast_step_type=scan_step_type; if(scan_step_type>=2) { fast_step_type=2; } sanei_genesys_slope_table(fast_table, &fast_steps, fast_dpi, scan_exposure_time, dev->motor.base_ydpi, fast_step_type, factor, dev->model->motor_type, gl847_motors); /* manual override of high start value */ fast_table[0]=fast_table[1]; RIE(gl847_send_slope_table (dev, STOP_TABLE, fast_table, fast_steps*factor)); RIE(gl847_send_slope_table (dev, FAST_TABLE, fast_table, fast_steps*factor)); RIE(gl847_send_slope_table (dev, HOME_TABLE, fast_table, fast_steps*factor)); /* correct move distance by acceleration and deceleration amounts */ feedl=feed_steps; if (use_fast_fed) { feedl<<=fast_step_type; dist=(scan_steps+2*fast_steps)*factor; /* TODO read and decode REGAB */ r = sanei_genesys_get_address (reg, 0x5e); dist += (r->value & 31); /* FEDCNT */ r = sanei_genesys_get_address (reg, REG_FEDCNT); dist += r->value; } else { feedl<<=scan_step_type; dist=scan_steps*factor; if (flags & MOTOR_FLAG_FEED) dist *=2; } DBG (DBG_io2, "%s: scan steps=%d\n", __func__, scan_steps); DBG (DBG_io2, "%s: acceleration distance=%d\n", __func__, dist); /* check for overflow */ if(distvalue & REG0C_CCDLMT)+1; r = sanei_genesys_get_address (reg, REG1C); tgtime=1<<(r->value & REG1C_TGTIME); /* hi res motor speed GPIO */ RIE (sanei_genesys_read_register (dev, REG6C, &effective)); /* if quarter step, bipolar Vref2 */ if (scan_step_type > 1) { if (scan_step_type < 3) { val = effective & ~REG6C_GPIO13; } else { val = effective | REG6C_GPIO13; } } else { val = effective; } RIE (sanei_genesys_write_register (dev, REG6C, val)); /* effective scan */ RIE (sanei_genesys_read_register (dev, REG6C, &effective)); val = effective | REG6C_GPIO10; RIE (sanei_genesys_write_register (dev, REG6C, val)); min_restep=scan_steps/2-1; if (min_restep < 1) min_restep = 1; r = sanei_genesys_get_address (reg, REG_FWDSTEP); r->value = min_restep; r = sanei_genesys_get_address (reg, REG_BWDSTEP); r->value = min_restep; sanei_genesys_calculate_zmode2(use_fast_fed, scan_exposure_time*ccdlmt*tgtime, scan_table, scan_steps*factor, feedl, min_restep*factor, &z1, &z2); DBG (DBG_info, "gl847_init_motor_regs_scan: z1 = %d\n", z1); sanei_genesys_set_triple(reg, REG60, z1 | (scan_step_type << (16+REG60S_STEPSEL))); DBG (DBG_info, "gl847_init_motor_regs_scan: z2 = %d\n", z2); sanei_genesys_set_triple(reg, REG63, z2 | (scan_step_type << (16+REG63S_FSTPSEL))); r = sanei_genesys_get_address (reg, 0x1e); r->value &= 0xf0; /* 0 dummy lines */ r->value |= scan_dummy; /* dummy lines */ r = sanei_genesys_get_address (reg, REG67); r->value = REG67_MTRPWM; r = sanei_genesys_get_address (reg, REG68); r->value = REG68_FASTPWM; r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = scan_steps; r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = scan_steps; r = sanei_genesys_get_address (reg, REG_FSHDEC); r->value = scan_steps; r = sanei_genesys_get_address (reg, REG_FMOVNO); r->value = fast_steps; r = sanei_genesys_get_address (reg, REG_FMOVDEC); r->value = fast_steps; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief set up registers related to sensor * Set up the following registers 0x01 0x03 0x10-0x015 R/G/B exposures 0x19 EXPDMY 0x2e BWHI 0x2f BWLO 0x04 0x87 0x05 0x2c,0x2d DPISET 0x30,0x31 STRPIXEL 0x32,0x33 ENDPIXEL 0x35,0x36,0x37 MAXWD [25:2] (>>2) 0x38,0x39 LPERIOD 0x34 DUMMY */ static SANE_Status gl847_init_optical_regs_scan (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int exposure_time, int used_res, unsigned int start, unsigned int pixels, int channels, int depth, SANE_Bool half_ccd, int color_filter, int flags) { unsigned int words_per_line; unsigned int startx, endx, used_pixels; unsigned int dpiset, dpihw,segnb,cksel,factor; unsigned int bytes; Genesys_Register_Set *r; SANE_Status status; Sensor_Profile *sensor; DBG (DBG_proc, "gl847_init_optical_regs_scan : exposure_time=%d, " "used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, " "half_ccd=%d, flags=%x\n", exposure_time, used_res, start, pixels, channels, depth, half_ccd, flags); /* resolution is divided according to CKSEL */ r = sanei_genesys_get_address (reg, REG18); cksel= (r->value & REG18_CKSEL)+1; DBG (DBG_io2, "%s: cksel=%d\n", __func__, cksel); /* to manage high resolution device while keeping good * low resolution scanning speed, we make hardware dpi vary */ dpihw=sanei_genesys_compute_dpihw(dev, used_res * cksel); factor=dev->sensor.optical_res/dpihw; DBG (DBG_io2, "%s: dpihw=%d (factor=%d)\n", __func__, dpihw, factor); /* sensor parameters */ sensor=get_sensor_profile(dev->model->ccd_type, dpihw); gl847_setup_sensor (dev, reg, dpihw); dpiset = used_res * cksel; /* start and end coordinate in optical dpi coordinates */ startx = start/cksel+dev->sensor.CCD_start_xoffset; used_pixels=pixels/cksel; /* end of sensor window */ endx = startx + used_pixels; /* sensors are built from 600 dpi segments for LiDE 100/200 * and 1200 dpi for the 700F */ if (dev->model->flags & GENESYS_FLAG_SIS_SENSOR) { segnb=dpihw/600; } else { segnb=1; } /* compute pixel coordinate in the given dpihw space, * taking segments into account */ startx/=factor*segnb; endx/=factor*segnb; dev->len=endx-startx; dev->dist=0; dev->skip=0; /* in cas of multi-segments sensor, we have to add the witdh * of the sensor crossed by the scan area */ if (dev->model->flags & GENESYS_FLAG_SIS_SENSOR && segnb>1) { dev->dist = sensor->segcnt; } /* use a segcnt rounded to next even number */ endx += ((dev->dist+1)&0xfffe)*(segnb-1); used_pixels=endx-startx; status = gl847_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_init_optical_regs_scan: failed to set frontend: %s\n", sane_strstatus (status)); return status; } /* enable shading */ r = sanei_genesys_get_address (reg, REG01); r->value &= ~REG01_SCAN; r->value |= REG01_SHDAREA; if ((flags & OPTICAL_FLAG_DISABLE_SHADING) || (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) { r->value &= ~REG01_DVDSET; } else { r->value |= REG01_DVDSET; } r = sanei_genesys_get_address (reg, REG03); r->value &= ~REG03_AVEENB; if (flags & OPTICAL_FLAG_DISABLE_LAMP) r->value &= ~REG03_LAMPPWR; else r->value |= REG03_LAMPPWR; /* BW threshold */ r = sanei_genesys_get_address (reg, 0x2e); r->value = dev->settings.threshold; r = sanei_genesys_get_address (reg, 0x2f); r->value = dev->settings.threshold; /* monochrome / color scan */ r = sanei_genesys_get_address (reg, REG04); switch (depth) { case 1: r->value &= ~REG04_BITSET; r->value |= REG04_LINEART; break; case 8: r->value &= ~(REG04_LINEART | REG04_BITSET); break; case 16: r->value &= ~REG04_LINEART; r->value |= REG04_BITSET; break; } r->value &= ~(REG04_FILTER | REG04_AFEMOD); if (channels == 1) { switch (color_filter) { case 0: r->value |= 0x14; /* red filter */ break; case 2: r->value |= 0x1c; /* blue filter */ break; default: r->value |= 0x18; /* green filter */ break; } } else r->value |= 0x10; /* mono */ /* register 05 */ r = sanei_genesys_get_address (reg, REG05); /* set up dpihw */ r->value &= ~REG05_DPIHW; switch(dpihw) { case 600: r->value |= REG05_DPIHW_600; break; case 1200: r->value |= REG05_DPIHW_1200; break; case 2400: r->value |= REG05_DPIHW_2400; break; case 4800: r->value |= REG05_DPIHW_4800; break; } /* enable gamma tables */ if (flags & OPTICAL_FLAG_DISABLE_GAMMA) r->value &= ~REG05_GMMENB; else r->value |= REG05_GMMENB; /* CIS scanners can do true gray by setting LEDADD */ /* we set up LEDADD only when asked */ if (dev->model->is_cis == SANE_TRUE) { r = sanei_genesys_get_address (reg, 0x87); r->value &= ~REG87_LEDADD; if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) { r->value |= REG87_LEDADD; } /* RGB weighting r = sanei_genesys_get_address (reg, 0x01); r->value &= ~REG01_TRUEGRAY; if (channels == 1 && (flags & OPTICAL_FLAG_ENABLE_LEDADD)) { r->value |= REG01_TRUEGRAY; }*/ } /* words(16bit) before gamma, conversion to 8 bit or lineart*/ words_per_line = (used_pixels * dpiset) / dpihw; bytes=depth/8; if (depth == 1) { words_per_line = (words_per_line+7)/8 ; dev->len = (dev->len >> 3) + ((dev->len & 7) ? 1 : 0); dev->dist = (dev->dist >> 3) + ((dev->dist & 7) ? 1 : 0); } else { words_per_line *= bytes; dev->dist *= bytes; dev->len *= bytes; } dev->bpl = words_per_line; dev->cur=0; dev->segnb=segnb; dev->line_interp = 0; sanei_genesys_set_double(reg,REG_DPISET,dpiset); DBG (DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset); sanei_genesys_set_double(reg,REG_STRPIXEL,startx); sanei_genesys_set_double(reg,REG_ENDPIXEL,endx); DBG (DBG_io2, "%s: startx=%d\n", __func__, startx); DBG (DBG_io2, "%s: endx =%d\n", __func__, endx); DBG (DBG_io2, "%s: used_pixels=%d\n", __func__, used_pixels); DBG (DBG_io2, "%s: pixels =%d\n", __func__, pixels); DBG (DBG_io2, "%s: depth =%d\n", __func__, depth); DBG (DBG_io2, "%s: dev->bpl =%lu\n", __func__, (unsigned long)dev->bpl); DBG (DBG_io2, "%s: dev->len =%lu\n", __func__, (unsigned long)dev->len); DBG (DBG_io2, "%s: dev->dist =%lu\n", __func__, (unsigned long)dev->dist); DBG (DBG_io2, "%s: dev->segnb =%lu\n", __func__, (unsigned long)dev->segnb); words_per_line *= channels; dev->wpl = words_per_line; if(dev->oe_buffer.buffer!=NULL) { sanei_genesys_buffer_free (&(dev->oe_buffer)); } RIE (sanei_genesys_buffer_alloc (&(dev->oe_buffer), dev->wpl)); /* MAXWD is expressed in 4 words unit */ sanei_genesys_set_triple(reg, REG_MAXWD, (words_per_line >> 2)); DBG (DBG_io2, "%s: words_per_line used=%d\n", __func__, words_per_line); sanei_genesys_set_double(reg, REG_LPERIOD, exposure_time); DBG (DBG_io2, "%s: exposure_time used=%d\n", __func__, exposure_time); r = sanei_genesys_get_address (reg, 0x34); r->value = dev->sensor.dummy_pixel; DBGCOMPLETED; return SANE_STATUS_GOOD; } /* set up registers for an actual scan * * this function sets up the scanner to scan in normal or single line mode */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ float yres, /*dpi */ float startx, /*optical_res, from dummy_pixel+1 */ float starty, /*base_ydpi, from home! */ float pixels, float lines, unsigned int depth, unsigned int channels, int color_filter, unsigned int flags) { int used_res; int start, used_pixels; int bytes_per_line; int move; unsigned int lincnt; unsigned int oflags; /**> optical flags */ unsigned int mflags; /**> motor flags */ int exposure_time; int stagger; int slope_dpi = 0; int dummy = 0; int scan_step_type = 1; int scan_power_mode = 0; int max_shift; size_t requested_buffer_size, read_buffer_size; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; SANE_Status status; DBG (DBG_info, "gl847_init_scan_regs settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g/%g\n" "Depth/Channels: %u/%u\n" "Flags : %x\n\n", xres, yres, lines, pixels, startx, starty, depth, channels, flags); /* we may have 2 domains for ccd: xres below or above half ccd max dpi */ if (dev->sensor.optical_res < 2 * xres || !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)) { half_ccd = SANE_FALSE; } else { half_ccd = SANE_TRUE; } /* optical_res */ optical_res = dev->sensor.optical_res; if (half_ccd) optical_res /= 2; /* stagger */ if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "gl847_init_scan_regs : stagger=%d lines\n", stagger); /* used_res */ if (flags & SCAN_FLAG_USE_OPTICAL_RES) { used_res = optical_res; } else { /* resolution is choosen from a list */ used_res = xres; } /* compute scan parameters values */ /* pixels are allways given at full optical resolution */ /* use detected left margin and fixed value */ /* start */ /* add x coordinates */ start = startx; if (stagger > 0) start |= 1; /* compute correct pixels number */ /* pixels */ used_pixels = (pixels * optical_res) / xres; /* round up pixels number if needed */ if (used_pixels * xres < pixels * optical_res) used_pixels++; dummy = 3-channels; /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ if (dev->model->is_cis) slope_dpi = yres * channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); exposure_time = gl847_compute_exposure (dev, used_res); scan_step_type = sanei_genesys_compute_step_type(gl847_motors, dev->model->motor_type, exposure_time); DBG (DBG_info, "gl847_init_scan_regs : exposure_time=%d pixels\n", exposure_time); DBG (DBG_info, "gl847_init_scan_regs : scan_step_type=%d\n", scan_step_type); /*** optical parameters ***/ /* in case of dynamic lineart, we use an internal 8 bit gray scan * to generate 1 lineart data */ if ((flags & SCAN_FLAG_DYNAMIC_LINEART) && (dev->settings.scan_mode == SCAN_MODE_LINEART)) { depth = 8; } /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ oflags = 0; if(flags & SCAN_FLAG_DISABLE_SHADING) oflags |= OPTICAL_FLAG_DISABLE_SHADING; if(flags & SCAN_FLAG_DISABLE_GAMMA) oflags |= OPTICAL_FLAG_DISABLE_GAMMA; if(flags & SCAN_FLAG_DISABLE_LAMP) oflags |= OPTICAL_FLAG_DISABLE_LAMP; if (dev->model->is_cis && dev->settings.true_gray) { oflags |= OPTICAL_FLAG_ENABLE_LEDADD; } status = gl847_init_optical_regs_scan (dev, reg, exposure_time, used_res, start, used_pixels, channels, depth, half_ccd, color_filter, oflags); if (status != SANE_STATUS_GOOD) return status; /*** motor parameters ***/ /* max_shift */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,flags); /* lincnt */ lincnt = lines + max_shift + stagger; /* add tl_y to base movement */ move = starty; DBG (DBG_info, "gl847_init_scan_regs: move=%d steps\n", move); mflags=0; if(flags & SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE) mflags |= MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE; if(flags & SCAN_FLAG_FEEDING) mflags |= MOTOR_FLAG_FEED; status = gl847_init_motor_regs_scan (dev, reg, exposure_time, slope_dpi, scan_step_type, dev->model->is_cis ? lincnt * channels : lincnt, dummy, move, scan_power_mode, mflags); if (status != SANE_STATUS_GOOD) return status; /*** prepares data reordering ***/ /* words_per_line */ bytes_per_line = (used_pixels * used_res) / optical_res; bytes_per_line = (bytes_per_line * channels * depth) / 8; requested_buffer_size = 8 * bytes_per_line; /* we must use a round number of bytes_per_line */ /* XXX STEF XXX if (requested_buffer_size > BULKIN_MAXSIZE) requested_buffer_size = (BULKIN_MAXSIZE / bytes_per_line) * bytes_per_line; */ read_buffer_size = 2 * requested_buffer_size + ((max_shift + stagger) * used_pixels * channels * depth) / 8; RIE (sanei_genesys_buffer_free (&(dev->read_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->lines_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer), requested_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->out_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer), (8 * dev->settings.pixels * channels * depth) / 8)); dev->read_bytes_left = bytes_per_line * lincnt; DBG (DBG_info, "gl847_init_scan_regs: physical bytes to read = %lu\n", (u_long) dev->read_bytes_left); dev->read_active = SANE_TRUE; dev->current_setup.pixels = (used_pixels * used_res) / optical_res; dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure_time; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; /* TODO: should this be done elsewhere? */ /* scan bytes to send to the frontend */ /* theory : target_size = (dev->settings.pixels * dev->settings.lines * channels * depth) / 8; but it suffers from integer overflow so we do the following: 1 bit color images store color data byte-wise, eg byte 0 contains 8 bits of red data, byte 1 contains 8 bits of green, byte 2 contains 8 bits of blue. This does not fix the overflow, though. 644mp*16 = 10gp, leading to an overflow -- pierre */ dev->total_bytes_read = 0; if (depth == 1) dev->total_bytes_to_read = ((dev->settings.pixels * dev->settings.lines) / 8 + (((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) * channels; else dev->total_bytes_to_read = dev->settings.pixels * dev->settings.lines * channels * (depth / 8); DBG (DBG_info, "gl847_init_scan_regs: total bytes to send = %lu\n", (u_long) dev->total_bytes_to_read); /* END TODO */ DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl847_calculate_current_setup (Genesys_Device * dev) { int channels; int depth; int start; float xres; /*dpi */ float yres; /*dpi */ float startx; /*optical_res, from dummy_pixel+1 */ float pixels; float lines; int used_res; int used_pixels; unsigned int lincnt; int exposure_time; int stagger; int slope_dpi = 0; int dummy = 0; int max_shift; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; DBG (DBG_info, "gl847_calculate_current_setup settings:\n" "Resolution: %uDPI\n" "Lines : %u\n" "PPL : %u\n" "Startpos : %.3f/%.3f\n" "Scan mode : %d\n\n", dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* channels */ if (dev->settings.scan_mode == 4) /* single pass color */ channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == 0) depth = 1; /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; xres = dev->settings.xres; /*dpi */ yres = dev->settings.yres; /*dpi */ startx = start; /*optical_res, from dummy_pixel+1 */ pixels = dev->settings.pixels; lines = dev->settings.lines; DBG (DBG_info, "gl847_calculate_current_setup settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g\n" "Depth/Channels: %u/%u\n\n", xres, yres, lines, pixels, startx, depth, channels); /* half_ccd */ /* we have 2 domains for ccd: xres below or above half ccd max dpi */ if ((dev->sensor.optical_res < 2 * xres) || !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)) { half_ccd = SANE_FALSE; } else { half_ccd = SANE_TRUE; } /* optical_res */ optical_res = dev->sensor.optical_res; /* stagger */ if (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "gl847_calculate_current_setup: stagger=%d lines\n", stagger); /* resolution is choosen from a fixed list */ used_res = xres; /* compute scan parameters values */ /* pixels are allways given at half or full CCD optical resolution */ /* use detected left margin and fixed value */ /* compute correct pixels number */ used_pixels = (pixels * optical_res) / used_res; dummy = 3-channels; /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ if (dev->model->is_cis) slope_dpi = yres * channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); exposure_time = gl847_compute_exposure (dev, used_res); DBG (DBG_info, "%s : exposure_time=%d pixels\n", __func__, exposure_time); /* max_shift */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0); /* lincnt */ lincnt = lines + max_shift + stagger; dev->current_setup.pixels = (used_pixels * used_res) / optical_res; dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure_time; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; DBGCOMPLETED; return SANE_STATUS_GOOD; } static void gl847_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set) { DBG (DBG_proc, "gl847_set_motor_power\n"); if (set) { sanei_genesys_set_reg_from_set (regs, REG02, sanei_genesys_read_reg_from_set (regs, REG02) | REG02_MTRPWR); } else { sanei_genesys_set_reg_from_set (regs, REG02, sanei_genesys_read_reg_from_set (regs, REG02) & ~REG02_MTRPWR); } } static void gl847_set_lamp_power (Genesys_Device __sane_unused__ * dev, Genesys_Register_Set * regs, SANE_Bool set) { if (set) { sanei_genesys_set_reg_from_set (regs, REG03, sanei_genesys_read_reg_from_set (regs, REG03) | REG03_LAMPPWR); } else { sanei_genesys_set_reg_from_set (regs, REG03, sanei_genesys_read_reg_from_set (regs, REG03) & ~REG03_LAMPPWR); } } /*for fast power saving methods only, like disabling certain amplifiers*/ static SANE_Status gl847_save_power (Genesys_Device * dev, SANE_Bool enable) { DBG (DBG_proc, "gl847_save_power: enable = %d\n", enable); if (dev == NULL) return SANE_STATUS_INVAL; DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl847_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ ) { DBG (DBG_proc, "gl847_set_powersaving (delay = %d)\n", delay); if (dev == NULL) return SANE_STATUS_INVAL; DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl847_start_action (Genesys_Device * dev) { return sanei_genesys_write_register (dev, 0x0f, 0x01); } #ifndef UNIT_TESTING static #endif SANE_Status gl847_stop_action (Genesys_Device * dev) { SANE_Status status; uint8_t val40, val; unsigned int loop; DBGSTART; /* post scan gpio : without that HOMSNR is unreliable */ gl847_homsnr_gpio(dev); status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } status = sanei_genesys_read_register (dev, REG40, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* only stop action if needed */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)) { DBG (DBG_info, "%s: already stopped\n", __func__); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* ends scan */ val = sanei_genesys_read_reg_from_set (dev->reg, REG01); val &= ~REG01_SCAN; sanei_genesys_set_reg_from_set (dev->reg, REG01, val); status = sanei_genesys_write_register (dev, REG01, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write register 01: %s\n", __func__, sane_strstatus (status)); return status; } usleep (100 * 1000); loop = 10; while (loop > 0) { status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } status = sanei_genesys_read_register (dev, REG40, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* if scanner is in command mode, we are done */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG) && !(val & REG41_MOTORENB)) { DBGCOMPLETED; return SANE_STATUS_GOOD; } usleep (100 * 1000); loop--; } DBGCOMPLETED; return SANE_STATUS_IO_ERROR; } /* Send the low-level scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor) { SANE_Status status; uint8_t val; Genesys_Register_Set *r; DBGSTART; /* clear GPIO 10 */ if (dev->model->gpo_type != GPO_CANONLIDE700) { RIE (sanei_genesys_read_register (dev, REG6C, &val)); val &= ~REG6C_GPIO10; RIE (sanei_genesys_write_register (dev, REG6C, val)); } val = REG0D_CLRLNCNT; RIE (sanei_genesys_write_register (dev, REG0D, val)); val = REG0D_CLRMCNT; RIE (sanei_genesys_write_register (dev, REG0D, val)); RIE (sanei_genesys_read_register (dev, REG01, &val)); val |= REG01_SCAN; RIE (sanei_genesys_write_register (dev, REG01, val)); r = sanei_genesys_get_address (reg, REG01); r->value = val; if (start_motor) { RIE (sanei_genesys_write_register (dev, REG0F, 1)); } else { RIE (sanei_genesys_write_register (dev, REG0F, 0)); } DBGCOMPLETED; return status; } /* Send the stop scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop) { SANE_Status status; DBG (DBG_proc, "gl847_end_scan (check_stop = %d)\n", check_stop); if (reg == NULL) return SANE_STATUS_INVAL; if (dev->model->is_sheetfed == SANE_TRUE) { status = SANE_STATUS_GOOD; } else /* flat bed scanners */ { status = gl847_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_end_scan: failed to stop: %s\n", sane_strstatus (status)); return status; } } DBGCOMPLETED; return status; } /** rewind scan * Move back by the same amount of distance than previous scan. * @param dev device to rewind * @returns SANE_STATUS_GOOD on success */ GENESYS_STATIC SANE_Status gl847_rewind(Genesys_Device * dev) { SANE_Status status; uint8_t byte; DBGSTART; /* set motor reverse */ RIE (sanei_genesys_read_register (dev, 0x02, &byte)); byte |= 0x04; RIE (sanei_genesys_write_register(dev, 0x02, byte)); /* and start scan, then wait completion */ RIE (gl847_begin_scan (dev, dev->reg, SANE_TRUE)); do { usleep(100*1000); RIE (sanei_genesys_read_register (dev, REG40, &byte)); } while(byte & REG40_MOTMFLG); RIE (gl847_end_scan (dev, dev->reg, SANE_TRUE)); /* restore direction */ RIE (sanei_genesys_read_register (dev, 0x02, &byte)); byte &= 0xfb; RIE (sanei_genesys_write_register(dev, 0x02, byte)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** Park head * Moves the slider to the home (top) position slowly * @param dev device to park * @param wait_until_home true to make the function waiting for head * to be home before returning, if fals returne immediately * @returns SANE_STATUS_GOO on success */ GENESYS_STATIC SANE_Status gl847_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) { Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; float resolution; uint8_t val; int loop = 0; int scan_mode; DBG (DBG_proc, "gl847_slow_back_home (wait_until_home = %d)\n", wait_until_home); /* post scan gpio : without that HOMSNR is unreliable */ gl847_homsnr_gpio(dev); /* first read gives HOME_SENSOR true */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } usleep (100000); /* sleep 100 ms */ /* second is reliable */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } /* is sensor at home? */ if (val & HOMESNR) { DBG (DBG_info, "%s: already at home, completed\n", __func__); dev->scanhead_position_in_steps = 0; DBGCOMPLETED; return SANE_STATUS_GOOD; } memcpy (local_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); /* TODO add scan_mode to the API */ scan_mode= dev->settings.scan_mode; dev->settings.scan_mode=SCAN_MODE_LINEART; status = gl847_init_scan_regs (dev, local_reg, resolution, resolution, 100, 30000, 100, 100, 8, 1, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_slow_back_home: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } dev->settings.scan_mode=scan_mode; /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); /* set up for reverse */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS)); status = gl847_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_slow_back_home: failed to start motor: %s\n", sane_strstatus (status)); gl847_stop_action (dev); /* send original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL847_MAX_REGS); return status; } /* post scan gpio : without that HOMSNR is unreliable */ gl847_homsnr_gpio(dev); if (wait_until_home) { while (loop < 300) /* do not wait longer then 30 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (val & HOMESNR) /* home sensor */ { DBG (DBG_info, "gl847_slow_back_home: reached home position\n"); gl847_stop_action (dev); dev->scanhead_position_in_steps = 0; DBGCOMPLETED; return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ ++loop; } /* when we come here then the scanner needed too much time for this, so we better stop the motor */ gl847_stop_action (dev); DBG (DBG_error, "gl847_slow_back_home: timeout while waiting for scanhead to go home\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_info, "gl847_slow_back_home: scanhead is still moving\n"); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi from very top of scanner */ static SANE_Status gl847_search_start_position (Genesys_Device * dev) { int size; SANE_Status status; uint8_t *data; Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS]; int steps; int pixels = 600; int dpi = 300; DBG (DBG_proc, "gl847_search_start_position\n"); memcpy (local_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); /* sets for a 200 lines * 600 pixels */ /* normal scan with no shading */ status = gl847_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, /*we should give a small offset here~60 steps */ 600, dev->model->search_lines, 8, 1, 1, /*green */ SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_search_start_position: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } /* send to scanner */ status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_search_start_position: failed to bulk write registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } size = pixels * dev->model->search_lines; data = malloc (size); if (!data) { DBG (DBG_error, "gl847_search_start_position: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } status = gl847_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_start_position: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, pixels, dev->model->search_lines); status = gl847_end_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_start_position: failed to end scan: %s\n", sane_strstatus (status)); return status; } /* update regs to copy ASIC internal state */ memcpy (dev->reg, local_reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); /*TODO: find out where sanei_genesys_search_reference_point stores information, and use that correctly*/ status = sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels, dev->model->search_lines); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_start_position: failed to set search reference point: %s\n", sane_strstatus (status)); return status; } free (data); return SANE_STATUS_GOOD; } /* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status gl847_init_regs_for_coarse_calibration (Genesys_Device * dev) { SANE_Status status; uint8_t channels; uint8_t cksel; DBG (DBG_proc, "gl847_init_regs_for_coarse_calibration\n"); cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */ /* set line size */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; status = gl847_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, dev->sensor.optical_res / cksel, 20, 16, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_init_register_for_coarse_calibration: Failed to setup scan: %s\n", sane_strstatus (status)); return status; } DBG (DBG_info, "gl847_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n", dev->sensor.optical_res / cksel, dev->settings.xres); status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_init_register_for_coarse_calibration: Failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief moves the slider to steps at motor base dpi * @param dev device to work on * @param steps number of steps to move in base_dpi line count * */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_feed (Genesys_Device * dev, unsigned int steps) { Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; float resolution; uint8_t val; DBGSTART; DBG (DBG_io, "%s: steps=%d\n", __func__, steps); /* prepare local registers */ memcpy (local_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); status = gl847_init_scan_regs (dev, local_reg, resolution, resolution, 0, steps, 100, 3, 8, 3, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_FEEDING | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_feed: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } /* set exposure to zero */ sanei_genesys_set_triple(local_reg,REG_EXPR,0); sanei_genesys_set_triple(local_reg,REG_EXPG,0); sanei_genesys_set_triple(local_reg,REG_EXPB,0); /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT)); RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT)); /* set up for no scan */ r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; /* send registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS)); status = gl847_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to start motor: %s\n", __func__, sane_strstatus (status)); gl847_stop_action (dev); /* restore original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL847_MAX_REGS); return status; } /* wait until feed count reaches the required value, but do not * exceed 30s */ do { status = sanei_genesys_get_status (dev, &val); } while (status == SANE_STATUS_GOOD && !(val & FEEDFSH)); /* then stop scanning */ RIE(gl847_stop_action (dev)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* init registers for shading calibration */ static SANE_Status gl847_init_regs_for_shading (Genesys_Device * dev) { SANE_Status status; float move; DBGSTART; dev->calib_channels = 3; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); dev->calib_resolution = sanei_genesys_compute_dpihw(dev,dev->settings.xres); dev->calib_lines = dev->model->shading_lines; if(dev->calib_resolution==4800) dev->calib_lines *= 2; dev->calib_pixels = (dev->sensor.sensor_pixels*dev->calib_resolution)/dev->sensor.optical_res; DBG (DBG_io, "%s: calib_lines = %d\n", __func__, (int)dev->calib_lines); DBG (DBG_io, "%s: calib_pixels = %d\n", __func__, (int)dev->calib_pixels); /* this is aworkaround insufficent distance for slope * motor acceleration TODO special motor slope for shading */ move=1; if(dev->calib_resolution<1200) { move=40; } status = gl847_init_scan_regs (dev, dev->calib_reg, dev->calib_resolution, dev->calib_resolution, 0, move, dev->calib_pixels, dev->calib_lines, 16, dev->calib_channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to bulk write registers: %s\n", __func__, sane_strstatus (status)); return status; } /* we use GENESYS_FLAG_SHADING_REPARK */ dev->scanhead_position_in_steps = 0; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief set up registers for the actual scan */ static SANE_Status gl847_init_regs_for_scan (Genesys_Device * dev) { int channels; int flags; int depth; float move; int move_dpi; float start; SANE_Status status; DBG (DBG_info, "gl847_init_regs_for_scan settings:\nResolution: %uDPI\n" "Lines : %u\nPPL : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n", dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* channels */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == SCAN_MODE_LINEART) depth = 1; /* steps to move to reach scanning area: - first we move to physical start of scanning either by a fixed steps amount from the black strip or by a fixed amount from parking position, minus the steps done during shading calibration - then we move by the needed offset whitin physical scanning area assumption: steps are expressed at maximum motor resolution we need: SANE_Fixed y_offset; SANE_Fixed y_size; SANE_Fixed y_offset_calib; mm_to_steps()=motor dpi / 2.54 / 10=motor dpi / MM_PER_INCH */ /* if scanner uses GENESYS_FLAG_SEARCH_START y_offset is relative from origin, else, it is from parking position */ move_dpi = dev->motor.base_ydpi; move = SANE_UNFIX (dev->model->y_offset); move += dev->settings.tl_y; move = (move * move_dpi) / MM_PER_INCH; move -= dev->scanhead_position_in_steps; DBG (DBG_info, "%s: move=%f steps\n",__func__, move); /* fast move to scan area */ /* we don't move fast the whole distance since it would involve * computing acceleration/deceleration distance for scan * resolution. So leave a remainder for it so scan makes the final * move tuning */ if(channels*dev->settings.yres>=600 && move>700) { status = gl847_feed (dev, move-500); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to move to scan area\n",__func__); return status; } move=500; } DBG (DBG_info, "gl124_init_regs_for_scan: move=%f steps\n", move); DBG (DBG_info, "%s: move=%f steps\n", __func__, move); /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; flags = 0; /* emulated lineart from gray data is required for now */ if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; } /* backtracking isn't handled well, so don't enable it */ flags |= SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE; status = gl847_init_scan_regs (dev, dev->reg, dev->settings.xres, dev->settings.yres, start, move, dev->settings.pixels, dev->settings.lines, depth, channels, dev->settings.color_filter, flags); if (status != SANE_STATUS_GOOD) return status; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * Send shading calibration data. The buffer is considered to always hold values * for all the channels. */ static SANE_Status gl847_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) { SANE_Status status = SANE_STATUS_GOOD; uint32_t addr, length, i, x, factor, pixels; uint32_t dpiset, dpihw, strpixel, endpixel; uint16_t tempo; uint32_t lines, channels; uint8_t val,*buffer,*ptr,*src; DBGSTART; DBG( DBG_io2, "%s: writing %d bytes of shading data\n",__func__,size); /* shading data is plit in 3 (up to 5 with IR) areas write(0x10014000,0x00000dd8) URB 23429 bulk_out len 3544 wrote 0x33 0x10 0x.... write(0x1003e000,0x00000dd8) write(0x10068000,0x00000dd8) */ length = (uint32_t) (size / 3); sanei_genesys_get_double(dev->reg,REG_STRPIXEL,&tempo); strpixel=tempo; sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&tempo); endpixel=tempo; /* compute deletion factor */ sanei_genesys_get_double(dev->reg,REG_DPISET,&tempo); dpiset=tempo; DBG( DBG_io2, "%s: STRPIXEL=%d, ENDPIXEL=%d, PIXELS=%d, DPISET=%d\n",__func__,strpixel,endpixel,endpixel-strpixel,dpiset); dpihw=sanei_genesys_compute_dpihw(dev,dpiset); factor=dpihw/dpiset; DBG( DBG_io2, "%s: factor=%d\n",__func__,factor); if(DBG_LEVEL>=DBG_data) { dev->binary=fopen("binary.pnm","wb"); sanei_genesys_get_triple(dev->reg, REG_LINCNT, &lines); channels=dev->current_setup.channels; if(dev->binary!=NULL) { fprintf(dev->binary,"P5\n%d %d\n%d\n",(endpixel-strpixel)/factor*channels,lines/channels,255); } } pixels=endpixel-strpixel; /* since we're using SHDAREA, substract startx coordinate from shading */ strpixel-=((dev->sensor.CCD_start_xoffset*600)/dev->sensor.optical_res); /* turn pixel value into bytes 2x16 bits words */ strpixel*=2*2; pixels*=2*2; /* allocate temporary buffer */ buffer=(uint8_t *)malloc(pixels); memset(buffer,0,pixels); DBG( DBG_io2, "%s: using chunks of %d (0x%04x) bytes\n",__func__,pixels,pixels); /* base addr of data has been written in reg D0-D4 in 4K word, so AHB address * is 8192*reg value */ /* write actual color channel data */ for(i=0;i<3;i++) { /* build up actual shading data by copying the part from the full width one * to the one corresponding to SHDAREA */ ptr=buffer; /* iterate on both sensor segment */ for(x=0;xdn, dev->usb_mode, addr, pixels, buffer); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_send_shading_data; write to AHB failed (%s)\n", sane_strstatus (status)); return status; } } free(buffer); DBGCOMPLETED; return status; } /** @brief calibrates led exposure * Calibrate exposure by scanning a white area until the used exposure gives * data white enough. * @param dev device to calibrate */ static SANE_Status gl847_led_calibration (Genesys_Device * dev) { int num_pixels; int total_size; int used_res; uint8_t *line; int i, j; SANE_Status status = SANE_STATUS_GOOD; int val; int channels, depth; int avg[3], top[3], bottom[3]; int turn; char fn[20]; uint16_t exp[3]; Sensor_Profile *sensor; float move; SANE_Bool acceptable; DBGSTART; move = SANE_UNFIX (dev->model->y_offset_calib); move = (move * (dev->motor.base_ydpi/4)) / MM_PER_INCH; if(move>20) { RIE(gl847_feed (dev, move)); } DBG (DBG_io, "%s: move=%f steps\n", __func__, move); /* offset calibration is always done in color mode */ channels = 3; depth=16; used_res=sanei_genesys_compute_dpihw(dev,dev->settings.xres); sensor=get_sensor_profile(dev->model->ccd_type, used_res); num_pixels = (dev->sensor.sensor_pixels*used_res)/dev->sensor.optical_res; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); /* set up for the calibration scan */ status = gl847_init_scan_regs (dev, dev->calib_reg, used_res, used_res, 0, 0, num_pixels, 1, depth, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } total_size = num_pixels * channels * (depth/8) * 1; /* colors * bytes_per_color * scan lines */ line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; /* initial loop values and boundaries */ exp[0]=sensor->expr; exp[1]=sensor->expg; exp[2]=sensor->expb; bottom[0]=29000; bottom[1]=29000; bottom[2]=29000; top[0]=41000; top[1]=51000; top[2]=51000; turn = 0; /* no move during led calibration */ gl847_set_motor_power (dev->calib_reg, SANE_FALSE); do { /* set up exposure */ sanei_genesys_set_double(dev->calib_reg,REG_EXPR,exp[0]); sanei_genesys_set_double(dev->calib_reg,REG_EXPG,exp[1]); sanei_genesys_set_double(dev->calib_reg,REG_EXPB,exp[2]); /* write registers and scan data */ RIEF (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS), line); DBG (DBG_info, "gl847_led_calibration: starting line reading\n"); RIEF (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); /* stop scanning */ RIEF (gl847_stop_action (dev), line); if (DBG_LEVEL >= DBG_data) { snprintf (fn, 20, "led_%02d.pnm", turn); sanei_genesys_write_pnm_file (fn, line, depth, channels, num_pixels, 1); } /* compute average */ for (j = 0; j < channels; j++) { avg[j] = 0; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * num_pixels + 1] * 256 + line[i * 2 + j * 2 * num_pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; avg[j] += val; } avg[j] /= num_pixels; } DBG (DBG_info, "gl847_led_calibration: average: %d,%d,%d\n", avg[0], avg[1], avg[2]); /* check if exposure gives average within the boundaries */ acceptable = SANE_TRUE; for(i=0;i<3;i++) { if(avg[i]top[i]) { exp[i]=(exp[i]*top[i])/avg[i]; acceptable = SANE_FALSE; } } turn++; } while (!acceptable && turn < 100); DBG (DBG_info, "gl847_led_calibration: acceptable exposure: %d,%d,%d\n", exp[0], exp[1], exp[2]); /* set these values as final ones for scan */ sanei_genesys_set_double(dev->reg,REG_EXPR,exp[0]); sanei_genesys_set_double(dev->reg,REG_EXPG,exp[1]); sanei_genesys_set_double(dev->reg,REG_EXPB,exp[2]); /* store in this struct since it is the one used by cache calibration */ dev->sensor.regs_0x10_0x1d[0] = (exp[0] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[1] = exp[0] & 0xff; dev->sensor.regs_0x10_0x1d[2] = (exp[1] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[3] = exp[1] & 0xff; dev->sensor.regs_0x10_0x1d[4] = (exp[2] >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[5] = exp[2] & 0xff; /* cleanup before return */ free (line); /* go back home */ if(move>20) { status=gl847_slow_back_home (dev, SANE_TRUE); } DBGCOMPLETED; return status; } /** * set up GPIO/GPOE for idle state */ static SANE_Status gl847_init_gpio (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; int idx=0; DBGSTART; /* search GPIO profile */ while(gpios[idx].sensor_id!=0 && dev->model->gpo_type!=gpios[idx].sensor_id) { idx++; } if(gpios[idx].sensor_id==0) { DBG (DBG_error, "%s: failed to find GPIO profile for sensor_id=%d\n", __func__, dev->model->ccd_type); return SANE_STATUS_INVAL; } RIE (sanei_genesys_write_register (dev, REGA7, gpios[idx].ra7)); RIE (sanei_genesys_write_register (dev, REGA6, gpios[idx].ra6)); RIE (sanei_genesys_write_register (dev, REG6E, gpios[idx].r6e)); RIE (sanei_genesys_write_register (dev, REG6C, 0x00)); RIE (sanei_genesys_write_register (dev, REG6B, gpios[idx].r6b)); RIE (sanei_genesys_write_register (dev, REG6C, gpios[idx].r6c)); RIE (sanei_genesys_write_register (dev, REG6D, gpios[idx].r6d)); RIE (sanei_genesys_write_register (dev, REG6E, gpios[idx].r6e)); RIE (sanei_genesys_write_register (dev, REG6F, gpios[idx].r6f)); RIE (sanei_genesys_write_register (dev, REGA8, gpios[idx].ra8)); RIE (sanei_genesys_write_register (dev, REGA9, gpios[idx].ra9)); DBGCOMPLETED; return status; } /** * set memory layout by filling values in dedicated registers */ static SANE_Status gl847_init_memory_layout (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; int idx = 0; uint8_t val; DBG (DBG_proc, "gl847_init_memory_layout\n"); /* point to per model memory layout */ idx = 0; if (strcmp (dev->model->name, "canon-lide-100") == 0) { idx = 0; } if (strcmp (dev->model->name, "canon-lide-200") == 0) { idx = 1; } if (strcmp (dev->model->name, "canon-5600f") == 0) { idx = 2; } if (strcmp (dev->model->name, "canon-lide-700f") == 0) { idx = 3; } /* CLKSET nd DRAMSEL */ val = layouts[idx].dramsel; RIE (sanei_genesys_write_register (dev, REG0B, val)); dev->reg[reg_0x0b].value = val; /* prevent further writings by bulk write register */ dev->reg[reg_0x0b].address = 0x00; /* setup base address for shading data. */ /* values must be multiplied by 8192=0x4000 to give address on AHB */ /* R-Channel shading bank0 address setting for CIS */ sanei_genesys_write_register (dev, 0xd0, layouts[idx].rd0); /* G-Channel shading bank0 address setting for CIS */ sanei_genesys_write_register (dev, 0xd1, layouts[idx].rd1); /* B-Channel shading bank0 address setting for CIS */ sanei_genesys_write_register (dev, 0xd2, layouts[idx].rd2); /* setup base address for scanned data. */ /* values must be multiplied by 1024*2=0x0800 to give address on AHB */ /* R-Channel ODD image buffer 0x0124->0x92000 */ /* size for each buffer is 0x16d*1k word */ sanei_genesys_write_register (dev, 0xe0, layouts[idx].re0); sanei_genesys_write_register (dev, 0xe1, layouts[idx].re1); /* R-Channel ODD image buffer end-address 0x0291->0x148800 => size=0xB6800*/ sanei_genesys_write_register (dev, 0xe2, layouts[idx].re2); sanei_genesys_write_register (dev, 0xe3, layouts[idx].re3); /* R-Channel EVEN image buffer 0x0292 */ sanei_genesys_write_register (dev, 0xe4, layouts[idx].re4); sanei_genesys_write_register (dev, 0xe5, layouts[idx].re5); /* R-Channel EVEN image buffer end-address 0x03ff*/ sanei_genesys_write_register (dev, 0xe6, layouts[idx].re6); sanei_genesys_write_register (dev, 0xe7, layouts[idx].re7); /* same for green, since CIS, same addresses */ sanei_genesys_write_register (dev, 0xe8, layouts[idx].re0); sanei_genesys_write_register (dev, 0xe9, layouts[idx].re1); sanei_genesys_write_register (dev, 0xea, layouts[idx].re2); sanei_genesys_write_register (dev, 0xeb, layouts[idx].re3); sanei_genesys_write_register (dev, 0xec, layouts[idx].re4); sanei_genesys_write_register (dev, 0xed, layouts[idx].re5); sanei_genesys_write_register (dev, 0xee, layouts[idx].re6); sanei_genesys_write_register (dev, 0xef, layouts[idx].re7); /* same for blue, since CIS, same addresses */ sanei_genesys_write_register (dev, 0xf0, layouts[idx].re0); sanei_genesys_write_register (dev, 0xf1, layouts[idx].re1); sanei_genesys_write_register (dev, 0xf2, layouts[idx].re2); sanei_genesys_write_register (dev, 0xf3, layouts[idx].re3); sanei_genesys_write_register (dev, 0xf4, layouts[idx].re4); sanei_genesys_write_register (dev, 0xf5, layouts[idx].re5); sanei_genesys_write_register (dev, 0xf6, layouts[idx].re6); sanei_genesys_write_register (dev, 0xf7, layouts[idx].re7); DBGCOMPLETED; return status; } /* * * initialize ASIC from power on condition */ static SANE_Status gl847_boot (Genesys_Device * dev, SANE_Bool cold) { SANE_Status status; uint8_t val; DBGSTART; /* reset ASIC if cold boot */ if(cold) { RIE (sanei_genesys_write_register (dev, 0x0e, 0x01)); RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); } /* test CHKVER */ RIE (sanei_genesys_read_register (dev, REG40, &val)); if (val & REG40_CHKVER) { RIE (sanei_genesys_read_register (dev, 0x00, &val)); DBG (DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val); } /* Set default values for registers */ gl847_init_registers (dev); /* Write initial registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL847_MAX_REGS)); /* Enable DRAM by setting a rising edge on bit 3 of reg 0x0b */ val = dev->reg[reg_0x0b].value & REG0B_DRAMSEL; val = (val | REG0B_ENBDRAM); RIE (sanei_genesys_write_register (dev, REG0B, val)); dev->reg[reg_0x0b].value = val; /* CIS_LINE */ SETREG (0x08, REG08_CIS_LINE); RIE (sanei_genesys_write_register (dev, 0x08, dev->reg[reg_0x08].value)); /* set up end access */ RIE (sanei_genesys_write_0x8c (dev, 0x10, 0x0b)); RIE (sanei_genesys_write_0x8c (dev, 0x13, 0x0e)); /* setup gpio */ RIE (gl847_init_gpio (dev)); /* setup internal memory layout */ RIE (gl847_init_memory_layout (dev)); SETREG (0xf8, 0x01); RIE (sanei_genesys_write_register (dev, 0xf8, dev->reg[reg_0xf8].value)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * initialize backend and ASIC : registers, motor tables, and gamma tables * then ensure scanner's head is at home */ #ifndef UNIT_TESTING static #endif SANE_Status gl847_init (Genesys_Device * dev) { SANE_Status status; DBG_INIT (); DBGSTART; status=sanei_genesys_asic_init(dev, GENESYS_GL847_MAX_REGS); DBGCOMPLETED; return status; } static SANE_Status gl847_update_hardware_sensors (Genesys_Scanner * s) { /* do what is needed to get a new set of events, but try to not lose any of them. */ SANE_Status status = SANE_STATUS_GOOD; uint8_t val; uint8_t scan, file, email, copy; switch(s->dev->model->gpo_type) { case GPO_CANONLIDE700: scan=0x04; file=0x02; email=0x01; copy=0x08; break; default: scan=0x01; file=0x02; email=0x04; copy=0x08; } RIE (sanei_genesys_read_register (s->dev, REG6D, &val)); if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b) s->val[OPT_SCAN_SW].b = (val & scan) == 0; if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b) s->val[OPT_FILE_SW].b = (val & file) == 0; if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b) s->val[OPT_EMAIL_SW].b = (val & email) == 0; if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b) s->val[OPT_COPY_SW].b = (val & copy) == 0; return status; } /** @brief search for a full width black or white strip. * This function searches for a black or white stripe across the scanning area. * When searching backward, the searched area must completely be of the desired * color since this area will be used for calibration which scans forward. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward * @param black SANE_TRUE if searching for a black strip, SANE_FALSE for a white strip * @return SANE_STATUS_GOOD if a matching strip is found, SANE_STATUS_UNSUPPORTED if not */ static SANE_Status gl847_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black) { unsigned int pixels, lines, channels; SANE_Status status; Genesys_Register_Set local_reg[GENESYS_GL847_MAX_REGS]; size_t size; uint8_t *data; int steps, depth, dpi; unsigned int pass, count, found, x, y; char title[80]; Genesys_Register_Set *r; DBG (DBG_proc, "gl847_search_strip %s %s\n", black ? "black" : "white", forward ? "forward" : "reverse"); gl847_set_fe (dev, AFE_SET); status = gl847_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_search_strip: failed to stop: %s\n", sane_strstatus (status)); return status; } /* set up for a gray scan at lowest dpi */ dpi = 9600; for (x = 0; x < MAX_RESOLUTIONS; x++) { if (dev->model->xdpi_values[x] > 0 && dev->model->xdpi_values[x] < dpi) dpi = dev->model->xdpi_values[x]; } channels = 1; /* 10 MM */ /* lines = (10 * dpi) / MM_PER_INCH; */ /* shading calibation is done with dev->motor.base_ydpi */ lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi; depth = 8; pixels = (dev->sensor.sensor_pixels * dpi) / dev->sensor.optical_res; size = pixels * channels * lines * (depth / 8); data = malloc (size); if (!data) { DBG (DBG_error, "gl847_search_strip: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } dev->scanhead_position_in_steps = 0; memcpy (local_reg, dev->reg, GENESYS_GL847_MAX_REGS * sizeof (Genesys_Register_Set)); status = gl847_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, pixels, lines, depth, channels, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "gl847_search_strip: failed to setup for scan: %s\n", sane_strstatus (status)); return status; } /* set up for reverse or forward */ r = sanei_genesys_get_address (local_reg, REG02); if (forward) r->value &= ~REG02_MTRREV; else r->value |= REG02_MTRREV; status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "gl847_search_strip: Failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } status = gl847_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_strip: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } status = gl847_stop_action (dev); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_strip: gl847_stop_action failed\n"); return status; } pass = 0; if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s_%s%02d.pnm", black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass); sanei_genesys_write_pnm_file (title, data, depth, channels, pixels, lines); } /* loop until strip is found or maximum pass number done */ found = 0; while (pass < 20 && !found) { status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL847_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_search_strip: Failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } /* now start scan */ status = gl847_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_strip: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } status = gl847_stop_action (dev); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl847_search_strip: gl847_stop_action failed\n"); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s_%s%02d.pnm", black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass); sanei_genesys_write_pnm_file (title, data, depth, channels, pixels, lines); } /* search data to find black strip */ /* when searching forward, we only need one line of the searched color since we * will scan forward. But when doing backward search, we need all the area of the * same color */ if (forward) { for (y = 0; y < lines && !found; y++) { count = 0; /* count of white/black pixels depending on the color searched */ for (x = 0; x < pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * pixels + x] > 90) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * pixels + x] < 60) { count++; } } /* at end of line, if count >= 3%, line is not fully of the desired color * so we must go to next line of the buffer */ /* count*100/pixels < 3 */ if ((count * 100) / pixels < 3) { found = 1; DBG (DBG_data, "gl847_search_strip: strip found forward during pass %d at line %d\n", pass, y); } else { DBG (DBG_data, "gl847_search_strip: pixels=%d, count=%d (%d%%)\n", pixels, count, (100 * count) / pixels); } } } else /* since calibration scans are done forward, we need the whole area to be of the required color when searching backward */ { count = 0; for (y = 0; y < lines; y++) { /* count of white/black pixels depending on the color searched */ for (x = 0; x < pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * pixels + x] > 90) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * pixels + x] < 60) { count++; } } } /* at end of area, if count >= 3%, area is not fully of the desired color * so we must go to next buffer */ if ((count * 100) / (pixels * lines) < 3) { found = 1; DBG (DBG_data, "gl847_search_strip: strip found backward during pass %d \n", pass); } else { DBG (DBG_data, "gl847_search_strip: pixels=%d, count=%d (%d%%)\n", pixels, count, (100 * count) / pixels); } } pass++; } free (data); if (found) { status = SANE_STATUS_GOOD; DBG (DBG_info, "gl847_search_strip: %s strip found\n", black ? "black" : "white"); } else { status = SANE_STATUS_UNSUPPORTED; DBG (DBG_info, "gl847_search_strip: %s strip not found\n", black ? "black" : "white"); } DBGCOMPLETED; return status; } /** * average dark pixels of a 8 bits scan */ static int dark_average (uint8_t * data, unsigned int pixels, unsigned int lines, unsigned int channels, unsigned int black) { unsigned int i, j, k, average, count; unsigned int avg[3]; uint8_t val; /* computes average value on black margin */ for (k = 0; k < channels; k++) { avg[k] = 0; count = 0; for (i = 0; i < lines; i++) { for (j = 0; j < black; j++) { val = data[i * channels * pixels + j + k]; avg[k] += val; count++; } } if (count) avg[k] /= count; DBG (DBG_info, "dark_average: avg[%d] = %d\n", k, avg[k]); } average = 0; for (i = 0; i < channels; i++) average += avg[i]; average /= channels; DBG (DBG_info, "dark_average: average = %d\n", average); return average; } static SANE_Status gl847_offset_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; uint8_t *first_line, *second_line, reg04; unsigned int channels, bpp; char title[32]; int pass = 0, avg, total_size; int topavg, bottomavg, resolution, lines; int top, bottom, black_pixels, pixels; DBGSTART; /* no gain nor offset for AKM AFE */ RIE (sanei_genesys_read_register (dev, REG04, ®04)); if ((reg04 & REG04_FESET) == 0x02) { DBGCOMPLETED; return status; } /* offset calibration is always done in color mode */ channels = 3; resolution=dev->sensor.optical_res; dev->calib_pixels = dev->sensor.sensor_pixels; lines=1; bpp=8; pixels= (dev->sensor.sensor_pixels*resolution) / dev->sensor.optical_res; black_pixels = (dev->sensor.black_pixels * resolution) / dev->sensor.optical_res; DBG (DBG_io2, "gl847_offset_calibration: black_pixels=%d\n", black_pixels); status = gl847_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, pixels, lines, bpp, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_offset_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } gl847_set_motor_power (dev->calib_reg, SANE_FALSE); /* allocate memory for scans */ total_size = pixels * channels * lines * (bpp/8); /* colors * bytes_per_color * scan lines */ first_line = malloc (total_size); if (!first_line) return SANE_STATUS_NO_MEM; second_line = malloc (total_size); if (!second_line) { free (first_line); return SANE_STATUS_NO_MEM; } /* init gain */ dev->frontend.gain[0] = 0; dev->frontend.gain[1] = 0; dev->frontend.gain[2] = 0; /* scan with no move */ bottom = 10; dev->frontend.offset[0] = bottom; dev->frontend.offset[1] = bottom; dev->frontend.offset[2] = bottom; RIEF2 (gl847_set_fe(dev, AFE_SET),first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS),first_line, second_line); DBG (DBG_info, "gl847_offset_calibration: starting first line reading\n"); RIEF2 (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE),first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size),first_line, second_line); if (DBG_LEVEL >= DBG_data) { snprintf(title,20,"offset%03d.pnm",bottom); sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines); } bottomavg = dark_average (first_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl847_offset_calibration: bottom avg=%d\n", bottomavg); /* now top value */ top = 255; dev->frontend.offset[0] = top; dev->frontend.offset[1] = top; dev->frontend.offset[2] = top; RIEF2 (gl847_set_fe(dev, AFE_SET),first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS),first_line, second_line); DBG (DBG_info, "gl847_offset_calibration: starting second line reading\n"); RIEF2 (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE),first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size),first_line, second_line); topavg = dark_average (second_line, pixels, lines, channels, black_pixels); DBG (DBG_io2, "gl847_offset_calibration: top avg=%d\n", topavg); /* loop until acceptable level */ while ((pass < 32) && (top - bottom > 1)) { pass++; /* settings for new scan */ dev->frontend.offset[0] = (top + bottom) / 2; dev->frontend.offset[1] = (top + bottom) / 2; dev->frontend.offset[2] = (top + bottom) / 2; /* scan with no move */ RIEF2 (gl847_set_fe(dev, AFE_SET),first_line, second_line); RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS),first_line, second_line); DBG (DBG_info, "gl847_offset_calibration: starting second line reading\n"); RIEF2 (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE),first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size),first_line, second_line); if (DBG_LEVEL >= DBG_data) { sprintf (title, "offset%03d.pnm", dev->frontend.offset[1]); sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines); } avg = dark_average (second_line, pixels, lines, channels, black_pixels); DBG (DBG_info, "gl847_offset_calibration: avg=%d offset=%d\n", avg, dev->frontend.offset[1]); /* compute new boundaries */ if (topavg == avg) { topavg = avg; top = dev->frontend.offset[1]; } else { bottomavg = avg; bottom = dev->frontend.offset[1]; } } DBG (DBG_info, "gl847_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); /* cleanup before return */ free (first_line); free (second_line); DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl847_coarse_gain_calibration (Genesys_Device * dev, int dpi) { int pixels; int total_size; uint8_t *line, reg04; int i, j, channels; SANE_Status status = SANE_STATUS_GOOD; int max[3]; float gain[3],coeff; int val, code, lines; int resolution; int bpp; DBG (DBG_proc, "gl847_coarse_gain_calibration: dpi = %d\n", dpi); /* no gain nor offset for AKM AFE */ RIE (sanei_genesys_read_register (dev, REG04, ®04)); if ((reg04 & REG04_FESET) == 0x02) { DBGCOMPLETED; return status; } /* coarse gain calibration is always done in color mode */ channels = 3; /* follow CKSEL */ if(dev->settings.xressensor.optical_res) { coeff=0.9; /*resolution=dev->sensor.optical_res/2; */ resolution=dev->sensor.optical_res; } else { resolution=dev->sensor.optical_res; coeff=1.0; } lines=10; bpp=8; pixels = (dev->sensor.sensor_pixels * resolution) / dev->sensor.optical_res; status = gl847_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, pixels, lines, bpp, channels, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); gl847_set_motor_power (dev->calib_reg, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl847_coarse_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } RIE (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL847_MAX_REGS)); total_size = pixels * channels * (16/bpp) * lines; line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; RIEF (gl847_set_fe(dev, AFE_SET), line); RIEF (gl847_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("coarse.pnm", line, bpp, channels, pixels, lines); /* average value on each channel */ for (j = 0; j < channels; j++) { max[j] = 0; for (i = pixels/4; i < (pixels*3/4); i++) { if(bpp==16) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * pixels + 1] * 256 + line[i * 2 + j * 2 * pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; } else { if (dev->model->is_cis) val = line[i + j * pixels]; else val = line[i * channels + j]; } max[j] += val; } max[j] = max[j] / (pixels/2); gain[j] = ((float) dev->sensor.gain_white_ref*coeff) / max[j]; /* turn logical gain value into gain code, checking for overflow */ code = 283 - 208 / gain[j]; if (code > 255) code = 255; else if (code < 0) code = 0; dev->frontend.gain[j] = code; DBG (DBG_proc, "gl847_coarse_gain_calibration: channel %d, max=%d, gain = %f, setting:%d\n", j, max[j], gain[j], dev->frontend.gain[j]); } if (dev->model->is_cis) { if (dev->frontend.gain[0] > dev->frontend.gain[1]) dev->frontend.gain[0] = dev->frontend.gain[1]; if (dev->frontend.gain[0] > dev->frontend.gain[2]) dev->frontend.gain[0] = dev->frontend.gain[2]; dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0]; } if (channels == 1) { dev->frontend.gain[0] = dev->frontend.gain[1]; dev->frontend.gain[2] = dev->frontend.gain[1]; } free (line); RIE (gl847_stop_action (dev)); status=gl847_slow_back_home (dev, SANE_TRUE); DBGCOMPLETED; return status; } /** the gl847 command set */ static Genesys_Command_Set gl847_cmd_set = { "gl847-generic", /* the name of this set */ gl847_init, NULL, /*gl847_init_regs_for_warmup*/ gl847_init_regs_for_coarse_calibration, gl847_init_regs_for_shading, gl847_init_regs_for_scan, gl847_get_filter_bit, gl847_get_lineart_bit, gl847_get_bitset_bit, gl847_get_gain4_bit, gl847_get_fast_feed_bit, gl847_test_buffer_empty_bit, gl847_test_motor_flag_bit, gl847_bulk_full_size, gl847_set_fe, gl847_set_powersaving, gl847_save_power, gl847_set_motor_power, gl847_set_lamp_power, gl847_begin_scan, gl847_end_scan, sanei_genesys_send_gamma_table, gl847_search_start_position, gl847_offset_calibration, gl847_coarse_gain_calibration, gl847_led_calibration, gl847_slow_back_home, gl847_rewind, sanei_genesys_bulk_write_register, NULL, gl847_bulk_read_data, gl847_update_hardware_sensors, NULL, /* no known gl847 sheetfed scanner */ NULL, /* no known gl847 sheetfed scanner */ NULL, /* no known gl847 sheetfed scanner */ gl847_search_strip, sanei_genesys_is_compatible_calibration, NULL, gl847_send_shading_data, gl847_calculate_current_setup, gl847_boot, NULL }; SANE_Status sanei_gl847_init_cmd_set (Genesys_Device * dev) { dev->model->cmd_set = &gl847_cmd_set; return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/sceptre.c0000664000175000017500000015073312112021330014414 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) Copyright (C) 2002 Other SANE contributors This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ Sceptre S1200 SCSI scanner (sometimes also called S120) */ /*--------------------------------------------------------------------------*/ #define BUILD 10 /* 2002-03-21 */ #define BACKEND_NAME sceptre #define SCEPTRE_CONFIG_FILE "sceptre.conf" /*--------------------------------------------------------------------------*/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "sceptre.h" /*--------------------------------------------------------------------------*/ static const SANE_String scan_mode_list[] = { LINEART_STR, HALFTONE_STR, GRAY_STR, COLOR_STR, NULL }; static const SANE_Range gamma_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const SANE_Range threshold_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const SANE_Range halftone_range = { 1, /* minimum */ 4, /* maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ #define NUM_OF_RES 15 /* Table of supported resolution and number of lines of color shifting. */ static const SANE_Word resolutions_list[NUM_OF_RES + 1] = { NUM_OF_RES, 10, 25, 30, 45, 75, 90, 150, 300, 450, 600, 750, 900, 1050, 1125, 1200 }; static const SANE_Word color_shift_list[NUM_OF_RES + 1] = { NUM_OF_RES, 0, 0, 0, 0, 1, 1, 2, 4, 6, 8, 10, 12, 14, 15, 16 }; /*--------------------------------------------------------------------------*/ /* Define the supported scanners and their characteristics. */ static const struct scanners_supported scanners[] = { /* { 6, "KINPO ", "Vividscan S600 ", "KINPO", "S600" }, */ {6, "KINPO ", "Vividscan S120 ", "Sceptre", "S1200"} }; /*--------------------------------------------------------------------------*/ /* List of scanner attached. */ static Sceptre_Scanner *first_dev = NULL; static int num_devices = 0; static const SANE_Device **devlist = NULL; /* Local functions. */ /* Display a buffer in the log. */ static void hexdump (int level, const char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; DBG (level, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { *ptr = '\0'; DBG (level, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3d:", i); ptr += 4; } sprintf (ptr, " %2.2x", *p); ptr += 3; } *ptr = '\0'; DBG (level, "%s\n", line); } /* Initialize a scanner entry. Return an allocated scanner with some * preset values. */ static Sceptre_Scanner * sceptre_init (void) { Sceptre_Scanner *dev; DBG (DBG_proc, "sceptre_init: enter\n"); /* Allocate a new scanner entry. */ dev = malloc (sizeof (Sceptre_Scanner)); if (dev == NULL) { return NULL; } memset (dev, 0, sizeof (Sceptre_Scanner)); /* Allocate the buffer used to transfer the SCSI data. */ dev->buffer_size = 64 * 1024; dev->buffer = malloc (dev->buffer_size); if (dev->buffer == NULL) { free (dev); return NULL; } dev->sfd = -1; DBG (DBG_proc, "sceptre_init: exit\n"); return (dev); } /* Closes an open scanner. */ static void sceptre_close (Sceptre_Scanner * dev) { DBG (DBG_proc, "sceptre_close: enter\n"); if (dev->sfd != -1) { sanei_scsi_close (dev->sfd); dev->sfd = -1; } DBG (DBG_proc, "sceptre_close: exit\n"); } /* Frees the memory used by a scanner. */ static void sceptre_free (Sceptre_Scanner * dev) { int i; DBG (DBG_proc, "sceptre_free: enter\n"); if (dev == NULL) return; sceptre_close (dev); if (dev->devicename) { free (dev->devicename); } if (dev->buffer) { free (dev->buffer); } if (dev->image) { free (dev->image); } for (i = 1; i < OPT_NUM_OPTIONS; i++) { if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) { free (dev->val[i].s); } } free (dev); DBG (DBG_proc, "sceptre_free: exit\n"); } /* Inquiry a device and returns TRUE if is supported. */ static int sceptre_identify_scanner (Sceptre_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; int i; DBG (DBG_proc, "sceptre_identify_scanner: enter\n"); size = 36; MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "sceptre_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } if (size < 36) { DBG (DBG_error, "sceptre_identify_scanner: not enough data to identify device\n"); return (SANE_FALSE); } dev->scsi_type = dev->buffer[0] & 0x1f; memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); dev->scsi_vendor[0x08] = 0; memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); dev->scsi_product[0x10] = 0; memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); dev->scsi_version[0x04] = 0; DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\"\n", dev->scsi_vendor, dev->scsi_product, dev->scsi_version); /* Lookup through the supported scanners table to find if this * backend supports that one. */ for (i = 0; i < NELEMS (scanners); i++) { if (dev->scsi_type == scanners[i].scsi_type && strcmp (dev->scsi_vendor, scanners[i].scsi_vendor) == 0 && strcmp (dev->scsi_product, scanners[i].scsi_product) == 0) { DBG (DBG_error, "sceptre_identify_scanner: scanner supported\n"); dev->scnum = i; return (SANE_TRUE); } } DBG (DBG_proc, "sceptre_identify_scanner: exit\n"); return (SANE_FALSE); } /* Return the number of bytes left to read. */ static SANE_Status sceptre_get_status (Sceptre_Scanner * dev, size_t * data_left) { size_t size; CDB cdb; SANE_Status status; DBG (DBG_proc, "sceptre_get_status: enter\n"); /* Get status. */ size = 0x10; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sceptre_get_status: cannot get buffer status\n"); *data_left = 0; return (SANE_STATUS_IO_ERROR); } if (size != 16) { DBG (DBG_error, "sceptre_get_status: invalid data size returned (%ld)\n", (long) size); return (SANE_STATUS_IO_ERROR); } hexdump (DBG_info2, "GET BUFFER STATUS result", dev->buffer, 16); /* Read the size left. The scanner returns the rest of the * bytes to read, not just what's in its buffers. */ *data_left = B32TOI (&dev->buffer[8]); if (dev->raster_real == 0) { /* First call. Set the correct parameters. */ dev->raster_real = B16TOI (&dev->buffer[12]) * 3; dev->params.lines = B16TOI (&dev->buffer[12]); dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); } DBG (DBG_proc, "sceptre_get_status: exit, data_left=%ld\n", (long) *data_left); return (SANE_STATUS_GOOD); } /* * Adjust the rasters. This function is used during a color scan, * because the scanner does not present a format sane can interpret * directly. * * The scanner sends the colors by rasters (R then G then B), whereas * sane is waiting for a group of 3 bytes per color. To make things * funnier, the rasters are shifted. This shift factor depends on the * resolution used. The format of those raster is: * R...R RG...RG RGB...RGB BG...GB B...B * * So this function reorders all that mess. It gets the input from * dev->buffer and write the output in dev->image. size_in the the * length of the valid data in dev->buffer. */ static void sceptre_adjust_raster (Sceptre_Scanner * dev, size_t size_in) { int nb_rasters; /* number of rasters in dev->buffer */ int raster; /* current raster number in buffer */ int line; /* line number for that raster */ int colour; /* colour for that raster */ size_t offset; DBG (DBG_proc, "sceptre_adjust_raster: enter\n"); assert (dev->scan_mode == SCEPTRE_COLOR); assert ((size_in % dev->params.bytes_per_line) == 0); if (size_in == 0) { return; } /* * The color coding is one line for each color (in the RGB order). * Recombine that stuff to create a RGB value for each pixel. */ nb_rasters = size_in / dev->raster_size; for (raster = 0; raster < nb_rasters; raster++) { /* * Find the color to which this raster belongs to. * 0 = red * 1 = green * 2 = blue * * When blue comes, it always finishes the current line; */ line = 0; if (dev->raster_num < dev->color_shift) { colour = 0; /* Red */ line = dev->raster_num; } else if (dev->raster_num < (3 * dev->color_shift)) { /* even = red, odd = green */ colour = (dev->raster_num - dev->color_shift) % 2; if (colour) { /* Green */ line = (dev->raster_num - dev->color_shift) / 2; } else { /* Red */ line = (dev->raster_num + dev->color_shift) / 2; } } else if (dev->raster_num >= dev->raster_real - dev->color_shift) { /* Blue */ colour = 2; line = dev->line; } else if (dev->raster_num >= dev->raster_real - 3 * dev->color_shift) { /* Green or Blue */ colour = (dev->raster_real - dev->raster_num - dev->color_shift) % 2 + 1; if (colour == 1) { /* Green */ line = dev->line + dev->color_shift; } else { /* Blue */ line = dev->line; } } else { colour = (dev->raster_num - 3 * dev->color_shift) % 3; switch (colour) { case 0: /* Red */ line = (dev->raster_num + 3 * dev->color_shift) / 3; break; case 1: /* Green */ line = dev->raster_num / 3; break; case 2: /* Blue */ line = (dev->raster_num - 3 * dev->color_shift) / 3; break; } } /* Adjust the line number relative to the image. */ line -= dev->line; offset = dev->image_end + line * dev->params.bytes_per_line; assert (offset <= (dev->image_size - dev->raster_size)); /* Copy the raster to the temporary image. */ { int i; unsigned char *src = dev->buffer + raster * dev->raster_size; unsigned char *dest = dev->image + offset + colour; for (i = 0; i < dev->raster_size; i++) { *dest = *src; src++; dest += 3; } } if (colour == 2) { /* This blue raster completes a new line */ dev->line++; dev->image_end += dev->params.bytes_per_line; } dev->raster_num++; } DBG (DBG_proc, "sceptre_adjust_raster: exit\n"); } /* SCSI sense handler. Callback for SANE. * * Since this scanner does not have REQUEST SENSE, it is always an * error if this function is called.*/ static SANE_Status sceptre_sense_handler (int scsi_fd, unsigned char __sane_unused__ *result, void __sane_unused__ *arg) { DBG (DBG_proc, "sceptre_sense_handler (scsi_fd = %d)\n", scsi_fd); return SANE_STATUS_IO_ERROR; } /* Attach a scanner to this backend. */ static SANE_Status attach_scanner (const char *devicename, Sceptre_Scanner ** devp) { Sceptre_Scanner *dev; int sfd; DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); if (devp) *devp = NULL; /* Check if we know this device name. */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (DBG_info, "device is already known\n"); return SANE_STATUS_GOOD; } } /* Allocate a new scanner entry. */ dev = sceptre_init (); if (dev == NULL) { DBG (DBG_error, "ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_scanner: opening %s\n", devicename); if (sanei_scsi_open (devicename, &sfd, sceptre_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: attach_scanner: open failed\n"); sceptre_free (dev); return SANE_STATUS_INVAL; } /* Fill some scanner specific values. */ dev->devicename = strdup (devicename); dev->sfd = sfd; /* Now, check that it is a scanner we support. */ if (sceptre_identify_scanner (dev) == SANE_FALSE) { DBG (DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); sceptre_free (dev); return SANE_STATUS_INVAL; } sceptre_close (dev); /* Set the default options for that scanner. */ dev->sane.name = dev->devicename; dev->sane.vendor = scanners[dev->scnum].real_vendor; dev->sane.model = scanners[dev->scnum].real_product; dev->sane.type = SANE_I18N ("flatbed scanner"); dev->resolution_range.min = SANE_FIX (50); dev->resolution_range.max = SANE_FIX (1200); dev->resolution_range.quant = SANE_FIX (1); /* * The S1200 has an area of 8.5 inches / 11.7 inches. (A4 like) * That's roughly 215*297 mm * The values are coded by * size in inch * 600 dpi. * The maximums are: * X: 8.5 inches * 600 = 5100 dots * Y: 11.7 inches * 600 = 7020 * (although the windows driver stops at 7019) * * The values are stored in mm. Inches sucks anyway. * X: 5078 dots (22 dots lost) * Y: 7015 dots (5 dots lost) * * There seems to be a minimum area, but yet to be determined. */ dev->x_range.min = SANE_FIX (0); dev->x_range.max = SANE_FIX (215.90); /* in mm */ dev->x_range.quant = 0; dev->y_range.min = SANE_FIX (0); dev->y_range.max = SANE_FIX (297.14); /* in mm */ dev->y_range.quant = SANE_FIX (0); /* Link the scanner with the others. */ dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } num_devices++; DBG (DBG_proc, "attach_scanner: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach_scanner (dev, NULL); return SANE_STATUS_GOOD; } /* Reset the options for that scanner. */ static void sceptre_init_options (Sceptre_Scanner * dev) { int i; DBG (DBG_proc, "sceptre_init_options: enter\n"); /* Pre-initialize the options. */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < OPT_NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options. */ dev->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; /* Mode group */ dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].cap = 0; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scanner supported modes */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = 30; /* should define yet another max_string_size() */ dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = (SANE_String_Const *) scan_mode_list; dev->val[OPT_MODE].s = (SANE_Char *) strdup (scan_mode_list[0]); /* Common resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_RESOLUTION].constraint.word_list = resolutions_list; dev->val[OPT_RESOLUTION].w = 150; /* Geometry group */ dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; dev->opt[OPT_GEOMETRY_GROUP].size = 0; dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Upper left X */ dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &(dev->x_range); dev->val[OPT_TL_X].w = dev->x_range.min; /* Upper left Y */ dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &(dev->y_range); dev->val[OPT_TL_Y].w = dev->y_range.min; /* bottom-right x */ dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &(dev->x_range); dev->val[OPT_BR_X].w = dev->x_range.max; /* bottom-right y */ dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &(dev->y_range); dev->val[OPT_BR_Y].w = dev->y_range.max; /* Enhancement group */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].cap = 0; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* custom-gamma table */ dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* red gamma vector */ dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_R].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_R].wa = dev->gamma_R; /* green gamma vector */ dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_G].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_G].wa = dev->gamma_G; /* blue gamma vector */ dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_B].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_B].wa = dev->gamma_B; /* Threshold */ dev->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; dev->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; dev->opt[OPT_THRESHOLD].size = sizeof (SANE_Int); dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_THRESHOLD].constraint.range = &threshold_range; dev->val[OPT_THRESHOLD].w = 128; /* Halftone pattern */ dev->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_INT; dev->opt[OPT_HALFTONE_PATTERN].size = sizeof (SANE_Int); dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_HALFTONE_PATTERN].constraint.range = &halftone_range; dev->val[OPT_HALFTONE_PATTERN].w = 1; /* preview */ dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; dev->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; dev->val[OPT_PREVIEW].w = SANE_FALSE; /* Lastly, set the default mode. This might change some values * previously set here. */ sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, (SANE_String *) COLOR_STR, NULL); DBG (DBG_proc, "sceptre_init_options: leave\n"); } /* Wait until the scanner is ready. * * The only reason I know the scanner is not ready is because it is * moving the CCD. */ static SANE_Status sceptre_wait_scanner (Sceptre_Scanner * dev) { SANE_Status status; int timeout; CDB cdb; size_t size; DBG (DBG_proc, "sceptre_wait_scanner: enter\n"); MKSCSI_TEST_UNIT_READY (cdb); cdb.data[4] = 1; /* returns one byte. Non standard SCSI. */ /* Set the timeout to 120 seconds. */ timeout = 120; while (timeout > 0) { /* test unit ready */ size = 1; /* read one info byte */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status != SANE_STATUS_GOOD || size != 1) { DBG (DBG_error, "sceptre_wait_scanner: TUR failed\n"); return (SANE_STATUS_IO_ERROR); } /* Apparently the scanner returns only 2 values: * 0x00 - ready * 0xff - not ready */ if (dev->buffer[0] != 0x00) { sleep (1); /* wait 1 seconds */ timeout--; } else { return (SANE_STATUS_GOOD); } }; DBG (DBG_proc, "sceptre_wait_scanner: scanner not ready\n"); return (SANE_STATUS_IO_ERROR); } /* Diagnostic the scanner. */ static SANE_Status sceptre_do_diag (Sceptre_Scanner * dev) { SANE_Status status; CDB cdb; size_t size; DBG (DBG_proc, "sceptre_receive_diag enter\n"); /* SEND DIAGNOSTIC. */ MKSCSI_SEND_DIAG (cdb, 0); /* The windows driver sets that field. This is non standard. */ cdb.data[2] = 0x80; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sceptre_do_diag: exit, status=%d\n", status); return (status); } /* RECEIVE DIAGNOSTIC */ /* The windows driver ask for 3 byte. This is non standard * SCSI. The page returned should be at least 4 bytes. */ size = 3; MKSCSI_RECEIVE_DIAG (cdb, 0, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sceptre_do_diag: exit, status=%d\n", status); return (status); } DBG (DBG_proc, "sceptre_receive_diag exit\n"); return (status); } /* I'm not sure if the command sent is really set mode. The SCSI * command used is MODE SELECT, but no data is sent. Again, this is * not standard. */ static SANE_Status sceptre_set_mode (Sceptre_Scanner * dev) { SANE_Status status; CDB cdb; size_t size; DBG (DBG_proc, "sceptre_set_mode: enter\n"); size = 0x18; MKSCSI_MODE_SELECT (cdb, 1, 0, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "sceptre_set_mode: exit, status=%d\n", status); return (status); } /* Start a scan. */ static SANE_Status sceptre_scan (Sceptre_Scanner * dev) { CDB cdb; SANE_Status status; DBG (DBG_proc, "sceptre_scan: enter\n"); MKSCSI_SCAN (cdb); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "sceptre_scan: exit, status=%d\n", status); return status; } /* Set a window. */ static SANE_Status sceptre_set_window (Sceptre_Scanner * dev) { size_t size; CDB cdb; unsigned char window[82]; SANE_Status status; DBG (DBG_proc, "sceptre_set_window: enter\n"); size = sizeof (window); MKSCSI_SET_WINDOW (cdb, size); memset (window, 0, size); /* size of the parameters (74 = 0x4a bytes) */ window[7] = sizeof (window) - 8; /* X and Y resolution */ Ito16 (dev->resolution, &window[10]); Ito16 (dev->resolution, &window[12]); /* Upper Left (X,Y) */ Ito32 (dev->x_tl, &window[14]); Ito32 (dev->y_tl, &window[18]); /* Width and length */ Ito32 (dev->width, &window[22]); Ito32 (dev->length, &window[26]); /* Image Composition, Halftone and Depth */ switch (dev->scan_mode) { case SCEPTRE_LINEART: window[31] = dev->val[OPT_THRESHOLD].w; window[33] = 0; window[34] = 1; window[36] = 0; break; case SCEPTRE_HALFTONE: window[31] = 0x80; window[33] = 0; window[34] = 1; window[36] = dev->val[OPT_HALFTONE_PATTERN].w; break; case SCEPTRE_GRAYSCALE: window[31] = 0x80; window[33] = 2; window[34] = 8; window[36] = 0; break; case SCEPTRE_COLOR: window[31] = 0x80; window[33] = 5; window[34] = 24; window[36] = 0; break; } /* Unknown parameters. They look constant in the windows driver. */ window[30] = 0x04; window[32] = 0x04; window[37] = 0x80; /* RIF, although it looks unused. */ hexdump (DBG_info2, "windows", window, sizeof (window)); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, window, sizeof (window), NULL, NULL); DBG (DBG_proc, "sceptre_set_window: exit, status=%d\n", status); return status; } /* Read the image from the scanner and fill the temporary buffer with it. */ static SANE_Status sceptre_fill_image (Sceptre_Scanner * dev) { SANE_Status status; size_t size; CDB cdb; size_t data_left; DBG (DBG_proc, "sceptre_fill_image: enter\n"); assert (dev->image_begin == dev->image_end); assert (dev->real_bytes_left > 0); /* Copy the complete lines, plus the imcompletes * ones. We don't keep the real end of data used * in image, so we copy the biggest possible. * * This is a no-op for non color images. */ memmove (dev->image, dev->image + dev->image_begin, dev->raster_ahead); dev->image_begin = 0; dev->image_end = 0; while (dev->real_bytes_left) { if ((status = sceptre_get_status (dev, &data_left)) != SANE_STATUS_GOOD) { return (status); } /* * Try to read the maximum number of bytes. */ size = data_left; if (size > dev->real_bytes_left) { size = dev->real_bytes_left; } if (size > dev->image_size - dev->raster_ahead - dev->image_end) { size = dev->image_size - dev->raster_ahead - dev->image_end; } if (size > dev->buffer_size) { size = dev->buffer_size; } /* Round down to a multiple of line size. */ size = size - (size % dev->params.bytes_per_line); if (size == 0) { /* Probably reached the end of the buffer. * Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } DBG (DBG_info, "sceptre_fill_image: to read = %ld bytes (bpl=%d)\n", (long) size, dev->params.bytes_per_line); MKSCSI_READ_10 (cdb, 0, 0, size); hexdump (DBG_info2, "sceptre_fill_image: READ_10 CDB", cdb.data, 10); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sceptre_fill_image: cannot read from the scanner\n"); return status; } DBG (DBG_info, "sceptre_fill_image: real bytes left = %ld\n", (long)dev->real_bytes_left); switch (dev->scan_mode) { case SCEPTRE_COLOR: sceptre_adjust_raster (dev, size); break; case SCEPTRE_LINEART: case SCEPTRE_HALFTONE: { /* Invert black and white. */ unsigned char *src = dev->buffer; unsigned char *dest = dev->image + dev->image_end; size_t i; for (i = 0; i < size; i++) { *dest = *src ^ 0xff; dest++; src++; } dev->image_end += size; } break; default: memcpy (dev->image + dev->image_end, dev->buffer, size); dev->image_end += size; } dev->real_bytes_left -= size; } return (SANE_STATUS_GOOD); /* unreachable */ } /* Copy from the raw buffer to the buffer given by the backend. * * len in input is the maximum length available in buf, and, in * output, is the length written into buf. */ static void sceptre_copy_raw_to_frontend (Sceptre_Scanner * dev, SANE_Byte * buf, size_t * len) { size_t size; size = dev->image_end - dev->image_begin; if (size > *len) { size = *len; } *len = size; memcpy (buf, dev->image + dev->image_begin, size); dev->image_begin += size; } /* Stop a scan. */ static SANE_Status do_cancel (Sceptre_Scanner * dev) { DBG (DBG_sane_proc, "do_cancel enter\n"); if (dev->scanning == SANE_TRUE) { /* Reposition the CCD. */ dev->x_tl = 0; dev->x_tl = 0; dev->width = 0; dev->length = 0; sceptre_set_window (dev); sceptre_scan (dev); sceptre_close (dev); } dev->scanning = SANE_FALSE; DBG (DBG_sane_proc, "do_cancel exit\n"); return SANE_STATUS_CANCELLED; } /* Start a scan. */ static const SANE_Word gamma_init[GAMMA_LENGTH] = { 0x00, 0x06, 0x0A, 0x0D, 0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, 0x25, 0x27, 0x28, 0x2A, 0x2C, 0x2D, 0x2F, 0x30, 0x32, 0x33, 0x35, 0x36, 0x38, 0x39, 0x3A, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC0, 0xC1, 0xC2, 0xC3, 0xC3, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCF, 0xCF, 0xD0, 0xD1, 0xD2, 0xD2, 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, 0xDE, 0xDF, 0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5, 0xE6, 0xE6, 0xE7, 0xE8, 0xE8, 0xE9, 0xEA, 0xEB, 0xEB, 0xEC, 0xED, 0xED, 0xEE, 0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF4, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC, 0xFC, 0xFD, 0xFE, 0xFE, 0xFF }; static SANE_Status sceptre_send_gamma (Sceptre_Scanner * dev) { CDB cdb; int i; struct { unsigned char gamma_R[GAMMA_LENGTH]; unsigned char gamma_G[GAMMA_LENGTH]; unsigned char gamma_B[GAMMA_LENGTH]; } param; size_t size; SANE_Status status; DBG (DBG_proc, "sceptre_send_gamma: enter\n"); size = sizeof (param); assert (size == 0x300); MKSCSI_SEND_10 (cdb, 0x03, 0x02, size); if (dev->val[OPT_CUSTOM_GAMMA].w) { /* Use the custom gamma. */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = dev->gamma_R[i]; param.gamma_G[i] = dev->gamma_G[i]; param.gamma_B[i] = dev->gamma_B[i]; } } else { for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = gamma_init[i]; param.gamma_G[i] = gamma_init[i]; param.gamma_B[i] = gamma_init[i]; } } hexdump (DBG_info2, "gamma", param.gamma_R, 3 * GAMMA_LENGTH); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, ¶m, sizeof (param), NULL, NULL); DBG (DBG_proc, "sceptre_send_gamma: exit, status=%d\n", status); return (status); } /*--------------------------------------------------------------------------*/ /* Entry points */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; char dev_name[PATH_MAX]; size_t len; DBG_INIT (); DBG (DBG_proc, "sane_init: enter\n"); DBG (DBG_error, "This is sane-sceptre version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_error, "(C) 2002 by Frank Zago\n"); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); } fp = sanei_config_open (SCEPTRE_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach_scanner ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); DBG (DBG_proc, "sane_init: leave\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { Sceptre_Scanner *dev; int i; DBG (DBG_proc, "sane_get_devices: enter\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Sceptre_Scanner *dev; SANE_Status status; DBG (DBG_proc, "sane_open: enter\n"); /* search for devicename */ if (devicename[0]) { DBG (DBG_info, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); dev = first_dev; /* empty devicename -> use first device */ } if (!dev) { DBG (DBG_error, "No scanner found\n"); return SANE_STATUS_INVAL; } sceptre_init_options (dev); /* Initialize the gamma table. */ memcpy (dev->gamma_R, gamma_init, dev->opt[OPT_GAMMA_VECTOR_R].size); memcpy (dev->gamma_G, gamma_init, dev->opt[OPT_GAMMA_VECTOR_G].size); memcpy (dev->gamma_B, gamma_init, dev->opt[OPT_GAMMA_VECTOR_B].size); *handle = dev; DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Sceptre_Scanner *dev = handle; DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); if ((unsigned) option >= OPT_NUM_OPTIONS) { return NULL; } DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return dev->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Sceptre_Scanner *dev = handle; SANE_Status status; SANE_Word cap; DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", option, action); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_THRESHOLD: case OPT_CUSTOM_GAMMA: case OPT_HALFTONE_PATTERN: case OPT_PREVIEW: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, dev->val[option].wa, dev->opt[option].size); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Side-effect options */ case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* Side-effect free options */ case OPT_THRESHOLD: case OPT_HALFTONE_PATTERN: case OPT_PREVIEW: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_MODE: free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); /* Set default options for the scan modes. */ dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, LINEART_STR) == 0) { dev->scan_mode = SCEPTRE_LINEART; dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, HALFTONE_STR) == 0) { dev->scan_mode = SCEPTRE_HALFTONE; dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, GRAY_STR) == 0) { dev->scan_mode = SCEPTRE_GRAYSCALE; } else if (strcmp (dev->val[OPT_MODE].s, COLOR_STR) == 0) { dev->scan_mode = SCEPTRE_COLOR; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (dev->val[option].wa, val, dev->opt[option].size); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: dev->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; if (dev->val[OPT_CUSTOM_GAMMA].w) { /* use custom_gamma_table */ dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } else { dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Sceptre_Scanner *dev = handle; int x_dpi; /* X-Resolution */ DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { /* Prepare the parameters for the caller. */ memset (&dev->params, 0, sizeof (SANE_Parameters)); if (dev->val[OPT_PREVIEW].w == SANE_TRUE) { dev->resolution = 30; /* Windows TWAIN does 32 */ dev->x_tl = 0; dev->y_tl = 0; dev->x_br = mmToIlu (SANE_UNFIX (dev->x_range.max)); dev->y_br = mmToIlu (SANE_UNFIX (dev->y_range.max)); } else { /* Setup the parameters for the scan. These values will be re-used * in the SET WINDOWS command. */ dev->resolution = dev->val[OPT_RESOLUTION].w; dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); } /* Check the corners are OK. */ if (dev->x_tl > dev->x_br) { int s; s = dev->x_tl; dev->x_tl = dev->x_br; dev->x_br = s; } if (dev->y_tl > dev->y_br) { int s; s = dev->y_tl; dev->y_tl = dev->y_br; dev->y_br = s; } dev->width = dev->x_br - dev->x_tl; dev->length = dev->y_br - dev->y_tl; /* * Adjust the "X Resolution". The sceptre S1200 ignores the * Y-Resolution parameter in the windows block. X-Resolution * is used instead. However the limits are not the same for X * (600 dpi) and Y (1200 dpi). */ x_dpi = dev->resolution; if (x_dpi > 600) { x_dpi = 600; } /* Set depth */ switch (dev->scan_mode) { case SCEPTRE_LINEART: dev->params.format = SANE_FRAME_GRAY; dev->depth = 1; break; case SCEPTRE_HALFTONE: dev->params.format = SANE_FRAME_GRAY; dev->depth = 1; break; case SCEPTRE_GRAYSCALE: dev->params.format = SANE_FRAME_GRAY; dev->depth = 8; break; case SCEPTRE_COLOR: dev->params.format = SANE_FRAME_RGB; dev->depth = 8; break; } /* this scanner does only one pass */ dev->params.last_frame = SANE_TRUE; dev->params.depth = dev->depth; /* Compute the number of pixels, bytes per lines and lines. */ switch (dev->scan_mode) { case SCEPTRE_LINEART: case SCEPTRE_HALFTONE: dev->params.pixels_per_line = (dev->width * x_dpi) / 600; dev->params.pixels_per_line &= ~0x7; /* round down to 8 */ dev->params.bytes_per_line = (dev->params.pixels_per_line) / 8; dev->params.lines = ((dev->length * dev->resolution) / 600); if ((dev->params.lines) * 600 != (dev->length * dev->resolution)) { /* Round up lines to 2. */ dev->params.lines &= ~1; dev->params.lines += 2; } break; case SCEPTRE_GRAYSCALE: case SCEPTRE_COLOR: /* pixels_per_line rounding rules: * 2n + [0.0 .. 1.0] -> round to 2n * 2n + ]1.0 .. 2.0] -> round to 2n + 2 */ dev->params.pixels_per_line = (dev->width * x_dpi) / 600; if (dev->params.pixels_per_line & 1) { if ((dev->params.pixels_per_line * 600) == (dev->width * x_dpi)) { /* 2n */ dev->params.pixels_per_line--; } else { /* 2n+2 */ dev->params.pixels_per_line++; } } dev->params.bytes_per_line = dev->params.pixels_per_line; if (dev->scan_mode == SCEPTRE_COLOR) dev->params.bytes_per_line *= 3; /* lines number rounding rules: * 2n + [0.0 .. 2.0[ -> round to 2n * * Note: the rounding is often incorrect at high * resolution (ag more than 300dpi) */ dev->params.lines = (dev->length * dev->resolution) / 600; dev->params.lines &= ~1; break; } /* Find the proper color shifting parameter. */ if (dev->scan_mode == SCEPTRE_COLOR) { int i = 1; while (resolutions_list[i] != dev->resolution) { i++; } dev->color_shift = color_shift_list[i]; } else { dev->color_shift = 0; } DBG (DBG_proc, "color_shift = %d\n", dev->color_shift); dev->bytes_left = dev->params.lines * dev->params.bytes_per_line; } /* Return the current values. */ if (params) { *params = (dev->params); } DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Sceptre_Scanner *dev = handle; SANE_Status status; DBG (DBG_proc, "sane_start: enter\n"); if (!(dev->scanning)) { sane_get_parameters (dev, NULL); if (dev->image) { free (dev->image); } /* Compute the length necessary in image. The first part will store * the complete lines, and the rest is used to stored ahead * rasters. */ dev->raster_ahead = (2 * dev->color_shift + 1) * dev->params.bytes_per_line; dev->image_size = dev->buffer_size + dev->raster_ahead; dev->image = malloc (dev->image_size); if (dev->image == NULL) { return SANE_STATUS_NO_MEM; } dev->image_begin = 0; dev->image_end = 0; dev->raster_size = dev->params.bytes_per_line / 3; dev->raster_num = 0; dev->raster_real = 0; dev->line = 0; /* Open again the scanner. */ if (sanei_scsi_open (dev->devicename, &(dev->sfd), sceptre_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: sane_start: open failed\n"); return SANE_STATUS_INVAL; } /* The scanner must be ready. */ status = sceptre_wait_scanner (dev); if (status) { sceptre_close (dev); return status; } status = sceptre_do_diag (dev); if (status) { sceptre_close (dev); return status; } status = sceptre_set_mode (dev); if (status) { sceptre_close (dev); return status; } status = sceptre_set_window (dev); if (status) { sceptre_close (dev); return status; } status = sceptre_send_gamma (dev); if (status) { sceptre_close (dev); return status; } status = sceptre_scan (dev); if (status) { sceptre_close (dev); return status; } status = sceptre_get_status (dev, &dev->real_bytes_left); if (status) { sceptre_close (dev); return status; } } dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->scanning = SANE_TRUE; DBG (DBG_proc, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status status; Sceptre_Scanner *dev = handle; size_t size; int buf_offset; /* offset into buf */ DBG (DBG_proc, "sane_read: enter\n"); *len = 0; if (!(dev->scanning)) { /* OOPS, not scanning */ return do_cancel (dev); } if (dev->bytes_left <= 0) { return (SANE_STATUS_EOF); } buf_offset = 0; do { if (dev->image_begin == dev->image_end) { /* Fill image */ status = sceptre_fill_image (dev); if (status != SANE_STATUS_GOOD) { return (status); } } /* Something must have been read */ if (dev->image_begin == dev->image_end) { DBG (DBG_info, "sane_read: nothing read\n"); return SANE_STATUS_IO_ERROR; } /* Copy the data to the frontend buffer. */ size = max_len - buf_offset; if (size > dev->bytes_left) { size = dev->bytes_left; } sceptre_copy_raw_to_frontend (dev, buf + buf_offset, &size); buf_offset += size; dev->bytes_left -= size; *len += size; } while ((buf_offset != max_len) && dev->bytes_left); DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", (long)dev->bytes_left); return SANE_STATUS_GOOD; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { SANE_Status status; Sceptre_Scanner *dev = handle; DBG (DBG_proc, "sane_set_io_mode: enter\n"); if (dev->scanning == SANE_FALSE) { return (SANE_STATUS_INVAL); } if (non_blocking == SANE_FALSE) { status = SANE_STATUS_GOOD; } else { status = SANE_STATUS_UNSUPPORTED; } DBG (DBG_proc, "sane_set_io_mode: exit\n"); return status; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { DBG (DBG_proc, "sane_get_select_fd: enter\n"); DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } void sane_cancel (SANE_Handle handle) { Sceptre_Scanner *dev = handle; DBG (DBG_proc, "sane_cancel: enter\n"); do_cancel (dev); DBG (DBG_proc, "sane_cancel: exit\n"); } void sane_close (SANE_Handle handle) { Sceptre_Scanner *dev = handle; Sceptre_Scanner *dev_tmp; DBG (DBG_proc, "sane_close: enter\n"); do_cancel (dev); sceptre_close (dev); /* Unlink dev. */ if (first_dev == dev) { first_dev = dev->next; } else { dev_tmp = first_dev; while (dev_tmp->next && dev_tmp->next != dev) { dev_tmp = dev_tmp->next; } if (dev_tmp->next != NULL) { dev_tmp->next = dev_tmp->next->next; } } sceptre_free (dev); num_devices--; DBG (DBG_proc, "sane_close: exit\n"); } void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); while (first_dev) { sane_close (first_dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); } sane-backends-1.0.27/backend/coolscan-scsidef.h0000664000175000017500000007031212112021330016165 00000000000000 /* ------------------------------------------------------------------------- */ /* coolscan-scsidef.h: scsi-definiton header file for COOLSCAN scanner driver. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------- */ #ifndef COOLSCAN_SCSIDEF_H #define COOLSCAN_SCSIDEF_H /* ========================================================================= */ /* I'm using functions derived from Eric Youngdale's scsiinfo * program here for dealing with parts of SCSI commands. */ static inline void setbitfield (unsigned char *pageaddr, int mask, int shift, int val) \ { *pageaddr = (*pageaddr & ~(mask << shift)) | ((val & mask) << shift); } /* ------------------------------------------------------------------------- */ static inline void resetbitfield (unsigned char *pageaddr, int mask, int shift, int val) \ { *pageaddr = (*pageaddr & ~(mask << shift)) | (((!val) & mask) << shift); } /* ------------------------------------------------------------------------- */ static inline int getbitfield (unsigned char *pageaddr, int mask, int shift) \ { return ((*pageaddr >> shift) & mask); } /* ------------------------------------------------------------------------- */ static inline int getnbyte (unsigned char *pnt, int nbytes) \ { unsigned int result = 0; int i; #ifdef DEBUG assert (nbytes < 5); #endif for (i = 0; i < nbytes; i++) result = (result << 8) | (pnt[i] & 0xff); return result; } /* ------------------------------------------------------------------------- */ static inline void putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) \ { int i; #ifdef DEBUG assert (nbytes < 5); #endif for (i = nbytes - 1; i >= 0; i--) \ { pnt[i] = value & 0xff; value = value >> 8; } } /* ==================================================================== */ /* Not all of these are defined in scsi.h, so we'll make sure * we agree about them here... */ #undef WRITE_BUFFER /* correct size write_buffer for scanner */ #define TEST_UNIT_READY 0x00 #define REQUEST_SENSE 0x03 #define INQUIRY 0x12 #define MODE_SELECT 0x15 #define RESERVE_UNIT 0x16 #define RELEASE_UNIT 0x17 #define MODE_SENSE 0x1a #define SCAN 0x1b #define SEND_DIAGNOSTIC 0x1d #define SET_WINDOW 0x24 #define GET_WINDOW 0x25 #define READ 0x28 #define SEND 0x2a #define OBJECT_POSITION 0x31 #define WRITE_BUFFER 0x3b #define READ_BUFFER 0x3c #define SABORT 0xc0 #define COMMAND_C1 0xc1 #define AUTO_FOCUS 0xc2 #define UNIT_MOVE 0xe0 /* ==================================================================== */ /* wdb_len if nothing is set by inquiry */ #define STD_WDB_LEN 0x28 /* ==================================================================== */ /* SCSI commands */ typedef struct { unsigned char *cmd; int size; } scsiblk; /* ==================================================================== */ #define set_inquiry_return_size(icb,val) icb[0x04]=val static unsigned char inquiryC[] = {INQUIRY, 0x00, 0x00, 0x00, 0x1f, 0x00}; static scsiblk inquiry = {inquiryC, sizeof (inquiryC)}; #define get_inquiry_periph_qual(in) getbitfield(in, 0x07, 5) #define IN_periph_qual_lun 0x00 #define IN_periph_qual_nolun 0x03 #define get_inquiry_periph_devtype(in) getbitfield(in, 0x1f, 0) #define IN_periph_devtype_scanner 0x06 #define IN_periph_devtype_unknown 0x1f #define get_inquiry_response_format(in) getbitfield(in + 0x03, 0x07, 0) #define IN_recognized 0x02 #define get_inquiry_additional_length(in) in[0x04] #define get_inquiry_length(in) in[0x03] #define set_inquiry_length(out,n) out[0x04]=n-5 #define get_inquiry_vendor(in, buf) strncpy(buf, in + 0x08, 0x08) #define get_inquiry_product(in, buf) strncpy(buf, in + 0x10, 0x010) #define get_inquiry_version(in, buf) strncpy(buf, in + 0x20, 0x04) /* ==================================================================== */ /* static unsigned char mode_selectC[] = { MODE_SELECT, 0x10, 0x00, 0x00, 0x00, 0x00 static scsiblk mode_select = { mode_selectC,sizeof(mode_selectC) }; */ /* ==================================================================== */ static unsigned char test_unit_readyC[] = { TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk test_unit_ready = {test_unit_readyC, sizeof (test_unit_readyC)}; /* ==================================================================== */ static unsigned char reserve_unitC[] = { RESERVE_UNIT, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk reserve_unit = {reserve_unitC, sizeof (reserve_unitC)}; /* ==================================================================== */ static unsigned char release_unitC[] = { RELEASE_UNIT, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk release_unit = {release_unitC, sizeof (release_unitC)}; /* ==================================================================== */ static unsigned char mode_senseC[] = { MODE_SENSE, 0x18, 0x03, 0x00, 0x00, 0x00, /* PF set, page type 03 */ }; #define set_MS_DBD(b, val) setbitfield(b, 0x01, 3, (val?1:0)) #define set_MS_len(b, val) putnbyte(b+0x04, val, 1) #define get_MS_MUD(b) getnbyte(b+(0x04+((int)*(b+0x3)))+0x4,2) static scsiblk mode_sense = {mode_senseC, sizeof (mode_senseC)}; /* ==================================================================== */ static unsigned char set_windowC[] = { SET_WINDOW, 0x00, /* opcode, lun */ 0x00, 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00, 0x00, /* transfer length; needs to be set */ 0x00, /* control byte */ }; #define set_SW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) static scsiblk set_window = {set_windowC, sizeof (set_windowC)}; /* ==================================================================== */ static unsigned char get_windowC[] = { GET_WINDOW, 0x01, /* opcode, lun, misc (should be 0x01? */ 0x00, 0x00, 0x00, /* reserved */ 0x00, /* Window identifier */ 0x00, 0x00, 0x00, /* transfer length; needs to be get */ 0x00, /* control byte */ }; #define set_GW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) #define set_WindowID_wid(sb, val) sb[5] = val static scsiblk get_window = {get_windowC, sizeof (get_windowC)}; /* ==================================================================== */ /* We use the same structure for both SET WINDOW and GET WINDOW. */ static unsigned char window_parameter_data_blockC[] = { 0x00, 0x00, /* window data length, in case of get, or 0 in case of set */ 0x00, 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00, /* Window Descriptor Length, value must be set by SHORT_WDB define */ }; #define set_WPDB_wdblen(sb, len) putnbyte(sb + 0x06, len, 2) static scsiblk window_parameter_data_block = { window_parameter_data_blockC, sizeof (window_parameter_data_blockC) }; /* ==================================================================== */ static unsigned char window_descriptor_blockC[] = { /* Any field maked with 'R' (e.g. R0x55) indicate a filed provided for * development. In normal operation, 0 is set here. If any other value is set, * operationis not guaranteed! */ #define max_WDB_size 0xff #define used_WDB_size 0x75 0x00, /* 0x00 */ /* Window Identifier */ #define set_WD_wid(sb, val) sb[0] = val #define WD_wid_all 0x00 /* Only one supported */ 0x00, /* 0x01 */ /* reserved, AUTO */ #define set_WD_auto(sb, val) setbitfield(sb + 0x01, 1, 0, val) #define get_WD_auto(sb) getbitfield(sb + 0x01, 1, 0) 0x00, 0x00, /* 0x02 */ /* X Resolution in dpi */ #define set_WD_Xres(sb, val) putnbyte(sb + 0x02, val, 2) #define get_WD_Xres(sb) getnbyte(sb + 0x02, 2) 0x00, 0x00, /* 0x04 */ /* Y Resolution in dpi */ #define set_WD_Yres(sb, val) putnbyte(sb + 0x04, val, 2) #define get_WD_Yres(sb) getnbyte(sb + 0x04, 2) 0x00, 0x00, 0x00, 0x00, /* 0x06 */ /* Upper Left X in 1200|2700pt/inch */ #define set_WD_ULX(sb, val) putnbyte(sb + 0x06, val, 4) #define get_WD_ULX(sb) getnbyte(sb + 0x06, 4) 0x00, 0x00, 0x00, 0x00, /* 0x0a */ /* Upper Left Y in 1200|2700pt/inch */ #define set_WD_ULY(sb, val) putnbyte(sb + 0x0a, val, 4) #define get_WD_ULY(sb) getnbyte(sb + 0x0a, 4) 0x00, 0x00, 0x00, 0x00, /* 0x0e */ /* Width 1200pt/inch */ #define set_WD_width(sb, val) putnbyte(sb + 0x0e, val, 4) #define get_WD_width(sb) getnbyte(sb + 0x0e, 4) 0x00, 0x00, 0x00, 0x00, /* 0x12 */ /* Length 1200pt/inch */ #define set_WD_length(sb, val) putnbyte(sb + 0x12, val, 4) #define get_WD_length(sb) getnbyte(sb + 0x12, 4) 0x00, /* 0x16 */ /* Brightness */ #define set_WD_brightness(sb, val) sb[0x16] = val #define get_WD_brightness(sb) sb[0x16] 0x00, /* 0x17 */ /* Reserved */ 0x00, /* 0x18 */ /* Contrast */ #define set_WD_contrast(sb, val) sb[0x18] = val #define get_WD_contrast(sb) sb[0x18] 0x05, /* 0x19 */ /* Image Mode */ #define set_WD_composition(sb, val) sb[0x19] = val #define get_WD_composition(sb) sb[0x19] #define WD_comp_grey 0x02 #define WD_comp_gray 0x02 #define WD_comp_rgb_full 0x05 0x08, /* 0x1a */ /* Bits/Pixel */ #define set_WD_bitsperpixel(sb, val) sb[0x1a] = val #define get_WD_bitsperpixel(sb) sb[0x1a] #define WD_bits_8 0x08 0, 0, 0, 0, 0, /* 0x1b */ /* Reserved */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28 */ /* X-axis pixel count (1-2592 */ #define get_WD_xpixels(sb) getnbyte(sb + 0x28, 4) 0, 0, 0, 0, /* 0x2c */ /* Y-axis pixel count (1-3888) */ #define get_WD_ypixels(sb) getnbyte(sb + 0x2c, 4) 0x01, /* 0x30 */ /* Reserved, negative/positive * reserved, drop-out color * (Green) */ #define set_WD_negative(sb, val) setbitfield(sb + 0x30, 0x1, 4, (val?1:0)) #define get_WD_negative(sb) getbitfield(sb + 0x30, 0x1, 4) #define WD_Negative 0x01 #define WD_Positive 0x00 #define set_WD_dropoutcolor(sb, val) setbitfield(sb + 0x30, 0x3, 0, val) #define get_WD_dropoutcolor(sb) getbitfield(sb + 0x30, 0x3, 0) #define WD_Dropout_Red 0x00 #define WD_Dropout_Green 0x01 #define WD_Dropout_Blue 0x02 0x00, /* 0x31 */ /* scan mode */ #define set_WD_scanmode(sb, val) setbitfield(sb + 0x31, 0x3, 4, val) #define get_WD_scanmode(sb) getbitfield(sb + 0x31, 0x3, 4) #define WD_Scan 0x00 #define WD_Prescan 0x01 0x40, /* 0x32 */ /* Data transfer mode */ #define set_WD_transfermode(sb, val) setbitfield(sb + 0x32, 0x3, 6, val) #define get_WD_transfermode(sb) getbitfield(sb + 0x32, 0x3, 6) #define WD_LineSequence 0x2 #define WD_DotSequence 0x1 0x02, /* 0x33 */ /* Gamma selection */ #define set_WD_gammaselection(sb, val) putnbyte(sb + 0x33, val, 1) #define get_WD_gammaselection(sb) getnbyte(sb + 0x33, 1) #define WD_Linear 0x2 #define WD_Monitor 0x3 0, /* 0x34 */ /* Reserved */ 0x40, /* 0x35 */ /* Reserved, shading, analog gamma, averaging */ #define set_WD_shading(sb, val) setbitfield(sb + 0x35, 0x1, 6, val) #define get_WD_shading(sb) getbitfield(sb + 0x35, 0x1, 6) #define WD_Shading_ON 0x0 #define WD_Shading_OFF 0x1 #define set_WD_analog_gamma_R(sb, val) setbitfield(sb + 0x35, 0x1, 5, val) #define set_WD_analog_gamma_G(sb, val) setbitfield(sb + 0x35, 0x1, 4, val) #define set_WD_analog_gamma_B(sb, val) setbitfield(sb + 0x35, 0x1, 3, val) #define get_WD_analog_gamma_R(sb) getbitfield(sb + 0x35, 0x1, 5) #define get_WD_analog_gamma_G(sb) getbitfield(sb + 0x35, 0x1, 4) #define get_WD_analog_gamma_B(sb) getbitfield(sb + 0x35, 0x1, 3) #define WD_Analog_Gamma_ON 0x0 #define WD_Analog_Gamma_OFF 0x1 #define set_WD_averaging(sb, val) setbitfield(sb + 0x35, 0x7, 0, (val?7:0)) #define get_WD_averaging(sb) getbitfield(sb + 0x35, 0x7, 0) #define WD_Averaging_ON 0x0 #define WD_Averaging_OFF 0x1 0, /* 0x36 */ /* reserved */ 0, /* 0x37 */ /* R brightness */ #define set_WD_brightness_R(b, val) putnbyte(b + 0x37, val, 1) #define get_WD_brightness_R(b) getnbyte(b + 0x37, 1) 0, /* 0x38 */ /* G brightness */ #define set_WD_brightness_G(b, val) putnbyte(b + 0x38, val, 1) #define get_WD_brightness_G(b) getnbyte(b + 0x38, 1) 0, /* 0x39 */ /* B brightness */ #define set_WD_brightness_B(b, val) putnbyte(b + 0x39, val, 1) #define get_WD_brightness_B(b) getnbyte(b + 0x39, 1) 0, /* 0x3a */ /* R contrast */ #define set_WD_contrast_R(b, val) putnbyte(b + 0x3a, val, 1) #define get_WD_contrast_R(b) getnbyte(b + 0x3a, 1) 0, /* 0x3b */ /* G contrast */ #define set_WD_contrast_G(b, val) putnbyte(b + 0x3b, val, 1) #define get_WD_contrast_G(b) getnbyte(b + 0x3b, 1) 0, /* 0x3c */ /* B contrast */ #define set_WD_contrast_B(b, val) putnbyte(b + 0x3c, val, 1) #define get_WD_contrast_B(b) getnbyte(b + 0x3c, 1) 0, 0, 0, 0, /* 0x3d */ /* Reserved */ 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x49 */ /* R exposure time adjustment [0, 12-200] */ #define set_WD_exposure_R(b, val) putnbyte(b + 0x49, val, 1) #define get_WD_exposure_R(b) getnbyte(b + 0x49, 1) 0, /* 0x4a */ /* G exposure time adjustment [0, 12-200] */ #define set_WD_exposure_G(b, val) putnbyte(b + 0x4a, val, 1) #define get_WD_exposure_G(b) getnbyte(b + 0x4a, 1) 0, /* 0x4b */ /* B exposure time adjustment [0, 12-200] */ #define set_WD_exposure_B(b, val) putnbyte(b + 0x4b, val, 1) #define get_WD_exposure_B(b) getnbyte(b + 0x4b, 1) 0, 0, 0, 0, /* 0x4c */ /* Reserved */ 0, 0, 0, /* 0x52 */ /* Amount of R shift [0, 128+-15] */ #define set_WD_shift_R(b, val) putnbyte(b + 0x52, val, 1) #define get_WD_shift_R(b) getnbyte(b + 0x52, 1) 0, /* 0x53 */ /* Amount of G shift [0, 128+-15] */ #define set_WD_shift_G(b, val) putnbyte(b + 0x53, val, 1) #define get_WD_shift_G(b) getnbyte(b + 0x53, 1) 0, /* 0x54 */ /* Amount of B shift [0, 128+-15] */ #define set_WD_shift_B(b, val) putnbyte(b + 0x54, val, 1) #define get_WD_shift_B(b) getnbyte(b + 0x54, 1) 0, /* R0x55 */ /* Amount of R offset [0-255] */ 0, /* R0x56 */ /* Amount of G offset [0-255] */ 0, /* R0x57 */ /* Amount of B offset [0-255] */ 0, 0, /* 0x58 */ /* Maximum resolution (for GET WINDOW: [2700]) */ #define get_WD_maxres(b) getnbyte(b + 0x58, 2) 0, 0, /* 0x5a */ /* Reserved */ 0, /* 0x5c */ /* LUT-R, LUT-G */ #define set_WD_LUT_R(b, val) setbitfield(b + 0x5c, 0x0f, 4, val) #define set_WD_LUT_G(b, val) setbitfield(b + 0x5c, 0x0f, 0, val) #define get_WD_LUT_R(b) getbitfield(b + 0x5c, 0x0f, 4) #define get_WD_LUT_G(b) getbitfield(b + 0x5c, 0x0f, 0) 0, /* 0x5d */ /* LUT-B, reserved */ #define set_WD_LUT_B(b, val) setbitfield(b + 0x5d, 0x0f, 4, val) #define get_WD_LUT_B(b) getbitfield(b + 0x5d, 0x0f, 4) 0, /* R0x5e */ /* LS-1000: reserved. LS-20: R B/W reference point */ 0, /* R0x5f */ /* LS-1000: reserved. LS-20: G B/W reference point */ 0, /* R0x60 */ /* LS-1000: reserved. LS-20: B B/W reference point */ 0, /* R0x61 */ /* R exposure time unit [0-7] (LS-1000); [0, 2-1] (LS-20) */ 0, /* R0x62 */ /* G exposure time unit [0-7] (LS-1000); [0, 2-1] (LS-20) */ 0, /* R0x63 */ /* B exposure time unit [0-7] (LS-1000); [0, 2-1] (LS-20) */ 0, /* 0x64 */ /* Reserved */ 0, /* 0x65 */ /* Reserved, stop */ #define set_WD_stop(b, val) setbitfield(b+0x65, 0x01, 0, val) #define get_WD_stop(b) getbitfield(b+0x65, 0x01, 0) 0, /* R0x66 */ /* R gain [0-4] (LS-1000), [0-255] (LS-20) */ 0, /* R0x67 */ /* G gain [0-4] (LS-1000), [0-255] (LS-20) */ 0, /* R0x68 */ /* B gain [0-4] (LS-1000), [0-255] (LS-20) */ 0, 0, 0, 0, /* R0x69 */ /* R exposure time variable [0, 64-65535] */ 0, 0, 0, 0, /* R0x6d */ /* G exposure time variable [0, 64-65535] */ 0, 0, 0, 0, /* R0x71 */ /* B exposure time variable [0, 64-65535] */ /* 0x75 (last) */ }; static scsiblk window_descriptor_block = { window_descriptor_blockC, sizeof (window_descriptor_blockC) }; /* LS-30 has different window-descriptor ! */ static unsigned char window_descriptor_blockC_LS30[] = { #define used_WDB_size_LS30 0x32 0x00, /* 0x00 */ /* Window Identifier */ #define WD_wid_0 0x00 /* Only one supported */ #define WD_wid_1 0x01 #define WD_wid_2 0x02 #define WD_wid_3 0x03 #define WD_wid_4 0x04 #define WD_wid_9 0x09 0x00, /* reserved, AUTO */ 0x00, 0x00, /* 0x02 */ /* X Resolution in dpi */ 0x00, 0x00, /* 0x04 */ /* Y Resolution in dpi */ 0x00, 0x00, 0x00, 0x00, /* 0x06 */ /* Upper Left X in 2700pt/inch */ 0x00, 0x00, 0x00, 0x00, /* 0x0a */ /* Upper Left Y in 2700pt/inch */ 0x00, 0x00, 0x00, 0x00, /* 0x0e */ /* Width 1200pt/inch */ 0x00, 0x00, 0x00, 0x00, /* 0x12 */ /* Length 1200pt/inch */ 0x00, /* 0x16 */ /* Brightness */ 0x00, /* 0x17 */ /* Reserved */ 0x00, /* 0x18 */ /* Contrast */ 0x05, /* 0x19 */ /* Image Mode */ 0x08, /* 0x1a */ /* Bits/Pixel */ #define WD_bits_10 0x0a 0, 0, 0, 0, 0, /* 0x1b */ /* Reserved */ 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */ 0, /* 0x29 */ /* Negative/positive prevue/scan */ #define set_WD_negative_LS30(sb, val) setbitfield(sb + 0x29, 0x1, 0, (val?0:1)) #define get_WD_negative_LS30(sb) getbitfield(sb + 0x29, 0x1, 0) /* scan mode */ #define set_WD_scanmode_LS30(sb, val) setbitfield(sb + 0x29, 0x3, 0, val) #define get_WD_scanmode_LS30(sb) getbitfield(sb + 0x29, 0x3, 0) 0x04, /* 0x2a */ 0x02, /* 0x2b */ 0x01, /* 0x2c */ 0xff, /* 0x2d */ 0,0, /* 0x2e */ 0,0, /* 0x30 */ #define set_gain_LS30(sb, val) putnbyte(sb + 0x2e, val, 4) #define get_gain_LS30(sb) getnbyte(sb + 0x2e, 4) }; static scsiblk window_descriptor_block_LS30 = { window_descriptor_blockC, sizeof (window_descriptor_blockC_LS30) }; /* ==================================================================== */ /*#define set_WDB_length(length) (window_descriptor_block.size = (length)) */ #define WPDB_OFF(b) (b + set_window.size) #define WDB_OFF(b, n) (b + set_window.size + \ window_parameter_data_block.size + \ ( window_descriptor_block.size * (n - 1) ) ) #define set_WPDB_wdbnum(sb,n) set_WPDB_wdblen(sb,window_descriptor_block.size*n) /* ==================================================================== */ static unsigned char scanC[] = { SCAN, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk scan = {scanC, sizeof (scanC)}; #define set_SC_xfer_length(sb, val) sb[0x04] = (unsigned char)val /* ==================================================================== */ /* static unsigned char send_diagnosticC[] = { SEND_DIAGNOSTIC, 0x04, 0x00, 0x00, 0x00, 0x00 }; static scsiblk send_diagnostic = { send_diagnosticC, sizeof(send_diagnosticC) }; */ /* ==================================================================== */ /* sread instead of read because read is a libc primitive */ static unsigned char sreadC[] = { READ, 0x00, 0x00, /* Data Type Code */ 0x00, /* reserved */ 0x00, 0x00, /* data type qualifier */ 0x00, 0x00, 0x00, /* transfer length */ 0x00 /* control */ }; static scsiblk sread = {sreadC, sizeof (sreadC)}; #define set_R_data1_code(sb, val) sb[0x01] = val #define set_R_datatype_code(sb, val) sb[0x02] = val #define R_datatype_imagedata 0x00 #define R_EX_datatype_LUT 0x01 /* Experiment code */ #define R_image_positions 0x88 #define R_EX_datatype_shading_data 0xa0 /* Experiment code */ #define R_user_reg_gamma 0xc0 #define R_device_internal_info 0xe0 #define set_R_datatype_qual_upper(sb, val) sb[0x04] = val #define set_R_datatype_qual_lower(sb, val) sb[0x05] = val #define R_DQ_none 0x00 #define R_DQ_Rcomp 0x06 #define R_DQ_Gcomp 0x07 #define R_DQ_Bcomp 0x08 #define R_DQ_Reg1 0x01 #define R_DQ_Reg2 0x02 #define R_DQ_Reg3 0x03 #define set_R_xfer_length(sb, val) putnbyte(sb + 0x06, val, 3) /* ==================================================================== */ /* Length of internal info structure */ #define DI_length 256 /* Functions for picking out data from the internal info structure */ #define get_DI_ADbits(b) getnbyte(b + 0x00, 1) #define get_DI_Outputbits(b) getnbyte(b + 0x01, 1) #define get_DI_MaxResolution(b) getnbyte(b + 0x02, 2) #define get_DI_Xmax(b) getnbyte(b + 0x04, 2) #define get_DI_Ymax(b) getnbyte(b + 0x06, 2) #define get_DI_Xmaxpixel(b) getnbyte(b + 0x08, 2) #define get_DI_Ymaxpixel(b) getnbyte(b + 0x0a, 2) #define get_DI_currentY(b) getnbyte(b + 0x10, 2) #define get_DI_currentFocus(b) getnbyte(b + 0x12, 2) #define get_DI_currentscanpitch(b) getnbyte(b + 0x14, 1) #define get_DI_autofeeder(b) getnbyte(b + 0x1e, 1) #define get_DI_analoggamma(b) getnbyte(b + 0x1f, 1) #define get_DI_deviceerror0(b) getnbyte(b + 0x40, 1) #define get_DI_deviceerror1(b) getnbyte(b + 0x41, 1) #define get_DI_deviceerror2(b) getnbyte(b + 0x42, 1) #define get_DI_deviceerror3(b) getnbyte(b + 0x43, 1) #define get_DI_deviceerror4(b) getnbyte(b + 0x44, 1) #define get_DI_deviceerror5(b) getnbyte(b + 0x45, 1) #define get_DI_deviceerror6(b) getnbyte(b + 0x46, 1) #define get_DI_deviceerror7(b) getnbyte(b + 0x47, 1) #define get_DI_WBETR_R(b) getnbyte(b + 0x80, 2) /* White balance exposure time variable R */ #define get_DI_WBETR_G(b) getnbyte(b + 0x82, 2) #define get_DI_WBETR_B(b) getnbyte(b + 0x84, 2) #define get_DI_PRETV_R(b) getnbyte(b + 0x88, 2) /* Prescan result exposure tim4e variable R */ #define get_DI_PRETV_G(b) getnbyte(b + 0x8a, 2) #define get_DI_PRETV_B(b) getnbyte(b + 0x8c, 2) #define get_DI_CETV_R(b) getnbyte(b + 0x90, 2) /* Current exposure time variable R */ #define get_DI_CETV_G(b) getnbyte(b + 0x92, 2) #define get_DI_CETV_B(b) getnbyte(b + 0x94, 2) #define get_DI_IETU_R(b) getnbyte(b + 0x98, 1) /* Internal exposure time unit R */ #define get_DI_IETU_G(b) getnbyte(b + 0x99, 1) #define get_DI_IETU_B(b) getnbyte(b + 0x9a, 1) #define get_DI_limitcondition(b) getnbyte(b + 0xa0, 1) #define get_DI_offsetdata_R(b) getnbyte(b + 0xa1, 1) #define get_DI_offsetdata_G(b) getnbyte(b + 0xa2, 1) #define get_DI_offsetdata_B(b) getnbyte(b + 0xa3, 1) #define get_DI_poweron_errors(b,to) memcpy(to, (b + 0xa8), 8) /* ==================================================================== */ static unsigned char sendC[] = { SEND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk send = {sendC, sizeof (sendC)}; #define set_S_datatype_code(sb, val) sb[0x02] = (unsigned char)val #define S_datatype_imagedatai 0x00 #define S_EX_datatype_LUT 0x01 /* Experiment code */ #define S_EX_datatype_shading_data 0xa0 /* Experiment code */ #define S_user_reg_gamma 0xc0 #define S_device_internal_info 0x03 #define set_S_datatype_qual_upper(sb, val) sb[0x04] = (unsigned char)val #define S_DQ_none 0x00 #define S_DQ_Rcomp 0x06 #define S_DQ_Gcomp 0x07 #define S_DQ_Bcomp 0x08 #define S_DQ_Reg1 0x01 #define S_DQ_Reg2 0x02 #define S_DQ_Reg3 0x03 #define S_DQ_Reg9 0x09 #define set_S_xfer_length(sb, val) putnbyte(sb + 0x06, val, 3) /* static unsigned char gamma_user_LUT_LS1K[512] = { 0x00 }; static scsiblk gamma_user_LUT_LS1K_LS1K = { gamma_user_LUT_LS1K, sizeof(gamma_user_LUT_LS1K) }; */ /* ==================================================================== */ static unsigned char object_positionC[] = { OBJECT_POSITION, 0x00, /* Auto feeder function */ 0x00, 0x00, 0x00, /* Count */ 0x00, 0x00, 0x00, 0x00, /* Reserved */ 0x00 /* Control byte */ }; #define set_OP_autofeed(b,val) setbitfield(b+0x01, 0x07, 0, val) #define OP_Discharge 0x00 #define OP_Feed 0x01 #define OP_Absolute 0x02 /* For development only */ static scsiblk object_position = { object_positionC, sizeof (object_positionC) }; /* ==================================================================== */ static unsigned char autofocusC[] = { AUTO_FOCUS, 0x00, 0x00, 0x00, 0x00, /* transfer length (0|8) */ 0x00 /* Control byte */ }; #define set_AF_transferlength(b, val) b[0x04] = (unsigned char)val #define get_AF_transferlength(b) ((int)b[0x04] & 0xff) #define set_AF_XPoint(b, val) putnbyte(b+0x06, val, 4) #define set_AF_YPoint(b, val) putnbyte(b+0x0a, val, 4) #define AF_Point_length 8 static scsiblk autofocus = {autofocusC, sizeof (autofocusC)}; /* ==================================================================== */ static unsigned char command_c1_C[] = { 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */ 0x00, 0x00 /* transfer length*/ }; static scsiblk command_c1 = {command_c1_C, sizeof (command_c1_C)}; /* ==================================================================== */ static unsigned char autofocusLS30C[] = { 0xe0, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, /* */ 0x09, 0x00 /* transfer length*/ }; static unsigned char autofocuspos[] = { 0x00, 0x00, 0x00, 0x05, 0x10, /* x-position */ 0x00, 0x00, 0x07, 0x9b, /* y-position */ }; #define set_AF_transferlength(b, val) b[0x04] = (unsigned char)val #define get_AF_transferlength(b) ((int)b[0x04] & 0xff) #define set_AF_XPoint(b, val) putnbyte(b+0x06, val, 4) #define set_AF_YPoint(b, val) putnbyte(b+0x0a, val, 4) #define AF_Point_length 8 static scsiblk autofocusLS30 = {autofocusLS30C, sizeof (autofocusLS30C)}; /* ==================================================================== */ static unsigned char commande1C[] = { 0xe1, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, /* */ 0x0d, 0x00 /* transfer length*/ }; static scsiblk commande1 = {commande1C, sizeof (commande1C)}; /* ==================================================================== */ /* static unsigned char request_senseC[] = { REQUEST_SENSE, 0x00, 0x00, 0x00, 0x00, 0x00 #define set_RS_allocation_length(sb,val) sb[0x04] = (unsigned char)val }; static scsiblk request_sense = { request_senseC, sizeof (request_senseC) }; */ /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) /* normally 0 */ #define get_RS_additional_length(b) b[0x07] /* always 10 */ #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /* valid, always 0 */ #define rs_return_block_size 18 /* Says Nikon */ #endif sane-backends-1.0.27/backend/abaton.conf.in0000664000175000017500000000003112112021330015304 00000000000000scsi ABATON /dev/scanner sane-backends-1.0.27/backend/hs2p.h0000664000175000017500000003665212112021330013633 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Jeremy Johnson This file is part of a SANE backend for Ricoh IS450 and IS420 family of HS2P Scanners using the SCSI controller. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef HS2P_H #define HS2P_H 1 #include #include "../include/sane/config.h" #include "hs2p-scsi.h" #include "hs2p-saneopts.h" #define HS2P_CONFIG_FILE "hs2p.conf" #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 typedef struct { const char *mfg; const char *model; } HS2P_HWEntry; enum CONNECTION_TYPES { CONNECTION_SCSI = 0, CONNECTION_USB }; enum media { FLATBED = 0x00, SIMPLEX, DUPLEX }; typedef struct data { size_t bufsize; /* 00H IMAGE */ /* 01H RESERVED */ /* 02H Halftone Mask */ SANE_Byte gamma[256]; /* 03H Gamma Function */ /* 04H - 7FH Reserved */ SANE_Byte endorser[19]; /* 80H Endorser */ SANE_Byte size; /* 81H startpos(4bits) + width(4bits) */ /* 82H Reserved */ /* 83H Reserved (Vendor Unique) */ SANE_Byte nlines[5]; /* 84H Page Length */ MAINTENANCE_DATA maintenance; /* 85H */ SANE_Byte adf_status; /* 86H */ /* 87H Reserved (Skew Data) */ /* 88H-91H Reserved (Vendor Unique) */ /* 92H Reserved (Scanner Extension I/O Access) */ /* 93H Reserved (Vendor Unique) */ /* 94H-FFH Reserved (Vendor Unique) */ } HS2P_DATA; typedef struct { SANE_Range xres_range; SANE_Range yres_range; SANE_Range x_range; SANE_Range y_range; SANE_Int window_width; SANE_Int window_height; SANE_Range brightness_range; SANE_Range contrast_range; SANE_Range threshold_range; char inquiry_data[256]; SANE_Byte max_win_sections; /* Number of supported window subsections IS450 supports max of 4 sections IS420 supports max of 6 sections */ /* Defaults */ SANE_Int default_res; SANE_Int default_xres; SANE_Int default_yres; SANE_Int default_imagecomposition; /* [lineart], halftone, grayscale, color */ SANE_Int default_media; /* [flatbed], simplex, duplex */ SANE_Int default_paper_size; /* [letter], legal, ledger, ... */ SANE_Int default_brightness; SANE_Int default_contrast; SANE_Int default_gamma; /* Normal, Soft, Sharp, Linear, User */ SANE_Bool default_adf; SANE_Bool default_duplex; /* SANE_Bool default_border; SANE_Bool default_batch; SANE_Bool default_deskew; SANE_Bool default_check_adf; SANE_Int default_timeout_adf; SANE_Int default_timeout_manual; SANE_Bool default_control_panel; */ /* Mode Page Parameters */ MP_CXN cxn; /* hdr + Connection Parameters */ SANE_Int bmu; SANE_Int mud; SANE_Int white_balance; /* 00H Relative, 01H Absolute; power on default is relative */ /* Lamp Timer not supported */ SANE_Int adf_control; /* 00H None, 01H Book, 01H Simplex, 02H Duplex */ SANE_Int adf_mode_control; /* bit2: prefeed mode invalid: "0" : valid "1" */ /* Medium Wait Timer not supported */ SANE_Int endorser_control; /* Default Off when power on */ SANE_Char endorser_string[20]; SANE_Bool scan_wait_mode; /* wait for operator panel start button to be pressed */ SANE_Bool service_mode; /* power on default self_diagnostics 00H; 01H optical_adjustment */ /* standard information: EVPD bit is 0 */ SANE_Byte devtype; /* devtype[6]="scanner" */ SANE_Char vendor[9]; /* model name 8+1 */ SANE_Char product[17]; /* product name 16+1 */ SANE_Char revision[5]; /* revision 4+1 */ /* VPD information: EVPD bit is 1, Page Code=C0H */ /* adf_id: 0: No ADF * 1: Single-sided ADF * 2: Double-sided ADF * 3: ARDF (Reverse double-sided ADF) * 4: Reserved */ SANE_Bool hasADF; /* If YES; can either be one of Simplex,Duplex,ARDF */ SANE_Bool hasSimplex; SANE_Bool hasDuplex; SANE_Bool hasARDF; SANE_Bool hasEndorser; SANE_Bool hasIPU; SANE_Bool hasXBD; /* VPD Image Composition */ SANE_Bool supports_lineart; SANE_Bool supports_dithering; SANE_Bool supports_errordiffusion; SANE_Bool supports_color; SANE_Bool supports_4bitgray; SANE_Bool supports_8bitgray; /* VPD Image Data Processing ACE (supported for IS420) */ SANE_Bool supports_whiteframing; SANE_Bool supports_blackframing; SANE_Bool supports_edgeextraction; SANE_Bool supports_noiseremoval; /* supported for IS450 if IPU installed */ SANE_Bool supports_smoothing; /* supported for IS450 if IPU installed */ SANE_Bool supports_linebolding; /* VPD Compression (not supported for IS450) */ SANE_Bool supports_MH; SANE_Bool supports_MR; SANE_Bool supports_MMR; SANE_Bool supports_MHB; /* VPD Marker Recognition (not supported for IS450) */ SANE_Bool supports_markerrecognition; /* VPD Size Recognition (supported for IS450 if IPU installed) */ SANE_Bool supports_sizerecognition; /* VPD X Maximum Output Pixel: IS450:4960 IS420:4880 */ SANE_Int xmaxoutputpixels; /* jis information VPD IDENTIFIER Page Code F0H */ SANE_Int resBasicX; /* basic X resolution */ SANE_Int resBasicY; /* basic Y resolution */ SANE_Int resXstep; /* resolution step in main scan direction */ SANE_Int resYstep; /* resolution step in sub scan direction */ SANE_Int resMaxX; /* maximum X resolution */ SANE_Int resMaxY; /* maximum Y resolution */ SANE_Int resMinX; /* minimum X resolution */ SANE_Int resMinY; /* minimum Y resolution */ SANE_Int resStdList[16 + 1]; /* list of available standard resolutions (first slot is the length) */ SANE_Int winWidth; /* length of window (in BasicX res DPI) */ SANE_Int winHeight; /* height of window (in BasicY res DPI) */ /* jis.functions duplicates vpd.imagecomposition lineart/dither/grayscale */ SANE_Bool overflow_support; SANE_Bool lineart_support; SANE_Bool dither_support; SANE_Bool grayscale_support; } HS2P_Info; typedef struct HS2P_Device { struct HS2P_Device *next; /* * struct with pointers to device/vendor/model names, and a type value * used to inform sane frontend about the device */ SANE_Device sane; HS2P_Info info; SENSE_DATA sense_data; } HS2P_Device; #define GAMMA_LENGTH 256 typedef struct HS2P_Scanner { /* all the state needed to define a scan request: */ struct HS2P_Scanner *next; /* linked list for housekeeping */ int fd; /* SCSI filedescriptor */ /* --------------------------------------------------------------------- */ /* immutable values which are set during reading of config file. */ int buffer_size; /* for sanei_open */ int connection; /* hardware interface type */ /* SANE option descriptors and values */ SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; /* SANE image parameters */ /* additional values that don't fit into Option_Value representation */ SANE_Word gamma_table[GAMMA_LENGTH]; /* Custom Gray Gamma Table */ /* state information - not options */ /* scanner dependent/low-level state: */ HS2P_Device *hw; SANE_Int bmu; /* Basic Measurement Unit */ SANE_Int mud; /* Measurement Unit Divisor */ SANE_Byte image_composition; /* LINEART, HALFTONE, GRAYSCALE */ SANE_Byte bpp; /* 1,4,6,or 8 Bits Per Pixel */ u_long InvalidBytes; size_t bytes_to_read; SANE_Bool cancelled; /*SANE_Bool backpage; */ SANE_Bool scanning; SANE_Bool another_side; SANE_Bool EOM; HS2P_DATA data; } HS2P_Scanner; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const SANE_Range u16_range = { 0, /* minimum */ 65535, /* maximum */ 0 /* quantization */ }; #define SM_LINEART SANE_VALUE_SCAN_MODE_LINEART #define SM_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE #define SM_DITHER "Dither" #define SM_ERRORDIFFUSION "Error Diffusion" #define SM_COLOR SANE_VALUE_SCAN_MODE_COLOR #define SM_4BITGRAY "4-Bit Gray" #define SM_6BITGRAY "6-Bit Gray" #define SM_8BITGRAY "8-Bit Gray" static SANE_String scan_mode_list[9]; enum { FB, ADF }; static SANE_String_Const scan_source_list[] = { "FB", /* Flatbed */ "ADF", /* Automatic Document Feeder */ NULL }; static SANE_String compression_list[6]; /* "none", "g31d MH", "g32d MR", "g42d MMR", "MH byte boundary", NULL} */ typedef struct { SANE_String name; double width, length; /* paper dimensions in mm */ } HS2P_Paper; /* list of support paper sizes */ /* 'custom' MUST be item 0; otherwise a width or length of 0 indicates * the maximum value supported by the scanner */ static const HS2P_Paper paper_sizes[] = { /* Name, Width, Height in mm */ {"Custom", 0.0, 0.0}, {"Letter", 215.9, 279.4}, {"Legal", 215.9, 355.6}, {"Ledger", 279.4, 431.8}, {"A3", 297, 420}, {"A4", 210, 297}, {"A4R", 297, 210}, {"A5", 148.5, 210}, {"A5R", 210, 148.5}, {"A6", 105, 148.5}, {"B4", 250, 353}, {"B5", 182, 257}, {"Full", 0.0, 0.0}, }; #define PORTRAIT "Portait" #define LANDSCAPE "Landscape" static SANE_String_Const orientation_list[] = { PORTRAIT, LANDSCAPE, NULL /* sentinel */ }; /* MUST be kept in sync with paper_sizes */ static SANE_String_Const paper_list[] = { "Custom", "Letter", "Legal", "Ledger", "A3", "A4", "A4R", "A5", "A5R", "A6", "B4", "B5", "Full", NULL /* (not the same as "") sentinel */ }; #if 0 static /* inline */ int _is_host_little_endian (void); static /* inline */ int _is_host_little_endian () { SANE_Int val = 255; unsigned char *firstbyte = (unsigned char *) &val; return (*firstbyte == 255) ? SANE_TRUE : SANE_FALSE; } #endif static /* inline */ void _lto2b (u_long val, SANE_Byte * bytes) { bytes[0] = (val >> 8) & 0xff; bytes[1] = val & 0xff; } static /* inline */ void _lto3b (u_long val, SANE_Byte * bytes) { bytes[0] = (val >> 16) & 0xff; bytes[1] = (val >> 8) & 0xff; bytes[2] = val & 0xff; } static /* inline */ void _lto4b (u_long val, SANE_Byte * bytes) { bytes[0] = (val >> 24) & 0xff; bytes[1] = (val >> 16) & 0xff; bytes[2] = (val >> 8) & 0xff; bytes[3] = val & 0xff; } static /* inline */ u_long _2btol (SANE_Byte * bytes) { u_long rv; rv = (bytes[0] << 8) | bytes[1]; return rv; } static /* inline */ u_long _4btol (SANE_Byte * bytes) { u_long rv; rv = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; return rv; } /* static inline SANE_Int _2btol(SANE_Byte *bytes) { SANE_Int rv; rv = (bytes[0] << 8) | bytes[1]; return (rv); } */ static inline SANE_Int _3btol (SANE_Byte * bytes) { SANE_Int rv; rv = (bytes[0] << 16) | (bytes[1] << 8) | bytes[2]; return (rv); } /* static inline SANE_Int _4btol(SANE_Byte *bytes) { SANE_Int rv; rv = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; return (rv); } */ enum adf_ret_bytes { ADF_SELECTION = 2, ADF_MODE_CONTROL, MEDIUM_WAIT_TIMER }; #define get_paddingtype_id(s) (get_list_index( paddingtype_list, (char *)(s) )) #define get_paddingtype_val(i) (paddingtype[ get_paddingtype_id( (i) ) ].val) #define get_paddingtype_strndx(v) (get_val_id_strndx(&paddingtype[0], NELEMS(paddingtype), (v))) #define get_halftone_code_id(s) (get_list_index( halftone_code, (char *)(s) )) #define get_halftone_code_val(i) (halftone[get_halftone_code_id( (i) ) ].val) #define get_halftone_pattern_id(s) (get_list_index( halftone_pattern_list, (char *)(s) )) #define get_halftone_pattern_val(i) (halftone[get_halftone_pattern_id( (i) ) ].val) #define get_auto_binarization_id(s) (get_list_index( auto_binarization_list, (char *)(s) )) #define get_auto_binarization_val(i) (auto_binarization[ get_auto_binarization_id( (i) ) ].val) #define get_auto_separation_id(s) (get_list_index( auto_separation_list, (char *)(s) )) #define get_auto_separation_val(i) (auto_separation[ get_auto_separation_id( (i) ) ].val) #define get_noisematrix_id(s) (get_list_index( noisematrix_list, (char *)(s) )) #define get_noisematrix_val(i) (noisematrix[ get_noisematrix_id( (i) ) ].val) #define get_grayfilter_id(s) (get_list_index( grayfilter_list, (char *)(s) )) #define get_grayfilter_val(i) (grayfilter[ get_grayfilter_id( (i) ) ].val) #define get_paper_id(s) (get_list_index( paper_list, (char *)(s) )) #define get_compression_id(s) (get_list_index( (const char **)compression_list, (char *)(s) )) #define get_scan_source_id(s) (get_list_index( (const char **)scan_source_list, (char *)(s) )) #define reserve_unit(fd) (unit_cmd((fd),HS2P_SCSI_RESERVE_UNIT)) #define release_unit(fd) (unit_cmd((fd),HS2P_SCSI_RELEASE_UNIT)) #define GET SANE_TRUE #define SET SANE_FALSE #define get_endorser_control(fd,val) (endorser_control( (fd), (val), GET )) #define set_endorser_control(fd,val) (endorser_control( (fd), (val), SET )) #define get_connection_parameters(fd,parm) (connection_parameters( (fd), (parm), GET )) #define set_connection_parameters(fd,parm) (connection_parameters( (fd), (parm), SET )) #define get_adf_control(fd, a, b, c) (adf_control( (fd), GET, (a), (b), (c) )) #define set_adf_control(fd, a, b, c) (adf_control( (fd), SET, (a), (b), (c) )) #define RELATIVE_WHITE 0x00 #define ABSOLUTE_WHITE 0x01 #define get_white_balance(fd,val) (white_balance( (fd), (val), GET )) #define set_white_balance(fd,val) (white_balance( (fd), (val), SET )) #define get_scan_wait_mode(fd) (scan_wait_mode( (fd), 0, GET )) #define set_scan_wait_mode(fd,val) (scan_wait_mode( (fd), (val), SET )) #define get_service_mode(fd) (service_mode( (fd), 0, GET )) #define set_service_mode(fd,val) (service_mode( (fd), (val), SET )) #define isset_ILI(sd) ( ((sd).sense_key & 0x20) != 0) #define isset_EOM(sd) ( ((sd).sense_key & 0x40) != 0) #endif /* HS2P_H */ sane-backends-1.0.27/backend/magicolor.conf.in0000664000175000017500000000234612112021330016027 00000000000000### magicolor.conf ### ### here are some examples for how to configure the Magicolor backend ### Timeout settings: SNMP autodetection, Scan data read requests and other ### read requests. All values are given in milliseconds, ### i.e. 1000 is 1 second. # SNMP auto-detection waits 1.5 seconds snmp-timeout 1500 # wait 15 seconds for scan data (color scans take ~6 seconds to initialize, # so we need to wait longer than that) scan-data-timeout 15000 # Wait 5 seconds for all other data requests request-timeout 5000 ### Network: Format is "net IP_ADDRESS [USB_ID]" or "net autodiscovery" ### if USB_ID is left out, SNMP is used to detect the device type net autodiscovery #net 10.0.0.5 ### The following is a magicolor 1690mf with explicit IP-Address #net 10.0.0.5 0x2098 # net 192.168.0.1 ### USB: format is "usb" for automatic (libusb) discovery, based on USB IDs, ### or "usb to force the use of a particular ### device (the backend has some additional checks and will not use ### non-KONICA MINOLTA devices, though) usb ### For libusb support for unknown scanners use the following command ### usb ### e.g.: # usb 0x132b 0x2098 sane-backends-1.0.27/backend/pieusb.c0000664000175000017500000015437013106201017014245 00000000000000/* sane - Scanner Access Now Easy. pieusb.c Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ========================================================================= * * SANE interface to three Reflecta USB scanners with USB-id 0x05e3/0x0145: * - Reflecta CrystalScan 7200 (model id 0x30) * - Reflecta ProScan 7200 (model id 0x36) * - Reflecta 6000 Multiple Slide Scanner (model id 0x3A) * * ========================================================================= */ #define DEBUG_NOT_STATIC /* -------------------------------------------------------------------------- * * INCLUDES * * --------------------------------------------------------------------------*/ #include "../include/sane/config.h" /* Standard includes for various utiliy functions */ #include /* for FILE */ #include /* for strlen */ #include /* for NULL */ #include #include /* Configuration defines */ #include "../include/sane/config.h" /* SANE includes */ #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_config.h" /* Backend includes */ #define BACKEND_NAME pieusb #include "../include/sane/sanei_backend.h" #include "pieusb.h" #include "pieusb_specific.h" #define CAN_DO_4_CHANNEL_TIFF #ifdef CAN_DO_4_CHANNEL_TIFF extern void write_tiff_rgbi_header (FILE *fptr, int width, int height, int depth, int resolution, const char *icc_profile); #endif /* -------------------------------------------------------------------------- * * DEFINES * * --------------------------------------------------------------------------*/ /* Build number of this backend */ #define BUILD 1 /* Configuration filename */ #define PIEUSB_CONFIG_FILE "pieusb.conf" /* Debug error levels */ #define DBG_error 1 /* errors */ #define DBG_warning 3 /* warnings */ #define DBG_info 5 /* information */ #define DBG_info_sane 7 /* information sane interface level */ #define DBG_inquiry 8 /* inquiry data */ #define DBG_info_proc 9 /* information pieusb backend functions */ #define DBG_info_scan 11 /* information scanner commands */ #define DBG_info_usb 13 /* information usb level functions */ /* device flags */ #define FLAG_SLIDE_TRANSPORT 0x01 /* -------------------------------------------------------------------------- * * SUPPORTED DEVICES SPECIFICS * * --------------------------------------------------------------------------*/ struct Pieusb_USB_Device_Entry* pieusb_supported_usb_device_list = NULL; struct Pieusb_USB_Device_Entry pieusb_supported_usb_device; /* for searching */ /* -------------------------------------------------------------------------- * * LISTS OF ACTIVE DEVICE DEFINITIONS AND SCANNERS * * --------------------------------------------------------------------------*/ Pieusb_Device_Definition *pieusb_definition_list_head = NULL; static Pieusb_Scanner *first_handle = NULL; static const SANE_Device **devlist = NULL; /* -------------------------------------------------------------------------- * * SANE INTERFACE * * --------------------------------------------------------------------------*/ /** * Initializes the debugging system, the USB system, the version code and * 'attaches' available scanners, i.e. creates device definitions for all * scanner devices found. * * @param version_code * @param authorize * @return SANE_STATUS_GOOD */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; char config_line[PATH_MAX]; SANE_Word vendor_id; SANE_Word product_id; SANE_Int model_number; SANE_Int flags; SANE_Status status; int i; /* Initialize debug logging */ DBG_INIT (); DBG (DBG_info_sane, "sane_init() build %d\n", BUILD); /* Set version code to current major, minor and build number */ /* TODO: use V_MINOR instead or SANE_CURRENT_MINOR? If so, why? */ if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); /* Initialize usb */ sanei_usb_init (); sanei_usb_set_timeout (30 * 1000); /* 30 sec timeout */ /* There are currently 3 scanners hardcoded into this backend, see below. * The config file may add other scanners using a line like * usb 0x1234 0x5678 0x9A * where the first two hex numbers are vendor and product id, and the last * number is the model number. Unfortunately, this is not according to the * config file standard. Anyone any suggestions? */ /* Create default list */ pieusb_supported_usb_device_list = calloc (4, sizeof(struct Pieusb_USB_Device_Entry)); if (pieusb_supported_usb_device_list == NULL) return SANE_STATUS_NO_MEM; /* Reflecta CrystalScan 7200, model number 0x30 */ pieusb_supported_usb_device_list[0].vendor = 0x05e3; pieusb_supported_usb_device_list[0].product = 0x0145; pieusb_supported_usb_device_list[0].model = 0x30; pieusb_supported_usb_device_list[0].flags = 0; /* Reflecta ProScan 7200, model number 0x36 */ pieusb_supported_usb_device_list[1].vendor = 0x05e3; pieusb_supported_usb_device_list[1].product = 0x0145; pieusb_supported_usb_device_list[1].model = 0x36; pieusb_supported_usb_device_list[1].flags = 0; /* Reflecta 6000 Multiple Slide Scanner, model number 0x3a */ pieusb_supported_usb_device_list[2].vendor = 0x05e3; pieusb_supported_usb_device_list[2].product = 0x0142; pieusb_supported_usb_device_list[2].model = 0x3a; pieusb_supported_usb_device_list[2].flags = FLAG_SLIDE_TRANSPORT; /* end of list */ pieusb_supported_usb_device_list[3].vendor = 0; pieusb_supported_usb_device_list[3].product = 0; pieusb_supported_usb_device_list[3].model = 0; pieusb_supported_usb_device_list[3].flags = 0; /* Add entries from config file */ fp = sanei_config_open (PIEUSB_CONFIG_FILE); if (!fp) { DBG (DBG_info_sane, "sane_init() did not find a config file, using default list of supported devices\n"); } else { while (sanei_config_read (config_line, sizeof (config_line), fp)) { /* Ignore line comments and empty lines */ if (config_line[0] == '#') continue; if (strlen (config_line) == 0) continue; /* Ignore lines which do not begin with 'usb ' */ if (strncmp (config_line, "usb ", 4) != 0) continue; /* Parse vendor-id, product-id and model number and add to list */ DBG (DBG_info_sane, "sane_init() config file parsing %s\n", config_line); status = sanei_pieusb_parse_config_line(config_line, &vendor_id, &product_id, &model_number, &flags); if (status == SANE_STATUS_GOOD) { DBG (DBG_info_sane, "sane_init() config file lists device %04x %04x %02x %02x\n",vendor_id, product_id, model_number, flags); if (!sanei_pieusb_supported_device_list_contains(vendor_id, product_id, model_number, flags)) { DBG (DBG_info_sane, "sane_init() adding device %04x %04x %02x %02x\n",vendor_id, product_id, model_number, flags); sanei_pieusb_supported_device_list_add(vendor_id, product_id, model_number, flags); } else { DBG (DBG_info_sane, "sane_init() list already contains %04x %04x %02x %02x\n", vendor_id, product_id, model_number, flags); } } else { DBG (DBG_info_sane, "sane_init() config file parsing %s: error\n", config_line); } } fclose (fp); } /* Loop through supported device list */ i = 0; while (pieusb_supported_usb_device_list[i].vendor != 0) { /* Check if the supported device is present. If so, create a device * definition structure for it. * The variable pieusb_supported_usb_device is set to current values, * which are used in the callback. */ pieusb_supported_usb_device.vendor = pieusb_supported_usb_device_list[i].vendor; pieusb_supported_usb_device.product = pieusb_supported_usb_device_list[i].product; pieusb_supported_usb_device.model = pieusb_supported_usb_device_list[i].model; pieusb_supported_usb_device.flags = pieusb_supported_usb_device_list[i].flags; pieusb_supported_usb_device.device_number = -1; /* No device number (yet) */ DBG( DBG_info_sane, "sane_init() looking for scanner %04x %04x model %02x, flags %02x\n", pieusb_supported_usb_device.vendor, pieusb_supported_usb_device.product, pieusb_supported_usb_device.model, pieusb_supported_usb_device.flags); sanei_usb_find_devices (pieusb_supported_usb_device.vendor, pieusb_supported_usb_device.product, sanei_pieusb_find_device_callback); i++; } return SANE_STATUS_GOOD; } /** * Backend exit. * Clean up allocated memory. */ void sane_exit (void) { Pieusb_Device_Definition *dev, *next; DBG (DBG_info_sane, "sane_exit()\n"); for (dev = pieusb_definition_list_head; dev; dev = next) { next = dev->next; free((void *)dev->sane.name); free((void *)dev->sane.vendor); free((void *)dev->sane.model); free (dev->version); free (dev); } pieusb_definition_list_head = NULL; if (devlist) { free (devlist); devlist = NULL; } } /** * Create a SANE device list from the device list generated by sane_init(). * * @param device_list List of SANE_Device elements * @param local_only If true, disregard network scanners. Not applicable for USB scanners. * @return SANE_STATUS_GOOD, or SANE_STATUS_NO_MEM if the list cannot be allocated */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { Pieusb_Device_Definition *dev; int i; DBG (DBG_info_sane, "sane_get_devices\n"); /* Create SANE_DEVICE list from device list created in sane_init() */ i = 0; for (dev = pieusb_definition_list_head; dev; dev = dev->next) { i++; } if (devlist) { free (devlist); } devlist = malloc ((i + 1) * sizeof (devlist[0])); if (!devlist) { return SANE_STATUS_NO_MEM; } i = 0; for (dev = pieusb_definition_list_head; dev; dev = dev->next) { devlist[i++] = &dev->sane; } devlist[i] = NULL; *device_list = devlist; return SANE_STATUS_GOOD; } /** * Open the scanner with the given devicename and return a handle to it, which * is a pointer to a Pieusb_Scanner struct. The handle will be an input to * a couple of other functions of the SANE interface. * * @param devicename Name of the device, corresponds to SANE_Device.name * @param handle handle to scanner (pointer to a Pieusb_Scanner struct) * @return SANE_STATUS_GOOD if the device has been opened */ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Pieusb_Device_Definition *dev; SANE_Status status; Pieusb_Scanner *scanner, *s; DBG (DBG_info_sane, "sane_open(%s)\n", devicename); /* Search for devicename */ if (devicename[0]) { for (dev = pieusb_definition_list_head; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { /* Is it a valid USB device? */ SANE_Word vendor; SANE_Word product; int i = 0; status = sanei_usb_get_vendor_product_byname (devicename, &vendor, &product); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_open: sanei_usb_get_vendor_product_byname failed %s\n", devicename); return status; } /* Get vendor-product-model & verify that is is supported */ /* Loop through supported device list */ while (pieusb_supported_usb_device_list[i].vendor != 0) { /* Check if vendor and product match */ if (pieusb_supported_usb_device_list[i].vendor == vendor && pieusb_supported_usb_device_list[i].product == product) { /* Check if a supported device is present * If so, create a device definition structure for it. */ /* Set pieusb_supported_usb_device to current values: these are used in callback */ pieusb_supported_usb_device.vendor = vendor; pieusb_supported_usb_device.product = product; pieusb_supported_usb_device.model = pieusb_supported_usb_device_list[i].model; pieusb_supported_usb_device.flags = pieusb_supported_usb_device_list[i].flags; pieusb_supported_usb_device.device_number = -1; sanei_usb_find_devices (vendor, product, sanei_pieusb_find_device_callback); if (pieusb_supported_usb_device.device_number == -1) { /* Did not succeed in opening the USB device, which is an error. * This error is not caught by sanei_usb_find_devices(), so handle * it here. */ DBG (DBG_error, "sane_open: sanei_usb_find_devices did not open device %s\n", devicename); return SANE_STATUS_INVAL; } } i++; } /* Now rescan the device list to see if it is present */ for (dev = pieusb_definition_list_head; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } } } else { /* empty devicename -> use first device */ dev = pieusb_definition_list_head; } /* If no device found, return error */ if (!dev) { return SANE_STATUS_INVAL; } /* Now create a scanner structure to return */ /* Check if we are not opening the same scanner again. */ for (s = first_handle; s; s = s->next) { if (s->device->sane.name == devicename) { *handle = s; return SANE_STATUS_GOOD; } } /* Create a new scanner instance */ scanner = malloc (sizeof (*scanner)); if (!scanner) { return SANE_STATUS_NO_MEM; } memset (scanner, 0, sizeof (*scanner)); scanner->device = dev; sanei_usb_open (dev->sane.name, &scanner->device_number); scanner->cancel_request = 0; scanner->shading_data_present = SANE_FALSE; /* Options and buffers */ (void)sanei_pieusb_init_options (scanner); /* wait for warmup */ status = sanei_pieusb_wait_ready (scanner, 0); if (status != SANE_STATUS_GOOD) { sanei_usb_close(scanner->device_number); free (scanner); DBG (DBG_error, "sane_open: scanner not ready\n"); return status; } /* First time settings */ /* ? */ /* Insert newly opened handle into list of open handles: */ scanner->next = first_handle; first_handle = scanner; *handle = scanner; return SANE_STATUS_GOOD; } /** * Close the scanner and remove the scanner from the list of active scanners. * * @param handle Scanner handle */ void sane_close (SANE_Handle handle) { Pieusb_Scanner *prev, *scanner; SANE_Int k; DBG (DBG_info_sane, "sane_close()\n"); /* Find handle in list of open handles: */ prev = 0; for (scanner = first_handle; scanner; scanner = scanner->next) { if (scanner == handle) { break; } prev = scanner; } /* Not a handle we know about. This may happen since all different backend * scanner instances are all cast to SANE_Handle (a void pointer) */ if (!scanner) { DBG (DBG_error, "sane_close(): invalid handle %p\n", handle); return; } /* Stop scan if still scanning */ if (scanner->scanning) { sanei_pieusb_on_cancel(scanner); } /* USB scanners may be still open here */ if (scanner->device_number >= 0) { sanei_usb_reset (scanner->device_number); sanei_usb_close (scanner->device_number); } /* Remove handle from list */ if (prev) { prev->next = scanner->next; } else { first_handle = scanner->next; } /* Free scanner related allocated memory and the scanner itself */ /*TODO: check if complete */ if (scanner->buffer.data) sanei_pieusb_buffer_delete(&scanner->buffer); free (scanner->ccd_mask); for (k=0; k<4; k++) free (scanner->shading_ref[k]); free (scanner->val[OPT_MODE].s); free (scanner->val[OPT_HALFTONE_PATTERN].s); free (scanner); } /** * Get option descriptor. Return the option descriptor with the given index * * @param handle Scanner handle * @param option Index of option descriptor to return * @return The option descriptor */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Pieusb_Scanner *scanner = handle; DBG (DBG_info_proc, "sane_get_option_descriptor() option=%d\n", option); if ((unsigned) option >= NUM_OPTIONS) { return 0; } return scanner->opt + option; } /** * Set or inquire the current value of option number 'option' of the device * represented by the given handle. * * @param handle Scanner handle * @param option Index of option to set or get * @param action Determines if the option value is read or set * @param val Pointer to value to set or get * @param info About set result. May be NULL. * @return SANE_STATUS_GOOD, or SANE_STATUS_INVAL if a parameter cannot be set */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Pieusb_Scanner *scanner = handle; SANE_Status status; SANE_Word cap; SANE_String_Const name; DBG(DBG_info_sane,"sane_control_option()\n"); if (info) { *info = 0; } /* Don't set or get options while the scanner is busy */ if (scanner->scanning) { DBG(DBG_error,"Device busy scanning, no option returned\n"); return SANE_STATUS_DEVICE_BUSY; } /* Check if option index is between bounds */ if ((unsigned) option >= NUM_OPTIONS) { DBG(DBG_error,"Index too large, no option returned\n"); return SANE_STATUS_INVAL; } /* Check if option is switched on */ cap = scanner->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG(DBG_error,"Option inactive (%s)\n", scanner->opt[option].name); return SANE_STATUS_INVAL; } /* Get name of option */ name = scanner->opt[option].name; if (!name) { name = "(no name)"; } /* */ switch (action) { case SANE_ACTION_GET_VALUE: DBG (DBG_info_sane, "get %s [#%d]\n", name, option); switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_BIT_DEPTH: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_THRESHOLD: case OPT_SHARPEN: case OPT_SHADING_ANALYSIS: case OPT_FAST_INFRARED: case OPT_ADVANCE_SLIDE: case OPT_CORRECT_SHADING: case OPT_CORRECT_INFRARED: case OPT_CLEAN_IMAGE: case OPT_SMOOTH_IMAGE: case OPT_TRANSFORM_TO_SRGB: case OPT_INVERT_IMAGE: case OPT_PREVIEW: case OPT_SAVE_SHADINGDATA: case OPT_SAVE_CCDMASK: case OPT_LIGHT: case OPT_DOUBLE_TIMES: case OPT_SET_EXPOSURE_R: case OPT_SET_EXPOSURE_G: case OPT_SET_EXPOSURE_B: case OPT_SET_EXPOSURE_I: case OPT_SET_GAIN_R: case OPT_SET_GAIN_G: case OPT_SET_GAIN_B: case OPT_SET_GAIN_I: case OPT_SET_OFFSET_R: case OPT_SET_OFFSET_G: case OPT_SET_OFFSET_B: case OPT_SET_OFFSET_I: *(SANE_Word *) val = scanner->val[option].w; DBG (DBG_info_sane, "get %s [#%d] val=%d\n", name, option,scanner->val[option].w); return SANE_STATUS_GOOD; /* word-array options: => for exposure gain offset? */ case OPT_CROP_IMAGE: memcpy (val, scanner->val[option].wa, scanner->opt[option].size); return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_CALIBRATION_MODE: case OPT_GAIN_ADJUST: case OPT_HALFTONE_PATTERN: strcpy (val, scanner->val[option].s); DBG (DBG_info_sane, "get %s [#%d] val=%s\n", name, option,scanner->val[option].s); return SANE_STATUS_GOOD; } break; case SANE_ACTION_SET_VALUE: switch (scanner->opt[option].type) { case SANE_TYPE_INT: DBG (DBG_info_sane, "set %s [#%d] to %d, size=%d\n", name, option, *(SANE_Word *) val, scanner->opt[option].size); break; case SANE_TYPE_FIXED: DBG (DBG_info_sane, "set %s [#%d] to %f\n", name, option, SANE_UNFIX (*(SANE_Word *) val)); break; case SANE_TYPE_STRING: DBG (DBG_info_sane, "set %s [#%d] to %s\n", name, option, (char *) val); break; case SANE_TYPE_BOOL: DBG (DBG_info_sane, "set %s [#%d] to %d\n", name, option, *(SANE_Word *) val); break; default: DBG (DBG_info_sane, "set %s [#%d]\n", name, option); } /* Check if option can be set */ if (!SANE_OPTION_IS_SETTABLE (cap)) { return SANE_STATUS_INVAL; } /* Check if new value within bounds */ status = sanei_constrain_value (scanner->opt + option, val, info); if (status != SANE_STATUS_GOOD) { return status; } /* Set option and handle info return */ switch (option) { /* (mostly) side-effect-free word options: */ case OPT_BIT_DEPTH: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_SHARPEN: case OPT_SHADING_ANALYSIS: case OPT_FAST_INFRARED: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } /* fall through */ case OPT_NUM_OPTS: case OPT_PREVIEW: case OPT_ADVANCE_SLIDE: case OPT_CORRECT_SHADING: case OPT_CORRECT_INFRARED: case OPT_CLEAN_IMAGE: case OPT_SMOOTH_IMAGE: case OPT_TRANSFORM_TO_SRGB: case OPT_INVERT_IMAGE: case OPT_SAVE_SHADINGDATA: case OPT_SAVE_CCDMASK: case OPT_THRESHOLD: case OPT_LIGHT: case OPT_DOUBLE_TIMES: case OPT_SET_GAIN_R: case OPT_SET_GAIN_G: case OPT_SET_GAIN_B: case OPT_SET_GAIN_I: case OPT_SET_OFFSET_R: case OPT_SET_OFFSET_G: case OPT_SET_OFFSET_B: case OPT_SET_OFFSET_I: case OPT_SET_EXPOSURE_R: case OPT_SET_EXPOSURE_G: case OPT_SET_EXPOSURE_B: case OPT_SET_EXPOSURE_I: scanner->val[option].w = *(SANE_Word *) val; break; /* side-effect-free word-array options: */ case OPT_CROP_IMAGE: memcpy (scanner->val[option].wa, val, scanner->opt[option].size); break; /* options with side-effects: */ case OPT_MODE: { /* Free current setting */ if (scanner->val[option].s) { free (scanner->val[option].s); } /* New setting */ scanner->val[option].s = (SANE_Char *) strdup (val); /* Info */ if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } break; } case OPT_CALIBRATION_MODE: case OPT_GAIN_ADJUST: case OPT_HALFTONE_PATTERN: { /* Free current setting */ if (scanner->val[option].s) { free (scanner->val[option].s); } /* New setting */ scanner->val[option].s = (SANE_Char *) strdup (val); break; } } /* Check the whole set */ if (sanei_pieusb_analyse_options(scanner)) { return SANE_STATUS_GOOD; } else { return SANE_STATUS_INVAL; } break; default: return SANE_STATUS_INVAL; break; } return SANE_STATUS_INVAL; } /** * Obtain the current scan parameters. The returned parameters are guaranteed * to be accurate between the time a scan has been started (sane start() has * been called) and the completion of that request. Outside of that window, the * returned values are best-effort estimates of what the parameters will be when * sane start() gets invoked. - says the SANE standard. * * @param handle Scanner handle * @param params Scan parameters * @return SANE_STATUS_GOOD */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Pieusb_Scanner *scanner = handle; const char *mode; double resolution, width, height; SANE_Int colors; DBG (DBG_info_sane, "sane_get_parameters\n"); if (params) { if (scanner->scanning) { /* sane_start() initialized a SANE_Parameters struct in the scanner */ DBG (DBG_info_sane, "sane_get_parameters from scanner values\n"); params->bytes_per_line = scanner->scan_parameters.bytes_per_line; params->depth = scanner->scan_parameters.depth; params->format = scanner->scan_parameters.format; params->last_frame = scanner->scan_parameters.last_frame; params->lines = scanner->scan_parameters.lines; params->pixels_per_line = scanner->scan_parameters.pixels_per_line; } else { /* Calculate appropriate values from option settings */ DBG (DBG_info_sane, "sane_get_parameters from option values\n"); if (scanner->val[OPT_PREVIEW].b) { resolution = scanner->device->fast_preview_resolution; } else { resolution = SANE_UNFIX(scanner->val[OPT_RESOLUTION].w); } DBG (DBG_info_sane, " resolution %f\n", resolution); width = SANE_UNFIX(scanner->val[OPT_BR_X].w)-SANE_UNFIX(scanner->val[OPT_TL_X].w); height = SANE_UNFIX(scanner->val[OPT_BR_Y].w)-SANE_UNFIX(scanner->val[OPT_TL_Y].w); DBG (DBG_info_sane, " width x height: %f x %f\n", width, height); params->lines = height / MM_PER_INCH * resolution; params->pixels_per_line = width / MM_PER_INCH * resolution; mode = scanner->val[OPT_MODE].s; if (strcmp(mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) { params->format = SANE_FRAME_GRAY; params->depth = 1; colors = 1; } else if(strcmp(mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { params->format = SANE_FRAME_GRAY; params->depth = 1; colors = 1; } else if(strcmp(mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { params->format = SANE_FRAME_GRAY; params->depth = scanner->val[OPT_BIT_DEPTH].w; colors = 1; } else if(strcmp(mode, SANE_VALUE_SCAN_MODE_RGBI) == 0) { params->format = SANE_FRAME_RGB; /* was: SANE_FRAME_RGBI */ params->depth = scanner->val[OPT_BIT_DEPTH].w; colors = 4; } else { /* SANE_VALUE_SCAN_MODE_COLOR */ params->format = SANE_FRAME_RGB; params->depth = scanner->val[OPT_BIT_DEPTH].w; colors = 3; } DBG (DBG_info_sane, " colors: %d\n", colors); if (params->depth == 1) { params->bytes_per_line = colors * (params->pixels_per_line + 7)/8; } else if (params->depth <= 8) { params->bytes_per_line = colors * params->pixels_per_line; } else if (params->depth <= 16) { params->bytes_per_line = 2 * colors * params->pixels_per_line; } params->last_frame = SANE_TRUE; } DBG(DBG_info_sane,"sane_get_parameters(): SANE parameters\n"); DBG(DBG_info_sane," format = %d\n",params->format); DBG(DBG_info_sane," last_frame = %d\n",params->last_frame); DBG(DBG_info_sane," bytes_per_line = %d\n",params->bytes_per_line); DBG(DBG_info_sane," pixels_per_line = %d\n",params->pixels_per_line); DBG(DBG_info_sane," lines = %d\n",params->lines); DBG(DBG_info_sane," depth = %d\n",params->depth); } else { DBG(DBG_info_sane," no params argument, no values returned\n"); } return SANE_STATUS_GOOD; } /** * Initiates aquisition of an image from the scanner. * SCAN Phase 1: initialization and calibration * (SCAN Phase 2: line-by-line scan & read is not implemented) * SCAN Phase 3: get CCD-mask * SCAN phase 4: scan slide and save data in scanner buffer * @param handle Scanner handle * @return */ SANE_Status sane_start (SANE_Handle handle) { struct Pieusb_Scanner *scanner = handle; struct Pieusb_Command_Status status; SANE_Byte colors; const char *mode; SANE_Bool shading_correction_relevant; SANE_Bool infrared_post_processing_relevant; SANE_Status st; SANE_Int bytes_per_line; SANE_Int shading_width; SANE_Int shading_idx; struct Pieusb_Exposure_Time exptime = { 0x93, /* code 0x93 */ 3 * 2 * sizeof(SANE_Int), /* number of bytes in rest of structure */ { { 0x02, 100 }, { 0x04, 100 }, { 0x08, 100 } } }; struct Pieusb_Highlight_Shadow shadow = { 0x94, /* code 0x94 */ 3 * 2 * sizeof(SANE_Int), /* number of bytes in rest of structure */ { { 0x02, 100 }, { 0x04, 100 }, { 0x08, 100 } } }; DBG (DBG_info_sane, "sane_start()\n"); /* ---------------------------------------------------------------------- * * Exit if currently scanning * * ---------------------------------------------------------------------- */ if (scanner->scanning) { DBG (DBG_error, "sane_start(): scanner is already scanning, exiting\n"); return SANE_STATUS_DEVICE_BUSY; } /* ---------------------------------------------------------------------- * * Exit with pause if not warmed up * * ---------------------------------------------------------------------- */ sanei_pieusb_cmd_read_state (scanner->device_number, &(scanner->state), &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { if (status.pieusb_status == PIEUSB_STATUS_DEVICE_BUSY) return SANE_STATUS_DEVICE_BUSY; /* was: SANE_STATUS_WARMING_UP */ DBG (DBG_error, "sane_start(): warmed up check returns status: %s\n", sane_strstatus (sanei_pieusb_convert_status(status.pieusb_status))); return SANE_STATUS_IO_ERROR; } if (scanner->state.warmingUp) { DBG (DBG_error, "sane_start(): warming up, exiting\n"); /* Seen SANE_STATUS_WARMING_UP in scanimage => enabled */ sleep (10); /* scanimage does not pause, so do it here */ return SANE_STATUS_DEVICE_BUSY; /* was: SANE_STATUS_WARMING_UP */ } /* ---------------------------------------------------------------------- * set exposure time * ---------------------------------------------------------------------- */ sanei_pieusb_cmd_set_exposure_time (scanner->device_number, &exptime, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_set_exposure_time failed: %d\n", status.pieusb_status); return SANE_STATUS_IO_ERROR; } /* ---------------------------------------------------------------------- * set highlight shadow * ---------------------------------------------------------------------- */ sanei_pieusb_cmd_set_highlight_shadow (scanner->device_number, &shadow, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_set_highlight_shadow failed: %d\n", status.pieusb_status); return SANE_STATUS_IO_ERROR; } /* ---------------------------------------------------------------------- * get calibration info * ---------------------------------------------------------------------- */ sanei_pieusb_cmd_get_shading_parms (scanner->device_number, scanner->device->shading_parameters, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { DBG (DBG_error, "sane_scan: sanei_pieusb_cmd_get_shading_parms failed: %d\n", status.pieusb_status); return SANE_STATUS_INVAL; } shading_width = scanner->device->shading_parameters[0].pixelsPerLine; DBG (DBG_info, "shading_width %d\n", shading_width); for (shading_idx = 0; shading_idx < SHADING_PARAMETERS_INFO_COUNT; shading_idx++) { scanner->shading_ref[shading_idx] = realloc(scanner->shading_ref[shading_idx], 2 * shading_width * sizeof(SANE_Int)); if (scanner->shading_ref[shading_idx] == NULL) { return SANE_STATUS_NO_MEM; } } scanner->ccd_mask = realloc (scanner->ccd_mask, shading_width); scanner->ccd_mask_size = shading_width; if (scanner->ccd_mask == NULL) { return SANE_STATUS_NO_MEM; } /* ---------------------------------------------------------------------- * * Standard run does; * - set exposure time 0x0A/0x13 * - set highlight shadow 0x0A/0x14 * - read shading parameters 0x0A/0x95/0x08 * - set scan frame 0x0A/0x12 * "12 00 0a00 80 00 0300 0000 b829 e31a" * => 0:12 1:0 2:10 4:80 5:0 6:3 8:0 10:10680 12:6883 * - read gain offset 0xD7 * - set gain offset 0xDC * - set mode 0x15 * "00 0f 2c01 80 04 04 00 01 0a 00 00 00 80 10 00" * size res pass dpt frm ord bitmap ptn thr * 15 300 RGB 8 inx intel 1=sharpen 0 128 * 3=skipshad * * ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- * * Show and check options * * ---------------------------------------------------------------------- */ sanei_pieusb_print_options (scanner); if (!sanei_pieusb_analyse_options (scanner)) { return SANE_STATUS_IO_ERROR; } /* ---------------------------------------------------------------------- * * Set scan frame * * ---------------------------------------------------------------------- */ if (sanei_pieusb_set_frame_from_options (scanner) != SANE_STATUS_GOOD) { return SANE_STATUS_IO_ERROR; } /* ---------------------------------------------------------------------- * * Function 17 * * ---------------------------------------------------------------------- */ if (scanner->device->flags & FLAG_SLIDE_TRANSPORT) { sanei_pieusb_cmd_17 (scanner->device_number, 1, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_17 failed: %d\n", status.pieusb_status); return SANE_STATUS_IO_ERROR; } st = sanei_pieusb_wait_ready (scanner, 0); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start(): scanner not ready after sanei_pieusb_cmd_17: %d\n", st); return st; } } /* ---------------------------------------------------------------------- * * Get & set initial gains and offsets * * There does not seem to be much reason to set exposure/gain/offset * now, but it does make a large difference in speed, because it * creates a small BADF-table. This is probably because without SET GAIN * OFFSET, extraEntries has a random value (it is not initialised). * * TODO: test if this may be done just once, in sane_open(). * * ---------------------------------------------------------------------- */ if (sanei_pieusb_set_gain_offset (scanner, scanner->val[OPT_CALIBRATION_MODE].s) != SANE_STATUS_GOOD) { return SANE_STATUS_IO_ERROR; } st = sanei_pieusb_wait_ready (scanner, 0); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: scanner not ready %d\n", st); return st; } /* ---------------------------------------------------------------------- * * Set mode * * ---------------------------------------------------------------------- */ if (sanei_pieusb_set_mode_from_options (scanner) != SANE_STATUS_GOOD) { return SANE_STATUS_IO_ERROR; } /* ---------------------------------------------------------------------- * * Init slide transport * * ---------------------------------------------------------------------- */ if (scanner->device->flags & FLAG_SLIDE_TRANSPORT) { sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_INIT, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_slide failed: %d\n", status.pieusb_status); return SANE_STATUS_IO_ERROR; } st = sanei_pieusb_wait_ready (scanner, 0); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: scanner not ready %d\n", st); return st; } } /* Enter SCAN phase 1 */ DBG (DBG_info_sane, "sane_start(): scan phase 1\n"); /* ---------------------------------------------------------------------- * * Start scan & wait until device ready * * ---------------------------------------------------------------------- */ scanner->scanning = SANE_TRUE; scanner->cancel_request = SANE_FALSE; for (;;) { sanei_pieusb_cmd_start_scan (scanner->device_number, &status); if (status.pieusb_status != PIEUSB_STATUS_WARMING_UP) break; sleep(5); } sanei_pieusb_wait_ready (scanner, 0); if ((status.pieusb_status == PIEUSB_STATUS_MUST_CALIBRATE) || (scanner->val[OPT_SHADING_ANALYSIS].b != 0)) { /* Overriding skip calibration */ DBG (DBG_info_sane, "sane_start(): process shading data\n"); /* ------------------------------------------------------------------ * * Get and set gain and offset * Get settings from scanner, from preview data, from options, * or use defaults. * * ------------------------------------------------------------------ */ if (sanei_pieusb_set_gain_offset (scanner, scanner->val[OPT_CALIBRATION_MODE].s) != SANE_STATUS_GOOD) { sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); scanner->scanning = SANE_FALSE; return SANE_STATUS_IO_ERROR; } /* ------------------------------------------------------------------ * * Obtain shading data * Get parameters from scanner->device->shading_parameters[0] although * it's 45 lines, scanner->ccd_mask_size pixels, 16 bit depth in all cases. * * ------------------------------------------------------------------ */ if (sanei_pieusb_get_shading_data (scanner) != SANE_STATUS_GOOD) { sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); scanner->scanning = SANE_FALSE; return SANE_STATUS_IO_ERROR; } } /* Enter SCAN phase 2 */ DBG (DBG_info_sane, "sane_start(): scan phase 2\n"); /* SCAN phase 2 (line-by-line scan) not implemented */ st = sanei_pieusb_wait_ready (scanner, 0); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: scanner not ready %d\n", st); return st; } /* Enter SCAN phase 3 */ DBG (DBG_info_sane, "sane_start(): scan phase 3\n"); /* Handle cancel request */ if (scanner->cancel_request) { return sanei_pieusb_on_cancel (scanner); } /* ---------------------------------------------------------------------- * * Get CCD mask * * ---------------------------------------------------------------------- */ if (sanei_pieusb_get_ccd_mask (scanner) != SANE_STATUS_GOOD) { sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); scanner->scanning = SANE_FALSE; return SANE_STATUS_IO_ERROR; } /* Enter SCAN phase 4 */ /* ---------------------------------------------------------------------- * * Read scan parameters & wait until ready for reading * * ---------------------------------------------------------------------- */ if (sanei_pieusb_get_parameters (scanner, &bytes_per_line) != SANE_STATUS_GOOD) { sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); scanner->scanning = SANE_FALSE; return SANE_STATUS_IO_ERROR; } st = sanei_pieusb_wait_ready (scanner, 0); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: scanner not ready %d\n", st); return st; } /* ---------------------------------------------------------------------- * * Prepare read buffer * Currently this buffer is always a memory mapped buffer * Might be faster to use RAM buffers for small images (such as preview) * * ---------------------------------------------------------------------- */ colors = 0x00; switch (scanner->mode.passes) { case SCAN_FILTER_RED: colors = 0x01; break; case SCAN_FILTER_GREEN: colors = 0x02; break; case SCAN_FILTER_BLUE: colors = 0x04; break; case SCAN_FILTER_INFRARED: colors = 0x08; break; case SCAN_ONE_PASS_COLOR: colors = 0x07; break; case SCAN_ONE_PASS_RGBI: colors = 0x0F; break; } if (scanner->buffer.data) sanei_pieusb_buffer_delete(&scanner->buffer); /* free resources from previous invocation */ st = sanei_pieusb_buffer_create (&(scanner->buffer), scanner->scan_parameters.pixels_per_line, scanner->scan_parameters.lines, colors, scanner->scan_parameters.depth); if (st != SANE_STATUS_GOOD) { scanner->scanning = SANE_FALSE; return st; } /* ---------------------------------------------------------------------- * * Read all image data into the buffer * * ---------------------------------------------------------------------- */ if (sanei_pieusb_get_scan_data (scanner, bytes_per_line) != SANE_STATUS_GOOD) { scanner->scanning = SANE_FALSE; return SANE_STATUS_IO_ERROR; } sleep(2); st = sanei_pieusb_wait_ready (scanner, 0); if (st != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start(): scanner not ready after sanei_pieusb_get_scan_data: %d\n", st); scanner->scanning = SANE_FALSE; return st; } /* ---------------------------------------------------------------------- * * Advance to next slide (except for preview) * * ---------------------------------------------------------------------- */ if (scanner->device->flags & FLAG_SLIDE_TRANSPORT) { if (scanner->val[OPT_ADVANCE_SLIDE].b && !scanner->val[OPT_PREVIEW].b) { sanei_pieusb_cmd_slide (scanner->device_number, SLIDE_NEXT, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { DBG (DBG_error, "sane_start(): sanei_pieusb_cmd_slide failed: %d\n", status.pieusb_status); } } } /* ---------------------------------------------------------------------- * * Post processing: * 1. Correct for shading * 2. Remove R-component from IR data * 3. Remove dust * * ---------------------------------------------------------------------- */ mode = scanner->val[OPT_MODE].s; if (strcmp(mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) { shading_correction_relevant = SANE_FALSE; /* Shading correction irrelavant at bit depth 1 */ infrared_post_processing_relevant = SANE_FALSE; /* No infrared, no postprocessing */ } else if (strcmp(mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { shading_correction_relevant = SANE_FALSE; /* Shading correction irrelavant at bit depth 1 */ infrared_post_processing_relevant = SANE_FALSE; /* No infrared, no postprocessing */ } else if (strcmp(mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { shading_correction_relevant = SANE_TRUE; infrared_post_processing_relevant = SANE_FALSE; /* No infrared, no postprocessing */ } else if (scanner->val[OPT_PREVIEW].b) { /* Catch preview here, otherwise next ifs get complicated */ shading_correction_relevant = SANE_TRUE; infrared_post_processing_relevant = SANE_FALSE; } else if (strcmp(mode, SANE_VALUE_SCAN_MODE_RGBI) == 0) { shading_correction_relevant = SANE_TRUE; infrared_post_processing_relevant = SANE_TRUE; } else if (strcmp(mode, SANE_VALUE_SCAN_MODE_COLOR) == 0 && scanner->val[OPT_CLEAN_IMAGE].b) { shading_correction_relevant = SANE_TRUE; infrared_post_processing_relevant = SANE_TRUE; } else { /* SANE_VALUE_SCAN_MODE_COLOR */ shading_correction_relevant = SANE_TRUE; infrared_post_processing_relevant = SANE_TRUE; } if (scanner->val[OPT_CORRECT_SHADING].b && shading_correction_relevant) { if (scanner->shading_data_present) { sanei_pieusb_correct_shading (scanner, &scanner->buffer); } else { DBG(DBG_warning, "sane_start(): unable to correct for shading, no shading data available\n"); } } if ((scanner->val[OPT_CORRECT_INFRARED].b || scanner->val[OPT_CLEAN_IMAGE].b) && !scanner->val[OPT_PREVIEW].b && infrared_post_processing_relevant) { /* Create array of pointers to color planes R, G, B, I */ SANE_Uint *planes[PLANES]; SANE_Int N; N = scanner->buffer.width * scanner->buffer.height; planes[0] = scanner->buffer.data; planes[1] = scanner->buffer.data + N; planes[2] = scanner->buffer.data + 2 * N; planes[3] = scanner->buffer.data + 3 * N; sanei_ir_init (); sanei_pieusb_post (scanner, planes, scanner->buffer.colors); } /* Save preview data. Preview data only used once to set gain and offset. */ if (scanner->val[OPT_PREVIEW].b) { sanei_pieusb_analyze_preview(scanner); } else { scanner->preview_done = SANE_FALSE; } /* Modify buffer in case the buffer has infrared, but no infrared should be returned */ if (scanner->buffer.colors == PLANES && (strcmp(mode,SANE_VALUE_SCAN_MODE_COLOR) == 0 && scanner->val[OPT_CLEAN_IMAGE].b)) { DBG(DBG_info_sane, "sane_start(): modifying buffer to ignore I\n"); /* Base buffer parameters */ scanner->buffer.colors = 3; /* Derived quantities */ scanner->buffer.image_size_bytes = scanner->buffer.colors * scanner->buffer.height * scanner->buffer.line_size_bytes; scanner->buffer.color_index_infrared = -1; scanner->buffer.bytes_unread = scanner->buffer.bytes_unread * 3 / 4; scanner->buffer.bytes_written = scanner->buffer.bytes_written * 3 / 4; } return SANE_STATUS_GOOD; } /** * Read image data from the scanner buffer. * * @param handle * @param buf * @param max_len * @param len * @return */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct Pieusb_Scanner *scanner = handle; SANE_Int return_size; DBG(DBG_info_sane, "sane_read(): requested %d bytes\n", max_len); /* No reading if not scanning */ if (!scanner->scanning) { *len = 0; return SANE_STATUS_IO_ERROR; /* SANE standard does not allow a SANE_STATUS_INVAL return */ } /* Handle cancel request */ if (scanner->cancel_request) { return sanei_pieusb_on_cancel(scanner); } #if 0 /* Return image data, just read from scanner buffer */ DBG(DBG_info_sane, "sane_read():\n"); DBG(DBG_info_sane, " image size %d\n", scanner->buffer.image_size_bytes); DBG(DBG_info_sane, " unread %d\n", scanner->buffer.bytes_unread); DBG(DBG_info_sane, " read %d\n", scanner->buffer.bytes_read); DBG(DBG_info_sane, " max_len %d\n", max_len); #endif if (scanner->buffer.bytes_read > scanner->buffer.image_size_bytes) { /* Test if not reading past buffer boundaries */ DBG(DBG_error, "sane_read(): reading past buffer boundaries (contains %d, read %d)\n", scanner->buffer.image_size_bytes, scanner->buffer.bytes_read); *len = 0; sanei_pieusb_on_cancel(scanner); return SANE_STATUS_EOF; } else if (scanner->buffer.bytes_read == scanner->buffer.image_size_bytes) { /* Return EOF since all data of this frame has already been read. */ *len = 0; scanner->scanning = SANE_FALSE; return SANE_STATUS_EOF; } else if (scanner->buffer.bytes_unread >= max_len) { /* Already enough data to return, do not read */ DBG(DBG_info_sane, "sane_read(): buffer suffices (contains %d, requested %d)\n", scanner->buffer.bytes_unread, max_len); return_size = max_len; } else if (scanner->buffer.bytes_read + scanner->buffer.bytes_unread == scanner->buffer.image_size_bytes) { /* All the remaining data is in the buffer, do not read */ DBG(DBG_info_sane, "sane_read(): buffer suffices (contains %d, requested %d, last batch though)\n", scanner->buffer.bytes_unread, max_len); return_size = scanner->buffer.bytes_unread; } else { /* Should not happen in this implementation - all data read by sane_start() */ DBG(DBG_error, "sane_read(): shouldn't be here...\n"); return SANE_STATUS_IO_ERROR; } /* Check */ if (return_size == 0 && scanner->buffer.bytes_read < scanner->buffer.image_size_bytes) { DBG(DBG_error, "sane_read(): unable to service read request, %d bytes in frame, %d read\n", scanner->buffer.image_size_bytes, scanner->buffer.bytes_read); } /* Return the available data: Output return_size bytes from buffer */ sanei_pieusb_buffer_get(&scanner->buffer, buf, max_len, len); #if 0 DBG(DBG_info_sane, "sane_read(): currently read %.2f lines of %d\n", (double)scanner->buffer.bytes_written/(scanner->buffer.line_size_bytes*scanner->buffer.colors), scanner->buffer.height); DBG(DBG_info_sane, "sane_read(): returning %d bytes (requested %d), returned %d of %d \n", *len, max_len,scanner->buffer.bytes_read, scanner->buffer.image_size_bytes); #endif return SANE_STATUS_GOOD; } /** * Request cancellation of current scanning process. * * @param handle Scanner handle */ void sane_cancel (SANE_Handle handle) { struct Pieusb_Scanner *scanner = handle; DBG (DBG_info_sane, "sane_cancel\n"); if (scanner->scanning) { scanner->cancel_request = 1; } } /** * Set the I/O mode of handle h. The I/O mode can be either blocking or * non-blocking, but for USB devices, only blocking mode is supported. * * @param handle Scanner handle * @param non_blocking * @return SANE_STATUS_UNSUPPORTED; */ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { /* Pieusb_Scanner *scanner = handle; */ DBG (DBG_info_sane, "sane_set_io_mode: handle = %p, non_blocking = %s\n", handle, non_blocking == SANE_TRUE ? "true" : "false"); if (non_blocking) { return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; } /** * Obtain a file-descriptor for the scanner that is readable if image data is * available. The select file-descriptor is returned in *fd. * The function has not been implemented since USB-device only operate in * blocking mode. * * @param handle Scanner handle * @param fd File descriptor with imae data * @return SANE_STATUS_INVAL */ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG(DBG_info_sane,"sane_get_select_fd(): not supported (only for non-blocking IO)\n"); handle = handle; fd = fd; return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/hp5400.h0000664000175000017500000001160312112021330013664 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Martijn van Oosterhout Copyright (C) 2003 Thomas Soumarmon Originally copied from HP3300 testtools. Original notice follows: Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. $Id$ */ /* Core HP5400 functions. */ #ifndef _HP5400_H_ #define _HP5400_H_ #include #include "hp5400_xfer.h" /* for EScannerModel */ #define HW_DPI 300 /* horizontal resolution of hardware */ #define HW_LPI 300 /* vertical resolution of hardware */ enum ScanType { SCAN_TYPE_CALIBRATION, SCAN_TYPE_PREVIEW, SCAN_TYPE_NORMAL }; /* In case we ever need to track multiple models */ typedef struct { char *pszVendor; char *pszName; } TScannerModel; typedef struct { /* transfer buffer */ void *buffer; /* Pointer to memory allocated for buffer */ int roff, goff, boff; /* Offset into buffer of rows to be copied *next* */ int bufstart, bufend; /* What is currently the valid buffer */ int bpp; /* Bytes per pixel per colour (1 or 2) */ int linelength, pixels; /* Bytes per line from scanner */ int transfersize; /* Number of bytes to transfer resulting image */ int blksize; /* Size of blocks to pull from scanner */ int buffersize; /* Size of the buffer */ } TDataPipe; typedef struct { int iXferHandle; /* handle used for data transfer to HW */ TDataPipe pipe; /* Pipe for data */ int iTopLeftX; /* in mm */ int iTopLeftY; /* in mm */ /* int iSensorSkew; *//* in units of 1/1200 inch */ /* int iSkipLines; *//* lines of garbage to skip */ /* int fReg07; *//* NIASH00019 */ /* int fGamma16; *//* if TRUE, gamma entries are 16 bit */ /* int iExpTime; */ /* int iReversedHead; *//* Head is reversed */ /* int iBufferSize; *//* Size of internal scan buffer */ /* EScannerModel eModel; */ } THWParams; /* The scanner needs a Base DPI off which all it's calibration and * offset/size parameters are based. For the time being this is the same as * the iDpi but maybe we want it seperate. This is because while this field * would have limited values (300,600,1200,2400) the x/y dpi can vary. The * windows interface seems to allow 200dpi (though I've never tried it). We * need to decide how these values are related to the HW coordinates. */ typedef struct { int iDpi; /* horizontal resolution */ int iLpi; /* vertical resolution */ int iTop; /* in HW coordinates (units HW_LPI) */ int iLeft; /* in HW coordinates (units HW_LPI) */ int iWidth; /* in HW coordinates (units HW_LPI) */ int iHeight; /* in HW coordinates (units HW_LPI) */ int iBytesPerLine; /* Resulting bytes per line */ int iLines; /* Resulting lines of image */ int iLinesRead; /* Lines of image already read */ int iColourOffset; /* How far the colours are offset. Currently this is * set by the caller. This doesn't seem to be * necessary anymore since the scanner is doing it * internally. Leave it for the time being as it * may be needed later. */ } TScanParams; #endif /* NO _HP5400_H_ */ sane-backends-1.0.27/backend/kvs1025_cmds.h0000664000175000017500000000407012112021330015065 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. */ /* sane - Scanner Access Now Easy. Panasonic KV-S1020C / KV-S1025C USB scanners. */ #ifndef KVS1025_CMDS_H #define KVS1025_CMDS_H /* Commands supported by the KV-S1020C / KV-S1025C scanner. */ #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_INQUIRY 0x12 #define SCSI_SET_WINDOW 0x24 #define SCSI_SCAN 0x1B #define SCSI_SEND_10 0x2A #define SCSI_READ_10 0x28 #define SCSI_REQUEST_SENSE 0x03 #define SCSI_GET_BUFFER_STATUS 0x34 #define SCSI_SET_TIMEOUT 0xE1 typedef enum { KV_CMD_NONE = 0, KV_CMD_IN = 0x81, /* scanner to pc */ KV_CMD_OUT = 0x02 /* pc to scanner */ } KV_CMD_DIRECTION; /* equals to endpoint address */ typedef struct { KV_CMD_DIRECTION direction; unsigned char cdb[12]; int cdb_size; int data_size; void *data; } KV_CMD_HEADER, *PKV_CMD_HEADER; #define KV_CMD_TIMEOUT 10000 static inline int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) typedef enum { KV_SUCCESS = 0, KV_FAILED = 1, KV_CHK_CONDITION = 2 } KV_STATUS; typedef struct { KV_STATUS status; unsigned char reserved[16]; unsigned char sense[18]; } KV_CMD_RESPONSE, *PKV_CMD_RESPONSE; #endif /*#ifndef KVS1025_CMDS_H */ sane-backends-1.0.27/backend/mustek_pp_null.c0000664000175000017500000001001512112021330015774 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2003 Jochen Eisinger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek PP flatbed scanners. */ #include "../include/sane/config.h" #if defined(HAVE_STDLIB_H) # include #endif #include #include #if defined(HAVE_STRING_H) # include #elif defined(HAVE_STRINGS_H) # include #endif #define DEBUG_DECLARE_ONLY #include "mustek_pp.h" #include "mustek_pp_decl.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #define MUSTEK_PP_NULL_DRIVER 0 static SANE_Status debug_drv_init(SANE_Int options, SANE_String_Const port, SANE_String_Const name, SANE_Attach_Callback attach) { if (options != CAP_NOTHING) return SANE_STATUS_INVAL; return attach(port, name, MUSTEK_PP_NULL_DRIVER, 0); } /*ARGSUSED*/ static void debug_drv_capabilities(SANE_Int info __UNUSED__, SANE_String *model, SANE_String *vendor, SANE_String *type, SANE_Int *maxres, SANE_Int *minres, SANE_Int *maxhsize, SANE_Int *maxvsize, SANE_Int *caps) { *model = strdup("debugger"); *vendor = strdup("mustek_pp"); *type = strdup("software emulated"); *maxres = 300; *minres = 50; *maxhsize = 1000; *maxvsize = 3000; *caps = CAP_NOTHING; } /*ARGSUSED*/ static SANE_Status debug_drv_open (SANE_String port __UNUSED__, SANE_Int caps __UNUSED__, SANE_Int *fd) { *fd = 1; return SANE_STATUS_GOOD; } static void debug_drv_setup (SANE_Handle hndl) { Mustek_pp_Handle *dev = hndl; dev->lamp_on = 0; dev->priv = NULL; } /*ARGSUSED*/ static SANE_Status debug_drv_config(SANE_Handle hndl __UNUSED__, SANE_String_Const optname, SANE_String_Const optval) { DBG (3, "debug_drv cfg option: %s=%s\n", optname, optval ? optval : ""); return SANE_STATUS_GOOD; } /*ARGSUSED*/ static void debug_drv_close (SANE_Handle hndl __UNUSED__) { } /*ARGSUSED*/ static SANE_Status debug_drv_start (SANE_Handle hndl __UNUSED__) { return SANE_STATUS_GOOD; } static void debug_drv_read (SANE_Handle hndl, SANE_Byte *buffer) { Mustek_pp_Handle *dev = hndl; memset (buffer, 0, dev->params.bytes_per_line); } /*ARGSUSED*/ static void debug_drv_stop (SANE_Handle hndl __UNUSED__) { } sane-backends-1.0.27/backend/epson_scsi.h0000664000175000017500000000130012112021330015102 00000000000000#ifndef _EPSON_SCSI_H_ #define _EPSON_SCSI_H_ #include #include "../include/sane/sane.h" #define TEST_UNIT_READY_COMMAND (0x00) #define READ_6_COMMAND (0x08) #define WRITE_6_COMMAND (0x0a) #define INQUIRY_COMMAND (0x12) #define TYPE_PROCESSOR (0x03) #define INQUIRY_BUF_SIZE (36) SANE_Status sanei_epson_scsi_sense_handler (int scsi_fd, u_char * result, void *arg); SANE_Status sanei_epson_scsi_inquiry (int fd, int page_code, void *buf, size_t * buf_size); int sanei_epson_scsi_read (int fd, void *buf, size_t buf_size, SANE_Status * status); int sanei_epson_scsi_write (int fd, const void *buf, size_t buf_size, SANE_Status * status); #endif sane-backends-1.0.27/backend/sm3600-gray.c0000664000175000017500000003477012112021330014641 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) Marian Eichholz 2001 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ====================================================================== Userspace scan tool for the Microtek 3600 scanner grayscale scan routine (C) Marian Eichholz 2001 ====================================================================== */ #include "sm3600-scantool.h" /* ********************************************************************** DoScanGray() ********************************************************************** */ #define LINE_THRESHOLD 0x800 static unsigned char uchRegs075[]={ /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x20, /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06, /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x3F, /*R_LEN*/ 0x28, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D, /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0, /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x40, /*0x13*/ 0x15, /*0x14*/ 0x80, /*0x15*/ 0x2A, /*0x16*/ 0xC0, /*0x17*/ 0x40, /*0x18*/ 0xC0, /*0x19*/ 0x40, /*0x1A*/ 0xFF, /*0x1B*/ 0x01, /*0x1C*/ 0x88, /*0x1D*/ 0x40, /*0x1E*/ 0x4C, /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C, /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40, /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0, /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E, /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00, /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80, /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20, /*0x34*/ 0x83, /*0x35*/ 0x29, /*0x36*/ 0x00, /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00, /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF, /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00, /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x00, /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00, /*R_CTL*/ 0x39, /*0x47*/ 0xC0, /*0x48*/ 0x40, /*0x49*/ 0x9E, /*0x4A*/ 0x8C }; static unsigned char uchRegs100[]={ /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x20, /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06, /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x3F, /*R_LEN*/ 0x34, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D, /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0, /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x42, /*0x13*/ 0x15, /*0x14*/ 0x84, /*0x15*/ 0x2A, /*0x16*/ 0xC2, /*0x17*/ 0x40, /*0x18*/ 0xC2, /*0x19*/ 0x40, /*0x1A*/ 0xFF, /*0x1B*/ 0x01, /*0x1C*/ 0x88, /*0x1D*/ 0x40, /*0x1E*/ 0x4C, /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C, /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40, /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0, /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E, /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00, /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80, /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20, /*0x34*/ 0x63, /*0x35*/ 0x29, /*0x36*/ 0x00, /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00, /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF, /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00, /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x80, /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00, /*R_CTL*/ 0x39, /*0x47*/ 0xC2, /*0x48*/ 0x40, /*0x49*/ 0x9E, /*0x4A*/ 0x8C }; static unsigned char uchRegs200[]={ /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x24, /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06, /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x3F, /*R_LEN*/ 0x22, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D, /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0, /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x42, /*0x13*/ 0x15, /*0x14*/ 0x42, /*0x15*/ 0x15, /*0x16*/ 0x42, /*0x17*/ 0x15, /*0x18*/ 0x42, /*0x19*/ 0x15, /*0x1A*/ 0x07, /*0x1B*/ 0x00, /*0x1C*/ 0x08, /*0x1D*/ 0x12, /*0x1E*/ 0x4C, /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C, /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40, /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0, /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E, /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00, /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80, /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20, /*0x34*/ 0x43, /*0x35*/ 0x29, /*0x36*/ 0x00, /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00, /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF, /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00, /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x80, /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00, /*R_CTL*/ 0x39, /*0x47*/ 0x42, /*0x48*/ 0x15, /*0x49*/ 0x9E, /*0x4A*/ 0x8C }; static unsigned char uchRegs300[]={ /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x2A, /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06, /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x2A, /*R_LEN*/ 0x16, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D, /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0, /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x40, /*0x13*/ 0x15, /*0x14*/ 0x40, /*0x15*/ 0x15, /*0x16*/ 0x40, /*0x17*/ 0x15, /*0x18*/ 0x40, /*0x19*/ 0x15, /*0x1A*/ 0x07, /*0x1B*/ 0x00, /*0x1C*/ 0x08, /*0x1D*/ 0x12, /*0x1E*/ 0x4C, /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C, /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40, /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0, /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E, /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00, /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80, /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20, /*0x34*/ 0x03, /*0x35*/ 0x29, /*0x36*/ 0x00, /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00, /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF, /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00, /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x80, /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00, /*R_CTL*/ 0x39, /*0x47*/ 0x40, /*0x48*/ 0x15, /*0x49*/ 0x96, /*0x4A*/ 0x8C }; static unsigned char uchRegs600[]={ /*R_SPOS*/ 0xFC, /*R_SPOSH*/ 0x00, /*0x03*/ 0x3F, /*R_SWID*/ 0xB0, /*R_SWIDH*/ 0x04, /*R_STPS*/ 0x06, /*R_STPSH*/ 0x00, /*0x08*/ 0x00, /*0x09*/ 0x3F, /*R_LEN*/ 0x16, /*R_LENH*/ 0x07, /*0x0C*/ 0x6D, /*0x0D*/ 0x70, /*0x0E*/ 0x69, /*0x0F*/ 0xD0, /*0x10*/ 0x00, /*0x11*/ 0x00, /*0x12*/ 0x42, /*0x13*/ 0x15, /*0x14*/ 0x42, /*0x15*/ 0x15, /*0x16*/ 0x42, /*0x17*/ 0x15, /*0x18*/ 0x42, /*0x19*/ 0x15, /*0x1A*/ 0x07, /*0x1B*/ 0x00, /*0x1C*/ 0x08, /*0x1D*/ 0x12, /*0x1E*/ 0x4C, /*0x1F*/ 0x50, /*0x20*/ 0x00, /*0x21*/ 0x0C, /*0x22*/ 0x21, /*0x23*/ 0xF0, /*0x24*/ 0x40, /*0x25*/ 0x00, /*0x26*/ 0x0A, /*0x27*/ 0xF0, /*0x28*/ 0x00, /*0x29*/ 0x00, /*0x2A*/ 0x4E, /*0x2B*/ 0xF0, /*0x2C*/ 0x00, /*0x2D*/ 0x00, /*0x2E*/ 0x4E, /*R_CCAL*/ 0x80, /*R_CCAL2*/ 0x80, /*R_CCAL3*/ 0x80, /*0x32*/ 0xC9, /*0x33*/ 0x20, /*0x34*/ 0x03, /*0x35*/ 0x29, /*0x36*/ 0x00, /*0x37*/ 0x00, /*0x38*/ 0x00, /*0x39*/ 0x00, /*0x3A*/ 0x00, /*0x3B*/ 0x00, /*0x3C*/ 0xFF, /*0x3D*/ 0x0F, /*0x3E*/ 0x00, /*0x3F*/ 0x00, /*0x40*/ 0x01, /*0x41*/ 0x00, /*R_CSTAT*/ 0x80, /*0x43*/ 0x03, /*R_LMP*/ 0x01, /*0x45*/ 0x00, /*R_CTL*/ 0x39, /*0x47*/ 0x42, /*0x48*/ 0x15, /*0x49*/ 0x96, /*0x4A*/ 0x8C }; /* ====================================================================== ReadNextGrayLine() ====================================================================== */ static TState ReadNextGrayLine(PTInstance this) { int iWrite; int iDot; unsigned char chBits; int iRead; /* read position in raw line */ int nInterpolator; iWrite=0; while (iWritestate.cxMax) /* max 1 time in reality */ { while (iWritestate.cxMax && this->state.iBulkReadPosstate.cchBulk) this->state.ppchLines[0][iWrite++] += /* add! */ this->state.pchBuf[this->state.iBulkReadPos++]<<4; if (iWritestate.cxMax) /* we need an additional chunk */ { if (this->state.bLastBulk) return SANE_STATUS_EOF; this->state.cchBulk=BulkReadBuffer(this,this->state.pchBuf, USB_CHUNK_SIZE); dprintf(DEBUG_SCAN,"bulk read: %d byte(s), line #%d\n", this->state.cchBulk, this->state.iLine); if (this->bWriteRaw) fwrite(this->state.pchBuf,1,this->state.cchBulk,this->fhScan); INST_ASSERT(); if (this->state.cchBulk!=USB_CHUNK_SIZE) this->state.bLastBulk=true; this->state.iBulkReadPos=0; } } /* while raw line buffer acquiring */ this->state.iLine++; iDot=0; chBits=0; /* init pixelbuffer */ for (nInterpolator=50, iWrite=0, iRead=0; iReadstate.cxMax; iRead++) { nInterpolator+=this->state.nFixAspect; if (nInterpolator<100) continue; /* res. reduction */ nInterpolator-=100; if (iWrite>=this->state.cchLineOut) continue; /* dprintf(DEBUG_SCAN," i=%d",iTo); */ if (this->mode==gray) this->state.pchLineOut[iWrite++]= this->state.ppchLines[0][iRead]>>4; else { unsigned char chBit; /* 1=white */ if (this->mode==line) chBit=(this->state.ppchLines[0][iRead]state.ppchLines[0][iRead]; /* printf("(%d)",nError); */ if (nError>=0xFF0) { nError-=0xFF0; chBit=0; } else chBit=1; /* since I sketched the Floyd-Steinberg algorithm from heart, I have no idea, if there is room for improvement in the coefficients. If You know, please drop me a line (eichholz@computer.org, 1.4.2001) */ #define FASTDITHER #ifdef FASTDITHER this->state.ppchLines[0][iRead+1]+=(nError>>2); /* 8/16 */ this->state.ppchLines[1][iRead+1]+=(nError>>1); this->state.ppchLines[1][iRead] +=(nError>>2); /* 8/16 */ #else this->state.ppchLines[0][iRead+1]+=(nError*5)>>4; this->state.ppchLines[1][iRead+1]+=(nError*8)>>4; this->state.ppchLines[1][iRead] +=(nError*3)>>4; #endif } chBits=(chBits<<1)|chBit; iDot++; if (iDot==8 && iWritestate.cchLineOut) { this->state.pchLineOut[iWrite++]=chBits; iDot=0; chBits=0; } } /* gray pixel postprocessing */ } /* line postprocessing */ if (iDot && iWritestate.cchLineOut) this->state.pchLineOut[iWrite++]=chBits; /* cycle the history lines and clear the preread buffer*/ { short *p=this->state.ppchLines[0]; this->state.ppchLines[0]=this->state.ppchLines[1]; this->state.ppchLines[1]=p; memset(this->state.ppchLines[1],0,(this->state.cxMax+1)*sizeof(short)); } return SANE_STATUS_GOOD; } /* ====================================================================== StartScanGray() ====================================================================== */ __SM3600EXPORT__ TState StartScanGray(TInstance *this) { unsigned char *puchRegs; int i; if (this->state.bScanning) return SetError(this,SANE_STATUS_DEVICE_BUSY,"scan active"); memset(&(this->state),0,sizeof(TScanState)); this->state.ReadProc =ReadNextGrayLine; puchRegs=NULL; switch (this->param.res) { case 75: puchRegs=uchRegs075; break; case 100: puchRegs=uchRegs100; break; case 200: puchRegs=uchRegs200; break; case 300: puchRegs=uchRegs300; break; case 600: puchRegs=uchRegs600; break; } GetAreaSize(this); this->state.cyTotalPath = this->param.y/2; DoJog(this,this->state.cyTotalPath); INST_ASSERT(); this->state.cyTotalPath += this->param.cy/2; /* for jogging back */ /* regular scan is asynchronously, that is, the scanning is issued, and the driver does bulk reads, until there are no data left. */ RegWriteArray(this,R_ALL, NUM_SCANREGS, puchRegs); INST_ASSERT(); RegWrite(this,R_SPOS, 2, this->param.x/2+this->calibration.xMargin); INST_ASSERT(); RegWrite(this,R_SLEN, 2, this->state.cyWindow); INST_ASSERT(); RegWrite(this,R_SWID, 2, this->state.cxWindow); INST_ASSERT(); RegWrite(this,R_STPS, 2, 0); INST_ASSERT(); /* upload gamma table */ RegWrite(this,0x41,1,0x01); /* gamma, gray */ RegWrite(this,0x40,1,0x20); /* FIFO at 0x08000 */ UploadGammaTable(this,0,this->agammaY); INST_ASSERT(); UploadGainCorrection(this, 0x2000); INST_ASSERT(); /* for halftone dithering we need one history line */ this->state.pchBuf=malloc(USB_CHUNK_SIZE); this->state.cBacklog=2; this->state.ppchLines=calloc(this->state.cBacklog,sizeof(short *)); if (!this->state.pchBuf || !this->state.ppchLines) return FreeState(this,SetError(this, SANE_STATUS_NO_MEM,"no buffers available")); for (i=0; istate.cBacklog; i++) { this->state.ppchLines[i]=calloc(this->state.cxMax+1, sizeof(short)); /* 1 dummy at right edge */ if (!this->state.ppchLines[i]) return FreeState(this,SetError(this, SANE_STATUS_NO_MEM,"no buffers available")); } /* calculate and prepare intermediate line transfer buffer */ this->state.cchLineOut=(this->mode==gray) ? this->state.cxPixel : (this->state.cxPixel+7)/8; this->state.pchLineOut = malloc(this->state.cchLineOut); if (!this->state.pchLineOut) return FreeState(this,SetError(this, SANE_STATUS_NO_MEM, "no buffers available")); /* start the unit, when all buffers are available */ RegWrite(this,R_CTL, 1, 0x39); INST_ASSERT(); RegWrite(this,R_CTL, 1, 0x79); INST_ASSERT(); RegWrite(this,R_CTL, 1, 0xF9); INST_ASSERT(); this->state.bScanning = true; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/snapscan-usb.h0000664000175000017500000001047112112021330015343 00000000000000/* Snapscan 1212U modifications for the Snapscan SANE backend Copyright (C) 2000 Henrik Johansson Henrik Johansson (henrikjo@post.urfors.se) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements USB equivalents to the SCSI routines used by the Snapscan backend. */ /* $Id$ SnapScan backend scan data sources */ #ifndef snapscan_usb_h #define snapscan_usb_h typedef SANE_Status (*sense_handler_type)(int fd, u_char *sense_buffer, void *arg); static SANE_Status snapscani_usb_cmd(int fd, const void *src, size_t src_size, void *dst, size_t * dst_size); static SANE_Status snapscani_usb_open(const char *dev, int *fdp, sense_handler_type, void*); static void snapscani_usb_close(int fd); /* * USB status codes */ #define GOOD 0x00 #define CHECK_CONDITION 0x01 #define CONDITION_GOOD 0x02 #define BUSY 0x04 #define INTERMEDIATE_GOOD 0x08 #define INTERMEDIATE_C_GOOD 0x0a #define RESERVATION_CONFLICT 0x0c #define COMMAND_TERMINATED 0x11 #define QUEUE_FULL 0x14 #define STATUS_MASK 0x3e /* * USB transaction status */ #define TRANSACTION_COMPLETED 0xfb /* Scanner considers the transaction done */ #define TRANSACTION_READ 0xf9 /* Scanner has data to deliver */ #define TRANSACTION_WRITE 0xf8 /* Scanner is expecting more data */ /* * Busy queue data structure and prototypes */ struct usb_busy_queue { int fd; void *src; size_t src_size; struct usb_busy_queue *next; }; static struct usb_busy_queue *bqhead,*bqtail; static int enqueue_bq(int fd,const void *src, size_t src_size); static void dequeue_bq(void); static int is_queueable(const char *src); static SANE_Status atomic_usb_cmd(int fd, const void *src, size_t src_size, void *dst, size_t * dst_size); static SANE_Status usb_cmd(int fd, const void *src, size_t src_size, void *dst, size_t * dst_size); #endif /* * $Log$ * Revision 1.6 2003/07/26 17:16:55 oliverschwartz * Changed licence to GPL + SANE exception for snapscan-usb.[ch] * * Revision 1.5 2002/04/10 21:45:53 oliverschwartz * Removed illegal character / removed declaration of bqelements * * Revision 1.10 2001/12/09 23:06:45 oliverschwartz * - use sense handler for USB if scanner reports CHECK_CONDITION * * Revision 1.9 2001/11/16 20:23:16 oliverschwartz * Merge with sane-1.0.6 * - Check USB vendor IDs to avoid hanging scanners * - fix bug in dither matrix computation * * Revision 1.8 2001/09/18 15:01:07 oliverschwartz * - Read scanner id string again after firmware upload * to indentify correct model * - Make firmware upload work for AGFA scanners * - Change copyright notice * * */ sane-backends-1.0.27/backend/genesys_low.h0000664000175000017500000012561412775312261015337 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Oliver Rauch Copyright (C) 2003, 2004 Henning Meier-Geinitz Copyright (C) 2004, 2005 Gerhard Jaeger Copyright (C) 2004-2013 Stéphane Voltz Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2006 Laurent Charpentier Parts of the structs have been taken from the gt68xx backend by Sergey Vlasov et al. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GENESYS_LOW_H #define GENESYS_LOW_H #include "../include/sane/config.h" #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_MKDIR #include #include #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "../include/_stdint.h" #ifndef UNIT_TESTING #define GENESYS_STATIC static #else #define GENESYS_STATIC #endif #define DBG_error0 0 /* errors/warnings printed even with devuglevel 0 */ #define DBG_error 1 /* fatal errors */ #define DBG_init 2 /* initialization and scanning time messages */ #define DBG_warn 3 /* warnings and non-fatal errors */ #define DBG_info 4 /* informational messages */ #define DBG_proc 5 /* starting/finishing functions */ #define DBG_io 6 /* io functions */ #define DBG_io2 7 /* io functions that are called very often */ #define DBG_data 8 /* log image data */ /** * call a function and return on error */ #define RIE(function) \ do { status = function; \ if (status != SANE_STATUS_GOOD) \ { \ DBG(DBG_error, "%s: %s\n", __func__, sane_strstatus (status)); \ return status; \ } \ } while (SANE_FALSE) #define RIEF(function, mem) \ do { status = function; \ if (status != SANE_STATUS_GOOD) \ { \ free(mem); \ DBG(DBG_error, "%s: %s\n", __func__, sane_strstatus (status)); \ return status; \ } \ } while (SANE_FALSE) #define RIEF2(function, mem1, mem2) \ do { status = function; \ if (status != SANE_STATUS_GOOD) \ { \ free(mem1); \ free(mem2); \ return status; \ } \ } while (SANE_FALSE) #define DBGSTART DBG (DBG_proc, "%s start\n", __func__); #define DBGCOMPLETED DBG (DBG_proc, "%s completed\n", __func__); #define FREE_IFNOT_NULL(x) if(x!=NULL) { free(x); x=NULL;} #define GENESYS_RED 0 #define GENESYS_GREEN 1 #define GENESYS_BLUE 2 /* Flags */ #define GENESYS_FLAG_UNTESTED (1 << 0) /**< Print a warning for these scanners */ #define GENESYS_FLAG_14BIT_GAMMA (1 << 1) /**< use 14bit Gamma table instead of 12 */ #define GENESYS_FLAG_LAZY_INIT (1 << 2) /**< skip extensive ASIC test at init */ #define GENESYS_FLAG_XPA (1 << 3) #define GENESYS_FLAG_SKIP_WARMUP (1 << 4) /**< skip genesys_warmup() */ /** @brief offset calibration flag * signals that the scanner does offset calibration. In this case off_calibration() and * coarse_gain_calibration() functions must be implemented */ #define GENESYS_FLAG_OFFSET_CALIBRATION (1 << 5) #define GENESYS_FLAG_SEARCH_START (1 << 6) /**< do start search before scanning */ #define GENESYS_FLAG_REPARK (1 << 7) /**< repark head (and check for lock) by moving without scanning */ #define GENESYS_FLAG_DARK_CALIBRATION (1 << 8) /**< do dark calibration */ #define GENESYS_FLAG_STAGGERED_LINE (1 << 9) /**< pixel columns are shifted vertically for hi-res modes */ #define GENESYS_FLAG_MUST_WAIT (1 << 10) /**< tells wether the scanner must wait for the head when parking */ #define GENESYS_FLAG_HAS_UTA (1 << 11) /**< scanner has a transparency adapter */ #define GENESYS_FLAG_DARK_WHITE_CALIBRATION (1 << 12) /**< yet another calibration method. does white and dark shading in one run, depending on a black and a white strip*/ #define GENESYS_FLAG_CUSTOM_GAMMA (1 << 13) /**< allow custom gamma tables */ #define GENESYS_FLAG_NO_CALIBRATION (1 << 14) /**< allow scanners to use skip the calibration, needed for sheetfed scanners */ #define GENESYS_FLAG_HALF_CCD_MODE (1 << 15) /**< scanner has setting for half ccd mode */ #define GENESYS_FLAG_SIS_SENSOR (1 << 16) /**< handling of multi-segments sensors in software */ #define GENESYS_FLAG_SHADING_NO_MOVE (1 << 17) /**< scanner doesn't move sensor during shading calibration */ #define GENESYS_FLAG_SHADING_REPARK (1 << 18) /**< repark head between shading scans */ #define GENESYS_FLAG_FULL_HWDPI_MODE (1 << 19) /**< scanner always use maximum hw dpi to setup the sensor */ #define GENESYS_HAS_NO_BUTTONS 0 /**< scanner has no supported button */ #define GENESYS_HAS_SCAN_SW (1 << 0) /**< scanner has SCAN button */ #define GENESYS_HAS_FILE_SW (1 << 1) /**< scanner has FILE button */ #define GENESYS_HAS_COPY_SW (1 << 2) /**< scanner has COPY button */ #define GENESYS_HAS_EMAIL_SW (1 << 3) /**< scanner has EMAIL button */ #define GENESYS_HAS_PAGE_LOADED_SW (1 << 4) /**< scanner has paper in detection */ #define GENESYS_HAS_OCR_SW (1 << 5) /**< scanner has OCR button */ #define GENESYS_HAS_POWER_SW (1 << 6) /**< scanner has power button */ #define GENESYS_HAS_CALIBRATE (1 << 7) /**< scanner has 'calibrate' software button to start calibration */ #define GENESYS_HAS_EXTRA_SW (1 << 8) /**< scanner has extra function button */ /* USB control message values */ #define REQUEST_TYPE_IN (USB_TYPE_VENDOR | USB_DIR_IN) #define REQUEST_TYPE_OUT (USB_TYPE_VENDOR | USB_DIR_OUT) #define REQUEST_REGISTER 0x0c #define REQUEST_BUFFER 0x04 #define VALUE_BUFFER 0x82 #define VALUE_SET_REGISTER 0x83 #define VALUE_READ_REGISTER 0x84 #define VALUE_WRITE_REGISTER 0x85 #define VALUE_INIT 0x87 #define GPIO_OUTPUT_ENABLE 0x89 #define GPIO_READ 0x8a #define GPIO_WRITE 0x8b #define VALUE_BUF_ENDACCESS 0x8c #define VALUE_GET_REGISTER 0x8e #define INDEX 0x00 /* todo: used? #define VALUE_READ_STATUS 0x86 */ /* Read/write bulk data/registers */ #define BULK_OUT 0x01 #define BULK_IN 0x00 #define BULK_RAM 0x00 #define BULK_REGISTER 0x11 #define BULKIN_MAXSIZE 0xFE00 #define GL646_BULKIN_MAXSIZE 0xFFC0 #define GL646_BULKIN_MINSIZE 0x0800 #define BULKOUT_MAXSIZE 0xF000 /* AFE values */ #define AFE_INIT 1 #define AFE_SET 2 #define AFE_POWER_SAVE 4 #define LOWORD(x) ((uint16_t)((x) & 0xffff)) #define HIWORD(x) ((uint16_t)((x) >> 16)) #define LOBYTE(x) ((uint8_t)((x) & 0xFF)) #define HIBYTE(x) ((uint8_t)((x) >> 8)) /* Global constants */ /* TODO: emove this leftover of early backend days */ #define MOTOR_SPEED_MAX 350 #define DARK_VALUE 0 #define PWRBIT 0x80 #define BUFEMPTY 0x40 #define FEEDFSH 0x20 #define SCANFSH 0x10 #define HOMESNR 0x08 #define LAMPSTS 0x04 #define FEBUSY 0x02 #define MOTORENB 0x01 typedef struct Genesys_Register_Set { uint16_t address; uint8_t value; } Genesys_Register_Set; /** @brief Data structure to set up analog frontend. * The analog frontend converts analog value from image sensor to * digital value. It has its own control registers which are set up * with this structure. The values are written using sanei_genesys_fe_write_data. * The actual register addresses they map to depends on the frontend used. * @see sanei_genesys_fe_write_data */ typedef struct { uint8_t fe_id; /**< id of the frontend description */ uint8_t reg[4]; /**< values to set up frontend control register, they usually map to analog register 0x00 to 0x03 */ uint8_t sign[3]; /**< sets the sign of the digital value */ uint8_t offset[3]; /**< offset correction to apply to signal, most often maps to frontend register 0x20-0x22 */ uint8_t gain[3]; /**< amplification to apply to signal, most often maps to frontend register 0x28-0x2a */ uint8_t reg2[3]; /**< extra control registers */ } Genesys_Frontend; typedef struct { uint8_t sensor_id; /**< id of the sensor description */ int optical_res; int black_pixels; int dummy_pixel; /* value of dummy register. */ int CCD_start_xoffset; /* last pixel of CCD margin at optical resolution */ int sensor_pixels; /* total pixels used by the sensor */ int fau_gain_white_ref; /* TA CCD target code (reference gain) */ int gain_white_ref; /* CCD target code (reference gain) */ uint8_t regs_0x08_0x0b[4]; uint8_t regs_0x10_0x1d[14]; uint8_t regs_0x52_0x5e[13]; float gamma[3]; /**< red, green and blue gamma coefficient for default gamma tables */ uint16_t *gamma_table[3]; /**< sensor specific gamma tables */ } Genesys_Sensor; typedef struct { uint8_t gpo_id; /**< id of the gpo description */ uint8_t value[2]; /**< registers 0x6c and 0x6d on gl843 */ uint8_t enable[2]; /**< registers 0x6e and 0x6F on gl843 */ } Genesys_Gpo; typedef struct { SANE_Int maximum_start_speed; /* maximum speed allowed when accelerating from standstill. Unit: pixeltime/step */ SANE_Int maximum_speed; /* maximum speed allowed. Unit: pixeltime/step */ SANE_Int minimum_steps; /* number of steps used for default curve */ float g; /* power for non-linear acceleration curves. */ /* vs*(1-i^g)+ve*(i^g) where vs = start speed, ve = end speed, i = 0.0 for first entry and i = 1.0 for last entry in default table*/ } Genesys_Motor_Slope; typedef struct { uint8_t motor_id; /**< id of the motor description */ SANE_Int base_ydpi; /* motor base steps. Unit: 1/" */ SANE_Int optical_ydpi; /* maximum resolution in y-direction. Unit: 1/" */ SANE_Int max_step_type; /* maximum step type. 0-2 */ SANE_Int power_mode_count; /* number of power modes*/ Genesys_Motor_Slope slopes[2][3]; /* slopes to derive individual slopes from */ } Genesys_Motor; typedef enum Genesys_Color_Order { COLOR_ORDER_RGB, COLOR_ORDER_BGR } Genesys_Color_Order; #define MAX_RESOLUTIONS 13 #define MAX_DPI 4 #define GENESYS_GL646 646 #define GENESYS_GL841 841 #define GENESYS_GL843 843 #define GENESYS_GL845 845 #define GENESYS_GL846 846 #define GENESYS_GL847 847 #define GENESYS_GL848 848 #define GENESYS_GL123 123 #define GENESYS_GL124 124 #define GENESYS_MAX_REGS 256 #define DAC_WOLFSON_UMAX 0 #define DAC_WOLFSON_ST12 1 #define DAC_WOLFSON_ST24 2 #define DAC_WOLFSON_5345 3 #define DAC_WOLFSON_HP2400 4 #define DAC_WOLFSON_HP2300 5 #define DAC_CANONLIDE35 6 #define DAC_AD_XP200 7 /* Analog Device frontend */ #define DAC_WOLFSON_XP300 8 #define DAC_WOLFSON_HP3670 9 #define DAC_WOLFSON_DSM600 10 #define DAC_CANONLIDE200 11 #define DAC_KVSS080 12 #define DAC_G4050 13 #define DAC_CANONLIDE110 14 #define DAC_PLUSTEK_3600 15 #define DAC_CANONLIDE700 16 #define DAC_CS8400F 17 #define DAC_IMG101 18 #define DAC_PLUSTEK3800 19 #define DAC_CANONLIDE80 20 #define DAC_CANONLIDE120 21 #define CCD_UMAX 0 #define CCD_ST12 1 /* SONY ILX548: 5340 Pixel ??? */ #define CCD_ST24 2 /* SONY ILX569: 10680 Pixel ??? */ #define CCD_5345 3 #define CCD_HP2400 4 #define CCD_HP2300 5 #define CCD_CANONLIDE35 6 #define CIS_XP200 7 /* CIS sensor for Strobe XP200 */ /* 8 is unused currently */ #define CCD_HP3670 9 #define CCD_DP665 10 #define CCD_ROADWARRIOR 11 #define CCD_DSMOBILE600 12 #define CCD_XP300 13 #define CCD_DP685 14 #define CIS_CANONLIDE200 15 #define CIS_CANONLIDE100 16 #define CCD_KVSS080 17 #define CCD_G4050 18 #define CIS_CANONLIDE110 19 #define CCD_PLUSTEK_3600 20 #define CCD_HP_N6310 21 #define CIS_CANONLIDE700 22 #define CCD_CS4400F 23 #define CCD_CS8400F 24 #define CCD_IMG101 25 #define CCD_PLUSTEK3800 26 #define CIS_CANONLIDE210 27 #define CIS_CANONLIDE80 28 #define CIS_CANONLIDE220 29 #define CIS_CANONLIDE120 30 #define GPO_UMAX 0 #define GPO_ST12 1 #define GPO_ST24 2 #define GPO_5345 3 #define GPO_HP2400 4 #define GPO_HP2300 5 #define GPO_CANONLIDE35 6 #define GPO_XP200 7 #define GPO_XP300 8 #define GPO_HP3670 9 #define GPO_DP665 10 #define GPO_DP685 11 #define GPO_CANONLIDE200 12 #define GPO_KVSS080 13 #define GPO_G4050 14 #define GPO_CANONLIDE110 15 #define GPO_PLUSTEK_3600 16 #define GPO_CANONLIDE210 17 #define GPO_HP_N6310 18 #define GPO_CANONLIDE700 19 #define GPO_CS4400F 20 #define GPO_CS8400F 21 #define GPO_IMG101 22 #define GPO_PLUSTEK3800 23 #define GPO_CANONLIDE80 24 #define GPO_CANONLIDE120 25 #define MOTOR_UMAX 0 #define MOTOR_5345 1 #define MOTOR_ST24 2 #define MOTOR_HP2400 3 #define MOTOR_HP2300 4 #define MOTOR_CANONLIDE35 5 #define MOTOR_XP200 6 #define MOTOR_XP300 7 #define MOTOR_HP3670 9 #define MOTOR_DP665 10 #define MOTOR_ROADWARRIOR 11 #define MOTOR_DSMOBILE_600 12 #define MOTOR_CANONLIDE200 13 #define MOTOR_CANONLIDE100 14 #define MOTOR_KVSS080 15 #define MOTOR_G4050 16 #define MOTOR_CANONLIDE110 17 #define MOTOR_PLUSTEK_3600 18 #define MOTOR_CANONLIDE700 19 #define MOTOR_CS8400F 20 #define MOTOR_IMG101 21 #define MOTOR_PLUSTEK3800 22 #define MOTOR_CANONLIDE210 23 #define MOTOR_CANONLIDE80 24 #define MOTOR_CANONLIDE120 25 /* Forward typedefs */ typedef struct Genesys_Device Genesys_Device; struct Genesys_Scanner; typedef struct Genesys_Calibration_Cache Genesys_Calibration_Cache; /** * Scanner command set description. * * This description contains parts which are common to all scanners with the * same command set, but may have different optical resolution and other * parameters. */ typedef struct Genesys_Command_Set { /** @name Identification */ /*@{ */ /** Name of this command set */ SANE_String_Const name; /*@} */ /** For ASIC initialization */ SANE_Status (*init) (Genesys_Device * dev); SANE_Status (*init_regs_for_warmup) (Genesys_Device * dev, Genesys_Register_Set * regs, int *channels, int *total_size); SANE_Status (*init_regs_for_coarse_calibration) (Genesys_Device * dev); SANE_Status (*init_regs_for_shading) (Genesys_Device * dev); SANE_Status (*init_regs_for_scan) (Genesys_Device * dev); SANE_Bool (*get_filter_bit) (Genesys_Register_Set * reg); SANE_Bool (*get_lineart_bit) (Genesys_Register_Set * reg); SANE_Bool (*get_bitset_bit) (Genesys_Register_Set * reg); SANE_Bool (*get_gain4_bit) (Genesys_Register_Set * reg); SANE_Bool (*get_fast_feed_bit) (Genesys_Register_Set * reg); SANE_Bool (*test_buffer_empty_bit) (SANE_Byte val); SANE_Bool (*test_motor_flag_bit) (SANE_Byte val); int (*bulk_full_size) (void); SANE_Status (*set_fe) (Genesys_Device * dev, uint8_t set); SANE_Status (*set_powersaving) (Genesys_Device * dev, int delay); SANE_Status (*save_power) (Genesys_Device * dev, SANE_Bool enable); void (*set_motor_power) (Genesys_Register_Set * regs, SANE_Bool set); void (*set_lamp_power) (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool set); SANE_Status (*begin_scan) (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool start_motor); SANE_Status (*end_scan) (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool check_stop); /** * Send gamma tables to ASIC */ SANE_Status (*send_gamma_table) (Genesys_Device * dev); SANE_Status (*search_start_position) (Genesys_Device * dev); SANE_Status (*offset_calibration) (Genesys_Device * dev); SANE_Status (*coarse_gain_calibration) (Genesys_Device * dev, int dpi); SANE_Status (*led_calibration) (Genesys_Device * dev); SANE_Status (*slow_back_home) (Genesys_Device * dev, SANE_Bool wait_until_home); SANE_Status (*rewind) (Genesys_Device * dev); SANE_Status (*bulk_write_register) (Genesys_Device * dev, Genesys_Register_Set * reg, size_t elems); SANE_Status (*bulk_write_data) (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len); SANE_Status (*bulk_read_data) (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len); /* Updates hardware sensor information in Genesys_Scanner.val[]. If possible, just get information for given option. The sensor state in Genesys_Scanner.val[] should be merged with the new sensor state, using the information that was last read by the frontend in Genesys_Scanner.last_val[], in such a way that a button up/down relative to Genesys_Scanner.last_val[] is not lost. */ SANE_Status (*update_hardware_sensors) (struct Genesys_Scanner * s); /* functions for sheetfed scanners */ /** * load document into scanner */ SANE_Status (*load_document) (Genesys_Device * dev); /** * detects is the scanned document has left scanner. In this * case it updates the amount of data to read and set up * flags in the dev struct */ SANE_Status (*detect_document_end) (Genesys_Device * dev); /** * eject document from scanner */ SANE_Status (*eject_document) (Genesys_Device * dev); /** * search for an black or white area in forward or reverse * direction */ SANE_Status (*search_strip) (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black); SANE_Status (*is_compatible_calibration) ( Genesys_Device * dev, Genesys_Calibration_Cache *cache, SANE_Bool for_overwrite); /* functions for transparency adapter */ /** * move scanning head to transparency adapter */ SANE_Status (*move_to_ta) (Genesys_Device * dev); /** * write shading data calibration to ASIC */ SANE_Status (*send_shading_data) (Genesys_Device * dev, uint8_t * data, int size); /** * calculate current scan setup */ SANE_Status (*calculate_current_setup) (Genesys_Device * dev); /** * cold boot init function */ SANE_Status (*asic_boot) (Genesys_Device * dev, SANE_Bool cold); /** * Scan register setting interface */ SANE_Status (*init_scan_regs) (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, float yres, float startx, float starty, float pixels, float lines, unsigned int depth, unsigned int channels, int scan_method, int scan_mode, int color_filter, unsigned int flags); } Genesys_Command_Set; /** @brief structure to describe a scanner model * This structure describes a model. It is composed of information on the * sensor, the motor, scanner geometry and flags to drive operation. */ typedef struct Genesys_Model { SANE_String_Const name; SANE_String_Const vendor; SANE_String_Const model; SANE_Int asic_type; /* ASIC type gl646 or gl841 */ Genesys_Command_Set *cmd_set; /* pointers to low level functions */ SANE_Int xdpi_values[MAX_RESOLUTIONS]; /* possible x resolutions */ SANE_Int ydpi_values[MAX_RESOLUTIONS]; /* possible y resolutions */ SANE_Int bpp_gray_values[MAX_DPI]; /* possible depths in gray mode */ SANE_Int bpp_color_values[MAX_DPI]; /* possible depths in color mode */ SANE_Fixed x_offset; /* Start of scan area in mm */ SANE_Fixed y_offset; /* Start of scan area in mm (Amount of feeding needed to get to the medium) */ SANE_Fixed x_size; /* Size of scan area in mm */ SANE_Fixed y_size; /* Size of scan area in mm */ SANE_Fixed y_offset_calib; /* Start of white strip in mm */ SANE_Fixed x_offset_mark; /* Start of black mark in mm */ SANE_Fixed x_offset_ta; /* Start of scan area in TA mode in mm */ SANE_Fixed y_offset_ta; /* Start of scan area in TA mode in mm */ SANE_Fixed x_size_ta; /* Size of scan area in TA mode in mm */ SANE_Fixed y_size_ta; /* Size of scan area in TA mode in mm */ SANE_Fixed y_offset_calib_ta; /* Start of white strip in TA mode in mm */ SANE_Fixed post_scan; /* Size of scan area after paper sensor stops sensing document in mm */ SANE_Fixed eject_feed; /* Amount of feeding needed to eject document after finishing scanning in mm */ /* Line-distance correction (in pixel at optical_ydpi) for CCD scanners */ SANE_Int ld_shift_r; /* red */ SANE_Int ld_shift_g; /* green */ SANE_Int ld_shift_b; /* blue */ Genesys_Color_Order line_mode_color_order; /* Order of the CCD/CIS colors */ SANE_Bool is_cis; /* Is this a CIS or CCD scanner? */ SANE_Bool is_sheetfed; /* Is this sheetfed scanner? */ SANE_Int ccd_type; /* which SENSOR type do we have ? */ SANE_Int dac_type; /* which DAC do we have ? */ SANE_Int gpo_type; /* General purpose output type */ SANE_Int motor_type; /* stepper motor type */ SANE_Word flags; /* Which hacks are needed for this scanner? */ SANE_Word buttons; /* Button flags, described existing buttons for the model */ /*@} */ SANE_Int shading_lines; /* how many lines are used for shading calibration */ SANE_Int search_lines; /* how many lines are used to search start position */ } Genesys_Model; #define SCAN_METHOD_FLATBED 0 /**< normal scan method */ #define SCAN_METHOD_TRANSPARENCY 2 /**< scan using transparency adaptor */ #define SCAN_METHOD_NEGATIVE 0x88 /**< scan using negative adaptor */ #define SCAN_MODE_LINEART 0 /**< lineart scan mode */ #define SCAN_MODE_HALFTONE 1 /**< halftone scan mode */ #define SCAN_MODE_GRAY 2 /**< gray scan mode */ #define SCAN_MODE_COLOR 4 /**< color scan mode */ typedef struct { int scan_method; /* todo: change >=2: Transparency, 0x88: negative film */ int scan_mode; /* todo: change 0,1 = lineart, halftone; 2 = gray, 3 = 3pass color, 4=single pass color */ int xres; /**< horizontal dpi */ int yres; /**< vertical dpi */ double tl_x; /* x start on scan table in mm */ double tl_y; /* y start on scan table in mm */ unsigned int lines; /**< number of lines at scan resolution */ unsigned int pixels; /**< number of pixels at scan resolution */ unsigned int depth;/* bit depth of the scan */ /* todo : remove these fields ? */ int exposure_time; unsigned int color_filter; /**< true if scan is true gray, false if monochrome scan */ int true_gray; /**< lineart threshold */ int threshold; /**< lineart threshold curve for dynamic rasterization */ int threshold_curve; /**< Disable interpolation for xres #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBC_H # include #endif #include "../include/sane/sane.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" #define DARK_TARGET 3.1 /* 3.5 target average for dark calibration */ #define DARK_MARGIN 0.3 /* acceptable margin for dark average */ #define OFFSET_TARGET 3.5 /* target average for offset calibration */ #define OFFSET_MARGIN 0.3 /* acceptable margin for offset average */ #define RED_GAIN_TARGET 170 /* target average for gain calibration for blue color */ #define GREEN_GAIN_TARGET 170 /* target average for gain calibration for blue color */ #define BLUE_GAIN_TARGET 180 /* target average for gain calibration for blue color */ #define GAIN_MARGIN 2 /* acceptable margin for gain average */ #define MARGIN_LEVEL 128 /* white level for margin detection */ /* width used for calibration */ #define CALIBRATION_WIDTH 637 /* data size for calibration: one RGB line*/ #define CALIBRATION_SIZE CALIBRATION_WIDTH*3 /* #define FAST_INIT 1 */ #define BUILD 2401 #define MOVE_DPI 100 #include "rts8891.h" #include "rts88xx_lib.h" #include "rts8891_low.c" #include "rts8891_devices.c" #define DEEP_DEBUG 1 /** * Pointer to the first Rts8891_Session in the linked list of * opened device. Sessions are inserted here on sane_open() and * removed on sane_close(). */ static Rts8891_Session *first_handle = NULL; /* pointer to the first device attached to the backend * the same device may be opened several time * entry are inserted here by attach_rts8891 */ static Rts8891_Device *first_device = NULL; static SANE_Int num_devices = 0; /* * needed by sane_get_devices */ static const SANE_Device **devlist = 0; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_LINEART, 0 }; static SANE_Range x_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (216.0), /* maximum */ SANE_FIX (0.0) /* quantization */ }; static SANE_Range y_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (299.0), /* maximum */ SANE_FIX (0.0) /* no quantization */ }; /* model number ranges from 0 to 2, must be changed if * Rts8891_USB_Device_Entry changes */ static const SANE_Range model_range = { 0, /* minimum */ 2, /* maximum */ 0 /* no quantization */ }; /* sensor number ranges from 0 to SENSOR_TYPE_MAX, must be changed if */ static const SANE_Range sensor_range = { 0, /* minimum */ SENSOR_TYPE_MAX, /* maximum */ 0 /* no quantization */ }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* no quantization */ }; static const SANE_Range threshold_percentage_range = { SANE_FIX (0), /* minimum */ SANE_FIX (100), /* maximum */ SANE_FIX (1) /* quantization */ }; static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /**> placeholders for decoded configuration values */ static Rts8891_Config rtscfg; /* ------------------------------------------------------------------------- */ static SANE_Status probe_rts8891_devices (void); static SANE_Status config_attach_rts8891 (SANEI_Config * config, const char *devname); static SANE_Status attach_rts8891 (const char *name); static SANE_Status set_lamp_brightness (struct Rts8891_Device *dev, int level); static SANE_Status init_options (struct Rts8891_Session *session); #ifndef FAST_INIT static SANE_Status init_device (struct Rts8891_Device *dev); #else static SANE_Status detect_device (struct Rts8891_Device *dev); static SANE_Status initialize_device (struct Rts8891_Device *dev); #endif static SANE_Status init_lamp (struct Rts8891_Device *dev); static SANE_Status find_origin (struct Rts8891_Device *dev, SANE_Bool * changed); static SANE_Status find_margin (struct Rts8891_Device *dev); static SANE_Status dark_calibration (struct Rts8891_Device *dev, int mode, int light); static SANE_Status gain_calibration (struct Rts8891_Device *dev, int mode, int light); static SANE_Status offset_calibration (struct Rts8891_Device *dev, int mode, int light); static SANE_Status shading_calibration (struct Rts8891_Device *dev, SANE_Bool color, int mode, int light); static SANE_Status send_calibration_data (struct Rts8891_Session *session); static SANE_Status write_scan_registers (struct Rts8891_Session *session); static SANE_Status read_data (struct Rts8891_Session *session, SANE_Byte * dest, SANE_Int length); static SANE_Status compute_parameters (struct Rts8891_Session *session); static SANE_Status move_to_scan_area (struct Rts8891_Session *session); static SANE_Status park_head (struct Rts8891_Device *dev, SANE_Bool wait); static SANE_Status update_button_status (struct Rts8891_Session *session); static SANE_Status set_lamp_state (struct Rts8891_Session *session, int on); /* ------------------------------------------------------------------------- */ /* writes gray data to a pnm file */ static void write_gray_data (unsigned char *image, char *name, SANE_Int width, SANE_Int height) { FILE *fdbg = NULL; fdbg = fopen (name, "wb"); if (fdbg == NULL) return; fprintf (fdbg, "P5\n%d %d\n255\n", width, height); fwrite (image, width, height, fdbg); fclose (fdbg); } /* ------------------------------------------------------------------------- */ /* writes rgb data to a pnm file */ static void write_rgb_data (char *name, unsigned char *image, SANE_Int width, SANE_Int height) { FILE *fdbg = NULL; fdbg = fopen (name, "wb"); if (fdbg == NULL) return; fprintf (fdbg, "P6\n%d %d\n255\n", width, height); fwrite (image, width * 3, height, fdbg); fclose (fdbg); } /* ------------------------------------------------------------------------- */ /* * SANE Interface */ /** * Called by SANE initially. * * From the SANE spec: * This function must be called before any other SANE function can be * called. The behavior of a SANE backend is undefined if this * function is not called first. The version code of the backend is * returned in the value pointed to by version_code. If that pointer * is NULL, no version code is returned. Argument authorize is either * a pointer to a function that is invoked when the backend requires * authentication for a specific resource or NULL if the frontend does * not support authentication. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { SANE_Status status; authorize = authorize; /* get rid of compiler warning */ /* init ASIC libraries */ sanei_rts88xx_lib_init (); rts8891_low_init (); /* init backend debug */ DBG_INIT (); DBG (DBG_info, "SANE Rts8891 backend version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_proc, "sane_init: start\n"); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); /* cold-plugging case : probe for already plugged devices */ status = probe_rts8891_devices (); DBG (DBG_proc, "sane_init: exit\n"); return status; } /** * Called by SANE to find out about supported devices. * * From the SANE spec: * This function can be used to query the list of devices that are * available. If the function executes successfully, it stores a * pointer to a NULL terminated array of pointers to SANE_Device * structures in *device_list. The returned list is guaranteed to * remain unchanged and valid until (a) another call to this function * is performed or (b) a call to sane_exit() is performed. This * function can be called repeatedly to detect when new devices become * available. If argument local_only is true, only local devices are * returned (devices directly attached to the machine that SANE is * running on). If it is false, the device list includes all remote * devices that are accessible to the SANE library. * * SANE does not require that this function is called before a * sane_open() call is performed. A device name may be specified * explicitly by a user which would make it unnecessary and * undesirable to call this function first. */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { SANE_Int dev_num; struct Rts8891_Device *device; SANE_Device *sane_device; int i; DBG (DBG_proc, "sane_get_devices: start: local_only = %s\n", local_only == SANE_TRUE ? "true" : "false"); /* hot-plugging case : probe for devices plugged since sane_init called */ probe_rts8891_devices (); /* reset devlist first if needed */ if (devlist) { for (i = 0; i < num_devices; i++) free ((char *) devlist[i]); free (devlist); devlist = NULL; } devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; *device_list = devlist; dev_num = 0; /* we build a list of SANE_Device from the list of attached devices */ for (device = first_device; dev_num < num_devices; device = device->next) { sane_device = malloc (sizeof (*sane_device)); if (!sane_device) return SANE_STATUS_NO_MEM; sane_device->name = device->file_name; sane_device->vendor = device->model->vendor; sane_device->model = device->model->product; sane_device->type = device->model->type; devlist[dev_num++] = sane_device; } devlist[dev_num++] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } /** * Called to establish connection with the session. This function will * also establish meaningful defaults and initialize the options. * * From the SANE spec: * This function is used to establish a connection to a particular * device. The name of the device to be opened is passed in argument * name. If the call completes successfully, a handle for the device * is returned in *h. As a special case, specifying a zero-length * string as the device requests opening the first available device * (if there is such a device). * TODO handle SANE_STATUS_BUSY */ SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle) { struct Rts8891_Session *session = NULL; struct Rts8891_Device *device = NULL; SANE_Status status; DBG (DBG_proc, "sane_open: start (devicename=%s)\n", name); if (name[0] == 0 || strncmp (name, "rts8891", 7) == 0) { DBG (DBG_info, "sane_open: no device requested, using default\n"); if (first_device) { device = first_device; DBG (DBG_info, "sane_open: device %s used as default device\n", device->file_name); } } else { DBG (DBG_info, "sane_open: device %s requested\n", name); /* walk the device list until we find a matching name */ device = first_device; while (device && strcmp (device->file_name, name) != 0) { DBG (DBG_info, "sane_open: device %s doesn't match\n", device->file_name); device = device->next; } } /* check wether we have found a match or reach the end of the device list */ if (!device) { DBG (DBG_info, "sane_open: no device found\n"); return SANE_STATUS_INVAL; } /* now we have a device, duplicate it and return it in handle */ DBG (DBG_info, "sane_open: device %s found\n", name); if (device->model->flags & RTS8891_FLAG_UNTESTED) { DBG (DBG_error0, "WARNING: Your scanner is not fully supported or at least \n"); DBG (DBG_error0, " had only limited testing. Please be careful and \n"); DBG (DBG_error0, " report any failure/success to \n"); DBG (DBG_error0, " sane-devel@lists.alioth.debian.org. Please provide as many\n"); DBG (DBG_error0, " details as possible, e.g. the exact name of your\n"); DBG (DBG_error0, " scanner and what does (not) work.\n"); } /* open USB link */ status = sanei_usb_open (device->file_name, &device->devnum); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "sane_open: couldn't open device `%s': %s\n", device->file_name, sane_strstatus (status)); return status; } /* device initialization */ if (device->initialized == SANE_FALSE) { #ifdef FAST_INIT status = detect_device (device); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_open: detect_device failed\n"); DBG (DBG_proc, "sane_open: exit on error\n"); return status; } status = initialize_device (device); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_open: initialize_device failed\n"); DBG (DBG_proc, "sane_open: exit on error\n"); return status; } #else status = init_device (device); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_open: init_device failed\n"); DBG (DBG_proc, "sane_open: exit on error\n"); return status; } device->initialized = SANE_TRUE; #endif } /* prepare handle to return */ session = (Rts8891_Session *) malloc (sizeof (Rts8891_Session)); session->scanning = SANE_FALSE; session->dev = device; init_options (session); session->scanning = SANE_FALSE; session->non_blocking = SANE_FALSE; *handle = session; /* add the handle to the list */ session->next = first_handle; first_handle = session; /* release the interface to allow device sharing */ if (session->dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (device->devnum, 0); } DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } /** * Set non blocking mode. In this mode, read return immediatly when * no data is available, instead of polling the scanner. */ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Rts8891_Session *session = (Rts8891_Session *) handle; DBG (DBG_proc, "sane_set_io_mode: start\n"); if (session->scanning != SANE_TRUE) { DBG (DBG_error, "sane_set_io_mode: called out of a scan\n"); return SANE_STATUS_INVAL; } session->non_blocking = non_blocking; DBG (DBG_warn, "sane_set_io_mode: I/O mode set to %sblocking.\n", non_blocking ? "non " : " "); DBG (DBG_proc, "sane_set_io_mode: exit\n"); return SANE_STATUS_GOOD; } /** * An advanced method we don't support but have to define. */ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fdp) { DBG (DBG_proc, "sane_get_select_fd: start\n"); if(handle==0 || fdp==NULL) { return SANE_STATUS_INVAL; } DBG (DBG_warn, "sane_get_select_fd: unsupported ...\n"); DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } /** * Returns the options we know. * * From the SANE spec: * This function is used to access option descriptors. The function * returns the option descriptor for option number n of the device * represented by handle h. Option number 0 is guaranteed to be a * valid option. Its value is an integer that specifies the number of * options that are available for device handle h (the count includes * option 0). If n is not a valid option index, the function returns * NULL. The returned option descriptor is guaranteed to remain valid * (and at the returned address) until the device is closed. */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct Rts8891_Session *session = handle; DBG (DBG_proc, "sane_get_option_descriptor: start\n"); if ((unsigned) option >= NUM_OPTIONS) return NULL; DBG (DBG_info, "sane_get_option_descriptor: \"%s\"\n", session->opt[option].name); DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return &(session->opt[option]); } /** * sets automatic value for an option , called by sane_control_option after * all checks have been done */ static SANE_Status set_automatic_value (Rts8891_Session * s, int option, SANE_Int * myinfo) { SANE_Status status = SANE_STATUS_GOOD; SANE_Int i, min; const SANE_Word *dpi_list; switch (option) { case OPT_TL_X: s->val[OPT_TL_X].w = x_range.min; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_TL_Y: s->val[OPT_TL_Y].w = y_range.min; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BR_X: s->val[OPT_BR_X].w = x_range.max; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BR_Y: s->val[OPT_BR_Y].w = y_range.max; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_RESOLUTION: /* we set up to the lowest available dpi value */ dpi_list = s->opt[OPT_RESOLUTION].constraint.word_list; min = 65536; for (i = 1; i < dpi_list[0]; i++) { if (dpi_list[i] < min) min = dpi_list[i]; } s->val[OPT_RESOLUTION].w = min; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_THRESHOLD: s->val[OPT_THRESHOLD].w = SANE_FIX (50); break; case OPT_PREVIEW: s->val[OPT_PREVIEW].w = SANE_FALSE; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_MODE: if (s->val[OPT_MODE].s) free (s->val[OPT_MODE].s); s->val[OPT_MODE].s = strdup (mode_list[0]); *myinfo |= SANE_INFO_RELOAD_OPTIONS; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_CUSTOM_GAMMA: s->val[option].b = SANE_FALSE; DISABLE (OPT_GAMMA_VECTOR); DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); break; case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: if (s->dev->model->gamma != s->val[option].wa) free (s->val[option].wa); s->val[option].wa = s->dev->model->gamma; break; default: DBG (DBG_warn, "set_automatic_value: can't set unknown option %d\n", option); } return status; } /** * sets an option , called by sane_control_option after all * checks have been done */ static SANE_Status set_option_value (Rts8891_Session * s, int option, void *val, SANE_Int * myinfo) { SANE_Status status = SANE_STATUS_GOOD; SANE_Int i; SANE_Word tmpw; switch (option) { case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; /* we ensure geometry is coherent */ /* this happens when user drags TL corner right or below the BR point */ if (s->val[OPT_BR_Y].w < s->val[OPT_TL_Y].w) { tmpw = s->val[OPT_BR_Y].w; s->val[OPT_BR_Y].w = s->val[OPT_TL_Y].w; s->val[OPT_TL_Y].w = tmpw; } if (s->val[OPT_BR_X].w < s->val[OPT_TL_X].w) { tmpw = s->val[OPT_BR_X].w; s->val[OPT_BR_X].w = s->val[OPT_TL_X].w; s->val[OPT_TL_X].w = tmpw; } *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_RESOLUTION: case OPT_THRESHOLD: case OPT_PREVIEW: s->val[option].w = *(SANE_Word *) val; *myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[option].s, LINEART_MODE) == 0) { ENABLE (OPT_THRESHOLD); } else { DISABLE (OPT_THRESHOLD); } /* if custom gamma, toggle gamma table options according to the mode */ if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE) { if (strcmp (s->val[option].s, COLOR_MODE) == 0) { DISABLE (OPT_GAMMA_VECTOR); ENABLE (OPT_GAMMA_VECTOR_R); ENABLE (OPT_GAMMA_VECTOR_G); ENABLE (OPT_GAMMA_VECTOR_B); } else { ENABLE (OPT_GAMMA_VECTOR); DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); } } *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_CUSTOM_GAMMA: *myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; s->val[OPT_CUSTOM_GAMMA].b = *(SANE_Bool *) val; if (s->val[OPT_CUSTOM_GAMMA].b == SANE_TRUE) { if (strcmp (s->val[OPT_MODE].s, COLOR_MODE) == 0) { DISABLE (OPT_GAMMA_VECTOR); ENABLE (OPT_GAMMA_VECTOR_R); ENABLE (OPT_GAMMA_VECTOR_G); ENABLE (OPT_GAMMA_VECTOR_B); } else { ENABLE (OPT_GAMMA_VECTOR); DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); } } else { DISABLE (OPT_GAMMA_VECTOR); DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); } break; case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: /* sanity checks */ for (i = 0; i < (int) (s->opt[option].size / sizeof (SANE_Word)); i++) { /* avoid 0xaa values since they will be problematic */ if (((SANE_Int *) val)[i] == 0xaa) ((SANE_Int *) val)[i] = 0xab; } /* free memory from previous set */ if (s->dev->model->gamma != s->val[option].wa) free (s->val[option].wa); /* then alloc memory */ s->val[option].wa = (SANE_Word *) malloc (256 * sizeof (SANE_Word)); if (s->val[option].wa == NULL) { s->val[option].wa = s->dev->model->gamma; DBG (DBG_error0, "set_option_value: not enough memory for %lu bytes!\n", (u_long) (256 * sizeof (SANE_Word))); return SANE_STATUS_NO_MEM; } /* data copy */ memcpy (s->val[option].wa, val, s->opt[option].size); break; case OPT_LAMP_ON: return set_lamp_state (s, 1); break; case OPT_LAMP_OFF: return set_lamp_state (s, 0); break; default: DBG (DBG_warn, "set_option_value: can't set unknown option %d\n", option); } return status; } /** * gets an option , called by sane_control_option after all checks * have been done */ static SANE_Status get_option_value (Rts8891_Session * s, int option, void *val) { switch (option) { /* word or word equivalent options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_THRESHOLD: case OPT_CUSTOM_GAMMA: *(SANE_Word *) val = s->val[option].w; break; case OPT_BUTTON_1: case OPT_BUTTON_2: case OPT_BUTTON_3: case OPT_BUTTON_4: case OPT_BUTTON_5: case OPT_BUTTON_6: case OPT_BUTTON_7: case OPT_BUTTON_8: case OPT_BUTTON_9: case OPT_BUTTON_10: case OPT_BUTTON_11: /* no button pressed by default */ *(SANE_Word *) val = SANE_FALSE; if (option - OPT_BUTTON_1 > s->dev->model->buttons) { DBG (DBG_warn, "get_option_value: invalid button option %d\n", option); } else { update_button_status (s); /* copy the button state */ *(SANE_Word *) val = s->val[option].w; /* clear the button state */ s->val[option].w = SANE_FALSE; DBG (DBG_io, "get_option_value: button option %d=%d\n", option, *(SANE_Word *) val); } break; /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); break; case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); break; default: DBG (DBG_warn, "get_option_value: can't get unknown option %d\n", option); } return SANE_STATUS_GOOD; } /** * Gets or sets an option value. * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which * the option is controlled is specified by parameter action. The * possible values of this parameter are described in more detail * below. The value of the option is passed through argument val. It * is a pointer to the memory that holds the option value. The memory * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon * encountering the first NUL terminator in the string. If argument i * is not NULL, the value of *i will be set to provide details on how * well the request has been met. * action is SANE_ACTION_GET_VALUE, SANE_ACTION_SET_VALUE or SANE_ACTION_SET_AUTO */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Rts8891_Session *s = handle; SANE_Status status; SANE_Word cap; SANE_Int myinfo = 0; DBG (DBG_io2, "sane_control_option: start: action = %s, option = %s (%d)\n", (action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_SET_VALUE) ? "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->opt[option].name, option); if (info) *info = 0; /* do checks before trying to apply action */ if (s->scanning) { DBG (DBG_warn, "sane_control_option: don't call this function while " "scanning (option = %s (%d))\n", s->opt[option].name, option); return SANE_STATUS_DEVICE_BUSY; } /* option must be within existing range */ if (option >= NUM_OPTIONS || option < 0) { DBG (DBG_warn, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", option); return SANE_STATUS_INVAL; } /* don't access an inactive option */ cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (DBG_warn, "sane_control_option: option %d is inactive\n", option); return SANE_STATUS_INVAL; } /* now checks have been done, apply action */ switch (action) { case SANE_ACTION_GET_VALUE: status = get_option_value (s, option, val); break; case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_warn, "sane_control_option: option %d is not settable\n", option); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } /* return immediatly if no change */ if (s->opt[option].type == SANE_TYPE_INT && *(SANE_Word *) val == s->val[option].w) { status = SANE_STATUS_GOOD; } else { /* apply change */ status = set_option_value (s, option, val, &myinfo); } break; case SANE_ACTION_SET_AUTO: /* sets automatic values */ if (!(cap & SANE_CAP_AUTOMATIC)) { DBG (DBG_warn, "sane_control_option: option %d is not autosettable\n", option); return SANE_STATUS_INVAL; } status = set_automatic_value (s, option, &myinfo); break; default: DBG (DBG_error, "sane_control_option: invalid action %d\n", action); status = SANE_STATUS_INVAL; break; } if (info) *info = myinfo; DBG (DBG_io2, "sane_control_option: exit\n"); return status; } /** * returns the name of the sensor * @param sensor sensor numnber * @return string holding the name of the sensor */ static char *sensor_name (int sensor) { switch (sensor) { case SENSOR_TYPE_BARE: return "SENSOR_TYPE_BARE"; case SENSOR_TYPE_XPA: return "SENSOR_TYPE_XPA"; case SENSOR_TYPE_4400: return "SENSOR_TYPE_4400"; case SENSOR_TYPE_4400_BARE: return "SENSOR_TYPE_4400_BARE"; default: return "BOGUS"; } } /** * Called by SANE when a page acquisition operation is to be started. * @param handle opaque handle to a frontend session * @return SANE_STATUS_GOOD on success, SANE_STATUS_BUSY if the device is * in use by another session or SANE_STATUS_WARMING_UP if the device is * warming up. In this case the fronted as to call sane_start again until * warming up is done. Any other values returned are error status. */ SANE_Status sane_start (SANE_Handle handle) { struct Rts8891_Session *session = handle; int light, mode; struct Rts8891_Device *dev = session->dev; SANE_Status status; SANE_Bool changed; #ifdef HAVE_SYS_TIME_H struct timeval current; #endif DBG (DBG_proc, "sane_start: start\n"); /* if already scanning, tell we're busy */ if (session->scanning == SANE_TRUE) { DBG (DBG_warn, "sane_start: device is already scanning\n"); return SANE_STATUS_DEVICE_BUSY; } /* claim the interface reserve device */ if (dev->conf.allowsharing == SANE_TRUE) { status = sanei_usb_claim_interface (dev->devnum, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "sane_start: cannot claim usb interface\n"); return SANE_STATUS_DEVICE_BUSY; } } /* check if we need warming-up */ sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs); if ((dev->regs[0x8e] & 0x60) != 0x60) { DBG (DBG_info, "sane_start: lamp needs warming (0x%02x)\n", dev->regs[0x8e]); dev->needs_warming = SANE_TRUE; #ifdef HAVE_SYS_TIME_H dev->start_time.tv_sec = current.tv_sec; dev->last_scan.tv_sec = current.tv_sec; #endif } #ifdef HAVE_SYS_TIME_H /* if last scan time is more than 10 minutes ago, scanner also needs * warming-up */ gettimeofday (¤t, NULL); if ((current.tv_sec - dev->last_scan.tv_sec) / 60 > 10) { DBG (DBG_info, "sane_start: more than 10 minutes without scanning, lamp needs warming\n"); dev->needs_warming = SANE_TRUE; dev->start_time.tv_sec = current.tv_sec; dev->last_scan.tv_sec = current.tv_sec; } #endif /* if parking, wait for head to stop */ if(dev->parking==SANE_TRUE) { rts8891_wait_for_home (dev, dev->regs); } /* reinit registers to start values */ rts8891_set_default_regs (dev->regs); /* step 0: light up */ init_lamp (dev); /* do warming up if needed: just detected or at sane_open() */ if (dev->needs_warming == SANE_TRUE) { DBG (DBG_info, "sane_start: warming lamp ...\n"); #ifdef HAVE_SYS_TIME_H /* check if current time is >15s after warming-up start */ gettimeofday (¤t, NULL); if ((current.tv_sec - dev->start_time.tv_sec) < 15) { #ifdef SANE_STATUS_WARMING_UP if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } return SANE_STATUS_WARMING_UP; #else DBG (DBG_info, "sane_start: waiting to let lamp get warm enough ...\n"); sleep (15 - (current.tv_sec - dev->start_time.tv_sec)); #endif } #else DBG (DBG_info, "sane_start: waiting 15s to let lamp get warm enough ...\n"); sleep (15); #endif } dev->needs_warming = SANE_FALSE; /* restore default brightness */ dev->regs[LAMP_BRIGHT_REG] = 0xA7; sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, dev->regs + LAMP_BRIGHT_REG); DBG (DBG_info, "sane_start: sensor initial type is %s (%d)\n", sensor_name (dev->sensor), dev->sensor); /* step 1: locate scan area by doing a scan, then goto calibration area */ /* we also detect if the sensor type is inadequate and then change it */ do { changed = SANE_FALSE; status = find_origin (dev, &changed); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed to find origin!\n"); return status; } /* in case find_origin detected we need to change sensor */ if (changed) { /* for a sensor 'pair', we switch */ switch (dev->sensor) { case SENSOR_TYPE_BARE: DBG (DBG_info, "sane_start: sensor changed to type 'SENSOR_TYPE_XPA'!\n"); dev->sensor = SENSOR_TYPE_XPA; break; case SENSOR_TYPE_XPA: DBG (DBG_info, "sane_start: sensor changed to type 'SENSOR_TYPE_BARE'!\n"); dev->sensor = SENSOR_TYPE_BARE; break; case SENSOR_TYPE_4400: DBG (DBG_info, "sane_start: sensor changed to type '4400 SENSOR_TYPE_4400_BARE'!\n"); dev->sensor = SENSOR_TYPE_4400_BARE; break; case SENSOR_TYPE_4400_BARE: DBG (DBG_info, "sane_start: sensor changed to type 'SENSOR_TYPE_4400'!\n"); dev->sensor = SENSOR_TYPE_4400; break; } } } while (changed); /* light source to use */ switch (dev->sensor) { case SENSOR_TYPE_XPA: light = 0x3f; mode = 0x20; break; case SENSOR_TYPE_BARE: light = 0x3b; mode = 0x20; break; case SENSOR_TYPE_4400: case SENSOR_TYPE_4400_BARE: light = 0x2a; mode = 0x10; break; default: light = 0x3b; mode = 0x20; break; } DBG (DBG_info, "sane_start: sensor final type is %s (%d)\n", sensor_name (dev->sensor), dev->sensor); DBG (DBG_info, "sane_start: mode=0x%02x, light=0x%02x\n", mode, light); /* step 2: dark calibration */ status = dark_calibration (dev, mode, light); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed to do dark calibration!\n"); return status; } /* step 3: find left margin */ status = find_margin (dev); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed find left margin!\n"); return status; } /* restore brightness */ dev->regs[LAMP_BRIGHT_REG] = 0xA7; sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, dev->regs + LAMP_BRIGHT_REG); /* step 4: gain calibration */ status = gain_calibration (dev, mode, light); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed to do gain calibration!\n"); return status; } /* step 5: fine offset calibration */ status = offset_calibration (dev, mode, light); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed to do offset calibration!\n"); return status; } /* we compute all the scan parameters so that */ /* we will be able to set up the registers correctly */ compute_parameters (session); /* allocate buffer and compute start pointer */ if (dev->scanned_data != NULL) free (dev->scanned_data); dev->scanned_data = (SANE_Byte *) malloc (dev->data_size + dev->lds_max + dev->ripple); dev->start = dev->scanned_data + dev->lds_max + dev->ripple; /* computes data end pointer */ dev->end = dev->start + dev->data_size; /* no bytes sent yet to frontend */ session->sent = 0; sanei_rts88xx_set_offset (dev->regs, dev->red_offset, dev->green_offset, dev->blue_offset); sanei_rts88xx_set_gain (dev->regs, dev->red_gain, dev->green_gain, dev->blue_gain); /* step 6: shading calibration */ status = shading_calibration (dev, session->params.format == SANE_FRAME_RGB || session->emulated_gray == SANE_TRUE, mode, light); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed to do shading calibration!\n"); return status; } /* step 6b: move at dev->model->min_ydpi to target area */ if (dev->ydpi > dev->model->min_ydpi && (dev->ystart * MOVE_DPI) / dev->ydpi > 150) { status = move_to_scan_area (session); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed to move to scan area!\n"); return status; } } /* step 7: effective scan start */ /* build register set and send it */ status = write_scan_registers (session); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed to write scan registers!\n"); return status; } /* step 8: send calibration data */ status = send_calibration_data (session); if (status != SANE_STATUS_GOOD) { if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_error, "sane_start: failed to send calibration data!\n"); return status; } /* commit the scan */ /* TODO send_calibration seems to embbed its commit */ sanei_rts88xx_cancel (dev->devnum); sanei_rts88xx_write_control (dev->devnum, 0x08); status = sanei_rts88xx_write_control (dev->devnum, 0x08); session->scanning = SANE_TRUE; DBG (DBG_proc, "sane_start: exit\n"); return status; } /** * This function computes two set of parameters. The one for the SANE's standard * and the other for the hardware. Among these parameters are the bit depth, total * number of lines, total number of columns, extra line to read for data reordering... */ static SANE_Status compute_parameters (Rts8891_Session * session) { Rts8891_Device *dev = session->dev; SANE_Int dpi; /* dpi for scan */ SANE_String mode; SANE_Status status = SANE_STATUS_GOOD; SANE_Int yshift; SANE_Int xshift; int tl_x, tl_y, br_x, br_y; mode = session->val[OPT_MODE].s; dpi = session->val[OPT_RESOLUTION].w; /* scan coordinates */ tl_x = SANE_UNFIX (session->val[OPT_TL_X].w); tl_y = SANE_UNFIX (session->val[OPT_TL_Y].w); br_x = SANE_UNFIX (session->val[OPT_BR_X].w); br_y = SANE_UNFIX (session->val[OPT_BR_Y].w); /* only single pass scanning supported */ session->params.last_frame = SANE_TRUE; session->emulated_gray = SANE_FALSE; /* gray modes */ dev->threshold = (255 * SANE_UNFIX (session->val[OPT_THRESHOLD].w)) / 100; if (strcmp (mode, GRAY_MODE) == 0 || strcmp (mode, LINEART_MODE) == 0) { session->params.format = SANE_FRAME_GRAY; if (dev->model->flags & RTS8891_FLAG_EMULATED_GRAY_MODE) session->emulated_gray = SANE_TRUE; } else { /* Color */ session->params.format = SANE_FRAME_RGB; } /* SANE level values */ session->params.lines = ((br_y - tl_y) * dpi) / MM_PER_INCH; if (session->params.lines == 0) session->params.lines = 1; session->params.pixels_per_line = ((br_x - tl_x) * dpi) / MM_PER_INCH; if (session->params.pixels_per_line == 0) session->params.pixels_per_line = 1; DBG (DBG_data, "compute_parameters: pixels_per_line =%d\n", session->params.pixels_per_line); if (strcmp (mode, LINEART_MODE) == 0) { session->params.depth = 1; /* in lineart, having pixels multiple of 8 avoids a costly test */ /* at each bit to see we must go to the next byte */ /* TODO : implement this requirement in sane_control_option */ session->params.pixels_per_line = ((session->params.pixels_per_line + 7) / 8) * 8; } else session->params.depth = 8; /* width needs to be even */ if (session->params.pixels_per_line & 1) session->params.pixels_per_line++; /* Hardware settings : they can differ from the ones at SANE level */ /* for instance the effective DPI used by a sensor may be higher */ /* than the one needed for the SANE scan parameters */ dev->lines = session->params.lines; dev->pixels = session->params.pixels_per_line; /* motor and sensor DPI */ dev->xdpi = dpi; dev->ydpi = dpi; /* handle bounds of motor's dpi range */ if (dev->ydpi > dev->model->max_ydpi) { dev->ydpi = dev->model->max_ydpi; dev->lines = (dev->lines * dev->model->max_ydpi) / dpi; if (dev->lines == 0) dev->lines = 1; /* round number of lines */ session->params.lines = (session->params.lines / dev->lines) * dev->lines; if (session->params.lines == 0) session->params.lines = 1; } if (dev->ydpi < dev->model->min_ydpi) { dev->ydpi = dev->model->min_ydpi; dev->lines = (dev->lines * dev->model->min_ydpi) / dpi; } /* hardware values */ dev->xstart = ((SANE_UNFIX (dev->model->x_offset) + tl_x) * dev->xdpi) / MM_PER_INCH; dev->ystart = ((SANE_UNFIX (dev->model->y_offset) + tl_y) * dev->ydpi) / MM_PER_INCH; /* xstart needs to be even */ if (dev->xstart & 1) dev->xstart++; /* computes bytes per line */ session->params.bytes_per_line = session->params.pixels_per_line; dev->bytes_per_line = dev->pixels; if (session->params.format == SANE_FRAME_RGB || session->emulated_gray == SANE_TRUE) { if (session->emulated_gray != SANE_TRUE) { session->params.bytes_per_line *= 3; } dev->bytes_per_line *= 3; } session->to_send = session->params.bytes_per_line * session->params.lines; /* in lineart mode we adjust bytes_per_line needed by frontend */ /* we do that here because we needed sent/to_send to be as if */ /* there was no lineart */ if (session->params.depth == 1) { session->params.bytes_per_line = (session->params.bytes_per_line + 7) / 8; } /* compute how many extra bytes we need to reorder data */ dev->ripple = 0; if (session->params.format == SANE_FRAME_RGB || session->emulated_gray == SANE_TRUE) { dev->lds_r = ((dev->model->ld_shift_r * dev->ydpi) / dev->model->max_ydpi) * dev->bytes_per_line; dev->lds_g = ((dev->model->ld_shift_g * dev->ydpi) / dev->model->max_ydpi) * dev->bytes_per_line; dev->lds_b = ((dev->model->ld_shift_b * dev->ydpi) / dev->model->max_ydpi) * dev->bytes_per_line; if (dev->xdpi == dev->model->max_xdpi) { dev->ripple = 2 * dev->bytes_per_line; } } else { dev->lds_r = 0; dev->lds_g = 0; dev->lds_b = 0; } /* pick max lds value */ dev->lds_max = dev->lds_r; if (dev->lds_g > dev->lds_max) dev->lds_max = dev->lds_g; if (dev->lds_b > dev->lds_max) dev->lds_max = dev->lds_b; /* since the extra lines for reordering are before data */ /* we substract lds_max */ dev->lds_r -= dev->lds_max; dev->lds_g -= dev->lds_max; dev->lds_b -= dev->lds_max; /* we need to add extra line to handle line distance reordering */ /* highest correction value is the blue one for our case */ /* decrease y start to take these extra lines into account */ dev->lines += (dev->lds_max + dev->ripple) / dev->bytes_per_line; /* shading calibration is allways 66 lines regardless of ydpi, so */ /* we take this into account to compute ystart */ if (dev->ydpi > dev->model->min_ydpi) { /* no that clean, but works ... */ switch (dev->ydpi) { case 300: yshift = 0; break; case 600: yshift = 33; break; default: yshift = 0; } dev->ystart += yshift; } dev->ystart -= (dev->lds_max + dev->ripple) / dev->bytes_per_line; /* 1200 and 600 dpi scans seems to have other timings that * need their own xstart */ /* no that clean, but works ... */ switch (dev->xdpi) { case 600: xshift = -38; break; case 1200: xshift = -76; break; default: xshift = 0; } dev->xstart += xshift; dev->read = 0; dev->to_read = dev->lines * dev->bytes_per_line; /* compute best size for scanned data buffer */ /* we must have a round number of lines, with */ /* enough space to handle line distance shift */ if (dev->xdpi < dev->model->max_ydpi) { dev->data_size = (PREFERED_BUFFER_SIZE / dev->bytes_per_line) * (dev->bytes_per_line); } else { dev->data_size = (((PREFERED_BUFFER_SIZE / 2) - dev->lds_max - dev->ripple) / dev->bytes_per_line) * dev->bytes_per_line; } /* 32 lines minimum in buffer */ if (dev->data_size < 32 * dev->bytes_per_line) dev->data_size = 32 * dev->bytes_per_line; /* buffer must be smaller than total amount to read from session */ if (dev->data_size > dev->to_read) dev->data_size = dev->to_read; DBG (DBG_data, "compute_parameters: bytes_per_line =%d\n", session->params.bytes_per_line); DBG (DBG_data, "compute_parameters: depth =%d\n", session->params.depth); DBG (DBG_data, "compute_parameters: lines =%d\n", session->params.lines); DBG (DBG_data, "compute_parameters: pixels_per_line =%d\n", session->params.pixels_per_line); DBG (DBG_data, "compute_parameters: image size =%d\n", session->to_send); DBG (DBG_data, "compute_parameters: xstart =%d\n", dev->xstart); DBG (DBG_data, "compute_parameters: ystart =%d\n", dev->ystart); DBG (DBG_data, "compute_parameters: dev lines =%d\n", dev->lines); DBG (DBG_data, "compute_parameters: dev extra lines =%d\n", (dev->lds_max + dev->ripple) / dev->bytes_per_line); DBG (DBG_data, "compute_parameters: dev bytes per line=%d\n", dev->bytes_per_line); DBG (DBG_data, "compute_parameters: dev pixels =%d\n", dev->pixels); DBG (DBG_data, "compute_parameters: data size =%d\n", dev->data_size); DBG (DBG_data, "compute_parameters: to read =%d\n", dev->to_read); DBG (DBG_data, "compute_parameters: threshold =%d\n", dev->threshold); return status; } /** * Called by SANE to retrieve information about the type of data * that the current scan will return. * * From the SANE spec: * This function is used to obtain the current scan parameters. The * returned parameters are guaranteed to be accurate between the time * a scan has been started (sane_start() has been called) and the * completion of that request. Outside of that window, the returned * values are best-effort estimates of what the parameters will be * when sane_start() gets invoked. * * Calling this function before a scan has actually started allows, * for example, to get an estimate of how big the scanned image will * be. The parameters passed to this function are the handle of the * device for which the parameters should be obtained and a pointer * to a parameter structure. */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { SANE_Status status; struct Rts8891_Session *session = (struct Rts8891_Session *) handle; DBG (DBG_proc, "sane_get_parameters: start\n"); /* call parameters computing function */ status = compute_parameters (session); if (status == SANE_STATUS_GOOD && params) *params = session->params; DBG (DBG_proc, "sane_get_parameters: exit\n"); return status; } /** * Called by SANE to read data. * * From the SANE spec: * This function is used to read image data from the device * represented by handle h. Argument buf is a pointer to a memory * area that is at least maxlen bytes long. The number of bytes * returned is stored in *len. A backend must set this to zero when * the call fails (i.e., when a status other than SANE_STATUS_GOOD is * returned). * * When the call succeeds, the number of bytes returned can be * anywhere in the range from 0 to maxlen bytes. */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct Rts8891_Session *session; struct Rts8891_Device *dev; SANE_Status status; SANE_Int length; SANE_Int data_size; SANE_Byte val = 0; SANE_Int bit; DBG (DBG_proc, "sane_read: start\n"); DBG (DBG_io, "sane_read: up to %d bytes required by frontend\n", max_len); /* some sanity checks first to protect from would be buggy frontends */ if (!handle) { DBG (DBG_error, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } session = (struct Rts8891_Session *) handle; if (!session) { DBG (DBG_error, "sane_read: session is null!\n"); return SANE_STATUS_INVAL; } dev = session->dev; if (!buf) { DBG (DBG_error, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (!len) { DBG (DBG_error, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } /* no data read yet */ *len = 0; buf[*len] = 0; /* check if session is scanning */ if (!session->scanning) { DBG (DBG_warn, "sane_read: scan was cancelled, is over or has not been initiated yet\n"); return SANE_STATUS_CANCELLED; } /* check for EOF, must be done before any physical read */ if (session->sent >= session->to_send) { DBG (DBG_io, "sane_read: end of scan reached\n"); /* signal end of scanning */ session->scanning=SANE_FALSE; /* send asynchronous head parking command then return */ park_head (session->dev, SANE_FALSE); return SANE_STATUS_EOF; } dev->regs[LAMP_REG] = 0xad; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); /* byte length for high dpi mode */ length = (session->params.bytes_per_line * 8) / session->params.depth; /* checks if buffer has been pre filled with the extra data needed for */ /* line distance reordering */ if (dev->read == 0 && (session->params.format == SANE_FRAME_RGB || session->emulated_gray == SANE_TRUE)) { /* the data need if the size of the highest line distance shift */ /* we must only read what's needed */ data_size = dev->data_size + dev->lds_max + dev->ripple; if (dev->to_read - dev->read < data_size) data_size = dev->to_read - dev->read; status = read_data (session, dev->scanned_data, data_size); if (status == SANE_STATUS_DEVICE_BUSY) { DBG (DBG_io, "sane_read: no data currently available\n"); return SANE_STATUS_GOOD; } if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_read: failed to read data from scanner\n"); return status; } /* now buffer is filled with data and an extra amount for line reordering */ dev->current = dev->start; } /* if all buffer has been used, get the next block of data from scanner */ if (dev->read == 0 || dev->current >= dev->end) { /* effective buffer filling */ /* we must only read what's needed */ data_size = dev->data_size; if (dev->to_read - dev->read < data_size) data_size = dev->to_read - dev->read; status = read_data (session, dev->start, data_size); if (status == SANE_STATUS_DEVICE_BUSY) { DBG (DBG_io, "sane_read: no data currently available\n"); return SANE_STATUS_GOOD; } if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_read: failed to read data from scanner\n"); return status; } /* reset current pointer */ dev->current = dev->start; } dev->regs[LAMP_REG] = 0x8d; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); /* it seems there is no gray or lineart hardware mode for the rts8891 */ if (session->params.format == SANE_FRAME_GRAY && session->emulated_gray == SANE_FALSE) { DBG (DBG_error0, "sane_read: unimplemented native gray scanning\n"); return SANE_STATUS_INVAL; } else /* hardware data is 3 bytes/per pixels */ { /* we return as much data as possible from current buffer */ /* if buffer is smaller than what is asked, we only return */ /* here we have made sure there is something to read from data buffers */ /* data from scanner is in R,G,B format, but we have to cope with line */ /* distance correction. We also take care that motor resolution may be */ /* higher than the scan resolution asked for some modes. */ /* We also handle emulated color mode */ /* we loop until we reach max_len or end of data buffer */ /* or we sent what we advised to frontend */ while (dev->current < dev->end && *len < max_len && session->sent < session->to_send) { /* data is received in RGB format */ /* these switches are there to handle reads not aligned * on pixels that are allowed by the SANE standard */ if (dev->xdpi == dev->model->max_xdpi) { /* at max xdpi, data received is distorted and ydpi is half of xdpi */ if (session->emulated_gray == SANE_TRUE) { /* in emulated gray mode we are allways reading 3 bytes of raw data */ /* at a time */ switch (((session->sent * 3) % dev->bytes_per_line) % 6) { case 0: case 1: case 2: val = dev->current[dev->lds_g]; break; case 3: case 4: case 5: val = dev->current[dev->lds_g - dev->ripple]; break; } if (session->params.depth == 1) { bit = 7 - (session->sent) % 8; if (val <= dev->threshold) { buf[*len] |= 1 << bit; } if (bit == 0) { (*len)++; buf[*len] = 0; } } else { buf[*len] = val; (*len)++; } session->sent++; dev->current += 3; } else { switch ((session->sent % dev->bytes_per_line) % 6) { case 0: buf[*len] = dev->current[dev->lds_r]; break; case 1: buf[*len] = dev->current[dev->lds_g]; break; case 2: buf[*len] = dev->current[dev->lds_b]; break; case 3: buf[*len] = dev->current[dev->lds_r - dev->ripple]; break; case 4: buf[*len] = dev->current[dev->lds_g - dev->ripple]; break; case 5: buf[*len] = dev->current[dev->lds_b - dev->ripple]; break; } (*len)++; session->sent++; dev->current++; } /* we currently double lines to have match xdpy */ /* so we logically rewind for each odd line */ /* we test at start of a scanned picture line */ if (((session->sent / length) % 2 == 1) && (session->sent % length == 0)) { DBG (DBG_io, "sane_read: rewind by %d bytes after %d bytes sent\n", dev->bytes_per_line, session->sent); dev->current -= dev->bytes_per_line; } } else if (dev->ydpi == session->val[OPT_RESOLUTION].w) { if (session->emulated_gray == SANE_TRUE) { /* in emulated gray mode we are allways reading 3 bytes of raw data */ /* at a time, so we know where we are */ val = dev->current[dev->lds_g]; if (session->params.depth == 1) { bit = 7 - (session->sent) % 8; if (val <= dev->threshold) { buf[*len] |= 1 << bit; } else { buf[*len] &= ~(1 << bit); } if (bit == 0) { (*len)++; } } else { buf[*len] = val; (*len)++; } session->sent++; dev->current += 3; } else { switch ((dev->current - dev->start) % 3) { case 0: buf[*len] = dev->current[dev->lds_r]; break; case 1: buf[*len] = dev->current[dev->lds_g]; break; case 2: buf[*len] = dev->current[dev->lds_b]; break; } (*len)++; session->sent++; dev->current++; } } else { /* we currently handle ydi=2*dpi */ if (session->emulated_gray == SANE_TRUE) { /* in emulated gray mode we are allways reading 3 bytes of raw data */ /* at a time, so we know where we are */ val = (dev->current[dev->lds_g] + dev->current[dev->lds_g + dev->bytes_per_line]) / 2; if (session->params.depth == 1) { bit = 7 - (session->sent) % 8; if (val <= dev->threshold) { buf[*len] |= 1 << bit; } else { buf[*len] &= ~(1 << bit); } if (bit == 0) { (*len)++; } } else { buf[*len] = val; (*len)++; } dev->current += 3; } else { switch ((dev->current - dev->start) % 3) { case 0: buf[*len] = (dev->current[dev->lds_r] + dev->current[dev->lds_r + dev->bytes_per_line]) / 2; break; case 1: buf[*len] = (dev->current[dev->lds_g] + dev->current[dev->lds_g + dev->bytes_per_line]) / 2; break; case 2: buf[*len] = (dev->current[dev->lds_b] + dev->current[dev->lds_b + dev->bytes_per_line]) / 2; break; } (*len)++; dev->current++; } session->sent++; /* at the end of each line, we must count another one because */ /* 2 lines are used to produce one */ if ((dev->current - dev->start) % dev->bytes_per_line == 0) dev->current += dev->bytes_per_line; } } } /* if we exhausted data buffer, we prepare for the next read */ /* in color mode, we need to copy the remainder of the */ /* buffer because of line distance handling, when blue data */ /* is exhausted, read and green haven't been fully read yet */ if (dev->current >= dev->end && (session->params.format == SANE_FRAME_RGB || session->emulated_gray == SANE_TRUE)) { memcpy (dev->scanned_data, dev->end - (dev->lds_max + dev->ripple), dev->lds_max + dev->ripple); } status = SANE_STATUS_GOOD; DBG (DBG_io, "sane_read: sent %d bytes to frontend\n", *len); DBG (DBG_proc, "sane_read: exit\n"); return status; } /** * Cancels a scan. * * From the SANE spec: * This function is used to immediately or as quickly as possible * cancel the currently pending operation of the device represented by * handle h. This function can be called at any time (as long as * handle h is a valid handle) but usually affects long-running * operations only (such as image is acquisition). It is safe to call * this function asynchronously (e.g., from within a signal handler). * It is important to note that completion of this operaton does not * imply that the currently pending operation has been cancelled. It * only guarantees that cancellation has been initiated. Cancellation * completes only when the cancelled call returns (typically with a * status value of SANE_STATUS_CANCELLED). Since the SANE API does * not require any other operations to be re-entrant, this implies * that a frontend must not call any other operation until the * cancelled operation has returned. */ void sane_cancel (SANE_Handle handle) { Rts8891_Session *session = handle; struct Rts8891_Device *dev = session->dev; #ifdef HAVE_SYS_TIME_H struct timeval current; #endif DBG (DBG_proc, "sane_cancel: start\n"); #ifdef HAVE_SYS_TIME_H /* store last scan time for the device */ gettimeofday (¤t, NULL); dev->last_scan.tv_sec = current.tv_sec; #endif /* if scanning, abort and park head */ if (session->scanning == SANE_TRUE) { /* canceling while all data hasn't bee read */ if (dev->read < dev->to_read) { sanei_rts88xx_cancel (dev->devnum); usleep (500000); sanei_rts88xx_cancel (dev->devnum); } session->scanning = SANE_FALSE; /* head parking */ if (park_head (dev, SANE_FALSE) != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_cancel: failed to park head!\n"); } } /* free ressources used by scanning */ if (dev->scanned_data != NULL) { free (dev->scanned_data); dev->scanned_data = NULL; } if (dev->shading_data != NULL) { free (dev->shading_data); dev->shading_data = NULL; } /* release the interface to allow device sharing */ if (dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (dev->devnum, 0); } DBG (DBG_proc, "sane_cancel: exit\n"); } /** * Ends use of the session. * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is * presently active, a call to sane_cancel() is performed first. After * this function returns, handle h must not be used anymore. * * Handle resources are free'd before disposing the handle. But devices * resources must not be mdofied, since it could be used or reused until * sane_exit() is called. */ void sane_close (SANE_Handle handle) { Rts8891_Session *prev, *session; Rts8891_Device *dev; int i; DBG (DBG_proc, "sane_close: start\n"); /* remove handle from list of open handles: */ prev = NULL; for (session = first_handle; session; session = session->next) { if (session == handle) break; prev = session; } if (!session) { DBG (DBG_error, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } dev=session->dev; /* cancel any active scan */ if (session->scanning == SANE_TRUE) { sane_cancel (handle); } /* if head is parking, wait for completion */ if(dev->parking==SANE_TRUE) { rts8891_wait_for_home (dev, dev->regs); } set_lamp_brightness (dev, 0); if (prev) prev->next = session->next; else first_handle = session->next; /* switch off lamp and close usb */ if (dev->conf.allowsharing == SANE_TRUE) { SANE_Status status = sanei_usb_claim_interface (dev->devnum, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "sane_close: cannot claim usb interface: %s\n", sane_strstatus(status)); DBG (DBG_warn, "sane_close: continuing anyway\n"); } } set_lamp_state (session, 0); sanei_usb_close (dev->devnum); /* free per session data */ if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR].wa) free (session->val[OPT_GAMMA_VECTOR].wa); if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_R].wa) free (session->val[OPT_GAMMA_VECTOR_R].wa); if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_G].wa) free (session->val[OPT_GAMMA_VECTOR_G].wa); if (session->dev->model->gamma != session->val[OPT_GAMMA_VECTOR_B].wa) free (session->val[OPT_GAMMA_VECTOR_B].wa); free (session->val[OPT_MODE].s); free ((void *) session->opt[OPT_RESOLUTION].constraint.word_list); for (i = OPT_BUTTON_1; i <= OPT_BUTTON_11; i++) { free ((void *) session->opt[i].name); free ((void *) session->opt[i].title); } free (session); DBG (DBG_proc, "sane_close: exit\n"); } /** * Terminates the backend. * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be * open (it is recommended to close device handles explicitly through * a call to sane_close(), but backends are required to release all * resources upon a call to this function). After this function * returns, no function other than sane_init() may be called * (regardless of the status value returned by sane_exit(). Neglecting * to call this function may result in some resources not being * released properly. */ void sane_exit (void) { struct Rts8891_Session *session, *next; struct Rts8891_Device *dev, *nextdev; int i; DBG (DBG_proc, "sane_exit: start\n"); /* free session structs */ for (session = first_handle; session; session = next) { next = session->next; sane_close ((SANE_Handle *) session); free (session); } first_handle = NULL; /* free devices structs */ for (dev = first_device; dev; dev = nextdev) { nextdev = dev->next; free (dev->file_name); free (dev); } first_device = NULL; /* now list of devices */ if (devlist) { for (i = 0; i < num_devices; i++) { free ((SANE_Device *) devlist[i]); } free (devlist); devlist = NULL; } num_devices = 0; DBG (DBG_proc, "sane_exit: exit\n"); } /** This function tries to find plugged relevant devices */ static SANE_Status probe_rts8891_devices (void) { /**> configuration structure used during attach */ SANEI_Config config; /**> list of configuration options */ SANE_Option_Descriptor *options[NUM_CFG_OPTIONS]; /**> placeholders pointers for option values */ void *values[NUM_CFG_OPTIONS]; int i; SANE_Status status; DBG (DBG_proc, "probe_rts8891_devices: start\n"); /* sharing is off by default and no model option */ rtscfg.allowsharing = SANE_FALSE; rtscfg.modelnumber = -1; rtscfg.sensornumber = -1; /* initialize configuration options */ options[CFG_MODEL_NUMBER] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_MODEL_NUMBER]->name = "modelnumber"; options[CFG_MODEL_NUMBER]->desc = "user provided scanner's internal model number"; options[CFG_MODEL_NUMBER]->type = SANE_TYPE_INT; options[CFG_MODEL_NUMBER]->unit = SANE_UNIT_NONE; options[CFG_MODEL_NUMBER]->size = sizeof (SANE_Word); options[CFG_MODEL_NUMBER]->cap = SANE_CAP_SOFT_SELECT; options[CFG_MODEL_NUMBER]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_MODEL_NUMBER]->constraint.range = &model_range; values[CFG_MODEL_NUMBER] = &rtscfg.modelnumber; options[CFG_ALLOW_SHARING] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_ALLOW_SHARING]->name = "allowsharing"; options[CFG_ALLOW_SHARING]->desc = "allow sharing of the scanner by several frontends"; options[CFG_ALLOW_SHARING]->type = SANE_TYPE_BOOL; options[CFG_ALLOW_SHARING]->unit = SANE_UNIT_NONE; options[CFG_ALLOW_SHARING]->size = sizeof (SANE_Bool); options[CFG_ALLOW_SHARING]->cap = SANE_CAP_SOFT_SELECT; options[CFG_ALLOW_SHARING]->constraint_type = SANE_CONSTRAINT_NONE; values[CFG_ALLOW_SHARING] = &rtscfg.allowsharing; /* sensor type override */ options[CFG_SENSOR_NUMBER] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_SENSOR_NUMBER]->name = "sensornumber"; options[CFG_SENSOR_NUMBER]->desc = "user provided scanner's internal sensor number"; options[CFG_SENSOR_NUMBER]->type = SANE_TYPE_INT; options[CFG_SENSOR_NUMBER]->unit = SANE_UNIT_NONE; options[CFG_SENSOR_NUMBER]->size = sizeof (SANE_Word); options[CFG_SENSOR_NUMBER]->cap = SANE_CAP_SOFT_SELECT; options[CFG_SENSOR_NUMBER]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_SENSOR_NUMBER]->constraint.range = &sensor_range; values[CFG_SENSOR_NUMBER] = &rtscfg.sensornumber; /* set configuration options structure */ config.descriptors = options; config.values = values; config.count = NUM_CFG_OPTIONS; /* init usb use */ sanei_usb_init (); /* generic configure and attach function */ status = sanei_configure_attach (RTS8891_CONFIG_FILE, &config, config_attach_rts8891); /* free allocated options */ for (i = 0; i < NUM_CFG_OPTIONS; i++) { free (options[i]); } DBG (DBG_proc, "probe_rts8891_devices: end\n"); return status; } /** This function is called by sanei_configure_attach to try * to attach the backend to a device specified by the configuration file. * * @param config configuration structure filled with values read * from configuration file * @param devname name of the device to try to attach to, it is * the unprocessed line of the configuration file * * @return status SANE_STATUS_GOOD if no errors (even if no matching * devices found) * SANE_STATUS_INVAL in case of error */ static SANE_Status config_attach_rts8891 (SANEI_Config * config, const char *devname) { /* currently, the config is a global variable so config is useless here */ /* the correct thing would be to have a generic sanei_attach_matching_devices * using an attach function with a config parameter */ if(config==NULL) { return SANE_STATUS_INVAL; } /* the devname has been processed and is ready to be used * directly. Since the backend is an USB only one, we can * call sanei_usb_attach_matching_devices straight */ sanei_usb_attach_matching_devices (devname, attach_rts8891); return SANE_STATUS_GOOD; } /** * The attach tries to open the given usb device and match it * with devices handled by the backend. The configuration parameter * contains the values of the allready parsed configuration options * from the conf file. * @param config configuration structure filled with values read * from configuration file * @param devicename name of the device to try to attach to, it is * the unprocessed line of the configuration file * * @return status SANE_STATUS_GOOD if no errors (even if no matching * devices found) * SANE_STATUS_NOM_MEM if there isn't enough memory to allocate the * device structure * SANE_STATUS_UNSUPPORTED if the device if unknown by the backend * SANE_STATUS_INVAL in case of other error */ static SANE_Status attach_rts8891 (const char *devicename) { struct Rts8891_Device *device; SANE_Int dn, vendor, product; SANE_Status status; DBG (DBG_proc, "attach_rts8891(%s): start\n", devicename); /* search if we already have it attached */ for (device = first_device; device; device = device->next) { if (strcmp (device->file_name, devicename) == 0) { DBG (DBG_warn, "attach_rts8891: device already attached (is ok)!\n"); DBG (DBG_proc, "attach_rts8891: exit\n"); return SANE_STATUS_GOOD; } } /* open usb device */ status = sanei_usb_open (devicename, &dn); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "attach_rts8891: couldn't open device `%s': %s\n", devicename, sane_strstatus (status)); return status; } else { DBG (DBG_info, "attach_rts8891: device `%s' successfully opened\n", devicename); } /* get vendor and product id */ status = sanei_usb_get_vendor_product (dn, &vendor, &product); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "attach_rts8891: couldn't get vendor and product ids of device `%s': %s\n", devicename, sane_strstatus (status)); sanei_usb_close (dn); DBG (DBG_proc, "attach_rts8891: exit\n"); return status; } sanei_usb_close (dn); /* get the index of the device in the device description table */ /* if the value is provided by configuration option, just use it */ if (rtscfg.modelnumber < 0) { /* walk the list of devices to find matching entry */ dn = 0; while ((vendor != rts8891_usb_device_list[dn].vendor_id || product != rts8891_usb_device_list[dn].product_id) && (rts8891_usb_device_list[dn].vendor_id != 0)) dn++; /* if we reach the list termination entry, the device is unknown */ if (rts8891_usb_device_list[dn].vendor_id == 0) { DBG (DBG_info, "attach_rts8891: unknown device `%s': 0x%04x:0x%04x\n", devicename, vendor, product); DBG (DBG_proc, "attach_rts8891: exit\n"); return SANE_STATUS_UNSUPPORTED; } } else { /* user provided value */ dn = rtscfg.modelnumber; } /* allocate device struct */ device = malloc (sizeof (*device)); if (device == NULL) { return SANE_STATUS_NO_MEM; } memset (device, 0, sizeof (*device)); /* struct describing low lvel device */ device->model = rts8891_usb_device_list[dn].model; /* name of the device */ device->file_name = strdup (devicename); DBG (DBG_info, "attach_rts8891: found %s %s %s at %s\n", device->model->vendor, device->model->product, device->model->type, device->file_name); /* we insert new device at start of the chained list */ /* head of the list becomes the next, and start is replaced */ /* with the new session struct */ num_devices++; device->next = first_device; first_device = device; device->reg_count = 244; /* intialization is done at sane_open */ device->initialized = SANE_FALSE; device->needs_warming = SANE_TRUE; device->parking = SANE_FALSE; #ifdef HAVE_SYS_TIME_H device->last_scan.tv_sec = 0; device->start_time.tv_sec = 0; #endif /* in case autodection au sensor doesn't work, use the given override */ device->sensor = rtscfg.sensornumber; /* copy configuration settings to device */ device->conf.modelnumber = dn; device->conf.allowsharing = rtscfg.allowsharing; DBG (DBG_proc, "attach_rts8891: exit\n"); return SANE_STATUS_GOOD; } /* set initial value for the scanning options */ static SANE_Status init_options (struct Rts8891_Session *session) { SANE_Int option, count, i, min, idx; SANE_Word *dpi_list; Rts8891_Model *model = session->dev->model; DBG (DBG_proc, "init_options: start\n"); /* we first initialize each options with a default value */ memset (session->opt, 0, sizeof (session->opt)); memset (session->val, 0, sizeof (session->val)); for (option = 0; option < NUM_OPTIONS; option++) { session->opt[option].size = sizeof (SANE_Word); session->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* we set up all the options listed in the Rts8891_Option enum */ /* last option / end of list marker */ session->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; session->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; session->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; session->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; session->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; session->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Standard" group: */ session->opt[OPT_STANDARD_GROUP].title = SANE_TITLE_STANDARD; session->opt[OPT_STANDARD_GROUP].name = SANE_NAME_STANDARD; session->opt[OPT_STANDARD_GROUP].desc = SANE_DESC_STANDARD; session->opt[OPT_STANDARD_GROUP].type = SANE_TYPE_GROUP; session->opt[OPT_STANDARD_GROUP].size = 0; session->opt[OPT_STANDARD_GROUP].cap = 0; session->opt[OPT_STANDARD_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ session->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; session->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; session->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; session->opt[OPT_MODE].type = SANE_TYPE_STRING; session->opt[OPT_MODE].cap |= SANE_CAP_AUTOMATIC; session->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; session->opt[OPT_MODE].size = max_string_size (mode_list); session->opt[OPT_MODE].constraint.string_list = mode_list; session->val[OPT_MODE].s = strdup (mode_list[0]); /* preview */ session->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; session->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; session->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; session->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; session->opt[OPT_PREVIEW].cap |= SANE_CAP_AUTOMATIC; session->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE; session->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; session->val[OPT_PREVIEW].w = SANE_FALSE; /* build resolution list */ /* TODO we build it from xdpi, one could prefer building it from * ydpi list, or even allow for independent X and Y dpi (with 2 options then) */ for (count = 0; model->xdpi_values[count] != 0; count++); dpi_list = malloc ((count + 1) * sizeof (SANE_Word)); if (!dpi_list) return SANE_STATUS_NO_MEM; dpi_list[0] = count; for (count = 0; model->xdpi_values[count] != 0; count++) dpi_list[count + 1] = model->xdpi_values[count]; session->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; session->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; session->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; session->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; session->opt[OPT_RESOLUTION].cap |= SANE_CAP_AUTOMATIC; session->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; session->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; session->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; /* initial value is lowest available dpi */ min = 65536; for (i = 1; i < count; i++) { if (dpi_list[i] < min) min = dpi_list[i]; } session->val[OPT_RESOLUTION].w = min; /* "Geometry" group: */ session->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY; session->opt[OPT_GEOMETRY_GROUP].name = SANE_NAME_GEOMETRY; session->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY; session->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; session->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; session->opt[OPT_GEOMETRY_GROUP].size = 0; session->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* adapt the constraint range to the detected model */ x_range.max = model->x_size; y_range.max = model->y_size; /* top-left x */ session->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; session->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; session->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; session->opt[OPT_TL_X].type = SANE_TYPE_FIXED; session->opt[OPT_TL_X].cap |= SANE_CAP_AUTOMATIC; session->opt[OPT_TL_X].unit = SANE_UNIT_MM; session->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_TL_X].constraint.range = &x_range; session->val[OPT_TL_X].w = 0; /* top-left y */ session->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; session->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; session->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; session->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; session->opt[OPT_TL_Y].cap |= SANE_CAP_AUTOMATIC; session->opt[OPT_TL_Y].unit = SANE_UNIT_MM; session->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_TL_Y].constraint.range = &y_range; session->val[OPT_TL_Y].w = 0; /* bottom-right x */ session->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; session->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; session->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; session->opt[OPT_BR_X].type = SANE_TYPE_FIXED; session->opt[OPT_BR_X].cap |= SANE_CAP_AUTOMATIC; session->opt[OPT_BR_X].unit = SANE_UNIT_MM; session->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_BR_X].constraint.range = &x_range; session->val[OPT_BR_X].w = x_range.max; /* bottom-right y */ session->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; session->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; session->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; session->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; session->opt[OPT_BR_Y].cap |= SANE_CAP_AUTOMATIC; session->opt[OPT_BR_Y].unit = SANE_UNIT_MM; session->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_BR_Y].constraint.range = &y_range; session->val[OPT_BR_Y].w = y_range.max; /* "Enhancement" group: */ session->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT; session->opt[OPT_ENHANCEMENT_GROUP].name = SANE_NAME_ENHANCEMENT; session->opt[OPT_ENHANCEMENT_GROUP].desc = SANE_DESC_ENHANCEMENT; session->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; session->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; session->opt[OPT_ENHANCEMENT_GROUP].size = 0; session->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* BW threshold */ session->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; session->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; session->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; session->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; session->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; session->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_EMULATED; session->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_THRESHOLD].constraint.range = &threshold_percentage_range; session->val[OPT_THRESHOLD].w = SANE_FIX (50); /* custom-gamma table */ session->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; session->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; session->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; session->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; session->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_ADVANCED; session->val[OPT_CUSTOM_GAMMA].b = SANE_FALSE; /* grayscale gamma vector */ session->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; session->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; session->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; session->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; session->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; session->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; session->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); session->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; session->val[OPT_GAMMA_VECTOR].wa = model->gamma; /* red gamma vector */ session->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; session->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; session->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; session->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; session->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; session->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; session->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); session->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; session->val[OPT_GAMMA_VECTOR_R].wa = model->gamma; /* green gamma vector */ session->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; session->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; session->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; session->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; session->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; session->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; session->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); session->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; session->val[OPT_GAMMA_VECTOR_G].wa = model->gamma; /* blue gamma vector */ session->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; session->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; session->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; session->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; session->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED; session->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; session->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); session->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; session->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; session->val[OPT_GAMMA_VECTOR_B].wa = model->gamma; /* "Sensors" group */ session->opt[OPT_SENSOR_GROUP].title = SANE_TITLE_SENSORS; session->opt[OPT_SENSOR_GROUP].name = SANE_NAME_SENSORS; session->opt[OPT_SENSOR_GROUP].desc = SANE_DESC_SENSORS; session->opt[OPT_SENSOR_GROUP].type = SANE_TYPE_GROUP; session->opt[OPT_SENSOR_GROUP].cap = SANE_CAP_ADVANCED; session->opt[OPT_SENSOR_GROUP].size = 0; session->opt[OPT_SENSOR_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scanner buttons */ for (i = OPT_BUTTON_1; i <= OPT_BUTTON_11; i++) { char name[39]; char title[64]; idx = i - OPT_BUTTON_1; if (idx < model->buttons) { sprintf (name, "button-%s", model->button_name[idx]); sprintf (title, "%s", model->button_title[idx]); session->opt[i].name = strdup (name); session->opt[i].title = strdup (title); session->opt[i].desc = SANE_I18N ("This option reflects the status " "of a scanner button."); session->opt[i].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; } else { session->opt[i].name = strdup ("unused"); session->opt[i].title = strdup ("unused button"); session->opt[i].cap |= SANE_CAP_INACTIVE; } session->opt[i].type = SANE_TYPE_BOOL; session->opt[i].unit = SANE_UNIT_NONE; session->opt[i].size = sizeof (SANE_Bool); session->opt[i].constraint_type = SANE_CONSTRAINT_NONE; session->opt[i].constraint.range = 0; session->val[i].w = SANE_FALSE; } update_button_status (session); /* "Advanced" group: */ session->opt[OPT_ADVANCED_GROUP].title = SANE_I18N ("Advanced"); session->opt[OPT_ADVANCED_GROUP].desc = ""; session->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; session->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; session->opt[OPT_ADVANCED_GROUP].size = 0; session->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* lamp on */ session->opt[OPT_LAMP_ON].name = "lamp-on"; session->opt[OPT_LAMP_ON].title = SANE_I18N ("Lamp on"); session->opt[OPT_LAMP_ON].desc = SANE_I18N ("Turn on scanner lamp"); session->opt[OPT_LAMP_ON].type = SANE_TYPE_BUTTON; session->opt[OPT_LAMP_ON].cap |= SANE_CAP_ADVANCED; session->opt[OPT_LAMP_ON].unit = SANE_UNIT_NONE; session->opt[OPT_LAMP_ON].size = 0; session->opt[OPT_LAMP_ON].constraint_type = SANE_CONSTRAINT_NONE; session->val[OPT_LAMP_ON].w = 0; /* lamp off */ session->opt[OPT_LAMP_OFF].name = "lamp-off"; session->opt[OPT_LAMP_OFF].title = SANE_I18N ("Lamp off"); session->opt[OPT_LAMP_OFF].desc = SANE_I18N ("Turn off scanner lamp"); session->opt[OPT_LAMP_OFF].type = SANE_TYPE_BUTTON; session->opt[OPT_LAMP_OFF].cap |= SANE_CAP_ADVANCED; session->opt[OPT_LAMP_OFF].unit = SANE_UNIT_NONE; session->opt[OPT_LAMP_OFF].size = 0; session->opt[OPT_LAMP_OFF].constraint_type = SANE_CONSTRAINT_NONE; session->val[OPT_LAMP_OFF].w = 0; DBG (DBG_proc, "init_options: exit\n"); return SANE_STATUS_GOOD; } /** * average scanned rgb data, returns the global average. Each channel avearge is also * returned. */ static float average_area (int color, SANE_Byte * data, int width, int height, float *ra, float *ga, float *ba) { int x, y; float global, pixels; float rc, gc, bc; pixels = width * height; *ra = 0; *ga = 0; *ba = 0; rc = 0; gc = 0; bc = 0; if (color == SANE_TRUE) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { rc += data[3 * width * y + x]; gc += data[3 * width * y + x + 1]; bc += data[3 * width * y + x + 2]; } } global = (rc + gc + bc) / (3 * pixels); *ra = rc / pixels; *ga = gc / pixels; *ba = bc / pixels; } else { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { gc += data[width * y + x]; } } global = gc / pixels; *ga = gc / pixels; } DBG (7, "average_area: global=%.2f, red=%.2f, green=%.2f, blue=%.2f\n", global, *ra, *ga, *ba); return global; } /** * Sets lamp brightness (hum, maybe some timing before light off) */ static SANE_Status set_lamp_brightness (struct Rts8891_Device *dev, int level) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte reg; reg = 0xA0 | (level & 0x0F); sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, ®); switch (level) { case 0: reg = 0x8d; break; case 7: reg = 0x82; break; default: reg = 0x8d; break; } sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); reg = (reg & 0xF0) | 0x20 | ((~reg) & 0x0F); dev->regs[LAMP_REG] = reg; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_get_status (dev->devnum, dev->regs); DBG (DBG_io, "set_lamp_brightness: status=0x%02x 0x%02x\n", dev->regs[0x10], dev->regs[0x11]); if (dev->sensor != SENSOR_TYPE_4400) { dev->regs[0x10] = 0x28; dev->regs[0x11] = 0x3f; } else { dev->regs[0x10] = 0x10; dev->regs[0x11] = 0x2f; } reg = dev->regs[LAMP_REG]; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, ®); if (reg != 0x00) { DBG (DBG_warn, "set_lamp_brightness: unexpected CONTROL_REG value, 0x%02x instead of 0x00\n", reg); } return status; } /** * Sets the lamp to half brightness and standard parameters */ static SANE_Status init_lamp (struct Rts8891_Device *dev) { SANE_Byte reg; sanei_rts88xx_write_control (dev->devnum, 0x01); sanei_rts88xx_write_control (dev->devnum, 0x01); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_cancel (dev->devnum); dev->regs[0x12] = 0xff; dev->regs[0x13] = 0x20; sanei_rts88xx_write_regs (dev->devnum, 0x12, dev->regs + 0x12, 2); /* 0xF8/0x28 expected */ sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); if (dev->sensor != SENSOR_TYPE_4400 && dev->sensor != SENSOR_TYPE_4400_BARE) { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x3f); dev->regs[0x11] = 0x3f; } else { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x22); dev->regs[0x11] = 0x22; } reg = 0x8d; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); dev->regs[LAMP_REG] = 0xa2; dev->regs[LAMP_BRIGHT_REG] = 0xa0; rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); return set_lamp_brightness (dev, 7); } /** * This function detects physical start of scanning area find finding a black area below the "roof" * if during scan we detect that sensor is inadequate, changed is set to SANE_TRUE */ static SANE_Status find_origin (struct Rts8891_Device *dev, SANE_Bool * changed) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte control, reg; unsigned int max = 0; unsigned char *image = NULL; unsigned char *data = NULL; SANE_Word total; int startx = 300; int width = 1200; int x, y, sum, current; int starty = 18; int height = 180; int timing; DBG (DBG_proc, "find_origin: start\n"); /* check if head is at home * once sensor is correctly set up, we are allways park here, * but in case sensor has just changed, we are not so we park head */ sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, ®); if ((reg & 0x02) == 0) { if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD) { DBG (DBG_error, "find_origin: failed to park head!\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_info, "find_origin: head parked\n"); } sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if (control != 0) { DBG (DBG_warn, "find_origin: unexpected control value 0x%02x\n", control); } sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if (control != 0) { DBG (DBG_warn, "find_origin: unexpected control value 0x%02x\n", control); } sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); /* set lamp to standard settings */ init_lamp (dev); /* set scan parameters */ dev->regs[0x00] = 0xe5; dev->regs[0x32] = 0x80; dev->regs[0x33] = 0x81; dev->regs[0x39] = 0x02; dev->regs[0x64] = 0x01; dev->regs[0x65] = 0x20; dev->regs[0x79] = 0x20; dev->regs[0x7a] = 0x01; dev->regs[0x90] = 0x1c; dev->regs[0x35] = 0x1b; dev->regs[0x36] = 0x29; dev->regs[0x3a] = 0x1b; timing=0x32; dev->regs[0x85] = 0x00; dev->regs[0x86] = 0x06; dev->regs[0x87] = 0x00; dev->regs[0x88] = 0x06; dev->regs[0x8d] = 0x80; dev->regs[0x8e] = 0x68; dev->regs[0xb2] = 0x02; /* 0x04 -> no data */ dev->regs[0xc0] = 0xff; dev->regs[0xc1] = 0x0f; dev->regs[0xc3] = 0xff; dev->regs[0xc4] = 0xff; dev->regs[0xc5] = 0xff; dev->regs[0xc6] = 0xff; dev->regs[0xc7] = 0xff; dev->regs[0xc8] = 0xff; dev->regs[0xc9] = 0x00; dev->regs[0xca] = 0x0e; dev->regs[0xcb] = 0x00; dev->regs[0xcd] = 0xf0; dev->regs[0xce] = 0xff; dev->regs[0xcf] = 0xf5; dev->regs[0xd0] = 0xf7; dev->regs[0xd1] = 0xea; dev->regs[0xd2] = 0x0b; dev->regs[0xd3] = 0x03; dev->regs[0xd4] = 0x05; dev->regs[0xd6] = 0xab; dev->regs[0xd7] = 0x30; dev->regs[0xd8] = 0xf6; dev->regs[0xe2] = 0x01; dev->regs[0xe3] = 0x00; dev->regs[0xe4] = 0x00; SET_DOUBLE (dev->regs, EXPOSURE_REG, 4124); /* dev->regs[0xe5] = 0x1c; dev->regs[0xe6] = 0x10; 101c=4124 */ dev->regs[0xe7] = 0x00; dev->regs[0xe8] = 0x00; dev->regs[0xe9] = 0x00; if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) { dev->regs[0xc3] = 0x00; dev->regs[0xc4] = 0xf0; dev->regs[0xc7] = 0x0f; dev->regs[0xc8] = 0x00; dev->regs[0xc9] = 0xff; dev->regs[0xca] = 0xf1; dev->regs[0xcb] = 0xff; dev->regs[0xd7] = 0x10; } if (dev->sensor == SENSOR_TYPE_4400 || dev->sensor == SENSOR_TYPE_4400_BARE) { /* 4400 values / 'XPA' values */ dev->regs[0x13] = 0x39; /* 0x20 */ dev->regs[0x14] = 0xf0; /* 0xf8 */ dev->regs[0x15] = 0x29; /* 0x28 */ dev->regs[0x16] = 0x0f; /* 0x07 */ dev->regs[0x17] = 0x10; /* 0x00 */ dev->regs[0x23] = 0x00; /* 0xff */ dev->regs[0x39] = 0x00; /* 0x02 */ } if (dev->sensor == SENSOR_TYPE_4400_BARE) { dev->regs[0xc3] = 0xff; /* 0x00 */ dev->regs[0xc4] = 0xff; /* 0xf0 */ dev->regs[0xc7] = 0xff; /* 0x0f */ dev->regs[0xc8] = 0xff; /* 0x00 */ dev->regs[0xc9] = 0x00; /* 0xff */ dev->regs[0xca] = 0x0e; /* 0xf1 */ dev->regs[0xcb] = 0x00; /* 0xff */ dev->regs[0xd7] = 0x30; /* 0x10 */ dev->regs[0xda] = 0xa7; /* 0xa0 */ } SET_DOUBLE (dev->regs, TIMING_REG, timing); SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); /* allocate memory for the data */ total = width * height; data = (unsigned char *) malloc (total); if (data == NULL) { DBG (DBG_error, "find_origin: failed to allocate %d bytes\n", total); return SANE_STATUS_NO_MEM; } image = (unsigned char *) malloc (total); if (image == NULL) { free(data); DBG (DBG_error, "find_origin: failed to allocate %d bytes\n", total); return SANE_STATUS_NO_MEM; } /* set vertical and horizontal start/end positions */ sanei_rts88xx_set_scan_area (dev->regs, starty, starty + height, startx, startx + width); sanei_rts88xx_set_offset (dev->regs, 0x7f, 0x7f, 0x7f); sanei_rts88xx_set_gain (dev->regs, 0x10, 0x10, 0x10); /* gray level scan */ dev->regs[LAMP_REG] = 0xad; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, dev->regs + LAMP_REG); if (dev->sensor != SENSOR_TYPE_4400 && (dev->sensor != SENSOR_TYPE_4400_BARE)) { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x3b); } else { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x22); } status = rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x03, total, data); if (status != SANE_STATUS_GOOD) { free(image); free(data); DBG (DBG_error, "find_origin: failed to scan\n"); return status; } if (DBG_LEVEL > DBG_io2) { write_gray_data (data, "find_origin.pnm", width, height); } /* now we have the data, search for the black area so that we can */ /* deduce start of scan area */ /* we apply an Y direction sobel filter to get reliable edge detection */ /* Meanwhile we check that picture is correct, if not, sensor needs to */ /* be changed . */ /* TODO possibly check for insufficient warming */ for (y = 1; y < height - 1; y++) for (x = 1; x < width - 1; x++) { /* if sensor is wrong, picture is black, so max will be low */ if (data[y * width + x] > max) max = data[y * width + x]; /* sobel y filter */ current = -data[(y - 1) * width + x + 1] - 2 * data[(y - 1) * width + x] - data[(y - 1) * width + x - 1] + data[(y + 1) * width + x + 1] + 2 * data[(y + 1) * width + x] + data[(y + 1) * width + x - 1]; if (current < 0) current = -current; image[y * width + x] = current; } if (DBG_LEVEL > DBG_io2) { write_gray_data (image, "find_origin_ysobel.pnm", width, height); } /* sensor test */ if (max < 10) { DBG (DBG_info, "find_origin: sensor type needs to be changed (max=%d)\n", max); *changed = SANE_TRUE; } else { *changed = SANE_FALSE; } /* the edge will be where the white area stops */ /* we average y position of white->black transition on each column */ sum = 0; for (x = 1; x < width - 1; x++) { for (y = 1; y < height - 2; y++) { /* egde detection on each line */ if (image[x + (y + 1) * width] - image[x + y * width] >= 20) { sum += y; break; } } } sum /= width; DBG (DBG_info, "find_origin: scan area offset=%d lines\n", sum); /* convert the detected value into max ydpi */ dev->top_offset = (48 * dev->model->max_ydpi) / 300; /* no we're done */ free (image); free (data); /* safe guard test against moving to far toward the top */ if (sum > 11) { /* now go back to the white area so that calibration can work on it */ dev->regs[0x35] = 0x0e; dev->regs[0x3a] = 0x0e; dev->regs[0xb2] = 0x06; /* no data (0x04) */ if (dev->sensor == SENSOR_TYPE_4400) { dev->regs[0x36] = 0x21; /* direction reverse (& ~0x08) */ dev->regs[0xe2] = 0x03; /* 0x01 */ /* dev->regs[0xe5] = 0x0d; 0x1c dev->regs[0xe6] = 0x08; 0x10 080d=2061=1030*2+1 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 2061); } else { dev->regs[0x11] = 0x3f; /* 0x3b */ dev->regs[0x36] = 0x24; /* direction reverse (& ~0x08) */ dev->regs[0xe2] = 0x07; /* dev->regs[0xe5] = 0x06; dev->regs[0xe6] = 0x04; 406=1030 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 1030); } /* move by a fixed amount relative to the 'top' of the scanner */ sanei_rts88xx_set_scan_area (dev->regs, height - sum + 10, height - sum + 11, 637, 893); rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); rts8891_commit (dev->devnum, 0x03); /* wait for the motor to stop */ do { status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, ®); } while ((reg & 0x08) == 0x08); } DBG (DBG_proc, "find_origin: exit\n"); return status; } /** * This function detects the left margin (ie x offset of scanning area) by doing * a grey scan of the very beginning of the sensor and finding the start of the * white area of calibration zone, which is start of usable pixels. */ static SANE_Status find_margin (struct Rts8891_Device *dev) { SANE_Status status = SANE_STATUS_GOOD; unsigned char *data = NULL; SANE_Word total; int startx = 33; int width = 250; int x; int starty = 1; int height = 1; SANE_Byte reg = 0xa2; int timing=0; DBG (DBG_proc, "find_margin: start\n"); /* increase brightness to have better margin detection */ sanei_rts88xx_write_reg (dev->devnum, LAMP_BRIGHT_REG, ®); /* maximum gain, offsets untouched */ if (dev->sensor == SENSOR_TYPE_4400 || dev->sensor == SENSOR_TYPE_4400_BARE) { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x10, 0x23); } else { sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x3b); } sanei_rts88xx_set_gain (dev->regs, 0x3f, 0x3f, 0x3f); /* set scan parameters */ dev->regs[0x33] = 0x01; dev->regs[0x34] = 0x10; dev->regs[0x35] = 0x1b; dev->regs[0x3a] = 0x1b; dev->regs[0x72] = 0x3a; dev->regs[0x73] = 0x15; dev->regs[0x74] = 0x62; timing=0; dev->regs[0xc0] = 0xff; dev->regs[0xc1] = 0xff; dev->regs[0xc2] = 0xff; dev->regs[0xc3] = 0x00; dev->regs[0xc4] = 0xf0; dev->regs[0xc7] = 0x0f; dev->regs[0xc8] = 0x00; dev->regs[0xcb] = 0xe0; dev->regs[0xcc] = 0xff; dev->regs[0xcd] = 0xff; dev->regs[0xce] = 0xff; dev->regs[0xcf] = 0xe9; dev->regs[0xd0] = 0xeb; dev->regs[0xd3] = 0x0c; dev->regs[0xd4] = 0x0e; dev->regs[0xd6] = 0xab; dev->regs[0xd7] = 0x14; dev->regs[0xd8] = 0xf6; dev->regs[0xda] = 0xa7; /* XXX STEF XXX à l'origine, pas 'bare' */ dev->regs[0xe2] = 0x01; /* dev->regs[0xe5] = 0x7b; dev->regs[0xe6] = 0x15; 157b=5499 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 5499); dev->regs[0xe7] = 0x00; dev->regs[0xe8] = 0x00; dev->regs[0xe9] = 0x00; dev->regs[0xea] = 0x00; dev->regs[0xeb] = 0x00; dev->regs[0xec] = 0x00; dev->regs[0xed] = 0x00; dev->regs[0xef] = 0x00; dev->regs[0xf0] = 0x00; dev->regs[0xf2] = 0x00; if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) { dev->regs[0xc0] = 0x00; dev->regs[0xc1] = 0xf8; dev->regs[0xc2] = 0x7f; dev->regs[0xc4] = 0xf8; dev->regs[0xc5] = 0x7f; dev->regs[0xc6] = 0x00; dev->regs[0xc7] = 0xf8; dev->regs[0xc8] = 0x7f; dev->regs[0xc9] = 0xff; dev->regs[0xca] = 0xff; dev->regs[0xcb] = 0x8f; dev->regs[0xcd] = 0x07; dev->regs[0xce] = 0x80; dev->regs[0xcf] = 0xea; dev->regs[0xd0] = 0xec; dev->regs[0xd1] = 0xf7; dev->regs[0xd2] = 0x00; dev->regs[0xd3] = 0x10; dev->regs[0xd4] = 0x12; dev->regs[0xd7] = 0x31; } if (dev->sensor == SENSOR_TYPE_4400_BARE) { dev->regs[0x13] = 0x39; /* 0x20 */ dev->regs[0x14] = 0xf0; /* 0xf8 */ dev->regs[0x15] = 0x29; /* 0x28 */ dev->regs[0x16] = 0x0f; /* 0x07 */ dev->regs[0x17] = 0x10; /* 0x00 */ dev->regs[0x23] = 0x00; /* 0xff */ dev->regs[0x39] = 0x00; /* 0x02 */ dev->regs[0x85] = 0x46; /* 0x00 */ dev->regs[0x86] = 0x0b; /* 0x06 */ dev->regs[0x87] = 0x8c; /* 0x00 */ dev->regs[0x88] = 0x10; /* 0x06 */ dev->regs[0x8d] = 0x3b; /* 0x00 */ timing=0x00b0; } SET_DOUBLE (dev->regs, TIMING_REG, timing); SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); /* set vertical and horizontal start/end positions */ sanei_rts88xx_set_scan_area (dev->regs, starty, starty + height, startx, startx + width); /* allocate memory for the data */ total = width * height; data = (unsigned char *) malloc (total); if (data == NULL) { DBG (DBG_error, "find_margin: failed to allocate %d bytes\n", total); return SANE_STATUS_NO_MEM; } /* gray level scan */ status = rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x0c, total, data); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "find_margin: failed to scan\n"); return status; } if (DBG_LEVEL > DBG_io2) { write_gray_data (data, "find_margin.pnm", width, height); } /* we search from left to right the first white pixel */ x = 0; while (x < width && data[x] < MARGIN_LEVEL) x++; if (x == width) { DBG (DBG_warn, "find_margin: failed to find left margin!\n"); DBG (DBG_warn, "find_margin: using default...\n"); x = 48 + 40; } DBG (DBG_info, "find_margin: scan area margin=%d pixels\n", x); /* convert the detected value into max ydpi */ dev->left_offset = ((x - 40) * dev->model->max_xdpi) / 150; DBG (DBG_info, "find_margin: left_offset=%d pixels\n", x); /* no we're done */ free (data); DBG (DBG_proc, "find_margin: exit\n"); return status; } #ifdef FAST_INIT /* * This function intializes the device: * - initial registers values * - test if at home * - head parking if needed */ static SANE_Status initialize_device (struct Rts8891_Device *dev) { SANE_Status status; SANE_Byte reg, control; DBG (DBG_proc, "initialize_device: start\n"); if (dev->initialized == SANE_TRUE) return SANE_STATUS_GOOD; sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x28); sanei_rts88xx_write_control (dev->devnum, 0x01); sanei_rts88xx_write_control (dev->devnum, 0x01); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control); DBG (DBG_io, "initialize_device: reg[0xb0]=0x%02x\n", control); /* we expect to get 0x80 */ if (control != 0x80) { DBG (DBG_warn, "initialize_device: expected reg[0xb0]=0x80, got 0x%02x\n", control); /* TODO fail here ??? */ } /* get lamp status */ status = sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "initialize_device: failed to read lamp status!\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_io, "initialize_device: lamp status=0x%02x\n", dev->regs[0x8e]); /* sensor type the one for 4470c sold with XPA is slightly different * than those sold bare, for this model we allways start with xpa type sensor, * and change it later if we detect black scans in find_origin(). In case the * attach function set up the sensor type, we don't modify it */ if (dev->sensor == -1) { dev->sensor = device->model->sensor; } DBG (DBG_info, "initialize_device: initial sensor type is %d\n", dev->sensor); DBG (DBG_info, "initialize_device: reg[8e]=0x%02x\n", dev->regs[0x8e]); /* detects if warming up is needed */ if ((dev->regs[0x8e] & 0x60) != 0x60) { DBG (DBG_info, "initialize_device: lamp needs warming\n"); dev->needs_warming = SANE_TRUE; } else { dev->needs_warming = SANE_FALSE; } sanei_rts88xx_read_reg (dev->devnum, LAMP_REG, ®); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); /* read scanner present register */ sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control); if (control != 0x00 && control != 0x01) { DBG (DBG_warn, "initialize_device: unexpected LINK_REG=0x%02x\n", control); } /* head parking if needed */ sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, &control); if (!(control & 0x02)) { if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD) { DBG (DBG_error, "initialize_device: failed to park head!\n"); return SANE_STATUS_IO_ERROR; } } /* writes initial register set */ dev->regs[0x00] = 0xe5; /* 0xf5 */ dev->regs[0x02] = 0x1f; /* 0x00 */ dev->regs[0x03] = 0x1f; /* 0x00 */ dev->regs[0x04] = 0x1f; /* 0x00 */ dev->regs[0x05] = 0x1f; /* 0x00 */ dev->regs[0x06] = 0x1f; /* 0x00 */ dev->regs[0x07] = 0x1f; /* 0x00 */ dev->regs[0x08] = 0x0a; /* 0x00 */ dev->regs[0x09] = 0x0a; /* 0x00 */ dev->regs[0x0a] = 0x0a; /* 0x00 */ dev->regs[0x10] = 0x28; /* 0x60 */ dev->regs[0x11] = 0x28; /* 0x1b */ dev->regs[0x13] = 0x20; /* 0x3e */ dev->regs[0x14] = 0xf8; /* 0x00 */ dev->regs[0x15] = 0x28; /* 0x00 */ dev->regs[0x16] = 0x07; /* 0xff */ dev->regs[0x17] = 0x00; /* 0x3e */ dev->regs[0x18] = 0xff; /* 0x00 */ dev->regs[0x1d] = 0x20; /* 0x22 */ /* LCD display */ dev->regs[0x20] = 0x3a; /* 0x00 */ dev->regs[0x21] = 0xf2; /* 0x00 */ dev->regs[0x24] = 0xff; /* 0x00 */ dev->regs[0x25] = 0x00; /* 0xff */ dev->regs[0x30] = 0x00; /* 0x01 */ dev->regs[0x31] = 0x00; /* 0x42 */ dev->regs[0x36] = 0x07; /* 0x00 */ dev->regs[0x39] = 0x00; /* 0x02 */ dev->regs[0x40] = 0x20; /* 0x80 */ dev->regs[0x44] = 0x8c; /* 0x18 */ dev->regs[0x45] = 0x76; /* 0x00 */ dev->regs[0x50] = 0x00; /* 0x20 */ dev->regs[0x51] = 0x00; /* 0x24 */ dev->regs[0x52] = 0x00; /* 0x04 */ dev->regs[0x64] = 0x00; /* 0x10 */ dev->regs[0x68] = 0x00; /* 0x10 */ dev->regs[0x6a] = 0x00; /* 0x01 */ dev->regs[0x70] = 0x00; /* 0x20 */ dev->regs[0x71] = 0x00; /* 0x20 */ dev->regs[0x72] = 0xe1; /* 0x00 */ dev->regs[0x73] = 0x14; /* 0x00 */ dev->regs[0x74] = 0x18; /* 0x00 */ dev->regs[0x75] = 0x15; /* 0x00 */ dev->regs[0x76] = 0x00; /* 0x20 */ dev->regs[0x77] = 0x00; /* 0x01 */ dev->regs[0x79] = 0x00; /* 0x02 */ dev->regs[0x81] = 0x00; /* 0x41 */ dev->regs[0x83] = 0x00; /* 0x10 */ dev->regs[0x84] = 0x00; /* 0x21 */ dev->regs[0x85] = 0x00; /* 0x20 */ dev->regs[0x87] = 0x00; /* 0x20 */ dev->regs[0x88] = 0x00; /* 0x81 */ dev->regs[0x89] = 0x00; /* 0x20 */ dev->regs[0x8a] = 0x00; /* 0x01 */ dev->regs[0x8b] = 0x00; /* 0x01 */ dev->regs[0x8d] = 0x80; /* 0x22 */ dev->regs[0x8e] = 0x68; /* 0x00 */ dev->regs[0x8f] = 0x00; /* 0x40 */ dev->regs[0x90] = 0x00; /* 0x05 */ dev->regs[0x93] = 0x02; /* 0x01 */ dev->regs[0x94] = 0x0e; /* 0x1e */ dev->regs[0xb0] = 0x00; /* 0x80 */ dev->regs[0xb2] = 0x02; /* 0x06 */ dev->regs[0xc0] = 0xff; /* 0x00 */ dev->regs[0xc1] = 0x0f; /* 0x00 */ dev->regs[0xc3] = 0xff; /* 0x00 */ dev->regs[0xc4] = 0xff; /* 0x00 */ dev->regs[0xc5] = 0xff; /* 0x00 */ dev->regs[0xc6] = 0xff; /* 0x00 */ dev->regs[0xc7] = 0xff; /* 0x00 */ dev->regs[0xc8] = 0xff; /* 0x00 */ dev->regs[0xca] = 0x0e; /* 0x00 */ dev->regs[0xcd] = 0xf0; /* 0x00 */ dev->regs[0xce] = 0xff; /* 0x00 */ dev->regs[0xcf] = 0xf5; /* 0x00 */ dev->regs[0xd0] = 0xf7; /* 0x00 */ dev->regs[0xd1] = 0xea; /* 0x00 */ dev->regs[0xd2] = 0x0b; /* 0x00 */ dev->regs[0xd3] = 0x03; /* 0x00 */ dev->regs[0xd4] = 0x05; /* 0x01 */ dev->regs[0xd5] = 0x86; /* 0x06 */ dev->regs[0xd7] = 0x30; /* 0x10 */ dev->regs[0xd8] = 0xf6; /* 0x7a */ dev->regs[0xd9] = 0x80; /* 0x00 */ dev->regs[0xda] = 0x00; /* 0x15 */ dev->regs[0xe2] = 0x01; /* 0x00 */ /* dev->regs[0xe5] = 0x14; 0x0f */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 20); status = rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); DBG (DBG_proc, "initialize_device: exit\n"); dev->initialized = SANE_TRUE; return status; } #else /* FAST_INIT */ #ifndef UNIT_TESTING static #endif SANE_Status init_registers (struct Rts8891_Device *dev) { int i; /* initial set written to scanner * 0xe5 0x41 0x1f 0x1f 0x1f 0x1f 0x1f 0x1f 0x0a 0x0a 0x0a 0x70 0x00 0x00 0x00 0x00 0x60 0x1b 0x08 0x20 0x00 0x20 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x00 0x00 0x3a 0xf2 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x10 0x00 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x00 0x00 0x00 0x8c 0x76 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x68 0x00 0x00 0x00 0x00 0x02 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xcc 0x27 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02 ---- 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x00 0x86 0x1b 0x00 0xff 0x00 0x27 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x14 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 */ /* lengthy set up to make register content obvious, may be some day I will * group corresponding values between models */ switch (dev->sensor) { case SENSOR_TYPE_BARE: case SENSOR_TYPE_XPA: dev->regs[0x01] = 0x41; dev->regs[0x0b] = 0x70; dev->regs[0x0c] = 0x00; dev->regs[0x0d] = 0x00; dev->regs[0x0e] = 0x00; dev->regs[0x0f] = 0x00; dev->regs[0x12] = 0x00; dev->regs[0x13] = 0x20; dev->regs[0x14] = 0x00; dev->regs[0x15] = 0x20; dev->regs[0x16] = 0x00; dev->regs[0x17] = 0x00; dev->regs[0x18] = 0x00; dev->regs[0x19] = 0x00; dev->regs[0x1a] = 0x00; dev->regs[0x1b] = 0x00; dev->regs[0x1c] = 0x00; dev->regs[0x1d] = 0x20; dev->regs[0x1e] = 0x00; dev->regs[0x1f] = 0x00; /* LCD display */ dev->regs[0x20] = 0x3a; dev->regs[0x21] = 0xf2; dev->regs[0x22] = 0x00; dev->regs[0x23] = 0x00; dev->regs[0x24] = 0x00; dev->regs[0x25] = 0x00; dev->regs[0x26] = 0x00; dev->regs[0x27] = 0x00; dev->regs[0x28] = 0x00; dev->regs[0x29] = 0x00; dev->regs[0x2a] = 0x00; dev->regs[0x2b] = 0x00; dev->regs[0x2c] = 0x00; dev->regs[0x2d] = 0x00; dev->regs[0x2e] = 0x00; dev->regs[0x2f] = 0x00; dev->regs[0x30] = 0x00; dev->regs[0x31] = 0x00; dev->regs[0x32] = 0x00; dev->regs[0x33] = 0x00; dev->regs[0x34] = 0x10; dev->regs[0x35] = 0x00; dev->regs[0x36] = 0x07; dev->regs[0x37] = 0x00; dev->regs[0x38] = 0x00; dev->regs[0x39] = 0x00; dev->regs[0x3a] = 0x00; dev->regs[0x3b] = 0x00; dev->regs[0x3c] = 0x00; dev->regs[0x3d] = 0x00; dev->regs[0x3e] = 0x00; dev->regs[0x3f] = 0x00; dev->regs[0x40] = 0x20; dev->regs[0x41] = 0x00; dev->regs[0x42] = 0x00; dev->regs[0x43] = 0x00; dev->regs[0x44] = 0x8c; dev->regs[0x45] = 0x76; dev->regs[0x46] = 0x00; dev->regs[0x47] = 0x00; dev->regs[0x48] = 0x00; dev->regs[0x49] = 0x00; dev->regs[0x4a] = 0x00; dev->regs[0x4b] = 0x00; dev->regs[0x4c] = 0x00; dev->regs[0x4d] = 0x00; dev->regs[0x4e] = 0x00; dev->regs[0x4f] = 0x00; dev->regs[0x50] = 0x00; dev->regs[0x51] = 0x00; dev->regs[0x52] = 0x00; dev->regs[0x53] = 0x00; dev->regs[0x54] = 0x00; dev->regs[0x55] = 0x00; dev->regs[0x56] = 0x00; dev->regs[0x57] = 0x00; dev->regs[0x58] = 0x00; dev->regs[0x59] = 0x00; dev->regs[0x5a] = 0x00; dev->regs[0x5b] = 0x00; dev->regs[0x5c] = 0x00; dev->regs[0x5d] = 0x00; dev->regs[0x5e] = 0x00; dev->regs[0x5f] = 0x00; dev->regs[0x64] = 0x00; dev->regs[0x65] = 0x00; dev->regs[0x66] = 0x00; dev->regs[0x67] = 0x00; dev->regs[0x68] = 0x00; dev->regs[0x69] = 0x00; dev->regs[0x6a] = 0x00; dev->regs[0x6b] = 0x00; dev->regs[0x6e] = 0x00; dev->regs[0x6f] = 0x00; dev->regs[0x70] = 0x00; dev->regs[0x71] = 0x00; dev->regs[0x72] = 0x00; dev->regs[0x73] = 0x00; dev->regs[0x74] = 0x00; dev->regs[0x75] = 0x00; dev->regs[0x76] = 0x00; dev->regs[0x77] = 0x00; dev->regs[0x78] = 0x00; dev->regs[0x79] = 0x00; dev->regs[0x7a] = 0x00; dev->regs[0x7b] = 0x00; dev->regs[0x7c] = 0x00; dev->regs[0x7d] = 0x00; dev->regs[0x7e] = 0x00; dev->regs[0x7f] = 0x00; dev->regs[0x80] = 0x00; dev->regs[0x81] = 0x00; dev->regs[0x82] = 0x00; dev->regs[0x83] = 0x00; dev->regs[0x84] = 0x00; dev->regs[0x85] = 0x00; dev->regs[0x86] = 0x00; dev->regs[0x87] = 0x00; dev->regs[0x88] = 0x00; dev->regs[0x89] = 0x00; dev->regs[0x8a] = 0x00; dev->regs[0x8b] = 0x00; dev->regs[0x8c] = 0x00; dev->regs[0x8d] = 0x80; dev->regs[0x8e] = 0x68; dev->regs[0x8f] = 0x00; dev->regs[0x90] = 0x00; dev->regs[0x91] = 0x00; dev->regs[0x92] = 0x00; dev->regs[0x93] = 0x02; dev->regs[0x94] = 0x0e; dev->regs[0x95] = 0x00; dev->regs[0x96] = 0x00; dev->regs[0x97] = 0x00; dev->regs[0x98] = 0x00; dev->regs[0x99] = 0x00; dev->regs[0x9a] = 0x00; dev->regs[0x9b] = 0x00; dev->regs[0x9c] = 0x00; dev->regs[0x9d] = 0x00; dev->regs[0x9e] = 0x00; dev->regs[0x9f] = 0x00; dev->regs[0xa0] = 0x00; dev->regs[0xa1] = 0x00; dev->regs[0xa2] = 0x00; dev->regs[0xa3] = 0xcc; dev->regs[0xa4] = 0x27; dev->regs[0xa5] = 0x64; dev->regs[0xa6] = 0x00; dev->regs[0xa7] = 0x00; dev->regs[0xa8] = 0x00; dev->regs[0xa9] = 0x00; dev->regs[0xaa] = 0x00; dev->regs[0xab] = 0x00; dev->regs[0xac] = 0x00; dev->regs[0xad] = 0x00; dev->regs[0xae] = 0x00; dev->regs[0xaf] = 0x00; dev->regs[0xb0] = 0x00; dev->regs[0xb1] = 0x00; dev->regs[0xb2] = 0x02; dev->regs[0xb4] = 0x00; dev->regs[0xb5] = 0x00; dev->regs[0xb6] = 0x00; dev->regs[0xb7] = 0x00; dev->regs[0xb8] = 0x00; dev->regs[0xb9] = 0x00; dev->regs[0xba] = 0x00; dev->regs[0xbb] = 0x00; dev->regs[0xbc] = 0x00; dev->regs[0xbd] = 0x00; dev->regs[0xbe] = 0x00; dev->regs[0xbf] = 0x00; dev->regs[0xc0] = 0x00; dev->regs[0xc1] = 0x00; dev->regs[0xc2] = 0x00; dev->regs[0xc3] = 0x00; dev->regs[0xc4] = 0x00; dev->regs[0xc5] = 0x00; dev->regs[0xc6] = 0x00; dev->regs[0xc7] = 0x00; dev->regs[0xc8] = 0x00; dev->regs[0xc9] = 0x00; dev->regs[0xca] = 0x00; dev->regs[0xcb] = 0x00; dev->regs[0xcc] = 0x00; dev->regs[0xcd] = 0x00; dev->regs[0xce] = 0x00; dev->regs[0xcf] = 0x00; dev->regs[0xd0] = 0x00; dev->regs[0xd1] = 0x00; dev->regs[0xd2] = 0x00; dev->regs[0xd3] = 0x00; dev->regs[0xd4] = 0x00; dev->regs[0xd5] = 0x86; dev->regs[0xd6] = 0x1b; dev->regs[0xd7] = 0x00; dev->regs[0xd8] = 0xff; dev->regs[0xd9] = 0x00; dev->regs[0xda] = 0x27; dev->regs[0xdb] = 0x00; dev->regs[0xdc] = 0x00; dev->regs[0xdd] = 0x00; dev->regs[0xde] = 0x00; dev->regs[0xdf] = 0x00; dev->regs[0xe0] = 0x00; dev->regs[0xe1] = 0x00; dev->regs[0xe2] = 0x01; dev->regs[0xe3] = 0x00; dev->regs[0xe4] = 0x00; /*dev->regs[0xe5] = 0x14; dev->regs[0xe6] = 0x00; 14=20 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 20); dev->regs[0xe7] = 0x00; dev->regs[0xe8] = 0x00; dev->regs[0xe9] = 0x00; dev->regs[0xea] = 0x00; dev->regs[0xeb] = 0x00; dev->regs[0xec] = 0x00; dev->regs[0xed] = 0x00; dev->regs[0xee] = 0x00; dev->regs[0xef] = 0x00; dev->regs[0xf0] = 0x00; dev->regs[0xf1] = 0x00; dev->regs[0xf2] = 0x00; dev->regs[0xf3] = 0x00; break; case SENSOR_TYPE_4400: case SENSOR_TYPE_4400_BARE: for (i = 0; i < dev->reg_count; i++) dev->regs[i] = 0x00; /* 2d may be 0x20 or 0x22: signals something */ dev->regs[0x00] = 0xf5; dev->regs[0x01] = 0x41; dev->regs[0x0b] = 0x70; dev->regs[0x10] = 0x50; dev->regs[0x11] = 0x03; dev->regs[0x12] = 0xff; dev->regs[0x13] = 0x3e; dev->regs[0x16] = 0xff; dev->regs[0x17] = 0x3e; dev->regs[0x1d] = 0x22; dev->regs[0x22] = 0x01; dev->regs[0x23] = 0xff; dev->regs[0x25] = 0xfe; dev->regs[0x34] = 0x10; dev->regs[0x39] = 0x02; dev->regs[0x40] = 0x80; dev->regs[0x44] = 0x8c; dev->regs[0x45] = 0x76; dev->regs[0x50] = 0x20; dev->regs[0x8b] = 0xff; dev->regs[0x8c] = 0x3f; dev->regs[0x8d] = 0x80; dev->regs[0x8e] = 0x68; dev->regs[0x93] = 0x01; dev->regs[0x94] = 0x1e; dev->regs[0xa3] = 0xcc; dev->regs[0xa4] = 0x27; dev->regs[0xa5] = 0x64; dev->regs[0xb0] = 0x80; dev->regs[0xb1] = 0x01; dev->regs[0xb2] = 0x06; dev->regs[0xd4] = 0x01; dev->regs[0xd5] = 0x06; dev->regs[0xd6] = 0x1b; dev->regs[0xd7] = 0x10; dev->regs[0xd8] = 0x7a; dev->regs[0xda] = 0xa7; dev->regs[0xe5] = 0x0f; if (dev->sensor == SENSOR_TYPE_4400_BARE) { dev->regs[0x30] = 0x40; /* 0x00 */ dev->regs[0x31] = 0x80; /* 0x00 */ dev->regs[0x44] = 0x00; /* 0x8c */ dev->regs[0x45] = 0x00; /* 0x76 */ dev->regs[0x52] = 0x04; /* 0x00 */ dev->regs[0x69] = 0x01; /* 0x00 */ dev->regs[0x6a] = 0x10; /* 0x00 */ dev->regs[0x6e] = 0x08; /* 0x00 */ dev->regs[0x70] = 0x40; /* 0x00 */ dev->regs[0x71] = 0x08; /* 0x00 */ dev->regs[0x78] = 0x08; /* 0x00 */ dev->regs[0x79] = 0x11; /* 0x00 */ dev->regs[0x82] = 0x40; /* 0x00 */ dev->regs[0x83] = 0x30; /* 0x00 */ dev->regs[0x84] = 0x45; /* 0x00 */ dev->regs[0x87] = 0x02; /* 0x00 */ dev->regs[0x88] = 0x05; /* 0x00 */ dev->regs[0x8b] = 0x01; /* 0xff */ dev->regs[0x8c] = 0x80; /* 0x3f */ dev->regs[0x8d] = 0x04; /* 0x80 */ dev->regs[0x8e] = 0x10; /* 0x68 */ dev->regs[0x8f] = 0x01; /* 0x00 */ dev->regs[0x90] = 0x80; /* 0x00 */ } break; } return SANE_STATUS_GOOD; } /* * This function intializes the device: * - initial registers values * - test if at home * - head parking if needed */ static SANE_Status init_device (struct Rts8891_Device *dev) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte control, reg, id; SANE_Int i, page; SANE_Byte buffer[2072]; char message[256 * 6]; SANE_Int val; /* these commands are used to acces NVRAM through a serial manner */ /* we ignore NVRAM settingsd for now */ SANE_Byte nv_cmd1[21] = { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x08 }; SANE_Byte nv_cmd2[21] = { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08 }; SANE_Byte nv_cmd3[21] = { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08 }; SANE_Byte nv_cmd4[21] = { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08, 0x18, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x08 }; SANE_Byte nv_cmd5[21] = { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08 }; SANE_Byte nv_cmd6[21] = { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x28, 0x38, 0x08 }; SANE_Byte nv_cmd7[21] = { 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x28, 0x38, 0x08, 0x18, 0x28, 0x38, 0x08, 0x18, 0x08, 0x18, 0x08, 0x18, 0x08 }; DBG (DBG_proc, "init_device: start\n"); if (dev->initialized == SANE_TRUE) return SANE_STATUS_GOOD; /* read control register, if busy, something will have to be done ... */ sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); DBG (DBG_io, "init_device: control=0x%02x\n", control); /* when just plugged, we expect to get 0x04 */ if (control != 0x04) { DBG (DBG_warn, "init_device: expected control=0x04, got 0x%02x\n", control); } /* then read "link" register */ sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control); DBG (DBG_io, "init_device: link=0x%02x\n", control); /* we expect to get 0x80 */ if (control != 0x80) { DBG (DBG_warn, "init_device: expected link=0x80, got 0x%02x\n", control); } /* reads scanner status */ sanei_rts88xx_get_status (dev->devnum, dev->regs); DBG (DBG_io, "init_device: status=0x%02x 0x%02x\n", dev->regs[0x10], dev->regs[0x11]); /* reads lamp status and sensor information */ sanei_rts88xx_get_lamp_status (dev->devnum, dev->regs); DBG (DBG_io, "init_device: lamp status=0x%02x\n", dev->regs[0x8e]); /* initalize sensor with default from model */ dev->sensor = dev->model->sensor; DBG (DBG_info, "init_device: reg[8e]=0x%02x\n", dev->regs[0x8e]); /* reset lamp */ sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); if ((dev->regs[0x8e] & 0x60) != 0x60) { DBG (DBG_info, "init_device: lamp needs warming\n"); dev->needs_warming = SANE_TRUE; } else { dev->needs_warming = SANE_FALSE; } /* reads lcd panel status */ sanei_rts88xx_get_lcd (dev->devnum, dev->regs); DBG (DBG_io, "init_device: lcd panel=0x%02x 0x%02x 0x%02x\n", dev->regs[0x20], dev->regs[0x21], dev->regs[0x22]); /* read mainboard ID/scanner present register */ sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &id); DBG (DBG_io, "init_device: link=0x%02x\n", id); /* only known ID is currently 0x00 or 0x01 */ if (id != 0x00 && id != 0x01) { DBG (DBG_warn, "init_device: expected id=0x00 or 0x01, got 0x%02x\n", id); } /* write 0x00 twice to control */ control = 0x00; sanei_rts88xx_write_control (dev->devnum, control); sanei_rts88xx_write_control (dev->devnum, control); /* read initial register set */ sanei_rts88xx_read_regs (dev->devnum, 0, dev->regs, dev->reg_count); if (DBG_LEVEL > DBG_io2) { sprintf (message, "init_device: initial register settings: "); for (i = 0; i < dev->reg_count; i++) sprintf (message + strlen (message), "0x%02x ", dev->regs[i]); DBG (DBG_io2, "%s\n", message); } /* initial sensor guess */ val = dev->regs[0x44] + 256 * dev->regs[0x45]; DBG (DBG_io, "init_device: R44/45=0x%04x\n", val); if (dev->sensor == SENSOR_TYPE_4400) { if(val != 0x00) { DBG (DBG_info, "init_device: SENSOR_TYPE_4400 detected\n"); } else { DBG (DBG_info, "init_device: SENSOR_TYPE_4400_BARE detected\n"); dev->sensor = SENSOR_TYPE_4400_BARE; } } init_registers(dev); sanei_rts88xx_set_offset (dev->regs, 31, 31, 31); sanei_rts88xx_set_gain (dev->regs, 10, 10, 10); dev->regs[0] = dev->regs[0] & 0xef; rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); /* now read button status read_reg(0x1a,2)=0x00 0x00 */ sanei_rts88xx_read_regs (dev->devnum, 0x1a, dev->regs + 0x1a, 2); /* we expect 0x00 0x00 here */ DBG (DBG_io, "init_device: 0x%02x 0x%02x\n", dev->regs[0x1a], dev->regs[0x1b]); dev->regs[0xcf] = 0x00; dev->regs[0xd0] = 0xe0; rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); sanei_rts88xx_read_regs (dev->devnum, 0x1a, dev->regs + 0x1a, 2); /* we expect 0x08 0x00 here */ DBG (DBG_io, "init_device: 0x%02x 0x%02x\n", dev->regs[0x1a], dev->regs[0x1b]); sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x20, 0x28); sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); sanei_rts88xx_cancel (dev->devnum); sanei_rts88xx_read_reg (dev->devnum, LAMP_REG, &control); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &id); if (id != 0x00 && id != 0x01) { DBG (DBG_warn, "init_device: got unexpected id 0x%02x\n", id); } dev->regs[0x12] = 0xff; dev->regs[0x14] = 0xf8; dev->regs[0x15] = 0x28; dev->regs[0x16] = 0x07; dev->regs[0x18] = 0xff; dev->regs[0x23] = 0xff; dev->regs[0x24] = 0xff; dev->regs[0x72] = 0xe1; dev->regs[0x73] = 0x14; dev->regs[0x74] = 0x18; dev->regs[0x75] = 0x15; dev->regs[0xc0] = 0xff; dev->regs[0xc1] = 0x0f; dev->regs[0xc3] = 0xff; dev->regs[0xc4] = 0xff; dev->regs[0xc5] = 0xff; dev->regs[0xc6] = 0xff; dev->regs[0xc7] = 0xff; dev->regs[0xc8] = 0xff; dev->regs[0xca] = 0x0e; dev->regs[0xcd] = 0xf0; dev->regs[0xce] = 0xff; dev->regs[0xcf] = 0xf5; dev->regs[0xd0] = 0xf7; dev->regs[0xd1] = 0xea; dev->regs[0xd2] = 0x0b; dev->regs[0xd3] = 0x03; dev->regs[0xd4] = 0x05; dev->regs[0xd7] = 0x30; dev->regs[0xd8] = 0xf6; dev->regs[0xd9] = 0x80; rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); /* now we are writing and reading back from memory, it is surely a memory test since the written data * don't look usefull at first glance */ reg = 0x06; sanei_rts88xx_write_reg (dev->devnum, 0x93, ®); for (i = 0; i < 2072; i++) { buffer[i] = i % 97; } sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer); sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer); /* check the data returned */ for (i = 0; i < 2072; i++) { if (buffer[i] != id) { DBG (DBG_error, "init_device: memory at %d is not 0x%02d (0x%02x)\n", i, id, buffer[i]); /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */ } } DBG (DBG_info, "init_device: memory set #1 passed\n"); /* now test (or set?) #2 */ reg = 0x02; sanei_rts88xx_write_reg (dev->devnum, 0x93, ®); for (i = 0; i < 2072; i++) { buffer[i] = i % 97; } sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer); sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer); /* check the data returned */ for (i = 0; i < 970; i++) { if (buffer[i] != (i + 0x36) % 97) { DBG (DBG_error, "init_device: memory at %d is not 0x%02x (0x%02x)\n", i, (i + 0x36) % 97, buffer[i]); /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */ } } for (i = 993; i < 2072; i++) { if (buffer[i] != i % 97) { DBG (DBG_error, "init_device: memory at %d is invalid 0x%02x, instead of 0x%02x\n", i, buffer[i], i % 97); /* XXX STEF XXX return SANE_STATUS_IO_ERROR; */ } } DBG (DBG_info, "init_device: memory set #2 passed\n"); /* now test (or set?) #3 */ reg = 0x01; sanei_rts88xx_write_reg (dev->devnum, 0x93, ®); for (i = 0; i < 2072; i++) { buffer[i] = i % 97; } sanei_rts88xx_set_mem (dev->devnum, 0x81, 0x00, 2072, buffer); sanei_rts88xx_get_mem (dev->devnum, 0x81, 0x00, 2072, buffer); /* check the data returned */ for (i = 0; i < 2072; i++) { if (buffer[i] != i % 97) { DBG (DBG_error, "init_device: memory at %d is invalid 0x%02x, instead of 0x%02x\n", i, buffer[i], i % 97); return SANE_STATUS_IO_ERROR; } } DBG (DBG_info, "init_device: memory set #3 passed\n"); /* we are writing page after page the same pattern, and reading at page 0 until we find we have 'wrapped' */ /* this is surely some memory amount/number pages detection */ dev->regs[0x91] = 0x00; /* page 0 ? */ dev->regs[0x92] = 0x00; dev->regs[0x93] = 0x01; rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); /* write pattern at page 0 */ for (i = 0; i < 32; i += 2) { buffer[i] = i; buffer[i + 1] = 0x00; } sanei_rts88xx_set_mem (dev->devnum, 0x00, 0x00, 32, buffer); page = 0; do { /* next page */ page++; /* fill buffer with pattern for page */ for (i = 0; i < 32; i += 2) { buffer[i] = i; buffer[i + 1] = page; } /* write it to memory */ sanei_rts88xx_set_mem (dev->devnum, 0x00, page * 16, 32, buffer); /* read memory from page 0 */ sanei_rts88xx_get_mem (dev->devnum, 0x00, 0x00, 32, buffer); for (i = 0; i < 32; i += 2) { if (buffer[i] != i) { DBG (DBG_error, "init_device: memory at %d is invalid: 0x%02x instead of 0x%02x\n", i, buffer[i], i); return SANE_STATUS_IO_ERROR; } if (buffer[i + 1] != page && buffer[i + 1] != 0) { DBG (DBG_error, "init_device: page %d, memory at %d is invalid: 0x%02x instead of 0x%02x\n", page, i + 1, buffer[i + 1], 0); return SANE_STATUS_IO_ERROR; } } } while (buffer[1] == 0); DBG (DBG_info, "init_device: %d pages detected\n", page - 1); sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, &control); if (!(control & 0x02)) { if (park_head (dev, SANE_TRUE) != SANE_STATUS_GOOD) { DBG (DBG_error, "init_device: failed to park head!\n"); return SANE_STATUS_IO_ERROR; } } reg = 0x80; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); reg = 0xad; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); sanei_rts88xx_read_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); /* we expect 0xF8 0x28 here */ dev->regs[0x14] = dev->regs[0x14] & 0x7F; sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); /* reads scanner status */ sanei_rts88xx_get_status (dev->devnum, dev->regs); DBG (DBG_io, "init_device: status=0x%02x 0x%02x\n", dev->regs[0x10], dev->regs[0x11]); sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control); DBG (DBG_io, "init_device: link=0x%02x\n", control); sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); reg = 0x8d; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); reg = 0xad; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); /* here, we are in iddle state */ /* check link status (scanner still plugged) */ sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control); DBG (DBG_io, "init_device: link=0x%02x\n", control); /* this block appears twice */ sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if (control != 0) { DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n", control); } sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); sanei_rts88xx_read_reg (dev->devnum, 0x40, ®); reg |= 0x80; sanei_rts88xx_read_reg (dev->devnum, 0x40, ®); sanei_rts88xx_read_reg (dev->devnum, 0x10, ®); sanei_rts88xx_read_reg (dev->devnum, 0x14, ®); reg = 0x78; sanei_rts88xx_write_reg (dev->devnum, 0x10, ®); reg = 0x38; sanei_rts88xx_write_reg (dev->devnum, 0x14, ®); reg = 0x78; sanei_rts88xx_write_reg (dev->devnum, 0x10, ®); reg = 0x01; sanei_rts88xx_write_reg (dev->devnum, CONTROLER_REG, ®); /* now we init nvram */ /* this is highly dangerous and thus desactivated * in sanei_rts88xx_setup_nvram (HAZARDOUS_EXPERIMENT #define) */ sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd1); sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd2); sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd3); sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); /* second occurence of this block */ sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if (control != 0) { DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n", control); } sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); sanei_rts88xx_read_reg (dev->devnum, 0x40, ®); reg |= 0x80; sanei_rts88xx_read_reg (dev->devnum, 0x40, ®); sanei_rts88xx_read_reg (dev->devnum, 0x10, ®); sanei_rts88xx_read_reg (dev->devnum, 0x14, ®); reg = 0x78; sanei_rts88xx_write_reg (dev->devnum, 0x10, ®); reg = 0x38; sanei_rts88xx_write_reg (dev->devnum, 0x14, ®); reg = 0x78; sanei_rts88xx_write_reg (dev->devnum, 0x10, ®); reg = 0x01; sanei_rts88xx_write_reg (dev->devnum, CONTROLER_REG, ®); /* nvram again */ /* this is highly dangerous and commented out in rts88xx_lib */ sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd4); sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd5); sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd6); sanei_rts88xx_setup_nvram (dev->devnum, 21, nv_cmd7); sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); /* then we do a simple scan to detect a black zone to locate scan area */ sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if (control != 0) { DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n", control); } sanei_rts88xx_reset_lamp (dev->devnum, dev->regs); sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if (control != 0) { DBG (DBG_warn, "init_device: unexpected control value 0x%02x\n", control); } sanei_rts88xx_write_control (dev->devnum, 0x01); sanei_rts88xx_write_control (dev->devnum, 0x01); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); dev->regs[0x12] = 0xff; dev->regs[0x13] = 0x20; sanei_rts88xx_write_regs (dev->devnum, 0x12, dev->regs + 0x12, 2); dev->regs[0x14] = 0xf8; dev->regs[0x15] = 0x28; sanei_rts88xx_write_regs (dev->devnum, 0x14, dev->regs + 0x14, 2); reg = 0; sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_write_control (dev->devnum, 0x00); sanei_rts88xx_set_status (dev->devnum, dev->regs, 0x28, 0x28); reg = 0x80; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); dev->regs[0x8b] = 0xff; dev->regs[0x8c] = 0x3f; dev->regs[LAMP_REG] = 0xad; rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); set_lamp_brightness (dev, 0); dev->initialized = SANE_TRUE; DBG (DBG_proc, "init_device: exit\n"); return status; } #endif /* FAST_INIT */ #ifdef FAST_INIT /* * This function detects the scanner */ static SANE_Status detect_device (struct Rts8891_Device *dev) { /* --- 5 74945 bulk_out len 4 wrote 0x80 0xb0 0x00 0x01 --- 6 74946 bulk_in len 1 read 0x80 --- 7 74947 bulk_out len 4 wrote 0x80 0xb3 0x00 0x01 --- 8 74948 bulk_in len 1 read 0x04 --- 9 74949 bulk_out len 4 wrote 0x80 0xb1 0x00 0x01 --- 10 74950 bulk_in len 1 read 0x00 --- 11 74951 bulk_out len 5 wrote 0x88 0xb3 0x00 0x01 0x00 --- 12 74952 bulk_out len 5 wrote 0x88 0xb3 0x00 0x01 0x00 --- 13 74953 bulk_out len 4 wrote 0x80 0x00 0x00 0xf4 --- 14 74954 bulk_in len 192 read 0xf5 0x41 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x70 0x00 0x00 0x00 0x00 0x60 0x1b 0xff 0x3e 0x00 0x00 0xff 0x3e 0x00 0x00 0x00 0x00 0x00 0x22 0x00 0x00 0x00 0x00 0x00 0xff 0x00 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x42 0x00 0x00 0x10 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x24 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x10 0x00 0x80 0x00 0x10 0x00 0x01 0x00 0x00 0x10 0x00 0x00 0x20 0x20 0x00 0x00 0x00 0x00 0x20 0x01 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x41 0x00 0x10 0x21 0x20 0x00 0x20 0x81 0x20 0x01 0x01 0x00 0x22 0x00 0x40 0x05 0x00 0x00 0x01 0x1e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xcc 0x27 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 --- 15 74955 bulk_in len 52 read 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x06 0x1b 0x10 0x7a 0x00 0x15 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 */ SANE_Status status = SANE_STATUS_GOOD; SANE_Byte control; char message[256 * 5]; int i; DBG (DBG_proc, "detect_device: start\n"); /* read "b0" register */ sanei_rts88xx_read_reg (dev->devnum, 0xb0, &control); DBG (DBG_io, "detect_device: reg[b0]=0x%02x\n", control); /* we expect to get 0x80 */ if (control != 0x80) { DBG (DBG_warn, "detect_device: expected reg[b0]=0x80, got 0x%02x\n", control); /* TODO : fail here ? */ } /* read control register, if busy, something will have to be done ... */ sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); /* when just plugged, we expect to get 0x04 */ if (control != 0x04) { DBG (DBG_warn, "detect_device: expected control=0x04, got 0x%02x\n", control); /* TODO ok if re-run without plugging */ } /* read "LINK" register */ sanei_rts88xx_read_reg (dev->devnum, LINK_REG, &control); DBG (DBG_io, "detect_device: LINK_REG=0x%02x\n", control); /* we expect to get 0x00 */ if (control != 0x00) { DBG (DBG_warn, "detect_device: expected LINK_REG=0x00, got 0x%02x\n", control); } /* write 0x00 twice to control: cancel/stop ? */ control = 0x00; sanei_rts88xx_write_control (dev->devnum, control); sanei_rts88xx_write_control (dev->devnum, control); /* read initial register set */ sanei_rts88xx_read_regs (dev->devnum, 0, dev->regs, dev->reg_count); if (DBG_LEVEL >= DBG_io2) { sprintf (message, "init_device: initial register settings: "); for (i = 0; i < dev->reg_count; i++) sprintf (message + strlen (message), "0x%02x ", dev->regs[i]); sprintf (message + strlen (message), "\n"); DBG (DBG_io2, message); } /* initial sensor guess */ val = dev->regs[0x44] + 256 * dev->regs[0x45]; DBG (DBG_io, "detect_device: R44/45=0x%04x\n", val); if (dev->sensor == SENSOR_TYPE_4400 && val == 0x00) { dev->sensor = SENSOR_TYPE_4400_BARE; DBG (DBG_info, "detect_device: changing to SENSOR_TYPE_4400_BARE\n"); } DBG (DBG_io, "detect_device: status=0x%02x 0x%02x\n", dev->regs[0x10], dev->regs[0x11]); DBG (DBG_io, "detect_device: lamp status=0x%02x\n", dev->regs[0x8e]); dev->initialized = SANE_FALSE; DBG (DBG_proc, "detect_device: exit\n"); return status; } #endif /** * Do dark calibration. We scan a well defined area until average pixel value * of the black area is about 0x03 for each color channel. This calibration is * currently done at 75 dpi regardless of the final scan dpi. */ static SANE_Status dark_calibration (struct Rts8891_Device *dev, int mode, int light) { SANE_Status status = SANE_STATUS_GOOD; /* red, green and blue offset, within a 't'op and 'b'ottom value */ int ro = 250, tro = 250, bro = 0; int bo = 250, tbo = 250, bbo = 0; int go = 250, tgo = 250, bgo = 0; unsigned char image[CALIBRATION_SIZE]; float global, ra, ga, ba; int num = 0; char name[32]; DBG (DBG_proc, "dark_calibration: start\n"); /* set up sensor specific bottom values */ if (dev->sensor == SENSOR_TYPE_4400) { bro = 128; bgo = 128; bbo = 128; } /* set up starting values */ sanei_rts88xx_set_gain (dev->regs, 0, 0, 0); sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + CALIBRATION_WIDTH); sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); dev->regs[0x00] = 0xe5; /* scan */ dev->regs[0x32] = 0x00; dev->regs[0x33] = 0x03; dev->regs[0x35] = 0x45; dev->regs[0x36] = 0x22; dev->regs[0x3a] = 0x43; dev->regs[0x8d] = 0x00; dev->regs[0x8e] = 0x60; dev->regs[0xb2] = 0x02; dev->regs[0xc0] = 0x06; dev->regs[0xc1] = 0xe6; dev->regs[0xc2] = 0x67; dev->regs[0xc9] = 0x07; dev->regs[0xca] = 0x00; dev->regs[0xcb] = 0xfe; dev->regs[0xcc] = 0xf9; dev->regs[0xcd] = 0x19; dev->regs[0xce] = 0x98; dev->regs[0xcf] = 0xe8; dev->regs[0xd0] = 0xea; dev->regs[0xd1] = 0xf3; dev->regs[0xd2] = 0x14; dev->regs[0xd3] = 0x02; dev->regs[0xd4] = 0x04; dev->regs[0xd6] = 0x0f; dev->regs[0xd8] = 0x52; dev->regs[0xe2] = 0x1f; /*dev->regs[0xe5] = 0x28; 28=40 dev->regs[0xe6] = 0x00; */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 40); dev->regs[0xe7] = 0x75; dev->regs[0xe8] = 0x01; dev->regs[0xe9] = 0x0b; dev->regs[0xea] = 0x54; dev->regs[0xeb] = 0x01; dev->regs[0xec] = 0x04; dev->regs[0xed] = 0xb8; dev->regs[0xef] = 0x03; dev->regs[0xf0] = 0x70; dev->regs[0xf2] = 0x01; /* handling of different sensors */ if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) { dev->regs[0xc0] = 0x67; dev->regs[0xc1] = 0x06; dev->regs[0xc2] = 0xe6; dev->regs[0xc3] = 0x98; dev->regs[0xc4] = 0xf9; dev->regs[0xc5] = 0x19; dev->regs[0xc6] = 0x67; dev->regs[0xc7] = 0x06; dev->regs[0xc8] = 0xe6; dev->regs[0xc9] = 0x01; dev->regs[0xca] = 0xf8; dev->regs[0xcb] = 0xff; dev->regs[0xcc] = 0x98; dev->regs[0xcd] = 0xf9; dev->regs[0xce] = 0x19; dev->regs[0xcf] = 0xe0; dev->regs[0xd0] = 0xe2; dev->regs[0xd1] = 0xeb; dev->regs[0xd2] = 0x0c; dev->regs[0xd7] = 0x10; dev->regs[0xda] = 0xa7; } if (dev->sensor == SENSOR_TYPE_4400) { dev->regs[0x13] = 0x39; /* 0x20 */ dev->regs[0x14] = 0xf0; /* 0xf8 */ dev->regs[0x15] = 0x29; /* 0x28 */ dev->regs[0x16] = 0x0f; /* 0x07 */ dev->regs[0x17] = 0x10; /* 0x00 */ dev->regs[0x23] = 0x00; /* 0xff */ dev->regs[0x35] = 0x48; /* 0x45 */ dev->regs[0x39] = 0x00; /* 0x02 */ dev->regs[0xe2] = 0x0f; /* 0x1f */ /* dev->regs[0xe5] = 0x52; 0x28 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */ dev->regs[0xe7] = 0x0e; /* 0x75 */ dev->regs[0xe9] = 0x0a; /* 0x0b */ dev->regs[0xea] = 0xc2; /* 0x54 */ dev->regs[0xed] = 0xf6; /* 0xb8 */ dev->regs[0xef] = 0x02; /* 0x03 */ dev->regs[0xf0] = 0xa8; /* 0x70 */ } if (dev->sensor == SENSOR_TYPE_4400_BARE) { dev->regs[0x13] = 0x39; /* 0x20 */ dev->regs[0x14] = 0xf0; /* 0xf8 */ dev->regs[0x15] = 0x29; /* 0x28 */ dev->regs[0x16] = 0x0f; /* 0x07 */ dev->regs[0x17] = 0x10; /* 0x00 */ dev->regs[0x23] = 0x00; /* 0xff */ dev->regs[0x35] = 0x48; /* 0x45 */ dev->regs[0x39] = 0x00; /* 0x02 */ dev->regs[0xda] = 0xa7; /* 0xa0 */ dev->regs[0xe2] = 0x0f; /* 0x1f */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); dev->regs[0xe7] = 0x0e; /* 0x75 */ dev->regs[0xe9] = 0x0a; /* 0x0b */ dev->regs[0xea] = 0xc2; /* 0x54 */ dev->regs[0xed] = 0xf6; /* 0xb8 */ dev->regs[0xef] = 0x02; /* 0x03 */ dev->regs[0xf0] = 0xa8; /* 0x70 */ } /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode * until each black average reaches the desired value */ sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); do { /* set scan with the values to try */ sanei_rts88xx_set_offset (dev->regs, ro, go, bo); DBG (DBG_info, "dark_calibration: trying offsets=(%d,%d,%d)\n", ro, go, bo); /* do scan */ status = rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02, CALIBRATION_SIZE, image); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "dark_calibration: failed to scan\n"); return status; } /* save scanned picture for data debugging */ if (DBG_LEVEL >= DBG_io2) { sprintf (name, "dark%03d.pnm", num); write_rgb_data (name, image, CALIBRATION_WIDTH, 1); num++; } /* we now compute the average of red pixels from the first 15 pixels */ global = average_area (SANE_TRUE, image, 15, 1, &ra, &ga, &ba); DBG (DBG_info, "dark_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n", global, ra, ga, ba); /* dichotomie ... */ if (abs (ra - DARK_TARGET) < DARK_MARGIN) { /* offset is OK */ tro = ro; bro = ro; } else { /* NOK */ if (ra > DARK_TARGET) { tro = ro; ro = (tro + bro) / 2; } if (ra < DARK_TARGET) { bro = ro; ro = (tro + bro + 1) / 2; } } /* same for blue channel */ if (abs (ba - DARK_TARGET) < DARK_MARGIN) { bbo = bo; tbo = bo; } else { /* NOK */ if (ba > DARK_TARGET) { tbo = bo; bo = (tbo + bbo) / 2; } if (ba < DARK_TARGET) { bbo = bo; bo = (tbo + bbo + 1) / 2; } } /* and for green channel */ if (abs (ga - DARK_TARGET) < DARK_MARGIN) { tgo = go; bgo = go; } else { /* NOK */ if (ga > DARK_TARGET) { tgo = go; go = (tgo + bgo) / 2; } if (ga < DARK_TARGET) { bgo = go; go = (tgo + bgo + 1) / 2; } } } while ((tro != bro) || (tgo != bgo) || (tbo != bbo)); /* store detected values in device struct */ dev->red_offset = bro; dev->green_offset = bgo; dev->blue_offset = bbo; DBG (DBG_info, "dark_calibration: final offsets=(%d,%d,%d)\n", bro, bgo, bbo); DBG (DBG_proc, "dark_calibration: exit\n"); return status; } /* * do gain calibration. We do scans until averaged values of the area match * the target code. We're doing a dichotomy again. */ static SANE_Status gain_calibration (struct Rts8891_Device *dev, int mode, int light) { SANE_Status status = SANE_STATUS_GOOD; float global, ra, ga, ba; /* previous values */ int xrg, xbg, xgg; /* current gains */ int rg, bg, gg; /* intervals for dichotomy */ int trg, tbg, tgg, bgg, brg, bbg; int num = 0; char name[32]; int width = CALIBRATION_WIDTH; int length = CALIBRATION_SIZE; unsigned char image[CALIBRATION_SIZE]; int pass = 0; int timing=0; int xstart = (dev->left_offset * 75) / dev->model->max_xdpi; DBG (DBG_proc, "gain_calibration: start\n"); /* set up starting values */ sanei_rts88xx_set_scan_area (dev->regs, 1, 2, xstart, xstart + width); sanei_rts88xx_set_offset (dev->regs, dev->red_offset, dev->green_offset, dev->blue_offset); /* same register set than dark calibration */ dev->regs[0x32] = 0x00; dev->regs[0x33] = 0x03; dev->regs[0x35] = 0x45; dev->regs[0x36] = 0x22; dev->regs[0x3a] = 0x43; dev->regs[0x8d] = 0x00; dev->regs[0x8e] = 0x60; dev->regs[0xb2] = 0x02; dev->regs[0xc0] = 0x06; dev->regs[0xc1] = 0xe6; dev->regs[0xc2] = 0x67; dev->regs[0xc9] = 0x07; dev->regs[0xca] = 0x00; dev->regs[0xcb] = 0xfe; dev->regs[0xcc] = 0xf9; dev->regs[0xcd] = 0x19; dev->regs[0xce] = 0x98; dev->regs[0xcf] = 0xe8; dev->regs[0xd0] = 0xea; dev->regs[0xd1] = 0xf3; dev->regs[0xd2] = 0x14; dev->regs[0xd3] = 0x02; dev->regs[0xd4] = 0x04; dev->regs[0xd6] = 0x0f; dev->regs[0xd8] = 0x52; dev->regs[0xe2] = 0x1f; /* dev->regs[0xe5] = 0x28; dev->regs[0xe6] = 0x00; 28=40 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 40); dev->regs[0xe7] = 0x75; dev->regs[0xe8] = 0x01; dev->regs[0xe9] = 0x0b; dev->regs[0xea] = 0x54; dev->regs[0xeb] = 0x01; dev->regs[0xec] = 0x04; dev->regs[0xed] = 0xb8; dev->regs[0xef] = 0x03; dev->regs[0xf0] = 0x70; dev->regs[0xf2] = 0x01; dev->regs[0x72] = 0xe1; dev->regs[0x73] = 0x14; dev->regs[0x74] = 0x18; dev->regs[0xc3] = 0xff; dev->regs[0xc4] = 0xff; dev->regs[0xc7] = 0xff; dev->regs[0xc8] = 0xff; dev->regs[0xd7] = 0x30; if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) { dev->regs[0xc0] = 0x67; dev->regs[0xc1] = 0x06; dev->regs[0xc2] = 0xe6; dev->regs[0xc3] = 0x98; dev->regs[0xc4] = 0xf9; dev->regs[0xc5] = 0x19; dev->regs[0xc6] = 0x67; dev->regs[0xc7] = 0x06; dev->regs[0xc8] = 0xe6; dev->regs[0xc9] = 0x01; dev->regs[0xca] = 0xf8; dev->regs[0xcb] = 0xff; dev->regs[0xcc] = 0x98; dev->regs[0xcd] = 0xf9; dev->regs[0xce] = 0x19; dev->regs[0xcf] = 0xe0; dev->regs[0xd0] = 0xe2; dev->regs[0xd1] = 0xeb; dev->regs[0xd2] = 0x0c; dev->regs[0xd3] = 0x02; dev->regs[0xd4] = 0x04; dev->regs[0xd6] = 0x0f; dev->regs[0xd7] = 0x10; dev->regs[0xd8] = 0x52; dev->regs[0xe2] = 0x1f; /* dev->regs[0xe5] = 0x28; 0028 -> 40 dev->regs[0xe6] = 0x00; */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 40); dev->regs[0xe7] = 0x75; dev->regs[0xe8] = 0x01; dev->regs[0xe9] = 0x0b; dev->regs[0xea] = 0x54; dev->regs[0xeb] = 0x01; dev->regs[0xec] = 0x04; dev->regs[0xed] = 0xb8; dev->regs[0xef] = 0x03; dev->regs[0xf0] = 0x70; dev->regs[0xf2] = 0x01; } if (dev->sensor == SENSOR_TYPE_4400) { dev->regs[0x35] = 0x48; /* 0x45 */ /* c5, c6 ? : untouched from previous scan ... */ dev->regs[0xe2] = 0x0f; /* 0x1f */ /* dev->regs[0xe5] = 0x52; */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */ dev->regs[0xe7] = 0x0e; /* 0x75 */ dev->regs[0xe9] = 0x0a; /* 0x0b */ dev->regs[0xea] = 0xc2; /* 0x54 */ dev->regs[0xed] = 0xf6; /* 0xb8 */ dev->regs[0xef] = 0x02; /* 0x03 */ dev->regs[0xf0] = 0xa8; /* 0x70 */ } if (dev->sensor == SENSOR_TYPE_4400_BARE) { dev->regs[0x13] = 0x39; dev->regs[0x14] = 0xf0; dev->regs[0x15] = 0x29; dev->regs[0x16] = 0x0f; dev->regs[0x17] = 0x10; dev->regs[0x23] = 0x00; dev->regs[0x35] = 0x48; dev->regs[0x39] = 0x00; dev->regs[0xe2] = 0x0f; SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); dev->regs[0xe7] = 0x0e; dev->regs[0xe9] = 0x0a; dev->regs[0xea] = 0xc2; dev->regs[0xed] = 0xf6; dev->regs[0xef] = 0x02; dev->regs[0xf0] = 0xa8; timing=0x32; dev->regs[0x85] = 0x00; dev->regs[0x86] = 0x06; dev->regs[0x87] = 0x00; dev->regs[0x88] = 0x06; } SET_DOUBLE (dev->regs, TIMING_REG, timing); SET_DOUBLE (dev->regs, TIMING1_REG, timing+1); SET_DOUBLE (dev->regs, TIMING2_REG, timing+2); /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode until each white average * reaches the desired value, doing a dichotomy */ rg = 0x1f; bg = 0x1f; gg = 0x1f; /* dichotomy interval */ /* bottom values */ brg = 0; bgg = 0; bbg = 0; /* top values */ trg = 0x1f; tgg = 0x1f; tbg = 0x1f; /* loop on gain calibration until we find until we find stable value * or we do more than 20 tries */ do { /* store current values as previous */ xrg = rg; xbg = bg; xgg = gg; /* set up for scan */ DBG (DBG_info, "gain_calibration: trying gains=(0x%02x,0x%02x,0x%02x)\n", rg, gg, bg); sanei_rts88xx_set_gain (dev->regs, rg, gg, bg); sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); /* scan on line in RGB */ status = rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02, length, image); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gain_calibration: failed scan data\n"); return status; } /* save scanned picture for data debugging */ if (DBG_LEVEL >= DBG_io2) { sprintf (name, "gain%03d.pnm", num); write_rgb_data (name, image, width, 1); num++; } /* we now compute the average pixel value on the scanned line */ /* TODO use computed left margin */ global = average_area (SANE_TRUE, image, width, 1, &ra, &ga, &ba); DBG (DBG_info, "gain_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n", global, ra, ga, ba); /* dichotomy again ... */ if (abs (ra - RED_GAIN_TARGET) < GAIN_MARGIN) { /* gain is OK, it is whitin the tolerance margin */ trg = rg; brg = rg; } else { /* average is higher than the desired value */ if (ra > RED_GAIN_TARGET) { /* changing gain for another channel alters other output */ /* a stable value is shown by top value == bottom value */ if (trg == brg) { brg--; rg = brg; } else { /* since we'ra above target value, current gain becomes top value */ trg = rg; rg = (trg + brg) / 2; } } else /* below target value */ { if (trg == brg) { trg++; rg = trg; } else { /* since we are below target, current value is assigned to bottom value */ brg = rg; rg = (trg + brg + 1) / 2; } } } /* same for blue channel */ if (abs (ba - BLUE_GAIN_TARGET) < GAIN_MARGIN) { bbg = bg; tbg = bg; } else { /* NOK */ if (ba > BLUE_GAIN_TARGET) { if (tbg == bbg) { bbg--; bg = bbg; } else { tbg = bg; bg = (tbg + bbg) / 2; } } else { if (tbg == bbg) { tbg++; bg = tbg; } else { bbg = bg; bg = (tbg + bbg + 1) / 2; } } } /* and for green channel */ if (abs (ga - GREEN_GAIN_TARGET) < GAIN_MARGIN) { tgg = gg; bgg = gg; } else { /* NOK */ if (ga > GREEN_GAIN_TARGET) { if (tgg == bgg) { bgg--; gg = bgg; } else { tgg = gg; gg = (tgg + bgg) / 2; } } else { if (tgg == bgg) { tgg++; gg = tgg; } else { bgg = gg; gg = (tgg + bgg + 1) / 2; } } } pass++; } while ((pass < 20) && ((trg != brg && xrg != rg) || (tgg != bgg && xgg != gg) || (tbg != bbg && xbg != bg))); /* store detected values in device struct */ dev->red_gain = brg; dev->green_gain = bgg; dev->blue_gain = bbg; DBG (DBG_info, "gain_calibration: gain=(0x%02x,0x%02x,0x%02x)\n", brg, bgg, bbg); DBG (DBG_proc, "gain_calibration: exit\n"); return status; } /** * Do fine offset calibration. Scans are done with gains from gain calibration * at 75 dpi regardless of the dpi of the final scan. We loop scanning a 637 * (1911 bytes) pixels wide area in color mode until each black average * reaches the desired value (OFFSET_TARGET). */ static SANE_Status offset_calibration (struct Rts8891_Device *dev, int mode, int light) { SANE_Status status = SANE_STATUS_GOOD; /* red, green and blue offset, within a 't'op and 'b'ottom value */ int ro = 250, tro = 250, bro = 123; int go = 250, tgo = 250, bgo = 123; int bo = 250, tbo = 250, bbo = 123; unsigned char image[CALIBRATION_SIZE]; float global, ra, ga, ba; int num = 0; char name[32]; DBG (DBG_proc, "offset_calibration: start\n"); /* set up starting values */ /* gains from previous step are a little higher than the one used */ sanei_rts88xx_set_gain (dev->regs, dev->red_gain, dev->green_gain, dev->blue_gain); sanei_rts88xx_set_scan_area (dev->regs, 1, 2, 4, 4 + CALIBRATION_WIDTH); dev->regs[0x32] = 0x00; dev->regs[0x33] = 0x03; dev->regs[0x35] = 0x45; dev->regs[0x36] = 0x22; dev->regs[0x3a] = 0x43; dev->regs[0x8d] = 0x00; dev->regs[0x8e] = 0x60; dev->regs[0xb2] = 0x02; dev->regs[0xc0] = 0x06; dev->regs[0xc1] = 0xe6; dev->regs[0xc2] = 0x67; dev->regs[0xc9] = 0x07; dev->regs[0xca] = 0x00; dev->regs[0xcb] = 0xfe; dev->regs[0xcc] = 0xf9; dev->regs[0xcd] = 0x19; dev->regs[0xce] = 0x98; dev->regs[0xcf] = 0xe8; dev->regs[0xd0] = 0xea; dev->regs[0xd1] = 0xf3; dev->regs[0xd2] = 0x14; dev->regs[0xd3] = 0x02; dev->regs[0xd4] = 0x04; dev->regs[0xd6] = 0x0f; dev->regs[0xd8] = 0x52; dev->regs[0xe2] = 0x1f; /* dev->regs[0xe5] = 0x28; dev->regs[0xe6] = 0x00; 0x0028=40 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 40); dev->regs[0xe7] = 0x75; dev->regs[0xe8] = 0x01; dev->regs[0xe9] = 0x0b; dev->regs[0xea] = 0x54; dev->regs[0xeb] = 0x01; dev->regs[0xec] = 0x04; dev->regs[0xed] = 0xb8; dev->regs[0xef] = 0x03; dev->regs[0xf0] = 0x70; dev->regs[0xf2] = 0x01; if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) { dev->regs[0x72] = 0xe1; dev->regs[0x73] = 0x14; dev->regs[0x74] = 0x18; dev->regs[0xc0] = 0x67; dev->regs[0xc1] = 0x06; dev->regs[0xc2] = 0xe6; dev->regs[0xc3] = 0x98; dev->regs[0xc4] = 0xf9; dev->regs[0xc5] = 0x19; dev->regs[0xc6] = 0x67; dev->regs[0xc7] = 0x06; dev->regs[0xc8] = 0xe6; dev->regs[0xc9] = 0x01; dev->regs[0xca] = 0xf8; dev->regs[0xcb] = 0xff; dev->regs[0xcc] = 0x98; dev->regs[0xcd] = 0xf9; dev->regs[0xce] = 0x19; dev->regs[0xcf] = 0xe0; dev->regs[0xd0] = 0xe2; dev->regs[0xd1] = 0xeb; dev->regs[0xd2] = 0x0c; dev->regs[0xd7] = 0x10; } if (dev->sensor == SENSOR_TYPE_4400) { dev->regs[0x35] = 0x48; /* 0x45 */ /* c5,c6 ?? */ dev->regs[0xe2] = 0x0f; /* 0x1f */ /* dev->regs[0xe5] = 0x52; 0x28 */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */ dev->regs[0xe7] = 0x0e; /* 0x75 */ dev->regs[0xe9] = 0x0a; /* 0x0b */ dev->regs[0xea] = 0xc2; /* 0x54 */ dev->regs[0xed] = 0xf6; /* 0xb8 */ dev->regs[0xef] = 0x02; /* 0x03 */ dev->regs[0xf0] = 0xa8; /* 0x70 */ } if (dev->sensor == SENSOR_TYPE_4400_BARE) { dev->regs[0x13] = 0x39; /* 0x20 */ dev->regs[0x14] = 0xf0; /* 0xf8 */ dev->regs[0x15] = 0x29; /* 0x28 */ dev->regs[0x16] = 0x0f; /* 0x07 */ dev->regs[0x17] = 0x10; /* 0x00 */ dev->regs[0x23] = 0x00; /* 0xff */ dev->regs[0x35] = 0x48; /* 0x45 */ dev->regs[0x39] = 0x00; /* 0x02 */ dev->regs[0xe2] = 0x0f; /* 0x1f */ SET_DOUBLE (dev->regs, EXPOSURE_REG, 82); /* 2*40+2 */ dev->regs[0xe7] = 0x0e; /* 0x75 */ dev->regs[0xe9] = 0x0a; /* 0x0b */ dev->regs[0xea] = 0xc2; /* 0x54 */ dev->regs[0xed] = 0xf6; /* 0xb8 */ dev->regs[0xef] = 0x02; /* 0x03 */ dev->regs[0xf0] = 0xa8; /* 0x70 */ } /* we loop scanning a 637 (1911 bytes) pixels wide area in color mode until each black average * reaches the desired value */ do { DBG (DBG_info, "offset_calibration: trying offsets=(%d,%d,%d) ...\n", ro, go, bo); sanei_rts88xx_set_offset (dev->regs, ro, go, bo); sanei_rts88xx_set_status (dev->devnum, dev->regs, mode, light); rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, 0x02, CALIBRATION_SIZE, image); /* save scanned picture for data debugging */ if (DBG_LEVEL >= DBG_io2) { sprintf (name, "offset%03d.pnm", num); write_rgb_data (name, image, CALIBRATION_WIDTH, 1); num++; } /* we now compute the average of red pixels from the first 15 pixels */ global = average_area (SANE_TRUE, image, 15, 1, &ra, &ga, &ba); DBG (DBG_info, "offset_calibration: global=%.2f, channels=(%.2f,%.2f,%.2f)\n", global, ra, ga, ba); /* dichotomie ... */ if (abs (ra - OFFSET_TARGET) < OFFSET_MARGIN) { /* offset is OK */ tro = ro; bro = ro; } else { /* NOK */ if (ra > OFFSET_TARGET) { tro = ro; ro = (tro + bro) / 2; } if (ra < OFFSET_TARGET) { bro = ro; ro = (tro + bro + 1) / 2; } } /* same for blue channel */ if (abs (ba - OFFSET_TARGET) < OFFSET_MARGIN) { bbo = bo; tbo = bo; } else { if (ba > OFFSET_TARGET) { tbo = bo; bo = (tbo + bbo) / 2; } if (ba < OFFSET_TARGET) { bbo = bo; bo = (tbo + bbo + 1) / 2; } } /* and for green channel */ if (abs (ga - OFFSET_TARGET) < OFFSET_MARGIN) { tgo = go; bgo = go; } else { if (ga > OFFSET_TARGET) { tgo = go; go = (tgo + bgo) / 2; } if (ga < OFFSET_TARGET) { bgo = go; go = (tgo + bgo + 1) / 2; } } } while ((tro != bro) || (tgo != bgo) || (tbo != bbo)); /* store detected values in device struct */ dev->red_offset = bro; dev->green_offset = bgo; dev->blue_offset = bbo; DBG (DBG_proc, "offset_calibration: exit\n"); return status; } /* * do shading calibration * We scan a 637 pixels by 66 linesxoffset=24 , xend=661, pixels=637 y offset=1 , yend=67, lines =66 */ #ifndef UNIT_TESTING static #endif SANE_Status setup_shading_calibration (struct Rts8891_Device *dev, int mode, int *light, int *status1, SANE_Byte * regs) { SANE_Status status = SANE_STATUS_GOOD; int lines = 66; int exposure=0; int timing=0; DBG (DBG_proc, "setup_shading_calibration: start\n"); DBG (DBG_info, "setup_shading_calibration: sensor type is %s (%d)\n", sensor_name (dev->sensor), dev->sensor); /* set up registers */ /* 0x20/0x28 0x3b/0x3f seen in logs */ *status1 = mode; if (dev->xdpi > 300) { *status1 |= 0x08; } /* we default to 75 dpi then override needed registers */ timing=0x00b0; regs[0x32] = 0x20; regs[0x33] = 0x83; regs[0x35] = 0x0e; regs[0x36] = 0x2c; regs[0x3a] = 0x0e; regs[0xe2] = 0x05; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0xf2] = 0x00; /* regs[0xe5] = 0xdd; */ exposure=221; if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) { regs[0xc0] = 0x67; regs[0xc1] = 0x06; regs[0xc2] = 0xe6; regs[0xc3] = 0x98; regs[0xc4] = 0xf9; regs[0xc5] = 0x19; regs[0xc6] = 0x67; regs[0xc7] = 0x06; regs[0xc8] = 0xe6; regs[0xc9] = 0x01; regs[0xca] = 0xf8; regs[0xcb] = 0xff; regs[0xcc] = 0x98; regs[0xcd] = 0xf9; regs[0xce] = 0x19; regs[0xcf] = 0xe0; regs[0xd0] = 0xe2; regs[0xd1] = 0xeb; regs[0xd2] = 0x0c; regs[0xd7] = 0x10; } if (dev->sensor == SENSOR_TYPE_4400) { *light &= 0xf7; /* clear bit 3 */ regs[0x36] = 0x29; /* 0x2c */ timing=0x0032; regs[0x85] = 0x00; /* 0x8c */ regs[0x86] = 0x06; /* 0x10 */ regs[0x87] = 0x00; /* 0x18 */ regs[0x88] = 0x06; /* 0x1b */ regs[0x8d] = 0x00; /* 0x77 */ /* c5,c6 ?? */ /* regs[0xd3] = 0x02; 0x0e */ regs[0xd4] = 0x04; /* 0x10 */ regs[0xe2] = 0x02; /* 0x05 */ /* regs[0xe5] = 0xbb; regs[0xe6] = 0x01; 1bb =443 */ exposure=443; } if (dev->sensor == SENSOR_TYPE_4400_BARE) { regs[0x13] = 0x39; /* 0x20 */ regs[0x14] = 0xf0; /* 0xf8 */ regs[0x15] = 0x29; /* 0x28 */ regs[0x16] = 0x0f; /* 0x07 */ regs[0x17] = 0x10; /* 0x00 */ regs[0x23] = 0x00; /* 0xff */ regs[0x36] = 0x29; /* 0x2c */ regs[0x39] = 0x00; /* 0x02 */ regs[0xe2] = 0x02; /* 0x05 */ exposure=443; } switch (dev->xdpi) { case 75: break; case 150: /* X resolution related registers */ switch (dev->sensor) { case SENSOR_TYPE_XPA: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 150 dpi\n"); timing=0x022b; regs[0x85] = 0x18; regs[0x86] = 0x1b; regs[0x87] = 0x30; regs[0x88] = 0x30; regs[0x8d] = 0xef; regs[0xc0] = 0x00; regs[0xc1] = 0x8e; regs[0xc2] = 0xff; regs[0xc3] = 0xff; regs[0xc4] = 0x71; regs[0xc5] = 0x00; regs[0xc6] = 0x00; regs[0xc7] = 0x8e; regs[0xc8] = 0xff; regs[0xc9] = 0xff; regs[0xca] = 0xff; regs[0xcb] = 0x1f; regs[0xcc] = 0xff; regs[0xcd] = 0x71; regs[0xce] = 0x00; regs[0xcf] = 0xe6; regs[0xd0] = 0xe8; regs[0xd1] = 0xf6; regs[0xd2] = 0x17; /* regs[0xd3] = 0x0b; */ regs[0xd4] = 0x0d; /* regs[0xe5] = 0xe4; */ exposure=228; break; case SENSOR_TYPE_BARE: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 150 dpi\n"); timing=0x012e; regs[0x85] = 0x8c; regs[0x86] = 0x10; regs[0x87] = 0x18; regs[0x88] = 0x1b; regs[0x8d] = 0x77; regs[0xc0] = 0x80; regs[0xc1] = 0x87; regs[0xc2] = 0x7f; regs[0xc9] = 0x00; regs[0xcb] = 0x78; regs[0xcc] = 0x7f; regs[0xcd] = 0x78; regs[0xce] = 0x80; regs[0xcf] = 0xe6; regs[0xd0] = 0xe8; regs[0xd1] = 0xf7; regs[0xd2] = 0x00; /* regs[0xd3] = 0x0e; */ regs[0xd4] = 0x10; /* regs[0xe5] = 0xe4; */ exposure=228; break; case SENSOR_TYPE_4400: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 150 dpi\n"); timing=0x012e; regs[0x85] = 0x8c; regs[0x86] = 0x10; regs[0x87] = 0x18; regs[0x88] = 0x1b; regs[0x8d] = 0x77; regs[0xc0] = 0x00; regs[0xc1] = 0x8e; regs[0xc2] = 0xff; regs[0xc3] = 0xff; regs[0xc4] = 0x71; regs[0xc5] = 0x00; regs[0xc6] = 0x00; regs[0xc7] = 0x8e; regs[0xc8] = 0xff; regs[0xc9] = 0xff; regs[0xca] = 0xff; regs[0xcb] = 0x1f; regs[0xcc] = 0xff; regs[0xcd] = 0x71; regs[0xce] = 0x00; regs[0xcf] = 0xe6; regs[0xd0] = 0xe8; regs[0xd1] = 0xf6; regs[0xd2] = 0x17; /* regs[0xd3] = 0x0b; */ regs[0xd4] = 0x0d; exposure=457; break; case SENSOR_TYPE_4400_BARE: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 150 dpi\n"); regs[0x13] = 0x39; /* 0x20 */ regs[0x14] = 0xf0; /* 0xf8 */ regs[0x15] = 0x29; /* 0x28 */ regs[0x16] = 0x0f; /* 0x07 */ regs[0x17] = 0x10; /* 0x00 */ regs[0x23] = 0x00; /* 0xff */ regs[0x36] = 0x29; /* 0x2c */ regs[0x39] = 0x00; /* 0x02 */ timing=0x00b0; regs[0x85] = 0x46; /* 0x00 */ regs[0x86] = 0x0b; /* 0x06 */ regs[0x87] = 0x8c; /* 0x00 */ regs[0x88] = 0x10; /* 0x06 */ regs[0x8d] = 0x3b; /* 0x00 */ regs[0xc0] = 0xff; /* 0x06 */ regs[0xc1] = 0x0f; /* 0xe6 */ regs[0xc2] = 0x00; /* 0x67 */ regs[0xc9] = 0x00; /* 0x07 */ regs[0xca] = 0x0e; /* 0x00 */ regs[0xcb] = 0x00; /* 0xfe */ regs[0xcc] = 0x00; /* 0xf9 */ regs[0xcd] = 0xf0; /* 0x19 */ regs[0xce] = 0xff; /* 0x98 */ regs[0xcf] = 0xf5; /* 0xe8 */ regs[0xd0] = 0xf7; /* 0xea */ regs[0xd1] = 0xea; /* 0xf3 */ regs[0xd2] = 0x0b; /* 0x14 */ /* regs[0xd3] = 0x17; 0x02 */ regs[0xd4] = 0x01; /* 0x04 */ regs[0xe2] = 0x02; /* 0x05 */ /* regs[0xe5] = 0x93; regs[0xe6] = 0x03; */ exposure=915; break; } break; case 300: switch (dev->sensor) { case SENSOR_TYPE_XPA: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 300 dpi\n"); timing=0x00b0; regs[0x85] = 0x46; regs[0x86] = 0x0b; regs[0x87] = 0x8c; regs[0x88] = 0x10; regs[0x8d] = 0x3b; regs[0xc0] = 0x00; regs[0xc1] = 0xff; regs[0xc2] = 0x0f; regs[0xc3] = 0xff; regs[0xc4] = 0x00; regs[0xc5] = 0xf0; regs[0xc6] = 0x00; regs[0xc7] = 0xff; regs[0xc8] = 0x0f; regs[0xc9] = 0xff; regs[0xca] = 0xff; regs[0xcb] = 0xf1; regs[0xcc] = 0xff; regs[0xcd] = 0x00; regs[0xce] = 0xf0; regs[0xcf] = 0xed; regs[0xd0] = 0xef; regs[0xd1] = 0xe2; regs[0xd2] = 0x03; /* regs[0xd3] = 0x17; */ regs[0xd4] = 0x01; /* regs[0xe5] = 0xc9; regs[0xe6] = 0x01; 0x01c9=457 */ exposure=457; break; case SENSOR_TYPE_BARE: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 300 dpi\n"); timing=0x012e; regs[0x85] = 0x8c; regs[0x86] = 0x10; regs[0x87] = 0x18; regs[0x88] = 0x1b; regs[0x8d] = 0xde; regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to the scanned width 1de => 5100 wide scan */ regs[0xc0] = 0xff; regs[0xc1] = 0x0f; regs[0xc2] = 0x00; regs[0xc9] = 0x00; regs[0xca] = 0x0e; regs[0xcb] = 0x00; regs[0xcc] = 0x00; regs[0xcd] = 0xf0; regs[0xce] = 0xff; regs[0xcf] = 0xf5; regs[0xd0] = 0xf7; regs[0xd1] = 0xea; regs[0xd2] = 0x0b; /* regs[0xd3] = 0x17; */ regs[0xd4] = 0x01; /* regs[0xe5] = 0xc9; regs[0xe6] = 0x01; 0x1c9=457 */ exposure=457; break; case SENSOR_TYPE_4400: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 300 dpi\n"); timing=0x022b; regs[0x85] = 0x18; regs[0x86] = 0x1b; regs[0x87] = 0x30; regs[0x88] = 0x30; regs[0x8d] = 0xef; regs[0xc0] = 0x00; regs[0xc1] = 0xff; regs[0xc2] = 0x0f; regs[0xc3] = 0xff; regs[0xc4] = 0x00; regs[0xc5] = 0xf0; regs[0xc6] = 0x00; regs[0xc7] = 0xff; regs[0xc8] = 0x0f; regs[0xc9] = 0xff; regs[0xca] = 0xff; regs[0xcb] = 0xf1; regs[0xcc] = 0xff; regs[0xcd] = 0x00; regs[0xce] = 0xf0; regs[0xcf] = 0xed; regs[0xd0] = 0xef; regs[0xd1] = 0xe2; regs[0xd2] = 0x03; /* regs[0xd3] = 0x17; */ regs[0xd4] = 0x01; /* 0x0393 = 915 = 2*457+1 */ exposure=915; break; case SENSOR_TYPE_4400_BARE: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 300 dpi\n"); return SANE_STATUS_INVAL; break; } break; case 600: switch (dev->sensor) { case SENSOR_TYPE_BARE: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 600 dpi\n"); regs[0x34] = 0x10; regs[0x72] = 0x3a; regs[0x73] = 0x15; regs[0x74] = 0x62; timing=0x022b; regs[0x85] = 0x18; regs[0x86] = 0x1b; regs[0x87] = 0x30; regs[0x88] = 0x30; regs[0x8d] = 0xde; regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to the scanned width 1de => 5100 wide scan */ regs[0xc0] = 0xff; regs[0xc1] = 0xff; regs[0xc2] = 0xff; regs[0xc3] = 0x00; regs[0xc4] = 0xf0; regs[0xc7] = 0x0f; regs[0xc8] = 0x00; regs[0xcb] = 0xe0; regs[0xcc] = 0xff; regs[0xcd] = 0xff; regs[0xce] = 0xff; regs[0xcf] = 0xe9; regs[0xd0] = 0xeb; regs[0xd7] = 0x14; /* regs[0xe5] = 0x93; regs[0xe6] = 0x03; 0x393=915 = 457*2+1 */ exposure=915; break; case SENSOR_TYPE_XPA: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 600 dpi\n"); *light &= 0xfb; /* clear bit 2 */ regs[0x16] = 0x07; regs[0x33] = 0x83; /* 0x86 */ regs[0x34] = 0x10; regs[0x50] = 0x00; /* 0x18 */ regs[0x64] = 0x01; /* 0x02 */ regs[0x65] = 0x20; /* 0x10 */ regs[0x72] = 0x3a; regs[0x73] = 0x15; regs[0x74] = 0x62; regs[0x85] = 0x00; regs[0x86] = 0x06; regs[0x87] = 0x00; regs[0x88] = 0x06; regs[0x8d] = 0x00; regs[0x8e] = 0x60; /* XXX STEF XXX */ regs[0xc0] = 0xf8; regs[0xc1] = 0x7f; regs[0xc2] = 0x00; regs[0xc3] = 0xf8; regs[0xc4] = 0x7f; regs[0xc5] = 0x00; regs[0xc6] = 0xf8; regs[0xc7] = 0x7f; regs[0xc8] = 0x00; regs[0xc9] = 0xff; regs[0xca] = 0x8f; regs[0xcb] = 0xff; regs[0xcc] = 0x07; regs[0xcd] = 0x80; regs[0xce] = 0xff; regs[0xcf] = 0xf2; regs[0xd0] = 0xf4; regs[0xd1] = 0xe7; regs[0xd2] = 0x08; regs[0xd3] = 0x0e; regs[0xd4] = 0x10; regs[0xd7] = 0x31; timing=0x0032; exposure=915; break; case SENSOR_TYPE_4400: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 600 dpi\n"); *light = 0x23; regs[0x13] = 0x39; regs[0x14] = 0xf0; regs[0x15] = 0x29; regs[0x16] = 0x0f; regs[0x17] = 0x10; regs[0x23] = 0x00; regs[0x34] = 0xf0; regs[0x36] = 0x29; regs[0x39] = 0x00; regs[0x72] = 0x3a; regs[0x73] = 0x15; regs[0x74] = 0x62; timing=0x0426; regs[0x85] = 0x30; regs[0x86] = 0x30; regs[0x87] = 0x60; regs[0x88] = 0x5a; regs[0x8d] = 0xde; regs[0x8e] = 0x61; regs[0xc0] = 0xf8; regs[0xc1] = 0x7f; regs[0xc2] = 0x00; regs[0xc3] = 0xf8; regs[0xc4] = 0x7f; regs[0xc5] = 0x00; regs[0xc6] = 0xf8; regs[0xc7] = 0x7f; regs[0xc8] = 0x00; regs[0xc9] = 0xff; regs[0xca] = 0x8f; regs[0xcb] = 0xff; regs[0xcc] = 0x07; regs[0xcd] = 0x80; regs[0xce] = 0xff; regs[0xcf] = 0xf2; regs[0xd0] = 0xf4; regs[0xd1] = 0xe7; regs[0xd2] = 0x08; regs[0xd3] = 0x0e; regs[0xd4] = 0x10; regs[0xd7] = 0x31; regs[0xe2] = 0x02; exposure=1832; break; case SENSOR_TYPE_4400_BARE: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 600 dpi\n"); return SANE_STATUS_INVAL; break; } break; case 1200: switch (dev->sensor) { case SENSOR_TYPE_BARE: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_BARE for 1200 dpi\n"); regs[0x34] = 0xf0; regs[0x40] = 0xa0; timing=0x0426; regs[0x85] = 0x30; regs[0x86] = 0x30; regs[0x87] = 0x60; regs[0x88] = 0x5a; regs[0x8d] = 0xbd; regs[0x8e] = 0x63; regs[0xc0] = 0xff; regs[0xc1] = 0xff; regs[0xc2] = 0xff; regs[0xc4] = 0x0f; regs[0xc5] = 0x00; regs[0xc6] = 0x00; regs[0xc7] = 0xf0; regs[0xc9] = 0x00; regs[0xca] = 0x0e; regs[0xcb] = 0x00; regs[0xcc] = 0xff; regs[0xcd] = 0xff; regs[0xce] = 0xff; regs[0xcf] = 0xf5; regs[0xd0] = 0xf7; regs[0xd1] = 0xea; regs[0xd2] = 0x0b; /* regs[0xd3] = 0x17; */ regs[0xd4] = 0xc1; regs[0xd7] = 0x14; regs[0xd8] = 0xa4; /* regs[0xe5] = 0x28; regs[0xe6] = 0x07; 0x728=1832=915*2+2 */ exposure=1832; break; case SENSOR_TYPE_XPA: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_XPA for 1200 dpi\n"); regs[0x34] = 0x10; regs[0x40] = 0xa0; timing=0x00b0; exposure=1832; /* XXX STEF XXX */ regs[0x85] = 0x46; regs[0x86] = 0x0b; regs[0x87] = 0x8c; regs[0x88] = 0x10; regs[0x8e] = 0x3b; regs[0x8d] = 0x60; regs[0xc1] = 0xff; regs[0xce] = 0xff; regs[0xcf] = 0xf5; regs[0xd0] = 0xf7; regs[0x33] = 0x83; regs[0x50] = 0x00; regs[0x64] = 0x01; regs[0x65] = 0x20; regs[0x8d] = 0xbc; regs[0xc0] = 0xe0; regs[0xc2] = 0x01; regs[0xc3] = 0x1f; regs[0xc4] = 0x00; regs[0xc5] = 0xfe; regs[0xc6] = 0xff; regs[0xc7] = 0xff; regs[0xc8] = 0x00; regs[0xc9] = 0x3f; regs[0xca] = 0xfe; regs[0xcb] = 0xff; regs[0xcc] = 0x00; regs[0xcd] = 0x00; regs[0xd1] = 0xec; regs[0xd2] = 0x0d; regs[0xd3] = 0x05; regs[0xd4] = 0x67; regs[0xd7] = 0x10; regs[0xd8] = 0x52; break; case SENSOR_TYPE_4400: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_4400 for 1200 dpi\n"); regs[0x13] = 0x39; regs[0x14] = 0xf0; regs[0x15] = 0x29; regs[0x16] = 0x0f; regs[0x17] = 0x10; regs[0x23] = 0x00; regs[0x34] = 0xf0; regs[0x36] = 0x29; regs[0x39] = 0x00; regs[0x40] = 0xa0; timing=0x0426; regs[0x85] = 0x30; regs[0x86] = 0x30; regs[0x87] = 0x60; regs[0x88] = 0x5a; regs[0x8d] = 0xde; regs[0x8e] = 0x61; regs[0xc0] = 0xe0; regs[0xc1] = 0xff; regs[0xc2] = 0x01; regs[0xc3] = 0x1f; regs[0xc4] = 0x00; regs[0xc5] = 0xfe; regs[0xc6] = 0xff; regs[0xc7] = 0xff; regs[0xc8] = 0x00; regs[0xc9] = 0x3f; regs[0xca] = 0xfe; regs[0xcb] = 0xff; regs[0xcc] = 0x00; regs[0xcd] = 0x00; regs[0xce] = 0xff; regs[0xcf] = 0xf5; regs[0xd0] = 0xf7; regs[0xd1] = 0xec; regs[0xd2] = 0x0d; /* regs[0xd3] = 0x05; */ regs[0xd4] = 0x67; regs[0xd7] = 0x10; regs[0xd8] = 0x52; regs[0xe2] = 0x02; *light = 0x23; exposure=3665; break; case SENSOR_TYPE_4400_BARE: DBG (DBG_io, "setup_shading_calibration: setting up SENSOR_TYPE_4400_BARE for 1200 dpi\n"); return SANE_STATUS_INVAL; break; } break; } /* apply computed settings */ SET_DOUBLE (regs, EXPOSURE_REG, exposure); SET_DOUBLE (regs, TIMING_REG, timing); SET_DOUBLE (regs, TIMING1_REG, timing+1); SET_DOUBLE (regs, TIMING2_REG, timing+2); /* in logs, the driver use the computed offset minus 2 */ sanei_rts88xx_set_offset (regs, dev->red_offset, dev->green_offset, dev->blue_offset); sanei_rts88xx_set_gain (regs, dev->red_gain, dev->green_gain, dev->blue_gain); sanei_rts88xx_set_scan_area (regs, 1, 1 + lines, dev->xstart, dev->xstart + dev->pixels); DBG (DBG_proc, "setup_shading_calibration: exit\n"); return status; } /* * do shading calibration * We scan a 637 pixels by 66 linesxoffset=24 , xend=661, pixels=637 y offset=1 , yend=67, lines =66 */ static SANE_Status shading_calibration (struct Rts8891_Device *dev, SANE_Bool color, int mode, int light) { SANE_Status status = SANE_STATUS_GOOD; int width; int lines = 66; SANE_Byte format; int size; int status1; int x, y, sum; SANE_Byte *image = NULL; FILE *dbg = NULL; DBG (DBG_proc, "shading_calibration: start\n"); DBG (DBG_info, "shading_calibration: sensor type is %s (%d)\n", sensor_name (dev->sensor), dev->sensor); width = dev->pixels; size = lines * dev->bytes_per_line; image = (SANE_Byte *) malloc (size); if (image == NULL) { DBG (DBG_error, "shading_calibration: failed to allocate memory for image\n"); return SANE_STATUS_NO_MEM; } if (dev->shading_data != NULL) free (dev->shading_data); dev->shading_data = (unsigned char *) malloc (dev->bytes_per_line); if (dev->shading_data == NULL) { free (image); DBG (DBG_error, "shading_calibration: failed to allocate memory for data\n"); return SANE_STATUS_NO_MEM; } /* set up registers */ status=setup_shading_calibration(dev, mode, &light, &status1, dev->regs); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "shading_calibration: failed to set up registers\n"); free (dev->shading_data); dev->shading_data = NULL; free (image); return status; } /* scan shading area */ sanei_rts88xx_set_status (dev->devnum, dev->regs, status1, light); format = rts8891_data_format (dev->xdpi, dev->sensor); status = rts8891_simple_scan (dev->devnum, dev->regs, dev->reg_count, format, size, image); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "shading_calibration: failed scan shading area\n"); free (dev->shading_data); dev->shading_data = NULL; free (image); return status; } if (DBG_LEVEL >= DBG_io2) { dbg = fopen ("shading.pnm", "wb"); if (color) { fprintf (dbg, "P6\n%d %d\n255\n", width, lines); fwrite (image, width * 3, lines, dbg); } else { fprintf (dbg, "P5\n%d %d\n255\n", width, lines); fwrite (image, width, lines, dbg); } fclose (dbg); } /* now we can compute shading calibration data */ /* we average each row */ /* we take the maximum of each row */ /* we skip first 3 lines and last 10 lines due to some bugs */ if (color) { width = width * 3; } for (x = 0; x < width; x++) { sum = 0; for (y = 3; y < lines - 10; y++) { sum += image[x + y * width]; } dev->shading_data[x] = sum / (lines - 13); } if (DBG_LEVEL >= DBG_io2) { dbg = fopen ("shading_data.pnm", "wb"); if (color) { fprintf (dbg, "P6\n%d %d\n255\n", width / 3, 1); fwrite (dev->shading_data, width, 1, dbg); } else { fprintf (dbg, "P5\n%d %d\n255\n", width, 1); fwrite (dev->shading_data, width, 1, dbg); } fclose (dbg); } free (image); DBG (DBG_proc, "shading_calibration: exit\n"); return status; } static void fill_gamma (SANE_Byte * calibration, int *idx, SANE_Word * gamma) { int i; calibration[*idx] = 0; (*idx)++; for (i = 0; i < 255; i++) { calibration[*idx] = gamma[i]; /* escape 0xaa with 0 */ if (calibration[*idx] == 0xaa) { (*idx)++; calibration[*idx] = 0; } (*idx)++; calibration[*idx] = gamma[i]; /* escape 0xaa with 0 */ if (calibration[*idx] == 0xaa) { (*idx)++; calibration[*idx] = 0; } (*idx)++; } calibration[*idx] = 0xff; (*idx)++; } /* * build and send calibration data which contains gamma table and * shading correction coefficient * */ static SANE_Status send_calibration_data (struct Rts8891_Session *session) { SANE_Status status = SANE_STATUS_GOOD; int size, width, data_size; SANE_Byte *calibration = NULL, format, val; struct Rts8891_Device *dev = session->dev; int i, idx; unsigned int value, red_code, blue_code, green_code; FILE *calib = NULL; SANE_Word *gamma_r, *gamma_g, *gamma_b; DBG (DBG_proc, "send_calibration_data: start\n"); /* 675 pixels at 75 DPI, 16 bits values, 3 color channels */ /* 5400 pixels at max sensor 600 dpi */ /* 3 16bits 256 value gamma tables plus start/end markers */ /* must multple of 32 */ data_size = (675 * dev->xdpi) / 75; width = dev->pixels; /* effective data calibration size */ size = data_size * 2 * 3 + 3 * (512 + 2); size = ((size + 31) / 32) * 32; DBG (DBG_io, "send_calibration_data: size=%d\n", size); /* * FORMAT: * 00 * 512 bytes gamma table (256 16 bit entry) * FF * 00 * 512 bytes gamma table (256 16 bit entry) * FF * 00 * 512 bytes gamma table (256 16 bit entry) * FF * 5400 max shading coefficients at 600 dpi repeated 3 times * overall size rounded at 32 bytes multiple * 675 CCD elements at 75 DPI. 16 bit per element. 1 or 3 channels. * there is a 0xFF marker at end of each coefficients row. * a gamma table comes first * 75 DPI: 5600=1542+(675)*2*3+8 ->size rounded to 'upper 32' * 150 DPI: 9664=675*2*2*3=1542+(675*2)*2*3+22 * 17760 4 +18 * 33952 8 +10 * 65472+896=66368= 16 +26 * * COEFFICIENT 16 bit value * first is 00, 0x40, 0x80 or 0xC0 => 10 significant bit * coeff*average=K => coeff=K/average */ calibration = (SANE_Byte *) malloc (size); if (calibration == NULL) { DBG (DBG_error, "send_calibration_data: failed to allocate memory for calibration data\n"); return SANE_STATUS_NO_MEM; } memset (calibration, 0x00, size); /* fill gamma tables first, markers and static gamma table */ idx = 0; /* select red gamma table */ if (session->params.format == SANE_FRAME_RGB) { /* 3 different gamma table */ gamma_r = session->val[OPT_GAMMA_VECTOR_R].wa; gamma_g = session->val[OPT_GAMMA_VECTOR_G].wa; gamma_b = session->val[OPT_GAMMA_VECTOR_B].wa; } else { /* 3 time the same gamma table */ gamma_r = session->val[OPT_GAMMA_VECTOR].wa; gamma_g = session->val[OPT_GAMMA_VECTOR].wa; gamma_b = session->val[OPT_GAMMA_VECTOR].wa; } fill_gamma (calibration, &idx, gamma_r); fill_gamma (calibration, &idx, gamma_g); fill_gamma (calibration, &idx, gamma_b); /* compute calibration coefficients */ /* real witdh != 675 --> 637 * shading data calibration starts at 1542. There are 3 rows of 16 bits values * first row is green calibration */ /* to avoid problems with 0xaa values which must be escaped, we change them * into 0xab values, which unnoticeable on scans */ for (i = 0; i < width; i++) { /* average TARGET CODE 3431046 */ /* #define RED_SHADING_TARGET_CODE 3000000 #define GREEN_SHADING_TARGET_CODE 300000 #define BLUE_SHADING_TARGET_CODE 2800000*/ #define RED_SHADING_TARGET_CODE 2800000 #define GREEN_SHADING_TARGET_CODE 2800000 #define BLUE_SHADING_TARGET_CODE 2700000 red_code = RED_SHADING_TARGET_CODE; green_code = GREEN_SHADING_TARGET_CODE; blue_code = BLUE_SHADING_TARGET_CODE; /* target code debug, will be removed for the release */ if (getenv ("RED_CODE") != NULL) { red_code = atoi (getenv ("RED_CODE")); } if (getenv ("GREEN_CODE") != NULL) { blue_code = atoi (getenv ("GREEN_CODE")); } if (getenv ("BLUE_CODE") != NULL) { green_code = atoi (getenv ("BLUE_CODE")); } /* correction coefficient is target code divided by average scanned value * but it is put in a 16 bits number. Only 10 first bits are significants. */ /* first color component red data */ if (gamma_r[dev->shading_data[i * 3]] < 5) value = 0x8000; else value = red_code / gamma_r[dev->shading_data[i * 3]]; val = (SANE_Byte) (value / 256); if (val == 0xaa) val++; calibration[idx + i * 2 + 1] = val; calibration[idx + i * 2] = (SANE_Byte) (value % 256) & 0xC0; /* second color component: green data */ if (gamma_r[dev->shading_data[i * 3 + 1]] < 5) value = 0x8000; else value = green_code / gamma_g[dev->shading_data[i * 3 + 1]]; val = (SANE_Byte) (value / 256); if (val == 0xaa) val++; calibration[idx + data_size * 2 + i * 2 + 1] = val; calibration[idx + data_size * 2 + i * 2] = (SANE_Byte) (value % 256) & 0xC0; /* third color component: blue data */ if (gamma_r[dev->shading_data[i * 3 + 2]] < 5) value = 0x8000; else value = blue_code / gamma_b[dev->shading_data[i * 3 + 2]]; val = (SANE_Byte) (value / 256); if (val == 0xaa) val++; calibration[idx + data_size * 4 + i * 2 + 1] = val; calibration[idx + data_size * 4 + i * 2] = (SANE_Byte) (value % 256) & 0xC0; } /* DEEP TRACING */ if (DBG_LEVEL >= DBG_io2) { calib = fopen ("calibration.hex", "wb"); fprintf (calib, "shading_data(%d)=", width); for (i = 0; i < width * 3; i++) { fprintf (calib, "%02x ", dev->shading_data[i]); } fprintf (calib, "\n"); fprintf (calib, "write_mem(0x00,%d)=", size); for (i = 0; i < size; i++) { fprintf (calib, "%02x ", calibration[i]); } fclose (calib); } /* signals color format/divisor from hardware */ format = rts8891_data_format (dev->xdpi, dev->sensor); status = sanei_rts88xx_write_reg (dev->devnum, 0xd3, &format); /* for some reason, we have to add 6 to the size for the first write */ /* related to the 6 0xaa in gamma table ? */ if (size > RTS88XX_MAX_XFER_SIZE) { status = sanei_rts88xx_write_mem (dev->devnum, RTS88XX_MAX_XFER_SIZE, 6, calibration); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "send_calibration_data: failed to write calibration data (part 1)\n"); return status; } size -= RTS88XX_MAX_XFER_SIZE; status = sanei_rts88xx_write_mem (dev->devnum, size, 0, calibration + RTS88XX_MAX_XFER_SIZE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "send_calibration_data: failed to write calibration data (part 2)\n"); return status; } } else { status = sanei_rts88xx_write_mem (dev->devnum, size, 6, calibration); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "send_calibration_data: failed to write calibration data\n"); return status; } } /* set mem start */ dev->regs[0x91] = 0x00; dev->regs[0x92] = 0x00; sanei_rts88xx_write_regs (dev->devnum, 0x91, dev->regs + 0x91, 2); free (calibration); DBG (DBG_proc, "send_calibration_data: exit\n"); return status; } /* move at dev->model->min_ydpi dpi up to the scanning area. Which speeds * up scanning */ static SANE_Status move_to_scan_area (struct Rts8891_Session *session) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte control; SANE_Byte regs[RTS8891_MAX_REGISTERS]; struct Rts8891_Device *dev = session->dev; SANE_Int distance; DBG (DBG_proc, "move_to_scan_area: start\n"); /* compute line number to move and fix scan values */ distance = ((dev->ystart - 1) * MOVE_DPI) / dev->ydpi; dev->ystart = dev->ystart - (distance * dev->ydpi) / MOVE_DPI; /* extra lines to let head stop */ distance -= 30; DBG (DBG_proc, "move_to_scan_area: distance=%d, ystart=%d\n", distance, dev->ystart); /* then send move command */ rts8891_move (dev, regs, distance, SANE_TRUE); /* wait for completion */ do { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); } while ((control & 0x08) == 0x08); DBG (DBG_proc, "move_to_scan_area: exit\n"); return status; } /* set up the shadow registers for scan, depending on scan parameters */ /* the ultimate goal is to have no direct access to registers, but to */ /* set them through helper functions */ /* NOTE : I couldn't manage to get scans that really uses gray settings. */ /* The windows driver is allways scanning in color, so we do the same. */ /* For now, the only mode that could be done would be 300 dpi gray scan, */ /* based on the register settings of find_origin() */ #ifndef UNIT_TESTING static #endif SANE_Status setup_scan_registers (struct Rts8891_Session *session, SANE_Byte *status1, SANE_Byte *status2, SANE_Byte *regs) { SANE_Status status = SANE_STATUS_GOOD; struct Rts8891_Device *dev = session->dev; int exposure=0; int timing=0; /* only software gray modes for now */ if (session->params.format == SANE_FRAME_GRAY && (session->dev->model->flags & RTS8891_FLAG_EMULATED_GRAY_MODE) == 0) { DBG (DBG_warn, "setup_scan_registers: native gray modes not implemented for this model, failure expected\n"); } sanei_rts88xx_set_scan_area (regs, dev->ystart, dev->ystart + dev->lines, dev->xstart, dev->xstart + dev->pixels); DBG (DBG_info, "setup_scan_registers: xstart=%d, pixels=%d\n", dev->xstart, dev->pixels); DBG (DBG_info, "setup_scan_registers: ystart=%d, lines =%d\n", dev->ystart, dev->lines); /* this is full register set from a color preview */ regs[0x00] = regs[0x00] & 0xef; regs[0x01] = 0x41; sanei_rts88xx_set_offset (regs, dev->red_offset, dev->green_offset, dev->blue_offset); sanei_rts88xx_set_gain (regs, dev->red_gain, dev->green_gain, dev->blue_gain); switch (dev->sensor) { case SENSOR_TYPE_4400: case SENSOR_TYPE_4400_BARE: *status1 = 0x10; *status2 = 0x2a; break; case SENSOR_TYPE_XPA: *status1 = 0x20; *status2 = 0x3f; break; default: *status1 = 0x20; *status2 = 0x3b; } /* default to 75 dpi color scan */ regs[0x0b] = 0x70; regs[0x0c] = 0x00; regs[0x0d] = 0x00; regs[0x0e] = 0x00; regs[0x0f] = 0x00; regs[0x12] = 0xff; regs[0x13] = 0x20; regs[0x14] = 0xf8; regs[0x15] = 0x28; regs[0x16] = 0x01; regs[0x17] = 0x00; regs[0x18] = 0xff; regs[0x19] = 0x00; regs[0x1a] = 0x00; regs[0x1b] = 0x00; regs[0x1c] = 0x00; regs[0x1d] = 0x20; regs[0x1e] = 0x00; regs[0x1f] = 0x00; /* LCD display */ regs[0x20] = 0x3a; regs[0x21] = 0xf2; regs[0x22] = 0x00; regs[0x23] = 0x80; regs[0x24] = 0xff; regs[0x25] = 0x00; regs[0x26] = 0x00; regs[0x27] = 0x00; regs[0x28] = 0x00; regs[0x29] = 0x00; regs[0x2a] = 0x00; regs[0x2b] = 0x00; regs[0x2c] = 0x00; regs[0x2d] = 0x00; regs[0x2e] = 0x00; regs[0x2f] = 0x00; regs[0x30] = 0x00; regs[0x31] = 0x00; regs[0x32] = 0x20; regs[0x33] = 0x83; regs[0x34] = 0x10; regs[0x35] = 0x47; regs[0x36] = 0x2c; regs[0x37] = 0x00; regs[0x38] = 0x00; regs[0x39] = 0x02; regs[0x3a] = 0x43; regs[0x3b] = 0x00; regs[0x3c] = 0x00; regs[0x3d] = 0x00; regs[0x3e] = 0x00; regs[0x3f] = 0x00; regs[0x40] = 0x2c; /* 0x0c -> use shading data */ regs[0x41] = 0x00; regs[0x42] = 0x00; regs[0x43] = 0x00; regs[0x44] = 0x8c; regs[0x45] = 0x76; regs[0x46] = 0x00; regs[0x47] = 0x00; regs[0x48] = 0x00; regs[0x49] = 0x00; regs[0x4a] = 0x00; regs[0x4b] = 0x00; regs[0x4c] = 0x00; regs[0x4d] = 0x00; regs[0x4e] = 0x00; regs[0x4f] = 0x00; regs[0x50] = 0x00; regs[0x51] = 0x00; regs[0x52] = 0x00; regs[0x53] = 0x00; regs[0x54] = 0x00; regs[0x55] = 0x00; regs[0x56] = 0x00; regs[0x57] = 0x00; regs[0x58] = 0x00; regs[0x59] = 0x00; regs[0x5a] = 0x00; regs[0x5b] = 0x00; regs[0x5c] = 0x00; regs[0x5d] = 0x00; regs[0x5e] = 0x00; regs[0x5f] = 0x00; regs[0x64] = 0x01; regs[0x65] = 0x20; regs[0x68] = 0x00; regs[0x69] = 0x00; regs[0x6a] = 0x00; regs[0x6b] = 0x00; regs[0x6e] = 0x00; regs[0x6f] = 0x00; regs[0x70] = 0x00; regs[0x71] = 0x00; regs[0x72] = 0xe1; regs[0x73] = 0x14; regs[0x74] = 0x18; regs[0x75] = 0x15; regs[0x76] = 0x00; regs[0x77] = 0x00; regs[0x78] = 0x00; regs[0x79] = 0x20; regs[0x7a] = 0x01; regs[0x7b] = 0x00; regs[0x7c] = 0x00; regs[0x7d] = 0x00; regs[0x7e] = 0x00; regs[0x7f] = 0x00; timing=0x00af; regs[0x84] = 0x00; regs[0x85] = 0x46; regs[0x86] = 0x0b; regs[0x87] = 0x8c; regs[0x88] = 0x10; regs[0x8b] = 0xff; regs[0x8c] = 0x3f; regs[0x8d] = 0x3b; regs[0x8e] = 0x60; regs[0x8f] = 0x00; regs[0x90] = 0x18; /* 0x1c when shading calibration */ /* overwritten when calibration data is sent */ regs[0x91] = 0x00; regs[0x92] = 0x00; regs[0x93] = 0x01; regs[0x94] = 0x0e; regs[0x95] = 0x00; regs[0x96] = 0x00; regs[0x97] = 0x00; regs[0x98] = 0x00; regs[0x99] = 0x00; regs[0x9a] = 0x00; regs[0x9b] = 0x00; regs[0x9c] = 0x00; regs[0x9d] = 0x00; regs[0x9e] = 0x00; regs[0x9f] = 0x00; regs[0xa0] = 0x00; regs[0xa1] = 0x00; regs[0xa2] = 0x00; regs[0xa3] = 0xcc; regs[0xa4] = 0x27; regs[0xa5] = 0x64; regs[0xa6] = 0x00; regs[0xa7] = 0x00; regs[0xa8] = 0x00; regs[0xa9] = 0x00; regs[0xaa] = 0x00; regs[0xab] = 0x00; regs[0xac] = 0x00; regs[0xad] = 0x00; regs[0xae] = 0x00; regs[0xaf] = 0x00; regs[0xb0] = 0x00; regs[0xb1] = 0x00; regs[0xb2] = 0x02; regs[0xb4] = 0x00; regs[0xb5] = 0x00; regs[0xb6] = 0x00; regs[0xb7] = 0x00; regs[0xb8] = 0x00; regs[0xb9] = 0x00; regs[0xba] = 0x00; regs[0xbb] = 0x00; regs[0xbc] = 0x00; regs[0xbd] = 0x00; regs[0xbe] = 0x00; regs[0xbf] = 0x00; regs[0xc0] = 0x06; regs[0xc1] = 0xe6; regs[0xc2] = 0x67; regs[0xc3] = 0xff; regs[0xc4] = 0xff; regs[0xc5] = 0xff; regs[0xc6] = 0xff; regs[0xc7] = 0xff; regs[0xc8] = 0xff; regs[0xc9] = 0x07; regs[0xca] = 0x00; regs[0xcb] = 0xfe; regs[0xcc] = 0xf9; regs[0xcd] = 0x19; regs[0xce] = 0x98; regs[0xcf] = 0xe8; regs[0xd0] = 0xea; regs[0xd1] = 0xf3; regs[0xd2] = 0x14; regs[0xd3] = 0x02; regs[0xd4] = 0x04; regs[0xd5] = 0x86; regs[0xd6] = 0x0f; regs[0xd7] = 0x30; /* 12303 */ regs[0xd8] = 0x52; /* 0x5230=21040 */ regs[0xd9] = 0xad; regs[0xda] = 0xa7; regs[0xdb] = 0x00; regs[0xdc] = 0x00; regs[0xdd] = 0x00; regs[0xde] = 0x00; regs[0xdf] = 0x00; regs[0xe0] = 0x00; regs[0xe1] = 0x00; regs[0xe2] = 0x0f; regs[0xe3] = 0x85; regs[0xe4] = 0x03; /* regs[0xe5] = 0x52; regs[0xe6] = 0x00; exposure time 0x0052=82 */ exposure=82; regs[0xe7] = 0x75; regs[0xe8] = 0x01; regs[0xe9] = 0x0b; regs[0xea] = 0x54; regs[0xeb] = 0x01; regs[0xec] = 0x04; regs[0xed] = 0xb8; regs[0xee] = 0x00; regs[0xef] = 0x03; regs[0xf0] = 0x70; regs[0xf1] = 0x00; regs[0xf2] = 0x01; regs[0xf3] = 0x00; if (dev->sensor == SENSOR_TYPE_XPA || dev->sensor == SENSOR_TYPE_4400) { regs[0xc0] = 0x67; regs[0xc1] = 0x06; regs[0xc2] = 0xe6; regs[0xc3] = 0x98; regs[0xc4] = 0xf9; regs[0xc5] = 0x19; regs[0xc6] = 0x67; regs[0xc7] = 0x06; regs[0xc8] = 0xe6; regs[0xc9] = 0x01; regs[0xca] = 0xf8; regs[0xcb] = 0xff; regs[0xcc] = 0x98; regs[0xcd] = 0xf9; regs[0xce] = 0x19; regs[0xcf] = 0xe0; regs[0xd0] = 0xe2; regs[0xd1] = 0xeb; regs[0xd2] = 0x0c; regs[0xd7] = 0x10; } if (dev->sensor == SENSOR_TYPE_4400) { regs[0x13] = 0x39; /* 0x20 */ regs[0x14] = 0xf0; /* 0xf8 */ regs[0x15] = 0x29; /* 0x28 */ regs[0x16] = 0x00; /* 0x01 */ regs[0x17] = 0x10; /* 0x00 */ regs[0x23] = 0x00; /* 0x80 */ regs[0x35] = 0x47; /* 0x45 */ regs[0x36] = 0x29; /* 0x2c */ regs[0x39] = 0x00; /* 0x02 */ timing=0x00af; regs[0x85] = 0x46; /* 0x8c */ regs[0x86] = 0x0b; /* 0x10 */ regs[0x87] = 0x8c; /* 0x18 */ regs[0x88] = 0x10; /* 0x1b */ regs[0x8d] = 0x3b; /* 0x77 */ regs[0xd3] = 0x02; /* 0x0e */ regs[0xd4] = 0x04; /* 0x10 */ regs[0xe2] = 0x07; /* 0x0f */ regs[0xe3] = 0x84; /* 0x87 */ /*regs[0xe5] = 0xa5; 0x54 */ exposure=165; regs[0xe7] = 0x0e; /* 0xa8 */ regs[0xe8] = 0x01; /* 0x00 */ regs[0xe9] = 0x0a; /* 0x0b */ regs[0xea] = 0xc2; /* 0x56 */ regs[0xed] = 0xf6; /* 0xba */ regs[0xef] = 0x02; /* 0x03 */ regs[0xf0] = 0xa8; /* 0x72 */ } if (dev->sensor == SENSOR_TYPE_4400_BARE) { regs[0x13] = 0x39; /* 0x20 */ regs[0x14] = 0xf0; /* 0xf8 */ regs[0x15] = 0x29; /* 0x28 */ regs[0x16] = 0x00; /* 0x07 */ regs[0x17] = 0x10; /* 0x00 */ regs[0x23] = 0x00; /* 0xff */ regs[0x35] = 0x47; /* 0x0e */ regs[0x36] = 0x29; /* 0x2c */ regs[0x39] = 0x00; /* 0x02 */ regs[0x3a] = 0x43; /* 0x0e */ regs[0x40] = 0x2c; /* 0x20 */ regs[0x85] = 0x46; /* 0x00 */ regs[0x86] = 0x0b; /* 0x06 */ regs[0x87] = 0x8c; /* 0x00 */ regs[0x88] = 0x10; /* 0x06 */ regs[0x8d] = 0x3b; /* 0x00 */ regs[0x90] = 0x18; /* 0x1c */ regs[0xe2] = 0x07; /* 0x05 */ regs[0xe3] = 0x84; /* 0x00 */ regs[0xe4] = 0x03; /* 0x00 */ timing=0x00af; exposure=165; regs[0xe7] = 0x0e; /* 0x00 */ regs[0xe8] = 0x01; /* 0x00 */ regs[0xe9] = 0x0a; /* 0x00 */ regs[0xea] = 0xc2; /* 0x00 */ regs[0xeb] = 0x01; /* 0x00 */ regs[0xec] = 0x04; /* 0x00 */ regs[0xed] = 0xf6; /* 0x00 */ regs[0xef] = 0x02; /* 0x00 */ regs[0xf0] = 0xa8; /* 0x00 */ regs[0xf2] = 0x01; /* 0x00 */ } switch (dev->xdpi) { case 75: break; case 150: regs[0x35] = 0x45; regs[0x85] = 0x8c; regs[0x86] = 0x10; regs[0x87] = 0x18; regs[0x88] = 0x1b; regs[0x8d] = 0x77; regs[0xe3] = 0x87; /* regs[0xe5] = 0x54; regs[0xe6] = 0x00; exposure time 0x0054=84 */ exposure=84; timing=0x012e; regs[0xe7] = 0xa8; regs[0xe8] = 0x00; regs[0xea] = 0x56; regs[0xed] = 0xba; regs[0xf0] = 0x72; switch (dev->sensor) { case SENSOR_TYPE_XPA: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 150 dpi\n"); regs[0xc0] = 0x00; regs[0xc1] = 0x8e; regs[0xc2] = 0xff; regs[0xc3] = 0xff; regs[0xc4] = 0x71; regs[0xc5] = 0x00; regs[0xc6] = 0x00; regs[0xc7] = 0x8e; regs[0xc8] = 0xff; regs[0xc9] = 0xff; regs[0xca] = 0xff; regs[0xcb] = 0x1f; regs[0xcc] = 0xff; regs[0xcd] = 0x71; regs[0xce] = 0x00; regs[0xcf] = 0xe6; regs[0xd0] = 0xe8; regs[0xd1] = 0xf6; regs[0xd2] = 0x17; regs[0xd3] = 0x0b; regs[0xd4] = 0x0d; break; case SENSOR_TYPE_BARE: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 150 dpi\n"); regs[0xc0] = 0x80; regs[0xc1] = 0x87; regs[0xc2] = 0x7f; regs[0xc9] = 0x00; regs[0xcb] = 0x78; regs[0xcc] = 0x7f; regs[0xcd] = 0x78; regs[0xce] = 0x80; regs[0xcf] = 0xe6; regs[0xd0] = 0xe8; regs[0xd1] = 0xf7; regs[0xd2] = 0x00; regs[0xd3] = 0x0e; regs[0xd4] = 0x10; break; case SENSOR_TYPE_4400: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 150 dpi\n"); regs[0x35] = 0x47; exposure=170; timing=0x012e; regs[0x85] = 0x8c; regs[0x86] = 0x10; regs[0x87] = 0x18; regs[0x88] = 0x1b; regs[0x8d] = 0x77; regs[0xc0] = 0x00; regs[0xc1] = 0x8e; regs[0xc2] = 0xff; regs[0xc3] = 0xff; regs[0xc4] = 0x71; regs[0xc5] = 0x00; regs[0xc6] = 0x00; regs[0xc7] = 0x8e; regs[0xc8] = 0xff; regs[0xc9] = 0xff; regs[0xca] = 0xff; regs[0xcb] = 0x1f; regs[0xcc] = 0xff; regs[0xcd] = 0x71; regs[0xce] = 0x00; regs[0xcf] = 0xe6; regs[0xd0] = 0xe8; regs[0xd1] = 0xf6; regs[0xd2] = 0x17; regs[0xd3] = 0x0b; regs[0xd4] = 0x0d; regs[0xe3] = 0x86; regs[0xe7] = 0x00; regs[0xe8] = 0x1c; regs[0xe9] = 0x01; regs[0xea] = 0x0a; regs[0xeb] = 0xc4; regs[0xec] = 0x01; regs[0xed] = 0x04; regs[0xee] = 0xf8; regs[0xef] = 0x00; regs[0xf0] = 0x02; regs[0xf2] = 0x00; break; } break; case 300: switch (dev->sensor) { case SENSOR_TYPE_XPA: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 300 dpi\n"); regs[0x35] = 0x0e; /* fast ? */ regs[0x3a] = 0x0e; regs[0x85] = 0x18; regs[0x86] = 0x1b; regs[0x87] = 0x30; regs[0x88] = 0x30; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0x8d] = 0xef; regs[0xc0] = 0x00; regs[0xc1] = 0xff; regs[0xc2] = 0x0f; regs[0xc3] = 0xff; regs[0xc4] = 0x00; regs[0xc5] = 0xf0; regs[0xc6] = 0x00; regs[0xc7] = 0xff; regs[0xc8] = 0x0f; regs[0xc9] = 0xff; regs[0xca] = 0xff; regs[0xcb] = 0xf1; regs[0xcc] = 0xff; regs[0xcd] = 0x00; regs[0xce] = 0xf0; regs[0xcf] = 0xed; regs[0xd0] = 0xef; regs[0xd1] = 0xe2; regs[0xd2] = 0x03; regs[0xd3] = 0x17; regs[0xd4] = 0x01; regs[0xe2] = 0x07; regs[0xe3] = 0x00; regs[0xe4] = 0x00; timing=0x022b; exposure=342; regs[0xf2] = 0x00; break; case SENSOR_TYPE_BARE: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 300 dpi\n"); regs[0x35] = 0x0e; /* fast ? */ regs[0x3a] = 0x0e; timing=0x022b; regs[0x85] = 0x18; regs[0x86] = 0x1b; regs[0x87] = 0x30; regs[0x88] = 0x30; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0x8d] = 0xf0; regs[0x8e] = 0x60; /* low nibble of 8e and 8d are proportional to the scanned width 1de => 5100 wide scan */ regs[0xc0] = 0xff; regs[0xc1] = 0x0f; regs[0xc2] = 0x00; regs[0xc9] = 0x00; regs[0xca] = 0x0e; regs[0xcb] = 0x00; regs[0xcc] = 0x00; regs[0xcd] = 0xf0; regs[0xce] = 0xff; regs[0xcf] = 0xf5; regs[0xd0] = 0xf7; regs[0xd1] = 0xea; regs[0xd2] = 0x0b; regs[0xd3] = 0x17; regs[0xd4] = 0x01; regs[0xe2] = 0x07; regs[0xe3] = 0x00; regs[0xe4] = 0x00; exposure=342; break; case SENSOR_TYPE_4400: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 300 dpi\n"); regs[0x11] = 0x22; regs[0x35] = 0x0e; regs[0x3a] = 0x0e; regs[0x85] = 0x18; regs[0x86] = 0x1b; regs[0x87] = 0x30; regs[0x88] = 0x30; regs[0x8d] = 0xef; regs[0xc0] = 0x00; regs[0xc1] = 0xff; regs[0xc2] = 0x0f; regs[0xc3] = 0xff; regs[0xc4] = 0x00; regs[0xc5] = 0xf0; regs[0xc6] = 0x00; regs[0xc7] = 0xff; regs[0xc8] = 0x0f; regs[0xc9] = 0xff; regs[0xca] = 0xff; regs[0xcb] = 0xf1; regs[0xcc] = 0xff; regs[0xcd] = 0x00; regs[0xce] = 0xf0; regs[0xcf] = 0xed; regs[0xd0] = 0xef; regs[0xd1] = 0xe2; regs[0xd2] = 0x03; regs[0xd3] = 0x17; regs[0xd4] = 0x01; regs[0xe2] = 0x03; regs[0xe3] = 0x00; regs[0xe4] = 0x00; timing=0x022b; exposure=686; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0xf2] = 0x00; break; } break; case 600: *status1 = 0x28; switch (dev->sensor) { case SENSOR_TYPE_BARE: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 600 dpi\n"); regs[0x34] = 0xf0; regs[0x35] = 0x1b; regs[0x36] = 0x29; regs[0x3a] = 0x1b; regs[0x72] = 0x3a; regs[0x73] = 0x15; regs[0x74] = 0x62; timing=0x0425; regs[0x85] = 0x30; regs[0x86] = 0x30; regs[0x87] = 0x60; regs[0x88] = 0x5a; regs[0x8d] = 0xde; regs[0x8e] = 0x61; /* low nibble of 8e and 8d are proportional to the scanned width 1de => 5100 wide scan */ regs[0xc0] = 0xff; regs[0xc1] = 0xff; regs[0xc2] = 0xff; regs[0xc3] = 0x00; regs[0xc4] = 0xf0; regs[0xc7] = 0x0f; regs[0xc8] = 0x00; regs[0xcb] = 0xe0; regs[0xcc] = 0xff; regs[0xcd] = 0xff; regs[0xce] = 0xff; regs[0xcf] = 0xe9; regs[0xd0] = 0xeb; regs[0xd7] = 0x14; regs[0xe2] = 0x01; regs[0xe3] = 0x00; regs[0xe4] = 0x00; /* regs[0xe5] = 0xbd; regs[0xe6] = 0x0a; exposure time = 0x0abd=2749 (5500/2-1) */ exposure=2749; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0xf2] = 0x00; break; case SENSOR_TYPE_XPA: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 600 dpi\n"); *status2 = 0x3b; regs[0x33] = 0x83; /* 0x86 */ regs[0x34] = 0xf0; regs[0x35] = 0x1b; regs[0x36] = 0x29; regs[0x3a] = 0x1b; regs[0x40] = 0x2c; /* 0x24 */ regs[0x50] = 0x00; /* 0x18 */ regs[0x64] = 0x01; /* 0x02 */ regs[0x65] = 0x20; /* 0x10 */ regs[0x72] = 0x3a; regs[0x73] = 0x15; regs[0x74] = 0x62; regs[0x85] = 0x30; regs[0x86] = 0x30; regs[0x87] = 0x60; regs[0x88] = 0x5a; regs[0x8d] = 0xde; regs[0x8e] = 0x61; /* 25054 */ regs[0xc0] = 0xf8; regs[0xc1] = 0x7f; regs[0xc2] = 0x00; regs[0xc3] = 0xf8; regs[0xc4] = 0x7f; regs[0xc5] = 0x00; regs[0xc6] = 0xf8; regs[0xc7] = 0x7f; regs[0xc8] = 0x00; regs[0xc9] = 0xff; regs[0xca] = 0x8f; regs[0xcb] = 0xff; regs[0xcc] = 0x07; regs[0xcd] = 0x80; regs[0xce] = 0xff; regs[0xcf] = 0xf2; regs[0xd0] = 0xf4; regs[0xd1] = 0xe7; regs[0xd2] = 0x08; regs[0xd3] = 0x02; regs[0xd4] = 0x10; regs[0xd7] = 0x31; regs[0xe2] = 0x01; regs[0xe3] = 0x00; regs[0xe4] = 0x00; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0xf2] = 0x00; exposure=2749; timing=0x0425; break; case SENSOR_TYPE_4400: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 600 dpi\n"); *status1 = 0x10; *status2 = 0x23; regs[0x13] = 0x39; regs[0x14] = 0xf0; regs[0x15] = 0x29; regs[0x16] = 0x00; regs[0x17] = 0x10; regs[0x23] = 0x00; regs[0x34] = 0xf0; regs[0x35] = 0x1b; regs[0x36] = 0x29; regs[0x39] = 0x00; regs[0x3a] = 0x1b; regs[0x72] = 0x3a; regs[0x73] = 0x15; regs[0x74] = 0x62; regs[0x85] = 0x30; regs[0x86] = 0x30; regs[0x87] = 0x60; regs[0x88] = 0x5a; regs[0x8d] = 0xde; regs[0x8e] = 0x61; regs[0xc0] = 0xf8; regs[0xc1] = 0x7f; regs[0xc2] = 0x00; regs[0xc3] = 0xf8; regs[0xc4] = 0x7f; regs[0xc5] = 0x00; regs[0xc6] = 0xf8; regs[0xc7] = 0x7f; regs[0xc8] = 0x00; regs[0xc9] = 0xff; regs[0xca] = 0x8f; regs[0xcb] = 0xff; regs[0xcc] = 0x07; regs[0xcd] = 0x80; regs[0xce] = 0xff; regs[0xcf] = 0xf2; regs[0xd0] = 0xf4; regs[0xd1] = 0xe7; regs[0xd2] = 0x08; regs[0xd3] = 0x0e; regs[0xd4] = 0x10; regs[0xd7] = 0x31; regs[0xe2] = 0x01; regs[0xe3] = 0x00; regs[0xe4] = 0x00; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0xf2] = 0x00; timing=0x0425; exposure=2749; break; case SENSOR_TYPE_4400_BARE: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400_BARE for 600 dpi\n"); return SANE_STATUS_INVAL; break; } break; case 1200: *status1 = 0x28; switch (dev->sensor) { case SENSOR_TYPE_BARE: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_BARE for 1200 dpi\n"); regs[0x34] = 0xf0; regs[0x35] = 0x1b; regs[0x36] = 0x29; regs[0x3a] = 0x1b; regs[0x40] = 0xac; timing=0x081a; regs[0x85] = 0x60; regs[0x86] = 0x5a; regs[0x87] = 0xc0; regs[0x88] = 0xae; regs[0x8d] = 0xbd; /* about twice the 600 dpi values */ regs[0x8e] = 0x63; /* low nibble of 8e and 8d are proportional to the scanned width 3b5 => 10124 wide scan */ regs[0xc0] = 0xff; regs[0xc1] = 0xff; regs[0xc2] = 0xff; regs[0xc4] = 0x0f; regs[0xc5] = 0x00; regs[0xc6] = 0x00; regs[0xc7] = 0xf0; regs[0xc9] = 0x00; regs[0xca] = 0x0e; regs[0xcb] = 0x00; regs[0xcc] = 0xff; regs[0xcd] = 0xff; regs[0xce] = 0xff; regs[0xcf] = 0xf5; regs[0xd0] = 0xf7; regs[0xd1] = 0xea; regs[0xd2] = 0x0b; regs[0xd3] = 0x17; regs[0xd4] = 0xc1; regs[0xd7] = 0x14; regs[0xd8] = 0xa4; regs[0xe2] = 0x01; regs[0xe3] = 0x00; regs[0xe4] = 0x00; /* regs[0xe5] = 0x7b; regs[0xe6] = 0x15; exposure time = 0x157b=5499 */ exposure=5499; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0xf2] = 0x00; break; case SENSOR_TYPE_XPA: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_XPA for 1200 dpi\n"); *status2 = 0x3f; regs[0x34] = 0xf0; regs[0x35] = 0x1b; regs[0x36] = 0x29; regs[0x3a] = 0x1b; regs[0x85] = 0x60; regs[0x86] = 0x5a; regs[0x87] = 0xc0; regs[0x8a] = 0x08; /* 81c=2076 */ regs[0xc1] = 0xff; regs[0xce] = 0xff; regs[0xcf] = 0xf5; regs[0xd0] = 0xf7; regs[0xe2] = 0x01; regs[0xe3] = 0x00; regs[0xe4] = 0x00; timing=0x081a; exposure=5499; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0xf2] = 0x00; regs[0x33] = 0x83; regs[0x40] = 0xac; regs[0x50] = 0x00; regs[0x64] = 0x01; regs[0x65] = 0x20; regs[0x88] = 0xae; regs[0x8d] = 0xbc; regs[0x8e] = 0x63; regs[0xc0] = 0xe0; regs[0xc2] = 0x01; regs[0xc3] = 0x1f; regs[0xc4] = 0x00; regs[0xc5] = 0xfe; regs[0xc6] = 0xff; regs[0xc7] = 0xff; regs[0xc8] = 0x00; regs[0xc9] = 0x3f; regs[0xca] = 0xfe; regs[0xcb] = 0xff; regs[0xcc] = 0x00; regs[0xcd] = 0x00; regs[0xd1] = 0xec; regs[0xd2] = 0x0d; regs[0xd3] = 0x05; regs[0xd4] = 0x67; regs[0xd7] = 0x10; regs[0xd8] = 0x52; break; case SENSOR_TYPE_4400: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400 for 1200 dpi\n"); regs[0x13] = 0x39; regs[0x14] = 0xf0; regs[0x15] = 0x29; regs[0x16] = 0x00; regs[0x17] = 0x10; regs[0x23] = 0x00; regs[0x33] = 0x86; regs[0x34] = 0xf0; regs[0x35] = 0x0e; regs[0x39] = 0x00; regs[0x3a] = 0x0e; regs[0x40] = 0xac; regs[0x64] = 0x02; regs[0x65] = 0x10; timing=0x081a; regs[0x85] = 0x60; regs[0x86] = 0x5a; regs[0x87] = 0xc0; regs[0x88] = 0xae; regs[0x8d] = 0xbc; regs[0x8e] = 0x63; regs[0xc0] = 0xe0; regs[0xc1] = 0xff; regs[0xc2] = 0x01; regs[0xc3] = 0x1f; regs[0xc4] = 0x00; regs[0xc5] = 0xfe; regs[0xc6] = 0xff; regs[0xc7] = 0xff; regs[0xc8] = 0x00; regs[0xc9] = 0x3f; regs[0xca] = 0xfe; regs[0xcb] = 0xff; regs[0xcc] = 0x00; regs[0xcd] = 0x00; regs[0xce] = 0xff; regs[0xcf] = 0xf5; regs[0xd0] = 0xf7; regs[0xd1] = 0xec; regs[0xd2] = 0x0d; regs[0xd3] = 0x05; regs[0xd4] = 0x67; regs[0xd7] = 0x10; regs[0xd8] = 0x52; regs[0xe2] = 0x00; regs[0xe3] = 0x00; regs[0xe4] = 0x00; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x00; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x00; regs[0xed] = 0x00; regs[0xef] = 0x00; regs[0xf0] = 0x00; regs[0xf2] = 0x00; exposure=10999; *status1 = 0x10; *status2 = 0x23; break; case SENSOR_TYPE_4400_BARE: DBG (DBG_io, "setup_scan_registers: setting up SENSOR_TYPE_4400_BARE for 1200 dpi\n"); return SANE_STATUS_INVAL; break; } break; } /* apply computed settings */ SET_DOUBLE (regs, EXPOSURE_REG, exposure); SET_DOUBLE (regs, TIMING_REG, timing); SET_DOUBLE (regs, TIMING1_REG, timing+1); SET_DOUBLE (regs, TIMING2_REG, timing+2); /* sets divisor */ regs[0xd3] = rts8891_data_format (dev->xdpi, dev->sensor); /* toggle front panel light to signal gray scan */ if (session->params.format == SANE_FRAME_GRAY) { *status1 = (*status1 & 0x0F) | 0x10; } return status; } /* set up the shadow registers for scan, depending on scan parameters */ /* the ultimate goal is to have no direct access to registers, but to */ /* set them through helper functions */ /* NOTE : I couldn't manage to get scans that really uses gray settings. */ /* The windows driver is allways scanning in color, so we do the same. */ /* For now, the only mode that could be done would be 300 dpi gray scan, */ /* based on the register settings of find_origin() */ static SANE_Status write_scan_registers (struct Rts8891_Session *session) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte control; SANE_Byte status1, status2; struct Rts8891_Device *dev = session->dev; /* setup registers for scan */ status=setup_scan_registers (session, &status1, &status2, dev->regs); if (status != SANE_STATUS_GOOD) { DBG (DBG_error0, "write_scan_registers: failed to setup registers\n"); return status; } /* check if session is idle */ control = 0x00; sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if (control != 0) { DBG (DBG_error0, "write_scan_registers: scanner is not idle!\n"); return SANE_STATUS_IO_ERROR; } /* effective write of register set for scan */ status = rts8891_write_all (dev->devnum, dev->regs, dev->reg_count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error0, "write_scan_registers: failed to write registers\n"); } return status; } /** * This function parks head relying by moving head backward by a * very large amount without scanning */ static SANE_Status park_head (struct Rts8891_Device *dev, SANE_Bool wait) { SANE_Status status; SANE_Byte reg, control; /* the hammer way : set all regs */ SANE_Byte regs[244]; DBG (DBG_proc, "park_head: start\n"); reg = 0x8d; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); reg = 0xad; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); status = sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); reg = 0xff; sanei_rts88xx_write_reg (dev->devnum, 0x23, ®); /* TODO create write_double_reg */ if (dev->sensor != SENSOR_TYPE_4400) { dev->regs[0x16] = 0x07; dev->regs[0x17] = 0x00; } else { dev->regs[0x16] = 0x0f; dev->regs[0x17] = 0x10; } sanei_rts88xx_write_regs (dev->devnum, 0x16, dev->regs + 0x16, 2); reg = 0x8d; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); reg = 0xad; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, ®); /* 0x20 expected */ sanei_rts88xx_read_reg (dev->devnum, CONTROLER_REG, ®); if (reg != 0x20) { DBG (DBG_warn, "park_head: unexpected controller value 0x%02x\n", reg); } /* head parking */ status = rts8891_park (dev, regs, wait); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "park_head: failed to park head!\n"); } DBG (DBG_proc, "park_head: end\n"); return status; } /* update button status * button access is allowed during scan, which is usefull for 'cancel' button */ static SANE_Status update_button_status (struct Rts8891_Session *session) { SANE_Int mask = 0, i; SANE_Status status = SANE_STATUS_GOOD; SANE_Bool lock = SANE_FALSE; /* while scanning, interface is reserved, so don't claim/release it */ if (session->scanning != SANE_TRUE) { lock = SANE_TRUE; /* claim the interface to reserve device */ if (session->dev->conf.allowsharing == SANE_TRUE) { status = sanei_usb_claim_interface (session->dev->devnum, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "update_button_status: cannot claim usb interface\n"); return SANE_STATUS_DEVICE_BUSY; } } } /* effective button reading */ status = rts8891_read_buttons (session->dev->devnum, &mask); /* release interface if needed */ if (lock == SANE_TRUE) { if (session->dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (session->dev->devnum, 0); } } for (i = 0; i < session->dev->model->buttons; i++) { if (mask & (1 << i)) { session->val[OPT_BUTTON_1 + i].w = SANE_TRUE; DBG (DBG_io2, "update_button_status: setting button %d to TRUE\n", i + 1); } } return status; } /* set lamp status, 0 for lamp off * other values set lamp on */ static SANE_Status set_lamp_state (struct Rts8891_Session *session, int on) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte reg; /* claim the interface reserve device */ if (session->dev->conf.allowsharing == SANE_TRUE) { status = sanei_usb_claim_interface (session->dev->devnum, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_warn, "set_lamp_state: cannot claim usb interface\n"); return SANE_STATUS_DEVICE_BUSY; } } status = sanei_rts88xx_read_reg (session->dev->devnum, LAMP_REG, ®); if (on) { DBG (DBG_info, "set_lamp_state: lamp on\n"); reg = session->dev->regs[LAMP_REG] | 0x80; } else { DBG (DBG_info, "set_lamp_state: lamp off\n"); reg = session->dev->regs[LAMP_REG] & 0x7F; #ifdef HAVE_SYS_TIME_H /* if lamp is switched off, warming up will be needed */ session->dev->last_scan.tv_sec = 0; #endif } status = sanei_rts88xx_write_reg (session->dev->devnum, LAMP_REG, ®); /* release interface and return status from lamp setting */ if (session->dev->conf.allowsharing == SANE_TRUE) { sanei_usb_release_interface (session->dev->devnum, 0); } return status; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/nec.c0000664000175000017500000032236112775312261013537 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2001 Kazuya Fukuda, based on sharp.c, which is based on canon.c. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for NEC flatbed scanners. */ /* Version 0.12 - Remove references to sharp backend (grep for "JX"). - Check for HAVE_SYS_SHM_H before including sys/shm.h and disable shared memory support if necessary. - free devlist allocated in sane_get_devices() in sane_exit() - resolution setting bug fixed(PC-IN500/4C 10dpi step) - remove resolution list Version 0.11 - get_data_buffer_status is not called in sane_get_parameter and sane_read_direct, sane_read_shuffled. - change some #include <> to "" Version 0.10 - First release! - suppoted scanner PC-IN500/4C available MultiReder 300U/300S series not available MultiReder 600U/600S series not available MultiReader PetiScan series not available */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" /* QUEUEDEBUG should be undefined unless you want to play with the sanei_scsi.c under Linux and/or with the Linux's SG driver, or your suspect problems with command queueing */ #define QUEUEDEBUG /*#define DEBUG*/ #ifdef DEBUG #include #include #endif /* USE_FORK: fork a special reader process disable shared memory support. */ #if 0 #ifdef HAVE_SYS_SHM_H #define USE_FORK #endif #endif #ifdef USE_FORK #include #include #include #include #include #include #endif /* USE_FORK */ #ifndef USE_CUSTOM_GAMMA #define USE_CUSTOM_GAMMA #endif #ifndef USE_COLOR_THRESHOLD #define USE_COLOR_THRESHOLD #endif /* enable a short list of some standard resolutions. XSane provides its own resolution list; therefore its is generally not reasonable to enable this list, if you mainly using XSane. But it might be handy if you are working with xscanimage */ /* #define USE_RESOLUTION_LIST */ #define BACKEND_NAME nec #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX #define PATH_MAX 1024 #endif #define DEFAULT_MUD_1200 1200 #define PIX_TO_MM(x, mud) ((x) * 25.4 / mud) #define MM_TO_PIX(x, mud) ((x) * mud / 25.4) #include "../include/sane/sanei_config.h" #define NEC_CONFIG_FILE "nec.conf" #include "nec.h" static int num_devices = 0; static NEC_Device *first_dev = NULL; static NEC_Scanner *first_handle = NULL; static const SANE_Device **devlist = 0; typedef enum { MODES_LINEART = 0, MODES_GRAY, MODES_COLOR, MODES_LINEART_COLOR } Modes; #define M_LINEART SANE_VALUE_SCAN_MODE_LINEART #define M_GRAY SANE_VALUE_SCAN_MODE_GRAY #define M_LINEART_COLOR "Lineart Color" #define M_COLOR SANE_VALUE_SCAN_MODE_COLOR static const SANE_String_Const mode_list[] = { #if 0 M_LINEART, M_GRAY, M_LINEART_COLOR, M_COLOR, #endif M_LINEART, M_GRAY, M_COLOR, 0 }; #define M_BILEVEL "none" #define M_BAYER "Dither Bayer" #define M_SPIRAL "Dither Spiral" #define M_DISPERSED "Dither Dispersed" #define M_ERRDIFFUSION "Error Diffusion" #define M_DITHER1 "Dither 1" #define M_DITHER2 "Dither 2" #define M_DITHER3 "Dither 3" #define M_DITHERUSER "User defined" static const SANE_String_Const halftone_list[] = { M_BILEVEL, M_DITHER1, M_DITHER2, M_DITHER3, 0 }; #define LIGHT_GREEN "green" #define LIGHT_RED "red" #define LIGHT_BLUE "blue" #define LIGHT_NONE "none" #define LIGHT_WHITE "white" static const SANE_String_Const light_color_list[] = { LIGHT_GREEN, LIGHT_RED, LIGHT_BLUE, LIGHT_NONE, 0 }; /* possible values for ADF/FSU selection */ static SANE_String use_adf = "Automatic Document Feeder"; static SANE_String use_fsu = "Transparency Adapter"; static SANE_String use_simple = "Flatbed"; #define HAVE_FSU 1 #define HAVE_ADF 2 /* The follow #defines are used in NEC_Scanner.adf_fsu_mode and as indexes for the arrays x_ranges, y_ranges in NEC_Device */ #define SCAN_SIMPLE 0 #define SCAN_WITH_FSU 1 #define SCAN_WITH_ADF 2 #define LOAD_PAPER 1 #define UNLOAD_PAPER 0 #define PAPER_MAX 10 #define W_LETTER "11\"x17\"" #define INVOICE "8.5\"x5.5\"" static const SANE_String_Const paper_list_pcinxxx[] = { "A3", "A4", "A5", "A6", "B4", "B5", W_LETTER, "Legal", "Letter", INVOICE, 0 }; static const SANE_String_Const paper_list_pcin500[] = { "A4", "A5", "A6", "B5", 0 }; #define CRT1 "CRT1" #define CRT2 "CRT2" #define PRINTER1 "PRINTER1" #define PRINTER2 "PRINTER2" #define NONE "NONE" /* #define CUSTOM "CUSTOM" */ static const SANE_String_Const gamma_list[] = { CRT1, CRT2, PRINTER1, PRINTER2, NONE, 0 }; #if 0 #define SPEED_NORMAL "Normal" #define SPEED_FAST "Fast" static const SANE_String_Const speed_list[] = { SPEED_NORMAL, SPEED_FAST, 0 }; #endif #ifdef USE_RESOLUTION_LIST #define RESOLUTION_MAX_PCINXXX 8 static const SANE_String_Const resolution_list_pcinxxx[] = { "50", "75", "100", "150", "200", "300", "400", "600", "Select", 0 }; #define RESOLUTION_MAX_PCIN500 8 static const SANE_String_Const resolution_list_pcin500[] = { "50", "75", "100", "150", "200", "300", "400", "480", "Select", 0 }; #endif #define EDGE_NONE "None" #define EDGE_MIDDLE "Middle" #define EDGE_STRONG "Strong" #define EDGE_BLUR "Blur" static const SANE_String_Const edge_emphasis_list[] = { EDGE_NONE, EDGE_MIDDLE, EDGE_STRONG, EDGE_BLUR, 0 }; #ifdef USE_CUSTOM_GAMMA static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; #endif static SANE_Status sense_handler(int fd, u_char *sense_buffer, void *ss) { int sense_key; NEC_Sense_Data *sdat = (NEC_Sense_Data *) ss; fd = fd; /* silence compilation warnings */ #define add_sense_code sense_buffer[12] #define add_sense_qual sense_buffer[13] memcpy(sdat->sb, sense_buffer, 16); DBG(10, "sense code: %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", sense_buffer[0], sense_buffer[1], sense_buffer[2], sense_buffer[3], sense_buffer[4], sense_buffer[5], sense_buffer[6], sense_buffer[7], sense_buffer[8], sense_buffer[9], sense_buffer[10], sense_buffer[11], sense_buffer[12], sense_buffer[13], sense_buffer[14], sense_buffer[15]); sense_key = sense_buffer[1] & 0x0F; /* do we have additional information ? */ if (sense_buffer[7] >= 5) { if (sdat->model == PCIN500) { switch (sense_key) { case 0x02: /* not ready */ switch (add_sense_code) { case 0x80: switch (add_sense_qual & 0xf0) { case 0x10: DBG(1, "Scanner not ready: memory error\n"); return SANE_STATUS_IO_ERROR; case 0x20: DBG(1, "Scanner not ready: hardware error\n"); return SANE_STATUS_IO_ERROR; case 0x30: DBG(1, "Scanner not ready: optical error\n"); return SANE_STATUS_IO_ERROR; case 0x40: DBG(1, "Scanner not ready: optical error\n"); return SANE_STATUS_IO_ERROR; case 0x50: DBG(1, "Scanner not ready: marker error\n"); return SANE_STATUS_IO_ERROR; case 0x60: DBG(1, "Scanner not ready: mechanical error\n"); return SANE_STATUS_IO_ERROR; case 0x70: DBG(1, "Scanner not ready: hardware error\n"); return SANE_STATUS_IO_ERROR; case 0x80: DBG(1, "Scanner not ready: hardware error\n"); return SANE_STATUS_IO_ERROR; case 0x90: default: DBG(5, "Scanner not ready: undocumented reason\n"); return SANE_STATUS_IO_ERROR; } } case 0x03: /* medium error */ DBG(5, "medium error: undocumented reason\n"); return SANE_STATUS_IO_ERROR; case 0x04: /* hardware error */ DBG(1, "general hardware error\n"); return SANE_STATUS_IO_ERROR; case 0x05: /* illegal request */ DBG(10, "error: illegal request\n"); return SANE_STATUS_IO_ERROR; case 0x06: /* unit attention */ DBG(5, "unit attention: exact reason not documented\n"); return SANE_STATUS_IO_ERROR; case 0x0B: /* data remains */ DBG(5, "error: aborted command\n"); return SANE_STATUS_IO_ERROR; default: DBG(5, "error: sense code not documented\n"); return SANE_STATUS_IO_ERROR; } } } return SANE_STATUS_IO_ERROR; } static SANE_Status test_unit_ready (int fd) { static u_char cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< test_unit_ready "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #if 0 static SANE_Status request_sense (int fd, void *sense_buf, size_t *sense_size) { static u_char cmd[] = {REQUEST_SENSE, 0, 0, 0, SENSE_LEN, 0}; SANE_Status status; DBG (11, "<< request_sense "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), sense_buf, sense_size); DBG (11, ">>\n"); return (status); } #endif static SANE_Status inquiry (int fd, void *inq_buf, size_t *inq_size) { static u_char cmd[] = {INQUIRY, 0, 0, 0, INQUIRY_LEN, 0}; SANE_Status status; DBG (11, "<< inquiry "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), inq_buf, inq_size); DBG (11, ">>\n"); return (status); } static SANE_Status mode_select_mud (int fd, int mud) { static u_char cmd[6 + MODEPARAM_LEN] = {MODE_SELECT6, 0x10, 0, 0, MODEPARAM_LEN, 0}; mode_select_param *mp; SANE_Status status; DBG (11, "<< mode_select_mud "); mp = (mode_select_param *)(cmd + 6); memset (mp, 0, MODEPARAM_LEN); mp->mode_param_header1 = 11; mp->page_code = 3; mp->page_length = 6; mp->mud[0] = mud >> 8; mp->mud[1] = mud & 0xFF; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #if 0 static SANE_Status mode_select_adf_fsu (int fd, int mode) { static u_char cmd[6 + MODE_SUBDEV_LEN] = {MODE_SELECT6, 0x10, 0, 0, MODE_SUBDEV_LEN, 0}; mode_select_subdevice *mp; SANE_Status status; DBG (11, "<< mode_select_adf_fsu "); mp = (mode_select_subdevice *)(cmd + 6); memset (mp, 0, MODE_SUBDEV_LEN); mp->page_code = 0x20; mp->page_length = 26; switch (mode) { case SCAN_SIMPLE: mp->a_mode = 0x40; mp->f_mode = 0x40; break; case SCAN_WITH_FSU: mp->a_mode = 0; mp->f_mode = 0x40; break; case SCAN_WITH_ADF: mp->a_mode = 0x40; mp->f_mode = 0; break; } status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #endif static SANE_Status wait_ready(int fd); static SANE_Status mode_sense (int fd, void *modeparam_buf, size_t * modeparam_size, int page) { static u_char cmd[6] = {MODE_SENSE6, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< mode_sense "); cmd[0] = 0x1a; cmd[2] = page; cmd[4] = *modeparam_size; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), modeparam_buf, modeparam_size); DBG (11, ">>\n"); return (status); } static SANE_Status scan (int fd) { static u_char cmd[] = {SCAN, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< scan "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #if 0 static SANE_Status send_diagnostics (int fd) { static u_char cmd[] = {SEND_DIAGNOSTIC, 0x04, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< send_diagnostics "); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } #endif static SANE_Status set_window (int fd, window_param *wp, int len) { static u_char cmd[10 + WINDOW_LEN] = {SET_WINDOW, 0, 0, 0, 0, 0, 0, 0, 0, 0}; window_param *winp; SANE_Status status; DBG (11, "<< set_window "); cmd[8] = len; winp = (window_param *)(cmd + 10); memset (winp, 0, WINDOW_LEN); memcpy (winp, wp, len); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, ">>\n"); return (status); } static SANE_Status get_window (int fd, void *buf, size_t * buf_size) { static u_char cmd[10] = {GET_WINDOW, 0, 0, 0, 0, 0, 0, 0, WINDOW_LEN, 0}; SANE_Status status; DBG (11, "<< get_window "); cmd[8] = *buf_size; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); DBG (11, ">>\n"); return (status); } #if 0 static SANE_Status get_data_buffer_status (int fd, void *buf, size_t *buf_size) { static u_char cmd[10] = {GET_DATA_BUFFER_STATUS, 0, 0, 0, 0, 0, 0, 0, 0, 0}; SANE_Status status; DBG (11, "<< get_data_buffer_status "); cmd[8] = *buf_size; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); DBG (11, ">>\n"); return (status); } #endif #ifdef USE_FORK /* the following four functions serve simply the purpose to avoid "over-optimised" code when reader_process and read_data wait for the buffer to become ready. The simple while-loops in these functions which check the buffer status may be optimised so that the machine code only operates with registers instead of using the variable values stored in memory. (This is only a workaround - it would be better to set a compiler pragma, which ensures that the program looks into the RAM in these while loops -- but unfortunately I could not find appropriate information about this at least for gcc, not to speak about other compilers... Abel) */ static int cancel_requested(NEC_Scanner *s) { return s->rdr_ctl->cancel; } static SANE_Status rdr_status(NEC_Scanner *s) { return s->rdr_ctl->status; } static int buf_status(NEC_shmem_ctl *s) { return s->shm_status; } static int reader_running(NEC_Scanner *s) { return s->rdr_ctl->running; } static int reader_process(NEC_Scanner *s) { SANE_Status status; sigset_t sigterm_set; static u_char cmd[] = {READ, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int full_count = 0, counted; size_t waitindex, cmdindex; size_t bytes_to_queue; size_t nread; size_t max_bytes_per_read; int max_queue; int i; NEC_shmem_ctl *bc; s->rdr_ctl->running = 1; DBG(11, "<< reader_process\n"); sigemptyset (&sigterm_set); bytes_to_queue = s->bytes_to_read; max_bytes_per_read = s->dev->info.bufsize / s->params.bytes_per_line; if (max_bytes_per_read) max_bytes_per_read *= s->params.bytes_per_line; else /* this is a really tiny buffer..*/ max_bytes_per_read = s->dev->info.bufsize; /* wait_ready(s->fd); */ if (s->dev->info.queued_reads <= s->dev->info.buffers) max_queue = s->dev->info.queued_reads; else max_queue = s->dev->info.buffers; for (i = 0; i < max_queue; i++) { bc = &s->rdr_ctl->buf_ctl[i]; if (bytes_to_queue) { nread = bytes_to_queue; if (nread > max_bytes_per_read) nread = max_bytes_per_read; bc->used = nread; cmd[6] = nread >> 16; cmd[7] = nread >> 8; cmd[8] = nread; #ifdef QUEUEDEBUG DBG(2, "reader: req_enter...\n"); #endif status = sanei_scsi_req_enter (s->fd, cmd, sizeof (cmd), bc->buffer, &bc->used, &bc->qid); #ifdef QUEUEDEBUG DBG(2, "reader: req_enter ok\n"); #endif if (status != SANE_STATUS_GOOD) { DBG(1, "reader_process: read command failed: %s", sane_strstatus(status)); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->status = status; s->rdr_ctl->running = 0; return 2; } bc->shm_status = SHM_BUSY; bc->nreq = bc->used; bytes_to_queue -= bc->nreq; } else { bc->used = 0; bc->shm_status = SHM_EMPTY; } } waitindex = 0; cmdindex = i % s->dev->info.buffers; while(s->bytes_to_read > 0) { if (cancel_requested(s)) { #ifdef QUEUEDEBUG DBG(2, "reader: flushing requests...\n"); #endif #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif #ifdef QUEUEDEBUG DBG(2, "reader: flushing requests ok\n"); #endif s->rdr_ctl->cancel = 0; s->rdr_ctl->status = SANE_STATUS_CANCELLED; s->rdr_ctl->running = 0; DBG(11, " reader_process (cancelled) >>\n"); return 1; } bc = &s->rdr_ctl->buf_ctl[waitindex]; if (bc->shm_status == SHM_BUSY) { #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: waiting for data %li.%06li\n", t.tv_sec, t.tv_usec); } #endif #ifdef QUEUEDEBUG DBG(2, "reader: req_wait...\n"); #endif status = sanei_scsi_req_wait(bc->qid); #ifdef QUEUEDEBUG DBG(2, "reader: req_wait ok\n"); #endif #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: data received %li.%06li\n", t.tv_sec, t.tv_usec); } #endif if (status != SANE_STATUS_GOOD) { DBG(1, "reader_process: read command failed: %s", sane_strstatus(status)); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->status = status; s->rdr_ctl->running = 0; return 2; } s->bytes_to_read -= bc->used; bytes_to_queue += bc->nreq - bc->used; bc->start = 0; bc->shm_status = SHM_FULL; waitindex++; if (waitindex == s->dev->info.buffers) waitindex = 0; } if (bytes_to_queue) { /* wait until the next buffer is completely read via read_data */ bc = &s->rdr_ctl->buf_ctl[cmdindex]; counted = 0; while (buf_status(bc) != SHM_EMPTY) { if (!counted) { counted = 1; full_count++; } if (cancel_requested(s)) { #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->cancel = 0; s->rdr_ctl->status = SANE_STATUS_CANCELLED; s->rdr_ctl->running = 0; DBG(11, " reader_process (cancelled) >>\n"); return 1; } } nread = bytes_to_queue; if (nread > max_bytes_per_read) nread = max_bytes_per_read; bc->used = nread; cmd[6] = nread >> 16; cmd[7] = nread >> 8; cmd[8] = nread; status = sanei_scsi_req_enter (s->fd, cmd, sizeof (cmd), bc->buffer, &bc->used, &bc->qid); if (status != SANE_STATUS_GOOD) { DBG(1, "reader_process: read command failed: %s", sane_strstatus(status)); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->status = status; s->rdr_ctl->running = 0; return 2; } bc->shm_status = SHM_BUSY; bc->nreq = nread; bytes_to_queue -= nread; cmdindex++; if (cmdindex == s->dev->info.buffers) cmdindex = 0; } if (cancel_requested(s)) { #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all_extended(s->fd); #else sanei_scsi_req_flush_all(); #endif s->rdr_ctl->cancel = 0; s->rdr_ctl->status = SANE_STATUS_CANCELLED; s->rdr_ctl->running = 0; DBG(11, " reader_process (cancelled) >>\n"); return 1; } } DBG(1, "buffer full conditions: %i\n", full_count); DBG(11, " reader_process>>\n"); s->rdr_ctl->running = 0; return 0; } static SANE_Status read_data (NEC_Scanner *s, SANE_Byte *buf, size_t * buf_size) { size_t copysize, copied = 0; NEC_shmem_ctl *bc; DBG(11, "<< read_data "); bc = &s->rdr_ctl->buf_ctl[s->read_buff]; while (copied < *buf_size) { /* wait until the reader process delivers data or a scanner error occurs: */ while ( buf_status(bc) != SHM_FULL && rdr_status(s) == SANE_STATUS_GOOD) { usleep(10); /* could perhaps be longer. make this user configurable?? */ } if (rdr_status(s) != SANE_STATUS_GOOD) { return rdr_status(s); DBG(11, ">>\n"); } copysize = bc->used - bc->start; if (copysize > *buf_size - copied ) copysize = *buf_size - copied; memcpy(buf, &(bc->buffer[bc->start]), copysize); copied += copysize; buf = &buf[copysize]; bc->start += copysize; if (bc->start >= bc->used) { bc->start = 0; bc->shm_status = SHM_EMPTY; s->read_buff++; if (s->read_buff == s->dev->info.buffers) s->read_buff = 0; bc = &s->rdr_ctl->buf_ctl[s->read_buff]; } } DBG(11, ">>\n"); return SANE_STATUS_GOOD; } #else /* don't USE_FORK: */ static SANE_Status read_data (NEC_Scanner *s, SANE_Byte *buf, size_t * buf_size) { static u_char cmd[] = {READ, 0, 0, 0, 0, 0, 0, 0, 0, 0}; SANE_Status status = SANE_STATUS_GOOD; size_t remain = *buf_size; size_t nread; DBG (11, "<< read_data "); /* sane_read_shuffled requires that read_data returns exactly *buf_size bytes, so it must be guaranteed here. Further make sure that not more bytes are read in than sanei_scsi_max_request_size allows, to avoid a failure of the read command */ while (remain > 0) { nread = remain; if (nread > s->dev->info.bufsize) nread = s->dev->info.bufsize; cmd[6] = nread >> 16; cmd[7] = nread >> 8; cmd[8] = nread; status = sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), &buf[*buf_size - remain], &nread); if (status != SANE_STATUS_GOOD) { DBG(11, ">>\n"); return(status); } remain -= nread; } DBG (11, ">>\n"); return (status); } #endif static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; DBG (10, "<< max_string_size "); for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } DBG (10, ">>\n"); return max_size; } static SANE_Status wait_ready(int fd) { SANE_Status status; int retry = 0; while ((status = test_unit_ready (fd)) != SANE_STATUS_GOOD) { DBG (5, "wait_ready failed (%d)\n", retry); DBG (5, "wait_ready status = (%d)\n", status); if (retry++ > 15){ return SANE_STATUS_IO_ERROR; } sleep(3); } return (status); } static SANE_Status attach (const char *devnam, NEC_Device ** devp) { SANE_Status status; NEC_Device *dev; NEC_Sense_Data sensedat; int fd; unsigned char inquiry_data[INQUIRY_LEN]; const unsigned char *model_name; mode_sense_param msp; size_t buf_size; DBG (10, "<< attach "); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } sensedat.model = unknown; sensedat.complain_on_adf_error = 0; DBG (3, "attach: opening %s\n", devnam); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED { int bufsize = 4096; status = sanei_scsi_open_extended (devnam, &fd, &sense_handler, &sensedat, &bufsize); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } if (bufsize < 4096) { DBG(1, "attach: open failed. no memory\n"); sanei_scsi_close(fd); return SANE_STATUS_NO_MEM; } } #else status = sanei_scsi_open (devnam, &fd, &sense_handler, &sensedat); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } #endif DBG (3, "attach: sending INQUIRY\n"); memset (inquiry_data, 0, sizeof (inquiry_data)); buf_size = sizeof (inquiry_data); status = inquiry (fd, inquiry_data, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } if (inquiry_data[0] == 6 && strncmp ((char *)inquiry_data + 8, "NEC", 3) == 0) { if (strncmp ((char *)inquiry_data + 16, "PC-IN500/4C", 11) == 0) sensedat.model = PCIN500; else sensedat.model = unknown; } if (sensedat.model == unknown) { DBG (1, "attach: device doesn't look like a NEC scanner\n"); DBG (1, " : Only PC-IN500/4C is supported.\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } DBG (3, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } DBG (3, "attach: sending MODE SELECT\n"); if (sensedat.model == PCIN500) status = mode_select_mud (fd, DEFAULT_MUD_1200); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT_MUD failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } DBG (3, "attach: sending MODE SENSE/MUP page\n"); memset (&msp, 0, sizeof (msp)); buf_size = sizeof (msp); status = mode_sense (fd, &msp, &buf_size, 3); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SENSE/MUP page failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #ifdef DEBUG_NEC DBG (3,"attach: MODE SENSE parameter\n"); DBG(11, "%02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", msp.mode_data_length, msp.mode_param_header2, msp.mode_param_header3, msp.mode_desciptor_length, msp.page_code, msp.page_length, msp.bmu, msp.res2, msp.mud[0], msp.mud[1], msp.res3, msp.res4); #endif dev = malloc (sizeof (*dev)); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); dev->sane.name = (SANE_String) strdup (devnam); dev->sane.vendor = "NEC"; model_name = inquiry_data + 16; dev->sane.model = strndup ((const char *)model_name, 10); dev->sane.type = "flatbed scanner"; dev->sensedat.model = sensedat.model; DBG (5, "dev->sane.name = %s\n", dev->sane.name); DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor); DBG (5, "dev->sane.model = %s\n", dev->sane.model); DBG (5, "dev->sane.type = %s\n", dev->sane.type); if (sensedat.model == PCIN500) dev->info.res_range.quant = 10; else dev->info.res_range.quant = 0; dev->info.tl_x_ranges[SCAN_SIMPLE].min = SANE_FIX(0); dev->info.br_x_ranges[SCAN_SIMPLE].min = SANE_FIX(1); dev->info.tl_y_ranges[SCAN_SIMPLE].min = SANE_FIX(0); dev->info.br_y_ranges[SCAN_SIMPLE].min = SANE_FIX(1); dev->info.tl_x_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); dev->info.br_x_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); dev->info.tl_y_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); dev->info.br_y_ranges[SCAN_SIMPLE].quant = SANE_FIX(0); if (sensedat.model == PCIN500) dev->info.res_default = 15; else dev->info.res_default = 150; dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(209); dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(210); dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(296); dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(297); dev->info.bmu = msp.bmu; dev->info.mud = (msp.mud[0] << 8) + msp.mud[1]; dev->info.adf_fsu_installed = 0; if (dev->sensedat.model == PCIN500) { dev->info.res_range.max = 48; dev->info.res_range.min = 5; dev->info.x_default = SANE_FIX(210); dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(210); /* 304.8mm is the real max */ dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(210); /* 304.8mm is the real max */ dev->info.y_default = SANE_FIX(297); dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(297); /* 431.8 is the real max */ dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(297); /* 431.8 is the real max */ } else { dev->info.res_range.max = 400; dev->info.res_range.min = 50; dev->info.x_default = SANE_FIX(210); dev->info.tl_x_ranges[SCAN_SIMPLE].max = SANE_FIX(210); /* 304.8mm is the real max */ dev->info.br_x_ranges[SCAN_SIMPLE].max = SANE_FIX(210); /* 304.8mm is the real max */ dev->info.y_default = SANE_FIX(297); dev->info.tl_y_ranges[SCAN_SIMPLE].max = SANE_FIX(297); /* 431.8 is the real max */ dev->info.br_y_ranges[SCAN_SIMPLE].max = SANE_FIX(297); /* 431.8 is the real max */ } sanei_scsi_close (fd); dev->info.threshold_range.min = 1; dev->info.threshold_range.max = 255; dev->info.threshold_range.quant = 0; dev->info.tint_range.min = 1; dev->info.tint_range.max = 255; dev->info.tint_range.quant = 0; dev->info.color_range.min = 1; dev->info.color_range.max = 255; dev->info.color_range.quant = 0; DBG (5, "res_default=%d\n", dev->info.res_default); DBG (5, "res_range.max=%d\n", dev->info.res_range.max); DBG (5, "res_range.min=%d\n", dev->info.res_range.min); DBG (5, "res_range.quant=%d\n", dev->info.res_range.quant); DBG (5, "x_default=%f\n", SANE_UNFIX(dev->info.x_default)); DBG (5, "tl_x_range[0].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_SIMPLE].max)); DBG (5, "tl_x_range[0].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_SIMPLE].min)); DBG (5, "tl_x_range[0].quant=%d\n", dev->info.tl_x_ranges[SCAN_SIMPLE].quant); DBG (5, "br_x_range[0].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_SIMPLE].max)); DBG (5, "br_x_range[0].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_SIMPLE].min)); DBG (5, "br_x_range[0].quant=%d\n", dev->info.br_x_ranges[SCAN_SIMPLE].quant); DBG (5, "y_default=%f\n", SANE_UNFIX(dev->info.y_default)); DBG (5, "tl_y_range[0].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_SIMPLE].max)); DBG (5, "tl_y_range[0].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_SIMPLE].min)); DBG (5, "tl_y_range[0].quant=%d\n", dev->info.tl_y_ranges[SCAN_SIMPLE].quant); DBG (5, "br_y_range[0].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_SIMPLE].max)); DBG (5, "br_y_range[0].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_SIMPLE].min)); DBG (5, "br_y_range[0].quant=%d\n", dev->info.br_y_ranges[SCAN_SIMPLE].quant); if (dev->info.adf_fsu_installed & HAVE_FSU) { DBG (5, "tl_x_range[1].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_FSU].max)); DBG (5, "tl_x_range[1].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_FSU].min)); DBG (5, "tl_x_range[1].quant=%d\n", dev->info.tl_x_ranges[SCAN_WITH_FSU].quant); DBG (5, "br_x_range[1].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_FSU].max)); DBG (5, "br_x_range[1].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_FSU].min)); DBG (5, "br_x_range[1].quant=%d\n", dev->info.br_x_ranges[SCAN_WITH_FSU].quant); DBG (5, "tl_y_range[1].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_FSU].max)); DBG (5, "tl_y_range[1].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_FSU].min)); DBG (5, "tl_y_range[1].quant=%d\n", dev->info.tl_y_ranges[SCAN_WITH_FSU].quant); DBG (5, "br_y_range[1].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_FSU].max)); DBG (5, "br_y_range[1].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_FSU].min)); DBG (5, "br_y_range[1].quant=%d\n", dev->info.br_y_ranges[SCAN_WITH_FSU].quant); } if (dev->info.adf_fsu_installed & HAVE_ADF) { DBG (5, "tl_x_range[2].max=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_ADF].max)); DBG (5, "tl_x_range[2].min=%f\n", SANE_UNFIX(dev->info.tl_x_ranges[SCAN_WITH_ADF].min)); DBG (5, "tl_x_range[2].quant=%d\n", dev->info.tl_x_ranges[SCAN_WITH_ADF].quant); DBG (5, "br_x_range[2].max=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_ADF].max)); DBG (5, "br_x_range[2].min=%f\n", SANE_UNFIX(dev->info.br_x_ranges[SCAN_WITH_ADF].min)); DBG (5, "br_x_range[2].quant=%d\n", dev->info.br_x_ranges[SCAN_WITH_ADF].quant); DBG (5, "tl_y_range[2].max=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_ADF].max)); DBG (5, "tl_y_range[2].min=%f\n", SANE_UNFIX(dev->info.tl_y_ranges[SCAN_WITH_ADF].min)); DBG (5, "tl_y_range[2].quant=%d\n", dev->info.tl_y_ranges[SCAN_WITH_ADF].quant); DBG (5, "br_y_range[2].max=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_ADF].max)); DBG (5, "br_y_range[2].min=%f\n", SANE_UNFIX(dev->info.br_y_ranges[SCAN_WITH_ADF].min)); DBG (5, "br_y_range[2].quant=%d\n", dev->info.br_y_ranges[SCAN_WITH_ADF].quant); } DBG (5, "bmu=%d\n", dev->info.bmu); DBG (5, "mud=%d\n", dev->info.mud); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } /* Enabling / disabling of gamma options. Depends on many user settable options, so lets put it into one function to be called by init_options and by sane_control_option */ #ifdef USE_CUSTOM_GAMMA static void set_gamma_caps(NEC_Scanner *s) { /* neither fixed nor custom gamma for line art modes */ if ( strcmp(s->val[OPT_MODE].s, M_LINEART) == 0 || strcmp(s->val[OPT_MODE].s, M_LINEART_COLOR) == 0) { s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else if (strcmp(s->val[OPT_MODE].s, M_GRAY) == 0) { s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) { s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { /* color mode */ s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) { s->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; } } #endif /* USE_CUSTOM_GAMMA */ /* The next function is a slightly modified version of sanei_constrain_value Instead of returning status information like STATUS_INVAL, it adjusts an invaild value to the nearest allowed one. */ static void clip_value (const SANE_Option_Descriptor * opt, void * value) { const SANE_String_Const * string_list; const SANE_Word * word_list; int i, num_matches, match; const SANE_Range * range; SANE_Word w, v; size_t len; switch (opt->constraint_type) { case SANE_CONSTRAINT_RANGE: w = *(SANE_Word *) value; range = opt->constraint.range; if (w < range->min) w = range->min; else if (w > range->max) w = range->max; if (range->quant) { v = (w - range->min + range->quant/2) / range->quant; w = v * range->quant + range->min; *(SANE_Word*) value = w; } break; case SANE_CONSTRAINT_WORD_LIST: w = *(SANE_Word *) value; word_list = opt->constraint.word_list; for (i = 1; w != word_list[i]; ++i) if (i >= word_list[0]) /* somewhat arbitrary... Would be better to have a default value explicitly defined. */ *(SANE_Word*) value = word_list[1]; break; case SANE_CONSTRAINT_STRING_LIST: /* Matching algorithm: take the longest unique match ignoring case. If there is an exact match, it is admissible even if the same string is a prefix of a longer option name. */ string_list = opt->constraint.string_list; len = strlen (value); /* count how many matches of length LEN characters we have: */ num_matches = 0; match = -1; for (i = 0; string_list[i]; ++i) if (strncasecmp (value, string_list[i], len) == 0 && len <= strlen (string_list[i])) { match = i; if (len == strlen (string_list[i])) { /* exact match... */ if (strcmp (value, string_list[i]) != 0) /* ...but case differs */ strcpy (value, string_list[match]); } ++num_matches; } if (num_matches > 1) /* xxx quite arbitrary... We could also choose the first match */ strcpy(value, string_list[match]); else if (num_matches == 1) strcpy (value, string_list[match]); else strcpy (value, string_list[0]); default: break; } } /* make sure that enough memory is allocated for each string, so that the strcpy in sane_control_option / set value cannot write behind the end of the allocated memory. */ static SANE_Status init_string_option(NEC_Scanner *s, SANE_String_Const name, SANE_String_Const title, SANE_String_Const desc, const SANE_String_Const *string_list, int option, int default_index) { int i; s->opt[option].name = name; s->opt[option].title = title; s->opt[option].desc = desc; s->opt[option].type = SANE_TYPE_STRING; s->opt[option].size = max_string_size (string_list); s->opt[option].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[option].constraint.string_list = string_list; s->val[option].s = malloc(s->opt[option].size); if (s->val[option].s == 0) { for (i = 1; i < NUM_OPTIONS; i++) { if (s->val[i].s && s->opt[i].type == SANE_TYPE_STRING) free(s->val[i].s); } return SANE_STATUS_NO_MEM; } strcpy(s->val[option].s, string_list[default_index]); return SANE_STATUS_GOOD; } static SANE_Status init_options (NEC_Scanner * s) { int i, default_source; SANE_Word scalar; DBG (10, "<< init_options "); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->val[i].s = 0; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* Mode group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ init_string_option(s, SANE_NAME_SCAN_MODE, SANE_TITLE_SCAN_MODE, SANE_DESC_SCAN_MODE, mode_list, OPT_MODE, MODES_COLOR); /* half tone */ init_string_option(s, SANE_NAME_HALFTONE_PATTERN, SANE_TITLE_HALFTONE_PATTERN, SANE_DESC_HALFTONE " (not support)", halftone_list, OPT_HALFTONE, 0); if (s->dev->sensedat.model == PCIN500) s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; i = 0; default_source = -1; if (s->dev->info.adf_fsu_installed & HAVE_ADF) { s->dev->info.scansources[i++] = use_adf; default_source = SCAN_WITH_ADF; } if (s->dev->info.adf_fsu_installed & HAVE_FSU) { s->dev->info.scansources[i++] = use_fsu; if (default_source < 0) default_source = SCAN_WITH_FSU; } s->dev->info.scansources[i++] = use_simple; if (default_source < 0) default_source = SCAN_SIMPLE; s->dev->info.scansources[i] = 0; init_string_option(s, SANE_NAME_SCAN_SOURCE, SANE_TITLE_SCAN_SOURCE, SANE_DESC_SCAN_SOURCE, (SANE_String_Const*)s->dev->info.scansources, OPT_SCANSOURCE, 0); if (i < 2) s->opt[OPT_SCANSOURCE].cap |= SANE_CAP_INACTIVE; if (s->dev->sensedat.model == PCIN500) init_string_option(s, "Paper size", "Paper size", "Paper size", paper_list_pcin500, OPT_PAPER, 0); else init_string_option(s, "Paper size", "Paper size", "Paper size", paper_list_pcinxxx, OPT_PAPER, 1); /* gamma */ init_string_option(s, "Gamma", "Gamma", "Gamma", gamma_list, OPT_GAMMA, 0); /* Resolution Group */ s->opt[OPT_RESOLUTION_GROUP].title = "Resolution"; s->opt[OPT_RESOLUTION_GROUP].desc = ""; s->opt[OPT_RESOLUTION_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_RESOLUTION_GROUP].cap = 0; s->opt[OPT_RESOLUTION_GROUP].constraint_type = SANE_CONSTRAINT_NONE; #ifdef USE_RESOLUTION_LIST /* select resolution */ if (s->dev->sensedat.model == PCIN500) init_string_option(s, "Resolution", "Resolution", "Resolution", resolution_list_pcin500, OPT_RESOLUTION_LIST, RESOLUTION_MAX_PCIN500); else init_string_option(s, "Resolution", "Resolution", "Resolution", resolution_list_pcinxxx, OPT_RESOLUTION_LIST, RESOLUTION_MAX_PCINXXX); #endif /* x & y resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; if (s->dev->sensedat.model == PCIN500) s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION"(x 10)"; else s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->dev->info.res_range; s->val[OPT_RESOLUTION].w = s->dev->info.res_default; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->dev->info.tl_x_ranges[default_source]; s->val[OPT_TL_X].w = s->dev->info.tl_x_ranges[default_source].min; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->dev->info.tl_y_ranges[default_source]; s->val[OPT_TL_Y].w = s->dev->info.tl_y_ranges[default_source].min; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->dev->info.br_x_ranges[default_source]; scalar = s->dev->info.x_default; clip_value (&s->opt[OPT_BR_X], &scalar); s->val[OPT_BR_X].w = scalar; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->dev->info.br_y_ranges[default_source]; scalar = s->dev->info.y_default; clip_value (&s->opt[OPT_BR_X], &scalar); s->val[OPT_BR_Y].w = scalar; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* edge emphasis */ init_string_option(s, "Edge emphasis", "Edge emphasis", "Edge emphasis", edge_emphasis_list, OPT_EDGE_EMPHASIS, 0); if (s->dev->sensedat.model == PCIN500) s->opt[OPT_EDGE_EMPHASIS].cap |= SANE_CAP_INACTIVE; /* OR */ s->opt[OPT_OR].name = "OR"; s->opt[OPT_OR].title = "OR"; s->opt[OPT_OR].desc = "Select OR emphancement"; s->opt[OPT_OR].type = SANE_TYPE_BOOL; s->val[OPT_OR].w = SANE_FALSE; /* EDGE */ s->opt[OPT_EDGE].name = "edge"; s->opt[OPT_EDGE].title = "Edge"; s->opt[OPT_EDGE].desc = "Select Edge emphancement"; s->opt[OPT_EDGE].type = SANE_TYPE_BOOL; s->val[OPT_EDGE].w = SANE_FALSE; /* NR */ s->opt[OPT_NR].name = "NR"; s->opt[OPT_NR].title = "NR"; s->opt[OPT_NR].desc = "Select noise reduction"; s->opt[OPT_NR].type = SANE_TYPE_BOOL; s->val[OPT_NR].w = SANE_FALSE; if (s->dev->sensedat.model != PCIN500) { s->opt[OPT_EDGE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_NR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_OR].cap |= SANE_CAP_INACTIVE; } /* tint */ s->opt[OPT_TINT].name = "tint"; s->opt[OPT_TINT].title = "Tint"; s->opt[OPT_TINT].desc = "Select tint"; s->opt[OPT_TINT].type = SANE_TYPE_INT; s->opt[OPT_TINT].unit = SANE_UNIT_NONE; s->opt[OPT_TINT].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TINT].constraint.range = &s->dev->info.tint_range; s->val[OPT_TINT].w = 128; if (s->dev->sensedat.model != PCIN500) s->opt[OPT_TINT].cap |= SANE_CAP_INACTIVE; /* color */ s->opt[OPT_COLOR].name = "color"; s->opt[OPT_COLOR].title = "Color"; s->opt[OPT_COLOR].desc = "Select color"; s->opt[OPT_COLOR].type = SANE_TYPE_INT; s->opt[OPT_COLOR].unit = SANE_UNIT_NONE; s->opt[OPT_COLOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_COLOR].constraint.range = &s->dev->info.color_range; s->val[OPT_COLOR].w = 128; if (s->dev->sensedat.model != PCIN500) s->opt[OPT_COLOR].cap |= SANE_CAP_INACTIVE; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &s->dev->info.threshold_range; s->val[OPT_THRESHOLD].w = 128; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].name = SANE_NAME_THRESHOLD "-red"; /* xxx the titles and decriptions are confusing: "set white point (red)" Any idea? maybe "threshold to get the red component on" */ s->opt[OPT_THRESHOLD_R].title = SANE_TITLE_THRESHOLD " (red)"; s->opt[OPT_THRESHOLD_R].desc = SANE_DESC_THRESHOLD " (red)"; s->opt[OPT_THRESHOLD_R].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD_R].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD_R].constraint.range = &s->dev->info.threshold_range; s->val[OPT_THRESHOLD_R].w = 128; s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].name = SANE_NAME_THRESHOLD "-green"; s->opt[OPT_THRESHOLD_G].title = SANE_TITLE_THRESHOLD " (green)"; s->opt[OPT_THRESHOLD_G].desc = SANE_DESC_THRESHOLD " (green)"; s->opt[OPT_THRESHOLD_G].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD_G].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD_G].constraint.range = &s->dev->info.threshold_range; s->val[OPT_THRESHOLD_G].w = 128; s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].name = SANE_NAME_THRESHOLD "-blue"; s->opt[OPT_THRESHOLD_B].title = SANE_TITLE_THRESHOLD " (blue)"; s->opt[OPT_THRESHOLD_B].desc = SANE_DESC_THRESHOLD " (blue)"; s->opt[OPT_THRESHOLD_B].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD_B].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD_B].constraint.range = &s->dev->info.threshold_range; s->val[OPT_THRESHOLD_B].w = 128; s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; #endif /* light color (for gray scale and line art scans) */ init_string_option(s, "LightColor", "LightColor", "LightColor", light_color_list, OPT_LIGHTCOLOR, 3); s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = SANE_FALSE; #ifdef USE_CUSTOM_GAMMA /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; #if 0 s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; #if 0 s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; #if 0 s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; #if 0 s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; set_gamma_caps(s); #endif DBG (10, ">>\n"); return SANE_STATUS_GOOD; } static SANE_Status do_cancel (NEC_Scanner * s) { DBG (10, "<< do_cancel "); #ifdef USE_FORK if (s->reader_pid > 0) { int exit_status; int count = 0; /* ensure child knows it's time to stop: */ DBG(11, "stopping reader process\n"); s->rdr_ctl->cancel = 1; while(reader_running(s) && count < 100) { usleep(100000); count++; }; if (reader_running(s)) { kill(s->reader_pid, SIGKILL); } wait(&exit_status); DBG(11, "reader process stopped\n"); s->reader_pid = 0; } #endif s->scanning = SANE_FALSE; if (s->fd >= 0) { sanei_scsi_close (s->fd); s->fd = -1; } #ifdef USE_FORK { struct shmid_ds ds; if (s->shmid != -1) shmctl(s->shmid, IPC_RMID, &ds); s->shmid = -1; } #endif if (s->buffer) free(s->buffer); s->buffer = 0; DBG (10, ">>\n"); return (SANE_STATUS_CANCELLED); } static NEC_New_Device *new_devs = 0; static NEC_New_Device *new_dev_pool = 0; static SANE_Status attach_and_list(const char *devnam) { SANE_Status res; NEC_Device *devp; NEC_New_Device *np; res = attach(devnam, &devp); if (res == SANE_STATUS_GOOD) { if (new_dev_pool) { np = new_dev_pool; new_dev_pool = np->next; } else { np = malloc(sizeof(NEC_New_Device)); if (np == 0) return SANE_STATUS_NO_MEM; } np->next =new_devs; np->dev = devp; new_devs = np; } return res; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char devnam[PATH_MAX] = "/dev/scanner"; char line[PATH_MAX]; const char *lp; char *word; char *end; FILE *fp; int opt_index = 0; int buffers[2] = {DEFAULT_BUFFERS, DEFAULT_BUFFERS}; int bufsize[2] = {DEFAULT_BUFSIZE, DEFAULT_BUFSIZE}; int queued_reads[2] = {DEFAULT_QUEUED_READS, DEFAULT_QUEUED_READS}; int linecount = 0; #if 1 NEC_Device nd; NEC_Device *dp = &nd; #else NEC_Device *dp; #endif NEC_New_Device *np; int i; authorize = authorize; /* silence compilation warnings */ DBG_INIT (); DBG (10, "<< sane_init "); DBG (1, "sane_init: NEC (Ver %d.%d)\n", NEC_MAJOR, NEC_MINOR); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (NEC_CONFIG_FILE); if (!fp) { /* use "/dev/scanner" as the default device name if no config file is available */ attach (devnam, &dp); /* make sure that there are at least two buffers */ if (DEFAULT_BUFFERS < 2) dp->info.buffers = DEFAULT_BUFFERS; else dp->info.buffers = 2; dp->info.wanted_bufsize = DEFAULT_BUFSIZE; dp->info.queued_reads = DEFAULT_QUEUED_READS; return SANE_STATUS_GOOD; } while (fgets(line, PATH_MAX, fp)) { linecount++; word = 0; lp = sanei_config_get_string(line, &word); if (word) { if (word[0] != '#') { if (strcmp(word, "option") == 0) { free(word); word = 0; lp = sanei_config_get_string(lp, &word); if (strcmp(word, "buffers") == 0) { free(word); word = 0; sanei_config_get_string(lp, &word); i = strtol(word, &end, 0); if (end == word) { DBG(1, "error in config file, line %i: number expected:\n", linecount); DBG(1, "%s\n", line); } else if (i > 2) buffers[opt_index] = i; else buffers[opt_index] = 2; } else if (strcmp(word, "buffersize") == 0) { free(word); word = 0; sanei_config_get_string(lp, &word); i = strtol(word, &end, 0); if (word == end) { DBG(1, "error in config file, line %i: number expected:\n", linecount); DBG(1, "%s\n", line); } else bufsize[opt_index] = i; } else if (strcmp(word, "readqueue") == 0) { free(word); word = 0; sanei_config_get_string(lp, &word); i = strtol(word, &end, 0); if (word == end) { DBG(1, "error in config file, line %i: number expected:\n", linecount); DBG(1, "%s\n", line); } else queued_reads[opt_index] = i; } else { DBG(1, "error in config file, line %i: unknown option\n", linecount); DBG(1, "%s\n", line); } } else { while (new_devs) { if (buffers[1] >= 2) new_devs->dev->info.buffers = buffers[1]; else new_devs->dev->info.buffers = 2; if (bufsize[1] > 0) new_devs->dev->info.wanted_bufsize = bufsize[1]; else new_devs->dev->info.wanted_bufsize = DEFAULT_BUFSIZE; if (queued_reads[1] >= 0) new_devs->dev->info.queued_reads = queued_reads[1]; else new_devs->dev->info.queued_reads = 0; np = new_devs->next; new_devs->next = new_dev_pool; new_dev_pool = new_devs; new_devs = np; } if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0; sanei_config_attach_matching_devices(line, &attach_and_list); buffers[1] = buffers[0]; bufsize[1] = bufsize[0]; queued_reads[1] = queued_reads[0]; opt_index = 1; } } if (word) free(word); } } while (new_devs) { if (buffers[1] >= 2) new_devs->dev->info.buffers = buffers[1]; else new_devs->dev->info.buffers = 2; if (bufsize[1] > 0) new_devs->dev->info.wanted_bufsize = bufsize[1]; else new_devs->dev->info.wanted_bufsize = DEFAULT_BUFSIZE; if (queued_reads[1] >= 0) new_devs->dev->info.queued_reads = queued_reads[1]; else new_devs->dev->info.queued_reads = 0; if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0; np = new_devs->next; free(new_devs); new_devs = np; } while (new_dev_pool) { np = new_dev_pool->next; free(new_dev_pool); new_dev_pool = np; } fclose(fp); DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } void sane_exit (void) { NEC_Device *dev, *next; DBG (10, "<< sane_exit "); for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free (dev); } first_dev = 0; if (devlist) free(devlist); DBG (10, ">>\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { NEC_Device *dev; int i; DBG (10, "<< sane_get_devices "); local_only = local_only; /* silence compilation warnings */ if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return (SANE_STATUS_NO_MEM); i = 0; for (dev = first_dev; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (10, ">>\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devnam, SANE_Handle * handle) { SANE_Status status; NEC_Device *dev; NEC_Scanner *s; #ifdef USE_CUSTOM_GAMMA int i, j; #endif DBG (10, "<< sane_open "); if (devnam[0]) { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) break; } if (!dev) { status = attach (devnam, &dev); if (status != SANE_STATUS_GOOD) return (status); } } else { dev = first_dev; } if (!dev) return (SANE_STATUS_INVAL); s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->dev = dev; s->buffer = 0; #ifdef USE_CUSTOM_GAMMA for (i = 0; i < 4; ++i) for (j = 0; j < 256; ++j) s->gamma_table[i][j] = j; #endif status = init_options (s); if (status != SANE_STATUS_GOOD) { /* xxx clean up mallocs */ return status; } s->next = first_handle; first_handle = s; *handle = s; DBG (10, ">>\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { NEC_Scanner *s = (NEC_Scanner *) handle; DBG (10, "<< sane_close "); if (s->fd != -1) sanei_scsi_close (s->fd); #ifdef USE_FORK { struct shmid_ds ds; if (s->shmid != -1) shmctl(s->shmid, IPC_RMID, &ds); } #endif if (s->buffer) free(s->buffer); free (s); DBG (10, ">>\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { NEC_Scanner *s = handle; DBG (10, "<< sane_get_option_descriptor "); if ((unsigned) option >= NUM_OPTIONS) return (0); DBG (10, ">>\n"); return (s->opt + option); } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { NEC_Scanner *s = handle; SANE_Status status; #ifdef USE_CUSTOM_GAMMA SANE_Word w, cap; #else SANE_Word cap; #endif int range_index; DBG (10, "<< sane_control_option %i", option); if (info) *info = 0; if (s->scanning) return (SANE_STATUS_DEVICE_BUSY); if (option >= NUM_OPTIONS) return (SANE_STATUS_INVAL); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return (SANE_STATUS_INVAL); if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_THRESHOLD: case OPT_TINT: case OPT_COLOR: #ifdef USE_COLOR_THRESHOLD case OPT_THRESHOLD_R: case OPT_THRESHOLD_G: case OPT_THRESHOLD_B: #endif case OPT_OR: case OPT_NR: case OPT_EDGE: case OPT_PREVIEW: #ifdef USE_CUSTOM_GAMMA case OPT_CUSTOM_GAMMA: #endif *(SANE_Word *) val = s->val[option].w; #if 0 /* here, values are read; reload should not be necessary */ if (info) *info |= SANE_INFO_RELOAD_PARAMS; #endif return (SANE_STATUS_GOOD); #ifdef USE_CUSTOM_GAMMA /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); return SANE_STATUS_GOOD; #endif /* string options: */ case OPT_MODE: case OPT_HALFTONE: case OPT_PAPER: case OPT_GAMMA: #ifdef USE_RESOLUTION_LIST case OPT_RESOLUTION_LIST: #endif case OPT_EDGE_EMPHASIS: case OPT_LIGHTCOLOR: case OPT_SCANSOURCE: strcpy (val, s->val[option].s); #if 0 if (info) *info |= SANE_INFO_RELOAD_PARAMS; #endif return (SANE_STATUS_GOOD); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; case OPT_NUM_OPTS: case OPT_THRESHOLD: /* xxx theoretically, we could use OPT_THRESHOLD in bi-level color mode to adjust all three other threshold together. But this would require to set the bit SANE_INFO_RELOAD_OPTIONS in *info, and that would unfortunately cause a crash in both xscanimage and xsane... Therefore, OPT_THRESHOLD is disabled for bi-level color scan right now. */ case OPT_TINT: case OPT_COLOR: #ifdef USE_COLOR_THRESHOLD case OPT_THRESHOLD_R: case OPT_THRESHOLD_G: case OPT_THRESHOLD_B: #endif case OPT_OR: case OPT_NR: case OPT_EDGE: case OPT_PREVIEW: s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_MODE: if (strcmp (val, M_LINEART) == 0) { s->opt[OPT_LIGHTCOLOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_TINT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_COLOR].cap |= SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; #endif if (s->dev->sensedat.model == PCIN500) s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (val, M_LINEART_COLOR) == 0) { s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_TINT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_COLOR].cap |= SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].cap &= ~SANE_CAP_INACTIVE; #endif if (s->dev->sensedat.model == PCIN500) s->opt[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (val, M_GRAY) == 0) { s->opt[OPT_LIGHTCOLOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_TINT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_COLOR].cap |= SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_TINT].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_COLOR].cap &= ~SANE_CAP_INACTIVE; #ifdef USE_COLOR_THRESHOLD s->opt[OPT_THRESHOLD_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD_B].cap |= SANE_CAP_INACTIVE; #endif s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; } #if 0 if ( strcmp (val, M_LINEART) == 0 || strcmp (val, M_GRAY) == 0) { s->opt[OPT_LIGHTCOLOR].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_LIGHTCOLOR].cap |= SANE_CAP_INACTIVE; } #endif strcpy(s->val[option].s, val); #ifdef USE_CUSTOM_GAMMA set_gamma_caps(s); #endif if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return (SANE_STATUS_GOOD); case OPT_GAMMA: case OPT_HALFTONE: case OPT_EDGE_EMPHASIS: case OPT_LIGHTCOLOR: #if 0 if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); #endif strcpy(s->val[option].s, val); return (SANE_STATUS_GOOD); case OPT_SCANSOURCE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; #if 0 if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); #endif strcpy(s->val[option].s, val); if (strcmp(val, use_fsu) == 0) range_index = SCAN_WITH_FSU; else if (strcmp(val, use_adf) == 0) range_index = SCAN_WITH_ADF; else range_index = SCAN_SIMPLE; s->opt[OPT_TL_X].constraint.range = &s->dev->info.tl_x_ranges[range_index]; clip_value (&s->opt[OPT_TL_X], &s->val[OPT_TL_X].w); s->opt[OPT_TL_Y].constraint.range = &s->dev->info.tl_y_ranges[range_index]; clip_value (&s->opt[OPT_TL_Y], &s->val[OPT_TL_Y].w); s->opt[OPT_BR_X].constraint.range = &s->dev->info.br_x_ranges[range_index]; clip_value (&s->opt[OPT_BR_X], &s->val[OPT_BR_X].w); s->opt[OPT_BR_Y].constraint.range = &s->dev->info.br_y_ranges[range_index]; clip_value (&s->opt[OPT_BR_Y], &s->val[OPT_BR_Y].w); return (SANE_STATUS_GOOD); case OPT_PAPER: if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; #if 0 if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); #endif strcpy(s->val[option].s, val); s->val[OPT_TL_X].w = SANE_FIX(0); s->val[OPT_TL_Y].w = SANE_FIX(0); if (strcmp (s->val[option].s, "A3") == 0){ s->val[OPT_BR_X].w = SANE_FIX(297); s->val[OPT_BR_Y].w = SANE_FIX(420); }else if (strcmp (s->val[option].s, "A4") == 0){ s->val[OPT_BR_X].w = SANE_FIX(210); s->val[OPT_BR_Y].w = SANE_FIX(297); }else if (strcmp (s->val[option].s, "A5") == 0){ s->val[OPT_BR_X].w = SANE_FIX(148.5); s->val[OPT_BR_Y].w = SANE_FIX(210); }else if (strcmp (s->val[option].s, "A6") == 0){ s->val[OPT_BR_X].w = SANE_FIX(105); s->val[OPT_BR_Y].w = SANE_FIX(148.5); }else if (strcmp (s->val[option].s, "B4") == 0){ s->val[OPT_BR_X].w = SANE_FIX(250); s->val[OPT_BR_Y].w = SANE_FIX(353); }else if (strcmp (s->val[option].s, "B5") == 0){ s->val[OPT_BR_X].w = SANE_FIX(182); s->val[OPT_BR_Y].w = SANE_FIX(257); }else if (strcmp (s->val[option].s, W_LETTER) == 0){ s->val[OPT_BR_X].w = SANE_FIX(279.4); s->val[OPT_BR_Y].w = SANE_FIX(431.8); }else if (strcmp (s->val[option].s, "Legal") == 0){ s->val[OPT_BR_X].w = SANE_FIX(215.9); s->val[OPT_BR_Y].w = SANE_FIX(355.6); }else if (strcmp (s->val[option].s, "Letter") == 0){ s->val[OPT_BR_X].w = SANE_FIX(215.9); s->val[OPT_BR_Y].w = SANE_FIX(279.4); }else if (strcmp (s->val[option].s, INVOICE) == 0){ s->val[OPT_BR_X].w = SANE_FIX(215.9); s->val[OPT_BR_Y].w = SANE_FIX(139.7); }else{ } return (SANE_STATUS_GOOD); #ifdef USE_RESOLUTION_LIST case OPT_RESOLUTION_LIST: if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; #if 0 if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); #endif for (i = 0; s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]; i++) { if (strcmp (val, s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]) == 0){ s->val[OPT_RESOLUTION].w = atoi(s->opt[OPT_RESOLUTION_LIST].constraint.string_list[i]); if (info) *info |= SANE_INFO_RELOAD_PARAMS; break; } } return (SANE_STATUS_GOOD); #endif #ifdef USE_CUSTOM_GAMMA /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == s->val[OPT_CUSTOM_GAMMA].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[OPT_CUSTOM_GAMMA].w = w; set_gamma_caps(s); return SANE_STATUS_GOOD; #endif } } DBG (10, ">>\n"); return (SANE_STATUS_INVAL); } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int width, length, res; const char *mode; NEC_Scanner *s = handle; DBG (10, "<< sane_get_parameters "); res = s->val[OPT_RESOLUTION].w * s->dev->info.res_range.quant; if (!s->scanning) { /* make best-effort guess at what parameters will look like once scanning starts. */ memset (&s->params, 0, sizeof (s->params)); width = MM_TO_PIX( SANE_UNFIX(s->val[OPT_BR_X].w) - SANE_UNFIX(s->val[OPT_TL_X].w), s->dev->info.mud); length = MM_TO_PIX( SANE_UNFIX(s->val[OPT_BR_Y].w) - SANE_UNFIX(s->val[OPT_TL_Y].w), s->dev->info.mud); s->width = width; s->length = length; s->params.pixels_per_line = width * res / s->dev->info.mud; s->params.lines = length * res / s->dev->info.mud; if (s->dev->sensedat.model == PCIN500) { s->params.pixels_per_line += 1; s->params.lines += 1; } s->unscanned_lines = s->params.lines; } #if 0 else { buffer_status bs; SANE_Status status; size_t len = sizeof (buffer_status); status = get_data_buffer_status (s->fd, &bs, &len); DBG (11, "<< get_data_buffer_status "); if (status != SANE_STATUS_GOOD) { do_cancel(s); return (status); } DBG (11, ">>\n "); { #ifdef DEBUG_NEC int i; u_char *buf = &bs; DBG(11, "get data buffer status(debug):\n"); for (i = 0; i < len; i += 16) { DBG(1, "%2x %2x %2x %2x %2x %2x %2x %2x - %2x %2x %2x %2x \n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7], buf[i+8], buf[i+9], buf[i+10], buf[i+11]); } #endif } } #endif res = s->val[OPT_RESOLUTION].w * s->dev->info.res_range.quant; mode = s->val[OPT_MODE].s; if (strcmp (mode, M_LINEART) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; s->params.depth = 1; s->modes = MODES_LINEART; } else if (strcmp (mode, M_GRAY) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; s->modes = MODES_GRAY; } else if (strcmp (mode, M_LINEART_COLOR) == 0) { s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * (s->params.pixels_per_line + 7) / 8; s->params.depth = 8; s->modes = MODES_LINEART_COLOR; } else { s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line; s->params.depth = 8; s->modes = MODES_COLOR; } s->params.last_frame = SANE_TRUE; if (params) *params = s->params; DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } #ifdef USE_CUSTOM_GAMMA static int sprint_gamma(Option_Value val, SANE_Byte *dst) { int i; SANE_Byte *p = dst; p += sprintf((char *) p, "%i", val.wa[0]); for (i = 1; i < 256; i++) p += sprintf((char *) p, ",%i", val.wa[i] > 255 ? 255 : val.wa[i]); return p - dst; } static SANE_Status send_ascii_gamma_tables (NEC_Scanner *s) { SANE_Status status; int i; DBG(11, "<< send_ascii_gamma_tables "); /* we need: 4 bytes for each gamma value (3 digits + delimiter) + 10 bytes for the command header i.e. 4 * 4 * 256 + 10 = 4106 bytes */ if (s->dev->info.bufsize < 4106) return SANE_STATUS_NO_MEM; memset(s->buffer, 0, 4106); i = sprint_gamma(s->val[OPT_GAMMA_VECTOR_R], &s->buffer[10]); s->buffer[10+i++] = '/'; i += sprint_gamma(s->val[OPT_GAMMA_VECTOR_G], &s->buffer[10+i]); s->buffer[10+i++] = '/'; i += sprint_gamma(s->val[OPT_GAMMA_VECTOR_B], &s->buffer[10+i]); s->buffer[10+i++] = '/'; i += sprint_gamma(s->val[OPT_GAMMA_VECTOR], &s->buffer[10+i]); DBG(12, "%s\n", &s->buffer[10]); s->buffer[0] = SEND; s->buffer[2] = 0x03; s->buffer[7] = i >> 8; s->buffer[8] = i & 0xff; wait_ready(s->fd); status = sanei_scsi_cmd (s->fd, s->buffer, i+10, 0, 0); DBG(11, ">>\n"); return status; } #endif static SANE_Status send_binary_g_table(NEC_Scanner *s, SANE_Word *a, int dtq) { SANE_Status status; unsigned int i, j; dtq = dtq; /* silence compilation warnings */ DBG(11, "<< send_binary_g_table\n"); i = 256; if (s->dev->info.bufsize < i) return SANE_STATUS_NO_MEM; memset(s->buffer, 0, i+10); s->buffer[0] = SEND; s->buffer[2] = 0x03; s->buffer[7] = i >> 8; s->buffer[8] = i & 0xff; for (i = 0; i < 256; i++) { s->buffer[i+11] = a[i&0xff] & 0xff; } for (j = 0; j < 256; j += 16) { DBG(11, "%02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x\n", a[j ], a[j+1], a[j+2], a[j+3], a[j+4], a[j+5], a[j+6], a[j+7], a[j+8], a[j+9], a[j+10], a[j+11], a[j+12], a[j+13], a[j+14], a[j+15]); } DBG(12, "transfer length = %d\n", i); DBG(12, "buffer[7] = %d\n", s->buffer[7]); DBG(12, "buffer[8] = %d\n", s->buffer[8]); /* wait_ready(s->fd); */ status = sanei_scsi_cmd (s->fd, s->buffer, i+10, 0, 0); DBG(11, ">>\n"); return status; } #ifdef USE_CUSTOM_GAMMA static SANE_Status send_binary_gamma_tables (NEC_Scanner *s) { SANE_Status status; status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR].wa, 0x10); if (status != SANE_STATUS_GOOD) return status; DBG(11, "send_binary_gamma_tables\n"); #if 0 status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_R].wa, 0x11); if (status != SANE_STATUS_GOOD) return status; status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_G].wa, 0x12); if (status != SANE_STATUS_GOOD) return status; status = send_binary_g_table(s, s->val[OPT_GAMMA_VECTOR_B].wa, 0x13); #endif return status; } static SANE_Status send_gamma_tables (NEC_Scanner *s) { if (s->dev->sensedat.model == PCIN500) { return send_binary_gamma_tables(s); } else { return send_ascii_gamma_tables(s); } } #endif #ifdef USE_COLOR_THRESHOLD /* not used? */ #if 0 static SANE_Status send_threshold_data(NEC_Scanner *s) { SANE_Status status; SANE_Byte cmd[26] = {SEND, 0, 0x82, 0, 0, 0, 0, 0, 0, 0}; int len; memset(cmd, 0, sizeof(cmd)); /* maximum string length: 3 bytes for each number (they are restricted to the range 0..255), 3 '/' and the null-byte, total: 16 bytes. */ len = sprintf((char *) &cmd[10], "%i/%i/%i/%i", s->val[OPT_THRESHOLD_R].w, s->val[OPT_THRESHOLD_G].w, s->val[OPT_THRESHOLD_B].w, s->val[OPT_THRESHOLD].w); cmd[8] = len; wait_ready(s->fd); status = sanei_scsi_cmd(s->fd, cmd, len + 10, 0, 0); return status; } #endif #endif SANE_Status sane_start (SANE_Handle handle) { char *mode, *halftone, *gamma, *edge, *lightcolor, *adf_fsu; NEC_Scanner *s = handle; SANE_Status status; size_t buf_size; window_param wp; DBG (10, "<< sane_start "); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; s->dev->sensedat.complain_on_adf_error = 1; #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED s->dev->info.bufsize = s->dev->info.wanted_bufsize; if (s->dev->info.bufsize < 32 * 1024) s->dev->info.bufsize = 32 * 1024; { int bsize = s->dev->info.bufsize; status = sanei_scsi_open_extended (s->dev->sane.name, &s->fd, &sense_handler, &s->dev->sensedat, &bsize); s->dev->info.bufsize = bsize; } if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->dev->sane.name, sane_strstatus (status)); return (status); } /* make sure that we got at least 32 kB. Even then, the scan will be awfully slow. */ if (s->dev->info.bufsize < 32 * 1024) { sanei_scsi_close(s->fd); s->fd = -1; return SANE_STATUS_NO_MEM; } #else status = sanei_scsi_open(s->dev->sane.name, &s->fd, &sense_handler, &s->dev->sensedat); if (s->dev->info.wanted_bufsize < sanei_scsi_max_request_size) s->dev->info.bufsize = s->dev->info.wanted_bufsize; else s->dev->info.bufsize = sanei_scsi_max_request_size; if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->dev->sane.name, sane_strstatus (status)); return (status); } #endif s->buffer = malloc(s->dev->info.bufsize); if (!s->buffer) { sanei_scsi_close(s->fd); s->fd = -1; free(s); return SANE_STATUS_NO_MEM; } #ifdef USE_FORK { struct shmid_ds ds; size_t n; s->shmid = shmget(IPC_PRIVATE, sizeof(NEC_rdr_ctl) + s->dev->info.buffers * (sizeof(NEC_shmem_ctl) + s->dev->info.bufsize), IPC_CREAT | 0600); if (s->shmid == -1) { free(s->buffer); s->buffer = 0; sanei_scsi_close(s->fd); s->fd = -1; return SANE_STATUS_NO_MEM; } s->rdr_ctl = (NEC_rdr_ctl*) shmat(s->shmid, 0, 0); if ((int)s->rdr_ctl == -1) { shmctl(s->shmid, IPC_RMID, &ds); free(s->buffer); s->buffer = 0; sanei_scsi_close(s->fd); s->fd = -1; return SANE_STATUS_NO_MEM; } s->rdr_ctl->buf_ctl = (NEC_shmem_ctl*) &s->rdr_ctl[1]; for (n = 0; n < s->dev->info.buffers; n++) { s->rdr_ctl->buf_ctl[n].buffer = (SANE_Byte*) &s->rdr_ctl->buf_ctl[s->dev->info.buffers] + n * s->dev->info.bufsize; } } #endif /* USE_FORK */ DBG (5, "start: TEST_UNIT_READY\n"); status = test_unit_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "TEST UNIT READY failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } DBG (3, "start: sending MODE SELECT\n"); status = mode_select_mud (s->fd, s->dev->info.mud); if (status != SANE_STATUS_GOOD) { DBG (1, "start: MODE_SELECT6 failed\n"); sanei_scsi_close (s->fd); s->fd = -1; return (status); } mode = s->val[OPT_MODE].s; halftone = s->val[OPT_HALFTONE].s; gamma = s->val[OPT_GAMMA].s; edge = s->val[OPT_EDGE_EMPHASIS].s; lightcolor = s->val[OPT_LIGHTCOLOR].s; adf_fsu = s->val[OPT_SCANSOURCE].s; if (s->val[OPT_PREVIEW].w == SANE_FALSE) { s->res = s->val[OPT_RESOLUTION].w * s->dev->info.res_range.quant; } else { s->res = 75; } s->ulx = MM_TO_PIX(SANE_UNFIX(s->val[OPT_TL_X].w), s->dev->info.mud); s->uly = MM_TO_PIX(SANE_UNFIX(s->val[OPT_TL_Y].w), s->dev->info.mud); s->threshold = s->val[OPT_THRESHOLD].w; if (strcmp (mode, M_LINEART_COLOR) == 0) s->bpp = 1; else s->bpp = s->params.depth; s->adf_fsu_mode = SCAN_SIMPLE; /* default: scan without ADF and FSU */ if (strcmp(adf_fsu, use_fsu) == 0) s->adf_fsu_mode = SCAN_WITH_FSU; else if (strcmp(adf_fsu, use_adf) == 0) s->adf_fsu_mode = SCAN_WITH_ADF; else if (strcmp(adf_fsu, use_adf) == 0) s->adf_fsu_mode = SCAN_SIMPLE; /* halftone must not set to be zero PC-IN500 */ s->halftone = 0x01; if (strcmp (mode, M_LINEART) == 0) { s->reverse = 0; s->image_composition = 1; if (strcmp(halftone, M_BILEVEL) == 0) { s->image_composition = 0; s->halftone = 0x01; } else if (strcmp(halftone, M_DITHER1) == 0) s->halftone = 0x01; else if (strcmp(halftone, M_DITHER2) == 0) s->halftone = 0x10; else if (strcmp(halftone, M_DITHER3) == 0) s->halftone = 0x20; } else if (strcmp (mode, M_GRAY) == 0) { s->image_composition = 2; s->reverse = 1; } else if (strcmp (mode, M_LINEART_COLOR) == 0) { s->reverse = 1; s->image_composition = 4; if (strcmp(halftone, M_BILEVEL) == 0) { s->image_composition = 3; s->halftone = 0x01; } else if (strcmp(halftone, M_DITHER1) == 0) s->halftone = 0x01; else if (strcmp(halftone, M_DITHER2) == 0) s->halftone = 0x10; else if (strcmp(halftone, M_DITHER3) == 0) s->halftone = 0x20; } else if (strcmp (mode, M_COLOR) == 0) { s->image_composition = 5; s->reverse = 1; } if (s->dev->sensedat.model == PCIN500) { s->or = s->val[OPT_OR].w; s->nr = s->val[OPT_NR].w; s->edge = s->val[OPT_EDGE].w; } else { if (strcmp (edge, EDGE_NONE) == 0) s->edge = 0; else if (strcmp (edge, EDGE_MIDDLE) == 0) s->edge = 1; else if (strcmp (edge, EDGE_STRONG) == 0) s->edge = 2; else if (strcmp (edge, EDGE_BLUR) == 0) s->edge = 3; } s->lightcolor = 3; if (strcmp(lightcolor, LIGHT_GREEN) == 0) s->lightcolor = 0; else if (strcmp(lightcolor, LIGHT_RED) == 0) s->lightcolor = 1; else if (strcmp(lightcolor, LIGHT_BLUE) == 0) s->lightcolor = 2; else if (strcmp(lightcolor, LIGHT_NONE) == 0) s->lightcolor = 3; s->adf_scan = 0; #ifdef USE_CUSTOM_GAMMA if (s->val[OPT_CUSTOM_GAMMA].w == SANE_FALSE) { #endif if (s->dev->sensedat.model == PCIN500) { if (strcmp (gamma, CRT1)) s->gamma = 1; else if (strcmp (gamma, CRT2)) s->gamma = 2; else if (strcmp (gamma, PRINTER1)) s->gamma = 3; else if (strcmp (gamma, PRINTER2)) s->gamma = 4; else if (strcmp (gamma, NONE)) s->gamma = 5; } #if 0 if (s->dev->sensedat.model != PCIN500) { ss.dtc = 0x03; if (strcmp (gamma, GAMMA10) == 0) ss.dtq = 0x01; else ss.dtq = 0x02; ss.length = 0; DBG (5, "start: SEND\n"); status = send (s->fd, &ss); if (status != SANE_STATUS_GOOD) { DBG (1, "send failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } } else #else { int i; SANE_Word gtbl[256]; #if 0 if (strcmp (gamma, GAMMA10) == 0) for (i = 0; i < 256; i++) gtbl[i] = i; else #endif { gtbl[0] = 0; for (i = 1; i < 256; i++) gtbl[i] = 255 * exp(0.45 * log(i/255.0)); } send_binary_g_table(s, gtbl, 0x10); send_binary_g_table(s, gtbl, 0x11); send_binary_g_table(s, gtbl, 0x12); send_binary_g_table(s, gtbl, 0x13); } #endif /* DEBUG_NEC */ #ifdef USE_CUSTOM_GAMMA } else { s->gamma = 9; status = send_gamma_tables(s); } if (status != SANE_STATUS_GOOD) { sanei_scsi_close (s->fd); s->fd = -1; return (status); } #endif s->tint = s->val[OPT_TINT].w; s->color = s->val[OPT_COLOR].w; memset (&wp, 0, sizeof (wp)); /* every NEC scanner seems to have a different window descriptor block... */ if (s->dev->sensedat.model == PCIN500) buf_size = sizeof(WDB) + sizeof(WDBX500); else buf_size = sizeof(WDB); wp.wpdh.wdl[0] = buf_size >> 8; wp.wpdh.wdl[1] = buf_size; wp.wdb.x_res[0] = s->res >> 8; wp.wdb.x_res[1] = s->res; wp.wdb.y_res[0] = s->res >> 8; wp.wdb.y_res[1] = s->res; wp.wdb.x_ul[0] = s->ulx >> 24; wp.wdb.x_ul[1] = s->ulx >> 16; wp.wdb.x_ul[2] = s->ulx >> 8; wp.wdb.x_ul[3] = s->ulx; wp.wdb.y_ul[0] = s->uly >> 24; wp.wdb.y_ul[1] = s->uly >> 16; wp.wdb.y_ul[2] = s->uly >> 8; wp.wdb.y_ul[3] = s->uly; wp.wdb.width[0] = s->width >> 24; wp.wdb.width[1] = s->width >> 16; wp.wdb.width[2] = s->width >> 8; wp.wdb.width[3] = s->width; wp.wdb.length[0] = s->length >> 24; wp.wdb.length[1] = s->length >> 16; wp.wdb.length[2] = s->length >> 8; wp.wdb.length[3] = s->length; wp.wdb.brightness = 0; wp.wdb.threshold = s->threshold; wp.wdb.brightness = 128; wp.wdb.contrast = 128; wp.wdb.image_composition = s->image_composition; if (s->image_composition <= 2 || s->image_composition >= 5) wp.wdb.bpp = s->bpp; else wp.wdb.bpp = 1; wp.wdb.ht_pattern[0] = 0; wp.wdb.ht_pattern[1] = 0; if (s->dev->sensedat.model == PCIN500) wp.wdb.ht_pattern[1] = s->halftone; wp.wdb.rif_padding = (s->reverse * 128) + 0; if (s->dev->sensedat.model == PCIN500) { wp.wdbx500.data_length = 0x07; wp.wdbx500.control = 0 | (s->or << 7) | (s->edge << 6) | (s->nr << 5) | (s->lightcolor << 2); wp.wdbx500.format = 0; wp.wdbx500.gamma = s->gamma; wp.wdbx500.tint = s->tint; wp.wdbx500.color = s->color; wp.wdbx500.reserved1 = 0; wp.wdbx500.reserved2 = 0; } DBG (5, "wdl=%d\n", (wp.wpdh.wdl[0] << 8) + wp.wpdh.wdl[1]); DBG (5, "xres=%d\n", (wp.wdb.x_res[0] << 8) + wp.wdb.x_res[1]); DBG (5, "yres=%d\n", (wp.wdb.y_res[0] << 8) + wp.wdb.y_res[1]); DBG (5, "ulx=%d\n", (wp.wdb.x_ul[0] << 24) + (wp.wdb.x_ul[1] << 16) + (wp.wdb.x_ul[2] << 8) + wp.wdb.x_ul[3]); DBG (5, "uly=%d\n", (wp.wdb.y_ul[0] << 24) + (wp.wdb.y_ul[1] << 16) + (wp.wdb.y_ul[2] << 8) + wp.wdb.y_ul[3]); DBG (5, "width=%d\n", (wp.wdb.width[0] << 8) + (wp.wdb.width[1] << 16) + (wp.wdb.width[2] << 8) + wp.wdb.width[3]); DBG (5, "length=%d\n", (wp.wdb.length[0] << 16) + (wp.wdb.length[1] << 16) + (wp.wdb.length[2] << 8) + wp.wdb.length[3]); DBG (5, "threshold=%d\n", wp.wdb.threshold); DBG (5, "image_composition=%d\n", wp.wdb.image_composition); DBG (5, "bpp=%d\n", wp.wdb.bpp); DBG (5, "rif_padding=%d\n", wp.wdb.rif_padding); #ifdef DEBUG_NEC { window_param foo; size_t len = buf_size; len += sizeof(WPDH); DBG (5, "start: GET WINDOW\n"); status = get_window (s->fd, &foo, &len); if (status != SANE_STATUS_GOOD) { DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } #if 1 { unsigned char *p = (unsigned char*) &foo; int i; DBG(11, "get window(debug):\n"); for (i = 0; i < len; i += 16) { DBG(1, "%2x %2x %2x %2x %2x %2x %2x %2x - %2x %2x %2x %2x %2x %2x %2x %2x\n", p[i], p[i+1], p[i+2], p[i+3], p[i+4], p[i+5], p[i+6], p[i+7], p[i+8], p[i+9], p[i+10], p[i+11], p[i+12], p[i+13], p[i+14], p[i+15]); } } #endif foo.wpdh.wpdh[1] = 0; status = set_window (s->fd, &foo, len); if (status != SANE_STATUS_GOOD) { DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } #if 1 { unsigned char *p = (unsigned char*) &foo; int i; DBG(11, "set window(debug):\n"); for (i = 0; i < len; i += 16) { DBG(1, "%2x %2x %2x %2x %2x %2x %2x %2x - %2x %2x %2x %2x %2x %2x %2x %2x\n", p[i], p[i+1], p[i+2], p[i+3], p[i+4], p[i+5], p[i+6], p[i+7], p[i+8], p[i+9], p[i+10], p[i+11], p[i+12], p[i+13], p[i+14], p[i+15]); } } #endif } #endif /* debug_nec */ #ifdef DEBUG_NEC { unsigned char *p = (unsigned char*) ℘ int i; DBG(11, "set window(debug):\n"); for (i = 0; i < sizeof(wp.wdb) + sizeof(wp.wdbx500); i += 16) { DBG(1, "%2x %2x %2x %2x %2x %2x %2x %2x - %2x %2x %2x %2x %2x %2x %2x %2x\n", p[i], p[i+1], p[i+2], p[i+3], p[i+4], p[i+5], p[i+6], p[i+7], p[i+8], p[i+9], p[i+10], p[i+11], p[i+12], p[i+13], p[i+14], p[i+15]); } } #endif /* debug_nec */ buf_size += sizeof(WPDH); DBG (5, "start: SET WINDOW\n"); status = set_window (s->fd, &wp, buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } memset (&wp, 0, buf_size); DBG (5, "start: GET WINDOW\n"); status = get_window (s->fd, &wp, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return (status); } #ifdef DEBUG_NEC { unsigned char *p = (unsigned char*) ℘ int i; DBG(11, "get window(debug):\n"); for (i = 0; i < buf_size; i += 16) { DBG(1, "%2x %2x %2x %2x %2x %2x %2x %2x - %2x %2x %2x %2x %2x %2x %2x %2x\n", p[i], p[i+1], p[i+2], p[i+3], p[i+4], p[i+5], p[i+6], p[i+7], p[i+8], p[i+9], p[i+10], p[i+11], p[i+12], p[i+13], p[i+14], p[i+15]); } } #endif DBG (5, "xres=%d\n", (wp.wdb.x_res[0] << 8) + wp.wdb.x_res[1]); DBG (5, "yres=%d\n", (wp.wdb.y_res[0] << 8) + wp.wdb.y_res[1]); DBG (5, "ulx=%d\n", (wp.wdb.x_ul[0] << 24) + (wp.wdb.x_ul[1] << 16) + (wp.wdb.x_ul[2] << 8) + wp.wdb.x_ul[3]); DBG (5, "uly=%d\n", (wp.wdb.y_ul[0] << 24) + (wp.wdb.y_ul[1] << 16) + (wp.wdb.y_ul[2] << 8) + wp.wdb.y_ul[3]); DBG (5, "width=%d\n", (wp.wdb.width[0] << 24) + (wp.wdb.width[1] << 16) + (wp.wdb.width[2] << 8) + wp.wdb.width[3]); DBG (5, "length=%d\n", (wp.wdb.length[0] << 24) + (wp.wdb.length[1] << 16) + (wp.wdb.length[2] << 8) + wp.wdb.length[3]); DBG (5, "start: SCAN\n"); s->scanning = SANE_TRUE; s->busy = SANE_TRUE; s->cancel = SANE_FALSE; s->get_params_called = 0; status = scan (s->fd); #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: scan started %li.%06li\n", t.tv_sec, t.tv_usec); } #endif if (status != SANE_STATUS_GOOD) { DBG (1, "start of scan failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; s->busy = SANE_FALSE; s->cancel = SANE_FALSE; return (status); } /* ask the scanner for the scan size */ /* wait_ready(s->fd); */ #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: wait_ready ok %li.%06li\n", t.tv_sec, t.tv_usec); } #endif sane_get_parameters(s, 0); #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: get_params ok %li.%06li\n", t.tv_sec, t.tv_usec); } #endif if (strcmp (mode, M_LINEART_COLOR) != 0) s->bytes_to_read = s->params.bytes_per_line * s->params.lines; else { s->bytes_to_read = s->params.bytes_per_line * s->params.lines; } #ifdef USE_FORK { size_t i; for (i = 0; i < s->dev->info.buffers; i++) s->rdr_ctl->buf_ctl[i].shm_status = SHM_EMPTY; s->read_buff = 0; s->rdr_ctl->cancel = 0; s->rdr_ctl->running = 0; s->rdr_ctl->status = SANE_STATUS_GOOD; } s->reader_pid = fork(); #ifdef DEBUG { struct timeval t; gettimeofday(&t, 0); DBG(2, "rd: forked %li.%06li %i\n", t.tv_sec, t.tv_usec, s->reader_pid); } #endif if (s->reader_pid == 0) { sigset_t ignore_set; struct SIGACTION act; sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); /* don't use exit() since that would run the atexit() handlers... */ _exit (reader_process (s)); } else if (s->reader_pid == -1) { s->busy = SANE_FALSE; do_cancel(s); return SANE_STATUS_NO_MEM; } #endif /* USE_FORK */ DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_RESOLUTION].w); s->busy = SANE_FALSE; s->buf_used = 0; s->buf_pos = 0; if (s->cancel == SANE_TRUE) { do_cancel(s); DBG (10, ">>\n"); return(SANE_STATUS_CANCELLED); } DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } static SANE_Status sane_read_direct (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, SANE_Int * len) { NEC_Scanner *s = handle; SANE_Status status; size_t nread; DBG (10, "<< sane_read_direct "); #if 0 { buffer_status bs; size_t len = sizeof (buffer_status); get_data_buffer_status (s->fd, &bs, &len); DBG (20, "buffer_status: %i ", bs.fdb[0]*256*256 + bs.fdb[1]*256 + bs.fdb[2]); } #endif DBG (20, "remaining: %lu ", (u_long) s->bytes_to_read); *len = 0; if (s->bytes_to_read == 0) { do_cancel (s); return (SANE_STATUS_EOF); } if (!s->scanning) return (do_cancel (s)); nread = max_len; if (nread > s->bytes_to_read) nread = s->bytes_to_read; if (nread > s->dev->info.bufsize) nread = s->dev->info.bufsize; #ifdef USE_FORK status = read_data(s, dst_buf, &nread); #else #ifdef NOTUSE_PCIN500 wait_ready(s->fd); #endif status = read_data (s, dst_buf, &nread); #endif if (status != SANE_STATUS_GOOD) { do_cancel (s); return (SANE_STATUS_IO_ERROR); } *len = nread; s->bytes_to_read -= nread; DBG (20, "remaining: %lu ", (u_long) s->bytes_to_read); DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } static SANE_Status sane_read_shuffled (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, SANE_Int * len, int eight_bit_data) { NEC_Scanner *s = handle; SANE_Status status; SANE_Byte *dest, *red, *green, *blue, mask; SANE_Int transfer; size_t nread, ntest, pixel, max_pixel, line, max_line; size_t start_input, bytes_per_line_in; DBG (10, "<< sane_read_shuffled "); #if 0 { buffer_status bs; size_t len = sizeof (buffer_status); get_data_buffer_status (s->fd, &bs, &len); DBG (20, "buffer_status: %i ", bs.fdb[0]*256*256 + bs.fdb[1]*256 + bs.fdb[2]); } #endif *len = 0; if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used) { do_cancel (s); DBG (10, ">>\n"); return (SANE_STATUS_EOF); } if (!s->scanning) { DBG (10, ">>\n"); return(do_cancel(s)); } if (s->buf_pos < s->buf_used) { transfer = s->buf_used - s->buf_pos; if (transfer > max_len) transfer = max_len; memcpy(dst_buf, &(s->buffer[s->buf_pos]), transfer); s->buf_pos += transfer; max_len -= transfer; *len = transfer; } while (max_len > 0 && s->bytes_to_read > 0) { if (eight_bit_data) { nread = s->dev->info.bufsize / s->params.bytes_per_line - 1; nread *= s->params.bytes_per_line; if (nread > s->bytes_to_read) nread = s->bytes_to_read; max_line = nread / s->params.bytes_per_line; start_input = s->params.bytes_per_line; bytes_per_line_in = s->params.bytes_per_line; } else { bytes_per_line_in = (s->params.pixels_per_line + 7) / 8; bytes_per_line_in *= 3; max_line = s->params.bytes_per_line + bytes_per_line_in; max_line = s->dev->info.bufsize / max_line; nread = max_line * bytes_per_line_in; if (nread > s->bytes_to_read) { nread = s->bytes_to_read; max_line = nread / bytes_per_line_in; } start_input = s->dev->info.bufsize - nread; } ntest = nread; #ifdef USE_FORK status = read_data (s, &(s->buffer[start_input]), &nread); #else status = read_data (s, &(s->buffer[start_input]), &nread); #endif if (status != SANE_STATUS_GOOD) { do_cancel (s); DBG (10, ">>\n"); return (SANE_STATUS_IO_ERROR); } if (nread != ntest) { /* if this happens, something is wrong in the input buffer management... */ DBG(1, "Warning: could not read an integral number of scan lines\n"); DBG(1, " image will be scrambled\n"); } s->buf_used = max_line * s->params.bytes_per_line; s->buf_pos = 0; s->bytes_to_read -= nread; dest = s->buffer; max_pixel = s->params.pixels_per_line; if (eight_bit_data) for (line = 1; line <= max_line; line++) { red = &(s->buffer[line * s->params.bytes_per_line]); green = &(red[max_pixel]); blue = &(green[max_pixel]); for (pixel = 0; pixel < max_pixel; pixel++) { *dest++ = *red++; *dest++ = *green++; *dest++ = *blue++; } } else for (line = 0; line < max_line; line++) { red = &(s->buffer[start_input + line * bytes_per_line_in]); green = &(red[(max_pixel+7)/8]); blue = &(green[(max_pixel+7)/8]); mask = 0x80; for (pixel = 0; pixel < max_pixel; pixel++) { *dest++ = (*red & mask) ? 0xff : 0; *dest++ = (*green & mask) ? 0xff : 0; *dest++ = (*blue & mask) ? 0xff : 0; mask = mask >> 1; if (mask == 0) { mask = 0x80; red++; green++; blue++; } } } transfer = max_len; if (transfer > s->buf_used) transfer = s->buf_used; memcpy(&(dst_buf[*len]), s->buffer, transfer); max_len -= transfer; s->buf_pos += transfer; *len += transfer; } if (s->bytes_to_read == 0 && s->buf_pos == s->buf_used) do_cancel (s); DBG (10, ">>\n"); return (SANE_STATUS_GOOD); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte *dst_buf, SANE_Int max_len, SANE_Int * len) { NEC_Scanner *s = handle; SANE_Status status; DBG (10, "<< sane_read "); s->busy = SANE_TRUE; if (s->cancel == SANE_TRUE) { do_cancel(s); *len = 0; return (SANE_STATUS_CANCELLED); } if (s->image_composition <= 2) status = sane_read_direct(handle, dst_buf, max_len, len); else if (s->image_composition <= 4) status = sane_read_shuffled(handle, dst_buf, max_len, len, 0); else if (s->dev->sensedat.model == PCIN500) status = sane_read_direct(handle, dst_buf, max_len, len); else status = sane_read_shuffled(handle, dst_buf, max_len, len, 1); s->busy = SANE_FALSE; if (s->cancel == SANE_TRUE) { do_cancel(s); return (SANE_STATUS_CANCELLED); } DBG (10, ">> \n"); return (status); } void sane_cancel (SANE_Handle handle) { NEC_Scanner *s = handle; DBG (10, "<< sane_cancel "); s->cancel = SANE_TRUE; if (s->busy == SANE_FALSE) do_cancel(s); DBG (10, ">>\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { handle = handle; non_blocking = non_blocking; /* silence compilation warnings */ DBG (10, "<< sane_set_io_mode"); DBG (10, ">>\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { handle = handle; fd = fd; /* silence compilation warnings */ DBG (10, "<< sane_get_select_fd"); DBG (10, ">>\n"); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/gt68xx_high.h0000664000175000017500000003007112112021330015113 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov Copyright (C) 2002-2007 Henning Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GT68XX_HIGH_H #define GT68XX_HIGH_H #include "gt68xx_mid.h" typedef struct GT68xx_Calibrator GT68xx_Calibrator; typedef struct GT68xx_Calibration GT68xx_Calibration; typedef struct GT68xx_Scanner GT68xx_Scanner; /** Calibration data for one channel. */ struct GT68xx_Calibrator { unsigned int *k_white; /**< White point vector */ unsigned int *k_black; /**< Black point vector */ double *white_line; /**< White average */ double *black_line; /**< Black average */ SANE_Int width; /**< Image width */ SANE_Int white_level; /**< Desired white level */ SANE_Int white_count; /**< Number of white lines scanned */ SANE_Int black_count; /**< Number of black lines scanned */ #ifdef TUNE_CALIBRATOR SANE_Int min_clip_count; /**< Count of too low values */ SANE_Int max_clip_count; /**< Count of too high values */ #endif /* TUNE_CALIBRATOR */ }; /** Calibration data for a given resolution */ struct GT68xx_Calibration { SANE_Int dpi; /**< optical horizontal dpi used to build the calibration data */ SANE_Int pixel_x0; /**< x start position used at calibration time */ GT68xx_Calibrator *gray; /**< Calibrator for grayscale data */ GT68xx_Calibrator *red; /**< Calibrator for the red channel */ GT68xx_Calibrator *green; /**< Calibrator for the green channel */ GT68xx_Calibrator *blue; /**< Calibrator for the blue channel */ }; /** Create a new calibrator for one (color or mono) channel. * * @param width Image width in pixels. * @param white_level Desired white level (65535 max). * @param cal_return Returned pointer to the created calibrator object. * * @return * - SANE_STATUS_GOOD - the calibrator object was created. * - SANE_STATUS_INVAL - invalid parameters. * - SANE_STATUS_NO_MEM - not enough memory to create the object. */ static SANE_Status gt68xx_calibrator_new (SANE_Int width, SANE_Int white_level, GT68xx_Calibrator ** cal_return); /** Destroy the channel calibrator object. * * @param cal Calibrator object. */ static SANE_Status gt68xx_calibrator_free (GT68xx_Calibrator * cal); /** Add a white calibration line to the calibrator. * * This function should be called after scanning each white calibration line. * The line width must be equal to the value passed to gt68xx_calibrator_new(). * * @param cal Calibrator object. * @param line Pointer to the line data. * * @return * - #SANE_STATUS_GOOD - the line data was processed successfully. */ static SANE_Status gt68xx_calibrator_add_white_line (GT68xx_Calibrator * cal, unsigned int *line); /** Calculate the white point for the calibrator. * * This function should be called when all white calibration lines have been * scanned. After doing this, gt68xx_calibrator_add_white_line() should not be * called again for this calibrator. * * @param cal Calibrator object. * @param factor White point correction factor. * * @return * - #SANE_STATUS_GOOD - the white point was calculated successfully. */ static SANE_Status gt68xx_calibrator_eval_white (GT68xx_Calibrator * cal, double factor); /** Add a black calibration line to the calibrator. * * This function should be called after scanning each black calibration line. * The line width must be equal to the value passed to gt68xx_calibrator_new(). * * @param cal Calibrator object. * @param line Pointer to the line data. * * @return * - #SANE_STATUS_GOOD - the line data was processed successfully. */ static SANE_Status gt68xx_calibrator_add_black_line (GT68xx_Calibrator * cal, unsigned int *line); /** Calculate the black point for the calibrator. * * This function should be called when all black calibration lines have been * scanned. After doing this, gt68xx_calibrator_add_black_line() should not be * called again for this calibrator. * * @param cal Calibrator object. * @param factor Black point correction factor. * * @return * - #SANE_STATUS_GOOD - the white point was calculated successfully. */ static SANE_Status gt68xx_calibrator_eval_black (GT68xx_Calibrator * cal, double factor); /** Finish the calibrator setup and prepare for real scanning. * * This function must be called after gt68xx_calibrator_eval_white() and * gt68xx_calibrator_eval_black(). * * @param cal Calibrator object. * * @return * - #SANE_STATUS_GOOD - the calibrator setup completed successfully. */ static SANE_Status gt68xx_calibrator_finish_setup (GT68xx_Calibrator * cal); /** Process the image line through the calibrator. * * This function must be called only after gt68xx_calibrator_finish_setup(). * The image line is modified in place. * * @param cal Calibrator object. * @param line Pointer to the image line data. * * @return * - #SANE_STATUS_GOOD - the image line was processed successfully. */ static SANE_Status gt68xx_calibrator_process_line (GT68xx_Calibrator * cal, unsigned int *line); /** List of SANE options */ enum GT68xx_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_GRAY_MODE_COLOR, OPT_SOURCE, OPT_PREVIEW, OPT_BIT_DEPTH, OPT_RESOLUTION, OPT_LAMP_OFF_AT_EXIT, OPT_BACKTRACK, OPT_DEBUG_GROUP, OPT_AUTO_WARMUP, OPT_FULL_SCAN, OPT_COARSE_CAL, OPT_COARSE_CAL_ONCE, OPT_QUALITY_CAL, OPT_BACKTRACK_LINES, OPT_ENHANCEMENT_GROUP, OPT_GAMMA_VALUE, OPT_THRESHOLD, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_SENSOR_GROUP, OPT_NEED_CALIBRATION_SW, /* signals calibration is needed */ OPT_PAGE_LOADED_SW, /* signals that a document is inserted in feeder */ OPT_BUTTON_GROUP, OPT_CALIBRATE, /* button option to trigger call to sheetfed calibration */ OPT_CLEAR_CALIBRATION, /* clear calibration */ /* must come last: */ NUM_OPTIONS }; /** Scanner object. */ struct GT68xx_Scanner { struct GT68xx_Scanner *next; /**< Next scanner in list */ GT68xx_Device *dev; /**< Low-level device object */ GT68xx_Line_Reader *reader; /**< Line reader object */ GT68xx_Calibrator *cal_gray; /**< Calibrator for grayscale data */ GT68xx_Calibrator *cal_r; /**< Calibrator for the red channel */ GT68xx_Calibrator *cal_g; /**< Calibrator for the green channel */ GT68xx_Calibrator *cal_b; /**< Calibrator for the blue channel */ /* SANE data */ SANE_Bool scanning; /**< We are currently scanning */ SANE_Option_Descriptor opt[NUM_OPTIONS]; /**< Option descriptors */ Option_Value val[NUM_OPTIONS]; /**< Option values */ SANE_Parameters params; /**< SANE Parameters */ SANE_Int line; /**< Current line */ SANE_Int total_bytes; /**< Bytes already transmitted */ SANE_Int byte_count; /**< Bytes transmitted in this line */ SANE_Bool calib; /**< Apply calibration data */ SANE_Bool auto_afe; /**< Use automatic gain/offset */ SANE_Bool first_scan; /**< Is this the first scan? */ struct timeval lamp_on_time; /**< Time when the lamp was turned on */ struct timeval start_time; /**< Time when the scan was started */ SANE_Int bpp_list[5]; /**< */ SANE_Int *gamma_table; /**< Gray gamma table */ #ifdef DEBUG_BRIGHTNESS SANE_Int average_white; /**< For debugging brightness problems */ SANE_Int max_white; SANE_Int min_black; #endif /** SANE_TRUE when the scanner has been calibrated */ SANE_Bool calibrated; /** per horizontal resolution calibration data */ GT68xx_Calibration calibrations[MAX_RESOLUTIONS]; /* AFE and exposure settings */ GT68xx_AFE_Parameters afe_params; GT68xx_Exposure_Parameters exposure_params; }; /** Create a new scanner object. * * @param dev Low-level device object. * @param scanner_return Returned pointer to the created scanner object. */ static SANE_Status gt68xx_scanner_new (GT68xx_Device * dev, GT68xx_Scanner ** scanner_return); /** Destroy the scanner object. * * The low-level device object is not destroyed. * * @param scanner Scanner object. */ static SANE_Status gt68xx_scanner_free (GT68xx_Scanner * scanner); /** Calibrate the scanner before the main scan. * * @param scanner Scanner object. * @param request Scan request data. * @param use_autogain Enable automatic offset/gain control */ static SANE_Status gt68xx_scanner_calibrate (GT68xx_Scanner * scanner, GT68xx_Scan_Request * request); /** Start scanning the image. * * This function does not perform calibration - it needs to be performed before * by calling gt68xx_scanner_calibrate(). * * @param scanner Scanner object. * @param request Scan request data. * @param params Returned scan parameters (calculated from the request). */ static SANE_Status gt68xx_scanner_start_scan (GT68xx_Scanner * scanner, GT68xx_Scan_Request * request, GT68xx_Scan_Parameters * params); /** Read one image line from the scanner. * * This function can be called only during the scan - after calling * gt68xx_scanner_start_scan() and before calling gt68xx_scanner_stop_scan(). * * @param scanner Scanner object. * @param buffer_pointers Array of pointers to the image lines. */ static SANE_Status gt68xx_scanner_read_line (GT68xx_Scanner * scanner, unsigned int **buffer_pointers); /** Stop scanning the image. * * This function must be called to finish the scan started by * gt68xx_scanner_start_scan(). It may be called before all lines are read to * cancel the scan prematurely. * * @param scanner Scanner object. */ static SANE_Status gt68xx_scanner_stop_scan (GT68xx_Scanner * scanner); /** Save calibration data to file * * This function stores in memory calibration data created at calibration * time into file * @param scanner Scanner object. * @return SANE_STATUS_GOOD when succesfull */ static SANE_Status gt68xx_write_calibration (GT68xx_Scanner * scanner); /** Read calibration data from file * * This function sets in memory calibration data from data saved into file. * * @param scanner Scanner object. * @return SANE_STATUS_GOOD when succesfull */ static SANE_Status gt68xx_read_calibration (GT68xx_Scanner * scanner); #endif /* not GT68XX_HIGH_H */ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/u12-shading.c0000664000175000017500000006307312112021330014771 00000000000000/* @file u12-shading.c - * @brief all the shading functions * * based on sources acquired from Plustek Inc. * Copyright (C) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #define _GAIN_HIGH 240 /* Volt. max. value */ #define _GAIN_LOW 220 /* Volt. min. value */ #define _CHANNEL_RED 0 #define _CHANNEL_GREEN 1 #define _CHANNEL_BLUE 2 /* for DAC programming */ #define _VALUE_CONFIG 0x51 #define _DAC_RED (SANE_Byte)(_VALUE_CONFIG | 0x00) #define _DAC_GREENCOLOR (SANE_Byte)(_VALUE_CONFIG | 0x04) #define _DAC_GREENMONO (SANE_Byte)(_VALUE_CONFIG | 0x06) #define _DAC_BLUE (SANE_Byte)(_VALUE_CONFIG | 0x08) /* forward declarations ... */ static void u12tpa_Reshading( U12_Device * ); static void u12tpa_FindCenterPointer( U12_Device * ); /** */ static void u12shading_DownloadShadingTable( U12_Device *dev, SANE_Byte *buf, u_long len ) { SANE_Byte *val, *rb; SANE_Byte reg, regs[20]; int c; DBG( _DBG_INFO, "u12shading_DownloadShadingTable()\n" ); u12io_DataToRegister( dev, REG_MODECONTROL, _ModeShadingMem ); u12io_DataToRegister( dev, REG_MEMORYLO, 0 ); u12io_DataToRegister( dev, REG_MEMORYHI, 0 ); /* set 12 bits output color */ u12io_DataToRegister( dev, REG_SCANCONTROL, (SANE_Byte)(dev->regs.RD_ScanControl | _SCAN_12BITMODE)); u12io_MoveDataToScanner( dev, buf, len ); regs[0] = REG_MODECONTROL; regs[1] = _ModeScan; /* FillShadingDarkToShadingRegister() */ dev->regs.RD_RedDarkOff = dev->shade.DarkOffset.Colors.Red; dev->regs.RD_GreenDarkOff = dev->shade.DarkOffset.Colors.Green; dev->regs.RD_BlueDarkOff = dev->shade.DarkOffset.Colors.Blue; val = (SANE_Byte*)&dev->regs.RD_RedDarkOff; rb = ®s[2]; c = 1; for( reg = REG_REDCHDARKOFFSETLO; reg <= REG_BLUECHDARKOFFSETHI; reg++, val++) { *(rb++) = reg; *(rb++) = *val; c++; } u12io_DataToRegs( dev, regs, c ); } /** */ static SANE_Status u12shadingAdjustShadingWaveform( U12_Device *dev ) { SANE_Byte b; u_short count, wR, wG, wB, tmp; DataType var; DataPointer pvar, psum; RBGPtrDef cp; RGBUShortDef *pRGB, *pwsum; u_long shadingBytes; DBG( _DBG_INFO, "u12shading_AdjustShadingWaveForm()\n" ); memset( &cp, 0, sizeof(RBGPtrDef)); memset( dev->bufs.b2.pSumBuf, 0, (5400 * 3 * 2)); u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle ); dev->regs.RD_LineControl = _LOBYTE(dev->shade.wExposure); dev->regs.RD_ExtLineControl = _HIBYTE(dev->shade.wExposure); u12io_DataToRegister( dev, REG_EXTENDEDLINECONTROL, dev->regs.RD_ExtLineControl ); u12io_DataToRegister( dev, REG_LINECONTROL, dev->regs.RD_LineControl ); dev->regs.RD_XStepTime = _LOBYTE(dev->shade.wExposure); dev->regs.RD_ExtXStepTime = _HIBYTE(dev->shade.wExposure); u12io_DataToRegister( dev, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime ); u12io_DataToRegister( dev, REG_XSTEPTIME, dev->regs.RD_XStepTime ); dev->regs.RD_ModeControl = _ModeScan; dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; dev->regs.RD_Motor0Control = _FORWARD_MOTOR; if( dev->shade.intermediate & _ScanMode_AverageOut ) { dev->regs.RD_Dpi = 300; dev->regs.RD_Pixels = 2700; shadingBytes = 2700 * 2; } else { dev->regs.RD_Dpi = 600; dev->regs.RD_Pixels = 5400; shadingBytes = 5400 * 2; } dev->regs.RD_Origin = _SHADING_BEGINX; for( pvar.pdw = (u_long*)dev->scanStates, var.dwValue = _SCANSTATE_BYTES >> 2; var.dwValue--; pvar.pdw++) { *pvar.pdw = 0x00f00080; } dev->scan.refreshState = SANE_FALSE; u12io_PutOnAllRegisters( dev ); /* _DODELAY( 100 ); */ if( dev->shade.pHilight ) { memset( dev->shade.pHilight, 0, shadingBytes * dev->shade.skipHilight * 3 ); memset((SANE_Byte*)dev->shade.pHilight + shadingBytes * dev->shade.skipHilight * 3, 0xff, shadingBytes * dev->shade.skipShadow * 3 ); } for( count = 32; count--; ) { if( u12io_IsEscPressed()) { DBG( _DBG_INFO, "* CANCEL detected!\n" ); return SANE_STATUS_CANCELLED; } u12io_ReadOneShadingLine( dev, ((SANE_Byte*)dev->bufs.b1.pShadingRam)+ _SHADING_BEGINX, shadingBytes ); if( dev->shade.pHilight ) { if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { cp.red.usp = dev->bufs.b1.pShadingRam + _SHADING_BEGINX; cp.green.usp = cp.red.usp + dev->regs.RD_Pixels; cp.blue.usp = cp.green.usp + dev->regs.RD_Pixels; pvar.pusrgb = (RGBUShortDef*)dev->shade.pHilight + _SHADING_BEGINX; for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { pRGB = pvar.pusrgb++; wR = *cp.red.usp; wG = *cp.green.usp; wB = *cp.blue.usp; for( b = dev->shade.skipHilight; b--; pRGB += dev->regs.RD_Pixels ) { if( wR > pRGB->Red ) { tmp = wR; wR = pRGB->Red; pRGB->Red = tmp; } if( wG > pRGB->Green ) { tmp = wG; wG = pRGB->Green; pRGB->Green = tmp; } if( wB > pRGB->Blue ) { tmp = wB; wB = pRGB->Blue; pRGB->Blue = tmp; } } wR = *cp.red.usp++; wG = *cp.green.usp++; wB = *cp.blue.usp++; for( b = dev->shade.skipShadow; b--; pRGB += dev->regs.RD_Pixels ) { if( wR < pRGB->Red ) { tmp = wR; wR = pRGB->Red; pRGB->Red = tmp; } if( wG < pRGB->Green ) { tmp = wG; wG = pRGB->Green; pRGB->Green = tmp; } if( wB < pRGB->Blue ) { tmp = wB; wB = pRGB->Blue; pRGB->Blue = tmp; } } } } else { cp.green.usp = dev->bufs.b1.pShadingRam + dev->regs.RD_Pixels + _SHADING_BEGINX; cp.blue.usp = (u_short*)dev->shade.pHilight + _SHADING_BEGINX; for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { cp.red.usp = cp.blue.usp++; wG = *cp.green.usp; for( b = dev->shade.skipHilight; b--; cp.red.usp += dev->regs.RD_Pixels) { if( wG > *cp.red.usp ) { tmp = wG; wG = *cp.red.usp; *cp.red.usp = tmp; } } wG = *cp.green.usp++; for( b = dev->shade.skipShadow; b--; cp.red.usp += dev->regs.RD_Pixels ) { if( wG < *cp.red.usp ) { tmp = wG; wG = *cp.red.usp; *cp.red.usp = tmp; } } } } } /* AddToSumBuffer() */ if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { cp.red.usp = dev->bufs.b1.pShadingRam + _SHADING_BEGINX; cp.green.usp = cp.red.usp + dev->regs.RD_Pixels; cp.blue.usp = cp.green.usp + dev->regs.RD_Pixels; pvar.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = (u_long)dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--; pvar.pulrgb++, cp.red.usp++, cp.green.usp++, cp.blue.usp++) { pvar.pulrgb->Red += (u_long)*cp.red.usp; pvar.pulrgb->Green += (u_long)*cp.green.usp; pvar.pulrgb->Blue += (u_long)*cp.blue.usp; } } else { cp.green.usp = dev->bufs.b1.pShadingRam + dev->regs.RD_Pixels + _SHADING_BEGINX; pvar.pdw = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = (u_long)dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--; pvar.pdw++, cp.green.usp++) { *pvar.pdw += (u_long)*cp.green.usp; } } u12io_ResetFifoLen(); if( u12io_GetFifoLength( dev ) < dev->regs.RD_Pixels ) u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); } /* AverageAfterSubHilightShadow() */ if( dev->shade.pHilight ) { if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { psum.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; pvar.pusrgb = (RGBUShortDef*)dev->shade.pHilight + _SHADING_BEGINX; for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { pRGB = pvar.pusrgb++; for( b = dev->shade.skipHilight + dev->shade.skipShadow; b--; pRGB += dev->regs.RD_Pixels ) { psum.pulrgb->Red -= (u_long)pRGB->Red; psum.pulrgb->Green -= (u_long)pRGB->Green; psum.pulrgb->Blue -= (u_long)pRGB->Blue; } pwsum->Red = (u_short)(psum.pulrgb->Red / dev->shade.dwDiv); pwsum->Green = (u_short)(psum.pulrgb->Green / dev->shade.dwDiv); pwsum->Blue = (u_short)(psum.pulrgb->Blue / dev->shade.dwDiv); psum.pulrgb++; pwsum++; } } else { cp.green.ulp = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; cp.blue.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; pvar.pw = (u_short*)dev->shade.pHilight + _SHADING_BEGINX; for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { cp.red.usp = pvar.pw++; for( b = dev->shade.skipHilight + dev->shade.skipShadow; b--; cp.red.usp += dev->regs.RD_Pixels ) *cp.green.ulp -= *cp.red.usp; *cp.blue.usp = (u_short)(*cp.green.ulp / dev->shade.dwDiv); cp.blue.usp++; cp.green.ulp++; } } } else { if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { psum.pulrgb = (RGBULongDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { pwsum->Red = (u_short)(psum.pulrgb->Red >> 5); pwsum->Green = (u_short)(psum.pulrgb->Green >> 5); pwsum->Blue = (u_short)(psum.pulrgb->Blue >> 5); psum.pulrgb++; pwsum++; } } else { cp.green.ulp = (u_long*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; cp.blue.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { *cp.blue.usp = (u_short)(*cp.green.ulp >> 5); cp.blue.usp++; cp.green.ulp++; } } } /* Process negative & transparency here */ if( dev->DataInf.dwScanFlag & _SCANDEF_TPA ) u12tpa_FindCenterPointer( dev ); if( dev->DataInf.dwScanFlag & _SCANDEF_Negative ) u12tpa_Reshading( dev ); pRGB = (RGBUShortDef*)&dev->shade.pCcdDac->GainResize; if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { pwsum = (RGBUShortDef*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { if ((short)(pwsum->Red -= dev->shade.DarkOffset.Colors.Red) > 0) { pwsum->Red = pwsum->Red * pRGB->Red / 100U; if( pwsum->Red > 0xfff ) pwsum->Red = 0xfff; } else pwsum->Red = 0; if((short)(pwsum->Green -= dev->shade.DarkOffset.Colors.Green) > 0) { pwsum->Green = pwsum->Green * pRGB->Green / 100U; if( pwsum->Green > 0xfff ) pwsum->Green = 0xfff; } else pwsum->Green = 0; if ((short)(pwsum->Blue -= dev->shade.DarkOffset.Colors.Blue) > 0) { pwsum->Blue = pwsum->Blue * pRGB->Blue / 100U; if( pwsum->Blue > 0xfff ) pwsum->Blue = 0xfff; } else pwsum->Blue = 0; wR = (u_short)(pwsum->Red >> 4); pwsum->Red <<= 12; pwsum->Red |= wR; wR = (u_short)(pwsum->Green >> 4); pwsum->Green <<= 12; pwsum->Green |= wR; wR = (u_short)(pwsum->Blue>> 4); pwsum->Blue <<= 12; pwsum->Blue |= wR; pwsum++; } } else { cp.green.usp = (u_short*)dev->bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = dev->regs.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { if((short)(*cp.green.usp -= dev->shade.DarkOffset.Colors.Green) > 0) { *cp.green.usp = *cp.green.usp * pRGB->Green / 100U; if( *cp.green.usp > 0xfff ) *cp.green.usp = 0xfff; } else *cp.green.usp = 0; wR = (u_short)(*cp.green.usp >> 4); *cp.green.usp <<= 12; *cp.green.usp |= wR; cp.green.usp++; } } u12shading_DownloadShadingTable(dev, dev->bufs.b2.pSumBuf, (5400 * 3 * 2)); return SANE_STATUS_GOOD; } /** */ static void u12shading_GainOffsetToDAC( U12_Device *dev, SANE_Byte ch, SANE_Byte reg, SANE_Byte d ) { if( dev->DACType == _DA_SAMSUNG8531 ) { u12io_DataRegisterToDAC( dev, 0, ch ); } u12io_DataRegisterToDAC( dev, reg, d ); } /** */ static void u12shading_FillToDAC( U12_Device *dev, RGBByteDef *regs, ColorByte *data ) { if( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { u12shading_GainOffsetToDAC(dev, _DAC_RED, regs->Red, data->Colors.Red); u12shading_GainOffsetToDAC(dev, _DAC_GREENCOLOR, regs->Green, data->Colors.Green); u12shading_GainOffsetToDAC(dev, _DAC_BLUE, regs->Blue, data->Colors.Blue); } else { u12shading_GainOffsetToDAC(dev, _DAC_GREENMONO, regs->Green, data->Colors.Green); } } /** */ static SANE_Byte u12shading_SumGains( SANE_Byte *pb, u_long pixelsLine ) { SANE_Byte hilight, tmp; u_long dwPixels, dwAve; u_short sum; hilight = 0; for( dwPixels = pixelsLine >> 4; dwPixels--; ) { for( sum = 0, dwAve = 16; dwAve--; pb++ ) sum += (u_short)*pb; sum >>= 4; tmp = (SANE_Byte)sum; if( tmp > hilight ) hilight = tmp; } return hilight; } /** */ static void u12shading_AdjustGain( U12_Device *dev, u_long color, SANE_Byte hilight ) { if( hilight < dev->shade.bGainLow ) { if( dev->shade.Hilight.bColors[color] < dev->shade.bGainHigh ) { dev->shade.fStop = SANE_FALSE; dev->shade.Hilight.bColors[color] = hilight; if( hilight <= (SANE_Byte)(dev->shade.bGainLow - hilight)) dev->shade.Gain.bColors[color] += dev->shade.bGainDouble; else dev->shade.Gain.bColors[color]++; } } else { if( hilight > dev->shade.bGainHigh ) { dev->shade.fStop = SANE_FALSE; dev->shade.Hilight.bColors[color] = hilight; dev->shade.Gain.bColors[color]--; } else { dev->shade.Hilight.bColors[color] = hilight; } } if( dev->shade.Gain.bColors[color] > dev->shade.bMaxGain ) { dev->shade.Gain.bColors[color] = dev->shade.bMaxGain; } } /** */ static SANE_Status u12shading_AdjustRGBGain( U12_Device *dev ) { int i; SANE_Byte hi[3]; DBG( _DBG_INFO, "u12shading_AdjustRGBGain()\n" ); dev->shade.Gain.Colors.Red = dev->shade.Gain.Colors.Green = dev->shade.Gain.Colors.Blue = dev->shade.bUniGain; dev->shade.Hilight.Colors.Red = dev->shade.Hilight.Colors.Green = dev->shade.Hilight.Colors.Blue = 0; dev->shade.bGainHigh = _GAIN_HIGH; dev->shade.bGainLow = _GAIN_LOW; dev->shade.fStop = SANE_FALSE; for( i = 10; i-- && !dev->shade.fStop; ) { if( u12io_IsEscPressed()) { DBG( _DBG_INFO, "* CANCEL detected!\n" ); return SANE_STATUS_CANCELLED; } dev->shade.fStop = SANE_TRUE; u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle ); dev->regs.RD_ScanControl = _SCAN_BYTEMODE; u12hw_SelectLampSource( dev ); u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl ); u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain ); dev->regs.RD_ModeControl = _ModeScan; dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; dev->regs.RD_Motor0Control = _FORWARD_MOTOR; if( dev->shade.intermediate & _ScanMode_AverageOut ) dev->regs.RD_Origin = (u_short)_DATA_ORIGIN_X >> 1; else dev->regs.RD_Origin = (u_short)_DATA_ORIGIN_X; dev->regs.RD_Dpi = 300; dev->regs.RD_Pixels = 2560; memset( dev->scanStates, 0, _SCANSTATE_BYTES ); dev->scanStates[1] = 0x77; u12io_PutOnAllRegisters( dev ); /* _DODELAY( 100 ); */ /* read one shading line and work on it */ if( u12io_ReadOneShadingLine( dev, (SANE_Byte*)dev->bufs.b1.pShadingRam, 2560)) { if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { hi[1] = u12shading_SumGains( (SANE_Byte*)dev->bufs.b1.pShadingRam + 2560, 2560); if( hi[1] ) { u12shading_AdjustGain( dev, _CHANNEL_GREEN, hi[1] ); } else { dev->shade.fStop = SANE_FALSE; } } else { hi[0] = u12shading_SumGains( (SANE_Byte*)dev->bufs.b1.pShadingRam, 2560); hi[1] = u12shading_SumGains( (SANE_Byte*)dev->bufs.b1.pShadingRam + 2560, 2560); hi[2] = u12shading_SumGains( (SANE_Byte*)dev->bufs.b1.pShadingRam + 5120, 2560); if (!hi[0] || !hi[1] || !hi[2] ) { dev->shade.fStop = SANE_FALSE; } else { u12shading_AdjustGain( dev, _CHANNEL_RED, hi[0] ); u12shading_AdjustGain( dev, _CHANNEL_GREEN, hi[1] ); u12shading_AdjustGain( dev, _CHANNEL_BLUE, hi[2] ); } } } else dev->shade.fStop = SANE_FALSE; } if( !dev->shade.fStop ) DBG( _DBG_INFO, "u12shading_AdjustRGBGain() - all loops done!!!\n" ); u12shading_FillToDAC( dev, &dev->RegDACGain, &dev->shade.Gain ); return SANE_STATUS_GOOD; } /** */ static u_short u12shading_SumDarks( U12_Device *dev, u_short *data ) { u_short i, loop; if( dev->CCDID == _CCD_3799 ) { if( dev->shade.intermediate & _ScanMode_AverageOut ) data += 0x18; else data += 0x30; } else { if( dev->shade.intermediate & _ScanMode_AverageOut ) data += 0x18; else data += 0x20; } for( i = 0, loop = 16; loop--; data++ ) i += *data; i >>= 4; return i; } /** */ static SANE_Status u12shadingAdjustDark( U12_Device *dev ) { u_long i; u_short wDarks[3]; DBG( _DBG_INFO, "u12shadingAdjustDark()\n" ); dev->shade.DarkDAC.Colors = dev->shade.pCcdDac->DarkDAC.Colors; dev->shade.fStop = SANE_FALSE; for( i = 16; i-- && !dev->shade.fStop;) { if( u12io_IsEscPressed()) { DBG( _DBG_INFO, "* CANCEL detected!\n" ); return SANE_STATUS_CANCELLED; } dev->shade.fStop = SANE_TRUE; u12shading_FillToDAC( dev, &dev->RegDACOffset, &dev->shade.DarkDAC ); u12io_DataToRegister( dev, REG_MODECONTROL, _ModeIdle ); dev->regs.RD_ScanControl = (_SCAN_12BITMODE + _SCAN_1ST_AVERAGE); u12hw_SelectLampSource( dev ); u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl ); dev->regs.RD_StepControl = _MOTOR0_SCANSTATE; dev->regs.RD_Motor0Control = _FORWARD_MOTOR; dev->regs.RD_Origin = _SHADING_BEGINX; dev->regs.RD_Pixels = 512; if( dev->shade.intermediate & _ScanMode_AverageOut ) dev->regs.RD_Dpi = 300; else dev->regs.RD_Dpi = 600; memset( dev->scanStates, 0, _SCANSTATE_BYTES ); dev->scanStates[1] = 0x77; u12io_PutOnAllRegisters( dev ); /* _DODELAY( 100 ); */ /* read one shading line and work on it */ if( u12io_ReadOneShadingLine(dev, (SANE_Byte*)dev->bufs.b1.pShadingRam, 512*2)) { if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { wDarks[0] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam); wDarks[1] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam + dev->regs.RD_Pixels ); wDarks[2] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam + dev->regs.RD_Pixels * 2UL); if( !wDarks[0] || !wDarks[1] || !wDarks[2] ) { dev->shade.fStop = SANE_FALSE; } else { dev->shade.DarkOffset.wColors[0] = wDarks[0]; dev->shade.DarkOffset.wColors[1] = wDarks[1]; dev->shade.DarkOffset.wColors[2] = wDarks[2]; (*dev->fnDACDark)( dev,dev->shade.pCcdDac, _CHANNEL_RED, wDarks[0] ); (*dev->fnDACDark)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN, wDarks[1] ); (*dev->fnDACDark)( dev, dev->shade.pCcdDac, _CHANNEL_BLUE, wDarks[2] ); } } else { wDarks[1] = u12shading_SumDarks(dev, dev->bufs.b1.pShadingRam + dev->regs.RD_Pixels ); if(!wDarks[1] ) { dev->shade.fStop = SANE_FALSE; } else { dev->shade.DarkOffset.wColors[1] = wDarks[1]; (*dev->fnDACDark)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN, wDarks[1] ); } } } else { dev->shade.fStop = SANE_FALSE; } } /* CalculateDarkDependOnCCD() */ if ( dev->DataInf.wPhyDataType > COLOR_256GRAY ) { (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_RED ); (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN ); (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_BLUE ); } else { (*dev->fnDarkOffset)( dev, dev->shade.pCcdDac, _CHANNEL_GREEN ); } return SANE_STATUS_GOOD; } /** here we download the current mapping table */ static void u12shading_DownloadMapTable( U12_Device *dev, SANE_Byte *buf ) { SANE_Byte addr, regs[6]; int i; u12io_DataToRegister( dev, REG_SCANCONTROL, (SANE_Byte)((dev->regs.RD_ScanControl & 0xfc) | _SCAN_BYTEMODE)); /* prepare register settings... */ regs[0] = REG_MODECONTROL; regs[1] = _ModeMappingMem; regs[2] = REG_MEMORYLO; regs[3] = 0; regs[4] = REG_MEMORYHI; for( i = 3, addr = _MAP_ADDR_RED; i--; addr += _MAP_ADDR_SIZE ) { regs[5] = addr; u12io_DataToRegs( dev, regs, 3 ); u12io_MoveDataToScanner( dev, buf, 4096 ); buf += 4096; } u12io_DataToRegister( dev, REG_SCANCONTROL, dev->regs.RD_ScanControl ); } /** */ static SANE_Status u12shading_DoCalibration( U12_Device *dev ) { SANE_Byte tb[4096*3]; u_long i, tmp; SANE_Byte bScanControl, rb[20]; SANE_Status res; int c; DBG( _DBG_INFO, "u12shading_DoCalibration()\n" ); /** before getting the shading data, (re)init the ASIC */ u12hw_InitAsic( dev, SANE_TRUE ); dev->shade.DarkOffset.Colors.Red = 0; dev->shade.DarkOffset.Colors.Green = 0; dev->shade.DarkOffset.Colors.Blue = 0; c = 0; _SET_REG( rb, c, REG_RESETMTSC, 0 ); _SET_REG( rb, c, REG_MODELCONTROL, dev->regs.RD_ModelControl); _SET_REG( rb, c, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType ); _SET_REG( rb, c, REG_SCANCONTROL1, (_SCANSTOPONBUFFULL| _MFRC_BY_XSTEP)); u12io_DataToRegs( dev, rb, c ); res = u12motor_GotoShadingPosition( dev ); if( SANE_STATUS_GOOD != res ) return res; bScanControl = dev->regs.RD_ScanControl; /* SetShadingMapForGainDark */ memset( dev->bufs.b2.pSumBuf, 0xff, (5400 * 3 * 2)); u12shading_DownloadShadingTable( dev, dev->bufs.b2.pSumBuf, (5400*3*2)); for( i = 0, tmp = 0; i < 1024; tmp += 0x01010101, i += 4 ) { dev->bufs.b1.Buf.pdw[i] = dev->bufs.b1.Buf.pdw[i+1] = dev->bufs.b1.Buf.pdw[i+2] = dev->bufs.b1.Buf.pdw[i+3] = tmp; } memcpy( dev->bufs.b1.pShadingMap + 4096, dev->bufs.b1.pShadingMap, 4096 ); memcpy( dev->bufs.b1.pShadingMap + 8192, dev->bufs.b1.pShadingMap, 4096 ); u12shading_DownloadMapTable( dev, dev->bufs.b1.pShadingMap ); DBG( _DBG_INFO, "* wExposure = %u\n", dev->shade.wExposure); DBG( _DBG_INFO, "* wXStep = %u\n", dev->shade.wXStep); dev->regs.RD_LineControl = (_LOBYTE(dev->shade.wExposure)); dev->regs.RD_ExtLineControl = (_HIBYTE(dev->shade.wExposure)); u12io_DataToRegister( dev, REG_EXTENDEDLINECONTROL, dev->regs.RD_ExtLineControl ); u12io_DataToRegister( dev, REG_LINECONTROL, dev->regs.RD_LineControl ); res = u12shading_AdjustRGBGain( dev ); if( SANE_STATUS_GOOD != res ) return res; res = u12shadingAdjustDark( dev ); if( SANE_STATUS_GOOD != res ) return res; res = u12shadingAdjustShadingWaveform( dev ); if( SANE_STATUS_GOOD != res ) return res; dev->regs.RD_ScanControl = bScanControl; /* here we have to prepare and download the table in any case...*/ if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { u12map_Adjust( dev, _MAP_MASTER, tb ); } else { u12map_Adjust( dev, _MAP_RED, tb ); u12map_Adjust( dev, _MAP_GREEN, tb ); u12map_Adjust( dev, _MAP_BLUE, tb ); } u12shading_DownloadMapTable( dev, tb ); u12motor_BackToHomeSensor( dev ); DBG( _DBG_INFO, "u12shading_DoCalibration() - done.\n" ); return SANE_STATUS_GOOD; } /* END U12-SHADING ..........................................................*/ sane-backends-1.0.27/backend/artec_eplus48u.conf.in0000664000175000017500000001004412112021330016714 00000000000000# artec_eplus48u - SANE Backend configuration file # This section is for use with the Artec E+ 48U scanner # This scanner is also sold as # Tevion MD 9693, Medion MD 9705, Medion MD 9693, Medion MD4394 # This sections contains verbose description of each option. # For other scanners, see below. # # The USB section: # each device needs at least the following line: # usb vendor-ID and product-ID # Every device configuration in this file must begin with an usb entry. usb 0x05d8 0x4003 # Path to the firmware file # This file comes with the Windows driver # The scanner won't work without it option artecFirmwareFile @DATADIR@/sane/artec_eplus48u/Artec48.usb # Is the scanner an Artec E Plus Pro (or compatible)? 0 = no, 1 = yes option ePlusPro 0 # for adjusting the default gamma values option redGamma 1.0 option greenGamma 1.0 option blueGamma 1.0 option masterGamma 1.9 #Use this options to set the default offset and exposure time values. option redOffset 0x28 option greenOffset 0x2f option blueOffset 0x2f option redExposure 0xa7 option greenExposure 0x116 option blueExposure 0xdc # The vendor and model string # This string is displayed by the frontends. If you do not want to get your # scanner reported as "Artec E+ 48U", then change the option accordingly. option vendorString "Artec" option modelString "E+ 48U" # device-name # # If autodetection does not work, then you can specify the device here # The device entry must be the last one in this config file (or the last one before a # new usb entry). #If you are using libusb, a device looks like this: #device libusb:001:002 #If you are using the scanner module (kernel driver), a device looks like this: #device /dev/usbscanner # ---------------------------------------------------------------------------- # Since the Trust Easy Webscan 19200 uses a different product id, we add # another usb section here. usb 0x05d8 0x4006 option artecFirmwareFile @DATADIR@/sane/artec_eplus48u/Artec48.usb option vendorString "Trust" option modelString "Easy Webscan 19200" # ---------------------------------------------------------------------------- # Since the Memorex Mem48U uses a different product id, we add # another usb section here. usb 0x05d8 0x4005 option artecFirmwareFile @DATADIR@/sane/artec_eplus48u/Artec48.usb option vendorString "Memorex" option modelString "MEM 48U" # ---------------------------------------------------------------------------- # Since the Trust 240H Easy Webscan Gold uses a different product id, we add # another usb section here. usb 0x05d8 0x4007 option artecFirmwareFile @DATADIR@/sane/artec_eplus48u/Artec48.usb option ePlusPro 1 option vendorString "Trust" option modelString "240H Easy Webscan Gold" # ---------------------------------------------------------------------------- # Since the UMAX AstraSlim SE uses a different product id, we add # another usb section here. usb 0x05d8 0x4009 option artecFirmwareFile @DATADIR@/sane/artec_eplus48u/Artec48.usb option vendorString "UMAX" option modelString "AstraSlim SE" # ---------------------------------------------------------------------------- # This section is for the Artec E+ Pro # Note, that the name of the firmware file is called 1200.usb for # this device usb 0x05d8 0x4004 option artecFirmwareFile @DATADIR@/sane/artec_eplus48u/1200.usb option ePlusPro 1 option vendorString "Artec" option modelString "E+ Pro" # ---------------------------------------------------------------------------- # This section is for the UMAX AstraSlim 1200 SE # Note, that the name of the firmware file is called 1200.usb for # this device usb 0x05d8 0x4010 option artecFirmwareFile @DATADIR@/sane/artec_eplus48u/1200.usb option vendorString "UMAX" option modelString "AstraSlim 1200 SE" # ---------------------------------------------------------------------------- # Since the Yakumo Scan50 uses a different product id, we add # another usb section here. usb 0x05d8 0x4011 option artecFirmwareFile @DATADIR@/sane/artec_eplus48u/Artec48.usb option vendorString "Yakumo" option modelString "Scan50" sane-backends-1.0.27/backend/agfafocus.h0000664000175000017500000000607612112021330014712 00000000000000/* sane - Scanner Access Now Easy. This file (C) 1997 Ingo Schneider (C) 1998 Karl Anders Øygard This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef agfafocus_h #define agfafocus_h enum AgfaFocus_Scanner_Type { AGFAGRAY64, AGFALINEART, AGFAGRAY256, AGFACOLOR }; typedef enum { LINEART, GRAY6BIT, GRAY8BIT, COLOR18BIT, COLOR24BIT } AgfaFocus_Scanner_Mode; enum AgfaFocus_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_HALFTONE_PATTERN, /* halftone matrix */ OPT_RESOLUTION, OPT_SOURCE, OPT_QUALITY, /* quality calibration */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_EXPOSURE, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_AUTO_BRIGHTNESS, OPT_AUTO_CONTRAST, OPT_ATTENUATION_RED, OPT_ATTENUATION_BLUE, OPT_ATTENUATION_GREEN, OPT_SHARPEN, /* sharpening */ /* must come last: */ NUM_OPTIONS }; typedef struct AgfaFocus_Device { struct AgfaFocus_Device *next; SANE_Device sane; SANE_Handle handle; SANE_Word type; SANE_Bool transparent; SANE_Bool analoglog; SANE_Bool tos5; SANE_Bool quality; SANE_Bool disconnect; SANE_Bool upload_user_defines; } AgfaFocus_Device; typedef struct AgfaFocus_Scanner { /* all the state needed to define a scan request: */ SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; /* Parsed option values and variables that are valid only during actual scanning: */ SANE_Bool scanning; SANE_Int pass; SANE_Parameters params; AgfaFocus_Scanner_Mode mode; SANE_Int image_composition; SANE_Int bpp; SANE_Int halftone; SANE_Int original; SANE_Int exposure; SANE_Int r_att; SANE_Int g_att; SANE_Int b_att; SANE_Int tonecurve; SANE_Int quality; SANE_Bool edge; SANE_Bool lin_log; int lines_available; /* Lines in scanner memory */ int fd; /* SCSI filedescriptor */ SANE_Pid reader_pid; /* process id of reader */ int pipe; /* pipe to reader process */ int reader_pipe; /* pipe from reader process */ /* scanner dependent/low-level state: */ AgfaFocus_Device *hw; } AgfaFocus_Scanner; #endif /* agfafocus_h */ sane-backends-1.0.27/backend/agfafocus.c0000664000175000017500000015516312775312260014733 00000000000000/* sane - Scanner Access Now Easy. This file (C) 1997 Ingo Schneider (C) 1998 Karl Anders Øygard This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. This file implements a SANE backend for AGFA Focus flatbed scanners. */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_thread.h" #define BACKEND_NAME agfafocus #include "../include/sane/sanei_backend.h" #include "agfafocus.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #undef Byte #define Byte SANE_Byte static const SANE_Device **devlist = 0; static int num_devices; static AgfaFocus_Device *agfafocus_devices; static const SANE_String_Const focus_mode_list[] = { "Lineart", "Gray (6 bit)", 0 }; static const SANE_String_Const focusii_mode_list[] = { "Lineart", "Gray (6 bit)", "Gray (8 bit)", 0 }; static const SANE_String_Const focuscolor_mode_list[] = { "Lineart", "Gray (6 bit)", "Gray (8 bit)", "Color (18 bit)", "Color (24 bit)", 0 }; static const SANE_String_Const halftone_list[] = { "None", "Dispersed dot 4x4", "Round (Clustered dot 4x4)", "Diamond (Clustered dot 4x4)", 0 }; static const SANE_String_Const halftone_upload_list[] = { "None", "Dispersed dot 4x4", "Round (Clustered dot 4x4)", "Diamond (Clustered dot 4x4)", 0 }; static const SANE_String_Const source_list[] = { "Opaque/Normal", "Transparency", 0 }; static const SANE_String_Const quality_list[] = { "Low", "Normal", "High", 0 }; static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; DBG (11, ">> max_string_size\n"); for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } DBG (11, "<< max_string_size\n"); return max_size; } /* sets loc_s bytes long value at offset loc in scsi command to value size */ static void set_size (Byte * loc, int loc_s, size_t size) { int i; for (i = 0; i < loc_s; i++) { loc[loc_s - i - 1] = (size >> (i * 8)) & 0xff; } } /* gets loc_s bytes long value from loc in scsi command */ static int get_size (Byte * loc, int loc_s) { int i; int j = 0; for (i = 0; i < loc_s; i++) { j = (j << 8) + (loc[i] & 0xff); } return j; } static long reserve_unit (int fd) { struct { /* Command */ Byte cmd; Byte lun; Byte res[2]; Byte tr_len; Byte ctrl; } scsi_reserve; memset (&scsi_reserve, 0, sizeof (scsi_reserve)); scsi_reserve.cmd = 0x16; /* RELEASE */ DBG (3, "reserve_unit()\n"); return sanei_scsi_cmd (fd, &scsi_reserve, sizeof (scsi_reserve), 0, 0); } static long release_unit (int fd) { struct { /* Command */ Byte cmd; Byte lun; Byte res[2]; Byte tr_len; Byte ctrl; } scsi_release; memset (&scsi_release, 0, sizeof (scsi_release)); scsi_release.cmd = 0x17; /* RELEASE */ DBG (3, "release_unit()\n"); return sanei_scsi_cmd (fd, &scsi_release, sizeof (scsi_release), 0, 0); } static SANE_Status test_ready (int fd) { SANE_Status status; int try; struct { /* Command */ Byte cmd; Byte lun; Byte res[2]; Byte tr_len; Byte ctrl; } scsi_test_ready; memset (&scsi_test_ready, 0, sizeof (scsi_test_ready)); scsi_test_ready.cmd = 0x00; /* TEST UNIT READY */ for (try = 0; try < 1000; ++try) { DBG (3, "test_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, &scsi_test_ready, sizeof (scsi_test_ready), 0, 0); switch (status) { case SANE_STATUS_DEVICE_BUSY: usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; default: DBG (1, "test_ready: test unit ready failed (%s)\n", sane_strstatus (status)); return status; } } DBG (1, "test_ready: timed out after %d attempts\n", try); return SANE_STATUS_IO_ERROR; } static SANE_Status sense_handler (int scsi_fd, u_char *result, void *arg) { scsi_fd = scsi_fd; /* silence gcc */ arg = arg; /* silence gcc */ if (result[0]) { DBG (0, "sense_handler() : sense code = %02x\n", result[0]); return SANE_STATUS_IO_ERROR; } else { return SANE_STATUS_GOOD; } } static SANE_Status stop_scan (int fd) { fd = fd; /* silence gcc */ /* XXX don't know how to stop the scanner. To be tested ! */ #if 0 const Byte scsi_rewind[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; DBG (1, "Trying to stop scanner...\n"); return sanei_scsi_cmd (fd, scsi_rewind, sizeof (scsi_rewind), 0, 0); #else return SANE_STATUS_GOOD; #endif } static SANE_Status start_scan (int fd, SANE_Bool cont) { struct { /* Command */ Byte cmd; Byte lun; Byte res[2]; Byte tr_len; Byte ctrl; /* Data */ Byte wid; } scsi_start_scan; memset (&scsi_start_scan, 0, sizeof (scsi_start_scan)); scsi_start_scan.cmd = 0x1b; /* SCAN */ scsi_start_scan.tr_len = 1; scsi_start_scan.wid = 0; scsi_start_scan.ctrl = (cont == SANE_TRUE) ? 0x80 : 0x00; DBG (1, "Starting scanner ...\n"); return sanei_scsi_cmd (fd, &scsi_start_scan, sizeof (scsi_start_scan), 0, 0); } static void wait_ready (int fd) { struct { Byte bytes[2]; /* Total # of bytes */ Byte scan[2]; /* ms to complete - driver sleep time */ } result; size_t size = sizeof (result); SANE_Status status; struct { Byte cmd; Byte lun; Byte data_type; Byte re1[3]; Byte tr_len[3]; Byte ctrl; } cmd; memset (&cmd, 0, sizeof (cmd)); cmd.cmd = 0x28; /* READ */ cmd.data_type = 0x80; /* get scan time */ set_size (cmd.tr_len, 3, sizeof (result)); while (1) { status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &result, &size); if (status != SANE_STATUS_GOOD || size != sizeof (result)) { /* Command failed, the assembler code of the windows scan library ignores this condition, and so do I */ break; } else { /* left is the amount of seconds left till the scanner is ready * 100 */ int left = get_size (result.scan, 2); DBG (1, "wait_ready() : %d left...\n", left); if (!left) break; /* We delay only for half the given time */ else if (left < 200) usleep (left * 5000); else sleep (left / 200); } } return; } static SANE_Status get_read_sizes (int fd, int *lines_available, int *bpl, int *total_lines) { struct { Byte reserved1[8]; Byte line_width[2]; Byte total_lines[2]; Byte cur_line[2]; Byte lines_this_block[2]; Byte reserved[8]; } read_sizes; const Byte scsi_read[] = { 0x28, 0x00, /* opcode, lun */ 0x81, /* data type 81 == read time left */ 0x00, 0x00, 0x00, /* reserved */ 0x00, 0x00, sizeof (read_sizes), /* transfer length */ 0x00, /* control byte */ }; size_t size = sizeof (read_sizes); SANE_Status status; status = sanei_scsi_cmd (fd, scsi_read, sizeof (scsi_read), &read_sizes, &size); if (status != SANE_STATUS_GOOD || size != sizeof (read_sizes)) { /* Command failed */ return SANE_STATUS_IO_ERROR; } else { *lines_available = get_size (read_sizes.lines_this_block, 2); *bpl = get_size (read_sizes.cur_line, 2); if (total_lines) *total_lines = get_size (read_sizes.total_lines, 2); } DBG (1, "get_read_sizes() : %d of %d, %d\n", *lines_available, total_lines ? *total_lines : -1, *bpl); return SANE_STATUS_GOOD; } static SANE_Status set_window (AgfaFocus_Scanner * s) /* This function sets and sends the window for scanning */ { double pixels_per_mm = (double) s->val[OPT_RESOLUTION].w / MM_PER_INCH; SANE_Bool auto_bright = s->val[OPT_AUTO_BRIGHTNESS].b; SANE_Bool auto_contr = s->val[OPT_AUTO_CONTRAST].b; /* ranges down 255 (dark) down to 1(bright) */ int brightness = auto_bright ? 0 : (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w) * -1.27 + 128.5); /* ranges from 1 (little contrast) up to 255 (much contrast) */ int contrast = auto_contr ? 0 : (SANE_UNFIX (s->val[OPT_CONTRAST].w) * 1.27 + 128.5); int width; /* ranges from 40 (dark) down to 0 (bright) */ int bright_adjust = (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w) * -20.0) / 100.0 + 20.0; /* ranges from 20 (little contrast) down to -20 = 235 (much contrast) */ int contr_adjust = (SANE_UNFIX (s->val[OPT_CONTRAST].w) * -20.0) / 100.0; /* Warning ! The following structur SEEMS to be a valid SCSI-2 SET_WINDOW command. But e.g. the limits for the window are only 2 Bytes instead of 4. The scanner was built at about 1990, so SCSI-2 wasn't available for development... */ struct { Byte cmd; Byte lun; Byte re1[4]; Byte tr_len[3]; Byte ctrl; Byte re2[6]; Byte wd_len[2]; struct { Byte wid; /* Window ID */ Byte autobit; /* Window creation */ Byte x_axis_res[2]; /* X resolution */ Byte y_axis_res[2]; /* X resolution */ Byte x_axis_ul[2]; /* X upper left */ Byte y_axis_ul[2]; /* Y upper left */ Byte wwidth[2]; /* Width */ Byte wlength[2]; /* Length */ Byte contrast; /* Contrast */ Byte dummy1; Byte intensity; /* Intensity */ Byte image_comp; /* Image composition (0, 2, 5) */ Byte bpp; /* Bits per pixel */ Byte tonecurve; /* Tone curve (0 - 8) */ Byte ht_pattern; /* Halftone pattern */ Byte paddingtype; /* Padding type */ Byte bitordering[2]; /* Bit ordering (0 = left to right) */ Byte comprtype; /* Compression type */ Byte comprarg; /* Compression argument */ Byte dummy2[6]; Byte edge; /* Sharpening (0 - 7) */ Byte dummy3; Byte bright_adjust; /* */ Byte contr_adjust; /* */ Byte imagewidthtruncation; /* */ Byte dummy4; Byte quality_type; /* 0 normal, 1 high, 255 low */ Byte red_att; Byte green_att; Byte blue_att; Byte dummy5[5]; Byte color_planes; Byte orig_type; Byte fixturetype; Byte exposure[2]; Byte defocus[2]; Byte dummy6[4]; Byte descreen_factor; Byte packing_word_length; Byte packing_number_of_pixels; Byte packing_color_mode; Byte strokenab; Byte rotatenab; Byte autostrokenab; Byte dummy7; } wd; } cmd; memset (&cmd, 0, sizeof (cmd)); cmd.cmd = 0x24; /* SET WINDOW PARAMETERS */ switch (s->hw->type) { case AGFAGRAY64: case AGFALINEART: case AGFAGRAY256: set_size (cmd.tr_len, 3, 36 + 8); set_size (cmd.wd_len, 2, 36); break; case AGFACOLOR: set_size (cmd.tr_len, 3, 65 + 8); set_size (cmd.wd_len, 2, 65); break; } /* Resolution. Original comment in German: Aufloesung */ set_size (cmd.wd.x_axis_res, 2, s->val[OPT_RESOLUTION].w); set_size (cmd.wd.y_axis_res, 2, s->val[OPT_RESOLUTION].w); /* Scan window position/size. Original comment in German: Fensterposition / Groesse */ set_size (cmd.wd.x_axis_ul, 2, SANE_UNFIX (s->val[OPT_TL_X].w) * pixels_per_mm + 0.5); set_size (cmd.wd.y_axis_ul, 2, SANE_UNFIX (s->val[OPT_TL_Y].w) * pixels_per_mm + 0.5); width = (SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * pixels_per_mm) + 0.5; if (s->bpp == 1 && width % 8) width += 8 - width % 8; set_size (cmd.wd.wwidth, 2, width); set_size (cmd.wd.wlength, 2, SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) * pixels_per_mm + 0.5); cmd.wd.bpp = s->bpp; if (s->mode == COLOR18BIT || s->mode == COLOR24BIT) { cmd.wd.paddingtype = 3; cmd.wd.ht_pattern = 3; cmd.wd.red_att = s->r_att; cmd.wd.blue_att = s->g_att; cmd.wd.green_att = s->b_att; cmd.wd.color_planes = 0x0e; set_size (cmd.wd.exposure, 2, s->exposure); cmd.wd.packing_word_length = 1; cmd.wd.packing_number_of_pixels = 1; cmd.wd.packing_color_mode = 2; if (s->bpp == 6) cmd.wd.edge = s->edge; DBG (3, "Setting parameters: imc %d, bpp %d, res %d, exp %d, attenuation [%d, %d, %d], edge %d\n", s->image_composition, s->bpp, s->val[OPT_RESOLUTION].w, s->exposure, cmd.wd.red_att, cmd.wd.blue_att, cmd.wd.green_att, s->edge); } else { if (s->bpp == 1) cmd.wd.ht_pattern = s->halftone; else cmd.wd.ht_pattern = 3; cmd.wd.intensity = brightness; cmd.wd.contrast = contrast; cmd.wd.contr_adjust = contr_adjust; cmd.wd.bright_adjust = bright_adjust; cmd.wd.tonecurve = s->tonecurve; cmd.wd.paddingtype = 3; cmd.wd.edge = s->edge; if (s->lin_log) cmd.wd.dummy3 = 0x02; DBG (3, "Setting parameters: imc %d, bpp %d, res %d, bri %d, con %d, bad %d, cad %d, ht %d, edge %d\n", s->image_composition, s->bpp, s->val[OPT_RESOLUTION].w, brightness, contrast, bright_adjust, contr_adjust, s->halftone, s->edge); } cmd.wd.image_comp = s->image_composition; cmd.wd.quality_type = s->quality; cmd.wd.orig_type = s->original; return sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); } /* Tell scanner to scan more data. */ static SANE_Status request_more_data (AgfaFocus_Scanner * s) { SANE_Status status; int lines_available; int bytes_per_line; status = start_scan (s->fd, SANE_TRUE); if (status != SANE_STATUS_GOOD) return status; if (!s->hw->disconnect) wait_ready (s->fd); status = get_read_sizes (s->fd, &lines_available, &bytes_per_line, 0); if (!lines_available) return SANE_STATUS_INVAL; s->lines_available = lines_available; return SANE_STATUS_GOOD; } static SANE_Status upload_dither_matrix (AgfaFocus_Scanner * s, int rows, int cols, int *dither_matrix) { struct { Byte cmd; Byte lun; Byte data_type; Byte re1[3]; Byte tr_len[3]; Byte ctrl; struct { Byte nrrows[2]; Byte nrcols[2]; struct { Byte data[2]; } element[256]; } wd; } cmd; SANE_Status status; int i; memset (&cmd, 0, sizeof (cmd)); cmd.cmd = 0x2a; /* WRITE */ cmd.data_type = 0x81; /* upload dither matrix */ set_size (cmd.tr_len, 3, 4 + (2 * rows * cols)); set_size (cmd.wd.nrrows, 2, rows); set_size (cmd.wd.nrcols, 2, cols); for (i = 0; i < cols * rows; ++i) set_size (cmd.wd.element[i].data, 2, dither_matrix[i]); status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); if (status != SANE_STATUS_GOOD) /* Command failed */ return SANE_STATUS_IO_ERROR; DBG (1, "upload_dither_matrix(): uploaded dither matrix: %d, %d\n", rows, cols); return SANE_STATUS_GOOD; } #if 0 static SANE_Status upload_tonecurve (AgfaFocus_Scanner * s, int color_type, int input, int output, int dither_matrix[256]) { struct { Byte cmd; Byte lun; Byte re1[4]; Byte tr_len[3]; Byte ctrl; Byte re2[6]; Byte wd_len[2]; struct { Byte color_type[2]; Byte nrinput[2]; Byte nroutput[2]; struct { Byte data[2]; } outputval[256]; } wd; } cmd; SANE_Status status; int i, j; memset (&cmd, 0, sizeof (cmd)); cmd.cmd = 0x80; set_size (cmd.tr_len, 3, sizeof (cmd.wd)); set_size (cmd.wd.nrrows, 2, rows); set_size (cmd.wd.nrrows, 2, cols); for (i = 0; i < cols; ++i) for (j = 0; j < rows; ++j) set_size (cmd.wd.element[j + i * rows].data, 2, dither_matrix[j + i * rows]); status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), 0, 0); if (status != SANE_STATUS_GOOD) /* * Command failed * */ return SANE_STATUS_IO_ERROR; DBG (1, "upload_dither_matrix(): uploaded dither matrix\n"); return SANE_STATUS_GOOD; } #endif /* May only be called when there is at least one row of data to be read. Original comment in German: Darf nur aufgerufen werden, wenn wirklich noch Zeilen zu scannen/lesen sind ! */ static SANE_Status read_data (AgfaFocus_Scanner * s, SANE_Byte *buf, int lines, int bpl) { struct { Byte cmd; Byte lun; Byte re1[4]; Byte tr_len[3]; Byte ctrl; } cmd; SANE_Status status; size_t size; unsigned int i; memset (&cmd, 0, sizeof (cmd)); cmd.cmd = 0x28; /* READ */ set_size (cmd.tr_len, 3, lines); size = lines * bpl; status = sanei_scsi_cmd (s->fd, &cmd, sizeof (cmd), buf, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_scsi_cmd() = %d\n", status); return SANE_STATUS_IO_ERROR; } if (size != ((unsigned int) lines * bpl)) { DBG (1, "sanei_scsi_cmd(): got %lu bytes, expected %d\n", (u_long) size, lines * bpl); return SANE_STATUS_INVAL; } DBG (1, "Got %lu bytes\n", (u_long) size); /* Reverse: */ if (s->bpp != 1) { if (s->bpp != 6) for (i = 0; i < size; i++) buf[i] = 255 - buf[i]; else for (i = 0; i < size; i++) buf[i] = 255 - ((buf[i] * 256.0f) / 64.0f); } s->lines_available -= lines; return SANE_STATUS_GOOD; } static SANE_Status attach (const char *devname, AgfaFocus_Device ** devp) { #define ATTACH_SCSI_INQ_LEN 55 const Byte scsi_inquiry[] = { 0x12, 0x00, 0x00, 0x00, ATTACH_SCSI_INQ_LEN, 0x00 }; Byte result[ATTACH_SCSI_INQ_LEN]; int fd; AgfaFocus_Device *dev; SANE_Status status; size_t size; int i; for (dev = agfafocus_devices; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } DBG (3, "attach: opening %s\n", devname); status = sanei_scsi_open (devname, &fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed (%s)\n", sane_strstatus (status)); return SANE_STATUS_INVAL; } DBG (4, "attach: sending INQUIRY\n"); size = sizeof (result); status = sanei_scsi_cmd (fd, scsi_inquiry, sizeof (scsi_inquiry), result, &size); if (status != SANE_STATUS_GOOD || size != ATTACH_SCSI_INQ_LEN) { DBG (1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } status = test_ready (fd); sanei_scsi_close (fd); if (status != SANE_STATUS_GOOD) return status; /* The structure send by the scanner after inquiry is not SCSI-2 compatible. The standard manufacturer/model fields are no ASCII strings, but ? At offset 36 my SIEMENS scanner identifies as an AGFA one ?! */ if (result[0] != 6 || strncmp ((char *)result + 36, "AGFA0", 5)) { DBG (1, "attach: device doesn't look like a Siemens 9036 scanner\n"); return SANE_STATUS_INVAL; } DBG (4, "Inquiry data:\n"); DBG (4, "-----------\n"); for (i = 5; i < 55; i += 10) DBG (4, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", result[i], result[i + 1], result[i + 2], result[i + 3], result[i + 4], result[i + 5], result[i + 6], result[i + 7], result[i + 8], result[i + 9]); dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devname); if (!strncmp ((char *)result + 36, "AGFA01", 6)) { dev->sane.vendor = "AGFA"; dev->sane.model = "Focus GS Scanner (6 bit)"; dev->upload_user_defines = SANE_TRUE; dev->type = AGFAGRAY64; } else if (!strncmp ((char *)result + 36, "AGFA02", 6)) { dev->sane.vendor = "AGFA"; dev->sane.model = "Focus Lineart Scanner"; dev->upload_user_defines = SANE_FALSE; dev->type = AGFALINEART; } else if (!strncmp ((char *)result + 36, "AGFA03", 6)) { dev->sane.vendor = "AGFA"; dev->sane.model = "Focus II"; dev->upload_user_defines = SANE_TRUE; dev->type = AGFAGRAY256; } else if (!strncmp ((char *)result + 36, "AGFA04", 6)) { dev->sane.vendor = "AGFA"; dev->sane.model = "Focus Color"; dev->upload_user_defines = SANE_TRUE; dev->type = AGFACOLOR; } else { free (dev); DBG (1, "attach: device looks like an AGFA scanner, but wasn't recognised\n"); return SANE_STATUS_INVAL; } dev->sane.type = "flatbed scanner"; dev->transparent = result[45] & 0x80 ? SANE_TRUE : SANE_FALSE; dev->analoglog = result[46] & 0x80 ? SANE_TRUE : SANE_FALSE; dev->tos5 = result[46] & 0x05 ? SANE_TRUE : SANE_FALSE; dev->quality = result[47] & 0x40 ? SANE_TRUE : SANE_FALSE; dev->disconnect = result[47] & 0x80 ? SANE_TRUE : SANE_FALSE; DBG (4, "\n"); DBG (4, "scan modes:\n"); DBG (4, "-----------\n"); DBG (4, "three pass color mode: %s\n", dev->type >= AGFACOLOR ? "yes" : "no"); DBG (4, "8 bit gray mode: %s\n", dev->type >= AGFAGRAY64 ? "yes" : "no"); DBG (4, "uploadable matrices: %s\n", dev->upload_user_defines ? "yes" : "no"); DBG (4, "transparency: %s\n", dev->transparent ? "yes" : "no"); DBG (4, "disconnect: %s\n", dev->disconnect ? "yes" : "no"); DBG (4, "quality calibration: %s\n", dev->quality ? "yes" : "no"); dev->handle = 0; DBG (3, "attach: found AgfaFocus scanner model\n"); ++num_devices; dev->next = agfafocus_devices; agfafocus_devices = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static SANE_Status do_eof (AgfaFocus_Scanner *s) { if (s->pipe >= 0) { close (s->pipe); s->pipe = -1; } return SANE_STATUS_EOF; } static SANE_Status do_cancel (AgfaFocus_Scanner * s) { s->scanning = SANE_FALSE; s->pass = 0; do_eof (s); if (sanei_thread_is_valid (s->reader_pid)) { int exit_status; /* ensure child knows it's time to stop: */ sanei_thread_kill (s->reader_pid); sanei_thread_waitpid (s->reader_pid, &exit_status); s->reader_pid = -1; } if (s->fd >= 0) { stop_scan (s->fd); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; } return SANE_STATUS_CANCELLED; } static SANE_Status init_options (AgfaFocus_Scanner * s) { int i; /* Hardware Limitations: must be static ! */ static const SANE_Int dpi_list[] = {8, 100, 200, 300, 400, 500, 600, 700, 800}; static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 1 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static const SANE_Range sharpen_range = {0, 7, 1}; static const SANE_Range exposure_range = {0, 100, 0}; static const SANE_Range attenuation_range = { 0 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 1 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static const SANE_Range x_range = {0, SANE_FIX (8.27 * MM_PER_INCH), 0}; static const SANE_Range y_range = {0, SANE_FIX (12.72 * MM_PER_INCH), 0}; /* ------ */ memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; switch (s->hw->type) { case AGFACOLOR: s->opt[OPT_MODE].size = max_string_size (focuscolor_mode_list); s->opt[OPT_MODE].constraint.string_list = focuscolor_mode_list; s->val[OPT_MODE].s = strdup (focuscolor_mode_list[0]); break; case AGFAGRAY256: s->opt[OPT_MODE].size = max_string_size (focusii_mode_list); s->opt[OPT_MODE].constraint.string_list = focusii_mode_list; s->val[OPT_MODE].s = strdup (focusii_mode_list[0]); break; default: s->opt[OPT_MODE].size = max_string_size (focus_mode_list); s->opt[OPT_MODE].constraint.string_list = focus_mode_list; s->val[OPT_MODE].s = strdup (focus_mode_list[0]); break; } s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; s->val[OPT_RESOLUTION].w = 100; s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].unit = SANE_UNIT_NONE; if (!s->hw->transparent) s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; else s->opt[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = source_list; s->opt[OPT_SOURCE].size = max_string_size (source_list); s->val[OPT_SOURCE].s = strdup (source_list[0]); /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &x_range; s->val[OPT_BR_X].w = x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &y_range; s->val[OPT_BR_Y].w = y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* exposure */ s->opt[OPT_EXPOSURE].name = "exposure"; s->opt[OPT_EXPOSURE].title = "Exposure"; s->opt[OPT_EXPOSURE].desc = "Analog exposure control."; s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT; s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_EXPOSURE].constraint.range = &exposure_range; s->val[OPT_EXPOSURE].w = 23; /* brightness automatic correct */ s->opt[OPT_AUTO_BRIGHTNESS].name = "adjust-bright"; s->opt[OPT_AUTO_BRIGHTNESS].title = "Automatic brightness correction"; s->opt[OPT_AUTO_BRIGHTNESS].desc = "Turns on automatic brightness correction of " "the acquired image. This makes the scanner do a two pass scan to analyse the " "brightness of the image before it's scanned."; s->opt[OPT_AUTO_BRIGHTNESS].type = SANE_TYPE_BOOL; s->val[OPT_AUTO_BRIGHTNESS].b = SANE_FALSE; /* contrast automatic correct */ s->opt[OPT_AUTO_CONTRAST].name = "adjust-contr"; s->opt[OPT_AUTO_CONTRAST].title = "Automatic contrast correction"; s->opt[OPT_AUTO_CONTRAST].desc = "Turns on automatic contrast correction of " "the acquired image. This makes the scanner do a two pass scan to analyse " "the contrast of the image to be scanned."; s->opt[OPT_AUTO_CONTRAST].type = SANE_TYPE_BOOL; s->val[OPT_AUTO_CONTRAST].b = SANE_FALSE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = "Controls the brightness of the acquired image. " "When automatic brightness is enabled, this can be used to adjust the selected brightness."; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; s->val[OPT_BRIGHTNESS].w = 0; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = "Controls the contrast of the acquired image. " "When automatic contrast is enabled, this can be used to adjust the selected contrast."; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; s->val[OPT_CONTRAST].w = 0; /* halftone patterns */ s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE_PATTERN].size = 32; s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; if (s->hw->upload_user_defines) { s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_upload_list; s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_upload_list[0]); } else { s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_list; s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_list[0]); } /* red-attenuation */ s->opt[OPT_ATTENUATION_RED].name = "red-attenuation"; s->opt[OPT_ATTENUATION_RED].title = "Red attenuation"; s->opt[OPT_ATTENUATION_RED].desc = "Controls the red attenuation of the acquired image. " "Higher values mean less impact on scanned image."; s->opt[OPT_ATTENUATION_RED].type = SANE_TYPE_FIXED; s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_RED].unit = SANE_UNIT_PERCENT; s->opt[OPT_ATTENUATION_RED].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_ATTENUATION_RED].constraint.range = &attenuation_range; s->val[OPT_ATTENUATION_RED].w = SANE_FIX (50.0); /* green-attenuation */ s->opt[OPT_ATTENUATION_GREEN].name = "green-attenuation"; s->opt[OPT_ATTENUATION_GREEN].title = "Green attenuation"; s->opt[OPT_ATTENUATION_GREEN].desc = "Controls the green attenuation of the acquired image. " "Higher values mean less impact on scanned image."; s->opt[OPT_ATTENUATION_GREEN].type = SANE_TYPE_FIXED; s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_GREEN].unit = SANE_UNIT_PERCENT; s->opt[OPT_ATTENUATION_GREEN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_ATTENUATION_GREEN].constraint.range = &attenuation_range; s->val[OPT_ATTENUATION_GREEN].w = SANE_FIX (50.0); /* blue-attenuation */ s->opt[OPT_ATTENUATION_BLUE].name = "blue-attenuation"; s->opt[OPT_ATTENUATION_BLUE].title = "Blue attenuation"; s->opt[OPT_ATTENUATION_BLUE].desc = "Controls the blue attenuation of the acquired image. " "Higher values mean less impact on scanned image."; s->opt[OPT_ATTENUATION_BLUE].type = SANE_TYPE_FIXED; s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_BLUE].unit = SANE_UNIT_PERCENT; s->opt[OPT_ATTENUATION_BLUE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_ATTENUATION_BLUE].constraint.range = &attenuation_range; s->val[OPT_ATTENUATION_BLUE].w = SANE_FIX (50.0); /* quality-calibration */ s->opt[OPT_QUALITY].name = SANE_NAME_QUALITY_CAL; s->opt[OPT_QUALITY].title = SANE_TITLE_QUALITY_CAL; s->opt[OPT_QUALITY].desc = "Controls the calibration that will be done in the " "scanner. Less calibration result in faster scanner times."; s->opt[OPT_QUALITY].type = SANE_TYPE_STRING; s->opt[OPT_QUALITY].size = 32; if (!s->hw->quality) s->opt[OPT_QUALITY].cap |= SANE_CAP_INACTIVE; else s->opt[OPT_QUALITY].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_QUALITY].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_QUALITY].constraint.string_list = quality_list; s->val[OPT_QUALITY].s = strdup (quality_list[1]); /* sharpening */ s->opt[OPT_SHARPEN].name = "sharpen"; s->opt[OPT_SHARPEN].title = "Sharpening"; s->opt[OPT_SHARPEN].desc = "Controls the sharpening that will be " "done by the video processor in the scanner."; s->opt[OPT_SHARPEN].type = SANE_TYPE_INT; s->opt[OPT_SHARPEN].unit = SANE_UNIT_NONE; s->opt[OPT_SHARPEN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_SHARPEN].constraint.range = &sharpen_range; s->val[OPT_SHARPEN].w = 1; return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach (dev, 0); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; authorize = authorize; /* silence gcc */ DBG_INIT (); sanei_thread_init (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open ("agfafocus.conf"); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { AgfaFocus_Device *dev, *next; for (dev = agfafocus_devices; dev; dev = next) { next = dev->next; if (dev->handle) sane_close (dev->handle); free (dev); } if (devlist) free (devlist); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { AgfaFocus_Device *dev; int i; local_only = local_only; /* silence gcc */ if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; for (dev = agfafocus_devices, i = 0; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { AgfaFocus_Device *dev; SANE_Status status; AgfaFocus_Scanner *s; if (devicename[0]) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } else { /* empty devicname -> use first device */ dev = agfafocus_devices; } if (!dev) return SANE_STATUS_INVAL; if (dev->handle) return SANE_STATUS_DEVICE_BUSY; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->scanning = SANE_FALSE; s->fd = -1; s->hw = dev; s->hw->handle = s; init_options (s); *handle = s; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { AgfaFocus_Scanner *s = handle; if (s->scanning) do_cancel (handle); s->hw->handle = 0; free (handle); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { AgfaFocus_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { AgfaFocus_Scanner *s = handle; SANE_Status status; if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS || !SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) return SANE_STATUS_UNSUPPORTED; if (action == SANE_ACTION_GET_VALUE) { switch (option) { case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_SHARPEN: case OPT_EXPOSURE: case OPT_ATTENUATION_RED: case OPT_ATTENUATION_GREEN: case OPT_ATTENUATION_BLUE: *(SANE_Word *) val = s->val[option].w; break; case OPT_AUTO_BRIGHTNESS: case OPT_AUTO_CONTRAST: *(SANE_Bool *) val = s->val[option].b; break; case OPT_MODE: case OPT_HALFTONE_PATTERN: case OPT_QUALITY: case OPT_SOURCE: strcpy (val, s->val[option].s); return (SANE_STATUS_GOOD); default: return SANE_STATUS_UNSUPPORTED; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) return SANE_STATUS_UNSUPPORTED; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info) *info |= SANE_INFO_RELOAD_PARAMS; case OPT_SHARPEN: case OPT_EXPOSURE: case OPT_ATTENUATION_RED: case OPT_ATTENUATION_GREEN: case OPT_ATTENUATION_BLUE: case OPT_BRIGHTNESS: case OPT_CONTRAST: s->val[option].w = *(SANE_Word *) val; break; case OPT_AUTO_BRIGHTNESS: case OPT_AUTO_CONTRAST: s->val[option].b = *(SANE_Bool *) val; break; case OPT_MODE: if (strcmp (s->val[option].s, (SANE_String) val)) { if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[option].s, "Gray (6 bit)") == 0) s->mode = GRAY6BIT; else if (strcmp (s->val[option].s, "Gray (8 bit)") == 0) s->mode = GRAY8BIT; else if (strcmp (s->val[option].s, "Color (18 bit)") == 0) s->mode = COLOR18BIT; else if (strcmp (s->val[option].s, "Color (24 bit)") == 0) s->mode = COLOR24BIT; else s->mode = LINEART; switch (s->mode) { case LINEART: s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE; break; case GRAY6BIT: s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; break; case GRAY8BIT: s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_AUTO_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_AUTO_CONTRAST].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_RED].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_GREEN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_BLUE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; break; case COLOR18BIT: s->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_RED].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_GREEN].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_BLUE].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_AUTO_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_AUTO_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SHARPEN].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; break; case COLOR24BIT: s->opt[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_RED].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_GREEN].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_ATTENUATION_BLUE].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_AUTO_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_AUTO_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; break; } } break; case OPT_SOURCE: case OPT_QUALITY: case OPT_HALFTONE_PATTERN: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); break; default: return SANE_STATUS_UNSUPPORTED; } } else { return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { AgfaFocus_Scanner *s = handle; if (!s->scanning) { double width, height, dpi; const char *quality; const char *original; memset (&s->params, 0, sizeof (s->params)); width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); dpi = s->val[OPT_RESOLUTION].w; /* make best-effort guess at what parameters will look like once scanning starts. */ if (dpi > 0.0 && width > 0.0 && height > 0.0) { double dots_per_mm = dpi / MM_PER_INCH; s->params.pixels_per_line = width * dots_per_mm + 0.5; s->params.lines = height * dots_per_mm + 0.5; } /* Should we specify calibration quality? */ if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_QUALITY].cap)) { DBG(3, " -------------- setting quality\n"); quality = s->val[OPT_QUALITY].s; if (strcmp (quality, "Low") == 0 ) s->quality = 255; else if (strcmp (quality, "High") == 0) s->quality = 1; else s->quality = 0; } else s->quality = 0; /* Should we select source type? */ if (SANE_OPTION_IS_ACTIVE (s->opt[OPT_SOURCE].cap)) { DBG(3, " -------------- setting source\n"); original = s->val[OPT_SOURCE].s; if (strcmp (original, "Transparency") == 0) s->original = 0; else s->original = 1; } else s->original = 0; s->exposure = ((s->val[OPT_EXPOSURE].w * (255.0f - 80.0f)) / 100.0f) + 80.0f; s->r_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_RED].w) * 20.0f) / 100.0f; s->g_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_GREEN].w) * 20.0f) / 100.0f; s->b_att = (SANE_UNFIX (s->val[OPT_ATTENUATION_BLUE].w) * 20.0f) / 100.0f; s->tonecurve = 0; switch (s->mode) { case LINEART: { const char *halftone; s->image_composition = 0; /* in 1 bpp mode, lines need to be 8 pixel length */ if (s->params.pixels_per_line % 8) s->params.pixels_per_line += 8 - (s->params.pixels_per_line % 8); s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line / 8; s->bpp = s->params.depth = 1; halftone = s->val[OPT_HALFTONE_PATTERN].s; if (strcmp (halftone, "1") == 0 ) s->halftone = 1; else if (strcmp (halftone, "Dispersed dot 4x4") == 0) s->halftone = 2; else if (strcmp (halftone, "Round (Clustered dot 4x4)") == 0) s->halftone = 3; else if (strcmp (halftone, "Diamond (Clustered dot 4x4)") == 0) s->halftone = 4; else if (strcmp (halftone, "User defined") == 0) s->halftone = 5; else s->halftone = 0; s->edge = s->val[OPT_SHARPEN].w; } break; case GRAY6BIT: s->image_composition = 2; s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->bpp = 6; s->params.depth = 8; s->edge = s->val[OPT_SHARPEN].w; break; case GRAY8BIT: s->image_composition = 2; s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->bpp = s->params.depth = 8; break; case COLOR18BIT: s->image_composition = 5; s->params.format = SANE_FRAME_RED; s->params.bytes_per_line = s->params.pixels_per_line; s->bpp = 6; s->params.depth = 8; s->edge = s->val[OPT_SHARPEN].w; break; case COLOR24BIT: s->image_composition = 5; s->params.format = SANE_FRAME_RED; s->params.bytes_per_line = s->params.pixels_per_line; s->bpp = s->params.depth = 8; break; } s->pass = 0; /*s->params.bytes_per_line = (s->params.pixels_per_line + (8 - s->params.depth)) / (8 / s->params.depth);*/ } else if (s->mode == COLOR18BIT || s->mode == COLOR24BIT) s->params.format = SANE_FRAME_RED + s->pass; s->params.last_frame = (s->params.format != SANE_FRAME_RED && s->params.format != SANE_FRAME_GREEN); if (params) *params = s->params; return SANE_STATUS_GOOD; } /* This function is executed as a child process. The reason this is executed as a subprocess is because some (most?) generic SCSI interfaces block a SCSI request until it has completed. With a subprocess, we can let it block waiting for the request to finish while the main process can go about to do more important things (such as recognizing when the user presses a cancel button). WARNING: Since this is executed as a subprocess, it's NOT possible to update any of the variables in the main process (in particular the scanner state cannot be updated). */ static int reader_process (void *scanner) { AgfaFocus_Scanner *s = (AgfaFocus_Scanner *) scanner; int fd = s->reader_pipe; SANE_Status status; SANE_Byte *data; int lines_read = 0; int lines_per_buffer; int bytes_per_line = 0, total_lines = 0; int i; sigset_t sigterm_set; sigset_t ignore_set; struct SIGACTION act; if (sanei_thread_is_forked()) close (s->pipe); sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); #if defined (__APPLE__) && defined (__MACH__) sigdelset (&ignore_set, SIGUSR2); #endif sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); if (!s->hw->disconnect) wait_ready (s->fd); status = get_read_sizes (s->fd, &s->lines_available, &bytes_per_line, &total_lines); if (status != SANE_STATUS_GOOD) { DBG (1, "open: get_read_sizes() failed: %s\n", sane_strstatus (status)); do_cancel (s); close (fd); return 1; } if (!s->lines_available || !bytes_per_line || !total_lines || bytes_per_line < s->params.bytes_per_line) { DBG (1, "open: invalid sizes: %d, %d, %d\n", s->lines_available, bytes_per_line, total_lines); do_cancel (s); close (fd); return 1; } lines_per_buffer = sanei_scsi_max_request_size / bytes_per_line; if (!lines_per_buffer) { close (fd); return 2; /* resolution is too high */ } data = malloc (lines_per_buffer * bytes_per_line); if (!data) { DBG (1, "open malloc(%lu) failed.\n", (u_long) lines_per_buffer * bytes_per_line); do_cancel (s); close (fd); return 1; } while (lines_read < s->params.lines) { int lines = lines_per_buffer; if (s->lines_available == 0) { /* No lines in scanner? Scan some more */ status = request_more_data (s); if (status != SANE_STATUS_GOOD) { close (fd); return 1; } } /* We only request as many lines as there are already scanned */ if (lines > s->lines_available) lines = s->lines_available; DBG (1, "Requesting %d lines, in scanner: %d, total: %d\n", lines, s->lines_available, s->params.lines); status = read_data (s, data, lines, bytes_per_line); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_read: read_data() failed (%s)\n", sane_strstatus (status)); do_cancel (s); close (fd); return 1; } /* Sometimes the scanner will return more bytes per line than requested, so we copy only what we wanted. */ for (i = 0; i < lines; i++) if (write (fd, data + i * bytes_per_line, s->params.bytes_per_line) != s->params.bytes_per_line) { do_cancel (s); close (fd); return 1; } lines_read += lines; } close (fd); return 0; } SANE_Status sane_start (SANE_Handle handle) { AgfaFocus_Scanner *s = handle; SANE_Status status; int fds[2]; /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; /* don't initialise scanner if we're doing a three-pass scan */ if (s->pass == 0) { if (s->fd < 0) { status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "open: open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); s->fd = -1; return status; } } status = test_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "open: test_ready() failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return status; } status = reserve_unit (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "open: reserve_unit() failed: %s\n", sane_strstatus (status)); sanei_scsi_close (s->fd); s->fd = -1; return status; } status = set_window (s); if (status != SANE_STATUS_GOOD) { DBG (1, "open: set_window() failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return status; } { int matrix[256] = { 2, 60, 16, 56, 3, 57, 13, 53, 34, 18, 48, 32, 35, 19, 45, 29, 10, 50, 6, 63, 11, 51, 7, 61, 42, 26, 38, 22, 43, 27, 39, 23, 4, 58, 14, 54, 1, 59, 15, 55, 36, 20, 46, 30, 33, 17, 47, 31, 12, 52, 8, 62, 9, 49, 5, 63, 44, 28, 40, 24, 41, 25, 37, 21 }; status = upload_dither_matrix (s, 8, 8, matrix); if (status != SANE_STATUS_GOOD) { DBG (1, "open: upload_dither_matrix() failed: %s\n", sane_strstatus (status)); release_unit (s->fd); sanei_scsi_close (s->fd); s->fd = -1; return status; } } s->scanning = SANE_TRUE; status = start_scan (s->fd, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (1, "open: start_scan() failed: %s\n", sane_strstatus (status)); do_cancel (s); return status; } } else { /* continue three-pass scan */ status = start_scan (s->fd, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (1, "open: start_scan() failed: %s\n", sane_strstatus (status)); do_cancel (s); return status; } } if (pipe (fds) < 0) return SANE_STATUS_IO_ERROR; s->pipe = fds[0]; s->reader_pipe = fds[1]; s->reader_pid = sanei_thread_begin (reader_process, (void *) s); if (sanei_thread_is_forked()) close (s->reader_pipe); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { AgfaFocus_Scanner *s = handle; ssize_t nread; *len = 0; nread = read (s->pipe, buf, max_len); DBG (3, "read %ld bytes\n", (long) nread); if (!s->scanning) return do_cancel (s); if (nread < 0) { if (errno == EAGAIN) { return SANE_STATUS_GOOD; } else { do_cancel (s); return SANE_STATUS_IO_ERROR; } } *len = nread; if (nread == 0) { s->pass++; return do_eof (s); } return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { AgfaFocus_Scanner *s = handle; if (sanei_thread_is_valid (s->reader_pid)) sanei_thread_kill (s->reader_pid); s->scanning = SANE_FALSE; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { AgfaFocus_Scanner *s = handle; if (!s->scanning) return SANE_STATUS_INVAL; if (fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { AgfaFocus_Scanner *s = handle; if (!s->scanning) return SANE_STATUS_INVAL; *fd = s->pipe; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/test.conf.in0000664000175000017500000000341712112021330015032 00000000000000# test backend configuration file ######################################## # number of test devices number_of_devices 2 # Initial option values and ranges ######################################## # Scan mode (Color, Gray) mode Gray # Bit depth (1, 8, 16) depth 8 # Hand-scanner mode (true, false) hand-scanner false # Three-pass mode (true, false) three-pass false # Three-pass order (RGB, RBG, GBR, GRB, BGR, BRG) three-pass-order RGB # Resolution (dpi) resolution_min 1.0 resolution_max 1200.0 resolution_quant 1.0 resolution 50.0 # Draw test picture ("Solid black", "Solid white", "Color pattern", "Grid") test-picture "Solid black" # Invert upper and lower byte in 16 bit modes invert-endianess false # Read-limit (true, false) read-limit false # Read-limit size (1 - 65536 bytes) read-limit-size 1 # Read-delay (true, false) read-delay false # Read-delay duration (1000 - 200,000 microseconds) read-delay-duration 1000 # Status code (return-value) of sane_read() ("Default", # "SANE_STATUS_UNSUPPORTED", # "SANE_STATUS_CANCELLED", "SANE_STATUS_DEVICE_BUSY", "SANE_STATUS_INVAL", # "SANE_STATUS_EOF", "SANE_STATUS_JAMMED", "SANE_STATUS_NO_DOCS", # "SANE_STATUS_COVER_OPEN", "SANE_STATUS_IO_ERROR", "SANE_STATUS_NO_MEM", # "SANE_STATUS_ACCESS_DENIED" read-status-code "Default" # Fuzzy parameters (true, false) fuzzy-parameters false # Loss of pixels per line (pixels) ppl-loss 0 # Non-blocking io (true, false) non-blocking false # Support select fd (true, false) select-fd false # Enable test options (true, false) enable-test-options false # Geometry (mm) geometry_min 0.0 geometry_max 200.0 geometry_quant 1.0 # Top-left x position (mm) tl_x 0.0 # Top-left y position (mm) tl_y 0.0 # Bottom-right x position (mm) br_x 80.0 # Bottom-right y position (mm) br_y 100.0 sane-backends-1.0.27/backend/sm3840_lib.c0000664000175000017500000006136012775312261014555 00000000000000/* sane - Scanner Access Now Easy. ScanMaker 3840 Backend Copyright (C) 2005-7 Earle F. Philhower, III earle@ziplabel.com - http://www.ziplabel.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include #include #include #include "sm3840_lib.h" #ifndef BACKENDNAME /* For standalone compilation */ static void DBG (int ignored, const char *fmt, ...) { va_list a; va_start (a, fmt); vfprintf (stderr, fmt, a); va_end (a); } #else /* For SANE compilation, convert libusb to sanei_usb */ static int my_usb_bulk_write (p_usb_dev_handle dev, int ep, unsigned char *bytes, int size, int timeout) { SANE_Status status; size_t my_size; timeout = timeout; ep = ep; my_size = size; status = sanei_usb_write_bulk ((SANE_Int) dev, (SANE_Byte *) bytes, &my_size); if (status != SANE_STATUS_GOOD) my_size = -1; return my_size; } static int my_usb_bulk_read (p_usb_dev_handle dev, int ep, unsigned char *bytes, int size, int timeout) { SANE_Status status; size_t my_size; timeout = timeout; ep = ep; my_size = size; status = sanei_usb_read_bulk ((SANE_Int) dev, (SANE_Byte *) bytes, &my_size); if (status != SANE_STATUS_GOOD) my_size = -1; return my_size; } static int my_usb_control_msg (p_usb_dev_handle dev, int requesttype, int request, int value, int index, unsigned char *bytes, int size, int timeout) { SANE_Status status; timeout = timeout; status = sanei_usb_control_msg ((SANE_Int) dev, (SANE_Int) requesttype, (SANE_Int) request, (SANE_Int) value, (SANE_Int) index, (SANE_Int) size, (SANE_Byte *) bytes); return status; } #endif /* Sanitize and convert scan parameters from inches to pixels */ static void prepare_params (SM3840_Params * params) { if (params->gray) params->gray = 1; if (params->lineart) { params->gray = 1; params->lineart = 1; } if (params->halftone) { params->gray = 1; params->halftone = 1; } if (params->dpi != 1200 && params->dpi != 600 && params->dpi != 300 && params->dpi != 150) params->dpi = 150; if (params->bpp != 8 && params->bpp != 16) params->bpp = 8; /* Sanity check input sizes */ if (params->top < 0) params->top = 0; if (params->left < 0) params->left = 0; if (params->width < 0) params->width = 0; if (params->height < 0) params->height = 0; if ((params->top + params->height) > 11.7) params->height = 11.7 - params->top; if ((params->left + params->width) > 8.5) params->width = 8.5 - params->left; params->topline = params->top * params->dpi; params->scanlines = params->height * params->dpi; params->leftpix = params->left * params->dpi; params->leftpix &= ~1; /* Always start on even pixel boundary for remap */ /* Scanpix always a multiple of 128 */ params->scanpix = params->width * params->dpi; params->scanpix = (params->scanpix + 127) & ~127; /* Sanity check outputs... */ if (params->topline < 0) params->topline = 0; if (params->scanlines < 1) params->scanlines = 1; if (params->leftpix < 0) params->leftpix = 0; if (params->scanpix < 128) params->scanpix = 128; /* Some handy calculations */ params->linelen = params->scanpix * (params->bpp / 8) * (params->gray ? 1 : 3); } #ifndef BACKENDNAME usb_dev_handle * find_device (unsigned int idVendor, unsigned int idProduct) { struct usb_bus *bus; struct usb_device *dev; usb_init (); usb_find_busses (); usb_find_devices (); for (bus = usb_get_busses (); bus; bus = bus->next) for (dev = bus->devices; dev; dev = dev->next) if (dev->descriptor.idVendor == idVendor && dev->descriptor.idProduct == idProduct) return usb_open (dev); return NULL; } #endif static void idle_ab (p_usb_dev_handle udev) { int i; unsigned char buff[8] = { 0x64, 0x65, 0x16, 0x17, 0x64, 0x65, 0x44, 0x45 }; for (i = 0; i < 8; i++) { usb_control_msg (udev, 0x40, 0x0c, 0x0090, 0x0000, buff + i, 0x0001, wr_timeout); } } /* CW: 40 04 00b0 0000 : ... */ static void write_regs (p_usb_dev_handle udev, int regs, unsigned char reg1, unsigned char val1, ... /*unsigned char reg, unsigned char val, ... */ ) { unsigned char buff[512]; va_list marker; int i; va_start (marker, val1); buff[0] = reg1; buff[1] = val1; for (i = 1; i < regs; i++) { buff[i * 2] = va_arg (marker, int); buff[i * 2 + 1] = va_arg (marker, int); } va_end (marker); usb_control_msg (udev, 0x40, 0x04, 0x00b0, 0x0000, buff, regs * 2, wr_timeout); } static int write_vctl (p_usb_dev_handle udev, int request, int value, int index, unsigned char byte) { return usb_control_msg (udev, 0x40, request, value, index, &byte, 1, wr_timeout); } static int read_vctl (p_usb_dev_handle udev, int request, int value, int index, unsigned char *byte) { return usb_control_msg (udev, 0xc0, request, value, index, byte, 1, wr_timeout); } #ifndef BACKENDNAME /* Copy from a USB data pipe to a file with optional header */ static void record_head (p_usb_dev_handle udev, char *fname, int bytes, char *header) { FILE *fp; unsigned char buff[65536]; int len; int toread; fp = fopen (fname, "wb"); if (header) fprintf (fp, "%s", header); do { toread = (bytes > 65536) ? 65536 : bytes; len = usb_bulk_read (udev, 1, buff, toread, rd_timeout); if (len > 0) { fwrite (buff, len, 1, fp); bytes -= len; } else { DBG (2, "TIMEOUT\n"); } } while (bytes); fclose (fp); } /* Copy from a USB data pipe to a file without header */ static void record (p_usb_dev_handle udev, char *fname, int bytes) { record_head (udev, fname, bytes, ""); } #endif static int max (int a, int b) { return (a > b) ? a : b; } #define DPI1200SHUFFLE 6 static void record_line (int reset, p_usb_dev_handle udev, unsigned char *storeline, int dpi, int scanpix, int gray, int bpp16, int *save_i, unsigned char **save_scan_line, unsigned char **save_dpi1200_remap, unsigned char **save_color_remap) { unsigned char *scan_line, *dpi1200_remap; unsigned char *color_remap; int i; int red_delay, blue_delay, green_delay; int j; int linelen; int pixsize; unsigned char *ptrcur, *ptrprev; unsigned char *savestoreline; int lineptr, outline, bufflines; i = *save_i; scan_line = *save_scan_line; dpi1200_remap = *save_dpi1200_remap; color_remap = *save_color_remap; pixsize = (gray ? 1 : 3) * (bpp16 ? 2 : 1); linelen = scanpix * pixsize; if (gray) { red_delay = 0; blue_delay = 0; green_delay = 0; } else if (dpi == 150) { red_delay = 0; blue_delay = 6; green_delay = 3; } else if (dpi == 300) { red_delay = 0; blue_delay = 12; green_delay = 6; } else if (dpi == 600) { red_delay = 0; blue_delay = 24; green_delay = 12; } else /*(dpi==1200) */ { red_delay = 0; blue_delay = 48; green_delay = 24; } bufflines = max (max (red_delay, blue_delay), green_delay) + 1; if (reset) { if (dpi1200_remap) free (dpi1200_remap); if (scan_line) free (scan_line); if (color_remap) free (color_remap); *save_color_remap = color_remap = (unsigned char *) malloc (bufflines * linelen); *save_scan_line = scan_line = (unsigned char *) calloc (linelen, 1); if (dpi == 1200) *save_dpi1200_remap = dpi1200_remap = (unsigned char *) calloc (linelen, DPI1200SHUFFLE); else *save_dpi1200_remap = dpi1200_remap = NULL; *save_i = i = 0; /* i is our linenumber */ } while (1) { /* We'll exit inside the loop... */ usb_bulk_read (udev, 1, scan_line, linelen, rd_timeout); if (dpi == 1200) { ptrcur = dpi1200_remap + (linelen * (i % DPI1200SHUFFLE)); ptrprev = dpi1200_remap + (linelen * ((i - (DPI1200SHUFFLE - 2)) % DPI1200SHUFFLE)); } else { ptrcur = scan_line; ptrprev = NULL; } if (gray) { memcpy (ptrcur, scan_line, linelen); } else { int pixsize = bpp16 ? 2 : 1; int pix = linelen / (3 * pixsize); unsigned char *outbuff = ptrcur; outline = i; lineptr = i % bufflines; memcpy (color_remap + linelen * lineptr, scan_line, linelen); outline++; if (outline > bufflines) { int redline = (outline + red_delay) % bufflines; int greenline = (outline + green_delay) % bufflines; int blueline = (outline + blue_delay) % bufflines; unsigned char *rp, *gp, *bp; rp = color_remap + linelen * redline; gp = color_remap + linelen * greenline + 1 * pixsize; bp = color_remap + linelen * blueline + 2 * pixsize; for (j = 0; j < pix; j++) { if (outbuff) { *(outbuff++) = *rp; if (pixsize == 2) *(outbuff++) = *(rp + 1); *(outbuff++) = *gp; if (pixsize == 2) *(outbuff++) = *(gp + 1); *(outbuff++) = *bp; if (pixsize == 2) *(outbuff++) = *(bp + 1); } rp += 3 * pixsize; gp += 3 * pixsize; bp += 3 * pixsize; } } lineptr = (lineptr + 1) % bufflines; } if (dpi != 1200) { if (i > blue_delay) { savestoreline = storeline; for (j = 0; j < scanpix; j++) { memcpy (storeline, ptrcur + linelen - (j + 1) * pixsize, pixsize); storeline += pixsize; } if (dpi == 150) { /* 150 DPI skips every 4th returned line */ if (i % 4) { i++; *save_i = i; if (bpp16) fix_endian_short ((unsigned short *) storeline, scanpix); return; } storeline = savestoreline; } else { i++; *save_i = i; if (bpp16) fix_endian_short ((unsigned short *) storeline, scanpix); return; } } } else /* dpi==1200 */ { if (i > (DPI1200SHUFFLE + blue_delay)) { for (j = 0; j < scanpix; j++) { if (1 == (j & 1)) memcpy (storeline, ptrcur + linelen - (j + 1) * pixsize, pixsize); else memcpy (storeline, ptrprev + linelen - (j + 1) * pixsize, pixsize); storeline += pixsize; } /* end for */ i++; *save_i = i; if (bpp16) fix_endian_short ((unsigned short *) storeline, scanpix); return; } /* end if >dpi1200shuffle */ } /* end if dpi1200 */ i++; } /* end for */ } #ifndef BACKENDNAME /* Record an image to a file with remapping/reordering/etc. */ void record_image (p_usb_dev_handle udev, char *fname, int dpi, int scanpix, int scanlines, int gray, char *head, int bpp16) { FILE *fp; int i; int save_i; unsigned char *save_scan_line; unsigned char *save_dpi1200_remap; unsigned char *save_color_remap; unsigned char *storeline; save_i = 0; save_scan_line = save_dpi1200_remap = save_color_remap = NULL; storeline = (unsigned char *) malloc (scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1)); fp = fopen (fname, "wb"); if (head) fprintf (fp, "%s", head); for (i = 0; i < scanlines; i++) { record_line ((i == 0) ? 1 : 0, udev, storeline, dpi, scanpix, gray, bpp16, &save_i, &save_scan_line, &save_dpi1200_remap, &save_color_remap); fwrite (storeline, scanpix * (gray ? 1 : 3) * (bpp16 ? 2 : 1), 1, fp); } fclose (fp); if (save_scan_line) free (save_scan_line); if (save_dpi1200_remap) free (save_dpi1200_remap); if (save_color_remap) free (save_color_remap); free (storeline); } #endif static void record_mem (p_usb_dev_handle udev, unsigned char **dest, int bytes) { unsigned char *mem; unsigned char buff[65536]; int len; mem = (unsigned char *) malloc (bytes); *dest = mem; do { len = usb_bulk_read (udev, 1, buff, bytes > 65536 ? 65536 : bytes, rd_timeout); if (len > 0) { memcpy (mem, buff, len); bytes -= len; mem += len; } } while (bytes); } static void reset_scanner (p_usb_dev_handle udev) { unsigned char rd_byte; DBG (2, "+reset_scanner\n"); write_regs (udev, 5, 0x83, 0x00, 0xa3, 0xff, 0xa4, 0xff, 0xa1, 0xff, 0xa2, 0xff); write_vctl (udev, 0x0c, 0x0001, 0x0000, 0x00); write_regs (udev, 2, 0xbe, 0x00, 0x84, 0x00); write_vctl (udev, 0x0c, 0x00c0, 0x8406, 0x00); write_vctl (udev, 0x0c, 0x00c0, 0x0406, 0x00); write_regs (udev, 16, 0xbe, 0x18, 0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x88, 0x00, 0x86, 0x00, 0x90, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3, 0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8, 0x00, 0xc0, 0x00); write_regs (udev, 16, 0x84, 0x94, 0x80, 0xd1, 0x80, 0xc1, 0x82, 0x7f, 0xcf, 0x04, 0xc1, 0x02, 0xc2, 0x00, 0xc3, 0x06, 0xc4, 0xff, 0xc5, 0x40, 0xc6, 0x8c, 0xc7, 0xdc, 0xc8, 0x20, 0xc0, 0x72, 0x89, 0xff, 0x86, 0xff); write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0xc8, 0x83, 0x82, 0x85, 0xaf, 0x83, 0x00, 0x93, 0x00); write_regs (udev, 3, 0xa8, 0x0a, 0x8c, 0x08, 0x94, 0x00); write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); write_regs (udev, 1, 0x97, 0x0b); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); write_regs (udev, 1, 0x97, 0x0f); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); write_regs (udev, 1, 0x97, 0x05); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); DBG (2, "-reset_scanner\n"); } static void poll1 (p_usb_dev_handle udev) { unsigned char rd_byte; DBG (2, "+poll1\n"); do { write_regs (udev, 1, 0x97, 0x00); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); } while (0 == (rd_byte & 0x40)); DBG (2, "-poll1\n"); } static void poll2 (p_usb_dev_handle udev) { unsigned char rd_byte; DBG (2, "+poll2\n"); do { write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); } while (0 == (rd_byte & 0x02)); DBG (2, "-poll2\n"); } #ifndef BACKENDNAME static void check_buttons (p_usb_dev_handle udev, int *scan, int *print, int *mail) { unsigned char rd_byte; write_regs (udev, 4, 0x83, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0x97, 0x0a); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); if (scan) { if (0 == (rd_byte & 1)) *scan = 1; else *scan = 0; } if (print) { if (0 == (rd_byte & 2)) *print = 1; else *print = 0; } if (mail) { if (0 == (rd_byte & 4)) *mail = 1; else *mail = 0; } write_regs (udev, 1, 0x97, 0x0b); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); idle_ab (udev); write_regs (udev, 1, 0x97, 0x0f); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); idle_ab (udev); write_regs (udev, 1, 0x97, 0x05); write_vctl (udev, 0x0c, 0x0004, 0x008b, 0x00); read_vctl (udev, 0x0c, 0x0007, 0x0000, &rd_byte); idle_ab (udev); } #endif static int lut (int val, double gain, int offset) { /* int offset = 1800; */ /* double exponent = 3.5; */ return (offset + 8192.0 * (pow ((8192.0 - val) / 8192.0, gain))); } static void calc_lightmap (unsigned short *buff, unsigned short *storage, int index, int dpi, double gain, int offset) { int val, line; int px = 5632; int i; line = px * 3; for (i = 0; i < px; i++) { if ((i >= 2) && (i <= (px - 2))) { val = 0; val += 1 * buff[i * 3 + index - 3 * 2]; val += 3 * buff[i * 3 + index - 3 * 1]; val += 5 * buff[i * 3 + index + 3 * 0]; val += 3 * buff[i * 3 + index + 3 * 1]; val += 1 * buff[i * 3 + index + 3 * 2]; val += 2 * buff[i * 3 + index - 3 * 1 + line]; val += 3 * buff[i * 3 + index + 3 * 0 + line]; val += 2 * buff[i * 3 + index + 3 * 1 + line]; val += 1 * buff[i * 3 + index + 3 * 0 + 2 * line]; val /= 21; } else { val = 1 * buff[i * 3 + index]; } val = val >> 3; if (val > 8191) val = 8191; val = lut (val, gain, offset); if (val > 8191) val = 8191; if (val < 0) val = 0; storage[i * (dpi == 1200 ? 2 : 1)] = val; if (dpi == 1200) storage[i * 2 + 1] = val; } fix_endian_short (storage, (dpi == 1200) ? i * 2 : i); } /*#define VALMAP 0x1fff */ /*#define SCANMAP 0x2000*/ #define RAWPIXELS600 7320 #define RAWPIXELS1200 14640 static void select_pixels (unsigned short *map, int dpi, int start, int end) { int i; int skip, offset; unsigned short VALMAP = 0x1fff; unsigned short SCANMAP = 0x2000; fix_endian_short (&VALMAP, 1); fix_endian_short (&SCANMAP, 1); /* Clear the pixel-on flags for all bits */ for (i = 0; i < ((dpi == 1200) ? RAWPIXELS1200 : RAWPIXELS600); i++) map[i] &= VALMAP; /* 300 and 150 have subsampling */ if (dpi == 300) skip = -2; else if (dpi == 150) skip = -4; else skip = -1; /* 1200 has 2x pixels so start at 2x the offset */ if (dpi == 1200) offset = 234 + (8.5 * 1200); else offset = 117 + (8.5 * 600); if (0 == (offset & 1)) offset++; DBG (2, "offset=%d start=%d skip=%d\n", offset, start, skip); for (i = 0; i < end; i++) { int x; x = offset + (start * skip) + (i * skip); if (x < 0 || x > ((dpi == 1200) ? RAWPIXELS1200 : RAWPIXELS600)) DBG (2, "ERR %d\n", x); else map[x] |= SCANMAP; } } static void set_lightmap_white (unsigned short *map, int dpi, int color) { int i; unsigned short VALMAP = 0x1fff; unsigned short SCANMAP = 0x2000; fix_endian_short (&VALMAP, 1); fix_endian_short (&SCANMAP, 1); if (dpi != 1200) { memset (map, 0, RAWPIXELS600 * 2); if (color != 0) return; /* Only 1st has enables... */ for (i = 0; i < 22; i++) map[7 + i] = SCANMAP; /* Get some black... */ for (i = 0; i < 1024; i++) map[2048 + i] = SCANMAP; /* And some white... */ } else { memset (map, 0, RAWPIXELS1200 * 2); if (color != 0) return; for (i = 16; i < 61; i++) map[i] = SCANMAP; for (i = 4076; i < 6145; i++) map[i] = SCANMAP; /* 3rd is all clear */ } } static void set_lamp_timer (p_usb_dev_handle udev, int timeout_in_mins) { write_regs (udev, 7, 0xa8, 0x80, 0x83, 0xa2, 0x85, 0xc8, 0x83, 0x82, 0x85, 0xaf, 0x83, 0x00, 0x93, 0x00); write_regs (udev, 3, 0xa8, timeout_in_mins * 2, 0x8c, 0x08, 0x94, 0x00); idle_ab (udev); write_regs (udev, 4, 0x83, 0x20, 0x8d, 0x26, 0x83, 0x00, 0x8d, 0xff); } static void calculate_lut8 (double *poly, int skip, unsigned char *dest) { int i; double sum, x; if (!poly || !dest) return; for (i = 0; i < 8192; i += skip) { sum = poly[0]; x = (double) i; sum += poly[1] * x; x = x * i; sum += poly[2] * x; x = x * i; sum += poly[3] * x; x = x * i; sum += poly[4] * x; x = x * i; sum += poly[5] * x; x = x * i; sum += poly[6] * x; x = x * i; sum += poly[7] * x; x = x * i; sum += poly[8] * x; x = x * i; sum += poly[9] * x; x = x * i; if (sum < 0) sum = 0; if (sum > 255) sum = 255; *dest = (unsigned char) sum; dest++; } } static void download_lut8 (p_usb_dev_handle udev, int dpi, int incolor) { double color[10] = { 0.0, 1.84615261590892E-01, -2.19613868292657E-04, 1.79549523214101E-07, -8.69378513113239E-11, 2.56694911984996E-14, -4.67288886157239E-18, 5.11622894146250E-22, -3.08729724411991E-26, 7.88581670873938E-31 }; double gray[10] = { 0.0, 1.73089945056694E-01, -1.39794924306080E-04, 9.70266873814926E-08, -4.57503008236968E-11, 1.37092321631794E-14, -2.54395068387198E-18, 2.82432084125966E-22, -1.71787408822688E-26, 4.40306800664567E-31 }; unsigned char *lut; DBG (2, "+download_lut8\n"); switch (dpi) { case 150: case 300: case 600: lut = (unsigned char *) malloc (4096); if (!lut) return; if (!incolor) { calculate_lut8 (gray, 2, lut); write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x07, 0xb3, 0xff, 0xb4, 0x2f, 0xb5, 0x07); write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00); usb_bulk_write (udev, 2, lut, 4096, wr_timeout); } else { calculate_lut8 (color, 2, lut); write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x10, 0xb2, 0x07, 0xb3, 0xff, 0xb4, 0x1f, 0xb5, 0x07); write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00); usb_bulk_write (udev, 2, lut, 4096, wr_timeout); write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x07, 0xb3, 0xff, 0xb4, 0x2f, 0xb5, 0x07); write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00); usb_bulk_write (udev, 2, lut, 4096, wr_timeout); write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x30, 0xb2, 0x07, 0xb3, 0xff, 0xb4, 0x3f, 0xb5, 0x07); write_vctl (udev, 0x0c, 0x0002, 0x1000, 0x00); usb_bulk_write (udev, 2, lut, 4096, wr_timeout); } break; case 1200: default: lut = (unsigned char *) malloc (8192); if (!lut) return; if (!incolor) { calculate_lut8 (gray, 1, lut); write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x06, 0xb3, 0xff, 0xb4, 0x5f, 0xb5, 0x06); write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00); usb_bulk_write (udev, 2, lut, 8192, wr_timeout); } else { calculate_lut8 (color, 1, lut); write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x20, 0xb2, 0x06, 0xb3, 0xff, 0xb4, 0x3f, 0xb5, 0x06); write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00); usb_bulk_write (udev, 2, lut, 8192, wr_timeout); write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x40, 0xb2, 0x06, 0xb3, 0xff, 0xb4, 0x5f, 0xb5, 0x06); write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00); usb_bulk_write (udev, 2, lut, 8192, wr_timeout); write_regs (udev, 6, 0xb0, 0x00, 0xb1, 0x60, 0xb2, 0x06, 0xb3, 0xff, 0xb4, 0x7f, 0xb5, 0x06); write_vctl (udev, 0x0c, 0x0002, 0x2000, 0x00); usb_bulk_write (udev, 2, lut, 8192, wr_timeout); } break; } free (lut); DBG (2, "-download_lut8\n"); } static void set_gain_black (p_usb_dev_handle udev, int r_gain, int g_gain, int b_gain, int r_black, int g_black, int b_black) { write_regs (udev, 1, 0x80, 0x00); write_regs (udev, 1, 0x80, 0x01); write_regs (udev, 1, 0x04, 0x80); write_regs (udev, 1, 0x04, 0x00); write_regs (udev, 1, 0x00, 0x00); write_regs (udev, 1, 0x01, 0x03); write_regs (udev, 1, 0x02, 0x04); write_regs (udev, 1, 0x03, 0x11); write_regs (udev, 1, 0x05, 0x00); write_regs (udev, 1, 0x28, r_gain); write_regs (udev, 1, 0x29, g_gain); write_regs (udev, 1, 0x2a, b_gain); write_regs (udev, 1, 0x20, r_black); write_regs (udev, 1, 0x21, g_black); write_regs (udev, 1, 0x22, b_black); write_regs (udev, 1, 0x24, 0x00); write_regs (udev, 1, 0x25, 0x00); write_regs (udev, 1, 0x26, 0x00); } /* Handle short endianness issues */ static void fix_endian_short (unsigned short *data, int count) { unsigned short testvalue = 255; unsigned char *firstbyte = (unsigned char *) &testvalue; int i; if (*firstbyte == 255) return; /* INTC endianness */ DBG (2, "swapping endiannes...\n"); for (i = 0; i < count; i++) data[i] = ((data[i] >> 8) & 0x00ff) | ((data[i] << 8) & 0xff00); } sane-backends-1.0.27/backend/snapscan.h0000664000175000017500000007035412775312261014607 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997, 1998, 1999, 2001, 2002, 2013 Franck Schnefra, Michel Roelofs, Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson, Andrew Goodbody, Oliver Schwartz and Kevin Charter This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is a component of the implementation of a backend for many of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ SANE SnapScan backend */ #ifndef snapscan_h #define snapscan_h #include "../include/sane/sane.h" #define UNREFERENCED_PARAMETER(x) ((void) x) /* snapscan device field values */ #define DEFAULT_DEVICE "/dev/scanner" /* Check this if config is missing */ #define SNAPSCAN_TYPE "flatbed scanner" #define SNAPSCAN_FS_TYPE "film scanner" #define TMP_FILE_PREFIX "/var/tmp/snapscan" #define SNAPSCAN_CONFIG_FILE "snapscan.conf" #define FIRMWARE_KW "firmware" #define OPTIONS_KW "options" /* Define the colour channel order in arrays */ #define R_CHAN 0 #define G_CHAN 1 #define B_CHAN 2 typedef enum { UNKNOWN_BUS, SCSI, USB } SnapScan_Bus; typedef enum { UNKNOWN, SNAPSCAN, /* the original SnapScan */ SNAPSCAN300, /* the SnapScan 300 */ SNAPSCAN310, /* the SnapScan 310 */ SNAPSCAN600, /* the SnapScan 600 */ SNAPSCAN1236, /* the SnapScan 1236 */ SNAPSCAN1212U, SNAPSCANE20, /* SnapScan e20/e25, 600 DPI */ SNAPSCANE50, /* SnapScan e40/e50, 1200 DPI */ SNAPSCANE52, /* SnapScan e52, 1200 DPI, no quality calibration */ ACER300F, PRISA310, /* Acer ScanPrisa 310 - 300 DPI */ PRISA610, /* Acer ScanPrisa 610 - 600 DPI */ PRISA620, /* Acer ScanPrisa 620 - 600 DPI */ PRISA640, /* Acer ScanPrisa 640 - 600 DPI */ PRISA1240, /* Acer ScanPrisa 1240 - 1200 DPI */ PRISA4300, /* Acer ScanPrisa 3300/4300 - 600 DPI */ PRISA4300_2, /* Acer ScanPrisa 3300/4300 - 600 DPI, 42 bit*/ PRISA5000, /* Acer ScanPrisa 5000 - 1200 DPI */ PRISA5000E, /* Acer ScanPrisa 5000E/5000U - 1200 DPI */ PRISA5150, /* Benq 5150 - 1200 DPI */ PRISA5300, /* Acer ScanPrisa 5300 - 1200 DPI */ PERFECTION660, /* Epson Perfection 660 - 1200 DPI */ PERFECTION1270, /* Epson Perfection 1270 - 1600 DPI */ PERFECTION1670, /* Epson Perfection 1670 - 1600 DPI */ PERFECTION2480, /* Epson Perfection 2480 - 2400 DPI */ PERFECTION3490, /* Epson Perfection 3490 - 3200 DPI */ STYLUS_CX1500, /* Epson Stylus CX 1500 - 600 DPI */ ARCUS1200, /* Agfa Arcus 1200 - 1200 DPI (rebadged Acer?) */ SCANWIT2720S /* BenQ ScanWit 2720S film scanner 2700 DPI */ } SnapScan_Model; struct SnapScan_Driver_desc { SnapScan_Model id; char *driver_name; }; static struct SnapScan_Driver_desc drivers[] = { /* enum value -> Driver name */ {UNKNOWN, "Unknown"}, {SNAPSCAN, "SnapScan"}, {SNAPSCAN300, "SnapScan300"}, {SNAPSCAN310, "SnapScan310"}, {SNAPSCAN600, "SnapScan600"}, {SNAPSCAN1236, "SnapScan1236"}, {SNAPSCAN1212U, "SnapScan1212"}, {SNAPSCANE20, "SnapScanE20"}, {SNAPSCANE50, "SnapScanE50"}, {SNAPSCANE52, "SnapScanE52"}, {ACER300F, "Acer300"}, {PRISA310, "Acer310"}, {PRISA610, "Acer610"}, {PRISA620, "Acer620"}, {PRISA640, "Acer640"}, {PRISA4300, "Acer4300"}, {PRISA4300_2, "Acer4300 (42 bit)"}, {PRISA1240, "Acer1240"}, {PRISA5000E, "Benq 5000E/5000U"}, {PRISA5000, "Benq 5000"}, {PRISA5150, "Benq 5150 / 5250"}, {PRISA5300, "Benq 5300"}, {ARCUS1200, "Arcus1200"}, {PERFECTION660, "Perfection 660"}, {PERFECTION1270, "Perfection 1270"}, {PERFECTION1670, "Perfection 1670"}, {PERFECTION2480, "Perfection 2480"}, {PERFECTION3490, "Perfection 3490"}, {STYLUS_CX1500, "Stylus CX 1500"}, {SCANWIT2720S, "BenQ ScanWit 2720S"} }; #define known_drivers ((int) (sizeof(drivers)/sizeof(drivers[0]))) struct SnapScan_Model_desc { char *scsi_name; SnapScan_Model id; }; static struct SnapScan_Model_desc scanners[] = { /* SCSI model name -> enum value */ {"FlatbedScanner_2", PRISA310}, {"FlatbedScanner_4", PRISA610}, {"FlatbedScanner_5", PRISA620}, {"FlatbedScanner_7", PRISA310}, {"FlatbedScanner_9", PRISA620}, {"FlatbedScanner13", PRISA620}, {"FlatbedScanner16", PRISA620}, {"FlatbedScanner17", PRISA620}, {"FlatbedScanner18", PRISA620}, {"FlatbedScanner19", PRISA1240}, {"FlatbedScanner20", PRISA640}, {"FlatbedScanner21", PRISA4300}, {"FlatbedScanner22", PRISA4300_2}, {"FlatbedScanner23", PRISA4300_2}, {"FlatbedScanner24", PRISA5300}, {"FlatbedScanner25", PRISA5000E},/* 5000E/5000U */ {"FlatbedScanner40", PRISA5150}, /* 5150 / 5250 */ {"FlatbedScanner42", PRISA5000}, /* 5000 */ {"SNAPSCAN 1212U", SNAPSCAN1212U}, {"SNAPSCAN 1212U_2", SNAPSCAN1212U}, {"SNAPSCAN e10", SNAPSCANE20}, {"SNAPSCAN e20", SNAPSCANE20}, {"SNAPSCAN e25", SNAPSCANE20}, {"SNAPSCAN e26", SNAPSCANE20}, {"SNAPSCAN e40", SNAPSCANE50}, {"SNAPSCAN e42", SNAPSCANE52}, {"SNAPSCAN e50", SNAPSCANE50}, {"SNAPSCAN e52", SNAPSCANE52}, {"SNAPSCAN 1236", SNAPSCAN1236}, {"SNAPSCAN 1236U", SNAPSCAN1236}, {"SNAPSCAN 300", SNAPSCAN300}, {"SNAPSCAN 310", SNAPSCAN310}, {"SNAPSCAN 600", SNAPSCAN600}, {"SnapScan", SNAPSCAN}, {"ACERSCAN_A4____1", ACER300F}, {"Perfection 660", PERFECTION660}, {"EPSON Scanner", PERFECTION1670}, /* dummy entry to detect scanner */ {"EPSON Scanner1", PERFECTION2480}, /* dummy entry to detect scanner */ {"EPSON Scanner2", PERFECTION3490}, /* dummy entry to detect scanner */ {"EPSON MFP00", STYLUS_CX1500}, {"ARCUS 1200", ARCUS1200}, {"FilmScanner____1", SCANWIT2720S} }; #define known_scanners ((int) (sizeof(scanners)/sizeof(scanners[0]))) static char *vendors[] = { /* SCSI Vendor name */ "AGFA", "COLOR", "Color", "ACERPER", "EPSON" }; #define known_vendors ((int) (sizeof(vendors)/sizeof(vendors[0]))) /* Known vendor IDs */ #define USB_VENDOR_AGFA 0x06bd #define USB_VENDOR_ACER 0x04a5 #define USB_VENDOR_EPSON 0x04b8 /* Agfa product IDs */ #define USB_PRODUCT_1212U2 0x2061 /* Acer product IDs */ #define USB_PRODUCT_PRISA310 0x1a20 #define USB_PRODUCT_PRISA320 0x2022 /* Epson product IDs */ #define USB_PRODUCT_PERFECTION660 0x0114 #define USB_PRODUCT_PERFECTION1270 0x0120 #define USB_PRODUCT_PERFECTION1670 0x011f #define USB_PRODUCT_PERFECTION2480 0x0121 #define USB_PRODUCT_PERFECTION3490 0x0122 static SANE_Word usb_vendor_ids[] = { /* USB Vendor IDs */ USB_VENDOR_AGFA, /* Agfa */ USB_VENDOR_ACER, /* Acer */ USB_VENDOR_EPSON /* Epson */ }; #define known_usb_vendor_ids ((int) (sizeof(usb_vendor_ids)/sizeof(usb_vendor_ids[0]))) struct SnapScan_USB_Model_desc { SANE_Word vendor_id; SANE_Word product_id; SnapScan_Model id; }; static struct SnapScan_USB_Model_desc usb_scanners[] = { {USB_VENDOR_ACER, USB_PRODUCT_PRISA310, PRISA310}, /* Acer 310U */ {USB_VENDOR_ACER, USB_PRODUCT_PRISA320, PRISA310}, /* Acer 320U */ {USB_VENDOR_EPSON, USB_PRODUCT_PERFECTION660, PERFECTION660}, /* Epson Perfection 660 */ {USB_VENDOR_EPSON, USB_PRODUCT_PERFECTION1270, PERFECTION1270}, /* Epson Perfection 1270 */ {USB_VENDOR_EPSON, USB_PRODUCT_PERFECTION1670, PERFECTION1670}, /* Epson Perfection 1670 */ {USB_VENDOR_EPSON, USB_PRODUCT_PERFECTION2480, PERFECTION2480}, /* Epson Perfection 2480 */ {USB_VENDOR_EPSON, USB_PRODUCT_PERFECTION3490, PERFECTION3490} /* Epson Perfection 3490 */ }; #define known_usb_scanners ((int) (sizeof(usb_scanners)/sizeof(usb_scanners[0]))) typedef enum { OPT_COUNT = 0, /* option count */ OPT_MODE_GROUP, /* scan mode group */ OPT_SCANRES, /* scan resolution */ OPT_PREVIEW, /* preview mode toggle */ OPT_MODE, /* scan mode */ OPT_PREVIEW_MODE, /* preview mode */ OPT_HIGHQUALITY, /* scan quality (fast / high) */ OPT_SOURCE, /* scan source (flatbed / TPO) */ OPT_FRAME_NO, /* frame number for film scanner */ OPT_FOCUS_MODE, /* manual or auto focus for film scanner */ OPT_FOCUS_POINT, /* focus point for film scanner */ OPT_GEOMETRY_GROUP, /* geometry group */ OPT_TLX, /* top left x */ OPT_TLY, /* top left y */ OPT_BRX, /* bottom right x */ OPT_BRY, /* bottom right y */ OPT_PREDEF_WINDOW, /* predefined window configuration */ OPT_ENHANCEMENT_GROUP, /* enhancement group */ OPT_BIT_DEPTH, /* 8/16 bit/pixel for colour scans */ OPT_QUALITY_CAL, /* quality calibration */ OPT_HALFTONE, /* halftone flag */ OPT_HALFTONE_PATTERN, /* halftone matrix */ OPT_CUSTOM_GAMMA, /* use custom gamma tables */ OPT_GAMMA_BIND, /* use same gamma value for all colors */ OPT_GAMMA_GS, /* gamma correction (greyscale) */ OPT_GAMMA_R, /* gamma correction (red) */ OPT_GAMMA_G, /* gamma correction (green) */ OPT_GAMMA_B, /* gamma correction (blue) */ OPT_GAMMA_VECTOR_GS, /* gamma correction vector (greyscale) */ OPT_GAMMA_VECTOR_R, /* gamma correction vector (red) */ OPT_GAMMA_VECTOR_G, /* gamma correction vector (green) */ OPT_GAMMA_VECTOR_B, /* gamma correction vector (blue) */ OPT_NEGATIVE, /* swap black and white */ OPT_THRESHOLD, /* threshold for line art */ OPT_BRIGHTNESS, /* brightness */ OPT_CONTRAST, /* contrast */ OPT_ADVANCED_GROUP, /* advanced group */ OPT_RGB_LPR, /* lines per scsi read (RGB) */ OPT_GS_LPR, /* lines per scsi read (GS) */ NUM_OPTS /* dummy (gives number of options) */ } SnapScan_Options; typedef enum { MD_COLOUR = 0, /* full colour */ MD_BILEVELCOLOUR, /* 1-bit per channel colour */ MD_GREYSCALE, /* grey scale */ MD_LINEART, /* black and white */ MD_NUM_MODES } SnapScan_Mode; typedef enum { SRC_FLATBED = 0, /* Flatbed (normal) */ SRC_TPO, /* Transparency unit */ SRC_ADF } SnapScan_Source; typedef enum { ST_IDLE, /* between scans */ ST_SCAN_INIT, /* scan initialization */ ST_SCANNING, /* actively scanning data */ ST_CANCEL_INIT /* cancellation begun */ } SnapScan_State; typedef struct snapscan_device { SANE_Device dev; SANE_Range x_range; /* x dimension of scan area */ SANE_Range y_range; /* y dimension of scan area */ SnapScan_Model model; /* type of scanner */ SnapScan_Bus bus; /* bus of the device usb/scsi */ SANE_Char *firmware_filename; /* The name of the firmware file for USB scanners */ struct snapscan_device *pnext; } SnapScan_Device; #define MD_AUTO 0 #define MD_MANUAL 1 #define MAX_SCSI_CMD_LEN 256 /* not that large */ #define DEFAULT_SCANNER_BUF_SZ 1024*63 typedef struct snapscan_scanner SnapScan_Scanner; #include struct snapscan_scanner { SANE_String devname; /* the scsi device name */ SnapScan_Device *pdev; /* the device */ int fd; /* scsi file descriptor */ int opens; /* open count */ int rpipe[2]; /* reader pipe descriptors */ int orig_rpipe_flags; /* initial reader pipe flags */ SANE_Pid child; /* child reader process pid */ SnapScan_Mode mode; /* mode */ SnapScan_Mode preview_mode; /* preview mode */ SnapScan_Source source; /* scanning source */ SnapScan_State state; /* scanner state */ u_char cmd[MAX_SCSI_CMD_LEN]; /* scsi command buffer */ u_char *buf; /* data buffer */ size_t phys_buf_sz; /* physical buffer size */ size_t buf_sz; /* effective buffer size */ size_t expected_read_bytes; /* expected amount of data in a single read */ size_t read_bytes; /* amount of actual data read */ size_t bytes_remaining; /* remaining bytes expected from scanner */ size_t actual_res; /* actual resolution */ size_t lines; /* number of scan lines */ size_t bytes_per_line; /* bytes per scan line */ size_t pixels_per_line; /* pixels per scan line */ u_char hconfig; /* hardware configuration byte */ u_char hconfig_epson; /* additional hw configuration for some Epson scanners */ u_char hwst; /* hardware status byte */ float ms_per_line; /* speed: milliseconds per scan line */ SANE_Bool nonblocking; /* wait on reads for data? */ char *sense_str; /* sense string */ char *as_str; /* additional sense string */ u_char asi1; /* first additional sense info byte */ u_char asi2; /* second additional sense info byte */ SANE_Byte chroma_offset[3]; /* chroma offsets */ SANE_Int chroma; Source *psrc; /* data source */ Source *preadersrc; /* data source for reader thread */ SANE_Option_Descriptor options[NUM_OPTS]; /* the option descriptors */ Option_Value val[NUM_OPTS]; /* the options themselves... */ SANE_Int res; /* resolution */ SANE_Int bpp; /* bit depth supported by scanner*/ SANE_Int bpp_scan; /* bit depth used for scanning */ SANE_Bool preview; /* preview mode toggle */ SANE_Bool highquality; /* high quality mode toggle */ SANE_String mode_s; /* scanning mode */ SANE_String source_s; /* scanning source */ SANE_String preview_mode_s; /* scanning mode for preview */ SANE_Fixed tlx; /* window top left x */ SANE_Fixed tly; /* window top left y */ SANE_Fixed brx; /* window bottom right x */ SANE_Fixed bry; /* window bottom right y */ int bright; /* brightness */ int contrast; /* contrast */ SANE_String predef_window; /* predefined window name */ SANE_Fixed gamma_gs; /* gamma correction value (greyscale) */ SANE_Fixed gamma_r; /* gamma correction value (red) */ SANE_Fixed gamma_g; /* gamma correction value (green) */ SANE_Fixed gamma_b; /* gamma correction value (blue) */ SANE_Int *gamma_tables; /* gamma correction vectors */ SANE_Int *gamma_table_gs; /* gamma correction vector (greyscale) */ SANE_Int *gamma_table_r; /* gamma correction vector (red) */ SANE_Int *gamma_table_g; /* gamma correction vector (green) */ SANE_Int *gamma_table_b; /* gamma correction vector (blue) */ int gamma_length; /* length of gamma vectors */ SANE_Bool halftone; /* halftone toggle */ SANE_String dither_matrix; /* the halftone dither matrix */ SANE_Bool negative; /* swap black and white */ SANE_Int threshold; /* threshold for line art */ SANE_Int rgb_lpr; /* lines per scsi read (RGB) */ SANE_Int gs_lpr; /* lines per scsi read (greyscale) */ SANE_Bool firmware_loaded; /* true if firmware was downloaded */ SANE_Word usb_vendor; /* USB vendor id */ SANE_Word usb_product; /* USB product id */ SANE_Byte frame_no; /* frame number for film scanner */ SANE_Int focus_mode; /* focus mode value */ SANE_String focus_mode_s; /* focus mode string */ SANE_Word focus; /* focus point */ }; #endif /* * $Log$ * Revision 1.42 2008/05/15 12:50:24 ellert-guest * Fix for bug #306751: sanei-thread with pthreads on 64 bit * * Revision 1.41 2006-02-02 21:28:05 oliver-guest * Corrected USB ID for Benq 310 * * Revision 1.40 2006/01/01 22:57:01 oliver-guest * Added calibration data for Benq 5150 / 5250, preliminary support for Epson Stylus CX 1500 * * Revision 1.39 2005/12/04 15:03:00 oliver-guest * Some fixes for Benq 5150 * * Revision 1.38 2005/10/31 21:08:47 oliver-guest * Distinguish between Benq 5000/5000E/5000U * * Revision 1.37 2005/10/24 19:46:40 oliver-guest * Preview and range fix for Epson 2480/2580 * * Revision 1.36 2005/09/28 21:33:11 oliver-guest * Added 16 bit option for Epson scanners (untested) * * Revision 1.35 2005/09/03 10:52:11 oliver-guest * Fixed debugging code for epson scanners * * Revision 1.34 2005/08/15 18:06:37 oliver-guest * Added support for Epson 3490/3590 (thanks to Matt Judge) * * Revision 1.33 2005/02/08 22:17:53 oliver-guest * Added IDs for Benq 5250C and 5000S * * Revision 1.32 2005/01/18 20:36:13 oliver-guest * Added ID for Benq 5250C * * Revision 1.31 2004/12/01 22:12:04 oliver-guest * Added support for Epson 1270 * * Revision 1.30 2004/09/02 20:59:12 oliver-guest * Added support for Epson 2480 * * Revision 1.29 2004/06/16 19:52:27 oliver-guest * Don't enforce even number of URB packages on 1212u_2. Fixes bug #300753. * * Revision 1.28 2004/04/08 21:53:10 oliver-guest * Use sanei_thread in snapscan backend * * Revision 1.27 2004/03/22 00:00:40 oliver-guest * Added detection for Epson 660 by USB ID since new models use new ID strings * * Revision 1.26 2003/10/21 20:43:25 oliver-guest * Bugfixes for SnapScan backend * * Revision 1.25 2003/10/07 19:41:34 oliver-guest * Updates for Epson Perfection 1670 * * Revision 1.24 2003/10/07 18:29:20 oliver-guest * Initial support for Epson 1670, minor bugfix * * Revision 1.23 2003/09/12 16:10:33 hmg-guest * Moved union Option_Value from backend header files to sanei_backend.h. No need * to copy it over and over again. Changed header inclusion order in backend * files to include backend.h after sanei_backend.h. Based on a patch from stef * . * * Revision 1.22 2003/08/19 21:05:08 oliverschwartz * Scanner ID cleanup * * Revision 1.21 2003/04/30 20:49:40 oliverschwartz * SnapScan backend 1.4.26 * * Revision 1.38 2003/04/30 20:42:22 oliverschwartz * Added support for Agfa Arcus 1200 (supplied by Valtteri Vuorikoski) * * Revision 1.37 2003/02/05 22:11:11 oliverschwartz * Added Epson Perfection 660 * * Revision 1.36 2003/01/08 21:16:36 oliverschwartz * Added support for Acer / Benq 310U * * Revision 1.35 2002/12/10 20:14:12 oliverschwartz * Enable color offset correction for SnapScan300 * * Revision 1.34 2002/10/12 10:40:48 oliverschwartz * Added support for Snapscan e10 * * Revision 1.33 2002/09/24 16:07:47 oliverschwartz * Added support for Benq 5000 * * Revision 1.32 2002/07/12 22:22:47 oliverschwartz * Correct driver description for 4300_2 * * Revision 1.31 2002/04/27 14:44:27 oliverschwartz * - Remove SCSI debug options * * Revision 1.30 2002/04/23 22:51:00 oliverschwartz * Cleanup, support for ADF * * Revision 1.29 2002/03/24 12:14:34 oliverschwartz * Add Snapcan_Driver_desc * * Revision 1.28 2002/01/23 20:38:20 oliverschwartz * Fix model ID for e42 * Improve recognition of Acer 320U * * Revision 1.27 2002/01/06 18:34:02 oliverschwartz * Added support for Snapscan e42 thanks to Yari Ad� Petralanda * * Revision 1.26 2001/12/20 23:18:01 oliverschwartz * Remove tmpfname * * Revision 1.25 2001/12/18 18:28:35 oliverschwartz * Removed temporary file * * Revision 1.24 2001/12/12 19:44:59 oliverschwartz * Clean up CVS log * * Revision 1.23 2001/11/25 18:51:41 oliverschwartz * added support for SnapScan e52 thanks to Rui Lopes * * Revision 1.22 2001/11/16 20:56:47 oliverschwartz * additional identification string for e26 added * * Revision 1.21 2001/11/16 20:28:35 oliverschwartz * add support for Snapscan e26 * * Revision 1.20 2001/11/16 20:23:16 oliverschwartz * Merge with sane-1.0.6 * - Check USB vendor IDs to avoid hanging scanners * - fix bug in dither matrix computation * * Revision 1.19 2001/10/11 14:02:10 oliverschwartz * Distinguish between e20/e25 and e40/e50 * * Revision 1.18 2001/10/10 10:11:10 oliverschwartz * Add support for Snapscan e25 thanks to Rodolphe Suescun * * Revision 1.17 2001/10/08 18:22:02 oliverschwartz * - Disable quality calibration for Acer Vuego 310F * - Use sanei_scsi_max_request_size as scanner buffer size * for SCSI devices * - Added new devices to snapscan.desc * * Revision 1.16 2001/09/28 13:39:16 oliverschwartz * - Added "Snapscan 300" ID string * - cleanup * - more debugging messages in snapscan-sources.c * * Revision 1.15 2001/09/18 15:01:07 oliverschwartz * - Read scanner id string again after firmware upload * to indentify correct model * - Make firmware upload work for AGFA scanners * - Change copyright notice * * Revision 1.14 2001/09/17 10:01:08 sable * Added model AGFA 1236U * * Revision 1.13 2001/09/09 20:39:52 oliverschwartz * add identification for 620ST+ * * Revision 1.12 2001/09/09 18:06:32 oliverschwartz * add changes from Acer (new models; automatic firmware upload for USB scanners); fix distorted colour scans after greyscale scans (call set_window only in sane_start); code cleanup * * Revision 1.11 2001/04/10 12:38:21 sable * Adding e20 support thanks to Steffen Hbner * * Revision 1.10 2001/04/10 11:04:31 sable * Adding support for snapscan e40 an e50 thanks to Giuseppe Tanzilli * * Revision 1.9 2001/03/17 22:53:21 sable * Applying Mikael Magnusson patch concerning Gamma correction * Support for 1212U_2 * * Revision 1.8 2000/11/10 01:01:59 sable * USB (kind of) autodetection * * Revision 1.7 2000/11/01 01:26:43 sable * Support for 1212U * * Revision 1.6 2000/10/28 14:06:35 sable * Add support for Acer300f * * Revision 1.5 2000/10/15 17:54:58 cbagwell * Adding USB files for optional USB compiles. * * Revision 1.4 2000/10/13 03:50:27 cbagwell * Updating to source from SANE 1.0.3. Calling this versin 1.1 * * Revision 1.3 2000/08/12 15:09:37 pere * Merge devel (v1.0.3) into head branch. * * Revision 1.1.1.1.2.2 2000/07/13 04:47:50 pere * New snapscan backend version dated 20000514 from Steve Underwood. * * Revision 1.2.1 2000/05/14 13:30:20 coppice * Some reformatting a minor tidying. * * Revision 1.2 2000/03/05 13:55:21 pere * Merged main branch with current DEVEL_1_9. * * Revision 1.1.1.1.2.1 1999/09/15 18:20:02 charter * Early version 1.0 snapscan.h * * Revision 2.2 1999/09/09 18:25:02 charter * Checkpoint. Removed references to snapscan-310.c stuff using * "#ifdef OBSOLETE". * * Revision 2.1 1999/09/08 03:05:05 charter * Start of branch 2; same as 1.30. * * Revision 1.30 1999/09/07 20:54:07 charter * Changed expected_data_len to bytes_remaining. * * Revision 1.29 1999/09/02 05:29:46 charter * Fixed the spelling of Petter's name (again). * * Revision 1.28 1999/09/02 05:28:50 charter * Added Gary Plewa's name to the list of contributors. * * Revision 1.27 1999/09/02 04:48:25 charter * Added models and strings for the Acer PRISA 620s (thanks to Gary Plewa). * * Revision 1.26 1999/09/02 02:01:46 charter * Checking in rev 1.26 (for backend version 0.7) again. * This is part of the recovery from the great disk crash of Sept 1, 1999. * * Revision 1.26 1999/07/09 20:54:34 charter * Modifications for SnapScan 1236s (Petter Reinholdsten). * * Revision 1.25 1998/12/16 18:40:53 charter * Commented the INOPERATIVE define to get rid of spurious brightness * and contrast controls accidentally reintroduced previously. * * Revision 1.24 1998/09/07 06:04:58 charter * Merged in Wolfgang Goeller's changes (Vuego 310S, bugfixes). * * Revision 1.23 1998/05/11 17:03:22 charter * Added Mikko's threshold stuff * * Revision 1.22 1998/03/10 23:43:05 eblot * Changing 310/600 models support (structure) * * Revision 1.21 1998/03/08 14:24:43 eblot * Debugging * * Revision 1.20 1998/02/15 21:55:03 charter * From Emmanuel Blot: * Added rgb ring buffer to handle snapscan 310 data specs. * * Revision 1.19 1998/02/06 02:29:52 charter * Added SnapScan_Mode and SnapScan_Model enums. * * Revision 1.18 1998/01/31 23:59:51 charter * Changed window coordinates type to SANE_Fixed (what it should be * for a length). * * Revision 1.17 1998/01/30 19:18:41 charter * Added sense_str and as_str to SnapScan_Scanner; these are intended to * be set by the sense handler. * * Revision 1.16 1998/01/30 11:02:17 charter * Added opens to the SnapScan_Scanner to support open_scanner() and * close_scanner(). * * Revision 1.15 1998/01/25 09:57:32 charter * Added more SCSI command options and a group for them. * * Revision 1.14 1998/01/25 08:50:49 charter * Added preview mode option. * * Revision 1.13 1998/01/25 02:24:31 charter * Added OPT_NEGATIVE and the extra sense data bytes. * * Revision 1.12 1998/01/24 05:14:56 charter * Added stuff for RGB gamma correction and for BW mode halftoning. * * Revision 1.11 1998/01/23 13:02:45 charter * Added rgb_lpr and gs_lpr so the user can tune scanning performance. * * Revision 1.10 1998/01/23 07:39:08 charter * Reindented using GNU convention at David Mosberger-Tang's request. * Added ms_per_line to SnapScan_Scanner. * * Revision 1.9 1998/01/22 05:14:23 charter * The bit depth option has been replaced with a mode option. We support * full color, greyscale and lineart modes. * * Revision 1.8 1998/01/21 20:40:13 charter * Added copyright info; added the new SnapScan_State type and * replaced the scanning member of SnapScan_Scanner with a state * member. This is for supporting cancellation. * * Revision 1.7 1998/01/21 11:05:20 charter * Inoperative options now #defined out. * * Revision 1.6 1997/11/26 15:40:24 charter * Brightness and contrast added by Michel. * * Revision 1.5 1997/11/12 12:52:16 charter * Added OPT_INQUIRY for the inquiry button. * * Revision 1.4 1997/11/10 05:51:45 charter * Added stuff for the child reader process and pipe. * * Revision 1.3 1997/11/03 03:16:46 charter * Added buffers and window parameter variables to the scanner structure. * * Revision 1.2 1997/10/14 05:59:53 charter * Basic options and structures added. * * Revision 1.1 1997/10/13 02:25:54 charter * Initial revision * */ sane-backends-1.0.27/backend/cardscan.conf.in0000664000175000017500000000105012775312260015644 00000000000000# For scanners connected via USB on a known device (kernel driver): #usb /dev/usb/scanner0 # For scanners connected via USB using vendor and device ids (libusb): #usb VENDORID PRODUCTID # NOTE: if you have to add your device here- please send the id and model # to the author via email, so it can be included in next version. kitno455 at # gmail dot com - with cardscan in the subject line # Corex Cardscan 800c usb 0x08f0 0x0005 # Sanford Cardscan 800c usb 0x0451 0x6250 # Corex Cardscan 600c has_cal_buffer 0 lines_per_block 1 usb 0x08f0 0x0002 sane-backends-1.0.27/backend/sm3600.c0000664000175000017500000005304412775312261013721 00000000000000/* sane - Scanner Access Now Easy. (C) Marian Matthias Eichholz 2001 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements SANE backend for Microtek scanners with M011 USB chip like the Microtek ScanMaker 3600, 3700 and 3750. */ /* ====================================================================== sm3600.c SANE backend master module (C) Marian Matthias Eichholz 2001 Start: 2.4.2001 ====================================================================== */ #include "../include/sane/config.h" #include #include #include #define BUILD 6 #ifndef BACKEND_NAME #define BACKEND_NAME sm3600 #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" #undef HAVE_LIBUSB_LEGACY /* prevent inclusion of scantool.h */ #define SCANTOOL_H /* make no real function export, since we include the modules */ #define __SM3600EXPORT__ static /* if defined, *before* sm3600.h inclusion */ #define SM3600_SUPPORT_EXPOSURE #include "sm3600.h" static unsigned long ulDebugMask; static int num_devices; static TDevice *pdevFirst; static TInstance *pinstFirst; /* ====================================================================== */ #include "sm3600-scanutil.c" #include "sm3600-scanusb.c" #include "sm3600-scanmtek.c" #include "sm3600-homerun.c" #include "sm3600-gray.c" #include "sm3600-color.c" /* ====================================================================== Initialise SANE options ====================================================================== */ typedef enum { optCount, optGroupMode, optMode, optResolution, #ifdef SM3600_SUPPORT_EXPOSURE optBrightness, optContrast, #endif optPreview, optGrayPreview, optGroupGeometry,optTLX, optTLY, optBRX, optBRY, optGroupEnhancement, optGammaY, optGammaR,optGammaG,optGammaB, optLast } TOptionIndex; static const SANE_String_Const aScanModes[]= { "color", "gray", "lineart", "halftone", NULL }; static const SANE_Range rangeXmm = { SANE_FIX(0), SANE_FIX(220), SANE_FIX(0.1) }; static const SANE_Range rangeYmm = { SANE_FIX(0), SANE_FIX(300), SANE_FIX(0.1) }; #ifdef SM3600_SUPPORT_EXPOSURE static const SANE_Range rangeLumi = { SANE_FIX(-100.0), SANE_FIX(100.0), SANE_FIX(1.0) }; #endif static const SANE_Range rangeGamma = { 0, 4095, 1 }; static const SANE_Int setResolutions[] = { 5, 75,100,200,300,600 }; static SANE_Status InitOptions(TInstance *this) { TOptionIndex iOpt; if (optLast!=NUM_OPTIONS) { DBG(1,"NUM_OPTIONS does not fit!"); return SANE_STATUS_INVAL; } memset(this->aoptDesc,0,sizeof(this->aoptDesc)); memset(this->aoptVal,0,sizeof(this->aoptVal)); InitGammaTables(this,0,0); for (iOpt=optCount; iOpt!=optLast; iOpt++) { static char *achNamesXY[]= { SANE_NAME_SCAN_TL_X, SANE_NAME_SCAN_TL_Y, SANE_NAME_SCAN_BR_X, SANE_NAME_SCAN_BR_Y }; static char *achTitlesXY[]= { SANE_TITLE_SCAN_TL_X, SANE_TITLE_SCAN_TL_Y, SANE_TITLE_SCAN_BR_X, SANE_TITLE_SCAN_BR_Y }; static char *achDescXY[]= { SANE_DESC_SCAN_TL_X, SANE_DESC_SCAN_TL_Y, SANE_DESC_SCAN_BR_X, SANE_DESC_SCAN_BR_Y }; static double afFullBed[] = { 22.0,30.0, 50.0, 80.0 }; /* TODO: calculate exactly! */ static const SANE_Range *aRangesXY[] = { &rangeXmm,&rangeYmm,&rangeXmm,&rangeYmm }; SANE_Option_Descriptor *pdesc; Option_Value *pval; /* shorthands */ pdesc=this->aoptDesc+iOpt; pval=this->aoptVal+iOpt; /* default */ pdesc->size=sizeof(SANE_Word); pdesc->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* Some hints: *every* field needs a constraint, elseway there will be a warning. */ switch (iOpt) { case optCount: pdesc->title =SANE_TITLE_NUM_OPTIONS; pdesc->desc =SANE_DESC_NUM_OPTIONS; pdesc->type =SANE_TYPE_INT; pdesc->cap =SANE_CAP_SOFT_DETECT; pval->w =(SANE_Word)optLast; break; case optGroupMode: pdesc->title="Mode"; pdesc->desc =""; pdesc->type = SANE_TYPE_GROUP; pdesc->cap = SANE_CAP_ADVANCED; break; case optMode: pdesc->name =SANE_NAME_SCAN_MODE; pdesc->title =SANE_TITLE_SCAN_MODE; pdesc->desc ="Select the scan mode"; pdesc->type =SANE_TYPE_STRING; pdesc->size =20; pdesc->constraint_type = SANE_CONSTRAINT_STRING_LIST; pdesc->constraint.string_list = aScanModes; pval->s = strdup(aScanModes[color]); break; case optResolution: pdesc->name =SANE_NAME_SCAN_RESOLUTION; pdesc->title =SANE_TITLE_SCAN_RESOLUTION; pdesc->desc =SANE_DESC_SCAN_RESOLUTION; pdesc->type =SANE_TYPE_INT; pdesc->unit =SANE_UNIT_DPI; pdesc->constraint_type = SANE_CONSTRAINT_WORD_LIST; pdesc->constraint.word_list = setResolutions; pval->w =75; break; #ifdef SM3600_SUPPORT_EXPOSURE case optBrightness: pdesc->name =SANE_NAME_BRIGHTNESS; pdesc->title =SANE_TITLE_BRIGHTNESS; pdesc->desc =SANE_DESC_BRIGHTNESS; pdesc->type =SANE_TYPE_FIXED; pdesc->unit =SANE_UNIT_PERCENT; pdesc->constraint_type =SANE_CONSTRAINT_RANGE; pdesc->constraint.range=&rangeLumi; pval->w =SANE_FIX(0); break; case optContrast: pdesc->name =SANE_NAME_CONTRAST; pdesc->title =SANE_TITLE_CONTRAST; pdesc->desc =SANE_DESC_CONTRAST; pdesc->type =SANE_TYPE_FIXED; pdesc->unit =SANE_UNIT_PERCENT; pdesc->constraint_type =SANE_CONSTRAINT_RANGE; pdesc->constraint.range=&rangeLumi; pval->w =SANE_FIX(0); break; #endif case optPreview: pdesc->name =SANE_NAME_PREVIEW; pdesc->title =SANE_TITLE_PREVIEW; pdesc->desc =SANE_DESC_PREVIEW; pdesc->type =SANE_TYPE_BOOL; pval->w =SANE_FALSE; break; case optGrayPreview: pdesc->name =SANE_NAME_GRAY_PREVIEW; pdesc->title =SANE_TITLE_GRAY_PREVIEW; pdesc->desc =SANE_DESC_GRAY_PREVIEW; pdesc->type =SANE_TYPE_BOOL; pval->w =SANE_FALSE; break; case optGroupGeometry: pdesc->title="Geometry"; pdesc->desc =""; pdesc->type = SANE_TYPE_GROUP; pdesc->constraint_type=SANE_CONSTRAINT_NONE; pdesc->cap = SANE_CAP_ADVANCED; break; case optTLX: case optTLY: case optBRX: case optBRY: pdesc->name =achNamesXY[iOpt-optTLX]; pdesc->title =achTitlesXY[iOpt-optTLX]; pdesc->desc =achDescXY[iOpt-optTLX]; pdesc->type =SANE_TYPE_FIXED; pdesc->unit =SANE_UNIT_MM; /* arghh */ pdesc->constraint_type =SANE_CONSTRAINT_RANGE; pdesc->constraint.range=aRangesXY[iOpt-optTLX]; pval->w =SANE_FIX(afFullBed[iOpt-optTLX]); break; case optGroupEnhancement: pdesc->title="Enhancement"; pdesc->desc =""; pdesc->type = SANE_TYPE_GROUP; pdesc->constraint_type=SANE_CONSTRAINT_NONE; pdesc->cap = SANE_CAP_ADVANCED; break; case optGammaY: pdesc->name = SANE_NAME_GAMMA_VECTOR; pdesc->title = SANE_TITLE_GAMMA_VECTOR; pdesc->desc = SANE_DESC_GAMMA_VECTOR; pdesc->type = SANE_TYPE_INT; pdesc->unit = SANE_UNIT_NONE; pdesc->size = 4096*sizeof(SANE_Int); pdesc->constraint_type = SANE_CONSTRAINT_RANGE; pdesc->constraint.range = &rangeGamma; pval->wa = this->agammaY; break; case optGammaR: pdesc->name = SANE_NAME_GAMMA_VECTOR_R; pdesc->title = SANE_TITLE_GAMMA_VECTOR_R; pdesc->desc = SANE_DESC_GAMMA_VECTOR_R; pdesc->type = SANE_TYPE_INT; pdesc->unit = SANE_UNIT_NONE; pdesc->size = 4096*sizeof(SANE_Int); pdesc->constraint_type = SANE_CONSTRAINT_RANGE; pdesc->constraint.range = &rangeGamma; pval->wa = this->agammaR; break; case optGammaG: pdesc->name = SANE_NAME_GAMMA_VECTOR_G; pdesc->title = SANE_TITLE_GAMMA_VECTOR_G; pdesc->desc = SANE_DESC_GAMMA_VECTOR_G; pdesc->type = SANE_TYPE_INT; pdesc->unit = SANE_UNIT_NONE; pdesc->size = 4096*sizeof(SANE_Int); pdesc->constraint_type = SANE_CONSTRAINT_RANGE; pdesc->constraint.range = &rangeGamma; pval->wa = this->agammaG; break; case optGammaB: pdesc->name = SANE_NAME_GAMMA_VECTOR_B; pdesc->title = SANE_TITLE_GAMMA_VECTOR_B; pdesc->desc = SANE_DESC_GAMMA_VECTOR_B; pdesc->type = SANE_TYPE_INT; pdesc->unit = SANE_UNIT_NONE; pdesc->size = 4096*sizeof(SANE_Int); pdesc->constraint_type = SANE_CONSTRAINT_RANGE; pdesc->constraint.range = &rangeGamma; pval->wa = this->agammaB; break; case optLast: /* not reached */ break; } } return SANE_STATUS_GOOD; } static SANE_Status RegisterSaneDev (TModel model, SANE_String_Const szName) { TDevice * q; errno = 0; q = malloc (sizeof (*q)); if (!q) return SANE_STATUS_NO_MEM; memset (q, 0, sizeof (*q)); /* clear every field */ q->szSaneName = strdup (szName); q->sane.name = (SANE_String_Const) q->szSaneName; q->sane.vendor = "Microtek"; q->sane.model = "ScanMaker 3600"; q->sane.type = "flatbed scanner"; q->model=model; ++num_devices; q->pNext = pdevFirst; /* link backwards */ pdevFirst = q; return SANE_STATUS_GOOD; } static SANE_Status sm_usb_attach (SANE_String_Const dev_name) { int fd; SANE_Status err; SANE_Word v, p; TModel model; err = sanei_usb_open(dev_name, &fd); if (err) return err; err = sanei_usb_get_vendor_product (fd, &v, &p); if (err) { sanei_usb_close (fd); return err; } DBG (DEBUG_JUNK, "found dev %04X/%04X, %s\n", v, p, dev_name); model = GetScannerModel (v, p); if (model != unknown) RegisterSaneDev (model, dev_name); sanei_usb_close(fd); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int *version_code, SANE_Auth_Callback authCB) { int i; DBG_INIT(); authCB=authCB; /* compiler */ DBG(DEBUG_VERBOSE,"SM3600 init\n"); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG(DEBUG_VERBOSE,"SM3600 version: %x\n", SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, BUILD)); } pdevFirst=NULL; sanei_usb_init(); for (i = 0; aScanners[i].idProduct; i++) { sanei_usb_find_devices(SCANNER_VENDOR, aScanners[i].idProduct, sm_usb_attach); } return SANE_STATUS_GOOD; } static const SANE_Device ** devlist = 0; /* only pseudo-statical */ void sane_exit (void) { TDevice *dev, *pNext; /* free all bound resources and instances */ while (pinstFirst) sane_close((SANE_Handle)pinstFirst); /* free all resources */ /* free all device descriptors */ for (dev = pdevFirst; dev; dev = pNext) { pNext = dev->pNext; free (dev->szSaneName); free (dev); } if (devlist) free(devlist); devlist=NULL; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { TDevice *dev; int i; if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = pdevFirst; i < num_devices; dev = dev->pNext) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle *handle) { TDevice *pdev; TInstance *this; DBG(DEBUG_VERBOSE,"opening %s\n",devicename); if (devicename[0]) /* selected */ { for (pdev=pdevFirst; pdev; pdev=pdev->pNext) { DBG(DEBUG_VERBOSE,"%s<>%s\n",devicename, pdev->sane.name); if (!strcmp(devicename,pdev->sane.name)) break; } /* no dynamic post-registration */ } else pdev=pdevFirst; if (!pdev) return SANE_STATUS_INVAL; this = (TInstance*) calloc(1,sizeof(TInstance)); if (!this) return SANE_STATUS_NO_MEM; *handle = (SANE_Handle)this; ResetCalibration(this); /* do not release memory */ this->pNext=pinstFirst; /* register open handle */ pinstFirst=this; this->model=pdev->model; /* memorize model */ /* open and prepare USB scanner handle */ if (sanei_usb_open (devicename, &this->hScanner) != SANE_STATUS_GOOD) return SetError (this, SANE_STATUS_IO_ERROR, "cannot open scanner device"); this->quality=fast; return InitOptions(this); } void sane_close (SANE_Handle handle) { TInstance *this,*pParent,*p; this=(TInstance*)handle; DBG(DEBUG_VERBOSE,"closing scanner\n"); if (this->hScanner) { if (this->state.bScanning) EndScan(this); sanei_usb_close(this->hScanner); this->hScanner=-1; } ResetCalibration(this); /* release calibration data */ /* unlink active device entry */ pParent=NULL; for (p=pinstFirst; p; p=p->pNext) { if (p==this) break; pParent=p; } if (!p) { DBG(1,"invalid handle in close()\n"); return; } /* delete instance from instance list */ if (pParent) pParent->pNext=this->pNext; else pinstFirst=this->pNext; /* NULL with last entry */ /* free resources */ if (this->pchPageBuffer) free(this->pchPageBuffer); if (this->szErrorReason) { DBG(DEBUG_VERBOSE,"Error status: %d, %s", this->nErrorState, this->szErrorReason); free(this->szErrorReason); } free(this); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int iOpt) { TInstance *this=(TInstance*)handle; if (iOptaoptDesc+iOpt; return NULL; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int iOpt, SANE_Action action, void *pVal, SANE_Int *pnInfo) { SANE_Word cap; SANE_Status rc; TInstance *this; this=(TInstance*)handle; rc=SANE_STATUS_GOOD; if (pnInfo) *pnInfo=0; if (this->state.bScanning) return SANE_STATUS_DEVICE_BUSY; if (iOpt>=NUM_OPTIONS) return SANE_STATUS_INVAL; cap=this->aoptDesc[iOpt].cap; switch (action) { /* ------------------------------------------------------------ */ case SANE_ACTION_GET_VALUE: switch ((TOptionIndex)iOpt) { case optCount: case optPreview: case optGrayPreview: case optResolution: #ifdef SM3600_SUPPORT_EXPOSURE case optBrightness: case optContrast: #endif case optTLX: case optTLY: case optBRX: case optBRY: *(SANE_Word*)pVal = this->aoptVal[iOpt].w; break; case optMode: strcpy(pVal,this->aoptVal[iOpt].s); break; case optGammaY: case optGammaR: case optGammaG: case optGammaB: DBG(DEBUG_INFO,"getting gamma\n"); memcpy(pVal,this->aoptVal[iOpt].wa, this->aoptDesc[iOpt].size); break; default: return SANE_STATUS_INVAL; } break; /* ------------------------------------------------------------ */ case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE(cap)) return SANE_STATUS_INVAL; rc=sanei_constrain_value(this->aoptDesc+iOpt,pVal,pnInfo); if (rc!=SANE_STATUS_GOOD) return rc; switch ((TOptionIndex)iOpt) { case optResolution: case optTLX: case optTLY: case optBRX: case optBRY: if (pnInfo) (*pnInfo) |= SANE_INFO_RELOAD_PARAMS; /* fall through side effect free */ #ifdef SM3600_SUPPORT_EXPOSURE case optBrightness: case optContrast: #endif case optPreview: case optGrayPreview: this->aoptVal[iOpt].w = *(SANE_Word*)pVal; break; case optMode: if (pnInfo) (*pnInfo) |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; strcpy(this->aoptVal[iOpt].s,pVal); break; case optGammaY: case optGammaR: case optGammaG: case optGammaB: DBG(DEBUG_INFO,"setting gamma #%d\n",iOpt); memcpy(this->aoptVal[iOpt].wa, pVal, this->aoptDesc[iOpt].size); break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_AUTO: return SANE_STATUS_UNSUPPORTED; } /* switch action */ return rc; /* normally GOOD */ } static SANE_Status SetupInternalParameters(TInstance *this) { int i; this->param.res=(int)this->aoptVal[optResolution].w; #ifdef SM3600_SUPPORT_EXPOSURE this->param.nBrightness=(int)(this->aoptVal[optBrightness].w>>SANE_FIXED_SCALE_SHIFT); this->param.nContrast=(int)(this->aoptVal[optContrast].w>>SANE_FIXED_SCALE_SHIFT); #else this->param.nBrightness=0; this->param.nContrast=0; #endif this->param.x=(int)(SANE_UNFIX(this->aoptVal[optTLX].w)*1200.0/25.4); this->param.y=(int)(SANE_UNFIX(this->aoptVal[optTLY].w)*1200.0/25.4); this->param.cx=(int)(SANE_UNFIX(this->aoptVal[optBRX].w-this->aoptVal[optTLX].w)*1200.0/25.4)+1; this->param.cy=(int)(SANE_UNFIX(this->aoptVal[optBRY].w-this->aoptVal[optTLY].w)*1200.0/25.4)+1; for (i=0; aScanModes[i]; i++) if (!strcasecmp(this->aoptVal[optMode].s,aScanModes[i])) { this->mode=(TMode)i; break; } DBG(DEBUG_INFO,"mode=%d, res=%d, BC=[%d,%d], xywh=[%d,%d,%d,%d]\n", this->mode, this->param.res, this->param.nBrightness, this->param.nContrast, this->param.x,this->param.y,this->param.cx,this->param.cy); return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *p) { /* extremly important for xscanimage */ TInstance *this; this=(TInstance*)handle; SetupInternalParameters(this); GetAreaSize(this); p->pixels_per_line=this->state.cxPixel; /* TODO: we need a more stable cyPixel prediction */ p->lines=this->state.cyPixel; p->last_frame=SANE_TRUE; switch (this->mode) { case color: p->format=SANE_FRAME_RGB; p->depth=8; p->bytes_per_line=p->pixels_per_line*3; break; case gray: p->format=SANE_FRAME_GRAY; p->depth=8; p->bytes_per_line=p->pixels_per_line; break; case halftone: case line: p->format=SANE_FRAME_GRAY; p->depth=1; p->bytes_per_line=(p->pixels_per_line+7)/8; break; } DBG(DEBUG_INFO,"getting parameters (%d,%d)...\n",p->bytes_per_line,p->lines); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { TInstance *this; SANE_Status rc; this=(TInstance*)handle; DBG(DEBUG_VERBOSE,"starting scan...\n"); if (this->state.bScanning) return SANE_STATUS_DEVICE_BUSY; rc=SetupInternalParameters(this); this->state.bCanceled=false; if (!rc) rc=DoInit(this); /* oopsi, we should initalise :-) */ if (!rc && !this->bOptSkipOriginate) rc=DoOriginate(this,true); if (!rc) rc=DoJog(this,this->calibration.yMargin); if (rc) return rc; this->state.bEOF=false; switch (this->mode) { case color: rc=StartScanColor(this); break; default: rc=StartScanGray(this); break; } if (this->state.bCanceled) return SANE_STATUS_CANCELLED; return rc; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte *puchBuffer, SANE_Int cchMax, SANE_Int *pcchRead) { SANE_Status rc; TInstance *this; this=(TInstance*)handle; DBG(DEBUG_INFO,"reading chunk %d...\n",(int)cchMax); *pcchRead=0; if (this->state.bEOF) return SANE_STATUS_EOF; rc=ReadChunk(this,puchBuffer,cchMax,pcchRead); DBG(DEBUG_INFO,"... line %d (%d/%d)...\n",this->state.iLine,*pcchRead,rc); switch (rc) { case SANE_STATUS_EOF: this->state.bEOF=true; /* flag EOF on next read() */ rc=SANE_STATUS_GOOD; /* we do not flag THIS block! */ break; case SANE_STATUS_GOOD: if (!*pcchRead) rc=SANE_STATUS_EOF; break; default: break; } return rc; } void sane_cancel (SANE_Handle handle) { TInstance *this; this=(TInstance*)handle; DBG(DEBUG_VERBOSE,"cancel called...\n"); if (this->state.bScanning) { this->state.bCanceled=true; if (this->state.bEOF) /* regular (fast) cancel */ { DBG(DEBUG_INFO,"regular end cancel\n"); EndScan(this); DoJog(this,-this->calibration.yMargin); } else { /* since Xsane does not continue scanning, we cannot defer cancellation */ DBG(DEBUG_INFO,"hard cancel called...\n"); CancelScan(this); } } } SANE_Status sane_set_io_mode(SANE_Handle h, SANE_Bool m) { h=h; if (m==SANE_TRUE) /* no non-blocking-mode */ return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd(SANE_Handle handle, SANE_Int *fd) { handle=handle; fd=fd; return SANE_STATUS_UNSUPPORTED; /* we have no file IO */ } sane-backends-1.0.27/backend/rts8891.conf.in0000664000175000017500000000026712112021330015215 00000000000000# rts8891.conf: Configuration file for the rts8891 backend # MODEL # HP scanjet 4400c usb 0x03f0 0x0705 # HP scanjet 4470c usb 0x03f0 0x0805 # UMAX Astra 4400/4450 usb 0x1606 0x0070 sane-backends-1.0.27/backend/plustek-pp_dac.c0000664000175000017500000023116312775312261015704 00000000000000/* @file plustek-pp_dac.c * @brief all the shading function formerly found in shading.c. * don't ask me why I called this file dac.c... * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2004 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - no changes * - 0.33 - added some comments * - 0.34 - slight changes * - 0.35 - removed SetInitialGainRAM from structure pScanData * - 0.36 - added dacP96001WaitForShading and changed dacP96WaitForShading to * dacP96003WaitForShading * - changes, due to define renaming * - 0.37 - removed dacP98FillShadingDarkToShadingRegister() * - removed // comments * - some code cleanup * - 0.38 - added P12 stuff * - 0.39 - no changes * - 0.40 - disabled the A3I stuff * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /************************** local definitions ********************************/ /***************************** global vars ***********************************/ static const Byte a_bCorrectTimesTable[4] = {0, 1, 2, 4}; static ULong dwADCPipeLine = 4 * 4; static ULong dwReadyLen; /*************************** local functions *********************************/ /** */ static void dacP98AdjustGainAverage( pScanData ps ) { pUChar pDest, pSrce; ULong dw, dw1; UShort wSum; pDest = pSrce = ps->pScanBuffer1; for (dw1 = 0; dw1 < (2560 * 3) / 16; dw1++, pDest++) { for (dw = 0, wSum = 0; dw < 16; dw++, pSrce++) wSum += *pSrce; *pDest = wSum / 16; } } /** */ static void dacP98FillDarkDAC( pScanData ps ) { IODataRegisterToDAC( ps, 0x20, ps->bRedDAC ); IODataRegisterToDAC( ps, 0x21, ps->bGreenDAC ); IODataRegisterToDAC( ps, 0x22, ps->bBlueDAC ); } /** */ static void dacP98SetReadFBKRegister( pScanData ps ) { IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE + _SCAN_1ST_AVERAGE; IOSelectLampSource( ps ); IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); ps->AsicReg.RD_Motor0Control = _MotorOn; ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; ps->AsicReg.RD_Origin = 4; ps->AsicReg.RD_Pixels = 512; ps->AsicReg.RD_Motor1Control = 0; ps->AsicReg.RD_Motor0Control = 0; ps->AsicReg.RD_ModelControl = _LED_CONTROL + _LED_ACTIVITY; if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { ps->AsicReg.RD_Dpi = 300; ps->AsicReg.RD_ModelControl += _ModelDpi300; } else { ps->AsicReg.RD_Dpi = 600; ps->AsicReg.RD_ModelControl += _ModelDpi600; } } /** */ static UShort dacP98CalDarkOff( pScanData ps, UShort wChDarkOff, UShort wDACCompareHigh, UShort wDACOffset ) { UShort wTemp; if ((_CCD_518 == ps->Device.bCCDID) || (_CCD_535 == ps->Device.bCCDID)) { wTemp = wChDarkOff + wDACOffset; } else { if (_CCD_3797 == ps->Device.bCCDID) { if (wChDarkOff > wDACOffset) { wTemp = wChDarkOff - wDACOffset; } else { wTemp = 0; } } else { if (wChDarkOff > wDACCompareHigh) { wTemp = wChDarkOff - wDACCompareHigh; } else { wTemp = 0; } } } return wTemp; } /** */ static Bool dacP98AdjustDAC( UShort DarkOff, UShort wHigh, UShort wLow, pUChar pbReg, Bool *fDACStopFlag ) { if (DarkOff > wHigh) { if ((DarkOff - wHigh) > 10) { if ((DarkOff - wHigh) > 2550) *pbReg += ((DarkOff - wHigh) / 20); else *pbReg += ((DarkOff - wHigh) / 10); } else *pbReg += 1; if (!(*pbReg)) *pbReg = 0xff; *fDACStopFlag = _FALSE; return _FALSE; } else { if (DarkOff < wLow) { if (DarkOff > 0) *pbReg -= 2; else *pbReg -= 10; *fDACStopFlag = _FALSE; return _FALSE; } else return _TRUE; } } /** */ static Bool dacP98CheckChannelDarkLevel( pScanData ps ) { Bool fDACStopFlag = _TRUE; dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Red, ps->Shade.pCcdDac->DarkCmpHi.Colors.Red, ps->Shade.pCcdDac->DarkCmpLo.Colors.Red, &ps->bRedDAC, &fDACStopFlag ); dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Green, ps->Shade.pCcdDac->DarkCmpHi.Colors.Green, ps->Shade.pCcdDac->DarkCmpLo.Colors.Green, &ps->bGreenDAC, &fDACStopFlag ); dacP98AdjustDAC( ps->Shade.DarkOffset.Colors.Blue, ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue, ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue, &ps->bBlueDAC, &fDACStopFlag ); return fDACStopFlag; } /** Average left offset 30, 16 pixels as each color's dark level */ static void dacP98FillChannelDarkLevelControl( pScanData ps ) { DataPointer p; ULong dwPos, dw, dwSum; if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { dwPos = 0x10 * 3; } else { dwPos = 0x20 * 2; } for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos), dwSum = 0, dw = 16; dw; dw--, p.pw++) { dwSum += (ULong)(*p.pw); } ps->Shade.DarkOffset.Colors.Red = (UShort)(dwSum / 16); for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos + 1024), dwSum = 0, dw = 16; dw; dw--, p.pw++) { dwSum += (ULong)(*p.pw); } ps->Shade.DarkOffset.Colors.Green = (UShort)(dwSum / 16); for (p.pw = (pUShort)(ps->pScanBuffer1 + dwPos + 1024 * 2), dwSum = 0, dw = 16; dw; dw--, p.pw++) { dwSum += (ULong)(*p.pw); } ps->Shade.DarkOffset.Colors.Blue = (UShort)(dwSum / 16); } /** */ static void dacP98AdjustGain( pScanData ps ) { DataPointer p; ULong dw; UShort w; Byte b[3]; pUChar pbReg[3]; dacP98AdjustGainAverage( ps ); pbReg[0] = &ps->bRedGainIndex; pbReg[1] = &ps->bGreenGainIndex; pbReg[2] = &ps->bBlueGainIndex; for (w = 0, p.pb = ps->pScanBuffer1; w < 3; w++) { for (dw = 2560 / 16, b [w] = 0; dw; dw--, p.pb++) { if (b [w] < *p.pb) b [w] = *p.pb; } if (b[w] < _GAIN_LOW) { if ((_GAIN_P98_HIGH - b[w]) < b[w]) *(pbReg[w]) += 1; else *(pbReg[w]) += 4; } else { if (b[w] > _GAIN_P98_HIGH) *(pbReg[w]) -= 1; } } } /** */ static void dacP98CheckLastGain( pScanData ps ) { DataPointer p; ULong dw; UShort w; Byte b[3]; pUChar pbReg[3]; dacP98AdjustGainAverage( ps ); pbReg[0] = &ps->bRedGainIndex; pbReg[1] = &ps->bGreenGainIndex; pbReg[2] = &ps->bBlueGainIndex; for (w = 0, p.pb = ps->pScanBuffer1; w < 3; w++) { for (dw = 2560 / 16, b [w] = 0; dw; dw--, p.pb++) { if (b[w] < *p.pb) b[w] = *p.pb; } if (b[w] > _GAIN_P98_HIGH) { *(pbReg [w]) -= 1; } } } /** */ static void dacP98FillGainInitialRestRegister( pScanData ps ) { ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegThresholdGapControl, ps->AsicReg.RD_ThresholdGapCtrl ); IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl ); ps->CloseScanPath( ps ); } /** */ static void dacP98SetInitialGainRegister( pScanData ps ) { DacP98FillGainOutDirectPort( ps ); /* R/G/B GainOut to scanner */ dacP98FillGainInitialRestRegister( ps );/* Model Control2, LED, Correct.*/ } /** Find the most ideal intensity for each color (RGB) */ static void dacP98SetRGBGainRegister( pScanData ps ) { IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeIdle ); ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; IOSelectLampSource( ps ); IOCmdRegisterToScanner( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); dacP98SetInitialGainRegister( ps ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorDirForward + _MotorHEightStep; ps->AsicReg.RD_XStepTime = ps->bSpeed4; if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi300; ps->AsicReg.RD_Origin = 32 + 60 + 4; } else { ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi600; ps->AsicReg.RD_Origin = 64 + 120 + 4; } ps->AsicReg.RD_Dpi = 300; ps->AsicReg.RD_Pixels = 2560; IOPutOnAllRegisters( ps ); } /** */ static void dacP98FillRGBMap( pUChar pBuffer ) { ULong dw, dw1; pULong pdw = (pULong)(pBuffer); for( dw = 256, dw1 = 0; dw; dw--, dw1 += 0x01010101 ) { *pdw++ = dw1; *pdw++ = dw1; *pdw++ = dw1; *pdw++ = dw1; } } /** here we download the current mapping table */ static void dacP98DownloadMapTable( pScanData ps, pUChar pBuffer ) { Byte bAddr; ULong i; IODataToRegister( ps, ps->RegScanControl, (Byte)((ps->AsicReg.RD_ScanControl & 0xfc) | _SCAN_BYTEMODE)); for( i = 3, bAddr = _MAP_ADDR_RED; i--; bAddr += _MAP_ADDR_SIZE ) { IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem ); IODataToRegister( ps, ps->RegMemoryLow, 0); IODataToRegister( ps, ps->RegMemoryHigh, bAddr ); IOMoveDataToScanner( ps, pBuffer, 4096 ); pBuffer += 4096; } IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); } /** */ static void dacP98DownloadShadingTable( pScanData ps, pUChar pBuffer, ULong size ) { IODataToRegister( ps, ps->RegModeControl, _ModeShadingMem ); IODataToRegister( ps, ps->RegMemoryLow, 0 ); IODataToRegister( ps, ps->RegMemoryHigh, 0 ); /* set 12 bits output color */ IODataToRegister( ps, ps->RegScanControl, (Byte)(ps->AsicReg.RD_ScanControl | _SCAN_12BITMODE)); /* MoveDataToShadingRam() */ IOMoveDataToScanner( ps ,pBuffer, size ); if( _ASIC_IS_98003 == ps->sCaps.AsicID ) IODataToRegister( ps, ps->RegModeControl, _ModeScan ); else IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); DacP98FillShadingDarkToShadingRegister( ps ); } /** Build a linear map for asic (this model is 12-bit scanner, there are 4096 * map entries but just generate 256 level output, so the content must be 0 to * 255), then fill the shading buffer (the first 3k), and map table (the last * 1k) to asic for R & G & B channels. * * I need pScanBuffer2 size = 5400 * 2 * 3 * pScanBuffer1 size = 256 * 16 * 2 */ static void dacP98SetInitialGainRAM( pScanData ps ) { memset( ps->pScanBuffer2, 0xff, (5400 * 2 * 3)); dacP98DownloadShadingTable( ps, ps->pScanBuffer2, (5400 * 2 * 3)); dacP98FillRGBMap( ps->pScanBuffer1 ); /* Fill 12 Bits R Map */ dacP98FillRGBMap( ps->pScanBuffer1 + 4096 ); /* Fill 12 Bits G Map */ dacP98FillRGBMap( ps->pScanBuffer1 + 8192 ); /* Fill 12 Bits B Map */ dacP98DownloadMapTable( ps, ps->pScanBuffer1 ); } /** Find the most ideal intensity for each color (RGB) */ static void dacP98AdjustRGBGain( pScanData ps ) { int bCorrectTimes; DBG( DBG_LOW, "dacP98AdjustRGBGain()\n" ); ps->OpenScanPath( ps ); dacP98SetInitialGainRAM( ps ); /* set shading ram and read out data to */ ps->CloseScanPath( ps ); ps->bRedGainIndex = 0x02; ps->bGreenGainIndex = 0x02; ps->bBlueGainIndex = 0x02; for (bCorrectTimes = 10; bCorrectTimes; bCorrectTimes-- ) { dacP98SetRGBGainRegister( ps ); /* shading the most brightness &*/ ps->PauseColorMotorRunStates( ps ); /* stop scan states */ IOReadOneShadingLine( ps, ps->pScanBuffer1, 2560UL ); dacP98AdjustGain( ps ); } dacP98SetRGBGainRegister( ps ); /* shading the most brightness & */ ps->PauseColorMotorRunStates( ps ); /* stop scan states */ IOReadOneShadingLine( ps, ps->pScanBuffer1, 2560UL ); dacP98CheckLastGain( ps ); DacP98FillGainOutDirectPort( ps ); } /** */ static void dacP98SetAdjustShadingRegister( pScanData ps ) { DBG( DBG_LOW, "dacP98SetAdjustShadingRegister()\n" ); IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeIdle ); ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE + _SCAN_1ST_AVERAGE; IOSelectLampSource( ps ); IOCmdRegisterToScanner( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_Motor0Control = _MotorOn + _MotorHEightStep + _MotorDirForward; ps->AsicReg.RD_XStepTime = ps->bSpeed1; ps->AsicReg.RD_ModelControl = _LED_ACTIVITY + _LED_CONTROL; if (ps->bSetScanModeFlag & _ScanMode_AverageOut) { ps->AsicReg.RD_Dpi = 300; ps->AsicReg.RD_Pixels = 2700; ps->AsicReg.RD_ModelControl += _ModelDpi300; } else { ps->AsicReg.RD_Dpi = 600; ps->AsicReg.RD_Pixels = 5400; ps->AsicReg.RD_ModelControl += _ModelDpi600; } ps->AsicReg.RD_Origin = 4; IOPutOnAllRegisters( ps ); } /** */ static void dacP98ReadShadingScanLine( pScanData ps ) { TimerDef timer; MiscStartTimer( &timer, _SECOND ); ps->Scan.bFifoSelect = ps->RegGFifoOffset; while((IOReadFifoLength( ps ) < dwReadyLen) && !MiscCheckTimer(&timer)) { _DO_UDELAY( 1 ); } IOReadColorData( ps, ps->pScanBuffer2, ps->dwShadingLen ); } /** */ static void dacP98GainResize( pUShort pValue, UShort wResize) { DataType Data; Byte bTemp; Data.dwValue = ((ULong) *pValue) * (ULong) wResize / 100; if (0x1000 <= Data.dwValue) Data.wValue = 0xfff; Data.wValue *= 16; bTemp = Data.wOverlap.b1st; Data.wOverlap.b1st = Data.wOverlap.b2nd; Data.wOverlap.b2nd = bTemp; *pValue = Data.wValue; } /** */ static void dacP98SortHilightShadow( pScanData ps, pUShort pwData, ULong dwHilightOff, ULong dwShadowOff ) { ULong dwLines, dwPixels; UShort wVCmp, wTmp; pUShort pw; for (dwPixels = 0; dwPixels < (ps->dwShadingPixels - 4); dwPixels++) { pw = (pUShort)ps->Shade.pHilight + dwHilightOff + dwPixels; wVCmp = pwData[dwPixels] & 0xfffU; for (dwLines = _DEF_BRIGHTEST_SKIP; dwLines--; pw += 5400UL) { if (wVCmp > *pw) { wTmp = wVCmp; wVCmp = *pw; *pw = wTmp; } } } for (dwPixels = 0; dwPixels < (ps->dwShadingPixels - 4); dwPixels++) { pw = ps->pwShadow + dwShadowOff + dwPixels; wVCmp = pwData [dwPixels] & 0xfffU; for (dwLines = _DEF_DARKEST_SKIP; dwLines--; pw += 5400UL) { if (wVCmp < *pw) { wTmp = wVCmp; wVCmp = *pw; *pw = wTmp; } } } } /** */ static void dacP98WriteBackToShadingRAM( pScanData ps ) { ULong dw; pUShort pBuffer = (pUShort)ps->pScanBuffer2; DBG( DBG_LOW, "dacP98WriteBackToShadingRAM()\n" ); if (ps->DataInf.wPhyDataType >= COLOR_TRUE24) { for (dw = 0; dw < 5400; dw++) { *pBuffer = ((pUShort)ps->pScanBuffer1)[dw] - ps->Shade.DarkOffset.Colors.Red; dacP98GainResize( pBuffer, ps->Shade.pCcdDac->GainResize.Colors.Red ); pBuffer ++; *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400] - ps->Shade.DarkOffset.Colors.Green; dacP98GainResize( pBuffer, ps->Shade.pCcdDac->GainResize.Colors.Green ); pBuffer ++; *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400 * 2] - ps->Shade.DarkOffset.Colors.Blue; dacP98GainResize( pBuffer, ps->Shade.pCcdDac->GainResize.Colors.Blue ); pBuffer ++; } } else { for (dw = 0; dw < 5400; dw++) { DataType Data; Byte bTemp; *pBuffer = ((pUShort)ps->pScanBuffer1)[dw + 5400] - ps->Shade.DarkOffset.Colors.Green; Data.wValue = (*pBuffer) * 16; bTemp = Data.wOverlap.b1st; Data.wOverlap.b1st = Data.wOverlap.b2nd; Data.wOverlap.b2nd = bTemp; *pBuffer = Data.wValue; pBuffer++; } } dacP98DownloadShadingTable( ps, ps->pScanBuffer2, (5400 * 2 * 3)); } /** */ static void dacP98ShadingRunLoop( pScanData ps ) { int i; DataPointer p; p.pb = ps->a_nbNewAdrPointer; switch( ps->IO.portMode ) { case _PORT_SPP: case _PORT_BIDI: *p.pw++ = 0; for (i = 0; i < 7; i++) *p.pdw++ = 0x00800700; *p.pw = 0; break; default: *p.pb++ = 0; for (i = 0; i < 15; i++) *p.pw++ = 0xf888; *p.pb = 0; } IOSetToMotorRegister( ps ); } /** */ static void dacP98Adjust12BitShading( pScanData ps ) { DataPointer pd, pt; ULong dw, dw1, dwLoop; DBG( DBG_LOW, "dacP98Adjust12BitShading()\n" ); memset( ps->pScanBuffer1, 0, (5400 * 4 * 3)); if( ps->Shade.pHilight && (_Shading_32Times == ps->bShadingTimeFlag)) { memset( ps->Shade.pHilight, 0, (ps->dwHilight * 2UL)); for (dw = 0; dw < ps->dwShadow; dw++) ps->pwShadow[dw] = 0xfff; } /* * in the original code this function does not exist ! * (of course the code behind the function does ;-) */ dacP98SetAdjustShadingRegister( ps ); dacP98ShadingRunLoop( ps ); _DODELAY( 24 ); if ((ps->DataInf.dwScanFlag & SCANDEF_TPA ) || (_Shading_32Times == ps->bShadingTimeFlag)) { dwLoop = 32; } else { if (_Shading_16Times == ps->bShadingTimeFlag) { dwLoop = 16; } else { dwLoop = 4; } } for (dw1 = 0; dw1 < dwLoop; dw1++) { ps->Scan.bFifoSelect = ps->RegGFifoOffset; dacP98ReadShadingScanLine( ps ); if((_Shading_32Times == ps->bShadingTimeFlag) && ps->Shade.pHilight ) { dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2, 0, 0 ); dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2 + ps->dwShadingPixels, ps->dwHilightCh, ps->dwShadowCh ); dacP98SortHilightShadow( ps, (pUShort)ps->pScanBuffer2 + ps->dwShadingPixels * 2, ps->dwHilightCh * 2, ps->dwShadowCh * 2); } /* SumAdd12BitShadingR */ pd.pw = (pUShort)ps->pScanBuffer2; pt.pdw = (pULong)(ps->pScanBuffer1 + dwADCPipeLine); for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++) *pt.pdw += (ULong)(*pd.pw & 0x0fff); /* SumAdd10BitShadingG */ if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) pd.pw = (pUShort)(ps->pScanBuffer2 + 2700 * 2); else pd.pw = (pUShort)(ps->pScanBuffer2 + 5400 * 2); pt.pdw = (pULong)(ps->pScanBuffer1 + 5400 * 4 + dwADCPipeLine); for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++) *pt.pdw += (ULong)(*pd.pw & 0x0fff); /* SumAdd12BitShadingB */ if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) pd.pw = (pUShort)(ps->pScanBuffer2 + 2700 * 4); else pd.pw = (pUShort)(ps->pScanBuffer2 + 5400 * 4); pt.pdw = (pULong)(ps->pScanBuffer1 + 5400 * 8 + dwADCPipeLine); for (dw = 5400 - 4; dw; dw--, pd.pw++, pt.pdw++) *pt.pdw += (ULong)(*pd.pw * 94 / 100 & 0x0fff); /* one line */ if (IOReadFifoLength( ps ) <= 2500) IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); } TPAP98001AverageShadingData( ps ); ps->OpenScanPath( ps ); dacP98WriteBackToShadingRAM( ps ); ps->CloseScanPath( ps ); } /** */ static Bool dacP98WaitForShading( pScanData ps ) { Byte oldLineControl; DBG( DBG_LOW, "dacP98WaitForShading()\n" ); /* * before getting the shading data, (re)init the ASIC */ ps->InitialSetCurrentSpeed( ps ); ps->ReInitAsic( ps, _TRUE ); IOCmdRegisterToScanner( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); ps->Shade.DarkOffset.Colors.Red = 0; ps->Shade.DarkOffset.Colors.Green = 0; ps->Shade.DarkOffset.Colors.Blue = 0; /* * according to the scan mode, switch on the lamp */ IOSelectLampSource( ps ); IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi300; } else { ps->AsicReg.RD_ModelControl = _LED_CONTROL + _ModelDpi600; } IOCmdRegisterToScanner( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl ); IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeScan); oldLineControl = ps->AsicReg.RD_LineControl; IOSetXStepLineScanTime( ps, _DEFAULT_LINESCANTIME ); /* set line control */ IOCmdRegisterToScanner( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); /* Wait for Sensor to position */ if( !ps->GotoShadingPosition( ps )) return _FALSE; ps->AsicReg.RD_LineControl = oldLineControl; IOCmdRegisterToScanner( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); dwADCPipeLine = 4 * 4; if( ps->bSetScanModeFlag & _ScanMode_AverageOut ) { dwReadyLen = 2500; ps->dwShadingLen = 2700 * 2; ps->dwShadingPixels = 2700; } else { dwReadyLen = 5000; ps->dwShadingLen = 5400 * 2; ps->dwShadingPixels = 5400; } dacP98AdjustRGBGain ( ps ); DacP98AdjustDark ( ps ); dacP98Adjust12BitShading( ps ); ps->OpenScanPath( ps ); DacP98FillShadingDarkToShadingRegister( ps ); if ( COLOR_BW != ps->DataInf.wPhyDataType ) dacP98DownloadMapTable( ps, ps->a_bMapTable ); ps->CloseScanPath( ps ); return _TRUE; } /** Set RAM bank and size, then write the data to it */ static void dacP96FillWhole4kRAM( pScanData ps, pUChar pBuf ) { ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegMemAccessControl, ps->Asic96Reg.RD_MemAccessControl ); ps->AsicReg.RD_ModeControl = _ModeProgram; IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); IOMoveDataToScanner( ps, pBuf, ps->ShadingBankSize ); ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); ps->CloseScanPath( ps ); } /** */ static void dacP96FillChannelDarkOffset( pScanData ps ) { ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegRedChDarkOffset, ps->Asic96Reg.RD_RedChDarkOff ); IODataToRegister( ps, ps->RegGreenChDarkOffset, ps->Asic96Reg.RD_GreenChDarkOff ); IODataToRegister( ps, ps->RegBlueChDarkOffset, ps->Asic96Reg.RD_BlueChDarkOff ); ps->CloseScanPath( ps ); } /** */ static void dacP96FillEvenOddControl( pScanData ps ) { ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegRedChEvenOffset, ps->Asic96Reg.RD_RedChEvenOff ); IODataToRegister( ps, ps->RegGreenChEvenOffset, ps->Asic96Reg.RD_GreenChEvenOff ); IODataToRegister( ps, ps->RegBlueChEvenOffset, ps->Asic96Reg.RD_BlueChEvenOff ); IODataToRegister( ps, ps->RegRedChOddOffset, ps->Asic96Reg.RD_RedChOddOff ); IODataToRegister( ps, ps->RegGreenChOddOffset, ps->Asic96Reg.RD_GreenChOddOff ); IODataToRegister( ps, ps->RegBlueChOddOffset, ps->Asic96Reg.RD_BlueChOddOff ); ps->CloseScanPath( ps ); } /** Used for capture data to pScanData->pPrescan16. * Used to replace: * 1) ReadFBKScanLine (3 * 1024, 5) * 2) ReadOneScanLine (3 * 2560, 11) * 4) ReadShadingScanLine (3 * 1280, 6) */ static void dacP96ReadDataWithinOneSecond( pScanData ps, ULong dwLen, Byte bBlks ) { TimerDef timer; MiscStartTimer( &timer, _SECOND ); while((IODataRegisterFromScanner( ps, ps->RegFifoOffset) < bBlks) && !MiscCheckTimer(&timer)); IOReadScannerImageData( ps, ps->pPrescan16, dwLen ); } /** */ static void dacP96GetEvenOddOffset( pUChar pb, pWordVal pwv ) { ULong dw; UShort we, wo; for (dw = 8, we = wo = 0; dw; dw-- ) { we += *pb++; wo += *pb++; } pwv->b1st = (Byte)(we >> 3); pwv->b2nd = (Byte)(wo >> 3); } /** */ static void dacP96SumAverageShading( pScanData ps, pUChar pDest, pUChar pSrce ) { ULong dw; UShort wLeft[6]; UShort wSumL, wSumR; pSrce += ps->Offset70 + ps->Device.DataOriginX; pDest += ps->Offset70 + ps->Device.DataOriginX; wLeft[0] = wLeft[1] = wLeft[2] = wLeft[3] = wLeft[4] = wLeft[5] = (UShort)*pSrce; wSumL = wLeft[0] * 6; wSumR = (UShort)pSrce[1] + pSrce[2] + pSrce[3] + pSrce[4] + pSrce[5] + pSrce[6]; /* for (dw = 2772; dw; dw--, pSrce++, pDest++) */ for (dw = ps->BufferSizePerModel - 6; dw; dw--, pSrce++, pDest++) { *pDest = (Byte)(((UShort)*pSrce * 4 + wSumL + wSumR) / 16); wSumL = wSumL - wLeft [0] + (UShort)*pSrce; wLeft[0] = wLeft[1]; wLeft[1] = wLeft[2]; wLeft[2] = wLeft[3]; wLeft[3] = wLeft[4]; wLeft[4] = wLeft[5]; wLeft[5] = (UShort)*pSrce; wSumR = wSumR - (UShort) *(pSrce + 1) + (UShort) *(pSrce + 7); } } /** */ static void dacP96WriteLinearGamma( pScanData ps, pUChar pBuf, ULong dwEntries, Byte bBank ) { ULong dw; pULong pdw = (pULong)(pBuf + ps->ShadingBufferSize); for (dw = 0; dwEntries; pdw++, dwEntries--, dw += 0x01010101) *pdw = dw; ps->Asic96Reg.RD_MemAccessControl = bBank; dacP96FillWhole4kRAM( ps, pBuf ); } /** */ static void dacP96FillChannelShadingOffset( pScanData ps ) { ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegRedChShadingOffset, ps->Asic96Reg.u28.RD_RedChShadingOff); IODataToRegister( ps, ps->RegGreenChShadingOffset, ps->Asic96Reg.u29.RD_GreenChShadingOff); IODataToRegister( ps, ps->RegBlueChShadingOffset, ps->Asic96Reg.RD_BlueChShadingOff); ps->CloseScanPath( ps ); } /** */ static void dacP96GetHilightShadow( pScanData ps, pUChar pBuf, pUChar pChOff, pUChar pHigh ) { ULong dw; /* GetShadingImageExtent (ps) */ if (ps->DataInf.wAppDataType < COLOR_256GRAY) dw = (ULong)(ps->DataInf.crImage.cx & 0xfff8); else dw = (ULong)ps->DataInf.crImage.cx; for( pBuf += ps->DataInf.crImage.x, *pChOff = 0xff, *pHigh = 0; dw; dw--, pBuf++ ) { if (*pChOff < *pBuf) { if (*pHigh < *pBuf) *pHigh = *pBuf; /* brightest */ } else *pChOff = *pBuf; /* darkest */ } } /** */ static void dacP96ReadColorShadingLine( pScanData ps ) { Byte b2ndDiscard, b3rdDiscard, b1stReadLines, b2ndReadLines; Byte b3rdReadLines; ULong dw; DataType Data; /* ClearScanBuffer1 (ps) */ /* buffer to keep sum of data */ memset( ps->pScanBuffer1, 0, ps->BufferForDataRead1 ); b2ndDiscard = ps->b2ndLinesOffset; b3rdDiscard = ps->b1stLinesOffset; b1stReadLines = b2ndReadLines = b3rdReadLines = 8; while( _TRUE ) { /* ReadShadingScanLine(ps) */ dacP96ReadDataWithinOneSecond( ps, ps->ShadingScanLineLen, ps->ShadingScanLineBlks ); if (b1stReadLines) { b1stReadLines--; /* SumAdd10BitShadingR */ for (dw = 0; dw < ps->BufferSizeBase; dw++) ((pUShort)ps->pScanBuffer1)[dw] += (UShort)ps->pPrescan16 [dw]; } if (!b2ndDiscard) { if (b2ndReadLines) { b2ndReadLines--; /* SumAdd10BitShadingG */ for (dw = ps->BufferSizeBase;dw < (ULong)ps->BufferSizeBase * 2;dw++) { ((pUShort)ps->pScanBuffer1)[dw] += (UShort)ps->pPrescan16[dw]; } } } else b2ndDiscard--; if (!b3rdDiscard) { if (b3rdReadLines) { b3rdReadLines--; /* SumAdd10BitShadingB */ for (dw = ps->BufferSizeBase * 2; dw < (ULong)ps->BufferSizeBase * 3; dw++) { ((pUShort)ps->pScanBuffer1)[dw] += (UShort)ps->pPrescan16[dw]; } } else break; } else b3rdDiscard--; IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); } for (dw = 0; dw < (ULong)ps->BufferSizeBase * 3; dw++) { Data.wOverlap.b1st = Data.wOverlap.b2nd = (Byte)(((pUShort)ps->pScanBuffer1)[dw] / 8); ((pUShort)ps->pPrescan16)[dw] = Data.wValue; } } /** */ static void dacP96SetShadingGainProc( pScanData ps, Byte bHigh, ULong dwCh ) { Byte bDark, bGain, bGainX2, bGainX4, bMask; pUChar pbChDark, pbSrce, pbDest; ULong dw; pbChDark = NULL, pbSrce = NULL, pbDest = NULL; bDark = 0, bGain = 0, bGainX2 = 0, bGainX4 = 0, bMask = 0; switch( dwCh ) { case 0: /* red */ pbChDark = &ps->Asic96Reg.u28.RD_RedChShadingOff; pbSrce = ps->pPrescan16; pbDest = ps->pScanBuffer1 + ps->Offset70 + ps->Device.DataOriginX; bGainX2 = 1; bGainX4 = 3; bMask = 0x3c; break; case 1: /* green */ pbChDark = &ps->Asic96Reg.u29.RD_GreenChShadingOff; pbSrce = ps->pPrescan16 + ps->BufferSizePerModel; pbDest = ps->pScanBuffer1 + ps->Offset70 + ps->ShadingBankSize + ps->Device.DataOriginX; bGainX2 = 4; bGainX4 = 0x0c; bMask = 0x33; break; case 2: pbChDark = &ps->Asic96Reg.RD_BlueChShadingOff; pbSrce = ps->pPrescan16 + ps->BufferSizePerModel * 2; pbDest = ps->pScanBuffer1 + ps->Offset70 + ps->ShadingBankSize * 2 + ps->Device.DataOriginX; bGainX2 = 0x10; bGainX4 = 0x30; bMask = 0x0f; } bDark = *pbChDark; if ((bHigh -= bDark) > 60U) { /* Hilight - Shadow > 60, Quality not so good */ bGain = bGainX2; /* Gain x 2 */ if (bHigh > 120U) bGain = bGainX4; /* Poor quality, Gain x 4 */ } else bGain = 0; ps->Asic96Reg.RD_ShadingCorrectCtrl &= bMask; ps->Asic96Reg.RD_ShadingCorrectCtrl |= bGain; if (!bGain) { /* GammaGain1 (ps) */ for (dw = ps->BufferSizePerModel; dw; dw--, pbSrce++, pbDest++) if (*pbSrce > bDark) *pbDest = (*pbSrce - bDark) * 4; else *pbDest = 0; } else if (bGain == bGainX2) { /* GammaGain2 */ for (dw = ps->BufferSizePerModel; dw; dw--, pbSrce++, pbDest++) if (*pbSrce > bDark) *pbDest = (*pbSrce - bDark) * 2; else *pbDest = 0; } else { /* GammaGain4 (ps) */ memcpy( pbDest, pbSrce, ps->BufferSizePerModel ); *pbChDark = 0; } } /** */ static void dacP96FillShadingAndGammaTable( pScanData ps ) { ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankRed; /* R */ dacP96FillWhole4kRAM( ps, ps->pPrescan16 ); ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankGreen; /* G */ dacP96FillWhole4kRAM( ps, ps->pPrescan16 ); ps->Asic96Reg.RD_MemAccessControl = ps->ShadingBankBlue; /* B */ dacP96FillWhole4kRAM( ps, ps->pPrescan16 ); } /** */ static void dacP96SetInitialGainRAM( pScanData ps ) { ULong dw, dw1; pULong pdw = (pULong)(ps->pPrescan16 + ps->ShadingBufferSize); memset( ps->pPrescan16, 0xff, ps->ShadingBufferSize ); for (dw = 256, dw1 = 0; dw; dw--, dw1 += 0x01010101, pdw++) *pdw = dw1; dacP96FillShadingAndGammaTable( ps ); } /** */ static void dacP96Adjust10BitShading( pScanData ps ) { pULong pdw; ULong dw; Byte bRedHigh, bGreenHigh, bBlueHigh; /* ShadingMotorRunLoop(ps) * set scan states as: * 40h, 00, 00, 00, 40h, 01, 03, 02, ... (repeat) * so, read a R/G/B line every 2 steps */ pdw = (pULong)ps->a_nbNewAdrPointer; for (dw = 0; dw < 4; dw++) { *pdw++ = 0x40; *pdw++ = 0x02030140; } dacP96SetInitialGainRAM( ps); /* initiates the shading buffers and maps */ /* SetAdjustShadingRegister(ps) */ /* Prepare Physical/2 dpi, 8.5" scanning condition for reading the shading area */ ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; ps->Asic96Reg.RD_MotorControl = ps->IgnorePF | ps->MotorOn | _MotorDirForward; ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; ps->AsicReg.RD_Dpi = ps->PhysicalDpi / 2; ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + ps->Device.DataOriginX); ps->AsicReg.RD_Pixels = ps->BufferSizeBase; IOPutOnAllRegisters( ps ); ps->Asic96Reg.RD_ShadingCorrectCtrl = _ShadingRCorrectX4|_ShadingGCorrectX4| _ShadingBCorrectX4; IOCmdRegisterToScanner( ps, ps->RegShadingCorrectCtrl, ps->Asic96Reg.RD_ShadingCorrectCtrl ); /* Read shaded data and do average */ dacP96ReadColorShadingLine( ps ); /* ExpandAndAverage (ps) ------------------------------------------------*/ /* for (dw = 0; dw < 1280 * 3; dw++) { Data.wOverlap.b1st = Data.wOverlap.b2nd = (Byte)(((pUShort) ps->pScanBuffer1)[dw] / 8); ((pULong) ps->pPrescan16)[dw] = Data.wValue; } */ /* CalculateShadingOffset (ps); */ dacP96GetHilightShadow( ps, ps->pPrescan16, &ps->Asic96Reg.u28.RD_RedChShadingOff, &bRedHigh ); dacP96GetHilightShadow( ps, ps->pPrescan16 + ps->BufferSizePerModel, &ps->Asic96Reg.u29.RD_GreenChShadingOff, &bGreenHigh ); dacP96GetHilightShadow( ps, ps->pPrescan16 + ps->BufferSizePerModel * 2, &ps->Asic96Reg.RD_BlueChShadingOff, &bBlueHigh ); /* SubTheImageDataBase (ps) */ dacP96SetShadingGainProc( ps, bRedHigh, 0 ); /* red */ dacP96SetShadingGainProc( ps, bGreenHigh, 1 ); /* green */ dacP96SetShadingGainProc( ps, bBlueHigh, 2 ); /* blue */ dacP96FillChannelShadingOffset( ps ); IOCmdRegisterToScanner( ps, ps->RegShadingCorrectCtrl, ps->Asic96Reg.RD_ShadingCorrectCtrl ); dacP96SumAverageShading( ps, ps->pPrescan16, ps->pScanBuffer1 ); dacP96SumAverageShading( ps, ps->pPrescan16 + ps->ShadingBankSize, ps->pScanBuffer1 + ps->ShadingBankSize ); dacP96SumAverageShading( ps, ps->pPrescan16 + ps->ShadingBankSize * 2, ps->pScanBuffer1 + ps->ShadingBankSize * 2 ); /* --------------------------------------------------------------------- */ /* PrewriteBackToGammaShadingRAM( ps) */ dacP96WriteLinearGamma( ps, ps->pPrescan16, 256, ps->ShadingBankRed ); dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize, 256, ps->ShadingBankGreen ); dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize * 2, 256, ps->ShadingBankBlue ); } /** */ static Bool dacP96003WaitForShading( pScanData ps ) { int bCorrectTimes; DataPointer p; ULong dw; UShort w; WordVal wv; pUChar pbReg[3]; Byte b[3]; DBG( DBG_LOW, "dacP96003WaitForShading()\n" ); /* TurnOnLamp () */ ps->AsicReg.RD_ScanControl |= ps->bLampOn; IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); ps->Asic96Reg.RD_LedControl = _LedActControl | _LedMotorActEnable; IOCmdRegisterToScanner(ps, ps->RegLedControl, ps->Asic96Reg.RD_LedControl); if ( ps->GotoShadingPosition( ps )) { /* AdjustRGBGain () =================================================*/ ps->Asic96Reg.RD_RedGainOut = ps->Asic96Reg.RD_GreenGainOut = ps->Asic96Reg.RD_BlueGainOut = 8; ps->Asic96Reg.u26.RD_ModelControl2 = _Model2DirectOutPort; IOCmdRegisterToScanner(ps, ps->RegModelControl2, _Model2DirectOutPort); for ( bCorrectTimes = 4; bCorrectTimes >= 1; bCorrectTimes-- ) { ps->PauseColorMotorRunStates( ps ); /* SetRGBGainRegister () ----------------------------------------*/ ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; dacP96SetInitialGainRAM( ps ); /* SetInitialGainRegister () ++++++++++++++++++++++++++++++++++++*/ ps->Asic96Reg.u28.RD_RedChShadingOff = ps->Asic96Reg.u29.RD_GreenChShadingOff = ps->Asic96Reg.RD_BlueChShadingOff = ps->Asic96Reg.RD_RedChDarkOff = ps->Asic96Reg.RD_GreenChDarkOff = ps->Asic96Reg.RD_BlueChDarkOff = ps->Asic96Reg.RD_RedChEvenOff = ps->Asic96Reg.RD_GreenChEvenOff = ps->Asic96Reg.RD_BlueChEvenOff = ps->Asic96Reg.RD_RedChOddOff = ps->Asic96Reg.RD_GreenChOddOff = ps->Asic96Reg.RD_BlueChOddOff = 0; ps->Asic96Reg.RD_ShadingCorrectCtrl = _ShadingRCorrectX4 | _ShadingGCorrectX4 | _ShadingBCorrectX4; dacP96FillChannelShadingOffset( ps ); dacP96FillChannelDarkOffset( ps ); dacP96FillEvenOddControl( ps ); /* FillGainOutDirectPort (); */ ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegRedGainOutDirect, ps->Asic96Reg.RD_RedGainOut ); IODataToRegister( ps, ps->RegGreenGainOutDirect, ps->Asic96Reg.RD_GreenGainOut ); IODataToRegister( ps, ps->RegBlueGainOutDirect, ps->Asic96Reg.RD_BlueGainOut ); /* FillGainInitialRestRegister (); */ IODataToRegister( ps, ps->RegModelControl2, ps->Asic96Reg.u26.RD_ModelControl2 ); IODataToRegister( ps, ps->RegThresholdGapControl, ps->AsicReg.RD_ThresholdGapCtrl ); IODataToRegister( ps, ps->RegLedControl, ps->Asic96Reg.RD_LedControl ); IODataToRegister( ps, ps->RegShadingCorrectCtrl, ps->Asic96Reg.RD_ShadingCorrectCtrl ); ps->CloseScanPath( ps ); ps->Asic96Reg.RD_MotorControl = 0; IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; ps->Asic96Reg.RD_MotorControl = (ps->IgnorePF | ps->MotorOn | _MotorDirForward); ps->AsicReg.RD_Origin = 142; ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; ps->AsicReg.RD_Dpi = ps->PhysicalDpi; ps->AsicReg.RD_Pixels = ps->BufferSizePerModel; IOPutOnAllRegisters( ps ); /*---------------------------------------------------------------*/ /* ReadOneScanLine (); */ dacP96ReadDataWithinOneSecond( ps, ps->OneScanLineLen, 11 ); /* AdjustGain () */ /* FindTheMaxGain (), AdjustGainOutData (); */ pbReg[0] = &ps->Asic96Reg.RD_RedGainOut; pbReg[1] = &ps->Asic96Reg.RD_GreenGainOut; pbReg[2] = &ps->Asic96Reg.RD_BlueGainOut; for (w = 0, p.pb = ps->pPrescan16; w < 3; w++) { /* CHANGE: org was: for (dw = 2560, b[w] = 0; dw; dw--, p.pb++) { */ for (dw = (ps->OneScanLineLen/3), b[w] = 0; dw; dw--, p.pb++) { if (b[w] < *p.pb) b[w] = *p.pb; } if (b[w] < _GAIN_LOW) *(pbReg[w]) += a_bCorrectTimesTable[bCorrectTimes - 1]; else if (b[w] > _GAIN_P96_HIGH) *(pbReg[w]) -= a_bCorrectTimesTable[bCorrectTimes - 1]; } } /*===================================================================*/ /* SonyFBK ()/ToshibaFBK ()====================================*/ /*FillRGBDarkLevel0Table (); */ memset( ps->pPrescan16, 0xff, ps->ShadingBankSize ); for( dw = 0, p.pb = ps->pPrescan16 + ps->ShadingBufferSize; dw <=255; dw++, p.pb++ ) { *p.pb = (Byte) dw; } dacP96FillShadingAndGammaTable( ps ); ps->PauseColorMotorRunStates( ps ); /* SetReadFBKRegister () */ ps->Asic96Reg.RD_MotorControl = 0; IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; ps->Asic96Reg.RD_MotorControl = ps->IgnorePF | ps->MotorOn | _MotorDirForward; ps->AsicReg.RD_Origin = 22; ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; ps->AsicReg.RD_Dpi = ps->PhysicalDpi; ps->AsicReg.RD_Pixels = ps->FBKScanLineLenBase; IOPutOnAllRegisters( ps ); /* ReadFBKScanLine () */ dacP96ReadDataWithinOneSecond( ps, ps->FBKScanLineLen, ps->FBKScanLineBlks ); /*===================================================================*/ if ( ps->fSonyCCD ) { /* FillChannelDarkLevelControl (); */ for ( p.pb = ps->pPrescan16 + 32, w = 0, dw = 16; dw; dw--, p.pb++) { w += (UShort) *p.pb; } ps->Asic96Reg.RD_RedChDarkOff = (Byte)(w / 16); for ( p.pb = ps->pPrescan16 + 32 + ps->FBKScanLineLenBase, w = 0, dw = 16; dw; dw--, p.pb++ ) { w += (UShort)*p.pb; } ps->Asic96Reg.RD_GreenChDarkOff = (Byte)(w / 16); for ( p.pb = ps->pPrescan16 + 32 + ps->FBKScanLineLenBase * 2, w = 0, dw = 16; dw; dw--, p.pb++) { w += (UShort)*p.pb; } ps->Asic96Reg.RD_BlueChDarkOff = (Byte)(w / 16); dacP96FillChannelDarkOffset( ps ); } else { /* FillToshibaDarkLevelControl (); */ dacP96GetEvenOddOffset( ps->pPrescan16 + 32, &wv ); ps->Asic96Reg.RD_RedChEvenOff = wv.b1st; ps->Asic96Reg.RD_RedChOddOff = wv.b2nd; dacP96GetEvenOddOffset( ps->pPrescan16 + 32 + ps->FBKScanLineLenBase, &wv ); ps->Asic96Reg.RD_GreenChEvenOff = wv.b1st; ps->Asic96Reg.RD_GreenChOddOff = wv.b2nd; dacP96GetEvenOddOffset( ps->pPrescan16 + 32 + ps->FBKScanLineLenBase * 2, &wv ); ps->Asic96Reg.RD_BlueChEvenOff = wv.b1st; ps->Asic96Reg.RD_BlueChOddOff = wv.b2nd; dacP96FillEvenOddControl( ps ); } /* SetInitialGainRAM (); */ dacP96Adjust10BitShading( ps ); return _TRUE; } return _FALSE; } /** */ static void dacP96001ToSetShadingAddress( pScanData ps, pUChar pData ) { ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegMemAccessControl, ps->Asic96Reg.RD_MemAccessControl); ps->AsicReg.RD_ModeControl = _ModeProgram; IODataToRegister( ps, ps->RegModeControl, _ModeProgram ); ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward; IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl); memset( ps->pScanBuffer1, 0, (64 + 8 + ps->Offset70)); memcpy( ps->pScanBuffer1 + 64 + 8 + ps->Offset70, pData, _BUF_SIZE_BASE_CONST * 2 ); IOMoveDataToScanner( ps, ps->pScanBuffer1, _BUF_SIZE_BASE_CONST * 2 + 64 + 8 + ps->Offset70 ); ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, _ModeScan ); ps->CloseScanPath( ps ); } /** */ static void dacP96001WriteBackToColorShadingRam( pScanData ps ) { ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3a); dacP96001ToSetShadingAddress( ps, ps->pPrescan16 ); ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3e); dacP96001ToSetShadingAddress( ps, ps->pPrescan16 + _BUF_SIZE_BASE_CONST*2); ps->Asic96Reg.RD_MemAccessControl = (_MemBankSize4k96001 | 0x3c); dacP96001ToSetShadingAddress( ps, ps->pPrescan16 + _BUF_SIZE_BASE_CONST*4); } /** */ static void dacP96001ModifyShadingColor( pByte pData, Byte bMul ) { UShort w; ULong dw; for ( dw = 0; dw < _BUF_SIZE_BASE_CONST * 2; dw++ ) { w = (UShort)(Byte)(~pData[dw]) * bMul / 100U; if (w >= 255U) pData[dw] = 0; else pData[dw] = (Byte)~w; } } /** */ static Byte dacP96001FBKReading( pScanData ps, Byte bValue, Byte bReg, pByte pbSave, Bool bFBKModify ) { TimerDef timer; UShort w, wSum; Byte addrSeq[8] = { 0x40, 0x20, 0x10, 0x08, 4, 2, 1, 0 }; Byte bTemp, bFBKTemp, bFBKIndex; if( bFBKModify ) { bFBKIndex = 3; bFBKTemp = *pbSave; } else { bFBKTemp = 0x80; bFBKIndex = 0; } while( _TRUE ) { *pbSave = bFBKTemp; IOCmdRegisterToScanner( ps, bReg, bFBKTemp ); /* SetColorRunTable (BYTE) */ memset( ps->a_nbNewAdrPointer, bValue, _SCANSTATE_BYTES ); MotorSetConstantMove( ps, 0 ); /* SetReadFBK (pScanData) */ ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward; IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE | ps->bLampOn; ps->AsicReg.RD_ModelControl = (_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0 ); ps->AsicReg.RD_Dpi = 300; ps->AsicReg.RD_Origin = 22; ps->AsicReg.RD_Pixels = 1024; IOPutOnAllRegisters( ps ); ps->Asic96Reg.RD_MotorControl = (ps->FullStep | ps->MotorOn | _MotorDirForward); IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); MiscStartTimer( &timer, _SECOND ); while((IODataRegisterFromScanner( ps, ps->RegFifoOffset) < 1) && !MiscCheckTimer( &timer )); IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); IOReadScannerImageData( ps, ps->pScanBuffer1, 64 ); for( w = 26, wSum = 0; w < 42; w++) wSum += ps->pScanBuffer1[w]; wSum >>= 4; bTemp = addrSeq[bFBKIndex++]; if( bTemp ) { if( wSum < 0xfe ) bFBKTemp += bTemp; else bFBKTemp -= bTemp; } else { return bFBKTemp; } } } /** */ static Bool dacP96001WaitForShading( pScanData ps ) { Bool bFBKModify; Byte bRSave; Byte bGSave; Byte bBSave; ULong dw; pULong pdw; DBG( DBG_LOW, "dacP96001WaitForShading()\n" ); ps->AsicReg.RD_ScanControl |= ps->bLampOn; IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); if ( ps->GotoShadingPosition( ps )) { _DODELAY( 250 ); /* AdjustMostWideOffset70 (pScanData) -------------------------------*/ /* FillABitGray (pScanData)*/ memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->a_nbNewAdrPointer[8] = ps->a_nbNewAdrPointer[24] = 0x30; MotorSetConstantMove( ps, 32 ); /* SetMaxWideRegister (pScanData) */ ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE | ps->bLampOn; ps->Asic96Reg.RD_MotorControl = (ps->MotorOn | ps->IgnorePF | _MotorDirForward); ps->AsicReg.RD_ModelControl = (_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0); ps->AsicReg.RD_Dpi = 300; ps->AsicReg.RD_Origin = 64 + 8; ps->AsicReg.RD_Pixels = 2700; IOPutOnAllRegisters( ps ); IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); /* ReadMaxWideLine */ dacP96ReadDataWithinOneSecond( ps, 2700, 5 ); /* AdjustOffset70Proc (pScanData)------------------------------------*/ { ULong dwSum, dw, dwLeft, dwCenter; /* AverageWideBank (pScanData) */ for( dwSum = 0, dw = 0; dw < 2700; dw++ ) dwSum += (ULong)ps->pPrescan16[dw]; dwSum /= 2700UL; if( dwSum <= 0x80 ) { memcpy( ps->pScanBuffer1, ps->pPrescan16, 140 ); memcpy( ps->pScanBuffer1 + 140, ps->pPrescan16 + _BUF_SIZE_BASE_CONST * 2, 140); /* BlackOffsetCheck (pScanData) */ for( dw = dwLeft = 0; dw < 140; dw++ ) { if( ps->pScanBuffer1[dw] >= 0xe0 ) dwLeft++; else break; } /* WhiteOffsetCheck (pScanData) */ for( dw = 140, dwCenter = 0; dw < 280; dw++ ) { if( ps->pScanBuffer1[dw] < 0xe0 ) dwCenter++; else break; } if (dwLeft) { ps->Offset70 = (dwLeft + dwCenter) / 2 + 14; } else { if (dwCenter == 140) ps->Offset70 = 70; else ps->Offset70 = dwCenter / 2 + 2; } } } memset( ps->pPrescan16, 0, ps->BufferSizePerModel * 3 ); dacP96001WriteBackToColorShadingRam( ps ); /* SetFBK */ if((IODataRegisterFromScanner(ps, ps->RegReadIOBufBus) & 0x0f) == 0x0f) bFBKModify = 0; else bFBKModify = 1; dacP96001FBKReading(ps, 0x10, ps->RegRedDCAdjust, &bRSave,bFBKModify); dacP96001FBKReading(ps, 0x30, ps->RegGreenDCAdjust,&bGSave,bFBKModify); dacP96001FBKReading(ps, 0x20, ps->RegBlueDCAdjust, &bBSave,bFBKModify); ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegRedDCAdjust, (Byte)(bRSave + 2)); IODataToRegister( ps, ps->RegGreenDCAdjust, (Byte)(bGSave + 2)); IODataToRegister( ps, ps->RegBlueDCAdjust, bBSave); ps->CloseScanPath( ps ); /* Turn off and then turn on motor */ IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->Asic96Reg.RD_MotorControl & ~ps->MotorOn)); IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); /* FillABitColor (pScanData) */ pdw = (pULong)ps->a_nbNewAdrPointer; for( dw = 0; dw < 4; dw++) { *pdw++ = 0x40; *pdw++ = 0x2030140; } IOSetToMotorRegister( ps ); /* SetShadingRegister (pScanData) */ ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward; IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_LineControl = ps->TimePerLine; ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE | ps->bLampOn; ps->Asic96Reg.RD_MotorControl = ps->FullStep | _MotorDirForward; ps->AsicReg.RD_ModelControl = (_ModelMemSize32k96001 | _ModelDpi300 | _ModelWhiteIs0); ps->AsicReg.RD_Dpi = 150; ps->AsicReg.RD_Origin = (UShort)(64 + 8 + ps->Offset70); ps->AsicReg.RD_Pixels = ps->BufferSizeBase; IOPutOnAllRegisters( ps ); IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->MotorOn | ps->IgnorePF | _MotorDirForward)); dacP96ReadColorShadingLine( ps ); /* ModifyShadingColor (pScanData) */ dacP96001ModifyShadingColor( ps->pPrescan16, 103 ); dacP96001ModifyShadingColor( ps->pPrescan16 + _BUF_SIZE_BASE_CONST * 2 * 2, 97); dacP96001WriteBackToColorShadingRam( ps ); return _TRUE; } return _FALSE; } /** */ static void dacP98003GainOffsetToDAC( pScanData ps, Byte ch, Byte reg, Byte d ) { if( ps->Device.bDACType == _DA_SAMSUNG8531 ) { IODataToRegister( ps, ps->RegADCAddress, 0 ); IODataToRegister( ps, ps->RegADCData, ch ); IODataToRegister( ps, ps->RegADCSerialOutStr, ch); } IODataToRegister( ps, ps->RegADCAddress, reg ); IODataToRegister( ps, ps->RegADCData, d ); IODataToRegister( ps, ps->RegADCSerialOutStr, d ); } /** */ static void dacP98003AdjustRGBGain( pScanData ps ) { ULong i; Byte bHi[3]; DBG( DBG_LOW, "dacP98003AdjustRGBGain()\n" ); ps->Shade.Gain.Colors.Red = ps->Shade.Gain.Colors.Green = ps->Shade.Gain.Colors.Blue = ps->Shade.bUniGain; ps->Shade.Hilight.Colors.Red = ps->Shade.Hilight.Colors.Green = ps->Shade.Hilight.Colors.Blue = 0; ps->Shade.bGainHigh = _GAIN_P98003_HIGH; ps->Shade.bGainLow = _GAIN_P98003_LOW; ps->Shade.fStop = _FALSE; for( i = 10; i-- && !ps->Shade.fStop; ) { ps->Shade.fStop = _TRUE; /* SetRGBGainRegister () */ IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; IOSelectLampSource( ps ); IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) ps->AsicReg.RD_Origin = (UShort)ps->Device.DataOriginX >> 1; else ps->AsicReg.RD_Origin = (UShort)ps->Device.DataOriginX; ps->AsicReg.RD_Dpi = 300; ps->AsicReg.RD_Pixels = 2560; /* PauseColorMotorRunStates () */ memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->a_nbNewAdrPointer[1] = 0x77; IOPutOnAllRegisters( ps ); _DODELAY( 70 ); /* read one shading line and work on it */ if( IOReadOneShadingLine( ps, (pUChar)ps->Bufs.b1.pShadingRam, 2560)) { if ( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) { bHi[1] = DacP98003SumGains( (pUChar)ps->Bufs.b1.pShadingRam + 2560, 2560); if( bHi[1] ) DacP98003AdjustGain( ps, _CHANNEL_GREEN, bHi[1] ); else { ps->Shade.fStop = _FALSE; } } else { bHi[0] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam, 2560); bHi[1] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam + 2560, 2560); bHi[2] = DacP98003SumGains((pUChar)ps->Bufs.b1.pShadingRam + 5120, 2560); if (!bHi[0] || !bHi[1] || !bHi[2] ) { ps->Shade.fStop = _FALSE; } else { DacP98003AdjustGain( ps, _CHANNEL_RED, bHi[0] ); DacP98003AdjustGain( ps, _CHANNEL_GREEN, bHi[1] ); DacP98003AdjustGain( ps, _CHANNEL_BLUE, bHi[2] ); } } } else ps->Shade.fStop = _FALSE; } #ifdef DEBUG if( !ps->Shade.fStop ) DBG( DBG_LOW, "dacP98003AdjustRGBGain() - all loops done!!!\n" ); #endif DacP98003FillToDAC( ps, &ps->Device.RegDACGain, &ps->Shade.Gain ); } /** */ static UShort dacP98003SumDarks( pScanData ps, pUShort data ) { UShort i, loop; if( ps->Device.bCCDID == _CCD_3799 ) { if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) data += 0x18; else data += 0x30; } else { if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) data += 0x18; else data += 0x20; } for( i = 0, loop = 16; loop--; data++ ) i += *data; i >>= 4; return i; } /** */ static void dacP98003AdjustShadingWaveform( pScanData ps ) { Byte b; UShort count, wR, wG, wB, tmp; DataType var; DataPointer pvar, psum; RBGPtrDef cp; pRGBUShortDef pRGB, pwsum; DBG( DBG_LOW, "dacP98003AdjustShadingWaveForm()\n" ); memset( &cp, 0, sizeof(RBGPtrDef)); memset( ps->Bufs.b2.pSumBuf, 0, (5400 * 3 * 2)); /* SetAdjustShadingRegister () */ IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); ps->AsicReg.RD_LineControl = _LOBYTE(ps->Shade.wExposure); ps->AsicReg.RD_ExtLineControl = _HIBYTE(ps->Shade.wExposure); IODataToRegister( ps, ps->RegExtendedLineControl, ps->AsicReg.RD_ExtLineControl ); IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); ps->AsicReg.RD_XStepTime = _LOBYTE(ps->Shade.wExposure); ps->AsicReg.RD_ExtXStepTime = _HIBYTE(ps->Shade.wExposure); IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime ); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime ); ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) { ps->AsicReg.RD_Dpi = 300; ps->AsicReg.RD_Pixels = 2700; ps->Shade.shadingBytes = 2700 * 2; } else { ps->AsicReg.RD_Dpi = 600; ps->AsicReg.RD_Pixels = 5400; ps->Shade.shadingBytes = 5400 * 2; } ps->AsicReg.RD_Origin = _SHADING_BEGINX; for( pvar.pdw = (pULong)ps->a_nbNewAdrPointer, var.dwValue = _SCANSTATE_BYTES >> 2; var.dwValue--; pvar.pdw++) { *pvar.pdw = 0x00f00080; } ps->Scan.fRefreshState = _FALSE; IOPutOnAllRegisters( ps ); _DODELAY( 55 ); /* SetupHilightShadow () */ if( ps->Shade.pHilight ) { memset( ps->Shade.pHilight, 0, ps->Shade.shadingBytes * ps->Shade.skipHilight * 3 ); memset((pUChar)ps->Shade.pHilight + ps->Shade.shadingBytes * ps->Shade.skipHilight * 3, 0xff, ps->Shade.shadingBytes * ps->Shade.skipShadow * 3 ); } for( count = 32; count--;) { IOReadOneShadingLine( ps, ((pUChar)ps->Bufs.b1.pShadingRam)+_SHADING_BEGINX, ps->Shade.shadingBytes ); /* SaveHilightShadow() */ if( ps->Shade.pHilight ) { if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { cp.red.usp = ps->Bufs.b1.pShadingRam + _SHADING_BEGINX; cp.green.usp = cp.red.usp + ps->AsicReg.RD_Pixels; cp.blue.usp = cp.green.usp + ps->AsicReg.RD_Pixels; pvar.pusrgb = (pRGBUShortDef)ps->Shade.pHilight + _SHADING_BEGINX; for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { pRGB = pvar.pusrgb++; wR = *cp.red.usp; wG = *cp.green.usp; wB = *cp.blue.usp; for( b = ps->Shade.skipHilight; b--; pRGB += ps->AsicReg.RD_Pixels) { if( wR > pRGB->Red ) { tmp = wR; wR = pRGB->Red; pRGB->Red = tmp; } if( wG > pRGB->Green ) { tmp = wG; wG = pRGB->Green; pRGB->Green = tmp; } if( wB > pRGB->Blue ) { tmp = wB; wB = pRGB->Blue; pRGB->Blue = tmp; } } wR = *cp.red.usp++; wG = *cp.green.usp++; wB = *cp.blue.usp++; for(b = ps->Shade.skipShadow; b--; pRGB += ps->AsicReg.RD_Pixels) { if (wR < pRGB->Red) { tmp = wR; wR = pRGB->Red; pRGB->Red = tmp; } if (wG < pRGB->Green) { tmp = wG; wG = pRGB->Green; pRGB->Green = tmp; } if (wB < pRGB->Blue) { tmp = wB; wB = pRGB->Blue; pRGB->Blue = tmp; } } } } else { cp.green.usp = ps->Bufs.b1.pShadingRam + ps->AsicReg.RD_Pixels + _SHADING_BEGINX; cp.blue.usp = (pUShort) ps->Shade.pHilight + _SHADING_BEGINX; for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { cp.red.usp = cp.blue.usp++; wG = *cp.green.usp; for( b = ps->Shade.skipHilight; b--; cp.red.usp += ps->AsicReg.RD_Pixels) { if( wG > *cp.red.usp ) { tmp = wG; wG = *cp.red.usp; *cp.red.usp = tmp; } } wG = *cp.green.usp++; for (b = ps->Shade.skipShadow; b--; cp.red.usp += ps->AsicReg.RD_Pixels) { if( wG < *cp.red.usp ) { tmp = wG; wG = *cp.red.usp; *cp.red.usp = tmp; } } } } } /* AddToSumBuffer() */ if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { cp.red.usp = ps->Bufs.b1.pShadingRam + _SHADING_BEGINX; cp.green.usp = cp.red.usp + ps->AsicReg.RD_Pixels; cp.blue.usp = cp.green.usp + ps->AsicReg.RD_Pixels; pvar.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = (ULong)ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--; pvar.pulrgb++, cp.red.usp++, cp.green.usp++, cp.blue.usp++) { pvar.pulrgb->Red += (ULong)*cp.red.usp; pvar.pulrgb->Green += (ULong)*cp.green.usp; pvar.pulrgb->Blue += (ULong)*cp.blue.usp; } } else { cp.green.usp = ps->Bufs.b1.pShadingRam + ps->AsicReg.RD_Pixels + _SHADING_BEGINX; pvar.pdw = (pULong)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; for(var.dwValue = (ULong)ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--; pvar.pdw++, cp.green.usp++) { *pvar.pdw += (ULong)*cp.green.usp; } } if( IOReadFifoLength( ps ) < ps->AsicReg.RD_Pixels ) IORegisterToScanner( ps, ps->RegRefreshScanState ); } /* AverageAfterSubHilightShadow() */ if( ps->Shade.pHilight ) { if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { psum.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; pwsum = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; pvar.pusrgb = (pRGBUShortDef)ps->Shade.pHilight + _SHADING_BEGINX; for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { pRGB = pvar.pusrgb++; for( b = ps->Shade.skipHilight + ps->Shade.skipShadow; b--; pRGB += ps->AsicReg.RD_Pixels ) { psum.pulrgb->Red -= (ULong)pRGB->Red; psum.pulrgb->Green -= (ULong)pRGB->Green; psum.pulrgb->Blue -= (ULong)pRGB->Blue; } pwsum->Red = (UShort)(psum.pulrgb->Red / ps->Shade.dwDiv); pwsum->Green = (UShort)(psum.pulrgb->Green / ps->Shade.dwDiv); pwsum->Blue = (UShort)(psum.pulrgb->Blue / ps->Shade.dwDiv); psum.pulrgb++; pwsum++; } } else { cp.green.ulp = (pULong)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; cp.blue.usp = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; pvar.pw = (pUShort)ps->Shade.pHilight + _SHADING_BEGINX; for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { cp.red.usp = pvar.pw++; for( b = ps->Shade.skipHilight + ps->Shade.skipShadow; b--; cp.red.usp += ps->AsicReg.RD_Pixels ) *cp.green.ulp -= *cp.red.usp; *cp.blue.usp = (UShort)(*cp.green.ulp / ps->Shade.dwDiv); cp.blue.usp++; cp.green.ulp++; } } } else { if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { psum.pulrgb = (pRGBULongDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; pwsum = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { pwsum->Red = (UShort)(psum.pulrgb->Red >> 5); pwsum->Green = (UShort)(psum.pulrgb->Green >> 5); pwsum->Blue = (UShort)(psum.pulrgb->Blue >> 5); psum.pulrgb++; pwsum++; } } else { cp.green.ulp = (pULong)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; cp.blue.usp = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; for (var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { *cp.blue.usp = (UShort)(*cp.green.ulp >> 5); cp.blue.usp++; cp.green.ulp++; } } } /* Process negative & transparency here */ if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) TPAP98003FindCenterPointer( ps ); if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) TPAP98003Reshading( ps ); pRGB = (pRGBUShortDef)&ps->Shade.pCcdDac->GainResize; if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { pwsum = (pRGBUShortDef)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { if ((short)(pwsum->Red -= ps->Shade.DarkOffset.Colors.Red) > 0) { pwsum->Red = pwsum->Red * pRGB->Red / 100U; if( pwsum->Red > 0xfff ) pwsum->Red = 0xfff; } else pwsum->Red = 0; if((short)(pwsum->Green -= ps->Shade.DarkOffset.Colors.Green) > 0) { pwsum->Green = pwsum->Green * pRGB->Green / 100U; if( pwsum->Green > 0xfff ) pwsum->Green = 0xfff; } else pwsum->Green = 0; if ((short)(pwsum->Blue -= ps->Shade.DarkOffset.Colors.Blue) > 0) { pwsum->Blue = pwsum->Blue * pRGB->Blue / 100U; if( pwsum->Blue > 0xfff ) pwsum->Blue = 0xfff; } else pwsum->Blue = 0; wR = (UShort)(pwsum->Red >> 4); pwsum->Red <<= 12; pwsum->Red |= wR; wR = (UShort)(pwsum->Green >> 4); pwsum->Green <<= 12; pwsum->Green |= wR; wR = (UShort)(pwsum->Blue>> 4); pwsum->Blue <<= 12; pwsum->Blue |= wR; pwsum++; } } else { cp.green.usp = (pUShort)ps->Bufs.b2.pSumBuf + _SHADING_BEGINX; for( var.dwValue = ps->AsicReg.RD_Pixels - _SHADING_BEGINX; var.dwValue--;) { if((short)(*cp.green.usp -= ps->Shade.DarkOffset.Colors.Green) > 0) { *cp.green.usp = *cp.green.usp * pRGB->Green / 100U; if( *cp.green.usp > 0xfff ) *cp.green.usp = 0xfff; } else *cp.green.usp = 0; wR = (UShort)(*cp.green.usp >> 4); *cp.green.usp <<= 12; *cp.green.usp |= wR; cp.green.usp++; } } /* DownloadShadingAndSetDark() */ dacP98DownloadShadingTable( ps, ps->Bufs.b2.pSumBuf, (5400 * 3 * 2)); } /** */ static void dacP98003AdjustDark( pScanData ps ) { ULong i; UShort wDarks[3]; DBG( DBG_LOW, "dacP98003AdjustDark()\n" ); ps->Shade.DarkDAC.Colors = ps->Shade.pCcdDac->DarkDAC.Colors; ps->Shade.fStop = _FALSE; for( i = 16; i-- && !ps->Shade.fStop;) { ps->Shade.fStop = _TRUE; /* FillDarkToDAC() */ DacP98003FillToDAC( ps, &ps->Device.RegDACOffset, &ps->Shade.DarkDAC ); IODataToRegister( ps, ps->RegModeControl, _ModeIdle ); ps->AsicReg.RD_ScanControl = (_SCAN_12BITMODE + _SCAN_1ST_AVERAGE); IOSelectLampSource( ps ); IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; ps->AsicReg.RD_Origin = _SHADING_BEGINX; ps->AsicReg.RD_Pixels = 512; if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) ps->AsicReg.RD_Dpi = 300; else ps->AsicReg.RD_Dpi = 600; /* PauseColorMotorRunStates () */ memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->a_nbNewAdrPointer[1] = 0x77; IOPutOnAllRegisters( ps ); _DODELAY( 70 ); /* read one shading line and work on it */ if( IOReadOneShadingLine(ps, (pUChar)ps->Bufs.b1.pShadingRam, 512*2)) { if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { wDarks[0] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam ); wDarks[1] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam + ps->AsicReg.RD_Pixels ); wDarks[2] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam + ps->AsicReg.RD_Pixels * 2UL); if( !wDarks[0] || !wDarks[1] || !wDarks[2] ) { ps->Shade.fStop = _FALSE; } else { ps->Shade.DarkOffset.wColors[0] = wDarks[0]; ps->Shade.DarkOffset.wColors[1] = wDarks[1]; ps->Shade.DarkOffset.wColors[2] = wDarks[2]; (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac, _CHANNEL_RED, wDarks[0] ); (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac, _CHANNEL_GREEN, wDarks[1] ); (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac, _CHANNEL_BLUE, wDarks[2] ); } } else { wDarks[1] = dacP98003SumDarks( ps, ps->Bufs.b1.pShadingRam + ps->AsicReg.RD_Pixels ); if (!wDarks[1] ) ps->Shade.fStop = _FALSE; else { ps->Shade.DarkOffset.wColors[1] = wDarks[1]; (*(ps->Device).fnDACDark)( ps, ps->Shade.pCcdDac, _CHANNEL_GREEN, wDarks[1] ); } } } else ps->Shade.fStop = _FALSE; } /* CalculateDarkDependOnCCD() */ if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { (*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_RED ); (*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_GREEN ); (*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_BLUE ); } else (*(ps->Device).fnDarkOffset)( ps, ps->Shade.pCcdDac, _CHANNEL_GREEN ); } /** */ static Bool dacP98003WaitForShading( pScanData ps ) { ULong i, tmp; Byte bScanControl; DBG( DBG_LOW, "dacP98003WaitForShading()\n" ); /* * before getting the shading data, (re)init the ASIC */ ps->ReInitAsic( ps, _TRUE ); ps->Shade.DarkOffset.Colors.Red = 0; ps->Shade.DarkOffset.Colors.Green = 0; ps->Shade.DarkOffset.Colors.Blue = 0; IORegisterToScanner( ps, ps->RegResetMTSC ); IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl); IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType ); IODataToRegister( ps, ps->RegScanControl1, (_SCANSTOPONBUFFULL| _MFRC_BY_XSTEP)); ps->GotoShadingPosition( ps ); bScanControl = ps->AsicReg.RD_ScanControl; /* SetShadingMapForGainDark */ memset( ps->Bufs.b2.pSumBuf, 0xff, (5400 * 3 * 2)); /* DownloadShadingAndSetDark() */ dacP98DownloadShadingTable( ps, ps->Bufs.b2.pSumBuf, (5400 * 3 * 2)); for( i = 0, tmp = 0; i < 1024; tmp += 0x01010101, i += 4 ) { ps->Bufs.b1.Buf.pdw[i] = ps->Bufs.b1.Buf.pdw[i+1] = ps->Bufs.b1.Buf.pdw[i+2] = ps->Bufs.b1.Buf.pdw[i+3] = tmp; } memcpy( ps->Bufs.b1.pShadingMap + 4096, ps->Bufs.b1.pShadingMap, 4096 ); memcpy( ps->Bufs.b1.pShadingMap + 8192, ps->Bufs.b1.pShadingMap, 4096 ); dacP98DownloadMapTable( ps, ps->Bufs.b1.pShadingMap ); DBG( DBG_LOW, "wExposure = %u\n", ps->Shade.wExposure); DBG( DBG_LOW, "wXStep = %u\n", ps->Shade.wXStep); ps->AsicReg.RD_LineControl = (_LOBYTE(ps->Shade.wExposure)); ps->AsicReg.RD_ExtLineControl = (_HIBYTE(ps->Shade.wExposure)); IODataToRegister(ps, ps->RegExtendedLineControl, ps->AsicReg.RD_ExtLineControl ); IODataToRegister(ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); dacP98003AdjustRGBGain( ps ); dacP98003AdjustDark( ps ); dacP98003AdjustShadingWaveform( ps ); ps->AsicReg.RD_ScanControl = bScanControl; /* here we have to download the table in any case...*/ dacP98DownloadMapTable( ps, ps->a_bMapTable ); MotorP98003BackToHomeSensor( ps ); return _TRUE; } /************************ exported functions *********************************/ /** */ _LOC int DacInitialize( pScanData ps ) { DBG( DBG_HIGH, "DacInitialize()\n" ); if( NULL == ps ) return _E_NULLPTR; /* * depending on the asic, we set some functions */ if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->WaitForShading = dacP98003WaitForShading; } else if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ps->WaitForShading = dacP98WaitForShading; } else if( _ASIC_IS_96003 == ps->sCaps.AsicID ) { ps->WaitForShading = dacP96003WaitForShading; } else if( _ASIC_IS_96001 == ps->sCaps.AsicID ) { ps->WaitForShading = dacP96001WaitForShading; } else { DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); return _E_NOSUPP; } return _OK; } /** Fill out the R/G/B GainOut value */ _LOC void DacP98FillGainOutDirectPort( pScanData ps ) { ps->OpenScanPath( ps ); IODataRegisterToDAC( ps, 0x28, ps->bRedGainIndex ); IODataRegisterToDAC( ps, 0x29, ps->bGreenGainIndex ); IODataRegisterToDAC( ps, 0x2a, ps->bBlueGainIndex ); ps->CloseScanPath( ps ); } /** */ _LOC void DacP98FillShadingDarkToShadingRegister( pScanData ps ) { pUChar pValue; Byte bReg; DBG( DBG_LOW, "DacP98FillShadingDarkToShadingRegister()\n" ); ps->AsicReg.RD_RedDarkOff = ps->Shade.DarkOffset.Colors.Red; ps->AsicReg.RD_GreenDarkOff = ps->Shade.DarkOffset.Colors.Green; ps->AsicReg.RD_BlueDarkOff = ps->Shade.DarkOffset.Colors.Blue; pValue = (pUChar)&ps->AsicReg.RD_RedDarkOff; for (bReg = ps->RegRedChDarkOffsetLow; bReg <= ps->RegBlueChDarkOffsetHigh; bReg++, pValue++) { IODataToRegister( ps, bReg, *pValue ); } } /** */ _LOC void DacP98AdjustDark( pScanData ps ) { Byte bCorrectTimes; /* used to be a global var !*/ DBG( DBG_LOW, "DacP98AdjustDark()\n" ); ps->Shade.pCcdDac->DarkDAC.Colors.Red = ps->bsPreRedDAC; ps->Shade.pCcdDac->DarkDAC.Colors.Green = ps->bsPreGreenDAC; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = ps->bsPreBlueDAC; if( ps->DataInf.dwScanFlag & SCANDEF_Negative ) { bCorrectTimes = 6; } else { bCorrectTimes = 5; } /* CHANGE ** original code seems to be buggy : for (bCorrectTimes ; bCorrectTimes--;) { */ for (;bCorrectTimes ; bCorrectTimes-- ) { ps->OpenScanPath( ps ); dacP98FillDarkDAC( ps ); dacP98SetReadFBKRegister( ps ); ps->CloseScanPath( ps ); IOPutOnAllRegisters( ps ); ps->PauseColorMotorRunStates( ps ); /* stop scan states */ IOReadOneShadingLine( ps, ps->pScanBuffer1, 512*2 ); dacP98FillChannelDarkLevelControl( ps ); if(dacP98CheckChannelDarkLevel( ps )) break; } ps->Shade.DarkOffset.Colors.Red= dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Red, ps->Shade.pCcdDac->DarkCmpHi.Colors.Red, ps->Shade.pCcdDac->DarkOffSub.Colors.Red ); ps->Shade.DarkOffset.Colors.Green = dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Green, ps->Shade.pCcdDac->DarkCmpHi.Colors.Green, ps->Shade.pCcdDac->DarkOffSub.Colors.Green ); ps->Shade.DarkOffset.Colors.Blue = dacP98CalDarkOff( ps, ps->Shade.DarkOffset.Colors.Blue, ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue, ps->Shade.pCcdDac->DarkOffSub.Colors.Blue ); } /** */ _LOC void DacP96WriteBackToGammaShadingRAM( pScanData ps ) { /* ModifyGammaShadingOffset(ps) */ ps->OpenScanPath( ps); IODataToRegister( ps, ps->RegRedChShadingOffset, ps->Asic96Reg.u28.RD_RedChShadingOff ); IODataToRegister( ps, ps->RegGreenChShadingOffset, (Byte)((ULong)ps->Asic96Reg.u29.RD_GreenChShadingOff * 96UL/100UL)); IODataToRegister( ps, ps->RegBlueChShadingOffset, (Byte)((ULong)ps->Asic96Reg.RD_BlueChShadingOff * 91UL/100UL)); ps->CloseScanPath( ps ); dacP96WriteLinearGamma( ps, ps->pPrescan16, 256, ps->ShadingBankRed); dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize, 256, ps->ShadingBankGreen); dacP96WriteLinearGamma( ps, ps->pPrescan16 + ps->ShadingBankSize * 2, 256, ps->ShadingBankBlue); } /** */ _LOC void DacP98003FillToDAC( pScanData ps, pRGBByteDef regs, pColorByte data ) { if ( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { dacP98003GainOffsetToDAC( ps, _DAC_RED, regs->Red, data->Colors.Red ); dacP98003GainOffsetToDAC( ps, _DAC_GREENCOLOR, regs->Green, data->Colors.Green ); dacP98003GainOffsetToDAC( ps, _DAC_BLUE, regs->Blue, data->Colors.Blue ); } else { dacP98003GainOffsetToDAC( ps, _DAC_GREENMONO, regs->Green, data->Colors.Green ); } } /** */ _LOC void DacP98003AdjustGain( pScanData ps, ULong color, Byte hilight ) { if( hilight < ps->Shade.bGainLow ) { if( ps->Shade.Hilight.bColors[color] < ps->Shade.bGainHigh ) { ps->Shade.fStop = _FALSE; ps->Shade.Hilight.bColors[color] = hilight; if( hilight <= (Byte)(ps->Shade.bGainLow - hilight)) ps->Shade.Gain.bColors[color] += ps->Shade.bGainDouble; else ps->Shade.Gain.bColors[color]++; } } else { if( hilight > ps->Shade.bGainHigh ) { ps->Shade.fStop = _FALSE; ps->Shade.Hilight.bColors[color] = hilight; ps->Shade.Gain.bColors[color]--; } else ps->Shade.Hilight.bColors[color] = hilight; } if( ps->Shade.Gain.bColors[color] > ps->Shade.bMaxGain ) { ps->Shade.Gain.bColors[color] = ps->Shade.bMaxGain; } } /** */ _LOC Byte DacP98003SumGains( pUChar pb, ULong pixelsLine ) { Byte bHilight, tmp; ULong dwPixels, dwAve; UShort sum; for( bHilight = 0, dwPixels = pixelsLine >> 4; dwPixels--; ) { for( sum = 0, dwAve = 16; dwAve--; pb++) sum += (UShort)*pb; sum >>= 4; tmp = (Byte)sum; if( tmp > bHilight ) bHilight = tmp; } return bHilight; } /* END PLUSTEK-PP_DAC.C .....................................................*/ sane-backends-1.0.27/backend/snapscan-data.c0000664000175000017500000124406512112021330015467 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2006 Oliver Schwartz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file contains static calibration data for the Benq 5150C scanner. Once it is known how calibration for this scanner works this file becomes obsolete. */ /* $Id$ SANE SnapScan backend */ static const SANE_Byte calibration_data_5150[] = { 0x78,0x01,0xcc,0x47,0xca,0x53,0xcd,0x4a,0xd0,0x57,0xd5,0x46,0xda,0x56,0xdd,0x49, 0xe2,0x50,0xe1,0x47,0xe0,0x51,0xdf,0x4b,0xdc,0x4f,0xd4,0x52,0xd0,0x52,0xcd,0x4a, 0xcd,0x4e,0xcf,0x46,0xd1,0x50,0xd8,0x4d,0xdc,0x53,0xdf,0x4c,0xe5,0x4f,0xe2,0x45, 0xe2,0x53,0xe3,0x4b,0xde,0x50,0xd8,0x4b,0xd4,0x55,0xcf,0x4a,0xd0,0x50,0xd0,0x49, 0xd4,0x4f,0xd8,0x49,0xe0,0x4d,0xe3,0x4a,0xe4,0x55,0xe7,0x47,0xe7,0x4f,0xe5,0x46, 0xe1,0x51,0xdd,0x4a,0xd6,0x4d,0xd2,0x46,0xcd,0x51,0xcd,0x44,0xd3,0x54,0xd6,0x48, 0xdb,0x51,0xe2,0x4a,0xe5,0x4f,0xe7,0x4b,0xe8,0x54,0xe5,0x4e,0xe0,0x4e,0xdc,0x47, 0xd9,0x50,0xd4,0x48,0xd2,0x4c,0xd3,0x46,0xd6,0x4f,0xd9,0x4a,0xdf,0x4e,0xe1,0x47, 0xe6,0x4e,0xe6,0x4d,0xe7,0x4e,0xe5,0x4a,0xe2,0x55,0xdc,0x47,0xd7,0x54,0xd2,0x4a, 0xd1,0x50,0xce,0x45,0xd2,0x4e,0xd6,0x4a,0xd9,0x50,0xde,0x4a,0xe2,0x4d,0xe2,0x45, 0xe5,0x4f,0xe3,0x4c,0xe0,0x4c,0xdc,0x4d,0xd4,0x51,0xd0,0x47,0xce,0x4d,0xcc,0x45, 0xcd,0x50,0xd1,0x48,0xd4,0x4c,0xd8,0x48,0xda,0x55,0xde,0x4c,0xdd,0x4d,0xdb,0x46, 0xda,0x52,0xd6,0x4b,0xd1,0x4f,0xcc,0x45,0xc9,0x4e,0xc7,0x48,0xc8,0x4e,0xcb,0x47, 0xd0,0x51,0xd4,0x4b,0xd8,0x50,0xda,0x4a,0xdc,0x55,0xdb,0x45,0xd8,0x50,0xd4,0x4c, 0xcf,0x53,0xca,0x45,0xc7,0x4b,0xc6,0x4a,0xc5,0x56,0xc7,0x47,0xcb,0x50,0xd2,0x4a, 0xd5,0x55,0xd7,0x4a,0xda,0x4f,0xda,0x4a,0xd7,0x52,0xd4,0x4b,0xcf,0x54,0xca,0x46, 0xc6,0x51,0xc5,0x4a,0xc5,0x51,0xc7,0x46,0xca,0x54,0xd0,0x4b,0xd3,0x51,0xd6,0x4a, 0xd9,0x53,0xd9,0x47,0xd8,0x4d,0xd5,0x48,0xd0,0x53,0xca,0x47,0xc8,0x4c,0xc5,0x48, 0xc5,0x52,0xc6,0x49,0xcb,0x4f,0xcd,0x47,0xd1,0x51,0xd6,0x49,0xd8,0x52,0xd7,0x43, 0xd7,0x4d,0xd5,0x4a,0xcf,0x53,0xca,0x49,0xc7,0x50,0xc3,0x47,0xc1,0x51,0xc5,0x46, 0xca,0x4d,0xcc,0x49,0xd2,0x52,0xd6,0x4c,0xd8,0x52,0xd8,0x47,0xd7,0x50,0xd4,0x49, 0xd2,0x4c,0xcc,0x48,0xc9,0x4d,0xc6,0x47,0xc4,0x54,0xc6,0x45,0xc8,0x50,0xcd,0x46, 0xd1,0x51,0xd4,0x44,0xd7,0x51,0xd7,0x46,0xd7,0x53,0xd5,0x4a,0xd2,0x4d,0xcd,0x45, 0xcb,0x4f,0xc8,0x4c,0xc7,0x4d,0xc8,0x48,0xca,0x51,0xcd,0x45,0xd2,0x50,0xd6,0x48, 0xda,0x50,0xdb,0x48,0xdb,0x4f,0xd8,0x47,0xd5,0x53,0xd1,0x4b,0xcc,0x51,0xc9,0x49, 0xc9,0x4f,0xc7,0x4f,0xc9,0x53,0xcf,0x4a,0xd2,0x55,0xd7,0x49,0xda,0x4e,0xdc,0x48, 0xdc,0x52,0xda,0x48,0xd7,0x4e,0xd3,0x4d,0xce,0x51,0xcc,0x4a,0xc8,0x4e,0xc9,0x47, 0xcb,0x51,0xd1,0x49,0xd6,0x4a,0xd9,0x47,0xdd,0x53,0xdd,0x46,0xdf,0x4e,0xdc,0x4b, 0xd8,0x51,0xd3,0x4c,0xd0,0x4c,0xcd,0x4a,0xc9,0x52,0xc8,0x4a,0xca,0x50,0xd0,0x4a, 0xd5,0x51,0xd9,0x49,0xde,0x4d,0xe0,0x48,0xe0,0x54,0xe0,0x4b,0xda,0x50,0xd7,0x48, 0xd2,0x50,0xce,0x49,0xcc,0x50,0xcb,0x45,0xcd,0x55,0xd0,0x49,0xd5,0x4f,0xda,0x49, 0xde,0x4f,0xdf,0x49,0xdf,0x4e,0xdf,0x48,0xdd,0x52,0xd8,0x4c,0xd3,0x51,0xcd,0x49, 0xcc,0x52,0xc9,0x44,0xca,0x4f,0xce,0x4c,0xd4,0x54,0xd7,0x48,0xdc,0x50,0xe0,0x49, 0xe0,0x52,0xdf,0x49,0xdc,0x4c,0xd7,0x4b,0xd3,0x50,0xd0,0x48,0xca,0x50,0xca,0x4a, 0xcc,0x50,0xcf,0x47,0xd2,0x51,0xd8,0x47,0xdd,0x53,0xe0,0x49,0xdf,0x51,0xde,0x46, 0xdc,0x52,0xd9,0x46,0xd4,0x4e,0xce,0x45,0xcc,0x52,0xc9,0x49,0xc9,0x55,0xcc,0x46, 0xd0,0x4d,0xd6,0x48,0xd9,0x4d,0xda,0x48,0xdf,0x52,0xdb,0x4a,0xde,0x50,0xd7,0x48, 0xd6,0x50,0xcd,0x47,0xca,0x50,0xc8,0x48,0xc8,0x52,0xcb,0x48,0xcf,0x50,0xd2,0x46, 0xd8,0x51,0xdb,0x49,0xde,0x4e,0xdd,0x48,0xda,0x52,0xd8,0x49,0xd3,0x4e,0xce,0x49, 0xc9,0x50,0xc8,0x4b,0xc9,0x4f,0xcb,0x46,0xcc,0x52,0xd2,0x4b,0xda,0x4f,0xdc,0x45, 0xdb,0x4f,0xdc,0x48,0xde,0x4e,0xda,0x44,0xd4,0x4f,0xcb,0x46,0xca,0x4e,0xc9,0x4b, 0xc3,0x52,0xc6,0x46,0xcb,0x4e,0xd2,0x4c,0xd5,0x52,0xd8,0x49,0xda,0x51,0xdc,0x49, 0xdc,0x51,0xd6,0x45,0xd3,0x4f,0xcd,0x49,0xc9,0x51,0xc5,0x4a,0xc5,0x54,0xc6,0x46, 0xc8,0x54,0xd0,0x48,0xd5,0x4c,0xd6,0x46,0xdb,0x51,0xdd,0x48,0xda,0x50,0xd7,0x44, 0xd3,0x4d,0xce,0x47,0xc9,0x52,0xc6,0x46,0xc5,0x56,0xc7,0x48,0xcb,0x53,0xce,0x48, 0xd5,0x4e,0xd9,0x4b,0xdc,0x4f,0xdc,0x48,0xdd,0x54,0xdb,0x49,0xd3,0x52,0xce,0x49, 0xcc,0x50,0xc6,0x4a,0xc5,0x4e,0xc7,0x46,0xcb,0x50,0xce,0x46,0xd4,0x4e,0xd7,0x46, 0xdb,0x4b,0xdc,0x47,0xdc,0x51,0xda,0x49,0xd5,0x56,0xd2,0x4a,0xcd,0x4b,0xc9,0x49, 0xc8,0x4f,0xc8,0x48,0xca,0x4c,0xce,0x47,0xd3,0x52,0xd8,0x4a,0xdc,0x51,0xdc,0x46, 0xdc,0x4c,0xdc,0x48,0xd9,0x4d,0xd1,0x47,0xcc,0x58,0xc8,0x46,0xc7,0x54,0xc6,0x48, 0xc8,0x4a,0xca,0x47,0xd2,0x4c,0xd4,0x45,0xd7,0x50,0xd9,0x4a,0xda,0x4e,0xd8,0x46, 0xd5,0x51,0xd0,0x43,0xcb,0x4f,0xc6,0x45,0xc4,0x52,0xc7,0x43,0xc8,0x52,0xcb,0x45, 0xcf,0x51,0xd5,0x46,0xd9,0x4f,0xda,0x4b,0xda,0x53,0xd9,0x46,0xd6,0x4e,0xd1,0x48, 0xcb,0x51,0xc6,0x46,0xc6,0x4b,0xc4,0x40,0xc5,0x51,0xcb,0x47,0xd0,0x4d,0xd4,0x48, 0xd7,0x52,0xd1,0x4d,0xdc,0x34,0xdb,0x2f,0xd9,0x37,0xd4,0x30,0xce,0x40,0xcb,0x33, 0xca,0x3e,0xca,0x34,0xcc,0x32,0xd0,0x2f,0xd5,0x37,0xd7,0x30,0xda,0x37,0xdd,0x2d, 0xdc,0x34,0xd9,0x30,0xd7,0x34,0xd3,0x2d,0xcc,0x35,0xca,0x2c,0xc7,0x33,0xc8,0x2e, 0xca,0x37,0xcd,0x30,0xd1,0x35,0xd6,0x2d,0xd8,0x38,0xda,0x2c,0xda,0x37,0xd8,0x2d, 0xd6,0x36,0xd3,0x2e,0xc8,0x32,0xc7,0x2f,0xc5,0x32,0xc6,0x2a,0xc8,0x38,0xca,0x2a, 0xd0,0x36,0xd5,0x2e,0xd6,0x37,0xd9,0x2c,0xd9,0x31,0xd7,0x2e,0xd4,0x35,0xcf,0x30, 0xcb,0x34,0xc9,0x2c,0xc4,0x32,0xc3,0x2e,0xc6,0x35,0xc9,0x2d,0xcc,0x34,0xd1,0x2d, 0xd3,0x32,0xd5,0x2d,0xd6,0x36,0xd4,0x2d,0xd0,0x32,0xcd,0x30,0xc8,0x35,0xc5,0x2f, 0xc2,0x36,0xc2,0x2d,0xc2,0x35,0xc4,0x2b,0xc9,0x39,0xcf,0x2f,0xd1,0x32,0xd3,0x2c, 0xd7,0x38,0xd4,0x2f,0xd0,0x30,0xcd,0x2d,0xc9,0x39,0xc5,0x30,0xc3,0x35,0xc2,0x31, 0xc3,0x35,0xc5,0x28,0xc8,0x33,0xcc,0x30,0xd0,0x37,0xd3,0x2e,0xd3,0x39,0xd0,0x2a, 0xd0,0x34,0xcc,0x2e,0xc8,0x35,0xc3,0x2d,0xc0,0x35,0xbe,0x2d,0xbe,0x33,0xc2,0x2d, 0xc5,0x33,0xca,0x2b,0xcd,0x36,0xcf,0x2a,0xd3,0x36,0xd2,0x29,0xd0,0x36,0xce,0x2e, 0xca,0x38,0xc5,0x2a,0xc1,0x34,0xbf,0x2c,0xbf,0x35,0xc3,0x2d,0xc5,0x36,0xcb,0x2a, 0xd0,0x37,0xd2,0x31,0xd5,0x3a,0xd5,0x2c,0xd2,0x37,0xd1,0x2d,0xcd,0x35,0xc9,0x2c, 0xc7,0x35,0xc4,0x2d,0xc3,0x34,0xc4,0x2c,0xc8,0x3a,0xcd,0x2e,0xd0,0x37,0xd4,0x2e, 0xd5,0x32,0xd6,0x2d,0xd3,0x35,0xd0,0x2e,0xcd,0x34,0xc9,0x2d,0xc6,0x38,0xc3,0x2c, 0xc3,0x33,0xc5,0x2d,0xc8,0x33,0xcc,0x2a,0xcf,0x33,0xd4,0x2d,0xd6,0x34,0xd5,0x2e, 0xd4,0x35,0xd0,0x28,0xcc,0x35,0xc8,0x2c,0xc6,0x36,0xc3,0x2d,0xc1,0x38,0xc2,0x2d, 0xc4,0x35,0xc9,0x2f,0xcd,0x31,0xcf,0x2d,0xd4,0x35,0xd5,0x2f,0xd4,0x36,0xd2,0x2e, 0xce,0x36,0xc8,0x2a,0xc5,0x36,0xc1,0x2a,0xc1,0x36,0xc2,0x2f,0xc6,0x3a,0xca,0x2f, 0xce,0x3a,0xd2,0x2f,0xd2,0x33,0xd4,0x2f,0xd5,0x39,0xd3,0x2d,0xce,0x33,0xca,0x2b, 0xc8,0x3c,0xc4,0x2f,0xc0,0x33,0xc2,0x2c,0xc6,0x35,0xc9,0x2f,0xcb,0x32,0xd0,0x2a, 0xd3,0x37,0xd5,0x2f,0xd3,0x31,0xd1,0x33,0xd0,0x35,0xcd,0x2c,0xc8,0x34,0xc6,0x2c, 0xc4,0x32,0xc4,0x31,0xc5,0x35,0xc7,0x30,0xcc,0x33,0xd2,0x2e,0xd6,0x35,0xd6,0x2e, 0xd6,0x36,0xd5,0x2f,0xd2,0x38,0xcc,0x2f,0xc9,0x36,0xc4,0x30,0xc4,0x33,0xc2,0x27, 0xc5,0x34,0xc9,0x2d,0xcc,0x32,0xcf,0x2c,0xd4,0x33,0xd6,0x30,0xd6,0x34,0xd4,0x2d, 0xd3,0x39,0xce,0x30,0xca,0x36,0xc6,0x2e,0xc3,0x36,0xc2,0x30,0xc4,0x32,0xc8,0x2d, 0xcd,0x35,0xd1,0x2f,0xd2,0x33,0xd3,0x2c,0xd6,0x36,0xd3,0x2f,0xcf,0x36,0xcd,0x2e, 0xc9,0x36,0xc5,0x2c,0xc2,0x32,0xc2,0x2e,0xc3,0x34,0xc7,0x2e,0xca,0x33,0xd0,0x2e, 0xd3,0x39,0xd3,0x30,0xd4,0x34,0xd4,0x2d,0xd2,0x35,0xcd,0x32,0xc9,0x33,0xc6,0x2f, 0xc4,0x37,0xc2,0x2c,0xc2,0x35,0xc5,0x2d,0xc9,0x35,0xcd,0x2f,0xce,0x36,0xd2,0x2d, 0xd2,0x36,0xd3,0x2f,0xcf,0x38,0xcc,0x2f,0xc8,0x37,0xc3,0x30,0xc1,0x36,0xbf,0x2f, 0xc1,0x39,0xc3,0x30,0xc7,0x32,0xcc,0x2a,0xd0,0x38,0xd0,0x30,0xd1,0x36,0xd1,0x2c, 0xcf,0x37,0xca,0x30,0xc5,0x37,0xc2,0x2c,0xc1,0x37,0xc0,0x2f,0xbf,0x38,0xc1,0x2e, 0xc6,0x38,0xca,0x2e,0xce,0x35,0xd1,0x2b,0xd3,0x35,0xd3,0x2c,0xd0,0x39,0xcd,0x2a, 0xca,0x36,0xc6,0x2e,0xc1,0x34,0xbe,0x31,0xc0,0x36,0xc1,0x2f,0xc4,0x39,0xc8,0x2a, 0xce,0x35,0xcf,0x2d,0xcf,0x31,0xd0,0x2d,0xce,0x35,0xcb,0x2c,0xc7,0x36,0xc4,0x29, 0xc2,0x35,0xbf,0x2f,0xbe,0x32,0xc0,0x2e,0xc3,0x38,0xc8,0x2e,0xca,0x36,0xcd,0x30, 0xcf,0x33,0xd0,0x2d,0xcd,0x34,0xca,0x2f,0xc7,0x35,0xc0,0x30,0xc1,0x35,0xbd,0x2e, 0xbc,0x32,0xbe,0x2d,0xc0,0x38,0xc5,0x31,0xca,0x37,0xcd,0x2d,0xce,0x37,0xce,0x2d, 0xce,0x37,0xcb,0x30,0xc8,0x36,0xc3,0x2f,0xc0,0x35,0xbc,0x32,0xbb,0x35,0xbc,0x2c, 0xc0,0x38,0xc5,0x2d,0xc7,0x33,0xc8,0x2f,0xcc,0x37,0xcd,0x2d,0xca,0x37,0xc8,0x31, 0xc5,0x36,0xc2,0x2e,0xbe,0x35,0xba,0x30,0xbb,0x39,0xba,0x30,0xbd,0x34,0xc2,0x2f, 0xc6,0x38,0xc8,0x2e,0xca,0x32,0xcb,0x30,0xc9,0x33,0xc7,0x2e,0xc4,0x35,0xbf,0x2c, 0xbd,0x37,0xb9,0x2c,0xb7,0x37,0xb8,0x2f,0xbb,0x36,0xbf,0x2c,0xc3,0x33,0xc4,0x31, 0xc7,0x31,0xc9,0x31,0xc8,0x34,0xc4,0x30,0xc2,0x34,0xc1,0x2b,0xbb,0x38,0xb8,0x30, 0xb8,0x34,0xb8,0x2e,0xb9,0x33,0xbd,0x2e,0xc2,0x37,0xc7,0x2b,0xc9,0x34,0xc8,0x2e, 0xc9,0x31,0xc9,0x2c,0xc4,0x33,0xbf,0x30,0xbb,0x35,0xba,0x2d,0xb9,0x39,0xb9,0x2c, 0xba,0x32,0xbc,0x30,0xc2,0x35,0xc5,0x2a,0xc8,0x36,0xc7,0x2e,0xc7,0x33,0xc7,0x2c, 0xc4,0x38,0xc0,0x2e,0xbb,0x32,0xb8,0x2d,0xb7,0x37,0xb6,0x2e,0xb8,0x36,0xbb,0x2f, 0xc1,0x37,0xc4,0x2f,0xc6,0x32,0xc8,0x29,0xc8,0x37,0xc8,0x2f,0xc4,0x37,0xc0,0x2c, 0xbc,0x32,0xbb,0x2d,0xb8,0x36,0xb6,0x2a,0xb7,0x32,0xbb,0x2f,0xbf,0x33,0xc2,0x30, 0xc6,0x38,0xc8,0x2c,0xc8,0x32,0xc6,0x2e,0xc5,0x37,0xc1,0x2c,0xbd,0x39,0xba,0x2d, 0xb8,0x32,0xb7,0x2b,0xb8,0x39,0xba,0x2f,0xbf,0x33,0xc3,0x2f,0xc6,0x34,0xc8,0x2c, 0xc9,0x36,0xc7,0x32,0xc2,0x30,0xbe,0x2f,0xbd,0x34,0xb9,0x2b,0xb4,0x34,0xb5,0x2e, 0xb7,0x37,0xb9,0x2b,0xbb,0x35,0xc1,0x2b,0xc5,0x39,0xc7,0x2f,0xc6,0x32,0xc6,0x2a, 0xc6,0x37,0xbe,0x30,0xbc,0x36,0xb8,0x31,0xb7,0x38,0xb4,0x29,0xb4,0x30,0xb8,0x25, 0xbb,0x30,0xbf,0x2c,0xc3,0x36,0xc5,0x2e,0xc5,0x38,0xbc,0x32,0xc2,0x51,0xc0,0x4c, 0xbd,0x52,0xb9,0x57,0xb6,0x61,0xb4,0x57,0xb6,0x5b,0xb9,0x51,0xbd,0x56,0xc0,0x50, 0xc3,0x56,0xc4,0x51,0xc6,0x56,0xc4,0x54,0xc2,0x55,0xbf,0x51,0xba,0x5a,0xb8,0x4f, 0xb6,0x57,0xb4,0x4f,0xb5,0x54,0xb8,0x4f,0xbd,0x57,0xbd,0x50,0xc2,0x56,0xc2,0x51, 0xc2,0x56,0xc0,0x50,0xc1,0x59,0xbb,0x4f,0xb7,0x58,0xb4,0x52,0xb2,0x59,0xb1,0x51, 0xb2,0x5a,0xb5,0x52,0xbc,0x58,0xbf,0x4e,0xbe,0x55,0xc0,0x4e,0xc6,0x56,0xc2,0x4f, 0xbc,0x58,0xbe,0x4f,0xb9,0x56,0xb6,0x4f,0xb2,0x56,0xb2,0x4e,0xb3,0x5a,0xb5,0x4f, 0xb6,0x54,0xbc,0x4c,0xbf,0x55,0xbf,0x52,0xc1,0x55,0xc2,0x4f,0xc0,0x57,0xbd,0x52, 0xb8,0x58,0xb5,0x50,0xb4,0x54,0xb0,0x50,0xb2,0x5a,0xb4,0x52,0xb6,0x59,0xb9,0x4e, 0xbd,0x57,0xbf,0x4f,0xbd,0x53,0xbe,0x4f,0xbe,0x59,0xbb,0x4e,0xb7,0x57,0xb4,0x4f, 0xb0,0x55,0xad,0x4b,0xae,0x58,0xad,0x4d,0xb3,0x58,0xb6,0x50,0xbb,0x5b,0xbd,0x50, 0xbf,0x56,0xc0,0x4b,0xbc,0x57,0xba,0x4f,0xb7,0x55,0xb2,0x4e,0xae,0x5f,0xae,0x4d, 0xb0,0x55,0xb0,0x51,0xb3,0x55,0xb7,0x4f,0xbb,0x59,0xbb,0x53,0xbe,0x58,0xbd,0x50, 0xbb,0x59,0xb8,0x50,0xb6,0x54,0xb1,0x50,0xae,0x55,0xaa,0x4c,0xac,0x55,0xb0,0x4e, 0xb2,0x5b,0xb4,0x4e,0xba,0x59,0xbd,0x4f,0xbf,0x56,0xbe,0x50,0xbe,0x58,0xb9,0x51, 0xb8,0x59,0xb4,0x4f,0xb0,0x56,0xae,0x4f,0xad,0x56,0xb1,0x4d,0xb3,0x55,0xb5,0x4f, 0xb9,0x5b,0xbc,0x51,0xbe,0x58,0xbc,0x51,0xbd,0x5e,0xbb,0x51,0xb6,0x57,0xb2,0x50, 0xae,0x59,0xab,0x51,0xab,0x53,0xaa,0x50,0xaf,0x5a,0xb2,0x50,0xb6,0x56,0xba,0x50, 0xbd,0x59,0xbb,0x55,0xba,0x57,0xb9,0x4d,0xb8,0x58,0xb1,0x52,0xaf,0x58,0xad,0x4e, 0xac,0x57,0xad,0x4c,0xaf,0x55,0xb1,0x4c,0xb4,0x59,0xb6,0x51,0xbb,0x59,0xba,0x4d, 0xba,0x59,0xba,0x4f,0xb6,0x59,0xb1,0x52,0xaf,0x56,0xac,0x4f,0xaa,0x56,0xab,0x51, 0xae,0x59,0xaf,0x51,0xb0,0x57,0xb8,0x53,0xba,0x5a,0xb8,0x4d,0xba,0x57,0xb9,0x51, 0xb7,0x58,0xb1,0x52,0xae,0x59,0xac,0x51,0xac,0x56,0xaa,0x4c,0xad,0x59,0xb1,0x4f, 0xb4,0x56,0xb7,0x52,0xb9,0x57,0xbb,0x4d,0xb9,0x57,0xb9,0x52,0xb8,0x5a,0xb1,0x50, 0xae,0x57,0xae,0x4e,0xac,0x58,0xaa,0x4f,0xad,0x57,0xb2,0x4f,0xb4,0x57,0xb7,0x4b, 0xb9,0x55,0xb9,0x50,0xba,0x55,0xb5,0x4e,0xb3,0x58,0xb3,0x4f,0xae,0x55,0xa9,0x4e, 0xa9,0x53,0xab,0x4f,0xad,0x56,0xb0,0x52,0xb2,0x54,0xb6,0x52,0xba,0x5b,0xba,0x51, 0xba,0x55,0xba,0x50,0xb6,0x56,0xb3,0x4d,0xb1,0x57,0xad,0x50,0xab,0x5a,0xac,0x4f, 0xac,0x54,0xae,0x4f,0xb1,0x57,0xb4,0x51,0xb7,0x56,0xb8,0x50,0xb9,0x59,0xbb,0x4e, 0xb8,0x57,0xad,0x4e,0xa6,0x55,0xac,0x4f,0xa8,0x58,0xa0,0x4d,0xa3,0x57,0xac,0x50, 0xb0,0x55,0xb3,0x52,0xb6,0x5a,0xb7,0x4d,0xb9,0x58,0xb8,0x4d,0xb5,0x59,0xb4,0x4f, 0xaf,0x56,0xac,0x4f,0xa9,0x57,0xa8,0x4d,0xa9,0x57,0xac,0x4f,0xaf,0x59,0xb1,0x50, 0xb7,0x56,0xb6,0x4e,0xb4,0x5a,0xb6,0x4f,0xb5,0x59,0xaf,0x50,0xac,0x58,0xa9,0x4e, 0xa7,0x5a,0xa6,0x54,0xa7,0x57,0xa9,0x4b,0xad,0x59,0xaf,0x50,0xb4,0x58,0xb3,0x4f, 0xb5,0x54,0xb8,0x4f,0xb4,0x53,0xb0,0x4d,0xae,0x5a,0xac,0x50,0xa9,0x5a,0xa7,0x51, 0xa7,0x57,0xa8,0x51,0xad,0x56,0xb1,0x54,0xb5,0x5a,0xb6,0x51,0xbb,0x59,0xb8,0x52, 0xb6,0x56,0xb3,0x4d,0xb1,0x54,0xae,0x54,0xa9,0x55,0xa6,0x4f,0xa8,0x55,0xab,0x4f, 0xae,0x5c,0xaf,0x53,0xb4,0x58,0xb6,0x51,0xb7,0x5f,0xb7,0x4f,0xb6,0x56,0xb3,0x50, 0xaf,0x56,0xad,0x4f,0xa9,0x57,0xa7,0x4f,0xa9,0x59,0xaa,0x55,0xad,0x57,0xaf,0x50, 0xb3,0x54,0xb7,0x52,0xb9,0x57,0xb6,0x54,0xb5,0x58,0xb7,0x4e,0xb1,0x57,0xab,0x50, 0xaa,0x57,0xa6,0x53,0xa6,0x56,0xa8,0x51,0xa9,0x5a,0xac,0x50,0xb1,0x56,0xb3,0x4d, 0xb8,0x5a,0xb7,0x50,0xb4,0x55,0xb4,0x4e,0xb4,0x59,0xaf,0x54,0xab,0x57,0xab,0x4d, 0xaa,0x5a,0xab,0x4f,0xab,0x59,0xae,0x51,0xb3,0x5b,0xb5,0x52,0xb7,0x58,0xb7,0x50, 0xba,0x5a,0xb6,0x4e,0xb3,0x54,0xae,0x53,0xac,0x59,0xac,0x4f,0xa7,0x57,0xa6,0x51, 0xab,0x56,0xad,0x51,0xb1,0x57,0xb3,0x4f,0xb9,0x5a,0xb7,0x4d,0xb6,0x5a,0xb7,0x4f, 0xb5,0x59,0xb1,0x54,0xac,0x57,0xa8,0x51,0xa6,0x55,0xa5,0x50,0xa8,0x57,0xac,0x4f, 0xae,0x56,0xb3,0x4f,0xb6,0x58,0xb8,0x4f,0xb8,0x59,0xb4,0x4e,0xb1,0x58,0xad,0x50, 0xac,0x54,0xa6,0x4b,0xa5,0x57,0xa5,0x4e,0xa8,0x58,0xaa,0x52,0xae,0x59,0xaf,0x52, 0xb4,0x59,0xb4,0x52,0xb4,0x55,0xb2,0x54,0xb2,0x57,0xad,0x4d,0xa8,0x55,0xa8,0x4e, 0xa6,0x55,0xa4,0x53,0xa5,0x56,0xa9,0x4d,0xae,0x58,0xb1,0x4d,0xb2,0x58,0xb4,0x51, 0xb6,0x5a,0xb5,0x51,0xb1,0x53,0xae,0x51,0xab,0x58,0xa8,0x51,0xa4,0x58,0xa4,0x4c, 0xa7,0x58,0xaa,0x4e,0xac,0x51,0xb0,0x4f,0xb4,0x59,0xb6,0x54,0xb5,0x56,0xb5,0x50, 0xb5,0x57,0xb0,0x52,0xac,0x50,0xaa,0x4b,0xa5,0x58,0xa2,0x50,0xa7,0x58,0xa8,0x4d, 0xaa,0x5b,0xad,0x50,0xb3,0x56,0xb7,0x4f,0xb6,0x57,0xb4,0x54,0xb2,0x55,0xb0,0x50, 0xad,0x5a,0xa9,0x51,0xa5,0x54,0xa6,0x4f,0xa8,0x54,0xa8,0x54,0xab,0x58,0xae,0x50, 0xb4,0x5a,0xb6,0x51,0xb6,0x56,0xad,0x4c,0xb2,0x58,0xb2,0x4f,0xa8,0x5d,0xa2,0x4b, 0xa7,0x54,0xa7,0x50,0xa5,0x57,0xa9,0x4e,0xac,0x57,0xae,0x53,0xb3,0x5a,0xb4,0x50, 0xb7,0x59,0xb6,0x50,0xb4,0x54,0xb1,0x4e,0xad,0x5c,0xa8,0x50,0xa5,0x57,0xa4,0x4f, 0xa2,0x5b,0xa5,0x4a,0xa8,0x4e,0xad,0x48,0xb1,0x54,0xb4,0x53,0xb4,0x57,0xb2,0x51, 0xb4,0x5a,0xa7,0x53,0xac,0x44,0xac,0x42,0xa9,0x46,0xa7,0x43,0xaa,0x4e,0xab,0x48, 0xaf,0x4f,0xb1,0x41,0xb5,0x48,0xb8,0x3e,0xb8,0x49,0xb7,0x43,0xb5,0x4c,0xb2,0x3e, 0xb0,0x45,0xa9,0x41,0xa9,0x47,0xa7,0x3d,0xa8,0x46,0xaa,0x41,0xae,0x49,0xb1,0x42, 0xb4,0x48,0xb8,0x3f,0xb7,0x43,0xb6,0x3d,0xb5,0x44,0xb2,0x40,0xaf,0x49,0xaa,0x40, 0xa8,0x4a,0xa6,0x40,0xa7,0x42,0xa8,0x43,0xaa,0x45,0xb0,0x42,0xb3,0x49,0xb4,0x40, 0xb6,0x4a,0xb5,0x41,0xb3,0x45,0xaf,0x42,0xaf,0x43,0xa9,0x41,0xa6,0x49,0xa5,0x43, 0xa4,0x49,0xa5,0x3e,0xa8,0x46,0xad,0x42,0xb1,0x44,0xb2,0x45,0xb4,0x48,0xb3,0x42, 0xb3,0x4b,0xb2,0x3e,0xac,0x47,0xa8,0x40,0xa7,0x49,0xa3,0x41,0xa3,0x46,0xa4,0x42, 0xa5,0x47,0xaa,0x3f,0xaf,0x45,0xb0,0x3c,0xb1,0x4b,0xb3,0x40,0xb2,0x46,0xad,0x42, 0xac,0x46,0xa9,0x45,0xa4,0x49,0xa2,0x42,0xa4,0x49,0xa4,0x3d,0xa8,0x4a,0xa8,0x41, 0xae,0x48,0xb0,0x40,0xb1,0x43,0xb0,0x42,0xb1,0x49,0xae,0x43,0xaa,0x4c,0xa7,0x41, 0xa6,0x4b,0xa3,0x40,0xa2,0x4c,0xa1,0x3b,0xa4,0x49,0xa6,0x41,0xab,0x48,0xad,0x44, 0xb1,0x4a,0xb0,0x42,0xb1,0x44,0xaf,0x44,0xad,0x46,0xa6,0x42,0xa4,0x46,0xa1,0x40, 0xa2,0x4b,0x9f,0x41,0xa2,0x46,0xa4,0x42,0xa9,0x49,0xad,0x42,0xae,0x4b,0xae,0x40, 0xaf,0x49,0xab,0x40,0xa9,0x42,0xa6,0x3d,0xa3,0x45,0xa0,0x43,0xa0,0x4c,0x9e,0x40, 0xa1,0x44,0xa6,0x3f,0xa8,0x42,0xab,0x41,0xaf,0x4a,0xaf,0x3c,0xb0,0x48,0xae,0x3f, 0xac,0x47,0xa8,0x3f,0xa3,0x43,0xa0,0x41,0xa0,0x49,0x9f,0x3e,0xa1,0x49,0xa3,0x3d, 0xa7,0x48,0xa9,0x40,0xad,0x4a,0xae,0x40,0xaf,0x4e,0xad,0x42,0xac,0x4a,0xa7,0x41, 0xa5,0x49,0xa2,0x43,0x9f,0x46,0x9f,0x3e,0xa0,0x49,0xa2,0x45,0xa5,0x47,0xa8,0x3c, 0xab,0x45,0xac,0x45,0xac,0x47,0xab,0x40,0xa9,0x4c,0xa5,0x40,0xa2,0x4a,0xa0,0x3c, 0x9d,0x4b,0x9b,0x3d,0x9d,0x46,0xa0,0x3e,0xa5,0x4d,0xa6,0x3f,0xaa,0x4d,0xac,0x3c, 0xad,0x49,0xab,0x3f,0xaa,0x4a,0xa6,0x43,0xa3,0x4e,0x9d,0x41,0x9b,0x48,0x9a,0x3f, 0x9d,0x49,0x9c,0x40,0xa1,0x48,0xa4,0x40,0xa8,0x4d,0xa8,0x42,0xaa,0x4d,0xaa,0x42, 0xa8,0x48,0xa5,0x41,0xa2,0x46,0x9f,0x3e,0x9c,0x4c,0x9b,0x42,0x9b,0x44,0x9c,0x43, 0x9f,0x47,0xa4,0x3f,0xa5,0x49,0xa8,0x3e,0xaa,0x4a,0xa8,0x42,0xa8,0x4c,0xa3,0x3c, 0x9f,0x48,0x9d,0x3f,0x9c,0x44,0x97,0x41,0x98,0x49,0x9c,0x42,0x9f,0x46,0xa2,0x42, 0xa5,0x46,0xa7,0x3f,0xaa,0x44,0xa7,0x41,0xa7,0x4d,0xa5,0x40,0xa1,0x49,0x9b,0x42, 0x9c,0x4c,0x9a,0x3f,0x9a,0x47,0x9b,0x3f,0x9e,0x46,0xa2,0x44,0xa4,0x46,0xa6,0x3f, 0xa8,0x48,0xa9,0x3e,0xa6,0x46,0xa4,0x40,0xa1,0x4b,0x9e,0x3f,0x9c,0x48,0x99,0x3d, 0x99,0x47,0x99,0x41,0x9d,0x4b,0xa2,0x3d,0xa4,0x4c,0xa7,0x40,0xaa,0x4b,0xa8,0x3f, 0xa9,0x4a,0xa8,0x3d,0xa2,0x4a,0x9e,0x41,0x9f,0x4e,0x9a,0x42,0x98,0x4d,0x98,0x44, 0x9e,0x49,0x9f,0x41,0xa2,0x48,0xa7,0x44,0xaa,0x4d,0xa7,0x40,0xa9,0x4a,0xa8,0x3e, 0xa3,0x47,0xa0,0x3e,0x9d,0x4b,0x99,0x40,0x9a,0x49,0x9a,0x3d,0x9d,0x4a,0x9f,0x3d, 0xa2,0x4d,0xa5,0x41,0xa8,0x4d,0xa4,0x41,0xa5,0x4c,0xa4,0x43,0xa2,0x4a,0x9c,0x3b, 0x9a,0x4a,0x98,0x42,0x97,0x48,0x96,0x44,0x99,0x4d,0x9d,0x41,0xa2,0x49,0xa3,0x3f, 0xa5,0x47,0xa6,0x3f,0xa5,0x45,0xa3,0x3e,0xa1,0x49,0x9d,0x42,0x9a,0x48,0x98,0x3e, 0x97,0x49,0x98,0x3f,0x98,0x47,0x9d,0x3f,0xa0,0x4b,0xa5,0x3e,0xa7,0x44,0xa5,0x40, 0xa7,0x49,0xa5,0x41,0xa3,0x47,0xa0,0x44,0x9b,0x4a,0x97,0x40,0x98,0x4a,0x97,0x40, 0x9b,0x49,0x9d,0x41,0xa1,0x49,0xa5,0x3f,0xa8,0x47,0xa6,0x40,0xa7,0x48,0xa7,0x3e, 0xa5,0x4b,0x9f,0x40,0x9b,0x48,0x97,0x40,0x96,0x4c,0x98,0x3f,0x97,0x4e,0x97,0x41, 0x9f,0x49,0xa0,0x3d,0xa0,0x49,0xa2,0x42,0xa7,0x49,0xa3,0x44,0x9f,0x4a,0x9e,0x41, 0x9b,0x4c,0x96,0x3e,0x98,0x48,0x96,0x3d,0x98,0x4d,0x9a,0x3e,0x9f,0x46,0xa2,0x41, 0xa3,0x4c,0xa7,0x3f,0xa5,0x45,0xa4,0x41,0xa4,0x4b,0xa2,0x40,0x9c,0x47,0x99,0x43, 0x98,0x45,0x97,0x3f,0x98,0x47,0x99,0x41,0x9d,0x4f,0xa1,0x41,0xa5,0x48,0xa6,0x3f, 0xa6,0x4b,0xa5,0x3e,0xa5,0x44,0xa2,0x3d,0x9d,0x4f,0x9a,0x3e,0x98,0x47,0x96,0x41, 0x99,0x48,0x9c,0x3d,0x9e,0x49,0xa2,0x3f,0xa5,0x48,0xa6,0x41,0xa7,0x4c,0xa5,0x3f, 0xa4,0x48,0xa3,0x3d,0x9e,0x49,0x9a,0x3d,0x99,0x49,0x97,0x43,0x99,0x4b,0x9a,0x3f, 0x9e,0x46,0xa1,0x43,0xa4,0x45,0xa6,0x42,0xa7,0x4b,0xa6,0x3e,0xa6,0x46,0xa2,0x46, 0x9f,0x47,0x99,0x42,0x96,0x46,0x98,0x3d,0x96,0x4b,0x97,0x41,0x9b,0x4a,0x9f,0x3f, 0xa2,0x47,0xa4,0x42,0xa5,0x49,0xa3,0x40,0xa4,0x4b,0xa2,0x3f,0x9e,0x49,0x9a,0x3f, 0x97,0x4b,0x96,0x42,0x96,0x4b,0x97,0x3b,0x99,0x49,0x9e,0x40,0xa2,0x48,0xa4,0x43, 0xa6,0x49,0xa5,0x40,0xa5,0x47,0xa2,0x3f,0xa0,0x4c,0x9b,0x40,0x97,0x49,0x95,0x40, 0x93,0x4a,0x96,0x43,0x99,0x45,0x9c,0x3f,0xa0,0x46,0xa3,0x40,0xa5,0x4a,0xa4,0x41, 0xa6,0x4c,0xa2,0x42,0x9f,0x46,0x9b,0x3f,0x9a,0x4e,0x97,0x41,0x97,0x48,0x97,0x41, 0x9b,0x47,0x9e,0x3e,0xa1,0x49,0xa2,0x41,0xa5,0x4a,0xa6,0x3f,0xa5,0x4a,0xa3,0x3f, 0xa1,0x46,0x9c,0x3b,0x96,0x45,0x96,0x3f,0x97,0x4b,0x94,0x3f,0x96,0x49,0x9c,0x3f, 0xa1,0x4c,0xa4,0x43,0xa4,0x48,0xa6,0x3e,0xa5,0x4a,0xa2,0x3d,0x9f,0x47,0x9d,0x3e, 0x9a,0x48,0x96,0x40,0x94,0x47,0x94,0x47,0x98,0x4f,0x9a,0x40,0xa0,0x41,0xa2,0x37, 0xa5,0x48,0xa6,0x3f,0xa4,0x44,0xa1,0x41,0xa1,0x4c,0x95,0x41,0x99,0x53,0x98,0x54, 0x99,0x58,0x9b,0x55,0x9e,0x60,0xa3,0x57,0xa5,0x63,0xa7,0x55,0xa9,0x5c,0xa8,0x54, 0xa8,0x56,0xa6,0x4e,0xa1,0x55,0x9e,0x50,0x9d,0x5c,0x9a,0x54,0x9b,0x57,0x9a,0x52, 0x9e,0x56,0xa2,0x4e,0xa4,0x5d,0xa6,0x50,0xaa,0x5e,0xa8,0x4d,0xa6,0x59,0xa7,0x4c, 0xa4,0x59,0x9e,0x4e,0x9d,0x55,0x97,0x51,0x99,0x5c,0x99,0x50,0x9a,0x53,0x9e,0x4f, 0xa3,0x57,0xa6,0x54,0xa6,0x57,0xa6,0x4d,0xa6,0x58,0xa6,0x4f,0xa2,0x56,0x9c,0x54, 0x9b,0x5d,0x99,0x54,0x96,0x55,0x97,0x4f,0x99,0x59,0x9c,0x51,0xa1,0x5d,0xa5,0x4d, 0xa6,0x5b,0xa6,0x50,0xa7,0x54,0xa5,0x4d,0xa2,0x5e,0x9e,0x52,0x9b,0x56,0x98,0x50, 0x98,0x56,0x98,0x4f,0x9a,0x58,0x9d,0x4e,0xa2,0x57,0xa4,0x51,0xa7,0x60,0xa7,0x51, 0xa8,0x59,0xa6,0x50,0xa3,0x55,0x9d,0x53,0x9b,0x5b,0x98,0x4f,0x96,0x58,0x96,0x53, 0x99,0x5a,0x9a,0x54,0x9f,0x5a,0xa2,0x52,0xa5,0x5c,0xa7,0x4d,0xa8,0x5a,0xa4,0x51, 0xa3,0x58,0x9f,0x51,0x99,0x54,0x96,0x50,0x96,0x5e,0x94,0x51,0x96,0x5a,0x99,0x52, 0x9d,0x55,0xa0,0x50,0xa4,0x58,0xa4,0x54,0xa6,0x5f,0xa6,0x4e,0xa2,0x57,0x9f,0x4f, 0x9e,0x5b,0x98,0x51,0x97,0x57,0x97,0x53,0x98,0x5a,0x9a,0x52,0x9c,0x55,0xa1,0x52, 0xa3,0x5a,0xa4,0x4d,0xa4,0x57,0xa4,0x54,0xa2,0x5a,0x9c,0x53,0x9c,0x5a,0x98,0x4e, 0x97,0x58,0x95,0x51,0x98,0x58,0x99,0x54,0x9d,0x5a,0x9f,0x51,0xa2,0x57,0xa5,0x4d, 0xa5,0x58,0xa3,0x51,0xa2,0x58,0x9f,0x4f,0x9b,0x58,0x97,0x4d,0x95,0x59,0x93,0x52, 0x95,0x5c,0x97,0x52,0x9a,0x5a,0x9d,0x54,0xa0,0x5d,0xa1,0x50,0xa4,0x5b,0xa2,0x53, 0x9f,0x56,0x9d,0x52,0x9b,0x58,0x96,0x51,0x94,0x5d,0x93,0x50,0x94,0x59,0x96,0x4f, 0x99,0x57,0x9d,0x51,0xa0,0x58,0xa0,0x52,0xa3,0x60,0xa3,0x52,0xa1,0x57,0x9d,0x52, 0x9d,0x5a,0x99,0x4f,0x94,0x54,0x94,0x52,0x94,0x5a,0x95,0x4e,0x99,0x55,0x9b,0x51, 0xa0,0x5d,0xa1,0x4d,0xa2,0x56,0xa1,0x52,0xa0,0x5a,0x9d,0x52,0x99,0x5b,0x97,0x50, 0x94,0x5f,0x90,0x52,0x92,0x58,0x94,0x50,0x98,0x5a,0x9a,0x4f,0x9d,0x57,0xa0,0x55, 0xa0,0x59,0xa0,0x4f,0x9f,0x5b,0x9d,0x4f,0x9a,0x5b,0x95,0x51,0x93,0x56,0x90,0x51, 0x91,0x5d,0x93,0x52,0x95,0x55,0x9a,0x4f,0x9d,0x60,0x9f,0x55,0xa0,0x57,0xa0,0x4d, 0xa1,0x5a,0x9d,0x52,0x99,0x56,0x97,0x56,0x95,0x5e,0x92,0x4e,0x92,0x58,0x92,0x51, 0x95,0x59,0x98,0x50,0x9c,0x59,0x9e,0x50,0xa0,0x5d,0xa0,0x4e,0xa0,0x5a,0x9c,0x50, 0x99,0x55,0x95,0x50,0x94,0x59,0x8e,0x50,0x8f,0x5a,0x91,0x50,0x94,0x59,0x96,0x51, 0x9a,0x59,0x9e,0x56,0x9f,0x5a,0xa0,0x53,0x9f,0x5a,0x9d,0x53,0x9a,0x59,0x96,0x51, 0x93,0x5a,0x90,0x51,0x8f,0x54,0x91,0x4f,0x92,0x56,0x93,0x50,0x98,0x57,0x9c,0x4c, 0x9c,0x59,0x9d,0x51,0x9e,0x5d,0x9c,0x4f,0x9a,0x61,0x97,0x4a,0x94,0x5b,0x8f,0x55, 0x8f,0x57,0x8e,0x50,0x91,0x5b,0x95,0x4e,0x98,0x5c,0x9c,0x4f,0x9d,0x55,0x9f,0x4d, 0x9e,0x5d,0x9b,0x53,0x99,0x57,0x96,0x50,0x92,0x5d,0x8f,0x52,0x8d,0x57,0x8d,0x50, 0x90,0x5e,0x92,0x53,0x97,0x5a,0x99,0x52,0x9c,0x5a,0x9d,0x53,0x9d,0x58,0x9b,0x53, 0x99,0x5a,0x95,0x51,0x93,0x59,0x90,0x53,0x8f,0x5e,0x8d,0x53,0x8e,0x5a,0x91,0x52, 0x96,0x5b,0x98,0x52,0x9b,0x5a,0x9d,0x4f,0x9c,0x5c,0x98,0x51,0x97,0x58,0x96,0x54, 0x91,0x58,0x8c,0x51,0x8c,0x59,0x8c,0x56,0x8e,0x5c,0x8e,0x52,0x94,0x58,0x97,0x56, 0x99,0x57,0x9a,0x53,0x9c,0x54,0x98,0x51,0x97,0x5b,0x95,0x4e,0x93,0x5a,0x8d,0x54, 0x8c,0x5b,0x8c,0x4f,0x8e,0x53,0x8e,0x52,0x93,0x5b,0x95,0x4e,0x99,0x59,0x98,0x51, 0x99,0x5a,0x99,0x52,0x98,0x55,0x94,0x4d,0x92,0x5d,0x8d,0x53,0x8b,0x5b,0x88,0x53, 0x8c,0x5c,0x8d,0x52,0x8f,0x5a,0x94,0x50,0x98,0x5f,0x98,0x53,0x9a,0x5c,0x99,0x51, 0x99,0x60,0x95,0x55,0x92,0x5a,0x8d,0x53,0x8b,0x5b,0x8a,0x50,0x8b,0x57,0x8d,0x4f, 0x90,0x5c,0x94,0x53,0x98,0x59,0x97,0x50,0x98,0x5e,0x99,0x51,0x99,0x5a,0x94,0x50, 0x91,0x5b,0x8f,0x51,0x8d,0x56,0x8a,0x51,0x8b,0x5b,0x8d,0x51,0x91,0x57,0x94,0x52, 0x99,0x5d,0x99,0x52,0x9c,0x58,0x9d,0x4e,0x9c,0x5b,0x99,0x4f,0x97,0x5a,0x92,0x51, 0x8f,0x5b,0x8d,0x55,0x8e,0x52,0x90,0x4f,0x92,0x5e,0x95,0x53,0x99,0x56,0x9b,0x51, 0x9e,0x58,0x9c,0x52,0x9c,0x58,0x9a,0x4d,0x97,0x5c,0x92,0x53,0x90,0x5c,0x8c,0x50, 0x8c,0x59,0x8e,0x52,0x92,0x59,0x94,0x53,0x97,0x5a,0x9a,0x54,0x9c,0x58,0x9c,0x4f, 0x9b,0x5c,0x9a,0x54,0x96,0x57,0x92,0x58,0x8f,0x5e,0x8c,0x50,0x8c,0x59,0x8d,0x50, 0x90,0x54,0x95,0x52,0x98,0x55,0x9a,0x52,0x9c,0x5c,0x9c,0x51,0x9c,0x58,0x98,0x51, 0x97,0x57,0x95,0x54,0x8f,0x57,0x8b,0x55,0x8b,0x5c,0x8b,0x4e,0x8e,0x5c,0x93,0x4f, 0x97,0x5b,0x99,0x50,0x9c,0x5a,0x9c,0x50,0x9c,0x59,0x99,0x52,0x97,0x55,0x93,0x54, 0x91,0x5a,0x8d,0x52,0x8c,0x5d,0x8d,0x4d,0x91,0x5c,0x93,0x54,0x98,0x5b,0x9a,0x52, 0x9c,0x59,0x9d,0x51,0x9e,0x59,0x9b,0x4f,0x99,0x5d,0x95,0x51,0x92,0x59,0x8d,0x52, 0x8e,0x58,0x90,0x4f,0x90,0x57,0x94,0x55,0x98,0x59,0x9b,0x56,0x9f,0x57,0x9e,0x52, 0x9e,0x58,0x9e,0x4f,0x9c,0x5a,0x95,0x50,0x91,0x5d,0x8d,0x50,0x8c,0x55,0x8d,0x4b, 0x90,0x5d,0x92,0x52,0x98,0x5f,0x9b,0x55,0x9f,0x5f,0x9e,0x50,0x9f,0x53,0x9e,0x50, 0x9e,0x59,0x9a,0x4e,0x96,0x59,0x92,0x54,0x92,0x5f,0x90,0x50,0x92,0x5c,0x95,0x54, 0x98,0x59,0x9b,0x4f,0x9f,0x4f,0x9e,0x48,0xa1,0x59,0xa0,0x4e,0x9d,0x58,0x9a,0x50, 0x96,0x5a,0x8c,0x55,0x94,0x4d,0x95,0x45,0x97,0x52,0x9c,0x4e,0xa0,0x5b,0xa2,0x50, 0xa5,0x52,0xa6,0x4c,0xa3,0x50,0xa2,0x47,0xa0,0x56,0x9b,0x49,0x98,0x4f,0x96,0x4b, 0x94,0x54,0x96,0x46,0x98,0x53,0x99,0x48,0x9e,0x56,0xa1,0x48,0xa1,0x52,0xa3,0x4a, 0xa5,0x4e,0xa1,0x47,0x9d,0x52,0x9b,0x48,0x97,0x52,0x94,0x48,0x94,0x4f,0x95,0x43, 0x96,0x50,0x9b,0x47,0x9e,0x51,0xa1,0x4a,0xa3,0x54,0xa5,0x45,0xa4,0x51,0xa2,0x47, 0x9f,0x53,0x9d,0x48,0x99,0x4d,0x94,0x48,0x94,0x54,0x94,0x48,0x97,0x4f,0x9a,0x49, 0x9e,0x4d,0xa0,0x49,0xa2,0x50,0xa3,0x4c,0xa3,0x51,0xa3,0x49,0xa0,0x50,0x9e,0x4b, 0x99,0x4f,0x95,0x4b,0x93,0x4f,0x93,0x48,0x94,0x53,0x97,0x48,0x9c,0x4b,0xa0,0x48, 0xa0,0x53,0xa3,0x49,0xa3,0x4d,0xa0,0x50,0xa0,0x55,0x9c,0x4d,0x97,0x50,0x95,0x4c, 0x93,0x4c,0x92,0x4b,0x94,0x52,0x96,0x4c,0x9a,0x56,0xa0,0x48,0xa1,0x4f,0xa2,0x47, 0xa3,0x51,0xa2,0x49,0xa1,0x4e,0x9c,0x4b,0x99,0x55,0x95,0x47,0x93,0x52,0x93,0x4a, 0x93,0x52,0x96,0x4c,0x99,0x53,0x9e,0x46,0x9f,0x53,0xa2,0x4a,0xa3,0x51,0xa1,0x47, 0x9f,0x50,0x9c,0x49,0x9a,0x4d,0x94,0x4b,0x91,0x52,0x91,0x48,0x92,0x52,0x94,0x48, 0x97,0x50,0x9c,0x48,0x9f,0x50,0x9f,0x4b,0xa0,0x54,0xa2,0x47,0x9f,0x4d,0x9a,0x49, 0x99,0x50,0x94,0x4a,0x93,0x4e,0x91,0x47,0x92,0x55,0x94,0x4a,0x97,0x50,0x9a,0x49, 0x9e,0x4f,0xa0,0x4a,0xa1,0x4e,0xa0,0x47,0xa0,0x58,0x9d,0x4a,0x99,0x53,0x95,0x45, 0x92,0x51,0x91,0x48,0x91,0x53,0x93,0x4a,0x95,0x53,0x9a,0x49,0x9e,0x52,0x9f,0x49, 0xa0,0x50,0xa1,0x48,0x9f,0x50,0x9d,0x4b,0x99,0x52,0x95,0x47,0x93,0x51,0x92,0x4c, 0x91,0x51,0x92,0x49,0x96,0x4f,0x99,0x49,0x9c,0x51,0x9e,0x46,0xa1,0x52,0xa0,0x4c, 0x9e,0x53,0x9c,0x4b,0x9a,0x4d,0x95,0x48,0x93,0x55,0x92,0x4e,0x91,0x55,0x93,0x48, 0x95,0x53,0x99,0x4c,0x9c,0x51,0x9e,0x4a,0xa0,0x56,0xa1,0x4c,0x9f,0x4f,0x9d,0x45, 0x9a,0x52,0x94,0x49,0x90,0x50,0x8f,0x4a,0x8f,0x53,0x90,0x48,0x91,0x50,0x96,0x4e, 0x9a,0x54,0x9e,0x48,0x9e,0x50,0x9e,0x4a,0x9e,0x4e,0x9d,0x48,0x9a,0x56,0x95,0x49, 0x91,0x50,0x90,0x47,0x8d,0x52,0x90,0x49,0x93,0x56,0x98,0x4b,0x9a,0x51,0x9d,0x4b, 0x9e,0x51,0x9f,0x4b,0x9f,0x4e,0x9c,0x48,0x99,0x54,0x95,0x4b,0x91,0x52,0x90,0x47, 0x8e,0x50,0x8f,0x48,0x92,0x51,0x95,0x4a,0x99,0x56,0x9c,0x49,0x9f,0x55,0x9f,0x4c, 0x9f,0x50,0x9d,0x49,0x9a,0x53,0x96,0x49,0x92,0x52,0x8f,0x48,0x8e,0x4f,0x8f,0x47, 0x92,0x4f,0x94,0x46,0x97,0x50,0x9a,0x47,0x9c,0x51,0x9f,0x45,0x9e,0x54,0x9c,0x4a, 0x99,0x50,0x97,0x48,0x93,0x4f,0x8f,0x4b,0x8d,0x52,0x8e,0x48,0x90,0x4c,0x93,0x49, 0x97,0x51,0x9a,0x49,0x9b,0x52,0x9c,0x46,0x9e,0x4e,0x9b,0x49,0x98,0x53,0x95,0x4b, 0x90,0x55,0x8d,0x4d,0x8c,0x54,0x8c,0x47,0x8e,0x57,0x91,0x4d,0x95,0x53,0x9a,0x48, 0x9c,0x53,0x9c,0x4c,0x9c,0x52,0x9c,0x46,0x99,0x54,0x96,0x4d,0x92,0x4e,0x8f,0x49, 0x8e,0x4f,0x8e,0x4e,0x8f,0x53,0x91,0x49,0x95,0x50,0x96,0x50,0x9b,0x4f,0x9a,0x4b, 0x9c,0x53,0x9b,0x48,0x9a,0x4f,0x95,0x49,0x92,0x56,0x8d,0x4d,0x8d,0x52,0x8c,0x4a, 0x8d,0x4f,0x90,0x49,0x94,0x4f,0x97,0x4a,0x9b,0x56,0x9c,0x4c,0x9a,0x53,0x9b,0x4b, 0x9b,0x52,0x97,0x4d,0x93,0x51,0x8f,0x49,0x8d,0x54,0x8b,0x4a,0x8b,0x53,0x90,0x4a, 0x94,0x51,0x96,0x49,0x99,0x51,0x9b,0x49,0x9d,0x58,0x9c,0x48,0x99,0x51,0x98,0x49, 0x93,0x50,0x90,0x4b,0x8d,0x52,0x8d,0x4c,0x8c,0x56,0x8f,0x4b,0x93,0x55,0x97,0x47, 0x99,0x52,0x9d,0x4a,0x9c,0x50,0x9b,0x4e,0x99,0x54,0x99,0x4a,0x95,0x4d,0x8f,0x47, 0x8d,0x57,0x8d,0x47,0x8c,0x52,0x8f,0x48,0x94,0x5a,0x96,0x4b,0x99,0x50,0x9b,0x4b, 0x9d,0x55,0x9e,0x4a,0x9b,0x50,0x99,0x49,0x95,0x51,0x92,0x4b,0x8f,0x50,0x8d,0x4b, 0x8e,0x51,0x8f,0x49,0x92,0x52,0x96,0x4c,0x9a,0x4d,0x9c,0x4c,0x9d,0x54,0x9c,0x4b, 0x9d,0x4e,0x9a,0x4a,0x97,0x53,0x91,0x4a,0x8c,0x51,0x8b,0x47,0x8e,0x52,0x8e,0x4c, 0x91,0x53,0x97,0x49,0x9a,0x50,0x9f,0x48,0x9e,0x50,0x9d,0x4a,0x9d,0x53,0x9b,0x47, 0x99,0x51,0x94,0x4b,0x92,0x55,0x8f,0x48,0x8f,0x54,0x91,0x4d,0x92,0x56,0x97,0x4c, 0x9a,0x53,0x9d,0x4a,0x9e,0x50,0x9d,0x48,0x9e,0x53,0x9d,0x4b,0x9a,0x54,0x96,0x4b, 0x93,0x57,0x91,0x4d,0x91,0x4e,0x92,0x49,0x95,0x53,0x98,0x4b,0x9c,0x53,0x9f,0x49, 0xa0,0x55,0xa1,0x4c,0x9f,0x51,0x9f,0x46,0x9c,0x4f,0x97,0x46,0x94,0x54,0x91,0x4a, 0x90,0x55,0x91,0x4a,0x93,0x4d,0x97,0x47,0x9b,0x55,0x9d,0x4a,0xa0,0x4f,0xa0,0x4a, 0x9f,0x56,0x9f,0x4e,0x9b,0x4e,0x97,0x49,0x94,0x51,0x92,0x4d,0x8e,0x55,0x90,0x49, 0x93,0x53,0x98,0x4e,0x9b,0x55,0xa0,0x49,0xa0,0x55,0xa2,0x4a,0xa1,0x50,0x9f,0x49, 0x9c,0x53,0x99,0x4b,0x94,0x53,0x92,0x4d,0x92,0x4f,0x91,0x49,0x93,0x4f,0x97,0x49, 0x9b,0x55,0x9e,0x4d,0xa0,0x4e,0xa0,0x49,0xa1,0x56,0x9e,0x48,0x9d,0x57,0x99,0x48, 0x96,0x56,0x91,0x47,0x93,0x4f,0x93,0x4d,0x93,0x56,0x95,0x4c,0x97,0x53,0x9a,0x4a, 0xa0,0x51,0x9f,0x4d,0x9e,0x4f,0x9d,0x4d,0x9f,0x4e,0x97,0x4a,0x93,0x51,0x92,0x45, 0x92,0x52,0x93,0x4a,0x93,0x52,0x95,0x4b,0x99,0x55,0x9e,0x49,0xa0,0x52,0xa1,0x4d, 0xa1,0x55,0xa0,0x4c,0x9e,0x51,0x9c,0x4b,0x97,0x52,0x94,0x4c,0x93,0x54,0x92,0x4a, 0x93,0x54,0x97,0x4e,0x99,0x4f,0x9c,0x4d,0xa0,0x53,0xa1,0x49,0xa0,0x4b,0xa1,0x40, 0xa0,0x4c,0x9d,0x4a,0x9a,0x4e,0x93,0x49,0x91,0x53,0x8c,0x4e,0x98,0x35,0x9c,0x33, 0xa2,0x38,0xa5,0x3a,0xa6,0x47,0xa7,0x38,0xa8,0x43,0xa7,0x3b,0xa2,0x3b,0x9e,0x35, 0x9c,0x3e,0x98,0x34,0x95,0x3b,0x95,0x33,0x9a,0x3e,0x9d,0x35,0xa1,0x3c,0xa3,0x32, 0xa7,0x40,0xa8,0x35,0xa8,0x3c,0xa6,0x34,0xa5,0x3d,0xa1,0x35,0x9c,0x3a,0x99,0x3a, 0x97,0x39,0x98,0x37,0x9c,0x3a,0x9e,0x34,0xa3,0x3d,0xa7,0x35,0xa9,0x38,0xaa,0x31, 0xac,0x3c,0xab,0x34,0xa7,0x37,0xa3,0x33,0xa0,0x3c,0x9d,0x3b,0x9b,0x3c,0x9c,0x36, 0x9c,0x3f,0x9d,0x37,0xa2,0x38,0xa6,0x31,0xa9,0x3e,0xaa,0x35,0xaa,0x3c,0xa9,0x36, 0xa8,0x3c,0xa4,0x36,0x9e,0x3c,0x9b,0x31,0x9c,0x3c,0x9c,0x35,0x9c,0x3d,0x9d,0x33, 0xa2,0x39,0xa5,0x33,0xa9,0x3a,0xa9,0x35,0xab,0x3a,0xab,0x32,0xa6,0x38,0xa3,0x32, 0xa1,0x3d,0x9e,0x33,0x9a,0x3a,0x9a,0x34,0x9c,0x41,0x9f,0x32,0xa3,0x3d,0xa7,0x32, 0xaa,0x3d,0xab,0x35,0xac,0x3d,0xab,0x35,0xab,0x3f,0xa6,0x33,0xa2,0x3d,0x9e,0x35, 0x9e,0x3d,0x9b,0x37,0x9b,0x3b,0x9e,0x3a,0xa2,0x3e,0xa7,0x36,0xaa,0x3b,0xaa,0x37, 0xac,0x3d,0xaa,0x36,0xa9,0x3b,0xa6,0x36,0xa3,0x3d,0x9c,0x34,0x9a,0x3c,0x99,0x38, 0x9b,0x3f,0x9b,0x33,0xa0,0x3c,0xa4,0x37,0xa7,0x3a,0xaa,0x39,0xab,0x34,0xa9,0x39, 0xa6,0x41,0xa5,0x33,0xa1,0x3b,0x9b,0x33,0x9a,0x3c,0x97,0x34,0x9a,0x3b,0x9a,0x34, 0x9e,0x3c,0xa3,0x34,0xa5,0x3d,0xa8,0x33,0xa9,0x3d,0xaa,0x2f,0xa8,0x3b,0xa6,0x36, 0xa2,0x41,0x9e,0x34,0x9b,0x3a,0x99,0x34,0x98,0x41,0x97,0x35,0x9c,0x3e,0xa3,0x34, 0xa4,0x3b,0xa6,0x33,0xa8,0x3b,0xaa,0x35,0xa7,0x3e,0xa4,0x32,0xa3,0x39,0x9e,0x36, 0x9c,0x3f,0x9a,0x35,0x99,0x39,0x99,0x32,0x9e,0x40,0xa1,0x35,0xa6,0x3c,0xa8,0x36, 0xab,0x3f,0xaa,0x36,0xaa,0x3e,0xa6,0x32,0xa4,0x3c,0xa1,0x33,0x9d,0x39,0x9a,0x37, 0x9a,0x3b,0x9b,0x38,0x9e,0x3b,0xa3,0x36,0xa6,0x3d,0xa8,0x37,0xab,0x3d,0xab,0x33, 0xaa,0x3e,0xa9,0x33,0xa6,0x3d,0xa0,0x32,0x9d,0x42,0x9b,0x30,0x9b,0x3b,0x9b,0x3a, 0x9e,0x3b,0xa0,0x35,0xa5,0x3b,0xa8,0x36,0xab,0x43,0xab,0x33,0xab,0x3c,0xa8,0x31, 0xa4,0x3f,0xa0,0x37,0x9e,0x3a,0x9a,0x31,0x98,0x40,0x99,0x34,0x9d,0x3e,0xa0,0x35, 0xa5,0x3d,0xa8,0x37,0xab,0x3c,0xaa,0x36,0xab,0x3c,0xab,0x34,0xa8,0x3c,0xa2,0x33, 0xa0,0x3d,0x9a,0x34,0x9a,0x3e,0x9b,0x34,0x9e,0x3d,0x9f,0x33,0xa6,0x3c,0xa7,0x33, 0xab,0x3b,0xab,0x33,0xac,0x3d,0xa8,0x3a,0xa5,0x3a,0xa2,0x35,0x9d,0x39,0x9a,0x34, 0x98,0x39,0x99,0x30,0x9b,0x3a,0x9e,0x32,0xa2,0x40,0xa6,0x36,0xa7,0x3d,0xaa,0x38, 0xac,0x3c,0xa9,0x35,0xa6,0x3b,0xa2,0x37,0x9f,0x3f,0x9a,0x32,0x9a,0x3a,0x98,0x34, 0x9b,0x39,0x9e,0x34,0xa2,0x3a,0xa5,0x34,0xa9,0x3f,0xa9,0x33,0xaa,0x3d,0xa8,0x30, 0xa8,0x3b,0xa4,0x36,0xa0,0x3b,0x9c,0x36,0x9a,0x3e,0x99,0x34,0x9b,0x40,0x9d,0x35, 0xa1,0x42,0xa5,0x35,0xa8,0x37,0xa8,0x35,0xac,0x3e,0xa9,0x35,0xa7,0x3d,0xa4,0x3a, 0xa2,0x3b,0x9a,0x39,0x9a,0x3b,0x98,0x34,0x9a,0x3e,0x9c,0x38,0x9f,0x40,0xa4,0x35, 0xa8,0x3e,0xa8,0x37,0xa9,0x3a,0xa9,0x34,0xa8,0x44,0xa4,0x39,0xa0,0x3b,0x9c,0x37, 0x9a,0x3f,0x98,0x34,0x9a,0x3e,0x9a,0x37,0x9e,0x3f,0xa3,0x38,0xa6,0x3f,0xa8,0x38, 0xa9,0x3c,0xa9,0x35,0xa7,0x3b,0xa3,0x35,0x9f,0x41,0x9c,0x3a,0x99,0x3f,0x98,0x37, 0x99,0x42,0x9a,0x32,0x9f,0x3d,0xa2,0x36,0xa8,0x3f,0xa5,0x37,0xa7,0x3c,0xa8,0x36, 0xa7,0x3e,0xa0,0x37,0x9e,0x3d,0x9c,0x33,0x97,0x40,0x95,0x38,0x96,0x40,0x9b,0x36, 0x9d,0x3f,0x9f,0x36,0xa4,0x3e,0xa5,0x33,0xa9,0x3f,0xa8,0x3a,0xa5,0x3e,0xa2,0x35, 0xa0,0x3f,0x99,0x35,0x99,0x3a,0x96,0x37,0x96,0x3c,0x97,0x34,0x9b,0x3c,0x9f,0x32, 0xa4,0x3d,0xa6,0x39,0xa7,0x3d,0xa7,0x38,0xa7,0x3f,0xa4,0x3a,0xa0,0x38,0x9d,0x36, 0x9b,0x3f,0x98,0x38,0x97,0x3d,0x98,0x34,0x9b,0x3e,0x9e,0x36,0xa2,0x3c,0xa4,0x37, 0xa7,0x3d,0xa7,0x3a,0xa6,0x3a,0xa3,0x37,0xa2,0x40,0x9d,0x37,0x99,0x3d,0x97,0x37, 0x99,0x3e,0x98,0x36,0x9c,0x39,0x9e,0x36,0xa4,0x3f,0xa6,0x38,0xa8,0x3f,0xa8,0x33, 0xa9,0x3f,0xa5,0x34,0xa3,0x3e,0xa0,0x36,0x9c,0x3c,0x99,0x35,0x97,0x3d,0x98,0x32, 0x9b,0x40,0x9e,0x31,0xa1,0x3b,0xa3,0x33,0xa7,0x41,0xa8,0x37,0xa5,0x41,0xa5,0x35, 0xa4,0x3c,0x9e,0x38,0x9c,0x3c,0x99,0x35,0x97,0x40,0x98,0x37,0x99,0x42,0x9e,0x35, 0xa2,0x3f,0xa6,0x35,0xa9,0x3f,0xa9,0x37,0xa9,0x41,0xa6,0x37,0xa5,0x3e,0xa1,0x37, 0x9f,0x3e,0x9b,0x37,0x98,0x3b,0x98,0x32,0x9c,0x3f,0x9d,0x34,0xa3,0x3b,0xa5,0x36, 0xa8,0x3c,0xa8,0x31,0xa8,0x40,0xa7,0x2e,0xa5,0x40,0xa1,0x34,0x9e,0x3f,0x9b,0x35, 0x9a,0x3f,0x99,0x33,0x99,0x41,0x9d,0x38,0xa1,0x40,0xa5,0x39,0xa9,0x3d,0xaa,0x35, 0xaa,0x3d,0xa7,0x34,0xa6,0x3f,0xa2,0x39,0x9e,0x3f,0x9a,0x36,0x99,0x3c,0x98,0x35, 0x9b,0x3f,0x9e,0x31,0xa2,0x3c,0xa6,0x34,0xa8,0x3b,0xa8,0x38,0xa9,0x3d,0xa9,0x36, 0xa6,0x40,0xa2,0x3b,0x9f,0x3e,0x9b,0x34,0x98,0x3b,0x98,0x36,0x98,0x41,0x9b,0x32, 0xa1,0x3d,0xa4,0x34,0xa5,0x3c,0xa6,0x33,0xa8,0x41,0xa7,0x37,0xa4,0x39,0xa2,0x35, 0xa1,0x3d,0x9b,0x35,0x9a,0x41,0x99,0x32,0x97,0x3e,0x99,0x35,0xa1,0x40,0xa3,0x35, 0xa3,0x3a,0xa7,0x39,0xaa,0x3a,0xa7,0x37,0xa7,0x3e,0xa3,0x36,0xa1,0x3f,0x9e,0x36, 0x9c,0x3e,0x9a,0x36,0x9c,0x3e,0x9d,0x35,0xa1,0x3f,0xa4,0x32,0xa8,0x3f,0xa7,0x3c, 0xa9,0x45,0xa9,0x35,0xa7,0x31,0xa5,0x2c,0xa3,0x38,0x9e,0x33,0x9b,0x3c,0x99,0x36, 0x98,0x42,0x93,0x3b,0xa3,0x4d,0xa8,0x3f,0xad,0x4d,0xad,0x4c,0xad,0x57,0xac,0x51, 0xaa,0x51,0xa6,0x4b,0xa3,0x4d,0xa0,0x48,0x9d,0x4f,0x9c,0x45,0xa0,0x4a,0xa3,0x48, 0xa7,0x4b,0xaa,0x43,0xac,0x52,0xae,0x40,0xb0,0x48,0xae,0x46,0xad,0x4b,0xa9,0x48, 0xa5,0x52,0xa1,0x46,0x9f,0x4f,0x9e,0x46,0x9f,0x50,0xa2,0x4a,0xa7,0x4b,0xab,0x46, 0xae,0x4b,0xb0,0x44,0xb1,0x4e,0xae,0x4a,0xae,0x4e,0xaa,0x47,0xa7,0x4c,0xa3,0x45, 0xa1,0x50,0x9f,0x42,0xa1,0x52,0xa2,0x42,0xa4,0x50,0xaa,0x45,0xab,0x4c,0xae,0x46, 0xac,0x52,0xae,0x47,0xab,0x4b,0xa9,0x41,0xa7,0x4d,0xa2,0x46,0x9f,0x50,0x9d,0x46, 0xa1,0x4e,0x9f,0x44,0xa3,0x4d,0xa8,0x47,0xab,0x50,0xae,0x44,0xb2,0x4d,0xb0,0x46, 0xac,0x4d,0xa8,0x45,0xa8,0x4d,0xa0,0x45,0x9c,0x4f,0x9c,0x47,0xa0,0x47,0xa0,0x44, 0xa5,0x4c,0xaa,0x48,0xad,0x51,0xaf,0x4a,0xb0,0x4f,0xb0,0x45,0xaf,0x4c,0xac,0x45, 0xa8,0x51,0xa4,0x45,0xa3,0x49,0x9e,0x45,0xa0,0x4e,0xa1,0x42,0xa5,0x4e,0xa8,0x45, 0xaa,0x50,0xae,0x46,0xb0,0x4c,0xad,0x44,0xae,0x51,0xae,0x48,0xa9,0x4c,0xa5,0x46, 0xa4,0x4b,0xa1,0x41,0xa2,0x4e,0xa1,0x45,0xa6,0x51,0xab,0x47,0xae,0x4d,0xaf,0x43, 0xb4,0x4c,0xb4,0x46,0xb3,0x4a,0xb1,0x46,0xab,0x4b,0xa7,0x47,0xa5,0x4e,0xa2,0x48, 0x9e,0x4e,0xa0,0x48,0xa5,0x4c,0xa7,0x48,0xa9,0x50,0xb1,0x49,0xb3,0x4f,0xb2,0x45, 0xb4,0x4b,0xb0,0x48,0xae,0x47,0xa9,0x42,0xa6,0x4f,0xa5,0x44,0xa5,0x50,0xa4,0x48, 0xa6,0x50,0xab,0x44,0xae,0x4d,0xb2,0x46,0xb3,0x4e,0xb2,0x44,0xb4,0x4b,0xb2,0x44, 0xb0,0x4e,0xaa,0x45,0xa8,0x4e,0xa6,0x42,0xa4,0x51,0xa3,0x48,0xa8,0x4d,0xaa,0x4b, 0xae,0x4d,0xaf,0x48,0xb2,0x4f,0xb2,0x46,0xb1,0x50,0xaf,0x48,0xaf,0x4d,0xaa,0x47, 0xa7,0x4b,0xa6,0x45,0xa3,0x51,0xa3,0x42,0xa6,0x54,0xa8,0x49,0xad,0x51,0xb1,0x43, 0xb3,0x50,0xb4,0x4a,0xb5,0x4f,0xb4,0x47,0xb0,0x50,0xac,0x48,0xa9,0x4f,0xa4,0x49, 0xa4,0x51,0xa1,0x47,0xa4,0x4a,0xa8,0x47,0xaf,0x4f,0xaf,0x47,0xb3,0x4d,0xb3,0x49, 0xb5,0x4b,0xb2,0x47,0xae,0x4a,0xaa,0x47,0xa7,0x4f,0xa2,0x45,0xa0,0x4b,0xa0,0x48, 0xa4,0x4e,0xa7,0x44,0xac,0x4b,0xaf,0x49,0xb4,0x4d,0xb5,0x47,0xb6,0x4d,0xb3,0x44, 0xaf,0x4e,0xad,0x48,0xa9,0x4b,0xa4,0x45,0xa3,0x51,0xa3,0x45,0xa5,0x4d,0xa8,0x46, 0xab,0x4f,0xaf,0x44,0xb4,0x4c,0xb3,0x47,0xb4,0x50,0xb4,0x45,0xb4,0x4d,0xae,0x43, 0xa9,0x52,0xa8,0x43,0xa7,0x4a,0xa1,0x44,0xa5,0x4d,0xa9,0x46,0xac,0x4c,0xae,0x45, 0xb4,0x4e,0xb5,0x49,0xb5,0x4b,0xb4,0x42,0xb3,0x50,0xaf,0x48,0xac,0x4d,0xa8,0x46, 0xa4,0x50,0xa4,0x46,0xa4,0x4e,0xa5,0x47,0xa9,0x4b,0xac,0x48,0xb1,0x4c,0xb3,0x48, 0xb4,0x52,0xb4,0x44,0xb3,0x4b,0xaf,0x42,0xac,0x4c,0xa8,0x48,0xa3,0x4b,0xa1,0x47, 0xa3,0x4b,0xa4,0x43,0xa8,0x4c,0xac,0x48,0xb1,0x51,0xb2,0x49,0xb3,0x4a,0xb4,0x4b, 0xb3,0x4f,0xac,0x46,0xab,0x4e,0xa8,0x46,0xa3,0x51,0xa0,0x47,0xa2,0x4d,0xa6,0x49, 0xa9,0x4e,0xad,0x4d,0xb2,0x4c,0xb2,0x4a,0xb3,0x50,0xb4,0x4a,0xb3,0x48,0xaf,0x47, 0xad,0x4d,0xa8,0x47,0xa6,0x4d,0xa2,0x46,0xa2,0x51,0xa5,0x46,0xa7,0x4d,0xab,0x42, 0xaf,0x50,0xb1,0x47,0xb3,0x51,0xb2,0x42,0xb3,0x53,0xb0,0x4b,0xad,0x52,0xa9,0x46, 0xa6,0x4f,0xa6,0x4a,0xa6,0x4f,0xa6,0x45,0xa8,0x4b,0xac,0x45,0xb0,0x4d,0xaf,0x47, 0xb3,0x4f,0xb2,0x49,0xaf,0x4e,0xac,0x45,0xac,0x4e,0xa8,0x4a,0xa4,0x4c,0xa3,0x48, 0xa1,0x4e,0xa1,0x44,0xa5,0x51,0xa9,0x44,0xab,0x4f,0xac,0x43,0xb2,0x52,0xb1,0x46, 0xb0,0x4c,0xaf,0x46,0xac,0x4e,0xa7,0x45,0xa4,0x54,0xa2,0x47,0xa0,0x4c,0x9f,0x45, 0xa4,0x53,0xa8,0x49,0xac,0x4f,0xad,0x46,0xb0,0x50,0xb0,0x47,0xaf,0x4b,0xab,0x43, 0xab,0x4e,0xa6,0x47,0xa5,0x4d,0xa2,0x46,0xa1,0x52,0xa2,0x4c,0xa4,0x4d,0xa8,0x43, 0xac,0x51,0xae,0x46,0xb1,0x4b,0xb3,0x46,0xb2,0x52,0xb1,0x47,0xaf,0x4b,0xa9,0x45, 0xa7,0x4d,0xa2,0x49,0xa0,0x4a,0xa2,0x48,0xa2,0x50,0xa3,0x43,0xaa,0x4d,0xac,0x47, 0xaf,0x4b,0xaf,0x4d,0xb0,0x4c,0xaf,0x43,0xad,0x53,0xaa,0x49,0xa6,0x4f,0xa2,0x47, 0xa2,0x53,0xa3,0x46,0xa4,0x4c,0xa5,0x46,0xaa,0x55,0xae,0x48,0xb1,0x4e,0xb0,0x42, 0xb1,0x4d,0xb0,0x49,0xae,0x4f,0xa9,0x46,0xa5,0x54,0xa2,0x47,0xa1,0x4b,0xa0,0x49, 0xa1,0x4e,0xa5,0x48,0xaa,0x4e,0xad,0x45,0xb0,0x52,0xb3,0x49,0xb3,0x4d,0xb1,0x4a, 0xb0,0x4c,0xae,0x47,0xa7,0x4e,0xa3,0x47,0xa3,0x50,0xa3,0x45,0xa4,0x4f,0xa5,0x45, 0xaa,0x4b,0xad,0x48,0xb0,0x4b,0xb1,0x48,0xb1,0x55,0xb0,0x48,0xaf,0x4f,0xac,0x43, 0xa9,0x53,0xa5,0x48,0xa3,0x4b,0xa1,0x45,0x9b,0x54,0x9d,0x46,0xa8,0x4d,0xaa,0x45, 0xaa,0x50,0xae,0x45,0xb4,0x4d,0xb2,0x43,0xb0,0x4e,0xaf,0x44,0xaa,0x4b,0xa7,0x46, 0xa7,0x4d,0xa3,0x48,0x9a,0x4d,0x9d,0x43,0xab,0x52,0xa4,0x43,0xa2,0x52,0xb1,0x47, 0xb5,0x4f,0xae,0x48,0xb0,0x4d,0xae,0x43,0xaa,0x55,0xa6,0x42,0xa3,0x50,0xa4,0x48, 0xa4,0x4e,0xa6,0x48,0xa8,0x4b,0xab,0x46,0xae,0x52,0xb2,0x49,0xb4,0x4d,0xb1,0x46, 0xb1,0x4b,0xaf,0x49,0xaa,0x48,0xa5,0x45,0xa3,0x4d,0xa3,0x46,0xa1,0x50,0xa2,0x49, 0xa6,0x4b,0xa9,0x44,0xac,0x4b,0xaf,0x49,0xb1,0x50,0xb0,0x45,0xaf,0x4f,0xac,0x46, 0xaa,0x4f,0xa7,0x49,0xa2,0x4d,0xa0,0x46,0xa2,0x53,0xa3,0x46,0xa7,0x49,0xa9,0x42, 0xad,0x4d,0xb0,0x45,0xb0,0x51,0xaf,0x49,0xaf,0x53,0xad,0x3f,0xa8,0x45,0xa5,0x3f, 0xa3,0x4f,0x9f,0x43,0xa0,0x4e,0xa1,0x47,0xa3,0x50,0x9f,0x4b,0xb1,0x1e,0xb3,0x10, 0xb6,0x1a,0xb5,0x15,0xb4,0x28,0xaf,0x1a,0xad,0x1e,0xa7,0x12,0xa4,0x1d,0xa2,0x17, 0xa4,0x1e,0xa4,0x14,0xa5,0x1b,0xaa,0x15,0xb0,0x1c,0xaf,0x14,0xb1,0x1f,0xb3,0x17, 0xb2,0x1d,0xad,0x14,0xaa,0x1b,0xa6,0x12,0xa3,0x20,0xa0,0x12,0xa1,0x20,0xa3,0x17, 0xa8,0x17,0xab,0x12,0xaf,0x1d,0xb0,0x16,0xb3,0x21,0xb3,0x16,0xb2,0x18,0xaf,0x16, 0xab,0x1f,0xa5,0x11,0xa0,0x1a,0x9e,0x12,0x9f,0x1d,0xa0,0x17,0xa2,0x1a,0xa7,0x16, 0xad,0x19,0xaf,0x13,0xb0,0x1b,0xb0,0x16,0xb0,0x1e,0xad,0x13,0xa9,0x1b,0xa4,0x15, 0xa1,0x19,0x9f,0x13,0x9f,0x1b,0xa1,0x12,0xa4,0x1e,0xa4,0x13,0xaa,0x19,0xac,0x14, 0xad,0x1a,0xad,0x13,0xad,0x1e,0xa7,0x17,0xa5,0x1d,0xa1,0x1a,0x9c,0x1c,0x99,0x19, 0x97,0x1a,0x9a,0x11,0xa0,0x17,0x9f,0x10,0xa4,0x1e,0xa9,0x13,0xad,0x1a,0xae,0x17, 0xac,0x1b,0xab,0x16,0xa8,0x1f,0xa3,0x13,0xa1,0x1b,0x9d,0x18,0x9e,0x1d,0x9e,0x12, 0xa0,0x1d,0xa1,0x14,0xa9,0x1d,0xa9,0x12,0xab,0x20,0xad,0x12,0xae,0x1c,0xa8,0x13, 0xa8,0x1a,0xa5,0x13,0xa0,0x1d,0x9b,0x13,0x9d,0x1f,0x9b,0x16,0x9e,0x1d,0xa1,0x14, 0xa5,0x1c,0xa8,0x11,0xab,0x1c,0xac,0x15,0xab,0x20,0xa9,0x16,0xa7,0x19,0xa3,0x16, 0x9f,0x16,0x9b,0x12,0x99,0x19,0x9a,0x16,0x9d,0x1d,0x9e,0x12,0xa3,0x1b,0xa6,0x15, 0xaa,0x1d,0xab,0x14,0xab,0x1c,0xaa,0x12,0xa8,0x1b,0xa5,0x13,0xa2,0x1a,0x9e,0x11, 0x9b,0x1a,0x9b,0x14,0x9b,0x1b,0x9d,0x11,0xa3,0x1a,0xa7,0x18,0xa9,0x1d,0xaa,0x17, 0xac,0x1c,0xa9,0x11,0xa8,0x1e,0xa3,0x15,0x9f,0x21,0x9c,0x13,0x9a,0x21,0x99,0x13, 0x9d,0x1d,0x9d,0x16,0xa1,0x1f,0xa4,0x11,0xa9,0x1e,0xaa,0x15,0xab,0x1b,0xab,0x17, 0xa7,0x16,0xa6,0x14,0xa3,0x1e,0x9e,0x16,0x9c,0x1e,0x9b,0x13,0x9c,0x1a,0x9c,0x14, 0xa0,0x1f,0xa3,0x11,0xa6,0x1c,0xa5,0x10,0xa7,0x20,0xa9,0x18,0xa6,0x17,0xa4,0x15, 0xa2,0x1a,0x9f,0x19,0x9d,0x1d,0x9b,0x16,0x9d,0x1f,0x9b,0x14,0xa0,0x1b,0xa1,0x10, 0xa5,0x15,0xa4,0x18,0xaa,0x1e,0xa5,0x16,0xa6,0x1e,0xa4,0x0e,0xa2,0x1c,0x9c,0x11, 0x9a,0x20,0x9a,0x19,0x9a,0x1d,0x9d,0x13,0xa0,0x20,0xa3,0x13,0xa8,0x1c,0xa9,0x18, 0xab,0x1a,0xa8,0x12,0xa9,0x1a,0xa6,0x11,0xa2,0x20,0x9d,0x12,0x9a,0x1d,0x97,0x11, 0x9a,0x1e,0x9b,0x14,0x9e,0x1d,0xa1,0x15,0xa5,0x1d,0xa7,0x15,0xaa,0x1c,0xa9,0x14, 0xa8,0x19,0xa5,0x17,0xa2,0x1b,0x9e,0x14,0x9d,0x1d,0x9a,0x13,0x99,0x1d,0x9b,0x18, 0x9f,0x1e,0xa1,0x18,0xa5,0x1d,0xa7,0x14,0xaa,0x1f,0xa7,0x16,0xa9,0x1c,0xa5,0x13, 0xa2,0x1b,0x9f,0x13,0x9c,0x1b,0x9a,0x17,0x9a,0x1e,0x99,0x10,0x9d,0x1c,0x9d,0x13, 0xa2,0x1e,0xa4,0x12,0xa8,0x17,0xa6,0x13,0xa5,0x24,0xa6,0x13,0xa2,0x1e,0x9d,0x13, 0x9b,0x17,0x99,0x18,0x99,0x17,0x9b,0x18,0x9b,0x21,0x9f,0x14,0xa4,0x1e,0xa6,0x15, 0xa9,0x1c,0xa9,0x16,0xa8,0x1d,0xa5,0x11,0xa2,0x22,0xa0,0x16,0x9c,0x1e,0x99,0x14, 0x9b,0x1f,0x99,0x12,0x9a,0x1f,0x9f,0x1a,0xa1,0x1a,0xa2,0x12,0xa6,0x1c,0xa6,0x15, 0xa6,0x20,0xa3,0x14,0xa1,0x1d,0x9d,0x10,0x9a,0x22,0x97,0x15,0x96,0x1d,0x95,0x14, 0x99,0x1f,0x9c,0x15,0xa2,0x1e,0xa3,0x18,0xa5,0x20,0xa7,0x19,0xa6,0x1b,0xa3,0x15, 0xa4,0x1e,0x9e,0x16,0x9b,0x19,0x97,0x13,0x97,0x24,0x96,0x15,0x98,0x1e,0x9a,0x17, 0x9f,0x1b,0xa3,0x17,0xa5,0x1b,0xa4,0x14,0xa6,0x1d,0xa5,0x19,0xa2,0x18,0x9d,0x13, 0x9a,0x1f,0x97,0x16,0x96,0x1d,0x94,0x16,0x95,0x23,0x9a,0x14,0x9d,0x1b,0x9f,0x17, 0xa2,0x22,0xa4,0x17,0xa4,0x1f,0xa4,0x1b,0xa3,0x20,0x9e,0x13,0x99,0x20,0x98,0x16, 0x97,0x1f,0x95,0x15,0x94,0x20,0x98,0x18,0x9d,0x21,0xa0,0x15,0xa2,0x21,0xa5,0x1a, 0xa6,0x1e,0xa3,0x17,0xa1,0x1c,0x9e,0x16,0x9b,0x1c,0x98,0x18,0x96,0x1e,0x95,0x13, 0x96,0x1c,0x97,0x15,0x9c,0x1b,0x9e,0x16,0x9f,0x21,0xa0,0x17,0xa3,0x1d,0xa3,0x15, 0xa0,0x1e,0x9e,0x18,0x9c,0x1e,0x97,0x18,0x96,0x21,0x94,0x16,0x97,0x1e,0x9a,0x15, 0x9c,0x1b,0x9f,0x16,0xa1,0x1e,0xa2,0x14,0xa4,0x1f,0xa4,0x17,0xa2,0x1e,0xa0,0x17, 0x9c,0x20,0x99,0x19,0x96,0x1e,0x94,0x14,0x94,0x21,0x94,0x15,0x99,0x1f,0x9c,0x16, 0x9f,0x1e,0xa0,0x19,0xa2,0x1d,0xa2,0x15,0xa0,0x22,0x9e,0x15,0x9b,0x1c,0x96,0x16, 0x94,0x22,0x92,0x18,0x93,0x1c,0x94,0x12,0x97,0x20,0x9c,0x1a,0xa1,0x1e,0xa1,0x18, 0xa4,0x19,0xa3,0x1a,0xa2,0x20,0x9e,0x19,0x9b,0x25,0x97,0x14,0x96,0x1c,0x94,0x17, 0x95,0x1c,0x95,0x14,0x98,0x1f,0x9b,0x19,0x9f,0x1e,0xa0,0x16,0xa2,0x1d,0xa2,0x19, 0xa0,0x1d,0x9c,0x19,0x9a,0x20,0x96,0x19,0x93,0x20,0x91,0x12,0x93,0x1f,0x92,0x12, 0x95,0x20,0x99,0x1c,0x9c,0x1d,0x9f,0x14,0xa0,0x23,0xa1,0x17,0x9f,0x20,0x9d,0x1c, 0x9a,0x22,0x97,0x18,0x94,0x1c,0x92,0x16,0x91,0x23,0x93,0x15,0x97,0x1d,0x97,0x13, 0x9b,0x20,0x9f,0x14,0xa0,0x1d,0x9f,0x17,0x9f,0x21,0x9e,0x18,0x9b,0x1a,0x98,0x1a, 0x95,0x21,0x93,0x17,0x92,0x1c,0x92,0x18,0x93,0x23,0x96,0x1b,0x9a,0x1f,0x9a,0x16, 0x9e,0x23,0x9f,0x18,0x9d,0x1e,0x9b,0x18,0x9b,0x1f,0x97,0x17,0x94,0x1f,0x90,0x19, 0x91,0x1d,0x91,0x17,0x93,0x1b,0x96,0x17,0x9b,0x1f,0x9d,0x15,0x9f,0x1d,0xa0,0x17, 0x9f,0x21,0x9c,0x15,0x9d,0x1f,0x97,0x16,0x95,0x1f,0x93,0x16,0x92,0x1b,0x92,0x15, 0x94,0x1b,0x96,0x15,0x9a,0x1a,0x9d,0x12,0xa0,0x21,0x9f,0x12,0x9f,0x24,0x9e,0x19, 0x9b,0x24,0x97,0x17,0x95,0x15,0x93,0x0f,0x92,0x1e,0x91,0x16,0x93,0x1d,0x95,0x18, 0x99,0x20,0x96,0x1c,0xa2,0x60,0xa3,0x60,0xa4,0x6c,0xa1,0x6a,0x9e,0x77,0x9a,0x6e, 0x98,0x74,0x94,0x66,0x95,0x6a,0x95,0x62,0x98,0x6e,0x9c,0x5f,0x9f,0x6e,0xa0,0x61, 0xa3,0x6e,0xa3,0x62,0xa2,0x6b,0x9f,0x5c,0x9d,0x6e,0x9a,0x65,0x96,0x66,0x93,0x63, 0x96,0x6b,0x95,0x64,0x98,0x6a,0x9a,0x63,0x9f,0x6e,0xa1,0x60,0xa2,0x67,0xa3,0x61, 0xa5,0x68,0xa2,0x64,0x9e,0x6a,0x9b,0x62,0x97,0x6a,0x95,0x62,0x94,0x6c,0x93,0x60, 0x96,0x67,0x99,0x61,0x9c,0x68,0x9e,0x64,0xa4,0x6b,0xa4,0x61,0xa2,0x66,0xa2,0x64, 0xa0,0x69,0x9b,0x64,0x98,0x6c,0x95,0x68,0x95,0x71,0x94,0x65,0x96,0x6c,0x98,0x61, 0x9d,0x6c,0x9e,0x64,0xa1,0x66,0xa1,0x62,0xa2,0x6d,0xa1,0x61,0x9e,0x6c,0x9a,0x60, 0x97,0x6d,0x92,0x64,0x91,0x67,0x92,0x65,0x94,0x6d,0x96,0x61,0x9a,0x69,0x9d,0x62, 0xa2,0x68,0xa0,0x61,0xa0,0x6a,0x9f,0x63,0x9f,0x6f,0x9a,0x5d,0x98,0x66,0x94,0x60, 0x93,0x70,0x94,0x63,0x95,0x67,0x97,0x62,0x9c,0x6b,0x9f,0x5e,0xa0,0x6c,0xa1,0x63, 0xa1,0x71,0x9f,0x61,0x9d,0x6b,0x99,0x61,0x97,0x6c,0x95,0x63,0x94,0x6b,0x92,0x62, 0x96,0x6b,0x97,0x61,0x9b,0x6a,0x9d,0x5f,0xa1,0x6c,0xa0,0x63,0xa0,0x69,0x9f,0x5d, 0x9e,0x6d,0x9b,0x63,0x98,0x69,0x94,0x64,0x92,0x6a,0x91,0x5d,0x93,0x6d,0x93,0x61, 0x96,0x6a,0x9b,0x63,0x9b,0x65,0x93,0x62,0x97,0x6b,0x9c,0x62,0x91,0x67,0x8b,0x5e, 0x93,0x6d,0x92,0x63,0x8e,0x6d,0x91,0x64,0x94,0x6f,0x94,0x63,0x97,0x68,0x9a,0x60, 0x9e,0x69,0x9f,0x63,0x9f,0x68,0x9e,0x62,0x9e,0x6e,0x99,0x61,0x96,0x67,0x93,0x5f, 0x90,0x66,0x8f,0x5e,0x90,0x6c,0x90,0x61,0x95,0x6c,0x97,0x64,0x9a,0x6a,0x9b,0x66, 0x9d,0x6a,0x9c,0x62,0x9b,0x6c,0x98,0x62,0x96,0x6d,0x91,0x64,0x8e,0x69,0x8b,0x62, 0x8e,0x6a,0x8f,0x62,0x91,0x65,0x95,0x62,0x9a,0x70,0x9b,0x61,0x9d,0x6a,0x9c,0x64, 0x9c,0x69,0x98,0x62,0x96,0x6b,0x93,0x66,0x8f,0x6a,0x8d,0x64,0x8e,0x6a,0x8f,0x63, 0x93,0x6b,0x96,0x62,0x99,0x6c,0x9b,0x65,0x9e,0x6e,0x9b,0x62,0x9c,0x6a,0x99,0x62, 0x97,0x68,0x93,0x65,0x91,0x6a,0x8f,0x61,0x8f,0x6f,0x8f,0x61,0x93,0x6f,0x95,0x63, 0x99,0x70,0x9b,0x60,0x9d,0x68,0x9d,0x60,0x9e,0x6c,0x99,0x61,0x97,0x6c,0x94,0x62, 0x91,0x6c,0x8e,0x68,0x8e,0x67,0x8f,0x61,0x93,0x6e,0x95,0x63,0x98,0x6b,0x99,0x65, 0x9e,0x6a,0x9c,0x62,0x9c,0x6b,0x9b,0x66,0x98,0x73,0x95,0x5f,0x92,0x6e,0x8e,0x62, 0x8f,0x6b,0x90,0x63,0x91,0x6c,0x94,0x68,0x97,0x6a,0x9a,0x68,0x9d,0x6b,0x9b,0x61, 0x9b,0x6e,0x98,0x62,0x96,0x65,0x91,0x66,0x91,0x6e,0x8e,0x63,0x8f,0x6b,0x8e,0x5f, 0x91,0x6d,0x92,0x60,0x96,0x6c,0x99,0x60,0x9b,0x6d,0x9c,0x62,0x9c,0x69,0x99,0x63, 0x99,0x6c,0x94,0x61,0x92,0x67,0x8f,0x63,0x8b,0x68,0x85,0x61,0x8b,0x67,0x94,0x66, 0x8f,0x6f,0x92,0x68,0x9b,0x68,0x9c,0x61,0x9c,0x6e,0x9a,0x67,0x98,0x6b,0x94,0x65, 0x90,0x68,0x8e,0x65,0x8d,0x68,0x8c,0x62,0x8f,0x6d,0x91,0x60,0x94,0x67,0x97,0x67, 0x9b,0x6d,0x9a,0x66,0x9a,0x68,0x99,0x62,0x96,0x70,0x94,0x68,0x91,0x6c,0x8d,0x62, 0x8c,0x6b,0x8b,0x65,0x8d,0x6a,0x8d,0x62,0x92,0x70,0x95,0x66,0x96,0x68,0x98,0x5e, 0x99,0x6e,0x97,0x66,0x96,0x6c,0x92,0x64,0x8f,0x6d,0x8a,0x64,0x89,0x6a,0x89,0x62, 0x8c,0x6a,0x8c,0x66,0x90,0x69,0x95,0x66,0x96,0x68,0x98,0x63,0x98,0x6d,0x97,0x63, 0x95,0x70,0x92,0x64,0x90,0x6c,0x8e,0x66,0x8d,0x6f,0x8b,0x64,0x8f,0x6c,0x8e,0x62, 0x93,0x69,0x96,0x61,0x9a,0x6f,0x9a,0x66,0x9b,0x70,0x9a,0x65,0x99,0x68,0x95,0x63, 0x94,0x68,0x8f,0x63,0x8d,0x6c,0x8d,0x63,0x8f,0x70,0x90,0x68,0x92,0x68,0x97,0x64, 0x98,0x70,0x9a,0x66,0x9c,0x6b,0x9a,0x63,0x9a,0x71,0x97,0x5f,0x93,0x71,0x8f,0x63, 0x8e,0x6b,0x8d,0x63,0x8c,0x6d,0x8f,0x68,0x90,0x70,0x95,0x64,0x98,0x70,0x9b,0x5f, 0x9b,0x6c,0x9b,0x65,0x99,0x6a,0x96,0x63,0x94,0x6f,0x90,0x64,0x8d,0x6b,0x8c,0x63, 0x8d,0x6c,0x8d,0x62,0x90,0x66,0x93,0x66,0x98,0x70,0x9a,0x64,0x9b,0x6c,0x9a,0x65, 0x9a,0x6c,0x97,0x65,0x94,0x6b,0x91,0x66,0x90,0x6f,0x8d,0x60,0x8d,0x6d,0x8e,0x67, 0x93,0x6e,0x94,0x66,0x97,0x72,0x99,0x63,0x9c,0x71,0x9b,0x66,0x99,0x6c,0x97,0x61, 0x97,0x6d,0x91,0x63,0x8e,0x6c,0x8c,0x66,0x8c,0x75,0x8e,0x63,0x91,0x6d,0x92,0x63, 0x97,0x6f,0x9a,0x63,0x9b,0x6b,0x9a,0x62,0x9a,0x70,0x99,0x65,0x96,0x6a,0x91,0x63, 0x8f,0x6e,0x8c,0x63,0x8c,0x6b,0x8d,0x60,0x8f,0x70,0x92,0x66,0x96,0x6e,0x99,0x66, 0x9a,0x70,0x9b,0x62,0x99,0x72,0x99,0x68,0x97,0x6e,0x91,0x60,0x8e,0x6c,0x8e,0x67, 0x8c,0x6c,0x8b,0x65,0x8e,0x6c,0x90,0x67,0x95,0x6f,0x97,0x69,0x99,0x6d,0x9a,0x68, 0x9a,0x6f,0x98,0x64,0x96,0x6c,0x92,0x63,0x90,0x71,0x8d,0x64,0x8b,0x71,0x8c,0x65, 0x8e,0x6f,0x92,0x69,0x94,0x6a,0x97,0x64,0x9a,0x71,0x9a,0x67,0x9a,0x6c,0x98,0x67, 0x96,0x6d,0x92,0x65,0x8f,0x6c,0x8d,0x64,0x8b,0x72,0x8c,0x61,0x8e,0x6f,0x90,0x66, 0x94,0x6f,0x96,0x69,0x98,0x6d,0x99,0x68,0x99,0x73,0x98,0x69,0x97,0x6f,0x93,0x64, 0x8f,0x70,0x8d,0x66,0x8d,0x6b,0x8a,0x65,0x8c,0x6d,0x8f,0x66,0x92,0x70,0x95,0x69, 0x99,0x6f,0x9a,0x67,0x9a,0x6d,0x97,0x63,0x95,0x70,0x93,0x63,0x8f,0x6b,0x8c,0x66, 0x8b,0x6a,0x8a,0x61,0x8c,0x6c,0x8d,0x65,0x93,0x6f,0x96,0x63,0x99,0x6b,0x99,0x64, 0x9b,0x6d,0x99,0x64,0x96,0x69,0x93,0x64,0x90,0x72,0x8c,0x61,0x8b,0x63,0x8b,0x60, 0x8d,0x69,0x8e,0x65,0x93,0x6c,0x96,0x61,0x98,0x70,0x93,0x6b,0x9b,0x5b,0x9a,0x50, 0x99,0x55,0x95,0x5b,0x92,0x66,0x8f,0x5e,0x8e,0x60,0x8f,0x56,0x91,0x5e,0x92,0x55, 0x99,0x5d,0x9b,0x54,0x9d,0x5e,0x9d,0x54,0x9e,0x65,0x9c,0x55,0x9a,0x62,0x97,0x58, 0x94,0x5a,0x90,0x53,0x90,0x59,0x8e,0x53,0x91,0x60,0x92,0x53,0x95,0x5c,0x98,0x57, 0x9d,0x5c,0x9c,0x57,0x9d,0x5a,0x9c,0x54,0x9c,0x5e,0x97,0x54,0x95,0x5c,0x91,0x53, 0x8f,0x60,0x8e,0x53,0x90,0x59,0x91,0x58,0x94,0x60,0x98,0x52,0x9b,0x5d,0x9d,0x54, 0x9f,0x5c,0x9b,0x52,0x9b,0x5f,0x96,0x57,0x93,0x5b,0x90,0x57,0x8e,0x5d,0x8d,0x59, 0x8f,0x60,0x91,0x52,0x95,0x5c,0x97,0x52,0x9b,0x5e,0x9c,0x53,0x9d,0x5e,0x9b,0x57, 0x99,0x5b,0x96,0x53,0x93,0x5e,0x90,0x55,0x8d,0x5e,0x8d,0x58,0x8d,0x5d,0x8e,0x54, 0x93,0x5d,0x97,0x55,0x99,0x5b,0x9a,0x51,0x9b,0x62,0x9b,0x52,0x9a,0x5f,0x96,0x50, 0x94,0x5c,0x90,0x54,0x8e,0x5a,0x8c,0x51,0x8e,0x5d,0x8f,0x58,0x92,0x5d,0x94,0x51, 0x99,0x5f,0x9b,0x53,0x9a,0x5d,0x99,0x53,0x97,0x60,0x95,0x56,0x92,0x5e,0x8f,0x5b, 0x8e,0x5d,0x8a,0x50,0x8b,0x5b,0x8d,0x54,0x90,0x5f,0x93,0x54,0x98,0x5f,0x98,0x54, 0x99,0x5b,0x99,0x54,0x99,0x5d,0x95,0x53,0x93,0x5d,0x8f,0x52,0x8d,0x5f,0x8a,0x57, 0x8c,0x5d,0x8c,0x53,0x8f,0x5c,0x92,0x57,0x96,0x5e,0x98,0x55,0x99,0x5e,0x99,0x55, 0x98,0x5b,0x97,0x53,0x93,0x5b,0x8e,0x54,0x8b,0x5c,0x89,0x52,0x8a,0x5b,0x8a,0x55, 0x8e,0x5b,0x91,0x55,0x94,0x5b,0x96,0x50,0x99,0x5e,0x97,0x51,0x97,0x5b,0x96,0x58, 0x93,0x5d,0x8e,0x55,0x8a,0x59,0x88,0x53,0x89,0x62,0x89,0x55,0x8b,0x5c,0x8f,0x57, 0x94,0x5d,0x96,0x55,0x97,0x5f,0x96,0x54,0x97,0x5f,0x95,0x59,0x93,0x5b,0x8f,0x53, 0x8d,0x5b,0x8a,0x54,0x8a,0x5d,0x8a,0x55,0x8d,0x5e,0x8f,0x55,0x93,0x5c,0x96,0x58, 0x98,0x5e,0x96,0x54,0x98,0x5f,0x95,0x53,0x93,0x62,0x8f,0x53,0x8e,0x5e,0x8a,0x53, 0x8a,0x5c,0x8b,0x5b,0x8c,0x5f,0x8e,0x54,0x92,0x5f,0x94,0x58,0x97,0x5b,0x97,0x55, 0x97,0x5f,0x96,0x57,0x93,0x5c,0x8f,0x58,0x8b,0x61,0x8a,0x55,0x88,0x60,0x89,0x56, 0x8b,0x5e,0x8e,0x57,0x91,0x59,0x94,0x54,0x96,0x5c,0x96,0x56,0x97,0x60,0x94,0x54, 0x93,0x60,0x90,0x58,0x8e,0x5f,0x89,0x57,0x88,0x60,0x87,0x54,0x89,0x60,0x8c,0x55, 0x90,0x62,0x93,0x5b,0x95,0x5c,0x96,0x55,0x96,0x5f,0x94,0x5a,0x94,0x62,0x90,0x5a, 0x8d,0x5d,0x8a,0x59,0x88,0x5d,0x86,0x53,0x87,0x62,0x8a,0x5c,0x8d,0x5f,0x91,0x5a, 0x93,0x63,0x94,0x57,0x96,0x5f,0x95,0x58,0x93,0x5f,0x90,0x59,0x8d,0x62,0x89,0x53, 0x89,0x5e,0x88,0x5b,0x89,0x59,0x8a,0x57,0x8d,0x60,0x90,0x5c,0x93,0x5f,0x95,0x59, 0x95,0x66,0x95,0x5a,0x93,0x5f,0x91,0x59,0x8c,0x62,0x8b,0x57,0x88,0x61,0x87,0x57, 0x88,0x5e,0x8a,0x5b,0x8e,0x5f,0x91,0x5b,0x93,0x64,0x95,0x58,0x95,0x64,0x94,0x59, 0x94,0x66,0x92,0x58,0x8d,0x65,0x8b,0x59,0x88,0x63,0x87,0x5d,0x87,0x62,0x8a,0x5e, 0x8c,0x66,0x91,0x5a,0x91,0x61,0x94,0x5d,0x94,0x65,0x94,0x59,0x92,0x61,0x92,0x5f, 0x8e,0x65,0x8a,0x5d,0x88,0x61,0x88,0x5b,0x87,0x67,0x89,0x59,0x8b,0x63,0x8f,0x5f, 0x93,0x65,0x94,0x5d,0x95,0x62,0x94,0x5b,0x94,0x68,0x91,0x5c,0x8e,0x67,0x8b,0x63, 0x88,0x6c,0x87,0x5d,0x86,0x5e,0x87,0x60,0x8a,0x68,0x8b,0x62,0x90,0x64,0x91,0x64, 0x93,0x68,0x92,0x63,0x92,0x67,0x8f,0x62,0x8e,0x6a,0x8a,0x63,0x87,0x67,0x85,0x64, 0x86,0x6e,0x86,0x63,0x89,0x6a,0x8b,0x5f,0x8f,0x6d,0x90,0x64,0x92,0x6a,0x91,0x6b, 0x91,0x71,0x8f,0x67,0x8c,0x68,0x88,0x60,0x86,0x6a,0x85,0x67,0x84,0x6e,0x85,0x66, 0x87,0x75,0x88,0x68,0x8d,0x6c,0x8e,0x64,0x8f,0x72,0x90,0x67,0x91,0x6f,0x8d,0x65, 0x8c,0x73,0x89,0x63,0x86,0x6c,0x83,0x67,0x82,0x73,0x82,0x67,0x84,0x70,0x88,0x66, 0x8b,0x70,0x8d,0x69,0x8e,0x70,0x8f,0x65,0x8e,0x71,0x8d,0x66,0x8a,0x70,0x89,0x66, 0x82,0x71,0x82,0x66,0x82,0x6a,0x81,0x66,0x84,0x6e,0x86,0x63,0x8b,0x6d,0x8c,0x63, 0x8f,0x6f,0x8f,0x64,0x8f,0x6c,0x8e,0x69,0x8c,0x70,0x87,0x67,0x85,0x6c,0x82,0x64, 0x80,0x70,0x82,0x68,0x83,0x68,0x84,0x66,0x89,0x6c,0x8b,0x62,0x8f,0x6b,0x8f,0x6a, 0x90,0x6b,0x8e,0x66,0x8c,0x69,0x88,0x65,0x86,0x6e,0x82,0x63,0x80,0x68,0x80,0x63, 0x84,0x6f,0x84,0x63,0x87,0x6a,0x8a,0x67,0x8c,0x70,0x8d,0x62,0x8d,0x6f,0x8c,0x62, 0x89,0x70,0x88,0x63,0x86,0x6a,0x82,0x5f,0x81,0x6d,0x80,0x64,0x82,0x6d,0x82,0x63, 0x85,0x6f,0x88,0x65,0x8b,0x69,0x8a,0x66,0x8b,0x70,0x8c,0x63,0x8c,0x6c,0x87,0x66, 0x85,0x72,0x82,0x66,0x80,0x69,0x7f,0x66,0x7f,0x75,0x80,0x67,0x85,0x6f,0x86,0x66, 0x88,0x70,0x8a,0x67,0x8b,0x70,0x8a,0x68,0x88,0x76,0x87,0x6f,0x84,0x75,0x81,0x6c, 0x7e,0x74,0x7e,0x6b,0x7d,0x74,0x7e,0x6b,0x80,0x74,0x83,0x68,0x86,0x77,0x88,0x6f, 0x88,0x7a,0x89,0x6e,0x87,0x71,0x85,0x6d,0x82,0x79,0x80,0x6e,0x7d,0x7b,0x7a,0x72, 0x7a,0x78,0x7c,0x70,0x7d,0x73,0x82,0x6f,0x84,0x77,0x86,0x6e,0x87,0x78,0x87,0x70, 0x87,0x76,0x85,0x71,0x83,0x77,0x7f,0x70,0x7f,0x76,0x7a,0x72,0x7a,0x78,0x7b,0x6f, 0x7e,0x79,0x81,0x6e,0x83,0x78,0x86,0x6f,0x88,0x76,0x88,0x6f,0x88,0x76,0x86,0x72, 0x84,0x7c,0x81,0x74,0x7e,0x76,0x7c,0x72,0x7c,0x7b,0x7c,0x72,0x7e,0x76,0x81,0x6c, 0x84,0x79,0x86,0x71,0x89,0x7c,0x88,0x71,0x89,0x7d,0x88,0x71,0x85,0x7b,0x82,0x72, 0x81,0x7a,0x7e,0x73,0x7d,0x7b,0x7c,0x75,0x80,0x7e,0x83,0x7a,0x86,0x7f,0x88,0x7b, 0x89,0x80,0x83,0x80,0x69,0x59,0x9c,0x9a,0x9a,0x9b,0x9d,0x9e,0xa0,0xa1,0xa0,0xa2, 0xa4,0xa4,0xa7,0xa7,0xa7,0xa8,0xa9,0xa9,0xa8,0xa7,0xa6,0xa4,0xa3,0xa2,0xa1,0x9f, 0x9f,0x9c,0x9b,0x9a,0x9a,0x9a,0x9b,0x9b,0x9c,0x9e,0xa0,0xa2,0xa3,0xa3,0xa4,0xa4, 0xa7,0xa6,0xa7,0xa7,0xa7,0xa6,0xa4,0xa3,0xa2,0xa0,0xa0,0x9d,0x9c,0x9a,0x9a,0x99, 0x97,0x99,0x9a,0x9a,0x9b,0x9c,0x9d,0x9f,0xa3,0xa3,0xa5,0xa6,0xa6,0xa6,0xa6,0xa6, 0xa5,0xa6,0xa5,0xa4,0xa2,0xa2,0xa0,0x9e,0x9c,0x9c,0x9b,0x9a,0x9a,0x9b,0x9a,0x9c, 0x9d,0x9e,0x9e,0xa0,0xa2,0xa2,0xa1,0xa4,0xa4,0xa4,0xa5,0xa6,0xa5,0xa6,0xa4,0xa4, 0xa3,0xa1,0xa1,0x9f,0x9d,0x9b,0x99,0x9a,0x99,0x99,0x99,0x98,0x9a,0x9b,0x9e,0x9d, 0x9f,0x9f,0xa3,0xa4,0xa5,0xa6,0xa4,0xa3,0xa2,0xa5,0xa6,0xa6,0xa5,0xa3,0xa1,0x9f, 0x9d,0x9c,0x9b,0x9b,0x99,0x98,0x97,0x97,0x9a,0x9b,0x9e,0x9e,0x9f,0x9f,0xa1,0xa2, 0xa5,0xa4,0xa5,0xa6,0xa6,0xa7,0xa5,0xa4,0xa3,0xa3,0xa2,0xa1,0x9e,0x9d,0x9d,0x99, 0x9a,0x99,0x99,0x98,0x9a,0x9c,0x9c,0x9f,0x9f,0xa1,0xa3,0xa2,0xa5,0xa7,0xa8,0xa8, 0xa7,0xa6,0xa4,0xa4,0xa4,0xa4,0xa4,0xa2,0x9e,0x9c,0x9b,0x9a,0x99,0x9b,0x99,0x9a, 0x9b,0x9b,0x9e,0xa0,0xa0,0xa1,0xa2,0xa3,0xa4,0xa6,0xa6,0xa7,0xa7,0xa8,0xa8,0xa7, 0xa4,0xa5,0xa3,0xa1,0xa0,0x9e,0x9e,0x9c,0x9d,0x9b,0x9a,0x9a,0x9b,0x9b,0x9f,0xa0, 0xa0,0xa1,0xa2,0xa3,0xa5,0xa6,0xa8,0xa8,0xa8,0xa7,0xa8,0xa6,0xa6,0xa5,0xa4,0xa3, 0xa1,0x9f,0x9b,0x9b,0x99,0x98,0x99,0x9b,0x9c,0x9b,0x9d,0x9d,0x9f,0xa1,0xa3,0xa5, 0xa6,0xaa,0xaa,0xa9,0xa9,0xa7,0xa7,0xa7,0xa6,0xa7,0xa6,0xa6,0xa4,0xa2,0xa0,0x9f, 0x9f,0x9c,0x9c,0x9b,0x9c,0x9d,0x9f,0x9f,0x9f,0xa3,0xa4,0xa6,0xa7,0xa8,0xa9,0xa9, 0xaa,0xa9,0xa9,0xaa,0xa9,0xa7,0xa8,0xa8,0xa5,0xa4,0xa3,0xa1,0xa0,0x9f,0x9e,0x9d, 0x9f,0x9f,0xa0,0xa0,0xa3,0xa3,0xa5,0xa7,0xa9,0xa9,0xab,0xab,0xac,0xad,0xad,0xab, 0xaa,0xab,0xaa,0xa7,0xa7,0xa4,0xa3,0xa3,0xa1,0x9f,0x9e,0x9e,0x9e,0x9e,0x9f,0x9f, 0xa2,0xa3,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xab,0xab,0xaa,0xaa,0xab,0xa9,0xa7, 0xa5,0xa4,0xa3,0xa1,0xa2,0xa1,0x9f,0x9d,0x9c,0x9f,0x9f,0xa0,0xa2,0xa4,0xa6,0xa6, 0xa8,0xaa,0xac,0xac,0xac,0xac,0xad,0xad,0xab,0xab,0xab,0xa8,0xa9,0xa6,0xa5,0xa3, 0xa3,0xa1,0x9f,0x9f,0x9f,0x9e,0x9f,0xa1,0xa1,0xa3,0xa5,0xa6,0xa9,0xa9,0xaa,0xab, 0xaa,0xaa,0xac,0xad,0xac,0xa9,0xaa,0xa9,0xa8,0xa8,0xa4,0xa4,0xa2,0x9f,0x9f,0xa0, 0x9f,0xa0,0xa2,0xa1,0xa2,0xa3,0xa4,0xa5,0xa4,0xa5,0xa8,0xaa,0xae,0xaa,0xaa,0xa8, 0xa8,0xa8,0xa9,0xaa,0xa9,0xa5,0xa2,0xa2,0xa2,0xa1,0xa0,0xa0,0xa0,0xa1,0xa1,0xa1, 0xa1,0xa2,0xa3,0xa5,0xa7,0xa9,0xaa,0xac,0xac,0xad,0xad,0xac,0xac,0xab,0xac,0xab, 0xa9,0xa8,0xa8,0xa5,0xa3,0xa2,0xa0,0xa1,0xa0,0xa0,0x9f,0xa0,0xa2,0xa4,0xa4,0xa5, 0xa4,0xa6,0xa9,0xab,0xae,0xae,0xad,0xab,0xad,0xac,0xad,0xab,0xab,0xa9,0xa7,0xa7, 0xa5,0xa1,0xa0,0x9e,0x9e,0x9d,0x98,0xa6,0xa9,0xab,0xac,0xae,0xaf,0xb1,0xb2,0xb3, 0xb2,0xb4,0xb3,0xb4,0xb4,0xb5,0xb2,0xaf,0xae,0xad,0xab,0xab,0xa9,0xa9,0xa6,0xa3, 0xa5,0xa5,0xa6,0xa8,0xa8,0xab,0xab,0xae,0xaf,0xb0,0xb2,0xb3,0xb5,0xb4,0xb4,0xb4, 0xb3,0xb2,0xb2,0xb1,0xb0,0xaf,0xae,0xab,0xaa,0xa8,0xa8,0xa6,0xa6,0xa5,0xa8,0xaa, 0xaa,0xaa,0xad,0xae,0xb0,0xb4,0xb5,0xb4,0xb6,0xb7,0xb6,0xb8,0xb7,0xb7,0xb7,0xb5, 0xb3,0xb0,0xb1,0xaf,0xad,0xab,0xac,0xaa,0xaa,0xab,0xac,0xab,0xac,0xab,0xad,0xaf, 0xb1,0xb4,0xb4,0xb6,0xb5,0xb6,0xb6,0xb6,0xb6,0xb7,0xb5,0xb6,0xb5,0xb3,0xb1,0xaf, 0xab,0xab,0xaa,0xaa,0xaa,0xab,0xaa,0xaa,0xab,0xac,0xac,0xaf,0xb0,0xb1,0xb2,0xb4, 0xb7,0xb7,0xb5,0xb5,0xb7,0xb9,0xb5,0xb4,0xb2,0xb1,0xaf,0xaf,0xad,0xad,0xab,0xa9, 0xa8,0xa9,0xaa,0xac,0xac,0xad,0xae,0xaf,0xb0,0xb4,0xb6,0xb7,0xb5,0xb5,0xb7,0xb7, 0xb9,0xb9,0xb7,0xb9,0xb6,0xb5,0xb2,0xb1,0xae,0xae,0xae,0xac,0xac,0xaa,0xa8,0xa9, 0xab,0xad,0xae,0xae,0xb0,0xb2,0xb4,0xb6,0xb5,0xb6,0xb7,0xb9,0xb8,0xb7,0xb5,0xb4, 0xb5,0xb3,0xb4,0xb2,0xad,0xac,0xaa,0xa9,0xa9,0xa8,0xa8,0xa8,0xa8,0xa9,0xaa,0xab, 0xae,0xaf,0xb2,0xb3,0xb3,0xb2,0xb7,0xb8,0xb5,0xb5,0xb6,0xb3,0xb2,0xb3,0xb2,0xaf, 0xae,0xab,0xa9,0xaa,0xa7,0xa5,0xa7,0xa7,0xa9,0xa9,0xa9,0xaa,0xab,0xae,0xb1,0xb1, 0xb2,0xb4,0xb5,0xb6,0xb3,0xb5,0xb5,0xb4,0xb4,0xb5,0xb1,0xaf,0xac,0xab,0xab,0xaa, 0xaa,0xa9,0xa7,0xa8,0xa6,0xa6,0xa6,0xa8,0xaa,0xaf,0xb1,0xb1,0xaf,0xb0,0xb3,0xb3, 0xb4,0xb5,0xb5,0xb3,0xb1,0xb0,0xb2,0xaf,0xaf,0xae,0xab,0xaa,0xa8,0xa8,0xa8,0xa7, 0xa7,0xa7,0xa9,0xac,0xad,0xad,0xae,0xaf,0xb3,0xb3,0xb5,0xb5,0xb6,0xb5,0xb6,0xb6, 0xb4,0xb3,0xb2,0xb1,0xb0,0xae,0xae,0xac,0xaa,0xaa,0xa8,0xa9,0xa7,0xa8,0xaa,0xab, 0xae,0xb0,0xb0,0xb1,0xb2,0xb2,0xb4,0xb5,0xb6,0xb9,0xb6,0xb5,0xb5,0xb4,0xb4,0xb1, 0xb1,0xb0,0xad,0xac,0xab,0xab,0xaa,0xa8,0xa9,0xa9,0xaa,0xab,0xac,0xac,0xac,0xb0, 0xb2,0xb3,0xb5,0xb6,0xb6,0xb6,0xb5,0xb7,0xb5,0xb6,0xb4,0xb1,0xb0,0xae,0xac,0xac, 0xac,0xab,0xa8,0xa8,0xa7,0xa8,0xa7,0xaa,0xac,0xad,0xaf,0xb1,0xb1,0xb2,0xb5,0xb6, 0xb7,0xb6,0xb5,0xb6,0xb5,0xb6,0xb7,0xb5,0xb4,0xb2,0xae,0xaf,0xac,0xaa,0xa8,0xa8, 0xa7,0xa8,0xab,0xab,0xac,0xad,0xad,0xb1,0xb3,0xb3,0xb6,0xb6,0xb6,0xb5,0xb8,0xb6, 0xb7,0xb5,0xb4,0xb2,0xb1,0xb0,0xad,0xab,0xaa,0xa9,0xa7,0xa7,0xa5,0xa7,0xa8,0xa8, 0xa9,0xac,0xad,0xaf,0xb1,0xb3,0xb3,0xb3,0xb3,0xb5,0xb7,0xb7,0xb7,0xb5,0xb5,0xb1, 0xb3,0xb0,0xb0,0xad,0xac,0xaa,0xa8,0xa9,0xa7,0xa8,0xa8,0xa9,0xa9,0xab,0xae,0xae, 0xb0,0xb2,0xb4,0xb4,0xb6,0xb6,0xb5,0xb6,0xb6,0xb7,0xb4,0xb5,0xb4,0xb2,0xb0,0xaf, 0xae,0xac,0xab,0xab,0xa8,0xa9,0xa8,0xa9,0xab,0xac,0xae,0xaf,0xad,0xb1,0xb3,0xb5, 0xb5,0xb5,0xb6,0xb7,0xb7,0xb7,0xb4,0xb5,0xb3,0xb2,0xb0,0xb0,0xae,0xaa,0xa8,0xa8, 0xa9,0xa8,0xa7,0xa9,0xaa,0xaa,0xac,0xac,0xaf,0xb0,0xb3,0xb5,0xb5,0xb5,0xb6,0xb6, 0xb7,0xb7,0xb7,0xb6,0xb5,0xb2,0xb0,0xad,0xad,0xac,0xaa,0xa9,0xa9,0xa9,0xa8,0xa9, 0xa9,0xaa,0xaa,0xac,0xad,0xaf,0xb1,0xb1,0xb3,0xb3,0xb5,0xb5,0xb5,0xb5,0xb6,0xb3, 0xb3,0xb1,0xb0,0xac,0xad,0xab,0xab,0xa9,0xa8,0xa9,0xa8,0xa8,0xa8,0xa9,0xaa,0xab, 0xaf,0xb0,0xb1,0xb3,0xb4,0xb2,0xb3,0xb2,0xb4,0xb5,0xb3,0xb3,0xb3,0xb0,0xad,0xaa, 0xaa,0xaa,0xab,0xa8,0xa4,0xa4,0xa4,0xa4,0xa7,0xab,0xaa,0xaa,0xac,0xac,0xad,0xb0, 0xb0,0xb2,0xb3,0xb4,0xb5,0xb4,0xb3,0xb1,0xb1,0xb0,0xaf,0xae,0xad,0xa9,0xa7,0xa9, 0xa8,0xa6,0xa6,0xa5,0xa5,0xa5,0xa8,0xa8,0xab,0xac,0xae,0xaf,0xb2,0xb1,0xb3,0xb2, 0xb3,0xb4,0xb4,0xb3,0xb4,0xb1,0xaf,0xae,0xad,0xac,0xad,0xab,0xa9,0xa7,0xa7,0xa5, 0xa7,0xa7,0xa9,0xa8,0xa9,0xaa,0xac,0xae,0xaf,0xb0,0xb1,0xb0,0xb4,0xb3,0xb3,0xb3, 0xb0,0xaf,0xb0,0xaf,0xae,0xad,0xa9,0xa8,0xa6,0xa6,0xa7,0xa7,0xa8,0xa7,0xa9,0xaa, 0xab,0xac,0xad,0xaf,0xb1,0xb2,0xb4,0xb4,0xb4,0xb4,0xb5,0xb5,0xb5,0xb3,0xb0,0xb0, 0xb1,0xaf,0xac,0xaa,0xaa,0xa9,0xa8,0xa6,0xa6,0xa9,0xa8,0xa9,0xab,0xac,0xad,0xae, 0xae,0xaf,0xb1,0xb3,0xb2,0xb4,0xb4,0xb1,0xb1,0xb0,0xb2,0xb1,0xb0,0xac,0xac,0xaa, 0xab,0xaa,0xa8,0xa8,0xa7,0xa8,0xa8,0xa8,0xaa,0xac,0xad,0xae,0xae,0xb2,0xb3,0xb5, 0xb5,0xb7,0xb5,0xb6,0xb6,0xb4,0xb3,0xb3,0xb1,0xae,0xaf,0xad,0xae,0xaa,0xaa,0xa8, 0xa6,0xa8,0xa8,0xa8,0xaa,0xaa,0xac,0xae,0xb0,0xb0,0xb2,0xb2,0xb4,0xb5,0xb4,0xb3, 0xb5,0xb2,0xb2,0xb1,0xb1,0xae,0xad,0xab,0xaa,0xaa,0xa9,0xa7,0xa8,0xa7,0xa9,0xa8, 0xa9,0xac,0xab,0xad,0xb1,0xb0,0xb2,0xb4,0xb5,0xb6,0xb5,0xb5,0xb5,0xb4,0xb3,0xb2, 0xb2,0xb0,0xaf,0xad,0xab,0xab,0xa8,0xa8,0xa8,0xa7,0xa9,0xa8,0xaa,0xab,0xad,0xac, 0xb0,0xb2,0xb3,0xb4,0xb4,0xb5,0xb4,0xb5,0xb6,0xb5,0xb6,0xb4,0xb2,0xaf,0xae,0xad, 0xac,0xaa,0xa9,0xa6,0xa6,0xa7,0xa6,0xa6,0xa6,0xa7,0xa9,0xaa,0xae,0xaf,0xb1,0xb1, 0xb1,0xb3,0xb3,0xb3,0xb4,0xb4,0xb2,0xb1,0xb1,0xb1,0xaf,0xae,0xae,0xaa,0xaa,0xa9, 0xa9,0xaa,0xa8,0xa6,0xa5,0xa7,0xa9,0xad,0xb0,0xb1,0xaf,0xae,0xb0,0xb3,0xb4,0xb7, 0xb6,0xb5,0xb4,0xb4,0xb3,0xb2,0xb1,0xae,0xae,0xad,0xad,0xaa,0xa8,0xa9,0xa9,0xa9, 0xac,0xab,0xad,0xae,0xb0,0xb1,0xb1,0xb2,0xb5,0xb3,0xb5,0xb5,0xb6,0xb5,0xb6,0xb4, 0xb3,0xb2,0xb1,0xb0,0xae,0xae,0xad,0xab,0xa9,0xa9,0xa6,0xa5,0xa7,0xa4,0xa1,0xb0, 0xb4,0xb4,0xb7,0xba,0xb9,0xba,0xb8,0xba,0xba,0xba,0xb9,0xb8,0xb8,0xb6,0xb3,0xb2, 0xb1,0xb2,0xb0,0xad,0xac,0xac,0xad,0xae,0xb0,0xb0,0xb3,0xb2,0xb6,0xb7,0xb8,0xb8, 0xbb,0xbb,0xbb,0xbb,0xba,0xbe,0xb9,0xb9,0xba,0xb7,0xb6,0xb5,0xb3,0xb2,0xb0,0xaf, 0xaf,0xae,0xaf,0xaf,0xaf,0xb0,0xb3,0xb2,0xb8,0xb8,0xb9,0xba,0xbb,0xbb,0xbd,0xbd, 0xbd,0xbb,0xbb,0xba,0xba,0xb9,0xb7,0xb5,0xb5,0xb3,0xb2,0xb2,0xb1,0xaf,0xb0,0xb0, 0xb2,0xb2,0xb1,0xb2,0xb4,0xb7,0xb8,0xb7,0xb8,0xbb,0xba,0xb8,0xb9,0xbb,0xba,0xb8, 0xb8,0xb8,0xb7,0xb7,0xb3,0xb1,0xb3,0xb0,0xb0,0xac,0xaf,0xae,0xb1,0xae,0xaf,0xaf, 0xb2,0xb4,0xb6,0xb7,0xb8,0xb9,0xba,0xbc,0xbe,0xbd,0xbb,0xb9,0xb7,0xb6,0xb5,0xb5, 0xb7,0xb2,0xae,0xac,0xad,0xac,0xae,0xb0,0xb0,0xb1,0xb0,0xb1,0xb5,0xb6,0xb9,0xbb, 0xbc,0xbd,0xbe,0xbc,0xbe,0xbe,0xbe,0xbc,0xbc,0xbc,0xb8,0xb8,0xb6,0xb4,0xb4,0xb5, 0xb4,0xb0,0xb0,0xae,0xb0,0xb0,0xb1,0xb2,0xb4,0xb6,0xb6,0xb6,0xb8,0xba,0xbc,0xbc, 0xbe,0xbb,0xb9,0xba,0xbb,0xbb,0xbc,0xb8,0xb5,0xb4,0xb4,0xb3,0xb3,0xb1,0xb1,0xb1, 0xb2,0xb2,0xb4,0xb7,0xb7,0xb8,0xba,0xbb,0xbc,0xbd,0xbf,0xbf,0xc2,0xc1,0xc1,0xc1, 0xbe,0xc0,0xbd,0xba,0xb8,0xb7,0xb6,0xb6,0xb6,0xb2,0xb3,0xaf,0xae,0xaf,0xb1,0xb5, 0xb6,0xb5,0xb8,0xb8,0xb9,0xbd,0xbe,0xbe,0xc0,0xc0,0xbf,0xc1,0xc0,0xbe,0xbe,0xbd, 0xbd,0xbb,0xb9,0xb7,0xb6,0xb5,0xb5,0xb7,0xb6,0xb4,0xb5,0xb6,0xb8,0xba,0xbb,0xbb, 0xbe,0xbf,0xc2,0xc1,0xc1,0xc0,0xc1,0xc2,0xc1,0xc1,0xc1,0xc0,0xbc,0xbc,0xb9,0xb8, 0xb9,0xb9,0xb6,0xb6,0xb4,0xb4,0xb4,0xb7,0xb9,0xb8,0xbb,0xbc,0xbc,0xbd,0xbd,0xbe, 0xc1,0xc2,0xc0,0xbf,0xbf,0xbf,0xbd,0xbc,0xbe,0xbb,0xb9,0xb8,0xb7,0xb7,0xb6,0xb4, 0xb4,0xb5,0xb4,0xb6,0xb7,0xb8,0xb8,0xbc,0xbd,0xbe,0xc1,0xc1,0xc2,0xc3,0xc2,0xc4, 0xc5,0xc5,0xc3,0xc2,0xbe,0xbe,0xbd,0xbb,0xb9,0xb8,0xb4,0xb6,0xb6,0xb3,0xb4,0xb6, 0xb5,0xb7,0xb9,0xbc,0xbe,0xbf,0xbe,0xc2,0xbf,0xc0,0xc0,0xc3,0xc2,0xc1,0xbe,0xbd, 0xbb,0xb9,0xb7,0xb6,0xb6,0xb5,0xb3,0xb2,0xb1,0xb1,0xb3,0xb5,0xb6,0xb7,0xb9,0xba, 0xbe,0xbe,0xbf,0xc2,0xc2,0xc3,0xc3,0xc4,0xc4,0xc1,0xc2,0xbf,0xbc,0xbe,0xbb,0xba, 0xb9,0xb7,0xb4,0xb5,0xb5,0xb4,0xb4,0xb5,0xb7,0xb7,0xb9,0xb9,0xbb,0xbd,0xbe,0xc1, 0xc3,0xc2,0xc0,0xc0,0xc2,0xc2,0xc1,0xc2,0xc1,0xc0,0xbc,0xba,0xb9,0xb9,0xb9,0xb9, 0xb6,0xb2,0xb3,0xb3,0xb6,0xb8,0xbb,0xba,0xbd,0xbd,0xbd,0xc1,0xc2,0xc2,0xc3,0xc2, 0xc3,0xc2,0xc2,0xc2,0xc0,0xbe,0xbd,0xbc,0xbb,0xb9,0xb9,0xb4,0xb4,0xb5,0xb4,0xb3, 0xb5,0xb5,0xb6,0xb6,0xb8,0xba,0xbb,0xbe,0xc0,0xc2,0xc1,0xc2,0xc2,0xc3,0xc3,0xc1, 0xc1,0xbf,0xbe,0xbb,0xb9,0xb8,0xb7,0xb3,0xb3,0xb2,0xb2,0xb2,0xb3,0xb4,0xb5,0xb5, 0xb8,0xb9,0xbd,0xbf,0xc0,0xbf,0xc0,0xbf,0xc0,0xc2,0xc4,0xc1,0xbf,0xbd,0xb9,0xb9, 0xba,0xba,0xb7,0xb6,0xb2,0xb2,0xb2,0xb2,0xb4,0xb7,0xb8,0xb7,0xb8,0xbb,0xbc,0xbe, 0xc1,0xc1,0xc1,0xc2,0xc0,0xc2,0xc2,0xc2,0xc0,0xbf,0xbe,0xbc,0xbc,0xba,0xb8,0xb7, 0xb5,0xb1,0xb4,0xb3,0xb3,0xb4,0xb4,0xb5,0xb7,0xb8,0xbb,0xbb,0xbc,0xbe,0xbe,0xc0, 0xbf,0xc0,0xc1,0xc1,0xbf,0xbf,0xbe,0xbd,0xbd,0xba,0xb8,0xb6,0xb6,0xb6,0xb6,0xb6, 0xb5,0xb5,0xb7,0xb6,0xb8,0xba,0xbb,0xbb,0xc0,0xbd,0xbd,0xc0,0xc1,0xbf,0xc0,0xbd, 0xbd,0xbb,0xbb,0xbb,0xb9,0xb8,0xb7,0xb5,0xb4,0xb6,0xb4,0xb3,0xb1,0xb2,0xb3,0xb4, 0xb8,0xb9,0xb8,0xb9,0xb9,0xb9,0xbb,0xc0,0xbf,0xc0,0xbe,0xbe,0xbc,0xbd,0xbc,0xbc, 0xb7,0xb8,0xb6,0xb4,0xb6,0xb5,0xb3,0xb1,0xb1,0xb1,0xb1,0xb4,0xb6,0xb7,0xb7,0xb9, 0xba,0xba,0xbd,0xbd,0xbd,0xbd,0xbd,0xbc,0xbc,0xba,0xb9,0xb8,0xb8,0xb6,0xb5,0xb5, 0xb3,0xb2,0xb2,0xb2,0xb2,0xb3,0xb4,0xb3,0xb4,0xb7,0xb7,0xb9,0xbc,0xbc,0xbd,0xbe, 0xbf,0xc0,0xc2,0xc0,0xbf,0xbe,0xbf,0xbe,0xbc,0xba,0xb8,0xb7,0xb6,0xb3,0xb2,0xb0, 0xb0,0xb2,0xb4,0xb2,0xb3,0xb2,0xb4,0xb5,0xba,0xba,0xbc,0xbb,0xba,0xbb,0xbc,0xbc, 0xbd,0xbc,0xbc,0xbb,0xba,0xba,0xb8,0xb6,0xb6,0xb4,0xb2,0xb2,0xb2,0xb2,0xb4,0xb5, 0xb6,0xb5,0xb6,0xb7,0xba,0xbb,0xbd,0xbe,0xbe,0xbd,0xbe,0xbe,0xbe,0xbf,0xbc,0xbc, 0xbb,0xba,0xb7,0xb6,0xb4,0xb4,0xb2,0xb2,0xb1,0xb0,0xb0,0xb1,0xb2,0xb3,0xb6,0xb8, 0xb8,0xbb,0xbd,0xbd,0xbe,0xbf,0xc1,0xbf,0xc0,0xbf,0xbe,0xbd,0xbd,0xbe,0xbb,0xb8, 0xb7,0xb5,0xb3,0xb5,0xb4,0xb4,0xb4,0xb3,0xb4,0xb5,0xb5,0xb7,0xb8,0xbb,0xba,0xbc, 0xbe,0xbe,0xbf,0xbe,0xbf,0xbe,0xbd,0xbb,0xbd,0xbb,0xba,0xb9,0xb7,0xb6,0xb5,0xb4, 0xb3,0xb1,0xb1,0xad,0xaa,0xac,0xaf,0xb3,0xb9,0xb8,0xb9,0xb8,0xb7,0xb8,0xbd,0xc1, 0xc0,0xbf,0xbe,0xbd,0xbd,0xbe,0xbd,0xba,0xb9,0xb8,0xb6,0xb7,0xb8,0xb6,0xb0,0xaa, 0xa9,0xa9,0xb0,0xb8,0xbb,0xb4,0xae,0xad,0xb1,0xba,0xc0,0xc1,0xbf,0xbc,0xba,0xbc, 0xbe,0xbb,0xbc,0xb9,0xb8,0xb7,0xb5,0xb3,0xb4,0xb4,0xb4,0xb2,0xb4,0xb3,0xb6,0xb6, 0xb7,0xb9,0xb8,0xbb,0xbb,0xbe,0xc0,0xc1,0xbf,0xbe,0xbc,0xbd,0xbb,0xbc,0xbc,0xb9, 0xb6,0xb5,0xb4,0xb3,0xb3,0xb4,0xb2,0xb2,0xb1,0xb1,0xb3,0xb3,0xb6,0xb5,0xb8,0xb8, 0xba,0xbc,0xbb,0xbd,0xbe,0xbd,0xbc,0xbc,0xbb,0xba,0xb9,0xb9,0xb7,0xb6,0xb6,0xb3, 0xb1,0xb1,0xb1,0xb2,0xb2,0xb2,0xb3,0xb5,0xb6,0xb7,0xb7,0xb9,0xbb,0xbe,0xbd,0xbe, 0xbd,0xbb,0xbc,0xbc,0xbb,0xbb,0xb9,0xb7,0xb4,0xb4,0xb2,0xb3,0xb0,0xb0,0xad,0xaf, 0xad,0xb1,0xb1,0xb1,0xb1,0xaf,0xad,0xbc,0xc2,0xc3,0xc1,0xc3,0xc1,0xc4,0xc2,0xc3, 0xc1,0xc0,0xbc,0xbb,0xbb,0xb9,0xb7,0xb5,0xb5,0xb3,0xb3,0xb3,0xb4,0xb5,0xb5,0xb3, 0xb6,0xb8,0xb9,0xbe,0xbd,0xbc,0xbc,0xbd,0xbd,0xbf,0xbf,0xbe,0xbe,0xbc,0xbb,0xba, 0xb8,0xb8,0xb5,0xb6,0xb2,0xb1,0xb0,0xb1,0xb2,0xb2,0xb4,0xb6,0xb7,0xb8,0xb9,0xbc, 0xbd,0xbd,0xbf,0xc1,0xc0,0xc0,0xc1,0xbe,0xbf,0xbe,0xbb,0xba,0xb8,0xb7,0xb4,0xb3, 0xb0,0xb0,0xaf,0xb0,0xae,0xaf,0xaf,0xb1,0xb2,0xb6,0xb6,0xb9,0xbb,0xbd,0xbd,0xbb, 0xbe,0xbf,0xbc,0xbe,0xbc,0xbb,0xbb,0xb9,0xb5,0xb4,0xb4,0xb2,0xb2,0xb1,0xaf,0xaf, 0xaf,0xb1,0xb3,0xb5,0xb3,0xb4,0xb4,0xb7,0xb9,0xbb,0xba,0xba,0xb9,0xba,0xbb,0xba, 0xba,0xb4,0xb4,0xb3,0xb2,0xaf,0xae,0xac,0xaa,0xa9,0xa8,0xa7,0xa6,0xa9,0xab,0xb0, 0xaf,0xb0,0xae,0xb0,0xb4,0xb6,0xb8,0xb9,0xba,0xbc,0xba,0xba,0xb9,0xb8,0xba,0xb7, 0xb5,0xb5,0xb1,0xb1,0xaf,0xae,0xae,0xae,0xae,0xae,0xae,0xaf,0xaf,0xaf,0xb1,0xb5, 0xb8,0xb8,0xb7,0xb9,0xb8,0xba,0xbb,0xbb,0xba,0xb8,0xb5,0xb5,0xb5,0xb4,0xb2,0xb0, 0xae,0xad,0xab,0xac,0xab,0xaa,0xac,0xac,0xae,0xb0,0xb0,0xb3,0xb3,0xb6,0xb6,0xb6, 0xb8,0xb8,0xb8,0xb8,0xb7,0xb8,0xb5,0xb5,0xb2,0xb1,0xb0,0xaf,0xad,0xac,0xaa,0xa8, 0xa9,0xaa,0xaa,0xac,0xad,0xae,0xae,0xb1,0xb2,0xb4,0xb4,0xb6,0xb6,0xb7,0xb7,0xb7, 0xb8,0xb8,0xb7,0xb7,0xb5,0xb4,0xb2,0xb2,0xae,0xae,0xad,0xaa,0xaa,0xab,0xab,0xaa, 0xaa,0xac,0xae,0xb0,0xb3,0xb4,0xb4,0xb5,0xb6,0xb8,0xb8,0xb9,0xba,0xb8,0xb8,0xb6, 0xb6,0xb3,0xb0,0xb0,0xae,0xac,0xab,0xab,0xaa,0xa8,0xa9,0xaa,0xab,0xab,0xac,0xad, 0xaf,0xb0,0xb3,0xb4,0xb5,0xb5,0xb7,0xb8,0xb8,0xb7,0xb8,0xb5,0xb4,0xb5,0xb4,0xb3, 0xb1,0xb0,0xae,0xac,0xab,0xac,0xab,0xac,0xac,0xac,0xab,0xac,0xae,0xb1,0xb2,0xb3, 0xb2,0xb2,0xb4,0xb4,0xb6,0xb6,0xb5,0xb3,0xb2,0xb2,0xb2,0xb2,0xaf,0xaf,0xae,0xad, 0xac,0xab,0xab,0xac,0xab,0xaa,0xac,0xaf,0xaf,0xaf,0xae,0xb0,0xb2,0xb1,0xb2,0xb5, 0xb6,0xb4,0xb1,0xb2,0xb2,0xb2,0xb0,0xb0,0xaf,0xae,0xab,0xaa,0xab,0xab,0xaa,0xa9, 0xaa,0xab,0xaf,0xb0,0xb1,0xb2,0xb1,0xb4,0xb5,0xb7,0xb7,0xb9,0xb7,0xb6,0xb5,0xb6, 0xb5,0xb5,0xb4,0xb2,0xaf,0xad,0xab,0xaa,0xa9,0xaa,0xa7,0xa9,0xa9,0xa9,0xac,0xac, 0xae,0xb0,0xb0,0xb1,0xb4,0xb3,0xb5,0xb5,0xb7,0xb5,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1, 0xaf,0xaf,0xad,0xae,0xab,0xaa,0xa9,0xa8,0xa9,0xaa,0xab,0xac,0xae,0xad,0xaf,0xaf, 0xb3,0xb4,0xb4,0xb6,0xb4,0xb3,0xb3,0xb5,0xb5,0xb3,0xb2,0xb0,0xad,0xac,0xad,0xab, 0xab,0xaa,0xa9,0xa8,0xaa,0xaa,0xa9,0xac,0xac,0xac,0xac,0xae,0xb0,0xb2,0xb1,0xb4, 0xb3,0xb3,0xb2,0xb2,0xb2,0xb4,0xb2,0xb1,0xae,0xad,0xab,0xaa,0xa9,0xa8,0xa6,0xa8, 0xa9,0xaa,0xa9,0xa9,0xaa,0xad,0xae,0xb0,0xb1,0xb4,0xb3,0xb5,0xb4,0xb5,0xb5,0xb5, 0xb3,0xb3,0xb2,0xb1,0xb0,0xaf,0xae,0xab,0xab,0xa8,0xa9,0xa7,0xaa,0xa8,0xa8,0xa8, 0xaa,0xac,0xae,0xaf,0xaf,0xaf,0xb0,0xb1,0xb3,0xb4,0xb3,0xb4,0xb1,0xaf,0xaf,0xae, 0xac,0xab,0xaa,0xa9,0xa7,0xa6,0xa6,0xa3,0xa5,0xa4,0xa5,0xa7,0xa7,0xaa,0xac,0xad, 0xaf,0xb0,0xaf,0xb1,0xb2,0xb4,0xb3,0xb1,0xb2,0xb0,0xaf,0xb0,0xaf,0xab,0xab,0xa9, 0xa8,0xa7,0xa6,0xa6,0xa6,0xa5,0xa6,0xa6,0xa6,0xa7,0xaa,0xab,0xac,0xaf,0xb1,0xb2, 0xb1,0xb1,0xb0,0xb1,0xb1,0xb2,0xb1,0xb0,0xad,0xac,0xa8,0xa8,0xa7,0xa7,0xa6,0xa6, 0xa4,0xa3,0xa3,0xa4,0xa4,0xa8,0xa7,0xa9,0xab,0xac,0xad,0xae,0xb0,0xb0,0xb0,0xae, 0xaf,0xaf,0xb0,0xaf,0xaf,0xad,0xa8,0xa8,0xa8,0xa7,0xa7,0xa7,0xa4,0xa2,0xa5,0xa3, 0xa5,0xa6,0xa7,0xa9,0xac,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb2,0xb0,0xaf,0xaf, 0xac,0xab,0xaa,0xa9,0xa7,0xa7,0xa5,0xa3,0xa5,0xa5,0xa3,0xa3,0xa4,0xa5,0xa6,0xa6, 0xaa,0xaa,0xab,0xab,0xa9,0xaa,0xab,0xad,0xae,0xae,0xad,0xac,0xaa,0xaa,0xab,0xa9, 0xa8,0xa6,0xa5,0xa6,0xa4,0xa3,0xa3,0xa4,0xa5,0xa8,0xaa,0xa8,0xaa,0xab,0xac,0xac, 0xaf,0xaf,0xae,0xae,0xb0,0xaf,0xb0,0xaf,0xad,0xae,0xaa,0xa9,0xa8,0xa8,0xa6,0xa4, 0xa3,0xa2,0xa3,0xa2,0xa3,0xa3,0xa4,0xa5,0xa5,0xa8,0xa9,0xaa,0xac,0xac,0xac,0xad, 0xad,0xad,0xad,0xac,0xab,0xab,0xaa,0xa8,0xa8,0xa5,0xa3,0xa3,0xa2,0xa1,0xa0,0x9f, 0xa2,0xa3,0xa2,0xa4,0xa5,0xa7,0xa9,0xaa,0xad,0xad,0xad,0xae,0xaf,0xaf,0xaf,0xaf, 0xad,0xac,0xaa,0xa9,0xa7,0xa5,0xa5,0xa4,0xa3,0xa3,0xa3,0xa2,0xa2,0xa3,0xa4,0xa4, 0xa6,0xa7,0xa8,0xaa,0xab,0xab,0xab,0xab,0xac,0xad,0xac,0xab,0xab,0xa9,0xa8,0xa6, 0xa6,0xa4,0xa3,0xa2,0xa1,0xa0,0x9f,0x9f,0xa1,0xa1,0xa1,0xa2,0xa4,0xa5,0xa6,0xa7, 0xaa,0xaa,0xac,0xab,0xac,0xad,0xad,0xac,0xac,0xa9,0xab,0xa8,0xa7,0xa6,0xa3,0xa2, 0xa2,0xa2,0xa0,0x9f,0xa0,0xa1,0xa2,0xa3,0xa5,0xa5,0xa4,0xa5,0xa8,0xab,0xab,0xab, 0xaa,0xaa,0xaa,0xaa,0xab,0xab,0xaa,0xa7,0xa7,0xa5,0xa6,0xa4,0xa3,0xa2,0xa2,0xa2, 0x9f,0xa0,0xa1,0x9f,0xa1,0xa2,0xa4,0xa6,0xa6,0xa5,0xa6,0xa8,0xab,0xab,0xab,0xa9, 0xa7,0xa7,0xa7,0xa9,0xa6,0xa5,0xa3,0xa1,0xa1,0x9f,0x9e,0x9e,0x9f,0x9f,0x9f,0x9f, 0xa0,0xa2,0xa4,0xa6,0xa7,0xa8,0xaa,0xaa,0xab,0xab,0xac,0xac,0xab,0xa9,0xa8,0xa8, 0xa8,0xa5,0xa5,0xa3,0xa1,0xa2,0xa1,0x9f,0xa0,0xa1,0xa0,0xa0,0xa1,0xa2,0xa4,0xa4, 0xa7,0xa9,0xa9,0xaa,0xab,0xab,0xab,0xaa,0xaa,0xa9,0xa9,0xa8,0xa7,0xa4,0xa4,0xa4, 0xa3,0xa1,0xa1,0xa0,0x9f,0x9e,0x9f,0xa1,0xa2,0xa2,0xa3,0xa5,0xa3,0xa6,0xa0,0xae, 0xb0,0xb1,0xb0,0xb0,0xaf,0xad,0xad,0xac,0xaa,0xa7,0xa7,0xa7,0xa6,0xa4,0xa2,0xa2, 0xa4,0xa4,0xa5,0xa5,0xa6,0xa8,0xa9,0xab,0xac,0xac,0xae,0xae,0xae,0xae,0xae,0xae, 0xaf,0xab,0xab,0xaa,0xa9,0xa8,0xa7,0xa6,0xa3,0xa3,0xa3,0xa3,0xa4,0xa4,0xa4,0xa6, 0xa6,0xa8,0xa8,0xab,0xac,0xb0,0xae,0xae,0xae,0xb0,0xb0,0xb2,0xb0,0xaf,0xad,0xab, 0xab,0xaa,0xa8,0xa6,0xa5,0xa5,0xa3,0xa3,0xa2,0xa3,0xa2,0xa4,0xa4,0xa8,0xa7,0xa7, 0xaa,0xac,0xac,0xaf,0xb0,0xb1,0xaf,0xaf,0xae,0xaf,0xaf,0xad,0xab,0xaa,0xa8,0xa6, 0xa5,0xa5,0xa3,0xa3,0xa4,0xa3,0xa2,0xa3,0xa4,0xa5,0xa6,0xa8,0xa9,0xaa,0xac,0xad, 0xac,0xad,0xae,0xad,0xac,0xae,0xad,0xab,0xa9,0xa9,0xa7,0xa7,0xa4,0xa2,0xa0,0x9f, 0x9e,0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa5,0xa7,0xa8,0xab,0xad,0xad,0xad,0xac,0xac, 0xac,0xab,0xab,0xab,0xab,0xa9,0xa6,0xa6,0xa5,0xa4,0xa3,0xa1,0xa2,0xa3,0xa4,0xa4, 0xa4,0xa6,0xa5,0xa7,0xaa,0xab,0xaa,0xab,0xac,0xad,0xad,0xad,0xab,0xac,0xaa,0xaa, 0xa7,0xa8,0xa4,0xa6,0xa3,0xa4,0xa2,0xa2,0xa1,0xa1,0xa1,0xa3,0xa3,0xa5,0xa4,0xa8, 0xa7,0xa7,0xa8,0xac,0xac,0xac,0xac,0xaa,0xac,0xab,0xab,0xaa,0xa8,0xa9,0xa6,0xa4, 0xa4,0xa5,0xa1,0xa2,0x9f,0xa0,0xa0,0xa1,0xa1,0xa2,0xa1,0xa2,0xa3,0xa6,0xa9,0xaa, 0xa2,0xa1,0x9c,0x9e,0xa5,0xa9,0xa7,0xa0,0x98,0x96,0x98,0x9f,0xa1,0xa1,0x9c,0x99, 0x9a,0x9e,0x9f,0x9f,0xa2,0xa2,0xa2,0xa4,0xa4,0xa5,0xa8,0xa8,0xa9,0xaa,0xaa,0xaa, 0xaa,0xaa,0xab,0xa9,0xa9,0xa7,0xa5,0xa5,0xa2,0xa2,0x9f,0x9e,0x9d,0x9d,0x9c,0x9e, 0x9e,0x9e,0xa0,0xa1,0xa1,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa7,0xa8,0xa8,0xa7,0xa7, 0xa6,0xa6,0xa3,0xa4,0xa1,0xa0,0x9e,0x9c,0x9c,0x9b,0x9a,0x9b,0x9d,0x9e,0x9e,0x9e, 0x9f,0xa1,0xa4,0xa5,0xa8,0xa8,0xa7,0xa8,0xa8,0xa9,0xa8,0xa7,0xa8,0xa5,0xa4,0xa2, 0xa3,0xa2,0xa0,0x9d,0x9c,0x9b,0x9c,0x9b,0x9d,0x9e,0x9e,0xa0,0xa1,0xa2,0xa3,0xa4, 0xa5,0xa6,0xa8,0xa9,0xa8,0xa8,0xa7,0xa7,0xa8,0xa5,0xa5,0xa4,0xa2,0xa0,0x9f,0x9f, 0x9e,0x9e,0x9d,0x9c,0x9c,0x9e,0x9e,0x9f,0xa2,0xa3,0xa3,0xa4,0xa6,0xa8,0xa8,0xaa, 0xa7,0xa9,0xa9,0xa7,0xa9,0xa7,0xa4,0xa4,0xa2,0xa4,0xa0,0xa0,0x9d,0x9c,0x9c,0x9d, 0x9d,0x9e,0x9d,0x9f,0xa0,0xa2,0xa3,0xa3,0xa4,0xa5,0xa6,0xa9,0xaa,0xa8,0xa7,0xa6, 0xa7,0xa6,0xa6,0xa4,0xa3,0xa0,0xa1,0x9f,0xa0,0x9d,0x9d,0x9d,0x9d,0x9e,0x9f,0x9f, 0xa0,0xa1,0xa3,0xa3,0xa3,0xa5,0xa7,0xa9,0xa7,0xa7,0xa5,0xa7,0xa6,0xa4,0xa5,0xa3, 0xa2,0xa0,0x9e,0x9e,0x9e,0x9d,0x9b,0x9c,0x9c,0x9b,0x9c,0x9e,0xa0,0xa1,0x9f,0xa1, 0xa3,0xa6,0xa5,0xa6,0xa7,0xa7,0xa7,0xa9,0xa7,0xa8,0xa5,0xa6,0xa3,0xa2,0xa1,0x9f, 0x9f,0x9e,0x9e,0x9e,0x96,0x94,0x94,0x96,0x9b,0xa3,0xa1,0x9c,0x9a,0x9b,0x9f,0xa6, 0xa7,0xa8,0xa8,0xa7,0xa8,0xa6,0xa5,0xa5,0xa5,0xa2,0xa1,0x9f,0x9d,0x9e,0x9c,0x9b, 0x9b,0x9a,0x9b,0x9c,0x9e,0xa0,0x9d,0x9f,0xa1,0xa3,0xa3,0xa5,0xa6,0xa6,0xa5,0xa4, 0xa6,0xa7,0xa3,0xa2,0xa1,0xa1,0x9e,0x9e,0x9d,0x9d,0x9b,0x9a,0x99,0x9a,0x99,0x9a, 0x9c,0x9c,0x9a,0x9e,0x9f,0x9f,0xa2,0xa1,0xa0,0xa2,0xa3,0xa3,0xa3,0xa2,0xa0,0xa0, 0xa0,0x9e,0x9e,0x9c,0x9a,0x99,0x96,0x96,0x95,0x96,0x97,0x98,0x99,0x99,0x99,0x9b, 0x9c,0xa0,0xa2,0xa1,0xa1,0xa2,0xa3,0xa3,0xa3,0xa2,0xa3,0xa1,0xa1,0x9f,0x9e,0x9d, 0x9d,0x9b,0x9d,0x9b,0x9a,0x99,0x9a,0x9b,0x9c,0x9b,0x9e,0x9e,0x9f,0xa1,0xa3,0xa4, 0xa4,0xa4,0xa6,0xa6,0xa7,0xa6,0xa5,0xa5,0xa4,0xa2,0xa2,0xa1,0xa0,0x9e,0x9d,0x9b, 0x9b,0x9b,0x9c,0x9d,0x9e,0x9d,0x9f,0x9f,0xa1,0xa4,0xa4,0xa4,0xa6,0xa7,0xa6,0xa7, 0xa8,0xa7,0xa6,0xa6,0xa6,0xa3,0xa2,0xa1,0xa0,0x9f,0x9d,0x9d,0x9b,0x9b,0x9c,0x9a, 0x9a,0x9d,0x9d,0x9e,0xa0,0xa0,0xa3,0xa3,0xa5,0xa5,0xa6,0xa6,0xa5,0xa7,0xa6,0xa6, 0xa3,0xa2,0xa3,0xa1,0x9e,0x9d,0x9d,0x9a,0x9a,0x9a,0x9a,0x9a,0x9b,0x9b,0x9c,0x9d, 0x9f,0x9f,0xa1,0xa4,0xa7,0xa6,0xa6,0xa7,0xa5,0xa7,0xa6,0xa7,0xa4,0xa5,0xa2,0xa1, 0xa0,0xa0,0x9e,0x9c,0x9e,0x9c,0x9b,0x99,0x9b,0x9b,0x9d,0x9f,0x9f,0x9f,0xa1,0xa3, 0xa5,0xa5,0xa6,0xa7,0xa8,0xa7,0xa6,0xa4,0xa4,0xa3,0xa3,0xa3,0xa3,0x9f,0x9e,0x9c, 0x9c,0x9b,0x9b,0x9a,0x9b,0x9c,0x9e,0x9f,0x9f,0x9e,0xa0,0xa2,0xa3,0xa5,0xa6,0xa6, 0xa6,0xa5,0xa6,0xa6,0xa5,0xa5,0xa5,0xa3,0xa1,0x9d,0x9e,0x9d,0x9d,0x9b,0x9b,0x99, 0x9a,0x9b,0x9c,0x9c,0x9d,0x9d,0xa0,0xa2,0xa1,0xa4,0xa5,0xa5,0xa6,0xa5,0xa6,0xa6, 0xa4,0xa5,0xa5,0xa4,0xa1,0xa0,0x9d,0x9c,0x9b,0x9c,0x9c,0x9a,0x9a,0x99,0x9a,0x9b, 0x9c,0x9d,0xa0,0xa1,0xa1,0xa3,0xa3,0xa4,0xa5,0xa6,0xa6,0xa5,0xa5,0xa5,0xa3,0xa3, 0xa2,0x9f,0x9f,0x9f,0x9e,0x9d,0x9c,0x9a,0x99,0x9b,0x9b,0x9b,0x9d,0xa0,0x9e,0x9f, 0xa2,0xa3,0xa5,0xa6,0xa6,0xa4,0xa6,0xa6,0xa5,0xa6,0xa4,0xa2,0xa1,0x9f,0xa0,0x9e, 0x9d,0x9c,0x9b,0x9a,0x98,0x9a,0x9b,0x9b,0x9c,0x9c,0x9e,0x9e,0xa1,0xa1,0xa2,0xa2, 0xa4,0xa4,0xa4,0xa5,0xa4,0xa4,0xa4,0xa2,0xa3,0xa1,0x9e,0x9d,0x9b,0x9b,0x9b,0x9b, 0x99,0x99,0x97,0x98,0x99,0x9c,0x9d,0x9e,0x9f,0xa1,0xa1,0xa2,0xa5,0xa6,0xa5,0xa6, 0xa4,0xa3,0xa3,0xa2,0xa1,0xa0,0x9f,0x9d,0x9c,0x9a,0x9a,0x99,0x98,0x98,0x99,0x9a, 0x9a,0x9b,0x9c,0x9d,0xa0,0xa1,0xa1,0xa2,0xa3,0xa4,0xa4,0xa5,0xa6,0xa5,0xa3,0xa2, 0xa1,0xa1,0x9f,0x9e,0x9d,0x9b,0x99,0x98,0x9a,0x99,0x99,0x99,0x9b,0x9b,0x9c,0x9f, 0x9f,0xa2,0xa3,0xa2,0xa2,0xa1,0x9e,0xa7,0xa9,0xa8,0xa7,0xa6,0xa5,0xa3,0xa1,0xa0, 0xa0,0xa0,0x9d,0x9e,0x9d,0x9d,0x9f,0xa0,0x9f,0x9f,0xa1,0xa4,0xa5,0xa8,0xa7,0xa7, 0xa9,0xa9,0xaa,0xac,0xaa,0xaa,0xa7,0xa8,0xa7,0xa6,0xa5,0xa3,0xa1,0xa1,0x9f,0x9f, 0x9f,0x9e,0x9d,0xa0,0xa1,0xa2,0xa0,0xa1,0xa2,0xa4,0xa6,0xa9,0xa8,0xa8,0xa7,0xa8, 0xa9,0xa9,0xa7,0xa8,0xa7,0xa5,0xa4,0xa4,0xa3,0xa1,0x9f,0x9f,0x9d,0x9d,0x9c,0x9f, 0x9f,0xa1,0xa0,0xa2,0xa2,0xa5,0xa5,0xa7,0xa7,0xa9,0xa9,0xaa,0xaa,0xa9,0xa6,0xa8, 0xa6,0xa5,0xa3,0xa1,0xa0,0x9f,0x9e,0x9e,0x9c,0x9b,0x9b,0x9e,0x9e,0x9f,0xa0,0xa1, 0xa3,0xa4,0xa4,0xa7,0xa6,0xa9,0xa6,0xa9,0xa7,0xa8,0xa6,0xa6,0xa4,0xa4,0xa2,0xa1, 0x9f,0xa0,0x9d,0x9c,0x9b,0x9c,0x9b,0x9b,0x9d,0x9e,0x9e,0xa0,0x9f,0xa4,0xa4,0xa4, 0xa6,0xa7,0xa6,0xa7,0xa6,0xa8,0xa6,0xa6,0xa5,0xa4,0xa2,0xa1,0x9f,0x9f,0x9e,0x9e, 0x9b,0x9b,0x9b,0x9b,0x9b,0x9c,0x9e,0x9e,0x9f,0xa1,0xa1,0xa3,0xa5,0xa7,0xa6,0xa5, 0xa5,0xa5,0xa4,0xa4,0xa3,0xa4,0xa1,0x9f,0x9d,0x9d,0x9c,0x9c,0x9b,0x9a,0x98,0x99, 0x99,0x9b,0x9d,0x9d,0x9c,0x9f,0x9f,0xa1,0xa4,0xa4,0xa3,0xa4,0xa4,0xa5,0xa4,0xa4, 0xa3,0xa4,0x9f,0xa1,0x9e,0x9e,0x9c,0x9c,0x9a,0x99,0x99,0x9a,0x9a,0x9b,0x99,0x9c, 0x9c,0x9e,0xa1,0xa0,0xa1,0xa4,0xa4,0xa3,0xa4,0xa5,0xa4,0xa3,0xa2,0xa3,0xa3,0x9f, 0x9e,0x9c,0x9b,0x9a,0x98,0x99,0x97,0x97,0x97,0x98,0x98,0x9b,0x9b,0x9d,0x9e,0x9f, 0xa0,0xa2,0xa3,0xa4,0xa3,0xa3,0xa3,0xa3,0xa2,0xa4,0xa1,0xa0,0x9e,0x9c,0x9a,0x9a, 0x97,0x97,0x95,0x97,0x97,0x97,0x98,0x98,0x98,0x9a,0x9d,0x9e,0x9f,0xa2,0xa2,0xa2, 0xa2,0xa2,0xa1,0xa3,0xa2,0xa1,0xa0,0xa0,0x9e,0x9d,0x9b,0x9b,0x9a,0x98,0x98,0x97, 0x98,0x9a,0x98,0x9a,0x9c,0x9e,0x9c,0x9f,0x9f,0xa1,0xa2,0xa4,0xa3,0xa3,0xa1,0xa3, 0xa3,0xa3,0xa2,0xa1,0x9e,0x9d,0x9d,0x9c,0x9b,0x99,0x97,0x97,0x97,0x99,0x99,0x9a, 0x99,0x9c,0x9c,0x9e,0x9e,0xa0,0xa1,0xa3,0xa2,0xa2,0xa3,0xa3,0xa2,0xa4,0xa1,0x9f, 0x9e,0x9e,0x9b,0x9c,0x98,0x98,0x97,0x96,0x96,0x98,0x97,0x97,0x98,0x9b,0x9a,0x9c, 0x9e,0xa0,0xa0,0xa0,0xa2,0xa1,0xa1,0xa1,0xa2,0xa2,0x9f,0x9f,0x9f,0x9c,0x9b,0x9b, 0x9a,0x98,0x97,0x97,0x96,0x95,0x96,0x96,0x98,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0, 0xa1,0xa1,0xa1,0xa2,0xa0,0xa0,0xa0,0xa2,0x9f,0x9c,0x9b,0x9a,0x9a,0x97,0x98,0x95, 0x95,0x95,0x96,0x97,0x95,0x96,0x97,0x97,0x9a,0x9c,0x9d,0x9e,0x9e,0x9e,0x9f,0xa1, 0xa0,0xa0,0xa0,0x9f,0x9d,0x9c,0x9a,0x9a,0x99,0x97,0x97,0x94,0x96,0x95,0x95,0x96, 0x97,0x97,0x99,0x98,0x9b,0x9c,0x9c,0x9e,0x9f,0xa0,0xa1,0xa0,0xa0,0xa0,0xa0,0x9f, 0x9e,0x9d,0x9d,0x99,0x99,0x99,0x98,0x95,0x97,0x96,0x94,0x96,0x95,0x97,0x98,0x9a, 0x9a,0x9c,0x9d,0x9d,0x9e,0xa0,0xa0,0x9f,0xa1,0xa0,0x9e,0x9f,0x9f,0x9e,0x9b,0x9a, 0x98,0x98,0x98,0x97,0x93,0x93,0x94,0x94,0x95,0x96,0x98,0x98,0x9a,0x9c,0x9d,0x9c, 0x9d,0x9e,0x9e,0xa0,0x9f,0x9f,0x9e,0x9d,0x9d,0x9e,0x9b,0x9b,0x99,0x97,0x96,0x96, 0x95,0x96,0x96,0x95,0x95,0x95,0x97,0x98,0x99,0x9b,0x9c,0x9e,0x9f,0x9e,0xa0,0xa1, 0xa0,0xa0,0x9f,0x9f,0x9d,0x9d,0x9c,0x9c,0x99,0x99,0x96,0x95,0x94,0x95,0x93,0x93, 0x92,0x94,0x96,0x96,0x97,0x96,0x97,0x9b,0x9c,0x9d,0x9d,0x9d,0x9d,0x9e,0x9d,0x9e, 0x9c,0x9b,0x9a,0x9a,0x98,0x98,0x96,0x96,0x93,0x93,0x92,0x94,0x93,0x94,0x94,0x95, 0x96,0x97,0x96,0x99,0x9b,0x9b,0x9b,0x9c,0x9c,0x9b,0x9b,0x9d,0x9c,0x9b,0x9a,0x99, 0x96,0x95,0x94,0x94,0x93,0x93,0x91,0x91,0x93,0x92,0x92,0x93,0x93,0x93,0x95,0x97, 0x99,0x99,0x99,0x99,0x99,0x9b,0x9c,0x9c,0x9b,0x98,0x98,0x96,0x97,0x97,0x94,0x93, 0x92,0x90,0x8f,0x8e,0x8f,0x8f,0x90,0x91,0x92,0x92,0x95,0x96,0x98,0x97,0x98,0x9a, 0x99,0x99,0x99,0x9a,0x99,0x97,0x97,0x97,0x95,0x95,0x92,0x8f,0x8e,0x8f,0x8e,0x8c, 0x8f,0x8e,0x8d,0x90,0x91,0x92,0x94,0x96,0x97,0x98,0x97,0x99,0x99,0x98,0x99,0x99, 0x99,0x99,0x98,0x96,0x97,0x93,0x92,0x92,0x91,0x8f,0x8e,0x8c,0x8d,0x8d,0x8e,0x90, 0x90,0x90,0x91,0x93,0x94,0x96,0x96,0x98,0x98,0x99,0x99,0x9a,0x99,0x9a,0x98,0x98, 0x96,0x95,0x93,0x93,0x91,0x90,0x8f,0x8d,0x8c,0x8d,0x8e,0x90,0x90,0x8f,0x90,0x91, 0x93,0x96,0x96,0x97,0x97,0x98,0x97,0x97,0x97,0x98,0x97,0x95,0x93,0x93,0x93,0x92, 0x91,0x90,0x8e,0x8e,0x8e,0x8c,0x8d,0x8e,0x8e,0x90,0x8e,0x8f,0x91,0x93,0x93,0x94, 0x94,0x95,0x95,0x96,0x95,0x95,0x95,0x95,0x94,0x93,0x90,0x90,0x90,0x8f,0x8d,0x8d, 0x8b,0x8c,0x8b,0x8b,0x8d,0x8c,0x8d,0x8e,0x8f,0x90,0x92,0x91,0x93,0x93,0x95,0x95, 0x95,0x94,0x95,0x93,0x92,0x91,0x91,0x8e,0x8e,0x8d,0x8b,0x8b,0x8a,0x8a,0x89,0x89, 0x89,0x89,0x8a,0x8b,0x8c,0x8c,0x8f,0x91,0x90,0x92,0x92,0x92,0x92,0x93,0x92,0x92, 0x91,0x90,0x8f,0x8f,0x8b,0x8c,0x8a,0x89,0x88,0x87,0x85,0x86,0x85,0x88,0x88,0x88, 0x89,0x8c,0x8d,0x8e,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,0x91,0x91,0x91,0x8f,0x8f, 0x8c,0x8d,0x8a,0x8b,0x8a,0x86,0x86,0x86,0x85,0x86,0x87,0x89,0x8a,0x8b,0x8a,0x8c, 0x8e,0x90,0x90,0x92,0x90,0x90,0x92,0x93,0x90,0x91,0x90,0x90,0x8d,0x8d,0x8c,0x8a, 0x8a,0x89,0x87,0x88,0x87,0x89,0x87,0x8a,0x8a,0x8b,0x8c,0x8e,0x8d,0x90,0x8f,0x91, 0x92,0x92,0x92,0x92,0x91,0x92,0x90,0x90,0x8e,0x8f,0x8c,0x8c,0x8b,0x8b,0x89,0x88, 0x89,0x88,0x89,0x8a,0x8c,0x8b,0x8e,0x8d,0x90,0x90,0x92,0x91,0x91,0x8f,0x8b,0x6f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf6,0x01,0x17,0x0f,0xd0,0x10,0x08,0x01, 0xb8,0xa1,0x34,0x01,0x78,0x01,0x34,0x01,0x42,0x46,0x41,0x45,0x43,0x48,0x43,0x48, 0x3d,0x44,0x40,0x44,0x41,0x49,0x3e,0x4d,0x43,0x44,0x3f,0x44,0x3e,0x47,0x41,0x49, 0x3f,0x44,0x3d,0x46,0x42,0x45,0x40,0x47,0x40,0x47,0x3f,0x44,0x3e,0x47,0x40,0x4a, 0x3d,0x49,0x3d,0x45,0x3f,0x4a,0x3f,0x49,0x3c,0x44,0x3f,0x42,0x3f,0x46,0x3f,0x49, 0x3f,0x47,0x3e,0x43,0x40,0x46,0x3e,0x49,0x3e,0x45,0x3e,0x4a,0x40,0x47,0x3d,0x48, 0x41,0x47,0x3e,0x45,0x3e,0x46,0x3e,0x45,0x42,0x46,0x3e,0x44,0x41,0x47,0x41,0x47, 0x3f,0x44,0x3d,0x44,0x3f,0x47,0x3a,0x48,0x40,0x46,0x3e,0x45,0x3f,0x48,0x3e,0x49, 0x41,0x45,0x3d,0x48,0x3d,0x47,0x41,0x4c,0x3f,0x43,0x41,0x45,0x41,0x47,0x3f,0x46, 0x42,0x44,0x3f,0x44,0x3f,0x47,0x3e,0x44,0x41,0x47,0x41,0x47,0x42,0x46,0x3c,0x47, 0x41,0x45,0x3e,0x44,0x40,0x45,0x3f,0x47,0x3d,0x45,0x3b,0x44,0x3f,0x42,0x3c,0x48, 0x41,0x46,0x3c,0x45,0x3d,0x49,0x3d,0x48,0x40,0x48,0x40,0x44,0x41,0x47,0x3d,0x47, 0x3d,0x41,0x3f,0x49,0x3f,0x48,0x3c,0x45,0x3d,0x44,0x3e,0x46,0x3e,0x47,0x3f,0x48, 0x3f,0x43,0x41,0x44,0x40,0x49,0x3d,0x47,0x3e,0x47,0x3e,0x46,0x40,0x44,0x40,0x48, 0x41,0x49,0x3e,0x43,0x40,0x44,0x3d,0x46,0x3e,0x47,0x41,0x42,0x40,0x48,0x3f,0x4a, 0x40,0x44,0x3e,0x45,0x3d,0x48,0x3f,0x46,0x3f,0x45,0x41,0x43,0x40,0x46,0x3d,0x47, 0x3e,0x46,0x3d,0x47,0x42,0x47,0x3e,0x44,0x3e,0x43,0x3e,0x44,0x41,0x47,0x3f,0x46, 0x40,0x41,0x3f,0x44,0x3f,0x48,0x3d,0x49,0x3d,0x43,0x3d,0x44,0x40,0x45,0x3e,0x47, 0x40,0x46,0x3c,0x46,0x40,0x46,0x3f,0x48,0x41,0x45,0x3f,0x46,0x43,0x45,0x3a,0x46, 0x3f,0x49,0x3c,0x43,0x40,0x44,0x3d,0x46,0x3e,0x48,0x3d,0x45,0x41,0x45,0x3b,0x49, 0x3f,0x44,0x40,0x4a,0x40,0x47,0x3e,0x4b,0x3d,0x44,0x40,0x43,0x3e,0x4b,0x3b,0x47, 0x40,0x47,0x3c,0x46,0x3f,0x49,0x3c,0x48,0x3e,0x44,0x3a,0x44,0x3f,0x47,0x3f,0x49, 0x3d,0x44,0x3e,0x47,0x3c,0x47,0x3a,0x46,0x3f,0x42,0x40,0x44,0x3e,0x46,0x3b,0x43, 0x3f,0x44,0x3d,0x44,0x40,0x48,0x3d,0x49,0x3c,0x43,0x3c,0x43,0x41,0x44,0x3e,0x49, 0x3f,0x41,0x3e,0x41,0x3d,0x44,0x3f,0x48,0x42,0x44,0x3d,0x44,0x40,0x45,0x3e,0x44, 0x3f,0x43,0x3d,0x44,0x3b,0x43,0x3e,0x47,0x41,0x48,0x3c,0x44,0x3e,0x47,0x3e,0x45, 0x3d,0x45,0x3d,0x41,0x3d,0x44,0x3d,0x44,0x3d,0x43,0x3d,0x45,0x3f,0x44,0x3b,0x47, 0x3e,0x42,0x3c,0x45,0x3f,0x44,0x39,0x4a,0x3d,0x42,0x3c,0x46,0x3f,0x45,0x3a,0x44, 0x3e,0x45,0x39,0x44,0x3d,0x45,0x3e,0x48,0x3d,0x42,0x3e,0x44,0x3f,0x43,0x3b,0x48, 0x3f,0x43,0x3b,0x44,0x3f,0x46,0x3b,0x44,0x3f,0x41,0x3e,0x43,0x40,0x46,0x3c,0x45, 0x3d,0x47,0x3e,0x44,0x3f,0x49,0x3e,0x48,0x3e,0x45,0x3d,0x46,0x3f,0x46,0x3d,0x47, 0x3e,0x46,0x3b,0x47,0x41,0x46,0x3b,0x48,0x3f,0x47,0x40,0x45,0x3e,0x47,0x40,0x48, 0x3f,0x43,0x3d,0x48,0x3e,0x44,0x3d,0x46,0x3b,0x43,0x3e,0x47,0x3c,0x45,0x3c,0x47, 0x3c,0x47,0x3e,0x45,0x3e,0x45,0x3f,0x45,0x39,0x45,0x3c,0x47,0x3e,0x45,0x3e,0x47, 0x3d,0x46,0x3e,0x47,0x3f,0x45,0x3a,0x49,0x3b,0x43,0x3e,0x45,0x3f,0x46,0x3d,0x43, 0x3d,0x44,0x3d,0x42,0x41,0x46,0x3d,0x44,0x41,0x44,0x3d,0x44,0x40,0x45,0x3c,0x45, 0x3d,0x45,0x3d,0x45,0x3c,0x45,0x3e,0x48,0x3e,0x43,0x3d,0x45,0x3f,0x46,0x3e,0x46, 0x3c,0x45,0x3e,0x49,0x3c,0x43,0x3a,0x44,0x3e,0x46,0x40,0x48,0x3f,0x45,0x3c,0x47, 0x3d,0x47,0x3e,0x47,0x40,0x41,0x3e,0x47,0x3c,0x44,0x3e,0x41,0x3c,0x45,0x3d,0x45, 0x3c,0x43,0x3f,0x46,0x40,0x42,0x3d,0x45,0x3f,0x45,0x3b,0x46,0x3c,0x46,0x3d,0x47, 0x3d,0x43,0x3c,0x46,0x3d,0x43,0x3d,0x44,0x3f,0x43,0x3d,0x45,0x3e,0x45,0x3b,0x49, 0x3e,0x46,0x3e,0x46,0x3e,0x44,0x3e,0x47,0x3e,0x45,0x3d,0x44,0x3e,0x43,0x3d,0x44, 0x3e,0x44,0x3c,0x46,0x3c,0x44,0x3c,0x49,0x3d,0x41,0x3e,0x47,0x3d,0x43,0x3b,0x46, 0x3a,0x44,0x3b,0x46,0x3f,0x43,0x3e,0x48,0x3b,0x43,0x3b,0x46,0x40,0x42,0x3b,0x46, 0x3d,0x42,0x3f,0x45,0x3e,0x45,0x41,0x44,0x41,0x43,0x3a,0x46,0x3d,0x46,0x40,0x46, 0x3c,0x42,0x3e,0x47,0x3f,0x45,0x3d,0x44,0x3d,0x44,0x38,0x42,0x3d,0x42,0x3d,0x45, 0x3d,0x46,0x3f,0x44,0x3e,0x44,0x3b,0x43,0x3c,0x47,0x3d,0x46,0x3e,0x40,0x3c,0x45, 0x3c,0x43,0x3d,0x43,0x42,0x43,0x39,0x45,0x3d,0x47,0x3d,0x44,0x3e,0x44,0x3e,0x48, 0x3d,0x43,0x3d,0x46,0x3c,0x46,0x3d,0x45,0x39,0x43,0x3d,0x42,0x3e,0x45,0x3a,0x45, 0x3a,0x44,0x3b,0x43,0x3e,0x44,0x3c,0x45,0x40,0x44,0x3e,0x45,0x3f,0x3f,0x3d,0x46, 0x3e,0x44,0x3c,0x45,0x3b,0x44,0x3d,0x43,0x3e,0x42,0x3f,0x44,0x40,0x47,0x3c,0x44, 0x3e,0x44,0x3b,0x45,0x3c,0x47,0x3b,0x41,0x3b,0x43,0x3b,0x44,0x3e,0x43,0x3d,0x42, 0x3c,0x44,0x3d,0x43,0x39,0x43,0x3c,0x47,0x3e,0x44,0x3d,0x46,0x3f,0x45,0x3c,0x41, 0x38,0x48,0x3c,0x44,0x3c,0x46,0x3d,0x44,0x3b,0x44,0x3b,0x44,0x3c,0x47,0x3b,0x44, 0x3e,0x43,0x3c,0x43,0x3c,0x45,0x3b,0x46,0x3f,0x45,0x3a,0x43,0x43,0x44,0x3a,0x46, 0x3e,0x44,0x3d,0x44,0x3c,0x41,0x3e,0x42,0x3d,0x44,0x3b,0x43,0x3e,0x43,0x3e,0x40, 0x3e,0x44,0x3b,0x46,0x3d,0x42,0x3b,0x41,0x3f,0x42,0x3b,0x45,0x3d,0x42,0x39,0x47, 0x3c,0x44,0x3e,0x46,0x3e,0x43,0x3b,0x46,0x3b,0x43,0x3d,0x43,0x3c,0x42,0x3a,0x45, 0x3d,0x45,0x39,0x45,0x3d,0x43,0x3d,0x44,0x40,0x43,0x3d,0x46,0x40,0x46,0x3a,0x3b, 0x35,0x3e,0x3c,0x46,0x3d,0x43,0x43,0x48,0x42,0x47,0x46,0x50,0x4a,0x4c,0x40,0x4a, 0x43,0x46,0x3f,0x4a,0x43,0x48,0x41,0x48,0x41,0x46,0x44,0x47,0x42,0x4a,0x43,0x4a, 0x43,0x48,0x41,0x46,0x41,0x47,0x41,0x47,0x44,0x44,0x42,0x47,0x42,0x46,0x3f,0x46, 0x41,0x47,0x43,0x48,0x42,0x48,0x43,0x49,0x41,0x48,0x41,0x48,0x45,0x43,0x40,0x47, 0x43,0x47,0x41,0x48,0x43,0x49,0x41,0x4a,0x41,0x49,0x41,0x47,0x3f,0x44,0x41,0x4a, 0x43,0x42,0x3f,0x48,0x41,0x47,0x42,0x4b,0x41,0x46,0x41,0x45,0x40,0x49,0x3f,0x48, 0x42,0x49,0x3e,0x4a,0x41,0x45,0x40,0x49,0x40,0x48,0x3e,0x48,0x40,0x45,0x41,0x46, 0x43,0x49,0x3f,0x48,0x3d,0x48,0x41,0x4a,0x43,0x47,0x3f,0x48,0x3f,0x46,0x40,0x4a, 0x40,0x48,0x3e,0x49,0x42,0x46,0x41,0x49,0x40,0x46,0x3f,0x47,0x42,0x4a,0x40,0x45, 0x41,0x45,0x41,0x47,0x41,0x48,0x41,0x4a,0x3e,0x49,0x3e,0x49,0x42,0x48,0x3f,0x48, 0x42,0x49,0x42,0x48,0x42,0x46,0x3f,0x48,0x42,0x48,0x43,0x49,0x42,0x49,0x40,0x4a, 0x44,0x45,0x3e,0x48,0x41,0x49,0x41,0x48,0x42,0x45,0x41,0x47,0x41,0x45,0x41,0x45, 0x40,0x48,0x3e,0x48,0x41,0x47,0x3d,0x4c,0x42,0x47,0x40,0x49,0x41,0x48,0x3f,0x4a, 0x42,0x48,0x3c,0x4c,0x43,0x45,0x3c,0x47,0x44,0x48,0x3d,0x48,0x3d,0x48,0x3e,0x49, 0x41,0x45,0x40,0x48,0x42,0x4a,0x42,0x4d,0x44,0x44,0x40,0x48,0x43,0x46,0x3f,0x4a, 0x42,0x46,0x42,0x46,0x43,0x49,0x3e,0x48,0x41,0x49,0x40,0x4c,0x43,0x45,0x41,0x47, 0x46,0x46,0x43,0x46,0x42,0x47,0x3e,0x48,0x43,0x48,0x41,0x46,0x42,0x48,0x3e,0x4b, 0x43,0x49,0x3f,0x46,0x42,0x47,0x40,0x49,0x43,0x44,0x41,0x47,0x3d,0x47,0x3e,0x4a, 0x3e,0x48,0x41,0x4b,0x42,0x44,0x40,0x4c,0x3f,0x46,0x42,0x48,0x42,0x49,0x40,0x47, 0x44,0x47,0x40,0x48,0x40,0x49,0x41,0x49,0x3f,0x49,0x40,0x46,0x41,0x4b,0x3f,0x46, 0x41,0x48,0x41,0x48,0x41,0x47,0x3c,0x48,0x45,0x45,0x3d,0x46,0x44,0x47,0x42,0x4b, 0x44,0x4a,0x40,0x48,0x42,0x47,0x42,0x4a,0x3f,0x48,0x3f,0x47,0x42,0x48,0x3c,0x4a, 0x3e,0x45,0x3f,0x48,0x46,0x49,0x3f,0x49,0x42,0x44,0x40,0x48,0x42,0x46,0x42,0x45, 0x3e,0x45,0x3f,0x4c,0x40,0x46,0x41,0x48,0x42,0x4a,0x44,0x49,0x3d,0x48,0x3f,0x48, 0x40,0x47,0x3f,0x47,0x3f,0x47,0x43,0x4a,0x42,0x49,0x41,0x44,0x42,0x49,0x3f,0x49, 0x42,0x46,0x42,0x46,0x41,0x47,0x43,0x4c,0x44,0x47,0x43,0x49,0x41,0x49,0x41,0x49, 0x41,0x45,0x41,0x46,0x44,0x45,0x41,0x47,0x40,0x47,0x3f,0x48,0x45,0x49,0x3e,0x47, 0x42,0x46,0x42,0x47,0x44,0x48,0x40,0x4b,0x43,0x47,0x40,0x49,0x42,0x49,0x42,0x45, 0x43,0x44,0x41,0x48,0x40,0x46,0x42,0x49,0x42,0x46,0x41,0x4c,0x43,0x47,0x41,0x4a, 0x43,0x46,0x40,0x47,0x42,0x47,0x3d,0x49,0x40,0x48,0x40,0x47,0x45,0x49,0x3e,0x47, 0x44,0x48,0x42,0x4b,0x44,0x4b,0x40,0x4b,0x41,0x4b,0x40,0x49,0x40,0x47,0x43,0x49, 0x42,0x47,0x42,0x4a,0x43,0x48,0x3f,0x4a,0x43,0x48,0x3f,0x4b,0x44,0x4a,0x40,0x48, 0x43,0x47,0x42,0x47,0x45,0x4a,0x42,0x4c,0x43,0x47,0x41,0x46,0x45,0x4d,0x41,0x49, 0x41,0x49,0x43,0x49,0x44,0x4a,0x42,0x4a,0x40,0x49,0x3e,0x49,0x44,0x4c,0x42,0x4a, 0x44,0x47,0x40,0x4a,0x42,0x49,0x43,0x4f,0x41,0x49,0x42,0x49,0x44,0x49,0x42,0x48, 0x46,0x48,0x40,0x4a,0x41,0x48,0x41,0x4b,0x43,0x45,0x3f,0x4a,0x3e,0x4b,0x3e,0x4b, 0x44,0x48,0x42,0x48,0x44,0x47,0x43,0x48,0x43,0x4b,0x40,0x49,0x45,0x47,0x42,0x4a, 0x45,0x45,0x40,0x45,0x42,0x4a,0x3f,0x48,0x42,0x48,0x43,0x48,0x41,0x4a,0x3d,0x4a, 0x40,0x48,0x3f,0x44,0x43,0x4c,0x42,0x47,0x43,0x47,0x42,0x49,0x41,0x4a,0x3e,0x4a, 0x40,0x48,0x43,0x46,0x40,0x49,0x42,0x49,0x43,0x47,0x42,0x48,0x42,0x4c,0x3f,0x4a, 0x41,0x49,0x3f,0x46,0x3f,0x48,0x42,0x4b,0x44,0x48,0x44,0x48,0x43,0x48,0x41,0x4a, 0x42,0x45,0x40,0x48,0x43,0x4a,0x42,0x4b,0x40,0x49,0x41,0x47,0x42,0x4b,0x41,0x48, 0x42,0x48,0x3d,0x4a,0x41,0x48,0x42,0x48,0x41,0x45,0x43,0x48,0x43,0x4a,0x40,0x4a, 0x44,0x49,0x43,0x48,0x40,0x4c,0x40,0x4c,0x43,0x46,0x42,0x4a,0x46,0x48,0x41,0x47, 0x42,0x48,0x41,0x49,0x44,0x47,0x41,0x49,0x42,0x4b,0x42,0x45,0x41,0x49,0x3f,0x49, 0x43,0x47,0x3e,0x4a,0x43,0x46,0x42,0x4b,0x44,0x46,0x42,0x48,0x42,0x47,0x3e,0x4a, 0x40,0x4a,0x40,0x47,0x42,0x4c,0x43,0x47,0x43,0x47,0x40,0x47,0x43,0x48,0x40,0x48, 0x45,0x49,0x42,0x47,0x41,0x47,0x41,0x49,0x43,0x49,0x3f,0x48,0x41,0x4a,0x3c,0x4a, 0x40,0x49,0x3e,0x46,0x40,0x47,0x42,0x4c,0x40,0x46,0x41,0x47,0x42,0x4a,0x40,0x4e, 0x44,0x47,0x41,0x47,0x42,0x48,0x42,0x4b,0x42,0x44,0x40,0x46,0x43,0x47,0x41,0x4a, 0x41,0x49,0x3f,0x4a,0x41,0x49,0x43,0x4b,0x40,0x4a,0x41,0x46,0x42,0x47,0x41,0x47, 0x42,0x49,0x44,0x4a,0x3e,0x4a,0x40,0x49,0x41,0x44,0x41,0x49,0x42,0x4a,0x42,0x4b, 0x41,0x46,0x40,0x44,0x42,0x49,0x40,0x48,0x41,0x47,0x3e,0x48,0x41,0x49,0x44,0x48, 0x3f,0x49,0x45,0x49,0x44,0x49,0x42,0x4d,0x41,0x48,0x40,0x48,0x40,0x48,0x40,0x4b, 0x43,0x48,0x41,0x46,0x41,0x47,0x3f,0x4b,0x44,0x48,0x42,0x45,0x42,0x4b,0x42,0x4a, 0x43,0x47,0x3e,0x45,0x44,0x49,0x45,0x49,0x40,0x49,0x3f,0x48,0x3f,0x47,0x40,0x48, 0x42,0x4c,0x40,0x47,0x42,0x46,0x42,0x49,0x43,0x44,0x41,0x47,0x45,0x48,0x42,0x48, 0x40,0x46,0x3f,0x48,0x45,0x4a,0x40,0x4c,0x42,0x4a,0x42,0x49,0x42,0x4a,0x40,0x4b, 0x42,0x49,0x3e,0x47,0x45,0x4c,0x3b,0x42,0x3b,0x42,0x41,0x46,0x47,0x47,0x47,0x44, 0x40,0x45,0x42,0x4d,0x42,0x4d,0x42,0x49,0x43,0x46,0x3f,0x43,0x3f,0x45,0x40,0x47, 0x3e,0x43,0x3f,0x45,0x40,0x49,0x3e,0x48,0x3f,0x48,0x42,0x45,0x42,0x48,0x3d,0x4c, 0x41,0x46,0x3d,0x47,0x3f,0x46,0x3f,0x46,0x42,0x42,0x3e,0x45,0x3f,0x49,0x3e,0x47, 0x3f,0x4a,0x3d,0x46,0x3e,0x45,0x3e,0x48,0x41,0x45,0x3f,0x45,0x41,0x48,0x3e,0x4a, 0x41,0x47,0x3e,0x48,0x42,0x4a,0x3e,0x47,0x41,0x44,0x42,0x44,0x43,0x47,0x3f,0x47, 0x40,0x49,0x3f,0x45,0x42,0x48,0x3e,0x48,0x41,0x45,0x3f,0x48,0x41,0x48,0x3b,0x4a, 0x41,0x45,0x42,0x42,0x40,0x44,0x40,0x4a,0x3e,0x47,0x40,0x43,0x3f,0x48,0x3c,0x45, 0x41,0x48,0x40,0x46,0x3f,0x47,0x40,0x47,0x40,0x44,0x3e,0x44,0x42,0x49,0x3f,0x48, 0x42,0x47,0x3d,0x47,0x40,0x45,0x40,0x47,0x40,0x47,0x3d,0x45,0x42,0x49,0x3f,0x48, 0x42,0x45,0x3e,0x44,0x3f,0x46,0x3c,0x49,0x40,0x43,0x3e,0x47,0x3f,0x47,0x3d,0x4c, 0x3e,0x48,0x40,0x45,0x3c,0x47,0x3d,0x48,0x40,0x43,0x3d,0x43,0x41,0x48,0x40,0x4a, 0x41,0x45,0x3e,0x45,0x3f,0x48,0x40,0x49,0x3f,0x48,0x3e,0x48,0x3e,0x49,0x40,0x49, 0x40,0x45,0x40,0x48,0x41,0x46,0x44,0x49,0x41,0x48,0x40,0x48,0x3d,0x45,0x3d,0x47, 0x40,0x46,0x3f,0x49,0x45,0x4a,0x3e,0x4b,0x40,0x47,0x40,0x47,0x41,0x46,0x42,0x49, 0x40,0x46,0x40,0x45,0x42,0x46,0x3e,0x4a,0x40,0x43,0x41,0x44,0x41,0x45,0x3f,0x44, 0x40,0x44,0x40,0x4b,0x43,0x48,0x40,0x4b,0x42,0x47,0x41,0x47,0x42,0x48,0x41,0x47, 0x40,0x46,0x40,0x48,0x3f,0x49,0x3c,0x48,0x3e,0x47,0x3e,0x45,0x3f,0x48,0x3f,0x48, 0x3f,0x44,0x40,0x47,0x40,0x4a,0x41,0x48,0x43,0x44,0x3f,0x43,0x41,0x48,0x41,0x4b, 0x3f,0x45,0x3e,0x44,0x3d,0x46,0x3d,0x47,0x40,0x46,0x3d,0x47,0x3e,0x4a,0x3f,0x4b, 0x40,0x44,0x41,0x44,0x43,0x47,0x3f,0x4c,0x40,0x49,0x40,0x44,0x40,0x46,0x3f,0x47, 0x3f,0x46,0x43,0x46,0x44,0x49,0x3b,0x46,0x45,0x47,0x40,0x46,0x43,0x47,0x40,0x48, 0x3f,0x46,0x3e,0x48,0x41,0x49,0x41,0x4b,0x41,0x45,0x3f,0x44,0x40,0x46,0x3f,0x49, 0x40,0x46,0x40,0x43,0x3f,0x4a,0x3f,0x47,0x42,0x44,0x3e,0x46,0x40,0x49,0x3f,0x48, 0x42,0x47,0x3d,0x44,0x40,0x48,0x3d,0x49,0x42,0x46,0x3d,0x47,0x3d,0x47,0x3e,0x49, 0x42,0x43,0x3e,0x45,0x41,0x47,0x3f,0x45,0x44,0x46,0x40,0x46,0x40,0x45,0x3f,0x46, 0x41,0x45,0x3f,0x42,0x41,0x46,0x3f,0x4b,0x41,0x48,0x3f,0x44,0x3f,0x46,0x3f,0x47, 0x41,0x45,0x3e,0x46,0x3f,0x4a,0x3f,0x49,0x3e,0x43,0x40,0x45,0x3e,0x47,0x3f,0x4a, 0x40,0x44,0x40,0x46,0x3d,0x4a,0x3d,0x48,0x3f,0x47,0x41,0x44,0x41,0x47,0x3d,0x49, 0x3e,0x47,0x3f,0x45,0x3f,0x4a,0x3d,0x48,0x3e,0x46,0x3d,0x45,0x40,0x45,0x3f,0x49, 0x40,0x46,0x3c,0x43,0x40,0x47,0x43,0x49,0x44,0x46,0x40,0x48,0x3e,0x48,0x3c,0x4b, 0x3d,0x47,0x40,0x47,0x40,0x47,0x40,0x49,0x42,0x48,0x3d,0x47,0x40,0x47,0x3f,0x48, 0x43,0x47,0x3f,0x46,0x41,0x47,0x3f,0x4a,0x44,0x43,0x41,0x45,0x43,0x47,0x42,0x47, 0x40,0x48,0x40,0x47,0x41,0x49,0x41,0x4b,0x40,0x43,0x3c,0x46,0x43,0x48,0x40,0x48, 0x40,0x48,0x3c,0x45,0x40,0x46,0x42,0x49,0x41,0x47,0x3f,0x49,0x41,0x48,0x40,0x4a, 0x41,0x45,0x40,0x47,0x41,0x49,0x41,0x4b,0x3f,0x47,0x41,0x46,0x41,0x48,0x41,0x4a, 0x42,0x46,0x40,0x47,0x40,0x49,0x3e,0x48,0x3f,0x47,0x3f,0x44,0x42,0x46,0x3e,0x48, 0x40,0x46,0x3f,0x4c,0x41,0x49,0x3f,0x4d,0x41,0x48,0x40,0x4a,0x43,0x46,0x3f,0x4a, 0x40,0x49,0x3f,0x48,0x40,0x48,0x3e,0x4b,0x42,0x45,0x3f,0x45,0x45,0x47,0x42,0x46, 0x44,0x45,0x3f,0x45,0x3e,0x4a,0x40,0x4c,0x3f,0x46,0x43,0x48,0x41,0x48,0x3f,0x4a, 0x41,0x48,0x3f,0x46,0x42,0x4a,0x43,0x4a,0x42,0x49,0x42,0x47,0x41,0x49,0x41,0x4b, 0x41,0x44,0x40,0x48,0x40,0x48,0x40,0x48,0x3f,0x48,0x3b,0x46,0x42,0x4b,0x40,0x4b, 0x3f,0x46,0x40,0x47,0x44,0x46,0x3f,0x49,0x43,0x48,0x41,0x48,0x42,0x4c,0x3f,0x49, 0x43,0x47,0x42,0x46,0x45,0x46,0x3f,0x47,0x3f,0x48,0x43,0x48,0x41,0x46,0x3d,0x47, 0x3f,0x48,0x3e,0x46,0x42,0x45,0x40,0x48,0x3f,0x47,0x3f,0x4b,0x41,0x46,0x3e,0x49, 0x41,0x47,0x41,0x4c,0x3e,0x47,0x41,0x4a,0x42,0x46,0x41,0x48,0x3f,0x48,0x3f,0x48, 0x43,0x47,0x41,0x47,0x42,0x4a,0x3e,0x49,0x42,0x46,0x3f,0x47,0x40,0x47,0x3f,0x48, 0x42,0x44,0x42,0x46,0x40,0x46,0x3c,0x4b,0x3f,0x46,0x43,0x47,0x40,0x4b,0x3f,0x4b, 0x42,0x47,0x3e,0x44,0x46,0x46,0x42,0x49,0x40,0x47,0x42,0x48,0x3f,0x46,0x3f,0x48, 0x41,0x46,0x3e,0x48,0x3e,0x4b,0x40,0x46,0x41,0x43,0x41,0x47,0x42,0x45,0x3e,0x48, 0x42,0x48,0x42,0x44,0x43,0x47,0x3f,0x47,0x40,0x46,0x42,0x46,0x42,0x46,0x3f,0x4a, 0x41,0x44,0x3e,0x47,0x41,0x44,0x41,0x46,0x41,0x46,0x3e,0x47,0x41,0x49,0x40,0x48, 0x42,0x48,0x3e,0x47,0x41,0x48,0x40,0x44,0x40,0x43,0x3f,0x48,0x3f,0x46,0x41,0x48, 0x41,0x45,0x3b,0x49,0x44,0x47,0x3d,0x48,0x41,0x46,0x3e,0x47,0x3f,0x48,0x3f,0x49, 0x40,0x46,0x3f,0x49,0x40,0x47,0x41,0x45,0x43,0x46,0x3e,0x45,0x42,0x4a,0x40,0x49, 0x43,0x46,0x42,0x47,0x42,0x47,0x40,0x4a,0x41,0x47,0x40,0x49,0x42,0x48,0x40,0x4b, 0x42,0x44,0x3e,0x47,0x41,0x46,0x41,0x47,0x44,0x48,0x3f,0x48,0x40,0x46,0x42,0x4a, 0x42,0x45,0x43,0x47,0x44,0x48,0x3e,0x4a,0x43,0x46,0x40,0x4a,0x40,0x45,0x41,0x46, 0x41,0x46,0x3e,0x46,0x42,0x45,0x42,0x48,0x42,0x46,0x41,0x4b,0x42,0x4d,0x3d,0x40, 0x39,0x43,0x3c,0x47,0x41,0x45,0x44,0x41,0x3c,0x40,0x43,0x4e,0x43,0x45,0x3d,0x46, 0x3c,0x44,0x3a,0x43,0x3e,0x40,0x39,0x45,0x3e,0x41,0x39,0x44,0x3d,0x43,0x41,0x45, 0x3d,0x42,0x3a,0x41,0x3a,0x42,0x3c,0x42,0x3d,0x43,0x3a,0x44,0x3b,0x46,0x3a,0x46, 0x3b,0x43,0x3c,0x45,0x3c,0x41,0x3c,0x41,0x3b,0x3e,0x39,0x41,0x3a,0x40,0x3a,0x46, 0x3b,0x42,0x3a,0x42,0x3c,0x42,0x39,0x43,0x3b,0x43,0x3e,0x41,0x3c,0x3f,0x3e,0x43, 0x3b,0x42,0x3a,0x43,0x3e,0x43,0x3c,0x43,0x3e,0x43,0x3b,0x43,0x3c,0x40,0x3e,0x45, 0x3b,0x43,0x3b,0x43,0x3e,0x41,0x3b,0x47,0x3a,0x46,0x3a,0x43,0x3b,0x44,0x3d,0x48, 0x3c,0x42,0x3c,0x40,0x40,0x42,0x37,0x42,0x3d,0x41,0x3b,0x47,0x3f,0x44,0x3c,0x42, 0x3b,0x43,0x39,0x44,0x39,0x43,0x3b,0x44,0x3b,0x42,0x38,0x46,0x3b,0x40,0x3c,0x42, 0x3b,0x45,0x3b,0x41,0x3b,0x43,0x3c,0x43,0x3d,0x42,0x3d,0x42,0x3d,0x3f,0x39,0x45, 0x3b,0x43,0x3b,0x44,0x39,0x44,0x3a,0x44,0x3a,0x44,0x3c,0x42,0x3a,0x42,0x3b,0x47, 0x3e,0x42,0x3a,0x44,0x3c,0x41,0x3a,0x48,0x3d,0x3d,0x3d,0x44,0x3d,0x42,0x3d,0x44, 0x3b,0x44,0x3c,0x43,0x39,0x41,0x3c,0x42,0x3d,0x43,0x3d,0x40,0x3a,0x40,0x3d,0x42, 0x3e,0x44,0x38,0x45,0x3e,0x3f,0x3c,0x45,0x3c,0x41,0x3d,0x44,0x3c,0x42,0x3b,0x43, 0x3d,0x43,0x3b,0x45,0x3c,0x41,0x38,0x44,0x3a,0x42,0x38,0x42,0x3a,0x43,0x3c,0x49, 0x3c,0x42,0x39,0x44,0x3b,0x44,0x37,0x44,0x3b,0x44,0x3a,0x44,0x3d,0x43,0x38,0x45, 0x3b,0x44,0x37,0x42,0x39,0x40,0x3a,0x43,0x3b,0x41,0x3c,0x41,0x3d,0x40,0x39,0x43, 0x40,0x44,0x38,0x43,0x3b,0x42,0x3b,0x44,0x3e,0x41,0x3d,0x44,0x3c,0x44,0x3b,0x45, 0x3b,0x44,0x3b,0x43,0x3e,0x43,0x3d,0x41,0x3d,0x40,0x3c,0x43,0x3a,0x45,0x3e,0x43, 0x3c,0x42,0x3b,0x42,0x3d,0x44,0x3e,0x47,0x3c,0x41,0x3c,0x43,0x3a,0x44,0x39,0x43, 0x3f,0x3f,0x3a,0x43,0x3e,0x40,0x3a,0x46,0x3b,0x41,0x39,0x44,0x3a,0x42,0x3a,0x45, 0x3e,0x40,0x3c,0x41,0x3b,0x41,0x3d,0x45,0x3e,0x44,0x39,0x43,0x3c,0x42,0x3c,0x45, 0x3b,0x43,0x3d,0x44,0x3b,0x43,0x3a,0x43,0x3e,0x3f,0x3d,0x42,0x3d,0x44,0x39,0x47, 0x3f,0x44,0x3c,0x42,0x3d,0x45,0x3b,0x43,0x3c,0x3e,0x3d,0x43,0x3f,0x44,0x3b,0x44, 0x3a,0x44,0x3e,0x42,0x3c,0x41,0x3a,0x43,0x3e,0x3e,0x3c,0x44,0x3d,0x44,0x3d,0x47, 0x3e,0x41,0x3a,0x45,0x3d,0x41,0x3d,0x43,0x3b,0x45,0x39,0x42,0x3b,0x45,0x39,0x45, 0x39,0x44,0x3f,0x44,0x3b,0x43,0x3b,0x44,0x3d,0x47,0x38,0x43,0x3e,0x42,0x3b,0x45, 0x3e,0x43,0x38,0x43,0x40,0x41,0x39,0x41,0x3e,0x43,0x36,0x42,0x3b,0x44,0x3c,0x41, 0x3b,0x43,0x3c,0x43,0x3b,0x40,0x3d,0x44,0x3c,0x43,0x3a,0x45,0x3d,0x42,0x38,0x44, 0x39,0x41,0x3a,0x42,0x3c,0x45,0x3a,0x47,0x3d,0x43,0x39,0x41,0x3f,0x41,0x3d,0x46, 0x3e,0x45,0x39,0x45,0x3b,0x41,0x3c,0x45,0x3f,0x44,0x3a,0x44,0x41,0x44,0x3b,0x46, 0x3f,0x43,0x3d,0x43,0x3d,0x43,0x3e,0x45,0x3d,0x46,0x3b,0x44,0x3f,0x43,0x3c,0x46, 0x3e,0x42,0x3a,0x42,0x3b,0x44,0x3a,0x47,0x3d,0x42,0x3d,0x45,0x39,0x42,0x38,0x46, 0x3c,0x44,0x3a,0x48,0x3e,0x42,0x3a,0x48,0x40,0x44,0x3c,0x43,0x3c,0x44,0x3b,0x42, 0x40,0x41,0x3a,0x44,0x3f,0x42,0x3e,0x45,0x3d,0x44,0x3b,0x42,0x3e,0x46,0x3b,0x44, 0x40,0x42,0x3a,0x45,0x3f,0x45,0x3b,0x44,0x3b,0x41,0x3c,0x44,0x3c,0x45,0x3a,0x45, 0x3c,0x44,0x39,0x43,0x3c,0x44,0x3a,0x44,0x3d,0x43,0x37,0x45,0x3c,0x43,0x3c,0x41, 0x3b,0x42,0x39,0x44,0x3d,0x45,0x3a,0x44,0x3d,0x43,0x40,0x42,0x3c,0x43,0x3d,0x44, 0x3b,0x42,0x3a,0x42,0x3e,0x44,0x3b,0x47,0x3b,0x41,0x3b,0x43,0x3b,0x42,0x3d,0x45, 0x3b,0x40,0x3c,0x43,0x40,0x43,0x3c,0x43,0x3f,0x42,0x3d,0x42,0x40,0x44,0x3a,0x44, 0x40,0x41,0x3e,0x47,0x3c,0x40,0x3e,0x44,0x40,0x44,0x3f,0x46,0x3b,0x44,0x3d,0x43, 0x3f,0x44,0x3d,0x47,0x42,0x43,0x39,0x46,0x3d,0x41,0x3b,0x44,0x3e,0x43,0x38,0x44, 0x3f,0x45,0x3d,0x46,0x3e,0x42,0x3d,0x43,0x3c,0x43,0x3a,0x45,0x3b,0x46,0x3c,0x48, 0x39,0x45,0x3c,0x45,0x39,0x41,0x3b,0x45,0x3d,0x43,0x3d,0x45,0x3e,0x42,0x3c,0x45, 0x3d,0x43,0x3b,0x45,0x3e,0x42,0x3e,0x41,0x3c,0x42,0x39,0x48,0x3e,0x46,0x3a,0x43, 0x3e,0x45,0x3a,0x46,0x3a,0x41,0x3c,0x46,0x3f,0x42,0x3b,0x44,0x3c,0x46,0x3a,0x47, 0x3a,0x44,0x3a,0x43,0x3e,0x45,0x39,0x44,0x3c,0x42,0x3a,0x44,0x3d,0x45,0x3b,0x47, 0x3c,0x43,0x3b,0x44,0x3a,0x44,0x3c,0x41,0x3e,0x43,0x3c,0x43,0x3c,0x41,0x3d,0x47, 0x3b,0x44,0x3e,0x41,0x3e,0x46,0x3c,0x43,0x3f,0x45,0x3a,0x43,0x3a,0x46,0x3b,0x46, 0x3f,0x42,0x3a,0x44,0x3b,0x47,0x3a,0x47,0x3b,0x41,0x3c,0x42,0x3e,0x44,0x3b,0x45, 0x3e,0x40,0x3b,0x42,0x3d,0x45,0x3d,0x48,0x3b,0x42,0x3a,0x43,0x3d,0x46,0x38,0x42, 0x3f,0x43,0x3d,0x40,0x3c,0x47,0x3b,0x47,0x3c,0x40,0x3d,0x42,0x3d,0x42,0x3d,0x46, 0x3c,0x41,0x3d,0x42,0x3c,0x43,0x3e,0x44,0x3d,0x3f,0x3c,0x42,0x37,0x47,0x3b,0x47, 0x3c,0x44,0x3d,0x44,0x3f,0x43,0x3d,0x44,0x3c,0x42,0x3a,0x44,0x3e,0x44,0x3c,0x45, 0x3b,0x44,0x3c,0x42,0x3b,0x44,0x3a,0x47,0x3c,0x45,0x38,0x42,0x3d,0x43,0x3c,0x46, 0x3e,0x41,0x3e,0x43,0x3a,0x44,0x37,0x46,0x3c,0x45,0x39,0x43,0x3c,0x47,0x3a,0x48, 0x3b,0x43,0x3c,0x44,0x3d,0x44,0x3e,0x48,0x3b,0x43,0x3a,0x44,0x3c,0x43,0x3a,0x48, 0x3b,0x41,0x3c,0x43,0x3d,0x45,0x38,0x48,0x3a,0x42,0x3f,0x43,0x3c,0x48,0x3b,0x48, 0x3c,0x40,0x3b,0x44,0x41,0x47,0x3a,0x3d,0x32,0x3e,0x3d,0x41,0x3e,0x43,0x41,0x48, 0x3f,0x46,0x48,0x52,0x4b,0x4e,0x45,0x4d,0x43,0x47,0x41,0x4a,0x45,0x4b,0x43,0x4a, 0x47,0x4b,0x43,0x47,0x41,0x4a,0x43,0x49,0x41,0x47,0x41,0x48,0x45,0x4b,0x46,0x4c, 0x43,0x47,0x45,0x49,0x41,0x4b,0x40,0x4d,0x47,0x47,0x43,0x49,0x44,0x49,0x42,0x4c, 0x42,0x46,0x40,0x48,0x43,0x4c,0x42,0x4c,0x41,0x4a,0x45,0x48,0x43,0x4b,0x42,0x4b, 0x43,0x4a,0x42,0x48,0x41,0x4a,0x44,0x4b,0x44,0x47,0x41,0x45,0x42,0x4b,0x40,0x4b, 0x43,0x4a,0x43,0x4a,0x44,0x4e,0x42,0x49,0x41,0x49,0x43,0x47,0x43,0x49,0x44,0x4d, 0x47,0x48,0x42,0x49,0x45,0x4a,0x41,0x49,0x45,0x48,0x3e,0x49,0x42,0x4b,0x44,0x4b, 0x42,0x4a,0x42,0x49,0x42,0x49,0x42,0x4c,0x46,0x48,0x42,0x45,0x44,0x4b,0x41,0x4f, 0x46,0x4a,0x43,0x4a,0x45,0x49,0x43,0x4a,0x43,0x48,0x42,0x45,0x44,0x4a,0x40,0x4c, 0x43,0x47,0x42,0x49,0x43,0x4a,0x45,0x4d,0x44,0x48,0x42,0x4b,0x41,0x4a,0x44,0x4d, 0x40,0x49,0x43,0x4c,0x45,0x47,0x42,0x4b,0x43,0x48,0x41,0x49,0x43,0x4a,0x43,0x49, 0x45,0x4a,0x43,0x49,0x40,0x4b,0x40,0x4c,0x43,0x4a,0x41,0x4b,0x42,0x48,0x3f,0x4d, 0x43,0x4b,0x41,0x4c,0x45,0x4a,0x42,0x4d,0x43,0x49,0x43,0x46,0x43,0x4b,0x44,0x4b, 0x44,0x49,0x45,0x49,0x41,0x47,0x41,0x4c,0x43,0x4b,0x42,0x4a,0x43,0x48,0x44,0x4d, 0x42,0x49,0x43,0x4a,0x43,0x4c,0x42,0x50,0x43,0x4b,0x44,0x49,0x45,0x4c,0x42,0x4a, 0x43,0x47,0x41,0x4a,0x43,0x4b,0x41,0x4b,0x42,0x46,0x43,0x48,0x40,0x4c,0x3e,0x4d, 0x44,0x47,0x41,0x4d,0x43,0x4c,0x41,0x4d,0x00,0x22,0x80,0x09,0x00,0x10,0x00,0x01, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xb6,0x48,0xb4,0x52,0xb6,0x4a,0xb7,0x56,0xba,0x48,0xbe,0x56,0xc1,0x49, 0xc4,0x50,0xc3,0x48,0xc3,0x4f,0xc1,0x4b,0xc0,0x4e,0xba,0x50,0xb8,0x52,0xb8,0x49, 0xb8,0x4f,0xb9,0x46,0xba,0x4f,0xbe,0x4c,0xc1,0x52,0xc4,0x4a,0xc8,0x51,0xc6,0x44, 0xc6,0x52,0xc7,0x4c,0xc5,0x4f,0xbe,0x49,0xbd,0x53,0xba,0x4b,0xbd,0x4f,0xbb,0x4a, 0xbc,0x51,0xbf,0x48,0xc6,0x4d,0xc7,0x4c,0xc9,0x53,0xcb,0x47,0xcb,0x50,0xcb,0x48, 0xc7,0x51,0xc4,0x4a,0xc1,0x4e,0xbd,0x47,0xbb,0x4d,0xbb,0x43,0xbf,0x56,0xc0,0x49, 0xc4,0x50,0xca,0x4b,0xcc,0x4f,0xcd,0x4b,0xce,0x54,0xcd,0x4c,0xc9,0x4d,0xc7,0x47, 0xc4,0x51,0xc2,0x47,0xc1,0x4c,0xc2,0x48,0xc2,0x50,0xc5,0x49,0xca,0x4f,0xcb,0x4a, 0xcf,0x4e,0xcf,0x4d,0xd1,0x4e,0xcf,0x4a,0xcc,0x53,0xc8,0x49,0xc4,0x55,0xc2,0x4b, 0xc2,0x51,0xc0,0x46,0xc3,0x4f,0xc4,0x4b,0xc7,0x4f,0xcb,0x4a,0xcd,0x50,0xcd,0x46, 0xd0,0x51,0xcf,0x4c,0xcd,0x4e,0xc9,0x4c,0xc3,0x50,0xc1,0x49,0xc1,0x4d,0xbf,0x47, 0xbf,0x53,0xc1,0x49,0xc3,0x4a,0xc6,0x49,0xc8,0x54,0xcb,0x48,0xca,0x4e,0xc9,0x45, 0xc8,0x51,0xc5,0x4a,0xc0,0x50,0xbe,0x44,0xbd,0x4f,0xbc,0x4b,0xbb,0x51,0xbd,0x49, 0xc0,0x50,0xc3,0x4b,0xc6,0x52,0xc7,0x48,0xc9,0x54,0xc8,0x46,0xc6,0x51,0xc3,0x49, 0xbf,0x51,0xbd,0x48,0xbb,0x4d,0xbb,0x4a,0xba,0x53,0xba,0x4a,0xbd,0x53,0xc2,0x4b, 0xc4,0x55,0xc7,0x49,0xc9,0x4e,0xc8,0x49,0xc6,0x4f,0xc4,0x4e,0xc0,0x51,0xbc,0x46, 0xba,0x52,0xba,0x4b,0xbb,0x4e,0xbb,0x45,0xbd,0x52,0xc1,0x4b,0xc3,0x54,0xc6,0x48, 0xc8,0x55,0xc8,0x47,0xc7,0x4f,0xc5,0x45,0xc0,0x51,0xbc,0x47,0xbc,0x4d,0xba,0x48, 0xba,0x50,0xb9,0x48,0xbd,0x4f,0xbf,0x45,0xc1,0x51,0xc5,0x47,0xc7,0x52,0xc6,0x46, 0xc7,0x4e,0xc4,0x4b,0xc0,0x53,0xbb,0x49,0xba,0x51,0xb9,0x4a,0xb7,0x4f,0xb9,0x48, 0xbc,0x4f,0xbe,0x4b,0xc1,0x53,0xc4,0x4d,0xc7,0x53,0xc6,0x49,0xc6,0x50,0xc4,0x47, 0xc2,0x4d,0xbd,0x4a,0xbc,0x4c,0xba,0x48,0xba,0x53,0xba,0x45,0xbb,0x50,0xbe,0x46, 0xc0,0x53,0xc3,0x46,0xc6,0x51,0xc5,0x48,0xc5,0x53,0xc3,0x48,0xc1,0x4e,0xbd,0x44, 0xbd,0x4f,0xbb,0x4c,0xbb,0x4e,0xba,0x49,0xbb,0x51,0xbc,0x46,0xc0,0x51,0xc4,0x49, 0xc7,0x50,0xc8,0x48,0xc8,0x4d,0xc5,0x46,0xc3,0x54,0xbf,0x49,0xbc,0x50,0xbb,0x4c, 0xbb,0x52,0xba,0x4f,0xbb,0x53,0xbd,0x4a,0xc0,0x53,0xc4,0x49,0xc6,0x4f,0xc8,0x49, 0xc8,0x53,0xc6,0x4b,0xc3,0x50,0xc0,0x4d,0xbd,0x54,0xbc,0x4d,0xb9,0x52,0xba,0x4a, 0xbb,0x54,0xbe,0x49,0xc2,0x4b,0xc4,0x47,0xc6,0x55,0xc6,0x47,0xc8,0x51,0xc6,0x4a, 0xc2,0x52,0xbe,0x4b,0xbd,0x4a,0xbb,0x49,0xb9,0x53,0xb9,0x49,0xb9,0x52,0xbd,0x4c, 0xc1,0x52,0xc4,0x49,0xc8,0x4e,0xc9,0x48,0xc8,0x50,0xc9,0x4a,0xc5,0x4f,0xc1,0x47, 0xbe,0x53,0xbc,0x4c,0xbb,0x51,0xba,0x45,0xbb,0x54,0xbc,0x4a,0xbe,0x51,0xc2,0x4b, 0xc5,0x50,0xc7,0x4a,0xc7,0x53,0xc7,0x46,0xc5,0x53,0xc1,0x4d,0xbe,0x52,0xba,0x48, 0xba,0x54,0xb8,0x45,0xb8,0x4f,0xba,0x4a,0xbe,0x56,0xc0,0x48,0xc4,0x52,0xc7,0x4a, 0xc6,0x54,0xc6,0x4b,0xc3,0x50,0xbf,0x49,0xbd,0x51,0xbb,0x4e,0xb9,0x4d,0xb8,0x49, 0xb9,0x51,0xba,0x47,0xbc,0x50,0xc1,0x48,0xc4,0x51,0xc7,0x48,0xc6,0x51,0xc5,0x4a, 0xc4,0x52,0xc1,0x49,0xbc,0x51,0xb8,0x47,0xb8,0x52,0xb7,0x4b,0xb7,0x55,0xb8,0x47, 0xba,0x50,0xbe,0x48,0xc0,0x50,0xc2,0x4a,0xc6,0x52,0xc2,0x4a,0xc4,0x51,0xbe,0x48, 0xc0,0x4f,0xb7,0x47,0xb7,0x4e,0xb6,0x46,0xb6,0x54,0xb7,0x47,0xba,0x4e,0xba,0x46, 0xbf,0x53,0xc2,0x4a,0xc4,0x4f,0xc3,0x44,0xc1,0x55,0xc0,0x4a,0xbb,0x50,0xb8,0x4a, 0xb6,0x52,0xb6,0x4e,0xb6,0x51,0xb6,0x45,0xb6,0x51,0xb9,0x4c,0xc1,0x4f,0xc3,0x48, 0xc1,0x51,0xc3,0x48,0xc5,0x4d,0xc1,0x45,0xbd,0x4e,0xb6,0x47,0xb7,0x4c,0xb7,0x4c, 0xb3,0x51,0xb3,0x47,0xb7,0x4e,0xbb,0x4c,0xbe,0x51,0xc0,0x46,0xc1,0x51,0xc3,0x49, 0xc2,0x52,0xbe,0x45,0xbb,0x51,0xb8,0x4c,0xb6,0x52,0xb4,0x47,0xb4,0x53,0xb5,0x48, 0xb4,0x52,0xba,0x49,0xbd,0x4d,0xbe,0x47,0xc1,0x54,0xc4,0x49,0xc2,0x4f,0xbf,0x45, 0xbb,0x4f,0xb7,0x47,0xb5,0x53,0xb4,0x48,0xb4,0x58,0xb5,0x46,0xb7,0x53,0xb8,0x49, 0xbf,0x4f,0xc2,0x49,0xc3,0x50,0xc2,0x49,0xc4,0x53,0xc2,0x49,0xbc,0x51,0xb9,0x48, 0xb7,0x52,0xb5,0x4a,0xb4,0x4f,0xb5,0x47,0xb7,0x51,0xb8,0x44,0xbe,0x4f,0xbf,0x4b, 0xc2,0x4c,0xc3,0x48,0xc3,0x51,0xc1,0x49,0xbe,0x56,0xbb,0x49,0xb8,0x4d,0xb6,0x4a, 0xb7,0x4e,0xb7,0x4b,0xb7,0x4c,0xb9,0x4a,0xbc,0x54,0xc0,0x49,0xc3,0x53,0xc3,0x45, 0xc3,0x4e,0xc2,0x4a,0xbf,0x50,0xbb,0x47,0xb7,0x54,0xb5,0x48,0xb6,0x53,0xb5,0x49, 0xb5,0x4c,0xb5,0x47,0xbb,0x4c,0xbd,0x47,0xbf,0x51,0xc1,0x49,0xc1,0x4e,0xc0,0x48, 0xbd,0x54,0xba,0x45,0xb7,0x4f,0xb4,0x46,0xb3,0x52,0xb6,0x42,0xb6,0x52,0xb7,0x47, 0xb9,0x55,0xbe,0x47,0xc0,0x4f,0xc2,0x4b,0xc1,0x51,0xc1,0x4a,0xbe,0x50,0xbb,0x49, 0xb7,0x4e,0xb4,0x45,0xb4,0x4a,0xb3,0x3f,0xb3,0x4e,0xb5,0x48,0xb8,0x50,0xbc,0x49, 0xc0,0x54,0xbe,0x4e,0xc6,0x35,0xc3,0x32,0xc2,0x37,0xbe,0x30,0xbc,0x3f,0xb9,0x34, 0xb9,0x3b,0xb9,0x33,0xba,0x33,0xbc,0x2e,0xbf,0x36,0xc0,0x30,0xc3,0x38,0xc5,0x2f, 0xc4,0x34,0xc3,0x2f,0xc0,0x35,0xbd,0x2d,0xb9,0x35,0xb8,0x2d,0xb7,0x36,0xb8,0x2e, 0xb8,0x34,0xb9,0x32,0xbb,0x38,0xc0,0x2e,0xc1,0x38,0xc3,0x2c,0xc3,0x38,0xc2,0x2d, 0xc0,0x36,0xbf,0x2d,0xb7,0x33,0xb6,0x31,0xb6,0x35,0xb7,0x2a,0xb7,0x39,0xb7,0x2a, 0xbb,0x36,0xbf,0x2d,0xc0,0x36,0xc2,0x2c,0xc2,0x36,0xc1,0x2e,0xbe,0x37,0xbb,0x2d, 0xb7,0x35,0xb7,0x2c,0xb5,0x31,0xb5,0x2f,0xb6,0x35,0xb7,0x2b,0xb8,0x35,0xbc,0x2d, 0xbd,0x30,0xbf,0x2d,0xc0,0x38,0xbf,0x2d,0xbb,0x36,0xb9,0x30,0xb5,0x35,0xb5,0x2d, 0xb3,0x37,0xb3,0x2a,0xb3,0x32,0xb4,0x2e,0xb6,0x39,0xbb,0x2e,0xbc,0x32,0xbe,0x2f, 0xc2,0x37,0xbf,0x31,0xbc,0x31,0xbb,0x2f,0xb8,0x39,0xb6,0x2f,0xb4,0x37,0xb6,0x2e, 0xb5,0x34,0xb5,0x2a,0xb7,0x34,0xba,0x2f,0xbc,0x3a,0xbf,0x2d,0xbe,0x38,0xbc,0x2b, 0xbc,0x37,0xb9,0x2e,0xb6,0x33,0xb3,0x2e,0xb2,0x34,0xb0,0x2b,0xb1,0x34,0xb2,0x2b, 0xb3,0x34,0xb7,0x2d,0xb9,0x35,0xbc,0x2c,0xbe,0x37,0xbe,0x2a,0xbd,0x36,0xba,0x2e, 0xb8,0x38,0xb3,0x2b,0xb3,0x32,0xb2,0x2a,0xb2,0x37,0xb3,0x2e,0xb4,0x37,0xb9,0x2b, 0xbe,0x38,0xbf,0x32,0xc1,0x3c,0xc1,0x2c,0xbf,0x3a,0xbe,0x2d,0xbb,0x35,0xb9,0x2c, 0xb8,0x34,0xb7,0x2e,0xb7,0x34,0xb6,0x2e,0xb8,0x3c,0xbb,0x2b,0xbe,0x39,0xc1,0x2f, 0xc1,0x31,0xc2,0x2b,0xc0,0x37,0xbe,0x2e,0xbb,0x35,0xb9,0x2f,0xb7,0x37,0xb7,0x2e, 0xb6,0x35,0xb7,0x2d,0xb8,0x36,0xba,0x2a,0xbc,0x35,0xc0,0x2e,0xc1,0x34,0xc1,0x2e, 0xbf,0x37,0xbd,0x29,0xb9,0x34,0xb7,0x2c,0xb7,0x39,0xb5,0x30,0xb4,0x3b,0xb4,0x2e, 0xb5,0x35,0xb7,0x30,0xbb,0x32,0xbd,0x2f,0xc1,0x37,0xc2,0x2f,0xc0,0x37,0xbf,0x2e, 0xbb,0x35,0xb7,0x2b,0xb5,0x36,0xb4,0x2c,0xb5,0x3a,0xb5,0x2f,0xb6,0x38,0xb8,0x2e, 0xbb,0x38,0xc0,0x2f,0xbf,0x32,0xc0,0x2f,0xc1,0x38,0xbf,0x2e,0xbb,0x33,0xb9,0x2d, 0xb7,0x3a,0xb5,0x2f,0xb3,0x32,0xb4,0x2b,0xb5,0x37,0xb7,0x30,0xb9,0x32,0xbd,0x2a, 0xbf,0x39,0xc1,0x2e,0xc0,0x2e,0xbe,0x36,0xbd,0x35,0xbb,0x2d,0xb7,0x34,0xb7,0x2d, 0xb7,0x35,0xb6,0x30,0xb6,0x33,0xb7,0x30,0xba,0x35,0xbf,0x2f,0xc2,0x36,0xc3,0x2e, 0xc2,0x35,0xc1,0x2f,0xbf,0x37,0xb9,0x30,0xb8,0x36,0xb6,0x32,0xb6,0x35,0xb4,0x2a, 0xb6,0x33,0xb8,0x2d,0xb9,0x31,0xbc,0x2d,0xc0,0x3b,0xc2,0x2c,0xc1,0x34,0xc0,0x2d, 0xbe,0x38,0xba,0x30,0xb8,0x35,0xb8,0x2d,0xb6,0x3c,0xb5,0x32,0xb5,0x34,0xb7,0x2d, 0xba,0x37,0xbd,0x2d,0xbf,0x33,0xbf,0x2c,0xc1,0x39,0xbf,0x2f,0xbc,0x33,0xbb,0x2f, 0xb8,0x35,0xb6,0x2d,0xb4,0x34,0xb4,0x30,0xb4,0x35,0xb4,0x31,0xb8,0x34,0xbd,0x2e, 0xbf,0x3a,0xbe,0x31,0xbf,0x36,0xc0,0x2f,0xbd,0x38,0xb9,0x30,0xb6,0x37,0xb4,0x30, 0xb4,0x37,0xb4,0x2d,0xb3,0x36,0xb4,0x2c,0xb6,0x38,0xba,0x2e,0xba,0x35,0xbd,0x2c, 0xbd,0x35,0xbc,0x32,0xbb,0x3b,0xb9,0x2e,0xb6,0x39,0xb3,0x31,0xb3,0x35,0xb1,0x2e, 0xb2,0x39,0xb3,0x30,0xb5,0x33,0xba,0x2b,0xbc,0x38,0xbc,0x31,0xbc,0x37,0xbc,0x2d, 0xbb,0x36,0xb6,0x30,0xb3,0x39,0xb2,0x2c,0xb1,0x37,0xb2,0x2f,0xb1,0x38,0xb1,0x2c, 0xb4,0x39,0xb7,0x2c,0xba,0x37,0xbd,0x2a,0xbf,0x34,0xbf,0x2e,0xbc,0x3a,0xba,0x2a, 0xb7,0x34,0xb4,0x2c,0xb2,0x33,0xb0,0x30,0xb2,0x3a,0xb1,0x2f,0xb2,0x3b,0xb6,0x2a, 0xbb,0x34,0xbb,0x2d,0xbc,0x2f,0xbc,0x2f,0xba,0x38,0xb7,0x2c,0xb5,0x36,0xb4,0x2d, 0xb3,0x34,0xb2,0x2f,0xb1,0x30,0xb2,0x2d,0xb3,0x38,0xb7,0x2f,0xb8,0x36,0xb9,0x30, 0xbb,0x35,0xbc,0x30,0xbb,0x35,0xb7,0x30,0xb5,0x37,0xb1,0x2f,0xb2,0x33,0xb0,0x2d, 0xae,0x34,0xb1,0x2e,0xb1,0x36,0xb5,0x30,0xb8,0x3b,0xbb,0x2f,0xbb,0x35,0xbb,0x2d, 0xbb,0x37,0xb9,0x30,0xb7,0x35,0xb4,0x2d,0xb2,0x37,0xb1,0x2f,0xb0,0x38,0xae,0x2b, 0xb0,0x39,0xb3,0x2c,0xb5,0x33,0xb7,0x2e,0xba,0x3b,0xbb,0x2c,0xb8,0x39,0xb6,0x30, 0xb3,0x35,0xb2,0x2d,0xaf,0x35,0xb0,0x2d,0xaf,0x3c,0xae,0x2d,0xaf,0x36,0xb1,0x2e, 0xb5,0x37,0xb7,0x2f,0xb7,0x36,0xb8,0x32,0xb8,0x35,0xb5,0x2c,0xb3,0x36,0xb1,0x2c, 0xb0,0x38,0xae,0x2d,0xad,0x36,0xad,0x2b,0xae,0x37,0xb0,0x29,0xb3,0x35,0xb4,0x31, 0xb6,0x35,0xb7,0x31,0xb7,0x33,0xb5,0x2f,0xb3,0x39,0xb1,0x2c,0xad,0x37,0xac,0x30, 0xae,0x35,0xae,0x2e,0xae,0x31,0xb0,0x2e,0xb3,0x39,0xb7,0x2a,0xb8,0x35,0xb7,0x2e, 0xb8,0x34,0xb8,0x2e,0xb5,0x36,0xb2,0x2f,0xae,0x36,0xae,0x2e,0xae,0x3a,0xae,0x2c, 0xae,0x34,0xaf,0x2f,0xb3,0x36,0xb6,0x2a,0xb8,0x39,0xb7,0x2e,0xb7,0x33,0xb7,0x2d, 0xb5,0x35,0xb1,0x30,0xaf,0x33,0xac,0x30,0xad,0x3a,0xad,0x2b,0xad,0x34,0xad,0x32, 0xb2,0x36,0xb5,0x2f,0xb6,0x31,0xb7,0x29,0xb8,0x38,0xb6,0x31,0xb4,0x36,0xb1,0x2d, 0xaf,0x34,0xaf,0x2f,0xae,0x33,0xac,0x2c,0xac,0x35,0xae,0x30,0xb1,0x32,0xb3,0x30, 0xb7,0x38,0xb8,0x2f,0xb9,0x34,0xb7,0x2d,0xb6,0x38,0xb4,0x2d,0xb1,0x38,0xaf,0x2f, 0xae,0x34,0xae,0x2b,0xae,0x36,0xae,0x30,0xb1,0x36,0xb5,0x2f,0xb8,0x37,0xb8,0x2b, 0xba,0x37,0xb8,0x32,0xb4,0x32,0xb1,0x30,0xb1,0x36,0xae,0x2c,0xab,0x32,0xac,0x32, 0xae,0x37,0xaf,0x2c,0xaf,0x37,0xb3,0x2b,0xb7,0x39,0xb7,0x31,0xb7,0x33,0xb7,0x2b, 0xb7,0x38,0xb2,0x2f,0xb1,0x36,0xaf,0x2f,0xb0,0x3a,0xac,0x29,0xac,0x30,0xad,0x25, 0xae,0x31,0xb1,0x2b,0xb4,0x35,0xb6,0x2e,0xb7,0x3a,0xb2,0x33,0xb8,0x52,0xb3,0x50, 0xb2,0x51,0xb0,0x58,0xae,0x61,0xad,0x58,0xaf,0x5c,0xb0,0x50,0xb2,0x58,0xb5,0x4d, 0xb7,0x57,0xb7,0x52,0xba,0x54,0xb9,0x54,0xb6,0x58,0xb5,0x4f,0xb0,0x59,0xae,0x50, 0xaf,0x56,0xad,0x4f,0xad,0x55,0xaf,0x4d,0xb1,0x5b,0xb1,0x51,0xb5,0x55,0xb6,0x50, 0xb6,0x56,0xb6,0x4f,0xb5,0x57,0xb1,0x4e,0xae,0x5a,0xac,0x50,0xac,0x5c,0xab,0x50, 0xab,0x58,0xac,0x51,0xb2,0x56,0xb3,0x4f,0xb2,0x57,0xb5,0x4d,0xba,0x56,0xb5,0x52, 0xb1,0x58,0xb3,0x4f,0xb0,0x59,0xae,0x4f,0xac,0x5a,0xad,0x4c,0xac,0x5a,0xac,0x50, 0xae,0x55,0xb3,0x4d,0xb4,0x56,0xb5,0x55,0xb7,0x58,0xb7,0x4e,0xb5,0x56,0xb4,0x50, 0xaf,0x58,0xad,0x50,0xae,0x56,0xac,0x50,0xad,0x5e,0xac,0x51,0xae,0x58,0xaf,0x4f, 0xb3,0x56,0xb4,0x50,0xb3,0x57,0xb4,0x4f,0xb4,0x59,0xb1,0x4f,0xae,0x59,0xac,0x4c, 0xaa,0x56,0xa9,0x4e,0xa9,0x5b,0xa7,0x4d,0xab,0x58,0xad,0x53,0xb1,0x59,0xb3,0x52, 0xb5,0x57,0xb6,0x4e,0xb3,0x57,0xb1,0x4d,0xae,0x57,0xaa,0x52,0xa9,0x5c,0xaa,0x4d, 0xab,0x55,0xaa,0x54,0xab,0x57,0xae,0x51,0xb2,0x59,0xb1,0x51,0xb4,0x56,0xb4,0x4f, 0xb2,0x58,0xaf,0x51,0xad,0x58,0xaa,0x50,0xa8,0x5c,0xa6,0x4e,0xa8,0x54,0xa9,0x50, 0xab,0x5c,0xaa,0x50,0xb1,0x58,0xb2,0x54,0xb5,0x5a,0xb4,0x52,0xb4,0x56,0xb1,0x50, 0xaf,0x58,0xad,0x4f,0xaa,0x57,0xa9,0x4f,0xa9,0x58,0xab,0x4f,0xac,0x57,0xac,0x4f, 0xb0,0x5b,0xb2,0x52,0xb4,0x59,0xb2,0x52,0xb4,0x5f,0xb1,0x52,0xad,0x57,0xab,0x4e, 0xa8,0x58,0xa8,0x51,0xa7,0x55,0xa7,0x4f,0xa9,0x57,0xaa,0x51,0xad,0x56,0xb0,0x50, 0xb3,0x5a,0xb0,0x52,0xb0,0x57,0xb0,0x4d,0xaf,0x5a,0xa8,0x53,0xa8,0x57,0xa7,0x50, 0xa8,0x56,0xa8,0x4c,0xa8,0x55,0xa9,0x4f,0xab,0x5b,0xad,0x52,0xb1,0x5a,0xb0,0x4f, 0xaf,0x57,0xb0,0x4f,0xac,0x57,0xa9,0x53,0xa8,0x5a,0xa6,0x51,0xa5,0x58,0xa6,0x53, 0xa7,0x5b,0xa6,0x50,0xa7,0x57,0xaf,0x53,0xb1,0x5d,0xae,0x4e,0xb1,0x58,0xaf,0x52, 0xae,0x5a,0xa9,0x52,0xa7,0x59,0xa6,0x52,0xa7,0x59,0xa5,0x4d,0xa6,0x5b,0xa8,0x50, 0xab,0x54,0xad,0x51,0xaf,0x55,0xb1,0x4f,0xaf,0x57,0xaf,0x51,0xae,0x5c,0xa9,0x4f, 0xa7,0x56,0xa7,0x4f,0xa6,0x59,0xa5,0x4f,0xa6,0x59,0xa7,0x50,0xaa,0x59,0xac,0x4b, 0xae,0x55,0xb0,0x4f,0xaf,0x55,0xab,0x4e,0xa9,0x5a,0xa9,0x4c,0xa6,0x58,0xa3,0x4e, 0xa4,0x53,0xa4,0x50,0xa6,0x57,0xa8,0x54,0xa9,0x58,0xac,0x51,0xb0,0x5a,0xb0,0x4f, 0xae,0x56,0xaf,0x51,0xac,0x57,0xa9,0x4e,0xa8,0x59,0xa6,0x4e,0xa5,0x58,0xa6,0x4f, 0xa6,0x52,0xa5,0x50,0xa8,0x53,0xaa,0x50,0xac,0x58,0xad,0x51,0xae,0x5a,0xaf,0x4e, 0xad,0x5a,0xa4,0x4f,0x9e,0x55,0xa4,0x4e,0xa3,0x5c,0x9b,0x4c,0x9e,0x58,0xa4,0x50, 0xa7,0x54,0xa9,0x52,0xab,0x59,0xac,0x50,0xae,0x5b,0xad,0x4d,0xab,0x57,0xa9,0x52, 0xa6,0x57,0xa2,0x50,0xa3,0x56,0xa2,0x4d,0xa2,0x59,0xa4,0x4f,0xa5,0x5b,0xa7,0x50, 0xac,0x56,0xab,0x4e,0xa9,0x5a,0xab,0x50,0xab,0x5a,0xa5,0x50,0xa2,0x58,0xa1,0x4e, 0xa0,0x59,0xa0,0x54,0xa1,0x56,0xa1,0x4b,0xa4,0x5c,0xa5,0x50,0xa8,0x57,0xa8,0x4e, 0xaa,0x54,0xac,0x4f,0xa9,0x55,0xa6,0x4f,0xa4,0x5b,0xa4,0x4f,0xa1,0x5b,0xa2,0x4e, 0xa0,0x5a,0xa1,0x4f,0xa4,0x55,0xa7,0x54,0xaa,0x5c,0xab,0x52,0xaf,0x59,0xad,0x51, 0xab,0x58,0xa9,0x4c,0xa7,0x57,0xa5,0x53,0xa2,0x59,0xa1,0x4f,0xa2,0x55,0xa4,0x4d, 0xa5,0x5c,0xa5,0x53,0xa9,0x5a,0xab,0x52,0xab,0x61,0xac,0x4f,0xab,0x56,0xa9,0x4f, 0xa6,0x58,0xa4,0x4e,0xa2,0x58,0xa2,0x4f,0xa3,0x5b,0xa4,0x55,0xa4,0x57,0xa5,0x50, 0xa9,0x53,0xac,0x51,0xae,0x59,0xab,0x56,0xaa,0x56,0xab,0x51,0xa7,0x59,0xa2,0x50, 0xa2,0x5a,0xa0,0x54,0xa0,0x56,0xa1,0x53,0xa2,0x5a,0xa4,0x4f,0xa7,0x59,0xa9,0x4d, 0xad,0x58,0xac,0x50,0xa9,0x57,0xaa,0x4f,0xaa,0x5a,0xa6,0x53,0xa3,0x58,0xa4,0x50, 0xa5,0x5b,0xa5,0x4f,0xa3,0x5a,0xa5,0x52,0xa9,0x5c,0xab,0x51,0xac,0x57,0xac,0x50, 0xaf,0x5b,0xac,0x54,0xa9,0x54,0xa5,0x52,0xa5,0x5c,0xa4,0x50,0xa2,0x58,0xa0,0x51, 0xa4,0x56,0xa4,0x50,0xa7,0x5a,0xa9,0x4d,0xae,0x5b,0xac,0x4c,0xac,0x5b,0xac,0x4f, 0xab,0x58,0xa8,0x53,0xa4,0x58,0xa2,0x51,0xa1,0x56,0xa0,0x54,0xa3,0x59,0xa4,0x4f, 0xa5,0x57,0xa8,0x50,0xac,0x57,0xae,0x4f,0xad,0x58,0xa9,0x50,0xa7,0x58,0xa4,0x50, 0xa4,0x56,0x9f,0x4b,0xa0,0x58,0xa1,0x4d,0xa2,0x57,0xa3,0x4f,0xa5,0x5b,0xa7,0x4f, 0xab,0x59,0xaa,0x50,0xaa,0x58,0xa8,0x54,0xa8,0x58,0xa4,0x4e,0xa1,0x58,0xa2,0x4c, 0xa1,0x55,0x9f,0x56,0x9f,0x52,0xa2,0x4e,0xa5,0x56,0xa8,0x4e,0xa9,0x58,0xaa,0x50, 0xac,0x59,0xab,0x51,0xa9,0x55,0xa5,0x50,0xa4,0x58,0xa2,0x51,0xa0,0x58,0xa0,0x4c, 0xa2,0x5b,0xa3,0x4f,0xa4,0x54,0xa8,0x4f,0xab,0x59,0xac,0x52,0xac,0x56,0xab,0x50, 0xac,0x58,0xa8,0x53,0xa5,0x4f,0xa4,0x4b,0xa1,0x57,0x9e,0x51,0xa2,0x58,0xa1,0x4d, 0xa2,0x5c,0xa6,0x4e,0xaa,0x53,0xac,0x51,0xac,0x56,0xaa,0x50,0xa9,0x55,0xa8,0x4e, 0xa5,0x5b,0xa2,0x53,0xa0,0x52,0xa0,0x50,0xa3,0x57,0xa2,0x53,0xa3,0x59,0xa7,0x52, 0xac,0x5c,0xac,0x52,0xac,0x58,0xa5,0x4f,0xa8,0x5b,0xa8,0x51,0xa0,0x5b,0x9c,0x4b, 0xa2,0x56,0xa3,0x4f,0xa1,0x57,0xa2,0x50,0xa5,0x55,0xa6,0x54,0xaa,0x5b,0xac,0x4e, 0xad,0x59,0xab,0x50,0xaa,0x56,0xa8,0x4f,0xa5,0x59,0xa1,0x51,0xa0,0x56,0xa0,0x53, 0x9e,0x5a,0xa0,0x4c,0xa1,0x4f,0xa5,0x49,0xa8,0x51,0xaa,0x53,0xaa,0x56,0xa9,0x4f, 0xab,0x59,0xa3,0x55,0xa6,0x45,0xa8,0x3f,0xa6,0x48,0xa4,0x44,0xa6,0x4d,0xa6,0x48, 0xa8,0x4d,0xaa,0x41,0xad,0x47,0xae,0x40,0xaf,0x4a,0xae,0x44,0xad,0x49,0xab,0x3c, 0xa9,0x46,0xa5,0x3f,0xa5,0x48,0xa4,0x3d,0xa5,0x47,0xa5,0x40,0xa8,0x48,0xaa,0x41, 0xad,0x48,0xb0,0x3f,0xaf,0x43,0xae,0x3c,0xae,0x45,0xac,0x3f,0xa8,0x4b,0xa6,0x3f, 0xa4,0x48,0xa4,0x3f,0xa3,0x43,0xa3,0x43,0xa5,0x45,0xa9,0x41,0xaa,0x47,0xac,0x3f, 0xad,0x4c,0xac,0x42,0xab,0x45,0xa8,0x42,0xa7,0x43,0xa3,0x43,0xa1,0x48,0xa2,0x40, 0xa2,0x4b,0xa0,0x41,0xa2,0x46,0xa6,0x43,0xaa,0x49,0xaa,0x42,0xad,0x4a,0xab,0x40, 0xab,0x4a,0xaa,0x40,0xa6,0x47,0xa2,0x44,0xa2,0x4b,0xa0,0x42,0xa0,0x43,0xa0,0x43, 0xa0,0x46,0xa3,0x40,0xa7,0x47,0xa8,0x3d,0xa9,0x4b,0xab,0x40,0xab,0x42,0xa7,0x41, 0xa6,0x47,0xa3,0x42,0xa0,0x4a,0xa0,0x43,0xa1,0x49,0xa1,0x3e,0xa3,0x4a,0xa2,0x40, 0xa7,0x47,0xa9,0x42,0xa9,0x43,0xa8,0x42,0xa9,0x47,0xa7,0x44,0xa4,0x49,0xa2,0x3f, 0xa1,0x4a,0xa0,0x40,0xa0,0x4b,0x9f,0x3d,0xa0,0x4a,0xa1,0x41,0xa5,0x47,0xa7,0x44, 0xaa,0x49,0xa9,0x43,0xa9,0x46,0xa8,0x42,0xa7,0x46,0xa1,0x41,0xa0,0x46,0x9e,0x40, 0xa0,0x4c,0x9d,0x41,0x9e,0x48,0x9e,0x42,0xa4,0x4a,0xa7,0x42,0xa7,0x48,0xa7,0x41, 0xa8,0x49,0xa5,0x40,0xa4,0x44,0xa0,0x3c,0x9f,0x44,0x9d,0x43,0x9e,0x4d,0x9c,0x40, 0x9d,0x46,0x9f,0x42,0xa2,0x45,0xa4,0x41,0xa8,0x49,0xa8,0x3e,0xa9,0x48,0xa7,0x3e, 0xa5,0x46,0xa2,0x3e,0x9e,0x45,0x9d,0x42,0x9d,0x4a,0x9c,0x40,0x9e,0x4b,0x9f,0x3d, 0xa1,0x49,0xa2,0x42,0xa6,0x4a,0xa6,0x40,0xa8,0x4a,0xa6,0x41,0xa5,0x4a,0xa1,0x41, 0xa0,0x49,0x9e,0x42,0x9d,0x47,0x9d,0x3f,0x9c,0x45,0x9e,0x46,0x9f,0x48,0xa3,0x3f, 0xa4,0x46,0xa6,0x43,0xa6,0x47,0xa5,0x3f,0xa3,0x49,0x9f,0x41,0x9d,0x49,0x9d,0x3e, 0x9b,0x4b,0x99,0x3e,0x9a,0x46,0x9b,0x3d,0x9f,0x4c,0xa1,0x3f,0xa4,0x4b,0xa5,0x3d, 0xa7,0x47,0xa5,0x42,0xa4,0x4a,0xa1,0x41,0x9e,0x4c,0x9b,0x3e,0x99,0x45,0x97,0x40, 0x9a,0x47,0x98,0x42,0x9c,0x48,0x9f,0x40,0xa3,0x49,0xa2,0x40,0xa4,0x4b,0xa4,0x42, 0xa2,0x4a,0x9f,0x41,0x9e,0x46,0x9c,0x3f,0x9a,0x4a,0x9a,0x43,0x9a,0x46,0x99,0x45, 0x9b,0x4a,0x9d,0x41,0xa0,0x48,0xa3,0x3d,0xa4,0x49,0xa1,0x44,0xa3,0x4d,0x9e,0x3c, 0x9a,0x49,0x98,0x42,0x99,0x47,0x97,0x3e,0x96,0x48,0x99,0x43,0x9b,0x45,0x9e,0x42, 0xa0,0x46,0xa2,0x3f,0xa3,0x47,0xa1,0x43,0xa1,0x4b,0xa0,0x3f,0x9c,0x48,0x98,0x41, 0x9a,0x4a,0x99,0x3d,0x98,0x46,0x99,0x3d,0x9a,0x45,0x9d,0x42,0x9e,0x47,0xa0,0x41, 0xa2,0x47,0xa2,0x40,0xa0,0x46,0x9f,0x3f,0x9c,0x4a,0x9a,0x3f,0x99,0x48,0x97,0x3f, 0x98,0x46,0x96,0x45,0x9a,0x4b,0x9c,0x3f,0x9f,0x45,0xa2,0x41,0xa4,0x4a,0xa1,0x42, 0xa3,0x4b,0xa2,0x3f,0x9d,0x48,0x9a,0x40,0x9c,0x4c,0x99,0x40,0x96,0x4c,0x96,0x41, 0x9b,0x49,0x9b,0x41,0x9e,0x49,0xa1,0x44,0xa4,0x4a,0xa3,0x3f,0xa4,0x4a,0xa2,0x3e, 0x9e,0x46,0x9c,0x3e,0x9a,0x4a,0x98,0x43,0x99,0x48,0x99,0x3d,0x9a,0x48,0x9a,0x40, 0x9d,0x4d,0xa1,0x3f,0xa2,0x4b,0x9f,0x40,0xa0,0x4b,0x9f,0x44,0x9d,0x46,0x98,0x3b, 0x97,0x48,0x96,0x41,0x96,0x46,0x95,0x45,0x96,0x4b,0x99,0x42,0x9d,0x49,0x9d,0x40, 0x9f,0x47,0x9f,0x42,0xa0,0x47,0x9c,0x40,0x9c,0x48,0x99,0x43,0x97,0x4a,0x97,0x3f, 0x97,0x4a,0x96,0x3d,0x96,0x48,0x99,0x3e,0x9c,0x49,0x9f,0x41,0xa1,0x44,0xa1,0x3f, 0xa2,0x48,0xa0,0x41,0x9f,0x48,0x9c,0x43,0x98,0x47,0x96,0x40,0x97,0x48,0x97,0x40, 0x99,0x4a,0x9a,0x41,0x9d,0x48,0xa0,0x3f,0xa3,0x44,0xa2,0x42,0xa2,0x4a,0xa2,0x3f, 0xa0,0x49,0x9d,0x3f,0x98,0x49,0x97,0x3f,0x96,0x4b,0x97,0x43,0x96,0x4b,0x95,0x41, 0x9b,0x49,0x9c,0x3e,0x9b,0x48,0x9e,0x43,0xa1,0x47,0x9e,0x43,0x9b,0x4a,0x9b,0x44, 0x97,0x4d,0x95,0x3d,0x97,0x4b,0x95,0x3c,0x96,0x4c,0x97,0x3f,0x9a,0x49,0x9d,0x43, 0x9e,0x4b,0xa2,0x3e,0xa0,0x47,0x9f,0x42,0xa0,0x4a,0x9e,0x40,0x99,0x47,0x97,0x43, 0x98,0x47,0x95,0x40,0x97,0x48,0x96,0x40,0x99,0x4b,0x9d,0x3e,0xa0,0x48,0xa0,0x41, 0xa1,0x4b,0x9f,0x40,0xa0,0x44,0x9e,0x3d,0x99,0x4d,0x97,0x40,0x98,0x47,0x97,0x43, 0x98,0x48,0x9a,0x3e,0x9b,0x49,0x9d,0x3c,0xa1,0x47,0xa1,0x42,0xa2,0x48,0xa0,0x3e, 0x9f,0x48,0x9d,0x40,0x9b,0x49,0x98,0x3f,0x98,0x47,0x98,0x41,0x99,0x49,0x98,0x42, 0x9a,0x46,0x9d,0x42,0xa0,0x46,0xa0,0x41,0xa2,0x4a,0xa1,0x3e,0xa1,0x48,0x9e,0x46, 0x9b,0x47,0x97,0x43,0x96,0x47,0x97,0x3d,0x96,0x4a,0x95,0x40,0x97,0x4a,0x9a,0x41, 0x9e,0x48,0x9f,0x41,0xa1,0x4b,0x9e,0x40,0x9f,0x48,0x9e,0x3f,0x9a,0x4a,0x98,0x3d, 0x96,0x4b,0x96,0x43,0x96,0x4a,0x95,0x3d,0x97,0x48,0x9c,0x3f,0x9f,0x47,0xa0,0x42, 0xa2,0x49,0xa0,0x42,0xa0,0x47,0x9c,0x40,0x9c,0x48,0x99,0x41,0x96,0x49,0x95,0x40, 0x94,0x49,0x95,0x43,0x97,0x47,0x9a,0x3d,0x9d,0x45,0xa0,0x42,0xa2,0x49,0xa1,0x42, 0xa2,0x4b,0x9f,0x41,0x9c,0x47,0x98,0x3d,0x99,0x4c,0x97,0x40,0x97,0x45,0x97,0x42, 0x99,0x46,0x9c,0x3e,0x9e,0x49,0x9f,0x3f,0xa1,0x48,0xa1,0x42,0xa0,0x4a,0x9f,0x40, 0x9e,0x48,0x99,0x3c,0x95,0x46,0x96,0x3f,0x97,0x47,0x94,0x40,0x95,0x49,0x99,0x41, 0x9e,0x4a,0xa0,0x44,0xa0,0x47,0xa2,0x3d,0xa2,0x4b,0x9e,0x3e,0x9c,0x44,0x99,0x40, 0x98,0x49,0x95,0x40,0x95,0x45,0x94,0x46,0x98,0x4b,0x99,0x3f,0x9d,0x41,0x9e,0x38, 0xa1,0x46,0xa1,0x40,0xa0,0x46,0x9d,0x40,0x9e,0x4b,0x96,0x44,0x9b,0x55,0x9a,0x52, 0x9b,0x58,0x9c,0x56,0x9d,0x60,0xa1,0x57,0xa4,0x60,0xa5,0x56,0xa6,0x5c,0xa6,0x53, 0xa6,0x57,0xa4,0x4e,0xa0,0x54,0x9e,0x4f,0x9c,0x5a,0x9b,0x52,0x9d,0x56,0x9b,0x50, 0x9d,0x58,0xa0,0x4d,0xa2,0x5b,0xa4,0x52,0xa7,0x5d,0xa6,0x4f,0xa4,0x57,0xa6,0x4d, 0xa2,0x59,0x9e,0x4e,0x9d,0x57,0x99,0x51,0x9a,0x5a,0x9b,0x4c,0x9a,0x55,0x9c,0x4f, 0xa0,0x59,0xa4,0x53,0xa4,0x58,0xa4,0x4f,0xa3,0x54,0xa4,0x4d,0x9f,0x57,0x9b,0x55, 0x9b,0x5a,0x9a,0x54,0x98,0x54,0x99,0x4e,0x99,0x58,0x9b,0x51,0xa0,0x5a,0xa2,0x50, 0xa4,0x5a,0xa5,0x4f,0xa5,0x56,0xa3,0x4d,0xa0,0x5b,0x9c,0x53,0x9b,0x57,0x99,0x50, 0x9b,0x58,0x99,0x4f,0x9a,0x5a,0x9b,0x50,0xa1,0x55,0xa2,0x51,0xa5,0x5d,0xa5,0x52, 0xa6,0x5a,0xa4,0x50,0xa1,0x57,0x9c,0x50,0x9b,0x58,0x98,0x50,0x98,0x59,0x98,0x53, 0x99,0x5a,0x9a,0x54,0x9d,0x5a,0xa0,0x50,0xa2,0x59,0xa4,0x4e,0xa5,0x5b,0xa1,0x52, 0xa0,0x5a,0x9d,0x50,0x99,0x56,0x97,0x4f,0x97,0x5b,0x96,0x52,0x96,0x58,0x98,0x53, 0x9b,0x57,0x9f,0x4f,0xa1,0x58,0xa2,0x53,0xa3,0x5a,0xa4,0x4c,0xa0,0x59,0x9d,0x51, 0x9d,0x5b,0x99,0x50,0x98,0x57,0x99,0x53,0x99,0x58,0x99,0x55,0x9a,0x56,0x9f,0x52, 0xa1,0x5a,0xa2,0x4c,0xa2,0x58,0xa2,0x55,0xa1,0x59,0x9b,0x52,0x9b,0x58,0x98,0x51, 0x99,0x57,0x99,0x4e,0x99,0x5a,0x99,0x53,0x9c,0x5e,0x9d,0x53,0xa0,0x58,0xa3,0x4d, 0xa3,0x5a,0xa1,0x51,0xa0,0x56,0x9d,0x50,0x9a,0x5a,0x97,0x4c,0x96,0x57,0x95,0x53, 0x96,0x5c,0x97,0x53,0x99,0x59,0x9c,0x50,0x9e,0x5b,0xa0,0x52,0xa2,0x5c,0xa1,0x55, 0x9e,0x56,0x9b,0x51,0x9a,0x57,0x97,0x51,0x97,0x5b,0x95,0x51,0x96,0x5c,0x95,0x50, 0x99,0x57,0x9c,0x53,0x9e,0x5a,0x9e,0x53,0xa1,0x5d,0xa1,0x51,0xa0,0x56,0x9c,0x54, 0x9b,0x5a,0x97,0x51,0x95,0x55,0x95,0x50,0x95,0x5a,0x95,0x4e,0x98,0x55,0x9a,0x51, 0x9e,0x5e,0x9f,0x4f,0xa0,0x55,0x9f,0x54,0x9f,0x58,0x9c,0x52,0x99,0x5b,0x97,0x54, 0x95,0x5e,0x92,0x51,0x94,0x58,0x95,0x52,0x98,0x58,0x9a,0x4c,0x9c,0x56,0x9e,0x57, 0x9e,0x5a,0x9e,0x53,0x9e,0x5c,0x9b,0x4f,0x98,0x58,0x95,0x52,0x94,0x56,0x92,0x52, 0x93,0x61,0x93,0x53,0x95,0x54,0x99,0x4e,0x9c,0x5d,0x9d,0x54,0x9d,0x59,0x9d,0x50, 0x9f,0x5f,0x9b,0x53,0x99,0x56,0x96,0x54,0x96,0x5e,0x94,0x4e,0x94,0x58,0x93,0x53, 0x96,0x5b,0x97,0x53,0x9a,0x58,0x9c,0x50,0x9e,0x5c,0x9e,0x4f,0x9e,0x59,0x99,0x52, 0x97,0x53,0x94,0x51,0x95,0x5c,0x90,0x50,0x91,0x59,0x92,0x54,0x94,0x58,0x95,0x51, 0x99,0x58,0x9c,0x57,0x9d,0x58,0x9e,0x52,0x9d,0x5a,0x9b,0x53,0x98,0x58,0x95,0x51, 0x93,0x5b,0x92,0x52,0x92,0x54,0x93,0x4f,0x93,0x56,0x92,0x51,0x97,0x57,0x9b,0x4f, 0x9a,0x57,0x9a,0x54,0x9c,0x59,0x99,0x51,0x99,0x5e,0x95,0x4e,0x94,0x5b,0x91,0x56, 0x90,0x5b,0x90,0x54,0x91,0x58,0x94,0x4f,0x96,0x57,0x99,0x51,0x9a,0x55,0x9c,0x4e, 0x9c,0x5d,0x99,0x55,0x97,0x58,0x94,0x51,0x91,0x5b,0x91,0x55,0x8f,0x5a,0x8f,0x52, 0x90,0x5e,0x92,0x54,0x95,0x58,0x97,0x52,0x9a,0x5b,0x9a,0x52,0x9b,0x59,0x99,0x53, 0x97,0x5a,0x94,0x52,0x92,0x55,0x91,0x54,0x90,0x5b,0x8f,0x56,0x8f,0x5d,0x90,0x51, 0x95,0x5a,0x96,0x57,0x98,0x5c,0x9b,0x4d,0x9a,0x5a,0x96,0x53,0x95,0x5b,0x95,0x56, 0x90,0x58,0x8d,0x53,0x8d,0x58,0x8d,0x56,0x8e,0x5b,0x8e,0x53,0x92,0x59,0x95,0x56, 0x98,0x55,0x98,0x52,0x99,0x57,0x96,0x52,0x95,0x5a,0x92,0x50,0x91,0x5b,0x8e,0x54, 0x8d,0x5a,0x8c,0x51,0x8e,0x57,0x8e,0x55,0x91,0x5c,0x93,0x4d,0x97,0x5b,0x96,0x51, 0x97,0x5a,0x97,0x53,0x96,0x55,0x93,0x4b,0x91,0x5a,0x8d,0x53,0x8c,0x5c,0x8a,0x51, 0x8d,0x5c,0x8d,0x55,0x8f,0x59,0x92,0x53,0x96,0x5d,0x96,0x52,0x98,0x5c,0x97,0x51, 0x97,0x60,0x94,0x56,0x92,0x5b,0x8d,0x52,0x8d,0x58,0x8d,0x4e,0x8d,0x5b,0x8d,0x51, 0x8f,0x5c,0x93,0x55,0x96,0x58,0x95,0x50,0x96,0x5a,0x97,0x54,0x97,0x59,0x92,0x51, 0x90,0x5e,0x90,0x53,0x8e,0x58,0x8c,0x52,0x8d,0x59,0x8e,0x54,0x90,0x58,0x93,0x52, 0x97,0x5a,0x98,0x50,0x9a,0x5a,0x9b,0x4e,0x9a,0x5a,0x97,0x51,0x95,0x5b,0x92,0x53, 0x90,0x58,0x90,0x53,0x90,0x53,0x90,0x4f,0x92,0x5c,0x94,0x53,0x97,0x59,0x99,0x50, 0x9b,0x5a,0x9a,0x52,0x9a,0x59,0x97,0x4e,0x95,0x59,0x91,0x51,0x90,0x5d,0x8f,0x4e, 0x8f,0x5a,0x8f,0x53,0x92,0x5b,0x93,0x52,0x96,0x5b,0x97,0x52,0x9a,0x59,0x9a,0x4f, 0x9a,0x5c,0x98,0x57,0x95,0x57,0x91,0x56,0x8f,0x5b,0x8d,0x51,0x8e,0x5b,0x8f,0x4f, 0x90,0x56,0x93,0x53,0x96,0x57,0x97,0x52,0x99,0x5a,0x9a,0x50,0x9a,0x5a,0x96,0x51, 0x96,0x58,0x94,0x52,0x8f,0x58,0x8d,0x52,0x8d,0x5a,0x8c,0x4f,0x8f,0x5b,0x92,0x50, 0x97,0x5b,0x98,0x4f,0x99,0x5c,0x9a,0x50,0x99,0x56,0x98,0x54,0x96,0x58,0x92,0x53, 0x92,0x59,0x8f,0x51,0x8e,0x5a,0x8f,0x4f,0x92,0x5a,0x93,0x54,0x98,0x5a,0x99,0x54, 0x9b,0x59,0x9c,0x51,0x9d,0x5c,0x9a,0x4f,0x97,0x5e,0x94,0x50,0x91,0x5b,0x8f,0x50, 0x90,0x56,0x91,0x4e,0x91,0x59,0x93,0x55,0x96,0x5a,0x9a,0x56,0x9d,0x59,0x9d,0x53, 0x9d,0x57,0x9b,0x50,0x99,0x5d,0x95,0x52,0x90,0x5d,0x8f,0x4f,0x8e,0x5a,0x8f,0x4a, 0x92,0x5b,0x92,0x52,0x97,0x5e,0x9b,0x53,0x9d,0x5f,0x9c,0x53,0x9e,0x56,0x9c,0x50, 0x9c,0x5b,0x99,0x4e,0x95,0x5a,0x93,0x50,0x94,0x5d,0x92,0x52,0x93,0x5a,0x95,0x55, 0x98,0x5a,0x9a,0x4f,0x9d,0x51,0x9c,0x48,0x9e,0x5a,0x9c,0x50,0x9b,0x57,0x99,0x4f, 0x97,0x59,0x90,0x57,0x99,0x4c,0x98,0x46,0x98,0x51,0x9c,0x4e,0xa0,0x5c,0xa2,0x4e, 0xa4,0x53,0xa4,0x4d,0xa2,0x52,0xa0,0x46,0x9f,0x56,0x9c,0x47,0x98,0x51,0x99,0x4b, 0x97,0x51,0x99,0x48,0x99,0x52,0x99,0x48,0x9e,0x53,0xa0,0x47,0xa0,0x50,0xa2,0x47, 0xa3,0x50,0x9f,0x46,0x9d,0x51,0x9b,0x4a,0x98,0x52,0x96,0x4b,0x97,0x4f,0x97,0x46, 0x97,0x50,0x9b,0x48,0x9d,0x52,0x9f,0x48,0xa2,0x52,0xa4,0x46,0xa3,0x54,0xa1,0x48, 0x9e,0x52,0x9c,0x46,0x99,0x4c,0x96,0x47,0x97,0x53,0x96,0x4c,0x98,0x4d,0x9a,0x4a, 0x9c,0x4f,0x9e,0x49,0xa0,0x54,0xa2,0x4c,0xa2,0x50,0xa2,0x4a,0xa0,0x50,0x9d,0x4b, 0x99,0x51,0x96,0x4a,0x94,0x51,0x96,0x49,0x95,0x50,0x97,0x48,0x9b,0x4f,0x9e,0x49, 0xa0,0x4f,0xa1,0x48,0xa2,0x4f,0xa1,0x4f,0x9f,0x55,0x9b,0x4c,0x98,0x50,0x96,0x4c, 0x96,0x4a,0x95,0x4b,0x96,0x52,0x96,0x4d,0x9a,0x53,0x9f,0x46,0xa0,0x51,0xa1,0x47, 0xa4,0x4f,0xa2,0x49,0xa1,0x4f,0x9c,0x4c,0x99,0x56,0x96,0x48,0x96,0x51,0x95,0x49, 0x97,0x4f,0x97,0x4c,0x99,0x54,0x9d,0x45,0x9e,0x53,0xa1,0x4a,0xa3,0x4e,0xa0,0x48, 0x9e,0x52,0x9c,0x4b,0x9a,0x4d,0x95,0x4d,0x94,0x52,0x94,0x4a,0x95,0x4d,0x95,0x49, 0x97,0x50,0x9c,0x49,0x9e,0x51,0x9d,0x4a,0x9f,0x54,0xa1,0x4a,0x9e,0x51,0x9a,0x46, 0x99,0x50,0x95,0x48,0x95,0x51,0x95,0x47,0x94,0x54,0x95,0x4a,0x97,0x51,0x9a,0x49, 0x9c,0x50,0xa0,0x4a,0xa0,0x4f,0x9e,0x48,0x9f,0x57,0x9c,0x4a,0x99,0x53,0x96,0x46, 0x95,0x51,0x95,0x47,0x93,0x52,0x95,0x4b,0x96,0x50,0x9a,0x48,0x9d,0x54,0x9e,0x4a, 0xa0,0x51,0xa0,0x49,0x9e,0x52,0x9c,0x4a,0x99,0x56,0x97,0x49,0x95,0x50,0x95,0x4b, 0x94,0x51,0x94,0x4a,0x97,0x4c,0x99,0x4a,0x9d,0x4f,0x9e,0x46,0xa0,0x53,0x9f,0x4e, 0x9f,0x55,0x9c,0x4d,0x9a,0x4e,0x97,0x45,0x94,0x53,0x95,0x4d,0x94,0x53,0x95,0x47, 0x96,0x54,0x99,0x4b,0x9c,0x51,0x9d,0x48,0xa0,0x58,0xa0,0x4d,0x9e,0x4f,0x9c,0x46, 0x9a,0x53,0x95,0x4a,0x92,0x4f,0x91,0x49,0x91,0x54,0x92,0x48,0x92,0x52,0x95,0x4e, 0x99,0x54,0x9c,0x49,0x9d,0x51,0x9d,0x48,0x9d,0x50,0x9d,0x4a,0x9a,0x53,0x95,0x4a, 0x93,0x50,0x92,0x46,0x90,0x51,0x92,0x4a,0x94,0x58,0x97,0x4c,0x99,0x51,0x9d,0x4c, 0x9d,0x50,0x9e,0x4a,0x9e,0x4d,0x9b,0x47,0x98,0x54,0x95,0x4d,0x93,0x52,0x92,0x48, 0x91,0x51,0x91,0x47,0x93,0x51,0x96,0x48,0x99,0x56,0x9b,0x4c,0x9d,0x55,0x9e,0x4a, 0x9d,0x50,0x9c,0x46,0x9a,0x4f,0x96,0x49,0x94,0x57,0x92,0x47,0x91,0x4e,0x91,0x47, 0x94,0x4e,0x95,0x47,0x97,0x50,0x9a,0x47,0x9c,0x52,0x9e,0x47,0x9d,0x55,0x9c,0x4b, 0x99,0x51,0x97,0x49,0x93,0x50,0x91,0x4b,0x90,0x55,0x91,0x4a,0x91,0x4e,0x93,0x4b, 0x98,0x4f,0x99,0x48,0x9a,0x54,0x9b,0x45,0x9d,0x4e,0x9a,0x46,0x97,0x54,0x94,0x4a, 0x91,0x55,0x8f,0x4c,0x8e,0x54,0x8f,0x46,0x90,0x59,0x91,0x4c,0x96,0x53,0x99,0x47, 0x9b,0x53,0x9c,0x4c,0x9b,0x53,0x9a,0x48,0x98,0x55,0x96,0x4b,0x92,0x4f,0x90,0x49, 0x90,0x52,0x91,0x4f,0x91,0x52,0x92,0x4c,0x95,0x52,0x96,0x52,0x99,0x51,0x99,0x49, 0x9b,0x54,0x9a,0x4a,0x98,0x52,0x95,0x45,0x92,0x57,0x8f,0x4c,0x8f,0x54,0x8f,0x4a, 0x8e,0x51,0x91,0x4b,0x92,0x50,0x97,0x4b,0x9a,0x56,0x9b,0x4c,0x99,0x56,0x9b,0x4c, 0x9a,0x53,0x96,0x4c,0x93,0x52,0x90,0x48,0x8f,0x57,0x8e,0x49,0x8e,0x51,0x91,0x4c, 0x93,0x50,0x95,0x4a,0x99,0x4f,0x9a,0x49,0x9c,0x58,0x9b,0x47,0x99,0x4d,0x98,0x4a, 0x94,0x50,0x91,0x49,0x8f,0x53,0x8f,0x4c,0x8e,0x55,0x91,0x4a,0x94,0x56,0x96,0x49, 0x98,0x52,0x9c,0x4b,0x9c,0x53,0x9b,0x4c,0x99,0x56,0x99,0x48,0x95,0x4e,0x90,0x48, 0x8f,0x56,0x90,0x49,0x90,0x4f,0x92,0x49,0x95,0x5c,0x96,0x4c,0x99,0x4f,0x9a,0x4b, 0x9c,0x52,0x9d,0x4c,0x9b,0x4f,0x99,0x4a,0x95,0x53,0x93,0x4b,0x92,0x4f,0x90,0x4c, 0x90,0x53,0x92,0x47,0x94,0x54,0x96,0x4b,0x9a,0x4e,0x9c,0x4e,0x9d,0x54,0x9b,0x49, 0x9b,0x4f,0x99,0x4c,0x96,0x53,0x92,0x4c,0x8e,0x54,0x8f,0x48,0x91,0x54,0x91,0x4a, 0x92,0x53,0x97,0x4a,0x9b,0x50,0x9e,0x4a,0x9f,0x4f,0x9c,0x4a,0x9b,0x54,0x9b,0x47, 0x99,0x52,0x95,0x4b,0x93,0x55,0x92,0x4a,0x92,0x55,0x93,0x4d,0x93,0x54,0x98,0x4c, 0x9a,0x52,0x9d,0x4b,0x9e,0x51,0x9d,0x48,0x9e,0x57,0x9c,0x4c,0x9a,0x53,0x97,0x4b, 0x95,0x54,0x95,0x4e,0x94,0x4d,0x95,0x48,0x96,0x56,0x98,0x4a,0x9c,0x53,0x9f,0x47, 0xa0,0x54,0xa0,0x4c,0x9e,0x51,0x9f,0x49,0x9b,0x51,0x98,0x4a,0x96,0x52,0x94,0x4a, 0x93,0x55,0x94,0x4b,0x95,0x4b,0x98,0x46,0x9b,0x57,0x9d,0x4a,0xa0,0x4f,0x9f,0x49, 0x9e,0x54,0x9d,0x50,0x9a,0x50,0x97,0x4c,0x96,0x55,0x95,0x4b,0x93,0x53,0x94,0x49, 0x95,0x53,0x99,0x4c,0x9c,0x54,0xa0,0x45,0xa1,0x56,0xa1,0x4c,0xa1,0x4f,0x9f,0x4b, 0x9c,0x56,0x9a,0x4b,0x96,0x50,0x95,0x4e,0x95,0x55,0x94,0x4b,0x96,0x4e,0x98,0x49, 0x9b,0x53,0x9e,0x4d,0x9f,0x51,0xa0,0x48,0xa1,0x5b,0x9e,0x46,0x9e,0x59,0x9a,0x47, 0x97,0x56,0x94,0x46,0x96,0x4d,0x96,0x4a,0x96,0x59,0x97,0x4c,0x98,0x52,0x9b,0x4c, 0xa0,0x53,0x9f,0x4d,0x9e,0x4f,0x9d,0x4c,0x9e,0x52,0x99,0x4a,0x95,0x53,0x95,0x42, 0x96,0x55,0x96,0x4d,0x96,0x52,0x96,0x48,0x9b,0x58,0x9e,0x4a,0xa1,0x53,0xa2,0x4b, 0xa1,0x55,0xa0,0x49,0x9f,0x4f,0x9d,0x4d,0x98,0x54,0x96,0x4d,0x96,0x54,0x95,0x4a, 0x96,0x55,0x98,0x4e,0x9a,0x4f,0x9d,0x4d,0xa1,0x55,0xa2,0x45,0xa1,0x4a,0xa0,0x41, 0x9f,0x4f,0x9c,0x47,0x9a,0x4f,0x95,0x48,0x95,0x57,0x93,0x4f,0x9c,0x33,0x9e,0x33, 0xa3,0x38,0xa6,0x3b,0xa7,0x48,0xa8,0x3a,0xa8,0x48,0xa8,0x3a,0xa3,0x3b,0x9f,0x33, 0x9d,0x40,0x9c,0x35,0x99,0x3c,0x9a,0x34,0x9d,0x3f,0x9f,0x35,0xa3,0x3d,0xa4,0x34, 0xa8,0x41,0xa8,0x34,0xa8,0x3e,0xa7,0x36,0xa5,0x41,0xa2,0x36,0x9e,0x3c,0x9c,0x39, 0x9c,0x3a,0x9c,0x36,0x9f,0x39,0xa0,0x34,0xa4,0x3f,0xa8,0x35,0xaa,0x39,0xaa,0x33, 0xac,0x3e,0xab,0x33,0xa9,0x37,0xa4,0x32,0xa3,0x3e,0xa1,0x3b,0xa0,0x3d,0xa1,0x35, 0xa0,0x3e,0xa0,0x37,0xa4,0x3a,0xa8,0x31,0xa9,0x43,0xab,0x35,0xab,0x3d,0xaa,0x35, 0xaa,0x3b,0xa5,0x35,0xa1,0x3c,0x9f,0x32,0xa0,0x3f,0xa1,0x37,0xa0,0x3e,0x9f,0x32, 0xa3,0x38,0xa5,0x32,0xaa,0x3a,0xa9,0x35,0xab,0x3b,0xab,0x34,0xa7,0x38,0xa4,0x32, 0xa3,0x3d,0xa1,0x35,0x9f,0x3a,0x9f,0x34,0xa1,0x42,0xa1,0x35,0xa4,0x3e,0xa8,0x32, 0xab,0x3b,0xaa,0x36,0xad,0x3a,0xac,0x35,0xab,0x41,0xa8,0x31,0xa4,0x3f,0xa1,0x36, 0xa2,0x3b,0x9f,0x36,0xa0,0x3b,0xa1,0x38,0xa3,0x40,0xa7,0x36,0xaa,0x3b,0xaa,0x39, 0xad,0x3e,0xaa,0x35,0xaa,0x3c,0xa7,0x37,0xa4,0x3f,0x9f,0x33,0x9e,0x3b,0x9d,0x37, 0x9f,0x3d,0x9e,0x33,0xa2,0x3f,0xa5,0x37,0xa7,0x3b,0xaa,0x37,0xab,0x35,0xaa,0x38, 0xa7,0x41,0xa6,0x34,0xa3,0x3e,0x9f,0x35,0x9e,0x3b,0x9c,0x32,0x9d,0x40,0x9d,0x34, 0xa0,0x3c,0xa4,0x35,0xa6,0x3a,0xa9,0x38,0xa9,0x40,0xa9,0x30,0xa9,0x3e,0xa7,0x36, 0xa4,0x3f,0xa0,0x37,0x9f,0x3a,0x9d,0x33,0x9d,0x3d,0x9b,0x36,0x9f,0x3e,0xa4,0x33, 0xa5,0x3c,0xa6,0x37,0xa9,0x3b,0xaa,0x35,0xa7,0x40,0xa6,0x32,0xa4,0x37,0xa1,0x39, 0x9f,0x3d,0x9e,0x35,0x9e,0x37,0x9d,0x32,0xa0,0x43,0xa2,0x34,0xa6,0x3d,0xa9,0x38, 0xaa,0x41,0xaa,0x38,0xaa,0x3e,0xa7,0x35,0xa5,0x3d,0xa2,0x31,0xa0,0x3a,0x9e,0x36, 0x9e,0x3b,0x9f,0x38,0xa1,0x3a,0xa4,0x36,0xa6,0x3f,0xa8,0x35,0xab,0x3b,0xab,0x32, 0xab,0x3e,0xa9,0x33,0xa6,0x3e,0xa2,0x33,0xa0,0x43,0x9f,0x32,0x9f,0x3b,0x9f,0x39, 0xa0,0x3c,0xa0,0x36,0xa6,0x39,0xa8,0x37,0xab,0x42,0xaa,0x35,0xaa,0x3c,0xa8,0x31, 0xa5,0x3d,0xa1,0x37,0xa0,0x3c,0x9e,0x32,0x9d,0x40,0x9d,0x34,0x9f,0x3f,0xa2,0x33, 0xa5,0x3a,0xa8,0x39,0xab,0x39,0xab,0x35,0xaa,0x40,0xaa,0x34,0xa9,0x3d,0xa3,0x35, 0xa3,0x3f,0x9e,0x35,0x9e,0x3e,0x9f,0x34,0x9f,0x43,0xa0,0x32,0xa7,0x3f,0xa8,0x31, 0xab,0x3d,0xab,0x32,0xab,0x41,0xa9,0x38,0xa5,0x3d,0xa2,0x38,0x9f,0x3b,0x9c,0x35, 0x9c,0x3b,0x9d,0x32,0x9d,0x3d,0x9f,0x34,0xa3,0x43,0xa7,0x37,0xa8,0x3c,0xaa,0x38, 0xab,0x3d,0xa9,0x34,0xa6,0x3b,0xa4,0x37,0x9f,0x40,0x9c,0x33,0x9d,0x39,0x9c,0x34, 0x9d,0x3d,0xa0,0x32,0xa3,0x3a,0xa6,0x37,0xa9,0x42,0xaa,0x35,0xaa,0x3e,0xa8,0x31, 0xa8,0x3d,0xa5,0x36,0xa2,0x3c,0xa0,0x37,0x9e,0x3d,0x9e,0x36,0x9e,0x43,0xa0,0x35, 0xa2,0x43,0xa6,0x37,0xa9,0x39,0xa9,0x34,0xaa,0x40,0xa9,0x36,0xa8,0x3d,0xa5,0x3a, 0xa3,0x3d,0x9d,0x38,0x9d,0x3d,0x9d,0x34,0x9e,0x40,0x9e,0x38,0xa1,0x42,0xa4,0x34, 0xa9,0x3e,0xa8,0x37,0xaa,0x3b,0xaa,0x35,0xa9,0x45,0xa4,0x38,0xa1,0x3c,0x9f,0x36, 0x9e,0x3f,0x9d,0x35,0x9e,0x3e,0x9e,0x38,0x9f,0x41,0xa4,0x36,0xa6,0x3e,0xa8,0x38, 0xaa,0x3b,0xaa,0x37,0xa7,0x3e,0xa4,0x38,0xa0,0x41,0x9e,0x39,0x9d,0x3c,0x9d,0x38, 0x9c,0x44,0x9d,0x34,0xa1,0x3c,0xa4,0x35,0xa8,0x42,0xa6,0x38,0xa8,0x3f,0xa8,0x37, 0xa8,0x3e,0xa2,0x36,0x9f,0x3f,0x9e,0x38,0x9b,0x42,0x99,0x36,0x9a,0x41,0x9e,0x37, 0x9e,0x40,0xa1,0x39,0xa4,0x3d,0xa6,0x37,0xa8,0x42,0xa8,0x3a,0xa5,0x3e,0xa3,0x37, 0xa1,0x3f,0x9b,0x34,0x9c,0x38,0x9a,0x39,0x9a,0x40,0x9a,0x35,0x9e,0x3c,0xa0,0x33, 0xa5,0x3d,0xa6,0x3a,0xa7,0x3c,0xa8,0x38,0xa7,0x40,0xa4,0x3a,0xa1,0x38,0x9f,0x35, 0x9d,0x41,0x9d,0x39,0x9c,0x3c,0x9b,0x34,0x9c,0x40,0x9f,0x36,0xa3,0x3c,0xa5,0x37, 0xa7,0x3d,0xa7,0x37,0xa6,0x39,0xa3,0x38,0xa3,0x41,0x9f,0x38,0x9c,0x3f,0x9c,0x37, 0x9e,0x3f,0x9d,0x38,0x9e,0x3b,0xa0,0x38,0xa4,0x43,0xa7,0x37,0xa8,0x3f,0xa8,0x35, 0xa9,0x40,0xa6,0x37,0xa5,0x3e,0xa1,0x35,0x9e,0x3e,0x9c,0x35,0x9b,0x40,0x9c,0x33, 0x9d,0x40,0x9f,0x32,0xa2,0x3c,0xa3,0x34,0xa7,0x45,0xa8,0x37,0xa5,0x41,0xa5,0x34, 0xa5,0x3c,0x9f,0x38,0x9e,0x3b,0x9c,0x36,0x9c,0x42,0x9b,0x3a,0x9b,0x40,0x9f,0x37, 0xa2,0x41,0xa6,0x37,0xa9,0x3d,0xaa,0x36,0xa9,0x42,0xa7,0x38,0xa5,0x40,0xa1,0x37, 0xa0,0x41,0x9e,0x36,0x9c,0x3b,0x9d,0x30,0x9e,0x3f,0x9e,0x34,0xa3,0x3d,0xa5,0x36, 0xa7,0x40,0xa7,0x32,0xa8,0x3d,0xa6,0x30,0xa4,0x42,0xa1,0x33,0x9e,0x41,0x9e,0x36, 0x9e,0x3d,0x9d,0x35,0x9d,0x41,0xa0,0x37,0xa3,0x40,0xa6,0x3b,0xaa,0x3e,0xaa,0x37, 0xaa,0x3e,0xa8,0x32,0xa5,0x43,0xa3,0x37,0x9f,0x3f,0x9d,0x37,0x9d,0x3c,0x9c,0x35, 0x9d,0x3f,0x9f,0x32,0xa2,0x3e,0xa6,0x35,0xa8,0x3f,0xa8,0x36,0xaa,0x3d,0xa9,0x36, 0xa6,0x40,0xa2,0x3b,0xa1,0x3c,0x9d,0x36,0x9c,0x3e,0x9c,0x36,0x9a,0x43,0x9c,0x35, 0xa0,0x41,0xa4,0x35,0xa5,0x3c,0xa6,0x34,0xa8,0x46,0xa7,0x38,0xa5,0x3a,0xa3,0x36, 0xa1,0x42,0x9e,0x37,0x9e,0x3f,0x9e,0x34,0x9a,0x40,0x9c,0x36,0xa2,0x42,0xa4,0x35, 0xa4,0x3c,0xa8,0x37,0xab,0x3c,0xa8,0x39,0xa6,0x42,0xa4,0x37,0xa1,0x40,0xa1,0x3a, 0x9f,0x3e,0x9e,0x36,0xa0,0x3e,0xa0,0x35,0xa2,0x42,0xa4,0x34,0xa8,0x3e,0xa8,0x3d, 0xaa,0x44,0xaa,0x37,0xa7,0x31,0xa5,0x2c,0xa3,0x38,0xa0,0x32,0x9f,0x3b,0x9d,0x37, 0x9c,0x40,0x9a,0x3d,0xa7,0x4d,0xaa,0x3f,0xaf,0x4f,0xae,0x4b,0xaf,0x58,0xad,0x52, 0xab,0x51,0xa9,0x48,0xa6,0x4f,0xa4,0x49,0xa1,0x51,0xa2,0x45,0xa4,0x4a,0xa6,0x49, 0xa9,0x4a,0xac,0x45,0xae,0x4f,0xb0,0x41,0xb1,0x4d,0xaf,0x44,0xad,0x4a,0xaa,0x47, 0xa7,0x52,0xa4,0x46,0xa4,0x4e,0xa4,0x44,0xa4,0x54,0xa6,0x48,0xa9,0x4c,0xac,0x47, 0xaf,0x4a,0xb1,0x47,0xb2,0x4f,0xaf,0x4d,0xae,0x52,0xac,0x47,0xa9,0x4c,0xa6,0x46, 0xa6,0x50,0xa4,0x44,0xa7,0x4e,0xa5,0x42,0xa7,0x50,0xac,0x44,0xad,0x4c,0xaf,0x45, 0xad,0x50,0xaf,0x46,0xac,0x50,0xab,0x41,0xaa,0x4f,0xa5,0x45,0xa4,0x50,0xa3,0x46, 0xa6,0x4e,0xa3,0x43,0xa6,0x4e,0xaa,0x46,0xac,0x50,0xaf,0x47,0xb2,0x4e,0xb0,0x44, 0xae,0x4d,0xaa,0x43,0xab,0x4c,0xa4,0x45,0xa2,0x4e,0xa2,0x46,0xa5,0x48,0xa4,0x47, 0xa8,0x4c,0xac,0x4a,0xb0,0x4e,0xb1,0x48,0xb2,0x4e,0xb2,0x48,0xb1,0x4d,0xae,0x47, 0xaa,0x52,0xa8,0x46,0xa8,0x49,0xa4,0x42,0xa4,0x50,0xa5,0x43,0xa8,0x4d,0xaa,0x46, 0xac,0x4f,0xaf,0x49,0xb1,0x4a,0xae,0x47,0xaf,0x50,0xb0,0x48,0xab,0x4c,0xa8,0x46, 0xa8,0x4e,0xa7,0x3f,0xa7,0x4d,0xa6,0x44,0xab,0x4e,0xad,0x47,0xb0,0x4e,0xb1,0x43, 0xb5,0x4d,0xb5,0x47,0xb5,0x4a,0xb3,0x44,0xae,0x4a,0xaa,0x47,0xaa,0x4d,0xa7,0x49, 0xa4,0x4f,0xa4,0x46,0xa9,0x4c,0xaa,0x47,0xac,0x50,0xb2,0x49,0xb4,0x4f,0xb3,0x46, 0xb5,0x4d,0xb2,0x45,0xb0,0x4a,0xac,0x42,0xaa,0x4c,0xaa,0x41,0xac,0x4e,0xa9,0x47, 0xab,0x4e,0xad,0x46,0xb0,0x4f,0xb4,0x47,0xb5,0x4d,0xb4,0x45,0xb5,0x4c,0xb4,0x46, 0xb2,0x4e,0xad,0x47,0xac,0x4c,0xab,0x45,0xaa,0x50,0xa8,0x45,0xac,0x4f,0xad,0x4b, 0xb0,0x4d,0xb0,0x4a,0xb3,0x4c,0xb4,0x48,0xb3,0x4e,0xb1,0x43,0xb1,0x4e,0xac,0x46, 0xab,0x4c,0xaa,0x44,0xa9,0x50,0xa8,0x43,0xaa,0x54,0xab,0x49,0xb0,0x4f,0xb2,0x47, 0xb6,0x4e,0xb6,0x4b,0xb7,0x4f,0xb6,0x4a,0xb3,0x4f,0xaf,0x47,0xac,0x4c,0xa9,0x47, 0xaa,0x50,0xa7,0x47,0xa9,0x49,0xaa,0x46,0xaf,0x50,0xb2,0x45,0xb4,0x4b,0xb4,0x48, 0xb6,0x4c,0xb2,0x47,0xaf,0x4b,0xab,0x47,0xaa,0x4f,0xa7,0x45,0xa6,0x4b,0xa7,0x49, 0xa9,0x4f,0xaa,0x46,0xaf,0x49,0xb1,0x4a,0xb5,0x4e,0xb6,0x47,0xb7,0x4f,0xb4,0x44, 0xb1,0x4e,0xaf,0x4b,0xac,0x4a,0xa8,0x43,0xaa,0x4f,0xa9,0x46,0xab,0x4f,0xaa,0x46, 0xad,0x50,0xb0,0x44,0xb5,0x4b,0xb4,0x46,0xb5,0x52,0xb5,0x46,0xb6,0x4c,0xb0,0x45, 0xac,0x50,0xac,0x44,0xac,0x4a,0xa7,0x43,0xa9,0x4e,0xac,0x47,0xae,0x4c,0xb0,0x45, 0xb5,0x4f,0xb6,0x49,0xb6,0x4e,0xb5,0x41,0xb5,0x4e,0xb0,0x46,0xae,0x4b,0xab,0x46, 0xa8,0x53,0xa9,0x43,0xa8,0x4e,0xa8,0x45,0xab,0x49,0xad,0x48,0xb2,0x4d,0xb5,0x4a, 0xb5,0x50,0xb5,0x44,0xb4,0x4f,0xb0,0x42,0xad,0x4a,0xaa,0x46,0xa7,0x4b,0xa6,0x49, 0xa7,0x4d,0xa7,0x43,0xa9,0x4d,0xad,0x45,0xb2,0x50,0xb2,0x48,0xb4,0x4b,0xb5,0x49, 0xb4,0x4e,0xad,0x46,0xab,0x50,0xaa,0x45,0xa7,0x4f,0xa6,0x44,0xa7,0x4d,0xa9,0x4a, 0xaa,0x50,0xae,0x4a,0xb3,0x4d,0xb3,0x4a,0xb4,0x4e,0xb4,0x49,0xb3,0x4a,0xb0,0x49, 0xae,0x4c,0xab,0x46,0xa9,0x4c,0xa6,0x45,0xa7,0x51,0xa8,0x47,0xa9,0x4c,0xac,0x43, 0xb0,0x4f,0xb2,0x47,0xb3,0x50,0xb3,0x40,0xb3,0x53,0xb2,0x4a,0xaf,0x51,0xab,0x46, 0xaa,0x4c,0xab,0x49,0xab,0x4f,0xa9,0x47,0xaa,0x4d,0xae,0x46,0xb1,0x4d,0xb0,0x44, 0xb3,0x52,0xb2,0x4b,0xb0,0x4f,0xad,0x45,0xad,0x4f,0xaa,0x46,0xa6,0x4c,0xa7,0x49, 0xa6,0x4e,0xa4,0x45,0xa7,0x55,0xab,0x46,0xac,0x4e,0xad,0x41,0xb2,0x54,0xb2,0x47, 0xb1,0x4e,0xaf,0x46,0xad,0x4f,0xa8,0x45,0xa7,0x50,0xa6,0x48,0xa5,0x4a,0xa4,0x45, 0xa7,0x52,0xa9,0x47,0xad,0x4d,0xae,0x47,0xb1,0x4d,0xb0,0x47,0xaf,0x4c,0xab,0x44, 0xaa,0x50,0xa8,0x47,0xa7,0x4b,0xa5,0x47,0xa8,0x4e,0xa7,0x49,0xa7,0x4b,0xaa,0x44, 0xae,0x4f,0xaf,0x46,0xb2,0x4d,0xb3,0x45,0xb2,0x50,0xb1,0x47,0xb0,0x4c,0xab,0x47, 0xa9,0x4c,0xa6,0x48,0xa5,0x4c,0xa6,0x49,0xa6,0x4e,0xa6,0x44,0xac,0x4c,0xae,0x49, 0xaf,0x4b,0xb0,0x49,0xb1,0x4c,0xaf,0x41,0xad,0x52,0xab,0x47,0xa9,0x4f,0xa6,0x48, 0xa6,0x50,0xa8,0x46,0xa8,0x4b,0xa7,0x46,0xab,0x53,0xaf,0x47,0xb2,0x4d,0xb1,0x43, 0xb2,0x4e,0xb1,0x47,0xae,0x50,0xaa,0x45,0xa7,0x53,0xa5,0x47,0xa6,0x4d,0xa4,0x4a, 0xa5,0x4d,0xa7,0x47,0xab,0x50,0xae,0x44,0xb0,0x50,0xb4,0x47,0xb3,0x4f,0xb1,0x49, 0xb1,0x4d,0xaf,0x46,0xaa,0x4c,0xa6,0x47,0xa8,0x4b,0xa7,0x45,0xa7,0x4f,0xa7,0x48, 0xab,0x4c,0xad,0x49,0xb0,0x4b,0xb1,0x48,0xb0,0x53,0xb0,0x47,0xaf,0x4f,0xad,0x44, 0xaa,0x50,0xa7,0x46,0xa7,0x4a,0xa6,0x47,0xa0,0x50,0xa1,0x46,0xaa,0x4b,0xac,0x45, 0xac,0x4e,0xae,0x46,0xb5,0x4a,0xb2,0x41,0xb1,0x4e,0xaf,0x46,0xac,0x4b,0xa9,0x45, 0xab,0x4f,0xa7,0x48,0x9e,0x4a,0x9f,0x43,0xad,0x4e,0xa5,0x45,0xa2,0x52,0xb1,0x47, 0xb5,0x4d,0xaf,0x48,0xb1,0x4d,0xae,0x42,0xab,0x51,0xa8,0x43,0xa8,0x4f,0xa9,0x47, 0xa9,0x4d,0xa8,0x48,0xaa,0x4c,0xab,0x47,0xaf,0x4f,0xb2,0x49,0xb4,0x4c,0xb0,0x46, 0xb1,0x4c,0xb0,0x49,0xab,0x4a,0xa7,0x44,0xa7,0x4e,0xa7,0x46,0xa6,0x4c,0xa5,0x47, 0xa8,0x4a,0xaa,0x44,0xac,0x4b,0xaf,0x49,0xb1,0x51,0xb0,0x46,0xb0,0x4e,0xac,0x46, 0xab,0x4f,0xa9,0x49,0xa5,0x4d,0xa5,0x43,0xa7,0x52,0xa6,0x46,0xa8,0x4a,0xa9,0x42, 0xae,0x4c,0xb0,0x46,0xb1,0x50,0xaf,0x48,0xb1,0x4f,0xad,0x42,0xa9,0x45,0xa6,0x3f, 0xa4,0x50,0xa2,0x47,0xa3,0x4e,0xa4,0x46,0xa6,0x4d,0xa4,0x4a,0xb5,0x1c,0xb6,0x0f, 0xb7,0x1d,0xb6,0x17,0xb6,0x28,0xb1,0x19,0xae,0x20,0xab,0x13,0xaa,0x1d,0xa7,0x14, 0xa9,0x1e,0xa8,0x16,0xa8,0x1c,0xab,0x12,0xb1,0x1c,0xb0,0x14,0xb2,0x1e,0xb3,0x17, 0xb2,0x20,0xaf,0x17,0xac,0x1a,0xa9,0x13,0xa8,0x1f,0xa5,0x12,0xa7,0x1f,0xa7,0x17, 0xaa,0x1b,0xad,0x11,0xb1,0x1b,0xb1,0x15,0xb4,0x20,0xb4,0x14,0xb2,0x1c,0xb0,0x14, 0xac,0x20,0xa8,0x15,0xa4,0x1a,0xa3,0x15,0xa4,0x1b,0xa3,0x19,0xa5,0x19,0xa9,0x14, 0xae,0x1d,0xb0,0x13,0xb1,0x1d,0xb1,0x15,0xb1,0x1e,0xae,0x13,0xaa,0x16,0xa6,0x15, 0xa6,0x1d,0xa4,0x10,0xa4,0x1a,0xa5,0x16,0xa7,0x1d,0xa6,0x14,0xab,0x19,0xae,0x14, 0xad,0x1c,0xad,0x11,0xae,0x1d,0xa7,0x14,0xa7,0x19,0xa3,0x18,0x9f,0x1b,0x9e,0x18, 0x9c,0x1a,0x9f,0x0f,0xa3,0x18,0xa2,0x0f,0xa6,0x19,0xaa,0x15,0xae,0x19,0xaf,0x17, 0xae,0x19,0xac,0x15,0xaa,0x1f,0xa6,0x13,0xa4,0x19,0xa2,0x16,0xa4,0x1d,0xa3,0x13, 0xa3,0x1d,0xa3,0x11,0xaa,0x1b,0xaa,0x12,0xad,0x1e,0xae,0x14,0xaf,0x1c,0xaa,0x14, 0xaa,0x1c,0xa6,0x13,0xa3,0x1d,0x9f,0x13,0xa1,0x1d,0xa0,0x15,0xa1,0x1d,0xa3,0x13, 0xa7,0x1d,0xa9,0x12,0xac,0x1c,0xac,0x15,0xac,0x1e,0xab,0x14,0xa8,0x18,0xa5,0x14, 0xa2,0x17,0x9f,0x10,0x9e,0x1b,0x9f,0x17,0xa1,0x1e,0xa1,0x15,0xa4,0x1a,0xa7,0x18, 0xab,0x1e,0xab,0x14,0xac,0x1c,0xaa,0x12,0xaa,0x19,0xa6,0x16,0xa4,0x1d,0xa1,0x13, 0x9f,0x1b,0xa0,0x14,0x9f,0x1f,0x9f,0x12,0xa5,0x1a,0xa8,0x19,0xaa,0x1d,0xab,0x17, 0xad,0x1c,0xab,0x12,0xaa,0x1b,0xa4,0x14,0xa3,0x1f,0x9f,0x13,0x9e,0x22,0x9e,0x15, 0x9f,0x20,0x9f,0x18,0xa3,0x1d,0xa5,0x12,0xa9,0x1b,0xaa,0x15,0xab,0x1b,0xab,0x18, 0xa8,0x1a,0xa7,0x15,0xa4,0x20,0xa1,0x14,0xa1,0x1d,0xa0,0x10,0xa1,0x19,0x9e,0x15, 0xa1,0x1f,0xa5,0x14,0xa7,0x1a,0xa6,0x14,0xa9,0x1f,0xa9,0x17,0xa7,0x19,0xa5,0x16, 0xa4,0x1b,0xa2,0x19,0xa1,0x1e,0x9f,0x12,0xa1,0x1e,0x9f,0x15,0xa2,0x1c,0xa3,0x12, 0xa6,0x16,0xa5,0x17,0xaa,0x1d,0xa6,0x15,0xa6,0x1e,0xa4,0x10,0xa4,0x1e,0x9f,0x11, 0x9e,0x22,0x9f,0x18,0x9e,0x1e,0xa0,0x13,0xa2,0x20,0xa4,0x15,0xa8,0x1c,0xaa,0x17, 0xab,0x1d,0xa9,0x13,0xa9,0x18,0xa6,0x12,0xa5,0x1f,0x9e,0x11,0x9d,0x1b,0x9c,0x11, 0x9e,0x1e,0x9e,0x14,0xa0,0x1e,0xa1,0x12,0xa5,0x1c,0xa8,0x15,0xaa,0x1c,0xa9,0x14, 0xa9,0x1c,0xa6,0x17,0xa4,0x1c,0xa0,0x13,0xa0,0x1c,0x9e,0x13,0x9e,0x1d,0x9f,0x17, 0xa2,0x1f,0xa2,0x17,0xa6,0x1e,0xa6,0x16,0xaa,0x1e,0xa8,0x18,0xa9,0x18,0xa6,0x14, 0xa3,0x19,0xa0,0x13,0xa0,0x1d,0x9e,0x16,0x9e,0x1f,0x9d,0x10,0xa0,0x1c,0x9f,0x16, 0xa2,0x20,0xa5,0x12,0xa8,0x1b,0xa6,0x15,0xa6,0x21,0xa6,0x16,0xa3,0x1f,0x9f,0x13, 0x9e,0x18,0x9c,0x19,0x9e,0x17,0x9e,0x15,0x9d,0x20,0xa1,0x16,0xa5,0x20,0xa7,0x14, 0xa9,0x1e,0xa9,0x16,0xa8,0x1d,0xa6,0x13,0xa3,0x22,0xa2,0x18,0x9f,0x1e,0x9d,0x14, 0x9f,0x1f,0x9d,0x16,0x9d,0x1d,0xa0,0x1a,0xa3,0x19,0xa3,0x12,0xa6,0x1d,0xa6,0x16, 0xa7,0x1e,0xa3,0x14,0xa2,0x1e,0x9d,0x12,0x9c,0x20,0x9b,0x16,0x9a,0x20,0x9a,0x16, 0x9c,0x1f,0x9f,0x19,0xa3,0x1d,0xa3,0x19,0xa5,0x21,0xa7,0x18,0xa7,0x1d,0xa3,0x15, 0xa4,0x1f,0x9f,0x15,0x9c,0x19,0x9a,0x12,0x9b,0x21,0x9a,0x16,0x9b,0x1c,0x9b,0x17, 0xa0,0x1b,0xa3,0x17,0xa5,0x1f,0xa5,0x14,0xa5,0x1c,0xa5,0x1a,0xa2,0x1b,0x9e,0x12, 0x9b,0x20,0x9a,0x18,0x9b,0x1f,0x98,0x17,0x97,0x20,0x9b,0x15,0x9e,0x1c,0xa0,0x18, 0xa2,0x22,0xa4,0x14,0xa2,0x20,0xa4,0x1a,0xa3,0x20,0x9e,0x14,0x9c,0x1d,0x9a,0x17, 0x9b,0x1d,0x99,0x15,0x99,0x1e,0x9a,0x17,0xa0,0x1f,0xa1,0x16,0xa2,0x21,0xa5,0x1a, 0xa6,0x1e,0xa3,0x17,0xa2,0x1b,0x9e,0x13,0x9c,0x1d,0x9a,0x19,0x9a,0x1d,0x99,0x15, 0x99,0x1d,0x99,0x14,0x9d,0x1d,0x9d,0x16,0x9f,0x1d,0xa0,0x18,0xa3,0x1f,0xa2,0x15, 0x9f,0x1d,0x9e,0x18,0x9d,0x1e,0x99,0x19,0x99,0x20,0x99,0x15,0x9a,0x1f,0x9c,0x17, 0x9d,0x1d,0x9f,0x18,0xa2,0x1f,0xa2,0x15,0xa4,0x1f,0xa4,0x13,0xa2,0x1d,0xa0,0x18, 0x9d,0x20,0x9b,0x1a,0x98,0x20,0x97,0x15,0x96,0x20,0x97,0x14,0x99,0x1f,0x9d,0x16, 0x9e,0x20,0xa0,0x19,0xa2,0x1d,0xa2,0x14,0xa0,0x22,0x9e,0x16,0x9c,0x1d,0x98,0x16, 0x97,0x21,0x96,0x17,0x96,0x1e,0x96,0x12,0x98,0x20,0x9c,0x1b,0xa0,0x1f,0xa0,0x14, 0xa3,0x1a,0xa3,0x19,0xa1,0x21,0x9e,0x17,0x9c,0x23,0x99,0x17,0x99,0x1e,0x98,0x17, 0x99,0x1d,0x98,0x12,0x99,0x1d,0x9b,0x16,0xa0,0x1c,0xa0,0x18,0xa1,0x1e,0xa1,0x19, 0xa0,0x1c,0x9d,0x19,0x9b,0x1e,0x97,0x19,0x97,0x1d,0x95,0x12,0x97,0x1f,0x95,0x10, 0x97,0x20,0x9a,0x18,0x9c,0x20,0x9f,0x11,0xa2,0x1e,0xa1,0x18,0xa1,0x1d,0x9d,0x1a, 0x9b,0x22,0x98,0x17,0x96,0x1c,0x95,0x17,0x95,0x22,0x96,0x15,0x98,0x1c,0x98,0x14, 0x9c,0x1f,0x9f,0x17,0x9f,0x1b,0x9e,0x19,0xa0,0x1e,0x9f,0x18,0x9b,0x1b,0x99,0x19, 0x97,0x21,0x97,0x15,0x96,0x1b,0x95,0x19,0x95,0x1e,0x96,0x1d,0x9a,0x20,0x9a,0x17, 0x9e,0x24,0x9f,0x15,0x9d,0x1c,0x9b,0x17,0x9c,0x1d,0x98,0x16,0x96,0x1d,0x94,0x19, 0x95,0x1e,0x94,0x16,0x94,0x1b,0x97,0x17,0x9b,0x1c,0x9d,0x16,0x9f,0x1f,0xa0,0x18, 0x9f,0x20,0x9c,0x15,0x9c,0x21,0x98,0x16,0x97,0x1c,0x96,0x19,0x95,0x1a,0x96,0x14, 0x95,0x1b,0x97,0x16,0x9a,0x1a,0x9c,0x13,0xa0,0x1e,0x9f,0x11,0x9f,0x25,0x9e,0x18, 0x9c,0x24,0x98,0x16,0x97,0x12,0x96,0x0d,0x96,0x1c,0x94,0x17,0x95,0x1d,0x96,0x16, 0x9a,0x1f,0x9a,0x1e,0xa4,0x5d,0xa4,0x60,0xa4,0x6b,0xa1,0x6b,0x9f,0x75,0x9b,0x6e, 0x9a,0x73,0x98,0x66,0x99,0x6c,0x98,0x63,0x9a,0x6b,0x9c,0x63,0xa0,0x6e,0xa1,0x61, 0xa3,0x6f,0xa3,0x63,0xa3,0x6a,0x9f,0x5f,0x9e,0x6d,0x9b,0x65,0x99,0x69,0x97,0x62, 0x9a,0x6c,0x98,0x63,0x9a,0x6c,0x9a,0x61,0xa0,0x6b,0xa1,0x61,0xa2,0x65,0xa3,0x63, 0xa5,0x6a,0xa2,0x64,0x9f,0x67,0x9c,0x61,0x99,0x6a,0x98,0x60,0x98,0x6b,0x96,0x60, 0x98,0x6a,0x9b,0x62,0x9c,0x69,0x9f,0x62,0xa4,0x6b,0xa4,0x62,0xa2,0x68,0xa2,0x63, 0xa0,0x6a,0x9c,0x61,0x9a,0x6d,0x99,0x67,0x9a,0x6d,0x98,0x63,0x99,0x6c,0x99,0x61, 0x9e,0x6e,0x9f,0x64,0xa1,0x66,0xa1,0x64,0xa2,0x6a,0xa1,0x62,0x9f,0x6b,0x9b,0x64, 0x99,0x6c,0x96,0x67,0x95,0x66,0x96,0x65,0x97,0x69,0x98,0x63,0x9a,0x6a,0x9d,0x62, 0xa1,0x68,0xa0,0x64,0xa0,0x6b,0x9f,0x61,0x9f,0x70,0x9c,0x5d,0x99,0x66,0x98,0x60, 0x98,0x6f,0x99,0x63,0x98,0x67,0x99,0x61,0x9d,0x69,0x9f,0x60,0xa0,0x6c,0xa1,0x64, 0xa1,0x71,0x9f,0x61,0x9e,0x6c,0x9a,0x61,0x99,0x6a,0x97,0x62,0x98,0x69,0x96,0x61, 0x99,0x6c,0x99,0x62,0x9c,0x6a,0x9c,0x60,0xa1,0x6b,0xa0,0x60,0xa0,0x6a,0xa0,0x5e, 0x9f,0x6f,0x9c,0x62,0x99,0x69,0x96,0x65,0x96,0x69,0x96,0x5d,0x97,0x6c,0x97,0x5f, 0x98,0x6d,0x9c,0x62,0x9c,0x65,0x94,0x61,0x98,0x69,0x9c,0x62,0x92,0x68,0x8d,0x5f, 0x95,0x6d,0x95,0x5f,0x91,0x69,0x95,0x65,0x97,0x6d,0x96,0x64,0x98,0x68,0x9b,0x61, 0x9e,0x6e,0x9f,0x63,0x9f,0x67,0x9f,0x62,0x9d,0x72,0x9a,0x62,0x98,0x67,0x94,0x60, 0x93,0x69,0x93,0x5f,0x93,0x69,0x93,0x63,0x95,0x6b,0x98,0x64,0x9a,0x6a,0x9b,0x62, 0x9d,0x6b,0x9d,0x5f,0x9c,0x6a,0x99,0x64,0x97,0x6d,0x93,0x64,0x91,0x6b,0x8f,0x64, 0x92,0x6c,0x92,0x65,0x92,0x64,0x95,0x62,0x9c,0x6e,0x9c,0x5f,0x9d,0x6b,0x9c,0x65, 0x9c,0x68,0x99,0x62,0x97,0x6a,0x94,0x66,0x92,0x69,0x91,0x64,0x92,0x6c,0x91,0x63, 0x94,0x6e,0x97,0x62,0x99,0x6d,0x9c,0x62,0x9e,0x6d,0x9d,0x5f,0x9d,0x6a,0x9a,0x61, 0x98,0x68,0x94,0x64,0x94,0x68,0x93,0x63,0x93,0x6f,0x92,0x63,0x95,0x6a,0x96,0x60, 0x9a,0x70,0x9b,0x62,0x9d,0x68,0x9d,0x60,0x9e,0x6d,0x99,0x60,0x98,0x6d,0x95,0x63, 0x93,0x6b,0x92,0x67,0x92,0x67,0x92,0x63,0x94,0x6d,0x97,0x63,0x98,0x6c,0x9a,0x64, 0x9e,0x6a,0x9d,0x61,0x9c,0x6b,0x9b,0x66,0x99,0x6f,0x96,0x5f,0x95,0x6b,0x92,0x64, 0x93,0x6e,0x93,0x63,0x94,0x6a,0x96,0x67,0x97,0x6b,0x9b,0x66,0x9c,0x6a,0x9a,0x62, 0x9b,0x6b,0x98,0x64,0x97,0x68,0x93,0x62,0x93,0x6d,0x92,0x64,0x93,0x6d,0x91,0x60, 0x93,0x6c,0x95,0x5f,0x98,0x6c,0x99,0x61,0x9b,0x6e,0x9c,0x63,0x9c,0x67,0x9a,0x64, 0x99,0x6c,0x95,0x62,0x93,0x6a,0x93,0x64,0x8f,0x68,0x89,0x63,0x8e,0x67,0x96,0x67, 0x91,0x6f,0x92,0x65,0x9b,0x69,0x9c,0x61,0x9c,0x6e,0x9a,0x68,0x99,0x6c,0x95,0x67, 0x92,0x67,0x91,0x64,0x90,0x69,0x90,0x63,0x92,0x6f,0x92,0x62,0x95,0x6a,0x97,0x67, 0x9a,0x6e,0x9a,0x63,0x9a,0x6c,0x99,0x63,0x97,0x6d,0x94,0x68,0x92,0x6c,0x90,0x63, 0x8f,0x6b,0x8e,0x63,0x8f,0x6a,0x8e,0x60,0x93,0x6f,0x95,0x66,0x96,0x69,0x97,0x5e, 0x98,0x6d,0x96,0x65,0x95,0x6a,0x92,0x65,0x90,0x6f,0x8b,0x62,0x8b,0x6a,0x8c,0x63, 0x8d,0x6e,0x8d,0x64,0x90,0x67,0x95,0x68,0x96,0x6c,0x97,0x61,0x98,0x6c,0x97,0x62, 0x96,0x70,0x93,0x62,0x91,0x6b,0x90,0x63,0x90,0x6f,0x8e,0x65,0x91,0x6b,0x90,0x62, 0x93,0x69,0x97,0x5f,0x99,0x6d,0x9a,0x64,0x9c,0x6d,0x9a,0x66,0x99,0x6a,0x96,0x64, 0x95,0x69,0x91,0x62,0x90,0x6c,0x91,0x64,0x93,0x6f,0x92,0x66,0x94,0x6c,0x98,0x62, 0x9a,0x6f,0x9b,0x66,0x9c,0x6a,0x9b,0x64,0x9a,0x71,0x98,0x5f,0x94,0x70,0x91,0x62, 0x91,0x68,0x91,0x63,0x90,0x6a,0x91,0x67,0x92,0x71,0x96,0x63,0x98,0x73,0x9b,0x5f, 0x9b,0x6a,0x9b,0x67,0x99,0x6b,0x96,0x63,0x95,0x6f,0x91,0x66,0x8f,0x6c,0x90,0x63, 0x90,0x6e,0x90,0x63,0x92,0x67,0x94,0x66,0x9a,0x6f,0x9a,0x64,0x9b,0x6e,0x9b,0x64, 0x9a,0x6d,0x98,0x65,0x95,0x6c,0x93,0x64,0x92,0x6f,0x91,0x63,0x90,0x6c,0x91,0x65, 0x94,0x6f,0x94,0x66,0x97,0x70,0x9a,0x62,0x9c,0x73,0x9b,0x67,0x99,0x6d,0x97,0x62, 0x98,0x6f,0x93,0x67,0x91,0x6c,0x90,0x63,0x90,0x73,0x91,0x66,0x93,0x6e,0x92,0x63, 0x97,0x70,0x9a,0x62,0x9b,0x6e,0x9a,0x61,0x9a,0x6f,0x99,0x64,0x96,0x6d,0x92,0x63, 0x91,0x6d,0x90,0x64,0x90,0x6b,0x90,0x63,0x91,0x70,0x93,0x66,0x95,0x70,0x98,0x66, 0x9a,0x70,0x9a,0x65,0x98,0x72,0x99,0x67,0x96,0x70,0x92,0x5e,0x90,0x6d,0x91,0x67, 0x90,0x6c,0x8e,0x63,0x90,0x6c,0x92,0x67,0x95,0x73,0x97,0x69,0x99,0x6c,0x9a,0x67, 0x99,0x70,0x98,0x63,0x97,0x6c,0x93,0x63,0x92,0x75,0x90,0x64,0x8e,0x71,0x8f,0x67, 0x90,0x71,0x93,0x68,0x95,0x6b,0x98,0x66,0x9a,0x71,0x99,0x69,0x9b,0x6f,0x99,0x67, 0x97,0x6f,0x93,0x66,0x92,0x69,0x90,0x64,0x8f,0x71,0x91,0x5d,0x8f,0x70,0x91,0x64, 0x94,0x6e,0x96,0x6a,0x98,0x6f,0x99,0x69,0x98,0x75,0x98,0x67,0x96,0x73,0x93,0x66, 0x91,0x6f,0x8f,0x66,0x90,0x6a,0x8d,0x68,0x8e,0x6e,0x90,0x67,0x93,0x6f,0x95,0x69, 0x99,0x6e,0x9a,0x65,0x9a,0x6f,0x97,0x64,0x97,0x6d,0x94,0x63,0x91,0x6b,0x8e,0x66, 0x8e,0x6c,0x8e,0x62,0x8f,0x6e,0x8f,0x65,0x93,0x70,0x95,0x66,0x97,0x6b,0x98,0x64, 0x9a,0x6e,0x98,0x63,0x97,0x69,0x95,0x66,0x92,0x74,0x8e,0x61,0x8e,0x65,0x8f,0x5f, 0x8e,0x6a,0x8f,0x64,0x93,0x6e,0x96,0x61,0x97,0x72,0x97,0x6a,0x9c,0x5a,0x9a,0x50, 0x9a,0x58,0x96,0x5a,0x94,0x67,0x93,0x5e,0x93,0x64,0x93,0x56,0x94,0x5d,0x93,0x57, 0x99,0x5d,0x9b,0x52,0x9d,0x5d,0x9e,0x54,0x9f,0x66,0x9c,0x54,0x9b,0x61,0x99,0x56, 0x96,0x5c,0x94,0x54,0x94,0x5c,0x93,0x53,0x95,0x60,0x95,0x54,0x96,0x5f,0x99,0x56, 0x9e,0x5a,0x9c,0x55,0x9d,0x5b,0x9c,0x55,0x9c,0x62,0x98,0x53,0x97,0x5d,0x94,0x51, 0x93,0x61,0x93,0x54,0x94,0x5b,0x94,0x58,0x96,0x62,0x9a,0x4f,0x9c,0x5c,0x9d,0x55, 0x9f,0x5c,0x9c,0x53,0x9b,0x62,0x98,0x54,0x95,0x5d,0x93,0x58,0x93,0x5f,0x91,0x59, 0x93,0x5f,0x93,0x54,0x97,0x5f,0x98,0x51,0x9c,0x5e,0x9c,0x52,0x9d,0x5f,0x9b,0x53, 0x9a,0x5a,0x97,0x56,0x95,0x5f,0x93,0x55,0x91,0x5c,0x91,0x56,0x91,0x5e,0x91,0x55, 0x94,0x5c,0x98,0x56,0x99,0x59,0x9b,0x53,0x9b,0x62,0x9b,0x50,0x9a,0x60,0x97,0x50, 0x95,0x5e,0x92,0x55,0x92,0x5c,0x91,0x53,0x91,0x62,0x91,0x56,0x94,0x5c,0x95,0x53, 0x99,0x5c,0x9a,0x54,0x9a,0x5f,0x99,0x54,0x97,0x63,0x96,0x55,0x92,0x60,0x91,0x57, 0x91,0x5d,0x8e,0x52,0x8f,0x5a,0x90,0x55,0x91,0x60,0x93,0x57,0x98,0x5e,0x98,0x52, 0x9a,0x5c,0x9a,0x54,0x99,0x5c,0x96,0x55,0x94,0x5f,0x91,0x53,0x8f,0x62,0x8e,0x55, 0x90,0x5e,0x8e,0x52,0x90,0x5c,0x94,0x58,0x95,0x60,0x99,0x54,0x99,0x5d,0x98,0x55, 0x98,0x59,0x97,0x55,0x94,0x5c,0x90,0x56,0x8e,0x5e,0x8d,0x53,0x8e,0x5a,0x8d,0x53, 0x8f,0x5c,0x92,0x57,0x94,0x5d,0x97,0x51,0x99,0x5e,0x97,0x53,0x97,0x59,0x97,0x55, 0x93,0x5e,0x8f,0x55,0x8d,0x5b,0x8c,0x56,0x8d,0x62,0x8c,0x52,0x8c,0x5d,0x90,0x55, 0x93,0x60,0x96,0x53,0x97,0x5c,0x96,0x55,0x97,0x60,0x95,0x58,0x94,0x5a,0x90,0x51, 0x8f,0x5c,0x8e,0x56,0x8e,0x5b,0x8e,0x55,0x8f,0x60,0x90,0x57,0x93,0x5c,0x96,0x58, 0x99,0x5f,0x96,0x55,0x98,0x5e,0x96,0x52,0x94,0x61,0x90,0x54,0x90,0x5f,0x8d,0x53, 0x8e,0x5a,0x8e,0x5b,0x8e,0x60,0x90,0x55,0x93,0x5f,0x94,0x58,0x97,0x5c,0x97,0x58, 0x97,0x60,0x96,0x58,0x93,0x5c,0x90,0x56,0x8e,0x61,0x8d,0x58,0x8c,0x63,0x8c,0x57, 0x8e,0x5d,0x8e,0x56,0x92,0x5b,0x94,0x54,0x96,0x5d,0x96,0x58,0x97,0x5e,0x94,0x56, 0x93,0x63,0x91,0x57,0x90,0x5f,0x8d,0x56,0x8c,0x60,0x8b,0x56,0x8c,0x60,0x8e,0x54, 0x90,0x60,0x93,0x5e,0x95,0x5d,0x96,0x57,0x95,0x61,0x95,0x5a,0x94,0x62,0x90,0x5a, 0x8e,0x61,0x8c,0x59,0x8b,0x5c,0x8a,0x58,0x8a,0x63,0x8a,0x5c,0x8d,0x5f,0x90,0x58, 0x92,0x63,0x93,0x59,0x96,0x5e,0x95,0x59,0x94,0x5f,0x90,0x5a,0x8d,0x61,0x8b,0x56, 0x8a,0x60,0x8b,0x5c,0x8c,0x5b,0x8c,0x58,0x8e,0x61,0x90,0x5b,0x92,0x63,0x95,0x5b, 0x94,0x64,0x95,0x59,0x93,0x5d,0x91,0x5a,0x8d,0x63,0x8d,0x57,0x8c,0x5f,0x8b,0x58, 0x8a,0x5d,0x8c,0x5b,0x8e,0x5f,0x91,0x5a,0x92,0x64,0x95,0x5a,0x94,0x64,0x94,0x58, 0x94,0x65,0x92,0x5b,0x8e,0x66,0x8c,0x59,0x8a,0x68,0x8a,0x5d,0x8a,0x60,0x8c,0x5f, 0x8d,0x66,0x91,0x59,0x91,0x60,0x94,0x5d,0x94,0x65,0x93,0x59,0x92,0x61,0x92,0x5c, 0x8e,0x63,0x8b,0x5c,0x8a,0x61,0x8b,0x5b,0x8b,0x67,0x8b,0x5b,0x8c,0x63,0x8e,0x61, 0x93,0x69,0x94,0x5a,0x95,0x62,0x94,0x5b,0x93,0x6a,0x91,0x5c,0x8f,0x66,0x8c,0x60, 0x8a,0x6a,0x8a,0x5e,0x88,0x60,0x89,0x60,0x8b,0x6a,0x8b,0x61,0x90,0x68,0x91,0x62, 0x93,0x68,0x92,0x61,0x93,0x68,0x8f,0x61,0x8e,0x6d,0x8b,0x62,0x8a,0x69,0x88,0x62, 0x8a,0x6b,0x89,0x63,0x8a,0x6c,0x8b,0x5f,0x8e,0x70,0x90,0x66,0x91,0x6a,0x91,0x6b, 0x91,0x72,0x8f,0x66,0x8d,0x68,0x88,0x61,0x88,0x6e,0x87,0x66,0x88,0x6d,0x87,0x68, 0x88,0x75,0x89,0x69,0x8d,0x6c,0x8e,0x62,0x8e,0x74,0x90,0x66,0x90,0x6d,0x8d,0x65, 0x8b,0x74,0x89,0x65,0x86,0x6c,0x85,0x66,0x85,0x72,0x84,0x69,0x86,0x72,0x88,0x6a, 0x8b,0x72,0x8d,0x68,0x8f,0x6e,0x8e,0x68,0x8e,0x72,0x8c,0x65,0x8a,0x71,0x88,0x67, 0x84,0x72,0x84,0x66,0x84,0x6c,0x84,0x68,0x85,0x70,0x87,0x63,0x8b,0x70,0x8c,0x65, 0x8e,0x70,0x8e,0x62,0x8f,0x6b,0x8e,0x6a,0x8c,0x71,0x88,0x67,0x87,0x6c,0x84,0x63, 0x83,0x71,0x84,0x67,0x85,0x68,0x85,0x66,0x89,0x6d,0x8b,0x62,0x8e,0x6c,0x8e,0x68, 0x8f,0x6d,0x8d,0x65,0x8c,0x69,0x88,0x64,0x86,0x71,0x85,0x64,0x83,0x68,0x83,0x64, 0x86,0x6f,0x84,0x64,0x87,0x6b,0x8b,0x65,0x8c,0x72,0x8c,0x62,0x8c,0x70,0x8c,0x62, 0x8a,0x6f,0x88,0x65,0x86,0x6c,0x84,0x60,0x84,0x71,0x83,0x64,0x84,0x6e,0x84,0x65, 0x85,0x6e,0x88,0x64,0x8a,0x68,0x8a,0x66,0x8b,0x74,0x8b,0x65,0x8a,0x70,0x87,0x65, 0x85,0x71,0x83,0x64,0x83,0x6b,0x82,0x64,0x83,0x77,0x83,0x68,0x84,0x70,0x87,0x66, 0x88,0x71,0x8a,0x66,0x8a,0x71,0x8a,0x68,0x88,0x7a,0x87,0x6e,0x83,0x74,0x82,0x6c, 0x81,0x77,0x80,0x6e,0x80,0x73,0x80,0x6c,0x81,0x77,0x83,0x6c,0x87,0x73,0x88,0x6d, 0x88,0x79,0x89,0x6e,0x87,0x74,0x86,0x6c,0x83,0x7d,0x80,0x72,0x7f,0x7a,0x7d,0x71, 0x7d,0x78,0x7d,0x72,0x7e,0x73,0x82,0x70,0x84,0x77,0x86,0x6d,0x86,0x77,0x86,0x71, 0x87,0x76,0x86,0x6f,0x83,0x77,0x80,0x71,0x80,0x7a,0x7d,0x71,0x7d,0x78,0x7c,0x71, 0x7f,0x79,0x80,0x72,0x83,0x76,0x85,0x72,0x87,0x7a,0x86,0x70,0x87,0x76,0x85,0x72, 0x84,0x7d,0x81,0x75,0x7f,0x75,0x7e,0x74,0x7f,0x7b,0x7e,0x73,0x7f,0x76,0x81,0x6f, 0x84,0x79,0x85,0x74,0x87,0x7b,0x88,0x75,0x88,0x7f,0x87,0x75,0x85,0x79,0x83,0x75, 0x81,0x78,0x80,0x73,0x80,0x7b,0x7f,0x74,0x80,0x82,0x82,0x77,0x83,0x82,0x87,0x7c, 0x88,0x81,0x85,0x7f,0x6a,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xb4,0x47,0xb1,0x52,0xb4,0x4b,0xb6,0x55,0xb8,0x46,0xbc,0x55,0xbe,0x47, 0xc1,0x50,0xc1,0x4a,0xc1,0x4e,0xbf,0x4b,0xbd,0x50,0xba,0x4e,0xb7,0x52,0xb5,0x4b, 0xb4,0x51,0xb7,0x48,0xb9,0x4f,0xbc,0x4b,0xc0,0x4f,0xc2,0x4b,0xc5,0x50,0xc4,0x45, 0xc5,0x52,0xc5,0x4d,0xc2,0x50,0xbe,0x48,0xbc,0x53,0xb9,0x49,0xb9,0x50,0xb9,0x4a, 0xbb,0x52,0xbe,0x4a,0xc4,0x4c,0xc6,0x4b,0xc7,0x51,0xca,0x46,0xc9,0x51,0xc9,0x46, 0xc5,0x51,0xc4,0x48,0xc0,0x4c,0xbc,0x46,0xba,0x4d,0xb9,0x42,0xbe,0x51,0xc0,0x4b, 0xc2,0x50,0xc8,0x4a,0xca,0x4c,0xcb,0x4a,0xcc,0x51,0xcb,0x4a,0xc8,0x4e,0xc5,0x46, 0xc4,0x51,0xc1,0x48,0xbf,0x4b,0xbf,0x47,0xc2,0x4f,0xc5,0x4a,0xc8,0x50,0xca,0x48, 0xce,0x4f,0xcd,0x4b,0xcf,0x4c,0xcd,0x49,0xcb,0x50,0xc7,0x47,0xc5,0x53,0xc1,0x4b, 0xc0,0x52,0xbe,0x45,0xc3,0x4d,0xc4,0x4b,0xc8,0x4c,0xcb,0x49,0xcd,0x4f,0xcc,0x45, 0xce,0x53,0xce,0x4b,0xcc,0x4a,0xc9,0x4b,0xc5,0x4e,0xc1,0x48,0xc0,0x4f,0xbe,0x45, 0xbf,0x53,0xc2,0x49,0xc4,0x4b,0xc6,0x49,0xc8,0x54,0xcb,0x4c,0xc9,0x4f,0xc9,0x45, 0xc7,0x51,0xc5,0x4a,0xc2,0x4f,0xbf,0x43,0xbd,0x4d,0xbb,0x4a,0xbb,0x51,0xbe,0x48, 0xc1,0x50,0xc4,0x4d,0xc8,0x4f,0xc7,0x47,0xc9,0x52,0xc8,0x47,0xc8,0x4f,0xc3,0x4b, 0xc1,0x52,0xbe,0x46,0xbb,0x4d,0xba,0x48,0xba,0x53,0xbb,0x49,0xbf,0x4f,0xc3,0x48, 0xc4,0x58,0xc6,0x49,0xc8,0x4d,0xc8,0x4a,0xc7,0x4e,0xc4,0x4d,0xc2,0x4e,0xbd,0x47, 0xba,0x52,0xba,0x4b,0xba,0x50,0xbc,0x42,0xbd,0x51,0xc1,0x4c,0xc3,0x52,0xc5,0x49, 0xc7,0x52,0xc7,0x47,0xc6,0x4d,0xc4,0x4a,0xc1,0x50,0xbd,0x49,0xbb,0x4c,0xb9,0x46, 0xb9,0x50,0xb9,0x47,0xbe,0x4f,0xbf,0x48,0xc1,0x4f,0xc5,0x48,0xc6,0x53,0xc5,0x46, 0xc6,0x4d,0xc3,0x4c,0xbf,0x52,0xbb,0x4a,0xba,0x50,0xb8,0x48,0xb5,0x51,0xb9,0x45, 0xbc,0x4c,0xbd,0x4a,0xc0,0x50,0xc3,0x4b,0xc5,0x51,0xc4,0x47,0xc5,0x4f,0xc2,0x47, 0xc0,0x4e,0xbc,0x47,0xbb,0x4d,0xb8,0x49,0xb7,0x52,0xb7,0x44,0xba,0x50,0xbc,0x47, 0xbe,0x51,0xc0,0x43,0xc4,0x4f,0xc2,0x43,0xc2,0x51,0xc1,0x47,0xbd,0x50,0xbb,0x46, 0xbb,0x4f,0xb8,0x4c,0xb7,0x4d,0xb7,0x49,0xb9,0x50,0xba,0x44,0xbd,0x52,0xc1,0x47, 0xc3,0x50,0xc4,0x49,0xc4,0x4c,0xc1,0x49,0xbf,0x52,0xbc,0x4a,0xb9,0x50,0xb6,0x48, 0xb5,0x52,0xb5,0x4b,0xb6,0x52,0xba,0x48,0xbb,0x50,0xbf,0x49,0xc0,0x4f,0xc2,0x4b, 0xc2,0x51,0xc0,0x49,0xbe,0x50,0xbc,0x4a,0xb9,0x51,0xb7,0x4c,0xb3,0x50,0xb5,0x4a, 0xb6,0x51,0xba,0x48,0xbd,0x4a,0xbe,0x45,0xc1,0x51,0xc1,0x48,0xc2,0x51,0xc0,0x4c, 0xbd,0x51,0xb9,0x4b,0xb8,0x49,0xb5,0x46,0xb2,0x51,0xb3,0x47,0xb4,0x52,0xb8,0x4c, 0xbb,0x51,0xbd,0x47,0xc2,0x4e,0xc2,0x49,0xc1,0x50,0xc1,0x4b,0xbe,0x4e,0xba,0x48, 0xb8,0x51,0xb6,0x48,0xb4,0x50,0xb3,0x45,0xb5,0x52,0xb6,0x49,0xba,0x4f,0xbd,0x4b, 0xbe,0x50,0xc0,0x4a,0xbf,0x50,0xbf,0x49,0xbe,0x54,0xbb,0x4b,0xb8,0x51,0xb4,0x48, 0xb3,0x51,0xb1,0x46,0xb2,0x4d,0xb4,0x49,0xb7,0x53,0xba,0x47,0xbd,0x51,0xc0,0x4a, 0xbf,0x53,0xbe,0x49,0xbd,0x4e,0xb9,0x4a,0xb7,0x51,0xb5,0x4c,0xb1,0x50,0xb0,0x47, 0xb2,0x50,0xb4,0x48,0xb5,0x50,0xb9,0x46,0xbd,0x4e,0xbf,0x49,0xbf,0x4f,0xbd,0x48, 0xbd,0x51,0xba,0x47,0xb7,0x4e,0xb3,0x44,0xb2,0x54,0xb0,0x4a,0xb1,0x55,0xb2,0x47, 0xb4,0x4e,0xb8,0x4a,0xba,0x4f,0xb9,0x48,0xbe,0x51,0xba,0x4b,0xbd,0x51,0xb8,0x46, 0xb8,0x50,0xb2,0x47,0xb1,0x4d,0xae,0x4a,0xae,0x51,0xb1,0x4a,0xb4,0x4d,0xb4,0x44, 0xb8,0x50,0xba,0x48,0xbd,0x4f,0xbb,0x44,0xba,0x54,0xb9,0x48,0xb5,0x50,0xb3,0x4b, 0xaf,0x53,0xaf,0x4e,0xae,0x50,0xb0,0x46,0xb1,0x52,0xb4,0x4c,0xb9,0x50,0xbc,0x46, 0xba,0x51,0xbc,0x48,0xbe,0x4f,0xbb,0x42,0xb7,0x4e,0xb1,0x48,0xb2,0x4c,0xb0,0x4c, 0xac,0x50,0xae,0x48,0xb2,0x4d,0xb6,0x4b,0xb7,0x51,0xba,0x47,0xba,0x50,0xbd,0x48, 0xbc,0x50,0xb8,0x43,0xb6,0x4f,0xb3,0x48,0xb1,0x50,0xaf,0x47,0xae,0x56,0xaf,0x49, 0xb0,0x51,0xb5,0x4b,0xb8,0x4a,0xb9,0x46,0xbd,0x51,0xbe,0x4b,0xbd,0x4f,0xbb,0x42, 0xb7,0x4d,0xb4,0x47,0xb1,0x51,0xaf,0x48,0xae,0x54,0xb0,0x46,0xb3,0x52,0xb5,0x4a, 0xba,0x4e,0xbd,0x4a,0xbe,0x4f,0xbd,0x49,0xbf,0x52,0xbd,0x4c,0xb8,0x54,0xb5,0x47, 0xb5,0x4e,0xb0,0x48,0xb0,0x4e,0xb1,0x47,0xb4,0x51,0xb5,0x45,0xba,0x4f,0xbc,0x47, 0xbe,0x4c,0xbf,0x47,0xbf,0x51,0xbd,0x49,0xba,0x54,0xb8,0x49,0xb7,0x4b,0xb3,0x4a, 0xb1,0x50,0xb3,0x49,0xb4,0x4d,0xb7,0x47,0xb9,0x51,0xbd,0x4a,0xc0,0x50,0xc0,0x47, 0xc0,0x4d,0xc0,0x48,0xbe,0x4f,0xb8,0x47,0xb6,0x53,0xb3,0x46,0xb2,0x53,0xb1,0x49, 0xb4,0x4c,0xb5,0x48,0xba,0x4c,0xbb,0x46,0xbd,0x50,0xbf,0x49,0xbf,0x4e,0xbe,0x45, 0xbc,0x52,0xb9,0x44,0xb6,0x4e,0xb3,0x45,0xb1,0x52,0xb4,0x44,0xb5,0x51,0xb7,0x46, 0xb9,0x52,0xbd,0x46,0xbe,0x50,0xc1,0x4a,0xc1,0x51,0xc0,0x45,0xbd,0x51,0xbb,0x4b, 0xb8,0x4f,0xb5,0x44,0xb4,0x48,0xb2,0x40,0xb3,0x4f,0xb7,0x48,0xb9,0x4f,0xbc,0x46, 0xbe,0x53,0xbb,0x4d,0xc5,0x35,0xc3,0x30,0xc3,0x36,0xbf,0x31,0xbc,0x41,0xb9,0x32, 0xb9,0x3e,0xb9,0x34,0xbb,0x33,0xbe,0x2f,0xc0,0x36,0xc1,0x30,0xc4,0x38,0xc5,0x2d, 0xc4,0x36,0xc3,0x30,0xc2,0x36,0xbf,0x2d,0xbb,0x33,0xba,0x2d,0xb7,0x35,0xb8,0x2d, 0xb9,0x36,0xbb,0x30,0xbe,0x37,0xc1,0x2f,0xc3,0x38,0xc4,0x2b,0xc4,0x37,0xc3,0x2f, 0xc2,0x35,0xc1,0x2e,0xb9,0x32,0xb9,0x2e,0xb6,0x35,0xb8,0x2c,0xb9,0x38,0xbb,0x2a, 0xbe,0x37,0xc1,0x2f,0xc2,0x36,0xc4,0x2a,0xc4,0x32,0xc4,0x2f,0xc1,0x35,0xbe,0x2c, 0xbb,0x37,0xba,0x2d,0xb7,0x31,0xb6,0x2c,0xb9,0x36,0xba,0x2a,0xbc,0x32,0xc0,0x2e, 0xc1,0x32,0xc2,0x2e,0xc3,0x37,0xc2,0x2b,0xbe,0x33,0xbd,0x2e,0xba,0x35,0xb8,0x2d, 0xb5,0x37,0xb5,0x2e,0xb6,0x34,0xb8,0x2b,0xba,0x37,0xbe,0x30,0xbf,0x32,0xc2,0x2c, 0xc5,0x36,0xc3,0x2d,0xc0,0x31,0xbe,0x2e,0xbc,0x3b,0xba,0x2d,0xb8,0x34,0xb8,0x2f, 0xb8,0x37,0xb9,0x2c,0xbb,0x34,0xbe,0x2f,0xc0,0x39,0xc3,0x2c,0xc2,0x39,0xc0,0x2b, 0xbf,0x36,0xbd,0x2f,0xba,0x34,0xb7,0x2c,0xb5,0x36,0xb4,0x2b,0xb4,0x31,0xb6,0x2b, 0xb8,0x35,0xbb,0x2d,0xbd,0x36,0xc0,0x2c,0xc2,0x36,0xc2,0x2d,0xc1,0x39,0xbf,0x2f, 0xbd,0x37,0xb8,0x2c,0xb6,0x33,0xb5,0x2c,0xb5,0x34,0xb8,0x2e,0xba,0x35,0xbe,0x2d, 0xc2,0x3a,0xc3,0x32,0xc5,0x3b,0xc6,0x2c,0xc4,0x38,0xc3,0x2d,0xc1,0x35,0xbf,0x2c, 0xbc,0x34,0xba,0x2e,0xba,0x34,0xbb,0x2e,0xbd,0x3a,0xc0,0x2a,0xc3,0x38,0xc4,0x31, 0xc7,0x2f,0xc6,0x2c,0xc4,0x36,0xc2,0x2f,0xc0,0x34,0xbf,0x2f,0xbc,0x39,0xba,0x2f, 0xba,0x33,0xbc,0x2d,0xbe,0x35,0xc0,0x2a,0xc1,0x32,0xc5,0x2b,0xc6,0x33,0xc4,0x30, 0xc4,0x36,0xc2,0x2c,0xbf,0x33,0xbd,0x2c,0xbc,0x36,0xba,0x31,0xb8,0x39,0xb9,0x2d, 0xbb,0x34,0xbc,0x30,0xc0,0x31,0xc2,0x2d,0xc6,0x34,0xc7,0x2f,0xc5,0x37,0xc4,0x2f, 0xc1,0x37,0xbd,0x2a,0xbc,0x36,0xba,0x2b,0xba,0x38,0xbb,0x2f,0xbd,0x38,0xbe,0x2f, 0xc2,0x38,0xc6,0x2f,0xc5,0x33,0xc4,0x30,0xc7,0x37,0xc6,0x2e,0xc1,0x32,0xbf,0x2e, 0xbe,0x3b,0xbb,0x2d,0xb8,0x31,0xba,0x2d,0xbc,0x38,0xbe,0x30,0xbf,0x30,0xc3,0x29, 0xc5,0x38,0xc7,0x2d,0xc6,0x31,0xc4,0x33,0xc4,0x34,0xc3,0x2e,0xbf,0x34,0xbe,0x2d, 0xbc,0x32,0xbc,0x31,0xbd,0x34,0xbf,0x2e,0xc1,0x33,0xc6,0x2e,0xc8,0x36,0xc9,0x2f, 0xc8,0x36,0xc6,0x31,0xc6,0x37,0xc0,0x2f,0xc0,0x36,0xbd,0x2f,0xbb,0x34,0xba,0x2a, 0xbc,0x33,0xbe,0x30,0xc0,0x30,0xc2,0x2c,0xc6,0x35,0xc9,0x2f,0xc7,0x34,0xc6,0x2d, 0xc5,0x38,0xc2,0x32,0xbf,0x34,0xbe,0x2b,0xbc,0x36,0xba,0x31,0xbc,0x33,0xbf,0x2d, 0xc2,0x38,0xc5,0x2d,0xc5,0x35,0xc5,0x2c,0xc8,0x37,0xc6,0x2f,0xc3,0x35,0xc2,0x2e, 0xc0,0x37,0xbd,0x2c,0xba,0x33,0xb9,0x30,0xba,0x33,0xbc,0x30,0xbf,0x34,0xc3,0x2e, 0xc5,0x3a,0xc4,0x30,0xc6,0x36,0xc6,0x2e,0xc4,0x37,0xc0,0x30,0xbf,0x35,0xbd,0x2f, 0xbb,0x3a,0xba,0x2c,0xb9,0x35,0xbb,0x2b,0xbe,0x38,0xc0,0x30,0xc2,0x36,0xc4,0x2f, 0xc4,0x36,0xc4,0x32,0xc2,0x36,0xbf,0x30,0xbe,0x38,0xbb,0x31,0xba,0x36,0xb6,0x30, 0xb9,0x3a,0xbb,0x30,0xbd,0x33,0xc1,0x2c,0xc4,0x3a,0xc4,0x31,0xc4,0x38,0xc4,0x2d, 0xc2,0x37,0xbe,0x30,0xbb,0x37,0xba,0x2f,0xb9,0x36,0xb8,0x30,0xb8,0x36,0xba,0x2f, 0xbd,0x36,0xc0,0x2e,0xc2,0x36,0xc4,0x2a,0xc6,0x33,0xc6,0x2b,0xc5,0x3a,0xc2,0x2c, 0xbf,0x35,0xbd,0x2c,0xba,0x33,0xb7,0x31,0xb9,0x38,0xba,0x2f,0xbc,0x3a,0xbe,0x28, 0xc3,0x37,0xc3,0x2d,0xc3,0x31,0xc3,0x30,0xc2,0x36,0xc0,0x2d,0xbd,0x36,0xbd,0x2e, 0xba,0x36,0xb8,0x30,0xb8,0x33,0xba,0x2d,0xbc,0x36,0xbe,0x30,0xc0,0x38,0xc1,0x31, 0xc4,0x35,0xc5,0x2d,0xc3,0x35,0xbf,0x30,0xbd,0x34,0xbb,0x2f,0xba,0x35,0xb7,0x2e, 0xb6,0x33,0xb9,0x2d,0xba,0x36,0xbd,0x32,0xc0,0x39,0xc3,0x2d,0xc3,0x36,0xc3,0x2d, 0xc3,0x37,0xc2,0x2f,0xc0,0x36,0xbc,0x2f,0xba,0x37,0xb9,0x2e,0xb7,0x36,0xb6,0x2d, 0xb9,0x38,0xbd,0x2e,0xbe,0x31,0xbf,0x2e,0xc2,0x37,0xc3,0x2b,0xc0,0x37,0xbf,0x32, 0xbd,0x35,0xbb,0x2e,0xb8,0x38,0xb7,0x2f,0xb7,0x38,0xb7,0x2f,0xb8,0x37,0xb9,0x30, 0xbe,0x37,0xbf,0x2b,0xc0,0x32,0xc1,0x33,0xc0,0x34,0xbe,0x2f,0xbc,0x34,0xb9,0x2b, 0xb9,0x36,0xb6,0x2c,0xb4,0x36,0xb5,0x2d,0xb7,0x37,0xb9,0x2c,0xbc,0x36,0xbe,0x2f, 0xbe,0x32,0xbf,0x32,0xbf,0x34,0xbd,0x2e,0xbb,0x36,0xba,0x2b,0xb7,0x36,0xb4,0x30, 0xb6,0x35,0xb5,0x2b,0xb6,0x33,0xb9,0x2d,0xbb,0x36,0xc1,0x2a,0xc1,0x35,0xc0,0x2e, 0xc1,0x32,0xc1,0x2c,0xbe,0x35,0xbb,0x2e,0xb7,0x37,0xb7,0x2d,0xb6,0x3b,0xb6,0x2d, 0xb7,0x33,0xb9,0x2f,0xbc,0x37,0xbf,0x2b,0xc0,0x36,0xbf,0x2c,0xbf,0x35,0xc0,0x2e, 0xbe,0x39,0xb9,0x30,0xb8,0x30,0xb5,0x2f,0xb4,0x38,0xb4,0x2c,0xb6,0x36,0xb7,0x30, 0xbc,0x34,0xbe,0x2d,0xc0,0x32,0xc0,0x2a,0xc1,0x37,0xbf,0x30,0xbd,0x36,0xba,0x2b, 0xb9,0x34,0xb8,0x2c,0xb6,0x33,0xb4,0x2b,0xb5,0x33,0xb7,0x30,0xb9,0x33,0xbd,0x2f, 0xbf,0x36,0xc1,0x2d,0xc2,0x35,0xc0,0x2d,0xbf,0x39,0xbc,0x2c,0xba,0x39,0xb8,0x2e, 0xb6,0x32,0xb5,0x28,0xb7,0x3a,0xb8,0x2f,0xba,0x34,0xbd,0x31,0xc1,0x37,0xc1,0x2b, 0xc2,0x37,0xc1,0x30,0xbd,0x32,0xba,0x2e,0xba,0x37,0xb7,0x2c,0xb3,0x31,0xb3,0x31, 0xb6,0x36,0xb8,0x2d,0xb9,0x36,0xbd,0x29,0xbf,0x39,0xc1,0x2f,0xc0,0x32,0xc0,0x2c, 0xc1,0x39,0xba,0x31,0xb9,0x37,0xb7,0x31,0xb7,0x38,0xb4,0x29,0xb5,0x2f,0xb7,0x26, 0xb8,0x31,0xbb,0x2d,0xbd,0x36,0xbe,0x2f,0xbe,0x36,0xb8,0x34,0xbf,0x53,0xbd,0x4f, 0xbc,0x52,0xb9,0x57,0xb6,0x61,0xb4,0x57,0xb7,0x5b,0xb9,0x50,0xba,0x57,0xbd,0x4d, 0xbe,0x58,0xc0,0x50,0xc1,0x56,0xc0,0x55,0xbf,0x56,0xbc,0x50,0xb9,0x59,0xb7,0x50, 0xb8,0x57,0xb6,0x4f,0xb6,0x54,0xb8,0x4c,0xbb,0x59,0xbb,0x50,0xbe,0x56,0xbf,0x51, 0xbf,0x55,0xbe,0x51,0xbe,0x5a,0xb9,0x4c,0xb8,0x59,0xb5,0x52,0xb4,0x5b,0xb3,0x50, 0xb3,0x5a,0xb6,0x53,0xbb,0x56,0xbc,0x4f,0xba,0x57,0xbd,0x4e,0xc2,0x56,0xbe,0x4f, 0xb9,0x5a,0xbc,0x4e,0xb8,0x56,0xb6,0x50,0xb5,0x58,0xb5,0x4e,0xb5,0x5b,0xb5,0x52, 0xb7,0x54,0xbb,0x4e,0xbd,0x56,0xbe,0x53,0xbf,0x55,0xc0,0x4e,0xbe,0x56,0xbd,0x52, 0xb9,0x55,0xb7,0x51,0xb6,0x56,0xb5,0x4e,0xb6,0x5a,0xb6,0x51,0xb8,0x59,0xb7,0x51, 0xbc,0x59,0xbd,0x52,0xbc,0x54,0xbc,0x4c,0xbc,0x58,0xba,0x4e,0xb7,0x57,0xb6,0x4f, 0xb4,0x57,0xb1,0x4c,0xb1,0x58,0xb0,0x4f,0xb4,0x5a,0xb6,0x51,0xba,0x5a,0xbb,0x52, 0xbe,0x56,0xbf,0x4a,0xbc,0x55,0xba,0x4c,0xb7,0x57,0xb3,0x51,0xb1,0x5c,0xb2,0x4d, 0xb3,0x53,0xb4,0x54,0xb5,0x57,0xb8,0x51,0xbb,0x5a,0xba,0x52,0xbd,0x55,0xbd,0x4f, 0xbb,0x58,0xb9,0x4f,0xb6,0x56,0xb4,0x50,0xb0,0x5a,0xae,0x4b,0xb0,0x55,0xb3,0x4f, 0xb4,0x5d,0xb4,0x51,0xba,0x5a,0xbb,0x50,0xbd,0x5a,0xbd,0x51,0xbd,0x57,0xb9,0x50, 0xb8,0x56,0xb7,0x4f,0xb3,0x55,0xb2,0x4f,0xb1,0x58,0xb4,0x4e,0xb6,0x54,0xb6,0x4e, 0xb9,0x5b,0xbc,0x50,0xbd,0x59,0xbb,0x51,0xbd,0x5d,0xbb,0x51,0xb6,0x57,0xb5,0x4f, 0xb2,0x57,0xb0,0x50,0xaf,0x53,0xaf,0x50,0xb3,0x5a,0xb5,0x4f,0xb6,0x55,0xb9,0x50, 0xbc,0x5b,0xb9,0x56,0xb8,0x57,0xb9,0x4c,0xb8,0x59,0xb2,0x51,0xb1,0x57,0xb0,0x51, 0xb0,0x55,0xb0,0x4c,0xb3,0x56,0xb3,0x4e,0xb4,0x5b,0xb6,0x52,0xba,0x5a,0xb9,0x4c, 0xb8,0x59,0xb9,0x4d,0xb5,0x57,0xb3,0x54,0xb2,0x58,0xb0,0x4c,0xae,0x59,0xaf,0x51, 0xb1,0x5b,0xb0,0x50,0xb0,0x56,0xb9,0x52,0xb9,0x5c,0xb7,0x4b,0xb9,0x56,0xb9,0x4e, 0xb7,0x5a,0xb2,0x52,0xb0,0x58,0xaf,0x51,0xae,0x58,0xad,0x4d,0xaf,0x58,0xb1,0x50, 0xb4,0x54,0xb6,0x52,0xb8,0x55,0xba,0x4e,0xb7,0x58,0xb8,0x53,0xb7,0x5c,0xb1,0x50, 0xb0,0x56,0xb0,0x4d,0xae,0x5a,0xad,0x4f,0xaf,0x58,0xb1,0x50,0xb3,0x57,0xb6,0x4b, 0xb6,0x56,0xb7,0x4f,0xb7,0x55,0xb3,0x4d,0xb2,0x57,0xb2,0x4f,0xaf,0x56,0xab,0x4d, 0xab,0x55,0xac,0x50,0xaf,0x57,0xb1,0x51,0xb1,0x56,0xb5,0x51,0xb8,0x5a,0xb8,0x50, 0xb7,0x55,0xb7,0x51,0xb4,0x57,0xb1,0x4d,0xb1,0x58,0xaf,0x4d,0xad,0x5a,0xae,0x4e, 0xae,0x52,0xaf,0x4f,0xb1,0x54,0xb2,0x51,0xb5,0x58,0xb6,0x50,0xb6,0x58,0xb8,0x4e, 0xb5,0x58,0xad,0x4f,0xa7,0x55,0xac,0x4f,0xaa,0x58,0xa2,0x4f,0xa6,0x56,0xac,0x50, 0xb0,0x55,0xb2,0x52,0xb4,0x5a,0xb4,0x4d,0xb6,0x5a,0xb5,0x4c,0xb3,0x59,0xb2,0x50, 0xaf,0x57,0xac,0x4f,0xac,0x57,0xaa,0x4f,0xab,0x58,0xac,0x50,0xae,0x5a,0xb1,0x4e, 0xb5,0x57,0xb3,0x4d,0xb2,0x59,0xb4,0x4f,0xb3,0x5c,0xae,0x4e,0xab,0x58,0xaa,0x4d, 0xa9,0x58,0xa8,0x52,0xa8,0x56,0xaa,0x4c,0xad,0x5b,0xae,0x4e,0xb1,0x57,0xb0,0x4c, 0xb2,0x54,0xb4,0x4f,0xb1,0x56,0xad,0x50,0xad,0x5b,0xad,0x4f,0xa9,0x56,0xa9,0x4d, 0xa8,0x58,0xa9,0x53,0xad,0x55,0xb0,0x53,0xb2,0x5c,0xb3,0x54,0xb6,0x56,0xb4,0x50, 0xb2,0x5a,0xb1,0x4d,0xaf,0x57,0xae,0x53,0xaa,0x59,0xa8,0x4e,0xa9,0x55,0xac,0x4c, 0xad,0x5c,0xae,0x50,0xb1,0x58,0xb4,0x51,0xb4,0x5d,0xb3,0x50,0xb3,0x56,0xb1,0x4f, 0xaf,0x59,0xad,0x4e,0xac,0x57,0xaa,0x4e,0xab,0x5c,0xac,0x54,0xae,0x56,0xae,0x50, 0xb2,0x53,0xb4,0x53,0xb7,0x56,0xb3,0x57,0xb3,0x57,0xb5,0x4f,0xb0,0x58,0xab,0x53, 0xab,0x58,0xa8,0x52,0xa8,0x55,0xa9,0x52,0xab,0x5b,0xad,0x4f,0xb0,0x59,0xb1,0x4e, 0xb5,0x59,0xb3,0x51,0xb1,0x57,0xb1,0x52,0xb3,0x5b,0xaf,0x55,0xab,0x59,0xab,0x52, 0xac,0x5e,0xac,0x4e,0xac,0x5b,0xae,0x52,0xb1,0x5d,0xb3,0x53,0xb5,0x59,0xb4,0x52, 0xb6,0x5c,0xb4,0x4e,0xb1,0x55,0xaf,0x52,0xae,0x5d,0xad,0x4e,0xa9,0x55,0xa8,0x4f, 0xac,0x58,0xae,0x4f,0xaf,0x58,0xb1,0x4f,0xb6,0x5d,0xb4,0x4d,0xb4,0x59,0xb4,0x4e, 0xb3,0x59,0xb0,0x54,0xae,0x58,0xab,0x51,0xa8,0x58,0xa8,0x52,0xab,0x58,0xad,0x4e, 0xae,0x58,0xb1,0x51,0xb4,0x58,0xb6,0x4f,0xb6,0x5a,0xb2,0x4f,0xb0,0x58,0xae,0x4f, 0xae,0x58,0xa8,0x4b,0xa8,0x58,0xa9,0x4e,0xab,0x5b,0xac,0x52,0xae,0x5a,0xaf,0x4e, 0xb3,0x58,0xb2,0x53,0xb2,0x54,0xb1,0x51,0xb1,0x59,0xae,0x4c,0xab,0x57,0xab,0x4f, 0xa9,0x53,0xa7,0x52,0xa7,0x56,0xaa,0x4e,0xae,0x58,0xb1,0x4f,0xb1,0x59,0xb1,0x53, 0xb4,0x5a,0xb3,0x52,0xb0,0x55,0xaf,0x4d,0xad,0x5b,0xaa,0x50,0xa7,0x59,0xa7,0x4c, 0xa9,0x5b,0xac,0x4d,0xad,0x52,0xb0,0x4f,0xb4,0x5c,0xb5,0x54,0xb5,0x53,0xb4,0x52, 0xb4,0x58,0xb0,0x52,0xad,0x50,0xad,0x4b,0xa9,0x59,0xa6,0x52,0xab,0x56,0xaa,0x4e, 0xab,0x5c,0xad,0x50,0xb2,0x53,0xb5,0x4e,0xb4,0x5d,0xb2,0x50,0xb1,0x55,0xb0,0x4e, 0xae,0x5a,0xab,0x51,0xa8,0x52,0xa8,0x50,0xaa,0x59,0xaa,0x54,0xac,0x58,0xae,0x52, 0xb4,0x59,0xb4,0x50,0xb4,0x56,0xad,0x4d,0xb0,0x5b,0xb1,0x4e,0xa9,0x5d,0xa5,0x4b, 0xa9,0x57,0xa9,0x50,0xa7,0x59,0xaa,0x50,0xad,0x5b,0xae,0x53,0xb2,0x5a,0xb4,0x4e, 0xb5,0x5c,0xb3,0x50,0xb2,0x54,0xaf,0x50,0xad,0x5d,0xab,0x4f,0xa9,0x55,0xa7,0x52, 0xa6,0x59,0xa7,0x4d,0xaa,0x4f,0xae,0x48,0xb0,0x57,0xb2,0x54,0xb2,0x56,0xaf,0x50, 0xb2,0x58,0xa9,0x55,0xaf,0x44,0xaf,0x41,0xad,0x4b,0xab,0x43,0xad,0x4d,0xad,0x49, 0xb0,0x4d,0xb2,0x41,0xb4,0x48,0xb7,0x3f,0xb8,0x4d,0xb6,0x44,0xb5,0x4a,0xb2,0x3d, 0xb1,0x44,0xac,0x40,0xac,0x47,0xaa,0x3d,0xac,0x4a,0xac,0x41,0xaf,0x49,0xb1,0x42, 0xb4,0x4a,0xb7,0x3f,0xb6,0x45,0xb6,0x3a,0xb5,0x46,0xb2,0x41,0xb0,0x49,0xad,0x41, 0xac,0x49,0xaa,0x3e,0xaa,0x43,0xab,0x45,0xad,0x49,0xb0,0x42,0xb2,0x47,0xb2,0x40, 0xb5,0x4a,0xb4,0x40,0xb2,0x45,0xb0,0x40,0xaf,0x48,0xab,0x42,0xa9,0x49,0xa8,0x41, 0xa8,0x4a,0xa7,0x42,0xaa,0x47,0xae,0x42,0xb2,0x4a,0xb2,0x44,0xb3,0x4a,0xb3,0x3f, 0xb2,0x4b,0xb1,0x41,0xae,0x44,0xab,0x41,0xaa,0x4f,0xa6,0x42,0xa6,0x45,0xa7,0x43, 0xa8,0x46,0xaa,0x42,0xaf,0x44,0xaf,0x3e,0xb0,0x4b,0xb3,0x3f,0xb2,0x45,0xae,0x40, 0xae,0x48,0xac,0x42,0xa8,0x48,0xa7,0x42,0xa8,0x4b,0xa8,0x3d,0xab,0x4a,0xab,0x3e, 0xaf,0x45,0xb1,0x41,0xb1,0x44,0xb0,0x44,0xb1,0x4b,0xaf,0x43,0xac,0x4a,0xaa,0x3f, 0xa9,0x49,0xa7,0x3f,0xa6,0x4b,0xa6,0x3d,0xa8,0x4c,0xa9,0x41,0xac,0x47,0xae,0x44, 0xb1,0x49,0xb0,0x43,0xb1,0x46,0xb0,0x43,0xaf,0x48,0xa9,0x40,0xa8,0x44,0xa7,0x3f, 0xa6,0x4b,0xa4,0x40,0xa6,0x47,0xa7,0x43,0xab,0x4b,0xaf,0x44,0xaf,0x4c,0xb0,0x3f, 0xaf,0x4a,0xad,0x3f,0xab,0x43,0xa9,0x3e,0xa7,0x46,0xa5,0x40,0xa5,0x4e,0xa3,0x40, 0xa4,0x46,0xa7,0x42,0xa9,0x45,0xac,0x41,0xaf,0x4a,0xaf,0x3d,0xaf,0x49,0xaf,0x3b, 0xac,0x47,0xaa,0x3e,0xa7,0x44,0xa5,0x44,0xa4,0x4b,0xa3,0x41,0xa6,0x49,0xa7,0x3d, 0xa8,0x48,0xaa,0x42,0xae,0x4a,0xaf,0x3f,0xb0,0x4b,0xad,0x40,0xac,0x4b,0xa8,0x43, 0xa9,0x49,0xa6,0x42,0xa4,0x48,0xa3,0x42,0xa4,0x4b,0xa6,0x45,0xa7,0x46,0xaa,0x3d, 0xac,0x46,0xad,0x46,0xad,0x46,0xad,0x3f,0xab,0x4b,0xa7,0x41,0xa5,0x4b,0xa4,0x3e, 0xa2,0x48,0xa0,0x3c,0xa2,0x46,0xa3,0x3e,0xa7,0x4c,0xa7,0x42,0xab,0x4c,0xac,0x3d, 0xae,0x48,0xac,0x41,0xab,0x49,0xa8,0x43,0xa6,0x4b,0xa1,0x42,0xa0,0x47,0x9e,0x3e, 0xa1,0x49,0xa0,0x41,0xa3,0x48,0xa7,0x3f,0xaa,0x4b,0xa9,0x41,0xab,0x4c,0xab,0x43, 0xaa,0x4a,0xa7,0x42,0xa6,0x43,0xa4,0x3e,0xa2,0x4d,0xa0,0x41,0xa1,0x45,0xa1,0x44, 0xa2,0x47,0xa6,0x3e,0xa7,0x49,0xaa,0x3f,0xab,0x4d,0xa8,0x44,0xaa,0x4b,0xa5,0x3c, 0xa2,0x48,0xa0,0x41,0xa0,0x46,0x9b,0x40,0x9d,0x4c,0xa0,0x41,0xa3,0x48,0xa5,0x43, 0xa7,0x45,0xa9,0x3f,0xaa,0x45,0xa7,0x43,0xa8,0x4d,0xa6,0x40,0xa3,0x4a,0xa0,0x41, 0xa0,0x4b,0x9f,0x3e,0x9e,0x47,0xa0,0x3e,0xa2,0x47,0xa5,0x42,0xa5,0x46,0xa6,0x40, 0xa9,0x48,0xaa,0x3f,0xa7,0x47,0xa5,0x41,0xa4,0x4c,0xa2,0x3e,0xa1,0x48,0x9e,0x3f, 0x9e,0x49,0x9e,0x44,0xa1,0x4c,0xa3,0x41,0xa6,0x48,0xa9,0x40,0xab,0x4b,0xa8,0x40, 0xaa,0x4b,0xaa,0x3f,0xa5,0x48,0xa3,0x41,0xa4,0x4e,0x9f,0x40,0x9d,0x4a,0x9d,0x41, 0xa2,0x49,0xa2,0x43,0xa5,0x46,0xa9,0x40,0xab,0x4f,0xa9,0x42,0xab,0x49,0xa9,0x3d, 0xa6,0x4a,0xa4,0x3e,0xa1,0x48,0x9f,0x42,0x9f,0x4b,0xa0,0x3d,0xa2,0x4a,0xa3,0x3f, 0xa5,0x4c,0xa7,0x40,0xa9,0x4b,0xa7,0x41,0xa7,0x4b,0xa7,0x41,0xa5,0x4a,0xa0,0x3c, 0x9f,0x4a,0x9d,0x42,0x9c,0x49,0x9d,0x45,0x9e,0x4b,0xa1,0x41,0xa4,0x49,0xa4,0x40, 0xa7,0x46,0xa7,0x3f,0xa7,0x46,0xa5,0x3e,0xa4,0x4a,0xa1,0x44,0x9f,0x49,0x9d,0x40, 0x9e,0x48,0x9d,0x40,0x9e,0x48,0xa2,0x3e,0xa4,0x4b,0xa6,0x41,0xa9,0x45,0xa8,0x40, 0xa9,0x48,0xa8,0x41,0xa6,0x48,0xa3,0x43,0xa0,0x4b,0x9e,0x40,0x9e,0x48,0x9d,0x41, 0xa1,0x49,0xa1,0x40,0xa4,0x49,0xa7,0x3f,0xa9,0x49,0xa8,0x42,0xaa,0x4a,0xaa,0x3f, 0xa8,0x4b,0xa4,0x40,0xa0,0x47,0x9d,0x41,0x9c,0x4c,0x9c,0x42,0x9d,0x4c,0x9c,0x40, 0xa3,0x49,0xa2,0x40,0xa2,0x48,0xa4,0x46,0xa8,0x4c,0xa6,0x43,0xa2,0x49,0xa2,0x42, 0xa0,0x4c,0x9c,0x3d,0x9d,0x47,0x9c,0x3e,0x9d,0x4b,0x9f,0x3f,0xa2,0x48,0xa5,0x44, 0xa5,0x4b,0xa8,0x3e,0xa7,0x45,0xa8,0x3f,0xa7,0x4b,0xa5,0x43,0xa1,0x47,0x9e,0x45, 0x9e,0x46,0x9c,0x3f,0x9d,0x48,0x9f,0x3e,0xa0,0x51,0xa3,0x42,0xa7,0x4a,0xa7,0x41, 0xa8,0x4c,0xa7,0x3f,0xa8,0x46,0xa5,0x3e,0xa1,0x4f,0x9f,0x41,0x9e,0x46,0x9c,0x41, 0x9f,0x4a,0xa1,0x3d,0xa2,0x4b,0xa5,0x3f,0xa7,0x4a,0xa8,0x41,0xa8,0x4b,0xa7,0x3b, 0xa7,0x48,0xa5,0x40,0xa3,0x47,0x9f,0x3e,0x9e,0x4a,0x9d,0x40,0x9f,0x4b,0x9f,0x42, 0xa2,0x45,0xa4,0x42,0xa7,0x44,0xa7,0x41,0xa9,0x4b,0xa7,0x40,0xa8,0x49,0xa6,0x45, 0xa3,0x47,0x9e,0x42,0x9d,0x48,0x9c,0x41,0x9c,0x4b,0x9d,0x41,0x9f,0x4b,0xa1,0x40, 0xa6,0x48,0xa7,0x41,0xa8,0x4c,0xa6,0x3e,0xa7,0x4b,0xa6,0x3d,0xa2,0x48,0xa0,0x3f, 0x9e,0x4b,0x9d,0x43,0x9c,0x49,0x9d,0x3d,0x9f,0x4b,0xa3,0x3f,0xa6,0x49,0xa7,0x43, 0xa8,0x4b,0xa8,0x41,0xa8,0x48,0xa5,0x40,0xa4,0x4d,0xa1,0x41,0x9d,0x47,0x9b,0x42, 0x9a,0x48,0x9c,0x43,0x9f,0x46,0x9f,0x40,0xa4,0x47,0xa6,0x42,0xa8,0x49,0xa8,0x42, 0xa9,0x4b,0xa7,0x3f,0xa3,0x47,0xa0,0x3e,0xa0,0x4e,0x9d,0x40,0x9c,0x45,0x9d,0x43, 0xa1,0x48,0xa3,0x3f,0xa4,0x46,0xa7,0x3f,0xa8,0x4d,0xa8,0x40,0xa8,0x4b,0xa6,0x3f, 0xa5,0x47,0xa1,0x3c,0x9d,0x45,0x9c,0x3d,0x9d,0x4c,0x9b,0x3f,0x9d,0x4c,0xa1,0x3f, 0xa5,0x4c,0xa7,0x43,0xa7,0x47,0xa9,0x3f,0xa9,0x4b,0xa5,0x3e,0xa3,0x48,0xa2,0x3e, 0xa0,0x47,0x9c,0x40,0x9a,0x49,0x9b,0x46,0x9e,0x50,0xa0,0x3f,0xa4,0x41,0xa5,0x38, 0xa8,0x47,0xa8,0x40,0xa6,0x43,0xa4,0x40,0xa3,0x4d,0x9a,0x44,0xa1,0x54,0x9f,0x52, 0xa0,0x56,0xa2,0x56,0xa4,0x62,0xa8,0x57,0xaa,0x62,0xab,0x55,0xac,0x59,0xac,0x55, 0xac,0x56,0xab,0x4e,0xa7,0x55,0xa5,0x4e,0xa3,0x5d,0xa0,0x54,0xa2,0x56,0xa1,0x51, 0xa4,0x57,0xa7,0x4f,0xa9,0x5a,0xaa,0x53,0xad,0x5e,0xac,0x4c,0xaa,0x58,0xac,0x4d, 0xa8,0x55,0xa5,0x4f,0xa4,0x54,0x9f,0x53,0xa0,0x5d,0xa0,0x50,0xa1,0x56,0xa3,0x4f, 0xa7,0x58,0xaa,0x54,0xaa,0x58,0xaa,0x4e,0xaa,0x58,0xab,0x4e,0xa6,0x56,0xa2,0x54, 0xa3,0x5c,0xa0,0x54,0x9d,0x54,0x9d,0x50,0xa1,0x58,0xa2,0x54,0xa6,0x5c,0xa9,0x4d, 0xaa,0x5b,0xaa,0x51,0xab,0x55,0xaa,0x4b,0xa7,0x5b,0xa4,0x52,0xa2,0x5a,0x9f,0x51, 0xa0,0x56,0x9f,0x4f,0xa1,0x59,0xa2,0x51,0xa7,0x59,0xa8,0x53,0xab,0x5e,0xab,0x51, 0xab,0x59,0xaa,0x53,0xa8,0x56,0xa4,0x4f,0xa2,0x5a,0x9f,0x4e,0x9d,0x59,0x9e,0x52, 0xa0,0x5b,0xa1,0x52,0xa4,0x5a,0xa7,0x4f,0xa9,0x5d,0xaa,0x4f,0xac,0x5c,0xa7,0x50, 0xa7,0x59,0xa4,0x51,0xa0,0x55,0x9d,0x50,0x9d,0x5d,0x9b,0x50,0x9d,0x58,0x9e,0x54, 0xa2,0x57,0xa6,0x4f,0xa8,0x56,0xa8,0x54,0xa9,0x5d,0xaa,0x4d,0xa6,0x59,0xa3,0x51, 0xa4,0x5c,0xa0,0x50,0x9d,0x58,0x9e,0x55,0x9f,0x5b,0xa1,0x54,0xa1,0x58,0xa5,0x52, 0xa8,0x59,0xa7,0x4f,0xa8,0x58,0xa8,0x54,0xa7,0x5c,0xa2,0x53,0xa2,0x59,0x9f,0x4e, 0x9e,0x58,0x9e,0x4f,0x9f,0x59,0xa0,0x54,0xa3,0x5f,0xa4,0x50,0xa7,0x57,0xa8,0x50, 0xa9,0x58,0xa7,0x50,0xa7,0x57,0xa4,0x4f,0xa0,0x5b,0x9e,0x4f,0x9d,0x59,0x9a,0x50, 0x9c,0x5b,0x9e,0x54,0xa0,0x59,0xa2,0x53,0xa5,0x5f,0xa6,0x52,0xa8,0x5d,0xa6,0x52, 0xa4,0x56,0xa1,0x51,0xa0,0x58,0x9e,0x54,0x9d,0x5c,0x9a,0x51,0x9c,0x5e,0x9d,0x51, 0x9f,0x57,0xa2,0x52,0xa5,0x5a,0xa4,0x54,0xa8,0x5e,0xa7,0x52,0xa6,0x58,0xa2,0x54, 0xa2,0x5d,0x9e,0x51,0x9c,0x57,0x9c,0x51,0x9c,0x5c,0x9b,0x4d,0x9f,0x58,0xa2,0x4f, 0xa5,0x5d,0xa5,0x4d,0xa7,0x57,0xa6,0x53,0xa5,0x57,0xa2,0x55,0x9f,0x5a,0x9e,0x52, 0x9c,0x5e,0x98,0x50,0x99,0x5b,0x9b,0x53,0x9f,0x58,0xa0,0x4e,0xa2,0x55,0xa4,0x54, 0xa4,0x59,0xa4,0x51,0xa4,0x5c,0xa1,0x52,0x9f,0x59,0x9c,0x51,0x9b,0x55,0x99,0x4f, 0x99,0x5c,0x99,0x54,0x9b,0x54,0x9e,0x51,0xa3,0x5e,0xa3,0x55,0xa3,0x58,0xa4,0x4e, 0xa6,0x5f,0xa1,0x52,0x9f,0x59,0x9d,0x53,0x9d,0x5e,0x99,0x50,0x99,0x59,0x99,0x51, 0x9c,0x59,0x9d,0x51,0xa0,0x58,0xa2,0x52,0xa4,0x5b,0xa5,0x4d,0xa5,0x5a,0xa0,0x52, 0x9f,0x55,0x9c,0x51,0x9b,0x59,0x96,0x4f,0x96,0x59,0x98,0x52,0x9a,0x58,0x9c,0x51, 0x9f,0x5a,0xa2,0x56,0xa4,0x59,0xa3,0x51,0xa3,0x57,0xa1,0x52,0x9e,0x55,0x9b,0x54, 0x9a,0x5a,0x97,0x54,0x97,0x55,0x97,0x50,0x99,0x55,0x99,0x51,0x9d,0x55,0xa1,0x4d, 0xa0,0x5a,0xa1,0x55,0xa2,0x5c,0x9f,0x51,0x9f,0x5c,0x9c,0x4a,0x9b,0x5b,0x96,0x54, 0x95,0x5c,0x95,0x52,0x98,0x5a,0x9a,0x51,0x9d,0x58,0xa0,0x4f,0xa0,0x53,0xa1,0x51, 0xa2,0x5c,0x9f,0x55,0x9d,0x59,0x9b,0x50,0x98,0x5c,0x96,0x55,0x94,0x58,0x94,0x52, 0x96,0x60,0x98,0x55,0x9c,0x58,0x9e,0x53,0xa1,0x5a,0xa0,0x53,0xa0,0x5a,0x9f,0x54, 0x9e,0x5b,0x9a,0x50,0x99,0x57,0x96,0x54,0x95,0x5c,0x94,0x55,0x95,0x5c,0x98,0x52, 0x9b,0x5c,0x9c,0x56,0x9e,0x59,0xa1,0x4e,0x9f,0x5c,0x9c,0x51,0x9c,0x5a,0x9b,0x55, 0x97,0x58,0x93,0x53,0x93,0x5a,0x92,0x55,0x94,0x5a,0x94,0x52,0x98,0x5d,0x9c,0x57, 0x9d,0x56,0x9e,0x51,0x9f,0x58,0x9c,0x53,0x9b,0x5b,0x98,0x50,0x98,0x5b,0x94,0x55, 0x92,0x5a,0x93,0x4f,0x95,0x55,0x94,0x54,0x98,0x5a,0x9a,0x4f,0x9d,0x58,0x9c,0x4f, 0x9d,0x58,0x9c,0x52,0x9c,0x54,0x99,0x4f,0x97,0x5b,0x93,0x52,0x91,0x5b,0x90,0x50, 0x92,0x5b,0x94,0x52,0x95,0x5a,0x98,0x50,0x9c,0x5e,0x9c,0x56,0x9e,0x5c,0x9c,0x51, 0x9e,0x5f,0x9a,0x55,0x98,0x5a,0x93,0x51,0x92,0x5a,0x92,0x4f,0x92,0x58,0x93,0x50, 0x96,0x5c,0x99,0x54,0x9c,0x58,0x9b,0x51,0x9c,0x5a,0x9c,0x53,0x9d,0x59,0x98,0x51, 0x96,0x5c,0x96,0x51,0x94,0x59,0x91,0x51,0x92,0x5a,0x95,0x52,0x97,0x59,0x99,0x53, 0x9d,0x5c,0x9d,0x51,0xa0,0x5b,0xa0,0x50,0xa0,0x5b,0x9d,0x50,0x9c,0x5b,0x98,0x52, 0x96,0x5a,0x95,0x55,0x95,0x51,0x95,0x50,0x99,0x5b,0x9a,0x55,0x9d,0x5a,0x9f,0x52, 0xa1,0x5b,0xa0,0x53,0xa0,0x57,0x9e,0x4e,0x9b,0x5a,0x98,0x52,0x97,0x5d,0x94,0x4f, 0x94,0x59,0x95,0x53,0x98,0x59,0x99,0x50,0x9c,0x59,0x9d,0x53,0xa0,0x59,0x9f,0x50, 0xa0,0x5a,0x9e,0x54,0x9c,0x57,0x97,0x58,0x96,0x5b,0x94,0x4f,0x93,0x58,0x93,0x51, 0x97,0x56,0x9a,0x52,0x9c,0x57,0x9d,0x50,0x9f,0x5a,0xa0,0x50,0xa0,0x59,0x9c,0x51, 0x9c,0x57,0x9a,0x53,0x96,0x55,0x92,0x54,0x92,0x59,0x91,0x52,0x95,0x5a,0x99,0x4e, 0x9c,0x5a,0x9d,0x51,0xa0,0x59,0x9f,0x50,0x9f,0x58,0x9e,0x54,0x9b,0x57,0x98,0x52, 0x98,0x59,0x94,0x51,0x93,0x5b,0x94,0x4f,0x98,0x5a,0x99,0x52,0x9d,0x5c,0x9f,0x53, 0xa0,0x5a,0xa1,0x50,0xa2,0x5b,0x9e,0x50,0x9d,0x5d,0x9b,0x54,0x98,0x59,0x95,0x4f, 0x94,0x55,0x95,0x50,0x97,0x55,0x99,0x53,0x9c,0x56,0xa0,0x54,0xa3,0x58,0xa2,0x52, 0xa2,0x58,0xa2,0x4e,0xa0,0x5c,0x9a,0x4f,0x96,0x5b,0x93,0x51,0x92,0x58,0x93,0x4a, 0x97,0x5c,0x98,0x53,0x9c,0x60,0xa0,0x54,0xa3,0x5a,0xa2,0x51,0xa3,0x57,0xa3,0x4e, 0xa2,0x5b,0x9e,0x4d,0x9c,0x5a,0x99,0x51,0x99,0x5d,0x98,0x4e,0x9a,0x5a,0x9b,0x54, 0x9d,0x5a,0xa0,0x4f,0xa3,0x53,0xa1,0x46,0xa3,0x58,0xa2,0x4d,0xa1,0x5a,0x9d,0x51, 0x9b,0x5b,0x94,0x55,0x9c,0x4b,0x9c,0x46,0x9e,0x4f,0xa2,0x4d,0xa5,0x5c,0xa7,0x4f, 0xa9,0x54,0xaa,0x4c,0xa8,0x51,0xa5,0x48,0xa4,0x52,0xa1,0x47,0x9f,0x4f,0x9d,0x4d, 0x9c,0x52,0x9d,0x46,0x9f,0x53,0x9f,0x45,0xa4,0x51,0xa5,0x47,0xa5,0x51,0xa8,0x48, 0xa9,0x4f,0xa5,0x47,0xa4,0x4f,0xa1,0x49,0x9e,0x55,0x9b,0x4c,0x9a,0x50,0x9c,0x47, 0x9d,0x4f,0xa1,0x47,0xa3,0x51,0xa5,0x49,0xa7,0x50,0xa9,0x47,0xa8,0x52,0xa6,0x47, 0xa4,0x53,0xa2,0x47,0x9f,0x4f,0x9b,0x48,0x9b,0x51,0x9b,0x4d,0x9e,0x4e,0x9f,0x49, 0xa2,0x4e,0xa4,0x48,0xa6,0x52,0xa7,0x4b,0xa7,0x50,0xa8,0x48,0xa5,0x50,0xa3,0x4c, 0x9f,0x52,0x9c,0x4b,0x99,0x51,0x9a,0x4a,0x9a,0x52,0x9d,0x48,0xa0,0x50,0xa4,0x49, 0xa6,0x4f,0xa7,0x48,0xa8,0x4b,0xa5,0x4d,0xa5,0x52,0xa1,0x4b,0x9e,0x51,0x9c,0x4d, 0x9b,0x4f,0x99,0x4a,0x9c,0x50,0x9c,0x4c,0xa0,0x52,0xa5,0x48,0xa5,0x51,0xa6,0x49, 0xa9,0x4f,0xa7,0x49,0xa6,0x4f,0xa1,0x49,0x9f,0x56,0x9d,0x45,0x9b,0x4f,0x9a,0x4c, 0x9b,0x51,0x9d,0x4b,0x9f,0x53,0xa3,0x46,0xa4,0x54,0xa6,0x4b,0xa8,0x4e,0xa5,0x49, 0xa3,0x50,0xa1,0x49,0xa0,0x4d,0x9b,0x4b,0x98,0x52,0x98,0x4b,0x9a,0x4d,0x9b,0x4a, 0x9d,0x50,0xa1,0x48,0xa4,0x50,0xa2,0x49,0xa4,0x53,0xa6,0x4a,0xa3,0x50,0x9f,0x4a, 0x9f,0x50,0x9b,0x48,0x9a,0x51,0x99,0x48,0x99,0x54,0x9c,0x4a,0x9e,0x4e,0xa0,0x48, 0xa3,0x4f,0xa5,0x49,0xa5,0x4f,0xa4,0x47,0xa4,0x54,0xa2,0x4a,0x9f,0x52,0x9c,0x44, 0x99,0x52,0x99,0x4a,0x98,0x50,0x9a,0x49,0x9b,0x51,0x9f,0x49,0xa3,0x52,0xa3,0x4a, 0xa5,0x50,0xa5,0x4a,0xa3,0x52,0xa2,0x4b,0x9e,0x52,0x9c,0x48,0x9a,0x52,0x99,0x4c, 0x98,0x53,0x99,0x48,0x9d,0x4e,0x9e,0x48,0xa1,0x52,0xa3,0x46,0xa5,0x52,0xa5,0x4e, 0xa3,0x52,0xa2,0x4c,0xa0,0x4d,0x9d,0x46,0x9a,0x52,0x99,0x4c,0x99,0x54,0x9b,0x49, 0x9c,0x54,0x9e,0x49,0xa2,0x52,0xa2,0x4b,0xa4,0x53,0xa5,0x4d,0xa3,0x52,0xa2,0x47, 0xa0,0x54,0x9a,0x4b,0x97,0x52,0x97,0x47,0x95,0x51,0x97,0x48,0x98,0x50,0x9a,0x51, 0x9f,0x55,0xa2,0x4a,0xa2,0x51,0xa2,0x47,0xa2,0x4e,0xa2,0x4c,0xa0,0x54,0x9b,0x49, 0x9a,0x4f,0x98,0x49,0x95,0x51,0x97,0x49,0x99,0x54,0x9d,0x4c,0x9f,0x51,0xa2,0x4b, 0xa2,0x53,0xa3,0x49,0xa3,0x4d,0xa1,0x47,0x9e,0x50,0x9c,0x4e,0x99,0x54,0x97,0x4a, 0x96,0x50,0x96,0x48,0x99,0x50,0x9b,0x48,0x9e,0x55,0xa1,0x4c,0xa3,0x55,0xa3,0x4c, 0xa3,0x52,0xa1,0x4b,0xa0,0x4f,0x9b,0x48,0x9a,0x54,0x97,0x49,0x94,0x50,0x96,0x44, 0x99,0x50,0x9a,0x48,0x9c,0x51,0x9f,0x46,0xa1,0x50,0xa3,0x46,0xa2,0x55,0xa1,0x4b, 0x9e,0x50,0x9c,0x49,0x99,0x50,0x95,0x49,0x94,0x53,0x95,0x48,0x97,0x4d,0x9a,0x4b, 0x9d,0x51,0x9f,0x47,0x9f,0x51,0xa0,0x46,0xa2,0x4e,0xa0,0x46,0x9c,0x53,0x9b,0x4a, 0x96,0x56,0x95,0x4d,0x93,0x54,0x94,0x48,0x95,0x56,0x97,0x4d,0x9b,0x54,0x9e,0x47, 0xa0,0x53,0xa0,0x4b,0xa0,0x52,0xa0,0x45,0x9d,0x54,0x9b,0x4c,0x97,0x50,0x96,0x4a, 0x94,0x52,0x95,0x4e,0x96,0x52,0x98,0x4a,0x9b,0x4f,0x9b,0x52,0x9e,0x50,0x9f,0x49, 0xa0,0x55,0x9f,0x49,0x9e,0x4e,0x9a,0x49,0x98,0x56,0x94,0x4c,0x95,0x53,0x93,0x4a, 0x93,0x51,0x97,0x4c,0x98,0x50,0x9c,0x4a,0xa0,0x56,0xa0,0x4c,0x9d,0x56,0x9f,0x4e, 0xa0,0x52,0x9c,0x4b,0x98,0x53,0x96,0x48,0x94,0x54,0x92,0x49,0x93,0x53,0x98,0x4a, 0x99,0x51,0x9b,0x48,0x9e,0x51,0x9f,0x49,0xa1,0x57,0xa0,0x47,0x9e,0x51,0x9d,0x4b, 0x99,0x50,0x98,0x4a,0x94,0x53,0x93,0x4b,0x93,0x52,0x96,0x4b,0x99,0x55,0x9c,0x48, 0x9d,0x53,0xa2,0x4c,0xa1,0x53,0x9f,0x4d,0x9e,0x56,0x9f,0x4c,0x9b,0x4f,0x96,0x46, 0x95,0x57,0x94,0x47,0x94,0x52,0x97,0x4b,0x9b,0x5b,0x9c,0x4b,0x9e,0x51,0xa0,0x4d, 0xa1,0x52,0xa2,0x4d,0xa0,0x50,0x9e,0x49,0x9b,0x52,0x99,0x4b,0x97,0x50,0x95,0x4c, 0x95,0x53,0x98,0x4a,0x9a,0x52,0x9c,0x49,0x9f,0x4c,0xa0,0x50,0xa2,0x53,0xa1,0x4b, 0xa0,0x50,0x9f,0x4b,0x9c,0x52,0x97,0x4b,0x94,0x51,0x93,0x49,0x96,0x54,0x96,0x4b, 0x99,0x51,0x9c,0x4a,0xa0,0x52,0xa3,0x49,0xa3,0x4e,0xa1,0x49,0xa0,0x52,0xa0,0x48, 0x9e,0x54,0x9b,0x4c,0x99,0x54,0x96,0x4a,0x96,0x53,0x98,0x4b,0x99,0x55,0x9d,0x4c, 0xa0,0x51,0xa2,0x49,0xa3,0x51,0xa2,0x4b,0xa3,0x54,0xa2,0x4d,0x9f,0x53,0x9d,0x4a, 0x9a,0x55,0x9a,0x4c,0x99,0x4d,0x9a,0x4a,0x9c,0x56,0x9e,0x46,0xa1,0x53,0xa4,0x48, 0xa5,0x55,0xa6,0x4c,0xa4,0x50,0xa4,0x48,0xa0,0x50,0x9e,0x48,0x9c,0x54,0x99,0x48, 0x98,0x56,0x99,0x4b,0x9b,0x4d,0x9e,0x46,0xa0,0x53,0xa2,0x4b,0xa5,0x4e,0xa5,0x49, 0xa4,0x55,0xa3,0x50,0xa0,0x50,0x9d,0x4a,0x9c,0x51,0x9a,0x4b,0x97,0x55,0x99,0x4b, 0x9b,0x54,0x9f,0x4c,0xa1,0x54,0xa4,0x45,0xa5,0x56,0xa6,0x4a,0xa6,0x50,0xa5,0x4d, 0xa2,0x54,0xa0,0x4a,0x9d,0x4f,0x9a,0x4c,0x9a,0x51,0x99,0x4a,0x9b,0x50,0x9e,0x48, 0xa1,0x55,0xa4,0x4e,0xa5,0x50,0xa5,0x49,0xa7,0x59,0xa3,0x48,0xa3,0x58,0xa0,0x48, 0x9d,0x57,0x99,0x49,0x9a,0x4f,0x9b,0x4b,0x9c,0x55,0x9d,0x4d,0x9e,0x54,0xa1,0x4b, 0xa6,0x54,0xa4,0x4c,0xa2,0x51,0xa2,0x4e,0xa4,0x4e,0x9e,0x4b,0x9b,0x51,0x9a,0x48, 0x9a,0x54,0x9b,0x4c,0x9b,0x50,0x9c,0x4a,0xa0,0x55,0xa3,0x4b,0xa6,0x53,0xa6,0x4b, 0xa6,0x56,0xa5,0x4b,0xa4,0x54,0xa2,0x4c,0x9e,0x52,0x9c,0x4d,0x9b,0x52,0x99,0x49, 0x9b,0x56,0x9e,0x4e,0x9f,0x4f,0xa2,0x4b,0xa6,0x54,0xa7,0x47,0xa6,0x48,0xa6,0x43, 0xa5,0x4e,0xa2,0x49,0xa1,0x4e,0x9b,0x48,0x98,0x52,0x95,0x4f,0xa1,0x35,0xa4,0x30, 0xa9,0x3b,0xab,0x3b,0xad,0x46,0xac,0x3b,0xad,0x44,0xad,0x3b,0xa9,0x3a,0xa6,0x35, 0xa5,0x3e,0xa1,0x35,0x9e,0x39,0x9f,0x33,0xa3,0x3c,0xa5,0x33,0xa9,0x3d,0xaa,0x35, 0xad,0x42,0xae,0x33,0xae,0x3b,0xac,0x33,0xab,0x3d,0xa8,0x37,0xa5,0x3a,0xa2,0x38, 0xa0,0x3b,0xa1,0x36,0xa4,0x38,0xa5,0x35,0xa9,0x3d,0xad,0x33,0xae,0x3a,0xaf,0x32, 0xb1,0x3c,0xb0,0x35,0xae,0x36,0xaa,0x33,0xa8,0x3b,0xa5,0x3a,0xa4,0x3b,0xa4,0x36, 0xa5,0x3d,0xa6,0x36,0xaa,0x39,0xad,0x32,0xae,0x40,0xb0,0x34,0xb0,0x3b,0xaf,0x35, 0xaf,0x3d,0xab,0x35,0xa8,0x3d,0xa4,0x32,0xa4,0x3c,0xa5,0x36,0xa4,0x3c,0xa5,0x32, 0xa9,0x37,0xab,0x32,0xaf,0x3b,0xae,0x33,0xb0,0x3c,0xb0,0x32,0xad,0x3a,0xaa,0x33, 0xa9,0x3d,0xa7,0x35,0xa4,0x3b,0xa2,0x34,0xa6,0x42,0xa7,0x32,0xaa,0x3f,0xae,0x32, 0xb0,0x3c,0xb0,0x36,0xb3,0x3d,0xb1,0x32,0xb1,0x3d,0xad,0x31,0xa9,0x40,0xa7,0x36, 0xa6,0x3d,0xa3,0x33,0xa4,0x3b,0xa7,0x38,0xa9,0x3e,0xad,0x37,0xb0,0x39,0xaf,0x38, 0xb2,0x3d,0xb0,0x38,0xaf,0x3b,0xad,0x35,0xa9,0x3e,0xa5,0x33,0xa3,0x3c,0xa2,0x39, 0xa3,0x3e,0xa4,0x31,0xa7,0x3d,0xaa,0x33,0xac,0x3a,0xaf,0x38,0xb0,0x34,0xaf,0x39, 0xac,0x40,0xac,0x33,0xa9,0x3b,0xa4,0x35,0xa2,0x3a,0xa0,0x36,0xa2,0x3d,0xa3,0x33, 0xa6,0x3e,0xaa,0x34,0xac,0x3c,0xae,0x36,0xae,0x3f,0xaf,0x2f,0xaf,0x3d,0xac,0x34, 0xa9,0x3f,0xa6,0x35,0xa4,0x39,0xa1,0x35,0xa1,0x40,0xa0,0x35,0xa4,0x3d,0xa9,0x33, 0xaa,0x3a,0xab,0x35,0xae,0x3b,0xaf,0x33,0xac,0x3e,0xaa,0x34,0xaa,0x3a,0xa7,0x39, 0xa3,0x40,0xa2,0x35,0xa2,0x39,0xa1,0x33,0xa7,0x3f,0xa7,0x33,0xab,0x3e,0xae,0x38, 0xaf,0x42,0xaf,0x35,0xb0,0x3d,0xac,0x33,0xaa,0x3e,0xa8,0x35,0xa6,0x39,0xa3,0x38, 0xa2,0x39,0xa4,0x37,0xa7,0x3c,0xa9,0x34,0xac,0x3c,0xae,0x37,0xb0,0x3d,0xb0,0x34, 0xb0,0x3e,0xae,0x33,0xab,0x3e,0xa7,0x32,0xa5,0x41,0xa3,0x32,0xa3,0x3d,0xa4,0x38, 0xa6,0x3b,0xa6,0x34,0xac,0x39,0xae,0x38,0xb0,0x41,0xaf,0x33,0xb0,0x3b,0xad,0x31, 0xaa,0x3e,0xa7,0x34,0xa6,0x3a,0xa2,0x33,0xa2,0x3f,0xa2,0x34,0xa5,0x3e,0xa8,0x35, 0xab,0x3e,0xae,0x37,0xb0,0x3a,0xaf,0x36,0xb0,0x3d,0xb0,0x32,0xae,0x3a,0xa9,0x34, 0xa9,0x3d,0xa4,0x35,0xa3,0x3e,0xa4,0x37,0xa6,0x3f,0xa7,0x33,0xad,0x3b,0xad,0x32, 0xb0,0x3c,0xb0,0x34,0xb1,0x3f,0xae,0x38,0xab,0x3b,0xa8,0x35,0xa5,0x39,0xa1,0x34, 0xa0,0x3b,0xa1,0x31,0xa3,0x3b,0xa5,0x34,0xa8,0x40,0xad,0x37,0xad,0x3e,0xaf,0x37, 0xb1,0x3c,0xae,0x33,0xab,0x3b,0xa9,0x38,0xa6,0x3d,0xa3,0x32,0xa2,0x3d,0xa1,0x32, 0xa4,0x3b,0xa6,0x33,0xa9,0x3c,0xac,0x36,0xae,0x40,0xaf,0x34,0xb0,0x3e,0xae,0x32, 0xae,0x3c,0xab,0x35,0xa9,0x3b,0xa5,0x36,0xa3,0x3b,0xa2,0x35,0xa3,0x42,0xa7,0x37, 0xa7,0x42,0xac,0x37,0xae,0x37,0xae,0x35,0xb1,0x3c,0xae,0x37,0xae,0x3d,0xab,0x39, 0xa9,0x3d,0xa4,0x3c,0xa3,0x3a,0xa2,0x35,0xa3,0x41,0xa5,0x38,0xa7,0x41,0xaa,0x34, 0xaf,0x3e,0xae,0x38,0xb0,0x3d,0xaf,0x34,0xae,0x46,0xaa,0x38,0xa8,0x39,0xa5,0x36, 0xa4,0x3e,0xa2,0x34,0xa3,0x3e,0xa4,0x36,0xa6,0x40,0xaa,0x38,0xad,0x3e,0xad,0x3a, 0xaf,0x3b,0xaf,0x37,0xad,0x3d,0xaa,0x36,0xa6,0x42,0xa4,0x38,0xa2,0x40,0xa1,0x36, 0xa2,0x43,0xa3,0x30,0xa7,0x3e,0xaa,0x36,0xad,0x44,0xac,0x3a,0xad,0x3e,0xad,0x38, 0xac,0x40,0xa8,0x36,0xa5,0x3d,0xa5,0x36,0xa0,0x45,0x9e,0x37,0xa0,0x3f,0xa4,0x33, 0xa5,0x3f,0xa7,0x35,0xaa,0x3d,0xac,0x35,0xae,0x40,0xae,0x3a,0xab,0x3f,0xa9,0x35, 0xa8,0x3f,0xa2,0x34,0xa2,0x37,0xa0,0x38,0x9f,0x40,0xa0,0x33,0xa4,0x3f,0xa6,0x36, 0xab,0x3e,0xac,0x38,0xad,0x3d,0xae,0x39,0xaf,0x3f,0xaa,0x3a,0xa7,0x3a,0xa6,0x35, 0xa4,0x41,0xa1,0x3b,0xa1,0x3c,0xa1,0x33,0xa2,0x40,0xa4,0x37,0xa8,0x3b,0xaa,0x36, 0xad,0x3e,0xac,0x38,0xab,0x3b,0xa9,0x37,0xa9,0x43,0xa5,0x38,0xa2,0x3e,0xa0,0x38, 0xa2,0x3f,0xa2,0x35,0xa4,0x3c,0xa6,0x37,0xaa,0x44,0xac,0x37,0xad,0x41,0xad,0x33, 0xb0,0x3e,0xac,0x35,0xaa,0x3c,0xa7,0x38,0xa4,0x3e,0xa2,0x35,0xa1,0x3c,0xa1,0x34, 0xa5,0x3f,0xa5,0x33,0xa8,0x3d,0xa9,0x35,0xac,0x46,0xad,0x38,0xab,0x3f,0xab,0x32, 0xab,0x3c,0xa6,0x39,0xa5,0x3b,0xa3,0x37,0xa1,0x41,0xa1,0x38,0xa2,0x41,0xa6,0x36, 0xa8,0x3e,0xac,0x37,0xae,0x40,0xb0,0x37,0xae,0x45,0xad,0x39,0xac,0x3e,0xa8,0x38, 0xa7,0x3e,0xa3,0x36,0xa1,0x3c,0xa1,0x32,0xa3,0x42,0xa4,0x37,0xa9,0x3a,0xaa,0x37, 0xac,0x42,0xad,0x32,0xad,0x42,0xab,0x31,0xab,0x41,0xa7,0x35,0xa5,0x40,0xa4,0x35, 0xa1,0x3e,0xa2,0x33,0xa3,0x3f,0xa5,0x39,0xa9,0x3e,0xab,0x38,0xae,0x3f,0xaf,0x36, 0xaf,0x3c,0xad,0x34,0xac,0x40,0xa9,0x38,0xa6,0x3e,0xa3,0x37,0xa2,0x3e,0xa1,0x34, 0xa3,0x40,0xa6,0x34,0xa8,0x3c,0xac,0x35,0xae,0x3f,0xad,0x37,0xaf,0x3e,0xae,0x38, 0xae,0x3f,0xa8,0x3d,0xa7,0x3d,0xa4,0x35,0xa1,0x3c,0xa1,0x36,0xa0,0x42,0xa2,0x35, 0xa7,0x3e,0xaa,0x36,0xab,0x3a,0xab,0x34,0xac,0x44,0xad,0x37,0xab,0x38,0xa9,0x36, 0xa8,0x40,0xa2,0x36,0xa2,0x40,0xa2,0x33,0x9f,0x40,0xa1,0x35,0xa8,0x41,0xaa,0x35, 0xa9,0x3c,0xad,0x3a,0xaf,0x3d,0xad,0x3a,0xac,0x3f,0xaa,0x37,0xa8,0x3f,0xa6,0x36, 0xa2,0x40,0xa2,0x37,0xa4,0x3e,0xa5,0x34,0xa8,0x42,0xaa,0x33,0xae,0x3d,0xad,0x3b, 0xaf,0x45,0xaf,0x36,0xad,0x32,0xab,0x2a,0xa9,0x39,0xa6,0x34,0xa4,0x3d,0xa0,0x37, 0x9f,0x41,0x9d,0x3b,0xad,0x4e,0xaf,0x3d,0xb3,0x4f,0xb3,0x4e,0xb3,0x57,0xb3,0x4e, 0xb1,0x51,0xae,0x4a,0xac,0x4e,0xaa,0x4a,0xa7,0x4f,0xa6,0x44,0xa9,0x4b,0xab,0x4a, 0xae,0x4d,0xb1,0x44,0xb3,0x53,0xb4,0x43,0xb5,0x4f,0xb4,0x46,0xb3,0x4a,0xb0,0x49, 0xad,0x51,0xaa,0x46,0xa8,0x4b,0xa8,0x45,0xa9,0x52,0xab,0x48,0xaf,0x4b,0xb1,0x49, 0xb4,0x4a,0xb6,0x45,0xb7,0x4e,0xb5,0x49,0xb3,0x51,0xb2,0x47,0xaf,0x4c,0xac,0x44, 0xab,0x52,0xa9,0x43,0xab,0x51,0xab,0x41,0xac,0x54,0xb2,0x45,0xb2,0x4c,0xb4,0x48, 0xb3,0x4f,0xb4,0x46,0xb2,0x4c,0xb0,0x41,0xaf,0x4e,0xab,0x45,0xa9,0x50,0xa7,0x48, 0xaa,0x4d,0xa8,0x44,0xab,0x4c,0xaf,0x46,0xb2,0x54,0xb4,0x43,0xb7,0x4c,0xb6,0x46, 0xb3,0x4c,0xb0,0x48,0xb1,0x4c,0xaa,0x47,0xa6,0x53,0xa6,0x46,0xaa,0x47,0xaa,0x44, 0xad,0x4a,0xb2,0x48,0xb5,0x4f,0xb7,0x4a,0xb7,0x4f,0xb7,0x45,0xb6,0x4a,0xb3,0x45, 0xb0,0x51,0xae,0x46,0xae,0x4b,0xa9,0x44,0xa9,0x50,0xab,0x45,0xad,0x4e,0xaf,0x44, 0xb0,0x50,0xb4,0x47,0xb7,0x48,0xb4,0x45,0xb4,0x51,0xb5,0x46,0xb1,0x4b,0xae,0x45, 0xae,0x4d,0xab,0x40,0xac,0x4c,0xac,0x44,0xb0,0x51,0xb3,0x47,0xb6,0x4f,0xb7,0x42, 0xbb,0x4c,0xbb,0x46,0xba,0x4b,0xb8,0x47,0xb3,0x4d,0xb0,0x48,0xb1,0x4e,0xac,0x49, 0xa9,0x4e,0xaa,0x46,0xaf,0x4e,0xb0,0x47,0xb2,0x50,0xb7,0x48,0xb9,0x4c,0xb9,0x46, 0xbb,0x4d,0xb8,0x44,0xb6,0x48,0xb3,0x41,0xb0,0x4d,0xaf,0x43,0xb1,0x4d,0xaf,0x48, 0xb2,0x4f,0xb4,0x43,0xb6,0x4d,0xba,0x46,0xba,0x4f,0xb9,0x44,0xbb,0x4b,0xba,0x46, 0xb8,0x4d,0xb4,0x46,0xb3,0x4c,0xb1,0x43,0xae,0x52,0xad,0x48,0xb1,0x50,0xb3,0x4a, 0xb6,0x4c,0xb6,0x46,0xb9,0x4c,0xb9,0x47,0xb9,0x4f,0xb7,0x46,0xb7,0x4e,0xb3,0x46, 0xb2,0x4b,0xb0,0x45,0xad,0x50,0xad,0x42,0xb0,0x55,0xb2,0x48,0xb7,0x4e,0xb8,0x44, 0xba,0x52,0xbb,0x4b,0xbd,0x4e,0xbd,0x49,0xb8,0x52,0xb6,0x48,0xb3,0x4f,0xaf,0x47, 0xb0,0x4e,0xad,0x47,0xaf,0x4a,0xb1,0x44,0xb6,0x50,0xb8,0x45,0xba,0x4c,0xb9,0x47, 0xbc,0x4c,0xb8,0x45,0xb5,0x4d,0xb1,0x48,0xaf,0x50,0xac,0x45,0xab,0x4b,0xab,0x4a, 0xaf,0x4f,0xb2,0x44,0xb5,0x49,0xb7,0x47,0xbc,0x4e,0xbc,0x46,0xbe,0x4c,0xbb,0x45, 0xb6,0x51,0xb6,0x4a,0xb3,0x4c,0xae,0x46,0xae,0x52,0xae,0x45,0xb0,0x4e,0xb1,0x46, 0xb4,0x4f,0xb6,0x43,0xbc,0x4b,0xba,0x45,0xbb,0x50,0xbb,0x45,0xbc,0x4d,0xb6,0x44, 0xb3,0x52,0xb2,0x45,0xb1,0x4a,0xac,0x46,0xae,0x52,0xb3,0x46,0xb5,0x4d,0xb6,0x43, 0xbb,0x4f,0xbc,0x4a,0xbc,0x4d,0xbc,0x41,0xba,0x51,0xb7,0x46,0xb5,0x4c,0xb2,0x45, 0xad,0x51,0xae,0x44,0xae,0x4f,0xaf,0x46,0xb1,0x4d,0xb3,0x45,0xb9,0x4d,0xba,0x49, 0xbb,0x50,0xbc,0x42,0xbb,0x4c,0xb8,0x44,0xb4,0x4e,0xb1,0x47,0xae,0x4d,0xab,0x47, 0xad,0x4d,0xad,0x41,0xb0,0x4c,0xb3,0x48,0xb8,0x52,0xb8,0x49,0xb9,0x4d,0xbb,0x4c, 0xba,0x4f,0xb4,0x45,0xb4,0x4f,0xb2,0x46,0xad,0x50,0xab,0x45,0xac,0x4d,0xb0,0x4a, 0xb2,0x4e,0xb5,0x4a,0xb8,0x50,0xba,0x4a,0xbb,0x4e,0xbb,0x4a,0xba,0x4a,0xb7,0x4a, 0xb6,0x4b,0xb2,0x46,0xaf,0x4e,0xac,0x46,0xad,0x54,0xad,0x46,0xb0,0x4e,0xb2,0x41, 0xb6,0x4e,0xb7,0x48,0xb9,0x53,0xb9,0x43,0xb9,0x56,0xb8,0x4a,0xb5,0x52,0xb2,0x45, 0xb1,0x4f,0xb0,0x4a,0xb0,0x4e,0xb0,0x46,0xb1,0x4e,0xb5,0x43,0xb7,0x4f,0xb6,0x45, 0xba,0x4f,0xb8,0x47,0xb7,0x4e,0xb4,0x45,0xb3,0x50,0xb1,0x4a,0xae,0x4c,0xad,0x46, 0xaa,0x50,0xab,0x45,0xaf,0x52,0xb2,0x48,0xb2,0x51,0xb3,0x43,0xb8,0x51,0xb8,0x47, 0xb7,0x4e,0xb6,0x46,0xb3,0x4e,0xb0,0x46,0xae,0x54,0xad,0x46,0xab,0x4c,0xaa,0x45, 0xaf,0x50,0xb0,0x48,0xb3,0x4d,0xb4,0x46,0xb6,0x4e,0xb6,0x47,0xb5,0x4b,0xb2,0x45, 0xb1,0x4d,0xae,0x48,0xaf,0x4b,0xac,0x48,0xac,0x53,0xad,0x48,0xae,0x4d,0xb1,0x44, 0xb4,0x50,0xb5,0x46,0xb8,0x4b,0xb9,0x45,0xb8,0x55,0xb8,0x44,0xb6,0x4c,0xb2,0x46, 0xb1,0x4c,0xac,0x4a,0xaa,0x4b,0xac,0x47,0xac,0x50,0xad,0x43,0xb2,0x4c,0xb4,0x47, 0xb5,0x4b,0xb6,0x49,0xb6,0x4d,0xb5,0x42,0xb4,0x55,0xb3,0x47,0xb0,0x4f,0xad,0x46, 0xab,0x51,0xac,0x46,0xaf,0x4b,0xaf,0x47,0xb2,0x55,0xb5,0x45,0xb8,0x4c,0xb7,0x43, 0xb7,0x50,0xb7,0x44,0xb5,0x50,0xb1,0x47,0xae,0x55,0xac,0x45,0xab,0x4c,0xa9,0x4b, 0xac,0x4c,0xae,0x47,0xb1,0x50,0xb5,0x45,0xb7,0x52,0xb9,0x46,0xb9,0x4f,0xb7,0x49, 0xb8,0x4b,0xb6,0x47,0xb1,0x4c,0xad,0x46,0xae,0x4d,0xad,0x44,0xac,0x50,0xae,0x46, 0xb1,0x4b,0xb4,0x4a,0xb6,0x4b,0xb7,0x47,0xb7,0x54,0xb7,0x45,0xb6,0x4e,0xb4,0x45, 0xb2,0x53,0xae,0x47,0xad,0x49,0xab,0x47,0xa6,0x54,0xa8,0x46,0xb0,0x4d,0xb1,0x46, 0xb1,0x51,0xb4,0x48,0xba,0x4c,0xb8,0x44,0xb8,0x4d,0xb6,0x46,0xb3,0x4d,0xb0,0x46, 0xb2,0x4d,0xac,0x48,0xa4,0x4b,0xa7,0x44,0xb3,0x51,0xab,0x44,0xa8,0x52,0xb7,0x45, 0xbb,0x4e,0xb5,0x46,0xb7,0x4c,0xb5,0x44,0xb3,0x55,0xb0,0x42,0xae,0x4f,0xae,0x45, 0xae,0x4d,0xaf,0x49,0xb1,0x4e,0xb2,0x47,0xb4,0x50,0xb8,0x48,0xba,0x4e,0xb6,0x45, 0xb7,0x4b,0xb6,0x47,0xb1,0x4a,0xae,0x45,0xad,0x4e,0xad,0x47,0xac,0x4e,0xac,0x48, 0xaf,0x4a,0xb0,0x44,0xb2,0x4b,0xb5,0x4a,0xb7,0x50,0xb6,0x44,0xb6,0x4e,0xb3,0x46, 0xb1,0x50,0xb0,0x47,0xac,0x4c,0xaa,0x43,0xac,0x53,0xac,0x44,0xaf,0x4a,0xb0,0x43, 0xb4,0x4b,0xb6,0x47,0xb6,0x50,0xb5,0x49,0xb5,0x51,0xb3,0x40,0xaf,0x45,0xad,0x3e, 0xac,0x4f,0xa8,0x46,0xa8,0x4e,0xa9,0x48,0xab,0x4f,0xa7,0x4b,0xba,0x1e,0xbb,0x10, 0xbc,0x1d,0xbc,0x16,0xbb,0x2b,0xb7,0x18,0xb4,0x21,0xb1,0x15,0xaf,0x1c,0xac,0x16, 0xae,0x1d,0xae,0x13,0xae,0x1a,0xb2,0x15,0xb6,0x20,0xb6,0x12,0xb6,0x20,0xb8,0x15, 0xb8,0x1d,0xb5,0x17,0xb2,0x19,0xb0,0x13,0xad,0x20,0xaa,0x14,0xab,0x20,0xac,0x17, 0xb1,0x1c,0xb3,0x11,0xb6,0x1c,0xb6,0x16,0xb9,0x20,0xba,0x15,0xb8,0x1a,0xb6,0x16, 0xb3,0x1f,0xad,0x11,0xab,0x1b,0xa8,0x12,0xa9,0x1e,0xa9,0x18,0xac,0x19,0xaf,0x15, 0xb4,0x1b,0xb6,0x13,0xb6,0x1f,0xb6,0x16,0xb6,0x20,0xb3,0x12,0xb0,0x19,0xac,0x14, 0xac,0x1c,0xa8,0x13,0xa9,0x19,0xab,0x14,0xad,0x1f,0xac,0x13,0xb2,0x1c,0xb3,0x13, 0xb3,0x19,0xb3,0x13,0xb3,0x1f,0xad,0x16,0xad,0x1f,0xa9,0x18,0xa5,0x1c,0xa2,0x1b, 0xa1,0x1c,0xa3,0x12,0xa9,0x1a,0xa9,0x0f,0xab,0x1e,0xb0,0x16,0xb3,0x1a,0xb5,0x18, 0xb4,0x18,0xb3,0x16,0xb0,0x20,0xac,0x14,0xab,0x1c,0xa7,0x18,0xa8,0x1e,0xa7,0x15, 0xaa,0x1c,0xaa,0x12,0xb0,0x1c,0xb0,0x14,0xb1,0x21,0xb4,0x13,0xb4,0x1c,0xaf,0x16, 0xaf,0x1b,0xac,0x14,0xa9,0x1c,0xa5,0x15,0xa6,0x1c,0xa5,0x14,0xa7,0x1c,0xaa,0x15, 0xad,0x1d,0xaf,0x12,0xb1,0x1d,0xb2,0x15,0xb2,0x1f,0xb0,0x14,0xae,0x18,0xaa,0x16, 0xa8,0x19,0xa5,0x13,0xa3,0x1d,0xa4,0x16,0xa7,0x1e,0xa7,0x14,0xab,0x1c,0xad,0x17, 0xb1,0x1d,0xb2,0x13,0xb1,0x1d,0xb0,0x13,0xb0,0x1c,0xad,0x17,0xab,0x1e,0xa7,0x16, 0xa4,0x1b,0xa5,0x15,0xa5,0x1e,0xa6,0x11,0xab,0x1c,0xae,0x17,0xb0,0x1d,0xb1,0x19, 0xb3,0x1a,0xb1,0x11,0xb0,0x1a,0xaa,0x15,0xa8,0x21,0xa5,0x16,0xa4,0x22,0xa2,0x15, 0xa5,0x1f,0xa6,0x17,0xa9,0x1e,0xab,0x12,0xae,0x21,0xb0,0x15,0xb2,0x1c,0xb1,0x18, 0xaf,0x19,0xae,0x15,0xac,0x1e,0xa8,0x18,0xa5,0x20,0xa5,0x13,0xa6,0x1c,0xa5,0x16, 0xa8,0x1c,0xac,0x14,0xad,0x1e,0xac,0x14,0xad,0x22,0xaf,0x17,0xac,0x1c,0xab,0x17, 0xaa,0x19,0xa9,0x18,0xa7,0x1e,0xa5,0x12,0xa6,0x21,0xa5,0x15,0xa9,0x1c,0xa8,0x10, 0xab,0x18,0xab,0x18,0xb0,0x1d,0xab,0x12,0xab,0x20,0xaa,0x10,0xaa,0x1e,0xa6,0x13, 0xa4,0x20,0xa4,0x1a,0xa4,0x1d,0xa7,0x14,0xaa,0x1f,0xab,0x15,0xaf,0x1c,0xb1,0x18, 0xb1,0x1d,0xaf,0x13,0xaf,0x17,0xad,0x14,0xaa,0x22,0xa6,0x12,0xa4,0x1c,0xa2,0x11, 0xa3,0x1f,0xa5,0x16,0xa7,0x1d,0xa8,0x15,0xab,0x20,0xae,0x15,0xb0,0x1e,0xaf,0x15, 0xaf,0x1c,0xac,0x16,0xaa,0x1d,0xa7,0x15,0xa5,0x21,0xa4,0x12,0xa3,0x1c,0xa4,0x17, 0xa9,0x1f,0xa8,0x16,0xac,0x1e,0xad,0x16,0xae,0x20,0xae,0x16,0xaf,0x1a,0xac,0x14, 0xaa,0x1c,0xa7,0x15,0xa5,0x1c,0xa3,0x17,0xa3,0x1e,0xa2,0x11,0xa6,0x1e,0xa6,0x18, 0xa8,0x20,0xab,0x14,0xae,0x18,0xac,0x15,0xac,0x23,0xad,0x14,0xaa,0x1e,0xa6,0x12, 0xa4,0x19,0xa2,0x19,0xa3,0x19,0xa4,0x16,0xa4,0x23,0xa8,0x15,0xab,0x20,0xad,0x14, 0xaf,0x1f,0xaf,0x18,0xae,0x1f,0xac,0x12,0xaa,0x21,0xa9,0x19,0xa5,0x21,0xa3,0x15, 0xa4,0x1f,0xa3,0x14,0xa4,0x1e,0xa7,0x1a,0xaa,0x1b,0xa9,0x10,0xab,0x1e,0xac,0x15, 0xad,0x1e,0xa9,0x14,0xa8,0x1e,0xa4,0x13,0xa2,0x22,0xa1,0x17,0x9f,0x1f,0x9f,0x14, 0xa3,0x1e,0xa5,0x17,0xa9,0x1d,0xaa,0x1a,0xac,0x23,0xad,0x18,0xad,0x1b,0xa9,0x16, 0xaa,0x1f,0xa5,0x16,0xa3,0x1a,0xa0,0x14,0xa0,0x25,0x9f,0x14,0xa1,0x1d,0xa2,0x18, 0xa6,0x1e,0xa9,0x16,0xac,0x1c,0xaa,0x14,0xaa,0x21,0xab,0x19,0xa8,0x1c,0xa4,0x11, 0xa3,0x1e,0xa1,0x16,0xa0,0x1d,0x9e,0x19,0x9e,0x20,0xa1,0x14,0xa5,0x1f,0xa6,0x18, 0xa8,0x20,0xab,0x17,0xa9,0x1d,0xaa,0x1b,0xab,0x1f,0xa5,0x13,0xa3,0x1d,0xa1,0x15, 0xa1,0x1c,0x9e,0x15,0x9f,0x1f,0xa1,0x17,0xa5,0x21,0xa7,0x17,0xa9,0x24,0xaa,0x19, 0xac,0x1f,0xa9,0x19,0xa8,0x1e,0xa4,0x14,0xa2,0x1e,0xa0,0x19,0x9f,0x1e,0x9d,0x16, 0x9f,0x1e,0x9f,0x15,0xa2,0x1a,0xa3,0x17,0xa5,0x1f,0xa5,0x19,0xa8,0x1e,0xa7,0x15, 0xa4,0x20,0xa5,0x1a,0xa4,0x1e,0xa0,0x1a,0xa0,0x1f,0x9e,0x15,0xa0,0x1e,0xa3,0x17, 0xa4,0x1e,0xa6,0x19,0xa8,0x1e,0xa7,0x15,0xa9,0x1d,0xa9,0x17,0xa8,0x1f,0xa6,0x19, 0xa3,0x20,0xa2,0x19,0x9e,0x1e,0x9c,0x14,0x9c,0x22,0x9d,0x15,0xa0,0x1e,0xa3,0x15, 0xa6,0x1e,0xa6,0x1b,0xa7,0x1e,0xa7,0x12,0xa6,0x21,0xa4,0x18,0xa2,0x1f,0x9e,0x15, 0x9d,0x20,0x9b,0x1a,0x9c,0x1f,0x9c,0x12,0x9f,0x20,0xa2,0x18,0xa5,0x21,0xa7,0x17, 0xa8,0x1a,0xa8,0x1a,0xa7,0x22,0xa5,0x18,0xa2,0x23,0x9f,0x16,0x9f,0x1d,0x9d,0x18, 0x9d,0x1d,0x9e,0x15,0xa0,0x1d,0xa1,0x18,0xa5,0x1e,0xa5,0x17,0xa7,0x1d,0xa7,0x19, 0xa6,0x1c,0xa3,0x19,0xa0,0x21,0x9e,0x18,0x9d,0x1d,0x9a,0x0f,0x9c,0x1f,0x9b,0x14, 0x9e,0x21,0xa0,0x1b,0xa3,0x1d,0xa4,0x15,0xa6,0x22,0xa7,0x17,0xa6,0x1d,0xa3,0x1b, 0xa1,0x23,0x9e,0x16,0x9c,0x1d,0x9b,0x1a,0x9a,0x21,0x9b,0x18,0x9f,0x1d,0x9e,0x14, 0xa0,0x20,0xa5,0x14,0xa5,0x1c,0xa4,0x17,0xa5,0x1f,0xa5,0x18,0xa2,0x19,0x9f,0x18, 0x9e,0x23,0x9c,0x16,0x9b,0x1a,0x9b,0x19,0x9b,0x20,0x9c,0x1d,0xa1,0x1f,0xa0,0x17, 0xa4,0x25,0xa5,0x17,0xa3,0x1b,0xa1,0x17,0xa2,0x1e,0x9e,0x17,0x9c,0x1d,0x99,0x1a, 0x99,0x21,0x9a,0x18,0x9a,0x1b,0x9d,0x17,0xa1,0x1e,0xa3,0x15,0xa5,0x1d,0xa6,0x18, 0xa5,0x22,0xa2,0x15,0xa2,0x21,0x9f,0x18,0x9d,0x1b,0x9c,0x17,0x9b,0x1d,0x9b,0x14, 0x9c,0x1c,0x9e,0x15,0xa0,0x1b,0xa2,0x14,0xa5,0x1f,0xa4,0x13,0xa4,0x25,0xa3,0x19, 0xa1,0x25,0x9e,0x15,0x9e,0x14,0x9a,0x12,0x9b,0x1e,0x99,0x18,0x9c,0x1d,0x9c,0x18, 0x9f,0x1d,0x9d,0x1d,0xa9,0x5e,0xaa,0x5f,0xaa,0x6b,0xa7,0x6a,0xa4,0x78,0xa1,0x6d, 0xa1,0x73,0x9d,0x66,0x9e,0x6b,0x9e,0x61,0xa0,0x6c,0xa2,0x61,0xa6,0x6e,0xa7,0x63, 0xa8,0x70,0xa8,0x65,0xa9,0x69,0xa6,0x5e,0xa4,0x6b,0xa1,0x67,0x9f,0x68,0x9c,0x65, 0x9f,0x6e,0x9e,0x63,0xa0,0x69,0xa0,0x60,0xa6,0x6c,0xa7,0x60,0xa8,0x68,0xa9,0x62, 0xaa,0x68,0xa8,0x63,0xa5,0x67,0xa2,0x61,0xa0,0x6c,0x9e,0x63,0x9d,0x69,0x9b,0x62, 0x9f,0x69,0xa1,0x61,0xa2,0x66,0xa4,0x63,0xaa,0x6a,0xa9,0x63,0xa8,0x68,0xa7,0x64, 0xa6,0x69,0xa3,0x63,0xa0,0x6d,0x9e,0x67,0x9e,0x70,0x9d,0x63,0x9e,0x6c,0xa0,0x60, 0xa4,0x6c,0xa5,0x63,0xa7,0x68,0xa6,0x64,0xa7,0x6c,0xa7,0x5f,0xa5,0x6e,0xa2,0x63, 0x9f,0x6c,0x9b,0x64,0x9a,0x67,0x9b,0x63,0x9c,0x6c,0x9e,0x63,0xa1,0x6a,0xa3,0x63, 0xa7,0x6a,0xa5,0x64,0xa6,0x6b,0xa5,0x62,0xa5,0x71,0xa2,0x5d,0x9f,0x68,0x9e,0x62, 0x9c,0x70,0x9d,0x64,0x9e,0x66,0x9f,0x61,0xa3,0x6a,0xa4,0x60,0xa6,0x6d,0xa7,0x63, 0xa7,0x70,0xa6,0x5f,0xa4,0x6b,0xa0,0x61,0xa0,0x6d,0x9d,0x62,0x9c,0x6c,0x9b,0x61, 0x9e,0x6d,0xa0,0x5f,0xa2,0x6b,0xa2,0x5f,0xa7,0x6b,0xa5,0x62,0xa6,0x6a,0xa5,0x5d, 0xa4,0x6e,0xa2,0x64,0xa0,0x68,0x9c,0x63,0x9b,0x68,0x9b,0x5f,0x9c,0x6c,0x9c,0x63, 0x9e,0x6d,0xa2,0x63,0xa1,0x66,0x99,0x60,0x9d,0x69,0xa2,0x62,0x97,0x66,0x92,0x60, 0x9b,0x6d,0x9a,0x60,0x95,0x6a,0x98,0x62,0x9c,0x6b,0x9c,0x65,0x9f,0x69,0xa1,0x61, 0xa4,0x6a,0xa4,0x64,0xa5,0x69,0xa5,0x5e,0xa4,0x6b,0xa0,0x63,0x9e,0x66,0x9c,0x5f, 0x98,0x66,0x97,0x61,0x99,0x67,0x99,0x61,0x9b,0x6a,0x9d,0x65,0xa0,0x6a,0xa1,0x65, 0xa3,0x6b,0xa2,0x61,0xa1,0x6c,0x9f,0x64,0x9d,0x6d,0x99,0x65,0x97,0x69,0x94,0x63, 0x97,0x6a,0x98,0x64,0x99,0x63,0x9c,0x62,0xa1,0x6d,0xa1,0x61,0xa3,0x68,0xa2,0x63, 0xa2,0x6b,0x9f,0x62,0x9d,0x69,0x9b,0x64,0x98,0x69,0x96,0x64,0x97,0x6b,0x97,0x63, 0x9b,0x6b,0x9d,0x62,0x9f,0x6c,0xa1,0x65,0xa4,0x6b,0xa2,0x61,0xa2,0x6d,0xa0,0x61, 0x9e,0x68,0x9b,0x65,0x9a,0x68,0x98,0x61,0x98,0x6d,0x98,0x60,0x9b,0x6c,0x9e,0x5f, 0xa0,0x70,0xa1,0x60,0xa3,0x68,0xa4,0x5f,0xa3,0x69,0xa0,0x5f,0x9f,0x6d,0x9c,0x62, 0x9a,0x6b,0x98,0x68,0x98,0x68,0x97,0x64,0x9b,0x6d,0x9d,0x62,0x9e,0x6c,0xa0,0x63, 0xa4,0x6a,0xa2,0x63,0xa1,0x6b,0xa0,0x66,0x9f,0x6f,0x9b,0x60,0x9b,0x6c,0x98,0x64, 0x98,0x6d,0x99,0x62,0x9a,0x69,0x9c,0x67,0x9d,0x67,0xa0,0x69,0xa2,0x6a,0xa0,0x61, 0xa1,0x6c,0x9e,0x63,0x9d,0x66,0x99,0x61,0x99,0x6a,0x97,0x63,0x97,0x6a,0x96,0x60, 0x9a,0x6d,0x9a,0x60,0x9e,0x6a,0x9f,0x62,0xa1,0x6b,0xa1,0x61,0xa2,0x6a,0xa0,0x64, 0x9f,0x6b,0x9b,0x62,0x9a,0x6b,0x98,0x63,0x94,0x66,0x8e,0x63,0x94,0x67,0x9c,0x65, 0x97,0x6d,0x98,0x65,0xa1,0x6a,0xa1,0x62,0xa2,0x6c,0xa0,0x64,0x9f,0x6c,0x9c,0x67, 0x99,0x6b,0x97,0x64,0x95,0x66,0x94,0x63,0x98,0x69,0x99,0x61,0x9b,0x6a,0x9e,0x68, 0xa0,0x6e,0xa0,0x65,0xa0,0x69,0x9e,0x61,0x9d,0x6d,0x9a,0x68,0x98,0x6a,0x96,0x62, 0x95,0x6c,0x94,0x65,0x96,0x6c,0x94,0x61,0x9a,0x6d,0x9b,0x69,0x9b,0x69,0x9b,0x61, 0x9e,0x6f,0x9c,0x63,0x9b,0x6b,0x98,0x63,0x96,0x6d,0x91,0x62,0x91,0x6c,0x91,0x62, 0x94,0x6c,0x93,0x64,0x96,0x69,0x9b,0x68,0x9c,0x69,0x9c,0x62,0x9e,0x6d,0x9c,0x64, 0x9d,0x6f,0x99,0x62,0x98,0x6b,0x96,0x65,0x96,0x6e,0x94,0x64,0x97,0x6c,0x97,0x63, 0x9a,0x6b,0x9c,0x60,0x9f,0x6f,0x9f,0x67,0xa1,0x6c,0xa0,0x66,0x9f,0x6b,0x9c,0x63, 0x9c,0x6b,0x98,0x64,0x96,0x69,0x95,0x63,0x98,0x6d,0x98,0x65,0x9b,0x69,0x9e,0x64, 0x9f,0x71,0xa0,0x66,0xa2,0x6a,0xa0,0x65,0xa0,0x71,0x9e,0x5f,0x9b,0x6e,0x98,0x64, 0x98,0x69,0x96,0x65,0x95,0x6d,0x97,0x67,0x9a,0x6e,0x9b,0x63,0x9e,0x72,0xa0,0x5f, 0xa1,0x6a,0xa1,0x64,0x9f,0x6b,0x9c,0x63,0x9b,0x6f,0x98,0x64,0x95,0x6c,0x94,0x63, 0x95,0x6d,0x96,0x63,0x98,0x66,0x9a,0x64,0xa0,0x6f,0xa0,0x64,0xa1,0x6d,0xa0,0x64, 0xa0,0x6c,0x9e,0x66,0x9c,0x6d,0x99,0x65,0x99,0x6d,0x96,0x61,0x96,0x6d,0x96,0x65, 0x9a,0x6e,0x9b,0x65,0x9e,0x71,0x9f,0x62,0xa2,0x71,0xa1,0x66,0x9f,0x6b,0x9d,0x64, 0x9e,0x6e,0x9a,0x66,0x97,0x6c,0x95,0x63,0x95,0x72,0x97,0x65,0x9a,0x6c,0x99,0x63, 0x9d,0x70,0xa0,0x63,0xa1,0x6b,0x9f,0x61,0xa0,0x6d,0xa0,0x68,0x9d,0x6c,0x98,0x64, 0x98,0x6e,0x96,0x65,0x95,0x6a,0x96,0x63,0x99,0x6c,0x99,0x68,0x9c,0x70,0x9e,0x65, 0xa1,0x6f,0xa0,0x64,0x9f,0x71,0xa0,0x67,0x9d,0x71,0x99,0x5f,0x97,0x6b,0x97,0x6b, 0x96,0x6d,0x95,0x65,0x97,0x6e,0x99,0x67,0x9b,0x70,0x9d,0x6d,0x9f,0x6d,0xa0,0x68, 0x9f,0x71,0x9e,0x64,0x9d,0x6c,0x99,0x63,0x99,0x74,0x96,0x65,0x93,0x72,0x95,0x65, 0x96,0x70,0x9a,0x68,0x9b,0x6e,0x9e,0x66,0xa1,0x6f,0x9f,0x67,0xa0,0x6c,0x9f,0x66, 0x9c,0x6f,0x9a,0x65,0x98,0x69,0x96,0x65,0x95,0x6f,0x94,0x63,0x95,0x71,0x98,0x66, 0x9b,0x6b,0x9c,0x69,0x9d,0x6e,0x9e,0x67,0x9e,0x77,0x9e,0x67,0x9c,0x72,0x9a,0x66, 0x97,0x71,0x96,0x68,0x96,0x6c,0x92,0x67,0x95,0x6e,0x98,0x68,0x99,0x6e,0x9b,0x6b, 0x9e,0x70,0xa0,0x65,0xa0,0x6c,0x9d,0x65,0x9d,0x6f,0x9a,0x63,0x97,0x69,0x94,0x68, 0x93,0x6d,0x93,0x62,0x95,0x6f,0x95,0x63,0x9a,0x6e,0x9c,0x65,0x9d,0x6a,0x9e,0x64, 0xa1,0x6e,0x9e,0x64,0x9c,0x68,0x9a,0x64,0x99,0x74,0x94,0x62,0x93,0x64,0x94,0x60, 0x95,0x69,0x96,0x65,0x99,0x6e,0x9c,0x61,0x9c,0x73,0x9a,0x6b,0xa3,0x59,0xa2,0x4f, 0xa1,0x58,0x9d,0x59,0x9c,0x66,0x99,0x5e,0x97,0x60,0x99,0x58,0x9a,0x5c,0x9a,0x57, 0xa0,0x5e,0xa2,0x55,0xa3,0x5d,0xa3,0x56,0xa5,0x64,0xa2,0x53,0xa1,0x62,0x9f,0x59, 0x9c,0x5b,0x9a,0x52,0x99,0x5c,0x98,0x55,0x9b,0x62,0x9c,0x56,0x9c,0x60,0x9f,0x54, 0xa3,0x5b,0xa2,0x58,0xa3,0x5b,0xa2,0x51,0xa2,0x60,0x9f,0x53,0x9e,0x5b,0x9a,0x56, 0x99,0x5f,0x97,0x55,0x99,0x5b,0x9b,0x56,0x9d,0x5f,0x9f,0x51,0xa2,0x5d,0xa3,0x55, 0xa5,0x5d,0xa2,0x54,0xa1,0x61,0x9e,0x59,0x9c,0x5e,0x99,0x57,0x98,0x5e,0x96,0x59, 0x99,0x5d,0x99,0x51,0x9d,0x5d,0x9e,0x53,0xa2,0x5e,0xa1,0x50,0xa3,0x5e,0xa1,0x54, 0xa0,0x5b,0x9d,0x56,0x9a,0x60,0x98,0x56,0x96,0x5b,0x95,0x59,0x96,0x5e,0x97,0x53, 0x9a,0x5c,0x9e,0x54,0x9f,0x5c,0xa0,0x54,0xa2,0x5f,0xa1,0x51,0xa0,0x60,0x9d,0x50, 0x9c,0x5d,0x99,0x54,0x97,0x5a,0x95,0x50,0x96,0x60,0x98,0x56,0x9a,0x5a,0x9b,0x52, 0x9f,0x5d,0xa1,0x54,0x9f,0x5e,0x9f,0x53,0x9d,0x60,0x9c,0x54,0x9a,0x5c,0x97,0x59, 0x97,0x5b,0x94,0x52,0x94,0x5a,0x95,0x57,0x98,0x5f,0x9a,0x56,0x9e,0x5a,0x9e,0x53, 0x9f,0x5b,0x9f,0x53,0x9f,0x5d,0x9b,0x52,0x9b,0x5c,0x97,0x52,0x95,0x61,0x94,0x56, 0x95,0x5b,0x95,0x56,0x97,0x5e,0x9a,0x56,0x9c,0x5e,0x9f,0x57,0x9f,0x5b,0x9e,0x55, 0x9e,0x5a,0x9d,0x55,0x9a,0x5d,0x96,0x57,0x94,0x5e,0x93,0x51,0x92,0x5a,0x93,0x54, 0x97,0x5b,0x99,0x55,0x9b,0x5b,0x9c,0x51,0x9f,0x5d,0x9d,0x53,0x9d,0x5c,0x9d,0x57, 0x9a,0x5e,0x96,0x55,0x94,0x5b,0x91,0x52,0x92,0x61,0x92,0x57,0x93,0x5c,0x96,0x58, 0x9a,0x5d,0x9c,0x56,0x9d,0x5c,0x9c,0x55,0x9e,0x5e,0x9b,0x59,0x9a,0x5b,0x97,0x52, 0x96,0x5d,0x93,0x57,0x93,0x59,0x93,0x57,0x95,0x60,0x97,0x56,0x9a,0x5a,0x9d,0x58, 0x9f,0x5d,0x9d,0x56,0x9e,0x5d,0x9c,0x53,0x9a,0x62,0x97,0x52,0x97,0x5f,0x93,0x52, 0x92,0x5c,0x93,0x5c,0x95,0x5e,0x96,0x56,0x99,0x5e,0x9a,0x56,0x9d,0x5b,0x9d,0x57, 0x9d,0x5f,0x9c,0x58,0x99,0x5c,0x96,0x58,0x95,0x5f,0x92,0x56,0x90,0x60,0x91,0x55, 0x93,0x5c,0x95,0x56,0x98,0x58,0x9a,0x56,0x9c,0x5b,0x9c,0x56,0x9c,0x60,0x9b,0x57, 0x99,0x61,0x96,0x58,0x96,0x5e,0x92,0x56,0x91,0x61,0x90,0x57,0x93,0x5e,0x94,0x56, 0x97,0x62,0x9a,0x5c,0x9b,0x5e,0x9b,0x57,0x9c,0x5d,0x9a,0x5b,0x9b,0x5f,0x96,0x5a, 0x94,0x61,0x93,0x59,0x90,0x5c,0x8f,0x56,0x91,0x63,0x92,0x5a,0x93,0x61,0x97,0x59, 0x99,0x62,0x99,0x5a,0x9c,0x5d,0x9b,0x57,0x9a,0x5d,0x97,0x5a,0x95,0x5f,0x92,0x52, 0x91,0x61,0x91,0x5c,0x92,0x5a,0x92,0x58,0x94,0x61,0x97,0x5c,0x98,0x60,0x9b,0x5b, 0x9a,0x64,0x9a,0x5a,0x9a,0x5d,0x97,0x59,0x94,0x61,0x94,0x58,0x91,0x62,0x90,0x57, 0x90,0x5c,0x93,0x5b,0x94,0x60,0x97,0x5d,0x99,0x62,0x9b,0x5a,0x9a,0x64,0x9a,0x59, 0x99,0x68,0x98,0x5b,0x94,0x64,0x93,0x56,0x90,0x64,0x8f,0x5d,0x90,0x61,0x93,0x5f, 0x94,0x64,0x97,0x5b,0x98,0x5f,0x9a,0x5e,0x9a,0x65,0x99,0x59,0x98,0x60,0x98,0x5d, 0x95,0x63,0x91,0x5c,0x90,0x61,0x90,0x5d,0x8f,0x65,0x91,0x5c,0x93,0x62,0x96,0x5f, 0x99,0x68,0x99,0x5a,0x9b,0x61,0x99,0x5d,0x99,0x68,0x97,0x5c,0x95,0x67,0x92,0x62, 0x90,0x6c,0x90,0x5f,0x8d,0x61,0x8f,0x62,0x91,0x67,0x91,0x61,0x96,0x66,0x97,0x64, 0x98,0x68,0x98,0x64,0x98,0x69,0x95,0x61,0x94,0x6c,0x92,0x64,0x90,0x69,0x8d,0x63, 0x8f,0x6d,0x8e,0x61,0x90,0x6b,0x92,0x5f,0x95,0x6d,0x96,0x65,0x97,0x6c,0x96,0x6b, 0x96,0x72,0x94,0x65,0x93,0x67,0x8f,0x61,0x8e,0x6a,0x8d,0x69,0x8d,0x6d,0x8d,0x67, 0x8e,0x75,0x8f,0x6a,0x93,0x6c,0x94,0x62,0x94,0x73,0x96,0x65,0x96,0x6e,0x93,0x65, 0x92,0x72,0x90,0x64,0x8d,0x6d,0x8b,0x65,0x8a,0x70,0x8b,0x67,0x8c,0x71,0x8e,0x6a, 0x92,0x6d,0x93,0x66,0x94,0x6d,0x94,0x68,0x94,0x70,0x92,0x67,0x91,0x71,0x8e,0x67, 0x8a,0x71,0x8a,0x65,0x89,0x6c,0x89,0x66,0x8b,0x6f,0x8d,0x65,0x91,0x6f,0x91,0x62, 0x94,0x6f,0x94,0x65,0x94,0x69,0x93,0x6a,0x92,0x71,0x8e,0x63,0x8d,0x6c,0x8a,0x62, 0x88,0x6f,0x89,0x67,0x8b,0x68,0x8b,0x63,0x8e,0x70,0x91,0x61,0x94,0x6b,0x93,0x68, 0x94,0x6d,0x93,0x65,0x92,0x67,0x8e,0x64,0x8d,0x6d,0x8a,0x63,0x88,0x68,0x89,0x65, 0x8b,0x71,0x8b,0x65,0x8d,0x6a,0x90,0x65,0x92,0x6f,0x92,0x62,0x91,0x70,0x91,0x61, 0x8f,0x72,0x8e,0x64,0x8d,0x6a,0x89,0x61,0x89,0x6c,0x88,0x62,0x8a,0x6e,0x8a,0x65, 0x8b,0x6e,0x8d,0x62,0x90,0x67,0x8f,0x64,0x91,0x6f,0x90,0x64,0x90,0x6f,0x8c,0x66, 0x8b,0x73,0x89,0x68,0x88,0x6b,0x86,0x64,0x87,0x76,0x88,0x69,0x8b,0x6f,0x8b,0x66, 0x8d,0x70,0x8f,0x65,0x90,0x6e,0x8e,0x68,0x8d,0x78,0x8d,0x6d,0x89,0x77,0x87,0x6c, 0x86,0x76,0x84,0x6c,0x84,0x73,0x85,0x6e,0x87,0x74,0x88,0x6b,0x8b,0x75,0x8d,0x6f, 0x8d,0x79,0x8e,0x6c,0x8c,0x74,0x8a,0x6b,0x88,0x77,0x85,0x70,0x84,0x79,0x81,0x71, 0x81,0x7a,0x83,0x72,0x83,0x74,0x87,0x6e,0x89,0x77,0x8b,0x6e,0x8b,0x78,0x8b,0x71, 0x8c,0x76,0x8a,0x70,0x88,0x78,0x86,0x6f,0x85,0x7a,0x81,0x72,0x80,0x75,0x81,0x71, 0x84,0x78,0x85,0x71,0x87,0x76,0x8a,0x70,0x8b,0x78,0x8c,0x6e,0x8b,0x77,0x8b,0x6f, 0x89,0x7d,0x86,0x76,0x85,0x77,0x83,0x73,0x82,0x7e,0x82,0x73,0x84,0x77,0x85,0x71, 0x89,0x7a,0x8a,0x72,0x8c,0x7c,0x8c,0x70,0x8d,0x7e,0x8b,0x70,0x8a,0x7b,0x88,0x72, 0x87,0x7a,0x84,0x73,0x83,0x7c,0x83,0x74,0x85,0x80,0x87,0x76,0x89,0x80,0x8b,0x7b, 0x8b,0x83,0x88,0x7d,0x6c,0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,00 }; sane-backends-1.0.27/backend/mustek_scsi_pp.c0000664000175000017500000006630712112021330016002 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 James Perry This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements the Mustek SCSI-over-parallel port protocol used by, for example, the Paragon 600 II EP */ /**************************************************************************/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_pa4s2.h" /* * Number of times to retry sending a SCSI command before giving up */ #define MUSTEK_SCSI_PP_NUM_RETRIES 4 /* * Internal middle-level API functionality */ static int mustek_scsi_pp_timeout = 5000; /* FIXME: use same method as mustek.c ? */ static int mustek_scsi_pp_get_time () { struct timeval tv; int retval; gettimeofday (&tv, 0); retval = tv.tv_sec * 1000 + tv.tv_usec / 1000; return retval; } static u_char mustek_scsi_pp_register = 0; static SANE_Status mustek_scsi_pp_select_register (int fd, u_char reg) { DBG (5, "mustek_scsi_pp_select_register: selecting register %d on fd %d\n", reg, fd); mustek_scsi_pp_register = reg; return sanei_pa4s2_scsi_pp_reg_select (fd, reg); } static SANE_Status mustek_scsi_pp_wait_for_valid_status (int fd) { int start_time; u_char status; DBG (5, "mustek_scsi_pp_wait_for_valid_status: entering\n"); start_time = mustek_scsi_pp_get_time (); do { if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_valid_status: I/O error while getting status\n"); return SANE_STATUS_IO_ERROR; } status &= 0xf0; if ((status != 0xf0) && (!(status & 0x40)) && (status & 0x20)) { DBG (5, "mustek_scsi_pp_wait_for_valid_status: returning success\n"); return SANE_STATUS_GOOD; } } while ((mustek_scsi_pp_get_time () - start_time) < mustek_scsi_pp_timeout); DBG (2, "mustek_scsi_pp_wait_for_valid_status: timed out\n"); return SANE_STATUS_DEVICE_BUSY; } static SANE_Status mustek_scsi_pp_wait_for_status_bit_5_set (int fd) { int t; u_char status; DBG (5, "mustek_scsi_pp_wait_for_status_bit_5_set: entering\n"); t = mustek_scsi_pp_get_time (); do { if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_5_set: I/O error\n"); return SANE_STATUS_IO_ERROR; } if (status & 0x20) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_5_set: returning success\n"); return SANE_STATUS_GOOD; } } while ((mustek_scsi_pp_get_time () - t) < mustek_scsi_pp_timeout); DBG (2, "mustek_scsi_pp_wait_for_status_bit_5_set: timed out\n"); return SANE_STATUS_DEVICE_BUSY; } static SANE_Status mustek_scsi_pp_wait_for_status_bit_5_clear (int fd) { int t; u_char status; DBG (5, "mustek_scsi_pp_wait_for_status_bit_5_clear: entering\n"); t = mustek_scsi_pp_get_time (); do { if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_5_clear: I/O error\n"); return SANE_STATUS_IO_ERROR; } if (!(status & 0x20)) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_5_clear: returning success\n"); return SANE_STATUS_GOOD; } } while ((mustek_scsi_pp_get_time () - t) < mustek_scsi_pp_timeout); DBG (2, "mustek_scsi_pp_wait_for_status_bit_5_clear: timed out\n"); return SANE_STATUS_DEVICE_BUSY; } static SANE_Status mustek_scsi_pp_wait_for_status_bit_7_set (int fd) { int t; u_char status; DBG (5, "mustek_scsi_pp_wait_for_status_bit_7_set: entering\n"); t = mustek_scsi_pp_get_time (); do { if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_7_set: I/O error\n"); return SANE_STATUS_IO_ERROR; } if (status & 0x80) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_7_set: returning success\n"); return SANE_STATUS_GOOD; } } while ((mustek_scsi_pp_get_time () - t) < mustek_scsi_pp_timeout); mustek_scsi_pp_select_register (fd, 0); DBG (2, "mustek_scsi_pp_wait_for_status_bit_7_set: timed out\n"); return SANE_STATUS_DEVICE_BUSY; } static SANE_Status mustek_scsi_pp_wait_for_status_bit_7_clear (int fd) { int t; u_char status; DBG (5, "mustek_scsi_pp_wait_for_status_bit_7_clear: entering\n"); t = mustek_scsi_pp_get_time (); do { if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_7_clear: I/O error\n"); return SANE_STATUS_IO_ERROR; } if (!(status & 0x80)) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_7_clear: returning success\n"); return SANE_STATUS_GOOD; } } while ((mustek_scsi_pp_get_time () - t) < mustek_scsi_pp_timeout); mustek_scsi_pp_select_register (fd, 0); DBG (2, "mustek_scsi_pp_wait_for_status_bit_7_clear: timed out\n"); return SANE_STATUS_DEVICE_BUSY; } static SANE_Status mustek_scsi_pp_wait_for_status_bit_4_set (int fd) { int t; u_char status; DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_set: entering\n"); if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_4_set: I/O error\n"); return SANE_STATUS_IO_ERROR; } if (status & 0x10) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_set: returning success\n"); return SANE_STATUS_GOOD; } t = mustek_scsi_pp_get_time (); do { if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_4_set: I/O error\n"); return SANE_STATUS_IO_ERROR; } if (status & 0x40) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_4_set: bit 6 set\n"); return SANE_STATUS_IO_ERROR; } if (status & 0x10) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_set: returning success\n"); return SANE_STATUS_GOOD; } } while ((mustek_scsi_pp_get_time () - t) < mustek_scsi_pp_timeout); DBG (2, "mustek_scsi_pp_wait_for_status_bit_4_set: timed out\n"); return SANE_STATUS_DEVICE_BUSY; } static SANE_Status mustek_scsi_pp_wait_for_status_bit_4_clear (int fd) { int t; u_char status; DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_clear: entering\n"); if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_4_clear: I/O error\n"); return SANE_STATUS_IO_ERROR; } if (!(status & 0x10)) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_clear: returning success\n"); return SANE_STATUS_GOOD; } t = mustek_scsi_pp_get_time (); do { if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_4_clear: I/O error\n"); return SANE_STATUS_IO_ERROR; } if (status & 0x40) { DBG (2, "mustek_scsi_pp_wait_for_status_bit_4_clear: bit 6 set\n"); return SANE_STATUS_IO_ERROR; } if (!(status & 0x10)) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_clear: returning success\n"); return SANE_STATUS_GOOD; } } while ((mustek_scsi_pp_get_time () - t) < mustek_scsi_pp_timeout); DBG (2, "mustek_scsi_pp_wait_for_status_bit_4_clear: timed out\n"); return SANE_STATUS_DEVICE_BUSY; } static u_char mustek_scsi_pp_bit_4_state = 0; static SANE_Status mustek_scsi_pp_wait_for_status_bit_4_toggle (int fd) { SANE_Status result; DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_toggle: entering\n"); mustek_scsi_pp_bit_4_state ^= 0xff; if (mustek_scsi_pp_bit_4_state) { DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_toggle: waiting for set\n"); result = mustek_scsi_pp_wait_for_status_bit_4_set (fd); mustek_scsi_pp_timeout = 5000; } else { DBG (5, "mustek_scsi_pp_wait_for_status_bit_4_toggle: waiting for clear\n"); result = mustek_scsi_pp_wait_for_status_bit_4_clear (fd); } return result; } static SANE_Status mustek_scsi_pp_send_command_byte (int fd, u_char cmd) { DBG (5, "mustek_scsi_pp_send_command byte: sending 0x%02X\n", cmd); mustek_scsi_pp_select_register (fd, 0); if (mustek_scsi_pp_wait_for_status_bit_7_clear (fd) != SANE_STATUS_GOOD) { mustek_scsi_pp_select_register (fd, 0); return SANE_STATUS_IO_ERROR; } if (sanei_pa4s2_writebyte (fd, mustek_scsi_pp_register, cmd) != SANE_STATUS_GOOD) { return SANE_STATUS_IO_ERROR; } mustek_scsi_pp_select_register (fd, 1); if (mustek_scsi_pp_wait_for_status_bit_7_set (fd) != SANE_STATUS_GOOD) { mustek_scsi_pp_select_register (fd, 0); return SANE_STATUS_IO_ERROR; } mustek_scsi_pp_select_register (fd, 0); DBG (5, "mustek_scsi_pp_send_command_byte: returning success\n"); return SANE_STATUS_GOOD; } static u_char mustek_scsi_pp_read_response (int fd) { u_char result; DBG (5, "mustek_scsi_pp_read_response: entering\n"); if (mustek_scsi_pp_wait_for_status_bit_7_set (fd) != SANE_STATUS_GOOD) { mustek_scsi_pp_select_register (fd, 0); return 0xff; } if (sanei_pa4s2_readbegin (fd, mustek_scsi_pp_register) != SANE_STATUS_GOOD) { return 0xff; } if (sanei_pa4s2_readbyte (fd, &result) != SANE_STATUS_GOOD) { return 0xff; } if (sanei_pa4s2_readend (fd) != SANE_STATUS_GOOD) { return 0xff; } mustek_scsi_pp_select_register (fd, 1); if (mustek_scsi_pp_wait_for_status_bit_7_clear (fd) != SANE_STATUS_GOOD) { result = 0xff; } mustek_scsi_pp_select_register (fd, 0); DBG (5, "mustek_scsi_pp_read_response: returning 0x%02X\n", result); return result; } static SANE_Status mustek_scsi_pp_check_response (int fd) { if (mustek_scsi_pp_wait_for_status_bit_5_clear (fd) != SANE_STATUS_GOOD) { return SANE_STATUS_IO_ERROR; } if (mustek_scsi_pp_read_response (fd) != 0xA5) { DBG (2, "mustek_scsi_pp_check_response: response!=0xA5\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "mustek_scsi_pp_check_response: returning success\n"); return SANE_STATUS_GOOD; } static SANE_Status mustek_scsi_pp_send_command (int fd, const u_char * cmd) { int i; signed char checksum; DBG (5, "mustek_scsi_pp_send_command: sending SCSI command 0x%02X\n", cmd[0]); /* Set timeout depending on command type */ switch (cmd[0]) { case 0xf: case 0x8: mustek_scsi_pp_timeout = 1000; break; case 0x2: mustek_scsi_pp_timeout = 80; break; case 0x12: case 0x3: case 0x11: mustek_scsi_pp_timeout = 500; break; default: mustek_scsi_pp_timeout = 1000; break; } if (mustek_scsi_pp_wait_for_status_bit_5_set (fd) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_send_command: timed out waiting for bit 5 to set\n"); return SANE_STATUS_DEVICE_BUSY; } checksum = 0; for (i = 0; i < 6; i++) { if (mustek_scsi_pp_send_command_byte (fd, cmd[i]) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_send_command: error sending byte %d (0x%02X)\n", i, cmd[i]); return SANE_STATUS_IO_ERROR; } checksum += cmd[i]; } if (mustek_scsi_pp_send_command_byte (fd, -checksum) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_send_command: error sending checksum (0x%02X)\n", -checksum); return SANE_STATUS_IO_ERROR; } return mustek_scsi_pp_check_response (fd); } static SANE_Status mustek_scsi_pp_send_data_block (int fd, const u_char * data, int len) { int i; signed char checksum; DBG (5, "mustek_scsi_pp_send_data_block: sending block of length %d\n", len); if (mustek_scsi_pp_wait_for_status_bit_5_set (fd) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_send_data_block: timed out waiting for bit 5 to set\n"); return SANE_STATUS_DEVICE_BUSY; } checksum = 0; for (i = 0; i < len; i++) { if (mustek_scsi_pp_send_command_byte (fd, data[i]) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_send_data_block: error sending byte %d (0x%02X)\n", i, data[i]); return SANE_STATUS_IO_ERROR; } checksum += data[i]; } if (mustek_scsi_pp_send_command_byte (fd, -checksum) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_send_data_block: error sending checksum (0x%02X)\n", -checksum); return SANE_STATUS_IO_ERROR; } return mustek_scsi_pp_check_response (fd); } static SANE_Status mustek_scsi_pp_read_data_block (int fd, u_char * buffer, int len) { int i; signed char checksum; DBG (5, "mustek_scsi_pp_read_data_block: reading block of length %d\n", len); if (mustek_scsi_pp_wait_for_status_bit_5_clear (fd) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_read_data_block: timed out waiting for bit 5 to clear\n"); return SANE_STATUS_DEVICE_BUSY; } checksum = 0; for (i = 0; i < len; i++) { buffer[i] = mustek_scsi_pp_read_response (fd); checksum += buffer[i]; } if ((signed char) mustek_scsi_pp_read_response (fd) != (-checksum)) { mustek_scsi_pp_send_command_byte (fd, 0xff); DBG (2, "mustek_scsi_pp_read_data_block: checksums do not match\n"); return SANE_STATUS_IO_ERROR; } if (mustek_scsi_pp_wait_for_status_bit_5_set (fd) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_read_data_block: error waiting for bit 5 to set\n"); return SANE_STATUS_IO_ERROR; } if (mustek_scsi_pp_send_command_byte (fd, 0) != SANE_STATUS_GOOD) { mustek_scsi_pp_send_command_byte (fd, 0xff); DBG (2, "mustek_scsi_pp_read_data_block: error sending final 0 byte\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "mustek_scsi_pp_read_data_block: returning success\n"); return SANE_STATUS_GOOD; } /* * Externally visible functions */ SANE_Status mustek_scsi_pp_open (const char *dev, int *fd) { SANE_Status status; status = sanei_pa4s2_scsi_pp_open (dev, fd); if (status == SANE_STATUS_GOOD) { DBG (5, "mustek_scsi_pp_open: device %s opened as fd %d\n", dev, *fd); } else { DBG (2, "mustek_scsi_pp_open: error opening device %s\n", dev); } return status; } static void mustek_scsi_pp_close (int fd) { DBG (5, "mustek_scsi_pp_close: closing fd %d\n", fd); sanei_pa4s2_close (fd); } static void mustek_scsi_pp_exit (void) { DBG (5, "mustek_scsi_pp_exit: entering\n"); } static SANE_Status mustek_scsi_pp_test_ready (int fd) { u_char status; SANE_Status retval; DBG (5, "mustek_scsi_pp_test_ready: entering with fd=%d\n", fd); if (sanei_pa4s2_enable (fd, SANE_TRUE) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_test_ready: error enabling scanner\n"); return SANE_STATUS_IO_ERROR; } if (sanei_pa4s2_scsi_pp_get_status (fd, &status) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_test_ready: error getting status\n"); sanei_pa4s2_enable (fd, SANE_FALSE); return SANE_STATUS_INVAL; } retval = SANE_STATUS_GOOD; status &= 0xf0; if (status == 0xf0) { retval = SANE_STATUS_DEVICE_BUSY; } if (status & 0x40) { retval = SANE_STATUS_DEVICE_BUSY; } if (!(status & 0x20)) { retval = SANE_STATUS_DEVICE_BUSY; } if (sanei_pa4s2_enable (fd, SANE_FALSE) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_test_ready: error disabling scanner\n"); return SANE_STATUS_IO_ERROR; } if (retval == SANE_STATUS_GOOD) { DBG (5, "mustek_scsi_pp_test_ready: returning SANE_STATUS_GOOD\n"); } else { DBG (5, "mustek_scsi_pp_test_ready: returning SANE_STATUS_DEVICE_BUSY\n"); } return retval; } static SANE_Status mustek_scsi_pp_cmd (int fd, const void *src, size_t src_size, void *dst, size_t * dst_size) { SANE_Status stat; int num_tries = 0; static u_char scan_options = 0; const u_char *cmd; u_char stop_cmd[6] = { 0x1b, 0, 0, 0, 0, 0 }; int max_tries; max_tries = MUSTEK_SCSI_PP_NUM_RETRIES; cmd = (const u_char *) src; DBG (5, "mustek_scsi_pp_cmd: sending command 0x%02X to device %d\n", cmd[0], fd); if (sanei_pa4s2_enable (fd, SANE_TRUE) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_cmd: error enabling scanner\n"); return SANE_STATUS_IO_ERROR; } if (cmd[0] == 0x1b) { if (!(cmd[4] & 0x1)) { unsigned char c; int i; DBG (5, "mustek_scsi_pp_cmd: doing stop-specific stuff\n"); /* * Remembers what flags were sent with a 'start' command, and * replicate them with a stop command. */ stop_cmd[4] = scan_options & 0xfe; cmd = &stop_cmd[0]; /* * In color mode at least, the scanner doesn't seem to like stopping at * the end. It's a bit of a horrible hack, but reading loads of bytes and * allowing 20 tries for the stop command is the only way I've found that * solves the problem. */ max_tries = 20; if (sanei_pa4s2_readbegin (fd, mustek_scsi_pp_register) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_cmd: error in readbegin for stop\n"); } for (i = 0; i < 10000; i++) { if (sanei_pa4s2_readbyte (fd, &c) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_cmd: error reading byte for stop\n"); break; } DBG (5, "mustek_scsi_pp_cmd: successfully read byte %d\n", i); } if (sanei_pa4s2_readend (fd) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_cmd: error in readend for stop\n"); } } } if (cmd[0] == 0x08) { DBG (5, "mustek_scsi_pp_cmd: doing read-specific stuff\n"); mustek_scsi_pp_timeout = 30000; mustek_scsi_pp_bit_4_state = 0xff; } /* * Send the command itself in one block, then any extra input data in a second * block. Not sure if that's necessary. */ if (src_size < 6) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_cmd: source size is only %lu (<6)\n", (u_long) src_size); return SANE_STATUS_INVAL; } /* * Retry the command several times, as occasionally it doesn't * work first time. */ do { stat = mustek_scsi_pp_send_command (fd, cmd); num_tries++; } while ((stat != SANE_STATUS_GOOD) && (num_tries < max_tries)); if (stat != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_cmd: sending command failed\n"); return stat; } if (src_size > 6) { DBG (5, "mustek_scsi_pp_cmd: sending data block of length %lu\n", (u_long) (src_size - 6)); stat = mustek_scsi_pp_send_data_block (fd, ((const u_char *) src) + 6, src_size - 6); if (stat != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_cmd: sending data block failed\n"); return stat; } } if (dst) { unsigned int length; /* check buffer is big enough to receive data */ length = (cmd[3] << 8) | cmd[4]; DBG (5, "mustek_scsi_pp_cmd: reading %d bytes\n", length); if (length > *dst_size) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_cmd: buffer (size %lu) not big enough for data (size %d)\n", (u_long) *dst_size, length); return SANE_STATUS_INVAL; } stat = mustek_scsi_pp_read_data_block (fd, dst, length); if (stat != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_cmd: error reading data block\n"); } } if (cmd[0] == 0x1b) { if (cmd[4] & 0x1) { DBG (5, "mustek_scsi_pp_cmd: doing start-specific stuff\n"); scan_options = cmd[4]; /* 'Start' command - wait for valid status */ mustek_scsi_pp_timeout = 70000; stat = mustek_scsi_pp_wait_for_valid_status (fd); if (stat != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_cmd: error waiting for valid status after start\n"); } } } if (sanei_pa4s2_enable (fd, SANE_FALSE) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_cmd: error disabling scanner\n"); return SANE_STATUS_IO_ERROR; } if (stat == SANE_STATUS_GOOD) { DBG (5, "mustek_scsi_pp_cmd: returning success\n"); } return stat; } static SANE_Status mustek_scsi_pp_rdata (int fd, int planes, SANE_Byte * buf, int lines, int bpl) { int i, j; DBG (5, "mustek_scsi_pp_rdata: reading %d lines at %d bpl, %d planes from %d\n", lines, bpl, planes, fd); if ((planes != 1) && (planes != 3)) { DBG (2, "mustek_scsi_pp_rdata: invalid number of planes (%d)\n", planes); return SANE_STATUS_INVAL; } if (sanei_pa4s2_enable (fd, SANE_TRUE) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_rdata: error enabling scanner\n"); return SANE_STATUS_IO_ERROR; } for (i = 0; i < lines; i++) { if (planes == 3) { if (mustek_scsi_pp_wait_for_status_bit_4_toggle (fd) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error waiting for bit 4 toggle for red, line %d\n", i); return SANE_STATUS_IO_ERROR; } if (sanei_pa4s2_readbegin (fd, mustek_scsi_pp_register) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error in readbegin for red, line %d\n", i); return SANE_STATUS_IO_ERROR; } for (j = 0; j < (bpl / 3); j++) { if (sanei_pa4s2_readbyte (fd, &buf[j]) != SANE_STATUS_GOOD) { sanei_pa4s2_readend (fd); sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error reading red byte, line %d, byte %d\n", i, j); return SANE_STATUS_IO_ERROR; } } if (sanei_pa4s2_readend (fd) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error in readend for red, line %d\n", i); return SANE_STATUS_IO_ERROR; } if (mustek_scsi_pp_wait_for_status_bit_4_toggle (fd) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error waiting for bit 4 toggle for green, line %d\n", i); return SANE_STATUS_IO_ERROR; } if (sanei_pa4s2_readbegin (fd, mustek_scsi_pp_register) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error in readbegin for green, line %d\n", i); return SANE_STATUS_IO_ERROR; } for (j = 0; j < (bpl / 3); j++) { if (sanei_pa4s2_readbyte (fd, &buf[j + (bpl / 3)]) != SANE_STATUS_GOOD) { sanei_pa4s2_readend (fd); sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error reading green byte, line %d, byte %d\n", i, j); return SANE_STATUS_IO_ERROR; } } if (sanei_pa4s2_readend (fd) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error in readend for green, line %d\n", i); return SANE_STATUS_IO_ERROR; } if (mustek_scsi_pp_wait_for_status_bit_4_toggle (fd) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error waiting for bit 4 toggle for blue, line %d\n", i); return SANE_STATUS_IO_ERROR; } if (sanei_pa4s2_readbegin (fd, mustek_scsi_pp_register) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error in readbegin for blue, line %d\n", i); return SANE_STATUS_IO_ERROR; } for (j = 0; j < (bpl / 3); j++) { if (sanei_pa4s2_readbyte (fd, &buf[j + (2 * (bpl / 3))]) != SANE_STATUS_GOOD) { sanei_pa4s2_readend (fd); sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error reading blue byte, line %d, byte %d\n", i, j); return SANE_STATUS_IO_ERROR; } } if (sanei_pa4s2_readend (fd) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error in readend for blue, line %d\n", i); return SANE_STATUS_IO_ERROR; } } else { if (mustek_scsi_pp_wait_for_status_bit_4_toggle (fd) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error waiting for bit 4 toggle, line %d\n", i); return SANE_STATUS_IO_ERROR; } if (sanei_pa4s2_readbegin (fd, mustek_scsi_pp_register) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error in readbegin, line %d\n", i); return SANE_STATUS_IO_ERROR; } for (j = 0; j < bpl; j++) { if (sanei_pa4s2_readbyte (fd, &buf[j]) != SANE_STATUS_GOOD) { sanei_pa4s2_readend (fd); sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error reading byte, line %d, byte %d\n", i, j); return SANE_STATUS_IO_ERROR; } } if (sanei_pa4s2_readend (fd) != SANE_STATUS_GOOD) { sanei_pa4s2_enable (fd, SANE_FALSE); DBG (2, "mustek_scsi_pp_rdata: error in readend, line %d\n", i); return SANE_STATUS_IO_ERROR; } } buf += bpl; } if (sanei_pa4s2_enable (fd, SANE_FALSE) != SANE_STATUS_GOOD) { DBG (2, "mustek_scsi_pp_rdata: error enabling scanner\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "mustek_scsi_pp_rdata: returning success\n"); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/hp-accessor.h0000664000175000017500000001010712112021330015151 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ #ifndef HP_ACCESSOR_H_INCLUDED #define HP_ACCESSOR_H_INCLUDED #include "hp.h" HpData sanei_hp_data_new (void); HpData sanei_hp_data_dup (HpData orig); void sanei_hp_data_destroy (HpData this); HpAccessor sanei_hp_accessor_new (HpData data, size_t size); HpAccessor sanei_hp_accessor_int_new (HpData data); HpAccessor sanei_hp_accessor_bool_new (HpData data); HpAccessor sanei_hp_accessor_fixed_new (HpData data); HpAccessor sanei_hp_accessor_choice_new(HpData data, HpChoice choices, hp_bool_t may_change); HpAccessor sanei_hp_accessor_vector_new(HpData data, unsigned length, unsigned depth); HpAccessor sanei_hp_accessor_gamma_vector_new(HpData data, unsigned length, unsigned depth); HpAccessor sanei_hp_accessor_matrix_vector_new(HpData data, unsigned length, unsigned depth); HpAccessor sanei_hp_accessor_subvector_new(HpAccessorVector super, unsigned nchan, unsigned chan); HpAccessor sanei_hp_accessor_geometry_new (HpAccessor val, HpAccessor lim, hp_bool_t is_br, HpAccessor res); SANE_Status sanei_hp_accessor_get (HpAccessor this, HpData data, void * valp); SANE_Status sanei_hp_accessor_set (HpAccessor this, HpData data, void * valp); int sanei_hp_accessor_getint(HpAccessor this, HpData data); void sanei_hp_accessor_setint(HpAccessor this, HpData data, int v); const void *sanei_hp_accessor_data (HpAccessor this, HpData data); void * sanei__hp_accessor_data (HpAccessor this, HpData data); size_t sanei_hp_accessor_size (HpAccessor this); unsigned sanei_hp_accessor_vector_length (HpAccessorVector this); SANE_Fixed sanei_hp_accessor_vector_minval (HpAccessorVector this); SANE_Fixed sanei_hp_accessor_vector_maxval (HpAccessorVector this); SANE_Int sanei_hp_accessor_choice_maxsize (HpAccessorChoice this); SANE_String_Const * sanei_hp_accessor_choice_strlist (HpAccessorChoice this, HpOptSet optset, HpData data, const HpDeviceInfo *info); #endif /* HP_ACCESSOR_H_INCLUDED */ sane-backends-1.0.27/backend/epsonds-net.h0000664000175000017500000000113612775312261015230 00000000000000#ifndef _EPSONDS_NET_H_ #define _EPSONDS_NET_H_ #include #include "../include/sane/sane.h" extern int epsonds_net_read(struct epsonds_scanner *s, unsigned char *buf, ssize_t buf_size, SANE_Status *status); extern int epsonds_net_write(struct epsonds_scanner *s, unsigned int cmd, const unsigned char *buf, size_t buf_size, size_t reply_len, SANE_Status *status); extern SANE_Status epsonds_net_lock(struct epsonds_scanner *s); extern SANE_Status epsonds_net_unlock(struct epsonds_scanner *s); extern SANE_Status epsonds_net_request_read(epsonds_scanner *s, size_t len); #endif sane-backends-1.0.27/backend/snapscan-sources.c0000664000175000017500000013657112775312261016267 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997, 1998, 2002, 2013 Franck Schnefra, Michel Roelofs, Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Max Ushakov, Andrew Goodbody, Oliver Schwartz and Kevin Charter This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is a component of the implementation of a backend for many of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ SnapScan backend data sources (implementation) */ /************************************************************************************** If you get confused from all the structs (like I did when I first saw them), think of it as "C++ in C". If you're accustomed to OO and UML maybe the following diagram helps you to make sense of it: ------------------------ ! Source ! ------------------------ !pss: SnapScan_Scanner*! ------------------------ +psub !init() = 0 !----------------- !remaining() = 0 ! ! !bytesPerLine() ! ! !pixelsPerLine() ! ! !get() = 0 ! !{TransformerSource forwards !done() = 0 ! ! function calls to corres- ------------------------ ! ponding functions in psub} ^ ! /_\ ! ! ! -------------------------------------------------- /\ ! ! ! ! \/ ------------- ------------- ------------- ------------------- !SCSISource ! ! FDSource ! !BufSource ! !TransformerSource! ============= ============= ============= =================== !remaining()! !remaining()! !remaining()! !init() ! !get() ! !get() ! !get() ! !remaining() ! !done() ! !done() ! !done() ! !bytesPerLine() ! !init() ! !init() ! !init() ! !pixelsPerLine() ! ------------- ------------- ------------- !get() ! !done() ! ------------------- ^ /_\ ! ------------------------------------ ! ! ! ---------------- ------------- ------------- ! Expander ! ! RGBRouter ! ! Inverter ! ================ ============= ============= !remaining() ! !remaining()! !remaining()! !bytesPerLine()! !get() ! !get() ! !get() ! !done() ! !done() ! !done() ! !init() ! !init() ! !init() ! ------------- ------------- ---------------- All instances of the descendants of TransformerSource can be chained together. For color scanning, a typical source chain would consist of an RGBRouter sitting on top of a SCSISource. In the get() method, RGBRouter will then call the get() method of the subsource, process the data and return it. I hope this makes sense to you (and I got the right idea of the original author's intention). ***********************************************************************************/ static SANE_Status Source_init (Source *pself, SnapScan_Scanner *pss, SourceRemaining remaining, SourceBytesPerLine bytesPerLine, SourcePixelsPerLine pixelsPerLine, SourceGet get, SourceDone done) { pself->pss = pss; pself->remaining = remaining; pself->bytesPerLine = bytesPerLine; pself->pixelsPerLine = pixelsPerLine; pself->get = get; pself->done = done; return SANE_STATUS_GOOD; } /* these are defaults, normally used only by base sources */ static SANE_Int Source_bytesPerLine (Source *pself) { return pself->pss->bytes_per_line; } static SANE_Int Source_pixelsPerLine (Source *pself) { return pself->pss->pixels_per_line; } /**********************************************************************/ /* the base sources */ typedef enum { SCSI_SRC, FD_SRC, BUF_SRC } BaseSourceType; typedef struct { SOURCE_GUTS; SANE_Int scsi_buf_pos; /* current position in scsi buffer */ SANE_Int scsi_buf_max; /* data limit */ SANE_Int absolute_max; /* largest possible data read */ } SCSISource; static SANE_Int SCSISource_remaining (Source *pself) { SCSISource *ps = (SCSISource *) pself; return ps->pss->bytes_remaining + (ps->scsi_buf_max - ps->scsi_buf_pos); } static SANE_Status SCSISource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen) { SCSISource *ps = (SCSISource *) pself; SANE_Status status = SANE_STATUS_GOOD; SANE_Int remaining = *plen; char* me = "SCSISource_get"; DBG (DL_CALL_TRACE, "%s\n", me); while (remaining > 0 && pself->remaining(pself) > 0 && status == SANE_STATUS_GOOD && !cancelRead) { SANE_Int ndata = ps->scsi_buf_max - ps->scsi_buf_pos; DBG (DL_DATA_TRACE, "%s: ndata %d; remaining %d\n", me, ndata, remaining); if (ndata == 0) { ps->pss->expected_read_bytes = MIN((size_t)ps->absolute_max, ps->pss->bytes_remaining); ps->scsi_buf_pos = 0; ps->scsi_buf_max = 0; status = scsi_read (ps->pss, READ_IMAGE); if (status != SANE_STATUS_GOOD) break; ps->scsi_buf_max = ps->pss->read_bytes; ndata = ps->pss->read_bytes; ps->pss->bytes_remaining -= ps->pss->read_bytes; DBG (DL_DATA_TRACE, "%s: pos: %d; max: %d; expected: %lu; read: %lu\n", me, ps->scsi_buf_pos, ps->scsi_buf_max, (u_long) ps->pss->expected_read_bytes, (u_long) ps->pss->read_bytes); } ndata = MIN(ndata, remaining); memcpy (pbuf, ps->pss->buf + ps->scsi_buf_pos, (size_t)ndata); pbuf += ndata; ps->scsi_buf_pos += ndata; remaining -= ndata; } *plen -= remaining; return status; } static SANE_Status SCSISource_done (Source *pself) { DBG(DL_MINOR_INFO, "SCSISource_done\n"); UNREFERENCED_PARAMETER(pself); return SANE_STATUS_GOOD; } static SANE_Status SCSISource_init (SCSISource *pself, SnapScan_Scanner *pss) { SANE_Status status = Source_init ((Source *) pself, pss, SCSISource_remaining, Source_bytesPerLine, Source_pixelsPerLine, SCSISource_get, SCSISource_done); if (status == SANE_STATUS_GOOD) { pself->scsi_buf_max = 0; pself->scsi_buf_pos = 0; pself->absolute_max = (pss->phys_buf_sz/pss->bytes_per_line)*pss->bytes_per_line; } return status; } /* File sources */ typedef struct { SOURCE_GUTS; int fd; SANE_Int bytes_remaining; } FDSource; static SANE_Int FDSource_remaining (Source *pself) { FDSource *ps = (FDSource *) pself; return ps->bytes_remaining; } static SANE_Status FDSource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen) { SANE_Status status = SANE_STATUS_GOOD; FDSource *ps = (FDSource *) pself; SANE_Int remaining = *plen; while (remaining > 0 && pself->remaining(pself) > 0 && status == SANE_STATUS_GOOD) { SANE_Int bytes_read = read (ps->fd, pbuf, remaining); if (bytes_read == -1) { if (errno == EAGAIN) { /* No data currently available */ break; } /* It's an IO error */ DBG (DL_MAJOR_ERROR, "%s: read failed: %s\n", __func__, strerror(errno)); status = SANE_STATUS_IO_ERROR; } else if (bytes_read == 0) { /* EOF of current reading */ DBG(DL_DATA_TRACE, "%s: EOF\n",__func__); break; } ps->bytes_remaining -= bytes_read; remaining -= bytes_read; pbuf += bytes_read; } *plen -= remaining; return status; } static SANE_Status FDSource_done (Source *pself) { close(((FDSource *) pself)->fd); return SANE_STATUS_GOOD; } static SANE_Status FDSource_init (FDSource *pself, SnapScan_Scanner *pss, int fd) { SANE_Status status = Source_init ((Source *) pself, pss, FDSource_remaining, Source_bytesPerLine, Source_pixelsPerLine, FDSource_get, FDSource_done); if (status == SANE_STATUS_GOOD) { pself->fd = fd; pself->bytes_remaining = pss->bytes_per_line * (pss->lines + pss->chroma); } return status; } /* buffer sources simply read from a pre-filled buffer; we have these so that we can include source chain processing overhead in the measure_transfer_rate() function */ typedef struct { SOURCE_GUTS; SANE_Byte *buf; SANE_Int buf_size; SANE_Int buf_pos; } BufSource; static SANE_Int BufSource_remaining (Source *pself) { BufSource *ps = (BufSource *) pself; return ps->buf_size - ps->buf_pos; } static SANE_Status BufSource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen) { BufSource *ps = (BufSource *) pself; SANE_Status status = SANE_STATUS_GOOD; SANE_Int to_move = MIN(*plen, pself->remaining(pself)); if (to_move == 0) { status = SANE_STATUS_EOF; } else { memcpy (pbuf, ps->buf + ps->buf_pos, to_move); ps->buf_pos += to_move; *plen = to_move; } return status; } static SANE_Status BufSource_done (Source *pself) { UNREFERENCED_PARAMETER(pself); return SANE_STATUS_GOOD; } static SANE_Status BufSource_init (BufSource *pself, SnapScan_Scanner *pss, SANE_Byte *buf, SANE_Int buf_size) { SANE_Status status = Source_init ((Source *) pself, pss, BufSource_remaining, Source_bytesPerLine, Source_pixelsPerLine, BufSource_get, BufSource_done); DBG(DL_DATA_TRACE, "BufSource_init: buf_size=%d\n", buf_size); if (status == SANE_STATUS_GOOD) { pself->buf = buf; pself->buf_size = buf_size; pself->buf_pos = 0; } return status; } /* base source creation */ static SANE_Status create_base_source (SnapScan_Scanner *pss, BaseSourceType st, Source **pps) { SANE_Status status = SANE_STATUS_GOOD; *pps = NULL; switch (st) { case SCSI_SRC: *pps = (Source *) malloc(sizeof(SCSISource)); if (*pps == NULL) { DBG (DL_MAJOR_ERROR, "failed to allocate SCSISource"); status = SANE_STATUS_NO_MEM; } else { status = SCSISource_init ((SCSISource *) *pps, pss); } break; case FD_SRC: *pps = (Source *) malloc(sizeof(FDSource)); if (*pps == NULL) { DBG (DL_MAJOR_ERROR, "failed to allocate FDSource"); status = SANE_STATUS_NO_MEM; } else { status = FDSource_init ((FDSource *) *pps, pss, pss->rpipe[0]); } break; case BUF_SRC: *pps = (Source *) malloc(sizeof(BufSource)); if (*pps == NULL) { DBG (DL_MAJOR_ERROR, "failed to allocate BufSource"); status = SANE_STATUS_NO_MEM; } else { status = BufSource_init ((BufSource *) *pps, pss, pss->buf, pss->read_bytes); } break; default: DBG (DL_MAJOR_ERROR, "illegal base source type %d", st); break; } return status; } /**********************************************************************/ /* The transformer sources */ #define TX_SOURCE_GUTS \ SOURCE_GUTS;\ Source *psub /* sub-source */ typedef struct { TX_SOURCE_GUTS; } TxSource; static SANE_Int TxSource_remaining (Source *pself) { TxSource *ps = (TxSource *) pself; return ps->psub->remaining(ps->psub); } static SANE_Int TxSource_bytesPerLine (Source *pself) { TxSource *ps = (TxSource *) pself; return ps->psub->bytesPerLine(ps->psub); } static SANE_Int TxSource_pixelsPerLine (Source *pself) { TxSource *ps = (TxSource *) pself; return ps->psub->pixelsPerLine(ps->psub); } static SANE_Status TxSource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen) { TxSource *ps = (TxSource *) pself; return ps->psub->get(ps->psub, pbuf, plen); } static SANE_Status TxSource_done (Source *pself) { TxSource *ps = (TxSource *) pself; SANE_Status status = ps->psub->done(ps->psub); free(ps->psub); ps->psub = NULL; return status; } static SANE_Status TxSource_init (TxSource *pself, SnapScan_Scanner *pss, SourceRemaining remaining, SourceBytesPerLine bytesPerLine, SourcePixelsPerLine pixelsPerLine, SourceGet get, SourceDone done, Source *psub) { SANE_Status status = Source_init((Source *) pself, pss, remaining, bytesPerLine, pixelsPerLine, get, done); if (status == SANE_STATUS_GOOD) pself->psub = psub; return status; } /* The expander makes three-channel, one-bit, raw scanner data into 8-bit data. It is used to support the bilevel colour scanning mode */ typedef struct { TX_SOURCE_GUTS; SANE_Byte *ch_buf; /* channel buffer */ SANE_Int ch_size; /* channel buffer size = #bytes in a channel */ SANE_Int ch_ndata; /* actual #bytes in channel buffer */ SANE_Int ch_pos; /* position in buffer */ SANE_Int bit; /* current bit */ SANE_Int last_bit; /* current last bit (counting down) */ SANE_Int last_last_bit; /* last bit in the last byte of the channel */ } Expander; static SANE_Int Expander_remaining (Source *pself) { Expander *ps = (Expander *) pself; SANE_Int sub_remaining = TxSource_remaining(pself); SANE_Int sub_bits_per_channel = TxSource_pixelsPerLine(pself); SANE_Int whole_channels = sub_remaining/ps->ch_size; SANE_Int result = whole_channels*sub_bits_per_channel; if (ps->ch_pos < ps->ch_size) { SANE_Int bits_covered = MAX((ps->ch_pos - 1)*8, 0) + 7 - ps->bit; result += sub_bits_per_channel - bits_covered; } return result; } static SANE_Int Expander_bytesPerLine (Source *pself) { return TxSource_pixelsPerLine(pself)*3; } static SANE_Status Expander_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen) { Expander *ps = (Expander *) pself; SANE_Status status = SANE_STATUS_GOOD; SANE_Int remaining = *plen; while (remaining > 0 && pself->remaining(pself) > 0 && !cancelRead) { if (ps->ch_pos == ps->ch_ndata) { /* we need more data; try to get the remainder of the current channel, or else the next channel */ SANE_Int ndata = ps->ch_size - ps->ch_ndata; if (ndata == 0) { ps->ch_ndata = 0; ps->ch_pos = 0; ndata = ps->ch_size; } status = TxSource_get(pself, ps->ch_buf + ps->ch_pos, &ndata); if (status != SANE_STATUS_GOOD) break; if (ndata == 0) break; ps->ch_ndata += ndata; if (ps->ch_pos == (ps->ch_size - 1)) ps->last_bit = ps->last_last_bit; else ps->last_bit = 0; ps->bit = 7; } *pbuf = ((ps->ch_buf[ps->ch_pos] >> ps->bit) & 0x01) ? 0xFF : 0x00; pbuf++; remaining--; if (ps->bit == ps->last_bit) { ps->bit = 7; ps->ch_pos++; if (ps->ch_pos == (ps->ch_size - 1)) ps->last_bit = ps->last_last_bit; else ps->last_bit = 0; } else { ps->bit--; } } *plen -= remaining; return status; } static SANE_Status Expander_done (Source *pself) { Expander *ps = (Expander *) pself; SANE_Status status = TxSource_done(pself); free(ps->ch_buf); ps->ch_buf = NULL; ps->ch_size = 0; ps->ch_pos = 0; return status; } static SANE_Status Expander_init (Expander *pself, SnapScan_Scanner *pss, Source *psub) { SANE_Status status = TxSource_init((TxSource *) pself, pss, Expander_remaining, Expander_bytesPerLine, TxSource_pixelsPerLine, Expander_get, Expander_done, psub); if (status == SANE_STATUS_GOOD) { pself->ch_size = TxSource_bytesPerLine((Source *) pself)/3; pself->ch_buf = (SANE_Byte *) malloc(pself->ch_size); if (pself->ch_buf == NULL) { DBG (DL_MAJOR_ERROR, "%s: couldn't allocate channel buffer.\n", __func__); status = SANE_STATUS_NO_MEM; } else { pself->ch_ndata = 0; pself->ch_pos = 0; pself->last_last_bit = pself->pixelsPerLine((Source *) pself)%8; if (pself->last_last_bit == 0) pself->last_last_bit = 7; pself->last_last_bit = 7 - pself->last_last_bit; pself->bit = 7; if (pself->ch_size > 1) pself->last_bit = 0; else pself->last_bit = pself->last_last_bit; } } return status; } static SANE_Status create_Expander (SnapScan_Scanner *pss, Source *psub, Source **pps) { SANE_Status status = SANE_STATUS_GOOD; *pps = (Source *) malloc(sizeof(Expander)); if (*pps == NULL) { DBG (DL_MAJOR_ERROR, "%s: failed to allocate Expander.\n", __func__); status = SANE_STATUS_NO_MEM; } else { status = Expander_init ((Expander *) *pps, pss, psub); } return status; } /* This filter implements a fix for scanners that have some columns of pixels offset. Currently it only shifts every other column starting with the first one down ch_offset pixels. The Deinterlacer detects if data is in SANE RGB frame format (3 bytes/pixel) or in Grayscale (1 byte/pixel). The first ch_offset lines of data in the output are fudged so that even indexed add odd indexed pixels will have the same value. This is necessary because the real pixel values of the columns that are shifted down are not in the data for the first ch_offset lines. A better way to handle this would be to scan in ch_offset extra lines of data, but I haven't figured out how to do this yet. */ typedef struct { TX_SOURCE_GUTS; SANE_Byte *ch_buf; /* channel buffer */ SANE_Int ch_size; /* channel buffer size */ SANE_Int ch_line_size; /* size of one line */ SANE_Int ch_ndata; /* actual #bytes in channel buffer */ SANE_Int ch_pos; /* position in buffer */ SANE_Int ch_bytes_per_pixel; SANE_Bool ch_lineart; SANE_Int ch_offset; /* The number of lines to be shifted */ SANE_Bool ch_past_init; /* flag indicating if we have enough data to shift pixels down */ SANE_Bool ch_shift_even; /* flag indicating wether even or odd pixels are shifted */ } Deinterlacer; static SANE_Int Deinterlacer_remaining (Source *pself) { Deinterlacer *ps = (Deinterlacer *) pself; SANE_Int result = TxSource_remaining(pself); result += ps->ch_ndata - ps->ch_pos; return result; } static SANE_Status Deinterlacer_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen) { Deinterlacer *ps = (Deinterlacer *) pself; SANE_Status status = SANE_STATUS_GOOD; SANE_Int remaining = *plen; SANE_Int org_len = *plen; char *me = "Deinterlacer_get"; DBG(DL_DATA_TRACE, "%s: remaining=%d, pself->remaining=%d, ch_ndata=%d, ch_pos=%d\n", me, remaining, pself->remaining(pself), ps->ch_ndata, ps->ch_pos); while (remaining > 0 && pself->remaining(pself) > 0 && !cancelRead) { if (ps->ch_pos % (ps->ch_line_size) == ps->ch_ndata % (ps->ch_line_size) ) { /* we need more data; try to get the remainder of the current line, or else the next line */ SANE_Int ndata = (ps->ch_line_size) - ps->ch_ndata % (ps->ch_line_size); if (ps->ch_pos >= ps->ch_size) { /* wrap to the beginning of the buffer if we need to */ ps->ch_ndata = 0; ps->ch_pos = 0; ndata = ps->ch_line_size; } status = TxSource_get(pself, ps->ch_buf + ps->ch_pos, &ndata); if (status != SANE_STATUS_GOOD) break; if (ndata == 0) break; ps->ch_ndata += ndata; } /* Handle special lineart mode: Valid pixels need to be masked */ if (ps->ch_lineart) { if (ps->ch_past_init) { if (ps->ch_shift_even) { /* Even columns need to be shifted, i.e. bits 1,3,5,7 -> 0xaa */ /* use valid pixels from this line and shifted pixels from ch_size lines back */ *pbuf = (ps->ch_buf[ps->ch_pos] & 0x55) | (ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size] & 0xaa); } else { /* Odd columns need to be shifted, i.e. bits 0,2,4,6 -> 0x55 */ *pbuf = (ps->ch_buf[ps->ch_pos] & 0xaa) | (ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size] & 0x55); } } else { /* not enough data. duplicate pixel values from previous column */ if (ps->ch_shift_even) { /* bits 0,2,4,6 contain valid data -> 0x55 */ SANE_Byte valid_pixel = ps->ch_buf[ps->ch_pos] & 0x55; *pbuf = valid_pixel | (valid_pixel >> 1); } else { /* bits 1,3,5,7 contain valid data -> 0xaa */ SANE_Byte valid_pixel = ps->ch_buf[ps->ch_pos] & 0xaa; *pbuf = valid_pixel | (valid_pixel << 1); } } } else /* colour / grayscale mode */ { if ((ps->ch_shift_even && ((ps->ch_pos/ps->ch_bytes_per_pixel) % 2 == 0)) || (!ps->ch_shift_even && ((ps->ch_pos/ps->ch_bytes_per_pixel) % 2 == 1))) { /* the even indexed pixels need to be shifted down */ if (ps->ch_past_init){ /* We need to use data 4 lines back */ /* So we just go one forward and it will wrap around to 4 back. */ *pbuf = ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size]; }else{ /* Use data from the next pixel for even indexed pixels if we are on the first few lines. TODO: also we will overread the buffer if the buffer read ended on the first pixel. */ if (ps->ch_pos % (ps->ch_line_size) == 0 ) *pbuf = ps->ch_buf[ps->ch_pos+ps->ch_bytes_per_pixel]; else *pbuf = ps->ch_buf[ps->ch_pos-ps->ch_bytes_per_pixel]; } }else{ /* odd indexed pixels are okay */ *pbuf = ps->ch_buf[ps->ch_pos]; } } /* set the flag so we know we have enough data to start shifting columns */ if (ps->ch_pos >= ps->ch_line_size * ps->ch_offset) ps->ch_past_init = SANE_TRUE; pbuf++; remaining--; ps->ch_pos++; } *plen -= remaining; DBG(DL_DATA_TRACE, "%s: Request=%d, remaining=%d, read=%d, TXSource_rem=%d, bytes_rem=%lu\n", me, org_len, pself->remaining(pself), *plen, TxSource_remaining(pself), (u_long) ps->pss->bytes_remaining); return status; } static SANE_Status Deinterlacer_done (Source *pself) { Deinterlacer *ps = (Deinterlacer *) pself; SANE_Status status = TxSource_done(pself); free(ps->ch_buf); ps->ch_buf = NULL; ps->ch_size = 0; ps->ch_line_size = 0; ps->ch_pos = 0; return status; } static SANE_Status Deinterlacer_init (Deinterlacer *pself, SnapScan_Scanner *pss, Source *psub) { SANE_Status status = TxSource_init((TxSource *) pself, pss, Deinterlacer_remaining, TxSource_bytesPerLine, TxSource_pixelsPerLine, Deinterlacer_get, Deinterlacer_done, psub); if (status == SANE_STATUS_GOOD) { pself->ch_shift_even = SANE_TRUE; switch (pss->pdev->model) { case PERFECTION3490: pself->ch_offset = 8; if ((actual_mode(pss) == MD_GREYSCALE) || (actual_mode(pss) == MD_LINEART)) pself->ch_shift_even = SANE_FALSE; break; case PERFECTION2480: default: pself->ch_offset = 4; break; } pself->ch_line_size = TxSource_bytesPerLine((Source *) pself); /* We need at least ch_offset+1 lines of buffer in order to shift up ch_offset pixels. */ pself->ch_size = pself->ch_line_size * (pself->ch_offset + 1); pself->ch_buf = (SANE_Byte *) malloc(pself->ch_size); if (pself->ch_buf == NULL) { DBG (DL_MAJOR_ERROR, "%s: couldn't allocate channel buffer.\n", __func__); status = SANE_STATUS_NO_MEM; } else { pself->ch_ndata = 0; pself->ch_pos = 0; pself->ch_past_init = SANE_FALSE; if ((actual_mode(pss) == MD_GREYSCALE) || (actual_mode(pss) == MD_LINEART)) pself->ch_bytes_per_pixel = 1; else pself->ch_bytes_per_pixel = 3; if (pss->bpp_scan == 16) pself->ch_bytes_per_pixel *= 2; } pself->ch_lineart = (actual_mode(pss) == MD_LINEART); } return status; } static SANE_Status create_Deinterlacer (SnapScan_Scanner *pss, Source *psub, Source **pps) { SANE_Status status = SANE_STATUS_GOOD; *pps = (Source *) malloc(sizeof(Deinterlacer)); if (*pps == NULL) { DBG (DL_MAJOR_ERROR, "%s: failed to allocate Deinterlacer.\n", __func__); status = SANE_STATUS_NO_MEM; } else { status = Deinterlacer_init ((Deinterlacer *) *pps, pss, psub); } return status; } /* ----------------------------------------------------- */ /* the RGB router assumes 8-bit RGB data arranged in contiguous channels, possibly with R-G and R-B offsets, and rearranges the data into SANE RGB frame format */ typedef struct { TX_SOURCE_GUTS; SANE_Byte *cbuf; /* circular line buffer */ SANE_Byte *xbuf; /* single line buffer */ SANE_Int pos; /* current position in xbuf */ SANE_Int cb_size; /* size of the circular buffer */ SANE_Int cb_line_size;/* size of a line in the circular buffer */ SANE_Int cb_start; /* start of valid data in the circular buffer */ SANE_Int cb_finish; /* finish of valid data, for next read */ SANE_Int ch_offset[3];/* offset in cbuf */ SANE_Int round_req; SANE_Int round_read; } RGBRouter; static void put_int16r (int n, u_char *p) { p[0] = (n & 0x00ff); p[1] = (n & 0xff00) >> 8; } static SANE_Int RGBRouter_remaining (Source *pself) { RGBRouter *ps = (RGBRouter *) pself; SANE_Int remaining; if (ps->round_req == ps->cb_size) remaining = TxSource_remaining(pself) - ps->cb_size + ps->cb_line_size; else remaining = TxSource_remaining(pself) + ps->cb_line_size - ps->pos; return (remaining); } static SANE_Status RGBRouter_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen) { RGBRouter *ps = (RGBRouter *) pself; SANE_Status status = SANE_STATUS_GOOD; SANE_Int remaining = *plen; SANE_Byte *s; SANE_Int i, t; SANE_Int r, g, b; SANE_Int run_req; SANE_Int org_len = *plen; char *me = "RGBRouter_get"; while (remaining > 0 && pself->remaining(pself) > 0 && !cancelRead) { DBG(DL_DATA_TRACE, "%s: remaining=%d, pself->remaining=%d, round_req=%d, cb_size=%d\n", me, remaining, pself->remaining(pself), ps->round_req, ps->cb_size); /* Check if there is no valid data left from previous get */ if (ps->pos >= ps->cb_line_size) { /* Try to get more data. either one line or full buffer (first time) */ do { run_req = ps->round_req - ps->round_read; status = TxSource_get (pself, ps->cbuf + ps->cb_start + ps->round_read, &run_req); if (status != SANE_STATUS_GOOD || run_req==0) { *plen -= remaining; if ( *plen > 0 ) DBG(DL_DATA_TRACE, "%s: request=%d, read=%d\n", me, org_len, *plen); return status; } ps->round_read += run_req; } while ((ps->round_req > ps->round_read) && !cancelRead); /* route RGB */ ps->cb_start = (ps->cb_start + ps->round_read)%ps->cb_size; s = ps->xbuf; r = (ps->cb_start + ps->ch_offset[0])%ps->cb_size; g = (ps->cb_start + ps->ch_offset[1])%ps->cb_size; b = (ps->cb_start + ps->ch_offset[2])%ps->cb_size; for (i = 0; i < ps->cb_line_size/3; i++) { if (pself->pss->bpp_scan == 8) { *s++ = ps->cbuf[r++]; *s++ = ps->cbuf[g++]; *s++ = ps->cbuf[b++]; } else if (pself->pss->pdev->model == SCANWIT2720S) { t = (((ps->cbuf[r+1] << 8) | ps->cbuf[r]) & 0xfff) << 4; put_int16r (t, s); s += 2; r += 2; t = (((ps->cbuf[g+1] << 8) | ps->cbuf[g]) & 0xfff) << 4; put_int16r (t, s); s += 2; g += 2; t = (((ps->cbuf[b+1] << 8) | ps->cbuf[b]) & 0xfff) << 4; put_int16r (t, s); s += 2; b += 2; i++; } else { *s++ = ps->cbuf[r++]; *s++ = ps->cbuf[r++]; *s++ = ps->cbuf[g++]; *s++ = ps->cbuf[g++]; *s++ = ps->cbuf[b++]; *s++ = ps->cbuf[b++]; i++; } } /* end of reading & offsetiing whole line data; reset valid position */ ps->pos = 0; /* prepare for next round */ ps->round_req = ps->cb_line_size; ps->round_read =0; } /* Repack the whole scan line and copy to caller's buffer */ while (remaining > 0 && ps->pos < ps->cb_line_size) { *pbuf++ = ps->xbuf[ps->pos++]; remaining--; } } *plen -= remaining; DBG(DL_DATA_TRACE, "%s: Request=%d, remaining=%d, read=%d, TXSource_rem=%d, bytes_rem=%lu\n", me, org_len, pself->remaining(pself), *plen, TxSource_remaining(pself), (u_long) ps->pss->bytes_remaining); return status; } static SANE_Status RGBRouter_done (Source *pself) { RGBRouter *ps = (RGBRouter *) pself; SANE_Status status = TxSource_done(pself); free(ps->cbuf); free(ps->xbuf); ps->cbuf = NULL; ps->cb_start = -1; ps->pos = 0; return status; } static SANE_Status RGBRouter_init (RGBRouter *pself, SnapScan_Scanner *pss, Source *psub) { SANE_Status status = TxSource_init((TxSource *) pself, pss, RGBRouter_remaining, TxSource_bytesPerLine, TxSource_pixelsPerLine, RGBRouter_get, RGBRouter_done, psub); if (status == SANE_STATUS_GOOD) { SANE_Int lines_in_buffer = 0; /* Size the buffer to accomodate the necessary number of scan lines to cater for the offset between R, G and B */ lines_in_buffer = pss->chroma + 1; pself->cb_line_size = pself->bytesPerLine((Source *) pself); pself->cb_size = pself->cb_line_size*lines_in_buffer; pself->pos = pself->cb_line_size; pself->round_req = pself->cb_size; pself->round_read = 0; pself->cbuf = (SANE_Byte *) malloc(pself->cb_size); pself->xbuf = (SANE_Byte *) malloc(pself->cb_line_size); if (pself->cbuf == NULL || pself->xbuf == NULL) { DBG (DL_MAJOR_ERROR, "%s: failed to allocate circular buffer.\n", __func__); status = SANE_STATUS_NO_MEM; } else { SANE_Int ch; pself->cb_start = 0; for (ch = 0; ch < 3; ch++) { pself->ch_offset[ch] = pss->chroma_offset[ch] * pself->cb_line_size + ch * (pself->cb_line_size / 3); } } DBG(DL_MINOR_INFO, "RGBRouter_init: buf_size: %d x %d = %d\n", pself->cb_line_size, lines_in_buffer, pself->cb_size); DBG(DL_MINOR_INFO, "RGBRouter_init: buf offset R:%d G:%d B:%d\n", pself->ch_offset[0], pself->ch_offset[1],pself->ch_offset[2]); } return status; } static SANE_Status create_RGBRouter (SnapScan_Scanner *pss, Source *psub, Source **pps) { static char me[] = "create_RGBRouter"; SANE_Status status = SANE_STATUS_GOOD; DBG (DL_CALL_TRACE, "%s\n", me); *pps = (Source *) malloc(sizeof(RGBRouter)); if (*pps == NULL) { DBG (DL_MAJOR_ERROR, "%s: failed to allocate RGBRouter.\n", __func__); status = SANE_STATUS_NO_MEM; } else { status = RGBRouter_init ((RGBRouter *) *pps, pss, psub); } return status; } /* An Inverter is used to invert the bits in a lineart image */ typedef struct { TX_SOURCE_GUTS; } Inverter; static SANE_Status Inverter_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen) { SANE_Status status = TxSource_get (pself, pbuf, plen); if (status == SANE_STATUS_GOOD) { int i; for (i = 0; i < *plen; i++) pbuf[i] ^= 0xFF; } return status; } static SANE_Status Inverter_init (Inverter *pself, SnapScan_Scanner *pss, Source *psub) { return TxSource_init ((TxSource *) pself, pss, TxSource_remaining, TxSource_bytesPerLine, TxSource_pixelsPerLine, Inverter_get, TxSource_done, psub); } static SANE_Status create_Inverter (SnapScan_Scanner *pss, Source *psub, Source **pps) { SANE_Status status = SANE_STATUS_GOOD; *pps = (Source *) malloc(sizeof(Inverter)); if (*pps == NULL) { DBG (DL_MAJOR_ERROR, "%s: failed to allocate Inverter.\n", __func__); status = SANE_STATUS_NO_MEM; } else { status = Inverter_init ((Inverter *) *pps, pss, psub); } return status; } /* Source chain creation */ static SANE_Status create_source_chain (SnapScan_Scanner *pss, BaseSourceType bst, Source **pps) { static char me[] = "create_source_chain"; SANE_Status status = create_base_source (pss, bst, pps); DBG (DL_CALL_TRACE, "%s\n", me); if (status == SANE_STATUS_GOOD) { SnapScan_Mode mode = actual_mode(pss); switch (mode) { case MD_COLOUR: status = create_RGBRouter (pss, *pps, pps); /* We only have the interlace probelms on some scanners like the Epson Perfection 2480/2580 at 2400 dpi. */ if (status == SANE_STATUS_GOOD && ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) || (pss->pdev->model == PERFECTION3490 && pss->res == 3200) || (pss->pdev->model == PRISA5000E && pss->res == 1200))) status = create_Deinterlacer (pss, *pps, pps); break; case MD_BILEVELCOLOUR: status = create_Expander (pss, *pps, pps); if (status == SANE_STATUS_GOOD) status = create_RGBRouter (pss, *pps, pps); if (status == SANE_STATUS_GOOD && ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) || (pss->pdev->model == PERFECTION3490 && pss->res == 3200) || (pss->pdev->model == PRISA5000E && pss->res == 1200))) status = create_Deinterlacer (pss, *pps, pps); break; case MD_GREYSCALE: if ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) || (pss->pdev->model == PERFECTION3490 && pss->res == 3200) || (pss->pdev->model == PRISA5000E && pss->res == 1200)) status = create_Deinterlacer (pss, *pps, pps); break; case MD_LINEART: /* The SnapScan creates a negative image by default... so for the user interface to make sense, the internal meaning of "negative" is reversed */ if (pss->negative == SANE_FALSE) status = create_Inverter (pss, *pps, pps); if (pss->pdev->model == PERFECTION3490 && pss->res == 3200) status = create_Deinterlacer (pss, *pps, pps); break; default: DBG (DL_MAJOR_ERROR, "%s: bad mode value %d (internal error)\n", __func__, mode); status = SANE_STATUS_INVAL; break; } } return status; } /* * $Log$ * Revision 1.21 2005/12/02 19:12:54 oliver-guest * Another fix for lineart mode for the Epson 3490 @ 3200 DPI * * Revision 1.20 2005/11/28 19:28:29 oliver-guest * Fix for lineart mode of Epson 3490 @ 3200 DPI * * Revision 1.19 2005/11/25 17:24:48 oliver-guest * Fix for Epson 3490 @ 3200 DPI for grayscale and lineart mode * * Revision 1.18 2005/11/17 23:47:11 oliver-guest * Revert previous 'fix', disable 2400 dpi for Epson 3490, use 1600 dpi instead * * Revision 1.17 2005/11/17 23:32:23 oliver-guest * Fixes for Epson 3490 @ 2400 DPI * * Revision 1.16 2005/11/10 19:42:02 oliver-guest * Added deinterlacing for Epson 3490 * * Revision 1.15 2005/10/31 21:08:47 oliver-guest * Distinguish between Benq 5000/5000E/5000U * * Revision 1.14 2005/10/13 22:43:30 oliver-guest * Fixes for 16 bit scan mode from Simon Munton * * Revision 1.13 2005/10/11 18:47:07 oliver-guest * Fixes for Epson 3490 and 16 bit scan mode * * Revision 1.12 2004/11/14 19:26:38 oliver-guest * Applied patch from Julien Blache to change ch_past_init from SANE_Int to SANE_Bool * * Revision 1.11 2004/11/09 23:17:38 oliver-guest * First implementation of deinterlacer for Epson scanners at high resolutions (thanks to Brad Johnson) * * Revision 1.10 2004/10/03 17:34:36 hmg-guest * 64 bit platform fixes (bug #300799). * * Revision 1.9 2004/04/09 16:18:37 oliver-guest * Fix initialization of FDSource.bytes_remaining * * Revision 1.8 2004/04/09 11:59:02 oliver-guest * Fixes for pthread implementation * * Revision 1.7 2004/04/08 21:53:10 oliver-guest * Use sanei_thread in snapscan backend * * Revision 1.6 2001/12/17 22:51:49 oliverschwartz * Update to snapscan-20011212 (snapscan 1.4.3) * * Revision 1.18 2001/12/12 19:44:59 oliverschwartz * Clean up CVS log * * Revision 1.17 2001/11/27 23:16:17 oliverschwartz * - Fix color alignment for SnapScan 600 * - Added documentation in snapscan-sources.c * - Guard against TL_X < BR_X and TL_Y < BR_Y * * Revision 1.16 2001/10/08 18:22:02 oliverschwartz * - Disable quality calibration for Acer Vuego 310F * - Use sanei_scsi_max_request_size as scanner buffer size * for SCSI devices * - Added new devices to snapscan.desc * * Revision 1.15 2001/09/28 15:56:51 oliverschwartz * - fix hanging for SNAPSCAN300 / VUEGO 310 * * Revision 1.14 2001/09/28 13:39:16 oliverschwartz * - Added "Snapscan 300" ID string * - cleanup * - more debugging messages in snapscan-sources.c * * Revision 1.13 2001/09/18 15:01:07 oliverschwartz * - Read scanner id string again after firmware upload * to indentify correct model * - Make firmware upload work for AGFA scanners * - Change copyright notice * * Revision 1.12 2001/09/09 18:06:32 oliverschwartz * add changes from Acer (new models; automatic firmware upload for USB scanners); fix distorted colour scans after greyscale scans (call set_window only in sane_start); code cleanup * * Revision 1.11 2001/04/13 13:12:18 oliverschwartz * use absolute_max as expected_read_bytes for PRISA620S * * Revision 1.10 2001/04/10 11:04:31 sable * Adding support for snapscan e40 an e50 thanks to Giuseppe Tanzilli * * Revision 1.9 2001/03/17 22:53:21 sable * Applying Mikael Magnusson patch concerning Gamma correction * Support for 1212U_2 * * Revision 1.8 2000/11/28 03:55:07 cbagwell * Reverting a fix to RGBRouter_remaining to original fix. This allows * most scanners to scan at 600 dpi by ignoring insufficent data in * the RGB circular buffer and always returning size = 1 in those cases. * This should probably be fixed at a higher level. * * Revision 1.7 2000/11/20 01:02:42 cbagwell * Updates so that USB will continue reading when it receives an EAGAIN error. * Also, changed RGBRouter_remaining to not be able to return a negative * value. * * Revision 1.6 2000/11/04 01:53:58 cbagwell * Commiting some needed USB updates. Added extra test logic to detect * bad bytes_expected values. Just to help debug faster on scanners * that tickle the bug. * * Revision 1.5 2000/10/30 22:32:20 sable * Support for vuego310s vuego610s and 1236s * * Revision 1.4 2000/10/28 14:16:10 sable * Bug correction for SnapScan310 * * Revision 1.3 2000/10/28 14:06:35 sable * Add support for Acer300f * * Revision 1.2 2000/10/13 03:50:27 cbagwell * Updating to source from SANE 1.0.3. Calling this versin 1.1 * */ sane-backends-1.0.27/backend/mustek_usb2.c0000664000175000017500000020546112775312261015236 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000-2005 Mustek. Originally maintained by Mustek Copyright (C) 2001-2005 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro and similar USB2 scanners. */ #define BUILD 10 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME mustek_usb2 #include "../include/sane/sanei_backend.h" #include "mustek_usb2_high.c" #include "mustek_usb2.h" static SANE_Int num_devices; static const SANE_Device **devlist = 0; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static SANE_Range x_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (8.3 * MM_PER_INCH), /* maximum */ SANE_FIX (0.0) /* quantization */ }; static SANE_Range y_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (11.6 * MM_PER_INCH), /* maximum */ SANE_FIX (0.0) /* quantization */ }; static SANE_Range gamma_range = { SANE_FIX (0.01), /* minimum */ SANE_FIX (5.0), /* maximum */ SANE_FIX (0.01) /* quantization */ }; static SANE_String_Const mode_list[] = { SANE_I18N ("Color48"), SANE_I18N ("Color24"), SANE_I18N ("Gray16"), SANE_I18N ("Gray8"), SANE_VALUE_SCAN_MODE_LINEART, 0 }; static SANE_String_Const negative_mode_list[] = { SANE_I18N ("Color24"), 0 }; static SANE_String_Const source_list[] = { SANE_I18N ("Reflective"), SANE_I18N ("Positive"), SANE_I18N ("Negative"), 0 }; static Scanner_Model mustek_A2nu2_model = { "mustek-A2nu2", /* Name */ "Mustek", /* Device vendor string */ "BearPaw 2448TA Pro", /* Device model name */ "", /* Name of the firmware file */ {1200, 600, 300, 150, 75, 0}, /* possible resolutions */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (0.0), /* Start of scan area in mm (y) */ SANE_FIX (8.3 * MM_PER_INCH), /* Size of scan area in mm (x) */ SANE_FIX (11.6 * MM_PER_INCH), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (1.46 * MM_PER_INCH), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (6.45 * MM_PER_INCH), /* Size of scan area in TA mode in mm (y) */ 0, /* Order of the CCD/CIS colors 0:RO_RGB 1:RO_BGR */ SANE_FIX (2.0), /* Default gamma value */ SANE_FALSE, /* Is this a CIS scanner? */ 0 /* Which flags are needed for this scanner? */ /* Setup and tested */ }; /* Forward declarations */ static SANE_Bool GetDeviceStatus (void); static SANE_Bool PowerControl (SANE_Bool isLampOn, SANE_Bool isTaLampOn); static SANE_Bool CarriageHome (void); static SANE_Bool SetParameters (LPSETPARAMETERS pSetParameters); static SANE_Bool GetParameters (LPGETPARAMETERS pGetParameters); static SANE_Bool StartScan (void); static SANE_Bool ReadScannedData (LPIMAGEROWS pImageRows); static SANE_Bool StopScan (void); static SANE_Bool IsTAConnected (void); static void AutoLevel (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines, unsigned int BytesPerLine); static size_t max_string_size (const SANE_String_Const strings[]); static SANE_Status calc_parameters (Mustek_Scanner * s); #ifdef SANE_UNUSED static SANE_Bool GetGammaInfo (LPGAMMAINFO pGamaInfo); static SANE_Bool GetKeyStatus (SANE_Byte * pKey); static void QBetChange (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines, unsigned int BytesPerLine); static void QBETDetectAutoLevel (void *pDIB, unsigned int ImageWidth, unsigned int ImageHeight); #endif static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status calc_parameters (Mustek_Scanner * s) { SANE_String val, val_source; val = s->val[OPT_MODE].s; val_source = s->val[OPT_SOURCE].s; s->params.last_frame = SANE_TRUE; if (strcmp (val, "Color48") == 0) /* Color48 */ { s->params.format = SANE_FRAME_RGB; s->params.depth = 16; s->setpara.smScanMode = SM_RGB48; if (s->val[OPT_PREVIEW].w) { DBG (DBG_DET, "calc_parameters : preview set ScanMode SM_RGB24\n"); s->params.depth = 8; s->setpara.smScanMode = SM_RGB24; } } else if (strcmp (val, "Color24") == 0) /* Color24 */ { s->params.format = SANE_FRAME_RGB; s->params.depth = 8; s->setpara.smScanMode = SM_RGB24; } else if (strcmp (val, "Gray16") == 0) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 16; s->setpara.smScanMode = SM_GRAY16; if (s->val[OPT_PREVIEW].w) { s->params.depth = 8; DBG (DBG_DET, "calc_parameters : preview set ScanMode SM_GRAY\n"); s->setpara.smScanMode = SM_GRAY; } } else if (strcmp (val, "Gray8") == 0) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 8; s->setpara.smScanMode = SM_GRAY; } else if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 1; s->setpara.smScanMode = SM_TEXT; } /*set Scan Source */ DBG (DBG_DET, "calc_parameters :scan Source = %s\n", val_source); if (strcmp (val_source, "Reflective") == 0) { s->setpara.ssScanSource = SS_Reflective; } else if (strcmp (val_source, "Positive") == 0) { s->setpara.ssScanSource = SS_Positive; } else if (strcmp (val_source, "Negative") == 0) { s->setpara.ssScanSource = SS_Negative; } s->setpara.fmArea.x1 = (unsigned short) ((SANE_UNFIX (s->val[OPT_TL_X].w) * 300.0) / MM_PER_INCH + 0.5); s->setpara.fmArea.x2 = (unsigned short) ((SANE_UNFIX (s->val[OPT_BR_X].w) * 300.0) / MM_PER_INCH + 0.5); s->setpara.fmArea.y1 = (unsigned short) ((SANE_UNFIX (s->val[OPT_TL_Y].w) * 300.0) / MM_PER_INCH + 0.5); s->setpara.fmArea.y2 = (unsigned short) ((SANE_UNFIX (s->val[OPT_BR_Y].w) * 300.0) / MM_PER_INCH + 0.5); if (s->val[OPT_PREVIEW].w) { s->setpara.fmArea.y1 = s->setpara.fmArea.y1 + PER_ADD_START_LINES; s->setpara.fmArea.x1 += PRE_ADD_START_X; } /*just for range bug. */ s->setpara.pfPixelFlavor = PF_BlackIs0; s->setpara.wLinearThreshold = s->val[OPT_THRESHOLD].w; s->setpara.wTargetDPI = s->val[OPT_RESOLUTION].w; if (s->val[OPT_PREVIEW].w) { s->setpara.wTargetDPI = 75; } s->setpara.pGammaTable = NULL; s->params.pixels_per_line = (SANE_Int) ((s->setpara.fmArea.x2 - s->setpara.fmArea.x1) * s->setpara.wTargetDPI / 300.0 + 0.5); switch (s->params.format) { case SANE_FRAME_RGB: if (s->params.depth == 8) s->params.bytes_per_line = s->params.pixels_per_line * 3; if (s->params.depth == 16) s->params.bytes_per_line = s->params.pixels_per_line * 6; break; case SANE_FRAME_GRAY: if (s->params.depth == 1) s->params.bytes_per_line = s->params.pixels_per_line / 8; if (s->params.depth == 8) s->params.bytes_per_line = s->params.pixels_per_line; if (s->params.depth == 16) s->params.bytes_per_line = s->params.pixels_per_line * 2; break; default: DBG (DBG_DET, "sane_star:sane params .format = %d\n", s->params.format); } s->params.lines = (SANE_Int) ((s->setpara.fmArea.y2 - s->setpara.fmArea.y1) * s->setpara.wTargetDPI / 300 + 0.5); DBG (DBG_FUNC, "calc_parameters: end\n"); return SANE_STATUS_GOOD; } static SANE_Status init_options (Mustek_Scanner * s) { SANE_Int option, count; SANE_Word *dpi_list; /*Resolution Support */ DBG (DBG_FUNC, "init_options: start\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (option = 0; option < NUM_OPTIONS; ++option) { s->opt[option].size = sizeof (SANE_Word); s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Option num */ s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup ("Color24"); /* Scan Source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].size = max_string_size (source_list); s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].s = strdup ("Reflective"); if (!IsTAConnected ()) { DISABLE (OPT_SOURCE); } /* resolution */ for (count = 0; s->model.dpi_values[count] != 0; count++) { } dpi_list = malloc ((count + 1) * sizeof (SANE_Word)); if (!dpi_list) return SANE_STATUS_NO_MEM; dpi_list[0] = count; for (count = 0; s->model.dpi_values[count] != 0; count++) dpi_list[count + 1] = s->model.dpi_values[count]; s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; s->val[OPT_RESOLUTION].w = 300; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_PREVIEW].w = SANE_FALSE; /* "Debug" group: */ s->opt[OPT_DEBUG_GROUP].title = SANE_I18N ("Debugging Options"); s->opt[OPT_DEBUG_GROUP].desc = ""; s->opt[OPT_DEBUG_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_DEBUG_GROUP].size = 0; s->opt[OPT_DEBUG_GROUP].cap = 0; s->opt[OPT_DEBUG_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* auto warmup */ s->opt[OPT_AUTO_WARMUP].name = "auto-warmup"; s->opt[OPT_AUTO_WARMUP].title = SANE_I18N ("Automatic warmup"); s->opt[OPT_AUTO_WARMUP].desc = SANE_I18N ("Warm-up until the lamp's brightness is constant " "instead of insisting on 40 seconds warm-up time."); s->opt[OPT_AUTO_WARMUP].type = SANE_TYPE_BOOL; s->opt[OPT_AUTO_WARMUP].unit = SANE_UNIT_NONE; s->opt[OPT_AUTO_WARMUP].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_AUTO_WARMUP].w = SANE_FALSE; if (s->model.is_cis) DISABLE (OPT_AUTO_WARMUP); /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &u8_range; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->val[OPT_THRESHOLD].w = DEF_LINEARTTHRESHOLD; /* internal gamma value */ s->opt[OPT_GAMMA_VALUE].name = "gamma-value"; s->opt[OPT_GAMMA_VALUE].title = SANE_I18N ("Gamma value"); s->opt[OPT_GAMMA_VALUE].desc = SANE_I18N ("Sets the gamma value of all channels."); s->opt[OPT_GAMMA_VALUE].type = SANE_TYPE_FIXED; s->opt[OPT_GAMMA_VALUE].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VALUE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VALUE].constraint.range = &gamma_range; s->opt[OPT_GAMMA_VALUE].cap |= SANE_CAP_EMULATED; s->val[OPT_GAMMA_VALUE].w = s->model.default_gamma_value; DISABLE (OPT_GAMMA_VALUE); /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; x_range.max = s->model.x_size; y_range.max = s->model.y_size; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &x_range; s->val[OPT_BR_X].w = x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &y_range; s->val[OPT_BR_Y].w = y_range.max; calc_parameters (s); DBG (DBG_FUNC, "init_options: exit\n"); return SANE_STATUS_GOOD; } /***************************** Code from spicall.c *****************************/ static SANE_Byte * g_lpNegImageData = NULL; static SANE_Bool g_bIsFirstGetNegData = TRUE; static SANE_Bool g_bIsMallocNegData = FALSE; static unsigned int g_dwAlreadyGetNegLines = 0; /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: Check the device connect status Parameters: none Return value: if the device is connected return TRUE else return FALSE ***********************************************************************/ static SANE_Bool GetDeviceStatus () { DBG (DBG_FUNC, "GetDeviceStatus: start\n"); return MustScanner_GetScannerState (); } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: Turn the lamp on or off Parameters: isLampOn: turn the lamp on or off isTALampOn: turn the TA lamp on or off Return value: if operation success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool PowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn) { DBG (DBG_FUNC, "PowerControl: start\n"); return MustScanner_PowerControl (isLampOn, isTALampOn); } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: Turn the carriage home Parameters: none Return value: if the operation success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool CarriageHome () { DBG (DBG_FUNC, "CarriageHome: start\n"); return MustScanner_BackHome (); } #ifdef SANE_UNUSED /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: Get gamma input/output bit count Parameters: pGammaInfo: the gamma information Return value: if the operation success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool GetGammaInfo (LPGAMMAINFO pGammaInfo) { DBG (DBG_FUNC, "GetGammaInfo: start\n"); switch (pGammaInfo->smScanMode) { case SM_GRAY: pGammaInfo->wInputGammaBits = 12; pGammaInfo->wOutputGammaBits = 8; break; case SM_RGB24: pGammaInfo->wInputGammaBits = 12; pGammaInfo->wOutputGammaBits = 8; break; case SM_GRAY16: pGammaInfo->wInputGammaBits = 16; pGammaInfo->wOutputGammaBits = 16; break; case SM_RGB48: pGammaInfo->wInputGammaBits = 16; pGammaInfo->wOutputGammaBits = 16; break; default: pGammaInfo->wInputGammaBits = 0; pGammaInfo->wOutputGammaBits = 0; return FALSE; } DBG (DBG_FUNC, "GetGammaInfo: exit\n"); return TRUE; } #endif /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: set scan parameters Parameters: pSetParameters: the information of scaning Return value: if the operation success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool SetParameters (LPSETPARAMETERS pSetParameters) { unsigned short X1inTargetDpi; unsigned short Y1inTargetDpi; unsigned short X2inTargetDpi; unsigned short Y2inTargetDpi; DBG (DBG_FUNC, "SetParameters: start\n"); /*0. Reset */ if (ST_Reflective == g_ScanType) { Reflective_Reset (); } else { Transparent_Reset (); } /*1. Scan mode */ switch (pSetParameters->smScanMode) { case SM_TEXT: g_tiTarget.cmColorMode = CM_TEXT; break; case SM_GRAY: g_tiTarget.cmColorMode = CM_GRAY8; break; case SM_GRAY16: g_tiTarget.cmColorMode = CM_GRAY16; break; case SM_RGB24: g_tiTarget.cmColorMode = CM_RGB24; break; case SM_RGB48: g_tiTarget.cmColorMode = CM_RGB48; break; default: return FALSE; } /*2. Scan source */ g_ssScanSource = pSetParameters->ssScanSource; g_tiTarget.bScanSource = pSetParameters->ssScanSource; if (SS_Reflective == pSetParameters->ssScanSource) { g_ScanType = ST_Reflective; } else if (SS_Positive == pSetParameters->ssScanSource || SS_Negative == pSetParameters->ssScanSource || SS_ADF == pSetParameters->ssScanSource) { g_ScanType = ST_Transparent; } else { DBG (DBG_ERR, "SetParameters: ScanSource error\n"); return FALSE; } /*3. pixel flavor */ if (PF_BlackIs0 == pSetParameters->pfPixelFlavor || PF_WhiteIs0 == pSetParameters->pfPixelFlavor) { g_PixelFlavor = pSetParameters->pfPixelFlavor; } else { DBG (DBG_ERR, "SetParameters: PixelFlavor error\n"); return FALSE; } /*4. Scan area */ if (pSetParameters->fmArea.x1 >= pSetParameters->fmArea.x2) { DBG (DBG_ERR, "SetParameters: x1 > x2, error\n"); return FALSE; } if (pSetParameters->fmArea.y1 >= pSetParameters->fmArea.y2) { DBG (DBG_ERR, "SetParameters: y1 >= y2, error\n"); return FALSE; } if (pSetParameters->fmArea.x2 > MAX_SCANNING_WIDTH) /* Just for A4 size */ { DBG (DBG_ERR, "SetParameters: x2 > MAX_SCANNING_WIDTH, error\n"); return FALSE; } if (pSetParameters->fmArea.y2 > MAX_SCANNING_HEIGHT) /* Just for A4 size */ { DBG (DBG_ERR, "SetParameters: y2 > MAX_SCANNING_HEIGHT, error\n"); return FALSE; } X1inTargetDpi = (unsigned short) ((unsigned int) (pSetParameters->fmArea.x1) * (unsigned int) (pSetParameters->wTargetDPI) / 300L); Y1inTargetDpi = (unsigned short) ((unsigned int) (pSetParameters->fmArea.y1) * (unsigned int) (pSetParameters->wTargetDPI) / 300L); X2inTargetDpi = (unsigned short) ((unsigned int) (pSetParameters->fmArea.x2) * (unsigned int) (pSetParameters->wTargetDPI) / 300L); Y2inTargetDpi = (unsigned short) ((unsigned int) (pSetParameters->fmArea.y2) * (unsigned int) (pSetParameters->wTargetDPI) / 300L); g_tiTarget.isOptimalSpeed = TRUE; g_tiTarget.wDpi = pSetParameters->wTargetDPI; g_tiTarget.wX = X1inTargetDpi; g_tiTarget.wY = Y1inTargetDpi; g_tiTarget.wWidth = X2inTargetDpi - X1inTargetDpi; g_tiTarget.wHeight = Y2inTargetDpi - Y1inTargetDpi; DBG (DBG_INFO, "SetParameters: g_tiTarget.wDpi=%d\n", g_tiTarget.wDpi); DBG (DBG_INFO, "SetParameters: g_tiTarget.wX=%d\n", g_tiTarget.wX); DBG (DBG_INFO, "SetParameters: g_tiTarget.wY=%d\n", g_tiTarget.wY); DBG (DBG_INFO, "SetParameters: g_tiTarget.wWidth=%d\n", g_tiTarget.wWidth); DBG (DBG_INFO, "SetParameters: g_tiTarget.wHeight=%d\n", g_tiTarget.wHeight); /*5.Prepare */ if (FALSE == MustScanner_Prepare (g_tiTarget.bScanSource)) { DBG (DBG_ERR, "SetParameters: MustScanner_Prepare fail\n"); return FALSE; } /*6. Linear threshold */ if (pSetParameters->wLinearThreshold > 256 && pSetParameters->smScanMode == SM_TEXT) { DBG (DBG_ERR, "SetParameters: LinearThreshold error\n"); return FALSE; } else { g_wLineartThreshold = pSetParameters->wLinearThreshold; } /*7. Gamma table */ if (NULL != pSetParameters->pGammaTable) { DBG (DBG_INFO, "SetParameters: IN gamma table not NULL\n"); g_pGammaTable = pSetParameters->pGammaTable; g_isSelfGamma = FALSE; } else if (pSetParameters->smScanMode == SM_GRAY || pSetParameters->smScanMode == SM_RGB24) { unsigned short i; SANE_Byte byGammaData; double pow_d; double pow_z = (double) 10 / 16.0; g_pGammaTable = (unsigned short *) malloc (sizeof (unsigned short) * 4096 * 3); DBG (DBG_INFO, "SetParameters: gamma table malloc %ld Bytes\n", (long int) sizeof (unsigned short) * 4096 * 3); DBG (DBG_INFO, "SetParameters: address of g_pGammaTable=%p\n", (void *) g_pGammaTable); if (NULL == g_pGammaTable) { DBG (DBG_ERR, "SetParameters: gamma table malloc fail\n"); return FALSE; } g_isSelfGamma = TRUE; for (i = 0; i < 4096; i++) { pow_d = (double) i / (double) 4096; byGammaData = (SANE_Byte) (pow (pow_d, pow_z) * 255); *(g_pGammaTable + i) = byGammaData; *(g_pGammaTable + i + 4096) = byGammaData; *(g_pGammaTable + i + 8192) = byGammaData; } } else if (pSetParameters->smScanMode == SM_GRAY16 || pSetParameters->smScanMode == SM_RGB48) { unsigned int i, wGammaData; g_pGammaTable = (unsigned short *) malloc (sizeof (unsigned short) * 65536 * 3); if (g_pGammaTable == NULL) { DBG (DBG_ERR, "SetParameters: gamma table malloc fail\n"); return FALSE; } g_isSelfGamma = TRUE; for (i = 0; i < 65536; i++) { wGammaData = (unsigned short) (pow ((((float) i) / 65536.0), (((float) 10) / 16.0)) * 65535); *(g_pGammaTable + i) = wGammaData; *(g_pGammaTable + i + 65536) = wGammaData; *(g_pGammaTable + i + 65536 * 2) = wGammaData; } } else { DBG (DBG_INFO, "SetParameters: set g_pGammaTable to NULL\n"); g_pGammaTable = NULL; } DBG (DBG_FUNC, "SetParameters: exit\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: get the optical dpi and scan area Parameters: pGetParameters: the information of scan Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool GetParameters (LPGETPARAMETERS pGetParameters) { DBG (DBG_FUNC, "GetParameters: start\n"); if (ST_Reflective == g_ScanType) { if (FALSE == Reflective_ScanSuggest (&g_tiTarget, &g_ssSuggest)) { DBG (DBG_ERR, "GetParameters: Reflective_ScanSuggest error\n"); return FALSE; } } else { if (FALSE == Transparent_ScanSuggest (&g_tiTarget, &g_ssSuggest)) { DBG (DBG_ERR, "GetParameters: Transparent_ScanSuggest error\n"); return FALSE; } } pGetParameters->wSourceXDPI = g_ssSuggest.wXDpi; pGetParameters->wSourceYDPI = g_ssSuggest.wYDpi; pGetParameters->dwLength = (unsigned int) g_ssSuggest.wHeight; pGetParameters->dwLineByteWidth = g_ssSuggest.dwBytesPerRow; DBG (DBG_FUNC, "GetParameters: exit\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: start scan image Parameters: none Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool StartScan () { DBG (DBG_FUNC, "StartScan: start\n"); if (ST_Reflective == g_ScanType) { DBG (DBG_INFO, "StartScan: g_ScanType==ST_Reflective\n"); return Reflective_SetupScan (g_ssSuggest.cmScanMode, g_ssSuggest.wXDpi, g_ssSuggest.wYDpi, PF_BlackIs0, g_ssSuggest.wX, g_ssSuggest.wY, g_ssSuggest.wWidth, g_ssSuggest.wHeight); } else { DBG (DBG_INFO, "StartScan: g_ScanType==ST_Transparent\n"); return Transparent_SetupScan (g_ssSuggest.cmScanMode, g_ssSuggest.wXDpi, g_ssSuggest.wYDpi, PF_BlackIs0, g_ssSuggest.wX, g_ssSuggest.wY, g_ssSuggest.wWidth, g_ssSuggest.wHeight); } } /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Read the scanner data Parameters: pImageRows: the information of the data Return value: if the operation is seccuss return TRUE else return FALSE ***********************************************************************/ static SANE_Bool ReadScannedData (LPIMAGEROWS pImageRows) { SANE_Bool isRGBInvert; unsigned short Rows = 0; SANE_Byte *lpBlock = (SANE_Byte *) pImageRows->pBuffer; SANE_Byte *lpReturnData = (SANE_Byte *) pImageRows->pBuffer; int i = 0; DBG (DBG_FUNC, "ReadScannedData: start\n"); if (pImageRows->roRgbOrder == RO_RGB) isRGBInvert = FALSE; else isRGBInvert = TRUE; Rows = pImageRows->wWantedLineNum; DBG (DBG_INFO, "ReadScannedData: wanted Rows = %d\n", Rows); if (ST_Reflective == g_ScanType) { if (FALSE == Reflective_GetRows (lpBlock, &Rows, isRGBInvert)) return FALSE; } else if (SS_Positive == g_ssScanSource) { if (FALSE == Transparent_GetRows (lpBlock, &Rows, isRGBInvert)) return FALSE; } pImageRows->wXferedLineNum = Rows; if (g_PixelFlavor == PF_WhiteIs0 || g_ScanMode == CM_TEXT) { int TotalSize = Rows * g_ssSuggest.dwBytesPerRow; for (i = 0; i < TotalSize; i++) { *(lpBlock++) ^= 0xff; } } if (SS_Negative == g_ssScanSource) { DBG (DBG_INFO, "ReadScannedData: deal with the Negative\n"); if (g_bIsFirstGetNegData) { unsigned int TotalImgeSize = g_SWHeight * g_ssSuggest.dwBytesPerRow; g_lpNegImageData = (SANE_Byte *) malloc (TotalImgeSize); if (NULL != g_lpNegImageData) { SANE_Byte * lpTempData = g_lpNegImageData; DBG (DBG_INFO, "ReadScannedData: malloc the negative data is success!\n"); g_bIsMallocNegData = TRUE; if (!Transparent_GetRows (g_lpNegImageData, &g_SWHeight, isRGBInvert)) { return FALSE; } DBG (DBG_INFO, "ReadScannedData: get image data is over!\n"); for (i = 0; i < (int) TotalImgeSize; i++) { *(g_lpNegImageData++) ^= 0xff; } g_lpNegImageData = lpTempData; AutoLevel (g_lpNegImageData, g_ScanMode, g_SWHeight, g_ssSuggest.dwBytesPerRow); DBG (DBG_INFO, "ReadScannedData: autolevel is ok\n"); } g_bIsFirstGetNegData = FALSE; } if (g_bIsMallocNegData) { memcpy (pImageRows->pBuffer, g_lpNegImageData + g_ssSuggest.dwBytesPerRow * g_dwAlreadyGetNegLines, g_ssSuggest.dwBytesPerRow * Rows); DBG (DBG_INFO, "ReadScannedData: copy the data over!\n"); g_dwAlreadyGetNegLines += Rows; if (g_dwAlreadyGetNegLines >= g_SWHeight) { DBG (DBG_INFO, "ReadScannedData: free the image data!\n"); free (g_lpNegImageData); g_lpNegImageData = NULL; g_bIsFirstGetNegData = TRUE; g_dwAlreadyGetNegLines = 0; g_bIsMallocNegData = FALSE; } } else { int TotalSize = Rows * g_ssSuggest.dwBytesPerRow; DBG (DBG_INFO, "ReadScannedData: malloc the negative data is fail!\n"); if (!Transparent_GetRows (lpReturnData, &Rows, isRGBInvert)) { return FALSE; } for (i = 0; i < TotalSize; i++) { *(lpReturnData++) ^= 0xff; } pImageRows->wXferedLineNum = Rows; g_dwAlreadyGetNegLines += Rows; if (g_dwAlreadyGetNegLines >= g_SWHeight) { g_bIsFirstGetNegData = TRUE; g_dwAlreadyGetNegLines = 0; g_bIsMallocNegData = FALSE; } } } DBG (DBG_FUNC, "ReadScannedData: leave ReadScannedData\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Stop scan Parameters: none Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool StopScan () { SANE_Bool rt; int i; DBG (DBG_FUNC, "StopScan: start\n"); /*stop read data and kill thread */ if (ST_Reflective == g_ScanType) { rt = Reflective_StopScan (); } else { rt = Transparent_StopScan (); } /*free gamma table */ if (g_isSelfGamma && g_pGammaTable != NULL) { for (i = 0; i < 20; i++) { if (!g_isScanning) { free (g_pGammaTable); g_pGammaTable = NULL; break; } else { sleep (1); /*waiting ReadScannedData return. */ } } } /*free image buffer */ if (g_lpReadImageHead != NULL) { free (g_lpReadImageHead); g_lpReadImageHead = NULL; } DBG (DBG_FUNC, "StopScan: exit\n"); return rt; } /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Check the status of TA Parameters: none Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool IsTAConnected () { SANE_Bool hasTA; DBG (DBG_FUNC, "StopScan: start\n"); if (Asic_Open (&g_chip, g_pDeviceFile) != STATUS_GOOD) { return FALSE; } if (Asic_IsTAConnected (&g_chip, &hasTA) != STATUS_GOOD) { Asic_Close (&g_chip); return FALSE; } Asic_Close (&g_chip); DBG (DBG_FUNC, "StopScan: exit\n"); return hasTA; } #ifdef SANE_UNUSED /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Get the status of the HK Parameters: pKey: the status of key Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool GetKeyStatus (SANE_Byte * pKey) { SANE_Byte pKeyTemp = 0x00; STATUS status = Asic_CheckFunctionKey (&g_chip, &pKeyTemp); DBG (DBG_FUNC, "GetKeyStatus: start\n"); if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile)) { DBG (DBG_ERR, "GetKeyStatus: Asic_Open is fail\n"); return FALSE; } if (STATUS_GOOD != status) { DBG (DBG_ERR, "GetKeyStatus: Asic_CheckFunctionKey is fail\n"); return FALSE; } if (0x01 == pKeyTemp) { *pKey = 0x01; /*Scan key pressed */ } if (0x02 == pKeyTemp) { *pKey = 0x02; /*Copy key pressed */ } if (0x04 == pKeyTemp) { *pKey = 0x03; /*Fax key pressed */ } if (0x08 == pKeyTemp) { *pKey = 0x04; /*Email key pressed */ } if (0x10 == pKeyTemp) { *pKey = 0x05; /*Panel key pressed */ } if (STATUS_GOOD != Asic_Close (&g_chip)) { DBG (DBG_ERR, "GetKeyStatus: Asic_Close is fail\n"); return FALSE; } DBG (DBG_FUNC, "GetKeyStatus: exit\n"); return TRUE; } #endif /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Deal with the image with auto level Parameters: lpSource: the data of image scanMode: the scan mode ScanLines: the rows of image BytesPerLine: the bytes of per line Return value: none ***********************************************************************/ static void AutoLevel (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines, unsigned int BytesPerLine) { int ii; unsigned int i, j; unsigned int tLines, CountPixels, TotalImgSize; unsigned short R, G, B, max_R, max_G, max_B, min_R, min_G, min_B; float fmax_R, fmax_G, fmax_B; unsigned int sum_R = 0, sum_G = 0, sum_B = 0; unsigned int hisgram_R[256], hisgram_G[256], hisgram_B[256]; unsigned int iWidth = BytesPerLine / 3; unsigned int iHeight = ScanLines; SANE_Byte *pbmpdata = (SANE_Byte *) lpSource; unsigned short imin_threshold[3]; unsigned short imax_threshold[3]; DBG (DBG_FUNC, "AutoLevel: start\n"); if (scanMode != CM_RGB24ext) { return; } i = j = 0; tLines = CountPixels = TotalImgSize = 0; TotalImgSize = iWidth * iHeight; for (i = 0; i < 256; i++) { hisgram_R[i] = 0; hisgram_G[i] = 0; hisgram_B[i] = 0; } DBG (DBG_INFO, "AutoLevel: init data is over\n"); /* Find min , max, mean */ max_R = max_G = max_B = 0; min_R = min_G = min_B = 255; tLines = 0; DBG (DBG_INFO, "AutoLevel: iHeight = %d, iWidth = %d\n", iHeight, iWidth); for (j = 0; j < iHeight; j++) { tLines = j * iWidth * 3; for (i = 0; i < iWidth; i++) { R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2)); G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1)); B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3)); max_R = _MAX (R, max_R); max_G = _MAX (G, max_G); max_B = _MAX (B, max_B); min_R = _MIN (R, min_R); min_G = _MIN (G, min_G); min_B = _MIN (B, min_B); hisgram_R[(SANE_Byte) R]++; hisgram_G[(SANE_Byte) G]++; hisgram_B[(SANE_Byte) B]++; sum_R += R; sum_G += G; sum_B += B; *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R; *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G; *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B; CountPixels++; } } DBG (DBG_INFO, "AutoLevel: Find min , max is over!\n"); imin_threshold[0] = 0; imin_threshold[1] = 0; imin_threshold[2] = 0; imax_threshold[0] = 0; imax_threshold[1] = 0; imax_threshold[2] = 0; for (ii = 0; ii < 256; ii++) { if (hisgram_R[ii] > 0) if (hisgram_R[ii] >= imin_threshold[0]) { min_R = ii; break; } } for (ii = 255; ii >= 0; ii--) { if (hisgram_R[ii] > 0) if (hisgram_R[ii] >= imax_threshold[0]) { max_R = ii; break; } } for (ii = 0; ii < 256; ii++) { if (hisgram_G[ii] > 0) if (hisgram_G[ii] >= imin_threshold[1]) { min_G = ii; break; } } for (ii = 255; ii >= 0; ii--) { if (hisgram_G[ii] > 0) if (hisgram_G[ii] >= imax_threshold[1]) { max_G = ii; break; } } for (ii = 0; ii < 256; ii++) { if (hisgram_B[ii] > 0) if (hisgram_B[ii] >= imin_threshold[2]) { min_B = ii; break; } } for (ii = 255; ii >= 0; ii--) { if (hisgram_B[ii] > 0) if (hisgram_B[ii] >= imax_threshold[2]) { max_B = ii; break; } } DBG (DBG_INFO, "AutoLevel: Set min , max is over!\n"); /*Autolevel: */ sum_R = max_R - min_R; sum_G = max_G - min_G; sum_B = max_B - min_B; for (j = 0; j < iHeight; j++) { tLines = j * iWidth * 3; for (i = 0; i < iWidth; i++) { R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2)); G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1)); B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3)); /*R*/ if (sum_R == 0) R = max_R; else if (R < min_R) R = 0; else if (R <= 255) { fmax_R = ((float) ((R - min_R) * 255) / (float) sum_R); R = (unsigned short) fmax_R; fmax_R = (fmax_R - R) * 10; if (fmax_R >= 5) R++; } if (R > 255) R = 255; /*G*/ if (sum_G == 0) G = max_G; else if (G < min_G) G = 0; else if (G <= 255) { fmax_G = ((float) ((G - min_G) * 255) / (float) sum_G); G = (unsigned short) fmax_G; fmax_G = (fmax_G - G) * 10; if (fmax_G >= 5) G++; } if (G > 255) G = 255; /*B*/ if (sum_B == 0) B = max_B; else if (B < min_B) B = 0; else if (B <= 255) { fmax_B = ((float) (B - min_B) * 255 / (float) sum_B); B = (unsigned short) fmax_B; fmax_B = (fmax_B - B) * 10; if (fmax_B >= 5) B++; } if (B > 255) B = 255; hisgram_R[(SANE_Byte) R]++; hisgram_G[(SANE_Byte) G]++; hisgram_B[(SANE_Byte) B]++; *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R; *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G; *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B; } } DBG (DBG_FUNC, "AutoLevel: exit\n"); return; } #ifdef SANE_UNUSED /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Deal with image with auto level Parameters: pDIB: the data of image ImageWidth: the width of image ImageHeight: the height of image Return value: none ***********************************************************************/ static void QBETDetectAutoLevel (void *pDIB, unsigned int ImageWidth, unsigned int ImageHeight) { unsigned short *pbmpdata; float fRPercent = 0.0; float fGPercent = 0.0; float fBPercent = 0.0; float fRSum, fGSum, fBSum; int i, j; unsigned int tLines, CountPixels, TotalImgSize; unsigned short R, G, B, max_R, max_G, max_B, min_R, min_G, min_B; unsigned short wIndexR, wIndexG, wIndexB; float fmax_R, fmax_G, fmax_B; unsigned int sum_R = 0, sum_G = 0, sum_B = 0; unsigned int hisgram_R[1024], hisgram_G[1024], hisgram_B[1024]; if (!pDIB) { return; } pbmpdata = (unsigned short *) pDIB; CountPixels = 0; TotalImgSize = ImageWidth * ImageHeight; for (i = 0; i < 1024; i++) { hisgram_R[i] = 0; hisgram_G[i] = 0; hisgram_B[i] = 0; } /*Find min , max, mean */ max_R = max_G = max_B = 0; min_R = min_G = min_B = 1023; tLines = 0; for (j = 0; j < (int) ImageHeight; j++) { tLines = j * ImageWidth * 3; for (i = 0; i < (int) ImageWidth; i++) { R = *(pbmpdata + (tLines + i * 3 + 2)); G = *(pbmpdata + (tLines + i * 3 + 1)); B = *(pbmpdata + (tLines + i * 3)); max_R = _MAX (R, max_R); max_G = _MAX (G, max_G); max_B = _MAX (B, max_B); min_R = _MIN (R, min_R); min_G = _MIN (G, min_G); min_B = _MIN (B, min_B); hisgram_R[R]++; hisgram_G[G]++; hisgram_B[B]++; sum_R += R; sum_G += G; sum_B += B; *(pbmpdata + (tLines + i * 3 + 2)) = R; *(pbmpdata + (tLines + i * 3 + 1)) = G; *(pbmpdata + (tLines + i * 3)) = B; CountPixels++; } } fRSum = 0.0; fGSum = 0.0; fBSum = 0.0; wIndexR = 511; wIndexG = 511; wIndexB = 511; for (i = 0; i < 1024; i++) { fRSum += (float) hisgram_R[i]; fRPercent = (fRSum / CountPixels) * 100; if (fRPercent > 50) { wIndexR = i; break; } } for (i = 0; i < 1024; i++) { fGSum += (float) hisgram_G[i]; fGPercent = (fGSum / CountPixels) * 100; if (fGPercent > 50) { wIndexG = i; break; } } for (i = 0; i < 1024; i++) { fBSum += (float) hisgram_B[i]; fBPercent = (fBSum / CountPixels) * 100; if (fBPercent > 50) { wIndexB = i; break; } } fRSum = 0.0; for (i = wIndexR; i >= 0; i--) { fRSum += (float) hisgram_R[i]; fRPercent = (fRSum / CountPixels) * 100; if (fRPercent >= 48) { min_R = i; break; } } fRSum = 0.0; for (i = wIndexR; i < 1024; i++) { fRSum += (float) hisgram_R[i]; fRPercent = (fRSum / CountPixels) * 100; if (fRPercent >= 47) { max_R = i; break; } } fGSum = 0.0; for (i = wIndexG; i >= 0; i--) { fGSum += (float) hisgram_G[i]; fGPercent = (fGSum / CountPixels) * 100; if (fGPercent >= 48) { min_G = i; break; } } fGSum = 0.0; for (i = wIndexG; i < 1024; i++) { fGSum += (float) hisgram_G[i]; fGPercent = (fGSum / CountPixels) * 100; if (fGPercent >= 47) { max_G = i; break; } } fBSum = 0.0; for (i = wIndexB; i >= 0; i--) { fBSum += (float) hisgram_B[i]; fBPercent = (fBSum / CountPixels) * 100; if (fBPercent >= 46) { min_B = i; break; } } fBSum = 0.0; for (i = wIndexB; i < 1024; i++) { fBSum += (float) hisgram_B[i]; fBPercent = (fBSum / CountPixels) * 100; if (fBPercent >= 47) { max_B = i; break; } } /*Autolevel: */ sum_R = max_R - min_R; sum_G = max_G - min_G; sum_B = max_B - min_B; for (j = 0; j < (int) ImageHeight; j++) { tLines = j * ImageWidth * 3; for (i = 0; i < (int) ImageWidth; i++) { R = *(pbmpdata + (tLines + i * 3 + 2)); G = *(pbmpdata + (tLines + i * 3 + 1)); B = *(pbmpdata + (tLines + i * 3)); /*R*/ if (sum_R == 0) R = max_R; else if (R < min_R) { R = 0; } else if ((R >= min_R) && (R <= 1023)) { fmax_R = ((float) ((R - min_R) * 923) / (float) sum_R) + 100; R = (unsigned short) fmax_R; fmax_R = (fmax_R - R) * 10; if (fmax_R >= 5) R++; } if (R > 1023) R = 1023; /*G*/ if (sum_G == 0) G = max_G; else if (G < min_G) { G = 0; } else if ((G >= min_G) && (G <= 1023)) { fmax_G = ((float) ((G - min_G) * 923) / (float) sum_G) + 100; G = (unsigned short) fmax_G; fmax_G = (fmax_G - G) * 10; if (fmax_G >= 5) G++; } if (G > 1023) G = 1023; /*B*/ if (sum_B == 0) B = max_B; else if (B < min_R) { B = 0; } else if ((B >= min_B) && (R <= 1023)) { fmax_B = ((float) (B - min_B) * 923 / (float) sum_B) + 100; B = (unsigned short) fmax_B; fmax_B = (fmax_B - B) * 10; if (fmax_B >= 5) B++; } if (B > 1023) B = 1023; *(pbmpdata + (tLines + i * 3 + 2)) = R; *(pbmpdata + (tLines + i * 3 + 1)) = G; *(pbmpdata + (tLines + i * 3)) = B; } } return; } #endif #ifdef SANE_UNUSED /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Change the image data and deal with auto level Parameters: lpSource: the data of image scanMode: the scan mode ScanLines: the rows of image BytesPerLine: the bytes of per line Return value: none ***********************************************************************/ static void QBetChange (SANE_Byte *lpSource, SCANMODE scanMode, unsigned short ScanLines, unsigned int BytesPerLine) { unsigned short i, j; unsigned int tLines, TotalImgSize; unsigned short R1, G1, B1, R, G, B, R2, G2, B2, QBET_RGB = 0, PointF, PointB; unsigned short *pwRGB; int k; unsigned int ImageWidth = BytesPerLine / 3; unsigned int ImageHeight = ScanLines; SANE_Byte *pbmpdata = (SANE_Byte *) lpSource; if (scanMode != CM_RGB24ext) { return; } TotalImgSize = ImageWidth * ImageHeight * 3 * 2; if ((pwRGB = (unsigned short *) malloc (TotalImgSize)) == NULL) { return; } for (j = 0; j < ImageHeight; j++) { tLines = j * ImageWidth * 3; for (i = 0; i < ImageWidth; i++) { if (i == 0) { R1 = R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2)); G1 = G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1)); B1 = B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3)); R2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 2)); G2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 1)); B2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3)); } else if (i == (ImageWidth - 1)) { R1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 2)); G1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 1)); B1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3)); R2 = R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2)); G2 = G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1)); B2 = B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3)); } else { R1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 2)); G1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3 + 1)); B1 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i - 1) * 3)); R = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 2)); G = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3 + 1)); B = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + i * 3)); R2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 2)); G2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3 + 1)); B2 = (unsigned short) (SANE_Byte) * (pbmpdata + (tLines + (i + 1) * 3)); } R1 = R1 & 0x0003; G1 = G1 & 0x0003; B1 = B1 & 0x0003; R2 = R2 & 0x0003; G2 = G2 & 0x0003; B2 = B2 & 0x0003; for (k = 0; k < 3; k++) { if (k == 0) { PointF = R1; PointB = R2; } else if (k == 1) { PointF = G1; PointB = G2; } else if (k == 2) { PointF = B1; PointB = B2; } switch (PointF) { case 0: case 1: if (PointB == 0) QBET_RGB = 0xFFFC; else if (PointB == 1) QBET_RGB = 0xFFFC; else if (PointB == 2) QBET_RGB = 0xFFFD; else if (PointB == 3) QBET_RGB = 0xFFFE; break; case 2: if (PointB == 0) QBET_RGB = 0xFFFD; else if (PointB == 1) QBET_RGB = 0xFFFD; else if (PointB == 2) QBET_RGB = 0xFFFF; else if (PointB == 3) QBET_RGB = 0xFFFF; break; case 3: if (PointB == 0) QBET_RGB = 0xFFFE; else if (PointB == 1) QBET_RGB = 0xFFFE; else if (PointB == 2) QBET_RGB = 0xFFFF; else if (PointB == 3) QBET_RGB = 0xFFFF; break; default: break; } if (k == 0) { R = R << 2; R = R + 0x0003; R = R & QBET_RGB; } else if (k == 1) { G = G << 2; G = G + 0x0003; G = G & QBET_RGB; } else if (k == 2) { B = B << 2; B = B + 0x0003; B = B & QBET_RGB; } } *(pwRGB + (tLines + i * 3 + 2)) = R; *(pwRGB + (tLines + i * 3 + 1)) = G; *(pwRGB + (tLines + i * 3)) = B; } } QBETDetectAutoLevel (pwRGB, ImageWidth, ImageHeight); for (j = 0; j < ImageHeight; j++) { tLines = j * ImageWidth * 3; for (i = 0; i < ImageWidth; i++) { R = *(pwRGB + (tLines + i * 3 + 2)); G = *(pwRGB + (tLines + i * 3 + 1)); B = *(pwRGB + (tLines + i * 3)); R = R >> 2; G = G >> 2; B = B >> 2; if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255; *(pbmpdata + (tLines + i * 3 + 2)) = (SANE_Byte) R; *(pbmpdata + (tLines + i * 3 + 1)) = (SANE_Byte) G; *(pbmpdata + (tLines + i * 3)) = (SANE_Byte) B; } } if (pwRGB != NULL) { free (pwRGB); } return; } #endif /****************************** SANE API functions *****************************/ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { DBG_INIT (); DBG (DBG_FUNC, "sane_init: start\n"); DBG (DBG_ERR, "SANE Mustek USB2 backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); num_devices = 1; /* HOLD: only one device in this backend */ if (version_code != NULL) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_INFO, "sane_init: authorize %s null\n", authorize ? "!=" : "=="); DBG (DBG_FUNC, "sane_init: exit\n"); return SANE_STATUS_GOOD; } void sane_exit (void) { DBG (DBG_FUNC, "sane_exit: start\n"); if (devlist != NULL) { free (devlist); devlist = NULL; } devlist = NULL; DBG (DBG_FUNC, "sane_exit: exit\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { SANE_Int dev_num; DBG (DBG_FUNC, "sane_get_devices: start: local_only = %s\n", local_only == SANE_TRUE ? "true" : "false"); if (devlist != NULL) { free (devlist); devlist = NULL; } devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (devlist == NULL) return SANE_STATUS_NO_MEM; dev_num = 0; /* HOLD: This is ugly (only one scanner!) and should go to sane_init */ if (GetDeviceStatus ()) { SANE_Device *sane_device; sane_device = malloc (sizeof (*sane_device)); if (sane_device == NULL) return SANE_STATUS_NO_MEM; sane_device->name = strdup (device_name); sane_device->vendor = strdup ("Mustek"); sane_device->model = strdup ("BearPaw 2448 TA Pro"); sane_device->type = strdup ("flatbed scanner"); devlist[dev_num++] = sane_device; } devlist[dev_num] = 0; *device_list = devlist; DBG (DBG_FUNC, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Mustek_Scanner *s; DBG (DBG_FUNC, "sane_open: start :devicename = %s\n", devicename); if (!MustScanner_Init ()) { return SANE_STATUS_INVAL; } if (!PowerControl (SANE_FALSE, SANE_FALSE)) { return SANE_STATUS_INVAL; } if (!CarriageHome ()) { return SANE_STATUS_INVAL; } s = malloc (sizeof (*s)); if (s == NULL) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->gamma_table = NULL; memcpy (&s->model, &mustek_A2nu2_model, sizeof (Scanner_Model)); s->next = NULL; s->bIsScanning = SANE_FALSE; s->bIsReading = SANE_FALSE; init_options (s); *handle = s; s->read_rows = 0; s->scan_buffer_len = 0; DBG (DBG_FUNC, "sane_open: exit\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Mustek_Scanner *s = handle; DBG (DBG_FUNC, "sane_close: start\n"); PowerControl (SANE_FALSE, SANE_FALSE); CarriageHome (); if (NULL != g_pDeviceFile) { free (g_pDeviceFile); g_pDeviceFile = NULL; } if (s->Scan_data_buf != NULL) free (s->Scan_data_buf); s->Scan_data_buf = NULL; free (handle); DBG (DBG_FUNC, "sane_close: exit\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Mustek_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; DBG (DBG_FUNC, "sane_get_option_descriptor: option = %s (%d)\n", s->opt[option].name, option); return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Mustek_Scanner *s = handle; SANE_Status status; SANE_Word cap; SANE_Int myinfo = 0; DBG (DBG_FUNC, "sane_control_option: start: action = %s, option = %s (%d)\n", (action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_SET_VALUE) ? "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->opt[option].name, option); if (info) *info = 0; if (s->bIsScanning) { DBG (DBG_ERR, "sane_control_option: don't call this function while " "scanning\n"); return SANE_STATUS_DEVICE_BUSY; } if (option >= NUM_OPTIONS || option < 0) { DBG (DBG_ERR, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", option); return SANE_STATUS_INVAL; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (DBG_ERR, "sane_control_option: option %d is inactive\n", option); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_AUTO_WARMUP: case OPT_GAMMA_VALUE: case OPT_THRESHOLD: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *) val = s->val[option].w; break; /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); break; case OPT_SOURCE: strcpy (val, s->val[option].s); break; default: DBG (DBG_ERR, "sane_control_option: can't get unknown option %d\n", option); ; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_ERR, "sane_control_option: option %d is not settable\n", option); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (2, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; RIE (calc_parameters (s)); myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_THRESHOLD: case OPT_AUTO_WARMUP: case OPT_GAMMA_VALUE: s->val[option].w = *(SANE_Word *) val; break; /* side-effect-free word-array options: */ case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { ENABLE (OPT_THRESHOLD); } else { DISABLE (OPT_THRESHOLD); } RIE (calc_parameters (s)); myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_SOURCE: if (strcmp (s->val[option].s, val) != 0) { /* something changed */ if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[option].s, "Reflective") == 0) { PowerControl (SANE_TRUE, SANE_FALSE); s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup ("Color24"); x_range.max = s->model.x_size; y_range.max = s->model.y_size; } else if (0 == strcmp (s->val[option].s, "Negative")) { PowerControl (SANE_FALSE, SANE_TRUE); s->opt[OPT_MODE].size = max_string_size (negative_mode_list); s->opt[OPT_MODE].constraint.string_list = negative_mode_list; s->val[OPT_MODE].s = strdup ("Color24"); x_range.max = s->model.x_size_ta; y_range.max = s->model.y_size_ta; } else if (0 == strcmp (s->val[option].s, "Positive")) { PowerControl (SANE_FALSE, SANE_TRUE); s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup ("Color24"); x_range.max = s->model.x_size_ta; y_range.max = s->model.y_size_ta; } } myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; default: DBG (DBG_ERR, "sane_control_option: can't set unknown option %d\n", option); } } else { DBG (DBG_ERR, "sane_control_option: unknown action %d for option %d\n", action, option); return SANE_STATUS_INVAL; } if (info) *info = myinfo; DBG (DBG_FUNC, "sane_control_option: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Mustek_Scanner *s = handle; DBG (DBG_FUNC, "sane_get_parameters: start\n"); DBG (DBG_INFO, "sane_get_parameters :params.format = %d\n", s->params.format); DBG (DBG_INFO, "sane_get_parameters :params.depth = %d\n", s->params.depth); DBG (DBG_INFO, "sane_get_parameters :params.pixels_per_line = %d\n", s->params.pixels_per_line); DBG (DBG_INFO, "sane_get_parameters :params.bytes_per_line = %d\n", s->params.bytes_per_line); DBG (DBG_INFO, "sane_get_parameters :params.lines = %d\n", s->params.lines); if (params != NULL) *params = s->params; DBG (DBG_FUNC, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { int i; Mustek_Scanner *s = handle; DBG (DBG_FUNC, "sane_start: start\n"); s->scan_buffer_len = 0; calc_parameters (s); if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w) { DBG (DBG_CRIT, "sane_start: top left x >= bottom right x --- exiting\n"); return SANE_STATUS_INVAL; } if (s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w) { DBG (DBG_CRIT, "sane_start: top left y >= bottom right y --- exiting\n"); return SANE_STATUS_INVAL; } s->setpara.pGammaTable = NULL; DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.x1=%d\n", s->setpara.fmArea.x1); DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.x2=%d\n", s->setpara.fmArea.x2); DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.y1=%d\n", s->setpara.fmArea.y1); DBG (DBG_INFO, "Sane_start:setpara ,setpara.fmArea.y2=%d\n", s->setpara.fmArea.y2); DBG (DBG_INFO, "Sane_start:setpara ,setpara.pfPixelFlavor=%d\n", s->setpara.pfPixelFlavor); DBG (DBG_INFO, "Sane_start:setpara ,setpara.wLinearThreshold=%d\n", s->setpara.wLinearThreshold); DBG (DBG_INFO, "Sane_start:setpara ,setpara.wTargetDPI=%d\n", s->setpara.wTargetDPI); DBG (DBG_INFO, "Sane_start:setpara ,setpara.smScanMode=%d\n", s->setpara.smScanMode); DBG (DBG_INFO, "Sane_start:setpara ,setpara.ssScanSource =%d\n", s->setpara.ssScanSource); DBG (DBG_INFO, "Sane_start:setpara ,setpara.pGammaTable =%p\n", (void *) s->setpara.pGammaTable); SetParameters (&s->setpara); GetParameters (&s->getpara); switch (s->params.format) { case SANE_FRAME_RGB: if (s->params.depth == 8) s->params.pixels_per_line = s->getpara.dwLineByteWidth / 3; if (s->params.depth == 16) s->params.pixels_per_line = s->getpara.dwLineByteWidth / 6; break; case SANE_FRAME_GRAY: if (s->params.depth == 1) s->params.pixels_per_line = s->getpara.dwLineByteWidth * 8; if (s->params.depth == 8) s->params.pixels_per_line = s->getpara.dwLineByteWidth; if (s->params.depth == 16) s->params.pixels_per_line = s->getpara.dwLineByteWidth / 2; break; default: DBG (DBG_INFO, "sane_start: sane_params.format = %d\n", s->params.format); } s->params.bytes_per_line = s->getpara.dwLineByteWidth; s->params.lines = s->getpara.dwLength; s->params.last_frame = TRUE; s->read_rows = s->getpara.dwLength; DBG (DBG_INFO, "sane_start : read_rows = %d\n", s->read_rows); /*warmming up */ if (s->val[OPT_AUTO_WARMUP].w) { for (i = 30; i > 0; i--) { sleep (1); DBG (DBG_ERR, "warming up: %d\n", i); } } DBG (DBG_INFO, "SCANNING ... \n"); s->bIsScanning = SANE_TRUE; if (s->Scan_data_buf != NULL) free (s->Scan_data_buf); s->Scan_data_buf = NULL; s->Scan_data_buf = malloc (SCAN_BUFFER_SIZE * sizeof (SANE_Byte)); if (s->Scan_data_buf == NULL) return SANE_STATUS_NO_MEM; StartScan (); DBG (DBG_FUNC, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Mustek_Scanner *s = handle; static SANE_Byte *tempbuf; SANE_Int lines_to_read, lines_read; IMAGEROWS image_row; int maxbuffersize = max_len; DBG (DBG_FUNC, "sane_read: start: max_len=%d\n", max_len); if (s == NULL) { DBG (DBG_ERR, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } if (buf == NULL) { DBG (DBG_ERR, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (len == NULL) { DBG (DBG_ERR, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } *len = 0; if (!s->bIsScanning) { DBG (DBG_WARN, "sane_read: scan was cancelled, is over or has not been " "initiated yet\n"); return SANE_STATUS_CANCELLED; } DBG (DBG_DBG, "sane_read: before read data read_row=%d\n", s->read_rows); if (s->scan_buffer_len == 0) { if (s->read_rows > 0) { lines_to_read = SCAN_BUFFER_SIZE / s->getpara.dwLineByteWidth; if (lines_to_read > s->read_rows) lines_to_read = s->read_rows; tempbuf = (SANE_Byte *) malloc (sizeof (SANE_Byte) * lines_to_read * s->getpara.dwLineByteWidth + 3 * 1024 + 1); memset (tempbuf, 0, sizeof (SANE_Byte) * lines_to_read * s->getpara.dwLineByteWidth + 3 * 1024 + 1); DBG (DBG_INFO, "sane_read: buffer size is %ld\n", (long int) sizeof (SANE_Byte) * lines_to_read * s->getpara.dwLineByteWidth + 3 * 1024 + 1); image_row.roRgbOrder = mustek_A2nu2_model.line_mode_color_order; image_row.wWantedLineNum = lines_to_read; image_row.pBuffer = (SANE_Byte *) tempbuf; s->bIsReading = SANE_TRUE; if (!ReadScannedData (&image_row)) { DBG (DBG_ERR, "sane_read: ReadScannedData error\n"); s->bIsReading = SANE_FALSE; return SANE_STATUS_INVAL; } DBG (DBG_DBG, "sane_read: Finish ReadScanedData\n"); s->bIsReading = SANE_FALSE; memset (s->Scan_data_buf, 0, SCAN_BUFFER_SIZE); s->scan_buffer_len = image_row.wXferedLineNum * s->getpara.dwLineByteWidth; DBG (DBG_INFO, "sane_read : s->scan_buffer_len = %ld\n", (long int) s->scan_buffer_len); memcpy (s->Scan_data_buf, tempbuf, s->scan_buffer_len); DBG (DBG_DBG, "sane_read :after memcpy\n"); free (tempbuf); s->Scan_data_buf_start = s->Scan_data_buf; s->read_rows -= image_row.wXferedLineNum; } else { DBG (DBG_FUNC, "sane_read: scan finished -- exit\n"); sane_cancel (handle); return SANE_STATUS_EOF; } } if (s->scan_buffer_len == 0) { DBG (DBG_FUNC, "sane_read: scan finished -- exit\n"); sane_cancel (handle); return SANE_STATUS_EOF; } lines_read = (maxbuffersize < (SANE_Int) s->scan_buffer_len) ? maxbuffersize : (SANE_Int) s->scan_buffer_len; DBG (DBG_DBG, "sane_read: after %d\n", lines_read); *len = (SANE_Int) lines_read; DBG (DBG_INFO, "sane_read : get lines_read = %d\n", lines_read); DBG (DBG_INFO, "sane_read : get *len = %d\n", *len); memcpy (buf, s->Scan_data_buf_start, lines_read); s->scan_buffer_len -= lines_read; s->Scan_data_buf_start += lines_read; DBG (DBG_FUNC, "sane_read: exit\n"); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Mustek_Scanner *s = handle; int i; DBG (DBG_FUNC, "sane_cancel: start\n"); if (s->bIsScanning) { s->bIsScanning = SANE_FALSE; if (s->read_rows > 0) { DBG (DBG_INFO, "sane_cancel: warning: is scanning\n"); } else { DBG (DBG_INFO, "sane_cancel: Scan finished\n"); } StopScan (); CarriageHome (); for (i = 0; i < 20; i++) { if (s->bIsReading == SANE_FALSE) { if (s->gamma_table != NULL) { free (s->gamma_table); s->gamma_table = NULL; break; } } else sleep (1); } if (s->Scan_data_buf != NULL) { free (s->Scan_data_buf); s->Scan_data_buf = NULL; s->Scan_data_buf_start = NULL; } s->read_rows = 0; s->scan_buffer_len = 0; memset (&s->setpara, 0, sizeof (s->setpara)); memset (&s->getpara, 0, sizeof (s->getpara)); } else { DBG (DBG_INFO, "sane_cancel: do nothing\n"); } DBG (DBG_FUNC, "sane_cancel: exit\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Mustek_Scanner *s = handle; DBG (DBG_FUNC, "sane_set_io_mode: handle = %p, non_blocking = %s\n", handle, non_blocking == SANE_TRUE ? "true" : "false"); if (!s->bIsScanning) { DBG (DBG_WARN, "sane_set_io_mode: not scanning\n"); return SANE_STATUS_INVAL; } if (non_blocking) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Mustek_Scanner *s = handle; DBG (DBG_FUNC, "sane_get_select_fd: handle = %p, fd = %p\n", handle, (void *) fd); if (!s->bIsScanning) { DBG (DBG_WARN, "%s", "sane_get_select_fd: not scanning\n"); return SANE_STATUS_INVAL; } return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/kvs20xx_cmd.c0000664000175000017500000001625512775312261015144 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. Copyright (C) 2010, m. allan noah */ /* Panasonic KV-S20xx USB-SCSI scanners. */ #include "../include/sane/config.h" #include /*#include */ #define DEBUG_DECLARE_ONLY #define BACKEND_NAME kvs20xx #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "kvs20xx.h" #include "kvs20xx_cmd.h" static SANE_Status usb_send_command (struct scanner *s, struct cmd *c, struct response *r, void *buf) { SANE_Status st; struct bulk_header *h = (struct bulk_header *) buf; u8 resp[sizeof (*h) + STATUS_SIZE]; size_t sz = sizeof (*h) + MAX_CMD_SIZE; memset (h, 0, sz); h->length = cpu2be32 (sz); h->type = cpu2be16 (COMMAND_BLOCK); h->code = cpu2be16 (COMMAND_CODE); memcpy (h + 1, c->cmd, c->cmd_size); st = sanei_usb_write_bulk (s->file, (const SANE_Byte *) h, &sz); if (st) return st; if (sz != sizeof (*h) + MAX_CMD_SIZE) return SANE_STATUS_IO_ERROR; if (c->dir == CMD_IN) { sz = sizeof (*h) + c->data_size; st = sanei_usb_read_bulk (s->file, (SANE_Byte *) h, &sz); c->data = h + 1; c->data_size = sz - sizeof (*h); if (st || sz < sizeof (*h)) { st = sanei_usb_release_interface (s->file, 0); if (st) return st; st = sanei_usb_claim_interface (s->file, 0); if (st) return st; r->status = CHECK_CONDITION; return SANE_STATUS_GOOD; } } else if (c->dir == CMD_OUT) { sz = sizeof (*h) + c->data_size; memset (h, 0, sizeof (*h)); h->length = cpu2be32 (sizeof (*h) + c->data_size); h->type = cpu2be16 (DATA_BLOCK); h->code = cpu2be16 (DATA_CODE); memcpy (h + 1, c->data, c->data_size); st = sanei_usb_write_bulk (s->file, (const SANE_Byte *) h, &sz); if (st) return st; } sz = sizeof (resp); st = sanei_usb_read_bulk (s->file, resp, &sz); if (st || sz != sizeof (resp)) return SANE_STATUS_IO_ERROR; r->status = be2cpu32 (*((u32 *) (resp + sizeof (*h)))); return st; } SANE_Status kvs20xx_sense_handler (int __sane_unused__ fd, u_char * sense_buffer, void __sane_unused__ * arg) { unsigned i; SANE_Status st = SANE_STATUS_GOOD; for (i = 0; i < sizeof (s_errors) / sizeof (s_errors[0]); i++) if ((sense_buffer[2] & 0xf) == s_errors[i].sense && sense_buffer[12] == s_errors[i].asc && sense_buffer[13] == s_errors[i].ascq) { st = s_errors[i].st; break; } if (st == SANE_STATUS_GOOD && sense_buffer[2] & END_OF_MEDIUM) st = SANE_STATUS_EOF; if (i == sizeof (s_errors) / sizeof (s_errors[0])) st = SANE_STATUS_IO_ERROR; DBG (DBG_ERR, "send_command: CHECK_CONDITION: sence:0x%x ASC:0x%x ASCQ:0x%x\n", sense_buffer[2], sense_buffer[12], sense_buffer[13]); return st; } static SANE_Status send_command (struct scanner * s, struct cmd * c) { SANE_Status st = SANE_STATUS_GOOD; if (s->bus == USB) { struct response r; memset (&r, 0, sizeof (r)); st = usb_send_command (s, c, &r, s->buffer); if (st) return st; if (r.status) { u8 b[sizeof (struct bulk_header) + RESPONSE_SIZE]; struct cmd c2 = { {0}, 6, 0, RESPONSE_SIZE, CMD_IN }; c2.cmd[0] = REQUEST_SENSE; c2.cmd[4] = RESPONSE_SIZE; st = usb_send_command (s, &c2, &r, b); if (st) return st; st = kvs20xx_sense_handler (0, b + sizeof (struct bulk_header), NULL); } } else { if (c->dir == CMD_OUT) { memcpy (s->buffer, c->cmd, c->cmd_size); memcpy (s->buffer + c->cmd_size, c->data, c->data_size); st = sanei_scsi_cmd (s->file, s->buffer, c->cmd_size + c->data_size, NULL, NULL); } else if (c->dir == CMD_IN) { c->data = s->buffer; st = sanei_scsi_cmd (s->file, c->cmd, c->cmd_size, c->data, (size_t *) & c->data_size); } else { st = sanei_scsi_cmd (s->file, c->cmd, c->cmd_size, NULL, NULL); } } return st; } SANE_Status kvs20xx_test_unit_ready (struct scanner * s) { struct cmd c = { {0}, 6, 0, 0, CMD_NONE }; c.cmd[0] = TEST_UNIT_READY; if (send_command (s, &c)) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_GOOD; } SANE_Status kvs20xx_set_timeout (struct scanner * s, int timeout) { u16 t = cpu2be16 ((u16) timeout); struct cmd c = { {0}, 10, 0, 0, CMD_OUT }; c.cmd[0] = SET_TIMEOUT; c.cmd[2] = 0x8d; copy16 (c.cmd + 7, cpu2be16 (sizeof (t))); c.data = &t; c.data_size = sizeof (t); if (s->bus == USB) sanei_usb_set_timeout (timeout * 1000); return send_command (s, &c); } SANE_Status kvs20xx_set_window (struct scanner * s, int wnd_id) { struct window wnd; struct cmd c = { {0}, 10, 0, 0, CMD_OUT }; c.cmd[0] = SET_WINDOW; copy16 (c.cmd + 7, cpu2be16 (sizeof (wnd))); c.data = &wnd; c.data_size = sizeof (wnd); kvs20xx_init_window (s, &wnd, wnd_id); return send_command (s, &c); } SANE_Status kvs20xx_reset_window (struct scanner * s) { struct cmd c = { {0}, 10, 0, 0, CMD_NONE }; c.cmd[0] = SET_WINDOW; return send_command (s, &c); } SANE_Status kvs20xx_scan (struct scanner * s) { struct cmd c = { {0}, 6, 0, 0, CMD_NONE }; c.cmd[0] = SCAN; return send_command (s, &c); } SANE_Status kvs20xx_document_exist (struct scanner * s) { SANE_Status status; struct cmd c = { {0}, 10, 0, 6, CMD_IN, }; u8 *d; c.cmd[0] = READ_10; c.cmd[2] = 0x81; set24 (c.cmd + 6, c.data_size); status = send_command (s, &c); if (status) return status; d = c.data; if (d[0] & 0x20) return SANE_STATUS_GOOD; return SANE_STATUS_NO_DOCS; } SANE_Status kvs20xx_read_picture_element (struct scanner * s, unsigned side, SANE_Parameters * p) { SANE_Status status; struct cmd c = { {0}, 10, 0, 16, CMD_IN }; u32 *data; c.cmd[0] = READ_10; c.cmd[2] = 0x80; c.cmd[5] = side; set24 (c.cmd + 6, c.data_size); status = send_command (s, &c); if (status) return status; data = (u32 *) c.data; p->pixels_per_line = be2cpu32 (data[0]); p->lines = be2cpu32 (data[1]); return SANE_STATUS_GOOD; } SANE_Status kvs20xx_read_image_data (struct scanner * s, unsigned page, unsigned side, void *buf, unsigned max_size, unsigned *size) { SANE_Status status; struct cmd c = { {0}, 10, 0, 0, CMD_IN }; c.cmd[0] = READ_10; c.cmd[4] = page; c.cmd[5] = side; c.data_size = max_size < MAX_READ_DATA_SIZE ? max_size : MAX_READ_DATA_SIZE; set24 (c.cmd + 6, c.data_size); status = send_command (s, &c); if (status && status != SANE_STATUS_EOF) return status; *size = c.data_size; DBG (DBG_INFO, "kvs20xx_read_image_data: read %d, status %d\n", *size, status); memcpy (buf, c.data, *size); return status; } SANE_Status get_adjust_data (struct scanner * s, unsigned *dummy_length) { SANE_Status status; struct cmd c = { {0}, 10, 0, 40, CMD_IN }; u16 *data; c.cmd[0] = GET_ADJUST_DATA; c.cmd[2] = 0x9b; c.cmd[8] = 40; status = send_command (s, &c); if (status) return status; data = (u16 *) c.data; *dummy_length = be2cpu16 (data[0]); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/st400.h0000664000175000017500000000310412112021330013613 00000000000000#ifndef st400_h #define st400_h #define ST400_CONFIG_FILE "st400.conf" #define ST400_DEFAULT_DEVICE "/dev/scanner" /* maximum scanning area in inch (guessed) */ #define ST400_MAX_X 8.5 #define ST400_MAX_Y 12.0 enum ST400_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_RESOLUTION, OPT_DEPTH, OPT_THRESHOLD, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, NUM_OPTIONS /* must be last */ }; typedef struct { size_t inq_voffset; /* offset in INQUIRY result */ char *inq_vendor; size_t inq_moffset; /* offset in INQUIRY result */ char *inq_model; size_t bits; /* 6 or 8 */ unsigned long bufsize; /* internal buffer of scanner */ unsigned long maxread; /* max bytes to read in a cmd (0 = no limit) */ SANE_Int *dpi_list; /* NULL for default list */ char *sane_vendor; char *sane_model; char *sane_type; } ST400_Model; typedef struct ST400_Device { struct ST400_Device *next; SANE_Device sane; SANE_Parameters params; SANE_Option_Descriptor opt[NUM_OPTIONS]; SANE_Word val[NUM_OPTIONS]; struct { unsigned open :1; unsigned scanning :1; unsigned eof :1; } status; /* pixel values of entire scan window - for convenience */ unsigned short x, y, w, h; int fd; /* SCSI filedescriptor */ /* backend buffer */ SANE_Byte *buffer; size_t bufsize; SANE_Byte *bufp; /* next byte to transfer */ size_t bytes_in_buffer; ST400_Model *model; /* scanner buffer */ unsigned short wy, wh; /* current subwindow */ unsigned long bytes_in_scanner; unsigned short lines_to_read; } ST400_Device; #endif /* st400_h */ /* The End */ sane-backends-1.0.27/backend/genesys_gl646.h0000664000175000017500000007220412775312261015374 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003-2004 Henning Meier-Geinitz Copyright (C) 2004-2005 Gerhard Jaeger Copyright (C) 2004-2013 Stéphane Voltz Copyright (C) 2005-2009 Pierre Willenbrock This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "genesys.h" /* * Genesys Logic GL646 based scanners */ /* Individual bits */ #define REG01_CISSET 0x80 #define REG01_DOGENB 0x40 #define REG01_DVDSET 0x20 #define REG01_FASTMOD 0x10 #define REG01_COMPENB 0x08 #define REG01_DRAMSEL 0x04 #define REG01_SHDAREA 0x02 #define REG01_SCAN 0x01 #define REG02_NOTHOME 0x80 #define REG02_ACDCDIS 0x40 #define REG02_AGOHOME 0x20 #define REG02_MTRPWR 0x10 #define REG02_FASTFED 0x08 #define REG02_MTRREV 0x04 #define REG02_STEPSEL 0x03 #define REG02_FULLSTEP 0x00 #define REG02_HALFSTEP 0x01 #define REG02_QUATERSTEP 0x02 #define REG03_TG3 0x80 #define REG03_AVEENB 0x40 #define REG03_XPASEL 0x20 #define REG03_LAMPPWR 0x10 #define REG03_LAMPDOG 0x08 #define REG03_LAMPTIM 0x07 #define REG04_LINEART 0x80 #define REG04_BITSET 0x40 #define REG04_ADTYPE 0x30 #define REG04_FILTER 0x0c #define REG04_FESET 0x03 #define REG05_DPIHW 0xc0 #define REG05_DPIHW_600 0x00 #define REG05_DPIHW_1200 0x40 #define REG05_DPIHW_2400 0x80 #define REG05_DPIHW_4800 0xc0 #define REG05_GMMTYPE 0x30 #define REG05_GMM14BIT 0x10 #define REG05_GMMENB 0x08 #define REG05_LEDADD 0x04 #define REG05_BASESEL 0x03 #define REG06_PWRBIT 0x10 #define REG06_GAIN4 0x08 #define REG06_OPTEST 0x07 #define REG07_DMASEL 0x02 #define REG07_DMARDWR 0x01 #define REG16_CTRLHI 0x80 #define REG16_SELINV 0x40 #define REG16_TGINV 0x20 #define REG16_CK1INV 0x10 #define REG16_CK2INV 0x08 #define REG16_CTRLINV 0x04 #define REG16_CKDIS 0x02 #define REG16_CTRLDIS 0x01 #define REG17_TGMODE 0xc0 #define REG17_TGMODE_NO_DUMMY 0x00 #define REG17_TGMODE_REF 0x40 #define REG17_TGMODE_XPA 0x80 #define REG17_TGW 0x3f #define REG18_CNSET 0x80 #define REG18_DCKSEL 0x60 #define REG18_CKTOGGLE 0x10 #define REG18_CKDELAY 0x0c #define REG18_CKSEL 0x03 #define REG1D_CKMANUAL 0x80 #define REG1E_WDTIME 0xf0 #define REG1E_LINESEL 0x0f #define REG41_PWRBIT 0x80 #define REG41_BUFEMPTY 0x40 #define REG41_FEEDFSH 0x20 #define REG41_SCANFSH 0x10 #define REG41_HOMESNR 0x08 #define REG41_LAMPSTS 0x04 #define REG41_FEBUSY 0x02 #define REG41_MOTMFLG 0x01 #define REG66_LOW_CURRENT 0x10 #define REG6A_FSTPSEL 0xc0 #define REG6A_FASTPWM 0x3f #define REG6C_TGTIME 0xc0 #define REG6C_Z1MOD 0x38 #define REG6C_Z2MOD 0x07 #define REG_SCANFED 0x1f #define REG_BUFSEL 0x20 #define REG_LINCNT 0x25 #define REG_DPISET 0x2c #define REG_STRPIXEL 0x30 #define REG_ENDPIXEL 0x32 #define REG_DUMMY 0x34 #define REG_MAXWD 0x35 #define REG_LPERIOD 0x38 #define REG_FEEDL 0x3d #define REG_VALIDWORD 0x42 #define REG_FEDCNT 0x48 #define REG_SCANCNT 0x4b #define REG_Z1MOD 0x60 #define REG_Z2MOD 0x62 #include "genesys.h" enum { reg_0x01 = 0, reg_0x02, reg_0x03, reg_0x04, reg_0x05, reg_0x06, reg_0x07, reg_0x08, reg_0x09, reg_0x0a, reg_0x0b, reg_0x10, reg_0x11, reg_0x12, reg_0x13, reg_0x14, reg_0x15, reg_0x16, reg_0x17, reg_0x18, reg_0x19, reg_0x1a, reg_0x1b, reg_0x1c, reg_0x1d, reg_0x1e, reg_0x1f, reg_0x20, reg_0x21, reg_0x22, reg_0x23, reg_0x24, reg_0x25, reg_0x26, reg_0x27, reg_0x28, reg_0x29, reg_0x2c, reg_0x2d, reg_0x2e, reg_0x2f, reg_0x30, reg_0x31, reg_0x32, reg_0x33, reg_0x34, reg_0x35, reg_0x36, reg_0x37, reg_0x38, reg_0x39, reg_0x3d, reg_0x3e, reg_0x3f, reg_0x52, reg_0x53, reg_0x54, reg_0x55, reg_0x56, reg_0x57, reg_0x58, reg_0x59, reg_0x5a, reg_0x5b, reg_0x5c, reg_0x5d, reg_0x5e, reg_0x60, reg_0x61, reg_0x62, reg_0x63, reg_0x64, reg_0x65, reg_0x66, reg_0x67, reg_0x68, reg_0x69, reg_0x6a, reg_0x6b, reg_0x6c, reg_0x6d, GENESYS_GL646_MAX_REGS }; #ifndef UNIT_TESTING static #endif SANE_Status gl646_set_fe (Genesys_Device * dev, uint8_t set, int dpi); #ifndef UNIT_TESTING static #endif SANE_Status gl646_public_set_fe (Genesys_Device * dev, uint8_t set); GENESYS_STATIC SANE_Status gl646_save_power (Genesys_Device * dev, SANE_Bool enable); GENESYS_STATIC SANE_Status gl646_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home); GENESYS_STATIC SANE_Status gl646_move_to_ta (Genesys_Device * dev); /** * sets up the scanner for a scan, registers, gamma tables, shading tables * and slope tables, based on the parameter struct. * @param dev device to set up * @param regs registers to set up * @param settings settings of the scan * @param split true if move before scan has to be done * @param xcorrection true if scanner's X geometry must be taken into account to * compute X, ie add left margins * @param ycorrection true if scanner's Y geometry must be taken into account to * compute Y, ie add top margins */ GENESYS_STATIC SANE_Status setup_for_scan (Genesys_Device *device, Genesys_Register_Set *regs, Genesys_Settings settings, SANE_Bool split, SANE_Bool xcorrection, SANE_Bool ycorrection); /** * sets up the registers for a scan corresponding to the settings. * Builds motor slope tables. Computes buffer sizes and data amount to * transfer. It also sets up analog frontend. * */ static SANE_Status gl646_setup_registers (Genesys_Device * dev, Genesys_Register_Set * regs, Genesys_Settings scan_settings, uint16_t * slope_table1, uint16_t * slope_table2, SANE_Int resolution, uint32_t move, uint32_t linecnt, uint16_t startx, uint16_t endx, SANE_Bool color, SANE_Int depth); /** * Does a simple move of the given distance by doing a scan at lowest resolution * shading correction. Memory for data is allocated in this function * and must be freed by caller. * @param dev device of the scanner * @param distance distance to move in MM */ #ifndef UNIT_TESTING static #endif SANE_Status simple_move (Genesys_Device * dev, SANE_Int distance); /** * Does a simple scan of the area given by the settings. Scanned data * it put in an allocated area which must be freed by the caller. * and slope tables, based on the parameter struct. There is no shading * correction while gamma correction is active. * @param dev device to set up * @param settings settings of the scan * @param move flag to enable scanhead to move * @param forward flag to tell movement direction * @param shading flag to tell if shading correction should be done * @param data pointer that will point to the scanned data */ #ifndef UNIT_TESTING static #endif SANE_Status simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move, SANE_Bool forward, SANE_Bool shading, unsigned char **data); /** * Send the stop scan command * */ static SANE_Status end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop, SANE_Bool eject); /** * writes control data to an area behind the last motor table. */ static SANE_Status write_control (Genesys_Device * dev, int resolution); /** * initialize scanner's registers at SANE init time */ static void gl646_init_regs (Genesys_Device * dev); #ifndef UNIT_TESTING static #endif SANE_Status gl646_load_document (Genesys_Device * dev); static SANE_Status gl646_detect_document_end (Genesys_Device * dev); #define FULL_STEP 0 #define HALF_STEP 1 #define QUATER_STEP 2 #define CALIBRATION_LINES 10 /** * master motor settings table entry */ typedef struct { /* key */ SANE_Int motor; SANE_Int dpi; SANE_Bool color; /* settings */ SANE_Int ydpi; /* real motor dpi, may be different from the resolution */ SANE_Int steptype; /* 0=full, 1=half, 2=quarter */ SANE_Bool fastmod; /* fast scanning 0/1 */ SANE_Bool fastfed; /* fast fed slope tables */ SANE_Int mtrpwm; SANE_Int steps1; /* table 1 informations */ SANE_Int vstart1; SANE_Int vend1; SANE_Int steps2; /* table 2 informations */ SANE_Int vstart2; SANE_Int vend2; float g1; float g2; SANE_Int fwdbwd; /* forward/backward steps */ } Motor_Master; /** * master sensor settings table entry */ typedef struct { /* key */ SANE_Int sensor; /**< sensor identifier */ SANE_Int dpi; /**< required dpi */ SANE_Bool color; /**< SANE_TRUE if color scan */ /* settings */ SANE_Int xdpi; /**< real sensor dpi, may be different from the required resolution */ SANE_Int exposure; /**< exposure time */ SANE_Int dpiset; /**< set sensor dpi */ SANE_Int cksel; /**< dpiset 'divisor', part of reg 18h */ SANE_Int dummy; /**< dummy exposure time */ /* uint8_t regs_0x10_0x15[6];*/ uint8_t *regs_0x10_0x15; /**< per color exposure time for CIS scanners */ SANE_Bool half_ccd; /**> true if manual CCD/2 clock programming or real dpi is half dpiset */ uint8_t r18; /**> content of register 18h */ uint8_t r1d; /**> content of register 1dh */ } Sensor_Master; /** * settings for a given resolution and DPISET * TODO clean up this when all scanners will have been added */ typedef struct { /* key */ SANE_Int sensor; SANE_Int cksel; /* values */ uint8_t regs_0x08_0x0b[4]; /**< settings for normal CCD clock */ uint8_t manual_0x08_0x0b[4]; /**< settings for CCD/2 clock */ uint8_t regs_0x16_0x1d[8]; uint8_t regs_0x52_0x5e[13]; uint8_t manual_0x52_0x58[7]; } Sensor_Settings; static uint8_t xp200_color[6]={0x16, 0x44, 0x0c, 0x80, 0x09, 0x2e}; static uint8_t xp200_gray[6]={0x05, 0x0a, 0x0f, 0xa0, 0x10, 0x10}; /** * master sensor settings, for a given sensor and dpi, * it gives exposure and CCD time */ /* *INDENT-OFF* */ static Sensor_Master sensor_master[] = { /* HP3670 master settings */ {CCD_HP3670, 75, SANE_TRUE , 75, 4879, 300, 4, 42, NULL, SANE_FALSE, 0x33, 0x43}, {CCD_HP3670, 100, SANE_TRUE , 100, 4487, 400, 4, 42, NULL, SANE_FALSE, 0x33, 0x43}, {CCD_HP3670, 150, SANE_TRUE , 150, 4879, 600, 4, 42, NULL, SANE_FALSE, 0x33, 0x43}, {CCD_HP3670, 300, SANE_TRUE , 300, 4503, 1200, 4, 42, NULL, SANE_FALSE, 0x33, 0x43}, {CCD_HP3670, 600, SANE_TRUE , 600, 10251, 1200, 2, 42, NULL, SANE_FALSE, 0x31, 0x43}, {CCD_HP3670,1200, SANE_TRUE , 1200, 12750, 1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x43}, {CCD_HP3670,2400, SANE_TRUE , 1200, 12750, 1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x43}, {CCD_HP3670, 75, SANE_FALSE, 75, 4879, 300, 4, 42, NULL, SANE_FALSE, 0x33, 0x43}, {CCD_HP3670, 100, SANE_FALSE, 100, 4487, 400, 4, 42, NULL, SANE_FALSE, 0x33, 0x43}, {CCD_HP3670, 150, SANE_FALSE, 150, 4879, 600, 4, 42, NULL, SANE_FALSE, 0x33, 0x43}, {CCD_HP3670, 300, SANE_FALSE, 300, 4503, 1200, 4, 42, NULL, SANE_FALSE, 0x33, 0x43}, {CCD_HP3670, 600, SANE_FALSE, 600, 10251, 1200, 2, 42, NULL, SANE_FALSE, 0x31, 0x43}, {CCD_HP3670,1200, SANE_FALSE, 1200, 12750, 1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x43}, {CCD_HP3670,2400, SANE_FALSE, 1200, 12750, 1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x43}, /* HP 2400 master settings */ {CCD_HP2400, 50, SANE_TRUE , 50, 7211, 200, 4, 42, NULL, SANE_FALSE, 0x3f, 0x02}, {CCD_HP2400, 100, SANE_TRUE , 100, 7211, 400, 4, 42, NULL, SANE_FALSE, 0x3f, 0x02}, {CCD_HP2400, 150, SANE_TRUE , 150, 7211, 600, 4, 42, NULL, SANE_FALSE, 0x3f, 0x02}, {CCD_HP2400, 300, SANE_TRUE , 300, 8751, 1200, 4, 42, NULL, SANE_FALSE, 0x3f, 0x02}, {CCD_HP2400, 600, SANE_TRUE , 600, 18760, 1200, 2, 42, NULL, SANE_FALSE, 0x31, 0x02}, {CCD_HP2400,1200, SANE_TRUE , 1200, 21749, 1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x42}, {CCD_HP2400, 50, SANE_FALSE, 50, 7211, 200, 4, 42, NULL, SANE_FALSE, 0x3f, 0x02}, {CCD_HP2400, 100, SANE_FALSE, 100, 7211, 400, 4, 42, NULL, SANE_FALSE, 0x3f, 0x02}, {CCD_HP2400, 150, SANE_FALSE, 150, 7211, 600, 4, 42, NULL, SANE_FALSE, 0x3f, 0x02}, {CCD_HP2400, 300, SANE_FALSE, 300, 8751, 1200, 4, 42, NULL, SANE_FALSE, 0x3f, 0x02}, {CCD_HP2400, 600, SANE_FALSE, 600, 18760, 1200, 2, 42, NULL, SANE_FALSE, 0x31, 0x02}, {CCD_HP2400,1200, SANE_FALSE, 1200, 21749, 1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x42}, /* XP 200 master settings */ {CIS_XP200 , 75, SANE_TRUE , 75, 5700, 75, 1, 42, xp200_color, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 100, SANE_TRUE , 100, 5700, 100, 1, 42, xp200_color, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 200, SANE_TRUE , 200, 5700, 200, 1, 42, xp200_color, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 300, SANE_TRUE , 300, 9000, 300, 1, 42, xp200_color, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 600, SANE_TRUE , 600, 16000, 600, 1, 42, xp200_color, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 75, SANE_FALSE, 75, 16000, 75, 1, 42, xp200_gray, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 100, SANE_FALSE, 100, 7800, 100, 1, 42, xp200_gray, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 200, SANE_FALSE, 200, 11000, 200, 1, 42, xp200_gray, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 300, SANE_FALSE, 300, 13000, 300, 1, 42, xp200_gray, SANE_FALSE, 0x00, 0x11}, {CIS_XP200 , 600, SANE_FALSE, 600, 24000, 600, 1, 42, xp200_gray, SANE_FALSE, 0x00, 0x11}, /* HP 2300 master settings */ {CCD_HP2300, 75, SANE_TRUE , 75, 4480, 150, 1, 42, NULL, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 150, SANE_TRUE , 150, 4350, 300, 1, 42, NULL, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 300, SANE_TRUE, 300, 4350, 600, 1, 42, NULL, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 600, SANE_TRUE , 600, 8700, 600, 1, 42, NULL, SANE_FALSE, 0x20, 0x05}, {CCD_HP2300,1200, SANE_TRUE , 600, 8700, 600, 1, 42, NULL, SANE_FALSE, 0x20, 0x05}, {CCD_HP2300, 75, SANE_FALSE, 75, 4480, 150, 1, 42, NULL, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 150, SANE_FALSE, 150, 4350, 300, 1, 42, NULL, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 300, SANE_FALSE, 300, 4350, 600, 1, 42, NULL, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 600, SANE_FALSE, 600, 8700, 600, 1, 42, NULL, SANE_FALSE, 0x20, 0x05}, {CCD_HP2300,1200, SANE_FALSE, 600, 8700, 600, 1, 42, NULL, SANE_FALSE, 0x20, 0x05}, /* non half ccd 300 dpi settings {CCD_HP2300, 300, SANE_TRUE , 300, 8700, 300, 1, 42, NULL, SANE_FALSE, 0x20, 0x05}, {CCD_HP2300, 300, SANE_FALSE, 300, 8700, 300, 1, 42, NULL, SANE_FALSE, 0x20, 0x05}, */ /* MD5345/6471 master settings */ {CCD_5345 , 50, SANE_TRUE , 50, 12000, 100, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 75, SANE_TRUE , 75, 11000, 150, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 100, SANE_TRUE , 100, 11000, 200, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 150, SANE_TRUE , 150, 11000, 300, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 200, SANE_TRUE , 200, 11000, 400, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 300, SANE_TRUE , 300, 11000, 600, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 400, SANE_TRUE , 400, 11000, 800, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 600, SANE_TRUE , 600, 11000,1200, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 ,1200, SANE_TRUE ,1200, 11000,1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x03}, {CCD_5345 ,2400, SANE_TRUE ,1200, 11000,1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x03}, {CCD_5345 , 50, SANE_FALSE, 50, 12000, 100, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 75, SANE_FALSE, 75, 11000, 150, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 100, SANE_FALSE, 100, 11000, 200, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 150, SANE_FALSE, 150, 11000, 300, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 200, SANE_FALSE, 200, 11000, 400, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 300, SANE_FALSE, 300, 11000, 600, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 400, SANE_FALSE, 400, 11000, 800, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 , 600, SANE_FALSE, 600, 11000,1200, 1, 42, NULL, SANE_TRUE , 0x28, 0x03}, {CCD_5345 ,1200, SANE_FALSE,1200, 11000,1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x03}, {CCD_5345 ,2400, SANE_FALSE,1200, 11000,1200, 1, 42, NULL, SANE_FALSE, 0x30, 0x03}, }; /** * master motor settings, for a given motor and dpi, * it gives steps and speed informations */ static Motor_Master motor_master[] = { /* HP3670 motor settings */ {MOTOR_HP3670, 75, SANE_TRUE , 75, FULL_STEP, SANE_FALSE, SANE_TRUE , 1, 200, 3429, 305, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 100, SANE_TRUE , 100, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 143, 2905, 187, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 150, SANE_TRUE , 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 73, 3429, 305, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 300, SANE_TRUE , 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 11, 1055, 563, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 600, SANE_TRUE , 600, FULL_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 10687, 5126, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670,1200, SANE_TRUE ,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 15937, 6375, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670,2400, SANE_TRUE ,2400, HALF_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 15937, 12750, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 75, SANE_FALSE, 75, FULL_STEP, SANE_FALSE, SANE_TRUE , 1, 200, 3429, 305, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 100, SANE_FALSE, 100, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 143, 2905, 187, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 150, SANE_FALSE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 73, 3429, 305, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 1, 11, 1055, 563, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670, 600, SANE_FALSE, 600, FULL_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 10687, 5126, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670,1200, SANE_FALSE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 15937, 6375, 192, 3399, 337, 0.3, 0.4, 192}, {MOTOR_HP3670,2400, SANE_TRUE ,2400, HALF_STEP, SANE_FALSE, SANE_TRUE , 0, 3, 15937, 12750, 192, 3399, 337, 0.3, 0.4, 192}, /* HP2400/G2410 motor settings base motor dpi = 600 */ {MOTOR_HP2400, 50, SANE_TRUE , 50, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 120, 8736, 601, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400, 100, SANE_TRUE , 100, HALF_STEP, SANE_FALSE, SANE_TRUE, 63, 120, 8736, 601, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400, 150, SANE_TRUE , 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 67, 15902, 902, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400, 300, SANE_TRUE , 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 32, 16703, 2188, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400, 600, SANE_TRUE , 600, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 18761, 18761, 192, 4905, 627, 0.30, 0.4, 192}, {MOTOR_HP2400,1200, SANE_TRUE ,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 43501, 43501, 192, 4905, 627, 0.30, 0.4, 192}, {MOTOR_HP2400, 50, SANE_FALSE, 50, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 120, 8736, 601, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400, 100, SANE_FALSE, 100, HALF_STEP, SANE_FALSE, SANE_TRUE, 63, 120, 8736, 601, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400, 150, SANE_FALSE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 67, 15902, 902, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 32, 16703, 2188, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400, 600, SANE_FALSE, 600, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 18761, 18761, 192, 4905, 337, 0.30, 0.4, 192}, {MOTOR_HP2400,1200, SANE_FALSE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 43501, 43501, 192, 4905, 337, 0.30, 0.4, 192}, /* XP 200 motor settings */ {MOTOR_XP200, 75, SANE_TRUE, 75, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6000, 2136, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 100, SANE_TRUE, 100, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6000, 2850, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 200, SANE_TRUE, 200, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6999, 5700, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 250, SANE_TRUE, 250, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6999, 6999, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 300, SANE_TRUE, 300, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 13500, 13500, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 600, SANE_TRUE, 600, HALF_STEP, SANE_TRUE , SANE_TRUE, 0, 4, 31998, 31998, 2, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 75, SANE_FALSE, 75, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6000, 2000, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 100, SANE_FALSE, 100, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6000, 1300, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 200, SANE_FALSE, 200, HALF_STEP, SANE_TRUE , SANE_TRUE, 0, 4, 6000, 3666, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 300, SANE_FALSE, 300, HALF_STEP, SANE_TRUE , SANE_FALSE, 0, 4, 6500, 6500, 8, 12000, 1200, 0.3, 0.5, 1}, {MOTOR_XP200, 600, SANE_FALSE, 600, HALF_STEP, SANE_TRUE , SANE_TRUE, 0, 4, 24000, 24000, 2, 12000, 1200, 0.3, 0.5, 1}, /* HP scanjet 2300c */ {MOTOR_HP2300, 75, SANE_TRUE, 75, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 120, 8139, 560, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 150, SANE_TRUE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 67, 7903, 543, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 2175, 1087, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 600, SANE_TRUE, 600, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 8700, 4350, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300,1200, SANE_TRUE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 17400, 8700, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 75, SANE_FALSE, 75, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 120, 8139, 560, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 150, SANE_FALSE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 67, 7903, 543, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 2175, 1087, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 600, SANE_FALSE, 600, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 8700, 4350, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300,1200, SANE_FALSE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 17400, 8700, 120, 4905, 337, 0.3, 0.4, 16}, /* non half ccd settings for 300 dpi {MOTOR_HP2300, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, */ /* MD5345/6471 motor settings */ /* vfinal=(exposure/(1200/dpi))/step_type */ {MOTOR_5345, 50, SANE_TRUE , 50, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 250, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 75, SANE_TRUE , 75, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 343, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 100, SANE_TRUE , 100, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 458, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 150, SANE_TRUE , 150, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 687, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 200, SANE_TRUE , 200, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 916, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 300, SANE_TRUE, 300, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 1375, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 400, SANE_TRUE, 400, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2000, 1833, 255, 2000, 300, 0.3, 0.4, 32}, {MOTOR_5345, 500, SANE_TRUE, 500, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2291, 2291, 255, 2000, 300, 0.3, 0.4, 32}, {MOTOR_5345, 600, SANE_TRUE, 600, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2750, 2750, 255, 2000, 300, 0.3, 0.4, 32}, {MOTOR_5345, 1200, SANE_TRUE ,1200, QUATER_STEP, SANE_FALSE, SANE_TRUE , 0, 16, 2750, 2750, 255, 2000, 300, 0.3, 0.4, 146}, {MOTOR_5345, 2400, SANE_TRUE ,2400, QUATER_STEP, SANE_FALSE, SANE_TRUE , 0, 16, 5500, 5500, 255, 2000, 300, 0.3, 0.4, 146}, {MOTOR_5345, 50, SANE_FALSE, 50, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 250, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 75, SANE_FALSE, 75, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 343, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 100, SANE_FALSE, 100, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 458, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 150, SANE_FALSE, 150, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 687, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 200, SANE_FALSE, 200, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 916, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 300, SANE_FALSE, 300, HALF_STEP , SANE_FALSE, SANE_TRUE , 2, 255, 2500, 1375, 255, 2000, 300, 0.3, 0.4, 64}, {MOTOR_5345, 400, SANE_FALSE, 400, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2000, 1833, 255, 2000, 300, 0.3, 0.4, 32}, {MOTOR_5345, 500, SANE_FALSE, 500, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2291, 2291, 255, 2000, 300, 0.3, 0.4, 32}, {MOTOR_5345, 600, SANE_FALSE, 600, HALF_STEP , SANE_FALSE, SANE_TRUE , 0, 32, 2750, 2750, 255, 2000, 300, 0.3, 0.4, 32}, {MOTOR_5345, 1200, SANE_FALSE,1200, QUATER_STEP, SANE_FALSE, SANE_TRUE , 0, 16, 2750, 2750, 255, 2000, 300, 0.3, 0.4, 146}, {MOTOR_5345, 2400, SANE_FALSE,2400, QUATER_STEP, SANE_FALSE, SANE_TRUE , 0, 16, 5500, 5500, 255, 2000, 300, 0.3, 0.4, 146}, /* 5500 guessed */ }; /** * sensor settings for a given sensor and timing method */ static Sensor_Settings sensor_settings[] = { /* HP 3670 */ {CCD_HP3670, 1, {0x0d, 0x0f, 0x11, 0x13}, {0x00, 0x00, 0x00, 0x00}, {0x2b, 0x07, 0x30, 0x2a, 0x00, 0x00, 0xc0, 0x43}, {0x03, 0x07, 0x0b, 0x0f, 0x13, 0x17, 0x23, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, }, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, {CCD_HP3670, 2, {0x00, 0x05, 0x06, 0x08}, {0x00, 0x00, 0x00, 0x00}, {0x33, 0x07, 0x31, 0x2a, 0x02, 0x0e, 0xc0, 0x43}, {0x0b, 0x0f, 0x13, 0x17, 0x03, 0x07, 0x63, 0x00, 0xc1, 0x02, 0x0e, 0x00, 0x00, }, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, {CCD_HP3670, 4, {0x00, 0x0a, 0x0b, 0x0d}, {0x00, 0x00, 0x00, 0x00}, {0x33, 0x07, 0x33, 0x2a, 0x02, 0x13, 0xc0, 0x43}, {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x15, 0xc1, 0x05, 0x0a, 0x0f, 0x00, }, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, /* HP 2400 */ {CCD_HP2400, 4, {0x14, 0x15, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00}, {0xbf, 0x08, 0x3f, 0x2a, 0x00, 0x00, 0x00, 0x02}, {11, 15, 19, 23, 3, 7, 0x63, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00}, {11, 15, 19, 23, 3, 7, 0x63} }, {CCD_HP2400, 2, {14, 15, 0, 0}, {14, 15, 0, 0}, {0xbf, 0x08, 0x31, 0x2a, 0, 0, 0, 0x02}, {3, 7, 11, 15, 19, 23, 0x23, 0, 0xc1, 0, 0, 0, 0}, {3, 7, 11, 15, 19, 23, 0x23} }, {CCD_HP2400, 1, {0x02, 0x04, 0x00, 0x00}, {0x02, 0x04, 0x00, 0x00}, {0xbf, 0x08, 0x30, 0x2a, 0x00, 0x00, 0xc0, 0x42}, {0x0b, 0x0f, 0x13, 0x17, 0x03, 0x07, 0x63, 0x00, 0xc1, 0x00, 0x0e, 0x00, 0x00}, {0x0b, 0x0f, 0x13, 0x17, 0x03, 0x07, 0x63} }, {CIS_XP200, 1, {6, 7, 10, 4}, {6, 7, 10, 4}, {0x24, 0x04, 0x00, 0x2a, 0x0a, 0x0a, 0, 0x11}, {8, 2, 0, 0, 0, 0, 0x1a, 0x51, 0, 0, 0, 0, 0}, {8, 2, 0, 0, 0, 0, 0x1a} }, {CCD_HP2300, 1, {0x01, 0x03, 0x04, 0x06}, {0x16, 0x00, 0x01, 0x03}, {0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a, 0x00, 0x05}, {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x00, 0xc1, 0x06, 0x0b, 0x10, 0x16}, {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83} }, {CCD_5345, 1, {0x0d, 0x0f, 0x11, 0x13}, {0x00, 0x05, 0x06, 0x08}, /* manual clock 1/2 settings or half ccd */ {0x0b, 0x0a, 0x30, 0x2a, 0x00, 0x00, 0x00, 0x03, }, {0x03, 0x07, 0x0b, 0x0f, 0x13, 0x17, 0x23, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00}, {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83} /* half ccd settings */ }, }; /* *INDENT-ON* */ sane-backends-1.0.27/backend/epsonds-cmd.c0000664000175000017500000004431113106201017015163 00000000000000/* * epsonds-cmd.c - Epson ESC/I-2 routines. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #include #include /* sleep */ #include "epsonds.h" #include "epsonds-io.h" #include "epsonds-cmd.h" #include "epsonds-ops.h" #include "epsonds-net.h" static SANE_Status esci2_parse_block(char *buf, int len, void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len)) { SANE_Status status = SANE_STATUS_GOOD; SANE_Status delayed_status = SANE_STATUS_GOOD; char *start = buf; char *end = (buf + len) - 1; /* 0 : # * 1-3: param * 4- : data */ while (1) { char param[4]; while (*start != '#' && start < end) start++; if (*start != '#') break; param[0] = *++start; param[1] = *++start; param[2] = *++start; param[3] = '\0'; if (strncmp("---", param, 3) == 0) break; /* ugly hack to skip over GMT in RESA */ if (strncmp("GMT", param, 3) == 0 && *(start + 5) == 'h') { start = start + 4 + 0x100; continue; } /* find the end of the token */ { int tlen; char *next = start; while (*next != '#' && *next != 0x00 && next < end) next++; tlen = next - start - 1; if (cb) { status = cb(userdata, start - 2, tlen); if (status != SANE_STATUS_GOOD) { delayed_status = status; } } start = next; } } if (delayed_status != SANE_STATUS_GOOD) return delayed_status; return status; } static SANE_Bool esci2_check_header(const char *cmd, const char *buf, unsigned int *more) { int err; *more = 0; if (strncmp(cmd, buf, 4) != 0) { if (strncmp("UNKN", buf, 4) == 0) { DBG(1, "UNKN reply code received\n"); } else if (strncmp("INVD", buf, 4) == 0) { DBG(1, "INVD reply code received\n"); } else { DBG(1, "%c%c%c%c, unexpected reply code\n", buf[0], buf[1], buf[2], buf[3]); } return 0; } /* INFOx0000100#.... */ /* read the answer len */ if (buf[4] != 'x') { DBG(1, "unknown type in header: %c\n", buf[4]); return 0; } err = sscanf(&buf[5], "%x#", more); if (err != 1) { DBG(1, "cannot decode length from header\n"); return 0; } return 1; } static SANE_Status esci2_cmd(epsonds_scanner* s, char *cmd, size_t len, char *payload, size_t plen, void *userdata, SANE_Status (*cb)(void *userdata, char *token, int len)) { SANE_Status status; unsigned int more; char header[13], rbuf[64]; /* add one more byte for header buffer to correct buffer overflow issue,*/ DBG(8, "%s: %4s len %lu, payload len: %lu\n", __func__, cmd, len, plen); memset(header, 0x00, sizeof(header)); memset(rbuf, 0x00, sizeof(rbuf)); // extra safety check, will not happen if (len != 12) { DBG(1, "%s: command has wrong size (%lu != 12)\n", __func__, len); return SANE_STATUS_INVAL; } // merge ParameterBlock size sprintf(header, "%4.4sx%07x", cmd, (unsigned int)plen); // send RequestBlock, request immediate response if there's no payload status = eds_txrx(s, header, len, rbuf, (plen > 0) ? 0 : 64); if (status != SANE_STATUS_GOOD) { return status; } /* send ParameterBlock, request response */ if (plen) { DBG(8, " %12.12s (%lu)\n", header, plen); status = eds_txrx(s, payload, plen, rbuf, 64); if (status != SANE_STATUS_GOOD) { return status; } } /* rxbuf holds the DataHeaderBlock, which should be * parsed to know if we need to read more data */ if (!esci2_check_header(cmd, rbuf, &more)) { return SANE_STATUS_IO_ERROR; } /* parse the received header block */ if (cb) { status = esci2_parse_block(rbuf + 12, 64 - 12, userdata, cb); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_DEVICE_BUSY) { DBG(1, "%s: %4s error while parsing received header\n", __func__, cmd); } } /* header valid, get the data block if present */ if (more) { char *pbuf = malloc(more); if (pbuf) { if (s->hw->connection == SANE_EPSONDS_NET) { epsonds_net_request_read(s, more); } ssize_t read = eds_recv(s, pbuf, more, &status); if (read != more) { } /* parse the received data block */ if (cb) { status = esci2_parse_block(pbuf, more, userdata, cb); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: %4s error while parsing received data block\n", __func__, cmd); } } free(pbuf); } else { return SANE_STATUS_NO_MEM; } } return status; } static SANE_Status esci2_cmd_simple(epsonds_scanner* s, char *cmd, SANE_Status (*cb)(void *userdata, char *token, int len)) { return esci2_cmd(s, cmd, 12, NULL, 0, s, cb); } SANE_Status esci2_fin(epsonds_scanner *s) { SANE_Status status; DBG(5, "%s\n", __func__); status = esci2_cmd_simple(s, "FIN x0000000", NULL); s->locked = 0; return status; } SANE_Status esci2_can(epsonds_scanner *s) { return esci2_cmd_simple(s, "CAN x0000000", NULL); } static int decode_value(char *buf, int len) { char tmp[10]; memcpy(tmp, buf, len); tmp[len] = '\0'; if (buf[0] == 'd' && len == 4) { return strtol(buf + 1, NULL, 10); } else if (buf[0] == 'i' && len == 8) { return strtol(buf + 1, NULL, 10); } else if (buf[0] == 'x' && len == 8) { return strtol(buf + 1, NULL, 16); } else if (buf[0] == 'h' && len == 4) { return strtol(buf + 1, NULL, 16); } return -1; } /* h000 */ static char *decode_binary(char *buf) { char tmp[6]; int hl; memcpy(tmp, buf, 4); tmp[4] = '\0'; if (buf[0] != 'h') return NULL; hl = strtol(tmp + 1, NULL, 16); if (hl) { char *v = malloc(hl + 1); memcpy(v, buf + 4, hl); v[hl] = '\0'; return v; } return NULL; } static char *decode_string(char *buf) { char *p, *s = decode_binary(buf); if (s == NULL) return NULL; /* trim white space at the end */ p = s + strlen(s); while (*--p == ' ') *p = '\0'; return s; } static void debug_token(int level, const char *func, char *token, int len) { char *tdata = malloc(len + 1); memcpy(tdata, token + 3, len); tdata[len] = '\0'; DBG(level, "%s: %3.3s / %s / %d\n", func, token, tdata, len); free(tdata); } static SANE_Status info_cb(void *userdata, char *token, int len) { epsonds_scanner *s = (epsonds_scanner *)userdata; char *value; if (DBG_LEVEL >= 11) { debug_token(DBG_LEVEL, __func__, token, len); } /* pointer to the token's value */ value = token + 3; /* nrd / nrdBUSY */ if (strncmp("nrd", token, 3) == 0) { if (strncmp("BUSY", value, 4) == 0) { return SANE_STATUS_DEVICE_BUSY; } } if (strncmp("PRD", token, 3) == 0) { free(s->hw->model); s->hw->model = decode_string(value); s->hw->sane.model = s->hw->model; DBG(1, " product: %s\n", s->hw->model); /* we will free the string later */ } if (strncmp("VER", token, 3) == 0) { char *v = decode_string(value); DBG(1, " version: %s\n", v); free(v); } if (strncmp("S/N", token, 3) == 0) { char *v = decode_string(value); DBG(1, " serial: %s\n", v); free(v); } if (strncmp("ADF", token, 3) == 0) { s->hw->has_adf = 1; if (len == 8) { if (strncmp("TYPEPAGE", value, len) == 0) { DBG(1, " ADF: page type\n"); } if (strncmp("TYPEFEED", value, len) == 0) { DBG(1, " ADF: sheet feed type\n"); } if (strncmp("DPLX1SCN", value, len) == 0) { DBG(1, " ADF: duplex single pass\n"); s->hw->adf_singlepass = 1; } if (strncmp("DPLX2SCN", value, len) == 0) { DBG(1, " ADF: duplex double pass\n"); s->hw->adf_singlepass = 0; } if (strncmp("FORDPF1N", value, len) == 0) { DBG(1, " ADF: order is 1 to N\n"); } if (strncmp("FORDPFN1", value, len) == 0) { DBG(1, " ADF: order is N to 1\n"); } if (strncmp("ALGNLEFT", value, len) == 0) { DBG(1, " ADF: left aligned\n"); s->hw->adf_alignment = 0; } if (strncmp("ALGNCNTR", value, len) == 0) { DBG(1, " ADF: center aligned\n"); s->hw->adf_alignment = 1; } if (strncmp("ALGNRIGT", value, len) == 0) { DBG(1, " ADF: right aligned (not supported!)\n"); s->hw->adf_alignment = 2; } } if (len == 4) { if (strncmp("PREF", value, len) == 0) { DBG(1, " ADF: auto pre-feed\n"); } if (strncmp("ASCN", value, len) == 0) { DBG(1, " ADF: auto scan\n"); } if (strncmp("RCVR", value, len) == 0) { DBG(1, " ADF: auto recovery\n"); } } if (len == 20) { /* ADFAREAi0000850i0001400 */ if (strncmp("AREA", value, 4) == 0) { int min = decode_value(value + 4, 8); int max = decode_value(value + 4 + 8, 8); DBG(1, " ADF: area %dx%d @ 100dpi\n", min, max); } if (strncmp("AMIN", value, 4) == 0) { int min = decode_value(value + 4, 8); int max = decode_value(value + 4 + 8, 8); DBG(1, " ADF: min %dx%d @ 100dpi\n", min, max); } if (strncmp("AMAX", value, 4) == 0) { int min = decode_value(value + 4, 8); int max = decode_value(value + 4 + 8, 8); DBG(1, " ADF: max %dx%d @ 100dpi\n", min, max); eds_set_adf_area(s->hw, min, max, 100); } } if (len == 12) { /* RESOi0000600 */ if (strncmp("RESO", value, 4) == 0) { int res = decode_value(value + 4, 8); DBG(1, " ADF: basic resolution is %d dpi\n", res); } /* OVSNd025d035 */ if (strncmp("OVSN", value, 4) == 0) { int x = decode_value(value + 4, 4); int y = decode_value(value + 4 + 4, 4); DBG(1, " ADF: overscan %dx%d @ 100dpi\n", x, y); } } } if (strncmp("FB ", token, 3) == 0) { s->hw->has_fb = 1; if (len == 20) { /* AREAi0000850i0001400 */ if (strncmp("AREA", value, 4) == 0) { int min = decode_value(value + 4, 8); int max = decode_value(value + 4 + 8, 8); DBG(1, " FB: area %dx%d @ 100dpi\n", min, max); eds_set_fbf_area(s->hw, min, max, 100); } } if (len == 8) { if (strncmp("ALGNLEFT", value, len) == 0) { DBG(1, " FB: left aligned\n"); s->hw->fbf_alignment = 0; } if (strncmp("ALGNCNTR", value, len) == 0) { DBG(1, " FB: center aligned\n"); s->hw->fbf_alignment = 1; } if (strncmp("ALGNRIGT", value, len) == 0) { DBG(1, " FB: right aligned (not supported!)\n"); s->hw->fbf_alignment = 2; } } if (len == 12) { /* RESOi0000600 */ if (strncmp("RESO", value, 4) == 0) { int res = decode_value(value + 4, 8); DBG(1, " FB: basic resolution is %d dpi\n", res); } /* OVSNd025d035 */ if (strncmp("OVSN", value, 4) == 0) { int x = decode_value(value + 4, 4); int y = decode_value(value + 4 + 4, 4); DBG(1, " FB: overscan %dx%d @ 100dpi\n", x, y); } } if (len == 4) { if (strncmp("DETX", value, len) == 0) { DBG(1, " FB: paper width detection\n"); } if (strncmp("DETY", value, len) == 0) { DBG(1, " FB: paper height detection\n"); } } } return SANE_STATUS_GOOD; } SANE_Status esci2_info(epsonds_scanner *s) { SANE_Status status; int i = 4; DBG(1, "= gathering device information\n"); do { status = esci2_cmd_simple(s, "INFOx0000000", &info_cb); if (status == SANE_STATUS_DEVICE_BUSY) { sleep(2); } i--; } while (status == SANE_STATUS_DEVICE_BUSY && i); return status; } /* CAPA */ static SANE_Status capa_cb(void *userdata, char *token, int len) { epsonds_scanner *s = (epsonds_scanner *)userdata; char *value = token + 3; if (DBG_LEVEL >= 11) { debug_token(DBG_LEVEL, __func__, token, len); } if (len == 4) { if (strncmp("ADFDPLX", token, 3 + 4) == 0) { DBG(1, " ADF: duplex\n"); s->hw->adf_is_duplex = 1; } if (strncmp("ADFSKEW", token, 3 + 4) == 0) { DBG(1, " ADF: skew correction\n"); s->hw->adf_has_skew = 1; } if (strncmp("ADFOVSN", token, 3 + 4) == 0) { DBG(1, " ADF: overscan\n"); } if (strncmp("ADFPEDT", token, 3 + 4) == 0) { DBG(1, " ADF: paper end detection\n"); } if (strncmp("ADFLOAD", token, 3 + 4) == 0) { DBG(1, " ADF: paper load\n"); s->hw->adf_has_load = 1; } if (strncmp("ADFEJCT", token, 3 + 4) == 0) { DBG(1, " ADF: paper eject\n"); s->hw->adf_has_eject = 1; } if (strncmp("ADFCRP ", token, 3 + 4) == 0) { DBG(1, " ADF: image cropping\n"); } if (strncmp("ADFFAST", token, 3 + 4) == 0) { DBG(1, " ADF: fast mode available\n"); } if (strncmp("ADFDFL1", token, 3 + 4) == 0) { DBG(1, " ADF: double feed detection\n"); s->hw->adf_has_dfd = 1; } } if (len == 8 && strncmp("ADFDFL1DFL2", token, 3 + 4) == 0) { DBG(1, " ADF: double feed detection (high sensitivity)\n"); s->hw->adf_has_dfd = 2; } if (strncmp("FMT", token, 3) == 0) { /* a bit ugly... */ if (len >= 8) { if (strncmp("RAW ", value + 4, 4) == 0) { s->hw->has_raw = 1; } } if (len >= 12) { if (strncmp("RAW ", value + 8, 4) == 0) { s->hw->has_raw = 1; } } } /* RSMRANGi0000050i0000600 */ if (strncmp("RSMRANG", token, 3 + 4) == 0) { char *p = token + 3 + 4; if (p[0] == 'i') { int min = decode_value(p, 8); int max = decode_value(p + 8, 8); eds_set_resolution_range(s->hw, min, max); DBG(1, "resolution min/max %d/%d\n", min, max); } } /* RSMLISTi0000300i0000600 */ if (strncmp("RSMLIST", token, 3 + 4) == 0) { char *p = token + 3 + 4; if (p[0] == 'i') { int i; int count = (len - 4) / 8; for (i = 0; i < count; i++) { eds_add_resolution(s->hw, decode_value(p, 8)); p += 8; } } } return SANE_STATUS_GOOD; } SANE_Status esci2_capa(epsonds_scanner *s) { return esci2_cmd_simple(s, "CAPAx0000000", &capa_cb); } /* STAT */ static SANE_Status stat_cb(void *userdata, char *token, int len) { /* epsonds_scanner *s = (epsonds_scanner *)userdata; char *value = token + 3; */ userdata = userdata; if (DBG_LEVEL >= 11) { debug_token(DBG_LEVEL, __func__, token, len); } return SANE_STATUS_GOOD; } SANE_Status esci2_stat(epsonds_scanner *s) { return esci2_cmd_simple(s, "STATx0000000", &stat_cb); } /* RESA */ static SANE_Status resa_cb(void *userdata, char *token, int len) { /* epsonds_scanner *s = (epsonds_scanner *)userdata; */ userdata = userdata; if (DBG_LEVEL >= 11) { debug_token(DBG_LEVEL, __func__, token, len); } return SANE_STATUS_GOOD; } SANE_Status esci2_resa(epsonds_scanner *s) { return esci2_cmd_simple(s, "RESAx0000000", &resa_cb); } /* PARA */ static SANE_Status para_cb(void *userdata, char *token, int len) { if (DBG_LEVEL >= 11) { debug_token(DBG_LEVEL, __func__, token, len); } userdata = userdata; if (strncmp("par", token, 3) == 0) { if (strncmp("FAIL", token + 3, 4) == 0) { DBG(1, "%s: parameter setting failed\n", __func__); return SANE_STATUS_INVAL; } } return SANE_STATUS_GOOD; } SANE_Status esci2_para(epsonds_scanner *s, char *parameters) { DBG(8, "%s: %s\n", __func__, parameters); return esci2_cmd(s, "PARAx0000000", 12, parameters, strlen(parameters), NULL, ¶_cb); } SANE_Status esci2_mech(epsonds_scanner *s, char *parameters) { DBG(8, "%s: %s\n", __func__, parameters); return esci2_cmd(s, "MECHx0000000", 12, parameters, strlen(parameters), NULL, ¶_cb); } SANE_Status esci2_trdt(epsonds_scanner *s) { return esci2_cmd_simple(s, "TRDTx0000000", NULL); } static SANE_Status img_cb(void *userdata, char *token, int len) { struct epsonds_scanner *s = userdata; if (DBG_LEVEL >= 11) { debug_token(DBG_LEVEL, __func__, token, len); } /* psti0000256i0000000i0000945 / 24 */ /* integer comparison first so it's faster */ if (len == 24 && strncmp("pst", token, 3) == 0) { s->dummy = decode_value(token + 3 + 8, 8); DBG(10, "%s: pst width: %d, height: %d, dummy: %d\n", __func__, decode_value(token + 3, 8), decode_value(token + 3 + 8 + 8, 8), s->dummy); return SANE_STATUS_GOOD; } if (len == 16 && strncmp("pen", token, 3) == 0) { DBG(10, "%s: page end\n", __func__); s->eof = 1; return SANE_STATUS_EOF; } /* typIMGA or typIMGB */ if (len == 4 && strncmp("typ", token, 3) == 0) { if (token[6] == 'B') s->backside = 1; else s->backside = 0; return SANE_STATUS_GOOD; } if (strncmp("err", token, 3) == 0) { char *option = token + 3; /* ADF, TPU, FB */ char *cause = token + 3 + 4; /* OPN, PJ, PE, ERR, LTF, LOCK, DFED, DTCL, AUT, PERM */ s->scanning = 0; DBG(1, "%s: error on option %3.3s, cause %4.4s\n", __func__, option, cause); if (cause[0] == 'P' && cause[1] == 'J') return SANE_STATUS_JAMMED; if (cause[0] == 'P' && cause[1] == 'E') return SANE_STATUS_NO_DOCS; if (cause[0] == 'O' && cause[1] == 'P' && cause[2] == 'N') return SANE_STATUS_COVER_OPEN; return SANE_STATUS_IO_ERROR; } if (len == 4 && strncmp("atnCAN ", token, 3 + 4) == 0) { DBG(1, "%s: cancel request\n", __func__); s->canceling = 1; s->scanning = 0; return SANE_STATUS_CANCELLED; } if (len == 4 && strncmp("lftd000", token, 3 + 4) == 0) { s->scanning = 0; } return SANE_STATUS_GOOD; } SANE_Status esci2_img(struct epsonds_scanner *s, SANE_Int *length) { SANE_Status status = SANE_STATUS_GOOD; SANE_Status parse_status; unsigned int more; ssize_t read; *length = 0; if (s->canceling) return SANE_STATUS_CANCELLED; /* request image data */ eds_send(s, "IMG x0000000", 12, &status, 64); if (status != SANE_STATUS_GOOD) { return status; } /* receive DataHeaderBlock */ memset(s->buf, 0x00, 64); eds_recv(s, s->buf, 64, &status); if (status != SANE_STATUS_GOOD) { return status; } /* check if we need to read any image data */ more = 0; if (!esci2_check_header("IMG ", (char *)s->buf, &more)) { return SANE_STATUS_IO_ERROR; } /* this handles eof and errors */ parse_status = esci2_parse_block((char *)s->buf + 12, 64 - 12, s, &img_cb); /* no more data? return using the status of the esci2_parse_block * call, which might hold other error conditions. */ if (!more) { return parse_status; } /* ALWAYS read image data */ if (s->hw->connection == SANE_EPSONDS_NET) { epsonds_net_request_read(s, more); } read = eds_recv(s, s->buf, more, &status); if (status != SANE_STATUS_GOOD) { return status; } if (read != more) { return SANE_STATUS_IO_ERROR; } /* handle esci2_parse_block errors */ if (parse_status != SANE_STATUS_GOOD) { return parse_status; } DBG(15, "%s: read %lu bytes, status: %d\n", __func__, (unsigned long) read, status); *length = read; if (s->canceling) { return SANE_STATUS_CANCELLED; } return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/test.c0000664000175000017500000026347212775312261013760 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002-2006 Henning Meier-Geinitz Changes according to the sanei_thread usage by Gerhard Jaeger This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This backend is for testing frontends. */ #define BUILD 28 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_thread.h" #define BACKEND_NAME test #include "../include/sane/sanei_backend.h" #include "test.h" #include "test-picture.c" #define TEST_CONFIG_FILE "test.conf" static SANE_Bool inited = SANE_FALSE; static SANE_Device **sane_device_list = 0; static Test_Device *first_test_device = 0; static SANE_Range geometry_range = { SANE_FIX (0.0), SANE_FIX (200.0), SANE_FIX (1.0) }; static SANE_Range resolution_range = { SANE_FIX (1.0), SANE_FIX (1200.0), SANE_FIX (1.0) }; static SANE_Range ppl_loss_range = { 0, 128, 1 }; static SANE_Range read_limit_size_range = { 1, 64 * 1024, /* 64 KB ought to be enough for everyone :-) */ 1 }; static SANE_Range read_delay_duration_range = { 1000, 200 * 1000, /* 200 msec */ 1000 }; static SANE_Range int_constraint_range = { 4, 192, 2 }; static SANE_Range fixed_constraint_range = { SANE_FIX (-42.17), SANE_FIX (32767.9999), SANE_FIX (2.0) }; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static SANE_String_Const order_list[] = { "RGB", "RBG", "GBR", "GRB", "BRG", "BGR", 0 }; static SANE_String_Const test_picture_list[] = { SANE_I18N ("Solid black"), SANE_I18N ("Solid white"), SANE_I18N ("Color pattern"), SANE_I18N ("Grid"), 0 }; static SANE_String_Const read_status_code_list[] = { SANE_I18N ("Default"), "SANE_STATUS_UNSUPPORTED", "SANE_STATUS_CANCELLED", "SANE_STATUS_DEVICE_BUSY", "SANE_STATUS_INVAL", "SANE_STATUS_EOF", "SANE_STATUS_JAMMED", "SANE_STATUS_NO_DOCS", "SANE_STATUS_COVER_OPEN", "SANE_STATUS_IO_ERROR", "SANE_STATUS_NO_MEM", "SANE_STATUS_ACCESS_DENIED", 0 }; static SANE_Int depth_list[] = { 3, 1, 8, 16 }; static SANE_Int int_constraint_word_list[] = { 9, -42, -8, 0, 17, 42, 256, 65536, 256 * 256 * 256, 256 * 256 * 256 * 64 }; static SANE_Int fixed_constraint_word_list[] = { 4, SANE_FIX (-32.7), SANE_FIX (12.1), SANE_FIX (42.0), SANE_FIX (129.5) }; static SANE_String_Const string_constraint_string_list[] = { SANE_I18N ("First entry"), SANE_I18N ("Second entry"), SANE_I18N ("This is the very long third entry. Maybe the frontend has an idea how to " "display it"), 0 }; static SANE_String_Const string_constraint_long_string_list[] = { SANE_I18N ("First entry"), SANE_I18N ("Second entry"), "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", 0 }; static SANE_Int int_array[] = { -17, 0, -5, 42, 91, 256 * 256 * 256 * 64 }; static SANE_Int int_array_constraint_range[] = { 48, 6, 4, 92, 190, 16 }; static SANE_Int int_array_constraint_word_list[] = { -42, 0, -8, 17, 42, 42 }; static SANE_String_Const source_list[] = { SANE_I18N ("Flatbed"), SANE_I18N ("Automatic Document Feeder"), 0 }; static double random_factor; /* use for fuzzyness of parameters */ /* initial values */ static SANE_Word init_number_of_devices = 2; static SANE_Fixed init_tl_x = SANE_FIX (0.0); static SANE_Fixed init_tl_y = SANE_FIX (0.0); static SANE_Fixed init_br_x = SANE_FIX (80.0); static SANE_Fixed init_br_y = SANE_FIX (100.0); static SANE_Word init_resolution = 50; static SANE_String init_mode =SANE_VALUE_SCAN_MODE_GRAY; static SANE_Word init_depth = 8; static SANE_Bool init_hand_scanner = SANE_FALSE; static SANE_Bool init_three_pass = SANE_FALSE; static SANE_String init_three_pass_order = "RGB"; static SANE_String init_scan_source = "Flatbed"; static SANE_String init_test_picture = "Solid black"; static SANE_Bool init_invert_endianess = SANE_FALSE; static SANE_Bool init_read_limit = SANE_FALSE; static SANE_Word init_read_limit_size = 1; static SANE_Bool init_read_delay = SANE_FALSE; static SANE_Word init_read_delay_duration = 1000; static SANE_String init_read_status_code = "Default"; static SANE_Bool init_fuzzy_parameters = SANE_FALSE; static SANE_Word init_ppl_loss = 0; static SANE_Bool init_non_blocking = SANE_FALSE; static SANE_Bool init_select_fd = SANE_FALSE; static SANE_Bool init_enable_test_options = SANE_FALSE; static SANE_String init_string = "This is the contents of the string option. " "Fill some more words to see how the frontend behaves."; static SANE_String init_string_constraint_string_list = "First entry"; static SANE_String init_string_constraint_long_string_list = "First entry"; /* Test if this machine is little endian (from coolscan.c) */ static SANE_Bool little_endian (void) { SANE_Int testvalue = 255; uint8_t *firstbyte = (uint8_t *) & testvalue; if (*firstbyte == 255) return SANE_TRUE; return SANE_FALSE; } static void swap_double (double *a, double *b) { double c; c = *a; *a = *b; *b = c; return; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Bool check_handle (SANE_Handle handle) { Test_Device *test_device = first_test_device; while (test_device) { if (test_device == (Test_Device *) handle) return SANE_TRUE; test_device = test_device->next; } return SANE_FALSE; } static SANE_Status init_options (Test_Device * test_device) { SANE_Option_Descriptor *od; DBG (2, "init_options: test_device=%p\n", (void *) test_device); /* opt_num_opts */ od = &test_device->opt[opt_num_opts]; od->name = ""; od->title = SANE_TITLE_NUM_OPTIONS; od->desc = SANE_DESC_NUM_OPTIONS; od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_num_opts].w = num_options; test_device->loaded[opt_num_opts] = 1; /* opt_mode_group */ od = &test_device->opt[opt_mode_group]; od->name = ""; od->title = SANE_I18N ("Scan Mode"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = 0; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_mode_group].w = 0; /* opt_mode */ od = &test_device->opt[opt_mode]; od->name = SANE_NAME_SCAN_MODE; od->title = SANE_TITLE_SCAN_MODE; od->desc = SANE_DESC_SCAN_MODE; od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = max_string_size (mode_list); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = mode_list; test_device->val[opt_mode].s = malloc (od->size); if (!test_device->val[opt_mode].s) return SANE_STATUS_NO_MEM; strcpy (test_device->val[opt_mode].s, init_mode); /* opt_depth */ od = &test_device->opt[opt_depth]; od->name = SANE_NAME_BIT_DEPTH; od->title = SANE_TITLE_BIT_DEPTH; od->desc = SANE_DESC_BIT_DEPTH; od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_WORD_LIST; od->constraint.word_list = depth_list; test_device->val[opt_depth].w = init_depth; /* opt_hand_scanner */ od = &test_device->opt[opt_hand_scanner]; od->name = "hand-scanner"; od->title = SANE_I18N ("Hand-scanner simulation"); od->desc = SANE_I18N ("Simulate a hand-scanner. Hand-scanners do not " "know the image height a priori. Instead, they " "return a height of -1. Setting this option allows one " "to test whether a frontend can handle this " "correctly. This option also enables a fixed width " "of 11 cm."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_hand_scanner].w = init_hand_scanner; /* opt_three_pass */ od = &test_device->opt[opt_three_pass]; od->name = "three-pass"; od->title = SANE_I18N ("Three-pass simulation"); od->desc = SANE_I18N ("Simulate a three-pass scanner. In color mode, three " "frames are transmitted."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; if (strcmp (init_mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_three_pass].w = init_three_pass; /* opt_three_pass_order */ od = &test_device->opt[opt_three_pass_order]; od->name = "three-pass-order"; od->title = SANE_I18N ("Set the order of frames"); od->desc = SANE_I18N ("Set the order of frames in three-pass color mode."); od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = max_string_size (order_list); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; if (strcmp (init_mode, SANE_VALUE_SCAN_MODE_COLOR) != 0) od->cap |= SANE_CAP_INACTIVE; if (!init_three_pass) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = order_list; test_device->val[opt_three_pass_order].s = malloc (od->size); if (!test_device->val[opt_three_pass_order].s) return SANE_STATUS_NO_MEM; strcpy (test_device->val[opt_three_pass_order].s, init_three_pass_order); /* opt_resolution */ od = &test_device->opt[opt_resolution]; od->name = SANE_NAME_SCAN_RESOLUTION; od->title = SANE_TITLE_SCAN_RESOLUTION; od->desc = SANE_DESC_SCAN_RESOLUTION; od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_DPI; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &resolution_range; test_device->val[opt_resolution].w = init_resolution; /* opt_scan_source */ od = &test_device->opt[opt_scan_source]; od->name = SANE_NAME_SCAN_SOURCE; od->title = SANE_TITLE_SCAN_SOURCE; od->desc = SANE_I18N("If Automatic Document Feeder is selected, the feeder will be 'empty' after 10 scans."); od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = max_string_size (source_list); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = source_list; test_device->val[opt_scan_source].s = malloc (od->size); if (!test_device->val[opt_scan_source].s) return SANE_STATUS_NO_MEM; strcpy (test_device->val[opt_scan_source].s, init_scan_source); /* opt_special_group */ od = &test_device->opt[opt_special_group]; od->name = ""; od->title = SANE_I18N ("Special Options"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = 0; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_special_group].w = 0; /* opt_test_picture */ od = &test_device->opt[opt_test_picture]; od->name = "test-picture"; od->title = SANE_I18N ("Select the test picture"); od->desc = SANE_I18N ("Select the kind of test picture. Available options:\n" "Solid black: fills the whole scan with black.\n" "Solid white: fills the whole scan with white.\n" "Color pattern: draws various color test patterns " "depending on the mode.\n" "Grid: draws a black/white grid with a width and " "height of 10 mm per square."); od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = max_string_size (test_picture_list); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = test_picture_list; test_device->val[opt_test_picture].s = malloc (od->size); if (!test_device->val[opt_test_picture].s) return SANE_STATUS_NO_MEM; strcpy (test_device->val[opt_test_picture].s, init_test_picture); /* opt_invert_endianness */ od = &test_device->opt[opt_invert_endianess]; od->name = "invert-endianess"; od->title = SANE_I18N ("Invert endianness"); od->desc = SANE_I18N ("Exchange upper and lower byte of image data in 16 " "bit modes. This option can be used to test the 16 " "bit modes of frontends, e.g. if the frontend uses " "the correct endianness."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_invert_endianess].w = init_invert_endianess; /* opt_read_limit */ od = &test_device->opt[opt_read_limit]; od->name = "read-limit"; od->title = SANE_I18N ("Read limit"); od->desc = SANE_I18N ("Limit the amount of data transferred with each " "call to sane_read()."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_read_limit].w = init_read_limit; /* opt_read_limit_size */ od = &test_device->opt[opt_read_limit_size]; od->name = "read-limit-size"; od->title = SANE_I18N ("Size of read-limit"); od->desc = SANE_I18N ("The (maximum) amount of data transferred with each " "call to sane_read()."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; if (!init_read_limit) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &read_limit_size_range; test_device->val[opt_read_limit_size].w = init_read_limit_size; /* opt_read_delay */ od = &test_device->opt[opt_read_delay]; od->name = "read-delay"; od->title = SANE_I18N ("Read delay"); od->desc = SANE_I18N ("Delay the transfer of data to the pipe."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_read_delay].w = init_read_delay; /* opt_read_delay_duration */ od = &test_device->opt[opt_read_delay_duration]; od->name = "read-delay-duration"; od->title = SANE_I18N ("Duration of read-delay"); od->desc = SANE_I18N ("How long to wait after transferring each buffer of " "data through the pipe."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_MICROSECOND; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; if (!init_read_delay) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &read_delay_duration_range; test_device->val[opt_read_delay_duration].w = init_read_delay_duration; /* opt_read_status_code */ od = &test_device->opt[opt_read_status_code]; od->name = "read-return-value"; od->title = SANE_I18N ("Return-value of sane_read"); od->desc = SANE_I18N ("Select the return-value of sane_read(). \"Default\" " "is the normal handling for scanning. All other status " "codes are for testing how the frontend handles them."); od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = max_string_size (read_status_code_list); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = read_status_code_list; test_device->val[opt_read_status_code].s = malloc (od->size); if (!test_device->val[opt_read_status_code].s) return SANE_STATUS_NO_MEM; strcpy (test_device->val[opt_read_status_code].s, init_read_status_code); /* opt_ppl_loss */ od = &test_device->opt[opt_ppl_loss]; od->name = "ppl-loss"; od->title = SANE_I18N ("Loss of pixels per line"); od->desc = SANE_I18N ("The number of pixels that are wasted at the end of each " "line."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_PIXEL; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &ppl_loss_range; test_device->val[opt_ppl_loss].w = init_ppl_loss; /* opt_fuzzy_parameters */ od = &test_device->opt[opt_fuzzy_parameters]; od->name = "fuzzy-parameters"; od->title = SANE_I18N ("Fuzzy parameters"); od->desc = SANE_I18N ("Return fuzzy lines and bytes per line when " "sane_parameters() is called before sane_start()."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_fuzzy_parameters].w = init_fuzzy_parameters; /* opt_non_blocking */ od = &test_device->opt[opt_non_blocking]; od->name = "non-blocking"; od->title = SANE_I18N ("Use non-blocking IO"); od->desc = SANE_I18N ("Use non-blocking IO for sane_read() if supported " "by the frontend."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_non_blocking].w = init_non_blocking; /* opt_select_fd */ od = &test_device->opt[opt_select_fd]; od->name = "select-fd"; od->title = SANE_I18N ("Offer select file descriptor"); od->desc = SANE_I18N ("Offer a select filedescriptor for detecting if " "sane_read() will return data."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_select_fd].w = init_select_fd; /* opt_enable_test_options */ od = &test_device->opt[opt_enable_test_options]; od->name = "enable-test-options"; od->title = SANE_I18N ("Enable test options"); od->desc = SANE_I18N ("Enable various test options. This is for testing " "the ability of frontends to view and modify all the " "different SANE option types."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_enable_test_options].w = init_enable_test_options; /* opt_print_options */ od = &test_device->opt[opt_print_options]; od->name = "print-options"; od->title = SANE_I18N ("Print options"); od->desc = SANE_I18N ("Print a list of all options."); od->type = SANE_TYPE_BUTTON; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.string_list = 0; test_device->val[opt_print_options].w = 0; /* opt_geometry_group */ od = &test_device->opt[opt_geometry_group]; od->name = ""; od->title = SANE_I18N ("Geometry"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = 0; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_geometry_group].w = 0; /* opt_tl_x */ od = &test_device->opt[opt_tl_x]; od->name = SANE_NAME_SCAN_TL_X; od->title = SANE_TITLE_SCAN_TL_X; od->desc = SANE_DESC_SCAN_TL_X; od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_MM; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &geometry_range; test_device->val[opt_tl_x].w = init_tl_x; /* opt_tl_y */ od = &test_device->opt[opt_tl_y]; od->name = SANE_NAME_SCAN_TL_Y; od->title = SANE_TITLE_SCAN_TL_Y; od->desc = SANE_DESC_SCAN_TL_Y; od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_MM; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &geometry_range; test_device->val[opt_tl_y].w = init_tl_y; /* opt_br_x */ od = &test_device->opt[opt_br_x]; od->name = SANE_NAME_SCAN_BR_X; od->title = SANE_TITLE_SCAN_BR_X; od->desc = SANE_DESC_SCAN_BR_X; od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_MM; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &geometry_range; test_device->val[opt_br_x].w = init_br_x; /* opt_br_y */ od = &test_device->opt[opt_br_y]; od->name = SANE_NAME_SCAN_BR_Y; od->title = SANE_TITLE_SCAN_BR_Y; od->desc = SANE_DESC_SCAN_BR_Y; od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_MM; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &geometry_range; test_device->val[opt_br_y].w = init_br_y; /* opt_bool_group */ od = &test_device->opt[opt_bool_group]; od->name = ""; od->title = SANE_I18N ("Bool test options"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = SANE_CAP_ADVANCED; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_bool_group].w = 0; /* opt_bool_soft_select_soft_detect */ od = &test_device->opt[opt_bool_soft_select_soft_detect]; od->name = "bool-soft-select-soft-detect"; od->title = SANE_I18N ("(1/6) Bool soft select soft detect"); od->desc = SANE_I18N ("(1/6) Bool test option that has soft select and soft " "detect (and advanced) capabilities. That's just a " "normal bool option."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_bool_soft_select_soft_detect].w = SANE_FALSE; /* opt_bool_hard_select_soft_detect */ od = &test_device->opt[opt_bool_hard_select_soft_detect]; od->name = "bool-hard-select-soft-detect"; od->title = SANE_I18N ("(2/6) Bool hard select soft detect"); od->desc = SANE_I18N ("(2/6) Bool test option that has hard select and soft " "detect (and advanced) capabilities. That means the " "option can't be set by the frontend but by the user " "(e.g. by pressing a button at the device)."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_bool_hard_select_soft_detect].w = SANE_FALSE; /* opt_bool_hard_select */ od = &test_device->opt[opt_bool_hard_select]; od->name = "bool-hard-select"; od->title = SANE_I18N ("(3/6) Bool hard select"); od->desc = SANE_I18N ("(3/6) Bool test option that has hard select " "(and advanced) capabilities. That means the option " "can't be set by the frontend but by the user " "(e.g. by pressing a button at the device) and can't " "be read by the frontend."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_bool_hard_select].w = SANE_FALSE; /* opt_bool_soft_detect */ od = &test_device->opt[opt_bool_soft_detect]; od->name = "bool-soft-detect"; od->title = SANE_I18N ("(4/6) Bool soft detect"); od->desc = SANE_I18N ("(4/6) Bool test option that has soft detect " "(and advanced) capabilities. That means the option " "is read-only."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_bool_soft_detect].w = SANE_FALSE; /* opt_bool_soft_select_soft_detect_emulated */ od = &test_device->opt[opt_bool_soft_select_soft_detect_emulated]; od->name = "bool-soft-select-soft-detect-emulated"; od->title = SANE_I18N ("(5/6) Bool soft select soft detect emulated"); od->desc = SANE_I18N ("(5/6) Bool test option that has soft select, soft " "detect, and emulated (and advanced) capabilities."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_EMULATED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_bool_soft_select_soft_detect_emulated].w = SANE_FALSE; /* opt_bool_soft_select_soft_detect_auto */ od = &test_device->opt[opt_bool_soft_select_soft_detect_auto]; od->name = "bool-soft-select-soft-detect-auto"; od->title = SANE_I18N ("(6/6) Bool soft select soft detect auto"); od->desc = SANE_I18N ("(6/6) Bool test option that has soft select, soft " "detect, and automatic (and advanced) capabilities. " "This option can be automatically set by the backend."); od->type = SANE_TYPE_BOOL; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_bool_soft_select_soft_detect_auto].w = SANE_FALSE; /* opt_int_group */ od = &test_device->opt[opt_int_group]; od->name = ""; od->title = SANE_I18N ("Int test options"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = SANE_CAP_ADVANCED; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_int_group].w = 0; /* opt_int */ od = &test_device->opt[opt_int]; od->name = "int"; od->title = SANE_I18N ("(1/6) Int"); od->desc = SANE_I18N ("(1/6) Int test option with no unit and no " "constraint set."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_int].w = 42; /* opt_int_constraint_range */ od = &test_device->opt[opt_int_constraint_range]; od->name = "int-constraint-range"; od->title = SANE_I18N ("(2/6) Int constraint range"); od->desc = SANE_I18N ("(2/6) Int test option with unit pixel and " "constraint range set. Minimum is 4, maximum 192, and " "quant is 2."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_PIXEL; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &int_constraint_range; test_device->val[opt_int_constraint_range].w = 26; /* opt_int_constraint_word_list */ od = &test_device->opt[opt_int_constraint_word_list]; od->name = "int-constraint-word-list"; od->title = SANE_I18N ("(3/6) Int constraint word list"); od->desc = SANE_I18N ("(3/6) Int test option with unit bits and " "constraint word list set."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_BIT; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_WORD_LIST; od->constraint.word_list = int_constraint_word_list; test_device->val[opt_int_constraint_word_list].w = 42; /* opt_int_array */ od = &test_device->opt[opt_int_array]; od->name = "int-constraint-array"; od->title = SANE_I18N ("(4/6) Int array"); od->desc = SANE_I18N ("(4/6) Int test option with unit mm and using " "an array without constraints."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_MM; od->size = 6 * sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_int_array].wa = &int_array[0]; /* opt_int_array_constraint_range */ od = &test_device->opt[opt_int_array_constraint_range]; od->name = "int-constraint-array-constraint-range"; od->title = SANE_I18N ("(5/6) Int array constraint range"); od->desc = SANE_I18N ("(5/6) Int test option with unit dpi and using " "an array with a range constraint. Minimum is 4, " "maximum 192, and quant is 2."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_DPI; od->size = 6 * sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &int_constraint_range; test_device->val[opt_int_array_constraint_range].wa = &int_array_constraint_range[0]; /* opt_int_array_constraint_word_list */ od = &test_device->opt[opt_int_array_constraint_word_list]; od->name = "int-constraint-array-constraint-word-list"; od->title = SANE_I18N ("(6/6) Int array constraint word list"); od->desc = SANE_I18N ("(6/6) Int test option with unit percent and using " "an array with a word list constraint."); od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_PERCENT; od->size = 6 * sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_WORD_LIST; od->constraint.word_list = int_constraint_word_list; test_device->val[opt_int_array_constraint_word_list].wa = &int_array_constraint_word_list[0]; /* opt_fixed_group */ od = &test_device->opt[opt_fixed_group]; od->name = ""; od->title = SANE_I18N ("Fixed test options"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = SANE_CAP_ADVANCED; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_fixed_group].w = 0; /* opt_fixed */ od = &test_device->opt[opt_fixed]; od->name = "fixed"; od->title = SANE_I18N ("(1/3) Fixed"); od->desc = SANE_I18N ("(1/3) Fixed test option with no unit and no " "constraint set."); od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_fixed].w = SANE_FIX (42.0); /* opt_fixed_constraint_range */ od = &test_device->opt[opt_fixed_constraint_range]; od->name = "fixed-constraint-range"; od->title = SANE_I18N ("(2/3) Fixed constraint range"); od->desc = SANE_I18N ("(2/3) Fixed test option with unit microsecond and " "constraint range set. Minimum is -42.17, maximum " "32767.9999, and quant is 2.0."); od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_MICROSECOND; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &fixed_constraint_range; test_device->val[opt_fixed_constraint_range].w = SANE_FIX (41.83); /* opt_fixed_constraint_word_list */ od = &test_device->opt[opt_fixed_constraint_word_list]; od->name = "fixed-constraint-word-list"; od->title = SANE_I18N ("(3/3) Fixed constraint word list"); od->desc = SANE_I18N ("(3/3) Fixed test option with no unit and " "constraint word list set."); od->type = SANE_TYPE_FIXED; od->unit = SANE_UNIT_NONE; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_WORD_LIST; od->constraint.word_list = fixed_constraint_word_list; test_device->val[opt_fixed_constraint_word_list].w = SANE_FIX (42.0); /* opt_string_group */ od = &test_device->opt[opt_string_group]; od->name = ""; od->title = SANE_I18N ("String test options"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = 0; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_string_group].w = 0; /* opt_string */ od = &test_device->opt[opt_string]; od->name = "string"; od->title = SANE_I18N ("(1/3) String"); od->desc = SANE_I18N ("(1/3) String test option without constraint."); od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = strlen (init_string) + 1; od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.string_list = 0; test_device->val[opt_string].s = malloc (od->size); if (!test_device->val[opt_string].s) return SANE_STATUS_NO_MEM; strcpy (test_device->val[opt_string].s, init_string); /* opt_string_constraint_string_list */ od = &test_device->opt[opt_string_constraint_string_list]; od->name = "string-constraint-string-list"; od->title = SANE_I18N ("(2/3) String constraint string list"); od->desc = SANE_I18N ("(2/3) String test option with string list " "constraint."); od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = max_string_size (string_constraint_string_list); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = string_constraint_string_list; test_device->val[opt_string_constraint_string_list].s = malloc (od->size); if (!test_device->val[opt_string_constraint_string_list].s) return SANE_STATUS_NO_MEM; strcpy (test_device->val[opt_string_constraint_string_list].s, init_string_constraint_string_list); /* opt_string_constraint_long_string_list */ od = &test_device->opt[opt_string_constraint_long_string_list]; od->name = "string-constraint-long-string-list"; od->title = SANE_I18N ("(3/3) String constraint long string list"); od->desc = SANE_I18N ("(3/3) String test option with string list " "constraint. Contains some more entries..."); od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = max_string_size (string_constraint_long_string_list); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = string_constraint_long_string_list; test_device->val[opt_string_constraint_long_string_list].s = malloc (od->size); if (!test_device->val[opt_string_constraint_long_string_list].s) return SANE_STATUS_NO_MEM; strcpy (test_device->val[opt_string_constraint_long_string_list].s, init_string_constraint_long_string_list); /* opt_button_group */ od = &test_device->opt[opt_button_group]; od->name = ""; od->title = SANE_I18N ("Button test options"); od->desc = ""; od->type = SANE_TYPE_GROUP; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = 0; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.range = 0; test_device->val[opt_button_group].w = 0; /* opt_button */ od = &test_device->opt[opt_button]; od->name = "button"; od->title = SANE_I18N ("(1/1) Button"); od->desc = SANE_I18N ("(1/1) Button test option. Prints some text..."); od->type = SANE_TYPE_BUTTON; od->unit = SANE_UNIT_NONE; od->size = 0; od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; if (init_enable_test_options == SANE_FALSE) od->cap |= SANE_CAP_INACTIVE; od->constraint_type = SANE_CONSTRAINT_NONE; od->constraint.string_list = 0; test_device->val[opt_button].w = 0; return SANE_STATUS_GOOD; } static SANE_Status read_option (SANE_String line, SANE_String option_string, parameter_type p_type, void *value) { SANE_String_Const cp; SANE_Char *word, *end; word = 0; cp = sanei_config_get_string (line, &word); if (!word) return SANE_STATUS_INVAL; if (strcmp (word, option_string) != 0) { free(word); return SANE_STATUS_INVAL; } free (word); word = 0; switch (p_type) { case param_none: return SANE_STATUS_GOOD; case param_bool: { cp = sanei_config_get_string (cp, &word); if (!word) return SANE_STATUS_INVAL; if (strlen (word) == 0) { DBG (3, "read_option: option `%s' requires parameter\n", option_string); return SANE_STATUS_INVAL; } if (strcmp (word, "true") != 0 && strcmp (word, "false") != 0) { DBG (3, "read_option: option `%s' requires parameter " "`true' or `false'\n", option_string); return SANE_STATUS_INVAL; } else if (strcmp (word, "true") == 0) *(SANE_Bool *) value = SANE_TRUE; else *(SANE_Bool *) value = SANE_FALSE; DBG (3, "read_option: set option `%s' to %s\n", option_string, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; } case param_int: { SANE_Int int_value; cp = sanei_config_get_string (cp, &word); if (!word) return SANE_STATUS_INVAL; errno = 0; int_value = (SANE_Int) strtol (word, &end, 0); if (end == word) { DBG (3, "read_option: option `%s' requires parameter\n", option_string); return SANE_STATUS_INVAL; } else if (errno) { DBG (3, "read_option: option `%s': can't parse parameter `%s' " "(%s)\n", option_string, word, strerror (errno)); return SANE_STATUS_INVAL; } else { DBG (3, "read_option: set option `%s' to %d\n", option_string, int_value); *(SANE_Int *) value = int_value; } break; } case param_fixed: { double double_value; SANE_Fixed fixed_value; cp = sanei_config_get_string (cp, &word); if (!word) return SANE_STATUS_INVAL; errno = 0; double_value = strtod (word, &end); if (end == word) { DBG (3, "read_option: option `%s' requires parameter\n", option_string); return SANE_STATUS_INVAL; } else if (errno) { DBG (3, "read_option: option `%s': can't parse parameter `%s' " "(%s)\n", option_string, word, strerror (errno)); return SANE_STATUS_INVAL; } else { DBG (3, "read_option: set option `%s' to %.0f\n", option_string, double_value); fixed_value = SANE_FIX (double_value); *(SANE_Fixed *) value = fixed_value; } break; } case param_string: { cp = sanei_config_get_string (cp, &word); if (!word) return SANE_STATUS_INVAL; if (strlen (word) == 0) { DBG (3, "read_option: option `%s' requires parameter\n", option_string); return SANE_STATUS_INVAL; } else { DBG (3, "read_option: set option `%s' to `%s'\n", option_string, word); *(SANE_String *) value = strdup (word); } break; } default: DBG (1, "read_option: unknown param_type %d\n", p_type); return SANE_STATUS_INVAL; } /* switch */ if (word) free (word); return SANE_STATUS_GOOD; } static SANE_Status reader_process (Test_Device * test_device, SANE_Int fd) { SANE_Status status; SANE_Word byte_count = 0, bytes_total; SANE_Byte *buffer = 0; ssize_t bytes_written = 0; size_t buffer_size = 0, write_count = 0; DBG (2, "(child) reader_process: test_device=%p, fd=%d\n", (void *) test_device, fd); bytes_total = test_device->lines * test_device->bytes_per_line; status = init_picture_buffer (test_device, &buffer, &buffer_size); if (status != SANE_STATUS_GOOD) return status; DBG (2, "(child) reader_process: buffer=%p, buffersize=%lu\n", buffer, (u_long) buffer_size); while (byte_count < bytes_total) { if (write_count == 0) { write_count = buffer_size; if (byte_count + (SANE_Word) write_count > bytes_total) write_count = bytes_total - byte_count; if (test_device->val[opt_read_delay].w == SANE_TRUE) usleep (test_device->val[opt_read_delay_duration].w); } bytes_written = write (fd, buffer, write_count); if (bytes_written < 0) { DBG (1, "(child) reader_process: write returned %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } byte_count += bytes_written; DBG (4, "(child) reader_process: wrote %ld bytes of %lu (%d total)\n", (long) bytes_written, (u_long) write_count, byte_count); write_count -= bytes_written; } free (buffer); if (sanei_thread_is_forked ()) { DBG (4, "(child) reader_process: finished, wrote %d bytes, expected %d " "bytes, now waiting\n", byte_count, bytes_total); while (SANE_TRUE) sleep (10); DBG (4, "(child) reader_process: this should have never happened..."); close (fd); } else { DBG (4, "(child) reader_process: finished, wrote %d bytes, expected %d " "bytes\n", byte_count, bytes_total); } return SANE_STATUS_GOOD; } /* * this code either runs in child or thread context... */ static int reader_task (void *data) { SANE_Status status; struct SIGACTION act; struct Test_Device *test_device = (struct Test_Device *) data; DBG (2, "reader_task started\n"); if (sanei_thread_is_forked ()) { DBG (3, "reader_task started (forked)\n"); close (test_device->pipe); test_device->pipe = -1; } else { DBG (3, "reader_task started (as thread)\n"); } memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); status = reader_process (test_device, test_device->reader_fds); DBG (2, "(child) reader_task: reader_process finished (%s)\n", sane_strstatus (status)); return (int) status; } static SANE_Status finish_pass (Test_Device * test_device) { SANE_Status return_status = SANE_STATUS_GOOD; DBG (2, "finish_pass: test_device=%p\n", (void *) test_device); test_device->scanning = SANE_FALSE; if (test_device->pipe >= 0) { DBG (2, "finish_pass: closing pipe\n"); close (test_device->pipe); DBG (2, "finish_pass: pipe closed\n"); test_device->pipe = -1; } if (sanei_thread_is_valid (test_device->reader_pid)) { int status; SANE_Pid pid; DBG (2, "finish_pass: terminating reader process %ld\n", (long) test_device->reader_pid); sanei_thread_kill (test_device->reader_pid); pid = sanei_thread_waitpid (test_device->reader_pid, &status); if (!sanei_thread_is_valid (pid)) { DBG (1, "finish_pass: sanei_thread_waitpid failed, already terminated? (%s)\n", strerror (errno)); } else { DBG (2, "finish_pass: reader process terminated with status: %s\n", sane_strstatus (status)); } test_device->reader_pid = -1; } /* this happens when running in thread context... */ if (test_device->reader_fds >= 0) { DBG (2, "finish_pass: closing reader pipe\n"); close (test_device->reader_fds); DBG (2, "finish_pass: reader pipe closed\n"); test_device->reader_fds = -1; } return return_status; } static void print_options (Test_Device * test_device) { SANE_Option_Descriptor *od; SANE_Word option_number; SANE_Char caps[1024]; for (option_number = 0; option_number < num_options; option_number++) { od = &test_device->opt[option_number]; DBG (0, "-----> number: %d\n", option_number); DBG (0, " name: `%s'\n", od->name); DBG (0, " title: `%s'\n", od->title); DBG (0, " description: `%s'\n", od->desc); DBG (0, " type: %s\n", od->type == SANE_TYPE_BOOL ? "SANE_TYPE_BOOL" : od->type == SANE_TYPE_INT ? "SANE_TYPE_INT" : od->type == SANE_TYPE_FIXED ? "SANE_TYPE_FIXED" : od->type == SANE_TYPE_STRING ? "SANE_TYPE_STRING" : od->type == SANE_TYPE_BUTTON ? "SANE_TYPE_BUTTON" : od->type == SANE_TYPE_GROUP ? "SANE_TYPE_GROUP" : "unknown"); DBG (0, " unit: %s\n", od->unit == SANE_UNIT_NONE ? "SANE_UNIT_NONE" : od->unit == SANE_UNIT_PIXEL ? "SANE_UNIT_PIXEL" : od->unit == SANE_UNIT_BIT ? "SANE_UNIT_BIT" : od->unit == SANE_UNIT_MM ? "SANE_UNIT_MM" : od->unit == SANE_UNIT_DPI ? "SANE_UNIT_DPI" : od->unit == SANE_UNIT_PERCENT ? "SANE_UNIT_PERCENT" : od->unit == SANE_UNIT_MICROSECOND ? "SANE_UNIT_MICROSECOND" : "unknown"); DBG (0, " size: %d\n", od->size); caps[0] = '\0'; if (od->cap & SANE_CAP_SOFT_SELECT) strcat (caps, "SANE_CAP_SOFT_SELECT "); if (od->cap & SANE_CAP_HARD_SELECT) strcat (caps, "SANE_CAP_HARD_SELECT "); if (od->cap & SANE_CAP_SOFT_DETECT) strcat (caps, "SANE_CAP_SOFT_DETECT "); if (od->cap & SANE_CAP_EMULATED) strcat (caps, "SANE_CAP_EMULATED "); if (od->cap & SANE_CAP_AUTOMATIC) strcat (caps, "SANE_CAP_AUTOMATIC "); if (od->cap & SANE_CAP_INACTIVE) strcat (caps, "SANE_CAP_INACTIVE "); if (od->cap & SANE_CAP_ADVANCED) strcat (caps, "SANE_CAP_ADVANCED "); DBG (0, " capabilities: %s\n", caps); DBG (0, "constraint type: %s\n", od->constraint_type == SANE_CONSTRAINT_NONE ? "SANE_CONSTRAINT_NONE" : od->constraint_type == SANE_CONSTRAINT_RANGE ? "SANE_CONSTRAINT_RANGE" : od->constraint_type == SANE_CONSTRAINT_WORD_LIST ? "SANE_CONSTRAINT_WORD_LIST" : od->constraint_type == SANE_CONSTRAINT_STRING_LIST ? "SANE_CONSTRAINT_STRING_LIST" : "unknown"); } } /***************************** SANE API ****************************/ SANE_Status sane_init (SANE_Int * __sane_unused__ version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; SANE_Int linenumber; SANE_Char line[PATH_MAX], *word = NULL; SANE_String_Const cp; SANE_Device *sane_device; Test_Device *test_device, *previous_device; SANE_Int num; DBG_INIT (); sanei_thread_init (); test_device = 0; previous_device = 0; DBG (1, "sane_init: SANE test backend version %d.%d.%d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); if (inited) DBG (3, "sane_init: warning: already inited\n"); fp = sanei_config_open (TEST_CONFIG_FILE); if (fp) { linenumber = 0; DBG (4, "sane_init: reading config file `%s'\n", TEST_CONFIG_FILE); while (sanei_config_read (line, sizeof (line), fp)) { if (word) free (word); word = NULL; linenumber++; cp = sanei_config_get_string (line, &word); if (!word || cp == line) { DBG (5, "sane_init: config file line %3d: ignoring empty line\n", linenumber); continue; } if (word[0] == '#') { DBG (5, "sane_init: config file line %3d: ignoring comment line\n", linenumber); continue; } DBG (5, "sane_init: config file line %3d: `%s'\n", linenumber, line); if (read_option (line, "number_of_devices", param_int, &init_number_of_devices) == SANE_STATUS_GOOD) continue; if (read_option (line, "mode", param_string, &init_mode) == SANE_STATUS_GOOD) continue; if (read_option (line, "hand-scanner", param_bool, &init_hand_scanner) == SANE_STATUS_GOOD) continue; if (read_option (line, "three-pass", param_bool, &init_three_pass) == SANE_STATUS_GOOD) continue; if (read_option (line, "three-pass-order", param_string, &init_three_pass_order) == SANE_STATUS_GOOD) continue; if (read_option (line, "resolution_min", param_fixed, &resolution_range.min) == SANE_STATUS_GOOD) continue; if (read_option (line, "resolution_max", param_fixed, &resolution_range.max) == SANE_STATUS_GOOD) continue; if (read_option (line, "resolution_quant", param_fixed, &resolution_range.quant) == SANE_STATUS_GOOD) continue; if (read_option (line, "resolution", param_fixed, &init_resolution) == SANE_STATUS_GOOD) continue; if (read_option (line, "depth", param_int, &init_depth) == SANE_STATUS_GOOD) continue; if (read_option (line, "scan-source", param_string, &init_scan_source) == SANE_STATUS_GOOD) continue; if (read_option (line, "test-picture", param_string, &init_test_picture) == SANE_STATUS_GOOD) continue; if (read_option (line, "invert-endianess", param_bool, &init_invert_endianess) == SANE_STATUS_GOOD) continue; if (read_option (line, "read-limit", param_bool, &init_read_limit) == SANE_STATUS_GOOD) continue; if (read_option (line, "read-limit-size", param_int, &init_read_limit_size) == SANE_STATUS_GOOD) continue; if (read_option (line, "read-delay", param_bool, &init_read_delay) == SANE_STATUS_GOOD) continue; if (read_option (line, "read-delay-duration", param_int, &init_read_delay_duration) == SANE_STATUS_GOOD) continue; if (read_option (line, "read-status-code", param_string, &init_read_status_code) == SANE_STATUS_GOOD) continue; if (read_option (line, "ppl-loss", param_int, &init_ppl_loss) == SANE_STATUS_GOOD) continue; if (read_option (line, "fuzzy-parameters", param_bool, &init_fuzzy_parameters) == SANE_STATUS_GOOD) continue; if (read_option (line, "non-blocking", param_bool, &init_non_blocking) == SANE_STATUS_GOOD) continue; if (read_option (line, "select-fd", param_bool, &init_select_fd) == SANE_STATUS_GOOD) continue; if (read_option (line, "enable-test-options", param_bool, &init_enable_test_options) == SANE_STATUS_GOOD) continue; if (read_option (line, "geometry_min", param_fixed, &geometry_range.min) == SANE_STATUS_GOOD) continue; if (read_option (line, "geometry_max", param_fixed, &geometry_range.max) == SANE_STATUS_GOOD) continue; if (read_option (line, "geometry_quant", param_fixed, &geometry_range.quant) == SANE_STATUS_GOOD) continue; if (read_option (line, "tl_x", param_fixed, &init_tl_x) == SANE_STATUS_GOOD) continue; if (read_option (line, "tl_y", param_fixed, &init_tl_y) == SANE_STATUS_GOOD) continue; if (read_option (line, "br_x", param_fixed, &init_br_x) == SANE_STATUS_GOOD) continue; if (read_option (line, "br_y", param_fixed, &init_br_y) == SANE_STATUS_GOOD) continue; DBG (3, "sane-init: I don't know how to handle option `%s'\n", word); } /* while */ if (word) free (word); fclose (fp); } /* if */ else { DBG (3, "sane_init: couldn't find config file (%s), using default " "settings\n", TEST_CONFIG_FILE); } /* create devices */ sane_device_list = malloc ((init_number_of_devices + 1) * sizeof (sane_device)); if (!sane_device_list) return SANE_STATUS_NO_MEM; for (num = 0; num < init_number_of_devices; num++) { SANE_Char number_string[PATH_MAX]; test_device = malloc (sizeof (*test_device)); if (!test_device) return SANE_STATUS_NO_MEM; test_device->sane.vendor = "Noname"; test_device->sane.type = "virtual device"; test_device->sane.model = "frontend-tester"; snprintf (number_string, sizeof (number_string), "%d", num); number_string[sizeof (number_string) - 1] = '\0'; test_device->name = strdup (number_string); if (!test_device->name) return SANE_STATUS_NO_MEM; test_device->sane.name = test_device->name; if (previous_device) previous_device->next = test_device; previous_device = test_device; if (num == 0) first_test_device = test_device; sane_device_list[num] = &test_device->sane; test_device->open = SANE_FALSE; test_device->eof = SANE_FALSE; test_device->scanning = SANE_FALSE; test_device->cancelled = SANE_FALSE; test_device->reader_pid = -1; test_device->pipe = -1; DBG (4, "sane_init: new device: `%s' is a %s %s %s\n", test_device->sane.name, test_device->sane.vendor, test_device->sane.model, test_device->sane.type); } test_device->next = 0; sane_device_list[num] = 0; srand (time (NULL)); random_factor = ((double) rand ()) / RAND_MAX + 0.5; inited = SANE_TRUE; return SANE_STATUS_GOOD; } void sane_exit (void) { Test_Device *test_device, *previous_device; DBG (2, "sane_exit\n"); if (!inited) { DBG (1, "sane_exit: not inited, call sane_init() first\n"); return; } test_device = first_test_device; while (test_device) { DBG (4, "sane_exit: freeing device %s\n", test_device->name); previous_device = test_device; test_device = test_device->next; if (previous_device->name) free (previous_device->name); free (previous_device); } DBG (4, "sane_exit: freeing device list\n"); if (sane_device_list) free (sane_device_list); sane_device_list = NULL; first_test_device = NULL; inited = SANE_FALSE; return; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n", (void *) device_list, local_only); if (!inited) { DBG (1, "sane_get_devices: not inited, call sane_init() first\n"); return SANE_STATUS_INVAL; } if (!device_list) { DBG (1, "sane_get_devices: device_list == 0\n"); return SANE_STATUS_INVAL; } *device_list = (const SANE_Device **) sane_device_list; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Test_Device *test_device = first_test_device; SANE_Status status; DBG (2, "sane_open: devicename = \"%s\", handle=%p\n", devicename, (void *) handle); if (!inited) { DBG (1, "sane_open: not inited, call sane_init() first\n"); return SANE_STATUS_INVAL; } if (!handle) { DBG (1, "sane_open: handle == 0\n"); return SANE_STATUS_INVAL; } if (!devicename || strlen (devicename) == 0) { DBG (2, "sane_open: device name NULL or empty\n"); } else { for (test_device = first_test_device; test_device; test_device = test_device->next) { if (strcmp (devicename, test_device->name) == 0) break; } } if (!test_device) { DBG (1, "sane_open: device `%s' not found\n", devicename); return SANE_STATUS_INVAL; } if (test_device->open) { DBG (1, "sane_open: device `%s' already open\n", devicename); return SANE_STATUS_DEVICE_BUSY; } DBG (2, "sane_open: opening device `%s', handle = %p\n", test_device->name, (void *) test_device); test_device->open = SANE_TRUE; *handle = test_device; status = init_options (test_device); if (status != SANE_STATUS_GOOD) return status; test_device->open = SANE_TRUE; test_device->scanning = SANE_FALSE; test_device->cancelled = SANE_FALSE; test_device->eof = SANE_FALSE; test_device->bytes_total = 0; test_device->pass = 0; test_device->number_of_scans = 0; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Test_Device *test_device = handle; DBG (2, "sane_close: handle=%p\n", (void *) handle); if (!inited) { DBG (1, "sane_close: not inited, call sane_init() first\n"); return; } if (!check_handle (handle)) { DBG (1, "sane_close: handle %p unknown\n", (void *) handle); return; } if (!test_device->open) { DBG (1, "sane_close: handle %p not open\n", (void *) handle); return; } test_device->open = SANE_FALSE; return; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Test_Device *test_device = handle; DBG (4, "sane_get_option_descriptor: handle=%p, option = %d\n", (void *) handle, option); if (!inited) { DBG (1, "sane_get_option_descriptor: not inited, call sane_init() " "first\n"); return 0; } if (!check_handle (handle)) { DBG (1, "sane_get_option_descriptor: handle %p unknown\n", (void *) handle); return 0; } if (!test_device->open) { DBG (1, "sane_get_option_descriptor: not open\n"); return 0; } if (option < 0 || option >= num_options) { DBG (3, "sane_get_option_descriptor: option < 0 || " "option > num_options\n"); return 0; } test_device->loaded[option] = 1; return &test_device->opt[option]; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { Test_Device *test_device = handle; SANE_Int myinfo = 0; SANE_Status status; DBG (4, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", (void *) handle, option, action, (void *) value, (void *) info); if (!inited) { DBG (1, "sane_control_option: not inited, call sane_init() first\n"); return SANE_STATUS_INVAL; } if (!check_handle (handle)) { DBG (1, "sane_control_option: handle %p unknown\n", (void *) handle); return SANE_STATUS_INVAL; } if (!test_device->open) { DBG (1, "sane_control_option: not open\n"); return SANE_STATUS_INVAL; } if (test_device->scanning) { DBG (1, "sane_control_option: is scanning\n"); return SANE_STATUS_INVAL; } if (option < 0 || option >= num_options) { DBG (1, "sane_control_option: option < 0 || option > num_options\n"); return SANE_STATUS_INVAL; } if (!test_device->loaded[option]) { DBG (1, "sane_control_option: option not loaded\n"); return SANE_STATUS_INVAL; } if (!SANE_OPTION_IS_ACTIVE (test_device->opt[option].cap)) { DBG (1, "sane_control_option: option is inactive\n"); return SANE_STATUS_INVAL; } if (test_device->opt[option].type == SANE_TYPE_GROUP) { DBG (1, "sane_control_option: option is a group\n"); return SANE_STATUS_INVAL; } switch (action) { case SANE_ACTION_SET_AUTO: if (!SANE_OPTION_IS_SETTABLE (test_device->opt[option].cap)) { DBG (1, "sane_control_option: option is not setable\n"); return SANE_STATUS_INVAL; } if (!(test_device->opt[option].cap & SANE_CAP_AUTOMATIC)) { DBG (1, "sane_control_option: option is not automatically " "setable\n"); return SANE_STATUS_INVAL; } switch (option) { case opt_bool_soft_select_soft_detect_auto: test_device->val[option].w = SANE_TRUE; DBG (4, "sane_control_option: set option %d (%s) automatically " "to %s\n", option, test_device->opt[option].name, test_device->val[option].w == SANE_TRUE ? "true" : "false"); break; default: DBG (1, "sane_control_option: trying to automatically set " "unexpected option\n"); return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE (test_device->opt[option].cap)) { DBG (1, "sane_control_option: option is not setable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (&test_device->opt[option], value, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (3, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } switch (option) { case opt_tl_x: /* Fixed with parameter reloading */ case opt_tl_y: case opt_br_x: case opt_br_y: case opt_resolution: if (test_device->val[option].w == *(SANE_Fixed *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Fixed *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; DBG (4, "sane_control_option: set option %d (%s) to %.0f %s\n", option, test_device->opt[option].name, SANE_UNFIX (*(SANE_Fixed *) value), test_device->opt[option].unit == SANE_UNIT_MM ? "mm" : "dpi"); break; case opt_fixed: /* Fixed */ case opt_fixed_constraint_range: if (test_device->val[option].w == *(SANE_Fixed *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Fixed *) value; DBG (4, "sane_control_option: set option %d (%s) to %.0f\n", option, test_device->opt[option].name, SANE_UNFIX (*(SANE_Fixed *) value)); break; case opt_read_limit_size: /* Int */ case opt_ppl_loss: case opt_read_delay_duration: case opt_int: case opt_int_constraint_range: if (test_device->val[option].w == *(SANE_Int *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Int *) value; DBG (4, "sane_control_option: set option %d (%s) to %d\n", option, test_device->opt[option].name, *(SANE_Int *) value); break; case opt_fuzzy_parameters: /* Bool with parameter reloading */ if (test_device->val[option].w == *(SANE_Bool *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Bool *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; case opt_invert_endianess: /* Bool */ case opt_non_blocking: case opt_select_fd: case opt_bool_soft_select_soft_detect: case opt_bool_soft_select_soft_detect_auto: case opt_bool_soft_select_soft_detect_emulated: if (test_device->val[option].w == *(SANE_Bool *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Bool *) value; DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; case opt_depth: /* Word list with parameter and options reloading */ if (test_device->val[option].w == *(SANE_Int *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Int *) value; if (test_device->val[option].w == 16) test_device->opt[opt_invert_endianess].cap &= ~SANE_CAP_INACTIVE; else test_device->opt[opt_invert_endianess].cap |= SANE_CAP_INACTIVE; myinfo |= SANE_INFO_RELOAD_PARAMS; myinfo |= SANE_INFO_RELOAD_OPTIONS; DBG (4, "sane_control_option: set option %d (%s) to %d\n", option, test_device->opt[option].name, *(SANE_Int *) value); break; case opt_three_pass_order: /* String list with parameter reload */ if (strcmp (test_device->val[option].s, value) == 0) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } strcpy (test_device->val[option].s, (SANE_String) value); myinfo |= SANE_INFO_RELOAD_PARAMS; DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, (SANE_String) value); break; case opt_int_constraint_word_list: /* Word list */ case opt_fixed_constraint_word_list: if (test_device->val[option].w == *(SANE_Int *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Int *) value; DBG (4, "sane_control_option: set option %d (%s) to %d\n", option, test_device->opt[option].name, *(SANE_Int *) value); break; case opt_read_status_code: /* String (list) */ case opt_test_picture: case opt_string: case opt_string_constraint_string_list: case opt_string_constraint_long_string_list: case opt_scan_source: if (strcmp (test_device->val[option].s, value) == 0) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } strcpy (test_device->val[option].s, (SANE_String) value); DBG (4, "sane_control_option: set option %d (%s) to `%s'\n", option, test_device->opt[option].name, (SANE_String) value); break; case opt_int_array: /* Word array */ case opt_int_array_constraint_range: case opt_int_array_constraint_word_list: memcpy (test_device->val[option].wa, value, test_device->opt[option].size); DBG (4, "sane_control_option: set option %d (%s) to %p\n", option, test_device->opt[option].name, (void *) value); break; /* options with side-effects */ case opt_print_options: DBG (4, "sane_control_option: set option %d (%s)\n", option, test_device->opt[option].name); print_options (test_device); break; case opt_button: DBG (0, "Yes! You pressed me!\n"); DBG (4, "sane_control_option: set option %d (%s)\n", option, test_device->opt[option].name); break; case opt_mode: if (strcmp (test_device->val[option].s, value) == 0) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } strcpy (test_device->val[option].s, (SANE_String) value); myinfo |= SANE_INFO_RELOAD_PARAMS; myinfo |= SANE_INFO_RELOAD_OPTIONS; if (strcmp (test_device->val[option].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { test_device->opt[opt_three_pass].cap &= ~SANE_CAP_INACTIVE; if (test_device->val[opt_three_pass].w == SANE_TRUE) test_device->opt[opt_three_pass_order].cap &= ~SANE_CAP_INACTIVE; } else { test_device->opt[opt_three_pass].cap |= SANE_CAP_INACTIVE; test_device->opt[opt_three_pass_order].cap |= SANE_CAP_INACTIVE; } DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, (SANE_String) value); break; case opt_three_pass: if (test_device->val[option].w == *(SANE_Bool *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Bool *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; myinfo |= SANE_INFO_RELOAD_OPTIONS; if (test_device->val[option].w == SANE_TRUE) test_device->opt[opt_three_pass_order].cap &= ~SANE_CAP_INACTIVE; else test_device->opt[opt_three_pass_order].cap |= SANE_CAP_INACTIVE; DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; case opt_hand_scanner: if (test_device->val[option].w == *(SANE_Bool *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Bool *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; myinfo |= SANE_INFO_RELOAD_OPTIONS; if (test_device->val[option].w == SANE_TRUE) { test_device->opt[opt_tl_x].cap |= SANE_CAP_INACTIVE; test_device->opt[opt_tl_y].cap |= SANE_CAP_INACTIVE; test_device->opt[opt_br_x].cap |= SANE_CAP_INACTIVE; test_device->opt[opt_br_y].cap |= SANE_CAP_INACTIVE; } else { test_device->opt[opt_tl_x].cap &= ~SANE_CAP_INACTIVE; test_device->opt[opt_tl_y].cap &= ~SANE_CAP_INACTIVE; test_device->opt[opt_br_x].cap &= ~SANE_CAP_INACTIVE; test_device->opt[opt_br_y].cap &= ~SANE_CAP_INACTIVE; } DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; case opt_read_limit: if (test_device->val[option].w == *(SANE_Bool *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Bool *) value; myinfo |= SANE_INFO_RELOAD_OPTIONS; if (test_device->val[option].w == SANE_TRUE) test_device->opt[opt_read_limit_size].cap &= ~SANE_CAP_INACTIVE; else test_device->opt[opt_read_limit_size].cap |= SANE_CAP_INACTIVE; DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; case opt_read_delay: if (test_device->val[option].w == *(SANE_Bool *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Bool *) value; myinfo |= SANE_INFO_RELOAD_OPTIONS; if (test_device->val[option].w == SANE_TRUE) test_device->opt[opt_read_delay_duration].cap &= ~SANE_CAP_INACTIVE; else test_device->opt[opt_read_delay_duration].cap |= SANE_CAP_INACTIVE; DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; case opt_enable_test_options: { int option_number; if (test_device->val[option].w == *(SANE_Bool *) value) { DBG (4, "sane_control_option: option %d (%s) not changed\n", option, test_device->opt[option].name); break; } test_device->val[option].w = *(SANE_Bool *) value; myinfo |= SANE_INFO_RELOAD_OPTIONS; for (option_number = opt_bool_soft_select_soft_detect; option_number < num_options; option_number++) { if (test_device->opt[option_number].type == SANE_TYPE_GROUP) continue; if (test_device->val[option].w == SANE_TRUE) test_device->opt[option_number].cap &= ~SANE_CAP_INACTIVE; else test_device->opt[option_number].cap |= SANE_CAP_INACTIVE; } DBG (4, "sane_control_option: set option %d (%s) to %s\n", option, test_device->opt[option].name, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; } default: DBG (1, "sane_control_option: trying to set unexpected option\n"); return SANE_STATUS_INVAL; } break; case SANE_ACTION_GET_VALUE: switch (option) { case opt_num_opts: *(SANE_Word *) value = num_options; DBG (4, "sane_control_option: get option 0, value = %d\n", num_options); break; case opt_tl_x: /* Fixed options */ case opt_tl_y: case opt_br_x: case opt_br_y: case opt_resolution: case opt_fixed: case opt_fixed_constraint_range: case opt_fixed_constraint_word_list: { *(SANE_Fixed *) value = test_device->val[option].w; DBG (4, "sane_control_option: get option %d (%s), value=%.1f %s\n", option, test_device->opt[option].name, SANE_UNFIX (*(SANE_Fixed *) value), test_device->opt[option].unit == SANE_UNIT_MM ? "mm" : SANE_UNIT_DPI ? "dpi" : ""); break; } case opt_hand_scanner: /* Bool options */ case opt_three_pass: case opt_invert_endianess: case opt_read_limit: case opt_read_delay: case opt_fuzzy_parameters: case opt_non_blocking: case opt_select_fd: case opt_bool_soft_select_soft_detect: case opt_bool_hard_select_soft_detect: case opt_bool_soft_detect: case opt_enable_test_options: case opt_bool_soft_select_soft_detect_emulated: case opt_bool_soft_select_soft_detect_auto: *(SANE_Bool *) value = test_device->val[option].w; DBG (4, "sane_control_option: get option %d (%s), value=%s\n", option, test_device->opt[option].name, *(SANE_Bool *) value == SANE_TRUE ? "true" : "false"); break; case opt_mode: /* String (list) options */ case opt_three_pass_order: case opt_read_status_code: case opt_test_picture: case opt_string: case opt_string_constraint_string_list: case opt_string_constraint_long_string_list: case opt_scan_source: strcpy (value, test_device->val[option].s); DBG (4, "sane_control_option: get option %d (%s), value=`%s'\n", option, test_device->opt[option].name, (SANE_String) value); break; case opt_depth: /* Int + word list options */ case opt_read_limit_size: case opt_ppl_loss: case opt_read_delay_duration: case opt_int: case opt_int_constraint_range: case opt_int_constraint_word_list: *(SANE_Int *) value = test_device->val[option].w; DBG (4, "sane_control_option: get option %d (%s), value=%d\n", option, test_device->opt[option].name, *(SANE_Int *) value); break; case opt_int_array: /* Int array */ case opt_int_array_constraint_range: case opt_int_array_constraint_word_list: memcpy (value, test_device->val[option].wa, test_device->opt[option].size); DBG (4, "sane_control_option: get option %d (%s), value=%p\n", option, test_device->opt[option].name, (void *) value); break; default: DBG (1, "sane_control_option: trying to get unexpected option\n"); return SANE_STATUS_INVAL; } break; default: DBG (1, "sane_control_option: trying unexpected action %d\n", action); return SANE_STATUS_INVAL; } if (info) *info = myinfo; if(myinfo & SANE_INFO_RELOAD_OPTIONS){ SANE_Int i = 0; for(i=1;iloaded[i] = 0; } } DBG (4, "sane_control_option: finished, info=%s %s %s \n", myinfo & SANE_INFO_INEXACT ? "inexact" : "", myinfo & SANE_INFO_RELOAD_PARAMS ? "reload_parameters" : "", myinfo & SANE_INFO_RELOAD_OPTIONS ? "reload_options" : ""); return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Test_Device *test_device = handle; SANE_Parameters *p; double res, tl_x = 0, tl_y = 0, br_x = 0, br_y = 0; SANE_String text_format, mode; SANE_Int channels = 1; DBG (2, "sane_get_parameters: handle=%p, params=%p\n", (void *) handle, (void *) params); if (!inited) { DBG (1, "sane_get_parameters: not inited, call sane_init() first\n"); return SANE_STATUS_INVAL; } if (!check_handle (handle)) { DBG (1, "sane_get_parameters: handle %p unknown\n", (void *) handle); return SANE_STATUS_INVAL; } if (!test_device->open) { DBG (1, "sane_get_parameters: handle %p not open\n", (void *) handle); return SANE_STATUS_INVAL; } res = SANE_UNFIX (test_device->val[opt_resolution].w); mode = test_device->val[opt_mode].s; p = &test_device->params; p->depth = test_device->val[opt_depth].w; if (test_device->val[opt_hand_scanner].w == SANE_TRUE) { tl_x = 0.0; br_x = 110.0; tl_y = 0.0; br_y = 170.0; p->lines = -1; test_device->lines = (SANE_Word) (res * (br_y - tl_y) / MM_PER_INCH); } else { tl_x = SANE_UNFIX (test_device->val[opt_tl_x].w); tl_y = SANE_UNFIX (test_device->val[opt_tl_y].w); br_x = SANE_UNFIX (test_device->val[opt_br_x].w); br_y = SANE_UNFIX (test_device->val[opt_br_y].w); if (tl_x > br_x) swap_double (&tl_x, &br_x); if (tl_y > br_y) swap_double (&tl_y, &br_y); test_device->lines = (SANE_Word) (res * (br_y - tl_y) / MM_PER_INCH); if (test_device->lines < 1) test_device->lines = 1; p->lines = test_device->lines; if (test_device->val[opt_fuzzy_parameters].w == SANE_TRUE && test_device->scanning == SANE_FALSE) p->lines *= random_factor; } if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { p->format = SANE_FRAME_GRAY; p->last_frame = SANE_TRUE; } else /* Color */ { if (test_device->val[opt_three_pass].w == SANE_TRUE) { if (test_device->val[opt_three_pass_order].s[test_device->pass] == 'R') p->format = SANE_FRAME_RED; else if (test_device->val[opt_three_pass_order].s[test_device->pass] == 'G') p->format = SANE_FRAME_GREEN; else p->format = SANE_FRAME_BLUE; if (test_device->pass > 1) p->last_frame = SANE_TRUE; else p->last_frame = SANE_FALSE; } else { p->format = SANE_FRAME_RGB; p->last_frame = SANE_TRUE; } } p->pixels_per_line = (SANE_Int) (res * (br_x - tl_x) / MM_PER_INCH); if (test_device->val[opt_fuzzy_parameters].w == SANE_TRUE && test_device->scanning == SANE_FALSE) p->pixels_per_line *= random_factor; if (p->pixels_per_line < 1) p->pixels_per_line = 1; if (p->format == SANE_FRAME_RGB) channels = 3; if (p->depth == 1) p->bytes_per_line = channels * (int) ((p->pixels_per_line + 7) / 8); else /* depth == 8 || depth == 16 */ p->bytes_per_line = channels * p->pixels_per_line * ((p->depth + 7) / 8); test_device->bytes_per_line = p->bytes_per_line; p->pixels_per_line -= test_device->val[opt_ppl_loss].w; if (p->pixels_per_line < 1) p->pixels_per_line = 1; test_device->pixels_per_line = p->pixels_per_line; switch (p->format) { case SANE_FRAME_GRAY: text_format = "gray"; break; case SANE_FRAME_RGB: text_format = "rgb"; break; case SANE_FRAME_RED: text_format = "red"; break; case SANE_FRAME_GREEN: text_format = "green"; break; case SANE_FRAME_BLUE: text_format = "blue"; break; default: text_format = "unknown"; break; } DBG (3, "sane_get_parameters: format=%s\n", text_format); DBG (3, "sane_get_parameters: last_frame=%s\n", p->last_frame ? "true" : "false"); DBG (3, "sane_get_parameters: lines=%d\n", p->lines); DBG (3, "sane_get_parameters: depth=%d\n", p->depth); DBG (3, "sane_get_parameters: pixels_per_line=%d\n", p->pixels_per_line); DBG (3, "sane_get_parameters: bytes_per_line=%d\n", p->bytes_per_line); if (params) *params = *p; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Test_Device *test_device = handle; int pipe_descriptor[2]; DBG (2, "sane_start: handle=%p\n", handle); if (!inited) { DBG (1, "sane_start: not inited, call sane_init() first\n"); return SANE_STATUS_INVAL; } if (!check_handle (handle)) { DBG (1, "sane_start: handle %p unknown\n", handle); return SANE_STATUS_INVAL; } if (!test_device->open) { DBG (1, "sane_start: not open\n"); return SANE_STATUS_INVAL; } if (test_device->scanning && (test_device->val[opt_three_pass].w == SANE_FALSE && strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0)) { DBG (1, "sane_start: already scanning\n"); return SANE_STATUS_INVAL; } if (strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0 && test_device->val[opt_three_pass].w == SANE_TRUE && test_device->pass > 2) { DBG (1, "sane_start: already in last pass of three\n"); return SANE_STATUS_INVAL; } if (test_device->pass == 0) { test_device->number_of_scans++; DBG (3, "sane_start: scanning page %d\n", test_device->number_of_scans); if ((strcmp (test_device->val[opt_scan_source].s, "Automatic Document Feeder") == 0) && (((test_device->number_of_scans) % 11) == 0)) { DBG (1, "sane_start: Document feeder is out of documents!\n"); return SANE_STATUS_NO_DOCS; } } test_device->scanning = SANE_TRUE; test_device->cancelled = SANE_FALSE; test_device->eof = SANE_FALSE; test_device->bytes_total = 0; sane_get_parameters (handle, 0); if (test_device->params.lines == 0) { DBG (1, "sane_start: lines == 0\n"); test_device->scanning = SANE_FALSE; return SANE_STATUS_INVAL; } if (test_device->params.pixels_per_line == 0) { DBG (1, "sane_start: pixels_per_line == 0\n"); test_device->scanning = SANE_FALSE; return SANE_STATUS_INVAL; } if (test_device->params.bytes_per_line == 0) { DBG (1, "sane_start: bytes_per_line == 0\n"); test_device->scanning = SANE_FALSE; return SANE_STATUS_INVAL; } if (pipe (pipe_descriptor) < 0) { DBG (1, "sane_start: pipe failed (%s)\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } /* create reader routine as new process or thread */ test_device->pipe = pipe_descriptor[0]; test_device->reader_fds = pipe_descriptor[1]; test_device->reader_pid = sanei_thread_begin (reader_task, (void *) test_device); if (!sanei_thread_is_valid (test_device->reader_pid)) { DBG (1, "sane_start: sanei_thread_begin failed (%s)\n", strerror (errno)); return SANE_STATUS_NO_MEM; } if (sanei_thread_is_forked ()) { close (test_device->reader_fds); test_device->reader_fds = -1; } return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { Test_Device *test_device = handle; SANE_Int max_scan_length; ssize_t bytes_read; size_t read_count; SANE_Int bytes_total = test_device->lines * test_device->bytes_per_line; DBG (4, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n", handle, data, max_length, (void *) length); if (!inited) { DBG (1, "sane_read: not inited, call sane_init() first\n"); return SANE_STATUS_INVAL; } if (!check_handle (handle)) { DBG (1, "sane_read: handle %p unknown\n", handle); return SANE_STATUS_INVAL; } if (!length) { DBG (1, "sane_read: length == NULL\n"); return SANE_STATUS_INVAL; } if (strcmp (test_device->val[opt_read_status_code].s, "Default") != 0) { SANE_String_Const sc = test_device->val[opt_read_status_code].s; DBG (3, "sane_read: setting return status to %s\n", sc); if (strcmp (sc, "SANE_STATUS_UNSUPPORTED") == 0) return SANE_STATUS_UNSUPPORTED; if (strcmp (sc, "SANE_STATUS_CANCELLED") == 0) return SANE_STATUS_CANCELLED; if (strcmp (sc, "SANE_STATUS_DEVICE_BUSY") == 0) return SANE_STATUS_DEVICE_BUSY; if (strcmp (sc, "SANE_STATUS_INVAL") == 0) return SANE_STATUS_INVAL; if (strcmp (sc, "SANE_STATUS_EOF") == 0) return SANE_STATUS_EOF; if (strcmp (sc, "SANE_STATUS_JAMMED") == 0) return SANE_STATUS_JAMMED; if (strcmp (sc, "SANE_STATUS_NO_DOCS") == 0) return SANE_STATUS_NO_DOCS; if (strcmp (sc, "SANE_STATUS_COVER_OPEN") == 0) return SANE_STATUS_COVER_OPEN; if (strcmp (sc, "SANE_STATUS_IO_ERROR") == 0) return SANE_STATUS_IO_ERROR; if (strcmp (sc, "SANE_STATUS_NO_MEM") == 0) return SANE_STATUS_NO_MEM; if (strcmp (sc, "SANE_STATUS_ACCESS_DENIED") == 0) return SANE_STATUS_ACCESS_DENIED; } max_scan_length = max_length; if (test_device->val[opt_read_limit].w == SANE_TRUE && test_device->val[opt_read_limit_size].w < max_scan_length) { max_scan_length = test_device->val[opt_read_limit_size].w; DBG (3, "sane_read: limiting max_scan_length to %d bytes\n", max_scan_length); } *length = 0; if (!data) { DBG (1, "sane_read: data == NULL\n"); return SANE_STATUS_INVAL; } if (!test_device->open) { DBG (1, "sane_read: not open\n"); return SANE_STATUS_INVAL; } if (test_device->cancelled) { DBG (1, "sane_read: scan was cancelled\n"); return SANE_STATUS_CANCELLED; } if (test_device->eof) { DBG (2, "sane_read: No more data available, sending EOF\n"); return SANE_STATUS_EOF; } if (!test_device->scanning) { DBG (1, "sane_read: not scanning (call sane_start first)\n"); return SANE_STATUS_INVAL; } read_count = max_scan_length; bytes_read = read (test_device->pipe, data, read_count); if (bytes_read == 0 || (bytes_read + test_device->bytes_total >= bytes_total)) { SANE_Status status; DBG (2, "sane_read: EOF reached\n"); status = finish_pass (test_device); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_read: finish_pass returned `%s'\n", sane_strstatus (status)); return status; } test_device->eof = SANE_TRUE; if (strcmp (test_device->val[opt_mode].s, SANE_VALUE_SCAN_MODE_COLOR) == 0 && test_device->val[opt_three_pass].w == SANE_TRUE) { test_device->pass++; if (test_device->pass > 2) test_device->pass = 0; } if (bytes_read == 0) return SANE_STATUS_EOF; } else if (bytes_read < 0) { if (errno == EAGAIN) { DBG (2, "sane_read: no data available, try again\n"); return SANE_STATUS_GOOD; } else { DBG (1, "sane_read: read returned error: %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } } *length = bytes_read; test_device->bytes_total += bytes_read; DBG (2, "sane_read: read %ld bytes of %d, total %d\n", (long) bytes_read, max_scan_length, test_device->bytes_total); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Test_Device *test_device = handle; DBG (2, "sane_cancel: handle = %p\n", handle); if (!inited) { DBG (1, "sane_cancel: not inited, call sane_init() first\n"); return; } if (!check_handle (handle)) { DBG (1, "sane_cancel: handle %p unknown\n", handle); return; } if (!test_device->open) { DBG (1, "sane_cancel: not open\n"); return; } if (test_device->cancelled) { DBG (1, "sane_cancel: scan already cancelled\n"); return; } if (!test_device->scanning) { DBG (2, "sane_cancel: scan is already finished\n"); return; } finish_pass (test_device); test_device->cancelled = SANE_TRUE; test_device->scanning = SANE_FALSE; test_device->eof = SANE_FALSE; test_device->pass = 0; return; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Test_Device *test_device = handle; DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, non_blocking); if (!inited) { DBG (1, "sane_set_io_mode: not inited, call sane_init() first\n"); return SANE_STATUS_INVAL; } if (!check_handle (handle)) { DBG (1, "sane_set_io_mode: handle %p unknown\n", handle); return SANE_STATUS_INVAL; } if (!test_device->open) { DBG (1, "sane_set_io_mode: not open\n"); return SANE_STATUS_INVAL; } if (!test_device->scanning) { DBG (1, "sane_set_io_mode: not scanning\n"); return SANE_STATUS_INVAL; } if (test_device->val[opt_non_blocking].w == SANE_TRUE) { if (fcntl (test_device->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { DBG (1, "sane_set_io_mode: can't set io mode"); return SANE_STATUS_INVAL; } } else { if (non_blocking) return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Test_Device *test_device = handle; DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", handle, fd ? "!=" : "="); if (!inited) { DBG (1, "sane_get_select_fd: not inited, call sane_init() first\n"); return SANE_STATUS_INVAL; } if (!check_handle (handle)) { DBG (1, "sane_get_select_fd: handle %p unknown\n", handle); return SANE_STATUS_INVAL; } if (!test_device->open) { DBG (1, "sane_get_select_fd: not open\n"); return SANE_STATUS_INVAL; } if (!test_device->scanning) { DBG (1, "sane_get_select_fd: not scanning\n"); return SANE_STATUS_INVAL; } if (test_device->val[opt_select_fd].w == SANE_TRUE) { *fd = test_device->pipe; return SANE_STATUS_GOOD; } return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/fujitsu-scsi.h0000664000175000017500000013743013072310726015423 00000000000000#ifndef FUJITSU_SCSI_H #define FUJITSU_SCSI_H /* * Part of SANE - Scanner Access Now Easy. * * Please see to opening comments in fujitsu.c */ /****************************************************/ #define USB_COMMAND_CODE 0x43 #define USB_COMMAND_LEN 0x1F #define USB_COMMAND_OFFSET 0x13 #define USB_COMMAND_TIME 30000 #define USB_DATA_TIME 30000 #define USB_STATUS_CODE 0x53 #define USB_STATUS_LEN 0x0D #define USB_STATUS_OFFSET 0x09 #define USB_STATUS_TIME 30000 /*static inline void */ static void setbitfield (unsigned char *pageaddr, int mask, int shift, int val) { *pageaddr = (*pageaddr & ~(mask << shift)) | ((val & mask) << shift); } /* ------------------------------------------------------------------------- */ /*static inline int */ static int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* ------------------------------------------------------------------------- */ static int getnbyte (unsigned char *pnt, int nbytes) { unsigned int result = 0; int i; #ifdef DEBUG assert (nbytes < 5); #endif for (i = 0; i < nbytes; i++) result = (result << 8) | (pnt[i] & 0xff); return result; } /* ------------------------------------------------------------------------- */ /*static inline void */ static void putnbyte (unsigned char *pnt, unsigned int value, unsigned int nbytes) { int i; #ifdef DEBUG assert (nbytes < 5); #endif for (i = nbytes - 1; i >= 0; i--) { pnt[i] = value & 0xff; value = value >> 8; } } /* ==================================================================== */ /* SCSI commands */ #define set_SCSI_opcode(out, val) out[0]=val #define set_SCSI_lun(out, val) setbitfield(out + 1, 7, 5, val) /* ==================================================================== */ /* TEST_UNIT_READY */ #define TEST_UNIT_READY_code 0x00 #define TEST_UNIT_READY_len 6 /* ==================================================================== */ /* REQUEST_SENSE */ #define REQUEST_SENSE_code 0x03 #define REQUEST_SENSE_len 6 #define RS_return_size 0x12 #define set_RS_return_size(icb,val) icb[0x04]=val /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) /* normally 0 */ #define get_RS_additional_length(b) b[0x07] /* always 10 */ #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /* valid=0 */ #define get_RS_SKSB(b) getnbyte(b+0x0f, 3) /* when RS is 0x05/0x26 bad bytes listed in sksb */ #define get_RS_offending_byte(b) getnbyte(b+0x10, 2) /* 3091 and 3092 use RS instead of ghs. RS must be 0x00/0x80 */ /* in ascq */ #define get_RS_adf_open(in) getbitfield(in+0x0d, 1, 7) #define get_RS_send_sw(in) getbitfield(in+0x0d, 1, 5) #define get_RS_scan_sw(in) getbitfield(in+0x0d, 1, 4) #define get_RS_duplex_sw(in) getbitfield(in+0x0d, 1, 2) #define get_RS_top(in) getbitfield(in+0x0d, 1, 1) #define get_RS_hopper(in) getbitfield(in+0x0d, 1, 0) /* in sksb */ #define get_RS_function(in) getbitfield(in+0x0f, 0x0f, 3) #define get_RS_density(in) getbitfield(in+0x0f, 0x07, 0) /* ==================================================================== */ /* INQUIRY */ #define INQUIRY_code 0x12 #define INQUIRY_len 6 #define INQUIRY_std_len 96 #define INQUIRY_vpd_len 204 /* unlikely maximum value */ #define set_IN_evpd(icb, val) setbitfield(icb + 1, 1, 0, val) #define set_IN_page_code(icb, val) icb[0x02]=val #define set_IN_return_size(icb,val) icb[0x04]=val #define set_IN_length(out,n) out[0x04]=n-5 #define get_IN_periph_qual(in) getbitfield(in, 0x07, 5) #define IN_periph_qual_lun 0x00 #define IN_periph_qual_nolun 0x03 #define get_IN_periph_devtype(in) getbitfield(in, 0x1f, 0) #define IN_periph_devtype_scanner 0x06 #define IN_periph_devtype_unknown 0x1f #define get_IN_response_format(in) getbitfield(in + 0x03, 0x07, 0) #define IN_recognized 0x02 #define get_IN_vendor(in, buf) strncpy(buf, (char *)in + 0x08, 0x08) #define get_IN_product(in, buf) strncpy(buf, (char *)in + 0x10, 0x010) #define get_IN_version(in, buf) strncpy(buf, (char *)in + 0x20, 0x04) #define get_IN_color_offset(in) getnbyte (in+0x2A, 2) /* offset between colors */ /* these only in some scanners */ #define get_IN_long_gray(in) getbitfield(in+0x2C, 1, 1) #define get_IN_long_color(in) getbitfield(in+0x2C, 1, 0) #define get_IN_emulation(in) getbitfield(in+0x2D, 1, 6) #define get_IN_cmp_cga(in) getbitfield(in+0x2D, 1, 5) #define get_IN_bg_back(in) getbitfield(in+0x2D, 1, 3) #define get_IN_bg_front(in) getbitfield(in+0x2D, 1, 2) #define get_IN_bg_fb(in) getbitfield(in+0x2D, 1, 1) #define get_IN_has_back(in) getbitfield(in+0x2D, 1, 0) #define get_IN_duplex_offset(in) getnbyte (in+0x2E, 2) /* the VPD response */ #define get_IN_page_length(in) in[0x04] #define get_IN_basic_x_res(in) getnbyte(in + 0x05, 2) #define get_IN_basic_y_res(in) getnbyte(in + 0x07, 2) #define get_IN_step_x_res(in) getbitfield(in+0x09, 1, 0) #define get_IN_step_y_res(in) getbitfield(in+0x09, 1, 4) #define get_IN_max_x_res(in) getnbyte(in + 0x0a, 2) #define get_IN_max_y_res(in) getnbyte(in + 0x0c, 2) #define get_IN_min_x_res(in) getnbyte(in + 0x0e, 2) #define get_IN_min_y_res(in) getnbyte(in + 0x10, 2) #define get_IN_std_res_200(in) getbitfield(in+ 0x12, 1, 0) #define get_IN_std_res_180(in) getbitfield(in+ 0x12, 1, 1) #define get_IN_std_res_160(in) getbitfield(in+ 0x12, 1, 2) #define get_IN_std_res_150(in) getbitfield(in+ 0x12, 1, 3) #define get_IN_std_res_120(in) getbitfield(in+ 0x12, 1, 4) #define get_IN_std_res_100(in) getbitfield(in+ 0x12, 1, 5) #define get_IN_std_res_75(in) getbitfield(in+ 0x12, 1, 6) #define get_IN_std_res_60(in) getbitfield(in+ 0x12, 1, 7) #define get_IN_std_res_1200(in) getbitfield(in+ 0x13, 1, 0) #define get_IN_std_res_800(in) getbitfield(in+ 0x13, 1, 1) #define get_IN_std_res_600(in) getbitfield(in+ 0x13, 1, 2) #define get_IN_std_res_480(in) getbitfield(in+ 0x13, 1, 3) #define get_IN_std_res_400(in) getbitfield(in+ 0x13, 1, 4) #define get_IN_std_res_320(in) getbitfield(in+ 0x13, 1, 5) #define get_IN_std_res_300(in) getbitfield(in+ 0x13, 1, 6) #define get_IN_std_res_240(in) getbitfield(in+ 0x13, 1, 7) #define get_IN_window_width(in) getnbyte(in + 0x14, 4) #define get_IN_window_length(in) getnbyte(in + 0x18, 4) #define get_IN_overflow(in) getbitfield(in+0x1c, 1, 0) #define get_IN_monochrome(in) getbitfield(in+0x1c, 1, 1) #define get_IN_half_tone(in) getbitfield(in+0x1c, 1, 2) #define get_IN_multilevel(in) getbitfield(in+0x1c, 1, 3) #define get_IN_monochrome_rgb(in) getbitfield(in+0x1c, 1, 5) #define get_IN_half_tone_rgb(in) getbitfield(in+0x1c, 1, 6) #define get_IN_multilevel_rgb(in) getbitfield(in+0x1c, 1, 7) /* vendor unique section */ #define get_IN_adf(in) getbitfield(in+0x20, 1, 7) #define get_IN_flatbed(in) getbitfield(in+0x20, 1, 6) #define get_IN_transparency(in) getbitfield(in+0x20, 1, 5) #define get_IN_duplex(in) getbitfield(in+0x20, 1, 4) #define get_IN_endorser_b(in) getbitfield(in+0x20, 1, 3) #define get_IN_barcode(in) getbitfield(in+0x20, 1, 2) #define get_IN_operator_panel(in) getbitfield(in+0x20, 1, 1) #define get_IN_endorser_f(in) getbitfield(in+0x20, 1, 0) #define get_IN_mp_stacker(in) getbitfield(in+0x21, 1, 7) #define get_IN_prepick(in) getbitfield(in+0x21, 1, 6) #define get_IN_mf_detect(in) getbitfield(in+0x21, 1, 5) #define get_IN_paperprot(in) getbitfield(in+0x21, 1, 4) #define get_IN_adbits(in) getbitfield(in+0x21, 0x0f, 0) #define get_IN_buffer_bytes(in) getnbyte(in + 0x22, 4) /*supported scsi commands*/ #define get_IN_has_cmd_msen10(in) getbitfield(in+0x26, 1, 1) #define get_IN_has_cmd_msel10(in) getbitfield(in+0x26, 1, 0) #define get_IN_has_cmd_lsen(in) getbitfield(in+0x27, 1, 7) #define get_IN_has_cmd_lsel(in) getbitfield(in+0x27, 1, 6) #define get_IN_has_cmd_change(in) getbitfield(in+0x27, 1, 5) #define get_IN_has_cmd_rbuff(in) getbitfield(in+0x27, 1, 4) #define get_IN_has_cmd_wbuff(in) getbitfield(in+0x27, 1, 3) #define get_IN_has_cmd_cav(in) getbitfield(in+0x27, 1, 2) #define get_IN_has_cmd_comp(in) getbitfield(in+0x27, 1, 1) #define get_IN_has_cmd_gdbs(in) getbitfield(in+0x27, 1, 0) #define get_IN_has_cmd_op(in) getbitfield(in+0x28, 1, 7) #define get_IN_has_cmd_send(in) getbitfield(in+0x28, 1, 6) #define get_IN_has_cmd_read(in) getbitfield(in+0x28, 1, 5) #define get_IN_has_cmd_gwin(in) getbitfield(in+0x28, 1, 4) #define get_IN_has_cmd_swin(in) getbitfield(in+0x28, 1, 3) #define get_IN_has_cmd_sdiag(in) getbitfield(in+0x28, 1, 2) #define get_IN_has_cmd_rdiag(in) getbitfield(in+0x28, 1, 1) #define get_IN_has_cmd_scan(in) getbitfield(in+0x28, 1, 0) #define get_IN_has_cmd_msen6(in) getbitfield(in+0x29, 1, 7) #define get_IN_has_cmd_copy(in) getbitfield(in+0x29, 1, 6) #define get_IN_has_cmd_rel(in) getbitfield(in+0x29, 1, 5) #define get_IN_has_cmd_runit(in) getbitfield(in+0x29, 1, 4) #define get_IN_has_cmd_msel6(in) getbitfield(in+0x29, 1, 3) #define get_IN_has_cmd_inq(in) getbitfield(in+0x29, 1, 2) #define get_IN_has_cmd_rs(in) getbitfield(in+0x29, 1, 1) #define get_IN_has_cmd_tur(in) getbitfield(in+0x29, 1, 0) /* more stuff here? (vendor commands) */ #define get_IN_has_cmd_subwindow(in) getbitfield(in+0x2b, 1, 0) #define get_IN_has_cmd_endorser(in) getbitfield(in+0x2b, 1, 1) #define get_IN_has_cmd_hw_status(in) getbitfield(in+0x2b, 1, 2) #define get_IN_has_cmd_hw_status_2(in) getbitfield(in+0x2b, 1, 3) #define get_IN_has_cmd_hw_status_3(in) getbitfield(in+0x2b, 1, 4) #define get_IN_has_cmd_scanner_ctl(in) getbitfield(in+0x31, 1, 1) #define get_IN_has_cmd_device_restart(in) getbitfield(in+0x31, 1, 2) #define get_IN_brightness_steps(in) getnbyte(in+0x52, 1) #define get_IN_threshold_steps(in) getnbyte(in+0x53, 1) #define get_IN_contrast_steps(in) getnbyte(in+0x54, 1) #define get_IN_num_dither_internal(in) getbitfield(in+0x56, 15, 4) #define get_IN_num_dither_download(in) getbitfield(in+0x56, 15, 0) #define get_IN_num_gamma_internal(in) getbitfield(in+0x57, 15, 4) #define get_IN_num_gamma_download(in) getbitfield(in+0x57, 15, 0) #define get_IN_ipc_bw_rif(in) getbitfield(in+0x58, 1, 7) #define get_IN_ipc_dtc(in) getbitfield(in+0x58, 1, 6) #define get_IN_ipc_sdtc(in) getbitfield(in+0x58, 1, 5) #define get_IN_ipc_outline_extraction(in) getbitfield(in+0x58, 1, 4) #define get_IN_ipc_image_emphasis(in) getbitfield(in+0x58, 1, 3) #define get_IN_ipc_auto_separation(in) getbitfield(in+0x58, 1, 2) #define get_IN_ipc_mirroring(in) getbitfield(in+0x58, 1, 1) #define get_IN_ipc_wl_follow(in) getbitfield(in+0x58, 1, 0) #define get_IN_ipc_subwindow(in) getbitfield(in+0x59, 1, 7) #define get_IN_ipc_diffusion(in) getbitfield(in+0x59, 1, 6) #define get_IN_ipc_ipc3(in) getbitfield(in+0x59, 1, 5) #define get_IN_ipc_rotation(in) getbitfield(in+0x59, 1, 4) #define get_IN_ipc_hybrid_crop_deskew(in) getbitfield(in+0x59, 1, 3) #define get_IN_ipc_ipc2_byte67(in) getbitfield(in+0x59, 1, 0) #define get_IN_compression_MH(in) getbitfield(in+0x5a, 1, 7) #define get_IN_compression_MR(in) getbitfield(in+0x5a, 1, 6) #define get_IN_compression_MMR(in) getbitfield(in+0x5a, 1, 5) #define get_IN_compression_JBIG(in) getbitfield(in+0x5a, 1, 4) #define get_IN_compression_JPG_BASE(in) getbitfield(in+0x5a, 1, 3) #define get_IN_compression_JPG_EXT(in) getbitfield(in+0x5a, 1, 2) #define get_IN_compression_JPG_INDEP(in) getbitfield(in+0x5a, 1, 1) #define get_IN_compression_JPG_gray(in) getbitfield(in+0x5b, 3, 6) #define IN_comp_JPG_gray_unsup 1 #define IN_comp_JPG_gray_color 2 #define IN_comp_JPG_gray_gray 3 #define get_IN_compression_JPG_YUV_422(in) getbitfield(in+0x5b, 1, 0) #define get_IN_endorser_b_mech(in) getbitfield(in+0x5c, 1, 7) #define get_IN_endorser_b_stamp(in) getbitfield(in+0x5c, 1, 6) #define get_IN_endorser_b_elec(in) getbitfield(in+0x5c, 1, 5) #define get_IN_endorser_max_id(in) getbitfield(in+0x5c, 0x0f, 0) #define get_IN_endorser_f_mech(in) getbitfield(in+0x5d, 1, 7) #define get_IN_endorser_f_stamp(in) getbitfield(in+0x5d, 1, 6) #define get_IN_endorser_f_elec(in) getbitfield(in+0x5d, 1, 5) #define get_IN_endorser_f_type(in) getbitfield(in+0x5d, 3, 2) #define get_IN_endorser_b_type(in) getbitfield(in+0x5d, 3, 0) #define get_IN_connection(in) getbitfield(in+0x62, 3, 0) #define get_IN_endorser_type_ext(in) getbitfield(in+0x63, 1, 4) #define get_IN_endorser_pre_back(in) getbitfield(in+0x63, 1, 3) #define get_IN_endorser_pre_front(in) getbitfield(in+0x63, 1, 2) #define get_IN_endorser_post_back(in) getbitfield(in+0x63, 1, 1) #define get_IN_endorser_post_front(in) getbitfield(in+0x63, 1, 0) #define get_IN_x_overscan_size(in) getnbyte(in + 0x64, 2) #define get_IN_y_overscan_size(in) getnbyte(in + 0x66, 2) #define get_IN_default_bg_adf_b(in) getbitfield(in+0x68, 1, 3) #define get_IN_default_bg_adf_f(in) getbitfield(in+0x68, 1, 2) #define get_IN_default_bg_fb(in) getbitfield(in+0x68, 1, 1) #define get_IN_auto_color(in) getbitfield(in+0x69, 1, 7) #define get_IN_blank_skip(in) getbitfield(in+0x69, 1, 6) #define get_IN_multi_image(in) getbitfield(in+0x69, 1, 5) #define get_IN_f_b_type_indep(in) getbitfield(in+0x69, 1, 4) #define get_IN_f_b_res_indep(in) getbitfield(in+0x69, 1, 3) #define get_IN_dropout_spec(in) getbitfield(in+0x6a, 1, 7) #define get_IN_dropout_non(in) getbitfield(in+0x6a, 1, 7) #define get_IN_dropout_white(in) getbitfield(in+0x6a, 1, 7) #define get_IN_skew_check(in) getbitfield(in+0x6d, 1, 7) #define get_IN_new_fd_roll(in) getbitfield(in+0x6d, 1, 6) #define get_IN_paper_prot_2(in) getbitfield(in+0x6d, 1, 1) #define get_IN_evpd_len(in) getnbyte(in + 0x6f, 1) #define get_IN_paper_count(in) getbitfield(in+0x70, 1, 7) #define get_IN_paper_number(in) getbitfield(in+0x70, 1, 6) #define get_IN_ext_send_to(in) getbitfield(in+0x70, 1, 5) #define get_IN_staple_det(in) getbitfield(in+0x70, 1, 4) #define get_IN_pause_host(in) getbitfield(in+0x70, 1, 3) #define get_IN_pause_panel(in) getbitfield(in+0x70, 1, 2) #define get_IN_pause_conf(in) getbitfield(in+0x70, 1, 1) #define get_IN_hq_print(in) getbitfield(in+0x70, 1, 0) #define get_IN_ext_GHS_len(in) getnbyte(in + 0x71, 1) #define get_IN_smbc_func(in) getbitfield(in+0x72, 1, 7) #define get_IN_imprint_chk_b(in) getbitfield(in+0x72, 1, 6) #define get_IN_imprint_chk_f(in) getbitfield(in+0x72, 1, 5) #define get_IN_force_w_bg(in) getbitfield(in+0x72, 1, 4) #define get_IN_mf_recover_lvl(in) getbitfield(in+0x72, 0x0f, 0) #define get_IN_first_read_time(in) getbitfield(in+0x73, 1, 7) #define get_IN_div_scanning(in) getbitfield(in+0x73, 1, 6) #define get_IN_start_job(in) getbitfield(in+0x73, 1, 5) #define get_IN_lifetime_log(in) getbitfield(in+0x73, 1, 4) #define get_IN_imff_save_rest(in) getbitfield(in+0x73, 1, 3) #define get_IN_wide_scsi_type(in) getbitfield(in+0x73, 0x07, 0) #define get_IN_lut_hybrid_crop(in) getbitfield(in+0x74, 1, 7) #define get_IN_over_under_amt(in) getbitfield(in+0x74, 1, 6) #define get_IN_rgb_lut(in) getbitfield(in+0x74, 1, 5) #define get_IN_num_lut_dl(in) getbitfield(in+0x74, 0x0f, 0) /*byte 75 is poorly documented*/ #define get_IN_erp_lot6_supp(in) getbitfield(in+0x76, 1, 7) #define get_IN_mode_change_jpeg(in) getbitfield(in+0x76, 1, 5) #define get_IN_mode_change_irdc(in) getbitfield(in+0x76, 1, 4) #define get_IN_mode_change_iomf(in) getbitfield(in+0x76, 1, 3) #define get_IN_sync_next_feed(in) getbitfield(in+0x76, 0x07, 0) #define get_IN_imp_func3(in) getbitfield(in+0x77, 1, 7) #define get_IN_reset_ms(in) getbitfield(in+0x78, 1, 7) #define get_IN_read_size(in) getbitfield(in+0x78, 1, 6) #define get_IN_start_end_ms(in) getbitfield(in+0x78, 1, 5) #define get_IN_battery(in) getbitfield(in+0x79, 1, 7) #define get_IN_battery_save(in) getbitfield(in+0x79, 1, 6) #define get_IN_op_reverse(in) getbitfield(in+0x79, 1, 1) #define get_IN_op_halt(in) getbitfield(in+0x7a, 1, 7) /* some scanners need evpd inquiry data manipulated */ #define set_IN_page_length(in,val) in[0x04]=val /* ==================================================================== */ /* page codes used by mode_sense and mode_select */ #define MS_pc_unk 0x2c /* Used by iX500 */ #define MS_pc_patch 0x2e /* Patch code scanning */ #define MS_pc_counter 0x2f /* Page number and counter reset */ #define MS_pc_autocolor 0x32 /* Automatic color detection */ #define MS_pc_prepick 0x33 /* Prepick next adf page */ #define MS_pc_sleep 0x34 /* Sleep mode */ #define MS_pc_duplex 0x35 /* ADF duplex transfer mode */ #define MS_pc_rand 0x36 /* All sorts of device controls */ #define MS_pc_bg 0x37 /* Backing switch control */ #define MS_pc_df 0x38 /* Double feed detection */ #define MS_pc_dropout 0x39 /* Drop out color */ #define MS_pc_buff 0x3a /* Scan buffer control */ #define MS_pc_auto 0x3c /* Auto paper size detection */ #define MS_pc_lamp 0x3d /* Lamp light timer set */ #define MS_pc_jobsep 0x3e /* Detect job separation sheet */ #define MS_pc_all 0x3f /* Only used with mode_sense */ /* ==================================================================== */ /* MODE_SELECT */ #define MODE_SELECT_code 0x15 #define MODE_SELECT_len 6 #define set_MSEL_pf(sb, val) setbitfield(sb + 1, 1, 4, val) #define set_MSEL_xferlen(sb, val) sb[0x04] = (unsigned char)val /* MS payloads are combined 4 byte header and 8 or 10 byte page * there is also 'descriptor block' & 'vendor-specific block' * but fujitsu seems not to use these */ /* 10 byte page only used by dropout? */ #define MSEL_header_len 4 #define MSEL_data_min_len 8 #define MSEL_data_max_len 10 #define set_MSEL_pc(sb, val) sb[0x00]=val #define set_MSEL_page_len(sb, val) sb[0x01]=val #define set_MSEL_sleep_mode(sb, val) sb[0x02]=val #define set_MSEL_transfer_mode(sb, val) setbitfield(sb + 0x02, 0x01, 0, val) #define set_MSEL_bg_enable(sb, val) setbitfield(sb + 2, 1, 7, val) #define set_MSEL_bg_front(sb, val) setbitfield(sb + 2, 1, 5, val) #define set_MSEL_bg_back(sb, val) setbitfield(sb + 2, 1, 4, val) #define set_MSEL_bg_fb(sb, val) setbitfield(sb + 2, 1, 3, val) #define set_MSEL_df_enable(sb, val) setbitfield(sb + 2, 1, 7, val) #define set_MSEL_df_continue(sb, val) setbitfield(sb + 2, 1, 6, val) #define set_MSEL_df_skew(sb, val) setbitfield(sb + 2, 1, 5, val) #define set_MSEL_df_thickness(sb, val) setbitfield(sb + 2, 1, 4, val) #define set_MSEL_df_length(sb, val) setbitfield(sb + 2, 1, 3, val) #define set_MSEL_df_diff(sb, val) setbitfield(sb + 2, 3, 0, val) #define MSEL_df_diff_DEFAULT 0 #define MSEL_df_diff_10MM 1 #define MSEL_df_diff_15MM 2 #define MSEL_df_diff_20MM 3 #define set_MSEL_df_paperprot(sb, val) setbitfield(sb + 3, 3, 6, val) #define set_MSEL_df_stapledet(sb, val) setbitfield(sb + 3, 3, 4, val) #define set_MSEL_df_recovery(sb, val) setbitfield(sb + 3, 3, 2, val) #define set_MSEL_df_paperprot2(sb, val) setbitfield(sb + 5, 3, 6, val) #define set_MSEL_dropout_front(sb, val) setbitfield(sb + 0x02, 0x0f, 0, val) #define set_MSEL_dropout_back(sb, val) setbitfield(sb + 0x02, 0x0f, 4, val) #define MSEL_dropout_DEFAULT 0 #define MSEL_dropout_GREEN 8 #define MSEL_dropout_RED 9 #define MSEL_dropout_BLUE 11 #define MSEL_dropout_CUSTOM 12 #define set_MSEL_buff_mode(sb, val) setbitfield(sb + 0x02, 0x03, 6, val) #define set_MSEL_buff_clear(sb, val) setbitfield(sb + 0x03, 0x03, 6, val) #define set_MSEL_prepick(sb, val) setbitfield(sb + 0x02, 0x03, 6, val) /*more automatic stuff with this one...*/ #define set_MSEL_awd(sb, val) setbitfield(sb + 0x02, 0x01, 7, val) #define set_MSEL_w_wfill(sb, val) setbitfield(sb + 0x02, 0x01, 6, val) #define set_MSEL_req_driv_lut(sb, val) setbitfield(sb + 0x02, 0x01, 1, val) #define set_MSEL_req_driv_crop(sb, val) setbitfield(sb + 0x02, 0x01, 0, val) #define set_MSEL_ald(sb, val) setbitfield(sb + 0x03, 0x01, 7, val) #define set_MSEL_l_wfill(sb, val) setbitfield(sb + 0x03, 0x01, 6, val) #define set_MSEL_deskew(sb, val) setbitfield(sb + 0x04, 0x01, 7, val) #define set_MSEL_overscan(sb, val) setbitfield(sb + 0x05, 0x03, 6, val) #define set_MSEL_overcrop(sb, val) setbitfield(sb + 0x05, 0x01, 5, val) #define set_MSEL_undercrop(sb, val) setbitfield(sb + 0x05, 0x01, 4, val) #define set_MSEL_over_under_amt(sb, val) sb[0x06]=val /*buffer, prepick, overscan and df use these*/ #define MSEL_DEFAULT 0 #define MSEL_OFF 2 #define MSEL_ON 3 /* ==================================================================== */ /* RESERVE_UNIT */ #define RESERVE_UNIT_code 0x16 #define RESERVE_UNIT_len 6 /* ==================================================================== */ /* RELEASE_UNIT */ #define RELEASE_UNIT_code 0x17 #define RELEASE_UNIT_len 6 /* ==================================================================== */ /* MODE_SENSE */ #define MODE_SENSE_code 0x1a #define MODE_SENSE_len 6 #define MODE_SENSE_data_len 0x14 #define set_MSEN_DBD(b, val) setbitfield(b, 0x01, 3, (val?1:0)) #define set_MSEN_pc(sb, val) setbitfield(sb + 0x02, 0x3f, 0, val) #define set_MSEN_xfer_length(sb, val) sb[0x04] = (unsigned char)val #define get_MSEN_MUD(b) getnbyte(b+(0x04+((int)*(b+0x3)))+0x4,2) /* ==================================================================== */ /* SCAN */ #define SCAN_code 0x1b #define SCAN_len 6 #define set_SC_xfer_length(sb, val) sb[0x04] = (unsigned char)val /* ==================================================================== */ /* READ_DIAGNOSTIC */ #define READ_DIAGNOSTIC_code 0x1c #define READ_DIAGNOSTIC_len 6 #define set_RD_xferlen(in, len) putnbyte(in + 3, len, 2) /* for 'FIRST READ DATE \0YMD' */ #define RD_frd_len 10 #define get_RD_date_status(in) in[0] #define RD_date_stored 0 #define RD_date_not_stored 0xff /* for 'GET FIRST DATE ' */ #define RD_gfd_len 10 #define get_RD_date_year(in) in[1] #define get_RD_date_month(in) in[2] #define get_RD_date_date(in) in[3] /* for 'GET DEVICE ID ' */ #define RD_gdi_len 10 #define get_RD_id_serial(in) getnbyte (in, 4) /* ==================================================================== */ /* SEND_DIAGNOSTIC */ #define SEND_DIAGNOSTIC_code 0x1d #define SEND_DIAGNOSTIC_len 6 #define set_SD_slftst(in, val) setbitfield(in + 1, 1, 2, val) #define set_SD_xferlen(in, len) putnbyte(in + 3, len, 2) #define SD_frd_string "FIRST READ DATE \0YMD" #define SD_frd_len 20 #define set_SD_frd_year(in, b) putnbyte(in + 0x11, b, 1) #define set_SD_frd_month(in, b) putnbyte(in + 0x12, b, 1) #define set_SD_frd_date(in, b) putnbyte(in + 0x13, b, 1) #define SD_gfd_string "GET FIRST DATE " #define SD_gfd_len 16 #define SD_gdi_string "GET DEVICE ID " #define SD_gdi_len 16 #define SD_preread_string "SET PRE READMODE" #define SD_preread_stringlen 16 #define SD_preread_len 32 #define set_SD_preread_xres(in, b) putnbyte(in + 0x10, b, 2) #define set_SD_preread_yres(in, b) putnbyte(in + 0x12, b, 2) #define set_SD_preread_paper_width(sb, val) putnbyte(sb + 0x14, val, 4) #define set_SD_preread_paper_length(sb, val) putnbyte(sb + 0x18, val, 4) #define set_SD_preread_composition(sb, val) putnbyte(sb + 0x1c, val, 1) #define set_SD_preread_escan(sb, val) putnbyte(sb + 0x1d, val, 1) #define SD_powoff_string "SET POWOFF TIME " #define SD_powoff_stringlen 16 #define SD_powoff_len 18 #define set_SD_powoff_disable(in, val) setbitfield(in + 16, 1, 7, val) #define set_SD_powoff_interval(in, val) setbitfield(in + 16, 0x7f, 0, val) #define set_SD_powoff_notify(sb, val) putnbyte(sb + 0x17, val, 1) /* ==================================================================== */ /* SET_WINDOW */ #define SET_WINDOW_code 0x24 #define SET_WINDOW_len 10 #define set_SW_xferlen(sb, len) putnbyte(sb + 0x06, len, 3) #define SW_header_len 8 #define SW_desc_len 64 /* ==================================================================== */ /* GET_WINDOW */ #define GET_WINDOW_code 0x25 #define GET_WINDOW_len 0 /* ==================================================================== */ /* READ */ #define READ_code 0x28 #define READ_len 10 #define set_R_datatype_code(sb, val) sb[0x02] = val #define R_datatype_imagedata 0x00 #define R_datatype_pixelsize 0x80 #define R_datatype_papersize 0x81 #define R_datatype_effective_id 0x82 #define set_R_window_id(sb, val) sb[0x05] = val #define set_R_xfer_length(sb, val) putnbyte(sb + 0x06, val, 3) #define R_PSIZE_len 0x20 #define get_PSIZE_num_x(in) getnbyte(in + 0x00, 4) #define get_PSIZE_num_y(in) getnbyte(in + 0x04, 4) #define get_PSIZE_paper_w(in) getnbyte(in + 0x08, 4) #define get_PSIZE_paper_l(in) getnbyte(in + 0x0C, 4) #define get_PSIZE_req_driv_crop(in) getbitfield(in + 0x10, 1, 7) #define get_PSIZE_req_driv_lut(in) getbitfield(in + 0x10, 1, 6) #define get_PSIZE_req_driv_valid(in) getbitfield(in + 0x10, 1, 0) #define R_PAPER_len 0x08 #define get_PAPER_job_sep(in) getnbyte(in + 0x02, 1) #define get_PAPER_paper_w(in) getnbyte(in + 0x03, 1) /* ==================================================================== */ /* SEND */ #define SEND_code 0x2a #define SEND_len 10 #define set_S_xfer_datatype(sb, val) sb[0x02] = (unsigned char)val #define S_datatype_halftone_mask 0x02 #define S_datatype_gamma_function 0x03 #define S_datatype_lut_data 0x83 #define S_datatype_lut_dropout 0x84 #define S_datatype_jpg_q_table 0x88 #define S_datatype_endorser_data 0x90 #define S_datatype_sendto_name 0xa0 /*#define S_EX_datatype_lut 0x01 #define S_EX_datatype_shading_data 0xa0 #define S_user_reg_gamma 0xc0 #define S_device_internal_info 0x03 #define set_S_datatype_qual_upper(sb, val) sb[0x04] = (unsigned char)val #define S_DQ_none 0x00 #define S_DQ_Rcomp 0x06 #define S_DQ_Gcomp 0x07 #define S_DQ_Bcomp 0x08 #define S_DQ_Reg1 0x01 #define S_DQ_Reg2 0x02 #define S_DQ_Reg3 0x03*/ #define set_S_xfer_id(sb, val) putnbyte(sb + 4, val, 2) #define set_S_xfer_length(sb, val) putnbyte(sb + 6, val, 3) /*lut*/ #define S_lut_header_len 0x0a #define set_S_lut_order(sb, val) putnbyte(sb + 2, val, 1) #define S_lut_order_single 0x10 #define set_S_lut_ssize(sb, val) putnbyte(sb + 4, val, 2) #define set_S_lut_dsize(sb, val) putnbyte(sb + 6, val, 2) #define S_lut_data_min_len 256 #define S_lut_data_max_len 1024 /*q-table*/ #define S_q_table_header_len 0x0a #define S_q_table_y_len 0x40 #define set_S_q_table_y_len(sb, val) putnbyte(sb + 4, val, 2) #define S_q_table_uv_len 0x40 #define set_S_q_table_uv_len(sb, val) putnbyte(sb + 6, val, 2) /*endorser*/ #define S_e_data_min_len 18 /*minimum 18 bytes no string bytes*/ #define S_e_data_max_len 98 /*maximum 18 bytes plus 80 string bytes*/ #define set_S_endorser_data_id(sb, val) sb[0] = val #define set_S_endorser_stamp(sb, val) setbitfield(sb + 0x01, 1, 7, val) #define set_S_endorser_elec(sb, val) setbitfield(sb + 0x01, 1, 6, val) #define set_S_endorser_decr(sb, val) setbitfield(sb + 0x01, 1, 5, val) #define S_e_decr_inc 0 #define S_e_decr_dec 1 #define set_S_endorser_lap24(sb, val) setbitfield(sb + 0x01, 1, 4, val) #define S_e_lap_24bit 1 #define S_e_lap_16bit 0 #define set_S_endorser_ctstep(sb, val) setbitfield(sb + 0x01, 0x03, 0, val) #define set_S_endorser_ulx(sb, val) putnbyte(sb + 0x02, val, 4) #define set_S_endorser_uly(sb, val) putnbyte(sb + 0x06, val, 4) #define set_S_endorser_font(sb, val) sb[0xa] = val #define S_e_font_horiz 0 #define S_e_font_vert 1 #define S_e_font_horiz_narrow 2 #define set_S_endorser_size(sb, val) sb[0xb] = val #define set_S_endorser_revs(sb, val) setbitfield(sb + 0x0c, 0x01, 7, val) #define S_e_revs_fwd 0 #define S_e_revs_rev 1 #define set_S_endorser_bold(sb, val) setbitfield(sb + 0x0c, 0x01, 2, val) #define set_S_endorser_dirs(sb, val) setbitfield(sb + 0x0c, 0x03, 0, val) #define S_e_dir_left_right 0 #define S_e_dir_top_bottom 1 #define S_e_dir_right_left 2 #define S_e_dir_bottom_top 3 #define set_S_endorser_string_length(sb, len) sb[0x11] = len #define set_S_endorser_string(sb,val,len) memcpy(sb+0x12,val,(size_t)len) /* ==================================================================== */ /* OBJECT_POSITION */ #define OBJECT_POSITION_code 0x31 #define OBJECT_POSITION_len 10 #define set_OP_action(b,val) setbitfield(b+0x01, 0x07, 0, val) #define OP_Discharge 0x00 #define OP_Feed 0x01 #define OP_Halt 0x04 /* ==================================================================== */ /* SET_SUBWINDOW */ #define SET_SUBWINDOW_code 0xc0 #define SET_SUBWINDOW_len 0 /* ==================================================================== */ /* ENDORSER */ #define ENDORSER_code 0xc1 #define ENDORSER_len 10 #define set_E_xferlen(sb, val) putnbyte(sb + 0x7, val, 2) /*endorser data*/ #define ED_min_len 4 #define ED_max_len 6 #define set_ED_endorser_data_id(sb, val) sb[0] = val /* enable/disable endorser printing*/ #define set_ED_stop(sb, val) setbitfield(sb + 0x01, 1, 7, val) #define ED_start 0 #define ED_stop 1 /* specifies the side of a document to be printed */ #define set_ED_side(sb, val) setbitfield(sb + 0x01, 1, 6, val) #define ED_front 0 #define ED_back 1 /* format of the counter 16/24 bit*/ #define set_ED_lap24(sb, val) setbitfield(sb + 0x01, 1, 5, val) #define ED_lap_16bit 0 #define ED_lap_24bit 1 /* initial count */ #define set_ED_initial_count_16(sb, val) putnbyte(sb + 0x02, val, 2) #define set_ED_initial_count_24(sb, val) putnbyte(sb + 0x03, val, 3) /* ==================================================================== */ /* GET_HW_STATUS*/ #define GET_HW_STATUS_code 0xc2 #define GET_HW_STATUS_len 10 #define set_GHS_allocation_length(sb, len) putnbyte(sb + 0x07, len, 2) #define GHS_data_len 12 #define get_GHS_top(in) getbitfield(in+0x02, 1, 7) #define get_GHS_fedalm(in) getbitfield(in+0x02, 1, 5) #define get_GHS_adjalm(in) getbitfield(in+0x02, 1, 4) #define get_GHS_A3(in) getbitfield(in+0x02, 1, 3) #define get_GHS_B4(in) getbitfield(in+0x02, 1, 2) #define get_GHS_A4(in) getbitfield(in+0x02, 1, 1) #define get_GHS_B5(in) getbitfield(in+0x02, 1, 0) #define get_GHS_hopper(in) !getbitfield(in+0x03, 1, 7) #define get_GHS_omr(in) getbitfield(in+0x03, 1, 6) #define get_GHS_adf_open(in) getbitfield(in+0x03, 1, 5) #define get_GHS_imp_open(in) getbitfield(in+0x03, 1, 4) #define get_GHS_fb_open(in) getbitfield(in+0x03, 1, 3) #define get_GHS_paper_end(in) getbitfield(in+0x03, 1, 2) #define get_GHS_fb_on(in) getbitfield(in+0x03, 1, 1) #define get_GHS_sleep(in) getbitfield(in+0x04, 1, 7) #define get_GHS_clean(in) getbitfield(in+0x04, 1, 6) #define get_GHS_scan_sw_long(in) getbitfield(in+0x04, 1, 5) #define get_GHS_hpos(in) getbitfield(in+0x04, 1, 4) #define get_GHS_send_sw(in) getbitfield(in+0x04, 1, 2) #define get_GHS_manual_feed(in) getbitfield(in+0x04, 1, 1) #define get_GHS_scan_sw(in) getbitfield(in+0x04, 1, 0) #define get_GHS_picalm(in) getbitfield(in+0x05, 1, 7) #define get_GHS_padalm(in) getbitfield(in+0x05, 1, 6) #define get_GHS_brkalm(in) getbitfield(in+0x05, 1, 5) #define get_GHS_sepalm(in) getbitfield(in+0x05, 1, 4) #define get_GHS_function(in) getbitfield(in+0x05, 0x0f, 0) #define get_GHS_ink_empty(in) getbitfield(in+0x06, 1, 7) #define get_GHS_consume(in) getbitfield(in+0x06, 1, 6) #define get_GHS_overskew(in) getbitfield(in+0x06, 1, 5) #define get_GHS_overthick(in) getbitfield(in+0x06, 1, 4) #define get_GHS_plen(in) getbitfield(in+0x06, 1, 3) #define get_GHS_ink_side(in) getbitfield(in+0x06, 1, 2) #define get_GHS_mf_to(in) getbitfield(in+0x06, 1, 1) #define get_GHS_double_feed(in) getbitfield(in+0x06, 1, 0) #define get_GHS_error_code(in) in[0x07] #define get_GHS_skew_angle(in) in[0x09] #define get_GHS_ink_remain(in) in[0x0a] #define get_GHS_lang_code(in) getnbyte(in+0x0c, 2) #define get_GHS_adjalm_fed(in) getbitfield(in+0x0e, 1, 7) #define get_GHS_non_sep(in) getbitfield(in+0x0e, 1, 4) #define get_GHS_ext_sendto(in) getbitfield(in+0x0e, 1, 2) #define get_GHS_rq_hldimg(in) getbitfield(in+0x0e, 1, 1) #define get_GHS_pacnt(in) getbitfield(in+0x0e, 1, 0) #define get_GHS_wifi_sw(in) getbitfield(in+0x10, 1, 7) #define get_GHS_w_use(in) getbitfield(in+0x10, 1, 6) #define get_GHS_w_use2(in) getbitfield(in+0x10, 1, 5) #define get_GHS_w_use3(in) getbitfield(in+0x10, 1, 4) #define get_GHS_w_use4(in) getbitfield(in+0x10, 1, 3) #define get_GHS_battery(in) getbitfield(in+0x11, 1, 7) #define get_GHS_btr_charge(in) getbitfield(in+0x11, 1, 6) #define get_GHS_btr_chg_tmp_stp(in) getbitfield(in+0x11, 1, 5) #define get_GHS_ibtr_ene_sav(in) getbitfield(in+0x11, 1, 4) #define get_GHS_fngr_caut(in) getbitfield(in+0x11, 1, 2) #define get_GHS_trnpg_l(in) getbitfield(in+0x11, 1, 1) #define get_GHS_trnpg_r(in) getbitfield(in+0x11, 1, 0) #define get_GHS_btr_power(in) in[0x12] /* ==================================================================== */ /* SCANNER_CONTROL */ #define SCANNER_CONTROL_code 0xf1 #define SCANNER_CONTROL_len 10 #define set_SC_ric(icb, val) setbitfield(icb + 1, 1, 4, val) #define set_SC_function(icb, val) setbitfield(icb + 1, 0xf, 0, val) #define SC_function_adf 0x00 #define SC_function_fb 0x01 #define SC_function_fb_hs 0x02 #define SC_function_lamp_off 0x03 #define SC_function_cancel 0x04 #define SC_function_lamp_on 0x05 #define SC_function_lamp_normal 0x06 #define SC_function_lamp_saving 0x07 #define SC_function_panel 0x08 #define SC_function_scan_complete 0x09 #define SC_function_eject_complete 0x0a #define SC_function_manual_feed 0x0c /* used with SC_function_panel */ #define set_SC_led_eb(icb, val) setbitfield(icb + 5, 1, 7, val) #define set_SC_led(icb, val) setbitfield(icb + 5, 1, 6, val) #define set_SC_fcno_eb(icb, val) setbitfield(icb + 5, 1, 4, val) #define set_SC_fcno(icb, val) setbitfield(icb + 5, 0xf, 0, val) #define set_SC_ric_dtq(sb, val) sb[2] = val #define set_SC_ric_len(sb, val) putnbyte(sb + 0x06, val, 3) /* ==================================================================== */ /* window descriptor macros for SET_WINDOW and GET_WINDOW */ #define set_WPDB_wdblen(sb, len) putnbyte(sb + 0x06, len, 2) /* ==================================================================== */ /* 0x00 - Window Identifier * 0x00 for 3096 * 0x00 (front) or 0x80 (back) for 3091 */ #define set_WD_wid(sb, val) sb[0] = val #define WD_wid_front 0x00 #define WD_wid_back 0x80 /* 0x01 - Reserved (bits 7-1), AUTO (bit 0) * Use 0x00 for 3091, 3096 */ #define set_WD_auto(sb, val) setbitfield(sb + 0x01, 1, 0, val) #define get_WD_auto(sb) getbitfield(sb + 0x01, 1, 0) /* 0x02,0x03 - X resolution in dpi * 3091 supports 50-300 in steps of 1 * 3096 suppors 200,240,300,400; or 100-1600 in steps of 4 * if image processiong option installed */ #define set_WD_Xres(sb, val) putnbyte(sb + 0x02, val, 2) #define get_WD_Xres(sb) getnbyte(sb + 0x02, 2) /* 0x04,0x05 - X resolution in dpi * 3091 supports 50-600 in steps of 1; 75,150,300,600 only * in color mode * 3096 suppors 200,240,300,400; or 100-1600 in steps of 4 * if image processiong option installed */ #define set_WD_Yres(sb, val) putnbyte(sb + 0x04, val, 2) #define get_WD_Yres(sb) getnbyte(sb + 0x04, 2) /* 0x06-0x09 - Upper Left X in 1/1200 inch */ #define set_WD_ULX(sb, val) putnbyte(sb + 0x06, val, 4) #define get_WD_ULX(sb) getnbyte(sb + 0x06, 4) /* 0x0a-0x0d - Upper Left Y in 1/1200 inch */ #define set_WD_ULY(sb, val) putnbyte(sb + 0x0a, val, 4) #define get_WD_ULY(sb) getnbyte(sb + 0x0a, 4) /* 0x0e-0x11 - Width in 1/1200 inch * 3091 left+width max 10200 * 3096 left+width max 14592 * also limited to page size, see bytes 0x35ff. */ #define set_WD_width(sb, val) putnbyte(sb + 0x0e, val, 4) #define get_WD_width(sb) getnbyte(sb + 0x0e, 4) /* 0x12-0x15 - Height in 1/1200 inch * 3091 top+height max 16832 * 3096 top+height max 20736, also if left+width>13199, * top+height has to be less than 19843 */ #define set_WD_length(sb, val) putnbyte(sb + 0x12, val, 4) #define get_WD_length(sb) getnbyte(sb + 0x12, 4) /* 0x16 - Brightness * 3091 always use 0x00 * 3096 if in halftone mode, 8 levels supported (01-1F, 20-3F, ..., E0-FF) * use 0x00 for user defined dither pattern */ #define set_WD_brightness(sb, val) sb[0x16] = val #define get_WD_brightness(sb) sb[0x16] /* 0x17 - Threshold * 3091 0x00 = use floating slice; 0x01..0xff fixed slice * with 0x01=brightest, 0x80=medium, 0xff=darkest; * only effective for line art mode. * 3096 0x00 = use "simplified dynamic treshold", otherwise * same as above but resolution is only 64 steps. */ #define set_WD_threshold(sb, val) sb[0x17] = val #define get_WD_threshold(sb) sb[0x17] /* 0x18 - Contrast * 3091 - not supported, always use 0x00 * 3096 - the same */ #define set_WD_contrast(sb, val) sb[0x18] = val #define get_WD_contrast(sb) sb[0x18] /* 0x19 - Image Composition (color mode) * 3091 - use 0x00 for line art, 0x01 for halftone, * 0x02 for grayscale, 0x05 for color. * 3096 - same but minus color. */ #define set_WD_composition(sb, val) sb[0x19] = val #define get_WD_composition(sb) sb[0x19] #define WD_comp_LA 0 #define WD_comp_HT 1 #define WD_comp_GS 2 #define WD_comp_CL 3 #define WD_comp_CH 4 #define WD_comp_CG 5 /* 0x1a - Depth * 3091 - use 0x01 for b/w or 0x08 for gray/color * 3096 - use 0x01 for b/w or 0x08 for gray */ #define set_WD_bitsperpixel(sb, val) sb[0x1a] = val #define get_WD_bitsperpixel(sb) sb[0x1a] /* 0x1b,0x1c - Halftone Pattern * 3091 byte 1b: 00h default(=dither), 01h dither, * 02h error dispersion * 1c: 00 dark images, 01h dark text+images, * 02h light images, * 03h light text+images, 80h download pattern * 3096: 1b unused; 1c bit 7=1: use downloadable pattern, * bit 7=0: use builtin pattern; rest of byte 1b denotes * pattern number, three builtin and five downloadable * supported; higher numbers = error. */ #define set_WD_ht_type(sb, val) sb[0x1b] = val #define get_WD_ht_type(sb) sb[0x1b] #define WD_ht_type_DEFAULT 0 #define WD_ht_type_DITHER 1 #define WD_ht_type_DIFFUSION 2 #define set_WD_ht_pattern(sb, val) sb[0x1c] = val #define get_WD_ht_pattern(sb) sb[0x1c] /* 0x1d - Reverse image, padding type * 3091: bit 7=1: reverse black&white * bits 0-2: padding type, must be 0 * 3096: the same; bit 7 must be set for gray and not * set for b/w. */ #define set_WD_rif(sb, val) setbitfield(sb + 0x1d, 1, 7, val) #define get_WD_rif(sb) getbitfield(sb + 0x1d, 1, 7) /* 0x1e,0x1f - Bit ordering * 3091 not supported, use 0x00 * 3096 not supported, use 0x00 */ #define set_WD_bitorder(sb, val) putnbyte(sb + 0x1e, val, 2) #define get_WD_bitorder(sb) getnbyte(sb + 0x1e, 2) /* 0x20 - compression type * not supported on smaller models, use 0x00 */ #define set_WD_compress_type(sb, val) sb[0x20] = val #define get_WD_compress_type(sb) sb[0x20] #define WD_cmp_NONE 0 #define WD_cmp_MH 1 #define WD_cmp_MR 2 #define WD_cmp_MMR 3 #define WD_cmp_JBIG 0x80 #define WD_cmp_JPG1 0x81 #define WD_cmp_JPG2 0x82 #define WD_cmp_JPG3 0x83 /* 0x21 - compression argument * specify "k" parameter with MR compress, * or with JPEG- Q param, 0-7 */ #define set_WD_compress_arg(sb, val) sb[0x21] = val #define get_WD_compress_arg(sb) sb[0x21] /* 0x22-0x27 - reserved */ /* 0x28 - vendor unique id code, decides meaning of remaining bytes * 0xc1 = color mode (fi-series) * 0xc0 = weird mode (M3091 and M3092) * 0x00 = mono mode (other M-series and fi-series) */ #define set_WD_vendor_id_code(sb, val) sb[0x28] = val #define get_WD_vendor_id_code(sb) sb[0x28] #define WD_VUID_MONO 0x00 #define WD_VUID_3091 0xc0 #define WD_VUID_COLOR 0xc1 /* 0x29 common gamma */ #define set_WD_gamma(sb, val) sb[0x29] = val #define get_WD_gamma(sb) sb[0x29] #define WD_gamma_DEFAULT 0 #define WD_gamma_NORMAL 1 #define WD_gamma_SOFT 2 #define WD_gamma_SHARP 3 /*==================================================================*/ /* 0x2a-0x3F - vary based on vuid */ /*==================================================================*/ /* vuid 0x00, mono params */ #define set_WD_outline(sb, val) setbitfield(sb + 0x2a, 1, 7, val) #define get_WD_outline(sb) getbitfield(sb + 0x2a, 1, 7) #define set_WD_emphasis(sb, val) sb[0x2b] = val #define get_WD_emphasis(sb) sb[0x2b] #define set_WD_separation(sb, val) setbitfield(sb + 0x2c, 1, 7, val) #define get_WD_separation(sb) getbitfield(sb + 0x2c, 1, 7) #define set_WD_mirroring(sb, val) setbitfield(sb + 0x2d, 1, 7, val) #define get_WD_mirroring(sb) getbitfield(sb + 0x2d, 1, 7) /* SDTC also called Auto-II mode?*/ #define set_WD_variance(sb, val) sb[0x2e] = val #define get_WD_variance(sb) sb[0x2e] /* DTC also called Auto-I mode?*/ /*warning: filtering uses inverse logic*/ #define set_WD_filtering(sb, val) setbitfield(sb + 0x2f, 1, 7, !val) #define get_WD_filtering(sb) !getbitfield(sb + 0x2f, 1, 7) /*warning: smoothing uses inverse logic*/ #define set_WD_smoothing(sb, val) setbitfield(sb + 0x2f, 3, 5, !val) #define get_WD_smoothing(sb) !getbitfield(sb + 0x2f, 3, 5) #define set_WD_gamma_curve(sb, val) setbitfield(sb + 0x2f, 3, 3, val) #define get_WD_gamma_curve(sb) getbitfield(sb + 0x2f, 3, 3) #define set_WD_threshold_curve(sb, val) setbitfield(sb + 0x2f, 7, 0, val) #define get_WD_threshold_curve(sb) getbitfield(sb + 0x2f, 7, 0) /*warning: noise removal uses inverse logic*/ #define set_WD_noise_removal(sb, val) setbitfield(sb + 0x30, 1, 5, !val) #define get_WD_noise_removal(sb) !getbitfield(sb + 0x30, 1, 5) #define set_WD_matrix5x5(sb, val) setbitfield(sb + 0x30, 1, 4, val) #define get_WD_matrix5x5(sb) getbitfield(sb + 0x30, 1, 4) #define set_WD_matrix4x4(sb, val) setbitfield(sb + 0x30, 1, 3, val) #define get_WD_matrix4x4(sb) getbitfield(sb + 0x30, 1, 3) #define set_WD_matrix3x3(sb, val) setbitfield(sb + 0x30, 1, 2, val) #define get_WD_matrix3x3(sb) getbitfield(sb + 0x30, 1, 2) #define set_WD_matrix2x2(sb, val) setbitfield(sb + 0x30, 1, 1, val) #define get_WD_matrix2x2(sb) getbitfield(sb + 0x30, 1, 1) #define set_WD_background(sb, val) setbitfield(sb + 0x30, 1, 0, val) #define get_WD_background(sb) getbitfield(sb + 0x30, 1, 0) #define WD_background_WHITE 0 #define WD_background_BLACK 1 /*31 reserved*/ #define set_WD_wl_follow(sb, val) setbitfield(sb + 0x32, 3, 6, val) #define get_WD_wl_follow(sb) getbitfield(sb + 0x32, 3, 6) #define WD_wl_follow_DEFAULT 0 #define WD_wl_follow_ON 2 #define WD_wl_follow_OFF 3 #define set_WD_subwindow_list(sb, val) putnbyte(sb + 0x33, val, 2) #define get_WD_subwindow_list(sb) getnbyte(sb + 0x33, 2) /* 0x35-0x3d - paper size */ #define set_WD_paper_selection(sb, val) setbitfield(sb + 0x35, 3, 6, val) #define WD_paper_SEL_UNDEFINED 0 #define WD_paper_SEL_NON_STANDARD 3 #define set_WD_paper_width_X(sb, val) putnbyte(sb + 0x36, val, 4) #define get_WD_paper_width_X(sb) getnbyte(sb + 0x36, 4) #define set_WD_paper_length_Y(sb, val) putnbyte(sb+0x3a, val, 4) #define get_WD_paper_length_Y(sb) getnbyte(sb+0x3a, 4) /* 3e switch ipc mode */ #define set_WD_ipc_mode(sb, val) setbitfield(sb + 0x3e, 3, 6, val) #define get_WD_ipc_mode(sb) getbitfield(sb + 0x3e, 3, 6) #define WD_ipc_DEFAULT 0 #define WD_ipc_DTC 1 #define WD_ipc_SDTC 2 /*3f reserved*/ /*==================================================================*/ /* vuid 0xc1, color params */ #define set_WD_scanning_order(sb, val) sb[0x2a] = val #define get_WD_scanning_order(sb) sb[0x2a] #define WD_SCAN_ORDER_LINE 0 #define WD_SCAN_ORDER_DOT 1 #define WD_SCAN_ORDER_FACE 2 #define set_WD_scanning_order_arg(sb, val) sb[0x2b] = val #define get_WD_scanning_order_arg(sb) sb[0x2b] #define WD_SCAN_ARG_RGB 0 #define WD_SCAN_ARG_RBG 1 #define WD_SCAN_ARG_GRB 2 #define WD_SCAN_ARG_GBR 3 #define WD_SCAN_ARG_BRG 4 #define WD_SCAN_ARG_BGR 5 /*2c-2d reserved*/ /*like vuid 00, but in different location*/ #define set_WD_c1_emphasis(sb, val) sb[0x2e] = val #define get_WD_c1_emphasis(sb) sb[0x2e] #define set_WD_c1_mirroring(sb, val) setbitfield(sb + 0x2f, 1, 7, val) #define get_WD_c1_mirroring(sb) getbitfield(sb + 0x2f, 1, 7) /*30-31 reserved*/ /*32 wlf (see vuid 00)*/ /*33-34 reserved*/ /*35-3d paper size (see vuid 00)*/ /*3e-3f reserved*/ /*==================================================================*/ /* vuid 0xc0, 3091/2 params */ /*2a-2b same as vuid 0xc1*/ #define set_WD_lamp_color(sb, val) sb[0x2d] = val #define get_WD_lamp_color(sb) sb[0x2d] #define WD_LAMP_DEFAULT 0x00 #define WD_LAMP_BLUE 0x01 #define WD_LAMP_RED 0x02 #define WD_LAMP_GREEN 0x04 /*2e-31 reserved*/ #define set_WD_quality(sb, val) sb[0x32] = val #define get_WD_quality(sb) sb[0x32] #define WD_QUAL_NORMAL 0x00 #define WD_QUAL_HIGH 0x02 /*33-34 reserved*/ /*35-3d paper size (see vuid 00)*/ /*3e-3f reserved*/ /*FIXME: more params here*/ /* ==================================================================== */ #endif sane-backends-1.0.27/backend/epsonds-net.c0000664000175000017500000001336012775312261015225 00000000000000/* * epsonds-net.c - SANE library for Epson scanners. * * Copyright (C) 2006-2016 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #ifdef HAVE_SYS_SELECT_H #include #endif #include "sane/sane.h" #include "sane/saneopts.h" #include "sane/sanei_tcp.h" #include "sane/sanei_config.h" #include "sane/sanei_backend.h" #include "epsonds.h" #include "epsonds-net.h" #include "byteorder.h" #include "sane/sanei_debug.h" static int epsonds_net_read_raw(epsonds_scanner *s, unsigned char *buf, ssize_t wanted, SANE_Status *status) { int ready, read = -1; fd_set readable; struct timeval tv; tv.tv_sec = 10; tv.tv_usec = 0; FD_ZERO(&readable); FD_SET(s->fd, &readable); ready = select(s->fd + 1, &readable, NULL, NULL, &tv); if (ready > 0) { read = sanei_tcp_read(s->fd, buf, wanted); } else { DBG(15, "%s: select failed: %d\n", __func__, ready); } *status = SANE_STATUS_GOOD; if (read < wanted) { *status = SANE_STATUS_IO_ERROR; } return read; } int epsonds_net_read(epsonds_scanner *s, unsigned char *buf, ssize_t wanted, SANE_Status * status) { ssize_t size; ssize_t read = 0; unsigned char header[12]; /* read from buffer, if available */ if (wanted && s->netptr != s->netbuf) { DBG(23, "reading %lu from buffer at %p, %lu available\n", (u_long) wanted, s->netptr, (u_long) s->netlen); memcpy(buf, s->netptr, wanted); read = wanted; s->netlen -= wanted; if (s->netlen == 0) { DBG(23, "%s: freeing %p\n", __func__, s->netbuf); free(s->netbuf); s->netbuf = s->netptr = NULL; s->netlen = 0; } return read; } /* receive net header */ size = epsonds_net_read_raw(s, header, 12, status); if (size != 12) { return 0; } if (header[0] != 'I' || header[1] != 'S') { DBG(1, "header mismatch: %02X %02x\n", header[0], header[1]); *status = SANE_STATUS_IO_ERROR; return 0; } // incoming payload size size = be32atoh(&header[6]); DBG(23, "%s: wanted = %lu, available = %lu\n", __func__, (u_long) wanted, (u_long) size); *status = SANE_STATUS_GOOD; if (size == wanted) { DBG(15, "%s: full read\n", __func__); if (size) { read = epsonds_net_read_raw(s, buf, size, status); } if (s->netbuf) { free(s->netbuf); s->netbuf = NULL; s->netlen = 0; } if (read < 0) { return 0; } } else if (wanted < size) { DBG(23, "%s: long tail\n", __func__); read = epsonds_net_read_raw(s, s->netbuf, size, status); if (read != size) { return 0; } memcpy(buf, s->netbuf, wanted); read = wanted; free(s->netbuf); s->netbuf = NULL; s->netlen = 0; } else { DBG(23, "%s: partial read\n", __func__); read = epsonds_net_read_raw(s, s->netbuf, size, status); if (read != size) { return 0; } s->netlen = size - wanted; s->netptr += wanted; read = wanted; DBG(23, "0,4 %02x %02x\n", s->netbuf[0], s->netbuf[4]); DBG(23, "storing %lu to buffer at %p, next read at %p, %lu bytes left\n", (u_long) size, s->netbuf, s->netptr, (u_long) s->netlen); memcpy(buf, s->netbuf, wanted); } return read; } SANE_Status epsonds_net_request_read(epsonds_scanner *s, size_t len) { SANE_Status status; epsonds_net_write(s, 0x2000, NULL, 0, len, &status); return status; } int epsonds_net_write(epsonds_scanner *s, unsigned int cmd, const unsigned char *buf, size_t buf_size, size_t reply_len, SANE_Status *status) { unsigned char *h1, *h2; unsigned char *packet = malloc(12 + 8); /* XXX check allocation failure */ h1 = packet; // packet header h2 = packet + 12; // data header if (reply_len) { s->netbuf = s->netptr = malloc(reply_len); s->netlen = reply_len; DBG(24, "allocated %lu bytes at %p\n", (u_long) reply_len, s->netbuf); } DBG(24, "%s: cmd = %04x, buf = %p, buf_size = %lu, reply_len = %lu\n", __func__, cmd, buf, (u_long) buf_size, (u_long) reply_len); memset(h1, 0x00, 12); memset(h2, 0x00, 8); h1[0] = 'I'; h1[1] = 'S'; h1[2] = cmd >> 8; // packet type h1[3] = cmd; // data type h1[4] = 0x00; h1[5] = 0x0C; // data offset DBG(24, "H1[0]: %02x %02x %02x %02x\n", h1[0], h1[1], h1[2], h1[3]); // 0x20 passthru // 0x21 job control if (buf_size) { htobe32a(&h1[6], buf_size); } if((cmd >> 8) == 0x20) { htobe32a(&h1[6], buf_size + 8); // data size (data header + payload) htobe32a(&h2[0], buf_size); // payload size htobe32a(&h2[4], reply_len); // expected answer size DBG(24, "H1[6]: %02x %02x %02x %02x (%lu)\n", h1[6], h1[7], h1[8], h1[9], (u_long) (buf_size + 8)); DBG(24, "H2[0]: %02x %02x %02x %02x (%lu)\n", h2[0], h2[1], h2[2], h2[3], (u_long) buf_size); DBG(24, "H2[4]: %02x %02x %02x %02x (%lu)\n", h2[4], h2[5], h2[6], h2[7], (u_long) reply_len); } if ((cmd >> 8) == 0x20 && (buf_size || reply_len)) { // send header + data header sanei_tcp_write(s->fd, packet, 12 + 8); } else { sanei_tcp_write(s->fd, packet, 12); } // send payload if (buf_size) sanei_tcp_write(s->fd, buf, buf_size); free(packet); *status = SANE_STATUS_GOOD; return buf_size; } SANE_Status epsonds_net_lock(struct epsonds_scanner *s) { SANE_Status status; unsigned char buf[7] = "\x01\xa0\x04\x00\x00\x01\x2c"; DBG(1, "%s\n", __func__); epsonds_net_write(s, 0x2100, buf, 7, 0, &status); epsonds_net_read(s, buf, 1, &status); // buf[0] should be ACK, 0x06 return status; } SANE_Status epsonds_net_unlock(struct epsonds_scanner *s) { SANE_Status status; DBG(1, "%s\n", __func__); epsonds_net_write(s, 0x2101, NULL, 0, 0, &status); /* epsonds_net_read(s, buf, 1, &status); */ return status; } sane-backends-1.0.27/backend/sm3840.conf.in0000664000175000017500000000016312112021330015004 00000000000000# usb vendor product # Microtek ScanMaker 3840 ID usb 0x05da 0x30d4 # Microtek ScanMaker 4800 ID usb 0x05da 0x30cf sane-backends-1.0.27/backend/plustek-pp_misc.c0000664000175000017500000005075312775277260016125 00000000000000/* @file plustek-pp_misc.c * @brief here we have some helpful functions * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - moved the parport functions inside this module * - now using the information, the parport-driver provides * - for selecting the port-mode this driver uses * - 0.33 - added code to use faster portmodes * - 0.34 - added sample code for changing from ECP to PS/2 bidi mode * - 0.35 - added Kevins' changes (new function miscSetFastMode()) * - moved function initPageSettings() to module models.c * - 0.36 - added random generator * - added additional debug messages * - changed prototype of MiscInitPorts() * - added miscPreemptionCallback() * - 0.37 - changed inb_p/outb_p to macro calls (kernel-mode) * - added MiscGetModelName() * - added miscShowPortModes() * - 0.38 - fixed a small bug in MiscGetModelName() * - 0.39 - added forceMode support * - 0.40 - no changes * - 0.41 - merged Kevins' patch to make EPP(ECP) work * - 0.42 - changed get_fast_time to _GET_TIME * - changed include names * - 0.43 - added LINUX_26 stuff * - minor fixes * - removed floating point stuff * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** some definitions ********************************/ #ifndef __KERNEL__ # define PPA_PROBE_SPP 0x0001 # define PPA_PROBE_PS2 0x0002 # define PPA_PROBE_ECR 0x0010 # define PPA_PROBE_EPP17 0x0100 # define PPA_PROBE_EPP19 0x0200 #else /* the parport driver in Kernel 2.4 has changed. It does report the * possible modes in a different, more general way. As long, as * we do not use the parport-module change mode facility, I assume * the following correlations */ #if defined LINUX_24 || defined LINUX_26 # define PARPORT_MODE_PCPS2 PARPORT_MODE_TRISTATE # define PARPORT_MODE_PCEPP PARPORT_MODE_EPP # define PARPORT_MODE_PCECPPS2 PARPORT_MODE_TRISTATE # define PARPORT_MODE_PCECPEPP PARPORT_MODE_EPP # define PARPORT_MODE_PCECR PARPORT_MODE_ECP #endif #endif #define _PP_A 16807 /**< multiplier */ #define _PP_M 2147483647L /**< 2**31 - 1 */ /*************************** some local vars *********************************/ static int port_feature = 0; static long randomnum = 1; #ifdef __KERNEL__ static int portIsClaimed[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = 0 }; MODELSTR; /**< a static char array (see plustek-pp.h) */ #else static int portIsClaimed[_MAX_PTDEVS] = { 0, 0, 0, 0 }; #endif /*************************** local functions *********************************/ #ifdef __KERNEL__ #ifdef LINUX_26 static pScanData __ps = NULL; static int __pa = -1; /** callback from parport driver */ static void misc_attach(struct parport *port) { DBG( DBG_LOW, "misc_attach\n" ); __ps->pp = NULL; if( port->base == (unsigned long)__pa ) { DBG( DBG_LOW, "Requested port (0x%02x) found\n", __pa ); DBG( DBG_LOW, "Port mode reported: (0x%04x)\n", port->modes ); __ps->pp = port; } } static void misc_detach( struct parport *port ) { DBG( DBG_LOW, "misc_detach\n" ); } static struct parport_driver pt_drv = { .name = "pt_drv", .attach = misc_attach, .detach = misc_detach, }; #endif /** display the avaialable port-modes */ #ifdef DEBUG static void miscShowPortModes( int modes ) { DBG( DBG_LOW, "parport-modi:" ); if( modes & PARPORT_MODE_PCSPP ) DBG( DBG_LOW, " SPP" ); if( modes & PARPORT_MODE_PCPS2 ) DBG( DBG_LOW, " PS/2" ); if( modes & PARPORT_MODE_PCEPP ) DBG( DBG_LOW, " EPP" ); if( modes & PARPORT_MODE_PCECR ) DBG( DBG_LOW, " ECP" ); if( modes & PARPORT_MODE_PCECPEPP ) DBG( DBG_LOW, " EPP(ECP)" ); if( modes & PARPORT_MODE_PCECPPS2 ) DBG( DBG_LOW, " PS/2(ECP)" ); DBG( DBG_LOW, "\n" ); } #endif /** probe the parallel port */ static int initPortProbe( pScanData ps ) { int retv = 0; /* clear the controls */ ps->IO.lastPortMode = 0xFFFF; if( NULL != ps->pardev ) retv = ps->pardev->port->modes; return retv; } /** will be called by the parport module when we already have access, but * another module wants access to the port... */ static int miscPreemptionCallback( pVoid data ) { pScanData ps = (pScanData)data; if( NULL != ps ) { /* never release during scanning */ if( ps->DataInf.dwScanFlag & _SCANNER_SCANNING ) { DBG( DBG_LOW, "no way!!!\n" ); return 1; } } /* let the port go...*/ return 0; } /** depending on the reported possible port modes, we try to set a faster mode * than SPP */ static int miscSetFastMode( pScanData ps ) { UChar a, b; /* * when previously found the EPP mode, break right here */ if (( _PORT_EPP == ps->IO.portMode ) && (!(port_feature & PARPORT_MODE_PCECR))) return _OK; /* CHECK REMOVE: from here we should have SPP (Paranoia Code !) */ if (( _PORT_SPP != ps->IO.portMode ) && (!(port_feature & PARPORT_MODE_PCECR))) return _OK; DBG(DBG_LOW, "Trying faster mode...\n" ); /* * ECP mode usually has sub-modes of EPP and/or PS2. * First we try to set EPP */ if((port_feature & PARPORT_MODE_PCECR) && (port_feature & PARPORT_MODE_PCECPEPP)){ DBG(DBG_LOW, "Attempting to set EPP from ECP mode.\n" ); a = _INB_ECTL(ps); /* get current ECR */ ps->IO.lastPortMode = a; /* save it for restoring later */ a = (a & 0x1F) | 0x80; /* set to EPP */ _OUTB_ECTL(ps, a); /* write it back */ _DO_UDELAY(1); /* * It is probably unnecessary to * do this check but it makes me feel better */ b = _INB_ECTL(ps); /* check to see if port set */ if( a == b ) { DBG( DBG_LOW, "Port is set to (ECP) EPP mode.\n" ); ps->IO.portMode = _PORT_EPP; return _OK; } else { DBG( DBG_LOW, "Port could not be set to (ECP) EPP mode. " "Using SPP mode.\n" ); _OUTB_ECTL(ps,(Byte)ps->IO.lastPortMode); /* restore */ _DO_UDELAY(1); ps->IO.portMode = _PORT_SPP; /* go ahead and try with other settings...*/ } } /* If port cannot be set to EPP, try PS2 */ if((port_feature & PARPORT_MODE_PCECR) && (port_feature & PARPORT_MODE_PCECPPS2)) { DBG(DBG_LOW, "Attempting to set PS2 from ECPPS2 mode.\n" ); a = _INB_ECTL(ps); /* get current ECR */ ps->IO.lastPortMode = a; /* save it for restoring later */ /* set to Fast Centronics/bi-directional/PS2 */ a = (a & 0x1F) | 0x20; _OUTB_ECTL(ps,a); /* write it back */ _DO_UDELAY(1); /* * It is probably unnecessary to do this check * but it makes me feel better */ b = _INB_ECTL(ps); /* check to see if port set */ if (a == b) { DBG(DBG_LOW, "Port is set to (ECP) PS2 bidirectional mode.\n"); ps->IO.portMode = _PORT_BIDI; return _OK; } else { DBG(DBG_LOW, "Port could not be set to (ECP) PS2 mode. " "Using SPP mode.\n"); a = ps->IO.lastPortMode & 0x1F; _OUTB_ECTL(ps, a); /* set ECP ctrl to SPP */ _DO_UDELAY(1); ps->IO.portMode = _PORT_SPP; /* next mode, last attempt... */ } } /* * Some BIOS/cards have only a Bi-directional/PS2 mode (no EPP). * Make one last attemp to set to PS2 mode. */ if ( port_feature & PARPORT_MODE_PCPS2 ){ DBG(DBG_LOW, "Attempting to set PS2 mode.\n" ); a = _INB_CTRL(ps); /* get current setting of control register*/ ps->IO.lastPortMode = a; /* save it for restoring later */ a = a | 0x20; /* set bit 5 of control reg */ _OUTB_CTRL(ps,a); /* set to Fast Centronics/bi-directional/PS2 */ _DO_UDELAY(1); a = 0; _OUTB_DATA(ps,0x55); _DO_UDELAY(1); if ((inb(ps->IO.portBase)) != 0x55) /* read data */ a++; _OUTB_DATA(ps,0xAA); _DO_UDELAY(1); if (_INB_DATA(ps) != 0xAA) /* read data */ a++; if( 2 == a ) { DBG(DBG_LOW, "Port is set to PS2 bidirectional mode.\n"); ps->IO.portMode = _PORT_BIDI; return _OK; } else { DBG(DBG_LOW, "Port could not be set to PS2 mode. " "Using SPP mode.\n"); _OUTB_CTRL(ps,(Byte)ps->IO.lastPortMode); /* restore */ _DO_UDELAY(1); ps->IO.portMode = _PORT_SPP; } } /* reaching this point, we're back in SPP mode and there's no need * to restore at shutdown... */ ps->IO.lastPortMode = 0xFFFF; return _OK; } /** check the state of the par-port and switch to EPP-mode if possible */ static int miscSetPortMode( pScanData ps ) { /* try to detect the port settings, SPP seems to work in any case ! */ port_feature = initPortProbe( ps ); #ifdef DEBUG miscShowPortModes( port_feature ); #endif switch( ps->IO.forceMode ) { case 1: DBG( DBG_LOW, "Use of SPP-mode enforced\n" ); ps->IO.portMode = _PORT_SPP; return _OK; break; case 2: DBG( DBG_LOW, "Use of EPP-mode enforced\n" ); ps->IO.portMode = _PORT_EPP; return _OK; break; default: break; } if( !(port_feature & PARPORT_MODE_PCEPP)) { if( !(port_feature & PARPORT_MODE_PCSPP )) { _PRINT("\nThis Port supports not the SPP- or EPP-Mode\n" ); _PRINT("Please activate SPP-Mode, EPP-Mode or\nEPP + ECP-Mode!\n"); return _E_NOSUPP; } else { DBG(DBG_LOW, "Using SPP-mode\n" ); ps->IO.portMode = _PORT_SPP; } } else { DBG(DBG_LOW, "Using EPP-mode\n" ); ps->IO.portMode = _PORT_EPP; } /* else try to set to a faster mode than SPP */ return miscSetFastMode( ps ); } #endif /** miscNextLongRand() -- generate 2**31-2 random numbers ** ** public domain by Ray Gardner ** ** based on "Random Number Generators: Good Ones Are Hard to Find", ** S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988), ** and "Two Fast Implementations of the 'Minimal Standard' Random ** Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), p. 87-88 ** ** linear congruential generator f(z) = 16807 z mod (2 ** 31 - 1) ** ** uses L. Schrage's method to avoid overflow problems */ static Long miscNextLongRand( Long seed ) { ULong lo, hi; lo = _PP_A * (Long)(seed & 0xFFFF); hi = _PP_A * (Long)((ULong)seed >> 16); lo += (hi & 0x7FFF) << 16; if (lo > _PP_M) { lo &= _PP_M; ++lo; } lo += hi >> 15; if (lo > _PP_M) { lo &= _PP_M; ++lo; } return (Long)lo; } /** initialize the random number generator */ static void miscSeedLongRand( long seed ) { randomnum = seed ? (seed & _PP_M) : 1; /* nonzero seed */ } /************************ exported functions *********************************/ /** allocate and initialize some memory for the scanner structure */ _LOC pScanData MiscAllocAndInitStruct( void ) { pScanData ps; ps = (pScanData)_KALLOC(sizeof(ScanData), GFP_KERNEL); if( NULL != ps ) { MiscReinitStruct( ps ); } DBG( DBG_HIGH, "ScanData = 0x%08lx\n", (unsigned long)ps ); return ps; } /** re-initialize the memory for the scanner structure */ _LOC int MiscReinitStruct( pScanData ps ) { if( NULL == ps ) return _E_NULLPTR; memset( ps, 0, sizeof(ScanData)); /* first init all constant stuff in ScanData */ ps->bCurrentSpeed = 1; ps->pbMapRed = ps->a_bMapTable; ps->pbMapGreen = &ps->a_bMapTable[256]; ps->pbMapBlue = &ps->a_bMapTable[512]; ps->sCaps.wIOBase = _NO_BASE; /* use memory address to seed the generator */ miscSeedLongRand((long)ps); DBG( DBG_HIGH, "Init settings done\n" ); return _OK; } /** in USER-Mode: probe the specified port and try to get the port-mode * in KERNEL-Mode: only use the modes, the driver returns */ _LOC int MiscInitPorts( pScanData ps, int port ) { #ifdef __KERNEL__ int status; if( NULL == ps ) return _E_NULLPTR; /* * Get access to the ports */ ps->IO.portBase = (UShort)port; status = miscSetPortMode(ps); if( _OK != status ) { ps->sCaps.wIOBase = _NO_BASE; ps->IO.portBase = _NO_BASE; return status; } /* * the port settings */ ps->IO.pbSppDataPort = (UShort)port; ps->IO.pbStatusPort = (UShort)port+1; ps->IO.pbControlPort = (UShort)port+2; ps->IO.pbEppDataPort = (UShort)port+4; #else int mode, mts; if( NULL == ps ) return _E_NULLPTR; if( SANE_STATUS_GOOD != sanei_pp_getmodes( ps->pardev, &mode )) { DBG( DBG_HIGH, "Cannot get port mode!\n" ); return _E_NO_PORT; } ps->IO.portMode = _PORT_NONE; mts = -1; if( mode & SANEI_PP_MODE_SPP ) { DBG( DBG_LOW, "Setting SPP-mode\n" ); ps->IO.portMode = _PORT_SPP; mts = SANEI_PP_MODE_SPP; } if( mode & SANEI_PP_MODE_BIDI ) { DBG( DBG_LOW, "Setting PS/2-mode\n" ); ps->IO.portMode = _PORT_BIDI; mts = SANEI_PP_MODE_BIDI; } if( mode & SANEI_PP_MODE_EPP ) { DBG( DBG_LOW, "Setting EPP-mode\n" ); ps->IO.portMode = _PORT_EPP; mts = SANEI_PP_MODE_EPP; } if( mode & SANEI_PP_MODE_ECP ) { DBG( DBG_HIGH, "ECP detected --> not supported\n" ); } if( sanei_pp_uses_directio()) { DBG( DBG_LOW, "We're using direct I/O\n" ); } else { DBG( DBG_LOW, "We're using libIEEE1284 I/O\n" ); } if( ps->IO.portMode == _PORT_NONE ) { DBG( DBG_HIGH, "None of the portmodes is supported.\n" ); return _E_NOSUPP; } sanei_pp_setmode( ps->pardev, mts ); _VAR_NOT_USED( port ); #endif return _OK; } /** Function to restore the port */ _LOC void MiscRestorePort( pScanData ps ) { #ifdef __KERNEL__ if( 0 == ps->IO.pbSppDataPort ) return; #endif DBG(DBG_LOW,"MiscRestorePort()\n"); /* don't restore if not necessary */ if( 0xFFFF == ps->IO.lastPortMode ) { DBG(DBG_LOW,"- no need to restore portmode !\n"); return; } /*Restore Port-Mode*/ #ifdef __KERNEL__ if( port_feature & PARPORT_MODE_PCECR ){ _OUTB_ECTL( ps, (Byte)ps->IO.lastPortMode ); _DO_UDELAY(1); } else { _OUTB_CTRL( ps, (Byte)ps->IO.lastPortMode ); _DO_UDELAY(1); } #else if( port_feature & PPA_PROBE_ECR ){ _OUTB_ECTL(ps,ps->IO.lastPortMode); } #endif } /** Initializes a timer. * @param timer - pointer to the timer to start * @param us - timeout value in micro-seconds */ _LOC void MiscStartTimer( TimerDef *timer , unsigned long us) { struct timeval start_time; #ifdef __KERNEL__ _GET_TIME( &start_time ); #else gettimeofday(&start_time, NULL); #endif *timer = (TimerDef)start_time.tv_sec * 1000000 + (TimerDef)start_time.tv_usec + us; } /** Checks if a timer has been expired or not. In Kernel-mode, the scheduler * will also be triggered, if the timer has not been expired. * @param timer - pointer to the timer to check * @return Function returns _E_TIMEOUT when the timer has been expired, * otherwise _OK; */ _LOC int MiscCheckTimer( TimerDef *timer ) { struct timeval current_time; #ifdef __KERNEL__ _GET_TIME( ¤t_time ); #else gettimeofday(¤t_time, NULL); #endif if ((TimerDef)current_time.tv_sec * 1000000 + (TimerDef)current_time.tv_usec > *timer) { return _E_TIMEOUT; } else { #ifdef __KERNEL__ schedule(); /*#else sched_yield(); */ #endif return _OK; } } /** Checks the function pointers * @param ps - pointer to the scanner data structure. * @return Function returns _TRUE if everything is okay and _FALSE if a NULL * ptr has been detected. */ #ifdef DEBUG _LOC Bool MiscAllPointersSet( pScanData ps ) { int i; unsigned long *ptr; for( ptr = (unsigned long *)&ps->OpenScanPath, i = 1; ptr <= (unsigned long *)&ps->ReadOneImageLine; ptr++, i++ ) { if( NULL == (pVoid)*ptr ) { DBG( DBG_HIGH, "Function pointer not set (pos = %d) !\n", i ); return _FALSE; } } return _TRUE; } #endif /** registers this driver to use port "portAddr" (KERNEL-Mode only) * @param ps - pointer to the scanner data structure. * @param portAddr - */ _LOC int MiscRegisterPort( pScanData ps, int portAddr ) { #ifndef __KERNEL__ DBG( DBG_LOW, "Assigning port handle %i\n", portAddr ); ps->pardev = portAddr; #else #ifdef LINUX_26 __ps = ps; __pa = portAddr; DBG( DBG_LOW, "Requested port at 0x%02x\n", portAddr ); if( parport_register_driver(&pt_drv)) { /* Failed; nothing we can do. */ return _E_REGISTER; } #else struct parport *pp = NULL; DBG( DBG_LOW, "Requested port at 0x%02x\n", portAddr ); pp = parport_enumerate(); ps->pardev = NULL; if( NULL == pp ) { return _E_PORTSEARCH; } /* go through the list */ for( ps->pp = NULL; NULL != pp; ) { if( pp->base == (unsigned long)portAddr ) { DBG( DBG_LOW, "Requested port (0x%02x) found\n", portAddr ); DBG( DBG_LOW, "Port mode reported: (0x%04x)\n", pp->modes ); ps->pp = pp; break; } pp = pp->next; } #endif if( NULL == ps->pp ) { printk("PORT not found!!!\n"); return _E_NO_PORT; } /* * register this device */ ps->pardev = parport_register_device( ps->pp, "Plustek Driver", miscPreemptionCallback, NULL, NULL, 0, (pVoid)ps ); if( NULL == ps->pardev ) { return _E_REGISTER; } DBG( DBG_LOW, "Port for device %u registered\n", ps->devno ); #endif portIsClaimed[ps->devno] = 0; return _OK; } /** unregisters the port from driver */ _LOC void MiscUnregisterPort( pScanData ps ) { #ifdef __KERNEL__ if( NULL != ps->pardev ) { DBG( DBG_LOW, "Port unregistered\n" ); parport_unregister_device( ps->pardev ); } #ifdef LINUX_26 parport_unregister_driver( &pt_drv ); #endif #else sanei_pp_close( ps->pardev ); #endif } /** Try to claim the port * @param ps - pointer to the scanner data structure. * @return Function returns _OK on success, otherwise _E_BUSY. */ _LOC int MiscClaimPort( pScanData ps ) { if( 0 == portIsClaimed[ps->devno] ) { DBG( DBG_HIGH, "Try to claim the parport\n" ); #ifdef __KERNEL__ if( 0 != parport_claim( ps->pardev )) { #else if( SANE_STATUS_GOOD != sanei_pp_claim( ps->pardev )) { #endif return _E_BUSY; } } portIsClaimed[ps->devno]++; return _OK; } /** Release previously claimed port * @param ps - pointer to the scanner data structure */ _LOC void MiscReleasePort( pScanData ps ) { if( portIsClaimed[ps->devno] > 0 ) { portIsClaimed[ps->devno]--; if( 0 == portIsClaimed[ps->devno] ) { DBG( DBG_HIGH, "Releasing parport\n" ); #ifdef __KERNEL__ parport_release( ps->pardev ); #else sanei_pp_release( ps->pardev ); #endif } } } /** Get random number * @return a random number. */ _LOC Long MiscLongRand( void ) { randomnum = miscNextLongRand( randomnum ); return randomnum; } /** According to the id, the function returns a pointer to the model name * @param id - internal id of the various scanner models. * @return a pointer to the model-string. */ _LOC const char *MiscGetModelName( UShort id ) { DBG( DBG_HIGH, "MiscGetModelName - id = %i\n", id ); if( MODEL_OP_PT12 < id ) return ModelStr[0]; return ModelStr[id]; } /* END PLUSTEK-PP_MISC.C ....................................................*/ sane-backends-1.0.27/backend/gt68xx_generic.c0000664000175000017500000004444712112021330015617 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov Copyright (C) 2005-2007 Henning Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file * @brief GT68xx commands common for most GT68xx-based scanners. */ #include "gt68xx_generic.h" SANE_Status gt68xx_generic_move_relative (GT68xx_Device * dev, SANE_Int distance) { GT68xx_Packet req; memset (req, 0, sizeof (req)); if (distance >= 0) req[0] = 0x14; else { req[0] = 0x15; distance = -distance; } req[1] = 0x01; req[2] = LOBYTE (distance); req[3] = HIBYTE (distance); return gt68xx_device_req (dev, req, req); } SANE_Status gt68xx_generic_start_scan (GT68xx_Device * dev) { GT68xx_Packet req; SANE_Status status; memset (req, 0, sizeof (req)); req[0] = 0x43; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); RIE (gt68xx_device_check_result (req, 0x43)); return SANE_STATUS_GOOD; } SANE_Status gt68xx_generic_read_scanned_data (GT68xx_Device * dev, SANE_Bool * ready) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x35; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); *ready = SANE_FALSE; if (req[0] == 0) *ready = SANE_TRUE; return SANE_STATUS_GOOD; } static SANE_Byte gt68xx_generic_fix_gain (SANE_Int gain) { if (gain < 0) gain = 0; else if (gain > 31) gain += 12; else if (gain > 51) gain = 63; return gain; } static SANE_Byte gt68xx_generic_fix_offset (SANE_Int offset) { if (offset < 0) offset = 0; else if (offset > 63) offset = 63; return offset; } SANE_Status gt68xx_generic_set_afe (GT68xx_Device * dev, GT68xx_AFE_Parameters * params) { GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x22; req[1] = 0x01; req[2] = gt68xx_generic_fix_offset (params->r_offset); req[3] = gt68xx_generic_fix_gain (params->r_pga); req[4] = gt68xx_generic_fix_offset (params->g_offset); req[5] = gt68xx_generic_fix_gain (params->g_pga); req[6] = gt68xx_generic_fix_offset (params->b_offset); req[7] = gt68xx_generic_fix_gain (params->b_pga); DBG (6, "gt68xx_generic_set_afe: real AFE: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", req[2], req[3], req[4], req[5], req[6], req[7]); return gt68xx_device_req (dev, req, req); } SANE_Status gt68xx_generic_set_exposure_time (GT68xx_Device * dev, GT68xx_Exposure_Parameters * params) { GT68xx_Packet req; SANE_Status status; memset (req, 0, sizeof (req)); req[0] = 0x76; req[1] = 0x01; req[2] = req[6] = req[10] = 0x04; req[4] = LOBYTE (params->r_time); req[5] = HIBYTE (params->r_time); req[8] = LOBYTE (params->g_time); req[9] = HIBYTE (params->g_time); req[12] = LOBYTE (params->b_time); req[13] = HIBYTE (params->b_time); DBG (6, "gt68xx_generic_set_exposure_time: 0x%03x 0x%03x 0x%03x\n", params->r_time, params->g_time, params->b_time); RIE (gt68xx_device_req (dev, req, req)); RIE (gt68xx_device_check_result (req, 0x76)); return SANE_STATUS_GOOD; } SANE_Status gt68xx_generic_get_id (GT68xx_Device * dev) { GT68xx_Packet req; SANE_Status status; memset (req, 0, sizeof (req)); req[0] = 0x2e; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); RIE (gt68xx_device_check_result (req, 0x2e)); DBG (2, "get_id: vendor id=0x%04X, product id=0x%04X, DID=0x%08X, FID=0x%04X\n", req[2] + (req[3] << 8), req[4] + (req[5] << 8), req[6] + (req[7] << 8) + (req[8] << 16) + (req[9] << 24), req[10] + (req[11] << 8)); return SANE_STATUS_GOOD; } SANE_Status gt68xx_generic_paperfeed (GT68xx_Device * dev) { GT68xx_Packet req; SANE_Status status; memset (req, 0, sizeof (req)); req[0] = 0x83; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); return SANE_STATUS_GOOD; } #define MAX_PIXEL_MODE 15600 SANE_Status gt68xx_generic_setup_scan (GT68xx_Device * dev, GT68xx_Scan_Request * request, GT68xx_Scan_Action action, GT68xx_Scan_Parameters * params) { SANE_Status status; GT68xx_Model *model; SANE_Int xdpi, ydpi; SANE_Bool color; SANE_Int depth; SANE_Int pixel_x0, pixel_y0, pixel_xs, pixel_ys; SANE_Int pixel_align; SANE_Int abs_x0, abs_y0, abs_xs, abs_ys, base_xdpi, base_ydpi; SANE_Int scan_xs, scan_ys, scan_bpl; SANE_Int bits_per_line; SANE_Byte color_mode_code; SANE_Bool line_mode; SANE_Int overscan_lines; SANE_Fixed x0, y0, xs, ys; SANE_Bool backtrack = SANE_FALSE; DBG (6, "gt6816_setup_scan: enter (action=%s)\n", action == SA_CALIBRATE ? "calibrate" : action == SA_CALIBRATE_ONE_LINE ? "calibrate one line" : action == SA_SCAN ? "scan" : "calculate only"); model = dev->model; xdpi = request->xdpi; ydpi = request->ydpi; color = request->color; depth = request->depth; base_xdpi = model->base_xdpi; base_ydpi = model->base_ydpi; if (xdpi > model->base_xdpi) base_xdpi = model->optical_xdpi; /* Special fixes */ if ((dev->model->flags & GT68XX_FLAG_USE_OPTICAL_X) && xdpi <= 50) base_xdpi = model->optical_xdpi; if ((dev->model->flags & GT68XX_FLAG_SCAN_FROM_HOME) && !request->use_ta && action == SA_SCAN) request->mbs = SANE_TRUE; if (!model->constant_ydpi) { if (ydpi > model->base_ydpi) base_ydpi = model->optical_ydpi; } DBG (6, "gt68xx_generic_setup_scan: base_xdpi=%d, base_ydpi=%d\n", base_xdpi, base_ydpi); switch (action) { case SA_CALIBRATE_ONE_LINE: { x0 = request->x0; if (request->use_ta) y0 = model->y_offset_calib_ta; else y0 = model->y_offset_calib; ys = SANE_FIX (1.0 * MM_PER_INCH / ydpi); /* one line */ xs = request->xs; depth = 8; break; } case SA_CALIBRATE: { if (request->use_ta) { if (dev->model->flags & GT68XX_FLAG_MIRROR_X) x0 = request->x0 - model->x_offset_ta; else x0 = request->x0 + model->x_offset_ta; if (request->mbs) y0 = model->y_offset_calib_ta; else y0 = 0; } else { if (dev->model->flags & GT68XX_FLAG_MIRROR_X) x0 = request->x0 - model->x_offset; else x0 = request->x0 + model->x_offset; if (request->mbs) y0 = model->y_offset_calib; else y0 = 0; } ys = SANE_FIX (CALIBRATION_HEIGHT); xs = request->xs; break; } case SA_SCAN: { SANE_Fixed x_offset, y_offset; if (strcmp (dev->model->command_set->name, "mustek-gt6816") != 0) request->mbs = SANE_TRUE; /* always go home for gt6801 scanners */ if (request->use_ta) { x_offset = model->x_offset_ta; if (request->mbs) y_offset = model->y_offset_ta; else { y_offset = model->y_offset_ta - model->y_offset_calib_ta - SANE_FIX (CALIBRATION_HEIGHT); if ((request->y0 + y_offset) < 0) { y_offset = model->y_offset_ta; request->mbs = SANE_TRUE; } } } else { x_offset = model->x_offset; if (request->mbs) y_offset = model->y_offset; else { y_offset = model->y_offset - model->y_offset_calib - SANE_FIX (CALIBRATION_HEIGHT); if ((request->y0 + y_offset) < 0) { y_offset = model->y_offset; request->mbs = SANE_TRUE; } } } if (dev->model->flags & GT68XX_FLAG_MIRROR_X) x0 = request->x0 - x_offset; else x0 = request->x0 + x_offset; y0 = request->y0 + y_offset; if (y0 < 0) y0 = 0; ys = request->ys; xs = request->xs; backtrack = request->backtrack; break; } default: DBG (1, "gt68xx_generic_setup_scan: invalid action=%d\n", (int) action); return SANE_STATUS_INVAL; } pixel_x0 = SANE_UNFIX (x0) * xdpi / MM_PER_INCH + 0.5; pixel_y0 = SANE_UNFIX (y0) * ydpi / MM_PER_INCH + 0.5; pixel_ys = SANE_UNFIX (ys) * ydpi / MM_PER_INCH + 0.5; pixel_xs = SANE_UNFIX (xs) * xdpi / MM_PER_INCH + 0.5; DBG (6, "gt68xx_generic_setup_scan: xdpi=%d, ydpi=%d\n", xdpi, ydpi); DBG (6, "gt68xx_generic_setup_scan: color=%s, depth=%d\n", color ? "TRUE" : "FALSE", depth); DBG (6, "gt68xx_generic_setup_scan: pixel_x0=%d, pixel_y0=%d\n", pixel_x0, pixel_y0); DBG (6, "gt68xx_generic_setup_scan: pixel_xs=%d, pixel_ys=%d\n", pixel_xs, pixel_ys); color_mode_code = 0x80; if (color) color_mode_code |= (1 << 2); else color_mode_code |= dev->gray_mode_color; if (depth > 12) color_mode_code |= (1 << 5); else if (depth > 8) { color_mode_code &= 0x7f; color_mode_code |= (1 << 4); } DBG (6, "gt68xx_generic_setup_scan: color_mode_code = 0x%02X\n", color_mode_code); overscan_lines = 0; params->ld_shift_r = params->ld_shift_g = params->ld_shift_b = 0; params->ld_shift_double = 0; /* Line distance correction is required for color scans. */ if (action == SA_SCAN && color) { SANE_Int optical_ydpi = model->optical_ydpi; SANE_Int ld_shift_r = model->ld_shift_r; SANE_Int ld_shift_g = model->ld_shift_g; SANE_Int ld_shift_b = model->ld_shift_b; SANE_Int max_ld = MAX (MAX (ld_shift_r, ld_shift_g), ld_shift_b); overscan_lines = max_ld * ydpi / optical_ydpi; params->ld_shift_r = ld_shift_r * ydpi / optical_ydpi; params->ld_shift_g = ld_shift_g * ydpi / optical_ydpi; params->ld_shift_b = ld_shift_b * ydpi / optical_ydpi; params->ld_shift_double = 0; DBG (6, "gt68xx_generic_setup_scan: overscan=%d, ld=%d/%d/%d\n", overscan_lines, params->ld_shift_r, params->ld_shift_g, params->ld_shift_b); } /* Used for CCD scanners with 6 instead of 3 CCD lines */ if (action == SA_SCAN && xdpi >= model->optical_xdpi && model->ld_shift_double > 0) { params->ld_shift_double = model->ld_shift_double * ydpi / model->optical_ydpi; if (color) overscan_lines += (params->ld_shift_double * 3); else overscan_lines += params->ld_shift_double; DBG (6, "gt68xx_generic_setup_scan: overscan=%d, ld double=%d\n", overscan_lines, params->ld_shift_double); } abs_x0 = pixel_x0 * base_xdpi / xdpi; abs_y0 = pixel_y0 * base_ydpi / ydpi; DBG (6, "gt68xx_generic_setup_scan: abs_x0=%d, abs_y0=%d\n", abs_x0, abs_y0); params->double_column = abs_x0 & 1; /* Calculate minimum number of pixels which span an integral multiple of 64 * bytes. */ pixel_align = 32; /* best case for depth = 16 */ while ((depth * pixel_align) % (64 * 8) != 0) pixel_align *= 2; DBG (6, "gt68xx_generic_setup_scan: pixel_align=%d\n", pixel_align); if (pixel_xs % pixel_align == 0) scan_xs = pixel_xs; else scan_xs = (pixel_xs / pixel_align + 1) * pixel_align; scan_ys = pixel_ys + overscan_lines; if ((xdpi != base_xdpi) && (strcmp (dev->model->command_set->name, "mustek-gt6816") != 0)) abs_xs = (scan_xs - 1) * base_xdpi / xdpi; /* gt6801 */ else abs_xs = scan_xs * base_xdpi / xdpi; /* gt6816 */ if (action == SA_CALIBRATE_ONE_LINE) abs_ys = 2; else abs_ys = scan_ys * base_ydpi / ydpi; DBG (6, "gt68xx_generic_setup_scan: abs_xs=%d, abs_ys=%d\n", abs_xs, abs_ys); if (model->flags & GT68XX_FLAG_NO_LINEMODE) { line_mode = SANE_FALSE; DBG (6, "gt68xx_generic_setup_scan: using pixel mode (GT68XX_FLAG_NO_LINEMODE)\n"); } else if (model->is_cis && !(model->flags & GT68XX_FLAG_CIS_LAMP)) { line_mode = SANE_TRUE; DBG (6, "gt68xx_generic_setup_scan: using line mode (CIS)\n"); } else if (model->flags & GT68XX_FLAG_ALWAYS_LINEMODE) { line_mode = SANE_TRUE; DBG (6, "gt68xx_generic_setup_scan: using line mode (GT68XX_FLAG_ALWAYS_LINEMODE)\n"); } else { SANE_Int max_bpl = xdpi * 3 * depth * (SANE_UNFIX (model->x_size) - SANE_UNFIX (model->x_offset)) / MM_PER_INCH / 8; line_mode = SANE_FALSE; if (!color) { DBG (6, "gt68xx_generic_setup_scan: using line mode for monochrome scan\n"); line_mode = SANE_TRUE; } else if (max_bpl > MAX_PIXEL_MODE) { DBG (6, "gt68xx_generic_setup_scan: max_bpl = %d > %d: forcing line mode\n", max_bpl, MAX_PIXEL_MODE); line_mode = SANE_TRUE; } else DBG (6, "gt68xx_generic_setup_scan: max_bpl = %d <= %d: using pixel mode\n", max_bpl, MAX_PIXEL_MODE); } bits_per_line = depth * scan_xs; if (color && !line_mode) bits_per_line *= 3; if (bits_per_line % 8) /* impossible */ { DBG (0, "gt68xx_generic_setup_scan: BUG: unaligned bits_per_line=%d\n", bits_per_line); return SANE_STATUS_INVAL; } scan_bpl = bits_per_line / 8; if (scan_bpl % 64) /* impossible */ { DBG (0, "gt68xx_generic_setup_scan: BUG: unaligned scan_bpl=%d\n", scan_bpl); return SANE_STATUS_INVAL; } if (color) if (line_mode || dev->model->flags & GT68XX_FLAG_SE_2400) scan_ys *= 3; DBG (6, "gt68xx_generic_setup_scan: scan_xs=%d, scan_ys=%d\n", scan_xs, scan_ys); DBG (6, "gt68xx_generic_setup_scan: scan_bpl=%d\n", scan_bpl); if (!request->calculate) { GT68xx_Packet req; SANE_Byte motor_mode_1, motor_mode_2; if (scan_bpl > (16 * 1024)) { DBG (0, "gt68xx_generic_setup_scan: scan_bpl=%d, too large\n", scan_bpl); return SANE_STATUS_NO_MEM; } if ((dev->model->flags & GT68XX_FLAG_NO_LINEMODE) && line_mode && color) { DBG (0, "gt68xx_generic_setup_scan: the scanner's memory is too small for " "that combination of resolution, dpi and width\n"); return SANE_STATUS_NO_MEM; } DBG (6, "gt68xx_generic_setup_scan: backtrack=%d\n", backtrack); motor_mode_1 = (request->mbs ? 0 : 1) << 1; motor_mode_1 |= (request->mds ? 0 : 1) << 2; motor_mode_1 |= (request->mas ? 0 : 1) << 0; motor_mode_1 |= (backtrack ? 1 : 0) << 3; motor_mode_2 = (request->lamp ? 0 : 1) << 0; motor_mode_2 |= (line_mode ? 0 : 1) << 2; if ((action != SA_SCAN) && (strcmp (dev->model->command_set->name, "mustek-gt6816") == 0)) motor_mode_2 |= 1 << 3; DBG (6, "gt68xx_generic_setup_scan: motor_mode_1 = 0x%02X, motor_mode_2 = 0x%02X\n", motor_mode_1, motor_mode_2); /* Fill in the setup command */ memset (req, 0, sizeof (req)); req[0x00] = 0x20; req[0x01] = 0x01; req[0x02] = LOBYTE (abs_y0); req[0x03] = HIBYTE (abs_y0); req[0x04] = LOBYTE (abs_ys); req[0x05] = HIBYTE (abs_ys); req[0x06] = LOBYTE (abs_x0); req[0x07] = HIBYTE (abs_x0); req[0x08] = LOBYTE (abs_xs); req[0x09] = HIBYTE (abs_xs); req[0x0a] = color_mode_code; if (model->is_cis && !(model->flags & GT68XX_FLAG_CIS_LAMP)) req[0x0b] = 0x60; else req[0x0b] = 0x20; req[0x0c] = LOBYTE (xdpi); req[0x0d] = HIBYTE (xdpi); req[0x0e] = 0x12; /* ??? 0x12 */ req[0x0f] = 0x00; /* ??? 0x00 */ req[0x10] = LOBYTE (scan_bpl); req[0x11] = HIBYTE (scan_bpl); req[0x12] = LOBYTE (scan_ys); req[0x13] = HIBYTE (scan_ys); req[0x14] = motor_mode_1; req[0x15] = motor_mode_2; req[0x16] = LOBYTE (ydpi); req[0x17] = HIBYTE (ydpi); if (backtrack) req[0x18] = request->backtrack_lines; else req[0x18] = 0x00; status = gt68xx_device_req (dev, req, req); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_generic_setup_scan: setup request failed: %s\n", sane_strstatus (status)); return status; } RIE (gt68xx_device_check_result (req, 0x20)); } /* Fill in calculated values */ params->xdpi = xdpi; params->ydpi = ydpi; params->depth = depth; params->color = color; params->pixel_xs = pixel_xs; params->pixel_ys = pixel_ys; params->scan_xs = scan_xs; params->scan_ys = scan_ys; params->scan_bpl = scan_bpl; params->line_mode = line_mode; params->overscan_lines = overscan_lines; params->pixel_x0 = pixel_x0; DBG (6, "gt68xx_generic_setup_scan: leave: ok\n"); return SANE_STATUS_GOOD; } SANE_Status gt68xx_generic_move_paper (GT68xx_Device * dev, GT68xx_Scan_Request * request) { GT68xx_Packet req; SANE_Status status; SANE_Int ydpi; SANE_Int pixel_y0; SANE_Int abs_y0, base_ydpi; GT68xx_Model *model = dev->model; ydpi = request->ydpi; base_ydpi = model->base_ydpi; if (ydpi > model->base_ydpi) ydpi = base_ydpi; pixel_y0 = SANE_UNFIX ((request->y0 + model->y_offset)) * ydpi / MM_PER_INCH + 0.5; abs_y0 = pixel_y0 * base_ydpi / ydpi; DBG (6, "gt68xx_generic_move_paper: base_ydpi=%d\n", base_ydpi); DBG (6, "gt68xx_generic_move_paper: ydpi=%d\n", ydpi); DBG (6, "gt68xx_generic_move_paper: abs_y0=%d\n", abs_y0); /* paper move request */ memset (req, 0, sizeof (req)); req[0] = 0x82; req[1] = 0x01; req[2] = LOBYTE (abs_y0); req[3] = HIBYTE (abs_y0); RIE (gt68xx_device_req (dev, req, req)); DBG (6, "gt68xx_generic_move_paper: leave: ok\n"); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/mustek_usb_low.h0000664000175000017500000002746312112021330016021 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Mustek. Originally maintained by Tom Wang Copyright (C) 2001, 2002 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek 1200UB and similar USB flatbed scanners. */ #ifndef mustek_usb_low_h #define mustek_usb_low_h #include "../include/sane/sane.h" /* ---------------------------------- macros ------------------------------ */ /* calculate the minimum/maximum values */ #if defined(MIN) #undef MIN #endif #if defined(MAX) #undef MAX #endif #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) /* return the lower/upper 8 bits of a 16 bit word */ #define HIBYTE(w) ((SANE_Byte)(((SANE_Word)(w) >> 8) & 0xFF)) #define LOBYTE(w) ((SANE_Byte)(w)) /* RIE: return if error */ #define RIE(function) do {status = function; if (status != SANE_STATUS_GOOD) \ return status;} while (SANE_FALSE) /* ---------------------------------- types ------------------------------- */ typedef enum Mustek_Type { MT_UNKNOWN = 0, MT_1200USB, MT_1200UB, MT_1200CU, MT_1200CU_PLUS, MT_600CU, MT_600USB } Mustek_Type; typedef enum Sensor_Type { ST_NONE = 0, ST_INI = 1, ST_INI_DARK = 2, ST_CANON300 = 3, ST_CANON600 = 4, ST_TOSHIBA600 = 5, ST_CANON300600 = 6, ST_NEC600 = 7 } Sensor_Type; typedef enum Motor_Type { MT_NONE = 0, MT_600 = 1, MT_1200 = 2 } Motor_Type; struct ma1017; typedef struct ma1017 { int fd; SANE_Bool is_opened; SANE_Bool is_rowing; /* A2 */ SANE_Byte append; SANE_Byte test_sram; SANE_Byte fix_pattern; /* A4 */ SANE_Byte select; SANE_Byte frontend; /* A6 */ SANE_Byte rgb_sel_pin; SANE_Byte asic_io_pins; /* A7 */ SANE_Byte timing; SANE_Byte sram_bank; /* A8 */ SANE_Byte dummy_msb; SANE_Byte ccd_width_msb; SANE_Byte cmt_table_length; /* A9 */ SANE_Byte cmt_second_pos; /* A10 + A8ID5 */ SANE_Word ccd_width; /* A11 + A8ID6 */ SANE_Word dummy; /* A12 + A13 */ SANE_Word byte_width; /* A14 + A30W */ SANE_Word loop_count; /* A15 */ SANE_Byte motor_enable; SANE_Byte motor_movement; SANE_Byte motor_direction; SANE_Byte motor_signal; SANE_Byte motor_home; /* A16 */ SANE_Byte pixel_depth; SANE_Byte image_invert; SANE_Byte optical_600; SANE_Byte sample_way; /* A17 + A18 + A19 */ SANE_Byte red_ref; SANE_Byte green_ref; SANE_Byte blue_ref; /* A20 + A21 + A22 */ SANE_Byte red_pd; SANE_Byte green_pd; SANE_Byte blue_pd; /* A23 */ SANE_Byte a23; /* A24 */ SANE_Byte fy1_delay; SANE_Byte special_ad; /* A27 */ SANE_Byte sclk; SANE_Byte sen; SANE_Byte serial_length; /* Use for Rowing */ SANE_Status (*get_row) (struct ma1017 * chip, SANE_Byte * row, SANE_Word * lines_left); SANE_Word cmt_table_length_word; SANE_Word cmt_second_pos_word; SANE_Word row_size; SANE_Word soft_resample; SANE_Word total_lines; SANE_Word lines_left; SANE_Bool is_transfer_table[32]; Sensor_Type sensor; Motor_Type motor; Mustek_Type scanner_type; SANE_Word max_block_size; SANE_Word total_read_urbs; SANE_Word total_write_urbs; } ma1017; typedef enum Channel { CH_NONE = 0, CH_RED = 1, CH_GREEN = 2, CH_BLUE = 3 } Channel; typedef enum Banksize { BS_NONE = 0, BS_4K = 1, BS_8K = 2, BS_16K = 3 } Banksize; typedef enum Pixeldepth { PD_NONE = 0, PD_1BIT = 1, PD_4BIT = 2, PD_8BIT = 3, PD_12BIT = 4 } Pixeldepth; typedef enum Sampleway { SW_NONE = 0, SW_P1P6 = 1, SW_P2P6 = 2, SW_P3P6 = 3, SW_P4P6 = 4, SW_P5P6 = 5, SW_P6P6 = 6 } Sampleway; /* ------------------------- function declarations ------------------------ */ static SANE_Status usb_low_init (ma1017 ** chip); static SANE_Status usb_low_exit (ma1017 * chip); /* Register read and write functions */ /* A0 ~ A1 */ static SANE_Status usb_low_set_cmt_table (ma1017 * chip, SANE_Int index, Channel channel, SANE_Bool is_move_motor, SANE_Bool is_transfer); /* A2 */ static SANE_Status usb_low_get_a2 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_start_cmt_table (ma1017 * chip); static SANE_Status usb_low_stop_cmt_table (ma1017 * chip); static SANE_Status usb_low_set_test_sram_mode (ma1017 * chip, SANE_Bool is_test); static SANE_Status usb_low_set_fix_pattern (ma1017 * chip, SANE_Bool is_fix); /* A3 */ static SANE_Status usb_low_adjust_timing (ma1017 * chip, SANE_Byte data); /* A4 */ static SANE_Status usb_low_get_a4 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_select_timing (ma1017 * chip, SANE_Byte data); static SANE_Status usb_low_turn_frontend_mode (ma1017 * chip, SANE_Bool is_on); /* A6 */ static SANE_Status usb_low_get_a6 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_asic_io_pins (ma1017 * chip, SANE_Byte data); static SANE_Status usb_low_set_rgb_sel_pins (ma1017 * chip, SANE_Byte data); /* A7 */ static SANE_Status usb_low_get_a7 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_timing (ma1017 * chip, SANE_Byte data); static SANE_Status usb_low_set_sram_bank (ma1017 * chip, Banksize banksize); /* A8 */ static SANE_Status usb_low_get_a8 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_cmt_table_length (ma1017 * chip, SANE_Byte table_length); /* A9 */ static SANE_Status usb_low_get_a9 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_cmt_second_position (ma1017 * chip, SANE_Byte position); /* A10 + A8ID5 */ static SANE_Status usb_low_get_a10 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_ccd_width (ma1017 * chip, SANE_Word ccd_width); /* A11 + A8ID6 */ static SANE_Status usb_low_get_a11 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_dummy (ma1017 * chip, SANE_Word dummy); /* A12 + A13 */ static SANE_Status usb_low_get_a12 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_get_a13 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_image_byte_width (ma1017 * chip, SANE_Word row_size); static SANE_Status usb_low_set_soft_resample (ma1017 * chip, SANE_Word soft_resample); /* A14 + A30W */ static SANE_Status usb_low_set_cmt_loop_count (ma1017 * chip, SANE_Word loop_count); /* A15 */ static SANE_Status usb_low_get_a15 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_enable_motor (ma1017 * chip, SANE_Bool is_enable); static SANE_Status usb_low_set_motor_movement (ma1017 * chip, SANE_Bool is_full_step, SANE_Bool is_double_phase, SANE_Bool is_two_step); static SANE_Status usb_low_set_motor_signal (ma1017 * chip, SANE_Byte signal); static SANE_Status usb_low_set_motor_direction (ma1017 * chip, SANE_Bool is_backward); static SANE_Status usb_low_move_motor_home (ma1017 * chip, SANE_Bool is_home, SANE_Bool is_backward); /* A16 */ static SANE_Status usb_low_get_a16 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_image_dpi (ma1017 * chip, SANE_Bool is_optical600, Sampleway sampleway); static SANE_Status usb_low_set_pixel_depth (ma1017 * chip, Pixeldepth pixeldepth); static SANE_Status usb_low_invert_image (ma1017 * chip, SANE_Bool is_invert); /* A17 + A18 + A19 */ static SANE_Status usb_low_get_a17 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_get_a18 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_get_a19 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_red_ref (ma1017 * chip, SANE_Byte red_ref); static SANE_Status usb_low_set_green_ref (ma1017 * chip, SANE_Byte green_ref); static SANE_Status usb_low_set_blue_ref (ma1017 * chip, SANE_Byte blue_ref); /* A20 + A21 + A22 */ static SANE_Status usb_low_get_a20 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_get_a21 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_get_a22 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_red_pd (ma1017 * chip, SANE_Byte red_pd); static SANE_Status usb_low_set_green_pd (ma1017 * chip, SANE_Byte green_pd); static SANE_Status usb_low_set_blue_pd (ma1017 * chip, SANE_Byte blue_pd); /* A23 */ static SANE_Status usb_low_get_a23 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_turn_peripheral_power (ma1017 * chip, SANE_Bool is_on); static SANE_Status usb_low_turn_lamp_power (ma1017 * chip, SANE_Bool is_on); static SANE_Status usb_low_set_io_3 (ma1017 * chip, SANE_Bool is_high); static SANE_Status usb_low_set_led_light_all (ma1017 * chip, SANE_Bool is_light_all); /* A24 */ static SANE_Status usb_low_get_a24 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_ad_timing (ma1017 * chip, SANE_Byte pattern); /* A25 + A26 */ static SANE_Status usb_low_set_serial_byte1 (ma1017 * chip, SANE_Byte data); static SANE_Status usb_low_set_serial_byte2 (ma1017 * chip, SANE_Byte data); /* A27 */ static SANE_Status usb_low_get_a27 (ma1017 * chip, SANE_Byte * value); static SANE_Status usb_low_set_serial_format (ma1017 * chip, SANE_Byte data); /* A31 */ static SANE_Status usb_low_get_home_sensor (ma1017 * chip); /* Special Mode */ static SANE_Status usb_low_start_rowing (ma1017 * chip); static SANE_Status usb_low_stop_rowing (ma1017 * chip); static SANE_Status usb_low_wait_rowing_stop (ma1017 * chip); /* Global functions */ static SANE_Status usb_low_read_all_registers (ma1017 * chip); static SANE_Status usb_low_get_row (ma1017 * chip, SANE_Byte * data, SANE_Word * lines_left); static SANE_Status usb_low_get_row_direct (ma1017 * chip, SANE_Byte * data, SANE_Word * lines_left); static SANE_Status usb_low_get_row_resample (ma1017 * chip, SANE_Byte * data, SANE_Word * lines_left); /* Direct access */ static SANE_Status usb_low_wait_rowing (ma1017 * chip); static SANE_Status usb_low_read_rows (ma1017 * chip, SANE_Byte * data, SANE_Word byte_count); static SANE_Status usb_low_write_reg (ma1017 * chip, SANE_Byte reg_no, SANE_Byte data); static SANE_Status usb_low_read_reg (ma1017 * chip, SANE_Byte reg_no, SANE_Byte * data); static SANE_Status usb_low_identify_scanner (SANE_Int fd, Mustek_Type * scanner_type); static SANE_Status usb_low_open (ma1017 * chip, const char *devname); static SANE_Status usb_low_close (ma1017 * chip); #endif /* defined mustek_usb_low_h */ sane-backends-1.0.27/backend/xerox_mfp-usb.c0000664000175000017500000000552713063340150015557 00000000000000/* * SANE backend for Xerox Phaser 3200MFP * Copyright 2008 ABC * * This program is licensed under GPL + SANE exception. * More info at http://www.sane-project.org/license.html */ #undef BACKEND_NAME #define BACKEND_NAME xerox_mfp #define DEBUG_DECLARE_ONLY #define DEBUG_NOT_STATIC #include "sane/config.h" #include "sane/saneopts.h" #include "sane/sanei_config.h" #include "sane/sanei_backend.h" #include "sane/sanei_debug.h" #include "sane/sanei_usb.h" #include "xerox_mfp.h" extern int sanei_debug_xerox_mfp; int usb_dev_request(struct device *dev, SANE_Byte *cmd, size_t cmdlen, SANE_Byte *resp, size_t *resplen) { SANE_Status status; size_t len = cmdlen; if (cmd && cmdlen) { status = sanei_usb_write_bulk(dev->dn, cmd, &cmdlen); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: sanei_usb_write_bulk: %s\n", __func__, sane_strstatus(status)); return SANE_STATUS_IO_ERROR; } if (cmdlen != len) { DBG(1, "%s: sanei_usb_write_bulk: wanted %lu bytes, wrote %lu bytes\n", __func__, (size_t)len, (size_t)cmdlen); return SANE_STATUS_IO_ERROR; } } if (resp && resplen) { status = sanei_usb_read_bulk(dev->dn, resp, resplen); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: sanei_usb_read_bulk: %s\n", __func__, sane_strstatus(status)); return SANE_STATUS_IO_ERROR; } } return SANE_STATUS_GOOD; } SANE_Status usb_dev_open(struct device *dev) { SANE_Status status; DBG(3, "%s: open %p\n", __func__, (void *)dev); status = sanei_usb_open(dev->sane.name, &dev->dn); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: sanei_usb_open(%s): %s\n", __func__, dev->sane.name, sane_strstatus(status)); dev->dn = -1; return status; } sanei_usb_clear_halt(dev->dn); return SANE_STATUS_GOOD; } void usb_dev_close(struct device *dev) { if (!dev) return; DBG(3, "%s: closing dev %p\n", __func__, (void *)dev); /* finish all operations */ if (dev->scanning) { dev->cancel = 1; /* flush READ_IMAGE data */ if (dev->reading) sane_read(dev, NULL, 1, NULL); /* send cancel if not sent before */ if (dev->state != SANE_STATUS_CANCELLED) ret_cancel(dev, 0); } sanei_usb_clear_halt(dev->dn); /* unstall for next users */ sanei_usb_close(dev->dn); dev->dn = -1; } /* SANE API ignores return code of this callback */ SANE_Status usb_configure_device(const char *devname, SANE_Status(*attach)(const char *dev)) { sanei_usb_set_timeout(1000); sanei_usb_attach_matching_devices(devname, attach); sanei_usb_set_timeout(30000); return SANE_STATUS_GOOD; } /* xerox_mfp-usb.c */ sane-backends-1.0.27/backend/canon.h0000664000175000017500000002431312775312260014070 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 BYTEC GmbH Germany Written by Helmut Koeberle, Email: helmut.koeberle@bytec.de Modified by Manuel Panea , Markus Mertinat , and ULrich Deiters This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef canon_h #define canon_h 1 /* all the different possible model names. */ #define FB1200S "IX-12015E " #define FB620S "IX-06035E " #define CS300 "IX-03035B " #define CS600 "IX-06015C " #define CS2700F "IX-27015C " #define IX_4025 "IX-4025 " #define IX_4015 "IX-4015 " #define IX_3010 "IX-3010 " #include #define AUTO_DOC_FEEDER_UNIT 0x01 #define TRANSPARENCY_UNIT 0x02 #define TRANSPARENCY_UNIT_FB1200 0x03 #define SCAN_CONTROL_CONDITIONS 0x20 #define SCAN_CONTROL_CON_FB1200 0x21 #define ALL_SCAN_MODE_PAGES 0x3F #define RED 0 #define GREEN 1 #define BLUE 2 #define ADF_STAT_NONE 0 #define ADF_STAT_INACTIVE 1 #define ADF_STAT_ACTIVE 2 #define ADF_STAT_DISABLED 3 #define ADF_Status (4+2) /* byte positioning */ #define ADF_Settings (4+3) /* in data block */ #define ADF_NOT_PRESENT 0x01 /* bit selection */ #define ADF_PROBLEM 0x0E /* from bytes in */ #define ADF_PRIORITY 0x03 /* data block. */ #define ADF_FEEDER 0x04 /* */ #define TPU_STAT_NONE 0 #define TPU_STAT_INACTIVE 1 #define TPU_STAT_ACTIVE 2 #define CS3_600 0 /* CanoScan 300/600 */ #define CS2700 1 /* CanoScan 2700F */ #define FB620 2 /* CanoScan FB620S */ #define FS2710 3 /* CanoScan FS2710S */ #define FB1200 4 /* CanoScan FB1200S */ #define IX4015 5 /* IX-4015 */ #ifndef MAX #define MAX(A,B) (((A) > (B))? (A) : (B)) #endif #ifndef MIN #define MIN(A,B) (((A) < (B))? (A) : (B)) #endif #ifndef SSIZE_MAX #define SSIZE_MAX LONG_MAX #endif typedef struct { SANE_Int Status; /* Auto Document Feeder Unit Status */ SANE_Int Problem; /* ADF Problems list */ SANE_Int Priority; /* ADF Priority setting */ SANE_Int Feeder; /* ADF Feeder setting */ } CANON_ADF; typedef struct { SANE_Int Status; /* Transparency Unit Status */ SANE_Bool PosNeg; /* Negative/Positive Film */ SANE_Int Transparency; /* TPU Transparency */ SANE_Int ControlMode; /* TPU Density Control Mode */ SANE_Int FilmType; /* TPU Film Type */ } CANON_TPU; typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_NEGATIVE, /* Reverse image format */ OPT_NEGATIVE_TYPE, /* Negative film type */ OPT_SCANNING_SPEED, OPT_RESOLUTION_GROUP, OPT_RESOLUTION_BIND, OPT_HW_RESOLUTION_ONLY, OPT_X_RESOLUTION, OPT_Y_RESOLUTION, OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_THRESHOLD, OPT_MIRROR, OPT_CUSTOM_GAMMA, /* use custom gamma tables? */ OPT_CUSTOM_GAMMA_BIND, /* The gamma vectors MUST appear in the order gray, red, green, blue. */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_AE, /* Auto Exposure */ OPT_CALIBRATION_GROUP, /* Calibration for FB620S */ OPT_CALIBRATION_NOW, /* Execute Calibration now for FB620S */ OPT_SCANNER_SELF_DIAGNOSTIC, /* Self diagnostic for FB620S */ OPT_RESET_SCANNER, /* Reset scanner for FB620S */ OPT_EJECT_GROUP, OPT_EJECT_AFTERSCAN, OPT_EJECT_BEFOREEXIT, OPT_EJECT_NOW, OPT_FOCUS_GROUP, OPT_AF, /* Auto Focus */ OPT_AF_ONCE, /* Auto Focus only once between ejects */ OPT_FOCUS, /* Manual focus position */ OPT_MARGINS_GROUP, /* scan margins */ OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_COLORS_GROUP, OPT_HNEGATIVE, /* Reverse image format */ OPT_BIND_HILO, /* Same values vor highlight and shadow points for red, green, blue */ OPT_HILITE_R, /* highlight point for red */ OPT_SHADOW_R, /* shadow point for red */ OPT_HILITE_G, /* highlight point for green */ OPT_SHADOW_G, /* shadow point for green */ OPT_HILITE_B, /* highlight point for blue */ OPT_SHADOW_B, /* shadow point for blue */ OPT_ADF_GROUP, /* to allow display of options. */ OPT_FLATBED_ONLY, /* in case you have a sheetfeeder but don't want to use it. */ OPT_TPU_GROUP, OPT_TPU_ON, OPT_TPU_PN, OPT_TPU_DCM, OPT_TPU_TRANSPARENCY, OPT_TPU_FILMTYPE, OPT_PREVIEW, /* must come last: */ NUM_OPTIONS } CANON_Option; typedef struct CANON_Info { int model; SANE_Range xres_range; SANE_Range yres_range; SANE_Range x_range; SANE_Range y_range; SANE_Range brightness_range; SANE_Range contrast_range; SANE_Range threshold_range; SANE_Range HiliteR_range; SANE_Range ShadowR_range; SANE_Range HiliteG_range; SANE_Range ShadowG_range; SANE_Range HiliteB_range; SANE_Range ShadowB_range; SANE_Range focus_range; SANE_Range x_adf_range; SANE_Range y_adf_range; SANE_Int xres_default; SANE_Int yres_default; SANE_Int bmu; SANE_Int mud; SANE_Range TPU_Transparency_range; SANE_Int TPU_Stat; SANE_Bool can_focus; /* has got focus control */ SANE_Bool can_autoexpose; /* can do autoexposure by hardware */ SANE_Bool can_calibrate; /* has got calibration control */ SANE_Bool can_diagnose; /* has diagnostic command */ SANE_Bool can_eject; /* can eject medium */ SANE_Bool can_mirror; /* can mirror image by hardware */ SANE_Bool is_filmscanner; SANE_Bool has_fixed_resolutions; /* only a finite number possible */ } CANON_Info; typedef struct CANON_Device { struct CANON_Device *next; SANE_Device sane; CANON_Info info; CANON_ADF adf; CANON_TPU tpu; } CANON_Device; typedef struct CANON_Scanner { struct CANON_Scanner *next; int fd; CANON_Device *hw; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; char *sense_str; /* sense string */ SANE_Int gamma_table[4][256]; SANE_Parameters params; SANE_Bool AF_NOW; /* To keep track of when to do AF */ SANE_Int xres; SANE_Int yres; SANE_Int ulx; SANE_Int uly; SANE_Int width; SANE_Int length; SANE_Int brightness; SANE_Int contrast; SANE_Int threshold; SANE_Int image_composition; SANE_Int bpp; SANE_Bool RIF; /* Reverse Image Format */ SANE_Int negative_filmtype; SANE_Int scanning_speed; SANE_Bool GRC; /* Gray Response Curve */ SANE_Bool Mirror; SANE_Bool AE; /* Auto Exposure */ SANE_Int HiliteR; SANE_Int ShadowR; SANE_Int HiliteG; SANE_Int ShadowG; SANE_Int HiliteB; SANE_Int ShadowB; /* 990320, ss: array for fixed resolutions */ SANE_Word xres_word_list[16]; SANE_Word yres_word_list[16]; SANE_Byte *inbuffer; /* modification for FB620S */ SANE_Byte *outbuffer; /* modification for FB620S */ SANE_Int buf_used; /* modification for FB620S */ SANE_Int buf_pos; /* modification for FB620S */ time_t time0; /* modification for FB620S */ time_t time1; /* modification for FB620S */ int switch_preview; /* modification for FB620S */ int reset_flag; /* modification for FB620S */ int tmpfile; /* modification for FB1200S */ size_t bytes_to_read; int scanning; u_char gamma_map[4][4096]; /* for FS2710S: */ int colour; /* index to gamma_map */ int auxbuf_len; /* size of auxiliary buffer */ u_char *auxbuf; } CANON_Scanner; static char *option_name[] = { "OPT_NUM_OPTS", "OPT_MODE_GROUP", "OPT_MODE", "OPT_NEGATIVE", "OPT_NEGATIVE_TYPE", "OPT_SCANNING_SPEED", "OPT_RESOLUTION_GROUP", "OPT_RESOLUTION_BIND", "OPT_HW_RESOLUTION_ONLY", "OPT_X_RESOLUTION", "OPT_Y_RESOLUTION", "OPT_ENHANCEMENT_GROUP", "OPT_BRIGHTNESS", "OPT_CONTRAST", "OPT_THRESHOLD", "OPT_MIRROR", "OPT_CUSTOM_GAMMA", "OPT_CUSTOM_GAMMA_BIND", "OPT_GAMMA_VECTOR", "OPT_GAMMA_VECTOR_R", "OPT_GAMMA_VECTOR_G", "OPT_GAMMA_VECTOR_B", "OPT_AE", "OPT_CALIBRATION_GROUP", "OPT_CALIBRATION_NOW", "OPT_SCANNER_SELF_DIAGNOSTIC", "OPT_RESET_SCANNER", "OPT_EJECT_GROUP", "OPT_EJECT_AFTERSCAN", "OPT_EJECT_BEFOREEXIT", "OPT_EJECT_NOW", "OPT_FOCUS_GROUP", "OPT_AF", "OPT_AF_ONCE", "OPT_FOCUS", "OPT_MARGINS_GROUP", "OPT_TL_X", "OPT_TL_Y", "OPT_BR_X", "OPT_BR_Y", "OPT_COLORS_GROUP", "OPT_HNEGATIVE", "OPT_BIND_HILO", "OPT_HILITE_R", "OPT_SHADOW_R", "OPT_HILITE_G", "OPT_SHADOW_G", "OPT_HILITE_B", "OPT_SHADOW_B", "OPT_ADF_GROUP", "OPT_FLATBED_ONLY", "OPT_TPU_GROUP", "OPT_TPU_ON", "OPT_TPU_PN", "OPT_TPU_DCM", "OPT_TPU_TRANSPARENCY", "OPT_TPU_FILMTYPE", "OPT_PREVIEW", "NUM_OPTIONS" }; #endif /* not canon_h */ sane-backends-1.0.27/backend/pixma_bjnp.c0000664000175000017500000021522013063340150015101 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2008 2012 by Louis Lagendijk This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME #define BACKEND_NAME bjnp #include "../include/sane/config.h" #include "../include/sane/sane.h" /* * Standard types etc */ #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #include #include #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_LIMITS_H #include #endif /* * networking stuff */ #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #include #include #include #include #ifdef HAVE_IFADDRS_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_PWD_H #include #endif #include #ifdef HAVE_FCNTL_H #include #endif #include "pixma_bjnp_private.h" #include "pixma_bjnp.h" /* #include "pixma_rename.h" */ #include "pixma.h" #include "pixma_common.h" #ifndef SSIZE_MAX # define SSIZE_MAX LONG_MAX #endif /* static data */ static bjnp_device_t device[BJNP_NO_DEVICES]; static int bjnp_no_devices = 0; /* * Private functions */ static void u8tohex (char *string, const uint8_t *value, int len ) { int i; int x; const char hdigit[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; for (i = 0; i < len; i++) { x = value[i]; string[ 2 * i ] = hdigit[(x >> 4) & 0xf]; string[ 2 * i + 1] = hdigit[x & 0xf]; } string[2 * len ] = '\0'; } static void u32tohex (uint32_t x, char *str) { uint8_t uint8[4]; uint8[0] = (uint8_t)(x >> 24); uint8[1] = (uint8_t)(x >> 16); uint8[2] = (uint8_t)(x >> 8); uint8[3] = (uint8_t)x ; u8tohex(str, uint8, 4); } static void bjnp_hexdump (int level, const void *d_, unsigned len) { const uint8_t *d = (const uint8_t *) (d_); unsigned ofs, c, plen; char line[100]; /* actually only 1+8+1+8*3+1+8*3+1 = 61 bytes needed */ if (level > DBG_LEVEL) return; if (level == DBG_LEVEL) /* if debuglevel == exact match and buffer contains more than 3 lines, print 2 lines + .... */ plen = (len > 64) ? 32: len; else plen = len; ofs = 0; while (ofs < plen) { char *p; line[0] = ' '; u32tohex (ofs, line + 1); line[9] = ':'; p = line + 10; for (c = 0; c != 16 && (ofs + c) < plen; c++) { u8tohex (p, d + ofs + c, 1); p[2] = ' '; p += 3; if (c == 7) { p[0] = ' '; p++; } } p[0] = '\0'; bjnp_dbg (level, "%s\n", line); ofs += c; } if (len > plen) bjnp_dbg(level, "......\n"); } static int sa_is_equal( const bjnp_sockaddr_t * sa1, const bjnp_sockaddr_t * sa2) { if ((sa1 == NULL) || (sa2 == NULL) ) return 0; if (sa1->addr.sa_family == sa2-> addr.sa_family) { if( sa1 -> addr.sa_family == AF_INET) { if ( (sa1->ipv4.sin_port == sa2->ipv4.sin_port) && (sa1->ipv4.sin_addr.s_addr == sa2->ipv4.sin_addr.s_addr)) { return 1; } } #ifdef ENABLE_IPV6 else if (sa1 -> addr.sa_family == AF_INET6 ) { if ( (sa1-> ipv6.sin6_port == sa2->ipv6.sin6_port) && (memcmp(&(sa1->ipv6.sin6_addr), &(sa2->ipv6.sin6_addr), sizeof(struct in6_addr)) == 0)) { return 1; } } #endif } return 0; } static int sa_size( const bjnp_sockaddr_t *sa) { switch (sa -> addr.sa_family) { case AF_INET: return (sizeof(struct sockaddr_in) ); #ifdef ENABLE_IPV6 case AF_INET6: return (sizeof(struct sockaddr_in6) ); #endif default: /* should not occur */ return sizeof( bjnp_sockaddr_t ); } } static int get_protocol_family( const bjnp_sockaddr_t *sa) { switch (sa -> addr.sa_family) { case AF_INET: return PF_INET; break; #ifdef ENABLE_IPV6 case AF_INET6: return PF_INET6; break; #endif default: /* should not occur */ return -1; } } static void get_address_info ( const bjnp_sockaddr_t *addr, char * addr_string, int *port) { char tmp_addr[BJNP_HOST_MAX]; if ( addr->addr.sa_family == AF_INET) { inet_ntop( AF_INET, &(addr -> ipv4.sin_addr.s_addr), addr_string, BJNP_HOST_MAX); *port = ntohs (addr->ipv4.sin_port); } #ifdef ENABLE_IPV6 else if (addr->addr.sa_family == AF_INET6) { inet_ntop( AF_INET6, addr -> ipv6.sin6_addr.s6_addr, tmp_addr, sizeof(tmp_addr) ); if (IN6_IS_ADDR_LINKLOCAL( &(addr -> ipv6.sin6_addr) ) ) sprintf(addr_string, "[%s%%%d]", tmp_addr, addr -> ipv6.sin6_scope_id); *port = ntohs (addr->ipv6.sin6_port); } #endif else { /* unknown address family, should not occur */ strcpy(addr_string, "Unknown address family"); *port = 0; } } static int parse_IEEE1284_to_model (char *scanner_id, char *model) { /* * parses the IEEE1284 ID of the scanner to retrieve make and model * of the scanner * Returns: 0 = not found * 1 = found, model is set */ char s[BJNP_IEEE1284_MAX]; char *tok; strncpy (s, scanner_id, BJNP_IEEE1284_MAX); s[BJNP_IEEE1284_MAX - 1] = '\0'; model[0] = '\0'; tok = strtok (s, ";"); while (tok != NULL) { /* MDL contains make and model */ if (strncmp (tok, "MDL:", 4) == 0) { strncpy (model, tok + 4, BJNP_IEEE1284_MAX); model[BJNP_IEEE1284_MAX -1] = '\0'; return 1; } tok = strtok (NULL, ";"); } return 0; } static int charTo2byte (char *d, const char *s, int len) { /* * copy ASCII string to UTF-16 unicode string * len is length of destination buffer * Returns: number of characters copied */ int done = 0; int copied = 0; int i; len = len / 2; for (i = 0; i < len; i++) { d[2 * i] = '\0'; if (s[i] == '\0') { done = 1; } if (done == 0) { d[2 * i + 1] = s[i]; copied++; } else d[2 * i + 1] = '\0'; } return copied; } static bjnp_protocol_defs_t *get_protocol_by_method( char *method) { int i = 0; while ( bjnp_protocol_defs[i].method_string != NULL) { if (strcmp(method, bjnp_protocol_defs[i].method_string) == 0) { return &bjnp_protocol_defs[i]; } i++; } return NULL; } static bjnp_protocol_defs_t *get_protocol_by_proto_string( char *proto_string) { int i = 0; while ( bjnp_protocol_defs[i].proto_string != NULL) { if (strncmp(proto_string, bjnp_protocol_defs[i].proto_string, 4) == 0) { return &bjnp_protocol_defs[i]; } i++; } return NULL; } static char * getusername (void) { static char noname[] = "sane_pixma"; struct passwd *pwdent; #ifdef HAVE_PWD_H if (((pwdent = getpwuid (geteuid ())) != NULL) && (pwdent->pw_name != NULL)) return pwdent->pw_name; #endif return noname; } static char * determine_scanner_serial (const char *hostname, const char * mac_address, char *serial) { char *dot; char copy[BJNP_HOST_MAX]; /* determine a "serial number" for the scanner */ /* if available we use the hostname or ipv4 address of the printer */ /* if we only have a literal ipv6 address, we use the mac-address */ strcpy(copy, hostname); if (strlen (copy) >= SERIAL_MAX) { /* make the string fit into the serial */ /* if this is a FQDN, not an ip-address, remove domain part of the name */ if ((dot = strchr (copy, '.')) != NULL) { *dot = '\0'; } } /* check if name is still to long. If so use the mac-address */ if (strlen(copy) >= SERIAL_MAX) { strcpy(copy, mac_address); } strcpy( serial, copy ); return serial; } static int bjnp_open_tcp (int devno) { int sock; int val; bjnp_sockaddr_t *addr = device[devno].addr; char host[BJNP_HOST_MAX]; int port; get_address_info( addr, host, &port); PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_open_tcp: Setting up a TCP socket, dest: %s port %d\n", host, port ) ); if ((sock = socket (get_protocol_family( addr ) , SOCK_STREAM, 0)) < 0) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not create socket: %s\n", strerror (errno))); return -1; } val = 1; setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val)); #if 0 val = 1; setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, &val, sizeof (val)); val = 1; #endif /* * Using TCP_NODELAY improves responsiveness, especially on systems * with a slow loopback interface... */ val = 1; setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val)); /* * Close this socket when starting another process... */ fcntl (sock, F_SETFD, FD_CLOEXEC); if (connect (sock, &(addr->addr), sa_size(device[devno].addr) )!= 0) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not connect to scanner: %s\n", strerror (errno))); return -1; } device[devno].tcp_socket = sock; return 0; } static int split_uri (const char *devname, char *method, char *host, char *port, char *args) { char copy[1024]; char *start; char next; int i; strncpy (copy, devname, 1024); copy[1023] = '\0'; start = copy; /* * retrieve method */ i = 0; while ((start[i] != '\0') && (start[i] != ':')) { i++; } if (((strncmp (start + i, "://", 3) != 0)) || (i > BJNP_METHOD_MAX -1 )) { PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find method in %s (offset %d)\n", devname, i)); return -1; } start[i] = '\0'; strcpy (method, start); start = start + i + 3; /* * retrieve host */ if (start[0] == '[') { /* literal IPv6 address */ char *end_of_address = strchr(start, ']'); if ( ( end_of_address == NULL) || ( (end_of_address[1] != ':') && (end_of_address[1] != '/' ) && (end_of_address[1] != '\0' )) || ( (end_of_address - start) >= BJNP_HOST_MAX ) ) { PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find hostname or address in %s\n", devname)); return -1; } next = end_of_address[1]; *end_of_address = '\0'; strcpy(host, start + 1); start = end_of_address + 2; } else { i = 0; while ((start[i] != '\0') && (start[i] != '/') && (start[i] != ':')) { i++; } next = start[i]; start[i] = '\0'; if ((i == 0) || (i >= BJNP_HOST_MAX ) ) { PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find hostname or address in %s\n", devname)); return -1; } strcpy (host, start); start = start + i +1; } /* * retrieve port number */ if (next != ':') strcpy(port, ""); else { char *end_of_port = strchr(start, '/'); if (end_of_port == NULL) { next = '\0'; } else { next = *end_of_port; *end_of_port = '\0'; } if ((strlen(start) == 0) || (strlen(start) >= BJNP_PORT_MAX ) ) { PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Can not find port in %s (have \"%s\")\n", devname, start)); return -1; } strcpy(port, start); start = end_of_port + 1; } /* * Retrieve arguments */ if (next == '/') { i = strlen(start); if ( i >= BJNP_ARGS_MAX) { PDBG (bjnp_dbg (LOG_NOTICE, "split_uri: ERROR - Argument string too long in %s\n", devname)); } strcpy (args, start); } else strcpy (args, ""); return 0; } static void set_cmd_from_string (char* protocol_string, struct BJNP_command *cmd, char cmd_code, int payload_len) { /* * Set command buffer with command code, session_id and length of payload * Returns: sequence number of command */ strncpy (cmd->BJNP_id, protocol_string, sizeof (cmd->BJNP_id)); cmd->dev_type = BJNP_CMD_SCAN; cmd->cmd_code = cmd_code; cmd->unknown1 = htons (0); /* device not yet opened, use 0 for serial and session) */ cmd->seq_no = htons (0); cmd->session_id = htons (0); cmd->payload_len = htonl (payload_len); } static void set_cmd_for_dev (int devno, struct BJNP_command *cmd, char cmd_code, int payload_len) { /* * Set command buffer with command code, session_id and length of payload * Returns: sequence number of command */ strncpy (cmd->BJNP_id, device[devno].protocol_string, sizeof (cmd->BJNP_id)); cmd->dev_type = BJNP_CMD_SCAN; cmd->cmd_code = cmd_code; cmd->unknown1 = htons (0); cmd->seq_no = htons (++(device[devno].serial)); cmd->session_id = (cmd_code == CMD_UDP_POLL ) ? 0 : htons (device[devno].session_id); device[devno].last_cmd = cmd_code; cmd->payload_len = htonl (payload_len); } static int bjnp_setup_udp_socket ( const int dev_no ) { /* * Setup a udp socket for the given device * Returns the socket or -1 in case of error */ int sockfd; char addr_string[256]; int port; bjnp_sockaddr_t * addr = device[dev_no].addr; get_address_info( addr, addr_string, &port); PDBG (bjnp_dbg (LOG_DEBUG, "setup_udp_socket: Setting up a UDP socket, dest: %s port %d\n", addr_string, port ) ); if ((sockfd = socket (get_protocol_family( addr ), SOCK_DGRAM, IPPROTO_UDP)) == -1) { PDBG (bjnp_dbg (LOG_CRIT, "setup_udp_socket: ERROR - can not open socket - %s\n", strerror (errno))); return -1; } if (connect (sockfd, &(device[dev_no].addr->addr), sa_size(device[dev_no].addr) )!= 0) { PDBG (bjnp_dbg (LOG_CRIT, "setup_udp_socket: ERROR - connect failed- %s\n", strerror (errno))); close(sockfd); return -1; } return sockfd; } static int udp_command (const int dev_no, char *command, int cmd_len, char *response, int resp_len) { /* * send udp command to given device and recieve the response` * returns: the legth of the response or -1 */ int sockfd; struct timeval timeout; int result; int try, attempt; int numbytes; fd_set fdset; struct BJNP_command *resp = (struct BJNP_command *) response; struct BJNP_command *cmd = (struct BJNP_command *) command; if ( (sockfd = bjnp_setup_udp_socket(dev_no) ) == -1 ) { PDBG (bjnp_dbg( LOG_CRIT, "udp_command: ERROR - Can not setup socket\n") ); return -1; } for (try = 0; try < BJNP_UDP_RETRY_MAX; try++) { if ((numbytes = send (sockfd, command, cmd_len, 0)) != cmd_len) { PDBG (bjnp_dbg (LOG_NOTICE, "udp_command: ERROR - Sent %d bytes, expected %d\n", numbytes, cmd_len)); continue; } attempt = 0; /* wait for data to be received, ignore signals being received */ /* skip late udp responses (they have an incorrect sequence number */ do { FD_ZERO (&fdset); FD_SET (sockfd, &fdset); timeout.tv_sec = device[dev_no].bjnp_timeout /1000; timeout.tv_usec = device[dev_no].bjnp_timeout %1000; } while (((result = select (sockfd + 1, &fdset, NULL, NULL, &timeout)) <= 0) && (errno == EINTR) && (attempt++ < BJNP_MAX_SELECT_ATTEMPTS) && resp-> seq_no != cmd->seq_no); if (result <= 0) { PDBG (bjnp_dbg (LOG_NOTICE, "udp_command: ERROR - select failed: %s\n", result == 0 ? "timed out" : strerror (errno))); continue; } if ((numbytes = recv (sockfd, response, resp_len, 0)) == -1) { PDBG (bjnp_dbg (LOG_NOTICE, "udp_command: ERROR - recv failed: %s", strerror (errno))); continue; } close(sockfd); return numbytes; } /* no response even after retry */ close(sockfd); PDBG (bjnp_dbg (LOG_CRIT, "udp_command: ERROR - no data received (timeout = %d)\n", device[dev_no].bjnp_timeout ) ); return -1; } static int get_scanner_id (const int dev_no, char *model) { /* * get scanner identity * Sets model (make and model) * Return 0 on success, -1 in case of errors */ struct BJNP_command cmd; struct IDENTITY *id; char scanner_id[BJNP_IEEE1284_MAX]; int resp_len; char resp_buf[BJNP_RESP_MAX]; int id_len; /* set defaults */ strcpy (model, "Unidentified scanner"); set_cmd_for_dev (dev_no, &cmd, CMD_UDP_GET_ID, 0); PDBG (bjnp_dbg (LOG_DEBUG2, "get_scanner_id: Get scanner identity\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &cmd, sizeof (struct BJNP_command))); if ( ( resp_len = udp_command (dev_no, (char *) &cmd, sizeof (struct BJNP_command), resp_buf, BJNP_RESP_MAX) ) < (int)sizeof(struct BJNP_command) ) { PDBG (bjnp_dbg (LOG_DEBUG, "get_scanner_id: ERROR - Failed to retrieve scanner identity:\n")); return -1; } PDBG (bjnp_dbg (LOG_DEBUG2, "get_scanner_id: scanner identity:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); id = (struct IDENTITY *) resp_buf; if (device[dev_no].protocol == PROTOCOL_BJNP) { id_len = MIN(ntohl( id-> cmd.payload_len ) - sizeof(id-> payload.bjnp.id_len), BJNP_IEEE1284_MAX); strncpy(scanner_id, id->payload.bjnp.id, id_len); scanner_id[id_len] = '\0'; } else { id_len = MIN(ntohl( id-> cmd.payload_len ), BJNP_IEEE1284_MAX); strncpy(scanner_id, id->payload.mfnp.id, id_len); scanner_id[id_len] = '\0'; } PDBG (bjnp_dbg (LOG_INFO, "get_scanner_id: Scanner identity string = %s - length = %d\n", scanner_id, id_len)); /* get make&model from IEEE1284 id */ if (model != NULL) { parse_IEEE1284_to_model (scanner_id, model); PDBG (bjnp_dbg (LOG_INFO, "get_scanner_id: Scanner model = %s\n", model)); } return 0; } static int get_scanner_name(const bjnp_sockaddr_t *scanner_sa, char *host) { /* * Parse identify command responses to ip-address * and hostname. Return qulity of the address */ struct addrinfo *results; struct addrinfo *result; char ip_address[BJNP_HOST_MAX]; int port; int error; int match = 0; int level; char service[64]; #ifdef ENABLE_IPV6 if ( ( scanner_sa -> addr.sa_family == AF_INET6 ) && ( IN6_IS_ADDR_LINKLOCAL( &(scanner_sa -> ipv6.sin6_addr ) ) ) ) level = BJNP_ADDRESS_IS_LINK_LOCAL; else #endif level = BJNP_ADDRESS_IS_GLOBAL; get_address_info( scanner_sa, ip_address, &port ); /* do reverse name lookup, if hostname can not be found return ip-address */ if( (error = getnameinfo( &(scanner_sa -> addr) , sa_size( scanner_sa), host, BJNP_HOST_MAX , NULL, 0, NI_NAMEREQD) ) != 0 ) { PDBG (bjnp_dbg(LOG_INFO, "get_scanner_name: Name for %s not found : %s\n", ip_address, gai_strerror(error) ) ); strcpy(host, ip_address); return level; } else { sprintf(service, "%d", port); /* some buggy routers return rubbish if reverse lookup fails, so * we do a forward lookup on the received name to see if the result matches */ if (getaddrinfo(host , service, NULL, &results) == 0) { result = results; while (result != NULL) { if(sa_is_equal( scanner_sa, (bjnp_sockaddr_t *)result-> ai_addr)) { /* found match, good */ PDBG (bjnp_dbg (LOG_INFO, "get_scanner_name: Forward lookup for %s succeeded, using as hostname\n", host)); match = 1; level = BJNP_ADDRESS_HAS_FQDN; break; } result = result-> ai_next; } freeaddrinfo(results); if (match != 1) { PDBG (bjnp_dbg (LOG_INFO, "get_scanner_name: Forward lookup for %s succeeded, IP-address does not match, using IP-address %s instead\n", host, ip_address)); strcpy (host, ip_address); } } else { /* forward lookup failed, use ip-address */ PDBG ( bjnp_dbg (LOG_INFO, "get_scanner_name: Forward lookup of %s failed, using IP-address", ip_address)); strcpy (host, ip_address); } } return level; } static int get_port_from_sa(const bjnp_sockaddr_t scanner_sa) { #ifdef ENABLE_IPV6 if ( scanner_sa.addr.sa_family == AF_INET6 ) { return ntohs(scanner_sa.ipv6.sin6_port); } else #endif if ( scanner_sa.addr.sa_family == AF_INET ) { return ntohs(scanner_sa.ipv4.sin_port); } return -1; } static int create_broadcast_socket( const bjnp_sockaddr_t * local_addr ) { int sockfd = -1; int broadcast = 1; int ipv6_v6only = 1; if ((sockfd = socket (local_addr-> addr.sa_family, SOCK_DGRAM, 0)) == -1) { PDBG (bjnp_dbg (LOG_CRIT, "create_broadcast_socket: ERROR - can not open socket - %s", strerror (errno))); return -1; } /* Set broadcast flag on socket */ if (setsockopt (sockfd, SOL_SOCKET, SO_BROADCAST, (const char *) &broadcast, sizeof (broadcast)) != 0) { PDBG (bjnp_dbg (LOG_CRIT, "create_broadcast_socket: ERROR - setting socket option SO_BROADCAST failed - %s", strerror (errno))); close (sockfd); return -1; }; /* For an IPv6 socket, bind to v6 only so a V6 socket can co-exist with a v4 socket */ if ( (local_addr -> addr.sa_family == AF_INET6) && ( setsockopt (sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &ipv6_v6only, sizeof (ipv6_v6only)) != 0) ) { PDBG (bjnp_dbg (LOG_CRIT, "create_broadcast_socket: ERROR - setting socket option IPV6_V6ONLY failed - %s", strerror (errno))); close (sockfd); return -1; }; if (bind (sockfd, &(local_addr->addr), (socklen_t) sa_size( local_addr)) != 0) { PDBG (bjnp_dbg (LOG_CRIT, "create_broadcast_socket: ERROR - bind socket to local address failed - %s\n", strerror (errno))); close (sockfd); return -1; } return sockfd; } static int prepare_socket(const char *if_name, const bjnp_sockaddr_t *local_sa, const bjnp_sockaddr_t *broadcast_sa, bjnp_sockaddr_t * dest_sa) { /* * Prepare a socket for broadcast or multicast * Input: * if_name: the name of the interface * local_sa: local address to use * broadcast_sa: broadcast address to use, if NULL we use all hosts * dest_sa: (write) where to return destination address of broadcast * retuns: open socket or -1 */ int socket = -1; bjnp_sockaddr_t local_sa_copy; if ( local_sa == NULL ) { PDBG (bjnp_dbg (LOG_DEBUG, "prepare_socket: %s is not a valid IPv4 interface, skipping...\n", if_name)); return -1; } memset( &local_sa_copy, 0, sizeof(local_sa_copy) ); memcpy( &local_sa_copy, local_sa, sa_size(local_sa) ); switch( local_sa_copy.addr.sa_family ) { case AF_INET: { local_sa_copy.ipv4.sin_port = htons(BJNP_PORT_SCAN); if (local_sa_copy.ipv4.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) { /* not a valid interface */ PDBG (bjnp_dbg (LOG_DEBUG, "prepare_socket: %s is not a valid IPv4 interface, skipping...\n", if_name)); return -1; } /* send broadcasts to the broadcast address of the interface */ memcpy(dest_sa, broadcast_sa, sa_size(dest_sa) ); /* we fill port when we send the broadcast */ dest_sa -> ipv4.sin_port = htons(0); if ( (socket = create_broadcast_socket( &local_sa_copy) ) != -1) { PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: %s is IPv4 capable, sending broadcast, socket = %d\n", if_name, socket)); } else { PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: ERROR - %s is IPv4 capable, but failed to create a socket.\n", if_name)); return -1; } } break; #ifdef ENABLE_IPV6 case AF_INET6: { local_sa_copy.ipv6.sin6_port = htons(BJNP_PORT_SCAN); if (IN6_IS_ADDR_LOOPBACK( &(local_sa_copy.ipv6.sin6_addr) ) ) { /* not a valid interface */ PDBG (bjnp_dbg (LOG_DEBUG, "prepare_socket: %s is not a valid IPv6 interface, skipping...\n", if_name)); return -1; } else { dest_sa -> ipv6.sin6_family = AF_INET6; /* We fill port when we send the broadcast */ dest_sa -> ipv6.sin6_port = htons(0); inet_pton(AF_INET6, "ff02::1", dest_sa -> ipv6.sin6_addr.s6_addr); if ( (socket = create_broadcast_socket( &local_sa_copy ) ) != -1) { PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: %s is IPv6 capable, sending broadcast, socket = %d\n", if_name, socket)); } else { PDBG (bjnp_dbg (LOG_INFO, "prepare_socket: ERROR - %s is IPv6 capable, but failed to create a socket.\n", if_name)); return -1; } } } break; #endif default: socket = -1; } return socket; } static int bjnp_send_broadcast (int sockfd, const bjnp_sockaddr_t * broadcast_addr, int port, struct BJNP_command cmd, int size) { int num_bytes; bjnp_sockaddr_t dest_addr; /* set address to send packet to broadcast address of interface, */ /* with port set to the destination port */ memcpy(&dest_addr, broadcast_addr, sizeof(dest_addr)); if( dest_addr.addr.sa_family == AF_INET) { dest_addr.ipv4.sin_port = htons(port); } #ifdef ENABLE_IPV6 if( dest_addr.addr.sa_family == AF_INET6) { dest_addr.ipv6.sin6_port = htons(port); } #endif if ((num_bytes = sendto (sockfd, &cmd, size, 0, &(dest_addr.addr), sa_size( broadcast_addr)) ) != size) { PDBG (bjnp_dbg (LOG_INFO, "bjnp_send_broadcast: Socket: %d: ERROR - sent only %x = %d bytes of packet, error = %s\n", sockfd, num_bytes, num_bytes, strerror (errno))); /* not allowed, skip this interface */ return -1; } return sockfd; } static void bjnp_finish_job (int devno) { /* * Signal end of scanjob to scanner */ char resp_buf[BJNP_RESP_MAX]; int resp_len; struct BJNP_command cmd; set_cmd_for_dev (devno, &cmd, CMD_UDP_CLOSE, 0); PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_finish_job: Finish scanjob\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &cmd, sizeof (struct BJNP_command))); resp_len = udp_command (devno, (char *) &cmd, sizeof (struct BJNP_command), resp_buf, BJNP_RESP_MAX); if (resp_len != sizeof (struct BJNP_command)) { PDBG (bjnp_dbg (LOG_INFO, "bjnp_finish_job: ERROR - Received %d characters on close scanjob command, expected %d\n", resp_len, (int) sizeof (struct BJNP_command))); return; } PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_finish_job: Finish scanjob response\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); } #ifdef PIXMA_BJNP_USE_STATUS static int bjnp_poll_scanner (int devno, char type,char *hostname, char *user, SANE_Byte *status, int size) { /* * send details of user to the scanner */ char cmd_buf[BJNP_CMD_MAX]; char resp_buf[BJNP_RESP_MAX]; int resp_len; int len = 0; /* payload length */ int buf_len; /* length of the whole command buffer */ struct POLL_DETAILS *poll; struct POLL_RESPONSE *response; char user_host[256]; time_t t; int user_host_len; poll = (struct POLL_DETAILS *) cmd_buf; memset( poll, 0, sizeof( struct POLL_DETAILS)); memset( &resp_buf, 0, sizeof( resp_buf) ); /* create payload */ poll->type = htons(type); user_host_len = sizeof( poll -> extensions.type2.user_host); snprintf(user_host, (user_host_len /2) ,"%s %s", user, hostname); user_host[ user_host_len /2 + 1] = '\0'; switch( type) { case 0: len = 80; break; case 1: charTo2byte(poll->extensions.type1.user_host, user_host, user_host_len); len = 80; break; case 2: poll->extensions.type2.dialog = htonl(device[devno].dialog); charTo2byte(poll->extensions.type2.user_host, user_host, user_host_len); poll->extensions.type2.unknown_1 = htonl(0x14); poll->extensions.type2.unknown_2 = htonl(0x10); t = time (NULL); strftime (poll->extensions.type2.ascii_date, sizeof (poll->extensions.type2.ascii_date), "%Y%m%d%H%M%S", localtime (&t)); len = 116; break; case 5: poll->extensions.type5.dialog = htonl(device[devno].dialog); charTo2byte(poll->extensions.type5.user_host, user_host, user_host_len); poll->extensions.type5.unknown_1 = htonl(0x14); poll->extensions.type5.key = htonl(device[devno].status_key); len = 100; break; default: PDBG (bjnp_dbg (LOG_INFO, "bjnp_poll_scanner: unknown packet type: %d\n", type)); return -1; }; /* we can only now set the header as we now know the length of the payload */ set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_POLL, len); buf_len = len + sizeof(struct BJNP_command); PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_poll_scanner: Poll details (type %d)\n", type)); PDBG (bjnp_hexdump (LOG_DEBUG2, cmd_buf, buf_len)); resp_len = udp_command (devno, cmd_buf, buf_len, resp_buf, BJNP_RESP_MAX); if (resp_len > 0) { PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_poll_scanner: Poll details response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); response = (struct POLL_RESPONSE *) resp_buf; device[devno].dialog = ntohl( response -> dialog ); if ( response -> result[3] == 1 ) { return BJNP_RESTART_POLL; } if ( (response -> result[2] & 0x80) != 0) { memcpy( status, response->status, size); PDBG( bjnp_dbg(LOG_INFO, "bjnp_poll_scanner: received button status!\n")); PDBG (bjnp_hexdump( LOG_DEBUG2, status, size )); device[devno].status_key = ntohl( response -> key ); return size; } } return 0; } #endif static void bjnp_send_job_details (int devno, char *hostname, char *user, char *title) { /* * send details of scanjob to scanner */ char cmd_buf[BJNP_CMD_MAX]; char resp_buf[BJNP_RESP_MAX]; int resp_len; struct JOB_DETAILS *job; struct BJNP_command *resp; /* send job details command */ set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_JOB_DETAILS, sizeof (*job) - sizeof (struct BJNP_command)); /* create payload */ job = (struct JOB_DETAILS *) (cmd_buf); charTo2byte (job->unknown, "", sizeof (job->unknown)); charTo2byte (job->hostname, hostname, sizeof (job->hostname)); charTo2byte (job->username, user, sizeof (job->username)); charTo2byte (job->jobtitle, title, sizeof (job->jobtitle)); PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_send_job_details: Job details\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, cmd_buf, (sizeof (struct BJNP_command) + sizeof (*job)))); resp_len = udp_command (devno, cmd_buf, sizeof (struct JOB_DETAILS), resp_buf, BJNP_RESP_MAX); if (resp_len > 0) { PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_send_job_details: Job details response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); resp = (struct BJNP_command *) resp_buf; device[devno].session_id = ntohs (resp->session_id); } } static int bjnp_get_scanner_mac_address ( int devno, char *mac_address ) { /* * send discover to scanner */ char cmd_buf[BJNP_CMD_MAX]; char resp_buf[BJNP_RESP_MAX]; int resp_len; struct DISCOVER_RESPONSE *resp = (struct DISCOVER_RESPONSE * )&resp_buf;; /* send job details command */ set_cmd_for_dev (devno, (struct BJNP_command *) cmd_buf, CMD_UDP_DISCOVER, 0); resp_len = udp_command (devno, cmd_buf, sizeof (struct BJNP_command), resp_buf, BJNP_RESP_MAX); if (resp_len > 0) { PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_get_scanner_mac_address: Discover response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, resp_buf, resp_len)); u8tohex( mac_address, resp -> mac_addr, sizeof( resp -> mac_addr ) ); return 0; } return -1; } static int bjnp_write (int devno, const SANE_Byte * buf, size_t count) { /* * This function writes TCP data to the scanner. * Returns: number of bytes written to the scanner */ int sent_bytes; int terrno; struct SCAN_BUF bjnp_buf; if (device[devno].scanner_data_left) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_write: ERROR - scanner data left = 0x%lx = %ld\n", (unsigned long) device[devno].scanner_data_left, (unsigned long) device[devno].scanner_data_left)); } /* set BJNP command header */ set_cmd_for_dev (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_SEND, count); memcpy (bjnp_buf.scan_data, buf, count); PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_write: sending 0x%lx = %ld bytes\n", (unsigned long) count, (unsigned long) count); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &bjnp_buf, sizeof (struct BJNP_command) + count))); if ((sent_bytes = send (device[devno].tcp_socket, &bjnp_buf, sizeof (struct BJNP_command) + count, 0)) < (ssize_t) (sizeof (struct BJNP_command) + count)) { /* return result from write */ terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, "bjnp_write: ERROR - Could not send data!\n")); errno = terrno; return sent_bytes; } /* correct nr of bytes sent for length of command */ else if (sent_bytes != (int) (sizeof (struct BJNP_command) + count)) { errno = EIO; return -1; } return count; } static int bjnp_send_read_request (int devno) { /* * This function reads responses from the scanner. * Returns: 0 on success, else -1 * */ int sent_bytes; int terrno; struct BJNP_command bjnp_buf; if (device[devno].scanner_data_left) PDBG (bjnp_dbg (LOG_CRIT, "bjnp_send_read_request: ERROR - scanner data left = 0x%lx = %ld\n", (unsigned long) device[devno].scanner_data_left, (unsigned long) device[devno].scanner_data_left)); /* set BJNP command header */ set_cmd_for_dev (devno, (struct BJNP_command *) &bjnp_buf, CMD_TCP_REQ, 0); PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_send_read_req sending command\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &bjnp_buf, sizeof (struct BJNP_command))); if ((sent_bytes = send (device[devno].tcp_socket, &bjnp_buf, sizeof (struct BJNP_command), 0)) < 0) { /* return result from write */ terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, "bjnp_send_read_request: ERROR - Could not send data!\n")); errno = terrno; return -1; } return 0; } static SANE_Status bjnp_recv_header (int devno, size_t *payload_size ) { /* * This function receives the response header to bjnp commands. * devno device number * size: return value for data size returned by scanner * Returns: * SANE_STATUS_IO_ERROR when any IO error occurs * SANE_STATUS_GOOD in case no errors were encountered */ struct BJNP_command resp_buf; fd_set input; struct timeval timeout; int recv_bytes; int terrno; int result; int fd; int attempt; PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_recv_header: receiving response header\n") ); fd = device[devno].tcp_socket; *payload_size = 0; attempt = 0; do { /* wait for data to be received, ignore signals being received */ FD_ZERO (&input); FD_SET (fd, &input); timeout.tv_sec = device[devno].bjnp_timeout /1000; timeout.tv_usec = device[devno].bjnp_timeout %1000; } while ( ( (result = select (fd + 1, &input, NULL, NULL, &timeout)) <= 0) && (errno == EINTR) && (attempt++ < BJNP_MAX_SELECT_ATTEMPTS)); if (result < 0) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_header: ERROR - could not read response header (select): %s!\n", strerror (terrno))); errno = terrno; return SANE_STATUS_IO_ERROR; } else if (result == 0) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_header: ERROR - could not read response header (select timed out after %d ms)!\n", device[devno].bjnp_timeout ) ); errno = terrno; return SANE_STATUS_IO_ERROR; } /* get response header */ if ((recv_bytes = recv (fd, (char *) &resp_buf, sizeof (struct BJNP_command), 0)) != sizeof (struct BJNP_command)) { terrno = errno; if (recv_bytes == 0) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_header: ERROR - (recv) Scanner closed the TCP-connection!\n")); } else { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_header: ERROR - (recv) could not read response header, received %d bytes!\n", recv_bytes)); PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_header: ERROR - (recv) error: %s!\n", strerror (terrno))); } errno = terrno; return SANE_STATUS_IO_ERROR; } if (resp_buf.cmd_code != device[devno].last_cmd) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_header: ERROR - Received response has cmd code %d, expected %d\n", resp_buf.cmd_code, device[devno].last_cmd)); return SANE_STATUS_IO_ERROR; } if (ntohs (resp_buf.seq_no) != (uint16_t) device[devno].serial) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_header: ERROR - Received response has serial %d, expected %d\n", (int) ntohs (resp_buf.seq_no), (int) device[devno].serial)); return SANE_STATUS_IO_ERROR; } /* got response header back, retrieve length of payload */ *payload_size = ntohl (resp_buf.payload_len); PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_recv_header: TCP response header(payload data = %ld bytes):\n", *payload_size) ); PDBG (bjnp_hexdump (LOG_DEBUG2, (char *) &resp_buf, sizeof (struct BJNP_command))); return SANE_STATUS_GOOD; } static int bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa, bjnp_protocol_defs_t *protocol_defs, int min_timeout) { /* initialize device structure */ char name[BJNP_HOST_MAX]; device[dn].open = 0; #ifdef PIXMA_BJNP_USE_STATUS device[dn].polling_status = BJNP_POLL_STOPPED; device[dn].dialog = 0; device[dn].status_key = 0; #endif device[dn].protocol = protocol_defs->protocol_version; device[dn].protocol_string = protocol_defs->proto_string; device[dn].tcp_socket = -1; device[dn].addr = (bjnp_sockaddr_t *) malloc(sizeof ( bjnp_sockaddr_t) ); memset( device[dn].addr, 0, sizeof( bjnp_sockaddr_t ) ); memcpy(device[dn].addr, sa, sa_size((bjnp_sockaddr_t *)sa) ); device[dn].address_level = get_scanner_name(sa, name); device[dn].session_id = 0; device[dn].serial = -1; device[dn].bjnp_timeout = min_timeout; device[dn].bjnp_min_timeout = min_timeout; device[dn].scanner_data_left = 0; device[dn].last_cmd = 0; device[dn].blocksize = BJNP_BLOCKSIZE_START; device[dn].last_block = 0; /* fill mac_address */ if (bjnp_get_scanner_mac_address(dn, device[dn].mac_address) != 0 ) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_init_device_structure: Cannot read mac address, skipping this scanner\n" ) ); return -1; } return 0; } static void bjnp_free_device_structure( int dn) { if (device[dn].addr != NULL) { free (device[dn].addr ); device[dn].addr = NULL; } device[dn].open = 0; } static SANE_Status bjnp_recv_data (int devno, SANE_Byte * buffer, size_t start_pos, size_t * len) { /* * This function receives the payload data. * NOTE: len may not exceed SSIZE_MAX (as that is max for recv) * len will be restricted to SSIZE_MAX to be sure * Returns: number of bytes of payload received from device */ fd_set input; struct timeval timeout; ssize_t recv_bytes; int terrno; int result; int fd; int attempt; PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_recv_data: read response payload (0x%lx bytes max), buffer: 0x%lx, start_pos: 0x%lx\n", (long) *len, (long) buffer, (long) start_pos)); if (*len == 0) { /* nothing to do */ PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_recv_data: Nothing to do (%ld bytes requested)\n", (long) *len)); return SANE_STATUS_GOOD; } else if ( *len > SSIZE_MAX ) { PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_recv_data: WARNING - requested block size (%ld) exceeds maximum, setting to maximum %ld\n", (long)*len, SSIZE_MAX)); *len = SSIZE_MAX; } fd = device[devno].tcp_socket; attempt = 0; do { /* wait for data to be received, retry on a signal being received */ FD_ZERO (&input); FD_SET (fd, &input); timeout.tv_sec = device[devno].bjnp_timeout /1000; timeout.tv_usec = device[devno].bjnp_timeout %1000; } while (((result = select (fd + 1, &input, NULL, NULL, &timeout)) <= 0) && (errno == EINTR) && (attempt++ < BJNP_MAX_SELECT_ATTEMPTS)); if (result < 0) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_data: ERROR - could not read response payload (select failed): %s!\n", strerror (errno))); errno = terrno; *len = 0; return SANE_STATUS_IO_ERROR; } else if (result == 0) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_data: ERROR - could not read response payload (select timed out after %d ms)!\n", device[devno].bjnp_timeout) ); errno = terrno; *len = 0; return SANE_STATUS_IO_ERROR; } if ((recv_bytes = recv (fd, buffer + start_pos, *len, 0)) < 0) { terrno = errno; PDBG (bjnp_dbg (LOG_CRIT, "bjnp_recv_data: ERROR - could not read response payload (%ld + %ld = %ld) (recv): %s!\n", (long) buffer, (long) start_pos, (long) buffer + start_pos, strerror (errno))); errno = terrno; *len = 0; return SANE_STATUS_IO_ERROR; } PDBG (bjnp_dbg (LOG_DEBUG2, "bjnp_recv_data: Received TCP response payload (%ld bytes):\n", (unsigned long) recv_bytes)); PDBG (bjnp_hexdump (LOG_DEBUG2, buffer, recv_bytes)); *len = recv_bytes; return SANE_STATUS_GOOD; } static BJNP_Status bjnp_allocate_device (SANE_String_Const devname, SANE_Int * dn, char *resulting_host) { char method[BJNP_METHOD_MAX]; char host[BJNP_HOST_MAX]; char port[BJNP_PORT_MAX] = ""; char args[BJNP_ARGS_MAX]; bjnp_protocol_defs_t *protocol_defs; struct addrinfo *res, *cur; struct addrinfo hints; int result; int i; int min_timeout = BJNP_TIMEOUT_DEFAULT; PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_allocate_device(%s) %d\n", devname, bjnp_no_devices)); if (split_uri (devname, method, host, port, args) != 0) { return BJNP_STATUS_INVAL; } if (strlen (args) > 0) { /* get device specific timeout if any */ if (strncmp(args, "timeout=", strlen("timeout=")) == 0) { min_timeout = atoi(args + strlen("timeout=")); if (min_timeout < BJNP_TIMEOUT_DEFAULT) min_timeout = BJNP_TIMEOUT_DEFAULT; } else { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_allocate_device: ERROR - Unrecognized argument: %s\n", devname)); return BJNP_STATUS_INVAL; } } if ( (protocol_defs = get_protocol_by_method(method)) == NULL) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_allocate_device: ERROR - URI %s contains invalid method: %s\n", devname, method)); return BJNP_STATUS_INVAL; } if (strlen(port) == 0) { sprintf( port, "%d", protocol_defs->default_port ); } hints.ai_flags = 0; #ifdef ENABLE_IPV6 hints.ai_family = AF_UNSPEC; #else hints.ai_family = AF_INET; #endif hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_addr = NULL; hints.ai_canonname = NULL; hints.ai_next = NULL; result = getaddrinfo (host, port, &hints, &res ); if (result != 0 ) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_allocate_device: ERROR - Cannot resolve host: %s port %s\n", host, port)); return SANE_STATUS_INVAL; } /* Check if a device number is already allocated to any of the scanner's addresses */ cur = res; while( cur != NULL) { /* create a new device structure for this address */ if (bjnp_no_devices == BJNP_NO_DEVICES) { PDBG (bjnp_dbg (LOG_CRIT, "bjnp_allocate_device: WARNING - Too many devices, ran out of device structures, cannot add %s\n", devname)); freeaddrinfo(res); return BJNP_STATUS_INVAL; } if (bjnp_init_device_structure( bjnp_no_devices, (bjnp_sockaddr_t *)cur -> ai_addr, protocol_defs, min_timeout) != 0) { /* giving up on this address, try next one if any */ break; } for (i = 0; i < bjnp_no_devices; i++) { /* Check if found the scanner before, if so we use the best address * but still make sure the scanner is listed only once. * We check for matching addresses as wel as matching mac_addresses as * an IPv6 host can have multiple adresses */ if ( strcmp( device[i].mac_address, device[bjnp_no_devices].mac_address ) == 0 ) { if ( device[i].address_level < device[bjnp_no_devices].address_level ) { /* use the new address instead as it is better */ free (device[i].addr); device[i].addr = device[bjnp_no_devices].addr; device[bjnp_no_devices].addr = NULL; device[i].address_level = device[bjnp_no_devices].address_level; } /* check if new timeout value was defined (e.g. from sanei_bjnp_device_open) * if so, use new timout value */ if (device[i].bjnp_min_timeout < device[bjnp_no_devices].bjnp_min_timeout) { /* use the longer timeout as requested */ device[i].bjnp_timeout = device[bjnp_no_devices].bjnp_min_timeout; device[i].bjnp_min_timeout = device[bjnp_no_devices].bjnp_min_timeout; } freeaddrinfo(res); *dn = i; bjnp_free_device_structure( bjnp_no_devices); return BJNP_STATUS_ALREADY_ALLOCATED; } } cur = cur->ai_next; } freeaddrinfo(res); PDBG (bjnp_dbg (LOG_INFO, "bjnp_allocate_device: Scanner not yet in our list, added it: %s:%s\n", host, port)); /* Commit new device structure */ *dn = bjnp_no_devices; bjnp_no_devices++; /* return hostname if required */ if (resulting_host != NULL) { strcpy (resulting_host, host); } return BJNP_STATUS_GOOD; } static void add_scanner(SANE_Int *dev_no, const char *uri, SANE_Status (*attach_bjnp) (SANE_String_Const devname, SANE_String_Const makemodel, SANE_String_Const serial, const struct pixma_config_t * const pixma_devices[]), const struct pixma_config_t *const pixma_devices[]) { char scanner_host[BJNP_HOST_MAX]; char serial[BJNP_SERIAL_MAX]; char makemodel[BJNP_IEEE1284_MAX]; /* Allocate device structure for scanner */ switch (bjnp_allocate_device (uri, dev_no, scanner_host)) { case BJNP_STATUS_GOOD: if (get_scanner_id (*dev_no, makemodel) != 0) { PDBG (bjnp_dbg (LOG_CRIT, "add_scanner: ERROR - Cannot read scanner make & model: %s\n", uri)); } else { /* * inform caller of found scanner */ determine_scanner_serial (scanner_host, device[*dev_no].mac_address, serial); attach_bjnp (uri, makemodel, serial, pixma_devices); PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: New scanner added: %s, serial %s, mac addres: %s.\n", uri, serial, device[*dev_no].mac_address)); } break; case BJNP_STATUS_ALREADY_ALLOCATED: PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: Scanner at %s was added before, good!\n", uri)); break; case BJNP_STATUS_INVAL: PDBG (bjnp_dbg (LOG_NOTICE, "add_scanner: Scanner at %s can not be added\n", uri)); break; } } int rewrite_uri(char *uri, int timeout, int max_len) { char method[BJNP_METHOD_MAX]; char host[BJNP_HOST_MAX]; char port_str[BJNP_PORT_MAX]; char args[BJNP_HOST_MAX]; int port; if (split_uri(uri, method, host, port_str, args ) != 0) { return -1; } port = atoi(port_str); if (port == 0) { port = 8612; } if (strstr(args, "timeout=") == NULL) { sprintf(args, "timeout=%d", timeout); } snprintf(uri, max_len -1, "bjnp://%s:%d/%s", host, port, args); return 0; } /* * Public functions */ /** Initialize sanei_bjnp. * * Call this before any other sanei_bjnp function. */ extern void sanei_bjnp_init (void) { DBG_INIT(); bjnp_no_devices = 0; } /** * Find devices that implement the bjnp protocol * * The function attach is called for every device which has been found. * * @param attach attach function * * @return SANE_STATUS_GOOD - on success (even if no scanner was found) */ extern SANE_Status sanei_bjnp_find_devices (const char **conf_devices, SANE_Status (*attach_bjnp) (SANE_String_Const devname, SANE_String_Const makemodel, SANE_String_Const serial, const struct pixma_config_t * const pixma_devices[]), const struct pixma_config_t *const pixma_devices[]) { int numbytes = 0; struct BJNP_command cmd; unsigned char resp_buf[2048]; struct DISCOVER_RESPONSE *disc_resp = ( struct DISCOVER_RESPONSE *) & resp_buf; int socket_fd[BJNP_SOCK_MAX]; int no_sockets; int i; int j; int attempt; int last_socketfd = 0; fd_set fdset; fd_set active_fdset; struct timeval timeout; char scanner_host[256]; char uri[256]; int dev_no; int port; int timeout_default = BJNP_TIMEOUT_DEFAULT; bjnp_sockaddr_t broadcast_addr[BJNP_SOCK_MAX]; bjnp_sockaddr_t scanner_sa; socklen_t socklen; bjnp_protocol_defs_t *protocol_defs; memset( broadcast_addr, 0, sizeof( broadcast_addr) ); memset( &scanner_sa, 0 ,sizeof( scanner_sa ) ); PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_find_devices, pixma backend version: %d.%d.%d\n", PIXMA_VERSION_MAJOR, PIXMA_VERSION_MINOR, PIXMA_VERSION_BUILD)); bjnp_no_devices = 0; for (i=0; i < BJNP_SOCK_MAX; i++) { socket_fd[i] = -1; } /* Add devices from config file */ if (conf_devices[0] == NULL) PDBG (bjnp_dbg( LOG_DEBUG, "sanei_bjnp_find_devices: No devices specified in configuration file.\n" ) ); for (i = 0; conf_devices[i] != NULL; i++) { if (strncmp(conf_devices[i], "bjnp-timeout=", strlen("bjnp-timeout="))== 0) { timeout_default = atoi(conf_devices[i] + strlen("bjnp-timeout=") ); if (timeout_default < BJNP_TIMEOUT_DEFAULT) { timeout_default = BJNP_TIMEOUT_DEFAULT; } PDBG ( bjnp_dbg (LOG_DEBUG, "Set new default timeout value: %d ms.", timeout_default)); continue; } PDBG (bjnp_dbg (LOG_DEBUG, "sanei_bjnp_find_devices: Adding scanner from pixma.conf: %s\n", conf_devices[i])); strncpy(uri, conf_devices[i], sizeof(uri)); rewrite_uri(uri, timeout_default, sizeof(uri)); add_scanner(&dev_no, uri, attach_bjnp, pixma_devices); } PDBG (bjnp_dbg (LOG_DEBUG, "sanei_bjnp_find_devices: Added all configured scanners, now do auto detection...\n")); /* * Send UDP DISCOVER to discover scanners and return the list of scanners found */ FD_ZERO (&fdset); no_sockets = 0; #ifdef HAVE_IFADDRS_H { struct ifaddrs *interfaces = NULL; struct ifaddrs *interface; getifaddrs (&interfaces); /* create a socket for each suitable interface */ interface = interfaces; while ((no_sockets < BJNP_SOCK_MAX) && (interface != NULL)) { if ( ! (interface -> ifa_flags & IFF_POINTOPOINT) && ( (socket_fd[no_sockets] = prepare_socket( interface -> ifa_name, (bjnp_sockaddr_t *) interface -> ifa_addr, (bjnp_sockaddr_t *) interface -> ifa_broadaddr, &broadcast_addr[no_sockets] ) ) != -1 ) ) { /* track highest used socket for later use in select */ if (socket_fd[no_sockets] > last_socketfd) { last_socketfd = socket_fd[no_sockets]; } FD_SET (socket_fd[no_sockets], &fdset); no_sockets++; } interface = interface->ifa_next; } freeifaddrs (interfaces); } #else /* we have no easy way to find interfaces with their broadcast addresses. */ /* use global broadcast and all-hosts instead */ { bjnp_sockaddr_t local; bjnp_sockaddr_t bc_addr; memset( &local, 0, sizeof( local) ); local.ipv4.sin_family = AF_INET; local.ipv4.sin_addr.s_addr = htonl (INADDR_ANY); bc_addr.ipv4.sin_family = AF_INET; bc_addr.ipv4.sin_port = htons(0); bc_addr.ipv4.sin_addr.s_addr = htonl (INADDR_BROADCAST); socket_fd[no_sockets] = prepare_socket( "any_interface", &local, &bc_addr, &broadcast_addr[no_sockets] ); if (socket_fd[no_sockets] >= 0) { FD_SET (socket_fd[no_sockets], &fdset); if (socket_fd[no_sockets] > last_socketfd) { last_socketfd = socket_fd[no_sockets]; } no_sockets++; } #ifdef ENABLE_IPV6 local.ipv6.sin6_family = AF_INET6; local.ipv6.sin6_addr = in6addr_any; socket_fd[no_sockets] = prepare_socket( "any_interface", &local, NULL, &broadcast_addr[no_sockets] ); if (socket_fd[no_sockets] >= 0) { FD_SET (socket_fd[no_sockets], &fdset); if (socket_fd[no_sockets] > last_socketfd) { last_socketfd = socket_fd[no_sockets]; } no_sockets++; } #endif } #endif /* send BJNP_MAX_BROADCAST_ATTEMPTS broadcasts on each prepared socket */ for (attempt = 0; attempt < BJNP_MAX_BROADCAST_ATTEMPTS; attempt++) { for ( i=0; i < no_sockets; i++) { j = 0; while(bjnp_protocol_defs[j].protocol_version != PROTOCOL_NONE) { set_cmd_from_string (bjnp_protocol_defs[j].proto_string, &cmd, CMD_UDP_DISCOVER, 0); bjnp_send_broadcast ( socket_fd[i], &broadcast_addr[i], bjnp_protocol_defs[j].default_port, cmd, sizeof (cmd)); j++; } } /* wait for some time between broadcast packets */ usleep (BJNP_BROADCAST_INTERVAL * BJNP_USLEEP_MS); } /* wait for a UDP response */ timeout.tv_sec = 0; timeout.tv_usec = BJNP_BC_RESPONSE_TIMEOUT * BJNP_USLEEP_MS; active_fdset = fdset; while (select (last_socketfd + 1, &active_fdset, NULL, NULL, &timeout) > 0) { PDBG (bjnp_dbg (LOG_DEBUG, "sanei_bjnp_find_devices: Select returned, time left %d.%d....\n", (int) timeout.tv_sec, (int) timeout.tv_usec)); for (i = 0; i < no_sockets; i++) { if (FD_ISSET (socket_fd[i], &active_fdset)) { socklen = sizeof(scanner_sa); if ((numbytes = recvfrom (socket_fd[i], resp_buf, sizeof (resp_buf), 0, &(scanner_sa.addr), &socklen ) ) == -1) { PDBG (bjnp_dbg (LOG_INFO, "sanei_find_devices: no data received")); break; } else { PDBG (bjnp_dbg (LOG_DEBUG2, "sanei_find_devices: Discover response:\n")); PDBG (bjnp_hexdump (LOG_DEBUG2, &resp_buf, numbytes)); /* check if something sensible is returned */ protocol_defs = get_protocol_by_proto_string(disc_resp-> response.BJNP_id); if ( (numbytes < (int)sizeof (struct BJNP_command)) || (protocol_defs == NULL)) { /* not a valid response, assume not a scanner */ char bjnp_id[5]; strncpy(bjnp_id, disc_resp-> response.BJNP_id, 4); bjnp_id[4] = '\0'; PDBG (bjnp_dbg (LOG_INFO, "sanei_find_devices: Invalid discover response! Length = %d, Id = %s\n", numbytes, bjnp_id ) ); break; } if ( !(disc_resp -> response.dev_type & 0x80) ) { /* not a response, a command from somebody else or */ /* a discover command that we generated */ break; } }; port = get_port_from_sa(scanner_sa); /* scanner found, get IP-address or hostname */ get_scanner_name( &scanner_sa, scanner_host); /* construct URI */ sprintf (uri, "%s://%s:%d/timeout=%d", protocol_defs->method_string, scanner_host, port, timeout_default); add_scanner( &dev_no, uri, attach_bjnp, pixma_devices); } } active_fdset = fdset; timeout.tv_sec = 0; timeout.tv_usec = BJNP_BC_RESPONSE_TIMEOUT * BJNP_USLEEP_MS; } PDBG (bjnp_dbg (LOG_DEBUG, "sanei_find_devices: scanner discovery finished...\n")); for (i = 0; i < no_sockets; i++) close (socket_fd[i]); return SANE_STATUS_GOOD; } /** Open a BJNP device. * * The device is opened by its name devname and the device number is * returned in dn on success. * * Device names consist of an URI * Where: * type = bjnp * hostname = resolvable name or IP-address * port = 8612 for a scanner * An example could look like this: bjnp://host.domain:8612 * * @param devname name of the device to open * @param dn device number * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_ACCESS_DENIED - if the file couldn't be accessed due to * permissions * - SANE_STATUS_INVAL - on every other error */ extern SANE_Status sanei_bjnp_open (SANE_String_Const devname, SANE_Int * dn) { int result; PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_open(%s, %d):\n", devname, *dn)); result = bjnp_allocate_device (devname, dn, NULL); if ( (result != BJNP_STATUS_GOOD) && (result != BJNP_STATUS_ALREADY_ALLOCATED ) ) { return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /** Close a BJNP device. * * @param dn device number */ void sanei_bjnp_close (SANE_Int dn) { PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_close(%d):\n", dn)); device[dn].open = 0; sanei_bjnp_deactivate(dn); } /** Activate BJNP device connection * * @param dn device number */ SANE_Status sanei_bjnp_activate (SANE_Int dn) { char hostname[256]; char pid_str[64]; PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_activate (%d)\n", dn)); gethostname (hostname, 256); hostname[255] = '\0'; sprintf (pid_str, "Process ID = %d", getpid ()); bjnp_send_job_details (dn, hostname, getusername (), pid_str); if (bjnp_open_tcp (dn) != 0) { return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /** Deactivate BJNP device connection * * @paran dn device number */ SANE_Status sanei_bjnp_deactivate (SANE_Int dn) { PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_deactivate (%d)\n", dn)); if ( device[dn].tcp_socket != -1) { bjnp_finish_job (dn); close (device[dn].tcp_socket); device[dn].tcp_socket = -1; } return SANE_STATUS_GOOD; } /** Set the timeout for interrupt reads. * we do not use it for bulk reads! * @param timeout the new timeout in ms */ extern void sanei_bjnp_set_timeout (SANE_Int devno, SANE_Int timeout) { if (timeout < device[devno].bjnp_min_timeout) { PDBG (bjnp_dbg (LOG_INFO, "bjnp_set_timeout to %d, but using minimum value %d\n", timeout, device[devno].bjnp_min_timeout)); timeout = device[devno].bjnp_min_timeout; } else { PDBG (bjnp_dbg (LOG_INFO, "bjnp_set_timeout to %d\n", timeout)); } device[devno].bjnp_timeout = timeout; } /** Initiate a bulk transfer read. * * Read up to size bytes from the device to buffer. After the read, size * contains the number of bytes actually read. * * @param dn device number * @param buffer buffer to store read data in * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size) { SANE_Status result; SANE_Status error; size_t recvd; size_t read_size; size_t read_size_max; size_t requested; PDBG (bjnp_dbg (LOG_INFO, "bjnp_read_bulk(dn=%d, bufferptr=%lx, 0x%lx = %ld)\n", dn, (long) buffer, (unsigned long) *size, (unsigned long) *size)); recvd = 0; requested = *size; PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: 0x%lx = %ld bytes available at start\n", (unsigned long) device[dn].scanner_data_left, (unsigned long) device[dn].scanner_data_left ) ); while ( (recvd < requested) && !( device[dn].last_block && (device[dn].scanner_data_left == 0)) ) { PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: Already received 0x%lx = %ld bytes, backend requested 0x%lx = %ld bytes\n", (unsigned long) recvd, (unsigned long) recvd, (unsigned long) requested, (unsigned long)requested )); /* Check first if there is data in flight from the scanner */ if (device[dn].scanner_data_left == 0) { /* There is no data in flight from the scanner, send new read request */ PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: No (more) scanner data available, requesting more( blocksize = %ld = %lx\n", (long int) device[dn].blocksize, (long int) device[dn].blocksize )); if ((error = bjnp_send_read_request (dn)) != SANE_STATUS_GOOD) { *size = recvd; return SANE_STATUS_IO_ERROR; } if ( ( error = bjnp_recv_header (dn, &(device[dn].scanner_data_left) ) ) != SANE_STATUS_GOOD) { *size = recvd; return SANE_STATUS_IO_ERROR; } /* correct blocksize if applicable */ device[dn].blocksize = MAX (device[dn].blocksize, device[dn].scanner_data_left); if ( device[dn].scanner_data_left < device[dn].blocksize) { /* the scanner will not react at all to a read request, when no more data is available */ /* we now determine end of data by comparing the payload size to the maximun blocksize */ /* this block is shorter than blocksize, so after this block we are done */ device[dn].last_block = 1; } } PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: In flight: 0x%lx = %ld bytes available\n", (unsigned long) device[dn].scanner_data_left, (unsigned long) device[dn].scanner_data_left)); /* read as many bytes as needed and available */ read_size_max = MIN( device[dn].scanner_data_left, (requested - recvd) ); read_size = read_size_max; PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: Try to read 0x%lx = %ld (of max 0x%lx = %ld) bytes\n", (unsigned long) read_size_max, (unsigned long) read_size_max, (unsigned long) device[dn].scanner_data_left, (unsigned long) device[dn].scanner_data_left) ); result = bjnp_recv_data (dn, buffer , recvd, &read_size); if (result != SANE_STATUS_GOOD) { *size = recvd; return SANE_STATUS_IO_ERROR; } PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: Expected at most %ld bytes, received this time: %ld\n", read_size_max, read_size) ); device[dn].scanner_data_left = device[dn].scanner_data_left - read_size; recvd = recvd + read_size; } PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_read_bulk: %s: Returning %ld bytes, backend expexts %ld\n", (recvd == *size)? "OK": "NOTICE",recvd, *size ) ); *size = recvd; if ( *size == 0 ) return SANE_STATUS_EOF; return SANE_STATUS_GOOD; } /** Initiate a bulk transfer write. * * Write up to size bytes from buffer to the device. After the write size * contains the number of bytes actually written. * * @param dn device number * @param buffer buffer to write to device * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_IO_ERROR - if an error occured during the write * - SANE_STATUS_INVAL - on every other error */ extern SANE_Status sanei_bjnp_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size) { ssize_t sent; size_t recvd; uint32_t buf; size_t payload_size; /* Write received data to scanner */ sent = bjnp_write (dn, buffer, *size); if (sent < 0) return SANE_STATUS_IO_ERROR; if (sent != (int) *size) { PDBG (bjnp_dbg (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Sent only %ld bytes to scanner, expected %ld!!\n", (unsigned long) sent, (unsigned long) *size)); return SANE_STATUS_IO_ERROR; } if (bjnp_recv_header (dn, &payload_size) != SANE_STATUS_GOOD) { PDBG (bjnp_dbg (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Could not read response to command!\n")); return SANE_STATUS_IO_ERROR; } if (payload_size != 4) { PDBG (bjnp_dbg (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Scanner length of write confirmation = 0x%lx bytes = %ld, expected %d!!\n", (unsigned long) payload_size, (unsigned long) payload_size, 4)); return SANE_STATUS_IO_ERROR; } recvd = payload_size; if ((bjnp_recv_data (dn, (unsigned char *) &buf, 0, &recvd) != SANE_STATUS_GOOD) || (recvd != payload_size)) { PDBG (bjnp_dbg (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Could not read length of data confirmed by device\n")); return SANE_STATUS_IO_ERROR; } recvd = ntohl (buf); if (recvd != *size) { PDBG (bjnp_dbg (LOG_CRIT, "sanei_bjnp_write_bulk: ERROR - Scanner confirmed %ld bytes, expected %ld!!\n", (unsigned long) recvd, (unsigned long) *size)); return SANE_STATUS_IO_ERROR; } /* we can expect data from the scanner */ device[dn].last_block = 0; return SANE_STATUS_GOOD; } /** Initiate a interrupt transfer read. * * Read up to size bytes from the interrupt endpoint from the device to * buffer. After the read, size contains the number of bytes actually read. * * @param dn device number * @param buffer buffer to store read data in * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size) { #ifndef PIXMA_BJNP_USE_STATUS PDBG (bjnp_dbg (LOG_INFO, "bjnp_read_int(%d, bufferptr, 0x%lx = %ld):\n", dn, (unsigned long) *size, (unsigned long) *size)); memset (buffer, 0, *size); sleep (1); return SANE_STATUS_IO_ERROR; #else char hostname[256]; int resp_len; int timeout; int seconds; PDBG (bjnp_dbg (LOG_INFO, "bjnp_read_int(%d, bufferptr, 0x%lx = %ld):\n", dn, (unsigned long) *size, (unsigned long) *size)); memset (buffer, 0, *size); gethostname (hostname, 32); hostname[32] = '\0'; switch (device[dn].polling_status) { case BJNP_POLL_STOPPED: /* establish dialog */ if ( (bjnp_poll_scanner (dn, 0, hostname, getusername (), buffer, *size ) != 0) || (bjnp_poll_scanner (dn, 1, hostname, getusername (), buffer, *size ) != 0) ) { PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: WARNING - Failed to setup read_intr dialog with device!\n")); device[dn].dialog = 0; device[dn].status_key = 0; return SANE_STATUS_IO_ERROR; } device[dn].polling_status = BJNP_POLL_STARTED; /* fall through to BJNP_POLL_STARTED */ case BJNP_POLL_STARTED: /* we use only seonds accuracy between poll attempts */ timeout = device[dn].bjnp_timeout /1000; do { if ( (resp_len = bjnp_poll_scanner (dn, 2, hostname, getusername (), buffer, *size ) ) < 0 ) { PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: Restarting polling dialog!\n")); device[dn].polling_status = BJNP_POLL_STOPPED; *size = 0; return SANE_STATUS_EOF; } *size = (size_t) resp_len; if ( resp_len > 0 ) { device[dn].polling_status = BJNP_POLL_STATUS_RECEIVED; return SANE_STATUS_GOOD; } seconds = timeout > 2 ? 2 : timeout; sleep(seconds); timeout = timeout - seconds; } while ( timeout > 0 ) ; break; case BJNP_POLL_STATUS_RECEIVED: if ( (resp_len = bjnp_poll_scanner (dn, 5, hostname, getusername (), buffer, *size ) ) < 0 ) { PDBG (bjnp_dbg (LOG_NOTICE, "bjnp_read_int: Restarting polling dialog!\n")); device[dn].polling_status = BJNP_POLL_STOPPED; *size = 0; break; } } return SANE_STATUS_EOF; #endif } sane-backends-1.0.27/backend/fujitsu.c0000664000175000017500000112701213106201017014441 00000000000000/* sane - Scanner Access Now Easy. This file is part of the SANE package, and implements a SANE backend for various Fujitsu scanners. Copyright (C) 2000 Randolph Bentson Copyright (C) 2001 Frederik Ramm Copyright (C) 2001-2004 Oliver Schirrmeister Copyright (C) 2003-2016 m. allan noah JPEG output and low memory usage support funded by: Archivista GmbH, www.archivista.ch Endorser support funded by: O A S Oilfield Accounting Service Ltd, www.oas.ca Automatic length detection support funded by: Martin G. Miller, mgmiller at optonline.net Software image enhancement routines and recent scanner support funded by: Fujitsu Computer Products of America, Inc. www.fcpa.com -------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. -------------------------------------------------------------------------- The source code is divided in sections which you can easily find by searching for the tag "@@". Section 1 - Boilerplate: Init & static stuff Section 2 - Init: sane_init, _get_devices, _open ... Section 3 - Options: sane_*_option functions Section 4 - Scanning: sane_start, _get_param, _read ... Section 5 - Cleanup: sane_cancel, ... Section 6 - Misc: sense_handler, hexdump, ... Section 7 - Image processing: deskew, crop, despeck Changes: v1, 2002-05-05, OS - release memory allocated by sane_get_devices - several bugfixes - supports the M3097 - get threshold, contrast and brightness from vpd - imprinter support - get_hardware_status now works before calling sane_start - avoid unnecessary reload of options when using source=fb v2, 2002-08-08, OS - bugfix. Imprinter didn't print the first time after switching on the scanner - bugfix. reader_generic_passthrough ignored the number of bytes returned by the scanner v3, 2002-09-13, OS - 3092 support (mgoppold a t tbz-pariv.de) - tested 4097 support - changed some functions to receive compressed data v4, 2003-02-13, OS - fi-4220C support (ron a t roncemer.com) - SCSI over USB support (ron a t roncemer.com) v5, 2003-02-20, OS - set availability of options THRESHOLD und VARIANCE - option RIF is available for 3091 and 3092 v6, 2003-03-04, OS - renamed some variables - bugfix: duplex scanning now works when disconnect is enabled v7, 2003-03-10, OS - displays the offending byte in the window descriptor block v8, 2003-03-28, OS - fi-4120C support, MAN - display information about gamma in vital_product_data v9 2003-06-04, MAN - separated the 4120 and 4220 into another model - color support for the 4x20 v10 2003-06-04, MAN - removed SP15 code - sane_open actually opens the device you request v11 2003-06-11, MAN - fixed bug in that code when a scanner is disconnected v12 2003-10-06, MAN - added code to support color modes of more recent scanners v13 2003-11-07, OS - Bugfix. If a scanner returned a color image in format rr...r gg...g bb...b the reader process crashed - Bugfix. Disable option gamma was for the fi-4120 v14 2003-12-15, OS - Bugfix: set default threshold range to 0..255 There is a problem with the M3093 when you are not allows to set the threshold to 0 - Bugfix: set the allowable x- and y-DPI values from VPD. Scanning with x=100 and y=100 dpi with an fi4120 resulted in an image with 100,75 dpi - Bugfix: Set the default value of gamma to 0x80 for all scanners that don't have built in gamma patterns - Bugfix: fi-4530 and fi-4210 don't support standard paper size v15 2003-12-16, OS - Bugfix: pagewidth and pageheight were disabled for the fi-4530C v16 2004-02-20, OS - merged the 3092-routines with the 3091-routines - inverted the image in mode color and grayscale - jpg hardware compression support (fi-4530C) v17 2004-03-04, OS - enabled option dropoutcolor for the fi-4530C, and fi-4x20C v18 2004-06-02, OS - bugfix: can read duplex color now v19 2004-06-28, MAN - 4220 use model code not strcmp (stan a t saticed.me.uk) v20 2004-08-24, OS - bugfix: 3091 did not work since 15.12.2003 - M4099 supported (bw only) v21 2006-05-01, MAN - Complete rewrite, half code size - better (read: correct) usb command support - basic support for most fi-series - most scanner capabilities read from VPD - reduced model-specific code - improved scanner detection/initialization - improved SANE_Option handling - basic button support - all IPC and Imprinter options removed temporarily - duplex broken temporarily v22 2006-05-04, MAN - do_scsi_cmd gets basic looping capability - reverse now divided by mode - re-write sane_fix/unfix value handling - fix several bugs in options code - some options' ranges modified by other options vals - added advanced read-only options for all known hardware sensors and buttons - rewrote hw status function - initial testing with M3091dc- color mode broken v23 2006-05-14, MAN - initial attempt to recover duplex mode - fix bad usb prodID when config file missing v24 2006-05-17, MAN - sane_read must set len=0 when return != good - simplify do_cmd() calls by removing timeouts - lengthen most timeouts, shorten those for wait_scanner() v25 2006-05-19, MAN - rename scsi-buffer-size to buffer-size, usb uses it too - default buffer-size increased to 64k - use sanei_scsi_open_extended() to set buffer size - fix some compiler warns: 32&64 bit gcc v26 2006-05-23, MAN - dont send scanner control (F1) if unsupported v27 2006-05-30, MAN - speed up hexdump (adeuring A T gmx D O T net) - duplex request same size block from both sides - dont #include or call sanei_thread - split usb/scsi command DBG into 25 and 30 v28 2006-06-01, MAN - sane_read() usleep if scanner is busy - do_*_cmd() no looping (only one caller used it), remove unneeded casts, cleanup/add error messages - scanner_control() look at correct has_cmd_* var, handles own looping on busy v29 2006-06-04, MAN - M3091/2 Color mode support (duplex still broken) - all sensors option names start with 'button-' - rewrite sane_read and helpers to use buffers, currently an extreme waste of ram, but should work with saned and scanimage -T - merge color conversion funcs into read_from_buf() - compare bytes tx v/s rx instead of storing EOFs - remove scanner cmd buf, use buf per func instead - print color and duplex raster offsets (inquiry) - print EOM, ILI, and info bytes (request sense) v30 2006-06-06, MAN - M3091/2 duplex support, color/gray/ht/lineart ok - sane_read helpers share code, report more errors - add error msg if VPD missing or non-extended - remove references to color_lineart and ht units - rework init_model to support more known models - dont send paper size data if using flatbed v31 2006-06-13, MAN - add 5220C usb id - dont show ink level buttons if no imprinter - run ghs/rs every second instead of every other v32 2006-06-14, MAN - add 4220C2 usb id v33 2006-06-14, MAN (SANE v1.0.18) - add Fi-5900 usb id and init_model section v34 2006-07-04, MAN - add S500 usb id - gather more data from inq and vpd - allow background color setting v35 2006-07-05, MAN - allow double feed sensor settings - more consistent naming of global strings v36 2006-07-06, MAN - deal with fi-5900 even bytes problem - less verbose calculateDerivedValues() v37 2006-07-14, MAN - mode sense command support - detect mode page codes instead of hardcoding - send command support - brightness/contrast support via LUT - merge global mode page buffers v38 2006-07-15, MAN - add 'useless noise' debug level (35) - move mode sense probe errors to DBG 35 v39 2006-07-17, MAN - rewrite contrast slope math for readability v40 2006-08-26, MAN - rewrite brightness/contrast more like xsane - initial gamma support - add fi-5530 usb id - rewrite do_*_cmd functions to handle short reads and to use ptr to return read in length - new init_user function split from init_model - init_vpd allows short vpd block for older models - support MS buffer (s.scipioni AT harvardgroup DOT it) - support MS prepick - read only 1 byte of mode sense output v41 2006-08-28, MAN - do_usb_cmd() returns io error on cmd/out/status/rs EOF - fix bug in MS buffer/prepick scsi data block v42 2006-08-31, MAN - fix bug in get_hardware_status (#303798) v43 2006-09-19, MAN - add model-specific code to init_vpd for M3099 v44 2007-01-26, MAN - set SANE_CAP_HARD_SELECT on all buttons/sensors - disable sending gamma LUT, seems wrong on some units? - support MS overscan - clamp the scan area to the pagesize on ADF v45 2007-01-28, MAN - update overscan code to extend max scan area v46 2007-03-08, MAN - tweak fi-4x20c2 and M3093 settings - add fi-5110EOXM usb id - add M3093 non-alternating duplex code v47 2007-04-13, MAN - change window_gamma determination - add fi-5650C usb id and color mode v48 2007-04-16, MAN - re-enable brightness/contrast for built-in models v49 2007-06-28, MAN - add fi-5750C usb id and color mode v50 2007-07-10, MAN - updated overscan and bgcolor option descriptions - added jpeg output support - restructured usb reading code to use RS len for short reads - combined calcDerivedValues with sane_get_params v51 2007-07-26, MAN - fix bug in jpeg output support v52 2007-07-27, MAN - remove unused jpeg function - reactivate look-up-table based brightness and contrast options - change range of hardware brightness/contrast to match LUT versions - call send_lut() from sane_control_option instead of sane_start v53 2007-11-18, MAN - add S510 usb id - OPT_NUM_OPTS type is SANE_TYPE_INT (jblache) v54 2007-12-29, MAN - disable SANE_FRAME_JPEG support until SANE 1.1.0 v55 2007-12-29, MAN (SANE v1.0.19) - add S500M usb id v56 2008-02-14, MAN - sanei_config_read has already cleaned string (#310597) v57 2008-02-24, MAN - fi-5900 does not (initially) interlace colors - add mode sense for color interlacing? (page code 32) - more debug output in init_ms() v58 2008-04-19, MAN - page code 32 is not color interlacing, rename to 'unknown' - increase number of bytes in response buffer of init_ms() - protect debug modification code in init_ms() if NDEBUG is set - proper async sane_cancel support - re-enable JPEG support - replace s->img_count with s->side - sane_get_parameters(): dont round up larger than current paper size - sane_start() rewritten, shorter, more clear - return values are SANE_Status, not int - hide unused functions v59 2008-04-22, MAN - add fi-6140 usb ID, and fi-6x40 color mode v60 2008-04-27, MAN - move call to sanei_usb_init() from sane_init() to find_scanners - free sane_devArray before calloc'ing a new one v61 2008-05-11, MAN - minor cleanups to init_ms() - add fi-5530C2 usb id - merge find_scanners into sane_get_devices - inspect correct bool to enable prepick mode option v62 2008-05-20, MAN - check for all supported scsi commands - use well-known option group strings from saneopts.h - rename pagewidth to page-width, to meet sane 1.1.0, same for height - add unused get_window() v63 2008-05-21, MAN - use sane 1.1.0 well-known option names for some buttons - remove 'button-' from other buttons and sensors v64 2008-05-28, MAN - strcpy device_name[] instead of strdup/free *device_name - add send/read diag commands to get scanner serial number - use model and serial to build sane.name (idea from Ryan Duryea) - allow both serial_name and device_name to sane_open scanner - correct mode select/sense 6 vs 10 booleans - rename product_name to model_name - simulate missing VPD data for M3097G - hide get_window - improve handling of vendor unique section of set_window - add init_interlace to detect proper color mode without hardcoding - add ascii output to hexdump v65 2008-06-24, MAN - detect endorser type during init_inquiry() - add endorser options - add send_endorser() and call from sane_control_option() - add endorser() and call from sane_start() - convert set_window() to use local cmd and payload copies - remove get_window() - mode_select_buff() now clears the buffer, and called in sane_close() - fi-4990 quirks added, including modified even_scan_line code v66 2008-06-26, MAN - restructure double feed detection options for finer-grained control - add endorser side option - prevent init_interlace() from overriding init_model() - simplify sane_start() and fix interlaced duplex jpeg support - simplify sane_read() and add non-interlaced duplex jpeg support - removed unused code v67 2008-07-01, MAN - add IPC/DTC/SDTC options - call check_for_cancel() in sane_cancel, unless s->reader flag is set v68 2008-07-02, MAN - add halftone type and pattern options - support M3097G with IPC and CMP options via modified VPD response v69 2008-07-03, MAN - support hot-unplugging scanners v70 2008-07-05, MAN - fix bug in sane_get_parameters (failed to copy values) - autodetect jpeg duplex interlacing mode by inspecting scan width v71 2008-07-13, MAN - disable overscan option if vpd does not tell overscan size - fi-5110EOX crops scan area based on absolute maximum, not paper - fi-5530C/2 and fi-5650C can't handle 10 bit LUT via USB - fi-5900 has background color, though it reports otherwise v72 2008-07-13, MAN - use mode_sense to determine background color support - remove fi-5900 background color override v73 2008-07-14, MAN - correct overscan dimension calculation - provide correct overscan size overrides for fi-5110C and fi-4x20C2 - add fi-6130 usb ID - fi-5750C can't handle 10 bit LUT via USB v74 2008-08-02, MAN - replace global scsi blocks with local ones in each function v75 2008-08-07, ReneR - added fi-6230 usb ID v76 2008-08-13, MAN - add independent maximum area values for flatbed - override said values for fi-4220C, fi-4220C2 and fi-5220C v77 2008-08-26, MAN - override flatbed maximum area for fi-6230C and fi-6240C - set PF bit in all mode_select(6) CDB's - set SANE_CAP_INACTIVE on all disabled options - fix bug in mode_select page for sleep timer v78 2008-08-26, MAN - recent model names (fi-6xxx) dont end in 'C' - simplify flatbed area overrides - call scanner_control to change source during sane_start v79 2008-10-01, MAN - add usb ids for several models - print additional hardware capability bits - detect front-side endorser - disable endorser-side controls if only one side installed - add quirks for fi-6x70 v80 2008-10-08, MAN - front-side endorser uses data ID 0x80 v81 2008-10-20, MAN - increase USB timeouts - enable get_pixelsize() to update scan params after set_window() - remove even_scan_line hack v82 2008-10-31, MAN - improved front-side endorser vpd detection - send scanner_control_ric during sane_read of each side - add fi-6770A and fi-6670A USB ID's v83 2008-11-06, MAN - round binary bpl and Bpl up to byte boundary - use s->params instead of user data in set_window() - read_from_scanner() only grabs an even number of lines v84 2008-11-07, MAN - round lines down to even number to get even # of total bytes - round binary bpl and Bpl down to byte boundary v85 2008-12-10, MAN - round pixels_per_line down to arbitrary limits for fi-4990 & fi-4860 - fi-4860 returns random garbage to serial number queries - initialize *info to 0 in sane_control_option() v86 2008-12-18, MAN - get_pixelsize() sets back window ID for back side scans v87 2008-12-21, MAN - accept null pointer as empty device name - track frontend reading sensor/button values to reload - deactivate double feed options if df-action == default v88 2009-01-21, MAN - dont export private symbols v89 2009-02-20, MAN - fi-4750 returns random garbage to serial number queries v90 2009-02-23, MAN - added ScanSnap S510M usb ids v91 2009-03-20, MAN - remove unused temp file code v92 2009-04-12, MAN - disable SANE_FRAME_JPEG support (again) v93 2009-04-14, MAN (SANE 1.0.20) - return cmd status for reads on sensors - ignore errors in scanner_control(), M3091 has not worked since sane 1.0.19, due to this. - copy_buffer needs to count lines, or M309[12] cannot duplex v94 2009-05-22, MAN - add side option to show which duplex image is being transferred - convert front and simplex buffers to use much less ram - add lowmemory option which makes duplex back buffer small too - refactor image handling code to track eof's instead of lengths - do color deinterlacing after reading from scanner, before buffering v95 2009-06-02, MAN - scanner_control_ric should return a subset of the possible errors v96 2009-08-07, MAN - split sane_get_parameters into two functions - remove unused code from get_pixelsize - support hardware based auto length detection v97 2009-09-14, MAN - use sanei_magic to provide software deskew, autocrop and despeckle v98 2010-02-09, MAN (SANE 1.0.21) - clean up #include lines and copyright - add SANE_I18N to static strings - don't fail if scsi buffer is too small - disable bg_color for S1500 - enable flatbed for M3092 v99 2010-05-14, MAN - sense_handler(): collect rs_info for any ILI, not just EOM - do_usb_cmd(): use rs_info whenever set, not just EOF - read_from_*(): better handling of EOF from lower level functions - sane_read(): improve duplexing logic v100 2010-06-01, MAN - store more Request Sense data in scanner struct - clear Request Sense data at start of every do_cmd() call - track per-side ILI and global EOM flags - set per-side EOF flag if ILI and EOM are set v101 2010-06-23, MAN - fix compilation bug when jpeg is enabled v102 2010-09-22, MAN - fix infinite loop when scan is an odd number of lines v103 2010-11-23, MAN - remove compiled-in default config file - initial support for new fi-6xxx machines v104 2010-11-24, MAN - never request more than s->buffer_size from scanner - silence noisy set_window() calls from init_interlace() v105 2010-12-02, MAN - backup and restore image params around image processing code - cache software crop/deskew parameters for use on backside of duplex - fi-6110 does not support bgcolor or prepick v106 2011-01-30, MAN (SANE 1.0.22) - dont call mode_select with a page code the scanner does not support v107 2011-11-03, MAN - M3091 does not support scanner_control(adf) - Correct buffer overflow in read_from_3091duplex() - sane_read() now always calls read_from_*() - read_from_*() are callable when there is no data, and read to eof - sane_read() will keep alternate duplex reads to similar length - Added debugging statements - Corrected comments - Updated Copyright v108 2011-11-21, MAN - merged x/y resolution options - moved page width/height to start of geometry group - use mode to pick resolution list v/s range - improved M3091 resolution choices v109 2011-12-20, MAN - added some MS and INQ information - increased default buffer size for later machines in config file - renamed new fi-6xx0Z models v110 2012-05-09, MAN - correct max_y_fb for fi-62x0 series - add must_fully_buffer helper routine - add hwdeskewcrop option, with fallback to software versions - add 'actual' param to get_pixelsize for post-scan - add recent model VPD params - only set params->lines = -1 when using ald without buffering - fix bugs in background color when using software deskew v111 2012-05-10, MAN (SANE 1.0.23) - call send_* and mode_select_* from sane_start - split read payloads into new debug level - add paper-protect, staple-detect and df-recovery options v112 2013-02-22, MAN - some scanners (fi-6x70 and later) don't enable IPC by default v113 2013-02-24, MAN - support for ScanSnap iX500 - fix bug with jpeg de-interlacing code - allow has_MS_* and has_pixelsize to be set in init_model - fix use of uninitialized buffer in send_lut - add send_q_table() - allow wait_scanner() to be bypassed in object_position - moved send_lut() to after set_window v114 2013-03-01, MAN - support resolutions > 300 for iX500 using diag_preread() - remove most communication with scanner during sane_control_option() v115 2013-03-09, MAN - separate s->mode into s_mode and u_mode - separate s->params into s_params and u_params - generate grayscale and binary in software if required (iX500) v116 2013-03-23, MAN - call set_mode() in init_interlace - add swskip option v117 2013-06-11, MAN (SANE 1.0.24) - default buffer-mode to off - improved error handling in sane_start - image width must be multiple of 8 when swcrop is used before binarization (iX500) - check hopper sensor before calling object_position(load) on iX500 v118 2013-12-09, MAN - support fi-7160, fi-7260, fi-7180 and fi-7280 - remove unused var from do_scsi_cmd() - added more request_sense options - add adv_paper_protect option - enable paper protection by default - increase max_x_fb for fi-6240 and fi-6230 v119 2013-12-18, MAN - call get_pixelsize after start_scan, not before - extend get_pixelsize to request backside data - stop using backup/restore_params - don't use extended get_pixelsize on M3091 or M3092 - call software crop code on backside images too v120 2014-01-29, MAN - only call hopper_before_op code at batch start - remove unused backup/restore_params v121 2014-04-07, MAN - add JFIF APP0 marker with resolution to jpeg images - improve jpeg duplex parsing code - simplify jpeg ifdefs - add offtimer option for more recent scanners - don't print 0 length line in hexdump v122 2014-10-28, MAN - add support for object_position halt - call object_position halt in check_for_cancel when requested v123 2014-11-06, MAN - workaround Linux USB3 bugs by adding command counting code and sending an even number of reads and writes during disconnect_fd v124 2014-12-09, MAN - support resolution controlled max page-height (fi-6/7xxx scanners) - reorder scanner sections in init_model chronologically v125 2014-12-16, MAN - remove USB packet counting code from v123, fix sanei_usb instead v126 2015-08-23, MAN - initial support for iX100 - add late_lut support for iX500/iX100 v127 2015-08-25, MAN (SANE 1.0.25) - separate iX100 from iX500 settings - iX100 has gray and lineart v128 2015-11-08, MAN - do not ask fi-4340 for serial number v129 2015-11-21, MAN - br_x and br_y locked to page_width/height until changed v130 2016-02-23, MAN - run init_model before init_ms so some scanners can override - set all M309x and M409x scanners s->broken_diag_serial = 1 v131 2016-06-06, MAN - hide compression-arg option when jpeg disabled - add Send/SC/GHS macros for recent scanners - add initial support for fi-74x0 - add initial support for fi-7030 - set has_MS_lamp=0 for fi-71x0 - add I18N macros to all option titles and descriptions v132 2016-10-07, MAN - remove ipc_mode option and variables - set ipc mode based on other options - cleanup inverted logic DTC options - fixes threshold option reported in #315069 v133 2017-04-08, MAN - initial support for fi-7600/7700 - autodetect various double feed capabilities using VPD - call send_lut if we are using a downloaded gamma table SANE FLOW DIAGRAM - sane_init() : initialize backend . - sane_get_devices() : query list of scanner devices . - sane_open() : open a particular scanner device . . - sane_set_io_mode : set blocking mode . . - sane_get_select_fd : get scanner fd . . . . - sane_get_option_descriptor() : get option information . . - sane_control_option() : change option values . . - sane_get_parameters() : returns estimated scan parameters . . - (repeat previous 3 functions) . . . . - sane_start() : start image acquisition . . - sane_get_parameters() : returns actual scan parameters . . - sane_read() : read image data (from pipe) . . (sane_read called multiple times; after sane_read returns EOF, . . loop may continue with sane_start which may return a 2nd page . . when doing duplex scans, or load the next page from the ADF) . . . . - sane_cancel() : cancel operation . - sane_close() : close opened scanner device - sane_exit() : terminate use of backend */ /* * @@ Section 1 - Boilerplate */ #include "../include/sane/config.h" #include /*memcpy...*/ #include /*isspace*/ #include /*tan*/ #include /*usleep*/ #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_magic.h" #include "fujitsu-scsi.h" #include "fujitsu.h" #define DEBUG 1 #define BUILD 133 /* values for SANE_DEBUG_FUJITSU env var: - errors 5 - function trace 10 - function detail 15 - get/setopt cmds 20 - scsi/usb trace 25 - scsi/usb writes 30 - scsi/usb reads 31 - useless noise 35 */ /* ------------------------------------------------------------------------- */ /* if JPEG support is not enabled in sane.h, we setup our own defines */ #ifndef SANE_FRAME_JPEG #define SANE_FRAME_JPEG 0x0B #define SANE_JPEG_DISABLED 1 #endif /* ------------------------------------------------------------------------- */ #define STRING_FLATBED SANE_I18N("Flatbed") #define STRING_ADFFRONT SANE_I18N("ADF Front") #define STRING_ADFBACK SANE_I18N("ADF Back") #define STRING_ADFDUPLEX SANE_I18N("ADF Duplex") #define STRING_LINEART SANE_VALUE_SCAN_MODE_LINEART #define STRING_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE #define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY #define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR #define STRING_DEFAULT SANE_I18N("Default") #define STRING_ON SANE_I18N("On") #define STRING_OFF SANE_I18N("Off") #define STRING_DTC SANE_I18N("DTC") #define STRING_SDTC SANE_I18N("SDTC") #define STRING_DITHER SANE_I18N("Dither") #define STRING_DIFFUSION SANE_I18N("Diffusion") #define STRING_RED SANE_I18N("Red") #define STRING_GREEN SANE_I18N("Green") #define STRING_BLUE SANE_I18N("Blue") #define STRING_WHITE SANE_I18N("White") #define STRING_BLACK SANE_I18N("Black") #define STRING_NONE SANE_I18N("None") #define STRING_JPEG SANE_I18N("JPEG") #define STRING_CONTINUE SANE_I18N("Continue") #define STRING_STOP SANE_I18N("Stop") #define STRING_10MM SANE_I18N("10mm") #define STRING_15MM SANE_I18N("15mm") #define STRING_20MM SANE_I18N("20mm") #define STRING_HORIZONTAL SANE_I18N("Horizontal") #define STRING_HORIZONTALBOLD SANE_I18N("Horizontal bold") #define STRING_HORIZONTALNARROW SANE_I18N("Horizontal narrow") #define STRING_VERTICAL SANE_I18N("Vertical") #define STRING_VERTICALBOLD SANE_I18N("Vertical bold") #define STRING_TOPTOBOTTOM SANE_I18N("Top to bottom") #define STRING_BOTTOMTOTOP SANE_I18N("Bottom to top") #define STRING_FRONT SANE_I18N("Front") #define STRING_BACK SANE_I18N("Back") #define max(a,b) (((a)>(b))?(a):(b)) /* Also set via config file. */ static int global_buffer_size = 64 * 1024; /* * used by attach* and sane_get_devices * a ptr to a null term array of ptrs to SANE_Device structs * a ptr to a single-linked list of fujitsu structs */ static const SANE_Device **sane_devArray = NULL; static struct fujitsu *fujitsu_devList = NULL; /* * @@ Section 2 - SANE & scanner init code */ /* * Called by SANE initially. * * From the SANE spec: * This function must be called before any other SANE function can be * called. The behavior of a SANE backend is undefined if this * function is not called first. The version code of the backend is * returned in the value pointed to by version_code. If that pointer * is NULL, no version code is returned. Argument authorize is either * a pointer to a function that is invoked when the backend requires * authentication for a specific resource or NULL if the frontend does * not support authentication. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { authorize = authorize; /* get rid of compiler warning */ DBG_INIT (); DBG (10, "sane_init: start\n"); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (5, "sane_init: fujitsu backend %d.%d.%d, from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); sanei_magic_init(); DBG (10, "sane_init: finish\n"); return SANE_STATUS_GOOD; } /* * Called by SANE to find out about supported devices. * * From the SANE spec: * This function can be used to query the list of devices that are * available. If the function executes successfully, it stores a * pointer to a NULL terminated array of pointers to SANE_Device * structures in *device_list. The returned list is guaranteed to * remain unchanged and valid until (a) another call to this function * is performed or (b) a call to sane_exit() is performed. This * function can be called repeatedly to detect when new devices become * available. If argument local_only is true, only local devices are * returned (devices directly attached to the machine that SANE is * running on). If it is false, the device list includes all remote * devices that are accessible to the SANE library. * * SANE does not require that this function is called before a * sane_open() call is performed. A device name may be specified * explicitly by a user which would make it unnecessary and * undesirable to call this function first. */ /* * Read the config file, find scanners with help from sanei_* * and store in global device structs */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { SANE_Status ret = SANE_STATUS_GOOD; struct fujitsu * s; struct fujitsu * prev = NULL; char line[PATH_MAX]; const char *lp; FILE *fp; int num_devices=0; int i=0; local_only = local_only; /* get rid of compiler warning */ DBG (10, "sane_get_devices: start\n"); /* mark all existing scanners as missing, attach_one will remove mark */ for (s = fujitsu_devList; s; s = s->next) { s->missing = 1; } sanei_usb_init(); /* set this to 64K before reading the file */ global_buffer_size = 64 * 1024; fp = sanei_config_open (FUJITSU_CONFIG_FILE); if (fp) { DBG (15, "sane_get_devices: reading config file %s\n", FUJITSU_CONFIG_FILE); while (sanei_config_read (line, PATH_MAX, fp)) { lp = line; /* ignore comments */ if (*lp == '#') continue; /* skip empty lines */ if (*lp == 0) continue; if ((strncmp ("option", lp, 6) == 0) && isspace (lp[6])) { lp += 6; lp = sanei_config_skip_whitespace (lp); /* we allow setting buffersize too big */ if ((strncmp (lp, "buffer-size", 11) == 0) && isspace (lp[11])) { int buf; lp += 11; lp = sanei_config_skip_whitespace (lp); buf = atoi (lp); if (buf < 4096) { DBG (5, "sane_get_devices: config option \"buffer-size\" (%d) is < 4096, ignoring!\n", buf); continue; } if (buf > 64*1024) { DBG (5, "sane_get_devices: config option \"buffer-size\" (%d) is > %d, warning!\n", buf, 64*1024); } DBG (15, "sane_get_devices: setting \"buffer-size\" to %d\n", buf); global_buffer_size = buf; } else { DBG (5, "sane_get_devices: config option \"%s\" unrecognized - ignored.\n", lp); } } else if ((strncmp ("usb", lp, 3) == 0) && isspace (lp[3])) { DBG (15, "sane_get_devices: looking for '%s'\n", lp); sanei_usb_attach_matching_devices(lp, attach_one_usb); } else if ((strncmp ("scsi", lp, 4) == 0) && isspace (lp[4])) { DBG (15, "sane_get_devices: looking for '%s'\n", lp); sanei_config_attach_matching_devices (lp, attach_one_scsi); } else{ DBG (5, "sane_get_devices: config line \"%s\" unrecognized - ignored.\n", lp); } } fclose (fp); } else { DBG (5, "sane_get_devices: missing required config file '%s'!\n", FUJITSU_CONFIG_FILE); } /*delete missing scanners from list*/ for (s = fujitsu_devList; s;) { if(s->missing){ DBG (5, "sane_get_devices: missing scanner %s\n",s->device_name); /*splice s out of list by changing pointer in prev to next*/ if(prev){ prev->next = s->next; free(s); s=prev->next; } /*remove s from head of list, using prev to cache it*/ else{ prev = s; s = s->next; free(prev); prev=NULL; /*reset head to next s*/ fujitsu_devList = s; } } else{ prev = s; s=prev->next; } } for (s = fujitsu_devList; s; s=s->next) { DBG (15, "sane_get_devices: found scanner %s\n",s->device_name); num_devices++; } DBG (15, "sane_get_devices: found %d scanner(s)\n",num_devices); if (sane_devArray) free (sane_devArray); sane_devArray = calloc (num_devices + 1, sizeof (SANE_Device*)); if (!sane_devArray) return SANE_STATUS_NO_MEM; for (s = fujitsu_devList; s; s=s->next) { sane_devArray[i++] = (SANE_Device *)&s->sane; } sane_devArray[i] = 0; if(device_list){ *device_list = sane_devArray; } DBG (10, "sane_get_devices: finish\n"); return ret; } /* callbacks used by sane_get_devices */ static SANE_Status attach_one_scsi (const char *device_name) { return attach_one(device_name,CONNECTION_SCSI); } static SANE_Status attach_one_usb (const char *device_name) { return attach_one(device_name,CONNECTION_USB); } /* build the scanner struct and link to global list * unless struct is already loaded, then pretend */ static SANE_Status attach_one (const char *device_name, int connType) { struct fujitsu *s; int ret; DBG (10, "attach_one: start\n"); DBG (15, "attach_one: looking for '%s'\n", device_name); for (s = fujitsu_devList; s; s = s->next) { if (strcmp (s->device_name, device_name) == 0){ DBG (10, "attach_one: already attached!\n"); s->missing = 0; return SANE_STATUS_GOOD; } } /* build a fujitsu struct to hold it */ if ((s = calloc (sizeof (*s), 1)) == NULL) return SANE_STATUS_NO_MEM; /* scsi command/data buffer */ s->buffer_size = global_buffer_size; /* copy the device name */ strcpy (s->device_name, device_name); /* connect the fd */ s->connection = connType; s->fd = -1; ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ free (s); return ret; } /* Now query the device to load its vendor/model/version */ ret = init_inquire (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: inquiry failed\n"); return ret; } /* load detailed specs/capabilities from the device */ ret = init_vpd (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: vpd failed\n"); return ret; } /* clean up the scanner struct based on model */ /* this is the only piece of model specific code */ ret = init_model (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: model failed\n"); return ret; } /* see what mode pages device supports */ ret = init_ms (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: ms failed\n"); return ret; } /* sets SANE option 'values' to good defaults */ ret = init_user (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: user failed\n"); return ret; } ret = init_options (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: options failed\n"); return ret; } ret = init_interlace (s); if (ret != SANE_STATUS_GOOD) { disconnect_fd(s); free (s); DBG (5, "attach_one: interlace failed\n"); return ret; } /* load strings into sane_device struct */ s->sane.name = s->device_name; s->sane.vendor = s->vendor_name; s->sane.model = s->model_name; s->sane.type = "scanner"; /* change name in sane_device struct if scanner has serial number */ ret = init_serial (s); if (ret == SANE_STATUS_GOOD) { s->sane.name = s->serial_name; } else{ DBG (5, "attach_one: serial number unsupported?\n"); } /* we close the connection, so that another backend can talk to scanner */ disconnect_fd(s); /* store this scanner in global vars */ s->next = fujitsu_devList; fujitsu_devList = s; DBG (10, "attach_one: finish\n"); return SANE_STATUS_GOOD; } /* * connect the fd in the scanner struct */ static SANE_Status connect_fd (struct fujitsu *s) { SANE_Status ret; int buffer_size = s->buffer_size; DBG (10, "connect_fd: start\n"); if(s->fd > -1){ DBG (5, "connect_fd: already open\n"); ret = SANE_STATUS_GOOD; } else if (s->connection == CONNECTION_USB) { DBG (15, "connect_fd: opening USB device\n"); ret = sanei_usb_open (s->device_name, &(s->fd)); } else { DBG (15, "connect_fd: opening SCSI device\n"); ret = sanei_scsi_open_extended (s->device_name, &(s->fd), sense_handler, s, &s->buffer_size); if(!ret && buffer_size != s->buffer_size){ DBG (5, "connect_fd: cannot get requested buffer size (%d/%d)\n", buffer_size, s->buffer_size); } } if(ret == SANE_STATUS_GOOD){ /* first generation usb scanners can get flaky if not closed * properly after last use. very first commands sent to device * must be prepared to correct this- see wait_scanner() */ ret = wait_scanner(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "connect_fd: could not wait_scanner\n"); disconnect_fd(s); } } else{ DBG (5, "connect_fd: could not open device: %d\n", ret); } DBG (10, "connect_fd: finish\n"); return ret; } /* * This routine will check if a certain device is a Fujitsu scanner * It also copies interesting data from INQUIRY into the handle structure */ static SANE_Status init_inquire (struct fujitsu *s) { int i; SANE_Status ret; unsigned char cmd[INQUIRY_len]; size_t cmdLen = INQUIRY_len; unsigned char in[INQUIRY_std_len]; size_t inLen = INQUIRY_std_len; DBG (10, "init_inquire: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, INQUIRY_code); set_IN_return_size (cmd, inLen); set_IN_evpd (cmd, 0); set_IN_page_code (cmd, 0); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret != SANE_STATUS_GOOD){ return ret; } if (get_IN_periph_devtype (in) != IN_periph_devtype_scanner){ DBG (5, "The device at '%s' is not a scanner.\n", s->device_name); return SANE_STATUS_INVAL; } get_IN_vendor (in, s->vendor_name); get_IN_product (in, s->model_name); get_IN_version (in, s->version_name); s->vendor_name[8] = 0; s->model_name[16] = 0; s->version_name[4] = 0; /* gobble trailing spaces */ for (i = 7; s->vendor_name[i] == ' ' && i >= 0; i--) s->vendor_name[i] = 0; for (i = 15; s->model_name[i] == ' ' && i >= 0; i--) s->model_name[i] = 0; for (i = 3; s->version_name[i] == ' ' && i >= 0; i--) s->version_name[i] = 0; if (strcmp ("FUJITSU", s->vendor_name)) { DBG (5, "The device at '%s' is reported to be made by '%s'\n", s->device_name, s->vendor_name); DBG (5, "This backend only supports Fujitsu products.\n"); return SANE_STATUS_INVAL; } DBG (15, "init_inquire: Found %s scanner %s version %s at %s\n", s->vendor_name, s->model_name, s->version_name, s->device_name); /*some scanners list random data here*/ DBG (15, "inquiry options\n"); s->color_raster_offset = get_IN_color_offset(in); DBG (15, " color offset: %d lines\n",s->color_raster_offset); /* FIXME: we dont store all of these? */ DBG (15, " long gray scan: %d\n",get_IN_long_gray(in)); DBG (15, " long color scan: %d\n",get_IN_long_color(in)); DBG (15, " emulation mode: %d\n",get_IN_emulation(in)); DBG (15, " CMP/CGA: %d\n",get_IN_cmp_cga(in)); DBG (15, " background back: %d\n",get_IN_bg_back(in)); DBG (15, " background front: %d\n",get_IN_bg_front(in)); DBG (15, " background fb: %d\n",get_IN_bg_fb(in)); DBG (15, " back only scan: %d\n",get_IN_has_back(in)); s->duplex_raster_offset = get_IN_duplex_offset(in); DBG (15, " duplex offset: %d lines\n",s->duplex_raster_offset); DBG (10, "init_inquire: finish\n"); return SANE_STATUS_GOOD; } /* * Use INQUIRY VPD to setup more detail about the scanner */ static SANE_Status init_vpd (struct fujitsu *s) { SANE_Status ret; unsigned char cmd[INQUIRY_len]; size_t cmdLen = INQUIRY_len; unsigned char in[INQUIRY_vpd_len]; size_t inLen = INQUIRY_vpd_len; DBG (10, "init_vpd: start\n"); /* get EVPD */ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, INQUIRY_code); set_IN_return_size (cmd, inLen); set_IN_evpd (cmd, 1); set_IN_page_code (cmd, 0xf0); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); /* M3099 gives all data, but wrong length */ if (strstr (s->model_name, "M3099") && (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) && get_IN_page_length (in) == 0x19){ DBG (5, "init_vpd: M3099 repair\n"); set_IN_page_length(in,0x5f); } /* M3097G has short vpd, fill in missing part */ else if (strstr (s->model_name, "M3097G") && (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) && get_IN_page_length (in) == 0x19){ unsigned char vpd3097g[] = { 0, 0, 0xc2, 0x08, 0, 0, 0, 0, 0, 0, 0xed, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0x45, 0x35, 0, 0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; DBG (5, "init_vpd: M3097G repair\n"); set_IN_page_length(in,0x5f); memcpy(in+0x1e,vpd3097g,sizeof(vpd3097g)); /*IPC*/ if(strstr (s->model_name, "i")){ DBG (5, "init_vpd: M3097G IPC repair\n"); /*subwin cmd*/ in[0x2b] = 1; /*rif/dtc/sdtc/outline/emph/sep/mirr/wlf*/ in[0x58] = 0xff; /*subwin/diffusion*/ in[0x59] = 0xc0; } /*CMP*/ if(strstr (s->model_name, "m")){ DBG (5, "init_vpd: M3097G CMP repair\n"); /*4megs*/ in[0x23] = 0x40; /*mh/mr/mmr*/ in[0x5a] = 0xe0; } } DBG (15, "init_vpd: length=%0x\n",get_IN_page_length (in)); /* This scanner supports vital product data. * Use this data to set dpi-lists etc. */ if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { DBG (15, "standard options\n"); s->basic_x_res = get_IN_basic_x_res (in); DBG (15, " basic x res: %d dpi\n",s->basic_x_res); s->basic_y_res = get_IN_basic_y_res (in); DBG (15, " basic y res: %d dpi\n",s->basic_y_res); s->step_x_res[MODE_LINEART] = get_IN_step_x_res (in); DBG (15, " step x res: %d dpi\n", s->step_x_res[MODE_LINEART]); s->step_y_res[MODE_LINEART] = get_IN_step_y_res (in); DBG (15, " step y res: %d dpi\n", s->step_y_res[MODE_LINEART]); s->max_x_res = get_IN_max_x_res (in); DBG (15, " max x res: %d dpi\n", s->max_x_res); s->max_y_res = get_IN_max_y_res (in); DBG (15, " max y res: %d dpi\n", s->max_y_res); s->min_x_res = get_IN_min_x_res (in); DBG (15, " min x res: %d dpi\n", s->min_x_res); s->min_y_res = get_IN_min_y_res (in); DBG (15, " min y res: %d dpi\n", s->min_y_res); /* some scanners list B&W resolutions. */ s->std_res[0] = get_IN_std_res_60 (in); DBG (15, " 60 dpi: %d\n", s->std_res[0]); s->std_res[1] = get_IN_std_res_75 (in); DBG (15, " 75 dpi: %d\n", s->std_res[1]); s->std_res[2] = get_IN_std_res_100 (in); DBG (15, " 100 dpi: %d\n", s->std_res[2]); s->std_res[3] = get_IN_std_res_120 (in); DBG (15, " 120 dpi: %d\n", s->std_res[3]); s->std_res[4] = get_IN_std_res_150 (in); DBG (15, " 150 dpi: %d\n", s->std_res[4]); s->std_res[5] = get_IN_std_res_160 (in); DBG (15, " 160 dpi: %d\n", s->std_res[5]); s->std_res[6] = get_IN_std_res_180 (in); DBG (15, " 180 dpi: %d\n", s->std_res[6]); s->std_res[7] = get_IN_std_res_200 (in); DBG (15, " 200 dpi: %d\n", s->std_res[7]); s->std_res[8] = get_IN_std_res_240 (in); DBG (15, " 240 dpi: %d\n", s->std_res[8]); s->std_res[9] = get_IN_std_res_300 (in); DBG (15, " 300 dpi: %d\n", s->std_res[9]); s->std_res[10] = get_IN_std_res_320 (in); DBG (15, " 320 dpi: %d\n", s->std_res[10]); s->std_res[11] = get_IN_std_res_400 (in); DBG (15, " 400 dpi: %d\n", s->std_res[11]); s->std_res[12] = get_IN_std_res_480 (in); DBG (15, " 480 dpi: %d\n", s->std_res[12]); s->std_res[13] = get_IN_std_res_600 (in); DBG (15, " 600 dpi: %d\n", s->std_res[13]); s->std_res[14] = get_IN_std_res_800 (in); DBG (15, " 800 dpi: %d\n", s->std_res[14]); s->std_res[15] = get_IN_std_res_1200 (in); DBG (15, " 1200 dpi: %d\n", s->std_res[15]); /* maximum window width and length are reported in basic units.*/ s->max_x_basic = get_IN_window_width(in); DBG(15, " max width: %2.2f inches\n",(float)s->max_x_basic/s->basic_x_res); s->max_y_basic = get_IN_window_length(in); DBG(15, " max length: %2.2f inches\n",(float)s->max_y_basic/s->basic_y_res); /* known modes */ s->can_overflow = get_IN_overflow(in); DBG (15, " overflow: %d\n", s->can_overflow); s->can_mode[MODE_LINEART] = get_IN_monochrome (in); DBG (15, " monochrome: %d\n", s->can_mode[MODE_LINEART]); s->can_mode[MODE_HALFTONE] = get_IN_half_tone (in); DBG (15, " halftone: %d\n", s->can_mode[MODE_HALFTONE]); s->can_mode[MODE_GRAYSCALE] = get_IN_multilevel (in); DBG (15, " grayscale: %d\n", s->can_mode[MODE_GRAYSCALE]); DBG (15, " color_monochrome: %d\n", get_IN_monochrome_rgb(in)); DBG (15, " color_halftone: %d\n", get_IN_half_tone_rgb(in)); s->can_mode[MODE_COLOR] = get_IN_multilevel_rgb (in); DBG (15, " color_grayscale: %d\n", s->can_mode[MODE_COLOR]); /* now we look at vendor specific data */ if (get_IN_page_length (in) >= 0x5f) { DBG (15, "vendor options\n"); s->has_adf = get_IN_adf(in); DBG (15, " adf: %d\n", s->has_adf); s->has_flatbed = get_IN_flatbed(in); DBG (15, " flatbed: %d\n", s->has_flatbed); s->has_transparency = get_IN_transparency(in); DBG (15, " transparency: %d\n", s->has_transparency); s->has_duplex = get_IN_duplex(in); s->has_back = s->has_duplex; DBG (15, " duplex: %d\n", s->has_duplex); s->has_endorser_b = get_IN_endorser_b(in); DBG (15, " back endorser: %d\n", s->has_endorser_b); s->has_barcode = get_IN_barcode(in); DBG (15, " barcode: %d\n", s->has_barcode); s->has_operator_panel = get_IN_operator_panel(in); DBG (15, " operator panel: %d\n", s->has_operator_panel); s->has_endorser_f = get_IN_endorser_f(in); DBG (15, " front endorser: %d\n", s->has_endorser_f); DBG (15, " multi-purpose stacker: %d\n", get_IN_mp_stacker(in)); DBG (15, " prepick: %d\n", get_IN_prepick(in)); DBG (15, " mf detect: %d\n", get_IN_mf_detect(in)); s->has_paper_protect = get_IN_paperprot(in); DBG (15, " paper protection: %d\n", s->has_paper_protect); s->adbits = get_IN_adbits(in); DBG (15, " A/D bits: %d\n",s->adbits); s->buffer_bytes = get_IN_buffer_bytes(in); DBG (15, " buffer bytes: %d\n",s->buffer_bytes); DBG (15, "Standard commands\n"); /* std scsi command support byte 26*/ s->has_cmd_msen10 = get_IN_has_cmd_msen10(in); DBG (15, " mode_sense_10 cmd: %d\n", s->has_cmd_msen10); s->has_cmd_msel10 = get_IN_has_cmd_msel10(in); DBG (15, " mode_select_10 cmd: %d\n", s->has_cmd_msel10); /* std scsi command support byte 27*/ s->has_cmd_lsen = get_IN_has_cmd_lsen(in); DBG (15, " log_sense cmd: %d\n", s->has_cmd_lsen); s->has_cmd_lsel = get_IN_has_cmd_lsel(in); DBG (15, " log_select cmd: %d\n", s->has_cmd_lsel); s->has_cmd_change = get_IN_has_cmd_change(in); DBG (15, " change cmd: %d\n", s->has_cmd_change); s->has_cmd_rbuff = get_IN_has_cmd_rbuff(in); DBG (15, " read_buffer cmd: %d\n", s->has_cmd_rbuff); s->has_cmd_wbuff = get_IN_has_cmd_wbuff(in); DBG (15, " write_buffer cmd: %d\n", s->has_cmd_wbuff); s->has_cmd_cav = get_IN_has_cmd_cav(in); DBG (15, " copy_and_verify cmd: %d\n", s->has_cmd_cav); s->has_cmd_comp = get_IN_has_cmd_comp(in); DBG (15, " compare cmd: %d\n", s->has_cmd_comp); s->has_cmd_gdbs = get_IN_has_cmd_gdbs(in); DBG (15, " get_d_b_status cmd: %d\n", s->has_cmd_gdbs); /* std scsi command support byte 28*/ s->has_cmd_op = get_IN_has_cmd_op(in); DBG (15, " object_pos cmd: %d\n", s->has_cmd_op); s->has_cmd_send = get_IN_has_cmd_send(in); DBG (15, " send cmd: %d\n", s->has_cmd_send); s->has_cmd_read = get_IN_has_cmd_read(in); DBG (15, " read cmd: %d\n", s->has_cmd_read); s->has_cmd_gwin = get_IN_has_cmd_gwin(in); DBG (15, " get_window cmd: %d\n", s->has_cmd_gwin); s->has_cmd_swin = get_IN_has_cmd_swin(in); DBG (15, " set_window cmd: %d\n", s->has_cmd_swin); s->has_cmd_sdiag = get_IN_has_cmd_sdiag(in); DBG (15, " send_diag cmd: %d\n", s->has_cmd_sdiag); s->has_cmd_rdiag = get_IN_has_cmd_rdiag(in); DBG (15, " read_diag cmd: %d\n", s->has_cmd_rdiag); s->has_cmd_scan = get_IN_has_cmd_scan(in); DBG (15, " scan cmd: %d\n", s->has_cmd_scan); /* std scsi command support byte 29*/ s->has_cmd_msen6 = get_IN_has_cmd_msen6(in); DBG (15, " mode_sense_6 cmd: %d\n", s->has_cmd_msen6); s->has_cmd_copy = get_IN_has_cmd_copy(in); DBG (15, " copy cmd: %d\n", s->has_cmd_copy); s->has_cmd_rel = get_IN_has_cmd_rel(in); DBG (15, " release cmd: %d\n", s->has_cmd_rel); s->has_cmd_runit = get_IN_has_cmd_runit(in); DBG (15, " reserve_unit cmd: %d\n", s->has_cmd_runit); s->has_cmd_msel6 = get_IN_has_cmd_msel6(in); DBG (15, " mode_select_6 cmd: %d\n", s->has_cmd_msel6); s->has_cmd_inq = get_IN_has_cmd_inq(in); DBG (15, " inquiry cmd: %d\n", s->has_cmd_inq); s->has_cmd_rs = get_IN_has_cmd_rs(in); DBG (15, " request_sense cmd: %d\n", s->has_cmd_rs); s->has_cmd_tur = get_IN_has_cmd_tur(in); DBG (15, " test_unit_ready cmd: %d\n", s->has_cmd_tur); /* vendor added scsi command support */ /* FIXME: there are more of these... */ DBG (15, "Vendor commands\n"); s->has_cmd_subwindow = get_IN_has_cmd_subwindow(in); DBG (15, " subwindow cmd: %d\n", s->has_cmd_subwindow); s->has_cmd_endorser = get_IN_has_cmd_endorser(in); DBG (15, " endorser cmd: %d\n", s->has_cmd_endorser); s->has_cmd_hw_status = get_IN_has_cmd_hw_status (in); DBG (15, " hardware status cmd: %d\n", s->has_cmd_hw_status); s->has_cmd_hw_status_2 = get_IN_has_cmd_hw_status_2 (in); DBG (15, " hardware status 2 cmd: %d\n", s->has_cmd_hw_status_2); s->has_cmd_hw_status_3 = get_IN_has_cmd_hw_status_3 (in); DBG (15, " hardware status 3 cmd: %d\n", s->has_cmd_hw_status_3); s->has_cmd_scanner_ctl = get_IN_has_cmd_scanner_ctl(in); DBG (15, " scanner control cmd: %d\n", s->has_cmd_scanner_ctl); s->has_cmd_device_restart = get_IN_has_cmd_device_restart(in); DBG (15, " device restart cmd: %d\n", s->has_cmd_device_restart); /* get threshold, brightness and contrast ranges. */ s->brightness_steps = get_IN_brightness_steps(in); DBG (15, " brightness steps: %d\n", s->brightness_steps); s->threshold_steps = get_IN_threshold_steps(in); DBG (15, " threshold steps: %d\n", s->threshold_steps); s->contrast_steps = get_IN_contrast_steps(in); DBG (15, " contrast steps: %d\n", s->contrast_steps); /* dither/gamma patterns */ s->num_internal_gamma = get_IN_num_gamma_internal (in); DBG (15, " built in gamma patterns: %d\n", s->num_internal_gamma); s->num_download_gamma = get_IN_num_gamma_download (in); DBG (15, " download gamma patterns: %d\n", s->num_download_gamma); s->num_internal_dither = get_IN_num_dither_internal (in); DBG (15, " built in dither patterns: %d\n", s->num_internal_dither); s->num_download_dither = get_IN_num_dither_download (in); DBG (15, " download dither patterns: %d\n", s->num_download_dither); /* ipc functions */ s->has_rif = get_IN_ipc_bw_rif (in); DBG (15, " RIF: %d\n", s->has_rif); s->has_dtc = get_IN_ipc_dtc(in); DBG (15, " DTC (AutoI): %d\n", s->has_dtc); s->has_sdtc = get_IN_ipc_sdtc(in); DBG (15, " SDTC (AutoII): %d\n", s->has_sdtc); s->has_outline = get_IN_ipc_outline_extraction (in); DBG (15, " outline extraction: %d\n", s->has_outline); s->has_emphasis = get_IN_ipc_image_emphasis (in); DBG (15, " image emphasis: %d\n", s->has_emphasis); s->has_autosep = get_IN_ipc_auto_separation (in); DBG (15, " automatic separation: %d\n", s->has_autosep); s->has_mirroring = get_IN_ipc_mirroring (in); DBG (15, " mirror image: %d\n", s->has_mirroring); s->has_wl_follow = get_IN_ipc_wl_follow (in); DBG (15, " white level follower: %d\n", s->has_wl_follow); /* byte 58 */ s->has_subwindow = get_IN_ipc_subwindow (in); DBG (15, " subwindow: %d\n", s->has_subwindow); s->has_diffusion = get_IN_ipc_diffusion (in); DBG (15, " diffusion: %d\n", s->has_diffusion); s->has_ipc3 = get_IN_ipc_ipc3 (in); DBG (15, " ipc3: %d\n", s->has_ipc3); s->has_rotation = get_IN_ipc_rotation (in); DBG (15, " rotation: %d\n", s->has_rotation); s->has_hybrid_crop_deskew = get_IN_ipc_hybrid_crop_deskew(in); DBG (15, " hybrid crop deskew: %d\n", s->has_hybrid_crop_deskew); DBG (15, " ipc2 byte 67: %d\n", get_IN_ipc_ipc2_byte67(in)); /* compression modes */ s->has_comp_MH = get_IN_compression_MH (in); DBG (15, " compression MH: %d\n", s->has_comp_MH); s->has_comp_MR = get_IN_compression_MR (in); DBG (15, " compression MR: %d\n", s->has_comp_MR); s->has_comp_MMR = get_IN_compression_MMR (in); DBG (15, " compression MMR: %d\n", s->has_comp_MMR); s->has_comp_JBIG = get_IN_compression_JBIG (in); DBG (15, " compression JBIG: %d\n", s->has_comp_JBIG); s->has_comp_JPG1 = get_IN_compression_JPG_BASE (in); DBG (15, " compression JPG1: %d\n", s->has_comp_JPG1); #ifdef SANE_JPEG_DISABLED DBG (15, " (Disabled)\n"); #endif s->has_comp_JPG2 = get_IN_compression_JPG_EXT (in); DBG (15, " compression JPG2: %d\n", s->has_comp_JPG2); s->has_comp_JPG3 = get_IN_compression_JPG_INDEP (in); DBG (15, " compression JPG3: %d\n", s->has_comp_JPG3); /* FIXME: we dont store these? */ DBG (15, " back endorser mech: %d\n", get_IN_endorser_b_mech(in)); DBG (15, " back endorser stamp: %d\n", get_IN_endorser_b_stamp(in)); DBG (15, " back endorser elec: %d\n", get_IN_endorser_b_elec(in)); DBG (15, " endorser max id: %d\n", get_IN_endorser_max_id(in)); DBG (15, " front endorser mech: %d\n", get_IN_endorser_f_mech(in)); DBG (15, " front endorser stamp: %d\n", get_IN_endorser_f_stamp(in)); DBG (15, " front endorser elec: %d\n", get_IN_endorser_f_elec(in)); s->endorser_type_b = get_IN_endorser_b_type(in); DBG (15, " back endorser type: %d\n", s->endorser_type_b); s->endorser_type_f = get_IN_endorser_f_type(in); DBG (15, " back endorser type: %d\n", s->endorser_type_f); /*not all scanners go this far*/ if (get_IN_page_length (in) >= 0x67-5) { DBG (15, " connection type: %d\n", get_IN_connection(in)); DBG (15, " endorser ext: %d\n", get_IN_endorser_type_ext(in)); DBG (15, " endorser pr_b: %d\n", get_IN_endorser_pre_back(in)); DBG (15, " endorser pr_f: %d\n", get_IN_endorser_pre_front(in)); DBG (15, " endorser po_b: %d\n", get_IN_endorser_post_back(in)); DBG (15, " endorser po_f: %d\n", get_IN_endorser_post_front(in)); s->os_x_basic = get_IN_x_overscan_size(in); DBG (15, " horizontal overscan: %d\n", s->os_x_basic); s->os_y_basic = get_IN_y_overscan_size(in); DBG (15, " vertical overscan: %d\n", s->os_y_basic); } if (get_IN_page_length (in) >= 0x70-5) { DBG (15, " default bg adf b: %d\n", get_IN_default_bg_adf_b(in)); DBG (15, " default bg adf f: %d\n", get_IN_default_bg_adf_f(in)); DBG (15, " default bg fb: %d\n", get_IN_default_bg_fb(in)); DBG (15, " auto color: %d\n", get_IN_auto_color(in)); DBG (15, " blank skip: %d\n", get_IN_blank_skip(in)); DBG (15, " multi image: %d\n", get_IN_multi_image(in)); DBG (15, " f b type indep: %d\n", get_IN_f_b_type_indep(in)); DBG (15, " f b res indep: %d\n", get_IN_f_b_res_indep(in)); DBG (15, " dropout spec: %d\n", get_IN_dropout_spec(in)); DBG (15, " dropout non: %d\n", get_IN_dropout_non(in)); DBG (15, " dropout white: %d\n", get_IN_dropout_white(in)); DBG (15, " skew check: %d\n", get_IN_skew_check(in)); DBG (15, " new feed roller: %d\n", get_IN_new_fd_roll(in)); s->has_adv_paper_prot = get_IN_paper_prot_2(in); DBG (15, " paper protection: %d\n", s->has_adv_paper_prot); } if (get_IN_page_length (in) > 0x70-5) { DBG (15, " paper count: %d\n", get_IN_paper_count(in)); DBG (15, " paper number: %d\n", get_IN_paper_number(in)); DBG (15, " ext send to: %d\n", get_IN_ext_send_to(in)); s->has_staple_detect = get_IN_staple_det(in); DBG (15, " staple det: %d\n", s->has_staple_detect); DBG (15, " pause host: %d\n", get_IN_pause_host(in)); DBG (15, " pause panel: %d\n", get_IN_pause_panel(in)); DBG (15, " pause conf: %d\n", get_IN_pause_conf(in)); DBG (15, " hq print: %d\n", get_IN_hq_print(in)); DBG (15, " ext GHS len: %d\n", get_IN_ext_GHS_len(in)); DBG (15, " smbc func: %d\n", get_IN_smbc_func(in)); DBG (15, " imprint chk b: %d\n", get_IN_imprint_chk_b(in)); DBG (15, " imprint chk f: %d\n", get_IN_imprint_chk_f(in)); DBG (15, " force w bg: %d\n", get_IN_force_w_bg(in)); s->has_df_recovery = get_IN_mf_recover_lvl(in); DBG (15, " mf recover lvl: %d\n", s->has_df_recovery); DBG (15, " first read time: %d\n", get_IN_first_read_time(in)); DBG (15, " div scanning: %d\n", get_IN_div_scanning(in)); DBG (15, " start job: %d\n", get_IN_start_job(in)); DBG (15, " lifetime log: %d\n", get_IN_lifetime_log(in)); DBG (15, " imff save rest: %d\n", get_IN_imff_save_rest(in)); DBG (15, " wide scsi type: %d\n", get_IN_wide_scsi_type(in)); DBG (15, " lut hybrid crop: %d\n", get_IN_lut_hybrid_crop(in)); DBG (15, " over under amt: %d\n", get_IN_over_under_amt(in)); DBG (15, " rgb lut: %d\n", get_IN_rgb_lut(in)); DBG (15, " num lut dl: %d\n", get_IN_num_lut_dl(in)); s->has_off_mode = get_IN_erp_lot6_supp(in); DBG (15, " ErP Lot6 (power off timer): %d\n", s->has_off_mode); DBG (15, " sync next feed: %d\n", get_IN_sync_next_feed(in)); s->has_op_halt = get_IN_op_halt(in); DBG (15, " object position halt: %d\n", s->has_op_halt); } ret = SANE_STATUS_GOOD; } /*FIXME no vendor vpd, set some defaults? */ else{ DBG (5, "init_vpd: Your scanner supports only partial VPD?\n"); DBG (5, "init_vpd: Please contact kitno455 at gmail dot com\n"); DBG (5, "init_vpd: with details of your scanner model.\n"); ret = SANE_STATUS_INVAL; } } /*FIXME no vpd, set some defaults? */ else{ DBG (5, "init_vpd: Your scanner does not support VPD?\n"); DBG (5, "init_vpd: Please contact kitno455 at gmail dot com\n"); DBG (5, "init_vpd: with details of your scanner model.\n"); } DBG (10, "init_vpd: finish\n"); return ret; } static SANE_Status init_ms(struct fujitsu *s) { int ret; int oldDbg=0; unsigned char cmd[MODE_SENSE_len]; size_t cmdLen = MODE_SENSE_len; unsigned char in[MODE_SENSE_data_len]; size_t inLen = MODE_SENSE_data_len; DBG (10, "init_ms: start\n"); if(!s->has_cmd_msen6){ DBG (10, "init_ms: unsupported\n"); return SANE_STATUS_GOOD; } /* some of the following probes will produce errors */ /* so we reduce the dbg level to reduce the noise */ /* however, if user builds with NDEBUG, we can't do that */ /* so we protect the code with the following macro */ IF_DBG( oldDbg=DBG_LEVEL; ) IF_DBG( if(DBG_LEVEL < 35){ DBG_LEVEL = 0; } ) memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SENSE_code); set_MSEN_xfer_length (cmd, inLen); if(s->has_MS_autocolor){ DBG (35, "init_ms: autocolor\n"); set_MSEN_pc(cmd, MS_pc_autocolor); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_autocolor=0; } } if(s->has_MS_prepick){ DBG (35, "init_ms: prepick\n"); set_MSEN_pc(cmd, MS_pc_prepick); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_prepick=0; } } if(s->has_MS_sleep){ DBG (35, "init_ms: sleep\n"); set_MSEN_pc(cmd, MS_pc_sleep); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_sleep=0; } } if(s->has_MS_duplex){ DBG (35, "init_ms: duplex\n"); set_MSEN_pc(cmd, MS_pc_duplex); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_duplex=0; } } if(s->has_MS_rand){ DBG (35, "init_ms: rand\n"); set_MSEN_pc(cmd, MS_pc_rand); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_rand=0; } } if(s->has_MS_bg){ DBG (35, "init_ms: bg\n"); set_MSEN_pc(cmd, MS_pc_bg); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_bg=0; } } if(s->has_MS_df){ DBG (35, "init_ms: df\n"); set_MSEN_pc(cmd, MS_pc_df); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_df=0; } } if(s->has_MS_dropout){ DBG (35, "init_ms: dropout\n"); set_MSEN_pc(cmd, MS_pc_dropout); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_dropout=0; } } if(s->has_MS_buff){ DBG (35, "init_ms: buffer\n"); set_MSEN_pc(cmd, MS_pc_buff); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_buff=0; } } if(s->has_MS_auto){ DBG (35, "init_ms: auto\n"); set_MSEN_pc(cmd, MS_pc_auto); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_auto=0; } } if(s->has_MS_lamp){ DBG (35, "init_ms: lamp\n"); set_MSEN_pc(cmd, MS_pc_lamp); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_lamp=0; } } if(s->has_MS_jobsep){ DBG (35, "init_ms: jobsep\n"); set_MSEN_pc(cmd, MS_pc_jobsep); inLen = MODE_SENSE_data_len; ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if(ret != SANE_STATUS_GOOD){ s->has_MS_jobsep=0; } } IF_DBG (DBG_LEVEL = oldDbg;) DBG (15, " autocolor: %d\n", s->has_MS_autocolor); DBG (15, " prepick: %d\n", s->has_MS_prepick); DBG (15, " sleep: %d\n", s->has_MS_sleep); DBG (15, " duplex: %d\n", s->has_MS_duplex); DBG (15, " rand: %d\n", s->has_MS_rand); DBG (15, " bg: %d\n", s->has_MS_bg); DBG (15, " df: %d\n", s->has_MS_df); DBG (15, " dropout: %d\n", s->has_MS_dropout); DBG (15, " buff: %d\n", s->has_MS_buff); DBG (15, " auto: %d\n", s->has_MS_auto); DBG (15, " lamp: %d\n", s->has_MS_lamp); DBG (15, " jobsep: %d\n", s->has_MS_jobsep); DBG (10, "init_ms: finish\n"); return SANE_STATUS_GOOD; } /* * get model specific info that is not in vpd, and correct * errors in vpd data. struct is already initialized to 0. */ static SANE_Status init_model (struct fujitsu *s) { int i; DBG (10, "init_model: start\n"); /* for most scanners these are good defaults */ if(s->can_mode[MODE_LINEART] || s->can_mode[MODE_HALFTONE] || s->can_mode[MODE_GRAYSCALE] ){ s->has_vuid_mono = 1; } if(s->can_mode[MODE_COLOR]){ s->has_vuid_color = 1; } for(i=MODE_HALFTONE;i<=MODE_COLOR;i++){ s->step_x_res[i] = s->step_x_res[MODE_LINEART]; s->step_y_res[i] = s->step_y_res[MODE_LINEART]; } s->reverse_by_mode[MODE_LINEART] = 0; s->reverse_by_mode[MODE_HALFTONE] = 0; s->reverse_by_mode[MODE_GRAYSCALE] = 1; s->reverse_by_mode[MODE_COLOR] = 1; s->ppl_mod_by_mode[MODE_LINEART] = 8; s->ppl_mod_by_mode[MODE_HALFTONE] = 8; s->ppl_mod_by_mode[MODE_GRAYSCALE] = 1; s->ppl_mod_by_mode[MODE_COLOR] = 1; /* if scanner has built-in gamma tables, we use the first one (0) */ /* otherwise, we use the first downloaded one (0x80) */ /* note that you may NOT need to send the table to use it, */ /* the scanner will fall back to the brightness/contrast LUT */ if (!s->num_internal_gamma && s->num_download_gamma){ s->window_gamma = 0x80; } /* endorser type tells string length (among other things) */ if(s->has_endorser_b){ /*old-style is 40 bytes*/ if(s->endorser_type_b == ET_OLD){ s->endorser_string_len = 40; } /*short new style is 60 bytes*/ else if(s->endorser_type_b == ET_30){ s->endorser_string_len = 60; } /*long new style is 80 bytes*/ else if(s->endorser_type_b == ET_40){ s->endorser_string_len = 80; } } else if(s->has_endorser_f){ /*old-style is 40 bytes*/ if(s->endorser_type_f == ET_OLD){ s->endorser_string_len = 40; } /*short new style is 60 bytes*/ else if(s->endorser_type_f == ET_30){ s->endorser_string_len = 60; } /*long new style is 80 bytes*/ else if(s->endorser_type_f == ET_40){ s->endorser_string_len = 80; } } /* convert to 1200dpi units */ s->max_x = s->max_x_basic * 1200 / s->basic_x_res; s->max_y = s->max_y_basic * 1200 / s->basic_y_res; /* setup the list with a single choice, in 1200dpi units, at max res */ s->max_y_by_res[0].res = s->max_y_res; s->max_y_by_res[0].len = s->max_y; /* assume these are same as adf, override below */ s->max_x_fb = s->max_x; s->max_y_fb = s->max_y; /* assume we can do these. we will disable * them at runtime if they cannot */ s->has_pixelsize = 1; s->has_MS_autocolor = 1; s->has_MS_prepick = 1; s->has_MS_sleep = 1; s->has_MS_duplex = 1; s->has_MS_rand = 1; s->has_MS_bg = 1; s->has_MS_df = 1; s->has_MS_dropout = 1; s->has_MS_buff = 1; s->has_MS_auto = 1; s->has_MS_lamp = 1; s->has_MS_jobsep = 1; /* these two scanners lie about their capabilities, * and/or differ significantly from most other models */ if (strstr (s->model_name, "M3091") || strstr (s->model_name, "M3092")) { /* lies */ s->has_rif = 1; s->has_back = 0; s->adbits = 8; if (strstr (s->model_name, "M3092")) s->has_flatbed = 1; /*actually does have res range in non-color modes */ for(i=MODE_LINEART;istep_x_res[i] = 1; s->step_y_res[i] = 1; } /*but the color mode y list is very limited, only 75, 150, 300 (and 600)*/ for(i=0;i<16;i++){ s->std_res[i] = 0; } s->std_res[1] = 1; s->std_res[4] = 1; s->std_res[9] = 1; /* weirdness */ s->has_vuid_3091 = 1; s->has_vuid_color = 0; s->has_vuid_mono = 0; s->has_short_pixelsize = 1; s->color_interlace = COLOR_INTERLACE_3091; s->duplex_interlace = DUPLEX_INTERLACE_3091; s->ghs_in_rs = 1; s->window_gamma = 0; s->reverse_by_mode[MODE_LINEART] = 1; s->reverse_by_mode[MODE_HALFTONE] = 1; s->reverse_by_mode[MODE_GRAYSCALE] = 0; s->reverse_by_mode[MODE_COLOR] = 0; } else if (strstr (s->model_name, "M3093")){ /* lies */ s->has_back = 0; s->adbits = 8; /* weirdness */ s->duplex_interlace = DUPLEX_INTERLACE_NONE; } else if ( strstr (s->model_name, "M309") || strstr (s->model_name, "M409")){ /* weirdness */ s->broken_diag_serial = 1; /* lies */ s->adbits = 8; } else if (strstr (s->model_name, "fi-4120C2") || strstr (s->model_name, "fi-4220C2") ) { /* missing from vpd */ s->os_x_basic = 118; s->os_y_basic = 118; s->max_y_fb = 14032; } else if (strstr (s->model_name, "fi-4220C")){ /* missing from vpd */ s->max_y_fb = 14032; } else if (strstr (s->model_name,"fi-4340") || strstr (s->model_name, "fi-4750") ) { /* weirdness */ s->broken_diag_serial = 1; } /* some firmware versions use capital f? */ else if (strstr (s->model_name, "Fi-4860") || strstr (s->model_name, "fi-4860") ) { /* weirdness */ s->broken_diag_serial = 1; s->ppl_mod_by_mode[MODE_LINEART] = 32; s->ppl_mod_by_mode[MODE_HALFTONE] = 32; s->ppl_mod_by_mode[MODE_GRAYSCALE] = 4; s->ppl_mod_by_mode[MODE_COLOR] = 4; } /* some firmware versions use capital f? */ else if (strstr (s->model_name, "Fi-4990") || strstr (s->model_name, "fi-4990") ) { /* weirdness */ s->duplex_interlace = DUPLEX_INTERLACE_NONE; s->color_interlace = COLOR_INTERLACE_RRGGBB; s->ppl_mod_by_mode[MODE_LINEART] = 32; s->ppl_mod_by_mode[MODE_HALFTONE] = 32; s->ppl_mod_by_mode[MODE_GRAYSCALE] = 4; s->ppl_mod_by_mode[MODE_COLOR] = 4; } else if (strstr (s->model_name,"fi-5110C")){ /* missing from vpd */ s->os_x_basic = 147; s->os_y_basic = 147; } else if (strstr (s->model_name,"fi-5110EOX")){ /* weirdness */ s->cropping_mode = CROP_ABSOLUTE; } else if (strstr (s->model_name,"fi-5220C")){ /* missing from vpd */ s->max_x_fb = 10764; s->max_y_fb = 14032; } else if (strstr (s->model_name,"fi-5530") || strstr (s->model_name,"fi-5650") || strstr (s->model_name,"fi-5750")){ /* lies - usb only */ if(s->connection == CONNECTION_USB) s->adbits = 8; } else if (strstr (s->model_name,"S1500")){ /*lies*/ s->has_MS_bg=0; s->has_MS_prepick=0; } /* also includes the 'Z' models */ else if (strstr (s->model_name,"fi-6130") || strstr (s->model_name,"fi-6140")){ /* weirdness */ /* these machines have longer max paper at lower res */ s->max_y_by_res[1].res = 200; s->max_y_by_res[1].len = 151512; } /* also includes the 'Z' models */ else if (strstr (s->model_name,"fi-6230") || strstr (s->model_name,"fi-6240")){ /* weirdness */ /* these machines have longer max paper at lower res */ s->max_y_by_res[1].res = 200; s->max_y_by_res[1].len = 151512; /* missing from vpd */ s->max_x_fb = 10764; /* was previously 10488 */ s->max_y_fb = 14032; /* some scanners can be slightly more? */ } else if (strstr (s->model_name,"fi-6110")){ /* weirdness */ /* these machines have longer max paper at lower res */ s->max_y_by_res[1].res = 200; s->max_y_by_res[1].len = 151512; /*lies*/ s->has_MS_bg=0; s->has_MS_prepick=0; } else if (strstr (s->model_name,"fi-6800") || strstr (s->model_name,"fi-5900")){ /* do not need overrides */ } else if (strstr (s->model_name,"iX500")){ /* locks up scanner if we try to auto detect */ s->has_MS_lamp = 0; /* weirdness */ s->need_q_table = 1; s->late_lut = 1; s->need_diag_preread = 1; s->ppl_mod_by_mode[MODE_COLOR] = 2; s->hopper_before_op = 1; s->no_wait_after_op = 1; /* lies */ s->adbits = 8; /* we have to simulate these in software*/ s->can_mode[MODE_LINEART] = 2; s->can_mode[MODE_GRAYSCALE] = 2; /* dont bother with this one */ s->can_mode[MODE_HALFTONE] = 0; } /*mostly copied from iX500*/ else if (strstr (s->model_name,"iX100")){ /* locks up scanner if we try to auto detect */ s->has_MS_lamp = 0; /* weirdness */ s->need_q_table = 1; s->late_lut = 1; s->need_diag_preread = 1; s->ppl_mod_by_mode[MODE_COLOR] = 2; s->hopper_before_op = 1; s->no_wait_after_op = 1; /* lies */ s->adbits = 8; /* dont bother with this one */ s->can_mode[MODE_HALFTONE] = 0; } else if (strstr (s->model_name,"fi-7180") || strstr (s->model_name,"fi-7160")){ /* locks up scanner if we try to auto detect */ s->has_MS_lamp = 0; /* weirdness */ /* these machines have longer max paper at lower res */ s->max_y_by_res[1].res = 400; s->max_y_by_res[1].len = 194268; s->max_y_by_res[2].res = 300; s->max_y_by_res[2].len = 260268; s->max_y_by_res[3].res = 200; s->max_y_by_res[3].len = 266268; } else if (strstr (s->model_name,"fi-7280") || strstr (s->model_name,"fi-7260")){ /* weirdness */ /* these machines have longer max paper at lower res */ s->max_y_by_res[1].res = 400; s->max_y_by_res[1].len = 194268; s->max_y_by_res[2].res = 300; s->max_y_by_res[2].len = 260268; s->max_y_by_res[3].res = 200; s->max_y_by_res[3].len = 266268; /* missing from vpd */ s->max_x_fb = 10764; s->max_y_fb = 14032; /* some scanners can be slightly more? */ } else if (strstr (s->model_name,"fi-7480") || strstr (s->model_name,"fi-7460")){ /* weirdness */ /* these machines have longer max paper at lower res */ s->max_y_by_res[1].res = 400; s->max_y_by_res[1].len = 194268; s->max_y_by_res[2].res = 300; s->max_y_by_res[2].len = 260268; s->max_y_by_res[3].res = 200; s->max_y_by_res[3].len = 266268; } else if (strstr (s->model_name,"fi-7030")){ /* weirdness */ /* these machines have longer max paper at lower res */ s->max_y_by_res[1].res = 400; s->max_y_by_res[1].len = 192000; s->max_y_by_res[2].res = 300; s->max_y_by_res[2].len = 258000; s->max_y_by_res[3].res = 200; s->max_y_by_res[3].len = 264000; } else if (strstr (s->model_name,"fi-7700") || strstr (s->model_name,"fi-7600")){ /* weirdness */ /* these machines have longer max paper at lower res */ s->max_y_by_res[1].res = 400; s->max_y_by_res[1].len = 192000; s->max_y_by_res[2].res = 300; s->max_y_by_res[2].len = 258000; s->max_y_by_res[3].res = 200; s->max_y_by_res[3].len = 264000; } DBG (10, "init_model: finish\n"); return SANE_STATUS_GOOD; } static SANE_Status set_mode (struct fujitsu *s, int mode) { int i; /* give the user what they asked for */ s->u_mode = mode; /* give the scanner the closest mode */ for(i=MODE_COLOR;i>=mode;i--){ if(s->can_mode[i] == 1){ s->s_mode = i; } } return SANE_STATUS_GOOD; } /* * set good default user values. * struct is already initialized to 0. */ static SANE_Status init_user (struct fujitsu *s) { DBG (10, "init_user: start\n"); /* source */ if(s->has_flatbed) s->source = SOURCE_FLATBED; else if(s->has_adf) s->source = SOURCE_ADF_FRONT; /* scan mode */ if(s->can_mode[MODE_LINEART]) set_mode(s,MODE_LINEART); else if(s->can_mode[MODE_HALFTONE]) set_mode(s,MODE_HALFTONE); else if(s->can_mode[MODE_GRAYSCALE]) set_mode(s,MODE_GRAYSCALE); else if(s->can_mode[MODE_COLOR]) set_mode(s,MODE_COLOR); /*x res*/ s->resolution_x = s->basic_x_res; /*y res*/ s->resolution_y = s->basic_y_res; if(s->resolution_y > s->resolution_x){ s->resolution_y = s->resolution_x; } /* page width US-Letter */ s->page_width = 8.5 * 1200; if(s->page_width > s->max_x){ s->page_width = s->max_x; } /* page height US-Letter */ s->page_height = 11 * 1200; set_max_y(s); if(s->page_height > s->max_y){ s->page_height = s->max_y; } /* bottom-right x */ s->br_x = s->page_width; /* bottom-right y */ s->br_y = s->page_height; /* gamma ramp exponent */ s->gamma = 1; /* safe endorser settings */ s->u_endorser_bits=16; s->u_endorser_step=1; s->u_endorser_side=ED_back; if(s->has_endorser_f){ s->u_endorser_side=ED_front; } s->u_endorser_dir=DIR_TTB; strcpy((char *)s->u_endorser_string,"%05ud"); /* more recent machines default to this being 'on', * * which causes the scanner to ingest multiple pages * * even when the user only wants one */ s->buff_mode = MSEL_OFF; /* useful features of newer scanners which we turn on, * even though the scanner defaults to off */ if(s->has_paper_protect){ s->paper_protect = MSEL_ON; } if(s->has_staple_detect){ s->staple_detect = MSEL_ON; } if(s->has_df_recovery){ s->df_recovery = MSEL_ON; } if(s->has_adv_paper_prot){ s->adv_paper_prot = MSEL_ON; } s->off_time = 240; DBG (10, "init_user: finish\n"); return SANE_STATUS_GOOD; } /* * This function presets the "option" array to blank */ static SANE_Status init_options (struct fujitsu *s) { int i; DBG (10, "init_options: start\n"); memset (s->opt, 0, sizeof (s->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].name = "filler"; s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_INACTIVE; } /* go ahead and setup the first opt, because * frontend may call control_option on it * before calling get_option_descriptor */ s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; DBG (10, "init_options: finish\n"); return SANE_STATUS_GOOD; } /* * send set window repeatedly to color scanners, * searching for valid color interlacing mode */ static SANE_Status init_interlace (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; int curr_mode = s->u_mode; int oldDbg=0; DBG (10, "init_interlace: start\n"); if(s->color_interlace != COLOR_INTERLACE_UNK){ DBG (10, "init_interlace: already loaded\n"); return SANE_STATUS_GOOD; } if(!s->has_vuid_color){ DBG (10, "init_interlace: color unsupported\n"); return SANE_STATUS_GOOD; } /* set to color mode first */ set_mode(s,MODE_COLOR); /* load our own private copy of scan params */ ret = update_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "init_interlace: ERROR: cannot update params\n"); return ret; } /*loop thru all the formats we support*/ for(s->color_interlace = COLOR_INTERLACE_RGB; s->color_interlace <= COLOR_INTERLACE_RRGGBB; s->color_interlace++){ /* some of the following probes will produce errors */ /* so we reduce the dbg level to reduce the noise */ /* however, if user builds with NDEBUG, we can't do that */ /* so we protect the code with the following macro */ IF_DBG( oldDbg=DBG_LEVEL; ) IF_DBG( if(DBG_LEVEL < 35){ DBG_LEVEL = 0; } ) ret = set_window(s); IF_DBG (DBG_LEVEL = oldDbg;) if (ret == SANE_STATUS_GOOD){ break; } else{ DBG (15, "init_interlace: not %d\n", s->color_interlace); } } if (ret != SANE_STATUS_GOOD){ DBG (5, "init_interlace: no valid interlacings\n"); return SANE_STATUS_INVAL; } DBG (15, "init_interlace: color_interlace: %d\n",s->color_interlace); /* restore mode */ set_mode(s,curr_mode); DBG (10, "init_interlace: finish\n"); return SANE_STATUS_GOOD; } /* * send diag query for serial number, and read result back * use it to build a unique name for scanner in s->serial_name */ static SANE_Status init_serial (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned int sn = 0; unsigned char cmd[SEND_DIAGNOSTIC_len]; /*also big enough for READ_DIAG*/ size_t cmdLen = SEND_DIAGNOSTIC_len; unsigned char out[SD_gdi_len]; size_t outLen = SD_gdi_len; unsigned char in[RD_gdi_len]; size_t inLen = RD_gdi_len; DBG (10, "init_serial: start\n"); if (!s->has_cmd_sdiag || !s->has_cmd_rdiag || s->broken_diag_serial){ DBG (5, "init_serial: send/read diag not supported, returning\n"); return SANE_STATUS_INVAL; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SEND_DIAGNOSTIC_code); set_SD_slftst(cmd, 0); set_SD_xferlen(cmd, outLen); memcpy(out,SD_gdi_string,outLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); if (ret != SANE_STATUS_GOOD){ DBG (5, "init_serial: send diag error: %d\n", ret); return ret; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_DIAGNOSTIC_code); set_RD_xferlen(cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret != SANE_STATUS_GOOD){ DBG (5, "init_serial: read diag error: %d\n", ret); return ret; } sn = get_RD_id_serial(in); DBG (15, "init_serial: found sn %d\n",sn); sprintf(s->serial_name, "%s:%d", s->model_name, sn); DBG (15, "init_serial: serial_name: %s\n",s->serial_name); DBG (10, "init_serial: finish\n"); return SANE_STATUS_GOOD; } /* * From the SANE spec: * This function is used to establish a connection to a particular * device. The name of the device to be opened is passed in argument * name. If the call completes successfully, a handle for the device * is returned in *h. As a special case, specifying a zero-length * string as the device requests opening the first available device * (if there is such a device). */ SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle) { struct fujitsu *dev = NULL; struct fujitsu *s = NULL; SANE_Status ret; DBG (10, "sane_open: start\n"); if(fujitsu_devList){ DBG (15, "sane_open: searching currently attached scanners\n"); } else{ DBG (15, "sane_open: no scanners currently attached, attaching\n"); ret = sane_get_devices(NULL,0); if(ret != SANE_STATUS_GOOD){ return ret; } } if(!name || !name[0]){ DBG (15, "sane_open: no device requested, using default\n"); s = fujitsu_devList; } else{ DBG (15, "sane_open: device %s requested\n", name); for (dev = fujitsu_devList; dev; dev = dev->next) { if (strcmp (dev->sane.name, name) == 0 || strcmp (dev->device_name, name) == 0) { /*always allow sanei devname*/ s = dev; break; } } } if (!s) { DBG (5, "sane_open: no device found\n"); return SANE_STATUS_INVAL; } DBG (15, "sane_open: device %s found\n", s->sane.name); *handle = s; /* connect the fd so we can talk to scanner */ ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ return ret; } DBG (10, "sane_open: finish\n"); return SANE_STATUS_GOOD; } /* * @@ Section 3 - SANE Options functions */ /* * Returns the options we know. * * From the SANE spec: * This function is used to access option descriptors. The function * returns the option descriptor for option number n of the device * represented by handle h. Option number 0 is guaranteed to be a * valid option. Its value is an integer that specifies the number of * options that are available for device handle h (the count includes * option 0). If n is not a valid option index, the function returns * NULL. The returned option descriptor is guaranteed to remain valid * (and at the returned address) until the device is closed. */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct fujitsu *s = handle; int i,j; SANE_Option_Descriptor *opt = &s->opt[option]; DBG (20, "sane_get_option_descriptor: %d\n", option); if ((unsigned) option >= NUM_OPTIONS) return NULL; /* "Mode" group -------------------------------------------------------- */ if(option==OPT_STANDARD_GROUP){ opt->name = SANE_NAME_STANDARD; opt->title = SANE_TITLE_STANDARD; opt->desc = SANE_DESC_STANDARD; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* source */ if(option==OPT_SOURCE){ i=0; if(s->has_flatbed){ s->source_list[i++]=STRING_FLATBED; } if(s->has_adf){ s->source_list[i++]=STRING_ADFFRONT; if(s->has_back){ s->source_list[i++]=STRING_ADFBACK; } if(s->has_duplex){ s->source_list[i++]=STRING_ADFDUPLEX; } } s->source_list[i]=NULL; opt->name = SANE_NAME_SCAN_SOURCE; opt->title = SANE_TITLE_SCAN_SOURCE; opt->desc = SANE_DESC_SCAN_SOURCE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->source_list; opt->size = maxStringSize (opt->constraint.string_list); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* scan mode */ if(option==OPT_MODE){ i=0; if(s->can_mode[MODE_LINEART]){ s->mode_list[i++]=STRING_LINEART; } if(s->can_mode[MODE_HALFTONE]){ s->mode_list[i++]=STRING_HALFTONE; } if(s->can_mode[MODE_GRAYSCALE]){ s->mode_list[i++]=STRING_GRAYSCALE; } if(s->can_mode[MODE_COLOR]){ s->mode_list[i++]=STRING_COLOR; } s->mode_list[i]=NULL; opt->name = SANE_NAME_SCAN_MODE; opt->title = SANE_TITLE_SCAN_MODE; opt->desc = SANE_DESC_SCAN_MODE; opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->mode_list; opt->size = maxStringSize (opt->constraint.string_list); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* resolution */ /* some scanners only support fixed res * build a list of possible choices */ if(option==OPT_RES){ opt->name = SANE_NAME_SCAN_RESOLUTION; opt->title = SANE_TITLE_SCAN_RESOLUTION; opt->desc = SANE_DESC_SCAN_RESOLUTION; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_DPI; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->step_x_res[s->s_mode] && s->step_y_res[s->s_mode]){ s->res_range.min = s->min_x_res; s->res_range.max = s->max_x_res; s->res_range.quant = s->step_x_res[s->s_mode]; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->res_range; } else{ int reses[] = {60,75,100,120,150,160,180,200,240,300,320,400,480,600,800,1200}; i=0; for(j=0;j<16;j++){ if(s->std_res[j] && s->max_x_res >= reses[j] && s->min_x_res <= reses[j] && s->max_y_res >= reses[j] && s->min_y_res <= reses[j] ){ s->res_list[++i] = reses[j]; } } s->res_list[0] = i; opt->constraint_type = SANE_CONSTRAINT_WORD_LIST; opt->constraint.word_list = s->res_list; } } /* "Geometry" group ---------------------------------------------------- */ if(option==OPT_GEOMETRY_GROUP){ opt->name = SANE_NAME_GEOMETRY; opt->title = SANE_TITLE_GEOMETRY; opt->desc = SANE_DESC_GEOMETRY; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* top-left x */ if(option==OPT_TL_X){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->tl_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->tl_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); s->tl_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_TL_X; opt->title = SANE_TITLE_SCAN_TL_X; opt->desc = SANE_DESC_SCAN_TL_X; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->tl_x_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* top-left y */ if(option==OPT_TL_Y){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->tl_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->tl_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); s->tl_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_TL_Y; opt->title = SANE_TITLE_SCAN_TL_Y; opt->desc = SANE_DESC_SCAN_TL_Y; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->tl_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* bottom-right x */ if(option==OPT_BR_X){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->br_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->br_x_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_width(s)); s->br_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_BR_X; opt->title = SANE_TITLE_SCAN_BR_X; opt->desc = SANE_DESC_SCAN_BR_X; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->br_x_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* bottom-right y */ if(option==OPT_BR_Y){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->br_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->br_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); s->br_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_SCAN_BR_Y; opt->title = SANE_TITLE_SCAN_BR_Y; opt->desc = SANE_DESC_SCAN_BR_Y; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->br_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* page width */ if(option==OPT_PAGE_WIDTH){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->paper_x_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_x); s->paper_x_range.max = SCANNER_UNIT_TO_FIXED_MM(s->max_x); s->paper_x_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_PAGE_WIDTH; opt->title = SANE_TITLE_PAGE_WIDTH; opt->desc = SANE_DESC_PAGE_WIDTH; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_x_range; if(s->has_adf){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; } } else{ opt->cap = SANE_CAP_INACTIVE; } } /* page height */ if(option==OPT_PAGE_HEIGHT){ /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->paper_y_range.min = SCANNER_UNIT_TO_FIXED_MM(s->min_y); s->paper_y_range.max = SCANNER_UNIT_TO_FIXED_MM(s->max_y); s->paper_y_range.quant = MM_PER_UNIT_FIX; opt->name = SANE_NAME_PAGE_HEIGHT; opt->title = SANE_TITLE_PAGE_HEIGHT; opt->desc = SANE_DESC_PAGE_HEIGHT; opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->paper_y_range; if(s->has_adf){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->source == SOURCE_FLATBED){ opt->cap |= SANE_CAP_INACTIVE; } } else{ opt->cap = SANE_CAP_INACTIVE; } } /* "Enhancement" group ------------------------------------------------- */ if(option==OPT_ENHANCEMENT_GROUP){ opt->name = SANE_NAME_ENHANCEMENT; opt->title = SANE_TITLE_ENHANCEMENT; opt->desc = SANE_DESC_ENHANCEMENT; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* brightness */ if(option==OPT_BRIGHTNESS){ opt->name = SANE_NAME_BRIGHTNESS; opt->title = SANE_TITLE_BRIGHTNESS; opt->desc = SANE_DESC_BRIGHTNESS; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->brightness_range; s->brightness_range.quant=1; /* some have hardware brightness (always 0 to 255?) */ /* some use LUT or GT (-127 to +127)*/ if (s->brightness_steps || s->num_download_gamma){ s->brightness_range.min=-127; s->brightness_range.max=127; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else{ opt->cap = SANE_CAP_INACTIVE; } } /* contrast */ if(option==OPT_CONTRAST){ opt->name = SANE_NAME_CONTRAST; opt->title = SANE_TITLE_CONTRAST; opt->desc = SANE_DESC_CONTRAST; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->contrast_range; s->contrast_range.quant=1; /* some have hardware contrast (always 0 to 255?) */ /* some use LUT or GT (-127 to +127)*/ if (s->contrast_steps || s->num_download_gamma){ s->contrast_range.min=-127; s->contrast_range.max=127; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else { opt->cap = SANE_CAP_INACTIVE; } } /* gamma */ if(option==OPT_GAMMA){ opt->name = "gamma"; opt->title = SANE_I18N ("Gamma function exponent"); opt->desc = SANE_I18N ("Changes intensity of midtones"); opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->gamma_range; /* value ranges from .3 to 5, should be log scale? */ s->gamma_range.quant=SANE_FIX(0.01); s->gamma_range.min=SANE_FIX(0.3); s->gamma_range.max=SANE_FIX(5); /* scanner has gamma via LUT or GT */ /*if (s->num_download_gamma){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else { opt->cap = SANE_CAP_INACTIVE; }*/ opt->cap = SANE_CAP_INACTIVE; } /*threshold*/ if(option==OPT_THRESHOLD){ opt->name = SANE_NAME_THRESHOLD; opt->title = SANE_TITLE_THRESHOLD; opt->desc = SANE_DESC_THRESHOLD; opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->threshold_range; s->threshold_range.min=0; s->threshold_range.max=s->threshold_steps; s->threshold_range.quant=1; if (s->threshold_steps){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->u_mode != MODE_LINEART){ opt->cap |= SANE_CAP_INACTIVE; } } else { opt->cap = SANE_CAP_INACTIVE; } } /* =============== common ipc params ================================ */ if(option==OPT_RIF){ opt->name = "rif"; opt->title = SANE_I18N ("RIF"); opt->desc = SANE_I18N ("Reverse image format"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_rif) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_HT_TYPE){ i=0; s->ht_type_list[i++]=STRING_DEFAULT; s->ht_type_list[i++]=STRING_DITHER; s->ht_type_list[i++]=STRING_DIFFUSION; s->ht_type_list[i]=NULL; opt->name = "ht-type"; opt->title = SANE_I18N ("Halftone type"); opt->desc = SANE_I18N ("Control type of halftone filter"); opt->type = SANE_TYPE_STRING; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->ht_type_list; opt->size = maxStringSize (opt->constraint.string_list); if(s->has_diffusion){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->s_mode != MODE_HALFTONE){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_HT_PATTERN){ opt->name = "ht-pattern"; opt->title = SANE_I18N ("Halftone pattern"); opt->desc = SANE_I18N ("Control pattern of halftone filter"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->ht_pattern_range; s->ht_pattern_range.min=0; s->ht_pattern_range.max=s->num_internal_dither - 1; s->ht_pattern_range.quant=1; if (s->num_internal_dither){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(s->s_mode != MODE_HALFTONE){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_OUTLINE){ opt->name = "outline"; opt->title = SANE_I18N ("Outline"); opt->desc = SANE_I18N ("Perform outline extraction"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_outline) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_EMPHASIS){ opt->name = "emphasis"; opt->title = SANE_I18N ("Emphasis"); opt->desc = SANE_I18N ("Negative to smooth or positive to sharpen image"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->emphasis_range; s->emphasis_range.min=-128; s->emphasis_range.max=127; s->emphasis_range.quant=1; if (s->has_emphasis) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_SEPARATION){ opt->name = "separation"; opt->title = SANE_I18N ("Separation"); opt->desc = SANE_I18N ("Enable automatic separation of image and text"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_autosep) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_MIRRORING){ opt->name = "mirroring"; opt->title = SANE_I18N ("Mirroring"); opt->desc = SANE_I18N ("Reflect output image horizontally"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_mirroring) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_WL_FOLLOW){ i=0; s->wl_follow_list[i++]=STRING_DEFAULT; s->wl_follow_list[i++]=STRING_ON; s->wl_follow_list[i++]=STRING_OFF; s->wl_follow_list[i]=NULL; opt->name = "wl-follow"; opt->title = SANE_I18N ("White level follower"); opt->desc = SANE_I18N ("Control white level follower"); opt->type = SANE_TYPE_STRING; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->wl_follow_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_wl_follow) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; else opt->cap = SANE_CAP_INACTIVE; } /* =============== DTC params ================================ */ /* enabled when in dtc mode (manually or by default) */ if(option==OPT_BP_FILTER){ opt->name = "bp-filter"; opt->title = SANE_I18N ("BP filter"); opt->desc = SANE_I18N ("Improves quality of high resolution ball-point pen text"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(get_ipc_mode(s) == WD_ipc_SDTC){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_SMOOTHING){ opt->name = "smoothing"; opt->title = SANE_I18N ("Smoothing"); opt->desc = SANE_I18N ("Enable smoothing for improved OCR"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(get_ipc_mode(s) == WD_ipc_SDTC){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_GAMMA_CURVE){ opt->name = "gamma-curve"; opt->title = SANE_I18N ("Gamma curve"); opt->desc = SANE_I18N ("Gamma curve, from light to dark, but upper two may not work"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->gamma_curve_range; s->gamma_curve_range.min=0; s->gamma_curve_range.max=3; s->gamma_curve_range.quant=1; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(get_ipc_mode(s) == WD_ipc_SDTC){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_THRESHOLD_CURVE){ opt->name = "threshold-curve"; opt->title = SANE_I18N ("Threshold curve"); opt->desc = SANE_I18N ("Threshold curve, from light to dark, but upper two may not be linear"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->threshold_curve_range; s->threshold_curve_range.min=0; s->threshold_curve_range.max=7; s->threshold_curve_range.quant=1; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(get_ipc_mode(s) == WD_ipc_SDTC){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_THRESHOLD_WHITE){ opt->name = "threshold-white"; opt->title = SANE_I18N ("Threshold white"); opt->desc = SANE_I18N ("Set pixels equal to threshold to white instead of black"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(get_ipc_mode(s) == WD_ipc_SDTC){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_NOISE_REMOVAL){ opt->name = "noise-removal"; opt->title = SANE_I18N ("Noise removal"); opt->desc = SANE_I18N ("Noise removal"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(get_ipc_mode(s) == WD_ipc_SDTC){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_MATRIX_5){ opt->name = "matrix-5x5"; opt->title = SANE_I18N ("Matrix 5x5"); opt->desc = SANE_I18N ("Remove 5 pixel square noise"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(!s->noise_removal){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_MATRIX_4){ opt->name = "matrix-4x4"; opt->title = SANE_I18N ("Matrix 4x4"); opt->desc = SANE_I18N ("Remove 4 pixel square noise"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(!s->noise_removal){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_MATRIX_3){ opt->name = "matrix-3x3"; opt->title = SANE_I18N ("Matrix 3x3"); opt->desc = SANE_I18N ("Remove 3 pixel square noise"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(!s->noise_removal){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_MATRIX_2){ opt->name = "matrix-2x2"; opt->title = SANE_I18N ("Matrix 2x2"); opt->desc = SANE_I18N ("Remove 2 pixel square noise"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if ( s->has_dtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(!s->noise_removal){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } /* =============== SDTC param ================================ */ /* enabled when in sdtc mode (manually or by default) */ /* called variance with ipc2, sensitivity with ipc3 */ if(option==OPT_VARIANCE){ opt->name = "variance"; opt->title = SANE_I18N ("Variance"); opt->desc = SANE_I18N ("Set SDTC variance rate (sensitivity), 0 equals 127"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->variance_range; s->variance_range.min=0; s->variance_range.max=255; s->variance_range.quant=1; if ( s->has_sdtc ){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if(get_ipc_mode(s) == WD_ipc_DTC){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } /* "Advanced" group ------------------------------------------------------ */ if(option==OPT_ADVANCED_GROUP){ opt->name = SANE_NAME_ADVANCED; opt->title = SANE_TITLE_ADVANCED; opt->desc = SANE_DESC_ADVANCED; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } /*automatic width detection */ if(option==OPT_AWD){ opt->name = "awd"; opt->title = SANE_I18N ("Auto width detection"); opt->desc = SANE_I18N ("Scanner detects paper sides. May reduce scanning speed."); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_NONE; /* this option is useless by itself? */ if (0 && s->has_MS_auto && s->has_hybrid_crop_deskew){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; } else opt->cap = SANE_CAP_INACTIVE; } /*automatic length detection */ if(option==OPT_ALD){ opt->name = "ald"; opt->title = SANE_I18N ("Auto length detection"); opt->desc = SANE_I18N ("Scanner detects paper lower edge. May confuse some frontends."); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_NONE; if (s->has_MS_auto){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; } else opt->cap = SANE_CAP_INACTIVE; } /*image compression*/ if(option==OPT_COMPRESS){ i=0; s->compress_list[i++]=STRING_NONE; if(s->has_comp_JPG1){ #ifndef SANE_JPEG_DISABLED s->compress_list[i++]=STRING_JPEG; #endif } s->compress_list[i]=NULL; opt->name = "compression"; opt->title = SANE_I18N ("Compression"); opt->desc = SANE_I18N ("Enable compressed data. May crash your front-end program"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->compress_list; opt->size = maxStringSize (opt->constraint.string_list); if (i > 1){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if ( must_downsample(s) || s->s_mode < MODE_GRAYSCALE ){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } /*image compression arg*/ if(option==OPT_COMPRESS_ARG){ opt->name = "compression-arg"; opt->title = SANE_I18N ("Compression argument"); opt->desc = SANE_I18N ("Level of JPEG compression. 1 is small file, 7 is large file. 0 (default) is same as 4"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->compress_arg_range; s->compress_arg_range.quant=1; if(s->has_comp_JPG1){ s->compress_arg_range.min=0; s->compress_arg_range.max=7; #ifndef SANE_JPEG_DISABLED opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; #endif if(s->compress != COMP_JPEG){ opt->cap |= SANE_CAP_INACTIVE; } } else opt->cap = SANE_CAP_INACTIVE; } /*double feed detection*/ if(option==OPT_DF_ACTION){ s->df_action_list[0] = STRING_DEFAULT; s->df_action_list[1] = STRING_CONTINUE; s->df_action_list[2] = STRING_STOP; s->df_action_list[3] = NULL; opt->name = "df-action"; opt->title = SANE_I18N ("DF action"); opt->desc = SANE_I18N ("Action following double feed error"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->df_action_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_df) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*double feed by skew*/ if(option==OPT_DF_SKEW){ opt->name = "df-skew"; opt->title = SANE_I18N ("DF skew"); opt->desc = SANE_I18N ("Enable double feed error due to skew"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_NONE; if (s->has_MS_df){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->df_action) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; } /*double feed by thickness */ if(option==OPT_DF_THICKNESS){ opt->name = "df-thickness"; opt->title = SANE_I18N ("DF thickness"); opt->desc = SANE_I18N ("Enable double feed error due to paper thickness"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_NONE; if (s->has_MS_df){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->df_action) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; } /*double feed by length*/ if(option==OPT_DF_LENGTH){ opt->name = "df-length"; opt->title = SANE_I18N ("DF length"); opt->desc = SANE_I18N ("Enable double feed error due to paper length"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_NONE; if (s->has_MS_df){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->df_action) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; } /*double feed length difference*/ if(option==OPT_DF_DIFF){ s->df_diff_list[0] = STRING_DEFAULT; s->df_diff_list[1] = STRING_10MM; s->df_diff_list[2] = STRING_15MM; s->df_diff_list[3] = STRING_20MM; s->df_diff_list[4] = NULL; opt->name = "df-diff"; opt->title = SANE_I18N ("DF length difference"); opt->desc = SANE_I18N ("Difference in page length to trigger double feed error"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->df_diff_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_df){ opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->df_action || !s->df_diff) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; } /*df_recovery*/ if(option==OPT_DF_RECOVERY){ s->df_recovery_list[0] = STRING_DEFAULT; s->df_recovery_list[1] = STRING_OFF; s->df_recovery_list[2] = STRING_ON; s->df_recovery_list[3] = NULL; opt->name = "df-recovery"; opt->title = SANE_I18N ("DF recovery mode"); opt->desc = SANE_I18N ("Request scanner to reverse feed on paper jam"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->df_recovery_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_df && s->has_df_recovery) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*paper_protect*/ if(option==OPT_PAPER_PROTECT){ s->paper_protect_list[0] = STRING_DEFAULT; s->paper_protect_list[1] = STRING_OFF; s->paper_protect_list[2] = STRING_ON; s->paper_protect_list[3] = NULL; opt->name = "paper-protect"; opt->title = SANE_I18N ("Paper protection"); opt->desc = SANE_I18N ("Request scanner to predict jams in the ADF"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->paper_protect_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_df && s->has_paper_protect) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*adv_paper_prot*/ if(option==OPT_ADV_PAPER_PROT){ s->adv_paper_prot_list[0] = STRING_DEFAULT; s->adv_paper_prot_list[1] = STRING_OFF; s->adv_paper_prot_list[2] = STRING_ON; s->adv_paper_prot_list[3] = NULL; opt->name = "adv-paper-protect"; opt->title = SANE_I18N ("Advanced paper protection"); opt->desc = SANE_I18N ("Request scanner to predict jams in the ADF using improved sensors"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->adv_paper_prot_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_df && s->has_adv_paper_prot) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*staple detection*/ if(option==OPT_STAPLE_DETECT){ s->staple_detect_list[0] = STRING_DEFAULT; s->staple_detect_list[1] = STRING_OFF; s->staple_detect_list[2] = STRING_ON; s->staple_detect_list[3] = NULL; opt->name = "staple-detect"; opt->title = SANE_I18N ("Staple detection"); opt->desc = SANE_I18N ("Request scanner to detect jams in the ADF caused by staples"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->staple_detect_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_df && s->has_staple_detect) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*background color*/ if(option==OPT_BG_COLOR){ s->bg_color_list[0] = STRING_DEFAULT; s->bg_color_list[1] = STRING_WHITE; s->bg_color_list[2] = STRING_BLACK; s->bg_color_list[3] = NULL; opt->name = "bgcolor"; opt->title = SANE_I18N ("Background color"); opt->desc = SANE_I18N ("Set color of background for scans. May conflict with overscan option"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->bg_color_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_bg) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*dropout color*/ if(option==OPT_DROPOUT_COLOR){ s->do_color_list[0] = STRING_DEFAULT; s->do_color_list[1] = STRING_RED; s->do_color_list[2] = STRING_GREEN; s->do_color_list[3] = STRING_BLUE; s->do_color_list[4] = NULL; opt->name = "dropoutcolor"; opt->title = SANE_I18N ("Dropout color"); opt->desc = SANE_I18N ("One-pass scanners use only one color during gray or binary scanning, useful for colored paper or ink"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->do_color_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_dropout || s->has_vuid_3091 || must_downsample(s)){ opt->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; if(s->u_mode == MODE_COLOR) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; } /*buffer mode*/ if(option==OPT_BUFF_MODE){ s->buff_mode_list[0] = STRING_DEFAULT; s->buff_mode_list[1] = STRING_OFF; s->buff_mode_list[2] = STRING_ON; s->buff_mode_list[3] = NULL; opt->name = "buffermode"; opt->title = SANE_I18N ("Buffer mode"); opt->desc = SANE_I18N ("Request scanner to read pages quickly from ADF into internal memory"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->buff_mode_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_buff) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*prepick*/ if(option==OPT_PREPICK){ s->prepick_list[0] = STRING_DEFAULT; s->prepick_list[1] = STRING_OFF; s->prepick_list[2] = STRING_ON; s->prepick_list[3] = NULL; opt->name = "prepick"; opt->title = SANE_I18N ("Prepick"); opt->desc = SANE_I18N ("Request scanner to grab next page from ADF"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->prepick_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_prepick) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*overscan*/ if(option==OPT_OVERSCAN){ s->overscan_list[0] = STRING_DEFAULT; s->overscan_list[1] = STRING_OFF; s->overscan_list[2] = STRING_ON; s->overscan_list[3] = NULL; opt->name = "overscan"; opt->title = SANE_I18N ("Overscan"); opt->desc = SANE_I18N ("Collect a few mm of background on top side of scan, before paper enters ADF, and increase maximum scan area beyond paper size, to allow collection on remaining sides. May conflict with bgcolor option"); opt->type = SANE_TYPE_STRING; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->overscan_list; opt->size = maxStringSize (opt->constraint.string_list); if (s->has_MS_auto && (s->os_x_basic || s->os_y_basic)) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*sleep_time*/ if(option==OPT_SLEEP_TIME){ s->sleep_time_range.min = 0; s->sleep_time_range.max = 60; s->sleep_time_range.quant = 1; opt->name = "sleeptimer"; opt->title = SANE_I18N ("Sleep timer"); opt->desc = SANE_I18N ("Time in minutes until the internal power supply switches to sleep mode"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range=&s->sleep_time_range; if(s->has_MS_sleep) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*off_time*/ if(option==OPT_OFF_TIME){ s->off_time_range.min = 0; s->off_time_range.max = 960; s->off_time_range.quant = 1; opt->name = "offtimer"; opt->title = SANE_I18N ("Off timer"); opt->desc = SANE_I18N ("Time in minutes until the internal power supply switches the scanner off. Will be rounded to nearest 15 minutes. Zero means never power off."); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range=&s->off_time_range; if(s->has_off_mode) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*duplex offset*/ if(option==OPT_DUPLEX_OFFSET){ s->duplex_offset_range.min = -16; s->duplex_offset_range.max = 16; s->duplex_offset_range.quant = 1; opt->name = "duplexoffset"; opt->title = SANE_I18N ("Duplex offset"); opt->desc = SANE_I18N ("Adjust front/back offset"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->duplex_offset_range; if(s->duplex_interlace == DUPLEX_INTERLACE_3091) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_GREEN_OFFSET){ s->green_offset_range.min = -16; s->green_offset_range.max = 16; s->green_offset_range.quant = 1; opt->name = "greenoffset"; opt->title = SANE_I18N ("Green offset"); opt->desc = SANE_I18N ("Adjust green/red offset"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->green_offset_range; if(s->color_interlace == COLOR_INTERLACE_3091) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_BLUE_OFFSET){ s->blue_offset_range.min = -16; s->blue_offset_range.max = 16; s->blue_offset_range.quant = 1; opt->name = "blueoffset"; opt->title = SANE_I18N ("Blue offset"); opt->desc = SANE_I18N ("Adjust blue/red offset"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->blue_offset_range; if(s->color_interlace == COLOR_INTERLACE_3091) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_LOW_MEM){ opt->name = "lowmemory"; opt->title = SANE_I18N ("Low Memory"); opt->desc = SANE_I18N ("Limit driver memory usage for use in embedded systems. Causes some duplex transfers to alternate sides on each call to sane_read. Value of option 'side' can be used to determine correct image. This option should only be used with custom front-end software."); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->size = sizeof(SANE_Word); if (1) opt->cap= SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_NONE; } if(option==OPT_SIDE){ opt->name = "side"; opt->title = SANE_I18N ("Duplex side"); opt->desc = SANE_I18N ("Tells which side (0=front, 1=back) of a duplex scan the next call to sane_read will return."); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->size = sizeof(SANE_Word); opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; opt->constraint_type = SANE_CONSTRAINT_NONE; } /*deskew and crop by hardware*/ if(option==OPT_HWDESKEWCROP){ opt->name = "hwdeskewcrop"; opt->title = SANE_I18N ("Hardware deskew and crop"); opt->desc = SANE_I18N ("Request scanner to rotate and crop pages digitally."); opt->type = SANE_TYPE_BOOL; if (s->has_hybrid_crop_deskew) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*deskew by software*/ if(option==OPT_SWDESKEW){ opt->name = "swdeskew"; opt->title = SANE_I18N ("Software deskew"); opt->desc = SANE_I18N ("Request driver to rotate skewed pages digitally."); opt->type = SANE_TYPE_BOOL; if (1) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /*software despeckle radius*/ if(option==OPT_SWDESPECK){ opt->name = "swdespeck"; opt->title = SANE_I18N ("Software despeckle diameter"); opt->desc = SANE_I18N ("Maximum diameter of lone dots to remove from scan."); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->swdespeck_range; s->swdespeck_range.quant=1; if(1){ s->swdespeck_range.min=0; s->swdespeck_range.max=9; opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } else opt->cap = SANE_CAP_INACTIVE; } /*crop by software*/ if(option==OPT_SWCROP){ opt->name = "swcrop"; opt->title = SANE_I18N ("Software crop"); opt->desc = SANE_I18N ("Request driver to remove border from pages digitally."); opt->type = SANE_TYPE_BOOL; if (1) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /* Software blank page skip */ if(option==OPT_SWSKIP){ opt->name = "swskip"; opt->title = SANE_I18N ("Software blank skip percentage"); opt->desc = SANE_I18N("Request driver to discard pages with low percentage of dark pixels"); opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_PERCENT; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->swskip_range; s->swskip_range.quant=SANE_FIX(0.10001); s->swskip_range.min=SANE_FIX(0); s->swskip_range.max=SANE_FIX(100); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /*halt scanner feeder when cancelling*/ if(option==OPT_HALT_ON_CANCEL){ opt->name = "halt-on-cancel"; opt->title = SANE_I18N ("Halt on Cancel"); opt->desc = SANE_I18N ("Request driver to halt the paper feed instead of eject during a cancel."); opt->type = SANE_TYPE_BOOL; if (s->has_op_halt) opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } /* "Endorser" group ------------------------------------------------------ */ if(option==OPT_ENDORSER_GROUP){ opt->name = "endorser-options"; opt->title = SANE_I18N ("Endorser Options"); opt->desc = SANE_I18N ("Controls for endorser unit"); opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; /*flaming hack to get scanimage to hide group*/ if ( !(s->has_endorser_f || s->has_endorser_b) ) opt->type = SANE_TYPE_BOOL; } if(option==OPT_ENDORSER){ opt->name = "endorser"; opt->title = SANE_I18N ("Endorser"); opt->desc = SANE_I18N ("Enable endorser unit"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; opt->size = sizeof(SANE_Word); if (s->has_endorser_f || s->has_endorser_b) opt->cap= SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_NONE; } if(option==OPT_ENDORSER_BITS){ opt->name = "endorser-bits"; opt->title = SANE_I18N ("Endorser bits"); opt->desc = SANE_I18N ("Determines maximum endorser counter value."); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->size = sizeof(SANE_Word); /*old type cant do this?*/ if ((s->has_endorser_f && s->endorser_type_f != ET_OLD) || (s->has_endorser_b && s->endorser_type_b != ET_OLD)){ opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->u_endorser) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->endorser_bits_range; s->endorser_bits_range.min = 16; s->endorser_bits_range.max = 24; s->endorser_bits_range.quant = 8; } if(option==OPT_ENDORSER_VAL){ opt->name = "endorser-val"; opt->title = SANE_I18N ("Endorser value"); opt->desc = SANE_I18N ("Initial endorser counter value."); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->size = sizeof(SANE_Word); if (s->has_endorser_f || s->has_endorser_b){ opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->u_endorser) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->endorser_val_range; s->endorser_val_range.min = 0; s->endorser_val_range.max = (1 << s->u_endorser_bits)-1; s->endorser_val_range.quant = 1; } if(option==OPT_ENDORSER_STEP){ opt->name = "endorser-step"; opt->title = SANE_I18N ("Endorser step"); opt->desc = SANE_I18N ("Change endorser counter value by this much for each page."); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; opt->size = sizeof(SANE_Word); if (s->has_endorser_f || s->has_endorser_b){ opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->u_endorser) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &s->endorser_step_range; s->endorser_step_range.min = -2; s->endorser_step_range.max = 2; s->endorser_step_range.quant = 1; } if(option==OPT_ENDORSER_Y){ opt->name = "endorser-y"; opt->title = SANE_I18N ("Endorser Y"); opt->desc = SANE_I18N ("Endorser print offset from top of paper."); opt->type = SANE_TYPE_FIXED; opt->unit = SANE_UNIT_MM; opt->size = sizeof(SANE_Word); if (s->has_endorser_f || s->has_endorser_b){ opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->u_endorser) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->endorser_y_range); /* values stored in 1200 dpi units */ /* must be converted to MM for sane */ s->endorser_y_range.min = SCANNER_UNIT_TO_FIXED_MM(0); s->endorser_y_range.max = SCANNER_UNIT_TO_FIXED_MM(get_page_height(s)); s->endorser_y_range.quant = MM_PER_UNIT_FIX; } if(option==OPT_ENDORSER_FONT){ opt->name = "endorser-font"; opt->title = SANE_I18N ("Endorser font"); opt->desc = SANE_I18N ("Endorser printing font."); opt->type = SANE_TYPE_STRING; opt->unit = SANE_UNIT_NONE; /*only newest can do this?*/ if ((s->has_endorser_f && s->endorser_type_f == ET_40) || (s->has_endorser_b && s->endorser_type_b == ET_40)){ opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->u_endorser) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->endorser_font_list; s->endorser_font_list[0] = STRING_HORIZONTAL; s->endorser_font_list[1] = STRING_HORIZONTALBOLD; s->endorser_font_list[2] = STRING_HORIZONTALNARROW; s->endorser_font_list[3] = STRING_VERTICAL; s->endorser_font_list[4] = STRING_VERTICALBOLD; s->endorser_font_list[5] = NULL; opt->size = maxStringSize (opt->constraint.string_list); } if(option==OPT_ENDORSER_DIR){ opt->name = "endorser-dir"; opt->title = SANE_I18N ("Endorser direction"); opt->desc = SANE_I18N ("Endorser printing direction."); opt->type = SANE_TYPE_STRING; opt->unit = SANE_UNIT_NONE; if (s->has_endorser_f || s->has_endorser_b){ opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->u_endorser) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->endorser_dir_list; s->endorser_dir_list[0] = STRING_TOPTOBOTTOM; s->endorser_dir_list[1] = STRING_BOTTOMTOTOP; s->endorser_dir_list[2] = NULL; opt->size = maxStringSize (opt->constraint.string_list); } if(option==OPT_ENDORSER_SIDE){ opt->name = "endorser-side"; opt->title = SANE_I18N ("Endorser side"); opt->desc = SANE_I18N ("Endorser printing side, requires hardware support to change"); opt->type = SANE_TYPE_STRING; opt->unit = SANE_UNIT_NONE; /* only show if both endorsers are installed */ if (s->has_endorser_f && s->has_endorser_b){ opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->u_endorser) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_STRING_LIST; opt->constraint.string_list = s->endorser_side_list; s->endorser_side_list[0] = STRING_FRONT; s->endorser_side_list[1] = STRING_BACK; s->endorser_side_list[2] = NULL; opt->size = maxStringSize (opt->constraint.string_list); } if(option==OPT_ENDORSER_STRING){ opt->name = "endorser-string"; opt->title = SANE_I18N ("Endorser string"); opt->desc = SANE_I18N ("Endorser alphanumeric print format. %05ud or %08ud at the end will be replaced by counter value."); opt->type = SANE_TYPE_STRING; opt->unit = SANE_UNIT_NONE; opt->size = s->endorser_string_len + 1; if (s->has_endorser_f || s->has_endorser_b){ opt->cap=SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; if(!s->u_endorser) opt->cap |= SANE_CAP_INACTIVE; } else opt->cap = SANE_CAP_INACTIVE; opt->constraint_type = SANE_CONSTRAINT_NONE; } /* "Sensor" group ------------------------------------------------------ */ if(option==OPT_SENSOR_GROUP){ opt->name = SANE_NAME_SENSORS; opt->title = SANE_TITLE_SENSORS; opt->desc = SANE_DESC_SENSORS; opt->type = SANE_TYPE_GROUP; opt->constraint_type = SANE_CONSTRAINT_NONE; } if(option==OPT_TOP){ opt->name = "top-edge"; opt->title = SANE_I18N ("Top edge"); opt->desc = SANE_I18N ("Paper is pulled partly into adf"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status || s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_A3){ opt->name = "a3-paper"; opt->title = SANE_I18N ("A3 paper"); opt->desc = SANE_I18N ("A3 paper detected"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_B4){ opt->name = "b4-paper"; opt->title = SANE_I18N ("B4 paper"); opt->desc = SANE_I18N ("B4 paper detected"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_A4){ opt->name = "a4-paper"; opt->title = SANE_I18N ("A4 paper"); opt->desc = SANE_I18N ("A4 paper detected"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_B5){ opt->name = "b5-paper"; opt->title = SANE_I18N ("B5 paper"); opt->desc = SANE_I18N ("B5 paper detected"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_HOPPER){ opt->name = SANE_NAME_PAGE_LOADED; opt->title = SANE_TITLE_PAGE_LOADED; opt->desc = SANE_DESC_PAGE_LOADED; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status || s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_OMR){ opt->name = "omr-df"; opt->title = SANE_I18N ("OMR or DF"); opt->desc = SANE_I18N ("OMR or double feed detected"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_ADF_OPEN){ opt->name = SANE_NAME_COVER_OPEN; opt->title = SANE_TITLE_COVER_OPEN; opt->desc = SANE_DESC_COVER_OPEN; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status || s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_SLEEP){ opt->name = "power-save"; opt->title = SANE_I18N ("Power saving"); opt->desc = SANE_I18N ("Scanner in power saving mode"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_SEND_SW){ opt->name = SANE_NAME_EMAIL; opt->title = SANE_TITLE_EMAIL; opt->desc = SANE_DESC_EMAIL; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status || s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_MANUAL_FEED){ opt->name = "manual-feed"; opt->title = SANE_I18N ("Manual feed"); opt->desc = SANE_I18N ("Manual feed selected"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_SCAN_SW){ opt->name = SANE_NAME_SCAN; opt->title = SANE_TITLE_SCAN; opt->desc = SANE_DESC_SCAN; opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status || s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_FUNCTION){ opt->name = "function"; opt->title = SANE_I18N ("Function"); opt->desc = SANE_I18N ("Function character on screen"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status || s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_INK_EMPTY){ opt->name = "ink-low"; opt->title = SANE_I18N ("Ink low"); opt->desc = SANE_I18N ("Imprinter ink running low"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status && (s->has_endorser_f || s->has_endorser_b)) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_DOUBLE_FEED){ opt->name = "double-feed"; opt->title = SANE_I18N ("Double feed"); opt->desc = SANE_I18N ("Double feed detected"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status || s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_ERROR_CODE){ opt->name = "error-code"; opt->title = SANE_I18N ("Error code"); opt->desc = SANE_I18N ("Hardware error code"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_SKEW_ANGLE){ opt->name = "skew-angle"; opt->title = SANE_I18N ("Skew angle"); opt->desc = SANE_I18N ("Requires black background for scanning"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_INK_REMAIN){ opt->name = "ink-remain"; opt->title = SANE_I18N ("Ink remaining"); opt->desc = SANE_I18N ("Imprinter ink level"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; if (s->has_cmd_hw_status && (s->has_endorser_f || s->has_endorser_b)) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_DENSITY_SW){ opt->name = "density"; opt->title = SANE_I18N ("Density"); opt->desc = SANE_I18N ("Density dial"); opt->type = SANE_TYPE_INT; opt->unit = SANE_UNIT_NONE; if (s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } if(option==OPT_DUPLEX_SW){ opt->name = "duplex"; opt->title = SANE_I18N ("Duplex switch"); opt->desc = SANE_I18N ("Duplex switch"); opt->type = SANE_TYPE_BOOL; opt->unit = SANE_UNIT_NONE; if (s->ghs_in_rs) opt->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else opt->cap = SANE_CAP_INACTIVE; } return opt; } /** * Gets or sets an option value. * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which * the option is controlled is specified by parameter action. The * possible values of this parameter are described in more detail * below. The value of the option is passed through argument val. It * is a pointer to the memory that holds the option value. The memory * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon * encountering the first NUL terminator in the string. If argument i * is not NULL, the value of *i will be set to provide details on how * well the request has been met. */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { struct fujitsu *s = (struct fujitsu *) handle; SANE_Int dummy = 0; SANE_Status ret = SANE_STATUS_GOOD; /* Make sure that all those statements involving *info cannot break (better * than having to do "if (info) ..." everywhere!) */ if (info == 0) info = &dummy; /*blast info in case frontend forgot*/ *info = 0; if (option >= NUM_OPTIONS) { DBG (5, "sane_control_option: %d too big\n", option); return SANE_STATUS_INVAL; } if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) { DBG (5, "sane_control_option: %d inactive\n", option); return SANE_STATUS_INVAL; } /* * SANE_ACTION_GET_VALUE: We have to find out the current setting and * return it in a human-readable form (often, text). */ if (action == SANE_ACTION_GET_VALUE) { SANE_Word * val_p = (SANE_Word *) val; DBG (20, "sane_control_option: get value for '%s' (%d)\n", s->opt[option].name,option); switch (option) { case OPT_NUM_OPTS: *val_p = NUM_OPTIONS; return SANE_STATUS_GOOD; case OPT_SOURCE: if(s->source == SOURCE_FLATBED){ strcpy (val, STRING_FLATBED); } else if(s->source == SOURCE_ADF_FRONT){ strcpy (val, STRING_ADFFRONT); } else if(s->source == SOURCE_ADF_BACK){ strcpy (val, STRING_ADFBACK); } else if(s->source == SOURCE_ADF_DUPLEX){ strcpy (val, STRING_ADFDUPLEX); } return SANE_STATUS_GOOD; case OPT_MODE: if(s->u_mode == MODE_LINEART){ strcpy (val, STRING_LINEART); } else if(s->u_mode == MODE_HALFTONE){ strcpy (val, STRING_HALFTONE); } else if(s->u_mode == MODE_GRAYSCALE){ strcpy (val, STRING_GRAYSCALE); } else if(s->u_mode == MODE_COLOR){ strcpy (val, STRING_COLOR); } return SANE_STATUS_GOOD; case OPT_RES: *val_p = s->resolution_x; return SANE_STATUS_GOOD; case OPT_TL_X: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->tl_x); return SANE_STATUS_GOOD; case OPT_TL_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->tl_y); return SANE_STATUS_GOOD; case OPT_BR_X: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->br_x); return SANE_STATUS_GOOD; case OPT_BR_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->br_y); return SANE_STATUS_GOOD; case OPT_PAGE_WIDTH: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->page_width); return SANE_STATUS_GOOD; case OPT_PAGE_HEIGHT: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->page_height); return SANE_STATUS_GOOD; case OPT_BRIGHTNESS: *val_p = s->brightness; return SANE_STATUS_GOOD; case OPT_CONTRAST: *val_p = s->contrast; return SANE_STATUS_GOOD; case OPT_GAMMA: *val_p = SANE_FIX(s->gamma); return SANE_STATUS_GOOD; case OPT_THRESHOLD: *val_p = s->threshold; return SANE_STATUS_GOOD; /* IPC */ case OPT_RIF: *val_p = s->rif; return SANE_STATUS_GOOD; case OPT_HT_TYPE: switch (s->ht_type) { case WD_ht_type_DEFAULT: strcpy (val, STRING_DEFAULT); break; case WD_ht_type_DITHER: strcpy (val, STRING_DITHER); break; case WD_ht_type_DIFFUSION: strcpy (val, STRING_DIFFUSION); break; } return SANE_STATUS_GOOD; case OPT_HT_PATTERN: *val_p = s->ht_pattern; return SANE_STATUS_GOOD; case OPT_OUTLINE: *val_p = s->outline; return SANE_STATUS_GOOD; case OPT_EMPHASIS: *val_p = s->emphasis; return SANE_STATUS_GOOD; case OPT_SEPARATION: *val_p = s->separation; return SANE_STATUS_GOOD; case OPT_MIRRORING: *val_p = s->mirroring; return SANE_STATUS_GOOD; case OPT_WL_FOLLOW: switch (s->wl_follow) { case WD_wl_follow_DEFAULT: strcpy (val, STRING_DEFAULT); break; case WD_wl_follow_ON: strcpy (val, STRING_ON); break; case WD_wl_follow_OFF: strcpy (val, STRING_OFF); break; } return SANE_STATUS_GOOD; /* DTC params*/ case OPT_BP_FILTER: *val_p = s->bp_filter; return SANE_STATUS_GOOD; case OPT_SMOOTHING: *val_p = s->smoothing; return SANE_STATUS_GOOD; case OPT_GAMMA_CURVE: *val_p = s->gamma_curve; return SANE_STATUS_GOOD; case OPT_THRESHOLD_CURVE: *val_p = s->threshold_curve; return SANE_STATUS_GOOD; case OPT_THRESHOLD_WHITE: *val_p = s->threshold_white; return SANE_STATUS_GOOD; case OPT_NOISE_REMOVAL: *val_p = s->noise_removal; return SANE_STATUS_GOOD; case OPT_MATRIX_5: *val_p = s->matrix_5; return SANE_STATUS_GOOD; case OPT_MATRIX_4: *val_p = s->matrix_4; return SANE_STATUS_GOOD; case OPT_MATRIX_3: *val_p = s->matrix_3; return SANE_STATUS_GOOD; case OPT_MATRIX_2: *val_p = s->matrix_2; return SANE_STATUS_GOOD; /* SDTC params*/ case OPT_VARIANCE: *val_p = s->variance; return SANE_STATUS_GOOD; /* Advanced Group */ case OPT_AWD: *val_p = s->awd; return SANE_STATUS_GOOD; case OPT_ALD: *val_p = s->ald; return SANE_STATUS_GOOD; case OPT_COMPRESS: if(s->compress == COMP_JPEG){ strcpy (val, STRING_JPEG); } else{ strcpy (val, STRING_NONE); } return SANE_STATUS_GOOD; case OPT_COMPRESS_ARG: *val_p = s->compress_arg; return SANE_STATUS_GOOD; case OPT_DF_ACTION: switch (s->df_action) { case DF_DEFAULT: strcpy (val, STRING_DEFAULT); break; case DF_CONTINUE: strcpy (val, STRING_CONTINUE); break; case DF_STOP: strcpy (val, STRING_STOP); break; } return SANE_STATUS_GOOD; case OPT_DF_SKEW: *val_p = s->df_skew; return SANE_STATUS_GOOD; case OPT_DF_THICKNESS: *val_p = s->df_thickness; return SANE_STATUS_GOOD; case OPT_DF_LENGTH: *val_p = s->df_length; return SANE_STATUS_GOOD; case OPT_DF_DIFF: switch (s->df_diff) { case MSEL_df_diff_DEFAULT: strcpy (val, STRING_DEFAULT); break; case MSEL_df_diff_10MM: strcpy (val, STRING_10MM); break; case MSEL_df_diff_15MM: strcpy (val, STRING_15MM); break; case MSEL_df_diff_20MM: strcpy (val, STRING_20MM); break; } return SANE_STATUS_GOOD; case OPT_DF_RECOVERY: switch (s->df_recovery) { case MSEL_DEFAULT: strcpy (val, STRING_DEFAULT); break; case MSEL_ON: strcpy (val, STRING_ON); break; case MSEL_OFF: strcpy (val, STRING_OFF); break; } return SANE_STATUS_GOOD; case OPT_PAPER_PROTECT: switch (s->paper_protect) { case MSEL_DEFAULT: strcpy (val, STRING_DEFAULT); break; case MSEL_ON: strcpy (val, STRING_ON); break; case MSEL_OFF: strcpy (val, STRING_OFF); break; } return SANE_STATUS_GOOD; case OPT_ADV_PAPER_PROT: switch (s->adv_paper_prot) { case MSEL_DEFAULT: strcpy (val, STRING_DEFAULT); break; case MSEL_ON: strcpy (val, STRING_ON); break; case MSEL_OFF: strcpy (val, STRING_OFF); break; } return SANE_STATUS_GOOD; case OPT_STAPLE_DETECT: switch (s->staple_detect) { case MSEL_DEFAULT: strcpy (val, STRING_DEFAULT); break; case MSEL_ON: strcpy (val, STRING_ON); break; case MSEL_OFF: strcpy (val, STRING_OFF); break; } return SANE_STATUS_GOOD; case OPT_BG_COLOR: switch (s->bg_color) { case COLOR_DEFAULT: strcpy (val, STRING_DEFAULT); break; case COLOR_WHITE: strcpy (val, STRING_WHITE); break; case COLOR_BLACK: strcpy (val, STRING_BLACK); break; } return SANE_STATUS_GOOD; case OPT_DROPOUT_COLOR: switch (s->dropout_color) { case COLOR_DEFAULT: strcpy (val, STRING_DEFAULT); break; case COLOR_RED: strcpy (val, STRING_RED); break; case COLOR_GREEN: strcpy (val, STRING_GREEN); break; case COLOR_BLUE: strcpy (val, STRING_BLUE); break; } return SANE_STATUS_GOOD; case OPT_BUFF_MODE: switch (s->buff_mode) { case MSEL_DEFAULT: strcpy (val, STRING_DEFAULT); break; case MSEL_ON: strcpy (val, STRING_ON); break; case MSEL_OFF: strcpy (val, STRING_OFF); break; } return SANE_STATUS_GOOD; case OPT_PREPICK: switch (s->prepick) { case MSEL_DEFAULT: strcpy (val, STRING_DEFAULT); break; case MSEL_ON: strcpy (val, STRING_ON); break; case MSEL_OFF: strcpy (val, STRING_OFF); break; } return SANE_STATUS_GOOD; case OPT_OVERSCAN: switch (s->overscan) { case MSEL_DEFAULT: strcpy (val, STRING_DEFAULT); break; case MSEL_ON: strcpy (val, STRING_ON); break; case MSEL_OFF: strcpy (val, STRING_OFF); break; } return SANE_STATUS_GOOD; case OPT_SLEEP_TIME: *val_p = s->sleep_time; return SANE_STATUS_GOOD; case OPT_OFF_TIME: *val_p = s->off_time; return SANE_STATUS_GOOD; case OPT_DUPLEX_OFFSET: *val_p = s->duplex_offset; return SANE_STATUS_GOOD; case OPT_GREEN_OFFSET: *val_p = s->green_offset; return SANE_STATUS_GOOD; case OPT_BLUE_OFFSET: *val_p = s->blue_offset; return SANE_STATUS_GOOD; case OPT_LOW_MEM: *val_p = s->low_mem; return SANE_STATUS_GOOD; case OPT_SIDE: *val_p = s->side; return SANE_STATUS_GOOD; case OPT_HWDESKEWCROP: *val_p = s->hwdeskewcrop; return SANE_STATUS_GOOD; case OPT_SWDESKEW: *val_p = s->swdeskew; return SANE_STATUS_GOOD; case OPT_SWDESPECK: *val_p = s->swdespeck; return SANE_STATUS_GOOD; case OPT_SWCROP: *val_p = s->swcrop; return SANE_STATUS_GOOD; case OPT_SWSKIP: *val_p = SANE_FIX(s->swskip); return SANE_STATUS_GOOD; case OPT_HALT_ON_CANCEL: *val_p = s->halt_on_cancel; return SANE_STATUS_GOOD; /* Endorser Group */ case OPT_ENDORSER: *val_p = s->u_endorser; return SANE_STATUS_GOOD; case OPT_ENDORSER_BITS: *val_p = s->u_endorser_bits; return SANE_STATUS_GOOD; case OPT_ENDORSER_VAL: *val_p = s->u_endorser_val; return SANE_STATUS_GOOD; case OPT_ENDORSER_STEP: *val_p = s->u_endorser_step; return SANE_STATUS_GOOD; case OPT_ENDORSER_Y: *val_p = SCANNER_UNIT_TO_FIXED_MM(s->u_endorser_y); return SANE_STATUS_GOOD; case OPT_ENDORSER_FONT: switch (s->u_endorser_font) { case FONT_H: strcpy (val, STRING_HORIZONTAL); break; case FONT_HB: strcpy (val, STRING_HORIZONTALBOLD); break; case FONT_HN: strcpy (val, STRING_HORIZONTALNARROW); break; case FONT_V: strcpy (val, STRING_VERTICAL); break; case FONT_VB: strcpy (val, STRING_VERTICALBOLD); break; } return SANE_STATUS_GOOD; case OPT_ENDORSER_DIR: switch (s->u_endorser_dir) { case DIR_TTB: strcpy (val, STRING_TOPTOBOTTOM); break; case DIR_BTT: strcpy (val, STRING_BOTTOMTOTOP); break; } return SANE_STATUS_GOOD; case OPT_ENDORSER_SIDE: switch (s->u_endorser_side) { case ED_front: strcpy (val, STRING_FRONT); break; case ED_back: strcpy (val, STRING_BACK); break; } return SANE_STATUS_GOOD; case OPT_ENDORSER_STRING: strncpy( (SANE_String)val, (SANE_String)s->u_endorser_string, s->endorser_string_len+1 ); return SANE_STATUS_GOOD; /* Sensor Group */ case OPT_TOP: ret = get_hardware_status(s,option); *val_p = s->hw_top; return ret; case OPT_A3: ret = get_hardware_status(s,option); *val_p = s->hw_A3; return ret; case OPT_B4: ret = get_hardware_status(s,option); *val_p = s->hw_B4; return ret; case OPT_A4: ret = get_hardware_status(s,option); *val_p = s->hw_A4; return ret; case OPT_B5: ret = get_hardware_status(s,option); *val_p = s->hw_B5; return ret; case OPT_HOPPER: ret = get_hardware_status(s,option); *val_p = s->hw_hopper; return ret; case OPT_OMR: ret = get_hardware_status(s,option); *val_p = s->hw_omr; return ret; case OPT_ADF_OPEN: ret = get_hardware_status(s,option); *val_p = s->hw_adf_open; return ret; case OPT_SLEEP: ret = get_hardware_status(s,option); *val_p = s->hw_sleep; return ret; case OPT_SEND_SW: ret = get_hardware_status(s,option); *val_p = s->hw_send_sw; return ret; case OPT_MANUAL_FEED: ret = get_hardware_status(s,option); *val_p = s->hw_manual_feed; return ret; case OPT_SCAN_SW: ret = get_hardware_status(s,option); *val_p = s->hw_scan_sw; return ret; case OPT_FUNCTION: ret = get_hardware_status(s,option); *val_p = s->hw_function; return ret; case OPT_INK_EMPTY: ret = get_hardware_status(s,option); *val_p = s->hw_ink_empty; return ret; case OPT_DOUBLE_FEED: ret = get_hardware_status(s,option); *val_p = s->hw_double_feed; return ret; case OPT_ERROR_CODE: ret = get_hardware_status(s,option); *val_p = s->hw_error_code; return ret; case OPT_SKEW_ANGLE: ret = get_hardware_status(s,option); *val_p = s->hw_skew_angle; return ret; case OPT_INK_REMAIN: ret = get_hardware_status(s,option); *val_p = s->hw_ink_remain; return ret; case OPT_DENSITY_SW: ret = get_hardware_status(s,option); *val_p = s->hw_density_sw; return ret; case OPT_DUPLEX_SW: ret = get_hardware_status(s,option); *val_p = s->hw_duplex_sw; return ret; } } else if (action == SANE_ACTION_SET_VALUE) { int tmp; SANE_Word val_c; SANE_Status status; DBG (20, "sane_control_option: set value for '%s' (%d)\n", s->opt[option].name,option); if ( s->started ) { DBG (5, "sane_control_option: cant set, device busy\n"); return SANE_STATUS_DEVICE_BUSY; } if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) { DBG (5, "sane_control_option: not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (5, "sane_control_option: bad value\n"); return status; } /* may have been changed by constrain, so dont copy until now */ val_c = *(SANE_Word *)val; /* * Note - for those options which can assume one of a list of * valid values, we can safely assume that they will have * exactly one of those values because that's what * sanei_constrain_value does. Hence no "else: invalid" branches * below. */ switch (option) { /* Mode Group */ case OPT_SOURCE: if (!strcmp (val, STRING_ADFFRONT)) { tmp = SOURCE_ADF_FRONT; } else if (!strcmp (val, STRING_ADFBACK)) { tmp = SOURCE_ADF_BACK; } else if (!strcmp (val, STRING_ADFDUPLEX)) { tmp = SOURCE_ADF_DUPLEX; } else{ tmp = SOURCE_FLATBED; } if (s->source == tmp) return SANE_STATUS_GOOD; s->source = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_MODE: if (!strcmp (val, STRING_LINEART)) { tmp = MODE_LINEART; } else if (!strcmp (val, STRING_HALFTONE)) { tmp = MODE_HALFTONE; } else if (!strcmp (val, STRING_GRAYSCALE)) { tmp = MODE_GRAYSCALE; } else{ tmp = MODE_COLOR; } if (tmp == s->u_mode) return SANE_STATUS_GOOD; set_mode(s,tmp); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_RES: if (s->resolution_x == val_c) return SANE_STATUS_GOOD; s->resolution_x = val_c; s->resolution_y = val_c; set_max_y(s); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; /* Geometry Group */ case OPT_TL_X: if (s->tl_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->tl_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_TL_Y: if (s->tl_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->tl_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_BR_X: if (s->br_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_BR_Y: if (s->br_y == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; s->br_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_PAGE_WIDTH: if (s->page_width == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; /* if full width image, and paper size is changed, change the image size to match new paper */ if (s->tl_x == 0 && s->br_x == s->page_width){ DBG (20, "sane_control_option: br_x tracking page_width\n"); s->br_x = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS; } s->page_width = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_PAGE_HEIGHT: if (s->page_height == FIXED_MM_TO_SCANNER_UNIT(val_c)) return SANE_STATUS_GOOD; /* if full height image, and paper size is changed, change the image size to match new paper */ if (s->tl_y == 0 && s->br_y == s->page_height){ DBG (20, "sane_control_option: br_y tracking page_height\n"); s->br_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS; } s->page_height = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; /* Enhancement Group */ case OPT_BRIGHTNESS: s->brightness = val_c; return SANE_STATUS_GOOD; case OPT_CONTRAST: s->contrast = val_c; return SANE_STATUS_GOOD; case OPT_GAMMA: s->gamma = SANE_UNFIX(val_c); return SANE_STATUS_GOOD; case OPT_THRESHOLD: s->threshold = val_c; return SANE_STATUS_GOOD; /* IPC */ case OPT_RIF: s->rif = val_c; return SANE_STATUS_GOOD; case OPT_HT_TYPE: if (!strcmp(val, STRING_DEFAULT)) s->ht_type = WD_ht_type_DEFAULT; else if (!strcmp(val, STRING_DITHER)) s->ht_type = WD_ht_type_DITHER; else if (!strcmp(val, STRING_DIFFUSION)) s->ht_type = WD_ht_type_DIFFUSION; return SANE_STATUS_GOOD; case OPT_HT_PATTERN: s->ht_pattern = val_c; return SANE_STATUS_GOOD; case OPT_OUTLINE: s->outline = val_c; return SANE_STATUS_GOOD; case OPT_EMPHASIS: s->emphasis = val_c; return SANE_STATUS_GOOD; case OPT_SEPARATION: s->separation = val_c; return SANE_STATUS_GOOD; case OPT_MIRRORING: s->mirroring = val_c; return SANE_STATUS_GOOD; case OPT_WL_FOLLOW: if (!strcmp(val, STRING_DEFAULT)) s->wl_follow = WD_wl_follow_DEFAULT; else if (!strcmp(val, STRING_ON)) s->wl_follow = WD_wl_follow_ON; else if (!strcmp(val, STRING_OFF)) s->wl_follow = WD_wl_follow_OFF; return SANE_STATUS_GOOD; /* DTC params*/ case OPT_BP_FILTER: s->bp_filter = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_SMOOTHING: s->smoothing = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_GAMMA_CURVE: s->gamma_curve = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_THRESHOLD_CURVE: s->threshold_curve = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_THRESHOLD_WHITE: s->threshold_white = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_NOISE_REMOVAL: s->noise_removal = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_MATRIX_5: s->matrix_5 = val_c; return SANE_STATUS_GOOD; case OPT_MATRIX_4: s->matrix_4 = val_c; return SANE_STATUS_GOOD; case OPT_MATRIX_3: s->matrix_3 = val_c; return SANE_STATUS_GOOD; case OPT_MATRIX_2: s->matrix_2 = val_c; return SANE_STATUS_GOOD; /* SDTC params*/ case OPT_VARIANCE: s->variance = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; /* Advanced Group */ case OPT_AWD: s->awd = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_ALD: s->ald = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_COMPRESS: if (!strcmp (val, STRING_JPEG)) { tmp = COMP_JPEG; } else{ tmp = COMP_NONE; } if (tmp == s->compress) return SANE_STATUS_GOOD; s->compress = tmp; return SANE_STATUS_GOOD; case OPT_COMPRESS_ARG: s->compress_arg = val_c; return SANE_STATUS_GOOD; case OPT_DF_ACTION: if (!strcmp(val, STRING_DEFAULT)) s->df_action = DF_DEFAULT; else if (!strcmp(val, STRING_CONTINUE)) s->df_action = DF_CONTINUE; else if (!strcmp(val, STRING_STOP)) s->df_action = DF_STOP; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_DF_SKEW: s->df_skew = val_c; return SANE_STATUS_GOOD; case OPT_DF_THICKNESS: s->df_thickness = val_c; return SANE_STATUS_GOOD; case OPT_DF_LENGTH: s->df_length = val_c; return SANE_STATUS_GOOD; case OPT_DF_DIFF: if (!strcmp(val, STRING_DEFAULT)) s->df_diff = MSEL_df_diff_DEFAULT; else if (!strcmp(val, STRING_10MM)) s->df_diff = MSEL_df_diff_10MM; else if (!strcmp(val, STRING_15MM)) s->df_diff = MSEL_df_diff_15MM; else if (!strcmp(val, STRING_20MM)) s->df_diff = MSEL_df_diff_20MM; return SANE_STATUS_GOOD; case OPT_DF_RECOVERY: if (!strcmp(val, STRING_DEFAULT)) s->df_recovery = MSEL_DEFAULT; else if (!strcmp(val, STRING_ON)) s->df_recovery = MSEL_ON; else if (!strcmp(val, STRING_OFF)) s->df_recovery = MSEL_OFF; return SANE_STATUS_GOOD; case OPT_PAPER_PROTECT: if (!strcmp(val, STRING_DEFAULT)) s->paper_protect = MSEL_DEFAULT; else if (!strcmp(val, STRING_ON)) s->paper_protect = MSEL_ON; else if (!strcmp(val, STRING_OFF)) s->paper_protect = MSEL_OFF; return SANE_STATUS_GOOD; case OPT_ADV_PAPER_PROT: if (!strcmp(val, STRING_DEFAULT)) s->adv_paper_prot = MSEL_DEFAULT; else if (!strcmp(val, STRING_ON)) s->adv_paper_prot = MSEL_ON; else if (!strcmp(val, STRING_OFF)) s->adv_paper_prot = MSEL_OFF; return SANE_STATUS_GOOD; case OPT_STAPLE_DETECT: if (!strcmp(val, STRING_DEFAULT)) s->staple_detect = MSEL_DEFAULT; else if (!strcmp(val, STRING_ON)) s->staple_detect = MSEL_ON; else if (!strcmp(val, STRING_OFF)) s->staple_detect = MSEL_OFF; return SANE_STATUS_GOOD; case OPT_BG_COLOR: if (!strcmp(val, STRING_DEFAULT)) s->bg_color = COLOR_DEFAULT; else if (!strcmp(val, STRING_WHITE)) s->bg_color = COLOR_WHITE; else if (!strcmp(val, STRING_BLACK)) s->bg_color = COLOR_BLACK; return SANE_STATUS_GOOD; case OPT_DROPOUT_COLOR: if (!strcmp(val, STRING_DEFAULT)) s->dropout_color = COLOR_DEFAULT; else if (!strcmp(val, STRING_RED)) s->dropout_color = COLOR_RED; else if (!strcmp(val, STRING_GREEN)) s->dropout_color = COLOR_GREEN; else if (!strcmp(val, STRING_BLUE)) s->dropout_color = COLOR_BLUE; return SANE_STATUS_GOOD; case OPT_BUFF_MODE: if (!strcmp(val, STRING_DEFAULT)) s->buff_mode = MSEL_DEFAULT; else if (!strcmp(val, STRING_ON)) s->buff_mode= MSEL_ON; else if (!strcmp(val, STRING_OFF)) s->buff_mode= MSEL_OFF; return SANE_STATUS_GOOD; case OPT_PREPICK: if (!strcmp(val, STRING_DEFAULT)) s->prepick = MSEL_DEFAULT; else if (!strcmp(val, STRING_ON)) s->prepick = MSEL_ON; else if (!strcmp(val, STRING_OFF)) s->prepick = MSEL_OFF; return SANE_STATUS_GOOD; case OPT_OVERSCAN: if (!strcmp(val, STRING_DEFAULT)) s->overscan = MSEL_DEFAULT; else if (!strcmp(val, STRING_ON)) s->overscan = MSEL_ON; else if (!strcmp(val, STRING_OFF)) s->overscan = MSEL_OFF; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_SLEEP_TIME: s->sleep_time = val_c; return set_sleep_mode(s); case OPT_OFF_TIME: /* do our own constrain, because we want to round up */ s->off_time = (val_c + 14)/15*15; if(s->off_time != val_c){ *info |= SANE_INFO_INEXACT; } return set_off_mode(s); case OPT_DUPLEX_OFFSET: s->duplex_offset = val_c; return SANE_STATUS_GOOD; case OPT_GREEN_OFFSET: s->green_offset = val_c; return SANE_STATUS_GOOD; case OPT_BLUE_OFFSET: s->blue_offset = val_c; return SANE_STATUS_GOOD; case OPT_LOW_MEM: s->low_mem = val_c; return SANE_STATUS_GOOD; case OPT_HWDESKEWCROP: s->hwdeskewcrop = val_c; return SANE_STATUS_GOOD; case OPT_SWDESKEW: s->swdeskew = val_c; return SANE_STATUS_GOOD; case OPT_SWDESPECK: s->swdespeck = val_c; return SANE_STATUS_GOOD; case OPT_SWCROP: s->swcrop = val_c; return SANE_STATUS_GOOD; case OPT_SWSKIP: s->swskip = SANE_UNFIX(val_c); return SANE_STATUS_GOOD; case OPT_HALT_ON_CANCEL: s->halt_on_cancel = val_c; return SANE_STATUS_GOOD; /* Endorser Group */ case OPT_ENDORSER: s->u_endorser = val_c; *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_ENDORSER_BITS: s->u_endorser_bits = val_c; return SANE_STATUS_GOOD; /*this val not used in send_endorser*/ case OPT_ENDORSER_VAL: s->u_endorser_val = val_c; return SANE_STATUS_GOOD; case OPT_ENDORSER_STEP: s->u_endorser_step = val_c; return SANE_STATUS_GOOD; case OPT_ENDORSER_Y: s->u_endorser_y = FIXED_MM_TO_SCANNER_UNIT(val_c); return SANE_STATUS_GOOD; case OPT_ENDORSER_FONT: if (!strcmp (val, STRING_HORIZONTAL)){ s->u_endorser_font = FONT_H; } else if (!strcmp (val, STRING_HORIZONTALBOLD)){ s->u_endorser_font = FONT_HB; } else if (!strcmp (val, STRING_HORIZONTALNARROW)){ s->u_endorser_font = FONT_HN; } else if (!strcmp (val, STRING_VERTICAL)){ s->u_endorser_font = FONT_V; } else if (!strcmp (val, STRING_VERTICALBOLD)){ s->u_endorser_font = FONT_VB; } return SANE_STATUS_GOOD; case OPT_ENDORSER_DIR: if (!strcmp (val, STRING_TOPTOBOTTOM)){ s->u_endorser_dir = DIR_TTB; } else if (!strcmp (val, STRING_BOTTOMTOTOP)){ s->u_endorser_dir = DIR_BTT; } return SANE_STATUS_GOOD; /*this val not used in send_endorser*/ case OPT_ENDORSER_SIDE: if (!strcmp (val, STRING_FRONT)){ s->u_endorser_side = ED_front; } else if (!strcmp (val, STRING_BACK)){ s->u_endorser_side = ED_back; } return SANE_STATUS_GOOD; case OPT_ENDORSER_STRING: strncpy( (SANE_String)s->u_endorser_string, (SANE_String)val, s->endorser_string_len+1 ); return SANE_STATUS_GOOD; } /* switch */ } /* else */ return SANE_STATUS_INVAL; } static SANE_Status set_sleep_mode(struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[MODE_SELECT_len]; size_t cmdLen = MODE_SELECT_len; unsigned char out[MSEL_header_len + MSEL_data_min_len]; size_t outLen = MSEL_header_len + MSEL_data_min_len; unsigned char * page = out+MSEL_header_len; DBG (10, "set_sleep_mode: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SELECT_code); set_MSEL_pf(cmd, 1); set_MSEL_xferlen(cmd, outLen); memset(out,0,outLen); set_MSEL_pc(page, MS_pc_sleep); set_MSEL_page_len(page, MSEL_data_min_len-2); set_MSEL_sleep_mode(page, s->sleep_time); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "set_sleep_mode: finish\n"); return ret; } static SANE_Status set_off_mode(struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[SEND_DIAGNOSTIC_len]; /*also big enough for READ_DIAG*/ size_t cmdLen = SEND_DIAGNOSTIC_len; unsigned char out[SD_powoff_len]; size_t outLen = SD_powoff_len; DBG (10, "set_off_mode: start\n"); if (!s->has_cmd_sdiag || !s->has_cmd_rdiag || !s->has_off_mode){ DBG (5, "set_off_mode: not supported, returning\n"); return ret; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SEND_DIAGNOSTIC_code); set_SD_slftst(cmd, 0); set_SD_xferlen(cmd, outLen); memcpy(out,SD_powoff_string,SD_powoff_stringlen); set_SD_powoff_disable(out,!s->off_time); set_SD_powoff_interval(out,s->off_time/15); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); if (ret != SANE_STATUS_GOOD){ DBG (5, "set_off_mode: send diag error: %d\n", ret); return ret; } DBG (10, "set_off_mode: finish\n"); return SANE_STATUS_GOOD; } static SANE_Status get_hardware_status (struct fujitsu *s, SANE_Int option) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "get_hardware_status: start\n"); /* only run this if frontend has already read the last time we got it */ /* or if we don't care for such bookkeeping (private use) */ if (!option || s->hw_read[option-OPT_TOP]) { DBG (15, "get_hardware_status: running\n"); /* mark all values as unread */ memset(s->hw_read,0,sizeof(s->hw_read)); if (s->has_cmd_hw_status){ unsigned char cmd[GET_HW_STATUS_len]; size_t cmdLen = GET_HW_STATUS_len; unsigned char in[GHS_data_len]; size_t inLen = GHS_data_len; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, GET_HW_STATUS_code); set_GHS_allocation_length(cmd, inLen); DBG (15, "get_hardware_status: calling ghs\n"); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { s->hw_top = get_GHS_top(in); s->hw_A3 = get_GHS_A3(in); s->hw_B4 = get_GHS_B4(in); s->hw_A4 = get_GHS_A4(in); s->hw_B5 = get_GHS_B5(in); s->hw_hopper = get_GHS_hopper(in); s->hw_omr = get_GHS_omr(in); s->hw_adf_open = get_GHS_adf_open(in); s->hw_sleep = get_GHS_sleep(in); s->hw_send_sw = get_GHS_send_sw(in); s->hw_manual_feed = get_GHS_manual_feed(in); s->hw_scan_sw = get_GHS_scan_sw(in); s->hw_function = get_GHS_function(in); s->hw_ink_empty = get_GHS_ink_empty(in); s->hw_double_feed = get_GHS_double_feed(in); s->hw_error_code = get_GHS_error_code(in); s->hw_skew_angle = get_GHS_skew_angle(in); if(inLen > 9){ s->hw_ink_remain = get_GHS_ink_remain(in); } ret = SANE_STATUS_GOOD; } } /* 3091/2 put hardware status in RS data */ else if (s->ghs_in_rs){ unsigned char cmd[REQUEST_SENSE_len]; size_t cmdLen = REQUEST_SENSE_len; unsigned char in[RS_return_size]; size_t inLen = RS_return_size; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, REQUEST_SENSE_code); set_RS_return_size(cmd, inLen); DBG(15,"get_hardware_status: calling rs\n"); ret = do_cmd( s,0,0, cmd, cmdLen, NULL,0, in, &inLen ); /* parse the rs data */ if(ret == SANE_STATUS_GOOD){ if(get_RS_sense_key(in)==0 && get_RS_ASC(in)==0x80){ s->hw_adf_open = get_RS_adf_open(in); s->hw_send_sw = get_RS_send_sw(in); s->hw_scan_sw = get_RS_scan_sw(in); s->hw_duplex_sw = get_RS_duplex_sw(in); s->hw_top = get_RS_top(in); s->hw_hopper = get_RS_hopper(in); s->hw_function = get_RS_function(in); s->hw_density_sw = get_RS_density(in); } else{ DBG (10, "get_hardware_status: unexpected RS values\n"); } } } } if(option) s->hw_read[option-OPT_TOP] = 1; DBG (10, "get_hardware_status: finish\n"); return ret; } static SANE_Status send_endorser(struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[SEND_len]; size_t cmdLen = SEND_len; size_t strLen = strlen(s->u_endorser_string); unsigned char out[S_e_data_max_len]; /*we probably send less below*/ size_t outLen = S_e_data_min_len + strLen; /*fi-5900 might want 1 more byte?*/ DBG (10, "send_endorser: start\n"); if (!s->has_endorser_f && !s->has_endorser_b){ DBG (10, "send_endorser: unsupported\n"); return ret; } /*build the payload*/ memset(out,0,outLen); /*fi-5900 front side uses 0x80, assume all others*/ if(s->u_endorser_side == ED_front){ set_S_endorser_data_id(out,0x80); } else{ set_S_endorser_data_id(out,0); } set_S_endorser_stamp(out,0); set_S_endorser_elec(out,0); if(s->u_endorser_step < 0){ set_S_endorser_decr(out,S_e_decr_dec); } else{ set_S_endorser_decr(out,S_e_decr_inc); } if(s->u_endorser_bits == 24){ set_S_endorser_lap24(out,S_e_lap_24bit); } else{ set_S_endorser_lap24(out,S_e_lap_16bit); } set_S_endorser_ctstep(out,abs(s->u_endorser_step)); set_S_endorser_ulx(out,0); set_S_endorser_uly(out,s->u_endorser_y); switch (s->u_endorser_font) { case FONT_H: set_S_endorser_font(out,S_e_font_horiz); set_S_endorser_bold(out,0); break; case FONT_HB: set_S_endorser_font(out,S_e_font_horiz); set_S_endorser_bold(out,1); break; case FONT_HN: set_S_endorser_font(out,S_e_font_horiz_narrow); set_S_endorser_bold(out,0); break; case FONT_V: set_S_endorser_font(out,S_e_font_vert); set_S_endorser_bold(out,0); break; case FONT_VB: set_S_endorser_font(out,S_e_font_vert); set_S_endorser_bold(out,1); break; } set_S_endorser_size(out,0); set_S_endorser_revs(out,0); if(s->u_endorser_dir == DIR_BTT){ set_S_endorser_dirs(out,S_e_dir_bottom_top); } else{ set_S_endorser_dirs(out,S_e_dir_top_bottom); } set_S_endorser_string_length(out, strLen); set_S_endorser_string(out, s->u_endorser_string, strLen); /*build the command*/ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SEND_code); set_S_xfer_datatype (cmd, S_datatype_endorser_data); set_S_xfer_length (cmd, outLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "send_endorser: finish %d\n", ret); return ret; } /* instead of internal brightness/contrast/gamma most scanners use a 256x256 or 1024x256 LUT default is linear table of slope 1 or 1/4 resp. brightness and contrast inputs are -127 to +127 contrast rotates slope of line around central input val high low . x . . x . xx out . x . xxxxxxxx . x xx ....x....... ............ in in then brightness moves line vertically, and clamps to 8bit bright dark . xxxxxxxx . . x . out x . x . . x ............ xxxxxxxx.... in in */ static SANE_Status send_lut (struct fujitsu *s) { int i, j, bytes = 1 << s->adbits; double b, slope, offset; SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[SEND_len]; size_t cmdLen = SEND_len; unsigned char out[S_lut_header_len + S_lut_data_max_len]; size_t outLen = S_lut_header_len + S_lut_data_max_len; unsigned char * p = out + S_lut_header_len; DBG (10, "send_lut: start\n"); if(!s->num_download_gamma || !s->adbits){ DBG (10, "send_lut: unsupported\n"); return ret; } /* contrast is converted to a slope [0,90] degrees: * first [-127,127] to [0,254] then to [0,1] * then multiply by PI/2 to convert to radians * then take the tangent to get slope (T.O.A) * then multiply by the normal linear slope * because the table may not be square, i.e. 1024x256*/ slope = tan(((double)s->contrast+127)/254 * M_PI/2) * 256/bytes; /* contrast slope must stay centered, so figure * out vertical offset at central input value */ offset = 127.5-(slope*bytes/2); /* convert the user brightness setting (-127 to +127) * into a scale that covers the range required * to slide the contrast curve entirely off the table */ b = ((double)s->brightness/127) * (256 - offset); DBG (15, "send_lut: %d %f %d %f %f\n", s->brightness, b, s->contrast, slope, offset); outLen = S_lut_header_len + bytes; memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SEND_code); set_S_xfer_datatype (cmd, S_datatype_lut_data); set_S_xfer_length (cmd, outLen); memset(out,0,outLen); set_S_lut_order (out, S_lut_order_single); set_S_lut_ssize (out, bytes); set_S_lut_dsize (out, 256); for(i=0;i255){ j=255; } *p=j; p++; } ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "send_lut: finish\n"); return ret; } static SANE_Status send_q_table (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[SEND_len]; size_t cmdLen = SEND_len; unsigned char out[S_q_table_header_len + S_q_table_y_len + S_q_table_uv_len]; size_t outLen = S_q_table_header_len + S_q_table_y_len + S_q_table_uv_len; unsigned char * yp = out + S_q_table_header_len; unsigned char * uvp = out + S_q_table_header_len + S_q_table_y_len; /* FIXME: generate these instead of hardcode */ unsigned char ydata[] = { 0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04, 0x03, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0c, 0x07, 0x07, 0x06, 0x06, 0x07, 0x0e, 0x0a, 0x0b, 0x08, 0x0c, 0x11, 0x0f, 0x12, 0x12, 0x11, 0x0f, 0x10, 0x10, 0x13, 0x15, 0x1b, 0x17, 0x13, 0x14, 0x1a, 0x14, 0x10, 0x10, 0x18, 0x20, 0x18, 0x1a, 0x1c, 0x1d, 0x1e, 0x1f, 0x1e, 0x12, 0x17, 0x21, 0x24, 0x21, 0x1e, 0x24, 0x1b, 0x1e, 0x1e, 0x1d }; unsigned char uvdata[] = { 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0e, 0x07, 0x07, 0x0e, 0x1d, 0x13, 0x10, 0x13, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d }; DBG (10, "send_q_table: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SEND_code); set_S_xfer_datatype (cmd, S_datatype_jpg_q_table); set_S_xfer_length (cmd, outLen); memset(out,0,outLen); set_S_q_table_y_len (out, S_q_table_y_len); set_S_q_table_uv_len (out, S_q_table_uv_len); memcpy (yp, ydata, S_q_table_y_len); memcpy (uvp, uvdata, S_q_table_uv_len); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "send_q_table: finish\n"); return ret; } /* only used by iX500? */ #if 0 static SANE_Status mode_select_unk (struct fujitsu *s, int foo) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[MODE_SELECT_len]; size_t cmdLen = MODE_SELECT_len; unsigned char out[MSEL_header_len + MSEL_data_min_len]; size_t outLen = MSEL_header_len + MSEL_data_min_len; unsigned char * page = out+MSEL_header_len; DBG (10, "mode_select_unk: start\n"); /*if (!s->has_MS_unk){ DBG (10, "mode_select_unk: unsupported\n"); return SANE_STATUS_GOOD; }*/ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SELECT_code); set_MSEL_pf(cmd, 1); set_MSEL_xferlen(cmd, outLen); memset(out,0,outLen); set_MSEL_pc(page, MS_pc_unk); set_MSEL_page_len(page, MSEL_data_min_len-2); *(page + 0x02) = foo; ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "mode_select_unk: finish\n"); return ret; } #endif /* only used by iX500? */ static SANE_Status diag_preread (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[SEND_DIAGNOSTIC_len]; /*also big enough for READ_DIAG*/ size_t cmdLen = SEND_DIAGNOSTIC_len; unsigned char out[SD_preread_len]; size_t outLen = SD_preread_len; DBG (10, "diag_preread: start\n"); if (!s->has_cmd_sdiag || !s->has_cmd_rdiag || !s->need_diag_preread){ DBG (5, "diag_preread: not supported, returning\n"); return ret; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SEND_DIAGNOSTIC_code); set_SD_slftst(cmd, 0); set_SD_xferlen(cmd, outLen); memcpy(out,SD_preread_string,SD_preread_stringlen); set_SD_preread_xres(out,s->resolution_x); set_SD_preread_yres(out,s->resolution_y); /* call helper function, scanner wants lies about paper width */ set_SD_preread_paper_width(out, get_page_width(s)); /* dont call helper function, scanner wants actual length? */ set_SD_preread_paper_length(out, s->page_height); set_SD_preread_composition(out, s->s_mode); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); if (ret != SANE_STATUS_GOOD){ DBG (5, "diag_preread: send diag error: %d\n", ret); return ret; } DBG (10, "diag_preread: finish\n"); return SANE_STATUS_GOOD; } static SANE_Status mode_select_df (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[MODE_SELECT_len]; size_t cmdLen = MODE_SELECT_len; unsigned char out[MSEL_header_len + MSEL_data_min_len]; size_t outLen = MSEL_header_len + MSEL_data_min_len; unsigned char * page = out+MSEL_header_len; DBG (10, "mode_select_df: start\n"); if(!s->has_MS_df){ DBG (10, "mode_select_df: unsupported\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SELECT_code); set_MSEL_pf(cmd, 1); set_MSEL_xferlen(cmd, outLen); memset(out,0,outLen); set_MSEL_pc(page, MS_pc_df); set_MSEL_page_len(page, MSEL_data_min_len-2); /* continue/stop */ if(s->df_action != DF_DEFAULT){ set_MSEL_df_enable (page, 1); /* continue */ if(s->df_action == DF_CONTINUE){ set_MSEL_df_continue (page, 1); } /* skew */ if(s->df_skew){ set_MSEL_df_skew (page, 1); } /* thickness */ if(s->df_thickness){ set_MSEL_df_thickness (page, 1); } /* length */ if(s->df_length){ set_MSEL_df_length (page, 1); set_MSEL_df_diff (page, s->df_diff); } } set_MSEL_df_paperprot(page,s->paper_protect); set_MSEL_df_stapledet(page,s->staple_detect); set_MSEL_df_recovery(page,s->df_recovery); set_MSEL_df_paperprot2(page,s->adv_paper_prot); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "mode_select_df: finish\n"); return ret; } static SANE_Status mode_select_bg (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[MODE_SELECT_len]; size_t cmdLen = MODE_SELECT_len; unsigned char out[MSEL_header_len + MSEL_data_min_len]; size_t outLen = MSEL_header_len + MSEL_data_min_len; unsigned char * page = out+MSEL_header_len; DBG (10, "mode_select_bg: start\n"); if(!s->has_MS_bg){ DBG (10, "mode_select_bg: unsupported\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SELECT_code); set_MSEL_pf(cmd, 1); set_MSEL_xferlen(cmd, outLen); memset(out,0,outLen); set_MSEL_pc(page, MS_pc_bg); set_MSEL_page_len(page, MSEL_data_min_len-2); if(s->bg_color != COLOR_DEFAULT){ set_MSEL_bg_enable (page, 1); if(s->bg_color == COLOR_BLACK){ set_MSEL_bg_front (page, 1); set_MSEL_bg_back (page, 1); set_MSEL_bg_fb (page, 1); } } ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "mode_select_bg: finish\n"); return ret; } static SANE_Status mode_select_dropout (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[MODE_SELECT_len]; size_t cmdLen = MODE_SELECT_len; unsigned char out[MSEL_header_len + MSEL_data_max_len]; size_t outLen = MSEL_header_len + MSEL_data_max_len; unsigned char * page = out+MSEL_header_len; DBG (10, "mode_select_dropout: start\n"); if(!s->has_MS_dropout){ DBG (10, "mode_select_dropout: unsupported\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SELECT_code); set_MSEL_pf(cmd, 1); set_MSEL_xferlen(cmd, outLen); memset(out,0,outLen); set_MSEL_pc(page, MS_pc_dropout); set_MSEL_page_len(page, MSEL_data_max_len-2); set_MSEL_dropout_front (page, s->dropout_color); set_MSEL_dropout_back (page, s->dropout_color); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "mode_select_dropout: finish\n"); return ret; } static SANE_Status mode_select_buff (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[MODE_SELECT_len]; size_t cmdLen = MODE_SELECT_len; unsigned char out[MSEL_header_len + MSEL_data_min_len]; size_t outLen = MSEL_header_len + MSEL_data_min_len; unsigned char * page = out+MSEL_header_len; DBG (10, "mode_select_buff: start\n"); if (!s->has_MS_buff){ DBG (10, "mode_select_buff: unsupported\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SELECT_code); set_MSEL_pf(cmd, 1); set_MSEL_xferlen(cmd, outLen); memset(out,0,outLen); set_MSEL_pc(page, MS_pc_buff); set_MSEL_page_len(page, MSEL_data_min_len-2); set_MSEL_buff_mode(page, s->buff_mode); set_MSEL_buff_clear(page, 3); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "mode_select_buff: finish\n"); return ret; } static SANE_Status mode_select_prepick (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[MODE_SELECT_len]; size_t cmdLen = MODE_SELECT_len; unsigned char out[MSEL_header_len + MSEL_data_min_len]; size_t outLen = MSEL_header_len + MSEL_data_min_len; unsigned char * page = out+MSEL_header_len; DBG (10, "mode_select_prepick: start\n"); if (!s->has_MS_prepick){ DBG (10, "mode_select_prepick: unsupported\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SELECT_code); set_MSEL_pf(cmd, 1); set_MSEL_xferlen(cmd, outLen); memset(out,0,outLen); set_MSEL_pc(page, MS_pc_prepick); set_MSEL_page_len(page, MSEL_data_min_len-2); set_MSEL_prepick(page, s->prepick); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "mode_select_prepick: finish\n"); return ret; } static SANE_Status mode_select_auto (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[MODE_SELECT_len]; size_t cmdLen = MODE_SELECT_len; unsigned char out[MSEL_header_len + MSEL_data_min_len]; size_t outLen = MSEL_header_len + MSEL_data_min_len; unsigned char * page = out+MSEL_header_len; DBG (10, "mode_select_auto: start\n"); if(!s->has_MS_auto){ DBG (10, "mode_select_auto: unsupported\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, MODE_SELECT_code); set_MSEL_pf(cmd, 1); set_MSEL_xferlen(cmd, outLen); memset(out,0,outLen); set_MSEL_pc(page, MS_pc_auto); set_MSEL_page_len(page, MSEL_data_min_len-2); set_MSEL_overscan(page, s->overscan); set_MSEL_ald(page, s->ald || s->hwdeskewcrop); set_MSEL_awd(page, s->awd || s->hwdeskewcrop); set_MSEL_req_driv_crop(page, s->hwdeskewcrop && (s->swcrop || s->swdeskew)); set_MSEL_deskew(page, s->hwdeskewcrop); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "mode_select_auto: finish\n"); return ret; } /* * @@ Section 4 - SANE scanning functions */ /* * Called by SANE to retrieve information about the type of data * that the current scan will return. * * From the SANE spec: * This function is used to obtain the current scan parameters. The * returned parameters are guaranteed to be accurate between the time * a scan has been started (sane_start() has been called) and the * completion of that request. Outside of that window, the returned * values are best-effort estimates of what the parameters will be * when sane_start() gets invoked. * * Calling this function before a scan has actually started allows, * for example, to get an estimate of how big the scanned image will * be. The parameters passed to this function are the handle h of the * device for which the parameters should be obtained and a pointer p * to a parameter structure. */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { SANE_Status ret = SANE_STATUS_GOOD; struct fujitsu *s = (struct fujitsu *) handle; DBG (10, "sane_get_parameters: start\n"); /* not started? update param data from user settings */ if(!s->started){ ret = update_params(s); if(ret) return ret; } params->format = s->u_params.format; params->last_frame = s->u_params.last_frame; params->lines = s->u_params.lines; params->depth = s->u_params.depth; params->pixels_per_line = s->u_params.pixels_per_line; params->bytes_per_line = s->u_params.bytes_per_line; /* we wont know the end until we get to it */ if(s->ald && !must_fully_buffer(s)){ DBG (15, "sane_get_parameters: hand-scanner mode\n"); params->lines = -1; } DBG (10, "sane_get_parameters: finish\n"); return ret; } /* set s_params and u_params data based on user settings * and scanner capabilities. */ SANE_Status update_params (struct fujitsu * s) { SANE_Status ret = SANE_STATUS_GOOD; SANE_Parameters * params = &(s->s_params); DBG (10, "update_params: start\n"); /* first, we setup s_params to describe the image to the scanner */ /* this backend only sends single frame images */ params->last_frame = 1; /* initial ppl from user settings */ params->pixels_per_line = s->resolution_x * (s->br_x - s->tl_x) / 1200; /* some scanners require even number of bytes in each transfer block, * so we round to even # of total lines, to ensure last block is even */ params->lines = s->resolution_y * (s->br_y - s->tl_y) / 1200; params->lines -= params->lines % 2; if (s->s_mode == MODE_COLOR) { params->depth = 8; /* jpeg requires 8x8 squares */ if(s->compress == COMP_JPEG){ params->format = SANE_FRAME_JPEG; params->pixels_per_line -= params->pixels_per_line % 8; params->lines -= params->lines % 8; } else{ params->format = SANE_FRAME_RGB; params->pixels_per_line -= params->pixels_per_line % max(s->ppl_mod_by_mode[s->s_mode], s->ppl_mod_by_mode[s->u_mode]); } params->bytes_per_line = params->pixels_per_line * 3; } else if (s->s_mode == MODE_GRAYSCALE) { params->depth = 8; /* jpeg requires 8x8 squares */ if(s->compress == COMP_JPEG){ params->format = SANE_FRAME_JPEG; params->pixels_per_line -= params->pixels_per_line % 8; params->lines -= params->lines % 8; } else{ params->format = SANE_FRAME_GRAY; params->pixels_per_line -= params->pixels_per_line % max(s->ppl_mod_by_mode[s->s_mode], s->ppl_mod_by_mode[s->u_mode]); } params->bytes_per_line = params->pixels_per_line; } else { params->depth = 1; params->format = SANE_FRAME_GRAY; params->pixels_per_line -= params->pixels_per_line % max(s->ppl_mod_by_mode[s->s_mode], s->ppl_mod_by_mode[s->u_mode]); params->bytes_per_line = params->pixels_per_line / 8; } DBG(15,"update_params: x: max=%d, page=%d, gpw=%d, res=%d\n", s->max_x, s->page_width, get_page_width(s), s->resolution_x); DBG(15,"update_params: y: max=%d, page=%d, gph=%d, res=%d\n", s->max_y, s->page_height, get_page_height(s), s->resolution_y); DBG(15,"update_params: area: tlx=%d, brx=%d, tly=%d, bry=%d\n", s->tl_x, s->br_x, s->tl_y, s->br_y); DBG(15,"update_params: params: ppl=%d, Bpl=%d, lines=%d\n", params->pixels_per_line, params->bytes_per_line, params->lines); DBG(15,"update_params: params: format=%d, depth=%d, last=%d\n", params->format, params->depth, params->last_frame); /* second, we setup u_params to describe the image to the user */ /* use a helper function cause it is called elsewhere */ ret = update_u_params(s); DBG (10, "update_params: finish\n"); return ret; } /* set u_param data based on user settings, and s_params */ SANE_Status update_u_params (struct fujitsu * s) { SANE_Status ret = SANE_STATUS_GOOD; SANE_Parameters * params = &(s->u_params); DBG (10, "update_u_params: start\n"); /* for most machines, it is the same, so we just copy */ memcpy(&(s->u_params), &(s->s_params), sizeof(SANE_Parameters)); /* some scanners don't support the user's mode, so params differ */ /* but not in jpeg mode. we don't support that. */ if(must_downsample(s)){ /* making gray from a color scan */ if (s->u_mode == MODE_GRAYSCALE) { params->format = SANE_FRAME_GRAY; params->bytes_per_line = params->pixels_per_line; } /* making binary from a gray or color scan */ else if (s->u_mode == MODE_LINEART) { params->depth = 1; params->format = SANE_FRAME_GRAY; params->bytes_per_line = params->pixels_per_line / 8; } DBG(15,"update_u_params: x: max=%d, page=%d, gpw=%d, res=%d\n", s->max_x, s->page_width, get_page_width(s), s->resolution_x); DBG(15,"update_u_params: y: max=%d, page=%d, gph=%d, res=%d\n", s->max_y, s->page_height, get_page_height(s), s->resolution_y); DBG(15,"update_u_params: area: tlx=%d, brx=%d, tly=%d, bry=%d\n", s->tl_x, s->br_x, s->tl_y, s->br_y); DBG(15,"update_u_params: params: ppl=%d, Bpl=%d, lines=%d\n", params->pixels_per_line, params->bytes_per_line, params->lines); DBG(15,"update_u_params: params: format=%d, depth=%d, last=%d\n", params->format, params->depth, params->last_frame); } DBG (10, "update_u_params: finish\n"); return ret; } /* * Called by SANE when a page acquisition operation is to be started. * commands: scanner control (lampon), send (lut), send (dither), * set window, object pos, and scan * * this will be called between sides of a duplex scan, * and at the start of each page of an adf batch. * hence, we spend alot of time playing with s->started, etc. */ SANE_Status sane_start (SANE_Handle handle) { struct fujitsu *s = handle; SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "sane_start: start\n"); DBG (15, "started=%d, side=%d, source=%d\n", s->started, s->side, s->source); /* undo any prior sane_cancel calls */ s->cancelled=0; /* protect this block from sane_cancel */ s->reading=1; /* not finished with current side, error */ if (s->started && !s->eof_tx[s->side]) { DBG(5,"sane_start: previous transfer not finished?"); ret = SANE_STATUS_INVAL; goto errors; } /* low mem mode messes up the side marker, reset it */ if(s->source == SOURCE_ADF_DUPLEX && s->low_mem && s->eof_tx[SIDE_FRONT] && s->eof_tx[SIDE_BACK] ){ s->side = SIDE_BACK; } /* batch start? initialize struct and scanner */ if(!s->started){ /* load side marker */ if(s->source == SOURCE_ADF_BACK){ s->side = SIDE_BACK; } else{ s->side = SIDE_FRONT; } /* load our own private copy of scan params */ ret = update_params(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot update params\n"); goto errors; } /* switch source */ if(s->source == SOURCE_FLATBED){ ret = scanner_control(s, SC_function_fb); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot control fb, ignoring\n"); } } else{ ret = scanner_control(s, SC_function_adf); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot control adf, ignoring\n"); } } /* required for hi res scans on iX500? */ ret = diag_preread(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot diag_preread %d\n", ret); /* enable overscan/auto detection */ ret = mode_select_auto(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot mode_select_auto %d\n", ret); /* enable double feed detection */ ret = mode_select_df(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot mode_select_df %d\n", ret); /* enable background color setting */ ret = mode_select_bg(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot mode_select_bg %d\n", ret); /* enable dropout color setting */ ret = mode_select_dropout(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot mode_select_dropout %d\n", ret); /* enable buffering setting */ ret = mode_select_buff(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot mode_select_buff %d\n", ret); /* enable prepick setting */ ret = mode_select_prepick(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot mode_select_prepick %d\n", ret); /* send endorser config */ ret = send_endorser(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot send_endorser %d\n", ret); /* send lut if scanner has no hardware brightness/contrast, * or we are going to ask it to use a downloaded gamma table */ if (!s->late_lut && (!s->brightness_steps || !s->contrast_steps || s->window_gamma & 0x80)){ ret = send_lut(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot early send_lut %d\n", ret); } /* set window command */ ret = set_window(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot set window\n"); goto errors; } /* send lut if scanner has no hardware brightness/contrast, * or we are going to ask it to use a downloaded gamma table */ if (s->late_lut && (!s->brightness_steps || !s->contrast_steps || s->window_gamma & 0x80)){ ret = send_lut(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot late send_lut %d\n", ret); } /* some scanners need the q table sent, even when not scanning jpeg */ if (s->need_q_table){ ret = send_q_table(s); if (ret != SANE_STATUS_GOOD) DBG (5, "sane_start: WARNING: cannot send_q_table %d\n", ret); } /* start/stop endorser */ ret = endorser(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot start/stop endorser\n"); goto errors; } /* turn lamp on */ ret = scanner_control(s, SC_function_lamp_on); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: WARNING: cannot start lamp, ignoring\n"); } /* iX500 errors if op is called with no paper * at the beginning of a batch, so we check */ if(s->hopper_before_op && s->source != SOURCE_FLATBED){ ret = get_hardware_status(s,0); if(!s->hw_hopper){ ret = SANE_STATUS_NO_DOCS; DBG (5, "sane_start: ERROR: hopper empty\n"); goto errors; } } } /* if already running, duplex needs to switch sides */ else if(s->source == SOURCE_ADF_DUPLEX){ s->side = !s->side; } /* set clean defaults with new sheet of paper */ /* dont reset the transfer vars on backside of duplex page */ /* otherwise buffered back page will be lost */ /* ingest paper with adf (no-op for fb) */ /* dont call object pos or scan on back side of duplex scan */ if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK){ s->bytes_rx[0]=0; s->bytes_rx[1]=0; s->lines_rx[0]=0; s->lines_rx[1]=0; s->eof_rx[0]=0; s->eof_rx[1]=0; s->ili_rx[0]=0; s->ili_rx[1]=0; s->eom_rx=0; s->bytes_tx[0]=0; s->bytes_tx[1]=0; s->eof_tx[0]=0; s->eof_tx[1]=0; s->buff_rx[0]=0; s->buff_rx[1]=0; s->buff_tx[0]=0; s->buff_tx[1]=0; /* reset jpeg just in case... */ s->jpeg_stage = JPEG_STAGE_NONE; s->jpeg_ff_offset = -1; s->jpeg_front_rst = 0; s->jpeg_back_rst = 0; ret = object_position (s, OP_Feed); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot load page\n"); goto errors; } ret = start_scan (s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot start_scan\n"); goto errors; } /* try to read scan size from scanner */ ret = get_pixelsize(s,0); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot get pixelsize\n"); goto errors; } /* store the number of front bytes */ if ( s->source != SOURCE_ADF_BACK ){ s->bytes_tot[SIDE_FRONT] = s->s_params.bytes_per_line * s->s_params.lines; s->buff_tot[SIDE_FRONT] = s->buffer_size; /* the front buffer is normally very small, but some scanners or * option combinations can't handle it, so we make a big one */ if( (s->s_mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091) || must_fully_buffer(s) ){ s->buff_tot[SIDE_FRONT] = s->bytes_tot[SIDE_FRONT]; } } else{ s->bytes_tot[SIDE_FRONT] = 0; s->buff_tot[SIDE_FRONT] = 0; } /* store the number of back bytes */ if ( s->source == SOURCE_ADF_DUPLEX || s->source == SOURCE_ADF_BACK ){ s->bytes_tot[SIDE_BACK] = s->s_params.bytes_per_line * s->s_params.lines; s->buff_tot[SIDE_BACK] = s->bytes_tot[SIDE_BACK]; /* the back buffer is normally very large, but some scanners or * option combinations dont need it, so we make a small one */ if(s->low_mem || s->source == SOURCE_ADF_BACK || s->duplex_interlace == DUPLEX_INTERLACE_NONE) s->buff_tot[SIDE_BACK] = s->buffer_size; } else{ s->bytes_tot[SIDE_BACK] = 0; s->buff_tot[SIDE_BACK] = 0; } /* first page of batch */ /* make large buffer to hold the images */ /* and set started flag */ if(!s->started){ ret = setup_buffers(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot load buffers\n"); goto errors; } s->started=1; } } else{ /* try to read scan size from scanner */ ret = get_pixelsize(s,0); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot get pixelsize\n"); goto errors; } } DBG (15, "started=%d, side=%d, source=%d\n", s->started, s->side, s->source); /* certain options require the entire image to * be collected from the scanner before we can * tell the user the size of the image. the sane * API has no way to inform the frontend of this, * so we block and buffer. yuck */ if( must_fully_buffer(s) ){ /* get image */ while(!s->eof_rx[s->side] && !ret){ SANE_Int len = 0; ret = sane_read((SANE_Handle)s, NULL, 0, &len); } /* check for errors */ if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot buffer image\n"); goto errors; } DBG (5, "sane_start: OK: done buffering\n"); /* hardware deskew will tell image size after transfer */ ret = get_pixelsize(s,1); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot get final pixelsize\n"); goto errors; } /* finished buffering, adjust image as required */ if(s->swdeskew && (!s->hwdeskewcrop || s->req_driv_crop)){ buffer_deskew(s,s->side); } if(s->swcrop && (!s->hwdeskewcrop || s->req_driv_crop)){ buffer_crop(s,s->side); } if(s->swdespeck){ buffer_despeck(s,s->side); } if(s->swskip){ /* Skipping means throwing out this image. * Pretend the user read the whole thing * and call sane_start again. * This assumes we are running in batch mode. */ if(buffer_isblank(s,s->side)){ s->bytes_tx[s->side] = s->bytes_rx[s->side]; s->eof_tx[s->side] = 1; return sane_start(handle); } } } /* check if user cancelled during this start */ ret = check_for_cancel(s); /* unprotect this block from sane_cancel */ s->reading=0; DBG (10, "sane_start: finish %d\n", ret); return ret; errors: DBG (10, "sane_start: error %d\n", ret); /* if we are started, but something went wrong, * chances are there is image data inside scanner, * which should be discarded via cancel command */ if(s->started){ s->cancelled = 1; check_for_cancel(s); } s->started = 0; s->cancelled = 0; s->reading = 0; return ret; } static SANE_Status endorser(struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[ENDORSER_len]; size_t cmdLen = ENDORSER_len; unsigned char out[ED_max_len]; size_t outLen = ED_max_len; DBG (10, "endorser: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, ENDORSER_code); memset(out,0,outLen); if (s->has_endorser_f || s->has_endorser_b){ /*fi-5900 front side uses 0x80, assume all others*/ if(s->u_endorser_side == ED_front){ set_ED_endorser_data_id(out,0x80); } else{ set_ED_endorser_data_id(out,0); } if(s->u_endorser){ set_ED_stop(out,ED_start); } else{ set_ED_stop(out,ED_stop); } set_ED_side(out,s->u_endorser_side); if(s->u_endorser_bits == 24){ set_ED_lap24(out,ED_lap_24bit); set_ED_initial_count_24(out,s->u_endorser_val); } else{ outLen = ED_min_len; set_ED_lap24(out,ED_lap_16bit); set_ED_initial_count_16(out,s->u_endorser_val); } set_E_xferlen(cmd, outLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); } DBG (10, "endorser: finish %d\n", ret); return ret; } static SANE_Status scanner_control (struct fujitsu *s, int function) { SANE_Status ret = SANE_STATUS_GOOD; int tries = 0; unsigned char cmd[SCANNER_CONTROL_len]; size_t cmdLen = SCANNER_CONTROL_len; DBG (10, "scanner_control: start\n"); if(s->has_cmd_scanner_ctl){ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SCANNER_CONTROL_code); set_SC_function (cmd, function); DBG (15, "scanner_control: function %d\n",function); /* don't really need to ask for adf if that's the only option */ /* doing so causes the 3091 to complain */ if(function == SC_function_adf && !s->has_flatbed){ DBG (10, "scanner_control: adf function not required\n"); return ret; } /* extremely long retry period */ while(tries++ < 120){ ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, NULL, NULL ); if(ret == SANE_STATUS_GOOD || function != SC_function_lamp_on){ break; } usleep(500000); } if(ret == SANE_STATUS_GOOD){ DBG (15, "scanner_control: success, tries %d, ret %d\n",tries,ret); } else{ DBG (5, "scanner_control: error, tries %d, ret %d\n",tries,ret); } } DBG (10, "scanner_control: finish\n"); return ret; } static SANE_Status scanner_control_ric (struct fujitsu *s, int bytes, int side) { SANE_Status ret = SANE_STATUS_GOOD; int tries = 0; unsigned char cmd[SCANNER_CONTROL_len]; size_t cmdLen = SCANNER_CONTROL_len; DBG (10, "scanner_control_ric: start\n"); if(s->has_cmd_scanner_ctl){ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SCANNER_CONTROL_code); set_SC_ric(cmd, 1); if (side == SIDE_BACK) { set_SC_ric_dtq(cmd, WD_wid_back); } else{ set_SC_ric_dtq(cmd, WD_wid_front); } set_SC_ric_len(cmd, bytes); DBG (15, "scanner_control_ric: %d %d\n",bytes,side); /* extremely long retry period */ while(tries++ < 120){ ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, NULL, NULL ); if(ret != SANE_STATUS_DEVICE_BUSY){ break; } usleep(500000); } if(ret == SANE_STATUS_GOOD){ DBG (15, "scanner_control_ric: success, tries %d, ret %d\n",tries,ret); } /* some errors pass thru unchanged */ else if(ret == SANE_STATUS_CANCELLED || ret == SANE_STATUS_JAMMED || ret == SANE_STATUS_NO_DOCS || ret == SANE_STATUS_COVER_OPEN ){ DBG (5, "scanner_control_ric: error, tries %d, ret %d\n",tries,ret); } /* other errors are ignored, since scanner may not support RIC */ else{ DBG (5, "scanner_control_ric: ignoring, tries %d, ret %d\n",tries,ret); ret = SANE_STATUS_GOOD; } } DBG (10, "scanner_control_ric: finish\n"); return ret; } /* * callocs a buffer to hold the scan data */ static SANE_Status setup_buffers (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; int side; DBG (10, "setup_buffers: start\n"); for(side=0;side<2;side++){ /* free old mem */ if (s->buffers[side]) { DBG (15, "setup_buffers: free buffer %d.\n",side); free(s->buffers[side]); s->buffers[side] = NULL; } if(s->buff_tot[side]){ s->buffers[side] = calloc (1,s->buff_tot[side]); if (!s->buffers[side]) { DBG (5, "setup_buffers: Error, no buffer %d.\n",side); return SANE_STATUS_NO_MEM; } } } DBG (10, "setup_buffers: finish\n"); return ret; } /* * This routine issues a SCSI SET WINDOW command to the scanner, using the * values currently in the scanner data structure. */ static SANE_Status set_window (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; /* The command specifies the number of bytes in the data phase * the data phase has a header, followed by 1 or 2 window desc blocks * the header specifies the number of bytes in 1 window desc block */ unsigned char cmd[SET_WINDOW_len]; size_t cmdLen = SET_WINDOW_len; /*this is max size, we might send less below*/ unsigned char out[SW_header_len + SW_desc_len + SW_desc_len]; size_t outLen = SW_header_len + SW_desc_len + SW_desc_len; unsigned char * header = out; /*header*/ unsigned char * desc1 = out + SW_header_len; /*1st desc*/ unsigned char * desc2 = out + SW_header_len + SW_desc_len; /*2nd desc*/ int length = 0; DBG (10, "set_window: start\n"); /*build the payload*/ memset(out,0,outLen); /* set window desc size in header */ set_WPDB_wdblen(header, SW_desc_len); /* init the window block */ if (s->source == SOURCE_ADF_BACK) { set_WD_wid (desc1, WD_wid_back); } else{ set_WD_wid (desc1, WD_wid_front); } set_WD_Xres (desc1, s->resolution_x); set_WD_Yres (desc1, s->resolution_y); set_WD_ULX (desc1, s->tl_x); /* low-end scanners ignore paper-size, * so we have to center the window ourselves */ if(s->cropping_mode == CROP_ABSOLUTE){ set_WD_ULX (desc1, s->tl_x + (s->max_x - s->page_width) / 2); } set_WD_ULY (desc1, s->tl_y); set_WD_width (desc1, s->s_params.pixels_per_line * 1200/s->resolution_x); length = s->s_params.lines * 1200/s->resolution_y; /* stupid trick. 3091/2 require reading extra lines, * because they have a gap between R G and B */ if(s->s_mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ length += (s->color_raster_offset+s->green_offset) * 1200/300 * 2; DBG(5,"set_window: Increasing length to %d\n",length); } set_WD_length (desc1, length); set_WD_brightness (desc1, 0); if(s->brightness_steps){ /*convert our common -127 to +127 range into HW's range *FIXME: this code assumes hardware range of 0-255 */ set_WD_brightness (desc1, s->brightness+128); } set_WD_threshold (desc1, s->threshold); set_WD_contrast (desc1, 0); if(s->contrast_steps){ /*convert our common -127 to +127 range into HW's range *FIXME: this code assumes hardware range of 0-255 */ set_WD_contrast (desc1, s->contrast+128); } set_WD_composition (desc1, s->s_mode); set_WD_bitsperpixel (desc1, s->s_params.depth); if(s->s_mode == MODE_HALFTONE){ set_WD_ht_type(desc1, s->ht_type); set_WD_ht_pattern(desc1, s->ht_pattern); } set_WD_rif (desc1, s->rif); set_WD_compress_type(desc1, COMP_NONE); set_WD_compress_arg(desc1, 0); /* some scanners support jpeg image compression, for color/gs only */ if(s->s_params.format == SANE_FRAME_JPEG){ set_WD_compress_type(desc1, COMP_JPEG); set_WD_compress_arg(desc1, s->compress_arg); } /* the remainder of the block varies based on model and mode, * except for gamma and paper size, those are in the same place */ /*vuid c0*/ if(s->has_vuid_3091){ set_WD_vendor_id_code (desc1, WD_VUID_3091); set_WD_gamma (desc1, s->window_gamma); if (s->s_mode != MODE_COLOR){ switch (s->dropout_color) { case COLOR_RED: set_WD_lamp_color (desc1, WD_LAMP_RED); break; case COLOR_GREEN: set_WD_lamp_color (desc1, WD_LAMP_GREEN); break; case COLOR_BLUE: set_WD_lamp_color (desc1, WD_LAMP_BLUE); break; default: set_WD_lamp_color (desc1, WD_LAMP_DEFAULT); break; } } /*set_WD_quality(desc1,s->quality);*/ } /*vuid c1*/ else if(s->s_mode == MODE_COLOR && s->has_vuid_color){ set_WD_vendor_id_code (desc1, WD_VUID_COLOR); set_WD_gamma (desc1, s->window_gamma); if(s->color_interlace == COLOR_INTERLACE_RGB){ set_WD_scanning_order (desc1, WD_SCAN_ORDER_DOT); set_WD_scanning_order_arg (desc1, WD_SCAN_ARG_RGB); } else if(s->color_interlace == COLOR_INTERLACE_BGR){ set_WD_scanning_order (desc1, WD_SCAN_ORDER_DOT); set_WD_scanning_order_arg (desc1, WD_SCAN_ARG_BGR); } else if(s->color_interlace == COLOR_INTERLACE_RRGGBB){ set_WD_scanning_order (desc1, WD_SCAN_ORDER_LINE); set_WD_scanning_order_arg (desc1, WD_SCAN_ARG_RGB); } else{ DBG (5,"set_window: unknown color interlacing\n"); return SANE_STATUS_INVAL; } /*scanner emphasis ranges from 0 to 7f and smoothing from 80 to ff*/ /* but we expose them to user as a single linear range smooth->emphasis */ /* flip the smooth part over, and tack it onto the upper end of emphasis */ if(s->emphasis < 0) set_WD_c1_emphasis(desc1,127-s->emphasis); else set_WD_c1_emphasis(desc1,s->emphasis); set_WD_c1_mirroring(desc1,s->mirroring); set_WD_wl_follow(desc1,s->wl_follow); } /*vuid 00*/ else if(s->has_vuid_mono){ set_WD_vendor_id_code (desc1, WD_VUID_MONO); set_WD_gamma (desc1, s->window_gamma); set_WD_outline(desc1,s->outline); /*scanner emphasis ranges from 0 to 7f and smoothing from 80 to ff*/ /* but we expose them to user as a single linear range smooth->emphasis */ /* flip the smooth part over, and tack it onto the upper end of emphasis */ if(s->emphasis < 0) set_WD_emphasis(desc1,127-s->emphasis); else set_WD_emphasis(desc1,s->emphasis); set_WD_separation(desc1,s->separation); set_WD_mirroring(desc1,s->mirroring); if (get_ipc_mode(s) == WD_ipc_SDTC) set_WD_variance(desc1,s->variance); else if (get_ipc_mode(s) == WD_ipc_DTC){ set_WD_filtering(desc1,s->bp_filter); set_WD_smoothing(desc1,s->smoothing); set_WD_gamma_curve(desc1,s->gamma_curve); set_WD_threshold_curve(desc1,s->threshold_curve); set_WD_noise_removal(desc1,s->noise_removal); if(s->noise_removal){ set_WD_matrix5x5(desc1,s->matrix_5); set_WD_matrix4x4(desc1,s->matrix_4); set_WD_matrix3x3(desc1,s->matrix_3); set_WD_matrix2x2(desc1,s->matrix_2); } set_WD_background(desc1,s->threshold_white); } set_WD_wl_follow(desc1,s->wl_follow); set_WD_subwindow_list(desc1,0); set_WD_ipc_mode(desc1,get_ipc_mode(s)); } else{ DBG (5,"set_window: no vuid to send?\n"); return SANE_STATUS_INVAL; } /* common to all vuids */ if(s->source == SOURCE_FLATBED){ set_WD_paper_selection(desc1,WD_paper_SEL_UNDEFINED); } else{ set_WD_paper_selection (desc1, WD_paper_SEL_NON_STANDARD); /* call helper function, scanner wants lies about paper width */ set_WD_paper_width_X (desc1, get_page_width(s)); /* dont call helper function, scanner wants actual length? */ set_WD_paper_length_Y (desc1, s->page_height); } /* when in duplex mode, copy first desc block into second */ if (s->source == SOURCE_ADF_DUPLEX) { memcpy (desc2, desc1, SW_desc_len); set_WD_wid (desc2, WD_wid_back); /* FIXME: do we really need these on back of page? */ set_WD_paper_selection (desc2, WD_paper_SEL_UNDEFINED); set_WD_paper_width_X (desc2, 0); set_WD_paper_length_Y (desc2, 0); } /* output shorter if not using duplex */ else{ outLen -= SW_desc_len; } /*build the command*/ memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SET_WINDOW_code); set_SW_xferlen(cmd, outLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "set_window: finish\n"); return ret; } /* update s_params with actual data size scanner reports */ /* then copy as required to the u_params to send to user */ static SANE_Status get_pixelsize(struct fujitsu *s, int actual) { SANE_Status ret; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char in[R_PSIZE_len]; size_t inLen = R_PSIZE_len; DBG (10, "get_pixelsize: start %d\n",actual); if (!s->has_pixelsize){ DBG (10, "get_pixelsize: unsupported\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, R_datatype_pixelsize); if(s->side == SIDE_BACK){ set_R_window_id (cmd, WD_wid_back); } else{ set_R_window_id (cmd, WD_wid_front); } set_R_xfer_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD){ /* when we are called post-scan, the scanner may give * more accurate data in other fields */ if(actual && !s->has_short_pixelsize && get_PSIZE_paper_w(in)){ DBG(5,"get_pixelsize: Actual width %d -> %d\n", s->s_params.pixels_per_line, get_PSIZE_paper_w(in)); s->s_params.pixels_per_line = get_PSIZE_paper_w(in); } else{ s->s_params.pixels_per_line = get_PSIZE_num_x(in); } /* stupid trick. 3091/2 require reading extra lines, * because they have a gap between R G and B * we only want to report the shorter value to the frontend */ if(s->s_mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ DBG(5,"get_pixelsize: Ignoring length %d\n",get_PSIZE_num_y(in)); } /* when we are called post-scan, the scanner may give * more accurate data in other fields */ else if(actual && !s->has_short_pixelsize && get_PSIZE_paper_l(in)){ DBG(5,"get_pixelsize: Actual length %d -> %d\n", s->s_params.lines, get_PSIZE_paper_l(in)); s->s_params.lines = get_PSIZE_paper_l(in); } else{ s->s_params.lines = get_PSIZE_num_y(in); } /* bytes per line differs by mode */ if (s->s_mode == MODE_COLOR) { s->s_params.bytes_per_line = s->s_params.pixels_per_line * 3; } else if (s->s_mode == MODE_GRAYSCALE) { s->s_params.bytes_per_line = s->s_params.pixels_per_line; } else { s->s_params.bytes_per_line = s->s_params.pixels_per_line / 8; } /* some scanners can request that the driver clean img */ if(!s->has_short_pixelsize && get_PSIZE_req_driv_valid(in)){ s->req_driv_crop = get_PSIZE_req_driv_crop(in); s->req_driv_lut = get_PSIZE_req_driv_lut(in); DBG(5,"get_pixelsize: scanner requests: crop=%d, lut=%d\n", s->req_driv_crop,s->req_driv_lut); } DBG (15, "get_pixelsize: scan_x=%d, Bpl=%d, scan_y=%d\n", s->s_params.pixels_per_line, s->s_params.bytes_per_line, s->s_params.lines ); /* the user params are usually the same */ s->u_params.pixels_per_line = s->s_params.pixels_per_line; s->u_params.lines = s->s_params.lines; /* bytes per line differs by mode */ if (s->u_mode == MODE_COLOR) { s->u_params.bytes_per_line = s->u_params.pixels_per_line * 3; } else if (s->u_mode == MODE_GRAYSCALE) { s->u_params.bytes_per_line = s->u_params.pixels_per_line; } else { s->u_params.bytes_per_line = s->u_params.pixels_per_line / 8; } } else{ DBG (10, "get_pixelsize: got bad status %d, ignoring\n", ret); s->has_pixelsize = 0; ret = SANE_STATUS_GOOD; } DBG (10, "get_pixelsize: finish\n"); return ret; } /* * Issues the SCSI OBJECT POSITION command if an ADF is in use. */ static SANE_Status object_position (struct fujitsu *s, int action) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[OBJECT_POSITION_len]; size_t cmdLen = OBJECT_POSITION_len; DBG (10, "object_position: start %d\n", action); if (s->source == SOURCE_FLATBED && action < OP_Halt) { DBG (10, "object_position: flatbed no-op\n"); return SANE_STATUS_GOOD; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, OBJECT_POSITION_code); set_OP_action (cmd, action); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, NULL, NULL ); if (ret != SANE_STATUS_GOOD) return ret; if(!s->no_wait_after_op) wait_scanner (s); DBG (10, "object_position: finish\n"); return ret; } /* * Issues SCAN command. * * (This doesn't actually read anything, it just tells the scanner * to start scanning.) */ static SANE_Status start_scan (struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[SCAN_len]; size_t cmdLen = SCAN_len; unsigned char out[] = {WD_wid_front, WD_wid_back}; size_t outLen = 2; DBG (10, "start_scan: start\n"); if (s->source != SOURCE_ADF_DUPLEX) { outLen--; if(s->source == SOURCE_ADF_BACK) { out[0] = WD_wid_back; } } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, SCAN_code); set_SC_xfer_length (cmd, outLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, out, outLen, NULL, NULL ); DBG (10, "start_scan: finish\n"); return ret; } /* checks started and cancelled flags in scanner struct, * sends cancel command to scanner if required. don't call * this function asyncronously, wait for pending operation */ static SANE_Status check_for_cancel(struct fujitsu *s) { SANE_Status ret=SANE_STATUS_GOOD; DBG (10, "check_for_cancel: start %d %d\n",s->started,s->cancelled); if(s->started && s->cancelled){ /* halt scan */ if(s->halt_on_cancel){ DBG (15, "check_for_cancel: halting\n"); ret = object_position (s, OP_Halt); } /* cancel scan */ else{ DBG (15, "check_for_cancel: cancelling\n"); ret = scanner_control(s, SC_function_cancel); } if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_CANCELLED) { ret = SANE_STATUS_CANCELLED; } else{ DBG (5, "check_for_cancel: ERROR: cannot cancel\n"); } s->started = 0; s->cancelled = 0; } else if(s->cancelled){ DBG (15, "check_for_cancel: already cancelled\n"); ret = SANE_STATUS_CANCELLED; s->cancelled = 0; } DBG (10, "check_for_cancel: finish %d\n",ret); return ret; } /* * Called by SANE to read data. * * From the SANE spec: * This function is used to read image data from the device * represented by handle h. Argument buf is a pointer to a memory * area that is at least maxlen bytes long. The number of bytes * returned is stored in *len. A backend must set this to zero when * the call fails (i.e., when a status other than SANE_STATUS_GOOD is * returned). * * When the call succeeds, the number of bytes returned can be * anywhere in the range from 0 to maxlen bytes. */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct fujitsu *s = (struct fujitsu *) handle; SANE_Status ret=SANE_STATUS_GOOD; DBG (10, "sane_read: start\n"); *len=0; /* maybe cancelled? */ if(!s->started){ DBG (5, "sane_read: not started, call sane_start\n"); return SANE_STATUS_CANCELLED; } /* sane_start required between sides */ if(s->eof_rx[s->side] && s->bytes_tx[s->side] == s->bytes_rx[s->side]){ DBG (15, "sane_read: returning eof\n"); s->eof_tx[s->side] = 1; /* swap sides if user asked for low-mem mode, we are duplexing, * and there is data waiting on the other side */ if(s->low_mem && s->source == SOURCE_ADF_DUPLEX && (s->bytes_rx[!s->side] > s->bytes_tx[!s->side] || (s->eof_rx[!s->side] && !s->eof_tx[!s->side]) ) ){ s->side = !s->side; } return SANE_STATUS_EOF; } /* protect this block from sane_cancel */ s->reading = 1; /* ---------------------------------------------- * try to read some data from scanner into buffer * these functions are expected not to overrun */ /* 3091/2 are on crack, get their own duplex reader function */ if(s->source == SOURCE_ADF_DUPLEX && s->duplex_interlace == DUPLEX_INTERLACE_3091 ){ ret = read_from_3091duplex(s); if(ret){ DBG(5,"sane_read: 3091 returning %d\n",ret); return ret; } } /* end 3091 */ /* alternating jpeg duplex interlacing */ else if(s->source == SOURCE_ADF_DUPLEX && s->s_params.format == SANE_FRAME_JPEG && s->jpeg_interlace == JPEG_INTERLACE_ALT ){ ret = read_from_JPEGduplex(s); if(ret){ DBG(5,"sane_read: jpeg duplex returning %d\n",ret); return ret; } } /* end alt jpeg */ /* alternating pnm duplex interlacing */ else if(s->source == SOURCE_ADF_DUPLEX && s->s_params.format != SANE_FRAME_JPEG && s->duplex_interlace == DUPLEX_INTERLACE_ALT ){ /* buffer front side */ ret = read_from_scanner(s, SIDE_FRONT); if(ret){ DBG(5,"sane_read: front returning %d\n",ret); return ret; } /* buffer back side, but don't get too far ahead of the front! */ if(s->bytes_rx[SIDE_BACK] < s->bytes_rx[SIDE_FRONT] + s->buffer_size){ ret = read_from_scanner(s, SIDE_BACK); if(ret){ DBG(5,"sane_read: back returning %d\n",ret); return ret; } } } /* end alt pnm */ /* simplex or non-alternating duplex */ else{ ret = read_from_scanner(s, s->side); if(ret){ DBG(5,"sane_read: side %d returning %d\n",s->side,ret); return ret; } } /*end simplex*/ /* uncommon case, downsample and copy a block from buffer to frontend */ if(must_downsample(s)){ ret = downsample_from_buffer(s,buf,max_len,len,s->side); } /* common case, memcpy a block from buffer to frontend */ else{ ret = read_from_buffer(s,buf,max_len,len,s->side); } /*finished sending small buffer, reset it*/ if(s->buff_tx[s->side] == s->buff_rx[s->side] && s->buff_tot[s->side] < s->bytes_tot[s->side] ){ DBG (15, "sane_read: reset buffers\n"); s->buff_rx[s->side] = 0; s->buff_tx[s->side] = 0; } /* check if user cancelled during this read */ ret = check_for_cancel(s); /* swap sides if user asked for low-mem mode, we are duplexing, * and there is data waiting on the other side */ if(s->low_mem && s->source == SOURCE_ADF_DUPLEX && (s->bytes_rx[!s->side] > s->bytes_tx[!s->side] || (s->eof_rx[!s->side] && !s->eof_tx[!s->side]) ) ){ s->side = !s->side; } /* unprotect this block from sane_cancel */ s->reading = 0; DBG (10, "sane_read: finish %d\n", ret); return ret; } /* bare jpeg images dont contain resolution, but JFIF APP0 does, so we add */ static SANE_Status inject_jfif_header(struct fujitsu *s, int side) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char out[] = { 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00 }; size_t outLen=JFIF_APP0_LENGTH; DBG (10, "inject_jfif_header: start %d\n", side); putnbyte(out + 12, s->resolution_x, 2); putnbyte(out + 14, s->resolution_y, 2); memcpy(s->buffers[side]+s->buff_rx[side], out, outLen); s->buff_rx[side] += outLen; s->bytes_rx[side] += outLen; DBG (10, "inject_jfif_header: finish %d\n", ret); return ret; } static SANE_Status read_from_JPEGduplex(struct fujitsu *s) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char * in; size_t inLen = 0; int bytes = s->buffer_size; int i = 0; DBG (10, "read_from_JPEGduplex: start\n"); if(s->eof_rx[SIDE_FRONT] && s->eof_rx[SIDE_BACK]){ DBG (10, "read_from_JPEGduplex: already have eofs, done\n"); return ret; } /* we don't know if the following read will give us front or back data * so we only get enough to fill whichever is smaller (and not yet done) */ if(!s->eof_rx[SIDE_FRONT]){ int avail = s->buff_tot[SIDE_FRONT] - s->buff_rx[SIDE_FRONT]; if(bytes > avail){ bytes = avail; /* leave space for JFIF header at start of image */ if(s->bytes_rx[SIDE_FRONT] < 2) bytes -= JFIF_APP0_LENGTH; } } if(!s->eof_rx[SIDE_BACK]){ int avail = s->buff_tot[SIDE_BACK] - s->buff_rx[SIDE_BACK]; if(bytes > avail){ bytes = avail; /* leave space for JFIF header at start of image */ if(s->bytes_rx[SIDE_BACK] < 2) bytes -= JFIF_APP0_LENGTH; } } DBG(15, "read_from_JPEGduplex: fto:%d frx:%d bto:%d brx:%d pa:%d\n", s->bytes_tot[SIDE_FRONT], s->bytes_rx[SIDE_FRONT], s->bytes_tot[SIDE_BACK], s->bytes_rx[SIDE_BACK], bytes); /* this will happen if buffer is not drained yet */ if(bytes < 1){ DBG(5, "read_from_JPEGduplex: Warning: no bytes this pass\n"); return ret; } /* fi-6770A gets mad if you 'read' too soon on usb, see if it is ready */ if(!s->bytes_rx[SIDE_FRONT] && s->connection == CONNECTION_USB){ DBG (15, "read: start of usb page, checking RIC\n"); ret = scanner_control_ric(s,bytes,SIDE_FRONT); if(ret){ DBG(5,"read: ric returning %d\n",ret); return ret; } } inLen = bytes; in = malloc(inLen); if(!in){ DBG(5, "read_from_JPEGduplex: not enough mem for buffer: %d\n",(int)inLen); return SANE_STATUS_NO_MEM; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, R_datatype_imagedata); /* interlaced jpeg duplex always reads from front */ set_R_window_id (cmd, WD_wid_front); set_R_xfer_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { DBG(15, "read_from_JPEGduplex: got GOOD/EOF, returning GOOD\n"); } else if (ret == SANE_STATUS_DEVICE_BUSY) { DBG(5, "read_from_JPEGduplex: got BUSY, returning GOOD\n"); inLen = 0; ret = SANE_STATUS_GOOD; } else { DBG(5, "read_from_JPEGduplex: error reading data status = %d\n", ret); inLen = 0; } for(i=0;i<(int)inLen;i++){ /* about to change stage */ if(in[i] == 0xff && s->jpeg_ff_offset != 0){ s->jpeg_ff_offset=0; continue; } /* last byte was an ff, this byte will change stage */ if(s->jpeg_ff_offset == 0){ /* first marker after SOI is not APP0, add one */ if(s->jpeg_stage == JPEG_STAGE_SOI && in[i] != 0xe0){ inject_jfif_header(s,SIDE_FRONT); inject_jfif_header(s,SIDE_BACK); s->jpeg_stage = JPEG_STAGE_HEAD; } /* SOI header, in both sides */ if(in[i] == 0xd8){ s->jpeg_stage = JPEG_STAGE_SOI; DBG(15, "read_from_JPEGduplex: stage SOI\n"); } /* headers (HuffTab/QTab/DRI), in both sides */ else if(in[i] == 0xc4 || in[i] == 0xdb || in[i] == 0xdd){ s->jpeg_stage = JPEG_STAGE_HEAD; DBG(15, "read_from_JPEGduplex: stage head\n"); } /* start of frame, in both sides, update x first */ else if(in[i]==0xc0){ s->jpeg_stage = JPEG_STAGE_SOF; DBG(15, "read_from_JPEGduplex: stage sof\n"); } /* start of scan, first few bytes of marker in both sides * but rest in front */ else if(in[i]==0xda){ s->jpeg_stage = JPEG_STAGE_SOS; DBG(15, "read_from_JPEGduplex: stage sos\n"); } /* found image block. images are not interlaced */ /* copy to front, don't change RST */ else if(in[i] >= 0xd0 && in[i] <= 0xd7 && s->jpeg_interlace == JPEG_INTERLACE_NONE){ s->jpeg_stage = JPEG_STAGE_FRONT; DBG(35, "read_from_JPEGduplex: stage front (all)\n"); } /* found even numbered image block. */ /* images are interlaced, so switch to back. */ /* also change from even RST to proper one */ else if(in[i] == 0xd0 || in[i] == 0xd2 || in[i] == 0xd4 || in[i] == 0xd6){ s->jpeg_stage = JPEG_STAGE_BACK; DBG(35, "read_from_JPEGduplex: stage back\n"); /* skip first RST for back side*/ if(!s->jpeg_back_rst){ DBG(15, "read_from_JPEGduplex: stage back jump\n"); s->jpeg_ff_offset++; s->jpeg_back_rst++; continue; } in[i] = 0xd0 + (s->jpeg_back_rst-1) % 8; s->jpeg_back_rst++; } /* finished back image block, switch to front */ /* also change from odd RST to proper one */ else if(in[i] == 0xd1 || in[i] == 0xd3 || in[i] == 0xd5 || in[i] == 0xd7){ s->jpeg_stage = JPEG_STAGE_FRONT; DBG(35, "read_from_JPEGduplex: stage front\n"); in[i] = 0xd0 + (s->jpeg_front_rst % 8); s->jpeg_front_rst++; } /* finished image, update totals */ else if(in[i]==0xd9){ s->jpeg_stage = JPEG_STAGE_EOI; DBG(15, "read_from_JPEGduplex: stage eoi %d %d\n",(int)inLen,i); } /* unknown, warn */ else if(in[i] != 0xff){ DBG(15, "read_from_JPEGduplex: unknown %02x\n", in[i]); } } s->jpeg_ff_offset++; /* first x byte in start of frame, buffer it */ if(s->jpeg_stage == JPEG_STAGE_SOF && s->jpeg_ff_offset == 7){ s->jpeg_x_byte = in[i]; continue; } /* second x byte in start of frame */ if(s->jpeg_stage == JPEG_STAGE_SOF && s->jpeg_ff_offset == 8){ int width = (s->jpeg_x_byte << 8) | in[i]; /* if image width equals what we asked for, then * the image is not interlaced, clean up the mess */ if(width == s->s_params.pixels_per_line){ DBG(15, "read_from_JPEGduplex: right width, req:%d got:%d\n", s->s_params.pixels_per_line,width); /* stop copying to the back */ s->jpeg_interlace = JPEG_INTERLACE_NONE; /* clear what is already in the back */ s->bytes_rx[SIDE_BACK]=0; s->lines_rx[SIDE_BACK]=0; s->buff_rx[SIDE_BACK]=0; /* and put the high-order width byte into front unchanged */ s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = s->jpeg_x_byte; s->bytes_rx[SIDE_FRONT]++; } /* image is interlaced afterall, continue */ else{ DBG(15, "read_from_JPEGduplex: wrong width, req:%d got:%d\n", s->s_params.pixels_per_line,width); /* put the high-order width byte into front side, shifted down */ s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = width >> 9; s->bytes_rx[SIDE_FRONT]++; /* put the high-order width byte into back side, shifted down */ s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = width >> 9; s->bytes_rx[SIDE_BACK]++; /* shift down low order byte */ in[i] = (width >> 1) & 0xff; } } /* copy these stages to front */ if(s->jpeg_stage == JPEG_STAGE_SOI || s->jpeg_stage == JPEG_STAGE_HEAD || s->jpeg_stage == JPEG_STAGE_SOF || s->jpeg_stage == JPEG_STAGE_SOS || s->jpeg_stage == JPEG_STAGE_EOI || s->jpeg_stage == JPEG_STAGE_FRONT ){ /* first byte after ff, send the ff first */ if(s->jpeg_ff_offset == 1){ s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = 0xff; s->bytes_rx[SIDE_FRONT]++; } s->buffers[SIDE_FRONT][s->buff_rx[SIDE_FRONT]++] = in[i]; s->bytes_rx[SIDE_FRONT]++; } /* copy these stages to back */ if( s->jpeg_interlace == JPEG_INTERLACE_ALT && ( s->jpeg_stage == JPEG_STAGE_SOI || s->jpeg_stage == JPEG_STAGE_HEAD || s->jpeg_stage == JPEG_STAGE_SOF || s->jpeg_stage == JPEG_STAGE_SOS || s->jpeg_stage == JPEG_STAGE_EOI || s->jpeg_stage == JPEG_STAGE_BACK ) ){ /* first byte after ff, send the ff first */ if(s->jpeg_ff_offset == 1){ s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = 0xff; s->bytes_rx[SIDE_BACK]++; } s->buffers[SIDE_BACK][s->buff_rx[SIDE_BACK]++] = in[i]; s->bytes_rx[SIDE_BACK]++; } /* reached last byte of SOS section, next byte front */ if(s->jpeg_stage == JPEG_STAGE_SOS && s->jpeg_ff_offset == 0x0d){ s->jpeg_stage = JPEG_STAGE_FRONT; } /* last byte of file, update totals, bail out */ if(s->jpeg_stage == JPEG_STAGE_EOI){ s->eof_rx[SIDE_FRONT] = 1; if(s->jpeg_interlace == JPEG_INTERLACE_ALT) s->eof_rx[SIDE_BACK] = 1; } } free(in); /* jpeg uses in-band EOI marker, so this is ususally redundant */ if(ret == SANE_STATUS_EOF){ DBG(15, "read_from_JPEGduplex: got EOF, finishing\n"); s->eof_rx[SIDE_FRONT] = 1; if(s->jpeg_interlace == JPEG_INTERLACE_ALT) s->eof_rx[SIDE_BACK] = 1; ret = SANE_STATUS_GOOD; } DBG (10, "read_from_JPEGduplex: finish\n"); return ret; } static SANE_Status read_from_3091duplex(struct fujitsu *s) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char * in; size_t inLen = 0; int side = SIDE_FRONT; int bytes = s->buffer_size; int off = (s->duplex_raster_offset+s->duplex_offset) * s->resolution_y/300; unsigned int i; DBG (10, "read_from_3091duplex: start\n"); if(s->eof_rx[SIDE_FRONT] && s->eof_rx[SIDE_BACK]){ DBG (10, "read_from_3091duplex: already have eofs, done\n"); return ret; } /* we don't know if the following read will give us front,back or both data * so we only get enough to fill whichever is smaller (and not yet done) */ if(!s->eof_rx[SIDE_FRONT]){ int avail = s->buff_tot[SIDE_FRONT] - s->buff_rx[SIDE_FRONT]; if(bytes > avail) bytes = avail; } if(!s->eof_rx[SIDE_BACK]){ int avail = s->buff_tot[SIDE_BACK] - s->buff_rx[SIDE_BACK]; if(bytes > avail) bytes = avail; } /* all requests must end on a line boundary */ bytes -= (bytes % s->s_params.bytes_per_line); DBG(15, "read_from_3091duplex: front img: to:%d rx:%d tx:%d li:%d\n", s->bytes_tot[SIDE_FRONT], s->bytes_rx[SIDE_FRONT], s->bytes_tx[SIDE_FRONT], s->lines_rx[SIDE_FRONT]); DBG(15, "read_from_3091duplex: front buf: to:%d rx:%d tx:%d\n", s->buff_tot[SIDE_FRONT], s->buff_rx[SIDE_FRONT], s->buff_tx[SIDE_FRONT]); DBG(15, "read_from_3091duplex: back img: to:%d rx:%d tx:%d li:%d\n", s->bytes_tot[SIDE_BACK], s->bytes_rx[SIDE_BACK], s->bytes_tx[SIDE_BACK], s->lines_rx[SIDE_BACK]); DBG(15, "read_from_3091duplex: back buf: to:%d rx:%d tx:%d\n", s->buff_tot[SIDE_BACK], s->buff_rx[SIDE_BACK], s->buff_tx[SIDE_BACK]); DBG(15, "read_from_3091duplex: bu:%d pa:%d of:%d\n", s->buffer_size, bytes, off); /* this could happen if the front buffer is not drained fast enough */ if(bytes < 1){ DBG(10, "read_from_3091duplex: Warning: no bytes this pass\n"); return ret; } inLen = bytes; in = malloc(inLen); if(!in){ DBG(5, "read_from_3091duplex: not enough mem for buffer: %d\n",(int)inLen); return SANE_STATUS_NO_MEM; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, R_datatype_imagedata); /* 3091 duplex always reads from front */ set_R_window_id (cmd, WD_wid_front); set_R_xfer_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { DBG(15, "read_from_3091duplex: got GOOD/EOF, returning GOOD\n"); } else if (ret == SANE_STATUS_DEVICE_BUSY) { DBG(5, "read_from_3091duplex: got BUSY, returning GOOD\n"); inLen = 0; ret = SANE_STATUS_GOOD; } else { DBG(5, "read_from_3091duplex: error reading data block status = %d\n", ret); inLen = 0; } /* loop thru all lines in read buffer */ for(i=0;is_params.bytes_per_line;i++){ /* start is front */ if(s->lines_rx[SIDE_FRONT] < off){ side=SIDE_FRONT; } /* end is back */ else if(s->eof_rx[SIDE_FRONT]){ side=SIDE_BACK; } /* odd are back */ else if( ((s->lines_rx[SIDE_FRONT] + s->lines_rx[SIDE_BACK] - off) % 2) ){ side=SIDE_BACK; } /* even are front */ else{ side=SIDE_FRONT; } if(s->s_mode == MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ copy_3091 (s, in + i*s->s_params.bytes_per_line, s->s_params.bytes_per_line, side); } else{ copy_buffer (s, in + i*s->s_params.bytes_per_line, s->s_params.bytes_per_line, side); } } if(ret == SANE_STATUS_EOF){ DBG(15, "read_from_3091duplex: got EOF, finishing both sides\n"); s->eof_rx[SIDE_FRONT] = 1; s->eof_rx[SIDE_BACK] = 1; ret = SANE_STATUS_GOOD; } free(in); DBG (10, "read_from_3091duplex: finish\n"); return ret; } static SANE_Status read_from_scanner(struct fujitsu *s, int side) { SANE_Status ret=SANE_STATUS_GOOD; unsigned char cmd[READ_len]; size_t cmdLen = READ_len; unsigned char * in; size_t inLen = 0; int bytes = s->buffer_size; int avail = s->buff_tot[side] - s->buff_rx[side]; int remain = s->bytes_tot[side] - s->bytes_rx[side]; DBG (10, "read_from_scanner: start %d\n", side); if(s->eof_rx[side]){ DBG (10, "read_from_scanner: already have eof, done\n"); return ret; } /* figure out the max amount to transfer */ if(bytes > avail) bytes = avail; /* all requests must end on line boundary */ bytes -= (bytes % s->s_params.bytes_per_line); /* some larger scanners require even bytes per block */ /* so we get even lines, but not on the last block */ /* cause odd number of lines would never finish */ if(bytes % 2 && bytes < remain){ bytes -= s->s_params.bytes_per_line; } /* jpeg scans leave space for JFIF header at start of image */ if(s->s_params.format == SANE_FRAME_JPEG && s->bytes_rx[side] < 2) bytes -= JFIF_APP0_LENGTH; DBG(15, "read_from_scanner: si:%d re:%d bs:%d by:%d av:%d\n", side, remain, s->buffer_size, bytes, avail); DBG(15, "read_from_scanner: img to:%d rx:%d tx:%d li:%d\n", s->bytes_tot[side], s->bytes_rx[side], s->bytes_tx[side], s->lines_rx[side]); DBG(15, "read_from_scanner: buf to:%d rx:%d tx:%d\n", s->buff_tot[side], s->buff_rx[side], s->buff_tx[side]); /* this will happen if buffer is not drained yet */ if(bytes < 1){ DBG(5, "read_from_scanner: no bytes this pass\n"); return ret; } /* fi-6770A gets mad if you 'read' too soon on usb, see if it is ready */ if(!s->bytes_rx[side] && s->connection == CONNECTION_USB){ DBG (15, "read_from_scanner: start of usb page, checking RIC\n"); ret = scanner_control_ric(s,bytes,side); if(ret){ DBG(5,"read_from_scanner: ric returning %d\n",ret); return ret; } } inLen = bytes; in = malloc(inLen); if(!in){ DBG(5, "read_from_scanner: not enough mem for buffer: %d\n",(int)inLen); return SANE_STATUS_NO_MEM; } memset(cmd,0,cmdLen); set_SCSI_opcode(cmd, READ_code); set_R_datatype_code (cmd, R_datatype_imagedata); if (side == SIDE_BACK) { set_R_window_id (cmd, WD_wid_back); } else{ set_R_window_id (cmd, WD_wid_front); } set_R_xfer_length (cmd, inLen); ret = do_cmd ( s, 1, 0, cmd, cmdLen, NULL, 0, in, &inLen ); if (ret == SANE_STATUS_GOOD || ret == SANE_STATUS_EOF) { DBG(15, "read_from_scanner: got GOOD/EOF, returning GOOD\n"); ret = SANE_STATUS_GOOD; } else if (ret == SANE_STATUS_DEVICE_BUSY) { DBG(5, "read_from_scanner: got BUSY, returning GOOD\n"); inLen = 0; ret = SANE_STATUS_GOOD; } else { DBG(5, "read_from_scanner: error reading data block status = %d\n",ret); inLen = 0; } DBG(15, "read_from_scanner: read %lu bytes\n",(unsigned long)inLen); if(inLen){ if(s->s_mode==MODE_COLOR && s->color_interlace == COLOR_INTERLACE_3091){ copy_3091 (s, in, inLen, side); } else if(s->s_params.format == SANE_FRAME_JPEG){ copy_JPEG (s, in, inLen, side); } else{ copy_buffer (s, in, inLen, side); } } free(in); /* if this was a short read or not, log it */ s->ili_rx[side] = s->rs_ili; if(s->ili_rx[side]){ DBG(15, "read_from_scanner: got ILI\n"); } /* if this was an end of medium, log it */ if(s->rs_eom){ DBG(15, "read_from_scanner: got EOM\n"); s->eom_rx = 1; } /* paper ran out. lets try to set the eof flag on both sides, * but only if that side had a short read last time */ if(s->eom_rx){ int i; for(i=0;i<2;i++){ if(s->ili_rx[i]){ DBG(15, "read_from_scanner: finishing side %d\n",i); s->eof_rx[i] = 1; } } } DBG (10, "read_from_scanner: finish\n"); return ret; } static SANE_Status copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side) { SANE_Status ret=SANE_STATUS_GOOD; int i, j, dest, boff, goff; DBG (10, "copy_3091: start\n"); /* Data is RR...GG...BB... on each line, * green is back 8 lines from red at 300 dpi * blue is back 4 lines from red at 300 dpi. * * Here, we get things on correct line, and * interlace to make RGBRGB. * * We add the user-supplied offsets before we scale * so that they are independent of scanning resolution. */ goff = (s->color_raster_offset+s->green_offset) * s->resolution_y/150; boff = (s->color_raster_offset+s->blue_offset) * s->resolution_y/300; /* loop thru all lines in read buffer */ for(i=0;is_params.bytes_per_line){ /* red at start of line */ dest = s->lines_rx[side] * s->s_params.bytes_per_line; if(dest >= 0 && dest < s->bytes_tot[side]){ for (j=0; js_params.pixels_per_line; j++){ s->buffers[side][dest+j*3] = buf[i+j]; } } /* green is in middle of line */ dest = (s->lines_rx[side] - goff) * s->s_params.bytes_per_line; if(dest >= 0 && dest < s->bytes_tot[side]){ for (j=0; js_params.pixels_per_line; j++){ s->buffers[side][dest+j*3+1] = buf[i+s->s_params.pixels_per_line+j]; } } /* blue is at end of line */ dest = (s->lines_rx[side] - boff) * s->s_params.bytes_per_line; if(dest >= 0 && dest < s->bytes_tot[side]){ for (j=0; js_params.pixels_per_line; j++){ s->buffers[side][dest+j*3+2] = buf[i+2*s->s_params.pixels_per_line+j]; } } s->lines_rx[side]++; } /* even if we have read data, we may not have any * full lines loaded yet, so we may have to lie */ i = (s->lines_rx[side]-goff) * s->s_params.bytes_per_line; if(i < 0){ i = 0; } s->bytes_rx[side] = i; s->buff_rx[side] = i; if(s->bytes_rx[side] == s->bytes_tot[side]){ s->eof_rx[side] = 1; } DBG(15, "copy_3091: si:%d imgrx:%d bufrx:%d li:%d eof:%d\n", side, s->bytes_rx[side], s->buff_rx[side], s->lines_rx[side], s->eof_rx[side]); DBG (10, "copy_3091: finish\n"); return ret; } static SANE_Status copy_JPEG(struct fujitsu *s, unsigned char * buf, int len, int side) { SANE_Status ret=SANE_STATUS_GOOD; int i, seen = 0; DBG (10, "copy_JPEG: start\n"); /* A jpeg image starts with the SOI marker, FF D8. * This is optionally followed by the JFIF APP0 * marker, FF E0. If that marker is not present, * we add it, so we can insert the resolution */ if(!s->bytes_rx[side] && len >= 4 && buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF && buf[3] != 0xE0 ){ /* SOI marker */ for (i=0; i<2; i++){ s->buffers[side][s->buff_rx[side]++] = buf[i]; s->bytes_rx[side]++; seen++; } /* JFIF header after SOI */ inject_jfif_header(s,side); } memcpy(s->buffers[side]+s->buff_rx[side],buf+seen,len-seen); s->buff_rx[side] += len-seen; s->bytes_rx[side] += len-seen; /* should never happen with jpeg */ if(s->bytes_rx[side] == s->bytes_tot[side]){ s->eof_rx[side] = 1; } DBG (10, "copy_JPEG: finish\n"); return ret; } static SANE_Status copy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side) { SANE_Status ret=SANE_STATUS_GOOD; int i, j; int bwidth = s->s_params.bytes_per_line; int pwidth = s->s_params.pixels_per_line; DBG (10, "copy_buffer: start\n"); /* invert image if scanner needs it for this mode */ /* jpeg data does not use inverting */ if(s->s_params.format != SANE_FRAME_JPEG && s->reverse_by_mode[s->s_mode]){ for(i=0; is_params.format == SANE_FRAME_RGB){ switch (s->color_interlace) { /* scanner returns pixel data as bgrbgr... */ case COLOR_INTERLACE_BGR: for(i=0; ibuffers[side][s->buff_rx[side]++] = buf[i+j*3+2]; s->buffers[side][s->buff_rx[side]++] = buf[i+j*3+1]; s->buffers[side][s->buff_rx[side]++] = buf[i+j*3]; } } break; /* one line has the following format: rrr...rrrggg...gggbbb...bbb */ case COLOR_INTERLACE_RRGGBB: for(i=0; ibuffers[side][s->buff_rx[side]++] = buf[i+j]; s->buffers[side][s->buff_rx[side]++] = buf[i+pwidth+j]; s->buffers[side][s->buff_rx[side]++] = buf[i+2*pwidth+j]; } } break; default: memcpy(s->buffers[side]+s->buff_rx[side],buf,len); s->buff_rx[side] += len; break; } } /* jpeg/gray/ht/binary */ else{ memcpy(s->buffers[side]+s->buff_rx[side],buf,len); s->buff_rx[side] += len; } s->bytes_rx[side] += len; s->lines_rx[side] += len/s->s_params.bytes_per_line; if(s->bytes_rx[side] == s->bytes_tot[side]){ s->eof_rx[side] = 1; } DBG (10, "copy_buffer: finish\n"); return ret; } static SANE_Status read_from_buffer(struct fujitsu *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side) { SANE_Status ret=SANE_STATUS_GOOD; int bytes = max_len; int remain = s->buff_rx[side] - s->buff_tx[side]; DBG (10, "read_from_buffer: start\n"); /* figure out the max amount to transfer */ if(bytes > remain){ bytes = remain; } *len = bytes; DBG(15, "read_from_buffer: si:%d re:%d ml:%d by:%d\n", side, remain, max_len, bytes); DBG(15, "read_from_buffer: img to:%d rx:%d tx:%d\n", s->bytes_tot[side], s->bytes_rx[side], s->bytes_tx[side]); DBG(15, "read_from_buffer: buf to:%d rx:%d tx:%d\n", s->buff_tot[side], s->buff_rx[side], s->buff_tx[side]); /*FIXME this needs to timeout eventually */ if(!bytes){ DBG(5,"read_from_buffer: nothing to do\n"); return SANE_STATUS_GOOD; } memcpy(buf,s->buffers[side]+s->buff_tx[side],bytes); s->buff_tx[side] += bytes; s->bytes_tx[side] += bytes; DBG (10, "read_from_buffer: finish\n"); return ret; } /* we have bytes of higher mode image data in s->buffers */ /* user asked for lower mode image. downsample and copy to buf */ static SANE_Status downsample_from_buffer(struct fujitsu *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side) { SANE_Status ret=SANE_STATUS_GOOD; DBG (10, "downsample_from_buffer: start %d %d %d %d\n", s->bytes_rx[side], s->bytes_tx[side], s->buff_rx[side], s->buff_tx[side]); if(s->s_mode == MODE_COLOR && s->u_mode == MODE_GRAYSCALE){ while(*len < max_len && s->buff_rx[side] - s->buff_tx[side] >= 3){ int gray = 0; switch (s->dropout_color) { case COLOR_RED: gray = *(s->buffers[side]+s->buff_tx[side]) * 3; break; case COLOR_GREEN: gray = *(s->buffers[side]+s->buff_tx[side]+1) * 3; break; case COLOR_BLUE: gray = *(s->buffers[side]+s->buff_tx[side]+2) * 3; break; default: gray = *(s->buffers[side]+s->buff_tx[side]) + *(s->buffers[side]+s->buff_tx[side]+1) + *(s->buffers[side]+s->buff_tx[side]+2); break; } /* bookkeeping for input */ s->buff_tx[side] += 3; s->bytes_tx[side] += 3; /* add byte to output */ *(buf + *len) = gray/3; (*len)++; } } else if(s->s_mode == MODE_COLOR && s->u_mode == MODE_LINEART){ /* threshold of 0 is actually middle of range */ /*FIXME: add dynamic threshold? */ unsigned char thresh = (s->threshold ? s->threshold : 127); while(*len < max_len && s->buff_rx[side] - s->buff_tx[side] >= 24){ int i; unsigned char out = 0; for(i=0; i<8; i++){ int gray = 0; switch (s->dropout_color) { case COLOR_RED: gray = *(s->buffers[side]+s->buff_tx[side]) * 3; break; case COLOR_GREEN: gray = *(s->buffers[side]+s->buff_tx[side]+1) * 3; break; case COLOR_BLUE: gray = *(s->buffers[side]+s->buff_tx[side]+2) * 3; break; default: gray = *(s->buffers[side]+s->buff_tx[side]) + *(s->buffers[side]+s->buff_tx[side]+1) + *(s->buffers[side]+s->buff_tx[side]+2); break; } /* black if input gray is lower than threshold */ if(gray/3 < thresh){ out |= (0x80 >> i); } /* bookkeeping for input */ s->buff_tx[side] += 3; s->bytes_tx[side] += 3; } /* add byte to output */ *(buf + *len) = out; (*len)++; } } else{ DBG (5, "downsample_from_buffer: invalid mode combination\n"); ret = SANE_STATUS_INVAL; } DBG (10, "downsample_from_buffer: finish %d %d %d %d\n", s->bytes_rx[side], s->bytes_tx[side], s->buff_rx[side], s->buff_tx[side]); return ret; } /* * @@ Section 5 - SANE cleanup functions */ /* * Cancels a scan. * * It has been said on the mailing list that sane_cancel is a bit of a * misnomer because it is routinely called to signal the end of a * batch - quoting David Mosberger-Tang: * * > In other words, the idea is to have sane_start() be called, and * > collect as many images as the frontend wants (which could in turn * > consist of multiple frames each as indicated by frame-type) and * > when the frontend is done, it should call sane_cancel(). * > Sometimes it's better to think of sane_cancel() as "sane_stop()" * > but that name would have had some misleading connotations as * > well, that's why we stuck with "cancel". * * The current consensus regarding duplex and ADF scans seems to be * the following call sequence: sane_start; sane_read (repeat until * EOF); sane_start; sane_read... and then call sane_cancel if the * batch is at an end. I.e. do not call sane_cancel during the run but * as soon as you get a SANE_STATUS_NO_DOCS. * * From the SANE spec: * This function is used to immediately or as quickly as possible * cancel the currently pending operation of the device represented by * handle h. This function can be called at any time (as long as * handle h is a valid handle) but usually affects long-running * operations only (such as image is acquisition). It is safe to call * this function asynchronously (e.g., from within a signal handler). * It is important to note that completion of this operaton does not * imply that the currently pending operation has been cancelled. It * only guarantees that cancellation has been initiated. Cancellation * completes only when the cancelled call returns (typically with a * status value of SANE_STATUS_CANCELLED). Since the SANE API does * not require any other operations to be re-entrant, this implies * that a frontend must not call any other operation until the * cancelled operation has returned. */ void sane_cancel (SANE_Handle handle) { struct fujitsu * s = (struct fujitsu *) handle; DBG (10, "sane_cancel: start\n"); s->cancelled = 1; /* if there is no other running function to check, we do it */ if(!s->reading) check_for_cancel(s); DBG (10, "sane_cancel: finish\n"); } /* * Ends use of the scanner. * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is * presently active, a call to sane_cancel() is performed first. After * this function returns, handle h must not be used anymore. */ void sane_close (SANE_Handle handle) { struct fujitsu * s = (struct fujitsu *) handle; DBG (10, "sane_close: start\n"); /*clears any held scans*/ mode_select_buff(s); disconnect_fd(s); DBG (10, "sane_close: finish\n"); } static SANE_Status disconnect_fd (struct fujitsu *s) { DBG (10, "disconnect_fd: start\n"); if(s->fd > -1){ if (s->connection == CONNECTION_USB) { DBG (15, "disconnecting usb device\n"); sanei_usb_close (s->fd); } else if (s->connection == CONNECTION_SCSI) { DBG (15, "disconnecting scsi device\n"); sanei_scsi_close (s->fd); } s->fd = -1; } DBG (10, "disconnect_fd: finish\n"); return SANE_STATUS_GOOD; } /* * Terminates the backend. * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be * open (it is recommended to close device handles explicitly through * a call to sane_close(), but backends are required to release all * resources upon a call to this function). After this function * returns, no function other than sane_init() may be called * (regardless of the status value returned by sane_exit(). Neglecting * to call this function may result in some resources not being * released properly. */ void sane_exit (void) { struct fujitsu *dev, *next; DBG (10, "sane_exit: start\n"); for (dev = fujitsu_devList; dev; dev = next) { disconnect_fd(dev); next = dev->next; free (dev); } if (sane_devArray) free (sane_devArray); fujitsu_devList = NULL; sane_devArray = NULL; DBG (10, "sane_exit: finish\n"); } /* * @@ Section 6 - misc helper functions */ /* * Called by the SANE SCSI core and our usb code on device errors * parses the request sense return data buffer, * decides the best SANE_Status for the problem, produces debug msgs, * and copies the sense buffer into the scanner struct */ static SANE_Status sense_handler (int fd, unsigned char * sensed_data, void *arg) { struct fujitsu *s = arg; unsigned int sense = get_RS_sense_key (sensed_data); unsigned int asc = get_RS_ASC (sensed_data); unsigned int ascq = get_RS_ASCQ (sensed_data); DBG (5, "sense_handler: start\n"); /* kill compiler warning */ fd = fd; /* copy the rs return data into the scanner struct so that the caller can use it if he wants */ s->rs_info = get_RS_information (sensed_data); s->rs_eom = get_RS_EOM (sensed_data); s->rs_ili = get_RS_ILI (sensed_data); DBG (5, "Sense=%#02x, ASC=%#02x, ASCQ=%#02x, EOM=%d, ILI=%d, info=%#08lx\n", sense, asc, ascq, s->rs_eom, s->rs_ili, (unsigned long)s->rs_info); switch (sense) { case 0x0: if (0x80 == asc) { DBG (5, "No sense: hardware status bits?\n"); return SANE_STATUS_GOOD; } if (0x00 != asc) { DBG (5, "No sense: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if (0x00 != ascq) { DBG (5, "No sense: unknown ascq\n"); return SANE_STATUS_IO_ERROR; } /* ready, but short read */ if (s->rs_ili) { DBG (5, "No sense: ILI remainder:%lu\n",(unsigned long)s->rs_info); } /* ready, but end of paper */ if (s->rs_eom) { DBG (5, "No sense: EOM\n"); return SANE_STATUS_EOF; } DBG (5, "No sense: ready\n"); return SANE_STATUS_GOOD; case 0x2: if (0x00 != asc) { DBG (5, "Not ready: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if (0x00 != ascq) { DBG (5, "Not ready: unknown ascq\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "Not ready: busy\n"); return SANE_STATUS_DEVICE_BUSY; break; case 0x3: if (0x80 != asc) { DBG (5, "Medium error: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if (0x01 == ascq) { DBG (5, "Medium error: paper jam\n"); return SANE_STATUS_JAMMED; } if (0x02 == ascq) { DBG (5, "Medium error: cover open\n"); return SANE_STATUS_COVER_OPEN; } if (0x03 == ascq) { DBG (5, "Medium error: hopper empty\n"); return SANE_STATUS_NO_DOCS; } if (0x04 == ascq) { DBG (5, "Medium error: unusual paper\n"); return SANE_STATUS_JAMMED; } if (0x07 == ascq) { DBG (5, "Medium error: double feed\n"); return SANE_STATUS_JAMMED; } if (0x08 == ascq) { DBG (5, "Medium error: ADF setup error\n"); return SANE_STATUS_JAMMED; } if (0x09 == ascq) { DBG (5, "Medium error: Carrier sheet\n"); return SANE_STATUS_JAMMED; } if (0x10 == ascq) { DBG (5, "Medium error: no ink cartridge\n"); return SANE_STATUS_IO_ERROR; } if (0x13 == ascq) { DBG (5, "Medium error: temporary no data\n"); return SANE_STATUS_DEVICE_BUSY; } if (0x14 == ascq) { DBG (5, "Medium error: endorser error\n"); return SANE_STATUS_IO_ERROR; } if (0x20 == ascq) { DBG (5, "Medium error: Stop button\n"); return SANE_STATUS_NO_DOCS; } if (0x22 == ascq) { DBG (5, "Medium error: scanning halted\n"); return SANE_STATUS_CANCELLED; } if (0x30 == ascq) { DBG (5, "Medium error: Not enough paper\n"); return SANE_STATUS_NO_DOCS; } if (0x31 == ascq) { DBG (5, "Medium error: scanning disabled\n"); return SANE_STATUS_IO_ERROR; } if (0x32 == ascq) { DBG (5, "Medium error: scanning paused\n"); return SANE_STATUS_DEVICE_BUSY; } if (0x33 == ascq) { DBG (5, "Medium error: WiFi control error\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "Medium error: unknown ascq\n"); return SANE_STATUS_IO_ERROR; break; case 0x4: if (0x80 != asc && 0x44 != asc) { DBG (5, "Hardware error: unknown asc\n"); return SANE_STATUS_IO_ERROR; } if ((0x44 == asc) && (0x00 == ascq)) { DBG (5, "Hardware error: EEPROM error\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x01 == ascq)) { DBG (5, "Hardware error: FB motor fuse\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x02 == ascq)) { DBG (5, "Hardware error: heater fuse\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x03 == ascq)) { DBG (5, "Hardware error: lamp fuse\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x04 == ascq)) { DBG (5, "Hardware error: ADF motor fuse\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x05 == ascq)) { DBG (5, "Hardware error: mechanical error\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x06 == ascq)) { DBG (5, "Hardware error: optical error\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x07 == ascq)) { DBG (5, "Hardware error: Fan error\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x08 == ascq)) { DBG (5, "Hardware error: IPC option error\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x10 == ascq)) { DBG (5, "Hardware error: endorser error\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x11 == ascq)) { DBG (5, "Hardware error: endorser fuse\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x80 == ascq)) { DBG (5, "Hardware error: interface board timeout\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x81 == ascq)) { DBG (5, "Hardware error: interface board error 1\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x82 == ascq)) { DBG (5, "Hardware error: interface board error 2\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "Hardware error: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; case 0x5: if ((0x00 == asc) && (0x00 == ascq)) { DBG (5, "Illegal request: paper edge detected too soon\n"); return SANE_STATUS_INVAL; } if ((0x1a == asc) && (0x00 == ascq)) { DBG (5, "Illegal request: Parameter list error\n"); return SANE_STATUS_INVAL; } if ((0x20 == asc) && (0x00 == ascq)) { DBG (5, "Illegal request: invalid command\n"); return SANE_STATUS_INVAL; } if ((0x24 == asc) && (0x00 == ascq)) { DBG (5, "Illegal request: invalid CDB field\n"); return SANE_STATUS_INVAL; } if ((0x25 == asc) && (0x00 == ascq)) { DBG (5, "Illegal request: unsupported logical unit\n"); return SANE_STATUS_UNSUPPORTED; } if ((0x26 == asc) && (0x00 == ascq)) { DBG (5, "Illegal request: invalid field in parm list\n"); if (get_RS_additional_length(sensed_data) >= 0x0a) { DBG (5, "Offending byte is %#02x\n", get_RS_offending_byte(sensed_data)); /* move this to set_window() ? */ if (get_RS_offending_byte(sensed_data) >= 8) { DBG (5, "Window desc block? byte %#02x\n",get_RS_offending_byte(sensed_data)-8); } } return SANE_STATUS_INVAL; } if ((0x2C == asc) && (0x00 == ascq)) { DBG (5, "Illegal request: command sequence error\n"); return SANE_STATUS_INVAL; } if ((0x2C == asc) && (0x02 == ascq)) { DBG (5, "Illegal request: wrong window combination \n"); return SANE_STATUS_INVAL; } DBG (5, "Illegal request: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; case 0x6: if ((0x00 == asc) && (0x00 == ascq)) { DBG (5, "Unit attention: device reset\n"); return SANE_STATUS_GOOD; } if ((0x80 == asc) && (0x01 == ascq)) { DBG (5, "Unit attention: power saving\n"); return SANE_STATUS_GOOD; } DBG (5, "Unit attention: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; case 0xb: if ((0x43 == asc) && (0x00 == ascq)) { DBG (5, "Aborted command: message error\n"); return SANE_STATUS_IO_ERROR; } if ((0x45 == asc) && (0x00 == ascq)) { DBG (5, "Aborted command: select failure\n"); return SANE_STATUS_IO_ERROR; } if ((0x47 == asc) && (0x00 == ascq)) { DBG (5, "Aborted command: SCSI parity error\n"); return SANE_STATUS_IO_ERROR; } if ((0x48 == asc) && (0x00 == ascq)) { DBG (5, "Aborted command: initiator error message\n"); return SANE_STATUS_IO_ERROR; } if ((0x4e == asc) && (0x00 == ascq)) { DBG (5, "Aborted command: overlapped commands\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x01 == ascq)) { DBG (5, "Aborted command: image transfer error\n"); return SANE_STATUS_IO_ERROR; } if ((0x80 == asc) && (0x03 == ascq)) { DBG (5, "Aborted command: JPEG overflow error\n"); return SANE_STATUS_NO_MEM; } DBG (5, "Aborted command: unknown asc/ascq\n"); return SANE_STATUS_IO_ERROR; break; default: DBG (5, "Unknown Sense Code\n"); return SANE_STATUS_IO_ERROR; } DBG (5, "sense_handler: should never happen!\n"); return SANE_STATUS_IO_ERROR; } /* * take a bunch of pointers, send commands to scanner */ static SANE_Status do_cmd(struct fujitsu *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { /* unset the request sense vars first */ s->rs_info = 0; s->rs_ili = 0; s->rs_eom = 0; if (s->connection == CONNECTION_SCSI) { return do_scsi_cmd(s, runRS, shortTime, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen ); } if (s->connection == CONNECTION_USB) { return do_usb_cmd(s, runRS, shortTime, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen ); } return SANE_STATUS_INVAL; } SANE_Status do_scsi_cmd(struct fujitsu *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { int ret; /*shut up compiler*/ runRS=runRS; shortTime=shortTime; DBG(10, "do_scsi_cmd: start\n"); DBG(25, "cmd: writing %d bytes\n", (int)cmdLen); hexdump(30, "cmd: >>", cmdBuff, cmdLen); if(outBuff && outLen){ DBG(25, "out: writing %d bytes\n", (int)outLen); hexdump(30, "out: >>", outBuff, outLen); } if (inBuff && inLen){ DBG(25, "in: reading %d bytes\n", (int)*inLen); memset(inBuff,0,*inLen); } ret = sanei_scsi_cmd2(s->fd, cmdBuff, cmdLen, outBuff, outLen, inBuff, inLen); if(ret != SANE_STATUS_GOOD && ret != SANE_STATUS_EOF){ DBG(5,"do_scsi_cmd: return '%s'\n",sane_strstatus(ret)); return ret; } /* FIXME: should we look at s->rs_info here? */ if (inBuff && inLen){ hexdump(30, "in: <<", inBuff, *inLen); DBG(25, "in: read %d bytes\n", (int)*inLen); } DBG(10, "do_scsi_cmd: finish\n"); return ret; } SANE_Status do_usb_cmd(struct fujitsu *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ) { /*sanei_usb overwrites the transfer size, * so make some local copies */ size_t usb_cmdLen = USB_COMMAND_LEN; size_t usb_outLen = outLen; size_t usb_statLen = USB_STATUS_LEN; size_t askLen = 0; /*copy the callers buffs into larger, padded ones*/ unsigned char usb_cmdBuff[USB_COMMAND_LEN]; unsigned char usb_statBuff[USB_STATUS_LEN]; int cmdTime = USB_COMMAND_TIME; int outTime = USB_DATA_TIME; int inTime = USB_DATA_TIME; int statTime = USB_STATUS_TIME; int ret = 0; int ret2 = 0; DBG (10, "do_usb_cmd: start\n"); if(shortTime){ cmdTime = USB_COMMAND_TIME/60; outTime = USB_DATA_TIME/60; inTime = USB_DATA_TIME/60; statTime = USB_STATUS_TIME/60; } /* build a USB packet around the SCSI command */ memset(&usb_cmdBuff,0,USB_COMMAND_LEN); usb_cmdBuff[0] = USB_COMMAND_CODE; memcpy(&usb_cmdBuff[USB_COMMAND_OFFSET],cmdBuff,cmdLen); /* change timeout */ sanei_usb_set_timeout(cmdTime); /* write the command out */ DBG(25, "cmd: writing %d bytes, timeout %d\n", USB_COMMAND_LEN, cmdTime); hexdump(30, "cmd: >>", usb_cmdBuff, USB_COMMAND_LEN); ret = sanei_usb_write_bulk(s->fd, usb_cmdBuff, &usb_cmdLen); DBG(25, "cmd: wrote %d bytes, retVal %d\n", (int)usb_cmdLen, ret); if(ret == SANE_STATUS_EOF){ DBG(5,"cmd: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"cmd: return error '%s'\n",sane_strstatus(ret)); return ret; } if(usb_cmdLen != USB_COMMAND_LEN){ DBG(5,"cmd: wrong size %d/%d\n", USB_COMMAND_LEN, (int)usb_cmdLen); return SANE_STATUS_IO_ERROR; } /* this command has a write component, and a place to get it */ if(outBuff && outLen && outTime){ /* change timeout */ sanei_usb_set_timeout(outTime); DBG(25, "out: writing %d bytes, timeout %d\n", (int)outLen, outTime); hexdump(30, "out: >>", outBuff, outLen); ret = sanei_usb_write_bulk(s->fd, outBuff, &usb_outLen); DBG(25, "out: wrote %d bytes, retVal %d\n", (int)usb_outLen, ret); if(ret == SANE_STATUS_EOF){ DBG(5,"out: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret != SANE_STATUS_GOOD){ DBG(5,"out: return error '%s'\n",sane_strstatus(ret)); return ret; } if(usb_outLen != outLen){ DBG(5,"out: wrong size %d/%d\n", (int)outLen, (int)usb_outLen); return SANE_STATUS_IO_ERROR; } } /* this command has a read component, and a place to put it */ if(inBuff && inLen && inTime){ askLen = *inLen; memset(inBuff,0,askLen); /* change timeout */ sanei_usb_set_timeout(inTime); DBG(25, "in: reading %lu bytes, timeout %d\n", (unsigned long)askLen, inTime); ret = sanei_usb_read_bulk(s->fd, inBuff, inLen); DBG(25, "in: retVal %d\n", ret); if(ret == SANE_STATUS_EOF){ DBG(5,"in: got EOF, continuing\n"); ret = SANE_STATUS_GOOD; } if(ret != SANE_STATUS_GOOD){ DBG(5,"in: return error '%s'\n",sane_strstatus(ret)); return ret; } DBG(25, "in: read %lu bytes\n", (unsigned long)*inLen); if(*inLen){ hexdump(31, "in: <<", inBuff, *inLen); } if(*inLen && *inLen != askLen){ ret = SANE_STATUS_EOF; DBG(5,"in: short read, %lu/%lu\n", (unsigned long)*inLen,(unsigned long)askLen); } } /*gather the scsi status byte. use ret2 instead of ret for status*/ memset(&usb_statBuff,0,USB_STATUS_LEN); /* change timeout */ sanei_usb_set_timeout(statTime); DBG(25, "stat: reading %d bytes, timeout %d\n", USB_STATUS_LEN, statTime); ret2 = sanei_usb_read_bulk(s->fd, usb_statBuff, &usb_statLen); hexdump(30, "stat: <<", usb_statBuff, usb_statLen); DBG(25, "stat: read %d bytes, retVal %d\n", (int)usb_statLen, ret2); if(ret2 == SANE_STATUS_EOF){ DBG(5,"stat: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret2 != SANE_STATUS_GOOD){ DBG(5,"stat: return error '%s'\n",sane_strstatus(ret2)); return ret2; } if(usb_statLen != USB_STATUS_LEN){ DBG(5,"stat: wrong size %d/%d\n", USB_STATUS_LEN, (int)usb_statLen); return SANE_STATUS_IO_ERROR; } /* busy status */ if(usb_statBuff[USB_STATUS_OFFSET] == 8){ DBG(25,"stat: busy\n"); return SANE_STATUS_DEVICE_BUSY; } /* if there is a non-busy status >0, try to figure out why */ if(usb_statBuff[USB_STATUS_OFFSET] > 0){ DBG(25,"stat: value %d\n", usb_statBuff[USB_STATUS_OFFSET]); /* caller is interested in having RS run on errors */ if(runRS){ unsigned char rs_cmd[REQUEST_SENSE_len]; size_t rs_cmdLen = REQUEST_SENSE_len; unsigned char rs_in[RS_return_size]; size_t rs_inLen = RS_return_size; memset(rs_cmd,0,rs_cmdLen); set_SCSI_opcode(rs_cmd, REQUEST_SENSE_code); set_RS_return_size(rs_cmd, rs_inLen); DBG(25,"rs sub call >>\n"); ret2 = do_cmd( s,0,0, rs_cmd, rs_cmdLen, NULL,0, rs_in, &rs_inLen ); DBG(25,"rs sub call <<\n"); if(ret2 == SANE_STATUS_EOF){ DBG(5,"rs: got EOF, returning IO_ERROR\n"); return SANE_STATUS_IO_ERROR; } if(ret2 != SANE_STATUS_GOOD){ DBG(5,"rs: return error '%s'\n",sane_strstatus(ret2)); return ret2; } /* parse the rs data */ ret2 = sense_handler( 0, rs_in, (void *)s ); /* this was a short read, but the usb layer did not know */ if(s->rs_ili && inBuff && inLen && inTime){ *inLen = askLen - s->rs_info; DBG(5,"do_usb_cmd: short read via rs, %lu/%lu\n", (unsigned long)*inLen,(unsigned long)askLen); } return ret2; } else{ DBG(5,"do_usb_cmd: Not calling rs!\n"); return SANE_STATUS_IO_ERROR; } } DBG (10, "do_usb_cmd: finish\n"); return ret; } static SANE_Status wait_scanner(struct fujitsu *s) { SANE_Status ret = SANE_STATUS_GOOD; unsigned char cmd[TEST_UNIT_READY_len]; size_t cmdLen = TEST_UNIT_READY_len; DBG (10, "wait_scanner: start\n"); memset(cmd,0,cmdLen); set_SCSI_opcode(cmd,TEST_UNIT_READY_code); ret = do_cmd ( s, 0, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); if (ret != SANE_STATUS_GOOD) { DBG(5,"WARNING: Brain-dead scanner. Hitting with stick\n"); ret = do_cmd ( s, 0, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); } if (ret != SANE_STATUS_GOOD) { DBG(5,"WARNING: Brain-dead scanner. Hitting with stick again\n"); ret = do_cmd ( s, 0, 1, cmd, cmdLen, NULL, 0, NULL, NULL ); } if (ret != SANE_STATUS_GOOD) { DBG (5, "wait_scanner: error '%s'\n", sane_strstatus (ret)); } DBG (10, "wait_scanner: finish\n"); return ret; } /* certain options require the entire image to * be collected from the scanner before we can * tell the user the size of the image. */ static int must_fully_buffer(struct fujitsu *s) { if(s->hwdeskewcrop){ return 1; } if( (s->swdeskew || s->swdespeck || s->swcrop || s->swskip) && s->s_params.format != SANE_FRAME_JPEG ){ return 1; } return 0; } /* certain scanners require the mode of the * image to be changed in software. */ static int must_downsample(struct fujitsu *s) { if(s->s_mode != s->u_mode && s->compress != COMP_JPEG ){ return 1; } return 0; } /* s->page_width stores the user setting * for the paper width in adf. sometimes, * we need a value that differs from this * due to using FB or overscan. */ static int get_page_width(struct fujitsu *s) { int width = s->page_width + 2 * (s->os_x_basic*1200/s->basic_x_res); /* scanner max for fb */ if(s->source == SOURCE_FLATBED){ return s->max_x_fb; } /* current paper size for adf not overscan */ if(s->overscan != MSEL_ON){ return s->page_width; } /* cant overscan larger than scanner max */ if(width > s->max_x){ return s->max_x; } /* overscan adds a margin to both sides */ return width; } /* s->page_height stores the user setting * for the paper height in adf. sometimes, * we need a value that differs from this * due to using FB or overscan. */ static int get_page_height(struct fujitsu *s) { int height = s->page_height + 2 * (s->os_y_basic*1200/s->basic_y_res); /* scanner max for fb */ if(s->source == SOURCE_FLATBED){ return s->max_y_fb; } /* current paper size for adf not overscan */ if(s->overscan != MSEL_ON){ return s->page_height; } /* cant overscan larger than scanner max */ if(height > s->max_y){ return s->max_y; } /* overscan adds a margin to both sides */ return height; } /* scanners have two different possible IPC * modes, which enable a different series of * subordinate options. Rather than provide * the user with an option to pick the IPC * mode, we show them the subordinate ones, * and pick the right mode to match. */ static int get_ipc_mode(struct fujitsu *s) { if ( s->bp_filter || s->smoothing || s->gamma_curve || s->threshold_curve || s->threshold_white || s->noise_removal || s->matrix_5 || s->matrix_4 || s->matrix_3 || s->matrix_2 ) return WD_ipc_DTC; if(s->variance) return WD_ipc_SDTC; /* special case: 0 threshold should activate IPC */ if(!s->threshold){ if(s->has_sdtc) return WD_ipc_SDTC; if(s->has_dtc) return WD_ipc_DTC; } return WD_ipc_DEFAULT; } /* s->max_y gives the maximum height of paper which can be scanned * this actually varies by resolution, so a helper to change it */ static int set_max_y(struct fujitsu *s) { int i; for(i=0;i<4;i++){ if(!s->max_y_by_res[i].res) break; if(s->resolution_x <= s->max_y_by_res[i].res){ s->max_y = s->max_y_by_res[i].len; } } return s->max_y; } /** * Convenience method to determine longest string size in a list. */ static size_t maxStringSize (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /* * Prints a hex dump of the given buffer onto the debug output stream. */ static void hexdump (int level, char *comment, unsigned char *p, int l) { int i; char line[70]; /* 'xxx: xx xx ... xx xx abc */ char *hex = line+4; char *bin = line+53; if(DBG_LEVEL < level) return; DBG (level, "%s\n", comment); for (i = 0; i < l; i++, p++) { /* at start of line */ if ((i % 16) == 0) { /* not at start of first line, print current, reset */ if (i) { DBG (level, "%s\n", line); } memset(line,0x20,69); line[69] = 0; hex = line + 4; bin = line + 53; sprintf (line, "%3.3x:", i); } /* the hex section */ sprintf (hex, " %2.2x", *p); hex += 3; *hex = ' '; /* the char section */ if(*p >= 0x20 && *p <= 0x7e){ *bin=*p; } else{ *bin='.'; } bin++; } /* print last (partial) line */ if (i) DBG (level, "%s\n", line); } /** * An advanced method we don't support but have to define. */ SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) { DBG (10, "sane_set_io_mode\n"); DBG (15, "%d %p\n", non_blocking, h); return SANE_STATUS_UNSUPPORTED; } /** * An advanced method we don't support but have to define. */ SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) { DBG (10, "sane_get_select_fd\n"); DBG (15, "%p %d\n", h, *fdp); return SANE_STATUS_UNSUPPORTED; } /* * @@ Section 7 - Image processing functions */ /* Look in image for likely upper and left paper edges, then rotate * image so that upper left corner of paper is upper left of image. * FIXME: should we do this before we binarize instead of after? */ static SANE_Status buffer_deskew(struct fujitsu *s, int side) { SANE_Status ret = SANE_STATUS_GOOD; int bg_color = 0xd6; DBG (10, "buffer_deskew: start\n"); /*only find skew on first image from a page, or if first image had error */ if(s->side == SIDE_FRONT || s->source == SOURCE_ADF_BACK || s->deskew_stat){ s->deskew_stat = sanei_magic_findSkew( &s->s_params,s->buffers[side],s->resolution_x,s->resolution_y, &s->deskew_vals[0],&s->deskew_vals[1],&s->deskew_slope); if(s->deskew_stat){ DBG (5, "buffer_deskew: bad findSkew, bailing\n"); goto cleanup; } } /* backside images can use a 'flipped' version of frontside data */ else{ s->deskew_slope *= -1; s->deskew_vals[0] = s->s_params.pixels_per_line - s->deskew_vals[0]; } /* tweak the bg color based on scanner settings */ if(s->s_mode == MODE_HALFTONE || s->s_mode == MODE_LINEART){ if(s->bg_color == COLOR_BLACK || s->hwdeskewcrop || s->overscan) bg_color = 0xff; else bg_color = 0; } else if(s->bg_color == COLOR_BLACK || s->hwdeskewcrop || s->overscan) bg_color = 0; ret = sanei_magic_rotate(&s->s_params,s->buffers[side], s->deskew_vals[0],s->deskew_vals[1],s->deskew_slope,bg_color); if(ret){ DBG(5,"buffer_deskew: rotate error: %d",ret); ret = SANE_STATUS_GOOD; goto cleanup; } cleanup: DBG (10, "buffer_deskew: finish\n"); return ret; } /* Look in image for likely left/right/bottom paper edges, then crop image. * Does not attempt to rotate the image, that should be done first. * FIXME: should we do this before we binarize instead of after? */ static SANE_Status buffer_crop(struct fujitsu *s, int side) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "buffer_crop: start\n"); ret = sanei_magic_findEdges( &s->s_params,s->buffers[side],s->resolution_x,s->resolution_y, &s->crop_vals[0],&s->crop_vals[1],&s->crop_vals[2],&s->crop_vals[3]); if(ret){ DBG (5, "buffer_crop: bad edges, bailing\n"); ret = SANE_STATUS_GOOD; goto cleanup; } DBG (15, "buffer_crop: t:%d b:%d l:%d r:%d\n", s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); /* if we will later binarize this image, make sure the width * is a multiple of 8 pixels, by adjusting the right side */ if ( must_downsample(s) && s->u_mode < MODE_GRAYSCALE ){ s->crop_vals[3] -= (s->crop_vals[3]-s->crop_vals[2]) % 8; } /* now crop the image */ ret = sanei_magic_crop(&s->s_params,s->buffers[side], s->crop_vals[0],s->crop_vals[1],s->crop_vals[2],s->crop_vals[3]); if(ret){ DBG (5, "buffer_crop: bad crop, bailing\n"); ret = SANE_STATUS_GOOD; goto cleanup; } /* need to update user with new size */ update_u_params(s); /* update image size counter to new, smaller size */ s->bytes_rx[side] = s->s_params.lines * s->s_params.bytes_per_line; s->buff_rx[side] = s->bytes_rx[side]; cleanup: DBG (10, "buffer_crop: finish\n"); return ret; } /* Look in image for disconnected 'spots' of the requested size. * Replace the spots with the average color of the surrounding pixels. * FIXME: should we do this before we binarize instead of after? */ static SANE_Status buffer_despeck(struct fujitsu *s, int side) { SANE_Status ret = SANE_STATUS_GOOD; DBG (10, "buffer_despeck: start\n"); ret = sanei_magic_despeck(&s->s_params,s->buffers[side],s->swdespeck); if(ret){ DBG (5, "buffer_despeck: bad despeck, bailing\n"); ret = SANE_STATUS_GOOD; goto cleanup; } cleanup: DBG (10, "buffer_despeck: finish\n"); return ret; } /* Look if image has too few dark pixels.*/ static int buffer_isblank(struct fujitsu *s, int side) { SANE_Status ret = SANE_STATUS_GOOD; int status = 0; DBG (10, "buffer_isblank: start\n"); ret = sanei_magic_isBlank2(&s->s_params, s->buffers[side], s->resolution_x, s->resolution_y, s->swskip); if(ret == SANE_STATUS_NO_DOCS){ DBG (5, "buffer_isblank: blank!\n"); status = 1; } else if(ret){ DBG (5, "buffer_isblank: error %d\n",ret); } DBG (10, "buffer_isblank: finished\n"); return status; } sane-backends-1.0.27/backend/hp3900_rts8822.c0000664000175000017500000132556712775312261015145 00000000000000/* HP Scanjet 3900 series - RTS8822 Core Copyright (C) 2005-2013 Jonathan Bravo Lopez This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* This code is still a bit ugly due to it's the result of applying reverse engineering techniques to windows driver. So at this moment what you see is exactly what windows driver does. And so many global vars exist that will be erased when driver is entirely debugged. There are some variables with unknown purpose. So they have no meaning name in form v+address. I hope to change their names when driver is debugged completely. */ #ifndef RTS8822_CORE #define RTS8822_CORE #define GetTickCount() (time(0) * 1000) #define min(A,B) (((A)<(B)) ? (A) : (B)) #define max(A,B) (((A)>(B)) ? (A) : (B)) #define PIXEL_TO_MM(_pixel_, _dpi_) ((_pixel_) * 25.4 / (_dpi_)) #define MM_TO_PIXEL(_mm_, _dpi_) ((_mm_) * (_dpi_) / 25.4) #include #include #include /* bzero() */ #include /* clock() */ #include /* truncf() */ #include /* tolower() */ #include /* usleep() */ #include #include "hp3900_types.c" #include "hp3900_debug.c" #include "hp3900_config.c" #include "hp3900_usb.c" /*-------------------- Exported function headers --------------------*/ #ifdef developing static SANE_Int hp4370_prueba (struct st_device *dev); static void prueba (SANE_Byte * a); void shadingtest1 (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib); static SANE_Int Calib_test (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg); static SANE_Int Calib_BlackShading_jkd (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg); #endif /*static void show_diff(struct st_device *dev, SANE_Byte *original);*/ /* functions to allocate and free space for a device */ static struct st_device *RTS_Alloc (void); static void RTS_Free (struct st_device *dev); /* Scanner level commands */ static SANE_Int RTS_Scanner_Init (struct st_device *dev); static SANE_Int RTS_Scanner_SetParams (struct st_device *dev, struct params *param); static SANE_Int RTS_Scanner_StartScan (struct st_device *dev); static void RTS_Scanner_StopScan (struct st_device *dev, SANE_Int wait); static void RTS_Scanner_End (struct st_device *dev); /* loading configuration functions */ static SANE_Int Load_Buttons (struct st_device *dev); static SANE_Int Load_Chipset (struct st_device *dev); static SANE_Int Load_Config (struct st_device *dev); static SANE_Int Load_Constrains (struct st_device *dev); static SANE_Int Load_Motor (struct st_device *dev); static SANE_Int Load_MotorCurves (struct st_device *dev); static SANE_Int Load_Motormoves (struct st_device *dev); static SANE_Int Load_Scanmodes (struct st_device *dev); static SANE_Int Load_Sensor (struct st_device *dev); static SANE_Int Load_Timings (struct st_device *dev); /* freeing configuration functions */ static void Free_Buttons (struct st_device *dev); static void Free_Chipset (struct st_device *dev); static void Free_Config (struct st_device *dev); static void Free_Constrains (struct st_device *dev); static void Free_Motor (struct st_device *dev); static void Free_MotorCurves (struct st_device *dev); static void Free_Motormoves (struct st_device *dev); static void Free_Scanmodes (struct st_device *dev); static void Free_Sensor (struct st_device *dev); static void Free_Timings (struct st_device *dev); static void Free_Vars (void); /* Functions to manage data */ static SANE_Byte data_bitget (SANE_Byte * address, SANE_Int mask); static void data_bitset (SANE_Byte * address, SANE_Int mask, SANE_Byte data); static SANE_Int data_lsb_get (SANE_Byte * address, SANE_Int size); static void data_lsb_set (SANE_Byte * address, SANE_Int data, SANE_Int size); static void data_msb_set (SANE_Byte * address, SANE_Int data, SANE_Int size); static void data_wide_bitset (SANE_Byte * address, SANE_Int mask, SANE_Int data); static SANE_Int data_swap_endianess (SANE_Int address, SANE_Int size); static SANE_Int Device_get (SANE_Int product, SANE_Int vendor); /* Chipset related commands */ static SANE_Int Chipset_ID (struct st_device *dev); static SANE_Int Chipset_Name (struct st_device *dev, char *name, SANE_Int size); static SANE_Int Chipset_Reset (struct st_device *dev); /* Initializing functions */ static SANE_Int Init_Registers (struct st_device *dev); static SANE_Int Init_USBData (struct st_device *dev); static SANE_Int Init_Vars (void); /* scanmode functions */ static SANE_Int Scanmode_fitres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, SANE_Int resolution); static SANE_Int Scanmode_maxres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode); static SANE_Int Scanmode_minres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode); /* Chipset management useful commands*/ static SANE_Int RTS_USBType (struct st_device *dev); static SANE_Byte RTS_Sensor_Type (USB_Handle usb_handle); static void RTS_DebugInit (void); static SANE_Int RTS_Enable_CCD (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels); /* DMA management commands */ static SANE_Int RTS_DMA_Cancel (struct st_device *dev); static SANE_Int RTS_DMA_CheckType (struct st_device *dev, SANE_Byte * Regs); static SANE_Int RTS_DMA_Enable_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int size, SANE_Int options); static SANE_Int RTS_DMA_Enable_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int size, SANE_Int options); static SANE_Int RTS_DMA_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int options, SANE_Int size, SANE_Byte * buffer); static SANE_Int RTS_DMA_Reset (struct st_device *dev); static SANE_Int RTS_DMA_SetType (struct st_device *dev, SANE_Byte * Regs, SANE_Byte ramtype); static SANE_Int RTS_DMA_WaitReady (struct st_device *dev, SANE_Int msecs); static SANE_Int RTS_DMA_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int options, SANE_Int size, SANE_Byte * buffer); /* EEPROM management commands */ static SANE_Int RTS_EEPROM_ReadByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data); static SANE_Int RTS_EEPROM_ReadInteger (USB_Handle usb_handle, SANE_Int address, SANE_Int * data); static SANE_Int RTS_EEPROM_ReadWord (USB_Handle usb_handle, SANE_Int address, SANE_Int * data); static SANE_Int RTS_EEPROM_WriteBuffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data, SANE_Int size); static SANE_Int RTS_EEPROM_WriteByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data); static SANE_Int RTS_EEPROM_WriteInteger (USB_Handle usb_handle, SANE_Int address, SANE_Int data); static SANE_Int RTS_EEPROM_WriteWord (USB_Handle usb_handle, SANE_Int address, SANE_Int data); static SANE_Int RTS_Execute (struct st_device *dev); static SANE_Int RTS_Warm_Reset (struct st_device *dev); static SANE_Byte RTS_IsExecuting (struct st_device *dev, SANE_Byte * Regs); static SANE_Int RTS_GetScanmode (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, SANE_Int resolution); static SANE_Int RTS_GetImage (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_gain_offset *gain_offset, SANE_Byte * buffer, struct st_calibration *myCalib, SANE_Int options, SANE_Int gainmode); static SANE_Int RTS_GetImage_GetBuffer (struct st_device *dev, double dSize, SANE_Byte * buffer, double *transferred); static SANE_Int RTS_GetImage_Read (struct st_device *dev, SANE_Byte * buffer, struct st_scanparams *myvar, struct st_hwdconfig *hwdcfg); static SANE_Int RTS_isTmaAttached (struct st_device *dev); /* functions to wait for a process tp finish */ static SANE_Int RTS_WaitInitEnd (struct st_device *dev, SANE_Int msecs); static SANE_Int RTS_WaitScanEnd (struct st_device *dev, SANE_Int msecs); /* functions to read/write control registers */ static SANE_Int RTS_ReadRegs (USB_Handle usb_handle, SANE_Byte * buffer); static SANE_Int RTS_WriteRegs (USB_Handle usb_handle, SANE_Byte * buffer); /* functions to manage the scan counter */ static SANE_Int RTS_ScanCounter_Inc (struct st_device *dev); static SANE_Int RTS_ScanCounter_Get (struct st_device *dev); /* functions to setup control registers */ static SANE_Int RTS_Setup (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myvar, struct st_hwdconfig *hwdcfg, struct st_gain_offset *gain_offset); static void RTS_Setup_Arrangeline (struct st_device *dev, struct st_hwdconfig *hwdcfg, SANE_Int colormode); static void RTS_Setup_Channels (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int mycolormode); static void RTS_Setup_Coords (SANE_Byte * Regs, SANE_Int iLeft, SANE_Int iTop, SANE_Int width, SANE_Int height); static SANE_Int RTS_Setup_Depth (SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int mycolormode); static void RTS_Setup_Exposure_Times (SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_scanmode *sm); static void RTS_Setup_GainOffset (SANE_Byte * Regs, struct st_gain_offset *gain_offset); static void RTS_Setup_Gamma (SANE_Byte * Regs, struct st_hwdconfig *lowcfg); static SANE_Int RTS_Setup_Line_Distances (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, SANE_Int mycolormode, SANE_Int arrangeline); static SANE_Int RTS_Setup_Motor (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myvar, SANE_Int somevalue); static void RTS_Setup_RefVoltages (struct st_device *dev, SANE_Byte * Regs); static void RTS_Setup_SensorTiming (struct st_device *dev, SANE_Int mytiming, SANE_Byte * Regs); static void RTS_Setup_Shading (SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, SANE_Int bytes_per_line); static SANE_Int Scan_Start (struct st_device *dev); static void SetLock (USB_Handle usb_handle, SANE_Byte * Regs, SANE_Byte Enable); static SANE_Int fn3330 (struct st_device *dev, SANE_Byte * Regs, struct st_cal2 *calbuffers, SANE_Int sensorchannelcolor, SANE_Int * tablepos, SANE_Int data); static SANE_Int fn3560 (USHORT * table, struct st_cal2 *calbuffers, SANE_Int * tablepos); static SANE_Int fn3730 (struct st_device *dev, struct st_cal2 *calbuffers, SANE_Byte * Regs, USHORT * table, SANE_Int sensorchannelcolor, SANE_Int data); static SANE_Int Reading_CreateBuffers (struct st_device *dev); static SANE_Int Reading_DestroyBuffers (struct st_device *dev); static SANE_Int Reading_BufferSize_Get (struct st_device *dev, SANE_Byte channels_per_dot, SANE_Int channel_size); static SANE_Int Reading_BufferSize_Notify (struct st_device *dev, SANE_Int data, SANE_Int size); static SANE_Int Reading_Wait (struct st_device *dev, SANE_Byte Channels_per_dot, SANE_Byte Channel_size, SANE_Int size, SANE_Int * last_amount, SANE_Int seconds, SANE_Byte op); static SANE_Int Read_Image (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transferred); static SANE_Int Read_ResizeBlock (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred); static SANE_Int Read_Block (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transferred); static SANE_Int Read_NonColor_Block (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Byte ColorMode, SANE_Int * transferred); /* Ref functions */ static SANE_Int Refs_Analyze_Pattern (struct st_scanparams *scancfg, SANE_Byte * scanned_pattern, SANE_Int * ler1, SANE_Int ler1order, SANE_Int * ser1, SANE_Int ser1order); static SANE_Int Refs_Counter_Inc (struct st_device *dev); static SANE_Byte Refs_Counter_Load (struct st_device *dev); static SANE_Int Refs_Counter_Save (struct st_device *dev, SANE_Byte data); static SANE_Int Refs_Detect (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution_x, SANE_Int resolution_y, SANE_Int * x, SANE_Int * y); static SANE_Int Refs_Load (struct st_device *dev, SANE_Int * x, SANE_Int * y); static SANE_Int Refs_Save (struct st_device *dev, SANE_Int left_leading, SANE_Int start_pos); static SANE_Int Refs_Set (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myscan); /* Coordinates' constrains functions */ static SANE_Int Constrains_Check (struct st_device *dev, SANE_Int Resolution, SANE_Int scantype, struct st_coords *mycoords); static struct st_coords *Constrains_Get (struct st_device *dev, SANE_Byte scantype); /* Gain and offset functions */ static SANE_Int GainOffset_Clear (struct st_device *dev); static SANE_Int GainOffset_Get (struct st_device *dev); static SANE_Int GainOffset_Save (struct st_device *dev, SANE_Int * offset, SANE_Byte * gain); static SANE_Int GainOffset_Counter_Inc (struct st_device *dev, SANE_Int * arg1); static SANE_Byte GainOffset_Counter_Load (struct st_device *dev); static SANE_Int GainOffset_Counter_Save (struct st_device *dev, SANE_Byte data); /* Gamma functions*/ static SANE_Int Gamma_AllocTable (SANE_Byte * table); static SANE_Int Gamma_Apply (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, struct st_gammatables *mygamma); static void Gamma_FreeTables (void); static SANE_Int Gamma_SendTables (struct st_device *dev, SANE_Byte * Regs, SANE_Byte * gammatable, SANE_Int size); static SANE_Int Gamma_GetTables (struct st_device *dev, SANE_Byte * Gamma_buffer); /* Lamp functions */ static SANE_Byte Lamp_GetGainMode (struct st_device *dev, SANE_Int resolution, SANE_Byte scantype); static void Lamp_SetGainMode (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution, SANE_Byte gainmode); static SANE_Int Lamp_PWM_DutyCycle_Get (struct st_device *dev, SANE_Int * data); static SANE_Int Lamp_PWM_DutyCycle_Set (struct st_device *dev, SANE_Int duty_cycle); static SANE_Int Lamp_PWM_Setup (struct st_device *dev, SANE_Int lamp); static SANE_Int Lamp_PWM_use (struct st_device *dev, SANE_Int enable); static SANE_Int Lamp_PWM_CheckStable (struct st_device *dev, SANE_Int resolution, SANE_Int lamp); static SANE_Int Lamp_PWM_Save (struct st_device *dev, SANE_Int fixedpwm); static SANE_Int Lamp_PWM_SaveStatus (struct st_device *dev, SANE_Byte status); static SANE_Int Lamp_Status_Get (struct st_device *dev, SANE_Byte * flb_lamp, SANE_Byte * tma_lamp); static SANE_Int Lamp_Status_Set (struct st_device *dev, SANE_Byte * Regs, SANE_Int turn_on, SANE_Int lamp); static SANE_Int Lamp_Status_Timer_Set (struct st_device *dev, SANE_Int minutes); static SANE_Int Lamp_Warmup (struct st_device *dev, SANE_Byte * Regs, SANE_Int lamp, SANE_Int resolution); /* Head related functions */ static SANE_Int Head_IsAtHome (struct st_device *dev, SANE_Byte * Regs); static SANE_Int Head_ParkHome (struct st_device *dev, SANE_Int bWait, SANE_Int movement); static SANE_Int Head_Relocate (struct st_device *dev, SANE_Int speed, SANE_Int direction, SANE_Int ypos); /* Motor functions */ static SANE_Byte *Motor_AddStep (SANE_Byte * steps, SANE_Int * bwriten, SANE_Int step); static SANE_Int Motor_Change (struct st_device *dev, SANE_Byte * buffer, SANE_Byte value); static SANE_Int Motor_GetFromResolution (SANE_Int resolution); static SANE_Int Motor_Move (struct st_device *dev, SANE_Byte * Regs, struct st_motormove *mymotor, struct st_motorpos *mtrpos); static void Motor_Release (struct st_device *dev); static SANE_Int Motor_Setup_Steps (struct st_device *dev, SANE_Byte * Regs, SANE_Int mysetting); static SANE_Int Motor_Curve_Equal (struct st_device *dev, SANE_Int motorsetting, SANE_Int direction, SANE_Int curve1, SANE_Int curve2); static void Motor_Curve_Free (struct st_motorcurve **motorcurves, SANE_Int * mtc_count); static struct st_curve *Motor_Curve_Get (struct st_device *dev, SANE_Int motorcurve, SANE_Int direction, SANE_Int itype); static struct st_motorcurve **Motor_Curve_Parse (SANE_Int * mtc_count, SANE_Int * buffer); /* Functions to arrange scanned lines */ static SANE_Int Arrange_Colour (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred); static SANE_Int Arrange_Compose (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred); static SANE_Int Arrange_NonColour (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred); /* Composing RGB triplet functions */ static void Triplet_Gray (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * buffer, SANE_Int channels_count); static void Triplet_Lineart (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * buffer, SANE_Int channels_count); static void Triplet_Compose_Order (struct st_device *dev, SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int dots); static void Triplet_Compose_HRes (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * pPointer3, SANE_Byte * pPointer4, SANE_Byte * pPointer5, SANE_Byte * pPointer6, SANE_Byte * buffer, SANE_Int Width); static void Triplet_Compose_LRes (SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int dots); static void Triplet_Colour_Order (struct st_device *dev, SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int Width); static void Triplet_Colour_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, SANE_Byte * pBlue1, SANE_Byte * pRed2, SANE_Byte * pGreen2, SANE_Byte * pBlue2, SANE_Byte * buffer, SANE_Int Width); static void Triplet_Colour_LRes (SANE_Int Width, SANE_Byte * Buffer, SANE_Byte * pChannel1, SANE_Byte * pChannel2, SANE_Byte * pChannel3); /* Timing functions */ static SANE_Int Timing_SetLinearImageSensorClock (SANE_Byte * Regs, struct st_cph *cph); /* Functions used to resize retrieved image */ static SANE_Int Resize_Start (struct st_device *dev, SANE_Int * transferred); static SANE_Int Resize_CreateBuffers (struct st_device *dev, SANE_Int size1, SANE_Int size2, SANE_Int size3); static SANE_Int Resize_DestroyBuffers (struct st_device *dev); static SANE_Int Resize_Increase (SANE_Byte * to_buffer, SANE_Int to_resolution, SANE_Int to_width, SANE_Byte * from_buffer, SANE_Int from_resolution, SANE_Int from_width, SANE_Int myresize_mode); static SANE_Int Resize_Decrease (SANE_Byte * to_buffer, SANE_Int to_resolution, SANE_Int to_width, SANE_Byte * from_buffer, SANE_Int from_resolution, SANE_Int from_width, SANE_Int myresize_mode); /* Scanner buttons support */ static SANE_Int Buttons_Count (struct st_device *dev); static SANE_Int Buttons_Enable (struct st_device *dev); static SANE_Int Buttons_Order (struct st_device *dev, SANE_Int mask); static SANE_Int Buttons_Status (struct st_device *dev); static SANE_Int Buttons_Released (struct st_device *dev); /* Calibration functions */ static SANE_Int Calib_CreateBuffers (struct st_device *dev, struct st_calibration *buffer, SANE_Int my14b4); static SANE_Int Calib_CreateFixedBuffers (void); static void Calib_FreeBuffers (struct st_calibration *caltables); static void Calib_LoadCut (struct st_device *dev, struct st_scanparams *scancfg, SANE_Int scantype, struct st_calibration_config *calibcfg); static SANE_Int Calib_AdcGain (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int arg2, SANE_Int gainmode); static SANE_Int Calib_AdcOffsetRT (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int value); static SANE_Int Calib_BlackShading (struct st_device *dev, struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode); static SANE_Int Calib_BWShading (struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode); static SANE_Int Calib_WhiteShading_3 (struct st_device *dev, struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode); static void Calibrate_Free (struct st_cal2 *calbuffers); static SANE_Int Calibrate_Malloc (struct st_cal2 *calbuffers, SANE_Byte * Regs, struct st_calibration *myCalib, SANE_Int somelength); static SANE_Int Calib_ReadTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, SANE_Int data); static SANE_Int Calib_WriteTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, SANE_Int data); static SANE_Int Calib_LoadConfig (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int scantype, SANE_Int resolution, SANE_Int bitmode); static SANE_Int Calib_PAGain (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int gainmode); static SANE_Int Calibration (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_calibration *myCalib, SANE_Int value); /* function for white shading correction */ static SANE_Int WShading_Calibrate (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg); static void WShading_Emulate (SANE_Byte * buffer, SANE_Int * chnptr, SANE_Int size, SANE_Int depth); /* functions for shading calibration */ static SANE_Int Shading_apply (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myvar, struct st_calibration *myCalib); static SANE_Int Shading_black_apply (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels, struct st_calibration *myCalib, struct st_cal2 *calbuffers); static SANE_Int Shading_white_apply (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels, struct st_calibration *myCalib, struct st_cal2 *calbuffers); /* Spread-Spectrum Clock Generator functions */ static SANE_Int SSCG_Enable (struct st_device *dev); static void Split_into_12bit_channels (SANE_Byte * destino, SANE_Byte * fuente, SANE_Int size); static SANE_Int Scan_Read_BufferA (struct st_device *dev, SANE_Int buffer_size, SANE_Int arg2, SANE_Byte * pBuffer, SANE_Int * bytes_transfered); static SANE_Int Bulk_Operation (struct st_device *dev, SANE_Byte op, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transfered); static SANE_Int Get_PAG_Value (SANE_Byte scantype, SANE_Byte color); static SANE_Int GetOneLineInfo (struct st_device *dev, SANE_Int resolution, SANE_Int * maximus, SANE_Int * minimus, double *average); static SANE_Int Load_StripCoords (SANE_Int scantype, SANE_Int * ypos, SANE_Int * xpos); /*static SANE_Int Free_Fixed_CalBuffer(void);*/ static SANE_Int SetMultiExposure (struct st_device *dev, SANE_Byte * Regs); static void Set_E950_Mode (struct st_device *dev, SANE_Byte mode); static SANE_Int LoadImagingParams (struct st_device *dev, SANE_Int inifile); static SANE_Int SetScanParams (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg); static SANE_Int IsScannerLinked (struct st_device *dev); static SANE_Int Read_FE3E (struct st_device *dev, SANE_Byte * destino); static double get_shrd (double value, SANE_Int desp); static char get_byte (double value); /*static SANE_Int RTS8822_GetRegisters(SANE_Byte *buffer);*/ /* ----------------- Implementation ------------------*/ static void RTS_Free (struct st_device *dev) { /* this function frees space of devices's variable */ if (dev != NULL) { /* next function shouldn't be necessary but I can NOT assure that other programmers will call Free_Config before this function */ Free_Config (dev); if (dev->init_regs != NULL) free (dev->init_regs); if (dev->Resize != NULL) free (dev->Resize); if (dev->Reading != NULL) free (dev->Reading); if (dev->scanning != NULL) free (dev->scanning); if (dev->status != NULL) free (dev->status); free (dev); } } static struct st_device * RTS_Alloc () { /* this function allocates space for device's variable */ struct st_device *dev = NULL; dev = malloc (sizeof (struct st_device)); if (dev != NULL) { SANE_Int rst = OK; bzero (dev, sizeof (struct st_device)); /* initial registers */ dev->init_regs = malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN); if (dev->init_regs != NULL) bzero (dev->init_regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); else rst = ERROR; if (rst == OK) { dev->scanning = malloc (sizeof (struct st_scanning)); if (dev->scanning != NULL) bzero (dev->scanning, sizeof (struct st_scanning)); else rst = ERROR; } if (rst == OK) { dev->Reading = malloc (sizeof (struct st_readimage)); if (dev->Reading != NULL) bzero (dev->Reading, sizeof (struct st_readimage)); else rst = ERROR; } if (rst == OK) { dev->Resize = malloc (sizeof (struct st_resize)); if (dev->Resize != NULL) bzero (dev->Resize, sizeof (struct st_resize)); else rst = ERROR; } if (rst == OK) { dev->status = malloc (sizeof (struct st_status)); if (dev->status != NULL) bzero (dev->status, sizeof (struct st_status)); else rst = ERROR; } /* if something fails, free space */ if (rst != OK) { RTS_Free (dev); dev = NULL; } } return dev; } static void RTS_Scanner_End (struct st_device *dev) { Gamma_FreeTables (); Free_Config (dev); Free_Vars (); } static SANE_Int Device_get (SANE_Int product, SANE_Int vendor) { return cfg_device_get (product, vendor); } static SANE_Int RTS_Scanner_Init (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "> RTS_Scanner_Init:\n"); DBG (DBG_FNC, "> Backend version: %s\n", BACKEND_VRSN); rst = ERROR; /* gets usb type of this scanner if it's not already set by user */ if (RTS_Debug->usbtype == -1) RTS_Debug->usbtype = RTS_USBType (dev); if (RTS_Debug->usbtype != ERROR) { DBG (DBG_FNC, " -> Chipset model ID: %i\n", Chipset_ID (dev)); Chipset_Reset (dev); if (Load_Config (dev) == OK) { if (IsScannerLinked (dev) == OK) { Set_E950_Mode (dev, 0); Gamma_AllocTable (NULL); rst = OK; } else Free_Config (dev); } } return rst; } static SANE_Int RTS_WriteRegs (USB_Handle usb_handle, SANE_Byte * buffer) { SANE_Int rst = ERROR; if (buffer != NULL) rst = Write_Buffer (usb_handle, 0xe800, buffer, RT_BUFFER_LEN * sizeof (SANE_Byte)); return rst; } static SANE_Int RTS_ReadRegs (USB_Handle usb_handle, SANE_Byte * buffer) { SANE_Int rst = ERROR; if (buffer != NULL) rst = Read_Buffer (usb_handle, 0xe800, buffer, RT_BUFFER_LEN * sizeof (SANE_Byte)); return rst; } static void SetLock (USB_Handle usb_handle, SANE_Byte * Regs, SANE_Byte Enable) { SANE_Byte lock; DBG (DBG_FNC, "+ SetLock(*Regs, Enable=%i):\n", Enable); if (Regs == NULL) { if (Read_Byte (usb_handle, 0xee00, &lock) != OK) lock = 0; } else lock = Regs[0x600]; if (Enable == FALSE) lock &= 0xfb; else lock |= 4; if (Regs != NULL) Regs[0x600] = lock; Write_Byte (usb_handle, 0xee00, lock); DBG (DBG_FNC, "- SetLock\n"); } static void Set_E950_Mode (struct st_device *dev, SANE_Byte mode) { SANE_Int data; DBG (DBG_FNC, "+ Set_E950_Mode(mode=%i):\n", mode); if (Read_Word (dev->usb_handle, 0xe950, &data) == OK) { data = (mode == 0) ? data & 0xffbf : data | 0x40; Write_Word (dev->usb_handle, 0xe950, data); } DBG (DBG_FNC, "- Set_E950_Mode\n"); } static struct st_curve * Motor_Curve_Get (struct st_device *dev, SANE_Int motorcurve, SANE_Int direction, SANE_Int itype) { struct st_curve *rst = NULL; if (dev != NULL) { if ((dev->mtrsetting != NULL) && (motorcurve < dev->mtrsetting_count)) { struct st_motorcurve *mtc = dev->mtrsetting[motorcurve]; if (mtc != NULL) { if ((mtc->curve != NULL) && (mtc->curve_count > 0)) { struct st_curve *crv; SANE_Int a = 0; while (a < mtc->curve_count) { /* get each curve */ crv = mtc->curve[a]; if (crv != NULL) { /* check direction and type */ if ((crv->crv_speed == direction) && (crv->crv_type == itype)) { /* found ! */ rst = crv; break; } } a++; } } } } } return rst; } static SANE_Int Motor_Curve_Equal (struct st_device *dev, SANE_Int motorsetting, SANE_Int direction, SANE_Int curve1, SANE_Int curve2) { /* compares two curves of the same direction returns TRUE if both buffers are equal */ SANE_Int rst = FALSE; struct st_curve *crv1 = Motor_Curve_Get (dev, motorsetting, direction, curve1); struct st_curve *crv2 = Motor_Curve_Get (dev, motorsetting, direction, curve2); if ((crv1 != NULL) && (crv2 != NULL)) { if (crv1->step_count == crv2->step_count) { rst = TRUE; if (crv1->step_count > 0) { SANE_Int a = 0; while ((a < crv1->step_count) && (rst == TRUE)) { rst = (crv1->step[a] == crv2->step[a]) ? TRUE : FALSE; a++; } } } } return rst; } static struct st_motorcurve ** Motor_Curve_Parse (SANE_Int * mtc_count, SANE_Int * buffer) { /* this function parses motorcurve buffer to get all motor settings */ struct st_motorcurve **rst = NULL; *mtc_count = 0; if (buffer != NULL) { /* phases: -1 : null phase 0 : -3 : initial config */ struct st_motorcurve *mtc = NULL; SANE_Int phase; phase = -1; while (*buffer != -1) { if (*buffer == -2) { /* end of motorcurve */ /* complete any openned phase */ /* close phase */ phase = -1; } else { /* step */ if (phase == -1) { /* new motorcurve */ phase = 0; mtc = (struct st_motorcurve *) malloc (sizeof (struct st_motorcurve)); if (mtc != NULL) { *mtc_count += 1; rst = realloc (rst, sizeof (struct st_motorcurve **) * *mtc_count); if (rst != NULL) { rst[*mtc_count - 1] = mtc; memset (mtc, 0, sizeof (struct st_motorcurve)); phase = -3; /* initial config */ } else { /* memory error */ *mtc_count = 0; break; } } else break; /* some error */ } if (mtc != NULL) { switch (phase) { case -3: /* initial config */ mtc->mri = *(buffer); mtc->msi = *(buffer + 1); mtc->skiplinecount = *(buffer + 2); mtc->motorbackstep = *(buffer + 3); buffer += 3; phase = -4; break; case -4: /**/ { /* create new step curve */ struct st_curve *curve = malloc (sizeof (struct st_curve)); if (curve != NULL) { /* add to step curve list */ mtc->curve = (struct st_curve **) realloc (mtc->curve, sizeof (struct st_curve **) * (mtc-> curve_count + 1)); if (mtc->curve != NULL) { mtc->curve_count++; mtc->curve[mtc->curve_count - 1] = curve; memset (curve, 0, sizeof (struct st_curve)); /* read crv speed and type */ curve->crv_speed = *buffer; curve->crv_type = *(buffer + 1); buffer += 2; /* get length of step buffer */ while (*(buffer + curve->step_count) != 0) curve->step_count++; if (curve->step_count > 0) { /* allocate step buffer */ curve->step = (SANE_Int *) malloc (sizeof (SANE_Int) * curve->step_count); if (curve->step != NULL) { memcpy (curve->step, buffer, sizeof (SANE_Int) * curve->step_count); buffer += curve->step_count; } else curve->step_count = 0; } } else { mtc->curve_count = 0; free (curve); } } else break; } break; } } } buffer++; } } return rst; } static void Motor_Curve_Free (struct st_motorcurve **motorcurves, SANE_Int * mtc_count) { if ((motorcurves != NULL) && (mtc_count != NULL)) { struct st_motorcurve *mtc; struct st_curve *curve; while (*mtc_count > 0) { mtc = motorcurves[*mtc_count - 1]; if (mtc != NULL) { if (mtc->curve != NULL) { while (mtc->curve_count > 0) { curve = mtc->curve[mtc->curve_count - 1]; if (curve != NULL) { if (curve->step != NULL) free (curve->step); free (curve); } mtc->curve_count--; } } free (mtc); } *mtc_count -= 1; } free (motorcurves); } } static SANE_Byte RTS_Sensor_Type (USB_Handle usb_handle) { /* Returns sensor type 01 = CCD 00 = CIS */ SANE_Int a, b, c; SANE_Byte rst; DBG (DBG_FNC, "+ RTS_Sensor_Type:\n"); a = b = c = 0; /* Save data first */ Read_Word (usb_handle, 0xe950, &a); Read_Word (usb_handle, 0xe956, &b); /* Enables GPIO 0xe950 writing directly 0x13ff */ Write_Word (usb_handle, 0xe950, 0x13ff); /* Sets GPIO 0xe956 writing 0xfcf0 */ Write_Word (usb_handle, 0xe956, 0xfcf0); /* Makes a sleep of 200 ms */ usleep (1000 * 200); /* Get GPIO 0xe968 */ Read_Word (usb_handle, 0xe968, &c); /* Restore data */ Write_Word (usb_handle, 0xe950, a); Write_Word (usb_handle, 0xe956, b); rst = ((_B1 (c) & 1) == 0) ? CCD_SENSOR : CIS_SENSOR; DBG (DBG_FNC, "- RTS_Sensor_Type: %s\n", (rst == CCD_SENSOR) ? "CCD" : "CIS"); return rst; } static void Free_Scanmodes (struct st_device *dev) { DBG (DBG_FNC, "> Free_Scanmodes\n"); if (dev->scanmodes != NULL) { if (dev->scanmodes_count > 0) { SANE_Int a; for (a = 0; a < dev->scanmodes_count; a++) if (dev->scanmodes[a] != NULL) free (dev->scanmodes[a]); } free (dev->scanmodes); dev->scanmodes = NULL; } dev->scanmodes_count = 0; } static SANE_Int Load_Scanmodes (struct st_device *dev) { SANE_Int rst = OK; SANE_Int a, b; struct st_scanmode reg, *mode; DBG (DBG_FNC, "> Load_Scanmodes\n"); if ((dev->scanmodes != NULL) || (dev->scanmodes_count > 0)) Free_Scanmodes (dev); a = 0; while ((cfg_scanmode_get (dev->sensorcfg->type, a, ®) == OK) && (rst == OK)) { mode = (struct st_scanmode *) malloc (sizeof (struct st_scanmode)); if (mode != NULL) { memcpy (mode, ®, sizeof (struct st_scanmode)); for (b = 0; b < 3; b++) { if (mode->mexpt[b] == 0) { mode->mexpt[b] = mode->ctpc; if (mode->multiexposure != 1) mode->expt[b] = mode->ctpc; } } mode->ctpc = ((mode->ctpc + 1) * mode->multiexposure) - 1; dev->scanmodes = (struct st_scanmode **) realloc (dev->scanmodes, (dev->scanmodes_count + 1) * sizeof (struct st_scanmode **)); if (dev->scanmodes != NULL) { dev->scanmodes[dev->scanmodes_count] = mode; dev->scanmodes_count++; } else rst = ERROR; } else rst = ERROR; a++; } if (rst == ERROR) Free_Scanmodes (dev); DBG (DBG_FNC, " -> Found %i scanmodes\n", dev->scanmodes_count); dbg_scanmodes (dev); return rst; } static void Free_Config (struct st_device *dev) { DBG (DBG_FNC, "+ Free_Config\n"); /* free buttons */ Free_Buttons (dev); /* free motor general configuration */ Free_Motor (dev); /* free sensor main configuration */ Free_Sensor (dev); /* free ccd sensor timing tables */ Free_Timings (dev); /* free motor curves */ Free_MotorCurves (dev); /* free motor movements */ Free_Motormoves (dev); /* free scan modes */ Free_Scanmodes (dev); /* free constrains */ Free_Constrains (dev); /* free chipset configuration */ Free_Chipset (dev); DBG (DBG_FNC, "- Free_Config\n"); } static void Free_Chipset (struct st_device *dev) { DBG (DBG_FNC, "> Free_Chipset\n"); if (dev->chipset != NULL) { if (dev->chipset->name != NULL) free (dev->chipset->name); free (dev->chipset); dev->chipset = NULL; } } static SANE_Int Load_Chipset (struct st_device *dev) { SANE_Int rst = ERROR; DBG (DBG_FNC, "> Load_Chipset\n"); if (dev->chipset != NULL) Free_Chipset (dev); dev->chipset = malloc (sizeof (struct st_chip)); if (dev->chipset != NULL) { SANE_Int model; bzero (dev->chipset, sizeof (struct st_chip)); /* get chipset model of selected scanner */ model = cfg_chipset_model_get (RTS_Debug->dev_model); /* get configuration for selected chipset */ rst = cfg_chipset_get (model, dev->chipset); } /* if rst == ERROR may be related to allocating space for chipset name */ return rst; } static SANE_Int Load_Config (struct st_device *dev) { DBG (DBG_FNC, "+ Load_Config\n"); /* load chipset configuration */ Load_Chipset (dev); /* load scanner's buttons */ Load_Buttons (dev); /* load scanner area constrains */ Load_Constrains (dev); /* load motor general configuration */ Load_Motor (dev); /* load sensor main configuration */ Load_Sensor (dev); if (dev->sensorcfg->type == -1) /* get sensor from gpio */ dev->sensorcfg->type = RTS_Sensor_Type (dev->usb_handle); /* load ccd sensor timing tables */ Load_Timings (dev); /* load motor curves */ Load_MotorCurves (dev); /* load motor movements */ Load_Motormoves (dev); /* load scan modes */ Load_Scanmodes (dev); /* deprecated */ if (dev->sensorcfg->type == CCD_SENSOR) /* ccd */ usbfile = (RTS_Debug->usbtype == USB20) ? T_RTINIFILE : T_USB1INIFILE; else /* cis */ usbfile = (RTS_Debug->usbtype == USB20) ? S_RTINIFILE : S_USB1INIFILE; scantype = ST_NORMAL; pwmlamplevel = get_value (SCAN_PARAM, PWMLAMPLEVEL, 1, usbfile); arrangeline2 = get_value (SCAN_PARAM, ARRANGELINE, FIX_BY_HARD, usbfile); shadingbase = get_value (TRUE_GRAY_PARAM, SHADINGBASE, 3, usbfile); shadingfact[0] = get_value (TRUE_GRAY_PARAM, SHADINGFACT1, 1, usbfile); shadingfact[1] = get_value (TRUE_GRAY_PARAM, SHADINGFACT2, 1, usbfile); shadingfact[2] = get_value (TRUE_GRAY_PARAM, SHADINGFACT3, 1, usbfile); LoadImagingParams (dev, usbfile); DBG (DBG_FNC, "- Load_Config\n"); return OK; } static SANE_Int LoadImagingParams (struct st_device *dev, SANE_Int inifile) { DBG (DBG_FNC, "> LoadImagingParams(inifile='%i'):\n", inifile); scan.startpos = get_value (SCAN_PARAM, STARTPOS, 0, inifile); scan.leftleading = get_value (SCAN_PARAM, LEFTLEADING, 0, inifile); arrangeline = get_value (SCAN_PARAM, ARRANGELINE, FIX_BY_HARD, inifile); compression = get_value (SCAN_PARAM, COMPRESSION, 0, inifile); /* get default gain and offset values */ cfg_gainoffset_get (dev->sensorcfg->type, default_gain_offset); linedarlampoff = get_value (CALI_PARAM, LINEDARLAMPOFF, 0, inifile); pixeldarklevel = get_value (CALI_PARAM, PIXELDARKLEVEL, 0x00ffff, inifile); binarythresholdh = get_value (PLATFORM, BINARYTHRESHOLDH, 0x80, inifile); binarythresholdl = get_value (PLATFORM, BINARYTHRESHOLDL, 0x7f, inifile); return OK; } static SANE_Int Arrange_Colour (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred) { /* 05F0FA78 04EC00D8 /CALL to Assumed StdFunc2 from hpgt3970.04EC00D3 05F0FA7C 05D10048 |Arg1 = 05D10048 05F0FA80 0000F906 \Arg2 = 0000F906 */ SANE_Int mydistance; SANE_Int Lines_Count; SANE_Int space; SANE_Int rst = OK; SANE_Int c; struct st_scanning *scn; DBG (DBG_FNC, "> Arrange_Colour(*buffer, buffer_size=%i, *transferred)\n", buffer_size); /* this is just to make code more legible */ scn = dev->scanning; if (scn->imagebuffer == NULL) { if (dev->sensorcfg->type == CCD_SENSOR) mydistance = (dev->sensorcfg->line_distance * scan2.resolution_y) / dev->sensorcfg->resolution; else mydistance = 0; /*aafa */ if (mydistance != 0) { scn->bfsize = (scn->arrange_hres == TRUE) ? scn->arrange_sensor_evenodd_dist : 0; scn->bfsize = (scn->bfsize + (mydistance * 2) + 1) * line_size; } else scn->bfsize = line_size * 2; /*ab3c */ space = (((scn->bfsize / line_size) * bytesperline) > scn->bfsize) ? (scn->bfsize / line_size) * bytesperline : scn->bfsize; scn->imagebuffer = (SANE_Byte *) malloc (space * sizeof (SANE_Byte)); if (scn->imagebuffer == NULL) return ERROR; scn->imagepointer = scn->imagebuffer; if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) != OK) return ERROR; scn->arrange_orderchannel = FALSE; scn->channel_size = (scan2.depth == 8) ? 1 : 2; /* Calculate channel displacements */ for (c = CL_RED; c <= CL_BLUE; c++) { if (mydistance == 0) { /*ab9b */ if (scn->arrange_hres == FALSE) { if ((((dev->sensorcfg->line_distance * scan2.resolution_y) * 2) / dev->sensorcfg->resolution) == 1) scn->arrange_orderchannel = TRUE; if (scn->arrange_orderchannel == TRUE) scn->desp[c] = ((dev->sensorcfg->rgb_order[c] / 2) * line_size) + (scn->channel_size * c); else scn->desp[c] = scn->channel_size * c; } } else { /*ac32 */ scn->desp[c] = (dev->sensorcfg->rgb_order[c] * (mydistance * line_size)) + (scn->channel_size * c); if (scn->arrange_hres == TRUE) { scn->desp1[c] = scn->desp[c]; scn->desp2[c] = ((scn->channel_size * 3) + scn->desp[c]) + (scn->arrange_sensor_evenodd_dist * line_size); } } } /*ace2 */ for (c = CL_RED; c <= CL_BLUE; c++) { if (scn->arrange_hres == TRUE) { scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; } else scn->pColour[c] = scn->imagebuffer + scn->desp[c]; } } /*ad91 */ Lines_Count = buffer_size / line_size; while (Lines_Count > 0) { if (scn->arrange_orderchannel == FALSE) { if (scn->arrange_hres == TRUE) Triplet_Colour_HRes (scn->pColour1[CL_RED], scn->pColour1[CL_GREEN], scn->pColour1[CL_BLUE], scn->pColour2[CL_RED], scn->pColour2[CL_GREEN], scn->pColour2[CL_BLUE], buffer, line_size / (scn->channel_size * 3)); else Triplet_Colour_LRes (line_size / (scn->channel_size * 3), buffer, scn->pColour[CL_RED], scn->pColour[CL_GREEN], scn->pColour[CL_BLUE]); } else Triplet_Colour_Order (dev, scn->pColour[CL_RED], scn->pColour[CL_GREEN], scn->pColour[CL_BLUE], buffer, line_size / (scn->channel_size * 3)); scn->arrange_size -= bytesperline; if (scn->arrange_size < 0) v15bc--; buffer += line_size; Lines_Count--; if (Lines_Count == 0) { if ((scn->arrange_size | v15bc) == 0) return OK; } if (Read_Block (dev, line_size, scn->imagepointer, transferred) == ERROR) return ERROR; /* Update displacements */ for (c = CL_RED; c <= CL_BLUE; c++) { if (scn->arrange_hres == TRUE) { /*aeb7 */ scn->desp2[c] = (scn->desp2[c] + line_size) % scn->bfsize; scn->desp1[c] = (scn->desp1[c] + line_size) % scn->bfsize; scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; } else { /*af86 */ scn->desp[c] = (scn->desp[c] + line_size) % scn->bfsize; scn->pColour[c] = scn->imagebuffer + scn->desp[c]; } } /*aff3 */ scn->imagepointer += line_size; if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) scn->imagepointer = scn->imagebuffer; } return rst; } static SANE_Int RTS_Scanner_SetParams (struct st_device *dev, struct params *param) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_Scanner_SetParams:\n"); DBG (DBG_FNC, "-> param->resolution_x=%i\n", param->resolution_x); DBG (DBG_FNC, "-> param->resolution_y=%i\n", param->resolution_y); DBG (DBG_FNC, "-> param->left =%i\n", param->coords.left); DBG (DBG_FNC, "-> param->width =%i\n", param->coords.width); DBG (DBG_FNC, "-> param->top =%i\n", param->coords.top); DBG (DBG_FNC, "-> param->height =%i\n", param->coords.height); DBG (DBG_FNC, "-> param->colormode =%s\n", dbg_colour (param->colormode)); DBG (DBG_FNC, "-> param->scantype =%s\n", dbg_scantype (param->scantype)); DBG (DBG_FNC, "-> param->depth =%i\n", param->depth); DBG (DBG_FNC, "-> param->channel =%i\n", param->channel); /* validate area size to scan */ if ((param->coords.width != 0) && (param->coords.height != 0)) { SANE_Byte mybuffer[1]; struct st_hwdconfig hwdcfg; /* setting coordinates */ memcpy (&scan.coord, ¶m->coords, sizeof (struct st_coords)); /* setting resolution */ scan.resolution_x = param->resolution_x; scan.resolution_y = param->resolution_y; /* setting colormode and depth */ scan.colormode = param->colormode; scan.depth = (param->colormode == CM_LINEART) ? 8 : param->depth; /* setting color channel for non color scans */ scan.channel = _B0 (param->channel); arrangeline = FIX_BY_HARD; if ((scan.resolution_x == 2400) || ((scan.resolution_x == 4800))) { if (scan.colormode != CM_COLOR) { if (scan.colormode == CM_GRAY) { if (scan.channel == 3) arrangeline = FIX_BY_SOFT; } } else arrangeline = FIX_BY_SOFT; } /* setting scan type */ if ((param->scantype > 0) && (param->scantype < 4)) scan.scantype = param->scantype; else scan.scantype = ST_NORMAL; /* setting scanner lamp */ data_bitset (&dev->init_regs[0x146], 0x40, ((dev->sensorcfg->type == CIS_SENSOR) ? 0 : 1)); /* turn on appropiate lamp */ if (scan.scantype == ST_NORMAL) Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); else Lamp_Status_Set (dev, NULL, TRUE, TMA_LAMP); mybuffer[0] = 0; if (RTS_IsExecuting (dev, mybuffer) == FALSE) RTS_WriteRegs (dev->usb_handle, dev->init_regs); if (scan.depth == 16) compression = FALSE; /* resetting low level config */ bzero (&hwdcfg, sizeof (struct st_hwdconfig)); /* setting low level config */ hwdcfg.scantype = scan.scantype; hwdcfg.calibrate = mybuffer[0]; hwdcfg.arrangeline = arrangeline; /*1 */ hwdcfg.highresolution = (scan.resolution_x > 1200) ? TRUE : FALSE; hwdcfg.sensorevenodddistance = dev->sensorcfg->evenodd_distance; SetScanParams (dev, dev->init_regs, &scan, &hwdcfg); scan.shadinglength = (((scan.sensorresolution * 17) / 2) + 3) & 0xfffffffc; rst = OK; } DBG (DBG_FNC, "- RTS_Scanner_SetParams: %i\n", rst); return rst; } static SANE_Int SetScanParams (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg) { struct st_coords mycoords; SANE_Int mycolormode; SANE_Int myvalue; SANE_Int mymode; SANE_Int channel_size; SANE_Int channel_count; SANE_Int dots_per_block; SANE_Int aditional_dots; DBG (DBG_FNC, "+ SetScanParams:\n"); dbg_ScanParams (scancfg); dbg_hwdcfg (hwdcfg); bzero (&mycoords, sizeof (struct st_coords)); /* Copy scancfg to scan2 */ memcpy (&scan2, scancfg, sizeof (struct st_scanparams)); mycolormode = scancfg->colormode; myvalue = scancfg->colormode; scantype = hwdcfg->scantype; if (scancfg->colormode == CM_LINEART) scan2.depth = 8; if ((scancfg->colormode != CM_COLOR) && (scancfg->channel == 3)) /*channel = 0x00 */ { if (scancfg->colormode == CM_GRAY) { mycolormode = (hwdcfg->arrangeline != FIX_BY_SOFT) ? 3 : CM_COLOR; } else mycolormode = 3; myvalue = mycolormode; } dev->Resize->resolution_x = scancfg->resolution_x; dev->Resize->resolution_y = scancfg->resolution_y; mymode = RTS_GetScanmode (dev, hwdcfg->scantype, myvalue, scancfg->resolution_x); /*0x0b */ if (mymode == -1) { /* Non supported resolution. We will resize image after scanning */ SANE_Int fitres; fitres = Scanmode_fitres (dev, hwdcfg->scantype, scancfg->colormode, scancfg->resolution_x); if (fitres != -1) { /* supported resolution found */ dev->Resize->type = RSZ_DECREASE; } else { dev->Resize->type = RSZ_INCREASE; fitres = Scanmode_maxres (dev, hwdcfg->scantype, scancfg->colormode); } scan2.resolution_x = fitres; scan2.resolution_y = fitres; mymode = RTS_GetScanmode (dev, hwdcfg->scantype, myvalue, scan2.resolution_x); if (mymode == -1) return ERROR; imageheight = scancfg->coord.height; dev->Resize->towidth = scancfg->coord.width; /* Calculate coords for new resolution */ mycoords.left = (scan2.resolution_x * scancfg->coord.left) / dev->Resize->resolution_x; mycoords.width = (scan2.resolution_x * scancfg->coord.width) / dev->Resize->resolution_x; mycoords.top = (scan2.resolution_y * scancfg->coord.top) / dev->Resize->resolution_y; mycoords.height = ((scan2.resolution_y * scancfg->coord.height) / dev->Resize->resolution_y) + 2; switch (scan2.colormode) { case CM_GRAY: if ((dev->scanmodes[mymode]->samplerate == PIXEL_RATE) && (mycolormode != 3)) dev->Resize->towidth *= 2; channel_size = (scan2.depth == 8) ? 1 : 2; dev->Resize->mode = (scan2.depth == 8) ? RSZ_GRAYL : RSZ_GRAYH; dev->Resize->bytesperline = dev->Resize->towidth * channel_size; break; case CM_LINEART: if (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) dev->Resize->towidth *= 2; dev->Resize->mode = RSZ_LINEART; dev->Resize->bytesperline = (dev->Resize->towidth + 7) / 8; break; default: /*CM_COLOR */ channel_count = 3; channel_size = (scan2.depth == 8) ? 1 : 2; dev->Resize->mode = (scan2.depth == 8) ? RSZ_COLOURL : RSZ_COLOURH; dev->Resize->bytesperline = scancfg->coord.width * (channel_count * channel_size); break; } } else { /* Supported scanmode */ dev->Resize->type = RSZ_NONE; scan2.resolution_x = scancfg->resolution_x; scan2.resolution_y = scancfg->resolution_y; mycoords.left = scancfg->coord.left; mycoords.top = scancfg->coord.top; mycoords.width = scancfg->coord.width; mycoords.height = scancfg->coord.height; } scancfg->timing = dev->scanmodes[mymode]->timing; scan2.sensorresolution = dev->timings[scancfg->timing]->sensorresolution; if ((scantype > 0) && (scantype < 5)) scan2.shadinglength = (((scan2.sensorresolution * 17) / 2) + 3) & 0xfffffffc; scancfg->sensorresolution = scan2.sensorresolution; scancfg->shadinglength = scan2.shadinglength; dev->scanning->arrange_compression = ((mycolormode != CM_LINEART) && (scan2.depth <= 8)) ? hwdcfg->compression : FALSE; if ((arrangeline2 == FIX_BY_HARD) || (mycolormode == CM_LINEART)) arrangeline2 = mycolormode; /*¿? */ else if ((mycolormode == CM_GRAY) && (hwdcfg->highresolution == FALSE)) arrangeline2 = 0; if (hwdcfg->highresolution == FALSE) { /* resolution < 1200 dpi */ dev->scanning->arrange_hres = FALSE; dev->scanning->arrange_sensor_evenodd_dist = 0; } else { /* resolution > 1200 dpi */ dev->scanning->arrange_hres = TRUE; dev->scanning->arrange_sensor_evenodd_dist = hwdcfg->sensorevenodddistance; } /* with must be adjusted to fit in the dots count per block */ aditional_dots = 0; if (mycolormode != CM_LINEART) { dots_per_block = ((scan2.resolution_x > 2400) && (scancfg->samplerate == PIXEL_RATE)) ? 8 : 4; /* fit width */ if ((mycoords.width % dots_per_block) != 0) { aditional_dots = dots_per_block - (mycoords.width % dots_per_block); mycoords.width += aditional_dots; } } else { /* Lineart */ dots_per_block = 32 - (mycoords.width & 0x1f); if (dots_per_block < 32) { mycoords.width += dots_per_block; aditional_dots = (dots_per_block / 8); } } DBG (DBG_FNC, " -> dots_per_block: %i\n", dots_per_block); DBG (DBG_FNC, " -> aditional_dots: %i\n", aditional_dots); if (mycolormode == CM_LINEART) { bytesperline = (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) ? mycoords.width / 4 : mycoords.width / 8; imagewidth3 = bytesperline; lineart_width = bytesperline * 8; line_size = bytesperline - aditional_dots; dev->Resize->fromwidth = line_size * 8; } else { /*4510 */ switch (mycolormode) { case CM_COLOR: channel_count = 3; break; case 3: channel_count = 1; break; case CM_GRAY: channel_count = (dev->scanmodes[mymode]->samplerate == PIXEL_RATE) ? 2 : 1; /*1 */ break; } channel_size = (scan2.depth == 8) ? 1 : 2; bytesperline = mycoords.width * (channel_count * channel_size); imagewidth3 = bytesperline / channel_count; lineart_width = imagewidth3 / channel_size; line_size = bytesperline - (aditional_dots * (channel_count * channel_size)); dev->Resize->fromwidth = line_size / (channel_count * channel_size); } imagesize = mycoords.height * bytesperline; v15b4 = 0; dev->scanning->arrange_size = imagesize; v15bc = 0; /* set resolution ratio */ data_bitset (&Regs[0xc0], 0x1f, scancfg->sensorresolution / scancfg->resolution_x); scancfg->coord.left = mycoords.left; scancfg->coord.top = mycoords.top; scancfg->coord.width = mycoords.width; scancfg->coord.height = mycoords.height; scancfg->resolution_x = scan2.resolution_x; scancfg->resolution_y = scan2.resolution_y; myvalue = (dev->Resize->type == RSZ_NONE) ? line_size : dev->Resize->bytesperline; scancfg->bytesperline = bytesperline; scancfg->v157c = myvalue; if (scan.colormode != CM_COLOR) { if (mycolormode == CM_COLOR) scancfg->v157c = (scancfg->v157c / 3); } if (scan.colormode == CM_LINEART) { if (mycolormode == 3) { scancfg->v157c = (scancfg->v157c + 7) / 8; scancfg->bytesperline = (scancfg->bytesperline + 7) / 8; } } DBG (DBG_FNC, "- SetScanParams:\n"); return OK; } static SANE_Int GainOffset_Counter_Save (struct st_device *dev, SANE_Byte data) { SANE_Int rst = OK; DBG (DBG_FNC, "> GainOffset_Counter_Save(data=%i):\n", data); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { data = min (data, 0x0f); rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x0077, data); } return rst; } static SANE_Int GainOffset_Counter_Inc (struct st_device *dev, SANE_Int * arg1) { SANE_Byte count; SANE_Int rst; DBG (DBG_FNC, "+ GainOffset_Counter_Inc:\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { count = GainOffset_Counter_Load (dev); if ((count >= 0x0f) || (GainOffset_Get (dev) != OK)) { offset[CL_BLUE] = offset[CL_GREEN] = offset[CL_RED] = 0; gain[CL_BLUE] = gain[CL_GREEN] = gain[CL_RED] = 0; count = 0; } else { count++; if (arg1 != NULL) *arg1 = 1; } rst = GainOffset_Counter_Save (dev, count); } else rst = OK; DBG (DBG_FNC, "- GainOffset_Counter_Inc: %i\n", rst); return rst; } static SANE_Int GainOffset_Get (struct st_device *dev) { SANE_Int a, data, rst; SANE_Byte checksum; DBG (DBG_FNC, "+ GainOffset_Get:\n"); checksum = 0; /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { /* get current checksum */ if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x76, &checksum) == OK) { rst = OK; /* read gain and offset values from EEPROM */ for (a = CL_RED; a <= CL_BLUE; a++) { if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x70 + (2 * a), &data) == ERROR) { rst = ERROR; break; } else offset[a] = data; } /* check checksum */ checksum = _B0 (checksum + offset[CL_GREEN] + offset[CL_BLUE] + offset[CL_RED]); } else rst = ERROR; } else rst = ERROR; /* extract gain and offset values */ if ((rst == OK) && (checksum == 0x5b)) { for (a = CL_RED; a <= CL_BLUE; a++) { gain[a] = (offset[a] >> 9) & 0x1f; offset[a] &= 0x01ff; } } else { /* null values, let's reset them */ for (a = CL_RED; a <= CL_BLUE; a++) { gain[a] = 0; offset[a] = 0; } rst = ERROR; } DBG (DBG_FNC, "-> Preview gainR=%i, gainG=%i, gainB=%i, offsetR=%i, offsetG=%i, offsetB=%i\n", gain[CL_RED], gain[CL_GREEN], gain[CL_BLUE], offset[CL_RED], offset[CL_GREEN], offset[CL_BLUE]); DBG (DBG_FNC, "- GainOffset_Get: %i\n", rst); return rst; } static SANE_Int Scanmode_maxres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode) { /* returns position in scanmodes table where data fits with given arguments */ SANE_Int rst = 0; SANE_Int a; struct st_scanmode *reg; for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { if ((reg->scantype == scantype) && (reg->colormode == colormode)) rst = max (rst, reg->resolution); /* found ! */ } } if (rst == 0) { /* There isn't any mode for these arguments. Most devices doesn't support specific setup to scan in lineart mode so they use gray colormode. Lets check this case */ if (colormode == CM_LINEART) rst = Scanmode_maxres (dev, scantype, CM_GRAY); } DBG (DBG_FNC, "> Scanmode_maxres(scantype=%s, colormode=%s): %i\n", dbg_scantype (scantype), dbg_colour (colormode), rst); return rst; } static SANE_Int Scanmode_minres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode) { /* returns position in scanmodes table where data fits with given arguments */ SANE_Int rst, a; struct st_scanmode *reg; rst = Scanmode_maxres (dev, scantype, colormode); for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { if ((reg->scantype == scantype) && (reg->colormode == colormode)) rst = min (rst, reg->resolution); /* found ! */ } } if (rst == 0) { /* There isn't any mode for these arguments. Most devices doesn't support specific setup to scan in lineart mode so they use gray colormode. Lets check this case */ if (colormode == CM_LINEART) rst = Scanmode_minres (dev, scantype, CM_GRAY); } DBG (DBG_FNC, "> Scanmode_minres(scantype=%s, colormode=%s): %i\n", dbg_scantype (scantype), dbg_colour (colormode), rst); return rst; } static SANE_Int Scanmode_fitres (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, SANE_Int resolution) { /* returns a supported resolution */ SANE_Int rst; SANE_Int a, nullres; struct st_scanmode *reg; nullres = Scanmode_maxres (dev, scantype, colormode) + 1; rst = nullres; for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { if ((reg->scantype == scantype) && (reg->colormode == colormode)) { if ((reg->resolution < rst) && (resolution <= reg->resolution)) rst = reg->resolution; } } } if (rst == nullres) { /* There isn't any mode for these arguments. Most devices doesn't support specific setup to scan in lineart mode so they use gray colormode. Lets check this case */ if (colormode != CM_LINEART) { /* at this point, given resolution is bigger than maximum supported resolution */ rst = -1; } else rst = Scanmode_minres (dev, scantype, CM_GRAY); } DBG (DBG_FNC, "> Scanmode_fitres(scantype=%s, colormode=%s, resolution=%i): %i\n", dbg_scantype (scantype), dbg_colour (colormode), resolution, rst); return rst; } static SANE_Int RTS_GetScanmode (struct st_device *dev, SANE_Int scantype, SANE_Int colormode, SANE_Int resolution) { /* returns position in scanmodes table where data fits with given arguments */ SANE_Int rst = -1; SANE_Int a; struct st_scanmode *reg; for (a = 0; a < dev->scanmodes_count; a++) { reg = dev->scanmodes[a]; if (reg != NULL) { if ((reg->scantype == scantype) && (reg->colormode == colormode) && (reg->resolution == resolution)) { /* found ! */ rst = a; break; } } } if (rst == -1) { /* There isn't any mode for these arguments. May be given resolution isn't supported by chipset. Most devices doesn't support specific setup to scan in lineart mode so they use gray colormode. Lets check this case */ if ((colormode == CM_LINEART) || (colormode == 3)) rst = RTS_GetScanmode (dev, scantype, CM_GRAY, resolution); } DBG (DBG_FNC, "> RTS_GetScanmode(scantype=%s, colormode=%s, resolution=%i): %i\n", dbg_scantype (scantype), dbg_colour (colormode), resolution, rst); return rst; } static void Free_Motor (struct st_device *dev) { /* this function releases space for stepper motor */ DBG (DBG_FNC, "> Free_Motor\n"); if (dev->motorcfg != NULL) { free (dev->motorcfg); dev->motorcfg = NULL; } } static SANE_Int Load_Motor (struct st_device *dev) { /* this function loads general configuration for motor */ SANE_Int rst = ERROR; DBG (DBG_FNC, "> Load_Motor\n"); if (dev->motorcfg != NULL) Free_Motor (dev); dev->motorcfg = malloc (sizeof (struct st_motorcfg)); if (dev->motorcfg != NULL) { rst = cfg_motor_get (dev->motorcfg); dbg_motorcfg (dev->motorcfg); } return rst; } static void Free_Sensor (struct st_device *dev) { /* this function releases space for ccd sensor */ DBG (DBG_FNC, "> Free_Sensor\n"); if (dev->sensorcfg != NULL) { free (dev->sensorcfg); dev->sensorcfg = NULL; } } static void Free_Buttons (struct st_device *dev) { /* this function releases space for buttons */ DBG (DBG_FNC, "> Free_Buttons\n"); if (dev->buttons != NULL) { free (dev->buttons); dev->buttons = NULL; } } static SANE_Int Load_Buttons (struct st_device *dev) { /* this function loads configuration for ccd sensor */ SANE_Int rst = ERROR; DBG (DBG_FNC, "> Load_Buttons\n"); if (dev->buttons != NULL) Free_Buttons (dev); dev->buttons = malloc (sizeof (struct st_buttons)); if (dev->buttons != NULL) { rst = cfg_buttons_get (dev->buttons); dbg_buttons (dev->buttons); } return rst; } static SANE_Int Load_Sensor (struct st_device *dev) { /* this function loads configuration for ccd sensor */ SANE_Int rst = ERROR; DBG (DBG_FNC, "> Load_Sensor\n"); if (dev->sensorcfg != NULL) Free_Sensor (dev); dev->sensorcfg = malloc (sizeof (struct st_sensorcfg)); if (dev->sensorcfg != NULL) { rst = cfg_sensor_get (dev->sensorcfg); dbg_sensor (dev->sensorcfg); } return rst; } static void Free_Timings (struct st_device *dev) { /* this function frees all ccd sensor timing tables */ DBG (DBG_FNC, "> Free_Timings\n"); if (dev->timings != NULL) { if (dev->timings_count > 0) { SANE_Int a; for (a = 0; a < dev->timings_count; a++) if (dev->timings[a] != NULL) free (dev->timings[a]); dev->timings_count = 0; } free (dev->timings); dev->timings = NULL; } } static SANE_Int Load_Timings (struct st_device *dev) { SANE_Int rst = OK; SANE_Int a; struct st_timing reg, *tmg; DBG (DBG_FNC, "> Load_Timings\n"); if (dev->timings != NULL) Free_Timings (dev); a = 0; while ((cfg_timing_get (dev->sensorcfg->type, a, ®) == OK) && (rst == OK)) { tmg = (struct st_timing *) malloc (sizeof (struct st_timing)); if (tmg != NULL) { memcpy (tmg, ®, sizeof (struct st_timing)); dev->timings_count++; dev->timings = (struct st_timing **) realloc (dev->timings, sizeof (struct st_timing **) * dev->timings_count); if (dev->timings == NULL) { rst = ERROR; dev->timings_count = 0; } else dev->timings[dev->timings_count - 1] = tmg; } else rst = ERROR; a++; } if (rst == ERROR) Free_Timings (dev); DBG (DBG_FNC, " -> Found %i timing registers\n", dev->timings_count); return rst; } static SANE_Int IsScannerLinked (struct st_device *dev) { SANE_Int var2; SANE_Byte lamp; DBG (DBG_FNC, "+ IsScannerLinked:\n"); Read_FE3E (dev, &v1619); Init_USBData (dev); scan.scantype = ST_NORMAL; RTS_WaitInitEnd (dev, 0x30000); lamp = FLB_LAMP; /* Comprobar si es la primera conexión con el escaner */ if (Read_Word (dev->usb_handle, 0xe829, &var2) == OK) { SANE_Int firstconnection; #ifdef STANDALONE firstconnection = TRUE; #else firstconnection = (var2 == 0) ? TRUE : FALSE; #endif if (firstconnection == TRUE) { /* primera conexión */ SANE_Byte flb_lamp, tma_lamp; flb_lamp = 0; tma_lamp = 0; Lamp_Status_Get (dev, &flb_lamp, &tma_lamp); if ((flb_lamp == 0) && (tma_lamp != 0)) lamp = TMA_LAMP; /*Clear GainOffset count */ GainOffset_Clear (dev); GainOffset_Counter_Save (dev, 0); /* Clear AutoRef count */ Refs_Counter_Save (dev, 0); Buttons_Enable (dev); Lamp_Status_Timer_Set (dev, 13); } else lamp = (_B0 (var2) == 0) ? FLB_LAMP : TMA_LAMP; } if (RTS_Warm_Reset (dev) != OK) return ERROR; Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); Lamp_Status_Timer_Set (dev, 13); /* Use fixed pwm? */ if (RTS_Debug->use_fixed_pwm != FALSE) { Lamp_PWM_Save (dev, cfg_fixedpwm_get (dev->sensorcfg->type, ST_NORMAL)); /* Lets enable using fixed pwm */ Lamp_PWM_SaveStatus (dev, TRUE); } Lamp_PWM_Setup (dev, lamp); DBG (DBG_FNC, "- IsScannerLinked:\n"); return OK; } static SANE_Int Lamp_PWM_SaveStatus (struct st_device *dev, SANE_Byte status) { SANE_Byte mypwm; SANE_Int rst = OK; DBG (DBG_FNC, "+ Lamp_PWM_SaveStatus(status=%i):\n", status); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { rst = ERROR; if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x007b, &mypwm) == OK) { mypwm = (status == FALSE) ? mypwm & 0x7f : mypwm | 0x80; if (RTS_EEPROM_WriteByte (dev->usb_handle, 0x007b, mypwm) == OK) rst = OK; } } DBG (DBG_FNC, "- Lamp_PWM_SaveStatus: %i\n", rst); return rst; } static SANE_Int Lamp_PWM_Save (struct st_device *dev, SANE_Int fixedpwm) { SANE_Int rst; DBG (DBG_FNC, "+ Lamp_PWM_Save(fixedpwm=%i):\n", fixedpwm); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x7b, ((fixedpwm << 2) | 0x80)); else rst = OK; DBG (DBG_FNC, "- Lamp_PWM_Save: %i\n", rst); return rst; } static SANE_Int Lamp_PWM_Setup (struct st_device *dev, SANE_Int lamp) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Lamp_PWM_Setup(lamp=%s):\n", (lamp == FLB_LAMP) ? "FLB_LAMP" : "TMA_LAMP"); if (Lamp_PWM_use (dev, 1) == OK) { SANE_Int fixedpwm, currentpwd; currentpwd = 0; fixedpwm = cfg_fixedpwm_get (dev->sensorcfg->type, (lamp == FLB_LAMP) ? ST_NORMAL : ST_TA); if (Lamp_PWM_DutyCycle_Get (dev, ¤tpwd) == OK) { /* set duty cycle if current one is different */ if (currentpwd != fixedpwm) rst = Lamp_PWM_DutyCycle_Set (dev, fixedpwm); } else rst = Lamp_PWM_DutyCycle_Set (dev, fixedpwm); } DBG (DBG_FNC, "- Lamp_PWM_Setup: %i\n", rst); return rst; } static SANE_Int Lamp_PWM_DutyCycle_Get (struct st_device *dev, SANE_Int * data) { SANE_Byte a; SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Lamp_PWM_DutyCycle_Get:\n"); if (Read_Byte (dev->usb_handle, 0xe948, &a) == OK) { *data = a & 0x3f; rst = OK; } DBG (DBG_FNC, "- Lamp_PWM_DutyCycle_Get = %i: %i\n", *data, rst); return rst; } static SANE_Int Lamp_PWM_DutyCycle_Set (struct st_device *dev, SANE_Int duty_cycle) { SANE_Byte *Regs; SANE_Int rst; DBG (DBG_FNC, "+ Lamp_PWM_DutyCycle_Set(duty_cycle=%i):\n", duty_cycle); rst = ERROR; Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { if (RTS_ReadRegs (dev->usb_handle, Regs) == OK) { data_bitset (&Regs[0x148], 0x3f, duty_cycle); if (pwmlamplevel == 0) { data_bitset (&Regs[0x148], 0x40, 0); Regs[0x1e0] |= ((duty_cycle >> 1) & 0x40); } data_bitset (&dev->init_regs[0x148], 0x7f, Regs[0x148]); data_bitset (&dev->init_regs[0x1e0], 0x3f, Regs[0x1e0]); Write_Byte (dev->usb_handle, 0xe948, Regs[0x0148]); rst = Write_Byte (dev->usb_handle, 0xe9e0, Regs[0x01e0]); } free (Regs); } DBG (DBG_FNC, "- Lamp_PWM_DutyCycle_Set: %i\n", rst); return rst; } static SANE_Int Head_ParkHome (struct st_device *dev, SANE_Int bWait, SANE_Int movement) { SANE_Int rst = ERROR; SANE_Byte *Regs; DBG (DBG_FNC, "+ Head_ParkHome(bWait=%i, movement=%i):\n", bWait, movement); Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { rst = OK; memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); /* Lets wait if it's required when is already executing */ if (bWait != FALSE) { if (RTS_WaitScanEnd (dev, 0x3a98) != OK) { DBG (DBG_FNC, " -> Head_ParkHome: RTS_WaitScanEnd Timeout\n"); rst = ERROR; /* timeout */ } } else { if (RTS_IsExecuting (dev, Regs) == FALSE) { DBG (DBG_FNC, " -> Head_ParkHome: RTS_IsExecuting = 0, exiting function\n"); rst = ERROR; /* if NOT executing */ } } /* Check if lamp is at home */ if ((rst == OK) && (Head_IsAtHome (dev, Regs) == FALSE)) { struct st_motormove mymotor; struct st_motorpos mtrpos; DBG (DBG_FNC, "-> Head_ParkHome: Lamp is not at home, lets move\n"); /* it isn't */ dev->status->parkhome = TRUE; if ((movement != -1) && (movement < dev->motormove_count)) { memcpy (&mymotor, dev->motormove[movement], sizeof (struct st_motormove)); } else { /* debug this code. Shouldn't have any relationship with offsets */ if (default_gain_offset->edcg2[CL_BLUE] < 4) mymotor.scanmotorsteptype = default_gain_offset->edcg2[CL_BLUE]; mymotor.ctpc = default_gain_offset->odcg2[1]; mymotor.systemclock = default_gain_offset->edcg2[1]; /*? */ } mtrpos.options = MTR_ENABLED | MTR_BACKWARD; mtrpos.v12e448 = 0x01; mtrpos.v12e44c = 0x00; mtrpos.coord_y = 0x4e20; Motor_Move (dev, Regs, &mymotor, &mtrpos); /* Should we wait? */ if (bWait != FALSE) rst = RTS_WaitScanEnd (dev, 15000); dev->status->parkhome = FALSE; } free (Regs); } DBG (DBG_FNC, "- Head_ParkHome: %i:\n", rst); return rst; } static SANE_Int Motor_Move (struct st_device *dev, SANE_Byte * Regs, struct st_motormove *mymotor, struct st_motorpos *mtrpos) { SANE_Byte *cpRegs; SANE_Int rst; DBG (DBG_FNC, "+ Motor_Move:\n"); rst = ERROR; cpRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (cpRegs != NULL) { SANE_Int data, v12dcf8, coord_y, step_type; memcpy (cpRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); v12dcf8 = 0; /* resolution = 1 dpi */ data_bitset (&cpRegs[0xc0], 0x1f, 1); /*---xxxxx*/ /* set motor step type */ data_bitset (&cpRegs[0xd9], 0x70, mymotor->scanmotorsteptype); /*-xxx----*/ /* set motor direction (polarity) */ data_bitset (&cpRegs[0xd9], 0x80, mtrpos->options >> 3); /*e------- */ /* next value doesn't seem to have any effect */ data_bitset (&cpRegs[0xd9], 0x0f, mtrpos->options); /*----efgh*/ /* 0 enable/1 disable motor */ data_bitset (&cpRegs[0xdd], 0x80, mtrpos->options >> 4); /*d------- */ /* next value doesn't seem to have any effect */ data_bitset (&cpRegs[0xdd], 0x40, mtrpos->options >> 4); /*-d------*/ switch (mymotor->scanmotorsteptype) { case STT_OCT: step_type = 8; break; case STT_QUART: step_type = 4; break; case STT_HALF: step_type = 2; break; case STT_FULL: step_type = 1; break; default: step_type = 0; break; /* shouldn't be used */ } coord_y = (mtrpos->coord_y * step_type) & 0xffff; if (coord_y < 2) coord_y = 2; /* Sets dummyline to 1 */ data_bitset (&cpRegs[0xd6], 0xf0, 1); /* set step_size - 1 */ cpRegs[0xe0] = 0; cpRegs[0x01] &= 0xf9; cpRegs[0x01] |= (mtrpos->v12e448 & 1) << 2; /* set dummy scan */ data_bitset (&cpRegs[0x01], 0x10, 1); /*---x----*/ /* set samplerate */ data_bitset (&cpRegs[0x1cf], 0x40, PIXEL_RATE); /*-x------*/ /* unknown data */ data_bitset (&cpRegs[0x1cf], 0x80, 1); /*x------- */ /* sets one chanel per color */ data_bitset (&cpRegs[0x12], 0x3f, 0); /* channel */ data_bitset (&cpRegs[0x12], 0xc0, 1); /* 1 channel */ /* timing cnpp */ data_bitset (&cpRegs[0x96], 0x3f, 0x0b); /*--001011*/ /* set systemclock */ data_bitset (&cpRegs[0x00], 0x0f, mymotor->systemclock); /*----xxxx*/ /* set last step of accurve.smearing table to 2 */ data_lsb_set (&cpRegs[0xe4], 2, 3); /* set last step of deccurve.scanbufferfull table to 16 */ data_lsb_set (&Regs[0xea], 0x10, 3); /* set last step of deccurve.normalscan table to 16 */ data_lsb_set (&Regs[0xed], 0x10, 3); /* set last step of deccurve.smearing table to 16 */ data_lsb_set (&Regs[0xf0], 0x10, 3); /* set last step of deccurve.parkhome table to 16 */ data_lsb_set (&Regs[0xf3], 0x10, 3); /* set msi */ cpRegs[0xda] = 2; cpRegs[0xdd] &= 0xfc; /* set if motor has motorcurves */ data_bitset (&cpRegs[0xdf], 0x10, ((mymotor->motorcurve != -1) ? 1 : 0)); if (mymotor->motorcurve != -1) { struct st_curve *crv; /* set last step of accurve.normalscan table */ crv = Motor_Curve_Get (dev, mymotor->motorcurve, ACC_CURVE, CRV_NORMALSCAN); if (crv != NULL) data_lsb_set (&cpRegs[0xe1], crv->step[crv->step_count - 1], 3); DBG (DBG_FNC, " -> Setting up stepper motor using motorcurve %i\n", mymotor->motorcurve); v12dcf8 = Motor_Setup_Steps (dev, cpRegs, mymotor->motorcurve); /* set step_size - 1 */ cpRegs[0xe0] = 0; crv = Motor_Curve_Get (dev, mymotor->motorcurve, DEC_CURVE, CRV_NORMALSCAN); if (crv != NULL) coord_y -= (v12dcf8 + crv->step_count); /* set line exposure time */ data_lsb_set (&cpRegs[0x30], mymotor->ctpc, 3); /* set last step of accurve.smearing table */ data_lsb_set (&cpRegs[0xe4], 0, 3); } else { /* Setting some motor step */ SANE_Int some_step; switch (Regs[0x00] & 0x0f) { case 0x00: some_step = 0x00895440; break; /* 3 x 0x2DC6C0 */ case 0x08: case 0x01: some_step = 0x00b71b00; break; /* 4 x 0x2DC6C0 */ case 0x02: some_step = 0x0112a880; break; /* 6 x 0x2DC6C0 */ case 0x0a: case 0x03: some_step = 0x016e3600; break; /* 8 x 0x2DC6C0 */ case 0x04: some_step = 0x02255100; break; /* 12 x 0x2DC6C0 */ case 0x0c: some_step = 0x02dc6c00; break; /* 16 x 0x2DC6C0 */ case 0x05: some_step = 0x044aa200; break; /* 24 x 0x2DC6C0 */ case 0x0d: some_step = 0x05b8d800; break; /* 32 x 0x2DC6C0 */ case 0x09: some_step = 0x00f42400; break; case 0x0b: some_step = 0x01e84800; break; /* = case 9 * 2 */ default: some_step = 0x0478f7f8; break; } /* divide by timing.cnpp */ some_step /= ((cpRegs[0x96] & 0x3f) + 1); if (mymotor->ctpc > 0) some_step /= mymotor->ctpc; /* set line exposure time */ data_lsb_set (&cpRegs[0x30], some_step, 3); /* set last step of accurve.normalscan table */ data_lsb_set (&cpRegs[0xe1], some_step, 3); } /* Setting coords */ RTS_Setup_Coords (cpRegs, 100, coord_y - 1, 800, 1); /* enable head movement */ data_bitset (&cpRegs[0xd8], 0x80, 1); /* release motor before executing */ Motor_Release (dev); RTS_Warm_Reset (dev); /* action! */ data = RTS_WriteRegs (dev->usb_handle, cpRegs); if (data == OK) RTS_Execute (dev); /* wait 10 seconds */ RTS_WaitScanEnd (dev, 10000); rst = (data != OK) ? v12dcf8 : RTS_WaitScanEnd (dev, 20000); free (cpRegs); } DBG (DBG_FNC, "- Motor_Move: %i\n", rst); return rst; } static void Free_Motormoves (struct st_device *dev) { DBG (DBG_FNC, "> Free_Motormoves\n"); if (dev->motormove != NULL) { SANE_Int a; struct st_motormove *ms; for (a = 0; a < dev->motormove_count; a++) { ms = dev->motormove[a]; if (ms != NULL) free (ms); } free (dev->motormove); dev->motormove = NULL; } dev->motormove_count = 0; } static void Free_MotorCurves (struct st_device *dev) { DBG (DBG_FNC, "> Free_MotorCurves\n"); if (dev->mtrsetting != NULL) Motor_Curve_Free (dev->mtrsetting, &dev->mtrsetting_count); dev->mtrsetting = NULL; dev->mtrsetting_count = 0; } static SANE_Int Load_MotorCurves (struct st_device *dev) { SANE_Int rst = ERROR; SANE_Int *mtc = NULL; if (dev->mtrsetting != NULL) Free_MotorCurves (dev); DBG (DBG_FNC, "> Load_MotorCurves\n"); /* get motor setttings buffer for this device */ mtc = cfg_motorcurve_get (); if (mtc != NULL) { /* parse buffer to get all motorcurves */ dev->mtrsetting = Motor_Curve_Parse (&dev->mtrsetting_count, mtc); if (dev->mtrsetting != NULL) rst = OK; } if (rst != ERROR) { DBG (DBG_FNC, " -> Found %i motor settings\n", dev->mtrsetting_count); dbg_motorcurves (dev); } else DBG (DBG_ERR, "- Load_MotorCurves error!!\n"); return rst; } static SANE_Int Load_Motormoves (struct st_device *dev) { SANE_Int rst = OK; SANE_Int a; struct st_motormove reg, *mm; DBG (DBG_FNC, "> Load_Motormoves\n"); /* if there is already any movement loaded let's free it */ if (dev->motormove != NULL) Free_Motormoves (dev); a = 0; while ((cfg_motormove_get (dev->sensorcfg->type, a, ®) != ERROR) && (rst == OK)) { dev->motormove_count++; dev->motormove = (struct st_motormove **) realloc (dev->motormove, sizeof (struct st_motormove **) * dev->motormove_count); if (dev->motormove != NULL) { mm = (struct st_motormove *) malloc (sizeof (struct st_motormove)); if (mm != NULL) { memcpy (mm, ®, sizeof (struct st_motormove)); dev->motormove[dev->motormove_count - 1] = mm; } else rst = ERROR; } else rst = ERROR; a++; } if (rst == ERROR) Free_Motormoves (dev); DBG (DBG_FNC, " -> Found %i motormoves\n", dev->motormove_count); dbg_motormoves (dev); return rst; } static SANE_Byte * Motor_AddStep (SANE_Byte * steps, SANE_Int * bwriten, SANE_Int step) { steps = (SANE_Byte *) realloc (steps, sizeof (SANE_Byte) * (*bwriten + 3)); if (steps != NULL) { data_msb_set (&steps[*bwriten], step, 3); *bwriten += 3; } else *bwriten = 0; return steps; } static SANE_Int Motor_Setup_Steps (struct st_device *dev, SANE_Byte * Regs, SANE_Int mysetting) { SANE_Int varx10, cont, last_acc_step, varx20, stepbuffer_size, mystep, bwriten; SANE_Int myvar, var1, myvalor, mybwriten; struct st_curve *mycurve; SANE_Byte *steps; DBG (DBG_FNC, "+ Motor_Setup_Steps(*Regs, motorsetting=%i):\n", mysetting); varx10 = 0; cont = 0; varx20 = 0; stepbuffer_size = (v15f8 << 4) & 0xffff; steps = NULL; bwriten = 0; deccurvecount = 0; acccurvecount = 0; last_acc_step = 0; /* mycurve points to acc normalscan steps table */ mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_NORMALSCAN); if (mycurve != NULL) { /* acccurvecount has the number of steps in acc normalscan table */ acccurvecount = mycurve->step_count; /* get last acccurve step from acc.normalscan step table */ last_acc_step = data_lsb_get (&Regs[0xe1], 3); /* sets pointer to acc.normalscan step table */ data_wide_bitset (&Regs[0xf6], 0x3fff, stepbuffer_size); /* Separate each step in three bytes */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) { mystep = mycurve->step[cont]; if (mystep <= last_acc_step) { acccurvecount = cont; break; } varx20 += mystep + 1; steps = Motor_AddStep (steps, &bwriten, mystep); } } if (acccurvecount == 0) { /* Write one step (last_acc_step + 0x01) to buffer */ acccurvecount++; varx20 += (last_acc_step + 1) + 1; steps = Motor_AddStep (steps, &bwriten, last_acc_step + 1); } /* write another step (last_acc_step) */ acccurvecount++; varx20 += last_acc_step + 1; steps = Motor_AddStep (steps, &bwriten, last_acc_step); /* get line exposure time */ myvar = data_lsb_get (&Regs[0x30], 3) + 1; var1 = (varx20 + myvar - 1) / myvar; var1 = ((var1 * myvar) + mycurve->step[0] - varx20) - 0x0d; if (steps != NULL) data_msb_set (&steps[0], var1, 3); /* dec.scanbufferfull step table */ /* set pointer to next table */ stepbuffer_size += (acccurvecount * 3); data_wide_bitset (&Regs[0xf8], 0x3fff, stepbuffer_size); /* set last step of deccurve.scanbufferfull table */ mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_BUFFERFULL); deccurvecount = mycurve->step_count; data_lsb_set (&Regs[0xea], mycurve->step[mycurve->step_count - 1], 3); /* write another step mycurve->step_count,cont,last_acc_step */ deccurvecount++; steps = Motor_AddStep (steps, &bwriten, last_acc_step); /* Separate each step in three bytes */ if (mycurve->step_count > 1) for (cont = 0; cont < (mycurve->step_count - 1); cont++) { mystep = mycurve->step[cont]; if (mystep > last_acc_step) steps = Motor_AddStep (steps, &bwriten, mystep); else deccurvecount--; } myvalor = dev->mtrsetting[mysetting]->motorbackstep; if (myvalor > 0) { SANE_Int step_size = _B0 (Regs[0xe0]) + 1; myvalor = ((myvalor - deccurvecount) - acccurvecount) + 2; varx10 = myvalor; myvalor /= step_size; myvalor *= step_size; var1 = mycurve->step[mycurve->step_count - 1]; /* last deccurve step */ if (last_acc_step >= var1) var1 = last_acc_step + 1; deccurvecount += (varx10 - myvalor); myvalor = varx10 - myvalor; } else myvalor = varx10; if (myvalor > 0) for (cont = myvalor; cont > 0; cont--) steps = Motor_AddStep (steps, &bwriten, var1 - 1); /* write another step , bwriten tiene 4b */ steps = Motor_AddStep (steps, &bwriten, var1); /* acc.smearing step table */ if (Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_SMEARING) != NULL) { /* acc.smearing curve enabled */ if (Motor_Curve_Equal (dev, mysetting, ACC_CURVE, CRV_SMEARING, CRV_NORMALSCAN) == TRUE) { /* acc.smearing pointer points to acc.normalscan table */ data_wide_bitset (&Regs[0xfa], 0x3fff, data_lsb_get (&Regs[0xf6], 2)); /* last step of acc.smearing table is the same as acc.normalscan */ data_lsb_set (&Regs[0xe4], data_lsb_get (&Regs[0xe1], 3), 3); } else { /* set pointer to next step table */ stepbuffer_size += (deccurvecount * 3); data_wide_bitset (&Regs[0xfa], 0x3fff, stepbuffer_size); /* set last step of acc.smearing table */ mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_SMEARING); if (mycurve != NULL) { smearacccurvecount = mycurve->step_count; data_lsb_set (&Regs[0xe4], mycurve->step[mycurve->step_count - 1], 3); /* generate acc.smearing table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* acc.smearing curve disabled */ data_wide_bitset (&Regs[0xfa], 0x3fff, 0); } /* dec.smearing */ if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_SMEARING) != NULL) { /* dec.smearing curve enabled */ if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_SMEARING, CRV_BUFFERFULL) == TRUE) { /* dec.smearing pointer points to dec.scanbufferfull table */ data_wide_bitset (&Regs[0x00fc], 0x3fff, data_lsb_get (&Regs[0x00f8], 2)); /* last step of dec.smearing table is the same as dec.scanbufferfull */ data_lsb_set (&Regs[0x00f0], data_lsb_get (&Regs[0x00ea], 3), 3); } else { /* set pointer to next step table */ if (mycurve != NULL) stepbuffer_size += (mycurve->step_count * 3); data_wide_bitset (&Regs[0xfc], 0x3fff, stepbuffer_size); /* set last step of dec.smearing table */ mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_SMEARING); if (mycurve != NULL) { smeardeccurvecount = mycurve->step_count; data_lsb_set (&Regs[0xf0], mycurve->step[mycurve->step_count - 1], 3); /* generate dec.smearing table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* dec.smearing curve disabled */ data_wide_bitset (&Regs[0x00fc], 0x3fff, 0); } /* dec.normalscan */ if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN) != NULL) { /* dec.normalscan enabled */ if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN, CRV_BUFFERFULL) == TRUE) { /* dec.normalscan pointer points to dec.scanbufferfull table */ data_wide_bitset (&Regs[0xfe], 0x3fff, data_lsb_get (&Regs[0xf8], 2)); /* last step of dec.normalscan table is the same as dec.scanbufferfull */ data_lsb_set (&Regs[0xed], data_lsb_get (&Regs[0xea], 3), 3); } else if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN, CRV_SMEARING) == TRUE) { /* dec.normalscan pointer points to dec.smearing table */ data_wide_bitset (&Regs[0xfe], 0x3fff, data_lsb_get (&Regs[0xfc], 2)); /* last step of dec.normalscan table is the same as dec.smearing */ data_lsb_set (&Regs[0xed], data_lsb_get (&Regs[0xf0], 3), 3); } else { /* set pointer to next step table */ if (mycurve != NULL) stepbuffer_size += (mycurve->step_count * 3); data_wide_bitset (&Regs[0xfe], 0x3fff, stepbuffer_size); /* set last step of dec.normalscan table */ mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_NORMALSCAN); if (mycurve != NULL) { data_lsb_set (&Regs[0xed], mycurve->step[mycurve->step_count - 1], 3); /* generate dec.normalscan table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* dec.normalscan disabled */ data_wide_bitset (&Regs[0xfe], 0x3fff, 0); } /* acc.parkhome */ if (Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_PARKHOME) != NULL) { /* parkhome curve enabled */ if (Motor_Curve_Equal (dev, mysetting, ACC_CURVE, CRV_PARKHOME, CRV_NORMALSCAN) == TRUE) { /* acc.parkhome pointer points to acc.normalscan table */ data_wide_bitset (&Regs[0x100], 0x3fff, data_lsb_get (&Regs[0xf6], 2)); /* last step of acc.parkhome table is the same as acc.normalscan */ data_lsb_set (&Regs[0xe7], data_lsb_get (&Regs[0xe1], 3), 3); } else if (Motor_Curve_Equal (dev, mysetting, ACC_CURVE, CRV_PARKHOME, CRV_SMEARING) == TRUE) { /* acc.parkhome pointer points to acc.smearing table */ data_wide_bitset (&Regs[0x100], 0x3fff, data_lsb_get (&Regs[0xfa], 2)); /* last step of acc.parkhome table is the same as acc.smearing */ data_lsb_set (&Regs[0xe7], data_lsb_get (&Regs[0xe4], 3), 3); } else { /* set pointer to next step table */ if (mycurve != NULL) stepbuffer_size += (mycurve->step_count * 3); data_wide_bitset (&Regs[0x100], 0x3fff, stepbuffer_size); /* set last step of acc.parkhome table */ mycurve = Motor_Curve_Get (dev, mysetting, ACC_CURVE, CRV_PARKHOME); if (mycurve != NULL) { data_lsb_set (&Regs[0xe7], mycurve->step[mycurve->step_count - 1], 3); /* generate acc.parkhome table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* parkhome curve is disabled */ /* acc.parkhome pointer points to 0 */ data_wide_bitset (&Regs[0x100], 0x3fff, 0); data_lsb_set (&Regs[0xe7], 16, 3); } /* dec.parkhome */ if (Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_PARKHOME) != NULL) { /* parkhome curve enabled */ if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_BUFFERFULL) == TRUE) { /* dec.parkhome pointer points to dec.scanbufferfull table */ data_wide_bitset (&Regs[0x102], 0x3fff, data_lsb_get (&Regs[0xf8], 2)); /* last step of dec.parkhome table is the same as dec.scanbufferfull */ data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xe4], 3), 3); } else if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_SMEARING) == TRUE) { /* dec.parkhome pointer points to dec.smearing table */ data_wide_bitset (&Regs[0x102], 0x3fff, data_lsb_get (&Regs[0xfe], 2)); /* last step of dec.parkhome table is the same as dec.smearing */ data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xf0], 3), 3); } else if (Motor_Curve_Equal (dev, mysetting, DEC_CURVE, CRV_PARKHOME, CRV_NORMALSCAN) == TRUE) { /* dec.parkhome pointer points to dec.normalscan table */ data_wide_bitset (&Regs[0x102], 0x3fff, data_lsb_get (&Regs[0xfe], 2)); /* last step of dec.parkhome table is the same as dec.normalscan */ data_lsb_set (&Regs[0xf3], data_lsb_get (&Regs[0xed], 3), 3); } else { /* set pointer to next step table */ if (mycurve != NULL) stepbuffer_size += (mycurve->step_count * 3); data_wide_bitset (&Regs[0x102], 0x3fff, stepbuffer_size); /* set last step of dec.parkhome table */ mycurve = Motor_Curve_Get (dev, mysetting, DEC_CURVE, CRV_PARKHOME); if (mycurve != NULL) { data_lsb_set (&Regs[0xf3], mycurve->step[mycurve->step_count - 1], 3); /* generate dec.parkhome table */ if (mycurve->step_count > 0) for (cont = 0; cont < mycurve->step_count; cont++) steps = Motor_AddStep (steps, &bwriten, mycurve->step[cont]); } } } else { /* parkhome curve is disabled */ /* dec.parkhome pointer points to 0 */ data_wide_bitset (&Regs[0x102], 0x3fff, 0); data_lsb_set (&Regs[0xf3], 16, 3); } mybwriten = bwriten & 0x8000000f; if (mybwriten < 0) mybwriten = ((mybwriten - 1) | 0xfffffff0) + 1; if (mybwriten != 0) bwriten = (((bwriten & 0xffff) >> 0x04) + 1) << 0x04; bwriten = bwriten & 0xffff; /* display table */ DBG (DBG_FNC, " -> Direction Type Offset Last step\n"); DBG (DBG_FNC, " -> --------- -------------- ------ ---------\n"); DBG (DBG_FNC, " -> ACC_CURVE CRV_NORMALSCAN %6i %6i\n", data_lsb_get (&Regs[0x0f6], 2) & 0x3fff, data_lsb_get (&Regs[0x0e1], 3)); DBG (DBG_FNC, " -> ACC_CURVE CRV_SMEARING %6i %6i\n", data_lsb_get (&Regs[0x0fa], 2) & 0x3fff, data_lsb_get (&Regs[0x0e4], 3)); DBG (DBG_FNC, " -> ACC_CURVE CRV_PARKHOME %6i %6i\n", data_lsb_get (&Regs[0x100], 2) & 0x3fff, data_lsb_get (&Regs[0x0e7], 3)); DBG (DBG_FNC, " -> DEC_CURVE CRV_NORMALSCAN %6i %6i\n", data_lsb_get (&Regs[0x0fe], 2) & 0x3fff, data_lsb_get (&Regs[0x0ed], 3)); DBG (DBG_FNC, " -> DEC_CURVE CRV_SMEARING %6i %6i\n", data_lsb_get (&Regs[0x0fc], 2) & 0x3fff, data_lsb_get (&Regs[0x0f0], 3)); DBG (DBG_FNC, " -> DEC_CURVE CRV_PARKHOME %6i %6i\n", data_lsb_get (&Regs[0x102], 2) & 0x3fff, data_lsb_get (&Regs[0x0f3], 3)); DBG (DBG_FNC, " -> DEC_CURVE CRV_BUFFERFULL %6i %6i\n", data_lsb_get (&Regs[0x0f8], 2) & 0x3fff, data_lsb_get (&Regs[0x0ea], 3)); RTS_Warm_Reset (dev); /* send motor steps */ if (steps != NULL) { if (bwriten > 0) { /* lock */ SetLock (dev->usb_handle, Regs, TRUE); /* send steps */ RTS_DMA_Write (dev, 0x0000, v15f8, bwriten, steps); /* unlock */ SetLock (dev->usb_handle, Regs, FALSE); } free (steps); } DBG (DBG_FNC, "- Motor_Setup_Steps: %i\n", acccurvecount); return acccurvecount; } static SANE_Int Lamp_PWM_use (struct st_device *dev, SANE_Int enable) { SANE_Byte a, b; SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Lamp_PWM_use(enable=%i):\n", enable); if (Read_Byte (dev->usb_handle, 0xe948, &a) == OK) { if (Read_Byte (dev->usb_handle, 0xe9e0, &b) == OK) { if (enable != 0) { if (pwmlamplevel != 0x00) { b |= 0x80; dev->init_regs[0x01e0] &= 0x3f; dev->init_regs[0x01e0] |= 0x80; } else { a |= 0x40; b &= 0x3f; dev->init_regs[0x0148] |= 0x40; dev->init_regs[0x01e0] &= 0x3f; } } else { b &= 0x7f; a &= 0xbf; } if (Write_Byte (dev->usb_handle, 0xe948, a) == OK) rst = Write_Byte (dev->usb_handle, 0xe9e0, b); } } DBG (DBG_FNC, "- Lamp_PWM_use: %i\n", rst); return rst; } static SANE_Int SSCG_Enable (struct st_device *dev) { SANE_Int rst; SANE_Int sscg; SANE_Byte data1, data2; SANE_Int enable, mode, clock; DBG (DBG_FNC, "+ SSCG_Enable:\n"); rst = cfg_sscg_get (&enable, &mode, &clock); if (rst == OK) { if ((Read_Byte (dev->usb_handle, 0xfe3a, &data1) == OK) && (Read_Byte (dev->usb_handle, 0xfe39, &data2) == OK)) { if (enable != FALSE) { /* clock values: 0=0.25%; 1=0.50%; 2=0.75%; 3=1.00% */ data2 = (mode == 0) ? data2 & 0x7f : data2 | 0x80; sscg = (data1 & 0xf3) | (((clock & 0x03) | 0x04) << 0x02); sscg = (sscg << 8) | data2; } else sscg = ((data1 & 0xef) << 8) | _B0 (data2); rst = Write_Word (dev->usb_handle, 0xfe39, sscg); } else rst = ERROR; } DBG (DBG_FNC, "- SSCG_Enable: %i\n", rst); return rst; } static void RTS_Setup_RefVoltages (struct st_device *dev, SANE_Byte * Regs) { /* this function sets top, midle and bottom reference voltages */ DBG (DBG_FNC, "> RTS_Setup_RefVoltages\n"); if (Regs != NULL) { SANE_Byte vrts, vrms, vrbs; cfg_refvoltages_get (dev->sensorcfg->type, &vrts, &vrms, &vrbs); /* Top Reference Voltage */ data_bitset (&Regs[0x14], 0xe0, vrts); /*xxx----- */ /* Middle Reference Voltage */ data_bitset (&Regs[0x15], 0xe0, vrms); /*xxx----- */ /* Bottom Reference Voltage */ data_bitset (&Regs[0x16], 0xe0, vrbs); /*xxx----- */ } } static SANE_Int Init_USBData (struct st_device *dev) { SANE_Byte data; SANE_Byte *resource; DBG (DBG_FNC, "+ Init_USBData:\n"); if (Read_Byte (dev->usb_handle, 0xf8ff, &data) != OK) return ERROR; data = (data | 1); if (Write_Byte (dev->usb_handle, 0xf8ff, data) != OK) return ERROR; if (SSCG_Enable (dev) != OK) return ERROR; Init_Registers (dev); /* Gamma table size = 0x100 */ data_bitset (&dev->init_regs[0x1d0], 0x30, 0x00); /*--00----*/ /* Set 3 channels_per_dot */ data_bitset (&dev->init_regs[0x12], 0xc0, 0x03); /*xx------ */ /* systemclock */ data_bitset (&dev->init_regs[0x00], 0x0f, 0x05); /*----xxxx*/ /* timing cnpp */ data_bitset (&dev->init_regs[0x96], 0x3f, 0x17); /*--xxxxxx*/ /* set sensor_channel_color_order */ data_bitset (&dev->init_regs[0x60a], 0x7f, 0x24); /*-xxxxxxx*/ /* set crvs */ data_bitset (&dev->init_regs[0x10], 0x1f, get_value (SCAN_PARAM, CRVS, 7, usbfile)); /*---xxxxx*/ /* set reference voltages */ RTS_Setup_RefVoltages (dev, dev->init_regs); dev->init_regs[0x11] |= 0x10; data_bitset (&dev->init_regs[0x26], 0x70, 5); /*-101----*/ dev->init_regs[0x185] = 0x88; dev->init_regs[0x186] = 0x88; /* SDRAM clock */ data = get_value (SCAN_PARAM, MCLKIOC, 8, usbfile); data_bitset (&dev->init_regs[0x187], 0x0f, 0x08); /*----xxxx*/ data_bitset (&dev->init_regs[0x187], 0xf0, data); /*xxxx---- */ data--; if (data < 7) { switch (data) { case 0: data |= 0xc0; break; case 1: data |= 0xa0; break; case 2: data |= 0xe0; break; case 3: data |= 0x90; break; case 4: data |= 0xd0; break; case 5: data |= 0xb0; break; case 6: data = (data & 0x0f); break; } dev->init_regs[0x187] = _B0 (data); } data_bitset (&dev->init_regs[0x26], 0x0f, 0); /*----0000*/ dev->init_regs[0x27] &= 0x3f; dev->init_regs[0x29] = 0x24; dev->init_regs[0x2a] = 0x10; dev->init_regs[0x150] = 0xff; dev->init_regs[0x151] = 0x13; dev->init_regs[0x156] = 0xf0; dev->init_regs[0x157] = 0xfd; if (dev->motorcfg->changemotorcurrent != FALSE) Motor_Change (dev, dev->init_regs, 3); dev->init_regs[0xde] = 0; data_bitset (&dev->init_regs[0xdf], 0x0f, 0); /* loads motor resource for this dev */ resource = cfg_motor_resource_get (&data); if ((resource != NULL) && (data > 1)) memcpy (&dev->init_regs[0x104], resource, data); /* this bit is set but I don't know its purpose */ dev->init_regs[0x01] |= 0x40; /*-1------*/ dev->init_regs[0x124] = 0x94; /* release motor */ Motor_Release (dev); DBG (DBG_FNC, "- Init_USBData:\n"); return OK; } static SANE_Int Init_Registers (struct st_device *dev) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Init_Registers:\n"); /* Lee dev->init_regs */ bzero (dev->init_regs, RT_BUFFER_LEN); RTS_ReadRegs (dev->usb_handle, dev->init_regs); Read_FE3E (dev, &v1619); if (dev->sensorcfg->type == CCD_SENSOR) { /* CCD sensor */ data_bitset (&dev->init_regs[0x11], 0xc0, 0); /*xx------ */ data_bitset (&dev->init_regs[0x146], 0x80, 1); /*x------- */ data_bitset (&dev->init_regs[0x146], 0x40, 1); /*-x------*/ } else { /* CIS sensor */ data_bitset (&dev->init_regs[0x146], 0x80, 0); /*0------- */ data_bitset (&dev->init_regs[0x146], 0x40, 0); /*-0------*/ data_bitset (&dev->init_regs[0x11], 0xc0, 2); /*xx------ */ data_bitset (&dev->init_regs[0xae], 0x3f, 0x14); /*--xxxxxx*/ data_bitset (&dev->init_regs[0xaf], 0x07, 1); /*-----xxx*/ dev->init_regs[0x9c] = dev->init_regs[0xa2] = dev->init_regs[0xa8] = (RTS_Debug->dev_model != UA4900) ? 1 : 0; dev->init_regs[0x9d] = dev->init_regs[0xa3] = dev->init_regs[0xa9] = 0; dev->init_regs[0x9e] = dev->init_regs[0xa4] = dev->init_regs[0xaa] = 0; dev->init_regs[0x9f] = dev->init_regs[0xa5] = dev->init_regs[0xab] = 0; dev->init_regs[0xa0] = dev->init_regs[0xa6] = dev->init_regs[0xac] = 0; dev->init_regs[0xa1] = dev->init_regs[0xa7] = dev->init_regs[0xad] = (RTS_Debug->dev_model != UA4900) ? 0x80 : 0; } /* disable CCD channels */ data_bitset (&dev->init_regs[0x10], 0xe0, 0); /*xxx----- */ data_bitset (&dev->init_regs[0x13], 0x80, 0); /*x------- */ /* enable timer to switch off lamp */ data_bitset (&dev->init_regs[0x146], 0x10, 1); /*---x----*/ /* set time to switch off lamp */ dev->init_regs[0x147] = 0xff; /* set last acccurve step */ data_lsb_set (&dev->init_regs[0xe1], 0x2af8, 3); /* set msi 0x02 */ dev->init_regs[0xda] = 0x02; data_bitset (&dev->init_regs[0xdd], 0x03, 0); /*------xx*/ /* set binary threshold high and low in little endian */ data_lsb_set (&dev->init_regs[0x19e], binarythresholdl, 2); data_lsb_set (&dev->init_regs[0x1a0], binarythresholdh, 2); data_bitset (&dev->init_regs[0x01], 0x08, 0); /*----x---*/ data_bitset (&dev->init_regs[0x16f], 0x40, 0); /*-x------*/ dev->init_regs[0x0bf] = (dev->init_regs[0x00bf] & 0xe0) | 0x20; dev->init_regs[0x163] = (dev->init_regs[0x0163] & 0x3f) | 0x40; data_bitset (&dev->init_regs[0xd6], 0x0f, 8); /*----xxxx*/ data_bitset (&dev->init_regs[0x164], 0x80, 1); /*x------- */ dev->init_regs[0x0bc] = 0x00; dev->init_regs[0x0bd] = 0x00; dev->init_regs[0x165] = (dev->init_regs[0x0165] & 0x3f) | 0x80; dev->init_regs[0x0ed] = 0x10; dev->init_regs[0x0be] = 0x00; dev->init_regs[0x0d5] = 0x00; dev->init_regs[0xee] = 0x00; dev->init_regs[0xef] = 0x00; dev->init_regs[0xde] = 0xff; /* set bit[4] has_curves = 0 | bit[0..3] unknown = 0 */ data_bitset (&dev->init_regs[0xdf], 0x10, 0); /*---x----*/ data_bitset (&dev->init_regs[0xdf], 0x0f, 0); /*----xxxx*/ /* Set motor type */ data_bitset (&dev->init_regs[0xd7], 0x80, dev->motorcfg->type); /*x------- */ if (dev->motorcfg->type == MT_ONCHIP_PWM) { data_bitset (&dev->init_regs[0x14e], 0x10, 1); /*---x----*/ /* set motorpwmfrequency */ data_bitset (&dev->init_regs[0xd7], 0x3f, dev->motorcfg->pwmfrequency); /*--xxxxxx*/ } dev->init_regs[0x600] &= 0xfb; dev->init_regs[0x1d8] |= 0x08; v160c_block_size = 0x04; mem_total = 0x80000; /* check and setup installed ram */ RTS_DMA_CheckType (dev, dev->init_regs); rst = RTS_DMA_WaitReady (dev, 1500); DBG (DBG_FNC, "- Init_Registers: %i\n", rst); return rst; } static SANE_Int Read_FE3E (struct st_device *dev, SANE_Byte * destino) { SANE_Int rst; DBG (DBG_FNC, "+ Read_FE3E:\n"); rst = ERROR; if (destino != NULL) { SANE_Byte data; if (Read_Byte (dev->usb_handle, 0xfe3e, &data) == 0) { *destino = data; rst = OK; DBG (DBG_FNC, " -> %02x\n", _B0 (data)); } } DBG (DBG_FNC, "- Read_FE3E: %i\n", rst); return rst; } static SANE_Int Head_IsAtHome (struct st_device *dev, SANE_Byte * Regs) { SANE_Int rst; DBG (DBG_FNC, "+ Head_IsAtHome:\n"); /* if returns TRUE, lamp is at home. Otherwise it returns FALSE */ rst = 0; if (Regs != NULL) { SANE_Byte data; if (Read_Byte (dev->usb_handle, 0xe96f, &data) == OK) { Regs[0x16f] = _B0 (data); rst = (data >> 6) & 1; } } rst = (rst == 1) ? TRUE : FALSE; DBG (DBG_FNC, "- Head_IsAtHome: %s\n", (rst == TRUE) ? "Yes" : "No"); return rst; } static SANE_Byte RTS_IsExecuting (struct st_device *dev, SANE_Byte * Regs) { SANE_Byte rst; DBG (DBG_FNC, "+ RTS_IsExecuting:\n"); rst = 0; if (Regs != NULL) { SANE_Byte data; if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) { Regs[0x00] = data; rst = (data >> 7) & 1; } } DBG (DBG_FNC, "- RTS_IsExecuting: %i\n", rst); return rst; } static SANE_Int RTS_WaitScanEnd (struct st_device *dev, SANE_Int msecs) { SANE_Byte data; SANE_Int rst; DBG (DBG_FNC, "+ RTS_WaitScanEnd(msecs=%i):\n", msecs); /* returns 0 if ok or timeout returns -1 if fails */ rst = ERROR; if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) { long ticks = GetTickCount () + msecs; rst = OK; while (((data & 0x80) != 0) && (ticks > GetTickCount ()) && (rst == OK)) { rst = Read_Byte (dev->usb_handle, 0xe800, &data); } } DBG (DBG_FNC, "- RTS_WaitScanEnd: Ending with rst=%i\n", rst); return rst; } static SANE_Int RTS_Enable_CCD (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_Enable_CCD(*Regs, arg2=%i):\n", channels); if (Read_Buffer (dev->usb_handle, 0xe810, &Regs[0x10], 4) == OK) { data_bitset (&Regs[0x10], 0xe0, channels); /*xxx----- */ data_bitset (&Regs[0x13], 0x80, channels >> 3); /*x------- */ Write_Buffer (dev->usb_handle, 0xe810, &Regs[0x10], 4); rst = OK; } DBG (DBG_FNC, "- RTS_Enable_CCD: %i\n", rst); return rst; } static SANE_Int RTS_Warm_Reset (struct st_device *dev) { SANE_Byte data; SANE_Int rst; DBG (DBG_FNC, "+ RTS_Warm_Reset:\n"); rst = ERROR; if (Read_Byte (dev->usb_handle, 0xe800, &data) == OK) { data = (data & 0x3f) | 0x40; /*01------ */ if (Write_Byte (dev->usb_handle, 0xe800, data) == OK) { data &= 0xbf; /*-0------*/ rst = Write_Byte (dev->usb_handle, 0xe800, data); } } DBG (DBG_FNC, "- RTS_Warm_Reset: %i\n", rst); return rst; } static SANE_Int Lamp_Status_Timer_Set (struct st_device *dev, SANE_Int minutes) { SANE_Byte MyBuffer[2]; SANE_Int rst; DBG (DBG_FNC, "+ Lamp_Status_Timer_Set(minutes=%i):\n", minutes); MyBuffer[0] = dev->init_regs[0x0146] & 0xef; MyBuffer[1] = dev->init_regs[0x0147]; if (minutes > 0) { double rst, op2; minutes = _B0 (minutes); op2 = 2.682163611980331; MyBuffer[0x00] |= 0x10; rst = (minutes * op2); MyBuffer[0x01] = (SANE_Byte) floor (rst); } dev->init_regs[0x147] = MyBuffer[1]; dev->init_regs[0x146] = (dev->init_regs[0x146] & 0xef) | (MyBuffer[0] & 0x10); rst = Write_Word (dev->usb_handle, 0xe946, (SANE_Int) ((MyBuffer[1] << 8) + MyBuffer[0])); DBG (DBG_FNC, "- Lamp_Status_Timer_Set: %i\n", rst); return rst; } static SANE_Int Buttons_Enable (struct st_device *dev) { SANE_Int data, rst; DBG (DBG_FNC, "+ Buttons_Enable:\n"); if (Read_Word (dev->usb_handle, 0xe958, &data) == OK) { data |= 0x0f; rst = Write_Word (dev->usb_handle, 0xe958, data); } else rst = ERROR; DBG (DBG_FNC, "- Buttons_Enable: %i\n", rst); return rst; } static SANE_Int Buttons_Count (struct st_device *dev) { SANE_Int rst = 0; /* This chipset supports up to six buttons */ if (dev->buttons != NULL) rst = dev->buttons->count; DBG (DBG_FNC, "> Buttons_Count: %i\n", rst); return rst; } static SANE_Int Buttons_Status (struct st_device *dev) { SANE_Int rst = -1; SANE_Byte data; DBG (DBG_FNC, "+ Buttons_Status\n"); /* Each bit is 1 if button is not pressed, and 0 if it is pressed This chipset supports up to six buttons */ if (Read_Byte (dev->usb_handle, 0xe968, &data) == OK) rst = _B0 (data); DBG (DBG_FNC, "- Buttons_Status: %i\n", rst); return rst; } static SANE_Int Buttons_Released (struct st_device *dev) { SANE_Int rst = -1; SANE_Byte data; DBG (DBG_FNC, "+ Buttons_Released\n"); /* Each bit is 1 if button is released, until reading this register. Then entire register is cleared. This chipset supports up to six buttons */ if (Read_Byte (dev->usb_handle, 0xe96a, &data) == OK) rst = _B0 (data); DBG (DBG_FNC, "- Buttons_Released: %i\n", rst); return rst; } static SANE_Int Buttons_Order (struct st_device *dev, SANE_Int mask) { /* this is a way to order each button according to its bit in register 0xe968 */ SANE_Int rst = -1; if (dev->buttons != NULL) { SANE_Int a; for (a = 0; a < 6; a++) { if (dev->buttons->mask[a] == mask) { rst = a; break; } } } return rst; } static SANE_Int GainOffset_Clear (struct st_device *dev) { SANE_Int rst = OK; DBG (DBG_FNC, "+ GainOffset_Clear:\n"); /* clear offsets */ offset[CL_RED] = offset[CL_GREEN] = offset[CL_BLUE] = 0; /* save offsets */ /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { SANE_Int a; for (a = CL_RED; a <= CL_BLUE; a++) RTS_EEPROM_WriteWord (dev->usb_handle, 0x70 + (2 * a), 0); /* update checksum */ rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x76, 0); } DBG (DBG_FNC, "- GainOffset_Clear: %i\n", rst); return rst; } static SANE_Int Lamp_Status_Get (struct st_device *dev, SANE_Byte * flb_lamp, SANE_Byte * tma_lamp) { /* The only reason that I think windows driver uses two variables to get which lamp is switched on instead of one variable is that some chipset model could have both lamps switched on, so I'm maintaining such var */ SANE_Int rst = ERROR; /* default */ DBG (DBG_FNC, "+ Lamp_Status_Get:\n"); if ((flb_lamp != NULL) && (tma_lamp != NULL)) { SANE_Int data1; SANE_Byte data2; if (Read_Byte (dev->usb_handle, 0xe946, &data2) == OK) { if (Read_Word (dev->usb_handle, 0xe954, &data1) == OK) { rst = OK; *flb_lamp = 0; *tma_lamp = 0; switch (dev->chipset->model) { case RTS8822BL_03A: *flb_lamp = ((data2 & 0x40) != 0) ? 1 : 0; *tma_lamp = (((data2 & 0x20) != 0) && ((data1 & 0x10) == 1)) ? 1 : 0; break; default: if ((_B1 (data1) & 0x10) == 0) *flb_lamp = (data2 >> 6) & 1; else *tma_lamp = (data2 >> 6) & 1; break; } } } } DBG (DBG_FNC, "- Lamp_Status_Get: rst=%i flb=%i tma=%i\n", rst, _B0 (*flb_lamp), _B0 (*tma_lamp)); return rst; } static SANE_Int RTS_DMA_WaitReady (struct st_device *dev, SANE_Int msecs) { SANE_Byte data; SANE_Int rst; long mytime; DBG (DBG_FNC, "+ RTS_DMA_WaitReady(msecs=%i):\n", msecs); rst = OK; mytime = GetTickCount () + msecs; while ((mytime > GetTickCount ()) && (rst == OK)) { if (Read_Byte (dev->usb_handle, 0xef09, &data) == OK) { if ((data & 1) == 0) usleep (1000 * 100); else break; } else rst = ERROR; } DBG (DBG_FNC, "- RTS_DMA_WaitReady: %i\n", rst); return rst; } static SANE_Int RTS_WaitInitEnd (struct st_device *dev, SANE_Int msecs) { SANE_Byte data; SANE_Int rst; long mytime; DBG (DBG_FNC, "+ RTS_WaitInitEnd(msecs=%i):\n", msecs); rst = OK; mytime = GetTickCount () + msecs; while ((mytime > GetTickCount ()) && (rst == OK)) { if (Read_Byte (dev->usb_handle, 0xf910, &data) == OK) { if ((data & 8) == 0) usleep (1000 * 100); else break; } else rst = ERROR; } DBG (DBG_FNC, "- RTS_WaitInitEnd: %i\n", rst); return rst; } static SANE_Int Motor_Change (struct st_device *dev, SANE_Byte * buffer, SANE_Byte value) { SANE_Int data, rst; DBG (DBG_FNC, "+ Motor_Change(*buffer, value=%i):\n", value); if (Read_Word (dev->usb_handle, 0xe954, &data) == OK) { data &= 0xcf; /*--00----*/ value--; switch (value) { case 2: data |= 0x30; break; /*--11----*/ case 1: data |= 0x20; break; /*--10----*/ case 0: data |= 0x10; break; /*--01----*/ } buffer[0x154] = _B0 (data); rst = Write_Byte (dev->usb_handle, 0xe954, buffer[0x154]); } else rst = ERROR; DBG (DBG_FNC, "- Motor_Change: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int options, SANE_Int size, SANE_Byte * buffer) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_DMA_Read(dmacs=%04x, options=%04x, size=%i., *buffer):\n", dmacs, options, size); /* is there any buffer to send? */ if ((buffer != NULL) && (size > 0)) { /* reset dma */ if (RTS_DMA_Reset (dev) == OK) { /* prepare dma to read */ if (RTS_DMA_Enable_Read (dev, dmacs, size, options) == OK) { SANE_Int transferred; rst = Bulk_Operation (dev, BLK_READ, size, buffer, &transferred); } } } DBG (DBG_FNC, "- RTS_DMA_Read(): %i\n", rst); return rst; } static SANE_Int RTS_DMA_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int options, SANE_Int size, SANE_Byte * buffer) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_DMA_Write(dmacs=%04x, options=%04x, size=%i., *buffer):\n", dmacs, options, size); /* is there any buffer to send? */ if ((buffer != NULL) && (size > 0)) { /* reset dma */ if (RTS_DMA_Reset (dev) == OK) { /* prepare dma to write */ if (RTS_DMA_Enable_Write (dev, dmacs, size, options) == OK) { SANE_Int transferred; SANE_Byte *check_buffer; check_buffer = (SANE_Byte *) malloc (size); if (check_buffer != NULL) { /* if some transfer fails we try again until ten times */ SANE_Int a; for (a = 10; a > 0; a--) { /* send buffer */ Bulk_Operation (dev, BLK_WRITE, size, buffer, &transferred); /* prepare dma to read */ if (RTS_DMA_Enable_Read (dev, dmacs, size, options) == OK) { SANE_Int b = 0, diff = FALSE; /* read buffer */ Bulk_Operation (dev, BLK_READ, size, check_buffer, &transferred); /* check buffers */ while ((b < size) && (diff == FALSE)) { if (buffer[b] == check_buffer[b]) b++; else diff = TRUE; } /* if buffers are equal we can break loop */ if (diff == TRUE) { /* cancel dma */ RTS_DMA_Cancel (dev); /* prepare dma to write buffer again */ if (RTS_DMA_Enable_Write (dev, dmacs, size, options) != OK) break; } else { /* everything went ok */ rst = OK; break; } } else break; } /* free check buffer */ free (check_buffer); } else { /* for some reason it's not posible to allocate space to check sent buffer so we just write data */ Bulk_Operation (dev, BLK_WRITE, size, buffer, &transferred); rst = OK; } } } } DBG (DBG_FNC, "- RTS_DMA_Write(): %i\n", rst); return rst; } static SANE_Int RTS_DMA_CheckType (struct st_device *dev, SANE_Byte * Regs) { /* This function tries to detect what kind of RAM supports chipset */ /* Returns a value between 0 and 4. -1 means error */ SANE_Int rst = -1; DBG (DBG_FNC, "+ RTS_DMA_CheckType(*Regs):\n"); if (Regs != NULL) { SANE_Byte *out_buffer; /* define buffer to send */ out_buffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * 2072); if (out_buffer != NULL) { SANE_Byte *in_buffer; /* define incoming buffer */ in_buffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * 2072); if (in_buffer != NULL) { SANE_Int a, b, diff; /* fill outgoing buffer with a known pattern */ b = 0; for (a = 0; a < 2072; a++) { out_buffer[a] = b; b++; if (b == 0x61) b = 0; } /* let's send buffer with different ram types and compare incoming buffer until getting the right type */ for (a = 4; a >= 0; a--) { /* set ram type */ if (RTS_DMA_SetType (dev, Regs, a) != OK) break; /* wait 1500 miliseconds */ if (RTS_DMA_WaitReady (dev, 1500) == OK) { /* reset dma */ RTS_DMA_Reset (dev); /* write buffer */ RTS_DMA_Write (dev, 0x0004, 0x102, 2072, out_buffer); /* now read buffer */ RTS_DMA_Read (dev, 0x0004, 0x102, 2072, in_buffer); /* check buffers */ b = 0; diff = FALSE; while ((b < 2072) && (diff == FALSE)) { if (out_buffer[b] == in_buffer[b]) b++; else diff = TRUE; } /* if buffers are equal */ if (diff == FALSE) { SANE_Int data = 0; /* buffers are equal so we've found the right ram type */ memset (out_buffer, 0, 0x20); for (b = 0; b < 0x20; b += 2) out_buffer[b] = b; /* write buffer */ if (RTS_DMA_Write (dev, 0x0004, 0x0000, 0x20, out_buffer) == OK) { SANE_Int c = 0; diff = TRUE; do { c++; for (b = 1; b < 0x20; b += 2) out_buffer[b] = c; if (RTS_DMA_Write (dev, 0x0004, (_B0 (c) << 0x11) >> 0x04, 0x20, out_buffer) == OK) { if (RTS_DMA_Read (dev, 0x0004, 0x0000, 0x20, in_buffer) == OK) { b = 0; diff = FALSE; while ((b < 0x20) && (diff == FALSE)) { if (out_buffer[b] == in_buffer[b]) b++; else diff = TRUE; } if (diff == FALSE) data = c << 7; } } } while ((c < 0x80) && (diff == TRUE)); } switch (data) { case 16384: Regs[0x708] &= 0x1f; Regs[0x708] |= 0x80; break; case 8192: Regs[0x708] &= 0x1f; Regs[0x708] |= 0x60; break; case 4096: Regs[0x708] &= 0x1f; Regs[0x708] |= 0x40; break; case 2048: Regs[0x708] &= 0x1f; Regs[0x708] |= 0x20; break; case 1024: Regs[0x708] &= 0x1f; data = 0x200; break; case 128: Regs[0x708] &= 0x1f; break; } DBG (DBG_FNC, " -> data1 = 0x%08x\n", (data * 4) * 1024); DBG (DBG_FNC, " -> data2 = 0x%08x\n", data * 1024); DBG (DBG_FNC, " -> type = 0x%04x\n", Regs[0x708] >> 5); RTS_DMA_SetType (dev, Regs, Regs[0x708] >> 5); rst = OK; break; } } else break; } free (in_buffer); } free (out_buffer); } } DBG (DBG_FNC, "- RTS_DMA_CheckType(): %i\n", rst); return rst; } static SANE_Int RTS_DMA_SetType (struct st_device *dev, SANE_Byte * Regs, SANE_Byte ramtype) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_DMA_SetType(*Regs, ramtype=%i):\n", ramtype); if (Regs != NULL) { data_bitset (&Regs[0x708], 0x08, 0); /*----0---*/ if (Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]) == OK) { data_bitset (&Regs[0x708], 0xe0, ramtype); if (Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]) == OK) { data_bitset (&Regs[0x708], 0x08, 1); /*----1---*/ rst = Write_Byte (dev->usb_handle, 0xef08, Regs[0x708]); } } } DBG (DBG_FNC, "- RTS_DMA_SetType: %i\n", rst); return rst; } static void Motor_Release (struct st_device *dev) { SANE_Byte data = 0; DBG (DBG_FNC, "+ Motor_Release:\n"); if (Read_Byte (dev->usb_handle, 0xe8d9, &data) == OK) { data |= 4; Write_Byte (dev->usb_handle, 0xe8d9, data); } DBG (DBG_FNC, "- Motor_Release:\n"); } static SANE_Byte GainOffset_Counter_Load (struct st_device *dev) { SANE_Byte data = 0x0f; DBG (DBG_FNC, "+ GainOffset_Counter_Load:\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x77, &data) != OK) data = 0x0f; DBG (DBG_FNC, "- GainOffset_Counter_Load: %i\n", _B0 (data)); return data; } static SANE_Int RTS_Execute (struct st_device *dev) { SANE_Byte e813, e800; SANE_Int ret; DBG (DBG_FNC, "+ RTS_Execute:\n"); e813 = 0; e800 = 0; ret = ERROR; if (Read_Byte (dev->usb_handle, 0xe800, &e800) == OK) { if (Read_Byte (dev->usb_handle, 0xe813, &e813) == OK) { e813 &= 0xbf; if (Write_Byte (dev->usb_handle, 0xe813, e813) == OK) { e800 |= 0x40; if (Write_Byte (dev->usb_handle, 0xe800, e800) == OK) { e813 |= 0x40; if (Write_Byte (dev->usb_handle, 0xe813, e813) == OK) { e800 &= 0xbf; if (Write_Byte (dev->usb_handle, 0xe800, e800) == OK) { usleep (1000 * 100); e800 |= 0x80; ret = Write_Byte (dev->usb_handle, 0xe800, e800); } } } } } } DBG (DBG_FNC, "- RTS_Execute: %i\n", ret); return ret; } static SANE_Int RTS_isTmaAttached (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_isTmaAttached:\n"); /* returns 0 if Tma is attached. Otherwise 1 */ if (Read_Word (dev->usb_handle, 0xe968, &rst) == OK) { rst = ((_B1 (rst) & 2) != 0) ? FALSE : TRUE; } else rst = TRUE; DBG (DBG_FNC, "- RTS_isTmaAttached: %s\n", (rst == TRUE) ? "Yes" : "No"); return rst; } static SANE_Int Gamma_AllocTable (SANE_Byte * table) { SANE_Int C; SANE_Int rst = OK; hp_gamma->depth = 8; for (C = 0; C < 3; C++) if (hp_gamma->table[C] == NULL) hp_gamma->table[C] = malloc (sizeof (SANE_Byte) * 256); if ((hp_gamma->table[CL_RED] != NULL) && (hp_gamma->table[CL_GREEN] != NULL) && (hp_gamma->table[CL_BLUE] != NULL)) { /* All tables allocated */ for (C = 0; C < 256; C++) { if ((table != NULL) && (RTS_Debug->EnableGamma == TRUE)) { /* fill gamma tables with user defined values */ hp_gamma->table[CL_RED][C] = table[C]; hp_gamma->table[CL_GREEN][C] = table[0x100 + C]; hp_gamma->table[CL_BLUE][C] = table[0x200 + C]; } else { hp_gamma->table[CL_RED][C] = C; hp_gamma->table[CL_GREEN][C] = C; hp_gamma->table[CL_BLUE][C] = C; } } /* Locate threshold of bw */ for (C = 0; C < 256; C++) if (hp_gamma->table[CL_RED][C] != 0) break; bw_threshold = C - 1; } else { /* Some alloc failed */ rst = ERROR; Gamma_FreeTables (); } DBG (DBG_FNC, "> Gamma_AllocTable: %i >> bw_threshold = %i\n", rst, bw_threshold); return rst; } static SANE_Int Gamma_Apply (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, struct st_gammatables *mygamma) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Gamma_Apply(*Regs, *scancfg, *hwdcfg, *mygamma):\n"); dbg_ScanParams (scancfg); if (hwdcfg->use_gamma_tables == FALSE) { DBG (DBG_FNC, "-> Gamma tables are not used\n"); v1600 = NULL; v1604 = NULL; v1608 = NULL; } else { /*390b */ SANE_Int table_size, buffersize, c; SANE_Byte channels, *gammabuffer; DBG (DBG_FNC, "-> Using gamma tables\n"); /* get channels count */ channels = 3; /* default */ if (scancfg->colormode != CM_COLOR) { if (scancfg->channel != 3) { if (scancfg->colormode != 3) channels = (scancfg->samplerate == PIXEL_RATE) ? 2 : 1; } } /* get size for gamma tables */ switch (mygamma->depth & 0x0c) { case 0: table_size = 0x100 + (mygamma->depth & 1); break; case 4: table_size = 0x400 + (mygamma->depth & 1); break; case 8: table_size = 0x1000 + (mygamma->depth & 1); break; default: table_size = 2; break; } /* allocate space for gamma buffer */ buffersize = table_size * channels; gammabuffer = (SANE_Byte *) malloc (buffersize * sizeof (SANE_Byte)); if (gammabuffer != NULL) { /* update gamma pointers for each channel */ v1600 = (SANE_Byte *) & mygamma->table[CL_RED]; v1604 = (SANE_Byte *) & mygamma->table[CL_GREEN]; v1608 = (SANE_Byte *) & mygamma->table[CL_BLUE]; /* include gamma tables into one buffer */ for (c = 0; c < channels; c++) memcpy (gammabuffer + (c * table_size), mygamma->table[c], table_size); /* send gamma buffer to scanner */ Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b] & 0xaf); rst = Gamma_SendTables (dev, Regs, gammabuffer, buffersize); Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); /* free gamma buffer */ free (gammabuffer); } else rst = ERROR; } return rst; } static SANE_Int Refs_Analyze_Pattern (struct st_scanparams *scancfg, SANE_Byte * scanned_pattern, SANE_Int * ler1, SANE_Int ler1order, SANE_Int * ser1, SANE_Int ser1order) { SANE_Int buffersize, xpos, ypos, coord, cnt, chn_size, dist, rst; double *color_sum, *color_dif, diff_max; SANE_Int vector[3]; DBG (DBG_FNC, "+ Refs_Analyze_Pattern(depth=%i, width=%i, height=%i, *scanned_pattern, *ler1, ler1order=%i, *ser1, ser1order=%i)\n", scancfg->depth, scancfg->coord.width, scancfg->coord.height, ler1order, ser1order); rst = ERROR; /* by default */ dist = 5; /* distance to compare */ chn_size = (scancfg->depth > 8) ? 2 : 1; buffersize = max (scancfg->coord.width, scancfg->coord.height); color_sum = (double *) malloc (sizeof (double) * buffersize); if (color_sum != NULL) { color_dif = (double *) malloc (sizeof (double) * buffersize); if (color_dif != NULL) { /*-------- 1st SER -------- */ coord = 1; if ((scancfg->coord.width - dist) > 1) { /* clear buffers */ bzero (color_sum, sizeof (double) * buffersize); bzero (color_dif, sizeof (double) * buffersize); for (xpos = 0; xpos < scancfg->coord.width; xpos++) { for (ypos = 0; ypos < 20; ypos++) color_sum[xpos] += data_lsb_get (scanned_pattern + (scancfg->coord.width * ypos) + xpos, chn_size); } diff_max = (ser1order != 0) ? color_sum[0] - color_sum[1] : color_sum[1] - color_sum[0]; color_dif[0] = diff_max; cnt = 1; do { color_dif[cnt] = (ser1order != 0) ? color_sum[cnt] - color_sum[cnt + dist] : color_sum[cnt + dist] - color_sum[cnt]; if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max)) { /*d4df */ diff_max = color_dif[cnt]; if (abs (color_dif[cnt] - color_dif[cnt - 1]) > abs (color_dif[coord] - color_dif[coord - 1])) coord = cnt; } cnt++; } while (cnt < (scancfg->coord.width - dist)); } vector[0] = coord + dist; /*-------- 1st LER -------- */ coord = 1; if ((scancfg->coord.height - dist) > 1) { /* clear buffers */ bzero (color_sum, sizeof (double) * buffersize); bzero (color_dif, sizeof (double) * buffersize); for (ypos = 0; ypos < scancfg->coord.height; ypos++) { for (xpos = vector[0]; xpos < scancfg->coord.width - dist; xpos++) color_sum[ypos] += data_lsb_get (scanned_pattern + (scancfg->coord.width * ypos) + xpos, chn_size); } diff_max = (ler1order != 0) ? color_sum[0] - color_sum[1] : color_sum[1] - color_sum[0]; color_dif[0] = diff_max; cnt = 1; do { color_dif[cnt] = (ler1order != 0) ? color_sum[cnt] - color_sum[cnt + dist] : color_sum[cnt + dist] - color_sum[cnt]; if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max)) { diff_max = color_dif[cnt]; if (abs (color_dif[cnt] - color_dif[cnt - 1]) > abs (color_dif[coord] - color_dif[coord - 1])) coord = cnt; } cnt++; } while (cnt < (scancfg->coord.height - dist)); } vector[1] = coord + dist; /*-------- 1st LER -------- */ if ((scancfg->coord.width - dist) > 1) { /* clear buffers */ bzero (color_sum, sizeof (double) * buffersize); bzero (color_dif, sizeof (double) * buffersize); for (xpos = 0; xpos < scancfg->coord.width; xpos++) { for (ypos = coord + 4; ypos < scancfg->coord.height; ypos++) color_sum[xpos] += data_lsb_get (scanned_pattern + (scancfg->coord.width * ypos) + xpos, chn_size); } diff_max = (ser1order != 0) ? color_sum[0] - color_sum[1] : color_sum[1] - color_sum[0]; color_dif[0] = diff_max; cnt = 1; do { color_dif[cnt] = (ser1order != 0) ? color_sum[cnt] - color_sum[cnt + dist] : color_sum[cnt + dist] - color_sum[cnt]; if ((color_dif[cnt] >= 0) && (color_dif[cnt] > diff_max)) { diff_max = color_dif[cnt]; if (abs (color_dif[cnt] - color_dif[cnt - 1]) > abs (color_dif[coord] - color_dif[coord - 1])) coord = cnt; } cnt++; } while (cnt < (scancfg->coord.width - dist)); } vector[2] = coord + dist; /* save image */ if (RTS_Debug->SaveCalibFile != FALSE) dbg_autoref (scancfg, scanned_pattern, vector[0], vector[2], vector[1]); /* assign values detected */ if (ser1 != NULL) *ser1 = vector[2]; if (ler1 != NULL) *ler1 = vector[1]; /* show values */ DBG (DBG_FNC, " -> Vectors found: x1=%i, x2=%i, y=%i\n", vector[0], vector[2], vector[1]); rst = OK; free (color_dif); } free (color_sum); } DBG (DBG_FNC, "- Refs_Analyze_Pattern: %i\n", rst); return rst; } static double get_shrd (double value, SANE_Int desp) { if (desp <= 0x40) return value / pow (2, desp); else return 0; } static char get_byte (double value) { unsigned int data; double temp; if (value > 0xffffffff) { temp = floor (get_shrd (value, 0x20)); temp *= pow (2, 32); value -= temp; } data = (unsigned int) value; data = _B0 (data); return data; } static SANE_Int Timing_SetLinearImageSensorClock (SANE_Byte * Regs, struct st_cph *cph) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Timing_SetLinearImageSensorClock(SANE_Byte *Regs, struct st_cph *cph)\n"); dbg_sensorclock (cph); if ((Regs != NULL) && (cph != NULL)) { Regs[0x00] = get_byte (cph->p1); Regs[0x01] = get_byte (get_shrd (cph->p1, 0x08)); Regs[0x02] = get_byte (get_shrd (cph->p1, 0x10)); Regs[0x03] = get_byte (get_shrd (cph->p1, 0x18)); Regs[0x04] &= 0x80; Regs[0x04] |= ((get_byte (get_shrd (cph->p1, 0x20))) & 0x0f); Regs[0x04] |= ((cph->ps & 1) << 6); Regs[0x04] |= ((cph->ge & 1) << 5); Regs[0x04] |= ((cph->go & 1) << 4); Regs[0x05] = get_byte (cph->p2); Regs[0x06] = get_byte (get_shrd (cph->p2, 0x08)); Regs[0x07] = get_byte (get_shrd (cph->p2, 0x10)); Regs[0x08] = get_byte (get_shrd (cph->p2, 0x18)); Regs[0x09] &= 0xf0; Regs[0x09] |= ((get_byte (get_shrd (cph->p2, 0x20))) & 0x0f); rst = OK; } DBG (DBG_FNC, "- Timing_SetLinearImageSensorClock: %i\n", rst); return rst; } static void RTS_Setup_SensorTiming (struct st_device *dev, SANE_Int mytiming, SANE_Byte * Regs) { DBG (DBG_FNC, "+ RTS_Setup_SensorTiming(mytiming=%i, *Regs):\n", mytiming); if ((Regs != NULL) && (mytiming < dev->timings_count)) { struct st_timing *mt = dev->timings[mytiming]; if (mt != NULL) { dbg_timing (mt); /* Correlated-Double-Sample 1 & 2 */ data_bitset (&Regs[0x92], 0x3f, mt->cdss[0]); data_bitset (&Regs[0x93], 0x3f, mt->cdsc[0]); data_bitset (&Regs[0x94], 0x3f, mt->cdss[1]); data_bitset (&Regs[0x95], 0x3f, mt->cdsc[1]); data_bitset (&Regs[0x96], 0x3f, mt->cnpp); /* Linear image sensor transfer gates */ data_bitset (&Regs[0x45], 0x80, mt->cvtrp[0]); data_bitset (&Regs[0x45], 0x40, mt->cvtrp[1]); data_bitset (&Regs[0x45], 0x20, mt->cvtrp[2]); data_bitset (&Regs[0x45], 0x1f, mt->cvtrfpw); data_bitset (&Regs[0x46], 0x1f, mt->cvtrbpw); data_lsb_set (&Regs[0x47], mt->cvtrw, 1); data_lsb_set (&Regs[0x84], mt->cphbp2s, 3); data_lsb_set (&Regs[0x87], mt->cphbp2e, 3); data_lsb_set (&Regs[0x8a], mt->clamps, 3); data_lsb_set (&Regs[0x8d], mt->clampe, 3); if (dev->chipset->model == RTS8822L_02A) { if (mt->clampe == -1) data_lsb_set (&Regs[0x8d], mt->cphbp2e, 3); } Regs[0x97] = get_byte (mt->adcclkp[0]); Regs[0x98] = get_byte (get_shrd (mt->adcclkp[0], 0x08)); Regs[0x99] = get_byte (get_shrd (mt->adcclkp[0], 0x10)); Regs[0x9a] = get_byte (get_shrd (mt->adcclkp[0], 0x18)); Regs[0x9b] &= 0xf0; Regs[0x9b] |= ((get_byte (get_shrd (mt->adcclkp[0], 0x20))) & 0x0f); Regs[0xc1] = get_byte (mt->adcclkp[1]); Regs[0xc2] = get_byte (get_shrd (mt->adcclkp[1], 0x08)); Regs[0xc3] = get_byte (get_shrd (mt->adcclkp[1], 0x10)); Regs[0xc4] = get_byte (get_shrd (mt->adcclkp[1], 0x18)); Regs[0xc5] &= 0xe0; Regs[0xc5] |= ((get_byte (get_shrd (mt->adcclkp[1], 0x20))) & 0x0f); /* bit(4) = bit(0) */ Regs[0xc5] |= ((mt->adcclkp2e & 1) << 4); Timing_SetLinearImageSensorClock (&Regs[0x48], &mt->cph[0]); Timing_SetLinearImageSensorClock (&Regs[0x52], &mt->cph[1]); Timing_SetLinearImageSensorClock (&Regs[0x5c], &mt->cph[2]); Timing_SetLinearImageSensorClock (&Regs[0x66], &mt->cph[3]); Timing_SetLinearImageSensorClock (&Regs[0x70], &mt->cph[4]); Timing_SetLinearImageSensorClock (&Regs[0x7a], &mt->cph[5]); } } } static SANE_Int Motor_GetFromResolution (SANE_Int resolution) { SANE_Int ret; ret = 3; if (RTS_Debug->usbtype != USB11) { if (scan.scantype != ST_NORMAL) { /* scantype is ST_NEG or ST_TA */ if (resolution >= 600) ret = 0; } else if (resolution >= 1200) ret = 0; } else if (resolution >= 600) ret = 0; DBG (DBG_FNC, "> Motor_GetFromResolution(resolution=%i): %i\n", resolution, ret); return ret; } static SANE_Int SetMultiExposure (struct st_device *dev, SANE_Byte * Regs) { SANE_Int iValue, myctpc; DBG (DBG_FNC, "> SetMultiExposure:\n"); /* set motor has no curves */ data_bitset (&Regs[0xdf], 0x10, 0); /*---0----*/ /* select case systemclock */ switch (Regs[0x00] & 0x0f) { case 0x00: iValue = 0x00895440; break; /* 3 x 0x2DC6C0 */ case 0x08: case 0x01: iValue = 0x00b71b00; break; /* 4 x 0x2DC6C0 */ case 0x02: iValue = 0x0112a880; break; /* 6 x 0x2DC6C0 */ case 0x0a: case 0x03: iValue = 0x016e3600; break; /* 8 x 0x2DC6C0 */ case 0x04: iValue = 0x02255100; break; /* 12 x 0x2DC6C0 */ case 0x0c: iValue = 0x02dc6c00; break; /* 16 x 0x2DC6C0 */ case 0x05: iValue = 0x044aa200; break; /* 24 x 0x2DC6C0 */ case 0x0d: iValue = 0x05b8d800; break; /* 32 x 0x2DC6C0 */ case 0x09: iValue = 0x00f42400; break; case 0x0b: iValue = 0x01e84800; break; /* = case 9 * 2 */ default: iValue = 0x0478f7f8; break; } /* divide by timing.cnpp */ iValue /= ((Regs[0x96] & 0x3f) + 1); iValue /= dev->motorcfg->basespeedpps; /* get line exposure time */ myctpc = data_lsb_get (&Regs[0x30], 3) + 1; DBG (DBG_FNC, "CTPC -- SetMultiExposure -- 1 =%i\n", myctpc); /* if last step of accurve.normalscan table is lower than iValue ... */ if (data_lsb_get (&Regs[0xe1], 3) < iValue) { SANE_Int traget; SANE_Int step_size = _B0 (Regs[0xe0]) + 1; /* set exposure time [RED] if zero */ if (data_lsb_get (&Regs[0x36], 3) == 0) data_lsb_set (&Regs[0x36], myctpc - 1, 3); /* set exposure time [GREEN] if zero */ if (data_lsb_get (&Regs[0x3c], 3) == 0) data_lsb_set (&Regs[0x3c], myctpc - 1, 3); /* set exposure time [BLUE] if zero */ if (data_lsb_get (&Regs[0x42], 3) == 0) data_lsb_set (&Regs[0x42], myctpc - 1, 3); iValue = (iValue + 1) * step_size; /* update line exposure time */ traget = (((myctpc + iValue - 1) / myctpc) * myctpc); data_lsb_set (&Regs[0x30], traget - 1, 3); traget = (traget / step_size) - 1; data_lsb_set (&Regs[0x00e1], traget, 3); } /* 8300 */ return OK; } static SANE_Int data_lsb_get (SANE_Byte * address, SANE_Int size) { SANE_Int ret = 0; if ((address != NULL) && (size > 0) && (size < 5)) { SANE_Int a; SANE_Byte b; size--; for (a = size; a >= 0; a--) { b = address[a]; ret = (ret << 8) + b; } } return ret; } static SANE_Byte data_bitget (SANE_Byte * address, SANE_Int mask) { SANE_Int desp = 0; if (mask & 1); else if (mask & 2) desp = 1; else if (mask & 4) desp = 2; else if (mask & 8) desp = 3; else if (mask & 16) desp = 4; else if (mask & 32) desp = 5; else if (mask & 64) desp = 6; else if (mask & 128) desp = 7; return (*address & mask) >> desp; } static void data_bitset (SANE_Byte * address, SANE_Int mask, SANE_Byte data) { /* This function fills mask bits of just a byte with bits given in data */ if (mask & 1); else if (mask & 2) data <<= 1; else if (mask & 4) data <<= 2; else if (mask & 8) data <<= 3; else if (mask & 16) data <<= 4; else if (mask & 32) data <<= 5; else if (mask & 64) data <<= 6; else if (mask & 128) data <<= 7; *address = (*address & (0xff - mask)) | (data & mask); } static void data_wide_bitset (SANE_Byte * address, SANE_Int mask, SANE_Int data) { /* Setting bytes bit per bit mask is 4 bytes size Example: data = 0111010111 mask = 00000000 11111111 11000000 00000000 rst = 00000000 01110101 11000000 00000000 */ SANE_Int mymask, started = FALSE; if ((address != NULL) && (mask != 0)) { while (mask != 0) { mymask = _B0 (mask); if (started == FALSE) { if (mymask != 0) { SANE_Int a, myvalue; for (a = 0; a < 8; a++) if ((mymask & (1 << a)) != 0) break; myvalue = _B0 (data << a); myvalue >>= a; data_bitset (address, mymask, myvalue); data >>= (8 - a); started = TRUE; } } else { data_bitset (address, mymask, _B0 (data)); data >>= 8; } address++; mask >>= 8; } } } static void data_lsb_set (SANE_Byte * address, SANE_Int data, SANE_Int size) { if ((address != NULL) && (size > 0) && (size < 5)) { SANE_Int a; for (a = 0; a < size; a++) { address[a] = _B0 (data); data >>= 8; } } } static void data_msb_set (SANE_Byte * address, SANE_Int data, SANE_Int size) { if ((address != NULL) && (size > 0) && (size < 5)) { SANE_Int a; for (a = size - 1; a >= 0; a--) { address[a] = _B0 (data); data >>= 8; } } } static SANE_Int data_swap_endianess (SANE_Int address, SANE_Int size) { SANE_Int rst = 0; if ((size > 0) && (size < 5)) { SANE_Int a; for (a = 0; a < size; a++) { rst = (rst << 8) | _B0 (address); address >>= 8; } } return rst; } static void Lamp_SetGainMode (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution, SANE_Byte gainmode) { DBG (DBG_FNC, "> Lamp_SetGainMode(*Regs, resolution=%i, gainmode=%i):\n", resolution, gainmode); if (dev->chipset->model == RTS8822L_02A) { /* hp4370 */ SANE_Int data1, data2; data1 = data_lsb_get (&Regs[0x154], 2) & 0xfe7f; data2 = data_lsb_get (&Regs[0x156], 2); switch (resolution) { case 4800: data2 |= 0x40; data1 &= 0xffbf; break; case 100: case 150: case 200: case 300: case 600: case 1200: case 2400: data1 |= 0x40; data2 &= 0xffbf; break; } data_lsb_set (&Regs[0x154], data1, 2); data_lsb_set (&Regs[0x156], data2, 2); } else { /* hp3970 hp4070 ua4900 */ SANE_Int data; data = data_lsb_get (&Regs[0x154], 2) & 0xfe7f; data = (gainmode == FALSE) ? data | 0x0040 : data & 0xffbf; switch (resolution) { case 100: case 200: case 300: case 600: data |= 0x0100; break; case 2400: data |= 0x0180; break; case 1200: if (dev->sensorcfg->type == CIS_SENSOR) data |= 0x80; else if (dev->sensorcfg->type == CCD_SENSOR) data |= 0x0180; break; } data_lsb_set (&Regs[0x0154], data, 2); } } static SANE_Int RTS_Scanner_StartScan (struct st_device *dev) { SANE_Int rst = ERROR; /* default */ SANE_Int data; DBG (DBG_FNC, "+ RTS_Scanner_StartScan():\n"); v14b4 = 1; /* TEMPORAL */ data = 0; Lamp_PWM_DutyCycle_Get (dev, &data); data = _B0 (data); DBG (DBG_FNC, "-> Pwm used = %i\n", data); /* windows driver saves pwm used, in file usbfile Section [SCAN_PARAM], field PwmUsed */ dev->status->cancel = FALSE; if (Scan_Start (dev) == OK) { SANE_Int transferred; rst = OK; if (dev->scanning->imagebuffer != NULL) { free (dev->scanning->imagebuffer); dev->scanning->imagebuffer = NULL; } SetLock (dev->usb_handle, NULL, (scan2.depth == 16) ? FALSE : TRUE); /* Reservamos los buffers necesarios para leer la imagen */ Reading_CreateBuffers (dev); if (dev->Resize->type != RSZ_NONE) Resize_Start (dev, &transferred); /* 6729 */ RTS_ScanCounter_Inc (dev); } DBG (DBG_FNC, "- RTS_Scanner_StartScan: %i\n", rst); return rst; } static void Triplet_Gray (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * buffer, SANE_Int channels_count) { /* pPointer1 = FAB8 pPointer2 = FABC buffer = FAC0 channels_count = FAC4 */ SANE_Int value; SANE_Int channel_size; DBG (DBG_FNC, "> Triplet_Gray(*pPointer1, *pPointer2, *buffer, channels_count=%i)\n", channels_count); channel_size = (scan2.depth > 8) ? 2 : 1; channels_count = channels_count / 2; while (channels_count > 0) { value = data_lsb_get (pPointer1, channel_size); data_lsb_set (buffer, value, channel_size); value = data_lsb_get (pPointer2, channel_size); data_lsb_set (buffer + channel_size, value, channel_size); pPointer1 += 2 * channel_size; pPointer2 += 2 * channel_size; buffer += 2 * channel_size; channels_count--; } } static void Triplet_Lineart (SANE_Byte * pPointer1, SANE_Byte * pPointer2, SANE_Byte * buffer, SANE_Int channels_count) { /* Composing colour in lineart mode */ SANE_Int dots_count = 0; SANE_Int channel; SANE_Byte mask; SANE_Byte value; SANE_Int C; DBG (DBG_FNC, "> Triplet_Lineart(*pPointer1, *pPointer2, *buffer, channels_count=%i)\n", channels_count); if (channels_count > 0) { dots_count = (channels_count + 1) / 2; while (dots_count > 0) { mask = 0x80; channel = 2; do { value = 0; for (C = 4; C > 0; C--) { value = (value << 2) + (((*pPointer2 & mask) << 1) | (*pPointer1 & mask)); mask = mask >> 1; } *buffer = value; buffer++; channel--; } while (channel > 0); pPointer2 += 2; pPointer1 += 2; dots_count--; } } } static SANE_Int Arrange_NonColour (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred) { /* buffer : fadc buffer_size : fae0 */ SANE_Int lines_count = 0; /* ebp */ SANE_Int channels_count = 0; /* fadc pisa buffer */ SANE_Int rst = ERROR; struct st_scanning *scn; DBG (DBG_FNC, "+ Arrange_NonColour(*buffer, buffer_size=%i, *transferred):\n", buffer_size); /* this is just to make code more legible */ scn = dev->scanning; if (scn->imagebuffer == NULL) { if ((scn->arrange_hres == TRUE) || (scan2.colormode == CM_LINEART)) { scn->bfsize = (scn->arrange_sensor_evenodd_dist + 1) * line_size; scn->imagebuffer = (SANE_Byte *) malloc (scn->bfsize * sizeof (SANE_Byte)); if (scn->imagebuffer != NULL) { if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) == OK) { scn->channel_size = (scan2.depth == 8) ? 1 : 2; scn->desp1[CL_RED] = 0; scn->desp2[CL_RED] = scn->channel_size + (scn->arrange_sensor_evenodd_dist * line_size); scn->pColour2[CL_RED] = scn->imagebuffer + scn->desp2[CL_RED]; scn->pColour1[CL_RED] = scn->imagebuffer + scn->desp1[CL_RED]; rst = OK; } } } } else rst = OK; /* b0f4 */ if (rst == OK) { scn->imagepointer = scn->imagebuffer; lines_count = buffer_size / line_size; channels_count = line_size / scn->channel_size; while (lines_count > 0) { if (scan2.colormode == CM_LINEART) Triplet_Lineart (scn->pColour1[CL_RED], scn->pColour2[CL_RED], buffer, channels_count); else Triplet_Gray (scn->pColour1[CL_RED], scn->pColour2[CL_RED], buffer, channels_count); buffer += line_size; scn->arrange_size -= bytesperline; lines_count--; if (lines_count == 0) { if ((scn->arrange_size | v15bc) == 0) break; } rst = Read_Block (dev, line_size, scn->imagepointer, transferred); if (rst != OK) break; if (scn->arrange_hres == TRUE) { scn->desp2[CL_RED] = (line_size + scn->desp2[CL_RED]) % scn->bfsize; scn->desp1[CL_RED] = (line_size + scn->desp1[CL_RED]) % scn->bfsize; scn->pColour2[CL_RED] = scn->imagebuffer + scn->desp2[CL_RED]; scn->pColour1[CL_RED] = scn->imagebuffer + scn->desp1[CL_RED]; } /* b21d */ scn->imagepointer += line_size; if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) scn->imagepointer = scn->imagebuffer; } } /* 2246 */ DBG (DBG_FNC, "- Arrange_NonColour(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Resize_Decrease (SANE_Byte * to_buffer, SANE_Int to_resolution, SANE_Int to_width, SANE_Byte * from_buffer, SANE_Int from_resolution, SANE_Int from_width, SANE_Int myresize_mode) { /* to_buffer = FAC8 = 0x236200 to_resolution = FACC = 0x4b to_width = FAD0 = 0x352 from_buffer = FAD4 = 0x235460 from_resolution = FAD8 = 0x64 from_width = FADC = 0x46d myresize_mode = FAE0 = 1 */ SANE_Int rst = ERROR; SANE_Int channels = 0; /* fac8 */ SANE_Int depth = 0; /* fae0 */ SANE_Int color[3] = { 0, 0, 0 }; /* fab8 | fabc | fac0 */ SANE_Int to_pos = 0; /* fad4 */ SANE_Int rescont = 0; SANE_Int from_pos = 0; /* fab4 */ SANE_Int C; SANE_Int smres = 0; /* fab0 */ SANE_Int value; SANE_Int channel_size; to_resolution = to_resolution & 0xffff; from_resolution = from_resolution & 0xffff; DBG (DBG_FNC, "+ Resize_Decrease(*to_buffer, to_resolution=%i, to_width=%i, *from_buffer, from_resolution=%i, from_width=%i, myresize_mode=%i):\n", to_resolution, to_width, from_resolution, from_width, myresize_mode); if (myresize_mode != RSZ_LINEART) { switch (myresize_mode) { case RSZ_GRAYL: channels = 1; depth = 8; break; case RSZ_COLOURL: channels = 3; depth = 8; break; case RSZ_COLOURH: channels = 3; depth = 16; break; case RSZ_GRAYH: channels = 1; depth = 16; break; } channel_size = (depth > 8) ? 2 : 1; to_pos = 0; rescont = 0; while (to_pos < to_width) { from_pos++; if (from_pos > from_width) from_buffer -= (((depth + 7) / 8) * channels); rescont += to_resolution; if (rescont < from_resolution) { /* Adds 3 color channel values */ for (C = 0; C < channels; C++) { color[C] += data_lsb_get (from_buffer, channel_size) * to_resolution; from_buffer += channel_size; } } else { /* fc3c */ to_pos++; smres = to_resolution - (rescont - from_resolution); for (C = 0; C < channels; C++) { value = ((data_lsb_get (from_buffer, channel_size) * smres) + color[C]) / from_resolution; data_lsb_set (to_buffer, value, channel_size); color[C] = data_lsb_get (from_buffer, channel_size) * (rescont - from_resolution); to_buffer += channel_size; from_buffer += channel_size; } rescont -= from_resolution; } } rst = OK; } else { /* fd60 */ SANE_Int bit, pos, desp, rescont2; *to_buffer = 0; bit = 0; pos = 0; desp = 0; rescont = 0; rescont2 = 0; if (to_width > 0) { do { if (bit == 8) { /* fda6 */ bit = 0; to_buffer++; *to_buffer = 0; } rescont += to_resolution; if (rescont < from_resolution) { if ((*from_buffer & (0x80 >> desp)) != 0) rescont2 += to_resolution; } else { /*fdd5 */ pos++; rescont -= from_resolution; if ((*from_buffer & (0x80 >> desp)) != 0) /*fdee */ rescont2 += (to_resolution - rescont); if (rescont2 > (to_resolution / 2)) /* fe00 */ *to_buffer = _B0 (*to_buffer | (0x80 >> bit)); rescont2 = ((*from_buffer & (0x80 >> desp)) != 0) ? rescont : 0; bit++; } /* fe2f */ desp++; if (desp == 8) { desp = 0; from_buffer++; } } while (pos < to_width); } else rst = OK; } DBG (DBG_FNC, "- Resize_Decrease: %i\n", rst); return rst; } static SANE_Int Resize_Increase (SANE_Byte * to_buffer, SANE_Int to_resolution, SANE_Int to_width, SANE_Byte * from_buffer, SANE_Int from_resolution, SANE_Int from_width, SANE_Int myresize_mode) { /* to_buffer = FAC8 = 0x2353f0 to_resolution = FACC = 0x4b to_width = FAD0 = 0x352 from_buffer = FAD4 = 0x234650 from_resolution = FAD8 = 0x64 from_width = FADC = 0x46d myresize_mode = FAE0 = 1 */ SANE_Int rst = ERROR; SANE_Int desp; /* fac0 */ SANE_Byte *myp2; /* faac */ SANE_Int mywidth; /* fab4 fab8 */ SANE_Int mychannels; /* fabc */ SANE_Int channels = 0; /* faa4 */ SANE_Int depth = 0; /* faa8 */ SANE_Int pos = 0; /* fae0 */ SANE_Int rescount; SANE_Int val6 = 0; SANE_Int val7 = 0; SANE_Int value; /**/ DBG (DBG_FNC, "+ Resize_Increase(*to_buffer, to_resolution=%i, to_width=%i, *from_buffer, from_resolution=%i, from_width=%i, myresize_mode=%i):\n", to_resolution, to_width, from_resolution, from_width, myresize_mode); if (myresize_mode != RSZ_LINEART) { switch (myresize_mode) { case RSZ_GRAYL: channels = 1; depth = 8; break; case RSZ_COLOURL: channels = 3; depth = 8; break; case RSZ_COLOURH: channels = 3; depth = 16; break; case RSZ_GRAYH: channels = 1; depth = 16; break; } if (channels > 0) { SANE_Byte channel_size; SANE_Byte *p_dst; /* fac8 */ SANE_Byte *p_src; /* fad4 */ desp = to_buffer - from_buffer; myp2 = from_buffer; channel_size = (depth == 8) ? 1 : 2; for (mychannels = 0; mychannels < channels; mychannels++) { pos = 0; rescount = (from_resolution / 2) + to_resolution; p_src = myp2; p_dst = myp2 + desp; /* f938 */ val7 = data_lsb_get (p_src, channel_size); if (to_width > 0) { for (mywidth = 0; mywidth < to_width; mywidth++) { if (rescount >= to_resolution) { rescount -= to_resolution; val6 = val7; pos++; if (pos < from_width) { p_src += (channels * channel_size); val7 = data_lsb_get (p_src, channel_size); } } /*f9a5 */ data_lsb_set (p_dst, ((((to_resolution - rescount) * val6) + (val7 * rescount)) / to_resolution), channel_size); rescount += from_resolution; p_dst += (channels * channel_size); } } myp2 += channel_size; } rst = OK; } else rst = OK; } else { /* RSZ_LINEART mode */ /* fa02 */ /* to_buffer = FAC8 = 0x2353f0 to_resolution = FACC = 0x4b to_width = FAD0 = 0x352 from_buffer = FAD4 = 0x234650 from_resolution = FAD8 = 0x64 from_width = FADC = 0x46d myresize_mode = FAE0 = 1 */ SANE_Int myres2; /* fac8 */ SANE_Int sres; SANE_Int lfae0; SANE_Int lfad8; SANE_Int myres; SANE_Int cont = 1; SANE_Int someval; SANE_Int bit; /*lfaa8 */ myres2 = from_resolution; sres = (myres2 / 2) + to_resolution; value = _B0 (*from_buffer); bit = 0; lfae0 = 0; lfad8 = value >> 7; someval = lfad8; *to_buffer = 0; if (to_width > 0) { myres = to_resolution; to_resolution = myres / 2; do { if (sres >= myres) { sres -= myres; lfae0++; cont++; lfad8 = someval; if (lfae0 < from_width) { if (cont == 8) { cont = 0; from_buffer++; } bit = (((0x80 >> cont) & *from_buffer) != 0) ? 1 : 0; } } /*faa6 */ if ((((myres - sres) * lfad8) + (bit * sres)) > to_resolution) *to_buffer |= (0x80 >> bit); bit++; if (bit == 8) { bit = 0; to_buffer++; *to_buffer = 0; } to_width--; sres += myres2; } while (to_width > 0); rst = OK; } } DBG (DBG_FNC, "- Resize_Increase: %i\n", rst); return rst; } static SANE_Int Resize_Start (struct st_device *dev, SANE_Int * transferred) { SANE_Int rst = ERROR; struct st_resize *rz = dev->Resize; DBG (DBG_FNC, "+ Resize_Start(*transferred):\n"); if (Resize_CreateBuffers (dev, line_size, rz->bytesperline, rz->bytesperline) == ERROR) return ERROR; if (arrangeline2 == FIX_BY_SOFT) { /* fee0 */ if (scan2.colormode == CM_COLOR) rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); else rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred); } else rst = Read_Block (dev, line_size, rz->v3624, transferred); /* ff03 */ /* Redimensionado */ switch (rz->type) { case RSZ_DECREASE: /* ff1b */ Resize_Decrease (rz->v3628, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); break; case RSZ_INCREASE: /* ff69 */ rz->rescount = 0; Resize_Increase (rz->v3628, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); if (arrangeline2 == FIX_BY_SOFT) { /* ffb1 */ if (scan2.colormode == CM_COLOR) rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); else rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred); } else rst = Read_Block (dev, line_size, rz->v3624, transferred); /* ffe0 */ /* fff2 */ Resize_Increase (rz->v362c, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); break; } /* 002a */ DBG (DBG_FNC, "- Resize_Start(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Resize_CreateBuffers (struct st_device *dev, SANE_Int size1, SANE_Int size2, SANE_Int size3) { SANE_Int rst = ERROR; struct st_resize *rz = dev->Resize; rz->v3624 = (SANE_Byte *) malloc ((size1 + 0x40) * sizeof (SANE_Byte)); rz->v3628 = (SANE_Byte *) malloc ((size2 + 0x40) * sizeof (SANE_Byte)); rz->v362c = (SANE_Byte *) malloc ((size3 + 0x40) * sizeof (SANE_Byte)); if ((rz->v3624 == NULL) || (rz->v3628 == NULL) || (rz->v362c == NULL)) Resize_DestroyBuffers (dev); else rst = OK; DBG (DBG_FNC, "> Resize_CreateBuffers(size1=%i, size2=%i, size3=%i): %i\n", size1, size2, size3, rst); return rst; } static SANE_Int Resize_DestroyBuffers (struct st_device *dev) { struct st_resize *rz = dev->Resize; if (rz->v3624 != NULL) free (rz->v3624); if (rz->v3628 != NULL) free (rz->v3628); if (rz->v362c != NULL) free (rz->v362c); rz->v3624 = NULL; rz->v3628 = NULL; rz->v362c = NULL; return OK; } static SANE_Int Reading_DestroyBuffers (struct st_device *dev) { DBG (DBG_FNC, "> Reading_DestroyBuffers():\n"); if (dev->Reading->DMABuffer != NULL) free (dev->Reading->DMABuffer); if (dev->scanning->imagebuffer != NULL) { free (dev->scanning->imagebuffer); dev->scanning->imagebuffer = NULL; } bzero (dev->Reading, sizeof (struct st_readimage)); return OK; } static SANE_Int Gamma_SendTables (struct st_device *dev, SANE_Byte * Regs, SANE_Byte * gammatable, SANE_Int size) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Gamma_SendTables(*Regs, *gammatable, size=%i):\n", size); if ((gammatable != NULL) && (size > 0)) { SANE_Int transferred; SANE_Int first_table; SANE_Int cont = 0; SANE_Int retry = TRUE; SANE_Byte *mybuffer; /* lock */ SetLock (dev->usb_handle, Regs, TRUE); first_table = (data_lsb_get (&Regs[0x1b4], 2) & 0x3fff) >> 4; mybuffer = (SANE_Byte *) malloc (sizeof (SANE_Byte) * size); if (mybuffer != NULL) { /* Try to send buffer during 10 seconds */ long tick = GetTickCount () + 10000; while ((retry == TRUE) && (tick > GetTickCount ())) { retry = FALSE; /* Operation type 0x14 */ if (IWrite_Word (dev->usb_handle, 0x0000, 0x0014, 0x0800) == OK) { /* Send size to write */ if (RTS_DMA_Enable_Write (dev, 0x0000, size, first_table) == OK) { /* Send data */ if (Bulk_Operation (dev, BLK_WRITE, size, gammatable, &transferred) == OK) { /* Send size to read */ if (RTS_DMA_Enable_Read (dev, 0x0000, size, first_table) == OK) { /* Retrieve data */ if (Bulk_Operation (dev, BLK_READ, size, mybuffer, &transferred) == OK) { /* Check data */ while ((cont < size) && (retry == FALSE)) { if (mybuffer[cont] != gammatable[cont]) retry = TRUE; cont++; } if (retry == FALSE) rst = OK; } } } } } } free (mybuffer); } /* unlock */ SetLock (dev->usb_handle, Regs, FALSE); } DBG (DBG_FNC, "- Gamma_SendTables: %i\n", rst); return rst; } static SANE_Int Gamma_GetTables (struct st_device *dev, SANE_Byte * Gamma_buffer) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Gamma_GetTables(SANE_Byte *Gamma_buffer):\n"); if (Gamma_buffer == NULL) return ERROR; /* Operation type 0x14 */ if (IWrite_Word (dev->usb_handle, 0x0000, 0x0014, 0x0800) == 0x00) { SANE_Int size = 768; if (RTS_DMA_Enable_Read (dev, 0x0000, size, 0) == OK) { SANE_Int transferred = 0; usleep (1000 * 500); /* Read buffer */ rst = Bulk_Operation (dev, BLK_READ, size, Gamma_buffer, &transferred); } } DBG (DBG_FNC, "- Gamma_GetTables: %i\n", rst); return rst; } static void Gamma_FreeTables () { SANE_Int c; DBG (DBG_FNC, "> Gamma_FreeTables()\n"); for (c = 0; c < 3; c++) { if (hp_gamma->table[c] != NULL) { free (hp_gamma->table[c]); hp_gamma->table[c] = NULL; } } use_gamma_tables = FALSE; } static void RTS_Scanner_StopScan (struct st_device *dev, SANE_Int wait) { SANE_Byte data; DBG (DBG_FNC, "+ RTS_Scanner_StopScan():\n"); data = 0; Reading_DestroyBuffers (dev); Resize_DestroyBuffers (dev); RTS_DMA_Reset (dev); data_bitset (&dev->init_regs[0x60b], 0x10, 0); data_bitset (&dev->init_regs[0x60a], 0x40, 0); if (Write_Buffer (dev->usb_handle, 0xee0a, &dev->init_regs[0x60a], 2) == OK) Motor_Change (dev, dev->init_regs, 3); usleep (1000 * 200); if (wait == FALSE) { Read_Byte (dev->usb_handle, 0xe801, &data); if ((data & 0x02) == 0) { if (Head_IsAtHome (dev, dev->init_regs) == FALSE) { /* clear execution bit */ data_bitset (&dev->init_regs[0x00], 0x80, 0); Write_Byte (dev->usb_handle, 0x00, dev->init_regs[0x00]); Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); } } } else { /*66a1 */ /* clear execution bit */ data_bitset (&dev->init_regs[0x00], 0x80, 0); Write_Byte (dev->usb_handle, 0x00, dev->init_regs[0x00]); if (Head_IsAtHome (dev, dev->init_regs) == FALSE) Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); } /*66e0 */ RTS_Enable_CCD (dev, dev->init_regs, 0); Lamp_Status_Timer_Set (dev, 13); DBG (DBG_FNC, "- RTS_Scanner_StopScan()\n"); } static SANE_Int Reading_CreateBuffers (struct st_device *dev) { SANE_Byte data; SANE_Int mybytesperline; SANE_Int mybuffersize, a, b; DBG (DBG_FNC, "+ Reading_CreateBuffers():\n"); data = 0; /* Gets BinarythresholdH */ if (Read_Byte (dev->usb_handle, 0xe9a1, &data) == OK) binarythresholdh = data; mybytesperline = (scan2.depth == 12) ? (bytesperline * 3) / 4 : bytesperline; dev->Reading->Max_Size = 0xfc00; dev->Reading->DMAAmount = 0; a = (RTS_Debug->dmabuffersize / 63); b = (((RTS_Debug->dmabuffersize - a) / 2) + a) >> 0x0f; mybuffersize = ((b << 6) - b) << 10; if (mybuffersize < 0x1f800) mybuffersize = 0x1f800; dev->Reading->DMABufferSize = mybuffersize; /*3FFC00 4193280 */ do { dev->Reading->DMABuffer = (SANE_Byte *) malloc (dev->Reading->DMABufferSize * sizeof (SANE_Byte)); if (dev->Reading->DMABuffer != NULL) break; dev->Reading->DMABufferSize -= dev->Reading->Max_Size; } while (dev->Reading->DMABufferSize >= dev->Reading->Max_Size); /* 6003 */ dev->Reading->Starting = TRUE; dev->Reading->Size4Lines = (mybytesperline > dev->Reading->Max_Size) ? mybytesperline : (dev->Reading->Max_Size / mybytesperline) * mybytesperline; dev->Reading->ImageSize = imagesize; read_v15b4 = v15b4; DBG (DBG_FNC, "- Reading_CreateBuffers():\n"); return OK; } static SANE_Int RTS_ScanCounter_Inc (struct st_device *dev) { /* Keep a count of the number of scans done by this scanner */ SANE_Int idata; DBG (DBG_FNC, "+ RTS_ScanCounter_Inc():\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { SANE_Byte cdata = 0; SANE_Byte somebuffer[26]; switch (dev->chipset->model) { case RTS8822L_02A: case RTS8822BL_03A: /* value is 4 bytes size starting from address 0x21 in msb format */ if (RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata) == OK) { idata = data_swap_endianess (idata, 4) + 1; idata = data_swap_endianess (idata, 4); RTS_EEPROM_WriteInteger (dev->usb_handle, 0x21, idata); } break; default: /* value is 4 bytes size starting from address 0x21 in lsb format */ bzero (&somebuffer, sizeof (somebuffer)); somebuffer[4] = 0x0c; RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata); data_lsb_set (&somebuffer[0], idata + 1, 4); RTS_EEPROM_ReadByte (dev->usb_handle, 0x003a, &cdata); somebuffer[25] = cdata; RTS_EEPROM_WriteBuffer (dev->usb_handle, 0x21, somebuffer, 0x1a); break; } } DBG (DBG_FNC, "- RTS_ScanCounter_Inc()\n"); return OK; } static SANE_Int RTS_ScanCounter_Get (struct st_device *dev) { /* Returns the number of scans done by this scanner */ SANE_Int idata = 0; DBG (DBG_FNC, "+ RTS_ScanCounter_Get():\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { RTS_EEPROM_ReadInteger (dev->usb_handle, 0x21, &idata); switch (dev->chipset->model) { case RTS8822L_02A: case RTS8822BL_03A: /* value is 4 bytes size starting from address 0x21 in msb format */ idata = data_swap_endianess (idata, 4); break; default: /* RTS8822L_01H */ /* value is 4 bytes size starting from address 0x21 in lsb format */ idata &= 0xffffffff; break; } } DBG (DBG_FNC, "- RTS_ScanCounter_Get(): %i\n", idata); return idata; } static SANE_Int Read_Image (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transferred) { SANE_Int rst; SANE_Byte mycolormode; DBG (DBG_FNC, "+ Read_Image(buffer_size=%i, *buffer, *transferred):\n", buffer_size); *transferred = 0; mycolormode = scan2.colormode; rst = ERROR; if ((scan2.colormode != CM_COLOR) && (scan2.channel == 3)) mycolormode = 3; if (dev->Resize->type == RSZ_NONE) { if (arrangeline == FIX_BY_SOFT) { switch (mycolormode) { case CM_COLOR: rst = Arrange_Colour (dev, buffer, buffer_size, transferred); break; case 3: rst = Arrange_Compose (dev, buffer, buffer_size, transferred); break; default: rst = Arrange_NonColour (dev, buffer, buffer_size, transferred); break; } } else rst = Read_Block (dev, buffer_size, buffer, transferred); /*00fe */ } else rst = Read_ResizeBlock (dev, buffer, buffer_size, transferred); /*010d */ DBG (DBG_FNC, "- Read_Image(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Arrange_Compose (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred) { /* fnb250 0600FA7C 05E10048 buffer 0600FA80 0000F906 buffer_size */ SANE_Byte *mybuffer = buffer; /* fa7c */ SANE_Int mydistance; /*ebp */ SANE_Int mydots; /*fa74 */ SANE_Int channel_size; SANE_Int c; struct st_scanning *scn; /*mywidth = fa70 */ DBG (DBG_FNC, "+ Arrange_Compose(*buffer, buffer_size=%i, *transferred):\n", buffer_size); channel_size = (scan2.depth == 8) ? 1 : 2; /* this is just to make code more legible */ scn = dev->scanning; if (scn->imagebuffer == NULL) { if (dev->sensorcfg->type == CCD_SENSOR) mydistance = (dev->sensorcfg->line_distance * scan2.resolution_y) / dev->sensorcfg->resolution; else mydistance = 0; if (mydistance != 0) { scn->bfsize = (scn->arrange_hres == TRUE) ? scn->arrange_sensor_evenodd_dist : 0; scn->bfsize = line_size * (scn->bfsize + (mydistance * 2) + 1); } else scn->bfsize = line_size * 2; /*b2f0 */ scn->imagebuffer = (SANE_Byte *) malloc (scn->bfsize * sizeof (SANE_Byte)); if (scn->imagebuffer == NULL) return ERROR; scn->imagepointer = scn->imagebuffer; if (Read_Block (dev, scn->bfsize, scn->imagebuffer, transferred) == ERROR) return ERROR; /* Calculate channel displacements */ scn->arrange_orderchannel = FALSE; for (c = CL_RED; c <= CL_BLUE; c++) { if (mydistance == 0) { /*b34e */ if (scn->arrange_hres == FALSE) { if ((((dev->sensorcfg->line_distance * scan2.resolution_y) * 2) / dev->sensorcfg->resolution) == 1) scn->arrange_orderchannel = TRUE; if (scn->arrange_orderchannel == TRUE) scn->desp[c] = ((dev->sensorcfg->rgb_order[c] / 2) * line_size) + (channel_size * c); else scn->desp[c] = channel_size * c; } } else { /*b3e3 */ scn->desp[c] = (dev->sensorcfg->rgb_order[c] * (mydistance * line_size)) + (channel_size * c); if (scn->arrange_hres == TRUE) { /*b43b */ scn->desp1[c] = scn->desp[c]; scn->desp2[c] = ((channel_size * 3) + scn->desp1[c]) + (scn->arrange_sensor_evenodd_dist * line_size); }; } } for (c = CL_RED; c <= CL_BLUE; c++) { if (scn->arrange_hres == TRUE) { scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; } else scn->pColour[c] = scn->imagebuffer + scn->desp[c]; } } /*b545 */ buffer_size /= line_size; mydots = line_size / (channel_size * 3); while (buffer_size > 0) { if (scn->arrange_orderchannel == FALSE) { /*b5aa */ if (scn->arrange_hres == TRUE) Triplet_Compose_HRes (scn->pColour1[CL_RED], scn->pColour1[CL_GREEN], scn->pColour1[CL_BLUE], scn->pColour2[CL_RED], scn->pColour2[CL_GREEN], scn->pColour2[CL_BLUE], mybuffer, mydots); else Triplet_Compose_LRes (scn->pColour[CL_RED], scn->pColour[CL_GREEN], scn->pColour[CL_BLUE], mybuffer, mydots); } else Triplet_Compose_Order (dev, scn->pColour[CL_RED], scn->pColour[CL_GREEN], scn->pColour[CL_BLUE], mybuffer, mydots); /*b5f8 */ mybuffer += line_size; scn->arrange_size -= bytesperline; if (scn->arrange_size < 0) v15bc--; buffer_size--; if (buffer_size == 0) { if ((scn->arrange_size | v15bc) == 0) return OK; } /*b63f */ if (Read_Block (dev, line_size, scn->imagepointer, transferred) == ERROR) return ERROR; for (c = CL_RED; c <= CL_BLUE; c++) { if (scn->arrange_hres == TRUE) { /*b663 */ scn->desp2[c] = (scn->desp2[c] + line_size) % scn->bfsize; scn->desp1[c] = (scn->desp1[c] + line_size) % scn->bfsize; scn->pColour2[c] = scn->imagebuffer + scn->desp2[c]; scn->pColour1[c] = scn->imagebuffer + scn->desp1[c]; } else { /*b74a */ scn->desp[c] = (scn->desp[c] + line_size) % scn->bfsize; scn->pColour[c] = scn->imagebuffer + scn->desp[c]; } } /*b7be */ scn->imagepointer += line_size; if (scn->imagepointer >= (scn->imagebuffer + scn->bfsize)) scn->imagepointer = scn->imagebuffer; } return OK; } static void Triplet_Compose_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, SANE_Byte * pBlue1, SANE_Byte * pRed2, SANE_Byte * pGreen2, SANE_Byte * pBlue2, SANE_Byte * buffer, SANE_Int Width) { SANE_Int Value; SANE_Int Channel_size; SANE_Int max_value; DBG (DBG_FNC, "> Triplet_Compose_HRes(*pRed1, *pGreen1, *pBlue1, *pRed2 *pGreen2, *pBlue2, *buffer, Width=%i):\n", Width); Width /= 2; Channel_size = (scan2.depth > 8) ? 2 : 1; max_value = (1 << scan2.depth) - 1; while (Width > 0) { Value = data_lsb_get (pRed1, Channel_size) + data_lsb_get (pGreen1, Channel_size) + data_lsb_get (pBlue1, Channel_size); Value = min (Value, max_value); if (v1600 != NULL) { if (scan2.depth > 8) Value = *(v1600 + (Value >> 8)) | _B0 (Value); else Value = *(v1600 + Value); } data_lsb_set (buffer, Value, Channel_size); buffer += Channel_size; Value = data_lsb_get (pRed2, Channel_size) + data_lsb_get (pGreen2, Channel_size) + data_lsb_get (pBlue2, Channel_size); Value = min (Value, max_value); if (v1600 != NULL) { if (scan2.depth > 8) Value = *(v1600 + (Value >> 8)) | _B0 (Value); else Value = *(v1600 + Value); } data_lsb_set (buffer, Value, Channel_size); buffer += Channel_size; pRed1 += 6 * Channel_size; pGreen1 += 6 * Channel_size; pBlue1 += 6 * Channel_size; pRed2 += 6 * Channel_size; pGreen2 += 6 * Channel_size; pBlue2 += 6 * Channel_size; Width--; } } static void Triplet_Compose_Order (struct st_device *dev, SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int dots) { SANE_Int Value; DBG (DBG_FNC, "> Triplet_Compose_Order(*pRed, *pGreen, *pBlue, *buffer, dots=%i):\n", dots); if (scan2.depth > 8) { /* c0fe */ dots = dots / 2; while (dots > 0) { Value = min (data_lsb_get (pRed, 2) + data_lsb_get (pGreen, 2) + data_lsb_get (pBlue, 2), 0xffff); if (v1600 != NULL) Value = (*(v1600 + (Value >> 8)) << 8) | _B0 (Value); data_lsb_set (buffer, Value, 2); buffer += 2; pRed += 6; pGreen += 6; pBlue += 6; dots--; } } else { SANE_Byte *myp1, *myp2, *myp3; if (dev->sensorcfg->rgb_order[CL_RED] == 1) { myp1 = pRed; myp2 = pGreen; myp3 = pBlue; } else if (dev->sensorcfg->rgb_order[CL_GREEN] == 1) { myp1 = pGreen; myp2 = pRed; myp3 = pBlue; } else { myp1 = pBlue; myp2 = pRed; myp3 = pGreen; } while (dots > 0) { Value = min (((*myp1 + *(line_size + myp1)) / 2) + *myp2 + *myp3, 0xff); *buffer = (v1600 == NULL) ? _B0 (Value) : *(v1600 + Value); buffer++; myp1 += 3; myp2 += 3; myp3 += 3; dots--; } } } static void Triplet_Compose_LRes (SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int dots) { SANE_Int Value; SANE_Int Channel_size; SANE_Int max_value; DBG (DBG_FNC, "> Triplet_Compose_LRes(*pRed, *pGreen, *pBlue, *buffer, dots=%i):\n", dots); Channel_size = (scan2.depth > 8) ? 2 : 1; max_value = (1 << scan2.depth) - 1; /*bf59 */ while (dots > 0) { Value = data_lsb_get (pRed, Channel_size) + data_lsb_get (pGreen, Channel_size) + data_lsb_get (pBlue, Channel_size); Value = min (Value, max_value); if (v1600 != NULL) { if (scan2.depth > 8) Value = (*(v1600 + (Value >> 8)) << 8) | _B0 (Value); else Value = _B0 (*(v1600 + Value)); } data_lsb_set (buffer, Value, Channel_size); buffer += Channel_size; pRed += Channel_size * 3; pGreen += Channel_size * 3; pBlue += Channel_size * 3; dots--; } } static void Triplet_Colour_Order (struct st_device *dev, SANE_Byte * pRed, SANE_Byte * pGreen, SANE_Byte * pBlue, SANE_Byte * buffer, SANE_Int Width) { SANE_Int Value; DBG (DBG_FNC, "> Triplet_Colour_Order(*pRed, *pGreen, *pBlue, *buffer, Width=%i):\n", Width); if (scan2.depth > 8) { Width = Width / 2; while (Width > 0) { Value = data_lsb_get (pRed, 2); data_lsb_set (buffer, Value, 2); Value = data_lsb_get (pGreen, 2); data_lsb_set (buffer + 2, Value, 2); Value = data_lsb_get (pBlue, 2); data_lsb_set (buffer + 4, Value, 2); pRed += 6; pGreen += 6; pBlue += 6; buffer += 6; Width--; } } else { SANE_Int Colour; if (dev->sensorcfg->rgb_order[CL_RED] == 1) Colour = CL_RED; else if (dev->sensorcfg->rgb_order[CL_GREEN] == 1) Colour = CL_GREEN; else Colour = CL_BLUE; while (Width > 0) { switch (Colour) { case CL_RED: *buffer = (*pRed + *(pRed + line_size)) / 2; *(buffer + 1) = *pGreen; *(buffer + 2) = *pBlue; break; case CL_GREEN: *buffer = *pRed; *(buffer + 1) = ((*pGreen + *(pGreen + line_size)) / 2); *(buffer + 2) = *pBlue; break; case CL_BLUE: *buffer = *pRed; *(buffer + 1) = *pGreen; *(buffer + 2) = ((*pBlue + *(pBlue + line_size)) / 2); break; } pRed += 3; pGreen += 3; pBlue += 3; buffer += 3; Width--; } } } static void Triplet_Colour_HRes (SANE_Byte * pRed1, SANE_Byte * pGreen1, SANE_Byte * pBlue1, SANE_Byte * pRed2, SANE_Byte * pGreen2, SANE_Byte * pBlue2, SANE_Byte * buffer, SANE_Int Width) { SANE_Int Value; SANE_Int channel_size; SANE_Int c; SANE_Byte *pPointers[6]; pPointers[0] = pRed1; pPointers[1] = pGreen1; pPointers[2] = pBlue1; pPointers[3] = pRed2; pPointers[4] = pGreen2; pPointers[5] = pBlue2; DBG (DBG_FNC, "> Triplet_Colour_HRes(*pRed1, *pGreen1, *pBlue1, *pRed2, *pGreen2, *pBlue2, *buffer, Width=%i):\n", Width); channel_size = (scan2.depth > 8) ? 2 : 1; Width = Width / 2; while (Width > 0) { for (c = 0; c < 6; c++) { Value = data_lsb_get (pPointers[c], channel_size); data_lsb_set (buffer, Value, channel_size); pPointers[c] += (6 * channel_size); buffer += (channel_size); } Width--; } } static void Triplet_Colour_LRes (SANE_Int Width, SANE_Byte * Buffer, SANE_Byte * pChannel1, SANE_Byte * pChannel2, SANE_Byte * pChannel3) { /* 05F0FA4C 04EBAE4A /CALL to Assumed StdFunc6 from hpgt3970.04EBAE45 05F0FA50 00234FF8 |Arg1 = 00234FF8 pChannel3 05F0FA54 002359EF |Arg2 = 002359EF pChannel2 05F0FA58 002363E6 |Arg3 = 002363E6 pChannel1 05F0FA5C 05D10048 |Arg4 = 05D10048 Buffer 05F0FA60 00000352 |Arg5 = 00000352 Width */ /* Esta funcion une los tres canales de color en un triplete Inicialmente cada color está separado en 3 buffers apuntados por pChannel1 ,2 y 3 */ SANE_Int Value; SANE_Int channel_size; SANE_Int c; SANE_Byte *pChannels[3]; pChannels[0] = pChannel3; pChannels[1] = pChannel2; pChannels[2] = pChannel1; DBG (DBG_FNC, "> Triplet_Colour_LRes(Width=%i, *Buffer2, *p1, *p2, *p3):\n", Width); channel_size = (scan2.depth > 8) ? 2 : 1; while (Width > 0) { /* ba74 */ for (c = 0; c < 3; c++) { Value = data_lsb_get (pChannels[c], channel_size); data_lsb_set (Buffer, Value, channel_size); pChannels[c] += channel_size; Buffer += channel_size; } Width--; } } static SANE_Int Read_ResizeBlock (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Int * transferred) { /*The Beach buffer = FA7C 05E30048 buffer_size = FA80 0000F906 */ SANE_Int rst = ERROR; /* fa68 */ SANE_Int lfa54; SANE_Int lfa58; SANE_Byte *pP1; /* fa5c */ SANE_Byte *pP2; /* fa60 */ SANE_Int bOk; struct st_resize *rz = dev->Resize; /* fa74 = Resize->resolution_y */ /* fa70 = Resize->resolution_x */ /* fa64 = scan2.resolution_y */ /* fa6c = scan2.resolution_x */ DBG (DBG_FNC, "+ Read_ResizeBlock(*buffer, buffer_size=%i, *transferred):\n", buffer_size); if (rz->type == RSZ_DECREASE) { lfa58 = 0; do { bOk = 1; if (arrangeline2 == FIX_BY_SOFT) { if (scan2.colormode == CM_COLOR) rst = Arrange_Colour (dev, rz->v3624, line_size, transferred); else rst = Arrange_NonColour (dev, rz->v3624, line_size, transferred); } else rst = Read_Block (dev, line_size, rz->v3624, transferred); /*f2df */ Resize_Decrease (rz->v362c, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); rz->rescount += rz->resolution_y; if (rz->rescount > scan2.resolution_y) { /*f331 */ rz->rescount -= scan2.resolution_y; if (scan2.depth == 8) { /* f345 */ pP1 = rz->v3628; pP2 = rz->v362c; if (rz->mode == RSZ_LINEART) { /* f36b */ SANE_Int bit = 0; SANE_Byte *pP3 = rz->v362c; SANE_Int value; *buffer = 0; lfa54 = 0; while (lfa54 < rz->towidth) { if (bit == 8) { buffer++; *buffer = 0; pP1++; bit = 0; pP3++; } value = ((*pP1 & (0x80 >> bit)) != 0) ? rz->rescount : 0; if ((*pP3 & (0x80 >> bit)) != 0) value += (scan2.resolution_y - rz->rescount); if (value > rz->resolution_y) *buffer |= (0x80 >> bit); bit++; lfa54++; } } else { /* f414 */ lfa54 = 0; while (lfa54 < rz->bytesperline) { *buffer = _B0 ((((scan2.resolution_y - rz->rescount) * *pP2) + (*pP1 * rz->rescount)) / scan2.resolution_y); pP1++; pP2++; buffer++; lfa54++; } } } else { /* f47d */ lfa54 = 0; pP1 = rz->v3628; pP2 = rz->v362c; if ((rz->bytesperline & 0xfffffffe) > 0) { SANE_Int value; do { value = (((scan2.resolution_y - rz->rescount) * data_lsb_get (pP2, 2)) + (data_lsb_get (pP1, 2) * rz->rescount)) / scan2.resolution_y; data_lsb_set (buffer, value, 2); buffer += 2; pP1 += 2; pP2 += 2; lfa54++; } while (lfa54 < (rz->bytesperline / 2)); } } } else bOk = 0; /* f4fd f502 */ pP1 = rz->v3628; /* swap pointers */ rz->v3628 = rz->v362c; rz->v362c = pP1; } while (bOk == 0); } else { /*f530 */ SANE_Int lfa68; SANE_Int transferred; SANE_Int channel_size; rz->rescount += scan2.resolution_y; lfa58 = 0; if (rz->rescount > rz->resolution_y) { lfa68 = 1; rz->rescount -= rz->resolution_y; } else lfa68 = 0; pP1 = rz->v3628; pP2 = rz->v362c; if (rz->mode == RSZ_LINEART) { /*f592 */ *buffer = 0; if (rz->towidth > 0) { SANE_Int mask, mres; /* lfa60 = rz->resolution_y */ /* lfa7c = rz->resolution_y / 2 */ for (lfa54 = 0; lfa54 < rz->towidth; lfa54++) { mask = 0x80 >> lfa58; mres = ((mask & *pP1) != 0) ? rz->rescount : 0; if ((mask & *pP2) != 0) mres += (rz->resolution_y - rz->rescount); if (mres > (rz->resolution_y / 2)) *buffer = *buffer | mask; lfa58++; if (lfa58 == 8) { lfa58 = 0; buffer++; pP1++; pP2++; *buffer = 0; } } } } else { /*f633 */ channel_size = (scan2.depth > 8) ? 2 : 1; if (rz->rescount < scan2.resolution_y) { if (rz->bytesperline != 0) { SANE_Int value; for (lfa54 = 0; lfa54 < rz->bytesperline; lfa54++) { value = (((scan2.resolution_y - rz->rescount) * data_lsb_get (pP2, channel_size)) + (rz->rescount * data_lsb_get (pP1, channel_size))) / scan2.resolution_y; data_lsb_set (buffer, value, channel_size); pP1 += channel_size; pP2 += channel_size; buffer += channel_size; } } } else memcpy (buffer, rz->v3628, rz->bytesperline); /*f6a8 */ } /*f736 */ if (lfa68 != 0) { SANE_Byte *temp; if (arrangeline2 == FIX_BY_SOFT) { /*f74b */ if (scan2.colormode == CM_COLOR) rst = Arrange_Colour (dev, rz->v3624, line_size, &transferred); else rst = Arrange_NonColour (dev, rz->v3624, line_size, &transferred); } else rst = Read_Block (dev, line_size, rz->v3624, &transferred); /*f77a */ /*f78c */ /* swap buffers */ temp = rz->v3628; rz->v3628 = rz->v362c; rz->v362c = temp; Resize_Increase (temp, rz->resolution_x, rz->towidth, rz->v3624, scan2.resolution_x, rz->fromwidth, rz->mode); } else rst = OK; } DBG (DBG_FNC, "- Read_ResizeBlock(*transferred=%i): %i\n", *transferred, rst); return rst; } static void Split_into_12bit_channels (SANE_Byte * destino, SANE_Byte * fuente, SANE_Int size) { /* Each letter represents a bit abcdefgh 12345678 lmnopqrs << before splitting [efgh1234 0000abcd] [lmnopqrs 00005678] << after splitting, in memory [0000abcd efgh1234] [00005678 lmnopqrs] << resulting channels */ DBG (DBG_FNC, "> Split_into_12bit_channels(*destino, *fuente, size=%i\n", size); if ((destino != NULL) && (fuente != NULL)) { if ((size - (size & 0x03)) != 0) { SANE_Int C; C = (size - (size & 0x03) + 3) / 4; do { *destino = _B0 ((*(fuente + 1) >> 4) + (*fuente << 4)); *(destino + 1) = _B0 (*fuente >> 4); *(destino + 2) = _B0 (*(fuente + 2)); *(destino + 3) = *(fuente + 1) & 0x0f; destino += 4; fuente += 3; C--; } while (C > 0); } /**/ if ((size & 0x03) != 0) { *destino = _B0 ((*(fuente + 1) >> 4) + (*fuente << 4)); *(destino + 1) = _B0 (*fuente >> 4); } } } static SANE_Int Read_NonColor_Block (struct st_device *dev, SANE_Byte * buffer, SANE_Int buffer_size, SANE_Byte ColorMode, SANE_Int * transferred) { /* FA50 05DA0048 buffer FA54 0000F906 buffer_size FA58 00 ColorMode */ SANE_Int rst = OK; SANE_Int lfa38 = 0; SANE_Byte *gamma = v1600; SANE_Int block_bytes_per_line; SANE_Int mysize; SANE_Byte *mybuffer; DBG (DBG_FNC, "+ Read_NonColor_Block(*buffer, buffer_size=%i, ColorMode=%s):\n", buffer_size, dbg_colour (ColorMode)); if (ColorMode != CM_GRAY) { /* Lineart mode */ if ((lineart_width & 7) != 0) lfa38 = 8 - (lineart_width & 7); block_bytes_per_line = (lineart_width + 7) / 8; } else block_bytes_per_line = line_size; /*61b2 */ mysize = (buffer_size / block_bytes_per_line) * bytesperline; mybuffer = (SANE_Byte *) malloc (mysize * sizeof (SANE_Byte)); /*fa40 */ if (mybuffer != NULL) { SANE_Int LinesCount; SANE_Int mysize4lines; SANE_Byte *pBuffer = buffer; SANE_Byte *pImage = NULL; /* fa30 */ SANE_Int puntero; SANE_Int value; do { mysize4lines = (mysize <= dev->Reading->Size4Lines) ? mysize : dev->Reading->Size4Lines; LinesCount = mysize4lines / bytesperline; if (ColorMode == CM_GRAY) { if (scan2.depth == 12) { /* 633b */ /*GRAY Bit mode 12 */ rst = Scan_Read_BufferA (dev, (mysize4lines * 3) / 4, 0, mybuffer, transferred); if (rst == OK) { pImage = mybuffer; pBuffer += LinesCount * block_bytes_per_line; while (LinesCount > 0) { Split_into_12bit_channels (mybuffer, pImage, line_size); pImage += (bytesperline * 3) / 4; LinesCount--; } } else break; } else { /* grayscale 8 and 16 bits */ SANE_Int channel_size; rst = Scan_Read_BufferA (dev, mysize4lines, 0, mybuffer, transferred); if (rst == OK) { channel_size = (scan2.depth > 8) ? 2 : 1; pImage = mybuffer; /* No gamma tables */ while (LinesCount > 0) { if (line_size > 0) { puntero = 0; do { value = data_lsb_get (pImage + puntero, channel_size); if (gamma != NULL) value += *gamma << (8 * (channel_size - 1)); data_lsb_set (pBuffer, value, channel_size); pBuffer += channel_size; puntero += channel_size; } while (puntero < line_size); } pImage += bytesperline; LinesCount--; } } else break; } } else { /*6429 */ /* LINEART */ SANE_Int desp; rst = Scan_Read_BufferA (dev, mysize4lines, 0, mybuffer, transferred); if (rst == OK) { pImage = mybuffer; while (LinesCount > 0) { if (lineart_width > 0) { desp = 0; do { if ((desp % 7) == 0) *pBuffer = 0; /* making a byte bit per bit */ *pBuffer = *pBuffer << 1; /* bit 1 if data is under thresholdh value */ if (*(pImage + desp) >= binarythresholdh) /* binarythresholdh = 0x0c */ *pBuffer = *pBuffer | 1; desp++; if ((desp % 7) == 0) pBuffer++; } while (desp < lineart_width); } if (lfa38 != 0) { *pBuffer = (*pBuffer << lfa38); pBuffer++; } /* 64b0 */ pImage += bytesperline; LinesCount--; } } else break; } /* 64c0 */ mysize -= mysize4lines; } while ((mysize > 0) && (dev->status->cancel == FALSE)); free (mybuffer); } else rst = ERROR; DBG (DBG_FNC, "- Read_NonColor_Block(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Read_Block (struct st_device *dev, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transferred) { /* SANE_Int buffer_size fa80 SANE_Byte *buffer fa7c */ /* scan2: 04F0155C 01 08 00 02 03 00 58 02 ..X 04F01564 58 02 58 02 C5 00 00 00 XXÅ... 04F0156C B4 07 00 00 8B 01 00 00 ´..‹.. 04F01574 10 06 00 00 EC 13 00 00 ..ì.. 04F0157C B2 07 00 00 B4 07 00 00 ²..´.. 04F01584 CF 08 00 00 Ï.. arrangeline2 = 1 */ SANE_Int rst, LinesCount; SANE_Int mysize; SANE_Byte *readbuffer = NULL; SANE_Byte *pImage = NULL; DBG (DBG_FNC, "+ Read_Block(buffer_size=%i, *buffer):\n", buffer_size); rst = ERROR; *transferred = 0; if ((scan2.colormode != CM_COLOR) && (scan2.channel == 3) && (arrangeline2 != FIX_BY_SOFT)) { /*6510 */ return Read_NonColor_Block (dev, buffer, buffer_size, scan2.colormode, transferred); } /*6544 */ mysize = (buffer_size / line_size) * bytesperline; readbuffer = (SANE_Byte *) malloc (mysize * sizeof (SANE_Byte)); pImage = buffer; if (readbuffer != NULL) { do { buffer_size = (dev->Reading->Size4Lines < mysize) ? dev->Reading->Size4Lines : mysize; LinesCount = buffer_size / bytesperline; if (scan2.depth == 12) { rst = Scan_Read_BufferA (dev, buffer_size, 0, readbuffer, transferred); if (rst == OK) { if (LinesCount > 0) { SANE_Byte *destino, *fuente; destino = buffer; fuente = readbuffer; do { Split_into_12bit_channels (destino, fuente, line_size); destino += line_size; fuente += (bytesperline * 3) / 4; LinesCount--; } while (LinesCount > 0); } } else break; } else { /*65d9 */ rst = Scan_Read_BufferA (dev, buffer_size, 0, readbuffer, transferred); if (rst == OK) { memcpy (pImage, readbuffer, *transferred); /* apply white shading correction */ if ((RTS_Debug->wshading == TRUE) && (scan2.scantype == ST_NORMAL)) WShading_Emulate (pImage, &wshading->ptr, *transferred, scan2.depth); pImage += *transferred; } else break; } /*6629 */ mysize -= buffer_size; } while ((mysize > 0) && (dev->status->cancel == FALSE)); free (readbuffer); } DBG (DBG_FNC, "- Read_Block(*transferred=%i): %i\n", *transferred, rst); return rst; } static SANE_Int Scan_Read_BufferA (struct st_device *dev, SANE_Int buffer_size, SANE_Int arg2, SANE_Byte * pBuffer, SANE_Int * bytes_transfered) { SANE_Int rst = OK; SANE_Byte *ptBuffer = NULL; SANE_Byte *ptImg = NULL; struct st_readimage *rd = dev->Reading; DBG (DBG_FNC, "+ Scan_Read_BufferA(buffer_size=%i, arg2, *pBuffer, *bytes_transfered):\n", buffer_size); arg2 = arg2; /* silence gcc */ *bytes_transfered = 0; if (pBuffer != NULL) { ptBuffer = pBuffer; while ((buffer_size > 0) && (rst == OK) && (dev->status->cancel == FALSE)) { /* Check if we've already started */ if (rd->Starting == TRUE) { /* Get channels per dot and channel's size in bytes */ SANE_Byte data; rd->Channels_per_dot = 1; if (Read_Byte (dev->usb_handle, 0xe812, &data) == OK) { data = data >> 6; if (data != 0) rd->Channels_per_dot = data; } rd->Channel_size = 1; if (Read_Byte (dev->usb_handle, 0xee0b, &data) == OK) if (((data & 0x40) != 0) && ((data & 0x08) == 0)) rd->Channel_size = 2; rd->RDStart = rd->DMABuffer; rd->RDSize = 0; rd->DMAAmount = 0; rd->Starting = FALSE; } /* Is there any data to read from scanner? */ if ((rd->ImageSize > 0) && (rd->RDSize == 0)) { /* Try to read from scanner all possible data to fill DMABuffer */ if (rd->RDSize < rd->DMABufferSize) { SANE_Int iAmount, dofree; /* Check if we have already notify buffer size */ if (rd->DMAAmount <= 0) { /* Initially I suppose that I can read all image */ iAmount = min (rd->ImageSize, rd->Max_Size); rd->DMAAmount = ((RTS_Debug->dmasetlength * 2) / iAmount) * iAmount; rd->DMAAmount = min (rd->DMAAmount, rd->ImageSize); Reading_BufferSize_Notify (dev, 0, rd->DMAAmount); iAmount = min (iAmount, rd->DMABufferSize - rd->RDSize); } else { iAmount = min (rd->DMAAmount, rd->ImageSize); iAmount = min (iAmount, rd->Max_Size); } /* Allocate buffer to read image if it's necessary */ if ((rd->RDSize == 0) && (iAmount <= buffer_size)) { ptImg = ptBuffer; dofree = FALSE; } else { ptImg = (SANE_Byte *) malloc (iAmount * sizeof (SANE_Byte)); dofree = TRUE; } if (ptImg != NULL) { /* We must wait for scanner to get data */ SANE_Int opStatus, sc; sc = (iAmount < rd->Max_Size) ? TRUE : FALSE; opStatus = Reading_Wait (dev, rd->Channels_per_dot, rd->Channel_size, iAmount, &rd->Bytes_Available, 10, sc); /* If something fails, perhaps we can read some bytes... */ if (opStatus != OK) { if (rd->Bytes_Available > 0) iAmount = rd->Bytes_Available; else rst = ERROR; } if (rst == OK) { /* Try to read from scanner */ SANE_Int transferred = 0; opStatus = Bulk_Operation (dev, BLK_READ, iAmount, ptImg, &transferred); DBG (DBG_FNC, "> Scan_Read_BufferA: Bulk read %i bytes\n", transferred); /*if something fails may be we can read some bytes */ iAmount = (SANE_Int) transferred; if (iAmount != 0) { /* Lets copy data into DMABuffer if it's necessary */ if (ptImg != ptBuffer) { SANE_Byte *ptDMABuffer; ptDMABuffer = rd->RDStart + rd->RDSize; if ((ptDMABuffer - rd->DMABuffer) >= rd->DMABufferSize) ptDMABuffer -= rd->DMABufferSize; if ((ptDMABuffer + iAmount) >= (rd->DMABuffer + rd->DMABufferSize)) { SANE_Int rest = iAmount - (rd->DMABufferSize - (ptDMABuffer - rd->DMABuffer)); memcpy (ptDMABuffer, ptImg, iAmount - rest); memcpy (rd->DMABuffer, ptImg + (iAmount - rest), rest); } else memcpy (ptDMABuffer, ptImg, iAmount); rd->RDSize += iAmount; } else { *bytes_transfered += iAmount; buffer_size -= iAmount; } rd->DMAAmount -= iAmount; rd->ImageSize -= iAmount; } else rst = ERROR; } /* Lets free buffer */ if (dofree == TRUE) { free (ptImg); ptImg = NULL; } } else rst = ERROR; } } /* is there any data read from scanner? */ if (rd->RDSize > 0) { /* Add to the given buffer so many bytes as posible */ SANE_Int iAmount; iAmount = min (buffer_size, rd->RDSize); if ((rd->RDStart + iAmount) >= (rd->DMABuffer + rd->DMABufferSize)) { SANE_Int rest = rd->DMABufferSize - (rd->RDStart - rd->DMABuffer); memcpy (ptBuffer, rd->RDStart, rest); memcpy (ptBuffer + rest, rd->DMABuffer, iAmount - rest); rd->RDStart = rd->DMABuffer + (iAmount - rest); } else { memcpy (ptBuffer, rd->RDStart, iAmount); rd->RDStart += iAmount; } ptBuffer += iAmount; rd->RDSize -= iAmount; buffer_size -= iAmount; *bytes_transfered += iAmount; /* if there isn't any data in DMABuffer we can point RDStart to the begining of DMABuffer */ if (rd->RDSize == 0) rd->RDStart = rd->DMABuffer; } /* in case of all data is read we return OK with bytes_transfered = 0 */ if ((*bytes_transfered == 0) || ((rd->RDSize == 0) && (rd->ImageSize == 0))) break; } if (rst == ERROR) RTS_DMA_Cancel (dev); } DBG (DBG_FNC, "-> *bytes_transfered=%i\n", *bytes_transfered); DBG (DBG_FNC, "-> Reading->ImageSize=%i\n", rd->ImageSize); DBG (DBG_FNC, "-> Reading->DMAAmount=%i\n", rd->DMAAmount); DBG (DBG_FNC, "-> Reading->RDSize =%i\n", rd->RDSize); DBG (DBG_FNC, "- Scan_Read_BufferA: %i\n", rst); return rst; } static SANE_Int Reading_BufferSize_Get (struct st_device *dev, SANE_Byte channels_per_dot, SANE_Int channel_size) { /* returns the ammount of bytes in scanner's buffer ready to be read */ SANE_Int rst; DBG (DBG_FNC, "+ Reading_BufferSize_Get(channels_per_dot=%i, channel_size=%i):\n", channels_per_dot, channel_size); rst = 0; if (channel_size > 0) { SANE_Int myAmount; if (channels_per_dot < 1) { /* read channels per dot from registers */ if (Read_Byte (dev->usb_handle, 0xe812, &channels_per_dot) == OK) channels_per_dot = _B0 (channels_per_dot >> 6); if (channels_per_dot == 0) channels_per_dot++; } if (Read_Integer (dev->usb_handle, 0xef16, &myAmount) == OK) rst = ((channels_per_dot * 32) / channel_size) * myAmount; } DBG (DBG_FNC, "- Reading_BufferSize_Get: %i bytes\n", rst); return rst; } static SANE_Int Lamp_Warmup (struct st_device *dev, SANE_Byte * Regs, SANE_Int lamp, SANE_Int resolution) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Lamp_Warmup(*Regs, lamp=%i, resolution=%i)\n", lamp, resolution); if (Regs != NULL) { SANE_Byte flb_lamp, tma_lamp; SANE_Int overdrivetime; Lamp_Status_Get (dev, &flb_lamp, &tma_lamp); /* ensure that selected lamp is switched on */ if (lamp == FLB_LAMP) { overdrivetime = RTS_Debug->overdrive_flb; if (flb_lamp == 0) { /* FLB-Lamp is turned off, lets turn on */ Lamp_Status_Set (dev, Regs, TRUE, FLB_LAMP); waitforpwm = TRUE; } } else { /* is tma device attached to scanner ? */ if (RTS_isTmaAttached (dev) == TRUE) { overdrivetime = RTS_Debug->overdrive_ta; if (tma_lamp == 0) { /* tma lamp is turned off */ Lamp_Status_Set (dev, Regs, FALSE, TMA_LAMP); waitforpwm = TRUE; } } else rst = ERROR; } /* perform warmup process */ if (rst == OK) { Lamp_PWM_Setup (dev, lamp); if (waitforpwm == TRUE) { /*Lamp_PWM_DutyCycle_Set(dev, (lamp == TMA_LAMP)? 0x0e : 0x00); */ if (RTS_Debug->warmup == TRUE) { long ticks = GetTickCount () + overdrivetime; DBG (DBG_VRB, "- Lamp Warmup process. Please wait...\n"); dev->status->warmup = TRUE; while (GetTickCount () <= ticks) usleep (1000 * 200); Lamp_PWM_CheckStable (dev, resolution, lamp); } else DBG (DBG_VRB, "- Lamp Warmup process disabled.\n"); } /*Lamp_PWM_Setup(dev, lamp); if (waitforpwm == TRUE) { if (RTS_Debug->warmup == TRUE) Lamp_PWM_CheckStable(dev, resolution, lamp); waitforpwm = FALSE; } */ } } else rst = ERROR; dev->status->warmup = FALSE; DBG (DBG_FNC, "- Lamp_Warmup: %i\n", rst); return rst; } static SANE_Int Scan_Start (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ Scan_Start:\n"); rst = ERROR; if (RTS_Enable_CCD (dev, dev->init_regs, 0x0f) == OK) { SANE_Byte Regs[RT_BUFFER_LEN], mlock; SANE_Int ypos, xpos, runb1; struct st_scanparams scancfg; struct st_hwdconfig hwdcfg; struct st_calibration myCalib; long tick; memcpy (&Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (&scancfg, &scan, sizeof (struct st_scanparams)); dbg_ScanParams (&scancfg); /* reserva buffer 6 dwords en fa84-fa9f */ bzero (&hwdcfg, sizeof (struct st_hwdconfig)); /* wait till lamp is at home (should use timeout windows driver doesn't use it) */ tick = GetTickCount () + 10000; while ((Head_IsAtHome (dev, Regs) == FALSE) && (tick > GetTickCount ())); if (v14b4 != 0) { SANE_Int lfaa0 = 0; if (GainOffset_Counter_Inc (dev, &lfaa0) != OK) return 0x02; } tick = GetTickCount (); /* set margin references */ Refs_Set (dev, Regs, &scancfg); /* locate head to right position */ Load_StripCoords (scantype, &ypos, &xpos); if (ypos != 0) Head_Relocate (dev, dev->motorcfg->parkhomemotormove, MTR_FORWARD, ypos); /* perform lamp warmup */ if (Lamp_Warmup (dev, Regs, (scancfg.scantype == ST_NORMAL) ? FLB_LAMP : TMA_LAMP, scan.resolution_x) == ERROR) return ERROR; /* Calibration process */ /*592c */ if (Calib_CreateBuffers (dev, &myCalib, v14b4) != OK) return ERROR; /*5947 */ /* if (Calib_BlackShading_jkd(dev, Regs, &myCalib, &scancfg) == OK) Head_ParkHome(dev, TRUE, dev->motorcfg->parkhomemotormove); */ /* if (Calib_test(dev, Regs, &myCalib, &scancfg) == OK ) Head_ParkHome(dev, TRUE, dev->motorcfg->parkhomemotormove); */ /* Calibrate White shading correction */ if ((RTS_Debug->wshading == TRUE) && (scan.scantype == ST_NORMAL)) if (WShading_Calibrate (dev, Regs, &myCalib, &scancfg) == OK) Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); hwdcfg.calibrate = RTS_Debug->calibrate; if (RTS_Debug->calibrate != 0) { /* Let's calibrate */ if ((scancfg.colormode != CM_COLOR) && (scancfg.channel == 3)) scancfg.colormode = CM_COLOR; hwdcfg.arrangeline = 0; if (scan.scantype == ST_NORMAL) { /* Calibration for reflective type */ /*59e3 */ memcpy (&Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Calibration (dev, Regs, &scancfg, &myCalib, 0) != OK) { if (v14b4 == 0) Calib_FreeBuffers (&myCalib); return ERROR; } } else { /*59ed */ /* Calibration for negative/slide type */ } /*5af1 */ if (RTS_Debug->ScanWhiteBoard != FALSE) { Head_ParkHome (dev, TRUE, dev->motorcfg->basespeedmotormove); scan.ler = 1; } scancfg.colormode = scan.colormode; } else { /*5b1e */ /*Don't calibrate */ if (scan.scantype == ST_NORMAL) { Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); } else { if ((scan.scantype == ST_TA) || (scan.scantype == ST_NEG)) { /*SANE_Int ta_y_start; */ Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP); /*ta_y_start = get_value(SCAN_PARAM, TA_Y_START, 0x2508, usbfile); ta_y_start += (((((scan.coord.top * 3) * 5) * 5) * 32) / scancfg.resolution_x); if (ta_y_start >= 500) { Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, ta_y_start); scancfg.coord.top = 1; scan.ler = 1; } else { / *5ba9* / if (ta_y_start > 0) { Head_Relocate(dev, dev->motorcfg->basespeedmotormove, MTR_FORWARD, ta_y_start); scancfg.coord.top = 1; scan.ler = 1; } } */ } } } /*5bd0 */ usleep (1000 * 200); hwdcfg.scantype = scan.scantype; hwdcfg.motor_direction = MTR_FORWARD; /* Set Origin */ if ((scan.scantype >= ST_NORMAL) || (scan.scantype <= ST_NEG)) { scancfg.coord.left += scan.ser; scancfg.coord.top += scan.ler; } hwdcfg.sensorevenodddistance = dev->sensorcfg->evenodd_distance; hwdcfg.highresolution = (scancfg.resolution_x <= 1200) ? FALSE : TRUE; /*5c55 */ /* if (RTS_Debug->calibrate == FALSE) { SANE_Int mytop = (((scancfg.coord.top * 5) * 5) * 16) / scancfg.resolution_y; if ((scancfg.resolution_y <= 150)&&(mytop < 300)) { scancfg.coord.top = scancfg.resolution_y / 4; } else { if (mytop < 100) scancfg.coord.top = scancfg.resolution_y / 12; } } */ /*5cd9 */ if (compression != FALSE) hwdcfg.compression = TRUE; /* setting arrangeline option */ hwdcfg.arrangeline = arrangeline; if (scancfg.resolution_x == 2400) { /* 5cfa */ if (scancfg.colormode != CM_COLOR) { if ((scancfg.colormode == CM_GRAY) && (scancfg.channel == 3)) hwdcfg.arrangeline = FIX_BY_SOFT; } else hwdcfg.arrangeline = FIX_BY_SOFT; } /*5d12 */ if (dev->sensorcfg->type == CCD_SENSOR) { /*5d3a */ scancfg.coord.left += 24; switch (scancfg.resolution_x) { case 1200: scancfg.coord.left -= 63; break; case 2400: scancfg.coord.left -= 127; break; } } else { /*5d5a */ /* CIS sensor */ /*5d6d */ scancfg.coord.left += 50; switch (scancfg.resolution_x) { case 1200: scancfg.coord.left -= 63; break; case 2400: scancfg.coord.left -= 127; break; } } /* 5d92 */ DBG (DBG_FNC, " ->Scan_Start xStart=%i, xExtent=%i\n", scancfg.coord.left, scancfg.coord.width); runb1 = 1; if (scan.scantype == ST_NORMAL) { /*5db7 */ if ((scancfg.resolution_x == 1200) || (scancfg.resolution_x == 2400)) { /*5e41 */ if ((scancfg.resolution_y / 10) > scancfg.coord.top) runb1 = 0; } else { if ((scancfg.resolution_x == 600) && (RTS_Debug->usbtype == USB11) && (scancfg.colormode == CM_COLOR)) { /*5ded */ if ((scancfg.resolution_y / 10) > scancfg.coord.top) runb1 = 0; } else { if ((scancfg.resolution_x == 600) || (scancfg.resolution_x == 300)) { /*5e11 */ if (scancfg.resolution_y > scancfg.coord.top) runb1 = 0; } else runb1 = 0; } } } else { /*5e7c *//* entra aquí */ if ((scancfg.resolution_y / 10) > scancfg.coord.top) runb1 = 0; } /*5eb1 */ if (runb1 == 1) /*entra */ { SANE_Int val1 = scancfg.coord.top - (scancfg.resolution_y / 10); scancfg.coord.top -= val1; Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, (dev->motorcfg->resolution / scancfg.resolution_y) * val1); /*x168 */ } /*5efe */ if (RTS_Debug->calibrate != FALSE) { if (use_gamma_tables != FALSE) { hwdcfg.use_gamma_tables = TRUE; hp_gamma->depth = 0; } /*5f24 */ hwdcfg.white_shading = TRUE; hwdcfg.black_shading = TRUE; hwdcfg.unk3 = 0; RTS_Setup (dev, Regs, &scancfg, &hwdcfg, &calibdata->gain_offset); myCalib.shading_type = 0; myCalib.shadinglength = min (myCalib.shadinglength, scan.shadinglength); if (scancfg.colormode != CM_COLOR) { if ((scancfg.channel > 0) && (scancfg.channel < 3)) myCalib.WRef[0] = myCalib.WRef[scancfg.channel]; } RTS_WriteRegs (dev->usb_handle, Regs); /* apply gamma if required */ Gamma_Apply (dev, Regs, &scancfg, &hwdcfg, hp_gamma); Shading_apply (dev, Regs, &scancfg, &myCalib); /* Save to file? */ if (RTS_Debug->DumpShadingData != FALSE) dump_shading (&myCalib); /*5ff9 */ } else RTS_Setup (dev, Regs, &scancfg, &hwdcfg, default_gain_offset); /*602a */ RTS_Debug->calibrate = hwdcfg.calibrate; binarythresholdh = bw_threshold; binarythresholdl = bw_threshold; DBG (DBG_FNC, "> bw threshold -- hi=%i, lo=%i\n", binarythresholdh, binarythresholdl); /* set threshold high */ data_lsb_set (&Regs[0x1a0], binarythresholdh, 2); /* set threshold low */ data_lsb_set (&Regs[0x19e], binarythresholdl, 2); /* if has motorcurves... */ if ((Regs[0xdf] & 0x10) != 0) data_bitset (&Regs[0x01], 0x02, 1); /* Set MLOCK */ mlock = get_value (SCAN_PARAM, MLOCK, 0, usbfile) & 1; data_bitset (&Regs[0x00], 0x10, mlock); /*---x----*/ if (dev->motorcfg->changemotorcurrent != FALSE) Motor_Change (dev, Regs, Motor_GetFromResolution (scancfg.resolution_x)); /* set gain control mode */ Lamp_SetGainMode (dev, Regs, scancfg.resolution_x, Lamp_GetGainMode (dev, scancfg.resolution_x, scan.scantype)); RTS_WaitScanEnd (dev, 15000); if (v14b4 == 0) Calib_FreeBuffers (&myCalib); /* release motor */ Motor_Release (dev); #ifdef developing /* prueba(Regs); dbg_registers(Regs);*/ /*WShading_Calibrate(dev, Regs, &myCalib, &scancfg); */ /*shadingtest1(dev, Regs, &myCalib); */ #endif if (RTS_Warm_Reset (dev) == OK) { RTS_WriteRegs (dev->usb_handle, Regs); usleep (1000 * 500); if (RTS_Execute (dev) == OK) { Lamp_Status_Timer_Set (dev, 0); /* Let scanner some time to store some data */ if ((dev->chipset->model == RTS8822L_02A) && (scancfg.resolution_x > 2400)) usleep (1000 * 5000); rst = OK; } } } DBG (DBG_FNC, "- Scan_Start: %i\n", rst); return rst; } static SANE_Int RTS_Setup_Motor (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int somevalue) { SANE_Int rst = ERROR; /* default */ DBG (DBG_FNC, "+ RTS_Setup_Motor(*Regs, *scancfg, somevalue=%i):\n", somevalue); dbg_ScanParams (scancfg); if ((Regs != NULL) && (scancfg != NULL)) { SANE_Int colormode, mymode; colormode = ((scancfg->colormode != CM_COLOR) && (scancfg->channel == 3)) ? 3 : scancfg->colormode; mymode = RTS_GetScanmode (dev, scantype, colormode, scancfg->resolution_x); if (mymode != -1) { SANE_Int mbs[2] = { 0 }; /* motor back steps */ SANE_Int step_size, step_type, dummyline, myvalue, lf02c; struct st_scanmode *sm; sm = dev->scanmodes[mymode]; /* set motor step type */ data_bitset (&Regs[0xd9], 0x70, sm->scanmotorsteptype); /*-xxx----*/ /* set motor direction (polarity) */ data_bitset (&Regs[0xd9], 0x80, somevalue >> 3); /*e------- */ /* next value doesn't seem to have any effect */ data_bitset (&Regs[0xd9], 0x0f, somevalue); /*----efgh*/ /* 0 enable/1 disable motor */ data_bitset (&Regs[0xdd], 0x80, somevalue >> 4); /*d------- */ /* next value doesn't seem to have any effect */ data_bitset (&Regs[0xdd], 0x40, somevalue >> 4); /*-d------*/ switch (sm->scanmotorsteptype) { case STT_OCT: step_type = 8; break; case STT_QUART: step_type = 4; break; case STT_HALF: step_type = 2; break; default: step_type = 1; break; /* STT_FULL */ } /* set dummy lines */ dummyline = sm->dummyline; if (dummyline == 0) dummyline++; data_bitset (&Regs[0xd6], 0xf0, dummyline); /*xxxx---- */ /* Set if motor has curves */ data_bitset (&Regs[0xdf], 0x10, ((sm->motorcurve != -1) ? 1 : 0)); /*---x----*/ /* set last step of deccurve.scanbufferfull table to 16 */ data_lsb_set (&Regs[0xea], 0x10, 3); /* set last step of deccurve.normalscan table to 16 */ data_lsb_set (&Regs[0xed], 0x10, 3); /* set last step of deccurve.smearing table to 16 */ data_lsb_set (&Regs[0xf0], 0x10, 3); /* set last step of deccurve.parkhome table to 16 */ data_lsb_set (&Regs[0xf3], 0x10, 3); /* set step size */ step_size = _B0 ((dev->motorcfg->resolution * step_type) / (dummyline * scancfg->resolution_y)); data_lsb_set (&Regs[0xe0], step_size - 1, 1); /* set line exposure time */ myvalue = data_lsb_get (&Regs[0x30], 3); myvalue += ((myvalue + 1) % step_size); data_lsb_set (&Regs[0x30], myvalue, 3); /* set last step of accurve.normalscan table */ myvalue = ((myvalue + 1) / step_size) - 1; data_lsb_set (&Regs[0xe1], myvalue, 3); /* 42b30eb */ lf02c = 0; if (sm->motorcurve != -1) { if (sm->motorcurve < dev->mtrsetting_count) { struct st_motorcurve *ms = dev->mtrsetting[sm->motorcurve]; ms->motorbackstep = sm->motorbackstep; } DBG (DBG_FNC, " -> Setting up step motor using motorcurve %i\n", sm->motorcurve); lf02c = Motor_Setup_Steps (dev, Regs, sm->motorcurve); /* set motor back steps */ mbs[1] = sm->motorbackstep; if (mbs[1] >= (smeardeccurvecount + smearacccurvecount)) mbs[0] = mbs[1] - (smeardeccurvecount + smearacccurvecount) + 2; else mbs[0] = 0; if (mbs[1] >= (deccurvecount + acccurvecount)) mbs[1] -= (deccurvecount + acccurvecount) + 2; else mbs[1] = 0; } else { /* this scanner hasn't got any motorcurve */ /* set last step of accurve.smearing table (same as accurve.normalscan) */ data_lsb_set (&Regs[0xe4], myvalue, 3); /* set last step of accurve.parkhome table (same as accurve.normalscan) */ data_lsb_set (&Regs[0xe7], myvalue, 3); /* both motorbacksteps are equal */ mbs[0] = sm->motorbackstep; mbs[1] = sm->motorbackstep; } /* show msi and motorbacksteps */ DBG (DBG_FNC, " -> msi = %i\n", sm->msi); DBG (DBG_FNC, " -> motorbackstep1 = %i\n", mbs[0]); DBG (DBG_FNC, " -> motorbackstep2 = %i\n", mbs[1]); /* set msi */ data_bitset (&Regs[0xda], 0xff, _B0 (sm->msi)); /*xxxxxxxx */ data_bitset (&Regs[0xdd], 0x03, _B1 (sm->msi)); /*------xx*/ /* set motorbackstep (a) */ data_bitset (&Regs[0xdb], 0xff, _B0 (mbs[0])); /*xxxxxxxx */ data_bitset (&Regs[0xdd], 0x0c, _B1 (mbs[0])); /*----xx--*/ /* set motorbackstep (b) */ data_bitset (&Regs[0xdc], 0xff, _B0 (mbs[1])); /*xxxxxxxx */ data_bitset (&Regs[0xdd], 0x30, _B1 (mbs[1])); /*--xx----*/ /* 328b */ /* get dummy lines count */ dummyline = data_bitget (&Regs[0xd6], 0xf0); myvalue = scancfg->coord.top * (dummyline * step_size); if (lf02c >= myvalue) scancfg->coord.top = 1; else scancfg->coord.top -= (lf02c / (dummyline * step_size)) - 1; rst = lf02c; /* Result from Motor_Setup_Steps */ } } DBG (DBG_FNC, "- RTS_Setup_Motor: %i\n", rst); return rst; } static void RTS_Setup_Exposure_Times (SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_scanmode *sm) { DBG (DBG_FNC, "> RTS_Setup_Exposure_Times\n"); if ((sm != NULL) && (Regs != NULL) && (scancfg != NULL)) { SANE_Int myexpt[3], linexpt, a; /* calculate line exposure time */ linexpt = sm->ctpc + 1; if (RTS_Debug->usbtype == USB11) linexpt *= sm->multiexposureforfullspeed; if (scancfg->depth > 8) linexpt *= sm->multiexposurefor16bitmode; linexpt--; /* generate exposure times for each channel color */ for (a = CL_RED; a <= CL_BLUE; a++) { if ((linexpt > sm->mexpt[a]) && (sm->expt[a] == 0)) sm->expt[a] = sm->mexpt[a]; myexpt[a] = (sm->expt[a] == 0) ? sm->mexpt[a] : sm->expt[a]; } /* save exposure times */ DBG (DBG_FNC, "-> Exposure times : %04x, %04x, %04x\n", sm->expt[0], sm->expt[1], sm->expt[2]); data_lsb_set (&Regs[0x36], sm->expt[CL_RED], 3); data_lsb_set (&Regs[0x3c], sm->expt[CL_GREEN], 3); data_lsb_set (&Regs[0x42], sm->expt[CL_BLUE], 3); /* save maximum exposure times */ DBG (DBG_FNC, "-> Maximum exposure times: %04x, %04x, %04x\n", sm->mexpt[0], sm->mexpt[1], sm->mexpt[2]); data_lsb_set (&Regs[0x33], sm->mexpt[CL_RED], 3); data_lsb_set (&Regs[0x39], sm->mexpt[CL_GREEN], 3); data_lsb_set (&Regs[0x3f], sm->mexpt[CL_BLUE], 3); /* save line exposure time */ data_lsb_set (&Regs[0x30], linexpt, 3); /* scancfg->expt = lowest value */ scancfg->expt = min (min (myexpt[1], myexpt[2]), myexpt[0]); } } static SANE_Int RTS_Setup_Line_Distances (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, SANE_Int mycolormode, SANE_Int arrangeline) { SANE_Int iLineDistance = 0; if (arrangeline == FIX_BY_HARD) { /* we don't need to arrange retrieved line */ SANE_Int mylinedistance, myevenodddist; mylinedistance = (dev->sensorcfg->line_distance * scancfg->resolution_y) / dev->sensorcfg->resolution; if (hwdcfg->highresolution == TRUE) myevenodddist = (hwdcfg->sensorevenodddistance * scancfg->resolution_y) / dev->sensorcfg->resolution; else myevenodddist = 0; data_bitset (&Regs[0x149], 0x3f, myevenodddist); data_bitset (&Regs[0x14a], 0x3f, mylinedistance); data_bitset (&Regs[0x14b], 0x3f, mylinedistance + myevenodddist); data_bitset (&Regs[0x14c], 0x3f, mylinedistance * 2); data_bitset (&Regs[0x14d], 0x3f, (mylinedistance * 2) + myevenodddist); } else { /* arrange retrieved line */ data_bitset (&Regs[0x149], 0x3f, 0); data_bitset (&Regs[0x14a], 0x3f, 0); data_bitset (&Regs[0x14b], 0x3f, 0); data_bitset (&Regs[0x14c], 0x3f, 0); data_bitset (&Regs[0x14d], 0x3f, 0); if (arrangeline == FIX_BY_SOFT) { if (hwdcfg->highresolution == FALSE) { if (mycolormode == CM_COLOR) { iLineDistance = (dev->sensorcfg->line_distance * scan2.resolution_y) * 2; iLineDistance = (iLineDistance / dev->sensorcfg->resolution) + 1; if (iLineDistance < 2) iLineDistance = 2; } } else { /* bcc */ if (mycolormode == CM_COLOR) iLineDistance = ((dev->sensorcfg->line_distance * 2) + hwdcfg->sensorevenodddistance) * scan2.resolution_y; else iLineDistance = dev->sensorcfg->line_distance * scan2.resolution_y; iLineDistance = (iLineDistance / dev->sensorcfg->resolution) + 1; if (iLineDistance < 2) iLineDistance = 2; } /* c25 */ iLineDistance &= 0xffff; v15b4 = (iLineDistance > 0) ? 1 : 0; imagesize += iLineDistance * bytesperline; } } DBG (DBG_FNC, "> RTS_Setup_Line_Distances(*Regs, *scancfg, *hwdcfg, mycolormode=%i, arrangeline=%i): %i\n", mycolormode, arrangeline, iLineDistance); return iLineDistance; } static SANE_Int RTS_Setup_Depth (SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int mycolormode) { /* channels_per_line = channels_per_dot * scan.width bytes_per_line = channels_per_line * bits_per_channel */ SANE_Int bytes_per_line = 0; if ((scancfg != NULL) && (Regs != NULL)) { SANE_Int channels_per_line = data_bitget (&Regs[0x12], 0xc0) * scancfg->coord.width; bytes_per_line = channels_per_line; /* set bits per channel in shading correction's register (0x1cf) */ if (mycolormode == CM_LINEART) { /* lineart mode */ bytes_per_line = (bytes_per_line + 7) / 8; data_bitset (&Regs[0x1cf], 0x30, 3); /*--11----*/ } else { /*f0c */ switch (scancfg->depth) { case 16: /* 16 bits per channel */ bytes_per_line *= 2; data_bitset (&Regs[0x1cf], 0x30, 2); /*--10----*/ break; case 12: /* 12 bits per channel */ bytes_per_line *= 2; data_bitset (&Regs[0x1cf], 0x30, 1); /*--01----*/ break; default: /* 8 bits per channel */ data_bitset (&Regs[0x1cf], 0x30, 0); /*--00----*/ break; } } } return bytes_per_line; } static void RTS_Setup_Shading (SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, SANE_Int bytes_per_line) { DBG (DBG_FNC, "> RTS_Setup_Shading(*Regs, *scancfg, *hwdcfg, bytes_per_line=%i)\n", bytes_per_line); if ((Regs != NULL) && (hwdcfg != NULL)) { SANE_Int dots_count, myvalue, myvalue2, mem_available, resolution_ratio, sensor_line_distance; SANE_Int channels, table_size; resolution_ratio = Regs[0x0c0] & 0x1f; /* 50de */ data_bitset (&Regs[0x1bf], 0x18, hwdcfg->unk3); /*---xx---*/ /* Enable black shading correction ? */ data_bitset (&Regs[0x1cf], 0x08, hwdcfg->black_shading); /*----x---*/ /* Enable white shading correction ? */ data_bitset (&Regs[0x1cf], 0x04, hwdcfg->white_shading); /*-----x--*/ if ((hwdcfg->white_shading != FALSE) && (hwdcfg->black_shading != FALSE) && (hwdcfg->unk3 != 0)) data_bitset (&Regs[0x1cf], 0x04, 0); /*-----x--*/ table_size = 0; /* if hwdcfg->black_shading */ if ((Regs[0x1cf] & 8) != 0) table_size = (resolution_ratio * scancfg->coord.width) * 2; /* black shading buffer size? */ /* if hwdcfg->white_shading */ if ((Regs[0x1cf] & 4) != 0) table_size += (resolution_ratio * scancfg->coord.width) * 2; /* white shading buffer size? */ /* Regs 0x1ba, 0x1bb, 0x1bd, 0x1c0 seem to be 4 pointers to some buffer related to shading correction */ Regs[0x1ba] = 0x00; table_size = (table_size + v160c_block_size - 1) / v160c_block_size; table_size = ((table_size + 15) / 16) + 16; Regs[0x1bf] &= 0xfe; Regs[0x1bb] = _B0 (table_size); Regs[0x1bc] = _B1 (table_size); Regs[0x1bf] |= _B2 (table_size) & 1; /*-------x*/ Regs[0x1bf] &= 0xf9; Regs[0x1bd] = _B0 (table_size * 2); Regs[0x1be] = _B1 (table_size * 2); Regs[0x1bf] |= (_B2 (table_size * 2) & 3) << 1; /*-----xx-*/ data_wide_bitset (&Regs[0x1c0], 0xfffff, table_size * 3); mem_available = mem_total - ((table_size * 3) * 16); sensor_line_distance = Regs[0x14a] & 0x3f; /* select case channels_per_dot */ channels = data_lsb_get (&Regs[0x12], 1) >> 6; switch (channels) { case 3: /* 3 channels per dot */ /* 528d */ dots_count = bytes_per_line / 3; /* 882 */ myvalue = (((sensor_line_distance + 1) * dots_count) + v160c_block_size - 1) / v160c_block_size; myvalue2 = myvalue; mem_available = (mem_available - (myvalue * 3) + 2) / 3; myvalue += (table_size * 3) * 8; myvalue = ((myvalue * 2) + mem_available); data_bitset (&Regs[0x1c2], 0xf0, _B2 ((myvalue / 16) + 1)); /* 4 higher bits xxxx---- */ data_wide_bitset (&Regs[0x1c3], 0xffff, (myvalue / 16) + 1); /* 16 lower bits */ myvalue = myvalue + myvalue2 + mem_available; data_wide_bitset (&Regs[0x1c5], 0xfffff, (myvalue / 16) + 1); break; case 2: /* 2 channels per dot */ dots_count = bytes_per_line / 2; myvalue = (((sensor_line_distance + 1) * dots_count) + v160c_block_size - 1) / v160c_block_size; mem_available = ((mem_available - myvalue) + 1) / 2; myvalue += (((table_size * 3) + mem_available) / 16) + 1; data_bitset (&Regs[0x1c2], 0xf0, _B2 (myvalue)); /* 4 higher bits xxxx---- */ data_wide_bitset (&Regs[0x1c3], 0xffff, myvalue); /* 16 lower bits */ break; default: dots_count = bytes_per_line; break; } Regs[0x01c7] &= 0x0f; Regs[0x01c8] = _B0 ((mem_total - 1) / 16); Regs[0x01c9] = _B1 ((mem_total - 1) / 16); Regs[0x01c7] |= (_B2 ((mem_total - 1) / 16) & 0x0f) << 4; mem_available -= (dots_count + v160c_block_size - 1) / v160c_block_size; mem_available /= 16; Regs[0x0712] &= 0x0f; Regs[0x0710] = _B0 (mem_available); Regs[0x0711] = _B1 (mem_available); Regs[0x0712] |= _B0 (_B2 (mem_available) << 4); /*xxxx---- */ Regs[0x0713] = 0x00; Regs[0x0714] = 0x10; Regs[0x0715] &= 0xf0; } } static void RTS_Setup_Arrangeline (struct st_device *dev, struct st_hwdconfig *hwdcfg, SANE_Int colormode) { dev->scanning->arrange_compression = (colormode == CM_LINEART) ? FALSE : hwdcfg->compression; if ((colormode == CM_LINEART) || ((colormode == CM_GRAY) && (hwdcfg->highresolution == FALSE))) arrangeline2 = 0; else arrangeline2 = hwdcfg->arrangeline; dev->scanning->arrange_hres = hwdcfg->highresolution; dev->scanning->arrange_sensor_evenodd_dist = (hwdcfg->highresolution == FALSE) ? 0 : hwdcfg->sensorevenodddistance; } static void RTS_Setup_Channels (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, SANE_Int mycolormode) { DBG (DBG_FNC, "> RTS_Setup_Channels(colormode=%i)\n", mycolormode); if ((scancfg != NULL) && (Regs != NULL)) { if ((mycolormode != CM_COLOR) && (mycolormode != 3)) { /* CM_GRAY || CM_LINEART */ if (scancfg->samplerate == LINE_RATE) { /* Setting channels_per_dot to 1 */ data_bitset (&Regs[0x12], 0xc0, 1); /*01------ */ /* setting one rgb_channel_order */ data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->rgb_order[scancfg->channel]); /*------xx*/ /* set sensor_channel_color_order */ data_bitset (&Regs[0x60a], 0x3f, 6); /*--xxxxxx*/ /* set samplerate */ data_bitset (&Regs[0x1cf], 0x40, PIXEL_RATE); /*-x------*/ /* set unknown data */ data_bitset (&Regs[0x1cf], 0x80, 1); /*x------- */ if (scancfg->channel == dev->sensorcfg->rgb_order[1]) { /* mexpts[CL_RED] = mexpts[CL_GREEN] */ data_lsb_set (&Regs[0x33], data_lsb_get (&Regs[0x39], 3), 3); /* expts[CL_RED] = expts[CL_GREEN] */ data_lsb_set (&Regs[0x36], data_lsb_get (&Regs[0x3c], 3), 3); } else if (scancfg->channel == dev->sensorcfg->rgb_order[2]) { /* mexpts[CL_RED] = mexpts[CL_BLUE] */ data_lsb_set (&Regs[0x33], data_lsb_get (&Regs[0x3f], 3), 3); /* expts[CL_RED] = expts[CL_BLUE] */ data_lsb_set (&Regs[0x36], data_lsb_get (&Regs[0x42], 3), 3); } } else { /* e01 */ /* setting channels_per_dot to 2 */ data_bitset (&Regs[0x12], 0xc0, 2); /* set two channel color order */ data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->channel_gray[0]); /*------xx*/ data_bitset (&Regs[0x12], 0x0c, dev->sensorcfg->channel_gray[1]); /*----xx--*/ /* set samplerate */ data_bitset (&Regs[0x1cf], 0x40, LINE_RATE); /* set unknown data */ data_bitset (&Regs[0x1cf], 0x80, 1); } } else { /* CM_COLOR || 3 */ /* e42 */ /* setting channels_per_dot to 3 */ data_bitset (&Regs[0x12], 0xc0, 3); /* setting samplerate */ data_bitset (&Regs[0x1cf], 0x40, scancfg->samplerate); /* set unknown data */ data_bitset (&Regs[0x1cf], 0x80, 0); /* set sensor chanel_color_order */ data_bitset (&Regs[0x60a], 0x03, dev->sensorcfg->channel_color[2]); /*------xx*/ data_bitset (&Regs[0x60a], 0x0c, dev->sensorcfg->channel_color[1]); /*----xx--*/ data_bitset (&Regs[0x60a], 0x30, dev->sensorcfg->channel_color[0]); /*--xx----*/ /* set rgb_channel_order */ data_bitset (&Regs[0x12], 0x03, dev->sensorcfg->rgb_order[0]); /*------xx*/ data_bitset (&Regs[0x12], 0x0c, dev->sensorcfg->rgb_order[1]); /*----xx--*/ data_bitset (&Regs[0x12], 0x30, dev->sensorcfg->rgb_order[2]); /*--xx----*/ } } } static SANE_Int RTS_Setup (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg, struct st_gain_offset *gain_offset) { SANE_Int rst = ERROR; /* default */ SANE_Int lSMode; SANE_Byte mycolormode; DBG (DBG_FNC, "+ RTS_Setup:\n"); dbg_ScanParams (scancfg); dbg_hwdcfg (hwdcfg); mycolormode = scancfg->colormode; if (scancfg->colormode != CM_COLOR) { if (scancfg->colormode == CM_LINEART) scancfg->depth = 8; if (scancfg->channel == 3) { if (scancfg->colormode == CM_GRAY) mycolormode = (hwdcfg->arrangeline != FIX_BY_SOFT) ? 3 : CM_COLOR; else mycolormode = 3; } } /* 42b47d6 */ memcpy (&scan2, scancfg, sizeof (struct st_scanparams)); scantype = hwdcfg->scantype; lSMode = RTS_GetScanmode (dev, scantype, mycolormode, scancfg->resolution_x); if (lSMode >= 0) { struct st_scanmode *sm = dev->scanmodes[lSMode]; if (sm != NULL) { SANE_Int dummyline, iLineDistance, resolution_ratio, bytes_per_line; struct st_coords rts_coords; iLineDistance = 0; scancfg->timing = sm->timing; scancfg->sensorresolution = dev->timings[scancfg->timing]->sensorresolution; scancfg->shadinglength = (((scancfg->sensorresolution * 17) / 2) + 3) & 0xfffffffc; scancfg->samplerate = sm->samplerate; hwdcfg->motorplus = sm->motorplus; /* set systemclock */ data_bitset (&Regs[0x00], 0x0f, sm->systemclock); /* setting exposure times */ RTS_Setup_Exposure_Times (Regs, scancfg, sm); /* setting arranges */ RTS_Setup_Arrangeline (dev, hwdcfg, mycolormode); /* set up line distances */ iLineDistance = RTS_Setup_Line_Distances (dev, Regs, scancfg, hwdcfg, mycolormode, arrangeline); /* 4c67 */ /* setup channel colors */ RTS_Setup_Channels (dev, Regs, scancfg, mycolormode); /* setup depth */ bytes_per_line = RTS_Setup_Depth (Regs, scancfg, mycolormode); /* f61 */ /* Set resolution ratio */ resolution_ratio = (scancfg->sensorresolution / scancfg->resolution_x) & 0x1f; data_bitset (&Regs[0xc0], 0x1f, resolution_ratio); /* set sensor timing values */ RTS_Setup_SensorTiming (dev, scancfg->timing, Regs); data_bitset (&Regs[0xd8], 0x40, ((scantype == ST_NORMAL) ? 0 : 1)); /*-x------*/ /* Use static head ? */ data_bitset (&Regs[0xd8], 0x80, ((hwdcfg->static_head == FALSE) ? 1 : 0)); /*x------- */ /* Setting up gamma */ RTS_Setup_Gamma (Regs, hwdcfg); /* setup shading correction */ RTS_Setup_Shading (Regs, scancfg, hwdcfg, bytes_per_line); /* setup stepper motor */ hwdcfg->startpos = RTS_Setup_Motor (dev, Regs, scancfg, hwdcfg->motor_direction | MTR_ENABLED); /* set coordinates */ dummyline = data_bitget (&Regs[0xd6], 0xf0); if (scancfg->coord.left == 0) scancfg->coord.left++; if (scancfg->coord.top == 0) scancfg->coord.top++; rts_coords.left = scancfg->coord.left * resolution_ratio; rts_coords.width = scancfg->coord.width * resolution_ratio; rts_coords.top = scancfg->coord.top * dummyline; rts_coords.height = ((Regs[0x14d] & 0x3f) + scancfg->coord.height + iLineDistance) * dummyline; if ((rts_coords.left & 1) == 0) rts_coords.left++; RTS_Setup_Coords (Regs, rts_coords.left, rts_coords.top, rts_coords.width, rts_coords.height); data_bitset (&Regs[0x01], 0x06, 0); /*-----xx-*/ /* dummy_scan? */ data_bitset (&Regs[0x01], 0x10, hwdcfg->dummy_scan); /*---x----*/ data_bitset (&Regs[0x163], 0xc0, 1); /*xx------ */ if (dev->scanning->arrange_compression != FALSE) { Regs[0x60b] &= 0x8f; data_bitset (&Regs[0x60b], 0x10, 1); /*-001----*/ } else data_bitset (&Regs[0x60b], 0x7f, 0); /*-0000000*/ if (mycolormode == 3) { SANE_Int channels_per_line; /* Set channels_per_line = channels_per_dot * scan_width */ channels_per_line = data_bitget (&Regs[0x12], 0xc0) * scancfg->coord.width; data_wide_bitset (&Regs[0x060c], 0x3ffff, channels_per_line); /* Sets 16 bits per channel */ data_bitset (&Regs[0x1cf], 0x30, 2); /*--10----*/ Regs[0x60b] |= 0x40; if (v1619 == 0x21) { dev->scanning->arrange_compression = FALSE; data_bitset (&Regs[0x60b], 0x10, 0); /*---0----*/ } switch (scancfg->depth) { case 8: case 16: Regs[0x060b] &= 0xf3; break; case 12: Regs[0x060b] = (Regs[0x060b] & 0xfb) | 0x08; break; } if (scancfg->colormode == CM_LINEART) data_bitset (&Regs[0x60b], 0x0c, 0); /* disable gamma correction ¿? */ data_bitset (&Regs[0x1d0], 0x40, 0); } /* 5683 */ /* Set calibration table */ RTS_Setup_GainOffset (Regs, gain_offset); rst = OK; } } DBG (DBG_FNC, "- RTS_Setup: %i\n", rst); return rst; } static void RTS_Setup_Coords (SANE_Byte * Regs, SANE_Int iLeft, SANE_Int iTop, SANE_Int width, SANE_Int height) { DBG (DBG_FNC, "> RTS_Setup_Coords(*Regs, iLeft=%i, iTop=%i, width=%i, height=%i)\n", iLeft, iTop, width, height); if (Regs != NULL) { /* Set Left coord */ data_lsb_set (&Regs[0xb0], iLeft, 2); /* Set Right coord */ data_lsb_set (&Regs[0xb2], iLeft + width, 2); /* Set Top coord */ data_lsb_set (&Regs[0xd0], iTop, 2); data_bitset (&Regs[0xd4], 0x0f, _B2 (iTop)); /* Set Down coord */ data_lsb_set (&Regs[0xd2], iTop + height, 2); data_bitset (&Regs[0xd4], 0xf0, _B2 (iTop + height)); } } static void RTS_Setup_GainOffset (SANE_Byte * Regs, struct st_gain_offset *gain_offset) { SANE_Byte fake[] = { 0x19, 0x15, 0x19, 0x64, 0x64, 0x64, 0x74, 0xc0, 0x74, 0xc0, 0x6d, 0xc0, 0x6d, 0xc0, 0x5f, 0xc0, 0x5f, 0xc0 }; DBG (DBG_FNC, "> RTS_Setup_GainOffset(*Regs, *gain_offset)\n"); dbg_calibtable (gain_offset); if ((Regs != NULL) && (gain_offset != NULL)) { if (RTS_Debug->calibrate == FALSE) { data_bitset (&Regs[0x13], 0x03, gain_offset->pag[CL_RED]); /*------xx*/ data_bitset (&Regs[0x13], 0x0c, gain_offset->pag[CL_GREEN]); /*----xx--*/ data_bitset (&Regs[0x13], 0x30, gain_offset->pag[CL_BLUE]); /*--xx----*/ memcpy (&Regs[0x14], &fake, 18); } else { SANE_Int a; for (a = CL_RED; a <= CL_BLUE; a++) { /* Offsets */ Regs[0x1a + (a * 4)] = _B0 (gain_offset->edcg1[a]); Regs[0x1b + (a * 4)] = ((gain_offset->edcg1[a] >> 1) & 0x80) | (gain_offset-> edcg2[a] & 0x7f); Regs[0x1c + (a * 4)] = _B0 (gain_offset->odcg1[a]); Regs[0x1d + (a * 4)] = ((gain_offset->odcg1[a] >> 1) & 0x80) | (gain_offset-> odcg2[a] & 0x7f); /* Variable Gain Amplifier */ data_bitset (&Regs[0x14 + a], 0x1f, gain_offset->vgag1[a]); data_bitset (&Regs[0x17 + a], 0x1f, gain_offset->vgag2[a]); } data_bitset (&Regs[0x13], 0x03, gain_offset->pag[CL_RED]); /*------xx*/ data_bitset (&Regs[0x13], 0x0c, gain_offset->pag[CL_GREEN]); /*----xx--*/ data_bitset (&Regs[0x13], 0x30, gain_offset->pag[CL_BLUE]); /*--xx----*/ } } } static void Calibrate_Free (struct st_cal2 *calbuffers) { DBG (DBG_FNC, "> Calibrate_Free(*calbuffers)\n"); if (calbuffers != NULL) { SANE_Int c; if (calbuffers->table2 != NULL) { free (calbuffers->table2); calbuffers->table2 = NULL; } for (c = 0; c < 4; c++) { if (calbuffers->tables[c] != NULL) { free (calbuffers->tables[c]); calbuffers->tables[c] = NULL; } } calbuffers->shadinglength1 = 0; calbuffers->tables_size = 0; calbuffers->shadinglength3 = 0; } } static SANE_Int Calibrate_Malloc (struct st_cal2 *calbuffers, SANE_Byte * Regs, struct st_calibration *myCalib, SANE_Int somelength) { SANE_Int myshadinglength, pos; SANE_Int rst; if ((calbuffers != NULL) && (Regs != NULL) && (myCalib != NULL)) { if ((Regs[0x1bf] & 0x18) == 0) { if ((((Regs[0x1cf] >> 1) & Regs[0x1cf]) & 0x04) != 0) calbuffers->table_count = 2; else calbuffers->table_count = 4; } else calbuffers->table_count = 4; /*365d */ myshadinglength = myCalib->shadinglength * 2; calbuffers->shadinglength1 = min (myshadinglength, somelength); if ((myshadinglength % somelength) != 0) calbuffers->tables_size = (myshadinglength >= somelength) ? somelength * 2 : somelength; else calbuffers->tables_size = somelength; if (myshadinglength >= somelength) { calbuffers->shadinglength1 = (myshadinglength % calbuffers->shadinglength1) + calbuffers->shadinglength1; calbuffers->shadinglength3 = ((myCalib->shadinglength * 2) / somelength) - 1; } else calbuffers->shadinglength3 = 0; calbuffers->shadinglength3 = (somelength / 16) * calbuffers->shadinglength3; rst = OK; for (pos = 0; pos < calbuffers->table_count; pos++) { calbuffers->tables[pos] = (USHORT *) malloc (calbuffers->tables_size * sizeof (USHORT)); if (calbuffers->tables[pos] == NULL) { rst = ERROR; break; } } if (rst == OK) { calbuffers->table2 = (USHORT *) malloc (calbuffers->tables_size * sizeof (USHORT)); if (calbuffers->table2 == NULL) rst = ERROR; } if (rst != OK) Calibrate_Free (calbuffers); } else rst = ERROR; DBG (DBG_FNC, "> Calibrate_Malloc(*calbuffers, *Regs, *myCalib, somelength=%i): %i\n", somelength, rst); return rst; } static SANE_Int fn3560 (USHORT * table, struct st_cal2 *calbuffers, SANE_Int * tablepos) { /*05FEF974 001F99B0 |table = 001F99B0 05FEF978 05FEFA08 |calbuffers->tables[0] = 05FEFA08 05FEF97C 000000A0 |calbuffers->shadinglength3 = 000000A0 05FEF980 00000348 |calbuffers->shadinglength1 = 00000348 05FEF984 04F01502 |calbuffers->table_count = 04F01502 05FEF988 05FEF998 \Arg6 = 05FEF998 */ if (table != NULL) { SANE_Int pos[4] = { 0, 0, 0, 0 }; /*f960 f964 f968 f96c */ SANE_Int usetable = 0; SANE_Int a; SANE_Int mylength3 = calbuffers->shadinglength1; /*f97c */ SANE_Byte *pPointer = (SANE_Byte *) (table + (calbuffers->shadinglength3 * 16)); DBG (DBG_FNC, "> fn3560(*table, *calbuffers, *tablepos)\n"); if (mylength3 > 0) { do { if (calbuffers->tables[usetable] != NULL) { if (mylength3 <= 16) { if (mylength3 > 0) { do { *(calbuffers->tables[usetable] + pos[usetable]) = _B0 (*pPointer); pPointer++; pos[usetable]++; mylength3--; } while (mylength3 > 0); } break; } for (a = 0; a < 16; a++) { *(calbuffers->tables[usetable] + pos[usetable]) = _B0 (*pPointer); pPointer++; pos[usetable]++; } } mylength3 -= 16; usetable++; if (usetable == calbuffers->table_count) usetable = 0; } while (mylength3 > 0); } /*35f8 */ if (calbuffers->table_count > 0) { /* Return position of each table */ memcpy (tablepos, pos, sizeof (SANE_Int) * 4); } } return OK; } static SANE_Int Calib_WriteTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, SANE_Int data) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Calib_WriteTable(*table, size=%i):\n", size); if ((table != NULL) && (size > 0)) { SANE_Int transferred; if (RTS_DMA_Reset (dev) == OK) { /* Send size to write */ if (RTS_DMA_Enable_Write (dev, 0x0004, size, data) == OK) /* Send data */ rst = Bulk_Operation (dev, BLK_WRITE, size, table, &transferred); } } DBG (DBG_FNC, "- Calib_WriteTable: %i\n", rst); return rst; } static SANE_Int Calib_ReadTable (struct st_device *dev, SANE_Byte * table, SANE_Int size, SANE_Int data) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ Calib_ReadTable(*table, size=%i):\n", size); if ((table != NULL) && (size > 0)) { SANE_Int transferred; if (RTS_DMA_Reset (dev) == OK) { /* Send size to read */ if (RTS_DMA_Enable_Read (dev, 0x0004, size, data) == OK) /* Retrieve data */ rst = Bulk_Operation (dev, BLK_READ, size, table, &transferred); } } DBG (DBG_FNC, "- Calib_ReadTable: %i\n", rst); return rst; } static SANE_Int fn3330 (struct st_device *dev, SANE_Byte * Regs, struct st_cal2 *calbuffers, SANE_Int sensorchannelcolor, SANE_Int * tablepos, SANE_Int data) { /*05EEF968 04F0F7F8 |Regs = 04F0F7F8 05EEF96C 02DEC838 |calbuffers->table2 = 02DEC838 05EEF970 05EEFA08 |calbuffers->tables[] = 05EEFA08 05EEF974 00000000 |sensorchannelcolor = 00000000 05EEF978 000000A0 |calbuffers->shadinglength3 = 000000A0 05EEF97C 00000400 |calbuffers->tables_size = 00000400 05EEF980 05EEF998 |&pos = 05EEF998 05EEF984 00221502 |calbuffers->table_count = 00221502 05EEF988 00000000 \data = 00000000 */ SANE_Int table_count = calbuffers->table_count; /*f960 */ SANE_Int schcolor = _B0 (sensorchannelcolor); SANE_Int a = 0; SANE_Int tablelength = calbuffers->shadinglength3 / table_count; /*f954 */ SANE_Int val_color = 0; /*f974 */ SANE_Int val_lineart = 0; /*f978 */ SANE_Int val_gray = 0; /*ebx */ SANE_Int value4 = 0; /*ebp */ SANE_Int size; SANE_Int rst = OK; DBG (DBG_FNC, "+ fn3330(*Regs, *calbuffers, sensorchannelcolor=%i, *tablepos, data=%i):\n", sensorchannelcolor, data); if (calbuffers->table_count > 0) { do { if (calbuffers->table_count == 2) { /*338c */ if (a != 0) { /*3394 */ if (_B0 (data) == 0) { val_color = 0x100000; val_lineart = 0x100000; val_gray = 0x200000; } else { /*343a */ val_color = 0x300000; val_lineart = 0x300000; val_gray = 0; } } else { /*33be */ if (_B0 (data) == 0) { val_color = 0; val_lineart = 0; val_gray = 0x300000; } else { /*342a */ val_color = 0x200000; val_lineart = 0x200000; val_gray = 0x100000; } } } else { /*33d5 */ switch (a) { case 0: val_color = 0; val_lineart = 0; val_gray = 0x300000; break; case 1: val_color = 0x200000; val_lineart = 0x200000; val_gray = 0x100000; break; case 2: val_color = 0x100000; val_lineart = 0x100000; val_gray = 0x200000; break; case 3: val_color = 0x300000; val_lineart = 0x300000; val_gray = 0; break; } } /*3449 */ switch (schcolor) { case CM_LINEART: size = (((Regs[0x1bf] >> 1) & 3) << 0x10) | (Regs[0x1be] << 0x08) | Regs[0x1bd]; value4 = (tablelength + size) | val_lineart; break; case CM_GRAY: size = ((Regs[0x1bf] & 1) << 0x10) | (Regs[0x1bc] << 0x08) | Regs[0x1bb]; value4 = (tablelength + size) | val_gray; break; default: size = _B0 (Regs[0x1ba]); value4 = (tablelength + size) | val_color; break; } if (Calib_ReadTable (dev, (SANE_Byte *) calbuffers->table2, calbuffers->tables_size, value4) != OK) { rst = ERROR; break; } memcpy (calbuffers->tables[a], calbuffers->table2, tablepos[a]); if (tablepos[a + 1] == 0) break; a++; } while (a < calbuffers->table_count); } DBG (DBG_FNC, "- fn3330: %i\n", rst); return rst; } static SANE_Int fn3730 (struct st_device *dev, struct st_cal2 *calbuffers, SANE_Byte * Regs, USHORT * table, SANE_Int sensorchannelcolor, SANE_Int data) { /*05FEF9AC |calbuffers = 05FEF9F8 05FEF9B0 |Regs = 04EFF7F8 05FEF9B4 |table = 001F99B0 05FEF9B8 |sensorchannelcolor = 00000000 05FEF9BC |data = 00000000 */ SANE_Int pos[4] = { 0, 0, 0, 0 }; /*f998 f99c f9a0 f9a4 */ SANE_Int rst; DBG (DBG_FNC, "+ fn3730(*calbuffers, *Regs, *table, sensorchannelcolor=%i, data=%i):\n", sensorchannelcolor, data); fn3560 (table, calbuffers, pos); rst = fn3330 (dev, Regs, calbuffers, sensorchannelcolor, pos, data); DBG (DBG_FNC, "- fn3730: %i\n", rst); return rst; } static SANE_Int Shading_white_apply (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels, struct st_calibration *myCalib, struct st_cal2 *calbuffers) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Shading_white_apply(channels=%i)\n", channels); /*3e7f */ Calibrate_Malloc (calbuffers, Regs, myCalib, (RTS_Debug->usbtype == USB20) ? 0x200 : 0x40); if (channels > 0) { /*int a; */ SANE_Int chnl; SANE_Int pos; /*fa2c */ SANE_Int transferred; rst = ERROR; for (chnl = 0; chnl < channels; chnl++) { /*for (a = 0; a < myCalib->shadinglength; a++) myCalib->black_shading[chnl][a] = 0x2000; */ /* 11 tries */ for (pos = 0; pos <= 10; pos++) { /* Send size to write */ if (RTS_DMA_Enable_Write (dev, dev->sensorcfg->channel_color[chnl] | 0x14, myCalib->shadinglength, 0) == OK) /* Send data */ Bulk_Operation (dev, BLK_WRITE, myCalib->shadinglength * sizeof (USHORT), (SANE_Byte *) & myCalib-> white_shading[chnl][myCalib->first_position - 1], &transferred); /*3df7 */ if (fn3730 (dev, calbuffers, Regs, &myCalib->white_shading[chnl][myCalib->first_position - 1], dev->sensorcfg->channel_color[chnl], 1) == OK) { rst = OK; break; } RTS_DMA_Cancel (dev); } } } Calibrate_Free (calbuffers); DBG (DBG_FNC, "- Shading_white_apply: %i\n", rst); return OK; } static SANE_Int Shading_black_apply (struct st_device *dev, SANE_Byte * Regs, SANE_Int channels, struct st_calibration *myCalib, struct st_cal2 *calbuffers) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Shading_black_apply(channels=%i)\n", channels); /* 3d79 */ Calibrate_Malloc (calbuffers, Regs, myCalib, (RTS_Debug->usbtype == USB20) ? 0x200 : 0x40); if (channels > 0) { /*int a; */ SANE_Int chnl; SANE_Int pos; /*fa2c */ SANE_Int transferred; rst = ERROR; for (chnl = 0; chnl < channels; chnl++) { /* 11 tries */ /*for (a = 0; a < myCalib->shadinglength; a++) myCalib->black_shading[chnl][a] = 0x2000; */ for (pos = 0; pos <= 10; pos++) { /* Send size to write */ if (RTS_DMA_Enable_Write (dev, dev->sensorcfg->channel_color[chnl] | 0x10, myCalib->shadinglength, 0) == OK) /* Send data */ Bulk_Operation (dev, BLK_WRITE, myCalib->shadinglength * sizeof (USHORT), (SANE_Byte *) & myCalib-> black_shading[chnl][myCalib->first_position - 1], &transferred); /*3df7 */ if (fn3730 (dev, calbuffers, Regs, &myCalib->black_shading[chnl][myCalib->first_position - 1], dev->sensorcfg->channel_color[chnl], 0) == OK) { rst = OK; break; } RTS_DMA_Cancel (dev); } } } /*3e62 */ Calibrate_Free (calbuffers); DBG (DBG_FNC, "- Shading_black_apply: %i\n", rst); return OK; } static SANE_Int Shading_apply (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *myvar, struct st_calibration *myCalib) { /* Regs f1bc myvar f020 hwdcfg e838 arg4 e81c myCalib e820 */ SANE_Int rst; /* lf9e0 */ SANE_Int myfact; /* e820 */ SANE_Int shadata; SANE_Byte channels; /* f9d4 */ SANE_Int myShadingBase; /* e818 */ char lf9d1; char lf9d0; DBG (DBG_FNC, "+ Shading_apply(*Regs, *myvar, *mygamma, *myCalib):\n"); dbg_ScanParams (myvar); lf9d0 = (Regs[0x60b] >> 6) & 1; lf9d1 = (Regs[0x60b] >> 4) & 1; Regs[0x060b] &= 0xaf; rst = Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); if (rst == OK) { SANE_Byte colormode = myvar->colormode; /*fa24 */ SANE_Int le7cc, le7d8; struct st_cal2 calbuffers; /* f9f8 */ if (colormode != CM_COLOR) { if (myvar->channel != 3) { if (colormode != 3) channels = (myvar->samplerate == PIXEL_RATE) ? 2 : 1; else channels = 3; } else { colormode = 3; channels = 3; } } else channels = 3; /* White shading formula : 2000H x Target / (Wn-Dn) = White Gain data ----- for 8 times system White shading formula : 4000H x Target / (Wn-Dn) = White Gain data ----- for 4 times system For example : Target = 3FFFH Wn = 2FFFH Dn = 0040H and 8 times system operation then White Gain = 2000H x 3FFFH / (2FFFH-0040H) = 2AE4H (1.34033 times) */ /* 3aad */ if (colormode == 3) { /* SANE_Int pos; SANE_Int colour; myShadingBase = shadingbase; for (colour = 0; colour < channels; colour++) { if (myCalib->white_shading[colour] != NULL) { myfact = shadingfact[colour]; if (myCalib->shadinglength > 0) { for (pos = myCalib->first_position - 1; pos < myCalib->shadinglength; pos++) myCalib->white_shading[colour][pos] = (myCalib->white_shading[colour][pos] * myfact) / myShadingBase; } } else break; } */ } /* 3b3b */ if (myCalib->shading_enabled != FALSE) { /* 3b46 */ SANE_Int colour, pos; le7cc = shadingbase; le7d8 = shadingbase; DBG (DBG_FNC, "-> Shading type: %i\n", myCalib->shading_type); for (colour = 0; colour < channels; colour++) { if (colormode == 3) le7cc = shadingfact[colour]; myShadingBase = ((Regs[0x1cf] & 2) != 0) ? 0x2000 : 0x4000; myfact = myCalib->WRef[colour] * myShadingBase; if (myCalib->shading_type == 2) { /*3bd8 */ if ((myCalib->black_shading[colour] != NULL) && (myCalib->white_shading[colour] != NULL)) { for (pos = myCalib->first_position - 1; pos < myCalib->shadinglength; pos++) { if (myCalib->white_shading[colour][pos] == 0) shadata = myShadingBase; else shadata = myfact / myCalib->white_shading[colour][pos]; shadata = min ((shadata * le7cc) / le7d8, 0xff00); myCalib->black_shading[colour][pos] &= 0xff; myCalib->black_shading[colour][pos] |= shadata & 0xff00; } } else break; } else { /*3c63 */ if (myCalib->shading_type == 3) { /*3c68 */ if (myCalib->black_shading[colour] != NULL) { for (pos = myCalib->first_position - 1; pos < myCalib->shadinglength; pos++) { if (myCalib->black_shading[colour][pos] == 0) shadata = myShadingBase; else shadata = myfact / myCalib->black_shading[colour][pos]; shadata = min ((shadata * le7cc) / le7d8, 0xffc0); myCalib->black_shading[colour][pos] &= 0x3f; myCalib->black_shading[colour][pos] |= shadata & 0xffc0; } } else break; } else { /*3ce3 */ if (myCalib->white_shading[colour] != NULL) { for (pos = 0; pos < myCalib->shadinglength; pos++) { if (myCalib->white_shading[colour][pos] == 0) shadata = myShadingBase; else shadata = myfact / myCalib->white_shading[colour][pos]; shadata = min ((shadata * le7cc) / le7d8, 0xffff); myCalib->white_shading[colour][pos] = shadata; } } else break; } } } } /*3d4c */ bzero (&calbuffers, sizeof (struct st_cal2)); /* If black shading correction is enabled ... */ if ((Regs[0x1cf] & 8) != 0) Shading_black_apply (dev, Regs, channels, myCalib, &calbuffers); /*3e6e */ /* If white shading correction is enabled ... */ if ((Regs[0x1cf] & 4) != 0) Shading_white_apply (dev, Regs, channels, myCalib, &calbuffers); /* 3f74 */ if (rst == 0) { data_bitset (&Regs[0x60b], 0x40, lf9d0); /*-x------*/ data_bitset (&Regs[0x60b], 0x10, lf9d1); /*---x----*/ rst = Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); } } /*3fb5 */ DBG (DBG_FNC, "- Shading_apply: %i\n", rst); return rst; } static SANE_Int Bulk_Operation (struct st_device *dev, SANE_Byte op, SANE_Int buffer_size, SANE_Byte * buffer, SANE_Int * transfered) { SANE_Int iTransferSize, iBytesToTransfer, iPos, rst, iBytesTransfered; DBG (DBG_FNC, "+ Bulk_Operation(op=%s, buffer_size=%i, buffer):\n", ((op & 0x01) != 0) ? "READ" : "WRITE", buffer_size); iBytesToTransfer = buffer_size; iPos = 0; rst = OK; iBytesTransfered = 0; if (transfered != NULL) *transfered = 0; iTransferSize = min (buffer_size, RTS_Debug->dmatransfersize); if (op != 0) { /* Lectura */ do { iTransferSize = min (iTransferSize, iBytesToTransfer); iBytesTransfered = Read_Bulk (dev->usb_handle, &buffer[iPos], iTransferSize); if (iBytesTransfered < 0) { rst = ERROR; break; } else { if (transfered != NULL) *transfered += iBytesTransfered; } iPos += iTransferSize; iBytesToTransfer -= iTransferSize; } while (iBytesToTransfer > 0); } else { /* Escritura */ do { iTransferSize = min (iTransferSize, iBytesToTransfer); if (Write_Bulk (dev->usb_handle, &buffer[iPos], iTransferSize) != OK) { rst = ERROR; break; } else { if (transfered != NULL) *transfered += iTransferSize; } iPos += iTransferSize; iBytesToTransfer -= iTransferSize; } while (iBytesToTransfer > 0); } DBG (DBG_FNC, "- Bulk_Operation: %i\n", rst); return rst; } static SANE_Int Reading_BufferSize_Notify (struct st_device *dev, SANE_Int data, SANE_Int size) { SANE_Int rst; DBG (DBG_FNC, "+ Reading_BufferSize_Notify(data=%i, size=%i):\n", data, size); rst = RTS_DMA_Enable_Read (dev, 0x0008, size, data); DBG (DBG_FNC, "- Reading_BufferSize_Notify: %i\n", rst); return rst; } static SANE_Int Reading_Wait (struct st_device *dev, SANE_Byte Channels_per_dot, SANE_Byte Channel_size, SANE_Int size, SANE_Int * last_amount, SANE_Int seconds, SANE_Byte op) { SANE_Int rst; SANE_Byte cTimeout, executing; SANE_Int lastAmount, myAmount; long tick; DBG (DBG_FNC, "+ Reading_Wait(Channels_per_dot=%i, Channel_size=%i, size=%i, *last_amount, seconds=%i, op=%i):\n", Channels_per_dot, Channel_size, size, seconds, op); rst = OK; cTimeout = FALSE; lastAmount = 0; myAmount = Reading_BufferSize_Get (dev, Channels_per_dot, Channel_size); if (myAmount < size) { /* Wait until scanner fills its buffer */ if (seconds == 0) seconds = 10; tick = GetTickCount () + (seconds * 1000); while (cTimeout == FALSE) { myAmount = Reading_BufferSize_Get (dev, Channels_per_dot, Channel_size); /* check special case */ if (op == TRUE) { if (((myAmount + 0x450) > size) || (RTS_IsExecuting (dev, &executing) == FALSE)) break; } if (myAmount < size) { /* Check timeout */ if (myAmount == lastAmount) { /* we are in timeout? */ if (tick < GetTickCount ()) { /* TIMEOUT */ rst = ERROR; cTimeout = TRUE; } else usleep (100 * 1000); } else { /* Amount increased, update tick */ lastAmount = myAmount; tick = GetTickCount () + (seconds * 1000); } } else { lastAmount = myAmount; break; /* buffer full */ } } } if (last_amount != NULL) *last_amount = myAmount; DBG (DBG_FNC, "- Reading_Wait: %i , last_amount=%i\n", rst, myAmount); return rst; } static SANE_Int RTS_GetImage_GetBuffer (struct st_device *dev, double dSize, char unsigned *buffer, double *transferred) { SANE_Int rst = ERROR; SANE_Int itransferred; double dtransferred = 0; DBG (DBG_FNC, "+ RTS_GetImage_GetBuffer(dSize=%f, buffer, transferred):\n", dSize); rst = OK; dSize /= 2; if (dSize > 0) { SANE_Int myLength; SANE_Int iPos = 0; do { itransferred = 0; myLength = (dSize <= RTS_Debug->dmasetlength) ? dSize : RTS_Debug->dmasetlength; if (myLength > 0x1ffe0) myLength = 0x1ffe0; rst = ERROR; if (Reading_Wait (dev, 0, 1, myLength * 2, NULL, 5, FALSE) == OK) { if (Reading_BufferSize_Notify (dev, 0, myLength * 2) == OK) rst = Bulk_Operation (dev, BLK_READ, myLength * 2, &buffer[iPos], &itransferred); } if (rst != OK) break; iPos += itransferred; dSize -= itransferred; dtransferred += itransferred * 2; } while (dSize > 0); } /* Return bytes transferred */ if (transferred != NULL) *transferred = dtransferred; if (rst != OK) RTS_DMA_Cancel (dev); DBG (DBG_FNC, "- RTS_GetImage_GetBuffer: %i\n", rst); return rst; } static SANE_Int RTS_GetImage_Read (struct st_device *dev, SANE_Byte * buffer, struct st_scanparams *scancfg, struct st_hwdconfig *hwdcfg) { /*buffer f80c = esp+14 scancfg f850 = esp+18 hwdcfg faac = */ SANE_Int rst = ERROR; DBG (DBG_FNC, "+ RTS_GetImage_Read(buffer, scancfg, hwdcfg):\n"); if (buffer != NULL) { double dSize = scancfg->bytesperline * scancfg->coord.height; SANE_Byte exfn; if (scancfg->depth == 12) dSize = (dSize * 3) / 4; /*3ff6 */ exfn = 1; if (hwdcfg != NULL) if (hwdcfg->compression != FALSE) exfn = 0; if (exfn != 0) { double transferred; rst = RTS_GetImage_GetBuffer (dev, dSize, buffer, &transferred); } if (rst == OK) RTS_WaitScanEnd (dev, 1500); } DBG (DBG_FNC, "- RTS_GetImage_Read: %i\n", rst); return rst; } static SANE_Int RTS_GetImage (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_gain_offset *gain_offset, SANE_Byte * buffer, struct st_calibration *myCalib, SANE_Int options, SANE_Int gaincontrol) { /* 42b8e10 */ SANE_Int rst = ERROR; /* default */ DBG (DBG_FNC, "+ RTS_GetImage(*Regs, *scancfg, *gain_offset, *buffer, myCalib, options=0x%08x, gaincontrol=%i):\n", options, gaincontrol); dbg_ScanParams (scancfg); /* validate arguments */ if ((Regs != NULL) && (scancfg != NULL)) { if ((scancfg->coord.width != 0) && (scancfg->coord.height != 0)) { struct st_scanparams *myscancfg; /* let's make a copy of scan config */ myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); if (myscancfg != NULL) { struct st_hwdconfig *hwdcfg; memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); /* Allocate space for low level config */ hwdcfg = (struct st_hwdconfig *) malloc (sizeof (struct st_hwdconfig)); if (hwdcfg != NULL) { bzero (hwdcfg, sizeof (struct st_hwdconfig)); if (((options & 2) != 0) || ((_B1 (options) & 1) != 0)) { /* switch off lamp */ data_bitset (&Regs[0x146], 0x40, 0); Write_Byte (dev->usb_handle, 0xe946, Regs[0x146]); usleep (1000 * ((v14b4 == 0) ? 500 : 300)); } hwdcfg->scantype = scan.scantype; hwdcfg->use_gamma_tables = ((options & OP_USE_GAMMA) != 0) ? 1 : 0; hwdcfg->white_shading = ((options & OP_WHITE_SHAD) != 0) ? 1 : 0; hwdcfg->black_shading = ((options & OP_BLACK_SHAD) != 0) ? 1 : 0; hwdcfg->motor_direction = ((options & OP_BACKWARD) != 0) ? MTR_BACKWARD : MTR_FORWARD; hwdcfg->compression = ((options & OP_COMPRESSION) != 0) ? 1 : 0; hwdcfg->static_head = ((options & OP_STATIC_HEAD) != 0) ? 1 : 0; hwdcfg->dummy_scan = (buffer == NULL) ? TRUE : FALSE; hwdcfg->arrangeline = 0; hwdcfg->highresolution = (myscancfg->resolution_x > 1200) ? TRUE : FALSE; hwdcfg->unk3 = 0; /* Set Left coord */ myscancfg->coord.left += ((dev->sensorcfg->type == CCD_SENSOR) ? 24 : 50); switch (myscancfg->resolution_x) { case 1200: myscancfg->coord.left -= 63; break; case 2400: myscancfg->coord.left -= 126; break; } if (myscancfg->coord.left < 0) myscancfg->coord.left = 0; RTS_Setup (dev, Regs, myscancfg, hwdcfg, gain_offset); /* Setting exposure time */ switch (scan.scantype) { case ST_NORMAL: if (scan.resolution_x == 100) { SANE_Int iValue; SANE_Byte *myRegs; myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (myRegs != NULL) { bzero (myRegs, RT_BUFFER_LEN * sizeof (SANE_Byte)); RTS_Setup (dev, myRegs, &scan, hwdcfg, gain_offset); iValue = data_lsb_get (&myRegs[0x30], 3); data_lsb_set (&Regs[0x30], iValue, 3); /*Copy myregisters mexpts to Regs mexpts */ iValue = data_lsb_get (&myRegs[0x33], 3); data_lsb_set (&Regs[0x33], iValue, 3); iValue = data_lsb_get (&myRegs[0x39], 3); data_lsb_set (&Regs[0x39], iValue, 3); iValue = data_lsb_get (&myRegs[0x3f], 3); data_lsb_set (&Regs[0x3f], iValue, 3); free (myRegs); } } break; case ST_NEG: { SANE_Int myvalue; /* Setting exposure times for Negative scans */ data_lsb_set (&Regs[0x30], myscancfg->expt, 3); data_lsb_set (&Regs[0x33], myscancfg->expt, 3); data_lsb_set (&Regs[0x39], myscancfg->expt, 3); data_lsb_set (&Regs[0x3f], myscancfg->expt, 3); data_lsb_set (&Regs[0x36], 0, 3); data_lsb_set (&Regs[0x3c], 0, 3); data_lsb_set (&Regs[0x42], 0, 3); myvalue = ((myscancfg->expt + 1) / (data_lsb_get (&Regs[0xe0], 1) + 1)) - 1; data_lsb_set (&Regs[0xe1], myvalue, 3); } break; } /* 91a0 */ if (myscancfg->resolution_y > 600) { options |= 0x20000000; if (options != 0) /* Always true ... */ SetMultiExposure (dev, Regs); else myscancfg->coord.top += hwdcfg->startpos; } else SetMultiExposure (dev, Regs); /* 91e2 */ RTS_WriteRegs (dev->usb_handle, Regs); if (myCalib != NULL) Shading_apply (dev, Regs, myscancfg, myCalib); if (dev->motorcfg->changemotorcurrent != FALSE) Motor_Change (dev, Regs, Motor_GetFromResolution (myscancfg-> resolution_x)); /* mlock = 0 */ data_bitset (&Regs[0x00], 0x10, 0); data_wide_bitset (&Regs[0xde], 0xfff, 0); /* release motor */ Motor_Release (dev); if (RTS_Warm_Reset (dev) == OK) { rst = OK; SetLock (dev->usb_handle, Regs, (myscancfg->depth == 16) ? FALSE : TRUE); /* set gain control */ Lamp_SetGainMode (dev, Regs, myscancfg->resolution_x, gaincontrol); /* send registers to scanner */ if (RTS_WriteRegs (dev->usb_handle, Regs) == OK) { /* execute! */ if (RTS_Execute (dev) == OK) RTS_GetImage_Read (dev, buffer, myscancfg, hwdcfg); /*92e7 */ } /*92fc */ SetLock (dev->usb_handle, Regs, FALSE); if ((options & 0x200) != 0) { /* switch on lamp */ data_bitset (&Regs[0x146], 0x40, 1); Write_Byte (dev->usb_handle, 0xe946, Regs[0x146]); /* Wait 3 seconds */ usleep (1000 * 3000); } /*9351 */ if (dev->motorcfg->changemotorcurrent == TRUE) Motor_Change (dev, dev->init_regs, 3); } /* free low level configuration */ free (hwdcfg); } /* free scanning configuration */ free (myscancfg); } } } DBG (DBG_FNC, "- RTS_GetImage: %i\n", rst); return rst; } static SANE_Int Refs_Detect (struct st_device *dev, SANE_Byte * Regs, SANE_Int resolution_x, SANE_Int resolution_y, SANE_Int * x, SANE_Int * y) { SANE_Int rst = ERROR; /* default */ DBG (DBG_FNC, "+ Refs_Detect(*Regs, resolution_x=%i, resolution_y=%i):\n", resolution_x, resolution_y); if ((x != NULL) && (y != NULL)) { SANE_Byte *image; struct st_scanparams scancfg; *x = *y = 0; /* default */ /* set configuration to scan a little area at the top-left corner */ bzero (&scancfg, sizeof (struct st_scanparams)); scancfg.depth = 8; scancfg.colormode = CM_GRAY; scancfg.channel = CL_RED; scancfg.resolution_x = resolution_x; scancfg.resolution_y = resolution_y; scancfg.coord.left = 4; scancfg.coord.width = (resolution_x * 3) / 10; scancfg.coord.top = 1; scancfg.coord.height = (resolution_y * 4) / 10; scancfg.shadinglength = (resolution_x * 17) / 2; scancfg.bytesperline = scancfg.coord.width; /* allocate space to store image */ image = (SANE_Byte *) malloc ((scancfg.coord.height * scancfg.coord.width) * sizeof (SANE_Byte)); if (image != NULL) { struct st_gain_offset gain_offset; SANE_Int gaincontrol, pwmlamplevel_backup, C; gaincontrol = 0; if (RTS_Debug->use_fixed_pwm == FALSE) { /* 3877 */ gaincontrol = Lamp_GetGainMode (dev, resolution_x, ST_NORMAL); /* scan.scantype */ pwmlamplevel = 0; Lamp_PWM_use (dev, 1); Lamp_PWM_DutyCycle_Set (dev, (gaincontrol == 0) ? 0x12 : 0x26); /* Enciende flb lamp */ Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); usleep (1000 * 2000); } /* 38d6 */ pwmlamplevel_backup = pwmlamplevel; pwmlamplevel = 0; Lamp_PWM_use (dev, 1); bzero (&gain_offset, sizeof (struct st_gain_offset)); for (C = CL_RED; C <= CL_BLUE; C++) { gain_offset.pag[C] = 3; gain_offset.vgag1[C] = 4; gain_offset.vgag2[C] = 4; } /* perform lamp warmup */ Lamp_Warmup (dev, Regs, FLB_LAMP, resolution_x); /* retrieve image from scanner */ if (RTS_GetImage (dev, Regs, &scancfg, &gain_offset, image, 0, 0x20000000, gaincontrol) == OK) { SANE_Int ser1, ler1; /* same image to disk if required by user */ if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("pre-autoref.tiff", scancfg.coord.width, scancfg.coord.height, scancfg.depth, CM_GRAY, scancfg.resolution_x, scancfg.resolution_y, image, scancfg.coord.height * scancfg.coord.width); } /* calculate reference position */ if (Refs_Analyze_Pattern (&scancfg, image, &ler1, 1, &ser1, 0) == OK) { *y = scancfg.coord.top + ler1; *x = scancfg.coord.left + ser1; rst = OK; } } free (image); pwmlamplevel = pwmlamplevel_backup; } DBG (DBG_FNC, " -> Detected refs: x=%i , y=%i\n", *x, *y); } DBG (DBG_FNC, "- Refs_Detect: %i\n", rst); return rst; } static SANE_Int Refs_Set (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg) { SANE_Int rst; SANE_Int y, x; struct st_autoref refcfg; DBG (DBG_FNC, "+ Refs_Set(*Regs, *scancfg):\n"); dbg_ScanParams (scancfg); rst = OK; /* get fixed references for given resolution */ cfg_vrefs_get (dev->sensorcfg->type, scancfg->resolution_x, &scan.ler, &scan.ser); scan.leftleading = scan.ser; scan.startpos = scan.ler; /* get auto reference configuration */ cfg_autoref_get (&refcfg); if (refcfg.type != REF_NONE) { /* if reference counter is == 0 perform auto detection */ if (Refs_Counter_Load (dev) == 0) { DBG (DBG_FNC, " -> Refs_Set - Autodetection mandatory (counter == 0)\n"); refcfg.type = REF_AUTODETECT; } switch (refcfg.type) { case REF_AUTODETECT: /* try to autodetect references scanning a little area */ if (Refs_Detect (dev, Regs, refcfg.resolution, refcfg.resolution, &x, &y) == OK) Refs_Save (dev, x, y); else rst = ERROR; Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); break; case REF_TAKEFROMSCANNER: /* Try to get values from scanner */ if (Refs_Load (dev, &x, &y) == ERROR) { if (Refs_Detect (dev, Regs, refcfg.resolution, refcfg.resolution, &x, &y) == OK) Refs_Save (dev, x, y); else rst = ERROR; Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); } break; } if (rst == OK) { /* values are based on resolution given by refcfg.resolution. offset_x and y are based on 2400 dpi so convert values to that dpi before adding offsets and then return to resolution given by user */ x *= (2400 / refcfg.resolution); y *= (2400 / refcfg.resolution); scan.leftleading = x; scan.startpos = y; scan.ser = ((x + refcfg.offset_x) * scancfg->resolution_x) / 2400; scan.ler = ((y + refcfg.offset_y) * scancfg->resolution_y) / 2400; DBG (DBG_FNC, " -> After SEROffset and LEROffset, xoffset = %i, yoffset =%i\n", scan.ser, scan.ler); } /* increase refs counter */ Refs_Counter_Inc (dev); } DBG (DBG_FNC, "- Refs_Set: %i\n", rst); return rst; } static SANE_Int Lamp_Status_Set (struct st_device *dev, SANE_Byte * Regs, SANE_Int turn_on, SANE_Int lamp) { SANE_Int rst = ERROR; /* default */ SANE_Byte freevar = FALSE; DBG (DBG_FNC, "+ Lamp_Status_Set(*Regs, turn_on=%i->%s, lamp=%s)\n", turn_on, ((((lamp - 1) | turn_on) & 1) == 1) ? "Yes" : "No", (lamp == FLB_LAMP) ? "FLB_LAMP" : "TMA_LAMP"); if (Regs == NULL) { Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) freevar = TRUE; } if (Regs != NULL) { RTS_ReadRegs (dev->usb_handle, Regs); /* next op depends on chipset */ switch (dev->chipset->model) { case RTS8822BL_03A: /* register 0xe946 has 2 bits and each one referres one lamp 0x40: FLB_LAMP | 0x20 : TMA_LAMP if both were enabled both lamps would be switched on */ data_bitset (&Regs[0x146], 0x20, ((lamp == TMA_LAMP) && (turn_on == TRUE)) ? 1 : 0); /* TMA */ data_bitset (&Regs[0x146], 0x40, ((lamp == FLB_LAMP) && (turn_on == TRUE)) ? 1 : 0); /* FLB */ data_bitset (&Regs[0x155], 0x10, (lamp != FLB_LAMP) ? 1 : 0); break; default: /* the other chipsets only use one bit to indicate when a lamp is switched on or not being bit 0x10 in 0xe955 who decides which lamp is affected */ /* switch on lamp? yes if TMA_LAMP, else whatever turn_on says */ data_bitset (&Regs[0x146], 0x40, ((lamp - 1) | turn_on)); /* what lamp must be switched on? */ if ((Regs[0x146] & 0x40) != 0) data_bitset (&Regs[0x155], 0x10, (lamp != FLB_LAMP) ? 1 : 0); break; } /*42b8cd1 */ /* switch on/off lamp */ /*dev->init_regs[0x0146] = (dev->init_regs[0x146] & 0xbf) | (Regs[0x146] & 0x40); */ dev->init_regs[0x0146] = (dev->init_regs[0x146] & 0x9f) | (Regs[0x146] & 0x60); /*-xx-----*/ /* Which lamp */ dev->init_regs[0x0155] = Regs[0x0155]; Write_Byte (dev->usb_handle, 0xe946, Regs[0x0146]); usleep (1000 * 200); Write_Buffer (dev->usb_handle, 0xe954, &Regs[0x0154], 2); } if (freevar != FALSE) { free (Regs); Regs = NULL; } DBG (DBG_FNC, "- Lamp_Status_Set: %i\n", rst); return rst; } static SANE_Int Get_PAG_Value (SANE_Byte scantype, SANE_Byte color) { SANE_Int rst, iType, iColor; switch (scantype) { case ST_NEG: iType = CALIBNEGATIVEFILM; break; case ST_TA: iType = CALIBTRANSPARENT; break; case ST_NORMAL: iType = CALIBREFLECTIVE; break; default: iType = CALIBREFLECTIVE; break; } switch (color) { case CL_BLUE: iColor = PAGB; break; case CL_GREEN: iColor = PAGG; break; case CL_RED: iColor = PAGR; break; default: iColor = PAGR; break; } rst = get_value (iType, iColor, 1, FITCALIBRATE); DBG (DBG_FNC, "> Get_PAG_Value(scantype=%s, color=%i): %i\n", dbg_scantype (scantype), color, rst); return rst; } static SANE_Byte Lamp_GetGainMode (struct st_device *dev, SANE_Int resolution, SANE_Byte scantype) { SANE_Byte ret; SANE_Int mygain, iValue; switch (scantype) { case ST_TA: ret = 0; iValue = DPIGAINCONTROL_TA600; break; case ST_NEG: ret = 1; iValue = DPIGAINCONTROL_NEG600; break; default: /* Reflective */ ret = 1; iValue = DPIGAINCONTROL600; break; } mygain = get_value (SCAN_PARAM, iValue, ret, usbfile); ret = 0; /* */ if (scantype == ST_NORMAL) { if (dev->chipset->model == RTS8822L_02A) { switch (resolution) { case 100: case 150: case 300: case 600: case 1200: case 2400: case 4800: ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; break; } } else { switch (resolution) { case 100: case 200: case 300: case 600: if (RTS_Debug->usbtype != USB11) ret = (mygain != 0) ? 1 : 0; else ret = (resolution == 100) ? 1 : 0; break; case 1200: case 2400: ret = 0; break; } } } else if (scantype == ST_TA) { switch (resolution) { /*hp3970 */ case 100: case 200: /*common */ case 300: case 600: case 1200: case 2400: /*hp4370 */ case 150: case 4800: ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; break; } } else { /* ST_NEG */ switch (resolution) { case 100: case 200: case 300: case 600: ret = ((RTS_Debug->usbtype != USB11) && (mygain != 0)) ? 1 : 0; break; case 1200: case 2400: case 4800: /*hp4370 */ ret = 0; break; } } DBG (DBG_FNC, "> Lamp_GetGainMode(resolution=%i, scantype=%s): %i\n", resolution, dbg_scantype (scantype), ret); return ret; } static SANE_Int GetOneLineInfo (struct st_device *dev, SANE_Int resolution, SANE_Int * maximus, SANE_Int * minimus, double *average) { SANE_Int rst = ERROR; DBG (DBG_FNC, "+ GetOneLineInfo(resolution=%i, *maximus, *minimus, *average):\n", resolution); /* Check parameters */ if ((maximus != NULL) && (minimus != NULL) && (average != NULL)) { SANE_Byte *Regs, *image; SANE_Int a, gainmode; struct st_gain_offset gain_offset; struct st_scanparams scancfg; Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { /* Copy scanner registers */ memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); /* Setting some registers */ for (a = 0x192; a <= 0x19d; a++) Regs[a] = 0; /* Create calibration table */ for (a = CL_RED; a <= CL_BLUE; a++) { gain_offset.edcg1[a] = 256; gain_offset.edcg2[a] = 0; gain_offset.odcg1[a] = 256; gain_offset.odcg2[a] = 0; gain_offset.vgag1[a] = 4; gain_offset.vgag2[a] = 4; gain_offset.pag[a] = Get_PAG_Value (scan.scantype, a); } RTS_GetScanmode (dev, scantype, 0, resolution); /* Setting scanning params */ memset (&scancfg, 0, sizeof (struct st_scanparams)); scancfg.colormode = CM_COLOR; scancfg.resolution_x = resolution; scancfg.resolution_y = resolution; scancfg.coord.left = 100; scancfg.coord.width = (resolution * 8.5) - 100; scancfg.coord.top = 1; scancfg.coord.height = 1; scancfg.depth = 8; scancfg.shadinglength = resolution * 8.5; scancfg.v157c = scancfg.coord.width * 3; scancfg.bytesperline = scancfg.v157c; /* Reserve buffer for line */ image = (SANE_Byte *) malloc (((scancfg.coord.width * 0x21) * 3) * sizeof (SANE_Byte)); if (image != NULL) { gainmode = Lamp_GetGainMode (dev, resolution & 0xffff, scan.scantype); if (RTS_GetImage (dev, Regs, &scancfg, &gain_offset, image, 0, OP_STATIC_HEAD, gainmode) != ERROR) { /* Read all image to take max min and average colours */ SANE_Byte *pointer1 = image; SANE_Byte *pointer2; SANE_Byte *pointer3; SANE_Int cmin[3]; /* min values */ SANE_Int cmax[3]; /* max values */ double cave[3]; /* average values */ SANE_Int mysize; if (scancfg.colormode != CM_GRAY) { pointer2 = image; pointer3 = image; } else { pointer2 = image + 1; pointer3 = image + 2; } for (a = CL_RED; a <= CL_BLUE; a++) { cmin[a] = 255; cmax[a] = 0; cave[a] = 0; } if (scancfg.coord.height > 0) { SANE_Int y, x; SANE_Byte *mypointer; SANE_Byte color; SANE_Int desp[3]; desp[CL_RED] = pointer1 - pointer3; desp[CL_GREEN] = pointer2 - pointer3; desp[CL_BLUE] = 0; for (y = 0; y < scancfg.coord.height; y++) { if (scancfg.coord.width > 0) { mypointer = pointer3; for (x = 0; x < scancfg.coord.width; x++) { for (a = CL_RED; a <= CL_BLUE; a++) { /* Take colour values */ color = *(mypointer + desp[a]); /* Take max values for each color */ cmax[a] = max (cmax[a], color); /* Take min values for each color */ cmin[a] = min (cmin[a], color); /* Average */ cave[a] += color; } mypointer += 3; } } /* point to the pixel that is below */ pointer1 += scancfg.coord.width * 3; pointer2 += scancfg.coord.width * 3; pointer3 += scancfg.coord.width * 3; } } mysize = scancfg.coord.height * scancfg.coord.width; if (mysize < 1) mysize = 1; for (a = CL_RED; a <= CL_BLUE; a++) { maximus[a] = cmax[a]; minimus[a] = cmin[a]; average[a] = cave[a] / mysize; } DBG (DBG_FNC, " -> GetOneLineInfo: max r=%3i g=%3i b=%3i\n", maximus[CL_RED], maximus[CL_GREEN], maximus[CL_BLUE]); DBG (DBG_FNC, " -> min r=%3i g=%3i b=%3i\n", minimus[CL_RED], minimus[CL_GREEN], minimus[CL_BLUE]); DBG (DBG_FNC, " -> avg r=%3.0f g=%3.0f b=%3.0f\n", average[CL_RED], average[CL_GREEN], average[CL_BLUE]); rst = OK; } free (image); } free (Regs); } } DBG (DBG_FNC, "- GetOneLineInfo: %i\n", rst); return OK; } static SANE_Int Lamp_PWM_CheckStable (struct st_device *dev, SANE_Int resolution, SANE_Int lamp) { struct st_checkstable check; SANE_Int rst; DBG (DBG_FNC, "+ Lamp_PWM_CheckStable(resolution=%i, lamp=%i):\n", resolution, lamp); rst = cfg_checkstable_get (lamp, &check); if (rst == OK) { SANE_Int maximus[3] = { 0 }; SANE_Int minimus[3] = { 0 }; double average[3] = { 0 }; SANE_Int maxbigger; SANE_Int last_colour = 0; double diff = check.diff * 0.01; long tottime = GetTickCount () + check.tottime; while (GetTickCount () <= tottime) { rst = GetOneLineInfo (dev, resolution, maximus, minimus, average); if (rst == OK) { /* Takes maximal colour value */ maxbigger = max (maximus[CL_GREEN], max (maximus[CL_BLUE], maximus[CL_RED])); /*breaks when colour intensity increases 'diff' or lower */ if (abs (maxbigger - last_colour) < diff) { DBG (DBG_FNC, " -> PWM is ready\n"); break; } last_colour = maxbigger; } usleep (1000 * check.interval); } } DBG (DBG_FNC, "- Lamp_PWM_CheckStable: %i\n", rst); return OK; } static SANE_Byte Refs_Counter_Load (struct st_device *dev) { SANE_Byte data = 15; DBG (DBG_FNC, "+ Refs_Counter_Load:\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) if (RTS_EEPROM_ReadByte (dev->usb_handle, 0x78, &data) != OK) data = 15; DBG (DBG_FNC, "- Refs_Counter_Load: %i\n", _B0 (data)); return data; } static SANE_Int Refs_Counter_Save (struct st_device *dev, SANE_Byte data) { SANE_Int rst = OK; DBG (DBG_FNC, "+ Refs_Counter_Save(data=%i):\n", data); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { if (data > 15) data = 15; rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x78, data); } DBG (DBG_FNC, "- Refs_Counter_Save: %i\n", rst); return rst; } static SANE_Int Refs_Counter_Inc (struct st_device *dev) { SANE_Byte data; DBG (DBG_FNC, "+ Refs_Counter_Inc:\n"); data = Refs_Counter_Load (dev) + 1; if (data >= 15) data = 0; Refs_Counter_Save (dev, data); DBG (DBG_FNC, "- Refs_Counter_Inc() : Count=%i\n", data); return OK; } static SANE_Int Load_StripCoords (SANE_Int scantype, SANE_Int * ypos, SANE_Int * xpos) { SANE_Int iType; switch (scantype) { case 3: iType = CALIBNEGATIVEFILM; break; case 2: iType = CALIBTRANSPARENT; break; default: iType = CALIBREFLECTIVE; break; } *xpos = get_value (iType, WSTRIPXPOS, 0, FITCALIBRATE); *ypos = get_value (iType, WSTRIPYPOS, 0, FITCALIBRATE); DBG (DBG_FNC, "> Load_StripCoords(scantype=%s): ypos=%i, xpos=%i\n", dbg_scantype (scantype), *ypos, *xpos); return OK; } static SANE_Int Head_Relocate (struct st_device *dev, SANE_Int speed, SANE_Int direction, SANE_Int ypos) { SANE_Int rst; SANE_Byte *Regs; DBG (DBG_FNC, "+ Head_Relocate(speed=%i, direction=%i, ypos=%i):\n", speed, direction, ypos); rst = ERROR; Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { struct st_motormove mymotor; struct st_motorpos mtrpos; bzero (&mymotor, sizeof (struct st_motormove)); memcpy (Regs, dev->init_regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); if (speed < dev->motormove_count) memcpy (&mymotor, dev->motormove[speed], sizeof (struct st_motormove)); /*83fe */ mtrpos.coord_y = ypos; mtrpos.options = MTR_ENABLED | ((direction == MTR_BACKWARD) ? MTR_BACKWARD : MTR_FORWARD); mtrpos.v12e448 = 0; mtrpos.v12e44c = 1; Motor_Move (dev, Regs, &mymotor, &mtrpos); /* waits 15 seconds */ RTS_WaitScanEnd (dev, 15000); free (Regs); rst = OK; } DBG (DBG_FNC, "- Head_Relocate: %i\n", rst); return rst; } static SANE_Int Calib_CreateFixedBuffers () { SANE_Byte channel; SANE_Int ret; DBG (DBG_FNC, "> Calib_CreateFixedBuffers()\n"); ret = OK; channel = 0; while ((channel < 3) && (ret == OK)) { /* First table */ if (fixed_black_shading[channel] == NULL) fixed_black_shading[channel] = (USHORT *) malloc (0x7f8 * sizeof (USHORT)); if (fixed_black_shading[channel] != NULL) bzero (fixed_black_shading[channel], 0x7f8 * sizeof (USHORT)); else ret = ERROR; /* Second table */ if (fixed_white_shading[channel] == NULL) fixed_white_shading[channel] = (USHORT *) malloc (0x7f8 * sizeof (USHORT)); if (fixed_white_shading[channel] != NULL) bzero (fixed_white_shading[channel], 0x7f8 * sizeof (USHORT)); else ret = ERROR; channel++; } return ret; } static SANE_Int Calib_CreateBuffers (struct st_device *dev, struct st_calibration *buffer, SANE_Int my14b4) { SANE_Int ebp, ret, channel; ret = ERROR; dev = dev; buffer->shadinglength = scan.coord.width; ebp = 0x14; if (my14b4 != 0) { /* 673d */ if (Calib_CreateFixedBuffers () == OK) { for (channel = 0; channel < 3; channel++) { buffer->white_shading[channel] = fixed_white_shading[channel]; buffer->black_shading[channel] = fixed_black_shading[channel]; } ret = OK; } } else { /* 677f */ SANE_Int pos; channel = 0; while ((channel < 3) && (ret == OK)) { buffer->black_shading[channel] = (USHORT *) malloc (ebp + (buffer->shadinglength * sizeof (USHORT))); buffer->white_shading[channel] = (USHORT *) malloc (ebp + (buffer->shadinglength * sizeof (USHORT))); if ((buffer->black_shading[channel] != NULL) && (buffer->white_shading[channel] != NULL)) { for (pos = 0; pos < buffer->shadinglength; pos++) { buffer->black_shading[channel][pos] = 0x00; buffer->white_shading[channel][pos] = 0x4000; } ret = OK; } else Calib_FreeBuffers (buffer); channel++; } } DBG (DBG_FNC, "> Calib_CreateBuffers: *buffer, my14b4=%i): %i\n", my14b4, ret); return ret; } static void Calib_FreeBuffers (struct st_calibration *caltables) { DBG (DBG_FNC, "> Calib_FreeBuffers(*caltables)\n"); if (caltables != NULL) { SANE_Int channel; for (channel = 0; channel < 3; channel++) { if (caltables->black_shading[channel] != NULL) { free (caltables->black_shading[channel]); caltables->black_shading[channel] = NULL; } if (caltables->white_shading[channel] != NULL) { free (caltables->white_shading[channel]); caltables->white_shading[channel] = NULL; } } } } static SANE_Int Calib_LoadConfig (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int scantype, SANE_Int resolution, SANE_Int bitmode) { SANE_Int section, a; struct st_autoref refcfg; DBG (DBG_FNC, "> Calib_LoadConfig(*calibcfg, scantype=%s, resolution=%i, bitmode=%i)\n", dbg_scantype (scantype), resolution, bitmode); switch (scantype) { case ST_NEG: section = CALIBNEGATIVEFILM; break; case ST_TA: section = CALIBTRANSPARENT; break; default: section = CALIBREFLECTIVE; break; } calibcfg->WStripXPos = get_value (section, WSTRIPXPOS, 0, FITCALIBRATE); calibcfg->WStripYPos = get_value (section, WSTRIPYPOS, 0, FITCALIBRATE); calibcfg->BStripXPos = get_value (section, BSTRIPXPOS, 0, FITCALIBRATE); calibcfg->BStripYPos = get_value (section, WSTRIPYPOS, 0, FITCALIBRATE); /* get calibration wrefs */ cfg_wrefs_get (dev->sensorcfg->type, bitmode, resolution, scantype, &calibcfg->WRef[CL_RED], &calibcfg->WRef[CL_GREEN], &calibcfg->WRef[CL_BLUE]); /* 4913 */ for (a = CL_RED; a <= CL_BLUE; a++) { WRef[a] = _B0 (calibcfg->WRef[a]); calibcfg->BRef[a] = get_value (section, BREFR + a, 10, FITCALIBRATE); calibcfg->OffsetEven1[a] = get_value (section, OFFSETEVEN1R + a, 256, FITCALIBRATE); calibcfg->OffsetEven2[a] = get_value (section, OFFSETEVEN2R + a, 0, FITCALIBRATE); calibcfg->OffsetOdd1[a] = get_value (section, OFFSETODD1R + a, 256, FITCALIBRATE); calibcfg->OffsetOdd2[a] = get_value (section, OFFSETODD2R + a, 0, FITCALIBRATE); } calibcfg->RefBitDepth = _B0 (get_value (section, REFBITDEPTH, 8, FITCALIBRATE)); calibcfg->CalibOffset10n = _B0 (get_value (section, CALIBOFFSET10N, 3, FITCALIBRATE)); calibcfg->CalibOffset20n = _B0 (get_value (section, CALIBOFFSET20N, 0, FITCALIBRATE)); calibcfg->OffsetHeight = get_value (section, OFFSETHEIGHT, 10, FITCALIBRATE); /* 4ae9 */ /* get left coordinate and length to calibrate offset */ cfg_offset_get (dev->sensorcfg->type, resolution, scantype, &calibcfg->OffsetPixelStart, &calibcfg->OffsetNPixel); /*4c49 */ calibcfg->OffsetNSigma = get_value (section, OFFSETNSIGMA, 2, FITCALIBRATE); calibcfg->OffsetTargetMax = get_value (section, OFFSETTARGETMAX, 0x32, FITCALIBRATE) * 0.01; calibcfg->OffsetTargetMin = get_value (section, OFFSETTARGETMIN, 2, FITCALIBRATE) * 0.01; calibcfg->OffsetBoundaryRatio1 = get_value (section, OFFSETBOUNDARYRATIO1, 0x64, FITCALIBRATE) * 0.01; calibcfg->OffsetBoundaryRatio2 = get_value (section, OFFSETBOUNDARYRATIO2, 0x64, FITCALIBRATE) * 0.01; calibcfg->OffsetAvgRatio1 = get_value (section, OFFSETAVGRATIO1, 0x64, FITCALIBRATE) * 0.01; calibcfg->OffsetAvgRatio2 = get_value (section, OFFSETAVGRATIO2, 0x64, FITCALIBRATE) * 0.01; calibcfg->AdcOffQuickWay = get_value (section, ADCOFFQUICKWAY, 1, FITCALIBRATE); calibcfg->AdcOffPredictStart = get_value (section, ADCOFFPREDICTSTART, 0xc8, FITCALIBRATE); calibcfg->AdcOffPredictEnd = get_value (section, ADCOFFPREDICTEND, 0x1f4, FITCALIBRATE); calibcfg->AdcOffEvenOdd = get_value (section, ADCOFFEVENODD, 1, FITCALIBRATE); calibcfg->OffsetTuneStep1 = _B0 (get_value (section, OFFSETTUNESTEP1, 1, FITCALIBRATE)); calibcfg->OffsetTuneStep2 = _B0 (get_value (section, OFFSETTUNESTEP2, 1, FITCALIBRATE)); calibcfg->CalibGain10n = get_value (section, CALIBGAIN10N, 1, FITCALIBRATE); calibcfg->CalibGain20n = get_value (section, CALIBGAIN20N, 0, FITCALIBRATE); calibcfg->CalibPAGOn = get_value (section, CALIBPAGON, 0, FITCALIBRATE); for (a = CL_RED; a <= CL_BLUE; a++) { calibcfg->OffsetAvgTarget[a] = _B0 (get_value (section, OFFSETAVGTARGETR + a, 0x0d, FITCALIBRATE)); calibcfg->PAG[a] = get_value (section, PAGR + a, 3, FITCALIBRATE); calibcfg->Gain1[a] = get_value (section, GAIN1R + a, 4, FITCALIBRATE); calibcfg->Gain2[a] = get_value (section, GAIN2R + a, 4, FITCALIBRATE); calibcfg->WShadingPreDiff[a] = get_value (section, WSHADINGPREDIFFR + a, -1, FITCALIBRATE); calibcfg->BShadingPreDiff[a] = get_value (section, BSHADINGPREDIFFR + a, 2, FITCALIBRATE); } calibcfg->GainHeight = get_value (section, GAINHEIGHT, 0x1e, FITCALIBRATE); calibcfg->GainTargetFactor = get_value (section, GAINTARGETFACTOR, 0x5a, FITCALIBRATE) * 0.01; calibcfg->TotShading = get_value (section, TOTSHADING, 0, FITCALIBRATE); /* White shading */ calibcfg->WShadingOn = get_value (section, WSHADINGON, 3, FITCALIBRATE); calibcfg->WShadingHeight = get_value (section, WSHADINGHEIGHT, 0x18, FITCALIBRATE); /* Black shading */ calibcfg->BShadingOn = get_value (section, BSHADINGON, 2, FITCALIBRATE); calibcfg->BShadingHeight = get_value (section, BSHADINGHEIGHT, 0x1e, FITCALIBRATE); calibcfg->BShadingDefCutOff = get_value (section, BSHADINGDEFCUTOFF, 0, FITCALIBRATE); refcfg.extern_boundary = 0; cfg_autoref_get (&refcfg); calibcfg->ExternBoundary = refcfg.extern_boundary * 0.01; calibcfg->EffectivePixel = cfg_effectivepixel_get (dev->sensorcfg->type, resolution); return OK; } static SANE_Int Calib_AdcGain (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int arg2, SANE_Int gaincontrol) { /* 0606F8E0 04F60738 |Arg1 = 04F60738 0606F8E4 0606F90C |Arg2 = 0606F90C calibcfg 0606F8E8 00000001 |Arg3 = 00000001 arg2 0606F8EC 00000001 \Arg4 = 00000001 gaincontrol */ SANE_Int rst = ERROR; SANE_Byte *myRegs; /*f1c0 */ DBG (DBG_FNC, "+ Calib_AdcGain(*calibcfg, arg2=%i, gaincontrol=%i)\n", arg2, gaincontrol); myRegs = (SANE_Byte *) malloc (sizeof (SANE_Byte) * RT_BUFFER_LEN); if (myRegs != NULL) { struct st_scanparams *scancfg; /*f17c */ SANE_Int bytes_per_line, bytes_to_next_colour, bytes_per_pixel; /* get register values to perform adc gain calibration */ memcpy (myRegs, &calibdata->Regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); scancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); if (scancfg != NULL) { SANE_Byte *image, *pgain, *pcalgain; /* get proper scan configuration */ memcpy (scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); /* set gain control type */ Lamp_SetGainMode (dev, myRegs, scancfg->resolution_x, gaincontrol); /* 8-bit depth */ scancfg->depth = 8; /* set coordinates */ if ((scan.scantype > 0) && (scan.scantype < 4)) scancfg->coord.left += scan.ser; if ((scancfg->coord.width & 1) == 0) scancfg->coord.width++; scancfg->coord.top = 1; scancfg->coord.height = calibcfg->OffsetHeight; /* three more values to read image data after getting image from scanner */ switch (scancfg->colormode) { case CM_GRAY: case CM_LINEART: bytes_to_next_colour = 0; bytes_per_pixel = 1; bytes_per_line = scancfg->coord.width; break; default: /* CM_COLOR */ /* c027 */ bytes_to_next_colour = 1; bytes_per_line = scancfg->coord.width * 3; if (scancfg->samplerate == LINE_RATE) { bytes_to_next_colour = scancfg->coord.width; bytes_per_pixel = 1; } else bytes_per_pixel = 3; break; } /*7fc7 */ scancfg->v157c = bytes_per_line; scancfg->bytesperline = bytes_per_line; /* select type of gain parameters to set */ if (arg2 != 0) { pgain = calibdata->gain_offset.vgag1; pcalgain = calibcfg->Gain1; } else { /*7ff2 */ pgain = calibdata->gain_offset.vgag2; pcalgain = calibcfg->Gain2; } /*8002 */ /* Allocate space for image | size = 132912 */ image = (SANE_Byte *) malloc (sizeof (SANE_Byte) * ((scancfg->coord.height + 16) * bytes_per_line)); if (image != NULL) { /* Lets read image */ if (RTS_GetImage (dev, myRegs, scancfg, &calibdata->gain_offset, image, NULL, OP_STATIC_HEAD, gaincontrol) == OK) { SANE_Int a; SANE_Int vmin[3], vmax[3]; double dval[3] = { 0.0 }; /*f1a8 f1b0 f1b8 */ SANE_Byte *pimage = image; /* initialize values */ for (a = CL_RED; a <= CL_BLUE; a++) { calibcfg->unk1[a] = 0; calibcfg->unk2[a] = 0xff; vmin[a] = 0xff; vmax[a] = 0; } /* process image data */ if (scancfg->coord.width > 0) { /*8104 */ SANE_Int pos, myheight /*f164 */ ; SANE_Int chn_sum[3]; for (pos = scancfg->coord.width; pos > 0; pos--) { chn_sum[CL_RED] = chn_sum[CL_GREEN] = chn_sum[CL_BLUE] = 0; if (scancfg->coord.height > 0) for (myheight = 0; myheight < scancfg->coord.height; myheight++) for (a = CL_RED; a <= CL_BLUE; a++) chn_sum[a] += *(pimage + (bytes_per_line * myheight) + (bytes_to_next_colour * a)); /*816e */ for (a = CL_RED; a <= CL_BLUE; a++) { vmin[a] = min (vmin[a], chn_sum[a] / scancfg->coord.height); vmax[a] = max (vmax[a], chn_sum[a] / scancfg->coord.height); calibcfg->unk1[a] = max (calibcfg->unk1[a], vmax[a]); calibcfg->unk2[a] = min (calibcfg->unk1[a], vmin[a]); dval[a] += vmax[a] & 0xffff; } pimage += bytes_per_pixel; } } /*82b0 */ dval[CL_RED] /= scancfg->coord.width; dval[CL_GREEN] /= scancfg->coord.width; dval[CL_BLUE] /= scancfg->coord.width; DBG (DBG_FNC, " -> adcgain (av/l): r=%f, g=%f, b=%f\n", dval[CL_RED], dval[CL_GREEN], dval[CL_BLUE]); DBG (DBG_FNC, " -> (max ): R=%i, G=%i, B=%i\n", calibcfg->unk1[CL_RED], calibcfg->unk1[CL_GREEN], calibcfg->unk1[CL_BLUE]); DBG (DBG_FNC, " -> (min ): r=%i, g=%i, b=%i\n", calibcfg->unk2[CL_RED], calibcfg->unk2[CL_GREEN], calibcfg->unk2[CL_BLUE]); if (scancfg->colormode == CM_COLOR) { /*8353 */ double dvalue; SANE_Int ival; for (a = CL_RED; a <= CL_BLUE; a++) { dvalue = ((((calibcfg->WRef[a] * (1 << scancfg->depth)) * calibcfg->GainTargetFactor) * 0.00390625) / dval[a]) * ((44 - pgain[a]) / 40); if (dvalue > 0.9090909090909091) { /*83d7 */ dvalue = min (44 - (40 / dvalue), 31); ival = dvalue; pgain[a] = _B0 (ival); pcalgain[a] = _B0 (ival); } else { pgain[a] = 0; pcalgain[a] = 0; } } } else { /*843c */ /*falta codigo */ double dvalue; SANE_Int ival; dvalue = ((44 - pgain[CL_RED]) / 40) * ((((1 << scancfg->depth) * calibcfg->WRef[scancfg-> channel]) * 0.9) * 0.00390625) / 17.08509389671362; for (a = CL_RED; a <= CL_BLUE; a++) { if (dvalue > 0.9090909090909091) { dvalue = min (44 - (40 / dvalue), 31); ival = dvalue; pgain[a] = _B0 (ival); pcalgain[a] = _B0 (ival); } else { /*84e3 */ pgain[a] = 0; pcalgain[a] = 0; } } } /*84fa */ /* Save buffer */ if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("adcgain.tiff", scancfg->coord.width, scancfg->coord.height, scancfg->depth, CM_COLOR, scancfg->resolution_x, scancfg->resolution_y, image, (scancfg->coord.height + 16) * bytes_per_line); } /* check if peak values are above offset average target + 5 */ for (a = CL_RED; a <= CL_BLUE; a++) if (calibcfg->unk1[a] >= calibcfg->OffsetAvgTarget[a] + 5) { rst = OK; break; } } free (image); } free (scancfg); } free (myRegs); } /* v14b8 = (rst == OK)? 0: 1; */ /* show */ dbg_calibtable (&calibdata->gain_offset); DBG (DBG_FNC, "- Calib_AdcGain: %i\n", rst); return rst; } static SANE_Int GainOffset_Save (struct st_device *dev, SANE_Int * offset, SANE_Byte * gain) { SANE_Int rst = OK; DBG (DBG_FNC, "+ GainOffset_Save(*offset, *gain):\n"); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { if ((offset != NULL) && (gain != NULL)) { SANE_Int a, crc, value; crc = 0x5B; for (a = CL_RED; a <= CL_BLUE; a++) { value = (*gain << 9) | *offset; crc = _B0 (abs (crc - _B0 (value))); rst = RTS_EEPROM_WriteWord (dev->usb_handle, 0x70 + (a * 2), value); } if (rst == OK) rst = RTS_EEPROM_WriteByte (dev->usb_handle, 0x76, crc); } else rst = ERROR; } DBG (DBG_FNC, "- GainOffset_Save: %i\n", rst); return rst; } static SANE_Int Calib_PAGain (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int gainmode) { SANE_Byte *Regs; struct st_scanparams *scancfg; SANE_Int channel_size; SANE_Int bytes_to_next_colour = 0; SANE_Int bytes_per_pixel = 0; SANE_Int length = 0; SANE_Byte *image; double rst; SANE_Int ret = ERROR; DBG (DBG_FNC, "+ Calib_PAGain(*calibcfg, gainmode=%i)\n", gainmode); Regs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); if (Regs != NULL) { scancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); if (scancfg != NULL) { memcpy (Regs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); if (scan.scantype == ST_NORMAL) { /* bfa5 */ scancfg->coord.left = scan.ser; scancfg->coord.width = (scancfg->sensorresolution * 17) / 2; } else { scancfg->coord.left = scan.ser + v0750; scancfg->coord.width = (scancfg->sensorresolution * 3) / 2; } /* bfca */ if ((scancfg->coord.width & 1) == 1) scancfg->coord.width++; scancfg->coord.top = 1; scancfg->coord.height = calibcfg->OffsetHeight; channel_size = (scancfg->depth > 8) ? 2 : 1; switch (scancfg->colormode) { case CM_GRAY: case CM_LINEART: bytes_to_next_colour = 0; bytes_per_pixel = 1; length = channel_size * scancfg->coord.width; break; default: /* CM_COLOR */ /* c027 */ bytes_to_next_colour = 1; length = (channel_size * scancfg->coord.width) * 3; if (scancfg->samplerate == LINE_RATE) { bytes_to_next_colour = scancfg->coord.width; bytes_per_pixel = 1; } else bytes_per_pixel = 3; break; } /* c070 */ scancfg->v157c = length; image = (SANE_Byte *) malloc ((scancfg->coord.height * length) * sizeof (SANE_Byte)); if (image != NULL) { ret = RTS_GetImage (dev, Regs, scancfg, &calibdata->gain_offset, image, 0, OP_STATIC_HEAD, gainmode); if (ret == OK) { /* 429c105 */ SANE_Int a; SANE_Byte *ptr[3]; SANE_Int vmin[3] = { 255, 255, 255 }; /* f16c|f16e|f170 */ SANE_Int vmax[3] = { 0, 0, 0 }; /* f164|f166|f168 */ SANE_Int total[3]; ptr[CL_RED] = image; ptr[CL_GREEN] = image + bytes_to_next_colour; ptr[CL_BLUE] = image + (bytes_to_next_colour * 2); if (scancfg->coord.width > 0) { SANE_Int pos, b; for (pos = 0; pos < scancfg->coord.width; pos++) { total[CL_BLUE] = 0; total[CL_GREEN] = 0; total[CL_RED] = 0; for (a = 0; a < scancfg->coord.height; a++) { for (b = CL_RED; b <= CL_BLUE; b++) total[b] += *(ptr[b] + ((scancfg->coord.height - a) * length)); } /* c1a5 */ for (a = CL_RED; a <= CL_BLUE; a++) { total[a] /= scancfg->coord.height; vmin[a] = min (vmin[a], total[a]); vmax[a] = max (vmax[a], total[a]); ptr[a] += bytes_per_pixel; } } } /* 429c234 */ for (a = CL_RED; a <= CL_BLUE; a++) { rst = (calibcfg->WRef[a] * calibcfg->GainTargetFactor) / vmax[a]; if (rst <= 1.5) { if (rst <= 1.286) { if (rst <= 1.125) calibdata->gain_offset.pag[a] = 0; else calibdata->gain_offset.pag[a] = 1; } else calibdata->gain_offset.pag[a] = 2; } else calibdata->gain_offset.pag[a] = 3; } } free (image); } free (scancfg); } free (Regs); } DBG (DBG_FNC, "- Calib_PAGain: %i\n", ret); return ret; } static SANE_Int Chipset_ID (struct st_device *dev) { SANE_Int ret; if (Read_Word (dev->usb_handle, 0xfe3c, &ret) == OK) ret = _B0 (ret); else ret = 0; DBG (DBG_FNC, "> Chipset_ID(): %i\n", ret); return ret; } static SANE_Int Chipset_Name (struct st_device *dev, char *name, SANE_Int size) { SANE_Int rst = ERROR; if (name != NULL) { strncpy (name, dev->chipset->name, size); rst = OK; } return rst; } static SANE_Int Refs_Load (struct st_device *dev, SANE_Int * x, SANE_Int * y) { SANE_Int ret = OK; DBG (DBG_FNC, "+ Refs_Load:\n"); *y = *x = 0; /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { SANE_Int data; ret = ERROR; if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6a, &data) == OK) { *x = data; if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6c, &data) == OK) { *y = data; if (RTS_EEPROM_ReadWord (dev->usb_handle, 0x6e, &data) == OK) { if ((_B0 (*y + *x + data)) == 0x5a) ret = OK; } } } } DBG (DBG_FNC, "- Refs_Load(y=%i, x=%i) : %i\n", *y, *x, ret); return ret; } static SANE_Int Refs_Save (struct st_device *dev, SANE_Int left_leading, SANE_Int start_pos) { SANE_Int ret = OK; DBG (DBG_FNC, "+ Refs_Save(left_leading=%i, start_pos=%i)\n", left_leading, start_pos); /* check if chipset supports accessing eeprom */ if ((dev->chipset->capabilities & CAP_EEPROM) != 0) { ret = ERROR; if (RTS_EEPROM_WriteWord (dev->usb_handle, 0x6a, left_leading) == OK) { if (RTS_EEPROM_WriteWord (dev->usb_handle, 0x6c, start_pos) == OK) { SANE_Byte data = _B0 (0x5a - (start_pos + left_leading)); ret = RTS_EEPROM_WriteByte (dev->usb_handle, 0x6e, data); } } } DBG (DBG_FNC, "- Refs_Save: %i\n", ret); return ret; } static SANE_Int Calib_AdcOffsetRT (struct st_device *dev, struct st_calibration_config *calibcfg, SANE_Int value) { /* 05EFF8E4 04F10738 |Arg1 = 04F10738 05EFF8E8 05EFF90C |Arg2 = 05EFF90C calibcfg 05EFF8EC 00000001 \Arg3 = 00000001 value */ SANE_Byte Regs[RT_BUFFER_LEN]; /*f1c4 */ SANE_Int channels_per_dot; /*f108 */ struct st_scanparams scancfg; /*f18c */ SANE_Int *pedcg; /*f114 */ SANE_Int *podcg; /*f118 */ SANE_Int *poffseteven; /*f130 */ SANE_Int *poffsetodd; /*f128 */ SANE_Int channel; SANE_Int avgtarget[3]; /*f1b8 f1bc f1c0 */ SANE_Byte *scanbuffer; /*f0f8 */ SANE_Int scan_options; /*f12c */ SANE_Int highresolution; /*f144 */ double dbValues[3] = { 0, 0, 0 }; /*f148 f14c f150 */ SANE_Int do_loop; /*f0ec */ SANE_Int gainmode; SANE_Byte *ptr; /*f0f4 */ SANE_Byte *mvgag; /*f0e4 *//*f10c */ USHORT wvalues[9]; /*0856 0858 085a 085c 085e 0860 0862 0864 0866 */ SANE_Int imgcount = 0; /* myoffsetnpixel = f120 */ /* desp f0e8 & f140 */ DBG (DBG_FNC, "+ Calib_AdcOffsetRT(*calibcfg, value=%i)\n", value); memcpy (&Regs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); channels_per_dot = (calibdata->scancfg.colormode == CM_COLOR) ? 3 : 1; if (value != 0) { pedcg = &calibdata->gain_offset.edcg1[CL_RED]; podcg = &calibdata->gain_offset.odcg1[CL_RED]; poffseteven = &calibcfg->OffsetEven1[CL_RED]; poffsetodd = &calibcfg->OffsetOdd1[CL_RED]; } else { /*c37c */ pedcg = &calibdata->gain_offset.edcg2[CL_RED]; podcg = &calibdata->gain_offset.odcg2[CL_RED]; poffseteven = &calibcfg->OffsetEven2[CL_RED]; poffsetodd = &calibcfg->OffsetOdd2[CL_RED]; } /*c3a4 */ scancfg.coord.left = calibcfg->OffsetPixelStart; if (channels_per_dot > 0) { for (channel = 0; channel < channels_per_dot; channel++) { avgtarget[channel] = calibcfg->OffsetAvgTarget[channel] << 8; if (avgtarget[channel] == 0) avgtarget[channel] = 0x80; } } /* set image coordinates to scan */ scancfg.coord.width = calibcfg->OffsetNPixel; if ((scancfg.coord.width & 1) == 0) scancfg.coord.width++; scancfg.bytesperline = channels_per_dot * scancfg.coord.width; scancfg.coord.top = 1; scancfg.coord.height = calibcfg->OffsetHeight; scancfg.depth = 8; /* allocate memory to store image */ scanbuffer = (SANE_Byte *) malloc ((scancfg.bytesperline * calibcfg->OffsetHeight) * sizeof (SANE_Byte)); if (scanbuffer == NULL) return ERROR; /*42ac477 */ scan_options = (linedarlampoff == 1) ? 1 : 0x101; highresolution = (scancfg.sensorresolution >= 1200) ? TRUE : FALSE; do { if (channels_per_dot > 0) { for (channel = 0; channel < channels_per_dot; channel++) dbValues[channel] = (40 / (44 - calibdata->gain_offset.vgag2[channel])) * (40 / (44 - calibdata-> gain_offset. vgag1 [channel])); } /*429c50f */ /* Get Image */ gainmode = Lamp_GetGainMode (dev, scancfg.resolution_x, scan.scantype); if (RTS_GetImage (dev, Regs, &scancfg, &calibdata->gain_offset, scanbuffer, 0, scan_options, gainmode) != OK) { free (scanbuffer); return ERROR; } /*429c55f */ /* Save retrieved image */ if (RTS_Debug->SaveCalibFile != FALSE) { char fname[30]; imgcount++; if (snprintf (fname, 30, "adcoffset_rt%i.tiff", imgcount) > 0) dbg_tiff_save (fname, scancfg.coord.width, scancfg.coord.height, scancfg.depth, CM_COLOR, scancfg.resolution_x, scancfg.resolution_y, scanbuffer, scancfg.bytesperline * calibcfg->OffsetHeight); } /*429c5a5 */ do_loop = FALSE; if (highresolution == TRUE) { /* f0fc = f0e4 = channel */ SANE_Int lf104; SANE_Int *mydcg; /*f0f4 */ USHORT *mywvalue; /*ebp */ SANE_Byte is_ready[6]; /*f174 f178 f17c f180 f184 f18c */ SANE_Byte *ptr_ready; /*f11c */ SANE_Int colour; for (channel = 0; channel < 6; channel++) is_ready[channel] = FALSE; if (channels_per_dot <= 0) break; ptr = scanbuffer; mvgag = (SANE_Byte *) calibdata->gain_offset.vgag1; for (channel = 0; channel < channels_per_dot; channel++) { for (lf104 = 0; lf104 < 2; lf104++) { if (lf104 == 0) { mywvalue = &wvalues[channel]; mydcg = pedcg; ptr_ready = &is_ready[0]; } else { /*1645 */ mywvalue = &wvalues[3]; mydcg = podcg; ptr_ready = &is_ready[3]; } /*1658 */ if (ptr_ready[channel] == FALSE) { colour = 0; if (lf104 < calibcfg->OffsetNPixel) { SANE_Int dot; for (dot = 0; dot < (calibcfg->OffsetNPixel - lf104 + 1) / 2; dot++) colour += scanbuffer[mvgag[(lf104 * channels_per_dot)] + (dot * (channels_per_dot * 2))]; } /*c6b2 */ colour = colour << 8; if (colour == 0) { /*c6b9 */ if (mydcg[channel] != 0x1ff) { /*c6d5 */ mydcg[channel] = 0x1ff; do_loop = TRUE; } else ptr_ready[channel] = TRUE; } else { SANE_Int myesi; SANE_Int d; /*c6e8 */ if (*mywvalue == 0) mywvalue += 2; colour /= (calibcfg->OffsetNPixel / 2); if (colour >= avgtarget[channel]) { colour -= avgtarget[channel]; myesi = 0; } else { colour = avgtarget[channel] - colour; myesi = 1; } d = mydcg[channel]; if (d < 0x100) d = 0xff - d; if (myesi != 0) { /*c76e */ if ((d + colour) > 0x1ff) { if (*mvgag > 0) { *mvgag = *mvgag - 1; do_loop = TRUE; } else ptr_ready[channel] = TRUE; /*c7a0 */ } else d += colour; } else { /*c7ad */ if (colour > d) { if (*mvgag > 0) { *mvgag = *mvgag - 1; do_loop = TRUE; } else ptr_ready[channel] = TRUE; } else d -= colour; } /*c7dd */ mydcg[channel] = (d < 0x100) ? 0x100 - d : d; } dbg_calibtable (&calibdata->gain_offset); } } /*c804 */ mvgag++; } } else { /* Low resolution */ SANE_Byte is_ready[3]; SANE_Int colour; /*429c845 */ for (channel = 0; channel < channels_per_dot; channel++) is_ready[channel] = FALSE; if (channels_per_dot <= 0) break; ptr = scanbuffer; mvgag = (SANE_Byte *) calibdata->gain_offset.vgag1; for (channel = 0; channel < channels_per_dot; channel++) { if (is_ready[channel] == FALSE) { colour = 0; if (calibcfg->OffsetNPixel > 0) { SANE_Int dot; /* Take one channel colour values from offsetnpixel pixels */ for (dot = 0; dot < calibcfg->OffsetNPixel; dot++) colour += *(ptr + (dot * channels_per_dot)); } colour <<= 8; if (colour == 0) { if (pedcg[channel] != 0x1ff) { do_loop = TRUE; podcg[channel] = 0x1ff; pedcg[channel] = 0x1ff; } else is_ready[channel] = TRUE; } else { /*c8f7 */ SANE_Int myesi; SANE_Int op1, op2, op3; /* Get colour average */ colour /= calibcfg->OffsetNPixel; /* get absolute difference with avgtarget */ myesi = (colour > avgtarget[channel]) ? 0 : 1; colour = abs (avgtarget[channel] - colour); if (scancfg.resolution_x > 600) { /*c923 */ if (wvalues[channel + 3] == 0) wvalues[channel + 3]++; if (wvalues[channel] == 0) wvalues[channel]++; op3 = max (wvalues[channel], wvalues[channel + 3]); } else { if (wvalues[channel + 6] == 0) wvalues[channel + 6]++; op3 = wvalues[channel + 6]; } /*c9d3 */ op1 = (SANE_Int) (colour / (dbValues[channel] * op3)); op2 = (pedcg[channel] < 0x100) ? pedcg[channel] - 0xff : pedcg[channel]; if (myesi != 0) { /*c9f5 */ if (((op2 + op1) & 0xffff) > 0x1ff) { if (*mvgag != 0) { do_loop = TRUE; *mvgag = *mvgag - 1; } else is_ready[channel] = TRUE; } else op2 += op1; } else { /*ca31 */ if (op1 > op2) { if (*mvgag > 0) { do_loop = TRUE; *mvgag = *mvgag - 1; } else is_ready[channel] = TRUE; } else op2 -= op1; } /*ca54 */ if (op2 < 0x100) op2 = 0x100 - op2; pedcg[channel] = op2; podcg[channel] = op2; } } /*ca6f */ ptr++; mvgag++; dbg_calibtable (&calibdata->gain_offset); } } } while (do_loop != FALSE); /*429cad1 */ for (channel = 0; channel < 3; channel++) { poffseteven[channel] = (pedcg[channel] < 0x100) ? 0xff - pedcg[channel] : pedcg[channel]; poffsetodd[channel] = (podcg[channel] < 0x100) ? 0xff - podcg[channel] : podcg[channel]; } free (scanbuffer); return OK; } static void Calib_LoadCut (struct st_device *dev, struct st_scanparams *scancfg, SANE_Int scantype, struct st_calibration_config *calibcfg) { double mylong; /*ee78 */ double mylong2; /**/ SANE_Int channel[3]; SANE_Int a; cfg_shading_cut_get (dev->sensorcfg->type, scancfg->depth, scancfg->resolution_x, scantype, &channel[0], &channel[1], &channel[2]); mylong = 1 << scancfg->depth; for (a = CL_RED; a <= CL_BLUE; a++) { mylong2 = channel[a]; calibcfg->ShadingCut[a] = (mylong * mylong2) * 0.000390625; } } static SANE_Int Calib_BWShading (struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode) { /* 0603F8E4 0603F90C |Arg1 = 0603F90C calibcfg 0603F8E8 0603FAAC |Arg2 = 0603FAAC myCalib 0603F8EC 00000001 \Arg3 = 00000001 gainmode */ /*falta codigo */ /*silence gcc */ calibcfg = calibcfg; myCalib = myCalib; gainmode = gainmode; return OK; } static SANE_Int Calib_WhiteShading_3 (struct st_device *dev, struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode) { /* 05EDF8E0 04F00738 |Arg1 = 04F00738 05EDF8E4 05EDF90C |Arg2 = 05EDF90C calibcfg 05EDF8E8 05EDFAAC |Arg3 = 05EDFAAC myCalib 05EDF8EC 00000001 \Arg4 = 00000001 gainmode */ SANE_Byte *myRegs; /*f1bc */ struct st_scanparams scancfg; /*f170 */ SANE_Int myWidth; /*f14c */ SANE_Int lf168, bytes_per_pixel; SANE_Int bytes_per_line; /**/ SANE_Int a; double lf1a4[3]; SANE_Int otherheight; /*f150 */ SANE_Int otherheight2; SANE_Int lf12c; SANE_Int lf130; double *buffer1; /*f138 */ double *buffer2; /*f144 */ SANE_Byte *scanbuffer; /*f164 */ SANE_Byte *ptr; /*f148 */ SANE_Int position; /*f140 */ SANE_Int lf13c, myHeight; SANE_Int myESI, myEDI; SANE_Int channel; /*f134 */ double myst; double sumatorio; SANE_Int rst; DBG (DBG_FNC, "> Calib_WhiteShading3(*calibcfg, *myCalib, gainmode=%i)\n", gainmode); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); Lamp_SetGainMode (dev, myRegs, scancfg.resolution_x, gainmode); rst = OK; scancfg.resolution_y = 200; switch (scan.scantype) { case ST_NORMAL: /*a184 */ scancfg.coord.left += scan.ser; scancfg.coord.width &= 0xffff; break; case ST_TA: case ST_NEG: scancfg.coord.left += scan.ser; break; } /*a11b */ if ((scancfg.coord.width & 1) != 0) scancfg.coord.width++; scancfg.coord.top = 1; scancfg.coord.height = calibcfg->WShadingHeight; switch (scancfg.colormode) { case CM_GRAY: case CM_LINEART: myWidth = scancfg.coord.width; lf168 = 0; bytes_per_line = ((scancfg.depth + 7) / 8) * myWidth; bytes_per_pixel = 1; break; default: /* CM_COLOR */ myWidth = scancfg.coord.width * 3; bytes_per_line = ((scancfg.depth + 7) / 8) * myWidth; lf168 = (scancfg.samplerate == LINE_RATE) ? scancfg.coord.width : 1; bytes_per_pixel = (scancfg.samplerate == PIXEL_RATE) ? 3 : 1; break; } /*a1e8 */ scancfg.v157c = bytes_per_line; scancfg.bytesperline = bytes_per_line; for (a = 0; a < 3; a++) lf1a4[a] = (calibcfg->WRef[a] * (1 << scancfg.depth)) >> 8; /* debug this code because if it's correct, lf130 and lf12c are always 2 */ otherheight = calibcfg->WShadingHeight - 3; otherheight -= (otherheight - 4); otherheight2 = otherheight / 2; otherheight -= otherheight2; lf130 = otherheight2; lf12c = otherheight; buffer1 = (double *) malloc (otherheight * sizeof (double)); if (buffer1 == NULL) return ERROR; buffer2 = (double *) malloc (otherheight * sizeof (double)); if (buffer2 == NULL) { free (buffer1); return ERROR; } scanbuffer = (SANE_Byte *) malloc (((scancfg.coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (scanbuffer == NULL) { free (buffer1); free (buffer2); return ERROR; } /* Scan image */ myCalib->shading_enabled = FALSE; rst = RTS_GetImage (dev, myRegs, &scancfg, &calibdata->gain_offset, scanbuffer, myCalib, 0x20000080, gainmode); for (a = 0; a < 3; a++) myCalib->WRef[a] *= ((1 << scancfg.depth) >> 8); if (rst == ERROR) { free (buffer1); free (buffer2); free (scanbuffer); return ERROR; } if (scancfg.depth > 8) { /*a6d9 */ position = 0; sumatorio = 0; if (myWidth > 0) { do { switch (scancfg.colormode) { case CM_GRAY: case CM_LINEART: channel = 0; lf13c = position; break; default: /*CM_COLOR */ if (scancfg.samplerate == PIXEL_RATE) { /* pixel rate */ channel = position % bytes_per_pixel; lf13c = position / bytes_per_pixel; } else { /* line rate */ channel = position / lf168; lf13c = position % lf168; } break; } /*a743 */ if (lf130 > 0) bzero (buffer1, lf130 * sizeof (double)); /*a761 */ if (lf12c > 0) { for (a = 0; a < lf12c; a++) buffer2[a] = (1 << scancfg.depth) - 1.0; } /*a78f */ myESI = 0; myEDI = 0; ptr = scanbuffer + (position * 2); myHeight = 0; if (otherheight > 0) { do { myst = 0; for (a = 0; a < 4; a++) myst += data_lsb_get (ptr + (a * (myWidth * 2)), 2); myEDI = 0; myst = myst * 0.25; if (myHeight < (otherheight - 4)) { if (myst < buffer2[myESI]) { buffer2[myESI] = myst; if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] < buffer2[a]) myESI = a; } } /*a820 */ if (myst >= buffer1[myEDI]) { buffer1[myEDI] = myst; if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] >= buffer1[a]) myEDI = a; } } sumatorio += myst; } else { /*a853 */ if (myHeight == (otherheight - 4)) { if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] >= buffer2[a]) myESI = a; } if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] < buffer1[a]) myEDI = a; } } /*a895 */ if (myst >= buffer2[myESI]) { /*a89c */ sumatorio -= buffer2[myESI]; sumatorio += myst; buffer2[myESI] = myst; if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] >= buffer2[a]) myESI = a; } } else { if (myst < buffer1[myEDI]) { sumatorio -= buffer1[myEDI]; sumatorio += myst; buffer1[myEDI] = myst; if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] < buffer1[a]) myEDI = a; } } } } /*a901 */ ptr += (myWidth * 2); myHeight++; } while (myHeight < otherheight); } /*a924 */ scancfg.ser = 0; scancfg.startpos = otherheight - 4; sumatorio = sumatorio / scancfg.startpos; if (myCalib->shading_enabled != FALSE) { /*a94a */ myCalib->white_shading[channel][lf13c] = (unsigned short) sumatorio; } else { /*a967 */ if ((scancfg.colormode != CM_GRAY) && (scancfg.colormode != CM_LINEART)) sumatorio /= lf1a4[channel]; else sumatorio /= lf1a4[scancfg.channel]; sumatorio = min (sumatorio * 0x4000, 65535); if (myRegs[0x1bf] != 0x18) myCalib->black_shading[channel][lf13c] |= (0x140 - ((((myRegs[0x1bf] >> 3) & 3) * 3) << 6)) & ((int) sumatorio); else myCalib->white_shading[channel][lf13c] = (unsigned short) sumatorio; } /*a9fd */ position++; } while (position < myWidth); } } else { /*a6d9 */ position = 0; sumatorio = 0; if (myWidth > 0) { do { switch (scancfg.colormode) { case CM_GRAY: case CM_LINEART: channel = 0; lf13c = position; break; default: /*CM_COLOR */ if (scancfg.samplerate == PIXEL_RATE) { channel = position % bytes_per_pixel; lf13c = position / bytes_per_pixel; } else { channel = position / lf168; lf13c = position % lf168; } break; } /*a743 */ if (lf130 > 0) bzero (buffer1, lf130 * sizeof (double)); /*a761 */ if (lf12c > 0) { for (a = 0; a < lf12c; a++) buffer2[a] = (1 << scancfg.depth) - 1.0; } /*a78f */ myESI = 0; myEDI = 0; ptr = scanbuffer + position; myHeight = 0; if (otherheight > 0) { do { myst = 0; for (a = 0; a < 4; a++) myst += *(ptr + (a * myWidth)); myEDI = 0; myst *= 0.25; if (myHeight < (otherheight - 4)) { if (myst < buffer2[myESI]) { buffer2[myESI] = myst; if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] < buffer2[a]) myESI = a; } } /*a820 */ if (myst >= buffer1[myEDI]) { buffer1[myEDI] = myst; if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] >= buffer1[a]) myEDI = a; } } sumatorio += myst; } else { /*a853 */ if (myHeight == (otherheight - 4)) { if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] >= buffer2[a]) myESI = a; } if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] < buffer1[a]) myEDI = a; } } /*a895 */ if (myst >= buffer2[myESI]) { /*a89c */ sumatorio -= buffer2[myESI]; sumatorio += myst; buffer2[myESI] = myst; if (lf12c > 0) { for (a = 0; a < lf12c; a++) if (buffer2[myESI] >= buffer2[a]) myESI = a; } } else { if (myst < buffer1[myEDI]) { sumatorio -= buffer1[myEDI]; sumatorio += myst; buffer1[myEDI] = myst; if (lf130 > 0) { for (a = 0; a < lf130; a++) if (buffer1[myEDI] < buffer1[a]) myEDI = a; } } } } /*a901 */ ptr += myWidth; myHeight++; } while (myHeight < otherheight); } /*a924 */ scancfg.ser = 0; scancfg.startpos = otherheight - 4; sumatorio /= scancfg.startpos; if (myCalib->shading_enabled != FALSE) { /*a94a */ myCalib->white_shading[channel][lf13c] = (unsigned short) sumatorio; } else { /*a967 */ if ((scancfg.colormode != CM_GRAY) && (scancfg.colormode != CM_LINEART)) sumatorio /= lf1a4[channel]; else sumatorio /= lf1a4[scancfg.channel]; sumatorio = min (sumatorio * 0x4000, 65535); if (myRegs[0x1bf] != 0x18) myCalib->black_shading[channel][lf13c] |= (0x140 - ((((myRegs[0x1bf] >> 3) & 0x03) * 3) << 6)) & ((int) sumatorio); else myCalib->white_shading[channel][lf13c] = (unsigned short) sumatorio; } /*a9fd */ position++; } while (position < myWidth); } } /*aa12 */ if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("whiteshading3.tiff", scancfg.coord.width, scancfg.coord.height, scancfg.depth, CM_COLOR, scancfg.resolution_x, scancfg.resolution_y, scanbuffer, (scancfg.coord.height + 16) * bytes_per_line); } free (buffer1); free (buffer2); free (scanbuffer); return OK; } static SANE_Int Calib_BlackShading (struct st_device *dev, struct st_calibration_config *calibcfg, struct st_calibration *myCalib, SANE_Int gainmode) { /* gainmode f8ec myCalib f8e8 calibcfg f8e4 */ SANE_Byte *myRegs; /*f1bc */ struct st_scanparams scancfg; /*f020 */ double shadingprediff[6]; /*f08c f094 f09c f0a4 f0ac f0b4 */ double mylong; /*f018 */ double maxvalue; /*eff8 */ double sumatorio = 0.0; double myst; SANE_Int rst; SANE_Int a; SANE_Int mheight; /*efe0 */ SANE_Int current_line; /*efe4 */ SANE_Int bytes_per_line; /*efd8 */ SANE_Int position; /*lefcc */ SANE_Int leff0, lf010, lefd0; SANE_Byte *buffer; /*efd4 */ SANE_Byte buff2[256]; /*F0BC */ SANE_Int buff3[0x8000]; SANE_Byte *ptr; /*f008 */ SANE_Int my14b4; /*f008 pisa ptr */ SANE_Int biggest; /*bx */ SANE_Int lowest; /*dx */ SANE_Int lefdc; SANE_Int channel; SANE_Int smvalues[3]; /*f04c f04e f050 */ double dbvalue[6]; /*lf05c lf060, lf064 lf068, lf06c lf070, lf074 lf078, lf07c lf080, lf084 lf088 */ DBG (DBG_FNC, "> Calib_BlackShading(*calibcfg, *myCalib, gainmode=%i)\n", gainmode); rst = OK; myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, &calibdata->Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (&scancfg, &calibdata->scancfg, sizeof (struct st_scanparams)); Lamp_SetGainMode (dev, myRegs, scancfg.resolution_x, gainmode); for (a = CL_RED; a <= CL_BLUE; a++) shadingprediff[a + 3] = calibcfg->BShadingPreDiff[a]; if ((scan.scantype >= ST_NORMAL) && (scan.scantype <= ST_NEG)) scancfg.coord.left += scan.ser; if ((scancfg.coord.width & 1) != 0) scancfg.coord.width++; scancfg.coord.top = 1; scancfg.depth = 8; scancfg.coord.height = calibcfg->BShadingHeight; if (scancfg.colormode != CM_COLOR) { bytes_per_line = scancfg.coord.width; leff0 = 0; lf010 = 1; } else { /*876c */ bytes_per_line = scancfg.coord.width * 3; if (scancfg.samplerate == LINE_RATE) { leff0 = scancfg.coord.width; lf010 = 1; } else { leff0 = 1; lf010 = 3; } } scancfg.v157c = bytes_per_line; scancfg.bytesperline = bytes_per_line; mylong = 1 << (16 - scancfg.depth); if ((myRegs[0x1bf] & 0x18) != 0) mylong /= 1 << (((myRegs[0x1bf] >> 5) & 3) + 4); lefd0 = ((((myRegs[0x1bf] >> 3) & 2) << 8) - ((((myRegs[0x1bf] >> 3) & 1) * 3) << 6)) - 1; if (scancfg.depth >= 8) maxvalue = ((1 << (scancfg.depth - 8)) << 8) - 1; else maxvalue = (256 / (1 << (8 - scancfg.depth))) - 1; Calib_LoadCut (dev, &scancfg, scan.scantype, calibcfg); for (a = CL_RED; a <= CL_BLUE; a++) shadingprediff[a] = calibcfg->ShadingCut[a]; if (calibcfg->BShadingOn == -1) { SANE_Int b, d; double e; for (a = CL_RED; a <= CL_BLUE; a++) { myst = max (shadingprediff[a], 0); myst = (maxvalue >= myst) ? shadingprediff[a] : maxvalue; shadingprediff[a] = max (myst, 0); } b = 0; while (b < bytes_per_line) { if (scancfg.colormode != CM_COLOR) { channel = 0; d = b; } else { if (scancfg.samplerate == PIXEL_RATE) { channel = (b % lf010) & 0xffff; d = (b / lf010) & 0xffff; } else { channel = (b / leff0) & 0xffff; d = (b % leff0) & 0xffff; } } /*89d0 */ e = min (lefd0, mylong * shadingprediff[channel]); myCalib->black_shading[channel][d] |= (unsigned short) e & 0xffff; b++; } return OK; } /* Allocate buffer to read image */ mheight = scancfg.coord.height; buffer = (SANE_Byte *) malloc (((scancfg.coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (buffer == NULL) return ERROR; /* Turn off lamp */ Lamp_Status_Set (dev, NULL, FALSE, FLB_LAMP); usleep (200 * 1000); /* Scan image */ myCalib->shading_enabled = FALSE; rst = RTS_GetImage (dev, myRegs, &scancfg, &calibdata->gain_offset, buffer, myCalib, 0x101, gainmode); if (rst == ERROR) { /*8ac2 */ free (buffer); memcpy (&calibdata->Regs, myRegs, RT_BUFFER_LEN * sizeof (SANE_Byte)); free (myRegs); return ERROR; } /* myRegs isn't going to be used anymore */ free (myRegs); myRegs = NULL; /* Turn on lamp again */ if (scan.scantype != ST_NORMAL) { Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP); usleep (1000 * 1000); } else Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); /* Save buffer */ if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("blackshading.tiff", scancfg.coord.width, scancfg.coord.height, scancfg.depth, CM_COLOR, scancfg.resolution_x, scancfg.resolution_y, buffer, (scancfg.coord.height + 16) * bytes_per_line); } if (scancfg.depth > 8) { /*8bb2 */ bzero (&dbvalue, 6 * sizeof (double)); position = 0; if (bytes_per_line > 0) { do { bzero (&buff3, 0x8000 * sizeof (SANE_Int)); sumatorio = 0; ptr = buffer + position; current_line = 0; biggest = 0; lowest = (int) maxvalue; /* Toma los valores de una columna */ if (mheight > 0) { SANE_Int value; do { value = data_lsb_get (ptr, 2); biggest = max (biggest, value); if (current_line < mheight) { sumatorio += value; lowest = min (lowest, value); biggest = max (biggest, value); buff3[value]++; } else { /*8cab */ if (value > lowest) { buff3[lowest]--; buff3[value]++; sumatorio += value; sumatorio -= lowest; if (buff3[lowest] != 0) { do { lowest++; } while (buff3[lowest] == 0); } } } /*8d0b */ ptr += (bytes_per_line * 2); current_line++; } while (current_line < mheight); } /*8d27 */ sumatorio /= mheight; if (scancfg.colormode != CM_COLOR) { channel = 0; lefdc = position; } else { /*8d5f */ if (scancfg.samplerate == PIXEL_RATE) { channel = position % lf010; lefdc = (position / lf010) & 0xffff; } else { channel = position / leff0; lefdc = position % leff0; } } dbvalue[channel] += sumatorio; if ((scancfg.colormode == CM_GRAY) || (scancfg.colormode == CM_LINEART)) sumatorio += shadingprediff[scancfg.channel]; else sumatorio += shadingprediff[channel]; myst = min (max (0, sumatorio), maxvalue); dbvalue[channel + 3] = myst; if ((calibcfg->BShadingOn == 1) || (calibcfg->BShadingOn == 2)) { if (calibcfg->BShadingOn == 2) { myst -= calibcfg->BRef[channel] * (1 << (scancfg.depth - 8)); myst = max (myst, 0); } /*8e6d */ myst *= mylong; myCalib->black_shading[channel][lefdc] = min (myst, lefd0); } position++; } while (position < bytes_per_line); } } else { /*8eb6 */ bzero (&dbvalue, 6 * sizeof (double)); position = 0; if (bytes_per_line > 0) { do { bzero (&buff2, 256 * sizeof (SANE_Byte)); sumatorio = 0; /* ptr points to the next position of the first line */ ptr = buffer + position; biggest = 0; lowest = (int) maxvalue; current_line = 0; /* Toma los valores de una columna */ if (mheight > 0) { my14b4 = v14b4; do { biggest = max (biggest, *ptr); if (my14b4 == 0) { /*8fd7 */ if (current_line < mheight) { sumatorio += *ptr; lowest = min (lowest, *ptr); biggest = max (biggest, *ptr); buff2[*ptr]++; } else { /*9011 */ if (*ptr > lowest) { buff2[lowest]--; buff2[*ptr]++; sumatorio += *ptr; sumatorio -= lowest; if (buff2[lowest] != 0) { do { lowest++; } while (buff2[lowest] == 0); } } } } else sumatorio += *ptr; /*9067 */ /* Point to the next pixel under current line */ ptr += bytes_per_line; current_line++; } while (current_line < mheight); } /*908a */ /* Calculates average of each column */ sumatorio = sumatorio / mheight; if (scancfg.colormode != CM_COLOR) { channel = 0; lefdc = position; } else { /*90c5 */ if (scancfg.samplerate == PIXEL_RATE) { channel = position % lf010; lefdc = (position / lf010) & 0xffff; } else { /*90fb */ channel = position / leff0; lefdc = position % leff0; } } /*911f */ dbvalue[channel] += sumatorio; if ((scancfg.colormode == CM_GRAY) || (scancfg.colormode == CM_LINEART)) sumatorio += shadingprediff[scancfg.channel]; else sumatorio += shadingprediff[channel]; /*9151 */ myst = min (max (0, sumatorio), maxvalue); /*9198 */ if (position >= 3) { double myst2; myst -= dbvalue[channel + 3]; myst2 = myst; myst = min (myst, shadingprediff[channel + 3]); my14b4 = -shadingprediff[channel + 3]; if (myst >= my14b4) myst = min (myst2, shadingprediff[channel + 3]); else myst = my14b4; myst += dbvalue[channel + 3]; } /*9203 */ dbvalue[channel + 3] = myst; switch (calibcfg->BShadingOn) { case 1: myCalib->black_shading[channel][lefdc] |= (unsigned short) (((int) myst & 0xff) << 8) & 0xffff; break; case 2: /*9268 */ my14b4 = calibcfg->BRef[channel] / (1 << (8 - scancfg.depth)); myst -= my14b4; myst = max (myst, 0); myst *= mylong; myCalib->black_shading[channel][lefdc] = min (myst, lefd0); break; } /*92d8 */ position++; } while (position < bytes_per_line); } } /*9306 */ if (calibcfg->BShadingOn == -2) { for (a = 0; a < 3; a++) { dbvalue[a] = (dbvalue[a] / scancfg.coord.width) + calibcfg->ShadingCut[a]; if (dbvalue[a] < 0) dbvalue[a] = 0; smvalues[a] = min ((int) (dbvalue[a] + 0.5) & 0xffff, maxvalue); } if (scancfg.coord.width > 0) { SANE_Int b, c; for (c = 0; c < scancfg.coord.width; c++) for (b = 0; b < 3; b++) myCalib->black_shading[b][c] |= (unsigned short) min (smvalues[b] * mylong, lefd0); } } /*9425 */ free (buffer); return OK; } static SANE_Int Calibration (struct st_device *dev, SANE_Byte * Regs, struct st_scanparams *scancfg, struct st_calibration *myCalib, SANE_Int value) { /*//SANE_Int Calibration([fa20]char *Regs, [fa24]struct st_scanparams *scancfg, [fa28]struct st_calibration myCalib, [fa2c]SANE_Int value) */ struct st_calibration_config calibcfg; /* f90c */ SANE_Int a; SANE_Byte gainmode; SANE_Int lf900; DBG (DBG_FNC, "> Calibration\n"); dbg_ScanParams (scancfg); value = value; /*silence gcc */ memcpy (&calibdata->Regs, Regs, sizeof (SANE_Byte) * RT_BUFFER_LEN); /*4213be8 */ memset (&calibcfg, 0x30, sizeof (struct st_calibration_config)); Calib_LoadConfig (dev, &calibcfg, scan.scantype, scancfg->resolution_x, scancfg->depth); bzero (&calibdata->gain_offset, sizeof (struct st_gain_offset)); /*[42b3654] */ for (a = CL_RED; a <= CL_BLUE; a++) { myCalib->WRef[a] = calibcfg.WRef[a]; calibdata->gain_offset.edcg1[a] = 256; calibdata->gain_offset.odcg1[a] = 256; calibdata->gain_offset.vgag1[a] = 4; calibdata->gain_offset.vgag2[a] = 4; /*3654|3656|3658 365a|365c|365e 3660|3662|3664 3666|3668|366a 366c|366d|366e 366f|3670|3671 3672|3673|3674 */ } memcpy (&calibdata->scancfg, scancfg, sizeof (struct st_scanparams)); gainmode = Lamp_GetGainMode (dev, scancfg->resolution_x, scan.scantype); /* [lf904] = 1 */ /* 3cf3 */ myCalib->first_position = 1; myCalib->shading_type = 0; if (calibdata->scancfg.colormode == CM_LINEART) { calibdata->scancfg.colormode = CM_GRAY; calibcfg.GainTargetFactor = 1.3; } lf900 = OK; if (calibcfg.CalibPAGOn != 0) { if (Calib_PAGain (dev, &calibcfg, gainmode) != 0) lf900 = ERROR; /*ERROR*/} else { /*3da7 */ if ((calibdata->scancfg.colormode != CM_GRAY) && (calibdata->scancfg.colormode != CM_LINEART)) { for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.pag[a] = calibcfg.PAG[a]; } else { /* 3dd3 */ /* Default PAGain */ if (calibdata->scancfg.channel > 2) calibdata->scancfg.channel = 0; for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.pag[a] = calibcfg.PAG[calibdata->scancfg.channel]; } } /* 3e01 */ if (calibcfg.CalibOffset10n != 0) /*==2*/ { /*v14b4=1 offset[CL_RED]=0x174 offset[CL_GREEN]=0x16d offset[CL_BLUE]=0x160 */ if ((v14b4 != 0) && (offset[CL_RED] != 0) && (offset[CL_GREEN] != 0) && (offset[CL_BLUE] != 0)) { for (a = CL_RED; a <= CL_BLUE; a++) { calibdata->gain_offset.edcg1[a] = offset[a]; calibdata->gain_offset.odcg1[a] = offset[a]; } } else { /* 3e84 */ if ((calibcfg.CalibOffset10n > 0) && (calibcfg.CalibOffset10n < 4)) { /*if (calibcfg.CalibOffset10n != 0) */ if (calibcfg.CalibOffset10n == 3) { lf900 = Calib_AdcOffsetRT (dev, &calibcfg, 1); } else { /* 3eb2 */ /*falta codigo */ } } } } else { /* 3faf */ for (a = CL_RED; a <= CL_BLUE; a++) { calibdata->gain_offset.edcg1[a] = abs (calibcfg.OffsetEven1[a] - 0x100); calibdata->gain_offset.odcg1[a] = abs (calibcfg.OffsetOdd1[a] - 0x100); } } /* 3f13 3f0b */ if ((gainmode != 0) && (calibcfg.CalibGain10n != 0)) { /*gain[CL_RED]=0x17 gain[CL_GREEN]=0x12 gain[CL_BLUE]=0x17 */ if ((v14b4 != 0) && (gain[CL_RED] != 0) && (gain[CL_GREEN] != 0) && (gain[CL_BLUE] != 0)) { for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.vgag1[a] = gain[a]; } else { /*4025 */ lf900 = Calib_AdcGain (dev, &calibcfg, 1, gainmode); if ((v14b4 != 0) && (lf900 == OK)) GainOffset_Save (dev, &calibdata->gain_offset.edcg1[0], &calibdata->gain_offset.vgag1[0]); } } else { /*4089 */ for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.vgag1[a] = calibcfg.Gain1[a]; } /*40a5 */ if ((gainmode != 0) && (calibcfg.CalibOffset20n != 0)) { switch (calibcfg.CalibOffset20n) { case 3: lf900 = Calib_AdcOffsetRT (dev, &calibcfg, 2); break; } /*4140 */ /*falta codigo */ } else { /*4162 */ for (a = CL_RED; a <= CL_BLUE; a++) { calibdata->gain_offset.edcg2[a] = abs (calibcfg.OffsetEven2[a] - 0x40); calibdata->gain_offset.odcg2[a] = abs (calibcfg.OffsetOdd2[a] - 0x40); } } /*41d6 */ if ((gainmode != 0) && (calibcfg.CalibGain20n != 0)) { lf900 = Calib_AdcGain (dev, &calibcfg, 0, gainmode); } else { /*423c */ for (a = CL_RED; a <= CL_BLUE; a++) calibdata->gain_offset.vgag2[a] = calibcfg.Gain2[a]; } /*4258 */ if (calibcfg.TotShading != 0) { lf900 = Calib_BWShading (&calibcfg, myCalib, gainmode); /*falta codigo */ } else { /*428f */ if (gainmode != 0) { if (calibcfg.BShadingOn != 0) lf900 = Calib_BlackShading (dev, &calibcfg, myCalib, gainmode); /*42fd */ if ((lf900 != ERROR) && (calibcfg.WShadingOn != 0)) { switch (calibcfg.WShadingOn) { default: break; case 3: lf900 = Calib_WhiteShading_3 (dev, &calibcfg, myCalib, gainmode); break; case 2: break; } } else myCalib->shading_enabled = FALSE; } else myCalib->shading_enabled = FALSE; } /*43ca */ memcpy (&myCalib->gain_offset, &calibdata->gain_offset, sizeof (struct st_gain_offset)); memcpy (&mitabla2, &calibdata->gain_offset, sizeof (struct st_gain_offset)); /*4424 */ /* Park home after calibration */ if (get_value (SCANINFO, PARKHOMEAFTERCALIB, TRUE, FITCALIBRATE) == FALSE) scan.ler -= calibcfg.WShadingHeight; else Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); return OK; } /*static void show_diff(struct st_device *dev, SANE_Byte *original) { SANE_Byte *buffer = (SANE_Byte *)malloc(RT_BUFFER_LEN * sizeof(SANE_Byte)); SANE_Int a; if ((buffer == NULL)||(original == NULL)) return; if (RTS_ReadRegs(dev->usb_handle, buffer) != OK) { free(buffer); return; } for (a = 0; a < RT_BUFFER_LEN; a++) { if ((original[a] & 0xff) != (buffer[a] & 0xff)) { printf("%5i: %i -> %i\n", a, original[a] & 0xff, buffer[a] & 0xff); original[a] = buffer[a] & 0xff; } } free(buffer); } */ static SANE_Int Load_Constrains (struct st_device *dev) { SANE_Int rst = ERROR; if (dev->constrains != NULL) Free_Constrains (dev); DBG (DBG_FNC, "> Load_Constrains\n"); dev->constrains = (struct st_constrains *) malloc (sizeof (struct st_constrains)); if (dev->constrains != NULL) { cfg_constrains_get (dev->constrains); rst = OK; } return rst; } static SANE_Int Constrains_Check (struct st_device *dev, SANE_Int Resolution, SANE_Int scantype, struct st_coords *mycoords) { /* Constrains: 100 dpi 850 x 1170 | 164 x 327 300 dpi 2550 x 3510 600 dpi 5100 x 7020 1200 dpi 10200 x 14040 */ SANE_Int rst = ERROR; if (dev->constrains != NULL) { struct st_coords coords; struct st_coords *mc; if ((scantype < ST_NORMAL) || (scantype > ST_NEG)) scantype = ST_NORMAL; switch (scantype) { case ST_TA: mc = &dev->constrains->slide; break; case ST_NEG: mc = &dev->constrains->negative; break; default: mc = &dev->constrains->reflective; break; } coords.left = MM_TO_PIXEL (mc->left, Resolution); coords.width = MM_TO_PIXEL (mc->width, Resolution); coords.top = MM_TO_PIXEL (mc->top, Resolution); coords.height = MM_TO_PIXEL (mc->height, Resolution); /* Check left and top */ if (mycoords->left < 0) mycoords->left = 0; mycoords->left += coords.left; if (mycoords->top < 0) mycoords->top = 0; mycoords->top += coords.top; /* Check width and height */ if ((mycoords->width < 0) || (mycoords->width > coords.width)) mycoords->width = coords.width; if ((mycoords->height < 0) || (mycoords->height > coords.height)) mycoords->height = coords.height; rst = OK; } DBG (DBG_FNC, "> Constrains_Check: Source=%s, Res=%i, LW=(%i,%i), TH=(%i,%i): %i\n", dbg_scantype (scantype), Resolution, mycoords->left, mycoords->width, mycoords->top, mycoords->height, rst); return rst; } static struct st_coords * Constrains_Get (struct st_device *dev, SANE_Byte scantype) { static struct st_coords *rst = NULL; if (dev->constrains != NULL) { switch (scantype) { case ST_TA: rst = &dev->constrains->slide; break; case ST_NEG: rst = &dev->constrains->negative; break; default: rst = &dev->constrains->reflective; break; } } return rst; } static void Free_Constrains (struct st_device *dev) { DBG (DBG_FNC, "> Free_Constrains\n"); if (dev->constrains != NULL) { free (dev->constrains); dev->constrains = NULL; } } static void RTS_DebugInit () { /* Default vaules */ RTS_Debug->dev_model = HP3970; RTS_Debug->DumpShadingData = FALSE; RTS_Debug->SaveCalibFile = FALSE; RTS_Debug->ScanWhiteBoard = FALSE; RTS_Debug->EnableGamma = TRUE; RTS_Debug->use_fixed_pwm = TRUE; RTS_Debug->dmatransfersize = 0x80000; RTS_Debug->dmasetlength = 0x7c0000; RTS_Debug->dmabuffersize = 0x400000; RTS_Debug->usbtype = -1; /* Lamp settings */ RTS_Debug->overdrive_flb = 10000; /* msecs */ RTS_Debug->overdrive_ta = 10000; /* msecs */ RTS_Debug->warmup = TRUE; /* Calibration settings */ RTS_Debug->calibrate = FALSE; RTS_Debug->wshading = TRUE; } static void RTS_Setup_Gamma (SANE_Byte * Regs, struct st_hwdconfig *hwdcfg) { DBG (DBG_FNC, "> RTS_Setup_Gamma(*Regs, *hwdcfg)\n"); if ((hwdcfg != NULL) && (Regs != NULL)) { if (hwdcfg->use_gamma_tables != FALSE) { SANE_Int table_size; /* set set table size */ data_bitset (&Regs[0x1d0], 0x0f, hwdcfg->gamma_tablesize); /* enable gamma correction */ data_bitset (&Regs[0x1d0], 0x40, 1); switch (Regs[0x1d0] & 0x0c) { case 0: table_size = (Regs[0x1d0] & 1) | 0x0100; break; case 4: table_size = (Regs[0x1d0] & 1) | 0x0400; break; case 8: table_size = (Regs[0x1d0] & 1) | 0x1000; break; default: table_size = hwdcfg->startpos & 0xffff; break; } /* 5073 */ /* points to red gamma table */ data_wide_bitset (&Regs[0x1b4], 0x3fff, 0); /* points to green gamma table */ data_wide_bitset (&Regs[0x1b6], 0x3fff, table_size); /* points to blue gamma table */ data_wide_bitset (&Regs[0x1b8], 0x3fff, table_size * 2); v15f8 = (((table_size * 3) + 15) / 16) & 0xffff; } else { /* disable gamma correction */ data_bitset (&Regs[0x1d0], 0x40, 0); v15f8 = 0; } } } static SANE_Int RTS_USBType (struct st_device *dev) { /* Gets USB type of this scanner */ SANE_Int rst = ERROR; SANE_Byte data; DBG (DBG_FNC, "+ RTS_USBType\n"); if (Read_Byte (dev->usb_handle, 0xfe11, &data) == OK) rst = (data & 1); DBG (DBG_FNC, "- RTS_USBType(void): %s\n", (rst == USB11) ? "USB1.1" : "USB2.0"); return rst; } static SANE_Int Init_Vars (void) { SANE_Int rst = OK; hp_gamma = malloc (sizeof (struct st_gammatables)); if (hp_gamma != NULL) bzero (hp_gamma, sizeof (struct st_gammatables)); else rst = ERROR; if (rst == OK) { RTS_Debug = malloc (sizeof (struct st_debug_opts)); if (RTS_Debug != NULL) bzero (RTS_Debug, sizeof (struct st_debug_opts)); else rst = ERROR; } if (rst == OK) { default_gain_offset = malloc (sizeof (struct st_gain_offset)); if (default_gain_offset != NULL) bzero (default_gain_offset, sizeof (struct st_gain_offset)); else rst = ERROR; } if (rst == OK) { calibdata = malloc (sizeof (struct st_calibration_data)); if (calibdata != NULL) bzero (calibdata, sizeof (struct st_calibration_data)); else rst = ERROR; } if (rst == OK) { wshading = malloc (sizeof (struct st_shading)); if (wshading != NULL) bzero (wshading, sizeof (struct st_shading)); else rst = ERROR; } waitforpwm = TRUE; use_gamma_tables = TRUE; if (rst == OK) RTS_DebugInit (); else Free_Vars (); return rst; } static void Free_Vars (void) { if (RTS_Debug != NULL) { free (RTS_Debug); RTS_Debug = NULL; } if (hp_gamma != NULL) { free (hp_gamma); hp_gamma = NULL; } if (calibdata != NULL) { free (calibdata); calibdata = NULL; } if (wshading != NULL) { if (wshading->rates != NULL) free (wshading->rates); free (wshading); wshading = NULL; } if (default_gain_offset != NULL) { free (default_gain_offset); default_gain_offset = NULL; } } static SANE_Int Chipset_Reset (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ Chipset_Reset:\n"); /* I've found two ways to reset chipset. Next one will stay commented rst = ERROR; if (Read_Byte(dev->usb_handle, 0xe800, &data) == OK) { data |= 0x20; if (Write_Byte(dev->usb_handle, 0xe800, data) == OK) { data &= 0xdf; rst = Write_Byte(dev->usb_handle, 0xe800, data); } } */ rst = IWrite_Buffer (dev->usb_handle, 0x0000, NULL, 0, 0x0801); DBG (DBG_FNC, "- Chipset_Reset: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Enable_Read (struct st_device *dev, SANE_Int dmacs, SANE_Int size, SANE_Int options) { SANE_Int rst = ERROR; SANE_Byte buffer[6]; DBG (DBG_FNC, "+ RTS_DMA_Enable_Read(dmacs=0x%04x, size=%i, options=0x%06x)\n", dmacs, size, options); data_msb_set (&buffer[0], options, 3); /* buffer size divided by 2 (words count) */ data_lsb_set (&buffer[3], size / 2, 3); rst = IWrite_Buffer (dev->usb_handle, dmacs, buffer, 6, 0x0400); DBG (DBG_FNC, "- RTS_DMA_Enable_Read: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Enable_Write (struct st_device *dev, SANE_Int dmacs, SANE_Int size, SANE_Int options) { SANE_Int rst = ERROR; SANE_Byte buffer[6]; DBG (DBG_FNC, "+ RTS_DMA_Enable_Write(dmacs=0x%04x, size=%i, options=0x%06x)\n", dmacs, size, options); data_msb_set (&buffer[0], options, 3); /* buffer size divided by 2 (words count) */ data_lsb_set (&buffer[3], size / 2, 3); rst = IWrite_Buffer (dev->usb_handle, dmacs, buffer, 6, 0x0401); DBG (DBG_FNC, "- RTS_DMA_Enable_Write: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Cancel (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_DMA_Cancel:\n"); rst = IWrite_Word (dev->usb_handle, 0x0000, 0, 0x0600); DBG (DBG_FNC, "- RTS_DMA_Cancel: %i\n", rst); return rst; } static SANE_Int RTS_DMA_Reset (struct st_device *dev) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_DMA_Reset:\n"); rst = IWrite_Word (dev->usb_handle, 0x0000, 0x0000, 0x0800); DBG (DBG_FNC, "- RTS_DMA_Reset: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_WriteByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_WriteByte(address=%04x, data=%i):\n", address, data); rst = IWrite_Byte (usb_handle, address, data, 0x200, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_WriteByte: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_ReadWord (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_ReadWord(address=%04x, data):\n", address); rst = IRead_Word (usb_handle, address, data, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_ReadWord: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_ReadByte (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_ReadByte(address=%04x, data):\n", address); rst = IRead_Byte (usb_handle, address, data, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_ReadByte: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_WriteWord (USB_Handle usb_handle, SANE_Int address, SANE_Int data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_WriteWord(address=%04x, data=%i):\n", address, data); rst = IWrite_Word (usb_handle, address, data, 0x0200); DBG (DBG_FNC, "- RTS_EEPROM_WriteWord: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_ReadInteger (USB_Handle usb_handle, SANE_Int address, SANE_Int * data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_ReadInteger(address=%04x, data):\n", address); rst = IRead_Integer (usb_handle, address, data, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_ReadInteger: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_WriteInteger (USB_Handle usb_handle, SANE_Int address, SANE_Int data) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_WriteInteger(address=%04x, data):\n", address); rst = IWrite_Integer (usb_handle, address, data, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_WriteInteger: %i\n", rst); return rst; } static SANE_Int RTS_EEPROM_WriteBuffer (USB_Handle usb_handle, SANE_Int address, SANE_Byte * data, SANE_Int size) { SANE_Int rst; DBG (DBG_FNC, "+ RTS_EEPROM_WriteBuffer(address=%04x, data, size=%i):\n", address, size); rst = IWrite_Buffer (usb_handle, address, data, size, 0x200); DBG (DBG_FNC, "- RTS_EEPROM_WriteBuffer: %i\n", rst); return rst; } static void WShading_Emulate (SANE_Byte * buffer, SANE_Int * chnptr, SANE_Int size, SANE_Int depth) { if ((wshading->rates != NULL) && (chnptr != NULL)) { if (*chnptr < wshading->count) { double maxvalue, chncolor; SANE_Int chnsize; SANE_Int pos; SANE_Int icolor; maxvalue = (1 << depth) - 1; chnsize = (depth > 8) ? 2 : 1; pos = 0; while (pos < size) { /* get channel color */ chncolor = data_lsb_get (buffer + pos, chnsize); /* apply shading coeficient */ chncolor *= wshading->rates[*chnptr]; /* care about limits */ chncolor = min (chncolor, maxvalue); /* save color */ icolor = chncolor; data_lsb_set (buffer + pos, icolor, chnsize); *chnptr = *chnptr + 1; if (*chnptr >= wshading->count) *chnptr = 0; pos += chnsize; } } } } static SANE_Int WShading_Calibrate (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg) { struct st_calibration_config *calibcfg; struct st_gain_offset myCalibTable; struct st_scanparams *myscancfg; SANE_Byte *myRegs; /*f1bc */ SANE_Int bytes_per_line; /**/ SANE_Int x, y, a, C; SANE_Byte *pattern; /*f164 */ double sumatorio; SANE_Int gainmode; SANE_Int rst; SANE_Byte *avg_colors; DBG (DBG_FNC, "> WShading_Calibrate(*myCalib)\n"); bzero (&myCalibTable, sizeof (struct st_gain_offset)); for (C = CL_RED; C <= CL_BLUE; C++) { myCalibTable.pag[C] = 3; myCalibTable.vgag1[C] = 4; myCalibTable.vgag2[C] = 4; } calibcfg = (struct st_calibration_config *) malloc (sizeof (struct st_calibration_config)); memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, myscancfg->depth); gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); rst = OK; switch (scan.scantype) { case ST_NORMAL: /*a184 */ myscancfg->coord.left += scan.ser; myscancfg->coord.width &= 0xffff; break; case ST_TA: case ST_NEG: myscancfg->coord.left += scan.ser; break; } /*a11b */ if ((myscancfg->coord.width & 1) != 0) myscancfg->coord.width++; myscancfg->coord.top = 1; myscancfg->coord.height = calibcfg->WShadingHeight; myscancfg->sensorresolution = 0; bytes_per_line = myscancfg->coord.width * (((myscancfg->colormode == CM_COLOR) ? 3 : 1) * ((myscancfg->depth > 8) ? 2 : 1)); /*a1e8 */ myscancfg->v157c = bytes_per_line; myscancfg->bytesperline = bytes_per_line; /* allocate space for pattern */ pattern = (SANE_Byte *) malloc (((myscancfg->coord.height) * bytes_per_line) * sizeof (SANE_Byte)); if (pattern == NULL) return ERROR; /* Scan image */ myCalib->shading_enabled = FALSE; rst = RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, pattern, myCalib, 0x20000000, gainmode); if (rst != ERROR) { SANE_Int chn; double colors[3] = { 0, 0, 0 }; double prueba; SANE_Int data; SANE_Int bytes_per_channel; bytes_per_channel = (myscancfg->depth > 8) ? 2 : 1; avg_colors = (SANE_Byte *) malloc (sizeof (SANE_Byte) * bytes_per_line); if (avg_colors != NULL) { wshading->ptr = 0; wshading->count = bytes_per_line / bytes_per_channel; if (wshading->rates != NULL) { free (wshading->rates); wshading->rates = NULL; } wshading->rates = (double *) malloc (sizeof (double) * wshading->count); chn = 0; for (x = 0; x < wshading->count; x++) { sumatorio = 0; for (y = 0; y < myscancfg->coord.height; y++) { data = data_lsb_get (pattern + ((x * bytes_per_channel) + (bytes_per_line * y)), bytes_per_channel); sumatorio += data; } sumatorio /= myscancfg->coord.height; a = sumatorio; colors[chn] = max (colors[chn], sumatorio); chn++; if (chn > 2) chn = 0; data_lsb_set (avg_colors + (x * bytes_per_channel), a, bytes_per_channel); } DBG (DBG_FNC, " -> max colors RGB= %f %f %f\n", colors[0], colors[1], colors[2]); chn = 0; for (x = 0; x < wshading->count; x++) { data = data_lsb_get (avg_colors + (x * bytes_per_channel), bytes_per_channel); prueba = data; *(wshading->rates + x) = colors[chn] / prueba; chn++; if (chn > 2) chn = 0; } } if (RTS_Debug->SaveCalibFile != FALSE) { dbg_tiff_save ("whiteshading_jkd.tiff", myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, scancfg->resolution_x, scancfg->resolution_y, pattern, (myscancfg->coord.height) * bytes_per_line); } #ifdef developing { FILE *archivo; char texto[1024]; /* apply correction to the pattern to see the result */ chn = 0; for (x = 0; x < myscancfg->coord.height * wshading->count; x++) { data = data_lsb_get (pattern + (x * bytes_per_channel), bytes_per_channel); sumatorio = data; sumatorio *= wshading->rates[chn]; if (sumatorio > ((1 << myscancfg->depth) - 1)) sumatorio = (1 << myscancfg->depth) - 1; a = sumatorio; data_lsb_set (pattern + (x * bytes_per_channel), a, bytes_per_channel); chn++; if (chn == wshading->count) chn = 0; } /* save corrected pattern */ dbg_tiff_save ("onwhiteshading_jkd.tiff", myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, scancfg->resolution_x, scancfg->resolution_y, pattern, (myscancfg->coord.height) * bytes_per_line); /* export coefficients */ archivo = fopen ("wShading.txt", "w"); for (x = 0; x < wshading->count; x++) { snprintf (texto, 1024, "%f", wshading->rates[x]); fprintf (archivo, "%s\n", texto); } fclose (archivo); } #endif } free (pattern); return OK; } #ifdef developing static SANE_Int motor_pos (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg) { struct st_calibration_config *calibcfg; struct st_gain_offset myCalibTable; struct st_scanparams *myscancfg; SANE_Byte *myRegs; /*f1bc */ SANE_Int bytes_per_line; /**/ SANE_Int a, C; SANE_Byte *scanbuffer; /*f164 */ SANE_Int gainmode; SANE_Int rst; DBG (DBG_FNC, "> Calib_test(*myCalib)\n"); bzero (&myCalibTable, sizeof (struct st_gain_offset)); calibcfg = (struct st_calibration_config *) malloc (sizeof (struct st_calibration_config)); memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, myscancfg->depth); gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); rst = OK; switch (scan.scantype) { case ST_NORMAL: /*a184 */ myscancfg->coord.left += scan.ser; myscancfg->coord.width &= 0xffff; break; case ST_TA: case ST_NEG: myscancfg->coord.left += scan.ser; break; } /*a11b */ if ((myscancfg->coord.width & 1) != 0) myscancfg->coord.width++; myscancfg->coord.top = 100; myscancfg->coord.height = 30; bytes_per_line = myscancfg->coord.width * 3; /*a1e8 */ myscancfg->v157c = bytes_per_line; myscancfg->bytesperline = bytes_per_line; scanbuffer = (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (scanbuffer == NULL) return ERROR; /* Scan image */ myCalib->shading_enabled = FALSE; /*Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5500); */ for (a = 0; a < 10; a++) { for (C = CL_RED; C <= CL_BLUE; C++) { myCalibTable.pag[C] = 3; myCalibTable.vgag1[C] = 4; myCalibTable.vgag2[C] = 4; myCalibTable.edcg1[C] = a * 20; } dbg_ScanParams (myscancfg); Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5000); rst = RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, myCalib, 0x20000000, gainmode); Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); if (rst != ERROR) { char name[30]; snprintf (name, 30, "calibtest-%i.tiff", a); dbg_tiff_save (name, myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, myscancfg->resolution_x, myscancfg->resolution_y, scanbuffer, (myscancfg->coord.height + 16) * bytes_per_line); } } free (scanbuffer); exit (0); return OK; } static SANE_Int hp4370_prueba (struct st_device *dev) { SANE_Int rst; SANE_Int data = 0x0530, a; SANE_Int transferred; SANE_Byte buffer[512]; for (a = 0; a < 256; a++) data_lsb_set (buffer + (a * 2), 0x9d7, 2); rst = IWrite_Word (dev->usb_handle, 0x0000, data, 0x0800); RTS_DMA_Enable_Write (dev, 0x4, 512, 0); Bulk_Operation (dev, BLK_WRITE, 512, buffer, &transferred); return rst; } static SANE_Int Calib_BlackShading_jkd (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg) { struct st_calibration_config *calibcfg; struct st_gain_offset myCalibTable; struct st_scanparams *myscancfg; SANE_Byte *myRegs; /*f1bc */ SANE_Int bytes_per_line; /**/ SANE_Int x, y, a, C; SANE_Byte *scanbuffer; /*f164 */ double sumatorio; SANE_Int gainmode; SANE_Int rst; DBG (DBG_FNC, "> Calib_BlackShading_jkd(*myCalib)\n"); bzero (&myCalibTable, sizeof (struct st_gain_offset)); for (C = CL_RED; C <= CL_BLUE; C++) { myCalibTable.pag[C] = 3; myCalibTable.vgag1[C] = 4; myCalibTable.vgag2[C] = 4; } calibcfg = (struct st_calibration_config *) malloc (sizeof (struct st_calibration_config)); memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, myscancfg->depth); gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); rst = OK; switch (scan.scantype) { case ST_NORMAL: /*a184 */ myscancfg->coord.left += scan.ser; myscancfg->coord.width &= 0xffff; break; case ST_TA: case ST_NEG: myscancfg->coord.left += scan.ser; break; } /*a11b */ if ((myscancfg->coord.width & 1) != 0) myscancfg->coord.width++; myscancfg->coord.top = 1; myscancfg->coord.height = calibcfg->BShadingHeight; bytes_per_line = myscancfg->coord.width * 3; /*a1e8 */ myscancfg->v157c = bytes_per_line; myscancfg->bytesperline = bytes_per_line; scanbuffer = (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (scanbuffer == NULL) return ERROR; /* Turn off lamp */ Lamp_Status_Set (dev, NULL, FALSE, FLB_LAMP); usleep (200 * 1000); /* Scan image */ myCalib->shading_enabled = FALSE; rst = RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, myCalib, 0x101, gainmode); /* Turn on lamp again */ if (scan.scantype != ST_NORMAL) { Lamp_Status_Set (dev, NULL, FALSE, TMA_LAMP); usleep (1000 * 1000); } else Lamp_Status_Set (dev, NULL, TRUE, FLB_LAMP); if (rst != ERROR) { jkd_black = (SANE_Byte *) malloc (bytes_per_line); if (jkd_black != NULL) { jkd_blackbpl = bytes_per_line; for (x = 0; x < bytes_per_line; x++) { sumatorio = 0; for (y = 0; y < myscancfg->coord.height + 16; y++) sumatorio += scanbuffer[x + (bytes_per_line * y)]; sumatorio /= myscancfg->coord.height + 16; a = sumatorio; *(jkd_black + x) = _B0 (a); } } /*if (RTS_Debug->SaveCalibFile != FALSE) */ { dbg_tiff_save ("blackshading_jkd.tiff", myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, myscancfg->resolution_x, myscancfg->resolution_y, scanbuffer, (myscancfg->coord.height + 16) * bytes_per_line); } } free (scanbuffer); return OK; } static SANE_Int Calib_test (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib, struct st_scanparams *scancfg) { struct st_calibration_config *calibcfg; struct st_gain_offset myCalibTable; struct st_scanparams *myscancfg; SANE_Byte *myRegs; /*f1bc */ SANE_Int bytes_per_line; /**/ SANE_Int a, C; SANE_Byte *scanbuffer; /*f164 */ SANE_Int gainmode; SANE_Int rst; DBG (DBG_FNC, "> Calib_test(*myCalib)\n"); bzero (&myCalibTable, sizeof (struct st_gain_offset)); calibcfg = (struct st_calibration_config *) malloc (sizeof (struct st_calibration_config)); memset (calibcfg, 0x30, sizeof (struct st_calibration_config)); myscancfg = (struct st_scanparams *) malloc (sizeof (struct st_scanparams)); memcpy (myscancfg, scancfg, sizeof (struct st_scanparams)); myRegs = (SANE_Byte *) malloc (RT_BUFFER_LEN * sizeof (SANE_Byte)); memcpy (myRegs, Regs, RT_BUFFER_LEN * sizeof (SANE_Byte)); Calib_LoadConfig (dev, calibcfg, scan.scantype, myscancfg->resolution_x, myscancfg->depth); gainmode = Lamp_GetGainMode (dev, myscancfg->resolution_x, scan.scantype); Lamp_SetGainMode (dev, myRegs, myscancfg->resolution_x, gainmode); rst = OK; switch (scan.scantype) { case ST_NORMAL: /*a184 */ myscancfg->coord.left += scan.ser; myscancfg->coord.width &= 0xffff; break; case ST_TA: case ST_NEG: myscancfg->coord.left += scan.ser; break; } /*a11b */ if ((myscancfg->coord.width & 1) != 0) myscancfg->coord.width++; myscancfg->coord.top = 100; myscancfg->coord.height = 30; bytes_per_line = myscancfg->coord.width * 3; /*a1e8 */ myscancfg->v157c = bytes_per_line; myscancfg->bytesperline = bytes_per_line; scanbuffer = (SANE_Byte *) malloc (((myscancfg->coord.height + 16) * bytes_per_line) * sizeof (SANE_Byte)); if (scanbuffer == NULL) return ERROR; /* Scan image */ myCalib->shading_enabled = FALSE; /*Head_Relocate(dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5500); */ for (a = 0; a < 10; a++) { for (C = CL_RED; C <= CL_BLUE; C++) { myCalibTable.pag[C] = 3; myCalibTable.vgag1[C] = 4; myCalibTable.vgag2[C] = 4; myCalibTable.edcg1[C] = a * 20; } Head_Relocate (dev, dev->motorcfg->highspeedmotormove, MTR_FORWARD, 5000); rst = RTS_GetImage (dev, myRegs, myscancfg, &myCalibTable, scanbuffer, myCalib, 0x20000000, gainmode); Head_ParkHome (dev, TRUE, dev->motorcfg->parkhomemotormove); if (rst != ERROR) { char name[30]; snprintf (name, 30, "calibtest-%i.tiff", a); dbg_tiff_save (name, myscancfg->coord.width, myscancfg->coord.height, myscancfg->depth, CM_COLOR, myscancfg->resolution_x, myscancfg->resolution_y, scanbuffer, (myscancfg->coord.height + 16) * bytes_per_line); } } free (scanbuffer); exit (0); return OK; } static void prueba (SANE_Byte * a) { /* SANE_Byte p[] = {}; */ /*int z = 69; */ /*(a + 11) = 0x0; */ /*a[1] = a[1] | 0x40; */ /*memcpy(a, &p, sizeof(p)); */ /*memcpy(a + 0x12, p, 10); */ /*a[0x146] &= 0xdf; */ } void shadingtest1 (struct st_device *dev, SANE_Byte * Regs, struct st_calibration *myCalib) { USHORT *buffer; int a; int bit[2]; DBG (DBG_FNC, "+ shadingtest1(*Regs, *myCalib):\n"); if ((Regs == NULL) || (myCalib == NULL)) return; RTS_DMA_Reset (dev); bit[0] = (Regs[0x60b] >> 6) & 1; bit[1] = (Regs[0x60b] >> 4) & 1; Regs[0x060b] &= 0xaf; Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); Regs[0x1cf] = 0; /* reset config. By default black shading disabled and pixel-rate */ /*Regs[0x1cf] |= 2; shadingbase 0x2000 */ Regs[0x1cf] |= 4; /* White shading enabled */ Regs[0x1cf] |= 0x20; /* 16 bits per channel */ Write_Byte (dev->usb_handle, 0xe9cf, Regs[0x01cf]); buffer = (USHORT *) malloc (sizeof (USHORT) * myCalib->shadinglength); DBG (DBG_FNC, " -> shading length = %i\n", myCalib->shadinglength); /* fill buffer */ for (a = 0; a < myCalib->shadinglength; a++) buffer[a] = RTS_Debug->shd + (a * 500); for (a = 0; a < 3; a++) { RTS_DMA_Write (dev, a | 0x14, 0, sizeof (USHORT) * myCalib->shadinglength, (SANE_Byte *) buffer); } data_bitset (&Regs[0x60b], 0x40, bit[0]); /*-x------*/ data_bitset (&Regs[0x60b], 0x10, bit[1]); /*---x----*/ Write_Byte (dev->usb_handle, 0xee0b, Regs[0x060b]); DBG (DBG_FNC, "- shadingtest1\n"); } #endif #endif /* RTS8822_CORE */ sane-backends-1.0.27/backend/dc210.conf.in0000664000175000017500000000173012112021330014660 00000000000000# Serial port where the camera is connected ## Linux port=/dev/ttyS0 ## IRIX #port=/dev/ttyd1 ## Solaris #port=/dev/term/a ## HP-UX #port=/dev/tty0p0 ## Digital UNIX #port=/dev/tty01 # Max baud rate for download. Camera always starts at 9600 baud, then # switches to the higher rate ## This works for Linux. Also works for IRIX (6.3 or higher), providing that ## the host is an O2, OCTANE, Origin2000/200, Onyx2, Origin3000/300, Onyx3 or ## a newer SGI hardware [see serial(7)]. #baud=115200 ## This works for most UNIX's baud=38400 # Prints some extra information during the init phase. This can be # handy, but note that printing anything to stderr breaks the saned # network scanning. #dumpinquiry # How many usec (1,000,000ths of a) between writing the command and reading the # result. 125000 seems to be the lowest I could go reliably. cmdrespause=125000 # How many usec (1,000,000ths of a) between sending the "back to default" break # sending commands. breakpause=1000000; sane-backends-1.0.27/backend/umax_pp_low.h0000664000175000017500000001104712775277260015336 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2012 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Umax PP flatbed scanners. */ #include #include "../include/sane/config.h" /*****************************************************************************/ /* set port to 'idle state' and get iopl */ /*****************************************************************************/ extern int sanei_umax_pp_initPort (int port, char *name); extern int sanei_umax_pp_initScanner (int recover); extern int sanei_umax_pp_initTransport (int recover); extern int sanei_umax_pp_endSession (void); extern int sanei_umax_pp_initCancel (void); extern int sanei_umax_pp_cancel (void); extern int sanei_umax_pp_checkModel (void); extern int sanei_umax_pp_getauto (void); extern int sanei_umax_pp_UTA (void); extern void sanei_umax_pp_setauto (int mode); #ifndef __GLOBALES__ #define RGB_MODE 0x10 #define RGB12_MODE 0x11 #define BW_MODE 0x08 #define BW12_MODE 0x09 #define BW2_MODE 0x04 #define __GLOBALES__ #endif /* __GLOBALES__ */ #ifndef PRECISION_ON #define PRECISION_ON 1 #define PRECISION_OFF 0 #define LAMP_STATE 0x20 #define MOTOR_BIT 0x40 #define ASIC_BIT 0x100 #define UMAX_PP_PARPORT_PS2 0x01 #define UMAX_PP_PARPORT_BYTE 0x02 #define UMAX_PP_PARPORT_EPP 0x04 #define UMAX_PP_PARPORT_ECP 0x08 #endif extern int sanei_umax_pp_scan (int x, int y, int width, int height, int dpi, int color, int gain, int offset); extern int sanei_umax_pp_move (int distance, int precision, unsigned char *buffer); extern int sanei_umax_pp_setLamp (int on); extern int sanei_umax_pp_completionWait (void); extern int sanei_umax_pp_commitScan (void); extern int sanei_umax_pp_park (void); extern int sanei_umax_pp_parkWait (void); extern int sanei_umax_pp_readBlock (long len, int window, int dpi, int last, unsigned char *buffer); extern int sanei_umax_pp_startScan (int x, int y, int width, int height, int dpi, int color, int gain, int offset, int *rbpp, int *rtw, int *rth); extern void sanei_umax_pp_setport (int port); extern int sanei_umax_pp_getport (void); extern void sanei_umax_pp_setparport (int fd); extern int sanei_umax_pp_getparport (void); extern void sanei_umax_pp_setastra (int mod); extern int sanei_umax_pp_getastra (void); extern void sanei_umax_pp_setLeft (int mod); extern int sanei_umax_pp_getLeft (void); extern void sanei_umax_pp_setfull (int mod); extern int sanei_umax_pp_getfull (void); extern int sanei_umax_pp_scannerStatus (void); extern int sanei_umax_pp_probeScanner (int recover); extern char **sanei_parport_find_port (void); extern char **sanei_parport_find_device (void); extern int sanei_umax_pp_cmdSync (int cmd); extern void sanei_umax_pp_gamma (int *red, int *green, int *blue); sane-backends-1.0.27/backend/lexmark_low.c0000664000175000017500000053124512775312261015321 00000000000000/* lexmark-low.c: scanner-interface file for low Lexmark scanners. (C) 2005 Fred Odendaal (C) 2006-2013 Stéphane Voltz (C) 2010 "Torsten Houwaart" X74 support This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. **************************************************************************/ #undef BACKEND_NAME #define BACKEND_NAME lexmark_low #include "lexmark.h" #include "lexmark_sensors.c" #include "lexmark_models.c" /* numbre of ranges for offset */ #define OFFSET_RANGES 5 typedef enum { black = 0, white } region_type; #define HomeTolerance 32 #define LOBYTE(x) ((uint8_t)((x) & 0xFF)) #define HIBYTE(x) ((uint8_t)((x) >> 8)) /* Static low function proto-types */ static SANE_Status low_usb_bulk_write (SANE_Int devnum, SANE_Byte * cmd, size_t * size); static SANE_Status low_usb_bulk_read (SANE_Int devnum, SANE_Byte * buf, size_t * size); static SANE_Status low_write_all_regs (SANE_Int devnum, SANE_Byte * regs); static SANE_Bool low_is_home_line (Lexmark_Device * dev, unsigned char *buffer); static SANE_Status low_get_start_loc (SANE_Int resolution, SANE_Int * vert_start, SANE_Int * hor_start, SANE_Int offset, Lexmark_Device * dev); static void low_rewind (Lexmark_Device * dev, SANE_Byte * regs); static SANE_Status low_start_mvmt (SANE_Int devnum); static SANE_Status low_stop_mvmt (SANE_Int devnum); static SANE_Status low_clr_c6 (SANE_Int devnum); static SANE_Status low_simple_scan (Lexmark_Device * dev, SANE_Byte * regs, int xoffset, int pixels, int yoffset, int lines, SANE_Byte ** data); static void low_set_scan_area (SANE_Int res, SANE_Int tlx, SANE_Int tly, SANE_Int brx, SANE_Int bry, SANE_Int offset, SANE_Bool half_step, SANE_Byte * regs, Lexmark_Device * dev); /* Static Read Buffer Proto-types */ static SANE_Status read_buffer_init (Lexmark_Device * dev, int bytesperline); static SANE_Status read_buffer_free (Read_Buffer * rb); static size_t read_buffer_bytes_available (Read_Buffer * rb); static SANE_Status read_buffer_add_byte (Read_Buffer * rb, SANE_Byte * byte_pointer); static SANE_Status read_buffer_add_byte_gray (Read_Buffer * rb, SANE_Byte * byte_pointer); static SANE_Status read_buffer_add_bit_lineart (Read_Buffer * rb, SANE_Byte * byte_pointer, SANE_Byte threshold); static size_t read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer, size_t rqst_size); static SANE_Bool read_buffer_is_empty (Read_Buffer * rb); /* * RTS88XX START * * these rts88xx functions will be spin off in a separate lib * so that they can be reused. */ /* * registers helpers to avoid direct access */ static SANE_Bool rts88xx_is_color (SANE_Byte * regs) { if ((regs[0x2f] & 0x11) == 0x11) return SANE_TRUE; return SANE_FALSE; } static void rts88xx_set_gray_scan (SANE_Byte * regs) { regs[0x2f] = (regs[0x2f] & 0x0f) | 0x20; } #if 0 static void rts88xx_set_color_scan (SANE_Byte * regs) { regs[0x2f] = (regs[0x2f] & 0x0f) | 0x10; } #endif static void rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, SANE_Byte blue) { /* offset for odd pixels */ regs[0x02] = red; regs[0x03] = green; regs[0x04] = blue; /* offset for even pixels */ regs[0x05] = red; regs[0x06] = green; regs[0x07] = blue; } static void rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, SANE_Byte blue) { regs[0x08] = red; regs[0x09] = green; regs[0x0a] = blue; } /* set # of head moves per CIS read */ static int rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency) { regs[0x64] = (regs[0x64] & 0xf0) | (frequency & 0x0f); return 0; } /* * read one register at given index */ static SANE_Status rts88xx_read_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg) { SANE_Status status = SANE_STATUS_GOOD; unsigned char cmd[] = { 0x80, 0x00, 0x00, 0x01 }; size_t size; cmd[1] = index; size = 4; #ifdef FAKE_USB status = SANE_STATUS_GOOD; #else status = sanei_usb_write_bulk (devnum, cmd, &size); #endif if (status != SANE_STATUS_GOOD) { DBG (5, "rts88xx_read_reg: bulk write failed\n"); return status; } size = 1; #ifdef FAKE_USB status = SANE_STATUS_GOOD; #else status = sanei_usb_read_bulk (devnum, reg, &size); #endif if (status != SANE_STATUS_GOOD) { DBG (5, "rts88xx_read_reg: bulk read failed\n"); return status; } DBG (15, "rts88xx_read_reg: reg[0x%02x]=0x%02x\n", index, *reg); return status; } /* * write one register at given index */ static SANE_Status rts88xx_write_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg) { SANE_Status status = SANE_STATUS_GOOD; unsigned char cmd[] = { 0x88, 0x00, 0x00, 0x01 }; size_t size; cmd[1] = index; size = 4; #ifdef FAKE_USB status = SANE_STATUS_GOOD; #else status = sanei_usb_write_bulk (devnum, cmd, &size); #endif if (status != SANE_STATUS_GOOD) { DBG (5, "rts88xx_write_reg: bulk write failed\n"); return status; } size = 1; #ifdef FAKE_USB status = SANE_STATUS_GOOD; #else status = sanei_usb_write_bulk (devnum, reg, &size); #endif if (status != SANE_STATUS_GOOD) { DBG (5, "rts88xx_write_reg: bulk write failed\n"); return status; } DBG (15, "rts88xx_write_reg: reg[0x%02x]=0x%02x\n", index, *reg); return status; } /* * write length consecutive registers, starting at index * register 0xb3 is never wrote in bulk register write, so we split * write if it belongs to the register set sent */ static SANE_Status rts88xx_write_regs (SANE_Int devnum, SANE_Int start, SANE_Byte * source, SANE_Int length) { size_t size = 0; /* when writing several registers at a time, we avoid writing 0xb3 register */ if ((start + length > 0xb3) && (length > 1)) { size = 0xb3 - start; if (low_usb_bulk_write (devnum, source, &size) != SANE_STATUS_GOOD) { DBG (5, "rts88xx_write_regs : write registers part 1 failed ...\n"); return SANE_STATUS_IO_ERROR; } /* skip 0xB3 register */ size++; start = 0xb4; source = source + size; } size = length - size; if (low_usb_bulk_write (devnum, source, &size) != SANE_STATUS_GOOD) { DBG (5, "rts88xx_write_regs : write registers part 2 failed ...\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* * reads 'needed' bytes of scanned data into 'data'. Actual number of bytes get * is retruned in 'size' */ static SANE_Status rts88xx_read_data (SANE_Int devnum, size_t needed, SANE_Byte * data, size_t * size) { SANE_Byte read_cmd[] = { 0x91, 0x00, 0x00, 0x00 }; size_t cmd_size; SANE_Status status = SANE_STATUS_GOOD; /* this block would deserve to be a function */ if (needed > MAX_XFER_SIZE) *size = MAX_XFER_SIZE; else *size = needed; read_cmd[3] = (*size) & 0xff; read_cmd[2] = (*size >> 8) & 0xff; read_cmd[1] = (*size >> 16) & 0xff; /* send header for 'get scanned data' */ cmd_size = 4; status = low_usb_bulk_write (devnum, read_cmd, &cmd_size); if (status != SANE_STATUS_GOOD) { *size = 0; DBG (5, "rts88xx_read_data : header sending failed ...\n"); return status; } /* get actual scanned data */ status = low_usb_bulk_read (devnum, data, size); if (status != SANE_STATUS_GOOD) { *size = 0; DBG (5, "rts88xx_read_data : data reading failed ...\n"); } return status; } /* starts scan by sending color depth, stopping head, the starting it */ static SANE_Status rts88xx_commit (SANE_Int devnum, SANE_Byte depth) { SANE_Status status; SANE_Byte reg; DBG (2, "rts88xx_commit: start\n"); /* send color depth depth ?? * X1100 -> 0x0f * X1100/B2 -> 0x0d * X1200 -> 0x01 */ reg = depth; rts88xx_write_reg (devnum, 0x2c, ®); /* stop before starting */ low_stop_mvmt (devnum); /* effective start */ status = low_start_mvmt (devnum); DBG (2, "rts88xx_commit: end\n"); return status; } /* * RTS88XX END */ /* * sets the scanner idle */ static SANE_Status lexmark_low_set_idle (SANE_Int devnum) { SANE_Byte regs[14] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60 }; if (rts88xx_write_regs (devnum, 16, regs, 14) != SANE_STATUS_GOOD) { DBG (5, "lexmark_low_set_idle : register write failed ...\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* wake up scanner */ #if 0 static SANE_Status lexmark_low_wake_up (Lexmark_Device * dev) { SANE_Byte regs[5] = { 0x12, 0x14, 0x16, 0x18, 0x1a }; SANE_Byte values[5] = { 0x0f, 0x00, 0x07, 0x00, 0x00 }; int i; /* send the wake-up sequence, one reg at at time */ for (i = 0; i < 10; i++) { if (rts88xx_write_reg (dev->devnum, regs[i], values + i) != SANE_STATUS_GOOD) { DBG (5, "lexmark_low_wake_up : register write pass %d failed ...\n", i); return SANE_STATUS_IO_ERROR; } } return SANE_STATUS_GOOD; } #endif /** * */ #ifdef DEEP_DEBUG static void write_pnm_file (char *title, int pixels, int lines, int color, unsigned char *data) { FILE *fdbg; int x, y; fdbg = fopen (title, "wb"); if (fdbg == NULL) return; if (color) { fprintf (fdbg, "P6\n%d %d\n255\n", pixels, lines); for (y = 0; y < lines; y++) { for (x = 0; x < pixels; x += 2) { fputc (data[y * pixels * 3 + x + 1], fdbg); fputc (data[y * pixels * 3 + x + 1 + pixels], fdbg); fputc (data[y * pixels * 3 + x + 1 + pixels * 2], fdbg); fputc (data[y * pixels * 3 + x], fdbg); fputc (data[y * pixels * 3 + x + pixels], fdbg); fputc (data[y * pixels * 3 + x + pixels * 2], fdbg); } } } else { fprintf (fdbg, "P5\n%d %d\n255\n", pixels, lines); fwrite (data, pixels, lines, fdbg); } fclose (fdbg); } #endif /* * mid level hardware functions */ /* * model init */ SANE_Status sanei_lexmark_low_init (Lexmark_Device * dev) { int i; SANE_Status status; DBG_INIT (); status = SANE_STATUS_UNSUPPORTED; DBG (2, "low_init: start\n"); /* clear all registers first */ for (i = 0; i < 255; i++) { dev->shadow_regs[i] = 0; } /* set up per model constant values */ dev->shadow_regs[0xf3] = 0xf8; dev->shadow_regs[0xf4] = 0x7f; switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x00] = 0x04; dev->shadow_regs[0x01] = 0x43; dev->shadow_regs[0x0b] = 0x70; dev->shadow_regs[0x12] = 0x0f; dev->shadow_regs[0x16] = 0x07; dev->shadow_regs[0x1d] = 0x20; dev->shadow_regs[0x28] = 0xe0; dev->shadow_regs[0x29] = 0xe3; dev->shadow_regs[0x2a] = 0xeb; dev->shadow_regs[0x2b] = 0x0d; dev->shadow_regs[0x2e] = 0x40; dev->shadow_regs[0x2e] = 0x86; dev->shadow_regs[0x2f] = 0x01; dev->shadow_regs[0x30] = 0x48; dev->shadow_regs[0x31] = 0x06; dev->shadow_regs[0x33] = 0x01; dev->shadow_regs[0x34] = 0x50; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x50; dev->shadow_regs[0x37] = 0x01; dev->shadow_regs[0x38] = 0x50; dev->shadow_regs[0x3a] = 0x20; dev->shadow_regs[0x3c] = 0x88; dev->shadow_regs[0x3d] = 0x08; dev->shadow_regs[0x65] = 0x80; dev->shadow_regs[0x66] = 0x64; dev->shadow_regs[0x6c] = 0xc8; dev->shadow_regs[0x72] = 0x1a; dev->shadow_regs[0x74] = 0x23; dev->shadow_regs[0x75] = 0x03; dev->shadow_regs[0x79] = 0x40; dev->shadow_regs[0x7A] = 0x01; dev->shadow_regs[0x8d] = 0x01; dev->shadow_regs[0x8e] = 0x60; dev->shadow_regs[0x8f] = 0x80; dev->shadow_regs[0x93] = 0x02; dev->shadow_regs[0x94] = 0x0e; dev->shadow_regs[0xa3] = 0xcc; dev->shadow_regs[0xa4] = 0x27; dev->shadow_regs[0xa5] = 0x24; dev->shadow_regs[0xc2] = 0x80; dev->shadow_regs[0xc3] = 0x01; dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x0a; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x0a; dev->shadow_regs[0xe2] = 0x70; dev->shadow_regs[0xe3] = 0x17; dev->shadow_regs[0xf3] = 0xe0; dev->shadow_regs[0xf4] = 0xff; dev->shadow_regs[0xf5] = 0x01; status = SANE_STATUS_GOOD; break; case X1100_B2_SENSOR: dev->shadow_regs[0x01] = 0x43; dev->shadow_regs[0x0b] = 0x70; dev->shadow_regs[0x11] = 0x01; dev->shadow_regs[0x12] = 0x0f; dev->shadow_regs[0x13] = 0x01; dev->shadow_regs[0x15] = 0x01; dev->shadow_regs[0x16] = 0x0f; dev->shadow_regs[0x1d] = 0x20; dev->shadow_regs[0x28] = 0xeb; dev->shadow_regs[0x29] = 0xee; dev->shadow_regs[0x2a] = 0xf7; dev->shadow_regs[0x2b] = 0x01; dev->shadow_regs[0x2e] = 0x86; dev->shadow_regs[0x30] = 0x48; dev->shadow_regs[0x33] = 0x01; dev->shadow_regs[0x3a] = 0x20; dev->shadow_regs[0x3b] = 0x37; dev->shadow_regs[0x3c] = 0x88; dev->shadow_regs[0x3d] = 0x08; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x72] = 0x05; dev->shadow_regs[0x74] = 0x0e; dev->shadow_regs[0x8b] = 0xff; dev->shadow_regs[0x8c] = 0x02; dev->shadow_regs[0x8d] = 0x01; dev->shadow_regs[0x8e] = 0x60; dev->shadow_regs[0x8f] = 0x80; dev->shadow_regs[0x94] = 0x0e; dev->shadow_regs[0xa3] = 0xcc; dev->shadow_regs[0xa4] = 0x27; dev->shadow_regs[0xa5] = 0x24; dev->shadow_regs[0xb0] = 0xb2; dev->shadow_regs[0xb2] = 0x04; dev->shadow_regs[0xc2] = 0x80; dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x3b; dev->shadow_regs[0xed] = 0xc2; dev->shadow_regs[0xee] = 0x02; status = SANE_STATUS_GOOD; break; case X1100_2C_SENSOR: dev->shadow_regs[0x00] = 0x00; dev->shadow_regs[0x01] = 0x43; dev->shadow_regs[0x0b] = 0x70; dev->shadow_regs[0x0c] = 0x28; dev->shadow_regs[0x0d] = 0xa4; dev->shadow_regs[0x11] = 0x01; dev->shadow_regs[0x12] = 0x0f; dev->shadow_regs[0x13] = 0x01; dev->shadow_regs[0x15] = 0x01; dev->shadow_regs[0x16] = 0x0f; dev->shadow_regs[0x17] = 0x00; dev->shadow_regs[0x1d] = 0x20; dev->shadow_regs[0x28] = 0xf5; dev->shadow_regs[0x29] = 0xf7; dev->shadow_regs[0x2a] = 0xf5; dev->shadow_regs[0x2b] = 0x17; dev->shadow_regs[0x2d] = 0x41; dev->shadow_regs[0x2e] = 0x86; dev->shadow_regs[0x2f] = 0x11; dev->shadow_regs[0x30] = 0x48; dev->shadow_regs[0x31] = 0x01; dev->shadow_regs[0x33] = 0x01; dev->shadow_regs[0x34] = 0x50; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x50; dev->shadow_regs[0x37] = 0x01; dev->shadow_regs[0x38] = 0x50; dev->shadow_regs[0x3a] = 0x20; dev->shadow_regs[0x3b] = 0x37; dev->shadow_regs[0x3c] = 0x88; dev->shadow_regs[0x3d] = 0x08; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x47] = 0x01; dev->shadow_regs[0x48] = 0x1a; dev->shadow_regs[0x49] = 0x5b; dev->shadow_regs[0x4a] = 0x1b; dev->shadow_regs[0x4b] = 0x5b; dev->shadow_regs[0x4c] = 0x05; dev->shadow_regs[0x4d] = 0x3f; dev->shadow_regs[0x60] = 0x2f; dev->shadow_regs[0x61] = 0x36; dev->shadow_regs[0x62] = 0x30; dev->shadow_regs[0x63] = 0x36; dev->shadow_regs[0x65] = 0x80; dev->shadow_regs[0x66] = 0x64; dev->shadow_regs[0x6c] = 0xc8; dev->shadow_regs[0x6d] = 0x00; dev->shadow_regs[0x72] = 0x35; dev->shadow_regs[0x74] = 0x4e; dev->shadow_regs[0x75] = 0x03; dev->shadow_regs[0x79] = 0x40; dev->shadow_regs[0x7a] = 0x01; dev->shadow_regs[0x85] = 0x02; dev->shadow_regs[0x86] = 0x33; dev->shadow_regs[0x87] = 0x0f; dev->shadow_regs[0x88] = 0x24; dev->shadow_regs[0x8b] = 0xff; dev->shadow_regs[0x8c] = 0x02; dev->shadow_regs[0x8d] = 0x01; dev->shadow_regs[0x8e] = 0x60; dev->shadow_regs[0x8f] = 0x80; dev->shadow_regs[0x91] = 0x19; dev->shadow_regs[0x92] = 0x20; dev->shadow_regs[0x93] = 0x02; dev->shadow_regs[0x94] = 0x0e; dev->shadow_regs[0xa3] = 0x0d; dev->shadow_regs[0xa4] = 0x5e; dev->shadow_regs[0xa5] = 0x23; dev->shadow_regs[0xb0] = 0x2c; dev->shadow_regs[0xb1] = 0x07; dev->shadow_regs[0xb2] = 0x04; dev->shadow_regs[0xc2] = 0x80; dev->shadow_regs[0xc3] = 0x01; dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x0a; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x3b; dev->shadow_regs[0xca] = 0x0a; dev->shadow_regs[0xe2] = 0xf8; dev->shadow_regs[0xe3] = 0x2a; status = SANE_STATUS_GOOD; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x01] = 0x43; dev->shadow_regs[0x11] = 0x01; dev->shadow_regs[0x12] = 0x0f; dev->shadow_regs[0x13] = 0x01; dev->shadow_regs[0x15] = 0x01; dev->shadow_regs[0x16] = 0x0f; dev->shadow_regs[0x17] = 0x00; dev->shadow_regs[0x1d] = 0x20; dev->shadow_regs[0x28] = 0xf5; dev->shadow_regs[0x29] = 0xf7; dev->shadow_regs[0x2a] = 0xf5; dev->shadow_regs[0x2b] = 0x17; dev->shadow_regs[0x2d] = 0x41; dev->shadow_regs[0x2e] = 0x86; dev->shadow_regs[0x30] = 0x48; dev->shadow_regs[0x31] = 0x01; dev->shadow_regs[0x33] = 0x01; dev->shadow_regs[0x34] = 0x50; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x50; dev->shadow_regs[0x37] = 0x01; dev->shadow_regs[0x38] = 0x50; dev->shadow_regs[0x3c] = 0x88; dev->shadow_regs[0x3d] = 0x08; dev->shadow_regs[0x66] = 0x64; dev->shadow_regs[0x67] = 0x00; dev->shadow_regs[0x6c] = 0xc8; dev->shadow_regs[0x6d] = 0x00; dev->shadow_regs[0x72] = 0x35; dev->shadow_regs[0x74] = 0x4e; dev->shadow_regs[0x75] = 0x03; dev->shadow_regs[0x7a] = 0x01; dev->shadow_regs[0x93] = 0x0a; dev->shadow_regs[0x94] = 0x0e; dev->shadow_regs[0xc3] = 0x01; dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x0a; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x3b; dev->shadow_regs[0xca] = 0x0a; dev->shadow_regs[0xe2] = 0xf8; dev->shadow_regs[0xe3] = 0x2a; status = SANE_STATUS_GOOD; break; case A920_SENSOR: dev->shadow_regs[0x01] = 0x43; dev->shadow_regs[0x0b] = 0x70; dev->shadow_regs[0x0c] = 0x28; dev->shadow_regs[0x0d] = 0xa4; dev->shadow_regs[0x11] = 0x01; dev->shadow_regs[0x12] = 0x0f; dev->shadow_regs[0x13] = 0x01; dev->shadow_regs[0x15] = 0x01; dev->shadow_regs[0x16] = 0x07; dev->shadow_regs[0x1d] = 0x20; dev->shadow_regs[0x28] = 0xf5; dev->shadow_regs[0x29] = 0xf7; dev->shadow_regs[0x2a] = 0xf5; dev->shadow_regs[0x2b] = 0x17; dev->shadow_regs[0x2e] = 0x86; dev->shadow_regs[0x30] = 0x48; dev->shadow_regs[0x31] = 0x01; dev->shadow_regs[0x33] = 0x01; dev->shadow_regs[0x3a] = 0x20; dev->shadow_regs[0x3b] = 0x37; dev->shadow_regs[0x3c] = 0x88; dev->shadow_regs[0x3d] = 0x08; dev->shadow_regs[0x47] = 0x21; dev->shadow_regs[0x48] = 0x1a; dev->shadow_regs[0x49] = 0x5b; dev->shadow_regs[0x4a] = 0x1b; dev->shadow_regs[0x4b] = 0x5b; dev->shadow_regs[0x4c] = 0x05; dev->shadow_regs[0x4d] = 0x3f; dev->shadow_regs[0x65] = 0x80; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x89] = 0xf5; dev->shadow_regs[0x8d] = 0x01; dev->shadow_regs[0x8e] = 0x60; dev->shadow_regs[0x8f] = 0x80; dev->shadow_regs[0x94] = 0x0e; dev->shadow_regs[0xa3] = 0x0d; dev->shadow_regs[0xa4] = 0x5e; dev->shadow_regs[0xa5] = 0x23; dev->shadow_regs[0xb0] = 0x2c; dev->shadow_regs[0xb1] = 0x0f; dev->shadow_regs[0xc2] = 0x80; dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc8] = 0x04; status = SANE_STATUS_GOOD; break; case X1200_SENSOR: dev->shadow_regs[0x01] = 0x43; dev->shadow_regs[0x0b] = 0x70; dev->shadow_regs[0x0c] = 0x28; dev->shadow_regs[0x0d] = 0xa4; dev->shadow_regs[0x11] = 0x01; dev->shadow_regs[0x12] = 0x0f; dev->shadow_regs[0x13] = 0x01; dev->shadow_regs[0x15] = 0x01; dev->shadow_regs[0x16] = 0x0f; dev->shadow_regs[0x1d] = 0x20; dev->shadow_regs[0x28] = 0xe9; dev->shadow_regs[0x29] = 0xeb; dev->shadow_regs[0x2a] = 0xe9; dev->shadow_regs[0x2b] = 0x0b; dev->shadow_regs[0x2d] = 0x01; dev->shadow_regs[0x2e] = 0x86; dev->shadow_regs[0x2f] = 0x11; dev->shadow_regs[0x30] = 0x48; dev->shadow_regs[0x33] = 0x01; dev->shadow_regs[0x34] = 0x50; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x50; dev->shadow_regs[0x37] = 0x01; dev->shadow_regs[0x38] = 0x50; dev->shadow_regs[0x3a] = 0x20; dev->shadow_regs[0x3b] = 0x37; dev->shadow_regs[0x3c] = 0x88; dev->shadow_regs[0x3d] = 0x08; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x47] = 0x01; dev->shadow_regs[0x48] = 0x1a; dev->shadow_regs[0x49] = 0x5b; dev->shadow_regs[0x4a] = 0x1b; dev->shadow_regs[0x4b] = 0x5b; dev->shadow_regs[0x4c] = 0x05; dev->shadow_regs[0x4d] = 0x3f; dev->shadow_regs[0x60] = 0x12; dev->shadow_regs[0x62] = 0x81; dev->shadow_regs[0x63] = 0x03; dev->shadow_regs[0x65] = 0x80; dev->shadow_regs[0x66] = 0x64; dev->shadow_regs[0x6c] = 0xc8; dev->shadow_regs[0x72] = 0x1e; dev->shadow_regs[0x74] = 0x3c; dev->shadow_regs[0x75] = 0x03; dev->shadow_regs[0x79] = 0x40; dev->shadow_regs[0x7a] = 0x01; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x1e; dev->shadow_regs[0x87] = 0x39; dev->shadow_regs[0x8b] = 0xff; dev->shadow_regs[0x8c] = 0x02; dev->shadow_regs[0x8d] = 0x01; dev->shadow_regs[0x8e] = 0x60; dev->shadow_regs[0x8f] = 0x80; dev->shadow_regs[0x92] = 0x92; dev->shadow_regs[0x93] = 0x02; dev->shadow_regs[0x94] = 0x0e; dev->shadow_regs[0xa3] = 0x0d; dev->shadow_regs[0xa4] = 0x5e; dev->shadow_regs[0xa5] = 0x23; dev->shadow_regs[0xb0] = 0x2c; dev->shadow_regs[0xb1] = 0x07; dev->shadow_regs[0xb2] = 0x04; dev->shadow_regs[0xc2] = 0x80; dev->shadow_regs[0xc3] = 0x01; dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x0a; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x3b; dev->shadow_regs[0xca] = 0x0a; dev->shadow_regs[0xe2] = 0xf8; dev->shadow_regs[0xe3] = 0x2a; dev->shadow_regs[0xf3] = 0xff; dev->shadow_regs[0xf4] = 0x0f; break; } DBG (5, "sanei_lexmark_low_init: init done for model %s/%s\n", dev->model.model, dev->model.name); DBG (2, "low_init: done\n"); return status; } void sanei_lexmark_low_destroy (Lexmark_Device * dev) { /* free the read buffer */ if (dev->read_buffer != NULL) read_buffer_free (dev->read_buffer); } SANE_Status low_usb_bulk_write (SANE_Int devnum, SANE_Byte * cmd, size_t * size) { SANE_Status status; size_t cmd_size; cmd_size = *size; #ifdef FAKE_USB status = SANE_STATUS_GOOD; #else status = sanei_usb_write_bulk (devnum, cmd, size); #endif if (status != SANE_STATUS_GOOD) { DBG (5, "low_usb_bulk_write: returned %s (size = %lu, expected %lu)\n", sane_strstatus (status), (u_long) * size, (u_long) cmd_size); /* F.O. should reset the pipe here... */ } return status; } SANE_Status low_usb_bulk_read (SANE_Int devnum, SANE_Byte * buf, size_t * size) { SANE_Status status; size_t exp_size; exp_size = *size; #ifdef FAKE_USB status = SANE_STATUS_GOOD; #else status = sanei_usb_read_bulk (devnum, buf, size); #endif if (status != SANE_STATUS_GOOD) { DBG (5, "low_usb_bulk_read: returned %s (size = %lu, expected %lu)\n", sane_strstatus (status), (u_long) * size, (u_long) exp_size); /* F.O. should reset the pipe here... */ } DBG (7, "low_usb_bulk_read: returned size = %lu (required %lu)\n", (u_long) * size, (u_long) exp_size); return status; } SANE_Status low_start_mvmt (SANE_Int devnum) { SANE_Status status; SANE_Byte reg; reg = 0x68; rts88xx_write_reg (devnum, 0xb3, ®); status = rts88xx_write_reg (devnum, 0xb3, ®); return status; } SANE_Status low_stop_mvmt (SANE_Int devnum) { SANE_Status status; SANE_Byte reg; /* Stop scanner - clear reg 0xb3: */ reg = 0x02; rts88xx_write_reg (devnum, 0xb3, ®); rts88xx_write_reg (devnum, 0xb3, ®); reg = 0x00; rts88xx_write_reg (devnum, 0xb3, ®); status = rts88xx_write_reg (devnum, 0xb3, ®); return status; } SANE_Status low_clr_c6 (SANE_Int devnum) { SANE_Status status; SANE_Byte reg; /* Clear register 0xC6 */ /* cmd_size = 0x05; return low_usb_bulk_write (devnum, clearC6_command_block, &cmd_size); */ reg = 0x00; status = rts88xx_write_reg (devnum, 0xc6, ®); return status; } /* stops current scan */ static SANE_Status low_cancel (SANE_Int devnum) { SANE_Status status; DBG (2, "low_cancel: start\n"); status = low_stop_mvmt (devnum); if (status != SANE_STATUS_GOOD) return status; status = low_clr_c6 (devnum); if (status != SANE_STATUS_GOOD) return status; DBG (2, "low_cancel: end.\n"); return status; } static SANE_Status low_start_scan (SANE_Int devnum, SANE_Byte * regs) { SANE_Status status; DBG (2, "low_start_scan: start\n"); /* writes registers to scanner */ regs[0x32] = 0x00; status = low_write_all_regs (devnum, regs); if (status != SANE_STATUS_GOOD) return status; regs[0x32] = 0x40; status = low_write_all_regs (devnum, regs); if (status != SANE_STATUS_GOOD) return status; /* Stop scanner - clear reg 0xb3: */ /* status = low_stop_mvmt (devnum); if (status != SANE_STATUS_GOOD) return status; */ /* then start */ status = rts88xx_commit (devnum, regs[0x2c]); DBG (2, "low_start_scan: end.\n"); return status; } /* wait for scan data being available */ static SANE_Status low_poll_data (SANE_Int devnum) { SANE_Status status; int loops = 0; size_t size; static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; SANE_Byte result[3]; SANE_Word count; /* Poll the available byte count until not 0 */ while (loops < 1000) { /* 10 ms sleep */ usleep (10000); /* as stated in sanei_lexmark_low_search_home_bwd, we read * available data count twice */ size = 4; status = low_usb_bulk_write (devnum, command4_block, &size); if (status != SANE_STATUS_GOOD) return status; size = 0x3; status = low_usb_bulk_read (devnum, result, &size); if (status != SANE_STATUS_GOOD) return status; size = 4; /* read availbale data size again */ status = low_usb_bulk_write (devnum, command4_block, &size); if (status != SANE_STATUS_GOOD) return status; size = 0x3; status = low_usb_bulk_read (devnum, result, &size); if (status != SANE_STATUS_GOOD) return status; count = result[0] + (result[1] << 8) + (result[2] << 16); if (count != 0) { DBG (15, "low_poll_data: %d bytes available\n", count); return SANE_STATUS_GOOD; } loops++; } return SANE_STATUS_IO_ERROR; } /** * do a simple scan with the given registers. data buffer is allocated within * the function */ static SANE_Status low_simple_scan (Lexmark_Device * dev, SANE_Byte * regs, int xoffset, int pixels, int yoffset, int lines, SANE_Byte ** data) { SANE_Status status = SANE_STATUS_GOOD; static SANE_Byte reg; size_t size, read, needed; int i, bpl, yend; DBG (2, "low_simple_scan: start\n"); DBG (15, "low_simple_scan: x=%d, pixels=%d (ex=%d), y=%d, lines=%d\n", xoffset, pixels, xoffset + pixels * regs[0x7a], yoffset, lines); /* set up registers */ regs[0x60] = LOBYTE (yoffset); regs[0x61] = HIBYTE (yoffset); yend = yoffset + lines; if ((dev->model.motor_type == A920_MOTOR || dev->model.motor_type == X74_MOTOR) && rts88xx_is_color (regs) && dev->val[OPT_RESOLUTION].w == 600) yend *= 2; regs[0x62] = LOBYTE (yend); regs[0x63] = HIBYTE (yend); regs[0x66] = LOBYTE (xoffset); regs[0x67] = HIBYTE (xoffset); regs[0x6c] = LOBYTE (xoffset + pixels * regs[0x7a]); regs[0x6d] = HIBYTE (xoffset + pixels * regs[0x7a]); /* allocate memory */ if (rts88xx_is_color (regs)) bpl = 3 * pixels; else bpl = pixels; *data = (SANE_Byte *) malloc (bpl * lines); if (*data == NULL) { DBG (2, "low_simple_scan: failed to allocate %d bytes !\n", bpl * lines); return SANE_STATUS_NO_MEM; } /* start scan */ status = low_cancel (dev->devnum); if (status != SANE_STATUS_GOOD) return status; status = low_start_scan (dev->devnum, regs); if (status != SANE_STATUS_GOOD) return status; /* wait for data */ status = low_poll_data (dev->devnum); if (status != SANE_STATUS_GOOD) { DBG (1, "low_simple_scan: time-out while waiting for data.\n"); return status; } /* data reading loop */ needed = bpl * lines; DBG (1, "low_simple_scan: bpl=%d, lines=%d, needed=%lu.\n", bpl, lines, (u_long) needed); read = 0; do { /* this block would deserve to be a function */ status = rts88xx_read_data (dev->devnum, needed - read, (*data) + read, &size); if (status != SANE_STATUS_GOOD) return status; read += size; } while (read < needed); /* if needed, wait for motor to stop */ if (regs[0xc3] & 0x80) { i = 0; do { if (rts88xx_read_reg (dev->devnum, 0xb3, ®) != SANE_STATUS_GOOD) { DBG (5, "low_simple_scan: register read failed ...\n"); return SANE_STATUS_IO_ERROR; } usleep (100000); i++; } while ((reg & 0x08) && (i < 100)); if (reg & 0x08) { DBG (5, "low_simple_scan : timeout waiting for motor to stop ...\n"); return SANE_STATUS_IO_ERROR; } } /* stop scan */ status = low_cancel (dev->devnum); if (status != SANE_STATUS_GOOD) { DBG (1, "low_simple_scan: cancel failed.\n"); return status; } DBG (2, "low_simple_scan: end.\n"); return status; } /* * open USB device ,read initial registers values and probe sensor */ SANE_Status sanei_lexmark_low_open_device (Lexmark_Device * dev) { /* This function calls the Sane Interface to open this usb device. It also needlessly does what the Windows driver does and reads the entire register set - this may be removed. */ SANE_Status result; static SANE_Byte command_block[] = { 0x80, 0, 0x00, 0xFF }; size_t size; SANE_Byte variant = 0; SANE_Byte shadow_regs[255]; int sx, ex; int sy, ey; int i; char msg[2048]; #ifdef FAKE_USB result = SANE_STATUS_GOOD; shadow_regs[0x00] = 0x91; shadow_regs[0xb0] = 0x2c; shadow_regs[0x10] = 0x97; shadow_regs[0x10] = 0x87; shadow_regs[0xf3] = 0xf8; shadow_regs[0xf4] = 0x7f; #else result = sanei_usb_open (dev->sane.name, &(dev->devnum)); #endif DBG (2, "sanei_lexmark_low_open_device: devnum=%d\n", dev->devnum); size = 4; low_usb_bulk_write (dev->devnum, command_block, &size); size = 0xFF; memset (shadow_regs, 0, sizeof (shadow_regs)); low_usb_bulk_read (dev->devnum, shadow_regs, &size); if (DBG_LEVEL > 2) { DBG (2, "sanei_lexmark_low_open_device: initial registers values\n"); for (i = 0; i < 255; i++) { sprintf (msg + i * 5, "0x%02x ", shadow_regs[i]); } DBG (3, "%s\n", msg); } /* it seems that at first read after reset, registers hold information * about the scanner. Register 0x00 is overwritten with 0, so only first read * after USB plug-in gives this value */ if (shadow_regs[0] == 0x91) { sx = shadow_regs[0x67] * 256 + shadow_regs[0x66]; ex = shadow_regs[0x6d] * 256 + shadow_regs[0x6c]; DBG (7, "startx=%d, endx=%d, pixels=%d, coef=%d, r2f=0x%02x\n", sx, ex, ex - sx, dev->shadow_regs[0x7a], shadow_regs[0x2f]); sy = shadow_regs[0x61] * 256 + shadow_regs[0x60]; ey = shadow_regs[0x63] * 256 + shadow_regs[0x62]; DBG (7, "starty=%d, endy=%d, lines=%d\n", sy, ey, ey - sy); } /* we use register 0xb0 to identify details about models */ /* this register isn't overwritten during normal operation */ if (shadow_regs[0xb0] == 0x2c && dev->model.sensor_type == X1100_B2_SENSOR) { variant = shadow_regs[0xb0]; } /* now the same with register 0x10 */ /* which most likely signals USB2.0/USB1.1 */ if ((dev->model.sensor_type == X1200_SENSOR) && (shadow_regs[0x10] == 0x97)) { variant = shadow_regs[0x10]; } /* if find a case where default model given is inappropriate, reassign it * since we have now the informations to get the real one. * We could avoid this if attach() did open and read registers, not init */ if (variant != 0) { DBG (3, "sanei_lexmark_low_open_device: reassign model/sensor for variant 0x%02x\n", variant); sanei_lexmark_low_assign_model (dev, dev->sane.name, dev->model.vendor_id, dev->model.product_id, variant); /* since model has changed, run init again */ sanei_lexmark_low_init (dev); } DBG (2, "sanei_lexmark_low_open_device: end\n"); return result; } void sanei_lexmark_low_close_device (Lexmark_Device * dev) { /* put scanner in idle state */ lexmark_low_set_idle (dev->devnum); /* This function calls the Sane USB library to close this usb device */ #ifndef FAKE_USB sanei_usb_close (dev->devnum); #endif return; } /* This function writes the contents of the given registers to the scanner. */ SANE_Status low_write_all_regs (SANE_Int devnum, SANE_Byte * regs) { int i; SANE_Status status; size_t size; static SANE_Byte command_block1[0xb7]; static SANE_Byte command_block2[0x4f]; command_block1[0] = 0x88; command_block1[1] = 0x00; command_block1[2] = 0x00; command_block1[3] = 0xb3; for (i = 0; i < 0xb3; i++) { command_block1[i + 4] = regs[i]; } command_block2[0] = 0x88; command_block2[1] = 0xb4; command_block2[2] = 0x00; command_block2[3] = 0x4b; for (i = 0; i < 0x4b; i++) { command_block2[i + 4] = regs[i + 0xb4]; } size = 0xb7; #ifdef DEEP_DEBUG fprintf (stderr, "write_all(0x00,255)="); for (i = 0; i < 255; i++) { fprintf (stderr, "0x%02x ", regs[i]); } fprintf (stderr, "\n"); #endif status = low_usb_bulk_write (devnum, command_block1, &size); if (status != SANE_STATUS_GOOD) return status; size = 0x4f; status = low_usb_bulk_write (devnum, command_block2, &size); if (status != SANE_STATUS_GOOD) return status; return SANE_STATUS_GOOD; } SANE_Bool low_is_home_line (Lexmark_Device * dev, unsigned char *buffer) { /* This function assumes the buffer has a size of 2500 bytes.It is destructive to the buffer. Here is what it does: Go through the buffer finding low and high values, which are computed by comparing to the average: average = (lowest value + highest value)/2 High bytes are changed to 0xFF (white), lower or equal bytes are changed to 0x00 (black),so that the buffer only contains white (0xFF) or black (0x00) values. Next, we go through the buffer. We use a tolerance of 5 bytes on each end of the buffer and check a region from bytes 5 to 2495. We start assuming we are in a white region and look for the start of a black region. We save this index as the transition from white to black. We also save where we change from black back to white. We continue checking for transitions until the end of the check region. If we don't have exactly two transitions when we reach the end we return SANE_FALSE. The final check compares the transition indices to the nominal values plus or minus the tolerence. For the first transition (white to black index) the value must lie in the range 1235-30 (1205) to 1235+30 (1265). For the second transition (black to white) the value must lie in the range 1258-30 (1228) to 1258+30 (1288). If the indices are out of range we return SANE_FALSE. Otherwise, we return SANE_TRUE. */ unsigned char max_byte = 0; unsigned char min_byte = 0xFF; unsigned char average; int i; int home_point1; int home_point2; region_type region; int transition_counter; int index1 = 0; int index2 = 0; int low_range, high_range; #ifdef DEEP_DEBUG static int numero = 0; char titre[80]; FILE *trace = NULL; sprintf (titre, "lgn%03d.pnm", numero); trace = fopen (titre, "wb"); if (trace) { fprintf (trace, "P5\n2500 1\n255\n"); fwrite (buffer, 2500, 1, trace); fclose (trace); } numero++; #endif DBG (15, "low_is_home_line: start\n"); /* Find the max and the min */ for (i = 0; i < 2500; i++) { if (*(buffer + i) > max_byte) max_byte = *(buffer + i); if (*(buffer + i) < min_byte) min_byte = *(buffer + i); } /* The average */ average = ((max_byte + min_byte) / 2); /* Set bytes as white (0xFF) or black (0x00) */ for (i = 0; i < 2500; i++) { if (*(buffer + i) > average) *(buffer + i) = 0xFF; else *(buffer + i) = 0x00; } region = white; transition_counter = 0; /* Go through the check region - bytes 5 to 2495 */ /* XXX STEF XXX shrink the area to where the dot should be * +-100 around the 1250 expected location */ for (i = 1150; i <= 1350; i++) { /* Check for transition to black */ if ((region == white) && (*(buffer + i) == 0)) { if (transition_counter < 2) { region = black; index1 = i; transition_counter++; } else { DBG (15, "low_is_home_line: no transition to black \n"); return SANE_FALSE; } } /* Check for transition to white */ else if ((region == black) && (*(buffer + i) == 0xFF)) { if (transition_counter < 2) { region = white; index2 = i; transition_counter++; } else { DBG (15, "low_is_home_line: no transition to white \n"); return SANE_FALSE; } } } /* Check that the number of transitions is 2 */ if (transition_counter != 2) { DBG (15, "low_is_home_line: transitions!=2 (%d)\n", transition_counter); return SANE_FALSE; } /* Check that the 1st index is in range */ home_point1 = dev->model.HomeEdgePoint1; low_range = home_point1 - HomeTolerance; high_range = home_point1 + HomeTolerance; if ((index1 < low_range) || (index1 > high_range)) { DBG (15, "low_is_home_line: index1=%d out of range\n", index1); return SANE_FALSE; } /* Check that the 2nd index is in range */ home_point2 = dev->model.HomeEdgePoint2; low_range = home_point2 - HomeTolerance; high_range = home_point2 + HomeTolerance; if ((index2 < low_range) || (index2 > high_range)) { DBG (15, "low_is_home_line: index2=%d out of range.\n", index2); return SANE_FALSE; } /* We made it this far, so its a good home line. Return True */ DBG (15, "low_is_home_line: success\n"); return SANE_TRUE; } void sanei_lexmark_low_move_fwd (SANE_Int distance, Lexmark_Device * dev, SANE_Byte * regs) { /* This function moves the scan head forward with the highest vertical resolution of 1200dpi. The distance moved is given by the distance parameter. As an example, given a distance parameter of 600, the scan head will move 600/1200", or 1/2" forward. */ static SANE_Byte pollstopmoving_command_block[] = { 0x80, 0xb3, 0x00, 0x01 }; size_t cmd_size; SANE_Int devnum; SANE_Bool scan_head_moving; SANE_Byte read_result; DBG (2, "sanei_lexmark_low_move_fwd: \n"); devnum = dev->devnum; /* registers set-up */ regs[0x2c] = 0x00; regs[0x2d] = 0x41; regs[0x65] = 0x80; switch (dev->model.sensor_type) { case X74_SENSOR: rts88xx_set_scan_frequency (regs, 0); regs[0x93] = 0x06; break; case X1100_B2_SENSOR: regs[0x8b] = 0x00; regs[0x8c] = 0x00; regs[0x93] = 0x06; break; case X1100_2C_SENSOR: rts88xx_set_scan_frequency (regs, 0); regs[0x93] = 0x06; break; case A920_SENSOR: rts88xx_set_scan_frequency (regs, 0); regs[0x8b] = 0xff; regs[0x8c] = 0x02; regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x2d] = 0x01; rts88xx_set_scan_frequency (regs, 0); break; case X1200_USB2_SENSOR: dev->shadow_regs[0x2d] = 0x4f; rts88xx_set_scan_frequency (regs, 0); break; } /* set grayscale scan + nodata/nochannel? */ regs[0x2f] = 0xa1; /* set ? */ regs[0x34] = 0x50; regs[0x35] = 0x01; regs[0x36] = 0x50; regs[0x37] = 0x01; regs[0x38] = 0x50; /* set motor resolution divisor */ regs[0x39] = 0x00; /* set vertical start/end positions */ regs[0x60] = LOBYTE (distance - 1); regs[0x61] = HIBYTE (distance - 1); regs[0x62] = LOBYTE (distance); regs[0x63] = HIBYTE (distance); /* set horizontal start position */ regs[0x66] = 0x64; regs[0x67] = 0x00; /* set horizontal end position */ regs[0x6c] = 0xc8; regs[0x6d] = 0x00; /* set horizontal resolution */ regs[0x79] = 0x40; regs[0x7a] = 0x01; /* don't buffer data for this scan */ regs[0xb2] = 0x04; /* Motor enable & Coordinate space denominator */ regs[0xc3] = 0x81; /* Movement direction & step size */ regs[0xc6] = 0x09; /* ? */ regs[0x80] = 0x00; regs[0x81] = 0x00; regs[0x82] = 0x00; regs[0xc5] = 0x0a; switch (dev->model.motor_type) { case X1100_MOTOR: case A920_MOTOR: /* step size range2 */ regs[0xc9] = 0x3b; /* ? */ regs[0xca] = 0x0a; /* motor curve stuff */ regs[0xe0] = 0x00; regs[0xe1] = 0x00; regs[0xe4] = 0x00; regs[0xe5] = 0x00; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe2] = 0x09; regs[0xe3] = 0x1a; regs[0xe6] = 0xdc; regs[0xe9] = 0x1b; regs[0xec] = 0x07; regs[0xef] = 0x03; break; case X74_MOTOR: regs[0xc5] = 0x41; /* step size range2 */ regs[0xc9] = 0x39; /* ? */ regs[0xca] = 0x40; /* motor curve stuff */ regs[0xe0] = 0x00; regs[0xe1] = 0x00; regs[0xe2] = 0x09; regs[0xe3] = 0x1a; regs[0xe4] = 0x00; regs[0xe5] = 0x00; regs[0xe6] = 0x64; regs[0xe7] = 0x00; regs[0xe8] = 0x00; regs[0xe9] = 0x32; regs[0xec] = 0x0c; regs[0xef] = 0x08; break; } /* prepare for register write */ low_clr_c6 (devnum); low_stop_mvmt (devnum); /* Move Forward without scanning: */ regs[0x32] = 0x00; low_write_all_regs (devnum, regs); regs[0x32] = 0x40; low_write_all_regs (devnum, regs); /* Stop scanner - clear reg 0xb3: */ /* low_stop_mvmt (devnum); */ rts88xx_commit (devnum, regs[0x2c]); /* Poll for scanner stopped - return value(3:0) = 0: */ scan_head_moving = SANE_TRUE; while (scan_head_moving) { #ifdef FAKE_USB scan_head_moving = SANE_FALSE; #else cmd_size = 0x04; low_usb_bulk_write (devnum, pollstopmoving_command_block, &cmd_size); cmd_size = 0x1; low_usb_bulk_read (devnum, &read_result, &cmd_size); if ((read_result & 0xF) == 0x0) { scan_head_moving = SANE_FALSE; } #endif } /* this is needed to find the start line properly */ if (dev->model.sensor_type == X74_SENSOR) low_stop_mvmt (devnum); DBG (2, "sanei_lexmark_low_move_fwd: end.\n"); } SANE_Bool sanei_lexmark_low_search_home_fwd (Lexmark_Device * dev) { /* This function actually searches backwards one line looking for home */ SANE_Int devnum; int i; SANE_Byte poll_result[3]; SANE_Byte *buffer; SANE_Byte temp_byte; static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; static SANE_Byte command5_block[] = { 0x91, 0x00, 0x09, 0xc4 }; size_t cmd_size; SANE_Bool got_line; SANE_Bool ret_val; devnum = dev->devnum; DBG (2, "sanei_lexmark_low_search_home_fwd:\n"); /* set up registers according to the sensor type */ switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x2c] = 0x03; dev->shadow_regs[0x2d] = 0x45; dev->shadow_regs[0x2f] = 0x21; dev->shadow_regs[0x30] = 0x48; dev->shadow_regs[0x31] = 0x06; dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x35] = 0x05; dev->shadow_regs[0x36] = 0x09; dev->shadow_regs[0x37] = 0x09; dev->shadow_regs[0x38] = 0x0d; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x75] = 0x00; dev->shadow_regs[0x8b] = 0xff; dev->shadow_regs[0x93] = 0x06; break; case X1100_B2_SENSOR: dev->shadow_regs[0x2c] = 0x0f; dev->shadow_regs[0x2d] = 0x51; dev->shadow_regs[0x2f] = 0x21; dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x35] = 0x04; dev->shadow_regs[0x36] = 0x08; dev->shadow_regs[0x37] = 0x08; dev->shadow_regs[0x38] = 0x0b; dev->shadow_regs[0x93] = 0x06; break; case X1100_2C_SENSOR: dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x35] = 0x05; dev->shadow_regs[0x36] = 0x09; dev->shadow_regs[0x37] = 0x09; dev->shadow_regs[0x38] = 0x0d; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x72] = 0x35; dev->shadow_regs[0x74] = 0x4e; dev->shadow_regs[0x85] = 0x20; /* 05 */ dev->shadow_regs[0x86] = 0x00; /* 05 */ dev->shadow_regs[0x87] = 0x00; /* 05 */ dev->shadow_regs[0x88] = 0x00; /* 45 */ dev->shadow_regs[0x89] = 0x00; dev->shadow_regs[0x8b] = 0xff; dev->shadow_regs[0x93] = 0x06; /* 0e */ dev->shadow_regs[0x75] = 0x00; /* */ dev->shadow_regs[0x91] = 0x00; /* 60 */ dev->shadow_regs[0x92] = 0x00; /* 8d */ dev->shadow_regs[0xb1] = 0x00; /* */ dev->shadow_regs[0xc5] = 0x00; /* */ dev->shadow_regs[0xca] = 0x00; /* */ dev->shadow_regs[0xc3] = 0x01; /* */ break; case A920_SENSOR: dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x35] = 0x05; dev->shadow_regs[0x36] = 0x09; dev->shadow_regs[0x37] = 0x09; dev->shadow_regs[0x38] = 0x0d; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x72] = 0x35; dev->shadow_regs[0x74] = 0x4e; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x88] = 0x45; dev->shadow_regs[0x89] = 0x00; dev->shadow_regs[0x8b] = 0xff; dev->shadow_regs[0x91] = 0x60; dev->shadow_regs[0x92] = 0x8d; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x2c] = 0x01; dev->shadow_regs[0x2d] = 0x03; dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x35] = 0x04; dev->shadow_regs[0x36] = 0x08; dev->shadow_regs[0x37] = 0x08; dev->shadow_regs[0x38] = 0x0b; dev->shadow_regs[0x66] = 0x88; dev->shadow_regs[0x6c] = 0x10; dev->shadow_regs[0x6d] = 0x14; dev->shadow_regs[0x75] = 0x00; dev->shadow_regs[0x93] = 0x06; dev->shadow_regs[0xc5] = 0x00; dev->shadow_regs[0xca] = 0x00; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x0b] = 0x70; dev->shadow_regs[0x0c] = 0x28; dev->shadow_regs[0x0d] = 0xa4; dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; dev->shadow_regs[0x2f] = 0x21; dev->shadow_regs[0x32] = 0x40; dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x35] = 0x05; dev->shadow_regs[0x36] = 0x09; dev->shadow_regs[0x37] = 0x09; dev->shadow_regs[0x38] = 0x0d; dev->shadow_regs[0x3a] = 0x20; dev->shadow_regs[0x3b] = 0x37; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x47] = 0x01; dev->shadow_regs[0x48] = 0x1a; dev->shadow_regs[0x49] = 0x5b; dev->shadow_regs[0x4a] = 0x1b; dev->shadow_regs[0x4b] = 0x5b; dev->shadow_regs[0x4c] = 0x05; dev->shadow_regs[0x4d] = 0x3f; dev->shadow_regs[0x75] = 0x00; dev->shadow_regs[0x85] = 0x03; dev->shadow_regs[0x86] = 0x33; dev->shadow_regs[0x87] = 0x8f; dev->shadow_regs[0x88] = 0x34; dev->shadow_regs[0x8b] = 0xff; dev->shadow_regs[0x8e] = 0x60; dev->shadow_regs[0x8f] = 0x80; dev->shadow_regs[0x91] = 0x59; dev->shadow_regs[0x92] = 0x10; dev->shadow_regs[0x93] = 0x06; dev->shadow_regs[0xa3] = 0x0d; dev->shadow_regs[0xa4] = 0x5e; dev->shadow_regs[0xa5] = 0x23; dev->shadow_regs[0xb1] = 0x07; dev->shadow_regs[0xc2] = 0x80; dev->shadow_regs[0xc5] = 0x00; dev->shadow_regs[0xca] = 0x00; break; } dev->shadow_regs[0x65] = 0x80; dev->shadow_regs[0x8c] = 0x02; dev->shadow_regs[0x8d] = 0x01; dev->shadow_regs[0xb2] = 0x00; dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; rts88xx_set_gain (dev->shadow_regs, dev->sensor->default_gain, dev->sensor->default_gain, dev->sensor->default_gain); rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80); /* set grayscale scan */ rts88xx_set_gray_scan (dev->shadow_regs); /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x07; /* set vertical start/end positions */ dev->shadow_regs[0x60] = 0x01; dev->shadow_regs[0x61] = 0x00; dev->shadow_regs[0x62] = 0x02; dev->shadow_regs[0x63] = 0x00; /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 1); /* set horizontal start position */ dev->shadow_regs[0x66] = 0x6a; /* 0x88 for X1200 */ dev->shadow_regs[0x67] = 0x00; /* set horizontal end position */ dev->shadow_regs[0x6c] = 0xf2; /* 0x1410 for X1200 */ dev->shadow_regs[0x6d] = 0x13; /* set horizontal resolution */ dev->shadow_regs[0x79] = 0x40; dev->shadow_regs[0x7a] = 0x02; /* Motor disable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x01; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x01; switch (dev->model.motor_type) { case A920_MOTOR: case X1100_MOTOR: /* step size range2 */ dev->shadow_regs[0xc9] = 0x3b; /* step size range0 */ dev->shadow_regs[0xe2] = 0x01; /* ? */ dev->shadow_regs[0xe3] = 0x03; break; case X74_MOTOR: dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x00; dev->shadow_regs[0xc8] = 0x04; /* step size range2 */ dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x00; /* motor curve stuff */ dev->shadow_regs[0xe0] = 0x29; dev->shadow_regs[0xe1] = 0x17; dev->shadow_regs[0xe2] = 0x8f; dev->shadow_regs[0xe3] = 0x06; dev->shadow_regs[0xe4] = 0x61; dev->shadow_regs[0xe5] = 0x16; dev->shadow_regs[0xe6] = 0x64; dev->shadow_regs[0xe7] = 0xb5; dev->shadow_regs[0xe8] = 0x08; dev->shadow_regs[0xe9] = 0x32; dev->shadow_regs[0xec] = 0x0c; dev->shadow_regs[0xef] = 0x08; break; } /* Stop the scanner */ low_stop_mvmt (devnum); /* write regs out twice */ dev->shadow_regs[0x32] = 0x00; low_write_all_regs (devnum, dev->shadow_regs); dev->shadow_regs[0x32] = 0x40; low_write_all_regs (devnum, dev->shadow_regs); /* Start Scan */ rts88xx_commit (devnum, dev->shadow_regs[0x2c]); /* Poll the available byte count until not 0 */ got_line = SANE_FALSE; while (!got_line) { cmd_size = 4; low_usb_bulk_write (devnum, command4_block, &cmd_size); cmd_size = 0x3; low_usb_bulk_read (devnum, poll_result, &cmd_size); if (! (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0)) { /* if result != 00 00 00 we got data */ got_line = SANE_TRUE; } } /* create buffer for scan data */ buffer = calloc (2500, sizeof (char)); if (buffer == NULL) { return SANE_FALSE; } /* Tell the scanner to send the data */ /* Write: 91 00 09 c4 */ cmd_size = 4; low_usb_bulk_write (devnum, command5_block, &cmd_size); /* Read it */ cmd_size = 0x09c4; low_usb_bulk_read (devnum, buffer, &cmd_size); /* Reverse order of bytes in words of buffer */ for (i = 0; i < 2500; i = i + 2) { temp_byte = *(buffer + i); *(buffer + i) = *(buffer + i + 1); *(buffer + i + 1) = temp_byte; } /* check for home position */ ret_val = low_is_home_line (dev, buffer); if (ret_val) DBG (2, "sanei_lexmark_low_search_home_fwd: !!!HOME POSITION!!!\n"); /* free the buffer */ free (buffer); DBG (2, "sanei_lexmark_low_search_home_fwd: end.\n"); return ret_val; } SANE_Bool sanei_lexmark_low_search_home_bwd (Lexmark_Device * dev) { /* This function must only be called if the scan head is past the home dot. It could damage the scanner if not. This function tells the scanner to do a grayscale scan backwards with a 300dpi resolution. It reads 2500 bytes of data between horizontal co-ordinates 0x6a and 0x13f2. The scan is set to read between vertical co-ordinates from 0x0a to 0x0f46, or 3900 lines. This equates to 13" at 300dpi, so we must stop the scan before it bangs against the end. A line limit is set so that a maximum of 0x0F3C (13"*300dpi) lines can be read. To read the scan data we create a buffer space large enough to hold 10 lines of data. For each read we poll twice, ignoring the first poll. This is required for timing. We repeat the double poll until there is data available. The number of lines (or number of buffers in our buffer space) is calculated from the size of the data available from the scanner. The number of buffers is calculated as the space required to hold 1.5 times the size of the data available from the scanner. After data is read from the scanner each line is checked if it is on the home dot. Lines are continued to be read until we are no longer on the home dot. */ SANE_Int devnum; SANE_Status status; int i, j; SANE_Byte poll_result[3]; SANE_Byte *buffer; SANE_Byte *buffer_start; SANE_Byte temp_byte; SANE_Int buffer_count = 0; SANE_Int size_requested; SANE_Int size_returned; SANE_Int no_of_buffers; SANE_Int buffer_limit = 0xF3C; SANE_Int high_byte, mid_byte, low_byte; SANE_Int home_line_count; SANE_Bool in_home_region; static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; static SANE_Byte command5_block[] = { 0x91, 0x00, 0xff, 0xc0 }; #ifdef DEEP_DEBUG FILE *img = NULL; #endif size_t cmd_size; SANE_Bool got_line; devnum = dev->devnum; DBG (2, "sanei_lexmark_low_search_home_bwd:\n"); /* set up registers */ switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x2c] = 0x03; dev->shadow_regs[0x2d] = 0x45; dev->shadow_regs[0x34] = 0x09; dev->shadow_regs[0x35] = 0x09; dev->shadow_regs[0x36] = 0x11; dev->shadow_regs[0x37] = 0x11; dev->shadow_regs[0x38] = 0x19; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x93] = 0x06; dev->shadow_regs[0x40] = 0x80; /* important for detection of b/w transitions */ dev->shadow_regs[0x75] = 0x00; dev->shadow_regs[0x8b] = 0xff; break; case X1100_B2_SENSOR: dev->shadow_regs[0x2c] = 0x0f; dev->shadow_regs[0x2d] = 0x51; dev->shadow_regs[0x34] = 0x07; dev->shadow_regs[0x35] = 0x07; dev->shadow_regs[0x36] = 0x0f; dev->shadow_regs[0x37] = 0x0f; dev->shadow_regs[0x38] = 0x15; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x93] = 0x06; break; case X1100_2C_SENSOR: dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; dev->shadow_regs[0x34] = 0x09; dev->shadow_regs[0x35] = 0x09; dev->shadow_regs[0x36] = 0x11; dev->shadow_regs[0x37] = 0x11; dev->shadow_regs[0x38] = 0x19; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; dev->shadow_regs[0x34] = 0x09; dev->shadow_regs[0x35] = 0x09; dev->shadow_regs[0x36] = 0x11; dev->shadow_regs[0x37] = 0x11; dev->shadow_regs[0x38] = 0x19; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x2c] = 0x01; dev->shadow_regs[0x2d] = 0x03; dev->shadow_regs[0x34] = 0x07; dev->shadow_regs[0x35] = 0x07; dev->shadow_regs[0x36] = 0x0f; dev->shadow_regs[0x37] = 0x0f; dev->shadow_regs[0x38] = 0x15; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; dev->shadow_regs[0x34] = 0x09; dev->shadow_regs[0x35] = 0x09; dev->shadow_regs[0x36] = 0x11; dev->shadow_regs[0x37] = 0x11; dev->shadow_regs[0x38] = 0x19; dev->shadow_regs[0x85] = 0x03; dev->shadow_regs[0x93] = 0x06; break; } rts88xx_set_gain (dev->shadow_regs, dev->sensor->default_gain, dev->sensor->default_gain, dev->sensor->default_gain); dev->shadow_regs[0x65] = 0x80; dev->shadow_regs[0x8b] = 0xff; dev->shadow_regs[0x8c] = 0x02; dev->shadow_regs[0xb2] = 0x00; /* set calibration */ rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80); /* set grayscale scan */ dev->shadow_regs[0x2f] = 0x21; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x03; /* set vertical start/end positions */ dev->shadow_regs[0x60] = 0x0a; dev->shadow_regs[0x61] = 0x00; dev->shadow_regs[0x62] = 0x46; dev->shadow_regs[0x63] = 0x0f; /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 2); /* set horizontal start position */ dev->shadow_regs[0x66] = 0x6a; /* 0x88 for X1200 */ dev->shadow_regs[0x67] = 0x00; /* set horizontal end position */ dev->shadow_regs[0x6c] = 0xf2; /* 0x1410 for X1200, 13f2 for X1200/rev. 97 */ dev->shadow_regs[0x6d] = 0x13; /* set horizontal resolution */ dev->shadow_regs[0x79] = 0x40; dev->shadow_regs[0x7a] = 0x02; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x01; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x81; switch (dev->model.motor_type) { case X74_MOTOR: dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x00; dev->shadow_regs[0xc8] = 0x04; /* step size range2 */ dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x00; /* motor curve stuff */ dev->shadow_regs[0xe0] = 0x29; dev->shadow_regs[0xe1] = 0x17; dev->shadow_regs[0xe2] = 0x8f; dev->shadow_regs[0xe3] = 0x06; dev->shadow_regs[0xe4] = 0x61; dev->shadow_regs[0xe5] = 0x16; dev->shadow_regs[0xe6] = 0x64; dev->shadow_regs[0xe7] = 0xb5; dev->shadow_regs[0xe8] = 0x08; dev->shadow_regs[0xe9] = 0x32; dev->shadow_regs[0xec] = 0x0c; dev->shadow_regs[0xef] = 0x08; break; case A920_MOTOR: case X1100_MOTOR: /* ? */ dev->shadow_regs[0xc5] = 0x19; /* step size range2 */ dev->shadow_regs[0xc9] = 0x3a; /* ? */ dev->shadow_regs[0xca] = 0x08; /* motor curve stuff */ dev->shadow_regs[0xe0] = 0xe3; dev->shadow_regs[0xe1] = 0x18; dev->shadow_regs[0xe2] = 0x03; dev->shadow_regs[0xe3] = 0x06; dev->shadow_regs[0xe4] = 0x2b; dev->shadow_regs[0xe5] = 0x17; dev->shadow_regs[0xe6] = 0xdc; dev->shadow_regs[0xe7] = 0xb3; dev->shadow_regs[0xe8] = 0x07; dev->shadow_regs[0xe9] = 0x1b; dev->shadow_regs[0xec] = 0x07; dev->shadow_regs[0xef] = 0x03; break; } /* Stop the scanner */ low_stop_mvmt (devnum); /* write regs out twice */ dev->shadow_regs[0x32] = 0x00; low_write_all_regs (devnum, dev->shadow_regs); dev->shadow_regs[0x32] = 0x40; low_write_all_regs (devnum, dev->shadow_regs); /* Start Scan */ status = rts88xx_commit (devnum, dev->shadow_regs[0x2c]); /* create buffer to hold up to 10 lines of scan data */ buffer = calloc (10 * 2500, sizeof (char)); if (buffer == NULL) { return SANE_FALSE; } home_line_count = 0; in_home_region = SANE_FALSE; #ifdef DEEP_DEBUG img = fopen ("find_bwd.pnm", "wb"); fprintf (img, "P5\n2500 100\n255\n"); #endif while (buffer_count < buffer_limit) { size_returned = 0; got_line = SANE_FALSE; while (!got_line) { /* always poll twice (needed for timing) - disregard 1st poll */ cmd_size = 4; status = low_usb_bulk_write (devnum, command4_block, &cmd_size); if (status != SANE_STATUS_GOOD) return SANE_FALSE; cmd_size = 0x3; status = low_usb_bulk_read (devnum, poll_result, &cmd_size); if (status != SANE_STATUS_GOOD) return SANE_FALSE; cmd_size = 4; status = low_usb_bulk_write (devnum, command4_block, &cmd_size); if (status != SANE_STATUS_GOOD) return SANE_FALSE; cmd_size = 0x3; status = low_usb_bulk_read (devnum, poll_result, &cmd_size); if (status != SANE_STATUS_GOOD) return SANE_FALSE; if (! (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0)) { /* if result != 00 00 00 we got data */ got_line = SANE_TRUE; high_byte = poll_result[2] << 16; mid_byte = poll_result[1] << 8; low_byte = poll_result[0]; size_returned = high_byte + mid_byte + low_byte; } } /*size_requested = size_returned;*/ size_requested = 2500; no_of_buffers = size_returned * 3; no_of_buffers = no_of_buffers / 2500; no_of_buffers = no_of_buffers >> 1; /* force 1 buffer at a time to improve accuray, which slow downs search */ no_of_buffers = 1; if (no_of_buffers < 1) no_of_buffers = 1; else if (no_of_buffers > 10) no_of_buffers = 10; buffer_count = buffer_count + no_of_buffers; size_requested = no_of_buffers * 2500; /* Tell the scanner to send the data */ /* Write: 91 */ command5_block[1] = (SANE_Byte) (size_requested >> 16); command5_block[2] = (SANE_Byte) (size_requested >> 8); command5_block[3] = (SANE_Byte) (size_requested & 0xFF); cmd_size = 4; status = low_usb_bulk_write (devnum, command5_block, &cmd_size); if (status != SANE_STATUS_GOOD) return SANE_FALSE; /* Read it */ cmd_size = size_requested; status = low_usb_bulk_read (devnum, buffer, &cmd_size); if (status != SANE_STATUS_GOOD) return SANE_FALSE; for (i = 0; i < no_of_buffers; i++) { buffer_start = buffer + (i * 2500); /* Reverse order of bytes in words of buffer */ for (j = 0; j < 2500; j = j + 2) { temp_byte = *(buffer_start + j); *(buffer_start + j) = *(buffer_start + j + 1); *(buffer_start + j + 1) = temp_byte; } #ifdef DEEP_DEBUG fwrite (buffer + (i * 2500), 2500, 1, img); #endif if (low_is_home_line (dev, buffer_start)) { home_line_count++; if (home_line_count > 7) in_home_region = SANE_TRUE; } if (in_home_region) { /* slow down scanning : on purpose backtracking */ if (home_line_count) sleep (1); free (buffer); #ifdef DEEP_DEBUG fflush (img); i = ftell (img) / 2500; rewind (img); DBG (2, "sanei_lexmark_low_search_home_bwd: offset=%d\n", i); fprintf (img, "P5\n2500 %03d\n", i); fclose (img); #endif low_stop_mvmt (devnum); DBG (2, "sanei_lexmark_low_search_home_bwd: in home region, end.\n"); return SANE_TRUE; } } } /* end while (buffer_count > buffer_limit); */ free (buffer); #ifdef DEEP_DEBUG fflush (img); i = ftell (img) / 2500; rewind (img); fprintf (img, "P5\n2500 %03d\n", i); fclose (img); #endif low_stop_mvmt (devnum); DBG (2, "sanei_lexmark_low_search_home_bwd: end.\n"); return SANE_FALSE; } SANE_Status low_get_start_loc (SANE_Int resolution, SANE_Int * vert_start, SANE_Int * hor_start, SANE_Int offset, Lexmark_Device * dev) { SANE_Int start_600; switch (dev->model.sensor_type) { case X1100_2C_SENSOR: case X1200_USB2_SENSOR: case A920_SENSOR: case X1200_SENSOR: start_600 = 195 - offset; *hor_start = 0x68; break; case X1100_B2_SENSOR: start_600 = 195 - offset; switch (resolution) { case 75: *hor_start = 0x68; break; case 150: *hor_start = 0x68; break; case 300: *hor_start = 0x6a; break; case 600: *hor_start = 0x6b; break; case 1200: *hor_start = 0x6b; break; default: /* If we're here we have an invalid resolution */ return SANE_STATUS_INVAL; } break; case X74_SENSOR: start_600 = 268 - offset; switch (resolution) { case 75: *hor_start = 0x48; break; case 150: *hor_start = 0x48; break; case 300: *hor_start = 0x4a; break; case 600: *hor_start = 0x4b; break; default: /* If we're here we have an invalid resolution */ return SANE_STATUS_INVAL; } break; default: /* If we're here we have an unknown dev->model.sensor_type */ return SANE_STATUS_INVAL; } /* Calculate vertical start distance at 600dpi */ switch (resolution) { case 75: *vert_start = start_600 / 8; break; case 150: *vert_start = start_600 / 4; break; case 300: *vert_start = start_600 / 2; break; case 600: *vert_start = start_600; break; case 1200: *vert_start = start_600 * 2; break; default: /* If we're here we have an invalid resolution */ return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } void low_set_scan_area (SANE_Int res, SANE_Int tlx, SANE_Int tly, SANE_Int brx, SANE_Int bry, SANE_Int offset, SANE_Bool half_step, SANE_Byte * regs, Lexmark_Device * dev) { SANE_Int vert_start = 0; SANE_Int hor_start = 0; SANE_Int vert_end; SANE_Int hor_end; low_get_start_loc (res, &vert_start, &hor_start, offset, dev); /* convert pixel height to vertical location coordinates */ vert_end = vert_start + (bry * res) / 600; vert_start += (tly * res) / 600; /* scan area size : for A920, 600 color scans are done at 1200 y dpi */ /* this follow what was found in usb logs */ if (half_step) { vert_end = vert_end * 2; vert_start = vert_start * 2; } /* set vertical start position registers */ regs[0x60] = LOBYTE (vert_start); regs[0x61] = HIBYTE (vert_start); /* set vertical end position registers */ regs[0x62] = LOBYTE (vert_end); regs[0x63] = HIBYTE (vert_end); /* convert pixel width to horizontal location coordinates */ hor_end = hor_start + brx; hor_start += tlx; regs[0x66] = LOBYTE (hor_start); regs[0x67] = HIBYTE (hor_start); /* set horizontal end position registers */ regs[0x6c] = LOBYTE (hor_end); regs[0x6d] = HIBYTE (hor_end); /* Debug */ DBG (2, "low_set_scan_area: vert_start: %d (tly=%d)\n", vert_start, tly); DBG (2, "low_set_scan_area: vert_end: %d\n", vert_end); DBG (2, "low_set_scan_area: hor_start: %d\n", hor_start); DBG (2, "low_set_scan_area: hor_end: %d\n", hor_end); } SANE_Int sanei_lexmark_low_find_start_line (Lexmark_Device * dev) { /* This function scans forward 59 lines, reading 88 bytes per line from the middle of the horizontal line: pixel 0xa84 to pixel 0x9d4. It scans with the following parameters: dir=fwd mode=grayscale h.res=300 dpi v.res=600 dpi hor. pixels = (0xa84 - 0x9d4)/2 = 0x58 = 88 vert. pixels = 0x3e - 0x03 = 0x3b = 59 data = 88x59=5192=0x1448 It assumes we are in the start dot, or just before it. We are reading enough lines at 600dpi to read past the dot. We return the number of entirely white lines read consecutively, so we know how far past the dot we are. To find the number of consecutive white lines we do the following: Byte swap the order of the bytes in the buffer. Go through the buffer finding low and high values, which are computed by comparing to the weighted average: weighted_average = (lowest value + (highest value - lowest value)/4) Low bytes are changed to 0xFF (white), higher of equal bytes are changed to 0x00 (black),so that the buffer only contains white (0xFF) or black (0x00) values. Next, we go through the buffer a line (88 bytes) at a time for 59 lines to read the entire buffer. For each byte in a line we check if the byte is black. If it is we increment the black byte counter. After each line we check the black byte counter. If it is greater than 0 we increment the black line count and set the white line count to 0. If there were no black bytes in the line we set the black line count to 0 and increment the white line count. When all lines have been processed we return the white line count. */ int blackLineCount = 0; int whiteLineCount = 0; int blackByteCounter = 0; unsigned char max_byte = 0; unsigned char min_byte = 0xFF; unsigned char weighted_average; int i, j; #ifdef DEEP_DEBUG FILE *fdbg = NULL; #endif SANE_Byte poll_result[3]; SANE_Byte *buffer; SANE_Byte temp_byte; static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; static SANE_Byte command5_block[] = { 0x91, 0x00, 0x14, 0x48 }; size_t cmd_size; SANE_Bool got_line; DBG (2, "sanei_lexmark_low_find_start_line:\n"); /* set up registers */ switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x2c] = 0x04; dev->shadow_regs[0x2d] = 0x46; dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x35] = 0x05; dev->shadow_regs[0x36] = 0x0b; dev->shadow_regs[0x37] = 0x0b; dev->shadow_regs[0x38] = 0x11; dev->shadow_regs[0x40] = 0x40; rts88xx_set_gain (dev->shadow_regs, 6, 6, 6); break; case X1100_B2_SENSOR: dev->shadow_regs[0x2c] = 0x0f; dev->shadow_regs[0x2d] = 0x51; dev->shadow_regs[0x34] = 0x0d; dev->shadow_regs[0x35] = 0x0d; dev->shadow_regs[0x36] = 0x1d; dev->shadow_regs[0x37] = 0x1d; dev->shadow_regs[0x38] = 0x29; dev->shadow_regs[0x65] = 0x80; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x93] = 0x06; rts88xx_set_gain (dev->shadow_regs, 6, 6, 6); break; case X1100_2C_SENSOR: rts88xx_set_gain (dev->shadow_regs, 10, 10, 10); dev->shadow_regs[0x28] = 0xf5; dev->shadow_regs[0x29] = 0xf7; dev->shadow_regs[0x2a] = 0xf5; dev->shadow_regs[0x2b] = 0x17; dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; dev->shadow_regs[0x31] = 0x01; dev->shadow_regs[0x34] = 0x11; dev->shadow_regs[0x35] = 0x11; dev->shadow_regs[0x36] = 0x21; dev->shadow_regs[0x37] = 0x21; dev->shadow_regs[0x38] = 0x31; dev->shadow_regs[0x72] = 0x35; dev->shadow_regs[0x74] = 0x4e; dev->shadow_regs[0x85] = 0x02; dev->shadow_regs[0x86] = 0x33; dev->shadow_regs[0x87] = 0x0f; dev->shadow_regs[0x88] = 0x24; dev->shadow_regs[0x91] = 0x19; dev->shadow_regs[0x92] = 0x20; dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; break; case A920_SENSOR: dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; dev->shadow_regs[0x34] = 0x11; dev->shadow_regs[0x35] = 0x11; dev->shadow_regs[0x36] = 0x21; dev->shadow_regs[0x37] = 0x21; dev->shadow_regs[0x38] = 0x31; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x88] = 0x44; dev->shadow_regs[0x92] = 0x85; dev->shadow_regs[0x93] = 0x0e; rts88xx_set_gain (dev->shadow_regs, 6, 6, 6); break; case X1200_SENSOR: dev->shadow_regs[0x2c] = 0x01; dev->shadow_regs[0x2d] = 0x03; dev->shadow_regs[0x34] = 0x0d; dev->shadow_regs[0x35] = 0x0d; dev->shadow_regs[0x36] = 0x1d; dev->shadow_regs[0x37] = 0x1d; dev->shadow_regs[0x38] = 0x29; dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x81] = 0x00; dev->shadow_regs[0x82] = 0x00; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0xff; dev->shadow_regs[0x88] = 0x02; dev->shadow_regs[0x92] = 0x00; rts88xx_set_gain (dev->shadow_regs, 10, 10, 10); break; case X1200_USB2_SENSOR: dev->shadow_regs[0x2c] = 0x01; dev->shadow_regs[0x2d] = 0x03; dev->shadow_regs[0x34] = 0x0d; dev->shadow_regs[0x35] = 0x0d; dev->shadow_regs[0x36] = 0x1d; dev->shadow_regs[0x37] = 0x1d; dev->shadow_regs[0x38] = 0x29; dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; rts88xx_set_gain (dev->shadow_regs, 10, 10, 10); break; } /* set offset to a safe value */ rts88xx_set_offset (dev->shadow_regs, 0x80, 0x80, 0x80); /* set grayscale scan */ dev->shadow_regs[0x2f] = 0x21; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x01; /* set vertical start/end positions */ dev->shadow_regs[0x60] = 0x03; dev->shadow_regs[0x61] = 0x00; dev->shadow_regs[0x62] = 0x3e; dev->shadow_regs[0x63] = 0x00; /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 1); /* set horizontal start position */ dev->shadow_regs[0x66] = 0xd4; /* 0xf2 for X1200 */ dev->shadow_regs[0x67] = 0x09; /* set horizontal end position */ dev->shadow_regs[0x6c] = 0x84; /* 0xa2 for X1200 */ dev->shadow_regs[0x6d] = 0x0a; /* set horizontal resolution */ dev->shadow_regs[0x79] = 0x40; dev->shadow_regs[0x7a] = 0x02; /* set for ? */ /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x81; switch (dev->model.motor_type) { case X1100_MOTOR: case A920_MOTOR: /* set for ? */ dev->shadow_regs[0xc5] = 0x22; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; /* step size range2 */ dev->shadow_regs[0xc9] = 0x3b; /* set for ? */ dev->shadow_regs[0xca] = 0x1f; dev->shadow_regs[0xe0] = 0xf7; dev->shadow_regs[0xe1] = 0x16; /* step size range0 */ dev->shadow_regs[0xe2] = 0x87; /* ? */ dev->shadow_regs[0xe3] = 0x13; dev->shadow_regs[0xe4] = 0x1b; dev->shadow_regs[0xe5] = 0x16; dev->shadow_regs[0xe6] = 0xdc; dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; dev->shadow_regs[0xe9] = 0x1b; dev->shadow_regs[0xec] = 0x07; dev->shadow_regs[0xef] = 0x03; break; case X74_MOTOR: dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x22; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x0b; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x1f; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x2f; dev->shadow_regs[0xe1] = 0x11; /* step size range0 */ dev->shadow_regs[0xe2] = 0x9f; /* ? */ dev->shadow_regs[0xe3] = 0x0f; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0xcb; dev->shadow_regs[0xe5] = 0x10; /* step size range1 */ dev->shadow_regs[0xe6] = 0x64; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x32; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x0c; /* bounds of movement range4 -only for 75dpi grayscale */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x08; break; } /* Stop the scanner */ low_stop_mvmt (dev->devnum); /* write regs out twice */ dev->shadow_regs[0x32] = 0x00; low_write_all_regs (dev->devnum, dev->shadow_regs); dev->shadow_regs[0x32] = 0x40; low_write_all_regs (dev->devnum, dev->shadow_regs); /* Start Scan */ rts88xx_commit (dev->devnum, dev->shadow_regs[0x2c]); /* Poll the available byte count until not 0 */ got_line = SANE_FALSE; while (!got_line) { cmd_size = 4; low_usb_bulk_write (dev->devnum, command4_block, &cmd_size); cmd_size = 0x3; low_usb_bulk_read (dev->devnum, poll_result, &cmd_size); if (! (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0)) { /* if result != 00 00 00 we got data */ got_line = SANE_TRUE; } #ifdef FAKE_USB got_line = SANE_TRUE; #endif } /* create buffer for scan data */ buffer = calloc (5192, sizeof (char)); if (buffer == NULL) { return -1; } /* Tell the scanner to send the data */ /* Write: 91 00 14 48 */ cmd_size = 4; low_usb_bulk_write (dev->devnum, command5_block, &cmd_size); /* Read it */ cmd_size = 0x1448; low_usb_bulk_read (dev->devnum, buffer, &cmd_size); /* Stop the scanner */ low_stop_mvmt (dev->devnum); /* Reverse order of bytes in words of buffer */ for (i = 0; i < 5192; i = i + 2) { temp_byte = *(buffer + i); *(buffer + i) = *(buffer + i + 1); *(buffer + i + 1) = temp_byte; } #ifdef DEEP_DEBUG fdbg = fopen ("find_start.pnm", "wb"); if (fdbg != NULL) { fprintf (fdbg, "P5\n%d %d\n255\n", 88, 59); fwrite (buffer, 5192, 1, fdbg); fclose (fdbg); } #endif /* Find the max and the min */ for (i = 0; i < 5192; i++) { if (*(buffer + i) > max_byte) max_byte = *(buffer + i); if (*(buffer + i) < min_byte) min_byte = *(buffer + i); } weighted_average = min_byte + ((max_byte - min_byte) / 4); /* Set bytes as black (0x00) or white (0xFF) */ for (i = 0; i < 5192; i++) { if (*(buffer + i) > weighted_average) *(buffer + i) = 0xFF; else *(buffer + i) = 0x00; } #ifdef DEEP_DEBUG fdbg = fopen ("find_start_after.pnm", "wb"); if (fdbg != NULL) { fprintf (fdbg, "P5\n%d %d\n255\n", 88, 59); fwrite (buffer, 5192, 1, fdbg); fclose (fdbg); } #endif /* Go through 59 lines */ for (j = 0; j < 59; j++) { blackByteCounter = 0; /* Go through 88 bytes per line */ for (i = 0; i < 88; i++) { /* Is byte black? */ if (*(buffer + (j * 88) + i) == 0) { blackByteCounter++; } } /* end for line */ if (blackByteCounter > 0) { /* This was a black line */ blackLineCount++; whiteLineCount = 0; } else { /* This is a white line */ whiteLineCount++; blackLineCount = 0; } } /* end for buffer */ free (buffer); /* Stop the scanner. This is needed to get the right distance to the scanning area */ if (dev->model.sensor_type == X74_SENSOR) low_stop_mvmt (dev->devnum); DBG (2, "sanei_lexmark_low_find_start_line: end.\n"); return whiteLineCount; } SANE_Status sanei_lexmark_low_set_scan_regs (Lexmark_Device * dev, SANE_Int resolution, SANE_Int offset, SANE_Bool calibrated) { SANE_Bool isColourScan; DBG (2, "sanei_lexmark_low_set_scan_regs:\n"); DBG (7, "sanei_lexmark_low_set_scan_regs: resolution=%d DPI\n", resolution); /* colour mode */ if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) isColourScan = SANE_TRUE; else isColourScan = SANE_FALSE; /* set up registers */ switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x2c] = 0x03; dev->shadow_regs[0x2d] = 0x45; break; case X1100_B2_SENSOR: dev->shadow_regs[0x2c] = 0x0f; dev->shadow_regs[0x2d] = 0x51; break; case X1100_2C_SENSOR: dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; break; case A920_SENSOR: dev->shadow_regs[0x2c] = 0x0d; dev->shadow_regs[0x2d] = 0x4f; break; case X1200_SENSOR: dev->shadow_regs[0x2c] = 0x01; dev->shadow_regs[0x2d] = 0x03; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x2c] = 0x01; dev->shadow_regs[0x2d] = 0x03; break; } low_set_scan_area (resolution, dev->val[OPT_TL_X].w, dev->val[OPT_TL_Y].w, dev->val[OPT_BR_X].w, dev->val[OPT_BR_Y].w, offset, (dev->model.motor_type == A920_MOTOR || dev->model.motor_type == X74_MOTOR) && isColourScan && (resolution == 600), dev->shadow_regs, dev); /* may be we could use a sensor descriptor that would held the max horiz dpi */ if (dev->val[OPT_RESOLUTION].w < 600) dev->shadow_regs[0x7a] = 600 / dev->val[OPT_RESOLUTION].w; else dev->shadow_regs[0x7a] = 1; /* 75dpi x 75dpi */ if (resolution == 75) { DBG (5, "sanei_lexmark_low_set_scan_regs(): 75 DPI resolution\n"); if (isColourScan) { switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x36] = 0x03; dev->shadow_regs[0x38] = 0x03; dev->shadow_regs[0x79] = 0x08; dev->shadow_regs[0x80] = 0x0d; dev->shadow_regs[0x81] = 0x0e; dev->shadow_regs[0x82] = 0x02; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06;; break; case X1100_B2_SENSOR: dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x36] = 0x05; dev->shadow_regs[0x38] = 0x05; dev->shadow_regs[0x80] = 0x0c; dev->shadow_regs[0x81] = 0x0c; dev->shadow_regs[0x82] = 0x09; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x8c; dev->shadow_regs[0x92] = 0x40; dev->shadow_regs[0x93] = 0x06; break; case X1100_2C_SENSOR: dev->shadow_regs[0x34] = 0x03; dev->shadow_regs[0x36] = 0x04; dev->shadow_regs[0x38] = 0x03; dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x02; dev->shadow_regs[0x82] = 0x03; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x34] = 0x02; dev->shadow_regs[0x36] = 0x04; dev->shadow_regs[0x38] = 0x03; dev->shadow_regs[0x80] = 0x07; dev->shadow_regs[0x81] = 0x0f; dev->shadow_regs[0x82] = 0x03; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x44; dev->shadow_regs[0x91] = 0x60; dev->shadow_regs[0x92] = 0x85; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x34] = 0x02; dev->shadow_regs[0x36] = 0x03; dev->shadow_regs[0x38] = 0x01; dev->shadow_regs[0x79] = 0x20; dev->shadow_regs[0x80] = 0x08; dev->shadow_regs[0x81] = 0x02; dev->shadow_regs[0x82] = 0x0d; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x1e; dev->shadow_regs[0x87] = 0x39; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; /* dev->shadow_regs[0x92] = 0x92; */ dev->shadow_regs[0x93] = 0x06; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x36] = 0x05; dev->shadow_regs[0x38] = 0x04; dev->shadow_regs[0x80] = 0x01; dev->shadow_regs[0x81] = 0x0a; dev->shadow_regs[0x82] = 0x0b; break; } switch (dev->model.motor_type) { case X74_MOTOR: dev->shadow_regs[0xc2] = 0x80; /* ? */ dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x0c; dev->shadow_regs[0xc6] = 0x0b; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x01; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x1b; dev->shadow_regs[0xe1] = 0x0a; /* step size range0 */ dev->shadow_regs[0xe2] = 0x4f; /* ? */ dev->shadow_regs[0xe3] = 0x01; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0xb3; dev->shadow_regs[0xe5] = 0x09; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0d; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0xe5; dev->shadow_regs[0xe8] = 0x02; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0xa0; dev->shadow_regs[0xeb] = 0x01; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* bounds of movement range4 */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; break; case A920_MOTOR: case X1100_MOTOR: /* ? */ dev->shadow_regs[0xc5] = 0x0a; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x2b; dev->shadow_regs[0xe1] = 0x0a; /* step size range0 */ dev->shadow_regs[0xe2] = 0x7f; /* ? */ dev->shadow_regs[0xe3] = 0x01; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0xbb; dev->shadow_regs[0xe5] = 0x09; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0e; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x2b; dev->shadow_regs[0xe8] = 0x03; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0xa0; dev->shadow_regs[0xeb] = 0x01; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; break; } /* set colour scan */ dev->shadow_regs[0x2f] = 0x11; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x37] = 0x01; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x83; } else /* 75 dpi gray */ { switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x34] = 0x01; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x02; dev->shadow_regs[0x37] = 0x02; dev->shadow_regs[0x38] = 0x03; dev->shadow_regs[0x39] = 0x0f; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x79] = 0x08; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x8c] = 0x02; dev->shadow_regs[0x8d] = 0x01; dev->shadow_regs[0x8e] = 0x60; dev->shadow_regs[0x8f] = 0x80; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_B2_SENSOR: dev->shadow_regs[0x34] = 0x02; dev->shadow_regs[0x35] = 0x02; dev->shadow_regs[0x36] = 0x04; dev->shadow_regs[0x37] = 0x04; dev->shadow_regs[0x38] = 0x06; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_2C_SENSOR: dev->shadow_regs[0x34] = 0x01; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x02; dev->shadow_regs[0x37] = 0x02; dev->shadow_regs[0x38] = 0x03; /* these are half of B2 sensor */ dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x34] = 0x01; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x02; dev->shadow_regs[0x37] = 0x02; dev->shadow_regs[0x38] = 0x03; dev->shadow_regs[0x85] = 0x0d; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x45; dev->shadow_regs[0x91] = 0x60; dev->shadow_regs[0x92] = 0x8d; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x34] = 0x01; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x02; dev->shadow_regs[0x37] = 0x02; dev->shadow_regs[0x38] = 0x02; dev->shadow_regs[0x79] = 0x20; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0xff; dev->shadow_regs[0x88] = 0x02; dev->shadow_regs[0x92] = 0x00; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x34] = 0x01; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x02; dev->shadow_regs[0x37] = 0x02; dev->shadow_regs[0x38] = 0x02; dev->shadow_regs[0x79] = 0x20; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0xff; dev->shadow_regs[0x88] = 0x02; dev->shadow_regs[0x92] = 0x00; break; } switch (dev->model.motor_type) { case X74_MOTOR: /* ? */ dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x0a; dev->shadow_regs[0xc6] = 0x0b; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x01; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x07; dev->shadow_regs[0xe1] = 0x18; /* step size range0 */ dev->shadow_regs[0xe2] = 0xe7; /* ? */ dev->shadow_regs[0xe3] = 0x03; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0xe7; dev->shadow_regs[0xe5] = 0x14; /* step size range1 */ dev->shadow_regs[0xe6] = 0x64; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0xcb; dev->shadow_regs[0xe8] = 0x08; /* step size range2 */ dev->shadow_regs[0xe9] = 0x32; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0xe3; dev->shadow_regs[0xeb] = 0x04; /* step size range3 */ dev->shadow_regs[0xec] = 0x0c; /* bounds of movement range4 */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x08; break; case A920_MOTOR: case X1100_MOTOR: /* ? */ dev->shadow_regs[0xc5] = 0x10; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; dev->shadow_regs[0xc9] = 0x3b; dev->shadow_regs[0xca] = 0x01; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x4d; dev->shadow_regs[0xe1] = 0x1c; /* step size range0 */ dev->shadow_regs[0xe2] = 0x71; /* ? */ dev->shadow_regs[0xe3] = 0x02; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x6d; dev->shadow_regs[0xe5] = 0x15; /* step size range1 */ dev->shadow_regs[0xe6] = 0xdc; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0xad; dev->shadow_regs[0xe8] = 0x07; /* step size range2 */ dev->shadow_regs[0xe9] = 0x1b; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0xe1; dev->shadow_regs[0xeb] = 0x03; /* step size range3 */ dev->shadow_regs[0xec] = 0x07; /* bounds of movement range4 -only for 75dpi grayscale */ dev->shadow_regs[0xed] = 0xc2; dev->shadow_regs[0xee] = 0x02; /* step size range4 */ dev->shadow_regs[0xef] = 0x03; break; } /* set grayscale scan */ dev->shadow_regs[0x2f] = 0x21; /* set ? only for colour? */ dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x00; dev->shadow_regs[0x82] = 0x00; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x81; } /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x0f; /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 1); /* set horizontal resolution */ if (dev->model.sensor_type != X1200_SENSOR) dev->shadow_regs[0x79] = 0x08; } /* 150dpi x 150dpi */ if (resolution == 150) { DBG (5, "sanei_lexmark_low_set_scan_regs(): 150 DPI resolution\n"); if (isColourScan) { switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x34] = 0x08; dev->shadow_regs[0x36] = 0x06; dev->shadow_regs[0x38] = 0x05; dev->shadow_regs[0x39] = 0x07; /* resolution divisor */ dev->shadow_regs[0x79] = 0x08; dev->shadow_regs[0x80] = 0x0a; dev->shadow_regs[0x81] = 0x0c; dev->shadow_regs[0x82] = 0x04; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_B2_SENSOR: dev->shadow_regs[0x34] = 0x0b; dev->shadow_regs[0x36] = 0x0b; dev->shadow_regs[0x38] = 0x0a; dev->shadow_regs[0x80] = 0x05; dev->shadow_regs[0x81] = 0x05; dev->shadow_regs[0x82] = 0x0a; dev->shadow_regs[0x85] = 0x83; dev->shadow_regs[0x86] = 0x7e; dev->shadow_regs[0x87] = 0xad; dev->shadow_regs[0x88] = 0x35; dev->shadow_regs[0x91] = 0xfe; dev->shadow_regs[0x92] = 0xdf; dev->shadow_regs[0x93] = 0x0e; break; case X1100_2C_SENSOR: dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x36] = 0x07; dev->shadow_regs[0x38] = 0x05; dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x02; dev->shadow_regs[0x82] = 0x06; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x34] = 0x03; dev->shadow_regs[0x36] = 0x08; dev->shadow_regs[0x38] = 0x05; dev->shadow_regs[0x80] = 0x0e; dev->shadow_regs[0x81] = 0x07; dev->shadow_regs[0x82] = 0x02; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x04; dev->shadow_regs[0x91] = 0xe0; dev->shadow_regs[0x92] = 0x85; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x36] = 0x05; dev->shadow_regs[0x38] = 0x02; /* data compression dev->shadow_regs[0x40] = 0x90; dev->shadow_regs[0x50] = 0x20; */ /* no data compression */ dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x79] = 0x20; dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x07; dev->shadow_regs[0x82] = 0x0b; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x1e; dev->shadow_regs[0x87] = 0x39; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x92] = 0x92; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x36] = 0x05; dev->shadow_regs[0x38] = 0x02; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x79] = 0x20; dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x07; dev->shadow_regs[0x82] = 0x0b; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x1e; dev->shadow_regs[0x87] = 0x39; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x92] = 0x92; break; } /* switch */ switch (dev->model.motor_type) { case X74_MOTOR: dev->shadow_regs[0xc2] = 0x80; /* ? */ dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x0e; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x0b; dev->shadow_regs[0xc7] = 0x00; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x03; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x41; dev->shadow_regs[0xe1] = 0x09; /* step size range0 */ dev->shadow_regs[0xe2] = 0x89; /* ? */ dev->shadow_regs[0xe3] = 0x02; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x0d; dev->shadow_regs[0xe5] = 0x09; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0d; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0xe8; dev->shadow_regs[0xe8] = 0x02; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* bounds of movement range4 */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; break; case X1100_MOTOR: case A920_MOTOR: /* ? */ dev->shadow_regs[0xc5] = 0x0e; /* ? */ dev->shadow_regs[0xc9] = 0x3a; dev->shadow_regs[0xca] = 0x03; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x61; dev->shadow_regs[0xe1] = 0x0a; /* step size range0 */ dev->shadow_regs[0xe2] = 0xed; /* ? */ dev->shadow_regs[0xe3] = 0x02; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x29; dev->shadow_regs[0xe5] = 0x0a; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0e; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x29; dev->shadow_regs[0xe8] = 0x03; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; break; } /* set colour scan */ dev->shadow_regs[0x2f] = 0x11; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x37] = 0x01; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x83; } /* if (isColourScan) */ else { switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x34] = 0x02; dev->shadow_regs[0x35] = 0x02; dev->shadow_regs[0x36] = 0x04; dev->shadow_regs[0x37] = 0x04; dev->shadow_regs[0x38] = 0x06; dev->shadow_regs[0x39] = 0x07; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0x40] = 0x40; /* resolution divisor */ dev->shadow_regs[0x79] = 0x08; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_B2_SENSOR: dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x35] = 0x04; dev->shadow_regs[0x36] = 0x07; dev->shadow_regs[0x37] = 0x07; dev->shadow_regs[0x38] = 0x0a; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_2C_SENSOR: dev->shadow_regs[0x34] = 0x02; dev->shadow_regs[0x35] = 0x02; dev->shadow_regs[0x36] = 0x04; dev->shadow_regs[0x37] = 0x04; dev->shadow_regs[0x38] = 0x05; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x34] = 0x02; dev->shadow_regs[0x35] = 0x02; dev->shadow_regs[0x36] = 0x04; dev->shadow_regs[0x37] = 0x04; dev->shadow_regs[0x38] = 0x05; dev->shadow_regs[0x85] = 0x0d; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x45; dev->shadow_regs[0x91] = 0x60; dev->shadow_regs[0x92] = 0x8d; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x34] = 0x01; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x02; dev->shadow_regs[0x37] = 0x02; dev->shadow_regs[0x38] = 0x03; /* dev->shadow_regs[0x40] = 0x90; dev->shadow_regs[0x50] = 0x20; */ /* no data compression */ dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x79] = 0x20; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0xff; dev->shadow_regs[0x88] = 0x02; dev->shadow_regs[0x92] = 0x92; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x34] = 0x01; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x02; dev->shadow_regs[0x37] = 0x02; dev->shadow_regs[0x38] = 0x03; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x79] = 0x20; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0xff; dev->shadow_regs[0x88] = 0x02; dev->shadow_regs[0x92] = 0x92; break; } /* switch */ switch (dev->model.motor_type) { case X74_MOTOR: /* ? */ dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x14; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x0b; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x01; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x09; dev->shadow_regs[0xe1] = 0x18; /* step size range0 */ dev->shadow_regs[0xe2] = 0xe9; /* ? */ dev->shadow_regs[0xe3] = 0x03; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x79; dev->shadow_regs[0xe5] = 0x16; /* step size range1 */ dev->shadow_regs[0xe6] = 0x64; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0xcd; dev->shadow_regs[0xe8] = 0x08; /* step size range2 */ dev->shadow_regs[0xe9] = 0x32; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0xe5; dev->shadow_regs[0xeb] = 0x04; /* step size range3 */ dev->shadow_regs[0xec] = 0x0c; /* bounds of movement range4 */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x08; break; case X1100_MOTOR: case A920_MOTOR: /* ? */ dev->shadow_regs[0xc5] = 0x16; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; /* ? */ dev->shadow_regs[0xc9] = 0x3b; dev->shadow_regs[0xca] = 0x01; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0xdd; dev->shadow_regs[0xe1] = 0x18; /* step size range0 */ dev->shadow_regs[0xe2] = 0x01; /* ? */ dev->shadow_regs[0xe3] = 0x03; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x6d; dev->shadow_regs[0xe5] = 0x15; /* step size range1 */ dev->shadow_regs[0xe6] = 0xdc; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0xad; dev->shadow_regs[0xe8] = 0x07; /* step size range2 */ dev->shadow_regs[0xe9] = 0x1b; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0xe1; dev->shadow_regs[0xeb] = 0x03; /* step size range3 */ dev->shadow_regs[0xec] = 0x07; /* step size range4 */ dev->shadow_regs[0xef] = 0x03; break; } /* set grayscale scan */ dev->shadow_regs[0x2f] = 0x21; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x07; /* set ? only for colour? */ dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x00; dev->shadow_regs[0x82] = 0x00; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x81; } /* else (greyscale) */ /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 1); /* hum, horizontal resolution different for X1200 ? */ /* if (dev->model.sensor_type != X1200_SENSOR) dev->shadow_regs[0x79] = 0x20; */ } /*300dpi x 300dpi */ if (resolution == 300) { DBG (5, "sanei_lexmark_low_set_scan_regs(): 300 DPI resolution\n"); if (isColourScan) { switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x34] = 0x08; dev->shadow_regs[0x36] = 0x06; dev->shadow_regs[0x38] = 0x05; dev->shadow_regs[0x39] = 0x07; dev->shadow_regs[0x80] = 0x08; dev->shadow_regs[0x81] = 0x0a; dev->shadow_regs[0x82] = 0x03; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_B2_SENSOR: dev->shadow_regs[0x34] = 0x15; dev->shadow_regs[0x36] = 0x15; dev->shadow_regs[0x38] = 0x14; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x03; dev->shadow_regs[0x80] = 0x0a; dev->shadow_regs[0x81] = 0x0a; dev->shadow_regs[0x82] = 0x06; dev->shadow_regs[0x85] = 0x83; dev->shadow_regs[0x86] = 0x7e; dev->shadow_regs[0x87] = 0xad; dev->shadow_regs[0x88] = 0x35; dev->shadow_regs[0x91] = 0xfe; dev->shadow_regs[0x92] = 0xdf; dev->shadow_regs[0x93] = 0x0e; break; case X1100_2C_SENSOR: dev->shadow_regs[0x34] = 0x08; dev->shadow_regs[0x36] = 0x0d; dev->shadow_regs[0x38] = 0x09; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x03; dev->shadow_regs[0x80] = 0x0e; dev->shadow_regs[0x81] = 0x04; dev->shadow_regs[0x82] = 0x0a; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x34] = 0x06; dev->shadow_regs[0x36] = 0x10; dev->shadow_regs[0x38] = 0x09; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x03; dev->shadow_regs[0x80] = 0x0c; dev->shadow_regs[0x81] = 0x02; dev->shadow_regs[0x82] = 0x04; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x04; dev->shadow_regs[0x91] = 0xe0; dev->shadow_regs[0x92] = 0x85; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x34] = 0x07; dev->shadow_regs[0x36] = 0x09; dev->shadow_regs[0x38] = 0x04; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x03; /* data compression dev->shadow_regs[0x40] = 0x90; dev->shadow_regs[0x50] = 0x20; */ /* no data compression */ dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x0e; dev->shadow_regs[0x82] = 0x06; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x34] = 0x07; dev->shadow_regs[0x36] = 0x09; dev->shadow_regs[0x38] = 0x04; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x03; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x0e; dev->shadow_regs[0x82] = 0x06; break; } switch (dev->model.motor_type) { case X74_MOTOR: /* ? */ dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x12; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x0f; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x5d; dev->shadow_regs[0xe1] = 0x05; /* step size range0 */ dev->shadow_regs[0xe2] = 0xed; /* ? */ dev->shadow_regs[0xe3] = 0x02; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x29; dev->shadow_regs[0xe5] = 0x05; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0d; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* bounds of movement range4 -only for 75dpi grayscale */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; break; case A920_MOTOR: case X1100_MOTOR: /* ? */ dev->shadow_regs[0xc5] = 0x17; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; /* ? */ dev->shadow_regs[0xc9] = 0x3a; dev->shadow_regs[0xca] = 0x0a; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x75; dev->shadow_regs[0xe1] = 0x0a; /* step size range0 */ dev->shadow_regs[0xe2] = 0xdd; /* ? */ dev->shadow_regs[0xe3] = 0x05; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x59; dev->shadow_regs[0xe5] = 0x0a; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0e; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; break; } dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x37] = 0x01; /* set colour scan */ dev->shadow_regs[0x2f] = 0x11; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x83; } else /* greyscale */ { switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x35] = 0x04; dev->shadow_regs[0x36] = 0x08; dev->shadow_regs[0x37] = 0x08; dev->shadow_regs[0x38] = 0x0c; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_B2_SENSOR: dev->shadow_regs[0x34] = 0x08; dev->shadow_regs[0x35] = 0x08; dev->shadow_regs[0x36] = 0x0f; dev->shadow_regs[0x37] = 0x0f; dev->shadow_regs[0x38] = 0x16; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_2C_SENSOR: dev->shadow_regs[0x34] = 0x04; dev->shadow_regs[0x35] = 0x04; dev->shadow_regs[0x36] = 0x07; dev->shadow_regs[0x37] = 0x07; dev->shadow_regs[0x38] = 0x0a; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x34] = 0x03; dev->shadow_regs[0x35] = 0x03; dev->shadow_regs[0x36] = 0x06; dev->shadow_regs[0x37] = 0x06; dev->shadow_regs[0x38] = 0x09; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x04; dev->shadow_regs[0x91] = 0xe0; dev->shadow_regs[0x92] = 0x85; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x34] = 0x02; dev->shadow_regs[0x35] = 0x02; dev->shadow_regs[0x36] = 0x04; dev->shadow_regs[0x37] = 0x04; dev->shadow_regs[0x38] = 0x06; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x34] = 0x02; dev->shadow_regs[0x35] = 0x02; dev->shadow_regs[0x36] = 0x04; dev->shadow_regs[0x37] = 0x04; dev->shadow_regs[0x38] = 0x06; break; } switch (dev->model.motor_type) { case X74_MOTOR: /* ? */ dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x1c; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x0b; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x05; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x29; dev->shadow_regs[0xe1] = 0x17; /* step size range0 */ dev->shadow_regs[0xe2] = 0x8f; /* ? */ dev->shadow_regs[0xe3] = 0x06; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x61; dev->shadow_regs[0xe5] = 0x16; /* step size range1 */ dev->shadow_regs[0xe6] = 0x64; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0xb5; dev->shadow_regs[0xe8] = 0x08; /* step size range2 */ dev->shadow_regs[0xe9] = 0x32; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x0c; /* bounds of movement range4 -only for 75dpi grayscale */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x08; break; case A920_MOTOR: case X1100_MOTOR: /* ? */ dev->shadow_regs[0xc5] = 0x19; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; /* ? */ dev->shadow_regs[0xc9] = 0x3a; dev->shadow_regs[0xca] = 0x08; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0xe3; dev->shadow_regs[0xe1] = 0x18; /* step size range0 */ dev->shadow_regs[0xe2] = 0x03; /* ? */ dev->shadow_regs[0xe3] = 0x06; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x2b; dev->shadow_regs[0xe5] = 0x17; /* step size range1 */ dev->shadow_regs[0xe6] = 0xdc; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0xb3; dev->shadow_regs[0xe8] = 0x07; /* step size range2 */ dev->shadow_regs[0xe9] = 0x1b; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x07; /* step size range4 */ dev->shadow_regs[0xef] = 0x03; break; } /* switch motortype */ /* set grayscale scan */ dev->shadow_regs[0x2f] = 0x21; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x03; /* set ? only for colour? */ dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x00; dev->shadow_regs[0x82] = 0x00; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x81; } /* else (gray) */ /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 1); /* set horizontal resolution */ dev->shadow_regs[0x79] = 0x20; } /* 600dpi x 600dpi */ if (resolution == 600) { DBG (5, "sanei_lexmark_low_set_scan_regs(): 600 DPI resolution\n"); if (isColourScan) { /* 600 dpi color doesn't work for X74 yet */ if (dev->model.sensor_type == X74_SENSOR) return SANE_STATUS_INVAL; switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x34] = 0x10; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x0c; dev->shadow_regs[0x37] = 0x01; dev->shadow_regs[0x38] = 0x09; dev->shadow_regs[0x80] = 0x02; dev->shadow_regs[0x81] = 0x08; dev->shadow_regs[0x82] = 0x08; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; /*dev->shadow_regs[0x34] = 0x08; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x36] = 0x06; dev->shadow_regs[0x37] = 0x01; dev->shadow_regs[0x38] = 0x05; dev->shadow_regs[0x80] = 0x09; dev->shadow_regs[0x81] = 0x0c; dev->shadow_regs[0x82] = 0x04; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; */ case X1100_B2_SENSOR: dev->shadow_regs[0x34] = 0x15; dev->shadow_regs[0x36] = 0x15; dev->shadow_regs[0x38] = 0x14; dev->shadow_regs[0x80] = 0x02; dev->shadow_regs[0x81] = 0x02; dev->shadow_regs[0x82] = 0x08; dev->shadow_regs[0x85] = 0x83; dev->shadow_regs[0x86] = 0x7e; dev->shadow_regs[0x87] = 0xad; dev->shadow_regs[0x88] = 0x35; dev->shadow_regs[0x91] = 0xfe; dev->shadow_regs[0x92] = 0xdf; dev->shadow_regs[0x93] = 0x0e; break; case X1100_2C_SENSOR: dev->shadow_regs[0x34] = 0x08; dev->shadow_regs[0x36] = 0x0d; dev->shadow_regs[0x38] = 0x09; dev->shadow_regs[0x80] = 0x0e; dev->shadow_regs[0x81] = 0x02; dev->shadow_regs[0x82] = 0x0a; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x34] = 0x06; dev->shadow_regs[0x36] = 0x0f; dev->shadow_regs[0x38] = 0x09; dev->shadow_regs[0x79] = 0x40; dev->shadow_regs[0x80] = 0x0e; dev->shadow_regs[0x81] = 0x0e; dev->shadow_regs[0x82] = 0x00; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x04; dev->shadow_regs[0x91] = 0x60; dev->shadow_regs[0x92] = 0x85; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x34] = 0x07; dev->shadow_regs[0x36] = 0x0a; dev->shadow_regs[0x38] = 0x04; /* data compression dev->shadow_regs[0x40] = 0x90; dev->shadow_regs[0x50] = 0x20; */ /* no data compression */ dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x80] = 0x02; dev->shadow_regs[0x81] = 0x00; dev->shadow_regs[0x82] = 0x06; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x34] = 0x0d; dev->shadow_regs[0x36] = 0x13; dev->shadow_regs[0x38] = 0x10; dev->shadow_regs[0x80] = 0x04; dev->shadow_regs[0x81] = 0x0e; dev->shadow_regs[0x82] = 0x08; dev->shadow_regs[0x85] = 0x02; dev->shadow_regs[0x86] = 0x3b; dev->shadow_regs[0x87] = 0x0f; dev->shadow_regs[0x88] = 0x24; dev->shadow_regs[0x91] = 0x19; dev->shadow_regs[0x92] = 0x30; dev->shadow_regs[0x93] = 0x0e; dev->shadow_regs[0xc5] = 0x17; dev->shadow_regs[0xc6] = 0x09; dev->shadow_regs[0xca] = 0x0a; break; } switch (dev->model.motor_type) { case X74_MOTOR: /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x81; /* ? */ dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x21; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x20; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x00; dev->shadow_regs[0xe1] = 0x00; /* step size range0 */ dev->shadow_regs[0xe2] = 0xbf; /* ? */ dev->shadow_regs[0xe3] = 0x05; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x00; dev->shadow_regs[0xe5] = 0x00; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0d; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* bounds of movement range4 -only for 75dpi grayscale */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; break; case A920_MOTOR: case X1100_MOTOR: /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x86; /* ? */ dev->shadow_regs[0xc5] = 0x27; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x0c; /* ? */ dev->shadow_regs[0xc9] = 0x3a; dev->shadow_regs[0xca] = 0x1a; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x57; dev->shadow_regs[0xe1] = 0x0a; /* step size range0 */ dev->shadow_regs[0xe2] = 0xbf; /* ? */ dev->shadow_regs[0xe3] = 0x05; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x3b; dev->shadow_regs[0xe5] = 0x0a; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0e; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; break; } /* set colour scan */ dev->shadow_regs[0x2f] = 0x11; dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x37] = 0x01; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x03; /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 2); } else { switch (dev->model.sensor_type) { case X74_SENSOR: dev->shadow_regs[0x2c] = 0x04; dev->shadow_regs[0x2d] = 0x46; dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x35] = 0x05; dev->shadow_regs[0x36] = 0x0b; dev->shadow_regs[0x37] = 0x0b; dev->shadow_regs[0x38] = 0x11; dev->shadow_regs[0x40] = 0x40; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_B2_SENSOR: dev->shadow_regs[0x34] = 0x11; dev->shadow_regs[0x35] = 0x11; dev->shadow_regs[0x36] = 0x21; dev->shadow_regs[0x37] = 0x21; dev->shadow_regs[0x38] = 0x31; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case X1100_2C_SENSOR: dev->shadow_regs[0x34] = 0x07; dev->shadow_regs[0x35] = 0x07; dev->shadow_regs[0x36] = 0x0d; dev->shadow_regs[0x37] = 0x0d; dev->shadow_regs[0x38] = 0x13; dev->shadow_regs[0x85] = 0x20; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; break; case A920_SENSOR: dev->shadow_regs[0x34] = 0x05; dev->shadow_regs[0x35] = 0x05; dev->shadow_regs[0x36] = 0x0b; dev->shadow_regs[0x37] = 0x0b; dev->shadow_regs[0x38] = 0x11; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x04; dev->shadow_regs[0x91] = 0xe0; dev->shadow_regs[0x92] = 0x85; dev->shadow_regs[0x93] = 0x0e; break; case X1200_SENSOR: dev->shadow_regs[0x34] = 0x03; dev->shadow_regs[0x35] = 0x03; dev->shadow_regs[0x36] = 0x07; dev->shadow_regs[0x37] = 0x07; dev->shadow_regs[0x38] = 0x0b; /* data compression dev->shadow_regs[0x40] = 0x90; dev->shadow_regs[0x50] = 0x20; */ /* no data compression */ dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0xff; dev->shadow_regs[0x88] = 0x02; dev->shadow_regs[0x92] = 0x00; break; case X1200_USB2_SENSOR: dev->shadow_regs[0x34] = 0x03; dev->shadow_regs[0x35] = 0x03; dev->shadow_regs[0x36] = 0x07; dev->shadow_regs[0x37] = 0x07; dev->shadow_regs[0x38] = 0x0b; dev->shadow_regs[0x40] = 0x80; dev->shadow_regs[0x50] = 0x00; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0xff; dev->shadow_regs[0x88] = 0x02; dev->shadow_regs[0x92] = 0x00; break; } switch (dev->model.motor_type) { case X74_MOTOR: /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 1); /* ? */ dev->shadow_regs[0xc4] = 0x20; dev->shadow_regs[0xc5] = 0x22; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x0b; dev->shadow_regs[0xc8] = 0x04; dev->shadow_regs[0xc9] = 0x39; dev->shadow_regs[0xca] = 0x1f; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x2f; dev->shadow_regs[0xe1] = 0x11; /* step size range0 */ dev->shadow_regs[0xe2] = 0x9f; /* ? */ dev->shadow_regs[0xe3] = 0x0f; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0xcb; dev->shadow_regs[0xe5] = 0x10; /* step size range1 */ dev->shadow_regs[0xe6] = 0x64; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x32; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x0c; /* bounds of movement range4 -only for 75dpi grayscale */ dev->shadow_regs[0xed] = 0x00; dev->shadow_regs[0xee] = 0x00; /* step size range4 */ dev->shadow_regs[0xef] = 0x08; break; case X1100_MOTOR: case A920_MOTOR: /* set ? only for colour? */ dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x00; dev->shadow_regs[0x82] = 0x00; /* ? */ dev->shadow_regs[0xc5] = 0x22; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; /* ? */ dev->shadow_regs[0xc9] = 0x3b; dev->shadow_regs[0xca] = 0x1f; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0xf7; dev->shadow_regs[0xe1] = 0x16; /* step size range0 */ dev->shadow_regs[0xe2] = 0x87; /* ? */ dev->shadow_regs[0xe3] = 0x13; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x1b; dev->shadow_regs[0xe5] = 0x16; /* step size range1 */ dev->shadow_regs[0xe6] = 0xdc; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x1b; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x07; /* step size range4 */ dev->shadow_regs[0xef] = 0x03; break; } /* set grayscale scan */ dev->shadow_regs[0x2f] = 0x21; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x01; /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 1); /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x81; } /* else (grayscale) */ /* set horizontal resolution */ dev->shadow_regs[0x79] = 0x40; } /*600dpi x 1200dpi */ if (resolution == 1200) { DBG (5, "sanei_lexmark_low_set_scan_regs(): 1200 DPI resolution\n"); /* 1200 dpi doesn't work for X74 yet */ if (dev->model.sensor_type == X74_SENSOR) return SANE_STATUS_INVAL; if (isColourScan) { /* set colour scan */ dev->shadow_regs[0x2f] = 0x11; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x01; /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 2); if (dev->model.sensor_type == X1100_B2_SENSOR) { /* set ? */ dev->shadow_regs[0x34] = 0x29; dev->shadow_regs[0x36] = 0x29; dev->shadow_regs[0x38] = 0x28; /* set ? */ dev->shadow_regs[0x80] = 0x04; dev->shadow_regs[0x81] = 0x04; dev->shadow_regs[0x82] = 0x08; dev->shadow_regs[0x85] = 0x83; dev->shadow_regs[0x86] = 0x7e; dev->shadow_regs[0x87] = 0xad; dev->shadow_regs[0x88] = 0x35; dev->shadow_regs[0x91] = 0xfe; dev->shadow_regs[0x92] = 0xdf; } else { /* A920 case */ dev->shadow_regs[0x34] = 0x0c; dev->shadow_regs[0x36] = 0x1e; dev->shadow_regs[0x38] = 0x10; dev->shadow_regs[0x80] = 0x0c; dev->shadow_regs[0x81] = 0x08; dev->shadow_regs[0x82] = 0x0c; dev->shadow_regs[0x85] = 0x05; dev->shadow_regs[0x86] = 0x14; dev->shadow_regs[0x87] = 0x06; dev->shadow_regs[0x88] = 0x04; dev->shadow_regs[0x91] = 0x60; dev->shadow_regs[0x92] = 0x85; } dev->shadow_regs[0x35] = 0x01; dev->shadow_regs[0x37] = 0x01; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x01; dev->shadow_regs[0x93] = 0x0e; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x86; /* ? */ dev->shadow_regs[0xc5] = 0x41; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x0c; /* ? */ dev->shadow_regs[0xc9] = 0x3a; dev->shadow_regs[0xca] = 0x40; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x00; dev->shadow_regs[0xe1] = 0x00; /* step size range0 */ dev->shadow_regs[0xe2] = 0x85; /* ? */ dev->shadow_regs[0xe3] = 0x0b; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x00; dev->shadow_regs[0xe5] = 0x00; /* step size range1 */ dev->shadow_regs[0xe6] = 0x0e; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x05; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x01; /* step size range4 */ dev->shadow_regs[0xef] = 0x01; } else { /* set grayscale scan */ dev->shadow_regs[0x2f] = 0x21; /* set ? */ dev->shadow_regs[0x34] = 0x22; dev->shadow_regs[0x35] = 0x22; dev->shadow_regs[0x36] = 0x42; dev->shadow_regs[0x37] = 0x42; dev->shadow_regs[0x38] = 0x62; /* set motor resolution divisor */ dev->shadow_regs[0x39] = 0x01; /* set # of head moves per CIS read */ rts88xx_set_scan_frequency (dev->shadow_regs, 0); /* set ? only for colour? */ dev->shadow_regs[0x80] = 0x00; dev->shadow_regs[0x81] = 0x00; dev->shadow_regs[0x82] = 0x00; dev->shadow_regs[0x85] = 0x00; dev->shadow_regs[0x86] = 0x00; dev->shadow_regs[0x87] = 0x00; dev->shadow_regs[0x88] = 0x00; dev->shadow_regs[0x91] = 0x00; dev->shadow_regs[0x92] = 0x00; dev->shadow_regs[0x93] = 0x06; /* Motor enable & Coordinate space denominator */ dev->shadow_regs[0xc3] = 0x81; /* ? */ dev->shadow_regs[0xc5] = 0x41; /* Movement direction & step size */ dev->shadow_regs[0xc6] = 0x09; /* ? */ dev->shadow_regs[0xc9] = 0x3a; dev->shadow_regs[0xca] = 0x40; /* bounds of movement range0 */ dev->shadow_regs[0xe0] = 0x00; dev->shadow_regs[0xe1] = 0x00; /* step size range0 */ dev->shadow_regs[0xe2] = 0xc7; /* ? */ dev->shadow_regs[0xe3] = 0x29; /* bounds of movement range1 */ dev->shadow_regs[0xe4] = 0x00; dev->shadow_regs[0xe5] = 0x00; /* step size range1 */ dev->shadow_regs[0xe6] = 0xdc; /* bounds of movement range2 */ dev->shadow_regs[0xe7] = 0x00; dev->shadow_regs[0xe8] = 0x00; /* step size range2 */ dev->shadow_regs[0xe9] = 0x1b; /* bounds of movement range3 */ dev->shadow_regs[0xea] = 0x00; dev->shadow_regs[0xeb] = 0x00; /* step size range3 */ dev->shadow_regs[0xec] = 0x07; /* step size range4 */ dev->shadow_regs[0xef] = 0x03; } /* set horizontal resolution */ dev->shadow_regs[0x79] = 0x40; } /* is calibration has been done, we override fixed settings with detected ones */ if (calibrated) { /* override fixed values with ones from calibration */ if (rts88xx_is_color (dev->shadow_regs)) { rts88xx_set_offset (dev->shadow_regs, dev->offset.red, dev->offset.green, dev->offset.blue); rts88xx_set_gain (dev->shadow_regs, dev->gain.red, dev->gain.green, dev->gain.blue); } else { rts88xx_set_offset (dev->shadow_regs, dev->offset.gray, dev->offset.gray, dev->offset.gray); rts88xx_set_gain (dev->shadow_regs, dev->gain.gray, dev->gain.gray, dev->gain.gray); } } DBG (2, "sanei_lexmark_low_set_scan_regs: end.\n"); return SANE_STATUS_GOOD; } SANE_Status sanei_lexmark_low_start_scan (Lexmark_Device * dev) { SANE_Int devnum; static SANE_Byte command4_block[] = { 0x90, 0x00, 0x00, 0x03 }; static SANE_Byte command5_block[] = { 0x80, 0xb3, 0x00, 0x01 }; SANE_Byte poll_result[3]; SANE_Byte read_result; SANE_Bool scan_head_moving; size_t size; devnum = dev->devnum; dev->transfer_buffer = NULL; /* No data xferred yet */ DBG (2, "sanei_lexmark_low_start_scan:\n"); /* 80 b3 00 01 - poll for scanner not moving */ scan_head_moving = SANE_TRUE; while (scan_head_moving) { size = 4; low_usb_bulk_write (devnum, command5_block, &size); size = 0x1; low_usb_bulk_read (devnum, &read_result, &size); if ((read_result & 0xF) == 0x0) { scan_head_moving = SANE_FALSE; } /* F.O. Should be a timeout here so we don't hang if something breaks */ #ifdef FAKE_USB scan_head_moving = SANE_FALSE; #endif } /* Clear C6 */ low_clr_c6 (devnum); /* Stop the scanner */ low_stop_mvmt (devnum); /*Set regs x2 */ dev->shadow_regs[0x32] = 0x00; low_write_all_regs (devnum, dev->shadow_regs); dev->shadow_regs[0x32] = 0x40; low_write_all_regs (devnum, dev->shadow_regs); /* Start Scan */ rts88xx_commit (devnum, dev->shadow_regs[0x2c]); /* We start with 0 bytes remaining to be read */ dev->bytes_remaining = 0; /* and 0 bytes in the transfer buffer */ dev->bytes_in_buffer = 0; dev->bytes_read = 0; /* Poll the available byte count until not 0 */ while (1) { size = 4; low_usb_bulk_write (devnum, command4_block, &size); size = 0x3; low_usb_bulk_read (devnum, poll_result, &size); if (! (poll_result[0] == 0 && poll_result[1] == 0 && poll_result[2] == 0)) { /* if result != 00 00 00 we got data */ /* data_size should be used to set bytes_remaining */ /* data_size is set from sane_get_parameters () */ dev->bytes_remaining = dev->data_size; /* Initialize the read buffer */ read_buffer_init (dev, dev->params.bytes_per_line); return SANE_STATUS_GOOD; } size = 4; /* I'm not sure why the Windows driver does this - probably a timeout? */ low_usb_bulk_write (devnum, command5_block, &size); size = 0x1; low_usb_bulk_read (devnum, &read_result, &size); if (read_result != 0x68) { dev->bytes_remaining = 0; return SANE_STATUS_IO_ERROR; } } DBG (2, "sanei_lexmark_low_start_scan: end.\n"); return SANE_STATUS_GOOD; } long sanei_lexmark_low_read_scan_data (SANE_Byte * data, SANE_Int size, Lexmark_Device * dev) { SANE_Bool isColourScan, isGrayScan; static SANE_Byte command1_block[] = { 0x91, 0x00, 0xff, 0xc0 }; size_t cmd_size, xfer_request; long bytes_read; SANE_Bool even_byte; SANE_Status status; int i, k, val; DBG (2, "sanei_lexmark_low_read_scan_data:\n"); /* colour mode */ isGrayScan = SANE_FALSE; if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) isColourScan = SANE_TRUE; else { isColourScan = SANE_FALSE; /* grayscale mode */ if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) isGrayScan = SANE_TRUE; } /* Check if we have a transfer buffer. Create one and fill it if we don't */ if (dev->transfer_buffer == NULL) { if (dev->bytes_remaining > 0) { if (dev->bytes_remaining > MAX_XFER_SIZE) xfer_request = MAX_XFER_SIZE; else xfer_request = dev->bytes_remaining; command1_block[2] = (SANE_Byte) (xfer_request >> 8); command1_block[3] = (SANE_Byte) (xfer_request & 0xFF); /* wait for data */ status = low_poll_data (dev->devnum); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_lexmark_low_read_scan_data: time-out while waiting for data.\n"); return status; } /* Create buffer to hold the amount we will request */ dev->transfer_buffer = (SANE_Byte *) malloc (MAX_XFER_SIZE); if (dev->transfer_buffer == NULL) return SANE_STATUS_NO_MEM; /* Fill it */ /* Write: 91 00 (xfer_size) */ cmd_size = 4; low_usb_bulk_write (dev->devnum, command1_block, &cmd_size); /* Read: xfer_size bytes */ cmd_size = xfer_request; low_usb_bulk_read (dev->devnum, dev->transfer_buffer, &cmd_size); /* apply shading coefficients */ k = dev->bytes_read % dev->read_buffer->linesize; for (i = 0; i < (int) cmd_size; i++) { val = dev->transfer_buffer[i]; val = (int) ((float) val * dev->shading_coeff[k] + 0.5); if (val > 255) val = 255; dev->transfer_buffer[i] = val; k++; if ((size_t) k == dev->read_buffer->linesize) k = 0; } /* advance by the amount actually read from device */ dev->bytes_read += cmd_size; dev->bytes_remaining -= cmd_size; dev->bytes_in_buffer = cmd_size; dev->read_pointer = dev->transfer_buffer; DBG (2, "sanei_lexmark_low_read_scan_data:\n"); DBG (2, " Filled a buffer from the scanner\n"); DBG (2, " bytes_remaining: %lu\n", (u_long) dev->bytes_remaining); DBG (2, " bytes_in_buffer: %lu\n", (u_long) dev->bytes_in_buffer); DBG (2, " read_pointer: %p\n", dev->read_pointer); } } DBG (5, "READ BUFFER INFO: \n"); DBG (5, " write ptr: %p\n", dev->read_buffer->writeptr); DBG (5, " read ptr: %p\n", dev->read_buffer->readptr); DBG (5, " max write ptr: %p\n", dev->read_buffer->max_writeptr); DBG (5, " buffer size: %lu\n", (u_long) dev->read_buffer->size); DBG (5, " line size: %lu\n", (u_long) dev->read_buffer->linesize); DBG (5, " empty: %d\n", dev->read_buffer->empty); DBG (5, " line no: %d\n", dev->read_buffer->image_line_no); /* If there is space in the read buffer, copy the transfer buffer over */ if (read_buffer_bytes_available (dev->read_buffer) >= dev->bytes_in_buffer) { even_byte = SANE_TRUE; while (dev->bytes_in_buffer) { /* Colour Scan */ if (isColourScan) { if (even_byte) read_buffer_add_byte (dev->read_buffer, dev->read_pointer + 1); else read_buffer_add_byte (dev->read_buffer, dev->read_pointer - 1); even_byte = !even_byte; } /* Gray Scan */ else if (isGrayScan) { if (even_byte) read_buffer_add_byte_gray (dev->read_buffer, dev->read_pointer + 1); else read_buffer_add_byte_gray (dev->read_buffer, dev->read_pointer - 1); even_byte = !even_byte; } /* Lineart Scan */ else { if (even_byte) read_buffer_add_bit_lineart (dev->read_buffer, dev->read_pointer + 1, dev->threshold); else read_buffer_add_bit_lineart (dev->read_buffer, dev->read_pointer - 1, dev->threshold); even_byte = !even_byte; } dev->read_pointer = dev->read_pointer + sizeof (SANE_Byte); dev->bytes_in_buffer--; } /* free the transfer buffer */ free (dev->transfer_buffer); dev->transfer_buffer = NULL; } DBG (5, "READ BUFFER INFO: \n"); DBG (5, " write ptr: %p\n", dev->read_buffer->writeptr); DBG (5, " read ptr: %p\n", dev->read_buffer->readptr); DBG (5, " max write ptr: %p\n", dev->read_buffer->max_writeptr); DBG (5, " buffer size: %lu\n", (u_long) dev->read_buffer->size); DBG (5, " line size: %lu\n", (u_long) dev->read_buffer->linesize); DBG (5, " empty: %d\n", dev->read_buffer->empty); DBG (5, " line no: %d\n", dev->read_buffer->image_line_no); /* Read blocks out of read buffer */ bytes_read = read_buffer_get_bytes (dev->read_buffer, data, size); DBG (2, "sanei_lexmark_low_read_scan_data:\n"); DBG (2, " Copying lines from buffer to data\n"); DBG (2, " bytes_remaining: %lu\n", (u_long) dev->bytes_remaining); DBG (2, " bytes_in_buffer: %lu\n", (u_long) dev->bytes_in_buffer); DBG (2, " read_pointer: %p\n", dev->read_buffer->readptr); DBG (2, " bytes_read %lu\n", (u_long) bytes_read); /* if no more bytes to xfer and read buffer empty we're at the end */ if ((dev->bytes_remaining == 0) && read_buffer_is_empty (dev->read_buffer)) { if (!dev->eof) { DBG (2, "sanei_lexmark_low_read_scan_data: EOF- parking the scanner\n"); dev->eof = SANE_TRUE; low_rewind (dev, dev->shadow_regs); } else { DBG (2, "ERROR: Why are we trying to set eof more than once?\n"); } } DBG (2, "sanei_lexmark_low_read_scan_data: end.\n"); return bytes_read; } void low_rewind (Lexmark_Device * dev, SANE_Byte * regs) { SANE_Int new_location; SANE_Int location; SANE_Int scale; DBG (2, "low_rewind: \n"); /* We rewind at 1200dpi resolution. We rely on content of shadow registers to compute the number of lines at 1200 dpi to go back */ /* first move to start of scanning area */ scale = 600 / dev->val[OPT_RESOLUTION].w; new_location = ((dev->val[OPT_BR_Y].w / scale) * scale) * 2; /* then add distance to go to the "origin dot" */ if (rts88xx_is_color (regs)) new_location += 400; else new_location += 420; if (dev->model.sensor_type == X74_SENSOR) new_location += 150; location = new_location - 1; DBG (2, "low_rewind: %d=>new_location=%d\n", dev->val[OPT_BR_Y].w, new_location); /* stops any pending scan */ low_clr_c6 (dev->devnum); low_cancel (dev->devnum); /* set regs for rewind */ regs[0x2f] = 0xa1; regs[0x32] = 0x00; regs[0x39] = 0x00; /* all other regs are always the same. these ones change with parameters */ /* the following 4 regs are the location 61,60 and the location+1 63,62 */ regs[0x60] = LOBYTE (location); regs[0x61] = HIBYTE (location); regs[0x62] = LOBYTE (new_location); regs[0x63] = HIBYTE (new_location); switch (dev->model.motor_type) { case X74_MOTOR: regs[0xc3] = 0x81; regs[0xc6] = 0x03; regs[0xc9] = 0x39; regs[0xe0] = 0x81; regs[0xe1] = 0x16; regs[0xe2] = 0xe1; regs[0xe3] = 0x04; regs[0xe4] = 0xe7; regs[0xe5] = 0x14; regs[0xe6] = 0x64; regs[0xe7] = 0xd5; regs[0xe8] = 0x08; regs[0xe9] = 0x32; regs[0xea] = 0xed; regs[0xeb] = 0x04; regs[0xec] = 0x0c; regs[0xef] = 0x08; break; case X1100_MOTOR: case A920_MOTOR: /* set regs for rewind */ regs[0x79] = 0x40; regs[0xb2] = 0x04; regs[0xc3] = 0x81; regs[0xc6] = 0x01; regs[0xc9] = 0x3b; regs[0xe0] = 0x2b; regs[0xe1] = 0x17; regs[0xe2] = 0xe7; regs[0xe3] = 0x03; regs[0xe6] = 0xdc; regs[0xe7] = 0xb3; regs[0xe8] = 0x07; regs[0xe9] = 0x1b; regs[0xea] = 0x00; regs[0xeb] = 0x00; regs[0xec] = 0x07; regs[0xef] = 0x03; break; } /* starts scan */ low_start_scan (dev->devnum, regs); DBG (2, "low_rewind: end.\n"); } SANE_Status read_buffer_init (Lexmark_Device * dev, int bytesperline) { size_t no_lines_in_buffer; DBG (2, "read_buffer_init: Start\n"); dev->read_buffer = (Read_Buffer *) malloc (sizeof (Read_Buffer)); if (dev->read_buffer == NULL) return SANE_STATUS_NO_MEM; dev->read_buffer->linesize = bytesperline; dev->read_buffer->gray_offset = 0; dev->read_buffer->max_gray_offset = bytesperline - 1; dev->read_buffer->region = RED; dev->read_buffer->red_offset = 0; dev->read_buffer->green_offset = 1; dev->read_buffer->blue_offset = 2; dev->read_buffer->max_red_offset = bytesperline - 3; dev->read_buffer->max_green_offset = bytesperline - 2; dev->read_buffer->max_blue_offset = bytesperline - 1; no_lines_in_buffer = 3 * MAX_XFER_SIZE / bytesperline; dev->read_buffer->size = bytesperline * no_lines_in_buffer; dev->read_buffer->data = (SANE_Byte *) malloc (dev->read_buffer->size); if (dev->read_buffer->data == NULL) return SANE_STATUS_NO_MEM; dev->read_buffer->readptr = dev->read_buffer->data; dev->read_buffer->writeptr = dev->read_buffer->data; dev->read_buffer->max_writeptr = dev->read_buffer->data + (no_lines_in_buffer - 1) * bytesperline; dev->read_buffer->empty = SANE_TRUE; dev->read_buffer->image_line_no = 0; dev->read_buffer->bit_counter = 0; dev->read_buffer->max_lineart_offset = dev->params.pixels_per_line - 1; return SANE_STATUS_GOOD; } SANE_Status read_buffer_free (Read_Buffer * read_buffer) { DBG (2, "read_buffer_free:\n"); if (read_buffer) { free (read_buffer->data); free (read_buffer); read_buffer = NULL; } return SANE_STATUS_GOOD; } size_t read_buffer_bytes_available (Read_Buffer * rb) { DBG (2, "read_buffer_bytes_available:\n"); if (rb->empty) return rb->size; else if ((size_t) abs (rb->writeptr - rb->readptr) < rb->linesize) return 0; /* ptrs are less than one line apart */ else if (rb->writeptr < rb->readptr) return (rb->readptr - rb->writeptr - rb->linesize); else return (rb->size + rb->readptr - rb->writeptr - rb->linesize); } SANE_Status read_buffer_add_byte (Read_Buffer * rb, SANE_Byte * byte_pointer) { /* DBG(2, "read_buffer_add_byte:\n"); */ /* F.O. Need to fix the endian byte ordering here */ switch (rb->region) { case RED: *(rb->writeptr + rb->red_offset) = *byte_pointer; if (rb->red_offset == rb->max_red_offset) { rb->red_offset = 0; rb->region = GREEN; } else rb->red_offset = rb->red_offset + (3 * sizeof (SANE_Byte)); return SANE_STATUS_GOOD; case GREEN: *(rb->writeptr + rb->green_offset) = *byte_pointer; if (rb->green_offset == rb->max_green_offset) { rb->green_offset = 1; rb->region = BLUE; } else rb->green_offset = rb->green_offset + (3 * sizeof (SANE_Byte)); return SANE_STATUS_GOOD; case BLUE: *(rb->writeptr + rb->blue_offset) = *byte_pointer; if (rb->blue_offset == rb->max_blue_offset) { rb->image_line_no++; /* finished a line. read_buffer no longer empty */ rb->empty = SANE_FALSE; rb->blue_offset = 2; rb->region = RED; if (rb->writeptr == rb->max_writeptr) rb->writeptr = rb->data; /* back to beginning of buffer */ else rb->writeptr = rb->writeptr + rb->linesize; /* next line */ } else rb->blue_offset = rb->blue_offset + (3 * sizeof (SANE_Byte)); return SANE_STATUS_GOOD; } return SANE_STATUS_GOOD; } SANE_Status read_buffer_add_byte_gray (Read_Buffer * rb, SANE_Byte * byte_pointer) { /* DBG(2, "read_buffer_add_byte_gray:\n"); */ *(rb->writeptr + rb->gray_offset) = *byte_pointer; if (rb->gray_offset == rb->max_gray_offset) { rb->image_line_no++; /* finished a line. read_buffer no longer empty */ rb->empty = SANE_FALSE; rb->gray_offset = 0; if (rb->writeptr == rb->max_writeptr) rb->writeptr = rb->data; /* back to beginning of buffer */ else rb->writeptr = rb->writeptr + rb->linesize; /* next line */ } else rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte)); return SANE_STATUS_GOOD; } SANE_Status read_buffer_add_bit_lineart (Read_Buffer * rb, SANE_Byte * byte_pointer, SANE_Byte threshold) { SANE_Byte tmpByte; SANE_Byte *currentBytePtr; SANE_Int bitIndex; /* DBG(2, "read_buffer_add_bit_lineart:\n"); */ /* threshold = 0x80; */ tmpByte = 0; /* Create a bit by comparing incoming byte to threshold */ if (*byte_pointer <= threshold) { tmpByte = 128; } /* Calculate the bit index in the current byte */ bitIndex = rb->bit_counter % 8; /* Move the bit to its correct position in the temporary byte */ tmpByte = tmpByte >> bitIndex; /* Get the pointer to the current byte */ currentBytePtr = rb->writeptr + rb->gray_offset; /* If this is the first write to this byte, clear the byte */ if (bitIndex == 0) *currentBytePtr = 0; /* Set the value of the bit in the current byte */ *currentBytePtr = *currentBytePtr | tmpByte; /* last bit in the line? */ if (rb->bit_counter == rb->max_lineart_offset) { /* Check if we're at the last byte of the line - error if not */ if (rb->gray_offset != rb->max_gray_offset) { DBG (5, "read_buffer_add_bit_lineart:\n"); DBG (5, " Last bit of line is not last byte.\n"); DBG (5, " Bit Index: %d, Byte Index: %d. \n", rb->bit_counter, rb->max_gray_offset); return SANE_STATUS_INVAL; } rb->image_line_no++; /* line finished read_buffer no longer empty */ rb->empty = SANE_FALSE; rb->gray_offset = 0; /* are we at the last line in the read buffer ? */ if (rb->writeptr == rb->max_writeptr) rb->writeptr = rb->data; /* back to beginning of buffer */ else rb->writeptr = rb->writeptr + rb->linesize; /* next line */ /* clear the bit counter */ rb->bit_counter = 0; } /* last bit in the byte? */ else if (bitIndex == 7) { /* Not at the end of the line, but byte done. Increment byte offset */ rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte)); /* increment bit counter */ rb->bit_counter++; } else { /* else increment bit counter */ rb->bit_counter++; } return SANE_STATUS_GOOD; } size_t read_buffer_get_bytes (Read_Buffer * rb, SANE_Byte * buffer, size_t rqst_size) { /* Read_Buffer *rb; */ size_t available_bytes; /* rb = read_buffer; */ if (rb->empty) return 0; else if (rb->writeptr > rb->readptr) { available_bytes = rb->writeptr - rb->readptr; if (available_bytes <= rqst_size) { /* We can read from the read pointer up to the write pointer */ memcpy (buffer, rb->readptr, available_bytes); rb->readptr = rb->writeptr; rb->empty = SANE_TRUE; return available_bytes; } else { /* We can read from the full request size */ memcpy (buffer, rb->readptr, rqst_size); rb->readptr = rb->readptr + rqst_size; return rqst_size; } } else { /* The read pointer is ahead of the write pointer. Its wrapped around. */ /* We can read to the end of the buffer and make a recursive call to */ /* read any available lines at the beginning of the buffer */ available_bytes = rb->data + rb->size - rb->readptr; if (available_bytes <= rqst_size) { /* We can read from the read pointer up to the end of the buffer */ memcpy (buffer, rb->readptr, available_bytes); rb->readptr = rb->data; if (rb->writeptr == rb->readptr) rb->empty = SANE_TRUE; return available_bytes + read_buffer_get_bytes (rb, buffer + available_bytes, rqst_size - available_bytes); } else { /* We can read from the full request size */ memcpy (buffer, rb->readptr, rqst_size); rb->readptr = rb->readptr + rqst_size; return rqst_size; } } } SANE_Bool read_buffer_is_empty (Read_Buffer * read_buffer) { return read_buffer->empty; } /* * average a width*height rgb/monochrome area * return values in given pointers */ static int average_area (SANE_Byte * regs, SANE_Byte * data, int width, int height, int *ra, int *ga, int *ba) { int x, y; int global = 0; int rc, gc, bc; *ra = 0; *ga = 0; *ba = 0; rc = 0; gc = 0; bc = 0; if (rts88xx_is_color (regs)) { for (x = 0; x < width; x++) for (y = 0; y < height; y++) { rc += data[3 * width * y + x]; gc += data[3 * width * y + width + x]; bc += data[3 * width * y + 2 * width + x]; } global = (rc + gc + bc) / (3 * width * height); *ra = rc / (width * height); *ga = gc / (width * height); *ba = bc / (width * height); } else { for (x = 0; x < width; x++) for (y = 0; y < height; y++) { gc += data[width * y + x]; } global = gc / (width * height); *ga = gc / (width * height); } DBG (7, "average_area: global=%d, red=%d, green=%d, blue=%d\n", global, *ra, *ga, *ba); return global; } /** * we scan a dark area with gain minimum to detect offset */ SANE_Status sanei_lexmark_low_offset_calibration (Lexmark_Device * dev) { SANE_Byte regs[255]; /* we have our own copy of shadow registers */ SANE_Status status = SANE_STATUS_GOOD; int i, lines = 8, yoffset = 2; int pixels; int failed = 0; /* offsets */ int ro = 0, go = 0, bo = 0; /* averages */ int ra, ga, ba, average; SANE_Byte *data = NULL; SANE_Byte top[OFFSET_RANGES] = { 0, 0x7f, 0x9f, 0xbf, 0xff }; #ifdef DEEP_DEBUG char title[20]; #endif DBG (2, "sanei_lexmark_low_offset_calibration: start\n"); /* copy registers */ for (i = 0; i < 255; i++) regs[i] = dev->shadow_regs[i]; /* we clear movement bit */ regs[0xc3] = regs[0xc3] & 0x7f; pixels = (dev->sensor->offset_endx - dev->sensor->offset_startx) / regs[0x7a]; /* there are 4 ranges of offset: 00-7F : almost no offset 80-9F : high noise A0-BF : high noise C0-FF : high noise we start with the highest one and decrease until overall offset is ok First loop may have such an high offset that scanned data overflow and gives a low average. So we allways skip its results */ /* minimal gains */ DBG (3, "sanei_lexmark_low_offset_calibration: setting gains to (1,1,1).\n"); rts88xx_set_gain (regs, 1, 1, 1); i = OFFSET_RANGES; average = 255; /* loop on ranges until one fits. Then adjust offset, first loop is * always done. TODO detect overflow by 'noise looking' data pattern */ while (((i > 0) && (average > dev->sensor->offset_threshold)) || (i == OFFSET_RANGES)) { /* next range */ i--; /* sets to top of range */ ro = top[i]; go = top[i]; bo = top[i]; rts88xx_set_offset (regs, ro, ro, ro); DBG (3, "sanei_lexmark_low_offset_calibration: setting offsets to (%d,%d,%d).\n", ro, ro, ro); status = low_simple_scan (dev, regs, dev->sensor->offset_startx, pixels, yoffset, lines, &data); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_lexmark_low_offset_calibration: low_simple_scan failed!\n"); if (data != NULL) free (data); return status; } #ifdef DEEP_DEBUG sprintf (title, "offset%02x.pnm", ro); write_pnm_file (title, pixels, lines, rts88xx_is_color (regs), data); #endif average = average_area (regs, data, pixels, lines, &ra, &ga, &ba); free (data); } if (i == 0) { DBG (2, "sanei_lexmark_low_offset_calibration: failed !\n"); failed = 1; } /* increase gain and scan again */ /* increase gain for fine offset tuning */ rts88xx_set_gain (regs, 6, 6, 6); status = low_simple_scan (dev, regs, dev->sensor->offset_startx, pixels, yoffset, lines, &data); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_lexmark_low_offset_calibration: low_simple_scan failed!\n"); if (data != NULL) free (data); return status; } average_area (regs, data, pixels, lines, &ra, &ga, &ba); #ifdef DEEP_DEBUG write_pnm_file ("offset-final.pnm", pixels, lines, rts88xx_is_color (regs), data); #endif /* this "law" is a guess, may (should?) be changed ... */ if (!failed) { if (ro > ra) dev->offset.red = ro - ra; if (go > ga) { dev->offset.green = go - ga; dev->offset.gray = go - ga; } if (bo > ba) dev->offset.blue = bo - ba; } else { dev->offset.red = dev->sensor->offset_fallback; dev->offset.green = dev->sensor->offset_fallback; dev->offset.blue = dev->sensor->offset_fallback; } DBG (7, "sanei_lexmark_low_offset_calibration: offset=(0x%02x,0x%02x,0x%02x).\n", dev->offset.red, dev->offset.green, dev->offset.blue); DBG (2, "sanei_lexmark_low_offset_calibration: end.\n"); free (data); return status; } /* * we scan a white area until average is good enough * level is good enough when it maximize the range value of output: * ie max-min is maximum */ SANE_Status sanei_lexmark_low_gain_calibration (Lexmark_Device * dev) { SANE_Byte regs[255]; /* we have our own copy of shadow registers */ SANE_Status status = SANE_STATUS_GOOD; int i, lines = 4, yoffset = 1; int sx, ex; int pixels; /* averages */ int ra, ga, ba; SANE_Byte *data = NULL; int red, green, blue; #ifdef DEEP_DEBUG char title[20]; #endif DBG (2, "sanei_lexmark_low_gain_calibration: start\n"); /* copy registers */ for (i = 0; i < 255; i++) regs[i] = dev->shadow_regs[i]; /* we clear movement bit */ regs[0xc3] = regs[0xc3] & 0x7f; sx = regs[0x67] * 256 + regs[0x66]; ex = regs[0x6d] * 256 + regs[0x6c]; pixels = (ex - sx) / regs[0x7a]; /* set up inital gains */ red = 6; green = 6; blue = 6; rts88xx_set_gain (regs, red, green, blue); /* init loop */ i = 0; ra = 0; ba = 0; ga = 0; status = low_cancel (dev->devnum); if (status != SANE_STATUS_GOOD) return status; /* we do a simple scan all 3 averages give the choosen level */ while (((rts88xx_is_color (regs) && ((ra < dev->sensor->red_gain_target) || (ga < dev->sensor->green_gain_target) || (ba < dev->sensor->blue_gain_target))) || (!rts88xx_is_color (regs) && (ga < dev->sensor->gray_gain_target))) && (i < 25)) { status = low_simple_scan (dev, regs, sx, pixels, yoffset, lines, &data); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_lexmark_low_gain_calibration: low_simple_scan failed!\n"); if (data != NULL) free (data); return status; } #ifdef DEEP_DEBUG sprintf (title, "gain%02d.pnm", i); write_pnm_file (title, pixels, lines, rts88xx_is_color (regs), data); #endif average_area (regs, data, pixels, lines, &ra, &ga, &ba); free (data); if (ra < dev->sensor->red_gain_target) red++; if (ga < dev->sensor->green_gain_target || (dev->sensor->gray_gain_target && !rts88xx_is_color (regs))) green++; if (ba < dev->sensor->blue_gain_target) blue++; rts88xx_set_gain (regs, red, green, blue); i++; } dev->gain.red = red; dev->gain.green = green; dev->gain.blue = blue; dev->gain.gray = green; DBG (7, "sanei_lexmark_low_gain_calibration: gain=(0x%02x,0x%02x,0x%02x).\n", dev->gain.red, dev->gain.green, dev->gain.blue); DBG (2, "sanei_lexmark_low_gain_calibration: end.\n"); return status; } /** * there is no hardware shading correction. So we have to do it in software. * We do it by scanning a pure white area which is before scanning area. Then * we compute per pixel coefficient to move the scanned value to the target * value. These coefficients are used later to correct scanned data. * The scan is done with all the final scan settings but the heigth and vertical * start position. */ SANE_Status sanei_lexmark_low_shading_calibration (Lexmark_Device * dev) { SANE_Byte regs[255]; /* we have our own copy of shadow registers */ int i, j, pixels, bpl; int sx, ex; SANE_Byte *data = NULL; SANE_Status status; /* enough 75 dpi lines to "go off" home position dot, and include shading area */ int lines = 4 + 4; int lineoffset = 1; int linetotal = lines + lineoffset; int yoffset; int x, y; float rtarget, btarget, gtarget; DBG (2, "sanei_lexmark_low_shading_calibration: start\n"); /* copy registers */ for (i = 0; i < 255; i++) regs[i] = dev->shadow_regs[i]; /* allocate memory for scan */ sx = regs[0x67] * 256 + regs[0x66]; ex = regs[0x6d] * 256 + regs[0x6c]; DBG (7, "startx=%d, endx=%d, coef=%d, r2f=0x%02x\n", sx, ex, regs[0x7a], regs[0x2f]); pixels = (ex - sx) / regs[0x7a]; if (rts88xx_is_color (regs)) bpl = 3 * pixels; else bpl = pixels; /* adjust the target area to the scanning resolution */ lines = (8 * lines) / regs[0x7a]; lineoffset = (8 * lineoffset) / regs[0x7a]; linetotal = (8 * linetotal) / regs[0x7a]; data = (SANE_Byte *) malloc (bpl * lines); DBG (7, "pixels=%d, lines=%d, size=%d\n", pixels, lines, bpl * lines); if (data == NULL) { DBG (2, "sanei_lexmark_low_shading_calibration: failed to allocate %d bytes !\n", bpl * lines); return SANE_STATUS_NO_MEM; } if (dev->shading_coeff != NULL) free (dev->shading_coeff); dev->shading_coeff = (float *) malloc (bpl * sizeof (float)); if (dev->shading_coeff == NULL) { DBG (2, "sanei_lexmark_low_shading_calibration: failed to allocate %d floats !\n", bpl); free (data); return SANE_STATUS_NO_MEM; } /* we set movement bit this time */ regs[0xc3] = regs[0xc3] | 0x80; /* execute scan */ status = low_simple_scan (dev, regs, sx, pixels, lineoffset, lines, &data); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_lexmark_low_shading_calibration: low_simple_scan failed!\n"); if (data != NULL) free (data); return status; } yoffset = -1; /* the very first lines of the scan may include the dark dot used * locate park position. We find the first line free of it in the scan. * We can't use is_home_line since it modifies data. */ for (y = 0; (y < lines) && (yoffset == y - 1); y++) { if (rts88xx_is_color (regs)) { for (x = 0; x < 3 * pixels; x++) { if (data[x + y * 3 * pixels] < 30) yoffset = y; } } else { for (x = 0; x < pixels; x++) { if (data[x + y * pixels] < 30) yoffset = y; } } } /* make sure we are really out of the dot */ yoffset++; /* yoffset is index of last dot line, go to first white line */ if (yoffset >= lines - 1) { DBG (7, "sanei_lexmark_low_shading_calibration: failed to detect yoffset.\n"); /* fail safe fallback, picture will be altered at dot position, but scanner is safe */ yoffset = lines - 2; } else yoffset++; DBG (7, "sanei_lexmark_low_shading_calibration: yoffset=%d.\n", yoffset); #ifdef DEEP_DEBUG write_pnm_file ("shading.pnm", pixels, lines, rts88xx_is_color (regs), data); #endif /* computes coefficients */ /* there are 8 lines usable for shading calibration at 150 dpi, between bottom of "home position" dot and the start of the scanner's window assembly, we only use 7 of them */ if (yoffset + (8 * 4) / regs[0x7a] < lines) lines = yoffset + (8 * 4) / regs[0x7a]; rtarget = dev->sensor->red_shading_target; gtarget = dev->sensor->green_shading_target; btarget = dev->sensor->blue_shading_target; for (i = 0; i < pixels; i++) { /* we computes the coefficient needed to move the scanned value to the target value */ if (rts88xx_is_color (dev->shadow_regs)) { /* RED */ dev->shading_coeff[i] = 0; for (j = yoffset; j < lines; j++) dev->shading_coeff[i] += data[i + j * bpl]; dev->shading_coeff[i] = (rtarget / (dev->shading_coeff[i] / (lines - yoffset))); /* GREEN */ dev->shading_coeff[i + pixels] = 0; for (j = yoffset; j < lines; j++) dev->shading_coeff[i + pixels] += data[i + j * bpl + pixels]; dev->shading_coeff[i + pixels] = ((gtarget / dev->shading_coeff[i + pixels]) * (lines - yoffset)); /* BLUE */ dev->shading_coeff[i + 2 * pixels] = 0; for (j = yoffset; j < lines; j++) dev->shading_coeff[i + 2 * pixels] += data[i + j * bpl + 2 * pixels]; dev->shading_coeff[i + 2 * pixels] = ((btarget / dev->shading_coeff[i + 2 * pixels]) * (lines - yoffset)); } else { dev->shading_coeff[i] = 0; for (j = yoffset; j < lines; j++) { dev->shading_coeff[i] += data[i + j * bpl]; } dev->shading_coeff[i] = (rtarget / dev->shading_coeff[i]) * (lines - yoffset); } } free(data); /* do the scan backward to go back to start position */ regs[0xc6] &= 0xF7; lines = (8 * 8) / regs[0x7a]; /* it shoud use linetotal to account for the lineoffset */ if (dev->model.sensor_type == X74_SENSOR) lines = linetotal; /* execute scan */ status = low_simple_scan (dev, regs, sx, pixels, 1, lines, &data); if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_lexmark_low_shading_calibration: low_simple_scan failed!\n"); if(data!=NULL) free(data); return status; } #ifdef DEEP_DEBUG write_pnm_file ("shading_bwd.pnm", pixels, lines, rts88xx_is_color (regs), data); #endif free (data); DBG (2, "sanei_lexmark_low_shading_calibration: end.\n"); return status; } SANE_Status sanei_lexmark_low_calibration (Lexmark_Device * dev) { SANE_Status status; DBG (2, "sanei_lexmark_low_calibration: start.\n"); status = sanei_lexmark_low_offset_calibration (dev); if (status != SANE_STATUS_GOOD) return status; /* we put the offset just computed in scanning regs */ if (rts88xx_is_color (dev->shadow_regs)) { rts88xx_set_offset (dev->shadow_regs, dev->offset.red, dev->offset.green, dev->offset.blue); } else { rts88xx_set_offset (dev->shadow_regs, dev->offset.gray, dev->offset.gray, dev->offset.gray); } /* if manual gain settings, no gain calibration */ if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE) { if (rts88xx_is_color (dev->shadow_regs)) { dev->gain.red = dev->val[OPT_RED_GAIN].w; dev->gain.green = dev->val[OPT_GREEN_GAIN].w; dev->gain.blue = dev->val[OPT_BLUE_GAIN].w; } else dev->gain.gray = dev->val[OPT_GRAY_GAIN].w; } else { status = sanei_lexmark_low_gain_calibration (dev); if (status != SANE_STATUS_GOOD) return status; } /* put the calibrated or manual settings before shading calibration which must be done with final setting values */ if (rts88xx_is_color (dev->shadow_regs)) { rts88xx_set_gain (dev->shadow_regs, dev->gain.red, dev->gain.green, dev->gain.blue); } else { rts88xx_set_gain (dev->shadow_regs, dev->gain.gray, dev->gain.gray, dev->gain.gray); } status = sanei_lexmark_low_shading_calibration (dev); if (status != SANE_STATUS_GOOD) return status; DBG (2, "sanei_lexmark_low_calibration: end.\n"); return SANE_STATUS_GOOD; } /* assign sensor data */ static SANE_Status sanei_lexmark_low_assign_sensor (Lexmark_Device * dev) { int dn; /* init sensor data */ dn = 0; while (sensor_list[dn].id != 0 && sensor_list[dn].id != dev->model.sensor_type) dn++; if (sensor_list[dn].id == 0) { DBG (1, "sanei_lexmark_low_assign_sensor: unknown sensor %d\n", dev->model.sensor_type); return SANE_STATUS_UNSUPPORTED; } dev->sensor = &(sensor_list[dn]); DBG (1, "sanei_lexmark_low_assign_sensor: assigned sensor number %d\n", dev->model.sensor_type); return SANE_STATUS_GOOD; } /* assign model description, based on USB id, and register content when * available */ SANE_Status sanei_lexmark_low_assign_model (Lexmark_Device * dev, SANE_String_Const devname, SANE_Int vendor, SANE_Int product, SANE_Byte mainboard) { int dn; SANE_Bool found = SANE_FALSE; DBG_INIT (); DBG (2, "sanei_lexmark_low_assign_model: start\n"); DBG (3, "sanei_lexmark_low_assign_model: assigning %04x:%04x, variant %d\n", vendor, product, mainboard); dn = 0; /* walk the list of known devices */ while (!found && model_list[dn].vendor_id != 0) { /* no mainboard id given (at attach time) */ if (mainboard == 0 && vendor == model_list[dn].vendor_id && product == model_list[dn].product_id) found = SANE_TRUE; /* mainboard given (init time) */ if (mainboard != 0 && mainboard == model_list[dn].mainboard_id && vendor == model_list[dn].vendor_id && product == model_list[dn].product_id) found = SANE_TRUE; if (!found) dn++; } /* we hit the end of list, so we don't know about the current model */ if (!found) { DBG (1, "sanei_lexmark_low_assign_model: unknown device 0x%04x:0x%04x\n", vendor, product); return SANE_STATUS_UNSUPPORTED; } dev->sane.name = strdup (devname); dev->sane.vendor = model_list[dn].vendor; dev->sane.model = model_list[dn].model; dev->model = model_list[dn]; dev->sane.type = "flatbed scanner"; DBG (3, "sanei_lexmark_low_assign_model: assigned %s\n", dev->model.model); /* init sensor data */ DBG (2, "sanei_lexmark_low_assign_model: end.\n"); return sanei_lexmark_low_assign_sensor (dev); } sane-backends-1.0.27/backend/mustek_usb_mid.c0000664000175000017500000025731212112021330015762 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Mustek. Originally maintained by Tom Wang Copyright (C) 2001, 2002 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek 1200UB and similar USB flatbed scanners. */ #include "mustek_usb_mid.h" #include "mustek_usb_low.c" /* ------------------ sensor NEC 3797 600 CIS functions ------------------- */ static SANE_Word usb_mid_n600_optical_x_dpi[] = { 600, 400, 300, 200, 100, 50, 0 }; SANE_Status usb_mid_n600_prepare_rgb_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_rgb_600_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P6P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_n600_prepare_rgb_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_rgb_400_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_rgb_400_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P4P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_n600_prepare_rgb_400_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_rgb_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_rgb_300_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P3P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_n600_prepare_rgb_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_rgb_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_rgb_200_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P2P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_n600_prepare_rgb_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_rgb_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_rgb_100_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_n600_prepare_rgb_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_rgb_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_rgb_50_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 2)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_n600_prepare_rgb_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_mono_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_mono_600_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P6P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_n600_prepare_mono_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_mono_400_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_mono_400_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P4P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_n600_prepare_mono_400_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_mono_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_mono_300_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P3P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_n600_prepare_mono_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_mono_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_mono_200_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P2P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_n600_prepare_mono_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_mono_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_mono_100_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_n600_prepare_mono_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_mono_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_n600_prepare_mono_50_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 2)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_n600_prepare_mono_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_rgb (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_n600_prepare_rgb: start\n"); switch (dpi) { case 50: return usb_mid_n600_prepare_rgb_50_dpi (chip); break; case 100: return usb_mid_n600_prepare_rgb_100_dpi (chip); break; case 200: return usb_mid_n600_prepare_rgb_200_dpi (chip); break; case 300: return usb_mid_n600_prepare_rgb_300_dpi (chip); break; case 400: return usb_mid_n600_prepare_rgb_400_dpi (chip); break; case 600: return usb_mid_n600_prepare_rgb_600_dpi (chip); break; default: DBG (3, "usb_mid_n600_prepare_rgb: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } DBG (6, "usb_mid_n600_prepare_rgb: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_n600_prepare_mono (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_n600_prepare_mono: start\n"); switch (dpi) { case 50: return usb_mid_n600_prepare_mono_50_dpi (chip); break; case 100: return usb_mid_n600_prepare_mono_100_dpi (chip); break; case 200: return usb_mid_n600_prepare_mono_200_dpi (chip); break; case 300: return usb_mid_n600_prepare_mono_300_dpi (chip); break; case 400: return usb_mid_n600_prepare_mono_400_dpi (chip); break; case 600: return usb_mid_n600_prepare_mono_600_dpi (chip); break; default: DBG (6, "usb_mid_n600_prepare_mono: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } /* ---------------------- sensor 600 CIS functions ----------------------- */ static SANE_Word usb_mid_c600_optical_x_dpi[] = { 600, 400, 300, 200, 150, 100, 50, 0 }; SANE_Status usb_mid_c600_prepare_rgb_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_rgb_600_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P6P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_rgb_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_rgb_400_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_rgb_400_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P4P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_rgb_400_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_rgb_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_rgb_300_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P3P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_rgb_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_rgb_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_rgb_200_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P2P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_rgb_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_rgb_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_rgb_150_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P3P6)); RIE (usb_low_set_soft_resample (chip, 2)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_rgb_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_rgb_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_rgb_100_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_rgb_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_rgb_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_rgb_50_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 2)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_rgb_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_mono_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_mono_600_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P6P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_mono_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_mono_400_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_mono_400_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P4P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_mono_400_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_mono_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_mono_300_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P3P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_mono_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_mono_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_mono_200_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P2P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_mono_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_mono_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_mono_150_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P3P6)); RIE (usb_low_set_soft_resample (chip, 2)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_mono_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_mono_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_mono_100_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_mono_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_mono_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c600_prepare_mono_50_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 2)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c600_prepare_mono_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_rgb (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_c600_prepare_rgb: start\n"); switch (dpi) { case 50: return usb_mid_c600_prepare_rgb_50_dpi (chip); break; case 100: return usb_mid_c600_prepare_rgb_100_dpi (chip); break; case 150: return usb_mid_c600_prepare_rgb_150_dpi (chip); break; case 200: return usb_mid_c600_prepare_rgb_200_dpi (chip); break; case 300: return usb_mid_c600_prepare_rgb_300_dpi (chip); break; case 400: return usb_mid_c600_prepare_rgb_400_dpi (chip); break; case 600: return usb_mid_c600_prepare_rgb_600_dpi (chip); break; default: DBG (3, "usb_mid_c600_prepare_rgb: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } DBG (6, "usb_mid_c600_prepare_rgb: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c600_prepare_mono (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_c600_prepare_mono: start\n"); switch (dpi) { case 50: return usb_mid_c600_prepare_mono_50_dpi (chip); break; case 100: return usb_mid_c600_prepare_mono_100_dpi (chip); break; case 150: return usb_mid_c600_prepare_mono_150_dpi (chip); break; case 200: return usb_mid_c600_prepare_mono_200_dpi (chip); break; case 300: return usb_mid_c600_prepare_mono_300_dpi (chip); break; case 400: return usb_mid_c600_prepare_mono_400_dpi (chip); break; case 600: return usb_mid_c600_prepare_mono_600_dpi (chip); break; default: DBG (6, "usb_mid_c600_prepare_mono: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } /* ------------------- sensor 300/600 CIS functions ----------------------- */ static SANE_Word usb_mid_c300600_optical_x_dpi[] = { 600, 400, 300, 200, 150, 100, 50, 0 }; SANE_Status usb_mid_c300600_prepare_rgb_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_rgb_600_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P6P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_rgb_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_rgb_400_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_rgb_400_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P4P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_rgb_400_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_rgb_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_rgb_300_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P6P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_rgb_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_rgb_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_rgb_200_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P2P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_rgb_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_rgb_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_rgb_150_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P3P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_rgb_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_rgb_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_rgb_100_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P2P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_rgb_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_rgb_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_rgb_50_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_rgb_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_mono_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_mono_600_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P6P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_mono_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_mono_400_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_mono_400_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P4P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_mono_400_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_mono_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_mono_300_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P6P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_mono_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_mono_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_mono_200_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P2P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_mono_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_mono_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_mono_150_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P3P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_mono_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_mono_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_mono_100_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P2P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_mono_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_mono_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300600_prepare_mono_50_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_FALSE, SW_P1P6)); RIE (usb_low_set_soft_resample (chip, 1)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300600_prepare_mono_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_rgb (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_c300600_prepare_rgb: start\n"); switch (dpi) { case 50: return usb_mid_c300600_prepare_rgb_50_dpi (chip); break; case 100: return usb_mid_c300600_prepare_rgb_100_dpi (chip); break; case 150: return usb_mid_c300600_prepare_rgb_150_dpi (chip); break; case 200: return usb_mid_c300600_prepare_rgb_200_dpi (chip); break; case 300: return usb_mid_c300600_prepare_rgb_300_dpi (chip); break; case 400: return usb_mid_c300600_prepare_rgb_400_dpi (chip); break; case 600: return usb_mid_c300600_prepare_rgb_600_dpi (chip); break; default: DBG (3, "usb_mid_c300600_prepare_rgb: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300600_prepare_mono (ma1017 * chip, SANE_Word dpi) { switch (dpi) { case 50: return usb_mid_c300600_prepare_mono_50_dpi (chip); break; case 100: return usb_mid_c300600_prepare_mono_100_dpi (chip); break; case 150: return usb_mid_c300600_prepare_mono_150_dpi (chip); break; case 200: return usb_mid_c300600_prepare_mono_200_dpi (chip); break; case 300: return usb_mid_c300600_prepare_mono_300_dpi (chip); break; case 400: return usb_mid_c300600_prepare_mono_400_dpi (chip); break; case 600: return usb_mid_c300600_prepare_mono_600_dpi (chip); break; default: DBG (3, "usb_mid_c300600_prepare_mono: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } /* ---------------------- sensor 300 CIS functions ----------------------- */ static SANE_Word usb_mid_c300_optical_x_dpi[] = { 300, 200, 150, 100, 50, 0 }; SANE_Status usb_mid_c300_prepare_rgb_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_rgb_300_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P6P6)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300_prepare_rgb_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_rgb_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_rgb_200_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P4P6)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300_prepare_rgb_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_rgb_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_rgb_150_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P3P6)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300_prepare_rgb_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_rgb_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_rgb_100_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P2P6)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300_prepare_rgb_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_rgb_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_rgb_50_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P1P6)); RIE (usb_low_set_led_light_all (chip, SANE_FALSE)); DBG (6, "usb_mid_c300_prepare_rgb_50_dpi: start\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_mono_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_mono_300_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P6P6)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_c300_prepare_mono_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_mono_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_mono_200_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P4P6)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_c300_prepare_mono_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_mono_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_mono_150_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P3P6)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_c300_prepare_mono_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_mono_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_mono_100_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P2P6)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_c300_prepare_mono_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_mono_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_c300_prepare_mono_50_dpi: start\n"); RIE (usb_low_set_image_dpi (chip, SANE_TRUE, SW_P1P6)); RIE (usb_low_set_led_light_all (chip, SANE_TRUE)); DBG (6, "usb_mid_c300_prepare_mono_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_rgb (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_c300_prepare_rgb: start\n"); switch (dpi) { case 50: return usb_mid_c300_prepare_rgb_50_dpi (chip); break; case 100: return usb_mid_c300_prepare_rgb_100_dpi (chip); break; case 150: return usb_mid_c300_prepare_rgb_150_dpi (chip); break; case 200: return usb_mid_c300_prepare_rgb_200_dpi (chip); break; case 300: return usb_mid_c300_prepare_rgb_300_dpi (chip); break; default: DBG (3, "usb_mid_c300_prepare_rgb: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_c300_prepare_mono (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_c300_prepare_mono: start\n"); switch (dpi) { case 50: return usb_mid_c300_prepare_mono_50_dpi (chip); break; case 100: return usb_mid_c300_prepare_mono_100_dpi (chip); break; case 150: return usb_mid_c300_prepare_mono_150_dpi (chip); break; case 200: return usb_mid_c300_prepare_mono_200_dpi (chip); break; case 300: return usb_mid_c300_prepare_mono_300_dpi (chip); break; default: DBG (3, "usb_mid_c300_prepare_mono: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } /* -------------------------- sensor functions ---------------------------- */ SANE_Bool usb_mid_sensor_is600_mode (ma1017 * chip, SANE_Word dpi) { if (chip->sensor == ST_CANON300) { DBG (6, "usb_mid_sensor_is600_mode: chip=%p, dpi=%d, FALSE\n", (void *) chip, dpi); return SANE_FALSE; } else if ((chip->sensor == ST_CANON600) || (chip->sensor == ST_NEC600)) { DBG (6, "usb_mid_sensor_is600_mode: chip=%p, dpi=%d, TRUE\n", (void *) chip, dpi); return SANE_TRUE; } else { switch (dpi) { case 300: case 150: case 100: case 50: DBG (6, "usb_mid_sensor_is600_mode: chip=%p, dpi=%d, FALSE\n", (void *) chip, dpi); return SANE_FALSE; case 600: case 400: case 200: DBG (6, "usb_mid_sensor_is600_mode: chip=%p, dpi=%d, TRUE\n", (void *) chip, dpi); return SANE_TRUE; default: DBG (3, "usb_mid_sensor_is600_mode: unmatched dpi: %d\n", dpi); return SANE_FALSE; break; } } return SANE_FALSE; } static SANE_Status usb_mid_sensor_prepare_rgb (ma1017 * chip, SANE_Word dpi) { if (chip->sensor == ST_CANON300) return usb_mid_c300_prepare_rgb (chip, dpi); else if (chip->sensor == ST_CANON600) return usb_mid_c600_prepare_rgb (chip, dpi); else if (chip->sensor == ST_NEC600) return usb_mid_n600_prepare_rgb (chip, dpi); else return usb_mid_c300600_prepare_rgb (chip, dpi); return SANE_STATUS_INVAL; } static SANE_Status usb_mid_sensor_prepare_mono (ma1017 * chip, SANE_Word dpi) { if (chip->sensor == ST_CANON300) return usb_mid_c300_prepare_mono (chip, dpi); else if (chip->sensor == ST_CANON600) return usb_mid_c600_prepare_mono (chip, dpi); else if (chip->sensor == ST_NEC600) return usb_mid_n600_prepare_mono (chip, dpi); else return usb_mid_c300600_prepare_mono (chip, dpi); return SANE_STATUS_INVAL; } static SANE_Status usb_mid_sensor_get_dpi (ma1017 * chip, SANE_Word wanted_dpi, SANE_Word * dpi) { SANE_Word *dpi_list; SANE_Word i; if (!dpi) return SANE_STATUS_INVAL; DBG (5, "usb_mid_sensor_get_dpi: chip->sensor=%d\n", chip->sensor); if (chip->sensor == ST_CANON300) dpi_list = usb_mid_c300_optical_x_dpi; else if (chip->sensor == ST_CANON300600) dpi_list = usb_mid_c300600_optical_x_dpi; else if (chip->sensor == ST_CANON600) dpi_list = usb_mid_c600_optical_x_dpi; else if (chip->sensor == ST_NEC600) dpi_list = usb_mid_n600_optical_x_dpi; else return SANE_STATUS_INVAL; for (i = 0; dpi_list[i] != 0; i++) { if (wanted_dpi > dpi_list[i]) break; } if (i) i--; *dpi = dpi_list[i]; DBG (5, "usb_mid_sensor_get_dpi: wanted %d dpi, got %d dpi\n", wanted_dpi, *dpi); return SANE_STATUS_GOOD; } /* ---------------1200 dpi motor function declarations --------------------- */ static SANE_Word usb_mid_motor1200_optical_dpi[] = { 1200, 600, 400, 300, 200, 150, 100, 50, 0 }; SANE_Status usb_mid_motor1200_prepare_rgb_1200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_1200_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 4)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_FALSE)); DBG (6, "usb_mid_motor1200_prepare_rgb_1200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_600_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 4)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_FALSE)); DBG (6, "usb_mid_motor1200_prepare_rgb_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_400_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_400_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_rgb_400_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 4)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_rgb_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_200_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_rgb_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_150_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 4)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_rgb_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_100_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_rgb_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_50_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_BLUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 5, CH_RED, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 6)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_rgb_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_1200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_1200_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_1200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_600_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 5, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 7, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 8, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 9, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 10, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 11, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 12, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 13, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 14, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 15, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 16, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 17, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 18, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 19, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 20, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 21, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 22, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 23, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 24, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 25, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 26, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 26)); RIE (usb_low_set_cmt_second_position (chip, 24)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_400_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_400_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_400_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 5, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 7, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 8, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 9, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 10, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 11, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 12, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 13, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 14, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 15, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 16, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 17, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 18, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 19, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 20, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 21, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 22, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 23, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 24, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 25, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 26, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 26)); RIE (usb_low_set_cmt_second_position (chip, 24)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_200_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_150_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_100_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_50_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 5, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 6)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_half_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_half_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 4, CH_RED, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 5, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 6)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_rgb_half_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_bi_full_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_bi_full_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 4, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 5, CH_RED, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 6)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_FALSE)); DBG (6, "usb_mid_motor1200_prepare_rgb_bi_full_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb_bi_full_x2300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb_bi_full_x2300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 4, CH_RED, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 5, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 6)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_rgb_bi_full_x2300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_half_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_half_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 4)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_half_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_bi_full_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_bi_full_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_bi_full_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono_bi_full_x2300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_mono_bi_full_x2300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_mono_bi_full_x2300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_rgb (ma1017 * chip, SANE_Word dpi) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_rgb: start\n"); RIE (usb_low_move_motor_home (chip, SANE_FALSE, SANE_FALSE)); /* No Motor & Forward */ RIE (usb_low_set_motor_direction (chip, SANE_FALSE)); RIE (usb_low_enable_motor (chip, SANE_TRUE)); switch (dpi) { case 1200: return usb_mid_motor1200_prepare_rgb_1200_dpi (chip); break; case 600: return usb_mid_motor1200_prepare_rgb_600_dpi (chip); break; case 400: return usb_mid_motor1200_prepare_rgb_400_dpi (chip); break; case 300: return usb_mid_motor1200_prepare_rgb_300_dpi (chip); break; case 200: return usb_mid_motor1200_prepare_rgb_200_dpi (chip); break; case 150: return usb_mid_motor1200_prepare_rgb_150_dpi (chip); break; case 100: return usb_mid_motor1200_prepare_rgb_100_dpi (chip); break; case 50: return usb_mid_motor1200_prepare_rgb_50_dpi (chip); break; default: DBG (3, "usb_mid_motor1200_prepare_rgb: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_mono (ma1017 * chip, SANE_Word dpi) { SANE_Status status; DBG (3, "usb_mid_motor1200_prepare_mono: start\n"); RIE (usb_low_move_motor_home (chip, SANE_FALSE, SANE_FALSE)); /* No Motor & Forward */ RIE (usb_low_set_motor_direction (chip, SANE_FALSE)); RIE (usb_low_enable_motor (chip, SANE_TRUE)); switch (dpi) { case 1200: return usb_mid_motor1200_prepare_mono_1200_dpi (chip); break; case 600: return usb_mid_motor1200_prepare_mono_600_dpi (chip); break; case 400: return usb_mid_motor1200_prepare_mono_400_dpi (chip); break; case 300: return usb_mid_motor1200_prepare_mono_300_dpi (chip); break; case 200: return usb_mid_motor1200_prepare_mono_200_dpi (chip); break; case 150: return usb_mid_motor1200_prepare_mono_150_dpi (chip); break; case 100: return usb_mid_motor1200_prepare_mono_100_dpi (chip); break; case 50: return usb_mid_motor1200_prepare_mono_50_dpi (chip); break; default: DBG (3, "usb_mid_motor1200_prepare_mono_: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_calibrate_rgb (ma1017 * chip, SANE_Word dpi) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_calibrate_rgb: start\n"); RIE (usb_low_move_motor_home (chip, SANE_FALSE, SANE_FALSE)); /* No Motor & Forward */ RIE (usb_low_set_motor_direction (chip, SANE_FALSE)); RIE (usb_low_enable_motor (chip, SANE_TRUE)); switch (dpi) { case 1200: case 400: case 300: return usb_mid_motor1200_prepare_rgb_half_300_dpi (chip); break; case 600: case 200: case 150: return usb_mid_motor1200_prepare_rgb_bi_full_300_dpi (chip); break; case 100: case 50: return usb_mid_motor1200_prepare_rgb_bi_full_x2300_dpi (chip); break; default: DBG (3, "usb_mid_motor1200_prepare_calibrate_rgb: unmatched dpi: " "%d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_calibrate_mono (ma1017 * chip, SANE_Word dpi) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_calibrate_mono: start\n"); RIE (usb_low_move_motor_home (chip, SANE_FALSE, SANE_FALSE)); /* No Motor & Forward */ RIE (usb_low_set_motor_direction (chip, SANE_FALSE)); RIE (usb_low_enable_motor (chip, SANE_TRUE)); switch (dpi) { case 1200: case 600: case 400: return usb_mid_motor1200_prepare_mono_half_300_dpi (chip); break; case 300: case 200: return usb_mid_motor1200_prepare_mono_bi_full_300_dpi (chip); break; case 150: case 100: case 50: return usb_mid_motor1200_prepare_mono_bi_full_x2300_dpi (chip); break; default: DBG (3, "usb_mid_motor1200_prepare_calibrate_mono: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_step (ma1017 * chip, SANE_Word step_count) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_step: start\n"); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); /* Make it in 600dpi */ RIE (usb_low_set_io_3 (chip, SANE_TRUE)); /* (IO3) ? High power : Low power */ RIE (usb_low_move_motor_home (chip, SANE_FALSE, SANE_FALSE)); /* No Motor & Forward */ if (step_count == 1) { RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 1)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, step_count)); } else if (step_count % 2 == 1) { RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 1)); RIE (usb_low_set_cmt_loop_count (chip, (step_count - 1) / 2)); } else { RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, step_count / 2)); } RIE (usb_low_enable_motor (chip, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_step: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_home (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_home: start\n"); if (chip->sensor == ST_NEC600) RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); else RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); /* Make it in 600dpi */ RIE (usb_low_set_io_3 (chip, SANE_TRUE)); /* (IO3) ? High power : Low power */ RIE (usb_low_move_motor_home (chip, SANE_TRUE, SANE_TRUE)); DBG (6, "usb_mid_motor1200_prepare_home: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor1200_prepare_adjust (ma1017 * chip, Channel channel) { SANE_Status status; DBG (6, "usb_mid_motor1200_prepare_adjust: start\n"); RIE (usb_low_set_cmt_table (chip, 0, channel, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, channel, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, channel, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); DBG (6, "usb_mid_motor1200_prepare_adjust: exit\n"); return SANE_STATUS_GOOD; } SANE_Word usb_mid_motor1200_rgb_capability (SANE_Word dpi) { DBG (6, "usb_mid_motor1200_rgb_capability: start\n"); switch (dpi) { case 1200: case 400: return 3008; /* 2816 */ ; case 600: return 3008; case 200: return 5056; case 300: return 3008; case 150: return 5056; case 100: case 50: return 10048; default: DBG (3, "usb_mid_motor1200_rgb_capability: unmatched dpi: %d\n", dpi); return 0; } } SANE_Word usb_mid_motor1200_mono_capability (SANE_Word dpi) { DBG (5, "usb_mid_motor1200_mono_capability: start\n"); switch (dpi) { case 1200: case 400: return 3008; case 600: return 3008; case 200: return 5056; case 300: return 5056; case 150: case 100: case 50: return 10048; default: DBG (3, "usb_mid_motor1200_mono_capability: unmatched dpi: %d\n", dpi); return 0; } } /* ---------------600 dpi motor function declarations --------------------- */ static SANE_Word usb_mid_motor600_optical_dpi[] = { 600, 300, 200, 150, 100, 50, 0 }; SANE_Status usb_mid_motor600_prepare_rgb_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_rgb_600_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 4)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_FALSE)); DBG (6, "usb_mid_motor600_prepare_rgb_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_rgb_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_rgb_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 4)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_FALSE)); DBG (6, "usb_mid_motor600_prepare_rgb_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_rgb_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_rgb_200_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 5, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 5)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_rgb_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_rgb_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_rgb_150_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_rgb_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_rgb_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_rgb_100_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 4, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 5, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 5)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_rgb_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_rgb_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_rgb_50_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_rgb_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono_600_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_mono_600_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_mono_600_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_mono_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_mono_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono_200_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_mono_200_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_mono_200_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono_150_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_mono_150_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_mono_150_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono_100_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_mono_100_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_mono_100_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono_50_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_mono_50_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_mono_50_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_rgb_half_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_rgb_half_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_BLUE, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 4, CH_RED, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 5, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 6)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_rgb_half_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_rgb_bi_full_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_rgb_bi_full_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 3, CH_BLUE, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 4, CH_RED, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 5, CH_RED, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 6, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 6)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_FALSE)); DBG (6, "usb_mid_motor600_prepare_rgb_bi_full_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono_half_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_mono_half_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_mono_half_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono_bi_full_300_dpi (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_mono_bi_full_300_dpi: start\n"); RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); RIE (usb_low_set_motor_movement (chip, SANE_TRUE, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_io_3 (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_mono_bi_full_300_dpi: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_rgb (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_motor600_prepare_rgb: start\n"); switch (dpi) { case 600: return usb_mid_motor600_prepare_rgb_600_dpi (chip); break; case 300: return usb_mid_motor600_prepare_rgb_300_dpi (chip); break; case 200: return usb_mid_motor600_prepare_rgb_200_dpi (chip); break; case 150: return usb_mid_motor600_prepare_rgb_150_dpi (chip); break; case 100: return usb_mid_motor600_prepare_rgb_100_dpi (chip); break; case 50: return usb_mid_motor600_prepare_rgb_50_dpi (chip); break; default: DBG (3, "usb_mid_motor600_prepare_rgb: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_mono (ma1017 * chip, SANE_Word dpi) { DBG (6, "usb_mid_motor600_prepare_mono: start\n"); switch (dpi) { case 600: return usb_mid_motor600_prepare_mono_600_dpi (chip); break; case 300: return usb_mid_motor600_prepare_mono_300_dpi (chip); break; case 200: return usb_mid_motor600_prepare_mono_200_dpi (chip); break; case 150: return usb_mid_motor600_prepare_mono_150_dpi (chip); break; case 100: return usb_mid_motor600_prepare_mono_100_dpi (chip); break; case 50: return usb_mid_motor600_prepare_mono_50_dpi (chip); break; default: DBG (3, "usb_mid_motor600_prepare_mono_: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_calibrate_rgb (ma1017 * chip, SANE_Word dpi) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_calibrate_rgb: start\n"); RIE (usb_low_move_motor_home (chip, SANE_FALSE, SANE_FALSE)); /* No Motor & Forward */ RIE (usb_low_set_motor_direction (chip, SANE_FALSE)); RIE (usb_low_enable_motor (chip, SANE_TRUE)); switch (dpi) { case 600: case 200: return usb_mid_motor600_prepare_rgb_half_300_dpi (chip); break; case 300: case 150: case 100: case 50: return usb_mid_motor600_prepare_rgb_bi_full_300_dpi (chip); break; default: DBG (3, "usb_mid_motor600_prepare_calibrate_rgb: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_calibrate_mono (ma1017 * chip, SANE_Word dpi) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_calibrate_mono: start\n"); RIE (usb_low_move_motor_home (chip, SANE_FALSE, SANE_FALSE)); /* No Motor & Forward */ RIE (usb_low_set_motor_direction (chip, SANE_FALSE)); RIE (usb_low_enable_motor (chip, SANE_TRUE)); switch (dpi) { case 600: case 200: return usb_mid_motor600_prepare_mono_half_300_dpi (chip); break; case 300: case 150: case 100: case 50: return usb_mid_motor600_prepare_mono_bi_full_300_dpi (chip); break; default: DBG (3, "usb_mid_motor600_prepare_calibrate_mono: unmatched dpi: %d\n", dpi); return SANE_STATUS_INVAL; break; } return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_step (ma1017 * chip, SANE_Word step_count) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_step: start\n"); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_FALSE)); /* Make it in 300dpi */ RIE (usb_low_set_io_3 (chip, SANE_TRUE)); /* (IO3) ? High power : Low power */ RIE (usb_low_move_motor_home (chip, SANE_FALSE, SANE_FALSE)); /* No Motor & Forward */ if (step_count == 1) { RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 1)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, step_count)); } else if (step_count % 2 == 1) { RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 3, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 3)); RIE (usb_low_set_cmt_second_position (chip, 1)); RIE (usb_low_set_cmt_loop_count (chip, (step_count - 1) / 2)); } else { RIE (usb_low_set_cmt_table (chip, 0, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 1, CH_GREEN, SANE_TRUE, SANE_FALSE)); RIE (usb_low_set_cmt_table (chip, 2, CH_GREEN, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, step_count / 2)); } RIE (usb_low_enable_motor (chip, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_step: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_home (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_home: start\n"); RIE (usb_low_set_motor_movement (chip, SANE_FALSE, SANE_TRUE, SANE_TRUE)); /* Make it in 600dpi */ RIE (usb_low_set_io_3 (chip, SANE_TRUE)); /* (IO3) ? High power : Low power */ RIE (usb_low_move_motor_home (chip, SANE_TRUE, SANE_TRUE)); DBG (6, "usb_mid_motor600_prepare_home: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_motor600_prepare_adjust (ma1017 * chip, Channel channel) { SANE_Status status; DBG (6, "usb_mid_motor600_prepare_adjust: start\n"); RIE (usb_low_set_cmt_table (chip, 0, channel, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 1, channel, SANE_FALSE, SANE_TRUE)); RIE (usb_low_set_cmt_table (chip, 2, channel, SANE_FALSE, SANE_FALSE)); RIE (usb_low_set_cmt_table_length (chip, 2)); RIE (usb_low_set_cmt_second_position (chip, 0)); RIE (usb_low_set_cmt_loop_count (chip, 0xefff)); DBG (6, "usb_mid_motor600_prepare_adjust: exit\n"); return SANE_STATUS_GOOD; } SANE_Word usb_mid_motor600_rgb_capability (SANE_Word dpi) { DBG (6, "usb_mid_motor600_rgb_capability: start\n"); switch (dpi) { case 600: case 300: case 200: return 2600; case 100: return 4500; case 150: case 50: return 9000; default: DBG (3, "usb_mid_motor600_rgb_capability: unmatched dpi: %d\n", dpi); return 0; } } SANE_Word usb_mid_motor600_mono_capability (SANE_Word dpi) { DBG (5, "usb_mid_motor600_mono_capability: start\n"); switch (dpi) { case 600: case 200: return 2600; case 300: case 100: return 4500; case 150: case 50: return 9000; default: DBG (3, "usb_mid_motor600_mono_capability: unmatched dpi: %d\n", dpi); return 0; } } /* ------------------ motor function declarations ------------------------ */ static SANE_Status usb_mid_motor_prepare_home (ma1017 * chip) { if (chip->motor == MT_600) return usb_mid_motor600_prepare_home (chip); else return usb_mid_motor1200_prepare_home (chip); } static SANE_Status usb_mid_motor_prepare_rgb (ma1017 * chip, SANE_Word dpi) { if (chip->motor == MT_600) return usb_mid_motor600_prepare_rgb (chip, dpi); else return usb_mid_motor1200_prepare_rgb (chip, dpi); } static SANE_Status usb_mid_motor_prepare_mono (ma1017 * chip, SANE_Word dpi) { if (chip->motor == MT_600) return usb_mid_motor600_prepare_mono (chip, dpi); else return usb_mid_motor1200_prepare_mono (chip, dpi); } static SANE_Status usb_mid_motor_prepare_adjust (ma1017 * chip, Channel channel) { if (chip->motor == MT_600) return usb_mid_motor600_prepare_adjust (chip, channel); else return usb_mid_motor1200_prepare_adjust (chip, channel); } static SANE_Status usb_mid_motor_prepare_calibrate_rgb (ma1017 * chip, SANE_Word dpi) { if (chip->motor == MT_600) return usb_mid_motor600_prepare_calibrate_rgb (chip, dpi); else return usb_mid_motor1200_prepare_calibrate_rgb (chip, dpi); } static SANE_Status usb_mid_motor_prepare_calibrate_mono (ma1017 * chip, SANE_Word dpi) { if (chip->motor == MT_600) return usb_mid_motor600_prepare_calibrate_mono (chip, dpi); else return usb_mid_motor1200_prepare_calibrate_mono (chip, dpi); } static SANE_Status usb_mid_motor_prepare_step (ma1017 * chip, SANE_Word step_count) { if (chip->motor == MT_600) return usb_mid_motor600_prepare_step (chip, step_count); else return usb_mid_motor1200_prepare_step (chip, step_count); } static SANE_Word usb_mid_motor_rgb_capability (ma1017 * chip, SANE_Word dpi) { if (chip->motor == MT_600) return usb_mid_motor600_rgb_capability (dpi); else return usb_mid_motor1200_rgb_capability (dpi); } static SANE_Word usb_mid_motor_mono_capability (ma1017 * chip, SANE_Word dpi) { if (chip->motor == MT_600) return usb_mid_motor600_mono_capability (dpi); else return usb_mid_motor1200_mono_capability (dpi); } static SANE_Status usb_mid_motor_get_dpi (ma1017 * chip, SANE_Word wanted_dpi, SANE_Word * dpi) { SANE_Word *dpi_list; SANE_Word i; if (!dpi) return SANE_STATUS_INVAL; if (chip->motor == MT_600) dpi_list = usb_mid_motor600_optical_dpi; else if (chip->motor == MT_1200) dpi_list = usb_mid_motor1200_optical_dpi; else return SANE_STATUS_INVAL; for (i = 0; dpi_list[i] != 0; i++) { if (wanted_dpi > dpi_list[i]) break; } if (i) i--; *dpi = dpi_list[i]; DBG (5, "usb_mid_motor_get_dpi: wanted %d dpi, got %d dpi\n", wanted_dpi, *dpi); return SANE_STATUS_GOOD; } /* ----------------------------- frontend ------------------------------- */ SANE_Status usb_mid_front_set_front_end_mode (ma1017 * chip, SANE_Byte mode) { SANE_Status status; DBG (6, "usb_mid_front_set_front_end_mode: start\n"); RIE (usb_low_set_serial_format (chip, mode)); DBG (6, "usb_mid_front_set_front_end_mode: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_front_enable (ma1017 * chip, SANE_Bool is_enable) { SANE_Status status; DBG (6, "usb_mid_front_enable: start\n"); RIE (usb_low_turn_frontend_mode (chip, is_enable)); DBG (6, "usb_mid_front_enable: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_front_set_top_reference (ma1017 * chip, SANE_Byte top) { SANE_Status status; DBG (6, "usb_mid_front_set_top_reference: start\n"); RIE (usb_mid_front_enable (chip, SANE_TRUE)); RIE (usb_low_set_serial_byte1 (chip, 0x00)); RIE (usb_low_set_serial_byte2 (chip, top)); RIE (usb_mid_front_enable (chip, SANE_FALSE)); DBG (6, "usb_mid_front_set_top_reference: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_front_set_red_offset (ma1017 * chip, SANE_Byte offset) { SANE_Status status; DBG (6, "usb_mid_front_set_red_offset: start\n"); RIE (usb_mid_front_enable (chip, SANE_TRUE)); RIE (usb_low_set_serial_byte1 (chip, 0x10)); RIE (usb_low_set_serial_byte2 (chip, offset)); RIE (usb_mid_front_enable (chip, SANE_FALSE)); DBG (6, "usb_mid_front_set_red_offset: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_front_set_green_offset (ma1017 * chip, SANE_Byte offset) { SANE_Status status; DBG (6, "usb_mid_front_set_green_offset: start\n"); RIE (usb_mid_front_enable (chip, SANE_TRUE)); RIE (usb_low_set_serial_byte1 (chip, 0x50)); RIE (usb_low_set_serial_byte2 (chip, offset)); RIE (usb_mid_front_enable (chip, SANE_FALSE)); DBG (6, "usb_mid_front_set_green_offset: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_front_set_blue_offset (ma1017 * chip, SANE_Byte offset) { SANE_Status status; DBG (6, "usb_mid_front_set_blue_offset: start\n"); RIE (usb_mid_front_enable (chip, SANE_TRUE)); RIE (usb_low_set_serial_byte1 (chip, 0x30)); RIE (usb_low_set_serial_byte2 (chip, offset)); RIE (usb_mid_front_enable (chip, SANE_FALSE)); DBG (6, "usb_mid_front_set_blue_offset: exit\n"); return SANE_STATUS_GOOD; } #if 0 /* CCD */ SANE_Word usb_mid_frontend_max_offset_index (ma1017 * chip) { DBG (6, "usb_mid_front_max_offset_index: start (chip = %p)\n", chip); DBG (6, "usb_mid_front_max_offset_index: exit\n"); return (OFFSET_TABLE_SIZE - 1); } #endif SANE_Status usb_mid_front_set_red_pga (ma1017 * chip, SANE_Byte pga) { SANE_Status status; DBG (6, "usb_mid_front_set_red_pga: start\n"); RIE (usb_mid_front_enable (chip, SANE_TRUE)); RIE (usb_low_set_serial_byte1 (chip, 0x40)); RIE (usb_low_set_serial_byte2 (chip, pga)); RIE (usb_mid_front_enable (chip, SANE_FALSE)); DBG (6, "usb_mid_front_set_red_pga: start\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_front_set_green_pga (ma1017 * chip, SANE_Byte pga) { SANE_Status status; DBG (6, "usb_mid_front_set_green_pga: start\n"); RIE (usb_mid_front_enable (chip, SANE_TRUE)); RIE (usb_low_set_serial_byte1 (chip, 0x20)); RIE (usb_low_set_serial_byte2 (chip, pga)); RIE (usb_mid_front_enable (chip, SANE_FALSE)); DBG (6, "usb_mid_front_set_green_pga: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_front_set_blue_pga (ma1017 * chip, SANE_Byte pga) { SANE_Status status; DBG (6, "usb_mid_front_set_blue_pga: start\n"); RIE (usb_mid_front_enable (chip, SANE_TRUE)); RIE (usb_low_set_serial_byte1 (chip, 0x60)); RIE (usb_low_set_serial_byte2 (chip, pga)); RIE (usb_mid_front_enable (chip, SANE_FALSE)); DBG (6, "usb_mid_front_set_blue_pga: exit\n"); return SANE_STATUS_GOOD; } SANE_Status usb_mid_front_set_rgb_signal (ma1017 * chip) { SANE_Status status; DBG (6, "usb_mid_front_set_rgb_signal: start\n"); RIE (usb_low_set_red_ref (chip, 0xEF)); RIE (usb_low_set_green_ref (chip, 0xF7)); RIE (usb_low_set_blue_ref (chip, 0xFF)); DBG (6, "usb_mid_front_set_rgb_signal: exit\n"); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/gt68xx.c0000664000175000017500000022160713106201017014124 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov Copyright (C) 2002 - 2007 Henning Geinitz Copyright (C) 2009 Stéphane Voltz for sheetfed calibration code. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* * SANE backend for Grandtech GT-6801 and GT-6816 based scanners */ #include "../include/sane/config.h" #define BUILD 84 #define MAX_DEBUG #define WARMUP_TIME 60 #define CALIBRATION_HEIGHT 2.5 #define SHORT_TIMEOUT (1 * 1000) #define LONG_TIMEOUT (30 * 1000) /* Use a reader process if possible (usually faster) */ #if defined (HAVE_SYS_SHM_H) && (!defined (USE_PTHREAD)) && (!defined (HAVE_OS2_H)) #define USE_FORK #define SHM_BUFFERS 10 #endif #define TUNE_CALIBRATOR /* Send coarse white or black calibration to stdout */ #if 0 #define SAVE_WHITE_CALIBRATION #endif #if 0 #define SAVE_BLACK_CALIBRATION #endif /* Debug calibration, print total brightness of the scanned image */ #if 0 #define DEBUG_BRIGHTNESS #endif /* Debug calibration, print black mark values */ #if 0 #define DEBUG_BLACK #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME gt68xx #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #ifndef SANE_I18N #define SANE_I18N(text) text #endif #include "gt68xx.h" #include "gt68xx_high.c" #include "gt68xx_devices.c" static SANE_Int num_devices = 0; static GT68xx_Device *first_dev = 0; static GT68xx_Scanner *first_handle = 0; static const SANE_Device **devlist = 0; /* Array of newly attached devices */ static GT68xx_Device **new_dev = 0; /* Length of new_dev array */ static SANE_Int new_dev_len = 0; /* Number of entries alloced for new_dev */ static SANE_Int new_dev_alloced = 0; /* Is this computer little-endian ?*/ SANE_Bool little_endian; SANE_Bool debug_options = SANE_FALSE; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_LINEART, 0 }; static SANE_String_Const gray_mode_list[] = { GT68XX_COLOR_RED, GT68XX_COLOR_GREEN, GT68XX_COLOR_BLUE, 0 }; static SANE_String_Const source_list[] = { SANE_I18N ("Flatbed"), SANE_I18N ("Transparency Adapter"), 0 }; static SANE_Range x_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (216.0), /* maximum */ SANE_FIX (0.0) /* quantization */ }; static SANE_Range y_range = { SANE_FIX (0.0), /* minimum */ SANE_FIX (299.0), /* maximum */ SANE_FIX (0.0) /* quantization */ }; static const SANE_Range offset_range = { -63, /* minimum */ 63, /* maximum */ 1 /* quantization */ }; static SANE_Range gamma_range = { SANE_FIX (0.01), /* minimum */ SANE_FIX (5.0), /* maximum */ SANE_FIX (0.01) /* quantization */ }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /* Test if this machine is little endian (from coolscan.c) */ static SANE_Bool calc_little_endian (void) { SANE_Int testvalue = 255; uint8_t *firstbyte = (uint8_t *) & testvalue; if (*firstbyte == 255) return SANE_TRUE; return SANE_FALSE; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status get_afe_values (SANE_String_Const cp, GT68xx_AFE_Parameters * afe) { SANE_Char *word, *end; int i; for (i = 0; i < 6; i++) { cp = sanei_config_get_string (cp, &word); if (word && *word) { long int long_value; errno = 0; long_value = strtol (word, &end, 0); if (end == word) { DBG (5, "get_afe_values: can't parse %d. parameter `%s'\n", i + 1, word); free (word); word = 0; return SANE_STATUS_INVAL; } else if (errno) { DBG (5, "get_afe_values: can't parse %d. parameter `%s' " "(%s)\n", i + 1, word, strerror (errno)); free (word); word = 0; return SANE_STATUS_INVAL; } else if (long_value < 0) { DBG (5, "get_afe_values: %d. parameter < 0 (%d)\n", i + 1, (int) long_value); free (word); word = 0; return SANE_STATUS_INVAL; } else if (long_value > 0x3f) { DBG (5, "get_afe_values: %d. parameter > 0x3f (%d)\n", i + 1, (int) long_value); free (word); word = 0; return SANE_STATUS_INVAL; } else { DBG (5, "get_afe_values: %d. parameter set to 0x%02x\n", i + 1, (int) long_value); switch (i) { case 0: afe->r_offset = (SANE_Byte) long_value; break; case 1: afe->r_pga = (SANE_Byte) long_value; break; case 2: afe->g_offset = (SANE_Byte) long_value; break; case 3: afe->g_pga = (SANE_Byte) long_value; break; case 4: afe->b_offset = (SANE_Byte) long_value; break; case 5: afe->b_pga = (SANE_Byte) long_value; break; } free (word); word = 0; } } else { DBG (5, "get_afe_values: option `afe' needs 6 parameters\n"); return SANE_STATUS_INVAL; } } return SANE_STATUS_GOOD; } static SANE_Status setup_scan_request (GT68xx_Scanner * s, GT68xx_Scan_Request * scan_request) { if (s->dev->model->flags & GT68XX_FLAG_MIRROR_X) scan_request->x0 = s->opt[OPT_TL_X].constraint.range->max - s->val[OPT_BR_X].w; else scan_request->x0 = s->val[OPT_TL_X].w; scan_request->y0 = s->val[OPT_TL_Y].w; scan_request->xs = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w; scan_request->ys = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w; if (s->val[OPT_FULL_SCAN].w == SANE_TRUE) { scan_request->x0 -= s->dev->model->x_offset; scan_request->y0 -= (s->dev->model->y_offset); scan_request->xs += s->dev->model->x_offset; scan_request->ys += s->dev->model->y_offset; } scan_request->xdpi = s->val[OPT_RESOLUTION].w; if (scan_request->xdpi > s->dev->model->optical_xdpi) scan_request->xdpi = s->dev->model->optical_xdpi; scan_request->ydpi = s->val[OPT_RESOLUTION].w; if (IS_ACTIVE (OPT_BIT_DEPTH) && !s->val[OPT_PREVIEW].w) scan_request->depth = s->val[OPT_BIT_DEPTH].w; else scan_request->depth = 8; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) scan_request->color = SANE_TRUE; else scan_request->color = SANE_FALSE; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { SANE_Int xs = SANE_UNFIX (scan_request->xs) * scan_request->xdpi / MM_PER_INCH + 0.5; if (xs % 8) { scan_request->xs = SANE_FIX ((xs - (xs % 8)) * MM_PER_INCH / scan_request->xdpi); DBG (5, "setup_scan_request: lineart mode, %d pixels %% 8 = %d\n", xs, xs % 8); } } scan_request->calculate = SANE_FALSE; scan_request->lamp = SANE_TRUE; scan_request->mbs = SANE_FALSE; if (strcmp (s->val[OPT_SOURCE].s, "Transparency Adapter") == 0) scan_request->use_ta = SANE_TRUE; else scan_request->use_ta = SANE_FALSE; return SANE_STATUS_GOOD; } static SANE_Status calc_parameters (GT68xx_Scanner * s) { SANE_String val; SANE_Status status = SANE_STATUS_GOOD; GT68xx_Scan_Request scan_request; GT68xx_Scan_Parameters scan_params; DBG (5, "calc_parameters: start\n"); val = s->val[OPT_MODE].s; s->params.last_frame = SANE_TRUE; if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0 || strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) s->params.format = SANE_FRAME_GRAY; else /* Color */ s->params.format = SANE_FRAME_RGB; setup_scan_request (s, &scan_request); scan_request.calculate = SANE_TRUE; status = gt68xx_device_setup_scan (s->dev, &scan_request, SA_SCAN, &scan_params); if (status != SANE_STATUS_GOOD) { DBG (1, "calc_parameters: gt68xx_device_setup_scan returned: %s\n", sane_strstatus (status)); return status; } if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) s->params.depth = 1; else s->params.depth = scan_params.depth; s->params.lines = scan_params.pixel_ys; s->params.pixels_per_line = scan_params.pixel_xs; /* Inflate X if necessary */ if (s->val[OPT_RESOLUTION].w > s->dev->model->optical_xdpi) s->params.pixels_per_line *= (s->val[OPT_RESOLUTION].w / s->dev->model->optical_xdpi); s->params.bytes_per_line = s->params.pixels_per_line; if (s->params.depth > 8) { s->params.depth = 16; s->params.bytes_per_line *= 2; } else if (s->params.depth == 1) s->params.bytes_per_line /= 8; if (s->params.format == SANE_FRAME_RGB) s->params.bytes_per_line *= 3; DBG (5, "calc_parameters: exit\n"); return status; } static SANE_Status create_bpp_list (GT68xx_Scanner * s, SANE_Int * bpp) { int count; for (count = 0; bpp[count] != 0; count++) ; s->bpp_list[0] = count; for (count = 0; bpp[count] != 0; count++) { s->bpp_list[s->bpp_list[0] - count] = bpp[count]; } return SANE_STATUS_GOOD; } static SANE_Status init_options (GT68xx_Scanner * s) { SANE_Int option, count; SANE_Status status; SANE_Word *dpi_list; GT68xx_Model *model = s->dev->model; SANE_Bool has_ta = SANE_FALSE; DBG (5, "init_options: start\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (option = 0; option < NUM_OPTIONS; ++option) { s->opt[option].size = sizeof (SANE_Word); s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (SANE_VALUE_SCAN_MODE_GRAY); /* scan mode */ s->opt[OPT_GRAY_MODE_COLOR].name = "gray-mode-color"; s->opt[OPT_GRAY_MODE_COLOR].title = SANE_I18N ("Gray mode color"); s->opt[OPT_GRAY_MODE_COLOR].desc = SANE_I18N ("Selects which scan color is used " "gray mode (default: green)."); s->opt[OPT_GRAY_MODE_COLOR].type = SANE_TYPE_STRING; s->opt[OPT_GRAY_MODE_COLOR].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_GRAY_MODE_COLOR].size = max_string_size (gray_mode_list); s->opt[OPT_GRAY_MODE_COLOR].constraint.string_list = gray_mode_list; s->val[OPT_GRAY_MODE_COLOR].s = strdup (GT68XX_COLOR_GREEN); /* scan source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].size = max_string_size (source_list); s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].s = strdup ("Flatbed"); status = gt68xx_device_get_ta_status (s->dev, &has_ta); if (status != SANE_STATUS_GOOD || !has_ta) DISABLE (OPT_SOURCE); /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE; s->opt[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_PREVIEW].w = SANE_FALSE; /* lamp on */ s->opt[OPT_LAMP_OFF_AT_EXIT].name = SANE_NAME_LAMP_OFF_AT_EXIT; s->opt[OPT_LAMP_OFF_AT_EXIT].title = SANE_TITLE_LAMP_OFF_AT_EXIT; s->opt[OPT_LAMP_OFF_AT_EXIT].desc = SANE_DESC_LAMP_OFF_AT_EXIT; s->opt[OPT_LAMP_OFF_AT_EXIT].type = SANE_TYPE_BOOL; s->opt[OPT_LAMP_OFF_AT_EXIT].unit = SANE_UNIT_NONE; s->opt[OPT_LAMP_OFF_AT_EXIT].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_LAMP_OFF_AT_EXIT].w = SANE_TRUE; if (s->dev->model->is_cis && !(s->dev->model->flags & GT68XX_FLAG_CIS_LAMP)) DISABLE (OPT_LAMP_OFF_AT_EXIT); /* bit depth */ s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_BIT_DEPTH].size = sizeof (SANE_Word); s->opt[OPT_BIT_DEPTH].constraint.word_list = 0; s->opt[OPT_BIT_DEPTH].constraint.word_list = s->bpp_list; RIE (create_bpp_list (s, s->dev->model->bpp_gray_values)); s->val[OPT_BIT_DEPTH].w = 8; if (s->opt[OPT_BIT_DEPTH].constraint.word_list[0] < 2) DISABLE (OPT_BIT_DEPTH); /* resolution */ for (count = 0; model->ydpi_values[count] != 0; count++) ; dpi_list = malloc ((count + 1) * sizeof (SANE_Word)); if (!dpi_list) return SANE_STATUS_NO_MEM; dpi_list[0] = count; for (count = 0; model->ydpi_values[count] != 0; count++) dpi_list[dpi_list[0] - count] = model->ydpi_values[count]; s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; s->val[OPT_RESOLUTION].w = 300; /* backtrack */ s->opt[OPT_BACKTRACK].name = SANE_NAME_BACKTRACK; s->opt[OPT_BACKTRACK].title = SANE_TITLE_BACKTRACK; s->opt[OPT_BACKTRACK].desc = SANE_DESC_BACKTRACK; s->opt[OPT_BACKTRACK].type = SANE_TYPE_BOOL; s->val[OPT_BACKTRACK].w = SANE_FALSE; /* "Debug" group: */ s->opt[OPT_DEBUG_GROUP].title = SANE_I18N ("Debugging Options"); s->opt[OPT_DEBUG_GROUP].desc = ""; s->opt[OPT_DEBUG_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_DEBUG_GROUP].size = 0; s->opt[OPT_DEBUG_GROUP].cap = 0; s->opt[OPT_DEBUG_GROUP].constraint_type = SANE_CONSTRAINT_NONE; if (!debug_options) DISABLE (OPT_DEBUG_GROUP); /* auto warmup */ s->opt[OPT_AUTO_WARMUP].name = "auto-warmup"; s->opt[OPT_AUTO_WARMUP].title = SANE_I18N ("Automatic warmup"); s->opt[OPT_AUTO_WARMUP].desc = SANE_I18N ("Warm-up until the lamp's brightness is constant " "instead of insisting on 60 seconds warm-up time."); s->opt[OPT_AUTO_WARMUP].type = SANE_TYPE_BOOL; s->opt[OPT_AUTO_WARMUP].unit = SANE_UNIT_NONE; s->opt[OPT_AUTO_WARMUP].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_AUTO_WARMUP].w = SANE_TRUE; if ((s->dev->model->is_cis && !(s->dev->model->flags & GT68XX_FLAG_CIS_LAMP)) || !debug_options) DISABLE (OPT_AUTO_WARMUP); /* full scan */ s->opt[OPT_FULL_SCAN].name = "full-scan"; s->opt[OPT_FULL_SCAN].title = SANE_I18N ("Full scan"); s->opt[OPT_FULL_SCAN].desc = SANE_I18N ("Scan the complete scanning area including calibration strip. " "Be careful. Don't select the full height. For testing only."); s->opt[OPT_FULL_SCAN].type = SANE_TYPE_BOOL; s->opt[OPT_FULL_SCAN].unit = SANE_UNIT_NONE; s->opt[OPT_FULL_SCAN].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_FULL_SCAN].w = SANE_FALSE; if (!debug_options) DISABLE (OPT_FULL_SCAN); /* coarse calibration */ s->opt[OPT_COARSE_CAL].name = "coarse-calibration"; s->opt[OPT_COARSE_CAL].title = SANE_I18N ("Coarse calibration"); s->opt[OPT_COARSE_CAL].desc = SANE_I18N ("Setup gain and offset for scanning automatically. If this " "option is disabled, options for setting the analog frontend " "parameters manually are provided. This option is enabled " "by default. For testing only."); s->opt[OPT_COARSE_CAL].type = SANE_TYPE_BOOL; s->opt[OPT_COARSE_CAL].unit = SANE_UNIT_NONE; s->opt[OPT_COARSE_CAL].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_COARSE_CAL].w = SANE_TRUE; if (!debug_options) DISABLE (OPT_COARSE_CAL); if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED) { s->val[OPT_COARSE_CAL].w = SANE_FALSE; DISABLE (OPT_COARSE_CAL); } /* coarse calibration only once */ s->opt[OPT_COARSE_CAL_ONCE].name = "coarse-calibration-once"; s->opt[OPT_COARSE_CAL_ONCE].title = SANE_I18N ("Coarse calibration for first scan only"); s->opt[OPT_COARSE_CAL_ONCE].desc = SANE_I18N ("Coarse calibration is only done for the first scan. Works " "with most scanners and can save scanning time. If the image " "brightness is different with each scan, disable this option. " "For testing only."); s->opt[OPT_COARSE_CAL_ONCE].type = SANE_TYPE_BOOL; s->opt[OPT_COARSE_CAL_ONCE].unit = SANE_UNIT_NONE; s->opt[OPT_COARSE_CAL_ONCE].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_COARSE_CAL_ONCE].w = SANE_FALSE; if (!debug_options) DISABLE (OPT_COARSE_CAL_ONCE); if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED) DISABLE (OPT_COARSE_CAL_ONCE); /* calibration */ s->opt[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL; s->opt[OPT_QUALITY_CAL].title = SANE_TITLE_QUALITY_CAL; s->opt[OPT_QUALITY_CAL].desc = SANE_TITLE_QUALITY_CAL; s->opt[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL; s->opt[OPT_QUALITY_CAL].unit = SANE_UNIT_NONE; s->opt[OPT_QUALITY_CAL].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_QUALITY_CAL].w = SANE_TRUE; if (!debug_options) DISABLE (OPT_QUALITY_CAL); /* we disable image correction for scanners that can't calibrate */ if ((s->dev->model->flags & GT68XX_FLAG_SHEET_FED) &&(!(s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE))) { s->val[OPT_QUALITY_CAL].w = SANE_FALSE; DISABLE (OPT_QUALITY_CAL); } /* backtrack lines */ s->opt[OPT_BACKTRACK_LINES].name = "backtrack-lines"; s->opt[OPT_BACKTRACK_LINES].title = SANE_I18N ("Backtrack lines"); s->opt[OPT_BACKTRACK_LINES].desc = SANE_I18N ("Number of lines the scan slider moves back when backtracking " "occurs. That happens when the scanner scans faster than the " "computer can receive the data. Low values cause faster scans " "but increase the risk of omitting lines."); s->opt[OPT_BACKTRACK_LINES].type = SANE_TYPE_INT; s->opt[OPT_BACKTRACK_LINES].unit = SANE_UNIT_NONE; s->opt[OPT_BACKTRACK_LINES].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BACKTRACK_LINES].constraint.range = &u8_range; if (s->dev->model->is_cis && !(s->dev->model->flags & GT68XX_FLAG_SHEET_FED)) s->val[OPT_BACKTRACK_LINES].w = 0x10; else s->val[OPT_BACKTRACK_LINES].w = 0x3f; if (!debug_options) DISABLE (OPT_BACKTRACK_LINES); /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* internal gamma value */ s->opt[OPT_GAMMA_VALUE].name = "gamma-value"; s->opt[OPT_GAMMA_VALUE].title = SANE_I18N ("Gamma value"); s->opt[OPT_GAMMA_VALUE].desc = SANE_I18N ("Sets the gamma value of all channels."); s->opt[OPT_GAMMA_VALUE].type = SANE_TYPE_FIXED; s->opt[OPT_GAMMA_VALUE].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VALUE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VALUE].constraint.range = &gamma_range; s->opt[OPT_GAMMA_VALUE].cap |= SANE_CAP_EMULATED; s->val[OPT_GAMMA_VALUE].w = s->dev->gamma_value; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &u8_range; s->val[OPT_THRESHOLD].w = 128; DISABLE (OPT_THRESHOLD); /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; x_range.max = model->x_size; y_range.max = model->y_size; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &x_range; s->val[OPT_BR_X].w = x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &y_range; s->val[OPT_BR_Y].w = y_range.max; /* sensor group */ s->opt[OPT_SENSOR_GROUP].name = SANE_NAME_SENSORS; s->opt[OPT_SENSOR_GROUP].title = SANE_TITLE_SENSORS; s->opt[OPT_SENSOR_GROUP].desc = SANE_DESC_SENSORS; s->opt[OPT_SENSOR_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_SENSOR_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* calibration needed */ s->opt[OPT_NEED_CALIBRATION_SW].name = "need-calibration"; s->opt[OPT_NEED_CALIBRATION_SW].title = SANE_I18N ("Need calibration"); s->opt[OPT_NEED_CALIBRATION_SW].desc = SANE_I18N ("The scanner needs calibration for the current settings"); s->opt[OPT_NEED_CALIBRATION_SW].type = SANE_TYPE_BOOL; s->opt[OPT_NEED_CALIBRATION_SW].unit = SANE_UNIT_NONE; if (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE) s->opt[OPT_NEED_CALIBRATION_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_NEED_CALIBRATION_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_NEED_CALIBRATION_SW].b = 0; /* document present sensor */ s->opt[OPT_PAGE_LOADED_SW].name = SANE_NAME_PAGE_LOADED; s->opt[OPT_PAGE_LOADED_SW].title = SANE_TITLE_PAGE_LOADED; s->opt[OPT_PAGE_LOADED_SW].desc = SANE_DESC_PAGE_LOADED; s->opt[OPT_PAGE_LOADED_SW].type = SANE_TYPE_BOOL; s->opt[OPT_PAGE_LOADED_SW].unit = SANE_UNIT_NONE; if (s->dev->model->command_set->document_present) s->opt[OPT_PAGE_LOADED_SW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_HARD_SELECT | SANE_CAP_ADVANCED; else s->opt[OPT_PAGE_LOADED_SW].cap = SANE_CAP_INACTIVE; s->val[OPT_PAGE_LOADED_SW].b = 0; /* button group */ s->opt[OPT_BUTTON_GROUP].name = "Buttons"; s->opt[OPT_BUTTON_GROUP].title = SANE_I18N ("Buttons"); s->opt[OPT_BUTTON_GROUP].desc = SANE_I18N ("Buttons"); s->opt[OPT_BUTTON_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_BUTTON_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* calibrate button */ s->opt[OPT_CALIBRATE].name = "calibrate"; s->opt[OPT_CALIBRATE].title = SANE_I18N ("Calibrate"); s->opt[OPT_CALIBRATE].desc = SANE_I18N ("Start calibration using special sheet"); s->opt[OPT_CALIBRATE].type = SANE_TYPE_BUTTON; s->opt[OPT_CALIBRATE].unit = SANE_UNIT_NONE; if (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE) s->opt[OPT_CALIBRATE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; else s->opt[OPT_CALIBRATE].cap = SANE_CAP_INACTIVE; s->val[OPT_CALIBRATE].b = 0; /* clear calibration cache button */ s->opt[OPT_CLEAR_CALIBRATION].name = "clear"; s->opt[OPT_CLEAR_CALIBRATION].title = SANE_I18N ("Clear calibration"); s->opt[OPT_CLEAR_CALIBRATION].desc = SANE_I18N ("Clear calibration cache"); s->opt[OPT_CLEAR_CALIBRATION].type = SANE_TYPE_BUTTON; s->opt[OPT_CLEAR_CALIBRATION].unit = SANE_UNIT_NONE; if (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE) s->opt[OPT_CLEAR_CALIBRATION].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC; else s->opt[OPT_CLEAR_CALIBRATION].cap = SANE_CAP_INACTIVE; s->val[OPT_CLEAR_CALIBRATION].b = 0; RIE (calc_parameters (s)); DBG (5, "init_options: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach (SANE_String_Const devname, GT68xx_Device ** devp, SANE_Bool may_wait) { GT68xx_Device *dev; SANE_Status status; DBG (5, "attach: start: devp %s NULL, may_wait = %d\n", devp ? "!=" : "==", may_wait); if (!devname) { DBG (1, "attach: devname == NULL\n"); return SANE_STATUS_INVAL; } for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->file_name, devname) == 0) { if (devp) *devp = dev; dev->missing = SANE_FALSE; DBG (4, "attach: device `%s' was already in device list\n", devname); return SANE_STATUS_GOOD; } } DBG (4, "attach: trying to open device `%s'\n", devname); RIE (gt68xx_device_new (&dev)); status = gt68xx_device_open (dev, devname); if (status == SANE_STATUS_GOOD) DBG (4, "attach: device `%s' successfully opened\n", devname); else { DBG (4, "attach: couldn't open device `%s': %s\n", devname, sane_strstatus (status)); gt68xx_device_free (dev); if (devp) *devp = 0; return status; } if (!gt68xx_device_is_configured (dev)) { GT68xx_Model *model = NULL; DBG (2, "attach: Warning: device `%s' is not listed in device table\n", devname); DBG (2, "attach: If you have manually added it, use override in gt68xx.conf\n"); gt68xx_device_get_model ("unknown-scanner", &model); status = gt68xx_device_set_model (dev, model); if (status != SANE_STATUS_GOOD) { DBG (4, "attach: couldn't set model: %s\n", sane_strstatus (status)); gt68xx_device_free (dev); if (devp) *devp = 0; return status; } dev->manual_selection = SANE_TRUE; } dev->file_name = strdup (devname); dev->missing = SANE_FALSE; if (!dev->file_name) return SANE_STATUS_NO_MEM; DBG (2, "attach: found %s flatbed scanner %s at %s\n", dev->model->vendor, dev->model->model, dev->file_name); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; gt68xx_device_close (dev); DBG (5, "attach: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one_device (SANE_String_Const devname) { GT68xx_Device *dev; SANE_Status status; RIE (attach (devname, &dev, SANE_FALSE)); if (dev) { /* Keep track of newly attached devices so we can set options as necessary. */ if (new_dev_len >= new_dev_alloced) { new_dev_alloced += 4; if (new_dev) new_dev = realloc (new_dev, new_dev_alloced * sizeof (new_dev[0])); else new_dev = malloc (new_dev_alloced * sizeof (new_dev[0])); if (!new_dev) { DBG (1, "attach_one_device: out of memory\n"); return SANE_STATUS_NO_MEM; } } new_dev[new_dev_len++] = dev; } return SANE_STATUS_GOOD; } #if defined(_WIN32) || defined(HAVE_OS2_H) # define PATH_SEP "\\" #else # define PATH_SEP "/" #endif static SANE_Status download_firmware_file (GT68xx_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte *buf = NULL; int size = -1; SANE_Char filename[PATH_MAX], dirname[PATH_MAX], basename[PATH_MAX]; FILE *f; if (strncmp (dev->model->firmware_name, PATH_SEP, 1) != 0) { /* probably filename only */ snprintf (filename, PATH_MAX, "%s%s%s%s%s%s%s", STRINGIFY (PATH_SANE_DATA_DIR), PATH_SEP, "sane", PATH_SEP, "gt68xx", PATH_SEP, dev->model->firmware_name); snprintf (dirname, PATH_MAX, "%s%s%s%s%s", STRINGIFY (PATH_SANE_DATA_DIR), PATH_SEP, "sane", PATH_SEP, "gt68xx"); strncpy (basename, dev->model->firmware_name, PATH_MAX); } else { /* absolute path */ char *pos; strncpy (filename, dev->model->firmware_name, PATH_MAX); strncpy (dirname, dev->model->firmware_name, PATH_MAX); pos = strrchr (dirname, PATH_SEP[0]); if (pos) pos[0] = '\0'; strncpy (basename, pos + 1, PATH_MAX); } /* first, try to open with exact case */ DBG (5, "download_firmware: trying %s\n", filename); f = fopen (filename, "rb"); if (!f) { /* and now any case */ DIR *dir; struct dirent *direntry; DBG (5, "download_firmware_file: Couldn't open firmware file `%s': %s\n", filename, strerror (errno)); dir = opendir (dirname); if (!dir) { DBG (5, "download_firmware: couldn't open directory `%s': %s\n", dirname, strerror (errno)); status = SANE_STATUS_INVAL; } if (status == SANE_STATUS_GOOD) { do { direntry = readdir (dir); if (direntry && (strncasecmp (direntry->d_name, basename, PATH_MAX) == 0)) { snprintf (filename, PATH_MAX, "%s%s%s", dirname, PATH_SEP, direntry->d_name); break; } } while (direntry != 0); if (direntry == 0) { DBG (5, "download_firmware: file `%s' not found\n", filename); status = SANE_STATUS_INVAL; } closedir (dir); } if (status == SANE_STATUS_GOOD) { DBG (5, "download_firmware: trying %s\n", filename); f = fopen (filename, "rb"); if (!f) { DBG (5, "download_firmware_file: Couldn't open firmware file `%s': %s\n", filename, strerror (errno)); status = SANE_STATUS_INVAL; } } if (status != SANE_STATUS_GOOD) { DBG (0, "Couldn't open firmware file (`%s'): %s\n", filename, strerror (errno)); } } if (status == SANE_STATUS_GOOD) { fseek (f, 0, SEEK_END); size = ftell (f); fseek (f, 0, SEEK_SET); if (size == -1) { DBG (1, "download_firmware_file: error getting size of " "firmware file \"%s\": %s\n", filename, strerror (errno)); status = SANE_STATUS_INVAL; } } if (status == SANE_STATUS_GOOD) { DBG (5, "firmware size: %d\n", size); buf = (SANE_Byte *) malloc (size); if (!buf) { DBG (1, "download_firmware_file: cannot allocate %d bytes " "for firmware\n", size); status = SANE_STATUS_NO_MEM; } } if (status == SANE_STATUS_GOOD) { int bytes_read = fread (buf, 1, size, f); if (bytes_read != size) { DBG (1, "download_firmware_file: problem reading firmware " "file \"%s\": %s\n", filename, strerror (errno)); status = SANE_STATUS_INVAL; } } if (f) fclose (f); if (status == SANE_STATUS_GOOD) { status = gt68xx_device_download_firmware (dev, buf, size); if (status != SANE_STATUS_GOOD) { DBG (1, "download_firmware_file: firmware download failed: %s\n", sane_strstatus (status)); } } if (buf) free (buf); return status; } /** probe for gt68xx devices * This function scan usb and try to attached to scanner * configured in gt68xx.conf . */ static SANE_Status probe_gt68xx_devices(void) { SANE_Char line[PATH_MAX]; SANE_Char *word; SANE_String_Const cp; SANE_Int linenumber; GT68xx_Device *dev; FILE *fp; /* set up for no new devices detected at first */ new_dev = 0; new_dev_len = 0; new_dev_alloced = 0; /* mark already detected devices as missing, during device probe * detected devices will clear this flag */ dev = first_dev; while(dev!=NULL) { dev->missing = SANE_TRUE; dev = dev->next; } fp = sanei_config_open (GT68XX_CONFIG_FILE); if (!fp) { /* default to /dev/usb/scanner instead of insisting on config file */ DBG (3, "sane_init: couldn't open config file `%s': %s. Using " "/dev/usb/scanner directly\n", GT68XX_CONFIG_FILE, strerror (errno)); attach ("/dev/usb/scanner", 0, SANE_FALSE); return SANE_STATUS_GOOD; } little_endian = calc_little_endian (); DBG (5, "sane_init: %s endian machine\n", little_endian ? "little" : "big"); linenumber = 0; DBG (4, "sane_init: reading config file `%s'\n", GT68XX_CONFIG_FILE); while (sanei_config_read (line, sizeof (line), fp)) { word = 0; linenumber++; cp = sanei_config_get_string (line, &word); if (!word || cp == line) { DBG (6, "sane_init: config file line %d: ignoring empty line\n", linenumber); if (word) free (word); continue; } if (word[0] == '#') { DBG (6, "sane_init: config file line %d: ignoring comment line\n", linenumber); free (word); continue; } if (strcmp (word, "firmware") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (word) { int i; for (i = 0; i < new_dev_len; i++) { new_dev[i]->model->firmware_name = word; DBG (5, "sane_init: device %s: firmware will be loaded " "from %s\n", new_dev[i]->model->name, new_dev[i]->model->firmware_name); } if (i == 0) DBG (5, "sane_init: firmware %s can't be loaded, set device " "first\n", word); } else { DBG (3, "sane_init: option `firmware' needs a parameter\n"); } } else if (strcmp (word, "vendor") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (word) { int i; for (i = 0; i < new_dev_len; i++) { new_dev[i]->model->vendor = word; DBG (5, "sane_init: device %s: vendor name set to %s\n", new_dev[i]->model->name, new_dev[i]->model->vendor); } if (i == 0) DBG (5, "sane_init: can't set vendor name %s, set device " "first\n", word); } else { DBG (3, "sane_init: option `vendor' needs a parameter\n"); } } else if (strcmp (word, "model") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (word) { int i; for (i = 0; i < new_dev_len; i++) { new_dev[i]->model->model = word; DBG (5, "sane_init: device %s: model name set to %s\n", new_dev[i]->model->name, new_dev[i]->model->model); } if (i == 0) DBG (5, "sane_init: can't set model name %s, set device " "first\n", word); free (word); } else { DBG (3, "sane_init: option `model' needs a parameter\n"); } } else if (strcmp (word, "override") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (word) { int i; for (i = 0; i < new_dev_len; i++) { SANE_Status status; GT68xx_Device *dev = new_dev[i]; GT68xx_Model *model; if (gt68xx_device_get_model (word, &model) == SANE_TRUE) { status = gt68xx_device_set_model (dev, model); if (status != SANE_STATUS_GOOD) DBG (1, "sane_init: couldn't override model: %s\n", sane_strstatus (status)); else DBG (5, "sane_init: new model set to %s\n", dev->model->name); } else { DBG (1, "sane_init: override: model %s not found\n", word); } } if (i == 0) DBG (5, "sane_init: can't override model to %s, set device " "first\n", word); free (word); } else { DBG (3, "sane_init: option `override' needs a parameter\n"); } } else if (strcmp (word, "afe") == 0) { GT68xx_AFE_Parameters afe = {0, 0, 0, 0, 0, 0}; SANE_Status status; free (word); word = 0; status = get_afe_values (cp, &afe); if (status == SANE_STATUS_GOOD) { int i; for (i = 0; i < new_dev_len; i++) { new_dev[i]->model->afe_params = afe; DBG (5, "sane_init: device %s: setting new afe values\n", new_dev[i]->model->name); } if (i == 0) DBG (5, "sane_init: can't set afe values, set device first\n"); } else DBG (3, "sane_init: can't set afe values\n"); } else { new_dev_len = 0; DBG (4, "sane_init: config file line %d: trying to attach `%s'\n", linenumber, line); sanei_usb_attach_matching_devices (line, attach_one_device); if (word) free (word); word = 0; } } if (new_dev_alloced > 0) { new_dev_len = new_dev_alloced = 0; free (new_dev); } fclose (fp); return SANE_STATUS_GOOD; } /* -------------------------- SANE API functions ------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { SANE_Status status; DBG_INIT (); #ifdef DBG_LEVEL if (DBG_LEVEL > 0) { DBG (5, "sane_init: debug options are enabled, handle with care\n"); debug_options = SANE_TRUE; } #endif DBG (2, "SANE GT68xx backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (5, "sane_init: authorize %s null\n", authorize ? "!=" : "=="); sanei_usb_init (); num_devices = 0; first_dev = 0; first_handle = 0; devlist = 0; new_dev = 0; new_dev_len = 0; new_dev_alloced = 0; status = probe_gt68xx_devices (); DBG (5, "sane_init: exit\n"); return status; } void sane_exit (void) { GT68xx_Device *dev, *next; DBG (5, "sane_exit: start\n"); sanei_usb_exit(); for (dev = first_dev; dev; dev = next) { next = dev->next; gt68xx_device_free (dev); } first_dev = 0; first_handle = 0; if (devlist) free (devlist); devlist = 0; DBG (5, "sane_exit: exit\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { GT68xx_Device *dev; SANE_Int dev_num; DBG (5, "sane_get_devices: start: local_only = %s\n", local_only == SANE_TRUE ? "true" : "false"); /* hot-plug case : detection of newly connected scanners */ sanei_usb_scan_devices (); probe_gt68xx_devices (); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; dev_num = 0; dev = first_dev; while(dev!=NULL) { SANE_Device *sane_device; /* don't return devices that have been unplugged */ if(dev->missing==SANE_FALSE) { sane_device = malloc (sizeof (*sane_device)); if (!sane_device) return SANE_STATUS_NO_MEM; sane_device->name = dev->file_name; sane_device->vendor = dev->model->vendor; sane_device->model = dev->model->model; sane_device->type = strdup ("flatbed scanner"); devlist[dev_num] = sane_device; dev_num++; } /* next device */ dev = dev->next; } devlist[dev_num] = 0; *device_list = devlist; DBG (5, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { GT68xx_Device *dev; SANE_Status status; GT68xx_Scanner *s; SANE_Bool power_ok; DBG (5, "sane_open: start (devicename = `%s')\n", devicename); if (devicename[0]) { /* test for gt68xx short hand name */ if(strcmp(devicename,"gt68xx")!=0) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->file_name, devicename) == 0) break; if (!dev) { DBG (5, "sane_open: couldn't find `%s' in devlist, trying attach\n", devicename); RIE (attach (devicename, &dev, SANE_TRUE)); } else DBG (5, "sane_open: found `%s' in devlist\n", dev->model->name); } else { dev = first_dev; if (dev) { devicename = dev->file_name; DBG (5, "sane_open: default empty devicename, using first device `%s'\n", devicename); } } } else { /* empty devicname -> use first device */ dev = first_dev; if (dev) { devicename = dev->file_name; DBG (5, "sane_open: empty devicename, trying `%s'\n", devicename); } } if (!dev) return SANE_STATUS_INVAL; RIE (gt68xx_device_open (dev, devicename)); RIE (gt68xx_device_activate (dev)); if (dev->model->flags & GT68XX_FLAG_UNTESTED) { DBG (0, "WARNING: Your scanner is not fully supported or at least \n"); DBG (0, " had only limited testing. Please be careful and \n"); DBG (0, " report any failure/success to \n"); DBG (0, " sane-devel@lists.alioth.debian.org. Please provide as many\n"); DBG (0, " details as possible, e.g. the exact name of your\n"); DBG (0, " scanner and what does (not) work.\n"); } if (dev->manual_selection) { DBG (0, "WARNING: You have manually added the ids of your scanner \n"); DBG (0, " to gt68xx.conf. Please use an appropriate override \n"); DBG (0, " for your scanner. Use extreme care and switch off \n"); DBG (0, " the scanner immediately if you hear unusual noise. \n"); DBG (0, " Please report any success to \n"); DBG (0, " sane-devel@lists.alioth.debian.org. Please provide as many\n"); DBG (0, " details as possible, e.g. the exact name of your\n"); DBG (0, " scanner, ids, settings etc.\n"); if (strcmp (dev->model->name, "unknown-scanner") == 0) { GT68xx_USB_Device_Entry *entry; DBG (0, "ERROR: You haven't chosen an override in gt68xx.conf. Please use \n"); DBG (0, " one of the following: \n"); for (entry = gt68xx_usb_device_list; entry->model; ++entry) { if (strcmp (entry->model->name, "unknown-scanner") != 0) DBG (0, " %s\n", entry->model->name); } return SANE_STATUS_UNSUPPORTED; } } /* The firmware check is disabled by default because it may confuse some scanners: So the firmware is loaded everytime. */ #if 0 RIE (gt68xx_device_check_firmware (dev, &firmware_loaded)); firmware_loaded = SANE_FALSE; if (firmware_loaded) DBG (3, "sane_open: firmware already loaded, skipping load\n"); else RIE (download_firmware_file (dev)); /* RIE (gt68xx_device_check_firmware (dev, &firmware_loaded)); */ if (!firmware_loaded) { DBG (1, "sane_open: firmware still not loaded? Proceeding anyway\n"); /* return SANE_STATUS_IO_ERROR; */ } #else RIE (download_firmware_file (dev)); #endif RIE (gt68xx_device_get_id (dev)); if (!(dev->model->flags & GT68XX_FLAG_NO_STOP)) RIE (gt68xx_device_stop_scan (dev)); RIE (gt68xx_device_get_power_status (dev, &power_ok)); if (power_ok) { DBG (5, "sane_open: power ok\n"); } else { DBG (0, "sane_open: power control failure: check power plug!\n"); return SANE_STATUS_IO_ERROR; } RIE (gt68xx_scanner_new (dev, &s)); RIE (gt68xx_device_lamp_control (s->dev, SANE_TRUE, SANE_FALSE)); gettimeofday (&s->lamp_on_time, 0); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; s->scanning = SANE_FALSE; s->first_scan = SANE_TRUE; s->gamma_table = 0; s->calibrated = SANE_FALSE; RIE (init_options (s)); dev->gray_mode_color = 0x02; /* try to restore calibration from file */ if((s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)) { /* error restoring calibration is non blocking */ gt68xx_read_calibration(s); } DBG (5, "sane_open: exit\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { GT68xx_Scanner *prev, *s; GT68xx_Device *dev; DBG (5, "sane_close: start\n"); /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (5, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (prev) prev->next = s->next; else first_handle = s->next; if (s->val[OPT_LAMP_OFF_AT_EXIT].w == SANE_TRUE) gt68xx_device_lamp_control (s->dev, SANE_FALSE, SANE_FALSE); dev = s->dev; free (s->val[OPT_MODE].s); free (s->val[OPT_GRAY_MODE_COLOR].s); free (s->val[OPT_SOURCE].s); free (dev->file_name); free ((void *)(size_t)s->opt[OPT_RESOLUTION].constraint.word_list); gt68xx_scanner_free (s); gt68xx_device_fix_descriptor (dev); gt68xx_device_deactivate (dev); gt68xx_device_close (dev); DBG (5, "sane_close: exit\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { GT68xx_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; DBG (5, "sane_get_option_descriptor: option = %s (%d)\n", s->opt[option].name, option); return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { GT68xx_Scanner *s = handle; SANE_Status status = SANE_STATUS_GOOD; SANE_Word cap; SANE_Int myinfo = 0; DBG (5, "sane_control_option: start: action = %s, option = %s (%d)\n", (action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_SET_VALUE) ? "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->opt[option].name, option); if (info) *info = 0; if (s->scanning) { DBG (1, "sane_control_option: don't call this function while " "scanning (option = %s (%d))\n", s->opt[option].name, option); return SANE_STATUS_DEVICE_BUSY; } if (option >= NUM_OPTIONS || option < 0) { DBG (1, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", option); return SANE_STATUS_INVAL; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (2, "sane_control_option: option %d is inactive\n", option); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_BIT_DEPTH: case OPT_FULL_SCAN: case OPT_COARSE_CAL: case OPT_COARSE_CAL_ONCE: case OPT_QUALITY_CAL: case OPT_BACKTRACK: case OPT_BACKTRACK_LINES: case OPT_PREVIEW: case OPT_LAMP_OFF_AT_EXIT: case OPT_AUTO_WARMUP: case OPT_GAMMA_VALUE: case OPT_THRESHOLD: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *) val = s->val[option].w; break; /* string options: */ case OPT_MODE: case OPT_GRAY_MODE_COLOR: case OPT_SOURCE: strcpy (val, s->val[option].s); break; case OPT_NEED_CALIBRATION_SW: *(SANE_Bool *) val = !s->calibrated; break; case OPT_PAGE_LOADED_SW: s->dev->model->command_set->document_present (s->dev, val); break; default: DBG (2, "sane_control_option: can't get unknown option %d\n", option); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (2, "sane_control_option: option %d is not settable\n", option); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (2, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } switch (option) { case OPT_RESOLUTION: case OPT_BIT_DEPTH: case OPT_FULL_SCAN: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; RIE (calc_parameters (s)); myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_LAMP_OFF_AT_EXIT: case OPT_AUTO_WARMUP: case OPT_COARSE_CAL_ONCE: case OPT_BACKTRACK_LINES: case OPT_QUALITY_CAL: case OPT_GAMMA_VALUE: case OPT_THRESHOLD: s->val[option].w = *(SANE_Word *) val; break; case OPT_GRAY_MODE_COLOR: if (strcmp (s->val[option].s, val) != 0) { /* something changed */ if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); } break; case OPT_SOURCE: if (strcmp (s->val[option].s, val) != 0) { /* something changed */ if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[option].s, "Transparency Adapter") == 0) { RIE (gt68xx_device_lamp_control (s->dev, SANE_FALSE, SANE_TRUE)); x_range.max = s->dev->model->x_size_ta; y_range.max = s->dev->model->y_size_ta; } else { RIE (gt68xx_device_lamp_control (s->dev, SANE_TRUE, SANE_FALSE)); x_range.max = s->dev->model->x_size; y_range.max = s->dev->model->y_size; } s->first_scan = SANE_TRUE; myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; gettimeofday (&s->lamp_on_time, 0); } break; case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { ENABLE (OPT_THRESHOLD); DISABLE (OPT_BIT_DEPTH); ENABLE (OPT_GRAY_MODE_COLOR); } else { DISABLE (OPT_THRESHOLD); if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) { RIE (create_bpp_list (s, s->dev->model->bpp_gray_values)); ENABLE (OPT_GRAY_MODE_COLOR); } else { RIE (create_bpp_list (s, s->dev->model->bpp_color_values)); DISABLE (OPT_GRAY_MODE_COLOR); } if (s->bpp_list[0] < 2) DISABLE (OPT_BIT_DEPTH); else ENABLE (OPT_BIT_DEPTH); } RIE (calc_parameters (s)); myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; case OPT_COARSE_CAL: s->val[option].w = *(SANE_Word *) val; if (s->val[option].w == SANE_TRUE) { ENABLE (OPT_COARSE_CAL_ONCE); s->first_scan = SANE_TRUE; } else { DISABLE (OPT_COARSE_CAL_ONCE); } myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case OPT_BACKTRACK: s->val[option].w = *(SANE_Word *) val; if (s->val[option].w == SANE_TRUE) ENABLE (OPT_BACKTRACK_LINES); else DISABLE (OPT_BACKTRACK_LINES); myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case OPT_CALIBRATE: status = gt68xx_sheetfed_scanner_calibrate (s); myinfo |= SANE_INFO_RELOAD_OPTIONS; break; case OPT_CLEAR_CALIBRATION: gt68xx_clear_calibration (s); myinfo |= SANE_INFO_RELOAD_OPTIONS; break; default: DBG (2, "sane_control_option: can't set unknown option %d\n", option); } } else { DBG (2, "sane_control_option: unknown action %d for option %d\n", action, option); return SANE_STATUS_INVAL; } if (info) *info = myinfo; DBG (5, "sane_control_option: exit\n"); return status; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { GT68xx_Scanner *s = handle; SANE_Status status; DBG (5, "sane_get_parameters: start\n"); RIE (calc_parameters (s)); if (params) *params = s->params; DBG (4, "sane_get_parameters: format=%d, last_frame=%d, lines=%d\n", s->params.format, s->params.last_frame, s->params.lines); DBG (4, "sane_get_parameters: pixels_per_line=%d, bytes per line=%d\n", s->params.pixels_per_line, s->params.bytes_per_line); DBG (3, "sane_get_parameters: pixels %dx%dx%d\n", s->params.pixels_per_line, s->params.lines, 1 << s->params.depth); DBG (5, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { GT68xx_Scanner *s = handle; GT68xx_Scan_Request scan_request; GT68xx_Scan_Parameters scan_params; SANE_Status status; SANE_Int i, gamma_size; unsigned int *buffer_pointers[3]; SANE_Bool document; DBG (5, "sane_start: start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ RIE (calc_parameters (s)); if (s->val[OPT_TL_X].w >= s->val[OPT_BR_X].w) { DBG (0, "sane_start: top left x >= bottom right x --- exiting\n"); return SANE_STATUS_INVAL; } if (s->val[OPT_TL_Y].w >= s->val[OPT_BR_Y].w) { DBG (0, "sane_start: top left y >= bottom right y --- exiting\n"); return SANE_STATUS_INVAL; } if (strcmp (s->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_BLUE) == 0) s->dev->gray_mode_color = 0x01; else if (strcmp (s->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_GREEN) == 0) s->dev->gray_mode_color = 0x02; else s->dev->gray_mode_color = 0x03; setup_scan_request (s, &scan_request); if (!s->first_scan && s->val[OPT_COARSE_CAL_ONCE].w == SANE_TRUE) s->auto_afe = SANE_FALSE; else s->auto_afe = s->val[OPT_COARSE_CAL].w; s->dev->gamma_value = s->val[OPT_GAMMA_VALUE].w; gamma_size = s->params.depth == 16 ? 65536 : 256; s->gamma_table = malloc (sizeof (SANE_Int) * gamma_size); if (!s->gamma_table) { DBG (1, "sane_start: couldn't malloc %d bytes for gamma table\n", gamma_size); return SANE_STATUS_NO_MEM; } for (i = 0; i < gamma_size; i++) { s->gamma_table[i] = (gamma_size - 1) * pow (((double) i + 1) / (gamma_size), 1.0 / SANE_UNFIX (s->dev->gamma_value)) + 0.5; if (s->gamma_table[i] > (gamma_size - 1)) s->gamma_table[i] = (gamma_size - 1); if (s->gamma_table[i] < 0) s->gamma_table[i] = 0; #if 0 printf ("%d %d\n", i, s->gamma_table[i]); #endif } if(!(s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)) { s->calib = s->val[OPT_QUALITY_CAL].w; } if (!(s->dev->model->flags & GT68XX_FLAG_NO_STOP)) RIE (gt68xx_device_stop_scan (s->dev)); if (!(s->dev->model->flags & GT68XX_FLAG_SHEET_FED)) RIE (gt68xx_device_carriage_home (s->dev)); gt68xx_scanner_wait_for_positioning (s); gettimeofday (&s->start_time, 0); if (s->val[OPT_BACKTRACK].w == SANE_TRUE) scan_request.backtrack = SANE_TRUE; else { if (s->val[OPT_RESOLUTION].w >= s->dev->model->ydpi_no_backtrack) scan_request.backtrack = SANE_FALSE; else scan_request.backtrack = SANE_TRUE; } if (scan_request.backtrack) scan_request.backtrack_lines = s->val[OPT_BACKTRACK_LINES].w; else scan_request.backtrack_lines = 0; /* don't call calibration for scanners that use sheetfed_calibrate */ if(!(s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE)) { RIE (gt68xx_scanner_calibrate (s, &scan_request)); } else { s->calib = s->calibrated; } /* is possible, wait for document to be inserted before scanning */ /* wait for 5 secondes max */ if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED && s->dev->model->command_set->document_present) { i=0; do { RIE(s->dev->model->command_set->document_present(s->dev,&document)); if(document==SANE_FALSE) { i++; sleep(1); } } while ((i<5) && (document==SANE_FALSE)); if(document==SANE_FALSE) { DBG (4, "sane_start: no doucment detected after %d s\n",i); return SANE_STATUS_NO_DOCS; } } /* some sheetfed scanners need a special operation to move * paper before starting real scan */ if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED) { RIE (gt68xx_sheetfed_move_to_scan_area (s, &scan_request)); } /* restore calibration */ if( (s->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE) &&(s->calibrated == SANE_TRUE)) { /* compute scan parameters */ scan_request.calculate = SANE_TRUE; gt68xx_device_setup_scan (s->dev, &scan_request, SA_SCAN, &scan_params); /* restore settings from calibration stored */ memcpy(s->dev->afe,&(s->afe_params), sizeof(GT68xx_AFE_Parameters)); RIE (gt68xx_assign_calibration (s, scan_params)); scan_request.calculate = SANE_FALSE; } /* send scan request to the scanner */ RIE (gt68xx_scanner_start_scan (s, &scan_request, &scan_params)); for (i = 0; i < scan_params.overscan_lines; ++i) RIE (gt68xx_scanner_read_line (s, buffer_pointers)); DBG (4, "sane_start: wanted: dpi=%d, x=%.1f, y=%.1f, width=%.1f, " "height=%.1f, color=%s\n", scan_request.xdpi, SANE_UNFIX (scan_request.x0), SANE_UNFIX (scan_request.y0), SANE_UNFIX (scan_request.xs), SANE_UNFIX (scan_request.ys), scan_request.color ? "color" : "gray"); s->line = 0; s->byte_count = s->reader->params.pixel_xs; s->total_bytes = 0; s->first_scan = SANE_FALSE; #ifdef DEBUG_BRIGHTNESS s->average_white = 0; s->max_white = 0; s->min_black = 255; #endif s->scanning = SANE_TRUE; DBG (5, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { GT68xx_Scanner *s = handle; SANE_Status status; static unsigned int *buffer_pointers[3]; SANE_Int inflate_x; SANE_Bool lineart; SANE_Int i, color, colors; if (!s) { DBG (1, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } if (!buf) { DBG (1, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (!len) { DBG (1, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } *len = 0; if (!s->scanning) { DBG (3, "sane_read: scan was cancelled, is over or has not been " "initiated yet\n"); return SANE_STATUS_CANCELLED; } DBG (5, "sane_read: start (line %d of %d, byte_count %d of %d)\n", s->line, s->reader->params.pixel_ys, s->byte_count, s->reader->params.pixel_xs); if (s->line >= s->reader->params.pixel_ys && s->byte_count >= s->reader->params.pixel_xs) { DBG (4, "sane_read: nothing more to scan: EOF\n"); return SANE_STATUS_EOF; } inflate_x = s->val[OPT_RESOLUTION].w / s->dev->model->optical_xdpi; if (inflate_x > 1) DBG (5, "sane_read: inflating x by factor %d\n", inflate_x); else inflate_x = 1; lineart = (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) ? SANE_TRUE : SANE_FALSE; if (s->reader->params.color) colors = 3; else colors = 1; while ((*len) < max_len) { if (s->byte_count >= s->reader->params.pixel_xs) { if (s->line >= s->reader->params.pixel_ys) { DBG (4, "sane_read: scan complete: %d bytes, %d total\n", *len, s->total_bytes); return SANE_STATUS_GOOD; } DBG (5, "sane_read: getting line %d of %d\n", s->line, s->reader->params.pixel_ys); RIE (gt68xx_scanner_read_line (s, buffer_pointers)); s->line++; s->byte_count = 0; /* Apply gamma */ for (color = 0; color < colors; color++) for (i = 0; i < s->reader->pixels_per_line; i++) { if (s->reader->params.depth > 8) buffer_pointers[color][i] = s->gamma_table[buffer_pointers[color][i]]; else buffer_pointers[color][i] = (s->gamma_table[buffer_pointers[color][i] >> 8] << 8) + (s->gamma_table[buffer_pointers[color][i] >> 8]); } /* mirror lines */ if (s->dev->model->flags & GT68XX_FLAG_MIRROR_X) { unsigned int swap; for (color = 0; color < colors; color++) { for (i = 0; i < s->reader->pixels_per_line / 2; i++) { swap = buffer_pointers[color][i]; buffer_pointers[color][i] = buffer_pointers[color][s->reader->pixels_per_line - 1 - i]; buffer_pointers[color][s->reader->pixels_per_line - 1 - i] = swap; } } } } if (lineart) { SANE_Int bit; SANE_Byte threshold = s->val[OPT_THRESHOLD].w; buf[*len] = 0; for (bit = 7; bit >= 0; bit--) { SANE_Byte is_black = (((buffer_pointers[0][s->byte_count] >> 8) & 0xff) > threshold) ? 0 : 1; buf[*len] |= (is_black << bit); if ((7 - bit) % inflate_x == (inflate_x - 1)) s->byte_count++; } } else if (s->reader->params.color) { /* color */ if (s->reader->params.depth > 8) { SANE_Int color = (s->total_bytes / 2) % 3; if ((s->total_bytes % 2) == 0) { if (little_endian) buf[*len] = buffer_pointers[color][s->byte_count] & 0xff; else buf[*len] = (buffer_pointers[color][s->byte_count] >> 8) & 0xff; } else { if (little_endian) buf[*len] = (buffer_pointers[color][s->byte_count] >> 8) & 0xff; else buf[*len] = buffer_pointers[color][s->byte_count] & 0xff; if (s->total_bytes % (inflate_x * 6) == (inflate_x * 6 - 1)) s->byte_count++; } } else { SANE_Int color = s->total_bytes % 3; buf[*len] = (buffer_pointers[color][s->byte_count] >> 8) & 0xff; if (s->total_bytes % (inflate_x * 3) == (inflate_x * 3 - 1)) s->byte_count++; #ifdef DEBUG_BRIGHTNESS s->average_white += buf[*len]; s->max_white = (buf[*len] > s->max_white) ? buf[*len] : s->max_white; s->min_black = (buf[*len] < s->min_black) ? buf[*len] : s->min_black; #endif } } else { /* gray */ if (s->reader->params.depth > 8) { if ((s->total_bytes % 2) == 0) { if (little_endian) buf[*len] = buffer_pointers[0][s->byte_count] & 0xff; else buf[*len] = (buffer_pointers[0][s->byte_count] >> 8) & 0xff; } else { if (little_endian) buf[*len] = (buffer_pointers[0][s->byte_count] >> 8) & 0xff; else buf[*len] = buffer_pointers[0][s->byte_count] & 0xff; if (s->total_bytes % (2 * inflate_x) == (2 * inflate_x - 1)) s->byte_count++; } } else { buf[*len] = (buffer_pointers[0][s->byte_count] >> 8) & 0xff; if (s->total_bytes % inflate_x == (inflate_x - 1)) s->byte_count++; } } (*len)++; s->total_bytes++; } DBG (4, "sane_read: exit (line %d of %d, byte_count %d of %d, %d bytes, " "%d total)\n", s->line, s->reader->params.pixel_ys, s->byte_count, s->reader->params.pixel_xs, *len, s->total_bytes); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { GT68xx_Scanner *s = handle; DBG (5, "sane_cancel: start\n"); if (s->scanning) { s->scanning = SANE_FALSE; if (s->total_bytes != (s->params.bytes_per_line * s->params.lines)) DBG (1, "sane_cancel: warning: scanned %d bytes, expected %d " "bytes\n", s->total_bytes, s->params.bytes_per_line * s->params.lines); else { struct timeval now; int secs; gettimeofday (&now, 0); secs = now.tv_sec - s->start_time.tv_sec; DBG (3, "sane_cancel: scan finished, scanned %d bytes in %d seconds\n", s->total_bytes, secs); #ifdef DEBUG_BRIGHTNESS DBG (1, "sane_cancel: average white: %d, max_white=%d, min_black=%d\n", s->average_white / s->total_bytes, s->max_white, s->min_black); #endif } /* some scanners don't like this command when cancelling a scan */ sanei_usb_set_timeout (SHORT_TIMEOUT); gt68xx_device_fix_descriptor (s->dev); gt68xx_scanner_stop_scan (s); sanei_usb_set_timeout (LONG_TIMEOUT); if (s->dev->model->flags & GT68XX_FLAG_SHEET_FED) { gt68xx_device_paperfeed (s->dev); } else { sanei_usb_set_timeout (SHORT_TIMEOUT); gt68xx_scanner_wait_for_positioning (s); sanei_usb_set_timeout (LONG_TIMEOUT); gt68xx_device_carriage_home (s->dev); } if (s->gamma_table) free (s->gamma_table); s->gamma_table = 0; } else { DBG (4, "sane_cancel: scan has not been initiated yet, " "or it is already aborted\n"); } DBG (5, "sane_cancel: exit\n"); return; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { GT68xx_Scanner *s = handle; DBG (5, "sane_set_io_mode: handle = %p, non_blocking = %s\n", handle, non_blocking == SANE_TRUE ? "true" : "false"); if (!s->scanning) { DBG (1, "sane_set_io_mode: not scanning\n"); return SANE_STATUS_INVAL; } if (non_blocking) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { GT68xx_Scanner *s = handle; DBG (5, "sane_get_select_fd: handle = %p, fd = %p\n", handle, (void *) fd); if (!s->scanning) { DBG (1, "sane_get_select_fd: not scanning\n"); return SANE_STATUS_INVAL; } return SANE_STATUS_UNSUPPORTED; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/gt68xx_gt6816.h0000664000175000017500000000526012112021330015135 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GT68XX_GT6816_H #define GT68XX_GT6816_H static SANE_Status gt6816_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded); static SANE_Status gt6816_download_firmware (GT68xx_Device * dev, SANE_Byte * data, SANE_Word size); static SANE_Status gt6816_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok); static SANE_Status gt6816_get_ta_status (GT68xx_Device * dev, SANE_Bool * ta_attached); static SANE_Status gt6816_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp, SANE_Bool ta_lamp); static SANE_Status gt6816_is_moving (GT68xx_Device * dev, SANE_Bool * moving); static SANE_Status gt6816_carriage_home (GT68xx_Device * dev); static SANE_Status gt6816_stop_scan (GT68xx_Device * dev); static SANE_Status gt6816_document_present (GT68xx_Device * dev, SANE_Bool * present); #endif /* not GT68XX_GT6816_H */ sane-backends-1.0.27/backend/microtek2.c0000664000175000017500000105225513106201017014655 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. microtek2.c This file (C) 1998, 1999 Bernd Schroeder modifications 2000, 2001 Karsten Festag This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for Microtek scanners with SCSI-2 command set. (feedback to: bernd@aquila.muc.de) ( karsten.festag@t-online.de) ***************************************************************************/ #ifdef _AIX # include /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include #include #include #include #include #include #include #include #include #include #include "../include/_stdint.h" #ifdef HAVE_AUTHORIZATION #include #endif #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_thread.h" #ifndef TESTBACKEND #define BACKEND_NAME microtek2 #else #define BACKEND_NAME microtek2_test #endif /* for testing*/ /*#define NO_PHANTOMTYPE_SHADING*/ #include "../include/sane/sanei_backend.h" #include "microtek2.h" #ifdef HAVE_AUTHORIZATION static SANE_Auth_Callback auth_callback; #endif static int md_num_devices = 0; /* number of devices from config file */ static Microtek2_Device *md_first_dev = NULL; /* list of known devices */ static Microtek2_Scanner *ms_first_handle = NULL; /* list of open scanners */ /* options that can be configured in the config file */ static Config_Options md_options = { 1.0, "off", "off", "off", "off", "off", "off"}; static Config_Temp *md_config_temp = NULL; static int md_dump = 0; /* from config file: */ /* 1: inquiry + scanner attributes */ /* 2: + all scsi commands and data */ /* 3: + all scan data */ static int md_dump_clear = 1; /*---------- sane_cancel() ---------------------------------------------------*/ void sane_cancel (SANE_Handle handle) { Microtek2_Scanner *ms = handle; DBG(30, "sane_cancel: handle=%p\n", handle); if ( ms->scanning == SANE_TRUE ) cleanup_scanner(ms); ms->cancelled = SANE_TRUE; ms->fd[0] = ms->fd[1] = -1; } /*---------- sane_close() ----------------------------------------------------*/ void sane_close (SANE_Handle handle) { Microtek2_Scanner *ms = handle; DBG(30, "sane_close: ms=%p\n", (void *) ms); if ( ! ms ) return; /* free malloc'ed stuff */ cleanup_scanner(ms); /* remove Scanner from linked list */ if ( ms_first_handle == ms ) ms_first_handle = ms->next; else { Microtek2_Scanner *ts = ms_first_handle; while ( (ts != NULL) && (ts->next != ms) ) ts = ts->next; ts->next = ts->next->next; /* == ms->next */ } DBG(100, "free ms at %p\n", (void *) ms); free((void *) ms); ms = NULL; } /*---------- sane_exit() -----------------------------------------------------*/ void sane_exit (void) { Microtek2_Device *next; int i; DBG(30, "sane_exit:\n"); /* close all leftover Scanners */ while (ms_first_handle != NULL) sane_close(ms_first_handle); /* free up device list */ while (md_first_dev != NULL) { next = md_first_dev->next; for ( i = 0; i < 4; i++ ) { if ( md_first_dev->custom_gamma_table[i] ) { DBG(100, "free md_first_dev->custom_gamma_table[%d] at %p\n", i, (void *) md_first_dev->custom_gamma_table[i]); free((void *) md_first_dev->custom_gamma_table[i]); md_first_dev->custom_gamma_table[i] = NULL; } } if ( md_first_dev->shading_table_w ) { DBG(100, "free md_first_dev->shading_table_w at %p\n", md_first_dev->shading_table_w); free((void *) md_first_dev->shading_table_w); md_first_dev->shading_table_w = NULL; } if ( md_first_dev->shading_table_d ) { DBG(100, "free md_first_dev->shading_table_d at %p\n", md_first_dev->shading_table_d); free((void *) md_first_dev->shading_table_d); md_first_dev->shading_table_d = NULL; } DBG(100, "free md_first_dev at %p\n", (void *) md_first_dev); free((void *) md_first_dev); md_first_dev = next; } sane_get_devices(NULL, SANE_FALSE); /* free list of SANE_Devices */ DBG(30, "sane_exit: MICROTEK2 says goodbye.\n"); } /*---------- sane_get_devices()-----------------------------------------------*/ SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only) { /* return a list of available devices; available here means that we get */ /* a positive response to an 'INQUIRY' and possibly to a */ /* 'READ SCANNER ATTRIBUTE' call */ static const SANE_Device **sd_list = NULL; Microtek2_Device *md; SANE_Status status; int index; DBG(30, "sane_get_devices: local_only=%d\n", local_only); /* this is hack to get the list freed with a call from sane_exit() */ if ( device_list == NULL ) { if ( sd_list ) { DBG(100, "free sd_list at %p\n", (void *) sd_list); free(sd_list); sd_list=NULL; } DBG(30, "sane_get_devices: sd_list_freed\n"); return SANE_STATUS_GOOD; } /* first free old list, if there is one; frontend wants a new list */ if ( sd_list ) { DBG(100, "free sd_list at %p\n", (void *) sd_list); free(sd_list); /* free array of pointers */ } sd_list = (const SANE_Device **) malloc( (md_num_devices + 1) * sizeof(SANE_Device **)); DBG(100, "sane_get_devices: sd_list=%p, malloc'd %lu bytes\n", (void *) sd_list, (u_long) ((md_num_devices + 1) * sizeof(SANE_Device **))); if ( ! sd_list ) { DBG(1, "sane_get_devices: malloc() for sd_list failed\n"); return SANE_STATUS_NO_MEM; } *device_list = sd_list; index = 0; md = md_first_dev; while ( md ) { status = attach(md); if ( status != SANE_STATUS_GOOD ) { DBG(10, "sane_get_devices: attach status '%s'\n", sane_strstatus(status)); md = md->next; continue; } /* check whether unit is ready, if so add it to the list */ status = scsi_test_unit_ready(md); if ( status != SANE_STATUS_GOOD ) { DBG(10, "sane_get_devices: test_unit_ready status '%s'\n", sane_strstatus(status)); md = md->next; continue; } sd_list[index] = &md->sane; ++index; md = md->next; } sd_list[index] = NULL; return SANE_STATUS_GOOD; } /*---------- sane_get_parameters() -------------------------------------------*/ SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters *params) { Microtek2_Scanner *ms = handle; Microtek2_Device *md; Option_Value *val; Microtek2_Info *mi; int mode; int depth; int bits_pp_in; /* bits per pixel from scanner */ int bits_pp_out; /* bits_per_pixel transferred to frontend */ int bytes_per_line; double x_pixel_per_mm; double y_pixel_per_mm; double x1_pixel; double y1_pixel; double width_pixel; double height_pixel; DBG(40, "sane_get_parameters: handle=%p, params=%p\n", handle, (void *) params); md = ms->dev; mi = &md->info[md->scan_source]; val= ms->val; if ( ! ms->scanning ) /* get an estimate for the params */ { get_scan_mode_and_depth(ms, &mode, &depth, &bits_pp_in, &bits_pp_out); switch ( mode ) { case MS_MODE_COLOR: if ( mi->onepass ) { ms->params.format = SANE_FRAME_RGB; ms->params.last_frame = SANE_TRUE; } else { ms->params.format = SANE_FRAME_RED; ms->params.last_frame = SANE_FALSE; } break; case MS_MODE_GRAY: case MS_MODE_HALFTONE: case MS_MODE_LINEART: case MS_MODE_LINEARTFAKE: ms->params.format = SANE_FRAME_GRAY; ms->params.last_frame = SANE_TRUE; break; default: DBG(1, "sane_get_parameters: Unknown scan mode %d\n", mode); break; } ms->params.depth = (SANE_Int) bits_pp_out; /* calculate lines, pixels per line and bytes per line */ if ( val[OPT_RESOLUTION_BIND].w == SANE_TRUE ) { x_pixel_per_mm = y_pixel_per_mm = SANE_UNFIX(val[OPT_RESOLUTION].w) / MM_PER_INCH; DBG(30, "sane_get_parameters: x_res=y_res=%f\n", SANE_UNFIX(val[OPT_RESOLUTION].w)); } else { x_pixel_per_mm = SANE_UNFIX(val[OPT_RESOLUTION].w) / MM_PER_INCH; y_pixel_per_mm = SANE_UNFIX(val[OPT_Y_RESOLUTION].w) / MM_PER_INCH; DBG(30, "sane_get_parameters: x_res=%f, y_res=%f\n", SANE_UNFIX(val[OPT_RESOLUTION].w), SANE_UNFIX(val[OPT_Y_RESOLUTION].w)); } DBG(30, "sane_get_parameters: x_ppm=%f, y_ppm=%f\n", x_pixel_per_mm, y_pixel_per_mm); y1_pixel = SANE_UNFIX(ms->val[OPT_TL_Y].w) * y_pixel_per_mm; height_pixel = fabs(SANE_UNFIX(ms->val[OPT_BR_Y].w) * y_pixel_per_mm - y1_pixel) + 0.5; ms->params.lines = (SANE_Int) height_pixel; x1_pixel = SANE_UNFIX(ms->val[OPT_TL_X].w) * x_pixel_per_mm; width_pixel = fabs(SANE_UNFIX(ms->val[OPT_BR_X].w) * x_pixel_per_mm - x1_pixel) + 0.5; ms->params.pixels_per_line = (SANE_Int) width_pixel; if ( bits_pp_out == 1 ) bytes_per_line = (width_pixel + 7 ) / 8; else { bytes_per_line = ( width_pixel * bits_pp_out ) / 8 ; if ( mode == MS_MODE_COLOR && mi->onepass ) bytes_per_line *= 3; } ms->params.bytes_per_line = (SANE_Int) bytes_per_line; } /* if ms->scanning */ if ( params ) *params = ms->params; DBG(30,"sane_get_parameters: format=%d, last_frame=%d, lines=%d\n", ms->params.format,ms->params.last_frame, ms->params.lines); DBG(30,"sane_get_parameters: depth=%d, ppl=%d, bpl=%d\n", ms->params.depth,ms->params.pixels_per_line, ms->params.bytes_per_line); return SANE_STATUS_GOOD; } /*---------- sane_get_select_fd() --------------------------------------------*/ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int *fd) { Microtek2_Scanner *ms = handle; DBG(30, "sane_get_select_fd: ms=%p\n", (void *) ms); if ( ! ms->scanning ) { DBG(1, "sane_get_select_fd: Scanner not scanning\n"); return SANE_STATUS_INVAL; } *fd = (SANE_Int) ms->fd[0]; return SANE_STATUS_GOOD; } /*---------- sane_init() -----------------------------------------------------*/ SANE_Status #ifdef HAVE_AUTHORIZATION sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) #else sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) #endif { Microtek2_Device *md; FILE *fp; DBG_INIT(); DBG(1, "sane_init: Microtek2 (v%d.%d build %s) says hello...\n", MICROTEK2_MAJOR, MICROTEK2_MINOR, MICROTEK2_BUILD); if ( version_code ) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, 0); #ifdef HAVE_AUTHORIZATION auth_callback = authorize; #endif sanei_thread_init(); fp = sanei_config_open(MICROTEK2_CONFIG_FILE); if ( fp == NULL ) DBG(10, "sane_init: file not opened: '%s'\n", MICROTEK2_CONFIG_FILE); else { /* check config file for devices and associated options */ parse_config_file(fp, &md_config_temp); while ( md_config_temp ) { sanei_config_attach_matching_devices(md_config_temp->device, attach_one); if ( md_config_temp->next ) /* go to next device, if existent */ md_config_temp = md_config_temp->next; else break; } fclose(fp); } if ( md_first_dev == NULL ) { /* config file not found or no valid entry; default to /dev/scanner */ /* instead of insisting on config file */ add_device_list("/dev/scanner", &md); if ( md ) attach(md); } return SANE_STATUS_GOOD; } /*---------- sane_open() -----------------------------------------------------*/ SANE_Status sane_open(SANE_String_Const name, SANE_Handle *handle) { SANE_Status status; Microtek2_Scanner *ms; Microtek2_Device *md; #ifdef HAVE_AUTHORIZATION struct stat st; int rc; #endif DBG(30, "sane_open: device='%s'\n", name); *handle = NULL; md = md_first_dev; if ( name ) { /* add_device_list() returns a pointer to the device struct if */ /* the device is known or newly added, else it returns NULL */ status = add_device_list(name, &md); if ( status != SANE_STATUS_GOOD ) return status; } if ( ! md ) { DBG(10, "sane_open: invalid device name '%s'\n", name); return SANE_STATUS_INVAL; } /* attach calls INQUIRY and READ SCANNER ATTRIBUTES */ status = attach(md); if ( status != SANE_STATUS_GOOD ) return status; ms = malloc(sizeof(Microtek2_Scanner)); DBG(100, "sane_open: ms=%p, malloc'd %lu bytes\n", (void *) ms, (u_long) sizeof(Microtek2_Scanner)); if ( ms == NULL ) { DBG(1, "sane_open: malloc() for ms failed\n"); return SANE_STATUS_NO_MEM; } memset(ms, 0, sizeof(Microtek2_Scanner)); ms->dev = md; ms->scanning = SANE_FALSE; ms->cancelled = SANE_FALSE; ms->current_pass = 0; ms->sfd = -1; ms->pid = -1; ms->fp = NULL; ms->gamma_table = NULL; ms->buf.src_buf = ms->buf.src_buffer[0] = ms->buf.src_buffer[1] = NULL; ms->control_bytes = NULL; ms->shading_image = NULL; ms->condensed_shading_w = NULL; ms->condensed_shading_d = NULL; ms->current_color = MS_COLOR_ALL; ms->current_read_color = MS_COLOR_RED; init_options(ms, MD_SOURCE_FLATBED); /* insert scanner into linked list */ ms->next = ms_first_handle; ms_first_handle = ms; *handle = ms; #ifdef HAVE_AUTHORIZATION /* check whether the file with the passwords exists. If it doesnt */ /* exist, we dont use any authorization */ rc = stat(PASSWD_FILE, &st); if ( rc == -1 && errno == ENOENT ) return SANE_STATUS_GOOD; else { status = do_authorization(md->name); return status; } #else return SANE_STATUS_GOOD; #endif } /*---------- sane_read() -----------------------------------------------------*/ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len ) { Microtek2_Scanner *ms = handle; SANE_Status status; ssize_t nread; DBG(30, "sane_read: handle=%p, buf=%p, maxlen=%d\n", handle, buf, maxlen); *len = 0; if ( ! ms->scanning || ms->cancelled ) { if ( ms->cancelled ) { status = SANE_STATUS_CANCELLED; } else { DBG(15, "sane_read: Scanner %p not scanning\n", (void *) ms); status = SANE_STATUS_IO_ERROR; } DBG(15, "sane_read: scan cancelled or scanner not scanning->cleanup\n"); cleanup_scanner(ms); return status; } nread = read(ms->fd[0], (void *) buf, (int) maxlen); if ( nread == -1 ) { if ( errno == EAGAIN ) { DBG(30, "sane_read: currently no data available\n"); return SANE_STATUS_GOOD; } else { DBG(1, "sane_read: read() failed, errno=%d\n", errno); cleanup_scanner(ms); return SANE_STATUS_IO_ERROR; } } if ( nread == 0 ) { DBG(15, "sane_read: read 0 bytes -> EOF\n"); ms->scanning = SANE_FALSE; cleanup_scanner(ms); return SANE_STATUS_EOF; } *len = (SANE_Int) nread; DBG(30, "sane_read: *len=%d\n", *len); return SANE_STATUS_GOOD; } /*---------- sane_set_io_mode() ---------------------------------------------*/ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Microtek2_Scanner *ms = handle; int rc; DBG(30, "sane_set_io_mode: handle=%p, nonblocking=%d\n", handle, non_blocking); if ( ! ms->scanning ) { DBG(1, "sane_set_io_mode: Scanner not scanning\n"); return SANE_STATUS_INVAL; } rc = fcntl(ms->fd[0], F_SETFL, non_blocking ? O_NONBLOCK : 0); if ( rc == -1 ) { DBG(1, "sane_set_io_mode: fcntl() failed\n"); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /*---------- add_device_list() -----------------------------------------------*/ static SANE_Status add_device_list(SANE_String_Const dev_name, Microtek2_Device **mdev) { Microtek2_Device *md; SANE_String hdev; size_t len; if ( (hdev = strdup(dev_name)) == NULL) { DBG(5, "add_device_list: malloc() for hdev failed\n"); return SANE_STATUS_NO_MEM; } len = strlen(hdev); if ( hdev[len - 1] == '\n' ) hdev[--len] = '\0'; DBG(30, "add_device_list: device='%s'\n", hdev); /* check, if device is already known */ md = md_first_dev; while ( md ) { if ( strcmp(hdev, md->name) == 0 ) { DBG(30, "add_device_list: device '%s' already in list\n", hdev); *mdev = md; return SANE_STATUS_GOOD; } md = md->next; } md = (Microtek2_Device *) malloc(sizeof(Microtek2_Device)); DBG(100, "add_device_list: md=%p, malloc'd %lu bytes\n", (void *) md, (u_long) sizeof(Microtek2_Device)); if ( md == NULL ) { DBG(1, "add_device_list: malloc() for md failed\n"); return SANE_STATUS_NO_MEM; } /* initialize Device and add it at the beginning of the list */ memset(md, 0, sizeof(Microtek2_Device)); md->next = md_first_dev; md_first_dev = md; md->sane.name = NULL; md->sane.vendor = NULL; md->sane.model = NULL; md->sane.type = NULL; md->scan_source = MD_SOURCE_FLATBED; md->shading_table_w = NULL; md->shading_table_d = NULL; strncpy(md->name, hdev, PATH_MAX - 1); if ( md_config_temp ) md->opts = md_config_temp->opts; else md->opts = md_options; ++md_num_devices; *mdev = md; DBG(100, "free hdev at %p\n", hdev); free(hdev); return SANE_STATUS_GOOD; } /*---------- attach() --------------------------------------------------------*/ static SANE_Status attach(Microtek2_Device *md) { /* This function is called from sane_init() to do the inquiry and to read */ /* the scanner attributes. If one of these calls fails, or if a new */ /* device is passed in sane_open() this function may also be called */ /* from sane_open() or sane_get_devices(). */ SANE_String model_string; SANE_Status status; SANE_Byte source_info; DBG(30, "attach: device='%s'\n", md->name); status = scsi_inquiry( &md->info[MD_SOURCE_FLATBED], md->name ); if ( status != SANE_STATUS_GOOD ) { DBG(1, "attach: '%s'\n", sane_strstatus(status)); return status; } /* We copy the inquiry info into the info structures for each scansource */ /* like ADF, TMA, STRIPE and SLIDE */ for ( source_info = 1; source_info < 5; ++source_info ) memcpy( &md->info[source_info], &md->info[MD_SOURCE_FLATBED], sizeof( Microtek2_Info ) ); /* Here we should insert a function, that stores all the relevant */ /* information in the info structure in a more conveniant format */ /* in the device structure, e.g. the model name with a trailing '\0'. */ status = check_inquiry(md, &model_string); if ( status != SANE_STATUS_GOOD ) return status; md->sane.name = md->name; md->sane.vendor = "Microtek"; md->sane.model = strdup(model_string); if ( md->sane.model == NULL ) DBG(1, "attach: strdup for model string failed\n"); md->sane.type = "flatbed scanner"; md->revision = strtod(md->info[MD_SOURCE_FLATBED].revision, NULL); status = scsi_read_attributes(&md->info[0], md->name, MD_SOURCE_FLATBED); if ( status != SANE_STATUS_GOOD ) { DBG(1, "attach: '%s'\n", sane_strstatus(status)); return status; } if ( MI_LUTCAP_NONE( md->info[MD_SOURCE_FLATBED].lut_cap) ) /* no gamma tables */ md->model_flags |= MD_NO_GAMMA; /* check whether the device supports transparency media adapters */ if ( md->info[MD_SOURCE_FLATBED].option_device & MI_OPTDEV_TMA ) { status = scsi_read_attributes(&md->info[0], md->name, MD_SOURCE_TMA); if ( status != SANE_STATUS_GOOD ) return status; } /* check whether the device supports an ADF */ if ( md->info[MD_SOURCE_FLATBED].option_device & MI_OPTDEV_ADF ) { status = scsi_read_attributes(&md->info[0], md->name, MD_SOURCE_ADF); if ( status != SANE_STATUS_GOOD ) return status; } /* check whether the device supports STRIPES */ if ( md->info[MD_SOURCE_FLATBED].option_device & MI_OPTDEV_STRIPE ) { status = scsi_read_attributes(&md->info[0], md->name, MD_SOURCE_STRIPE); if ( status != SANE_STATUS_GOOD ) return status; } /* check whether the device supports SLIDES */ if ( md->info[MD_SOURCE_FLATBED].option_device & MI_OPTDEV_SLIDE ) { /* The Phantom 636cx indicates in its attributes that it supports */ /* slides, but it doesn't. Thus this command would fail. */ if ( ! (md->model_flags & MD_NO_SLIDE_MODE) ) { status = scsi_read_attributes(&md->info[0], md->name, MD_SOURCE_SLIDE); if ( status != SANE_STATUS_GOOD ) return status; } } status = scsi_read_system_status(md, -1); if ( status != SANE_STATUS_GOOD ) return status; return SANE_STATUS_GOOD; } /*---------- attach_one() ----------------------------------------------------*/ static SANE_Status attach_one (const char *name) { Microtek2_Device *md; Microtek2_Device *md_tmp; DBG(30, "attach_one: name='%s'\n", name); md_tmp = md_first_dev; /* if add_device_list() adds an entry it does this at the beginning */ /* of the list and thus changes md_first_dev */ add_device_list(name, &md); if ( md_tmp != md_first_dev ) attach(md); return SANE_STATUS_GOOD; } /*---------- cancel_scan() ---------------------------------------------------*/ static SANE_Status cancel_scan(Microtek2_Scanner *ms) { SANE_Status status; DBG(30, "cancel_scan: ms=%p\n", (void *) ms); /* READ IMAGE with a transferlength of 0 aborts a scan */ ms->transfer_length = 0; status = scsi_read_image(ms, (uint8_t *) NULL, 1); if ( status != SANE_STATUS_GOOD ) { DBG(1, "cancel_scan: cancel failed: '%s'\n", sane_strstatus(status)); status = SANE_STATUS_IO_ERROR; } else status = SANE_STATUS_CANCELLED; close(ms->fd[1]); /* if we are aborting a scan because, for example, we run out of material on a feeder, then pid may be already -1 and kill(-1, SIGTERM), i.e. killing all our processes, is not likely what we really want - --mj, 2001/Nov/19 */ if (sanei_thread_is_valid (ms->pid)) { sanei_thread_kill(ms->pid); sanei_thread_waitpid(ms->pid, NULL); } return status; } /*---------- check_option() --------------------------------------------------*/ static void check_option(const char *cp, Config_Options *co) { /* This function analyses options in the config file */ char *endptr; /* When this function is called, it is already made sure that this */ /* is an option line, i.e. a line that starts with option */ cp = sanei_config_skip_whitespace(cp); /* skip blanks */ cp = sanei_config_skip_whitespace(cp + 6); /* skip "option" */ if ( strncmp(cp, "dump", 4) == 0 && isspace(cp[4]) ) { cp = sanei_config_skip_whitespace(cp + 4); if ( *cp ) { md_dump = (int) strtol(cp, &endptr, 10); if ( md_dump > 4 || md_dump < 0 ) { md_dump = 1; DBG(30, "check_option: setting dump to %d\n", md_dump); } cp = sanei_config_skip_whitespace(endptr); if ( *cp ) { /* something behind the option value or value wrong */ md_dump = 1; DBG(30, "check_option: option value wrong\n"); } } else { DBG(30, "check_option: missing option value\n"); /* reasonable fallback */ md_dump = 1; } } else if ( strncmp(cp, "strip-height", 12) == 0 && isspace(cp[12]) ) { cp = sanei_config_skip_whitespace(cp + 12); if ( *cp ) { co->strip_height = strtod(cp, &endptr); DBG(30, "check_option: setting strip_height to %f\n", co->strip_height); if ( co->strip_height <= 0.0 ) co->strip_height = 14.0; cp = sanei_config_skip_whitespace(endptr); if ( *cp ) { /* something behind the option value or value wrong */ co->strip_height = 14.0; DBG(30, "check_option: option value wrong: %f\n", co->strip_height); } } } else if ( strncmp(cp, "no-backtrack-option", 19) == 0 && isspace(cp[19]) ) { cp = sanei_config_skip_whitespace(cp + 19); if ( strncmp(cp, "on", 2) == 0 ) { cp = sanei_config_skip_whitespace(cp + 2); co->no_backtracking = "on"; } else if ( strncmp(cp, "off", 3) == 0 ) { cp = sanei_config_skip_whitespace(cp + 3); co->no_backtracking = "off"; } else co->no_backtracking = "off"; if ( *cp ) { /* something behind the option value or value wrong */ co->no_backtracking = "off"; DBG(30, "check_option: option value wrong: %s\n", cp); } } else if ( strncmp(cp, "lightlid-35", 11) == 0 && isspace(cp[11]) ) { cp = sanei_config_skip_whitespace(cp + 11); if ( strncmp(cp, "on", 2) == 0 ) { cp = sanei_config_skip_whitespace(cp + 2); co->lightlid35 = "on"; } else if ( strncmp(cp, "off", 3) == 0 ) { cp = sanei_config_skip_whitespace(cp + 3); co->lightlid35 = "off"; } else co->lightlid35 = "off"; if ( *cp ) { /* something behind the option value or value wrong */ co->lightlid35 = "off"; DBG(30, "check_option: option value wrong: %s\n", cp); } } else if ( strncmp(cp, "toggle-lamp", 11) == 0 && isspace(cp[11]) ) { cp = sanei_config_skip_whitespace(cp + 11); if ( strncmp(cp, "on", 2) == 0 ) { cp = sanei_config_skip_whitespace(cp + 2); co->toggle_lamp = "on"; } else if ( strncmp(cp, "off", 3) == 0 ) { cp = sanei_config_skip_whitespace(cp + 3); co->toggle_lamp = "off"; } else co->toggle_lamp = "off"; if ( *cp ) { /* something behind the option value or value wrong */ co->toggle_lamp = "off"; DBG(30, "check_option: option value wrong: %s\n", cp); } } else if ( strncmp(cp, "lineart-autoadjust", 18) == 0 && isspace(cp[18]) ) { cp = sanei_config_skip_whitespace(cp + 18); if ( strncmp(cp, "on", 2) == 0 ) { cp = sanei_config_skip_whitespace(cp + 2); co->auto_adjust = "on"; } else if ( strncmp(cp, "off", 3) == 0 ) { cp = sanei_config_skip_whitespace(cp + 3); co->auto_adjust = "off"; } else co->auto_adjust = "off"; if ( *cp ) { /* something behind the option value or value wrong */ co->auto_adjust = "off"; DBG(30, "check_option: option value wrong: %s\n", cp); } } else if ( strncmp(cp, "backend-calibration", 19) == 0 && isspace(cp[19]) ) { cp = sanei_config_skip_whitespace(cp + 19); if ( strncmp(cp, "on", 2) == 0 ) { cp = sanei_config_skip_whitespace(cp + 2); co->backend_calibration = "on"; } else if ( strncmp(cp, "off", 3) == 0 ) { cp = sanei_config_skip_whitespace(cp + 3); co->backend_calibration = "off"; } else co->backend_calibration = "off"; if ( *cp ) { /* something behind the option value or value wrong */ co->backend_calibration = "off"; DBG(30, "check_option: option value wrong: %s\n", cp); } } else if ( strncmp(cp, "colorbalance-adjust", 19) == 0 && isspace(cp[19]) ) { cp = sanei_config_skip_whitespace(cp + 19); if ( strncmp(cp, "on", 2) == 0 ) { cp = sanei_config_skip_whitespace(cp + 2); co->colorbalance_adjust = "on"; } else if ( strncmp(cp, "off", 3) == 0 ) { cp = sanei_config_skip_whitespace(cp + 3); co->colorbalance_adjust = "off"; } else co->colorbalance_adjust = "off"; if ( *cp ) { /* something behind the option value or value wrong */ co->colorbalance_adjust = "off"; DBG(30, "check_option: option value wrong: %s\n", cp); } } else DBG(30, "check_option: invalid option in '%s'\n", cp); } /*---------- check_inquiry() -------------------------------------------------*/ static SANE_Status check_inquiry(Microtek2_Device *md, SANE_String *model_string) { Microtek2_Info *mi; DBG(30, "check_inquiry: md=%p\n", (void *) md); md->n_control_bytes = 0; md->shading_length = 0; md->shading_table_contents = 0; mi = &md->info[MD_SOURCE_FLATBED]; if ( mi->scsi_version != MI_SCSI_II_VERSION ) { DBG(1, "check_inquiry: Device is not a SCSI-II device, but 0x%02x\n", mi->scsi_version); return SANE_STATUS_IO_ERROR; } if ( mi->device_type != MI_DEVTYPE_SCANNER ) { DBG(1, "check_inquiry: Device is not a scanner, but 0x%02x\n", mi->device_type); return SANE_STATUS_IO_ERROR; } if ( strncasecmp("MICROTEK", mi->vendor, INQ_VENDOR_L) != 0 && strncmp(" ", mi->vendor, INQ_VENDOR_L) != 0 && strncmp("AGFA ", mi->vendor, INQ_VENDOR_L) != 0 ) { DBG(1, "check_inquiry: Device is not a Microtek, but '%.*s'\n", INQ_VENDOR_L, mi->vendor); return SANE_STATUS_IO_ERROR; } if ( mi->depth & MI_HASDEPTH_16 ) md->shading_depth = 16; else if ( mi->depth & MI_HASDEPTH_14 ) md->shading_depth = 14; else if ( mi->depth & MI_HASDEPTH_12 ) md->shading_depth = 12; else if ( mi->depth & MI_HASDEPTH_10 ) md->shading_depth = 10; else md->shading_depth = 8; switch (mi->model_code) { case 0x81: case 0xab: *model_string = "ScanMaker 4"; break; case 0x85: *model_string = "ScanMaker V300 / ColorPage-EP"; /* The ScanMaker V300 (FW < 2.70) returns some values for the */ /* "read image info" command in only two bytes */ /* and doesn't understand read_image_status */ md->model_flags |= MD_NO_RIS_COMMAND; if ( md->revision < 2.70 ) md->model_flags |= MD_RII_TWO_BYTES; break; case 0x87: *model_string = "ScanMaker 5"; md->model_flags |= MD_NO_GAMMA; break; case 0x89: *model_string = "ScanMaker 6400XL"; break; case 0x8a: *model_string = "ScanMaker 9600XL"; break; case 0x8c: *model_string = "ScanMaker 630 / ScanMaker V600"; break; case 0x8d: *model_string = "ScanMaker 336 / ScanMaker V310"; break; case 0x90: case 0x92: *model_string = "E3+ / Vobis HighScan"; break; case 0x91: *model_string = "ScanMaker X6 / Phantom 636"; /* The X6 indicates a data format of segregated data in TMA mode */ /* but actually transfers as chunky data */ md->model_flags |= MD_DATA_FORMAT_WRONG; if ( md->revision == 1.00 ) md->model_flags |= MD_OFFSET_2; break; case 0x93: *model_string = "ScanMaker 336 / ScanMaker V310"; break; case 0x70: case 0x71: case 0x94: case 0xa0: *model_string = "Phantom 330cx / Phantom 336cx / SlimScan C3"; /* These models do not accept gamma tables. Apparently they */ /* read the control bits and do not accept shading tables */ /* They also don't support enhancements (contrast, brightness...)*/ md->model_flags |= MD_NO_SLIDE_MODE | MD_NO_GAMMA #ifndef NO_PHANTOMTYPE_SHADING | MD_PHANTOM336CX_TYPE_SHADING #endif | MD_READ_CONTROL_BIT | MD_NO_ENHANCEMENTS; md->opt_backend_calib_default = SANE_TRUE; md->opt_no_backtrack_default = SANE_TRUE; md->n_control_bytes = 320; md->shading_length = 18; md->shading_depth = 10; md->controlbit_offset = 7; break; case 0x95: *model_string = "ArtixScan 1010"; break; case 0x97: *model_string = "ScanMaker 636"; break; case 0x98: *model_string = "ScanMaker X6EL"; if ( md->revision == 1.00 ) md->model_flags |= MD_OFFSET_2; break; case 0x99: *model_string = "ScanMaker X6USB"; if ( md->revision == 1.00 ) md->model_flags |= MD_OFFSET_2; md->model_flags |= MD_X6_SHORT_TRANSFER; break; case 0x9a: *model_string = "Phantom 636cx / C6"; /* The Phantom 636cx says it supports the SLIDE mode, but it */ /* doesn't. Thus inquring the attributes for slide mode would */ /* fail. Also it does not accept gamma tables. Apparently */ /* it reads the control bits and does not accept shading tables */ md->model_flags |= MD_NO_SLIDE_MODE | MD_READ_CONTROL_BIT | MD_NO_GAMMA | MD_PHANTOM_C6; md->opt_backend_calib_default = SANE_TRUE; md->opt_no_backtrack_default = SANE_TRUE; md->n_control_bytes = 647; /* md->shading_length = 18; firmware values seem to work better */ md->shading_depth = 12; md->controlbit_offset = 18; break; case 0x9d: *model_string = "AGFA Duoscan T1200"; break; case 0xa3: *model_string = "ScanMaker V6USL"; /* The V6USL does not accept gamma tables */ md->model_flags |= MD_NO_GAMMA; break; case 0xa5: *model_string = "ArtixScan 4000t"; break; case 0xac: *model_string = "ScanMaker V6UL"; /* The V6USL does not accept gamma tables, perhaps the V6UL also */ md->model_flags |= MD_NO_GAMMA; break; case 0xaf: *model_string = "SlimScan C3"; md->model_flags |= MD_NO_SLIDE_MODE | MD_NO_GAMMA | MD_READ_CONTROL_BIT | MD_NO_ENHANCEMENTS; md->opt_backend_calib_default = SANE_TRUE; md->opt_no_backtrack_default = SANE_TRUE; md->n_control_bytes = 320; md->controlbit_offset = 7; break; case 0xb0: *model_string = "ScanMaker X12USL"; md->opt_backend_calib_default = SANE_TRUE; md->model_flags |= MD_16BIT_TRANSFER | MD_CALIB_DIVISOR_600; break; case 0xb3: *model_string = "ScanMaker 3600"; break; case 0xb4: *model_string = "ScanMaker 4700"; break; case 0xb6: *model_string = "ScanMaker V6UPL"; /* is like V6USL but with USB and Parport interface ?? */ md->model_flags |= MD_NO_GAMMA; break; case 0xb8: *model_string = "ScanMaker 3700"; break; case 0xde: *model_string = "ScanMaker 9800XL"; md->model_flags |= MD_NO_GAMMA | MD_16BIT_TRANSFER; md->opt_backend_calib_default = SANE_TRUE; md->opt_no_backtrack_default = SANE_TRUE; break; default: DBG(1, "check_inquiry: Model 0x%02x not supported\n", mi->model_code); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /*---------- cleanup_scanner() -----------------------------------------------*/ static void cleanup_scanner(Microtek2_Scanner *ms) { DBG(30, "cleanup_scanner: ms=%p, ms->sfd=%d\n", (void *) ms, ms->sfd); if ( ms->scanning == SANE_TRUE ) cancel_scan(ms); if ( ms->sfd != -1 ) sanei_scsi_close(ms->sfd); ms->sfd = -1; ms->pid = -1; ms->fp = NULL; ms->current_pass = 0; ms->scanning = SANE_FALSE; ms->cancelled = SANE_FALSE; /* free buffers */ if ( ms->buf.src_buffer[0] ) { DBG(100, "free ms->buf.src_buffer[0] at %p\n", ms->buf.src_buffer[0]); free((void *) ms->buf.src_buffer[0]); ms->buf.src_buffer[0] = NULL; ms->buf.src_buf = NULL; } if ( ms->buf.src_buffer[1] ) { DBG(100, "free ms->buf.src_buffer[1] at %p\n", ms->buf.src_buffer[1]); free((void *) ms->buf.src_buffer[1]); ms->buf.src_buffer[1] = NULL; ms->buf.src_buf = NULL; } if ( ms->buf.src_buf ) { DBG(100, "free ms->buf.src_buf at %p\n", ms->buf.src_buf); free((void *) ms->buf.src_buf); ms->buf.src_buf = NULL; } if ( ms->temporary_buffer ) { DBG(100, "free ms->temporary_buffer at %p\n", ms->temporary_buffer); free((void *) ms->temporary_buffer); ms->temporary_buffer = NULL; } if ( ms->gamma_table ) { DBG(100, "free ms->gamma_table at %p\n", ms->gamma_table); free((void *) ms->gamma_table); ms->gamma_table = NULL; } if ( ms->control_bytes ) { DBG(100, "free ms->control_bytes at %p\n", ms->control_bytes); free((void *) ms->control_bytes); ms->control_bytes = NULL; } if ( ms->condensed_shading_w ) { DBG(100, "free ms->condensed_shading_w at %p\n", ms->condensed_shading_w); free((void *) ms->condensed_shading_w); ms->condensed_shading_w = NULL; } if ( ms->condensed_shading_d ) { DBG(100, "free ms->condensed_shading_d at %p\n", ms->condensed_shading_d); free((void *) ms->condensed_shading_d); ms->condensed_shading_d = NULL; } return; } #ifdef HAVE_AUTHORIZATION /*---------- do_authorization() ----------------------------------------------*/ static SANE_Status do_authorization(char *ressource) { /* This function implements a simple authorization function. It looks */ /* up an entry in the file SANE_PATH_CONFIG_DIR/auth. Such an entry */ /* must be of the form device:user:password where password is a crypt() */ /* encrypted password. If several users are allowed to access a device */ /* an entry must be created for each user. If no entry exists for device */ /* or the file does not exist no authentication is neccessary. If the */ /* file exists, but cant be opened the authentication fails */ SANE_Status status; FILE *fp; int device_found; char username[SANE_MAX_USERNAME_LEN]; char password[SANE_MAX_PASSWORD_LEN]; char line[MAX_LINE_LEN]; char *linep; char *device; char *user; char *passwd; char *p; DBG(30, "do_authorization: ressource=%s\n", ressource); if ( auth_callback == NULL ) /* frontend does not require authorization */ return SANE_STATUS_GOOD; /* first check if an entry exists in for this device. If not, we dont */ /* use authorization */ fp = fopen(PASSWD_FILE, "r"); if ( fp == NULL ) { if ( errno == ENOENT ) { DBG(1, "do_authorization: file not found: %s\n", PASSWD_FILE); return SANE_STATUS_GOOD; } else { DBG(1, "do_authorization: fopen() failed, errno=%d\n", errno); return SANE_STATUS_ACCESS_DENIED; } } linep = &line[0]; device_found = 0; while ( fgets(line, MAX_LINE_LEN, fp) ) { p = index(linep, SEPARATOR); if ( p ) { *p = '\0'; device = linep; if ( strcmp(device, ressource) == 0 ) { DBG(2, "equal\n"); device_found = 1; break; } } } if ( ! device_found ) { fclose(fp); return SANE_STATUS_GOOD; } fseek(fp, 0L, SEEK_SET); (*auth_callback) (ressource, username, password); status = SANE_STATUS_ACCESS_DENIED; do { fgets(line, MAX_LINE_LEN, fp); if ( ! ferror(fp) && ! feof(fp) ) { /* neither strsep(3) nor strtok(3) seem to work on my system */ p = index(linep, SEPARATOR); if ( p == NULL ) continue; *p = '\0'; device = linep; if ( strcmp( device, ressource) != 0 ) /* not a matching entry */ continue; linep = ++p; p = index(linep, SEPARATOR); if ( p == NULL ) continue; *p = '\0'; user = linep; if ( strncmp(user, username, SANE_MAX_USERNAME_LEN) != 0 ) continue; /* username doesnt match */ linep = ++p; /* rest of the line is considered to be the password */ passwd = linep; /* remove newline */ *(passwd + strlen(passwd) - 1) = '\0'; p = crypt(password, SALT); if ( strcmp(p, passwd) == 0 ) { /* authentication ok */ status = SANE_STATUS_GOOD; break; } else continue; } } while ( ! ferror(fp) && ! feof(fp) ); fclose(fp); return status; } #endif /*---------- dump_area() -----------------------------------------------------*/ static SANE_Status dump_area(uint8_t *area, int len, char *info) { /* this function dumps control or information blocks */ #define BPL 16 /* bytes per line to print */ int i; int o; int o_limit; char outputline[100]; char *outbuf; if ( ! info[0] ) info = "No additional info available"; DBG(30, "dump_area: %s\n", info); outbuf = outputline; o_limit = (len + BPL - 1) / BPL; for ( o = 0; o < o_limit; o++) { sprintf(outbuf, " %4d: ", o * BPL); outbuf += 8; for ( i=0; i < BPL && (o * BPL + i ) < len; i++) { if ( i == BPL / 2 ) { sprintf(outbuf, " "); outbuf +=1; } sprintf(outbuf, "%02x", area[o * BPL + i]); outbuf += 2; } sprintf(outbuf, "%*s", 2 * ( 2 + BPL - i), " " ); outbuf += (2 * ( 2 + BPL - i)); sprintf(outbuf, "%s", (i == BPL / 2) ? " " : ""); outbuf += ((i == BPL / 2) ? 1 : 0); for ( i = 0; i < BPL && (o * BPL + i ) < len; i++) { if ( i == BPL / 2 ) { sprintf(outbuf, " "); outbuf += 1; } sprintf(outbuf, "%c", isprint(area[o * BPL + i]) ? area[o * BPL + i] : '.'); outbuf += 1; } outbuf = outputline; DBG(1, "%s\n", outbuf); } return SANE_STATUS_GOOD; } /*---------- dump_area2() ----------------------------------------------------*/ static SANE_Status dump_area2(uint8_t *area, int len, char *info) { #define BPL 16 /* bytes per line to print */ int i; char outputline[100]; char *outbuf; if ( ! info[0] ) info = "No additional info available"; DBG(1, "[%s]\n", info); outbuf = outputline; for ( i = 0; i < len; i++) { sprintf(outbuf, "%02x,", *(area + i)); outbuf += 3; if ( ((i+1)%BPL == 0) || (i == len-1) ) { outbuf = outputline; DBG(1, "%s\n", outbuf); } } return SANE_STATUS_GOOD; } /*---------- dump_to_file() --------------------------------------------------*/ /*--- only for debugging, currently not used -----*/ #if 0 static SANE_Status dump_to_file(uint8_t *area, int len, char *filename, char *mode) { FILE *out; int i; out = fopen(filename, mode); for ( i = 0; i < len; i++) fputc( *(area + i ), out); fclose(out); return SANE_STATUS_GOOD; } #endif /*---------- dump_attributes() -----------------------------------------------*/ static SANE_Status dump_attributes(Microtek2_Info *mi) { /* dump all we know about the scanner */ int i; DBG(30, "dump_attributes: mi=%p\n", (void *) mi); DBG(1, "\n"); DBG(1, "Scanner attributes from device structure\n"); DBG(1, "========================================\n"); DBG(1, "Scanner ID...\n"); DBG(1, "~~~~~~~~~~~~~\n"); DBG(1, " Vendor Name%15s: '%s'\n", " ", mi->vendor); DBG(1, " Model Name%16s: '%s'\n", " ", mi->model); DBG(1, " Revision%18s: '%s'\n", " ", mi->revision); DBG(1, " Model Code%16s: 0x%02x\n"," ", mi->model_code); switch(mi->model_code) { case 0x80: DBG(1, "Redondo 2000XL / ArtixScan 2020\n"); break; case 0x81: DBG(1, "ScanMaker 4 / Aruba\n"); break; case 0x82: DBG(1, "Bali\n"); break; case 0x83: DBG(1, "Washington\n"); break; case 0x84: DBG(1, "Manhattan\n"); break; case 0x85: DBG(1, "ScanMaker V300 / Phantom parallel / TR3\n"); break; case 0x86: DBG(1, "CCP\n"); break; case 0x87: DBG(1, "Scanmaker V\n"); break; case 0x88: DBG(1, "Scanmaker VI\n"); break; case 0x89: DBG(1, "ScanMaker 6400XL / A3-400\n"); break; case 0x8a: DBG(1, "ScanMaker 9600XL / A3-600\n"); break; case 0x8b: DBG(1, "Watt\n"); break; case 0x8c: DBG(1, "ScanMaker V600 / TR6\n"); break; case 0x8d: DBG(1, "ScanMaker V310 / Tr3 10-bit\n"); break; case 0x8e: DBG(1, "CCB\n"); break; case 0x8f: DBG(1, "Sun Rise\n"); break; case 0x90: DBG(1, "ScanMaker E3+ 10-bit\n"); break; case 0x91: DBG(1, "ScanMaker X6 / Phantom 636\n"); break; case 0x92: DBG(1, "ScanMaker E3+ / Vobis Highscan\n"); break; case 0x93: DBG(1, "ScanMaker V310\n"); break; case 0x94: DBG(1, "SlimScan C3 / Phantom 330cx / 336cx\n"); break; case 0x95: DBG(1, "ArtixScan 1010\n"); break; case 0x97: DBG(1, "ScanMaker V636\n"); break; case 0x98: DBG(1, "ScanMaker X6EL\n"); break; case 0x99: DBG(1, "ScanMaker X6 / X6USB\n"); break; case 0x9a: DBG(1, "SlimScan C6 / Phantom 636cx\n"); break; case 0x9d: DBG(1, "AGFA DuoScan T1200\n"); break; case 0xa0: DBG(1, "SlimScan C3 / Phantom 336cx\n"); break; case 0xac: DBG(1, "ScanMaker V6UL\n"); break; case 0xa3: DBG(1, "ScanMaker V6USL\n"); break; case 0xaf: DBG(1, "SlimScan C3 / Phantom 336cx\n"); break; case 0xb0: DBG(1, "ScanMaker X12USL\n"); break; case 0xb3: DBG(1, "ScanMaker 3600\n"); break; case 0xb4: DBG(1, "ScanMaker 4700\n"); break; case 0xb6: DBG(1, "ScanMaker V6UPL\n"); break; case 0xb8: DBG(1, "ScanMaker 3700\n"); break; case 0xde: DBG(1, "ScanMaker 9800XL\n"); break; default: DBG(1, "Unknown\n"); break; } DBG(1, " Device Type Code%10s: 0x%02x (%s),\n", " ", mi->device_type, mi->device_type & MI_DEVTYPE_SCANNER ? "Scanner" : "Unknown type"); switch (mi->scanner_type) { case MI_TYPE_FLATBED: DBG(1, " Scanner type%14s:%s", " ", " Flatbed scanner\n"); break; case MI_TYPE_TRANSPARENCY: DBG(1, " Scanner type%14s:%s", " ", " Transparency scanner\n"); break; case MI_TYPE_SHEEDFEED: DBG(1, " Scanner type%14s:%s", " ", " Sheet feed scanner\n"); break; default: DBG(1, " Scanner type%14s:%s", " ", " Unknown\n"); break; } DBG(1, " Supported options%9s: Automatic document feeder: %s\n", " ", mi->option_device & MI_OPTDEV_ADF ? "Yes" : "No"); DBG(1, "%30sTransparency media adapter: %s\n", " ", mi->option_device & MI_OPTDEV_TMA ? "Yes" : "No"); DBG(1, "%30sAuto paper detecting: %s\n", " ", mi->option_device & MI_OPTDEV_ADP ? "Yes" : "No"); DBG(1, "%30sAdvanced picture system: %s\n", " ", mi->option_device & MI_OPTDEV_APS ? "Yes" : "No"); DBG(1, "%30sStripes: %s\n", " ", mi->option_device & MI_OPTDEV_STRIPE ? "Yes" : "No"); DBG(1, "%30sSlides: %s\n", " ", mi->option_device & MI_OPTDEV_SLIDE ? "Yes" : "No"); DBG(1, " Scan button%15s: %s\n", " ", mi->scnbuttn ? "Yes" : "No"); DBG(1, "\n"); DBG(1, " Imaging Capabilities...\n"); DBG(1, " ~~~~~~~~~~~~~~~~~~~~~~~\n"); DBG(1, " Color scanner%6s: %s\n", " ", (mi->color) ? "Yes" : "No"); DBG(1, " Number passes%6s: %d pass%s\n", " ", (mi->onepass) ? 1 : 3, (mi->onepass) ? "" : "es"); DBG(1, " Resolution%9s: X-max: %5d dpi\n%35sY-max: %5d dpi\n", " ", mi->max_xresolution, " ",mi->max_yresolution); DBG(1, " Geometry%11s: Geometric width: %5d pts (%2.2f'')\n", " ", mi->geo_width, (float) mi->geo_width / (float) mi->opt_resolution); DBG(1, "%23sGeometric height:%5d pts (%2.2f'')\n", " ", mi->geo_height, (float) mi->geo_height / (float) mi->opt_resolution); DBG(1, " Optical resolution%1s: %d\n", " ", mi->opt_resolution); DBG(1, " Modes%14s: Lineart: %s\n%35sHalftone: %s\n", " ", (mi->scanmode & MI_HASMODE_LINEART) ? " Yes" : " No", " ", (mi->scanmode & MI_HASMODE_HALFTONE) ? "Yes" : "No"); DBG(1, "%23sGray: %s\n%35sColor: %s\n", " ", (mi->scanmode & MI_HASMODE_GRAY) ? " Yes" : " No", " ", (mi->scanmode & MI_HASMODE_COLOR) ? " Yes" : " No"); DBG(1, " Depths%14s: Nibble Gray: %s\n", " ", (mi->depth & MI_HASDEPTH_NIBBLE) ? "Yes" : "No"); DBG(1, "%23s10-bit-color: %s\n", " ", (mi->depth & MI_HASDEPTH_10) ? "Yes" : "No"); DBG(1, "%23s12-bit-color: %s\n", " ", (mi->depth & MI_HASDEPTH_12) ? "Yes" : "No"); DBG(1, "%23s14-bit-color: %s\n", " ", (mi->depth & MI_HASDEPTH_14) ? "Yes" : "No"); DBG(1, "%23s16-bit-color: %s\n", " ", (mi->depth & MI_HASDEPTH_16) ? "Yes" : "No"); DBG(1, " d/l of HT pattern%2s: %s\n", " ", (mi->has_dnldptrn) ? "Yes" : "No"); DBG(1, " Builtin HT pattern%1s: %d\n", " ", mi->grain_slct); if ( MI_LUTCAP_NONE(mi->lut_cap) ) DBG(1, " LUT capabilities : None\n"); if ( mi->lut_cap & MI_LUTCAP_256B ) DBG(1, " LUT capabilities : 256 bytes\n"); if ( mi->lut_cap & MI_LUTCAP_1024B ) DBG(1, " LUT capabilities : 1024 bytes\n"); if ( mi->lut_cap & MI_LUTCAP_1024W ) DBG(1, " LUT capabilities : 1024 words\n"); if ( mi->lut_cap & MI_LUTCAP_4096B ) DBG(1, " LUT capabilities : 4096 bytes\n"); if ( mi->lut_cap & MI_LUTCAP_4096W ) DBG(1, " LUT capabilities : 4096 words\n"); if ( mi->lut_cap & MI_LUTCAP_64k_W ) DBG(1, " LUT capabilities : 64k words\n"); if ( mi->lut_cap & MI_LUTCAP_16k_W ) DBG(1, " LUT capabilities : 16k words\n"); DBG(1, "\n"); DBG(1, " Miscellaneous capabilities...\n"); DBG(1, " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); if ( mi->onepass) { switch(mi->data_format) { case MI_DATAFMT_CHUNKY: DBG(1, " Data format :%s", " Chunky data, R, G & B in one pixel\n"); break; case MI_DATAFMT_LPLCONCAT: DBG(1, " Data format :%s", " Line by line in concatenated sequence,\n"); DBG(1, "%23swithout color indicator\n", " "); break; case MI_DATAFMT_LPLSEGREG: DBG(1, " Data format :%s", " Line by line in segregated sequence,\n"); DBG(1, "%23swith color indicator\n", " "); break; case MI_DATAFMT_WORDCHUNKY: DBG(1, " Data format : Word chunky data\n"); break; default: DBG(1, " Data format : Unknown\n"); break; } } else DBG(1, "No information with 3-pass scanners\n"); DBG(1, " Color Sequence%17s: \n", " "); for ( i = 0; i < RSA_COLORSEQUENCE_L; i++) { switch(mi->color_sequence[i]) { case MI_COLSEQ_RED: DBG(1,"%34s%s\n", " ","R"); break; case MI_COLSEQ_GREEN: DBG(1,"%34s%s\n", " ","G"); break; case MI_COLSEQ_BLUE: DBG(1,"%34s%s\n", " ","B"); break; } } if ( mi->new_image_status == SANE_TRUE ) DBG(1, " Using new ReadImageStatus format\n"); else DBG(1, " Using old ReadImageStatus format\n"); if ( mi->direction & MI_DATSEQ_RTOL ) DBG(1, " Scanning direction : right to left\n"); else DBG(1, " Scanning direction : left to right\n"); DBG(1, " CCD gap%24s: %d lines\n", " ", mi->ccd_gap); DBG(1, " CCD pixels%21s: %d\n", " ", mi->ccd_pixels); DBG(1, " Calib white stripe location%4s: %d\n", " ", mi->calib_white); DBG(1, " Max calib space%16s: %d\n", " ", mi->calib_space); DBG(1, " Number of lens%17s: %d\n", " ", mi->nlens); DBG(1, " Max number of windows%10s: %d\n", " ", mi->nwindows); DBG(1, " Shading transfer function%6s: 0x%02x\n", " ",mi->shtrnsferequ); DBG(1, " Red balance%20s: %d\n", " ", mi->balance[0]); DBG(1, " Green balance%18s: %d\n", " ", mi->balance[1]); DBG(1, " Blue balance%19s: %d\n", " " , mi->balance[2]); DBG(1, " Buffer type%20s: %s\n", " ", mi->buftype ? "Ping-Pong" : "Ring"); DBG(1, " FEPROM%25s: %s\n", " ", mi->feprom ? "Yes" : "No"); md_dump_clear = 0; return SANE_STATUS_GOOD; } /*---------- max_string_size() -----------------------------------------------*/ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size; size_t max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen(strings[i]) + 1; /* +1 because NUL counts as part of string */ if (size > max_size) max_size = size; } return max_size; } /*---------- parse_config_file() ---------------------------------------------*/ static void parse_config_file(FILE *fp, Config_Temp **ct) { /* builds a list of device names with associated options from the */ /* config file for later use, when building the list of devices. */ /* ct->device = NULL indicates global options (valid for all devices */ char s[PATH_MAX]; Config_Options global_opts; Config_Temp *hct1; Config_Temp *hct2; DBG(30, "parse_config_file: fp=%p\n", (void *) fp); *ct = hct1 = NULL; /* first read global options and store them in global_opts */ /* initialize global_opts with default values */ global_opts = md_options; while ( sanei_config_read(s, sizeof(s), fp) ) { DBG(100, "parse_config_file: read line: %s\n", s); if ( *s == '#' || *s == '\0' ) /* ignore empty lines and comments */ continue; if ( strncmp( sanei_config_skip_whitespace(s), "option ", 7) == 0 || strncmp( sanei_config_skip_whitespace(s), "option\t", 7) == 0 ) { DBG(100, "parse_config_file: found global option %s\n", s); check_option(s, &global_opts); } else /* it is considered a new device */ break; } if ( ferror(fp) || feof(fp) ) { if ( ferror(fp) ) DBG(1, "parse_config_file: fread failed: errno=%d\n", errno); return; } while ( ! feof(fp) && ! ferror(fp) ) { if ( *s == '#' || *s == '\0' ) /* ignore empty lines and comments */ { sanei_config_read(s, sizeof(s), fp); continue; } if ( strncmp( sanei_config_skip_whitespace(s), "option ", 7) == 0 || strncmp( sanei_config_skip_whitespace(s), "option\t", 7) == 0 ) { /* when we enter this loop for the first time we allocate */ /* memory, because the line surely contains a device name, */ /* so hct1 is always != NULL at this point */ DBG(100, "parse_config_file: found device option %s\n", s); check_option(s, &hct1->opts); } else /* it is considered a new device */ { DBG(100, "parse_config_file: found device %s\n", s); hct2 = (Config_Temp *) malloc(sizeof(Config_Temp)); if ( hct2 == NULL ) { DBG(1, "parse_config_file: malloc() failed\n"); return; } if ( *ct == NULL ) /* first element */ *ct = hct1 = hct2; hct1->next = hct2; hct1 = hct2; hct1->device = strdup(s); hct1->opts = global_opts; hct1->next = NULL; } sanei_config_read(s, sizeof(s), fp); } /* set filepointer to the beginning of the file */ fseek(fp, 0L, SEEK_SET); return; } /*---------- signal_handler() ------------------------------------------------*/ static void signal_handler (int signal) { if ( signal == SIGTERM ) { sanei_scsi_req_flush_all (); _exit (SANE_STATUS_GOOD); } } /*---------- init_options() --------------------------------------------------*/ static SANE_Status init_options(Microtek2_Scanner *ms, uint8_t current_scan_source) { /* This function is called every time, when the scan source changes. */ /* The option values, that possibly change, are then reinitialized, */ /* whereas the option descriptors and option values that never */ /* change are not */ SANE_Option_Descriptor *sod; SANE_Status status; Option_Value *val; Microtek2_Device *md; Microtek2_Info *mi; int tablesize; int option_size; int max_gamma_value; int color; int i; static int first_call = 1; /* indicates, whether option */ /* descriptors must be initialized */ /* cannot be used as after a sane_close the sod's must be initialized */ DBG(30, "init_options: handle=%p, source=%d\n", (void *) ms, current_scan_source); sod = ms->sod; val = ms->val; md = ms->dev; mi = &md->info[current_scan_source]; /* needed for gamma calculation */ get_lut_size(mi, &md->max_lut_size, &md->lut_entry_size); /* calculate new values, where possibly needed */ /* Scan source */ if ( val[OPT_SOURCE].s ) free((void *) val[OPT_SOURCE].s); i = 0; md->scansource_list[i] = (SANE_String) MD_SOURCESTRING_FLATBED; if ( current_scan_source == MD_SOURCE_FLATBED ) val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); if ( md->status.adfcnt ) { md->scansource_list[++i] = (SANE_String) MD_SOURCESTRING_ADF; if ( current_scan_source == MD_SOURCE_ADF ) val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); } if ( md->status.tmacnt ) { md->scansource_list[++i] = (SANE_String) MD_SOURCESTRING_TMA; if ( current_scan_source == MD_SOURCE_TMA ) val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); } if ( mi->option_device & MI_OPTDEV_STRIPE ) { md->scansource_list[++i] = (SANE_String) MD_SOURCESTRING_STRIPE; if ( current_scan_source == MD_SOURCE_STRIPE ) val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); } /* Comment this out as long as I do not know in which bit */ /* it is indicated, whether a slide adapter is connected */ #if 0 if ( mi->option_device & MI_OPTDEV_SLIDE ) { md->scansource_list[++i] = (SANE_String) MD_SOURCESTRING_SLIDE; if ( current_scan_source == MD_SOURCE_SLIDE ) val[OPT_SOURCE].s = (SANE_String) strdup(md->scansource_list[i]); } #endif md->scansource_list[++i] = NULL; /* Scan mode */ if ( val[OPT_MODE].s ) free((void *) val[OPT_MODE].s); i = 0; if ( (mi->scanmode & MI_HASMODE_COLOR) ) { md->scanmode_list[i] = (SANE_String) MD_MODESTRING_COLOR; val[OPT_MODE].s = strdup(md->scanmode_list[i]); ++i; } if ( mi->scanmode & MI_HASMODE_GRAY ) { md->scanmode_list[i] = (SANE_String) MD_MODESTRING_GRAY; if ( ! (mi->scanmode & MI_HASMODE_COLOR ) ) val[OPT_MODE].s = strdup(md->scanmode_list[i]); ++i; } if ( mi->scanmode & MI_HASMODE_HALFTONE ) { md->scanmode_list[i] = (SANE_String) MD_MODESTRING_HALFTONE; if ( ! (mi->scanmode & MI_HASMODE_COLOR ) && ! (mi->scanmode & MI_HASMODE_GRAY ) ) val[OPT_MODE].s = strdup(md->scanmode_list[i]); ++i; } /* Always enable a lineart mode. Some models (X6, FW 1.40) say */ /* that they have no lineart mode. In this case we will do a grayscale */ /* scan and convert it to onebit data */ md->scanmode_list[i] = (SANE_String) MD_MODESTRING_LINEART; if ( ! (mi->scanmode & MI_HASMODE_COLOR ) && ! (mi->scanmode & MI_HASMODE_GRAY ) && ! (mi->scanmode & MI_HASMODE_HALFTONE ) ) val[OPT_MODE].s = strdup(md->scanmode_list[i]); ++i; md->scanmode_list[i] = NULL; /* bitdepth */ i = 0; #if 0 if ( mi->depth & MI_HASDEPTH_NIBBLE ) md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_4; #endif md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_8; if ( mi->depth & MI_HASDEPTH_10 ) md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_10; if ( mi->depth & MI_HASDEPTH_12 ) md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_12; if ( mi->depth & MI_HASDEPTH_14 ) md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_14; if ( mi->depth & MI_HASDEPTH_16 ) md->bitdepth_list[++i] = (SANE_Int) MD_DEPTHVAL_16; md->bitdepth_list[0] = i; if ( md->bitdepth_list[1] == (SANE_Int) MD_DEPTHVAL_8 ) val[OPT_BITDEPTH].w = md->bitdepth_list[1]; else val[OPT_BITDEPTH].w = md->bitdepth_list[2]; /* Halftone */ md->halftone_mode_list[0] = (SANE_String) MD_HALFTONE0; md->halftone_mode_list[1] = (SANE_String) MD_HALFTONE1; md->halftone_mode_list[2] = (SANE_String) MD_HALFTONE2; md->halftone_mode_list[3] = (SANE_String) MD_HALFTONE3; md->halftone_mode_list[4] = (SANE_String) MD_HALFTONE4; md->halftone_mode_list[5] = (SANE_String) MD_HALFTONE5; md->halftone_mode_list[6] = (SANE_String) MD_HALFTONE6; md->halftone_mode_list[7] = (SANE_String) MD_HALFTONE7; md->halftone_mode_list[8] = (SANE_String) MD_HALFTONE8; md->halftone_mode_list[9] = (SANE_String) MD_HALFTONE9; md->halftone_mode_list[10] = (SANE_String) MD_HALFTONE10; md->halftone_mode_list[11] = (SANE_String) MD_HALFTONE11; md->halftone_mode_list[12] = NULL; if ( val[OPT_HALFTONE].s ) free((void *) val[OPT_HALFTONE].s); val[OPT_HALFTONE].s = strdup(md->halftone_mode_list[0]); /* Resolution */ md->x_res_range_dpi.min = SANE_FIX(10.0); md->x_res_range_dpi.max = SANE_FIX(mi->max_xresolution); md->x_res_range_dpi.quant = SANE_FIX(1.0); val[OPT_RESOLUTION].w = MIN(MD_RESOLUTION_DEFAULT, md->x_res_range_dpi.max); md->y_res_range_dpi.min = SANE_FIX(10.0); md->y_res_range_dpi.max = SANE_FIX(mi->max_yresolution); md->y_res_range_dpi.quant = SANE_FIX(1.0); val[OPT_Y_RESOLUTION].w = val[OPT_RESOLUTION].w; /* bind is default */ /* Preview mode */ val[OPT_PREVIEW].w = SANE_FALSE; /* Geometry */ md->x_range_mm.min = SANE_FIX(0.0); md->x_range_mm.max = SANE_FIX((double) mi->geo_width / (double) mi->opt_resolution * MM_PER_INCH); md->x_range_mm.quant = SANE_FIX(0.0); md->y_range_mm.min = SANE_FIX(0.0); md->y_range_mm.max = SANE_FIX((double) mi->geo_height / (double) mi->opt_resolution * MM_PER_INCH); md->y_range_mm.quant = SANE_FIX(0.0); val[OPT_TL_X].w = SANE_FIX(0.0); val[OPT_TL_Y].w = SANE_FIX(0.0); val[OPT_BR_X].w = md->x_range_mm.max; val[OPT_BR_Y].w = md->y_range_mm.max; /* Enhancement group */ val[OPT_BRIGHTNESS].w = MD_BRIGHTNESS_DEFAULT; val[OPT_CONTRAST].w = MD_CONTRAST_DEFAULT; val[OPT_THRESHOLD].w = MD_THRESHOLD_DEFAULT; /* Gamma */ /* linear gamma must come first */ i = 0; md->gammamode_list[i++] = (SANE_String) MD_GAMMAMODE_LINEAR; md->gammamode_list[i++] = (SANE_String) MD_GAMMAMODE_SCALAR; md->gammamode_list[i++] = (SANE_String) MD_GAMMAMODE_CUSTOM; if ( val[OPT_GAMMA_MODE].s ) free((void *) val[OPT_GAMMA_MODE].s); val[OPT_GAMMA_MODE].s = strdup(md->gammamode_list[0]); md->gammamode_list[i] = NULL; /* bind gamma */ val[OPT_GAMMA_BIND].w = SANE_TRUE; val[OPT_GAMMA_SCALAR].w = MD_GAMMA_DEFAULT; val[OPT_GAMMA_SCALAR_R].w = MD_GAMMA_DEFAULT; val[OPT_GAMMA_SCALAR_G].w = MD_GAMMA_DEFAULT; val[OPT_GAMMA_SCALAR_B].w = MD_GAMMA_DEFAULT; /* If the device supports gamma tables, we allocate memory according */ /* to lookup table capabilities, otherwise we allocate 4096 elements */ /* which is sufficient for a color depth of 12. If the device */ /* does not support gamma tables, we fill the table according to */ /* the actual bit depth, i.e. 256 entries with a range of 0..255 */ /* if the actual bit depth is 8, for example. This will hopefully*/ /* make no trouble if the bit depth is 1. */ if ( md->model_flags & MD_NO_GAMMA ) { tablesize = 4096; option_size = (int) pow(2.0, (double) val[OPT_BITDEPTH].w ); max_gamma_value = option_size - 1; } else { tablesize = md->max_lut_size; option_size = tablesize; max_gamma_value = md->max_lut_size - 1; } for ( color = 0; color < 4; color++ ) { /* index 0 is used if bind gamma == true, index 1 to 3 */ /* if bind gamma == false */ if ( md->custom_gamma_table[color] ) free((void *) md->custom_gamma_table[color]); md->custom_gamma_table[color] = (SANE_Int *) malloc(tablesize * sizeof(SANE_Int)); DBG(100, "init_options: md->custom_gamma_table[%d]=%p, malloc'd %lu bytes\n", color, (void *) md->custom_gamma_table[color], (u_long) (tablesize * sizeof(SANE_Int))); if ( md->custom_gamma_table[color] == NULL ) { DBG(1, "init_options: malloc for custom gamma table failed\n"); return SANE_STATUS_NO_MEM; } for ( i = 0; i < max_gamma_value; i++ ) md->custom_gamma_table[color][i] = i; } md->custom_gamma_range.min = 0; md->custom_gamma_range.max = max_gamma_value; md->custom_gamma_range.quant = 1; sod[OPT_GAMMA_CUSTOM].size = option_size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_R].size = option_size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_G].size = option_size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_B].size = option_size * sizeof (SANE_Int); val[OPT_GAMMA_CUSTOM].wa = &md->custom_gamma_table[0][0]; val[OPT_GAMMA_CUSTOM_R].wa = &md->custom_gamma_table[1][0]; val[OPT_GAMMA_CUSTOM_G].wa = &md->custom_gamma_table[2][0]; val[OPT_GAMMA_CUSTOM_B].wa = &md->custom_gamma_table[3][0]; /* Shadow, midtone, highlight, exposure time */ md->channel_list[0] = (SANE_String) MD_CHANNEL_MASTER; md->channel_list[1] = (SANE_String) MD_CHANNEL_RED; md->channel_list[2] = (SANE_String) MD_CHANNEL_GREEN; md->channel_list[3] = (SANE_String) MD_CHANNEL_BLUE; md->channel_list[4] = NULL; if ( val[OPT_CHANNEL].s ) free((void *) val[OPT_CHANNEL].s); val[OPT_CHANNEL].s = strdup(md->channel_list[0]); val[OPT_SHADOW].w = MD_SHADOW_DEFAULT; val[OPT_SHADOW_R].w = MD_SHADOW_DEFAULT; val[OPT_SHADOW_G].w = MD_SHADOW_DEFAULT; val[OPT_SHADOW_B].w = MD_SHADOW_DEFAULT; val[OPT_MIDTONE].w = MD_MIDTONE_DEFAULT; val[OPT_MIDTONE_R].w = MD_MIDTONE_DEFAULT; val[OPT_MIDTONE_G].w = MD_MIDTONE_DEFAULT; val[OPT_MIDTONE_B].w = MD_MIDTONE_DEFAULT; val[OPT_HIGHLIGHT].w = MD_HIGHLIGHT_DEFAULT; val[OPT_HIGHLIGHT_R].w = MD_HIGHLIGHT_DEFAULT; val[OPT_HIGHLIGHT_G].w = MD_HIGHLIGHT_DEFAULT; val[OPT_HIGHLIGHT_B].w = MD_HIGHLIGHT_DEFAULT; val[OPT_EXPOSURE].w = MD_EXPOSURE_DEFAULT; val[OPT_EXPOSURE_R].w = MD_EXPOSURE_DEFAULT; val[OPT_EXPOSURE_G].w = MD_EXPOSURE_DEFAULT; val[OPT_EXPOSURE_B].w = MD_EXPOSURE_DEFAULT; /* special options */ val[OPT_RESOLUTION_BIND].w = SANE_TRUE; /* enable/disable option for backtracking */ val[OPT_DISABLE_BACKTRACK].w = md->opt_no_backtrack_default; /* enable/disable calibration by backend */ val[OPT_CALIB_BACKEND].w = md->opt_backend_calib_default; /* turn off the lamp during a scan */ val[OPT_LIGHTLID35].w = SANE_FALSE; /* auto adjustment of threshold during a lineart scan */ val[OPT_AUTOADJUST].w = SANE_FALSE; /* color balance (100% means no correction) */ val[OPT_BALANCE_R].w = SANE_FIX(100); val[OPT_BALANCE_G].w = SANE_FIX(100); val[OPT_BALANCE_B].w = SANE_FIX(100); if ( first_call ) { /* initialize option descriptors and ranges */ /* Percentage range for brightness, contrast */ md->percentage_range.min = 0 << SANE_FIXED_SCALE_SHIFT; md->percentage_range.max = 200 << SANE_FIXED_SCALE_SHIFT; md->percentage_range.quant = 1 << SANE_FIXED_SCALE_SHIFT; md->threshold_range.min = 1; md->threshold_range.max = 255; md->threshold_range.quant = 1; md->scalar_gamma_range.min = SANE_FIX(0.1); md->scalar_gamma_range.max = SANE_FIX(4.0); md->scalar_gamma_range.quant = SANE_FIX(0.1); md->shadow_range.min = 0; md->shadow_range.max = 253; md->shadow_range.quant = 1; md->midtone_range.min = 1; md->midtone_range.max = 254; md->midtone_range.quant = 1; md->highlight_range.min = 2; md->highlight_range.max = 255; md->highlight_range.quant = 1; md->exposure_range.min = 0; md->exposure_range.max = 510; md->exposure_range.quant = 2; md->balance_range.min = 0; md->balance_range.max = 200 << SANE_FIXED_SCALE_SHIFT; md->balance_range.quant = 1 << SANE_FIXED_SCALE_SHIFT; /* default for most options */ for ( i = 0; i < NUM_OPTIONS; i++ ) { sod[i].type = SANE_TYPE_FIXED; sod[i].unit = SANE_UNIT_NONE; sod[i].size = sizeof(SANE_Fixed); sod[i].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; sod[i].constraint_type = SANE_CONSTRAINT_RANGE; } sod[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; sod[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; sod[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; sod[OPT_NUM_OPTS].type = SANE_TYPE_INT; sod[OPT_NUM_OPTS].size = sizeof (SANE_Int); sod[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; sod[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* NUM_OPTIONS is no option */ DBG(255, "sod=%p\n", (void *) sod); DBG(255, "OPT_NUM_OPTS=%d\n", OPT_NUM_OPTS); DBG(255, "SANE_CAP_SOFT_DETECT=%d\n", SANE_CAP_SOFT_DETECT); DBG(255, "OPT_NUM_OPTS.cap=%d\n", sod[0].cap); /* The Scan Mode Group */ sod[OPT_MODE_GROUP].title = M_TITLE_SCANMODEGRP; sod[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; sod[OPT_MODE_GROUP].size = 0; sod[OPT_MODE_GROUP].desc = ""; sod[OPT_MODE_GROUP].cap = 0; sod[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scan source */ sod[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; sod[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; sod[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; sod[OPT_SOURCE].type = SANE_TYPE_STRING; sod[OPT_SOURCE].size = max_string_size(md->scansource_list); /* if there is only one scan source, deactivate option */ if ( md->scansource_list[1] == NULL ) sod[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; sod[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; sod[OPT_SOURCE].constraint.string_list = md->scansource_list; /* Scan mode */ sod[OPT_MODE].name = SANE_NAME_SCAN_MODE; sod[OPT_MODE].title = SANE_TITLE_SCAN_MODE; sod[OPT_MODE].desc = SANE_DESC_SCAN_MODE; sod[OPT_MODE].type = SANE_TYPE_STRING; sod[OPT_MODE].size = max_string_size(md->scanmode_list); sod[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; sod[OPT_MODE].constraint.string_list = md->scanmode_list; /* Bit depth */ sod[OPT_BITDEPTH].name = SANE_NAME_BIT_DEPTH; sod[OPT_BITDEPTH].title = SANE_TITLE_BIT_DEPTH; sod[OPT_BITDEPTH].desc = SANE_DESC_BIT_DEPTH; sod[OPT_BITDEPTH].type = SANE_TYPE_INT; sod[OPT_BITDEPTH].unit = SANE_UNIT_BIT; sod[OPT_BITDEPTH].size = sizeof(SANE_Int); /* if we have only 8 bit color deactivate this option */ if ( md->bitdepth_list[0] == 1 ) sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; sod[OPT_BITDEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; sod[OPT_BITDEPTH].constraint.word_list = md->bitdepth_list; /* Halftone */ sod[OPT_HALFTONE].name = SANE_NAME_HALFTONE; sod[OPT_HALFTONE].title = SANE_TITLE_HALFTONE; sod[OPT_HALFTONE].desc = SANE_DESC_HALFTONE; sod[OPT_HALFTONE].type = SANE_TYPE_STRING; sod[OPT_HALFTONE].size = max_string_size(md->halftone_mode_list); sod[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; sod[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; sod[OPT_HALFTONE].constraint.string_list = md->halftone_mode_list; /* Resolution */ sod[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; sod[OPT_RESOLUTION].title = SANE_TITLE_SCAN_X_RESOLUTION; sod[OPT_RESOLUTION].desc = SANE_DESC_SCAN_X_RESOLUTION; sod[OPT_RESOLUTION].unit = SANE_UNIT_DPI; sod[OPT_RESOLUTION].constraint.range = &md->x_res_range_dpi; sod[OPT_Y_RESOLUTION].name = SANE_NAME_SCAN_Y_RESOLUTION; sod[OPT_Y_RESOLUTION].title = SANE_TITLE_SCAN_Y_RESOLUTION; sod[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_Y_RESOLUTION; sod[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; sod[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; sod[OPT_Y_RESOLUTION].constraint.range = &md->y_res_range_dpi; /* Preview */ sod[OPT_PREVIEW].name = SANE_NAME_PREVIEW; sod[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; sod[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; sod[OPT_PREVIEW].type = SANE_TYPE_BOOL; sod[OPT_PREVIEW].size = sizeof(SANE_Bool); sod[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; /* Geometry group, for scan area selection */ sod[OPT_GEOMETRY_GROUP].title = M_TITLE_GEOMGRP; sod[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; sod[OPT_GEOMETRY_GROUP].size = 0; sod[OPT_GEOMETRY_GROUP].desc = ""; sod[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; sod[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; sod[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; sod[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; sod[OPT_TL_X].unit = SANE_UNIT_MM; sod[OPT_TL_X].constraint.range = &md->x_range_mm; sod[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; sod[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; sod[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; sod[OPT_TL_Y].unit = SANE_UNIT_MM; sod[OPT_TL_Y].constraint.range = &md->y_range_mm; sod[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; sod[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; sod[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; sod[OPT_BR_X].unit = SANE_UNIT_MM; sod[OPT_BR_X].constraint.range = &md->x_range_mm; sod[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; sod[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; sod[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; sod[OPT_BR_Y].unit = SANE_UNIT_MM; sod[OPT_BR_Y].constraint.range = &md->y_range_mm; /* Enhancement group */ sod[OPT_ENHANCEMENT_GROUP].title = M_TITLE_ENHANCEGRP; sod[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; sod[OPT_ENHANCEMENT_GROUP].desc = ""; sod[OPT_ENHANCEMENT_GROUP].size = 0; sod[OPT_ENHANCEMENT_GROUP].cap = 0; sod[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; sod[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; sod[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; sod[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; sod[OPT_BRIGHTNESS].constraint.range = &md->percentage_range; sod[OPT_CONTRAST].name = SANE_NAME_CONTRAST; sod[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; sod[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; sod[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; sod[OPT_CONTRAST].constraint.range = &md->percentage_range; sod[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; sod[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; sod[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; sod[OPT_THRESHOLD].type = SANE_TYPE_INT; sod[OPT_THRESHOLD].size = sizeof(SANE_Int); sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; sod[OPT_THRESHOLD].constraint.range = &md->threshold_range; /* automatically adjust threshold for a lineart scan */ sod[OPT_AUTOADJUST].name = M_NAME_AUTOADJUST; sod[OPT_AUTOADJUST].title = M_TITLE_AUTOADJUST; sod[OPT_AUTOADJUST].desc = M_DESC_AUTOADJUST; sod[OPT_AUTOADJUST].type = SANE_TYPE_BOOL; sod[OPT_AUTOADJUST].size = sizeof(SANE_Bool); sod[OPT_AUTOADJUST].constraint_type = SANE_CONSTRAINT_NONE; if ( strncmp(md->opts.auto_adjust, "off", 3) == 0 ) sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; /* Gamma */ sod[OPT_GAMMA_GROUP].title = "Gamma"; sod[OPT_GAMMA_GROUP].desc = ""; sod[OPT_GAMMA_GROUP].type = SANE_TYPE_GROUP; sod[OPT_GAMMA_GROUP].size = 0; sod[OPT_GAMMA_GROUP].cap = 0; sod[OPT_GAMMA_GROUP].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_GAMMA_MODE].name = M_NAME_GAMMA_MODE; sod[OPT_GAMMA_MODE].title = M_TITLE_GAMMA_MODE; sod[OPT_GAMMA_MODE].desc = M_DESC_GAMMA_MODE; sod[OPT_GAMMA_MODE].type = SANE_TYPE_STRING; sod[OPT_GAMMA_MODE].size = max_string_size(md->gammamode_list); sod[OPT_GAMMA_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; sod[OPT_GAMMA_MODE].constraint.string_list = md->gammamode_list; sod[OPT_GAMMA_BIND].name = M_NAME_GAMMA_BIND; sod[OPT_GAMMA_BIND].title = M_TITLE_GAMMA_BIND; sod[OPT_GAMMA_BIND].desc = M_DESC_GAMMA_BIND; sod[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL; sod[OPT_GAMMA_BIND].size = sizeof(SANE_Bool); sod[OPT_GAMMA_BIND].constraint_type = SANE_CONSTRAINT_NONE; /* this is active if gamma_bind == true and gammamode == scalar */ sod[OPT_GAMMA_SCALAR].name = M_NAME_GAMMA_SCALAR; sod[OPT_GAMMA_SCALAR].title = M_TITLE_GAMMA_SCALAR; sod[OPT_GAMMA_SCALAR].desc = M_DESC_GAMMA_SCALAR; sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR].constraint.range = &md->scalar_gamma_range; sod[OPT_GAMMA_SCALAR_R].name = M_NAME_GAMMA_SCALAR_R; sod[OPT_GAMMA_SCALAR_R].title = M_TITLE_GAMMA_SCALAR_R; sod[OPT_GAMMA_SCALAR_R].desc = M_DESC_GAMMA_SCALAR_R; sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_R].constraint.range = &md->scalar_gamma_range; sod[OPT_GAMMA_SCALAR_G].name = M_NAME_GAMMA_SCALAR_G; sod[OPT_GAMMA_SCALAR_G].title = M_TITLE_GAMMA_SCALAR_G; sod[OPT_GAMMA_SCALAR_G].desc = M_DESC_GAMMA_SCALAR_G; sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_G].constraint.range = &md->scalar_gamma_range; sod[OPT_GAMMA_SCALAR_B].name = M_NAME_GAMMA_SCALAR_B; sod[OPT_GAMMA_SCALAR_B].title = M_TITLE_GAMMA_SCALAR_B; sod[OPT_GAMMA_SCALAR_B].desc = M_DESC_GAMMA_SCALAR_B; sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_B].constraint.range = &md->scalar_gamma_range; sod[OPT_GAMMA_CUSTOM].name = SANE_NAME_GAMMA_VECTOR; sod[OPT_GAMMA_CUSTOM].title = SANE_TITLE_GAMMA_VECTOR; sod[OPT_GAMMA_CUSTOM].desc = SANE_DESC_GAMMA_VECTOR; sod[OPT_GAMMA_CUSTOM].type = SANE_TYPE_INT; sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM].size = option_size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM].constraint.range = &md->custom_gamma_range; sod[OPT_GAMMA_CUSTOM_R].name = SANE_NAME_GAMMA_VECTOR_R; sod[OPT_GAMMA_CUSTOM_R].title = SANE_TITLE_GAMMA_VECTOR_R; sod[OPT_GAMMA_CUSTOM_R].desc = SANE_DESC_GAMMA_VECTOR_R; sod[OPT_GAMMA_CUSTOM_R].type = SANE_TYPE_INT; sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_R].size = option_size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_R].constraint.range = &md->custom_gamma_range; sod[OPT_GAMMA_CUSTOM_G].name = SANE_NAME_GAMMA_VECTOR_G; sod[OPT_GAMMA_CUSTOM_G].title = SANE_TITLE_GAMMA_VECTOR_G; sod[OPT_GAMMA_CUSTOM_G].desc = SANE_DESC_GAMMA_VECTOR_G; sod[OPT_GAMMA_CUSTOM_G].type = SANE_TYPE_INT; sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_G].size = option_size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_G].constraint.range = &md->custom_gamma_range; sod[OPT_GAMMA_CUSTOM_B].name = SANE_NAME_GAMMA_VECTOR_B; sod[OPT_GAMMA_CUSTOM_B].title = SANE_TITLE_GAMMA_VECTOR_B; sod[OPT_GAMMA_CUSTOM_B].desc = SANE_DESC_GAMMA_VECTOR_B; sod[OPT_GAMMA_CUSTOM_B].type = SANE_TYPE_INT; sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_B].size = option_size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_B].constraint.range = &md->custom_gamma_range; /* Shadow, midtone, highlight */ sod[OPT_SMH_GROUP].title = M_TITLE_SMHGRP; sod[OPT_SMH_GROUP].desc = ""; sod[OPT_SMH_GROUP].type = SANE_TYPE_GROUP; sod[OPT_SMH_GROUP].size = 0; sod[OPT_SMH_GROUP].cap = 0; sod[OPT_SMH_GROUP].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_CHANNEL].name = M_NAME_CHANNEL; sod[OPT_CHANNEL].title = M_TITLE_CHANNEL; sod[OPT_CHANNEL].desc = M_DESC_CHANNEL; sod[OPT_CHANNEL].type = SANE_TYPE_STRING; sod[OPT_CHANNEL].size = max_string_size(md->channel_list); sod[OPT_CHANNEL].constraint_type = SANE_CONSTRAINT_STRING_LIST; sod[OPT_CHANNEL].constraint.string_list = md->channel_list; sod[OPT_SHADOW].name = SANE_NAME_SHADOW; sod[OPT_SHADOW].title = SANE_TITLE_SHADOW; sod[OPT_SHADOW].desc = SANE_DESC_SHADOW; sod[OPT_SHADOW].type = SANE_TYPE_INT; sod[OPT_SHADOW].size = sizeof(SANE_Int); sod[OPT_SHADOW].constraint.range = &md->shadow_range; sod[OPT_SHADOW_R].name = SANE_NAME_SHADOW_R; sod[OPT_SHADOW_R].title = SANE_TITLE_SHADOW_R; sod[OPT_SHADOW_R].desc = SANE_DESC_SHADOW_R; sod[OPT_SHADOW_R].type = SANE_TYPE_INT; sod[OPT_SHADOW_R].size = sizeof(SANE_Int); sod[OPT_SHADOW_R].constraint.range = &md->shadow_range; sod[OPT_SHADOW_G].name = SANE_NAME_SHADOW_G; sod[OPT_SHADOW_G].title = SANE_TITLE_SHADOW_G; sod[OPT_SHADOW_G].desc = SANE_DESC_SHADOW_G; sod[OPT_SHADOW_G].type = SANE_TYPE_INT; sod[OPT_SHADOW_G].size = sizeof(SANE_Int); sod[OPT_SHADOW_G].constraint.range = &md->shadow_range; sod[OPT_SHADOW_B].name = SANE_NAME_SHADOW_B; sod[OPT_SHADOW_B].title = SANE_TITLE_SHADOW_B; sod[OPT_SHADOW_B].desc = SANE_DESC_SHADOW_B; sod[OPT_SHADOW_B].type = SANE_TYPE_INT; sod[OPT_SHADOW_B].size = sizeof(SANE_Int); sod[OPT_SHADOW_B].constraint.range = &md->shadow_range; sod[OPT_MIDTONE].name = M_NAME_MIDTONE; sod[OPT_MIDTONE].title = M_TITLE_MIDTONE; sod[OPT_MIDTONE].desc = M_DESC_MIDTONE; sod[OPT_MIDTONE].type = SANE_TYPE_INT; sod[OPT_MIDTONE].size = sizeof(SANE_Int); sod[OPT_MIDTONE].constraint.range = &md->midtone_range; sod[OPT_MIDTONE_R].name = M_NAME_MIDTONE_R; sod[OPT_MIDTONE_R].title = M_TITLE_MIDTONE_R; sod[OPT_MIDTONE_R].desc = M_DESC_MIDTONE_R; sod[OPT_MIDTONE_R].type = SANE_TYPE_INT; sod[OPT_MIDTONE_R].size = sizeof(SANE_Int); sod[OPT_MIDTONE_R].constraint.range = &md->midtone_range; sod[OPT_MIDTONE_G].name = M_NAME_MIDTONE_G; sod[OPT_MIDTONE_G].title = M_TITLE_MIDTONE_G; sod[OPT_MIDTONE_G].desc = M_DESC_MIDTONE_G; sod[OPT_MIDTONE_G].type = SANE_TYPE_INT; sod[OPT_MIDTONE_G].size = sizeof(SANE_Int); sod[OPT_MIDTONE_G].constraint.range = &md->midtone_range; sod[OPT_MIDTONE_B].name = M_NAME_MIDTONE_B; sod[OPT_MIDTONE_B].title = M_TITLE_MIDTONE_B; sod[OPT_MIDTONE_B].desc = M_DESC_MIDTONE_B; sod[OPT_MIDTONE_B].type = SANE_TYPE_INT; sod[OPT_MIDTONE_B].size = sizeof(SANE_Int); sod[OPT_MIDTONE_B].constraint.range = &md->midtone_range; sod[OPT_HIGHLIGHT].name = SANE_NAME_HIGHLIGHT; sod[OPT_HIGHLIGHT].title = SANE_TITLE_HIGHLIGHT; sod[OPT_HIGHLIGHT].desc = SANE_DESC_HIGHLIGHT; sod[OPT_HIGHLIGHT].type = SANE_TYPE_INT; sod[OPT_HIGHLIGHT].size = sizeof(SANE_Int); sod[OPT_HIGHLIGHT].constraint.range = &md->highlight_range; sod[OPT_HIGHLIGHT_R].name = SANE_NAME_HIGHLIGHT_R; sod[OPT_HIGHLIGHT_R].title = SANE_TITLE_HIGHLIGHT_R; sod[OPT_HIGHLIGHT_R].desc = SANE_DESC_HIGHLIGHT_R; sod[OPT_HIGHLIGHT_R].type = SANE_TYPE_INT; sod[OPT_HIGHLIGHT_R].size = sizeof(SANE_Int); sod[OPT_HIGHLIGHT_R].constraint.range = &md->highlight_range; sod[OPT_HIGHLIGHT_G].name = SANE_NAME_HIGHLIGHT_G; sod[OPT_HIGHLIGHT_G].title = SANE_TITLE_HIGHLIGHT_G; sod[OPT_HIGHLIGHT_G].desc = SANE_DESC_HIGHLIGHT_G; sod[OPT_HIGHLIGHT_G].type = SANE_TYPE_INT; sod[OPT_HIGHLIGHT_G].size = sizeof(SANE_Int); sod[OPT_HIGHLIGHT_G].constraint.range = &md->highlight_range; sod[OPT_HIGHLIGHT_B].name = SANE_NAME_HIGHLIGHT_B; sod[OPT_HIGHLIGHT_B].title = SANE_TITLE_HIGHLIGHT_B; sod[OPT_HIGHLIGHT_B].desc = SANE_DESC_HIGHLIGHT_B; sod[OPT_HIGHLIGHT_B].type = SANE_TYPE_INT; sod[OPT_HIGHLIGHT_B].size = sizeof(SANE_Int); sod[OPT_HIGHLIGHT_B].constraint.range = &md->highlight_range; sod[OPT_EXPOSURE].name = SANE_NAME_SCAN_EXPOS_TIME; sod[OPT_EXPOSURE].title = SANE_TITLE_SCAN_EXPOS_TIME; sod[OPT_EXPOSURE].desc = SANE_DESC_SCAN_EXPOS_TIME; sod[OPT_EXPOSURE].type = SANE_TYPE_INT; sod[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; sod[OPT_EXPOSURE].size = sizeof(SANE_Int); sod[OPT_EXPOSURE].constraint.range = &md->exposure_range; sod[OPT_EXPOSURE_R].name = SANE_NAME_SCAN_EXPOS_TIME_R; sod[OPT_EXPOSURE_R].title = SANE_TITLE_SCAN_EXPOS_TIME_R; sod[OPT_EXPOSURE_R].desc = SANE_DESC_SCAN_EXPOS_TIME_R; sod[OPT_EXPOSURE_R].type = SANE_TYPE_INT; sod[OPT_EXPOSURE_R].unit = SANE_UNIT_PERCENT; sod[OPT_EXPOSURE_R].size = sizeof(SANE_Int); sod[OPT_EXPOSURE_R].constraint.range = &md->exposure_range; sod[OPT_EXPOSURE_G].name = SANE_NAME_SCAN_EXPOS_TIME_G; sod[OPT_EXPOSURE_G].title = SANE_TITLE_SCAN_EXPOS_TIME_G; sod[OPT_EXPOSURE_G].desc = SANE_DESC_SCAN_EXPOS_TIME_G; sod[OPT_EXPOSURE_G].type = SANE_TYPE_INT; sod[OPT_EXPOSURE_G].unit = SANE_UNIT_PERCENT; sod[OPT_EXPOSURE_G].size = sizeof(SANE_Int); sod[OPT_EXPOSURE_G].constraint.range = &md->exposure_range; sod[OPT_EXPOSURE_B].name = SANE_NAME_SCAN_EXPOS_TIME_B; sod[OPT_EXPOSURE_B].title = SANE_TITLE_SCAN_EXPOS_TIME_B; sod[OPT_EXPOSURE_B].desc = SANE_DESC_SCAN_EXPOS_TIME_B; sod[OPT_EXPOSURE_B].type = SANE_TYPE_INT; sod[OPT_EXPOSURE_B].unit = SANE_UNIT_PERCENT; sod[OPT_EXPOSURE_B].size = sizeof(SANE_Int); sod[OPT_EXPOSURE_B].constraint.range = &md->exposure_range; /* The Special Options Group */ sod[OPT_SPECIAL].title = M_TITLE_SPECIALGRP; sod[OPT_SPECIAL].type = SANE_TYPE_GROUP; sod[OPT_SPECIAL].size = 0; sod[OPT_SPECIAL].desc = ""; sod[OPT_SPECIAL].cap = SANE_CAP_ADVANCED; sod[OPT_SPECIAL].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_RESOLUTION_BIND].name = SANE_NAME_RESOLUTION_BIND; sod[OPT_RESOLUTION_BIND].title = SANE_TITLE_RESOLUTION_BIND; sod[OPT_RESOLUTION_BIND].desc = SANE_DESC_RESOLUTION_BIND; sod[OPT_RESOLUTION_BIND].type = SANE_TYPE_BOOL; sod[OPT_RESOLUTION_BIND].size = sizeof(SANE_Bool); sod[OPT_RESOLUTION_BIND].cap |= SANE_CAP_ADVANCED; sod[OPT_RESOLUTION_BIND].constraint_type = SANE_CONSTRAINT_NONE; /* enable/disable option for backtracking */ sod[OPT_DISABLE_BACKTRACK].name = M_NAME_NOBACKTRACK; sod[OPT_DISABLE_BACKTRACK].title = M_TITLE_NOBACKTRACK; sod[OPT_DISABLE_BACKTRACK].desc = M_DESC_NOBACKTRACK; sod[OPT_DISABLE_BACKTRACK].type = SANE_TYPE_BOOL; sod[OPT_DISABLE_BACKTRACK].size = sizeof(SANE_Bool); sod[OPT_DISABLE_BACKTRACK].cap |= SANE_CAP_ADVANCED; sod[OPT_DISABLE_BACKTRACK].constraint_type = SANE_CONSTRAINT_NONE; if ( strncmp(md->opts.no_backtracking, "off", 3) == 0 ) sod[OPT_DISABLE_BACKTRACK].cap |= SANE_CAP_INACTIVE; /* calibration by driver */ sod[OPT_CALIB_BACKEND].name = M_NAME_CALIBBACKEND; sod[OPT_CALIB_BACKEND].title = M_TITLE_CALIBBACKEND; sod[OPT_CALIB_BACKEND].desc = M_DESC_CALIBBACKEND; sod[OPT_CALIB_BACKEND].type = SANE_TYPE_BOOL; sod[OPT_CALIB_BACKEND].size = sizeof(SANE_Bool); sod[OPT_CALIB_BACKEND].cap |= SANE_CAP_ADVANCED; sod[OPT_CALIB_BACKEND].constraint_type = SANE_CONSTRAINT_NONE; if ( strncmp(md->opts.backend_calibration, "off", 3) == 0 ) sod[OPT_CALIB_BACKEND].cap |= SANE_CAP_INACTIVE; /* turn off the lamp of the flatbed during a scan */ sod[OPT_LIGHTLID35].name = M_NAME_LIGHTLID35; sod[OPT_LIGHTLID35].title = M_TITLE_LIGHTLID35; sod[OPT_LIGHTLID35].desc = M_DESC_LIGHTLID35; sod[OPT_LIGHTLID35].type = SANE_TYPE_BOOL; sod[OPT_LIGHTLID35].size = sizeof(SANE_Bool); sod[OPT_LIGHTLID35].cap |= SANE_CAP_ADVANCED; sod[OPT_LIGHTLID35].constraint_type = SANE_CONSTRAINT_NONE; if ( strncmp(md->opts.lightlid35, "off", 3) == 0 ) sod[OPT_LIGHTLID35].cap |= SANE_CAP_INACTIVE; /* toggle the lamp of the flatbed */ sod[OPT_TOGGLELAMP].name = M_NAME_TOGGLELAMP; sod[OPT_TOGGLELAMP].title = M_TITLE_TOGGLELAMP; sod[OPT_TOGGLELAMP].desc = M_DESC_TOGGLELAMP; sod[OPT_TOGGLELAMP].type = SANE_TYPE_BUTTON; sod[OPT_TOGGLELAMP].size = 0; sod[OPT_TOGGLELAMP].cap |= SANE_CAP_ADVANCED; sod[OPT_TOGGLELAMP].constraint_type = SANE_CONSTRAINT_NONE; if ( strncmp(md->opts.toggle_lamp, "off", 3) == 0 ) sod[OPT_TOGGLELAMP].cap |= SANE_CAP_INACTIVE; /* color balance */ sod[OPT_COLORBALANCE].title = M_TITLE_COLBALANCEGRP; sod[OPT_COLORBALANCE].type = SANE_TYPE_GROUP; sod[OPT_COLORBALANCE].size = 0; sod[OPT_COLORBALANCE].desc = ""; sod[OPT_COLORBALANCE].cap = SANE_CAP_ADVANCED; sod[OPT_COLORBALANCE].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_BALANCE_R].name = M_NAME_BALANCE_R; sod[OPT_BALANCE_R].title = M_TITLE_BALANCE_R; sod[OPT_BALANCE_R].desc = M_DESC_BALANCE_R; sod[OPT_BALANCE_R].unit = SANE_UNIT_PERCENT; sod[OPT_BALANCE_R].cap |= SANE_CAP_ADVANCED; sod[OPT_BALANCE_R].constraint.range = &md->balance_range; if ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) sod[OPT_BALANCE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_G].name = M_NAME_BALANCE_G; sod[OPT_BALANCE_G].title = M_TITLE_BALANCE_G; sod[OPT_BALANCE_G].desc = M_DESC_BALANCE_G; sod[OPT_BALANCE_G].unit = SANE_UNIT_PERCENT; sod[OPT_BALANCE_G].cap |= SANE_CAP_ADVANCED; sod[OPT_BALANCE_G].constraint.range = &md->balance_range; if ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) sod[OPT_BALANCE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_B].name = M_NAME_BALANCE_B; sod[OPT_BALANCE_B].title = M_TITLE_BALANCE_B; sod[OPT_BALANCE_B].desc = M_DESC_BALANCE_B; sod[OPT_BALANCE_B].unit = SANE_UNIT_PERCENT; sod[OPT_BALANCE_B].cap |= SANE_CAP_ADVANCED; sod[OPT_BALANCE_B].constraint.range = &md->balance_range; if ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) sod[OPT_BALANCE_B].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_FW].name = M_NAME_BALANCE_FW; sod[OPT_BALANCE_FW].title = M_TITLE_BALANCE_FW; sod[OPT_BALANCE_FW].desc = M_DESC_BALANCE_FW; sod[OPT_BALANCE_FW].type = SANE_TYPE_BUTTON; sod[OPT_BALANCE_FW].size = 0; sod[OPT_BALANCE_FW].cap |= SANE_CAP_ADVANCED; sod[OPT_BALANCE_FW].constraint_type = SANE_CONSTRAINT_NONE; if ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) sod[OPT_BALANCE_FW].cap |= SANE_CAP_INACTIVE; } status = set_option_dependencies(ms, sod, val); if ( status != SANE_STATUS_GOOD ) return status; return SANE_STATUS_GOOD; } /*---------- set_option_dependencies() ---------------------------------------*/ static SANE_Status set_option_dependencies(Microtek2_Scanner *ms, SANE_Option_Descriptor *sod, Option_Value *val) { Microtek2_Device *md; md = ms->dev; DBG(40, "set_option_dependencies: val=%p, sod=%p, mode=%s\n", (void *) val, (void *) sod, val[OPT_MODE].s); if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_COLOR) == 0 ) { /* activate brightness,..., deactivate halftone pattern */ /* and threshold */ sod[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; sod[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; sod[OPT_CHANNEL].cap &= ~SANE_CAP_INACTIVE; sod[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap &= ~SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; sod[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; sod[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; if ( md->bitdepth_list[0] != 1 ) sod[OPT_BITDEPTH].cap &= ~SANE_CAP_INACTIVE; else sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; if ( ! ( strncmp(md->opts.colorbalance_adjust, "off", 3) == 0 ) ) { sod[OPT_BALANCE_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_BALANCE_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_BALANCE_B].cap &= ~SANE_CAP_INACTIVE; sod[OPT_BALANCE_FW].cap &= ~SANE_CAP_INACTIVE; } /* reset options values that are inactive to their default */ val[OPT_THRESHOLD].w = MD_THRESHOLD_DEFAULT; } else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_GRAY) == 0 ) { sod[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; sod[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; sod[OPT_CHANNEL].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap &= ~SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; sod[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; sod[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; if ( md->bitdepth_list[0] != 1 ) sod[OPT_BITDEPTH].cap &= ~SANE_CAP_INACTIVE; else sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_B].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_FW].cap |= SANE_CAP_INACTIVE; /* reset options values that are inactive to their default */ if ( val[OPT_CHANNEL].s ) free((void *) val[OPT_CHANNEL].s); val[OPT_CHANNEL].s = strdup((SANE_String) MD_CHANNEL_MASTER); } else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_HALFTONE) == 0 ) { sod[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; sod[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; sod[OPT_CHANNEL].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; sod[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE; sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_B].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_FW].cap |= SANE_CAP_INACTIVE; /* reset options values that are inactive to their default */ val[OPT_BRIGHTNESS].w = MD_BRIGHTNESS_DEFAULT; val[OPT_CONTRAST].w = MD_CONTRAST_DEFAULT; if ( val[OPT_CHANNEL].s ) free((void *) val[OPT_CHANNEL].s); val[OPT_CHANNEL].s = strdup((SANE_String) MD_CHANNEL_MASTER); val[OPT_SHADOW].w = MD_SHADOW_DEFAULT; val[OPT_MIDTONE].w = MD_MIDTONE_DEFAULT; val[OPT_HIGHLIGHT].w = MD_HIGHLIGHT_DEFAULT; val[OPT_EXPOSURE].w = MD_EXPOSURE_DEFAULT; val[OPT_THRESHOLD].w = MD_THRESHOLD_DEFAULT; } else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_LINEART) == 0 ) { sod[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; sod[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; sod[OPT_CHANNEL].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; sod[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; if ( val[OPT_AUTOADJUST].w == SANE_FALSE ) sod[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; else sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; sod[OPT_AUTOADJUST].cap &= ~SANE_CAP_INACTIVE; sod[OPT_BALANCE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_B].cap |= SANE_CAP_INACTIVE; sod[OPT_BALANCE_FW].cap |= SANE_CAP_INACTIVE; /* reset options values that are inactive to their default */ val[OPT_BRIGHTNESS].w = MD_BRIGHTNESS_DEFAULT; val[OPT_CONTRAST].w = MD_CONTRAST_DEFAULT; if ( val[OPT_CHANNEL].s ) free((void *) val[OPT_CHANNEL].s); val[OPT_CHANNEL].s = strdup((SANE_String) MD_CHANNEL_MASTER); val[OPT_SHADOW].w = MD_SHADOW_DEFAULT; val[OPT_MIDTONE].w = MD_MIDTONE_DEFAULT; val[OPT_HIGHLIGHT].w = MD_HIGHLIGHT_DEFAULT; val[OPT_EXPOSURE].w = MD_EXPOSURE_DEFAULT; } else { DBG(1, "set_option_dependencies: unknown mode '%s'\n", val[OPT_MODE].s ); return SANE_STATUS_INVAL; } /* these ones are always inactive if the mode changes */ sod[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_B].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_B].cap |= SANE_CAP_INACTIVE; /* reset options values that are inactive to their default */ val[OPT_SHADOW_R].w = val[OPT_SHADOW_G].w = val[OPT_SHADOW_B].w = MD_SHADOW_DEFAULT; val[OPT_MIDTONE_R].w = val[OPT_MIDTONE_G].w = val[OPT_MIDTONE_B].w = MD_MIDTONE_DEFAULT; val[OPT_HIGHLIGHT_R].w = val[OPT_HIGHLIGHT_G].w = val[OPT_HIGHLIGHT_B].w = MD_HIGHLIGHT_DEFAULT; val[OPT_EXPOSURE_R].w = val[OPT_EXPOSURE_G].w = val[OPT_EXPOSURE_B].w = MD_EXPOSURE_DEFAULT; if ( SANE_OPTION_IS_SETTABLE(sod[OPT_GAMMA_MODE].cap) ) { restore_gamma_options(sod, val); } return SANE_STATUS_GOOD; } /*---------- sane_control_option() -------------------------------------------*/ SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info) { Microtek2_Scanner *ms = handle; Microtek2_Device *md; Microtek2_Info *mi; Option_Value *val; SANE_Option_Descriptor *sod; SANE_Status status; md = ms->dev; val = &ms->val[0]; sod = &ms->sod[0]; mi = &md->info[md->scan_source]; if ( ms->scanning ) return SANE_STATUS_DEVICE_BUSY; if ( option < 0 || option >= NUM_OPTIONS ) { DBG(100, "sane_control_option: option %d; action %d \n", option, action); DBG(10, "sane_control_option: option %d invalid\n", option); return SANE_STATUS_INVAL; } if ( ! SANE_OPTION_IS_ACTIVE(ms->sod[option].cap) ) { DBG(100, "sane_control_option: option %d; action %d \n", option, action); DBG(10, "sane_control_option: option %d not active\n", option); return SANE_STATUS_INVAL; } if ( info ) *info = 0; switch ( action ) { case SANE_ACTION_GET_VALUE: /* read out option values */ switch ( option ) { /* word options */ case OPT_BITDEPTH: case OPT_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_THRESHOLD: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_PREVIEW: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_SHADOW: case OPT_SHADOW_R: case OPT_SHADOW_G: case OPT_SHADOW_B: case OPT_MIDTONE: case OPT_MIDTONE_R: case OPT_MIDTONE_G: case OPT_MIDTONE_B: case OPT_HIGHLIGHT: case OPT_HIGHLIGHT_R: case OPT_HIGHLIGHT_G: case OPT_HIGHLIGHT_B: case OPT_EXPOSURE: case OPT_EXPOSURE_R: case OPT_EXPOSURE_G: case OPT_EXPOSURE_B: case OPT_GAMMA_SCALAR: case OPT_GAMMA_SCALAR_R: case OPT_GAMMA_SCALAR_G: case OPT_GAMMA_SCALAR_B: case OPT_BALANCE_R: case OPT_BALANCE_G: case OPT_BALANCE_B: *(SANE_Word *) value = val[option].w; if (sod[option].type == SANE_TYPE_FIXED ) DBG(50, "sane_control_option: opt=%d, act=%d, val=%f\n", option, action, SANE_UNFIX(val[option].w)); else DBG(50, "sane_control_option: opt=%d, act=%d, val=%d\n", option, action, val[option].w); return SANE_STATUS_GOOD; /* boolean options */ case OPT_RESOLUTION_BIND: case OPT_DISABLE_BACKTRACK: case OPT_CALIB_BACKEND: case OPT_LIGHTLID35: case OPT_GAMMA_BIND: case OPT_AUTOADJUST: *(SANE_Bool *) value = val[option].w; DBG(50, "sane_control_option: opt=%d, act=%d, val=%d\n", option, action, val[option].w); return SANE_STATUS_GOOD; /* string options */ case OPT_SOURCE: case OPT_MODE: case OPT_HALFTONE: case OPT_CHANNEL: case OPT_GAMMA_MODE: strcpy(value, val[option].s); DBG(50, "sane_control_option: opt=%d, act=%d, val=%s\n", option, action, val[option].s); return SANE_STATUS_GOOD; /* word array options */ case OPT_GAMMA_CUSTOM: case OPT_GAMMA_CUSTOM_R: case OPT_GAMMA_CUSTOM_G: case OPT_GAMMA_CUSTOM_B: memcpy(value, val[option].wa, sod[option].size); return SANE_STATUS_GOOD; /* button options */ case OPT_TOGGLELAMP: case OPT_BALANCE_FW: return SANE_STATUS_GOOD; /* others */ case OPT_NUM_OPTS: *(SANE_Word *) value = NUM_OPTIONS; return SANE_STATUS_GOOD; default: return SANE_STATUS_UNSUPPORTED; } /* NOTREACHED */ /* break; */ case SANE_ACTION_SET_VALUE: /* set option values */ if ( ! SANE_OPTION_IS_SETTABLE(sod[option].cap) ) { DBG(100, "sane_control_option: option %d; action %d \n", option, action); DBG(10, "sane_control_option: trying to set unsettable option\n"); return SANE_STATUS_INVAL; } /* do not check OPT_BR_Y, xscanimage sometimes tries to set */ /* it to a too large value; bug in xscanimage ? */ /* if ( option != OPT_BR_Y ) { */ status = sanei_constrain_value(ms->sod + option, value, info); if (status != SANE_STATUS_GOOD) { DBG(10, "sane_control_option: invalid option value\n"); return status; } /* } */ switch ( sod[option].type ) { case SANE_TYPE_BOOL: DBG(50, "sane_control_option: option=%d, action=%d, value=%d\n", option, action, *(SANE_Int *) value); if ( ! ( ( *(SANE_Bool *) value == SANE_TRUE ) || ( *(SANE_Bool *) value == SANE_FALSE ) ) ) { DBG(10, "sane_control_option: invalid BOOL option value\n"); return SANE_STATUS_INVAL; } if ( val[option].w == *(SANE_Bool *) value ) /* no change */ return SANE_STATUS_GOOD; val[option].w = *(SANE_Bool *) value; break; case SANE_TYPE_INT: if ( sod[option].size == sizeof(SANE_Int) ) { /* word option */ DBG(50, "sane_control_option: option=%d, action=%d, " "value=%d\n", option, action, *(SANE_Int *) value); if ( val[option].w == *(SANE_Int *) value ) /* no change */ return SANE_STATUS_GOOD; val[option].w = *(SANE_Int *) value; } else { /* word array option */ memcpy(val[option].wa, value, sod[option].size); } break; case SANE_TYPE_FIXED: DBG(50, "sane_control_option: option=%d, action=%d, value=%f\n", option, action, SANE_UNFIX( *(SANE_Fixed *) value)); if ( val[option].w == *(SANE_Fixed *) value ) /* no change */ return SANE_STATUS_GOOD; val[option].w = *(SANE_Fixed *) value; break; case SANE_TYPE_STRING: DBG(50, "sane_control_option: option=%d, action=%d, value=%s\n", option, action, (SANE_String) value); if ( strcmp(val[option].s, (SANE_String) value) == 0 ) return SANE_STATUS_GOOD; /* no change */ if ( val[option].s ) free((void *) val[option].s); val[option].s = strdup(value); if ( val[option].s == NULL ) { DBG(1, "sane_control_option: strdup failed\n"); return SANE_STATUS_NO_MEM; } break; case SANE_TYPE_BUTTON: break; default: DBG(1, "sane_control_option: unknown type %d\n", sod[option].type); break; } switch ( option ) { case OPT_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if ( info ) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_DISABLE_BACKTRACK: case OPT_CALIB_BACKEND: case OPT_LIGHTLID35: case OPT_PREVIEW: case OPT_BRIGHTNESS: case OPT_THRESHOLD: case OPT_CONTRAST: case OPT_EXPOSURE: case OPT_EXPOSURE_R: case OPT_EXPOSURE_G: case OPT_EXPOSURE_B: case OPT_GAMMA_SCALAR: case OPT_GAMMA_SCALAR_R: case OPT_GAMMA_SCALAR_G: case OPT_GAMMA_SCALAR_B: case OPT_GAMMA_CUSTOM: case OPT_GAMMA_CUSTOM_R: case OPT_GAMMA_CUSTOM_G: case OPT_GAMMA_CUSTOM_B: case OPT_HALFTONE: case OPT_BALANCE_R: case OPT_BALANCE_G: case OPT_BALANCE_B: return SANE_STATUS_GOOD; case OPT_BITDEPTH: /* If the bitdepth has changed we must change the size of */ /* the gamma table if the device does not support gamma */ /* tables. This will hopefully cause no trouble if the */ /* mode is one bit */ if ( md->model_flags & MD_NO_GAMMA ) { int max_gamma_value; int size; int color; int i; size = (int) pow(2.0, (double) val[OPT_BITDEPTH].w) - 1; max_gamma_value = size - 1; for ( color = 0; color < 4; color++ ) { for ( i = 0; i < max_gamma_value; i++ ) md->custom_gamma_table[color][i] = (SANE_Int) i; } md->custom_gamma_range.max = (SANE_Int) max_gamma_value; sod[OPT_GAMMA_CUSTOM].size = size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_R].size = size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_G].size = size * sizeof (SANE_Int); sod[OPT_GAMMA_CUSTOM_B].size = size * sizeof (SANE_Int); if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; } if ( info ) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_SOURCE: if ( info ) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; if ( strcmp(val[option].s, MD_SOURCESTRING_FLATBED) == 0 ) md->scan_source = MD_SOURCE_FLATBED; else if ( strcmp(val[option].s, MD_SOURCESTRING_TMA) == 0 ) md->scan_source = MD_SOURCE_TMA; else if ( strcmp(val[option].s, MD_SOURCESTRING_ADF) == 0 ) md->scan_source = MD_SOURCE_ADF; else if ( strcmp(val[option].s, MD_SOURCESTRING_STRIPE) == 0 ) md->scan_source = MD_SOURCE_STRIPE; else if ( strcmp(val[option].s, MD_SOURCESTRING_SLIDE) == 0 ) md->scan_source = MD_SOURCE_SLIDE; else { DBG(1, "sane_control_option: unsupported option %s\n", val[option].s); return SANE_STATUS_UNSUPPORTED; } init_options(ms, md->scan_source); return SANE_STATUS_GOOD; case OPT_MODE: if ( info ) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; status = set_option_dependencies(ms, sod, val); /* Options with side effects need special treatment. They are */ /* reset, even if they were set by set_option_dependencies(): */ /* if we have more than one color depth activate this option */ if ( md->bitdepth_list[0] == 1 ) sod[OPT_BITDEPTH].cap |= SANE_CAP_INACTIVE; if ( strncmp(md->opts.auto_adjust, "off", 3) == 0 ) sod[OPT_AUTOADJUST].cap |= SANE_CAP_INACTIVE; if ( status != SANE_STATUS_GOOD ) return status; return SANE_STATUS_GOOD; case OPT_CHANNEL: if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; if ( strcmp(val[option].s, MD_CHANNEL_MASTER) == 0 ) { sod[OPT_SHADOW].cap &= ~SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap &= ~SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT].cap &= ~SANE_CAP_INACTIVE; sod[OPT_EXPOSURE].cap &= ~SANE_CAP_INACTIVE; sod[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_B].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_B].cap |= SANE_CAP_INACTIVE; } else if ( strcmp(val[option].s, MD_CHANNEL_RED) == 0 ) { sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_MIDTONE_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_B].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_B].cap |= SANE_CAP_INACTIVE; } else if ( strcmp(val[option].s, MD_CHANNEL_GREEN) == 0 ) { sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_MIDTONE_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_SHADOW_B].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_B].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_B].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_B].cap |= SANE_CAP_INACTIVE; } else if ( strcmp(val[option].s, MD_CHANNEL_BLUE) == 0 ) { sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_R].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_R].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_R].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_G].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_G].cap |= SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_G].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW_B].cap &= ~SANE_CAP_INACTIVE; sod[OPT_MIDTONE_B].cap &= ~SANE_CAP_INACTIVE; sod[OPT_HIGHLIGHT_B].cap &= ~SANE_CAP_INACTIVE; sod[OPT_EXPOSURE_B].cap &= ~SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; case OPT_GAMMA_MODE: restore_gamma_options(sod, val); if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_GAMMA_BIND: restore_gamma_options(sod, val); if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_SHADOW: case OPT_SHADOW_R: case OPT_SHADOW_G: case OPT_SHADOW_B: if ( val[option].w >= val[option + 1].w ) { val[option + 1].w = val[option].w + 1; if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; } if ( val[option + 1].w >= val[option + 2].w ) val[option + 2].w = val[option + 1].w + 1; return SANE_STATUS_GOOD; case OPT_MIDTONE: case OPT_MIDTONE_R: case OPT_MIDTONE_G: case OPT_MIDTONE_B: if ( val[option].w <= val[option - 1].w ) { val[option - 1].w = val[option].w - 1; if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; } if ( val[option].w >= val[option + 1].w ) { val[option + 1].w = val[option].w + 1; if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_HIGHLIGHT: case OPT_HIGHLIGHT_R: case OPT_HIGHLIGHT_G: case OPT_HIGHLIGHT_B: if ( val[option].w <= val[option - 1].w ) { val[option - 1].w = val[option].w - 1; if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; } if ( val[option - 1].w <= val[option - 2].w ) val[option - 2].w = val[option - 1].w - 1; return SANE_STATUS_GOOD; case OPT_RESOLUTION_BIND: if ( ms->val[option].w == SANE_FALSE ) { ms->sod[OPT_Y_RESOLUTION].cap &= ~SANE_CAP_INACTIVE; } else { ms->sod[OPT_Y_RESOLUTION].cap |= SANE_CAP_INACTIVE; } if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_TOGGLELAMP: status = scsi_read_system_status(md, -1); if ( status != SANE_STATUS_GOOD ) return SANE_STATUS_IO_ERROR; md->status.flamp ^= 1; status = scsi_send_system_status(md, -1); if ( status != SANE_STATUS_GOOD ) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; case OPT_AUTOADJUST: if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; if ( ms->val[option].w == SANE_FALSE ) ms->sod[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; else ms->sod[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; return SANE_STATUS_GOOD; case OPT_BALANCE_FW: val[OPT_BALANCE_R].w = SANE_FIX((uint8_t)( (float)mi->balance[0] / 2.55 ) ); val[OPT_BALANCE_G].w = SANE_FIX((uint8_t)( (float)mi->balance[1] / 2.55 ) ); val[OPT_BALANCE_B].w = SANE_FIX((uint8_t)( (float)mi->balance[2] / 2.55 ) ); if ( info ) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; default: return SANE_STATUS_UNSUPPORTED; } #if 0 break; #endif default: DBG(1, "sane_control_option: Unsupported action %d\n", action); return SANE_STATUS_UNSUPPORTED; } } /*---------- sane_get_option_descriptor() ------------------------------------*/ const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle handle, SANE_Int n) { Microtek2_Scanner *ms = handle; DBG(255, "sane_get_option_descriptor: handle=%p, sod=%p, opt=%d\n", (void *) handle, (void *) ms->sod, n); if ( n < 0 || n >= NUM_OPTIONS ) { DBG(30, "sane_get_option_descriptor: invalid option %d\n", n); return NULL; } return &ms->sod[n]; } /*---------- restore_gamma_options() -----------------------------------------*/ static SANE_Status restore_gamma_options(SANE_Option_Descriptor *sod, Option_Value *val) { DBG(40, "restore_gamma_options: val=%p, sod=%p\n", (void *) val, (void *) sod); /* if we dont have a gamma table return immediately */ if ( ! val[OPT_GAMMA_MODE].s ) return SANE_STATUS_GOOD; if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_COLOR) == 0 ) { sod[OPT_GAMMA_MODE].cap &= ~SANE_CAP_INACTIVE; if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_LINEAR) == 0 ) { sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; } else if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_SCALAR) == 0 ) { sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; if ( val[OPT_GAMMA_BIND].w == SANE_TRUE ) { sod[OPT_GAMMA_SCALAR].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; } else { sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_B].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; } } else if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_CUSTOM) == 0 ) { sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; if ( val[OPT_GAMMA_BIND].w == SANE_TRUE ) { sod[OPT_GAMMA_CUSTOM].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; } else { sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_B].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; } } } else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_GRAY) == 0 ) { sod[OPT_GAMMA_MODE].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_LINEAR) == 0 ) { sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; } else if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_SCALAR) == 0 ) { sod[OPT_GAMMA_SCALAR].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; } else if ( strcmp(val[OPT_GAMMA_MODE].s, MD_GAMMAMODE_CUSTOM) == 0 ) { sod[OPT_GAMMA_CUSTOM].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; } } else if ( strcmp(val[OPT_MODE].s, MD_MODESTRING_HALFTONE) == 0 || strcmp(val[OPT_MODE].s, MD_MODESTRING_LINEART) == 0 ) { /* reset gamma to default */ if ( val[OPT_GAMMA_MODE].s ) free((void *) val[OPT_GAMMA_MODE].s); val[OPT_GAMMA_MODE].s = strdup(MD_GAMMAMODE_LINEAR); sod[OPT_GAMMA_MODE].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_SCALAR_B].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_CUSTOM_B].cap |= SANE_CAP_INACTIVE; } else DBG(1, "restore_gamma_options: unknown mode %s\n", val[OPT_MODE].s); return SANE_STATUS_GOOD; } /*---------- calculate_sane_params() -----------------------------------------*/ static SANE_Status calculate_sane_params(Microtek2_Scanner *ms) { Microtek2_Device *md; Microtek2_Info *mi; DBG(30, "calculate_sane_params: ms=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; if ( ! mi->onepass && ms->mode == MS_MODE_COLOR ) { if ( ms->current_pass == 1 ) ms->params.format = SANE_FRAME_RED; else if ( ms->current_pass == 2 ) ms->params.format = SANE_FRAME_GREEN; else if ( ms->current_pass == 3 ) ms->params.format = SANE_FRAME_BLUE; else { DBG(1, "calculate_sane_params: invalid pass number %d\n", ms->current_pass); return SANE_STATUS_IO_ERROR; } } else if ( mi->onepass && ms->mode == MS_MODE_COLOR ) ms->params.format = SANE_FRAME_RGB; else ms->params.format = SANE_FRAME_GRAY; if ( ! mi->onepass && ms->mode == MS_MODE_COLOR && ms->current_pass < 3 ) ms->params.last_frame = SANE_FALSE; else ms->params.last_frame = SANE_TRUE; ms->params.lines = ms->src_remaining_lines; ms->params.pixels_per_line = ms->ppl; ms->params.bytes_per_line = ms->real_bpl; ms->params.depth = ms->bits_per_pixel_out; return SANE_STATUS_GOOD; } /*---------- get_calib_params() ----------------------------------------------*/ static void get_calib_params(Microtek2_Scanner *ms) { Microtek2_Device *md; Microtek2_Info *mi; DBG(30, "get_calib_params: handle=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; if ( md->model_flags & MD_CALIB_DIVISOR_600 ) { if ( ms->x_resolution_dpi <= 600 ) mi->calib_divisor = 2; else mi->calib_divisor = 1; } DBG(30, "Calib Divisor: %d\n", mi->calib_divisor); ms->x_resolution_dpi = mi->opt_resolution / mi->calib_divisor; ms->y_resolution_dpi = mi->opt_resolution / 5; /* ignore dust particles */ ms->x1_dots = 0; ms->y1_dots = mi->calib_white; ms->width_dots = mi->geo_width; if ( md->shading_length != 0 ) ms->height_dots = md->shading_length; else ms->height_dots = mi->calib_space; ms->mode = MS_MODE_COLOR; if ( mi->depth & MI_HASDEPTH_16 ) ms->depth = 16; else if ( mi->depth & MI_HASDEPTH_14 ) ms->depth = 14; else if ( mi->depth & MI_HASDEPTH_12 ) ms->depth = 12; else if ( mi->depth & MI_HASDEPTH_10 ) ms->depth = 10; else ms->depth = 8; ms->stay = 0; if ( mi->calib_space < 10 ) ms->stay = 1; ms->rawdat = 1; ms->quality = 1; ms->fastscan = 0; /* ms->scan_source = md->scan_source; */ ms->scan_source = 0; ms->brightness_m = ms->brightness_r = ms->brightness_g = ms->brightness_b = 128; ms->exposure_m = ms->exposure_r = ms->exposure_g = ms->exposure_b = 0; ms->contrast_m = ms->contrast_r = ms->contrast_g = ms->contrast_b = 128; ms->shadow_m = ms->shadow_r = ms->shadow_g = ms->shadow_b = 0; ms->midtone_m = ms->midtone_r = ms->midtone_g = ms->midtone_b = 128; ms->highlight_m = ms->highlight_r = ms->highlight_g = ms->highlight_b = 255; return; } /*---------- get_scan_parameters () ------------------------------------------*/ static SANE_Status get_scan_parameters(Microtek2_Scanner *ms) { Microtek2_Device *md; Microtek2_Info *mi; double dpm; /* dots per millimeter */ int x2_dots; int y2_dots; int i; DBG(30, "get_scan_parameters: handle=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; get_scan_mode_and_depth(ms, &ms->mode, &ms->depth, &ms->bits_per_pixel_in, &ms->bits_per_pixel_out); /* get the scan_source */ if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_FLATBED) == 0 ) ms->scan_source = MS_SOURCE_FLATBED; else if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_ADF) == 0 ) ms->scan_source = MS_SOURCE_ADF; else if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_TMA) == 0 ) ms->scan_source = MS_SOURCE_TMA; else if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_STRIPE) == 0 ) ms->scan_source = MS_SOURCE_STRIPE; else if ( strcmp(ms->val[OPT_SOURCE].s, MD_SOURCESTRING_SLIDE) == 0 ) ms->scan_source = MS_SOURCE_SLIDE; /* enable/disable backtracking */ if ( ms->val[OPT_DISABLE_BACKTRACK].w == SANE_TRUE ) ms->no_backtracking = 1; else ms->no_backtracking = 0; /* turn off the lamp during a scan */ if ( ms->val[OPT_LIGHTLID35].w == SANE_TRUE ) ms->lightlid35 = 1; else ms->lightlid35 = 0; /* automatic adjustment of threshold */ if ( ms->val[OPT_AUTOADJUST].w == SANE_TRUE) ms->auto_adjust = 1; else ms->auto_adjust = 0; /* color calibration by backend */ if ( ms->val[OPT_CALIB_BACKEND].w == SANE_TRUE ) ms->calib_backend = 1; else ms->calib_backend = 0; /* if halftone mode select halftone pattern */ if ( ms->mode == MS_MODE_HALFTONE ) { i = 0; while ( strcmp(md->halftone_mode_list[i], ms->val[OPT_HALFTONE].s) ) ++i; ms->internal_ht_index = i; } /* if lineart get the value for threshold */ if ( ms->mode == MS_MODE_LINEART || ms->mode == MS_MODE_LINEARTFAKE) ms->threshold = (uint8_t) ms->val[OPT_THRESHOLD].w; else ms->threshold = (uint8_t) M_THRESHOLD_DEFAULT; DBG(30, "get_scan_parameters: mode=%d, depth=%d, bpp_in=%d, bpp_out=%d\n", ms->mode, ms->depth, ms->bits_per_pixel_in, ms->bits_per_pixel_out); /* calculate positions, width and height in dots */ /* check for impossible values */ /* ensure a minimum scan area of 10 x 10 pixels */ dpm = (double) mi->opt_resolution / MM_PER_INCH; ms->x1_dots = (SANE_Int) ( SANE_UNFIX(ms->val[OPT_TL_X].w) * dpm + 0.5 ); if ( ms->x1_dots > ( mi->geo_width - 10 ) ) ms->x1_dots = ( mi->geo_width - 10 ); ms->y1_dots = (SANE_Int) ( SANE_UNFIX(ms->val[OPT_TL_Y].w) * dpm + 0.5 ); if ( ms->y1_dots > ( mi->geo_height - 10 ) ) ms->y1_dots = ( mi->geo_height - 10 ); x2_dots = (int) ( SANE_UNFIX(ms->val[OPT_BR_X].w) * dpm + 0.5 ); if ( x2_dots >= mi->geo_width ) x2_dots = mi->geo_width - 1; y2_dots = (int) ( SANE_UNFIX(ms->val[OPT_BR_Y].w) * dpm + 0.5 ); if ( y2_dots >= mi->geo_height ) y2_dots = mi->geo_height - 1; ms->width_dots = x2_dots - ms->x1_dots; if ( md->model_flags && MD_OFFSET_2 ) /* this firmware has problems with */ if ( ( ms->width_dots % 2 ) == 1 ) /* odd pixel numbers */ ms->width_dots -= 1; if ( ms->width_dots < 10 ) ms->width_dots = 10; ms->height_dots = y2_dots - ms->y1_dots; if ( ms->height_dots < 10 ) ms->height_dots = 10; /*test!!!*/ /* ms->y1_dots -= 50;*/ /* take scanning direction into account */ if ((mi->direction & MI_DATSEQ_RTOL) == 1) ms->x1_dots = mi->geo_width - ms->x1_dots - ms->width_dots; if ( ms->val[OPT_RESOLUTION_BIND].w == SANE_TRUE ) { ms->x_resolution_dpi = (SANE_Int) (SANE_UNFIX(ms->val[OPT_RESOLUTION].w) + 0.5); ms->y_resolution_dpi = (SANE_Int) (SANE_UNFIX(ms->val[OPT_RESOLUTION].w) + 0.5); } else { ms->x_resolution_dpi = (SANE_Int) (SANE_UNFIX(ms->val[OPT_RESOLUTION].w) + 0.5); ms->y_resolution_dpi = (SANE_Int) (SANE_UNFIX(ms->val[OPT_Y_RESOLUTION].w) + 0.5); } if ( ms->x_resolution_dpi < 10 ) ms->x_resolution_dpi = 10; if ( ms->y_resolution_dpi < 10 ) ms->y_resolution_dpi = 10; DBG(30, "get_scan_parameters: yres=%d, x1=%d, width=%d, y1=%d, height=%d\n", ms->y_resolution_dpi, ms->x1_dots, ms->width_dots, ms->y1_dots, ms->height_dots); /* Preview mode */ if ( ms->val[OPT_PREVIEW].w == SANE_TRUE ) { ms->fastscan = SANE_TRUE; ms->quality = SANE_FALSE; } else { ms->fastscan = SANE_FALSE; ms->quality = SANE_TRUE; } ms->rawdat = 0; /* brightness, contrast, values 1,..,255 */ ms->brightness_m = (uint8_t) (SANE_UNFIX(ms->val[OPT_BRIGHTNESS].w) / SANE_UNFIX(md->percentage_range.max) * 254.0) + 1; ms->brightness_r = ms->brightness_g = ms->brightness_b = ms->brightness_m; ms->contrast_m = (uint8_t) (SANE_UNFIX(ms->val[OPT_CONTRAST].w) / SANE_UNFIX(md->percentage_range.max) * 254.0) + 1; ms->contrast_r = ms->contrast_g = ms->contrast_b = ms->contrast_m; /* shadow, midtone, highlight, exposure */ ms->shadow_m = (uint8_t) ms->val[OPT_SHADOW].w; ms->shadow_r = (uint8_t) ms->val[OPT_SHADOW_R].w; ms->shadow_g = (uint8_t) ms->val[OPT_SHADOW_G].w; ms->shadow_b = (uint8_t) ms->val[OPT_SHADOW_B].w; ms->midtone_m = (uint8_t) ms->val[OPT_MIDTONE].w; ms->midtone_r = (uint8_t) ms->val[OPT_MIDTONE_R].w; ms->midtone_g = (uint8_t) ms->val[OPT_MIDTONE_G].w; ms->midtone_b = (uint8_t) ms->val[OPT_MIDTONE_B].w; ms->highlight_m = (uint8_t) ms->val[OPT_HIGHLIGHT].w; ms->highlight_r = (uint8_t) ms->val[OPT_HIGHLIGHT_R].w; ms->highlight_g = (uint8_t) ms->val[OPT_HIGHLIGHT_G].w; ms->highlight_b = (uint8_t) ms->val[OPT_HIGHLIGHT_B].w; ms->exposure_m = (uint8_t) (ms->val[OPT_EXPOSURE].w / 2); ms->exposure_r = (uint8_t) (ms->val[OPT_EXPOSURE_R].w / 2); ms->exposure_g = (uint8_t) (ms->val[OPT_EXPOSURE_G].w / 2); ms->exposure_b = (uint8_t) (ms->val[OPT_EXPOSURE_B].w / 2); ms->gamma_mode = strdup( (char *) ms->val[OPT_GAMMA_MODE].s); ms->balance[0] = (uint8_t) (SANE_UNFIX(ms->val[OPT_BALANCE_R].w)); ms->balance[1] = (uint8_t) (SANE_UNFIX(ms->val[OPT_BALANCE_G].w)); ms->balance[2] = (uint8_t) (SANE_UNFIX(ms->val[OPT_BALANCE_B].w)); DBG(255, "get_scan_parameters:ms->balance[0]=%d,[1]=%d,[2]=%d\n", ms->balance[0], ms->balance[1], ms->balance[2]); return SANE_STATUS_GOOD; } /*---------- get_scan_mode_and_depth() ---------------------------------------*/ static SANE_Status get_scan_mode_and_depth(Microtek2_Scanner *ms, int *mode, int *depth, int *bits_per_pixel_in, int *bits_per_pixel_out) { /* This function translates the strings for the possible modes and */ /* bitdepth into a more conveniant format as needed for SET WINDOW. */ /* bits_per_pixel is the number of bits per color one pixel needs */ /* when transferred from the scanner, bits_perpixel_out is the */ /* number of bits per color one pixel uses when transferred to the */ /* frontend. These may be different. For example, with a depth of 4 */ /* two pixels per byte are transferred from the scanner, but only one */ /* pixel per byte is transferred to the frontend. */ /* If lineart_fake is set to !=0, we need the parameters for a */ /* grayscale scan, because the scanner has no lineart mode */ Microtek2_Device *md; Microtek2_Info *mi; DBG(30, "get_scan_mode_and_depth: handle=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_COLOR) == 0 ) *mode = MS_MODE_COLOR; else if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_GRAY) == 0 ) *mode = MS_MODE_GRAY; else if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_HALFTONE) == 0) *mode = MS_MODE_HALFTONE; else if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_LINEART) == 0 ) { if ( MI_LINEART_NONE(mi->scanmode) || ms->val[OPT_AUTOADJUST].w == SANE_TRUE || md->model_flags & MD_READ_CONTROL_BIT) *mode = MS_MODE_LINEARTFAKE; else *mode = MS_MODE_LINEART; } else { DBG(1, "get_scan_mode_and_depth: Unknown mode %s\n", ms->val[OPT_MODE].s); return SANE_STATUS_INVAL; } if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_COLOR) == 0 || strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_GRAY) == 0 ) { if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_16 ) { *depth = 16; *bits_per_pixel_in = *bits_per_pixel_out = 16; } else if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_14 ) { *depth = 14; *bits_per_pixel_in = *bits_per_pixel_out = 16; } else if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_12 ) { *depth = 12; *bits_per_pixel_in = *bits_per_pixel_out = 16; } else if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_10 ) { *depth = 10; *bits_per_pixel_in = *bits_per_pixel_out = 16; } else if ( ms->val[OPT_BITDEPTH].w == MD_DEPTHVAL_8 ) { *depth = 8; *bits_per_pixel_in = *bits_per_pixel_out = 8; } else if ( ms->val[OPT_MODE].w == MD_DEPTHVAL_4 ) { *depth = 4; *bits_per_pixel_in = 4; *bits_per_pixel_out = 8; } } else if ( strcmp(ms->val[OPT_MODE].s, MD_MODESTRING_HALFTONE) == 0 ) { *depth = 1; *bits_per_pixel_in = *bits_per_pixel_out = 1; } else /* lineart */ { *bits_per_pixel_out = 1; if ( *mode == MS_MODE_LINEARTFAKE ) { *depth = 8; *bits_per_pixel_in = 8; } else { *depth = 1; *bits_per_pixel_in = 1; } } #if 0 if ( ms->val[OPT_PREVIEW].w == SANE_TRUE ) { if ( *depth > 8 ) { *depth = 8; *bits_per_pixel_in = *bits_per_pixel_out = 8; } } #endif DBG(30, "get_scan_mode_and_depth: mode=%d, depth=%d," " bits_pp_in=%d, bits_pp_out=%d, preview=%d\n", *mode, *depth, *bits_per_pixel_in, *bits_per_pixel_out, ms->val[OPT_PREVIEW].w); return SANE_STATUS_GOOD; } /*---------- scsi_wait_for_image() -------------------------------------------*/ static SANE_Status scsi_wait_for_image(Microtek2_Scanner *ms) { int retry = 60; SANE_Status status; DBG(30, "scsi_wait_for_image: ms=%p\n", (void *) ms); while ( retry-- > 0 ) { status = scsi_read_image_status(ms); if (status == SANE_STATUS_DEVICE_BUSY ) { sleep(1); continue; } if ( status == SANE_STATUS_GOOD ) return status; /* status != GOOD && != BUSY */ DBG(1, "scsi_wait_for_image: '%s'\n", sane_strstatus(status)); return status; } /* BUSY after n retries */ DBG(1, "scsi_wait_for_image: '%s'\n", sane_strstatus(status)); return status; } /*---------- scsi_read_gamma() -----------------------------------------------*/ /* currently not used */ /* static SANE_Status scsi_read_gamma(Microtek2_Scanner *ms, int color) { uint8_t readgamma[RG_CMD_L]; uint8_t result[3072]; size_t size; SANE_Bool endiantype; SANE_Status status; RG_CMD(readgamma); ENDIAN_TYPE(endiantype); RG_PCORMAC(readgamma, endiantype); RG_COLOR(readgamma, color); RG_WORD(readgamma, ( ms->dev->lut_entry_size == 1 ) ? 0 : 1); RG_TRANSFERLENGTH(readgamma, (color == 3 ) ? 3072 : 1024); dump_area(readgamma, 10, "ReadGamma"); size = sizeof(result); status = sanei_scsi_cmd(ms->sfd, readgamma, sizeof(readgamma), result, &size); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_read_gamma: (L,R) read_gamma failed: status '%s'\n", sane_strstatus(status)); return status; } dump_area(result, 3072, "Result"); return SANE_STATUS_GOOD; } */ /*---------- scsi_send_gamma() -----------------------------------------------*/ static SANE_Status scsi_send_gamma(Microtek2_Scanner *ms) { SANE_Bool endiantype; SANE_Status status; size_t size; uint8_t *cmd, color; DBG(30, "scsi_send_gamma: pos=%p, size=%d, word=%d, color=%d\n", ms->gamma_table, ms->lut_size_bytes, ms->word, ms->current_color); if ( ( 3 * ms->lut_size_bytes ) <= 0xffff ) /*send Gamma with one command*/ { cmd = (uint8_t *) alloca(SG_CMD_L + 3 * ms->lut_size_bytes); if ( cmd == NULL ) { DBG(1, "scsi_send_gamma: Couldn't get buffer for gamma table\n"); return SANE_STATUS_IO_ERROR; } SG_SET_CMD(cmd); ENDIAN_TYPE(endiantype) SG_SET_PCORMAC(cmd, endiantype); SG_SET_COLOR(cmd, ms->current_color); SG_SET_WORD(cmd, ms->word); SG_SET_TRANSFERLENGTH(cmd, 3 * ms->lut_size_bytes); memcpy(cmd + SG_CMD_L, ms->gamma_table, 3 * ms->lut_size_bytes); size = 3 * ms->lut_size_bytes; if ( md_dump >= 2 ) dump_area2(cmd, SG_CMD_L, "sendgammacmd"); if ( md_dump >= 3 ) dump_area2(cmd + SG_CMD_L, size, "sendgammadata"); status = sanei_scsi_cmd(ms->sfd, cmd, size + SG_CMD_L, NULL, 0); if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_send_gamma: '%s'\n", sane_strstatus(status)); } else /* send gamma with 3 commands, one for each color */ { for ( color = 0; color < 3; color++ ) { cmd = (uint8_t *) alloca(SG_CMD_L + ms->lut_size_bytes); if ( cmd == NULL ) { DBG(1, "scsi_send_gamma: Couldn't get buffer for gamma table\n"); return SANE_STATUS_IO_ERROR; } SG_SET_CMD(cmd); ENDIAN_TYPE(endiantype) SG_SET_PCORMAC(cmd, endiantype); SG_SET_COLOR(cmd, color); SG_SET_WORD(cmd, ms->word); SG_SET_TRANSFERLENGTH(cmd, ms->lut_size_bytes); memcpy(cmd + SG_CMD_L, ms->gamma_table + color * ms->lut_size_bytes, ms->lut_size_bytes); size = ms->lut_size_bytes; if ( md_dump >= 2 ) dump_area2(cmd, SG_CMD_L, "sendgammacmd"); if ( md_dump >= 3 ) dump_area2(cmd + SG_CMD_L, size, "sendgammadata"); status = sanei_scsi_cmd(ms->sfd, cmd, size + SG_CMD_L, NULL, 0); if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_send_gamma: '%s'\n", sane_strstatus(status)); } } return status; } /*---------- scsi_inquiry() --------------------------------------------------*/ static SANE_Status scsi_inquiry(Microtek2_Info *mi, char *device) { SANE_Status status; uint8_t cmd[INQ_CMD_L]; uint8_t *result; uint8_t inqlen; size_t size; int sfd; DBG(30, "scsi_inquiry: mi=%p, device='%s'\n", (void *) mi, device); status = sanei_scsi_open(device, &sfd, scsi_sense_handler, 0); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_inquiry: '%s'\n", sane_strstatus(status)); return status; } INQ_CMD(cmd); INQ_SET_ALLOC(cmd, INQ_ALLOC_L); result = (uint8_t *) alloca(INQ_ALLOC_L); if ( result == NULL ) { DBG(1, "scsi_inquiry: malloc failed\n"); sanei_scsi_close(sfd); return SANE_STATUS_NO_MEM; } size = INQ_ALLOC_L; status = sanei_scsi_cmd(sfd, cmd, sizeof(cmd), result, &size); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_inquiry: '%s'\n", sane_strstatus(status)); sanei_scsi_close(sfd); return status; } INQ_GET_INQLEN(inqlen, result); INQ_SET_ALLOC(cmd, inqlen + INQ_ALLOC_L); result = alloca(inqlen + INQ_ALLOC_L); if ( result == NULL ) { DBG(1, "scsi_inquiry: malloc failed\n"); sanei_scsi_close(sfd); return SANE_STATUS_NO_MEM; } size = inqlen + INQ_ALLOC_L; if (md_dump >= 2 ) dump_area2(cmd, sizeof(cmd), "inquiry"); status = sanei_scsi_cmd(sfd, cmd, sizeof(cmd), result, &size); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_inquiry: cmd '%s'\n", sane_strstatus(status)); sanei_scsi_close(sfd); return status; } sanei_scsi_close(sfd); if (md_dump >= 2 ) { dump_area2((uint8_t *) result, size, "inquiryresult"); dump_area((uint8_t *) result, size, "inquiryresult"); } /* copy results */ INQ_GET_QUAL(mi->device_qualifier, result); INQ_GET_DEVT(mi->device_type, result); INQ_GET_VERSION(mi->scsi_version, result); INQ_GET_VENDOR(mi->vendor, (char *)result); INQ_GET_MODEL(mi->model, (char *)result); INQ_GET_REV(mi->revision, (char *)result); INQ_GET_MODELCODE(mi->model_code, result); return SANE_STATUS_GOOD; } /*---------- scsi_read_attributes() ------------------------------------------*/ static SANE_Status scsi_read_attributes(Microtek2_Info *pmi, char *device, uint8_t scan_source) { SANE_Status status; Microtek2_Info *mi; uint8_t readattributes[RSA_CMD_L]; uint8_t result[RSA_TRANSFERLENGTH]; size_t size; int sfd; mi = &pmi[scan_source]; DBG(30, "scsi_read_attributes: mi=%p, device='%s', source=%d\n", (void *) mi, device, scan_source); RSA_CMD(readattributes); RSA_SETMEDIA(readattributes, scan_source); status = sanei_scsi_open(device, &sfd, scsi_sense_handler, 0); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_read_attributes: open '%s'\n", sane_strstatus(status)); return status; } if (md_dump >= 2 ) dump_area2(readattributes, sizeof(readattributes), "scannerattributes"); size = sizeof(result); status = sanei_scsi_cmd(sfd, readattributes, sizeof(readattributes), result, &size); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_read_attributes: cmd '%s'\n", sane_strstatus(status)); sanei_scsi_close(sfd); return status; } sanei_scsi_close(sfd); /* The X6 appears to lie about the data format for a TMA */ if ( (&pmi[0])->model_code == 0x91 ) result[0] &= 0xfd; /* default value for calib_divisor ... bit49?? */ mi->calib_divisor = 1; /* 9600XL */ if ( (&pmi[0])->model_code == 0xde ) mi->calib_divisor = 2; /* 6400XL has problems in lineart mode*/ if ( (&pmi[0])->model_code == 0x89 ) result[13] &= 0xfe; /* simulate no lineart */ #if 0 result[13] &= 0xfe; /* simulate no lineart */ #endif /* copy all the stuff into the info structure */ RSA_COLOR(mi->color, result); RSA_ONEPASS(mi->onepass, result); RSA_SCANNERTYPE(mi->scanner_type, result); RSA_FEPROM(mi->feprom, result); RSA_DATAFORMAT(mi->data_format, result); RSA_COLORSEQUENCE(mi->color_sequence, result); RSA_NIS(mi->new_image_status, result); RSA_DATSEQ(mi->direction, result); RSA_CCDGAP(mi->ccd_gap, result); RSA_MAX_XRESOLUTION(mi->max_xresolution, result); RSA_MAX_YRESOLUTION(mi->max_yresolution, result); RSA_GEOWIDTH(mi->geo_width, result); RSA_GEOHEIGHT(mi->geo_height, result); RSA_OPTRESOLUTION(mi->opt_resolution, result); RSA_DEPTH(mi->depth, result); /* The X12USL doesn't say that it has 14bit */ if ( (&pmi[0])->model_code == 0xb0 ) mi->depth |= MI_HASDEPTH_14; RSA_SCANMODE(mi->scanmode, result); RSA_CCDPIXELS(mi->ccd_pixels, result); RSA_LUTCAP(mi->lut_cap, result); RSA_DNLDPTRN(mi->has_dnldptrn, result); RSA_GRAINSLCT(mi->grain_slct, result); RSA_SUPPOPT(mi->option_device, result); RSA_CALIBWHITE(mi->calib_white, result); RSA_CALIBSPACE(mi->calib_space, result); RSA_NLENS(mi->nlens, result); RSA_NWINDOWS(mi->nwindows, result); RSA_SHTRNSFEREQU(mi->shtrnsferequ, result); RSA_SCNBTTN(mi->scnbuttn, result); RSA_BUFTYPE(mi->buftype, result); RSA_REDBALANCE(mi->balance[0], result); RSA_GREENBALANCE(mi->balance[1], result); RSA_BLUEBALANCE(mi->balance[2], result); RSA_APSMAXFRAMES(mi->aps_maxframes, result); if (md_dump >= 2 ) dump_area2((uint8_t *) result, sizeof(result), "scannerattributesresults"); if ( md_dump >= 1 && md_dump_clear ) dump_attributes(mi); return SANE_STATUS_GOOD; } /*---------- scsi_read_control_bits() ----------------------------------------*/ static SANE_Status scsi_read_control_bits(Microtek2_Scanner *ms) { SANE_Status status; uint8_t cmd[RCB_CMD_L]; uint32_t byte; int bit; int count_1s; DBG(30, "scsi_read_control_bits: ms=%p, fd=%d\n", (void *) ms, ms->sfd); DBG(30, "ms->control_bytes = %p\n", ms->control_bytes); RCB_SET_CMD(cmd); RCB_SET_LENGTH(cmd, ms->n_control_bytes); if ( md_dump >= 2) dump_area2(cmd, RCB_CMD_L, "readcontrolbits"); status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), ms->control_bytes, &ms->n_control_bytes); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_read_control_bits: cmd '%s'\n", sane_strstatus(status)); return status; } if ( md_dump >= 2) dump_area2(ms->control_bytes, ms->n_control_bytes, "readcontrolbitsresult"); count_1s = 0; for ( byte = 0; byte < ms->n_control_bytes; byte++ ) { for ( bit = 0; bit < 8; bit++ ) { if ( (ms->control_bytes[byte] >> bit) & 0x01 ) ++count_1s; } } DBG(20, "read_control_bits: number of 1's in controlbytes: %d\n", count_1s); return SANE_STATUS_GOOD; } /*---------- scsi_set_window() -----------------------------------------------*/ static SANE_Status scsi_set_window(Microtek2_Scanner *ms, int n) { /* n windows, not yet */ /* implemented */ SANE_Status status; uint8_t *setwindow; int size; DBG(30, "scsi_set_window: ms=%p, wnd=%d\n", (void *) ms, n); size = SW_CMD_L + SW_HEADER_L + n * SW_BODY_L; setwindow = (uint8_t *) malloc(size); DBG(100, "scsi_set_window: setwindow= %p, malloc'd %d Bytes\n", setwindow, size); if ( setwindow == NULL ) { DBG(1, "scsi_set_window: malloc for setwindow failed\n"); return SANE_STATUS_NO_MEM; } memset(setwindow, 0, size); SW_CMD(setwindow); SW_PARAM_LENGTH(setwindow, SW_HEADER_L + n * SW_BODY_L); SW_WNDDESCLEN(setwindow + SW_HEADER_P, SW_WNDDESCVAL); #define POS (setwindow + SW_BODY_P(n-1)) SW_WNDID(POS, n-1); SW_XRESDPI(POS, ms->x_resolution_dpi); SW_YRESDPI(POS, ms->y_resolution_dpi); SW_XPOSTL(POS, ms->x1_dots); SW_YPOSTL(POS, ms->y1_dots); SW_WNDWIDTH(POS, ms->width_dots); SW_WNDHEIGHT(POS, ms->height_dots); SW_THRESHOLD(POS, ms->threshold); SW_IMGCOMP(POS, ms->mode); SW_BITSPERPIXEL(POS, ms->depth); SW_EXTHT(POS, ms->use_external_ht); SW_INTHTINDEX(POS, ms->internal_ht_index); SW_RIF(POS, 1); SW_LENS(POS, 0); /* ???? */ SW_INFINITE(POS, 0); SW_STAY(POS, ms->stay); SW_RAWDAT(POS, ms->rawdat); SW_QUALITY(POS, ms->quality); SW_FASTSCAN(POS, ms->fastscan); SW_MEDIA(POS, ms->scan_source); SW_BRIGHTNESS_M(POS, ms->brightness_m); SW_CONTRAST_M(POS, ms->contrast_m); SW_EXPOSURE_M(POS, ms->exposure_m); SW_SHADOW_M(POS, ms->shadow_m); SW_MIDTONE_M(POS, ms->midtone_m); SW_HIGHLIGHT_M(POS, ms->highlight_m); /* the following properties are only referenced if it's a color scan */ /* but I guess they don't matter at a gray scan */ SW_BRIGHTNESS_R(POS, ms->brightness_r); SW_CONTRAST_R(POS, ms->contrast_r); SW_EXPOSURE_R(POS, ms->exposure_r); SW_SHADOW_R(POS, ms->shadow_r); SW_MIDTONE_R(POS, ms->midtone_r); SW_HIGHLIGHT_R(POS, ms->highlight_r); SW_BRIGHTNESS_G(POS, ms->brightness_g); SW_CONTRAST_G(POS, ms->contrast_g); SW_EXPOSURE_G(POS, ms->exposure_g); SW_SHADOW_G(POS, ms->shadow_g); SW_MIDTONE_G(POS, ms->midtone_g); SW_HIGHLIGHT_G(POS, ms->highlight_g); SW_BRIGHTNESS_B(POS, ms->brightness_b); SW_CONTRAST_B(POS, ms->contrast_b); SW_EXPOSURE_B(POS, ms->exposure_b); SW_SHADOW_B(POS, ms->shadow_b); SW_MIDTONE_B(POS, ms->midtone_b); SW_HIGHLIGHT_B(POS, ms->highlight_b); if ( md_dump >= 2 ) { dump_area2(setwindow, 10, "setwindowcmd"); dump_area2(setwindow + 10 ,8 , "setwindowheader"); dump_area2(setwindow + 18 ,61 , "setwindowbody"); } status = sanei_scsi_cmd(ms->sfd, setwindow, size, NULL, 0); if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_set_window: '%s'\n", sane_strstatus(status)); DBG(100, "scsi_set_window: free setwindow at %p\n", setwindow); free((void *) setwindow); return status; } /*---------- scsi_read_image_info() ------------------------------------------*/ static SANE_Status scsi_read_image_info(Microtek2_Scanner *ms) { uint8_t cmd[RII_CMD_L]; uint8_t result[RII_RESULT_L]; size_t size; SANE_Status status; Microtek2_Device *md; md = ms->dev; DBG(30, "scsi_read_image_info: ms=%p\n", (void *) ms); RII_SET_CMD(cmd); if ( md_dump >= 2) dump_area2(cmd, RII_CMD_L, "readimageinfo"); size = sizeof(result); status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), result, &size); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_read_image_info: '%s'\n", sane_strstatus(status)); return status; } if ( md_dump >= 2) dump_area2(result, size, "readimageinforesult"); /* The V300 returns some values in only two bytes */ if ( !(md->revision==2.70) && (md->model_flags & MD_RII_TWO_BYTES) ) { RII_GET_V300_WIDTHPIXEL(ms->ppl, result); RII_GET_V300_WIDTHBYTES(ms->bpl, result); RII_GET_V300_HEIGHTLINES(ms->src_remaining_lines, result); RII_GET_V300_REMAINBYTES(ms->remaining_bytes, result); } else { RII_GET_WIDTHPIXEL(ms->ppl, result); RII_GET_WIDTHBYTES(ms->bpl, result); RII_GET_HEIGHTLINES(ms->src_remaining_lines, result); RII_GET_REMAINBYTES(ms->remaining_bytes, result); } DBG(30, "scsi_read_image_info: ppl=%d, bpl=%d, lines=%d, remain=%d\n", ms->ppl, ms->bpl, ms->src_remaining_lines, ms->remaining_bytes); return SANE_STATUS_GOOD; } /*---------- scsi_read_image() -----------------------------------------------*/ static SANE_Status scsi_read_image(Microtek2_Scanner *ms, uint8_t *buffer, int bytes_per_pixel) { uint8_t cmd[RI_CMD_L]; SANE_Bool endiantype; SANE_Status status; size_t size; size_t i; uint8_t tmp; DBG(30, "scsi_read_image: ms=%p, buffer=%p\n", (void *) ms, buffer); ENDIAN_TYPE(endiantype) RI_SET_CMD(cmd); RI_SET_PCORMAC(cmd, endiantype); RI_SET_COLOR(cmd, ms->current_read_color); RI_SET_TRANSFERLENGTH(cmd, ms->transfer_length); DBG(30, "scsi_read_image: transferlength=%d\n", ms->transfer_length); if ( md_dump >= 2 ) dump_area2(cmd, RI_CMD_L, "readimagecmd"); size = ms->transfer_length; status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), buffer, &size); if ( buffer && ( ms->dev->model_flags & MD_PHANTOM_C6 ) && endiantype ) { switch(bytes_per_pixel) { case 1: break; case 2: for ( i = 1; i < size; i += 2 ) { tmp = buffer[i-1]; buffer[i-1] = buffer[i]; buffer[i] = tmp; } break; default: DBG(1, "scsi_read_image: Unexpected bytes_per_pixel=%d\n", bytes_per_pixel); } } if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_read_image: '%s'\n", sane_strstatus(status)); if ( md_dump > 3 ) dump_area2(buffer, ms->transfer_length, "readimageresult"); return status; } /*---------- scsi_read_image_status() ----------------------------------------*/ static SANE_Status scsi_read_image_status(Microtek2_Scanner *ms) { Microtek2_Device *md; Microtek2_Info *mi; uint8_t cmd[RIS_CMD_L]; uint8_t dummy; size_t dummy_length; SANE_Status status; SANE_Bool endian_type; md = ms->dev; mi = &md->info[md->scan_source]; DBG(30, "scsi_read_image_status: ms=%p\n", (void *) ms); ENDIAN_TYPE(endian_type) RIS_SET_CMD(cmd); RIS_SET_PCORMAC(cmd, endian_type); RIS_SET_COLOR(cmd, ms->current_read_color); /* mi->new_image_status = SANE_TRUE; */ /* for testing*/ if ( mi->new_image_status == SANE_TRUE ) { DBG(30, "scsi_read_image_status: use new image status \n"); dummy_length = 1; cmd[8] = 1; } else { DBG(30, "scsi_read_image_status: use old image status \n"); dummy_length = 0; cmd[8] = 0; } if ( md_dump >= 2 ) dump_area2(cmd, sizeof(cmd), "readimagestatus"); status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), &dummy, &dummy_length); if ( mi->new_image_status == SANE_TRUE ) { if ( dummy == 0 ) status = SANE_STATUS_GOOD; else status = SANE_STATUS_DEVICE_BUSY; } /* For some (X6USB) scanner We say we are going to try to read 1 byte of data (as recommended in the Microtek SCSI command documentation under "New Image Status") so that dubious SCSI host adapters (like the one in at least some Microtek X6 USB scanners) don't get wedged trying to do a zero length read. However, we do not actually try to read this byte of data, as that wedges the USB scanner as well. IOW the SCSI command says we are going to read 1 byte, but in fact we don't: */ /*cmd[8] = 1; status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), &dummy, 0); */ if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_read_image_status: '%s'\n", sane_strstatus(status)); return status; } /*---------- scsi_read_shading () --------------------------------------------*/ static SANE_Status scsi_read_shading(Microtek2_Scanner *ms, uint8_t *buffer, uint32_t length) { uint8_t cmd[RSI_CMD_L]; SANE_Bool endiantype; SANE_Status status = SANE_STATUS_GOOD; size_t size; DBG(30, "scsi_read_shading: pos=%p, size=%d, word=%d, color=%d, dark=%d\n", buffer, length, ms->word, ms->current_color, ms->dark); size = length; RSI_SET_CMD(cmd); ENDIAN_TYPE(endiantype) RSI_SET_PCORMAC(cmd, endiantype); RSI_SET_COLOR(cmd, ms->current_color); RSI_SET_DARK(cmd, ms->dark); RSI_SET_WORD(cmd, ms->word); RSI_SET_TRANSFERLENGTH(cmd, size); if ( md_dump >= 2 ) dump_area2(cmd, RSI_CMD_L, "readshading"); DBG(100, "scsi_read_shading: sfd=%d, cmd=%p, sizeofcmd=%lu," "dest=%p, destsize=%lu\n", ms->sfd, cmd, (u_long) sizeof(cmd), buffer, (u_long) size); status = sanei_scsi_cmd(ms->sfd, cmd, sizeof(cmd), buffer, &size); if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_read_shading: '%s'\n", sane_strstatus(status)); if ( md_dump > 3) dump_area2(buffer, size, "readshadingresult"); return status; } /*---------- scsi_send_shading () --------------------------------------------*/ static SANE_Status scsi_send_shading(Microtek2_Scanner *ms, uint8_t *shading_data, uint32_t length, uint8_t dark) { SANE_Bool endiantype; SANE_Status status; size_t size; uint8_t *cmd; DBG(30, "scsi_send_shading: pos=%p, size=%d, word=%d, color=%d, dark=%d\n", shading_data, length, ms->word, ms->current_color, dark); cmd = (uint8_t *) malloc(SSI_CMD_L + length); DBG(100, "scsi_send_shading: cmd=%p, malloc'd %d bytes\n", cmd, SSI_CMD_L + length); if ( cmd == NULL ) { DBG(1, "scsi_send_shading: Couldn't get buffer for shading table\n"); return SANE_STATUS_NO_MEM; } SSI_SET_CMD(cmd); ENDIAN_TYPE(endiantype) SSI_SET_PCORMAC(cmd, endiantype); SSI_SET_COLOR(cmd, ms->current_color); SSI_SET_DARK(cmd, dark); SSI_SET_WORD(cmd, ms->word); SSI_SET_TRANSFERLENGTH(cmd, length); memcpy(cmd + SSI_CMD_L, shading_data, length); size = length; if ( md_dump >= 2 ) dump_area2(cmd, SSI_CMD_L, "sendshading"); if ( md_dump >= 3 ) dump_area2(cmd + SSI_CMD_L, size, "sendshadingdata"); status = sanei_scsi_cmd(ms->sfd, cmd, size + SSI_CMD_L, NULL, 0); if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_send_shading: '%s'\n", sane_strstatus(status)); DBG(100, "free cmd at %p\n", cmd); free((void *) cmd); return status; } /*---------- scsi_read_system_status() ---------------------------------------*/ static SANE_Status scsi_read_system_status(Microtek2_Device *md, int fd) { uint8_t cmd[RSS_CMD_L]; uint8_t result[RSS_RESULT_L]; int sfd; size_t size; SANE_Status status; DBG(30, "scsi_read_system_status: md=%p, fd=%d\n", (void *) md, fd); if ( fd == -1 ) { status = sanei_scsi_open(md->name, &sfd, scsi_sense_handler, 0); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_read_system_status: open '%s'\n", sane_strstatus(status)); return status; } } else sfd = fd; RSS_CMD(cmd); if ( md_dump >= 2) dump_area2(cmd, RSS_CMD_L, "readsystemstatus"); size = sizeof(result); status = sanei_scsi_cmd(sfd, cmd, sizeof(cmd), result, &size); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_read_system_status: cmd '%s'\n", sane_strstatus(status)); sanei_scsi_close(sfd); return status; } if ( fd == -1 ) sanei_scsi_close(sfd); if ( md_dump >= 2) dump_area2(result, size, "readsystemstatusresult"); md->status.sskip = RSS_SSKIP(result); md->status.ntrack = RSS_NTRACK(result); md->status.ncalib = RSS_NCALIB(result); md->status.tlamp = RSS_TLAMP(result); md->status.flamp = RSS_FLAMP(result); md->status.rdyman= RSS_RDYMAN(result); md->status.trdy = RSS_TRDY(result); md->status.frdy = RSS_FRDY(result); md->status.adp = RSS_RDYMAN(result); md->status.detect = RSS_DETECT(result); md->status.adptime = RSS_ADPTIME(result); md->status.lensstatus = RSS_LENSSTATUS(result); md->status.aloff = RSS_ALOFF(result); md->status.timeremain = RSS_TIMEREMAIN(result); md->status.tmacnt = RSS_TMACNT(result); md->status.paper = RSS_PAPER(result); md->status.adfcnt = RSS_ADFCNT(result); md->status.currentmode = RSS_CURRENTMODE(result); md->status.buttoncount = RSS_BUTTONCOUNT(result); return SANE_STATUS_GOOD; } /*---------- scsi_request_sense() --------------------------------------------*/ /* currently not used */ #if 0 static SANE_Status scsi_request_sense(Microtek2_Scanner *ms) { uint8_t requestsense[RQS_CMD_L]; uint8_t buffer[100]; SANE_Status status; int size; int asl; int as_info_length; DBG(30, "scsi_request_sense: ms=%p\n", (void *) ms); RQS_CMD(requestsense); RQS_ALLOCLENGTH(requestsense, 100); size = sizeof(buffer); status = sanei_scsi_cmd(ms->sfd, requestsense, sizeof(requestsense), buffer, &size); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_request_sense: '%s'\n", sane_strstatus(status)); return status; } if ( md_dump >= 2 ) dump_area2(buffer, size, "requestsenseresult"); dump_area(buffer, RQS_LENGTH(buffer), "RequestSense"); asl = RQS_ASL(buffer); if ( (as_info_length = RQS_ASINFOLENGTH(buffer)) > 0 ) DBG(25, "scsi_request_sense: info '%.*s'\n", as_info_length, RQS_ASINFO(buffer)); return SANE_STATUS_GOOD; } #endif /*---------- scsi_send_system_status() ---------------------------------------*/ static SANE_Status scsi_send_system_status(Microtek2_Device *md, int fd) { uint8_t cmd[SSS_CMD_L + SSS_DATA_L]; uint8_t *pos; int sfd; SANE_Status status; DBG(30, "scsi_send_system_status: md=%p, fd=%d\n", (void *) md, fd); memset(cmd, 0, SSS_CMD_L + SSS_DATA_L); if ( fd == -1 ) { status = sanei_scsi_open(md->name, &sfd, scsi_sense_handler, 0); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_send_system_status: open '%s'\n", sane_strstatus(status)); return status; } } else sfd = fd; SSS_CMD(cmd); pos = cmd + SSS_CMD_L; SSS_STICK(pos, md->status.stick); SSS_NTRACK(pos, md->status.ntrack); SSS_NCALIB(pos, md->status.ncalib); SSS_TLAMP(pos, md->status.tlamp); SSS_FLAMP(pos, md->status.flamp); SSS_RESERVED17(pos, md->status.reserved17); SSS_RDYMAN(pos, md->status.rdyman); SSS_TRDY(pos, md->status.trdy); SSS_FRDY(pos, md->status.frdy); SSS_ADP(pos, md->status.adp); SSS_DETECT(pos, md->status.detect); SSS_ADPTIME(pos, md->status.adptime); SSS_LENSSTATUS(pos, md->status.lensstatus); SSS_ALOFF(pos, md->status.aloff); SSS_TIMEREMAIN(pos, md->status.timeremain); SSS_TMACNT(pos, md->status.tmacnt); SSS_PAPER(pos, md->status.paper); SSS_ADFCNT(pos, md->status.adfcnt); SSS_CURRENTMODE(pos, md->status.currentmode); SSS_BUTTONCOUNT(pos, md->status.buttoncount); if ( md_dump >= 2) { dump_area2(cmd, SSS_CMD_L, "sendsystemstatus"); dump_area2(cmd + SSS_CMD_L, SSS_DATA_L, "sendsystemstatusdata"); } status = sanei_scsi_cmd(sfd, cmd, sizeof(cmd), NULL, 0); if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_send_system_status: '%s'\n", sane_strstatus(status)); if ( fd == -1 ) sanei_scsi_close(sfd); return status; } /*---------- scsi_sense_handler() --------------------------------------------*/ /* rewritten 19.12.2001 for better SANE_STATUS return codes */ static SANE_Status scsi_sense_handler (int fd, u_char *sense, void *arg) { int as_info_length; uint8_t sense_key; uint8_t asc; uint8_t ascq; DBG(30, "scsi_sense_handler: fd=%d, sense=%p arg=%p\n",fd, sense, arg); dump_area(sense, RQS_LENGTH(sense), "SenseBuffer"); sense_key = RQS_SENSEKEY(sense); asc = RQS_ASC(sense); ascq = RQS_ASCQ(sense); DBG(5, "scsi_sense_handler: SENSE KEY (0x%02x), " "ASC (0x%02x), ASCQ (0x%02x)\n", sense_key, asc, ascq); if ( (as_info_length = RQS_ASINFOLENGTH(sense)) > 0 ) DBG(5,"scsi_sense_handler: info: '%*s'\n", as_info_length, RQS_ASINFO(sense)); switch ( sense_key ) { case RQS_SENSEKEY_NOSENSE: return SANE_STATUS_GOOD; case RQS_SENSEKEY_HWERR: case RQS_SENSEKEY_ILLEGAL: case RQS_SENSEKEY_VENDOR: if ( asc == 0x4a && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Command phase error\n"); else if ( asc == 0x2c && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Command sequence error\n"); else if ( asc == 0x4b && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Data phase error\n"); else if ( asc == 0x40 ) { DBG(5, "scsi_sense_handler: Hardware diagnostic failure:\n"); switch ( ascq ) { case RQS_ASCQ_CPUERR: DBG(5, "scsi_sense_handler: CPU error\n"); break; case RQS_ASCQ_SRAMERR: DBG(5, "scsi_sense_handler: SRAM error\n"); break; case RQS_ASCQ_DRAMERR: DBG(5, "scsi_sense_handler: DRAM error\n"); break; case RQS_ASCQ_DCOFF: DBG(5, "scsi_sense_handler: DC Offset error\n"); break; case RQS_ASCQ_GAIN: DBG(5, "scsi_sense_handler: Gain error\n"); break; case RQS_ASCQ_POS: DBG(5, "scsi_sense_handler: Positoning error\n"); break; default: DBG(5, "scsi_sense_handler: Unknown combination of ASC" " (0x%02x) and ASCQ (0x%02x)\n", asc, ascq); break; } } else if ( asc == 0x00 && ascq == 0x05) { DBG(5, "scsi_sense_handler: End of data detected\n"); return SANE_STATUS_EOF; } else if ( asc == 0x3d && ascq == 0x00) DBG(5, "scsi_sense_handler: Invalid bit in IDENTIFY\n"); else if ( asc == 0x2c && ascq == 0x02 ) /* Ok */ DBG(5, "scsi_sense_handler: Invalid comb. of windows specified\n"); else if ( asc == 0x20 && ascq == 0x00 ) /* Ok */ DBG(5, "scsi_sense_handler: Invalid command opcode\n"); else if ( asc == 0x24 && ascq == 0x00 ) /* Ok */ DBG(5, "scsi_sense_handler: Invalid field in CDB\n"); else if ( asc == 0x26 && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Invalid field in the param list\n"); else if ( asc == 0x49 && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Invalid message error\n"); else if ( asc == 0x60 && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Lamp failure\n"); else if ( asc == 0x25 && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Unsupported logic. unit\n"); else if ( asc == 0x53 && ascq == 0x00 ) { DBG(5, "scsi_sense_handler: ADF paper jam or no paper\n"); return SANE_STATUS_NO_DOCS; } else if ( asc == 0x54 && ascq == 0x00 ) { DBG(5, "scsi_sense_handler: Media bumping\n"); return SANE_STATUS_JAMMED; /* Don't know if this is right! */ } else if ( asc == 0x55 && ascq == 0x00 ) { DBG(5, "scsi_sense_handler: Scan Job stopped or cancelled\n"); return SANE_STATUS_CANCELLED; } else if ( asc == 0x3a && ascq == 0x00 ) { DBG(5, "scsi_sense_handler: Media (ADF or TMA) not available\n"); return SANE_STATUS_NO_DOCS; } else if ( asc == 0x3a && ascq == 0x01 ) { DBG(5, "scsi_sense_handler: Door is not closed\n"); return SANE_STATUS_COVER_OPEN; } else if ( asc == 0x3a && ascq == 0x02 ) DBG(5, "scsi_sense_handler: Door is not opened\n"); else if ( asc == 0x00 && ascq == 0x00 ) DBG(5, "scsi_sense_handler: No additional sense information\n"); /* Ok */ else if ( asc == 0x1a && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Parameter list length error\n"); else if ( asc == 0x26 && ascq == 0x02 ) DBG(5, "scsi_sense_handler: Parameter value invalid\n"); else if ( asc == 0x03 && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Peripheral device write fault - " "Firmware Download Error\n"); else if ( asc == 0x2c && ascq == 0x01 ) DBG(5, "scsi_sense_handler: Too many windows specified\n"); else if ( asc == 0x80 && ascq == 0x00 ) DBG(5, "scsi_sense_handler: Target abort scan\n"); else if ( asc == 0x96 && ascq == 0x08 ) { DBG(5, "scsi_sense_handler: Firewire Device busy\n"); return SANE_STATUS_DEVICE_BUSY; } else DBG(5, "scsi_sense_handler: Unknown combination of SENSE KEY " "(0x%02x), ASC (0x%02x) and ASCQ (0x%02x)\n", sense_key, asc, ascq); return SANE_STATUS_IO_ERROR; default: DBG(5, "scsi_sense_handler: Unknown sense key (0x%02x)\n", sense_key); return SANE_STATUS_IO_ERROR; } } /*---------- scsi_test_unit_ready() ------------------------------------------*/ static SANE_Status scsi_test_unit_ready(Microtek2_Device *md) { SANE_Status status; uint8_t tur[TUR_CMD_L]; int sfd; DBG(30, "scsi_test_unit_ready: md=%s\n", md->name); TUR_CMD(tur); status = sanei_scsi_open(md->name, &sfd, scsi_sense_handler, 0); if ( status != SANE_STATUS_GOOD ) { DBG(1, "scsi_test_unit_ready: open '%s'\n", sane_strstatus(status)); return status; } if ( md_dump >= 2 ) dump_area2(tur, sizeof(tur), "testunitready"); status = sanei_scsi_cmd(sfd, tur, sizeof(tur), NULL, 0); if ( status != SANE_STATUS_GOOD ) DBG(1, "scsi_test_unit_ready: cmd '%s'\n", sane_strstatus(status)); sanei_scsi_close(sfd); return status; } /*---------- sane_start() ----------------------------------------------------*/ SANE_Status sane_start(SANE_Handle handle) { SANE_Status status = SANE_STATUS_GOOD; Microtek2_Scanner *ms = handle; Microtek2_Device *md; Microtek2_Info *mi; uint8_t *pos; int color, rc, retry; DBG(30, "sane_start: handle=0x%p\n", handle); md = ms->dev; mi = &md->info[md->scan_source]; ms->n_control_bytes = md->n_control_bytes; if ( md->model_flags & MD_READ_CONTROL_BIT ) { if (ms->control_bytes) free((void *)ms->control_bytes); ms->control_bytes = (uint8_t *) malloc(ms->n_control_bytes); DBG(100, "sane_start: ms->control_bytes=%p, malloc'd %lu bytes\n", ms->control_bytes, (u_long) ms->n_control_bytes); if ( ms->control_bytes == NULL ) { DBG(1, "sane_start: malloc() for control bits failed\n"); status = SANE_STATUS_NO_MEM; goto cleanup; } } if (ms->sfd < 0) /* first or only pass of this scan */ { /* open device */ for ( retry = 0; retry < 10; retry++ ) { status = sanei_scsi_open (md->sane.name, &ms->sfd, scsi_sense_handler, 0); if ( status != SANE_STATUS_DEVICE_BUSY ) break; DBG(30, "sane_start: Scanner busy, trying again\n"); sleep(1); } if ( status != SANE_STATUS_GOOD ) { DBG(1, "sane_start: scsi_open: '%s'\n", sane_strstatus(status)); goto cleanup; } status = scsi_read_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) goto cleanup; if ( ms->val[OPT_CALIB_BACKEND].w == SANE_TRUE ) DBG(30, "sane_start: backend calibration on\n"); else DBG(30, "sane_start: backend calibration off\n"); if ( ( ms->val[OPT_CALIB_BACKEND].w == SANE_TRUE ) && !( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) ) { /* Read shading only once - possible with CIS scanners */ /* assuming only CIS scanners use Controlbits */ if ( ( md->shading_table_w == NULL ) || !( md->model_flags & MD_READ_CONTROL_BIT ) ) { status = get_scan_parameters(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; status = read_shading_image(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; } } status = get_scan_parameters(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; status = scsi_read_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) goto cleanup; md->status.aloff |= 128; md->status.timeremain = 10; if ( ms->scan_source == MS_SOURCE_FLATBED || ms->scan_source == MS_SOURCE_ADF ) { md->status.flamp |= MD_FLAMP_ON; md->status.tlamp &= ~MD_TLAMP_ON; } else { md->status.flamp &= ~MD_FLAMP_ON; md->status.tlamp |= MD_TLAMP_ON; } if ( ms->lightlid35 ) { md->status.flamp &= ~MD_FLAMP_ON; /* md->status.tlamp |= MD_TLAMP_ON;*/ /* with this line on some scanners (X6, 0x91) the Flamp goes on */ } if ( ms->no_backtracking ) md->status.ntrack |= MD_NTRACK_ON; else md->status.ntrack &= ~MD_NTRACK_ON; status = scsi_send_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) goto cleanup; /* calculate gamma: we assume, that the gamma values are transferred */ /* with one send gamma command, even if it is a 3 pass scanner */ if ( md->model_flags & MD_NO_GAMMA ) { ms->lut_size = (int) pow(2.0, (double) ms->depth); ms->lut_entry_size = ms->depth > 8 ? 2 : 1; } else { get_lut_size(mi, &ms->lut_size, &ms->lut_entry_size); } ms->lut_size_bytes = ms->lut_size * ms->lut_entry_size; ms->word = (ms->lut_entry_size == 2); ms->gamma_table = (uint8_t *) malloc(3 * ms->lut_size_bytes ); DBG(100, "sane_start: ms->gamma_table=%p, malloc'd %d bytes\n", ms->gamma_table, 3 * ms->lut_size_bytes); if ( ms->gamma_table == NULL ) { DBG(1, "sane_start: malloc for gammatable failed\n"); status = SANE_STATUS_NO_MEM; goto cleanup; } for ( color = 0; color < 3; color++ ) { pos = ms->gamma_table + color * ms->lut_size_bytes; calculate_gamma(ms, pos, color, ms->gamma_mode); } /* Some models ignore the settings for the exposure time, */ /* so we must do it ourselves. Apparently this seems to be */ /* the case for all models that have the chunky data format */ if ( mi->data_format == MI_DATAFMT_CHUNKY ) set_exposure(ms); if ( ! (md->model_flags & MD_NO_GAMMA) ) { status = scsi_send_gamma(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; } status = scsi_set_window(ms, 1); if ( status != SANE_STATUS_GOOD ) goto cleanup; ms->scanning = SANE_TRUE; ms->cancelled = SANE_FALSE; } ++ms->current_pass; status = scsi_read_image_info(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; status = prepare_buffers(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; status = calculate_sane_params(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; if ( !( md->model_flags & MD_NO_RIS_COMMAND ) ) { /* !!FIXME!! - hack for C6USB because RIS over USB doesn't wait until */ /* scanner ready */ if (mi->model_code == 0x9a) sleep(2); status = scsi_wait_for_image(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; } if ( ms->calib_backend && ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) && ( ( md->shading_table_w == NULL ) || ( ms->mode != md->shading_table_contents ) ) ) { status = read_cx_shading(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; } if ( ms->lightlid35 ) /* hopefully this leads to a switched off flatbed lamp with lightlid */ { status = scsi_read_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) goto cleanup; md->status.flamp &= ~MD_FLAMP_ON; md->status.tlamp &= ~MD_TLAMP_ON; status = scsi_send_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) goto cleanup; } if ( md->model_flags & MD_READ_CONTROL_BIT ) { status = scsi_read_control_bits(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; if ( ms->calib_backend ) { status = condense_shading(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; } } /* open a pipe and fork a child process, that actually reads the data */ rc = pipe(ms->fd); if ( rc == -1 ) { DBG(1, "sane_start: pipe failed\n"); status = SANE_STATUS_IO_ERROR; goto cleanup; } /* create reader routine as new thread or process */ ms->pid = sanei_thread_begin( reader_process,(void*) ms); if ( !sanei_thread_is_valid (ms->pid) ) { DBG(1, "sane_start: fork failed\n"); status = SANE_STATUS_IO_ERROR; goto cleanup; } if (sanei_thread_is_forked()) close(ms->fd[1]); return SANE_STATUS_GOOD; cleanup: cleanup_scanner(ms); return status; } /*---------- prepare_buffers -------------------------------------------------*/ static SANE_Status prepare_buffers(Microtek2_Scanner *ms) { SANE_Status status; Microtek2_Device *md; Microtek2_Info *mi; uint32_t strip_lines; int i; status = SANE_STATUS_GOOD; DBG(30, "prepare_buffers: ms=0x%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; /* calculate maximum number of lines to read */ strip_lines = (int) ((double) ms->y_resolution_dpi * md->opts.strip_height); if ( strip_lines == 0 ) strip_lines = 1; /* calculate number of lines that fit into the source buffer */ #ifdef TESTBACKEND ms->src_max_lines = MIN( 5000000 / ms->bpl, strip_lines); #else ms->src_max_lines = MIN( sanei_scsi_max_request_size / ms->bpl, strip_lines); #endif if ( ms->src_max_lines == 0 ) { DBG(1, "sane_start: Scan buffer too small\n"); status = SANE_STATUS_IO_ERROR; goto cleanup; } /* allocate buffers */ ms->src_buffer_size = ms->src_max_lines * ms->bpl; if ( ms->mode == MS_MODE_COLOR && mi->data_format == MI_DATAFMT_LPLSEGREG ) { /* In this case the data is not neccessarily in the order RGB */ /* and there may be different numbers of read red, green and blue */ /* segments. We allocate a second buffer to read new lines in */ /* and hold undelivered pixels in the other buffer */ int extra_buf_size; extra_buf_size = 2 * ms->bpl * mi->ccd_gap * (int) ceil( (double) mi->max_yresolution / (double) mi->opt_resolution); for ( i = 0; i < 2; i++ ) { if ( ms->buf.src_buffer[i] ) free((void *) ms->buf.src_buffer[i]); ms->buf.src_buffer[i] = (uint8_t *) malloc(ms->src_buffer_size + extra_buf_size); DBG(100, "prepare_buffers: ms->buf.src_buffer[%d]=%p," "malloc'd %d bytes\n", i, ms->buf.src_buffer[i], ms->src_buffer_size + extra_buf_size); if ( ms->buf.src_buffer[i] == NULL ) { DBG(1, "sane_start: malloc for scan buffer failed\n"); status = SANE_STATUS_NO_MEM; goto cleanup; } } ms->buf.free_lines = ms->src_max_lines + extra_buf_size / ms->bpl; ms->buf.free_max_lines = ms->buf.free_lines; ms->buf.src_buf = ms->buf.src_buffer[0]; ms->buf.current_src = 0; /* index to current buffer */ } else { if ( ms->buf.src_buf ) free((void *) ms->buf.src_buf); ms->buf.src_buf = malloc(ms->src_buffer_size); DBG(100, "sane_start: ms->buf.src_buf=%p, malloc'd %d bytes\n", ms->buf.src_buf, ms->src_buffer_size); if ( ms->buf.src_buf == NULL ) { DBG(1, "sane_start: malloc for scan buffer failed\n"); status = SANE_STATUS_NO_MEM; goto cleanup; } } for ( i = 0; i < 3; i++ ) { ms->buf.current_pos[i] = ms->buf.src_buffer[0]; ms->buf.planes[0][i] = 0; ms->buf.planes[1][i] = 0; } /* allocate a temporary buffer for the data, if auto_adjust threshold */ /* is selected. */ if ( ms->auto_adjust == 1 ) { ms->temporary_buffer = (uint8_t *) malloc(ms->remaining_bytes); DBG(100, "sane_start: ms->temporary_buffer=%p, malloc'd %d bytes\n", ms->temporary_buffer, ms->remaining_bytes); if ( ms->temporary_buffer == NULL ) { DBG(1, "sane_start: malloc() for temporary buffer failed\n"); status = SANE_STATUS_NO_MEM; goto cleanup; } } else ms->temporary_buffer = NULL; /* some data formats have additional information in a scan line, which */ /* is not transferred to the frontend; real_bpl is the number of bytes */ /* per line, that is copied into the frontend's buffer */ ms->real_bpl = (uint32_t) ceil( ((double) ms->ppl * (double) ms->bits_per_pixel_out) / 8.0 ); if ( mi->onepass && ms->mode == MS_MODE_COLOR ) ms->real_bpl *= 3; ms->real_remaining_bytes = ms->real_bpl * ms->src_remaining_lines; return SANE_STATUS_GOOD; cleanup: cleanup_scanner(ms); return status; } static void write_shading_buf_pnm(Microtek2_Scanner *ms, uint32_t lines) { FILE *outfile; uint16_t pixel, color, linenr, factor; unsigned char img_val_out; float img_val = 0; Microtek2_Device *md; Microtek2_Info *mi; md = ms->dev; mi = &md->info[md->scan_source]; if ( mi->depth & MI_HASDEPTH_16 ) factor = 256; else if ( mi->depth & MI_HASDEPTH_14 ) factor = 64; else if ( mi->depth & MI_HASDEPTH_12 ) factor = 16; else if ( mi->depth & MI_HASDEPTH_10 ) factor = 4; else factor = 1; if ( md->model_flags & MD_16BIT_TRANSFER ) factor = 256; outfile = fopen("shading_buf_w.pnm", "w"); fprintf(outfile, "P6\n#imagedata\n%d %d\n255\n", mi->geo_width / mi->calib_divisor, lines); for ( linenr=0; linenr < lines; linenr++ ) { if (mi->data_format == MI_DATAFMT_LPLSEGREG) { DBG(1, "Output of shading buffer unsupported for" "Segreg Data format\n"); break; } for ( pixel=0; pixel < (uint16_t) (mi->geo_width / mi->calib_divisor); pixel++) { for ( color=0; color < 3; color++ ) { switch( mi->data_format ) { case MI_DATAFMT_LPLCONCAT: if ( md->shading_depth > 8) img_val = *((uint16_t *) ms->shading_image + linenr * ( ms->bpl / ms->lut_entry_size ) + mi->color_sequence[color] * ( ms->bpl / ms->lut_entry_size / 3 ) + pixel); else img_val = *((uint8_t *) ms->shading_image + linenr * ( ms->bpl / ms->lut_entry_size ) + mi->color_sequence[color] * ( ms->bpl / ms->lut_entry_size / 3 ) + pixel); break; case MI_DATAFMT_CHUNKY: case MI_DATAFMT_9800: img_val = *((uint16_t *)ms->shading_image + linenr * 3 * ( mi->geo_width / mi->calib_divisor ) + 3 * pixel + mi->color_sequence[color]); break; } img_val /= factor; img_val_out = (unsigned char)img_val; fputc(img_val_out, outfile); } } } fclose(outfile); return; } static void write_shading_pnm(Microtek2_Scanner *ms) { FILE *outfile_w = NULL, *outfile_d = NULL; int pixel, color, line, offset, num_shading_pixels, output_height; uint16_t img_val, factor; Microtek2_Device *md; Microtek2_Info *mi; output_height = 180; md = ms->dev; mi = &md->info[md->scan_source]; DBG(30, "write_shading_pnm: ms=%p\n", (void *) ms); if ( mi->depth & MI_HASDEPTH_16 ) factor = 256; else if ( mi->depth & MI_HASDEPTH_14 ) factor = 64; else if ( mi->depth & MI_HASDEPTH_12 ) factor = 16; else if ( mi->depth & MI_HASDEPTH_10 ) factor = 4; else factor = 1; if ( md->model_flags & MD_16BIT_TRANSFER ) factor = 256; if ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) num_shading_pixels = ms->n_control_bytes * 8; else num_shading_pixels = mi->geo_width / mi->calib_divisor; if ( md->shading_table_w != NULL ) { outfile_w = fopen("microtek2_shading_w.pnm", "w"); fprintf(outfile_w, "P6\n#imagedata\n%d %d\n255\n", num_shading_pixels, output_height); } if ( md->shading_table_d != NULL ) { outfile_d = fopen("microtek2_shading_d.pnm", "w"); fprintf(outfile_d, "P6\n#imagedata\n%d %d\n255\n", num_shading_pixels, output_height); } for ( line=0; line < output_height; ++line ) { for ( pixel=0; pixel < num_shading_pixels ; ++pixel) { for ( color=0; color < 3; ++color ) { offset = mi->color_sequence[color] * num_shading_pixels + pixel; if ( md->shading_table_w != NULL ) { if ( ms->lut_entry_size == 2 ) { img_val = *((uint16_t *) md->shading_table_w + offset ); img_val /= factor; } else img_val = *((uint8_t *) md->shading_table_w + offset ); fputc((unsigned char)img_val, outfile_w); } if ( md->shading_table_d != NULL ) { if ( ms->lut_entry_size == 2 ) { img_val = *((uint16_t *) md->shading_table_d + offset ); img_val /= factor; } else img_val = *((uint8_t *) md->shading_table_d + offset ); fputc((unsigned char)img_val, outfile_d); } } } } if ( md->shading_table_w != NULL ) fclose(outfile_w); if ( md->shading_table_d != NULL ) fclose(outfile_d); return; } static void write_cshading_pnm(Microtek2_Scanner *ms) { FILE *outfile; Microtek2_Device *md; Microtek2_Info *mi; int pixel, color, line, offset, img_val, img_height=30, factor; md = ms->dev; mi = &md->info[md->scan_source]; if ( mi->depth & MI_HASDEPTH_16 ) factor = 256; else if ( mi->depth & MI_HASDEPTH_14 ) factor = 64; else if ( mi->depth & MI_HASDEPTH_12 ) factor = 16; else if ( mi->depth & MI_HASDEPTH_10 ) factor = 4; else factor = 1; if ( md->model_flags & MD_16BIT_TRANSFER ) factor = 256; outfile = fopen("microtek2_cshading_w.pnm", "w"); if ( ms->mode == MS_MODE_COLOR ) fprintf(outfile, "P6\n#imagedata\n%d %d\n255\n", ms->ppl, img_height); else fprintf(outfile, "P5\n#imagedata\n%d %d\n255\n", ms->ppl, img_height); for ( line=0; line < img_height; ++line ) { for ( pixel=0; pixel < (int)ms->ppl; ++pixel) { for ( color=0; color < 3; ++color ) { offset = color * (int)ms->ppl + pixel; if ( ms->lut_entry_size == 1 ) img_val = (int) *((uint8_t *)ms->condensed_shading_w + offset); else { img_val = (int) *((uint16_t *)ms->condensed_shading_w + offset); img_val /= factor; } fputc((unsigned char)img_val, outfile); if ( ms->mode == MS_MODE_GRAY ) break; } } } fclose(outfile); return; } /*---------- condense_shading() ----------------------------------------------*/ static SANE_Status condense_shading(Microtek2_Scanner *ms) { /* This function extracts the relevant shading pixels from */ /* the shading image according to the 1's in the result of */ /* 'read control bits', and stores them in a memory block. */ /* We will then have as many shading pixels as there are */ /* pixels per line. The order of the pixels in the condensed */ /* shading data block will always be left to right. The color */ /* sequence remains unchanged. */ Microtek2_Device *md; Microtek2_Info *mi; uint32_t byte; uint32_t cond_length; /* bytes per condensed shading line */ int color, count, lfd_bit; int shad_bplc, shad_pixels; /* bytes per line & color in shading image */ int bit, flag; uint32_t sh_offset, csh_offset; int gray_filter_color = 1; /* which color of the shading is taken for gray*/ md = ms->dev; mi = &md->info[md->scan_source]; DBG(30, "condense_shading: ms=%p, ppl=%d\n", (void *) ms, ms->ppl); if ( md->shading_table_w == NULL ) { DBG(1, "condense shading: no shading table found, skip shading\n"); return SANE_STATUS_GOOD; } get_lut_size( mi, &ms->lut_size, &ms->lut_entry_size ); if ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) { shad_pixels = ms->n_control_bytes * 8; gray_filter_color = 0; /* 336CX reads only one shading in gray mode*/ } else shad_pixels = mi->geo_width; shad_bplc = shad_pixels * ms->lut_entry_size; if ( md_dump >= 3 ) { dump_area2(md->shading_table_w, shad_bplc * 3, "shading_table_w"); if ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) write_shading_pnm(ms); } cond_length = ms->bpl * ms->lut_entry_size; if ( ms->condensed_shading_w ) { free((void*) ms->condensed_shading_w ); ms->condensed_shading_w = NULL; } ms->condensed_shading_w = (uint8_t *)malloc(cond_length); DBG(100, "condense_shading: ms->condensed_shading_w=%p," "malloc'd %d bytes\n", ms->condensed_shading_w, cond_length); if ( ms->condensed_shading_w == NULL ) { DBG(1, "condense_shading: malloc for white table failed\n"); return SANE_STATUS_NO_MEM; } if ( md->shading_table_d != NULL ) { if ( md_dump >= 3 ) dump_area2(md->shading_table_d, shad_bplc * 3, "shading_table_d"); if ( ms->condensed_shading_d ) { free((void*) ms->condensed_shading_d ); ms->condensed_shading_d = NULL; } ms->condensed_shading_d = (uint8_t *)malloc(cond_length); DBG(100, "condense_shading: ms->condensed_shading_d=%p," " malloc'd %d bytes\n", ms->condensed_shading_d, cond_length); if ( ms->condensed_shading_d == NULL ) { DBG(1, "condense_shading: malloc for dark table failed\n"); return SANE_STATUS_NO_MEM; } } DBG(128, "controlbit offset=%d\n", md->controlbit_offset); count = 0; for (lfd_bit = 0; ( lfd_bit < mi->geo_width ) && ( count < (int)ms->ppl ); ++lfd_bit) { byte = ( lfd_bit + md->controlbit_offset ) / 8; bit = ( lfd_bit + md->controlbit_offset ) % 8; if ( mi->direction & MI_DATSEQ_RTOL ) flag = ((ms->control_bytes[byte] >> bit) & 0x01); else flag = ((ms->control_bytes[byte] >> (7 - bit)) & 0x01); if ( flag == 1 ) /* flag==1 if byte's bit is set */ { for ( color = 0; color < 3; ++color ) { if ( ( ms->mode == MS_MODE_COLOR ) || ( ( ms->mode == MS_MODE_GRAY ) && ( color == gray_filter_color ) ) || ( ( ms->mode == MS_MODE_LINEARTFAKE ) && ( color == gray_filter_color ) ) ) { sh_offset = color * shad_pixels + lfd_bit; if ( md->model_flags & MD_PHANTOM336CX_TYPE_SHADING ) sh_offset += md->controlbit_offset; if ( ms->mode == MS_MODE_COLOR ) csh_offset = color * ms->ppl + count; else csh_offset = count; if ( csh_offset > cond_length ) { DBG(1, "condense_shading: wrong control bits data, " ); DBG(1, "csh_offset (%d) > cond_length(%d)\n", csh_offset, cond_length ); csh_offset = cond_length; } if ( ms->lut_entry_size == 2 ) { *((uint16_t *)ms->condensed_shading_w + csh_offset) = *((uint16_t *)md->shading_table_w + sh_offset); if ( ms->condensed_shading_d != NULL ) *((uint16_t *)ms->condensed_shading_d + csh_offset) = *((uint16_t *)md->shading_table_d + sh_offset); } else { *((uint8_t *)ms->condensed_shading_w + csh_offset) = *((uint8_t *)md->shading_table_w + sh_offset); if ( ms->condensed_shading_d != NULL ) *((uint8_t *)ms->condensed_shading_d + csh_offset) = *((uint8_t *)md->shading_table_d + sh_offset); } } } ++count; } } if ( md_dump >= 3 ) { dump_area2(ms->condensed_shading_w, cond_length, "condensed_shading_w"); if ( ms->condensed_shading_d != NULL ) dump_area2(ms->condensed_shading_d, cond_length, "condensed_shading_d"); write_cshading_pnm(ms); } return SANE_STATUS_GOOD; } /*---------- read_shading_image() --------------------------------------------*/ static SANE_Status read_shading_image(Microtek2_Scanner *ms) { SANE_Status status; Microtek2_Device *md; Microtek2_Info *mi; uint32_t lines; uint8_t *buf; int max_lines; int lines_to_read; DBG(30, "read_shading_image: ms=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; if ( ! MI_WHITE_SHADING_ONLY(mi->shtrnsferequ) || ( md->model_flags & MD_PHANTOM_C6 ) ) /* Dark shading correction */ /* ~~~~~~~~~~~~~~~~~~~~~~~ */ { DBG(30, "read_shading_image: reading black data\n"); md->status.ntrack |= MD_NTRACK_ON; md->status.ncalib &= ~MD_NCALIB_ON; md->status.flamp |= MD_FLAMP_ON; if ( md->model_flags & MD_PHANTOM_C6 ) { md->status.stick |= MD_STICK_ON; md->status.reserved17 |= MD_RESERVED17_ON; } get_calib_params(ms); if ( md->model_flags & MD_PHANTOM_C6 ) ms->stay = 1; status = scsi_send_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) return status; status = scsi_set_window(ms, 1); if ( status != SANE_STATUS_GOOD ) return status; #ifdef TESTBACKEND status = scsi_read_sh_image_info(ms); #else status = scsi_read_image_info(ms); #endif if ( status != SANE_STATUS_GOOD ) return status; status = scsi_wait_for_image(ms); if ( status != SANE_STATUS_GOOD ) return status; status = scsi_read_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) return status; md->status.flamp &= ~MD_FLAMP_ON; status = scsi_send_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) return status; ms->shading_image = malloc(ms->bpl * ms->src_remaining_lines); DBG(100, "read shading image: ms->shading_image=%p," " malloc'd %d bytes\n", ms->shading_image, ms->bpl * ms->src_remaining_lines); if ( ms->shading_image == NULL ) { DBG(1, "read_shading_image: malloc for buffer failed\n"); return SANE_STATUS_NO_MEM; } buf = ms->shading_image; #ifdef TESTBACKEND max_lines = 5000000 / ms->bpl; #else max_lines = sanei_scsi_max_request_size / ms->bpl; #endif if ( max_lines == 0 ) { DBG(1, "read_shading_image: buffer too small\n"); return SANE_STATUS_IO_ERROR; } lines = ms->src_remaining_lines; while ( ms->src_remaining_lines > 0 ) { lines_to_read = MIN(max_lines, ms->src_remaining_lines); ms->src_buffer_size = lines_to_read * ms->bpl; ms->transfer_length = ms->src_buffer_size; #ifdef TESTBACKEND status = scsi_read_sh_d_image(ms, buf); #else status = scsi_read_image(ms, buf, md->shading_depth>8 ? 2 : 1); #endif if ( status != SANE_STATUS_GOOD ) { DBG(1, "read_shading_image: read image failed: '%s'\n", sane_strstatus(status)); return status; } ms->src_remaining_lines -= lines_to_read; buf += ms->src_buffer_size; } status = prepare_shading_data(ms, lines, &md->shading_table_d); if ( status != SANE_STATUS_GOOD ) return status; /* send shading data to the device */ /* Some models use "read_control bit", and the shading must be */ /* applied by the backend later */ if ( ! (md->model_flags & MD_READ_CONTROL_BIT) ) { status = shading_function(ms, md->shading_table_d); if ( status != SANE_STATUS_GOOD ) return status; ms->word = ms->lut_entry_size == 2 ? 1 : 0; ms->current_color = MS_COLOR_ALL; status = scsi_send_shading(ms, md->shading_table_d, 3 * ms->lut_entry_size * mi->geo_width / mi->calib_divisor, 1); if ( status != SANE_STATUS_GOOD ) return status; } DBG(100, "free memory for ms->shading_image at %p\n", ms->shading_image); free((void *) ms->shading_image); ms->shading_image = NULL; } /* white shading correction */ /* ~~~~~~~~~~~~~~~~~~~~~~~~ */ DBG(30, "read_shading_image: reading white data\n"); /* According to the doc NCalib must be set for white shading data */ /* if we have a black and a white shading correction and must be */ /* cleared if we have only a white shading collection */ if ( ! MI_WHITE_SHADING_ONLY(mi->shtrnsferequ) || ( md->model_flags & MD_PHANTOM_C6 ) ) md->status.ncalib |= MD_NCALIB_ON; else md->status.ncalib &= ~MD_NCALIB_ON; md->status.flamp |= MD_FLAMP_ON; /* md->status.tlamp &= ~MD_TLAMP_ON; */ md->status.ntrack |= MD_NTRACK_ON; if ( md->model_flags & MD_PHANTOM_C6 ) { md->status.stick &= ~MD_STICK_ON; md->status.reserved17 |= MD_RESERVED17_ON; } get_calib_params(ms); #ifdef NO_PHANTOMTYPE_SHADING /* md->status.stick &= ~MD_STICK_ON; */ /* md->status.ncalib &= ~MD_NCALIB_ON; */ /* md->status.reserved17 &= ~MD_RESERVED17_ON; */ ms->rawdat = 0; #endif status = scsi_send_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) return status; status = scsi_set_window(ms, 1); if ( status != SANE_STATUS_GOOD ) return status; #ifdef TESTBACKEND status = scsi_read_sh_image_info(ms); #else status = scsi_read_image_info(ms); #endif if ( status != SANE_STATUS_GOOD ) return status; status = scsi_wait_for_image(ms); if ( status != SANE_STATUS_GOOD ) return status; #ifdef NO_PHANTOMTYPE_SHADING if ( !( md->model_flags & MD_READ_CONTROL_BIT ) ) { #endif status = scsi_read_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) return status; #ifdef NO_PHANTOMTYPE_SHADING } #endif #ifdef NO_PHANTOMTYPE_SHADING if ( mi->model_code == 0x94 ) status = scsi_read_control_bits(ms); #endif ms->shading_image = malloc(ms->bpl * ms->src_remaining_lines); DBG(100, "read shading image: ms->shading_image=%p, malloc'd %d bytes\n", ms->shading_image, ms->bpl * ms->src_remaining_lines); if ( ms->shading_image == NULL ) { DBG(1, "read_shading_image: malloc for buffer failed\n"); return SANE_STATUS_NO_MEM; } buf = ms->shading_image; #ifdef TESTBACKEND max_lines = 5000000 / ms->bpl; #else max_lines = sanei_scsi_max_request_size / ms->bpl; #endif if ( max_lines == 0 ) { DBG(1, "read_shading_image: buffer too small\n"); return SANE_STATUS_IO_ERROR; } lines = ms->src_remaining_lines; while ( ms->src_remaining_lines > 0 ) { lines_to_read = MIN(max_lines, ms->src_remaining_lines); ms->src_buffer_size = lines_to_read * ms->bpl; ms->transfer_length = ms->src_buffer_size; #ifdef TESTBACKEND status = scsi_read_sh_w_image(ms, buf); #else status = scsi_read_image(ms, buf, md->shading_depth>8 ? 2 : 1); #endif if ( status != SANE_STATUS_GOOD ) return status; ms->src_remaining_lines -= lines_to_read; buf += ms->src_buffer_size; } status = prepare_shading_data(ms, lines, &md->shading_table_w); if ( status != SANE_STATUS_GOOD ) return status; if ( md_dump >= 3 ) { write_shading_buf_pnm(ms, lines); write_shading_pnm(ms); } /* send shading data to the device */ /* Some models use "read_control bit", and the shading must be */ /* applied by the backend later */ if ( ! (md->model_flags & MD_READ_CONTROL_BIT) ) { status = shading_function(ms, md->shading_table_w); if ( status != SANE_STATUS_GOOD ) return status; ms->word = ms->lut_entry_size == 2 ? 1 : 0; ms->current_color = MS_COLOR_ALL; status = scsi_send_shading(ms, md->shading_table_w, 3 * ms->lut_entry_size * mi->geo_width / mi->calib_divisor, 0); if ( status != SANE_STATUS_GOOD ) return status; } ms->rawdat = 0; ms->stay = 0; md->status.ncalib |= MD_NCALIB_ON; if ( md->model_flags & MD_PHANTOM_C6 ) { md->status.stick &= ~MD_STICK_ON; md->status.reserved17 &= ~MD_RESERVED17_ON; } #ifdef NO_PHANTOMTYPE_SHADING if (mi->model_code == 0x94) md->status.ncalib &= ~MD_NCALIB_ON; #endif status = scsi_send_system_status(md, ms->sfd); if ( status != SANE_STATUS_GOOD ) return status; DBG(100, "free memory for ms->shading_image at %p\n", ms->shading_image); free((void *) ms->shading_image); ms->shading_image = NULL; return SANE_STATUS_GOOD; } /*---------- prepare_shading_data() ------------------------------------------*/ static SANE_Status prepare_shading_data(Microtek2_Scanner *ms, uint32_t lines, uint8_t **data) { /* This function calculates one line of black or white shading data */ /* from the shading image. At the end we have one line. The */ /* color sequence is unchanged. */ #define MICROTEK2_CALIB_USE_MEDIAN Microtek2_Device *md; Microtek2_Info *mi; uint32_t length,line; int color, i; SANE_Status status; #ifdef MICROTEK2_CALIB_USE_MEDIAN uint16_t *sortbuf, value; #else uint32_t value; #endif DBG(30, "prepare_shading_data: ms=%p, lines=%d, *data=%p\n", (void *) ms, lines, *data); md = ms->dev; mi = &md->info[md->scan_source]; status = SANE_STATUS_GOOD; get_lut_size(mi, &ms->lut_size, &ms->lut_entry_size); length = 3 * ms->lut_entry_size * mi->geo_width / mi->calib_divisor; if ( *data == NULL ) { *data = (uint8_t *) malloc(length); DBG(100, "prepare_shading_data: malloc'd %d bytes at %p\n", length, *data); if ( *data == NULL ) { DBG(1, "prepare_shading_data: malloc for shading table failed\n"); return SANE_STATUS_NO_MEM; } } #ifdef MICROTEK2_CALIB_USE_MEDIAN sortbuf = malloc( lines * ms->lut_entry_size ); DBG(100, "prepare_shading_data: sortbuf= %p, malloc'd %d Bytes\n", (void *) sortbuf, lines * ms->lut_entry_size); if ( sortbuf == NULL ) { DBG(1, "prepare_shading_data: malloc for sort buffer failed\n"); return SANE_STATUS_NO_MEM; } #endif switch( mi->data_format ) { case MI_DATAFMT_LPLCONCAT: if ( ms->lut_entry_size == 1 ) { DBG(1, "prepare_shading_data: wordsize == 1 unsupported\n"); return SANE_STATUS_UNSUPPORTED; } for ( color = 0; color < 3; color++ ) { for ( i = 0; i < ( mi->geo_width / mi->calib_divisor ); i++ ) { value = 0; for ( line = 0; line < lines; line++ ) #ifndef MICROTEK2_CALIB_USE_MEDIAN /* average the shading lines to get the shading data */ value += *((uint16_t *) ms->shading_image + line * ( ms->bpl / ms->lut_entry_size ) + color * ( ms->bpl / ms->lut_entry_size / 3 ) + i); value /= lines; *((uint16_t *) *data + color * ( mi->geo_width / mi->calib_divisor ) + i) = (uint16_t) MIN(0xffff, value); #else /* use a median filter to get the shading data -- should be better */ *(sortbuf + line ) = *((uint16_t *) ms->shading_image + line * ( ms->bpl / ms->lut_entry_size ) + color * ( ms->bpl / ms->lut_entry_size / 3 ) + i); qsort(sortbuf, lines, sizeof(uint16_t), (qsortfunc)compare_func_16); value = *(sortbuf + ( lines - 1 ) / 2 ); *((uint16_t *) *data + color * ( mi->geo_width / mi->calib_divisor ) + i) = value; #endif } } break; case MI_DATAFMT_CHUNKY: case MI_DATAFMT_9800: if ( ms->lut_entry_size == 1 ) { DBG(1, "prepare_shading_data: wordsize == 1 unsupported\n"); return SANE_STATUS_UNSUPPORTED; } for ( color = 0; color < 3; color++ ) { for ( i = 0; i < ( mi->geo_width / mi->calib_divisor ); i++ ) { value = 0; for ( line = 0; line < lines; line++ ) #ifndef MICROTEK2_CALIB_USE_MEDIAN /* average the shading lines to get the shading data */ value += *((uint16_t *) ms->shading_image + line * 3 * mi->geo_width / mi->calib_divisor + 3 * i + color); value /= lines; *((uint16_t *) *data + color * ( mi->geo_width / mi->calib_divisor ) + i) = (uint16_t) MIN(0xffff, value); #else /* use a median filter to get the shading data -- should be better */ *(sortbuf + line ) = *((uint16_t *) ms->shading_image + line * 3 * mi->geo_width / mi->calib_divisor + 3 * i + color); qsort(sortbuf, lines, sizeof(uint16_t), (qsortfunc)compare_func_16); value = *(sortbuf + ( lines - 1 ) / 2 ); *((uint16_t *) *data + color * ( mi->geo_width / mi->calib_divisor ) + i) = value; #endif } } break; case MI_DATAFMT_LPLSEGREG: for ( color = 0; color < 3; color++ ) { for ( i = 0; i < ( mi->geo_width / mi->calib_divisor ); i++ ) { value = 0; if ( ms->lut_entry_size == 1 ) { for ( line = 0; line < lines; line++ ) value += *((uint8_t *) ms->shading_image + line * 3 * mi->geo_width / mi->calib_divisor + 3 * i + color); value /= lines; *((uint8_t *) *data + color * ( mi->geo_width / mi->calib_divisor ) + i) = (uint8_t) MIN(0xff, value); } else { for ( line = 0; line < lines; line++ ) value += *((uint16_t *) ms->shading_image + line * 3 * mi->geo_width / mi->calib_divisor + 3 * i + color); value /= lines; #ifndef MICROTEK2_CALIB_USE_MEDIAN *((uint16_t *) *data + color * ( mi->geo_width / mi->calib_divisor ) + i) = (uint16_t) MIN(0xffff, value); #else *((uint16_t *) *data + color * ( mi->geo_width / mi->calib_divisor ) + i) = value; #endif } } } break; default: DBG(1, "prepare_shading_data: Unsupported data format 0x%02x\n", mi->data_format); status = SANE_STATUS_UNSUPPORTED; } #ifdef MICROTEK2_CALIB_USE_MEDIAN DBG(100, "prepare_shading_data: free sortbuf at %p\n", (void *) sortbuf); free(sortbuf); sortbuf = NULL; #endif return status; } /*---------- read_cx_shading() -----------------------------------------------*/ static SANE_Status read_cx_shading(Microtek2_Scanner *ms) { SANE_Status status; Microtek2_Device *md; md = ms->dev; DBG(30, "read_cx_shading: ms=%p\n",(void *) ms); md->shading_table_contents = ms->mode; if ( ms->mode == MS_MODE_COLOR ) ms->current_color = MS_COLOR_ALL; else ms->current_color = MS_COLOR_GREEN; /* for grayscale */ ms->word = 1; ms->dark = 0; status = read_cx_shading_image(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; ms->word = 0; /* the Windows driver reads dark shading with word=0 */ ms->dark = 1; status = read_cx_shading_image(ms); if ( status != SANE_STATUS_GOOD ) goto cleanup; return SANE_STATUS_GOOD; cleanup: cleanup_scanner(ms); return status; } /*---------- read_cx_shading_image() -----------------------------------------*/ static SANE_Status read_cx_shading_image(Microtek2_Scanner *ms) { SANE_Status status; Microtek2_Device *md; uint32_t shading_bytes, linesize, buffer_size; uint8_t *buf; int max_lines, lines_to_read, remaining_lines; md = ms->dev; shading_bytes = ms->n_control_bytes * 8 * md->shading_length; if ( ms->current_color == MS_COLOR_ALL ) shading_bytes *= 3; if ( ms->word == 1 ) shading_bytes *= 2; if ( ms->shading_image ) { free((void *) ms->shading_image); ms->shading_image = NULL; } ms->shading_image = malloc(shading_bytes); DBG(100, "read_cx_shading: ms->shading_image=%p, malloc'd %d bytes\n", ms->shading_image, shading_bytes); if ( ms->shading_image == NULL ) { DBG(1, "read_cx_shading: malloc for cx_shading buffer failed\n"); return SANE_STATUS_NO_MEM; } buf = ms->shading_image; DBG(30, "read_cx_shading_image: ms=%p, shading_bytes=%d\n", (void *) ms, shading_bytes); linesize = shading_bytes / md->shading_length; #ifdef TESTBACKEND max_lines = 5000000 / linesize; #else max_lines = sanei_scsi_max_request_size / linesize; #endif /* the following part is like in "read_shading_image" */ remaining_lines = md->shading_length; while ( remaining_lines > 0 ) { lines_to_read = MIN(max_lines, remaining_lines); buffer_size = lines_to_read * linesize; status = scsi_read_shading(ms, buf, buffer_size); if ( status != SANE_STATUS_GOOD ) { DBG(1, "read_cx_shading: '%s'\n", sane_strstatus(status)); return status; } remaining_lines -= lines_to_read; buf += buffer_size; } status = calc_cx_shading_line(ms); if ( status != SANE_STATUS_GOOD ) { DBG(1, "read_cx_shading: '%s'\n", sane_strstatus(status)); return status; } if ( ms->shading_image ) { DBG(100, "free memory for ms->shading_image at %p\n", ms->shading_image); free((void *) ms->shading_image); ms->shading_image = NULL; } return status; } /*---------- calc_cx_shading_line() ------------------------------------------*/ /* calculates the mean value of the shading lines and stores one line of */ /* 8-bit shading data. Scanning direction + color sequence remain as they are */ /* ToDo: more than 8-bit data */ static SANE_Status calc_cx_shading_line(Microtek2_Scanner *ms) { Microtek2_Device *md; SANE_Status status; uint8_t *current_byte, *buf, *shading_table_pointer; uint8_t color, factor; uint32_t shading_line_pixels, shading_line_bytes, shading_data_bytes, line, i, accu, color_offset; uint16_t *sortbuf, value; md = ms->dev; status = SANE_STATUS_GOOD; sortbuf = malloc( md->shading_length * sizeof(float) ); DBG(100, "calc_cx_shading: sortbuf= %p, malloc'd %lu Bytes\n", (void *) sortbuf, (u_long) (md->shading_length * sizeof(float))); if ( sortbuf == NULL ) { DBG(1, "calc_cx_shading: malloc for sort buffer failed\n"); return SANE_STATUS_NO_MEM; } buf = ms->shading_image; shading_line_pixels = ms->n_control_bytes * 8; /* = 2560 for 330CX */ shading_line_bytes = shading_line_pixels; /* grayscale */ if ( ms->mode == MS_MODE_COLOR ) /* color */ shading_line_bytes *= 3; shading_data_bytes = shading_line_bytes; /* 8-bit color depth */ if (ms->word == 1) /* > 8-bit color depth */ shading_data_bytes *= 2; factor = 4; /* shading bit depth = 10bit; shading line bit depth = 8bit */ if (ms->dark == 0) /* white shading data */ { if ( md->shading_table_w ) free( (void *)md->shading_table_w ); md->shading_table_w = (uint8_t *) malloc(shading_line_bytes); DBG(100, "calc_cx_shading: md->shading_table_w=%p, malloc'd %d bytes\n", md->shading_table_w, shading_line_bytes); if ( md->shading_table_w == NULL ) { DBG(100, "calc_cx_shading: malloc for white shadingtable failed\n"); status = SANE_STATUS_NO_MEM; cleanup_scanner(ms); } shading_table_pointer = md->shading_table_w; } else /* dark shading data */ { if ( md->shading_table_d ) free( (void *)md->shading_table_d); md->shading_table_d = (uint8_t *) malloc(shading_line_bytes); DBG(100, "calc_cx_shading: md->shading_table_d=%p, malloc'd %d bytes\n", md->shading_table_d, shading_line_bytes); if ( md->shading_table_d == NULL ) { DBG(1, "calc_cx_shading: malloc for dark shading table failed\n"); status = SANE_STATUS_NO_MEM; cleanup_scanner(ms); } shading_table_pointer = md->shading_table_d; } DBG(30, "calc_cx_shading_line: ms=%p\n" "md->shading_table_w=%p\n" "md->shading_table_d=%p\n" "shading_line_bytes=%d\n" "shading_line_pixels=%d\n" "shading_table_pointer=%p\n", (void *) ms, md->shading_table_w, md->shading_table_d, shading_line_bytes, shading_line_pixels, shading_table_pointer); /* calculating the median pixel values over the shading lines */ /* and write them to the shading table */ for (color = 0; color < 3; color++) { color_offset = color * shading_line_pixels; if ( ms->word == 1 ) color_offset *=2; for (i = 0; i < shading_line_pixels; i++) { value = 0; for (line = 0; line < md->shading_length; line++) { current_byte = buf + ( line * shading_data_bytes ) + color_offset + i; accu = *current_byte; /* word shading data: the lower bytes per line and color are */ /* transfered first in one block and then the high bytes */ /* in one block */ /* the dark shading data is also 10 bit, but only the */ /* low byte is transferred (ms->word = 0) */ if ( ms->word == 1 ) { current_byte = buf + ( line * shading_data_bytes ) + color_offset + shading_line_pixels + i; accu += ( *current_byte * 256 ); } *( sortbuf + line ) = accu; } /* this is the Median filter: sort the values ascending and take the middlest */ qsort(sortbuf, md->shading_length, sizeof(float), (qsortfunc)compare_func_16); value = *( sortbuf + ( md->shading_length - 1 ) / 2 ); *shading_table_pointer = (uint8_t) (value / factor); shading_table_pointer++; } if ( ms->mode != MS_MODE_COLOR ) break; } return status; } /*---------- get_lut_size() --------------------------------------------------*/ static SANE_Status get_lut_size(Microtek2_Info *mi, int *max_lut_size, int *lut_entry_size) { /* returns the maximum lookup table size. A device might indicate */ /* several lookup table sizes. */ DBG(30, "get_lut_size: mi=%p\n", (void *) mi); *max_lut_size = 0; *lut_entry_size = 0; /* Normally this function is used for both gamma and shading tables */ /* If, however, the device indicates, that it does not support */ /* lookup tables, we set these values as if the device has a maximum */ /* bitdepth of 12, and these values are only used to determine the */ /* size of the shading table */ if ( MI_LUTCAP_NONE(mi->lut_cap) ) { *max_lut_size = 4096; *lut_entry_size = 2; } if ( mi->lut_cap & MI_LUTCAP_256B ) { *max_lut_size = 256; *lut_entry_size = 1; } if ( mi->lut_cap & MI_LUTCAP_1024B ) { *max_lut_size = 1024; *lut_entry_size = 1; } if ( mi->lut_cap & MI_LUTCAP_1024W ) { *max_lut_size = 1024; *lut_entry_size = 2; } if ( mi->lut_cap & MI_LUTCAP_4096B ) { *max_lut_size = 4096; *lut_entry_size = 1; } if ( mi->lut_cap & MI_LUTCAP_4096W ) { *max_lut_size = 4096; *lut_entry_size = 2; } if ( mi->lut_cap & MI_LUTCAP_64k_W ) { *max_lut_size = 65536; *lut_entry_size = 2; } if ( mi->lut_cap & MI_LUTCAP_16k_W ) { *max_lut_size = 16384; *lut_entry_size = 2; } DBG(30, "get_lut_size: mi=%p, lut_size=%d, lut_entry_size=%d\n", (void *) mi, *max_lut_size, *lut_entry_size); return SANE_STATUS_GOOD; } /*---------- calculate_gamma() -----------------------------------------------*/ static SANE_Status calculate_gamma(Microtek2_Scanner *ms, uint8_t *pos, int color, char *mode) { Microtek2_Device *md; Microtek2_Info *mi; double exp; double mult; double steps; unsigned int val; int i; int factor; /* take into account the differences between the */ /* possible values for the color and the number */ /* of bits the scanner works with internally. */ /* If depth == 1 handle this as if the maximum */ /* depth was chosen */ DBG(30, "calculate_gamma: ms=%p, pos=%p, color=%d, mode=%s\n", (void *) ms, pos, color, mode); md = ms->dev; mi = &md->info[md->scan_source]; /* does this work everywhere ? */ if ( md->model_flags & MD_NO_GAMMA ) { factor = 1; mult = (double) (ms->lut_size - 1); } else { if ( mi->depth & MI_HASDEPTH_16 ) { factor = ms->lut_size / 65536; mult = 65535.0; } else if ( mi->depth & MI_HASDEPTH_14 ) { factor = ms->lut_size / 16384; mult = 16383.0; } else if ( mi->depth & MI_HASDEPTH_12 ) { factor = ms->lut_size / 4096; mult = 4095.0; } else if ( mi->depth & MI_HASDEPTH_10 ) { factor = ms->lut_size / 1024; mult = 1023.0; } else { factor = ms->lut_size / 256; mult = 255.0; } } #if 0 factor = ms->lut_size / (int) pow(2.0, (double) ms->depth); mult = pow(2.0, (double) ms->depth) - 1.0; /* depending on output size */ #endif steps = (double) (ms->lut_size - 1); /* depending on input size */ DBG(30, "calculate_gamma: factor=%d, mult =%f, steps=%f, mode=%s\n", factor, mult, steps, ms->val[OPT_GAMMA_MODE].s); if ( strcmp(mode, MD_GAMMAMODE_SCALAR) == 0 ) { int option; option = OPT_GAMMA_SCALAR; /* OPT_GAMMA_SCALAR_R follows OPT_GAMMA_SCALAR directly */ if ( ms->val[OPT_GAMMA_BIND].w == SANE_TRUE ) exp = 1.0 / SANE_UNFIX(ms->val[option].w); else exp = 1.0 / SANE_UNFIX(ms->val[option + color + 1].w); for ( i = 0; i < ms->lut_size; i++ ) { val = (unsigned int) (mult * pow((double) i / steps, exp) + .5); if ( ms->lut_entry_size == 2 ) *((uint16_t *) pos + i) = (uint16_t) val; else *((uint8_t *) pos + i) = (uint8_t) val; } } else if ( strcmp(mode, MD_GAMMAMODE_CUSTOM) == 0 ) { int option; SANE_Int *src; option = OPT_GAMMA_CUSTOM; if ( ms->val[OPT_GAMMA_BIND].w == SANE_TRUE ) src = ms->val[option].wa; else src = ms->val[option + color + 1].wa; for ( i = 0; i < ms->lut_size; i++ ) { if ( ms->lut_entry_size == 2 ) *((uint16_t *) pos + i) = (uint16_t) (src[i] / factor); else *((uint8_t *) pos + i) = (uint8_t) (src[i] / factor); } } else if ( strcmp(mode, MD_GAMMAMODE_LINEAR) == 0 ) { for ( i = 0; i < ms->lut_size; i++ ) { if ( ms->lut_entry_size == 2 ) *((uint16_t *) pos + i) = (uint16_t) (i / factor); else *((uint8_t *) pos + i) = (uint8_t) (i / factor); } } return SANE_STATUS_GOOD; } /*---------- shading_function() ----------------------------------------------*/ static SANE_Status shading_function(Microtek2_Scanner *ms, uint8_t *data) { Microtek2_Device *md; Microtek2_Info *mi; uint32_t value; int color; int i; DBG(40, "shading_function: ms=%p, data=%p\n", (void *) ms, data); md = ms->dev; mi = &md->info[md->scan_source]; /* mi = &md->info[MD_SOURCE_FLATBED]; */ if ( ms->lut_entry_size == 1 ) { DBG(1, "shading_function: wordsize = 1 unsupported\n"); return SANE_STATUS_IO_ERROR; } for ( color = 0; color < 3; color++ ) { for ( i = 0; i < ( mi->geo_width / mi->calib_divisor ); i++) { value = *((uint16_t *) data + color * ( mi->geo_width / mi->calib_divisor ) + i); switch ( mi->shtrnsferequ ) { case 0x00: /* output == input */ break; case 0x01: value = (ms->lut_size * ms->lut_size) / value; *((uint16_t *) data + color * ( mi->geo_width / mi->calib_divisor ) + i) = (uint16_t) MIN(0xffff, value); break; case 0x11: value = (ms->lut_size * ms->lut_size) / (uint32_t) ( (double) value * ((double) mi->balance[color] / 255.0)); *((uint16_t *) data + color * ( mi->geo_width / mi->calib_divisor ) + i) = (uint16_t) MIN(0xffff, value); break; case 0x15: value = (uint32_t) ( ( 1073741824 / (double) value ) * ( (double) mi->balance[color] / 256.0) ); value = MIN(value, (uint32_t)65535); *((uint16_t *) data + color * ( mi->geo_width / mi->calib_divisor ) + i) = (uint16_t) MIN(0xffff, value); break; default: DBG(1, "Unsupported shading transfer function 0x%02x\n", mi->shtrnsferequ ); break; } } } return SANE_STATUS_GOOD; } /*---------- set_exposure() --------------------------------------------------*/ static void set_exposure(Microtek2_Scanner *ms) { /* This function manipulates the colors according to the exposure time */ /* settings on models where they are ignored. Currently this seems to */ /* be the case for all models with the data format chunky data. They */ /* all have tables with two byte gamma output, so for now we ignore */ /* gamma tables with one byte output */ Microtek2_Device *md; Microtek2_Info *mi; int color; int size; int depth; int maxval; int byte; uint32_t val32; uint8_t *from; uint8_t exposure; uint8_t exposure_rgb[3]; DBG(30, "set_exposure: ms=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; if ( ms->lut_entry_size == 1 ) { DBG(1, "set_exposure: 1 byte gamma output tables currently ignored\n"); return; } if ( mi->depth & MI_HASDEPTH_16 ) depth = 16; else if ( mi->depth & MI_HASDEPTH_14 ) depth = 14; else if ( mi->depth & MI_HASDEPTH_12 ) depth = 12; else if ( mi->depth & MI_HASDEPTH_10 ) depth = 10; else depth = 8; maxval = ( 1 << depth ) - 1; from = ms->gamma_table; size = ms->lut_size; /* first master channel, apply transformation to all colors */ exposure = ms->exposure_m; for ( byte = 0; byte < ms->lut_size; byte++ ) { for ( color = 0; color < 3; color++) { val32 = (uint32_t) *((uint16_t *) from + color * size + byte); val32 = MIN(val32 + val32 * (2 * (uint32_t) exposure / 100), (uint32_t) maxval); *((uint16_t *) from + color * size + byte) = (uint16_t) val32; } } /* and now apply transformation to each channel */ exposure_rgb[0] = ms->exposure_r; exposure_rgb[1] = ms->exposure_g; exposure_rgb[2] = ms->exposure_b; for ( color = 0; color < 3; color++ ) { for ( byte = 0; byte < size; byte++ ) { val32 = (uint32_t) *((uint16_t *) from + color * size + byte); val32 = MIN(val32 + val32 * (2 * (uint32_t) exposure_rgb[color] / 100), (uint32_t) maxval); *((uint16_t *) from + color * size + byte) = (uint16_t) val32; } } return; } /*---------- reader_process() ------------------------------------------------*/ static int reader_process(void *data) { Microtek2_Scanner *ms = (Microtek2_Scanner *) data; SANE_Status status; Microtek2_Info *mi; Microtek2_Device *md; struct SIGACTION act; sigset_t sigterm_set; static uint8_t *temp_current = NULL; DBG(30, "reader_process: ms=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; if (sanei_thread_is_forked()) close(ms->fd[0]); sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); memset (&act, 0, sizeof (act)); act.sa_handler = signal_handler; sigaction (SIGTERM, &act, 0); ms->fp = fdopen(ms->fd[1], "w"); if ( ms->fp == NULL ) { DBG(1, "reader_process: fdopen() failed, errno=%d\n", errno); return SANE_STATUS_IO_ERROR; } if ( ms->auto_adjust == 1 ) { if ( temp_current == NULL ) temp_current = ms->temporary_buffer; } while ( ms->src_remaining_lines > 0 ) { ms->src_lines_to_read = MIN(ms->src_remaining_lines, ms->src_max_lines); ms->transfer_length = ms->src_lines_to_read * ms->bpl; DBG(30, "reader_process: transferlength=%d, lines=%d, linelength=%d, " "real_bpl=%d, srcbuf=%p\n", ms->transfer_length, ms->src_lines_to_read, ms->bpl, ms->real_bpl, ms->buf.src_buf); sigprocmask (SIG_BLOCK, &sigterm_set, 0); status = scsi_read_image(ms, ms->buf.src_buf, (ms->depth > 8) ? 2 : 1); sigprocmask (SIG_UNBLOCK, &sigterm_set, 0); if ( status != SANE_STATUS_GOOD ) return SANE_STATUS_IO_ERROR; ms->src_remaining_lines -= ms->src_lines_to_read; /* prepare data for frontend */ switch (ms->mode) { case MS_MODE_COLOR: if ( ! mi->onepass ) /* TODO */ { DBG(1, "reader_process: 3 pass not yet supported\n"); return SANE_STATUS_IO_ERROR; } else { switch ( mi->data_format ) { case MI_DATAFMT_CHUNKY: case MI_DATAFMT_9800: status = chunky_proc_data(ms); if ( status != SANE_STATUS_GOOD ) return status; break; case MI_DATAFMT_LPLCONCAT: status = lplconcat_proc_data(ms); if ( status != SANE_STATUS_GOOD ) return status; break; case MI_DATAFMT_LPLSEGREG: status = segreg_proc_data(ms); if ( status != SANE_STATUS_GOOD ) return status; break; case MI_DATAFMT_WORDCHUNKY: status = wordchunky_proc_data(ms); if ( status != SANE_STATUS_GOOD ) return status; break; default: DBG(1, "reader_process: format %d\n", mi->data_format); return SANE_STATUS_IO_ERROR; } } break; case MS_MODE_GRAY: status = gray_proc_data(ms); if ( status != SANE_STATUS_GOOD ) return status; break; case MS_MODE_HALFTONE: case MS_MODE_LINEART: status = proc_onebit_data(ms); if ( status != SANE_STATUS_GOOD ) return status; break; case MS_MODE_LINEARTFAKE: if ( ms->auto_adjust == 1 ) status = auto_adjust_proc_data(ms, &temp_current); else status = lineartfake_proc_data(ms); if ( status != SANE_STATUS_GOOD ) return status; break; default: DBG(1, "reader_process: Unknown scan mode %d\n", ms->mode); return SANE_STATUS_IO_ERROR; } } fclose(ms->fp); return SANE_STATUS_GOOD; } /*---------- chunky_proc_data() ----------------------------------------------*/ static SANE_Status chunky_proc_data(Microtek2_Scanner *ms) { SANE_Status status; Microtek2_Device *md; uint32_t line; uint8_t *from; int pad; int bpp; /* bytes per pixel */ int bits_pp_in; /* bits per pixel input */ int bits_pp_out; /* bits per pixel output */ int bpl_ppl_diff; DBG(30, "chunky_proc_data: ms=%p\n", (void *) ms); md = ms->dev; bits_pp_in = ms->bits_per_pixel_in; bits_pp_out = ms->bits_per_pixel_out; pad = (int) ceil( (double) (ms->ppl * bits_pp_in) / 8.0 ) % 2; bpp = bits_pp_out / 8; /* Some models have 3 * ppl + 6 bytes per line if the number of pixels */ /* per line is even and 3 * ppl + 3 bytes per line if the number of */ /* pixels per line is odd. According to the documentation it should be */ /* bpl = 3*ppl (even number of pixels) or bpl=3*ppl+1 (odd number of */ /* pixels. Even worse: On different models it is different at which */ /* position in a scanline the image data starts. bpl_ppl_diff tries */ /* to fix this. */ if ( (md->model_flags & MD_OFFSET_2) && pad == 1 ) bpl_ppl_diff = 2; else bpl_ppl_diff = 0; #if 0 if ( md->revision == 1.00 && mi->model_code != 0x81 ) bpl_ppl_diff = ms->bpl - ( 3 * ms->ppl * bpp ) - pad; else bpl_ppl_diff = ms->bpl - ( 3 * ms->ppl * bpp ); if ( md->revision > 1.00 ) bpl_ppl_diff = ms->bpl - ( 3 * ms->ppl * bpp ); else bpl_ppl_diff = ms->bpl - ( 3 * ms->ppl * bpp ) - pad; #endif from = ms->buf.src_buf; from += bpl_ppl_diff; DBG(30, "chunky_proc_data: lines=%d, bpl=%d, ppl=%d, bpp=%d, depth=%d" " junk=%d\n", ms->src_lines_to_read, ms->bpl, ms->ppl, bpp, ms->depth, bpl_ppl_diff); for ( line = 0; line < (uint32_t) ms->src_lines_to_read; line++ ) { status = chunky_copy_pixels(ms, from); if ( status != SANE_STATUS_GOOD ) return status; from += ms->bpl; } return SANE_STATUS_GOOD; } /*---------- chunky_copy_pixels() --------------------------------------------*/ static SANE_Status chunky_copy_pixels(Microtek2_Scanner *ms, uint8_t *from) { Microtek2_Device *md; uint32_t pixel; int color; DBG(30, "chunky_copy_pixels: from=%p, pixels=%d, fp=%p, depth=%d\n", from, ms->ppl, (void *) ms->fp, ms->depth); md = ms->dev; if ( ms->depth > 8 ) { if ( !( md->model_flags & MD_16BIT_TRANSFER ) ) { int scale1; int scale2; uint16_t val16; scale1 = 16 - ms->depth; scale2 = 2 * ms->depth - 16; for ( pixel = 0; pixel < ms->ppl; pixel++ ) { for ( color = 0; color < 3; color++ ) { val16 = *( (uint16_t *) from + 3 * pixel + color ); val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); fwrite((void *) &val16, 2, 1, ms->fp); } } } else { fwrite((void *) from, 2, 3 * ms->ppl, ms->fp); } } else if ( ms->depth == 8 ) { fwrite((void *) from, 1, 3 * ms->ppl, ms->fp); } else { DBG(1, "chunky_copy_pixels: Unknown depth %d\n", ms->depth); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /*---------- segreg_proc_data() ----------------------------------------------*/ static SANE_Status segreg_proc_data(Microtek2_Scanner *ms) { SANE_Status status; Microtek2_Device *md; Microtek2_Info *mi; char colormap[] = "RGB"; uint8_t *from; uint32_t lines_to_deliver; int bpp; /* bytes per pixel */ int bpf; /* bytes per frame including color indicator */ int pad; int colseq2; int color; int save_current_src; int frame; DBG(30, "segreg_proc_data: ms=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; /* take a trailing junk byte into account */ pad = (int) ceil( (double) (ms->ppl * ms->bits_per_pixel_in) / 8.0 ) % 2; bpp = ms->bits_per_pixel_out / 8; /* bits_per_pixel_out is either 8 or 16 */ bpf = ms->bpl / 3; DBG(30, "segreg_proc_data: lines=%d, bpl=%d, ppl=%d, bpf=%d, bpp=%d,\n" "depth=%d, pad=%d, freelines=%d, calib_backend=%d\n", ms->src_lines_to_read, ms->bpl, ms->ppl, bpf, bpp, ms->depth, pad, ms->buf.free_lines, ms->calib_backend); /* determine how many planes of each color are in the source buffer */ from = ms->buf.src_buf; for ( frame = 0; frame < 3 * ms->src_lines_to_read; frame++, from += bpf ) { switch ( *from ) { case 'R': ++ms->buf.planes[0][MS_COLOR_RED]; break; case 'G': ++ms->buf.planes[0][MS_COLOR_GREEN]; break; case 'B': ++ms->buf.planes[0][MS_COLOR_BLUE]; break; default: DBG(1, "segreg_proc_data: unknown color indicator (1) " "0x%02x\n", *from); return SANE_STATUS_IO_ERROR; } } ms->buf.free_lines -= ms->src_lines_to_read; save_current_src = ms->buf.current_src; if ( ms->buf.free_lines < ms->src_max_lines ) { ms->buf.current_src = !ms->buf.current_src; ms->buf.src_buf = ms->buf.src_buffer[ms->buf.current_src]; ms->buf.free_lines = ms->buf.free_max_lines; } else ms->buf.src_buf += ms->src_lines_to_read * ms->bpl; colseq2 = mi->color_sequence[2]; lines_to_deliver = ms->buf.planes[0][colseq2] + ms->buf.planes[1][colseq2]; if ( lines_to_deliver == 0 ) return SANE_STATUS_GOOD; DBG(30, "segreg_proc_data: planes[0][0]=%d, planes[0][1]=%d, " "planes[0][2]=%d\n", ms->buf.planes[0][0], ms->buf.planes[0][1], ms->buf.planes[0][2] ); DBG(30, "segreg_proc_data: planes[1][0]=%d, planes[1][1]=%d, " "planes[1][2]=%d\n", ms->buf.planes[1][0], ms->buf.planes[1][1], ms->buf.planes[1][2] ); while ( lines_to_deliver > 0 ) { for ( color = 0; color < 3; color++ ) { /* get the position of the next plane for each color */ do { if ( *ms->buf.current_pos[color] == colormap[color] ) break; ms->buf.current_pos[color] += bpf; } while ( 1 ); ms->buf.current_pos[color] += 2; /* skip color indicator */ } status = segreg_copy_pixels(ms); if ( status != SANE_STATUS_GOOD ) { DBG(1, "segreg_copy_pixels:status %d\n", status); return status; } for ( color = 0; color < 3; color++ ) { /* skip a padding byte at the end, if present */ ms->buf.current_pos[color] += pad; if ( ms->buf.planes[1][color] > 0 ) { --ms->buf.planes[1][color]; if ( ms->buf.planes[1][color] == 0 ) /* we have copied from the prehold buffer and are */ /* done now, we continue with the source buffer */ ms->buf.current_pos[color] = ms->buf.src_buffer[save_current_src]; } else { --ms->buf.planes[0][color]; if ( ms->buf.planes[0][color] == 0 && ms->buf.current_src != save_current_src ) ms->buf.current_pos[color] = ms->buf.src_buffer[ms->buf.current_src]; } } DBG(100, "planes_to_deliver=%d\n", lines_to_deliver); --lines_to_deliver; } if ( ms->buf.current_src != save_current_src ) { for ( color = 0; color < 3; color++ ) { ms->buf.planes[1][color] += ms->buf.planes[0][color]; ms->buf.planes[0][color] = 0; } } DBG(30, "segreg_proc_data: src_buf=%p, free_lines=%d\n", ms->buf.src_buf, ms->buf.free_lines); return SANE_STATUS_GOOD; } /*---------- segreg_copy_pixels() --------------------------------------------*/ static SANE_Status segreg_copy_pixels(Microtek2_Scanner *ms) { Microtek2_Device *md; Microtek2_Info *mi; uint32_t pixel; int color, i, gamma_by_backend, right_to_left, scale1, scale2, bpp_in; float s_w, s_d; /* shading byte from condensed_shading */ float val, maxval = 0, shading_factor = 0; uint16_t val16 = 0; uint8_t val8 = 0; uint8_t *from_effective; uint8_t *gamma[3]; float f[3]; /* color balance factor */ md = ms->dev; mi = &md->info[md->scan_source]; gamma_by_backend = md->model_flags & MD_NO_GAMMA ? 1 : 0; right_to_left = mi->direction & MI_DATSEQ_RTOL; scale1 = 16 - ms->depth; scale2 = 2 * ms->depth - 16; bpp_in = ( ms->bits_per_pixel_in + 7 ) / 8; /*Bytes per pixel from scanner*/ if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend) { maxval = (float) pow(2.0, (float) ms->depth) - 1.0; s_w = maxval; s_d = 0.0; shading_factor = (float) pow(2.0, (double) (md->shading_depth - ms->depth) ); } if ( gamma_by_backend ) { i = (ms->depth > 8) ? 2 : 1; for ( color = 0; color < 3; color++) gamma[color] = ms->gamma_table + i * (int) pow(2.0, (double)ms->depth); } DBG(30, "segreg_copy_pixels: pixels=%d\n", ms->ppl); DBG(100, "segreg_copy_pixels: buffer 0x%p, right_to_left=%d, depth=%d\n", (void *) ms->buf.current_pos, right_to_left, ms->depth); for (color = 0; color < 3; color++ ) f[color] = (float) ms->balance[color] / 100.0; DBG(100, "segreg_copy_pixels: color balance:\n" " ms->balance[R]=%d, ms->balance[G]=%d, ms->balance[B]=%d\n", ms->balance[0], ms->balance[1], ms->balance[2]); for ( pixel = 0; pixel < ms->ppl; pixel++ ) { for ( color = 0; color < 3; color++ ) { if ( right_to_left ) from_effective = ms->buf.current_pos[color] + ( ms->ppl - 1 - pixel ) * bpp_in; else from_effective = ms->buf.current_pos[color] + pixel * bpp_in; if ( ms->depth > 8 ) val = (float) *(uint16_t *)from_effective; else if ( ms->depth == 8 ) val = (float) *from_effective; else { DBG(1, "segreg_copy_pixels: Unknown depth %d\n", ms->depth); return SANE_STATUS_IO_ERROR; } if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend && ( ms->condensed_shading_w != NULL )) /* apply shading by backend */ { get_cshading_values(ms, color, pixel, shading_factor, right_to_left, &s_d, &s_w); if ( s_w == s_d ) s_w = s_d + 1; if ( val < s_d ) val = s_d; val = maxval *( val - s_d ) / ( s_w - s_d ); val *= f[color]; /* if scanner doesn't support brightness, contrast */ if ( md->model_flags & MD_NO_ENHANCEMENTS ) { val += ( ( ms->brightness_m - 128 ) * 2 ); val = ( val - 128 ) * ( ms->contrast_m / 128 ) + 128; } val = MAX( 0.0, val); val = MIN( maxval, val ); } val16 = (uint16_t) val; val8 = (uint8_t) val; /* apply gamma correction if needed */ if ( gamma_by_backend ) { if ( ms->depth > 8 ) val16 = *((uint16_t *) gamma[color] + val16); else val8 = gamma[color][val8]; } if ( ms->depth > 8 ) { val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); fwrite((void *) &val16, 2, 1, ms->fp); } else { fputc((unsigned char) val8, ms->fp); } } } for ( color = 0; color < 3; color++ ) { ms->buf.current_pos[color] += ms->ppl; if ( ms->depth > 8 ) ms->buf.current_pos[color] += ms->ppl; } return SANE_STATUS_GOOD; } /*---------- lplconcat_proc_data() -------------------------------------------*/ static SANE_Status lplconcat_proc_data(Microtek2_Scanner *ms) { SANE_Status status; Microtek2_Device *md; Microtek2_Info *mi; uint32_t line; uint8_t *from[3]; uint8_t *save_from[3]; int color; int bpp; int gamma_by_backend; int right_to_left; /* 0=left to right, 1=right to left */ DBG(30, "lplconcat_proc_data: ms=%p\n", (void *) ms); /* This data format seems to honour the color sequence indicator */ md = ms->dev; mi = &md->info[md->scan_source]; bpp = ms->bits_per_pixel_out / 8; /* ms->bits_per_pixel_out is 8 or 16 */ right_to_left = mi->direction & MI_DATSEQ_RTOL; gamma_by_backend = md->model_flags & MD_NO_GAMMA ? 1 : 0; if ( right_to_left == 1 ) { for ( color = 0; color < 3; color++ ) { from[color] = ms->buf.src_buf + ( mi->color_sequence[color] + 1 ) * ( ms->bpl / 3 ) - bpp - (ms->bpl - 3 * ms->ppl * bpp) / 3; } } else for ( color = 0; color < 3; color++ ) from[color] = ms->buf.src_buf + mi->color_sequence[color] * ( ms->bpl / 3 ); for ( line = 0; line < (uint32_t) ms->src_lines_to_read; line++ ) { for ( color = 0 ; color < 3; color++ ) save_from[color] = from[color]; status = lplconcat_copy_pixels(ms, from, right_to_left, gamma_by_backend); if ( status != SANE_STATUS_GOOD ) return status; for ( color = 0; color < 3; color++ ) from[color] = save_from[color] + ms->bpl; } return SANE_STATUS_GOOD; } /*---------- lplconcat_copy_pixels() -----------------------------------------*/ static SANE_Status lplconcat_copy_pixels(Microtek2_Scanner *ms, uint8_t **from, int right_to_left, int gamma_by_backend) { Microtek2_Device *md; Microtek2_Info *mi; uint32_t pixel; uint16_t val16 = 0; uint8_t val8 = 0; uint8_t *gamma[3]; float s_d; /* dark shading pixel */ float s_w; /* white shading pixel */ float shading_factor = 0; float f[3]; /* color balance factor */ float val, maxval = 0; int color; int step, scale1, scale2; int i; DBG(30, "lplconcat_copy_pixels: ms=%p, righttoleft=%d, gamma=%d,\n", (void *) ms, right_to_left, gamma_by_backend); md = ms->dev; mi = &md->info[md->scan_source]; if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend) { shading_factor = (float) pow(2.0,(double)(md->shading_depth - ms->depth)); maxval = (float) pow(2.0, (double) ms->depth) - 1.0; s_w = maxval; s_d = 0.0; } step = ( right_to_left == 1 ) ? -1 : 1; if ( ms->depth > 8 ) step *= 2; scale1 = 16 - ms->depth; scale2 = 2 * ms->depth - 16; if ( gamma_by_backend ) { i = ( ms->depth > 8 ) ? 2 : 1; for ( color = 0; color < 3; color++ ) gamma[color] = ms->gamma_table + i * (int) pow(2.0,(double)ms->depth); } for (color = 0; color < 3; color++ ) f[color] = (float)ms->balance[color] / 100.0; DBG(100, "lplconcat_copy_pixels: color balance:\n" " ms->balance[R]=%d, ms->balance[G]=%d, ms->balance[B]=%d\n", ms->balance[0], ms->balance[1], ms->balance[2]); for ( pixel = 0; pixel < ms->ppl; pixel++ ) { for ( color = 0; color < 3; color++ ) { if ( ms->depth > 8 ) val = (float) *(uint16_t *) from[color]; else if ( ms->depth == 8 ) val = (float) *from[color]; else { DBG(1, "lplconcat_copy_pixels: Unknown depth %d\n", ms->depth); return SANE_STATUS_IO_ERROR; } if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend && ( ms->condensed_shading_w != NULL )) /* apply shading by backend */ { get_cshading_values(ms, mi->color_sequence[color], pixel, shading_factor, right_to_left, &s_d, &s_w); if ( val < s_d ) val = s_d; if ( s_w == s_d ) s_w = s_d + 1; val = ( maxval * ( val - s_d ) ) / (s_w - s_d); val *= f[color]; /* apply color balance */ /* if scanner doesn't support brightness, contrast ... */ if ( md->model_flags & MD_NO_ENHANCEMENTS ) { val += ( ( ms->brightness_m - 128 ) * 2 ); val = ( val - 128 ) * ( ms->contrast_m / 128 ) + 128; } if ( val > maxval ) val = maxval; if ( val < 0.0 ) val = 0.0; } val16 = (uint16_t) val; val8 = (uint8_t) val; /* apply gamma correction if needed */ if ( gamma_by_backend ) { if ( ms->depth > 8 ) val16 = *((uint16_t *) gamma[color] + val16); else val8 = gamma[color][val8]; } if ( ms->depth > 8 ) { val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); fwrite((void *) &val16, 2, 1, ms->fp); } else { fputc((unsigned char) val8, ms->fp); } from[color] += step; } } return SANE_STATUS_GOOD; } /*---------- wordchunky_proc_data() ------------------------------------------*/ static SANE_Status wordchunky_proc_data(Microtek2_Scanner *ms) { SANE_Status status; uint8_t *from; uint32_t line; DBG(30, "wordchunky_proc_data: ms=%p\n", (void *) ms); from = ms->buf.src_buf; for ( line = 0; line < (uint32_t) ms->src_lines_to_read; line++ ) { status = wordchunky_copy_pixels(from, ms->ppl, ms->depth, ms->fp); if ( status != SANE_STATUS_GOOD ) return status; from += ms->bpl; } return SANE_STATUS_GOOD; } /*---------- wordchunky_copy_pixels() ----------------------------------------*/ static SANE_Status wordchunky_copy_pixels(uint8_t *from, uint32_t pixels, int depth, FILE *fp) { uint32_t pixel; int color; DBG(30, "wordchunky_copy_pixels: from=%p, pixels=%d, depth=%d\n", from, pixels, depth); if ( depth > 8 ) { int scale1; int scale2; uint16_t val16; scale1 = 16 - depth; scale2 = 2 * depth - 16; for ( pixel = 0; pixel < pixels; pixel++ ) { for ( color = 0; color < 3; color++ ) { val16 = *(uint16_t *) from; val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); fwrite((void *) &val16, 2, 1, fp); from += 2; } } } else if ( depth == 8 ) { pixel = 0; do { fputc((char ) *from, fp); fputc((char) *(from + 2), fp); fputc((char) *(from + 4), fp); ++pixel; if ( pixel < pixels ) { fputc((char) *(from + 1), fp); fputc((char) *(from + 3), fp); fputc((char) *(from + 5), fp); ++pixel; } from += 6; } while ( pixel < pixels ); } else { DBG(1, "wordchunky_copy_pixels: Unknown depth %d\n", depth); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /*---------- gray_proc_data() ------------------------------------------------*/ static SANE_Status gray_proc_data(Microtek2_Scanner *ms) { SANE_Status status; Microtek2_Device *md; Microtek2_Info *mi; uint8_t *from; int gamma_by_backend, bpp; int right_to_left; /* for scanning direction */ DBG(30, "gray_proc_data: lines=%d, bpl=%d, ppl=%d, depth=%d\n", ms->src_lines_to_read, ms->bpl, ms->ppl, ms->depth); md = ms->dev; mi = &md->info[md->scan_source]; gamma_by_backend = md->model_flags & MD_NO_GAMMA ? 1 : 0; right_to_left = mi->direction & MI_DATSEQ_RTOL; bpp = ( ms->bits_per_pixel_in + 7 ) / 8; if ( right_to_left == 1 ) from = ms->buf.src_buf + ms->ppl * bpp - bpp; else from = ms->buf.src_buf; do { status = gray_copy_pixels(ms, from, right_to_left, gamma_by_backend); if ( status != SANE_STATUS_GOOD ) return status; from += ms->bpl; --ms->src_lines_to_read; } while ( ms->src_lines_to_read > 0 ); return SANE_STATUS_GOOD; } /*---------- gray_copy_pixels() ----------------------------------------------*/ static SANE_Status gray_copy_pixels(Microtek2_Scanner *ms, uint8_t *from, int right_to_left, int gamma_by_backend) { Microtek2_Device *md; uint32_t pixel; uint16_t val16; uint8_t val8; int step, scale1, scale2; float val, maxval = 0; float s_w, s_d, shading_factor = 0; DBG(30, "gray_copy_pixels: pixels=%d, from=%p, fp=%p, depth=%d\n", ms->ppl, from, (void *) ms->fp, ms->depth); md = ms->dev; step = right_to_left == 1 ? -1 : 1; if ( ms->depth > 8 ) step *= 2; val = 0; scale1 = 16 - ms->depth; scale2 = 2 * ms->depth - 16; if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend) { maxval = (float) pow(2.0, (float) ms->depth) - 1.0; s_w = maxval; s_d = 0.0; shading_factor = (float) pow(2.0, (double) (md->shading_depth - ms->depth) ); } if ( ms->depth >= 8 ) { for ( pixel = 0; pixel < ms->ppl; pixel++ ) { if ( ms->depth > 8 ) val = (float) *(uint16_t *) from; if ( ms->depth == 8 ) val = (float) *from; if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend && ( ms->condensed_shading_w != NULL )) /* apply shading by backend */ { get_cshading_values(ms, 0, pixel, shading_factor, right_to_left, &s_d, &s_w); if ( val < s_d ) val = s_d; val = ( val - s_d ) * maxval / (s_w - s_d ); val = MAX( 0.0, val ); val = MIN( maxval, val ); } if ( ms->depth > 8 ) { val16 = (uint16_t) val; if ( gamma_by_backend ) val16 = *((uint16_t *) ms->gamma_table + val16); if ( !( md->model_flags & MD_16BIT_TRANSFER ) ) val16 = ( val16 << scale1 ) | ( val16 >> scale2 ); fwrite((void *) &val16, 2, 1, ms->fp); } if ( ms->depth == 8 ) { val8 = (uint8_t) val; if ( gamma_by_backend ) val8 = ms->gamma_table[(int)val8]; fputc((char)val8, ms->fp); } from += step; } } else if ( ms->depth == 4 ) { pixel = 0; while ( pixel < ms->ppl ) { fputc((char) ( ((*from >> 4) & 0x0f) | (*from & 0xf0) ), ms->fp); ++pixel; if ( pixel < ms->ppl ) fputc((char) ((*from & 0x0f) | ((*from << 4) & 0xf0)), ms->fp); from += step; ++pixel; } } else { DBG(1, "gray_copy_pixels: Unknown depth %d\n", ms->depth); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /*---------- proc_onebit_data() ----------------------------------------------*/ static SANE_Status proc_onebit_data(Microtek2_Scanner *ms) { Microtek2_Device *md; Microtek2_Info *mi; uint32_t bytes_to_copy; /* bytes per line to copy */ uint32_t line; uint32_t byte; uint32_t ppl; uint8_t *from; uint8_t to; int right_to_left; int bit; int toindex; DBG(30, "proc_onebit_data: ms=%p\n", (void *) ms); md = ms->dev; mi = &md->info[md->scan_source]; from = ms->buf.src_buf; bytes_to_copy = ( ms->ppl + 7 ) / 8 ; right_to_left = mi->direction & MI_DATSEQ_RTOL; DBG(30, "proc_onebit_data: bytes_to_copy=%d, lines=%d\n", bytes_to_copy, ms->src_lines_to_read); line = 0; to = 0; do { /* in onebit mode black and white colors are inverted */ if ( right_to_left ) { /* If the direction is right_to_left, we must skip some */ /* trailing bits at the end of the scan line and invert the */ /* bit sequence. We copy 8 bits into a byte, but these bits */ /* are normally not byte aligned. */ /* Determine the position of the first bit to copy */ ppl = ms->ppl; byte = ( ppl + 7 ) / 8 - 1; bit = ppl % 8 - 1; to = 0; toindex = 8; while ( ppl > 0 ) { to |= ( ( from[byte] >> (7 - bit) ) & 0x01); --toindex; if ( toindex == 0 ) { fputc( (char) ~to, ms->fp); toindex = 8; to = 0; } else to <<= 1; --bit; if ( bit < 0 ) { bit = 7; --byte; } --ppl; } /* print the last byte of the line, if it was not */ /* completely filled */ bit = ms->ppl % 8; if ( bit != 0 ) fputc( (char) ~(to << (7 - bit)), ms->fp); } else for ( byte = 0; byte < bytes_to_copy; byte++ ) fputc( (char) ~from[byte], ms->fp); from += ms->bpl; } while ( ++line < (uint32_t) ms->src_lines_to_read ); return SANE_STATUS_GOOD; } /*---------- lineartfake_proc_data() -----------------------------------------*/ static SANE_Status lineartfake_proc_data(Microtek2_Scanner *ms) { Microtek2_Device *md; Microtek2_Info *mi; SANE_Status status; uint8_t *from; int right_to_left; DBG(30, "lineartfake_proc_data: lines=%d, bpl=%d, ppl=%d, depth=%d\n", ms->src_lines_to_read, ms->bpl, ms->ppl, ms->depth); md = ms->dev; mi = &md->info[md->scan_source]; right_to_left = mi->direction & MI_DATSEQ_RTOL; if ( right_to_left == 1 ) from = ms->buf.src_buf + ms->ppl - 1; else from = ms->buf.src_buf; do { status = lineartfake_copy_pixels(ms, from, ms->ppl, ms->threshold, right_to_left, ms->fp); if ( status != SANE_STATUS_GOOD ) return status; from += ms->bpl; --ms->src_lines_to_read; } while ( ms->src_lines_to_read > 0 ); return SANE_STATUS_GOOD; } /*---------- lineartfake_copy_pixels() ---------------------------------------*/ static SANE_Status lineartfake_copy_pixels(Microtek2_Scanner *ms, uint8_t *from, uint32_t pixels, uint8_t threshold, int right_to_left, FILE *fp) { Microtek2_Device *md; uint32_t pixel; uint32_t bit; uint8_t dest; uint8_t val; float s_d, s_w, maxval, shading_factor, grayval; int step; DBG(30, "lineartfake_copy_pixels: from=%p,pixels=%d,threshold=%d,file=%p\n", from, pixels, threshold, (void *) fp); md = ms->dev; bit = 0; dest = 0; step = right_to_left == 1 ? -1 : 1; maxval = 255.0; s_w = maxval; s_d = 0.0; shading_factor = (float) pow(2.0, (double) (md->shading_depth - 8) ); for ( pixel = 0; pixel < pixels; pixel++ ) { if ((md->model_flags & MD_READ_CONTROL_BIT) && ms->calib_backend && ( ms->condensed_shading_w != NULL )) /* apply shading by backend */ { get_cshading_values(ms, 0, pixel, shading_factor, right_to_left, &s_d, &s_w); } else /* no shading */ { s_w = maxval; s_d = 0.0; } grayval = (float) *from; if ( grayval < s_d ) grayval = s_d; grayval = ( grayval - s_d ) * maxval / (s_w - s_d ); grayval = MAX( 0.0, grayval ); grayval = MIN( maxval, grayval ); if ( (uint8_t)grayval < threshold ) val = 1; else val = 0; dest = ( dest << 1 ) | val; bit = ( bit + 1 ) % 8; if ( bit == 0 ) /* 8 input bytes processed */ { fputc((char) dest, fp); dest = 0; } from += step; } if ( bit != 0 ) { dest <<= 7 - bit; fputc((char) dest, fp); } return SANE_STATUS_GOOD; } /*---------- auto_adjust_proc_data() -----------------------------------------*/ static SANE_Status auto_adjust_proc_data(Microtek2_Scanner *ms, uint8_t **temp_current) { Microtek2_Device *md; Microtek2_Info *mi; SANE_Status status; uint8_t *from; uint32_t line; uint32_t lines; uint32_t pixel; uint32_t threshold; int right_to_left; DBG(30, "auto_adjust_proc_data: ms=%p, temp_current=%p\n", (void *) ms, *temp_current); md = ms->dev; mi = &md->info[md->scan_source]; right_to_left = mi->direction & MI_DATSEQ_RTOL; memcpy(*temp_current, ms->buf.src_buf, ms->transfer_length); *temp_current += ms->transfer_length; threshold = 0; status = SANE_STATUS_GOOD; if ( ms->src_remaining_lines == 0 ) /* we have read all the image data, */ { /* calculate threshold value */ for ( pixel = 0; pixel < ms->remaining_bytes; pixel++ ) threshold += *(ms->temporary_buffer + pixel); threshold /= ms->remaining_bytes; lines = ms->remaining_bytes / ms->bpl; for ( line = 0; line < lines; line++ ) { from = ms->temporary_buffer + line * ms->bpl; if ( right_to_left == 1 ) from += ms->ppl - 1; status = lineartfake_copy_pixels(ms, from, ms->ppl, (uint8_t) threshold, right_to_left, ms->fp); } *temp_current = NULL; } return status; } /*-------------- get_cshading_values -----------------------------------------*/ static SANE_Status get_cshading_values(Microtek2_Scanner *ms, uint8_t color, uint32_t pixel, float shading_factor, int right_to_left, float *s_d, float *s_w) { Microtek2_Device *md; uint32_t csh_offset; md = ms->dev; if ( right_to_left == 1 ) csh_offset = (color + 1) * ms->ppl - 1 - pixel; else csh_offset = color * ms->ppl + pixel; if ( ( md->shading_depth > 8 ) && ( ms->lut_entry_size == 2) ) /* condensed shading is 2 byte color data */ { if ( ms->condensed_shading_d != NULL ) *s_d = (float) *( (uint16_t *)ms->condensed_shading_d + csh_offset ); else *s_d = 0.0; *s_w = (float) *( (uint16_t *)ms->condensed_shading_w + csh_offset ); *s_w /= shading_factor; *s_d /= shading_factor; } else /* condensed shading is 8 bit data */ { *s_w = (float) *( ms->condensed_shading_w + csh_offset ); if ( ms->condensed_shading_d != NULL ) *s_d = (float) *( ms->condensed_shading_d + csh_offset ); else *s_d = 0.0; } return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/saned.conf.in0000664000175000017500000000203412617742237015171 00000000000000# saned.conf # Configuration for the saned daemon ## Daemon options # Port range for the data connection. Choose a range inside [1024 - 65535]. # Avoid specifying too large a range, for performance reasons. # # ONLY use this if your saned server is sitting behind a firewall. If your # firewall is a Linux machine, we strongly recommend using the # Netfilter nf_conntrack_sane connection tracking module instead. # # data_portrange = 10000 - 10100 ## Access list # A list of host names, IP addresses or IP subnets (CIDR notation) that # are permitted to use local SANE devices. IPv6 addresses must be enclosed # in brackets, and should always be specified in their compressed form. # # The hostname matching is not case-sensitive. #scan-client.somedomain.firm #192.168.0.1 #192.168.0.1/29 #[2001:db8:185e::42:12] #[2001:db8:185e::42:12]/64 # NOTE: /etc/inetd.conf (or /etc/xinetd.conf) and # /etc/services must also be properly configured to start # the saned daemon as documented in saned(8), services(4) # and inetd.conf(4) (or xinetd.conf(5)). sane-backends-1.0.27/backend/pieusb_specific.c0000664000175000017500000032520613106201017016110 00000000000000/* sane - Scanner Access Now Easy. pieusb_specific.c Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ========================================================================= * * Various Pieusb backend specific functions * * Option handling, configuration file handling, post-processing * * ========================================================================= */ #define DEBUG_DECLARE_ONLY #include "pieusb.h" #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include #include #include #include "pieusb_usb.h" #include "pieusb_scancmd.h" #include "pieusb_buffer.h" #include "pieusb_specific.h" /* Pieusb specific */ /* sub to sanei_pieusb_find_device_callback() */ static SANE_Status pieusb_initialize_device_definition (Pieusb_Device_Definition* dev, Pieusb_Scanner_Properties* inq, const char* devicename, SANE_Word vendor_id, SANE_Word product_id); static void pieusb_print_inquiry (Pieusb_Device_Definition * dev); /* sub to sane_start() */ static void pieusb_calculate_shading(struct Pieusb_Scanner *scanner, SANE_Byte* buffer); /* MR */ /* sub to sanei_pieusb_post() */ static SANE_Status pieusb_write_pnm_file (char *filename, uint16_t *data, int depth, int channels, int pixels_per_line, int lines); /* Auxilary */ static size_t max_string_size (SANE_String_Const const strings[]); static double getGain(int gain); static int getGainSetting(double gain); /* static void updateGain(Pieusb_Scanner *scanner, int color_index); */ static void updateGain2(Pieusb_Scanner *scanner, int color_index, double gain_increase); /* -------------------------------------------------------------------------- * * SPECIFIC PIEUSB * * --------------------------------------------------------------------------*/ /* Settings for byte order */ #define SCAN_IMG_FMT_OKLINE 0x08 #define SCAN_IMG_FMT_BLK_ONE 0x04 #define SCAN_IMG_FMT_MOTOROLA 0x02 #define SCAN_IMG_FMT_INTEL 0x01 /* Settings for scanner capabilities */ #define SCAN_CAP_PWRSAV 0x80 #define SCAN_CAP_EXT_CAL 0x40 #define SCAN_CAP_FAST_PREVIEW 0x10 #define SCAN_CAP_DISABLE_CAL 0x08 #define SCAN_CAP_SPEEDS 0x07 /* Available scanner options */ #define SCAN_OPT_DEV_MPCL 0x80 #define SCAN_OPT_DEV_TP1 0x04 #define SCAN_OPT_DEV_TP 0x02 #define SCAN_OPT_DEV_ADF 0x01 /* Options */ #define SANE_NAME_EXPOSURE_R "exposure-time-r" #define SANE_TITLE_EXPOSURE_R "Exposure time red" #define SANE_DESC_EXPOSURE_R "The time the red color filter of the CCD is exposed" #define SANE_NAME_EXPOSURE_G "exposure-time-g" #define SANE_TITLE_EXPOSURE_G "Exposure time green" #define SANE_DESC_EXPOSURE_G "The time the green color filter of the CCD is exposed" #define SANE_NAME_EXPOSURE_B "exposure-time-b" #define SANE_TITLE_EXPOSURE_B "Exposure time blue" #define SANE_DESC_EXPOSURE_B "The time the blue color filter of the CCD is exposed" #define SANE_NAME_EXPOSURE_I "exposure-time-i" #define SANE_TITLE_EXPOSURE_I "Exposure time infrared" #define SANE_DESC_EXPOSURE_I "The time the infrared color filter of the CCD is exposed" #define SANE_EXPOSURE_DEFAULT DEFAULT_EXPOSURE #if 1 #define SANE_NAME_GAIN_R "gain-r" #define SANE_TITLE_GAIN_R "Gain red" #define SANE_DESC_GAIN_R "The gain of the signal processor for red" #define SANE_NAME_GAIN_G "gain-g" #define SANE_TITLE_GAIN_G "Gain green" #define SANE_DESC_GAIN_G "The gain of the signal processor for green" #define SANE_NAME_GAIN_B "gain-b" #define SANE_TITLE_GAIN_B "Gain blue" #define SANE_DESC_GAIN_B "The gain of the signal processor for blue" #define SANE_NAME_GAIN_I "gain-i" #define SANE_TITLE_GAIN_I "Gain infrared" #define SANE_DESC_GAIN_I "The gain of the signal processor for infrared" #define SANE_GAIN_DEFAULT DEFAULT_GAIN #define SANE_NAME_OFFSET_R "offset-r" #define SANE_TITLE_OFFSET_R "Offset red" #define SANE_DESC_OFFSET_R "The offset of the signal processor for red" #define SANE_NAME_OFFSET_G "offset-g" #define SANE_TITLE_OFFSET_G "Offset greed" #define SANE_DESC_OFFSET_G "The offset of the signal processor for green" #define SANE_NAME_OFFSET_B "offset-b" #define SANE_TITLE_OFFSET_B "Offset blue" #define SANE_DESC_OFFSET_B "The offset of the signal processor for blue" #define SANE_NAME_OFFSET_I "offset-i" #define SANE_TITLE_OFFSET_I "Offset infrared" #define SANE_DESC_OFFSET_I "The offset of the signal processor for infrared" #define SANE_OFFSET_DEFAULT DEFAULT_OFFSET #else #define SANE_NAME_GAIN "gain" #define SANE_TITLE_GAIN "Gain" #define SANE_DESC_GAIN "The gain of the signal processor for the 4 CCD color filters (R,G,B,I)" #define SANE_GAIN_DEFAULT 0x13 #define SANE_NAME_OFFSET "offset" #define SANE_TITLE_OFFSET "Offset" #define SANE_DESC_OFFSET "The offset of the signal processor for the 4 CCD color filters (R,G,B,I)" #define SANE_OFFSET_DEFAULT 0 #endif #define min(a,b) (((a)<(b))?(a):(b)) #define max(a,b) (((a)>(b))?(a):(b)) static const SANE_Range percentage_range_100 = { 0 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 0 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; /* From the firmware disassembly */ static const SANE_Range gain_range = { 0, /* minimum */ 63, /* maximum */ 0 /* quantization */ }; /* From the firmware disassembly */ static const SANE_Range offset_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const double gains[] = { 1.000, 1.075, 1.154, 1.251, 1.362, 1.491, 1.653, /* 0, 5, 10, 15, 20, 25, 30 */ 1.858, 2.115, 2.458, 2.935, 3.638, 4.627 /* 35, 40, 45, 50, 55, 60 */ }; /** * Callback called whenever a connected USB device reports a supported vendor * and product id combination. * Used by sane_init() and by sane_open(). * * @param name Device name which has required vendor and product id * @return SANE_STATUS_GOOD */ SANE_Status sanei_pieusb_find_device_callback (const char *devicename) { struct Pieusb_Command_Status status; SANE_Status r; Pieusb_Device_Definition *dev; int device_number; /* index in usb devices list maintained by sani_usb */ Pieusb_Scanner_Properties inq; int retry; DBG (DBG_info_proc, "sanei_pieusb_find_device_callback: %s\n", devicename); /* Check if device is present in the Pieusb device list */ for (dev = pieusb_definition_list_head; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { return SANE_STATUS_GOOD; } } /* If not, create a new device struct */ dev = malloc (sizeof (*dev)); if (!dev) { return SANE_STATUS_NO_MEM; } /* Get device number: index of the device in the sanei_usb devices list */ r = sanei_usb_open (devicename, &device_number); if (r != SANE_STATUS_GOOD) { free (dev); DBG (DBG_error, "sanei_pieusb_find_device_callback: sanei_usb_open failed for device %s: %s\n",devicename,sane_strstatus(r)); return r; } /* Get device properties */ retry = 2; while (retry > 0) { retry--; /* get inquiry data length */ sanei_pieusb_cmd_inquiry (device_number, &inq, 5, &status); if (status.pieusb_status == PIEUSB_STATUS_GOOD) { break; } else if (status.pieusb_status == PIEUSB_STATUS_IO_ERROR) { if (retry > 0) { DBG (DBG_info_proc, "inquiry failed, resetting usb\n"); if (sanei_pieusb_usb_reset(device_number) == SANE_STATUS_GOOD) { continue; /* retry after IEEE1284 reset */ } if (sanei_usb_reset(device_number) == SANE_STATUS_GOOD) { continue; /* retry after USB reset */ } } } free (dev); DBG (DBG_error, "sanei_pieusb_find_device_callback: get scanner properties (5 bytes) failed with %d\n", status.pieusb_status); sanei_usb_close (device_number); return status.pieusb_status; } /* get full inquiry data */ sanei_pieusb_cmd_inquiry(device_number, &inq, inq.additionalLength+4, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { free (dev); DBG (DBG_error, "sanei_pieusb_find_device_callback: get scanner properties failed\n"); sanei_usb_close (device_number); return status.pieusb_status; } /* Close the device again */ sanei_usb_close(device_number); /* Initialize device definition */ r = pieusb_initialize_device_definition(dev, &inq, devicename, pieusb_supported_usb_device.vendor, pieusb_supported_usb_device.product); if (r != SANE_STATUS_GOOD) { return r; } /* Output */ pieusb_print_inquiry (dev); /* Check model number */ if (inq.model != pieusb_supported_usb_device.model) { free (dev); DBG (DBG_error, "sanei_pieusb_find_device_callback: wrong model number %d\n", inq.model); return SANE_STATUS_INVAL; } dev->flags = pieusb_supported_usb_device.flags; /* Found a supported scanner, put it in the definitions list*/ DBG (DBG_info_proc, "sanei_pieusb_find_device_callback: success\n"); dev->next = pieusb_definition_list_head; pieusb_definition_list_head = dev; return SANE_STATUS_GOOD; } /** * Full initialization of a Pieusb_Device structure from INQUIRY data. * The function is used in find_device_callback(), so when sane_init() or * sane_open() is called. * * @param dev */ static SANE_Status pieusb_initialize_device_definition (Pieusb_Device_Definition* dev, Pieusb_Scanner_Properties* inq, const char* devicename, SANE_Word vendor_id, SANE_Word product_id) { char *pp, *buf; /* Initialize device definition */ dev->next = NULL; dev->sane.name = strdup(devicename); /* Create 0-terminated string without trailing spaces for vendor */ buf = malloc(9); if (buf == NULL) return SANE_STATUS_NO_MEM; strncpy(buf, inq->vendor, 8); pp = buf + 8; *pp-- = '\0'; while (*pp == ' ') *pp-- = '\0'; dev->sane.vendor = buf; /* Create 0-terminated string without trailing spaces for model */ buf = malloc(17); if (buf == NULL) return SANE_STATUS_NO_MEM; strncpy(buf, inq->product, 16); pp = buf + 16; *pp-- = '\0'; while (*pp == ' ') *pp-- = '\0'; dev->sane.model = buf; dev->sane.type = "film scanner"; dev->vendorId = vendor_id; dev->productId = product_id; /* Create 0-terminated strings without trailing spaces for revision */ buf = malloc(5); if (buf == NULL) return SANE_STATUS_NO_MEM; strncpy(buf, inq->productRevision, 4); pp = buf + 4; *pp-- = '\0'; while (*pp == ' ') *pp-- = '\0'; dev->version = buf; dev->model = inq->model; /* Maximum resolution values */ dev->maximum_resolution_x = inq->maxResolutionX; dev->maximum_resolution_y = inq->maxResolutionY; if (dev->maximum_resolution_y < 256) { /* y res is a multiplier */ dev->maximum_resolution = dev->maximum_resolution_x; dev->maximum_resolution_x *= dev->maximum_resolution_y; dev->maximum_resolution_y = dev->maximum_resolution_x; } else { /* y res really is resolution */ dev->maximum_resolution = min (dev->maximum_resolution_x, dev->maximum_resolution_y); } /* Geometry */ dev->scan_bed_width = (double) inq->maxScanWidth / dev->maximum_resolution; dev->scan_bed_height = (double) inq->maxScanHeight / dev->maximum_resolution; dev->slide_top_left_x = inq->x0; dev->slide_top_left_y = inq->y0; dev->slide_width = (double) (inq->x1 - inq->x0) / dev->maximum_resolution; dev->slide_height = (double) (inq->y1 - inq->y0) / dev->maximum_resolution; /* Integer and bit-encoded properties */ dev->halftone_patterns = inq->halftones & 0x0f; dev->color_filters = inq->filters; dev->color_depths = inq->colorDepths; dev->color_formats = inq->colorFormat; dev->image_formats = inq->imageFormat; dev->scan_capabilities = inq->scanCapability; dev->optional_devices = inq->optionalDevices; dev->enhancements = inq->enhancements; dev->gamma_bits = inq->gammaBits; dev->fast_preview_resolution = inq->previewScanResolution; dev->minimum_highlight = inq->minumumHighlight; dev->maximum_shadow = inq->maximumShadow; dev->calibration_equation = inq->calibrationEquation; dev->minimum_exposure = inq->minimumExposure; dev->maximum_exposure = inq->maximumExposure*4; /* *4 to solve the strange situation that the default value is out of range */ dev->x0 = inq->x0; dev->y0 = inq->y0; dev->x1 = inq->x1; dev->y1 = inq->y1; dev->production = strndup(inq->production, 4); dev->timestamp = strndup(inq->timestamp, 20); dev->signature = (char *)strndup((char *)inq->signature, 40); /* Ranges for various quantities */ dev->x_range.min = SANE_FIX (0); dev->x_range.quant = SANE_FIX (0); dev->x_range.max = SANE_FIX (dev->scan_bed_width * MM_PER_INCH); dev->y_range.min = SANE_FIX (0); dev->y_range.quant = SANE_FIX (0); dev->y_range.max = SANE_FIX (dev->scan_bed_height * MM_PER_INCH); dev->dpi_range.min = SANE_FIX (25); dev->dpi_range.quant = SANE_FIX (1); dev->dpi_range.max = SANE_FIX (max (dev->maximum_resolution_x, dev->maximum_resolution_y)); dev->shadow_range.min = SANE_FIX (0); dev->shadow_range.quant = SANE_FIX (1); dev->shadow_range.max = SANE_FIX (dev->maximum_shadow); dev->highlight_range.min = SANE_FIX (dev->minimum_highlight); dev->highlight_range.quant = SANE_FIX (1); dev->highlight_range.max = SANE_FIX (100); dev->exposure_range.min = dev->minimum_exposure; dev->exposure_range.quant = 1; dev->exposure_range.max = dev->maximum_exposure; dev->dust_range.min = 0; dev->dust_range.quant = 1; dev->dust_range.max = 100; /* Enumerated ranges vor various quantities */ /*TODO: create from inq->filters */ dev->scan_mode_list[0] = SANE_VALUE_SCAN_MODE_LINEART; dev->scan_mode_list[1] = SANE_VALUE_SCAN_MODE_HALFTONE; dev->scan_mode_list[2] = SANE_VALUE_SCAN_MODE_GRAY; dev->scan_mode_list[3] = SANE_VALUE_SCAN_MODE_COLOR; dev->scan_mode_list[4] = SANE_VALUE_SCAN_MODE_RGBI; dev->scan_mode_list[5] = 0; dev->calibration_mode_list[0] = SCAN_CALIBRATION_DEFAULT; dev->calibration_mode_list[1] = SCAN_CALIBRATION_AUTO; dev->calibration_mode_list[2] = SCAN_CALIBRATION_PREVIEW; dev->calibration_mode_list[3] = SCAN_CALIBRATION_OPTIONS; dev->calibration_mode_list[4] = 0; dev->gain_adjust_list[0] = SCAN_GAIN_ADJUST_03; dev->gain_adjust_list[1] = SCAN_GAIN_ADJUST_05; dev->gain_adjust_list[2] = SCAN_GAIN_ADJUST_08; dev->gain_adjust_list[3] = SCAN_GAIN_ADJUST_10; dev->gain_adjust_list[4] = SCAN_GAIN_ADJUST_12; dev->gain_adjust_list[5] = SCAN_GAIN_ADJUST_16; dev->gain_adjust_list[6] = SCAN_GAIN_ADJUST_19; dev->gain_adjust_list[7] = SCAN_GAIN_ADJUST_24; dev->gain_adjust_list[8] = SCAN_GAIN_ADJUST_30; dev->gain_adjust_list[9] = 0; /*TODO: create from inq->colorDepths? Maybe not: didn't experiment with * 4 and 12 bit depths. Don;t know how they behave. */ dev->bpp_list[0] = 3; /* count */ dev->bpp_list[1] = 1; dev->bpp_list[2] = 8; dev->bpp_list[3] = 16; /* Infrared */ dev->ir_sw_list[0] = "None"; dev->ir_sw_list[1] = "Reduce red overlap"; dev->ir_sw_list[2] = "Remove dirt"; dev->ir_sw_list[3] = 0; dev->grain_sw_list[0] = 4; dev->grain_sw_list[1] = 0; dev->grain_sw_list[2] = 1; dev->grain_sw_list[3] = 2; dev->grain_sw_list[4] = 3; dev->grain_sw_list[5] = 0; dev->crop_sw_list[0] = "None"; dev->crop_sw_list[1] = "Outside"; dev->crop_sw_list[2] = "Inside"; dev->crop_sw_list[3] = 0; /* halftone_list */ dev->halftone_list[0] = "53lpi 45d ROUND"; /* 8x8 pattern */ dev->halftone_list[1] = "70lpi 45d ROUND"; /* 6x6 pattern */ dev->halftone_list[2] = "75lpi Hori. Line"; /* 4x4 pattern */ dev->halftone_list[3] = "4X4 BAYER"; /* 4x4 pattern */ dev->halftone_list[4] = "4X4 SCROLL"; /* 4x4 pattern */ dev->halftone_list[5] = "5x5 26 Levels"; /* 5x5 pattern */ dev->halftone_list[6] = "4x4 SQUARE"; /* 4x4 pattern */ dev->halftone_list[7] = "5x5 TILE"; /* 5x5 pattern */ dev->halftone_list[8] = 0; return SANE_STATUS_GOOD; } /** * Output device definition. * The function is used in find_device_callback(), so when sane_init() or * sane_open() is called. * * @param dev Device to output */ static void pieusb_print_inquiry (Pieusb_Device_Definition * dev) { DBG (DBG_inquiry, "INQUIRY:\n"); DBG (DBG_inquiry, "========\n"); DBG (DBG_inquiry, "\n"); DBG (DBG_inquiry, "vendor........................: '%s'\n", dev->sane.vendor); DBG (DBG_inquiry, "product.......................: '%s'\n", dev->sane.model); DBG (DBG_inquiry, "model .......................: 0x%04x\n", dev->model); DBG (DBG_inquiry, "version.......................: '%s'\n", dev->version); DBG (DBG_inquiry, "X resolution..................: %d dpi\n", dev->maximum_resolution_x); DBG (DBG_inquiry, "Y resolution..................: %d dpi\n", dev->maximum_resolution_y); DBG (DBG_inquiry, "pixel resolution..............: %d dpi\n", dev->maximum_resolution); DBG (DBG_inquiry, "fb width......................: %f in\n", dev->scan_bed_width); DBG (DBG_inquiry, "fb length.....................: %f in\n", dev->scan_bed_height); DBG (DBG_inquiry, "transparency width............: %f in\n", dev->slide_width); DBG (DBG_inquiry, "transparency length...........: %f in\n", dev->slide_height); DBG (DBG_inquiry, "transparency offset...........: %d,%d\n", dev->slide_top_left_x, dev->slide_top_left_y); DBG (DBG_inquiry, "# of halftones................: %d\n", dev->halftone_patterns); DBG (DBG_inquiry, "One pass color................: %s\n", dev->color_filters & SCAN_ONE_PASS_COLOR ? "yes" : "no"); DBG (DBG_inquiry, "Filters.......................: %s%s%s%s%s (%02x)\n", dev->color_filters & SCAN_FILTER_INFRARED ? "Infrared " : "", dev->color_filters & SCAN_FILTER_RED ? "Red " : "", dev->color_filters & SCAN_FILTER_GREEN ? "Green " : "", dev->color_filters & SCAN_FILTER_BLUE ? "Blue " : "", dev->color_filters & SCAN_FILTER_NEUTRAL ? "Neutral " : "", dev->color_filters); DBG (DBG_inquiry, "Color depths..................: %s%s%s%s%s%s (%02x)\n", dev->color_depths & SCAN_COLOR_DEPTH_16 ? "16 bit " : "", dev->color_depths & SCAN_COLOR_DEPTH_12 ? "12 bit " : "", dev->color_depths & SCAN_COLOR_DEPTH_10 ? "10 bit " : "", dev->color_depths & SCAN_COLOR_DEPTH_8 ? "8 bit " : "", dev->color_depths & SCAN_COLOR_DEPTH_4 ? "4 bit " : "", dev->color_depths & SCAN_COLOR_DEPTH_1 ? "1 bit " : "", dev->color_depths); DBG (DBG_inquiry, "Color Format..................: %s%s%s (%02x)\n", dev->color_formats & SCAN_COLOR_FORMAT_INDEX ? "Indexed " : "", dev->color_formats & SCAN_COLOR_FORMAT_LINE ? "Line " : "", dev->color_formats & SCAN_COLOR_FORMAT_PIXEL ? "Pixel " : "", dev->color_formats); DBG (DBG_inquiry, "Image Format..................: %s%s%s%s (%02x)\n", dev->image_formats & SCAN_IMG_FMT_OKLINE ? "OKLine " : "", dev->image_formats & SCAN_IMG_FMT_BLK_ONE ? "BlackOne " : "", dev->image_formats & SCAN_IMG_FMT_MOTOROLA ? "Motorola " : "", dev->image_formats & SCAN_IMG_FMT_INTEL ? "Intel" : "", dev->image_formats); DBG (DBG_inquiry, "Scan Capability...............: %s%s%s%s%d speeds (%02x)\n", dev->scan_capabilities & SCAN_CAP_PWRSAV ? "PowerSave " : "", dev->scan_capabilities & SCAN_CAP_EXT_CAL ? "ExtCal " : "", dev->scan_capabilities & SCAN_CAP_FAST_PREVIEW ? "FastPreview" : "", dev->scan_capabilities & SCAN_CAP_DISABLE_CAL ? "DisCal " : "", dev->scan_capabilities & SCAN_CAP_SPEEDS, dev->scan_capabilities); DBG (DBG_inquiry, "Optional Devices..............: %s%s%s%s (%02x)\n", dev->optional_devices & SCAN_OPT_DEV_MPCL ? "MultiPageLoad " : "", dev->optional_devices & SCAN_OPT_DEV_TP1 ? "TransModule1 " : "", dev->optional_devices & SCAN_OPT_DEV_TP ? "TransModule " : "", dev->optional_devices & SCAN_OPT_DEV_ADF ? "ADF " : "", dev->optional_devices); DBG (DBG_inquiry, "Enhancement...................: %02x\n", dev->enhancements); DBG (DBG_inquiry, "Gamma bits....................: %d\n", dev->gamma_bits); DBG (DBG_inquiry, "Fast Preview Resolution.......: %d\n", dev->fast_preview_resolution); DBG (DBG_inquiry, "Min Highlight.................: %d\n", dev->minimum_highlight); DBG (DBG_inquiry, "Max Shadow....................: %d\n", dev->maximum_shadow); DBG (DBG_inquiry, "Cal Eqn.......................: %d\n", dev->calibration_equation); DBG (DBG_inquiry, "Min Exposure..................: %d\n", dev->minimum_exposure); DBG (DBG_inquiry, "Max Exposure..................: %d\n", dev->maximum_exposure); DBG (DBG_inquiry, "x0,y0 x1,y1...................: %d,%d %d,%d\n", dev->x0, dev->y0, dev->x1, dev->y1); DBG (DBG_inquiry, "production....................: '%s'\n", dev->production); DBG (DBG_inquiry, "timestamp.....................: '%s'\n", dev->timestamp); DBG (DBG_inquiry, "signature.....................: '%s'\n", dev->signature); } /** * Initiaize scanner options from the device definition and from exposure, * gain and offset defaults. The function is called by sane_open(), when no * optimized settings are available yet. The scanner object is fully * initialized in sane_start(). * * @param scanner Scanner to initialize * @return SANE_STATUS_GOOD */ SANE_Status sanei_pieusb_init_options (Pieusb_Scanner* scanner) { int i; DBG (DBG_info_proc, "sanei_pieusb_init_options\n"); memset (scanner->opt, 0, sizeof (scanner->opt)); memset (scanner->val, 0, sizeof (scanner->val)); for (i = 0; i < NUM_OPTIONS; ++i) { scanner->opt[i].size = sizeof (SANE_Word); scanner->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options (a pseudo-option) */ scanner->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; scanner->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ scanner->opt[OPT_MODE_GROUP].title = "Scan Mode"; scanner->opt[OPT_MODE_GROUP].desc = ""; scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_MODE_GROUP].cap = 0; scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; scanner->opt[OPT_MODE].type = SANE_TYPE_STRING; scanner->opt[OPT_MODE].size = max_string_size ((SANE_String_Const const *) scanner->device->scan_mode_list); scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_MODE].constraint.string_list = (SANE_String_Const const *) scanner->device->scan_mode_list; scanner->val[OPT_MODE].s = (SANE_Char *) strdup (scanner->device->scan_mode_list[3]); /* default RGB */ /* bit depth */ scanner->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; scanner->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; scanner->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_BIT_DEPTH].size = sizeof (SANE_Word); scanner->opt[OPT_BIT_DEPTH].constraint.word_list = scanner->device->bpp_list; scanner->val[OPT_BIT_DEPTH].w = scanner->device->bpp_list[2]; /* resolution */ scanner->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; scanner->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; scanner->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_RESOLUTION].constraint.range = &scanner->device->dpi_range; scanner->val[OPT_RESOLUTION].w = scanner->device->fast_preview_resolution << SANE_FIXED_SCALE_SHIFT; /* halftone pattern */ scanner->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; scanner->opt[OPT_HALFTONE_PATTERN].size = max_string_size ((SANE_String_Const const *) scanner->device->halftone_list); scanner->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_HALFTONE_PATTERN].constraint.string_list = (SANE_String_Const const *) scanner->device->halftone_list; scanner->val[OPT_HALFTONE_PATTERN].s = (SANE_Char *) strdup (scanner->device->halftone_list[6]); scanner->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; /* Not implemented, and only meaningful at depth 1 */ /* lineart threshold */ scanner->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; scanner->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; scanner->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; scanner->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; scanner->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_THRESHOLD].constraint.range = &percentage_range_100; scanner->val[OPT_THRESHOLD].w = SANE_FIX (50); /* scanner->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; Not implemented, and only meaningful at depth 1 */ /* create a sharper scan at the cost of scan time */ scanner->opt[OPT_SHARPEN].name = "sharpen"; scanner->opt[OPT_SHARPEN].title = "Sharpen scan"; scanner->opt[OPT_SHARPEN].desc = "Sharpen scan by taking more time to discharge the CCD."; scanner->opt[OPT_SHARPEN].type = SANE_TYPE_BOOL; scanner->opt[OPT_SHARPEN].unit = SANE_UNIT_NONE; scanner->opt[OPT_SHARPEN].constraint_type = SANE_CONSTRAINT_NONE; scanner->val[OPT_SHARPEN].b = SANE_FALSE; scanner->opt[OPT_SHARPEN].cap |= SANE_CAP_SOFT_SELECT; /* skip the auto-calibration phase before the scan */ scanner->opt[OPT_SHADING_ANALYSIS].name = "shading-analysis"; scanner->opt[OPT_SHADING_ANALYSIS].title = "Perform shading analysis"; scanner->opt[OPT_SHADING_ANALYSIS].desc = "Collect shading reference data before scanning the image. If set to 'no', this option may be overridden by the scanner."; scanner->opt[OPT_SHADING_ANALYSIS].type = SANE_TYPE_BOOL; scanner->opt[OPT_SHADING_ANALYSIS].unit = SANE_UNIT_NONE; scanner->opt[OPT_SHADING_ANALYSIS].constraint_type = SANE_CONSTRAINT_NONE; scanner->val[OPT_SHADING_ANALYSIS].b = SANE_FALSE; scanner->opt[OPT_SHADING_ANALYSIS].cap |= SANE_CAP_SOFT_SELECT; /* use auto-calibration settings for scan */ scanner->opt[OPT_CALIBRATION_MODE].name = "calibration"; scanner->opt[OPT_CALIBRATION_MODE].title = "Calibration mode"; scanner->opt[OPT_CALIBRATION_MODE].desc = "How to calibrate the scanner."; scanner->opt[OPT_CALIBRATION_MODE].type = SANE_TYPE_STRING; scanner->opt[OPT_CALIBRATION_MODE].size = max_string_size ((SANE_String_Const const *) scanner->device->calibration_mode_list); scanner->opt[OPT_CALIBRATION_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_CALIBRATION_MODE].constraint.string_list = (SANE_String_Const const *) scanner->device->calibration_mode_list; scanner->val[OPT_CALIBRATION_MODE].s = (SANE_Char *) strdup (scanner->device->calibration_mode_list[1]); /* default auto */ /* OPT_GAIN_ADJUST */ scanner->opt[OPT_GAIN_ADJUST].name = "gain-adjust"; scanner->opt[OPT_GAIN_ADJUST].title = "Adjust gain"; scanner->opt[OPT_GAIN_ADJUST].desc = "Adjust gain determined by calibration procedure."; scanner->opt[OPT_GAIN_ADJUST].type = SANE_TYPE_STRING; scanner->opt[OPT_GAIN_ADJUST].size = max_string_size ((SANE_String_Const const *) scanner->device->gain_adjust_list); scanner->opt[OPT_GAIN_ADJUST].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_GAIN_ADJUST].constraint.string_list = (SANE_String_Const const *) scanner->device->gain_adjust_list; scanner->val[OPT_GAIN_ADJUST].s = (SANE_Char *) strdup (scanner->device->gain_adjust_list[2]); /* x 1.0 (no change) */ /* scan infrared channel faster but less accurate */ scanner->opt[OPT_FAST_INFRARED].name = "fast-infrared"; scanner->opt[OPT_FAST_INFRARED].title = "Fast infrared scan"; scanner->opt[OPT_FAST_INFRARED].desc = "Do not reposition scan head before scanning infrared line. Results in an infrared offset which may deteriorate IR dust and scratch removal."; scanner->opt[OPT_FAST_INFRARED].type = SANE_TYPE_BOOL; scanner->opt[OPT_FAST_INFRARED].unit = SANE_UNIT_NONE; scanner->opt[OPT_FAST_INFRARED].constraint_type = SANE_CONSTRAINT_NONE; scanner->val[OPT_FAST_INFRARED].b = SANE_FALSE; scanner->opt[OPT_FAST_INFRARED].cap |= SANE_CAP_SOFT_SELECT; /* automatically advance to next slide after scan */ scanner->opt[OPT_ADVANCE_SLIDE].name = "advcane"; scanner->opt[OPT_ADVANCE_SLIDE].title = "Advance slide"; scanner->opt[OPT_ADVANCE_SLIDE].desc = "Automatically advance to next slide after scan"; scanner->opt[OPT_ADVANCE_SLIDE].type = SANE_TYPE_BOOL; scanner->opt[OPT_ADVANCE_SLIDE].unit = SANE_UNIT_NONE; scanner->opt[OPT_ADVANCE_SLIDE].constraint_type = SANE_CONSTRAINT_NONE; scanner->val[OPT_ADVANCE_SLIDE].w = SANE_TRUE; scanner->opt[OPT_ADVANCE_SLIDE].cap |= SANE_CAP_SOFT_SELECT; /* "Geometry" group: */ scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; scanner->opt[OPT_GEOMETRY_GROUP].desc = ""; scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_X].constraint.range = &(scanner->device->x_range); scanner->val[OPT_TL_X].w = 0; /* top-left y */ scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_Y].constraint.range = &(scanner->device->y_range); scanner->val[OPT_TL_Y].w = 0; /* bottom-right x */ scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_X].constraint.range = &(scanner->device->x_range); scanner->val[OPT_BR_X].w = scanner->device->x_range.max; /* bottom-right y */ scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_Y].constraint.range = &(scanner->device->y_range); scanner->val[OPT_BR_Y].w = scanner->device->y_range.max; /* "Enhancement" group: */ scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; scanner->opt[OPT_ENHANCEMENT_GROUP].desc = ""; scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ENHANCEMENT_GROUP].cap = 0; scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* correct data for lamp variations (shading) */ scanner->opt[OPT_CORRECT_SHADING].name = "correct-shading"; scanner->opt[OPT_CORRECT_SHADING].title = "Correct shading"; scanner->opt[OPT_CORRECT_SHADING].desc = "Correct data for lamp variations (shading)"; scanner->opt[OPT_CORRECT_SHADING].type = SANE_TYPE_BOOL; scanner->opt[OPT_CORRECT_SHADING].unit = SANE_UNIT_NONE; scanner->val[OPT_CORRECT_SHADING].w = SANE_TRUE; /* correct infrared for red crosstalk */ scanner->opt[OPT_CORRECT_INFRARED].name = "correct-infrared"; scanner->opt[OPT_CORRECT_INFRARED].title = "Correct infrared"; scanner->opt[OPT_CORRECT_INFRARED].desc = "Correct infrared for red crosstalk"; scanner->opt[OPT_CORRECT_INFRARED].type = SANE_TYPE_BOOL; scanner->opt[OPT_CORRECT_INFRARED].unit = SANE_UNIT_NONE; scanner->val[OPT_CORRECT_INFRARED].w = SANE_FALSE; /* detect and remove dust and scratch artifacts */ scanner->opt[OPT_CLEAN_IMAGE].name = "clean-image"; scanner->opt[OPT_CLEAN_IMAGE].title = "Clean image"; scanner->opt[OPT_CLEAN_IMAGE].desc = "Detect and remove dust and scratch artifacts"; scanner->opt[OPT_CLEAN_IMAGE].type = SANE_TYPE_BOOL; scanner->opt[OPT_CLEAN_IMAGE].unit = SANE_UNIT_NONE; scanner->val[OPT_CLEAN_IMAGE].w = SANE_FALSE; /* strength of grain filtering */ scanner->opt[OPT_SMOOTH_IMAGE].name = "smooth"; scanner->opt[OPT_SMOOTH_IMAGE].title = "Attenuate film grain"; scanner->opt[OPT_SMOOTH_IMAGE].desc = "Amount of smoothening"; scanner->opt[OPT_SMOOTH_IMAGE].type = SANE_TYPE_INT; scanner->opt[OPT_SMOOTH_IMAGE].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_SMOOTH_IMAGE].size = sizeof (SANE_Word); scanner->opt[OPT_SMOOTH_IMAGE].constraint.word_list = scanner->device->grain_sw_list; scanner->val[OPT_SMOOTH_IMAGE].w = scanner->device->grain_sw_list[1]; if (scanner->opt[OPT_SMOOTH_IMAGE].constraint.word_list[0] < 2) { scanner->opt[OPT_SMOOTH_IMAGE].cap |= SANE_CAP_INACTIVE; } /* gamma correction, to make image sRGB like */ scanner->opt[OPT_TRANSFORM_TO_SRGB].name = "srgb"; scanner->opt[OPT_TRANSFORM_TO_SRGB].title = "sRGB colors"; scanner->opt[OPT_TRANSFORM_TO_SRGB].desc = "Transform image to approximate sRGB color space"; scanner->opt[OPT_TRANSFORM_TO_SRGB].type = SANE_TYPE_BOOL; scanner->opt[OPT_TRANSFORM_TO_SRGB].unit = SANE_UNIT_NONE; scanner->val[OPT_TRANSFORM_TO_SRGB].w = SANE_FALSE; scanner->opt[OPT_TRANSFORM_TO_SRGB].cap |= SANE_CAP_INACTIVE; /* color correction for generic negative film */ scanner->opt[OPT_INVERT_IMAGE].name = "invert"; scanner->opt[OPT_INVERT_IMAGE].title = "Invert colors"; scanner->opt[OPT_INVERT_IMAGE].desc = "Correct for generic negative film"; scanner->opt[OPT_INVERT_IMAGE].type = SANE_TYPE_BOOL; scanner->opt[OPT_INVERT_IMAGE].unit = SANE_UNIT_NONE; scanner->val[OPT_INVERT_IMAGE].w = SANE_FALSE; scanner->opt[OPT_INVERT_IMAGE].cap |= SANE_CAP_INACTIVE; /* crop image */ scanner->opt[OPT_CROP_IMAGE].name = "crop"; scanner->opt[OPT_CROP_IMAGE].title = "Cropping"; scanner->opt[OPT_CROP_IMAGE].desc = "How to crop the image"; scanner->opt[OPT_CROP_IMAGE].type = SANE_TYPE_STRING; scanner->opt[OPT_CROP_IMAGE].size = max_string_size ((SANE_String_Const const *)(void*) scanner->device->crop_sw_list); scanner->opt[OPT_CROP_IMAGE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_CROP_IMAGE].constraint.string_list = (SANE_String_Const const *)(void*) scanner->device->crop_sw_list; scanner->val[OPT_CROP_IMAGE].s = (SANE_Char *) strdup (scanner->device->crop_sw_list[2]); /* "Advanced" group: */ scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced"; scanner->opt[OPT_ADVANCED_GROUP].desc = ""; scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* preview */ scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; scanner->val[OPT_PREVIEW].w = SANE_FALSE; /* save shading data */ scanner->opt[OPT_SAVE_SHADINGDATA].name = "save-shading-data"; scanner->opt[OPT_SAVE_SHADINGDATA].title = "Save shading data"; scanner->opt[OPT_SAVE_SHADINGDATA].desc = "Save shading data in 'pieusb.shading'"; scanner->opt[OPT_SAVE_SHADINGDATA].type = SANE_TYPE_BOOL; scanner->val[OPT_SAVE_SHADINGDATA].w = SANE_FALSE; /* save CCD mask */ scanner->opt[OPT_SAVE_CCDMASK].name = "save-ccdmask"; scanner->opt[OPT_SAVE_CCDMASK].title = "Save CCD mask"; scanner->opt[OPT_SAVE_CCDMASK].desc = "Save CCD mask 'pieusb.ccd'"; scanner->opt[OPT_SAVE_CCDMASK].type = SANE_TYPE_BOOL; scanner->val[OPT_SAVE_CCDMASK].w = SANE_FALSE; scanner->opt[OPT_LIGHT].name = "light"; scanner->opt[OPT_LIGHT].title = "Light"; scanner->opt[OPT_LIGHT].desc = "Light"; scanner->opt[OPT_LIGHT].type = SANE_TYPE_INT; scanner->opt[OPT_LIGHT].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_LIGHT].cap |= SANE_CAP_SOFT_SELECT; scanner->opt[OPT_LIGHT].size = sizeof(SANE_Word); scanner->val[OPT_LIGHT].w = DEFAULT_LIGHT; scanner->opt[OPT_DOUBLE_TIMES].name = "double-times"; scanner->opt[OPT_DOUBLE_TIMES].title = "Double times"; scanner->opt[OPT_DOUBLE_TIMES].desc = "Double times"; scanner->opt[OPT_DOUBLE_TIMES].type = SANE_TYPE_INT; scanner->opt[OPT_DOUBLE_TIMES].unit = SANE_UNIT_MICROSECOND; scanner->opt[OPT_DOUBLE_TIMES].cap |= SANE_CAP_SOFT_SELECT; scanner->opt[OPT_DOUBLE_TIMES].size = sizeof(SANE_Word); scanner->val[OPT_DOUBLE_TIMES].w = DEFAULT_DOUBLE_TIMES; /* exposure times for R, G, B and I */ scanner->opt[OPT_SET_EXPOSURE_R].name = SANE_NAME_EXPOSURE_R; scanner->opt[OPT_SET_EXPOSURE_R].title = SANE_TITLE_EXPOSURE_R; scanner->opt[OPT_SET_EXPOSURE_R].desc = SANE_DESC_EXPOSURE_R; scanner->opt[OPT_SET_EXPOSURE_G].name = SANE_NAME_EXPOSURE_G; scanner->opt[OPT_SET_EXPOSURE_G].title = SANE_TITLE_EXPOSURE_G; scanner->opt[OPT_SET_EXPOSURE_G].desc = SANE_DESC_EXPOSURE_G; scanner->opt[OPT_SET_EXPOSURE_B].name = SANE_NAME_EXPOSURE_B; scanner->opt[OPT_SET_EXPOSURE_B].title = SANE_TITLE_EXPOSURE_B; scanner->opt[OPT_SET_EXPOSURE_B].desc = SANE_DESC_EXPOSURE_B; scanner->opt[OPT_SET_EXPOSURE_I].name = SANE_NAME_EXPOSURE_I; scanner->opt[OPT_SET_EXPOSURE_I].title = SANE_TITLE_EXPOSURE_I; scanner->opt[OPT_SET_EXPOSURE_I].desc = SANE_DESC_EXPOSURE_I; for (i = OPT_SET_EXPOSURE_R; i <= OPT_SET_EXPOSURE_I; ++i) { scanner->opt[i].type = SANE_TYPE_INT; scanner->opt[i].unit = SANE_UNIT_MICROSECOND; scanner->opt[i].cap |= SANE_CAP_SOFT_SELECT; scanner->opt[i].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[i].constraint.range = &(scanner->device->exposure_range); scanner->opt[i].size = sizeof(SANE_Word); scanner->val[i].w = SANE_EXPOSURE_DEFAULT; } /* gain for R, G, B and I */ scanner->opt[OPT_SET_GAIN_R].name = SANE_NAME_GAIN_R; scanner->opt[OPT_SET_GAIN_R].title = SANE_TITLE_GAIN_R; scanner->opt[OPT_SET_GAIN_R].desc = SANE_DESC_GAIN_R; scanner->opt[OPT_SET_GAIN_G].name = SANE_NAME_GAIN_G; scanner->opt[OPT_SET_GAIN_G].title = SANE_TITLE_GAIN_G; scanner->opt[OPT_SET_GAIN_G].desc = SANE_DESC_GAIN_G; scanner->opt[OPT_SET_GAIN_B].name = SANE_NAME_GAIN_B; scanner->opt[OPT_SET_GAIN_B].title = SANE_TITLE_GAIN_B; scanner->opt[OPT_SET_GAIN_B].desc = SANE_DESC_GAIN_B; scanner->opt[OPT_SET_GAIN_I].name = SANE_NAME_GAIN_I; scanner->opt[OPT_SET_GAIN_I].title = SANE_TITLE_GAIN_I; scanner->opt[OPT_SET_GAIN_I].desc = SANE_DESC_GAIN_I; for (i = OPT_SET_GAIN_R; i <= OPT_SET_GAIN_I; ++i) { scanner->opt[i].type = SANE_TYPE_INT; scanner->opt[i].unit = SANE_UNIT_NONE; scanner->opt[i].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[i].constraint.range = &gain_range; scanner->opt[i].size = sizeof(SANE_Word); scanner->val[i].w = SANE_GAIN_DEFAULT; } /* offsets for R, G, B and I */ scanner->opt[OPT_SET_OFFSET_R].name = SANE_NAME_OFFSET_R; scanner->opt[OPT_SET_OFFSET_R].title = SANE_TITLE_OFFSET_R; scanner->opt[OPT_SET_OFFSET_R].desc = SANE_DESC_OFFSET_R; scanner->opt[OPT_SET_OFFSET_G].name = SANE_NAME_OFFSET_G; scanner->opt[OPT_SET_OFFSET_G].title = SANE_TITLE_OFFSET_G; scanner->opt[OPT_SET_OFFSET_G].desc = SANE_DESC_OFFSET_G; scanner->opt[OPT_SET_OFFSET_B].name = SANE_NAME_OFFSET_B; scanner->opt[OPT_SET_OFFSET_B].title = SANE_TITLE_OFFSET_B; scanner->opt[OPT_SET_OFFSET_B].desc = SANE_DESC_OFFSET_B; scanner->opt[OPT_SET_OFFSET_I].name = SANE_NAME_OFFSET_I; scanner->opt[OPT_SET_OFFSET_I].title = SANE_TITLE_OFFSET_I; scanner->opt[OPT_SET_OFFSET_I].desc = SANE_DESC_OFFSET_I; for (i = OPT_SET_OFFSET_R; i <= OPT_SET_OFFSET_I; ++i) { scanner->opt[i].type = SANE_TYPE_INT; scanner->opt[i].unit = SANE_UNIT_NONE; scanner->opt[i].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[i].constraint.range = &offset_range; scanner->opt[i].size = sizeof(SANE_Word); scanner->val[i].w = SANE_OFFSET_DEFAULT; } return SANE_STATUS_GOOD; } /** * Parse line from config file into a vendor id, product id, model number, and flags * * @param config_line Text to parse * @param vendor_id * @param product_id * @param model_number * @param flags * @return SANE_STATUS_GOOD, or SANE_STATUS_INVAL in case of a parse error */ SANE_Status sanei_pieusb_parse_config_line(const char* config_line, SANE_Word* vendor_id, SANE_Word* product_id, SANE_Int* model_number, SANE_Int* flags) { char *vendor_id_string, *product_id_string, *model_number_string, *flags_string; if (strncmp (config_line, "usb ", 4) != 0) { return SANE_STATUS_INVAL; } /* Detect vendor-id */ config_line += 4; config_line = sanei_config_skip_whitespace (config_line); if (*config_line) { config_line = sanei_config_get_string (config_line, &vendor_id_string); if (vendor_id_string) { *vendor_id = strtol (vendor_id_string, 0, 0); free (vendor_id_string); } else { return SANE_STATUS_INVAL; } config_line = sanei_config_skip_whitespace (config_line); } else { return SANE_STATUS_INVAL; } /* Detect product-id */ config_line = sanei_config_skip_whitespace (config_line); if (*config_line) { config_line = sanei_config_get_string (config_line, &product_id_string); if (product_id_string) { *product_id = strtol (product_id_string, 0, 0); free (product_id_string); } else { return SANE_STATUS_INVAL; } config_line = sanei_config_skip_whitespace (config_line); } else { return SANE_STATUS_INVAL; } /* Detect model number */ config_line = sanei_config_skip_whitespace (config_line); if (*config_line) { config_line = sanei_config_get_string (config_line, &model_number_string); if (model_number_string) { *model_number = (SANE_Int) strtol (model_number_string, 0, 0); free (model_number_string); } else { return SANE_STATUS_INVAL; } config_line = sanei_config_skip_whitespace (config_line); } else { return SANE_STATUS_INVAL; } /* Detect (optional) flags */ *flags = 0; config_line = sanei_config_skip_whitespace (config_line); if (*config_line) { config_line = sanei_config_get_string (config_line, &flags_string); if (flags_string) { *flags = (SANE_Int) strtol (flags_string, 0, 0); free (flags_string); } } return SANE_STATUS_GOOD; } /** * Check if current list of supported devices contains the given specifications. * * @param vendor_id * @param product_id * @param model_number * @param flags * @return */ SANE_Bool sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags) { int i = 0; while (pieusb_supported_usb_device_list[i].vendor != 0) { if (pieusb_supported_usb_device_list[i].vendor == vendor_id && pieusb_supported_usb_device_list[i].product == product_id && pieusb_supported_usb_device_list[i].model == model_number && pieusb_supported_usb_device_list[i].flags == flags) { return SANE_TRUE; } i++; } return SANE_FALSE; } /** * Add the given specifications to the current list of supported devices * @param vendor_id * @param product_id * @param model_number * @param flags * @return */ SANE_Status sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags) { int i = 0, k; struct Pieusb_USB_Device_Entry* dl; while (pieusb_supported_usb_device_list[i].vendor != 0) { i++; } /* i is index of last entry */ for (k=0; k<=i; k++) { DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add(): current %03d: %04x %04x %02x %02x\n", i, pieusb_supported_usb_device_list[k].vendor, pieusb_supported_usb_device_list[k].product, pieusb_supported_usb_device_list[k].model, pieusb_supported_usb_device_list[k].flags); } dl = realloc(pieusb_supported_usb_device_list,(i+2)*sizeof(struct Pieusb_USB_Device_Entry)); /* Add one entry to list */ if (dl == NULL) { return SANE_STATUS_INVAL; } /* Copy values */ pieusb_supported_usb_device_list = dl; pieusb_supported_usb_device_list[i].vendor = vendor_id; pieusb_supported_usb_device_list[i].product = product_id; pieusb_supported_usb_device_list[i].model = model_number; pieusb_supported_usb_device_list[i].flags = flags; pieusb_supported_usb_device_list[i+1].vendor = 0; pieusb_supported_usb_device_list[i+1].product = 0; pieusb_supported_usb_device_list[i+1].model = 0; pieusb_supported_usb_device_list[i+1].flags = 0; for (k=0; k<=i+1; k++) { DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add() add: %03d: %04x %04x %02x %02x\n", i, pieusb_supported_usb_device_list[k].vendor, pieusb_supported_usb_device_list[k].product, pieusb_supported_usb_device_list[k].model, pieusb_supported_usb_device_list[k].flags); } return SANE_STATUS_GOOD; } /** * Actions to perform when a cancel request has been received. * * @param scanner scanner to stop scanning * @return SANE_STATUS_CANCELLED */ SANE_Status sanei_pieusb_on_cancel (Pieusb_Scanner * scanner) { struct Pieusb_Command_Status status; DBG (DBG_info_proc, "sanei_pieusb_on_cancel()\n"); sanei_pieusb_cmd_stop_scan (scanner->device_number, &status); sanei_pieusb_cmd_set_scan_head (scanner->device_number, 1, 0, &status); sanei_pieusb_buffer_delete (&scanner->buffer); scanner->scanning = SANE_FALSE; return SANE_STATUS_CANCELLED; } /** * Determine maximum lengt of a set of strings. * * @param strings Set of strings * @return maximum length */ static size_t max_string_size (SANE_String_Const const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* From MR's pie.c */ /* ------------------------- PIEUSB_CORRECT_SHADING -------------------------- */ /** * Correct the given buffer for shading using shading data in scanner. * If the loop order is width->color->height, a 7200 dpi scan correction takes * 45 minutes. If the loop order is color->height->width, this is less than 3 * minutes. So it is worthwhile to find the used pixels first (array width_to_loc). * * @param scanner Scanner * @param buffer Buffer to correct */ void sanei_pieusb_correct_shading(struct Pieusb_Scanner *scanner, struct Pieusb_Read_Buffer *buffer) { int i, j, c, k; SANE_Uint val, val_org, *p; int *width_to_loc; DBG (DBG_info_proc, "sanei_pieusb_correct_shading()\n"); /* Loop through CCD-mask to find used pixels */ width_to_loc = calloc(buffer->width,sizeof(int)); j = 0; for (i = 0; i < scanner->ccd_mask_size; i++) { if (scanner->ccd_mask[i] == 0) { width_to_loc[j++] = i; } } /* Correct complete image */ for (c = 0; c < buffer->colors; c++) { DBG(DBG_info,"sanei_pieusb_correct_shading() correct color %d\n",c); for (k = 0; k < buffer->height; k++) { /* DBG(DBG_info,"Correct line %d\n",k); */ p = buffer->data + c * buffer->width * buffer->height + k * buffer->width; for (j = 0; j < buffer->width; j++) { val_org = *p; val = lround((double)scanner->shading_mean[c] / scanner->shading_ref[c][width_to_loc[j]] * val_org); /* DBG(DBG_info,"Correct [%d,%d,%d] %d -> %d\n",k,j,c,val_org,val); */ *p++ = val; } } } /* Free memory */ free(width_to_loc); } /* === functions copied from MR's code === */ /** * * @param scanner * @param in_img * @param planes * @param out_planes * @return */ SANE_Status sanei_pieusb_post (Pieusb_Scanner *scanner, uint16_t **in_img, int planes) { uint16_t *cplane[PLANES]; /* R, G, B, I gray scale planes */ SANE_Parameters parameters; /* describes the image */ int winsize_smooth; /* for adapting replaced pixels */ char filename[64]; SANE_Status status; int smooth, i; memcpy (¶meters, &scanner->scan_parameters, sizeof (SANE_Parameters)); parameters.format = SANE_FRAME_GRAY; parameters.bytes_per_line = parameters.pixels_per_line; if (parameters.depth > 8) parameters.bytes_per_line *= 2; parameters.last_frame = 0; DBG (DBG_info, "pie_usb_post: %d ppl, %d lines, %d bits, %d planes, %d dpi\n", parameters.pixels_per_line, parameters.lines, parameters.depth, planes, scanner->mode.resolution); if (planes > PLANES) { DBG (DBG_error, "pie_usb_post: too many planes: %d (max %d)\n", planes, PLANES); return SANE_STATUS_INVAL; } for (i = 0; i < planes; i++) cplane[i] = in_img[i]; /* dirt is rather resolution invariant, so * setup resolution dependent parameters */ /* film grain reduction */ smooth = scanner->val[OPT_SMOOTH_IMAGE].w; winsize_smooth = (scanner->mode.resolution / 540) | 1; /* smoothen whole image or only replaced pixels */ if (smooth) { winsize_smooth += 2 * (smooth - 3); /* even */ if (winsize_smooth < 3) smooth = 0; } if (winsize_smooth < 3) winsize_smooth = 3; DBG (DBG_info, "pie_usb_sw_post: winsize_smooth %d\n", winsize_smooth); /* RGBI post-processing if selected: * 1) remove spectral overlay from ired plane, * 2) remove dirt, smoothen if, crop if */ if (scanner->val[OPT_CORRECT_INFRARED].b) /* (scanner->processing & POST_SW_IRED_MASK) */ { /* remove spectral overlay from ired plane */ status = sanei_ir_spectral_clean (¶meters, scanner->ln_lut, cplane[0], cplane[3]); if (status != SANE_STATUS_GOOD) return status; if (DBG_LEVEL >= 15) { snprintf (filename, 63, "/tmp/ir-spectral.pnm"); pieusb_write_pnm_file (filename, cplane[3], parameters.depth, 1, parameters.pixels_per_line, parameters.lines); } if (scanner->cancel_request) /* asynchronous cancel ? */ return SANE_STATUS_CANCELLED; } /* scanner-> processing & POST_SW_IRED_MASK */ /* remove dirt, smoothen if, crop if */ if (scanner->val[OPT_CLEAN_IMAGE].b) /* (scanner->processing & POST_SW_DIRT) */ { double *norm_histo; uint16_t *thresh_data; int static_thresh, too_thresh; /* static thresholds */ int winsize_filter; /* primary size of filtering window */ int size_dilate; /* the dirt mask */ /* size of filter detecting dirt */ winsize_filter = (int) (5.0 * (double) scanner->mode.resolution / 300.0) | 1; if (winsize_filter < 3) winsize_filter = 3; /* dirt usually has smooth edges which also need correction */ size_dilate = scanner->mode.resolution / 1000 + 1; /* first detect large dirt by a static threshold */ status = sanei_ir_create_norm_histogram (¶meters, cplane[3], &norm_histo); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "pie_usb_sw_post: no buffer\n"); return SANE_STATUS_NO_MEM; } /* generate a "bimodal" static threshold */ status = sanei_ir_threshold_yen (¶meters, norm_histo, &static_thresh); if (status != SANE_STATUS_GOOD) return status; /* generate traditional static threshold */ status = sanei_ir_threshold_otsu (¶meters, norm_histo, &too_thresh); if (status != SANE_STATUS_GOOD) return status; /* choose lower one */ if (too_thresh < static_thresh) static_thresh = too_thresh; free (norm_histo); /* then generate dirt mask with adaptive thresholding filter * and add the dirt from the static threshold */ /* last two parameters: 10, 50 detects more, 20, 75 less */ status = sanei_ir_filter_madmean (¶meters, cplane[3], &thresh_data, winsize_filter, 20, 100); if (status != SANE_STATUS_GOOD) { free (thresh_data); return status; } sanei_ir_add_threshold (¶meters, cplane[3], thresh_data, static_thresh); if (DBG_LEVEL >= 15) { snprintf (filename, 63, "/tmp/ir-threshold.pnm"); pieusb_write_pnm_file (filename, thresh_data, 8, 1, parameters.pixels_per_line, parameters.lines); } if (scanner->cancel_request) { /* asynchronous cancel ? */ free (thresh_data); return SANE_STATUS_CANCELLED; } /* replace the dirt and smoothen film grain and crop if possible */ status = sanei_ir_dilate_mean (¶meters, cplane, thresh_data, 500, size_dilate, winsize_smooth, smooth, 0, NULL); if (status != SANE_STATUS_GOOD) { free (thresh_data); return status; } smooth = 0; free (thresh_data); } if (DBG_LEVEL >= 15) { pieusb_write_pnm_file ("/tmp/RGBi-img.pnm", scanner->buffer.data, scanner->scan_parameters.depth, 3, scanner->scan_parameters.pixels_per_line, scanner->scan_parameters.lines); } return status; } /* ------------------------------ PIE_USB_WRITE_PNM_FILE ------------------------------- */ static SANE_Status pieusb_write_pnm_file (char *filename, SANE_Uint *data, int depth, int channels, int pixels_per_line, int lines) { FILE *out; int r, c, ch; SANE_Uint val; uint8_t b = 0; DBG (DBG_info_proc, "pie_usb_write_pnm_file: depth=%d, channels=%d, ppl=%d, lines=%d\n", depth, channels, pixels_per_line, lines); out = fopen (filename, "w"); if (!out) { DBG (DBG_error, "pie_usb_write_pnm_file: could not open %s for writing: %s\n", filename, strerror (errno)); return SANE_STATUS_INVAL; } switch (depth) { case 1: fprintf (out, "P4\n%d\n%d\n", pixels_per_line, lines); for (r = 0; r < lines; r++) { int i; i = 0; b = 0; for (c = 0; c < pixels_per_line; c++) { val = *(data + r * pixels_per_line + c); if (val > 0) b |= (0x80 >> i); i++; if (i == 7) { fputc(b, out); i = 0; b = 0; } } if (i != 0) { fputc(b, out); } } break; case 8: fprintf (out, "P%c\n%d\n%d\n%d\n", channels == 1 ? '5' : '6', pixels_per_line, lines, 255); for (r = 0; r < lines; r++) { for (c = 0; c < pixels_per_line; c++) { for (ch = 0; ch < channels; ch++) { val = *(data + ch * lines * pixels_per_line + r * pixels_per_line + c); b = val & 0xFF; fputc(b, out); } } } break; case 16: fprintf (out, "P%c\n%d\n%d\n%d\n", channels == 1 ? '5' : '6', pixels_per_line, lines, 65535); for (r = 0; r < lines; r++) { for (c = 0; c < pixels_per_line; c++) { for (ch = 0; ch < channels; ch++) { val = *(data + ch * lines * pixels_per_line + r * pixels_per_line + c); b = (val >> 8) & 0xFF; fputc(b, out); b = val & 0xFF; fputc(b, out); } } } break; default: DBG (DBG_error, "pie_usb_write_pnm_file: depth %d not implemented\n", depth); } fclose (out); DBG (DBG_info, "pie_usb_write_pnm_file: finished\n"); return SANE_STATUS_GOOD; } /** * Check option inconsistencies. * In most cases an inconsistency can be solved by ignoring an option setting. * Message these situations and return 1 to indicate we can work with the * current set op options. If the settings are really inconsistent, return 0. */ int sanei_pieusb_analyse_options(struct Pieusb_Scanner *scanner) { /* Checks*/ if (scanner->val[OPT_TL_X].w > scanner->val[OPT_BR_X].w) { DBG (DBG_error, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) -- aborting\n", scanner->opt[OPT_TL_X].title, SANE_UNFIX (scanner->val[OPT_TL_X].w), scanner->opt[OPT_BR_X].title, SANE_UNFIX (scanner->val[OPT_BR_X].w)); return 0; } if (scanner->val[OPT_TL_Y].w > scanner->val[OPT_BR_Y].w) { DBG (DBG_error, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) -- aborting\n", scanner->opt[OPT_TL_Y].title, SANE_UNFIX (scanner->val[OPT_TL_Y].w), scanner->opt[OPT_BR_Y].title, SANE_UNFIX (scanner->val[OPT_BR_Y].w)); return 0; } /* Modes sometimes limit other choices */ if (scanner->val[OPT_PREVIEW].b) { /* Preview uses its own specific settings */ if (scanner->val[OPT_RESOLUTION].w != (scanner->device->fast_preview_resolution << SANE_FIXED_SCALE_SHIFT)) { DBG (DBG_info_sane, "Option %s = %f ignored during preview\n", scanner->opt[OPT_RESOLUTION].name, SANE_UNFIX(scanner->val[OPT_RESOLUTION].w)); } if (scanner->val[OPT_SHARPEN].b) { DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_SHARPEN].name, scanner->val[OPT_SHARPEN].b); } if (!scanner->val[OPT_FAST_INFRARED].b) { DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_FAST_INFRARED].name, scanner->val[OPT_FAST_INFRARED].b); } if (scanner->val[OPT_CORRECT_INFRARED].b) { DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_CORRECT_INFRARED].name, scanner->val[OPT_CORRECT_INFRARED].b); } if (scanner->val[OPT_CLEAN_IMAGE].b) { DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_CLEAN_IMAGE].name, scanner->val[OPT_CLEAN_IMAGE].b); } if (scanner->val[OPT_SMOOTH_IMAGE].w != 0) { DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_SMOOTH_IMAGE].name, scanner->val[OPT_SMOOTH_IMAGE].w); } if (strcmp(scanner->val[OPT_CROP_IMAGE].s, scanner->device->crop_sw_list[0]) != 0) { DBG (DBG_info_sane, "Option %s = %s ignored during preview\n", scanner->opt[OPT_CROP_IMAGE].name, scanner->val[OPT_CROP_IMAGE].s); } if (scanner->val[OPT_TRANSFORM_TO_SRGB].b) { DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_TRANSFORM_TO_SRGB].name, scanner->val[OPT_TRANSFORM_TO_SRGB].w); } if (scanner->val[OPT_INVERT_IMAGE].w) { DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_INVERT_IMAGE].name, scanner->val[OPT_INVERT_IMAGE].w); } } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_LINEART)==0) { /* Can we do any post processing in lineart? Needs testing to see what's possible */ if (scanner->val[OPT_BIT_DEPTH].w != 1) { DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (will use 1)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w); } if (!scanner->val[OPT_FAST_INFRARED].b) { DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_FAST_INFRARED].name, scanner->val[OPT_FAST_INFRARED].b); } if (!scanner->val[OPT_CORRECT_SHADING].b) { DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_CORRECT_SHADING].name, scanner->val[OPT_CORRECT_SHADING].b); } if (!scanner->val[OPT_CORRECT_INFRARED].b) { DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_CORRECT_INFRARED].name, scanner->val[OPT_CORRECT_INFRARED].b); } if (scanner->val[OPT_CLEAN_IMAGE].b) { DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_CLEAN_IMAGE].name, scanner->val[OPT_CLEAN_IMAGE].b); } if (scanner->val[OPT_SMOOTH_IMAGE].w != 0) { DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_SMOOTH_IMAGE].name, scanner->val[OPT_SMOOTH_IMAGE].w); } if (strcmp(scanner->val[OPT_CROP_IMAGE].s, scanner->device->crop_sw_list[0]) != 0) { DBG (DBG_info_sane, "Option %s = %s ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_CROP_IMAGE].name, scanner->val[OPT_CROP_IMAGE].s); } if (scanner->val[OPT_TRANSFORM_TO_SRGB].b) { DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_TRANSFORM_TO_SRGB].name, scanner->val[OPT_TRANSFORM_TO_SRGB].w); } } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_HALFTONE)==0) { /* Can we do any post processing in halftone? Needs testing to see what's possible */ if (scanner->val[OPT_BIT_DEPTH].w != 1) { DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (will use 1)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w); } if (!scanner->val[OPT_FAST_INFRARED].b) { DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_FAST_INFRARED].name, scanner->val[OPT_FAST_INFRARED].b); } if (!scanner->val[OPT_CORRECT_SHADING].b) { DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_CORRECT_SHADING].name, scanner->val[OPT_CORRECT_SHADING].b); } if (!scanner->val[OPT_CORRECT_INFRARED].b) { DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_CORRECT_INFRARED].name, scanner->val[OPT_CORRECT_INFRARED].b); } if (scanner->val[OPT_CLEAN_IMAGE].b) { DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_CLEAN_IMAGE].name, scanner->val[OPT_CLEAN_IMAGE].b); } if (scanner->val[OPT_SMOOTH_IMAGE].w != 0) { DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_SMOOTH_IMAGE].name, scanner->val[OPT_SMOOTH_IMAGE].w); } if (strcmp(scanner->val[OPT_CROP_IMAGE].s, scanner->device->crop_sw_list[0]) != 0) { DBG (DBG_info_sane, "Option %s = %s ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_CROP_IMAGE].name, scanner->val[OPT_CROP_IMAGE].s); } if (scanner->val[OPT_TRANSFORM_TO_SRGB].b) { DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_TRANSFORM_TO_SRGB].name, scanner->val[OPT_TRANSFORM_TO_SRGB].w); } } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_GRAY)==0) { /* Can we do any post processing in gray mode? */ /* Can we obtain a single color channel in this mode? How? */ /* Is this just RGB with luminance trasformation? */ /* Needs testing to see what's possible */ /* Only do 8 or 16 bit scans */ if (scanner->val[OPT_BIT_DEPTH].w == 1) { DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (will use 8)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w); } if (!scanner->val[OPT_FAST_INFRARED].b) { DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (irrelevant)\n", scanner->opt[OPT_FAST_INFRARED].name, scanner->val[OPT_FAST_INFRARED].b); } if (!scanner->val[OPT_CORRECT_INFRARED].b) { DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (irrelevant)\n", scanner->opt[OPT_CORRECT_INFRARED].name, scanner->val[OPT_CORRECT_INFRARED].b); } if (scanner->val[OPT_CLEAN_IMAGE].b) { DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (irrelevant)\n", scanner->opt[OPT_CLEAN_IMAGE].name, scanner->val[OPT_CLEAN_IMAGE].b); } if (scanner->val[OPT_TRANSFORM_TO_SRGB].b) { DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (irrelevant)\n", scanner->opt[OPT_TRANSFORM_TO_SRGB].name, scanner->val[OPT_TRANSFORM_TO_SRGB].w); } } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_COLOR)==0) { /* Some options require infrared data to be obtained, so all infrared options are relevant */ /* Only do 8 or 16 bit scans */ if (scanner->val[OPT_BIT_DEPTH].w == 1) { DBG (DBG_info_sane, "Option %s = %d ignored in color mode (will use 8)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w); } } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_RGBI)==0) { /* Only do 8 or 16 bit scans */ if (scanner->val[OPT_BIT_DEPTH].w == 1) { DBG (DBG_info_sane, "Option %s = %d ignored in color mode (will use 8)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w); } } return 1; } /** * Print options * * @param scanner */ void sanei_pieusb_print_options(struct Pieusb_Scanner *scanner) { int k; /* List current options and values */ DBG (DBG_info, "Num options = %d\n", scanner->val[OPT_NUM_OPTS].w); for (k = 1; k < scanner->val[OPT_NUM_OPTS].w; k++) { switch (scanner->opt[k].type) { case SANE_TYPE_BOOL: DBG(DBG_info," Option %d: %s = %d\n", k, scanner->opt[k].name, scanner->val[k].b); break; case SANE_TYPE_INT: DBG(DBG_info," Option %d: %s = %d\n", k, scanner->opt[k].name, scanner->val[k].w); break; case SANE_TYPE_FIXED: DBG(DBG_info," Option %d: %s = %f\n", k, scanner->opt[k].name, SANE_UNFIX (scanner->val[k].w)); break; case SANE_TYPE_STRING: DBG(DBG_info," Option %d: %s = %s\n", k, scanner->opt[k].name, scanner->val[k].s); break; case SANE_TYPE_GROUP: DBG(DBG_info," Option %d: %s = %s\n", k, scanner->opt[k].title, scanner->val[k].s); break; default: DBG(DBG_info," Option %d: %s unknown type %d\n", k, scanner->opt[k].name, scanner->opt[k].type); break; } } } /** * Calculate reference values for each pixel, line means and line maxima. * We have got 45 lines for all four colors and for each CCD pixel. * The reference value for each pixel is the 45-line average for that * pixel, for each color separately. * * @param scanner * @param buffer */ static void pieusb_calculate_shading(struct Pieusb_Scanner *scanner, SANE_Byte* buffer) { int k, m; SANE_Byte* p; SANE_Int ci, val; SANE_Int shading_width = scanner->device->shading_parameters[0].pixelsPerLine; SANE_Int shading_height = scanner->device->shading_parameters[0].nLines; /* Initialze all to 0 */ for (k = 0; k < SHADING_PARAMETERS_INFO_COUNT; k++) { scanner->shading_max[k] = 0; scanner->shading_mean[k] = 0; memset(scanner->shading_ref[k], 0, shading_width * sizeof (SANE_Int)); } /* Process data from buffer */ p = buffer; switch (scanner->mode.colorFormat) { case 0x01: /* Pixel */ /* Process pixel by pixel */ for (k = 0; k < shading_height; k++) { for (m = 0; m < shading_width; m++) { for (ci = 0; ci < SHADING_PARAMETERS_INFO_COUNT; ci++) { val = *(p) + *(p+1) * 256; scanner->shading_ref[ci][m] += val; scanner->shading_max[ci] = scanner->shading_max[ci] < val ? val : scanner->shading_max[ci]; p += 2; } } } break; case 0x04: /* Indexed */ /* Process each line in the sequence found in the buffer */ for (k = 0; k < shading_height*4; k++) { /* Save at right color */ switch (*p) { case 'R': ci = 0; break; case 'G': ci = 1; break; case 'B': ci = 2; break; case 'I': ci = 3; break; default: ci = -1; break; /* ignore line */ } /* Add scanned data to reference line and keep track of maximum */ if (ci != -1) { for (m = 0; m < shading_width; m++) { val = *(p+2+2*m) + *(p+2+2*m+1) * 256; scanner->shading_ref[ci][m] += val; scanner->shading_max[ci] = scanner->shading_max[ci] < val ? val : scanner->shading_max[ci]; /* DBG(DBG_error,"%02d Shading_ref[%d][%d] = %d\n",k,ci,m,scanner->shading_ref[ci][m]); */ } } /* Next line */ p += 2*shading_width+2; } break; default: DBG (DBG_error,"sane_start(): color format %d not implemented\n",scanner->mode.colorFormat); return; } /* Mean reference value needs division */ for (k = 0; k < SHADING_PARAMETERS_INFO_COUNT; k++) { for (m = 0; m < shading_width; m++) { scanner->shading_ref[k][m] = lround((double)scanner->shading_ref[k][m]/shading_height); /* DBG(DBG_error,"Shading_ref[%d][%d] = %d\n",k,m,scanner->shading_ref[k][m]); */ } } /* Overall means */ for (k = 0; k < SHADING_PARAMETERS_INFO_COUNT; k++) { for (m=0; mshading_mean[k] += scanner->shading_ref[k][m]; } scanner->shading_mean[k] = lround((double)scanner->shading_mean[k]/shading_width); DBG (DBG_error,"Shading_mean[%d] = %d\n",k,scanner->shading_mean[k]); } /* Set shading data present */ scanner->shading_data_present = SANE_TRUE; /* Export shading data as TIFF */ #ifdef CAN_DO_4_CHANNEL_TIFF if (scanner->val[OPT_SAVE_SHADINGDATA].b) { struct Pieusb_Read_Buffer shading; SANE_Byte* lboff = buffer; SANE_Int bpl = shading_width*2; SANE_Int n; buffer_create(&shading, shading_width, shading_height, 0x0F, 16); for (n=0; n<4*shading_height; n++) { if (buffer_put_single_color_line(&shading, *lboff, lboff+2, bpl) == 0) { break; } lboff += (bpl + 2); } FILE* fs = fopen("pieusb.shading", "w"); /* write_tiff_rgbi_header (fs, shading_width, shading_height, 16, 3600, NULL); */ fwrite(shading.data, 1, shading.image_size_bytes, fs); fclose(fs); buffer_delete(&shading); } #endif } /* * Set frame (from scanner options) */ SANE_Status sanei_pieusb_set_frame_from_options(Pieusb_Scanner * scanner) { double dpmm; struct Pieusb_Command_Status status; dpmm = (double) scanner->device->maximum_resolution / MM_PER_INCH; scanner->frame.x0 = SANE_UNFIX(scanner->val[OPT_TL_X].w) * dpmm; scanner->frame.y0 = SANE_UNFIX(scanner->val[OPT_TL_Y].w) * dpmm; scanner->frame.x1 = SANE_UNFIX(scanner->val[OPT_BR_X].w) * dpmm; scanner->frame.y1 = SANE_UNFIX(scanner->val[OPT_BR_Y].w) * dpmm; scanner->frame.index = 0x80; /* 0x80: value from cyberview */ sanei_pieusb_cmd_set_scan_frame (scanner->device_number, scanner->frame.index, &(scanner->frame), &status); DBG (DBG_info_sane, "sanei_pieusb_set_frame_from_options(): sanei_pieusb_cmd_set_scan_frame status %s\n", sane_strstatus (sanei_pieusb_convert_status (status.pieusb_status))); return status.pieusb_status; } /* * Set mode (from scanner options) */ SANE_Status sanei_pieusb_set_mode_from_options(Pieusb_Scanner * scanner) { struct Pieusb_Command_Status status; const char *mode; SANE_Status res; mode = scanner->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) { scanner->mode.passes = SCAN_FILTER_GREEN; /* G */ scanner->mode.colorFormat = SCAN_COLOR_FORMAT_PIXEL; } else if(strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { scanner->mode.passes = SCAN_FILTER_GREEN; /* G */ scanner->mode.colorFormat = SCAN_COLOR_FORMAT_PIXEL; } else if(strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { scanner->mode.passes = SCAN_FILTER_GREEN; /* G=gray; unable to get R & B & I to work */ scanner->mode.colorFormat = SCAN_COLOR_FORMAT_PIXEL; } else if(scanner->val[OPT_PREVIEW].b) { /* Catch preview here, otherwise next ifs get complicated */ scanner->mode.passes = SCAN_ONE_PASS_COLOR; scanner->mode.colorFormat = SCAN_COLOR_FORMAT_INDEX; /* pixel format might be an alternative */ } else if(strcmp (mode, SANE_VALUE_SCAN_MODE_RGBI) == 0) { scanner->mode.passes = SCAN_ONE_PASS_RGBI; scanner->mode.colorFormat = SCAN_COLOR_FORMAT_INDEX; } else if(strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0 && scanner->val[OPT_CLEAN_IMAGE].b) { scanner->mode.passes = SCAN_ONE_PASS_RGBI; /* Need infrared for cleaning */ scanner->mode.colorFormat = SCAN_COLOR_FORMAT_INDEX; } else { /* SANE_VALUE_SCAN_MODE_COLOR */ scanner->mode.passes = SCAN_ONE_PASS_COLOR; scanner->mode.colorFormat = SCAN_COLOR_FORMAT_INDEX; /* pixel format might be an alternative */ } /* Resolution */ if (scanner->val[OPT_PREVIEW].b) { scanner->mode.resolution = scanner->device->fast_preview_resolution; DBG (DBG_info_sane, "sanei_pieusb_set_mode_from_options(): resolution fast preview (%d)\n", scanner->mode.resolution); } else { scanner->mode.resolution = SANE_UNFIX (scanner->val[OPT_RESOLUTION].w); DBG (DBG_info_sane, "sanei_pieusb_set_mode_from_options(): resolution from option setting (%d)\n", scanner->mode.resolution); } /* Bit depth: exit on untested values */ switch (scanner->val[OPT_BIT_DEPTH].w) { case 1: scanner->mode.colorDepth = SCAN_COLOR_DEPTH_1; break; case 8: scanner->mode.colorDepth = SCAN_COLOR_DEPTH_8; break; case 16: scanner->mode.colorDepth = SCAN_COLOR_DEPTH_16; break; default: /* 4, 10 & 12 */ DBG (DBG_error, "sanei_pieusb_set_mode_from_options(): sanei_pieusb_cmd_set_scan_frame untested bit depth %d\n", scanner->val[OPT_BIT_DEPTH].w); return SANE_STATUS_INVAL; } scanner->mode.byteOrder = 0x01; /* 0x01 = Intel; only bit 0 used */ scanner->mode.sharpen = scanner->val[OPT_SHARPEN].b && !scanner->val[OPT_PREVIEW].b; scanner->mode.skipShadingAnalysis = !scanner->val[OPT_SHADING_ANALYSIS].b; scanner->mode.fastInfrared = scanner->val[OPT_FAST_INFRARED].b && !scanner->val[OPT_PREVIEW].b; if (strcmp (scanner->val[OPT_HALFTONE_PATTERN].s, "53lpi 45d ROUND") == 0) { scanner->mode.halftonePattern = 0; } else { /*TODO: the others */ scanner->mode.halftonePattern = 0; } scanner->mode.lineThreshold = SANE_UNFIX (scanner->val[OPT_THRESHOLD].w) / 100 * 0xFF; /* 0xFF = 100% */ sanei_pieusb_cmd_set_mode (scanner->device_number, &(scanner->mode), &status); res = sanei_pieusb_convert_status(status.pieusb_status); if (res == SANE_STATUS_GOOD) { res = sanei_pieusb_wait_ready (scanner, 0); } DBG (DBG_info_sane, "sanei_pieusb_set_mode_from_options(): sanei_pieusb_cmd_set_mode status %s\n", sane_strstatus(res)); return res; } /** * Set gains, exposure and offset, to: * - values default (pieusb_set_default_gain_offset) * - values set by options * - values set by auto-calibration procedure * - values determined from preceeding preview * * @param scanner * @return */ SANE_Status sanei_pieusb_set_gain_offset(Pieusb_Scanner * scanner, const char *calibration_mode) { struct Pieusb_Command_Status status; SANE_Status ret; double gain; DBG (DBG_info,"sanei_pieusb_set_gain_offset(): mode = %s\n", calibration_mode); if (strcmp (calibration_mode, SCAN_CALIBRATION_DEFAULT) == 0) { /* Default values */ DBG(DBG_info_sane,"sanei_pieusb_set_gain_offset(): get calibration data from defaults\n"); scanner->settings.exposureTime[0] = DEFAULT_EXPOSURE; scanner->settings.exposureTime[1] = DEFAULT_EXPOSURE; scanner->settings.exposureTime[2] = DEFAULT_EXPOSURE; scanner->settings.exposureTime[3] = DEFAULT_EXPOSURE; scanner->settings.offset[0] = DEFAULT_OFFSET; scanner->settings.offset[1] = DEFAULT_OFFSET; scanner->settings.offset[2] = DEFAULT_OFFSET; scanner->settings.offset[3] = DEFAULT_OFFSET; scanner->settings.gain[0] = DEFAULT_GAIN; scanner->settings.gain[1] = DEFAULT_GAIN; scanner->settings.gain[2] = DEFAULT_GAIN; scanner->settings.gain[3] = DEFAULT_GAIN; scanner->settings.light = DEFAULT_LIGHT; scanner->settings.extraEntries = DEFAULT_ADDITIONAL_ENTRIES; scanner->settings.doubleTimes = DEFAULT_DOUBLE_TIMES; status.pieusb_status = PIEUSB_STATUS_GOOD; } else if ((strcmp(calibration_mode, SCAN_CALIBRATION_PREVIEW) == 0) && scanner->preview_done) { /* If no preview data availble, do the auto-calibration. */ double dg, dgi; DBG (DBG_info, "sanei_pieusb_set_gain_offset(): get calibration data from preview. scanner->mode.passes %d\n", scanner->mode.passes); switch (scanner->mode.passes) { case SCAN_ONE_PASS_RGBI: dg = 3.00; dgi = ((double)scanner->settings.saturationLevel[0] / 65536) / ((double)scanner->preview_upper_bound[0] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; dgi = ((double)scanner->settings.saturationLevel[1] / 65536) / ((double)scanner->preview_upper_bound[1] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; dgi = ((double)scanner->settings.saturationLevel[2] / 65536) / ((double)scanner->preview_upper_bound[2] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; updateGain2(scanner, 0, dg); updateGain2(scanner, 1, dg); updateGain2(scanner, 2, dg); break; case SCAN_ONE_PASS_COLOR: dg = 3.00; dgi = ((double)scanner->settings.saturationLevel[0] / 65536) / ((double)scanner->preview_upper_bound[0] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; dgi = ((double)scanner->settings.saturationLevel[1] / 65536) / ((double)scanner->preview_upper_bound[1] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; dgi = ((double)scanner->settings.saturationLevel[2] / 65536) / ((double)scanner->preview_upper_bound[2] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; updateGain2(scanner, 0, dg); updateGain2(scanner, 1, dg); updateGain2(scanner, 2, dg); break; case SCAN_FILTER_BLUE: dg = 3.00; dgi = ((double)scanner->settings.saturationLevel[2] / 65536) / ((double)scanner->preview_upper_bound[2] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; updateGain2(scanner, 2, dg); break; case SCAN_FILTER_GREEN: dg = 3.00; dgi = ((double)scanner->settings.saturationLevel[1] / 65536) / ((double)scanner->preview_upper_bound[1] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; updateGain2(scanner, 1, dg); break; case SCAN_FILTER_RED: dg = 3.00; dgi = ((double)scanner->settings.saturationLevel[0] / 65536) / ((double)scanner->preview_upper_bound[0] / HISTOGRAM_SIZE); if (dgi < dg) dg = dgi; updateGain2(scanner, 0, dg); break; case SCAN_FILTER_NEUTRAL: break; } status.pieusb_status = PIEUSB_STATUS_GOOD; } else if (strcmp (calibration_mode, SCAN_CALIBRATION_OPTIONS) == 0) { DBG (DBG_info_sane, "sanei_pieusb_set_gain_offset(): get calibration data from options\n"); /* Exposure times */ scanner->settings.exposureTime[0] = scanner->val[OPT_SET_EXPOSURE_R].w; scanner->settings.exposureTime[1] = scanner->val[OPT_SET_EXPOSURE_G].w; scanner->settings.exposureTime[2] = scanner->val[OPT_SET_EXPOSURE_B].w; scanner->settings.exposureTime[3] = scanner->val[OPT_SET_EXPOSURE_I].w; /* Infrared */ /* Offsets */ scanner->settings.offset[0] = scanner->val[OPT_SET_OFFSET_R].w; scanner->settings.offset[1] = scanner->val[OPT_SET_OFFSET_G].w; scanner->settings.offset[2] = scanner->val[OPT_SET_OFFSET_B].w; scanner->settings.offset[3] = scanner->val[OPT_SET_OFFSET_I].w; /* Infrared */ /* Gains */ scanner->settings.gain[0] = scanner->val[OPT_SET_GAIN_R].w; scanner->settings.gain[1] = scanner->val[OPT_SET_GAIN_G].w; scanner->settings.gain[2] = scanner->val[OPT_SET_GAIN_B].w; scanner->settings.gain[3] = scanner->val[OPT_SET_GAIN_I].w; /* Infrared */ /* Light, extra entries and doubling */ scanner->settings.light = scanner->val[OPT_LIGHT].w; scanner->settings.extraEntries = DEFAULT_ADDITIONAL_ENTRIES; scanner->settings.doubleTimes = scanner->val[OPT_DOUBLE_TIMES].w; status.pieusb_status = PIEUSB_STATUS_GOOD; } else { /* SCAN_CALIBRATION_AUTO */ DBG (DBG_info_sane, "sanei_pieusb_set_gain_offset(): get calibration data from scanner\n"); sanei_pieusb_cmd_get_gain_offset (scanner->device_number, &scanner->settings, &status); } /* Check status */ if (status.pieusb_status == PIEUSB_STATUS_DEVICE_BUSY) { ret = sanei_pieusb_wait_ready (scanner, 0); if (ret != SANE_STATUS_GOOD) { DBG (DBG_error,"sanei_pieusb_set_gain_offset(): not ready after sanei_pieusb_cmd_get_gain_offset(): %d\n", ret); return ret; } } else if (status.pieusb_status != PIEUSB_STATUS_GOOD) { return SANE_STATUS_INVAL; } /* Adjust gain */ gain = 1.0; if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_03) == 0) { gain = 0.3; } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_05) == 0) { gain = 0.5; } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_08) == 0) { gain = 0.8; } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_10) == 0) { gain = 1.0; } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_12) == 0) { gain = 1.2; } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_16) == 0) { gain = 1.6; } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_19) == 0) { gain = 1.9; } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_24) == 0) { gain = 2.4; } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_30) == 0) { gain = 3.0; } switch (scanner->mode.passes) { case SCAN_ONE_PASS_RGBI: case SCAN_ONE_PASS_COLOR: updateGain2 (scanner, 0, gain); updateGain2 (scanner, 1, gain); updateGain2 (scanner, 2, gain); /* Don't correct IR, hampers cleaning process... */ break; case SCAN_FILTER_INFRARED: updateGain2 (scanner, 3, gain); break; case SCAN_FILTER_BLUE: updateGain2 (scanner, 2, gain); break; case SCAN_FILTER_GREEN: updateGain2 (scanner, 1, gain); break; case SCAN_FILTER_RED: updateGain2 (scanner, 0, gain); break; case SCAN_FILTER_NEUTRAL: break; } /* Now set values for gain, offset and exposure */ sanei_pieusb_cmd_set_gain_offset (scanner->device_number, &(scanner->settings), &status); ret = sanei_pieusb_convert_status (status.pieusb_status); DBG (DBG_info_sane, "sanei_pieusb_set_gain_offset(): status %s\n", sane_strstatus (ret)); return ret; } /* * get shading data * must be called immediately after sanei_pieusb_set_gain_offset */ SANE_Status sanei_pieusb_get_shading_data(Pieusb_Scanner * scanner) { struct Pieusb_Command_Status status; SANE_Int shading_width; SANE_Int shading_height; SANE_Byte* buffer; SANE_Int lines; SANE_Int cols; SANE_Int size; SANE_Status res = SANE_STATUS_GOOD; DBG (DBG_info_sane, "sanei_pieusb_get_shading_data()\n"); shading_width = scanner->device->shading_parameters[0].pixelsPerLine; shading_height = scanner->device->shading_parameters[0].nLines; if (shading_height < 1) { DBG (DBG_error, "shading_height < 1\n"); return SANE_STATUS_INVAL; } switch (scanner->mode.colorFormat) { case SCAN_COLOR_FORMAT_PIXEL: /* Pixel */ lines = shading_height * 4; cols = 2 * shading_width; break; case SCAN_COLOR_FORMAT_INDEX: /* Indexed */ lines = shading_height * 4; cols = (2 * shading_width + 2); break; default: DBG (DBG_error, "sanei_pieusb_get_shading_data(): color format %d not implemented\n", scanner->mode.colorFormat); return SANE_STATUS_INVAL; } size = cols * lines; buffer = malloc (size); if (buffer == NULL) { return SANE_STATUS_NO_MEM; } sanei_pieusb_cmd_get_scanned_lines (scanner->device_number, buffer, 4, cols * 4, &status); if (status.pieusb_status == PIEUSB_STATUS_GOOD) { res = sanei_pieusb_wait_ready (scanner, 0); if (res == SANE_STATUS_GOOD) { sanei_pieusb_cmd_get_scanned_lines (scanner->device_number, buffer + cols*4, lines - 4, (lines - 4) * cols, &status); if (status.pieusb_status == PIEUSB_STATUS_GOOD) { pieusb_calculate_shading (scanner, buffer); } res = sanei_pieusb_convert_status (status.pieusb_status); } } else { res = sanei_pieusb_convert_status (status.pieusb_status); } free (buffer); return res; } /* * */ SANE_Status sanei_pieusb_get_ccd_mask(Pieusb_Scanner * scanner) { struct Pieusb_Command_Status status; DBG(DBG_info_proc, "sanei_pieusb_get_ccd_mask()\n"); sanei_pieusb_cmd_get_ccd_mask(scanner->device_number, scanner->ccd_mask, scanner->ccd_mask_size, &status); if (status.pieusb_status == PIEUSB_STATUS_GOOD) { /* Save CCD mask */ if (scanner->val[OPT_SAVE_CCDMASK].b) { FILE* fs = fopen ("pieusb.ccd", "w"); fwrite (scanner->ccd_mask, 1, scanner->ccd_mask_size, fs); fclose (fs); } } return sanei_pieusb_convert_status(status.pieusb_status); } /** * Read parameters from scanner * and initialize SANE parameters * * @param scanner * @return parameter_bytes for use in get_scan_data() */ SANE_Status sanei_pieusb_get_parameters(Pieusb_Scanner * scanner, SANE_Int *parameter_bytes) { struct Pieusb_Command_Status status; struct Pieusb_Scan_Parameters parameters; const char *mode; DBG (DBG_info_proc, "sanei_pieusb_get_parameters()\n"); sanei_pieusb_cmd_get_parameters (scanner->device_number, ¶meters, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD) { return sanei_pieusb_convert_status (status.pieusb_status); } *parameter_bytes = parameters.bytes; /* Use response from sanei_pieusb_cmd_get_parameters() for initialization of SANE parameters. * Note the weird values of the bytes-field: this is because of the colorFormat * setting in sanei_pieusb_cmd_set_mode(). The single-color modes all use the pixel format, * which makes sanei_pieusb_cmd_get_parameters() return a full color line although just * one color actually contains data. For the index format, the bytes field * gives the size of a single color line. */ mode = scanner->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) { scanner->scan_parameters.format = SANE_FRAME_GRAY; scanner->scan_parameters.depth = 1; scanner->scan_parameters.bytes_per_line = parameters.bytes/3; } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { scanner->scan_parameters.format = SANE_FRAME_GRAY; scanner->scan_parameters.depth = 1; scanner->scan_parameters.bytes_per_line = parameters.bytes/3; } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { scanner->scan_parameters.format = SANE_FRAME_GRAY; scanner->scan_parameters.depth = scanner->val[OPT_BIT_DEPTH].w; scanner->scan_parameters.bytes_per_line = parameters.bytes/3; } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_RGBI) == 0) { scanner->scan_parameters.format = SANE_FRAME_RGB; /* was: SANE_FRAME_RGBI */ scanner->scan_parameters.depth = scanner->val[OPT_BIT_DEPTH].w; scanner->scan_parameters.bytes_per_line = 4*parameters.bytes; } else { /* SANE_VALUE_SCAN_MODE_COLOR, with and without option clean image set */ scanner->scan_parameters.format = SANE_FRAME_RGB; scanner->scan_parameters.depth = scanner->val[OPT_BIT_DEPTH].w; scanner->scan_parameters.bytes_per_line = 3*parameters.bytes; } scanner->scan_parameters.lines = parameters.lines; scanner->scan_parameters.pixels_per_line = parameters.width; scanner->scan_parameters.last_frame = SANE_TRUE; DBG (DBG_info_sane,"sanei_pieusb_get_parameters(): mode '%s'\n", mode); DBG (DBG_info_sane," format = %d\n", scanner->scan_parameters.format); DBG (DBG_info_sane," depth = %d\n", scanner->scan_parameters.depth); DBG (DBG_info_sane," bytes_per_line = %d\n", scanner->scan_parameters.bytes_per_line); DBG (DBG_info_sane," lines = %d\n", scanner->scan_parameters.lines); DBG (DBG_info_sane," pixels_per_line = %d\n", scanner->scan_parameters.pixels_per_line); DBG (DBG_info_sane," last_frame = %d\n", scanner->scan_parameters.last_frame); return SANE_STATUS_GOOD; } SANE_Status sanei_pieusb_get_scan_data(Pieusb_Scanner * scanner, SANE_Int parameter_bytes) { struct Pieusb_Command_Status status; SANE_Parameters *parameters = &scanner->scan_parameters; SANE_Int lines_to_read, lines_remaining; SANE_Int ppl, bpl; SANE_Byte *linebuf, *lboff; SANE_Bool compress; int n, k, i; switch (scanner->mode.colorFormat) { case SCAN_COLOR_FORMAT_PIXEL: /* Pixel */ lines_to_read = scanner->buffer.height; break; case SCAN_COLOR_FORMAT_INDEX: /* Indexed */ lines_to_read = scanner->buffer.colors * scanner->buffer.height; break; default: DBG(DBG_error, "sanei_pieusb_get_scan_data(): color format %d not implemented\n",scanner->mode.colorFormat); return SANE_STATUS_INVAL; } lines_remaining = lines_to_read; DBG (DBG_info_proc, "sanei_pieusb_get_scan_data(colorFormat %d), lines_to_read %d, bytes %d\n", scanner->mode.colorFormat, lines_to_read, parameter_bytes); /* fdraw = open("/tmp/pieusb.raw", O_WRONLY | O_CREAT | O_TRUNC, (mode_t)0600); if (fdraw == -1) { perror("error opening raw image buffer file"); } */ while (lines_remaining > 0) { SANE_Int lines; /* Read lines */ /* The amount of bytes_per_line varies with color format setting; only 'pixel' and 'index' implemented */ ppl = parameters->pixels_per_line; switch (scanner->mode.colorFormat) { case SCAN_COLOR_FORMAT_PIXEL: /* Pixel */ bpl = parameter_bytes; break; case SCAN_COLOR_FORMAT_INDEX: /* Indexed */ bpl = parameter_bytes + 2; /* Index bytes! */ break; default: DBG(DBG_error, "sanei_pieusb_get_scan_data(): color format %d not implemented\n", scanner->mode.colorFormat); return SANE_STATUS_INVAL; } lines = (lines_remaining < 256) ? lines_remaining : 255; DBG(DBG_info_sane, "sanei_pieusb_get_scan_data(): reading lines: now %d, bytes per line = %d\n", lines, bpl); linebuf = malloc(lines * bpl); sanei_pieusb_cmd_get_scanned_lines(scanner->device_number, linebuf, lines, lines * bpl, &status); if (status.pieusb_status != PIEUSB_STATUS_GOOD ) { /* Error, return */ free(linebuf); return SANE_STATUS_INVAL; } /* Save raw data */ /* if (fdraw != -1) { wcnt = write(fdraw,linebuf,parameters.lines*bpl); DBG(DBG_info_sane,"Raw written %d\n",wcnt); } */ /* Copy into official buffer * Sometimes the scanner returns too many lines. Take care not to * overflow the buffer. */ lboff = linebuf; switch (scanner->mode.colorFormat) { case SCAN_COLOR_FORMAT_PIXEL: /* The scanner may return lines with 3 colors even though only * one color is actually scanned. Detect this situation and * eliminate the excess samples from the line buffer before * handing it to buffer_put_full_color_line(). */ compress = SANE_FALSE; if (scanner->buffer.colors == 1 && (bpl * scanner->buffer.packing_density / ppl) == (3 * scanner->buffer.packet_size_bytes)) { compress = SANE_TRUE; } for (n = 0; n < lines; n++) { if (compress) { /* Move samples to fill up all unused locations */ int ps = scanner->buffer.packet_size_bytes; for (k = 0; k < scanner->buffer.line_size_packets; k++) { for (i = 0; i < ps; i++) { lboff[ps*k+i] = lboff[3*ps*k+i]; } } } if (sanei_pieusb_buffer_put_full_color_line(&scanner->buffer, lboff, bpl/3) == 0) { /* Error, return */ return SANE_STATUS_INVAL; } lboff += bpl; } break; case SCAN_COLOR_FORMAT_INDEX: /* Indexed data */ for (n = 0; n < lines; n++) { if (sanei_pieusb_buffer_put_single_color_line(&scanner->buffer, *lboff, lboff+2, bpl-2) == 0) { /* Error, return */ return SANE_STATUS_INVAL; } lboff += bpl; } break; default: DBG(DBG_error, "sanei_pieusb_get_scan_data(): store color format %d not implemented\n", scanner->mode.colorFormat); free(linebuf); return SANE_STATUS_INVAL; } free(linebuf); lines_remaining -= lines; /* Note: excess discarded */ DBG(DBG_info_sane, "sanei_pieusb_get_scan_data(): reading lines: remaining %d\n", lines_remaining); } /* if (fdraw != -1) close(fdraw); */ return SANE_STATUS_GOOD; } /** * Wait for scanner to get ready * * loop of test_ready/read_state * * @param scanner * @param device_number, used if scanner == NULL * @return SANE_Status */ SANE_Status sanei_pieusb_wait_ready(Pieusb_Scanner * scanner, SANE_Int device_number) { struct Pieusb_Command_Status status; struct Pieusb_Scanner_State state; time_t start, elapsed; DBG (DBG_info_proc, "sanei_pieusb_wait_ready()\n"); start = time(NULL); if (scanner) device_number = scanner->device_number; for(;;) { sanei_pieusb_cmd_test_unit_ready(device_number, &status); DBG (DBG_info_proc, "-> sanei_pieusb_cmd_test_unit_ready: %d\n", status.pieusb_status); if (status.pieusb_status == PIEUSB_STATUS_GOOD) break; if (status.pieusb_status == PIEUSB_STATUS_IO_ERROR) break; sanei_pieusb_cmd_read_state(device_number, &state, &status); DBG (DBG_info_proc, "-> sanei_pieusb_cmd_read_state: %d\n", status.pieusb_status); if (status.pieusb_status != PIEUSB_STATUS_DEVICE_BUSY) break; sleep(2); elapsed = time(NULL) - start; if (elapsed > 120) { /* 2 minute overall timeout */ DBG (DBG_error, "scanner not ready after 2 minutes\n"); break; } if (elapsed % 2) { DBG (DBG_info, "still waiting for scanner to get ready\n"); } } return sanei_pieusb_convert_status(status.pieusb_status); } SANE_Status sanei_pieusb_analyze_preview(Pieusb_Scanner * scanner) { int k, n; SANE_Parameters params; SANE_Int N; double *norm_histo; double level; DBG(DBG_info, "sanei_pieusb_analyze_preview(): saving preview data\n"); /* Settings */ scanner->preview_done = SANE_TRUE; for (k = 0; k < 4; k++) { scanner->preview_exposure[k] = scanner->settings.exposureTime[k]; scanner->preview_gain[k] = scanner->settings.gain[k]; scanner->preview_offset[k] = scanner->settings.offset[k]; } /* Analyze color planes */ N = scanner->buffer.width * scanner->buffer.height; params.format = SANE_FRAME_GRAY; params.depth = scanner->buffer.depth; params.pixels_per_line = scanner->buffer.width; params.lines = scanner->buffer.height; for (k = 0; k < scanner->buffer.colors; k++) { /* Create histogram for color k */ sanei_ir_create_norm_histogram (¶ms, scanner->buffer.data + k * N, &norm_histo); /* Find 1% and 99% limits */ level = 0; for (n =0; n < HISTOGRAM_SIZE; n++) { level += norm_histo[n]; if (level < 0.01) { scanner->preview_lower_bound[k] = n; } if (level < 0.99) { scanner->preview_upper_bound[k] = n; } } DBG(DBG_info,"sanei_pieusb_analyze_preview(): 1%%-99%% levels for color %d: %d - %d\n", k, scanner->preview_lower_bound[k], scanner->preview_upper_bound[k]); } /* Disable remaining color planes */ for (k = scanner->buffer.colors; k < 4; k++) { scanner->preview_lower_bound[k] = 0; scanner->preview_upper_bound[k] = 0; } return SANE_STATUS_GOOD; } /** * Return actual gain at given gain setting * * @param gain Gain setting (0 - 63) * @return */ static double getGain(int gain) { int k; /* Actually an error, but don't be picky */ if (gain <= 0) { return gains[0]; } /* A gain > 63 is also an error, but don't be picky */ if (gain >= 60) { return (gain-55)*(gains[12]-gains[11])/5 + gains[11]; } /* Interpolate other values */ k = gain/5; /* index of array value just below given gain */ return (gain-5*k)*(gains[k+1]-gains[k])/5 + gains[k]; } static int getGainSetting(double gain) { int k, m; /* Out of bounds */ if (gain < 1.0) { return 0; } if (gain >= gains[12]) { m = 60 + lround((gain-gains[11])/(gains[12]-gains[11])*5); if (m > 63) m = 63; return m; } /* Interpolate the rest */ m = 0; for (k = 0; k <= 11; k++) { if (gains[k] <= gain && gain < gains[k+1]) { m = 5*k + lround((gain-gains[k])/(gains[k+1]-gains[k])*5); } } return m; } /** * Modify gain and exposure times in order to make maximal use of the scan depth. * Each color treated separately, infrared excluded. * * This may be too aggressive => leads to a noisy whitish border instead of the orange. * In a couuple of tries, gain was set to values of 60 and above, which introduces * the noise? * The whitish border is logical since the brightest parts of the negative, the * unexposed borders, are amplified to values near CCD saturation, which is white. * Maybe a uniform gain increase for each color is more appropriate? Somewhere * between 2.5 and 3 seems worthwhile trying, see updateGain2(). * switch (scanner->mode.passes) { case SCAN_ONE_PASS_RGBI: updateGain(scanner,0); updateGain(scanner,1); updateGain(scanner,2); updateGain(scanner,3); break; case SCAN_ONE_PASS_COLOR: updateGain(scanner,0); updateGain(scanner,1); updateGain(scanner,2); break; case SCAN_FILTER_INFRARED: updateGain(scanner,3); break; case SCAN_FILTER_BLUE: updateGain(scanner,2); break; case SCAN_FILTER_GREEN: updateGain(scanner,1); break; case SCAN_FILTER_RED: updateGain(scanner,0); break; case SCAN_FILTER_NEUTRAL: break; } * @param scanner */ /* static void updateGain(Pieusb_Scanner *scanner, int color_index) { double g, dg; DBG(DBG_info_sane,"updateGain(): color %d preview used G=%d Exp=%d\n", color_index, scanner->preview_gain[color_index], scanner->preview_exposure[color_index]); // Additional gain to obtain dg = ((double)scanner->settings.saturationLevel[color_index] / 65536) / ((double)scanner->preview_upper_bound[color_index] / HISTOGRAM_SIZE); DBG(DBG_info_sane,"updateGain(): additional gain %f\n", dg); // Achieve this by modifying gain and exposure // Gain used for preview g = getGain(scanner->preview_gain[color_index]); DBG(DBG_info_sane,"updateGain(): preview had gain %d => %f\n",scanner->preview_gain[color_index],g); // Look up new gain setting g*sqrt(dg) DBG(DBG_info_sane,"updateGain(): optimized gain * %f = %f\n",sqrt(dg),sqrt(dg)*g); scanner->settings.gain[color_index] = getGainSetting(g*sqrt(dg)); DBG(DBG_info_sane,"updateGain(): optimized gain setting %d => %f\n",scanner->settings.gain[color_index],getGain(scanner->settings.gain[color_index])); // Exposure change is straightforward DBG(DBG_info_sane,"updateGain(): remains for exposure %f\n",dg/(getGain(scanner->settings.gain[color_index])/g)); scanner->settings.exposureTime[color_index] = lround( g / getGain(scanner->settings.gain[color_index]) * dg * scanner->preview_exposure[color_index] ); DBG(DBG_info_sane,"updateGain(): new setting G=%d Exp=%d\n", scanner->settings.gain[color_index], scanner->settings.exposureTime[color_index]); } */ static void updateGain2(Pieusb_Scanner *scanner, int color_index, double gain_increase) { double g; DBG(DBG_info,"updateGain2(): color %d preview used G=%d Exp=%d\n", color_index, scanner->settings.gain[color_index], scanner->settings.exposureTime[color_index]); /* Additional gain to obtain */ DBG(DBG_info,"updateGain2(): additional gain %f\n", gain_increase); /* Achieve this by modifying gain and exposure */ /* Gain used for preview */ g = getGain(scanner->settings.gain[color_index]); DBG(DBG_info,"updateGain2(): preview had gain %d => %f\n", scanner->settings.gain[color_index], g); /* Look up new gain setting g*sqrt(dg) */ DBG(DBG_info,"updateGain2(): optimized gain * %f = %f\n", sqrt(gain_increase), sqrt(gain_increase) * g); scanner->settings.gain[color_index] = getGainSetting(g * sqrt(gain_increase)); DBG(DBG_info,"updateGain2(): optimized gain setting %d => %f\n", scanner->settings.gain[color_index], getGain(scanner->settings.gain[color_index])); /* Exposure change is straightforward */ DBG(DBG_info,"updateGain2(): remains for exposure %f\n", gain_increase / (getGain(scanner->settings.gain[color_index]) / g)); scanner->settings.exposureTime[color_index] = lround( g / getGain(scanner->settings.gain[color_index]) * gain_increase * scanner->settings.exposureTime[color_index] ); DBG(DBG_info,"updateGain2(): new setting G=%d Exp=%d\n", scanner->settings.gain[color_index], scanner->settings.exposureTime[color_index]); } sane-backends-1.0.27/backend/pixma_sane_options.h0000664000175000017500000000151613072310420016654 00000000000000/* Automatically generated from pixma_sane.c */ typedef union { SANE_Word w; SANE_Int i; SANE_Bool b; SANE_Fixed f; SANE_String s; void *ptr; } option_value_t; typedef enum { opt_opt_num_opts, opt__group_1, opt_resolution, opt_mode, opt_source, opt_button_controlled, opt__group_2, opt_custom_gamma, opt_gamma_table, opt_gamma, opt__group_3, opt_tl_x, opt_tl_y, opt_br_x, opt_br_y, opt__group_4, opt_button_update, opt_button_1, opt_button_2, opt_original, opt_target, opt_scan_resolution, opt__group_5, opt_threshold, opt_threshold_curve, opt_adf_wait, opt_last } option_t; typedef struct { SANE_Option_Descriptor sod; option_value_t val,def; SANE_Word info; } option_descriptor_t; struct pixma_sane_t; static int build_option_descriptors(struct pixma_sane_t *ss); sane-backends-1.0.27/backend/gt68xx_high.c0000664000175000017500000022661612112021330015122 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov AFE offset/gain setting by David Stevenson Copyright (C) 2002 - 2007 Henning Geinitz Copyright (C) 2009 Stéphane Voltz for sheetfed calibration code. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "gt68xx_high.h" #include "gt68xx_mid.c" #include #include static SANE_Status gt68xx_afe_ccd_auto (GT68xx_Scanner * scanner, GT68xx_Scan_Request * request); static SANE_Status gt68xx_afe_cis_auto (GT68xx_Scanner * scanner); SANE_Status gt68xx_calibrator_new (SANE_Int width, SANE_Int white_level, GT68xx_Calibrator ** cal_return) { GT68xx_Calibrator *cal; SANE_Int i; DBG (4, "gt68xx_calibrator_new: enter: width=%d, white_level=%d\n", width, white_level); *cal_return = 0; if (width <= 0) { DBG (5, "gt68xx_calibrator_new: invalid width=%d\n", width); return SANE_STATUS_INVAL; } cal = (GT68xx_Calibrator *) malloc (sizeof (GT68xx_Calibrator)); if (!cal) { DBG (5, "gt68xx_calibrator_new: no memory for GT68xx_Calibrator\n"); return SANE_STATUS_NO_MEM; } cal->k_white = NULL; cal->k_black = NULL; cal->white_line = NULL; cal->black_line = NULL; cal->width = width; cal->white_level = white_level; cal->white_count = 0; cal->black_count = 0; #ifdef TUNE_CALIBRATOR cal->min_clip_count = cal->max_clip_count = 0; #endif /* TUNE_CALIBRATOR */ cal->k_white = (unsigned int *) malloc (width * sizeof (unsigned int)); cal->k_black = (unsigned int *) malloc (width * sizeof (unsigned int)); cal->white_line = (double *) malloc (width * sizeof (double)); cal->black_line = (double *) malloc (width * sizeof (double)); if (!cal->k_white || !cal->k_black | !cal->white_line || !cal->black_line) { DBG (5, "gt68xx_calibrator_new: no memory for calibration data\n"); gt68xx_calibrator_free (cal); return SANE_STATUS_NO_MEM; } for (i = 0; i < width; ++i) { cal->k_white[i] = 0; cal->k_black[i] = 0; cal->white_line[i] = 0.0; cal->black_line[i] = 0.0; } *cal_return = cal; DBG (5, "gt68xx_calibrator_new: leave: ok\n"); return SANE_STATUS_GOOD; } SANE_Status gt68xx_calibrator_free (GT68xx_Calibrator * cal) { DBG (5, "gt68xx_calibrator_free: enter\n"); if (!cal) { DBG (5, "gt68xx_calibrator_free: cal==NULL\n"); return SANE_STATUS_INVAL; } #ifdef TUNE_CALIBRATOR DBG (4, "gt68xx_calibrator_free: min_clip_count=%d, max_clip_count=%d\n", cal->min_clip_count, cal->max_clip_count); #endif /* TUNE_CALIBRATOR */ if (cal->k_white) { free (cal->k_white); cal->k_white = NULL; } if (cal->k_black) { free (cal->k_black); cal->k_black = NULL; } if (cal->white_line) { free (cal->white_line); cal->white_line = NULL; } if (cal->black_line) { free (cal->black_line); cal->black_line = NULL; } free (cal); DBG (5, "gt68xx_calibrator_free: leave: ok\n"); return SANE_STATUS_GOOD; } SANE_Status gt68xx_calibrator_add_white_line (GT68xx_Calibrator * cal, unsigned int *line) { SANE_Int i; SANE_Int width = cal->width; SANE_Int sum = 0; cal->white_count++; for (i = 0; i < width; ++i) { cal->white_line[i] += line[i]; sum += line[i]; #ifdef SAVE_WHITE_CALIBRATION printf ("%c", line[i] >> 8); #endif } if (sum / width / 256 < 0x50) DBG (1, "gt68xx_calibrator_add_white_line: WARNING: dark calibration line: " "%2d medium white: 0x%02x\n", cal->white_count - 1, sum / width / 256); else DBG (5, "gt68xx_calibrator_add_white_line: line: %2d medium white: 0x%02x\n", cal->white_count - 1, sum / width / 256); return SANE_STATUS_GOOD; } SANE_Status gt68xx_calibrator_eval_white (GT68xx_Calibrator * cal, double factor) { SANE_Int i; SANE_Int width = cal->width; for (i = 0; i < width; ++i) { cal->white_line[i] = cal->white_line[i] / cal->white_count * factor; } return SANE_STATUS_GOOD; } SANE_Status gt68xx_calibrator_add_black_line (GT68xx_Calibrator * cal, unsigned int *line) { SANE_Int i; SANE_Int width = cal->width; SANE_Int sum = 0; cal->black_count++; for (i = 0; i < width; ++i) { cal->black_line[i] += line[i]; sum += line[i]; #ifdef SAVE_BLACK_CALIBRATION printf ("%c", line[i] >> 8); #endif } DBG (5, "gt68xx_calibrator_add_black_line: line: %2d medium black: 0x%02x\n", cal->black_count - 1, sum / width / 256); return SANE_STATUS_GOOD; } SANE_Status gt68xx_calibrator_eval_black (GT68xx_Calibrator * cal, double factor) { SANE_Int i; SANE_Int width = cal->width; for (i = 0; i < width; ++i) { cal->black_line[i] = cal->black_line[i] / cal->black_count - factor; } return SANE_STATUS_GOOD; } SANE_Status gt68xx_calibrator_finish_setup (GT68xx_Calibrator * cal) { #ifdef TUNE_CALIBRATOR double ave_black = 0.0; double ave_diff = 0.0; #endif /* TUNE_CALIBRATOR */ int i; int width = cal->width; unsigned int max_value = 65535; for (i = 0; i < width; ++i) { unsigned int white = cal->white_line[i]; unsigned int black = cal->black_line[i]; unsigned int diff = (white > black) ? white - black : 1; if (diff > max_value) diff = max_value; cal->k_white[i] = diff; cal->k_black[i] = black; #ifdef TUNE_CALIBRATOR ave_black += black; ave_diff += diff; #endif /* TUNE_CALIBRATOR */ } #ifdef TUNE_CALIBRATOR ave_black /= width; ave_diff /= width; DBG (4, "gt68xx_calibrator_finish_setup: ave_black=%f, ave_diff=%f\n", ave_black, ave_diff); #endif /* TUNE_CALIBRATOR */ return SANE_STATUS_GOOD; } SANE_Status gt68xx_calibrator_process_line (GT68xx_Calibrator * cal, unsigned int *line) { int i; int width = cal->width; unsigned int white_level = cal->white_level; for (i = 0; i < width; ++i) { unsigned int src_value = line[i]; unsigned int black = cal->k_black[i]; unsigned int value; if (src_value > black) { value = (src_value - black) * white_level / cal->k_white[i]; if (value > 0xffff) { value = 0xffff; #ifdef TUNE_CALIBRATOR cal->max_clip_count++; #endif /* TUNE_CALIBRATOR */ } } else { value = 0; #ifdef TUNE_CALIBRATOR if (src_value < black) cal->min_clip_count++; #endif /* TUNE_CALIBRATOR */ } line[i] = value; } return SANE_STATUS_GOOD; } SANE_Status gt68xx_scanner_new (GT68xx_Device * dev, GT68xx_Scanner ** scanner_return) { GT68xx_Scanner *scanner; int i; *scanner_return = NULL; scanner = (GT68xx_Scanner *) malloc (sizeof (GT68xx_Scanner)); if (!scanner) { DBG (5, "gt68xx_scanner_new: no memory for GT68xx_Scanner\n"); return SANE_STATUS_NO_MEM; } scanner->dev = dev; scanner->reader = NULL; scanner->cal_gray = NULL; scanner->cal_r = NULL; scanner->cal_g = NULL; scanner->cal_b = NULL; for(i=0;icalibrations[i].dpi = 0; scanner->calibrations[i].red = NULL; scanner->calibrations[i].green = NULL; scanner->calibrations[i].blue = NULL; scanner->calibrations[i].gray = NULL; } *scanner_return = scanner; return SANE_STATUS_GOOD; } static void gt68xx_scanner_free_calibrators (GT68xx_Scanner * scanner) { if (scanner->cal_gray) { gt68xx_calibrator_free (scanner->cal_gray); scanner->cal_gray = NULL; } if (scanner->cal_r) { gt68xx_calibrator_free (scanner->cal_r); scanner->cal_r = NULL; } if (scanner->cal_g) { gt68xx_calibrator_free (scanner->cal_g); scanner->cal_g = NULL; } if (scanner->cal_b) { gt68xx_calibrator_free (scanner->cal_b); scanner->cal_b = NULL; } } SANE_Status gt68xx_scanner_free (GT68xx_Scanner * scanner) { int i; if (!scanner) { DBG (5, "gt68xx_scanner_free: scanner==NULL\n"); return SANE_STATUS_INVAL; } if (scanner->reader) { gt68xx_line_reader_free (scanner->reader); scanner->reader = NULL; } gt68xx_scanner_free_calibrators (scanner); /* free in memory calibration data */ for (i = 0; i < MAX_RESOLUTIONS; i++) { scanner->calibrations[i].dpi = 0; if (scanner->calibrations[i].red != NULL) { gt68xx_calibrator_free (scanner->calibrations[i].red); } if (scanner->calibrations[i].green != NULL) { gt68xx_calibrator_free (scanner->calibrations[i].green); } if (scanner->calibrations[i].blue != NULL) { gt68xx_calibrator_free (scanner->calibrations[i].blue); } if (scanner->calibrations[i].gray != NULL) { gt68xx_calibrator_free (scanner->calibrations[i].gray); } } free (scanner); return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_wait_for_positioning (GT68xx_Scanner * scanner) { SANE_Status status; SANE_Bool moving; SANE_Int status_count = 0; usleep (100000); /* needed by the BP 2400 CU Plus? */ while (SANE_TRUE) { status = gt68xx_device_is_moving (scanner->dev, &moving); if (status == SANE_STATUS_GOOD) { if (!moving) break; } else { if (status_count > 9) { DBG (1, "gt68xx_scanner_wait_for_positioning: error count too high!\n"); return status; } status_count++; DBG(3, "gt68xx_scanner_wait_for_positioning: ignored error\n"); } usleep (100000); } return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_internal_start_scan (GT68xx_Scanner * scanner) { SANE_Status status; SANE_Bool ready; SANE_Int repeat_count; status = gt68xx_scanner_wait_for_positioning (scanner); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_internal_start_scan: gt68xx_scanner_wait_for_positioning error: %s\n", sane_strstatus (status)); return status; } status = gt68xx_device_start_scan (scanner->dev); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_internal_start_scan: gt68xx_device_start_scan error: %s\n", sane_strstatus (status)); return status; } for (repeat_count = 0; repeat_count < 30 * 100; ++repeat_count) { status = gt68xx_device_read_scanned_data (scanner->dev, &ready); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_internal_start_scan: gt68xx_device_read_scanned_data error: %s\n", sane_strstatus (status)); return status; } if (ready) break; usleep (10000); } if (!ready) { DBG (5, "gt68xx_scanner_internal_start_scan: scanner still not ready - giving up\n"); return SANE_STATUS_DEVICE_BUSY; } status = gt68xx_device_read_start (scanner->dev); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_internal_start_scan: gt68xx_device_read_start error: %s\n", sane_strstatus (status)); return status; } return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_start_scan_extended (GT68xx_Scanner * scanner, GT68xx_Scan_Request * request, GT68xx_Scan_Action action, GT68xx_Scan_Parameters * params) { SANE_Status status; GT68xx_AFE_Parameters afe = *scanner->dev->afe; status = gt68xx_scanner_wait_for_positioning (scanner); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_start_scan_extended: gt68xx_scanner_wait_for_positioning error: %s\n", sane_strstatus (status)); return status; } status = gt68xx_device_setup_scan (scanner->dev, request, action, params); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_start_scan_extended: gt68xx_device_setup_scan failed: %s\n", sane_strstatus (status)); return status; } status = gt68xx_line_reader_new (scanner->dev, params, action == SA_SCAN ? SANE_TRUE : SANE_FALSE, &scanner->reader); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_start_scan_extended: gt68xx_line_reader_new failed: %s\n", sane_strstatus (status)); return status; } if (scanner->dev->model->is_cis && !((scanner->dev->model->flags & GT68XX_FLAG_SHEET_FED) && scanner->calibrated == SANE_FALSE)) { status = gt68xx_device_set_exposure_time (scanner->dev, scanner->dev->exposure); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_start_scan_extended: gt68xx_device_set_exposure_time failed: %s\n", sane_strstatus (status)); return status; } } status = gt68xx_device_set_afe (scanner->dev, &afe); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_start_scan_extended: gt68xx_device_set_afe failed: %s\n", sane_strstatus (status)); return status; } status = gt68xx_scanner_internal_start_scan (scanner); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_start_scan_extended: gt68xx_scanner_internal_start_scan failed: %s\n", sane_strstatus (status)); return status; } return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_create_calibrator (GT68xx_Scan_Parameters * params, GT68xx_Calibrator ** cal_return) { return gt68xx_calibrator_new (params->pixel_xs, 65535, cal_return); } static SANE_Status gt68xx_scanner_create_color_calibrators (GT68xx_Scanner * scanner, GT68xx_Scan_Parameters * params) { SANE_Status status; if (!scanner->cal_r) { status = gt68xx_scanner_create_calibrator (params, &scanner->cal_r); if (status != SANE_STATUS_GOOD) return status; } if (!scanner->cal_g) { status = gt68xx_scanner_create_calibrator (params, &scanner->cal_g); if (status != SANE_STATUS_GOOD) return status; } if (!scanner->cal_b) { status = gt68xx_scanner_create_calibrator (params, &scanner->cal_b); if (status != SANE_STATUS_GOOD) return status; } return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_create_gray_calibrators (GT68xx_Scanner * scanner, GT68xx_Scan_Parameters * params) { SANE_Status status; if (!scanner->cal_gray) { status = gt68xx_scanner_create_calibrator (params, &scanner->cal_gray); if (status != SANE_STATUS_GOOD) return status; } return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_calibrate_color_white_line (GT68xx_Scanner * scanner, unsigned int **buffer_pointers) { gt68xx_calibrator_add_white_line (scanner->cal_r, buffer_pointers[0]); gt68xx_calibrator_add_white_line (scanner->cal_g, buffer_pointers[1]); gt68xx_calibrator_add_white_line (scanner->cal_b, buffer_pointers[2]); return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_calibrate_gray_white_line (GT68xx_Scanner * scanner, unsigned int **buffer_pointers) { gt68xx_calibrator_add_white_line (scanner->cal_gray, buffer_pointers[0]); return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_calibrate_color_black_line (GT68xx_Scanner * scanner, unsigned int **buffer_pointers) { gt68xx_calibrator_add_black_line (scanner->cal_r, buffer_pointers[0]); gt68xx_calibrator_add_black_line (scanner->cal_g, buffer_pointers[1]); gt68xx_calibrator_add_black_line (scanner->cal_b, buffer_pointers[2]); return SANE_STATUS_GOOD; } static SANE_Status gt68xx_scanner_calibrate_gray_black_line (GT68xx_Scanner * scanner, unsigned int **buffer_pointers) { gt68xx_calibrator_add_black_line (scanner->cal_gray, buffer_pointers[0]); return SANE_STATUS_GOOD; } SANE_Status gt68xx_scanner_calibrate (GT68xx_Scanner * scanner, GT68xx_Scan_Request * request) { SANE_Status status; GT68xx_Scan_Parameters params; GT68xx_Scan_Request req; SANE_Int i; unsigned int *buffer_pointers[3]; GT68xx_AFE_Parameters *afe = scanner->dev->afe; GT68xx_Exposure_Parameters *exposure = scanner->dev->exposure; memcpy (&req, request, sizeof (req)); gt68xx_scanner_free_calibrators (scanner); if (scanner->auto_afe) { if (scanner->dev->model->is_cis) status = gt68xx_afe_cis_auto (scanner); else status = gt68xx_afe_ccd_auto (scanner, request); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: gt68xx_afe_*_auto failed: %s\n", sane_strstatus (status)); return status; } req.mbs = SANE_FALSE; } else req.mbs = SANE_TRUE; DBG (3, "afe 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", afe->r_offset, afe->r_pga, afe->g_offset, afe->g_pga, afe->b_offset, afe->b_pga); DBG (3, "exposure 0x%02x 0x%02x 0x%02x\n", exposure->r_time, exposure->g_time, exposure->b_time); if (!scanner->calib) return SANE_STATUS_GOOD; req.mds = SANE_TRUE; req.mas = SANE_FALSE; if (scanner->dev->model->is_cis && !(scanner->dev->model->flags & GT68XX_FLAG_CIS_LAMP)) req.color = SANE_TRUE; if (req.use_ta) { req.lamp = SANE_FALSE; status = gt68xx_device_lamp_control (scanner->dev, SANE_FALSE, SANE_TRUE); } else { req.lamp = SANE_TRUE; status = gt68xx_device_lamp_control (scanner->dev, SANE_TRUE, SANE_FALSE); } status = gt68xx_scanner_start_scan_extended (scanner, &req, SA_CALIBRATE, ¶ms); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: gt68xx_scanner_start_scan_extended failed: %s\n", sane_strstatus (status)); return status; } if (params.color) { status = gt68xx_scanner_create_color_calibrators (scanner, ¶ms); } else { status = gt68xx_scanner_create_gray_calibrators (scanner, ¶ms); } #if defined(SAVE_WHITE_CALIBRATION) || defined(SAVE_BLACK_CALIBRATION) printf ("P5\n%d %d\n255\n", params.pixel_xs, params.pixel_ys * 3); #endif for (i = 0; i < params.pixel_ys; ++i) { status = gt68xx_line_reader_read (scanner->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: gt68xx_line_reader_read failed: %s\n", sane_strstatus (status)); return status; } if (params.color) status = gt68xx_scanner_calibrate_color_white_line (scanner, buffer_pointers); else status = gt68xx_scanner_calibrate_gray_white_line (scanner, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: calibration failed: %s\n", sane_strstatus (status)); return status; } } gt68xx_scanner_stop_scan (scanner); if (params.color) { gt68xx_calibrator_eval_white (scanner->cal_r, 1); gt68xx_calibrator_eval_white (scanner->cal_g, 1); gt68xx_calibrator_eval_white (scanner->cal_b, 1); } else { gt68xx_calibrator_eval_white (scanner->cal_gray, 1); } req.mbs = SANE_FALSE; req.mds = SANE_FALSE; req.mas = SANE_FALSE; req.lamp = SANE_FALSE; status = gt68xx_device_lamp_control (scanner->dev, SANE_FALSE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: gt68xx_device_lamp_control failed: %s\n", sane_strstatus (status)); return status; } if (!scanner->dev->model->is_cis || (scanner->dev->model->flags & GT68XX_FLAG_CIS_LAMP)) usleep (500000); status = gt68xx_scanner_start_scan_extended (scanner, &req, SA_CALIBRATE, ¶ms); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: gt68xx_scanner_start_scan_extended failed: %s\n", sane_strstatus (status)); return status; } for (i = 0; i < params.pixel_ys; ++i) { status = gt68xx_line_reader_read (scanner->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: gt68xx_line_reader_read failed: %s\n", sane_strstatus (status)); return status; } if (params.color) status = gt68xx_scanner_calibrate_color_black_line (scanner, buffer_pointers); else status = gt68xx_scanner_calibrate_gray_black_line (scanner, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: calibration failed: %s\n", sane_strstatus (status)); return status; } } gt68xx_scanner_stop_scan (scanner); if (req.use_ta) status = gt68xx_device_lamp_control (scanner->dev, SANE_FALSE, SANE_TRUE); else status = gt68xx_device_lamp_control (scanner->dev, SANE_TRUE, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_calibrate: gt68xx_device_lamp_control failed: %s\n", sane_strstatus (status)); return status; } if (!scanner->dev->model->is_cis) usleep (500000); if (params.color) { gt68xx_calibrator_eval_black (scanner->cal_r, 0.0); gt68xx_calibrator_eval_black (scanner->cal_g, 0.0); gt68xx_calibrator_eval_black (scanner->cal_b, 0.0); gt68xx_calibrator_finish_setup (scanner->cal_r); gt68xx_calibrator_finish_setup (scanner->cal_g); gt68xx_calibrator_finish_setup (scanner->cal_b); } else { gt68xx_calibrator_eval_black (scanner->cal_gray, 0.0); gt68xx_calibrator_finish_setup (scanner->cal_gray); } return SANE_STATUS_GOOD; } SANE_Status gt68xx_scanner_start_scan (GT68xx_Scanner * scanner, GT68xx_Scan_Request * request, GT68xx_Scan_Parameters * params) { request->mbs = SANE_FALSE; /* don't go home before real scan */ request->mds = SANE_TRUE; request->mas = SANE_FALSE; if (request->use_ta) { gt68xx_device_lamp_control (scanner->dev, SANE_FALSE, SANE_TRUE); request->lamp = SANE_FALSE; } else { gt68xx_device_lamp_control (scanner->dev, SANE_TRUE, SANE_FALSE); request->lamp = SANE_TRUE; } if (!scanner->dev->model->is_cis) sleep (2); return gt68xx_scanner_start_scan_extended (scanner, request, SA_SCAN, params); } SANE_Status gt68xx_scanner_read_line (GT68xx_Scanner * scanner, unsigned int **buffer_pointers) { SANE_Status status; status = gt68xx_line_reader_read (scanner->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_scanner_read_line: gt68xx_line_reader_read failed: %s\n", sane_strstatus (status)); return status; } if (scanner->calib) { if (scanner->reader->params.color) { gt68xx_calibrator_process_line (scanner->cal_r, buffer_pointers[0]); gt68xx_calibrator_process_line (scanner->cal_g, buffer_pointers[1]); gt68xx_calibrator_process_line (scanner->cal_b, buffer_pointers[2]); } else { if (scanner->dev->model->is_cis && !(scanner->dev->model->flags & GT68XX_FLAG_CIS_LAMP)) { if (strcmp (scanner->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_BLUE) == 0) gt68xx_calibrator_process_line (scanner->cal_b, buffer_pointers[0]); else if (strcmp (scanner->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_GREEN) == 0) gt68xx_calibrator_process_line (scanner->cal_g, buffer_pointers[0]); else gt68xx_calibrator_process_line (scanner->cal_r, buffer_pointers[0]); } else { gt68xx_calibrator_process_line (scanner->cal_gray, buffer_pointers[0]); } } } return SANE_STATUS_GOOD; } SANE_Status gt68xx_scanner_stop_scan (GT68xx_Scanner * scanner) { gt68xx_line_reader_free (scanner->reader); scanner->reader = NULL; return gt68xx_device_stop_scan (scanner->dev); } /************************************************************************/ /* */ /* AFE offset/gain automatic configuration */ /* */ /************************************************************************/ typedef struct GT68xx_Afe_Values GT68xx_Afe_Values; struct GT68xx_Afe_Values { SANE_Int black; /* minimum black (0-255) */ SANE_Int white; /* maximum white (0-255) */ SANE_Int total_white; /* average white of the complete line (0-65536) */ SANE_Int calwidth; SANE_Int callines; SANE_Int max_width; SANE_Int scan_dpi; SANE_Fixed start_black; SANE_Int offset_direction; SANE_Int coarse_black; SANE_Int coarse_white; }; /************************************************************************/ /* CCD scanners */ /************************************************************************/ /** Calculate average black and maximum white * * This function is used for CCD scanners. The black mark to the left ist used * for the calculation of average black. The remaining calibration strip * is used for searching the segment whose white average is the highest. * * @param values AFE values * @param buffer scanned line */ static void gt68xx_afe_ccd_calc (GT68xx_Afe_Values * values, unsigned int *buffer) { SANE_Int start_black; SANE_Int end_black; SANE_Int start_white; SANE_Int end_white; SANE_Int i; SANE_Int max_black = 0; SANE_Int min_black = 255; SANE_Int max_white = 0; SANE_Int total_white = 0; /* set size of black mark and white segments */ start_black = SANE_UNFIX (values->start_black) * values->scan_dpi / MM_PER_INCH; end_black = start_black + 1.0 * values->scan_dpi / MM_PER_INCH; /* 1 mm */ /* 5mm after mark */ start_white = end_black + 5.0 * values->scan_dpi / MM_PER_INCH; end_white = values->calwidth; DBG (5, "gt68xx_afe_ccd_calc: dpi=%d, start_black=%d, end_black=%d, start_white=%d, end_white=%d\n", values->scan_dpi, start_black, end_black, start_white, end_white); /* calc min and max black value */ for (i = start_black; i < end_black; i++) { if ((SANE_Int) (buffer[i] >> 8) < min_black) min_black = (buffer[i] >> 8); if ((SANE_Int) (buffer[i] >> 8) > max_black) max_black = (buffer[i] >> 8); #ifdef DEBUG_BLACK if ((buffer[i] >> 8) > 15) fprintf (stderr, "+"); else if ((buffer[i] >> 8) < 5) fprintf (stderr, "-"); else fprintf (stderr, "_"); #endif } #ifdef DEBUG_BLACK fprintf (stderr, "\n"); #endif for (i = start_white; i < end_white; ++i) { if ((SANE_Int) (buffer[i] >> 8) > max_white) max_white = (buffer[i] >> 8); total_white += buffer[i]; } values->total_white = total_white / (end_white - start_white); values->black = min_black; values->white = max_white; if (values->white < 50 || values->black > 150 || values->white - values->black < 30 || max_black - min_black > 15) DBG (1, "gt68xx_afe_ccd_calc: WARNING: max_white %3d min_black %3d max_black %3d\n", values->white, values->black, max_black); else DBG (5, "gt68xx_afe_ccd_calc: max_white %3d min_black %3d max_black %3d\n", values->white, values->black, max_black); } static SANE_Bool gt68xx_afe_ccd_adjust_offset_gain (SANE_String_Const color_name, GT68xx_Afe_Values * values, unsigned int *buffer, SANE_Byte * offset, SANE_Byte * pga, SANE_Byte * old_offset, SANE_Byte * old_pga) { SANE_Int black_low = values->coarse_black, black_high = black_low + 10; SANE_Int white_high = values->coarse_white, white_low = white_high - 10; SANE_Bool done = SANE_TRUE; SANE_Byte local_pga = *pga; SANE_Byte local_offset = *offset; gt68xx_afe_ccd_calc (values, buffer); #if 0 /* test all offset values */ local_offset++; done = SANE_FALSE; goto finish; #endif if (values->white > white_high) { if (values->black > black_high) local_offset += values->offset_direction; else if (values->black < black_low) local_pga--; else { local_offset += values->offset_direction; local_pga--; } done = SANE_FALSE; goto finish; } else if (values->white < white_low) { if (values->black < black_low) local_offset -= values->offset_direction; else if (values->black > black_high) local_pga++; else { local_offset -= values->offset_direction; local_pga++; } done = SANE_FALSE; goto finish; } if (values->black > black_high) { if (values->white > white_high) local_offset += values->offset_direction; else if (values->white < white_low) local_pga++; else { local_offset += values->offset_direction; local_pga++; } done = SANE_FALSE; goto finish; } else if (values->black < black_low) { if (values->white < white_low) local_offset -= values->offset_direction; else if (values->white > white_high) local_pga--; else { local_offset -= values->offset_direction; local_pga--; } done = SANE_FALSE; goto finish; } finish: if ((local_pga == *pga) && (local_offset == *offset)) done = SANE_TRUE; if ((local_pga == *old_pga) && (local_offset == *old_offset)) done = SANE_TRUE; *old_pga = *pga; *old_offset = *offset; DBG (4, "%5s white=%3d, black=%3d, offset=%2d, gain=%2d, old offs=%2d, " "old gain=%2d, total_white=%5d %s\n", color_name, values->white, values->black, local_offset, local_pga, *offset, *pga, values->total_white, done ? "DONE " : ""); *pga = local_pga; *offset = local_offset; return done; } /* Wait for lamp to give stable brightness */ static SANE_Status gt68xx_wait_lamp_stable (GT68xx_Scanner * scanner, GT68xx_Scan_Parameters * params, GT68xx_Scan_Request *request, unsigned int *buffer_pointers[3], GT68xx_Afe_Values *values, SANE_Bool dont_move) { SANE_Status status = SANE_STATUS_GOOD; SANE_Int last_white = 0; SANE_Bool first = SANE_TRUE; SANE_Bool message_printed = SANE_FALSE; struct timeval now, start_time; int secs_lamp_on, secs_start; int increase = -5; gettimeofday (&start_time, 0); do { usleep (200000); if (!first && dont_move) { request->mbs = SANE_FALSE; request->mds = SANE_FALSE; } first = SANE_FALSE; /* read line */ status = gt68xx_scanner_start_scan_extended (scanner, request, SA_CALIBRATE_ONE_LINE, params); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_wait_lamp_stable: gt68xx_scanner_start_scan_extended " "failed: %s\n", sane_strstatus (status)); return status; } status = gt68xx_line_reader_read (scanner->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_wait_lamp_stable: gt68xx_line_reader_read failed: %s\n", sane_strstatus (status)); return status; } gt68xx_scanner_stop_scan (scanner); gt68xx_afe_ccd_calc (values, buffer_pointers[0]); DBG (4, "gt68xx_wait_lamp_stable: this white = %d, last white = %d\n", values->total_white, last_white); gettimeofday (&now, 0); secs_lamp_on = now.tv_sec - scanner->lamp_on_time.tv_sec; secs_start = now.tv_sec - start_time.tv_sec; if (!message_printed && secs_start > 5) { DBG (0, "Please wait for lamp warm-up\n"); message_printed = SANE_TRUE; } if (scanner->val[OPT_AUTO_WARMUP].w == SANE_TRUE) { if (scanner->dev->model->flags & GT68XX_FLAG_CIS_LAMP) { if (values->total_white <= (last_white - 20)) increase--; if (values->total_white >= last_white) increase++; if (increase > 0 && (values->total_white <= (last_white + 20)) && values->total_white != 0) break; } else { if ((values->total_white <= (last_white + 20)) && values->total_white != 0) break; /* lamp is warmed up */ } } last_white = values->total_white; } while (secs_lamp_on <= WARMUP_TIME); DBG (3, "gt68xx_wait_lamp_stable: Lamp is stable after %d secs (%d secs total)\n", secs_start, secs_lamp_on); return status; } /** Select best AFE gain and offset parameters. * * This function must be called before the main scan to choose the best values * for the AFE gains and offsets. It performs several one-line scans of the * calibration strip. * * @param scanner Scanner object. * @param orig_request Scan parameters. * * @returns * - #SANE_STATUS_GOOD - gain and offset setting completed successfully * - other error value - failure of some internal function */ static SANE_Status gt68xx_afe_ccd_auto (GT68xx_Scanner * scanner, GT68xx_Scan_Request * orig_request) { SANE_Status status; GT68xx_Scan_Parameters params; GT68xx_Scan_Request request; int i; GT68xx_Afe_Values values; unsigned int *buffer_pointers[3]; GT68xx_AFE_Parameters *afe = scanner->dev->afe, old_afe; SANE_Bool gray_done = SANE_FALSE; SANE_Bool red_done = SANE_FALSE, green_done = SANE_FALSE, blue_done = SANE_FALSE; values.offset_direction = 1; if (scanner->dev->model->flags & GT68XX_FLAG_OFFSET_INV) values.offset_direction = -1; memset (&old_afe, 255, sizeof (old_afe)); request.x0 = SANE_FIX (0.0); request.xs = scanner->dev->model->x_size; request.xdpi = 300; request.ydpi = 300; request.depth = 8; request.color = orig_request->color; /* request.color = SANE_TRUE; */ request.mas = SANE_FALSE; request.mbs = SANE_FALSE; request.mds = SANE_TRUE; request.calculate = SANE_FALSE; request.use_ta = orig_request->use_ta; if (orig_request->use_ta) { gt68xx_device_lamp_control (scanner->dev, SANE_FALSE, SANE_TRUE); request.lamp = SANE_FALSE; } else { gt68xx_device_lamp_control (scanner->dev, SANE_TRUE, SANE_FALSE); request.lamp = SANE_TRUE; } /* read line */ status = gt68xx_scanner_start_scan_extended (scanner, &request, SA_CALIBRATE_ONE_LINE, ¶ms); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_afe_ccd_auto: gt68xx_scanner_start_scan_extended failed: %s\n", sane_strstatus (status)); return status; } values.scan_dpi = params.xdpi; values.calwidth = params.pixel_xs; values.max_width = (params.pixel_xs * scanner->dev->model->optical_xdpi) / params.xdpi; if (orig_request->use_ta) values.start_black = SANE_FIX (20.0); else values.start_black = scanner->dev->model->x_offset_mark; values.coarse_black = 1; values.coarse_white = 254; request.mds = SANE_FALSE; DBG (5, "gt68xx_afe_ccd_auto: scan_dpi=%d, calwidth=%d, max_width=%d, " "start_black=%.1f mm\n", values.scan_dpi, values.calwidth, values.max_width, SANE_UNFIX (values.start_black)); status = gt68xx_line_reader_read (scanner->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_afe_ccd_auto: gt68xx_line_reader_read failed: %s\n", sane_strstatus (status)); return status; } gt68xx_scanner_stop_scan (scanner); status = gt68xx_wait_lamp_stable (scanner, ¶ms, &request, buffer_pointers, &values, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_afe_ccd_auto: gt68xx_wait_lamp_stable failed %s\n", sane_strstatus (status)); return status; } i = 0; do { i++; /* read line */ status = gt68xx_scanner_start_scan_extended (scanner, &request, SA_CALIBRATE_ONE_LINE, ¶ms); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_afe_ccd_auto: gt68xx_scanner_start_scan_extended failed: %s\n", sane_strstatus (status)); return status; } status = gt68xx_line_reader_read (scanner->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (3, "gt68xx_afe_ccd_auto: gt68xx_line_reader_read failed: %s\n", sane_strstatus (status)); return status; } if (params.color) { /* red */ if (!red_done) red_done = gt68xx_afe_ccd_adjust_offset_gain ("red", &values, buffer_pointers[0], &afe->r_offset, &afe->r_pga, &old_afe.r_offset, &old_afe.r_pga); /* green */ if (!green_done) green_done = gt68xx_afe_ccd_adjust_offset_gain ("green", &values, buffer_pointers[1], &afe->g_offset, &afe->g_pga, &old_afe.g_offset, &old_afe.g_pga); /* blue */ if (!blue_done) blue_done = gt68xx_afe_ccd_adjust_offset_gain ("blue", &values, buffer_pointers[2], &afe->b_offset, &afe->b_pga, &old_afe.b_offset, &old_afe.b_pga); } else { if (strcmp (scanner->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_BLUE) == 0) { gray_done = gt68xx_afe_ccd_adjust_offset_gain ("gray", &values, buffer_pointers[0], &afe->b_offset, &afe->b_pga, &old_afe.b_offset, &old_afe.b_pga); } else if (strcmp (scanner->val[OPT_GRAY_MODE_COLOR].s, GT68XX_COLOR_GREEN) == 0) { gray_done = gt68xx_afe_ccd_adjust_offset_gain ("gray", &values, buffer_pointers[0], &afe->g_offset, &afe->g_pga, &old_afe.g_offset, &old_afe.g_pga); afe->r_offset = afe->b_offset = 0x20; afe->r_pga = afe->b_pga = 0x18; } else { gray_done = gt68xx_afe_ccd_adjust_offset_gain ("gray", &values, buffer_pointers[0], &afe->r_offset, &afe->r_pga, &old_afe.r_offset, &old_afe.r_pga); } } gt68xx_scanner_stop_scan (scanner); } while (((params.color && (!red_done || !green_done || !blue_done)) || (!params.color && !gray_done)) && i < 100); return status; } /************************************************************************/ /* CIS scanners */ /************************************************************************/ static void gt68xx_afe_cis_calc_black (GT68xx_Afe_Values * values, unsigned int *black_buffer) { SANE_Int start_black; SANE_Int end_black; SANE_Int i, j; SANE_Int min_black = 255; SANE_Int average = 0; start_black = 0; end_black = values->calwidth; /* find min average black value */ for (i = start_black; i < end_black; ++i) { SANE_Int avg_black = 0; for (j = 0; j < values->callines; j++) avg_black += (*(black_buffer + i + j * values->calwidth) >> 8); avg_black /= values->callines; average += avg_black; if (avg_black < min_black) min_black = avg_black; } values->black = min_black; average /= (end_black - start_black); DBG (5, "gt68xx_afe_cis_calc_black: min_black=0x%02x, average_black=0x%02x\n", values->black, average); } static void gt68xx_afe_cis_calc_white (GT68xx_Afe_Values * values, unsigned int *white_buffer) { SANE_Int start_white; SANE_Int end_white; SANE_Int i, j; SANE_Int max_white = 0; start_white = 0; end_white = values->calwidth; values->total_white = 0; /* find max average white value */ for (i = start_white; i < end_white; ++i) { SANE_Int avg_white = 0; for (j = 0; j < values->callines; j++) { avg_white += (*(white_buffer + i + j * values->calwidth) >> 8); values->total_white += (*(white_buffer + i + j * values->calwidth)); } avg_white /= values->callines; if (avg_white > max_white) max_white = avg_white; } values->white = max_white; values->total_white /= (values->callines * (end_white - start_white)); DBG (5, "gt68xx_afe_cis_calc_white: max_white=0x%02x, average_white=0x%02x\n", values->white, values->total_white >> 8); } static SANE_Bool gt68xx_afe_cis_adjust_gain_offset (SANE_String_Const color_name, GT68xx_Afe_Values * values, unsigned int *black_buffer, unsigned int *white_buffer, GT68xx_AFE_Parameters * afe, GT68xx_AFE_Parameters * old_afe) { SANE_Byte *offset, *old_offset, *gain, *old_gain; SANE_Int o, g; SANE_Int black_low = values->coarse_black, black_high = black_low + 10; SANE_Int white_high = values->coarse_white, white_low = white_high - 10; SANE_Bool done = SANE_TRUE; gt68xx_afe_cis_calc_black (values, black_buffer); gt68xx_afe_cis_calc_white (values, white_buffer); if (strcmp (color_name, "red") == 0) { offset = &(afe->r_offset); old_offset = &old_afe->r_offset; gain = &afe->r_pga; old_gain = &old_afe->r_pga; } else if (strcmp (color_name, "green") == 0) { offset = &afe->g_offset; old_offset = &old_afe->g_offset; gain = &afe->g_pga; old_gain = &old_afe->g_pga; } else { offset = &afe->b_offset; old_offset = &old_afe->b_offset; gain = &afe->b_pga; old_gain = &old_afe->b_pga; } o = *offset; g = *gain; if (values->white > white_high) { if (values->black > black_high) o -= values->offset_direction; else if (values->black < black_low) g--; else { o -= values->offset_direction; g--; } done = SANE_FALSE; goto finish; } else if (values->white < white_low) { if (values->black < black_low) o += values->offset_direction; else if (values->black > black_high) g++; else { o += values->offset_direction; g++; } done = SANE_FALSE; goto finish; } if (values->black > black_high) { if (values->white > white_high) o -= values->offset_direction; else if (values->white < white_low) g++; else { o -= values->offset_direction; g++; } done = SANE_FALSE; goto finish; } else if (values->black < black_low) { if (values->white < white_low) o += values->offset_direction; else if (values->white > white_high) g--; else { o += values->offset_direction; g--; } done = SANE_FALSE; goto finish; } finish: if (g < 0) g = 0; if (g > 48) g = 48; if (o < 0) o = 0; if (o > 64) o = 64; if ((g == *gain) && (o == *offset)) done = SANE_TRUE; if ((g == *old_gain) && (o == *old_offset)) done = SANE_TRUE; *old_gain = *gain; *old_offset = *offset; DBG (4, "%5s white=%3d, black=%3d, offset=0x%02X, gain=0x%02X, old offs=0x%02X, " "old gain=0x%02X, total_white=%5d %s\n", color_name, values->white, values->black, o, g, *offset, *gain, values->total_white, done ? "DONE " : ""); *gain = g; *offset = o; return done; } static SANE_Bool gt68xx_afe_cis_adjust_exposure (SANE_String_Const color_name, GT68xx_Afe_Values * values, unsigned int *white_buffer, SANE_Int border, SANE_Int * exposure_time) { SANE_Int exposure_change = 0; gt68xx_afe_cis_calc_white (values, white_buffer); if (values->white < border) { exposure_change = ((border - values->white) * 1); (*exposure_time) += exposure_change; DBG (4, "%5s: white = %3d, total_white=%5d (exposure too low) --> exposure += %d (=0x%03x)\n", color_name, values->white, values->total_white, exposure_change, *exposure_time); return SANE_FALSE; } else if (values->white > border + 5) { exposure_change = -((values->white - (border + 5)) * 1); (*exposure_time) += exposure_change; DBG (4, "%5s: white = %3d, total_white=%5d (exposure too high) --> exposure -= %d (=0x%03x)\n", color_name, values->white, values->total_white, exposure_change, *exposure_time); return SANE_FALSE; } else { DBG (4, "%5s: white = %3d, total_white=%5d (exposure ok=0x%03x)\n", color_name, values->white, values->total_white, *exposure_time); } return SANE_TRUE; } static SANE_Status gt68xx_afe_cis_read_lines (GT68xx_Afe_Values * values, GT68xx_Scanner * scanner, SANE_Bool lamp, SANE_Bool first, unsigned int *r_buffer, unsigned int *g_buffer, unsigned int *b_buffer) { SANE_Status status; int line; unsigned int *buffer_pointers[3]; GT68xx_Scan_Request request; GT68xx_Scan_Parameters params; request.x0 = SANE_FIX (0.0); request.xs = scanner->dev->model->x_size; request.xdpi = 300; request.ydpi = 300; request.depth = 8; request.color = SANE_TRUE; request.mas = SANE_FALSE; request.calculate = SANE_FALSE; request.use_ta = SANE_FALSE; if (first) /* go to start position */ { request.mbs = SANE_TRUE; request.mds = SANE_TRUE; } else { request.mbs = SANE_FALSE; request.mds = SANE_FALSE; } request.lamp = lamp; if (!r_buffer) /* First, set the size parameters */ { request.calculate = SANE_TRUE; RIE (gt68xx_device_setup_scan (scanner->dev, &request, SA_CALIBRATE_ONE_LINE, ¶ms)); values->scan_dpi = params.xdpi; values->calwidth = params.pixel_xs; values->callines = params.pixel_ys; values->start_black = scanner->dev->model->x_offset_mark; return SANE_STATUS_GOOD; } if (first && (scanner->dev->model->flags & GT68XX_FLAG_CIS_LAMP)) { if (request.use_ta) { gt68xx_device_lamp_control (scanner->dev, SANE_FALSE, SANE_TRUE); request.lamp = SANE_FALSE; } else { gt68xx_device_lamp_control (scanner->dev, SANE_TRUE, SANE_FALSE); request.lamp = SANE_TRUE; } status = gt68xx_wait_lamp_stable (scanner, ¶ms, &request, buffer_pointers, values, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_afe_cis_read_lines: gt68xx_wait_lamp_stable failed %s\n", sane_strstatus (status)); return status; } request.mbs = SANE_FALSE; request.mds = SANE_FALSE; } status = gt68xx_scanner_start_scan_extended (scanner, &request, SA_CALIBRATE_ONE_LINE, ¶ms); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_afe_cis_read_lines: gt68xx_scanner_start_scan_extended failed: %s\n", sane_strstatus (status)); return status; } values->scan_dpi = params.xdpi; values->calwidth = params.pixel_xs; values->callines = params.pixel_ys; values->coarse_black = 2; values->coarse_white = 253; if (r_buffer && g_buffer && b_buffer) for (line = 0; line < values->callines; line++) { status = gt68xx_line_reader_read (scanner->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_afe_cis_read_lines: gt68xx_line_reader_read failed: %s\n", sane_strstatus (status)); return status; } memcpy (r_buffer + values->calwidth * line, buffer_pointers[0], values->calwidth * sizeof (unsigned int)); memcpy (g_buffer + values->calwidth * line, buffer_pointers[1], values->calwidth * sizeof (unsigned int)); memcpy (b_buffer + values->calwidth * line, buffer_pointers[2], values->calwidth * sizeof (unsigned int)); } status = gt68xx_scanner_stop_scan (scanner); if (status != SANE_STATUS_GOOD) { DBG (5, "gt68xx_afe_cis_read_lines: gt68xx_scanner_stop_scan failed: %s\n", sane_strstatus (status)); return status; } return SANE_STATUS_GOOD; } static SANE_Status gt68xx_afe_cis_auto (GT68xx_Scanner * scanner) { SANE_Status status; int total_count, exposure_count; GT68xx_Afe_Values values; GT68xx_AFE_Parameters *afe = scanner->dev->afe, old_afe; GT68xx_Exposure_Parameters *exposure = scanner->dev->exposure; SANE_Int red_done, green_done, blue_done; SANE_Bool first = SANE_TRUE; unsigned int *r_gbuffer = 0, *g_gbuffer = 0, *b_gbuffer = 0; unsigned int *r_obuffer = 0, *g_obuffer = 0, *b_obuffer = 0; DBG (5, "gt68xx_afe_cis_auto: start\n"); memset (&old_afe, 255, sizeof (old_afe)); /* Start with the preset exposure settings */ memcpy (scanner->dev->exposure, &scanner->dev->model->exposure, sizeof (*scanner->dev->exposure)); RIE (gt68xx_afe_cis_read_lines (&values, scanner, SANE_FALSE, SANE_FALSE, r_gbuffer, g_gbuffer, b_gbuffer)); r_gbuffer = malloc (values.calwidth * values.callines * sizeof (unsigned int)); g_gbuffer = malloc (values.calwidth * values.callines * sizeof (unsigned int)); b_gbuffer = malloc (values.calwidth * values.callines * sizeof (unsigned int)); r_obuffer = malloc (values.calwidth * values.callines * sizeof (unsigned int)); g_obuffer = malloc (values.calwidth * values.callines * sizeof (unsigned int)); b_obuffer = malloc (values.calwidth * values.callines * sizeof (unsigned int)); if (!r_gbuffer || !g_gbuffer || !b_gbuffer || !r_obuffer || !g_obuffer || !b_obuffer) return SANE_STATUS_NO_MEM; total_count = 0; red_done = green_done = blue_done = SANE_FALSE; old_afe.r_offset = old_afe.g_offset = old_afe.b_offset = 255; old_afe.r_pga = old_afe.g_pga = old_afe.b_pga = 255; do { values.offset_direction = 1; if (scanner->dev->model->flags & GT68XX_FLAG_OFFSET_INV) values.offset_direction = -1; RIE (gt68xx_afe_cis_read_lines (&values, scanner, SANE_FALSE, first, r_obuffer, g_obuffer, b_obuffer)); RIE (gt68xx_afe_cis_read_lines (&values, scanner, SANE_TRUE, SANE_FALSE, r_gbuffer, g_gbuffer, b_gbuffer)); if (!red_done) red_done = gt68xx_afe_cis_adjust_gain_offset ("red", &values, r_obuffer, r_gbuffer, afe, &old_afe); if (!green_done) green_done = gt68xx_afe_cis_adjust_gain_offset ("green", &values, g_obuffer, g_gbuffer, afe, &old_afe); if (!blue_done) blue_done = gt68xx_afe_cis_adjust_gain_offset ("blue", &values, b_obuffer, b_gbuffer, afe, &old_afe); total_count++; first = SANE_FALSE; } while (total_count < 100 && (!red_done || !green_done || !blue_done)); if (!red_done || !green_done || !blue_done) DBG (0, "gt68xx_afe_cis_auto: setting AFE reached limit\n"); /* Exposure time */ exposure_count = 0; red_done = green_done = blue_done = SANE_FALSE; do { /* read white line */ RIE (gt68xx_afe_cis_read_lines (&values, scanner, SANE_TRUE, SANE_FALSE, r_gbuffer, g_gbuffer, b_gbuffer)); if (!red_done) red_done = gt68xx_afe_cis_adjust_exposure ("red", &values, r_gbuffer, 245, &exposure->r_time); if (!green_done) green_done = gt68xx_afe_cis_adjust_exposure ("green", &values, g_gbuffer, 245, &exposure->g_time); if (!blue_done) blue_done = gt68xx_afe_cis_adjust_exposure ("blue", &values, b_gbuffer, 245, &exposure->b_time); exposure_count++; total_count++; } while ((!red_done || !green_done || !blue_done) && exposure_count < 50); if (!red_done || !green_done || !blue_done) DBG (0, "gt68xx_afe_cis_auto: setting exposure reached limit\n"); /* store afe calibration when needed */ if(scanner->dev->model->flags & GT68XX_FLAG_HAS_CALIBRATE) { memcpy(&(scanner->afe_params), afe, sizeof(GT68xx_AFE_Parameters)); scanner->exposure_params.r_time=exposure->r_time; scanner->exposure_params.g_time=exposure->g_time; scanner->exposure_params.b_time=exposure->b_time; } free (r_gbuffer); free (g_gbuffer); free (b_gbuffer); free (r_obuffer); free (g_obuffer); free (b_obuffer); DBG (4, "gt68xx_afe_cis_auto: total_count: %d\n", total_count); return SANE_STATUS_GOOD; } /** @brief create and copy calibrator * Creates a calibrator of the given width and copy data from reference * to initialize it * @param calibator pointer to the calibrator to create * @param reference calibrator with reference data to copy * @param width the width in pixels of the calibrator * @param offset offset in pixels when copying data from reference * @return SANE_STATUS_GOOD and a filled calibrator if enough memory */ static SANE_Status gt68xx_calibrator_create_copy (GT68xx_Calibrator ** calibrator, GT68xx_Calibrator * reference, int width, int offset) { SANE_Status status; int i; if (reference == NULL) { DBG (1, "gt68xx_calibrator_create_copy: NULL reference, skipping...\n"); *calibrator = NULL; return SANE_STATUS_GOOD; } /* check for reference overflow */ if(width+offset>reference->width) { DBG (1, "gt68xx_calibrator_create_copy: required with and offset exceed reference width\n"); return SANE_STATUS_INVAL; } status = gt68xx_calibrator_new (width, 65535, calibrator); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_calibrator_create_copy: failed to create calibrator: %s\n", sane_strstatus (status)); return status; } for(i=0;ik_white[i]=reference->k_white[i+offset]; (*calibrator)->k_black[i]=reference->k_black[i+offset]; (*calibrator)->white_line[i]=reference->white_line[i+offset]; (*calibrator)->black_line[i]=reference->black_line[i+offset]; } return status; } static SANE_Status gt68xx_sheetfed_move_to_scan_area (GT68xx_Scanner * scanner, GT68xx_Scan_Request * request) { SANE_Status status; if (!(scanner->dev->model->flags & GT68XX_FLAG_SHEET_FED) || scanner->dev->model->command_set->move_paper == NULL) return SANE_STATUS_GOOD; /* send move paper command */ RIE (scanner->dev->model->command_set->move_paper (scanner->dev, request)); /* wait until paper is set to the desired position */ return gt68xx_scanner_wait_for_positioning (scanner); } /**< number of consecutive white line to detect a white area */ #define WHITE_LINES 2 /** @brief calibrate sheet fed scanner * This function calibrates sheet fed scanner by scanning a calibration * target (which may be a blank page). It first move to a white area then * does afe and exposure calibration. Then it scans white lines to get data * for shading correction. * @param scanner structure describing the frontend session and the device * @return SANE_STATUS_GOOD is everything goes right, SANE_STATUS_INVAL * otherwise. */ static SANE_Status gt68xx_sheetfed_scanner_calibrate (GT68xx_Scanner * scanner) { SANE_Status status; GT68xx_Scan_Request request; GT68xx_Scan_Parameters params; int count, i, x, y, white; unsigned int *buffer_pointers[3]; #ifdef DEBUG_CALIBRATION FILE *fcal; char title[50]; #endif DBG (3, "gt68xx_sheetfed_scanner_calibrate: start.\n"); /* clear calibration if needed */ gt68xx_scanner_free_calibrators (scanner); for (i = 0; i < MAX_RESOLUTIONS; i++) { if(scanner->calibrations[i].red!=NULL) { gt68xx_calibrator_free (scanner->calibrations[i].red); } if(scanner->calibrations[i].green!=NULL) { gt68xx_calibrator_free (scanner->calibrations[i].green); } if(scanner->calibrations[i].blue!=NULL) { gt68xx_calibrator_free (scanner->calibrations[i].blue); } if(scanner->calibrations[i].gray!=NULL) { gt68xx_calibrator_free (scanner->calibrations[i].gray); } } scanner->calibrated = SANE_FALSE; /* find minimum horizontal resolution */ request.xdpi = 9600; for (i = 0; scanner->dev->model->xdpi_values[i] != 0; i++) { if (scanner->dev->model->xdpi_values[i] < request.xdpi) { request.xdpi = scanner->dev->model->xdpi_values[i]; request.ydpi = scanner->dev->model->xdpi_values[i]; } } /* move to white area SA_CALIBRATE uses its own y0/ys fixed values */ request.x0 = 0; request.y0 = scanner->dev->model->y_offset_calib; request.xs = scanner->dev->model->x_size; request.depth = 8; request.color = SANE_FALSE; request.mbs = SANE_TRUE; request.mds = SANE_TRUE; request.mas = SANE_FALSE; request.lamp = SANE_TRUE; request.calculate = SANE_FALSE; request.use_ta = SANE_FALSE; request.backtrack = SANE_FALSE; request.backtrack_lines = 0; /* skip start of calibration sheet */ status = gt68xx_sheetfed_move_to_scan_area (scanner, &request); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: failed to skip start of calibration sheet %s\n", sane_strstatus (status)); return status; } status = gt68xx_device_lamp_control (scanner->dev, SANE_FALSE, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: gt68xx_device_lamp_control returned %s\n", sane_strstatus (status)); return status; } /* loop until we find a white area to calibrate on */ i = 0; request.y0 = 0; do { /* start scan */ status = gt68xx_scanner_start_scan_extended (scanner, &request, SA_CALIBRATE, ¶ms); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: gt68xx_scanner_start_scan_extended returned %s\n", sane_strstatus (status)); return status; } /* loop until we find WHITE_LINES consecutive white lines or we reach and of area */ white = 0; y = 0; do { status = gt68xx_line_reader_read (scanner->reader, buffer_pointers); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: gt68xx_line_reader_read returned %s\n", sane_strstatus (status)); gt68xx_scanner_stop_scan (scanner); return status; } /* check for white line */ count = 0; for (x = 0; x < params.pixel_xs; x++) { if (((buffer_pointers[0][x] >> 8) & 0xff) > 50) { count++; } } /* line is white if 93% is above black level */ if ((100 * count) / params.pixel_xs < 93) { white = 0; } else { white++; } y++; } while ((white < WHITE_LINES) && (y < params.pixel_ys)); /* end scan */ gt68xx_scanner_stop_scan (scanner); i++; } while (i < 20 && white < WHITE_LINES); /* check if we found a white area */ if (white != WHITE_LINES) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: didn't find a white area\n"); return SANE_STATUS_INVAL; } /* now do calibration */ scanner->auto_afe = SANE_TRUE; scanner->calib = SANE_TRUE; /* loop at each possible xdpi to create calibrators */ i = 0; while (scanner->dev->model->xdpi_values[i] > 0) { request.xdpi = scanner->dev->model->xdpi_values[i]; request.ydpi = scanner->dev->model->xdpi_values[i]; request.x0 = 0; request.y0 = 0; request.xs = scanner->dev->model->x_size; request.color = SANE_FALSE; request.mbs = SANE_FALSE; request.mds = SANE_TRUE; request.mas = SANE_FALSE; request.lamp = SANE_TRUE; request.calculate = SANE_FALSE; request.use_ta = SANE_FALSE; request.backtrack = SANE_FALSE; request.backtrack_lines = 0; /* calibrate in color */ request.color = SANE_TRUE; status = gt68xx_scanner_calibrate (scanner, &request); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: gt68xx_scanner_calibrate returned %s\n", sane_strstatus (status)); return status; } /* since auto afe is done at a fixed resolution, we don't need to * do each each time, once is enough */ scanner->auto_afe = SANE_FALSE; /* allocate and save per dpi calibrators */ scanner->calibrations[i].dpi = request.xdpi; /* recompute params */ request.calculate = SANE_TRUE; gt68xx_device_setup_scan (scanner->dev, &request, SA_SCAN, ¶ms); scanner->calibrations[i].pixel_x0 = params.pixel_x0; status = gt68xx_calibrator_create_copy (&(scanner->calibrations[i].red), scanner->cal_r, scanner->cal_r->width, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: failed to create red calibrator: %s\n", sane_strstatus (status)); return status; } status = gt68xx_calibrator_create_copy (&(scanner->calibrations[i].green), scanner->cal_g, scanner->cal_g->width, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: failed to create green calibrator: %s\n", sane_strstatus (status)); return status; } status = gt68xx_calibrator_create_copy (&(scanner->calibrations[i].blue), scanner->cal_b, scanner->cal_b->width, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: failed to create blue calibrator: %s\n", sane_strstatus (status)); return status; } /* calibrate in gray */ request.color = SANE_FALSE; status = gt68xx_scanner_calibrate (scanner, &request); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: gt68xx_scanner_calibrate returned %s\n", sane_strstatus (status)); return status; } if (scanner->cal_gray) { status = gt68xx_calibrator_create_copy (&(scanner->calibrations[i].gray), scanner->cal_gray, scanner->cal_gray->width, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_sheetfed_scanner_calibrate: failed to create gray calibrator: %s\n", sane_strstatus (status)); return status; } } #ifdef DEBUG_CALIBRATION sprintf (title, "cal-%03d-red.pnm", scanner->calibrations[i].dpi); fcal = fopen (title, "wb"); if (fcal != NULL) { fprintf (fcal, "P5\n%d 1\n255\n", params.pixel_xs); for (x = 0; x < params.pixel_xs; x++) fputc ((scanner->calibrations[i].red->k_white[x] >> 8) & 0xff, fcal); fclose (fcal); } sprintf (title, "cal-%03d-green.pnm", scanner->calibrations[i].dpi); fcal = fopen (title, "wb"); if (fcal != NULL) { fprintf (fcal, "P5\n%d 1\n255\n", params.pixel_xs); for (x = 0; x < params.pixel_xs; x++) fputc ((scanner->calibrations[i].green->k_white[x] >> 8) & 0xff, fcal); fclose (fcal); } sprintf (title, "cal-%03d-blue.pnm", scanner->calibrations[i].dpi); fcal = fopen (title, "wb"); if (fcal != NULL) { fprintf (fcal, "P5\n%d 1\n255\n", params.pixel_xs); for (x = 0; x < params.pixel_xs; x++) fputc ((scanner->calibrations[i].blue->k_white[x] >> 8) & 0xff, fcal); fclose (fcal); } #endif /* next resolution */ i++; } scanner->calibrated = SANE_TRUE; /* eject calibration target from feeder */ gt68xx_device_paperfeed (scanner->dev); /* save calibration to file */ gt68xx_write_calibration (scanner); DBG (3, "gt68xx_sheetfed_scanner_calibrate: end.\n"); return SANE_STATUS_GOOD; } /** @brief assign calibration for scan * This function creates the calibrators and set up afe for the requested * scan. It uses calibration data that has been created by * gt68xx_sheetfed_scanner_calibrate. * @param scanner structure describing the frontend session and the device * @return SANE_STATUS_GOOD is everything goes right, SANE_STATUS_INVAL * otherwise. */ static SANE_Status gt68xx_assign_calibration (GT68xx_Scanner * scanner, GT68xx_Scan_Parameters params) { int i, dpi, offset; SANE_Status status = SANE_STATUS_GOOD; DBG (3, "gt68xx_assign_calibration: start.\n"); dpi = params.xdpi; DBG (4, "gt68xx_assign_calibration: searching calibration for %d dpi\n", dpi); /* search matching dpi */ i = 0; while (scanner->calibrations[i].dpi > 0 && scanner->calibrations[i].dpi != dpi) { i++; } /* check if found a match */ if (scanner->calibrations[i].dpi == 0) { DBG (4, "gt68xx_assign_calibration: failed to find calibration for %d dpi\n", dpi); return SANE_STATUS_INVAL; } DBG (4, "gt68xx_assign_calibration: using entry %d for %d dpi\n", i, dpi); DBG (5, "gt68xx_assign_calibration: using scan_parameters: pixel_x0=%d, pixel_xs=%d \n", params.pixel_x0, params.pixel_xs); /* AFE/exposure data copy */ memcpy (scanner->dev->afe, &(scanner->afe_params), sizeof (GT68xx_AFE_Parameters)); scanner->dev->exposure->r_time = scanner->exposure_params.r_time; scanner->dev->exposure->g_time = scanner->exposure_params.g_time; scanner->dev->exposure->b_time = scanner->exposure_params.b_time; /* free calibrators if needed */ gt68xx_scanner_free_calibrators (scanner); /* TODO compute offset based on the x0 value from scan_request */ offset = params.pixel_x0 - scanner->calibrations[i].pixel_x0; /* calibrator allocation and copy */ if (scanner->calibrations[i].red!=NULL) { status = gt68xx_calibrator_create_copy (&(scanner->cal_r), scanner->calibrations[i].red, params.pixel_xs, offset); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_assign_calibration: failed to create calibrator: %s\n", sane_strstatus (status)); return status; } } if (scanner->calibrations[i].green!=NULL) { status = gt68xx_calibrator_create_copy (&(scanner->cal_g), scanner->calibrations[i].green, params.pixel_xs, offset); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_assign_calibration: failed to create calibrator: %s\n", sane_strstatus (status)); return status; } } if (scanner->calibrations[i].blue!=NULL) { status = gt68xx_calibrator_create_copy (&(scanner->cal_b), scanner->calibrations[i].blue, params.pixel_xs, offset); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_assign_calibration: failed to create calibrator: %s\n", sane_strstatus (status)); return status; } } if (scanner->calibrations[i].gray!=NULL) { status = gt68xx_calibrator_create_copy (&(scanner->cal_gray), scanner->calibrations[i].gray, params.pixel_xs, offset); if (status != SANE_STATUS_GOOD) { DBG (1, "gt68xx_assign_calibration: failed to create calibrator: %s\n", sane_strstatus (status)); return status; } } DBG (3, "gt68xx_assign_calibration: end.\n"); return status; } static char *gt68xx_calibration_file(GT68xx_Scanner * scanner) { char *ptr=NULL; char tmp_str[PATH_MAX]; ptr=getenv("HOME"); if(ptr!=NULL) { sprintf (tmp_str, "%s/.sane/gt68xx-%s.cal", ptr, scanner->dev->model->name); } else { ptr=getenv("TMPDIR"); if(ptr!=NULL) { sprintf (tmp_str, "%s/gt68xx-%s.cal", ptr, scanner->dev->model->name); } else { sprintf (tmp_str, "/tmp/gt68xx-%s.cal", scanner->dev->model->name); } } DBG(5,"gt68xx_calibration_file: using >%s< for calibration file name\n",tmp_str); return strdup(tmp_str); } static SANE_Status gt68xx_clear_calibration (GT68xx_Scanner * scanner) { char *fname; int i; if (scanner->calibrated == SANE_FALSE) return SANE_STATUS_GOOD; /* clear file */ fname = gt68xx_calibration_file (scanner); unlink (fname); free (fname); /* free calibrators */ for (i = 0; i < MAX_RESOLUTIONS && scanner->calibrations[i].dpi > 0; i++) { scanner->calibrations[i].dpi = 0; if (scanner->calibrations[i].red) gt68xx_calibrator_free (scanner->calibrations[i].red); if (scanner->calibrations[i].green) gt68xx_calibrator_free (scanner->calibrations[i].green); if (scanner->calibrations[i].blue) gt68xx_calibrator_free (scanner->calibrations[i].blue); if (scanner->calibrations[i].gray) gt68xx_calibrator_free (scanner->calibrations[i].gray); } /* reset flags */ scanner->calibrated = SANE_FALSE; scanner->val[OPT_QUALITY_CAL].w = SANE_FALSE; scanner->val[OPT_NEED_CALIBRATION_SW].w = SANE_TRUE; DBG (5, "gt68xx_clear_calibration: done\n"); return SANE_STATUS_GOOD; } static SANE_Status gt68xx_write_calibration (GT68xx_Scanner * scanner) { char *fname; FILE *fcal; int i; SANE_Int nullwidth = 0; if (scanner->calibrated == SANE_FALSE) { return SANE_STATUS_GOOD; } /* open file */ fname = gt68xx_calibration_file (scanner); fcal = fopen (fname, "wb"); free (fname); if (fcal == NULL) { DBG (1, "gt68xx_write_calibration: failed to open calibration file for writing %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } /* TODO we save check endianness and word alignment in case of a home * directory used trough different archs */ fwrite (&(scanner->afe_params), sizeof (GT68xx_AFE_Parameters), 1, fcal); fwrite (&(scanner->exposure_params), sizeof (GT68xx_Exposure_Parameters), 1, fcal); for (i = 0; i < MAX_RESOLUTIONS && scanner->calibrations[i].dpi > 0; i++) { DBG (1, "gt68xx_write_calibration: saving %d dpi calibration\n", scanner->calibrations[i].dpi); fwrite (&(scanner->calibrations[i].dpi), sizeof (SANE_Int), 1, fcal); fwrite (&(scanner->calibrations[i].pixel_x0), sizeof (SANE_Int), 1, fcal); fwrite (&(scanner->calibrations[i].red->width), sizeof (SANE_Int), 1, fcal); fwrite (&(scanner->calibrations[i].red->white_level), sizeof (SANE_Int), 1, fcal); fwrite (scanner->calibrations[i].red->k_white, sizeof (unsigned int), scanner->calibrations[i].red->width, fcal); fwrite (scanner->calibrations[i].red->k_black, sizeof (unsigned int), scanner->calibrations[i].red->width, fcal); fwrite (scanner->calibrations[i].red->white_line, sizeof (double), scanner->calibrations[i].red->width, fcal); fwrite (scanner->calibrations[i].red->black_line, sizeof (double), scanner->calibrations[i].red->width, fcal); fwrite (&(scanner->calibrations[i].green->width), sizeof (SANE_Int), 1, fcal); fwrite (&(scanner->calibrations[i].green->white_level), sizeof (SANE_Int), 1, fcal); fwrite (scanner->calibrations[i].green->k_white, sizeof (unsigned int), scanner->calibrations[i].green->width, fcal); fwrite (scanner->calibrations[i].green->k_black, sizeof (unsigned int), scanner->calibrations[i].green->width, fcal); fwrite (scanner->calibrations[i].green->white_line, sizeof (double), scanner->calibrations[i].green->width, fcal); fwrite (scanner->calibrations[i].green->black_line, sizeof (double), scanner->calibrations[i].green->width, fcal); fwrite (&(scanner->calibrations[i].blue->width), sizeof (SANE_Int), 1, fcal); fwrite (&(scanner->calibrations[i].blue->white_level), sizeof (SANE_Int), 1, fcal); fwrite (scanner->calibrations[i].blue->k_white, sizeof (unsigned int), scanner->calibrations[i].blue->width, fcal); fwrite (scanner->calibrations[i].blue->k_black, sizeof (unsigned int), scanner->calibrations[i].blue->width, fcal); fwrite (scanner->calibrations[i].blue->white_line, sizeof (double), scanner->calibrations[i].blue->width, fcal); fwrite (scanner->calibrations[i].blue->black_line, sizeof (double), scanner->calibrations[i].blue->width, fcal); if (scanner->calibrations[i].gray != NULL) { fwrite (&(scanner->calibrations[i].gray->width), sizeof (SANE_Int), 1, fcal); fwrite (&(scanner->calibrations[i].gray->white_level), sizeof (SANE_Int), 1, fcal); fwrite (scanner->calibrations[i].gray->k_white, sizeof (unsigned int), scanner->calibrations[i].gray->width, fcal); fwrite (scanner->calibrations[i].gray->k_black, sizeof (unsigned int), scanner->calibrations[i].gray->width, fcal); fwrite (scanner->calibrations[i].gray->white_line, sizeof (double), scanner->calibrations[i].gray->width, fcal); fwrite (scanner->calibrations[i].gray->black_line, sizeof (double), scanner->calibrations[i].gray->width, fcal); } else { fwrite (&nullwidth, sizeof (SANE_Int), 1, fcal); } } DBG (5, "gt68xx_write_calibration: wrote %d calibrations\n", i); fclose (fcal); return SANE_STATUS_GOOD; } static SANE_Status gt68xx_read_calibration (GT68xx_Scanner * scanner) { char *fname; FILE *fcal; int i; SANE_Int width, level; scanner->calibrated = SANE_FALSE; fname = gt68xx_calibration_file (scanner); fcal = fopen (fname, "rb"); free (fname); if (fcal == NULL) { DBG (1, "gt68xx_read_calibration: failed to open calibration file for reading %s\n", strerror (errno)); return SANE_STATUS_IO_ERROR; } /* TODO we should check endiannes and word alignment in case of a home * directory used trough different archs */ /* TODO check for errors */ fread (&(scanner->afe_params), sizeof (GT68xx_AFE_Parameters), 1, fcal); fread (&(scanner->exposure_params), sizeof (GT68xx_Exposure_Parameters), 1, fcal); /* loop on calibrators */ i = 0; fread (&(scanner->calibrations[i].dpi), sizeof (SANE_Int), 1, fcal); while (!feof (fcal) && scanner->calibrations[i].dpi > 0) { fread (&(scanner->calibrations[i].pixel_x0), sizeof (SANE_Int), 1, fcal); fread (&width, sizeof (SANE_Int), 1, fcal); fread (&level, sizeof (SANE_Int), 1, fcal); gt68xx_calibrator_new (width, level, &(scanner->calibrations[i].red)); fread (scanner->calibrations[i].red->k_white, sizeof (unsigned int), width, fcal); fread (scanner->calibrations[i].red->k_black, sizeof (unsigned int), width, fcal); fread (scanner->calibrations[i].red->white_line, sizeof (double), width, fcal); fread (scanner->calibrations[i].red->black_line, sizeof (double), width, fcal); fread (&width, sizeof (SANE_Int), 1, fcal); fread (&level, sizeof (SANE_Int), 1, fcal); gt68xx_calibrator_new (width, level, &(scanner->calibrations[i].green)); fread (scanner->calibrations[i].green->k_white, sizeof (unsigned int), width, fcal); fread (scanner->calibrations[i].green->k_black, sizeof (unsigned int), width, fcal); fread (scanner->calibrations[i].green->white_line, sizeof (double), width, fcal); fread (scanner->calibrations[i].green->black_line, sizeof (double), width, fcal); fread (&width, sizeof (SANE_Int), 1, fcal); fread (&level, sizeof (SANE_Int), 1, fcal); gt68xx_calibrator_new (width, level, &(scanner->calibrations[i].blue)); fread (scanner->calibrations[i].blue->k_white, sizeof (unsigned int), width, fcal); fread (scanner->calibrations[i].blue->k_black, sizeof (unsigned int), width, fcal); fread (scanner->calibrations[i].blue->white_line, sizeof (double), width, fcal); fread (scanner->calibrations[i].blue->black_line, sizeof (double), width, fcal); fread (&width, sizeof (SANE_Int), 1, fcal); if (width > 0) { fread (&level, sizeof (SANE_Int), 1, fcal); gt68xx_calibrator_new (width, level, &(scanner->calibrations[i].gray)); fread (scanner->calibrations[i].gray->k_white, sizeof (unsigned int), width, fcal); fread (scanner->calibrations[i].gray->k_black, sizeof (unsigned int), width, fcal); fread (scanner->calibrations[i].gray->white_line, sizeof (double), width, fcal); fread (scanner->calibrations[i].gray->black_line, sizeof (double), width, fcal); } /* prepare for nex resolution */ i++; fread (&(scanner->calibrations[i].dpi), sizeof (SANE_Int), 1, fcal); } DBG (5, "gt68xx_read_calibration: read %d calibrations\n", i); fclose (fcal); scanner->val[OPT_QUALITY_CAL].w = SANE_TRUE; scanner->val[OPT_NEED_CALIBRATION_SW].w = SANE_FALSE; scanner->calibrated = SANE_TRUE; return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/ricoh.conf.in0000664000175000017500000000003512112021330015150 00000000000000scsi RICOH IS60 /dev/scanner sane-backends-1.0.27/backend/canon_dr.h0000664000175000017500000004503212775312260014556 00000000000000#ifndef CANON_DR_H #define CANON_DR_H /* * Part of SANE - Scanner Access Now Easy. * Please see opening comments in canon_dr.c */ /* ------------------------------------------------------------------------- * This option list has to contain all options for all scanners supported by * this driver. If a certain scanner cannot handle a certain option, there's * still the possibility to say so, later. */ enum scanner_Option { OPT_NUM_OPTS = 0, OPT_STANDARD_GROUP, OPT_SOURCE, /*fb/adf/front/back/duplex*/ OPT_MODE, /*mono/gray/color*/ OPT_RES, /*a range or a list*/ OPT_GEOMETRY_GROUP, OPT_PAGE_WIDTH, OPT_PAGE_HEIGHT, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_THRESHOLD, OPT_RIF, OPT_ADVANCED_GROUP, OPT_COMPRESS, OPT_COMPRESS_ARG, OPT_DF_THICKNESS, OPT_DF_LENGTH, OPT_ROLLERDESKEW, OPT_SWDESKEW, OPT_SWDESPECK, OPT_SWCROP, OPT_SWSKIP, OPT_STAPLEDETECT, OPT_DROPOUT_COLOR_F, OPT_DROPOUT_COLOR_B, OPT_BUFFERMODE, OPT_SIDE, /*sensor group*/ OPT_SENSOR_GROUP, OPT_START, OPT_STOP, OPT_BUTT3, OPT_NEWFILE, OPT_COUNTONLY, OPT_BYPASSMODE, OPT_COUNTER, OPT_ADF_LOADED, OPT_CARD_LOADED, /* must come last: */ NUM_OPTIONS }; struct img_params { int mode; /*color,lineart,etc*/ int source; /*fb,adf front,adf duplex,etc*/ int dpi_x; /*these are in dpi */ int dpi_y; int tl_x; /*these are in 1200dpi units */ int tl_y; int br_x; int br_y; int page_x; int page_y; int width; /*these are in pixels*/ int height; SANE_Frame format; /*SANE_FRAME_**/ int bpp; /* 1,8,24 */ int Bpl; /* in bytes */ int valid_width; /*some machines have black padding*/ int valid_Bpl; /* done yet? */ int eof[2]; /* how far we have read/written */ int bytes_sent[2]; /* total to read/write */ int bytes_tot[2]; /* dumb scanners send extra data */ int skip_lines[2]; }; struct scanner { /* --------------------------------------------------------------------- */ /* immutable values which are set during init of scanner. */ struct scanner *next; char device_name[1024]; /* The name of the device from sanei */ int missing; /* used to mark unplugged scanners */ /* --------------------------------------------------------------------- */ /* immutable values which are set during reading of config file. */ int buffer_size; int connection; /* hardware interface type */ /* --------------------------------------------------------------------- */ /* immutable values which are set during inquiry probing of the scanner. */ /* members in order found in scsi data... */ char vendor_name[9]; /* raw data as returned by SCSI inquiry. */ char model_name[17]; /* raw data as returned by SCSI inquiry. */ char version_name[5]; /* raw data as returned by SCSI inquiry. */ /* --------------------------------------------------------------------- */ /* immutable values which are set during std VPD probing of the scanner. */ /* members in order found in scsi data... */ int basic_x_res; int basic_y_res; int step_x_res; int step_y_res; int max_x_res; int max_y_res; int min_x_res; int min_y_res; int std_res_x[16]; int std_res_y[16]; /* max scan size in pixels converted to 1200dpi units */ int max_x; int max_y; /*FIXME: 4 more unknown values here*/ int can_grayscale; int can_halftone; int can_monochrome; int can_overflow; /* --------------------------------------------------------------------- */ /* immutable values which are hard coded because they are not in vpd */ int brightness_steps; int threshold_steps; int contrast_steps; int ppl_mod; /* modulus of scanline width */ /* the scan size in 1/1200th inches, NOT basic_units or sane units */ int min_x; int min_y; int valid_x; int max_x_fb; int max_y_fb; int can_color; /* actually might be in vpd, but which bit? */ int need_ccal; /* scanner needs software to help with afe calibration */ int need_fcal; /* scanner needs software to help with fine calibration */ int need_fcal_buffer; /* software to apply calibration stored in scanner*/ int ccal_version; /* 0 in most scanners, 3 in newer ones */ int has_counter; int has_rif; int has_adf; int has_flatbed; int has_duplex; int has_back; /* not all duplex scanners can do adf back side only */ int has_card; /* P215 has a card reader instead of fb */ int has_comp_JPEG; int has_buffer; int has_df; int has_df_ultra; int has_btc; int has_ssm; /* older scanners use this set scan mode command */ int has_ssm2; /* newer scanners user this similar command */ int has_ssm_pay_head_len; /* newer scanners put the length twice in ssm */ int can_read_sensors; int can_read_panel; int can_write_panel; int rgb_format; /* meaning unknown */ int padding; /* meaning unknown */ int always_op; /* send object pos between pages */ int invert_tly; /* weird bug in some smaller scanners */ int unknown_byte2; /* weird byte, required, meaning unknown */ int padded_read; /* some machines need extra 12 bytes on reads */ int extra_status; /* some machines need extra status read after cmd */ int fixed_width; /* some machines always scan full width */ int even_Bpl; /* some machines require even bytes per line */ int gray_interlace[2]; /* different models interlace heads differently */ int color_interlace[2]; /* different models interlace colors differently */ int color_inter_by_res[16]; /* and some even change by resolution */ int duplex_interlace; /* different models interlace sides differently */ int jpeg_interlace; /* different models interlace jpeg sides differently */ int duplex_offset; /* number of lines of padding added to front (1/1200)*/ int duplex_offset_side; /* padding added to front or back? */ int sw_lut; /* no hardware brightness/contrast support */ int bg_color; /* needed to fill in after rotation */ int reverse_by_mode[6]; /* mode specific */ /* --------------------------------------------------------------------- */ /* immutable values which are set during serial number probing scanner */ char serial_name[28]; /* 16 char model, ':', 10 byte serial, null */ /* --------------------------------------------------------------------- */ /* struct with pointers to device/vendor/model names, and a type value */ /* used to inform sane frontend about the device */ SANE_Device sane; /* --------------------------------------------------------------------- */ /* changeable SANE_Option structs provide our interface to frontend. */ /* some options require lists of strings or numbers, we keep them here */ /* instead of in global vars so that they can differ for each scanner */ /* long array of option structs */ SANE_Option_Descriptor opt[NUM_OPTIONS]; /*mode group*/ SANE_String_Const mode_list[7]; SANE_String_Const source_list[8]; SANE_Int res_list[17]; SANE_Range res_range; /*geometry group*/ SANE_Range tl_x_range; SANE_Range tl_y_range; SANE_Range br_x_range; SANE_Range br_y_range; SANE_Range paper_x_range; SANE_Range paper_y_range; /*enhancement group*/ SANE_Range brightness_range; SANE_Range contrast_range; SANE_Range threshold_range; /*advanced group*/ SANE_String_Const compress_list[3]; SANE_Range compress_arg_range; SANE_Range swdespeck_range; SANE_Range swskip_range; SANE_String_Const do_color_list[8]; /*sensor group*/ SANE_Range counter_range; /* --------------------------------------------------------------------- */ /* changeable vars to hold user input. modified by SANE_Options above */ /* the user's requested image params */ /* exposed in standard and geometry option groups */ struct img_params u; /*enhancement group*/ int brightness; int contrast; int threshold; int rif; /*advanced group*/ int compress; int compress_arg; int df_length; int df_thickness; int dropout_color[2]; int buffermode; int rollerdeskew; int swdeskew; int swdespeck; int swcrop; int swskip; int stapledetect; /* --------------------------------------------------------------------- */ /* values which are derived from setting the options above */ /* the user never directly modifies these */ /* the scanner image params (what we ask from scanner) */ struct img_params s; /* the intermediate image params (like user, but possible higher depth) */ struct img_params i; /* the brightness/contrast LUT for dumb scanners */ unsigned char lut[256]; /* --------------------------------------------------------------------- */ /* values used by the software enhancment code (deskew, crop, etc) */ SANE_Status deskew_stat; int deskew_vals[2]; double deskew_slope; int crop_vals[4]; /* this is defined in sane spec as a struct containing: SANE_Frame format; SANE_Bool last_frame; SANE_Int lines; SANE_Int depth; ( binary=1, gray=8, color=8 (!24) ) SANE_Int pixels_per_line; SANE_Int bytes_per_line; */ SANE_Parameters s_params; /* --------------------------------------------------------------------- */ /* values which are set by calibration functions */ int c_res; int c_mode; int c_offset[2]; int c_gain[2]; int c_exposure[2][3]; int f_res; int f_mode; unsigned char * f_offset[2]; unsigned char * f_gain[2]; /* --------------------------------------------------------------------- */ /* values which are set by scanning functions to keep track of pages, etc */ int started; int reading; int cancelled; int side; int prev_page; int jpeg_stage; int jpeg_ff_offset; unsigned char * buffers[2]; /* --------------------------------------------------------------------- */ /* values used by the command and data sending functions (scsi/usb) */ int fd; /* The scanner device file descriptor. */ size_t rs_info; /* --------------------------------------------------------------------- */ /* values used to hold hardware or control panel status */ int panel_start; int panel_stop; int panel_butt3; int panel_new_file; int panel_count_only; int panel_bypass_mode; int panel_enable_led; int panel_counter; int sensor_adf_loaded; int sensor_card_loaded; /* values which are used to track the frontend's access to sensors */ char panel_read[OPT_COUNTER - OPT_START + 1]; char sensors_read[OPT_CARD_LOADED - OPT_ADF_LOADED + 1]; }; #define CONNECTION_SCSI 0 /* SCSI interface */ #define CONNECTION_USB 1 /* USB interface */ #define SIDE_FRONT 0 #define SIDE_BACK 1 #define CHAN_RED 0 #define CHAN_GREEN 1 #define CHAN_BLUE 2 #define SOURCE_FLATBED 0 #define SOURCE_ADF_FRONT 1 #define SOURCE_ADF_BACK 2 #define SOURCE_ADF_DUPLEX 3 #define SOURCE_CARD_FRONT 4 #define SOURCE_CARD_BACK 5 #define SOURCE_CARD_DUPLEX 6 static const int dpi_list[] = { 60,75,100,120,150,160,180,200, 240,300,320,400,480,600,800,1200 }; #define DPI_60 0 #define DPI_75 1 #define DPI_100 2 #define DPI_120 3 #define DPI_150 4 #define DPI_160 5 #define DPI_180 6 #define DPI_200 7 #define DPI_240 8 #define DPI_300 9 #define DPI_320 10 #define DPI_400 11 #define DPI_480 12 #define DPI_600 13 #define DPI_800 14 #define DPI_1200 15 #define COMP_NONE WD_cmp_NONE #define COMP_JPEG WD_cmp_JPEG #define JPEG_STAGE_NONE 0 #define JPEG_STAGE_SOF 1 /* these are same as scsi data to make code easier */ #define MODE_LINEART WD_comp_LA #define MODE_HALFTONE WD_comp_HT #define MODE_GRAYSCALE WD_comp_GS #define MODE_COLOR WD_comp_CG enum { COLOR_NONE = 0, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_EN_RED, COLOR_EN_GREEN, COLOR_EN_BLUE }; /* these are same as scsi data to make code easier */ #define COLOR_WHITE 1 #define COLOR_BLACK 2 #define GRAY_INTERLACE_NONE 0 #define GRAY_INTERLACE_2510 1 #define GRAY_INTERLACE_gG 2 #define COLOR_INTERLACE_UNK 0 #define COLOR_INTERLACE_RGB 1 #define COLOR_INTERLACE_BGR 2 #define COLOR_INTERLACE_BRG 3 #define COLOR_INTERLACE_GBR 4 #define COLOR_INTERLACE_RRGGBB 5 #define COLOR_INTERLACE_rRgGbB 6 #define COLOR_INTERLACE_2510 7 #define DUPLEX_INTERLACE_NONE 0 #define DUPLEX_INTERLACE_FfBb 1 #define DUPLEX_INTERLACE_FBfb 2 #define DUPLEX_INTERLACE_2510 3 #define DUPLEX_INTERLACE_fFBb 4 #define JPEG_INTERLACE_ALT 0 #define JPEG_INTERLACE_NONE 1 #define CROP_RELATIVE 0 #define CROP_ABSOLUTE 1 /* ------------------------------------------------------------------------- */ #define MM_PER_UNIT_UNFIX SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0)) #define MM_PER_UNIT_FIX SANE_FIX(SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0))) #define SCANNER_UNIT_TO_FIXED_MM(number) SANE_FIX((number) * MM_PER_UNIT_UNFIX) #define FIXED_MM_TO_SCANNER_UNIT(number) SANE_UNFIX(number) / MM_PER_UNIT_UNFIX #define CANON_DR_CONFIG_FILE "canon_dr.conf" #ifndef PATH_MAX # define PATH_MAX 1024 #endif /* ------------------------------------------------------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle); SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking); SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp); const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info); SANE_Status sane_start (SANE_Handle handle); SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len); void sane_cancel (SANE_Handle h); void sane_close (SANE_Handle h); void sane_exit (void); /* ------------------------------------------------------------------------- */ static SANE_Status attach_one_scsi (const char *name); static SANE_Status attach_one_usb (const char *name); static SANE_Status attach_one (const char *devicename, int connType); static SANE_Status connect_fd (struct scanner *s); static SANE_Status disconnect_fd (struct scanner *s); static SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg); static SANE_Status init_inquire (struct scanner *s); static SANE_Status init_vpd (struct scanner *s); static SANE_Status init_model (struct scanner *s); static SANE_Status init_panel (struct scanner *s); static SANE_Status init_user (struct scanner *s); static SANE_Status init_options (struct scanner *s); static SANE_Status do_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ); static SANE_Status do_scsi_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ); static SANE_Status do_usb_cmd(struct scanner *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ); static SANE_Status do_usb_status(struct scanner *s, int runRS, int shortTime, size_t * extraLength); static SANE_Status do_usb_clear(struct scanner *s, int clear, int runRS); static SANE_Status wait_scanner (struct scanner *s); static SANE_Status object_position (struct scanner *s, int i_load); static SANE_Status ssm_buffer (struct scanner *s); static SANE_Status ssm_do (struct scanner *s); static SANE_Status ssm_df (struct scanner *s); static int get_color_inter(struct scanner *s, int side, int res); static int get_page_width (struct scanner *s); static int get_page_height (struct scanner *s); static SANE_Status set_window (struct scanner *s); static SANE_Status update_params (struct scanner *s, int calib); static SANE_Status update_i_params (struct scanner *s); static SANE_Status clean_params (struct scanner *s); static SANE_Status read_sensors(struct scanner *s, SANE_Int option); static SANE_Status read_panel(struct scanner *s, SANE_Int option); static SANE_Status send_panel(struct scanner *s); static SANE_Status start_scan (struct scanner *s, int type); static SANE_Status check_for_cancel(struct scanner *s); static SANE_Status read_from_scanner(struct scanner *s, int side, int exact); static SANE_Status read_from_scanner_duplex(struct scanner *s, int exact); static SANE_Status copy_simplex(struct scanner *s, unsigned char * buf, int len, int side); static SANE_Status copy_duplex(struct scanner *s, unsigned char * buf, int len); static SANE_Status copy_line(struct scanner *s, unsigned char * buf, int side); static SANE_Status fill_image(struct scanner *s,int side); static int must_downsample (struct scanner *s); static int must_fully_buffer (struct scanner *s); static unsigned char calc_bg_color(struct scanner *s); static SANE_Status buffer_despeck(struct scanner *s, int side); static SANE_Status buffer_deskew(struct scanner *s, int side); static SANE_Status buffer_crop(struct scanner *s, int side); static int buffer_isblank(struct scanner *s, int side); static SANE_Status load_lut (unsigned char * lut, int in_bits, int out_bits, int out_min, int out_max, int slope, int offset); static SANE_Status read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side); static SANE_Status image_buffers (struct scanner *s, int setup); static SANE_Status offset_buffers (struct scanner *s, int setup); static SANE_Status gain_buffers (struct scanner *s, int setup); static SANE_Status calibrate_AFE(struct scanner *s); static SANE_Status calibrate_fine(struct scanner *s); static SANE_Status calibrate_fine_buffer(struct scanner *s); static SANE_Status write_AFE (struct scanner *s); static SANE_Status calibration_scan (struct scanner *s, int); static void hexdump (int level, char *comment, unsigned char *p, int l); static void default_globals (void); static size_t maxStringSize (const SANE_String_Const strings[]); static void rmemcpy(void* dest, const void* src, size_t count, size_t stride); #endif /* CANON_DR_H */ sane-backends-1.0.27/backend/epson2.h0000664000175000017500000003033212775312261014177 00000000000000/* * epson2.h - SANE library for Epson scanners. * * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for original copyrights. * * Copyright (C) 2006 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #ifndef epson2_h #define epson2_h #undef BACKEND_NAME #define BACKEND_NAME epson2 #define DEBUG_NOT_STATIC #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include /* for memset and memcpy */ #include #include "sane/sane.h" #include "sane/sanei_backend.h" #include "sane/sanei_debug.h" #define EPSON2_CONFIG_FILE "epson2.conf" #ifndef PATH_MAX #define PATH_MAX (1024) #endif #ifndef XtNumber #define XtNumber(x) (sizeof(x) / sizeof(x[0])) #define XtOffset(p_type, field) ((size_t)&(((p_type)NULL)->field)) #define XtOffsetOf(s_type, field) XtOffset(s_type*, field) #endif #define NUM_OF_HEX_ELEMENTS (16) /* number of hex numbers per line for data dump */ #define DEVICE_NAME_LEN (16) /* length of device name in extended status */ /* string constants for GUI elements that are not defined SANE-wide */ #define SANE_NAME_GAMMA_CORRECTION "gamma-correction" #define SANE_TITLE_GAMMA_CORRECTION SANE_I18N("Gamma Correction") #define SANE_DESC_GAMMA_CORRECTION SANE_I18N("Selects the gamma correction value from a list of pre-defined devices or the user defined table, which can be downloaded to the scanner") #define SANE_EPSON_FOCUS_NAME "focus-position" #define SANE_EPSON_FOCUS_TITLE SANE_I18N("Focus Position") #define SANE_EPSON_FOCUS_DESC SANE_I18N("Sets the focus position to either the glass or 2.5mm above the glass") #define SANE_EPSON_WAIT_FOR_BUTTON_NAME "wait-for-button" #define SANE_EPSON_WAIT_FOR_BUTTON_TITLE SANE_I18N("Wait for Button") #define SANE_EPSON_WAIT_FOR_BUTTON_DESC SANE_I18N("After sending the scan command, wait until the button on the scanner is pressed to actually start the scan process."); /* misc constants */ #define LINES_SHUFFLE_MAX 17 /* 2 x 8 lines plus 1 */ #define SANE_EPSON_MAX_RETRIES 14 /* warmup max retry */ #define CMD_SIZE_EXT_STATUS 42 /* NOTE: you can find these codes with "man ascii". */ #define STX 0x02 #define ACK 0x06 #define NAK 0x15 #define CAN 0x18 #define ESC 0x1B #define PF 0x19 #define FS 0x1C #define S_ACK "\006" #define S_CAN "\030" /* status bits */ #define STATUS_FER 0x80 /* fatal error */ #define STATUS_NOT_READY 0x40 /* scanner is in use on another interface */ #define STATUS_AREA_END 0x20 /* area end */ #define STATUS_OPTION 0x10 /* option installed */ #define STATUS_EXT_COMMANDS 0x02 /* scanners supports extended commands */ #define STATUS_RESERVED 0x01 /* this should be always 0 */ #define EXT_STATUS_FER 0x80 /* fatal error */ #define EXT_STATUS_FBF 0x40 /* flat bed scanner */ #define EXT_STATUS_ADFT 0x20 /* page type ADF */ #define EXT_STATUS_ADFS 0x10 /* ADF is duplex capable */ #define EXT_STATUS_ADFO 0x08 /* ADF loads from the first sheet (page type only) */ #define EXT_STATUS_LID 0x04 /* lid is open */ #define EXT_STATUS_WU 0x02 /* warming up */ #define EXT_STATUS_PB 0x01 /* scanner has a push button */ #define EXT_STATUS_IST 0x80 /* option detected */ #define EXT_STATUS_EN 0x40 /* option enabled */ #define EXT_STATUS_ERR 0x20 /* other error */ #define EXT_STATUS_PE 0x08 /* no paper */ #define EXT_STATUS_PJ 0x04 /* paper jam */ #define EXT_STATUS_OPN 0x02 /* cover open */ #define EXT_IDTY_CAP1_DLF 0x80 #define EXT_IDTY_CAP1_NOTFBF 0x40 /* not a flat bed scanner */ #define EXT_IDTY_CAP1_ADFT 0x20 /* page type ADF ? */ #define EXT_IDTY_CAP1_ADFS 0x10 /* ADF is duplex capable */ #define EXT_IDTY_CAP1_ADFO 0x08 /* ADF loads from the first sheet (page type only) */ #define EXT_IDTY_CAP1_LID 0x04 /* lid type option ? */ #define EXT_IDTY_CAP1_TPIR 0x02 /* TPU with infrared */ #define EXT_IDTY_CAP1_PB 0x01 /* scanner has a push button */ #define EXT_IDTY_CAP2_AFF 0x04 /* auto form feed */ #define EXT_IDTY_CAP2_DFD 0x08 /* double feed detection */ #define EXT_IDTY_CAP2_ADFAS 0x10 /* ADF with auto scan support */ #define FSF_STATUS_MAIN_FER 0x80 /* system error */ #define FSF_STATUS_MAIN_NR 0x40 /* not ready */ #define FSF_STATUS_MAIN_WU 0x02 /* warming up */ #define FSF_STATUS_MAIN_CWU 0x01 /* warm up can be cancelled (?) */ #define FSF_STATUS_ADF_IST 0x80 /* installed */ #define FSF_STATUS_ADF_EN 0x40 /* enabled */ #define FSF_STATUS_ADF_ERR 0x20 /* system error */ #define FSF_STATUS_ADF_PE 0x08 /* paper empty */ #define FSF_STATUS_ADF_PJ 0x04 /* paper jam */ #define FSF_STATUS_ADF_OPN 0x02 /* cover open */ #define FSF_STATUS_ADF_PAG 0x01 /* duplex */ #define FSF_STATUS_TPU_IST 0x80 /* installed */ #define FSF_STATUS_TPU_EN 0x40 /* enabled */ #define FSF_STATUS_TPU_ERR 0x20 /* system error */ #define FSF_STATUS_TPU_OPN 0x02 /* cover open */ #define FSF_STATUS_MAIN2_ERR 0x20 /* system error */ #define FSF_STATUS_MAIN2_PE 0x08 /* paper empty */ #define FSF_STATUS_MAIN2_PJ 0x04 /* paper jam */ #define FSF_STATUS_MAIN2_OPN 0x02 /* cover open */ #define FSG_STATUS_FER 0x80 #define FSG_STATUS_NOT_READY 0x40 /* in use via other interface */ #define FSG_STATUS_CANCEL_REQ 0x10 /* cancel request from scanner */ #define EPSON_LEVEL_A1 0 #define EPSON_LEVEL_A2 1 #define EPSON_LEVEL_B1 2 #define EPSON_LEVEL_B2 3 #define EPSON_LEVEL_B3 4 #define EPSON_LEVEL_B4 5 #define EPSON_LEVEL_B5 6 #define EPSON_LEVEL_B6 7 #define EPSON_LEVEL_B7 8 #define EPSON_LEVEL_B8 9 #define EPSON_LEVEL_F5 10 #define EPSON_LEVEL_D1 11 #define EPSON_LEVEL_D7 12 #define EPSON_LEVEL_D8 13 /* there is also a function level "A5", which I'm igoring here until somebody can * convince me that this is still needed. The A5 level was for the GT-300, which * was (is) a monochrome only scanner. So if somebody really wants to use this * scanner with SANE get in touch with me and we can work something out - khk */ #define EPSON_LEVEL_DEFAULT EPSON_LEVEL_B3 struct EpsonCmd { char *level; unsigned char request_identity; unsigned char request_identity2; /* new request identity level Dx */ unsigned char request_status; unsigned char request_condition; unsigned char set_color_mode; unsigned char start_scanning; unsigned char set_data_format; unsigned char set_resolution; unsigned char set_zoom; unsigned char set_scan_area; unsigned char set_bright; SANE_Range bright_range; unsigned char set_gamma; unsigned char set_halftoning; unsigned char set_color_correction; unsigned char initialize_scanner; unsigned char set_speed; /* B4 and later */ unsigned char set_lcount; unsigned char mirror_image; /* B5 and later */ unsigned char set_gamma_table; /* B4 and later */ unsigned char set_outline_emphasis; /* B4 and later */ unsigned char set_dither; /* B4 and later */ unsigned char set_color_correction_coefficients; /* B3 and later */ unsigned char request_extended_status; /* get extended status from scanner */ unsigned char control_an_extension; /* for extension control */ unsigned char eject; /* for extension control */ unsigned char feed; unsigned char request_push_button_status; unsigned char control_auto_area_segmentation; unsigned char set_film_type; /* for extension control */ unsigned char set_exposure_time; /* F5 only */ unsigned char set_bay; /* F5 only */ unsigned char set_threshold; unsigned char set_focus_position; /* B8 only */ unsigned char request_focus_position; /* B8 only */ unsigned char request_extended_identity; unsigned char request_scanner_status; }; enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_BIT_DEPTH, OPT_HALFTONE, OPT_DROPOUT, OPT_BRIGHTNESS, OPT_SHARPNESS, OPT_GAMMA_CORRECTION, OPT_COLOR_CORRECTION, OPT_RESOLUTION, OPT_THRESHOLD, OPT_ADVANCED_GROUP, OPT_MIRROR, OPT_AAS, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_WAIT_FOR_BUTTON, OPT_CCT_GROUP, OPT_CCT_MODE, OPT_CCT_PROFILE, OPT_PREVIEW_GROUP, OPT_PREVIEW, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_EQU_GROUP, OPT_SOURCE, OPT_AUTO_EJECT, OPT_FILM_TYPE, OPT_FOCUS, OPT_BAY, OPT_EJECT, OPT_ADF_MODE, NUM_OPTIONS }; typedef enum { /* hardware connection to the scanner */ SANE_EPSON_NODEV, /* default, no HW specified yet */ SANE_EPSON_SCSI, /* SCSI interface */ SANE_EPSON_PIO, /* parallel interface */ SANE_EPSON_USB, /* USB interface */ SANE_EPSON_NET /* network interface */ } Epson_Connection_Type; struct epson_profile { unsigned int model; double cct[4][9]; }; enum { CCTP_REFLECTIVE = 0, CCTP_COLORNEG, CCTP_MONONEG, CCTP_COLORPOS }; struct epson_profile_map { char *name; unsigned int id; }; extern const struct epson_profile epson_cct_profiles[]; extern const struct epson_profile_map epson_cct_models[]; /* hardware description */ struct Epson_Device { struct Epson_Device *next; char *name; char *model; unsigned int model_id; SANE_Device sane; SANE_Int level; SANE_Range dpi_range; SANE_Range *x_range; /* x range w/out extension */ SANE_Range *y_range; /* y range w/out extension */ SANE_Range fbf_x_range; /* flattbed x range */ SANE_Range fbf_y_range; /* flattbed y range */ SANE_Range adf_x_range; /* autom. document feeder x range */ SANE_Range adf_y_range; /* autom. document feeder y range */ SANE_Range tpu_x_range; /* transparency unit x range */ SANE_Range tpu_y_range; /* transparency unit y range */ SANE_Range tpu2_x_range; /* transparency unit 2 x range */ SANE_Range tpu2_y_range; /* transparency unit 2 y range */ Epson_Connection_Type connection; SANE_Int *res_list; /* list of resolutions */ SANE_Int res_list_size; /* number of entries in this list */ SANE_Int last_res; /* last selected resolution */ SANE_Int last_res_preview; /* last selected preview resolution */ SANE_Word *resolution_list; /* for display purposes we store a second copy */ SANE_Bool extension; /* extension is installed */ SANE_Int use_extension; /* use the installed extension */ SANE_Bool TPU; /* TPU is installed */ SANE_Bool TPU2; /* TPU2 is installed */ SANE_Bool ADF; /* ADF is installed */ SANE_Bool duplex; /* does the ADF handle duplex scanning */ SANE_Bool focusSupport; /* does this scanner have support for "set focus position" ? */ SANE_Bool color_shuffle; /* does this scanner need color shuffling */ SANE_Int maxDepth; /* max. color depth */ SANE_Int *depth_list; SANE_Int optical_res; /* optical resolution */ SANE_Int max_line_distance; SANE_Bool need_double_vertical; SANE_Bool need_color_reorder; SANE_Bool need_reset_on_source_change; SANE_Bool wait_for_button; /* do we have to wait until the scanner button is pressed? */ SANE_Bool extended_commands; struct EpsonCmd *cmd; const struct epson_profile *cct_profile; }; typedef struct Epson_Device Epson_Device; /* an instance of a scanner */ struct Epson_Scanner { struct Epson_Scanner *next; struct Epson_Device *hw; int fd; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; SANE_Bool block; SANE_Bool eof; SANE_Byte *buf, *end, *ptr; SANE_Bool canceling; SANE_Word gamma_table[3][256]; SANE_Word cct_table[9]; SANE_Int retry_count; /* buffer lines for color shuffling */ SANE_Byte *line_buffer[LINES_SHUFFLE_MAX]; SANE_Int color_shuffle_line; /* current line number for color shuffling */ SANE_Int line_distance; /* current line distance */ SANE_Int current_output_line; /* line counter when color shuffling */ SANE_Int lines_written; /* debug variable */ SANE_Int left, top, lcount; SANE_Bool focusOnGlass; SANE_Byte currentFocusPosition; /* network buffers */ unsigned char *netbuf, *netptr; size_t netlen; /* extended image data handshaking */ SANE_Int ext_block_len; SANE_Int ext_last_len; SANE_Int ext_blocks; SANE_Int ext_counter; }; typedef struct Epson_Scanner Epson_Scanner; struct mode_param { int color; int flags; int dropout_mask; int depth; }; enum { MODE_BINARY, MODE_GRAY, MODE_COLOR, MODE_INFRARED }; #endif sane-backends-1.0.27/backend/hp-device.h0000664000175000017500000000735012112021330014614 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ #ifndef HP_DEVICE_INCLUDED #define HP_DEVICE_INCLUDED #include "hp.h" enum hp_device_compat_e { HP_COMPAT_PLUS = 1 << 0, /* HP ScanJet Plus */ HP_COMPAT_2C = 1 << 1, HP_COMPAT_2P = 1 << 2, HP_COMPAT_2CX = 1 << 3, HP_COMPAT_4C = 1 << 4, /* also 3c, 6100C */ HP_COMPAT_3P = 1 << 5, HP_COMPAT_4P = 1 << 6, HP_COMPAT_5P = 1 << 7, /* also 4100C, 5100C */ HP_COMPAT_5100C = 1 << 8, /* redundant with 5p */ HP_COMPAT_PS = 1 << 9, /* HP PhotoSmart Photo Scanner */ HP_COMPAT_OJ_1150C = 1 << 10, HP_COMPAT_OJ_1170C = 1 << 11, /* also later OfficeJets */ HP_COMPAT_6200C = 1 << 12, HP_COMPAT_5200C = 1 << 13, HP_COMPAT_6300C = 1 << 14 }; struct hp_device_s { HpData data; HpOptSet options; SANE_Device sanedev; enum hp_device_compat_e compat; }; SANE_Status sanei_hp_device_new (HpDevice * new, const char * devname); const SANE_Device * sanei_hp_device_sanedevice (HpDevice this); void sanei_hp_device_simulate_clear (const char *devname); SANE_Status sanei_hp_device_simulate_set (const char *devname, HpScl scl, int flag); SANE_Status sanei_hp_device_support_get (const char *devname, HpScl scl, int *minval, int *maxval); SANE_Status sanei_hp_device_support_probe (HpScsi scsi); SANE_Status sanei_hp_device_probe_model (enum hp_device_compat_e *compat, HpScsi scsi, int *model_num, const char **model_name); SANE_Status sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi); hp_bool_t sanei_hp_device_compat (HpDevice this, enum hp_device_compat_e c); #endif /* HP_DEVICE_INCLUDED */ sane-backends-1.0.27/backend/pixma_mp750.c0000664000175000017500000006066012775312261015041 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /**************************************************************************** * Credits should go to Martin Schewe (http://pixma.schewe.com) who analysed * the protocol of MP750. ****************************************************************************/ #include "../include/sane/config.h" #include #include #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" /* TODO: remove lines marked with SIM. They are inserted so that I can test the subdriver with the simulator. WY */ #ifdef __GNUC__ # define UNUSED(v) (void) v #else # define UNUSED(v) #endif #define IMAGE_BLOCK_SIZE 0xc000 #define CMDBUF_SIZE 512 #define HAS_PAPER(s) (s[1] == 0) #define IS_WARMING_UP(s) (s[7] != 3) #define IS_CALIBRATED(s) (s[8] == 0xf) #define MP750_PID 0x1706 #define MP760_PID 0x1708 #define MP780_PID 0x1707 enum mp750_state_t { state_idle, state_warmup, state_scanning, state_transfering, state_finished }; enum mp750_cmd_t { cmd_start_session = 0xdb20, cmd_select_source = 0xdd20, cmd_scan_param = 0xde20, cmd_status = 0xf320, cmd_abort_session = 0xef20, cmd_time = 0xeb80, cmd_read_image = 0xd420, cmd_activate = 0xcf60, cmd_calibrate = 0xe920, cmd_error_info = 0xff20 }; typedef struct mp750_t { enum mp750_state_t state; pixma_cmdbuf_t cb; unsigned raw_width, raw_height; uint8_t current_status[12]; uint8_t *buf, *rawimg, *img; /* make new buffer for rgb_to_gray to act on */ uint8_t *imgcol; unsigned line_size; /* need in 2 functions */ unsigned rawimg_left, imgbuf_len, last_block_size, imgbuf_ofs; int shifted_bytes; int stripe_shift; /* for 2400dpi */ unsigned last_block; unsigned monochrome:1; unsigned needs_abort:1; } mp750_t; static void mp750_finish_scan (pixma_t * s); static void check_status (pixma_t * s); static int has_paper (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; return HAS_PAPER (mp->current_status); } static int is_warming_up (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; return IS_WARMING_UP (mp->current_status); } static int is_calibrated (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; return IS_CALIBRATED (mp->current_status); } static void drain_bulk_in (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; while (pixma_read (s->io, mp->buf, IMAGE_BLOCK_SIZE) >= 0); } static int abort_session (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_abort_session); } static int query_status (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_status, 0, 12); error = pixma_exec (s, &mp->cb); if (error >= 0) { memcpy (mp->current_status, data, 12); PDBG (pixma_dbg (3, "Current status: paper=%u cal=%u lamp=%u\n", data[1], data[8], data[7])); } return error; } static int activate (pixma_t * s, uint8_t x) { mp750_t *mp = (mp750_t *) s->subdriver; uint8_t *data = pixma_newcmd (&mp->cb, cmd_activate, 10, 0); data[0] = 1; data[3] = x; return pixma_exec (s, &mp->cb); } static int activate_cs (pixma_t * s, uint8_t x) { /*SIM*/ check_status (s); return activate (s, x); } static int start_session (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_start_session); } static int select_source (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; uint8_t *data = pixma_newcmd (&mp->cb, cmd_select_source, 10, 0); data[0] = (s->param->source == PIXMA_SOURCE_ADF) ? 2 : 1; data[1] = 1; return pixma_exec (s, &mp->cb); } static int has_ccd_sensor (pixma_t * s) { return ((s->cfg->cap & PIXMA_CAP_CCD) != 0); } static int is_ccd_grayscale (pixma_t * s) { return (has_ccd_sensor (s) && (s->param->channels == 1)); } /* CCD sensors don't have a Grayscale mode, but use color mode instead */ static unsigned get_cis_ccd_line_size (pixma_t * s) { return (s->param->wx ? s->param->line_size / s->param->w * s->param->wx : s->param->line_size) * ((is_ccd_grayscale (s)) ? 3 : 1); } static int send_scan_param (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; uint8_t *data; data = pixma_newcmd (&mp->cb, cmd_scan_param, 0x2e, 0); pixma_set_be16 (s->param->xdpi | 0x8000, data + 0x04); pixma_set_be16 (s->param->ydpi | 0x8000, data + 0x06); pixma_set_be32 (s->param->x, data + 0x08); pixma_set_be32 (s->param->y, data + 0x0c); pixma_set_be32 (mp->raw_width, data + 0x10); pixma_set_be32 (mp->raw_height, data + 0x14); data[0x18] = 8; /* 8 = color, 4 = grayscale(?) */ /* GH: No, there is no grayscale for CCD devices, Windows shows same */ data[0x19] = s->param->depth * ((is_ccd_grayscale (s)) ? 3 : s->param->channels); /* bits per pixel */ data[0x20] = 0xff; data[0x23] = 0x81; data[0x26] = 0x02; data[0x27] = 0x01; data[0x29] = mp->monochrome ? 0 : 1; return pixma_exec (s, &mp->cb); } static int calibrate (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_calibrate); } static int calibrate_cs (pixma_t * s) { /*SIM*/ check_status (s); return calibrate (s); } static int request_image_block_ex (pixma_t * s, unsigned *size, uint8_t * info, unsigned flag) { mp750_t *mp = (mp750_t *) s->subdriver; int error; memset (mp->cb.buf, 0, 10); pixma_set_be16 (cmd_read_image, mp->cb.buf); mp->cb.buf[7] = *size >> 8; mp->cb.buf[8] = 4 | flag; mp->cb.reslen = pixma_cmd_transaction (s, mp->cb.buf, 10, mp->cb.buf, 6); mp->cb.expected_reslen = 0; error = pixma_check_result (&mp->cb); if (error >= 0) { if (mp->cb.reslen == 6) { *info = mp->cb.buf[2]; *size = pixma_get_be16 (mp->cb.buf + 4); } else { error = PIXMA_EPROTO; } } return error; } static int request_image_block (pixma_t * s, unsigned *size, uint8_t * info) { return request_image_block_ex (s, size, info, 0); } static int request_image_block2 (pixma_t * s, uint8_t * info) { unsigned temp = 0; return request_image_block_ex (s, &temp, info, 0x20); } static int read_image_block (pixma_t * s, uint8_t * data) { int count, temp; count = pixma_read (s->io, data, IMAGE_BLOCK_SIZE); if (count < 0) return count; if (count == IMAGE_BLOCK_SIZE) { int error = pixma_read (s->io, &temp, 0); if (error < 0) { PDBG (pixma_dbg (1, "WARNING: reading zero-length packet failed %d\n", error)); } } return count; } static int read_error_info (pixma_t * s, void *buf, unsigned size) { unsigned len = 16; mp750_t *mp = (mp750_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_error_info, 0, len); error = pixma_exec (s, &mp->cb); if (error >= 0 && buf) { if (len < size) size = len; /* NOTE: I've absolutely no idea what the returned data mean. */ memcpy (buf, data, size); error = len; } return error; } static int send_time (pixma_t * s) { /* TODO: implement send_time() */ UNUSED (s); PDBG (pixma_dbg (3, "send_time() is not yet implemented.\n")); return 0; } static int handle_interrupt (pixma_t * s, int timeout) { int error; uint8_t intr[16]; error = pixma_wait_interrupt (s->io, intr, sizeof (intr), timeout); if (error == PIXMA_ETIMEDOUT) return 0; if (error < 0) return error; if (error != 16) { PDBG (pixma_dbg (1, "WARNING: unexpected interrupt packet length %d\n", error)); return PIXMA_EPROTO; } if (intr[10] & 0x40) send_time (s); if (intr[12] & 0x40) query_status (s); if (intr[15] & 1) s->events = PIXMA_EV_BUTTON2; /* b/w scan */ if (intr[15] & 2) s->events = PIXMA_EV_BUTTON1; /* color scan */ return 1; } static void check_status (pixma_t * s) { while (handle_interrupt (s, 0) > 0); } static int step1 (pixma_t * s) { int error, tmo; error = activate (s, 0); if (error < 0) return error; error = query_status (s); if (error < 0) return error; if (s->param->source == PIXMA_SOURCE_ADF && !has_paper (s)) return PIXMA_ENO_PAPER; error = activate_cs (s, 0); /*SIM*/ if (error < 0) return error; error = activate_cs (s, 0x20); if (error < 0) return error; tmo = 60; error = calibrate_cs (s); while (error == PIXMA_EBUSY && --tmo >= 0) { if (s->cancel) return PIXMA_ECANCELED; PDBG (pixma_dbg (2, "Scanner is busy. Timed out in %d sec.\n", tmo + 1)); pixma_sleep (1000000); error = calibrate_cs (s); } return error; } static void shift_rgb (const uint8_t * src, unsigned pixels, int sr, int sg, int sb, int stripe_shift, int line_size, uint8_t * dst) { unsigned st; for (; pixels != 0; pixels--) { st = (pixels % 2 == 0) ? -2 * stripe_shift * line_size : 0; *(dst++ + sr + st) = *src++; *(dst++ + sg + st) = *src++; *(dst++ + sb + st) = *src++; } } static uint8_t * rgb_to_gray (uint8_t * gptr, const uint8_t * cptr, unsigned pixels, unsigned c) { unsigned i, j, g; /* gptr: destination gray scale buffer */ /* cptr: source color scale buffer */ /* c: 3 for 3-channel single-byte data, 6 for double-byte data */ for (i=0; i < pixels; i++) { for (j = 0, g = 0; j < 3; j++) { g += *cptr++; if (c == 6) g += (*cptr++ << 8); } g /= 3; *gptr++ = g; if (c == 6) *gptr++ = (g >> 8); } return gptr; } static int calc_component_shifting (pixma_t * s) { switch (s->cfg->pid) { case MP760_PID: switch (s->param->ydpi) { case 300: return 3; case 600: return 6; default: return s->param->ydpi / 75; } /* never reached */ break; case MP750_PID: case MP780_PID: default: return 2 * s->param->ydpi / 75; } } static void workaround_first_command (pixma_t * s) { /* FIXME: Send a dummy command because the device doesn't response to the first command that is sent directly after the USB interface has been set up. Why? USB isn't set up properly? */ uint8_t cmd[10]; int error; if (s->cfg->pid == MP750_PID) return; /* MP750 doesn't have this problem(?) */ PDBG (pixma_dbg (1, "Work-around for the problem: device doesn't response to the first command.\n")); memset (cmd, 0, sizeof (cmd)); pixma_set_be16 (cmd_calibrate, cmd); error = pixma_write (s->io, cmd, 10); if (error != 10) { if (error < 0) { PDBG (pixma_dbg (1, " Sending a dummy command failed: %s\n", pixma_strerror (error))); } else { PDBG (pixma_dbg (1, " Sending a dummy command failed: count = %d\n", error)); } return; } error = pixma_read (s->io, cmd, sizeof (cmd)); if (error >= 0) { PDBG (pixma_dbg (1, " Got %d bytes response from a dummy command.\n", error)); } else { PDBG (pixma_dbg (1, " Reading response of a dummy command failed: %s\n", pixma_strerror (error))); } } static int mp750_open (pixma_t * s) { mp750_t *mp; uint8_t *buf; mp = (mp750_t *) calloc (1, sizeof (*mp)); if (!mp) return PIXMA_ENOMEM; buf = (uint8_t *) malloc (CMDBUF_SIZE); if (!buf) { free (mp); return PIXMA_ENOMEM; } s->subdriver = mp; mp->state = state_idle; /* ofs: 0 1 2 3 4 5 6 7 8 9 cmd: cmd1 cmd2 00 00 00 00 00 00 00 00 data length-^^^^^ => cmd_len_field_ofs |--------- cmd_header_len --------| res: res1 res2 |---------| res_header_len */ mp->cb.buf = buf; mp->cb.size = CMDBUF_SIZE; mp->cb.res_header_len = 2; mp->cb.cmd_header_len = 10; mp->cb.cmd_len_field_ofs = 7; handle_interrupt (s, 200); workaround_first_command (s); return 0; } static void mp750_close (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; mp750_finish_scan (s); free (mp->cb.buf); free (mp); s->subdriver = NULL; } static int mp750_check_param (pixma_t * s, pixma_scan_param_t * sp) { unsigned raw_width; UNUSED (s); sp->depth = 8; /* FIXME: Does MP750 supports other depth? */ /* GH: my implementation */ /* if ((sp->channels == 3) || (is_ccd_grayscale (s))) raw_width = ALIGN_SUP (sp->w, 4); else raw_width = ALIGN_SUP (sp->w, 12);*/ /* the above code gives segmentation fault?!? why... it seems to work in the mp750_scan function */ raw_width = ALIGN_SUP (sp->w, 4); /*sp->line_size = raw_width * sp->channels;*/ sp->line_size = raw_width * sp->channels * (sp->depth / 8); /* no cropping? */ return 0; } static int mp750_scan (pixma_t * s) { mp750_t *mp = (mp750_t *) s->subdriver; int error; uint8_t *buf; unsigned size, dpi, spare; dpi = s->param->ydpi; /* add a stripe shift for 2400dpi */ mp->stripe_shift = (dpi == 2400) ? 4 : 0; if (mp->state != state_idle) return PIXMA_EBUSY; /* clear interrupt packets buffer */ while (handle_interrupt (s, 0) > 0) { } /* if (s->param->channels == 1) mp->raw_width = ALIGN_SUP (s->param->w, 12); else mp->raw_width = ALIGN_SUP (s->param->w, 4);*/ /* change to use CCD grayscale mode --- why does this give segmentation error at runtime in mp750_check_param? */ if ((s->param->channels == 3) || (is_ccd_grayscale (s))) mp->raw_width = ALIGN_SUP (s->param->w, 4); else mp->raw_width = ALIGN_SUP (s->param->w, 12); /* not sure about MP750, but there is no need for aligning at 12 for the MP760/770, MP780/790 since always use CCD color mode */ /* modify for stripe shift */ spare = 2 * calc_component_shifting (s) + 2 * mp->stripe_shift; /* FIXME: or maybe (2*... + 1)? */ mp->raw_height = s->param->h + spare; PDBG (pixma_dbg (3, "raw_width=%u raw_height=%u dpi=%u\n", mp->raw_width, mp->raw_height, dpi)); /* PDBG (pixma_dbg (4, "line_size=%"PRIu64"\n",s->param->line_size)); */ mp->line_size = get_cis_ccd_line_size (s); /* scanner hardware line_size multiplied by 3 for CCD grayscale */ size = 8 + 2 * IMAGE_BLOCK_SIZE + spare * mp->line_size; buf = (uint8_t *) malloc (size); if (!buf) return PIXMA_ENOMEM; mp->buf = buf; mp->rawimg = buf; mp->imgbuf_ofs = spare * mp->line_size; mp->imgcol = mp->rawimg + IMAGE_BLOCK_SIZE + 8; /* added to make rgb->gray */ mp->img = mp->rawimg + IMAGE_BLOCK_SIZE + 8; mp->imgbuf_len = IMAGE_BLOCK_SIZE + mp->imgbuf_ofs; mp->rawimg_left = 0; mp->last_block_size = 0; mp->shifted_bytes = -(int) mp->imgbuf_ofs; error = step1 (s); if (error >= 0) error = start_session (s); if (error >= 0) mp->state = state_warmup; if (error >= 0) error = select_source (s); if (error >= 0) error = send_scan_param (s); if (error < 0) { mp750_finish_scan (s); return error; } return 0; } static int mp750_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { mp750_t *mp = (mp750_t *) s->subdriver; int error; uint8_t info; unsigned block_size, bytes_received, n; int shift[3], base_shift; int c; c = ((is_ccd_grayscale (s)) ? 3 : s->param->channels) * s->param->depth / 8; /* single-byte or double-byte data */ if (mp->state == state_warmup) { int tmo = 60; query_status (s); check_status (s); /*SIM*/ while (!is_calibrated (s) && --tmo >= 0) { if (s->cancel) return PIXMA_ECANCELED; if (handle_interrupt (s, 1000) > 0) { block_size = 0; error = request_image_block (s, &block_size, &info); /*SIM*/ if (error < 0) return error; } } if (tmo < 0) { PDBG (pixma_dbg (1, "WARNING: Timed out waiting for calibration\n")); return PIXMA_ETIMEDOUT; } pixma_sleep (100000); query_status (s); if (is_warming_up (s) || !is_calibrated (s)) { PDBG (pixma_dbg (1, "WARNING: Wrong status: wup=%d cal=%d\n", is_warming_up (s), is_calibrated (s))); return PIXMA_EPROTO; } block_size = 0; request_image_block (s, &block_size, &info); /*SIM*/ mp->state = state_scanning; mp->last_block = 0; } /* TODO: Move to other place, values are constant. */ base_shift = calc_component_shifting (s) * mp->line_size; if (s->param->source == PIXMA_SOURCE_ADF) { shift[0] = 0; shift[1] = -base_shift; shift[2] = -2 * base_shift; } else { shift[0] = -2 * base_shift; shift[1] = -base_shift; shift[2] = 0; } do { if (mp->last_block_size > 0) { block_size = mp->imgbuf_len - mp->last_block_size; memcpy (mp->img, mp->img + mp->last_block_size, block_size); } do { if (s->cancel) return PIXMA_ECANCELED; if (mp->last_block) { /* end of image */ info = mp->last_block; if (info != 0x38) { query_status (s); /*SIM*/ while ((info & 0x28) != 0x28) { pixma_sleep (10000); error = request_image_block2 (s, &info); if (s->cancel) return PIXMA_ECANCELED; /* FIXME: Is it safe to cancel here? */ if (error < 0) return error; } } mp->needs_abort = (info != 0x38); mp->last_block = info; mp->state = state_finished; return 0; } check_status (s); /*SIM*/ while (handle_interrupt (s, 1) > 0); /*SIM*/ block_size = IMAGE_BLOCK_SIZE; error = request_image_block (s, &block_size, &info); if (error < 0) { if (error == PIXMA_ECANCELED) read_error_info (s, NULL, 0); return error; } mp->last_block = info; if ((info & ~0x38) != 0) { PDBG (pixma_dbg (1, "WARNING: Unknown info byte %x\n", info)); } if (block_size == 0) { /* no image data at this moment. */ pixma_sleep (10000); } } while (block_size == 0); error = read_image_block (s, mp->rawimg + mp->rawimg_left); if (error < 0) { mp->state = state_transfering; return error; } bytes_received = error; PASSERT (bytes_received == block_size); /* TODO: simplify! */ mp->rawimg_left += bytes_received; n = mp->rawimg_left / 3; /* n = number of pixels in the buffer? */ /* Color to Grayscale converion for CCD sensor */ if (is_ccd_grayscale (s)) { shift_rgb (mp->rawimg, n, shift[0], shift[1], shift[2], mp->stripe_shift, mp->line_size, mp->imgcol + mp->imgbuf_ofs); /* dst: img, src: imgcol */ rgb_to_gray (mp->img, mp->imgcol, n, c); /* cropping occurs later? */ PDBG (pixma_dbg (4, "*fill_buffer: did grayscale conversion \n")); } /* Color image processing */ else { shift_rgb (mp->rawimg, n, shift[0], shift[1], shift[2], mp->stripe_shift, mp->line_size, mp->img + mp->imgbuf_ofs); PDBG (pixma_dbg (4, "*fill_buffer: no grayscale conversion---keep color \n")); } /* entering remaining unprocessed bytes after last complete pixel into mp->rawimg buffer -- no influence on mp->img */ n *= 3; mp->shifted_bytes += n; mp->rawimg_left -= n; /* rawimg_left = 0, 1 or 2 bytes left in the buffer. */ mp->last_block_size = n; memcpy (mp->rawimg, mp->rawimg + n, mp->rawimg_left); } while (mp->shifted_bytes <= 0); if ((unsigned) mp->shifted_bytes < mp->last_block_size) { if (is_ccd_grayscale (s)) ib->rptr = mp->img + mp->last_block_size/3 - mp->shifted_bytes/3; /* testing---works OK */ else ib->rptr = mp->img + mp->last_block_size - mp->shifted_bytes; } else ib->rptr = mp->img; if (is_ccd_grayscale (s)) ib->rend = mp->img + mp->last_block_size/3; /* testing---works OK */ else ib->rend = mp->img + mp->last_block_size; return ib->rend - ib->rptr; } static void mp750_finish_scan (pixma_t * s) { int error; mp750_t *mp = (mp750_t *) s->subdriver; switch (mp->state) { case state_transfering: drain_bulk_in (s); /* fall through */ case state_scanning: case state_warmup: error = abort_session (s); if (error == PIXMA_ECANCELED) read_error_info (s, NULL, 0); /* fall through */ case state_finished: if (s->param->source == PIXMA_SOURCE_FLATBED) { /*SIM*/ query_status (s); if (abort_session (s) == PIXMA_ECANCELED) { read_error_info (s, NULL, 0); query_status (s); } } query_status (s); /*SIM*/ activate (s, 0); if (mp->needs_abort) { mp->needs_abort = 0; abort_session (s); } free (mp->buf); mp->buf = mp->rawimg = NULL; mp->state = state_idle; /* fall through */ case state_idle: break; } } static void mp750_wait_event (pixma_t * s, int timeout) { /* FIXME: timeout is not correct. See usbGetCompleteUrbNoIntr() for * instance. */ while (s->events == 0 && handle_interrupt (s, timeout) > 0) { } } static int mp750_get_status (pixma_t * s, pixma_device_status_t * status) { int error; error = query_status (s); if (error < 0) return error; status->hardware = PIXMA_HARDWARE_OK; status->adf = (has_paper (s)) ? PIXMA_ADF_OK : PIXMA_ADF_NO_PAPER; status->cal = (is_calibrated (s)) ? PIXMA_CALIBRATION_OK : PIXMA_CALIBRATION_OFF; status->lamp = (is_warming_up (s)) ? PIXMA_LAMP_WARMING_UP : PIXMA_LAMP_OK; return 0; } static const pixma_scan_ops_t pixma_mp750_ops = { mp750_open, mp750_close, mp750_scan, mp750_fill_buffer, mp750_finish_scan, mp750_wait_event, mp750_check_param, mp750_get_status }; #define DEVICE(name, model, pid, dpi, cap) { \ name, /* name */ \ model, /* model */ \ 0x04a9, pid, /* vid pid */ \ 0, /* iface */ \ &pixma_mp750_ops, /* ops */ \ dpi, 2*(dpi), /* xdpi, ydpi */ \ 0, 0, /* adftpu_min_dpi & adftpu_max_dpi not used in this subdriver */ \ 0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \ 637, 877, /* width, height */ \ PIXMA_CAP_GRAY|PIXMA_CAP_EVENTS|cap \ } const pixma_config_t pixma_mp750_devices[] = { DEVICE ("Canon PIXMA MP750", "MP750", MP750_PID, 2400, PIXMA_CAP_CCD | PIXMA_CAP_ADF), DEVICE ("Canon PIXMA MP760/770", "MP760/770", MP760_PID, 2400, PIXMA_CAP_CCD | PIXMA_CAP_TPU), DEVICE ("Canon PIXMA MP780/790", "MP780/790", MP780_PID, 2400, PIXMA_CAP_CCD | PIXMA_CAP_ADF), DEVICE (NULL, NULL, 0, 0, 0) }; sane-backends-1.0.27/backend/teco3.conf.in0000664000175000017500000000033112112021330015060 00000000000000# VM3552 scsi "" "Flat-bed scanner" Scanner scsi "RELISYS" "Scorpio" # Trust Imagery 2400SP scsi "Aashima" "IMAGERY 2400SP" Scanner * * * 0 # Trust Imagery 4800 SP +: scsi "Aashima" "IMAGERY 4800SP +" /dev/scanner sane-backends-1.0.27/backend/hp3900_types.c0000664000175000017500000004506412112021330015116 00000000000000/* HP Scanjet 3900 series - Structures and global variables Copyright (C) 2005-2009 Jonathan Bravo Lopez This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* devices */ #define DEVSCOUNT 0x09 /* Number of scanners supported by this backend */ #define HP3970 0x00 /* rts8822l-01H HP Scanjet 3970 */ #define HP4070 0x01 /* rts8822l-01H HP Scanjet 4070 */ #define HP4370 0x02 /* rts8822l-02A HP Scanjet 4370 */ #define UA4900 0x03 /* rts8822l-01H UMAX Astra 4900 */ #define HP3800 0x04 /* rts8822bl-03A HP Scanjet 3800 */ #define HPG3010 0x05 /* rts8822l-02A HP Scanjet G3010 */ #define BQ5550 0x06 /* rts8823l-01E BenQ 5550 */ #define HPG2710 0x07 /* rts8822bl-03A HP Scanjet G2710 */ #define HPG3110 0x08 /* rts8822l-02A HP Scanjet G3110 */ /* chipset models */ #define RTS8822L_01H 0x00 #define RTS8822L_02A 0x01 #define RTS8822BL_03A 0x02 #define RTS8823L_01E 0x03 /* chipset capabilities */ #define CAP_EEPROM 0x01 /* acceleration types */ #define ACC_CURVE 0x00 #define DEC_CURVE 0x01 /* curve types */ #define CRV_NORMALSCAN 0x00 #define CRV_PARKHOME 0x01 #define CRV_SMEARING 0x02 #define CRV_BUFFERFULL 0x03 /* Sample rates */ #define PIXEL_RATE 0x00 #define LINE_RATE 0x01 /* motor types */ #define MT_OUTPUTSTATE 0x00 #define MT_ONCHIP_PWM 0x01 /* motor step types */ #define STT_FULL 0x00 /* 90 degrees */ #define STT_HALF 0x01 /* 45 degrees */ #define STT_QUART 0x02 /* 22.5 degrees */ #define STT_OCT 0x03 /* 11.25 degrees */ /* motor options */ #define MTR_BACKWARD 0x00 #define MTR_FORWARD 0x08 #define MTR_ENABLED 0x00 #define MTR_DISABLED 0x10 /* sensors */ #define CCD_SENSOR 0x01 #define CIS_SENSOR 0x00 /* sony sensor models */ #define SNYS575 0x00 /* toshiba sensor models */ #define TCD2952 0x01 #define TCD2958 0x02 #define TCD2905 0x03 /* usb types */ #define USB20 0x01 #define USB11 0x00 /* scan types */ #define ST_NEG 0x03 #define ST_TA 0x02 #define ST_NORMAL 0x01 /* colour modes */ #define CM_COLOR 0x00 #define CM_GRAY 0x01 #define CM_LINEART 0x02 /* colour channels */ #define CL_RED 0x00 #define CL_GREEN 0x01 #define CL_BLUE 0x02 /* lamp types */ #define FLB_LAMP 0x01 #define TMA_LAMP 0x02 #define IST_NORMAL 0x00 #define IST_TA 0x01 #define IST_NEG 0x02 #define ICM_GRAY 0x00 #define ICM_LINEART 0x01 #define ICM_COLOR 0x02 #define TRUE 0x01 #define FALSE 0x00 /* function results */ #define OK 0x00 #define ERROR -1 #define RT_BUFFER_LEN 0x71a #define FIX_BY_HARD 0x01 #define FIX_BY_SOFT 0x02 #define REF_AUTODETECT 0x02 #define REF_TAKEFROMSCANNER 0x01 #define REF_NONE 0x00 /* bulk operations */ #define BLK_WRITE 0x00 #define BLK_READ 0x01 /* constants for resizing functions */ #define RSZ_NONE 0x00 #define RSZ_DECREASE 0x01 #define RSZ_INCREASE 0x02 #define RSZ_GRAYL 0x00 #define RSZ_COLOURL 0x01 #define RSZ_COLOURH 0x02 #define RSZ_LINEART 0x03 #define RSZ_GRAYH 0x04 /* Macros for managing data */ #define _B0(x) ((SANE_Byte)((x) & 0xFF)) #define _B1(x) ((SANE_Byte)((x) >> 0x08)) #define _B2(x) ((SANE_Byte)((x) >> 0x10)) #define _B3(x) ((SANE_Byte)((x) >> 0x18)) /* operation constants used in RTS_GetImage */ #define OP_STATIC_HEAD 0x00000001 #define OP_COMPRESSION 0x00000004 #define OP_BACKWARD 0x00000010 #define OP_WHITE_SHAD 0x00000020 #define OP_USE_GAMMA 0x00000040 #define OP_BLACK_SHAD 0x00000080 #define OP_LAMP_ON 0x00000200 /* data types */ typedef unsigned short USHORT; #ifdef STANDALONE /* Stand-alone*/ #define SANE_STATUS_GOOD 0x00 typedef unsigned char SANE_Byte; typedef int SANE_Int; typedef usb_dev_handle *USB_Handle; #else /* SANE backend */ typedef SANE_Int USB_Handle; #endif /* structures */ struct st_debug_opts { /* device capabilities */ SANE_Int dev_model; SANE_Byte SaveCalibFile; SANE_Byte DumpShadingData; SANE_Byte ScanWhiteBoard; SANE_Byte EnableGamma; SANE_Byte use_fixed_pwm; SANE_Int dmabuffersize; SANE_Int dmatransfersize; SANE_Int dmasetlength; SANE_Int usbtype; SANE_Int calibrate; SANE_Int wshading; SANE_Int overdrive_flb; SANE_Int overdrive_ta; SANE_Byte warmup; SANE_Int shd; }; struct st_chip { SANE_Int model; SANE_Int capabilities; char *name; }; struct st_shading { double *rates; SANE_Int count; SANE_Int ptr; }; struct st_scanning { SANE_Byte *imagebuffer; SANE_Byte *imagepointer; SANE_Int bfsize; SANE_Int channel_size; /* arrange line related variables */ SANE_Int arrange_hres; SANE_Int arrange_compression; SANE_Int arrange_sensor_evenodd_dist; SANE_Int arrange_orderchannel; SANE_Int arrange_size; /* Pointers to each channel colour */ SANE_Byte *pColour[3]; SANE_Byte *pColour1[3]; SANE_Byte *pColour2[3]; /* Channel displacements */ SANE_Int desp[3]; SANE_Int desp1[3]; SANE_Int desp2[3]; }; struct st_resize { SANE_Byte mode; SANE_Int type; SANE_Int fromwidth; SANE_Int towidth; SANE_Int bytesperline; SANE_Int rescount; SANE_Int resolution_x; SANE_Int resolution_y; SANE_Byte *v3624; SANE_Byte *v3628; SANE_Byte *v362c; }; struct st_gammatables { SANE_Int depth; /*0=0x100| 4=0x400 |8=0x1000 */ SANE_Byte *table[3]; }; struct st_readimage { SANE_Int Size4Lines; SANE_Byte Starting; SANE_Byte *DMABuffer; SANE_Int DMABufferSize; SANE_Byte *RDStart; SANE_Int RDSize; SANE_Int DMAAmount; SANE_Int Channel_size; SANE_Byte Channels_per_dot; SANE_Int ImageSize; SANE_Int Bytes_Available; SANE_Int Max_Size; SANE_Byte Cancel; }; struct st_gain_offset { /* 32 bytes 08be|08e0|3654 red green blue */ SANE_Int edcg1[3]; /* 08e0|08e2|08e4 *//*Even offset 1 */ SANE_Int edcg2[3]; /* 08e6|08e8|08ea *//*Even offset 2 */ SANE_Int odcg1[3]; /* 08ec|08ee|08f0 *//*Odd offset 1 */ SANE_Int odcg2[3]; /* 08f2|08f4|08f6 *//*Odd offset 2 */ SANE_Byte pag[3]; /* 08f8|08f9|08fa */ SANE_Byte vgag1[3]; /* 08fb|08fc|08fd */ SANE_Byte vgag2[3]; /* 08fe|08ff|0900 */ }; struct st_calibration_config { SANE_Int WStripXPos; SANE_Int WStripYPos; SANE_Int BStripXPos; SANE_Int BStripYPos; SANE_Int WRef[3]; SANE_Int BRef[3]; SANE_Byte RefBitDepth; double OffsetTargetMax; double OffsetTargetMin; double OffsetBoundaryRatio1; double OffsetBoundaryRatio2; double OffsetAvgRatio1; double OffsetAvgRatio2; SANE_Int CalibOffset10n; SANE_Int CalibOffset20n; SANE_Int AdcOffEvenOdd; SANE_Int AdcOffQuickWay; SANE_Int OffsetEven1[3]; SANE_Int OffsetOdd1[3]; SANE_Int OffsetEven2[3]; SANE_Int OffsetOdd2[3]; SANE_Byte OffsetHeight; SANE_Int OffsetPixelStart; SANE_Int OffsetNPixel; SANE_Byte OffsetNSigma; SANE_Int AdcOffPredictStart; SANE_Int AdcOffPredictEnd; SANE_Byte OffsetAvgTarget[3]; SANE_Byte OffsetTuneStep1; SANE_Byte OffsetTuneStep2; double GainTargetFactor; SANE_Int CalibGain10n; SANE_Int CalibGain20n; SANE_Int CalibPAGOn; SANE_Int GainHeight; SANE_Int unk1[3]; SANE_Int unk2[3]; SANE_Byte PAG[3]; SANE_Byte Gain1[3]; SANE_Byte Gain2[3]; /* White Shading */ SANE_Int WShadingOn; SANE_Int WShadingHeight; SANE_Int WShadingPreDiff[3]; SANE_Int unknown; /*?? */ double ShadingCut[3]; /* Black Shading */ SANE_Int BShadingOn; SANE_Int BShadingHeight; SANE_Int BShadingDefCutOff; SANE_Int BShadingPreDiff[3]; double ExternBoundary; SANE_Int EffectivePixel; SANE_Byte TotShading; }; struct st_calibration { /* faac */ struct st_gain_offset gain_offset; /* 0..35 */ USHORT *white_shading[3]; /* +36 +40 +44 */ USHORT *black_shading[3]; /* +48 +52 +56 */ SANE_Int WRef[3]; /* +60 +62 +64 */ SANE_Byte shading_type; /* +66 */ SANE_Byte shading_enabled; /* +67 */ SANE_Int first_position; /* +68 */ SANE_Int shadinglength; /* +72 */ }; struct st_cal2 { /* f9f8 35 bytes */ SANE_Int table_count; /* +0 f9f8 */ SANE_Int shadinglength1; /* +4 f9fc */ SANE_Int tables_size; /* +8 fa00 */ SANE_Int shadinglength3; /* +12 fa04 */ USHORT *tables[4]; /* +16+20+24+28 fa08 fa0c fa10 fa14 */ USHORT *table2; /* +32 fa18 */ }; struct st_coords { SANE_Int left; SANE_Int width; SANE_Int top; SANE_Int height; }; struct params { SANE_Int scantype; SANE_Int colormode; SANE_Int resolution_x; SANE_Int resolution_y; struct st_coords coords; SANE_Int depth; SANE_Int channel; }; struct st_constrains { struct st_coords reflective; struct st_coords negative; struct st_coords slide; }; struct st_scanparams /* 44 bytes size */ { /* 760-78b|155c-1587|fa58-fa83|f0c4 */ SANE_Byte colormode; /* [+00] 760 */ SANE_Byte depth; /* [+01] 761 */ SANE_Byte samplerate; /* [+02] 762 */ SANE_Byte timing; /* [+03] 763 */ SANE_Int channel; /* [+04] 764 */ SANE_Int sensorresolution; /* [+06] 766 */ SANE_Int resolution_x; /* [+08] 768 */ SANE_Int resolution_y; /* [+10] 76a */ struct st_coords coord; /* [+12] left */ /* [+16] width */ /* [+20] top */ /* [+24] height */ SANE_Int shadinglength; /* [+28] 77c */ SANE_Int v157c; /* [+32] 780 */ SANE_Int bytesperline; /* [+36] 784 */ SANE_Int expt; /* [+40] 788 */ SANE_Int startpos; /* [+44] 78c */ SANE_Int leftleading; /* [+46] 78e */ SANE_Int ser; /* [+48] 790 */ SANE_Int ler; /* [+52] 794 */ SANE_Int scantype; /* [+58] 79a */ }; struct st_hwdconfig /* 28 bytes size */ { /* fa84-fa9f|f0ac-f0c7|e838-e853|f3a4-f3bf */ SANE_Int startpos; /* +0 */ /* +1..7 */ SANE_Byte arrangeline; /* +8 */ SANE_Byte scantype; /* +9 */ SANE_Byte compression; /* +10 */ SANE_Byte use_gamma_tables; /* +11 */ SANE_Byte gamma_tablesize; /* +12 */ SANE_Byte white_shading; /* +13 */ SANE_Byte black_shading; /* +14 */ SANE_Byte unk3; /* +15 */ SANE_Byte motorplus; /* +16 */ SANE_Byte static_head; /* +17 */ SANE_Byte motor_direction; /* +18 */ SANE_Byte dummy_scan; /* +19 */ SANE_Byte highresolution; /* +20 */ SANE_Byte sensorevenodddistance; /* +21 */ /* +22..23 */ SANE_Int calibrate; /* +24 */ }; struct st_calibration_data { SANE_Byte Regs[RT_BUFFER_LEN]; struct st_scanparams scancfg; struct st_gain_offset gain_offset; }; struct st_cph { double p1; double p2; SANE_Byte ps; SANE_Byte ge; SANE_Byte go; }; struct st_timing { SANE_Int sensorresolution; SANE_Byte cnpp; SANE_Byte cvtrp[3]; /* 3 transfer gates */ SANE_Byte cvtrw; SANE_Byte cvtrfpw; SANE_Byte cvtrbpw; struct st_cph cph[6]; /* Linear Image Sensor Clocks */ SANE_Int cphbp2s; SANE_Int cphbp2e; SANE_Int clamps; SANE_Int clampe; SANE_Byte cdss[2]; SANE_Byte cdsc[2]; SANE_Byte cdscs[2]; /* Toshiba T958 ccd from hp4370 */ double adcclkp[2]; SANE_Int adcclkp2e; }; struct st_scanmode { SANE_Int scantype; SANE_Int colormode; SANE_Int resolution; SANE_Byte timing; SANE_Int motorcurve; SANE_Byte samplerate; SANE_Byte systemclock; SANE_Int ctpc; SANE_Int motorbackstep; SANE_Byte scanmotorsteptype; SANE_Byte dummyline; SANE_Int expt[3]; SANE_Int mexpt[3]; SANE_Int motorplus; SANE_Int multiexposurefor16bitmode; SANE_Int multiexposureforfullspeed; SANE_Int multiexposure; SANE_Int mri; SANE_Int msi; SANE_Int mmtir; SANE_Int mmtirh; SANE_Int skiplinecount; }; struct st_motormove { SANE_Byte systemclock; SANE_Int ctpc; SANE_Byte scanmotorsteptype; SANE_Int motorcurve; }; struct st_motorpos { SANE_Int coord_y; SANE_Byte options; SANE_Int v12e448; SANE_Int v12e44c; }; struct st_find_edge { SANE_Int exposuretime; SANE_Int scanystart; SANE_Int scanylines; SANE_Int findlermethod; SANE_Int findlerstart; SANE_Int findlerend; SANE_Int checkoffsetser; SANE_Int findserchecklines; SANE_Int findserstart; SANE_Int findserend; SANE_Int findsermethod; SANE_Int offsettoser; SANE_Int offsettoler; }; struct st_curve { SANE_Int crv_speed; /* acceleration or deceleration */ SANE_Int crv_type; SANE_Int step_count; SANE_Int *step; }; struct st_motorcurve { SANE_Int mri; SANE_Int msi; SANE_Int skiplinecount; SANE_Int motorbackstep; SANE_Int curve_count; struct st_curve **curve; }; struct st_checkstable { double diff; SANE_Int interval; long tottime; }; struct st_sensorcfg { SANE_Int type; SANE_Int name; SANE_Int resolution; SANE_Int channel_color[3]; SANE_Int channel_gray[2]; SANE_Int rgb_order[3]; SANE_Int line_distance; SANE_Int evenodd_distance; }; struct st_autoref { SANE_Byte type; SANE_Int offset_x; SANE_Int offset_y; SANE_Int resolution; SANE_Int extern_boundary; }; struct st_motorcfg { SANE_Byte type; SANE_Int resolution; SANE_Byte pwmfrequency; SANE_Int basespeedpps; SANE_Int basespeedmotormove; SANE_Int highspeedmotormove; SANE_Int parkhomemotormove; SANE_Byte changemotorcurrent; }; struct st_buttons { SANE_Int count; SANE_Int mask[6]; /* up to 6 buttons */ }; struct st_status { SANE_Byte warmup; SANE_Byte parkhome; SANE_Byte cancel; }; struct st_device { /* next var handles usb device, used for every usb operations */ USB_Handle usb_handle; /* next buffer will contain initial state registers of the chipset */ SANE_Byte *init_regs; /* next structure will contain information and capabilities about chipset */ struct st_chip *chipset; /* next structure will contain general configuration of stepper motor */ struct st_motorcfg *motorcfg; /* next structure will contain general configuration of ccd sensor */ struct st_sensorcfg *sensorcfg; /* next structure will contain all ccd timing values */ SANE_Int timings_count; struct st_timing **timings; /* next structure will contain all possible motor movements */ SANE_Int motormove_count; struct st_motormove **motormove; /* next structure will contain all motorcurve values */ SANE_Int mtrsetting_count; struct st_motorcurve **mtrsetting; /* next structure will contain all possible scanning modes for one scanner */ SANE_Int scanmodes_count; struct st_scanmode **scanmodes; /* next structure contains constrain values for one scanner */ struct st_constrains *constrains; /* next structure contains supported buttons and their order */ struct st_buttons *buttons; /* next structure will be used to resize scanned image */ struct st_resize *Resize; /* next structure will be used while reading image from device */ struct st_readimage *Reading; /* next structure will be used to arrange color channels while scanning */ struct st_scanning *scanning; /* next structure will contain some status which can be requested */ struct st_status *status; }; /* Unknown vars */ SANE_Int v14b4 = 0; SANE_Byte *v1600 = NULL; /* tabla */ SANE_Byte *v1604 = NULL; /* tabla */ SANE_Byte *v1608 = NULL; /* tabla */ SANE_Byte v160c_block_size; SANE_Int mem_total; SANE_Byte v1619; SANE_Int v15f8; SANE_Int acccurvecount; /* counter used y MotorSetup */ SANE_Int deccurvecount; /* counter used y MotorSetup */ SANE_Int smearacccurvecount; /* counter used y MotorSetup */ SANE_Int smeardeccurvecount; /* counter used y MotorSetup */ /* Known vars */ SANE_Int offset[3]; SANE_Byte gain[3]; static SANE_Int usbfile = -1; SANE_Int scantype; SANE_Byte pwmlamplevel; SANE_Byte arrangeline; SANE_Byte binarythresholdh; SANE_Byte binarythresholdl; SANE_Byte shadingbase; SANE_Byte shadingfact[3]; SANE_Byte arrangeline; SANE_Int compression; SANE_Byte linedarlampoff; SANE_Int pixeldarklevel; SANE_Int bw_threshold = 0x00; /* SetScanParams */ struct st_scanparams scan; struct st_scanparams scan2; SANE_Int bytesperline; /* width * (3 colors [RGB]) */ SANE_Int imagewidth3; SANE_Int lineart_width; SANE_Int imagesize; /* bytesperline * coords.height */ SANE_Int imageheight; SANE_Int line_size; SANE_Int v15b4; SANE_Int v15bc; SANE_Int waitforpwm; SANE_Byte WRef[3]; USHORT *fixed_black_shading[3] = { NULL, NULL, NULL }; USHORT *fixed_white_shading[3] = { NULL, NULL, NULL }; /* Calibration */ struct st_gain_offset mitabla2; /* calibration table */ SANE_Int v0750; static SANE_Byte use_gamma_tables; SANE_Int read_v15b4 = 0; SANE_Int v35b8 = 0; SANE_Int arrangeline2; SANE_Int v07c0 = 0; /* next structure contains coefficients for white shading correction */ struct st_shading *wshading; struct st_gammatables *hp_gamma; struct st_gain_offset *default_gain_offset; struct st_calibration_data *calibdata; struct st_debug_opts *RTS_Debug; /* testing */ SANE_Byte *jkd_black = NULL; SANE_Int jkd_blackbpl; sane-backends-1.0.27/backend/hs2p-scsi.h0000664000175000017500000013416712112021330014572 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007 Jeremy Johnson This file is part of a SANE backend for Ricoh IS450 and IS420 family of HS2P Scanners using the SCSI controller. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_thread.h" /* 1-2 SCSI STATUS BYTE KEYS */ #define HS2P_SCSI_STATUS_GOOD 0x00 #define HS2P_SCSI_STATUS_CHECK 0x02 #define HS2P_SCSI_STATUS_BUSY 0x08 #define HS2P_SCSI_STATUS_RESERVATION CONFLICT 0x18 /* All other status byte keys are reserved */ /* * SCSI Command List for Command Descriptor Block * All reserved bit and fields in the CDB must be zero * Values in the CDB described as "Reserved" must no be specified * The FLAG and LINK bits in the CONTROL byte must be zero * Any values in the Vendor Unique field are ignored * The Logical Unit Number in the CDB must always be zero * All Reserved bit and fields in the data fields must be zero * Values of parameters in the data fields described as * "Reserved" or "Not supported" must not be specified */ /* 1-3 SCSI COMMANDS */ #define HS2P_SCSI_TEST_UNIT_READY 0x00 #define HS2P_SCSI_REQUEST_SENSE 0x03 #define HS2P_SCSI_INQUIRY 0x12 #define HS2P_SCSI_MODE_SELECT 0x15 #define HS2P_SCSI_RESERVE_UNIT 0x16 #define HS2P_SCSI_RELEASE_UNIT 0x17 #define HS2P_SCSI_MODE_SENSE 0x1a #define HS2P_SCSI_START_SCAN 0x1b #define HS2P_SCSI_RECEIVE_DIAGNOSTICS 0x1c #define HS2P_SCSI_SEND_DIAGNOSTICS 0x1d #define HS2P_SCSI_SET_WINDOW 0x24 #define HS2P_SCSI_GET_WINDOW 0x25 #define HS2P_SCSI_READ_DATA 0x28 #define HS2P_SCSI_SEND_DATA 0x2a #define HS2P_SCSI_OBJECT_POSITION 0x31 #define HS2P_SCSI_GET_BUFFER_STATUS 0x34 /* Sense Key Defines */ #define HS2P_SK_NO_SENSE 0x00 #define HS2P_SK_RECOVERED_ERROR 0x01 #define HS2P_SK_NOT_READY 0x02 #define HS2P_SK_MEDIUM_ERROR 0x03 #define HS2P_SK_HARDWARE_ERROR 0x04 #define HS2P_SK_ILLEGAL_REQUEST 0x05 #define HS2P_SK_UNIT_ATTENTION 0x06 #define HS2P_SK_DATA_PROJECT 0x07 #define HS2P_SK_BLANK_CHECK 0x08 #define HS2P_SK_VENDOR_UNIQUE 0x09 #define HS2P_SK_COPY_ABORTED 0x0a #define HS2P_SK_ABORTED_COMMAND 0x0b #define HS2P_SK_EQUAL 0x0c #define HS2P_SK_VOLUME_OVERFLOW 0x0d #define HS2P_SK_MISCOMPARE 0x0e #define HS2P_SK_RESERVED 0x0f struct sense_key { int key; char *meaning; char *description; }; static struct sense_key sensekey_errmsg[16] = { {0x00, "NO SENSE", "Indicates that there is no Sense Key information"}, {0x01, "RECOVERED ERROR", "Invalid"}, {0x02, "NOT READY", "Indicates that the scanner is not ready, e.g. ADF cover not closed"}, {0x03, "MEDIUM ERROR", "Error regarding document such as paper jam"}, {0x04, "HARDWARE ERROR", "Error relating to hardware, e.g. CCD line clock error"}, {0x05, "ILLEGAL REQUEST", "Used such as when illegal parameter exists in data or command"}, {0x06, "UNIT ATTENTION", "Used when power on, BUS DEVICE RESET message or hardware reset"}, {0x07, "DATA PROJECT", "Invalid"}, {0x08, "BLANK CHECK", "Invalid"}, {0x09, "VENDOR UNIQUE", "Invalid"}, {0x0a, "COPY ABORTED", "Invalid"}, {0x0b, "ABORTED COMMAND", "Used when scanner aborts a command execution"}, {0x0c, "EQUAL", "Invalid"}, {0x0d, "VOLUME OVERFLOW", "Invalid"}, {0x0e, "MISCOMPARE", "Invalid"}, {0x0f, "RESERVED", "Invalid"} }; /* When Error_Code = 0x70 more detailed information is available: * code, qualifier, description */ struct ASCQ { /* ADDITIONAL SENSE CODE QUALIFIER */ unsigned int codequalifier; char *description; }; static struct ASCQ ascq_errmsg[74] = { {0x0000, "No additional sense information"}, {0x0002, "End of Medium detected"}, {0x0005, "End of Data detected"}, {0x0400, "Logical unit not ready. Don't know why."}, {0x0401, "Logical unit is in process of becoming ready."}, {0x0403, "Logical unit not ready. Manual intervention required."}, {0x0500, "Logical unit does not respond to selection."}, {0x0700, "Multiple peripheral devices selected."}, {0x1100, "Unrecovered read error."}, {0x1101, "Read retries exhausted."}, {0x1501, "Mechanical positioning error."}, {0x1a00, "Parameter list length error."}, {0x2000, "Invalid command operation mode."}, {0x2400, "Invalid field in CDB (check field pointer)."}, {0x2500, "Logical unit not supported."}, {0x2600, "Invalid field in parameter list (check field pointer)."}, {0x2900, "Power on, reset, or BUS DEVICE RESET occurred."}, {0x2a01, "(MODE parameter changed.)"}, {0x2c00, "Command sequence error."}, {0x2c01, "(Too many windows specified."}, {0x2c02, "(Invalid combination of windows specified."}, {0x3700, "(Rounded parameter.)"}, {0x3900, "(Saving parameters not supported.)"}, {0x3a00, "Medium not present."}, {0x3b09, "(Read past end of medium.)"}, {0x3b0b, "(Position past end of medium.)"}, {0x3d00, "Invalid bits in IDENTIFY message."}, {0x4300, "Message error."}, {0x4500, "Select/Reselect failure."}, {0x4700, "(SCSI parity error)"}, {0x4800, "Initiator detected error message received."}, {0x4900, "Invalid message error."}, {0x4a00, "Command phase error."}, {0x4b00, "Data phase error."}, {0x5300, "(Media Load/Eject failed)"}, {0x6000, "Lamp failure"}, {0x6001, "(Shading Error)"}, {0x6002, "White adjustment error"}, {0x6010, "Reverse Side Lamp Failure"}, {0x6200, "Scan head positioning error"}, {0x6300, "Document Waiting Cancel"}, {0x8000, "(PSU overheat)"}, {0x8001, "(PSU 24V fuse down)"}, {0x8002, "(ADF 24V fuse down)"}, {0x8003, "(5V fuse down)"}, {0x8004, "(-12V fuse down)"}, {0x8100, "(ADF 24V power off)"}, {0x8101, "(Base 12V power off)"}, {0x8102, "(SCSI 5V power off)"}, {0x8103, "Lamp cover open (Lamp 24V power off)"}, {0x8104, "(-12V power off)"}, {0x8105, "(Endorser 6V power off)"}, {0x8106, "SCU 3.3V power down error"}, {0x8107, "RCU 3.3V power down error"}, {0x8108, "OIPU 3.3V power down error"}, {0x8200, "Memory Error (Bus error)"}, {0x8210, "Reverse-side memory error (Bus error)"}, {0x8300, "(Image data processing LSI error)"}, {0x8301, "(Interfac LSI error)"}, {0x8302, "(SCSI controller error)"}, {0x8303, "(Compression unit error)"}, {0x8304, "(Marker detect unit error)"}, {0x8400, "Endorser error"}, {0x8500, "(Origin Positioning error)"}, {0x8600, "Mechanical Time Out error (Pick Up Roller error)"}, {0x8700, "(Heater error)"}, {0x8800, "(Thermistor error)"}, {0x8900, "ADF cover open"}, {0x8901, "(ADF lift up)"}, {0x8902, "Document jam error for ADF"}, {0x8903, "Document misfeed for ADF"}, {0x8a00, "(Interlock open)"}, {0x8b00, "(Not enough memory)"}, {0x8c00, "Size detection failed"} }; typedef struct sense_data { /* HS2P_REQUEST_SENSE_DATA */ /* bit7:valid is 1 if information byte is valid, bits6:0 error_code */ SANE_Byte error_code; /* not used, set to 0 */ SANE_Byte segment_number; /* bit7 file-mark (unused, set to 0), bit6 EOM is 1 if end of document detected before completing scan bit5 ILI (incorrect length indicator) is 1 when data length mismatch occurs on READ bits3:0 sense_key indicates error conditions. */ SANE_Byte sense_key; SANE_Byte information[4]; /* fixed at 6 */ SANE_Byte sense_length; /* not used and set to 0 */ SANE_Byte command_specific_information[4]; SANE_Byte sense_code; SANE_Byte sense_code_qualifier; } SENSE_DATA; /* page codes used with HS2P_SCSI_INQUIRY */ #define HS2P_INQUIRY_STANDARD_PAGE_CODE 0x00 #define HS2P_INQUIRY_VPD_PAGE_CODE 0xC0 #define HS2P_INQUIRY_JIS_PAGE_CODE 0xF0 /* * The EVPD and Page Code are used in pair. When the EVPD bit is 0, INQUIRY data * in the standard format is returned to the initiator. When the EVPD bit is 1, * the EVPD information specified by each Page Code is returned in each Page Code * data format. * * EVPD=0x00, Page_Code=0x00 => Standard Data Format * * EVPD=0x01, PAGE_CODE=0x00 => Return list of supported Page Codes * EVPD=0x01, PAGE_CODE=0x01~0x7F => Not Supported * EVPD=0x01, PAGE_CODE=0x80~0x82 => Not Supported * EVPD=0x01, PAGE_CODE=0x83~0xBF => Reserved * EVPD=0x01, PAGE_CODE=0xC0 => RICOH Scanner VPD information * EVPD=0x01, PAGE_CODE=0xF0 => JIS Version VPD information */ struct inquiry_standard_data { /* bits7-5 peripheral qualifier * bits4-0 peripheral device * Peripheral Qualifier and Peripheral Devide Type are not supported on logical unit * Therefore LUN=0 and this field indicates scanner and is set to 0x06 * When LUN!=0 this field becomes 0x1F and means undefined data */ SANE_Byte devtype; /* must be 0x06 */ /* bit7: repaceable media bit is set to 0 * bits6-1: reserved * bit0: EVPD */ SANE_Byte rmb_evpd; /* bits7-6: ISO Version is set to 0 * bits5-3: ECMA Version is set to 0 * bits2-0: ANSI Version is set to 2 */ SANE_Byte version; /* bit7: AENC (asynchronous event notification capability) is set to 0 * bit6: TrmIOP (terminate I/O process) is set to 0 * bits5-4: reserved * bits3-0: Response Data Format is set to 2 */ SANE_Byte response_data_format; /* Additional Length indicate number of bytes which follows, set to 31 */ SANE_Byte length; SANE_Byte reserved[2]; /* bit7: RelAdr (relative addressing) is set to 0 * bit6: Wbus32 is set to 0 * bit5: Wbus16 is set to 0 * bit4: Sync is set to 0 * bit3: Linked is set to 0 * bit2: reserved * bit1: CmdQue is set to 0 * bit0: SftRe is set to 0 * Sync is set to 1 with this scanner to support synchronous data transfer * When DIPSW2 is on, Sync is set to 0 for asynchronous data transfer */ SANE_Byte byte7; SANE_Byte vendor[8]; /* vendor_id="RICOH " */ SANE_Byte product[16]; /* product_id="IS450 " */ SANE_Byte revision[4]; /* product_revision_level="xRxx" where x indicate firmware version number */ }; /* VPD Information [EVPD=0x01, PageCode=0xC0] */ struct inquiry_vpd_data { SANE_Byte devtype; /* bits7-5: Peripheral Qualifier * bits4-0: Peripheral Device Type */ SANE_Byte pagecode; /* Page Code => 0xC0 */ SANE_Byte byte2; /* Reserved */ SANE_Byte pagelength; /* Page Length => 12 (0x0C) */ SANE_Byte adf_id; /* ADF Identification * 0: No ADF is mounted * 1: Single sided ADF is mounted * 2: Double sided ADF is mounted * 3: ARDF is mounted. (Reverse double side scanning available) * 4: Reserved * It should be 1 or 2 with this scanner. */ SANE_Byte end_id; /* Endorser Identification * 0: No endorser * 1: Endorser mounted * 2: Reserved * It should be 0 or 1 with this scanner */ SANE_Byte ipu_id; /* Image Processing Unit Identification * bits 7:2 Reserved * bit 1 0:Extended board not mounted * 1:Extended board is mounted * bit 0 0:IPU is not mounted * 1:IPU is mounted * It should always be 0 with this scanner */ SANE_Byte imagecomposition; /* indicates supported image data type. * This is set to 0x37 * bit0 => Line art supported ? 1:0 * bit1 => Dither supported ? 1:0 * bit2 => Error Diffusion supported ? 1:0 * bit3 => Color supported ? 1:0 * bit4 => 4bits gray scale supported ? 1:0 * bit5 => 5-8bit gray scale supported ? 1:0 * bit6 => 5-8bit gray scale supported ? 1:0 * bit7 => Reserved */ SANE_Byte imagedataprocessing[2]; /* Image Data Processing Method * IPU installed ? 0x18 : 0x00 * Byte8 => White Framing ? 1:0 * Byte9 => Black Framing ? 1:0 * Byte10 => Edge Extraction ? 1:0 * Byte11 => Noise Removal ? 1:0 * Byte12 => Smoothing ? 1:0 * Byte13 => Line Bolding ? 0:1 * Byte14 => Reserved * Byte15 => Reserved */ SANE_Byte compression; /* Compression Method is set to 0x00 * bit0 => MH supported ? 1:0 * bit1 => MR supported ? 1:0 * bit2 => MMR supported ? 1:0 * bit3 => MH (byte boundary) supported ? 1:0 * bit4 => Reserved */ SANE_Byte markerrecognition; /* Marker Recognition Method is set to 0x00 * bit0 => Marker Recognition supported ? 1:0 * bits1-7 => Reserved */ SANE_Byte sizerecognition; /* Size Detection * bit0 => Size Detection Supported ? 1:0 * bits1-7 => Reserved */ SANE_Byte byte13; /* Reserved */ SANE_Byte xmaxoutputpixels[2]; /* X Maximum Output Pixel is set to 4960 (0x1360) * indicates maximum number of pixels in the main * scanning direction that can be output by scanner */ }; struct inquiry_jis_data { /* JIS INFORMATION VPD_IDENTIFIER_F0H */ SANE_Byte devtype; /* 7-5: peripheral qualifier, 4-0: peripheral device type */ SANE_Byte pagecode; SANE_Byte jisversion; SANE_Byte reserved1; SANE_Byte alloclen; /* page length: Set to 25 (19H) */ struct { SANE_Byte x[2]; /* Basic X Resolution: Set to 400 (01H,90H) */ SANE_Byte y[2]; /* Basic Y Resolution: Set to 400 (01H,90H) */ } BasicRes; SANE_Byte resolutionstep; /* 7-4: xstep, 3-0 ystep: Both set to 1 (11H) */ struct { SANE_Byte x[2]; /* Maximum X resolution: Set to 800 (03H,20H) */ SANE_Byte y[2]; /* Maximum Y resolution: Set to 800 (03H,20H) */ } MaxRes; struct { SANE_Byte x[2]; /* Minimum X resolution: Set to 100 (00H,64H) */ SANE_Byte y[2]; /* Minimum Y resolution */ } MinRes; SANE_Byte standardres[2]; /* Standard Resolution: bits 7-0: * byte18: 60, 75,100,120,150,160,180, 200 * byte19: 240,300,320,400,480,600,800,1200 */ struct { SANE_Byte width[4]; /* in pixels based on basic resolution. Set to 4787 (12B3H) */ SANE_Byte length[4]; /* maximum number of scan lines based on basic resolution. Set to 6803 (1A93H) */ } Window; SANE_Byte functions; /* This is set to 0EH: 0001110 * bit0: data overflow possible * bit1: line art support * bit2: dither support * bit3: gray scale support * bits7-4: reserved */ SANE_Byte reserved2; }; #define SMS_SP 0x01 /* Mask for Bit0 */ #define SMS_PF 0x10 /* Mask for Bit4 */ typedef struct scsi_mode_select_cmd { SANE_Byte opcode; /* 15H */ SANE_Byte byte1; /* 7-5:LUN; 4:PF; 2:Reserved; 1:SP * Save Page Bit must be 0 since pages cannot be saved * Page Format Bit must be 1 */ SANE_Byte reserved[2]; SANE_Byte len; /* Parameter List Length */ SANE_Byte control; /* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */ } SELECT; /* MODE SELECT PARAMETERS: * 0-n Mode Parameter Header * 0-n mode Block Descriptor (not used) * 0-n mode Page */ typedef struct scsi_mode_parameter_header { SANE_Byte data_len; /* Mode Data Length NOT USED so must be 0 */ SANE_Byte medium_type; /* Medium Type NOT USED so must be 0 */ SANE_Byte dev_spec; /* Device Specific Parameter NOT USED so must be 0 */ SANE_Byte blk_desc_len; /* Block Descriptor Length is set to 0 */ } MPHdr; typedef struct page { SANE_Byte code; /* 7:PS; 6:Reserved; 5-0:Page Code */ SANE_Byte len; /* set to 14 when MPC=02H and 6 otherwise */ SANE_Byte parameter[14]; /* either 14 or 6, so let's allow room for 14 */ } MPP; /* Mode Page Parameters */ typedef struct mode_pages { MPHdr hdr; /* Mode Page Header */ MPP page; /* Mode Page Parameters */ } MP; /* MODE PAGE CODES (MPC) */ /* 00H Reserved (Vendor Unique) */ /* 01H Reserved */ #define PAGE_CODE_CONNECTION 0x02 /* 02H Disconnect/Reconnect Parameters */ #define PAGE_CODE_SCANNING_MEASUREMENTS 0x03 /* 03H Scanning Measurement Parameters */ /* 04H-08H Reserved */ /* 09H-0AH Reserved (Not supported) */ /* 0BH-1FH Reserved */ #define PAGE_CODE_WHITE_BALANCE 0x20 /* 20H White Balance */ /* 21H Reserved (Vendor Unique) */ #define PAGE_CODE_LAMP_TIMER_SET 0x22 /* 22H Lamp Timer Set */ #define PAGE_CODE_SCANNING_SPEED 0x23 /* 23H Reserved (Scanning speed select) */ /* 24H Reserved (Vendor Unique) */ /* 25H Reserved (Vendor Unique) */ #define PAGE_CODE_ADF_CONTROL 0x26 /* 26H ADF Control */ #define PAGE_CODE_ENDORSER_CONTROL 0x27 /* 27H Endorser Control */ /* 28H Reserved (Marker Area Data Processing) */ /* 29H-2AH Reserved (Vendor Unique) */ #define PAGE_CODE_SCAN_WAIT_MODE 0x2B /* 2BH Scan Wait Mode (Medium Wait Mode) */ /* 2CH-3DH Reserved (Vendor Unique) */ #define PAGE_CODE_SERVICE_MODE_SELECT 0x3E /* 3EH Service Mode Select */ /* 3FH Reserved (Not Supported) */ typedef struct mode_page_connect { MPHdr hdr; /* Mode Page Header: 4 bytes */ SANE_Byte code; /* 7-6:Reserved; 5-0: 02H */ SANE_Byte len; /* Parameter Length 0EH */ SANE_Byte buffer_full_ratio; /* Ignored */ SANE_Byte buffer_empty_ratio; /* Ignored */ SANE_Byte bus_inactive_limit[2]; /* Ignored */ SANE_Byte disconnect_time_limit[2]; /* indicates minimum time to disconnect SCSI bus until reconnection. * It is expressed in 100msec increments; i.e. "1" for 100msec, "2" for 200msec * The maximum time is 2sec */ SANE_Byte connect_time_limit[2]; /* Ignored */ SANE_Byte maximum_burst_size[2]; /* expressed in 512 increments, i.e. "1" for 512 bytes, "2" for 1024 bytes * "0" indicates unlimited amount of data */ SANE_Byte dtdc; /* 7-2:Reserved; 1-0:DTDC indicates limitations of disconnection (bit1,bit0): * 00 (DEFAULT) Controlled by the other field in this page * 01 Once the command data transfer starts, the target never disconnects until * the whole data transfer completes * 10 Reserved * 11 Once the command data transfer starts, the target never disconnects until * the completion of the command */ SANE_Byte reserved[3]; } MP_CXN; /* 1 inch = 6 picas = 72 points = 25.4 mm */ #define DEFAULT_MUD 1200 /* WHY ? */ /* BASIC MEASUREMENT UNIT * 00H INCH * 01H MILLIMETER * 02H POINT * 03H-FFH Reserved */ enum BMU { INCHES = 0, MILLIMETERS, POINTS }; /* Basic Measurement Unit */ typedef struct mode_page_scanning_measurement { MPHdr hdr; /* Mode Page Header: 4 bytes */ SANE_Byte code; /* 7-6:Reserved; 5-0:Page Code (03H) */ SANE_Byte len; /* Parameter Length (06H) */ SANE_Byte bmu; /* Basic Measurement Unit */ SANE_Byte reserved0; SANE_Byte mud[2]; /* Measurement Unit Divisor * produces an error if 0 * mud is fixed to 1 for millimeter or point * point is default when scanner powers on */ SANE_Byte reserved1[2]; } MP_SMU; /* Scanning Measurement Units */ typedef struct mode_page_white_balance { MPHdr hdr; /* Mode Page Header: 4 bytes */ SANE_Byte code; /* 7-6:Reserved; 5-0:Page Code (03H) */ SANE_Byte len; /* Parameter Length (06H) */ SANE_Byte white_balance; /* "0" selects relative white mode (DEFAULT when power on) * "1" selects absolute white mode */ SANE_Byte reserved[5]; } MP_WhiteBal; /* White Balance */ typedef struct mode_page_lamp_timer_set { MPHdr hdr; /* Mode Page Header: 4 bytes */ SANE_Byte code; /* 7-6:Reserved; 5-0:Page Code (22H) */ SANE_Byte len; /* Parameter Length (06H) */ SANE_Byte time_on; /* indicates the time of lamp turned on */ SANE_Byte ignored[5]; } MP_LampTimer; /* Lamp Timer Set (Not supported ) */ typedef struct mode_page_adf_control { MPHdr hdr; /* Mode Page Header: 4 bytes */ SANE_Byte code; /* 7-6:Reserved; 5-0:Page Code (26H) */ SANE_Byte len; /* Parameter Length (06H) */ SANE_Byte adf_control; /* 7-2:Reserved; 1-0:ADF selection: * 00H Book Mode (DEFAULT when power on) * 01H Simplex ADF * 02H Duplex ADF * 03H-FFH Reserved */ SANE_Byte adf_mode_control; /* 7-3:Reserved; 2:Prefeed Mode Validity 1-0:Ignored * Prefeed Mode "0" means invalid, "1" means valid */ SANE_Byte medium_wait_timer; /* indicates time for scanner to wait for media. Scanner * will send CHECK on timeout. NOT SUPPORTED */ SANE_Byte ignored[3]; } MP_ADF; /* ADF Control */ typedef struct mode_page_endorser_control { MPHdr hdr; /* Mode Page Header: 4 bytes */ SANE_Byte code; /* 7-6:Reserved; 5-0:Page Code (27H) */ SANE_Byte len; /* Parameter Length (06H) */ SANE_Byte endorser_control; /* 7-3:Reserved; 2-0:Endorser Control: * 0H Disable Endorser (DEFAULT) * 1H Enable Endorser * 3H-7H Reserved */ SANE_Byte ignored[5]; } MP_EndCtrl; /* Endorser Control */ typedef struct mode_page_scan_wait { MPHdr hdr; /* Mode Page Header: 4 bytes */ SANE_Byte code; /* 7-6:Reserved; 5-0:Page Code (2BH) */ SANE_Byte len; /* Parameter Length (06H) */ SANE_Byte swm; /* 7-1:Reserved; 0:Scan Wait Mode * 0H Disable Medium wait mode * 1H Enable Medium wait mode * In Medium wait mode, when SCAN, READ, or LOAD (in ADF mode) is issued, * the scanner waits until start button is pressed on operation panel * When abort button is pressed, the command is cancelled * In ADF mode, when there are no originals on ADF, CHECK condition is * not given unless start button is pressed. */ SANE_Byte ignored[5]; } MP_SWM; /* Scan Wait */ typedef struct mode_page_service { /* Selectable when Send Diagnostic command is performed */ MPHdr hdr; /* Mode Page Header: 4 bytes */ SANE_Byte code; /* 7-6:Reserved; 5-0:Page Code (3EH) */ SANE_Byte len; /* Parameter Length (06H) */ SANE_Byte service; /* 7-1:Reserved; 0:Service Mode * "0" selects Self Diagnostics mode (DEFAULT when power on ) * "1" selects Optical Adjustment mode */ SANE_Byte ignored[5]; } MP_SRV; /* Service */ typedef struct scsi_mode_sense_cmd { SANE_Byte opcode; /* 1AH */ SANE_Byte dbd; /* 7-5:LUN; 4:Reserved; 3:DBD (Disable Block Desciption) set to "0"; 2-0:Reserved */ SANE_Byte pc; /* 7-6:PC; 5-0:Page Code * PC field indicates the type of data to be returned (bit7,bit6): * 00 Current Value (THIS IS THE ONLY VALUE WHICH WORKS!) * 01 Changeable Value * 10 Default Value * 11 Saved Value * * Page Code indicates requested page. (See PAGE_CODE defines) */ SANE_Byte reserved; SANE_Byte len; /* Allocation length */ SANE_Byte control; /* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */ } SENSE; /* MODE SENSE DATA FORMAT -- * The format of Sense Data to be returned is Mode Parameter Header + Page * see struct scsi_mode_parameter_header * struct mode_pages */ /* 1-3-8 SCAN command */ typedef struct scsi_start_scan_cmd { SANE_Byte opcode; /* 1BH */ SANE_Byte byte1; /* 7-5:LUN; 4-0:Reserved */ SANE_Byte page_code; SANE_Byte reserved; SANE_Byte len; /* Transfer Length * Length of Window List in bytes * Since scanner supports up to 2 windows, len is 1 or 2 */ SANE_Byte control; /* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */ } START_SCAN; /* 1-3-9 RECEIVE DIAGNOSTIC * 1-3-10 SEND DIAGNOSTIC */ /* BinaryFilter Byte * bit7: Noise Removal '1':removal * bit6: Smoothing '1':smoothing * bits5-2: ignored * bits1-0: Noise Removal Matrix * 00:3x3 01:4x4 * 10:5x5 11:Reserved */ struct val_id { SANE_Byte val; SANE_Byte id; }; static SANE_String_Const noisematrix_list[] = { "None", "3x3", "4x4", "5x5", NULL }; struct val_id noisematrix[] = { {0x03, 0}, /* dummy value for "None" */ {0x00, 1}, {0x01, 2}, {0x02, 3} }; static SANE_String_Const grayfilter_list[] = { "none", "averaging", "MTF correction", NULL }; struct val_id grayfilter[] = { {0x00, 0}, {0x01, 1}, {0x03, 2} }; static SANE_String_Const paddingtype_list[] = { "Pad with 0's to byte boundary", "Pad with 1's to byte boundary", "Truncate to byte boundary", NULL }; enum paddingtypes { PAD_WITH_ZEROS = 0x01, PAD_WITH_ONES, TRUNCATE }; struct val_id paddingtype[] = { {PAD_WITH_ZEROS, 0}, {PAD_WITH_ONES, 1}, {TRUNCATE, 2} }; #define NPADDINGTYPES 3 #define PADDINGTYPE_DEFAULT 2 static SANE_String_Const auto_separation_list[] = { "Off", "On", "User", NULL }; struct val_id auto_separation[] = { {0x00, 0}, {0x01, 1}, {0x80, 2} }; static SANE_String_Const auto_binarization_list[] = { "Off", "On", "Enhancement of light characters", "Removal of background color", "User", NULL }; struct val_id auto_binarization[] = { {0x00, 0}, {0x01, 1}, {0x02, 2}, {0x03, 3}, {0x80, 4} }; enum imagecomposition { LINEART = 0x00, HALFTONE, GRAYSCALE }; enum halftonecode { DITHER = 0x02, ERROR_DIFFUSION }; static SANE_String_Const halftone_code[] = { "Dither", "Error Diffusion", NULL }; static SANE_String_Const halftone_pattern_list[] = { "8x4, 45 degree", "6x6, 90 degree", "4x4, spiral", "8x8, 90 degree", "70 lines", "95 lines", "180 lines", "16x8, 45 degree", "16x16, 90 degree", "8x8, Bayer", "User #1", "User #2", NULL }; struct val_id halftone[] = { {0x01, 1}, {0x02, 2}, {0x03, 3}, {0x04, 4}, {0x05, 5}, {0x06, 6}, {0x07, 7}, {0x08, 9}, {0x09, 9}, {0x0A, 10}, {0x80, 11}, {0x81, 12} }; #if 0 static struct { SANE_Byte code; char *type; } compression_types[] = { { 0x00, "No compression"}, { 0x01, "CCITT G3, 1-dimensional (MH)"}, { 0x02, "CCITT G3, 2-dimensional (MR)"}, { 0x03, "CCITT G4, 2-dimensional (MMR)"}, /* 04H-0FH Reserved * 10H Reserved (not supported) * 11H-7FH Reserved */ { 0x80, "CCITT G3, 1-dimensional (MH) Padding with 0's to byte boundary"} /* 80H-FFH Reserved (Vendor Unique) */ }; static struct { SANE_Byte code; char *argument; } compression_argument[] = { /* 00H Reserved */ /* 01H Reserved */ { 0x02, "K factor-0~255"} /* 03H Reserved */ /* 04H-0FH Reserved */ /* 10H Reserved */ /* 11H-7FH Reserved */ /* 80H Reserved */ /* 80H-FFH Reserved */ }; #endif #define GAMMA_NORMAL 0x00 #define GAMMA_SOFT 0x01 #define GAMMA_SHARP 0x02 #define GAMMA_LINEAR 0x03 #define GAMMA_USER 0x08 /* 04H-07H Reserved */ /* 09H-0FH Reserved */ static SANE_String gamma_list[6] = { "Normal", "Soft", "Sharp", "Linear", "User", NULL }; /* 1-3-11 SET WINDOW command */ struct window_section { /* 32 bytes */ SANE_Byte sef; /*byte1 7-2:ignored 1:SEF '0'-invalid section; '1'-valid section */ SANE_Byte ignored0; SANE_Byte ulx[4]; SANE_Byte uly[4]; SANE_Byte width[4]; SANE_Byte length[4]; SANE_Byte binary_filtering; SANE_Byte ignored1; SANE_Byte threshold; SANE_Byte ignored2; SANE_Byte image_composition; SANE_Byte halftone_id; SANE_Byte halftone_code; SANE_Byte ignored3[7]; }; /* 1-3-11 SET WINDOW COMMAND * Byte0: 24H * Byte1: 7-5: LUN; 4-0: Reserved * Byte2-5: Reserved * Byte6-8: Transfer Length * Byte9: 7-6: Vendor Unique; 5-2: Reserved; 1: Flag; 0: Link * * Transfer length indicates the byte length of Window Parameters (Set Window Data Header + * Window Descriptor Bytes transferred from the initiator in the DATA OUT PHASE * The scanner supports 2 windows, so Transfer Length is 648 bytes: * Set Window Header 8 bytes + Window Descriptor Bytes 640 (320*2) bytes). * If data length is longer than 648 bytes only the first 648 bytes are valid, The remainng data is ignored. * If data length is shorter than 648 only the specified byte length is valid data. * * * WINDOW DATA HEADER * Byte0-5: Reserved * Byte6-7: Window Descriptor Length (WDL) * WDL indicates the number of bytes of one Window Descriptor Bytes which follows. * In this scanner, this value is 640 since it supports 2 windows. * * WINDOW DESCRIPTOR BYTES */ #define HS2P_WINDOW_DATA_SIZE 640 struct hs2p_window_data { /* HS2P_WINDOW_DATA_FORMAT */ SANE_Byte window_id; /* 0: Window Identifier */ SANE_Byte auto_bit; /* 1: 1-1:Reserved; 0:Auto */ SANE_Byte xres[2]; /* 2-3: X-Axis Resolution 100-800dpi in 1dpi steps */ SANE_Byte yres[2]; /* 4-5: Y-Axis Resolution 100-800dpi in 1dpi steps */ SANE_Byte ulx[4]; /* 6-9: X-Axis Upper Left */ SANE_Byte uly[4]; /* 10-13: Y-Axis Upper Left */ SANE_Byte width[4]; /* 14-17: Window Width */ SANE_Byte length[4]; /* 18-21: Window Length */ SANE_Byte brightness; /* 22: Brightness [0-255] dark-light 0 means default value of 128 */ SANE_Byte threshold; /* 23: Threshold [0-255] 0 means default value of 128 */ SANE_Byte contrast; /* 24: Contrast [0-255] low-high 0 means default value of 128 */ SANE_Byte image_composition; /* 25: Image Composition * 00H Lineart * 01H Dithered Halftone * 02H Gray scale */ SANE_Byte bpp; /* 26: Bits Per Pixel */ SANE_Byte halftone_code; /* 27: Halftone Code * 00H-01H Reserved * 02H Dither (partial Dot) * 03H Error Diffusion * 04H-07H Reserved */ SANE_Byte halftone_id; /* 28: Halftone ID * 00H Reserved * 01H 8x4, 45 degree * 02H 6x6, 90 degree * 03H 4x4, Spiral * 04H 8x8, 90 degree * 05H 70 lines * 06H 95 lines * 07H 180 lines * 08H 16x8, 45 degree * 09H 16x16, 90 degree * 0AH 8x8, Bayer * 0Bh-7FH Reserved * 80H Download #1 * 81H Download #2 * 82H-FFH Reserved */ SANE_Byte byte29; /* 29: 7: RIF (Reverse Image Format) bit inversion * Image Composition field must be lineart or dithered halftone * RIF=0: White=0 Black=1 * RIF=1: White=1 Black=0 * 6-3: Reserved; * 2-0: Padding Type: * 00H Reserved * 01H Pad with 0's to byte boundary * 02H Pad with 1's to byte boundary * 03H Truncate to byte boundary * 04H-FFH Reserved */ SANE_Byte bit_ordering[2]; /* 30-31: Bit Ordering: Default 0xF8 * 0: 0=>output from bit0 of each byte; 1=>output from bit7 * 1: 0=>output from LSB; 1=>output from MSB * 2: 0=>unpacked 4 bits gray; 1=>Packed 4 bits gray * 3: 1=>Bits arrangment from LSB in grayscale; 0=>from MSB * 4-6: reserved * 7: 1=>Mirroring; 0=>Normal output * 8-15: reserved */ SANE_Byte compression_type; /* 32: Compression Type: Unsupported in IS450 */ SANE_Byte compression_arg; /* 33: Compression Argument: Unsupported in IS450 */ SANE_Byte reserved2[6]; /* 34-39: Reserved */ SANE_Byte ignored1; /* 40: Ignored */ SANE_Byte ignored2; /* 41: Ignored */ SANE_Byte byte42; /* 42: 7: MRIF: Grayscale Reverse Image Format * MRIF=0: White=0 Black=1 * MRIF=1: White=1 Black=0 * 6-4: Filtering: for Grayscale * 000 No filter * 001 Averaging * 010 Reserved * 011 MTF Correction * 100 Reserved * 110 Reserved * 111 Reserved * 3-0: Gamma ID * 00H Normal * 01H Soft * 02H Sharp * 03H Linear * 04H-07H Reserved * 08H Download table * 09H-0FH Reserved */ SANE_Byte ignored3; /* 43: Ignored */ SANE_Byte ignored4; /* 44: Ignored */ SANE_Byte binary_filtering; /* 45: Binary Filtering * 0-1: Noise Removal Matrix: * 00: 3x3 * 01: 4x4 * 10: 5x5 * 11: Reserved * 5-2: Ignored * 6: Smoothing Flag * 7: Noise Removal Flag * * Smoothing and Noise removal can be set when option IPU is installed * Setting is ignored for reverse side because optional IPU is not valid * for reverse side scanning */ /* * The following is only available when IPU is installed: * SECTION, Automatic Separation, Automatic Binarization * 46-319 is ignored for Window 2 */ SANE_Byte ignored5; /* 46: Ignored */ SANE_Byte ignored6; /* 47: Ignored */ SANE_Byte automatic_separation; /* 48: Automatic Separation * 00H OFF * 01H Default * 02H-7FH Reserved * 80H Download table * 91H-FFH Reserved */ SANE_Byte ignored7; /* 49: Ignored */ SANE_Byte automatic_binarization; /* 50: Automatic Binarization * 00H OFF * 01H Default * 02H Enhancement of light characters * 03H Removal of background color * 04H-7FH Reserved * 80H Download table * 81H-FFH Reserved */ SANE_Byte ignored8[13]; /* 51-63: Ignored */ struct window_section sec[8]; /* Each window can have multiple sections, each of 32 bytes long * 53-319: = 256 bytes = 8 sections of 32 bytes * IS450 supports up to 4 sections, * IS420 supports up to 6 sections */ }; struct set_window_cmd { SANE_Byte opcode; /* 24H */ SANE_Byte byte2; /* 7-5:LUN 4-0:Reserve */ SANE_Byte reserved[4]; /* Reserved */ SANE_Byte len[3]; /* Transfer Length */ SANE_Byte control; /* 76543210 * XX Vendor Unique * XXXX Reserved * X Flag * X Link */ }; struct set_window_data_hdr { SANE_Byte reserved[6]; SANE_Byte len[2]; }; typedef struct set_window_data { struct set_window_data_hdr hdr; struct hs2p_window_data data[2]; } SWD; /* 1-3-12 GET WINDOW command */ struct get_window_cmd { SANE_Byte opcode; SANE_Byte byte1; /* 7-5: LUN; * 4-1:Reserved; * 0:Single bit is 0 */ SANE_Byte reserved[3]; SANE_Byte win_id; /* Window ID is either 0 or 1 */ SANE_Byte len[3]; /* Transfer Length */ SANE_Byte control; /* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */ }; /* The data format to be returned is Get Window Data header + Window Descriptor Bytes * The format of Window Descriptor Bytes is the same as that for SET WINDOW */ struct get_window_data_hdr { SANE_Byte data_len[2]; /* Window Data Length indicates byte len of data which follows less its own 2 bytes */ SANE_Byte reserved[4]; SANE_Byte desc_len[2]; /* Window Descriptor Length indicates byte length of one Window Descriptor which is 640 */ }; typedef struct get_window_data { struct get_window_data_hdr hdr; struct hs2p_window_data data[2]; } GWD; /* READ/SEND DATA TYPE CODES */ /* DATA TYPE CODES (DTC): */ #define DATA_TYPE_IMAGE 0x00 /* 01H Reserved (Vendor Unique) */ #define DATA_TYPE_HALFTONE 0x02 #define DATA_TYPE_GAMMA 0x03 /*04H-7FH Reserved */ #define DATA_TYPE_ENDORSER 0x80 #define DATA_TYPE_SIZE 0x81 /* 82H Reserved */ /* 83H Reserved (Vendor Unique) */ #define DATA_TYPE_PAGE_LEN 0x84 #define DATA_TYPE_MAINTENANCE 0x85 #define DATA_TYPE_ADF_STATUS 0x86 /* 87H Reserved (Skew Data) */ /* 88H-91H Reserved (Vendor Unique) */ /* 92H Reserved (Scanner Extension I/O Access) */ /* 93H Reserved (Vendor Unique) */ /* 94H-FFH Reserved (Vendor Unique) */ #define DATA_TYPE_EOL -1 /* va_end */ /* DATA TYPE QUALIFIER CODES when DTC=93H */ #define DTQ 0x00 /* ignored */ #define DTQ_AUTO_PHOTOLETTER 0x00 /* default */ #define DTQ_DYNAMIC_THRESHOLDING 0x01 /* default */ #define DTQ_LIGHT_CHARS_ENHANCEMENT 0x02 #define DTQ_BACKGROUND_REMOVAL 0x03 /* 04H-7FH Reserved */ #define DTQ_AUTO_PHOTOLETTER_DOWNLOAD_TABLE 0x80 #define DTQ_DYNAMIC_THRESHOLD_DOWNLOAD_TABLE 0x81 /* 82H-FFH Reserved */ /* 1-3-13 READ command */ /* 1-3-14 SEND command */ struct scsi_rs_scanner_cmd { SANE_Byte opcode; /* READ=28H SEND=2AH */ SANE_Byte byte1; /* 7-5:LUN; 4-0:Reserved */ SANE_Byte dtc; /* Data Type Code: See DTC DEFINES above */ SANE_Byte reserved; SANE_Byte dtq[2]; /* Data Type Qualifier valid only for DTC 02H,03H,93H */ SANE_Byte len[3]; /* Transfer Length */ SANE_Byte control; /* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */ }; /* * Data Format for Image Data * Non-compressed: {first_line, second_line, ... nth_line} * MH/MR Compression: {EOL, 1st_line_compressed, EOL, 2nd_line_compressed,..., EOL, last_line_compressed, EOL,EOL,EOL,EOL,EOL,EOL * where EOL = 000000000001 * MMR Compression: = {1st_line_compressed, 2nd_line_compressed,...,last_line_compressed, EOL,EOL} * * Normal Binary Output: MSB-LSB 1stbytes,2nd,3rd...Last * Mirror Binary Output: MSB-LSB Last,...2nd,1st * * Normal Gray Output MSB-LSB: 1st,2nd,3rd...Last * 4 bit/pixel gray: [32103210] * 8 bit/pixel gray: [76543210] * Mirror Gray Output MSB-LSB Last,...2nd,1st * * * HALFTONE MASK DATA: 1byte(row,col) ={2,3,4,6,8,16} * (r0,c0), (r0,c1), (r0,c2)...(r1,c0),(r1,c2)...(rn,cn) * * GAMMA FUNCTION TABLE Output (D) vs. Input (I)(0,0)=(Black,Black) (255,255)=(White,White) * The number of gray scale M = 8 * 2^8 = 256 total table data * D0 = D(I=0), D1=D(I=1)...D255=D(I=255) * DATA= [1st byte ID],[2nd byte M],[D0],[D1],...[D255] * * ENDORSER DATA: 1st_char, 2nd_char,...last_char * * SIZE DATA: 1byte: 4bits-Start Position; 4bits-Width Info * * PAGE LENGTH: 5bytes: 1st byte is MSB, Last byte is LSB */ typedef struct maintenance_data { SANE_Byte nregx_adf; /* number of registers of main-scanning in ADF mode */ SANE_Byte nregy_adf; /* number of registers of sub-scanning in ADF mode */ SANE_Byte nregx_book; /* number of registers of main-scanning in Book mode */ SANE_Byte nregy_book; /* number of registers of sub-scanning in Book mode */ SANE_Byte nscans_adf[4]; /* Number of scanned pages in ADF mode */ SANE_Byte nscans_book[4]; /* Number of scanned pages in Book mode */ SANE_Byte lamp_time[4]; /* Lamp Time */ SANE_Byte eo_odd; /* Adjustment data of E/O balance in black level (ODD) */ SANE_Byte eo_even; /* Adjustment data of E/O balance in black level (EVEN) */ SANE_Byte black_level_odd; /* The adjustment data in black level (ODD) */ SANE_Byte black_level_even; /* The adjustment data in black level (EVEN) */ SANE_Byte white_level_odd[2]; /* The adjustment data in white level (ODD) */ SANE_Byte white_level_even[2]; /* The adjustment data in white level (EVEN) */ SANE_Byte first_adj_white_odd[2]; /* First adjustment data in white level (ODD) */ SANE_Byte first_adj_white_even[2]; /* First adjustment data in white level (EVEN) */ SANE_Byte density_adj; /* Density adjustment */ SANE_Byte nregx_reverse; /* The number of registers of main-scanning of the reverse-side ADF */ SANE_Byte nregy_reverse; /* The number of registers of sub-scanning of the reverse-side ADF */ SANE_Byte nscans_reverse_adf[4]; /* Number of scanned pages of the reverse side ADF */ SANE_Byte reverse_time[4]; /* The period of lamp turn on of the reverse side */ SANE_Byte nchars[4]; /* The number of endorser characters */ SANE_Byte reserved0; SANE_Byte reserved1; SANE_Byte reserved2; SANE_Byte zero[2]; /* All set as 0 */ } MAINTENANCE_DATA; /* ADF status 1byte: * 7-3:Reserved; * 2:Reserved; * 1: '0'-ADF cover closed; '1'-ADF cover open * 0: '0'-Document on ADF; '1'-No document on ADF * */ struct IPU { SANE_Byte byte0; /* 7-4:Reserved; 3:White mode; 2:Reserved; 1-0: Gamma Table Select */ SANE_Byte byte1; /* 7-2:Reserved; 1-0: MTF Filter Select */ }; struct IPU_Auto_PhotoLetter { /* Halftone Separations for each level * 256 steps of relative value with 0 the sharpest and 255 the softest * The relation of strength is Strength2 > Strength3 > Strength4 ... */ struct { SANE_Byte level[6]; } halftone_separation[2]; /* 7-2:Reversed 1-0:Halftone * 00 Default * 01 Peak Detection Soft * 10 Peak Detection Sharp * 11 Don't Use */ SANE_Byte byte12; SANE_Byte black_correction; /* Black correction strength: 0-255 sharpest-softest */ SANE_Byte edge_sep[4]; /* Edge Separation strengths: 0-255 sharpest-softest 1-4 */ SANE_Byte white_background_sep_strength; /* 0-255 sharpest-softest */ SANE_Byte byte19; /* 7-1:Reversed; 0:White mode '0'-Default; '1'-Sharp */ SANE_Byte byte20; /* 7-1:Reversed; 0:Halftone mode '0'-widen dots; '1'-Default */ SANE_Byte halftone_sep_levela; SANE_Byte halftone_sep_levelb; SANE_Byte byte23; /* 7-4:Reversed; 3-0:Adjustment of separation level: usually fixed to 0 */ /* 7-4:Reversed; 3-0:Judge Conditions Select * 0XXX Black Correction OFF 1XXX Black Correction ON * X0XX Halftone Separation OFF X1XX Halftone Separation ON * XX0X White Separation OFF XX1X White Separation ON * XXX0 Edge Separation OFF XXX1 Edge Separation ON */ SANE_Byte byte24; /* 7-4:Filter A; 3-0:Filter B * FilterA: 16 types are valid from 0000 to 1111 * FilterB: 0000 to 1110 are valid; 1111 is not valid */ SANE_Byte MTF_correction; /* 7-4:Filter A; 3-0:Filter B * 0000(soft) to 0111(sharp) are valid; 1000 to 1111 are invalid */ SANE_Byte MTF_strength; /* 7-4:Filter A; 3-0:Filter B * slightly adjusts the strength of the filters */ SANE_Byte MTF_adjustment; /* 7-4:Reserved; 3-0: smoothing filter select * 14 kinds are valid from 0000 to 1101; 1110 to 1111 are invalid */ SANE_Byte smoothing; /* 7-2:Reversed; 1-0: Filter Select * 10 MTF Correction Select * 11 Smoothing Select * from 00 to 01 are not valid and basically it is set as 10 */ SANE_Byte byte29; /* 7-4:Reserved; 3-0: MTF Correction Filter C * 16 kinds are valid from 0000 to 1111 */ SANE_Byte MTF_correction_c; /* 7-3:Reserved; 2-0: MTF Correction Filter strength C * 000(soft) to 111(sharp) are valid */ SANE_Byte MTF_strength_c; }; /* struct IPU_Dynamic { to be implemented }; sensor data */ /* for object_position command */ #define OBJECT_POSITION_UNLOAD 0 #define OBJECT_POSITION_LOAD 1 /* 1-3-15 OBJECT POSITION */ typedef struct scsi_object_position_cmd { SANE_Byte opcode; /* 31H */ SANE_Byte position_func; /* 7-5:LUN; 4-3:Reserved; 2-0:Position Function (bit2,bit1,bit0): * 000 Unload Object (NO CHECK ERROR even though no document on ADF) * 001 Load Object (NO CHECK ERROR even though document already fed to start position) * 010 Absolute Positioning in Y-axis. Not Supported in this scanner * 3H-7H Reserved */ SANE_Byte count[3]; /* Reserved */ SANE_Byte reserved[4]; SANE_Byte control; /* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */ } POSITION; /* 1-3-16 GET DATA BUFFER STATUS */ typedef struct scsi_get_data_buffer_status_cmd { SANE_Byte opcode; /* 34H */ SANE_Byte wait; /* 7-5:LUN; 4-1:Reserved; 0: Wait bit is "0" */ SANE_Byte reserved[5]; SANE_Byte len[2]; /* Allocation Length */ SANE_Byte control; /* 7-6:Vendor Unique; 5-2:Reserved; 1:Flag; 0:Link */ } GET_DBS_CMD; typedef struct scsi_status_hdr { SANE_Byte len[3]; /* Data Buffer Status Length */ SANE_Byte block; /* 7-1:Reserved; 0:Block bit is 0 */ } STATUS_HDR; typedef struct scsi_status_data { SANE_Byte wid; /* window identifier is 0 or 1 */ SANE_Byte reserved; SANE_Byte free[3]; /* Available Space Data `Buffer */ SANE_Byte filled[3]; /* Scan Data Available (Filled Data Bufferj) */ } STATUS_DATA; /* BUFFER STATUS DATA FORMAT */ typedef struct scsi_buffer_status { STATUS_HDR hdr; STATUS_DATA data; } STATUS_BUFFER; sane-backends-1.0.27/backend/sp15c.h0000664000175000017500000002133712775312261013731 00000000000000#ifndef SP15C_H #define SP15C_H static const char RCSid_h[] = "$Header$"; /* sane - Scanner Access Now Easy. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Fujitsu ScanParner 15c flatbed/ADF scanners. It was derived from the COOLSCAN driver. Written by Randolph Bentson */ /* ------------------------------------------------------------------------- */ /* * $Log$ * Revision 1.8 2008/05/15 12:50:24 ellert-guest * Fix for bug #306751: sanei-thread with pthreads on 64 bit * * Revision 1.7 2005-09-19 19:57:48 fzago-guest * Replaced __unused__ with __sane_unused__ to avoid a namespace conflict. * * Revision 1.6 2004/11/13 19:53:04 fzago-guest * Fixes some warnings. * * Revision 1.5 2004/05/23 17:28:56 hmg-guest * Use sanei_thread instead of fork() in the unmaintained backends. * Patches from Mattias Ellert (bugs: 300635, 300634, 300633, 300629). * * Revision 1.4 2003/12/27 17:48:38 hmg-guest * Silenced some compilation warnings. * * Revision 1.3 2000/08/12 15:09:42 pere * Merge devel (v1.0.3) into head branch. * * Revision 1.1.2.3 2000/03/14 17:47:14 abel * new version of the Sharp backend added. * * Revision 1.1.2.2 2000/01/26 03:51:50 pere * Updated backends sp15c (v1.12) and m3096g (v1.11). * * Revision 1.7 2000/01/05 05:22:26 bentson * indent to barfable GNU style * * Revision 1.6 1999/12/03 20:57:13 bentson * add MEDIA CHECK command * * Revision 1.5 1999/11/24 15:55:56 bentson * remove some debug stuff; rename function * * Revision 1.4 1999/11/23 18:54:26 bentson * tidy up function types for constraint checking * * Revision 1.3 1999/11/23 06:41:54 bentson * add debug flag to interface * * Revision 1.2 1999/11/22 18:15:20 bentson * more work on color support * * Revision 1.1 1999/11/19 15:09:08 bentson * cribbed from m3096g * */ static const SANE_Device **devlist = NULL; static int num_devices; static struct sp15c *first_dev; enum sp15c_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_SOURCE, OPT_MODE, OPT_TYPE, OPT_X_RES, OPT_Y_RES, OPT_PRESCAN, OPT_PREVIEW_RES, OPT_GEOMETRY_GROUP, OPT_TL_X, /* in mm/2^16 */ OPT_TL_Y, /* in mm/2^16 */ OPT_BR_X, /* in mm/2^16 */ OPT_BR_Y, /* in mm/2^16 */ OPT_ENHANCEMENT_GROUP, OPT_AVERAGING, OPT_BRIGHTNESS, OPT_THRESHOLD, OPT_ADVANCED_GROUP, OPT_PREVIEW, /* must come last: */ NUM_OPTIONS }; struct sp15c { struct sp15c *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; SANE_Device sane; char vendor[9]; char product[17]; char version[5]; char *devicename; /* name of the scanner device */ int sfd; /* output file descriptor, scanner device */ int pipe; int reader_pipe; int scanning; /* "in progress" flag */ int autofeeder; /* detected */ int use_adf; /* requested */ SANE_Pid reader_pid; /* child is running */ int prescan; /* ??? */ /***** terms for "set window" command *****/ int x_res; /* resolution in */ int y_res; /* pixels/inch */ int tl_x; /* top left position, */ int tl_y; /* in inch/1200 units */ int br_x; /* bottom right position, */ int br_y; /* in inch/1200 units */ int brightness; int threshold; int contrast; int composition; int bitsperpixel; /* at the scanner interface */ int halftone; int rif; int bitorder; int compress_type; int compress_arg; int vendor_id_code; int outline; int emphasis; int auto_sep; int mirroring; int var_rate_dyn_thresh; int white_level_follow; int subwindow_list; int paper_size; int paper_width_X; int paper_length_Y; /***** end of "set window" terms *****/ /* buffer used for scsi-transfer */ unsigned char *buffer; unsigned int row_bufsize; }; /* ------------------------------------------------------------------------- */ #define length_quant SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0)) #define mmToIlu(mm) ((mm) / length_quant) #define iluToMm(ilu) ((ilu) * length_quant) #define SP15C_CONFIG_FILE "sp15c.conf" /* ------------------------------------------------------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle); SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking); SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp); const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info); SANE_Status sane_start (SANE_Handle handle); SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len); void sane_cancel (SANE_Handle h); void sane_close (SANE_Handle h); void sane_exit (void); /* ------------------------------------------------------------------------- */ static SANE_Status attach_scanner (const char *devicename, struct sp15c **devp); static SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg); static int request_sense_parse (u_char * sensed_data); static SANE_Status sp15c_identify_scanner (struct sp15c *s); static SANE_Status sp15c_do_inquiry (struct sp15c *s); static SANE_Status do_scsi_cmd (int fd, unsigned char *cmd, int cmd_len, unsigned char *out, size_t out_len); static void hexdump (int level, char *comment, unsigned char *p, int l); static SANE_Status init_options (struct sp15c *scanner); static int sp15c_check_values (struct sp15c *s); static int sp15c_grab_scanner (struct sp15c *s); static int sp15c_free_scanner (struct sp15c *s); static int wait_scanner (struct sp15c *s); static int __sane_unused__ sp15c_object_position (struct sp15c *s); static SANE_Status do_cancel (struct sp15c *scanner); static void swap_res (struct sp15c *s); static int __sane_unused__ sp15c_object_discharge (struct sp15c *s); static int sp15c_set_window_param (struct sp15c *s, int prescan); static size_t max_string_size (const SANE_String_Const strings[]); static int sp15c_start_scan (struct sp15c *s); static int reader_process (void *scanner); static SANE_Status do_eof (struct sp15c *scanner); static int pixels_per_line (struct sp15c *s); static int lines_per_scan (struct sp15c *s); static int bytes_per_line (struct sp15c *s); static void sp15c_trim_rowbufsize (struct sp15c *s); static int sp15c_read_data_block (struct sp15c *s, unsigned int length); static SANE_Status attach_one (const char *name); static void adjust_width (struct sp15c *s, SANE_Int * info); static SANE_Status apply_constraints (struct sp15c *s, SANE_Int opt, SANE_Int * target, SANE_Word * info); static int sp15c_media_check (struct sp15c *s); #endif /* SP15C_H */ sane-backends-1.0.27/backend/magicolor.c0000664000175000017500000024102712775312261014745 00000000000000/* * magicolor.c - SANE library for Magicolor scanners. * * (C) 2010 Reinhold Kainhofer * * Based on the epson2 sane backend: * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for additional copyrights. * Copyright (C) 2006-10 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define MAGICOLOR_VERSION 0 #define MAGICOLOR_REVISION 0 #define MAGICOLOR_BUILD 1 /* debugging levels: * * 127 mc_recv buffer * 125 mc_send buffer * 35 fine-grained status and progress * 30 sane_read * 25 setvalue, getvalue, control_option * 20 low-level (I/O) mc_* functions * 15 mid-level mc_* functions * 10 high-level cmd_* functions * 7 open/close/attach * 6 print_params * 5 basic functions * 3 status info and progress * 2 scanner info and capabilities * 1 errors & warnings */ #include "sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #if HAVE_LIBSNMP #include #include #include #include #endif #include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_tcp.h" #include "../include/sane/sanei_udp.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" #include "magicolor.h" #define min(x,y) (((x)<(y))?(x):(y)) /**************************************************************************** * Devices supported by this backend ****************************************************************************/ /* Scanner command type * | Start scan * | | Poll for error * | | | Stop scan? * | | | | Query image parameters * | | | | | set scan parameters * | | | | | | Get status? * | | | | | | | Read scanned data * | | | | | | | | Unknown * | | | | | | | | | Unknown * | | | | | | | | | | Net wrapper command type * | | | | | | | | | | | Net Welcome * | | | | | | | | | | | | Net Lock * | | | | | | | | | | | | | Net Lock ACK * | | | | | | | | | | | | | | Net Unlock * | | | | | | | | | | | | | | | */ static struct MagicolorCmd magicolor_cmd[] = { {"mc1690mf", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03}, {"mc4690mf", CMD, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x12, NET, 0x00, 0x01, 0x02, 0x03}, }; static SANE_Int magicolor_default_resolutions[] = {150, 300, 600}; static SANE_Int magicolor_default_depths[] = {1,8}; static struct MagicolorCap magicolor_cap[] = { /* KONICA MINOLTA magicolor 1690MF, USB ID 0x123b:2089 */ { 0x2089, "mc1690mf", "KONICA MINOLTA magicolor 1690MF", "1.3.6.1.4.1.183341.1.1.2.1.32.3.2", -1, 0x85, 600, {150, 600, 0}, magicolor_default_resolutions, 3, /* 600 dpi max, 3 resolutions */ 8, magicolor_default_depths, /* color depth 8 default, 1 and 8 possible */ {1, 9, 0}, /* brightness ranges (TODO!) */ {0, SANE_FIX(0x13f8 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x1b9c * MM_PER_INCH / 600), 0}, /* FBF x/y ranges (TODO!) */ SANE_TRUE, SANE_FALSE, /* non-duplex ADF, x/y ranges (TODO!) */ {0, SANE_FIX(0x1390 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x20dc * MM_PER_INCH / 600), 0}, }, /* KONICA MINOLTA magicolor 4690MF, USB ID 0x132b:2079 */ { 0x2079, "mc4690mf", "KONICA MINOLTA magicolor 4690MF", "FIXME", /* FIXME: fill in the correct OID! */ 0x03, 0x85, 600, {150, 600, 0}, magicolor_default_resolutions, 3, /* 600 dpi max, 3 resolutions */ 8, magicolor_default_depths, /* color depth 8 default, 1 and 8 possible */ {1, 9, 0}, /* brightness ranges (TODO!) */ {0, SANE_FIX(0x13f8 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x1b9c * MM_PER_INCH / 600), 0}, /* FBF x/y ranges (TODO!) */ SANE_TRUE, SANE_TRUE, /* duplex ADF, x/y ranges (TODO!) */ {0, SANE_FIX(0x1390 * MM_PER_INCH / 600), 0}, {0, SANE_FIX(0x20dc * MM_PER_INCH / 600), 0}, }, }; static int MC_SNMP_Timeout = 2500; static int MC_Scan_Data_Timeout = 15000; static int MC_Request_Timeout = 5000; /**************************************************************************** * General configuration parameter definitions ****************************************************************************/ /* * Definition of the mode_param struct, that is used to * specify the valid parameters for the different scan modes. * * The depth variable gets updated when the bit depth is modified. */ static struct mode_param mode_params[] = { {0x00, 1, 1}, /* Lineart, 1 color, 1 bit */ {0x02, 1, 24}, /* Grayscale, 1 color, 24 bit */ {0x03, 3, 24} /* Color, 3 colors, 24 bit */ }; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; static const SANE_String_Const adf_mode_list[] = { SANE_I18N("Simplex"), SANE_I18N("Duplex"), NULL }; /* Define the different scan sources */ #define FBF_STR SANE_I18N("Flatbed") #define ADF_STR SANE_I18N("Automatic Document Feeder") /* * source list need one dummy entry (save device settings is crashing). * NOTE: no const - this list gets created while exploring the capabilities * of the scanner. */ static SANE_String_Const source_list[] = { FBF_STR, NULL, NULL, NULL }; /* Some utility functions */ static size_t max_string_size(const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; i++) { size = strlen(strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status attach_one_usb(SANE_String_Const devname); static SANE_Status attach_one_net(SANE_String_Const devname, unsigned int device); static void print_params(const SANE_Parameters params) { DBG(6, "params.format = %d\n", params.format); DBG(6, "params.last_frame = %d\n", params.last_frame); DBG(6, "params.bytes_per_line = %d\n", params.bytes_per_line); DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line); DBG(6, "params.lines = %d\n", params.lines); DBG(6, "params.depth = %d\n", params.depth); } /**************************************************************************** * Low-level Network communication functions ****************************************************************************/ #define MAGICOLOR_SNMP_SYSDESCR_OID ".1.3.6.1.2.1.1.1.0" #define MAGICOLOR_SNMP_SYSOBJECT_OID ".1.3.6.1.2.1.1.2.0" #define MAGICOLOR_SNMP_MAC_OID ".1.3.6.1.2.1.2.2.1.6.1" #define MAGICOLOR_SNMP_DEVICE_TREE ".1.3.6.1.4.1.18334.1.1.1.1.1" /* We don't have a packet wrapper, which holds packet size etc., so we don't have to use a *read_raw and a *_read function... */ static int sanei_magicolor_net_read(struct Magicolor_Scanner *s, unsigned char *buf, size_t wanted, SANE_Status * status) { size_t size, read = 0; struct pollfd fds[1]; *status = SANE_STATUS_GOOD; /* poll for data-to-be-read (using a 5 seconds timeout) */ fds[0].fd = s->fd; fds[0].events = POLLIN; if (poll (fds, 1, MC_Request_Timeout) <= 0) { *status = SANE_STATUS_IO_ERROR; return read; } while (read < wanted) { size = sanei_tcp_read(s->fd, buf + read, wanted - read); if (size == 0) break; read += size; } if (read < wanted) *status = SANE_STATUS_IO_ERROR; return read; } /* We need to optionally pad the buffer with 0x00 to send 64-byte chunks. On the other hand, the 0x04 commands don't need this, so we need two functions, one *_write function that pads the buffer and then calls *_write_raw */ static int sanei_magicolor_net_write_raw(struct Magicolor_Scanner *s, const unsigned char *buf, size_t buf_size, SANE_Status *status) { sanei_tcp_write(s->fd, buf, buf_size); /* TODO: Check whether sending failed... */ *status = SANE_STATUS_GOOD; return buf_size; } static int sanei_magicolor_net_write(struct Magicolor_Scanner *s, const unsigned char *buf, size_t buf_size, SANE_Status *status) { size_t len = 64; unsigned char *new_buf = malloc(len); if (!new_buf) { *status = SANE_STATUS_NO_MEM; return 0; } memset(new_buf, 0x00, len); if (buf_size > len) buf_size = len; if (buf_size) memcpy(new_buf, buf, buf_size); return sanei_magicolor_net_write_raw (s, new_buf, len, status); } static SANE_Status sanei_magicolor_net_open(struct Magicolor_Scanner *s) { SANE_Status status; unsigned char buf[5]; ssize_t read; struct timeval tv; struct MagicolorCmd *cmd = s->hw->cmd; tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); DBG(1, "%s\n", __func__); /* the scanner sends a kind of welcome msg */ read = sanei_magicolor_net_read(s, buf, 3, &status); if (read != 3) return SANE_STATUS_IO_ERROR; if (buf[0] != cmd->net_wrapper_cmd || buf[1] != cmd->net_welcome) { DBG (32, "Invalid welcome message received, Expected 0x%02x %02x 00, but got 0x%02x %02x %02x\n", cmd->net_wrapper_cmd, cmd->net_welcome, buf[0], buf[1], buf[2]); return SANE_STATUS_IO_ERROR; } else if (buf[2] != 0x00) { /* TODO: Handle response "04 00 01", indicating an error! */ DBG (32, "Welcome message received, busy status %02x\n", buf[2]); /* TODO: Return a human-readable error message (Unable to connect to scanner, scanner is not ready) */ return SANE_STATUS_DEVICE_BUSY; } buf[0] = cmd->net_wrapper_cmd; buf[1] = cmd->net_lock; buf[2] = 0x00; /* Copy the device's USB id to bytes 3-4: */ buf[3] = s->hw->cap->id & 0xff; buf[4] = (s->hw->cap->id >> 8) & 0xff; DBG(32, "Proper welcome message received, locking the scanner...\n"); sanei_magicolor_net_write_raw(s, buf, 5, &status); read = sanei_magicolor_net_read(s, buf, 3, &status); if (read != 3) return SANE_STATUS_IO_ERROR; if (buf[0] != cmd->net_wrapper_cmd || buf[1] != cmd->net_lock_ack || buf[2] != 0x00) { DBG (32, "Welcome message received, Expected 0x%x %x 00, but got 0x%x %x %x\n", cmd->net_wrapper_cmd, cmd->net_lock_ack, buf[0], buf[1], buf[2]); return SANE_STATUS_IO_ERROR; } DBG(32, "scanner locked\n"); return status; } static SANE_Status sanei_magicolor_net_close(struct Magicolor_Scanner *s) { SANE_Status status; struct MagicolorCmd *cmd = s->hw->cmd; unsigned char buf[3]; DBG(1, "%s\n", __func__); buf[0] = cmd->net_wrapper_cmd; buf[1] = cmd->net_unlock; buf[2] = 0x00; sanei_magicolor_net_write_raw(s, buf, 3, &status); return status; } /**************************************************************************** * Low-level USB communication functions ****************************************************************************/ #define SANE_MAGICOLOR_VENDOR_ID (0x132b) SANE_Word sanei_magicolor_usb_product_ids[] = { 0x2089, /* magicolor 1690MF */ 0x2079, /* magicolor 4690MF */ 0 /* last entry - this is used for devices that are specified in the config file as "usb " */ }; static int sanei_magicolor_getNumberOfUSBProductIds (void) { return sizeof (sanei_magicolor_usb_product_ids) / sizeof (SANE_Word); } /**************************************************************************** * Magicolor low-level communication commands ****************************************************************************/ static void dump_hex_buffer_dense (int level, const unsigned char *buf, size_t buf_size) { size_t k; char msg[1024], fmt_buf[1024]; memset (&msg[0], 0x00, 1024); memset (&fmt_buf[0], 0x00, 1024); for (k = 0; k < min(buf_size, 80); k++) { if (k % 16 == 0) { if (k>0) { DBG (level, "%s\n", msg); memset (&msg[0], 0x00, 1024); } sprintf (fmt_buf, " 0x%04lx ", (unsigned long)k); strcat (msg, fmt_buf); } if (k % 8 == 0) { strcat (msg, " "); } sprintf (fmt_buf, " %02x" , buf[k]); strcat (msg, fmt_buf); } if (msg[0] != 0 ) { DBG (level, "%s\n", msg); } } /* Create buffers containing the command and arguments. Length of reserved * buffer is returned. It's the caller's job to free the buffer! */ static int mc_create_buffer (Magicolor_Scanner *s, unsigned char cmd_type, unsigned char cmd, unsigned char **buf, unsigned char* arg1, size_t len1, SANE_Status *status) { unsigned char* b = NULL; size_t buf_len = 2+4+len1+4; NOT_USED (s); if (len1 <= 0) buf_len = 6; /* no args, just cmd + final 0x00 00 00 00 */ *buf = b = malloc (buf_len); memset (b, 0x00, buf_len); if (!b) { *status = SANE_STATUS_NO_MEM; return 0; } b[0] = cmd_type; b[1] = cmd; if (len1>0) { b[2] = len1 & 0xff; b[3] = (len1 >> 8) & 0xff; b[4] = (len1 >> 16) & 0xff; b[5] = (len1 >> 24) & 0xff; if (arg1) memcpy(b+6, arg1, len1); } /* Writing the final 0x00 00 00 00 is not necessary, they are 0x00 already */ *status = SANE_STATUS_GOOD; return buf_len; } static int mc_create_buffer2 (Magicolor_Scanner *s, unsigned char cmd_type, unsigned char cmd, unsigned char **buf, unsigned char* arg1, size_t len1, unsigned char* arg2, size_t len2, SANE_Status *status) { unsigned char* b = NULL; size_t buf_len = 2+4+len1+4+len2+4; /* If any of the two args has size 0, use the simpler mc_create_buffer */ if (len1<=0) return mc_create_buffer (s, cmd_type, cmd, buf, arg2, len2, status); else if (len2<=0) return mc_create_buffer (s, cmd_type, cmd, buf, arg1, len1, status); /* Allocate memory and copy over args and their lengths */ *buf = b = malloc (buf_len); if (!b) { *status = SANE_STATUS_NO_MEM; return 0; } memset (b, 0x00, buf_len); b[0] = cmd_type; b[1] = cmd; /* copy over the argument length in lower endian */ b[2] = len1 & 0xff; b[3] = (len1 >> 8) & 0xff; b[4] = (len1 >> 16) & 0xff; b[5] = (len1 >> 24) & 0xff; if (arg1) { /* Copy the arguments */ memcpy(b+6, arg1, len1); } /* copy over the second argument length in little endian */ b[6+len1] = len2 & 0xff; b[7+len1] = (len2 >> 8) & 0xff; b[8+len1] = (len2 >> 16) & 0xff; b[9+len1] = (len2 >> 24) & 0xff; if (arg2) { memcpy(b+10+len1, arg2, len2); } *status = SANE_STATUS_GOOD; return buf_len; } static int mc_send(Magicolor_Scanner * s, void *buf, size_t buf_size, SANE_Status * status) { DBG(15, "%s: size = %lu\n", __func__, (u_long) buf_size); if (DBG_LEVEL >= 125) { const unsigned char *s = buf; DBG(125, "Cmd: 0x%02x %02x, complete buffer:\n", s[0], s[1]); dump_hex_buffer_dense (125, s, buf_size); } if (s->hw->connection == SANE_MAGICOLOR_NET) { return sanei_magicolor_net_write(s, buf, buf_size, status); } else if (s->hw->connection == SANE_MAGICOLOR_USB) { size_t n; n = buf_size; *status = sanei_usb_write_bulk(s->fd, buf, &n); DBG(125, "USB: wrote %lu bytes, status: %s\n", (unsigned long)n, sane_strstatus(*status)); return n; } *status = SANE_STATUS_INVAL; return 0; /* never reached */ } static ssize_t mc_recv(Magicolor_Scanner * s, void *buf, ssize_t buf_size, SANE_Status * status) { ssize_t n = 0; DBG(15, "%s: size = %ld, buf = %p\n", __func__, (long) buf_size, buf); if (s->hw->connection == SANE_MAGICOLOR_NET) { n = sanei_magicolor_net_read(s, buf, buf_size, status); } else if (s->hw->connection == SANE_MAGICOLOR_USB) { /* !!! only report an error if we don't read anything */ n = buf_size; /* buf_size gets overwritten */ *status = sanei_usb_read_bulk(s->fd, (SANE_Byte *) buf, (size_t *) & n); if (n > 0) *status = SANE_STATUS_GOOD; } if (n < buf_size) { DBG(1, "%s: expected = %lu, got = %ld\n", __func__, (u_long) buf_size, (long) n); *status = SANE_STATUS_IO_ERROR; } /* dump buffer if appropriate */ if (DBG_LEVEL >= 127 && n > 0) { const unsigned char* b=buf; dump_hex_buffer_dense (125, b, buf_size); } return n; } /* Simple function to exchange a fixed amount of * data with the scanner */ static SANE_Status mc_txrx(Magicolor_Scanner * s, unsigned char *txbuf, size_t txlen, unsigned char *rxbuf, size_t rxlen) { SANE_Status status; mc_send(s, txbuf, txlen, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status)); return status; } mc_recv(s, rxbuf, rxlen, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status)); } return status; } /**************************************************************************** * Magicolor high-level communication commands ****************************************************************************/ /** 0x03 09 01 - Request last error * <- Information block (0x00 for OK, 0x01 for ERROR) */ static SANE_Status cmd_request_error (SANE_Handle handle) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char params[1]; unsigned char *buf; size_t buflen; DBG(8, "%s\n", __func__); if (s->hw->cmd->request_status == 0) return SANE_STATUS_UNSUPPORTED; buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_error, &buf, NULL, 1, &status); if (buflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } status = mc_txrx (s, buf, buflen, params, 1); free(buf); if (status != SANE_STATUS_GOOD) return status; DBG(1, "status: %02x\n", params[0]); switch (params[0]) { case STATUS_READY: DBG(1, " ready\n"); break; case STATUS_ADF_JAM: DBG(1, " paper jam in ADF\n"); return SANE_STATUS_JAMMED; break; case STATUS_OPEN: DBG(1, " printer door open or waiting for button press\n"); return SANE_STATUS_COVER_OPEN; break; case STATUS_NOT_READY: DBG(1, " scanner not ready (in use on another interface or warming up)\n"); return SANE_STATUS_DEVICE_BUSY; break; default: DBG(1, " unknown status 0x%x\n", params[0]); } return status; } /** 0x03 0d - Request status command */ static SANE_Status cmd_request_status(SANE_Handle handle, unsigned char *b) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char *buf; size_t buflen; DBG(8, "%s\n", __func__); if (!b) { DBG(1, "%s called with NULL buffer\n", __func__); return SANE_STATUS_INVAL; } memset (b, 0x00, 0x0b); /* initialize all 0x0b bytes with 0 */ buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_status, &buf, NULL, 0x0b, &status); if (buflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } status = mc_txrx (s, buf, buflen, b, 0x0b); free (buf); if (status != SANE_STATUS_GOOD) DBG(8, "%s: Status NOT successfully retrieved\n", __func__); else { DBG(8, "%s: Status successfully retrieved:\n", __func__); /* TODO: debug output of the returned parameters... */ DBG (11, " ADF status: 0x%02x", b[1]); if (b[1] & ADF_LOADED) { DBG (11, " loaded\n"); } else { DBG (11, " not loaded\n"); } } return status; } /** 0x03 08 - Start scan command */ static SANE_Status cmd_start_scan (SANE_Handle handle, size_t value) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char params1[4], params2[1]; unsigned char *buf; size_t buflen; DBG(8, "%s\n", __func__); /* Copy params to buffers */ /* arg1 is expected returned bytes per line, 4-byte little endian */ /* arg2 is unknown, seems to be always 0x00 */ params1[0] = value & 0xff; params1[1] = (value >> 8) & 0xff; params1[2] = (value >> 16) & 0xff; params1[3] = (value >> 24) & 0xff; params2[0] = 0x00; buflen = mc_create_buffer2 (s, s->hw->cmd->scanner_cmd, s->hw->cmd->start_scanning, &buf, params1, 4, params2, 1, &status); if (buflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } mc_send(s, buf, buflen, &status); free (buf); if (status != SANE_STATUS_GOOD) DBG(8, "%s: Data NOT successfully sent\n", __func__); else DBG(8, "%s: Data successfully sent\n", __func__); return status; } /** 0x03 0a - Cancel(?) Scan command */ /* TODO: Does this command really mean CANCEL??? */ static SANE_Status cmd_cancel_scan (SANE_Handle handle) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char *buf; size_t buflen; DBG(8, "%s\n", __func__); buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->stop_scanning, &buf, NULL, 0, &status); if (buflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } mc_send(s, buf, buflen, &status); free (buf); if (status != SANE_STATUS_GOOD) DBG(8, "%s: Data NOT successfully sent\n", __func__); else DBG(8, "%s: Data successfully sent\n", __func__); return status; } /** 0x03 12 - Finish(?) scan command */ /* TODO: Does this command really mean FINISH??? */ static SANE_Status cmd_finish_scan (SANE_Handle handle) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char *buf, returned[0x0b]; size_t buflen; DBG(8, "%s\n", __func__); buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->unknown2, &buf, NULL, 0x0b, &status); if (buflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } memset (&returned[0], 0x00, 0x0b); status = mc_txrx (s, buf, buflen, returned, 0x0b); free (buf); if (status != SANE_STATUS_GOOD) DBG(8, "%s: Data NOT successfully sent\n", __func__); else DBG(8, "%s: Data successfully sent\n", __func__); return status; } /** 0x03 0b - Get scanning parameters command * input buffer seems to be 0x00 always */ static SANE_Status cmd_get_scanning_parameters(SANE_Handle handle, SANE_Frame *format, SANE_Int *depth, SANE_Int *data_pixels, SANE_Int *pixels_per_line, SANE_Int *lines) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char *txbuf, rxbuf[8]; size_t buflen; NOT_USED (format); NOT_USED (depth); DBG(8, "%s\n", __func__); buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_scan_parameters, &txbuf, NULL, 8, &status); if (buflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } status = mc_txrx (s, txbuf, buflen, rxbuf, 8); free (txbuf); if (status != SANE_STATUS_GOOD) DBG(8, "%s: Parameters NOT successfully retrieved\n", __func__); else { DBG(8, "%s: Parameters successfully retrieved\n", __func__); /* Assign px_per_line and lines. Bytes 7-8 must match 3-4 */ if (rxbuf[2]!=rxbuf[6] || rxbuf[3]!=rxbuf[7]) { DBG (1, "%s: ERROR: Returned image parameters indicate an " "unsupported device: Bytes 3-4 do not match " "bytes 7-8! Trying to continue with bytes 3-4.\n", __func__); dump_hex_buffer_dense (1, rxbuf, 8); } /* Read returned values, encoded in 2-byte little endian */ *data_pixels = rxbuf[1] * 0x100 + rxbuf[0]; *lines = rxbuf[3] * 0x100 + rxbuf[2]; *pixels_per_line = rxbuf[5] * 0x100 + rxbuf[4]; DBG (8, "%s: data_pixels = 0x%x (%u), lines = 0x%x (%u), " "pixels_per_line = 0x%x (%u)\n", __func__, *data_pixels, *data_pixels, *lines, *lines, *pixels_per_line, *pixels_per_line); } return status; } /** 0x03 0c - Set scanning parameters command */ static SANE_Status cmd_set_scanning_parameters(SANE_Handle handle, unsigned char resolution, unsigned char color_mode, unsigned char brightness, unsigned char contrast, int tl_x, int tl_y, int width, int height, unsigned char source) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char param[0x11]; unsigned char *buf; size_t buflen; DBG(8, "%s\n", __func__); /* Copy over the params to the param byte array */ /* Byte structure: * byte 0: resolution * byte 1: color mode * byte 2: brightness * byte 3: 0xff * byte 4-5: x-start * byte 6-7: y-start * byte 8-9: x-extent * byte 10-11: y-extent * byte 12: source (ADF/FBF) **/ memset (¶m[0], 0x00, 0x11); param[0] = resolution; param[1] = color_mode; param[2] = brightness; param[3] = contrast | 0xff; /* TODO: Always 0xff? What about contrast? */ /* Image coordinates are encoded 2-byte little endian: */ param[4] = tl_x & 0xff; param[5] = (tl_x >> 8) & 0xff; param[6] = tl_y & 0xff; param[7] = (tl_y >> 8) & 0xff; param[8] = width & 0xff; param[9] = (width >> 8) & 0xff; param[10] = height & 0xff; param[11] = (height >> 8) & 0xff; param[12] = source; /* dump buffer if appropriate */ DBG (127, " Scanning parameter buffer:"); dump_hex_buffer_dense (127, param, 0x11); buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->set_scan_parameters, &buf, param, 0x11, &status); if (buflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } mc_send(s, buf, buflen, &status); free (buf); if (status != SANE_STATUS_GOOD) DBG(8, "%s: Data NOT successfully sent\n", __func__); else DBG(8, "%s: Data successfully sent\n", __func__); return status; } /** 0x03 ?? - Request push button status command */ #if 0 static SANE_Status cmd_request_push_button_status(SANE_Handle handle, unsigned char *bstatus) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char *buf; size_t buflen; DBG(8, "%s\n", __func__); if (s->hw->cmd->unknown1 == 0) return SANE_STATUS_UNSUPPORTED; DBG(8, "%s: Supported\n", __func__); memset (bstatus, 0x00, 1); buflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->unknown1, &buf, bstatus, 1, &status); if (buflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } status = mc_txrx (s, buf, buflen, bstatus, 1); free(buf); if (status != SANE_STATUS_GOOD) return status; DBG(1, "push button status: %02x ", bstatus[0]); switch (bstatus[0]) { /* TODO: What's the response code for button pressed??? */ default: DBG(1, " unknown\n"); status = SANE_STATUS_UNSUPPORTED; } return status; } #endif /** 0x03 0e - Read data command */ static SANE_Status cmd_read_data (SANE_Handle handle, unsigned char *buf, size_t len) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; unsigned char *txbuf; unsigned char param[4]; size_t txbuflen; int oldtimeout = MC_Request_Timeout; DBG(8, "%s\n", __func__); param[0] = len & 0xff; param[1] = (len >> 8) & 0xff; param[2] = (len >> 16) & 0xff; param[3] = (len >> 24) & 0xff; txbuflen = mc_create_buffer (s, s->hw->cmd->scanner_cmd, s->hw->cmd->request_data, &txbuf, param, 4, &status); if (txbuflen <= 0 ) { return SANE_STATUS_NO_MEM; } else if (status != SANE_STATUS_GOOD) { return status; } /* Temporarily set the poll timeout to 10 seconds instead of 2, * because a color scan needs >5 seconds to initialize. */ MC_Request_Timeout = MC_Scan_Data_Timeout; status = mc_txrx (s, txbuf, txbuflen, buf, len); MC_Request_Timeout = oldtimeout; free (txbuf); if (status != SANE_STATUS_GOOD) DBG(8, "%s: Image data NOT successfully retrieved\n", __func__); else { DBG(8, "%s: Image data successfully retrieved\n", __func__); } return status; } /* TODO: 0x03 0f command (unknown), 0x03 10 command (set button wait) */ /**************************************************************************** * Magicolor backend high-level operations ****************************************************************************/ static void mc_dev_init(Magicolor_Device *dev, const char *devname, int conntype) { DBG(5, "%s\n", __func__); dev->name = NULL; dev->model = NULL; dev->connection = conntype; dev->sane.name = devname; dev->sane.model = NULL; dev->sane.type = "flatbed scanner"; dev->sane.vendor = "Magicolor"; dev->cap = &magicolor_cap[MAGICOLOR_CAP_DEFAULT]; dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_DEFAULT]; /* Change default level when using a network connection */ if (dev->connection == SANE_MAGICOLOR_NET) dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_NET]; } static SANE_Status mc_dev_post_init(struct Magicolor_Device *dev) { DBG(5, "%s\n", __func__); NOT_USED (dev); /* Correct device parameters if needed */ return SANE_STATUS_GOOD; } static SANE_Status mc_set_model(Magicolor_Scanner * s, const char *model, size_t len) { unsigned char *buf; unsigned char *p; struct Magicolor_Device *dev = s->hw; buf = malloc(len + 1); if (buf == NULL) return SANE_STATUS_NO_MEM; memcpy(buf, model, len); buf[len] = '\0'; p = &buf[len - 1]; while (*p == ' ') { *p = '\0'; p--; } if (dev->model) free(dev->model); dev->model = strndup((const char *) buf, len); dev->sane.model = dev->model; DBG(10, "%s: model is '%s'\n", __func__, dev->model); free(buf); return SANE_STATUS_GOOD; } static void mc_set_device (SANE_Handle handle, unsigned int device) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; Magicolor_Device *dev = s->hw; const char* cmd_level; int n; DBG(1, "%s: 0x%x\n", __func__, device); for (n = 0; n < NELEMS (magicolor_cap); n++) { if (magicolor_cap[n].id == device) break; } if (n < NELEMS(magicolor_cap)) { dev->cap = &magicolor_cap[n]; } else { dev->cap = &magicolor_cap[MAGICOLOR_CAP_DEFAULT]; DBG(1, " unknown device 0x%x, using default %s\n", device, dev->cap->model); } mc_set_model (s, dev->cap->model, strlen (dev->cap->model)); cmd_level = dev->cap->cmds; /* set command type and level */ for (n = 0; n < NELEMS(magicolor_cmd); n++) { if (!strcmp(cmd_level, magicolor_cmd[n].level)) break; } if (n < NELEMS(magicolor_cmd)) { dev->cmd = &magicolor_cmd[n]; } else { dev->cmd = &magicolor_cmd[MAGICOLOR_LEVEL_DEFAULT]; DBG(1, " unknown command level %s, using %s\n", cmd_level, dev->cmd->level); } } static SANE_Status mc_discover_capabilities(Magicolor_Scanner *s) { SANE_Status status; Magicolor_Device *dev = s->hw; SANE_String_Const *source_list_add = source_list; DBG(5, "%s\n", __func__); /* always add flatbed */ *source_list_add++ = FBF_STR; /* TODO: How can I check for existence of an ADF??? */ if (dev->cap->ADF) *source_list_add++ = ADF_STR; /* TODO: Is there any capability that we can extract from the * device by some scanne command? So far, it looks like * the device does not support any reporting. I don't even * see a way to determine which device we are talking to! */ /* request error status */ status = cmd_request_error(s); if (status != SANE_STATUS_GOOD) return status; dev->x_range = &dev->cap->fbf_x_range; dev->y_range = &dev->cap->fbf_y_range; DBG(5, " x-range: %f %f\n", SANE_UNFIX(dev->x_range->min), SANE_UNFIX(dev->x_range->max)); DBG(5, " y-range: %f %f\n", SANE_UNFIX(dev->y_range->min), SANE_UNFIX(dev->y_range->max)); DBG(5, "End of %s, status:%s\n", __func__, sane_strstatus(status)); *source_list_add = NULL; /* add end marker to source list */ return status; } static SANE_Status mc_setup_block_mode (Magicolor_Scanner *s) { /* block_len should always be a multiple of bytes_per_line, so * we retrieve only whole lines at once */ s->block_len = (int)(0xff00/s->scan_bytes_per_line) * s->scan_bytes_per_line; s->blocks = s->data_len / s->block_len; s->last_len = s->data_len - (s->blocks * s->block_len); if (s->last_len>0) s->blocks++; DBG(5, "%s: block_len=0x%x, last_len=0x%0x, blocks=%d\n", __func__, s->block_len, s->last_len, s->blocks); s->counter = 0; s->bytes_read_in_line = 0; if (s->line_buffer) free(s->line_buffer); s->line_buffer = malloc(s->scan_bytes_per_line); if (s->line_buffer == NULL) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } DBG (5, " %s: Setup block mode - scan_bytes_per_line=%d, pixels_per_line=%d, depth=%d, data_len=%x, block_len=%x, blocks=%d, last_len=%x\n", __func__, s->scan_bytes_per_line, s->params.pixels_per_line, s->params.depth, s->data_len, s->block_len, s->blocks, s->last_len); return SANE_STATUS_GOOD; } /* Call the 0x03 0c command to set scanning parameters from the s->opt list */ static SANE_Status mc_set_scanning_parameters(Magicolor_Scanner * s) { SANE_Status status; unsigned char rs, source, brightness; struct mode_param *mparam = &mode_params[s->val[OPT_MODE].w]; SANE_Int scan_pixels_per_line = 0; DBG(1, "%s\n", __func__); /* Find the resolution in the res list and assign the index to buf[1] */ for (rs=0; rs < s->hw->cap->res_list_size; rs++ ) { if ( s->val[OPT_RESOLUTION].w == s->hw->cap->res_list[rs] ) break; } if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_BRIGHTNESS].cap)) { brightness = s->val[OPT_BRIGHTNESS].w; } else { brightness = 5; } /* ADF used? */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { /* Use ADF */ if (s->val[OPT_ADF_MODE].w == 0) { source = 0x01; } else { /* Use duplex */ source = 0x02; } } else { source = 0x00; } /* TODO: Any way to set PREVIEW??? */ /* Remaining bytes unused */ status = cmd_set_scanning_parameters(s, rs, mparam->flags, /* res, color mode */ brightness, 0xff, /* brightness, contrast? */ s->left, s->top, /* top/left start */ s->width, s->height, /* extent */ source); /* source */ if (status != SANE_STATUS_GOOD) DBG (2, "%s: Command cmd_set_scanning_parameters failed, %s\n", __func__, sane_strstatus(status)); /* Now query the scanner for the current image parameters */ status = cmd_get_scanning_parameters (s, &s->params.format, &s->params.depth, &scan_pixels_per_line, &s->params.pixels_per_line, &s->params.lines); if (status != SANE_STATUS_GOOD) { DBG (2, "%s: Command cmd_get_scanning_parameters failed, %s\n", __func__, sane_strstatus(status)); return status; } /* Calculate how many bytes are really used per line */ s->params.bytes_per_line = ceil (s->params.pixels_per_line * s->params.depth / 8.0); if (s->val[OPT_MODE].w == MODE_COLOR) s->params.bytes_per_line *= 3; /* Calculate how many bytes per line will be returned by the scanner. * The values needed for this are returned by get_scannign_parameters */ s->scan_bytes_per_line = ceil (scan_pixels_per_line * s->params.depth / 8.0); if (s->val[OPT_MODE].w == MODE_COLOR) { s->scan_bytes_per_line *= 3; } s->data_len = s->params.lines * s->scan_bytes_per_line; status = mc_setup_block_mode (s); if (status != SANE_STATUS_GOOD) DBG (2, "%s: Command mc_setup_block_mode failed, %s\n", __func__, sane_strstatus(status)); DBG (1, "%s: bytes_read in line: %d\n", __func__, s->bytes_read_in_line); return status; } static SANE_Status mc_check_adf(Magicolor_Scanner * s) { SANE_Status status; unsigned char buf[0x0b]; DBG(5, "%s\n", __func__); status = cmd_request_status(s, buf); if (status != SANE_STATUS_GOOD) return status; if (!(buf[1] & ADF_LOADED)) return SANE_STATUS_NO_DOCS; /* TODO: Check for jam in ADF */ return SANE_STATUS_GOOD; } static SANE_Status mc_scan_finish(Magicolor_Scanner * s) { SANE_Status status; DBG(5, "%s\n", __func__); /* If we have not yet read all data, cancel the scan */ if (s->buf && !s->eof) status = cmd_cancel_scan (s); if (s->line_buffer) free (s->line_buffer); s->line_buffer = NULL; free(s->buf); s->buf = s->end = s->ptr = NULL; /* TODO: Any magicolor command for "scan finished"? */ status = cmd_finish_scan (s); status = cmd_request_error(s); if (status != SANE_STATUS_GOOD) cmd_cancel_scan (s); return status; /* XXX required? */ /* TODO: cmd_reset(s);*/ return SANE_STATUS_GOOD; } static void mc_copy_image_data(Magicolor_Scanner * s, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { DBG (1, "%s: bytes_read in line: %d\n", __func__, s->bytes_read_in_line); if (s->params.format == SANE_FRAME_RGB) { SANE_Int bytes_available, scan_pixels_per_line = s->scan_bytes_per_line/3; *length = 0; while ((max_length >= s->params.bytes_per_line) && (s->ptr < s->end)) { SANE_Int bytes_to_copy = s->scan_bytes_per_line - s->bytes_read_in_line; /* First, fill the line buffer for the current line: */ bytes_available = (s->end - s->ptr); /* Don't copy more than we have buffer and available */ if (bytes_to_copy > bytes_available) bytes_to_copy = bytes_available; if (bytes_to_copy > 0) { memcpy (s->line_buffer + s->bytes_read_in_line, s->ptr, bytes_to_copy); s->ptr += bytes_to_copy; s->bytes_read_in_line += bytes_to_copy; } /* We have filled as much as possible of the current line * with data from the scanner. If we have a complete line, * copy it over. */ if ((s->bytes_read_in_line >= s->scan_bytes_per_line) && (s->params.bytes_per_line <= max_length)) { SANE_Int i; SANE_Byte *line = s->line_buffer; *length += s->params.bytes_per_line; for (i=0; i< s->params.pixels_per_line; ++i) { *data++ = line[0]; *data++ = line[scan_pixels_per_line]; *data++ = line[2 * scan_pixels_per_line]; line++; } max_length -= s->params.bytes_per_line; s->bytes_read_in_line -= s->scan_bytes_per_line; } } } else { /* B/W and Grayscale use the same structure, so we use the same code */ SANE_Int bytes_available; *length = 0; while ((max_length != 0) && (s->ptr < s->end)) { SANE_Int bytes_to_skip, bytes_to_copy; bytes_available = (s->end - s->ptr); bytes_to_copy = s->params.bytes_per_line - s->bytes_read_in_line; bytes_to_skip = s->scan_bytes_per_line - s->bytes_read_in_line; /* Don't copy more than we have buffer */ if (bytes_to_copy > max_length) { bytes_to_copy = max_length; bytes_to_skip = max_length; } /* Don't copy/skip more bytes than we have read in */ if (bytes_to_copy > bytes_available) bytes_to_copy = bytes_available; if (bytes_to_skip > bytes_available) bytes_to_skip = bytes_available; if (bytes_to_copy > 0) { /* we have not yet copied all pixels of the line */ memcpy (data, s->ptr, bytes_to_copy); max_length -= bytes_to_copy; *length += bytes_to_copy; data += bytes_to_copy; } if (bytes_to_skip > 0) { s->ptr += bytes_to_skip; s->bytes_read_in_line += bytes_to_skip; } if (s->bytes_read_in_line >= s->scan_bytes_per_line) s->bytes_read_in_line -= s->scan_bytes_per_line; } } } static SANE_Status mc_init_parameters(Magicolor_Scanner * s) { int dpi, optres; DBG(5, "%s\n", __func__); memset(&s->params, 0, sizeof(SANE_Parameters)); dpi = s->val[OPT_RESOLUTION].w; optres = s->hw->cap->optical_res; if (SANE_UNFIX(s->val[OPT_BR_Y].w) == 0 || SANE_UNFIX(s->val[OPT_BR_X].w) == 0) return SANE_STATUS_INVAL; /* TODO: Use OPT_RESOLUTION or fixed 600dpi for left/top/width/height? */ s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) * optres) + 0.5; s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) * optres) + 0.5; s->width = ((SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) / MM_PER_INCH) * optres) + 0.5; s->height = ((SANE_UNFIX(s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) / MM_PER_INCH) * optres) + 0.5; s->params.pixels_per_line = s->width * dpi / optres + 0.5; s->params.lines = s->height * dpi / optres + 0.5; DBG(1, "%s: resolution = %d, preview = %d\n", __func__, dpi, s->val[OPT_PREVIEW].w); DBG(1, "%s: %p %p tlx %f tly %f brx %f bry %f [mm]\n", __func__, (void *) s, (void *) s->val, SANE_UNFIX(s->val[OPT_TL_X].w), SANE_UNFIX(s->val[OPT_TL_Y].w), SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w)); /* * The default color depth is stored in mode_params.depth: */ DBG(1, " %s, vor depth\n", __func__); if (mode_params[s->val[OPT_MODE].w].depth == 1) s->params.depth = 1; else s->params.depth = s->val[OPT_BIT_DEPTH].w; s->params.last_frame = SANE_TRUE; s->params.bytes_per_line = ceil (s->params.depth * s->params.pixels_per_line / 8.0); switch (s->val[OPT_MODE].w) { case MODE_BINARY: case MODE_GRAY: s->params.format = SANE_FRAME_GRAY; break; case MODE_COLOR: s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line *= 3; break; } DBG(1, "%s: Parameters are format=%d, bytes_per_line=%d, lines=%d\n", __func__, s->params.format, s->params.bytes_per_line, s->params.lines); return (s->params.lines > 0) ? SANE_STATUS_GOOD : SANE_STATUS_INVAL; } static SANE_Status mc_start_scan(Magicolor_Scanner * s) { SANE_Status status = cmd_start_scan (s, s->data_len); if (status != SANE_STATUS_GOOD ) { DBG (1, "%s: starting the scan failed (%s)\n", __func__, sane_strstatus(status)); } return status; } static SANE_Status mc_read(struct Magicolor_Scanner *s) { SANE_Status status = SANE_STATUS_GOOD; ssize_t buf_len = 0; /* did we passed everything we read to sane? */ if (s->ptr == s->end) { if (s->eof) return SANE_STATUS_EOF; s->counter++; buf_len = s->block_len; if (s->counter == s->blocks && s->last_len) buf_len = s->last_len; DBG(18, "%s: block %d/%d, size %lu\n", __func__, s->counter, s->blocks, (unsigned long) buf_len); /* receive image data + error code */ status = cmd_read_data (s, s->buf, buf_len); if (status != SANE_STATUS_GOOD) { DBG (1, "%s: Receiving image data failed (%s)\n", __func__, sane_strstatus(status)); cmd_cancel_scan(s); return status; } DBG(18, "%s: successfully read %lu bytes\n", __func__, (unsigned long) buf_len); if (s->counter < s->blocks) { if (s->canceling) { cmd_cancel_scan(s); return SANE_STATUS_CANCELLED; } } else s->eof = SANE_TRUE; s->end = s->buf + buf_len; s->ptr = s->buf; } return status; } /**************************************************************************** * SANE API implementation (high-level functions) ****************************************************************************/ #if HAVE_LIBSNMP static struct MagicolorCap * mc_get_device_from_identification (const char*ident) { int n; for (n = 0; n < NELEMS (magicolor_cap); n++) { if (strcmp (magicolor_cap[n].model, ident) || strcmp (magicolor_cap[n].OID, ident)) return &magicolor_cap[n]; } return NULL; } #endif /* * close_scanner() * * Close the open scanner. Depending on the connection method, a different * close function is called. */ static void close_scanner(Magicolor_Scanner *s) { DBG(7, "%s: fd = %d\n", __func__, s->fd); if (s->fd == -1) return; mc_scan_finish(s); if (s->hw->connection == SANE_MAGICOLOR_NET) { sanei_magicolor_net_close(s); sanei_tcp_close(s->fd); } else if (s->hw->connection == SANE_MAGICOLOR_USB) { sanei_usb_close(s->fd); } s->fd = -1; } static SANE_Bool split_scanner_name (const char *name, char * IP, unsigned int *model) { const char *device = name; const char *qm; *model = 0; /* cut off leading net: */ if (strncmp(device, "net:", 4) == 0) device = &device[4]; qm = strchr(device, '?'); if (qm != NULL) { size_t len = qm-device; strncpy (IP, device, len); IP[len] = '\0'; qm++; if (strncmp(qm, "model=", 6) == 0) { qm += 6; if (!sscanf(qm, "0x%x", model)) sscanf(qm, "%x", model); } } else { strcpy (IP, device); } return SANE_TRUE; } /* * open_scanner() * * Open the scanner device. Depending on the connection method, * different open functions are called. */ static SANE_Status open_scanner(Magicolor_Scanner *s) { SANE_Status status = 0; DBG(7, "%s: %s\n", __func__, s->hw->sane.name); if (s->fd != -1) { DBG(7, "scanner is already open: fd = %d\n", s->fd); return SANE_STATUS_GOOD; /* no need to open the scanner */ } if (s->hw->connection == SANE_MAGICOLOR_NET) { /* device name has the form net:ipaddr?model=... */ char IP[1024]; unsigned int model = 0; if (!split_scanner_name (s->hw->sane.name, IP, &model)) return SANE_STATUS_INVAL; status = sanei_tcp_open(IP, 4567, &s->fd); if (model>0) mc_set_device (s, model); if (status == SANE_STATUS_GOOD) { DBG(7, "awaiting welcome message\n"); status = sanei_magicolor_net_open (s); } } else if (s->hw->connection == SANE_MAGICOLOR_USB) { status = sanei_usb_open(s->hw->sane.name, &s->fd); if (s->hw->cap->out_ep>0) sanei_usb_set_endpoint (s->fd, USB_DIR_OUT | USB_ENDPOINT_TYPE_BULK, s->hw->cap->out_ep); if (s->hw->cap->in_ep>0) sanei_usb_set_endpoint (s->fd, USB_DIR_IN | USB_ENDPOINT_TYPE_BULK, s->hw->cap->in_ep); } if (status == SANE_STATUS_ACCESS_DENIED) { DBG(1, "please check that you have permissions on the device.\n"); DBG(1, "if this is a multi-function device with a printer,\n"); DBG(1, "disable any conflicting driver (like usblp).\n"); } if (status != SANE_STATUS_GOOD) DBG(1, "%s open failed: %s\n", s->hw->sane.name, sane_strstatus(status)); else DBG(3, "scanner opened\n"); return status; } static SANE_Status detect_usb(struct Magicolor_Scanner *s) { SANE_Status status; int vendor, product; int i, numIds; SANE_Bool is_valid; /* if the sanei_usb_get_vendor_product call is not supported, * then we just ignore this and rely on the user to config * the correct device. */ status = sanei_usb_get_vendor_product(s->fd, &vendor, &product); if (status != SANE_STATUS_GOOD) { DBG(1, "the device cannot be verified - will continue\n"); return SANE_STATUS_GOOD; } /* check the vendor ID to see if we are dealing with an MAGICOLOR device */ if (vendor != SANE_MAGICOLOR_VENDOR_ID) { /* this is not a supported vendor ID */ DBG(1, "not an Magicolor device at %s (vendor id=0x%x)\n", s->hw->sane.name, vendor); return SANE_STATUS_INVAL; } numIds = sanei_magicolor_getNumberOfUSBProductIds(); is_valid = SANE_FALSE; i = 0; /* check all known product IDs to verify that we know * about the device */ while (i != numIds && !is_valid) { if (product == sanei_magicolor_usb_product_ids[i]) is_valid = SANE_TRUE; i++; } if (is_valid == SANE_FALSE) { DBG(1, "the device at %s is not a supported (product id=0x%x)\n", s->hw->sane.name, product); return SANE_STATUS_INVAL; } DBG(2, "found valid Magicolor scanner: 0x%x/0x%x (vendorID/productID)\n", vendor, product); mc_set_device(s, product); return SANE_STATUS_GOOD; } /* * used by attach* and sane_get_devices * a ptr to a single-linked list of Magicolor_Device structs * a ptr to a null term array of ptrs to SANE_Device structs */ static int num_devices; /* number of scanners attached to backend */ static Magicolor_Device *first_dev; /* first MAGICOLOR scanner in list */ static const SANE_Device **devlist = NULL; static struct Magicolor_Scanner * scanner_create(struct Magicolor_Device *dev, SANE_Status *status) { struct Magicolor_Scanner *s; s = malloc(sizeof(struct Magicolor_Scanner)); if (s == NULL) { *status = SANE_STATUS_NO_MEM; return NULL; } memset(s, 0x00, sizeof(struct Magicolor_Scanner)); s->fd = -1; s->hw = dev; return s; } static struct Magicolor_Scanner * device_detect(const char *name, int type, SANE_Status *status) { struct Magicolor_Scanner *s; struct Magicolor_Device *dev; /* try to find the device in our list */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, name) == 0) { dev->missing = 0; DBG (10, "%s: Device %s already attached!\n", __func__, name); return scanner_create(dev, status); } } if (type == SANE_MAGICOLOR_NODEV) { *status = SANE_STATUS_INVAL; return NULL; } /* alloc and clear our device structure */ dev = malloc(sizeof(*dev)); if (!dev) { *status = SANE_STATUS_NO_MEM; return NULL; } memset(dev, 0x00, sizeof(struct Magicolor_Device)); s = scanner_create(dev, status); if (s == NULL) return NULL; mc_dev_init(dev, name, type); *status = open_scanner(s); if (*status != SANE_STATUS_GOOD) { free(s); return NULL; } /* from now on, close_scanner() must be called */ /* USB requires special care */ if (dev->connection == SANE_MAGICOLOR_USB) { *status = detect_usb(s); } if (*status != SANE_STATUS_GOOD) goto close; /* set name and model (if not already set) */ if (dev->model == NULL) mc_set_model(s, "generic", 7); dev->name = strdup(name); dev->sane.name = dev->name; *status = mc_discover_capabilities(s); if (*status != SANE_STATUS_GOOD) goto close; if (source_list[0] == NULL || dev->cap->dpi_range.min == 0) { DBG(1, "something is wrong in the discovery process, aborting.\n"); *status = SANE_STATUS_IO_ERROR; goto close; } mc_dev_post_init(dev); /* add this scanner to the device list */ num_devices++; dev->missing = 0; dev->next = first_dev; first_dev = dev; return s; close: close_scanner(s); free(s); return NULL; } #if HAVE_LIBSNMP /* Keep a linked list of already observed IP addresses */ /* typedef struct snmp_ip SNMP_IP; */ typedef struct snmp_ip { char ip_addr[1024]; struct snmp_ip*next; } snmp_ip; typedef struct { int nr; snmp_ip*handled; snmp_ip*detected; } snmp_discovery_data; /** Handle one SNMP response (whether received sync or async) and if describes * a magicolor device, attach it. Returns the number of attached devices (0 * or 1) */ static int mc_network_discovery_handle (struct snmp_pdu *pdu, snmp_discovery_data *magic) { netsnmp_variable_list *varlist = pdu->variables, *vp; oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; /* Device information variables */ char ip_addr[1024]; char model[1024]; char device[1024]; /* remote IP detection variables */ netsnmp_indexed_addr_pair *responder = (netsnmp_indexed_addr_pair *) pdu->transport_data; struct sockaddr_in *remote = NULL; struct MagicolorCap *cap; snmp_ip *ip = NULL; DBG(5, "%s: Handling SNMP response \n", __func__); if (responder == NULL || pdu->transport_data_length != sizeof(netsnmp_indexed_addr_pair )) { DBG(1, "%s: Unable to extract IP address from SNMP response.\n", __func__); return 0; } remote = (struct sockaddr_in *) &(responder->remote_addr); if (remote == NULL) { DBG(1, "%s: Unable to extract IP address from SNMP response.\n", __func__); return 0; } snprintf(ip_addr, sizeof(ip_addr), "%s", inet_ntoa(remote->sin_addr)); DBG(35, "%s: IP Address of responder is %s\n", __func__, ip_addr); if (magic) ip = magic->handled; while (ip) { if (strcmp (ip->ip_addr, ip_addr) == 0) { DBG (5, "%s: Already handled device %s, skipping\n", __func__, ip_addr); return 0; } ip = ip->next; } if (magic) { snmp_ip *new_handled = malloc(sizeof(snmp_ip)); strcpy (&new_handled->ip_addr[0], ip_addr); new_handled->next = magic->handled; magic->handled = new_handled; } /* System Object ID (Unique OID identifying model) * This determines whether we really have a magicolor device */ anOID_len = MAX_OID_LEN; read_objid(MAGICOLOR_SNMP_SYSOBJECT_OID, anOID, &anOID_len); vp = find_varbind_in_list (varlist, anOID, anOID_len); if (vp) { size_t value_len = vp->val_len/sizeof(oid); if (vp->type != ASN_OBJECT_ID) { DBG (3, "%s: SystemObjectID does not return an OID, device is not a magicolor device\n", __func__); return 0; } snprint_objid (device, sizeof(device), vp->val.objid, value_len); DBG (5, "%s: Device object ID is '%s'\n", __func__, device); anOID_len = MAX_OID_LEN; read_objid (MAGICOLOR_SNMP_DEVICE_TREE, anOID, &anOID_len); if (netsnmp_oid_is_subtree (anOID, anOID_len, vp->val.objid, value_len) == 0) { DBG (5, "%s: Device appears to be a magicolor device (OID=%s)\n", __func__, device); } else { DBG (5, "%s: Device is not a Magicolor device\n", __func__); return 0; } } /* Retrieve sysDescr (i.e. model name) */ anOID_len = MAX_OID_LEN; read_objid(MAGICOLOR_SNMP_SYSDESCR_OID, anOID, &anOID_len); vp = find_varbind_in_list (varlist, anOID, anOID_len); if (vp) { memcpy(model,vp->val.string,vp->val_len); model[vp->val_len] = '\0'; DBG (5, "%s: Found model: %s\n", __func__, model); } DBG (1, "%s: Detected device '%s' on IP %s\n", __func__, model, ip_addr); vp = pdu->variables; /* TODO: attach the IP with attach_one_net(ip) */ cap = mc_get_device_from_identification (device); if (cap) { DBG(1, "%s: Found autodiscovered device: %s (type 0x%x)\n", __func__, cap->model, cap->id); attach_one_net (ip_addr, cap->id); if (magic) { snmp_ip *new_detected = malloc(sizeof(snmp_ip)); strcpy (&new_detected->ip_addr[0], ip_addr); new_detected->next = magic->detected; magic->detected = new_detected; } return 1; } return 0; } static int mc_network_discovery_cb (int operation, struct snmp_session *sp, int reqid, struct snmp_pdu *pdu, void *magic) { NOT_USED (reqid); NOT_USED (sp); DBG(5, "%s: Received broadcast response \n", __func__); if (operation == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { snmp_discovery_data *m = (snmp_discovery_data*)magic; int nr = mc_network_discovery_handle (pdu, m); m->nr += nr; DBG(5, "%s: Added %d discovered host(s) for SNMP response.\n", __func__, nr); } return 0; } #endif /* Use SNMP for automatic network discovery. If host is given, try to detect * that one host (using sync SNMP, otherwise send an SNMP broadcast (async). */ static int mc_network_discovery(const char*host) { #if HAVE_LIBSNMP netsnmp_session session, *ss; netsnmp_pdu *pdu; oid anOID[MAX_OID_LEN]; size_t anOID_len = MAX_OID_LEN; snmp_discovery_data magic; magic.nr = 0; magic.handled = 0; magic.detected = 0; DBG(1, "%s: running network discovery \n", __func__); /* Win32: init winsock */ SOCK_STARTUP; init_snmp("sane-magicolor-backend"); snmp_sess_init (&session); session.version = SNMP_VERSION_2c; session.community = (u_char *) "public"; session.community_len = strlen ((char *)session.community); if (host) { session.peername = (char *) host; } else { /* Do a network discovery via a broadcast */ session.peername = "255.255.255.255"; session.flags |= SNMP_FLAGS_UDP_BROADCAST; session.callback = mc_network_discovery_cb; session.callback_magic = &magic; } ss = snmp_open (&session); /* establish the session */ if (!ss) { snmp_sess_perror ("ack", &session); SOCK_CLEANUP; return 0; } /* Create the PDU for the data for our request and add the three * desired OIDs to the PDU */ pdu = snmp_pdu_create (SNMP_MSG_GET); /* SNMPv2-MIB::sysDescr.0 */ anOID_len = MAX_OID_LEN; if (read_objid(MAGICOLOR_SNMP_SYSDESCR_OID, anOID, &anOID_len)) { snmp_add_null_var (pdu, anOID, anOID_len); } /* SNMPv2-MIB::sysObjectID.0 */ anOID_len = MAX_OID_LEN; if (read_objid(MAGICOLOR_SNMP_SYSOBJECT_OID, anOID, &anOID_len)) { snmp_add_null_var (pdu, anOID, anOID_len); } /* IF-MIB::ifPhysAddress.1 */ anOID_len = MAX_OID_LEN; if (read_objid(MAGICOLOR_SNMP_MAC_OID, anOID, &anOID_len)) { snmp_add_null_var (pdu, anOID, anOID_len); } /* TODO: Add more interesting OIDs, in particular vendor OIDs */ /* Now send out the request and wait for responses for some time. * If we get a response, connect to that device (in the callback), * otherwise we probably don't have a magicolor device in the * LAN (or SNMP is turned off, in which case we have no way to detect * it. */ DBG(100, "%s: Sending SNMP packet\n", __func__); if (host) { /* sync request to given hostname, immediately read the reply */ netsnmp_pdu *response = 0; int status = snmp_synch_response(ss, pdu, &response); if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { magic.nr = mc_network_discovery_handle (response, &magic); } if (response) snmp_free_pdu(response); } else { /* No hostname, so do a broadcast */ struct timeval nowtime, endtime; /* end time for SNMP scan */ struct timeval timeout; int i=0; if (!snmp_send(ss, pdu)) { snmp_free_pdu(pdu); DBG(100, "%s: Sending SNMP packet NOT successful\n", __func__); return 0; } /* listen for responses for MC_AutoDetectionTimeout milliseconds: */ /* First get the final timeout time */ gettimeofday (&nowtime, NULL); timeout.tv_sec = MC_SNMP_Timeout / 1000; timeout.tv_usec = (MC_SNMP_Timeout % 1000) * 1000; timeradd (&nowtime, &timeout, &endtime); while (timercmp(&nowtime, &endtime, <)) { int fds = 0, block = 0; fd_set fdset; DBG(1, " loop=%d\n", i++); timeout.tv_sec = 0; /* Use a 125ms timeout for select. If we get a response, * the loop will be entered earlier again, anyway */ timeout.tv_usec = 125000; FD_ZERO (&fdset); snmp_select_info (&fds, &fdset, &timeout, &block); fds = select (fds, &fdset, NULL, NULL, /*block?NULL:*/&timeout); if (fds) snmp_read(&fdset); else snmp_timeout(); gettimeofday(&nowtime, NULL); } /* Clean up the data in magic */ while (magic.handled) { snmp_ip *tmp = magic.handled->next; free (magic.handled); magic.handled = tmp; } while (magic.detected) { snmp_ip *tmp = magic.detected->next; free (magic.detected); magic.detected = tmp; } } /* Clean up */ snmp_close(ss); SOCK_CLEANUP; DBG (5, "%s: Discovered %d host(s)\n", __func__, magic.nr); return magic.nr; #else DBG (1, "%s: net-snmp library not enabled, auto-detecting network scanners not supported.\n", __func__); NOT_USED (host); return 0; #endif } static SANE_Status attach(const char *name, int type) { SANE_Status status; Magicolor_Scanner *s; DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type); s = device_detect(name, type, &status); if(s == NULL) return status; close_scanner(s); free(s); return status; } SANE_Status attach_one_usb(const char *dev) { DBG(7, "%s: dev = %s\n", __func__, dev); return attach(dev, SANE_MAGICOLOR_USB); } static SANE_Status attach_one_net(const char *dev, unsigned int model) { char name[1024]; DBG(7, "%s: dev = %s\n", __func__, dev); if (model > 0) { snprintf(name, 1024, "net:%s?model=0x%x", dev, model); } else { snprintf(name, 1024, "net:%s", dev); } return attach(name, SANE_MAGICOLOR_NET); } static SANE_Status attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) { int vendor, product, timeout; int len = strlen(line); DBG(7, "%s: len = %d, line = %s\n", __func__, len, line); if (sscanf(line, "usb %i %i", &vendor, &product) == 2) { /* add the vendor and product IDs to the list of * known devices before we call the attach function */ int numIds = sanei_magicolor_getNumberOfUSBProductIds(); if (vendor != SANE_MAGICOLOR_VENDOR_ID) return SANE_STATUS_INVAL; /* this is not a KONICA MINOLTA device */ sanei_magicolor_usb_product_ids[numIds - 1] = product; sanei_usb_attach_matching_devices(line, attach_one_usb); } else if (strncmp(line, "usb", 3) == 0 && len == 3) { int i, numIds; numIds = sanei_magicolor_getNumberOfUSBProductIds(); for (i = 0; i < numIds; i++) { sanei_usb_find_devices(SANE_MAGICOLOR_VENDOR_ID, sanei_magicolor_usb_product_ids[i], attach_one_usb); } } else if (strncmp(line, "net", 3) == 0) { /* remove the "net" sub string */ const char *name = sanei_config_skip_whitespace(line + 3); char IP[1024]; unsigned int model = 0; if (strncmp(name, "autodiscovery", 13) == 0) { DBG (50, "%s: Initiating network autodiscovervy via SNMP\n", __func__); mc_network_discovery(NULL); } else if (sscanf(name, "%s %x", IP, &model) == 2) { DBG(50, "%s: Using network device on IP %s, forcing model 0x%x\n", __func__, IP, model); attach_one_net(IP, model); } else { /* use SNMP to detect the type. If not successful, * add the host with model type 0 */ DBG(50, "%s: Using network device on IP %s, trying to autodetect model\n", __func__, IP); if (mc_network_discovery(name)==0) { DBG(1, "%s: Autodetecting device model failed, using default model\n", __func__); attach_one_net(name, 0); } } } else if (sscanf(line, "snmp-timeout %i\n", &timeout)) { /* Timeout for SNMP network discovery */ DBG(50, "%s: SNMP timeout set to %d\n", __func__, timeout); MC_SNMP_Timeout = timeout; } else if (sscanf(line, "scan-data-timeout %i\n", &timeout)) { /* Timeout for scan data requests */ DBG(50, "%s: Scan data timeout set to %d\n", __func__, timeout); MC_Scan_Data_Timeout = timeout; } else if (sscanf(line, "request-timeout %i\n", &timeout)) { /* Timeout for all other read requests */ DBG(50, "%s: Request timeout set to %d\n", __func__, timeout); MC_Request_Timeout = timeout; } else { /* TODO: Warning about unparsable line! */ } return SANE_STATUS_GOOD; } static void free_devices(void) { Magicolor_Device *dev, *next; DBG(5, "%s\n", __func__); for (dev = first_dev; dev; dev = next) { next = dev->next; free(dev->name); free(dev->model); free(dev); } if (devlist) free(devlist); devlist = NULL; first_dev = NULL; } SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) { DBG_INIT(); DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__); DBG(1, "magicolor backend, version %i.%i.%i\n", MAGICOLOR_VERSION, MAGICOLOR_REVISION, MAGICOLOR_BUILD); if (version_code != NULL) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, MAGICOLOR_BUILD); sanei_usb_init(); return SANE_STATUS_GOOD; } /* Clean up the list of attached scanners. */ void sane_exit(void) { DBG(5, "%s\n", __func__); free_devices(); } SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool __sane_unused__ local_only) { Magicolor_Device *dev, *s, *prev=0; int i; DBG(5, "%s\n", __func__); sanei_usb_init(); /* mark all existing scanners as missing, attach_one will remove mark */ for (s = first_dev; s; s = s->next) { s->missing = 1; } /* Read the config, mark each device as found, possibly add new devs */ sanei_configure_attach(MAGICOLOR_CONFIG_FILE, NULL, attach_one_config); /*delete missing scanners from list*/ for (s = first_dev; s;) { if (s->missing) { DBG (5, "%s: missing scanner %s\n", __func__, s->name); /*splice s out of list by changing pointer in prev to next*/ if (prev) { prev->next = s->next; free (s); s = prev->next; num_devices--; } else { /*remove s from head of list */ first_dev = s->next; free(s); s = first_dev; prev=NULL; num_devices--; } } else { prev = s; s = prev->next; } } DBG (15, "%s: found %d scanner(s)\n", __func__, num_devices); for (s = first_dev; s; s=s->next) { DBG (15, "%s: found scanner %s\n", __func__, s->name); } if (devlist) free (devlist); devlist = malloc((num_devices + 1) * sizeof(devlist[0])); if (!devlist) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } DBG(5, "%s - results:\n", __func__); for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) { DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model); devlist[i] = &dev->sane; } devlist[i] = NULL; if(device_list){ *device_list = devlist; } return SANE_STATUS_GOOD; } static SANE_Status init_options(Magicolor_Scanner *s) { int i; SANE_Word *res_list; for (i = 0; i < NUM_OPTIONS; i++) { s->opt[i].size = sizeof(SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_MODE_GROUP].name = SANE_NAME_STANDARD; s->opt[OPT_MODE_GROUP].title = SANE_TITLE_STANDARD; s->opt[OPT_MODE_GROUP].desc = SANE_DESC_STANDARD; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size(mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = 0; /* Binary */ /* bit depth */ s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_NONE; s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_BIT_DEPTH].constraint.word_list = s->hw->cap->depth_list; s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; s->val[OPT_BIT_DEPTH].w = s->hw->cap->depth_list[1]; /* the first "real" element is the default */ if (s->hw->cap->depth_list[0] == 1) /* only one element in the list -> hide the option */ s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->cap->brightness; s->val[OPT_BRIGHTNESS].w = 5; /* Normal */ /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; res_list = malloc((s->hw->cap->res_list_size + 1) * sizeof(SANE_Word)); if (res_list == NULL) { return SANE_STATUS_NO_MEM; } *(res_list) = s->hw->cap->res_list_size; memcpy(&(res_list[1]), s->hw->cap->res_list, s->hw->cap->res_list_size * sizeof(SANE_Word)); s->opt[OPT_RESOLUTION].constraint.word_list = res_list; s->val[OPT_RESOLUTION].w = s->hw->cap->dpi_range.min; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_PREVIEW].w = SANE_FALSE; /* source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].size = max_string_size(source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].w = 0; /* always use Flatbed as default */ s->opt[OPT_ADF_MODE].name = "adf-mode"; s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode"); s->opt[OPT_ADF_MODE].desc = SANE_I18N("Selects the ADF mode (simplex/duplex)"); s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING; s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list); s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list; s->val[OPT_ADF_MODE].w = 0; /* simplex */ if ((!s->hw->cap->ADF) || (s->hw->cap->adf_duplex == SANE_FALSE)) s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].name = SANE_NAME_GEOMETRY; s->opt[OPT_GEOMETRY_GROUP].title = SANE_TITLE_GEOMETRY; s->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range->max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range->max; return SANE_STATUS_GOOD; } SANE_Status sane_open(SANE_String_Const name, SANE_Handle *handle) { SANE_Status status; Magicolor_Scanner *s = NULL; int l = strlen(name); DBG(7, "%s: name = %s\n", __func__, name); /* probe if empty device name provided */ if (l == 0) { status = sane_get_devices(NULL,0); if (status != SANE_STATUS_GOOD) { return status; } if (first_dev == NULL) { DBG(1, "no device detected\n"); return SANE_STATUS_INVAL; } s = device_detect(first_dev->sane.name, first_dev->connection, &status); if (s == NULL) { DBG(1, "cannot open a perfectly valid device (%s)," " please report to the authors\n", name); return SANE_STATUS_INVAL; } } else { if (strncmp(name, "net:", 4) == 0) { s = device_detect(name, SANE_MAGICOLOR_NET, &status); if (s == NULL) return status; } else if (strncmp(name, "libusb:", 7) == 0) { s = device_detect(name, SANE_MAGICOLOR_USB, &status); if (s == NULL) return status; } else { /* as a last resort, check for a match * in the device list. This should handle platforms without libusb. */ if (first_dev == NULL) { status = sane_get_devices(NULL,0); if (status != SANE_STATUS_GOOD) { return status; } } s = device_detect(name, SANE_MAGICOLOR_NODEV, &status); if (s == NULL) { DBG(1, "invalid device name: %s\n", name); return SANE_STATUS_INVAL; } } } /* s is always valid here */ DBG(1, "handle obtained\n"); init_options(s); *handle = (SANE_Handle) s; status = open_scanner(s); if (status != SANE_STATUS_GOOD) { free(s); return status; } return status; } void sane_close(SANE_Handle handle) { Magicolor_Scanner *s; /* * XXX Test if there is still data pending from * the scanner. If so, then do a cancel */ s = (Magicolor_Scanner *) handle; if (s->fd != -1) close_scanner(s); free(s); } const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; if (option < 0 || option >= NUM_OPTIONS) return NULL; return s->opt + option; } static const SANE_String_Const * search_string_list(const SANE_String_Const *list, SANE_String value) { while (*list != NULL && strcmp(value, *list) != 0) list++; return ((*list == NULL) ? NULL : list); } /* Activate, deactivate an option. Subroutines so we can add debugging info if we want. The change flag is set to TRUE if we changed an option. If we did not change an option, then the value of the changed flag is not modified. */ static void activateOption(Magicolor_Scanner *s, SANE_Int option, SANE_Bool *change) { if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { s->opt[option].cap &= ~SANE_CAP_INACTIVE; *change = SANE_TRUE; } } static void deactivateOption(Magicolor_Scanner *s, SANE_Int option, SANE_Bool *change) { if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { s->opt[option].cap |= SANE_CAP_INACTIVE; *change = SANE_TRUE; } } static SANE_Status getvalue(SANE_Handle handle, SANE_Int option, void *value) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); DBG(17, "%s: option = %d\n", __func__, option); switch (option) { case OPT_NUM_OPTS: case OPT_BIT_DEPTH: case OPT_BRIGHTNESS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *((SANE_Word *) value) = sval->w; break; case OPT_MODE: case OPT_SOURCE: case OPT_ADF_MODE: strcpy((char *) value, sopt->constraint.string_list[sval->w]); break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /* * Handles setting the source (flatbed, or auto document feeder (ADF)). * */ static void change_source(Magicolor_Scanner *s, SANE_Int optindex, char *value) { int force_max = SANE_FALSE; SANE_Bool dummy; DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex, value); if (s->val[OPT_SOURCE].w == optindex) return; s->val[OPT_SOURCE].w = optindex; if (s->val[OPT_TL_X].w == s->hw->x_range->min && s->val[OPT_TL_Y].w == s->hw->y_range->min && s->val[OPT_BR_X].w == s->hw->x_range->max && s->val[OPT_BR_Y].w == s->hw->y_range->max) { force_max = SANE_TRUE; } if (strcmp(ADF_STR, value) == 0) { s->hw->x_range = &s->hw->cap->adf_x_range; s->hw->y_range = &s->hw->cap->adf_y_range; if (s->hw->cap->adf_duplex) { activateOption(s, OPT_ADF_MODE, &dummy); } else { deactivateOption(s, OPT_ADF_MODE, &dummy); s->val[OPT_ADF_MODE].w = 0; } DBG(1, "adf activated (%d)\n",s->hw->cap->adf_duplex); } else { /* ADF not active */ s->hw->x_range = &s->hw->cap->fbf_x_range; s->hw->y_range = &s->hw->cap->fbf_y_range; deactivateOption(s, OPT_ADF_MODE, &dummy); } s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max) s->val[OPT_TL_X].w = s->hw->x_range->min; if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max) s->val[OPT_TL_Y].w = s->hw->y_range->min; if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max) s->val[OPT_BR_X].w = s->hw->x_range->max; if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max) s->val[OPT_BR_Y].w = s->hw->y_range->max; } static SANE_Status setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); SANE_Status status; const SANE_String_Const *optval = NULL; int optindex = 0; SANE_Bool reload = SANE_FALSE; DBG(17, "%s: option = %d, value = %p, as word: %d\n", __func__, option, value, *(SANE_Word *) value); status = sanei_constrain_value(sopt, value, info); if (status != SANE_STATUS_GOOD) return status; if (info && value && (*info & SANE_INFO_INEXACT) && sopt->type == SANE_TYPE_INT) DBG(17, "%s: constrained val = %d\n", __func__, *(SANE_Word *) value); if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) { optval = search_string_list(sopt->constraint.string_list, (char *) value); if (optval == NULL) return SANE_STATUS_INVAL; optindex = optval - sopt->constraint.string_list; } switch (option) { case OPT_MODE: { sval->w = optindex; /* if binary, then disable the bit depth selection */ if (optindex == 0) { s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; } else { if (s->hw->cap->depth_list[0] == 1) s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; else { s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth; } } reload = SANE_TRUE; break; } case OPT_BIT_DEPTH: sval->w = *((SANE_Word *) value); mode_params[s->val[OPT_MODE].w].depth = sval->w; reload = SANE_TRUE; break; case OPT_RESOLUTION: sval->w = *((SANE_Word *) value); DBG(17, "setting resolution to %d\n", sval->w); reload = SANE_TRUE; break; case OPT_BR_X: case OPT_BR_Y: sval->w = *((SANE_Word *) value); if (SANE_UNFIX(sval->w) == 0) { DBG(17, "invalid br-x or br-y\n"); return SANE_STATUS_INVAL; } /* passthru */ case OPT_TL_X: case OPT_TL_Y: sval->w = *((SANE_Word *) value); DBG(17, "setting size to %f\n", SANE_UNFIX(sval->w)); if (NULL != info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_SOURCE: change_source(s, optindex, (char *) value); reload = SANE_TRUE; break; case OPT_ADF_MODE: sval->w = optindex; /* Simple lists */ break; case OPT_BRIGHTNESS: case OPT_PREVIEW: /* needed? */ sval->w = *((SANE_Word *) value); break; default: return SANE_STATUS_INVAL; } if (reload && info != NULL) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; DBG(17, "%s: end\n", __func__); return SANE_STATUS_GOOD; } SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info) { DBG(17, "%s: action = %x, option = %d\n", __func__, action, option); if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_INVAL; if (info != NULL) *info = 0; switch (action) { case SANE_ACTION_GET_VALUE: return getvalue(handle, option, value); case SANE_ACTION_SET_VALUE: return setvalue(handle, option, value, info); default: return SANE_STATUS_INVAL; } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters *params) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; DBG(5, "%s\n", __func__); if (params == NULL) DBG(1, "%s: params is NULL\n", __func__); /* * If sane_start was already called, then just retrieve the parameters * from the scanner data structure */ if (!s->eof && s->ptr != NULL) { DBG(5, "scan in progress, returning saved params structure\n"); } else { /* otherwise initialize the params structure and gather the data */ mc_init_parameters(s); } if (params != NULL) *params = s->params; print_params(s->params); return SANE_STATUS_GOOD; } /* * This function is part of the SANE API and gets called from the front end to * start the scan process. */ SANE_Status sane_start(SANE_Handle handle) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; SANE_Status status; DBG(5, "%s\n", __func__); /* calc scanning parameters */ status = mc_init_parameters(s); if (status != SANE_STATUS_GOOD) return status; print_params(s->params); /* set scanning parameters; also query the current image * parameters from the sanner and save * them to s->params */ status = mc_set_scanning_parameters(s); if (status != SANE_STATUS_GOOD) return status; /* if we scan from ADF, check if it is loaded */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { status = mc_check_adf(s); if (status != SANE_STATUS_GOOD) return status; } /* prepare buffer here so that a memory allocation failure * will leave the scanner in a sane state. */ s->buf = realloc(s->buf, s->block_len); if (s->buf == NULL) return SANE_STATUS_NO_MEM; s->eof = SANE_FALSE; s->ptr = s->end = s->buf; s->canceling = SANE_FALSE; /* start scanning */ DBG(1, "%s: scanning...\n", __func__); status = mc_start_scan(s); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: start failed: %s\n", __func__, sane_strstatus(status)); return status; } return status; } /* this moves data from our buffers to SANE */ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length) { SANE_Status status; Magicolor_Scanner *s = (Magicolor_Scanner *) handle; if (s->buf == NULL || s->canceling) return SANE_STATUS_CANCELLED; *length = 0; status = mc_read(s); if (status == SANE_STATUS_CANCELLED) { mc_scan_finish(s); return status; } DBG(18, "moving data %p %p, %d (%d lines)\n", s->ptr, s->end, max_length, max_length / s->params.bytes_per_line); mc_copy_image_data(s, data, max_length, length); DBG(18, "%d lines read, status: %d\n", *length / s->params.bytes_per_line, status); /* continue reading if appropriate */ if (status == SANE_STATUS_GOOD) return status; mc_scan_finish(s); return status; } /* * void sane_cancel(SANE_Handle handle) * * Set the cancel flag to true. The next time the backend requests data * from the scanner the CAN message will be sent. */ void sane_cancel(SANE_Handle handle) { Magicolor_Scanner *s = (Magicolor_Scanner *) handle; s->canceling = SANE_TRUE; } /* * SANE_Status sane_set_io_mode() * * not supported - for asynchronous I/O */ SANE_Status sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { return SANE_STATUS_UNSUPPORTED; } /* * SANE_Status sane_get_select_fd() * * not supported - for asynchronous I/O */ SANE_Status sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/pixma_io.h0000664000175000017500000001470012775312261014577 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIXMA_IO_H #define PIXMA_IO_H /* TODO: move to pixma_common.h, to reduce the number of files */ /*! * \defgroup IO IO interface * \brief The IO interface. * * Return value of functions that return \c int if not otherwise specified: * - >= if succeeded * - < 0 if failed (e.g. \c PIXMA_ETIMEDOUT) * . * @{ */ /** Timeout for pixma_read() in milliseconds */ #define PIXMA_BULKIN_TIMEOUT 1000 /** Timeout for pixma_write() in milliseconds */ #define PIXMA_BULKOUT_TIMEOUT 1000 struct pixma_io_t; struct pixma_config_t; /** IO handle */ typedef struct pixma_io_t pixma_io_t; /** Initialize IO module. It must be called before any other functions in this * module. * \return 0 on success or * - \c PIXMA_ENOMEM * - \c PIXMA_EACCES * - \c PIXMA_EIO */ int pixma_io_init (void); /** Shutdown all connections and free resources allocated in this module. */ void pixma_io_cleanup (void); /** Find devices currently connected to the computer. * \c devnr passed to functions * - pixma_get_device_config() * - pixma_get_device_id() * - pixma_connect() * . * should be less than the number of devices returned by this function. * \param[in] pixma_devices A \c NULL terminated array of pointers to * array of pixma_config_t which is terminated by setting * pixma_config_t::name to \c NULL. * \return Number of devices found */ unsigned pixma_collect_devices (const char ** conf_devices, const struct pixma_config_t *const pixma_devices[]); /** Get device configuration. */ const struct pixma_config_t *pixma_get_device_config (unsigned devnr); /** Get a unique ID of the device \a devnr. */ const char *pixma_get_device_id (unsigned devnr); /** Connect to the device and claim the scanner interface. * \param[in] devnr * \param[out] handle * \return 0 on success or * - \c PIXMA_ENODEV the device is gone from the system. * - \c PIXMA_EINVAL \a devnr is invalid. * - \c PIXMA_EBUSY * - \c PIXMA_EACCES * - \c PIXMA_ENOMEM * - \c PIXMA_EIO */ int pixma_connect (unsigned devnr, pixma_io_t ** handle); /** Release the scanner interface and disconnect from the device. */ void pixma_disconnect (pixma_io_t *); /** Activate connection to scanner */ int pixma_activate (pixma_io_t *); /** De-activate connection to scanner */ int pixma_deactivate (pixma_io_t *); /** Reset the USB interface. \warning Use with care! */ int pixma_reset_device (pixma_io_t *); /** Write data to the device. This function may not be interrupted by signals. * It will return iff * - \a len bytes have been successfully written or * - an error (inclusive timeout) occured. * . * \note Calling pixma_write(io, buf, n1) and pixma(io, buf+n1, n2) may * not be the same as pixma_write(io, buf, n1+n2) if n1 is not * multiple of the maximum packet size of the endpoint. * \param[in] cmd Data * \param[in] len Length of data * \return Number of bytes successfully written (always = \a len) or * - \c PIXMA_ETIMEDOUT * - \c PIXMA_EIO * - \c PIXMA_ENOMEM * \see #PIXMA_BULKOUT_TIMEOUT */ int pixma_write (pixma_io_t *, const void *cmd, unsigned len); /** Read data from the device. This function may not be interrupted by signals. * It will return iff * - \a size bytes have been successfully read, * - a short packet has been read or * - an error (inclusive timeout) occured. * . * \param[out] buf * \param[in] size of the buffer * \return Number of bytes successfully read. A return value of zero means that * a zero length USB packet was received. Or * - \c PIXMA_ETIMEDOUT * - \c PIXMA_EIO * - \c PIXMA_ENOMEM * \see #PIXMA_BULKIN_TIMEOUT */ int pixma_read (pixma_io_t *, void *buf, unsigned size); /** Wait for an interrupt. This function can be interrupted by signals. * \a size should be less than or equal to the maximum packet size. * \param[out] buf * \param[in] size of the buffer * \param[in] timeout in milliseconds; if < 0, wait forever. * \return Number of bytes successfully read or * - \c PIXMA_ETIMEDOUT * - \c PIXMA_EIO * - \c PIXMA_ENOMEM * - \c PIXMA_ECANCELED if it was interrupted by a signal. */ int pixma_wait_interrupt (pixma_io_t *, void *buf, unsigned size, int timeout); /** Enable or disable background interrupt monitoring. * Background mode is enabled by default. * \param[in] background if not zero, a URB is submitted in background * for interrupt endpoint. * \return 0 on success or * - \c PIXMA_ENOTSUP * - \c PIXMA_EIO * - \c PIXMA_ENOMEM */ int pixma_set_interrupt_mode (pixma_io_t *, int background); /** @} end of IO group */ #endif sane-backends-1.0.27/backend/dc240.h0000664000175000017500000001631412775312260013610 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. dc240.h 03/12/01 - Peter Fales Based on the dc210 driver, (C) 1998 Brian J. Murrell (which is based on dc25 driver (C) 1998 by Peter Fales) This file (C) 2001 by Peter Fales This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for the Kodak DC-240 digital camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! (feedback to: dc240-devel@fales-lorenz.net) This backend is based somewhat on the dc25 backend included in this package by Peter Fales, and the dc210 backend by Brian J. Murrell ***************************************************************************/ #include #include #include #include #include #include #ifndef TRUE #define TRUE (1==1) #endif #ifndef FALSE #define FALSE (!TRUE) #endif #ifndef NULL #define NULL 0L #endif typedef struct picture_info { int low_res; int size; } PictureInfo; typedef struct DC240_s { SANE_Int fd; /* file descriptor to talk to it */ char *tty_name; /* the tty port name it's on */ speed_t baud; /* current tty speed */ SANE_Bool scanning; /* currently scanning an image? */ SANE_Byte model; SANE_Byte ver_major; SANE_Byte ver_minor; SANE_Int pic_taken; SANE_Int pic_left; struct { unsigned int low_res:1; unsigned int low_batt:1; } flags; PictureInfo *Pictures; /* array of pictures */ SANE_Int current_picture_number; /* picture being operated on */ } DC240; typedef struct dc240_info_s { SANE_Byte model; SANE_Byte ver_major; SANE_Byte ver_minor; SANE_Int pic_taken; SANE_Int pic_left; struct { SANE_Int low_res:1; SANE_Int low_batt:1; } flags; } Dc240Info, *Dc240InfoPtr; static SANE_Int get_info (DC240 *); #define INIT_PCK {0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^^^^^^^ * Baud rate: (see pkt_speed structure) * 0x96 0x00 -> 9600 baud * 0x19 0x20 -> 19200 baud * 0x38 0x40 -> 38400 baud * 0x57 0x60 -> 57600 baud * 0x11 0x52 -> 115200 baud */ #define INFO_PCK {0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define SHOOT_PCK {0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define ERASE_PCK {0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define RES_PCK {0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * Resolution: 0x00 = low, 0x01 = high */ #define THUMBS_PCK {0x93, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x1A} /* * */ #define PICS_PCK {0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* * */ #define PICS_INFO_PCK {0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* * */ #define OPEN_CARD_PCK {0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define READ_DIR_PCK {0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * 1=Report number of entries only */ struct pkt_speed { speed_t baud; SANE_Byte pkt_code[2]; }; #if defined (B57600) && defined (B115200) # define SPEEDS { { B9600, { 0x96, 0x00 } }, \ { B19200, { 0x19, 0x20 } }, \ { B38400, { 0x38, 0x40 } }, \ { B57600, { 0x57, 0x60 } }, \ { B115200, { 0x11, 0x52 } } } #else # define SPEEDS { { B9600, { 0x96, 0x00 } }, \ { B19200, { 0x19, 0x20 } }, \ { B38400, { 0x38, 0x40 } } } #endif #define HIGH_RES 0 #define LOW_RES 1 #define HIGHRES_WIDTH 1280 #define HIGHRES_HEIGHT 960 #define LOWRES_WIDTH 640 #define LOWRES_HEIGHT 480 /* * External definitions */ extern char *__progname; /* Defined in /usr/lib/crt0.o */ struct cam_dirent { SANE_Char name[11]; SANE_Byte attr; SANE_Byte create_time[2]; SANE_Byte creat_date[2]; long size; }; #ifdef OLD /* This is the layout of the directory in the camera - Unfortunately, * this only works in gcc. */ struct dir_buf { SANE_Byte entries_msb PACKED; SANE_Byte entries_lsb PACKED; struct cam_dirent entry[1000] PACKED; }; #else /* So, we have to do it the hard way... */ #define CAMDIRENTRYSIZE 20 #define DIRENTRIES 1000 #define get_name(entry) (SANE_Char*) &dir_buf2[2+CAMDIRENTRYSIZE*(entry)] #define get_attr(entry) dir_buf2[2+11+CAMDIRENTRYSIZE*(entry)] #define get_create_time(entry) \ ( dir_buf2[2+12+CAMDIRENTRYSIZE*(entry)] << 8 \ + dir_buf2[2+13+CAMDIRENTRYSIZE*(entry)]) #endif struct cam_dirlist { SANE_Char name[48]; struct cam_dirlist *next; }; #include FILE *sanei_config_open (const char *filename); static SANE_Int init_dc240 (DC240 *); static void close_dc240 (SANE_Int); static SANE_Int read_data (SANE_Int fd, SANE_Byte * buf, SANE_Int sz); static SANE_Int end_of_data (SANE_Int fd); static PictureInfo *get_pictures_info (void); static SANE_Int get_picture_info (PictureInfo * pic, SANE_Int p); static SANE_Status snap_pic (SANE_Int fd); char *sanei_config_read (char *str, int n, FILE * stream); static SANE_Int read_dir (SANE_String dir); static SANE_Int read_info (SANE_String fname); static SANE_Int dir_insert (struct cam_dirent *entry); static SANE_Int dir_delete (SANE_String name); static SANE_Int send_data (SANE_Byte * buf); static void set_res (SANE_Int lowres); sane-backends-1.0.27/backend/hp-device.c0000664000175000017500000003371112775312261014634 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ /*#define STUBS extern int sanei_debug_hp;*/ #define DEBUG_DECLARE_ONLY #include "../include/sane/config.h" #include #include #include "../include/lassert.h" #include "hp-device.h" #include "hp-accessor.h" #include "hp-option.h" #include "hp-scsi.h" #include "hp-scl.h" /* Mark an scl-command to be simulated */ SANE_Status sanei_hp_device_simulate_set (const char *devname, HpScl scl, int flag) {HpDeviceInfo *info; int inqid; info = sanei_hp_device_info_get ( devname ); if (!info) return SANE_STATUS_INVAL; inqid = SCL_INQ_ID(scl)-HP_SCL_INQID_MIN; info->simulate.sclsimulate[inqid] = flag; DBG(3, "hp_device_simulate_set: %d set to %ssimulated\n", inqid+HP_SCL_INQID_MIN, flag ? "" : "not "); return SANE_STATUS_GOOD; } /* Clear all simulation flags */ void sanei_hp_device_simulate_clear (const char *devname) {HpDeviceInfo *info; info = sanei_hp_device_info_get ( devname ); if (!info) return; memset (&(info->simulate.sclsimulate[0]), 0, sizeof (info->simulate.sclsimulate)); info->simulate.gamma_simulate = 0; } /* Get simulate flag for an scl-command */ hp_bool_t sanei_hp_device_simulate_get (const char *devname, HpScl scl) {HpDeviceInfo *info; int inqid; info = sanei_hp_device_info_get ( devname ); if (!info) return 0; inqid = SCL_INQ_ID(scl)-HP_SCL_INQID_MIN; return info->simulate.sclsimulate[inqid]; } SANE_Status sanei_hp_device_support_get (const char *devname, HpScl scl, int *minval, int *maxval) {HpDeviceInfo *info; HpSclSupport *sclsupport; int inqid; /* #define HP_TEST_SIMULATE */ #ifdef HP_TEST_SIMULATE if (scl == SCL_BRIGHTNESS) return SANE_STATUS_UNSUPPORTED; if (scl == SCL_CONTRAST) return SANE_STATUS_UNSUPPORTED; if (scl == SCL_DOWNLOAD_TYPE) { *minval = 2; *maxval = 14; return SANE_STATUS_GOOD; } #endif info = sanei_hp_device_info_get ( devname ); if (!info) return SANE_STATUS_INVAL; inqid = SCL_INQ_ID(scl)-HP_SCL_INQID_MIN; sclsupport = &(info->sclsupport[inqid]); if ( !(sclsupport->checked) ) return SANE_STATUS_INVAL; if ( !(sclsupport->is_supported) ) return SANE_STATUS_UNSUPPORTED; if (minval) *minval = sclsupport->minval; if (maxval) *maxval = sclsupport->maxval; return SANE_STATUS_GOOD; } /* Update the list of supported commands */ SANE_Status sanei_hp_device_support_probe (HpScsi scsi) {HpDeviceInfo *info; HpSclSupport *sclsupport; SANE_Status status; int k, val, inqid; static HpScl sclprobe[] = /* The commands that should be probed */ { SCL_AUTO_BKGRND, SCL_COMPRESSION, SCL_DOWNLOAD_TYPE, SCL_X_SCALE, SCL_Y_SCALE, SCL_DATA_WIDTH, SCL_INVERSE_IMAGE, SCL_BW_DITHER, SCL_CONTRAST, SCL_BRIGHTNESS, #ifdef SCL_SHARPENING SCL_SHARPENING, #endif SCL_MIRROR_IMAGE, SCL_X_RESOLUTION, SCL_Y_RESOLUTION, SCL_OUTPUT_DATA_TYPE, SCL_PRELOAD_ADF, SCL_MEDIA, SCL_X_EXTENT, SCL_Y_EXTENT, SCL_X_POS, SCL_Y_POS, SCL_SPEED, SCL_FILTER, SCL_TONE_MAP, SCL_MATRIX, SCL_UNLOAD, SCL_CHANGE_DOC, SCL_ADF_BFEED }; enum hp_device_compat_e compat; DBG(1, "hp_device_support_probe: Check supported commands for %s\n", sanei_hp_scsi_devicename (scsi) ); info = sanei_hp_device_info_get ( sanei_hp_scsi_devicename (scsi) ); assert (info); memset (&(info->sclsupport[0]), 0, sizeof (info->sclsupport)); for (k = 0; k < (int)(sizeof (sclprobe) / sizeof (sclprobe[0])); k++) { inqid = SCL_INQ_ID(sclprobe[k])-HP_SCL_INQID_MIN; sclsupport = &(info->sclsupport[inqid]); status = sanei_hp_scl_inquire (scsi, sclprobe[k], &val, &(sclsupport->minval), &(sclsupport->maxval)); sclsupport->is_supported = (status == SANE_STATUS_GOOD); sclsupport->checked = 1; /* The OfficeJets seem to ignore brightness and contrast settings, * so we'll pretend they're not supported at all. */ if (((sclprobe[k]==SCL_BRIGHTNESS) || (sclprobe[k]==SCL_CONTRAST)) && (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_OJ_1150C)) { sclsupport->is_supported=0; } if (sclsupport->is_supported) { DBG(1, "hp_device_support_probe: %d supported (%d..%d, %d)\n", inqid+HP_SCL_INQID_MIN, sclsupport->minval, sclsupport->maxval, val); } else { DBG(1, "hp_device_support_probe: %d not supported\n", inqid+HP_SCL_INQID_MIN); } } return SANE_STATUS_GOOD; } SANE_Status sanei_hp_device_probe_model (enum hp_device_compat_e *compat, HpScsi scsi, int *model_num, const char **model_name) { static struct { HpScl cmd; int model_num; const char * model; enum hp_device_compat_e flag; } probes[] = { { SCL_HP_MODEL_1, 1, "ScanJet Plus", HP_COMPAT_PLUS }, { SCL_HP_MODEL_2, 2, "ScanJet IIc", HP_COMPAT_2C }, { SCL_HP_MODEL_3, 3, "ScanJet IIp", HP_COMPAT_2P }, { SCL_HP_MODEL_4, 4, "ScanJet IIcx", HP_COMPAT_2CX }, { SCL_HP_MODEL_5, 5, "ScanJet 3c/4c/6100C", HP_COMPAT_4C }, { SCL_HP_MODEL_6, 6, "ScanJet 3p", HP_COMPAT_3P }, { SCL_HP_MODEL_8, 8, "ScanJet 4p", HP_COMPAT_4P }, { SCL_HP_MODEL_9, 9, "ScanJet 5p/4100C/5100C", HP_COMPAT_5P }, { SCL_HP_MODEL_10,10,"PhotoSmart Photo Scanner", HP_COMPAT_PS }, { SCL_HP_MODEL_11,11,"OfficeJet 1150C", HP_COMPAT_OJ_1150C }, { SCL_HP_MODEL_12,12,"OfficeJet 1170C or later", HP_COMPAT_OJ_1170C }, { SCL_HP_MODEL_14,14,"ScanJet 62x0C", HP_COMPAT_6200C }, { SCL_HP_MODEL_16,15,"ScanJet 5200C", HP_COMPAT_5200C }, { SCL_HP_MODEL_17,17,"ScanJet 63x0C", HP_COMPAT_6300C } }; int i; char buf[8]; SANE_Status status; static char *last_device = NULL; static enum hp_device_compat_e last_compat; static int last_model_num = -1; static const char *last_model_name = "Model Unknown"; assert(scsi); DBG(1, "probe_scanner: Probing %s\n", sanei_hp_scsi_devicename (scsi)); if (last_device != NULL) /* Look if we already probed the device */ { if (strcmp (last_device, sanei_hp_scsi_devicename (scsi)) == 0) { DBG(3, "probe_scanner: use cached compatibility flags\n"); *compat = last_compat; if (model_num) *model_num = last_model_num; if (model_name) *model_name = last_model_name; return SANE_STATUS_GOOD; } sanei_hp_free (last_device); last_device = NULL; } *compat = 0; last_model_num = -1; last_model_name = "Model Unknown"; for (i = 0; i < (int)(sizeof(probes)/sizeof(probes[0])); i++) { DBG(1,"probing %s\n",probes[i].model); if (!FAILED( status = sanei_hp_scl_upload(scsi, probes[i].cmd, buf, sizeof(buf)) )) { DBG(1, "probe_scanner: %s compatible (%5s)\n", probes[i].model, buf); last_model_name = probes[i].model; /* Some scanners have different responses */ if (probes[i].model_num == 9) { if (strncmp (buf, "5110A", 5) == 0) last_model_name = "ScanJet 5p"; else if (strncmp (buf, "5190A", 5) == 0) last_model_name = "ScanJet 5100C"; else if (strncmp (buf, "6290A", 5) == 0) last_model_name = "ScanJet 4100C"; } *compat |= probes[i].flag; last_model_num = probes[i].model_num; } else if (!UNSUPPORTED( status )) return status; /* SCL inquiry failed */ } /* Save values for next call */ last_device = sanei_hp_strdup (sanei_hp_scsi_devicename (scsi)); last_compat = *compat; if (model_num) *model_num = last_model_num; if (model_name) *model_name = last_model_name; return SANE_STATUS_GOOD; } SANE_Status sanei_hp_device_probe (enum hp_device_compat_e *compat, HpScsi scsi) { return sanei_hp_device_probe_model (compat, scsi, 0, 0); } hp_bool_t sanei_hp_device_compat (HpDevice this, enum hp_device_compat_e which) { return (this->compat & which) != 0; } static SANE_Status hp_nonscsi_device_new (HpDevice * newp, const char * devname, HpConnect connect) { HpDevice this; HpScsi scsi; SANE_Status status; const char * model_name = "ScanJet"; if (FAILED( sanei_hp_nonscsi_new(&scsi, devname, connect) )) { DBG(1, "%s: Can't open nonscsi device\n", devname); return SANE_STATUS_INVAL; /* Can't open device */ } /* reset scanner; returns all parameters to defaults */ if (FAILED( sanei_hp_scl_reset(scsi) )) { DBG(1, "hp_nonscsi_device_new: SCL reset failed\n"); sanei_hp_scsi_destroy(scsi,1); return SANE_STATUS_IO_ERROR; } /* Things seem okay, allocate new device */ this = sanei_hp_allocz(sizeof(*this)); this->data = sanei_hp_data_new(); if (!this || !this->data) return SANE_STATUS_NO_MEM; this->sanedev.name = sanei_hp_strdup(devname); if (!this->sanedev.name) return SANE_STATUS_NO_MEM; this->sanedev.vendor = "Hewlett-Packard"; this->sanedev.type = "flatbed scanner"; status = sanei_hp_device_probe_model (&(this->compat), scsi, 0, &model_name); if (!FAILED(status)) { sanei_hp_device_support_probe (scsi); status = sanei_hp_optset_new(&(this->options), scsi, this); } sanei_hp_scsi_destroy(scsi,1); if (!model_name) model_name = "ScanJet"; this->sanedev.model = sanei_hp_strdup (model_name); if (!this->sanedev.model) return SANE_STATUS_NO_MEM; if (FAILED(status)) { DBG(1, "hp_nonscsi_device_new: %s: probe failed (%s)\n", devname, sane_strstatus(status)); sanei_hp_data_destroy(this->data); sanei_hp_free((void *)this->sanedev.name); sanei_hp_free((void *)this->sanedev.model); sanei_hp_free(this); return status; } DBG(1, "hp_nonscsi_device_new: %s: found HP ScanJet model %s\n", devname, this->sanedev.model); *newp = this; return SANE_STATUS_GOOD; } SANE_Status sanei_hp_device_new (HpDevice * newp, const char * devname) { HpDevice this; HpScsi scsi; HpConnect connect; SANE_Status status; char * str; DBG(3, "sanei_hp_device_new: %s\n", devname); connect = sanei_hp_get_connect (devname); if ( connect != HP_CONNECT_SCSI ) return hp_nonscsi_device_new (newp, devname, connect); if (FAILED( sanei_hp_scsi_new(&scsi, devname) )) { DBG(1, "%s: Can't open scsi device\n", devname); return SANE_STATUS_INVAL; /* Can't open device */ } if (sanei_hp_scsi_inq(scsi)[0] != 0x03 || memcmp(sanei_hp_scsi_vendor(scsi), "HP ", 8) != 0) { DBG(1, "%s: does not seem to be an HP scanner\n", devname); sanei_hp_scsi_destroy(scsi,1); return SANE_STATUS_INVAL; } /* reset scanner; returns all parameters to defaults */ if (FAILED( sanei_hp_scl_reset(scsi) )) { DBG(1, "sanei_hp_device_new: SCL reset failed\n"); sanei_hp_scsi_destroy(scsi,1); return SANE_STATUS_IO_ERROR; } /* Things seem okay, allocate new device */ this = sanei_hp_allocz(sizeof(*this)); this->data = sanei_hp_data_new(); if (!this || !this->data) return SANE_STATUS_NO_MEM; this->sanedev.name = sanei_hp_strdup(devname); str = sanei_hp_strdup(sanei_hp_scsi_model(scsi)); if (!this->sanedev.name || !str) return SANE_STATUS_NO_MEM; this->sanedev.model = str; if ((str = strchr(str, ' ')) != 0) *str = '\0'; this->sanedev.vendor = "Hewlett-Packard"; this->sanedev.type = "flatbed scanner"; status = sanei_hp_device_probe(&(this->compat), scsi); if (!FAILED(status)) { sanei_hp_device_support_probe (scsi); status = sanei_hp_optset_new(&this->options, scsi, this); } sanei_hp_scsi_destroy(scsi,1); if (FAILED(status)) { DBG(1, "sanei_hp_device_new: %s: probe failed (%s)\n", devname, sane_strstatus(status)); sanei_hp_data_destroy(this->data); sanei_hp_free((void *)this->sanedev.name); sanei_hp_free((void *)this->sanedev.model); sanei_hp_free(this); return status; } DBG(1, "sanei_hp_device_new: %s: found HP ScanJet model %s\n", devname, this->sanedev.model); *newp = this; return SANE_STATUS_GOOD; } const SANE_Device * sanei_hp_device_sanedevice (HpDevice this) { return &this->sanedev; } sane-backends-1.0.27/backend/u12-motor.c0000664000175000017500000003561612112021330014516 00000000000000/* @file u12-motor.c * @brief all functions for motor control * * based on sources acquired from Plustek Inc. * Copyright (C) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /*************************** some definitons *********************************/ #define _BACKSTEPS 120 #define _FORWARDSTEPS 120 /**************************** local vars *************************************/ static TimerDef u12motor_Timer; /*************************** local functions *********************************/ /** */ static void u12motor_DownloadNullScanStates( U12_Device *dev ) { memset( dev->scanStates, 0, _SCANSTATE_BYTES ); u12io_DownloadScanStates( dev ); } /** */ static void u12motor_Force16Steps( U12_Device *dev, int dir ) { u_long dw; if( dir == _DIR_FW ) u12io_DataToRegister( dev, REG_MOTOR0CONTROL, _FORWARD_MOTOR ); else if( dir == _DIR_BW ) u12io_DataToRegister( dev, REG_MOTOR0CONTROL, _BACKWARD_MOTOR ); for( dw = 16; dw; dw-- ) { u12io_RegisterToScanner( dev, REG_FORCESTEP ); _DODELAY( 10 ); } } /** */ static void u12motor_ModuleFreeRun( U12_Device *dev, u_long steps ) { SANE_Byte rb[6]; rb[0] = REG_MOTORFREERUNCOUNT1; rb[1] = _HIBYTE(steps); rb[2] = REG_MOTORFREERUNCOUNT0; rb[3] = _LOBYTE(steps); rb[4] = REG_MOTORFREERUNTRIGGER; rb[5] = 0; u12io_DataToRegs( dev, rb, 3 ); } /** */ static SANE_Status u12motor_PositionYProc( U12_Device *dev, u_long steps ) { TimerDef timer; DBG( _DBG_INFO, "u12motor_PositionYProc()\n" ); u12io_StartTimer( &timer, _SECOND * 5 ); u12io_ResetFifoLen(); while(!(u12io_GetScanState( dev ) & _SCANSTATE_STOP) && (!u12io_CheckTimer( &timer ))); _DODELAY( 12 ); u12motor_ModuleFreeRun( dev, steps ); _DODELAY( 15 ); u12io_StartTimer( &timer, _SECOND * 30 ); do { if( !(u12io_GetExtendedStatus( dev ) & _STILL_FREE_RUNNING)) { break; } if( u12io_IsEscPressed()) { DBG( _DBG_INFO, "* CANCEL detected!\n" ); return SANE_STATUS_CANCELLED; } } while( !u12io_CheckTimer( &timer )); DBG( _DBG_INFO, "u12motor_PositionYProc() - done\n" ); return SANE_STATUS_GOOD; } /** initialize this module and setup the correct function pointer according * to the ASIC */ static void u12motor_PositionModuleToHome( U12_Device *dev ) { SANE_Byte rb[50]; SANE_Byte save, saveModel; int c = 0; DBG( _DBG_INFO, "u12motor_PositionModuleToHome()\n" ); saveModel = dev->regs.RD_ModelControl; dev->scan.refreshState = SANE_FALSE; u12motor_DownloadNullScanStates( dev ); _DODELAY( 125 ); save = dev->shade.intermediate; dev->shade.intermediate = _ScanMode_AverageOut; u12hw_InitAsic( dev, SANE_FALSE ); dev->shade.intermediate = save; _SET_REG( rb, c, REG_MODECONTROL, _ModeScan ); _SET_REG( rb, c, REG_RESETMTSC, 0 ); _SET_REG( rb, c, REG_SCANCONTROL1, 0 ); _SET_REG( rb, c, REG_MODELCONTROL, (dev->ModelCtrl | _MODEL_DPI300)); _SET_REG( rb, c, REG_LINECONTROL, 80 ); _SET_REG( rb, c, REG_XSTEPTIME, dev->XStepBack ); _SET_REG( rb, c, REG_MOTORDRVTYPE, dev->MotorPower ); _SET_REG( rb, c, REG_MOTOR0CONTROL, (_MotorHHomeStop | _MotorOn | _MotorHQuarterStep | _MotorPowerEnable)); _SET_REG( rb, c, REG_STEPCONTROL, (_MOTOR0_SCANSTATE | _MOTOR_FREERUN)); u12io_DataToRegs( dev, rb, c ); memset( dev->scanStates, 0x88, _SCANSTATE_BYTES ); u12io_DownloadScanStates( dev ); u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); dev->regs.RD_ModelControl = saveModel; } /** function to bring the sensor back home */ static void u12motor_ToHomePosition( U12_Device *dev, SANE_Bool wait ) { TimerDef timer; DBG( _DBG_INFO, "Waiting for Sensor to be back in position\n" ); if( !(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) { u12motor_PositionModuleToHome( dev ); if( wait ) { u12io_StartTimer( &timer, _SECOND * 20); do { if( u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER) break; } while( !u12io_CheckTimer( &timer )); } } DBG( _DBG_INFO, "- done !\n" ); } /** */ static SANE_Status u12motor_BackToHomeSensor( U12_Device *dev ) { SANE_Byte rb[20]; int c; TimerDef timer; DBG( _DBG_INFO, "u12Motor_BackToHomeSensor()\n" ); c = 0; _SET_REG( rb, c, REG_STEPCONTROL, _MOTOR0_SCANSTATE ); _SET_REG( rb, c, REG_MODECONTROL, _ModeScan ); u12io_DataToRegs( dev, rb, c ); u12motor_Force16Steps( dev, _DIR_NONE ); /* stepping every state */ memset( dev->scanStates, 0x88, _SCANSTATE_BYTES ); u12io_DownloadScanStates( dev ); _DODELAY(50); u12io_StartTimer( &timer, _SECOND * 2 ); u12io_ResetFifoLen(); while(!(u12io_GetScanState( dev ) & _SCANSTATE_STOP) && !u12io_CheckTimer( &timer )) { if( u12io_IsEscPressed()) { DBG( _DBG_INFO, "* CANCEL detected!\n" ); return SANE_STATUS_CANCELLED; } } u12motor_Force16Steps( dev, _DIR_BW ); dev->regs.RD_ModeControl = _ModeScan; c = 0; if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA)) { _SET_REG( rb, c, REG_LINECONTROL, _LOBYTE(dev->shade.wExposure)); _SET_REG( rb, c, REG_XSTEPTIME, _LOBYTE(dev->shade.wXStep)); } else { _SET_REG( rb, c, REG_LINECONTROL, _DEFAULT_LINESCANTIME ); _SET_REG( rb, c, REG_XSTEPTIME, 6 ); } _SET_REG( rb, c, REG_STEPCONTROL, (_MOTOR_FREERUN | _MOTOR0_SCANSTATE)); _SET_REG( rb, c, REG_MOTOR0CONTROL, (_MotorHQuarterStep | _MotorOn | _MotorDirBackward | _MotorPowerEnable | _MotorHHomeStop)); _SET_REG( rb, c, REG_REFRESHSCANSTATE, 0); u12io_DataToRegs( dev, rb, c ); u12io_StartTimer( &timer, _SECOND * 5 ); do { if( u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER ) break; if( u12io_IsEscPressed()) { DBG( _DBG_INFO, "* CANCEL detected!\n" ); return SANE_STATUS_CANCELLED; } _DODELAY( 55 ); } while( !u12io_CheckTimer( &timer )); c = 0; _SET_REG( rb, c, REG_LINECONTROL, dev->regs.RD_LineControl); _SET_REG( rb, c, REG_XSTEPTIME, dev->regs.RD_XStepTime); u12io_DataToRegs( dev, rb, c ); DBG( _DBG_INFO, "* LineCtrl=0x%02x, XStepTime=0x%02x\n", dev->regs.RD_LineControl, dev->regs.RD_XStepTime ); u12motor_DownloadNullScanStates( dev ); return SANE_STATUS_GOOD; } /** */ static SANE_Status u12motor_ModuleToHome( U12_Device *dev ) { SANE_Status res; DBG( _DBG_INFO, "u12motor_ModuleToHome()\n" ); if(!(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) { u12io_DataToRegister( dev, REG_MOTOR0CONTROL, (SANE_Byte)(dev->regs.RD_Motor0Control|_MotorDirForward)); res = u12motor_PositionYProc( dev, 40 ); if( SANE_STATUS_GOOD != res ) return res; res = u12motor_BackToHomeSensor( dev ); if( SANE_STATUS_GOOD != res ) return res; _DODELAY( 250 ); } DBG( _DBG_INFO, "* done.\n" ); return SANE_STATUS_GOOD; } /** */ static SANE_Status u12motor_WaitForPositionY( U12_Device *dev ) { SANE_Byte rb[20]; SANE_Status res; SANE_Byte bXStep; int c; u_long dwBeginY; c = 0; dwBeginY = (u_long)dev->DataInf.crImage.y * 4 + dev->scan.dwScanOrigin; if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { if( dev->f0_8_16 ) dwBeginY += 16; else dwBeginY += 8; } bXStep = (SANE_Byte)((dev->DataInf.wPhyDataType <= COLOR_256GRAY) ? dev->XStepMono : dev->XStepColor); if( dev->shade.intermediate & _ScanMode_AverageOut ) bXStep = 8; u12motor_Force16Steps( dev, _DIR_NONE ); dwBeginY -= 16; if( dwBeginY > (_RFT_SCANNING_ORG + _YOFFSET) && bXStep < dev->regs.RD_XStepTime ) { u12io_DataToRegister( dev, REG_MOTORDRVTYPE, dev->MotorPower ); _DODELAY( 12 ); u12io_DataToRegister( dev, REG_XSTEPTIME, bXStep); u12io_DataToRegister( dev, REG_EXTENDEDXSTEP, 0 ); u12io_DataToRegister( dev, REG_SCANCONTROL1, (SANE_Byte)(dev->regs.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); res = u12motor_PositionYProc( dev, dwBeginY - 64 ); if( SANE_STATUS_GOOD != res ) return res; dwBeginY = 64; } else { _SET_REG(rb, c, REG_SCANCONTROL1, dev->regs.RD_ScanControl1 ); } _SET_REG( rb, c, REG_FIFOFULLEN0, _LOBYTE(dev->regs.RD_BufFullSize)); _SET_REG( rb, c, REG_FIFOFULLEN1, _HIBYTE(dev->regs.RD_BufFullSize)); _SET_REG( rb, c, REG_FIFOFULLEN2, _LOBYTE(_HIWORD(dev->regs.RD_BufFullSize))); u12io_DataToRegs( dev, rb, c ); u12io_DataToRegister( dev, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType); _DODELAY( 12 ); if(!dev->f2003 || (dev->shade.intermediate & _ScanMode_AverageOut) || ( dev->DataInf.xyAppDpi.y <= 75 && dev->DataInf.wPhyDataType <= COLOR_256GRAY)) { u12io_DataToRegister( dev, REG_MOTORDRVTYPE, (SANE_Byte)(dev->MotorPower & (_MOTORR_MASK | _MOTORR_STRONG))); } else { u12io_DataToRegister( dev, REG_MOTORDRVTYPE, dev->regs.RD_MotorDriverType ); } c = 0; _SET_REG( rb, c, REG_XSTEPTIME, dev->regs.RD_XStepTime ); _SET_REG( rb, c, REG_EXTENDEDXSTEP, dev->regs.RD_ExtXStepTime ); _SET_REG( rb, c, REG_SCANCONTROL1, (SANE_Byte)(dev->regs.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); u12io_DataToRegs( dev, rb, c ); if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) { TimerDef timer; u12motor_ModuleFreeRun( dev, dwBeginY ); _DODELAY( 15 ); u12io_StartTimer( &timer, (_SECOND * 20)); while(( u12io_GetExtendedStatus( dev ) & _STILL_FREE_RUNNING) && !u12io_CheckTimer(&timer)); u12io_DataToRegister( dev, REG_MODECONTROL, _ModeScan ); } else { u12motor_PositionYProc( dev, dwBeginY ); u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); } return SANE_STATUS_GOOD; } /** */ static void u12motor_ForceToLeaveHomePos( U12_Device *dev ) { SANE_Byte rb[4]; TimerDef timer; DBG( _DBG_INFO, "u12motor_ForceToLeaveHomePos()\n" ); rb[0] = REG_STEPCONTROL; rb[1] = _MOTOR0_ONESTEP; rb[2] = REG_MOTOR0CONTROL; rb[3] = _FORWARD_MOTOR; u12io_DataToRegs( dev, rb, 2 ); u12io_StartTimer( &timer, _SECOND ); do { if( !(u12io_DataFromRegister( dev, REG_STATUS ) & _FLAG_PAPER)) break; u12io_RegisterToScanner( dev, REG_FORCESTEP ); _DODELAY( 10 ); } while( !u12io_CheckTimer( &timer )); u12io_DataToRegister( dev, REG_STEPCONTROL, _MOTOR0_SCANSTATE ); } /** move the sensor to the appropriate shading position */ static SANE_Status u12motor_GotoShadingPosition( U12_Device *dev ) { SANE_Byte rb[20]; SANE_Status res; int c; DBG( _DBG_INFO, "u12motor_GotoShadingPosition()\n" ); res = u12motor_ModuleToHome( dev ); if( SANE_STATUS_GOOD == res ) return res; /* position to somewhere under the transparency adapter */ if( dev->DataInf.dwScanFlag & _SCANDEF_TPA ) { u12motor_ForceToLeaveHomePos( dev ); u12motor_DownloadNullScanStates( dev ); c = 0; _SET_REG( rb, c, REG_STEPCONTROL, _MOTOR0_SCANSTATE ); _SET_REG( rb, c, REG_MODECONTROL, _ModeScan); _SET_REG( rb, c, REG_MOTOR0CONTROL, _FORWARD_MOTOR ); _SET_REG( rb, c, REG_XSTEPTIME, 6); _SET_REG( rb, c, REG_EXTENDEDXSTEP, 0); _SET_REG( rb, c, REG_SCANCONTROL1, _MFRC_BY_XSTEP); u12io_DataToRegs( dev, rb, c ); res = u12motor_PositionYProc( dev, _TPA_SHADINGORG ); if( SANE_STATUS_GOOD != res ) return res; } DBG( _DBG_INFO, "* Position reached\n" ); return SANE_STATUS_GOOD; } /** */ static void u12motor_ModuleForwardBackward( U12_Device *dev ) { DBG( _DBG_INFO, "u12motor_ModuleForwardBackward()\n" ); switch( dev->scan.bModuleState ) { case _MotorInNormalState: DBG( _DBG_INFO, "* _MotorInNormalState\n" ); dev->scan.bModuleState = _MotorGoBackward; u12io_DataToRegister( dev, REG_SCANCONTROL1, (SANE_Byte)(dev->regs.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); u12io_DataToRegister( dev, REG_MOTOR0CONTROL, (SANE_Byte)(dev->regs.RD_Motor0Control & ~_MotorDirForward)); u12motor_ModuleFreeRun( dev, _BACKSTEPS ); u12io_StartTimer( &u12motor_Timer, (15 * _MSECOND)); break; case _MotorGoBackward: DBG( _DBG_INFO, "* _MotorGoBackward\n" ); if( u12io_CheckTimer( &u12motor_Timer)) { if(!(u12io_GetExtendedStatus( dev ) & _STILL_FREE_RUNNING )) { dev->scan.bModuleState = _MotorInStopState; u12io_StartTimer( &u12motor_Timer, (50 *_MSECOND)); } } break; case _MotorInStopState: DBG( _DBG_INFO, "* _MotorInStopState\n" ); if( u12io_CheckTimer( &u12motor_Timer )) { if( u12io_GetFifoLength( dev ) < dev->scan.dwMaxReadFifo ) { dev->scan.bModuleState = _MotorAdvancing; u12io_DataToRegister( dev, REG_SCANCONTROL1, dev->regs.RD_ScanControl1); u12io_DataToRegister( dev, REG_MOTOR0CONTROL, dev->regs.RD_Motor0Control); u12motor_ModuleFreeRun( dev, _FORWARDSTEPS ); u12io_StartTimer( &u12motor_Timer, (15 * _MSECOND)); } } break; case _MotorAdvancing: DBG( _DBG_INFO, "* _MotorAdvancing\n" ); if( u12io_CheckTimer( &u12motor_Timer)) { if( !(u12io_GetScanState( dev ) & _SCANSTATE_STOP)) dev->scan.bModuleState = _MotorInNormalState; else { if (!(u12io_GetExtendedStatus( dev ) & _STILL_FREE_RUNNING )) { u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); dev->scan.bModuleState = _MotorInNormalState; } } } break; } } /* END U12-MOTOR.C ..........................................................*/ sane-backends-1.0.27/backend/epson2.c0000664000175000017500000017031012775312261014173 00000000000000/* * epson2.c - SANE library for Epson scanners. * * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for additional copyrights. * * Copyright (C) 2006-10 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define EPSON2_VERSION 1 #define EPSON2_REVISION 0 #define EPSON2_BUILD 124 /* debugging levels: * * 127 e2_recv buffer * 125 e2_send buffer * 32 more network progression * 24 network header * 23 network info * 20 usb cmd counters * 18 sane_read * 17 setvalue, getvalue, control_option * 16 gamma table * 15 e2_send, e2_recv calls * 13 e2_cmd_info_block * 12 epson_cmd_simple * 11 even more * 10 more debug in ESC/I commands * 9 ESC x/FS x in e2_send * 8 ESC/I commands * 7 open/close/attach * 6 print_params * 5 basic functions * 3 status information * 1 scanner info and capabilities * warnings */ #include "sane/config.h" #include "epson2.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #include "sane/saneopts.h" #include "sane/sanei_scsi.h" #include "sane/sanei_usb.h" #include "sane/sanei_pio.h" #include "sane/sanei_tcp.h" #include "sane/sanei_udp.h" #include "sane/sanei_backend.h" #include "sane/sanei_config.h" #include "epson2-io.h" #include "epson2-commands.h" #include "epson2-ops.h" #include "epson2_scsi.h" #include "epson_usb.h" #include "epson2_net.h" /* * Definition of the mode_param struct, that is used to * specify the valid parameters for the different scan modes. * * The depth variable gets updated when the bit depth is modified. */ struct mode_param mode_params[] = { {0, 0x00, 0x30, 1}, {0, 0x00, 0x30, 8}, {1, 0x02, 0x00, 8}, {0, 0x00, 0x30, 1} }; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, #ifdef SANE_FRAME_IR SANE_I18N("Infrared"), #endif NULL }; static const SANE_String_Const adf_mode_list[] = { SANE_I18N("Simplex"), SANE_I18N("Duplex"), NULL }; /* Define the different scan sources */ #define FBF_STR SANE_I18N("Flatbed") #define TPU_STR SANE_I18N("Transparency Unit") #define TPU_STR2 SANE_I18N("TPU8x10") #define ADF_STR SANE_I18N("Automatic Document Feeder") /* * source list need one dummy entry (save device settings is crashing). * NOTE: no const - this list gets created while exploring the capabilities * of the scanner. */ SANE_String_Const source_list[] = { FBF_STR, NULL, NULL, NULL }; static const SANE_String_Const film_list[] = { SANE_I18N("Positive Film"), SANE_I18N("Negative Film"), SANE_I18N("Positive Slide"), SANE_I18N("Negative Slide"), NULL }; static const SANE_String_Const focus_list[] = { SANE_I18N("Focus on glass"), SANE_I18N("Focus 2.5mm above glass"), NULL }; #define HALFTONE_NONE 0x01 #define HALFTONE_TET 0x03 const int halftone_params[] = { HALFTONE_NONE, 0x00, 0x10, 0x20, 0x80, 0x90, 0xa0, 0xb0, HALFTONE_TET, 0xc0, 0xd0 }; static const SANE_String_Const halftone_list[] = { SANE_I18N("None"), SANE_I18N("Halftone A (Hard Tone)"), SANE_I18N("Halftone B (Soft Tone)"), SANE_I18N("Halftone C (Net Screen)"), NULL }; static const SANE_String_Const halftone_list_4[] = { SANE_I18N("None"), SANE_I18N("Halftone A (Hard Tone)"), SANE_I18N("Halftone B (Soft Tone)"), SANE_I18N("Halftone C (Net Screen)"), SANE_I18N("Dither A (4x4 Bayer)"), SANE_I18N("Dither B (4x4 Spiral)"), SANE_I18N("Dither C (4x4 Net Screen)"), SANE_I18N("Dither D (8x4 Net Screen)"), NULL }; static const SANE_String_Const halftone_list_7[] = { SANE_I18N("None"), SANE_I18N("Halftone A (Hard Tone)"), SANE_I18N("Halftone B (Soft Tone)"), SANE_I18N("Halftone C (Net Screen)"), SANE_I18N("Dither A (4x4 Bayer)"), SANE_I18N("Dither B (4x4 Spiral)"), SANE_I18N("Dither C (4x4 Net Screen)"), SANE_I18N("Dither D (8x4 Net Screen)"), SANE_I18N("Text Enhanced Technology"), SANE_I18N("Download pattern A"), SANE_I18N("Download pattern B"), NULL }; static const SANE_String_Const dropout_list[] = { SANE_I18N("None"), SANE_I18N("Red"), SANE_I18N("Green"), SANE_I18N("Blue"), NULL }; static const SANE_Bool correction_userdefined[] = { SANE_FALSE, SANE_TRUE, SANE_TRUE, }; static const SANE_String_Const correction_list[] = { SANE_I18N("None"), SANE_I18N("Built in CCT profile"), SANE_I18N("User defined CCT profile"), NULL }; enum { CORR_NONE, CORR_AUTO, CORR_USER }; static const SANE_String_Const cct_mode_list[] = { "Automatic", "Reflective", "Colour negatives", "Monochrome negatives", "Colour positives", NULL }; enum { CCT_AUTO, CCT_REFLECTIVE, CCT_COLORNEG, CCT_MONONEG, CCT_COLORPOS }; /* * Gamma correction: * The A and B level scanners work differently than the D level scanners, * therefore I define two different sets of arrays, plus one set of * variables that get set to the actally used params and list arrays at runtime. */ static int gamma_params_ab[] = { 0x01, 0x03, 0x00, 0x10, 0x20 }; static const SANE_String_Const gamma_list_ab[] = { SANE_I18N("Default"), SANE_I18N("User defined"), SANE_I18N("High density printing"), SANE_I18N("Low density printing"), SANE_I18N("High contrast printing"), NULL }; static SANE_Bool gamma_userdefined_ab[] = { SANE_FALSE, SANE_TRUE, SANE_FALSE, SANE_FALSE, SANE_FALSE, }; static int gamma_params_d[] = { 0x03, 0x04 }; static const SANE_String_Const gamma_list_d[] = { SANE_I18N("User defined (Gamma=1.0)"), SANE_I18N("User defined (Gamma=1.8)"), NULL }; static SANE_Bool gamma_userdefined_d[] = { SANE_TRUE, SANE_TRUE }; static SANE_Bool *gamma_userdefined; int *gamma_params; /* Bay list: * this is used for the FilmScan * XXX Add APS loader support */ static const SANE_String_Const bay_list[] = { "1", "2", "3", "4", "5", "6", NULL }; /* minimum, maximum, quantization */ static const SANE_Range u8_range = { 0, 255, 0 }; static const SANE_Range s8_range = { -127, 127, 0 }; static const SANE_Range fx_range = { SANE_FIX(-2.0), SANE_FIX(2.0), 0 }; static const SANE_Range outline_emphasis_range = { -2, 2, 0 }; /* * List of pointers to devices - will be dynamically allocated depending * on the number of devices found. */ static const SANE_Device **devlist; /* Some utility functions */ static size_t max_string_size(const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; i++) { size = strlen(strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status attach_one_usb(SANE_String_Const devname); static SANE_Status attach_one_net(SANE_String_Const devname); static void print_params(const SANE_Parameters params) { DBG(6, "params.format = %d\n", params.format); DBG(6, "params.last_frame = %d\n", params.last_frame); DBG(6, "params.bytes_per_line = %d\n", params.bytes_per_line); DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line); DBG(6, "params.lines = %d\n", params.lines); DBG(6, "params.depth = %d\n", params.depth); } /* * close_scanner() * * Close the open scanner. Depending on the connection method, a different * close function is called. */ static void close_scanner(Epson_Scanner *s) { int i; DBG(7, "%s: fd = %d\n", __func__, s->fd); if (s->fd == -1) goto free; /* send a request_status. This toggles w_cmd_count and r_cmd_count */ if (r_cmd_count % 2) esci_request_status(s, NULL); /* request extended status. This toggles w_cmd_count only */ if (w_cmd_count % 2) esci_request_extended_status(s, NULL, NULL); if (s->hw->connection == SANE_EPSON_NET) { sanei_epson_net_unlock(s); sanei_tcp_close(s->fd); } else if (s->hw->connection == SANE_EPSON_SCSI) { sanei_scsi_close(s->fd); } else if (s->hw->connection == SANE_EPSON_PIO) { sanei_pio_close(s->fd); } else if (s->hw->connection == SANE_EPSON_USB) { sanei_usb_close(s->fd); } s->fd = -1; free: for (i = 0; i < LINES_SHUFFLE_MAX; i++) { if (s->line_buffer[i] != NULL) free(s->line_buffer[i]); } free(s); } static void e2_network_discovery(void) { fd_set rfds; int fd, len; SANE_Status status; char *ip, *query = "EPSONP\x00\xff\x00\x00\x00\x00\x00\x00\x00"; unsigned char buf[76]; struct timeval to; status = sanei_udp_open_broadcast(&fd); if (status != SANE_STATUS_GOOD) return; sanei_udp_write_broadcast(fd, 3289, (unsigned char *) query, 15); DBG(5, "%s, sent discovery packet\n", __func__); to.tv_sec = 1; to.tv_usec = 0; FD_ZERO(&rfds); FD_SET(fd, &rfds); sanei_udp_set_nonblock(fd, SANE_TRUE); while (select(fd + 1, &rfds, NULL, NULL, &to) > 0) { if ((len = sanei_udp_recvfrom(fd, buf, 76, &ip)) == 76) { DBG(5, " response from %s\n", ip); /* minimal check, protocol unknown */ if (strncmp((char *) buf, "EPSON", 5) == 0) attach_one_net(ip); } } DBG(5, "%s, end\n", __func__); sanei_udp_close(fd); } /* * open_scanner() * * Open the scanner device. Depending on the connection method, * different open functions are called. */ static SANE_Status open_scanner(Epson_Scanner *s) { SANE_Status status = 0; DBG(7, "%s: %s\n", __func__, s->hw->sane.name); if (s->fd != -1) { DBG(5, "scanner is already open: fd = %d\n", s->fd); return SANE_STATUS_GOOD; /* no need to open the scanner */ } if (s->hw->connection == SANE_EPSON_NET) { unsigned char buf[5]; /* device name has the form net:ipaddr */ status = sanei_tcp_open(&s->hw->sane.name[4], 1865, &s->fd); if (status == SANE_STATUS_GOOD) { ssize_t read; struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); s->netlen = 0; DBG(32, "awaiting welcome message\n"); /* the scanner sends a kind of welcome msg */ read = e2_recv(s, buf, 5, &status); if (read != 5) { sanei_tcp_close(s->fd); s->fd = -1; return SANE_STATUS_IO_ERROR; } DBG(32, "welcome message received, locking the scanner...\n"); /* lock the scanner for use by sane */ status = sanei_epson_net_lock(s); if (status != SANE_STATUS_GOOD) { DBG(1, "%s cannot lock scanner: %s\n", s->hw->sane.name, sane_strstatus(status)); sanei_tcp_close(s->fd); s->fd = -1; return status; } DBG(32, "scanner locked\n"); } } else if (s->hw->connection == SANE_EPSON_SCSI) status = sanei_scsi_open(s->hw->sane.name, &s->fd, sanei_epson2_scsi_sense_handler, NULL); else if (s->hw->connection == SANE_EPSON_PIO) /* device name has the form pio:0xnnn */ status = sanei_pio_open(&s->hw->sane.name[4], &s->fd); else if (s->hw->connection == SANE_EPSON_USB) status = sanei_usb_open(s->hw->sane.name, &s->fd); if (status == SANE_STATUS_ACCESS_DENIED) { DBG(1, "please check that you have permissions on the device.\n"); DBG(1, "if this is a multi-function device with a printer,\n"); DBG(1, "disable any conflicting driver (like usblp).\n"); } if (status != SANE_STATUS_GOOD) DBG(1, "%s open failed: %s\n", s->hw->sane.name, sane_strstatus(status)); else DBG(5, "scanner opened\n"); return status; } static SANE_Status detect_scsi(struct Epson_Scanner *s) { SANE_Status status; struct Epson_Device *dev = s->hw; char buf[INQUIRY_BUF_SIZE + 1]; size_t buf_size = INQUIRY_BUF_SIZE; char *vendor = buf + 8; char *model = buf + 16; char *rev = buf + 32; status = sanei_epson2_scsi_inquiry(s->fd, buf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: inquiry failed: %s\n", __func__, sane_strstatus(status)); return status; } buf[INQUIRY_BUF_SIZE] = 0; DBG(1, "inquiry data:\n"); DBG(1, " vendor : %.8s\n", vendor); DBG(1, " model : %.16s\n", model); DBG(1, " revision: %.4s\n", rev); if (buf[0] != TYPE_PROCESSOR) { DBG(1, "%s: device is not of processor type (%d)\n", __func__, buf[0]); return SANE_STATUS_INVAL; } if (strncmp(vendor, "EPSON", 5) != 0) { DBG(1, "%s: device doesn't look like an EPSON scanner\n", __func__); return SANE_STATUS_INVAL; } if (strncmp(model, "SCANNER ", 8) != 0 && strncmp(model, "FilmScan 200", 12) != 0 && strncmp(model, "Perfection", 10) != 0 && strncmp(model, "Expression", 10) != 0 && strncmp(model, "GT", 2) != 0) { DBG(1, "%s: this EPSON scanner is not supported\n", __func__); return SANE_STATUS_INVAL; } if (strncmp(model, "FilmScan 200", 12) == 0) { dev->sane.type = "film scanner"; e2_set_model(s, (unsigned char *) model, 12); } /* Issue a test unit ready SCSI command. The FilmScan 200 * requires it for a sort of "wake up". We might eventually * get the return code and reissue it in case of failure. */ sanei_epson2_scsi_test_unit_ready(s->fd); return SANE_STATUS_GOOD; } static SANE_Status detect_usb(struct Epson_Scanner *s, SANE_Bool assume_valid) { SANE_Status status; int vendor, product; int i, numIds; SANE_Bool is_valid = assume_valid; /* if the sanei_usb_get_vendor_product call is not supported, * then we just ignore this and rely on the user to config * the correct device. */ status = sanei_usb_get_vendor_product(s->fd, &vendor, &product); if (status != SANE_STATUS_GOOD) { DBG(1, "the device cannot be verified - will continue\n"); return SANE_STATUS_GOOD; } /* check the vendor ID to see if we are dealing with an EPSON device */ if (vendor != SANE_EPSON_VENDOR_ID) { /* this is not a supported vendor ID */ DBG(1, "not an Epson device at %s (vendor id=0x%x)\n", s->hw->sane.name, vendor); return SANE_STATUS_INVAL; } numIds = sanei_epson_getNumberOfUSBProductIds(); i = 0; /* check all known product IDs to verify that we know about the device */ while (i != numIds) { if (product == sanei_epson_usb_product_ids[i]) { is_valid = SANE_TRUE; break; } i++; } if (is_valid == SANE_FALSE) { DBG(1, "the device at %s is not supported (product id=0x%x)\n", s->hw->sane.name, product); return SANE_STATUS_INVAL; } DBG(1, "found valid Epson scanner: 0x%x/0x%x (vendorID/productID)\n", vendor, product); return SANE_STATUS_GOOD; } static int num_devices; /* number of scanners attached to backend */ static Epson_Device *first_dev; /* first EPSON scanner in list */ static struct Epson_Scanner * scanner_create(struct Epson_Device *dev, SANE_Status *status) { struct Epson_Scanner *s; s = malloc(sizeof(struct Epson_Scanner)); if (s == NULL) { *status = SANE_STATUS_NO_MEM; return NULL; } memset(s, 0x00, sizeof(struct Epson_Scanner)); s->fd = -1; s->hw = dev; return s; } static struct Epson_Scanner * device_detect(const char *name, int type, SANE_Bool assume_valid, SANE_Status *status) { struct Epson_Scanner *s; struct Epson_Device *dev; /* try to find the device in our list */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, name) == 0) { /* the device might have been just probed, * sleep a bit. */ if (dev->connection == SANE_EPSON_NET) sleep(1); return scanner_create(dev, status); } } if (type == SANE_EPSON_NODEV) { *status = SANE_STATUS_INVAL; return NULL; } /* alloc and clear our device structure */ dev = malloc(sizeof(*dev)); if (!dev) { *status = SANE_STATUS_NO_MEM; return NULL; } memset(dev, 0x00, sizeof(struct Epson_Device)); s = scanner_create(dev, status); if (s == NULL) return NULL; e2_dev_init(dev, name, type); *status = open_scanner(s); if (*status != SANE_STATUS_GOOD) { free(s); return NULL; } /* from now on, close_scanner() must be called */ /* SCSI and USB requires special care */ if (dev->connection == SANE_EPSON_SCSI) { *status = detect_scsi(s); } else if (dev->connection == SANE_EPSON_USB) { *status = detect_usb(s, assume_valid); } if (*status != SANE_STATUS_GOOD) goto close; /* set name and model (if not already set) */ if (dev->model == NULL) e2_set_model(s, (unsigned char *) "generic", 7); dev->name = strdup(name); dev->sane.name = dev->name; /* ESC @, reset */ *status = esci_reset(s); if (*status != SANE_STATUS_GOOD) goto close; *status = e2_discover_capabilities(s); if (*status != SANE_STATUS_GOOD) goto close; if (source_list[0] == NULL || dev->dpi_range.min == 0) { DBG(1, "something is wrong in the discovery process, aborting.\n"); *status = SANE_STATUS_IO_ERROR; goto close; } e2_dev_post_init(dev); *status = esci_reset(s); if (*status != SANE_STATUS_GOOD) goto close; DBG(1, "scanner model: %s\n", dev->model); /* add this scanner to the device list */ num_devices++; dev->next = first_dev; first_dev = dev; return s; close: close_scanner(s); return NULL; } static SANE_Status attach(const char *name, int type) { SANE_Status status; Epson_Scanner *s; DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type); s = device_detect(name, type, 0, &status); if(s == NULL) return status; close_scanner(s); return status; } static SANE_Status attach_one_scsi(const char *dev) { DBG(7, "%s: dev = %s\n", __func__, dev); return attach(dev, SANE_EPSON_SCSI); } SANE_Status attach_one_usb(const char *dev) { DBG(7, "%s: dev = %s\n", __func__, dev); return attach(dev, SANE_EPSON_USB); } static SANE_Status attach_one_net(const char *dev) { char name[39+4]; DBG(7, "%s: dev = %s\n", __func__, dev); strcpy(name, "net:"); strcat(name, dev); return attach(name, SANE_EPSON_NET); } static SANE_Status attach_one_pio(const char *dev) { DBG(7, "%s: dev = %s\n", __func__, dev); return attach(dev, SANE_EPSON_PIO); } static SANE_Status attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) { int vendor, product; int len = strlen(line); DBG(7, "%s: len = %d, line = %s\n", __func__, len, line); if (sscanf(line, "usb %i %i", &vendor, &product) == 2) { /* add the vendor and product IDs to the list of known devices before we call the attach function */ int numIds = sanei_epson_getNumberOfUSBProductIds(); if (vendor != 0x4b8) return SANE_STATUS_INVAL; /* this is not an EPSON device */ sanei_epson_usb_product_ids[numIds - 1] = product; sanei_usb_attach_matching_devices(line, attach_one_usb); } else if (strncmp(line, "usb", 3) == 0 && len == 3) { int i, numIds; numIds = sanei_epson_getNumberOfUSBProductIds(); for (i = 0; i < numIds; i++) { sanei_usb_find_devices(0x4b8, sanei_epson_usb_product_ids[i], attach_one_usb); } } else if (strncmp(line, "net", 3) == 0) { /* remove the "net" sub string */ const char *name = sanei_config_skip_whitespace(line + 3); if (strncmp(name, "autodiscovery", 13) == 0) e2_network_discovery(); else attach_one_net(name); } else if (strncmp(line, "pio", 3) == 0) { /* remove the "pio" sub string */ const char *name = sanei_config_skip_whitespace(line + 3); attach_one_pio(name); } else { sanei_config_attach_matching_devices(line, attach_one_scsi); } return SANE_STATUS_GOOD; } static void free_devices(void) { Epson_Device *dev, *next; DBG(5, "%s\n", __func__); for (dev = first_dev; dev; dev = next) { next = dev->next; free(dev->name); free(dev->model); free(dev); } free(devlist); first_dev = NULL; } static void probe_devices(void) { DBG(5, "%s\n", __func__); free_devices(); sanei_configure_attach(EPSON2_CONFIG_FILE, NULL, attach_one_config); } SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) { DBG_INIT(); DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__); DBG(1, "epson2 backend, version %i.%i.%i\n", EPSON2_VERSION, EPSON2_REVISION, EPSON2_BUILD); if (version_code != NULL) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, EPSON2_BUILD); sanei_usb_init(); return SANE_STATUS_GOOD; } /* Clean up the list of attached scanners. */ void sane_exit(void) { DBG(5, "%s\n", __func__); free_devices(); } SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool __sane_unused__ local_only) { Epson_Device *dev; int i; DBG(5, "%s\n", __func__); probe_devices(); devlist = malloc((num_devices + 1) * sizeof(devlist[0])); if (!devlist) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } DBG(5, "%s - results:\n", __func__); for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) { DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model); devlist[i] = &dev->sane; } devlist[i] = NULL; *device_list = devlist; return SANE_STATUS_GOOD; } static SANE_Status init_options(Epson_Scanner *s) { int i; for (i = 0; i < NUM_OPTIONS; i++) { s->opt[i].size = sizeof(SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size(mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = 0; /* Lineart */ /* disable infrared on unsupported scanners */ if (!e2_model(s, "GT-X800") && !e2_model(s, "GT-X700") && !e2_model(s, "GT-X900") && !e2_model(s, "GT-X980")) mode_list[MODE_INFRARED] = NULL; /* bit depth */ s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_BIT_DEPTH].unit = SANE_UNIT_BIT; s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_BIT_DEPTH].constraint.word_list = s->hw->depth_list; s->val[OPT_BIT_DEPTH].w = 8; /* default to 8 bit */ /* default is Lineart, disable depth selection */ s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; /* halftone */ s->opt[OPT_HALFTONE].name = SANE_NAME_HALFTONE; s->opt[OPT_HALFTONE].title = SANE_TITLE_HALFTONE; s->opt[OPT_HALFTONE].desc = SANE_I18N("Selects the halftone."); s->opt[OPT_HALFTONE].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE].size = max_string_size(halftone_list_7); s->opt[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_STRING_LIST; /* XXX use defines */ if (s->hw->level >= 7) s->opt[OPT_HALFTONE].constraint.string_list = halftone_list_7; else if (s->hw->level >= 4) s->opt[OPT_HALFTONE].constraint.string_list = halftone_list_4; else s->opt[OPT_HALFTONE].constraint.string_list = halftone_list; s->val[OPT_HALFTONE].w = 1; /* Halftone A */ if (!s->hw->cmd->set_halftoning) s->opt[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE; /* dropout */ s->opt[OPT_DROPOUT].name = "dropout"; s->opt[OPT_DROPOUT].title = SANE_I18N("Dropout"); s->opt[OPT_DROPOUT].desc = SANE_I18N("Selects the dropout."); s->opt[OPT_DROPOUT].type = SANE_TYPE_STRING; s->opt[OPT_DROPOUT].size = max_string_size(dropout_list); s->opt[OPT_DROPOUT].cap |= SANE_CAP_ADVANCED; s->opt[OPT_DROPOUT].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_DROPOUT].constraint.string_list = dropout_list; s->val[OPT_DROPOUT].w = 0; /* None */ /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_I18N("Selects the brightness."); s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &s->hw->cmd->bright_range; s->val[OPT_BRIGHTNESS].w = 0; /* Normal */ if (!s->hw->cmd->set_bright) s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; /* sharpness */ s->opt[OPT_SHARPNESS].name = "sharpness"; s->opt[OPT_SHARPNESS].title = SANE_I18N("Sharpness"); s->opt[OPT_SHARPNESS].desc = ""; s->opt[OPT_SHARPNESS].type = SANE_TYPE_INT; s->opt[OPT_SHARPNESS].unit = SANE_UNIT_NONE; s->opt[OPT_SHARPNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_SHARPNESS].constraint.range = &outline_emphasis_range; s->val[OPT_SHARPNESS].w = 0; /* Normal */ if (!s->hw->cmd->set_outline_emphasis) s->opt[OPT_SHARPNESS].cap |= SANE_CAP_INACTIVE; /* gamma */ s->opt[OPT_GAMMA_CORRECTION].name = SANE_NAME_GAMMA_CORRECTION; s->opt[OPT_GAMMA_CORRECTION].title = SANE_TITLE_GAMMA_CORRECTION; s->opt[OPT_GAMMA_CORRECTION].desc = SANE_DESC_GAMMA_CORRECTION; s->opt[OPT_GAMMA_CORRECTION].type = SANE_TYPE_STRING; s->opt[OPT_GAMMA_CORRECTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; /* * special handling for D1 function level - at this time I'm not * testing for D1, I'm just assuming that all D level scanners will * behave the same way. This has to be confirmed with the next D-level * scanner */ if (s->hw->cmd->level[0] == 'D') { s->opt[OPT_GAMMA_CORRECTION].size = max_string_size(gamma_list_d); s->opt[OPT_GAMMA_CORRECTION].constraint.string_list = gamma_list_d; s->val[OPT_GAMMA_CORRECTION].w = 1; /* Default */ gamma_userdefined = gamma_userdefined_d; gamma_params = gamma_params_d; } else { s->opt[OPT_GAMMA_CORRECTION].size = max_string_size(gamma_list_ab); s->opt[OPT_GAMMA_CORRECTION].constraint.string_list = gamma_list_ab; s->val[OPT_GAMMA_CORRECTION].w = 0; /* Default */ gamma_userdefined = gamma_userdefined_ab; gamma_params = gamma_params_ab; } if (!s->hw->cmd->set_gamma) s->opt[OPT_GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof(SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[0][0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof(SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[1][0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof(SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[2][0]; if (s->hw->cmd->set_gamma_table && gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w] == SANE_TRUE) { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } /* initialize the Gamma tables */ memset(&s->gamma_table[0], 0, 256 * sizeof(SANE_Word)); memset(&s->gamma_table[1], 0, 256 * sizeof(SANE_Word)); memset(&s->gamma_table[2], 0, 256 * sizeof(SANE_Word)); /* memset(&s->gamma_table[3], 0, 256 * sizeof(SANE_Word)); */ for (i = 0; i < 256; i++) { s->gamma_table[0][i] = i; s->gamma_table[1][i] = i; s->gamma_table[2][i] = i; /* s->gamma_table[3][i] = i; */ } /* color correction */ s->opt[OPT_COLOR_CORRECTION].name = "color-correction"; s->opt[OPT_COLOR_CORRECTION].title = SANE_I18N("Color correction"); s->opt[OPT_COLOR_CORRECTION].desc = SANE_I18N("Sets the color correction table for the selected output device."); s->opt[OPT_COLOR_CORRECTION].type = SANE_TYPE_STRING; s->opt[OPT_COLOR_CORRECTION].size = max_string_size(correction_list); s->opt[OPT_COLOR_CORRECTION].cap |= SANE_CAP_ADVANCED; s->opt[OPT_COLOR_CORRECTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_COLOR_CORRECTION].constraint.string_list = correction_list; s->val[OPT_COLOR_CORRECTION].w = CORR_AUTO; if (!s->hw->cmd->set_color_correction) s->opt[OPT_COLOR_CORRECTION].cap |= SANE_CAP_INACTIVE; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->resolution_list; s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &u8_range; s->val[OPT_THRESHOLD].w = 0x80; if (!s->hw->cmd->set_threshold) s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* "Advanced" group: */ s->opt[OPT_ADVANCED_GROUP].title = SANE_I18N("Advanced"); s->opt[OPT_ADVANCED_GROUP].desc = ""; s->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; /* "Color correction" group: */ s->opt[OPT_CCT_GROUP].title = SANE_I18N("Color correction"); s->opt[OPT_CCT_GROUP].desc = ""; s->opt[OPT_CCT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_CCT_GROUP].cap = SANE_CAP_ADVANCED; /* XXX disabled for now */ s->opt[OPT_CCT_MODE].name = "cct-type"; s->opt[OPT_CCT_MODE].title = "CCT Profile Type"; s->opt[OPT_CCT_MODE].desc = "Color correction profile type"; s->opt[OPT_CCT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_CCT_MODE].cap |= SANE_CAP_ADVANCED | SANE_CAP_INACTIVE; s->opt[OPT_CCT_MODE].size = max_string_size(cct_mode_list); s->opt[OPT_CCT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_CCT_MODE].constraint.string_list = cct_mode_list; s->val[OPT_CCT_MODE].w = CCT_AUTO; s->opt[OPT_CCT_PROFILE].name = "cct-profile"; s->opt[OPT_CCT_PROFILE].title = "CCT Profile"; s->opt[OPT_CCT_PROFILE].desc = "Color correction profile data"; s->opt[OPT_CCT_PROFILE].type = SANE_TYPE_FIXED; s->opt[OPT_CCT_PROFILE].cap |= SANE_CAP_ADVANCED; s->opt[OPT_CCT_PROFILE].unit = SANE_UNIT_NONE; s->opt[OPT_CCT_PROFILE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CCT_PROFILE].constraint.range = &fx_range; s->opt[OPT_CCT_PROFILE].size = 9 * sizeof(SANE_Word); s->val[OPT_CCT_PROFILE].wa = s->cct_table; /* if (!s->hw->cmd->set_color_correction) s->opt[OPT_FILM_TYPE].cap |= SANE_CAP_INACTIVE; */ /* mirror */ s->opt[OPT_MIRROR].name = "mirror"; s->opt[OPT_MIRROR].title = SANE_I18N("Mirror image"); s->opt[OPT_MIRROR].desc = SANE_I18N("Mirror the image."); s->opt[OPT_MIRROR].type = SANE_TYPE_BOOL; s->val[OPT_MIRROR].w = SANE_FALSE; if (!s->hw->cmd->mirror_image) s->opt[OPT_MIRROR].cap |= SANE_CAP_INACTIVE; /* auto area segmentation */ s->opt[OPT_AAS].name = "auto-area-segmentation"; s->opt[OPT_AAS].title = SANE_I18N("Auto area segmentation"); s->opt[OPT_AAS].desc = "Enables different dithering modes in image and text areas"; s->opt[OPT_AAS].type = SANE_TYPE_BOOL; s->val[OPT_AAS].w = SANE_TRUE; if (!s->hw->cmd->control_auto_area_segmentation) s->opt[OPT_AAS].cap |= SANE_CAP_INACTIVE; /* "Preview settings" group: */ s->opt[OPT_PREVIEW_GROUP].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW_GROUP].desc = ""; s->opt[OPT_PREVIEW_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_PREVIEW_GROUP].cap = SANE_CAP_ADVANCED; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_PREVIEW].w = SANE_FALSE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range->max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range->max; /* "Optional equipment" group: */ s->opt[OPT_EQU_GROUP].title = SANE_I18N("Optional equipment"); s->opt[OPT_EQU_GROUP].desc = ""; s->opt[OPT_EQU_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_EQU_GROUP].cap = SANE_CAP_ADVANCED; /* source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].size = max_string_size(source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = source_list; if (!s->hw->extension) s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; s->val[OPT_SOURCE].w = 0; /* always use Flatbed as default */ /* film type */ s->opt[OPT_FILM_TYPE].name = "film-type"; s->opt[OPT_FILM_TYPE].title = SANE_I18N("Film type"); s->opt[OPT_FILM_TYPE].desc = ""; s->opt[OPT_FILM_TYPE].type = SANE_TYPE_STRING; s->opt[OPT_FILM_TYPE].size = max_string_size(film_list); s->opt[OPT_FILM_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_FILM_TYPE].constraint.string_list = film_list; s->val[OPT_FILM_TYPE].w = 0; if (!s->hw->cmd->set_bay) s->opt[OPT_FILM_TYPE].cap |= SANE_CAP_INACTIVE; /* focus position */ s->opt[OPT_FOCUS].name = SANE_EPSON_FOCUS_NAME; s->opt[OPT_FOCUS].title = SANE_EPSON_FOCUS_TITLE; s->opt[OPT_FOCUS].desc = SANE_EPSON_FOCUS_DESC; s->opt[OPT_FOCUS].type = SANE_TYPE_STRING; s->opt[OPT_FOCUS].size = max_string_size(focus_list); s->opt[OPT_FOCUS].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_FOCUS].constraint.string_list = focus_list; s->val[OPT_FOCUS].w = 0; s->opt[OPT_FOCUS].cap |= SANE_CAP_ADVANCED; if (s->hw->focusSupport == SANE_TRUE) s->opt[OPT_FOCUS].cap &= ~SANE_CAP_INACTIVE; else s->opt[OPT_FOCUS].cap |= SANE_CAP_INACTIVE; /* forward feed / eject */ s->opt[OPT_EJECT].name = "eject"; s->opt[OPT_EJECT].title = SANE_I18N("Eject"); s->opt[OPT_EJECT].desc = SANE_I18N("Eject the sheet in the ADF"); s->opt[OPT_EJECT].type = SANE_TYPE_BUTTON; if ((!s->hw->ADF) && (!s->hw->cmd->set_bay)) { /* Hack: Using set_bay to indicate. */ s->opt[OPT_EJECT].cap |= SANE_CAP_INACTIVE; } /* auto forward feed / eject */ s->opt[OPT_AUTO_EJECT].name = "auto-eject"; s->opt[OPT_AUTO_EJECT].title = SANE_I18N("Auto eject"); s->opt[OPT_AUTO_EJECT].desc = SANE_I18N("Eject document after scanning"); s->opt[OPT_AUTO_EJECT].type = SANE_TYPE_BOOL; s->val[OPT_AUTO_EJECT].w = SANE_FALSE; if (!s->hw->ADF) s->opt[OPT_AUTO_EJECT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ADF_MODE].name = "adf-mode"; s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode"); s->opt[OPT_ADF_MODE].desc = SANE_I18N("Selects the ADF mode (simplex/duplex)"); s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING; s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list); s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list; s->val[OPT_ADF_MODE].w = 0; /* simplex */ if ((!s->hw->ADF) || (s->hw->duplex == SANE_FALSE)) s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE; /* select bay */ s->opt[OPT_BAY].name = "bay"; s->opt[OPT_BAY].title = SANE_I18N("Bay"); s->opt[OPT_BAY].desc = SANE_I18N("Select bay to scan"); s->opt[OPT_BAY].type = SANE_TYPE_STRING; s->opt[OPT_BAY].size = max_string_size(bay_list); s->opt[OPT_BAY].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_BAY].constraint.string_list = bay_list; s->val[OPT_BAY].w = 0; /* Bay 1 */ if (!s->hw->cmd->set_bay) s->opt[OPT_BAY].cap |= SANE_CAP_INACTIVE; s->opt[OPT_WAIT_FOR_BUTTON].name = SANE_EPSON_WAIT_FOR_BUTTON_NAME; s->opt[OPT_WAIT_FOR_BUTTON].title = SANE_EPSON_WAIT_FOR_BUTTON_TITLE; s->opt[OPT_WAIT_FOR_BUTTON].desc = SANE_EPSON_WAIT_FOR_BUTTON_DESC; s->opt[OPT_WAIT_FOR_BUTTON].type = SANE_TYPE_BOOL; s->opt[OPT_WAIT_FOR_BUTTON].unit = SANE_UNIT_NONE; s->opt[OPT_WAIT_FOR_BUTTON].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_WAIT_FOR_BUTTON].constraint.range = NULL; s->opt[OPT_WAIT_FOR_BUTTON].cap |= SANE_CAP_ADVANCED; if (!s->hw->cmd->request_push_button_status) s->opt[OPT_WAIT_FOR_BUTTON].cap |= SANE_CAP_INACTIVE; return SANE_STATUS_GOOD; } SANE_Status sane_open(SANE_String_Const name, SANE_Handle *handle) { SANE_Status status; Epson_Scanner *s = NULL; int l = strlen(name); DBG(7, "%s: name = %s\n", __func__, name); *handle = NULL; /* probe if empty device name provided */ if (l == 0) { probe_devices(); if (first_dev == NULL) { DBG(1, "no device detected\n"); return SANE_STATUS_INVAL; } s = device_detect(first_dev->sane.name, first_dev->connection, 0, &status); if (s == NULL) { DBG(1, "cannot open a perfectly valid device (%s)," " please report to the authors\n", name); return SANE_STATUS_INVAL; } } else { if (strncmp(name, "net:", 4) == 0) { s = device_detect(name, SANE_EPSON_NET, 0, &status); if (s == NULL) return status; } else if (strncmp(name, "libusb:", 7) == 0) { s = device_detect(name, SANE_EPSON_USB, 1, &status); if (s == NULL) return status; } else if (strncmp(name, "pio:", 4) == 0) { s = device_detect(name, SANE_EPSON_PIO, 0, &status); if (s == NULL) return status; } else { /* as a last resort, check for a match * in the device list. This should handle SCSI * devices and platforms without libusb. */ if (first_dev == NULL) probe_devices(); s = device_detect(name, SANE_EPSON_NODEV, 0, &status); if (s == NULL) { DBG(1, "invalid device name: %s\n", name); return SANE_STATUS_INVAL; } } } /* s is always valid here */ DBG(1, "handle obtained\n"); init_options(s); status = open_scanner(s); if (status != SANE_STATUS_GOOD) { free(s); return status; } status = esci_reset(s); if (status != SANE_STATUS_GOOD) { close_scanner(s); return status; } *handle = (SANE_Handle)s; return SANE_STATUS_GOOD; } void sane_close(SANE_Handle handle) { Epson_Scanner *s; DBG(1, "* %s\n", __func__); /* * XXX Test if there is still data pending from * the scanner. If so, then do a cancel */ s = (Epson_Scanner *) handle; close_scanner(s); } const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) { Epson_Scanner *s = (Epson_Scanner *) handle; if (option < 0 || option >= NUM_OPTIONS) return NULL; return s->opt + option; } static const SANE_String_Const * search_string_list(const SANE_String_Const *list, SANE_String value) { while (*list != NULL && strcmp(value, *list) != 0) list++; return ((*list == NULL) ? NULL : list); } /* Activate, deactivate an option. Subroutines so we can add debugging info if we want. The change flag is set to TRUE if we changed an option. If we did not change an option, then the value of the changed flag is not modified. */ static void activateOption(Epson_Scanner *s, SANE_Int option, SANE_Bool *change) { if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { s->opt[option].cap &= ~SANE_CAP_INACTIVE; *change = SANE_TRUE; } } static void deactivateOption(Epson_Scanner *s, SANE_Int option, SANE_Bool *change) { if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { s->opt[option].cap |= SANE_CAP_INACTIVE; *change = SANE_TRUE; } } static void setOptionState(Epson_Scanner *s, SANE_Bool state, SANE_Int option, SANE_Bool *change) { if (state) activateOption(s, option, change); else deactivateOption(s, option, change); } static SANE_Status getvalue(SANE_Handle handle, SANE_Int option, void *value) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); DBG(17, "%s: option = %d\n", __func__, option); switch (option) { case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_CCT_PROFILE: memcpy(value, sval->wa, sopt->size); break; case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_MIRROR: case OPT_AAS: case OPT_PREVIEW: case OPT_BRIGHTNESS: case OPT_SHARPNESS: case OPT_AUTO_EJECT: case OPT_THRESHOLD: case OPT_BIT_DEPTH: case OPT_WAIT_FOR_BUTTON: *((SANE_Word *) value) = sval->w; break; case OPT_MODE: case OPT_CCT_MODE: case OPT_ADF_MODE: case OPT_HALFTONE: case OPT_DROPOUT: case OPT_SOURCE: case OPT_FILM_TYPE: case OPT_GAMMA_CORRECTION: case OPT_COLOR_CORRECTION: case OPT_BAY: case OPT_FOCUS: strcpy((char *) value, sopt->constraint.string_list[sval->w]); break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /* * This routine handles common options between OPT_MODE and * OPT_HALFTONE. These options are TET (a HALFTONE mode), AAS * - auto area segmentation, and threshold. Apparently AAS * is some method to differentiate between text and photos. * Or something like that. * * AAS is available when the scan color depth is 1 and the * halftone method is not TET. * * Threshold is available when halftone is NONE, and depth is 1. */ static void handle_depth_halftone(Epson_Scanner *s, SANE_Bool *reload) { int hti = s->val[OPT_HALFTONE].w; int mdi = s->val[OPT_MODE].w; SANE_Bool aas = SANE_FALSE; SANE_Bool thresh = SANE_FALSE; /* this defaults to false */ setOptionState(s, thresh, OPT_THRESHOLD, reload); if (!s->hw->cmd->control_auto_area_segmentation) return; if (mode_params[mdi].depth == 1) { if (halftone_params[hti] != HALFTONE_TET) aas = SANE_TRUE; if (halftone_params[hti] == HALFTONE_NONE) thresh = SANE_TRUE; } setOptionState(s, aas, OPT_AAS, reload); setOptionState(s, thresh, OPT_THRESHOLD, reload); } /* * Handles setting the source (flatbed, transparency adapter (TPU), * or auto document feeder (ADF)). * * For newer scanners it also sets the focus according to the * glass / TPU settings. */ static void change_source(Epson_Scanner *s, SANE_Int optindex, char *value) { int force_max = SANE_FALSE; SANE_Bool dummy; DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex, value); /* reset the scanner when we are changing the source setting - this is necessary for the Perfection 1650 */ if (s->hw->need_reset_on_source_change) esci_reset(s); s->focusOnGlass = SANE_TRUE; /* this is the default */ if (s->val[OPT_SOURCE].w == optindex) return; s->val[OPT_SOURCE].w = optindex; if (s->val[OPT_TL_X].w == s->hw->x_range->min && s->val[OPT_TL_Y].w == s->hw->y_range->min && s->val[OPT_BR_X].w == s->hw->x_range->max && s->val[OPT_BR_Y].w == s->hw->y_range->max) { force_max = SANE_TRUE; } if (strcmp(ADF_STR, value) == 0) { s->hw->x_range = &s->hw->adf_x_range; s->hw->y_range = &s->hw->adf_y_range; s->hw->use_extension = SANE_TRUE; /* disable film type option */ deactivateOption(s, OPT_FILM_TYPE, &dummy); s->val[OPT_FOCUS].w = 0; if (s->hw->duplex) { activateOption(s, OPT_ADF_MODE, &dummy); } else { deactivateOption(s, OPT_ADF_MODE, &dummy); s->val[OPT_ADF_MODE].w = 0; } DBG(1, "adf activated (ext: %d, duplex: %d)\n", s->hw->use_extension, s->hw->duplex); } else if (strcmp(TPU_STR, value) == 0 || strcmp(TPU_STR2, value) == 0) { if (strcmp(TPU_STR, value) == 0) { s->hw->x_range = &s->hw->tpu_x_range; s->hw->y_range = &s->hw->tpu_y_range; s->hw->TPU2 = SANE_FALSE; } if (strcmp(TPU_STR2, value) == 0) { s->hw->x_range = &s->hw->tpu2_x_range; s->hw->y_range = &s->hw->tpu2_y_range; s->hw->TPU2 = SANE_TRUE; } s->hw->use_extension = SANE_TRUE; /* enable film type option only if the scanner supports it */ if (s->hw->cmd->set_film_type != 0) activateOption(s, OPT_FILM_TYPE, &dummy); else deactivateOption(s, OPT_FILM_TYPE, &dummy); /* enable focus position if the scanner supports it */ if (s->hw->cmd->set_focus_position != 0) { s->val[OPT_FOCUS].w = 1; s->focusOnGlass = SANE_FALSE; } deactivateOption(s, OPT_ADF_MODE, &dummy); deactivateOption(s, OPT_EJECT, &dummy); deactivateOption(s, OPT_AUTO_EJECT, &dummy); } else { /* neither ADF nor TPU active */ s->hw->x_range = &s->hw->fbf_x_range; s->hw->y_range = &s->hw->fbf_y_range; s->hw->use_extension = SANE_FALSE; /* disable film type option */ deactivateOption(s, OPT_FILM_TYPE, &dummy); s->val[OPT_FOCUS].w = 0; deactivateOption(s, OPT_ADF_MODE, &dummy); } /* special handling for FilmScan 200 */ if (s->hw->cmd->level[0] == 'F') activateOption(s, OPT_FILM_TYPE, &dummy); s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max) s->val[OPT_TL_X].w = s->hw->x_range->min; if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max) s->val[OPT_TL_Y].w = s->hw->y_range->min; if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max) s->val[OPT_BR_X].w = s->hw->x_range->max; if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max) s->val[OPT_BR_Y].w = s->hw->y_range->max; setOptionState(s, s->hw->ADF && s->hw->use_extension, OPT_AUTO_EJECT, &dummy); setOptionState(s, s->hw->ADF && s->hw->use_extension, OPT_EJECT, &dummy); } static SANE_Status setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); SANE_Status status; const SANE_String_Const *optval = NULL; int optindex = 0; SANE_Bool reload = SANE_FALSE; DBG(17, "%s: option = %d, value = %p\n", __func__, option, value); status = sanei_constrain_value(sopt, value, info); if (status != SANE_STATUS_GOOD) return status; if (info && value && (*info & SANE_INFO_INEXACT) && sopt->type == SANE_TYPE_INT) DBG(17, "%s: constrained val = %d\n", __func__, *(SANE_Word *) value); if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) { optval = search_string_list(sopt->constraint.string_list, (char *) value); if (optval == NULL) return SANE_STATUS_INVAL; optindex = optval - sopt->constraint.string_list; } switch (option) { case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_CCT_PROFILE: memcpy(sval->wa, value, sopt->size); /* Word arrays */ break; case OPT_CCT_MODE: case OPT_ADF_MODE: case OPT_DROPOUT: case OPT_FILM_TYPE: case OPT_BAY: case OPT_FOCUS: sval->w = optindex; /* Simple lists */ break; case OPT_EJECT: /* XXX required? control_extension(s, 1); */ esci_eject(s); break; case OPT_RESOLUTION: sval->w = *((SANE_Word *) value); DBG(17, "setting resolution to %d\n", sval->w); reload = SANE_TRUE; break; case OPT_BR_X: case OPT_BR_Y: sval->w = *((SANE_Word *) value); if (SANE_UNFIX(sval->w) == 0) { DBG(17, "invalid br-x or br-y\n"); return SANE_STATUS_INVAL; } /* passthru */ case OPT_TL_X: case OPT_TL_Y: sval->w = *((SANE_Word *) value); DBG(17, "setting size to %f\n", SANE_UNFIX(sval->w)); if (NULL != info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_SOURCE: change_source(s, optindex, (char *) value); reload = SANE_TRUE; break; case OPT_MODE: { SANE_Bool isColor = mode_params[optindex].color; sval->w = optindex; DBG(17, "%s: setting mode to %d\n", __func__, optindex); /* halftoning available only on bw scans */ if (s->hw->cmd->set_halftoning != 0) setOptionState(s, mode_params[optindex].depth == 1, OPT_HALFTONE, &reload); /* disable dropout on non-color scans */ setOptionState(s, !isColor, OPT_DROPOUT, &reload); if (s->hw->cmd->set_color_correction) setOptionState(s, isColor, OPT_COLOR_CORRECTION, &reload); /* if binary, then disable the bit depth selection */ if (optindex == 0) { DBG(17, "%s: disabling bit depth selection\n", __func__); s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; } else { if (s->hw->depth_list[0] == 1) { DBG(17, "%s: only one depth is available\n", __func__); s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; } else { DBG(17, "%s: enabling bit depth selection\n", __func__); s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth; } } handle_depth_halftone(s, &reload); reload = SANE_TRUE; break; } case OPT_BIT_DEPTH: sval->w = *((SANE_Word *) value); mode_params[s->val[OPT_MODE].w].depth = sval->w; reload = SANE_TRUE; break; case OPT_HALFTONE: sval->w = optindex; handle_depth_halftone(s, &reload); break; case OPT_COLOR_CORRECTION: { sval->w = optindex; break; } case OPT_GAMMA_CORRECTION: { SANE_Bool f = gamma_userdefined[optindex]; sval->w = optindex; setOptionState(s, f, OPT_GAMMA_VECTOR_R, &reload); setOptionState(s, f, OPT_GAMMA_VECTOR_G, &reload); setOptionState(s, f, OPT_GAMMA_VECTOR_B, &reload); setOptionState(s, !f, OPT_BRIGHTNESS, &reload); /* Note... */ break; } case OPT_MIRROR: case OPT_AAS: case OPT_PREVIEW: /* needed? */ case OPT_BRIGHTNESS: case OPT_SHARPNESS: case OPT_AUTO_EJECT: case OPT_THRESHOLD: case OPT_WAIT_FOR_BUTTON: sval->w = *((SANE_Word *) value); break; default: return SANE_STATUS_INVAL; } if (reload && info != NULL) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; DBG(17, "%s: end\n", __func__); return SANE_STATUS_GOOD; } SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info) { DBG(17, "%s: action = %x, option = %d\n", __func__, action, option); if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_INVAL; if (info != NULL) *info = 0; switch (action) { case SANE_ACTION_GET_VALUE: return getvalue(handle, option, value); case SANE_ACTION_SET_VALUE: return setvalue(handle, option, value, info); default: return SANE_STATUS_INVAL; } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters *params) { Epson_Scanner *s = (Epson_Scanner *) handle; DBG(5, "%s\n", __func__); if (params == NULL) DBG(1, "%s: params is NULL\n", __func__); /* * If sane_start was already called, then just retrieve the parameters * from the scanner data structure */ if (!s->eof && s->ptr != NULL) { DBG(5, "scan in progress, returning saved params structure\n"); } else { /* otherwise initialize the params structure and gather the data */ e2_init_parameters(s); } if (params != NULL) *params = s->params; print_params(s->params); return SANE_STATUS_GOOD; } static void e2_load_cct_profile(struct Epson_Scanner *s, unsigned int index) { s->cct_table[0] = SANE_FIX(s->hw->cct_profile->cct[index][0]); s->cct_table[1] = SANE_FIX(s->hw->cct_profile->cct[index][1]); s->cct_table[2] = SANE_FIX(s->hw->cct_profile->cct[index][2]); s->cct_table[3] = SANE_FIX(s->hw->cct_profile->cct[index][3]); s->cct_table[4] = SANE_FIX(s->hw->cct_profile->cct[index][4]); s->cct_table[5] = SANE_FIX(s->hw->cct_profile->cct[index][5]); s->cct_table[6] = SANE_FIX(s->hw->cct_profile->cct[index][6]); s->cct_table[7] = SANE_FIX(s->hw->cct_profile->cct[index][7]); s->cct_table[8] = SANE_FIX(s->hw->cct_profile->cct[index][8]); } /* * This function is part of the SANE API and gets called from the front end to * start the scan process. */ SANE_Status sane_start(SANE_Handle handle) { Epson_Scanner *s = (Epson_Scanner *) handle; Epson_Device *dev = s->hw; SANE_Status status; DBG(5, "* %s\n", __func__); s->eof = SANE_FALSE; s->canceling = SANE_FALSE; /* check if we just have finished working with the ADF */ status = e2_check_adf(s); if (status != SANE_STATUS_GOOD) return status; /* calc scanning parameters */ status = e2_init_parameters(s); if (status != SANE_STATUS_GOOD) return status; print_params(s->params); /* enable infrared */ if (s->val[OPT_MODE].w == MODE_INFRARED) esci_enable_infrared(handle); /* ESC , bay */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_BAY].cap)) { status = esci_set_bay(s, s->val[OPT_BAY].w); if (status != SANE_STATUS_GOOD) return status; } /* set scanning parameters */ if (dev->extended_commands) status = e2_set_extended_scanning_parameters(s); else status = e2_set_scanning_parameters(s); if (status != SANE_STATUS_GOOD) return status; /* ESC z, user defined gamma table */ if (dev->cmd->set_gamma_table && gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w]) { status = esci_set_gamma_table(s); if (status != SANE_STATUS_GOOD) return status; } if (s->val[OPT_COLOR_CORRECTION].w == CORR_AUTO) { /* Automatic */ DBG(1, "using built in CCT profile\n"); if (dev->model_id == 0) DBG(1, " specific profile not available, using default\n"); if (0) { /* XXX TPU */ /* XXX check this */ if (s->val[OPT_FILM_TYPE].w == 0) e2_load_cct_profile(s, CCTP_COLORPOS); else e2_load_cct_profile(s, CCTP_COLORNEG); } else { e2_load_cct_profile(s, CCTP_REFLECTIVE); } } /* ESC m, user defined color correction */ if (s->hw->cmd->set_color_correction_coefficients && correction_userdefined[s->val[OPT_COLOR_CORRECTION].w]) { status = esci_set_color_correction_coefficients(s, s->cct_table); if (status != SANE_STATUS_GOOD) return status; } /* check if we just have finished working with the ADF. * this seems to work only after the scanner has been * set up with scanning parameters */ status = e2_check_adf(s); if (status != SANE_STATUS_GOOD) return status; /* * If WAIT_FOR_BUTTON is active, then do just that: * Wait until the button is pressed. If the button was already * pressed, then we will get the button pressed event right away. */ if (s->val[OPT_WAIT_FOR_BUTTON].w == SANE_TRUE) e2_wait_button(s); /* for debug, request command parameter */ /* if (DBG_LEVEL) { unsigned char buf[45]; request_command_parameter(s, buf); } */ /* set the retry count to 0 */ s->retry_count = 0; /* allocate buffers for color shuffling */ if (dev->color_shuffle == SANE_TRUE) { int i; /* initialize the line buffers */ for (i = 0; i < s->line_distance * 2 + 1; i++) { if (s->line_buffer[i] != NULL) free(s->line_buffer[i]); s->line_buffer[i] = malloc(s->params.bytes_per_line); if (s->line_buffer[i] == NULL) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } } } /* prepare buffer here so that a memory allocation failure * will leave the scanner in a sane state. * the buffer will have to hold the image data plus * an error code in the extended handshaking mode. */ s->buf = realloc(s->buf, (s->lcount * s->params.bytes_per_line) + 1); if (s->buf == NULL) return SANE_STATUS_NO_MEM; s->ptr = s->end = s->buf; /* feed the first sheet in the ADF */ if (dev->ADF && dev->use_extension && dev->cmd->feed) { status = esci_feed(s); if (status != SANE_STATUS_GOOD) return status; } /* this seems to work only for some devices */ status = e2_wait_warm_up(s); if (status != SANE_STATUS_GOOD) return status; /* start scanning */ DBG(1, "%s: scanning...\n", __func__); if (dev->extended_commands) { status = e2_start_ext_scan(s); /* sometimes the scanner gives an io error when * it's warming up. */ if (status == SANE_STATUS_IO_ERROR) { status = e2_wait_warm_up(s); if (status == SANE_STATUS_GOOD) status = e2_start_ext_scan(s); } } else status = e2_start_std_scan(s); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: start failed: %s\n", __func__, sane_strstatus(status)); return status; } /* this is a kind of read request */ if (dev->connection == SANE_EPSON_NET) { sanei_epson_net_write(s, 0x2000, NULL, 0, s->ext_block_len + 1, &status); } return status; } static inline int get_color(int status) { switch ((status >> 2) & 0x03) { case 1: return 1; case 2: return 0; case 3: return 2; default: return 0; /* required to make the compiler happy */ } } /* this moves data from our buffers to SANE */ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length) { SANE_Status status; Epson_Scanner *s = (Epson_Scanner *) handle; DBG(18, "* %s: eof: %d, canceling: %d\n", __func__, s->eof, s->canceling); /* sane_read called before sane_start? */ if (s->buf == NULL) { DBG(1, "%s: buffer is NULL", __func__); return SANE_STATUS_INVAL; } *length = 0; if (s->hw->extended_commands) status = e2_ext_read(s); else status = e2_block_read(s); /* The scanning operation might be canceled by the scanner itself * or the fronted program */ if (status == SANE_STATUS_CANCELLED || s->canceling) { e2_scan_finish(s); return SANE_STATUS_CANCELLED; } /* XXX if FS G and STATUS_IOERR, use e2_check_extended_status */ DBG(18, "moving data %p %p, %d (%d lines)\n", s->ptr, s->end, max_length, max_length / s->params.bytes_per_line); e2_copy_image_data(s, data, max_length, length); DBG(18, "%d lines read, eof: %d, canceling: %d, status: %d\n", *length / s->params.bytes_per_line, s->canceling, s->eof, status); /* continue reading if appropriate */ if (status == SANE_STATUS_GOOD) return status; e2_scan_finish(s); return status; } /* * void sane_cancel(SANE_Handle handle) * * Set the cancel flag to true. The next time the backend requests data * from the scanner the CAN message will be sent. */ void sane_cancel(SANE_Handle handle) { Epson_Scanner *s = (Epson_Scanner *) handle; DBG(1, "* %s\n", __func__); s->canceling = SANE_TRUE; } /* * SANE_Status sane_set_io_mode() * * not supported - for asynchronous I/O */ SANE_Status sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { return SANE_STATUS_UNSUPPORTED; } /* * SANE_Status sane_get_select_fd() * * not supported - for asynchronous I/O */ SANE_Status sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/avision.conf.in0000664000175000017500000000104412112021330015515 00000000000000 # These are the possible options. Normally any scanner # should work just fine without them - and they are only # needed for test and debugging. So if you experience problems # and you solve them with enabling options here, please notify # the SANE/Avision maintainer: Mike Kelly #option disable-gamma-table #option disable-calibration #option force-a4 #scsi AVISION #scsi FCPA #scsi MINOLTA #scsi MITSBISH MCA-S600C #scsi MITSBISH MCA-SS600 #scsi HP #scsi hp #scsi /dev/scanner # usb libusb:002:003 # usb 0x03f0 0x0701 sane-backends-1.0.27/backend/mustek_usb2_reflective.c0000664000175000017500000014466412621240574017452 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005 Mustek. Originally maintained by Mustek Author:Jack Roy 2005.5.24 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro and similar USB2 scanners. */ /* forward declarations */ static SANE_Bool Reflective_Reset (void); static SANE_Bool Reflective_ScanSuggest (PTARGETIMAGE pTarget, PSUGGESTSETTING pSuggest); static SANE_Bool Reflective_SetupScan (COLORMODE ColorMode, unsigned short XDpi, unsigned short YDpi, SANE_Bool isInvert, unsigned short X, unsigned short Y, unsigned short Width, unsigned short Height); static SANE_Bool Reflective_StopScan (void); static SANE_Bool Reflective_GetRows (SANE_Byte * lpBlock, unsigned short * Rows, SANE_Bool isOrderInvert); static SANE_Bool Reflective_AdjustAD (void); static SANE_Bool Reflective_FindTopLeft (unsigned short * lpwStartX, unsigned short * lpwStartY); static SANE_Bool Reflective_LineCalibration16Bits (void); static SANE_Bool Reflective_PrepareScan (void); /*function description*/ /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: reset the scanner status Parameters: none Return value: if operation is success return TRUE els return FALSE ***********************************************************************/ static SANE_Bool Reflective_Reset () { DBG (DBG_FUNC, "Reflective_Reset: call in\n"); if (g_bOpened) { DBG (DBG_FUNC, "Reflective_Reset: scanner has been opened\n"); return FALSE; } if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile)) { DBG (DBG_FUNC, "Reflective_Reset: Asic_Open return error\n"); return FALSE; } if (STATUS_GOOD != Asic_Reset (&g_chip)) { DBG (DBG_FUNC, "Reflective_Reset: Asic_Reset return error\n"); return FALSE; } if (STATUS_GOOD != Asic_SetSource (&g_chip, LS_REFLECTIVE)) { DBG (DBG_FUNC, "Reflective_Reset: Asic_SetSource return error\n"); return FALSE; } if (STATUS_GOOD != Asic_TurnLamp (&g_chip, TRUE)) { DBG (DBG_FUNC, "Reflective_Reset: Asic_TurnLamp return error\n"); return FALSE; } if (STATUS_GOOD != Asic_Close (&g_chip)) { DBG (DBG_FUNC, "Reflective_Reset: Asic_Close return error\n"); return FALSE; } g_Y = 0; g_X = 0; g_Width = 0; g_SWWidth = 0; g_Height = 0; g_SWHeight = 0; g_wLineartThreshold = 128; g_dwTotalTotalXferLines = 0; g_bFirstReadImage = TRUE; g_pGammaTable = NULL; if (NULL != g_pDeviceFile) { free (g_pDeviceFile); g_pDeviceFile = NULL; } DBG (DBG_FUNC, "Reflective_Reset: exit\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: get the suggest parameter of scaning Parameters: pTarget: the information of scaning pSuggest: suggest parameter of scaning Return value: if the operation is success return TRUE els return FALSE ***********************************************************************/ static SANE_Bool Reflective_ScanSuggest (PTARGETIMAGE pTarget, PSUGGESTSETTING pSuggest) { int i; unsigned short wMaxWidth, wMaxHeight; DBG (DBG_FUNC, "Reflective_ScanSuggest: call in\n"); if (NULL == pTarget || NULL == pSuggest) { DBG (DBG_FUNC, "Reflective_ScanSuggest: parameters error\n"); return FALSE; } /*1. Looking up Optical Y Resolution */ for (i = 0; s_wOpticalYDpi[i] != 0; i++) { if (s_wOpticalYDpi[i] <= pTarget->wDpi) { pSuggest->wYDpi = s_wOpticalYDpi[i]; break; } } if (s_wOpticalYDpi[i] == 0) { i--; pSuggest->wYDpi = s_wOpticalYDpi[i]; } /*2. Looking up Optical X Resolution */ for (i = 0; s_wOpticalXDpi[i] != 0; i++) { if (s_wOpticalXDpi[i] <= pTarget->wDpi) { pSuggest->wXDpi = s_wOpticalXDpi[i]; break; } } if (s_wOpticalXDpi[i] == 0) { i--; pSuggest->wXDpi = s_wOpticalXDpi[i]; } DBG (DBG_FUNC, "Reflective_ScanSuggest: pTarget->wDpi = %d\n", pTarget->wDpi); DBG (DBG_FUNC, "Reflective_ScanSuggest: pSuggest->wXDpi = %d\n", pSuggest->wXDpi); DBG (DBG_FUNC, "Reflective_ScanSuggest: pSuggest->wYDpi = %d\n", pSuggest->wYDpi); /*3. suggest scan area */ pSuggest->wX = (unsigned short) (((unsigned int) (pTarget->wX) * (unsigned int) (pSuggest->wXDpi)) / (unsigned int) (pTarget->wDpi)); pSuggest->wY = (unsigned short) (((unsigned int) (pTarget->wY) * (unsigned int) (pSuggest->wYDpi)) / (unsigned int) (pTarget->wDpi)); pSuggest->wWidth = (unsigned short) (((unsigned int) (pTarget->wWidth) * (unsigned int) (pSuggest->wXDpi)) / (unsigned int) (pTarget->wDpi)); pSuggest->wHeight = (unsigned short) (((unsigned int) (pTarget->wHeight) * (unsigned int) (pSuggest->wYDpi)) / (unsigned int) (pTarget->wDpi)); pSuggest->wWidth = (pSuggest->wWidth / 2) * 2; DBG (DBG_FUNC, "Reflective_ScanSuggest: pTarget->wX = %d\n", pTarget->wX); DBG (DBG_FUNC, "Reflective_ScanSuggest: pTarget->wY = %d\n", pTarget->wY); DBG (DBG_FUNC, "Reflective_ScanSuggest: pTarget->wWidth = %d\n", pTarget->wWidth); DBG (DBG_FUNC, "Reflective_ScanSuggest: pTarget->wHeight = %d\n", pTarget->wHeight); DBG (DBG_FUNC, "Reflective_ScanSuggest: pSuggest->wX = %d\n", pSuggest->wX); DBG (DBG_FUNC, "Reflective_ScanSuggest: pSuggest->wY = %d\n", pSuggest->wY); DBG (DBG_FUNC, "Reflective_ScanSuggest: pSuggest->wWidth = %d\n", pSuggest->wWidth); DBG (DBG_FUNC, "Reflective_ScanSuggest: pSuggest->wHeight = %d\n", pSuggest->wHeight); if (pTarget->cmColorMode == CM_TEXT) { pSuggest->wWidth = ((pSuggest->wWidth + 7) >> 3) << 3; if (pSuggest->wWidth < 8) pSuggest->wWidth = 8; } /*4. check width and height */ wMaxWidth = (MAX_SCANNING_WIDTH * pSuggest->wXDpi) / 300; wMaxHeight = (3480 * pSuggest->wYDpi) / 300; /* 3480 for bumping */ DBG (DBG_FUNC, "Reflective_ScanSuggest: wMaxWidth = %d\n", wMaxWidth); DBG (DBG_FUNC, "Reflective_ScanSuggest: wMaxHeight = %d\n", wMaxHeight); if (CM_TEXT == pTarget->cmColorMode) { wMaxWidth = (wMaxWidth >> 3) << 3; } if (pSuggest->wWidth > wMaxWidth) { pSuggest->wWidth = wMaxWidth; } if (pSuggest->wHeight > wMaxHeight) { pSuggest->wHeight = wMaxHeight; } DBG (DBG_FUNC, "Reflective_ScanSuggest: g_Width=%d\n", g_Width); g_Width = ((pSuggest->wWidth + 15) >> 4) << 4; /*Real Scan Width */ DBG (DBG_FUNC, "Reflective_ScanSuggest: again, g_Width=%d\n", g_Width); g_Height = pSuggest->wHeight; if (pTarget->isOptimalSpeed) { switch (pTarget->cmColorMode) { case CM_RGB48: pSuggest->cmScanMode = CM_RGB48; pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 6); break; case CM_RGB24: pSuggest->cmScanMode = CM_RGB24ext; pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 3); break; case CM_GRAY16: pSuggest->cmScanMode = CM_GRAY16ext; pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 2); break; case CM_GRAY8: pSuggest->cmScanMode = CM_GRAY8ext; pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth)); break; case CM_TEXT: pSuggest->cmScanMode = CM_TEXT; pSuggest->dwBytesPerRow = (unsigned int) (pSuggest->wWidth) / 8; break; default: break; } } else { switch (pTarget->cmColorMode) { case CM_RGB48: pSuggest->cmScanMode = CM_RGB48; pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 6); break; case CM_RGB24: pSuggest->cmScanMode = CM_RGB24ext; pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 3); break; case CM_GRAY16: pSuggest->cmScanMode = CM_GRAY16ext; pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth) * 2); break; case CM_GRAY8: pSuggest->cmScanMode = CM_GRAY8ext; pSuggest->dwBytesPerRow = (unsigned int) ((pSuggest->wWidth)); break; case CM_TEXT: pSuggest->cmScanMode = CM_TEXT; pSuggest->dwBytesPerRow = (unsigned int) (pSuggest->wWidth) / 8; break; default: break; } } DBG (DBG_FUNC, "Reflective_ScanSuggest: pSuggest->dwBytesPerRow = %d\n", pSuggest->dwBytesPerRow); DBG (DBG_FUNC, "Reflective_ScanSuggest: leave Reflective_ScanSuggest\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: setup scanning process Parameters: ColorMode: ScanMode of Scanning, CM_RGB48, CM_GRAY and so on XDpi: X Resolution YDpi: Y Resolution isInvert: the RGB order X: X start coordinate Y: Y start coordinate Width: Width of Scan Image Height: Height of Scan Image Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool Reflective_SetupScan (COLORMODE ColorMode, unsigned short XDpi, unsigned short YDpi, SANE_Bool isInvert, unsigned short X, unsigned short Y, unsigned short Width, unsigned short Height) { isInvert = isInvert; DBG (DBG_FUNC, "Reflective_SetupScan: Call in\n"); if (g_bOpened) { DBG (DBG_FUNC, "Reflective_SetupScan: scanner has been opened\n"); return FALSE; } if (!g_bPrepared) { DBG (DBG_FUNC, "Reflective_SetupScan: scanner not prepared\n"); return FALSE; } g_ScanMode = ColorMode; g_XDpi = XDpi; g_YDpi = YDpi; g_SWWidth = Width; g_SWHeight = Height; switch (g_YDpi) { case 1200: g_wPixelDistance = 4; /*even & odd sensor problem */ g_wLineDistance = 24; g_Height += g_wPixelDistance; break; case 600: g_wPixelDistance = 0; /*no even & odd problem */ g_wLineDistance = 12; break; case 300: g_wPixelDistance = 0; g_wLineDistance = 6; break; case 150: g_wPixelDistance = 0; g_wLineDistance = 3; break; case 75: case 50: g_wPixelDistance = 0; g_wLineDistance = 1; break; default: g_wLineDistance = 0; } switch (g_ScanMode) { case CM_RGB48: g_BytesPerRow = 6 * g_Width; g_SWBytesPerRow = 6 * g_SWWidth; g_bScanBits = 48; g_Height += g_wLineDistance * 2; /*add height to do line distance */ break; case CM_RGB24ext: g_BytesPerRow = 3 * g_Width; g_SWBytesPerRow = 3 * g_SWWidth; g_bScanBits = 24; g_Height += g_wLineDistance * 2; /*add height to do line distance */ break; case CM_GRAY16ext: g_BytesPerRow = 2 * g_Width; g_SWBytesPerRow = 2 * g_SWWidth; g_bScanBits = 16; break; case CM_GRAY8ext: case CM_TEXT: g_BytesPerRow = g_Width; g_SWBytesPerRow = g_SWWidth; g_bScanBits = 8; break; default: break; } if (Asic_Open (&g_chip, g_pDeviceFile) != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_SetupScan: Asic_Open return error\n"); return FALSE; } DBG (DBG_FUNC, "Reflective_SetupScan: Asic_Open successfully\n"); g_bOpened = TRUE; Asic_TurnLamp (&g_chip, FALSE); Asic_TurnTA (&g_chip, FALSE); Asic_TurnLamp (&g_chip, TRUE); if (1200 == g_XDpi) { g_XDpi = 600; if (Reflective_AdjustAD () == FALSE) { DBG (DBG_FUNC, "Reflective_SetupScan: Reflective_AdjustAD return error\n"); return FALSE; } DBG (DBG_FUNC, "Reflective_SetupScan: Reflective_AdjustAD successfully\n"); if (Reflective_FindTopLeft (&g_X, &g_Y) == FALSE) { g_X = 187; g_Y = 43; } g_XDpi = 1200; if (Reflective_AdjustAD () == FALSE) { DBG (DBG_FUNC, "Reflective_SetupScan: Reflective_AdjustAD return error\n"); return FALSE; } DBG (DBG_FUNC, "Reflective_SetupScan: Reflective_AdjustAD successfully\n"); } else { if (Reflective_AdjustAD () == FALSE) { DBG (DBG_FUNC, "Reflective_SetupScan: Reflective_AdjustAD return error\n"); return FALSE; } DBG (DBG_FUNC, "Reflective_SetupScan: Reflective_AdjustAD successfully\n"); if (Reflective_FindTopLeft (&g_X, &g_Y) == FALSE) { g_X = 187; g_Y = 43; } } DBG (DBG_FUNC, "after find top left,g_X=%d,g_Y=%d\n", g_X, g_Y); if (1200 == g_XDpi) { g_X = g_X * 1200 / FIND_LEFT_TOP_CALIBRATE_RESOLUTION + X * 1200 / g_XDpi + 47; } else { if (75 == g_XDpi) { g_X = g_X + X * 600 / g_XDpi; } else { g_X = g_X + X * 600 / g_XDpi + 23; } } g_Y = g_Y * 1200 / FIND_LEFT_TOP_CALIBRATE_RESOLUTION + Y * 1200 / g_YDpi + 47; DBG (DBG_FUNC, "before line calibration,g_X=%d,g_Y=%d\n", g_X, g_Y); if (Reflective_LineCalibration16Bits () == FALSE) { DBG (DBG_FUNC, "Reflective_SetupScan: Reflective_LineCalibration16Bits return error\n"); return FALSE; } DBG (DBG_FUNC, "Reflective_SetupScan: after Reflective_LineCalibration16Bits,g_X=%d,g_Y=%d\n", g_X, g_Y); DBG (DBG_FUNC, "Reflective_SetupScan: before Asic_SetWindow\n"); DBG (DBG_FUNC, "Reflective_SetupScan: g_bScanBits=%d, g_XDpi=%d, g_YDpi=%d, g_X=%d, g_Y=%d, g_Width=%d, g_Height=%d\n", g_bScanBits, g_XDpi, g_YDpi, g_X, g_Y, g_Width, g_Height); if (g_Y > 300) { Asic_MotorMove (&g_chip, TRUE, g_Y - 300); } else { Asic_MotorMove (&g_chip, FALSE, 300 - g_Y); } g_Y = 300; Asic_SetWindow (&g_chip, g_bScanBits, g_XDpi, g_YDpi, g_X, g_Y, g_Width, g_Height); DBG (DBG_FUNC, "Reflective_SetupScan: leave Reflective_SetupScan\n"); return Reflective_PrepareScan (); } /********************************************************************** Author: Jack Date: 2005/05/13 Routine Description: To adjust the value of offset gain of R/G/B Parameters: none Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool Reflective_AdjustAD () { SANE_Byte * lpCalData; unsigned short wCalWidth; int nTimesOfCal; unsigned short wMaxValueR, wMinValueR, wMaxValueG, wMinValueG, wMaxValueB, wMinValueB; #if 0 SANE_Byte bDarkMaxLevel; SANE_Byte bDarkMinLevel; SANE_Byte bLastMinR, bLastROffset, bROffsetUpperBound = 255, bROffsetLowerBound = 0; SANE_Byte bLastMinG, bLastGOffset, bGOffsetUpperBound = 255, bGOffsetLowerBound = 0; SANE_Byte bLastMinB, bLastBOffset, bBOffsetUpperBound = 255, bBOffsetLowerBound = 0; float fRFactor = 1.0; float fGFactor = 1.0; float fBFactor = 1.0; #endif unsigned short wAdjustADResolution; DBG (DBG_FUNC, "Reflective_AdjustAD: call in\n"); if (!g_bOpened) { DBG (DBG_FUNC, "Reflective_AdjustAD: scanner has been opened\n"); return FALSE; } if (!g_bPrepared) { DBG (DBG_FUNC, "Reflective_AdjustAD: scanner not prepared\n"); return FALSE; } g_chip.AD.DirectionR = R_DIRECTION; g_chip.AD.DirectionG = G_DIRECTION; g_chip.AD.DirectionB = B_DIRECTION; g_chip.AD.GainR = R_GAIN; g_chip.AD.GainG = G_GAIN; g_chip.AD.GainB = B_GAIN; g_chip.AD.OffsetR = 152; g_chip.AD.OffsetG = 56; g_chip.AD.OffsetB = 8; if (g_XDpi <= 600) { wAdjustADResolution = 600; } else { wAdjustADResolution = 1200; } wCalWidth = 10240; lpCalData = (SANE_Byte *) malloc (sizeof (SANE_Byte) * wCalWidth * 3); if (lpCalData == NULL) { DBG (DBG_FUNC, "Reflective_AdjustAD: lpCalData malloc error\n"); return FALSE; } Asic_SetMotorType (&g_chip, FALSE, TRUE); Asic_SetCalibrate (&g_chip, 24, wAdjustADResolution, wAdjustADResolution, 0, 0, wCalWidth, 1, FALSE); MustScanner_PrepareCalculateMaxMin (wAdjustADResolution); nTimesOfCal = 0; #ifdef DEBUG_SAVE_IMAGE Asic_SetAFEGainOffset (&g_chip); Asic_ScanStart (&g_chip); Asic_ReadCalibrationData (&g_chip, lpCalData, wCalWidth * 3, 24); Asic_ScanStop (&g_chip); FILE *stream = NULL; SANE_Byte * lpBuf = (SANE_Byte *) malloc (50); if (NULL == lpBuf) { return FALSE; } memset (lpBuf, 0, 50); stream = fopen ("/root/AD(Ref).pnm\n", "wb+\n"); sprintf (lpBuf, "P6\n%d %d\n255\n\n", wCalWidth, 1); fwrite (lpBuf, sizeof (SANE_Byte), strlen (lpBuf), stream); fwrite (lpCalData, sizeof (SANE_Byte), wCalWidth * 3, stream); fclose (stream); free (lpBuf); #endif do { DBG (DBG_FUNC, "Reflective_AdjustAD: run in first adjust offset do-while\n"); Asic_SetAFEGainOffset (&g_chip); Asic_ScanStart (&g_chip); Asic_ReadCalibrationData (&g_chip, lpCalData, wCalWidth * 3, 24); Asic_ScanStop (&g_chip); MustScanner_CalculateMaxMin (lpCalData, &wMaxValueR, &wMinValueR, wAdjustADResolution); MustScanner_CalculateMaxMin (lpCalData + wCalWidth, &wMaxValueG, &wMinValueG, wAdjustADResolution); MustScanner_CalculateMaxMin (lpCalData + wCalWidth * 2, &wMaxValueB, &wMinValueB, wAdjustADResolution); if (g_chip.AD.DirectionR == 0) { if (wMinValueR > 15) { if (g_chip.AD.OffsetR < 8) g_chip.AD.DirectionR = 1; else g_chip.AD.OffsetR -= 8; } else if (wMinValueR < 5) g_chip.AD.OffsetR += 8; } else { if (wMinValueR > 15) g_chip.AD.OffsetR += 8; else if (wMinValueR < 5) g_chip.AD.OffsetR -= 8; } if (g_chip.AD.DirectionG == 0) { if (wMinValueG > 15) { if (g_chip.AD.OffsetG < 8) g_chip.AD.DirectionG = 1; else g_chip.AD.OffsetG -= 8; } else if (wMinValueG < 5) g_chip.AD.OffsetG += 8; } else { if (wMinValueG > 15) g_chip.AD.OffsetG += 8; else if (wMinValueG < 5) g_chip.AD.OffsetG -= 8; } if (g_chip.AD.DirectionB == 0) { if (wMinValueB > 15) { if (g_chip.AD.OffsetB < 8) g_chip.AD.DirectionB = 1; else g_chip.AD.OffsetB -= 8; } else if (wMinValueB < 5) g_chip.AD.OffsetB += 8; } else { if (wMinValueB > 15) g_chip.AD.OffsetB += 8; else if (wMinValueB < 5) g_chip.AD.OffsetB -= 8; } nTimesOfCal++; if (nTimesOfCal > 10) break; } while (wMinValueR > 15 || wMinValueR < 5 || wMinValueG > 15 || wMinValueG < 5 || wMinValueB > 15 || wMinValueB < 5); DBG (DBG_FUNC, "Reflective_AdjustAD: run out first adjust offset do-while\n"); DBG (DBG_FUNC, "Reflective_AdjustAD: \ g_chip.AD.OffsetR=%d,\ g_chip.AD.OffsetG=%d,\ g_chip.AD.OffsetB=%d\n", g_chip.AD.OffsetR, g_chip.AD.OffsetG, g_chip.AD.OffsetB); g_chip.AD.GainR = 1 - (double) (wMaxValueR - wMinValueR) / 210 > 0 ? (SANE_Byte) (((1 - (double) (wMaxValueR - wMinValueR) / 210)) * 63 * 6 / 5) : 0; g_chip.AD.GainG = 1 - (double) (wMaxValueG - wMinValueG) / 210 > 0 ? (SANE_Byte) (((1 - (double) (wMaxValueG - wMinValueG) / 210)) * 63 * 6 / 5) : 0; g_chip.AD.GainB = 1 - (double) (wMaxValueB - wMinValueB) / 210 > 0 ? (SANE_Byte) (((1 - (double) (wMaxValueB - wMinValueB) / 210)) * 63 * 6 / 5) : 0; if (g_chip.AD.GainR > 63) g_chip.AD.GainR = 63; if (g_chip.AD.GainG > 63) g_chip.AD.GainG = 63; if (g_chip.AD.GainB > 63) g_chip.AD.GainB = 63; DBG (DBG_FUNC, "Reflective_AdjustAD: " "g_chip.AD.GainR = %d," "g_chip.AD.GainG = %d," "g_chip.AD.GainB = %d\n", g_chip.AD.GainR, g_chip.AD.GainG, g_chip.AD.GainB); nTimesOfCal = 0; do { Asic_SetAFEGainOffset (&g_chip); Asic_ScanStart (&g_chip); Asic_ReadCalibrationData (&g_chip, lpCalData, wCalWidth * 3, 24); Asic_ScanStop (&g_chip); MustScanner_CalculateMaxMin (lpCalData, &wMaxValueR, &wMinValueR, wAdjustADResolution); MustScanner_CalculateMaxMin (lpCalData + wCalWidth, &wMaxValueG, &wMinValueG, wAdjustADResolution); MustScanner_CalculateMaxMin (lpCalData + wCalWidth * 2, &wMaxValueB, &wMinValueB, wAdjustADResolution); DBG (DBG_FUNC, "Reflective_AdjustAD: " "RGain=%d, ROffset=%d, RDir=%d GGain=%d, GOffset=%d, GDir=%d BGain=%d, BOffset=%d, BDir=%d\n", g_chip.AD.GainR, g_chip.AD.OffsetR, g_chip.AD.DirectionR, g_chip.AD.GainG, g_chip.AD.OffsetG, g_chip.AD.DirectionG, g_chip.AD.GainB, g_chip.AD.OffsetB, g_chip.AD.DirectionB); DBG (DBG_FUNC, "Reflective_AdjustAD: " "MaxR=%d, MinR=%d MaxG=%d, MinG=%d MaxB=%d, MinB=%d\n", wMaxValueR, wMinValueR, wMaxValueG, wMinValueG, wMaxValueB, wMinValueB); /*R Channel */ if ((wMaxValueR - wMinValueR) > REFL_MAX_LEVEL_RANGE) { if (g_chip.AD.GainR > 0) g_chip.AD.GainR--; } else { if ((wMaxValueR - wMinValueR) < REFL_MIN_LEVEL_RANGE) { if (wMaxValueR < REFL_WHITE_MIN_LEVEL) { g_chip.AD.GainR++; if (g_chip.AD.GainR > 63) g_chip.AD.GainR = 63; } else { if (wMaxValueR > REFL_WHITE_MAX_LEVEL) { if (g_chip.AD.GainR < 1) g_chip.AD.GainR = 0; else g_chip.AD.GainR--; } else { if (g_chip.AD.GainR > 63) g_chip.AD.GainR = 63; else g_chip.AD.GainR++; } } } else { if (wMaxValueR > REFL_WHITE_MAX_LEVEL) { if (g_chip.AD.GainR < 1) g_chip.AD.GainR = 0; else g_chip.AD.GainR--; } if (wMaxValueR < REFL_WHITE_MIN_LEVEL) { if (g_chip.AD.GainR > 63) g_chip.AD.GainR = 63; else g_chip.AD.GainR++; } } } /*G Channel */ if ((wMaxValueG - wMinValueG) > REFL_MAX_LEVEL_RANGE) { if (g_chip.AD.GainG > 0) g_chip.AD.GainG--; } else { if ((wMaxValueG - wMinValueG) < REFL_MIN_LEVEL_RANGE) { if (wMaxValueG < REFL_WHITE_MIN_LEVEL) { g_chip.AD.GainG++; if (g_chip.AD.GainG > 63) g_chip.AD.GainG = 63; } else { if (wMaxValueG > REFL_WHITE_MAX_LEVEL) { if (g_chip.AD.GainG < 1) g_chip.AD.GainG = 0; else g_chip.AD.GainG--; } else { if (g_chip.AD.GainG > 63) g_chip.AD.GainG = 63; else g_chip.AD.GainG++; } } } else { if (wMaxValueG > REFL_WHITE_MAX_LEVEL) { if (g_chip.AD.GainG < 1) g_chip.AD.GainG = 0; else g_chip.AD.GainG--; } if (wMaxValueG < REFL_WHITE_MIN_LEVEL) { if (g_chip.AD.GainG > 63) g_chip.AD.GainG = 63; else g_chip.AD.GainG++; } } } /* B Channel */ if ((wMaxValueB - wMinValueB) > REFL_MAX_LEVEL_RANGE) { if (g_chip.AD.GainB > 0) g_chip.AD.GainB--; } else { if ((wMaxValueB - wMinValueB) < REFL_MIN_LEVEL_RANGE) { if (wMaxValueB < REFL_WHITE_MIN_LEVEL) { g_chip.AD.GainB++; if (g_chip.AD.GainB > 63) g_chip.AD.GainB = 63; } else { if (wMaxValueB > REFL_WHITE_MAX_LEVEL) { if (g_chip.AD.GainB < 1) g_chip.AD.GainB = 0; else g_chip.AD.GainB--; } else { if (g_chip.AD.GainB > 63) g_chip.AD.GainB = 63; else g_chip.AD.GainB++; } } } else { if (wMaxValueB > REFL_WHITE_MAX_LEVEL) { if (g_chip.AD.GainB < 1) g_chip.AD.GainB = 0; else g_chip.AD.GainB--; } if (wMaxValueB < REFL_WHITE_MIN_LEVEL) { if (g_chip.AD.GainB > 63) g_chip.AD.GainB = 63; else g_chip.AD.GainB++; } } } nTimesOfCal++; if (nTimesOfCal > 10) break; } while ((wMaxValueR - wMinValueR) > REFL_MAX_LEVEL_RANGE || (wMaxValueR - wMinValueR) < REFL_MIN_LEVEL_RANGE || (wMaxValueG - wMinValueG) > REFL_MAX_LEVEL_RANGE || (wMaxValueG - wMinValueG) < REFL_MIN_LEVEL_RANGE || (wMaxValueB - wMinValueB) > REFL_MAX_LEVEL_RANGE || (wMaxValueB - wMinValueB) < REFL_MIN_LEVEL_RANGE); /* Adjust Offset 2nd */ nTimesOfCal = 0; do { DBG (DBG_FUNC, "Reflective_AdjustAD: run in second adjust offset do-while\n"); Asic_SetAFEGainOffset (&g_chip); Asic_ScanStart (&g_chip); Asic_ReadCalibrationData (&g_chip, lpCalData, wCalWidth * 3, 24); Asic_ScanStop (&g_chip); MustScanner_CalculateMaxMin (lpCalData, &wMaxValueR, &wMinValueR, wAdjustADResolution); MustScanner_CalculateMaxMin (lpCalData + wCalWidth, &wMaxValueG, &wMinValueG, wAdjustADResolution); MustScanner_CalculateMaxMin (lpCalData + wCalWidth * 2, &wMaxValueB, &wMinValueB, wAdjustADResolution); DBG (DBG_FUNC, "Reflective_AdjustAD: " "RGain=%d, ROffset=%d, RDir=%d GGain=%d, GOffset=%d, GDir=%d BGain=%d, BOffset=%d, BDir=%d\n", g_chip.AD.GainR, g_chip.AD.OffsetR, g_chip.AD.DirectionR, g_chip.AD.GainG, g_chip.AD.OffsetG, g_chip.AD.DirectionG, g_chip.AD.GainB, g_chip.AD.OffsetB, g_chip.AD.DirectionB); DBG (DBG_FUNC, "Reflective_AdjustAD: " "MaxR=%d, MinR=%d MaxG=%d, MinG=%d MaxB=%d, MinB=%d\n", wMaxValueR, wMinValueR, wMaxValueG, wMinValueG, wMaxValueB, wMinValueB); if (g_chip.AD.DirectionR == 0) { if (wMinValueR > 20) { if (g_chip.AD.OffsetR < 8) g_chip.AD.DirectionR = 1; else g_chip.AD.OffsetR -= 8; } else if (wMinValueR < 10) g_chip.AD.OffsetR += 8; } else { if (wMinValueR > 20) g_chip.AD.OffsetR += 8; else if (wMinValueR < 10) g_chip.AD.OffsetR -= 8; } if (g_chip.AD.DirectionG == 0) { if (wMinValueG > 20) { if (g_chip.AD.OffsetG < 8) g_chip.AD.DirectionG = 1; else g_chip.AD.OffsetG -= 8; } else if (wMinValueG < 10) g_chip.AD.OffsetG += 8; } else { if (wMinValueG > 20) g_chip.AD.OffsetG += 8; else if (wMinValueG < 10) g_chip.AD.OffsetG -= 8; } if (g_chip.AD.DirectionB == 0) { if (wMinValueB > 20) { if (g_chip.AD.OffsetB < 8) g_chip.AD.DirectionB = 1; else g_chip.AD.OffsetB -= 8; } else if (wMinValueB < 10) g_chip.AD.OffsetB += 8; } else { if (wMinValueB > 20) g_chip.AD.OffsetB += 8; else if (wMinValueB < 10) g_chip.AD.OffsetB -= 8; } nTimesOfCal++; if (nTimesOfCal > 8) break; } while (wMinValueR > 20 || wMinValueR < 10 || wMinValueG > 20 || wMinValueG < 10 || wMinValueB > 20 || wMinValueB < 10); DBG (DBG_FUNC, "Reflective_AdjustAD: run in second adjust offset do-while\n"); DBG (DBG_FUNC, "Reflective_AdjustAD:after ad gain\n"); DBG (DBG_FUNC, "Reflective_AdjustAD: " "g_chip.AD.GainR = %d," "g_chip.AD.GainG = %d," "g_chip.AD.GainB = %d\n", g_chip.AD.GainR, g_chip.AD.GainG, g_chip.AD.GainB); free (lpCalData); DBG (DBG_FUNC, "Reflective_AdjustAD: leave Reflective_AdjustAD\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Find top and left side Parameters: lpwStartX: the left side lpwStartY: the top side Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool Reflective_FindTopLeft (unsigned short * lpwStartX, unsigned short * lpwStartY) { unsigned short wCalWidth = FIND_LEFT_TOP_WIDTH_IN_DIP; unsigned short wCalHeight = FIND_LEFT_TOP_HEIGHT_IN_DIP; int i, j; unsigned short wLeftSide; unsigned short wTopSide; int nScanBlock; SANE_Byte * lpCalData; unsigned int dwTotalSize; unsigned short wXResolution, wYResolution; DBG (DBG_FUNC, "Reflective_FindTopLeft: call in\n"); if (!g_bOpened) { DBG (DBG_FUNC, "Reflective_FindTopLeft: scanner has been opened\n"); return FALSE; } if (!g_bPrepared) { DBG (DBG_FUNC, "Reflective_FindTopLeft: scanner not prepared\n"); return FALSE; } wXResolution = wYResolution = FIND_LEFT_TOP_CALIBRATE_RESOLUTION; lpCalData = (SANE_Byte *) malloc (sizeof (SANE_Byte) * wCalWidth * wCalHeight); if (lpCalData == NULL) { DBG (DBG_FUNC, "Reflective_FindTopLeft: lpCalData malloc error\n"); return FALSE; } dwTotalSize = wCalWidth * wCalHeight; nScanBlock = (int) (dwTotalSize / g_dwCalibrationSize); Asic_SetMotorType (&g_chip, TRUE, TRUE); Asic_SetCalibrate (&g_chip, 8, wXResolution, wYResolution, 0, 0, wCalWidth, wCalHeight, FALSE); Asic_SetAFEGainOffset (&g_chip); if (Asic_ScanStart (&g_chip) != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_FindTopLeft: Asic_ScanStart return error\n"); free (lpCalData); return FALSE; } for (i = 0; i < nScanBlock; i++) { if (STATUS_GOOD != Asic_ReadCalibrationData (&g_chip, lpCalData + i * g_dwCalibrationSize, g_dwCalibrationSize, 8)) { DBG (DBG_FUNC, "Reflective_FindTopLeft: Asic_ReadCalibrationData return error\n"); free (lpCalData); return FALSE; } } if (STATUS_GOOD != Asic_ReadCalibrationData (&g_chip, lpCalData + (nScanBlock) * g_dwCalibrationSize, (dwTotalSize - g_dwCalibrationSize * nScanBlock), 8)) { DBG (DBG_FUNC, "Reflective_FindTopLeft: Asic_ReadCalibrationData return error\n"); free (lpCalData); return FALSE; } Asic_ScanStop (&g_chip); #ifdef DEBUG_SAVE_IMAGE FILE *stream = NULL; stream = fopen ("/root/bound(Ref).pnm", "wb+\n"); SANE_Byte * lpBuf = (SANE_Byte *) malloc (50); if (NULL == lpBuf) { return FALSE; } memset (lpBuf, 0, 50); sprintf (lpBuf, "P5\n%d %d\n255\n", wCalWidth, wCalHeight); fwrite (lpBuf, sizeof (SANE_Byte), strlen (lpBuf), stream); fwrite (lpCalData, sizeof (SANE_Byte), wCalWidth * wCalHeight, stream); fclose (stream); free (lpBuf); #endif wLeftSide = 0; wTopSide = 0; /* Find Left Side */ for (i = wCalWidth - 1; i > 0; i--) { wLeftSide = *(lpCalData + i); wLeftSide += *(lpCalData + wCalWidth * 2 + i); wLeftSide += *(lpCalData + wCalWidth * 4 + i); wLeftSide += *(lpCalData + wCalWidth * 6 + i); wLeftSide += *(lpCalData + wCalWidth * 8 + i); wLeftSide /= 5; if (wLeftSide < 60) { if (i == wCalWidth - 1) { break; } *lpwStartX = i; { break; } } } /*Find Top Side i=left side */ for (j = 0; j < wCalHeight; j++) { wTopSide = *(lpCalData + wCalWidth * j + i - 2); wTopSide += *(lpCalData + wCalWidth * j + i - 4); wTopSide += *(lpCalData + wCalWidth * j + i - 6); wTopSide += *(lpCalData + wCalWidth * j + i - 8); wTopSide += *(lpCalData + wCalWidth * j + i - 10); wTopSide /= 5; if (wTopSide > 60) { if (j == 0) { break; } *lpwStartY = j; { break; } } } if ((*lpwStartX < 100) || (*lpwStartX > 250)) { *lpwStartX = 187; } if ((*lpwStartY < 10) || (*lpwStartY > 100)) { *lpwStartY = 43; } DBG (DBG_FUNC, "Reflective_FindTopLeft: *lpwStartY = %d, *lpwStartX = %d\n", *lpwStartY, *lpwStartX); Asic_MotorMove (&g_chip, FALSE, (wCalHeight - *lpwStartY + BEFORE_SCANNING_MOTOR_FORWARD_PIXEL) * 1200 / wYResolution); free (lpCalData); DBG (DBG_FUNC, "Reflective_FindTopLeft: leave Reflective_FindTopLeft\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Stop scan Parameters: none Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool Reflective_StopScan () { DBG (DBG_FUNC, "Reflective_StopScan: call in\n"); if (!g_bOpened) { DBG (DBG_FUNC, "Reflective_StopScan: scanner not opened\n"); return FALSE; } if (!g_bPrepared) { DBG (DBG_FUNC, "Reflective_StopScan: scanner not prepared\n"); return FALSE; } g_isCanceled = TRUE; /*tell parent process stop read image */ pthread_cancel (g_threadid_readimage); pthread_join (g_threadid_readimage, NULL); DBG (DBG_FUNC, "Reflective_StopScan: thread exit\n"); Asic_ScanStop (&g_chip); Asic_Close (&g_chip); g_bOpened = FALSE; DBG (DBG_FUNC, "Reflective_StopScan: leave Reflective_StopScan\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Get the calibration data Parameters: none Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool Reflective_LineCalibration16Bits () { STATUS status; SANE_Byte * lpWhiteData; SANE_Byte * lpDarkData; unsigned int dwWhiteTotalSize; unsigned int dwDarkTotalSize; unsigned short wCalHeight = LINE_CALIBRATION__16BITS_HEIGHT; unsigned short wCalWidth; unsigned short *lpWhiteShading; unsigned short *lpDarkShading; double wRWhiteLevel = 0; double wGWhiteLevel = 0; double wBWhiteLevel = 0; unsigned int dwRDarkLevel = 0; unsigned int dwGDarkLevel = 0; unsigned int dwBDarkLevel = 0; unsigned int dwREvenDarkLevel = 0; unsigned int dwGEvenDarkLevel = 0; unsigned int dwBEvenDarkLevel = 0; unsigned short * lpRWhiteSort; unsigned short * lpGWhiteSort; unsigned short * lpBWhiteSort; unsigned short * lpRDarkSort; unsigned short * lpGDarkSort; unsigned short * lpBDarkSort; int i, j; DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: call in\n"); if (!g_bOpened) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: scanner not opened\n"); return FALSE; } if (!g_bPrepared) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: scanner not prepared\n"); return FALSE; } wCalWidth = g_Width; dwWhiteTotalSize = wCalWidth * wCalHeight * 3 * 2; dwDarkTotalSize = wCalWidth * wCalHeight * 3 * 2; lpWhiteData = (SANE_Byte *) malloc (sizeof (SANE_Byte) * dwWhiteTotalSize); lpDarkData = (SANE_Byte *) malloc (sizeof (SANE_Byte) * dwDarkTotalSize); if (lpWhiteData == NULL || lpDarkData == NULL) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: lpWhiteData or lpDarkData malloc error \n"); return FALSE; } Asic_SetMotorType (&g_chip, TRUE, TRUE); Asic_SetAFEGainOffset (&g_chip); status = Asic_SetCalibrate (&g_chip, 48, g_XDpi, g_YDpi, g_X, 0, wCalWidth, wCalHeight, TRUE); if (status != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: Asic_SetCalibrate return error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } status = Asic_ScanStart (&g_chip); if (status != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: Asic_ScanStart return error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } status = Asic_ReadCalibrationData (&g_chip, lpWhiteData, dwWhiteTotalSize, 8); if (status != STATUS_GOOD) { free (lpWhiteData); free (lpDarkData); return FALSE; } Asic_ScanStop (&g_chip); /*Read dark level data */ status = Asic_SetMotorType (&g_chip, FALSE, TRUE); if (status != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: Asic_SetMotorType return error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } status = Asic_SetCalibrate (&g_chip, 48, g_XDpi, g_YDpi, g_X, 0, wCalWidth, wCalHeight, TRUE); if (status != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: Asic_SetCalibrate return error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } status = Asic_TurnLamp (&g_chip, FALSE); if (status != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: Asic_TurnLamp return error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } usleep (500000); status = Asic_ScanStart (&g_chip); if (status != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: Asic_ScanStart return error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } status = Asic_ReadCalibrationData (&g_chip, lpDarkData, dwDarkTotalSize, 8); if (status != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: Asic_ReadCalibrationData return error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } Asic_ScanStop (&g_chip); /* Turn on lamp */ status = Asic_TurnLamp (&g_chip, TRUE); if (status != STATUS_GOOD) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: Asic_TurnLamp return error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } #ifdef DEBUG_SAVE_IMAGE FILE *stream = NULL; SANE_Byte * lpBuf = (SANE_Byte *) malloc (50); if (NULL == lpBuf) { return FALSE; } memset (lpBuf, 0, 50); stream = fopen ("/root/whiteshading(Ref).pnm", "wb+\n"); sprintf (lpBuf, "P6\n%d %d\n65535\n", wCalWidth, wCalHeight); fwrite (lpBuf, sizeof (SANE_Byte), strlen (lpBuf), stream); fwrite (lpWhiteData, sizeof (SANE_Byte), wCalWidth * wCalHeight * 3 * 2, stream); fclose (stream); memset (lpBuf, 0, 50); stream = fopen ("/root/darkshading(Ref).pnm", "wb+\n"); sprintf (lpBuf, "P6\n%d %d\n65535\n", wCalWidth, wCalHeight); fwrite (lpBuf, sizeof (SANE_Byte), strlen (lpBuf), stream); fwrite (lpDarkData, sizeof (SANE_Byte), wCalWidth * wCalHeight * 3 * 2, stream); fclose (stream); free (lpBuf); #endif sleep (1); lpWhiteShading = (unsigned short *) malloc (sizeof (unsigned short) * wCalWidth * 3); lpDarkShading = (unsigned short *) malloc (sizeof (unsigned short) * wCalWidth * 3); lpRWhiteSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight); lpGWhiteSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight); lpBWhiteSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight); lpRDarkSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight); lpGDarkSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight); lpBDarkSort = (unsigned short *) malloc (sizeof (unsigned short) * wCalHeight); if (lpWhiteShading == NULL || lpDarkShading == NULL || lpRWhiteSort == NULL || lpGWhiteSort == NULL || lpBWhiteSort == NULL || lpRDarkSort == NULL || lpGDarkSort == NULL || lpBDarkSort == NULL) { DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: malloc error \n"); free (lpWhiteData); free (lpDarkData); return FALSE; } /* create dark level shading */ dwRDarkLevel = 0; dwGDarkLevel = 0; dwBDarkLevel = 0; dwREvenDarkLevel = 0; dwGEvenDarkLevel = 0; dwBEvenDarkLevel = 0; DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: wCalWidth = %d, wCalHeight = %d\n", wCalWidth, wCalHeight); for (i = 0; i < wCalWidth; i++) { for (j = 0; j < wCalHeight; j++) { lpRDarkSort[j] = (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 0)); lpRDarkSort[j] += (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 1) << 8); lpGDarkSort[j] = (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 2)); lpGDarkSort[j] += (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 3) << 8); lpBDarkSort[j] = (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 4)); lpBDarkSort[j] += (unsigned short) (*(lpDarkData + j * wCalWidth * 6 + i * 6 + 5) << 8); } if (g_XDpi == 1200) { /*do dark shading table with mean */ if (i % 2) { dwRDarkLevel += (unsigned int) MustScanner_FiltLower (lpRDarkSort, wCalHeight, 20, 30); dwGDarkLevel += (unsigned int) MustScanner_FiltLower (lpGDarkSort, wCalHeight, 20, 30); dwBDarkLevel += (unsigned int) MustScanner_FiltLower (lpBDarkSort, wCalHeight, 20, 30); } else { dwREvenDarkLevel += (unsigned int) MustScanner_FiltLower (lpRDarkSort, wCalHeight, 20, 30); dwGEvenDarkLevel += (unsigned int) MustScanner_FiltLower (lpGDarkSort, wCalHeight, 20, 30); dwBEvenDarkLevel += (unsigned int) MustScanner_FiltLower (lpBDarkSort, wCalHeight, 20, 30); } } else { dwRDarkLevel += (unsigned int) MustScanner_FiltLower (lpRDarkSort, wCalHeight, 20, 30); dwGDarkLevel += (unsigned int) MustScanner_FiltLower (lpGDarkSort, wCalHeight, 20, 30); dwBDarkLevel += (unsigned int) MustScanner_FiltLower (lpBDarkSort, wCalHeight, 20, 30); } } if (g_XDpi == 1200) { dwRDarkLevel = (unsigned int) (dwRDarkLevel / (wCalWidth / 2)); dwGDarkLevel = (unsigned int) (dwGDarkLevel / (wCalWidth / 2)); dwBDarkLevel = (unsigned int) (dwBDarkLevel / (wCalWidth / 2)); dwREvenDarkLevel = (unsigned int) (dwREvenDarkLevel / (wCalWidth / 2)); dwGEvenDarkLevel = (unsigned int) (dwGEvenDarkLevel / (wCalWidth / 2)); dwBEvenDarkLevel = (unsigned int) (dwBEvenDarkLevel / (wCalWidth / 2)); } else { dwRDarkLevel = (unsigned int) (dwRDarkLevel / wCalWidth); dwGDarkLevel = (unsigned int) (dwGDarkLevel / wCalWidth); dwBDarkLevel = (unsigned int) (dwBDarkLevel / wCalWidth); } /*Create white shading */ for (i = 0; i < wCalWidth; i++) { wRWhiteLevel = 0; wGWhiteLevel = 0; wBWhiteLevel = 0; for (j = 0; j < wCalHeight; j++) { lpRWhiteSort[j] = (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 0)); lpRWhiteSort[j] += (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 1) << 8); lpGWhiteSort[j] = (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 2)); lpGWhiteSort[j] += (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 3) << 8); lpBWhiteSort[j] = (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 4)); lpBWhiteSort[j] += (unsigned short) (*(lpWhiteData + j * wCalWidth * 2 * 3 + i * 6 + 5) << 8); } if (g_XDpi == 1200) { if (i % 2) { *(lpDarkShading + i * 3 + 0) = (unsigned short) dwRDarkLevel; *(lpDarkShading + i * 3 + 1) = (unsigned short) dwGDarkLevel; *(lpDarkShading + i * 3 + 2) = (unsigned short) dwBDarkLevel; } else { *(lpDarkShading + i * 3 + 0) = (unsigned short) dwREvenDarkLevel; *(lpDarkShading + i * 3 + 1) = (unsigned short) dwGEvenDarkLevel; *(lpDarkShading + i * 3 + 2) = (unsigned short) dwBEvenDarkLevel; } } else { *(lpDarkShading + i * 3 + 0) = (unsigned short) dwRDarkLevel; *(lpDarkShading + i * 3 + 1) = (unsigned short) dwGDarkLevel; *(lpDarkShading + i * 3 + 2) = (unsigned short) dwBDarkLevel; } /*Create white shading */ wRWhiteLevel = (double) (MustScanner_FiltLower (lpRWhiteSort, wCalHeight, 20, 30) - *(lpDarkShading + i * 3 + 0)); wGWhiteLevel = (double) (MustScanner_FiltLower (lpGWhiteSort, wCalHeight, 20, 30) - *(lpDarkShading + i * 3 + 1)); wBWhiteLevel = (double) (MustScanner_FiltLower (lpBWhiteSort, wCalHeight, 20, 30) - *(lpDarkShading + i * 3 + 2)); if (wRWhiteLevel > 0) *(lpWhiteShading + i * 3 + 0) = (unsigned short) (((float) 65535 / wRWhiteLevel * 0x2000)); else *(lpWhiteShading + i * 3 + 0) = 0x2000; if (wGWhiteLevel > 0) *(lpWhiteShading + i * 3 + 1) = (unsigned short) (((float) 65535 / wGWhiteLevel * 0x2000)); else *(lpWhiteShading + i * 3 + 1) = 0x2000; if (wBWhiteLevel > 0) *(lpWhiteShading + i * 3 + 2) = (unsigned short) (((float) 65535 / wBWhiteLevel * 0x2000)); else *(lpWhiteShading + i * 3 + 2) = 0x2000; } free (lpWhiteData); free (lpDarkData); free (lpRWhiteSort); free (lpGWhiteSort); free (lpBWhiteSort); free (lpRDarkSort); free (lpGDarkSort); free (lpBDarkSort); Asic_SetShadingTable (&g_chip, lpWhiteShading, lpDarkShading, g_XDpi, wCalWidth, 0); free (lpWhiteShading); free (lpDarkShading); DBG (DBG_FUNC, "Reflective_LineCalibration16Bits: leave Reflective_LineCalibration16Bits\n"); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/14 Routine Description: Prepare scan image Parameters: none Return value: if operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool Reflective_PrepareScan () { g_wScanLinesPerBlock = g_dwBufferSize / g_BytesPerRow; g_wMaxScanLines = g_dwImageBufferSize / g_BytesPerRow; g_wMaxScanLines = (g_wMaxScanLines / g_wScanLinesPerBlock) * g_wScanLinesPerBlock; g_isCanceled = FALSE; g_dwScannedTotalLines = 0; g_wReadedLines = 0; g_wtheReadyLines = 0; g_wReadImageLines = 0; g_wReadyShadingLine = 0; g_wStartShadingLinePos = 0; switch (g_ScanMode) { case CM_RGB48: g_wtheReadyLines = g_wLineDistance * 2 + g_wPixelDistance; DBG (DBG_FUNC, "Reflective_PrepareScan:g_wtheReadyLines=%d\n", g_wtheReadyLines); DBG (DBG_FUNC, "Reflective_PrepareScan:g_lpReadImageHead malloc %d Bytes\n", g_dwImageBufferSize); g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize); if (g_lpReadImageHead == NULL) { DBG (DBG_FUNC, "Reflective_PrepareScan: g_lpReadImageHead malloc error \n"); return FALSE; } break; case CM_RGB24ext: g_wtheReadyLines = g_wLineDistance * 2 + g_wPixelDistance; DBG (DBG_FUNC, "Reflective_PrepareScan:g_wtheReadyLines=%d\n", g_wtheReadyLines); DBG (DBG_FUNC, "Reflective_PrepareScan:g_lpReadImageHead malloc %d Bytes\n", g_dwImageBufferSize); g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize); if (g_lpReadImageHead == NULL) { DBG (DBG_FUNC, "Reflective_PrepareScan: g_lpReadImageHead malloc error \n"); return FALSE; } break; case CM_GRAY16ext: g_wtheReadyLines = g_wPixelDistance; DBG (DBG_FUNC, "Reflective_PrepareScan:g_wtheReadyLines=%d\n", g_wtheReadyLines); DBG (DBG_FUNC, "Reflective_PrepareScan:g_lpReadImageHead malloc %d Bytes\n", g_dwImageBufferSize); g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize); if (g_lpReadImageHead == NULL) { DBG (DBG_FUNC, "Reflective_PrepareScan: g_lpReadImageHead malloc error \n"); return FALSE; } break; case CM_GRAY8ext: g_wtheReadyLines = g_wPixelDistance; DBG (DBG_FUNC, "Reflective_PrepareScan:g_wtheReadyLines=%d\n", g_wtheReadyLines); DBG (DBG_FUNC, "Reflective_PrepareScan:g_lpReadImageHead malloc %d Bytes\n", g_dwImageBufferSize); g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize); if (g_lpReadImageHead == NULL) { DBG (DBG_FUNC, "Reflective_PrepareScan: g_lpReadImageHead malloc error \n"); return FALSE; } break; case CM_TEXT: g_wtheReadyLines = g_wPixelDistance; DBG (DBG_FUNC, "Reflective_PrepareScan:g_wtheReadyLines=%d\n", g_wtheReadyLines); DBG (DBG_FUNC, "Reflective_PrepareScan:g_lpReadImageHead malloc %d Bytes\n", g_dwImageBufferSize); g_lpReadImageHead = (SANE_Byte *) malloc (g_dwImageBufferSize); if (g_lpReadImageHead == NULL) { DBG (DBG_FUNC, "Reflective_PrepareScan: g_lpReadImageHead malloc error \n"); return FALSE; } break; default: break; } Asic_ScanStart (&g_chip); return TRUE; } /********************************************************************** Author: Jack Date: 2005/05/15 Routine Description: Get the data of image Parameters: lpBlock: the data of image Rows: the rows of image isOrderInvert: the RGB order Return value: if the operation is success return TRUE else return FALSE ***********************************************************************/ static SANE_Bool Reflective_GetRows (SANE_Byte * lpBlock, unsigned short * Rows, SANE_Bool isOrderInvert) { DBG (DBG_FUNC, "Reflective_GetRows: call in \n"); if (!g_bOpened) { DBG (DBG_FUNC, "Reflective_GetRows: scanner not opened \n"); return FALSE; } if (!g_bPrepared) { DBG (DBG_FUNC, "Reflective_GetRows: scanner not prepared \n"); return FALSE; } switch (g_ScanMode) { case CM_RGB48: if (g_XDpi == 1200) return MustScanner_GetRgb48BitLine1200DPI (lpBlock, isOrderInvert, Rows); else return MustScanner_GetRgb48BitLine (lpBlock, isOrderInvert, Rows); case CM_RGB24ext: if (g_XDpi == 1200) return MustScanner_GetRgb24BitLine1200DPI (lpBlock, isOrderInvert, Rows); else return MustScanner_GetRgb24BitLine (lpBlock, isOrderInvert, Rows); case CM_GRAY16ext: if (g_XDpi == 1200) return MustScanner_GetMono16BitLine1200DPI (lpBlock, isOrderInvert, Rows); else return MustScanner_GetMono16BitLine (lpBlock, isOrderInvert, Rows); case CM_GRAY8ext: if (g_XDpi == 1200) return MustScanner_GetMono8BitLine1200DPI (lpBlock, isOrderInvert, Rows); else return MustScanner_GetMono8BitLine (lpBlock, isOrderInvert, Rows); case CM_TEXT: if (g_XDpi == 1200) return MustScanner_GetMono1BitLine1200DPI (lpBlock, isOrderInvert, Rows); else return MustScanner_GetMono1BitLine (lpBlock, isOrderInvert, Rows); default: return FALSE; } DBG (DBG_FUNC, "Reflective_GetRows: leave Reflective_GetRows \n"); return FALSE; } /* end of the file ScannerReflective.c */ sane-backends-1.0.27/backend/u12.h0000664000175000017500000002350012112021330013352 00000000000000/** @file u12.h * @brief Definitions for the backend. * * Copyright (c) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - added scaling variables to struct u12d * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __U12_H__ #define __U12_H__ #ifndef SANE_OPTION /* for compatibility with older versions */ typedef union { SANE_Word w; SANE_Word *wa; /* word array */ SANE_String s; } Option_Value; #endif /************************ some definitions ***********************************/ #define U12_CONFIG_FILE "u12.conf" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define _MM_PER_INCH 25.4 #define _MEASURE_BASE 300UL #define _DEF_DPI 50 /** the default image */ #define _DEFAULT_TLX 0 #define _DEFAULT_TLY 0 #define _DEFAULT_BRX 126 #define _DEFAULT_BRY 76 #define _DEFAULT_TP_TLX 3.5 #define _DEFAULT_TP_TLY 10.5 #define _DEFAULT_TP_BRX 38.5 #define _DEFAULT_TP_BRY 33.5 #define _DEFAULT_NEG_TLX 1.5 #define _DEFAULT_NEG_TLY 1.5 #define _DEFAULT_NEG_BRX 37.5 #define _DEFAULT_NEG_BRY 25.5 /** image sizes for normal, transparent and negative modes */ #define _TPAPageWidth 500U #define _TPAPageHeight 510U #define _TPAMinDpi 150 #define _TPAModeSupportMin COLOR_TRUE24 #define _NegativePageWidth 460UL #define _NegativePageHeight 350UL #define _TP_X ((double)_TPAPageWidth/300.0 * _MM_PER_INCH) #define _TP_Y ((double)_TPAPageHeight/300.0 * _MM_PER_INCH) #define _NEG_X ((double)_NegativePageWidth/300.0 * _MM_PER_INCH) #define _NEG_Y ((double)_NegativePageHeight/300.0 * _MM_PER_INCH) /** scan modes */ #define COLOR_BW 0 #define COLOR_256GRAY 1 #define COLOR_TRUE24 2 #define COLOR_TRUE42 3 #define _VAR_NOT_USED(x) ((x)=(x)) /** usb id buffer */ #define _MAX_ID_LEN 20 /** Scanmodes */ #define _ScanMode_Color 0 #define _ScanMode_AverageOut 1 /* CCD averaged 2 pixels value for output*/ #define _ScanMode_Mono 2 /* not color mode */ /** Scansource + additional flags */ #define _SCANDEF_PREVIEW 0x00000001 #define _SCANDEF_Transparency 0x00000100 #define _SCANDEF_Negative 0x00000200 #define _SCANDEF_TPA (_SCANDEF_Transparency | _SCANDEF_Negative) #define _SCANDEF_SCANNING 0x8000000 /** for Gamma tables */ #define _MAP_RED 0 #define _MAP_GREEN 1 #define _MAP_BLUE 2 #define _MAP_MASTER 3 /** the ASIC modes */ #define _PP_MODE_SPP 0 #define _PP_MODE_EPP 1 /************************ some structures ************************************/ enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, #ifdef ALL_MODES OPT_MODE, OPT_EXT_MODE, #endif OPT_RESOLUTION, OPT_PREVIEW, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_CUSTOM_GAMMA, OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, NUM_OPTIONS }; /** for adjusting the scanner settings */ typedef struct { int lampOff; int lampOffOnEnd; int warmup; /* for adjusting the default gamma settings */ double rgamma; double ggamma; double bgamma; double graygamma; /* for adjusting scan-area */ long upNormal; long upPositive; long upNegative; long leftNormal; } AdjDef, *pAdjDef; /** for holding basic capabilities */ typedef struct { unsigned short scanAreaX; unsigned short scanAreaY; unsigned long flag; #if 0 RANGE rDataType; /* available scan modes */ unsigned short wMaxExtentX; /* scanarea width */ unsigned short wMaxExtentY; /* scanarea height */ #endif } ScannerCaps, *pScannerCaps; /** for defining the scanmodes */ typedef const struct mode_param { int color; int depth; int scanmode; } ModeParam, *pModeParam; /** Here we hold all device specific data */ typedef struct u12d { SANE_Bool initialized; /* device already initialized? */ struct u12d *next; /* pointer to next dev in list */ int fd; /* device handle */ int mode; char *name; /* (to avoid compiler warnings!)*/ SANE_Device sane; /* info struct */ /* scan-area settings */ SANE_Int max_x; /* max XY-extension of the scan-*/ SANE_Int max_y; /* area */ SANE_Range x_range; /* x-range of the scan-area */ SANE_Range y_range; /* y-range of the scan-area */ /* resolution settings */ SANE_Int dpi_max_x; /* */ SANE_Int dpi_max_y; /* */ SANE_Range dpi_range; /* resolution range */ SANE_Int *res_list; /* to hold the available phys. */ SANE_Int res_list_size; /* resolution values */ ScannerCaps caps; /* caps reported by the driver */ AdjDef adj; /* for driver adjustment */ char usbId[_MAX_ID_LEN];/* to keep Vendor and product */ /* ID string (from conf) file */ /* our gamma tables */ SANE_Word gamma_table[4][4096]; SANE_Range gamma_range; int gamma_length; /* the shading section */ pFnDACOffs fnDarkOffset; /**< ... */ ShadingDef shade; /**< shading parameters */ /* */ SANE_Byte PCBID; /**< which version of the PCB */ /* motor control section */ SANE_Byte MotorID; /**< the type of the motor drivers */ SANE_Byte MotorPower; /**< how to drive the motor */ SANE_Bool f2003; SANE_Byte XStepMono; SANE_Byte XStepColor; SANE_Byte XStepBack; SANE_Bool f0_8_16; SANE_Byte scanStates[_SCANSTATE_BYTES]; /* CCD section */ SANE_Byte CCDID; /**< what CCD do we have */ RegDef *CCDRegs; /**< pointer to the register descr */ u_short numCCDRegs; /**< number of values to write */ /* DAC section */ SANE_Byte DACType; /**< what DAC do we have */ RegDef *DACRegs; /**< pointer to DAC reg descr. */ u_short numDACRegs; /**< number of values to write */ pFnDACDark fnDACDark; /**< */ RGBByteDef RegDACOffset; RGBByteDef RegDACGain; ShadowRegs regs; /**< for holding ASIC register values */ DataInfo DataInf; /**< all static info about the current scan */ ScanInfo scan; /**< buffer and motor management during scan */ BufferDef bufs; void *scaleBuf; /**< buffer for line scaling */ int scaleStep; /**< step size for line scaling */ int scaleIzoom; /**< factor for line scaling */ u_long ModelOriginY; SANE_Byte ModelCtrl; SANE_Bool Tpa; /**< do we have a TPA */ SANE_Byte Buttons; /**< number of buttons */ /* lamp control section */ SANE_Bool warmupNeeded; SANE_Byte lastLampStatus; /**< for keeping the lamp status */ #ifdef HAVE_SETITIMER struct itimerval saveSettings; /**< for lamp timer */ #endif } U12_Device; typedef struct u12s { struct u12s *next; SANE_Pid reader_pid; /* process id of reader */ SANE_Status exit_code; /* status of the reader process */ int r_pipe; /* pipe to reader process */ int w_pipe; /* pipe from reader process */ unsigned long bytes_read; /* number of bytes currently read*/ U12_Device *hw; /* pointer to current device */ Option_Value val[NUM_OPTIONS]; SANE_Byte *buf; /* the image buffer */ SANE_Bool scanning; /* TRUE during scan-process */ SANE_Parameters params; /* for keeping the parameter */ SANE_Option_Descriptor opt[NUM_OPTIONS]; } U12_Scanner; /** for collecting configuration info... */ typedef struct { char devName[PATH_MAX]; char usbId[_MAX_ID_LEN]; /* contains the stuff to adjust... */ AdjDef adj; } CnfDef, *pCnfDef; #endif /* guard __U12_H__ */ /* END U12.H ................................................................*/ sane-backends-1.0.27/backend/hp3900_config.c0000664000175000017500000147764412112021330015235 00000000000000/* HP Scanjet 3900 series - RTS8822 internal config Copyright (C) 2005-2009 Jonathan Bravo Lopez This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* returns device model according to given product and vendor id's */ static SANE_Int cfg_device_get(SANE_Int product, SANE_Int vendor); /* returns information and capabilities about selected chipset model */ static SANE_Int cfg_chipset_get(SANE_Int model, struct st_chip *chipset); /* returns the chipset model for each scanner */ static SANE_Int cfg_chipset_model_get(SANE_Int device); /* buttons for each scanner */ static SANE_Int cfg_buttons_get(struct st_buttons *reg); /* area constrains for each scanner */ static SANE_Int cfg_constrains_get(struct st_constrains *constrain); /* spectrum clock generator for each scanner */ static SANE_Int cfg_sscg_get(SANE_Int *enable, SANE_Int *mode, SANE_Int *clock); /* motor general configuration for each scanner */ static SANE_Int cfg_motor_get(struct st_motorcfg *reg); /* motor resource for each scanner */ static SANE_Byte *cfg_motor_resource_get(SANE_Byte *size); /* sensor general configuration for each scanner */ static SANE_Int cfg_sensor_get(struct st_sensorcfg *reg); /* reference voltages for each scanner */ static void cfg_refvoltages_get(SANE_Int sensortype, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs); static void hp3800_refvoltages(SANE_Int usb, SANE_Int sensor, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs); static void hp3970_refvoltages(SANE_Int usb, SANE_Int sensor, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs); /* offset calibration start and length */ static void cfg_offset_get(SANE_Int sensortype, SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); static void ua4900_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); static void hp3800_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); static void hp3970_offset(SANE_Int sensor, SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); static void hp4370_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width); /* autoref configuration */ static void cfg_autoref_get(struct st_autoref *reg); /* autoref start effective pixel */ static SANE_Int cfg_effectivepixel_get(SANE_Int sensortype, SANE_Int resolution); static SANE_Int ua4900_effectivepixel(SANE_Int resolution); static SANE_Int hp3800_effectivepixel(SANE_Int resolution); static SANE_Int hp3970_effectivepixel(SANE_Int sensor, SANE_Int resolution); static SANE_Int hp4370_effectivepixel(SANE_Int resolution); /* default values for gain and offset */ static SANE_Int cfg_gainoffset_get(SANE_Int sensortype, struct st_gain_offset *reg); static SANE_Int bq5550_gainoffset(SANE_Int usb, struct st_gain_offset *myreg); static SANE_Int ua4900_gainoffset(SANE_Int usb, struct st_gain_offset *myreg); static SANE_Int hp3800_gainoffset(SANE_Int usb, struct st_gain_offset *myreg); static SANE_Int hp3970_gainoffset(SANE_Int usb, SANE_Int sensor, struct st_gain_offset *myreg); static SANE_Int hp4370_gainoffset(SANE_Int usb, struct st_gain_offset *myreg); /* values to detect optimum pulse-width modulation */ static SANE_Int cfg_checkstable_get(SANE_Int lamp, struct st_checkstable *check); static SANE_Int ua4900_checkstable(SANE_Int lamp, struct st_checkstable *check); static SANE_Int hp3800_checkstable(SANE_Int lamp, struct st_checkstable *check); static SANE_Int hp3970_checkstable(SANE_Int lamp, struct st_checkstable *check); static SANE_Int hp4370_checkstable(SANE_Int lamp, struct st_checkstable *check); /* fixed pulse-width modulation values */ static SANE_Int cfg_fixedpwm_get(SANE_Int sensortype, SANE_Int scantype); static SANE_Int ua4900_fixedpwm(SANE_Int scantype, SANE_Int usb); static SANE_Int hp3800_fixedpwm(SANE_Int scantype, SANE_Int usb); static SANE_Int hp3970_fixedpwm(SANE_Int scantype, SANE_Int usb, SANE_Int sensor); static SANE_Int hp4370_fixedpwm(SANE_Int scantype, SANE_Int usb); /* virtual origin (ser and ler references) */ static void cfg_vrefs_get(SANE_Int sensortype, SANE_Int res, SANE_Int *ser, SANE_Int *ler); static void hp3800_vrefs(SANE_Int res, SANE_Int *ser, SANE_Int *ler); static void hp3970_vrefs(SANE_Int usb, SANE_Int sensor, SANE_Int res, SANE_Int *ser, SANE_Int *ler); static void hp4370_vrefs(SANE_Int res, SANE_Int *ser, SANE_Int *ler); /* scanmodes supported by each scanner */ static SANE_Int cfg_scanmode_get(SANE_Int sensortype, SANE_Int sm, struct st_scanmode *mymode); static SANE_Int bq5550_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode); static SANE_Int ua4900_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode); static SANE_Int hp3800_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode); static SANE_Int hp3970_scanmodes(SANE_Int usb, SANE_Int ccd, SANE_Int sm, struct st_scanmode *mymode); static SANE_Int hp4370_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode); /* timing values for ccd sensors */ static SANE_Int cfg_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timing *reg); static SANE_Int bq5550_timing_get(SANE_Int tm, struct st_timing *reg); static SANE_Int ua4900_timing_get(SANE_Int tm, struct st_timing *reg); static SANE_Int hp3800_timing_get(SANE_Int tm, struct st_timing *reg); static SANE_Int hp3970_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timing *reg); static SANE_Int hp4370_timing_get(SANE_Int tm, struct st_timing *reg); /* motor movements */ static SANE_Int cfg_motormove_get(SANE_Int sensortype, SANE_Int mm, struct st_motormove *reg); static SANE_Int bq5550_motormove(SANE_Int item, struct st_motormove *reg); static SANE_Int hp3800_motormove(SANE_Int item, struct st_motormove *reg); static SANE_Int hp3970_motormove(SANE_Int usb, SANE_Int ccd, SANE_Int item, struct st_motormove *reg); /* motor curves */ static SANE_Int *cfg_motorcurve_get(void); static SANE_Int *bq5550_motor(void); static SANE_Int *hp3800_motor(void); static SANE_Int *hp3970_motor(void); static SANE_Int *hp4370_motor(void); /* shading cut values */ static void cfg_shading_cut_get(SANE_Int sensortype, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); static void ua4900_shading_cut(SANE_Int usb, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); static void hp3800_shading_cut(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); static void hp3970_shading_cut(SANE_Int usb, SANE_Int ccd, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); static void hp4370_shading_cut(SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); /* wrefs values */ static void cfg_wrefs_get(SANE_Int sensortype, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); static void ua4900_wrefs(SANE_Int usb, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); static void hp3800_wrefs(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); static void hp3970_wrefs(SANE_Int usb, SANE_Int ccd, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); static void hp4370_wrefs(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue); /* DEPRECATED FUNCTIONS !!!!!!!!!!!!!!!!!!! */ static int get_value(int section, int option, int defvalue, int file); /* HP Scanjet 3800 */ static int hp3800_calibreflective(int option, int defvalue); static int hp3800_calibtransparent(int option, int defvalue); static int hp3800_calibnegative(int option, int defvalue); static int srt_hp3800_scanparam_get(int option, int defvalue); /* UMAX Astra 4900 */ static int ua4900_calibreflective(int option, int defvalue); static int ua4900_calibtransparent(int option, int defvalue); static int ua4900_calibnegative(int option, int defvalue); /* HP Scanjet 3970 */ static int hp3970_calibreflective(int option, int defvalue); static int hp3970_calibtransparent(int option, int defvalue); static int hp3970_calibnegative(int option, int defvalue); static int srt_hp3970_scanparam_get(int file, int option, int defvalue); static int srt_hp3970_platform_get(int option, int defvalue); /* HP Scanjet 4370 */ static int hp4370_calibreflective(int option, int defvalue); static int hp4370_calibtransparent(int option, int defvalue); static int hp4370_calibnegative(int option, int defvalue); static int srt_hp4370_scanparam_get(int file, int option, int defvalue); /* HP Scanjet g3110 */ static int hpg3110_calibnegative(int option, int defvalue); static int hpg3110_calibtransparent(int option, int defvalue); /* ----- Implementation ----- */ /* DEPRECATED enumerations */ enum ConfigFiles { FITCALIBRATE=0, T_RTINIFILE, T_USB1INIFILE, S_RTINIFILE, S_USB1INIFILE }; enum fcsec6 { CALIBREFLECTIVE = 0, CALIBTRANSPARENT, CALIBNEGATIVEFILM, SCANINFO, SCAN_CALI, WSTRIPXPOS, WSTRIPYPOS, BSTRIPXPOS, BSTRIPYPOS, BREFR, BREFG, BREFB, REFBITDEPTH, OFFSETHEIGHT, OFFSETNSIGMA, OFFSETTARGETMAX, OFFSETTARGETMIN, OFFSETAVGTARGETR, OFFSETAVGTARGETG, OFFSETAVGTARGETB, ADCOFFEVENODD, CALIBOFFSET1ON, ADCOFFQUICKWAY, ADCOFFPREDICTSTART, ADCOFFPREDICTEND, OFFSETTUNESTEP1, OFFSETBOUNDARYRATIO1, OFFSETAVGRATIO1, OFFSETEVEN1R, OFFSETEVEN1G, OFFSETEVEN1B, OFFSETODD1R, OFFSETODD1G, OFFSETODD1B, ADCOFFPREDICTR, ADCOFFPREDICTG, ADCOFFPREDICTB, ADCOFFEVEN1R_1ST, ADCOFFEVEN1G_1ST, ADCOFFEVEN1B_1ST, ADCOFFODD1R_1ST, ADCOFFODD1G_1ST, ADCOFFODD1B_1ST, PEAKR, PEAKG, PEAKB, MINR, MING, MINB, CALIBOFFSET2ON, OFFSETTUNESTEP2, OFFSETBOUNDARYRATIO2, OFFSETAVGRATIO2, OFFSETEVEN2R, OFFSETEVEN2G, OFFSETEVEN2B, OFFSETODD2R, OFFSETODD2G, OFFSETODD2B, GAINHEIGHT, GAINTARGETFACTOR, CALIBPAGON, HIPAGR, HIPAGG, HIPAGB, LOPAGR, LOPAGG, LOPAGB, PAGR, PAGG, PAGB, CALIBGAIN1ON, GAIN1R, GAIN1G, GAIN1B, CALIBGAIN2ON, GAIN2R, GAIN2G, GAIN2B, TOTSHADING, BSHADINGON, BSHADINGHEIGHT, BSHADINGPREDIFFR, BSHADINGPREDIFFG, BSHADINGPREDIFFB, BSHADINGDEFCUTOFF, WSHADINGON, WSHADINGHEIGHT, WSHADINGPREDIFFR, WSHADINGPREDIFFG, WSHADINGPREDIFFB, PARKHOMEAFTERCALIB, SHADINGTIME_16BIT, SHADOWTIME_16BIT, SHADINGTIME_8BIT, SHADOWTIME_8BIT, PREVIEWDPI, FIRSTDCOFFSETEVEN0, FIRSTDCOFFSETODD0, FIRSTDCOFFSETEVEN1, FIRSTDCOFFSETODD1, FIRSTDCOFFSETEVEN2, FIRSTDCOFFSETODD2, CALIBOFFSET10N, CALIBOFFSET20N, CALIBGAIN10N, CALIBGAIN20N, ARRANGELINE, COMPRESSION, TA_X_START, TA_Y_START, DPIGAINCONTROL600, DPIGAINCONTROL_TA600, DPIGAINCONTROL_NEG600, CRVS, MLOCK, ENABLEWARMUP, NMAXTARGET, NMINTARGET, NMAXTARGETTA, NMINTARGETTA, NMAXTARGETNEG, NMINTARGETNEG, STABLEDIFF, DELTAPWM, PWMLAMPLEVEL, TMAPWMDUTY, PAG1, PAG2, PAG3, LEFTLEADING, WAVE_XSTART, WAVE_S575_XDUMMY_2400, WAVE_S575_XDUMMY_1200, WAVE_S575_XDUMMY_600, ODD_DCOFFSET11, ODD_DCOFFSET12, ODD_DCOFFSET13, ODD_DCOFFSET21, ODD_DCOFFSET22, ODD_DCOFFSET23, EVEN_DCOFFSET11, EVEN_DCOFFSET12, EVEN_DCOFFSET13, EVEN_DCOFFSET21, EVEN_DCOFFSET22, EVEN_DCOFFSET23, DCGAIN11, DCGAIN12, DCGAIN13, DCGAIN21, DCGAIN22, DCGAIN23, CRYSTALFREQ, PGA1, PGA2, PGA3, VGAGAIN11, VGAGAIN12, VGAGAIN13, DCSTEPEVEN1, DCSTEPODD1, DCSTEPEVEN2, DCSTEPODD2, DCSTEPEVEN3, DCSTEPODD3, FIRSTDCOFFSETEVEN11, FIRSTDCOFFSETODD11, FIRSTDCOFFSETEVEN12, FIRSTDCOFFSETODD12, FIRSTDCOFFSETEVEN13, FIRSTDCOFFSETODD13, DCOFFSETEVEN11, DCOFFSETODD11, DCOFFSETEVEN12, DCOFFSETODD12, DCOFFSETEVEN13, DCOFFSETODD13, SHADINGBASE, SHADINGFACT1, SHADINGFACT2, SHADINGFACT3, PIXELDARKLEVEL, EXPOSURETIME, SCANYSTART, SCANYLINES, BINARYTHRESHOLDH, BINARYTHRESHOLDL, CLOSETIME, PLATFORM, SCAN_PARAM, USB1_PWM, USB2_PWM, WAVETEST, DMA_PARAM, TRUE_GRAY_PARAM, CALI_PARAM, DUMMYLINE, MEXPT1, MEXPT2, MEXPT3, EXPT1, EXPT2, EXPT3, STARTPOS, LINEDARLAMPOFF, MCLKIOC }; static SANE_Int cfg_device_get(SANE_Int product, SANE_Int vendor) { struct st_myreg { SANE_Int vendor, product, device; }; struct st_myreg myreg[] = { /*vendor, prodct, device */ { 0x4a5, 0x2211, BQ5550 }, /* BenQ 5550 */ { 0x6dc, 0x0020, UA4900 }, /* UMAX Astra 4900 */ { 0x3f0, 0x2605, HP3800 }, /* HP Scanjet 3800 */ { 0x3f0, 0x2805, HPG2710}, /* HP Scanjet G2710 */ { 0x3f0, 0x2305, HP3970 }, /* HP Scanjet 3970c */ { 0x3f0, 0x2405, HP4070 }, /* HP Scanjet 4070 Photosmart */ { 0x3f0, 0x4105, HP4370 }, /* HP Scanjet 4370 */ { 0x3f0, 0x4205, HPG3010}, /* HP Scanjet G3010 */ { 0x3f0, 0x4305, HPG3110} /* HP Scanjet G3010 */ }; SANE_Int rst = -1; /* default */ SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_myreg); for (a = 0; a < count; a++) { if ((vendor == myreg[a].vendor)&&(product == myreg[a].product)) { rst = myreg[a].device; break; } } return rst; } static SANE_Int cfg_chipset_model_get(SANE_Int device) { /* returns the chipset model for each scanner */ struct st_myreg { SANE_Int device, chipset; }; struct st_myreg myreg[] = { /*device , chipset */ { HP3800 , RTS8822BL_03A }, { HPG2710, RTS8822BL_03A }, { BQ5550 , RTS8823L_01E }, { UA4900 , RTS8822L_01H }, { HP3970 , RTS8822L_01H }, { HP4070 , RTS8822L_01H }, { HP4370 , RTS8822L_02A }, { HPG3010, RTS8822L_02A }, { HPG3110, RTS8822L_02A } }; SANE_Int rst = RTS8822L_01H; /* default */ SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_myreg); for (a = 0; a < count; a++) { if (device == myreg[a].device) { rst = myreg[a].chipset; break; } } return rst; } static SANE_Int cfg_chipset_get(SANE_Int model, struct st_chip *chipset) { /* returns info and capabilities of selected chipset */ SANE_Int rst = ERROR; if (chipset != NULL) { struct st_chip data[] = { /* model , capabilities, name */ {RTS8823L_01E , 0 , "RTS8823L-01E" }, {RTS8822BL_03A, CAP_EEPROM , "RTS8822BL-03A"}, {RTS8822L_02A , CAP_EEPROM , "RTS8822L-02A" }, {RTS8822L_01H , CAP_EEPROM , "RTS8822L-01H" } }; SANE_Int a; for (a = 0; a < 4; a++) { if (model == data[a].model) { /* model found, fill information */ chipset->model = data[a].model; chipset->capabilities = data[a].capabilities; chipset->name = strdup(data[a].name); if (chipset->name != NULL) rst = OK; break; } } } return rst; } /** SEC: Device's Buttons ---------- */ static SANE_Int cfg_buttons_get(struct st_buttons *reg) { /* buttons for each scanner */ SANE_Int rst = ERROR; if (reg != NULL) { struct st_myreg { SANE_Int device; struct st_buttons value; }; struct st_myreg myreg[] = { /*device, {count, {btn1, btn2, btn3, btn4, btn5, btn6)} */ { BQ5550 , {3 , {0x01, 0x02, 0x08, -1, -1, -1}}}, { UA4900 , {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, { HP3800 , {3 , {0x01, 0x02, 0x04, -1, -1, -1}}}, { HPG2710, {3 , {0x01, 0x02, 0x04, -1, -1, -1}}}, { HP3970 , {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, { HP4070 , {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, { HP4370 , {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, { HPG3010, {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}}, { HPG3110, {4 , {0x04, 0x08, 0x02, 0x01, -1, -1}}} }; SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_myreg); for (a = 0; a < count; a++) { if (RTS_Debug->dev_model == myreg[a].device) { memcpy(reg, &myreg[a].value, sizeof(struct st_buttons)); rst = OK; break; } } } return rst; } /** SEC: Spectrum clock generator ---------- */ static SANE_Int cfg_sscg_get(SANE_Int *enable, SANE_Int *mode, SANE_Int *clock) { SANE_Int rst = ERROR; if ((enable != NULL)&&(mode != NULL)&&(clock != NULL)) { struct st_myreg { SANE_Int device; SANE_Int value[3]; }; struct st_myreg myreg[] = { /*device, {enable, mode, clock} */ { BQ5550, {1 , 1, 1}}, { UA4900, {1 , 1, 0}}, { HP3800, {1 , 1, 0}}, {HPG2710, {1 , 1, 0}}, { HP3970, {1 , 1, 0}}, { HP4070, {1 , 1, 0}}, { HP4370, {1 , 1, 0}}, {HPG3010, {1 , 1, 0}}, {HPG3110, {1 , 1, 0}} }; SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_myreg); /* default values */ *enable = 0; *mode = 0; *clock = 3; for (a = 0; a < count; a++) { if (RTS_Debug->dev_model == myreg[a].device) { *enable = myreg[a].value[0]; *mode = myreg[a].value[1]; *clock = myreg[a].value[2]; rst = OK; break; } } } return rst; } /** SEC: Motors ---------- */ static SANE_Int cfg_motor_get(struct st_motorcfg *reg) { SANE_Int rst = ERROR; if (reg != NULL) { struct st_myreg { SANE_Int device; struct st_motorcfg motor; }; struct st_myreg myreg[] = { /*device, {type , res, freq, speed, basemove, highmove, parkmove, change}} */ { BQ5550, {MT_OUTPUTSTATE, 1200, 30, 800, 1, 0, 0, TRUE}}, { UA4900, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, { HP3800, {MT_OUTPUTSTATE, 1200, 30, 800, 1, 0, 0, TRUE}}, {HPG2710, {MT_OUTPUTSTATE, 1200, 30, 800, 1, 0, 0, TRUE}}, { HP3970, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, { HP4070, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, { HP4370, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, {HPG3010, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}}, {HPG3110, {MT_OUTPUTSTATE, 2400, 30, 800, 1, 0, 0, TRUE}} }; SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_myreg); /* default values */ memset(reg, 0, sizeof(struct st_motorcfg)); reg->type = -1; for (a = 0; a < count; a++) { if (RTS_Debug->dev_model == myreg[a].device) { memcpy(reg, &myreg[a].motor, sizeof(struct st_motorcfg)); rst = OK; break; } } } return rst; } /** SEC: Sensors ---------- */ static SANE_Int cfg_sensor_get(struct st_sensorcfg *reg) { SANE_Int rst = ERROR; if (reg != NULL) { struct st_myreg { SANE_Int device; struct st_sensorcfg sensor; }; struct st_myreg myreg[] = { /*device, {type , name , resolution, {chnl_colors }, {chnl_gray }, {rgb_order }, line_dist, evenodd_dist} */ { BQ5550, {CCD_SENSOR, -1, 1200 , {CL_BLUE, CL_GREEN, CL_RED }, {CL_GREEN, 0}, {CL_BLUE, CL_GREEN, CL_RED }, 24 , 4 }}, { UA4900, {CIS_SENSOR, SNYS575, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 24 , 0 }}, { HP3800, {CCD_SENSOR, TCD2905, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 64 , 8 }}, {HPG2710, {CCD_SENSOR, TCD2905, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 64 , 8 }}, { HP3970, {CCD_SENSOR, TCD2952, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 24 , 4 }}, { HP4070, {CCD_SENSOR, TCD2952, 2400 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 24 , 4 }}, { HP4370, {CCD_SENSOR, TCD2958, 4800 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 128 , 6 }}, {HPG3010, {CCD_SENSOR, TCD2958, 4800 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 128 , 6 }}, {HPG3110, {CCD_SENSOR, TCD2958, 4800 , {CL_RED , CL_GREEN, CL_BLUE}, {CL_RED , 0}, {CL_RED , CL_GREEN, CL_BLUE}, 128 , 6 }} }; SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_myreg); /* default values */ memset(reg, 0, sizeof(struct st_sensorcfg)); reg->type = -1; for (a = 0; a < count; a++) { if (RTS_Debug->dev_model == myreg[a].device) { memcpy(reg, &myreg[a].sensor, sizeof(struct st_sensorcfg)); rst = OK; break; } } } return rst; } /** SEC: Reference voltages ---------- */ static void hp3800_refvoltages(SANE_Int usb, SANE_Int sensor, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs) { /* this function returns top, middle and bottom reference voltages for each scanner */ struct st_reg { SANE_Int usb; SANE_Int sensor; SANE_Byte values[3]; }; struct st_reg myreg[] = { /* usb, sensor , {vrts, vrms, vrbs} */ {USB20, CCD_SENSOR, { 2, 3, 2}}, {USB11, CCD_SENSOR, { 2, 3, 2}}, }; if ((vrts != NULL)&&(vrms != NULL)&&(vrbs != NULL)) { SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_reg); *vrts = *vrms = *vrbs = 0; for (a = 0; a < count; a++) { if ((myreg[a].usb == usb)&&(myreg[a].sensor == sensor)) { *vrts = myreg[a].values[0]; *vrms = myreg[a].values[1]; *vrbs = myreg[a].values[2]; } } } } static void hp3970_refvoltages(SANE_Int usb, SANE_Int sensor, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs) { /* this function returns top, middle and bottom reference voltages for each scanner */ struct st_reg { SANE_Int usb; SANE_Int sensor; SANE_Byte values[3]; }; struct st_reg myreg[] = { /* usb, sensor , {vrts, vrms, vrbs} */ {USB20, CCD_SENSOR, { 0, 0, 0}}, {USB11, CCD_SENSOR, { 0, 0, 0}}, {USB20, CIS_SENSOR, { 0, 0, 0}}, {USB11, CIS_SENSOR, { 0, 0, 0}} }; if ((vrts != NULL)&&(vrms != NULL)&&(vrbs != NULL)) { SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_reg); *vrts = *vrms = *vrbs = 0; for (a = 0; a < count; a++) { if ((myreg[a].usb == usb)&&(myreg[a].sensor == sensor)) { *vrts = myreg[a].values[0]; *vrms = myreg[a].values[1]; *vrbs = myreg[a].values[2]; } } } } static void cfg_refvoltages_get(SANE_Int sensortype, SANE_Byte *vrts, SANE_Byte *vrms, SANE_Byte *vrbs) { /* this function returns top, middle and bottom reference voltages for each scanner */ switch(RTS_Debug->dev_model) { case HP3800: case HPG2710: hp3800_refvoltages(RTS_Debug->usbtype, sensortype, vrts, vrms, vrbs); break; default: /* at this momment all analyzed scanners have the same values */ hp3970_refvoltages(RTS_Debug->usbtype, sensortype, vrts, vrms, vrbs); break; } } /** SEC: Calibration Offset ---------- */ static void hp3800_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) { /* this function provides left coordinate and width to calculate offset Sensor = Toshiba T2905 */ struct st_ofst { SANE_Int left; SANE_Int width; }; struct st_reg { SANE_Int resolution; struct st_ofst values[3]; }; struct st_reg myreg[] = { /*res , {ref(L,W), tma(L,W), neg(L,W)} */ { 2400, {{15, 20}, {15, 20}, {15, 20}}}, { 1200, {{10, 10}, {10, 10}, {10, 10}}}, { 600, {{ 2, 10}, { 5, 10}, { 5, 10}}}, { 300, {{ 1, 5}, { 1, 5}, { 1, 5}}}, { 150, {{ 0, 3}, { 0, 3}, { 0, 3}}} }; if ((left != NULL)&&(width != NULL)) { SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (myreg[a].resolution == resolution) { scantype--; *left = myreg[a].values[scantype].left; *width = myreg[a].values[scantype].width; break; } } } } static void hp3970_offset(SANE_Int sensor, SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) { /* this function provides left coordinate and width to calculate offset */ struct st_ofst { SANE_Int left; SANE_Int width; }; struct st_reg { SANE_Int sensor; SANE_Int resolution; struct st_ofst values[3]; }; struct st_reg myreg[] = { /* sensor , res , {ref(L,W), tma(L,W), neg(L,W)} */ {CCD_SENSOR, 2400, {{16, 20}, {16, 20}, {16, 20}}}, {CCD_SENSOR, 1200, {{16, 10}, {16, 10}, {16, 10}}}, {CCD_SENSOR, 600, {{15, 10}, {15, 10}, {15, 10}}}, {CCD_SENSOR, 300, {{ 7, 5}, { 7, 5}, { 7, 5}}}, {CCD_SENSOR, 200, {{ 7, 3}, { 7, 3}, { 7, 3}}}, {CCD_SENSOR, 100, {{ 3, 3}, { 3, 3}, { 3, 3}}}, /* sensor , res , {ref(L,W), tma(L,W), neg(L,W)} */ {CIS_SENSOR, 2400, {{84, 20}, {84, 20}, {84, 20}}}, {CIS_SENSOR, 1200, {{54, 10}, {54, 10}, {54, 10}}}, {CIS_SENSOR, 600, {{28, 10}, {28, 10}, {28, 10}}}, {CIS_SENSOR, 300, {{15, 5}, {15, 5}, {15, 5}}}, {CIS_SENSOR, 200, {{ 5, 3}, { 5, 3}, { 5, 3}}}, {CIS_SENSOR, 100, {{ 2, 3}, { 2, 3}, { 2, 3}}} }; if ((left != NULL)&&(width != NULL)) { SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if ((myreg[a].sensor == sensor)&&(myreg[a].resolution == resolution)) { scantype--; *left = myreg[a].values[scantype].left; *width = myreg[a].values[scantype].width; break; } } } } static void hp4370_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) { /* this function provides left coordinate and width to calculate offset */ struct st_ofst { SANE_Int left; SANE_Int width; }; struct st_reg { SANE_Int resolution; struct st_ofst values[3]; }; struct st_reg myreg[] = { /* res, {ref(L,W), tma(L,W), neg(L,W)} */ { 4800, {{42, 20}, {42, 20}, {52, 26}}}, { 2400, {{14, 20}, {14, 20}, {14, 26}}}, { 1200, {{ 8, 14}, { 8, 14}, { 8, 14}}}, { 600, {{ 4, 8}, { 4, 8}, { 4, 8}}}, { 300, {{ 2, 4}, { 2, 4}, { 2, 4}}}, { 150, {{ 1, 2}, { 1, 2}, { 1, 2}}} }; if ((left != NULL)&&(width != NULL)) { SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (myreg[a].resolution == resolution) { scantype--; *left = myreg[a].values[scantype].left; *width = myreg[a].values[scantype].width; break; } } } } static void ua4900_offset(SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) { /* this function provides left coordinate and width to calculate offset */ struct st_ofst { SANE_Int left; SANE_Int width; }; struct st_reg { SANE_Int resolution; struct st_ofst values[3]; }; struct st_reg myreg[] = { /* res , {ref(L,W), tma(L,W), neg(L,W)} */ { 2400, {{20, 20}, {16, 20}, {16, 20}}}, { 1200, {{20, 10}, {10, 10}, {10, 10}}}, { 600, {{ 7, 10}, {15, 10}, {15, 10}}}, { 300, {{ 5, 10}, { 7, 8}, { 7, 8}}}, { 200, {{ 2, 10}, { 7, 6}, { 7, 6}}}, { 100, {{ 0, 10}, { 3, 4}, { 3, 4}}} }; if ((left != NULL)&&(width != NULL)) { SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (myreg[a].resolution == resolution) { scantype--; *left = myreg[a].values[scantype].left; *width = myreg[a].values[scantype].width; break; } } } } static void cfg_offset_get(SANE_Int sensortype, SANE_Int resolution, SANE_Int scantype, SANE_Int *left, SANE_Int *width) { switch(RTS_Debug->dev_model) { case UA4900: ua4900_offset(resolution, scantype, left, width); break; case HP3800: case HPG2710: hp3800_offset(resolution, scantype, left, width); break; case HPG3010: case HPG3110: case HP4370: hp4370_offset(resolution, scantype, left, width); break; default: hp3970_offset(sensortype, resolution, scantype, left, width); break; } } /** SEC: Device constrains ---------- */ static SANE_Int cfg_constrains_get(struct st_constrains *constrain) { SANE_Int rst = ERROR; struct st_reg { SANE_Int device; struct st_constrains constrain; }; struct st_reg reg[] = { /* constrains are set in milimeters */ /*device , reflective , negative , transparent */ /* , {{left, width, top, height}, {left, width, top, height}, {left, width, top, height}}}, */ { BQ5550 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}}, { HP3800 , {{ 0, 220, 0, 300}, { 89, 45, 0, 85}, { 89, 45, 0, 100}}}, {HPG2710 , {{ 0, 220, 0, 300}, { 89, 45, 0, 85}, { 89, 45, 0, 100}}}, { HP3970 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}}, { HP4070 , {{ 0, 220, 0, 300}, { 58, 99, 0, 197}, { 58, 99, 0, 197}}}, { HP4370 , {{ 0, 220, 0, 300}, { 90, 45, 0, 85}, { 90, 45, 0, 100}}}, { UA4900 , {{ 0, 220, 0, 300}, { 88, 42, 0, 83}, { 88, 42, 0, 83}}}, {HPG3010 , {{ 0, 220, 0, 300}, { 90, 45, 0, 85}, { 89, 45, 0, 100}}}, {HPG3110 , {{ 0, 220, 0, 300}, { 92, 28, 0, 190}, { 85, 44, 0, 190}}} }; if (constrain != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].device == RTS_Debug->dev_model) { memcpy(constrain, ®[a].constrain, sizeof(struct st_constrains)); rst = OK; break; } } } return rst; } /** SEC: Motor resource ------------------- */ static SANE_Byte *cfg_motor_resource_get(SANE_Byte *size) { /* this function returns the proper motor resources for a given device */ SANE_Byte *rst = NULL; /* Until now, resource size is always 32 bytes */ rst = (SANE_Byte *)malloc(sizeof(SANE_Byte) * 32); if (size != NULL) *size = 0; if (rst != NULL) { bzero(rst, sizeof(SANE_Byte) * 32); switch(RTS_Debug->dev_model) { case BQ5550: { SANE_Byte Resource[] = {0xff, 0xb4, 0xb0, 0xd4, 0xd0, 0x70, 0x50, 0x54, 0x30, 0x34, 0x14, 0x38, 0x18, 0x0c, 0x08, 0x28, 0x04, 0x24, 0x20, 0x44, 0x40, 0xe0, 0xc0, 0xc4, 0xa0, 0xa4, 0x84, 0xa8, 0x88, 0x9c, 0x98, 0xb8}; memcpy(rst, &Resource, sizeof(SANE_Byte) * 32); if (size != NULL) *size = 32; } break; default: { SANE_Byte Resource[] = {0xff, 0x90, 0xb0, 0xd4, 0xd0, 0x70, 0x50, 0x54, 0x30, 0x10, 0x14, 0x38, 0x18, 0x0c, 0x08, 0x28, 0x04, 0x00, 0x20, 0x44, 0x40, 0xe0, 0xc0, 0xc4, 0xa0, 0x80, 0x84, 0xa8, 0x88, 0x9c, 0x98, 0xb8}; memcpy(rst, &Resource, sizeof(SANE_Byte) * 32); if (size != NULL) *size = 32; } break; } } return rst; } /** SEC: Auto reference position ---------- */ static void cfg_autoref_get(struct st_autoref *reg) { if (reg != NULL) { struct st_reg { SANE_Int device; struct st_autoref value; }; struct st_reg myreg[] = { /* x and y offsets are based on 2400 dpi */ /* device, { type , x , y , resolution, extern_boundary}*/ { BQ5550 , {REF_NONE , -40, -40, 600 , 40}}, { UA4900 , {REF_NONE , -40, -40, 600 , 40}}, { HP3800 , {REF_TAKEFROMSCANNER, 88, 624, 600 , 40}}, {HPG2710 , {REF_TAKEFROMSCANNER, 88, 624, 600 , 40}}, { HP3970 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}}, { HP4070 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}}, { HP4370 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}}, {HPG3010 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}}, {HPG3110 , {REF_TAKEFROMSCANNER, 88, 717, 600 , 40}} }; SANE_Int a; SANE_Int count = sizeof(myreg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (myreg[a].device == RTS_Debug->dev_model) { memcpy(reg, &myreg[a].value, sizeof(struct st_autoref)); break; } } } } static SANE_Int hp3800_effectivepixel(SANE_Int resolution) { struct st_reg { SANE_Int resolution; SANE_Int pixel; }; struct st_reg reg[] = { /* res , pixel */ { 2400, 134 }, { 1200, 134 }, { 600, 230 }, { 300, 172 }, { 200, 230 }, { 100, 230 } }; SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); SANE_Int rst = 230; /* default */ for (a = 0; a < count; a++) { if (reg[a].resolution == resolution) { rst = reg[a].pixel; break; } } return rst; } static SANE_Int hp3970_effectivepixel(SANE_Int sensor, SANE_Int resolution) { struct st_reg { SANE_Int resolution; SANE_Int pixel[2]; }; struct st_reg reg[] = { /* res , {Toshiba, sony}} */ { 2400, {134 , 218 }}, { 1200, {134 , 240 }}, { 600, {230 , 242 }}, { 300, {160 , 172 }}, { 200, {230 , 242 }}, { 100, {230 , 242 }} }; SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); SANE_Int rst = 230; /* default */ for (a = 0; a < count; a++) { if (reg[a].resolution == resolution) { rst = (sensor == CCD_SENSOR)? reg[a].pixel[0] : reg[a].pixel[1]; break; } } return rst; } static SANE_Int hp4370_effectivepixel(SANE_Int resolution) { struct st_reg { SANE_Int resolution; SANE_Int pixel; }; struct st_reg reg[] = { /* res , pxl */ { 4800, 134}, { 2400, 134}, { 1200, 134}, { 600, 230}, { 300, 230}, { 150, 230} }; SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); SANE_Int rst = 230; /* default */ for (a = 0; a < count; a++) { if (reg[a].resolution == resolution) { rst = reg[a].pixel; break; } } return rst; } static SANE_Int ua4900_effectivepixel(SANE_Int resolution) { struct st_reg { SANE_Int resolution; SANE_Int pixel; }; struct st_reg reg[] = { /* res , pixel */ { 2400, 134 }, { 1200, 134 }, { 600, 230 }, { 300, 172 }, { 200, 230 }, { 100, 230 } }; SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); SANE_Int rst = 230; /* default */ for (a = 0; a < count; a++) { if (reg[a].resolution == resolution) { rst = reg[a].pixel; break; } } return rst; } static SANE_Int cfg_effectivepixel_get(SANE_Int sensortype, SANE_Int resolution) { SANE_Int rst; switch(RTS_Debug->dev_model) { case UA4900: rst = ua4900_effectivepixel(resolution); break; case HP3800: case HPG2710: rst = hp3800_effectivepixel(resolution); break; case HP4370: case HPG3010: case HPG3110: rst = hp4370_effectivepixel(resolution); break; default: rst = hp3970_effectivepixel(sensortype, resolution); break; } return rst; } /** SEC: Gain and offset values ---------- */ static SANE_Int bq5550_gainoffset(SANE_Int usb, struct st_gain_offset *myreg) { struct st_reg { SANE_Int usb; struct st_gain_offset values; }; struct st_reg reg[] = { /* usb , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }}} */ { USB20, {{264, 264, 264}, {0, 0, 0}, {262, 262, 262}, {0, 0, 0}, {3, 3, 3}, {27, 27, 27}, {4, 4, 4}}}, { USB11, {{264, 264, 264}, {0, 0, 0}, {262, 262, 262}, {0, 0, 0}, {3, 3, 3}, {27, 27, 27}, {4, 4, 4}}} }; SANE_Int rst = ERROR; if (myreg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].usb == usb) { memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); rst = OK; break; } } } return rst; } static SANE_Int hp3800_gainoffset(SANE_Int usb, struct st_gain_offset *myreg) { struct st_reg { SANE_Int usb; struct st_gain_offset values; }; struct st_reg reg[] = { /* usb , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }}} */ { USB20, {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {2, 2, 2}, {4, 4, 4}, {4, 4, 4}}}, { USB11, {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {2, 2, 2}, {4, 4, 4}, {4, 4, 4}}} }; SANE_Int rst = ERROR; if (myreg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].usb == usb) { memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); rst = OK; break; } } } return rst; } static SANE_Int hp3970_gainoffset(SANE_Int usb, SANE_Int sensor, struct st_gain_offset *myreg) { struct st_reg { SANE_Int usb; SANE_Int sensor; struct st_gain_offset values; }; struct st_reg reg[] = { /* usb , sensor , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }}} */ { USB20, CCD_SENSOR, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}}, { USB11, CCD_SENSOR, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}}, { USB20, CIS_SENSOR, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}}, { USB11, CIS_SENSOR, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}} }; SANE_Int rst = ERROR; if (myreg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; count < 4; a++) { if ((reg[a].usb == usb)&&(reg[a].sensor == sensor)) { memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); rst = OK; break; } } } return rst; } static SANE_Int hp4370_gainoffset(SANE_Int usb, struct st_gain_offset *myreg) { struct st_reg { SANE_Int usb; struct st_gain_offset values; }; struct st_reg reg[] = { /* usb , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }} */ { USB20, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}}, { USB11, {{280, 266, 286}, {0, 0, 0}, {280, 266, 286}, {0, 0, 0}, {3, 3, 3}, {7, 4, 4}, {7, 4, 4}}} }; SANE_Int rst = ERROR; if (myreg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].usb == usb) { memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); rst = OK; break; } } } return rst; } static SANE_Int ua4900_gainoffset(SANE_Int usb, struct st_gain_offset *myreg) { struct st_reg { SANE_Int usb; struct st_gain_offset values; }; struct st_reg reg[] = { /* usb , {{edcg1 }, {edcg2 }, {odcg1 }, {odcg2 }, {pag }, {vgag1 }, {vgag2 }}} */ { USB20, {{321, 321, 321}, {0, 0, 0}, {321, 321, 321}, {0, 0, 0}, {0, 0, 0}, {24, 21, 19}, {8, 8, 8}}}, { USB11, {{321, 321, 321}, {0, 0, 0}, {321, 321, 321}, {0, 0, 0}, {0, 0, 0}, {16, 16, 16}, {4, 4, 4}}} }; SANE_Int rst = ERROR; if (myreg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].usb == usb) { memcpy(myreg, ®[a].values, sizeof(struct st_gain_offset)); rst = OK; break; } } } return rst; } static SANE_Int cfg_gainoffset_get(SANE_Int sensortype, struct st_gain_offset *reg) { SANE_Int rst; switch(RTS_Debug->dev_model) { case BQ5550: rst = bq5550_gainoffset(RTS_Debug->usbtype, reg); break; case UA4900: rst = ua4900_gainoffset(RTS_Debug->usbtype, reg); break; case HP3800: case HPG2710: rst = hp3800_gainoffset(RTS_Debug->usbtype, reg); break; case HP4370: case HPG3010: case HPG3110: rst = hp4370_gainoffset(RTS_Debug->usbtype, reg); break; default: rst = hp3970_gainoffset(RTS_Debug->usbtype, sensortype, reg); break; } return rst; } /** SEC: Pulse-width modulation check stable ---------- */ static SANE_Int hp3800_checkstable(SANE_Int lamp, struct st_checkstable *check) { struct st_reg { SANE_Int lamp; struct st_checkstable values; }; struct st_reg reg[] = { /* lamp , { diff, interval, tottime } */ { 0 , { 100., 200, 10000}}, { FLB_LAMP, { 100., 200, 10000}}, { TMA_LAMP, { 100., 200, 10000}} }; SANE_Int rst = ERROR; if (reg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].lamp == lamp) { memcpy(check, ®[a].values, sizeof(struct st_checkstable)); rst = OK; break; } } } return rst; } static SANE_Int hp3970_checkstable(SANE_Int lamp, struct st_checkstable *check) { struct st_reg { SANE_Int lamp; struct st_checkstable values; }; struct st_reg reg[] = { /* lamp , { diff, interval, tottime } */ { 0 , {1000., 200, 5000}}, { FLB_LAMP, { 500., 200, 5000}}, { TMA_LAMP, { 500., 200, 5000}} }; SANE_Int rst = ERROR; if (reg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].lamp == lamp) { memcpy(check, ®[a].values, sizeof(struct st_checkstable)); rst = OK; break; } } } return rst; } static SANE_Int hp4370_checkstable(SANE_Int lamp, struct st_checkstable *check) { struct st_reg { SANE_Int lamp; struct st_checkstable values; }; struct st_reg reg[] = { /* lamp , { diff, interval, tottime } */ { 0 , { 100., 200, 5000}}, { FLB_LAMP, { 300., 200, 5000}}, { TMA_LAMP, { 0., 200, 25000}} }; SANE_Int rst = ERROR; if (reg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].lamp == lamp) { memcpy(check, ®[a].values, sizeof(struct st_checkstable)); rst = OK; break; } } } return rst; } static SANE_Int ua4900_checkstable(SANE_Int lamp, struct st_checkstable *check) { struct st_reg { SANE_Int lamp; struct st_checkstable values; }; struct st_reg reg[] = { /* lamp , { diff, interval, tottime } */ { 0 , { 100., 200, 5000}}, { FLB_LAMP, { 10., 200, 5000}}, { TMA_LAMP, { 10., 200, 25000}} }; SANE_Int rst = ERROR; if (reg != NULL) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].lamp == lamp) { memcpy(check, ®[a].values, sizeof(struct st_checkstable)); rst = OK; break; } } } return rst; } static SANE_Int cfg_checkstable_get(SANE_Int lamp, struct st_checkstable *check) { SANE_Int rst; switch(RTS_Debug->dev_model) { case UA4900: rst = ua4900_checkstable(lamp, check); break; case HP3800: case HPG2710: rst = hp3800_checkstable(lamp, check); break; case HP4370: case HPG3010: case HPG3110: rst = hp4370_checkstable(lamp, check); break; default: rst = hp3970_checkstable(lamp, check); break; } return rst; } /** SEC: Fixed pulse-width modulation values ---------- */ static SANE_Int hp3800_fixedpwm(SANE_Int scantype, SANE_Int usb) { struct st_reg { SANE_Int usb; SANE_Int pwm[3]; }; struct st_reg reg[] = { /* usb , { ST_NORMAL, ST_TA, ST_NEG} */ { USB20, { 0, 0, 0}}, { USB11, { 0, 0, 0}} }; SANE_Int a, rst = 0x16; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].usb == usb) { if ((scantype < ST_NORMAL)||(scantype > ST_NEG)) scantype = ST_NORMAL; rst = reg[a].pwm[scantype - 1]; break; } } return rst; } static SANE_Int hp3970_fixedpwm(SANE_Int scantype, SANE_Int usb, SANE_Int sensor) { struct st_reg { SANE_Int usb; SANE_Int sensor; SANE_Int pwm[3]; }; struct st_reg reg[] = { /* usb , sensor , { ST_NORMAL, ST_TA, ST_NEG} */ { USB20, CCD_SENSOR, { 22, 22, 22}}, { USB11, CCD_SENSOR, { 22, 22, 22}}, { USB20, CIS_SENSOR, { 22, 22, 22}}, { USB11, CIS_SENSOR, { 22, 22, 22}} }; SANE_Int a, rst = 0x16; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if ((reg[a].usb == usb)&&(reg[a].sensor == sensor)) { if ((scantype < ST_NORMAL)||(scantype > ST_NEG)) scantype = ST_NORMAL; rst = reg[a].pwm[scantype - 1]; break; } } return rst; } static SANE_Int hp4370_fixedpwm(SANE_Int scantype, SANE_Int usb) { struct st_reg { SANE_Int usb; SANE_Int pwm[3]; }; struct st_reg reg[] = { /* usb , { ST_NORMAL, ST_TA, ST_NEG} */ { USB20, { 20, 28, 28}}, { USB11, { 20, 28, 28}} }; SANE_Int a, rst = 0x16; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].usb == usb) { if ((scantype < ST_NORMAL)||(scantype > ST_NEG)) scantype = ST_NORMAL; rst = reg[a].pwm[scantype - 1]; break; } } return rst; } static SANE_Int ua4900_fixedpwm(SANE_Int scantype, SANE_Int usb) { struct st_reg { SANE_Int usb; SANE_Int pwm[3]; }; struct st_reg reg[] = { /* usb , { ST_NORMAL, ST_TA, ST_NEG} */ { USB20, { 20, 28, 28}}, { USB11, { 20, 28, 28}} }; SANE_Int a, rst = 0x16; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); for (a = 0; a < count; a++) { if (reg[a].usb == usb) { if ((scantype < ST_NORMAL)||(scantype > ST_NEG)) scantype = ST_NORMAL; rst = reg[a].pwm[scantype - 1]; break; } } return rst; } static SANE_Int cfg_fixedpwm_get(SANE_Int sensortype, SANE_Int scantype) { SANE_Int rst; switch(RTS_Debug->dev_model) { case UA4900: rst = ua4900_fixedpwm(scantype, RTS_Debug->usbtype); break; case HP3800: case HPG2710: rst = hp3800_fixedpwm(scantype, RTS_Debug->usbtype); break; case HP4370: case HPG3010: case HPG3110: rst = hp4370_fixedpwm(scantype, RTS_Debug->usbtype); break; default: rst = hp3970_fixedpwm(scantype, RTS_Debug->usbtype, sensortype); break; } return rst; } /** SEC: Fixed reference positions ---------- */ static void cfg_vrefs_get(SANE_Int sensortype, SANE_Int res, SANE_Int *ser, SANE_Int *ler) { switch(RTS_Debug->dev_model) { case HP3800: case HPG2710: hp3800_vrefs(res, ser, ler); break; case HP4370: case HPG3010: case HPG3110: hp4370_vrefs(res, ser, ler); break; default: hp3970_vrefs(RTS_Debug->usbtype, sensortype, res, ser, ler); break; } } static void hp3800_vrefs(SANE_Int res, SANE_Int *ser, SANE_Int *ler) { struct st_reg { SANE_Int resolution; SANE_Int vref[2]; }; struct st_reg reg[] = { /* res, { ser, ler} */ { 150, { 25, 50}}, { 300, { 50, 101}}, { 600, { 102, 202}}, { 1200, { 204, 404}}, { 2400, { 408, 808}} }; if ((ser != NULL)&&(ler != NULL)) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); /* values by default */ *ser = *ler = 0; for (a = 0; a < count; a++) { if (reg[a].resolution == res) { *ser = reg[a].vref[0]; *ler = reg[a].vref[1]; break; } } } } static void hp3970_vrefs(SANE_Int usb, SANE_Int sensor, SANE_Int res, SANE_Int *ser, SANE_Int *ler) { struct st_reg { SANE_Int usb; SANE_Int sensor; SANE_Int resolution; SANE_Int vref[2]; }; /* I think these references should be the same in all usb versions and in all sensor types but windows driver has some different values in some cases. */ struct st_reg reg[] = { /* usb , sensor , res, { ser, ler} */ { USB20, CCD_SENSOR, 100, { 28, 60}}, { USB20, CCD_SENSOR, 200, { 37, 117}}, { USB20, CCD_SENSOR, 300, { 52, 162}}, { USB20, CCD_SENSOR, 600, { 103, 344}}, { USB20, CCD_SENSOR, 1200, { 156, 660}}, { USB20, CCD_SENSOR, 2400, { 309, 1262}}, /* usb , sensor , res, { ser, ler} */ { USB11, CCD_SENSOR, 100, { 28, 60}}, { USB11, CCD_SENSOR, 200, { 37, 117}}, { USB11, CCD_SENSOR, 300, { 52, 162}}, { USB11, CCD_SENSOR, 600, { 103, 344}}, { USB11, CCD_SENSOR, 1200, { 156, 660}}, { USB11, CCD_SENSOR, 2400, { 309, 1262}}, /* usb , sensor , res, { ser, ler} */ { USB20, CIS_SENSOR, 100, { 15, 60}}, { USB20, CIS_SENSOR, 200, { 39, 117}}, { USB20, CIS_SENSOR, 300, { 56, 161}}, { USB20, CIS_SENSOR, 600, { 108, 342}}, { USB20, CIS_SENSOR, 1200, { 221, 642}}, { USB20, CIS_SENSOR, 2400, { 407, 1285}}, /* usb , sensor , res, { ser, ler} */ { USB11, CIS_SENSOR, 100, { 15, 60}}, { USB11, CIS_SENSOR, 200, { 39, 117}}, { USB11, CIS_SENSOR, 300, { 56, 161}}, { USB11, CIS_SENSOR, 600, { 108, 342}}, { USB11, CIS_SENSOR, 1200, { 221, 642}}, { USB11, CIS_SENSOR, 2400, { 407, 1285}} }; if ((ser != NULL)&&(ler != NULL)) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); /* values by default */ *ser = *ler = 0; for (a = 0; a < count; a++) { if ((reg[a].usb == usb)&&(reg[a].sensor == sensor)&&(reg[a].resolution == res)) { *ser = reg[a].vref[0]; *ler = reg[a].vref[1]; break; } } } } static void hp4370_vrefs(SANE_Int res, SANE_Int *ser, SANE_Int *ler) { struct st_reg { SANE_Int resolution; SANE_Int vref[2]; }; struct st_reg reg[] = { /* res, { ser, ler} */ { 150, { 31, 81}}, { 300, { 61, 162}}, { 600, { 122, 324}}, { 1200, { 244, 648}}, { 2400, { 488, 1256}}, { 4800, { 976, 2512}} }; if ((ser != NULL)&&(ler != NULL)) { SANE_Int a; SANE_Int count = sizeof(reg) / sizeof(struct st_reg); /* values by default */ *ser = *ler = 0; for (a = 0; a < count; a++) { if (reg[a].resolution == res) { *ser = reg[a].vref[0]; *ler = reg[a].vref[1]; break; } } } } /** SEC: Motor movements ---------- */ static SANE_Int cfg_motormove_get(SANE_Int sensortype, SANE_Int item, struct st_motormove *reg) { SANE_Int rst = ERROR; switch(RTS_Debug->dev_model) { case BQ5550: rst = bq5550_motormove(item, reg); break; case HP3800: case HPG2710: rst = hp3800_motormove(item, reg); break; default: rst = hp3970_motormove(RTS_Debug->usbtype, sensortype, item, reg); break; } return rst; } static SANE_Int bq5550_motormove(SANE_Int item, struct st_motormove *reg) { SANE_Int rst = ERROR; /* data is the same in all usb types and sensors so those args aren't needed */ if (reg != NULL) { struct st_motormove mv[] = { /* systemclock, ctpc, steptype , motorcurve } */ { 0x05 , 4059, STT_HALF , 0 }, { 0x02 , 1200, STT_QUART, -1 } }; rst = OK; if ((item < 2)&&(item > -1)) memcpy(reg, &mv[item], sizeof(struct st_motormove)); else rst = ERROR; } return rst; } static SANE_Int hp3800_motormove(SANE_Int item, struct st_motormove *reg) { SANE_Int rst = ERROR; /* data is the same in all usb types and sensors so those args aren't needed */ if (reg != NULL) { struct st_motormove mv[] = { /* systemclock, ctpc, steptype, motorcurve } */ { 0x04 , 1991, STT_HALF, 2 }, { 0x02 , 1991, STT_HALF, -1 } }; rst = OK; if ((item < 2)&&(item > -1)) memcpy(reg, &mv[item], sizeof(struct st_motormove)); else rst = ERROR; } return rst; } static SANE_Int hp3970_motormove(SANE_Int usb, SANE_Int ccd, SANE_Int item, struct st_motormove *reg) { SANE_Int rst = ERROR; struct st_mtmove { SANE_Int usbtype; SANE_Int sensor; struct st_motormove move; }; if (reg != NULL) { struct st_mtmove mv[] = { /* usb, sensor , {systemclock, ctpc, steptype, motorcurve } */ {USB20, CCD_SENSOR, {0x02 , 6431, STT_HALF, 1 }}, {USB20, CCD_SENSOR, {0x02 , 2000, STT_HALF, -1 }}, {USB20, CIS_SENSOR, {0x02 , 6431, STT_HALF, 1 }}, {USB20, CIS_SENSOR, {0x02 , 2000, STT_HALF, -1 }}, {USB11, CCD_SENSOR, {0x02 , 6431, STT_HALF, 1 }}, {USB11, CCD_SENSOR, {0x02 , 2000, STT_HALF, -1 }}, {USB11, CIS_SENSOR, {0x02 , 6431, STT_HALF, 1 }}, {USB11, CIS_SENSOR, {0x02 , 2000, STT_HALF, -1 }} }; if (item < 2) { SANE_Int a, count = 0; SANE_Int total = sizeof(mv) / sizeof(struct st_mtmove); for (a = 0; a < total; a++) { if ((mv[a].usbtype == usb)&&(mv[a].sensor == ccd)) { if (item == count) { memcpy(reg, &mv[a].move, sizeof(struct st_motormove)); rst = OK; break; } else count++; } } } } return rst; } /** SEC: Scanning modes ---------- */ static SANE_Int cfg_scanmode_get(SANE_Int sensortype, SANE_Int sm, struct st_scanmode *mymode) { SANE_Int rst = ERROR; switch(RTS_Debug->dev_model) { case BQ5550: rst = bq5550_scanmodes(RTS_Debug->usbtype, sm, mymode); break; case UA4900: rst = ua4900_scanmodes(RTS_Debug->usbtype, sm, mymode); break; case HP3800: case HPG2710: rst = hp3800_scanmodes(RTS_Debug->usbtype, sm, mymode); break; case HP4370: case HPG3010: case HPG3110: rst = hp4370_scanmodes(RTS_Debug->usbtype, sm, mymode); break; default: /* hp3970 hp4070 */ rst = hp3970_scanmodes(RTS_Debug->usbtype, sensortype, sm, mymode); break; } return rst; } static SANE_Int hp3970_scanmodes(SANE_Int usb, SANE_Int ccd, SANE_Int sm, struct st_scanmode *mymode) { struct st_modes { SANE_Int usb; SANE_Int sensor; struct st_scanmode mode; }; struct st_modes reg[] = { /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 24499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 600, 0x02 , 2 , PIXEL_RATE, 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 24499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 600, 0x07 , 2 , LINE_RATE , 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 300, 0x03 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 200, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 300, 0x08 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 200, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CCD_SENSOR, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 24499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 600, 0x02 , 2 , PIXEL_RATE, 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 24499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 600, 0x07 , 2 , LINE_RATE , 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 300, 0x03 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 200, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 300, 0x08 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 200, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, CIS_SENSOR, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x03 , 21499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x04 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x04 , 21999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 10727, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 5591, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 21499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x04 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 600, 0x07 , 2 , LINE_RATE , 0x04 , 6999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 4671, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 300, 0x03 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 200, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 300, 0x08 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 200, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 21499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x04 , 21999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 10727, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 5591, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 21499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x04 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 600, 0x07 , 2 , LINE_RATE , 0x04 , 6999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 4671, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 200, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x04 , 25599, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 200, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, sensor , {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 300, 0x03 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 200, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CIS_SENSOR, {ST_NEG , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x02 , 76799, 256 , STT_FULL, 0x00 , {25599, 51199, 0}, {25599, 25599, 76799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CIS_SENSOR, {ST_NEG , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 300, 0x08 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 200, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, CCD_SENSOR, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} }; SANE_Int rst = ERROR; if (mymode != NULL) { SANE_Int a; SANE_Int total = sizeof(reg) / sizeof(struct st_modes); SANE_Int count = 0; struct st_modes *md; for (a = 0; a < total; a++) { md = ®[a]; if ((md->usb == usb)&&(md->sensor == ccd)) { if (count == sm) { memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); rst = OK; break; } count++; } } } return rst; } static SANE_Int hp4370_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode) { struct st_modes { SANE_Int usb; struct st_scanmode mode; }; struct st_modes reg[] = { /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_NORMAL, CM_COLOR , 4800, 0x00 , -1 , PIXEL_RATE, 0x05 , 47799, 256 , STT_HALF, 0x00 , {23899, 23899, 23899}, {23899, 23899, 23899}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 31849, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 600, 0x03 , 2 , PIXEL_RATE, 0x05 , 7999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 300, 0x04 , 3 , PIXEL_RATE, 0x04 , 2799, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 150, 0x04 , 4 , PIXEL_RATE, 0x04 , 2799, 1856 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 4800, 0x05 , -1 , LINE_RATE , 0x05 , 47799, 256 , STT_HALF, 0x00 , {23899, 23899, 23899}, {23899, 23899, 23899}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 31849, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 600, 0x08 , 2 , LINE_RATE , 0x05 , 7999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 300, 0x09 , 3 , LINE_RATE , 0x04 , 2799, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 150, 0x09 , 4 , LINE_RATE , 0x04 , 2799, 1856 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_TA , CM_COLOR , 4800, 0x0A , -1 , PIXEL_RATE, 0x05 , 53999, 256 , STT_HALF, 0x00 , {26999, 26999, 26999}, {26999, 26999, 26999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 35999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 17999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 600, 0x03 , 2 , PIXEL_RATE, 0x05 , 8999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 300, 0x04 , 3 , PIXEL_RATE, 0x04 , 2959, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 150, 0x04 , 4 , PIXEL_RATE, 0x04 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 4800, 0x0B , -1 , LINE_RATE , 0x05 , 53999, 256 , STT_HALF, 0x00 , {26999, 26999, 26999}, {26999, 26999, 26999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 35999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 17999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 600, 0x08 , 3 , LINE_RATE , 0x05 , 8999, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 300, 0x09 , 4 , LINE_RATE , 0x04 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 150, 0x09 , 4 , LINE_RATE , 0x05 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_NEG , CM_COLOR , 4800, 0x0C , -1 , PIXEL_RATE, 0x05 , 60599, 256 , STT_HALF, 0x00 , {30299, 30299, 30299}, {30299, 30299, 30299}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 145799, 256 , STT_FULL, 0x00 , {48599, 97199, 0}, {48599, 48599, 145799}, 0 , 1 , -1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 89999, 256 , STT_FULL, 0x00 , {29999, 59999, 0}, {29999, 29999, 89999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 600, 0x03 , -1 , PIXEL_RATE, 0x05 , 45999, 256 , STT_HALF, 0x00 , {15333, 30666, 0}, {15333, 15333, 45999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 300, 0x04 , -1 , PIXEL_RATE, 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 150, 0x04 , 3 , PIXEL_RATE, 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 4800, 0x0D , -1 , LINE_RATE , 0x05 , 60599, 256 , STT_FULL, 0x00 , {30299, 30299, 30299}, {30299, 30299, 30299}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 ,145799, 256 , STT_FULL, 0x00 , {48599, 97199, 0}, {48599, 48599, 145799}, 0 , 1 , -1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 89999, 256 , STT_FULL, 0x00 , {29999, 59999, 0}, {29999, 29999, 89999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 600, 0x08 , -1 , LINE_RATE , 0x05 , 45999, 256 , STT_HALF, 0x00 , {15333, 30666, 0}, {15333, 15333, 45999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 300, 0x09 , -1 , LINE_RATE , 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 150, 0x09 , 3 , LINE_RATE , 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, {ST_NORMAL, CM_COLOR , 4800, 0x00 , -1 , PIXEL_RATE, 0x05 , 47799, 64 , STT_HALF, 0x00 , {23899, 23899, 23899}, {23899, 23899, 23899}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 31849, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 600, 0x03 , 2 , PIXEL_RATE, 0x05 , 7999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 300, 0x04 , 3 , PIXEL_RATE, 0x04 , 2799, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 150, 0x04 , 4 , PIXEL_RATE, 0x04 , 2799, 1856 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 4800, 0x05 , -1 , LINE_RATE , 0x05 , 47799, 64 , STT_HALF, 0x00 , {23899, 23899, 23899}, {23899, 23899, 23899}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 31849, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 600, 0x08 , 2 , LINE_RATE , 0x05 , 7999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 300, 0x09 , 3 , LINE_RATE , 0x04 , 2799, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 150, 0x09 , 4 , LINE_RATE , 0x04 , 2799, 1856 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, {ST_TA , CM_COLOR , 4800, 0x0A , -1 , PIXEL_RATE, 0x05 , 53999, 64 , STT_HALF, 0x00 , {26999, 26999, 26999}, {26999, 26999, 26999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 , 35999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 17999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 600, 0x03 , 2 , PIXEL_RATE, 0x05 , 8999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 300, 0x04 , 3 , PIXEL_RATE, 0x04 , 2959, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 150, 0x04 , 4 , PIXEL_RATE, 0x04 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 4800, 0x0B , -1 , LINE_RATE , 0x05 , 53999, 64 , STT_HALF, 0x00 , {26999, 26999, 26999}, {26999, 26999, 26999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 , 35999, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 17999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 600, 0x08 , 3 , LINE_RATE , 0x05 , 8999, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 300, 0x09 , 4 , LINE_RATE , 0x04 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 150, 0x09 , 4 , LINE_RATE , 0x05 , 2959, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, {ST_NEG , CM_COLOR , 4800, 0x0C , -1 , PIXEL_RATE, 0x05 , 60599, 64 , STT_HALF, 0x00 , {30299, 30299, 30299}, {30299, 30299, 30299}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 2400, 0x01 , -1 , PIXEL_RATE, 0x05 ,145799, 256 , STT_FULL, 0x00 , {48599, 97199, 0}, {48599, 48599,145799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 1200, 0x02 , -1 , PIXEL_RATE, 0x05 , 89999, 256 , STT_FULL, 0x00 , {29999, 59999, 0}, {29999, 29999, 89999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 600, 0x03 , -1 , PIXEL_RATE, 0x05 , 45999, 256 , STT_HALF, 0x00 , {15333, 30666, 0}, {15333, 15333, 45999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 300, 0x04 , -1 , PIXEL_RATE, 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 150, 0x04 , 3 , PIXEL_RATE, 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 4800, 0x0D , -1 , LINE_RATE , 0x05 , 60599, 64 , STT_FULL, 0x00 , {30299, 30299, 30299}, {30299, 30299, 30299}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 2400, 0x06 , -1 , LINE_RATE , 0x05 ,145799, 256 , STT_FULL, 0x00 , {48599, 97199, 0}, {48599, 48599,145799}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 1200, 0x07 , -1 , LINE_RATE , 0x05 , 89999, 256 , STT_FULL, 0x00 , {29999, 59999, 0}, {29999, 29999, 59999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 600, 0x08 , -1 , LINE_RATE , 0x05 , 45999, 256 , STT_HALF, 0x00 , {15333, 30666, 0}, {15333, 15333, 45999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 300, 0x09 , -1 , LINE_RATE , 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 150, 0x09 , 3 , LINE_RATE , 0x04 , 14879, 256 , STT_HALF, 0x00 , { 4959, 9919, 0}, { 4959, 4959, 14879}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} }; SANE_Int rst = ERROR; if (mymode != NULL) { SANE_Int a; SANE_Int total = sizeof(reg) / sizeof(struct st_modes); SANE_Int count = 0; struct st_modes *md; for (a = 0; a < total; a++) { md = ®[a]; if (md->usb == usb) { if (count == sm) { memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); rst = OK; break; } count++; } } } return rst; } static SANE_Int hp3800_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode) { struct st_modes { SANE_Int usb; struct st_scanmode mode; }; struct st_modes reg[] = { /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x05 , 23999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x04 , 7999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 300, 0x03 , 9 , PIXEL_RATE, 0x04 , 4999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 150, 0x03 , 10 , PIXEL_RATE, 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x05 , 23999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x04 , 7999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 300, 0x08 , 9 , LINE_RATE , 0x04 , 4999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 150, 0x08 , 10 , LINE_RATE , 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 600, 0x09 , -1 , PIXEL_RATE, 0x04 , 5999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 2999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 150, 0x03 , 10 , PIXEL_RATE, 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x04 , 5999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 2999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 150, 0x08 , 10 , LINE_RATE , 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_NEG , CM_COLOR , 2400, 0x0A , -1 , PIXEL_RATE, 0x04 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 1200, 0x0B , -1 , PIXEL_RATE, 0x05 ,127999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 600, 0x0C , -1 , PIXEL_RATE, 0x04 , 31999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 31999, 31999, 31999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 300, 0x0D , -1 , PIXEL_RATE, 0x04 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 150, 0x0D , 10 , PIXEL_RATE, 0x04 , 15999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 2400, 0x0F , -1 , LINE_RATE , 0x05 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 1200, 0x10 , -1 , LINE_RATE , 0x05 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 600, 0x11 , -1 , LINE_RATE , 0x04 , 31999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 31999, 31999, 31999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 300, 0x12 , -1 , LINE_RATE , 0x04 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 150, 0x12 , 10 , LINE_RATE , 0x04 , 15999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, {ST_NORMAL, CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x05 , 23999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 2 , 5 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 2 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 600, 0x02 , -1 , PIXEL_RATE, 0x04 , 7999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 300, 0x03 , 9 , PIXEL_RATE, 0x04 , 4999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_COLOR , 150, 0x03 , 10 , PIXEL_RATE, 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x05 , 23999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 2 , 2 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 2 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x04 , 7999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 300, 0x08 , 9 , LINE_RATE , 0x04 , 4999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NORMAL, CM_GRAY , 150, 0x08 , 10 , LINE_RATE , 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, {ST_TA , CM_COLOR , 2400, 0x00 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 1200, 0x01 , -1 , PIXEL_RATE, 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 600, 0x09 , -1 , PIXEL_RATE, 0x04 , 5999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 300, 0x03 , 3 , PIXEL_RATE, 0x04 , 2999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_COLOR , 150, 0x03 , 10 , PIXEL_RATE, 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 2400, 0x05 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 1200, 0x06 , -1 , LINE_RATE , 0x05 , 23999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 600, 0x07 , -1 , LINE_RATE , 0x04 , 5999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 300, 0x08 , 3 , LINE_RATE , 0x04 , 2999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_TA , CM_GRAY , 150, 0x08 , 10 , LINE_RATE , 0x04 , 2999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB11, {ST_NEG , CM_COLOR , 2400, 0x0A , -1 , PIXEL_RATE, 0x04 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 1200, 0x0B , -1 , PIXEL_RATE, 0x05 ,127999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 600, 0x0C , -1 , PIXEL_RATE, 0x04 , 31999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 31999, 31999, 31999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 300, 0x0D , -1 , PIXEL_RATE, 0x04 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_COLOR , 150, 0x0D , 10 , PIXEL_RATE, 0x04 , 15999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 2400, 0x0F , -1 , LINE_RATE , 0x05 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 1200, 0x10 , -1 , LINE_RATE , 0x05 ,127999, 96 , STT_HALF, 0x00 , { 0, 0, 0}, {127999,127999,127999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 600, 0x11 , -1 , LINE_RATE , 0x04 , 31999, 128 , STT_HALF, 0x00 , { 0, 0, 0}, { 31999, 31999, 31999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 300, 0x12 , -1 , LINE_RATE , 0x04 , 15999, 256 , STT_HALF, 0x00 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB11, {ST_NEG , CM_GRAY , 150, 0x12 , 10 , LINE_RATE , 0x04 , 15999, 1024 , STT_HALF, 0x01 , { 0, 0, 0}, { 15999, 15999, 15999}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} }; SANE_Int rst = ERROR; if (mymode != NULL) { SANE_Int a; SANE_Int total = sizeof(reg) / sizeof(struct st_modes); SANE_Int count = 0; struct st_modes *md; for (a = 0; a < total; a++) { md = ®[a]; if (md->usb == usb) { if (count == sm) { memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); rst = OK; break; } count++; } } } return rst; } static SANE_Int bq5550_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode) { struct st_modes { SANE_Int usb; struct st_scanmode mode; }; struct st_modes reg[] = { /* usb, {scantype , colormode , res , timing, curve, samplerate, clock, ctpc , backstp, steptype , dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_NORMAL, CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x05 , 12999, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x05 , 6999, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 5 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 300, 0x02 , 0 , PIXEL_RATE, 0x05 , 5599, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 150, 0x02 , 0 , PIXEL_RATE, 0x05 , 6439, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 2 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 100, 0x02 , 0 , PIXEL_RATE, 0x05 , 5759, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 1200, 0x03 , -1 , LINE_RATE , 0x05 , 12999, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 600, 0x04 , -1 , LINE_RATE , 0x05 , 7199, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 2 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 300, 0x05 , 0 , LINE_RATE , 0x05 , 5599, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 150, 0x05 , 0 , LINE_RATE , 0x05 , 6239, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 100, 0x05 , 0 , LINE_RATE , 0x05 , 5759, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_LINEART, 1200, 0x03 , -1 , LINE_RATE , 0x05 , 12999, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 3 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_LINEART, 600, 0x04 , -1 , LINE_RATE , 0x05 , 7199, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 2 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_LINEART, 300, 0x05 , 0 , LINE_RATE , 0x05 , 5599, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_LINEART, 150, 0x05 , 0 , LINE_RATE , 0x05 , 6239, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_LINEART, 100, 0x05 , 0 , LINE_RATE , 0x05 , 5759, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode , res , timing, curve, samplerate, clock, ctpc , backstp, steptype , dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_TA , CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x05 , 9899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x05 , 9999, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 300, 0x02 , 0 , PIXEL_RATE, 0x05 , 4799, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 150, 0x02 , 0 , PIXEL_RATE, 0x05 , 4959, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 100, 0x02 , 0 , PIXEL_RATE, 0x05 , 5059, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 1200, 0x03 , -1 , LINE_RATE , 0x05 , 9899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 600, 0x04 , -1 , LINE_RATE , 0x05 , 9999, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 300, 0x05 , 0 , LINE_RATE , 0x05 , 4799, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 150, 0x05 , 0 , LINE_RATE , 0x05 , 4959, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 100, 0x05 , 0 , LINE_RATE , 0x05 , 5059, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_LINEART, 1200, 0x03 , -1 , LINE_RATE , 0x05 , 9899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_LINEART, 600, 0x04 , -1 , LINE_RATE , 0x05 , 9999, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_LINEART, 300, 0x05 , 0 , LINE_RATE , 0x05 , 4799, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_LINEART, 150, 0x05 , 0 , LINE_RATE , 0x05 , 4959, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_LINEART, 100, 0x05 , 0 , LINE_RATE , 0x05 , 5059, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode , res , timing, curve, samplerate, clock, ctpc , backstp, steptype , dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_NEG , CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x05 , 51899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x05 , 51799, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 300, 0x02 , 0 , PIXEL_RATE, 0x05 , 25899, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 150, 0x02 , 0 , PIXEL_RATE, 0x05 , 25899, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 100, 0x02 , 0 , PIXEL_RATE, 0x05 , 25499, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 1200, 0x03 , -1 , LINE_RATE , 0x05 , 51899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 600, 0x04 , -1 , LINE_RATE , 0x05 , 51799, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 300, 0x05 , 0 , LINE_RATE , 0x05 , 25899, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 150, 0x05 , 0 , LINE_RATE , 0x05 , 25899, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 100, 0x05 , 0 , LINE_RATE , 0x05 , 25499, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_LINEART, 1200, 0x03 , -1 , LINE_RATE , 0x05 , 51899, 10 , STT_QUART, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_LINEART, 600, 0x04 , -1 , LINE_RATE , 0x05 , 51799, 32 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_LINEART, 300, 0x05 , 0 , LINE_RATE , 0x05 , 25899, 128 , STT_FULL , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_LINEART, 150, 0x05 , 0 , LINE_RATE , 0x05 , 25899, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_LINEART, 100, 0x05 , 0 , LINE_RATE , 0x05 , 25499, 128 , STT_HALF , 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} }; SANE_Int rst = ERROR; /* silence compiler */ usb = usb; if (mymode != NULL) { SANE_Int a; SANE_Int total = sizeof(reg) / sizeof(struct st_modes); SANE_Int count = 0; struct st_modes *md; for (a = 0; a < total; a++) { md = ®[a]; if (count == sm) { memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); rst = OK; break; } count++; } } return rst; } static SANE_Int ua4900_scanmodes(SANE_Int usb, SANE_Int sm, struct st_scanmode *mymode) { struct st_modes { SANE_Int usb; struct st_scanmode mode; }; struct st_modes reg[] = { /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_NORMAL, CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 600, 0x01 , 2 , PIXEL_RATE, 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 300, 0x02 , 3 , PIXEL_RATE, 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 200, 0x03 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 1200, 0x05 , -1 , LINE_RATE , 0x05 , 14667, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 600, 0x06 , 2 , LINE_RATE , 0x04 , 5499, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 300, 0x07 , 3 , LINE_RATE , 0x04 , 2751, 768 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 200, 0x08 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NORMAL, CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 2255, 1856 , STT_HALF, 0x02 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_TA , CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 300, 0x02 , 3 , PIXEL_RATE, 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 200, 0x03 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_COLOR , 100, 0x04 , 4 , PIXEL_RATE, 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 1200, 0x05 , -1 , LINE_RATE , 0x03 , 10899, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 600, 0x06 , -1 , LINE_RATE , 0x01 , 5487, 256 , STT_FULL, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 300, 0x07 , 3 , LINE_RATE , 0x04 , 8351, 512 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 200, 0x08 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_TA , CM_GRAY , 100, 0x09 , 4 , LINE_RATE , 0x04 , 7343, 1024 , STT_HALF, 0x00 , { 0, 0, 0}, { 0, 0, 0}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, /* usb, {scantype , colormode, res , timing, curve, samplerate, clock, ctpc , backstp, steptype, dummyline, {expt }, {mexpt }, motorplus, mexpt16, mexptfull, mexposure, mri , msi , mmtir, mmtirh, skips } */ {USB20, {ST_NEG , CM_COLOR , 1200, 0x00 , -1 , PIXEL_RATE, 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 600, 0x01 , -1 , PIXEL_RATE, 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 300, 0x02 , -1 , PIXEL_RATE, 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 200, 0x03 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_COLOR , 100, 0x04 , -1 , PIXEL_RATE, 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 1200, 0x05 , -1 , LINE_RATE , 0x03 , 36467, 256 , STT_FULL, 0x00 , {12155, 24311, 0}, {12155, 12155, 36467}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 600, 0x06 , -1 , LINE_RATE , 0x02 , 16463, 256 , STT_FULL, 0x00 , { 5487, 10975, 0}, { 5487, 5487, 16463}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 300, 0x07 , -1 , LINE_RATE , 0x02 , 8351, 256 , STT_HALF, 0x00 , { 2783, 5567, 0}, { 2783, 2783, 8351}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 200, 0x08 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x00 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }}, {USB20, {ST_NEG , CM_GRAY , 100, 0x09 , -1 , LINE_RATE , 0x02 , 6191, 256 , STT_HALF, 0x02 , { 2063, 4127, 0}, { 2063, 2063, 6191}, 0 , 1 , 1 , 0x01 , 0x01, 0x10, 0x02 , 0x02 , 0x00 }} }; SANE_Int rst = ERROR; if (mymode != NULL) { SANE_Int a; SANE_Int total = sizeof(reg) / sizeof(struct st_modes); SANE_Int count = 0; struct st_modes *md; for (a = 0; a < total; a++) { md = ®[a]; if (md->usb == usb) { if (count == sm) { memcpy(mymode, &md->mode, sizeof(struct st_scanmode)); rst = OK; break; } count++; } } } return rst; } /** SEC: Calibration wreferences ---------- */ static void hp3970_wrefs(SANE_Int usb, SANE_Int ccd, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { struct st_wref { SANE_Int usb; SANE_Int sensor; SANE_Int depth; SANE_Int res; SANE_Int transparent[3]; SANE_Int negative[3]; }; struct st_wref wrefs[] = { /*usb , sensor , depth, res , {transparent }, {negative} */ {USB20, CCD_SENSOR, 8 , 2400, { 78, 78, 68}, {120, 136, 157}}, {USB20, CCD_SENSOR, 8 , 1200, { 78, 78, 68}, {120, 136, 157}}, {USB20, CCD_SENSOR, 8 , 600 , { 79, 80, 70}, {119, 136, 157}}, {USB20, CCD_SENSOR, 8 , 300 , { 79, 80, 70}, {119, 136, 157}}, {USB20, CCD_SENSOR, 8 , 200 , { 79, 80, 70}, {119, 136, 157}}, {USB20, CCD_SENSOR, 8 , 100 , { 79, 80, 70}, {119, 136, 157}}, {USB20, CCD_SENSOR, 16 , 2400, { 81, 81, 71}, {119, 137, 158}}, {USB20, CCD_SENSOR, 16 , 1200, { 81, 81, 71}, {119, 137, 158}}, {USB20, CCD_SENSOR, 16 , 600 , { 81, 82, 72}, {119, 137, 158}}, {USB20, CCD_SENSOR, 16 , 300 , { 81, 82, 72}, {119, 137, 158}}, {USB20, CCD_SENSOR, 16 , 200 , { 81, 82, 72}, {119, 137, 158}}, {USB20, CCD_SENSOR, 16 , 100 , { 81, 82, 72}, {119, 137, 158}}, /*usb , sensor , depth, res , {transparent }, {negative } */ {USB20, CIS_SENSOR, 8 , 2400, { 94, 85, 78}, { 94, 85, 78}}, {USB20, CIS_SENSOR, 8 , 1200, { 83, 82, 75}, {140, 155, 155}}, {USB20, CIS_SENSOR, 8 , 600 , { 84, 84, 76}, {145, 155, 165}}, {USB20, CIS_SENSOR, 8 , 300 , {146, 166, 166}, {146, 166, 166}}, {USB20, CIS_SENSOR, 8 , 200 , {145, 310, 160}, {145, 310, 160}}, {USB20, CIS_SENSOR, 8 , 100 , {140, 300, 155}, {140, 300, 155}}, {USB20, CIS_SENSOR, 16 , 2400, { 94, 85, 78}, { 94, 85, 78}}, {USB20, CIS_SENSOR, 16 , 1200, { 83, 82, 75}, {140, 155, 155}}, {USB20, CIS_SENSOR, 16 , 600 , { 84, 84, 76}, {145, 155, 165}}, {USB20, CIS_SENSOR, 16 , 300 , {146, 166, 166}, {146, 166, 166}}, {USB20, CIS_SENSOR, 16 , 200 , {145, 310, 160}, {145, 310, 160}}, {USB20, CIS_SENSOR, 16 , 100 , {140, 300, 155}, {140, 300, 155}}, /*usb , sensor , depth, res , {transparent }, {negative } */ {USB11, CCD_SENSOR, 8 , 2400, { 78, 78, 68}, {120, 137, 158}}, {USB11, CCD_SENSOR, 8 , 1200, { 78, 78, 68}, {120, 137, 158}}, {USB11, CCD_SENSOR, 8 , 600 , { 79, 79, 70}, {120, 137, 158}}, {USB11, CCD_SENSOR, 8 , 300 , { 79, 79, 70}, {120, 137, 158}}, {USB11, CCD_SENSOR, 8 , 200 , { 79, 79, 70}, {120, 137, 158}}, {USB11, CCD_SENSOR, 8 , 100 , { 79, 79, 70}, {120, 137, 158}}, {USB11, CCD_SENSOR, 16 , 2400, { 80, 80, 70}, {120, 137, 158}}, {USB11, CCD_SENSOR, 16 , 1200, { 80, 80, 70}, {120, 137, 158}}, {USB11, CCD_SENSOR, 16 , 600 , { 80, 81, 71}, {120, 137, 158}}, {USB11, CCD_SENSOR, 16 , 300 , { 80, 81, 71}, {120, 137, 158}}, {USB11, CCD_SENSOR, 16 , 200 , { 80, 81, 71}, {120, 137, 158}}, {USB11, CCD_SENSOR, 16 , 100 , { 80, 81, 71}, {120, 137, 158}}, /*usb , sensor , depth, res , {transparent }, {negative} */ {USB11, CIS_SENSOR, 8 , 2400, { 94, 85, 78}, {94 , 85 , 78}}, {USB11, CIS_SENSOR, 8 , 1200, { 83, 82, 75}, {140, 155, 155}}, {USB11, CIS_SENSOR, 8 , 600 , { 84, 84, 76}, {145, 155, 165}}, {USB11, CIS_SENSOR, 8 , 300 , {146, 166, 166}, {146, 166, 166}}, {USB11, CIS_SENSOR, 8 , 200 , {145, 310, 160}, {145, 310, 160}}, {USB11, CIS_SENSOR, 8 , 100 , {140, 300, 155}, {140, 300, 155}}, {USB11, CIS_SENSOR, 16 , 2400, { 94, 85, 78}, { 94, 85, 78}}, {USB11, CIS_SENSOR, 16 , 1200, { 83, 82, 75}, {140, 155, 155}}, {USB11, CIS_SENSOR, 16 , 600 , { 84, 84, 76}, {145, 155, 165}}, {USB11, CIS_SENSOR, 16 , 300 , {146, 166, 166}, {146, 166, 166}}, {USB11, CIS_SENSOR, 16 , 200 , {145, 310, 160}, {145, 310, 160}}, {USB11, CIS_SENSOR, 16 , 100 , {140, 300, 155}, {140, 300, 155}} }; struct st_wref *rf; *red = *green = *blue = 0x50; if (res <= 100) res = 100; else if (res <= 200) res = 200; else if (res <= 300) res = 300; else if (res <= 600) res = 600; else if (res <= 1200) res = 1200; else res = 2400; if (scantype != ST_NORMAL) { SANE_Int a; SANE_Int count = sizeof(wrefs) / sizeof(struct st_wref); for (a = 0; a < count; a++) { rf = &wrefs[a]; if ((rf->usb == usb)&&(rf->sensor == ccd)&&(rf->depth == depth)&&(rf->res == res)) { switch(scantype) { case ST_NEG: *red = rf->negative[CL_RED]; *green = rf->negative[CL_GREEN]; *blue = rf->negative[CL_BLUE]; break; case ST_TA: *red = rf->transparent[CL_RED]; *green = rf->transparent[CL_GREEN]; *blue = rf->transparent[CL_BLUE]; break; } break; } } } else { /* reflective mode */ *red = 233; *green = 230; *blue = 222; } } static void ua4900_wrefs(SANE_Int usb, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { struct st_wref { SANE_Int usb; SANE_Int depth; SANE_Int res; SANE_Int transparent[3]; SANE_Int negative[3]; }; struct st_wref wrefs[] = { /*usb , depth, res , {transparent }, {negative } */ {USB20, 8 , 1200, {136, 131, 121}, {215, 210, 260}}, {USB20, 8 , 600 , {133, 129, 118}, {219, 215, 264}}, {USB20, 8 , 300 , {133, 129, 119}, {218, 215, 261}}, {USB20, 8 , 200 , {133, 130, 119}, {218, 215, 261}}, {USB20, 8 , 100 , {132, 128, 118}, {218, 215, 261}}, {USB20, 16 , 1200, {264, 263, 266}, { 0, 0, 0}}, {USB20, 16 , 600 , {264, 265, 268}, { 0, 0, 0}}, {USB20, 16 , 300 , {264, 260, 263}, { 0, 0, 0}}, {USB20, 16 , 200 , {257, 255, 253}, { 0, 0, 0}}, {USB20, 16 , 100 , {258, 259, 256}, { 0, 0, 0}}, /*usb , depth, res , {transparent }, {negative } */ {USB11, 8 , 1200, {135, 130, 119}, {220, 215, 264}}, {USB11, 8 , 600 , {132, 128, 117}, {217, 213, 259}}, {USB11, 8 , 300 , {132, 128, 117}, {216, 211, 259}}, {USB11, 8 , 200 , {132, 128, 118}, {215, 352, 259}}, {USB11, 8 , 100 , {266, 264, 264}, {215, 352, 259}}, {USB11, 16 , 1200, {264, 263, 266}, { 0, 0, 0}}, {USB11, 16 , 600 , {257, 256, 253}, { 0, 0, 0}}, {USB11, 16 , 300 , {259, 252, 254}, { 0, 0, 0}}, {USB11, 16 , 200 , {257, 255, 253}, { 0, 0, 0}}, {USB11, 16 , 100 , {258, 259, 256}, { 0, 0, 0}} }; struct st_wref *rf; *red = *green = *blue = 0x50; if (res <= 100) res = 100; else if (res <= 200) res = 200; else if (res <= 300) res = 300; else if (res <= 600) res = 600; else res = 1200; if (scantype != ST_NORMAL) { SANE_Int a; SANE_Int count = sizeof(wrefs) / sizeof(struct st_wref); for (a = 0; a < count; a++) { rf = &wrefs[a]; if ((rf->usb == usb)&&(rf->depth == depth)&&(rf->res == res)) { switch(scantype) { case ST_NEG: *red = rf->negative[CL_RED]; *green = rf->negative[CL_GREEN]; *blue = rf->negative[CL_BLUE]; break; case ST_TA: *red = rf->transparent[CL_RED]; *green = rf->transparent[CL_GREEN]; *blue = rf->transparent[CL_BLUE]; break; } break; } } } else { /* reflective mode */ *red = 233; *green = 230; *blue = 222; } } static void hp3800_wrefs(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { /* in this scanner, values are the same in all usb versions and depths */ struct st_wref { SANE_Int res; SANE_Int transparent[3]; SANE_Int negative[3]; }; struct st_wref wrefs[] = { /* res , {transparent }, {negative } */ { 2400, {276, 279, 243}, { 98, 162, 229}}, { 1200, {276, 279, 243}, { 98, 162, 229}}, { 600, {276, 279, 243}, {100, 162, 229}}, { 300, {276, 279, 243}, {100, 162, 229}}, { 150, {276, 279, 243}, {100, 162, 229}}, }; struct st_wref *rf; *red = *green = *blue = 0x50; if (res <= 150) res = 150; else if (res <= 300) res = 300; else if (res <= 600) res = 600; else if (res <= 1200) res = 1200; else res = 2400; if (scantype != ST_NORMAL) { SANE_Int a; SANE_Int count = sizeof(wrefs) / sizeof(struct st_wref); for (a = 0; a < count; a++) { rf = &wrefs[a]; if (rf->res == res) { switch(scantype) { case ST_NEG: *red = rf->negative[CL_RED]; *green = rf->negative[CL_GREEN]; *blue = rf->negative[CL_BLUE]; break; case ST_TA: *red = rf->transparent[CL_RED]; *green = rf->transparent[CL_GREEN]; *blue = rf->transparent[CL_BLUE]; break; } break; } } } else { /* reflective mode */ *red = 248; *green = 250; *blue = 248; } } static void hp4370_wrefs(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { struct st_wref { SANE_Int res; SANE_Int transparent[3]; SANE_Int negative[3]; }; /* values are the same in all usb versions and depths */ struct st_wref wrefs[] = { /* res, {transparent }, {negative} */ { 4800, { 93, 93, 82}, {156, 308, 454}}, { 2400, { 93, 93, 82}, {156, 156, 153}}, { 1200, { 93, 93, 82}, {156, 156, 153}}, { 600, { 93, 93, 82}, {155, 155, 152}}, { 300, { 94, 94, 83}, {155, 155, 152}}, { 150, { 86, 87, 77}, {148, 145, 138}} }; struct st_wref *rf; SANE_Int a; *red = *green = *blue = 0x50; if (res <= 150) res = 150; else if (res <= 300) res = 300; else if (res <= 600) res = 600; else if (res <= 1200) res = 1200; else if (res <= 2400) res = 2400; else res = 4800; if (scantype != ST_NORMAL) { SANE_Int count = sizeof(wrefs) / sizeof(struct st_wref); for (a = 0; a < count; a++) { rf = &wrefs[a]; if (rf->res == res) { switch(scantype) { case ST_NEG: *red = rf->negative[CL_RED]; *green = rf->negative[CL_GREEN]; *blue = rf->negative[CL_BLUE]; break; case ST_TA: *red = rf->transparent[CL_RED]; *green = rf->transparent[CL_GREEN]; *blue = rf->transparent[CL_BLUE]; break; } break; } } } else { /* reflective mode */ *red = 233; *green = 232; *blue = 223; } } static void cfg_wrefs_get(SANE_Int sensortype, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { switch(RTS_Debug->dev_model) { case UA4900: ua4900_wrefs(RTS_Debug->usbtype, depth, res, scantype, red, green, blue); break; case HP3800: case HPG2710: hp3800_wrefs(res, scantype, red, green, blue); break; case HP4370: case HPG3010: case HPG3110: hp4370_wrefs(res, scantype, red, green, blue); break; default: /* hp3970 and hp4070 */ hp3970_wrefs(RTS_Debug->usbtype, sensortype, depth, res, scantype, red, green, blue); break; } } static void hp3800_shading_cut(SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { /* values are the same in all usb versions and depths */ struct st_cut { SANE_Int res; SANE_Int reflective[3]; SANE_Int transparent[3]; SANE_Int negative[3]; }; struct st_cut cuts[] = { /* res, {reflective }, {transparent }, {negative } */ { 2400, { -6, -6, -6}, {-75, -75, -75}, {440, -300, -250}}, { 1200, { -6, -6, -6}, {-75, -75, -75}, {440, -300, -250}}, { 600, { 10, 9, 12}, {-75, -75, -75}, {440, -300, -250}}, { 300, { -6, -6, -6}, {-75, -75, -75}, {440, -300, -250}}, { 150, { -6, -6, -6}, {-75, -75, -75}, {440, -300, -250}} }; struct st_cut *ct; SANE_Int a; SANE_Int count = sizeof(cuts) / sizeof(struct st_cut); *red = *green = *blue = 0; if (res <= 150) res = 150; else if (res <= 300) res = 300; else if (res <= 600) res = 600; else if (res <= 1200) res = 1200; else res = 2400; for (a = 0; a < count; a++) { ct = &cuts[a]; if (ct->res == res) { switch(scantype) { case ST_NEG: *red = ct->negative[CL_RED]; *green = ct->negative[CL_GREEN]; *blue = ct->negative[CL_BLUE]; break; case ST_TA: *red = ct->transparent[CL_RED]; *green = ct->transparent[CL_GREEN]; *blue = ct->transparent[CL_BLUE]; break; default: /* reflective */ *red = ct->reflective[CL_RED]; *green = ct->reflective[CL_GREEN]; *blue = ct->reflective[CL_BLUE]; break; } break; } } } static void hp3970_shading_cut(SANE_Int usb, SANE_Int ccd, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { struct st_cut { SANE_Int usb; SANE_Int sensor; SANE_Int depth; SANE_Int res; SANE_Int reflective[3]; SANE_Int transparent[3]; SANE_Int negative[3]; }; struct st_cut cuts[] = { /*usb , sensor , depth, res , {reflective }, {transparent }, {negative} */ {USB20, CCD_SENSOR, 8 , 2400, {-15, -15, -15}, { 0, 0, 0}, {63, 0, 3}}, {USB20, CCD_SENSOR, 8 , 1200, {-15, -15, -15}, { 0, 0, 0}, {63, 0, 5}}, {USB20, CCD_SENSOR, 8 , 600 , {-15, -15, -15}, { 0, 0, 0}, {75, 0, 5}}, {USB20, CCD_SENSOR, 8 , 300 , {-15, -15, -15}, { 0, 0, 0}, {75, 0, 5}}, {USB20, CCD_SENSOR, 8 , 200 , {-15, -15, -15}, { 0, 0, 0}, {75, 0, 5}}, {USB20, CCD_SENSOR, 8 , 100 , {-15, -15, -15}, { 0, 0, 0}, {75, 0, 5}}, {USB20, CCD_SENSOR, 16 , 2400, {-15, -15, -15}, { -7, -7, -7}, {43, 0, 3}}, {USB20, CCD_SENSOR, 16 , 1200, {-15, -15, -15}, {-15, -15, -15}, {63, 0, 5}}, {USB20, CCD_SENSOR, 16 , 600 , {-15, -15, -15}, {-15, -15, -15}, {75, 0, 5}}, {USB20, CCD_SENSOR, 16 , 300 , {-15, -15, -15}, {-15, -15, -15}, {75, 0, 5}}, {USB20, CCD_SENSOR, 16 , 200 , {-15, -15, -15}, {-15, -15, -15}, {75, 0, 5}}, {USB20, CCD_SENSOR, 16 , 100 , {-15, -15, -15}, {-15, -15, -15}, {75, 0, 5}}, /*usb , sensor , depth, res , {reflective }, {transparent }, {negative} */ {USB20, CIS_SENSOR, 8 , 2400, {-15, -15, -15}, {-68, -37, -43}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 8 , 1200, {-15, -15, -15}, {-20, -20, -28}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 8 , 600 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 8 , 300 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 8 , 200 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 8 , 100 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 16 , 2400, {-15, -15, -15}, {-68, -37, -43}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 16 , 1200, {-15, -15, -15}, {-20, -20, -28}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 16 , 600 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 16 , 300 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 16 , 200 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB20, CIS_SENSOR, 16 , 100 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, /*usb , sensor , depth, res , {reflective }, {transparent }, {negative} */ {USB11, CCD_SENSOR, 8 , 2400, {-15, -15, -15}, { 0, 0, 0}, {63, 0, 3}}, {USB11, CCD_SENSOR, 8 , 1200, {-15, -15, -15}, { 0, 0, 0}, {63, 0, 5}}, {USB11, CCD_SENSOR, 8 , 600 , {-15, -15, -15}, { 0, 0, 0}, {50, 0, 5}}, {USB11, CCD_SENSOR, 8 , 300 , {-15, -15, -15}, { 0, 0, 0}, {50, 0, 5}}, {USB11, CCD_SENSOR, 8 , 200 , {-15, -15, -15}, { 0, 0, 0}, {50, 0, 5}}, {USB11, CCD_SENSOR, 8 , 100 , {-15, -15, -15}, { 0, 0, 0}, {50, 0, 5}}, {USB11, CCD_SENSOR, 16 , 2400, {-15, -15, -15}, { -7, -7, -7}, {43, 0, 3}}, {USB11, CCD_SENSOR, 16 , 1200, {-15, -15, -15}, {-15, -15, -15}, {63, 0, 5}}, {USB11, CCD_SENSOR, 16 , 600 , {-15, -15, -15}, {-15, -15, -15}, {50, 0, 5}}, {USB11, CCD_SENSOR, 16 , 300 , {-15, -15, -15}, {-15, -15, -15}, {50, 0, 5}}, {USB11, CCD_SENSOR, 16 , 200 , {-15, -15, -15}, {-15, -15, -15}, {50, 0, 5}}, {USB11, CCD_SENSOR, 16 , 100 , {-15, -15, -15}, {-15, -15, -15}, {50, 0, 5}}, /*usb , sensor , depth, res , {reflective }, {transparent }, {negative} */ {USB11, CIS_SENSOR, 8 , 2400, {-15, -15, -15}, {-68, -37, -43}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 8 , 1200, {-15, -15, -15}, {-20, -20, -28}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 8 , 600 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 8 , 300 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 8 , 200 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 8 , 100 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 16 , 2400, {-15, -15, -15}, {-68, -37, -43}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 16 , 1200, {-15, -15, -15}, {-20, -20, -28}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 16 , 600 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 16 , 300 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 16 , 200 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}}, {USB11, CIS_SENSOR, 16 , 100 , {-15, -15, -15}, { 0, 0, 0}, { 0, 0, 0}} }; struct st_cut *ct; SANE_Int a; SANE_Int count = sizeof(cuts) / sizeof(struct st_cut); *red = *green = *blue = 0; if (res <= 100) res = 100; else if (res <= 200) res = 200; else if (res <= 300) res = 300; else if (res <= 600) res = 600; else if (res <= 1200) res = 1200; else res = 2400; for (a = 0; a < count; a++) { ct = &cuts[a]; if ((ct->usb == usb)&&(ct->sensor == ccd)&&(ct->depth == depth)&&(ct->res == res)) { switch(scantype) { case ST_NEG: *red = ct->negative[CL_RED]; *green = ct->negative[CL_GREEN]; *blue = ct->negative[CL_BLUE]; break; case ST_TA: *red = ct->transparent[CL_RED]; *green = ct->transparent[CL_GREEN]; *blue = ct->transparent[CL_BLUE]; break; default: /* reflective */ *red = ct->reflective[CL_RED]; *green = ct->reflective[CL_GREEN]; *blue = ct->reflective[CL_BLUE]; break; } break; } } } static void hp4370_shading_cut(SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { struct st_cut { SANE_Int depth; SANE_Int res; SANE_Int reflective[3]; SANE_Int transparent[3]; SANE_Int negative[3]; }; /* values are the same in all usb versions for each depth */ struct st_cut cuts[] = { /* depth, res , {reflective }, {transparent }, {negative } */ { 8 , 4800, { 0, 0, 0}, { -3, -3, -3}, {35, -10, -7}}, { 8 , 2400, {-15, -15, -15}, { -3, -3, -3}, {35, -10, -7}}, { 8 , 1200, {-15, -15, -15}, { -3, -3, -3}, {35, -10, -22}}, { 8 , 600 , {-15, -15, -15}, { -2, -2, -2}, {38, -10, -22}}, { 8 , 300 , {-15, -15, -15}, { -2, -2, -2}, {38, -10, -22}}, { 8 , 150 , {-15, -15, -15}, { 0, 0, 0}, {50, -23, -14}}, { 16 , 4800, { 0, 0, 0}, { -3, -3, -3}, {35, -10, -7}}, { 16 , 2400, {-15, -15, -15}, { -3, -3, -3}, {35, -10, -7}}, { 16 , 1200, {-15, -15, -15}, { -3, -3, -3}, {35, -10, -22}}, { 16 , 600 , {-15, -15, -15}, { -2, -2, -2}, {38, -10, -22}}, { 16 , 300 , {-15, -15, -15}, { -2, -2, -2}, {38, -10, -22}}, { 16 , 150 , {-15, -15, -15}, {-15, -15, -15}, {40, -15, -5}} }; struct st_cut *ct; SANE_Int a; SANE_Int count = sizeof(cuts) / sizeof(struct st_cut); *red = *green = *blue = 0; if (res <= 150) res = 150; else if (res <= 300) res = 300; else if (res <= 600) res = 600; else if (res <= 1200) res = 1200; else if (res <= 2400) res = 2400; else res = 4800; for (a = 0; a < count; a++) { ct = &cuts[a]; if ((ct->depth == depth)&&(ct->res == res)) { switch(scantype) { case ST_NEG: *red = ct->negative[CL_RED]; *green = ct->negative[CL_GREEN]; *blue = ct->negative[CL_BLUE]; break; case ST_TA: *red = ct->transparent[CL_RED]; *green = ct->transparent[CL_GREEN]; *blue = ct->transparent[CL_BLUE]; break; default: /* reflective */ *red = ct->reflective[CL_RED]; *green = ct->reflective[CL_GREEN]; *blue = ct->reflective[CL_BLUE]; break; } break; } } } static void ua4900_shading_cut(SANE_Int usb, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { struct st_cut { SANE_Int usb; SANE_Int depth; SANE_Int res; SANE_Int reflective[3]; SANE_Int transparent[3]; SANE_Int negative[3]; }; struct st_cut cuts[] = { /*usb , depth, res , {reflective }, {transparent }, {negative } */ {USB20, 8 , 1200, {-15, -17, -13}, { 6, 0, 0}, {110, 15, 250}}, {USB20, 8 , 600 , {-16, -15, -15}, { 6, 7, 5}, {105, 11, 20}}, {USB20, 8 , 300 , {-15, -15, -15}, { 6, 7, 5}, {105, 10, 25}}, {USB20, 8 , 200 , {-15, -15, -15}, { 5, 5, 5}, {110, 15, 32}}, {USB20, 8 , 100 , {-15, -15, -15}, { 5, 5, 5}, {110, 15, 32}}, {USB20, 16 , 1200, {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, {USB20, 16 , 600 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, {USB20, 16 , 300 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, {USB20, 16 , 200 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, {USB20, 16 , 100 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, /*usb , depth, res , {reflective }, {transparent }, {negative } */ {USB11, 8 , 1200, {-15, -17, -13}, { 5, 5, 5}, {105, 12, 23}}, {USB11, 8 , 600 , {-17, -15, -16}, { 8, 8, 8}, {105, 12, 20}}, {USB11, 8 , 300 , {-15, -15, -15}, { 8, 8, 8}, {105, 15, 25}}, {USB11, 8 , 200 , {-15, -15, -15}, { 8, 8, 8}, {105, 40, 25}}, {USB11, 8 , 100 , {-15, -15, -15}, { 8, 8, 8}, {-20, 50, 23}}, {USB11, 16 , 1200, {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, {USB11, 16 , 600 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, {USB11, 16 , 300 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, {USB11, 16 , 200 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}}, {USB11, 16 , 100 , {-15, -15, -15}, { 5, 5, 5}, { 0, 0, 0}} }; struct st_cut *ct; SANE_Int a; SANE_Int count = sizeof(cuts) / sizeof(struct st_cut); *red = *green = *blue = 0; if (res <= 100) res = 100; else if (res <= 200) res = 200; else if (res <= 300) res = 300; else if (res <= 600) res = 600; else res = 1200; for (a = 0; a < count; a++) { ct = &cuts[a]; if ((ct->usb == usb)&&(ct->depth == depth)&&(ct->res == res)) { switch(scantype) { case ST_NEG: *red = ct->negative[CL_RED]; *green = ct->negative[CL_GREEN]; *blue = ct->negative[CL_BLUE]; break; case ST_TA: *red = ct->transparent[CL_RED]; *green = ct->transparent[CL_GREEN]; *blue = ct->transparent[CL_BLUE]; break; default: /* reflective */ *red = ct->reflective[CL_RED]; *green = ct->reflective[CL_GREEN]; *blue = ct->reflective[CL_BLUE]; break; } break; } } } static void cfg_shading_cut_get(SANE_Int sensortype, SANE_Int depth, SANE_Int res, SANE_Int scantype, SANE_Int *red, SANE_Int *green, SANE_Int *blue) { switch(RTS_Debug->dev_model) { case UA4900: ua4900_shading_cut(RTS_Debug->usbtype, depth, res, scantype, red, green, blue); break; case HP3800: case HPG2710: hp3800_shading_cut(res, scantype, red, green, blue); break; case HP4370: case HPG3010: case HPG3110: hp4370_shading_cut(depth, res, scantype, red, green, blue); break; default: /* hp3970 and hp4070 */ hp3970_shading_cut(RTS_Debug->usbtype, sensortype, depth, res, scantype, red, green, blue); break; } } /** SEC: Sensor Timings ---------- */ /* ccd timing values for bq5550 scanner */ static SANE_Int bq5550_timing_get(SANE_Int tm, struct st_timing *reg) { SANE_Int rst = ERROR; if ((tm < 7)&&(reg != NULL)) { /* bq5550 sensor timing values for each resolution and color mode */ struct st_timing data[] = { /* res , cnpp, {cvtrp 1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{67645734915., 0. , 0x00 , 0x01 , 0x00 }, {132120576. , 0. , 0x00 , 0x01 , 0x00 }, {68585259519., 0. , 0x01 , 0x01 , 0x00 }, {134217216. , 0. , 0x01 , 0x01 , 0x01 }, {68585259519., 0. , 0x01 , 0x01 , 0x00 }, {134217216. , 0. , 0x01 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x0F , 0x1F }, {0x12 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{66571993091., 0. , 0x00 , 0x01 , 0x00 }, {132120576. , 0. , 0x00 , 0x01 , 0x00 }, {131071. , 0. , 0x00 , 0x01 , 0x00 }, {68719345664., 0. , 0x00 , 0x01 , 0x01 }, {131071. , 0. , 0x00 , 0x01 , 0x00 }, {68719345664., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x10 , 0x1F }, {0x13 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{67645734915., 0. , 0x00 , 0x01 , 0x00 }, {125829120. , 0. , 0x00 , 0x01 , 0x00 }, {67654057987., 0. , 0x00 , 0x01 , 0x00 }, {1065418748. , 0. , 0x00 , 0x01 , 0x01 }, {16383. , 0. , 0x00 , 0x01 , 0x00 }, {68182605824., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x10 , 0x1F }, {0x13 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{67645734915., 0. , 0x00 , 0x01 , 0x00 }, {132120576. , 0. , 0x00 , 0x01 , 0x00 }, {68585259519., 0. , 0x01 , 0x01 , 0x00 }, {134217216. , 0. , 0x01 , 0x01 , 0x01 }, {68585259519., 0. , 0x01 , 0x01 , 0x00 }, {134217216. , 0. , 0x01 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x0F , 0x1F }, {0x12 , 0x22 }, {0x00 , 0x00 }, {262140. , 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{66571993091., 0. , 0x00 , 0x01 , 0x00 }, {132120576. , 0. , 0x00 , 0x01 , 0x00 }, {131071. , 0. , 0x00 , 0x01 , 0x00 }, {68719345664., 0. , 0x00 , 0x01 , 0x01 }, {131071. , 0. , 0x00 , 0x01 , 0x00 }, {68719345664., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x10 , 0x1F }, {0x13 , 0x22 }, {0x00 , 0x00 }, {262140. , 0. }, 0x00}, {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x16 , 0x02 , 0x02 , {{67645734915., 0. , 0x00 , 0x01 , 0x00 }, {125829120. , 0. , 0x00 , 0x01 , 0x00 }, {67654057987., 0. , 0x00 , 0x01 , 0x00 }, {1065418748. , 0. , 0x00 , 0x01 , 0x01 }, {16383. , 0. , 0x00 , 0x01 , 0x00 }, {68182605824., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x10 , 0x1F }, {0x13 , 0x22 }, {0x00 , 0x00 }, {524284. , 0. }, 0x00} }; memcpy(reg, &data[tm], sizeof(struct st_timing)); rst = OK; } return rst; } /* ccd timing values for hp3800 scanner */ static SANE_Int hp3800_timing_get(SANE_Int tm, struct st_timing *reg) { SANE_Int rst = ERROR; if ((tm < 20)&&(reg != NULL)) { /* Toshiba T2905 sensor timing values for each resolution and color mode */ struct st_timing data[] = { /* res , cnpp, {cvtrp 1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{8589934588. , 0. , 0x00 , 0x01 , 0x01 }, {68719476732., 0. , 0x00 , 0x01 , 0x01 }, {134217216. , 0. , 0x01 , 0x01 , 0x00 }, {68585259519., 0. , 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x0F , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{64692944895., 0. , 0x00 , 0x01 , 0x01 }, {66571993087., 0. , 0x00 , 0x01 , 0x01 }, {524287. , 0. , 0x00 , 0x01 , 0x00 }, {68718952448., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x10 , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {1069563840. , 0. , 0x00 , 0x01 , 0x00 }, {67649912895., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x02 , 0x21 }, {0x03 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {477225440. , 0. , 0x00 , 0x01 , 0x00 }, {68242251295., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x02 , 0x21 }, {0x04 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x0096, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {13743895344., 0. , 0x00 , 0x01 , 0x00 }, {54975581391., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x01 , 0x21 }, {0x02 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{8589934588. , 0. , 0x00 , 0x01 , 0x01 }, {68719476732., 0. , 0x00 , 0x01 , 0x01 }, {134217216. , 0. , 0x01 , 0x01 , 0x00 }, {68585259519., 0. , 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x0F , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{64692944895., 0. , 0x00 , 0x01 , 0x01 }, {66571993087., 0. , 0x00 , 0x01 , 0x01 }, {524287. , 0. , 0x00 , 0x01 , 0x00 }, {68718952448., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x10 , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {1069563840. , 0. , 0x00 , 0x01 , 0x00 }, {67649912895., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x02 , 0x21 }, {0x03 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {477225440. , 0. , 0x00 , 0x01 , 0x00 }, {68242251295., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x02 , 0x21 }, {0x04 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 0. , 0x00 , 0x01 , 0x01 }, {68719476733., 0. , 0x00 , 0x01 , 0x01 }, {266346464. , 0. , 0x00 , 0x01 , 0x00 }, {68453130271., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x01 , -1 , {0x04 , 0x21 }, {0x06 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{8589934588. , 8589934588. , 0x00 , 0x01 , 0x01 }, {68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {134217216. , 134217216. , 0x01 , 0x01 , 0x00 }, {68585259519., 68585259519., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x80FF , 0x01 , -1 , {0x0F , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{64692944895., 64692944895., 0x00 , 0x01 , 0x01 }, {66571993087., 66571993087., 0x00 , 0x01 , 0x01 }, {524287. , 524287. , 0x00 , 0x01 , 0x00 }, {68718952448., 68718952448., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x80FF , 0x01 , -1 , {0x10 , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {534781920. , 534781920. , 0x00 , 0x01 , 0x00 }, {68184694815., 68184694815., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x20FF , 0x01 , -1 , {0x05 , 0x21 }, {0x07 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {477225440. , 477225440. , 0x00 , 0x01 , 0x00 }, {68242251295., 68242251295., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x11FF , 0x01 , -1 , {0x02 , 0x21 }, {0x04 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x0096, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {13743895344., 13743895344., 0x00 , 0x01 , 0x00 }, {54975581391., 54975581391., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x110F , 0x01 , -1 , {0x01 , 0x21 }, {0x02 , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{8589934588. , 8589934588. , 0x00 , 0x01 , 0x01 }, {68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {134217216. , 134217216. , 0x01 , 0x01 , 0x00 }, {68585259519., 68585259519., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x80FF , 0x01 , -1 , {0x0F , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{64692944895., 64692944895., 0x00 , 0x01 , 0x01 }, {66571993087., 66571993087., 0x00 , 0x01 , 0x01 }, {524287. , 524287. , 0x00 , 0x01 , 0x00 }, {68718952448., 68718952448., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x80FF , 0x01 , -1 , {0x10 , 0x20 }, {0x11 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {534781920. , 534781920. , 0x00 , 0x01 , 0x00 }, {68184694815., 68184694815., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x20FF , 0x01 , -1 , {0x05 , 0x21 }, {0x07 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {477225440. , 477225440. , 0x00 , 0x01 , 0x00 }, {68242251295., 68242251295., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x110F , 0x01 , -1 , {0x02 , 0x21 }, {0x04 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x0096, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{68719476732., 68719476732., 0x00 , 0x01 , 0x01 }, {68719476733., 68719476733., 0x00 , 0x01 , 0x01 }, {13743895344., 13743895344., 0x00 , 0x01 , 0x00 }, {54975581391., 54975581391., 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0xFF , 0x110F , 0x01 , -1 , {0x01 , 0x21 }, {0x02 , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, }; memcpy(reg, &data[tm], sizeof(struct st_timing)); rst = OK; } return rst; } /* ccd timing values for hp3970 scanner */ static SANE_Int hp3970_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timing *reg) { SANE_Int rst = ERROR; if ((tm < 12)&&(reg != NULL)) { rst = OK; if (sensortype == CCD_SENSOR) { /* Toshiba T2952 sensor timing values for each resolution and color mode */ struct st_timing data[] = { /* res , cnpp, {cvtrp 1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ {0x0960, 0x0B, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {34376515584., 0. , 0x00 , 0x01 , 0x00 }, {8455716864. , 0. , 0x01 , 0x01 , 0x00 }, {60246982656., 0. , 0x01 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x24000, {0x04 , 0x09 }, {0x06 , 0x0B }, {0x00 , 0x00 }, {27481079808., 0. }, 0x00}, {0x04B0, 0x1A, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {64424511232., 0. , 0x00 , 0x01 , 0x00 }, {68711088128., 0. , 0x00 , 0x01 , 0x00 }, {8388352. , 0. , 0x00 , 0x01 , 0x01 }, {68719476480., 0. , 0x00 , 0x01 , 0x01 }, {68719476480., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x08 , 0x15 }, {0x0C , 0x18 }, {0x00 , 0x00 }, {33351135232., 33351135232.}, 0x01}, {0x0258, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {60129570816., 0. , 0x00 , 0x01 , 0x00 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {16773120. , 0. , 0x00 , 0x01 , 0x00 }, {68702699520., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x09 , 0x12 }, {0x0C , 0x14 }, {0x00 , 0x00 }, {64677150720., 0. }, 0x00}, {0x012C, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {51539611648., 0. , 0x00 , 0x01 , 0x00 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {1057222656. , 0. , 0x00 , 0x01 , 0x00 }, {67662249984., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x04 , 0x15 }, {0x06 , 0x17 }, {0x00 , 0x00 }, {8084643840. , 0. }, 0x00}, {0x00C8, 0x1D, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68182605888., 0. , 0x00 , 0x01 , 0x00 }, {68719476720., 0. , 0x00 , 0x01 , 0x01 }, {68719476720., 0. , 0x00 , 0x01 , 0x01 }, {16659267072., 0. , 0x00 , 0x01 , 0x00 }, {52060209600., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0A , 0x1B }, {0x0C , 0x1D }, {0x00 , 0x00 }, {4164816768. , 0. }, 0x00}, {0x0960, 0x0B, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {34376515584., 0. , 0x00 , 0x01 , 0x00 }, {8455716864. , 0. , 0x01 , 0x01 , 0x00 }, {60246982656., 0. , 0x01 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x24000, {0x04 , 0x09 }, {0x06 , 0x0B }, {0x00 , 0x00 }, {2113929216. , 0. }, 0x00}, {0x04B0, 0x1A, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {64424511232., 0. , 0x00 , 0x01 , 0x00 }, {68711088128., 0. , 0x00 , 0x01 , 0x00 }, {8388352. , 0. , 0x00 , 0x01 , 0x01 }, {68719476480., 0. , 0x00 , 0x01 , 0x01 }, {68719476480., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x08 , 0x15 }, {0x0C , 0x18 }, {0x00 , 0x00 }, {67104768. , 67104768. }, 0x01}, {0x0258, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {60129570816., 0. , 0x00 , 0x01 , 0x00 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {16773120. , 0. , 0x00 , 0x01 , 0x00 }, {68702699520., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x09 , 0x12 }, {0x0C , 0x14 }, {0x00 , 0x00 }, {268369920. , 0. }, 0x00}, {0x012C, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {51539611648., 0. , 0x00 , 0x01 , 0x00 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {68719472640., 0. , 0x00 , 0x01 , 0x01 }, {1057222656. , 0. , 0x00 , 0x01 , 0x00 }, {67662249984., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x04 , 0x15 }, {0x06 , 0x17 }, {0x00 , 0x00 }, {33546240. , 0. }, 0x00}, {0x00C8, 0x1D, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{68585258944., 0. , 0x00 , 0x01 , 0x00 }, {536870784. , 0. , 0x00 , 0x01 , 0x00 }, {16659267072., 0. , 0x00 , 0x01 , 0x00 }, {52060209600., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0A , 0x1B }, {0x0C , 0x1C }, {0x00 , 0x00 }, {4194176. , 0. }, 0x00}, {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {34359738368., 0. , 0x00 , 0x01 , 0x00 }, {68719476735., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x01 , 0x01 }, {7635497415. , 0. , 0x00 , 0x01 , 0x00 }, {61083979320., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x02 , 0x22 }, {0x03 , 0x23 }, {0x00 , 0x00 }, {2114445438. , 0. }, 0x00}, {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {34359738368., 0. , 0x00 , 0x01 , 0x00 }, {68719476735., 0. , 0x00 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x01 , 0x01 }, {7635497415. , 0. , 0x00 , 0x01 , 0x00 }, {61083979320., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x02 , 0x22 }, {0x03 , 0x23 }, {0x00 , 0x00 }, {524286. , 0. }, 0x00} }; memcpy(reg, &data[tm], sizeof(struct st_timing)); } else { /* Sony S575 sensor timing values for each resolution and color mode I haven't found any hp3970 scanner using sony sensor but windows drivers support this case */ struct st_timing data[] = { /* res , cnpp, {cvtrp1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ {0x0960, 0x0B, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{60112764928., 0. , 0x00 , 0x01 , 0x00 }, {34326183936., 0. , 0x00 , 0x01 , 0x00 }, {1056964608. , 0. , 0x01 , 0x01 , 0x00 }, {67645734912., 0. , 0x01 , 0x01 , 0x01 }, {1056964608. , 0. , 0x00 , 0x01 , 0x00 }, {67645734912., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x24000, {0x05 , 0x09 }, {0x07 , 0x0b }, {0x00 , 0x00 }, {27481079808., 0. }, 0x00}, {0x04B0, 0x1A, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{68316823296., 0. , 0x00 , 0x01 , 0x00 }, {42949672704., 0. , 0x00 , 0x01 , 0x00 }, {4194048. , 0. , 0x00 , 0x01 , 0x00 }, {68715282432., 0. , 0x00 , 0x01 , 0x01 }, {4194048. , 0. , 0x00 , 0x01 , 0x00 }, {68715282432., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x0B , 0x17 }, {0x0D , 0x19 }, {0x00 , 0x00 }, {16675567616., 16675567616.}, 0x01}, {0x0258, 0x17, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{67914166272., 0. , 0x00 , 0x01 , 0x00 }, {42949668864., 0. , 0x00 , 0x01 , 0x00 }, {16773120. , 0. , 0x00 , 0x01 , 0x00 }, {68702699520., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x09 , 0x15 }, {0x0B , 0x17 }, {0x00 , 0x00 }, {8084643840. , 0. }, 0x00}, {0x012C, 0x17, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{60129538048., 0. , 0x00 , 0x01 , 0x00 }, {34359730176., 0. , 0x00 , 0x01 , 0x00 }, {1057222656. , 0. , 0x00 , 0x01 , 0x00 }, {67662249984., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x04 , 0x15 }, {0x06 , 0x17 }, {0x00 , 0x00 }, {8084643840. , 0. }, 0x00}, {0x00C8, 0x1D, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{68585258944., 0. , 0x00 , 0x01 , 0x00 }, {536870784. , 0. , 0x00 , 0x01 , 0x00 }, {16659267072., 0. , 0x00 , 0x01 , 0x00 }, {52060209600., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0A , 0x1A }, {0x0C , 0x1C }, {0x00 , 0x00 }, {8329633536. , 0. }, 0x00}, {0x0960, 0x0B, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{60112764928., 0. , 0x00 , 0x01 , 0x00 }, {34326183936., 0. , 0x00 , 0x01 , 0x00 }, {1056964608. , 0. , 0x01 , 0x01 , 0x00 }, {67645734912., 0. , 0x01 , 0x01 , 0x01 }, {1056964608. , 0. , 0x00 , 0x01 , 0x00 }, {67645734912., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x24000, {0x05 , 0x09 }, {0x07 , 0x0B }, {0x00 , 0x00 }, {2113929216. , 0. }, 0x00}, {0x04B0, 0x1A, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{68316823296., 0. , 0x00 , 0x01 , 0x00 }, {42949672704., 0. , 0x00 , 0x01 , 0x00 }, {4194048. , 0. , 0x00 , 0x01 , 0x00 }, {68715282432., 0. , 0x00 , 0x01 , 0x01 }, {4194048. , 0. , 0x00 , 0x01 , 0x00 }, {68715282432., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x0B , 0x17 }, {0x0D , 0x19 }, {0x00 , 0x00 }, {33552384. , 33552384. }, 0x01}, {0x0258, 0x17, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{67914166272., 0. , 0x00 , 0x01 , 0x00 }, {42949668864., 0. , 0x00 , 0x01 , 0x00 }, {16773120. , 0. , 0x00 , 0x01 , 0x00 }, {68702699520., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x09 , 0x15 }, {0x0B , 0x17 }, {0x00 , 0x00 }, {33546240. , 0. }, 0x00}, {0x012C, 0x17, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{60129538048., 0. , 0x00 , 0x01 , 0x00 }, {34359730176., 0. , 0x00 , 0x01 , 0x00 }, {34359730176., 0. , 0x00 , 0x01 , 0x00 }, {67662249984., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x04 , 0x15 }, {0x06 , 0x17 }, {0x00 , 0x00 }, {33546240. , 0. }, 0x00}, {0x00C8, 0x1D, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68182605888., 0. , 0x00 , 0x01 , 0x00 }, {68719476720., 0. , 0x00 , 0x01 , 0x01 }, {68719476720., 0. , 0x00 , 0x01 , 0x01 }, {16659267072., 0. , 0x00 , 0x01 , 0x00 }, {52060209600., 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0A , 0x1A }, {0x0C , 0x1D }, {0x00 , 0x00 }, {4194176. , 0. }, 0x00}, {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{51539607551., 0. , 0x00 , 0x01 , 0x00 }, {34359738366., 0. , 0x00 , 0x01 , 0x00 }, {7635497415. , 0. , 0x00 , 0x01 , 0x00 }, {61083979320., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x02 , 0x22 }, {0x03 , 0x23 }, {0x00 , 0x00 }, {2114445438. , 0. }, 0x00}, {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x01 , 0x0F , {{51539607551., 0. , 0x00 , 0x01 , 0x00 }, {34359738366., 0. , 0x00 , 0x01 , 0x00 }, {7635497415. , 0. , 0x00 , 0x01 , 0x00 }, {61083979320., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x01 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x02 , 0x22 }, {0x03 , 0x23 }, {0x00 , 0x00 }, {524286. , 0. }, 0x00} }; memcpy(reg, &data[tm], sizeof(struct st_timing)); } } return rst; } /* ccd timing values for hp4370 scanner */ static SANE_Int hp4370_timing_get(SANE_Int tm, struct st_timing *reg) { SANE_Int rst = ERROR; if ((reg != NULL)&&(tm < 14)) { /* Toshiba T2958 sensor timing values for each resolution and color mode */ struct st_timing data[] = { /* res , cnpp, {cvtrp 1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2 , cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ {0x12C0, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869183., 17179869183., 0x00 , 0x01 , 0x01 }, {1073479680. , 1073479680., 0x01 , 0x01 , 0x00 }, {67645997055., 67645997055., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x5D5B , 0xBAB7 , 0x1A , -1 , {0x08 , 0x15 }, {0x0A , 0x17 }, {0x00 , 0x00 }, {8084644321. , 8084644321. }, 0x00}, {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869182., 0. , 0x00 , 0x01 , 0x01 }, {268434432. , 0. , 0x01 , 0x01 , 0x00 }, {68451042303., 0. , 0x01 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , -1 , {0x07 , 0x18 }, {0x0B , 0x1E }, {0x00 , 0x00 }, {67662254016., 0. }, 0x00}, {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68719475967., 0. , 0x00 , 0x01 , 0x01 }, {1048572. , 0. , 0x00 , 0x01 , 0x01 }, {68718428163., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x1F , 0x17 }, {0x21 , 0x19 }, {0x01 , 0x01 }, {34888349727., 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68719476731., 0. , 0x00 , 0x01 , 0x01 }, {4261672960. , 0. , 0x00 , 0x01 , 0x00 }, {64457803775., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , 0x05500, {0x00 , 0x1F }, {0x03 , 0x21 }, {0x00 , 0x00 }, {8457781752. , 0. }, 0x00}, {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {51808043007., 0. , 0x00 , 0x01 , 0x01 }, {8084644320. , 0. , 0x00 , 0x01 , 0x00 }, {60634832415., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , 0x05500, {0x09 , 0x20 }, {0x0A , 0x22 }, {0x00 , 0x00 }, {4228890876. , 0. }, 0x00}, {0x12C0, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869183., 17179869183., 0x00 , 0x01 , 0x01 }, {1073479680. , 1073479680., 0x01 , 0x01 , 0x00 }, {67645997055., 67645997055., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x5D5B , 0xBAB7 , 0x1A , -1 , {0x08 , 0x15 }, {0x0A , 0x17 }, {0x00 , 0x00 }, {33546240. , 33546240. }, 0x00}, {0x0960, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869182., 0. , 0x00 , 0x01 , 0x01 }, {268434432. , 0. , 0x01 , 0x01 , 0x00 }, {68451042303., 0. , 0x01 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , -1 , {0x07 , 0x18 }, {0x0B , 0x1E }, {0x00 , 0x00 }, {16777152. , 0. }, 0x00}, {0x04B0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68719475967., 0. , 0x00 , 0x01 , 0x01 }, {1048572. , 0. , 0x00 , 0x01 , 0x01 }, {68718428163., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x01 , 0x00 }, {0. , 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x1F , 0x17 }, {0x21 , 0x19 }, {0x01 , 0x01 }, {536868864. , 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {68719476731., 0. , 0x00 , 0x01 , 0x01 }, {4261672960. , 0. , 0x00 , 0x01 , 0x00 }, {64457803775., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , 0x05500, {0x00 , 0x1F }, {0x03 , 0x21 }, {0x00 , 0x00 }, {2097144. , 0. }, 0x00}, {0x012C, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x04 , 0x04 , {{0. , 0. , 0x00 , 0x01 , 0x00 }, {51808043007., 0. , 0x00 , 0x01 , 0x01 }, {8084644320. , 0. , 0x00 , 0x01 , 0x00 }, {60634832415., 0. , 0x00 , 0x01 , 0x01 }, {0. , 0. , 0x00 , 0x00 , 0x00 }, {0. , 0. , 0x00 , 0x00 , 0x00 }}, 0x00 , 0x00 , 0x1A , 0x05500, {0x09 , 0x20 }, {0x0A , 0x22 }, {0x00 , 0x00 }, {1048572. , 0. }, 0x00}, {0x12C0, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869183., 17179869183., 0x00 , 0x01 , 0x01 }, {1073479680. , 1073479680., 0x01 , 0x01 , 0x00 }, {67645997055., 67645997055., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x6977 , 0xD2EF , 0x1A , -1 , {0x07 , 0x15 }, {0x0A , 0x17 }, {0x00 , 0x00 }, {8084644321. , 8084644321. }, 0x00}, {0x12C0, 0x17, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {17179869183., 17179869183., 0x00 , 0x01 , 0x01 }, {1073479680. , 1073479680., 0x01 , 0x01 , 0x00 }, {67645997055., 67645997055., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x6977 , 0xD2EF , 0x1A , -1 , {0x07 , 0x15 }, {0x0A , 0x17 }, {0x00 , 0x00 }, {33546240. , 33546240. }, 0x00}, {0x12C0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {8589934591. , 8589934591. , 0x00 , 0x01 , 0x01 }, {134217216. , 134217216. , 0x01 , 0x01 , 0x00 }, {68585259519., 68585259519., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x765B , 0xECB7 , 0x1A , -1 , {0x07 , 0x1B }, {0x0D , 0x21 }, {0x00 , 0x00 }, {8457781752. , 8457781752. }, 0x00}, {0x12C0, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x05 , 0x0E , {{0. , 0. , 0x00 , 0x01 , 0x01 }, {8589934591. , 8589934591. , 0x00 , 0x01 , 0x01 }, {134217216. , 134217216. , 0x01 , 0x01 , 0x00 }, {68585259519., 68585259519., 0x01 , 0x01 , 0x01 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }, {68719476735., 0. , 0x00 , 0x00 , 0x00 }}, 0x765B , 0xECB7 , 0x1A , -1 , {0x07 , 0x1B }, {0x0D , 0x21 }, {0x00 , 0x00 }, {2097144. , 2097144. }, 0x00} }; memcpy(reg, &data[tm], sizeof(struct st_timing)); rst = OK; } return rst; } /* ccd timing values for ua4900 scanner */ static SANE_Int ua4900_timing_get(SANE_Int tm, struct st_timing *reg) { SANE_Int rst = ERROR; if ((tm < 10)&&(reg != NULL)) { /* Sony S575 sensor timing values for each resolution and color mode */ struct st_timing data[] = { /* res , cnpp, {cvtrp1 2 3 }, cvtrw, cvtrfpw, cvtrbpw, {{cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}, {cphp1 , cphp2, cphps, cphge, cphgo}}, cphbp2s, cphbp2e, clamps, clampe , {cdss1, cdss2}, {cdsc1, cdsc2}, {cdscs1, cdscs2}, {adcclkp 1 y 2 }, adcclkp2e */ {0x04b0, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{ 1073737728., 0. , 0x01 , 0x01 , 0x00 }, {67645739007., 0. , 0x01 , 0x01 , 0x01 }, {67645739007., 0. , 0x01 , 0x01 , 0x01 }, { 1073737728., 0. , 0x01 , 0x01 , 0x00 }, {25769803776., 0. , 0x00 , 0x01 , 0x00 }, { 62., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x08 , 0x1c }, {0x0A , 0x1e }, {0x00 , 0x00 }, {67662254016., 0. }, 0x00}, {0x0258, 0x23, {0x00, 0x00, 0x00}, 0x0F , 0x03 , 0x03 , {{ 262143., 0. , 0x00 , 0x01 , 0x00 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }, {68719214592., 0. , 0x00 , 0x01 , 0x01 }, { 262143., 3. , 0x00 , 0x01 , 0x00 }, { 2080374784., 0. , 0x00 , 0x01 , 0x00 }, {64424509455., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x10 , 0x1d }, {0x12 , 0x1f }, {0x00 , 0x00 }, {33831127008., 0. }, 0x00}, {0x012c, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{ 32767., 0. , 0x00 , 0x01 , 0x00 }, {68182605824., 0. , 0x00 , 0x01 , 0x01 }, { 2130837500., 0. , 0x00 , 0x01 , 0x01 }, {66588639235., 0. , 0x00 , 0x01 , 0x00 }, { 117440512., 0. , 0x00 , 0x01 , 0x00 }, {68182605825., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x12 , 0x1f }, {0x14 , 0x21 }, {0x00 , 0x00 }, { 8457781752., 0. }, 0x00}, {0x00c8, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{51539608575., 0. , 0x00 , 0x01 , 0x00 }, {16642998272., 0. , 0x00 , 0x01 , 0x01 }, { 2082408447., 0. , 0x00 , 0x01 , 0x01 }, {66637068288., 0. , 0x00 , 0x01 , 0x00 }, { 14680064., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x10 , 0x1f }, {0x12 , 0x21 }, {0x00 , 0x00 }, { 8457781752., 0. }, 0x00}, {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{51539608575., 0. , 0x00 , 0x01 , 0x00 }, {16642998272., 0. , 0x00 , 0x01 , 0x01 }, { 2082408447., 0. , 0x00 , 0x01 , 0x01 }, {66637068288., 0. , 0x00 , 0x01 , 0x00 }, { 14680064., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x10 , 0x1f }, {0x12 , 0x21 }, {0x00 , 0x00 }, { 8457781752., 0. }, 0x00}, {0x04b0, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{ 268434432., 0. , 0x01 , 0x01 , 0x00 }, {68451042303., 0. , 0x01 , 0x01 , 0x01 }, {68451042303., 0. , 0x01 , 0x01 , 0x01 }, { 268434432., 0. , 0x01 , 0x01 , 0x00 }, {51539607552., 0. , 0x00 , 0x01 , 0x00 }, {30. , 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x11000, {0x08 , 0x1d }, {0x09 , 0x1e }, {0x00 , 0x00 }, {16777152. , 0. }, 0x00}, {0x0258, 0x1d, {0x00, 0x00, 0x00}, 0x0f , 0x03 , 0x03 , {{ 2097088., 0. , 0x00 , 0x01 , 0x00 }, {68717379632., 0. , 0x00 , 0x01 , 0x01 }, {68717379632., 0. , 0x00 , 0x01 , 0x01 }, { 2097088., 3. , 0x00 , 0x01 , 0x00 }, { 1879048192., 0. , 0x00 , 0x01 , 0x00 }, {60129542592., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x05500, {0x0d , 0x16 }, {0x0f , 0x18 }, {0x00 , 0x00 }, {134213632. , 0. }, 0x00}, {0x012c, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{64424510463., 0. , 0x00 , 0x01 , 0x00 }, { 4278190080., 0. , 0x00 , 0x01 , 0x01 }, { 267390975., 0. , 0x00 , 0x01 , 0x01 }, {68452085760., 0. , 0x00 , 0x01 , 0x00 }, { 6291456., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x15 , 0x1f }, {0x17 , 0x21 }, {0x00 , 0x00 }, {2097144. , 0. }, 0x00}, {0x00C8, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{51539608575., 0. , 0x00 , 0x01 , 0x00 }, {16642998272., 0. , 0x00 , 0x01 , 0x01 }, { 2082408447., 0. , 0x00 , 0x01 , 0x01 }, {66637068288., 0. , 0x00 , 0x01 , 0x00 }, { 14680064., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x17 , 0x1f }, {0x19 , 0x21 }, {0x00 , 0x00 }, {2097144. , 0. }, 0x00}, {0x0064, 0x23, {0x00, 0x00, 0x00}, 0x1E , 0x03 , 0x03 , {{51539608575., 0. , 0x00 , 0x01 , 0x00 }, {16642998272., 0. , 0x00 , 0x01 , 0x01 }, { 2082408447., 0. , 0x00 , 0x01 , 0x01 }, {66637068288., 0. , 0x00 , 0x01 , 0x00 }, { 14680064., 0. , 0x00 , 0x01 , 0x00 }, {68652367872., 0. , 0x00 , 0x01 , 0x00 }}, 0x00 , 0x00 , 0x01 , 0x02700, {0x17 , 0x1f }, {0x19 , 0x21 }, {0x00 , 0x00 }, {2097144. , 0. }, 0x00} }; memcpy(reg, &data[tm], sizeof(struct st_timing)); rst = OK; } return rst; } static SANE_Int cfg_timing_get(SANE_Int sensortype, SANE_Int tm, struct st_timing *reg) { /* return timing values for current device */ SANE_Int rst = ERROR; switch(RTS_Debug->dev_model) { case BQ5550: rst = bq5550_timing_get(tm, reg); break; case UA4900: rst = ua4900_timing_get(tm, reg); break; case HP4370: case HPG3010: case HPG3110: rst = hp4370_timing_get(tm, reg); break; case HP3800: case HPG2710: rst = hp3800_timing_get(tm, reg); break; default: /* hp3970 and hp4070 */ rst = hp3970_timing_get(sensortype, tm, reg); break; } return rst; } /** SEC: Motor curves ---------- */ static SANE_Int *bq5550_motor() { SANE_Int *rst = NULL; SANE_Int steps[] = { /* motorcurve 1 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 20000 ,6323 ,4095 ,3270 ,2823 ,2533 ,2318 ,2151 ,2016 ,1905 ,1811 ,1730 ,1660 ,1599 ,1544 ,1494 ,1450 ,1409 ,1373 ,1339 ,1307 ,1278 ,1251 ,1225 ,1201 ,1179 ,1158 ,1138 ,1119 ,1101 ,1084 ,1067 ,1052 ,1037 ,1023 ,1009 ,996 ,984 ,972 ,960 ,949 ,938 ,928 ,918 ,909 ,899 ,890 ,882 ,873 ,865 ,857 ,849 ,842 ,835 ,828 ,821 ,814 ,807 ,801 ,795 ,789 ,783 ,777 ,772 ,766 ,761 ,756 ,751 ,746 ,741 ,736 ,731 ,727 ,722 ,718 ,714 ,709 ,705 ,701 ,697 ,693 ,690 ,686 ,682 ,678 ,675 ,671 ,668 ,665 ,661 ,658 ,655 ,652 ,649 ,645 ,642 ,640 ,637 ,634 ,631 ,628 ,625 ,623 ,620 ,617 ,615 ,612 ,610 ,607 ,605 ,602 ,600 ,597 ,595 ,593 ,591 ,588 ,586 ,584 ,582 ,580 ,577 ,575 ,573 ,571 ,569 ,567 ,565 ,563 ,562 ,560 ,558 ,556 ,554 ,552 ,550 ,549 ,547 ,545 ,543 ,542 ,540 ,538 ,537 ,535 ,534 ,532 ,530 ,529 ,527 ,526 ,524 ,523 ,521 ,520 ,518 ,517 ,515 ,514 ,513 ,511 ,510 ,508 ,507 ,506 ,504 ,503 ,502 ,501 ,499 ,498 ,497 ,495 ,494 ,493 ,492 ,491 ,489 ,488 ,487 ,486 ,485 ,484 ,482 ,481 ,480 ,479 ,478 ,477 ,476 ,475 ,474 ,473 ,472 ,470 ,469 ,468 ,467 ,466 ,465 ,464 ,463 ,462 ,461 ,460 ,460 ,459 ,458 ,457 ,456 ,455 ,454 ,453 ,452 ,451 ,450 ,449 ,449 ,448 ,447 ,446 ,445 ,444 ,443 ,443 ,442 ,441 ,440 ,439 ,438 ,438 ,437 ,436 ,435 ,434 ,434 ,433 ,432 ,431 ,431 ,430 ,429 ,428 ,428 ,427 ,426 ,425 ,425 ,424 ,423 ,422 ,422 ,421 ,420 ,420 ,419 ,418 ,418 ,417 ,416 ,416 ,415 ,414 ,414 ,413 ,412 ,412 ,411 ,410 ,410 ,409 ,408 ,408 ,407 ,407 ,406 ,405 ,405 ,404 ,404 ,403 ,402 ,402 ,401 ,401 ,400 ,399 ,399 ,398 ,398 ,397 ,397 ,396 ,395 ,395 ,394 ,394 ,393 ,393 ,392 ,392 ,391 ,390 ,390 ,389 ,389 ,388 ,388 ,387 ,387 ,386 ,386 ,385 ,385 ,384 ,384 ,383 ,383 ,382 ,382 ,381 ,381 ,380 ,380 ,379 ,379 ,378 ,378 ,377 ,377 ,377 ,376 ,376 ,375 ,375 ,374 ,374 ,373 ,373 ,372 ,372 ,372 ,371 ,371 ,370 ,370 ,369 ,369 ,368 ,368 ,368 ,367 ,367 ,366 ,366 ,365 ,365 ,365 ,364 ,364 ,363 ,363 ,363 ,362 ,362 ,361 ,361 ,361 ,360 ,360 ,359 ,359 ,359 ,358 ,358 ,357 ,357 ,357 ,356 ,356 ,356 ,355 ,355 ,354 ,354 ,354 ,353 ,353 ,353 ,352 ,352 ,351 ,351 ,351 ,350 ,350 ,350 ,349 ,349 ,349 ,348 ,348 ,348 ,347 ,347 ,347 ,346 ,346 ,346 ,345 ,345 ,345 ,344 ,344 ,344 ,343 ,343 ,343 ,342 ,342 ,342 ,341 ,341 ,341 ,340 ,340 ,340 ,339 ,339 ,339 ,338 ,338 ,338 ,337 ,337 ,337 ,337 ,336 ,336 ,336 ,335 ,335 ,335 ,334 ,334 ,334 ,334 ,333 ,333 ,333 ,332 ,332 ,332 ,332 ,331 ,331 ,331 ,330 ,330 ,330 ,330 ,329 ,329 ,329 ,328 ,328 ,328 ,328 ,327 ,327 ,327 ,326 ,326 ,326 ,326 ,325 ,325 ,325 ,325 ,324 ,324 ,324 ,324 ,323 ,323 ,323 ,323 ,322 ,322 ,322 ,321 ,321 ,321 ,321 ,320 ,320 ,320 ,320 ,319 ,319 ,319 ,319 ,318 ,318 ,318 ,318 ,317 ,317 ,317 ,317 ,317 ,316 ,316 ,316 ,316 ,315 ,315 ,315 ,315 ,314 ,314 ,314 ,314 ,313 ,313 ,313 ,313 ,313 ,312 ,312 ,312 ,312 ,311 ,311 ,311 ,311 ,311 ,310 ,310 ,310 ,310 ,309 ,309 ,309 ,309 ,309 ,308 ,308 ,308 ,308 ,307 ,307 ,307 ,307 ,307 ,306 ,306 ,306 ,306 ,306 ,305 ,305 ,305 ,305 ,305 ,304 ,304 ,304 ,304 ,303 ,303 ,303 ,303 ,303 ,302 ,302 ,302 ,302 ,302 ,301 ,301 ,301 ,301 ,301 ,300 ,300 ,300 ,300 ,300 ,300 ,299 ,299 ,299 ,299 ,299 ,298 ,298 ,298 ,298 ,298 ,297 ,297 ,297 ,297 ,297 ,297 ,296 ,296 ,296 ,296 ,296 ,295 ,295 ,295 ,295 ,295 ,295 ,294 ,294 ,294 ,294 ,294 ,293 ,293 ,293 ,293 ,293 ,293 ,292 ,292 ,292 ,292 ,292 ,292 ,291 ,291 ,291 ,291 ,291 ,290 ,290 ,290 ,290 ,290 ,290 ,289 ,289 ,289 ,289 ,289 ,289 ,288 ,288 ,288 ,288 ,288 ,288 ,288 ,287 ,287 ,287 ,287 ,287 ,287 ,286 ,286 ,286 ,286 ,286 ,286 ,285 ,285 ,285 ,285 ,285 ,285, 0, ACC_CURVE,CRV_SMEARING , 4000, 3877, 3377, 2777, 2127, 1724, 1449, 1250, 0, DEC_CURVE,CRV_NORMALSCAN, 479 ,500 ,547 ,607 ,682 ,766 ,865 ,950 ,1040 ,1200 ,1369 ,1580 ,1810 ,2087 ,2500 ,3048 ,3877 ,4818 ,5822 ,6896, 0, DEC_CURVE,CRV_SMEARING , 1250, 1449, 1724, 2127, 2777, 3377, 3877, 4000, 0, DEC_CURVE,CRV_BUFFERFULL, 479 ,500 ,547 ,607 ,682 ,766 ,865 ,950 ,1040 ,1200 ,1369 ,1580 ,1810 ,2087 ,2500 ,3048 ,3877 ,4818 ,5822 ,6896, 0, -1 }; rst = (SANE_Int *)malloc(sizeof(steps)); if (rst != NULL) memcpy(rst, &steps, sizeof(steps)); return rst; } static SANE_Int *hp4370_motor() { SANE_Int *rst = NULL; SANE_Int steps[] = { /* motorcurve 1 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 2000, 1984, 1968, 1953, 1937, 1921, 1906, 1890, 1874, 1859, 1843, 1827, 1812, 1796, 1781, 1765, 1749, 1734, 1715, 1700, 1684, 1669, 1653, 1637, 1622, 1606, 1590, 1572, 1556, 1541, 1525, 1510, 1494, 1478, 1463, 1447, 1431, 1416, 1400, 1384, 1366, 1351, 1335, 1319, 1304, 1288, 1272, 1257, 1241, 1225, 1210, 1194, 1179, 1160, 1145, 1129, 1113, 1098, 1082, 1066, 1051, 1035, 1017, 1001, 986, 970, 954, 939, 923, 907, 892, 876, 861, 845, 829, 814, 798, 782, 767, 749, 0, ACC_CURVE,CRV_PARKHOME , 4705, 2913, 2253, 1894, 1662, 1498, 1374, 1276, 1196, 1129, 1073, 1024, 981, 944, 910, 880, 852, 827, 804, 783, 764, 746, 729, 713, 699, 685, 672, 659, 648, 637, 626, 616, 607, 598, 589, 581, 573, 565, 558, 551, 544, 538, 532, 526, 520, 514, 509, 503, 500, 0, ACC_CURVE,CRV_SMEARING , 200, 12, 14, 16, 0, DEC_CURVE,CRV_NORMALSCAN, 749, 1166, 1583, 2000, 0, DEC_CURVE,CRV_PARKHOME , 500, 503, 509, 514, 520, 526, 532, 538, 544, 551, 558, 565, 573, 581, 589, 598, 607, 616, 626, 637, 648, 659, 672, 685, 699, 713, 729, 746, 764, 783, 804, 827, 852, 880, 910, 944, 981, 1024, 1073, 1129, 1196, 1276, 1374, 1498, 1662, 1894, 2253, 2913, 4705, 0, DEC_CURVE,CRV_SMEARING , 300, 234, 167, 100, 0, DEC_CURVE,CRV_BUFFERFULL, 1100, 867, 633, 400, 0, -2, /* motorcurve 2 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, ACC_CURVE,CRV_PARKHOME , 4705, 2913, 2253, 1894, 1662, 1498, 1374, 1276, 1196, 1129, 1073, 1024, 981, 944, 910, 880, 852, 827, 804, 783, 764, 746, 729, 713, 699, 685, 672, 659, 648, 637, 626, 616, 607, 598, 589, 581, 573, 565, 558, 551, 544, 538, 532, 526, 520, 514, 509, 503, 500, 0, ACC_CURVE,CRV_SMEARING , 200, 12, 14, 16, 0, DEC_CURVE,CRV_NORMALSCAN, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, DEC_CURVE,CRV_PARKHOME , 500, 503, 509, 514, 520, 526, 532, 538, 544, 551, 558, 565, 573, 581, 589, 598, 607, 616, 626, 637, 648, 659, 672, 685, 699, 713, 729, 746, 764, 783, 804, 827, 852, 880, 910, 944, 981, 1024, 1073, 1129, 1196, 1276, 1374, 1498, 1662, 1894, 2253, 2913, 4705, 0, DEC_CURVE,CRV_SMEARING , 300, 234, 167, 100, 0, DEC_CURVE,CRV_BUFFERFULL, 1100, 867, 633, 400, 0, -2, /* motorcurve 3 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 5360, 3655, 2855, 2422, 2142, 1944, 1795, 1678, 1582, 1503, 1434, 1374, 0, ACC_CURVE,CRV_PARKHOME , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 1458, 1384, 1319, 1264, 1214, 1170, 1131, 1096, 1063, 1034, 1006, 981, 958, 937, 916, 897, 880, 863, 847, 832, 818, 805, 792, 780, 769, 758, 747, 737, 727, 718, 709, 700, 692, 684, 677, 669, 662, 655, 648, 642, 636, 629, 624, 618, 612, 607, 602, 596, 591, 587, 582, 577, 573, 568, 564, 560, 556, 552, 548, 544, 540, 537, 533, 530, 526, 523, 520, 516, 513, 510, 507, 504, 501, 498, 496, 493, 490, 488, 485, 482, 480, 477, 475, 472, 470, 468, 466, 463, 461, 459, 457, 455, 453, 450, 448, 446, 444, 443, 441, 439, 437, 435, 433, 431, 430, 428, 426, 425, 423, 421, 420, 418, 416, 415, 413, 412, 410, 409, 407, 406, 405, 403, 402, 400, 399, 398, 396, 395, 394, 392, 391, 390, 389, 387, 386, 385, 384, 382, 381, 380, 379, 378, 377, 376, 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354, 353, 353, 352, 351, 350, 349, 348, 0, ACC_CURVE,CRV_SMEARING , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 0, DEC_CURVE,CRV_NORMALSCAN, 1374, 1434, 1503, 1582, 1678, 1795, 1944, 2142, 2422, 2855, 3655, 5360, 0, DEC_CURVE,CRV_PARKHOME , 348, 351, 353, 356, 359, 362, 365, 368, 371, 374, 378, 381, 385, 389, 392, 396, 400, 405, 409, 413, 418, 423, 428, 433, 439, 444, 450, 457, 463, 470, 477, 485, 493, 501, 510, 520, 530, 540, 552, 564, 577, 591, 607, 624, 642, 662, 684, 709, 737, 769, 805, 847, 897, 958, 1034, 1131, 1264, 1458, 1791, 2628, 5360, 0, DEC_CURVE,CRV_SMEARING , 1547, 1654, 1791, 1973, 2229, 2628, 3362, 5360, 0, DEC_CURVE,CRV_BUFFERFULL, 1374, 1434, 1503, 1582, 1678, 1795, 1944, 2142, 2422, 2855, 3655, 5360, 0, -2, /* motorcurve 4 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, ACC_CURVE,CRV_PARKHOME , 4705, 2888, 2234, 1878, 1648, 1485, 1362, 1265, 1186, 1120, 1064, 1016, 973, 936, 903, 873, 845, 821, 798, 777, 758, 740, 723, 708, 693, 679, 666, 654, 643, 632, 621, 612, 602, 593, 585, 576, 569, 561, 554, 547, 540, 534, 528, 522, 516, 510, 505, 499, 494, 490, 485, 480, 476, 471, 467, 463, 459, 455, 451, 448, 444, 440, 437, 434, 430, 427, 424, 421, 418, 415, 412, 409, 407, 404, 401, 399, 396, 394, 391, 389, 387, 384, 382, 380, 378, 376, 374, 371, 369, 367, 366, 364, 362, 360, 358, 356, 354, 353, 351, 349, 348, 346, 344, 343, 341, 340, 338, 337, 335, 334, 332, 331, 329, 328, 327, 325, 324, 323, 321, 320, 319, 318, 316, 315, 314, 313, 312, 311, 309, 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 285, 284, 283, 282, 281, 280, 279, 279, 278, 277, 276, 275, 275, 274, 273, 272, 272, 271, 270, 269, 269, 268, 267, 267, 266, 265, 264, 264, 263, 262, 262, 261, 260, 260, 259, 259, 258, 257, 257, 256, 255, 255, 254, 254, 253, 252, 252, 251, 251, 250, 249, 249, 248, 248, 247, 247, 246, 246, 245, 245, 244, 243, 243, 242, 242, 241, 241, 240, 240, 239, 239, 238, 238, 237, 237, 237, 236, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 231, 230, 230, 229, 229, 228, 228, 228, 227, 227, 226, 226, 225, 225, 225, 224, 224, 223, 223, 223, 222, 222, 222, 221, 221, 220, 220, 220, 219, 219, 219, 218, 218, 217, 217, 217, 216, 216, 216, 215, 215, 215, 214, 214, 214, 213, 213, 213, 212, 212, 212, 211, 211, 211, 210, 210, 210, 209, 209, 209, 208, 208, 208, 207, 207, 207, 207, 206, 206, 206, 205, 205, 205, 204, 204, 204, 204, 203, 203, 203, 202, 202, 202, 202, 201, 201, 201, 200, 200, 200, 200, 199, 199, 199, 199, 198, 198, 198, 198, 197, 197, 197, 196, 196, 196, 196, 195, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 193, 192, 192, 192, 192, 192, 191, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 184, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 171, 171, 171, 171, 0, ACC_CURVE,CRV_SMEARING , 4705, 3056, 2724, 2497, 1498, 1498, 1374, 1276, 1196, 1130, 1073, 1025, 982, 944, 911, 880, 853, 828, 805, 784, 764, 746, 730, 714, 699, 685, 675, 0, DEC_CURVE,CRV_NORMALSCAN, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, DEC_CURVE,CRV_PARKHOME , 171, 172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 177, 178, 179, 179, 180, 180, 181, 182, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 195, 195, 196, 197, 198, 199, 199, 200, 201, 202, 203, 204, 205, 206, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228, 230, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246, 247, 249, 251, 253, 254, 256, 258, 260, 262, 264, 266, 268, 271, 273, 275, 278, 280, 282, 285, 288, 290, 293, 296, 299, 302, 305, 309, 312, 316, 319, 323, 327, 331, 336, 340, 345, 350, 355, 360, 365, 371, 377, 384, 391, 398, 406, 414, 422, 432, 441, 452, 463, 476, 489, 504, 520, 538, 558, 580, 605, 633, 667, 706, 752, 810, 883, 979, 1116, 1326, 1714, 4705, 0, DEC_CURVE,CRV_SMEARING , 675, 685, 699, 714, 730, 746, 764, 784, 805, 828, 853, 880, 911, 944, 982, 1025, 1073, 1130, 1196, 1276, 1374, 1498, 1498, 2497, 2724, 3056, 4705, 0, DEC_CURVE,CRV_BUFFERFULL, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, -2, /* motorcurve 5 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 3763, 3763, 3763, 3763, 3763, 3763, 2444, 2178, 1997, 1198, 1198, 1098, 1020, 956, 903, 858, 819, 785, 754, 727, 703, 681, 662, 644, 626, 610, 596, 582, 571, 558, 547, 537, 527, 518, 509, 500, 492, 485, 478, 471, 464, 458, 452, 446, 440, 435, 430, 425, 420, 415, 410, 407, 402, 398, 394, 391, 386, 383, 380, 376, 373, 369, 366, 364, 360, 357, 355, 352, 349, 347, 344, 341, 338, 337, 334, 332, 329, 328, 325, 323, 321, 319, 317, 315, 313, 311, 310, 308, 306, 304, 302, 301, 299, 297, 295, 294, 293, 291, 290, 288, 286, 285, 284, 283, 281, 280, 278, 277, 275, 275, 274, 272, 271, 270, 268, 267, 266, 265, 264, 263, 262, 261, 259, 258, 257, 257, 256, 255, 254, 253, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 243, 242, 241, 240, 239, 239, 238, 237, 236, 235, 235, 234, 233, 232, 231, 230, 230, 230, 229, 228, 228, 227, 226, 225, 225,224, 223, 222, 222, 221, 221, 221, 220, 219, 219, 218, 217, 217, 216, 215, 215, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 206, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 190, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 185, 185, 185, 185, 185, 185, 184, 184, 183, 183, 183, 182, 182, 182, 181, 181, 180, 180, 180, 179, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 171, 170, 170, 170, 169, 169, 169, 169, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 101, 101, 101, 101, 101, 101, 101, 101,101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, ACC_CURVE,CRV_PARKHOME , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, ACC_CURVE,CRV_SMEARING , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, DEC_CURVE,CRV_NORMALSCAN, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 345, 348, 351, 354, 357, 360, 363, 366, 369, 372, 375, 378, 381, 384, 387, 391, 395, 399, 403, 407, 411, 415, 419, 422, 425, 429, 433, 437, 441, 445, 449, 453, 458, 463, 468, 473, 478, 483, 489, 495, 501, 507, 514, 521, 528, 536, 544, 553, 562, 572, 582, 593, 604, 616, 629, 643, 658, 674, 692, 711, 732, 755, 781, 810, 843, 880, 923, 974,1035, 1110, 1205, 1331, 1510, 1796, 2368, 3400, 4922, 0, DEC_CURVE,CRV_PARKHOME , 138, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, DEC_CURVE,CRV_SMEARING , 138, 139, 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 153, 154, 154, 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 162, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, 167, 168, 168, 168, 168, 169, 169, 169, 170, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 174, 175, 175, 175, 176, 176, 176, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 184, 184, 184, 185, 185, 185, 185, 185, 186, 186, 186, 187, 187, 188, 188, 188, 189, 189, 190, 190, 191, 191, 191, 192, 192, 193, 193, 194, 194, 194, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 202, 202, 203, 203, 203, 203, 204, 204, 205, 205, 206, 207, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 212, 213, 213, 214, 214, 215, 216, 216, 217, 218, 218, 219, 220, 220, 221, 221, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 230, 230, 231, 232, 233, 233, 234, 235, 236, 237, 238, 239, 239, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 266, 267, 269, 270, 271, 273, 274, 275, 276, 277, 279, 280, 282, 283, 284, 285, 287, 289, 290, 292, 293, 294, 296, 298, 300, 301, 302, 304, 306, 308, 310, 311, 313, 315, 318, 320, 321, 323, 326, 328, 330, 332, 335, 337, 339, 342, 344, 347, 349, 352, 355, 358, 361, 364, 366, 370, 374, 376, 380, 383, 387, 391, 394, 399, 402, 407, 411, 416, 420, 425, 430, 436, 441, 446, 453, 458, 464, 472, 478, 485, 493, 501, 509, 518, 527, 537, 548, 559, 571, 583, 597, 611, 626, 644, 662, 682, 704, 728, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, DEC_CURVE,CRV_BUFFERFULL, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 115, 117, 119, 121, 122, 124, 127, 130, 132, 135, 139, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, -2, /* motorcurve 6 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, ACC_CURVE,CRV_PARKHOME , 4705, 2888, 2234, 1878, 1648, 1485, 1362, 1265, 1186, 1120, 1064, 1016, 973, 936, 903, 873, 845, 821, 798, 777, 758, 740, 723, 708, 693, 679, 666, 654, 643, 632, 621, 612, 602, 593, 585, 576, 569, 561, 554, 547, 540, 534, 528, 522, 516, 510, 505, 499, 494, 490, 485, 480, 476, 471, 467, 463, 459, 455, 451, 448, 444, 440, 437, 434, 430, 427, 424, 421, 418, 415, 412, 409, 407, 404, 401, 399, 396, 394, 391, 389, 387, 384, 382, 380, 378, 376, 374, 371, 369, 367, 366, 364, 362, 360, 358, 356, 354, 353, 351, 349, 348, 346, 344, 343, 341, 340, 338, 337, 335, 334, 332, 331, 329, 328, 327, 325, 324, 323, 321, 320, 319, 318, 316, 315, 314, 313, 312, 311, 309, 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 285, 284, 283, 282, 281, 280, 279, 279, 278, 277, 276, 275, 275, 274, 273, 272, 272, 271, 270, 269, 269, 268, 267, 267, 266, 265, 264, 264, 263, 262, 262, 261, 260, 260, 259, 259, 258, 257, 257, 256, 255, 255, 254, 254, 253, 252, 252, 251, 251, 250, 249, 249, 248, 248, 247, 247, 246, 246, 245, 245, 244, 243, 243, 242, 242, 241, 241, 240, 240, 239, 239, 238, 238, 237, 237, 237, 236, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 231, 230, 230, 229, 229, 228, 228, 228, 227, 227, 226, 226, 225, 225, 225, 224, 224, 223, 223, 223, 222, 222, 222, 221, 221, 220, 220, 220, 219, 219, 219, 218, 218, 217, 217, 217, 216, 216, 216, 215, 215, 215, 214, 214, 214, 213, 213, 213, 212, 212, 212, 211, 211, 211, 210, 210, 210, 209, 209, 209, 208, 208, 208, 207, 207, 207, 207, 206, 206, 206, 205, 205, 205, 204, 204, 204, 204, 203, 203, 203, 202, 202, 202, 202, 201, 201, 201, 200, 200, 200, 200, 199, 199, 199, 199, 198, 198, 198, 198, 197, 197, 197, 196, 196, 196, 196, 195, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 193, 192, 192, 192, 192, 192, 191, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 184, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 171, 171, 171, 171, 0, ACC_CURVE,CRV_SMEARING , 4705, 3056, 2724, 2497, 1498, 1498, 1374, 1276, 1196, 1130, 1073, 1025, 982, 944, 911, 880, 853, 828, 805, 784, 764, 746, 730, 714, 699, 685, 675, 0, DEC_CURVE,CRV_NORMALSCAN, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, DEC_CURVE,CRV_PARKHOME , 171, 172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 177, 178, 179, 179, 180, 180, 181, 182, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 195, 195, 196, 197, 198, 199, 199, 200, 201, 202, 203, 204, 205, 206, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228, 230, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246, 247, 249, 251, 253, 254, 256, 258, 260, 262, 264, 266, 268, 271, 273, 275, 278, 280, 282, 285, 288, 290, 293, 296, 299, 302, 305, 309, 312, 316, 319, 323, 327, 331, 336, 340, 345, 350, 355, 360, 365, 371, 377, 384, 391, 398, 406, 414, 422, 432, 441, 452, 463, 476, 489, 504, 520, 538, 558, 580, 605, 633, 667, 706, 752, 810, 883, 979, 1116, 1326, 1714, 4705, 0, DEC_CURVE,CRV_SMEARING , 675, 685, 699, 714, 730, 746, 764, 784, 805, 828, 853, 880, 911, 944, 982, 1025, 1073, 1130, 1196, 1276, 1374, 1498, 1498, 2497, 2724, 3056, 4705, 0, DEC_CURVE,CRV_BUFFERFULL, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, -2, /* motorcurve 7 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 3763, 3763, 3763, 3763, 3763, 3763, 2444, 2178, 1997, 1198, 1198, 1098, 1020, 956, 903, 858, 819, 785, 754, 727, 703, 681, 662, 644, 626, 610, 596, 582, 571, 558, 547, 537, 527, 518, 509, 500, 492, 485, 478, 471, 464, 458, 452, 446, 440, 435, 430, 425, 420, 415, 410, 407, 402, 398, 394, 391, 386, 383, 380, 376, 373, 369, 366, 364, 360, 357, 355, 352, 349, 347, 344, 341, 338, 337, 334, 332, 329, 328, 325, 323, 321, 319, 317, 315, 313, 311, 310, 308, 306, 304, 302, 301, 299, 297, 295, 294, 293, 291, 290, 288, 286, 285, 284, 283, 281, 280, 278, 277, 275, 275, 274, 272, 271, 270, 268, 267, 266, 265, 264, 263, 262, 261, 259, 258, 257, 257, 256, 255, 254, 253, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 243, 242, 241, 240, 239, 239, 238, 237, 236, 235, 235, 234, 233, 232, 231, 230, 230, 230, 229, 228, 228, 227, 226, 225, 225,224, 223, 222, 222, 221, 221, 221, 220, 219, 219, 218, 217, 217, 216, 215, 215, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 206, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 190, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 185, 185, 185, 185, 185, 185, 184, 184, 183, 183, 183, 182, 182, 182, 181, 181, 180, 180, 180, 179, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 171, 170, 170, 170, 169, 169, 169, 169, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 101, 101, 101, 101, 101, 101, 101, 101,101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, ACC_CURVE,CRV_PARKHOME , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, ACC_CURVE,CRV_SMEARING , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, DEC_CURVE,CRV_NORMALSCAN, 522, 522, 528, 536, 544, 553, 562, 572, 582, 593, 604, 616, 629, 643, 658, 674, 692, 711, 732, 755, 781, 810, 843, 880, 923, 974, 1035, 1110, 1205, 1331, 1510, 1796, 2368, 3400, 4922, 0, DEC_CURVE,CRV_PARKHOME , 138, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, DEC_CURVE,CRV_SMEARING , 138, 139, 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 153, 154, 154, 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 162, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, 167, 168, 168, 168, 168, 169, 169, 169, 170, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 174, 175, 175, 175, 176, 176, 176, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 184, 184, 184, 185, 185, 185, 185, 185, 186, 186, 186, 187, 187, 188, 188, 188, 189, 189, 190, 190, 191, 191, 191, 192, 192, 193, 193, 194, 194, 194, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 202, 202, 203, 203, 203, 203, 204, 204, 205, 205, 206, 207, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 212, 213, 213, 214, 214, 215, 216, 216, 217, 218, 218, 219, 220, 220, 221, 221, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 230, 230, 231, 232, 233, 233, 234, 235, 236, 237, 238, 239, 239, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 266, 267, 269, 270, 271, 273, 274, 275, 276, 277, 279, 280, 282, 283, 284, 285, 287, 289, 290, 292, 293, 294, 296, 298, 300, 301, 302, 304, 306, 308, 310, 311, 313, 315, 318, 320, 321, 323, 326, 328, 330, 332, 335, 337, 339, 342, 344, 347, 349, 352, 355, 358, 361, 364, 366, 370, 374, 376, 380, 383, 387, 391, 394, 399, 402, 407, 411, 416, 420, 425, 430, 436, 441, 446, 453, 458, 464, 472, 478, 485, 493, 501, 509, 518, 527, 537, 548, 559, 571, 583, 597, 611, 626, 644, 662, 682, 704, 728, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, DEC_CURVE,CRV_BUFFERFULL, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 115, 117, 119, 121, 122, 124, 127, 130, 132, 135, 139, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, -2, /* motorcurve 8 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 1046, 1046, 1046, 1046, 1046, 1046, 647, 501, 421, 370, 333, 305, 284, 266, 251, 239, 228, 218, 210, 202, 196, 190, 184, 179, 174, 170, 166, 162, 159, 155, 152, 149, 147, 144, 142, 139, 137, 135, 133, 131, 129, 127, 126, 124, 123, 121, 120, 118, 117, 116, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 100, 99, 98, 97, 96, 96, 95, 94, 94, 93, 92, 92, 91, 91, 90, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 82, 81, 81, 80, 80, 79, 79, 79, 78, 78, 78, 77, 77, 76, 76, 76, 75, 75, 75, 74, 74, 74, 74, 73, 73, 73, 72, 72, 72, 71, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 64, 64, 64, 64, 63, 63, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 23, 0, ACC_CURVE,CRV_PARKHOME , 1045, 678, 604, 554, 332, 332, 304, 283, 265, 250, 238, 227, 217, 209, 201, 195, 189, 183, 178,173, 169, 165, 161, 158, 154, 151, 148, 146, 143, 141, 138, 136, 134, 132, 130, 128, 126, 125, 123, 122, 120, 119, 117, 116, 115, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103,102, 101, 100, 99, 99, 98, 97, 96, 95, 95, 94, 93, 93, 92, 91, 91, 90, 90, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 81, 80, 80, 79, 79, 78, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 0, ACC_CURVE,CRV_SMEARING , 1045, 678, 604, 554, 332, 332, 304, 283, 265, 250, 238, 227, 217, 209, 201, 195, 189, 183, 178,173, 169, 165, 161, 158, 154, 151, 148, 146, 143, 141, 138, 136, 134, 132, 130, 128, 126, 125, 123, 122, 120, 119, 117, 116, 115, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103,102, 101, 100, 99, 99, 98, 97, 96, 95, 95, 94, 93, 93, 92, 91, 91, 90, 90, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 81, 80, 80, 79, 79, 78, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 0, DEC_CURVE,CRV_NORMALSCAN, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, DEC_CURVE,CRV_PARKHOME , 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, DEC_CURVE,CRV_SMEARING , 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 81, 81, 81, 82, 82, 83, 83, 84, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 96, 96, 97, 98, 99, 99, 100, 101, 102, 103, 104, 105, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 118, 119, 120, 122, 123, 125, 127, 128, 130, 132, 134, 136, 138, 140, 142, 145, 147, 150, 153, 156, 159, 163, 167, 171, 175, 180, 185, 190, 196, 203, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, DEC_CURVE,CRV_BUFFERFULL, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, -1 }; rst = (SANE_Int *)malloc(sizeof(steps)); if (rst != NULL) memcpy(rst, &steps, sizeof(steps)); return rst; } static SANE_Int *hp3970_motor() { SANE_Int *rst = NULL; SANE_Int steps[] = { /* motorcurve 1 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 2000, 1984, 1968, 1953, 1937, 1921, 1906, 1890, 1874, 1859, 1843, 1827, 1812, 1796, 1781, 1765, 1749, 1734, 1715, 1700, 1684, 1669, 1653, 1637, 1622, 1606, 1590, 1572, 1556, 1541, 1525, 1510, 1494, 1478, 1463, 1447, 1431, 1416, 1400, 1384, 1366, 1351, 1335, 1319, 1304, 1288, 1272, 1257, 1241, 1225, 1210, 1194, 1179, 1160, 1145, 1129, 1113, 1098, 1082, 1066, 1051, 1035, 1017, 1001, 986, 970, 954, 939, 923, 907, 892, 876, 861, 845, 829, 814, 798, 782, 767, 749, 0, ACC_CURVE,CRV_PARKHOME , 4705, 2913, 2253, 1894, 1662, 1498, 1374, 1276, 1196, 1129, 1073, 1024, 981, 944, 910, 880, 852, 827, 804, 783, 764, 746, 729, 713, 699, 685, 672, 659, 648, 637, 626, 616, 607, 598, 589, 581, 573, 565, 558, 551, 544, 538, 532, 526, 520, 514, 509, 503, 500, 0, ACC_CURVE,CRV_SMEARING , 200, 12, 14, 16, 0, DEC_CURVE,CRV_NORMALSCAN, 749, 1166, 1583, 2000, 0, DEC_CURVE,CRV_PARKHOME , 500, 503, 509, 514, 520, 526, 532, 538, 544, 551, 558, 565, 573, 581, 589, 598, 607, 616, 626, 637, 648, 659, 672, 685, 699, 713, 729, 746, 764, 783, 804, 827, 852, 880, 910, 944, 981, 1024, 1073, 1129, 1196, 1276, 1374, 1498, 1662, 1894, 2253, 2913, 4705, 0, DEC_CURVE,CRV_SMEARING , 300, 234, 167, 100, 0, DEC_CURVE,CRV_BUFFERFULL, 1100, 867, 633, 400, 0, -2, /* motorcurve 2 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, ACC_CURVE,CRV_PARKHOME , 4705, 2913, 2253, 1894, 1662, 1498, 1374, 1276, 1196, 1129, 1073, 1024, 981, 944, 910, 880, 852, 827, 804, 783, 764, 746, 729, 713, 699, 685, 672, 659, 648, 637, 626, 616, 607, 598, 589, 581, 573, 565, 558, 551, 544, 538, 532, 526, 520, 514, 509, 503, 500, 0, ACC_CURVE,CRV_SMEARING , 200, 12, 14, 16, 0, DEC_CURVE,CRV_NORMALSCAN, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, DEC_CURVE,CRV_PARKHOME , 500, 503, 509, 514, 520, 526, 532, 538, 544, 551, 558, 565, 573, 581, 589, 598, 607, 616, 626, 637, 648, 659, 672, 685, 699, 713, 729, 746, 764, 783, 804, 827, 852, 880, 910, 944, 981, 1024, 1073, 1129, 1196, 1276, 1374, 1498, 1662, 1894, 2253, 2913, 4705, 0, DEC_CURVE,CRV_SMEARING , 300, 234, 167, 100, 0, DEC_CURVE,CRV_BUFFERFULL, 1100, 867, 633, 400, 0, -2, /* motorcurve 3 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 5360, 3655, 2855, 2422, 2142, 1944, 1795, 1678, 1582, 1503, 1434, 1374, 0, ACC_CURVE,CRV_PARKHOME , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 1458, 1384, 1319, 1264, 1214, 1170, 1131, 1096, 1063, 1034, 1006, 981, 958, 937, 916, 897, 880, 863, 847, 832, 818, 805, 792, 780, 769, 758, 747, 737, 727, 718, 709, 700, 692, 684, 677, 669, 662, 655, 648, 642, 636, 629, 624, 618, 612, 607, 602, 596, 591, 587, 582, 577, 573, 568, 564, 560, 556, 552, 548, 544, 540, 537, 533, 530, 526, 523, 520, 516, 513, 510, 507, 504, 501, 498, 496, 493, 490, 488, 485, 482, 480, 477, 475, 472, 470, 468, 466, 463, 461, 459, 457, 455, 453, 450, 448, 446, 444, 443, 441, 439, 437, 435, 433, 431, 430, 428, 426, 425, 423, 421, 420, 418, 416, 415, 413, 412, 410, 409, 407, 406, 405, 403, 402, 400, 399, 398, 396, 395, 394, 392, 391, 390, 389, 387, 386, 385, 384, 382, 381, 380, 379, 378, 377, 376, 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354, 353, 353, 352, 351, 350, 349, 348, 0, ACC_CURVE,CRV_SMEARING , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 0, DEC_CURVE,CRV_NORMALSCAN, 1374, 1434, 1503, 1582, 1678, 1795, 1944, 2142, 2422, 2855, 3655, 5360, 0, DEC_CURVE,CRV_PARKHOME , 348, 351, 353, 356, 359, 362, 365, 368, 371, 374, 378, 381, 385, 389, 392, 396, 400, 405, 409, 413, 418, 423, 428, 433, 439, 444, 450, 457, 463, 470, 477, 485, 493, 501, 510, 520, 530, 540, 552, 564, 577, 591, 607, 624, 642, 662, 684, 709, 737, 769, 805, 847, 897, 958, 1034, 1131, 1264, 1458, 1791, 2628, 5360, 0, DEC_CURVE,CRV_SMEARING , 1547, 1654, 1791, 1973, 2229, 2628, 3362, 5360, 0, DEC_CURVE,CRV_BUFFERFULL, 1374, 1434, 1503, 1582, 1678, 1795, 1944, 2142, 2422, 2855, 3655, 5360, 0, -2, /* motorcurve 4 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 4705, 2664, 2061, 1732, 1521, 1370, 1257, 1167, 1094, 1033, 982, 937, 898, 864, 833, 805, 780, 757, 736, 717, 699, 683, 667, 653, 640, 627, 615, 604, 593, 583, 574, 564, 556, 547, 540, 532, 525, 518, 511, 505, 499, 493, 487, 481, 476, 471, 466, 461, 456, 452, 447, 443, 439, 435, 431, 427, 424, 420, 417, 413, 410, 407, 403, 400, 397, 394, 391, 389, 386, 383, 381, 378, 375, 373, 371, 368, 366, 364, 361, 359, 357, 355, 353, 351, 349, 347, 345, 343, 341, 339, 338, 336, 334, 332, 331, 329, 327, 326, 324, 323, 321, 320, 318, 317, 315, 314, 312, 311, 310, 308, 307, 306, 304, 303, 302, 301, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 270, 269, 268, 267, 266, 265, 264, 264, 263, 262, 261, 260, 260, 259, 258, 257, 257, 256, 255, 255, 254, 253, 252, 252, 251, 250, 250, 249, 248, 248, 247, 246, 246, 245, 244, 244, 243, 242, 242, 241, 241, 240, 239, 239, 238, 238, 237, 237, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 230, 230, 229, 229, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 216, 215, 215, 214, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 210, 210, 209, 209, 208, 208, 208, 207, 207, 207, 206, 206, 206, 205, 205, 204, 204, 204, 203, 203, 203, 202, 202, 202, 201, 201, 201, 200, 200, 200, 199, 199, 199, 198, 198, 198, 197, 197, 197, 197, 196, 196, 196, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 192, 192, 192, 192, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 183, 183, 183, 183, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 171, 171, 171, 0, ACC_CURVE,CRV_PARKHOME , 4705, 2888, 2234, 1878, 1648, 1485, 1362, 1265, 1186, 1120, 1064, 1016, 973, 936, 903, 873, 845, 821, 798, 777, 758, 740, 723, 708, 693, 679, 666, 654, 643, 632, 621, 612, 602, 593, 585, 576, 569, 561, 554, 547, 540, 534, 528, 522, 516, 510, 505, 499, 494, 490, 485, 480, 476, 471, 467, 463, 459, 455, 451, 448, 444, 440, 437, 434, 430, 427, 424, 421, 418, 415, 412, 409, 407, 404, 401, 399, 396, 394, 391, 389, 387, 384, 382, 380, 378, 376, 374, 371, 369, 367, 366, 364, 362, 360, 358, 356, 354, 353, 351, 349, 348, 346, 344, 343, 341, 340, 338, 337, 335, 334, 332, 331, 329, 328, 327, 325, 324, 323, 321, 320, 319, 318, 316, 315, 314, 313, 312, 311, 309, 308, 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 285, 284, 283, 282, 281, 280, 279, 279, 278, 277, 276, 275, 275, 274, 273, 272, 272, 271, 270, 269, 269, 268, 267, 267, 266, 265, 264, 264, 263, 262, 262, 261, 260, 260, 259, 259, 258, 257, 257, 256, 255, 255, 254, 254, 253, 252, 252, 251, 251, 250, 249, 249, 248, 248, 247, 247, 246, 246, 245, 245, 244, 243, 243, 242, 242, 241, 241, 240, 240, 239, 239, 238, 238, 237, 237, 237, 236, 236, 235, 235, 234, 234, 233, 233, 232, 232, 231, 231, 231, 230, 230, 229, 229, 228, 228, 228, 227, 227, 226, 226, 225, 225, 225, 224, 224, 223, 223, 223, 222, 222, 222, 221, 221, 220, 220, 220, 219, 219, 219, 218, 218, 217, 217, 217, 216, 216, 216, 215, 215, 215, 214, 214, 214, 213, 213, 213, 212, 212, 212, 211, 211, 211, 210, 210, 210, 209, 209, 209, 208, 208, 208, 207, 207, 207, 207, 206, 206, 206, 205, 205, 205, 204, 204, 204, 204, 203, 203, 203, 202, 202, 202, 202, 201, 201, 201, 200, 200, 200, 200, 199, 199, 199, 199, 198, 198, 198, 198, 197, 197, 197, 196, 196, 196, 196, 195, 195, 195, 195, 194, 194, 194, 194, 193, 193, 193, 193, 192, 192, 192, 192, 192, 191, 191, 191, 191, 190, 190, 190, 190, 189, 189, 189, 189, 189, 188, 188, 188, 188, 187, 187, 187, 187, 187, 186, 186, 186, 186, 186, 185, 185, 185, 185, 184, 184, 184, 184, 184, 183, 183, 183, 183, 183, 182, 182, 182, 182, 182, 181, 181, 181, 181, 181, 180, 180, 180, 180, 180, 180, 179, 179, 179, 179, 179, 178, 178, 178, 178, 178, 177, 177, 177, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 175, 175, 174, 174, 174, 174, 174, 174, 173, 173, 173, 173, 173, 173, 172, 172, 172, 172, 172, 172, 171, 171, 171, 171, 0, ACC_CURVE,CRV_SMEARING , 4705, 3056, 2724, 2497, 1498, 1498, 1374, 1276, 1196, 1130, 1073, 1025, 982, 944, 911, 880, 853, 828, 805, 784, 764, 746, 730, 714, 699, 685, 675, 0, DEC_CURVE,CRV_NORMALSCAN, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, DEC_CURVE,CRV_PARKHOME , 171, 172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 177, 178, 179, 179, 180, 180, 181, 182, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 194, 195, 195, 196, 197, 198, 199, 199, 200, 201, 202, 203, 204, 205, 206, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228, 230, 231, 232, 234, 235, 237, 238, 240, 241, 243, 244, 246, 247, 249, 251, 253, 254, 256, 258, 260, 262, 264, 266, 268, 271, 273, 275, 278, 280, 282, 285, 288, 290, 293, 296, 299, 302, 305, 309, 312, 316, 319, 323, 327, 331, 336, 340, 345, 350, 355, 360, 365, 371, 377, 384, 391, 398, 406, 414, 422, 432, 441, 452, 463, 476, 489, 504, 520, 538, 558, 580, 605, 633, 667, 706, 752, 810, 883, 979, 1116, 1326, 1714, 4705, 0, DEC_CURVE,CRV_SMEARING , 675, 685, 699, 714, 730, 746, 764, 784, 805, 828, 853, 880, 911, 944, 982, 1025, 1073, 1130, 1196, 1276, 1374, 1498, 1498, 2497, 2724, 3056, 4705, 0, DEC_CURVE,CRV_BUFFERFULL, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 184, 184, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210, 211, 213, 214, 215, 217, 218, 219, 221, 222, 224, 225, 227, 228, 230, 232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 258, 260, 262, 265, 268, 270, 273, 276, 279, 282, 285, 289, 292, 296, 299, 303, 307, 311, 316, 320, 325, 330, 335, 341, 347, 353, 359, 366, 373, 381, 390, 398, 408, 418, 429, 441, 455, 469, 485, 503, 523, 545, 571, 601, 636, 678, 730, 796, 883, 1005, 1195, 1544, 4705, 0, -2, /* motorcurve 5 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 3763, 3763, 3763, 3763, 3763, 3763, 2444, 2178, 1997, 1198, 1198, 1098, 1020, 956, 903, 858, 819, 785, 754, 727, 703, 681, 662, 644, 626, 610, 596, 582, 571, 558, 547, 537, 527, 518, 509, 500, 492, 485, 478, 471, 464, 458, 452, 446, 440, 435, 430, 425, 420, 415, 410, 407, 402, 398, 394, 391, 386, 383, 380, 376, 373, 369, 366, 364, 360, 357, 355, 352, 349, 347, 344, 341, 338, 337, 334, 332, 329, 328, 325, 323, 321, 319, 317, 315, 313, 311, 310, 308, 306, 304, 302, 301, 299, 297, 295, 294, 293, 291, 290, 288, 286, 285, 284, 283, 281, 280, 278, 277, 275, 275, 274, 272, 271, 270, 268, 267, 266, 265, 264, 263, 262, 261, 259, 258, 257, 257, 256, 255, 254, 253, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 243, 242, 241, 240, 239, 239, 238, 237, 236, 235, 235, 234, 233, 232, 231, 230, 230, 230, 229, 228, 228, 227, 226, 225, 225,224, 223, 222, 222, 221, 221, 221, 220, 219, 219, 218, 217, 217, 216, 215, 215, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 206, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 190, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 185, 185, 185, 185, 185, 185, 184, 184, 183, 183, 183, 182, 182, 182, 181, 181, 180, 180, 180, 179, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 171, 170, 170, 170, 169, 169, 169, 169, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 159, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 138, 138, 138, 138, 138, 138, 137, 137, 137, 137, 137, 137, 137, 136, 136, 136, 136, 136, 136, 136, 135, 135, 135, 135, 135, 135, 135, 134, 134, 134, 134, 134, 134, 134, 134, 133, 133, 133, 133, 133, 133, 133, 133, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 130, 130, 130, 130, 130, 130, 130, 130, 129, 129, 129, 129, 129, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 126, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 101, 101, 101, 101, 101, 101, 101, 101, 101,101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, ACC_CURVE,CRV_PARKHOME , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, ACC_CURVE,CRV_SMEARING , 3763, 2330, 1803, 1515, 1330, 1198, 1099, 1021, 957, 904, 859, 819, 785, 755, 728, 704, 682, 662, 644, 626, 611, 597, 583, 571, 559, 548, 537, 527, 518, 509, 501, 493, 485, 478, 472, 464, 458, 453, 446, 441, 436, 430, 425, 420, 416, 411, 407, 402, 399, 394, 391, 387, 383, 380, 376, 374, 370, 366, 364, 361, 358, 355, 352, 349, 347, 344, 342, 339, 337, 335, 332, 330, 328, 326, 323, 321, 320, 318, 315, 313, 311, 310, 308, 306, 304, 302, 301, 300, 298, 296, 294, 293, 292, 290, 289, 287, 285, 284, 283, 282, 280, 279, 277, 276, 275, 274, 273, 271, 270, 269, 267, 266, 266, 265, 263, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 239, 239, 238, 237, 236, 235, 234, 233, 233, 232, 231, 230, 230, 230, 229, 228, 227, 227, 226, 225, 224, 224, 223, 222, 221, 221, 221, 220, 220, 219, 218, 218, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 212, 211, 211, 210, 209, 209, 208, 208, 207, 207, 206, 205, 205, 204, 204, 203, 203, 203, 203, 202, 202, 201, 201, 200, 200, 199, 199, 198, 198, 197, 197, 196, 196, 195, 195, 194, 194, 194, 194, 194, 193, 193, 192, 192, 191, 191, 191, 190, 190, 189, 189, 188, 188, 188, 187, 187, 186, 186, 186, 185, 185, 185, 185, 185, 184, 184, 184, 183, 183, 182, 182, 182, 181, 181, 181, 180, 180, 180, 179, 179, 178, 178, 178, 177, 177, 177, 176, 176, 176, 176, 176, 176, 175, 175, 175, 174, 174, 174, 174, 173, 173, 173, 172, 172, 172, 171, 171, 171, 170, 170, 170, 170, 169, 169, 169, 168, 168, 168, 168, 167, 167, 167, 167, 167, 167, 167, 166, 166, 166, 166, 165, 165, 165, 165, 164, 164, 164, 163, 163, 163, 163, 162, 162, 162, 162, 161, 161, 161, 161, 160, 160, 160, 160, 160, 159, 159, 159, 159, 158, 158, 158, 158, 158, 158, 158, 158, 157, 157, 157, 157, 157, 156, 156, 156, 156, 155, 155, 155, 155, 155, 154, 154, 154, 154, 154, 153, 153, 153, 153, 153, 152, 152, 152, 152, 152, 151, 151, 151, 151, 151, 150, 150, 150, 150, 150, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 148, 148, 148, 148, 148, 148, 147, 147, 147, 147, 147, 147, 146, 146, 146, 146, 146, 145, 145, 145, 145, 145, 145, 144, 144, 144, 144, 144, 144, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 141, 141, 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 139, 139, 139, 139, 139, 139, 139, 138, 0, DEC_CURVE,CRV_NORMALSCAN, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 92, 92, 92, 92, 93, 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 115, 117, 119, 121, 122, 124, 127, 130, 132, 135, 139, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, DEC_CURVE,CRV_PARKHOME , 138, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, DEC_CURVE,CRV_SMEARING , 138, 139, 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 153, 154, 154, 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 158, 158, 158, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 162, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, 167, 168, 168, 168, 168, 169, 169, 169, 170, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 174, 175, 175, 175, 176, 176, 176, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 184, 184, 184, 185, 185, 185, 185, 185, 186, 186, 186, 187, 187, 188, 188, 188, 189, 189, 190, 190, 191, 191, 191, 192, 192, 193, 193, 194, 194, 194, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 202, 202, 203, 203, 203, 203, 204, 204, 205, 205, 206, 207, 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 212, 213, 213, 214, 214, 215, 216, 216, 217, 218, 218, 219, 220, 220, 221, 221, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, 230, 230, 231, 232, 233, 233, 234, 235, 236, 237, 238, 239, 239, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 266, 267, 269, 270, 271, 273, 274, 275, 276, 277, 279, 280, 282, 283, 284, 285, 287, 289, 290, 292, 293, 294, 296, 298, 300, 301, 302, 304, 306, 308, 310, 311, 313, 315, 318, 320, 321, 323, 326, 328, 330, 332, 335, 337, 339, 342, 344, 347, 349, 352, 355, 358, 361, 364, 366, 370, 374, 376, 380, 383, 387, 391, 394, 399, 402, 407, 411, 416, 420, 425, 430, 436, 441, 446, 453, 458, 464, 472, 478, 485, 493, 501, 509, 518, 527, 537, 548, 559, 571, 583, 597, 611, 626, 644, 662, 682, 704, 728, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, DEC_CURVE,CRV_BUFFERFULL, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 94, 94, 95, 95, 95, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 113, 115, 117, 119, 121, 122, 124, 127, 130, 132, 135, 139, 142, 146, 149, 153, 158, 162, 167, 171, 176, 180, 186, 193, 202, 209, 216, 223, 232, 243, 254, 266, 279, 292, 306, 320, 335, 337, 351, 367, 380, 396, 414, 437, 464, 493, 520, 549, 583, 611, 644, 675, 711, 755, 785, 819, 859, 904, 957, 1021, 1099, 1198, 1330, 1515, 1803, 2330, 3763, 0, -2, /* motorcurve 6 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 23999, 0, ACC_CURVE,CRV_PARKHOME , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 1458, 1384, 1319, 1264, 1214, 1170, 1131, 1096, 1063, 1034, 1006, 981, 958, 937, 916, 897, 880, 863, 847, 832, 818, 805, 792, 780, 769, 758, 747, 737, 727, 718, 709, 700, 692, 0, ACC_CURVE,CRV_SMEARING , 23999, 0, DEC_CURVE,CRV_NORMALSCAN, 23999, 0, DEC_CURVE,CRV_PARKHOME , 692, 700, 709, 718, 727, 737, 747, 758, 769, 780, 792, 805, 818, 832, 847, 863, 880, 897, 916, 937, 958, 981, 1006, 1034, 1063, 1096, 1131, 1170, 1214, 1264, 1319, 1384, 1458, 1547, 1654, 1791, 1973, 2229, 2628, 3362, 5360, 0, DEC_CURVE,CRV_SMEARING , 23999, 0, DEC_CURVE,CRV_BUFFERFULL, 23999, 0, -2, /* motorcurve 7 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 6667, 0, ACC_CURVE,CRV_PARKHOME , 5360, 3362, 2628, 2229, 1973, 1791, 1654, 1547, 1458, 1384, 1319, 1264, 1214, 1170, 1131, 1096, 1063, 1034, 1006, 981, 958, 937, 916, 897, 880, 863, 847, 832, 818, 805, 792, 780, 769, 758, 747, 737, 727, 718, 709, 700, 692, 0, ACC_CURVE,CRV_SMEARING , 6667, 0, DEC_CURVE,CRV_NORMALSCAN, 6667, 0, DEC_CURVE,CRV_PARKHOME , 692, 700, 709, 718, 727, 737, 747, 758, 769, 780, 792, 805, 818, 832, 847, 863, 880, 897, 916, 937, 958, 981, 1006, 1034, 1063, 1096, 1131, 1170, 1214, 1264, 1319, 1384, 1458, 1547, 1654, 1791, 1973, 2229, 2628, 3362, 5360, 0, DEC_CURVE,CRV_SMEARING , 6667, 0, DEC_CURVE,CRV_BUFFERFULL, 6667, 0, -2, /* motorcurve 8 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN, 1046, 1046, 1046, 1046, 1046, 1046, 647, 501, 421, 370, 333, 305, 284, 266, 251, 239, 228, 218, 210, 202, 196, 190, 184, 179, 174, 170, 166, 162, 159, 155, 152, 149, 147, 144, 142, 139, 137, 135, 133, 131, 129, 127, 126, 124, 123, 121, 120, 118, 117, 116, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 100, 99, 98, 97, 96, 96, 95, 94, 94, 93, 92, 92, 91, 91, 90, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 82, 81, 81, 80, 80, 79, 79, 79, 78, 78, 78, 77, 77, 76, 76, 76, 75, 75, 75, 74, 74, 74, 74, 73, 73, 73, 72, 72, 72, 71, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 64, 64, 64, 64, 63, 63, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 23, 0, ACC_CURVE,CRV_PARKHOME , 1045, 678, 604, 554, 332, 332, 304, 283, 265, 250, 238, 227, 217, 209, 201, 195, 189, 183, 178,173, 169, 165, 161, 158, 154, 151, 148, 146, 143, 141, 138, 136, 134, 132, 130, 128, 126, 125, 123, 122, 120, 119, 117, 116, 115, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103,102, 101, 100, 99, 99, 98, 97, 96, 95, 95, 94, 93, 93, 92, 91, 91, 90, 90, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 81, 80, 80, 79, 79, 78, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 0, ACC_CURVE,CRV_SMEARING , 1045, 678, 604, 554, 332, 332, 304, 283, 265, 250, 238, 227, 217, 209, 201, 195, 189, 183, 178,173, 169, 165, 161, 158, 154, 151, 148, 146, 143, 141, 138, 136, 134, 132, 130, 128, 126, 125, 123, 122, 120, 119, 117, 116, 115, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103,102, 101, 100, 99, 99, 98, 97, 96, 95, 95, 94, 93, 93, 92, 91, 91, 90, 90, 89, 88, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 81, 80, 80, 79, 79, 78, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 73, 72, 72, 72, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, 68, 67, 67, 67, 67, 66, 66, 66, 66, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59, 59, 59, 58, 58, 58, 58, 58, 58, 58, 57, 57, 57, 57, 57, 57, 57, 56, 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 54, 54, 54, 54, 54, 54, 54, 54, 53, 53, 53, 53, 53, 53, 53, 53, 53, 52, 52, 52, 52, 52, 52, 52, 52, 52, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 0, DEC_CURVE,CRV_NORMALSCAN, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, DEC_CURVE,CRV_PARKHOME , 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, DEC_CURVE,CRV_SMEARING , 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 81, 81, 81, 82, 82, 83, 83, 84, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 96, 96, 97, 98, 99, 99, 100, 101, 102, 103, 104, 105, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 118, 119, 120, 122, 123, 125, 127, 128, 130, 132, 134, 136, 138, 140, 142, 145, 147, 150, 153, 156, 159, 163, 167, 171, 175, 180, 185, 190, 196, 203, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, DEC_CURVE,CRV_BUFFERFULL, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 53, 54, 57, 59, 61, 63, 65, 68, 71, 75, 78, 82, 86, 90, 94, 94, 98, 103, 106, 111, 116, 122, 130, 138, 145, 153, 163, 171, 180, 188, 198, 211, 219, 228, 239, 252, 267, 284, 306, 334, 370, 422, 502, 648, 1045, 0, -1 }; rst = (SANE_Int *)malloc(sizeof(steps)); if (rst != NULL) memcpy(rst, &steps, sizeof(steps)); return rst; } static SANE_Int *hp3800_motor() { SANE_Int *rst = NULL; SANE_Int steps[] = { /* motorcurve 1 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,2000,1984,1968,1953,1937,1921,1906,1890,1874,1859,1843,1827,1812,1796,1781,1765,1749,1734,1715,1700,1684,1669,1653,1637,1622,1606,1590,1572,1556,1541,1525,1510,1494,1478,1463,1447,1431,1416,1400,1384,1366,1351,1335,1319,1304,1288,1272,1257,1241,1225,1210,1194,1179,1160,1145,1129,1113,1098,1082,1066,1051,1035,1017,1001,986,970,954,939,923,907,892,876,861,845,829,814,798,782,767,749, 0, ACC_CURVE,CRV_PARKHOME ,4705,2913,2253,1894,1662,1498,1374,1276,1196,1129,1073,1024,981,944,910,880,852,827,804,783,764,746,729,713,699,685,672,659,648,637,626,616,607,598,589,581,573,565,558,551,544,538,532,526,520,514,509,503,500, 0, ACC_CURVE,CRV_SMEARING ,200,12,14,16, 0, DEC_CURVE,CRV_NORMALSCAN,749,1166,1583,2000, 0, DEC_CURVE,CRV_PARKHOME ,500,503,509,514,520,526,532,538,544,551,558,565,573,581,589,598,607,616,626,637,648,659,672,685,699,713,729,746,764,783,804,827,852,880,910,944,981,1024,1073,1129,1196,1276,1374,1498,1662,1894,2253,2913,4705, 0, DEC_CURVE,CRV_SMEARING ,300,234,167,100, 0, DEC_CURVE,CRV_BUFFERFULL,1100,867,633,400, 0, -2, /* motorcurve 2 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,4705,2664,2061,1732,1521,1370,1257,1167,1094,1033,982,937,898,864,833,805,780,757,736,717,699,683,667,653,640,627,615,604,593,583,574,564,556,547,540,532,525,518,511,505,499,493,487,481,476,471,466,461,456,452,447,443,439,435,431,427,424,420,417,413,410,407,403,400,397,394,391,389,386,383,381,378,375,373,371,368,366,364,361,359,357,355,353,351,349,347,345,343,341,339,338,336,334,332,331,329,327,326,324,323,321,320,318,317,315,314,312,311,310,308,307,306,304,303,302,301,299,298,297,296,295,293,292,291,290,289,288,287,286,285,284,283,282,281,280,279,278,277,276,275,274,273,272,271,270,270,269,268,267,266,265,264,264,263,262,261,260,260,259,258,257,257,256,255,255,254,253,252,252,251,250,250,249,248,248,247,246,246,245,244,244,243,242,242,241,241,240,239,239,238,238,237,237,236,235,235,234,234,233,233,232,232,231,231,230,230,229,229,228,227,227,227,226,226,225,225,224,224,223,223,222,222,221,221,220,220,219,219,219,218,218,217,217,216,216,216,215,215,214,214,214,213,213,212,212,212,211,211,210,210,210,209,209,208,208,208,207,207,207,206,206,206,205,205,204,204,204,203,203,203,202,202,202,201,201,201,200,200,200,199,199,199,198,198,198,197,197,197,197,196,196,196,195,195,195,194,194,194,194,193,193,193,192,192,192,192,191,191,191,190,190,190,190,189,189,189,188,188,188,188,187,187,187,187,186,186,186,186,185,185,185,185,184,184,184,184,183,183,183,183,182,182,182,182,181,181,181,181,181,180,180,180,180,179,179,179,179,178,178,178,178,178,177,177,177,177,177,176,176,176,176,175,175,175,175,175,174,174,174,174,174,173,173,173,173,173,172,172,172,172,172,171,171,171, 0, ACC_CURVE,CRV_PARKHOME ,4705,2913,2253,1894,1662,1498,1374,1276,1196,1129,1073,1024,981,944,910,880,852,827,804,783,764,746,729,713,699,685,672,659,648,637,626,616,607,598,589,581,573,565,558,551,544,538,532,526,520,514,509,503,500, 0, ACC_CURVE,CRV_SMEARING ,200,12,14,16, 0, DEC_CURVE,CRV_NORMALSCAN,171,172,172,173,174,174,175,176,176,177,178,178,179,180,181,181,182,183,184,184,185,186,187,188,189,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,207,208,209,210,211,213,214,215,217,218,219,221,222,224,225,227,228,230,232,233,235,237,239,241,243,245,247,249,251,253,255,258,260,262,265,268,270,273,276,279,282,285,289,292,296,299,303,307,311,316,320,325,330,335,341,347,353,359,366,373,381,390,398,408,418,429,441,455,469,485,503,523,545,571,601,636,678,730,796,883,1005,1195,1544,4705, 0, DEC_CURVE,CRV_PARKHOME ,500,503,509,514,520,526,532,538,544,551,558,565,573,581,589,598,607,616,626,637,648,659,672,685,699,713,729,746,764,783,804,827,852,880,910,944,981,1024,1073,1129,1196,1276,1374,1498,1662,1894,2253,2913,4705, 0, DEC_CURVE,CRV_SMEARING ,300,234,167,100, 0, DEC_CURVE,CRV_BUFFERFULL,1100,867,633,400, 0, -2, /* motorcurve 3 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,5360,3655,2855,2422,2142,1944,1795,1678,1582,1503,1434,1374, 0, ACC_CURVE,CRV_PARKHOME ,5360,3362,2628,2229,1973,1791,1654,1547,1458,1384,1319,1264,1214,1170,1131,1096,1063,1034,1006,981,958,937,916,897,880,863,847,832,818,805,792,780,769,758,747,737,727,718,709,700,692,684,677,669,662,655,648,642,636,629,624,618,612,607,602,596,591,587,582,577,573,568,564,560,556,552,548,544,540,537,533,530,526,523,520,516,513,510,507,504,501,498,496,493,490,488,485,482,480,477,475,472,470,468,466,463,461,459,457,455,453,450,448,446,444,443,441,439,437,435,433,431,430,428,426,425,423,421,420,418,416,415,413,412,410,409,407,406,405,403,402,400,399,398,396,395,394,392,391,390,389,387,386,385,384,382,381,380,379,378,377,376,374,373,372,371,370,369,368,367,366,365,364,363,362,361,360,359,358,357,356,355,354,353,353,352,351,350,349,348, 0, ACC_CURVE,CRV_SMEARING ,5360,3362,2628,2229,1973,1791,1654,1547, 0, DEC_CURVE,CRV_NORMALSCAN,1374,1434,1503,1582,1678,1795,1944,2142,2422,2855,3655,5360, 0, DEC_CURVE,CRV_PARKHOME ,348,351,353,356,359,362,365,368,371,374,378,381,385,389,392,396,400,405,409,413,418,423,428,433,439,444,450,457,463,470,477,485,493,501,510,520,530,540,552,564,577,591,607,624,642,662,684,709,737,769,805,847,897,958,1034,1131,1264,1458,1791,2628,5360, 0, DEC_CURVE,CRV_SMEARING ,1547,1654,1791,1973,2229,2628,3362,5360, 0, DEC_CURVE,CRV_BUFFERFULL,1374,1434,1503,1582,1678,1795,1944,2142,2422,2855,3655,5360, 0, -2, /* motorcurve 4 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,4705,2664,2061,1732,1521,1370,1257,1167,1094,1033,982,937,898,864,833,805,780,757,736,717,699,683,667,653,640,627,615,604,593,583,574,564,556,547,540,532,525,518,511,505,499,493,487,481,476,471,466,461,456,452,447,443,439,435,431,427,424,420,417,413,410,407,403,400,397,394,391,389,386,383,381,378,375,373,371,368,366,364,361,359,357,355,353,351,349,347,345,343,341,339,338,336,334,332,331,329,327,326,324,323,321,320,318,317,315,314,312,311,310,308,307,306,304,303,302,301,299,298,297,296,295,293,292,291,290,289,288,287,286,285,284,283,282,281,280,279,278,277,276,275,274,273,272,271,270,270,269,268,267,266,265,264,264,263,262,261,260,260,259,258,257,257,256,255,255,254,253,252,252,251,250,250,249,248,248,247,246,246,245,244,244,243,242,242,241,241,240,239,239,238,238,237,237,236,235,235,234,234,233,233,232,232,231,231,230,230,229,229,228,227,227,227,226,226,225,225,224,224,223,223,222,222,221,221,220,220,219,219,219,218,218,217,217,216,216,216,215,215,214,214,214,213,213,212,212,212,211,211,210,210,210,209,209,208,208,208,207,207,207,206,206,206,205,205,204,204,204,203,203,203,202,202,202,201,201,201,200,200,200,199,199,199,198,198,198,197,197,197,197,196,196,196,195,195,195,194,194,194,194,193,193,193,192,192,192,192,191,191,191,190,190,190,190,189,189,189,188,188,188,188,187,187,187,187,186,186,186,186,185,185,185,185,184,184,184,184,183,183,183,183,182,182,182,182,181,181,181,181,181,180,180,180,180,179,179,179,179,178,178,178,178,178,177,177,177,177,177,176,176,176,176,175,175,175,175,175,174,174,174,174,174,173,173,173,173,173,172,172,172,172,172,171,171,171, 0, ACC_CURVE,CRV_PARKHOME ,4705,2888,2234,1878,1648,1485,1362,1265,1186,1120,1064,1016,973,936,903,873,845,821,798,777,758,740,723,708,693,679,666,654,643,632,621,612,602,593,585,576,569,561,554,547,540,534,528,522,516,510,505,499,494,490,485,480,476,471,467,463,459,455,451,448,444,440,437,434,430,427,424,421,418,415,412,409,407,404,401,399,396,394,391,389,387,384,382,380,378,376,374,371,369,367,366,364,362,360,358,356,354,353,351,349,348,346,344,343,341,340,338,337,335,334,332,331,329,328,327,325,324,323,321,320,319,318,316,315,314,313,312,311,309,308,307,306,305,304,303,302,301,300,299,298,297,296,295,294,293,292,291,290,289,288,287,286,285,285,284,283,282,281,280,279,279,278,277,276,275,275,274,273,272,272,271,270,269,269,268,267,267,266,265,264,264,263,262,262,261,260,260,259,259,258,257,257,256,255,255,254,254,253,252,252,251,251,250,249,249,248,248,247,247,246,246,245,245,244,243,243,242,242,241,241,240,240,239,239,238,238,237,237,237,236,236,235,235,234,234,233,233,232,232,231,231,231,230,230,229,229,228,228,228,227,227,226,226,225,225,225,224,224,223,223,223,222,222,222,221,221,220,220,220,219,219,219,218,218,217,217,217,216,216,216,215,215,215,214,214,214,213,213,213,212,212,212,211,211,211,210,210,210,209,209,209,208,208,208,207,207,207,207,206,206,206,205,205,205,204,204,204,204,203,203,203,202,202,202,202,201,201,201,200,200,200,200,199,199,199,199,198,198,198,198,197,197,197,196,196,196,196,195,195,195,195,194,194,194,194,193,193,193,193,192,192,192,192,192,191,191,191,191,190,190,190,190,189,189,189,189,189,188,188,188,188,187,187,187,187,187,186,186,186,186,186,185,185,185,185,184,184,184,184,184,183,183,183,183,183,182,182,182,182,182,181,181,181,181,181,180,180,180,180,180,180,179,179,179,179,179,178,178,178,178,178,177,177,177,177,177,177,176,176,176,176,176,176,175,175,175,175,175,174,174,174,174,174,174,173,173,173,173,173,173,172,172,172,172,172,172,171,171,171,171, 0, ACC_CURVE,CRV_SMEARING ,4705,3056,2724,2497,1498,1498,1374,1276,1196,1130,1073,1025,982,944,911,880,853,828,805,784,764,746,730,714,699,685,675, 0, DEC_CURVE,CRV_NORMALSCAN,171,172,172,173,174,174,175,176,176,177,178,178,179,180,181,181,182,183,184,184,185,186,187,188,189,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,207,208,209,210,211,213,214,215,217,218,219,221,222,224,225,227,228,230,232,233,235,237,239,241,243,245,247,249,251,253,255,258,260,262,265,268,270,273,276,279,282,285,289,292,296,299,303,307,311,316,320,325,330,335,341,347,353,359,366,373,381,390,398,408,418,429,441,455,469,485,503,523,545,571,601,636,678,730,796,883,1005,1195,1544,4705, 0, DEC_CURVE,CRV_PARKHOME ,171,172,172,173,173,174,174,175,175,176,176,177,177,178,179,179,180,180,181,182,182,183,183,184,185,185,186,187,187,188,189,189,190,191,192,192,193,194,195,195,196,197,198,199,199,200,201,202,203,204,205,206,206,207,208,209,210,211,212,213,214,215,217,218,219,220,221,222,223,225,226,227,228,230,231,232,234,235,237,238,240,241,243,244,246,247,249,251,253,254,256,258,260,262,264,266,268,271,273,275,278,280,282,285,288,290,293,296,299,302,305,309,312,316,319,323,327,331,336,340,345,350,355,360,365,371,377,384,391,398,406,414,422,432,441,452,463,476,489,504,520,538,558,580,605,633,667,706,752,810,883,979,1116,1326,1714,4705, 0, DEC_CURVE,CRV_SMEARING ,675,685,699,714,730,746,764,784,805,828,853,880,911,944,982,1025,1073,1130,1196,1276,1374,1498,1498,2497,2724,3056,4705, 0, DEC_CURVE,CRV_BUFFERFULL,171,172,172,173,174,174,175,176,176,177,178,178,179,180,181,181,182,183,184,184,185,186,187,188,189,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,207,208,209,210,211,213,214,215,217,218,219,221,222,224,225,227,228,230,232,233,235,237,239,241,243,245,247,249,251,253,255,258,260,262,265,268,270,273,276,279,282,285,289,292,296,299,303,307,311,316,320,325,330,335,341,347,353,359,366,373,381,390,398,408,418,429,441,455,469,485,503,523,545,571,601,636,678,730,796,883,1005,1195,1544,4705, 0, -2, /* motorcurve 5 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,3763,3763,3763,3763,3763,3763,2444,2178,1997,1198,1198,1098,1020,956,903,858,819,785,754,727,703,681,662,644,626,610,596,582,571,558,547,537,527,518,509,500,492,485,478,471,464,458,452,446,440,435,430,425,420,415,410,407,402,398,394,391,386,383,380,376,373,369,366,364,360,357,355,352,349,347,344,341,338,337,334,332,329,328,325,323,321,319,317,315,313,311,310,308,306,304,302,301,299,297,295,294,293,291,290,288,286,285,284,283,281,280,278,277,275,275,274,272,271,270,268,267,266,265,264,263,262,261,259,258,257,257,256,255,254,253,251,250,249,248,248,247,246,245,244,243,243,242,241,240,239,239,238,237,236,235,235,234,233,232,231,230,230,230,229,228,228,227,226,225,225,224,223,222,222,221,221,221,220,219,219,218,217,217,216,215,215,214,213,213,212,212,212,211,211,210,209,209,208,208,207,207,206,206,205,204,204,203,203,203,203,202,202,201,201,200,200,199,199,198,198,197,197,196,196,195,195,194,194,194,194,194,193,193,192,192,191,191,190,190,190,189,189,188,188,188,187,187,186,186,185,185,185,185,185,185,184,184,183,183,183,182,182,182,181,181,180,180,180,179,179,179,178,178,178,177,177,177,176,176,176,176,176,176,175,175,175,174,174,174,173,173,173,172,172,172,171,171,171,171,170,170,170,169,169,169,169,168,168,168,167,167,167,167,167,167,167,166,166,166,166,165,165,165,165,164,164,164,163,163,163,163,162,162,162,162,161,161,161,161,160,160,160,160,159,159,159,159,159,158,158,158,158,158,158,158,158,157,157,157,157,157,156,156,156,156,155,155,155,155,155,154,154,154,154,154,153,153,153,153,152,152,152,152,152,151,151,151,151,151,150,150,150,150,150,149,149,149,149,149,149,149,149,149,149,149,148,148,148,148,148,147,147,147,147,147,147,146,146,146,146,146,145,145,145,145,145,145,144,144,144,144,144,144,143,143,143,143,143,143,142,142,142,142,142,142,141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,140,140,140,139,139,139,139,139,139,139,138,138,138,138,138,138,138,137,137,137,137,137,137,137,136,136,136,136,136,136,136,135,135,135,135,135,135,135,134,134,134,134,134,134,134,134,133,133,133,133,133,133,133,133,132,132,132,132,132,132,132,132,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,130,130,130,130,130,130,130,130,129,129,129,129,129,129,129,129,129,128,128,128,128,128,128,128,128,128,127,127,127,127,127,127,127,127,127,126,126,126,126,126,126,126,126,126,125,125,125,125,125,125,125,125,125,125,124,124,124,124,124,124,124,124,124,124,123,123,123,123,123,123,123,123,123,123,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,121,121,121,121,121,121,121,121,121,121,121,120,120,120,120,120,120,120,120,120,120,120,119,119,119,119,119,119,119,119,119,119,119,119,118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,116,116,116,116,116,116,116,116,116,116,116,116,115,115,115,115,115,115,115,115,115,115,115,115,115,114,114,114,114,114,114,114,114,114,114,114,114,114,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,95,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,94,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93, 0, ACC_CURVE,CRV_PARKHOME ,3763,2330,1803,1515,1330,1198,1099,1021,957,904,859,819,785,755,728,704,682,662,644,626,611,597,583,571,559,548,537,527,518,509,501,493,485,478,472,464,458,453,446,441,436,430,425,420,416,411,407,402,399,394,391,387,383,380,376,374,370,366,364,361,358,355,352,349,347,344,342,339,337,335,332,330,328,326,323,321,320,318,315,313,311,310,308,306,304,302,301,300,298,296,294,293,292,290,289,287,285,284,283,282,280,279,277,276,275,274,273,271,270,269,267,266,266,265,263,262,261,260,259,258,257,256,255,254,253,252,251,250,249,248,248,247,246,245,244,243,242,241,240,239,239,239,238,237,236,235,234,233,233,232,231,230,230,230,229,228,227,227,226,225,224,224,223,222,221,221,221,220,220,219,218,218,217,216,216,215,214,214,213,213,212,212,212,211,211,210,209,209,208,208,207,207,206,205,205,204,204,203,203,203,203,202,202,201,201,200,200,199,199,198,198,197,197,196,196,195,195,194,194,194,194,194,193,193,192,192,191,191,191,190,190,189,189,188,188,188,187,187,186,186,186,185,185,185,185,185,184,184,184,183,183,182,182,182,181,181,181,180,180,180,179,179,178,178,178,177,177,177,176,176,176,176,176,176,175,175,175,174,174,174,174,173,173,173,172,172,172,171,171,171,170,170,170,170,169,169,169,168,168,168,168,167,167,167,167,167,167,167,166,166,166,166,165,165,165,165,164,164,164,163,163,163,163,162,162,162,162,161,161,161,161,160,160,160,160,160,159,159,159,159,158,158,158,158,158,158,158,158,157,157,157,157,157,156,156,156,156,155,155,155,155,155,154,154,154,154,154,153,153,153,153,153,152,152,152,152,152,151,151,151,151,151,150,150,150,150,150,149,149,149,149,149,149,149,149,149,149,148,148,148,148,148,148,147,147,147,147,147,147,146,146,146,146,146,145,145,145,145,145,145,144,144,144,144,144,144,143,143,143,143,143,143,142,142,142,142,142,142,141,141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,140,140,140,139,139,139,139,139,139,139,138, 0, ACC_CURVE,CRV_SMEARING ,3763,2330,1803,1515,1330,1198,1099,1021,957,904,859,819,785,755,728,704,682,662,644,626,611,597,583,571,559,548,540, 0, DEC_CURVE,CRV_NORMALSCAN,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,86,87,87,87,87,87,87,87,87,88,88,88,88,88,88,88,88,89,89,89,89,89,89,89,90,90,90,90,90,90,91,91,91,91,91,92,92,92,92,93,93,93,93,94,94,94,95,95,95,95,95,96,96,97,97,98,98,99,99,100,100,101,101,102,102,103,104,104,105,106,107,108,109,110,111,112,113,113,115,117,119,121,122,124,127,130,132,135,139,142,146,149,153,158,162,167,171,176,180,186,193,202,209,216,223,232,243,254,266,279,292,306,320,335,337,351,367,380,396,414,437,464,493,520,549,583,611,644,675,711,755,785,819,859,904,957,1021,1099,1198,1330,1515,1803,2330,3763, 0, DEC_CURVE,CRV_PARKHOME ,138,142,146,149,153,158,162,167,171,176,180,186,193,202,209,216,223,232,243,254,266,279,292,306,320,335,337,351,367,380,396,414,437,464,493,520,549,583,611,644,675,711,755,785,819,859,904,957,1021,1099,1198,1330,1515,1803,2330,3763, 0, DEC_CURVE,CRV_SMEARING ,138,139,139,139,139,139,139,139,140,140,140,140,140,140,140,140,140,140,140,140,140,141,141,141,141,141,141,141,142,142,142,142,142,142,143,143,143,143,143,143,144,144,144,144,144,144,145,145,145,145,145,145,146,146,146,146,146,147,147,147,147,147,147,148,148,148,148,148,148,149,149,149,149,149,149,149,149,149,149,150,150,150,150,150,151,151,151,151,151,152,152,152,152,152,153,153,153,153,153,154,154,154,154,154,155,155,155,155,155,156,156,156,156,157,157,157,157,157,158,158,158,158,158,158,158,158,159,159,159,159,160,160,160,160,160,161,161,161,161,162,162,162,162,163,163,163,163,164,164,164,165,165,165,165,166,166,166,166,167,167,167,167,167,167,167,168,168,168,168,169,169,169,170,170,170,170,171,171,171,172,172,172,173,173,173,174,174,174,174,175,175,175,176,176,176,176,176,176,177,177,177,178,178,178,179,179,180,180,180,181,181,181,182,182,182,183,183,184,184,184,185,185,185,185,185,186,186,186,187,187,188,188,188,189,189,190,190,191,191,191,192,192,193,193,194,194,194,194,194,195,195,196,196,197,197,198,198,199,199,200,200,201,201,202,202,203,203,203,203,204,204,205,205,206,207,207,208,208,209,209,210,211,211,212,212,212,213,213,214,214,215,216,216,217,218,218,219,220,220,221,221,221,222,223,224,224,225,226,227,227,228,229,230,230,230,231,232,233,233,234,235,236,237,238,239,239,239,240,241,242,243,244,245,246,247,248,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,265,266,266,267,269,270,271,273,274,275,276,277,279,280,282,283,284,285,287,289,290,292,293,294,296,298,300,301,302,304,306,308,310,311,313,315,318,320,321,323,326,328,330,332,335,337,339,342,344,347,349,352,355,358,361,364,366,370,374,376,380,383,387,391,394,399,402,407,411,416,420,425,430,436,441,446,453,458,464,472,478,485,493,501,509,518,527,537,548,559,571,583,597,611,626,644,662,682,704,728,755,785,819,859,904,957,1021,1099,1198,1330,1515,1803,2330,3763, 0, DEC_CURVE,CRV_BUFFERFULL,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,94,94,94,95,95,95,95,95,96,96,97,97,98,98,99,99,100,100,101,101,102,102,103,104,104,105,106,107,108,109,110,111,112,113,113,115,117,119,121,122,124,127,130,132,135,139,142,146,149,153,158,162,167,171,176,180,186,193,202,209,216,223,232,243,254,266,279,292,306,320,335,337,351,367,380,396,414,437,464,493,520,549,583,611,644,675,711,755,785,819,859,904,957,1021,1099,1198,1330,1515,1803,2330,3763, 0, -2, /* motorcurve 6 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,23999, 0, ACC_CURVE,CRV_PARKHOME ,5360,3362,2628,2229,1973,1791,1654,1547,1458,1384,1319,1264,1214,1170,1131,1096,1063,1034,1006,981,958,937,916,897,880,863,847,832,818,805,792,780,769,758,747,737,727,718,709,700,692, 0, ACC_CURVE,CRV_SMEARING ,23999, 0, DEC_CURVE,CRV_NORMALSCAN,23999, 0, DEC_CURVE,CRV_PARKHOME ,692,700,709,718,727,737,747,758,769,780,792,805,818,832,847,863,880,897,916,937,958,981,1006,1034,1063,1096,1131,1170,1214,1264,1319,1384,1458,1547,1654,1791,1973,2229,2628,3362,5360, 0, DEC_CURVE,CRV_SMEARING ,23999, 0, DEC_CURVE,CRV_BUFFERFULL,23999, 0, -2, /* motorcurve 7 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,6667, 0, ACC_CURVE,CRV_PARKHOME ,5360,3362,2628,2229,1973,1791,1654,1547,1458,1384,1319,1264,1214,1170,1131,1096,1063,1034,1006,981,958,937,916,897,880,863,847,832,818,805,792,780,769,758,747,737,727,718,709,700,692, 0, ACC_CURVE,CRV_SMEARING ,6667, 0, DEC_CURVE,CRV_NORMALSCAN,6667, 0, DEC_CURVE,CRV_PARKHOME ,692,700,709,718,727,737,747,758,769,780,792,805,818,832,847,863,880,897,916,937,958,981,1006,1034,1063,1096,1131,1170,1214,1264,1319,1384,1458,1547,1654,1791,1973,2229,2628,3362,5360, 0, DEC_CURVE,CRV_SMEARING ,6667, 0, DEC_CURVE,CRV_BUFFERFULL,6667, 0, -2, /* motorcurve 8 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,1046,1046,1046,1046,1046,1046,647,501,421,370,333,305,284,266,251,239,228,218,210,202,196,190,184,179,174,170,166,162,159,155,152,149,147,144,142,139,137,135,133,131,129,127,126,124,123,121,120,118,117,116,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,100,99,98,97,96,96,95,94,94,93,92,92,91,91,90,89,89,88,88,87,87,86,86,85,85,84,84,83,83,82,82,82,81,81,80,80,79,79,79,78,78,78,77,77,76,76,76,75,75,75,74,74,74,74,73,73,73,72,72,72,71,71,71,71,70,70,70,70,69,69,69,69,68,68,68,68,67,67,67,67,66,66,66,66,65,65,65,65,64,64,64,64,63,63,63,63,62,62,62,62,61,61,61,61,61,60,60,60,60,60,60,59,59,59,59,59,59,59,58,58,58,58,58,58,57,57,57,57,57,57,57,56,56,56,56,56,56,56,56,55,55,55,55,55,55,55,55,54,54,54,54,54,54,54,54,53,53,53,53,53,53,53,53,52,52,52,52,52,52,52,52,51,51,51,51,51,51,51,51,51,51,51,51,50,50,50,50,50,50,50,50,50,50,50,49,49,49,49,49,49,49,49,49,49,49,49,48,48,48,48,48,48,48,48,48,48,48,48,47,47,47,47,47,47,47,47,47,47,47,47,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,23,23, 0, ACC_CURVE,CRV_PARKHOME ,1045,678,604,554,332,332,304,283,265,250,238,227,217,209,201,195,189,183,178,173,169,165,161,158,154,151,148,146,143,141,138,136,134,132,130,128,126,125,123,122,120,119,117,116,115,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,99,98,97,96,95,95,94,93,93,92,91,91,90,90,89,88,88,87,87,86,86,85,85,84,84,83,83,82,82,81,81,81,80,80,79,79,78,78,78,77,77,77,76,76,75,75,75,74,74,74,73,73,73,73,72,72,72,71,71,71,70,70,70,70,69,69,69,69,68,68,68,68,67,67,67,67,66,66,66,66,65,65,65,65,65,64,64,64,64,64,63,63,63,63,63,62,62,62,62,62,61,61,61,61,61,61,60,60,60,60,60,60,59,59,59,59,59,59,58,58,58,58,58,58,58,57,57,57,57,57,57,57,56,56,56,56,56,56,56,55,55,55,55,55,55,55,55,54,54,54,54,54,54,54,54,53,53,53,53,53,53,53,53,53,52,52,52,52,52,52,52,52,52,51,51,51,51,51,51,51,51,51,51,50,50,50,50,50,50,50,50,50,50,50,49,49,49,49,49,49,49,49,49,49,49,48,48,48,48,48,48,48,48,48,48,48,48,47,47,47,47,47,47,47,47,47,47,47,47,47,46,46,46,46,46,46,46,46,46,46,46,46,46,46,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,39, 0, ACC_CURVE,CRV_SMEARING ,1045,678,604,554,332,332,304,283,265,250,238,227,217,209,201,195,189,183,178,173,169,165,161,158,154,151,148,146,143,141,138,136,134,132,130,128,126,125,123,122,120,119,117,116,115,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,99,98,97,96,95,95,94,93,93,92,91,91,90,90,89,88,88,87,87,86,86,85,85,84,84,83,83,82,82,81,81,81,80,80,79,79,78,78,78,77,77,77,76,76,75,75,75,74,74,74,73,73,73,73,72,72,72,71,71,71,70,70,70,70,69,69,69,69,68,68,68,68,67,67,67,67,66,66,66,66,65,65,65,65,65,64,64,64,64,64,63,63,63,63,63,62,62,62,62,62,61,61,61,61,61,61,60,60,60,60,60,60,59,59,59,59,59,59,58,58,58,58,58,58,58,57,57,57,57,57,57,57,56,56,56,56,56,56,56,55,55,55,55,55,55,55,55,54,54,54,54,54,54,54,54,53,53,53,53,53,53,53,53,53,52,52,52,52,52,52,52,52,52,51,51,51,51,51,51,51,51,51,51,50,50,50,50,50,50,50,50,50,50,50,49,49,49,49,49,49,49,49,49,49,49,48,48,48,48,48,48,48,48,48,48,48,48,47,47,47,47,47,47,47,47,47,47,47,47,47,46,46,46,46,46,46,46,46,46,46,46,46,46,46,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,39, 0, DEC_CURVE,CRV_NORMALSCAN,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,30,30,30,30,31,31,31,31,32,32,32,32,33,33,34,34,35,35,36,37,38,38,39,40,41,42,43,45,46,47,48,50,51,53,54,57,59,61,63,65,68,71,75,78,82,86,90,94,94,98,103,106,111,116,122,130,138,145,153,163,171,180,188,198,211,219,228,239,252,267,284,306,334,370,422,502,648,1045, 0, DEC_CURVE,CRV_PARKHOME ,39,40,41,42,43,45,46,47,48,50,51,53,54,57,59,61,63,65,68,71,75,78,82,86,90,94,94,98,103,106,111,116,122,130,138,145,153,163,171,180,188,198,211,219,228,239,252,267,284,306,334,370,422,502,648,1045, 0, DEC_CURVE,CRV_SMEARING ,39,39,39,39,39,39,39,39,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,48,48,48,48,48,48,48,48,48,48,48,48,48,48,49,49,49,49,49,49,49,49,49,49,49,49,49,50,50,50,50,50,50,50,50,50,50,50,50,51,51,51,51,51,51,51,51,51,51,51,52,52,52,52,52,52,52,52,52,52,53,53,53,53,53,53,53,53,53,53,54,54,54,54,54,54,54,54,54,55,55,55,55,55,55,55,55,55,56,56,56,56,56,56,56,56,57,57,57,57,57,57,57,57,58,58,58,58,58,58,58,59,59,59,59,59,59,59,60,60,60,60,60,60,60,61,61,61,61,61,61,62,62,62,62,62,62,63,63,63,63,63,64,64,64,64,64,65,65,65,65,65,66,66,66,66,66,67,67,67,67,67,68,68,68,68,69,69,69,69,70,70,70,70,71,71,71,71,72,72,72,73,73,73,73,74,74,74,75,75,75,76,76,76,77,77,77,78,78,78,79,79,79,80,80,81,81,81,82,82,83,83,84,84,84,85,85,86,86,87,87,88,88,89,90,90,91,91,92,93,93,94,94,95,96,96,97,98,99,99,100,101,102,103,104,105,105,106,107,108,109,110,112,113,114,115,116,118,119,120,122,123,125,127,128,130,132,134,136,138,140,142,145,147,150,153,156,159,163,167,171,175,180,185,190,196,203,211,219,228,239,252,267,284,306,334,370,422,502,648,1045, 0, DEC_CURVE,CRV_BUFFERFULL,1045,648,502,422,370,334,306,284,267,252,239,228,219,211,198,188,180,171,163,153,145,138,130,122,116,111,106,103,98,94,94,90,86,82,78,75,71,68,65,63,61,59,57,54,53,51,50,48,47,46,45,43,42,41,40,39,38,38,37,36,35,35,34,34,33,33,32,32,32,32,31,31,31,31,30,30,30,30,29,29,29,29,29,29,29,28,28,28,28,28,28,28,28,27,27,27,27,27,27,27,27,27,27,27,27,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25, 0, -2, /* motorcurve 9 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, ACC_CURVE,CRV_PARKHOME ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166,166,166, 0, ACC_CURVE,CRV_SMEARING ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,455, 0, DEC_CURVE,CRV_NORMALSCAN,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136,3136,3136,3136,3136,3136, 0, DEC_CURVE,CRV_PARKHOME ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136,3136,3136,3136,3136,3136, 0, DEC_CURVE,CRV_SMEARING ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136,3136,3136,3136,3136,3136, 0, DEC_CURVE,CRV_BUFFERFULL,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,127,127,128,128,129,129,130,131,132,133,133,134,135,136,137,138,139,140,141,143,144,145,146,147,149,150,151,153,154,156,157,159,161,162,164,166,168,170,172,174,176,179,181,184,186,189,192,195,198,202,206,209,213,218,222,227,233,239,245,252,259,267,276,282,286,291,298,305,310,319,325,331,342,354,362,376,387,404,417,431,456,475,509,551,586,654,715,850,998,1664,3136,3136, 0, -2, /* motorcurve 10 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376, 0, ACC_CURVE,CRV_PARKHOME ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, ACC_CURVE,CRV_SMEARING ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,455, 0, DEC_CURVE,CRV_NORMALSCAN,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, DEC_CURVE,CRV_PARKHOME ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, DEC_CURVE,CRV_SMEARING ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, DEC_CURVE,CRV_BUFFERFULL,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, -2, /* motorcurve 11 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, ACC_CURVE,CRV_PARKHOME ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, ACC_CURVE,CRV_SMEARING ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, DEC_CURVE,CRV_NORMALSCAN,167,168,169,170,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,190,191,192,193,194,196,197,198,200,201,203,204,206,207,209,211,212,214,216,218,219,221,223,225,227,230,232,234,236,239,241,244,247,249,252,255,258,261,265,268,272,275,279,283,288,292,297,302,307,313,318,325,331,338,346,353,362,371,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, DEC_CURVE,CRV_PARKHOME ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, DEC_CURVE,CRV_SMEARING ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, DEC_CURVE,CRV_BUFFERFULL,167,168,169,170,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,190,191,192,193,194,196,197,198,200,201,203,204,206,207,209,211,212,214,216,218,219,221,223,225,227,230,232,234,236,239,241,244,247,249,252,255,258,261,265,268,272,275,279,283,288,292,297,302,307,313,318,325,331,338,346,353,362,371,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, -2, /* motorcurve 12 */ 1, 1, 1, 0, /* mri, msi, skiplinecount, motorbackstep */ ACC_CURVE,CRV_NORMALSCAN,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166,166,166,165,165,165,164,164,163,163,163,162,162,162,161,161,161,160,160,160,159,159,159,158,158,158,157,157,157,156,156,156,156,155,155,155,154,154,154,153,153,153,153,152,152,152,151,151,151,151,150,150,150,150,149,149,149,148,148,148,148,147,147,147,147,146,146,146,146,145,145,145,145,144,144,144,144,144,143,143,143,143,142,142,142,142,141,141,141,141,141,140,140,140,140,140,139,139,139,139,138,138,138,138,138,137,137,137,137,137,136,136,136,136,136,135,135,135,135,135,135,134,134,134,134,134,133,133,133,133,133,133,132,132,132,132,132,131,131,131,131,131,131,130,130,130,130,130,130,129,129,129,129,129,129,128,128,128,128,128,128,127,127,127,127,127,127,127,126,126,126,126,126,126,125, 0, ACC_CURVE,CRV_PARKHOME ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,447,439,431,424,417,410,404,398,392,387,381,376,371,367,362,358,354,350,346,342,338,335,331,328,325,322,319,316,313,310,308,305,302,300,298,295,293,291,288,286,284,282,280,278,276,274,272,271,269,267,265,264,262,261,259,257,256,254,253,252,250,249,247,246,245,244,242,241,240,239,237,236,235,234,233,232,231,230,228,227,226,225,224,223,222,221,221,220,219,218,217,216,215,214,213,213,212,211,210,209,209,208,207,206,206,205,204,203,203,202,201,200,200,199,198,198,197,196,196,195,195,194,193,193,192,192,191,190,190,189,189,188,187,187,186,186,185,185,184,184,183,183,182,182,181,181,180,180,179,179,178,178,177,177,176,176,175,175,175,174,174,173,173,172,172,172,171,171,170,170,170,169,169,168,168,168,167,167,166, 0, ACC_CURVE,CRV_SMEARING ,3136,3136,3136,3136,3136,3136,2036,1815,1664,998,998,915,850,797,752,715,682,654,628,606,586,568,551,536,522,509,497,485,475,465,456,455, 0, DEC_CURVE,CRV_NORMALSCAN,110,110,110,110,110,110,110,110,111,111,111,111,111,112,112,112,112,112,113,113,113,113,114,114,114,114,115,115,115,115,115,116,116,116,116,117,117,117,117,118,118,118,118,119,119,119,120,120,120,120,121,121,121,121,122,122,122,123,123,123,124,124,124,124,125,125,125,126,126,126,127,127,127,128,128,128,129,129,129,130,130,130,131,131,132,132,132,133,133,133,134,134,135,135,135,136,136,137,137,138,138,138,139,139,140,140,141,141,142,142,142,143,143,144,144,145,145,146,146,147,148,148,149,149,150,150,151,151,152,153,153,154,154,155,156,156,157,158,158,159,160,160,161,162,163,163,164,165,166,166,167,168,169,170,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,190,191,192,193,194,196,197,198,200,201,203,204,206,207,209,211,212,214,216,218,219,221,223,225,227,230,232,234,236,239,241,244,247,249,252,255,258,261,265,268,272,275,279,283,288,292,297,302,307,313,318,325,331,338,346,353,362,371,381,392,404,417,431,447,465,485,508,535,566,604,650,709,787,897,1067,2227,3136, 0, DEC_CURVE,CRV_PARKHOME ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, DEC_CURVE,CRV_SMEARING ,455,456,465,475,485,497,509,522,536,551,568,586,606,628,654,682,715,752,797,850,915,998,998,1664,1815,2036,3136, 0, DEC_CURVE,CRV_BUFFERFULL,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,127,127,128,128,129,129,130,131,132,133,133,134,135,136,137,138,139,140,141,143,144,145,146,147,149,150,151,153,154,156,157,159,161,162,164,166,168,170,172,174,176,179,181,184,186,189,192,195,198,202,206,209,213,218,222,227,233,239,245,252,259,267,276,282,286,291,298,305,310,319,325,331,342,354,362,376,387,404,417,431,456,475,509,551,586,654,715,850,998,1664,3136, 0, -1 }; rst = (SANE_Int *)malloc(sizeof(steps)); if (rst != NULL) memcpy(rst, &steps, sizeof(steps)); return rst; } static SANE_Int *cfg_motorcurve_get() { /* returns motor setting buffer for a device */ SANE_Int *rst = NULL; switch(RTS_Debug->dev_model) { case BQ5550: rst = bq5550_motor(); break; case HP3800: case HPG2710: rst = hp3800_motor(); break; case HP4370: case HPG3010: case HPG3110: rst = hp4370_motor(); break; default: rst = hp3970_motor(); break; } return rst; } /* DEPRECATED functions */ static int ua4900_calibreflective(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 0; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 10; break; case BREFG: rst = 10; break; case BREFB: rst = 10; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 300; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 310; break; case OFFSETODD1R: rst = 310; break; case OFFSETEVEN1G: rst = 313; break; case OFFSETODD1G: rst = 313; break; case OFFSETEVEN1B: rst = 319; break; case OFFSETODD1B: rst = 319; break; case ADCOFFPREDICTR: rst = 321; break; case ADCOFFPREDICTG: rst = 321; break; case ADCOFFPREDICTB: rst = 321; break; case ADCOFFEVEN1R_1ST: rst = 344; break; case ADCOFFODD1R_1ST: rst = 344; break; case ADCOFFEVEN1G_1ST: rst = 328; break; case ADCOFFODD1G_1ST: rst = 328; break; case ADCOFFEVEN1B_1ST: rst = 341; break; case ADCOFFODD1B_1ST: rst = 341; break; case PEAKR: rst = 122; break; case PEAKG: rst = 122; break; case PEAKB: rst = 122; break; case MINR: rst = 50; break; case MING: rst = 50; break; case MINB: rst = 50; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 10; break; case GAINTARGETFACTOR: rst = 90; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 3; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 8; break; case GAIN1G: rst = 8; break; case GAIN1B: rst = 8; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 8; break; case GAIN2G: rst = 8; break; case GAIN2B: rst = 8; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -2; break; case BSHADINGHEIGHT: rst = 10; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 1; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 15; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp3800_calibreflective(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 0; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 10; break; case BREFG: rst = 10; break; case BREFB: rst = 10; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 300; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 310; break; case OFFSETODD1R: rst = 310; break; case OFFSETEVEN1G: rst = 317; break; case OFFSETODD1G: rst = 317; break; case OFFSETEVEN1B: rst = 293; break; case OFFSETODD1B: rst = 293; break; case ADCOFFPREDICTR: rst = 500; break; case ADCOFFPREDICTG: rst = 500; break; case ADCOFFPREDICTB: rst = 500; break; case ADCOFFEVEN1R_1ST: rst = 128; break; case ADCOFFODD1R_1ST: rst = 128; break; case ADCOFFEVEN1G_1ST: rst = 128; break; case ADCOFFODD1G_1ST: rst = 128; break; case ADCOFFEVEN1B_1ST: rst = 128; break; case ADCOFFODD1B_1ST: rst = 128; break; case PEAKR: rst = 104; break; case PEAKG: rst = 111; break; case PEAKB: rst = 105; break; case MINR: rst = 50; break; case MING: rst = 56; break; case MINB: rst = 57; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 10; break; case GAINTARGETFACTOR: rst = 80; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 3; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 23; break; case GAIN1G: rst = 19; break; case GAIN1B: rst = 0; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -3; break; case BSHADINGHEIGHT: rst = 20; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp3970_calibreflective(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 0; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 10; break; case BREFG: rst = 10; break; case BREFB: rst = 10; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 300; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 327; break; case OFFSETODD1R: rst = 327; break; case OFFSETEVEN1G: rst = 315; break; case OFFSETODD1G: rst = 315; break; case OFFSETEVEN1B: rst = 322; break; case OFFSETODD1B: rst = 322; break; case ADCOFFPREDICTR: rst = 322; break; case ADCOFFPREDICTG: rst = 310; break; case ADCOFFPREDICTB: rst = 322; break; case ADCOFFEVEN1R_1ST: rst = 344; break; case ADCOFFODD1R_1ST: rst = 344; break; case ADCOFFEVEN1G_1ST: rst = 328; break; case ADCOFFODD1G_1ST: rst = 328; break; case ADCOFFEVEN1B_1ST: rst = 341; break; case ADCOFFODD1B_1ST: rst = 341; break; case PEAKR: rst = 82; break; case PEAKG: rst = 117; break; case PEAKB: rst = 116; break; case MINR: rst = 37; break; case MING: rst = 51; break; case MINB: rst = 53; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 10; break; case GAINTARGETFACTOR: rst = 90; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 3; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 28; break; case GAIN1G: rst = 22; break; case GAIN1B: rst = 21; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -2; break; case BSHADINGHEIGHT: rst = 10; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp4370_calibreflective(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 0; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 10; break; case BREFG: rst = 10; break; case BREFB: rst = 10; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 300; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 305; break; case OFFSETODD1R: rst = 3305; break; case OFFSETEVEN1G: rst = 313; break; case OFFSETODD1G: rst = 313; break; case OFFSETEVEN1B: rst = 317; break; case OFFSETODD1B: rst = 317; break; case ADCOFFPREDICTR: rst = 500; break; case ADCOFFPREDICTG: rst = 500; break; case ADCOFFPREDICTB: rst = 500; break; case ADCOFFEVEN1R_1ST: rst = 344; break; case ADCOFFODD1R_1ST: rst = 344; break; case ADCOFFEVEN1G_1ST: rst = 328; break; case ADCOFFODD1G_1ST: rst = 328; break; case ADCOFFEVEN1B_1ST: rst = 341; break; case ADCOFFODD1B_1ST: rst = 341; break; case PEAKR: rst = 159; break; case PEAKG: rst = 191; break; case PEAKB: rst = 191; break; case MINR: rst = 146; break; case MING: rst = 180; break; case MINB: rst = 179; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 10; break; case GAINTARGETFACTOR: rst = 80; break; case CALIBPAGON: rst = 0; break; case HIPAGR: rst = 3; break; case HIPAGG: rst = 0; break; case HIPAGB: rst = 0; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 3; break; case LOPAGR: rst = 3; break; case LOPAGG: rst = 3; break; case LOPAGB: rst = 3; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 10; break; case GAIN1G: rst = 2; break; case GAIN1B: rst = 1; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -2; break; case BSHADINGHEIGHT: rst = 10; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int fc_calibreflective(int option, int defvalue) { int rst; switch(RTS_Debug->dev_model) { case UA4900: rst = ua4900_calibreflective(option, defvalue); break; case HPG2710: case HP3800: rst = hp3800_calibreflective(option, defvalue); break; case HPG3010: case HPG3110: case HP4370: rst = hp4370_calibreflective(option, defvalue); break; default : rst = hp3970_calibreflective(option, defvalue); break; } return rst; } static int ua4900_calibtransparent(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 12100; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 2; break; case BREFG: rst = 2; break; case BREFB: rst = 2; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 13; break; case OFFSETAVGTARGETG: rst = 13; break; case OFFSETAVGTARGETB: rst = 13; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 321; break; case OFFSETODD1R: rst = 321; break; case OFFSETEVEN1G: rst = 321; break; case OFFSETODD1G: rst = 321; break; case OFFSETEVEN1B: rst = 321; break; case OFFSETODD1B: rst = 321; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 177; break; case PEAKG: rst = 177; break; case PEAKB: rst = 177; break; case MINR: rst = 136; break; case MING: rst = 136; break; case MINB: rst = 136; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 90; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 0; break; case PAGG: rst = 0; break; case PAGB: rst = 0; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 24; break; case GAIN1G: rst = 21; break; case GAIN1B: rst = 19; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 8; break; case GAIN2G: rst = 8; break; case GAIN2B: rst = 8; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = 2; break; case BSHADINGHEIGHT: rst = 10; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp3800_calibtransparent(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 4155; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 2; break; case BREFG: rst = 2; break; case BREFB: rst = 2; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 310; break; case OFFSETODD1R: rst = 310; break; case OFFSETEVEN1G: rst = 299; break; case OFFSETODD1G: rst = 299; break; case OFFSETEVEN1B: rst = 309; break; case OFFSETODD1B: rst = 309; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 67; break; case PEAKG: rst = 61; break; case PEAKB: rst = 57; break; case MINR: rst = 10; break; case MING: rst = 10; break; case MINB: rst = 10; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 90; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 2; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 9; break; case GAIN1G: rst = 12; break; case GAIN1B: rst = 10; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -3; break; case BSHADINGHEIGHT: rst = 30; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp3970_calibtransparent(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 7500; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 2; break; case BREFG: rst = 2; break; case BREFB: rst = 2; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 323; break; case OFFSETODD1R: rst = 323; break; case OFFSETEVEN1G: rst = 327; break; case OFFSETODD1G: rst = 327; break; case OFFSETEVEN1B: rst = 327; break; case OFFSETODD1B: rst = 327; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 42; break; case PEAKG: rst = 55; break; case PEAKB: rst = 53; break; case MINR: rst = 31; break; case MING: rst = 39; break; case MINB: rst = 38; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 90; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 2; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 21; break; case GAIN1G: rst = 14; break; case GAIN1B: rst = 12; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = 1; break; case BSHADINGHEIGHT: rst = 30; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp4370_calibtransparent(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 6580; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 2; break; case BREFG: rst = 2; break; case BREFB: rst = 2; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 315; break; case OFFSETODD1R: rst = 321; break; case OFFSETEVEN1G: rst = 321; break; case OFFSETODD1G: rst = 324; break; case OFFSETEVEN1B: rst = 324; break; case OFFSETODD1B: rst = 327; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 62; break; case PEAKG: rst = 66; break; case PEAKB: rst = 54; break; case MINR: rst = 42; break; case MING: rst = 45; break; case MINB: rst = 45; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 80; break; case CALIBPAGON: rst = 0; break; case HIPAGR: rst = 3; break; case HIPAGG: rst = 3; break; case HIPAGB: rst = 2; break; case LOPAGR: rst = 3; break; case LOPAGG: rst = 3; break; case LOPAGB: rst = 2; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 2; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 11; break; case GAIN1G: rst = 9; break; case GAIN1B: rst = 12; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -2; break; case BSHADINGHEIGHT: rst = 30; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hpg3110_calibtransparent(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 5100; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 2; break; case BREFG: rst = 2; break; case BREFB: rst = 2; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 315; break; case OFFSETODD1R: rst = 321; break; case OFFSETEVEN1G: rst = 321; break; case OFFSETODD1G: rst = 324; break; case OFFSETEVEN1B: rst = 324; break; case OFFSETODD1B: rst = 327; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 62; break; case PEAKG: rst = 66; break; case PEAKB: rst = 54; break; case MINR: rst = 42; break; case MING: rst = 45; break; case MINB: rst = 45; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 80; break; case CALIBPAGON: rst = 0; break; case HIPAGR: rst = 3; break; case HIPAGG: rst = 3; break; case HIPAGB: rst = 2; break; case LOPAGR: rst = 3; break; case LOPAGG: rst = 3; break; case LOPAGB: rst = 2; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 2; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 11; break; case GAIN1G: rst = 9; break; case GAIN1B: rst = 12; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -2; break; case BSHADINGHEIGHT: rst = 30; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int fc_calibtransparent(int option, int defvalue) { int rst; switch(RTS_Debug->dev_model) { case UA4900: rst = ua4900_calibtransparent(option, defvalue); break; case HPG2710: case HP3800: rst = hp3800_calibtransparent(option, defvalue); break; case HPG3010: case HP4370: rst = hp4370_calibtransparent(option, defvalue); break; case HPG3110: rst = hpg3110_calibtransparent(option, defvalue); break; default : rst = hp3970_calibtransparent(option, defvalue); break; } return rst; } static int ua4900_calibnegative(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 12100; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 2; break; case BREFG: rst = 2; break; case BREFB: rst = 2; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 5; break; case OFFSETAVGTARGETG: rst = 5; break; case OFFSETAVGTARGETB: rst = 5; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 283; break; case OFFSETODD1R: rst = 283; break; case OFFSETEVEN1G: rst = 279; break; case OFFSETODD1G: rst = 279; break; case OFFSETEVEN1B: rst = 295; break; case OFFSETODD1B: rst = 295; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 113; break; case PEAKG: rst = 145; break; case PEAKB: rst = 126; break; case MINR: rst = 80; break; case MING: rst = 105; break; case MINB: rst = 96; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 10; break; case GAINTARGETFACTOR: rst = 90; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 0; break; case PAGG: rst = 0; break; case PAGB: rst = 0; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 8; break; case GAIN1G: rst = 8; break; case GAIN1B: rst = 8; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 8; break; case GAIN2G: rst = 8; break; case GAIN2B: rst = 8; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = 2; break; case BSHADINGHEIGHT: rst = 10; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp3800_calibnegative(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 4155; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 10; break; case BREFG: rst = 10; break; case BREFB: rst = 10; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 315; break; case OFFSETODD1R: rst = 315; break; case OFFSETEVEN1G: rst = 307; break; case OFFSETODD1G: rst = 304; break; case OFFSETEVEN1B: rst = 309; break; case OFFSETODD1B: rst = 309; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 37; break; case PEAKG: rst = 234; break; case PEAKB: rst = 202; break; case MINR: rst = 32; break; case MING: rst = 195; break; case MINB: rst = 166; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 90; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 3; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 30; break; case GAIN1G: rst = 3; break; case GAIN1B: rst = 0; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -2; break; case BSHADINGHEIGHT: rst = 30; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp3970_calibnegative(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 7500; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 10; break; case BREFG: rst = 10; break; case BREFB: rst = 10; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 294; break; case OFFSETODD1R: rst = 294; break; case OFFSETEVEN1G: rst = 276; break; case OFFSETODD1G: rst = 276; break; case OFFSETEVEN1B: rst = 266; break; case OFFSETODD1B: rst = 266; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 33; break; case PEAKG: rst = 75; break; case PEAKB: rst = 105; break; case MINR: rst = 19; break; case MING: rst = 34; break; case MINB: rst = 42; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 90; break; case CALIBPAGON: rst = 0; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 3; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 23; break; case GAIN1G: rst = 18; break; case GAIN1B: rst = 23; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = 1; break; case BSHADINGHEIGHT: rst = 30; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hpg3110_calibnegative(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 5100; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 10; break; case BREFG: rst = 10; break; case BREFB: rst = 10; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 308; break; case OFFSETODD1R: rst = 308; break; case OFFSETEVEN1G: rst = 317; break; case OFFSETODD1G: rst = 317; break; case OFFSETEVEN1B: rst = 319; break; case OFFSETODD1B: rst = 319; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 116; break; case PEAKG: rst = 126; break; case PEAKB: rst = 102; break; case MINR: rst = 103; break; case MING: rst = 112; break; case MINB: rst = 80; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 80; break; case CALIBPAGON: rst = 0; break; case HIPAGR: rst = 3; break; case HIPAGG: rst = 3; break; case HIPAGB: rst = 3; break; case LOPAGR: rst = 3; break; case LOPAGG: rst = 3; break; case LOPAGB: rst = 3; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 3; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 6; break; case GAIN1G: rst = 1; break; case GAIN1B: rst = 7; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -2; break; case BSHADINGHEIGHT: rst = 30; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int hp4370_calibnegative(int option, int defvalue) { int rst = defvalue; switch(option) { case WSTRIPXPOS: rst = 0; break; case WSTRIPYPOS: rst = 6580; break; case BSTRIPXPOS: rst = 0; break; case BSTRIPYPOS: rst = 0; break; case BREFR: rst = 10; break; case BREFG: rst = 10; break; case BREFB: rst = 10; break; case REFBITDEPTH: rst = 8; break; case OFFSETHEIGHT: rst = 10; break; case OFFSETNSIGMA: rst = 2; break; case OFFSETTARGETMAX: rst = 50; break; case OFFSETTARGETMIN: rst = 2; break; case OFFSETAVGTARGETR: rst = 10; break; case OFFSETAVGTARGETG: rst = 10; break; case OFFSETAVGTARGETB: rst = 10; break; case ADCOFFEVENODD: rst = 1; break; case CALIBOFFSET1ON: rst = 2; break; case ADCOFFQUICKWAY: rst = 1; break; case ADCOFFPREDICTSTART: rst = 200; break; case ADCOFFPREDICTEND: rst = 500; break; case OFFSETTUNESTEP1: rst = 5; break; case OFFSETBOUNDARYRATIO1: rst = 100; break; case OFFSETAVGRATIO1: rst = 100; break; case OFFSETEVEN1R: rst = 308; break; case OFFSETODD1R: rst = 308; break; case OFFSETEVEN1G: rst = 317; break; case OFFSETODD1G: rst = 317; break; case OFFSETEVEN1B: rst = 319; break; case OFFSETODD1B: rst = 319; break; case ADCOFFPREDICTR: rst = 333; break; case ADCOFFPREDICTG: rst = 313; break; case ADCOFFPREDICTB: rst = 317; break; case ADCOFFEVEN1R_1ST: rst = 69; break; case ADCOFFODD1R_1ST: rst = 69; break; case ADCOFFEVEN1G_1ST: rst = 87; break; case ADCOFFODD1G_1ST: rst = 87; break; case ADCOFFEVEN1B_1ST: rst = 106; break; case ADCOFFODD1B_1ST: rst = 106; break; case PEAKR: rst = 116; break; case PEAKG: rst = 126; break; case PEAKB: rst = 102; break; case MINR: rst = 103; break; case MING: rst = 112; break; case MINB: rst = 80; break; case CALIBOFFSET2ON: rst = 0; break; case OFFSETTUNESTEP2: rst = 1; break; case OFFSETBOUNDARYRATIO2: rst = 100; break; case OFFSETAVGRATIO2: rst = 100; break; case OFFSETEVEN2R: rst = 0; break; case OFFSETODD2R: rst = 0; break; case OFFSETEVEN2G: rst = 0; break; case OFFSETODD2G: rst = 0; break; case OFFSETEVEN2B: rst = 0; break; case OFFSETODD2B: rst = 0; break; case GAINHEIGHT: rst = 30; break; case GAINTARGETFACTOR: rst = 80; break; case CALIBPAGON: rst = 0; break; case HIPAGR: rst = 3; break; case HIPAGG: rst = 3; break; case HIPAGB: rst = 3; break; case LOPAGR: rst = 3; break; case LOPAGG: rst = 3; break; case LOPAGB: rst = 3; break; case PAGR: rst = 3; break; case PAGG: rst = 3; break; case PAGB: rst = 3; break; case CALIBGAIN1ON: rst = 1; break; case GAIN1R: rst = 6; break; case GAIN1G: rst = 1; break; case GAIN1B: rst = 7; break; case CALIBGAIN2ON: rst = 0; break; case GAIN2R: rst = 4; break; case GAIN2G: rst = 4; break; case GAIN2B: rst = 4; break; case TOTSHADING: rst = 0; break; case BSHADINGON: rst = -2; break; case BSHADINGHEIGHT: rst = 30; break; case BSHADINGPREDIFFR: rst = 2; break; case BSHADINGPREDIFFG: rst = 2; break; case BSHADINGPREDIFFB: rst = 2; break; case BSHADINGDEFCUTOFF: rst = 0; break; case WSHADINGON: rst = 3; break; case WSHADINGHEIGHT: rst = 24; break; case WSHADINGPREDIFFR: rst = -1; break; case WSHADINGPREDIFFG: rst = -1; break; case WSHADINGPREDIFFB: rst = -1; break; } return rst; } static int fc_calibnegative(int option, int defvalue) { int rst; switch(RTS_Debug->dev_model) { case UA4900: rst = ua4900_calibnegative(option, defvalue); break; case HPG2710: case HP3800: rst = hp3800_calibnegative(option, defvalue); break; case HPG3010: case HP4370: rst = hp4370_calibnegative(option, defvalue); break; case HPG3110: rst = hpg3110_calibnegative(option, defvalue); break; default : rst = hp3970_calibnegative(option, defvalue); break; } return rst; } static int fc_scaninfo_get(int option, int defvalue) { int value[] = {1, 0, 0, 0, 0, 100}; int ua4900_value[] = {1, 0xcdcdcdcd, 0xcdcdcdcd, 0xcdcdcdcd, 0xcdcdcdcd, 100}; int rst = defvalue; int *myvalue = NULL; switch(RTS_Debug->dev_model) { case UA4900: myvalue = ua4900_value; break; default: myvalue = value; break; } switch(option) { case PARKHOMEAFTERCALIB: rst = myvalue[0]; break; case SHADINGTIME_16BIT: rst = myvalue[1]; break; case SHADOWTIME_16BIT: rst = myvalue[2]; break; case SHADINGTIME_8BIT: rst = myvalue[3]; break; case SHADOWTIME_8BIT: rst = myvalue[4]; break; case PREVIEWDPI: rst = myvalue[5]; break; } return rst; } /* fitcalibrate */ static int fitcalibrate_get(int section, int option, int defvalue) { int rst = defvalue; switch(section) { case CALIBREFLECTIVE: rst = fc_calibreflective(option, defvalue); break; case CALIBTRANSPARENT: rst = fc_calibtransparent(option, defvalue); break; case CALIBNEGATIVEFILM: rst = fc_calibnegative(option, defvalue); break; case SCANINFO: rst = fc_scaninfo_get(option, defvalue); break; } return rst; } static int srt_hp3800_scanparam_get(int option, int defvalue) { int rst = defvalue; /* t_rtinifile */ int value3[] = {1, 0, 0, 0, 1, 12, 0, 1, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 0}; int *value = value3; if (value != NULL) switch(option) { case ARRANGELINE: rst = value[0]; break; case COMPRESSION: rst = value[1]; break; case TA_X_START: rst = value[2]; break; case TA_Y_START: rst = value[3]; break; case DPIGAINCONTROL600: rst = value[4]; break; case CRVS: rst = value[5]; break; case MLOCK: rst = value[6]; break; case ENABLEWARMUP: rst = value[7]; break; case NMAXTARGET: rst = value[8]; break; case NMINTARGET: rst = value[9]; break; case NMAXTARGETTA: rst = value[10]; break; case NMINTARGETTA: rst = value[11]; break; case NMAXTARGETNEG: rst = value[12]; break; case NMINTARGETNEG: rst = value[13]; break; case STABLEDIFF: rst = value[14]; break; case DELTAPWM: rst = value[15]; break; case PWMLAMPLEVEL: rst = value[16]; break; case TMAPWMDUTY: rst = value[17]; break; case LEFTLEADING: rst = value[18]; break; } return rst; } static int srt_hp3970_scanparam_get(int file, int option, int defvalue) { int rst = defvalue; /* s_rtinifile */ int value1[] = {1, 0, 150, 0, 1, 6, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 360}; /* s_usb1inifile */ int value2[] = {1, 0, 150, 0, 1, 6, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 360}; /* t_rtinifile */ int value3[] = {1, 0, 150, 0, 1, 12, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 0}; /* t_usb1inifile */ int value4[] = {1, 0, 150, 0, 1, 12, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 0}; int *value = NULL; switch(file) { case S_RTINIFILE: value = value1; break; case S_USB1INIFILE: value = value2; break; case T_RTINIFILE: value = value3; break; case T_USB1INIFILE: value = value4; break; } if (value != NULL) switch(option) { case ARRANGELINE: rst = value[0]; break; case COMPRESSION: rst = value[1]; break; case TA_X_START: rst = value[2]; break; case TA_Y_START: rst = value[3]; break; case DPIGAINCONTROL600: rst = value[4]; break; case CRVS: rst = value[5]; break; case MLOCK: rst = value[6]; break; case ENABLEWARMUP: rst = value[7]; break; case NMAXTARGET: rst = value[8]; break; case NMINTARGET: rst = value[9]; break; case NMAXTARGETTA: rst = value[10]; break; case NMINTARGETTA: rst = value[11]; break; case NMAXTARGETNEG: rst = value[12]; break; case NMINTARGETNEG: rst = value[13]; break; case STABLEDIFF: rst = value[14]; break; case DELTAPWM: rst = value[15]; break; case PWMLAMPLEVEL: rst = value[16]; break; case TMAPWMDUTY: rst = value[17]; break; case LEFTLEADING: rst = value[18]; break; } return rst; } static int srt_hp4370_scanparam_get(int file, int option, int defvalue) { /* s_rtinifile */ int value1[] = {1, 0, 150, 0, 1, 6, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 360}; /* s_usb1inifile */ int value2[] = {1, 0, 150, 0, 1, 6, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 360}; /* t_rtinifile */ int value3[] = {1, 0, 150, 0, 1, 12, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 0}; /* t_usb1inifile */ int value4[] = {1, 0, 150, 0, 1, 12, 0, 0, 170, 140, 40, 30, 40, 30, 1500, 20, 0, 36, 0}; int *value = NULL; int rst = defvalue; switch(file) { case S_RTINIFILE: value = value1; break; case S_USB1INIFILE: value = value2; break; case T_RTINIFILE: value = value3; break; case T_USB1INIFILE: value = value4; break; } if (value != NULL) switch(option) { case ARRANGELINE: rst = value[0]; break; case COMPRESSION: rst = value[1]; break; case TA_X_START: rst = value[2]; break; case TA_Y_START: rst = value[3]; break; case DPIGAINCONTROL600: rst = value[4]; break; case CRVS: rst = value[5]; break; case MLOCK: rst = value[6]; break; case ENABLEWARMUP: rst = value[7]; break; case NMAXTARGET: rst = value[8]; break; case NMINTARGET: rst = value[9]; break; case NMAXTARGETTA: rst = value[10]; break; case NMINTARGETTA: rst = value[11]; break; case NMAXTARGETNEG: rst = value[12]; break; case NMINTARGETNEG: rst = value[13]; break; case STABLEDIFF: rst = value[14]; break; case DELTAPWM: rst = value[15]; break; case PWMLAMPLEVEL: rst = value[16]; break; case TMAPWMDUTY: rst = value[17]; break; case LEFTLEADING: rst = value[18]; break; } return rst; } static int srt_scancali_get(int file, int option, int defvalue) { int rst = defvalue; /* s_rtinifile */ int value1[] = {3, 3, 3, 14, 4, 4, 41, 41, 42, 41, 41, 42, 91, 91, 53, 53, 48, 48, 104, 104, 59, 59, 64,64}; /* s_usb1inifile */ int value2[] = {3, 3, 3, 14, 4, 4, 41, 41, 42, 41, 41, 42, 91, 91, 53, 53, 48, 48, 104, 104, 59, 59, 64, 64}; /* t_rtinifile*/ int value3[] = {3, 3, 3, 14, 4, 4, 41, 41, 42, 41, 41, 42, 270, 270, 511, 511, 511, 511, 270, 270, 511, 511, 511, 511}; /* t_usb1inifile*/ int value4[] = {3, 3, 3, 14, 4, 4, 41, 41, 42, 41, 41, 42, 270, 270, 511, 511, 511, 511, 270, 270, 511, 511, 511, 511}; int *value = NULL; switch(file) { case S_RTINIFILE: value = value1; break; case S_USB1INIFILE: value = value2; break; case T_RTINIFILE: value = value3; break; case T_USB1INIFILE: value = value4; break; } if (value != NULL) switch(option) { case PGA1: rst = value[0]; break; case PGA2: rst = value[1]; break; case PGA3: rst = value[2]; break; case VGAGAIN11: rst = value[3]; break; case VGAGAIN12: rst = value[4]; break; case VGAGAIN13: rst = value[5]; break; case DCSTEPEVEN1: rst = value[6]; break; case DCSTEPODD1: rst = value[7]; break; case DCSTEPEVEN2: rst = value[8]; break; case DCSTEPODD2: rst = value[9]; break; case DCSTEPEVEN3: rst = value[10]; break; case DCSTEPODD3: rst = value[11]; break; case FIRSTDCOFFSETEVEN11: rst = value[12]; break; case FIRSTDCOFFSETODD11: rst = value[13]; break; case FIRSTDCOFFSETEVEN12: rst = value[14]; break; case FIRSTDCOFFSETODD12: rst = value[15]; break; case FIRSTDCOFFSETEVEN13: rst = value[16]; break; case FIRSTDCOFFSETODD13: rst = value[17]; break; case DCOFFSETEVEN11: rst = value[18]; break; case DCOFFSETODD11: rst = value[19]; break; case DCOFFSETEVEN12: rst = value[20]; break; case DCOFFSETODD12: rst = value[21]; break; case DCOFFSETEVEN13: rst = value[22]; break; case DCOFFSETODD13: rst = value[23]; break; } return rst; } static int srt_truegrayparam_get(int file, int option, int defvalue) { int rst = defvalue; /* s_rtinifile */ int value1[] = {100, 30, 59, 11}; /* s_usb1inifile */ int value2[] = {100, 30, 59, 11}; /* t_rtinifile */ int value3[] = {100, 30, 59, 11}; /* t_usb1inifile */ int value4[] = {100, 30, 59, 11}; int *value = NULL; switch(file) { case S_RTINIFILE: value = value1; break; case S_USB1INIFILE: value = value2; break; case T_RTINIFILE: value = value3; break; case T_USB1INIFILE: value = value4; break; } if (value != NULL) switch(option) { case SHADINGBASE: rst = value[0]; break; case SHADINGFACT1: rst = value[1]; break; case SHADINGFACT2: rst = value[2]; break; case SHADINGFACT3: rst = value[3]; break; } return rst; } static int srt_caliparam_get(int file, int option, int defvalue) { int rst = defvalue; /* s_rtinifile */ int value1[] = {0xffff}; /* s_usb1inifile */ int value2[] = {0xffff}; /* t_rtinifile */ int value3[] = {0xffff}; /* t_usb1inifile */ int value4[] = {0xffff}; int *value = NULL; switch(file) { case S_RTINIFILE: value = value1; break; case S_USB1INIFILE: value = value2; break; case T_RTINIFILE: value = value3; break; case T_USB1INIFILE: value = value4; break; } if (value != NULL) switch(option) { case PIXELDARKLEVEL: rst = value[0]; break; } return rst; } static int srt_hp3800_platform_get(int option, int defvalue) { /* s_rtinifile*/ int value1[] = {100, 99, 1214636}; int *value = value1; int rst = defvalue; if (value != NULL) { switch(option) { case BINARYTHRESHOLDH: rst = value[0]; break; case BINARYTHRESHOLDL: rst = value[1]; break; case CLOSETIME: rst = value[2]; break; } } return rst; } static int srt_hp3970_platform_get(int option, int defvalue) { /* s_rtinifile*/ int value1[] = {128, 127, 1214636}; int *value = value1; int rst = defvalue; if (value != NULL) { switch(option) { case BINARYTHRESHOLDH: rst = value[0]; break; case BINARYTHRESHOLDL: rst = value[1]; break; case CLOSETIME: rst = value[2]; break; } } return rst; } static int srt_ua4900_platform_get(int option, int defvalue) { int value1[] = {128, 127, 1214636}; int *value = value1; int rst = defvalue; if (value != NULL) { switch(option) { case BINARYTHRESHOLDH: rst = value[0]; break; case BINARYTHRESHOLDL: rst = value[1]; break; case CLOSETIME: rst = value[2]; break; } } return rst; } static int srt_hp4370_platform_get(int option, int defvalue) { /* t_rtinifile */ int value3[] = {128, 127, 1214636}; int *value = value3; int rst = defvalue; if (value != NULL) { switch(option) { case BINARYTHRESHOLDH: rst = value[0]; break; case BINARYTHRESHOLDL: rst = value[1]; break; case CLOSETIME: rst = value[2]; break; } } return rst; } static int srt_scaninfo_get(int file, int option, int defvalue) { int rst = defvalue; int value1[] = {0, 0, 0, 0}; int value2[] = {0, 0, 0, 0}; int value3[] = {0, 0, 0, 0}; int value4[] = {0, 0, 0, 0}; int *value = NULL; switch(file) { case S_RTINIFILE: value = value1; break; case S_USB1INIFILE: value = value2; break; case T_RTINIFILE: value = value3; break; case T_USB1INIFILE: value = value4; break; } if (value != NULL) { switch(option) { case SHADINGTIME_16BIT: rst = value[0]; break; case SHADOWTIME_16BIT: rst = value[1]; break; case SHADINGTIME_8BIT: rst = value[2]; break; case SHADOWTIME_8BIT: rst = value[3]; break; } } return rst; } static int srt_sec_get(int file, int section, int option, int defvalue) { int rst = defvalue; switch(section) { case SCAN_PARAM: switch(RTS_Debug->dev_model) { case HPG2710: case HP3800: rst = srt_hp3800_scanparam_get(option, defvalue); break; case HPG3010: case HPG3110: case HP4370: rst = srt_hp4370_scanparam_get(file, option, defvalue); break; default : rst = srt_hp3970_scanparam_get(file, option, defvalue); break; } break; case SCAN_CALI: rst = srt_scancali_get(file, option, defvalue); break; case TRUE_GRAY_PARAM: rst = srt_truegrayparam_get(file, option, defvalue); break; case CALI_PARAM: rst = srt_caliparam_get(file, option, defvalue); break; case PLATFORM: switch(RTS_Debug->dev_model) { case HPG2710: case HP3800: rst = srt_hp3800_platform_get(option, defvalue); break; case UA4900: rst = srt_ua4900_platform_get(option, defvalue); break; case HPG3010: case HPG3110: case HP4370: rst = srt_hp4370_platform_get(option, defvalue); break; default : rst = srt_hp3970_platform_get(option, defvalue); break; } break; case SCANINFO: rst = srt_scaninfo_get(file, option, defvalue); break; } return rst; } static int get_value(int section, int option, int defvalue, int file) { int rst = defvalue; switch(file) { case FITCALIBRATE: rst = fitcalibrate_get(section, option, defvalue); break; case S_RTINIFILE: case S_USB1INIFILE: case T_RTINIFILE: case T_USB1INIFILE: rst = srt_sec_get(file, section, option, defvalue); break; } return rst; } sane-backends-1.0.27/backend/epsonds.h0000664000175000017500000001011412775312261014440 00000000000000/* * epsonds.c - Epson ESC/I-2 driver. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #ifndef epsonds_h #define epsonds_h #undef BACKEND_NAME #define BACKEND_NAME epsonds #define DEBUG_NOT_STATIC #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include /* for memset and memcpy */ #include #include "sane/sane.h" #include "sane/sanei_backend.h" #include "sane/sanei_debug.h" #include "sane/sanei_usb.h" #include "sane/sanei_jpeg.h" #define EPSONDS_CONFIG_FILE "epsonds.conf" #ifndef PATH_MAX #define PATH_MAX (1024) #endif #ifndef XtNumber #define XtNumber(x) (sizeof(x) / sizeof(x[0])) #define XtOffset(p_type, field) ((size_t)&(((p_type)NULL)->field)) #define XtOffsetOf(s_type, field) XtOffset(s_type*, field) #endif #define ACK 0x06 #define NAK 0x15 #define FS 0x1C #define FBF_STR SANE_I18N("Flatbed") #define TPU_STR SANE_I18N("Transparency Unit") #define ADF_STR SANE_I18N("Automatic Document Feeder") enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_DEPTH, OPT_RESOLUTION, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_EQU_GROUP, OPT_SOURCE, OPT_EJECT, OPT_LOAD, OPT_ADF_MODE, OPT_ADF_SKEW, NUM_OPTIONS }; typedef enum { /* hardware connection to the scanner */ SANE_EPSONDS_NODEV, /* default, no HW specified yet */ SANE_EPSONDS_USB, /* USB interface */ SANE_EPSONDS_NET /* network interface */ } epsonds_conn_type; /* hardware description */ struct epsonds_device { struct epsonds_device *next; epsonds_conn_type connection; char *name; char *model; unsigned int model_id; SANE_Device sane; SANE_Range *x_range; SANE_Range *y_range; SANE_Range dpi_range; SANE_Byte alignment; SANE_Int *res_list; /* list of resolutions */ SANE_Int *depth_list; SANE_Int max_depth; /* max. color depth */ SANE_Bool has_raw; /* supports RAW format */ SANE_Bool has_fb; /* flatbed */ SANE_Range fbf_x_range; /* x range */ SANE_Range fbf_y_range; /* y range */ SANE_Byte fbf_alignment; /* left, center, right */ SANE_Bool fbf_has_skew; /* supports skew correction */ SANE_Bool has_adf; /* adf */ SANE_Range adf_x_range; /* x range */ SANE_Range adf_y_range; /* y range */ SANE_Bool adf_is_duplex; /* supports duplex mode */ SANE_Bool adf_singlepass; /* supports single pass duplex */ SANE_Bool adf_has_skew; /* supports skew correction */ SANE_Bool adf_has_load; /* supports load command */ SANE_Bool adf_has_eject; /* supports eject command */ SANE_Byte adf_alignment; /* left, center, right */ SANE_Byte adf_has_dfd; /* supports double feed detection */ SANE_Bool has_tpu; /* tpu */ SANE_Range tpu_x_range; /* transparency unit x range */ SANE_Range tpu_y_range; /* transparency unit y range */ }; typedef struct epsonds_device epsonds_device; typedef struct ring_buffer { SANE_Byte *ring, *wp, *rp, *end; SANE_Int fill, size; } ring_buffer; /* an instance of a scanner */ struct epsonds_scanner { struct epsonds_scanner *next; struct epsonds_device *hw; int fd; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; SANE_Byte *buf, *line_buffer; ring_buffer *current, front, back; SANE_Bool eof, scanning, canceling, locked, backside, mode_jpeg; SANE_Int left, top, pages, dummy; /* jpeg stuff */ djpeg_dest_ptr jdst; struct jpeg_decompress_struct jpeg_cinfo; struct jpeg_error_mgr jpeg_err; SANE_Bool jpeg_header_seen; /* network buffers */ unsigned char *netbuf, *netptr; size_t netlen; }; typedef struct epsonds_scanner epsonds_scanner; struct mode_param { int color; int flags; int dropout_mask; int depth; }; enum { MODE_BINARY, MODE_GRAY, MODE_COLOR }; #endif sane-backends-1.0.27/backend/pixma_bjnp.h0000664000175000017500000001442413063340150015111 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2008 by Louis Lagendijk based on sane_usb.h: Copyright (C) 2003, 2005 Rene Rebe (sanei_read_int,sanei_set_timeout) Copyright (C) 2001, 2002 Henning Meier-Geinitz This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file sanei_bjnp.h * This file provides a generic BJNP interface. */ #ifndef sanei_bjnp_h #define sanei_bjnp_h #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "pixma.h" #ifdef HAVE_STDLIB_H #include /* for size_t */ #endif /** Initialize sanei_bjnp. * * Call this before any other sanei_bjnp function. */ extern void sanei_bjnp_init (void); /** Find scanners responding to a BJNP broadcast. * * The function sanei_bjnp_attach is called for every device which has * been found. * Serial is the address of the scanner in human readable form of max * SERIAL_MAX characters * @param conf_devices list of pre-configures device URI's to attach * @param attach attach function * @param pixma_devices device informatio needed by attach function * * @return SANE_STATUS_GOOD - on success (even if no scanner was found) */ #define SERIAL_MAX 16 extern SANE_Status sanei_bjnp_find_devices (const char **conf_devices, SANE_Status (*attach_bjnp) (SANE_String_Const devname, SANE_String_Const makemodel, SANE_String_Const serial, const struct pixma_config_t * const pixma_devices[]), const struct pixma_config_t *const pixma_devices[]); /** Open a BJNP device. * * The device is opened by its name devname and the device number is * returned in dn on success. * * Device names consist of an URI * Where: * method = bjnp * hostname = resolvable name or IP-address * port = 8612 for a bjnp scanner, 8610 for a mfnp device * An example could look like this: bjnp://host.domain:8612 * * @param devname name of the device to open * @param dn device number * * @return * - SANE_STATUS_GOOD - on success * - SANE_STATUS_ACCESS_DENIED - if the file couldn't be accessed due to * permissions * - SANE_STATUS_INVAL - on every other error */ extern SANE_Status sanei_bjnp_open (SANE_String_Const devname, SANE_Int * dn); /** Close a BJNP device. * * @param dn device number */ extern void sanei_bjnp_close (SANE_Int dn); /** Activate a BJNP device connection * * @param dn device number */ extern SANE_Status sanei_bjnp_activate (SANE_Int dn); /** De-activate a BJNP device connection * * @param dn device number */ extern SANE_Status sanei_bjnp_deactivate (SANE_Int dn); /** Set the libbjnp timeout for bulk and interrupt reads. * * @param devno device number * @param timeout the new timeout in ms */ extern void sanei_bjnp_set_timeout (SANE_Int devno, SANE_Int timeout); /** Check if sanei_bjnp_set_timeout() is available. */ #define HAVE_SANEI_BJNP_SET_TIMEOUT /** Initiate a bulk transfer read. * * Read up to size bytes from the device to buffer. After the read, size * contains the number of bytes actually read. * * @param dn device number * @param buffer buffer to store read data in * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_bjnp_read_bulk (SANE_Int dn, SANE_Byte * buffer, size_t * size); /** Initiate a bulk transfer write. * * Write up to size bytes from buffer to the device. After the write size * contains the number of bytes actually written. * * @param dn device number * @param buffer buffer to write to device * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_IO_ERROR - if an error occured during the write * - SANE_STATUS_INVAL - on every other error */ extern SANE_Status sanei_bjnp_write_bulk (SANE_Int dn, const SANE_Byte * buffer, size_t * size); /** Initiate a interrupt transfer read. * * Read up to size bytes from the interrupt endpoint from the device to * buffer. After the read, size contains the number of bytes actually read. * * @param dn device number * @param buffer buffer to store read data in * @param size size of the data * * @return * - SANE_STATUS_GOOD - on succes * - SANE_STATUS_EOF - if zero bytes have been read * - SANE_STATUS_IO_ERROR - if an error occured during the read * - SANE_STATUS_INVAL - on every other error * */ extern SANE_Status sanei_bjnp_read_int (SANE_Int dn, SANE_Byte * buffer, size_t * size); /*------------------------------------------------------*/ #endif /* sanei_bjnp_h */ sane-backends-1.0.27/backend/mustek_pp.conf.in0000664000175000017500000000736012112021330016063 00000000000000# For documentation see sane-mustek_pp(5) # Global options: # =============== # # option no_epp # # Disable parallel port mode EPP: works around a known bug in # the Linux parport code. Enable this option, if the backend # hangs when trying to access the parallel port in EPP mode: # # # SANE_DEBUG_SANEI_PA4S2=128 scanimage -L # ... # hangs here -> [sanei_pa4s2] sanei_pa4s2_readbyte: read in EPP mode # # Scanner definition template: # ============================ # # scanner # option ? # option ? # ... # # where: # # is an arbitrary name for the scanner (eg. Mustek-1200CP) # # is the parallel port to which the scanner is connected # Possible values are 0x378, 0x278, and 0x3bc. For Linux, the # mapping between ports an numbers is different for kernel # version 2.2 and 2.4. Port 0x378 corresponds to lp0 on 2.4 kernel. # If you are using libieee1284, you can as well use parport0, etc.. # If you use the magic value * the port is probed. # # is an identification of the scanner type. # Possible values are: # - cis600 (for Mustek 600CP & OEM versions), # - cis1200 (for Mustek 1200CP & OEM versions), # - cis1200+ (for Mustek 1200CP+ & OEM versions), # - ccd300 (for Mustek 600 III EPP & OEM versions) # - ... more types will be added in the future # # is a name of an option, and an optional value # for the option. # Currently available options for *CIS* type scanners are: # - top_adjust : # Vertical adjustment of origin, in millimeter. # Values between -5.0 and +5.0 mm are possible # (floating point). # Default: 0.0 # - slow_skip: # Boolean option. Disables fast skipping to the start # of the scan region. May be necessary in case fast # skipping results in inaccuracies. # Default: fast skipping enabled # - bw : # Black/white discrimination value for lineart scans. # Pixel values below that value are considered black, # others are considered white. Range: 0-255. # Default: 127 # # Currently available options for *CCD* type scanners are: # - wait_bank # usecs to wait for a bank change. Positive integer # values are possible. You shouldn't mess with this # parameter. # Default: 700 # - bw # Black/white discrimination value for lineart scans. # Pixel values below that value are considered black, # others are considered white. Range: 0-255. # Default: 127 # - top # Scanlines to skip to the top area. Positive integer # values are possible. 47 and 56 are values I know of. # Default: 47 # # # Example for a LifeTec LT9350 (Mustek 1200CP clone): # # scanner LT9350 0x378 cis1200 # option top_adjust 0 # option bw 127 # # Example for Mustek 6000P # # scanner 6000P 0x378 ccd300 # option top 56 # # # Uncomment/customize to your needs # # scanner Mustek-600CP 0x378 cis600 # scanner Mustek-1200CP 0x378 cis1200 # scanner Mustek-1200CP+ 0x378 cis1200+ # scanner Mustek-600-IIIEP 0x378 ccd300 # # auto probing: # # scanner mustek-cis600 * cis600 # scanner mustek-cis1200 * cis1200 # scanner mustek-cis1200+ * cis1200+ # scanner mustek-ccd300 * ccd300 sane-backends-1.0.27/backend/kvs1025_usb.c0000664000175000017500000002171712617742237014764 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. */ /* sane - Scanner Access Now Easy. Panasonic KV-S1020C / KV-S1025C USB scanners. */ #define DEBUG_DECLARE_ONLY #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "kvs1025.h" #include "kvs1025_low.h" #include "kvs1025_usb.h" #include "kvs1025_cmds.h" #include "../include/sane/sanei_debug.h" extern PKV_DEV g_devices; /* Chain of devices */ extern const SANE_Device **g_devlist; /* static functions */ /* Attach USB scanner */ static SANE_Status attach_scanner_usb (const char *device_name) { PKV_DEV dev; SANE_Word vendor, product; DBG (DBG_error, "attaching USB scanner %s\n", device_name); sanei_usb_get_vendor_product_byname(device_name,&vendor,&product); dev = (PKV_DEV) malloc (sizeof (KV_DEV)); if (dev == NULL) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (KV_DEV)); dev->bus_mode = KV_USB_BUS; dev->usb_fd = -1; dev->scsi_fd = -1; strcpy (dev->device_name, device_name); dev->buffer0 = (unsigned char *) malloc (SCSI_BUFFER_SIZE + 12); dev->buffer = dev->buffer0 + 12; if (dev->buffer0 == NULL) { free (dev); return SANE_STATUS_NO_MEM; } dev->scsi_type = 6; strcpy (dev->scsi_type_str, "ADF Scanner"); strcpy (dev->scsi_vendor, "Panasonic"); strcpy (dev->scsi_product, product == (int) KV_S1020C ? "KV-S1020C" : product == (int) KV_S1025C ? "KV-S1025C" : product == (int) KV_S1045C ? "KV-S1045C" : "KV-S10xxC"); strcpy (dev->scsi_version, "1.00"); /* Set SANE_Device */ dev->sane.name = dev->device_name; dev->sane.vendor = dev->scsi_vendor; dev->sane.model = dev->scsi_product; dev->sane.type = dev->scsi_type_str; /* Add into g_devices chain */ dev->next = g_devices; g_devices = dev; return SANE_STATUS_GOOD; } /* Get all supported scanners, and store into g_devlist */ SANE_Status kv_usb_enum_devices (void) { int cnt = 0; int i; PKV_DEV pd; char usb_str[18]; DBG (DBG_proc, "kv_usb_enum_devices: enter\n"); sanei_usb_init(); sprintf(usb_str,"usb %#04x %#04x",VENDOR_ID,KV_S1020C); sanei_usb_attach_matching_devices(usb_str, attach_scanner_usb); sprintf(usb_str,"usb %#04x %#04x",VENDOR_ID,KV_S1025C); sanei_usb_attach_matching_devices(usb_str, attach_scanner_usb); sprintf(usb_str,"usb %#04x %#04x",VENDOR_ID,KV_S1045C); sanei_usb_attach_matching_devices(usb_str, attach_scanner_usb); for (pd = g_devices; pd; pd=pd->next) { cnt++; } g_devlist = (const SANE_Device **) malloc (sizeof (SANE_Device *) * (cnt + 1)); if (g_devlist == NULL) { DBG (DBG_proc, "kv_usb_enum_devices: leave on error " " --out of memory\n"); return SANE_STATUS_NO_MEM; } pd = g_devices; for (i = 0; i < cnt; i++) { g_devlist[i] = (const SANE_Device *) &pd->sane; pd = pd->next; } g_devlist[cnt] = 0; DBG (DBG_proc, "kv_usb_enum_devices: leave with %d devices.\n", cnt); return SANE_STATUS_GOOD; } /* Check if device is already open */ SANE_Bool kv_usb_already_open (PKV_DEV dev) { return (dev->usb_fd > -1); } /* Open an USB device */ SANE_Status kv_usb_open (PKV_DEV dev) { SANE_Status ret; DBG (DBG_proc, "kv_usb_open: enter\n"); if (kv_usb_already_open(dev)) { DBG (DBG_proc, "kv_usb_open: leave -- already open\n"); return SANE_STATUS_GOOD; } ret = sanei_usb_open (dev->device_name, &(dev->usb_fd)); if (ret) { DBG (DBG_error, "kv_usb_open: leave -- cannot open device\n"); return SANE_STATUS_IO_ERROR; } sanei_usb_clear_halt (dev->usb_fd); DBG (DBG_proc, "kv_usb_open: leave\n"); return SANE_STATUS_GOOD; } /* Close an USB device */ void kv_usb_close (PKV_DEV dev) { DBG (DBG_proc, "kv_usb_close: enter\n"); if (kv_usb_already_open(dev)) { sanei_usb_close(dev->usb_fd); dev->usb_fd = -1; } DBG (DBG_proc, "kv_usb_close: leave\n"); } /* Clean up the USB bus and release all resources allocated to devices */ void kv_usb_cleanup (void) { } /* Send command via USB, and get response data */ SANE_Status kv_usb_escape (PKV_DEV dev, PKV_CMD_HEADER header, unsigned char *status_byte) { int got_response = 0; size_t len; unsigned char cmd_buff[24]; memset (cmd_buff, 0, 24); cmd_buff[3] = 0x18; /* container length */ cmd_buff[5] = 1; /* container type: command block */ cmd_buff[6] = 0x90; /* code */ if (!kv_usb_already_open(dev)) { DBG (DBG_error, "kv_usb_escape: error, device not open.\n"); return SANE_STATUS_IO_ERROR; } memcpy (cmd_buff + 12, header->cdb, header->cdb_size); /* change timeout */ sanei_usb_set_timeout(KV_CMD_TIMEOUT); /* Send command */ len = 24; if (sanei_usb_write_bulk (dev->usb_fd, (SANE_Byte *) cmd_buff, &len)) { DBG (DBG_error, "usb_bulk_write: Error writing command.\n"); hexdump (DBG_error, "cmd block", cmd_buff, 24); return SANE_STATUS_IO_ERROR; } /* Send / Read data */ if (header->direction == KV_CMD_IN) { size_t size = header->data_size + 12; size_t size_read = size; unsigned char *data = ((unsigned char *) header->data) - 12; SANE_Status ret; ret = sanei_usb_read_bulk (dev->usb_fd, (SANE_Byte *) data, &size_read); /*empty read is ok?*/ if (ret == SANE_STATUS_EOF){ sanei_usb_clear_halt (dev->usb_fd); ret = SANE_STATUS_GOOD; } if (ret) { sanei_usb_clear_halt (dev->usb_fd); DBG (DBG_error, "usb_bulk_read: Error reading data.\n"); return SANE_STATUS_IO_ERROR; } if (size_read != size) { DBG (DBG_shortread, "usb_bulk_read: Warning - short read\n"); DBG (DBG_shortread, "usb_bulk_read: bytes to read = %lu\n", (unsigned long)size); DBG (DBG_shortread, "usb_bulk_read: bytes actual read = %lu\n", (unsigned long)size_read); /*hexdump (DBG_shortread, "data", data, size_read); */ } } if (header->direction == KV_CMD_OUT) { size_t size = header->data_size + 12; size_t size_written = size; unsigned char *data = ((unsigned char *) header->data) - 12; SANE_Status ret; memset (data, 0, 12); Ito32 (size, data); data[5] = 0x02; /* container type: data block */ data[6] = 0xb0; /* code */ ret = sanei_usb_write_bulk (dev->usb_fd, (SANE_Byte *) data, &size_written); /*empty write is ok?*/ if (ret == SANE_STATUS_EOF){ sanei_usb_clear_halt (dev->usb_fd); ret = SANE_STATUS_GOOD; } if (ret) { sanei_usb_clear_halt (dev->usb_fd); DBG (DBG_error, "usb_bulk_write: Error writing data.\n"); return SANE_STATUS_IO_ERROR; } if (size_written != size) { DBG (DBG_shortread, "usb_bulk_write: Warning - short written\n"); DBG (DBG_shortread, "usb_bulk_write: bytes to write = %lu\n", (unsigned long)size); DBG (DBG_shortread, "usb_bulk_write: bytes actual written = %lu\n", (unsigned long)size_written); hexdump (DBG_shortread, "data", data, size_written); } } /* Get response */ if (!got_response) { SANE_Status ret; size_t len = 16; ret = sanei_usb_read_bulk (dev->usb_fd, (SANE_Byte *) cmd_buff, &len); if (ret || len != 16) { DBG (DBG_error, "usb_bulk_read: Error reading response." " read %lu bytes\n", (unsigned long)len); sanei_usb_clear_halt (dev->usb_fd); return SANE_STATUS_IO_ERROR; } } if (cmd_buff[5] != 3) { DBG (DBG_error, "usb_bulk_read: Invalid response block.\n"); hexdump (DBG_error, "response", cmd_buff, 16); return SANE_STATUS_IO_ERROR; } *status_byte = cmd_buff[15] & 0x3E; return SANE_STATUS_GOOD; } /* Send command via USB, and request sense on CHECK CONDITION status */ SANE_Status kv_usb_send_command (PKV_DEV dev, PKV_CMD_HEADER header, PKV_CMD_RESPONSE response) { unsigned char status = 0; SANE_Status s; memset (response, 0, sizeof (KV_CMD_RESPONSE)); response->status = KV_FAILED; s = kv_usb_escape (dev, header, &status); if (s) { status = 0x02; } if (status == 0x02) { /* check condition */ /* request sense */ KV_CMD_HEADER hdr; memset (&hdr, 0, sizeof (hdr)); hdr.direction = KV_CMD_IN; hdr.cdb[0] = SCSI_REQUEST_SENSE; hdr.cdb[4] = 0x12; hdr.cdb_size = 6; hdr.data_size = 0x12; hdr.data = &response->sense; if (kv_usb_escape (dev, &hdr, &status) != 0) return SANE_STATUS_IO_ERROR; hexdump (DBG_error, "sense data", (unsigned char *) &response->sense, 0x12); response->status = KV_CHK_CONDITION; } else { response->status = KV_SUCCESS; } return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/plustek.h0000664000175000017500000003246012112021330014437 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek.h * @brief Definitions for the backend. * * Based on Kazuhiro Sasayama previous * work on plustek.[ch] file from the SANE package.
* * original code taken from sane-0.71
* Copyright (C) 1997 Hypercore Software Design, Ltd.
* Copyright (C) 2001-2007 Gerhard Jaeger * * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - no changes * - 0.33 - no changes * - 0.34 - moved some definitions and typedefs from plustek.c * - 0.35 - removed OPT_MODEL from options list * - added max_y to struct Plustek_Scan * - 0.36 - added reader_pid, pipe and bytes_read to struct Plustek_Scanner * - removed unused variables from struct Plustek_Scanner * - moved fd from struct Plustek_Scanner to Plustek_Device * - added next members to struct Plustek_Scanner and Plustek_Device * - 0.37 - added max_x to struct Plustek_Device * - 0.38 - added caps to struct Plustek_Device * - added exit code to struct Plustek_Scanner * - removed dropout stuff * - 0.39 - PORTTYPE enum * - added function pointers to control a scanner device * (Parport and USB) * - 0.40 - added USB stuff * - 0.41 - added configuration stuff * - 0.42 - added custom gamma tables * - changed usbId to static array * - added _MAX_ID_LEN * - 0.43 - no changes * - 0.44 - added flag initialized * - 0.45 - added readLine function * - 0.46 - flag initialized is now used as device index * - added calFile to Plustek_Device * - removed _OPT_HALFTONE * - 0.47 - added mov to adjustment * - changed stopScan function definition * - removed open function * - added OPT_LAMPSWITCH and OPT_WARMUPTIME * - 0.48 - added OPT_CACHECAL, OPT_OVR_*, OPT_LAMPOFF_TIMER and * OPT_LAMPOFF_ONEND, also did some cleanup * - moved SCANDEF definitions to plustek-usb.h * - removed function pointer * - added OPT_BIT_DEPTH * - 0.49 - added typedef struct DevList * - added button stuff * - added transferRate to struct Plustek_Device * - 0.50 - cleanup * - added OPT_SPEEDUP * - 0.51 - added OPT_CALIBRATE * - 0.52 - added skipDarkStrip and incDarkTgt to struct AdjDef * - added OPT_LOFF4DARK * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifndef __PLUSTEK_H__ #define __PLUSTEK_H__ /************************ some definitions ***********************************/ #define PLUSTEK_CONFIG_FILE "plustek.conf" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define _MEASURE_BASE 300UL #define _DEF_DPI 50 #define DEFAULT_RATE 1000000 /** the default image size */ #define _DEFAULT_TLX 0 /* 0..216 mm */ #define _DEFAULT_TLY 0 /* 0..297 mm */ #define _DEFAULT_BRX 103 /* 0..216 mm */ #define _DEFAULT_BRY 76.21 /* 0..297 mm */ #define _DEFAULT_TP_TLX 3.5 /* 0..42.3 mm */ #define _DEFAULT_TP_TLY 10.5 /* 0..43.1 mm */ #define _DEFAULT_TP_BRX 38.5 /* 0..42.3 mm */ #define _DEFAULT_TP_BRY 33.5 /* 0..43.1 mm */ #define _DEFAULT_NEG_TLX 1.5 /* 0..38.9 mm */ #define _DEFAULT_NEG_TLY 1.5 /* 0..29.6 mm */ #define _DEFAULT_NEG_BRX 37.5 /* 0..38.9 mm */ #define _DEFAULT_NEG_BRY 25.5 /* 0..29.6 mm */ /** image sizes for normal, transparent and negative modes */ #define _TPAPageWidth 500UL #define _TPAPageHeight 510UL #define _TPALargePageWidth 1270UL #define _TPALargePageHeight 1570UL #define _TPAMinDpi 150 #define _NegPageWidth 460UL #define _NegPageHeight 350UL #define _NegLargePageWidth 1270UL #define _NegLargePageHeight 1570UL #define _SCALE(X) ((double)(X)/300.0 * MM_PER_INCH) /** scan modes */ #define COLOR_BW 0 #define COLOR_256GRAY 1 #define COLOR_GRAY16 2 #define COLOR_TRUE24 3 #define COLOR_TRUE48 4 /** usb id buffer */ #define _MAX_ID_LEN 20 /** */ #define SFLAG_ADF 0x00000010 /* Automatic document feeder */ #define SFLAG_TPA 0x00000080 /* has transparency adapter */ /** */ #define SOURCE_Reflection 0 #define SOURCE_Transparency 1 #define SOURCE_Negative 2 #define SOURCE_ADF 3 /** for Gamma tables */ #define _MAP_RED 0 #define _MAP_GREEN 1 #define _MAP_BLUE 2 #define _MAP_MASTER 3 /** generic error codes... */ #define _FIRST_ERR -9000 #define _E_ALLOC (_FIRST_ERR-1) /**< error allocating memory */ #define _E_INVALID (_FIRST_ERR-2) /**< invalid parameter detected */ #define _E_INTERNAL (_FIRST_ERR-3) /**< internal error */ #define _E_ABORT (_FIRST_ERR-4) /**< operation aborted */ #define _E_LAMP_NOT_IN_POS (_FIRST_ERR-10) #define _E_LAMP_NOT_STABLE (_FIRST_ERR-11) #define _E_NODATA (_FIRST_ERR-12) #define _E_BUFFER_TOO_SMALL (_FIRST_ERR-13) #define _E_DATAREAD (_FIRST_ERR-14) /************************ some structures ************************************/ #define _ENABLE(option) s->opt[option].cap &= ~SANE_CAP_INACTIVE #define _DISABLE(option) s->opt[option].cap |= SANE_CAP_INACTIVE enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, OPT_BIT_DEPTH, OPT_EXT_MODE, OPT_RESOLUTION, OPT_PREVIEW, OPT_GEOMETRY_GROUP, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_CUSTOM_GAMMA, OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_DEVICE_GROUP, OPT_LAMPSWITCH, OPT_LAMPOFF_TIMER, OPT_LAMPOFF_ONEND, OPT_WARMUPTIME, OPT_LOFF4DARK, OPT_CACHECAL, OPT_SPEEDUP, OPT_CALIBRATE, OPT_AFE_GROUP, OPT_OVR_REDGAIN, OPT_OVR_GREENGAIN, OPT_OVR_BLUEGAIN, OPT_OVR_REDOFS, OPT_OVR_GREENOFS, OPT_OVR_BLUEOFS, OPT_OVR_RED_LOFF, OPT_OVR_GREEN_LOFF, OPT_OVR_BLUE_LOFF, OPT_BUTTON_GROUP, OPT_BUTTON_0, OPT_BUTTON_1, OPT_BUTTON_2, OPT_BUTTON_3, OPT_BUTTON_4, OPT_BUTTON_LAST = OPT_BUTTON_4, NUM_OPTIONS }; /** */ typedef struct { int x; int y; } OffsDef, *pOffsDef; /** for adjusting the scanner settings */ typedef struct { int mov; /**< model override */ int lampOff; int lampOffOnEnd; int warmup; int enableTpa; int skipCalibration; /**< skip entire calibration */ int skipFine; int skipFineWhite; int skipDarkStrip; int incDarkTgt; int disableSpeedup; int invertNegatives; int cacheCalData; int altCalibrate; /* force use of the alternate canoscan autocal; perhaps other Canon scanners require the alternate autocalibration as well */ /* AFE adjustemnts, gain and offset */ int rgain; int ggain; int bgain; int rofs; int gofs; int bofs; int rlampoff; /* for red lamp off setting (CIS-scanner) */ int glampoff; /* for green lamp off setting (CIS-scanner) */ int blampoff; /* for blue lamp off setting (CIS-scanner) */ OffsDef pos; /* for adjusting normal scan area */ OffsDef tpa; /* for adjusting transparency scan area */ OffsDef neg; /* for adjusting negative scan area */ int posShadingY; int tpaShadingY; int negShadingY; /* for adjusting the default gamma settings */ double rgamma; double ggamma; double bgamma; double graygamma; } AdjDef; typedef struct { unsigned short x; unsigned short y; unsigned short cx; unsigned short cy; } CropRect; typedef struct image { unsigned long dwFlag; CropRect crArea; XY xyDpi; unsigned short wDataType; } ImgDef; typedef struct { unsigned long dwPixelsPerLine; unsigned long dwBytesPerLine; unsigned long dwLinesPerArea; ImgDef ImgDef; } CropInfo; typedef struct { ImgDef ImgDef; short siBrightness; short siContrast; } ScanInfo; typedef struct { unsigned long dwFlag; unsigned short wMaxExtentX; /**< scanarea width */ unsigned short wMaxExtentY; /**< scanarea height */ } ScannerCaps; typedef struct Plustek_Device { SANE_Int initialized; /* device already initialized? */ struct Plustek_Device *next; /* pointer to next dev in list */ int fd; /* device handle */ char *name; /* (to avoid compiler warnings!)*/ char *calFile; /* for saving calibration data */ unsigned long transferRate; /* detected USB-Speed in Bytes/s*/ SANE_Device sane; /* info struct */ SANE_Int max_x; /* max XY-extension of the scan-*/ SANE_Int max_y; /* area */ SANE_Range dpi_range; /* resolution range */ SANE_Range x_range; /* x-range of the scan-area */ SANE_Range y_range; /* y-range of the scan-area */ SANE_Int *res_list; /* to hold the available phys. */ SANE_Int res_list_size; /* resolution values */ ScannerCaps caps; /* caps reported by the driver */ AdjDef adj; /* for driver adjustment */ /**************************** USB-stuff **********************************/ char usbId[_MAX_ID_LEN];/* to keep Vendor and product */ /* ID string (from conf) file */ struct ScanDef scanning; /* here we hold all stuff for */ /* the USB-scanner */ struct DeviceDef usbDev; #ifdef HAVE_SETITIMER struct itimerval saveSettings; /* for lamp timer */ #endif } Plustek_Device; #ifndef SANE_OPTION /* for compatibility with older versions */ typedef union { SANE_Word w; SANE_Word *wa; SANE_String s; } Option_Value; #endif typedef struct Plustek_Scanner { struct Plustek_Scanner *next; SANE_Pid reader_pid; /* process id of reader */ SANE_Status exit_code; /* status of the reader process */ int r_pipe; /* pipe to reader process */ int w_pipe; /* pipe from reader process */ unsigned long bytes_read; /* number of bytes currently read*/ Plustek_Device *hw; /* pointer to current device */ Option_Value val[NUM_OPTIONS]; SANE_Byte *buf; /* the image buffer */ SANE_Bool scanning; /* TRUE during scan-process */ SANE_Bool calibrating; /* TRUE during calibration */ SANE_Bool ipc_read_done; /* TRUE after ipc has been red */ SANE_Parameters params; /* for keeping the parameter */ /************************** gamma tables *********************************/ SANE_Word gamma_table[4][4096]; SANE_Range gamma_range; int gamma_length; SANE_Option_Descriptor opt[NUM_OPTIONS]; } Plustek_Scanner; /** for collecting configuration info... */ typedef struct { char devName[PATH_MAX]; char usbId[_MAX_ID_LEN]; /* contains the stuff to adjust... */ AdjDef adj; } CnfDef; /** for supported device list */ typedef struct DevList { SANE_Word vendor_id; SANE_Word device_id; SANE_Bool attached; SANE_Char *dev_name; struct DevList *next; } DevList; #endif /* guard __PLUSTEK_H__ */ /* END PLUSTEK.H.............................................................*/ sane-backends-1.0.27/backend/Makefile.am0000644000175000017500000020471713072433473014664 00000000000000## Makefile.am -- an automake template for Makefile.in file ## Copyright (C) 2009 Chris Bagwell, Olaf Meeuwissen, and Sane Developers. ## ## This file is part of the "Sane" build infra-structure. See ## included LICENSE file for license information. AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include $(USB_CFLAGS) -DLIBDIR="\"$(libdir)/sane\"" AM_LDFLAGS += $(STRICT_LDFLAGS) # The -rpath option is added because we are creating _LTLIBRARIES based # on configure substitution. This causes automake to not know the # correct $libdir and must be added here. DIST_SANELIBS_LDFLAGS = $(AM_LDFLAGS) -rpath '$(libdir)/sane' -version-number $(V_MAJOR):$(V_MINOR):$(V_REV) $(DYNAMIC_FLAG) DIST_LIBS_LDFLAGS = $(AM_LDFLAGS) -rpath '$(libdir)' -version-number $(V_MAJOR):$(V_MINOR):$(V_REV) # LIBTOOL install is a little to noisy for my liking. LIBTOOL += --silent FIRMWARE_DIRS = artec_eplus48u gt68xx snapscan epjitsu EXTRA_DIST = sane_strstatus.c all: becfg EXTRA_DIST += stubs.c # FIXME: % is a GNU extension... This is only thing left requiring # use to use GNU make. %-s.c: $(srcdir)/stubs.c $(AM_V_at)rm -f $@ $(AM_V_at)$(LN_S) $(srcdir)/stubs.c $@ dll-preload.h: $(AM_V_at)rm -f $@ $(AM_V_at)list="$(PRELOADABLE_BACKENDS)"; for be in $$list; do \ echo "PRELOAD_DECL($$be)" >> $@; \ done; \ echo "static struct backend preloaded_backends[] = {" >> $@; \ sep=""; \ list="$(PRELOADABLE_BACKENDS)"; \ if test -z "$${list}"; then \ echo { 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} >> $@; \ else \ for be in $$list; do \ echo "$${sep}PRELOAD_DEFN($$be)" >> $@; \ sep=","; \ done; \ fi; \ echo "};" >> $@ # TODO: This really belongs together with the saned sources and # should be installed there as well. EXTRA_DIST += saned.conf.in # Backends are not required to have a config file. Any backend # that wants to install a config file should list it here. BACKEND_CONFS= abaton.conf agfafocus.conf apple.conf artec.conf \ artec_eplus48u.conf avision.conf bh.conf \ canon630u.conf canon.conf canon_dr.conf \ canon_pp.conf cardscan.conf coolscan2.conf coolscan3.conf \ coolscan.conf dc210.conf dc240.conf dc25.conf \ dell1600n_net.conf dmc.conf epjitsu.conf epson2.conf \ epson.conf epsonds.conf fujitsu.conf genesys.conf gphoto2.conf \ gt68xx.conf hp3900.conf hp4200.conf hp5400.conf \ hp.conf hpsj5s.conf hs2p.conf ibm.conf kodak.conf kodakaio.conf\ kvs1025.conf \ leo.conf lexmark.conf ma1509.conf magicolor.conf \ matsushita.conf microtek2.conf microtek.conf mustek.conf \ mustek_pp.conf mustek_usb.conf nec.conf net.conf \ p5.conf \ pie.conf pieusb.conf pixma.conf plustek.conf plustek_pp.conf \ qcam.conf ricoh.conf rts8891.conf s9036.conf sceptre.conf \ sharp.conf sm3840.conf snapscan.conf sp15c.conf \ st400.conf stv680.conf tamarack.conf \ teco1.conf teco2.conf teco3.conf test.conf \ u12.conf umax1220u.conf umax.conf umax_pp.conf v4l.conf \ xerox_mfp.conf dll.conf saned.conf becfg: $(BACKEND_CONFS) SUFFIXES = .conf.in .conf .conf.in.conf: @echo Generating $@ from $^ @sed -e 's|@DATADIR@|$(datadir)|g' \ -e 's|@CONFIGDIR@|$(configdir)|g' \ -e 's|@DOCDIR@|$(docdir)|g' \ -e 's|@LIBDIR@|$(libdir)/sane|g' \ -e 's|@BINDIR@|$(bindir)|g' \ -e 's|@SBINDIR@|$(sbindir)|g' \ -e 's|@PACKAGEVERSION@|$(PACKAGE_VERSION)|g' $? > $@ install-data-hook: install-becfg install-firmware-path $(INSTALL_LOCKPATH) # Custom install target to install config files. Do not overwrite # files that have been previously installed so that user modifications # are not lost. install-becfg: @# Libtool has a bug where it will sometimes symlink the last @# installed library in $(sanelibdir) to $(sanelibdir)/libsane.*. @# Having two libsane's can cause issues so get rid of it. -rm -f $(DESTDIR)$(sanelibdir)/libsane.* test -z "$(configdir)" || $(MKDIR_P) "$(DESTDIR)$(configdir)" test -z "$(configdir)/dll.d" || $(MKDIR_P) "$(DESTDIR)$(configdir)/dll.d" @list="$(BACKEND_CONFS_ENABLED) saned.conf dll.conf"; for cfg in $$list; do \ if test ! -r $${cfg}; then continue; fi; \ if test -f $(DESTDIR)$(configdir)/$${cfg}; then \ echo NOT overwriting $${cfg} in $(configdir)...; \ else \ echo installing $${cfg} in $(configdir)/$${cfg}...; \ $(INSTALL_DATA) $${cfg} $(DESTDIR)$(configdir)/$${cfg} \ || exit 1; \ fi; \ done install-firmware-path: for dir in $(FIRMWARE_DIRS) ; do \ $(mkinstalldirs) $(DESTDIR)$(datadir)/sane/$${dir} ; \ done install-lockpath: $(mkinstalldirs) -m 775 $(DESTDIR)$(locksanedir) uninstall-hook: rm -rf $(DESTDIR)$(libdir)/sane $(DESTDIR)$(configdir) $(DESTDIR)$(locksanedir) rm -f $(DESTDIR)$(libdir)/libsane.* -for dir in $(FIRMWARE_DIRS) ; do \ rmdir $(DESTDIR)$(datadir)/sane/$${dir} ; \ done CLEANFILES = $(BACKEND_CONFS) $(be_convenience_libs) clean-local: find . -type l -name \*-s.c | xargs rm -f # Backends # # All possible backends should be listed here. As a first step, we create # a convenience library containing all files needed to link a backend # directly into libsane.la. Convenience library should have the # form of lib${backend}.la to match what configure will list to # build. # Occasionally, this approach will have name conflicts with external # libraries that need to be linked in. See libgphoto2_i.la for # example of working around that issue. be_convenience_libs = libabaton.la libagfafocus.la \ libapple.la libartec.la libartec_eplus48u.la \ libas6e.la libavision.la libbh.la \ libcanon.la libcanon630u.la libcanon_dr.la \ libcanon_pp.la libcardscan.la libcoolscan.la \ libcoolscan2.la libcoolscan3.la libdc25.la \ libdc210.la libdc240.la libdell1600n_net.la \ libdmc.la libdll.la libdll_preload.la libepjitsu.la libepson.la \ libepson2.la libepsonds.la libfujitsu.la libgenesys.la \ libgphoto2_i.la libgt68xx.la libhp.la \ libhp3500.la libhp3900.la libhp4200.la \ libhp5400.la libhp5590.la libhpljm1005.la \ libhpsj5s.la libhs2p.la libibm.la libkodak.la libkodakaio.la\ libkvs1025.la libkvs20xx.la libkvs40xx.la \ libleo.la liblexmark.la libma1509.la libmagicolor.la \ libmatsushita.la libmicrotek.la libmicrotek2.la \ libmustek.la libmustek_pp.la libmustek_usb.la \ libmustek_usb2.la libnec.la libnet.la \ libniash.la libp5.la \ libpie.la libpieusb.la libpint.la libpixma.la \ libplustek.la libplustek_pp.la libpnm.la \ libqcam.la libricoh.la librts8891.la \ libs9036.la libsceptre.la libsharp.la \ libsm3600.la libsm3840.la libsnapscan.la \ libsp15c.la libst400.la libstv680.la \ libtamarack.la libtest.la libteco1.la \ libteco2.la libteco3.la libu12.la libumax.la \ libumax1220u.la libumax_pp.la libv4l.la \ libxerox_mfp.la # Each stand alone backend thats possible to be built should be listed # here. There are the libraries that are installed under $(libdir)/sane. # Format is libsane-${backend}.la. be_dlopen_libs = libsane-abaton.la libsane-agfafocus.la \ libsane-apple.la libsane-artec.la libsane-artec_eplus48u.la \ libsane-as6e.la libsane-avision.la libsane-bh.la \ libsane-canon.la libsane-canon630u.la libsane-canon_dr.la \ libsane-canon_pp.la libsane-cardscan.la libsane-coolscan.la \ libsane-coolscan2.la libsane-coolscan3.la libsane-dc25.la \ libsane-dc210.la libsane-dc240.la libsane-dell1600n_net.la \ libsane-dmc.la libsane-epjitsu.la libsane-epson.la \ libsane-epson2.la libsane-epsonds.la libsane-fujitsu.la libsane-genesys.la \ libsane-gphoto2.la libsane-gt68xx.la libsane-hp.la \ libsane-hp3500.la libsane-hp3900.la libsane-hp4200.la \ libsane-hp5400.la libsane-hp5590.la libsane-hpljm1005.la \ libsane-hpsj5s.la libsane-hs2p.la libsane-ibm.la libsane-kodak.la libsane-kodakaio.la\ libsane-kvs1025.la libsane-kvs20xx.la libsane-kvs40xx.la \ libsane-leo.la \ libsane-lexmark.la libsane-ma1509.la libsane-magicolor.la \ libsane-matsushita.la libsane-microtek.la libsane-microtek2.la \ libsane-mustek.la libsane-mustek_pp.la libsane-mustek_usb.la \ libsane-mustek_usb2.la libsane-nec.la libsane-net.la \ libsane-niash.la libsane-p5.la \ libsane-pie.la libsane-pieusb.la libsane-pint.la libsane-pixma.la \ libsane-plustek.la libsane-plustek_pp.la libsane-pnm.la \ libsane-qcam.la libsane-ricoh.la libsane-rts8891.la \ libsane-s9036.la libsane-sceptre.la libsane-sharp.la \ libsane-sm3600.la libsane-sm3840.la libsane-snapscan.la \ libsane-sp15c.la libsane-st400.la libsane-stv680.la \ libsane-tamarack.la libsane-test.la libsane-teco1.la \ libsane-teco2.la libsane-teco3.la libsane-u12.la libsane-umax.la \ libsane-umax1220u.la libsane-umax_pp.la libsane-v4l.la \ libsane-xerox_mfp.la EXTRA_LTLIBRARIES = $(be_convenience_libs) $(be_dlopen_libs) lib_LTLIBRARIES = libsane.la sanelibdir = $(libdir)/sane sanelib_LTLIBRARIES = $(BACKEND_LIBS_ENABLED) libsane-dll.la COMMON_LIBS = ../lib/liblib.la # Each backend should define a convenience library that compiles # all related files within backend directory. General guideline # is to have a ${backend}.c and ${backend}.h. Some backends also # add a few support source files to convience library. # Note: automake doesn't really use header files listed here. # They are indications that they need to be distributed only. libabaton_la_SOURCES = abaton.c abaton.h libabaton_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=abaton # Each backend should define a stand alone library that gets installed. # This will need to link in a special file ${backend}-s.c that allows # the backend to be stand alone and contain all SANE API functions. # Also, it will need to link in related convenience library as well as # any external libraries required to resolve symbols. # # All backends should include $(DIST_SANELIBS_LDFLAGS) so that # library is correctly versioned. # # If a backend has a config file, it must be listed here to get distributed. nodist_libsane_abaton_la_SOURCES = abaton-s.c libsane_abaton_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=abaton libsane_abaton_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_abaton_la_LIBADD = $(COMMON_LIBS) libabaton.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += abaton.conf.in libagfafocus_la_SOURCES = agfafocus.c agfafocus.h libagfafocus_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=agfafocus nodist_libsane_agfafocus_la_SOURCES = agfafocus-s.c libsane_agfafocus_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=agfafocus libsane_agfafocus_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_agfafocus_la_LIBADD = $(COMMON_LIBS) libagfafocus.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += agfafocus.conf.in libapple_la_SOURCES = apple.c apple.h libapple_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=apple nodist_libsane_apple_la_SOURCES = apple-s.c libsane_apple_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=apple libsane_apple_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_apple_la_LIBADD = $(COMMON_LIBS) libapple.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += apple.conf.in libartec_la_SOURCES = artec.c artec.h libartec_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec nodist_libsane_artec_la_SOURCES = artec-s.c libsane_artec_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_artec_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec libsane_artec_la_LIBADD = $(COMMON_LIBS) libartec.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += artec.conf.in libartec_eplus48u_la_SOURCES = artec_eplus48u.c artec_eplus48u.h libartec_eplus48u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec_eplus48u nodist_libsane_artec_eplus48u_la_SOURCES = artec_eplus48u-s.c libsane_artec_eplus48u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=artec_eplus48u libsane_artec_eplus48u_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_artec_eplus48u_la_LIBADD = $(COMMON_LIBS) libartec_eplus48u.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMEG_LIBS) EXTRA_DIST += artec_eplus48u.conf.in libas6e_la_SOURCES = as6e.c as6e.h libas6e_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=as6e nodist_libsane_as6e_la_SOURCES = as6e-s.c libsane_as6e_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=as6e libsane_as6e_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_as6e_la_LIBADD = $(COMMON_LIBS) libas6e.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo libavision_la_SOURCES = avision.c avision.h libavision_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=avision nodist_libsane_avision_la_SOURCES = avision-s.c libsane_avision_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=avision libsane_avision_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_avision_la_LIBADD = $(COMMON_LIBS) libavision.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += avision.conf.in libbh_la_SOURCES = bh.c bh.h libbh_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=bh nodist_libsane_bh_la_SOURCES = bh-s.c libsane_bh_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=bh libsane_bh_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_bh_la_LIBADD = $(COMMON_LIBS) libbh.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += bh.conf.in libcanon_la_SOURCES = canon.c canon.h libcanon_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon nodist_libsane_canon_la_SOURCES = canon-s.c libsane_canon_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon libsane_canon_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_canon_la_LIBADD = $(COMMON_LIBS) libcanon.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += canon.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += canon-sane.c canon-scsi.c libcanon630u_la_SOURCES = canon630u.c libcanon630u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon630u nodist_libsane_canon630u_la_SOURCES = canon630u-s.c libsane_canon630u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon630u libsane_canon630u_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_canon630u_la_LIBADD = $(COMMON_LIBS) libcanon630u.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += canon630u.conf.in # TODO: Why are this distributed but not compiled? EXTRA_DIST += canon630u-common.c lm9830.h libcanon_dr_la_SOURCES = canon_dr.c canon_dr.h canon_dr-cmd.h libcanon_dr_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_dr nodist_libsane_canon_dr_la_SOURCES = canon_dr-s.c libsane_canon_dr_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_dr libsane_canon_dr_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_canon_dr_la_LIBADD = $(COMMON_LIBS) libcanon_dr.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_magic.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += canon_dr.conf.in libcanon_pp_la_SOURCES = canon_pp.c canon_pp.h canon_pp-io.c canon_pp-io.h canon_pp-dev.c canon_pp-dev.h libcanon_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_pp nodist_libsane_canon_pp_la_SOURCES = canon_pp-s.c libsane_canon_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=canon_pp libsane_canon_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_canon_pp_la_LIBADD = $(COMMON_LIBS) libcanon_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(IEEE1284_LIBS) EXTRA_DIST += canon_pp.conf.in libcardscan_la_SOURCES = cardscan.c cardscan.h libcardscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=cardscan nodist_libsane_cardscan_la_SOURCES = cardscan-s.c libsane_cardscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=cardscan libsane_cardscan_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_cardscan_la_LIBADD = $(COMMON_LIBS) libcardscan.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += cardscan.conf.in libcoolscan_la_SOURCES = coolscan.c coolscan.h coolscan-scsidef.h libcoolscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan nodist_libsane_coolscan_la_SOURCES = coolscan-s.c libsane_coolscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan libsane_coolscan_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_coolscan_la_LIBADD = $(COMMON_LIBS) libcoolscan.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += coolscan.conf.in libcoolscan2_la_SOURCES = coolscan2.c libcoolscan2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan2 nodist_libsane_coolscan2_la_SOURCES = coolscan2-s.c libsane_coolscan2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan2 libsane_coolscan2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_coolscan2_la_LIBADD = $(COMMON_LIBS) libcoolscan2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += coolscan2.conf.in libcoolscan3_la_SOURCES = coolscan3.c libcoolscan3_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan3 nodist_libsane_coolscan3_la_SOURCES = coolscan3-s.c libsane_coolscan3_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=coolscan3 libsane_coolscan3_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_coolscan3_la_LIBADD = $(COMMON_LIBS) libcoolscan3.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += coolscan3.conf.in libdc25_la_SOURCES = dc25.c dc25.h libdc25_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc25 nodist_libsane_dc25_la_SOURCES = dc25-s.c libsane_dc25_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc25 libsane_dc25_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dc25_la_LIBADD = $(COMMON_LIBS) libdc25.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(MATH_LIB) EXTRA_DIST += dc25.conf.in libdc210_la_SOURCES = dc210.c dc210.h libdc210_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc210 nodist_libsane_dc210_la_SOURCES = dc210-s.c libsane_dc210_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc210 libsane_dc210_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dc210_la_LIBADD = $(COMMON_LIBS) libdc210.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) EXTRA_DIST += dc210.conf.in libdc240_la_SOURCES = dc240.c dc240.h libdc240_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc240 nodist_libsane_dc240_la_SOURCES = dc240-s.c libsane_dc240_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dc240 libsane_dc240_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dc240_la_LIBADD = $(COMMON_LIBS) libdc240.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) EXTRA_DIST += dc240.conf.in libdell1600n_net_la_SOURCES = dell1600n_net.c libdell1600n_net_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dell1600n_net nodist_libsane_dell1600n_net_la_SOURCES = dell1600n_net-s.c libsane_dell1600n_net_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dell1600n_net libsane_dell1600n_net_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dell1600n_net_la_LIBADD = $(COMMON_LIBS) libdell1600n_net.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(TIFF_LIBS) $(JPEG_LIBS) $(SOCKET_LIBS) EXTRA_DIST += dell1600n_net.conf.in libdmc_la_SOURCES = dmc.c dmc.h libdmc_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dmc nodist_libsane_dmc_la_SOURCES = dmc-s.c libsane_dmc_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dmc libsane_dmc_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dmc_la_LIBADD = $(COMMON_LIBS) libdmc.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += dmc.conf.in libepjitsu_la_SOURCES = epjitsu.c epjitsu.h epjitsu-cmd.h libepjitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epjitsu nodist_libsane_epjitsu_la_SOURCES = epjitsu-s.c libsane_epjitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epjitsu libsane_epjitsu_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_epjitsu_la_LIBADD = $(COMMON_LIBS) libepjitsu.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += epjitsu.conf.in libepson_la_SOURCES = epson.c epson.h epson_scsi.c epson_scsi.h epson_usb.c epson_usb.h libepson_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson nodist_libsane_epson_la_SOURCES = epson-s.c libsane_epson_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson libsane_epson_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_epson_la_LIBADD = $(COMMON_LIBS) libepson.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += epson.conf.in libepson2_la_SOURCES = epson2.c epson2.h epson2_scsi.c epson2_scsi.h epson2_usb.c epson2_net.c epson2_net.h epson2-io.c epson2-io.h epson2-commands.c epson2-commands.h epson2-ops.c epson2-ops.h epson2-cct.c libepson2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson2 nodist_libsane_epson2_la_SOURCES = epson2-s.c libsane_epson2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epson2 libsane_epson2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_epson2_la_LIBADD = $(COMMON_LIBS) libepson2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(SCSI_LIBS) $(USB_LIBS) $(SOCKET_LIBS) $(MATH_LIB) $(RESMGR_LIBS) EXTRA_DIST += epson2.conf.in libepsonds_la_SOURCES = epsonds.c epsonds.h epsonds-usb.c epsonds-usb.h epsonds-io.c epsonds-io.h \ epsonds-cmd.c epsonds-cmd.h epsonds-ops.c epsonds-ops.h epsonds-jpeg.c epsonds-jpeg.h \ epsonds-net.c epsonds-net.h libepsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds nodist_libsane_epsonds_la_SOURCES = epsonds-s.c libsane_epsonds_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=epsonds libsane_epsonds_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_epsonds_la_LIBADD = $(COMMON_LIBS) libepsonds.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo \ ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo \ ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo \ $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(USB_LIBS) $(MATH_LIB) $(RESMGR_LIBS) $(SOCKET_LIBS) EXTRA_DIST += epsonds.conf.in libfujitsu_la_SOURCES = fujitsu.c fujitsu.h fujitsu-scsi.h libfujitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=fujitsu nodist_libsane_fujitsu_la_SOURCES = fujitsu-s.c libsane_fujitsu_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=fujitsu libsane_fujitsu_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_fujitsu_la_LIBADD = $(COMMON_LIBS) libfujitsu.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_magic.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += fujitsu.conf.in libgenesys_la_SOURCES = genesys.c genesys.h genesys_gl646.c genesys_gl646.h genesys_gl841.c genesys_gl841.h genesys_gl843.c genesys_gl843.h genesys_gl846.c genesys_gl846.h genesys_gl847.c genesys_gl847.h genesys_gl124.c genesys_gl124.h genesys_low.c genesys_low.h libgenesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys nodist_libsane_genesys_la_SOURCES = genesys-s.c libsane_genesys_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=genesys libsane_genesys_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_genesys_la_LIBADD = $(COMMON_LIBS) libgenesys.la ../sanei/sanei_magic.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += genesys.conf.in # TODO: Why are this distributed but not compiled? EXTRA_DIST += genesys_conv.c genesys_conv_hlp.c genesys_devices.c libgphoto2_i_la_SOURCES = gphoto2.c gphoto2.h libgphoto2_i_la_CPPFLAGS = $(AM_CPPFLAGS) $(GPHOTO2_CPPFLAGS) -DBACKEND_NAME=gphoto2 nodist_libsane_gphoto2_la_SOURCES = gphoto2-s.c libsane_gphoto2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=gphoto2 libsane_gphoto2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_gphoto2_la_LIBADD = $(GPHOTO2_LDFLAGS) $(COMMON_LIBS) libgphoto2_i.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(SANEI_SANEI_JPEG_LO) $(GPHOTO2_LIBS) $(JPEG_LIBS) EXTRA_DIST += gphoto2.conf.in libgt68xx_la_SOURCES = gt68xx.c gt68xx.h libgt68xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=gt68xx nodist_libsane_gt68xx_la_SOURCES = gt68xx-s.c libsane_gt68xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=gt68xx libsane_gt68xx_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_gt68xx_la_LIBADD = $(COMMON_LIBS) libgt68xx.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += gt68xx.conf.in # TODO: Why are this distributed but not compiled? EXTRA_DIST += gt68xx_devices.c gt68xx_generic.c gt68xx_generic.h gt68xx_gt6801.c gt68xx_gt6801.h gt68xx_gt6816.c gt68xx_gt6816.h gt68xx_high.c gt68xx_high.h gt68xx_low.c gt68xx_low.h gt68xx_mid.c gt68xx_mid.h gt68xx_shm_channel.c gt68xx_shm_channel.h libhp_la_SOURCES = hp.c hp.h hp-accessor.c hp-accessor.h hp-device.c hp-device.h hp-handle.c hp-handle.h hp-hpmem.c hp-option.c hp-option.h hp-scl.c hp-scl.h hp-scsi.h libhp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp nodist_libsane_hp_la_SOURCES = hp-s.c libsane_hp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp libsane_hp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp_la_LIBADD = $(COMMON_LIBS) libhp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pio.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += hp.conf.in # TODO: These should be moved to ../docs/hp; don't belong here. EXTRA_DIST += hp.README hp.TODO libhp3500_la_SOURCES = hp3500.c libhp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500 nodist_libsane_hp3500_la_SOURCES = hp3500-s.c libsane_hp3500_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3500 libsane_hp3500_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp3500_la_LIBADD = $(COMMON_LIBS) libhp3500.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libhp3900_la_SOURCES = hp3900.c libhp3900_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3900 nodist_libsane_hp3900_la_SOURCES = hp3900-s.c libsane_hp3900_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp3900 libsane_hp3900_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp3900_la_LIBADD = $(COMMON_LIBS) libhp3900.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(TIFF_LIBS) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += hp3900.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += hp3900_config.c hp3900_debug.c hp3900_rts8822.c hp3900_sane.c hp3900_types.c hp3900_usb.c libhp4200_la_SOURCES = hp4200.c hp4200.h libhp4200_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp4200 nodist_libsane_hp4200_la_SOURCES = hp4200-s.c libsane_hp4200_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp4200 libsane_hp4200_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp4200_la_LIBADD = $(COMMON_LIBS) libhp4200.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_pv8630.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += hp4200.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += hp4200_lm9830.c hp4200_lm9830.h libhp5400_la_SOURCES = hp5400.c hp5400.h libhp5400_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp5400 nodist_libsane_hp5400_la_SOURCES = hp5400-s.c libsane_hp5400_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp5400 libsane_hp5400_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp5400_la_LIBADD = $(COMMON_LIBS) libhp5400.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += hp5400.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += hp5400_debug.c hp5400_debug.h hp5400_internal.c hp5400_internal.h hp5400_sane.c hp5400_sanei.c hp5400_sanei.h hp5400_xfer.h libhp5590_la_SOURCES = hp5590.c libhp5590_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp5590 nodist_libsane_hp5590_la_SOURCES = hp5590-s.c libsane_hp5590_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hp5590 libsane_hp5590_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hp5590_la_LIBADD = $(COMMON_LIBS) libhp5590.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) # TODO: Why are these distributed but not compiled? EXTRA_DIST += hp5590_cmds.c hp5590_cmds.h hp5590_low.c hp5590_low.h libhpljm1005_la_SOURCES = hpljm1005.c libhpljm1005_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hpljm1005 nodist_libsane_hpljm1005_la_SOURCES = hpljm1005-s.c libsane_hpljm1005_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hpljm1005 libsane_hpljm1005_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hpljm1005_la_LIBADD = $(COMMON_LIBS) libhpljm1005.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) libhpsj5s_la_SOURCES = hpsj5s.c hpsj5s.h libhpsj5s_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hpsj5s nodist_libsane_hpsj5s_la_SOURCES = hpsj5s-s.c libsane_hpsj5s_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hpsj5s libsane_hpsj5s_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hpsj5s_la_LIBADD = $(COMMON_LIBS) libhpsj5s.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(IEEE1284_LIBS) EXTRA_DIST += hpsj5s.conf.in libhs2p_la_SOURCES = hs2p.c hs2p.h hs2p-saneopts.h libhs2p_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hs2p nodist_libsane_hs2p_la_SOURCES = hs2p-s.c libsane_hs2p_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=hs2p libsane_hs2p_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_hs2p_la_LIBADD = $(COMMON_LIBS) libhs2p.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += hs2p.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += hs2p-scsi.c hs2p-scsi.h libibm_la_SOURCES = ibm.c ibm.h libibm_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ibm nodist_libsane_ibm_la_SOURCES = ibm-s.c libsane_ibm_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ibm libsane_ibm_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_ibm_la_LIBADD = $(COMMON_LIBS) libibm.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += ibm.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += ibm-scsi.c libkodak_la_SOURCES = kodak.c kodak.h kodak-cmd.h libkodak_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodak nodist_libsane_kodak_la_SOURCES = kodak-s.c libsane_kodak_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodak libsane_kodak_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kodak_la_LIBADD = $(COMMON_LIBS) libkodak.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += kodak.conf.in libkodakaio_la_SOURCES = kodakaio.c kodakaio.h libkodakaio_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodakaio nodist_libsane_kodakaio_la_SOURCES = kodakaio-s.c libsane_kodakaio_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kodakaio libsane_kodakaio_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kodakaio_la_LIBADD = $(COMMON_LIBS) libkodakaio.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(USB_LIBS) $(SOCKET_LIBS) $(AVAHI_LIBS) $(MATH_LIB) $(RESMGR_LIBS) EXTRA_DIST += kodakaio.conf.in libkvs1025_la_SOURCES = kvs1025.c kvs1025_low.c kvs1025_opt.c kvs1025_usb.c \ kvs1025.h kvs1025_low.h kvs1025_usb.h kvs1025_cmds.h libkvs1025_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs1025 nodist_libsane_kvs1025_la_SOURCES = kvs1025-s.c libsane_kvs1025_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs1025 libsane_kvs1025_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kvs1025_la_LIBADD = $(COMMON_LIBS) libkvs1025.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_magic.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += kvs1025.conf.in libkvs20xx_la_SOURCES = kvs20xx.c kvs20xx_cmd.c kvs20xx_opt.c \ kvs20xx_cmd.h kvs20xx.h libkvs20xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs20xx nodist_libsane_kvs20xx_la_SOURCES = kvs20xx-s.c libsane_kvs20xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs20xx libsane_kvs20xx_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kvs20xx_la_LIBADD = $(COMMON_LIBS) libkvs20xx.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libkvs40xx_la_SOURCES = kvs40xx.c kvs40xx_cmd.c kvs40xx_opt.c \ kvs40xx.h libkvs40xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs40xx nodist_libsane_kvs40xx_la_SOURCES = kvs40xx-s.c libsane_kvs40xx_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=kvs40xx libsane_kvs40xx_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_kvs40xx_la_LIBADD = $(COMMON_LIBS) libkvs40xx.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) libleo_la_SOURCES = leo.c leo.h libleo_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=leo nodist_libsane_leo_la_SOURCES = leo-s.c libsane_leo_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=leo libsane_leo_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_leo_la_LIBADD = $(COMMON_LIBS) libleo.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += leo.conf.in liblexmark_la_SOURCES = lexmark.c lexmark.h lexmark_low.c liblexmark_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=lexmark nodist_libsane_lexmark_la_SOURCES = lexmark-s.c libsane_lexmark_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=lexmark libsane_lexmark_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_lexmark_la_LIBADD = $(COMMON_LIBS) liblexmark.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += lexmark.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += lexmark_models.c lexmark_sensors.c libma1509_la_SOURCES = ma1509.c ma1509.h libma1509_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ma1509 nodist_libsane_ma1509_la_SOURCES = ma1509-s.c libsane_ma1509_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ma1509 libsane_ma1509_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_ma1509_la_LIBADD = $(COMMON_LIBS) libma1509.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += ma1509.conf.in libmagicolor_la_SOURCES = magicolor.c magicolor.h libmagicolor_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=magicolor $(SNMP_CFLAGS) nodist_libsane_magicolor_la_SOURCES = magicolor-s.c libsane_magicolor_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=magicolor libsane_magicolor_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_magicolor_la_LIBADD = $(COMMON_LIBS) libmagicolor.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo $(USB_LIBS) $(SOCKET_LIBS) $(MATH_LIB) $(RESMGR_LIBS) $(SNMP_LIBS) EXTRA_DIST += magicolor.conf.in libmatsushita_la_SOURCES = matsushita.c matsushita.h libmatsushita_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=matsushita nodist_libsane_matsushita_la_SOURCES = matsushita-s.c libsane_matsushita_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=matsushita libsane_matsushita_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_matsushita_la_LIBADD = $(COMMON_LIBS) libmatsushita.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += matsushita.conf.in libmicrotek_la_SOURCES = microtek.c microtek.h libmicrotek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek nodist_libsane_microtek_la_SOURCES = microtek-s.c libsane_microtek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek libsane_microtek_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_microtek_la_LIBADD = $(COMMON_LIBS) libmicrotek.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += microtek.conf.in libmicrotek2_la_SOURCES = microtek2.c microtek2.h libmicrotek2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek2 nodist_libsane_microtek2_la_SOURCES = microtek2-s.c libsane_microtek2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=microtek2 libsane_microtek2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_microtek2_la_LIBADD = $(COMMON_LIBS) libmicrotek2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += microtek2.conf.in libmustek_la_SOURCES = mustek.c mustek.h libmustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek nodist_libsane_mustek_la_SOURCES = mustek-s.c libsane_mustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek libsane_mustek_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_mustek_la_LIBADD = $(COMMON_LIBS) libmustek.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pa4s2.lo $(IEEE1284_LIBS) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += mustek.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += mustek_scsi_pp.c mustek_scsi_pp.h libmustek_pp_la_SOURCES = mustek_pp.c mustek_pp.h mustek_pp_decl.h mustek_pp_drivers.h libmustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_pp nodist_libsane_mustek_pp_la_SOURCES = mustek_pp-s.c libsane_mustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_pp libsane_mustek_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_mustek_pp_la_LIBADD = $(COMMON_LIBS) libmustek_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_pa4s2.lo $(MATH_LIB) $(IEEE1284_LIBS) EXTRA_DIST += mustek_pp.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += mustek_pp_ccd300.c mustek_pp_ccd300.h mustek_pp_cis.c mustek_pp_cis.h mustek_pp_null.c libmustek_usb_la_SOURCES = mustek_usb.c mustek_usb.h libmustek_usb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb nodist_libsane_mustek_usb_la_SOURCES = mustek_usb-s.c libsane_mustek_usb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb libsane_mustek_usb_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_mustek_usb_la_LIBADD = $(COMMON_LIBS) libmustek_usb.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += mustek_usb.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += mustek_usb_high.c mustek_usb_high.h mustek_usb_low.c mustek_usb_low.h mustek_usb_mid.c mustek_usb_mid.h libmustek_usb2_la_SOURCES = mustek_usb2.c mustek_usb2.h libmustek_usb2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb2 nodist_libsane_mustek_usb2_la_SOURCES = mustek_usb2-s.c libsane_mustek_usb2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=mustek_usb2 libsane_mustek_usb2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_mustek_usb2_la_LIBADD = $(COMMON_LIBS) libmustek_usb2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(PTHREAD_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) # TODO: Why are these distributed but not compiled? EXTRA_DIST += mustek_usb2_asic.c mustek_usb2_asic.h mustek_usb2_high.c mustek_usb2_high.h mustek_usb2_reflective.c mustek_usb2_transparent.c libnec_la_SOURCES = nec.c nec.h libnec_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=nec nodist_libsane_nec_la_SOURCES = nec-s.c libsane_nec_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=nec libsane_nec_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_nec_la_LIBADD = $(COMMON_LIBS) libnec.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += nec.conf.in libnet_la_SOURCES = net.c net.h libnet_la_CPPFLAGS = $(AM_CPPFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=net nodist_libsane_net_la_SOURCES = net-s.c libsane_net_la_CPPFLAGS = $(AM_CPPFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=net libsane_net_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_net_la_LIBADD = $(COMMON_LIBS) libnet.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo $(AVAHI_LIBS) $(SOCKET_LIBS) EXTRA_DIST += net.conf.in libniash_la_SOURCES = niash.c libniash_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=niash nodist_libsane_niash_la_SOURCES = niash-s.c libsane_niash_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=niash libsane_niash_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_niash_la_LIBADD = $(COMMON_LIBS) libniash.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) # TODO: Why are these distributed but not compiled? EXTRA_DIST += niash_core.c niash_core.h niash_xfer.c niash_xfer.h libpie_la_SOURCES = pie.c pie-scsidef.h libpie_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pie nodist_libsane_pie_la_SOURCES = pie-s.c libsane_pie_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pie libsane_pie_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pie_la_LIBADD = $(COMMON_LIBS) libpie.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += pie.conf.in libpieusb_la_SOURCES = pieusb.h pieusb_buffer.c pieusb_buffer.h pieusb_scancmd.c pieusb_scancmd.h pieusb_specific.c pieusb_specific.h pieusb_usb.c pieusb_usb.h pieusb.c libpieusb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pieusb nodist_libsane_pieusb_la_SOURCES = pieusb-s.c libsane_pieusb_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pieusb libsane_pieusb_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pieusb_la_LIBADD = $(COMMON_LIBS) libpieusb.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_thread.lo ../sanei/sanei_usb.lo ../sanei/sanei_ir.lo ../sanei/sanei_magic.lo $(PTHREAD_LIBS) $(RESMGR_LIBS) $(USB_LIBS) $(MATH_LIB) EXTRA_DIST += pieusb.conf.in libp5_la_SOURCES = p5.c p5.h p5_device.h libp5_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=p5 nodist_libsane_p5_la_SOURCES = p5-s.c libsane_p5_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=p5 libsane_p5_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_p5_la_LIBADD = $(COMMON_LIBS) libp5.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo EXTRA_DIST += p5.conf.in p5_device.c libpint_la_SOURCES = pint.c pint.h libpint_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pint nodist_libsane_pint_la_SOURCES = pint-s.c libsane_pint_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pint libsane_pint_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pint_la_LIBADD = $(COMMON_LIBS) libpint.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo libpixma_la_SOURCES = pixma.c pixma.h pixma_io_sanei.c pixma_io.h pixma_common.c pixma_common.h pixma_mp150.c pixma_mp730.c pixma_mp750.c pixma_mp810.c pixma_imageclass.c pixma_bjnp.c pixma_bjnp.h pixma_bjnp_private.h pixma_rename.h libpixma_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pixma nodist_libsane_pixma_la_SOURCES = pixma-s.c libsane_pixma_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pixma libsane_pixma_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pixma_la_LIBADD = $(COMMON_LIBS) libpixma.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += pixma.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += pixma_sane_options.c pixma_sane_options.h libplustek_la_SOURCES = plustek.c plustek.h libplustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek nodist_libsane_plustek_la_SOURCES = plustek-s.c libsane_plustek_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek libsane_plustek_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_plustek_la_LIBADD = $(COMMON_LIBS) libplustek.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += plustek.conf.in EXTRA_DIST += plustek-usb.c plustek-usb.h plustek-usbcal.c plustek-usbcalfile.c plustek-usbdevs.c plustek-usbhw.c plustek-usbimg.c plustek-usbio.c plustek-usbmap.c plustek-usbscan.c plustek-usbshading.c libplustek_pp_la_SOURCES = plustek_pp.c plustek-pp.h libplustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek_pp nodist_libsane_plustek_pp_la_SOURCES = plustek_pp-s.c libsane_plustek_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=plustek_pp libsane_plustek_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_plustek_pp_la_LIBADD = $(COMMON_LIBS) libplustek_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(IEEE1284_LIBS) $(PTHREAD_LIBS) EXTRA_DIST += plustek_pp.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += plustek-pp_dac.c plustek-pp_dbg.h plustek-pp_detect.c plustek-pp_genericio.c plustek-pp_hwdefs.h plustek-pp_image.c plustek-pp_io.c plustek-pp_map.c plustek-pp_misc.c plustek-pp_models.c plustek-pp_motor.c plustek-pp_p12.c plustek-pp_p12ccd.c plustek-pp_p48xx.c plustek-pp_p9636.c plustek-pp_procfs.c plustek-pp_procs.h plustek-pp_ptdrv.c plustek-pp_scale.c plustek-pp_scan.h plustek-pp_scandata.h plustek-pp_sysdep.h plustek-pp_tpa.c plustek-pp_types.h plustek-pp_wrapper.c libpnm_la_SOURCES = pnm.c libpnm_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pnm nodist_libsane_pnm_la_SOURCES = pnm-s.c libsane_pnm_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pnm libsane_pnm_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_pnm_la_LIBADD = $(COMMON_LIBS) libpnm.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo libqcam_la_SOURCES = qcam.c qcam.h libqcam_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=qcam nodist_libsane_qcam_la_SOURCES = qcam-s.c libsane_qcam_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=qcam libsane_qcam_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_qcam_la_LIBADD = $(COMMON_LIBS) libqcam.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_pio.lo EXTRA_DIST += qcam.conf.in libricoh_la_SOURCES = ricoh.c ricoh.h libricoh_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ricoh nodist_libsane_ricoh_la_SOURCES = ricoh-s.c libsane_ricoh_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ricoh libsane_ricoh_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_ricoh_la_LIBADD = $(COMMON_LIBS) libricoh.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += ricoh.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += ricoh-scsi.c librts8891_la_SOURCES = rts8891.c rts8891.h rts88xx_lib.c rts88xx_lib.h librts8891_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=rts8891 nodist_libsane_rts8891_la_SOURCES = rts8891-s.c libsane_rts8891_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=rts8891 libsane_rts8891_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_rts8891_la_LIBADD = $(COMMON_LIBS) librts8891.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_scsi.lo ../sanei/sanei_usb.lo $(SCSI_LIBS) $(USB_LIBS) $(RESMGR_LIBS) $(RESMGR_LIBS) EXTRA_DIST += rts8891.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += rts8891_devices.c rts8891_low.c rts8891_low.h libs9036_la_SOURCES = s9036.c s9036.h libs9036_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=s9036 nodist_libsane_s9036_la_SOURCES = s9036-s.c libsane_s9036_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=s9036 libsane_s9036_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_s9036_la_LIBADD = $(COMMON_LIBS) libs9036.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += s9036.conf.in libsceptre_la_SOURCES = sceptre.c sceptre.h libsceptre_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sceptre nodist_libsane_sceptre_la_SOURCES = sceptre-s.c libsane_sceptre_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sceptre libsane_sceptre_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sceptre_la_LIBADD = $(COMMON_LIBS) libsceptre.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += sceptre.conf.in libsharp_la_SOURCES = sharp.c sharp.h libsharp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sharp nodist_libsane_sharp_la_SOURCES = sharp-s.c libsane_sharp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sharp libsane_sharp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sharp_la_LIBADD = $(COMMON_LIBS) libsharp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += sharp.conf.in libsm3600_la_SOURCES = sm3600.c sm3600.h libsm3600_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sm3600 nodist_libsane_sm3600_la_SOURCES = sm3600-s.c libsane_sm3600_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sm3600 libsane_sm3600_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sm3600_la_LIBADD = $(COMMON_LIBS) libsm3600.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) # TODO: Why are these distributed but not compiled? EXTRA_DIST += sm3600-color.c sm3600-gray.c sm3600-homerun.c sm3600-scanmtek.c sm3600-scantool.h sm3600-scanusb.c sm3600-scanutil.c libsm3840_la_SOURCES = sm3840.c sm3840.h sm3840_params.h libsm3840_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sm3840 nodist_libsane_sm3840_la_SOURCES = sm3840-s.c libsane_sm3840_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sm3840 libsane_sm3840_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sm3840_la_LIBADD = $(COMMON_LIBS) libsm3840.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += sm3840.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += sm3840_lib.c sm3840_lib.h sm3840_scan.c libsnapscan_la_SOURCES = snapscan.c snapscan.h libsnapscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=snapscan nodist_libsane_snapscan_la_SOURCES = snapscan-s.c libsane_snapscan_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=snapscan libsane_snapscan_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_snapscan_la_LIBADD = $(COMMON_LIBS) libsnapscan.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += snapscan.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += snapscan-data.c snapscan-mutex.c snapscan-options.c snapscan-scsi.c snapscan-sources.c snapscan-sources.h snapscan-usb.c snapscan-usb.h libsp15c_la_SOURCES = sp15c.c sp15c.h sp15c-scsi.h libsp15c_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sp15c nodist_libsane_sp15c_la_SOURCES = sp15c-s.c libsane_sp15c_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=sp15c libsane_sp15c_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_sp15c_la_LIBADD = $(COMMON_LIBS) libsp15c.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += sp15c.conf.in libst400_la_SOURCES = st400.c st400.h libst400_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=st400 nodist_libsane_st400_la_SOURCES = st400-s.c ../sanei/sanei_scsi.lo libsane_st400_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=st400 libsane_st400_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_st400_la_LIBADD = $(COMMON_LIBS) libst400.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += st400.conf.in libstv680_la_SOURCES = stv680.c stv680.h libstv680_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=stv680 nodist_libsane_stv680_la_SOURCES = stv680-s.c libsane_stv680_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=stv680 libsane_stv680_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_stv680_la_LIBADD = $(COMMON_LIBS) libstv680.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += stv680.conf.in libtamarack_la_SOURCES = tamarack.c tamarack.h libtamarack_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=tamarack nodist_libsane_tamarack_la_SOURCES = tamarack-s.c libsane_tamarack_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=tamarack libsane_tamarack_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_tamarack_la_LIBADD = $(COMMON_LIBS) libtamarack.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += tamarack.conf.in libtest_la_SOURCES = test.c test.h libtest_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=test nodist_libsane_test_la_SOURCES = test-s.c libsane_test_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=test libsane_test_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_test_la_LIBADD = $(COMMON_LIBS) libtest.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_thread.lo $(PTHREAD_LIBS) EXTRA_DIST += test.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += test-picture.c libteco1_la_SOURCES = teco1.c teco1.h libteco1_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco1 nodist_libsane_teco1_la_SOURCES = teco1-s.c libsane_teco1_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco1 libsane_teco1_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_teco1_la_LIBADD = $(COMMON_LIBS) libteco1.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += teco1.conf.in libteco2_la_SOURCES = teco2.c teco2.h libteco2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco2 nodist_libsane_teco2_la_SOURCES = teco2-s.c libsane_teco2_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco2 libsane_teco2_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_teco2_la_LIBADD = $(COMMON_LIBS) libteco2.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += teco2.conf.in libteco3_la_SOURCES = teco3.c teco3.h libteco3_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco3 nodist_libsane_teco3_la_SOURCES = teco3-s.c libsane_teco3_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=teco3 libsane_teco3_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_teco3_la_LIBADD = $(COMMON_LIBS) libteco3.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_scsi.lo $(SCSI_LIBS) $(RESMGR_LIBS) EXTRA_DIST += teco3.conf.in libu12_la_SOURCES = u12.c u12.h libu12_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=u12 nodist_libsane_u12_la_SOURCES = u12-s.c libsane_u12_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=u12 libsane_u12_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_u12_la_LIBADD = $(COMMON_LIBS) libu12.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(MATH_LIB) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += u12.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += u12-ccd.c u12-hw.c u12-hwdef.h u12-if.c u12-image.c u12-io.c u12-map.c u12-motor.c u12-scanner.h u12-shading.c u12-tpa.c libumax_la_SOURCES = umax.c umax.h libumax_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax nodist_libsane_umax_la_SOURCES = umax-s.c libsane_umax_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax libsane_umax_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_umax_la_LIBADD = $(COMMON_LIBS) libumax.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo $(MATH_LIB) $(SCSI_LIBS) $(USB_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += umax.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += umax-scanner.c umax-scanner.h umax-scsidef.h umax-uc1200s.c umax-uc1200se.c umax-uc1260.c umax-uc630.c umax-uc840.c umax-ug630.c umax-ug80.c umax-usb.c libumax1220u_la_SOURCES = umax1220u.c libumax1220u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax1220u nodist_libsane_umax1220u_la_SOURCES = umax1220u-s.c libsane_umax1220u_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax1220u libsane_umax1220u_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_umax1220u_la_LIBADD = $(COMMON_LIBS) libumax1220u.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_pv8630.lo $(MATH_LIB) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += umax1220u.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += umax1220u-common.c libumax_pp_la_SOURCES = umax_pp.c umax_pp.h umax_pp_low.c umax_pp_low.h umax_pp_mid.c umax_pp_mid.h libumax_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax_pp nodist_libsane_umax_pp_la_SOURCES = umax_pp-s.c libsane_umax_pp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=umax_pp libsane_umax_pp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_umax_pp_la_LIBADD = $(COMMON_LIBS) libumax_pp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(MATH_LIB) EXTRA_DIST += umax_pp.conf.in libv4l_la_SOURCES = v4l.c v4l.h v4l-frequencies.h libv4l_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBV4L_CFLAGS) -DBACKEND_NAME=v4l nodist_libsane_v4l_la_SOURCES = v4l-s.c libsane_v4l_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=v4l libsane_v4l_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_v4l_la_LIBADD = $(COMMON_LIBS) libv4l.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(LIBV4L_LIBS) EXTRA_DIST += v4l.conf.in libxerox_mfp_la_SOURCES = xerox_mfp.c xerox_mfp-usb.c xerox_mfp-tcp.c xerox_mfp.h libxerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp nodist_libsane_xerox_mfp_la_SOURCES = xerox_mfp-s.c libsane_xerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp libsane_xerox_mfp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo @SANEI_SANEI_JPEG_LO@ $(JPEG_LIBS) ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += xerox_mfp.conf.in libdll_preload_la_SOURCES = dll.c libdll_preload_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll -DENABLE_PRELOAD libdll_la_SOURCES = dll.c libdll_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll BUILT_SOURCES = dll-preload.h CLEANFILES += dll-preload.h nodist_libsane_dll_la_SOURCES = dll-s.c libsane_dll_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll libsane_dll_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_dll_la_LIBADD = $(COMMON_LIBS) libdll.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(DL_LIBS) EXTRA_DIST += dll.conf.in # TODO: Why is this distributed but not installed? EXTRA_DIST += dll.aliases # libsane.la and libsane-dll.la are the same thing except for # the addition of backends listed by PRELOADABLE_BACKENDS that are # statically linked in. # Also, libsane.la goes into $(libdir) where as all libsane-* # (including libsane-dll.la) go into $(libdir)/sane # FIXME: Since we are throwing in the kitchen sink, might as # well link in ../sanei/libsanei.la instead. But currently, # libsanei.la is linking in sanei_auth which requires md5. # Shipping md5 could cause symbol conflicts with commonly used # md5 external libraries. Either need to prefix md5 with sanei_ # (see liblib.la and snprintf), or move sanei_auth outside # of libsanei. # # FIXME: This is linking in every possible external library because there # is the off chance user is using PRELOADABLE_BACKENDS that may need # them. Since standard mode is to only have the dll backend, its a waste. # Need to update configure to build a list of only what needs to go into # LIBADD based on whats being preloaded. nodist_libsane_la_SOURCES = dll-s.c libsane_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll libsane_la_LDFLAGS = $(DIST_LIBS_LDFLAGS) libsane_la_LIBADD = $(COMMON_LIBS) $(PRELOADABLE_BACKENDS_ENABLED) libdll_preload.la sane_strstatus.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo ../sanei/sanei_pa4s2.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo ../sanei/sanei_magic.lo $(DL_LIBS) $(LIBV4L_LIBS) $(MATH_LIB) $(IEEE1284_LIBS) $(TIFF_LIBS) $(JPEG_LIBS) $(GPHOTO2_LIBS) $(SOCKET_LIBS) $(USB_LIBS) $(AVAHI_LIBS) $(SCSI_LIBS) $(PTHREAD_LIBS) $(RESMGR_LIBS) # WARNING: Automake is getting this wrong so have to do it ourselves. libsane_la_DEPENDENCIES = $(COMMON_LIBS) $(PRELOADABLE_BACKENDS_ENABLED) libdll_preload.la sane_strstatus.lo ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo ../sanei/sanei_config2.lo ../sanei/sanei_usb.lo ../sanei/sanei_scsi.lo ../sanei/sanei_pv8630.lo ../sanei/sanei_pp.lo ../sanei/sanei_thread.lo ../sanei/sanei_lm983x.lo ../sanei/sanei_access.lo ../sanei/sanei_net.lo ../sanei/sanei_wire.lo ../sanei/sanei_codec_bin.lo ../sanei/sanei_pa4s2.lo ../sanei/sanei_ab306.lo ../sanei/sanei_pio.lo ../sanei/sanei_tcp.lo ../sanei/sanei_udp.lo ../sanei/sanei_magic.lo $(SANEI_SANEI_JPEG_LO) sane-backends-1.0.27/backend/mustek_usb.conf.in0000664000175000017500000000145112112021330016230 00000000000000# mustek_usb.conf: Configuration file for Mustek USB scanner # Read man sane-mustek_usb for documentation # If USB errors occur, using this option may help #option max_block_size 1024 # Autodetect 1200 UB and Trust Compact Scan USB 19200 usb 0x055f 0x0006 # Autodetect 1200 USB (not supported) # usb 0x055f 0x0003 # Autodetect 1200 CU usb 0x055f 0x0001 # Autodetect 1200 CU Plus usb 0x055f 0x0008 # Autodetect 600 CU usb 0x055f 0x0002 # Autodetect 600 USB (not supported) usb 0x055f 0x0873 # If autodetection doesn't work uncomment or add your device file and one # suitable option (1200ub is also for Trust Compact Scan USB 19200). #/dev/usb/scanner0 #option 1200ub #option 1200cu #option 1200cu_plus #option 600cu #/dev/usbscanner0 #option 1200ub #option 1200cu #option 1200cu_plus #option 600cu sane-backends-1.0.27/backend/umax1220u.c0000664000175000017500000006050412775312261014434 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001, Marcio Luis Teixeira Parts copyright (C) 1996, 1997 Andreas Beck Parts copyright (C) 2000, 2001 Michael Herder Parts copyright (C) 2001 Henning Meier-Geinitz Parts copyright (C) 2006 Patrick Lessard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #define BUILD 2 #define MM_IN_INCH 25.4 #include "../include/sane/config.h" #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_pv8630.h" #define BACKEND_NAME umax1220u #define UMAX_CONFIG_FILE "umax1220u.conf" #include "../include/sane/sanei_backend.h" #include "umax1220u-common.c" typedef struct Umax_Device { struct Umax_Device *next; SANE_String name; SANE_Device sane; } Umax_Device; typedef struct Umax_Scanner { struct Umax_Scanner *next; Umax_Device *device; UMAX_Handle scan; } Umax_Scanner; static int num_devices = 0; static const SANE_Device **devlist = NULL; static Umax_Device *first_dev = NULL; static Umax_Scanner *first_handle = NULL; static SANE_Parameters parms = { SANE_FRAME_RGB, 0, 0, /* Number of bytes returned per scan line: */ 0, /* Number of pixels per scan line. */ 0, /* Number of lines for the current scan. */ 8 /* Number of bits per sample. */ }; struct _SANE_Option { SANE_Option_Descriptor *descriptor; SANE_Status (*callback) (struct _SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info); }; typedef struct _SANE_Option SANE_Option; static SANE_Word getNumberOfOptions (void); /* Forward declaration */ /* This read-only option returns the number of options available for the device. It should be the first option in the options array declared below. */ static SANE_Option_Descriptor optionNumOptionsDescriptor = { SANE_NAME_NUM_OPTIONS, SANE_TITLE_NUM_OPTIONS, SANE_DESC_NUM_OPTIONS, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Status optionNumOptionsCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { option = option; handle = handle; info = info; /* Eliminate warning about unused parameters */ if (action != SANE_ACTION_GET_VALUE) return SANE_STATUS_INVAL; *(SANE_Word *) value = getNumberOfOptions (); return SANE_STATUS_GOOD; } /* This option lets the user select the scan resolution. The UMAX scanner only supports the following resolutions: 75, 150, 300 and 600 */ static const SANE_Word optionResolutionList[] = { 4, /* Number of elements */ 75, 150, 300, 600 /* Resolution list */ }; static SANE_Option_Descriptor optionResolutionDescriptor = { SANE_NAME_SCAN_RESOLUTION, SANE_TITLE_SCAN_RESOLUTION, SANE_DESC_SCAN_RESOLUTION, SANE_TYPE_INT, SANE_UNIT_DPI, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC, SANE_CONSTRAINT_WORD_LIST, {(const SANE_String_Const *) optionResolutionList} }; static SANE_Word optionResolutionValue = 75; static SANE_Status optionResolutionCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { SANE_Status status; SANE_Word autoValue = 75; handle = handle; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: status = sanei_constrain_value (option->descriptor, (void *) &autoValue, info); if (status != SANE_STATUS_GOOD) return status; optionResolutionValue = autoValue; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_SET_VALUE: *info |= SANE_INFO_RELOAD_PARAMS; optionResolutionValue = *(SANE_Word *) value; break; case SANE_ACTION_GET_VALUE: *(SANE_Word *) value = optionResolutionValue; break; } return SANE_STATUS_GOOD; } /* This option lets the user select a gray scale scan */ static SANE_Word optionGrayscaleValue = SANE_FALSE; static SANE_Option_Descriptor optionGrayscaleDescriptor = { "gray", SANE_I18N ("Grayscale scan"), SANE_I18N ("Do a grayscale rather than color scan"), SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Status optionGrayscaleCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { handle = handle; option = option; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: *info |= SANE_INFO_RELOAD_PARAMS; optionGrayscaleValue = *(SANE_Bool *) value; break; case SANE_ACTION_GET_VALUE: *(SANE_Word *) value = optionGrayscaleValue; break; } return SANE_STATUS_GOOD; } /* This option is a button that allows the user to turn off the lamp in the UMAX scanner */ static SANE_Option_Descriptor optionLampOffDescriptor = { "lamp-off", SANE_I18N ("Lamp off"), SANE_I18N ("Turn off scanner lamp"), SANE_TYPE_BUTTON, SANE_UNIT_NONE, 0, SANE_CAP_SOFT_SELECT, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Status optionLampOffCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { Umax_Scanner *scanner = handle; SANE_Status res = SANE_STATUS_GOOD; /* Eliminate warnings about unused parameters */ option = option; handle = handle; info = info; value = value; if (action != SANE_ACTION_SET_VALUE) return SANE_STATUS_INVAL; res = UMAX_set_lamp_state (&scanner->scan, UMAX_LAMP_OFF); return res; } static const SANE_Range widthRange = { 0, /* minimum */ SANE_FIX (UMAX_MAX_WIDTH * MM_IN_INCH / 600), /* maximum */ 0 /* quantization */ }; static const SANE_Range heightRange = { 0, /* minimum */ SANE_FIX (UMAX_MAX_HEIGHT * MM_IN_INCH / 600), /* maximum */ 0 /* quantization */ }; /* This option controls the top-left-x corner of the scan */ static SANE_Fixed optionTopLeftXValue = 0; static SANE_Option_Descriptor optionTopLeftXDescriptor = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Fixed), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) & widthRange} }; static SANE_Status optionTopLeftXCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { option = option; handle = handle; value = value; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionTopLeftXValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionTopLeftXValue; break; } return SANE_STATUS_GOOD; } /* This option controls the top-left-y corner of the scan */ static SANE_Fixed optionTopLeftYValue = 0; static SANE_Option_Descriptor optionTopLeftYDescriptor = { SANE_NAME_SCAN_TL_Y, SANE_TITLE_SCAN_TL_Y, SANE_DESC_SCAN_TL_Y, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Fixed), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) & heightRange} }; static SANE_Status optionTopLeftYCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { /* Eliminate warnings about unused parameters */ option = option; handle = handle; switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionTopLeftYValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionTopLeftYValue; break; } return SANE_STATUS_GOOD; } /* This option controls the bot-right-x corner of the scan */ static SANE_Fixed optionBotRightXValue = SANE_FIX (UMAX_MAX_WIDTH * MM_IN_INCH / 600); static SANE_Option_Descriptor optionBotRightXDescriptor = { SANE_NAME_SCAN_BR_X, SANE_TITLE_SCAN_BR_X, SANE_DESC_SCAN_BR_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Fixed), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) & widthRange} }; static SANE_Status optionBotRightXCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { /* Eliminate warnings about unused parameters */ option = option; handle = handle; switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionBotRightXValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionBotRightXValue; break; } return SANE_STATUS_GOOD; } /* This option controls the bot-right-y corner of the scan */ static SANE_Fixed optionBotRightYValue = SANE_FIX (UMAX_MAX_HEIGHT * MM_IN_INCH / 600); static SANE_Option_Descriptor optionBotRightYDescriptor = { SANE_NAME_SCAN_BR_Y, SANE_TITLE_SCAN_BR_Y, SANE_DESC_SCAN_BR_Y, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Fixed), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(const SANE_String_Const *) & heightRange} }; static SANE_Status optionBotRightYCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { /* Eliminate warnings about unused parameters */ option = option; handle = handle; switch (action) { case SANE_ACTION_SET_AUTO: return SANE_STATUS_INVAL; break; case SANE_ACTION_SET_VALUE: optionBotRightYValue = *(SANE_Fixed *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Fixed *) value = optionBotRightYValue; break; } return SANE_STATUS_GOOD; } /* The following array binds the option descriptors to their respective callback routines */ static SANE_Option so[] = { {&optionNumOptionsDescriptor, optionNumOptionsCallback}, {&optionResolutionDescriptor, optionResolutionCallback}, {&optionGrayscaleDescriptor, optionGrayscaleCallback}, {&optionTopLeftXDescriptor, optionTopLeftXCallback}, {&optionTopLeftYDescriptor, optionTopLeftYCallback}, {&optionBotRightXDescriptor, optionBotRightXCallback}, {&optionBotRightYDescriptor, optionBotRightYCallback}, {&optionLampOffDescriptor, optionLampOffCallback} }; static SANE_Word getNumberOfOptions (void) { return NELEMS (so); } /* This routine dispatches the control message to the appropriate callback routine, it outght to be called by sane_control_option after any driver specific validation. */ static SANE_Status dispatch_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { SANE_Option *op = so + option; SANE_Int myinfo = 0; SANE_Status status = SANE_STATUS_GOOD; if (option < 0 || option >= NELEMS (so)) return SANE_STATUS_INVAL; /* Unknown option ... */ if ((action == SANE_ACTION_SET_VALUE) && ((op->descriptor->cap & SANE_CAP_SOFT_SELECT) == 0)) return SANE_STATUS_INVAL; if ((action == SANE_ACTION_GET_VALUE) && ((op->descriptor->cap & SANE_CAP_SOFT_DETECT) == 0)) return SANE_STATUS_INVAL; if ((action == SANE_ACTION_SET_AUTO) && ((op->descriptor->cap & SANE_CAP_AUTOMATIC) == 0)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_SET_VALUE) { status = sanei_constrain_value (op->descriptor, value, &myinfo); if (status != SANE_STATUS_GOOD) return status; } status = (op->callback) (op, handle, action, value, &myinfo); if (info) *info = myinfo; return status; } static SANE_Status attach_scanner (const char *devicename, Umax_Device ** devp) { UMAX_Handle scan; Umax_Device *dev; SANE_Status status; DBG (3, "attach_scanner: %s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } } dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, '\0', sizeof (Umax_Device)); /* clear structure */ DBG (4, "attach_scanner: opening %s\n", devicename); status = UMAX_open_device (&scan, devicename); if (status != SANE_STATUS_GOOD) { DBG (1, "ERROR: attach_scanner: opening %s failed\n", devicename); free (dev); return status; } dev->name = strdup (devicename); dev->sane.name = dev->name; dev->sane.vendor = "UMAX"; dev->sane.model = UMAX_get_device_name (&scan); dev->sane.type = "flatbed scanner"; UMAX_close_device (&scan); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } /* callback function for sanei_usb_attach_matching_devices */ static SANE_Status attach_one (const char *name) { attach_scanner (name, 0); return SANE_STATUS_GOOD; } /* This file implements a SANE backend for the UMAX Astra 1220U scanner. */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char config_line[PATH_MAX]; size_t len; FILE *fp; DBG_INIT (); DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); DBG (1, "sane_init: SANE umax1220u backend version %d.%d.%d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); sanei_usb_init (); sanei_pv8630_init (); fp = sanei_config_open (UMAX_CONFIG_FILE); if (!fp) { /* no config-file: try /dev/scanner and /dev/usbscanner. */ attach_scanner ("/dev/scanner", 0); attach_scanner ("/dev/usbscanner", 0); return SANE_STATUS_GOOD; } DBG (3, "reading configure file %s\n", UMAX_CONFIG_FILE); while (sanei_config_read (config_line, sizeof (config_line), fp)) { if (config_line[0] == '#') continue; /* ignore line comments */ len = strlen (config_line); if (!len) continue; /* ignore empty lines */ DBG (4, "attach_matching_devices(%s)\n", config_line); sanei_usb_attach_matching_devices (config_line, attach_one); } DBG (4, "finished reading configure file\n"); fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { Umax_Device *dev, *next; DBG (3, "sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free (dev->name); free (dev); } if (devlist) free (devlist); return; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Umax_Device *dev; int i; DBG (3, "sane_get_devices(local_only = %d)\n", local_only); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Umax_Device *dev; SANE_Status status; Umax_Scanner *scanner; DBG (3, "sane_open\n"); if (devicename[0]) /* search for devicename */ { DBG (4, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } } else { DBG (2, "sane_open: no devicename, opening first device\n"); dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; scanner = malloc (sizeof (*scanner)); if (!scanner) return SANE_STATUS_NO_MEM; memset (scanner, 0, sizeof (*scanner)); scanner->device = dev; status = UMAX_open_device (&scanner->scan, dev->sane.name); if (status != SANE_STATUS_GOOD) { free (scanner); return status; } *handle = scanner; /* insert newly opened handle into list of open handles: */ scanner->next = first_handle; first_handle = scanner; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Umax_Scanner *prev, *scanner; DBG (3, "sane_close\n"); if (!first_handle) { DBG (1, "ERROR: sane_close: no handles opened\n"); return; } /* remove handle from list of open handles: */ prev = NULL; for (scanner = first_handle; scanner; scanner = scanner->next) { if (scanner == handle) break; prev = scanner; } if (!scanner) { DBG (1, "ERROR: sane_close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (prev) prev->next = scanner->next; else first_handle = scanner->next; UMAX_close_device (&scanner->scan); free (scanner); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { handle = handle; /* Eliminate compiler warning */ DBG (3, "sane_get_option_descriptor: option = %d\n", option); if (option < 0 || option >= NELEMS (so)) return NULL; return so[option].descriptor; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { handle = handle; /* Eliminate compiler warning */ DBG (3, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", handle, option, action, value, (void*) info); return dispatch_control_option (handle, option, action, value, info); } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int rc = SANE_STATUS_GOOD; int w = SANE_UNFIX (optionBotRightXValue - optionTopLeftXValue) / MM_IN_INCH * optionResolutionValue; int h = SANE_UNFIX (optionBotRightYValue - optionTopLeftYValue) / MM_IN_INCH * optionResolutionValue; handle = handle; /* Eliminate compiler warning */ DBG (3, "sane_get_parameters\n"); parms.depth = 8; parms.last_frame = SANE_TRUE; parms.pixels_per_line = w; parms.lines = h; if (optionGrayscaleValue == SANE_TRUE) { parms.format = SANE_FRAME_GRAY; parms.bytes_per_line = w; } else { parms.format = SANE_FRAME_RGB; parms.bytes_per_line = w * 3; } *params = parms; return rc; } SANE_Status sane_start (SANE_Handle handle) { Umax_Scanner *scanner = handle; SANE_Status res; DBG (3, "sane_start\n"); res = UMAX_set_scan_parameters (&scanner->scan, optionGrayscaleValue == SANE_FALSE, SANE_UNFIX (optionTopLeftXValue) / MM_IN_INCH * 600, SANE_UNFIX (optionTopLeftYValue) / MM_IN_INCH * 600, SANE_UNFIX (optionBotRightXValue - optionTopLeftXValue) / MM_IN_INCH * optionResolutionValue, SANE_UNFIX (optionBotRightYValue - optionTopLeftYValue) / MM_IN_INCH * optionResolutionValue, optionResolutionValue, optionResolutionValue); if (res != SANE_STATUS_GOOD) return res; if (scanner->scan.model == ASTRA_1220U) return UMAX_start_scan (&scanner->scan); else return UMAX_start_scan_2100U (&scanner->scan); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { Umax_Scanner *scanner = handle; SANE_Status res; int len; unsigned char rgb[3]; len = *length = 0; if (!data || !length) return SANE_STATUS_INVAL; if (scanner->scan.done) { res = UMAX_finish_scan (&scanner->scan); if (scanner->scan.model == ASTRA_1220U) res = UMAX_park_head (&scanner->scan); else res = UMAX_park_head_2100U (&scanner->scan); return SANE_STATUS_EOF; } DBG (3, "sane_read: max_length = %d\n", max_length); if (optionGrayscaleValue == SANE_FALSE) { while (!scanner->scan.done && (max_length >= 3)) { res = UMAX_get_rgb (&scanner->scan, rgb); if (res != SANE_STATUS_GOOD) { *length = 0; return res; } *data++ = rgb[0]; *data++ = rgb[1]; *data++ = rgb[2]; max_length -= 3; len += 3; } } else { while (!scanner->scan.done && max_length) { res = UMAX_get_rgb (&scanner->scan, rgb); if (res != SANE_STATUS_GOOD) { *length = 0; return res; } *data++ = rgb[0]; max_length--; len++; } } *length = len; return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { DBG (3, "sane_cancel: handle = %p\n", handle); DBG (3, "sane_cancel: canceling is unsupported in this backend\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (3, "sane_set_io_mode: handle = %p, non_blocking = %d\n", handle, non_blocking); if (non_blocking != SANE_FALSE) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (3, "sane_get_select_fd: handle = %p, fd %s 0\n", handle, fd ? "!=" : "="); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/hp.h0000664000175000017500000001511412775312261013401 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ #ifndef HP_H_INCLUDED #define HP_H_INCLUDED #include #include #include "../include/sane/sane.h" #undef BACKEND_NAME #define BACKEND_NAME hp #define DEBUG_NOT_STATIC #include "../include/sane/sanei_debug.h" /* FIXME: these should be options? */ #undef ENABLE_7x12_TONEMAPS #define ENABLE_16x16_DITHERS #define ENABLE_10BIT_MATRIXES #define FAKE_COLORSEP_MATRIXES #undef ENABLE_CUSTOM_MATRIX #define HP_CONFIG_FILE STRINGIFY(BACKEND_NAME) ".conf" #define DEVPIX_PER_INCH 300.0 #define MM_PER_DEVPIX (MM_PER_INCH / DEVPIX_PER_INCH) /* * Macros for testing return values of functions which * return SANE_Status types. */ #define FAILED(status) (status != SANE_STATUS_GOOD) #define UNSUPPORTED(status) (status == SANE_STATUS_UNSUPPORTED) #define RETURN_IF_FAIL(try) do { \ SANE_Status status = (try); \ if (FAILED(status)) \ return status; \ } while (0) #define CATCH_RET_FAIL(try, catch) do { \ SANE_Status status = (try); \ if (FAILED(status)) { (catch); return status; } \ } while (0) #ifndef DBG_LEVEL #define DBG_LEVEL PASTE(sanei_debug_, BACKEND_NAME) #endif #ifndef NDEBUG # define DBGDUMP(level, buf, size) \ do { if (DBG_LEVEL >= (level)) sanei_hp_dbgdump(buf, size); } while (0) #else # define DBGDUMP(level, buf, size) #endif /* * */ typedef unsigned int hp_bool_t; typedef unsigned char hp_byte_t; typedef enum { HP_CONNECT_SCSI, HP_CONNECT_DEVICE, HP_CONNECT_PIO, HP_CONNECT_USB, HP_CONNECT_RESERVE } HpConnect; typedef struct { HpConnect connect; hp_bool_t got_connect_type; hp_bool_t use_scsi_request; hp_bool_t use_image_buffering; hp_bool_t dumb_read; } HpDeviceConfig; #define HP_SCL_INQID_MIN 10306 #define HP_SCL_INQID_MAX 10971 typedef struct { hp_bool_t checked, is_supported; int minval, maxval; } HpSclSupport; typedef struct { /* Flags for simulated commands */ hp_bool_t sclsimulate[HP_SCL_INQID_MAX - HP_SCL_INQID_MIN + 1]; hp_bool_t gamma_simulate; unsigned char brightness_map[256]; /* Map to simulate brightness level */ unsigned char contrast_map[256]; /* Map to simulate contrast level */ unsigned char gamma_map[256]; /* Map to simulate custom gamma table */ } HpSimulate; /* Information about a connected device */ typedef struct { char devname[64]; /* unique device name */ hp_bool_t config_is_up; /* flag if config-struct is valid */ HpDeviceConfig config; /* device configuration*/ /* List of command support */ HpSclSupport sclsupport[HP_SCL_INQID_MAX - HP_SCL_INQID_MIN + 1]; HpSimulate simulate; /* Info about simulations */ hp_bool_t unload_after_scan; int active_xpa; int max_model; } HpDeviceInfo; HpDeviceInfo *sanei_hp_device_info_get (const char *dev_name); /* hp-scl.c */ #if INT_MAX > 30000 typedef int HpScl; #else typedef long int HpScl; #endif void sanei_hp_init_openfd (void); typedef struct { int lines; int bytes_per_line; /* as received from scanner */ int bits_per_channel; hp_bool_t out8; /* This flag is set and only set, when data with */ /* depths > 8 is to be mapped to 8 bit output. */ hp_bool_t mirror_vertical; hp_bool_t invert; HpScl startscan; } HpProcessData; /* hp-option.c */ typedef SANE_Option_Descriptor * HpSaneOption; typedef const struct hp_choice_s * HpChoice; typedef struct hp_option_s * HpOption; typedef const struct hp_option_descriptor_s * HpOptionDescriptor; typedef struct hp_optset_s * HpOptSet; /* hp-accessor.c */ typedef struct hp_data_s * HpData; typedef struct hp_accessor_s * HpAccessor; typedef struct hp_accessor_vector_s * HpAccessorVector; typedef struct hp_accessor_choice_s * HpAccessorChoice; /* hp-device.c */ typedef struct hp_device_s * HpDevice; hp_bool_t sanei_hp_device_simulate_get (const char *devname, HpScl scl); HpDevice sanei_hp_device_get (const char *dev_name); /* hp-handle.c */ typedef struct hp_handle_s * HpHandle; /* hp-scsi.c */ typedef struct hp_scsi_s * HpScsi; /* hp-scl.c */ hp_bool_t sanei_hp_is_active_xpa (HpScsi scsi); int sanei_hp_get_max_model (HpScsi scsi); int sanei_hp_is_flatbed_adf (HpScsi scsi); HpConnect sanei_hp_get_connect (const char *devname); HpConnect sanei_hp_scsi_get_connect (HpScsi this); /* hp.c */ #ifndef NDEBUG void sanei_hp_dbgdump (const void * bufp, size_t len); #endif /* hp-hpmem.c */ void * sanei_hp_alloc(size_t sz); void * sanei_hp_allocz(size_t sz); void * sanei_hp_memdup(const void * src, size_t sz); char * sanei_hp_strdup(const char * str); void * sanei_hp_realloc(void * ptr, size_t sz); void sanei_hp_free(void * ptr); void sanei_hp_free_all(void); #endif /* HP_H_INCLUDED */ sane-backends-1.0.27/backend/plustek-usbcal.c0000664000175000017500000012301112112021330015672 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners; canoscan calibration *............................................................................. */ /** @file plustek-usbcal.c * @brief Calibration routines for CanoScan CIS devices. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2007 Gerhard Jaeger
* Large parts Copyright (C) 2003 Christopher Montgomery * * Montys' comment: * The basic premise: The stock Plustek-usbshading.c in the plustek * driver is effectively nonfunctional for Canon CanoScan scanners. * These scanners rely heavily on all calibration steps, especially * fine white, to produce acceptible scan results. However, to make * autocalibration work and make it work well involves some * substantial mucking aobut in code that supports thirty other * scanners with widely varying characteristics... none of which I own * or can test. * * Therefore, I'm splitting out a few calibration functions I need * to modify for the CanoScan which allows me to simplify things * greatly for the CanoScan without worrying about breaking other * scanners, as well as reuse the vast majority of the Plustek * driver infrastructure without forking. * * History: * - 0.45m - birth of the file; tested extensively with the LiDE 20 * - 0.46 - renamed to plustek-usbcal.c * - fixed problems with LiDE30, works now with 650, 1220, 670, 1240 * - cleanup * - added CCD calibration capability * - added the usage of the swGain and swOffset values, to allow * tweaking the calibration results on a sensor base * - 0.47 - moved usb_HostSwap() to plustek_usbhw.c * - fixed problem in cano_AdjustLightsource(), so that it won't * stop too early. * - 0.48 - cleanup * - 0.49 - a_bRegs is now part of the device structure * - fixed lampsetting in cano_AdjustLightsource() * - 0.50 - tried to use the settings from SANE-1.0.13 * - added _TWEAK_GAIN to allow increasing GAIN during * lamp coarse calibration * - added also speedtest * - fixed segfault in fine calibration * - 0.51 - added fine calibration cache * - usb_SwitchLamp() now really switches off the sensor * - 0.52 - fixed setting for frontend values (gain/offset) * - added 0 pixel detection for offset calculation * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /* un-/comment the following to en-/disable lamp coarse calibration to tweak * the initial AFE gain settings */ #define _TWEAK_GAIN 1 /* set the threshold for 0 pixels (in percent if pixels per line) */ #define _DARK_TGT_THRESH 1 /** 0 for not ready, 1 pos white lamp on, 2 lamp off */ static int strip_state = 0; /** depending on the strip state, the sensor is moved to the shading position * and the lamp ist switched on */ static int cano_PrepareToReadWhiteCal( Plustek_Device *dev, SANE_Bool mv2shading_pos ) { SANE_Bool goto_shading_pos = SANE_TRUE; HWDef *hw = &dev->usbDev.HwSetting; switch (strip_state) { case 0: if( !usb_IsSheetFedDevice(dev)) { if(!usb_ModuleToHome( dev, SANE_TRUE )) { DBG( _DBG_ERROR, "cano_PrepareToReadWhiteCal() failed\n" ); return _E_LAMP_NOT_IN_POS; } } else { goto_shading_pos = mv2shading_pos; } if( goto_shading_pos ) { if( !usb_ModuleMove(dev, MOVE_Forward, (u_long)dev->usbDev.pSource->ShadingOriginY)) { DBG( _DBG_ERROR, "cano_PrepareToReadWhiteCal() failed\n" ); return _E_LAMP_NOT_IN_POS; } } break; case 2: dev->usbDev.a_bRegs[0x29] = hw->bReg_0x29; usb_switchLamp( dev, SANE_TRUE ); if( !usbio_WriteReg( dev->fd, 0x29, dev->usbDev.a_bRegs[0x29])) { DBG( _DBG_ERROR, "cano_PrepareToReadWhiteCal() failed\n" ); return _E_LAMP_NOT_IN_POS; } break; } strip_state = 1; return 0; } /** also here, depending on the strip state, the sensor will be moved to * the shading position and the lamp will be switched off */ static int cano_PrepareToReadBlackCal( Plustek_Device *dev ) { if( strip_state == 0 ) if(cano_PrepareToReadWhiteCal(dev, SANE_FALSE)) return SANE_FALSE; if( strip_state != 2 ) { /* * if we have a dark shading strip, there's no need to switch * the lamp off, leave in on a go to that strip */ if( dev->usbDev.pSource->DarkShadOrgY >= 0 ) { if( !usb_IsSheetFedDevice(dev)) usb_ModuleToHome( dev, SANE_TRUE ); usb_ModuleMove ( dev, MOVE_Forward, (u_long)dev->usbDev.pSource->DarkShadOrgY ); dev->usbDev.a_bRegs[0x45] &= ~0x10; strip_state = 0; } else { /* switch lamp off to read dark data... */ dev->usbDev.a_bRegs[0x29] = 0; usb_switchLamp( dev, SANE_FALSE ); strip_state = 2; } } return 0; } /** according to the strip-state we switch the lamp on */ static int cano_LampOnAfterCalibration( Plustek_Device *dev ) { HWDef *hw = &dev->usbDev.HwSetting; switch (strip_state) { case 2: dev->usbDev.a_bRegs[0x29] = hw->bReg_0x29; usb_switchLamp( dev, SANE_TRUE ); if( !usbio_WriteReg( dev->fd, 0x29, dev->usbDev.a_bRegs[0x29])) { DBG( _DBG_ERROR, "cano_LampOnAfterCalibration() failed\n" ); return _E_LAMP_NOT_IN_POS; } strip_state = 1; break; } return 0; } /** function to adjust the CIS lamp-off setting for a given channel. * @param min - pointer to the min OFF point for the CIS-channel * @param max - pointer to the max OFF point for the CIS-channel * @param off - pointer to the current OFF point of the CIS-channel * @param val - current value to check * @return returns 0 if the value is fine, 1, if we need to adjust */ static int cano_adjLampSetting( u_short *min, u_short *max, u_short *off, u_short val ) { u_long newoff = *off; /* perfect value, no need to adjust * val [53440..61440] is perfect */ if((val < (IDEAL_GainNormal)) && (val > (IDEAL_GainNormal-8000))) return 0; if(val >= (IDEAL_GainNormal-4000)) { DBG(_DBG_INFO2, "* TOO BRIGHT --> reduce\n" ); *max = newoff; *off = ((newoff + *min)>>1); } else { u_short bisect = (newoff + *max)>>1; u_short twice = newoff*2; DBG(_DBG_INFO2, "* TOO DARK --> up\n" ); *min = newoff; *off = twice 0x3FFF ) { DBG( _DBG_INFO, "* lamp off limited (0x%04x --> 0x3FFF)\n", *off); *off = 0x3FFF; return 10; } } if((*min+1) >= *max ) return 0; return 1; } /** cano_AdjustLightsource * coarse calibration step 0 * [Monty changes]: On the CanoScan at least, the default lamp * settings are several *hundred* percent too high and vary from * scanner-to-scanner by 20-50%. This is only for CIS devices * where the lamp_off parameter is adjustable; I'd make it more general, * but I only have the CIS hardware to test. */ static int cano_AdjustLightsource( Plustek_Device *dev ) { char tmp[40]; int i; int res_r, res_g, res_b; u_long dw, dwR, dwG, dwB, dwDiv, dwLoop1, dwLoop2; RGBUShortDef max_rgb, min_rgb, tmp_rgb; u_long *scanbuf = dev->scanning.pScanBuffer; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; if( usb_IsEscPressed()) return SANE_FALSE; DBG( _DBG_INFO, "cano_AdjustLightsource()\n" ); if( !usb_IsCISDevice(dev)) { DBG( _DBG_INFO, "- function skipped, CCD device!\n" ); /* HEINER: we might have to tweak the PWM for the lamps */ return SANE_TRUE; } /* define the strip to scan for coarse calibration * done at optical resolution. */ m_ScanParam.Size.dwLines = 1; m_ScanParam.Size.dwPixels = scaps->Normal.Size.x * scaps->OpticDpi.x / 300UL; m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2; if( m_ScanParam.bDataType == SCANDATATYPE_Color ) m_ScanParam.Size.dwBytes *=3; m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart * 300UL / scaps->OpticDpi.x); m_ScanParam.bCalibration = PARAM_Gain; DBG( _DBG_INFO2, "* Coarse Calibration Strip:\n" ); DBG( _DBG_INFO2, "* Lines = %lu\n", m_ScanParam.Size.dwLines ); DBG( _DBG_INFO2, "* Pixels = %lu\n", m_ScanParam.Size.dwPixels ); DBG( _DBG_INFO2, "* Bytes = %lu\n", m_ScanParam.Size.dwBytes ); DBG( _DBG_INFO2, "* Origin.X = %u\n", m_ScanParam.Origin.x ); /* init... */ max_rgb.Red = max_rgb.Green = max_rgb.Blue = 0x3fff; min_rgb.Red = hw->red_lamp_on; min_rgb.Green = hw->green_lamp_on; min_rgb.Blue = hw->blue_lamp_on; if((dev->adj.rlampoff != -1) && (dev->adj.glampoff != -1) && (dev->adj.rlampoff != -1)) { DBG( _DBG_INFO, "- function skipped, using frontend values!\n" ); return SANE_TRUE; } /* we probably should preset gain to some reasonably good value * i.e. 0x0a as it's done by Canon within their Windoze driver! */ #ifdef _TWEAK_GAIN for( i=0x3b; i<0x3e; i++ ) dev->usbDev.a_bRegs[i] = 0x0a; #endif for( i = 0; ; i++ ) { m_ScanParam.dMCLK = dMCLK; if( !usb_SetScanParameters( dev, &m_ScanParam )) { return SANE_FALSE; } if( !usb_ScanBegin( dev, SANE_FALSE) || !usb_ScanReadImage( dev, scanbuf, m_ScanParam.Size.dwPhyBytes ) || !usb_ScanEnd( dev )) { DBG( _DBG_ERROR, "* cano_AdjustLightsource() failed\n" ); return SANE_FALSE; } DBG( _DBG_INFO2, "* PhyBytes = %lu\n", m_ScanParam.Size.dwPhyBytes ); DBG( _DBG_INFO2, "* PhyPixels = %lu\n", m_ScanParam.Size.dwPhyPixels); sprintf( tmp, "coarse-lamp-%u.raw", i ); dumpPicInit(&m_ScanParam, tmp); dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwPhyBytes, 0); if(usb_HostSwap()) usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwPhyBytes ); sprintf( tmp, "coarse-lamp-swap%u.raw", i ); dumpPicInit(&m_ScanParam, tmp); dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwPhyBytes, 0); dwDiv = 10; dwLoop1 = m_ScanParam.Size.dwPhyPixels/dwDiv; tmp_rgb.Red = tmp_rgb.Green = tmp_rgb.Blue = 0; /* find out the max pixel value for R, G, B */ for( dw = 0; dwLoop1; dwLoop1-- ) { /* do some averaging... */ for (dwLoop2 = dwDiv, dwR = dwG = dwB = 0; dwLoop2; dwLoop2--, dw++) { if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { if( usb_IsCISDevice(dev)) { dwR += ((u_short*)scanbuf)[dw]; dwG += ((u_short*)scanbuf) [dw+m_ScanParam.Size.dwPhyPixels+1]; dwB += ((u_short*)scanbuf) [dw+(m_ScanParam.Size.dwPhyPixels+1)*2]; } else { dwR += ((RGBUShortDef*)scanbuf)[dw].Red; dwG += ((RGBUShortDef*)scanbuf)[dw].Green; dwB += ((RGBUShortDef*)scanbuf)[dw].Blue; } } else { dwG += ((u_short*)scanbuf)[dw]; } } dwR = dwR / dwDiv; dwG = dwG / dwDiv; dwB = dwB / dwDiv; if( tmp_rgb.Red < dwR ) tmp_rgb.Red = dwR; if( tmp_rgb.Green < dwG ) tmp_rgb.Green = dwG; if( tmp_rgb.Blue < dwB ) tmp_rgb.Blue = dwB; } if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { DBG( _DBG_INFO2, "red_lamp_off = %u/%u/%u\n", min_rgb.Red ,hw->red_lamp_off, max_rgb.Red ); } DBG( _DBG_INFO2, "green_lamp_off = %u/%u/%u\n", min_rgb.Green, hw->green_lamp_off, max_rgb.Green ); if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { DBG( _DBG_INFO2, "blue_lamp_off = %u/%u/%u\n", min_rgb.Blue, hw->blue_lamp_off, max_rgb.Blue ); } DBG(_DBG_INFO2, "CUR(R,G,B)= 0x%04x(%u), 0x%04x(%u), 0x%04x(%u)\n", tmp_rgb.Red, tmp_rgb.Red, tmp_rgb.Green, tmp_rgb.Green, tmp_rgb.Blue, tmp_rgb.Blue ); res_r = 0; res_g = 0; res_b = 0; /* bisect */ if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { res_r = cano_adjLampSetting( &min_rgb.Red, &max_rgb.Red, &hw->red_lamp_off, tmp_rgb.Red ); res_b = cano_adjLampSetting( &min_rgb.Blue, &max_rgb.Blue, &hw->blue_lamp_off,tmp_rgb.Blue ); } res_g = cano_adjLampSetting( &min_rgb.Green, &max_rgb.Green, &hw->green_lamp_off, tmp_rgb.Green ); /* nothing adjusted, so stop here */ if((res_r == 0) && (res_g == 0) && (res_b == 0)) break; /* no need to adjust more, we have already reached the limit * without tweaking the gain. */ if((res_r == 10) && (res_g == 10) && (res_b == 10)) break; /* we raise the gain for channels, that have been limited */ #ifdef _TWEAK_GAIN if( res_r == 10 ) { if( dev->usbDev.a_bRegs[0x3b] < 0xf) dev->usbDev.a_bRegs[0x3b]++; } if( res_g == 10 ) { if( dev->usbDev.a_bRegs[0x3c] < 0x0f) dev->usbDev.a_bRegs[0x3c]++; } if( res_b == 10 ) { if( dev->usbDev.a_bRegs[0x3d] < 0x0f) dev->usbDev.a_bRegs[0x3d]++; } #endif /* now decide what to do: * if we were too bright, we have to rerun the loop in any * case * if we're too dark, we should rerun it too, but we can * compensate that using higher gain values later */ if( i >= 10 ) { DBG(_DBG_INFO, "* 10 times limit reached, still too dark!!!\n"); break; } usb_AdjustLamps(dev, SANE_TRUE); } DBG( _DBG_INFO, "* red_lamp_on = %u\n", hw->red_lamp_on ); DBG( _DBG_INFO, "* red_lamp_off = %u\n", hw->red_lamp_off ); DBG( _DBG_INFO, "* green_lamp_on = %u\n", hw->green_lamp_on ); DBG( _DBG_INFO, "* green_lamp_off = %u\n", hw->green_lamp_off ); DBG( _DBG_INFO, "* blue_lamp_on = %u\n", hw->blue_lamp_on ); DBG( _DBG_INFO, "* blue_lamp_off = %u\n", hw->blue_lamp_off ); DBG( _DBG_INFO, "cano_AdjustLightsource() done.\n" ); return SANE_TRUE; } /** */ static int cano_adjGainSetting( u_char *min, u_char *max, u_char *gain,u_long val ) { u_long newgain = *gain; if((val < IDEAL_GainNormal) && (val > (IDEAL_GainNormal-8000))) return 0; if(val > (IDEAL_GainNormal-4000)) { *max = newgain; *gain = (newgain + *min)>>1; } else { *min = newgain; *gain = (newgain + *max)>>1; } if((*min+1) >= *max) return 0; return 1; } /** cano_AdjustGain * function to perform the "coarse calibration step" part 1. * We scan reference image pixels to determine the optimum coarse gain settings * for R, G, B. (Analog gain and offset prior to ADC). These coefficients are * applied at the line rate during normal scanning. * The scanned line should contain a white strip with some black at the * beginning. The function searches for the maximum value which corresponds to * the maximum white value. * Affects register 0x3b, 0x3c and 0x3d * * adjLightsource, above, steals most of this function's thunder. */ static SANE_Bool cano_AdjustGain( Plustek_Device *dev ) { char tmp[40]; int i = 0, adj = 1; u_long dw; u_long *scanbuf = dev->scanning.pScanBuffer; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; unsigned char max[3], min[3]; if( usb_IsEscPressed()) return SANE_FALSE; bMaxITA = 0xff; max[0] = max[1] = max[2] = 0x3f; min[0] = min[1] = min[2] = 1; DBG( _DBG_INFO, "cano_AdjustGain()\n" ); if( !usb_InCalibrationMode(dev)) { if((dev->adj.rgain != -1) && (dev->adj.ggain != -1) && (dev->adj.bgain != -1)) { setAdjGain( dev->adj.rgain, &dev->usbDev.a_bRegs[0x3b] ); setAdjGain( dev->adj.ggain, &dev->usbDev.a_bRegs[0x3c] ); setAdjGain( dev->adj.bgain, &dev->usbDev.a_bRegs[0x3d] ); DBG( _DBG_INFO, "- function skipped, using frontend values!\n" ); return SANE_TRUE; } } /* define the strip to scan for coarse calibration * done at 300dpi */ m_ScanParam.Size.dwLines = 1; /* for gain */ m_ScanParam.Size.dwPixels = scaps->Normal.Size.x * scaps->OpticDpi.x / 300UL; m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2; if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color) m_ScanParam.Size.dwBytes *=3; m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart * 300UL / scaps->OpticDpi.x); m_ScanParam.bCalibration = PARAM_Gain; DBG( _DBG_INFO2, "Coarse Calibration Strip:\n" ); DBG( _DBG_INFO2, "Lines = %lu\n", m_ScanParam.Size.dwLines ); DBG( _DBG_INFO2, "Pixels = %lu\n", m_ScanParam.Size.dwPixels ); DBG( _DBG_INFO2, "Bytes = %lu\n", m_ScanParam.Size.dwBytes ); DBG( _DBG_INFO2, "Origin.X = %u\n", m_ScanParam.Origin.x ); while( adj ) { m_ScanParam.dMCLK = dMCLK; if( !usb_SetScanParameters( dev, &m_ScanParam )) return SANE_FALSE; if( !usb_ScanBegin( dev, SANE_FALSE) || !usb_ScanReadImage(dev,scanbuf,m_ScanParam.Size.dwPhyBytes) || !usb_ScanEnd( dev )) { DBG( _DBG_ERROR, "cano_AdjustGain() failed\n" ); return SANE_FALSE; } DBG( _DBG_INFO2, "PhyBytes = %lu\n", m_ScanParam.Size.dwPhyBytes ); DBG( _DBG_INFO2, "PhyPixels = %lu\n", m_ScanParam.Size.dwPhyPixels ); sprintf( tmp, "coarse-gain-%u.raw", i++ ); dumpPicInit(&m_ScanParam, tmp); dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwPhyBytes, 0); if(usb_HostSwap()) usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwPhyBytes ); if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { RGBUShortDef max_rgb; u_long dwR, dwG, dwB; u_long dwDiv = 10; u_long dwLoop1 = m_ScanParam.Size.dwPhyPixels/dwDiv, dwLoop2; max_rgb.Red = max_rgb.Green = max_rgb.Blue = 0; /* find out the max pixel value for R, G, B */ for( dw = 0; dwLoop1; dwLoop1-- ) { /* do some averaging... */ for (dwLoop2 = dwDiv, dwR=dwG=dwB=0; dwLoop2; dwLoop2--, dw++) { if( usb_IsCISDevice(dev)) { dwR += ((u_short*)scanbuf)[dw]; dwG += ((u_short*)scanbuf) [dw+m_ScanParam.Size.dwPhyPixels+1]; dwB += ((u_short*)scanbuf) [dw+(m_ScanParam.Size.dwPhyPixels+1)*2]; } else { dwR += ((RGBUShortDef*)scanbuf)[dw].Red; dwG += ((RGBUShortDef*)scanbuf)[dw].Green; dwB += ((RGBUShortDef*)scanbuf)[dw].Blue; } } dwR = dwR / dwDiv; dwG = dwG / dwDiv; dwB = dwB / dwDiv; if(max_rgb.Red < dwR) max_rgb.Red = dwR; if(max_rgb.Green < dwG) max_rgb.Green = dwG; if(max_rgb.Blue < dwB) max_rgb.Blue = dwB; } DBG(_DBG_INFO2, "MAX(R,G,B)= 0x%04x(%u), 0x%04x(%u), 0x%04x(%u)\n", max_rgb.Red, max_rgb.Red, max_rgb.Green, max_rgb.Green, max_rgb.Blue, max_rgb.Blue ); adj = cano_adjGainSetting(min , max ,dev->usbDev.a_bRegs+0x3b,max_rgb.Red ); adj += cano_adjGainSetting(min+1, max+1,dev->usbDev.a_bRegs+0x3c,max_rgb.Green); adj += cano_adjGainSetting(min+2, max+2,dev->usbDev.a_bRegs+0x3d,max_rgb.Blue ); } else { u_short w_max = 0; for( dw = 0; dw < m_ScanParam.Size.dwPhyPixels; dw++ ) { if( w_max < ((u_short*)scanbuf)[dw]) w_max = ((u_short*)scanbuf)[dw]; } adj = cano_adjGainSetting(min,max,dev->usbDev.a_bRegs+0x3c,w_max); dev->usbDev.a_bRegs[0x3b] = (dev->usbDev.a_bRegs[0x3d] = dev->usbDev.a_bRegs[0x3c]); DBG(_DBG_INFO2, "MAX(G)= 0x%04x(%u)\n", w_max, w_max ); } DBG( _DBG_INFO2, "REG[0x3b] = %u\n", dev->usbDev.a_bRegs[0x3b] ); DBG( _DBG_INFO2, "REG[0x3c] = %u\n", dev->usbDev.a_bRegs[0x3c] ); DBG( _DBG_INFO2, "REG[0x3d] = %u\n", dev->usbDev.a_bRegs[0x3d] ); } DBG( _DBG_INFO, "cano_AdjustGain() done.\n" ); return SANE_TRUE; } static int tweak_offset[3]; /** */ static int cano_GetNewOffset(Plustek_Device *dev, u_long *val, int channel, signed char *low, signed char *now, signed char *high, u_long *zc) { DCapsDef *scaps = &dev->usbDev.Caps; if (tweak_offset[channel]) { /* if we're too black, we're likely off the low end */ if( val[channel] <= 16 ) { low[channel] = now[channel]; now[channel] = (now[channel]+high[channel])/2; dev->usbDev.a_bRegs[0x38+channel]= (now[channel]&0x3f); if( low[channel]+1 >= high[channel] ) return 0; return 1; } else if ( val[channel]>=2048 ) { high[channel]=now[channel]; now[channel]=(now[channel]+low[channel])/2; dev->usbDev.a_bRegs[0x38+channel]= (now[channel]&0x3f); if(low[channel]+1>=high[channel]) return 0; return 1; } } if (!(scaps->workaroundFlag & _WAF_INC_DARKTGT)) { DBG( _DBG_INFO, "0 Pixel adjustment not active!\n"); return 0; } /* reaching this point, our black level should be okay, but * we also should check the percentage of 0 level pixels. * It turned out, that when having a lot of 0 level pixels, * the calibration will be bad and the resulting scans show up * stripes... */ if (zc[channel] > _DARK_TGT_THRESH) { DBG( _DBG_INFO2, "More than %u%% 0 pixels detected, raise offset!\n", _DARK_TGT_THRESH); high[channel]=now[channel]; now[channel]=(now[channel]+low[channel])/2; /* no more value checks, the goal to set the black level < 2048 * will cause stripes... */ tweak_offset[channel] = 0; dev->usbDev.a_bRegs[0x38+channel]= (now[channel]&0x3f); if( low[channel]+1 >= high[channel] ) return 0; return 1; } #if 0 else if ( val[channel]>=4096 ) { low[channel] = now[channel]; now[channel] = (now[channel]+high[channel])/2; dev->usbDev.a_bRegs[0x38+channel]= (now[channel]&0x3f); if( low[channel]+1 >= high[channel] ) return 0; return 1; } #endif return 0; } /** cano_AdjustOffset * function to perform the "coarse calibration step" part 2. * We scan reference image pixels to determine the optimum coarse offset settings * for R, G, B. (Analog gain and offset prior to ADC). These coefficients are * applied at the line rate during normal scanning. * On CIS based devices, we switch the light off, on CCD devices, we use the optical * black pixels. * Affects register 0x38, 0x39 and 0x3a */ /* Move this to a bisection-based algo and correct some fenceposts; Plustek's example code disagrees with NatSemi's docs; going by the docs works better, I will assume the docs are correct. --Monty */ static int cano_AdjustOffset( Plustek_Device *dev ) { char tmp[40]; int i, adj; u_short r, g, b; u_long dw, dwPixels; u_long dwSum[3], zCount[3]; signed char low[3] = {-32,-32,-32 }; signed char now[3] = { 0, 0, 0 }; signed char high[3] = { 31, 31, 31 }; u_long *scanbuf = dev->scanning.pScanBuffer; HWDef *hw = &dev->usbDev.HwSetting; DCapsDef *scaps = &dev->usbDev.Caps; if( usb_IsEscPressed()) return SANE_FALSE; DBG( _DBG_INFO, "cano_AdjustOffset()\n" ); if( !usb_InCalibrationMode(dev)) { if((dev->adj.rofs != -1) && (dev->adj.gofs != -1) && (dev->adj.bofs != -1)) { dev->usbDev.a_bRegs[0x38] = (dev->adj.rofs & 0x3f); dev->usbDev.a_bRegs[0x39] = (dev->adj.gofs & 0x3f); dev->usbDev.a_bRegs[0x3a] = (dev->adj.bofs & 0x3f); DBG( _DBG_INFO, "- function skipped, using frontend values!\n" ); return SANE_TRUE; } } m_ScanParam.Size.dwLines = 1; m_ScanParam.Size.dwPixels = scaps->Normal.Size.x*scaps->OpticDpi.x/300UL; if( usb_IsCISDevice(dev)) dwPixels = m_ScanParam.Size.dwPixels; else dwPixels = (u_long)(hw->bOpticBlackEnd - hw->bOpticBlackStart); m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2; if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color) m_ScanParam.Size.dwBytes *= 3; m_ScanParam.Origin.x = (u_short)((u_long)hw->bOpticBlackStart * 300UL / dev->usbDev.Caps.OpticDpi.x); m_ScanParam.bCalibration = PARAM_Offset; m_ScanParam.dMCLK = dMCLK; if( !usb_SetScanParameters( dev, &m_ScanParam )) { DBG( _DBG_ERROR, "cano_AdjustOffset() failed\n" ); return SANE_FALSE; } DBG( _DBG_INFO2, "S.dwPixels = %lu\n", m_ScanParam.Size.dwPixels ); DBG( _DBG_INFO2, "dwPixels = %lu\n", dwPixels ); DBG( _DBG_INFO2, "dwPhyBytes = %lu\n", m_ScanParam.Size.dwPhyBytes ); DBG( _DBG_INFO2, "dwPhyPixels = %lu\n", m_ScanParam.Size.dwPhyPixels ); tweak_offset[0] = tweak_offset[1] = tweak_offset[2] = 1; for( i = 0, adj = 1; adj != 0; i++ ) { if((!usb_ScanBegin(dev, SANE_FALSE)) || (!usb_ScanReadImage(dev,scanbuf,m_ScanParam.Size.dwPhyBytes)) || !usb_ScanEnd( dev )) { DBG( _DBG_ERROR, "cano_AdjustOffset() failed\n" ); return SANE_FALSE; } sprintf( tmp, "coarse-off-%u.raw", i ); dumpPicInit(&m_ScanParam, tmp); dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwPhyBytes, 0); if(usb_HostSwap()) usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwPhyBytes ); if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { dwSum[0] = dwSum[1] = dwSum[2] = 0; zCount[0] = zCount[1] = zCount[2] = 0; for (dw = 0; dw < dwPixels; dw++) { if( usb_IsCISDevice(dev)) { r = ((u_short*)scanbuf)[dw]; g = ((u_short*)scanbuf)[dw+m_ScanParam.Size.dwPhyPixels+1]; b = ((u_short*)scanbuf)[dw+(m_ScanParam.Size.dwPhyPixels+1)*2]; } else { r = ((RGBUShortDef*)scanbuf)[dw].Red; g = ((RGBUShortDef*)scanbuf)[dw].Green; b = ((RGBUShortDef*)scanbuf)[dw].Blue; } dwSum[0] += r; dwSum[1] += g; dwSum[2] += b; if (r==0) zCount[0]++; if (g==0) zCount[1]++; if (b==0) zCount[2]++; } DBG( _DBG_INFO2, "RedSum = %lu, ave = %lu, ZC=%lu, %lu%%\n", dwSum[0], dwSum[0]/dwPixels, zCount[0], (zCount[0]*100)/dwPixels); DBG( _DBG_INFO2, "GreenSum = %lu, ave = %lu, ZC=%lu, %lu%%\n", dwSum[1], dwSum[1]/dwPixels, zCount[1], (zCount[1]*100)/dwPixels); DBG( _DBG_INFO2, "BlueSum = %lu, ave = %lu, ZC=%lu, %lu%%\n", dwSum[2], dwSum[2]/dwPixels, zCount[2], (zCount[2]*100)/dwPixels); /* do averaging for each channel */ dwSum[0] /= dwPixels; dwSum[1] /= dwPixels; dwSum[2] /= dwPixels; zCount[0] = (zCount[0] * 100)/ dwPixels; zCount[1] = (zCount[1] * 100)/ dwPixels; zCount[2] = (zCount[2] * 100)/ dwPixels; adj = cano_GetNewOffset(dev, dwSum, 0, low, now, high, zCount); adj |= cano_GetNewOffset(dev, dwSum, 1, low, now, high, zCount); adj |= cano_GetNewOffset(dev, dwSum, 2, low, now, high, zCount); DBG( _DBG_INFO2, "RedOff = %d/%d/%d\n", (int)low[0],(int)now[0],(int)high[0]); DBG( _DBG_INFO2, "GreenOff = %d/%d/%d\n", (int)low[1],(int)now[1],(int)high[1]); DBG( _DBG_INFO2, "BlueOff = %d/%d/%d\n", (int)low[2],(int)now[2],(int)high[2]); } else { dwSum[0] = 0; zCount[0] = 0; for( dw = 0; dw < dwPixels; dw++ ) { dwSum[0] += ((u_short*)scanbuf)[dw]; if (((u_short*)scanbuf)[dw] == 0) zCount[0]++; } DBG( _DBG_INFO2, "Sum=%lu, ave=%lu, ZC=%lu, %lu%%\n", dwSum[0],dwSum[0]/dwPixels, zCount[0], (zCount[0]*100)/dwPixels); dwSum[0] /= dwPixels; zCount[0] = (zCount[0] * 100)/ dwPixels; adj = cano_GetNewOffset(dev, dwSum, 0, low, now, high, zCount); dev->usbDev.a_bRegs[0x3a] = dev->usbDev.a_bRegs[0x39] = dev->usbDev.a_bRegs[0x38]; DBG( _DBG_INFO2, "GrayOff = %d/%d/%d\n", (int)low[0],(int)now[0],(int)high[0]); } DBG( _DBG_INFO2, "REG[0x38] = %u\n", dev->usbDev.a_bRegs[0x38] ); DBG( _DBG_INFO2, "REG[0x39] = %u\n", dev->usbDev.a_bRegs[0x39] ); DBG( _DBG_INFO2, "REG[0x3a] = %u\n", dev->usbDev.a_bRegs[0x3a] ); _UIO(sanei_lm983x_write(dev->fd, 0x38, &dev->usbDev.a_bRegs[0x38], 3, SANE_TRUE)); } /* is that really needed?! */ if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { dev->usbDev.a_bRegs[0x38] = now[0] & 0x3f; dev->usbDev.a_bRegs[0x39] = now[1] & 0x3f; dev->usbDev.a_bRegs[0x3a] = now[2] & 0x3f; } else { dev->usbDev.a_bRegs[0x38] = dev->usbDev.a_bRegs[0x39] = dev->usbDev.a_bRegs[0x3a] = now[0] & 0x3f; } DBG( _DBG_INFO, "cano_AdjustOffset() done.\n" ); return SANE_TRUE; } /** usb_AdjustDarkShading * fine calibration part 1 */ static SANE_Bool cano_AdjustDarkShading( Plustek_Device *dev, u_short cal_dpi ) { char tmp[40]; ScanParam *param = &dev->scanning.sParam; ScanDef *scan = &dev->scanning; u_long *scanbuf = scan->pScanBuffer; u_short *bufp; unsigned int i, j; int step, stepW, val; u_long red, green, blue, gray; DBG( _DBG_INFO, "cano_AdjustDarkShading()\n" ); if( usb_IsEscPressed()) return SANE_FALSE; usb_PrepareFineCal( dev, &m_ScanParam, cal_dpi ); m_ScanParam.bCalibration = PARAM_DarkShading; sprintf( tmp, "fine-dark.raw" ); dumpPicInit(&m_ScanParam, tmp); usb_SetScanParameters( dev, &m_ScanParam ); if( usb_ScanBegin( dev, SANE_FALSE ) && usb_ScanReadImage( dev, scanbuf, m_ScanParam.Size.dwTotalBytes)) { dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwTotalBytes, 0); if(usb_HostSwap()) usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwTotalBytes); } if (!usb_ScanEnd( dev )){ DBG( _DBG_ERROR, "cano_AdjustDarkShading() failed\n" ); return SANE_FALSE; } /* average the n lines, compute reg values */ if( scan->sParam.bDataType == SCANDATATYPE_Color ) { stepW = m_ScanParam.Size.dwPhyPixels; if( usb_IsCISDevice(dev)) step = m_ScanParam.Size.dwPhyPixels + 1; else step = (m_ScanParam.Size.dwPhyPixels*3) + 1; for( i=0; iswOffset[0]); if( val < 0 ) { DBG( _DBG_INFO, "val < 0!!!!\n" ); val = 0; } a_wDarkShading[i] = (u_short)val; val = ((int)(green/m_ScanParam.Size.dwPhyLines) + param->swOffset[1]); if( val < 0 ) { DBG( _DBG_INFO, "val < 0!!!!\n" ); val = 0; } a_wDarkShading[i+stepW] = (u_short)val; val = ((int)(blue/m_ScanParam.Size.dwPhyLines) + param->swOffset[2]); if( val < 0 ) { DBG( _DBG_INFO, "val < 0!!!!\n" ); val = 0; } a_wDarkShading[i+stepW*2] = (u_short)val; } } else { step = m_ScanParam.Size.dwPhyPixels + 1; for( i=0; iswOffset[0]; } memcpy( a_wDarkShading + m_ScanParam.Size.dwPhyPixels, a_wDarkShading, m_ScanParam.Size.dwPhyPixels * 2); memcpy( a_wDarkShading + m_ScanParam.Size.dwPhyPixels * 2, a_wDarkShading, m_ScanParam.Size.dwPhyPixels * 2); } if(usb_HostSwap()) usb_Swap(a_wDarkShading, m_ScanParam.Size.dwPhyPixels * 2 * 3); usb_line_statistics( "Dark", a_wDarkShading, m_ScanParam.Size.dwPhyPixels, scan->sParam.bDataType == SCANDATATYPE_Color?1:0); DBG( _DBG_INFO, "cano_AdjustDarkShading() done\n" ); return SANE_TRUE; } /** usb_AdjustWhiteShading * fine calibration part 2 - read the white calibration area and calculate * the gain coefficient for each pixel */ static SANE_Bool cano_AdjustWhiteShading( Plustek_Device *dev, u_short cal_dpi ) { char tmp[40]; ScanParam *param = &dev->scanning.sParam; ScanDef *scan = &dev->scanning; u_long *scanbuf = scan->pScanBuffer; u_short *bufp; unsigned int i, j; int step, stepW; u_long red, green, blue, gray; DBG( _DBG_INFO, "cano_AdjustWhiteShading()\n" ); if( usb_IsEscPressed()) return SANE_FALSE; usb_PrepareFineCal( dev, &m_ScanParam, cal_dpi ); m_ScanParam.bCalibration = PARAM_WhiteShading; sprintf( tmp, "fine-white.raw" ); DBG( _DBG_INFO2, "FINE WHITE Calibration Strip: %s\n", tmp ); DBG( _DBG_INFO2, "Lines = %lu\n", m_ScanParam.Size.dwLines ); DBG( _DBG_INFO2, "Pixels = %lu\n", m_ScanParam.Size.dwPixels ); DBG( _DBG_INFO2, "Bytes = %lu\n", m_ScanParam.Size.dwBytes ); DBG( _DBG_INFO2, "Origin.X = %u\n", m_ScanParam.Origin.x ); dumpPicInit(&m_ScanParam, tmp); if( usb_SetScanParameters( dev, &m_ScanParam ) && usb_ScanBegin( dev, SANE_FALSE ) && usb_ScanReadImage( dev, scanbuf, m_ScanParam.Size.dwTotalBytes)) { dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwTotalBytes, 0); if(usb_HostSwap()) usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwTotalBytes); if (!usb_ScanEnd( dev )) { DBG( _DBG_ERROR, "cano_AdjustWhiteShading() failed\n" ); return SANE_FALSE; } } else { DBG( _DBG_ERROR, "cano_AdjustWhiteShading() failed\n" ); return SANE_FALSE; } /* average the n lines, compute reg values */ if( scan->sParam.bDataType == SCANDATATYPE_Color ) { stepW = m_ScanParam.Size.dwPhyPixels; if( usb_IsCISDevice(dev)) step = m_ScanParam.Size.dwPhyPixels + 1; else step = (m_ScanParam.Size.dwPhyPixels*3) + 1; for( i=0; i < m_ScanParam.Size.dwPhyPixels; i++ ) { red = 0; green = 0; blue = 0; if( usb_IsCISDevice(dev)) bufp = ((u_short *)scanbuf)+i; else bufp = ((u_short *)scanbuf)+(i*3); for( j=0; j 1000/swGain[r,g,b] */ red = (65535.*1000./(double)param->swGain[0]) * 16384.*j/red; green = (65535.*1000./(double)param->swGain[1]) * 16384.*j/green; blue = (65535.*1000./(double)param->swGain[2]) * 16384.*j/blue; a_wWhiteShading[i] = (red > 65535 ? 65535:red ); a_wWhiteShading[i+stepW] = (green > 65535 ? 65535:green); a_wWhiteShading[i+stepW*2] = (blue > 65535 ? 65535:blue ); } } else { step = m_ScanParam.Size.dwPhyPixels + 1; for( i=0; iswGain[0]) * 16384.*j/gray; a_wWhiteShading[i]= (gray > 65535 ? 65535:gray); } memcpy( a_wWhiteShading + m_ScanParam.Size.dwPhyPixels, a_wWhiteShading, m_ScanParam.Size.dwPhyPixels * 2); memcpy( a_wWhiteShading + m_ScanParam.Size.dwPhyPixels * 2, a_wWhiteShading, m_ScanParam.Size.dwPhyPixels * 2); } if(usb_HostSwap()) usb_Swap(a_wWhiteShading, m_ScanParam.Size.dwPhyPixels * 2 * 3 ); usb_SaveCalSetShading( dev, &m_ScanParam ); usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels, scan->sParam.bDataType == SCANDATATYPE_Color?1:0); DBG( _DBG_INFO, "cano_AdjustWhiteShading() done\n" ); return SANE_TRUE; } /** the entry function for the CIS calibration stuff. */ static int cano_DoCalibration( Plustek_Device *dev ) { u_short dpi, idx, idx_end; u_long save_waf; SANE_Bool skip_fine; ScanDef *scan = &dev->scanning; HWDef *hw = &dev->usbDev.HwSetting; DCapsDef *scaps = &dev->usbDev.Caps; if( SANE_TRUE == scan->fCalibrated ) return SANE_TRUE; DBG( _DBG_INFO, "cano_DoCalibration()\n" ); if( _IS_PLUSTEKMOTOR(hw->motorModel)){ DBG( _DBG_ERROR, "altCalibration can't work with this " "Plustek motor control setup\n" ); return SANE_FALSE; /* can't cal this */ } /* Don't allow calibration settings from the other driver to confuse our * use of a few of its functions. */ save_waf = scaps->workaroundFlag; scaps->workaroundFlag &= ~_WAF_SKIP_WHITEFINE; scaps->workaroundFlag &= ~_WAF_SKIP_FINE; scaps->workaroundFlag &= ~_WAF_BYPASS_CALIBRATION; if( !dev->adj.cacheCalData && !usb_IsSheetFedDevice(dev)) usb_SpeedTest( dev ); /* here we handle that warmup stuff for CCD devices */ if( !usb_AutoWarmup( dev )) return SANE_FALSE; /* Set the shading position to undefined */ strip_state = 0; usb_PrepareCalibration( dev ); usb_SetMCLK( dev, &scan->sParam ); if( !scan->skipCoarseCalib ) { if( !usb_Wait4ScanSample( dev )) return SANE_FALSE; DBG( _DBG_INFO2, "###### ADJUST LAMP (COARSE)#######\n" ); if( cano_PrepareToReadWhiteCal(dev, SANE_TRUE)) return SANE_FALSE; dev->usbDev.a_bRegs[0x45] &= ~0x10; if( !cano_AdjustLightsource(dev)) { DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" ); return SANE_FALSE; } DBG( _DBG_INFO2, "###### ADJUST OFFSET (COARSE) ####\n" ); if(cano_PrepareToReadBlackCal(dev)) return SANE_FALSE; if( !cano_AdjustOffset(dev)) { DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" ); return SANE_FALSE; } DBG( _DBG_INFO2, "###### ADJUST GAIN (COARSE)#######\n" ); if(cano_PrepareToReadWhiteCal(dev, SANE_FALSE)) return SANE_FALSE; if( !cano_AdjustGain(dev)) { DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" ); return SANE_FALSE; } } else { strip_state = 1; DBG( _DBG_INFO2, "###### COARSE calibration skipped #######\n" ); } skip_fine = SANE_FALSE; idx_end = 2; if( dev->adj.cacheCalData || usb_IsSheetFedDevice(dev)) { skip_fine = usb_FineShadingFromFile(dev); /* we recalibrate in any case ! */ if( usb_InCalibrationMode(dev)) { skip_fine = SANE_FALSE; idx_end = DIVIDER+1; /* did I say any case? */ if (scan->sParam.bBitDepth != 8) { skip_fine = SANE_TRUE; DBG( _DBG_INFO2, "No fine calibration for non-8bit modes!\n" ); } } else if( usb_IsSheetFedDevice(dev)) { /* we only do the calibration upon request !*/ if( !skip_fine ) { DBG( _DBG_INFO2, "SHEET-FED device, skip fine calibration!\n" ); skip_fine = SANE_TRUE; scaps->workaroundFlag |= _WAF_BYPASS_CALIBRATION; } } } if( !skip_fine ) { for( idx = 1; idx < idx_end; idx++ ) { dpi = 0; if( usb_InCalibrationMode(dev)) { dpi = usb_get_res( scaps->OpticDpi.x, idx ); /* we might should check against device specific limit */ if(dpi < 50) continue; } DBG( _DBG_INFO2, "###### ADJUST DARK (FINE) ########\n" ); if(cano_PrepareToReadBlackCal(dev)) return SANE_FALSE; dev->usbDev.a_bRegs[0x45] |= 0x10; if( !cano_AdjustDarkShading(dev, dpi)) { DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" ); return SANE_FALSE; } DBG( _DBG_INFO2, "###### ADJUST WHITE (FINE) #######\n" ); if(cano_PrepareToReadWhiteCal(dev, SANE_FALSE)) return SANE_FALSE; if( !usb_IsSheetFedDevice(dev)) { if(!usb_ModuleToHome( dev, SANE_TRUE )) return SANE_FALSE; if( !usb_ModuleMove(dev, MOVE_Forward, (u_long)dev->usbDev.pSource->ShadingOriginY)) { return SANE_FALSE; } } if( !cano_AdjustWhiteShading(dev, dpi)) { DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" ); return SANE_FALSE; } /* force to go back */ strip_state = 0; } } else { DBG( _DBG_INFO2, "###### FINE calibration skipped #######\n" ); dev->usbDev.a_bRegs[0x45] |= 0x10; strip_state = 2; m_ScanParam = scan->sParam; usb_GetPhyPixels( dev, &m_ScanParam ); usb_line_statistics( "Dark", a_wDarkShading, m_ScanParam.Size.dwPhyPixels, m_ScanParam.bDataType == SCANDATATYPE_Color?1:0); usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels, m_ScanParam.bDataType == SCANDATATYPE_Color?1:0); } /* Lamp on if it's not */ cano_LampOnAfterCalibration(dev); strip_state = 0; /* home the sensor after calibration */ if( !usb_IsSheetFedDevice(dev)) usb_ModuleToHome( dev, SANE_TRUE ); scan->fCalibrated = SANE_TRUE; DBG( _DBG_INFO, "cano_DoCalibration() done\n" ); DBG( _DBG_INFO, "-------------------------\n" ); DBG( _DBG_INFO, "Static Gain:\n" ); DBG( _DBG_INFO, "REG[0x3b] = %u\n", dev->usbDev.a_bRegs[0x3b] ); DBG( _DBG_INFO, "REG[0x3c] = %u\n", dev->usbDev.a_bRegs[0x3c] ); DBG( _DBG_INFO, "REG[0x3d] = %u\n", dev->usbDev.a_bRegs[0x3d] ); DBG( _DBG_INFO, "Static Offset:\n" ); DBG( _DBG_INFO, "REG[0x38] = %i\n", dev->usbDev.a_bRegs[0x38] ); DBG( _DBG_INFO, "REG[0x39] = %i\n", dev->usbDev.a_bRegs[0x39] ); DBG( _DBG_INFO, "REG[0x3a] = %i\n", dev->usbDev.a_bRegs[0x3a] ); DBG( _DBG_INFO, "-------------------------\n" ); scaps->workaroundFlag |= save_waf; return SANE_TRUE; } /* END PLUSTEK-USBCAL.C .....................................................*/ sane-backends-1.0.27/backend/umax_pp_low.c0000664000175000017500000111273513106201017015310 00000000000000/** Copyright (C) 2001-2012 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Umax PP flatbed scanners. */ #undef BACKEND_NAME #define BACKEND_NAME umax_pp_low #include "../include/sane/config.h" #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_IO_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include #ifdef HAVE_DEV_PPBUS_PPI_H #include #include #endif #ifdef HAVE_MACHINE_CPUFUNC_H #include #endif #ifdef HAVE_I386_SET_IOPERM #include #endif #ifdef HAVE_LINUX_PPDEV_H #include #include #include #endif /*************************************************/ /* here we define sanei_inb/sanei_outb based on */ /* OS dependant inb/outb definitions */ /* SANE_INB is defined whenever a valid inb/outb */ /* definition has been found */ /* once all these work, it might be moved to */ /* sanei_pio.c */ /*************************************************/ #ifdef ENABLE_PARPORT_DIRECTIO #if (! defined SANE_INB ) && ( defined HAVE_SYS_HW_H ) /* OS/2 EMX case */ #define SANE_INB 1 static int sanei_ioperm (int start, int length, int enable) { if (enable) return _portaccess (port, port + length - 1); return 0; } static unsigned char sanei_inb (unsigned int port) { return _inp8 (port) & 0xFF; } static void sanei_outb (unsigned int port, unsigned char value) { _outp8 (port, value); } static void sanei_insb (unsigned int port, unsigned char *addr, unsigned long count) { _inps8 (port, (unsigned char *) addr, count); } static void sanei_insl (unsigned int port, unsigned char *addr, unsigned long count) { _inps32 (port, (unsigned long *) addr, count); } static void sanei_outsb (unsigned int port, const unsigned char *addr, unsigned long count) { _outps8 (port, (unsigned char *) addr, count); } static void sanei_outsl (unsigned int port, const unsigned char *addr, unsigned long count) { _outps32 (port, (unsigned long *) addr, count); } #endif /* OS/2 EMX case */ #if (! defined SANE_INB ) && ( defined HAVE_MACHINE_CPUFUNC_H ) /* FreeBSD case */ #define SANE_INB 2 static int sanei_ioperm (int start, int length, int enable) { #ifdef HAVE_I386_SET_IOPERM return i386_set_ioperm (start, length, enable); #else int fd = 0; /* makes compilers happy */ start = length + enable; fd = open ("/dev/io", O_RDONLY); if (fd > 0) return 0; return -1; #endif } static unsigned char sanei_inb (unsigned int port) { return inb (port); } static void sanei_outb (unsigned int port, unsigned char value) { outb (port, value); } static void sanei_insb (unsigned int port, unsigned char *addr, unsigned long count) { insb (port, addr, count); } static void sanei_insl (unsigned int port, unsigned char *addr, unsigned long count) { insl (port, addr, count); } static void sanei_outsb (unsigned int port, const unsigned char *addr, unsigned long count) { outsb (port, addr, count); } static void sanei_outsl (unsigned int port, const unsigned char *addr, unsigned long count) { outsl (port, addr, count); } #endif /* FreeBSD case */ /* linux GCC on i386 */ #if ( ! defined SANE_INB ) && ( defined HAVE_SYS_IO_H ) && ( defined __GNUC__ ) && ( defined __i386__ ) #define SANE_INB 3 static int sanei_ioperm (int start, int length, int enable) { #ifdef HAVE_IOPERM return ioperm (start, length, enable); #else /* linux without ioperm ? hum ... */ /* makes compilers happy */ start = length + enable; return 0; #endif } static unsigned char sanei_inb (unsigned int port) { return inb (port); } static void sanei_outb (unsigned int port, unsigned char value) { outb (value, port); } static void sanei_insb (unsigned int port, unsigned char *addr, unsigned long count) { insb (port, addr, count); } static void sanei_insl (unsigned int port, unsigned char *addr, unsigned long count) { insl (port, addr, count); } static void sanei_outsb (unsigned int port, const unsigned char *addr, unsigned long count) { outsb (port, addr, count); } static void sanei_outsl (unsigned int port, const unsigned char *addr, unsigned long count) { /* oddly, 32 bit I/O are done with outsw instead of the expected outsl */ outsw (port, addr, count); } #endif /* linux GCC on i386 */ /* linux GCC non i386 */ #if ( ! defined SANE_INB ) && ( defined HAVE_SYS_IO_H ) && ( defined __GNUC__ ) && ( ! defined __i386__ ) #define SANE_INB 4 static int sanei_ioperm (int start, int length, int enable) { #ifdef HAVE_IOPERM return ioperm (start, length, enable); #else /* linux without ioperm ? hum ... */ /* makes compilers happy */ start = length + enable; return 0; #endif } static unsigned char sanei_inb (unsigned int port) { return inb (port); } static void sanei_outb (unsigned int port, unsigned char value) { outb (value, port); } static void sanei_insb (unsigned int port, unsigned char *addr, unsigned long count) { int i; for (i = 0; i < count; i++) addr[i] = sanei_inb (port); } static void sanei_insl (unsigned int port, unsigned char *addr, unsigned long count) { int i; for (i = 0; i < count * 4; i++) addr[i] = sanei_inb (port); } static void sanei_outsb (unsigned int port, const unsigned char *addr, unsigned long count) { int i; for (i = 0; i < count; i++) sanei_outb (port, addr[i]); } static void sanei_outsl (unsigned int port, const unsigned char *addr, unsigned long count) { int i; for (i = 0; i < count * 4; i++) sanei_outb (port, addr[i]); } #endif /* linux GCC non i386 */ /* ICC on i386 */ #if ( ! defined SANE_INB ) && ( defined __INTEL_COMPILER ) && ( defined __i386__ ) #define SANE_INB 5 static int sanei_ioperm (int start, int length, int enable) { #ifdef HAVE_IOPERM return ioperm (start, length, enable); #else /* ICC without ioperm() ... */ /* makes compilers happy */ start = length + enable; return 0; #endif } static unsigned char sanei_inb (unsigned int port) { unsigned char ret; __asm__ __volatile__ ("inb %%dx,%%al":"=a" (ret):"d" ((u_int) port)); return ret; } static void sanei_outb (unsigned int port, unsigned char value) { __asm__ __volatile__ ("outb %%al,%%dx"::"a" (value), "d" ((u_int) port)); } static void sanei_insb (unsigned int port, void *addr, unsigned long count) { __asm__ __volatile__ ("rep ; insb":"=D" (addr), "=c" (count):"d" (port), "0" (addr), "1" (count)); } static void sanei_insl (unsigned int port, void *addr, unsigned long count) { __asm__ __volatile__ ("rep ; insl":"=D" (addr), "=c" (count):"d" (port), "0" (addr), "1" (count)); } static void sanei_outsb (unsigned int port, const void *addr, unsigned long count) { __asm__ __volatile__ ("rep ; outsb":"=S" (addr), "=c" (count):"d" (port), "0" (addr), "1" (count)); } static void sanei_outsl (unsigned int port, const void *addr, unsigned long count) { __asm__ __volatile__ ("rep ; outsl":"=S" (addr), "=c" (count):"d" (port), "0" (addr), "1" (count)); } #endif /* ICC on i386 */ /* direct io requested, but no valid inb/oub */ #if ( ! defined SANE_INB) && ( defined ENABLE_PARPORT_DIRECTIO ) #warning "ENABLE_PARPORT_DIRECTIO cannot be used du to lack of inb/out definition" #undef ENABLE_PARPORT_DIRECTIO #endif #endif /* ENABLE_PARPORT_DIRECTIO */ /* * no inb/outb without --enable-parport-directio * */ #ifndef ENABLE_PARPORT_DIRECTIO #define SANE_INB 0 static int sanei_ioperm (__sane_unused__ int start, __sane_unused__ int length, __sane_unused__ int enable) { /* returns failure */ return -1; } static unsigned char sanei_inb (__sane_unused__ unsigned int port) { return 255; } static void sanei_outb (__sane_unused__ unsigned int port, __sane_unused__ unsigned char value) { } static void sanei_insb (__sane_unused__ unsigned int port, __sane_unused__ unsigned char *addr, __sane_unused__ unsigned long count) { } static void sanei_insl (__sane_unused__ unsigned int port, __sane_unused__ unsigned char *addr, __sane_unused__ unsigned long count) { } static void sanei_outsb (__sane_unused__ unsigned int port, __sane_unused__ const unsigned char *addr, __sane_unused__ unsigned long count) { } static void sanei_outsl (__sane_unused__ unsigned int port, __sane_unused__ const unsigned char *addr, __sane_unused__ unsigned long count) { } #endif /* ENABLE_PARPORT_DIRECTIO is not defined */ /* we need either direct io or ppdev */ #if ! defined ENABLE_PARPORT_DIRECTIO && ! defined HAVE_LINUX_PPDEV_H && ! defined HAVE_DEV_PPBUS_PPI_H #define IO_SUPPORT_MISSING #endif #include "umax_pp_low.h" #ifdef DMALLOC #include "dmalloc.h" #endif #ifndef __IO__ #define __IO__ #define DATA gPort+0x00 #define STATUS gPort+0x01 #define CONTROL gPort+0x02 #define EPPADDR gPort+0x03 #define EPPDATA gPort+0x04 #define ECPDATA gPort+0x400 #define ECR gPort+0x402 #define FIFO_WAIT 1000 #endif static int fonc001 (void); static int foncSendWord (int *cmd); static void setEPPMode (int mode); static int getEPPMode (void); static void setModel (int model); static int getModel (void); static int ringScanner (int count, unsigned long delay); static int testVersion (int no); static int probePS2 (unsigned char *dest); static int probeEPP (unsigned char *dest); static int probeECP (unsigned char *dest); static int sendCommand (int cmd); static void SPPResetLPT (void); static int sendWord (int *cmd); static int sendData (int *cmd, int len); static int receiveData (int *cmd, int len); static int sendLength (int *cmd, int len); static int waitAck (void); static void init001 (void); static int init002 (int arg); static int init005 (int arg); /* 610p comm functions */ static int putByte610p (int data); static int EPPputByte610p (int data); static int sendLength610p (int *cmd); static int sendData610p (int *cmd, int len); static int receiveData610p (int *cmd, int len); static int connect610p (void); static int sync610p (void); static int cmdSync610p (int cmd); static int EPPcmdSync610p (int cmd); static int getStatus610p (void); static int EPPgetStatus610p (void); static int disconnect610p (void); static int EPPsendWord610p (int *cmd); static int SPPsendWord610p (int *cmd); static int cmdSet610p (int cmd, int len, int *buffer); static int cmdGet610p (int cmd, int len, int *buffer); static int EPPcmdSet610p (int cmd, int len, int *buffer); static int EPPcmdGet610p (int cmd, int len, int *buffer); static int initScanner610p (int recover); static int cmdGetBuffer610p (int cmd, int len, unsigned char *buffer); /* parport mode setting */ static void compatMode (void); static void byteMode (void); static void ECPFifoMode (void); /* block transfer init */ static void ECPSetBuffer (int size); /* mode dependant operations */ static int PS2Something (int reg); static void PS2bufferRead (int size, unsigned char *dest); static void PS2bufferWrite (int size, unsigned char *source); static int PS2registerRead (int reg); static void PS2registerWrite (int reg, int value); static int EPPconnect (void); static int EPPregisterRead (int reg); static void EPPregisterWrite (int reg, int value); static void EPPbufferRead (int size, unsigned char *dest); static void EPPbufferWrite (int size, unsigned char *source); static void EPPRead32Buffer (int size, unsigned char *dest); static void EPPWrite32Buffer (int size, unsigned char *source); static int ECPconnect (void); static void ECPdisconnect (void); static int ECPregisterRead (int reg); static void ECPregisterWrite (int reg, int value); static int ECPbufferRead (int size, unsigned char *dest); static void ECPbufferWrite (int size, unsigned char *source); static int waitFifoEmpty (void); static int waitFifoNotEmpty (void); static int waitFifoFull (void); /* generic operations */ static int connect (void); static void disconnect (void); static void bufferRead (int size, unsigned char *dest); static void bufferWrite (int size, unsigned char *source); static int pausedBufferRead (int size, unsigned char *dest); static void ClearRegister (int reg); static int connect_epat (int r08); static int prologue (int r08); static int epilogue (void); static int cmdSet (int cmd, int len, int *buffer); static int cmdGet (int cmd, int len, int *buffer); static int cmdSetGet (int cmd, int len, int *buffer); static int cmdGetBuffer (int cmd, int len, unsigned char *buffer); static int cmdGetBuffer32 (int cmd, int len, unsigned char *buffer); static int cmdGetBlockBuffer (int cmd, int len, int window, unsigned char *buffer); static void bloc2Decode (int *op); static void bloc8Decode (int *op); /* * high level operations */ static int loadDefaultTables (void); static int inquire (void); static int offsetCalibration (int color, int *offRed, int *offGreen, int *offBlue); static int coarseGainCalibration (int color, int dcRed, int dcGreen, int dcBlue, int *vgaRed, int *vgaGreen, int *vgaBlue); static int shadingCalibration (int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration); static int leftShadingCalibration610p (int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration); #define WRITESLOW(x,y) \ PS2registerWrite((x),(y)); \ DBG(16,"PS2registerWrite(0x%X,0x%X) passed... (%s:%d)\n",(x),(y),__FILE__,__LINE__); #define SLOWNIBBLEREGISTERREAD(x,y) \ tmp=PS2registerRead(x);\ if(tmp!=y)\ {\ DBG(0,"PS2registerRead: found 0x%X expected 0x%X (%s:%d)\n",tmp,y,__FILE__,__LINE__);\ /*return 0;*/ \ }\ DBG(16,"PS2registerRead(0x%X)=0x%X passed... (%s:%d)\n",x,y,__FILE__,__LINE__); #define REGISTERWRITE(x,y) \ registerWrite((x),(y)); \ DBG(16,"registerWrite(0x%X,0x%X) passed... (%s:%d)\n",(x),(y),__FILE__,__LINE__); #define REGISTERREAD(x,y) \ tmp=registerRead(x);\ if(tmp!=y)\ {\ DBG(0,"registerRead, found 0x%X expected 0x%X (%s:%d)\n",tmp,y,__FILE__,__LINE__);\ return 0;\ }\ DBG(16,"registerRead(0x%X)=0x%X passed... (%s:%d)\n",x,y,__FILE__,__LINE__); #define TRACE(level,msg) DBG(level, msg" (%s:%d)\n",__FILE__,__LINE__); #define CMDSYNC(x) if(sanei_umax_pp_cmdSync(x)!=1)\ {\ DBG(0,"cmdSync(0x%02X) failed (%s:%d)\n",x,__FILE__,__LINE__);\ return 0;\ }\ DBG(16,"cmdSync(0x%02X)=%02X passed ... (%s:%d)\n",x,sanei_umax_pp_scannerStatus(),__FILE__,__LINE__) #define CMDSETGET(cmd,len,sent) if(cmdSetGet(cmd,len,sent)!=1)\ {\ DBG(0,"cmdSetGet(0x%02X,%d,sent) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\ return 0;\ }\ TRACE(16,"cmdSetGet() passed ...") #define YOFFSET 40 #define YOFFSET1220P 40 #define YOFFSET2000P 40 #define COMPLETIONWAIT if(completionWait()==0)\ {\ DBG(0,"completionWait() failed (%s:%d)\n",__FILE__,__LINE__);\ return 0;\ }\ TRACE(16,"completionWait() passed ...") #define MOVE(x,y,t) if(move(x,y,t)==0)\ {\ DBG(0,"move(%d,%d,buffer) failed (%s:%d)\n",x,y,__FILE__,__LINE__);\ return 0;\ }\ TRACE(16,"move() passed ...") #define CMDGETBUF(cmd,len,sent) if(cmdGetBuffer(cmd,len,sent)!=1)\ {\ DBG(0,"cmdGetBuffer(0x%02X,%ld,buffer) failed (%s:%d)\n",cmd,(long)len,__FILE__,__LINE__);\ return 0;\ }\ DBG(16,"cmdGetBuffer(%ld) passed ... (%s:%d)\n",(long)len,__FILE__,__LINE__); #define CMDGETBUF32(cmd,len,sent) if(cmdGetBuffer32(cmd,len,sent)!=1)\ {\ DBG(0,"cmdGetBuffer32(0x%02X,%ld,buffer) failed (%s:%d)\n",cmd,(long)len,__FILE__,__LINE__);\ return 0;\ }\ TRACE(16,"cmdGetBuffer32() passed ...") #define CMDSET(cmd,len,sent) if(cmdSet(cmd,len,sent)!=1)\ {\ DBG(0,"cmdSet(0x%02X,%d,sent) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\ return 0;\ }\ TRACE(16,"cmdSet() passed ...") #define CMDGET(cmd,len,sent) if(cmdGet(cmd,len,sent)!=1)\ {\ DBG(0,"cmdGet(0x%02X,%d,read) failed (%s:%d)\n",cmd,len,__FILE__,__LINE__);\ return 0;\ }\ TRACE(16,"cmdGet() passed ...") static int gPort = 0x378; static float targetCode = 250.0; /* global control vars */ static int gControl = 0; static int gData = 0; static int g674 = 0; /* semble indiquer qu'on utilise les IRQ */ static int g67D = 0; static int g67E = 0; static int gEPAT = 0; /* signals fast mode ? */ static int g6FE = 0; static int gECP = 0; static int gLeft = 144; /* default value for 1220P */ /* default gamma translation table */ static int ggamma[256] = { 0x00, 0x06, 0x0A, 0x0D, 0x10, 0x12, 0x14, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, 0x24, 0x26, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x30, 0x31, 0x33, 0x34, 0x36, 0x37, 0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x40, 0x41, 0x42, 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB8, 0xB9, 0xBA, 0xBB, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC8, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCD, 0xCE, 0xCE, 0xCF, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6, 0xD6, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE1, 0xE1, 0xE2, 0xE3, 0xE3, 0xE4, 0xE5, 0xE6, 0xE6, 0xE7, 0xE8, 0xE8, 0xE9, 0xEA, 0xEA, 0xEB, 0xEC, 0xEC, 0xED, 0xEE, 0xEF, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2, 0xF3, 0xF3, 0xF4, 0xF5, 0xF5, 0xF6, 0xF7, 0xF7, 0xF8, 0xF9, 0xF9, 0xFA, 0xFB, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFF }; /* default gamma translation table */ static int *ggGreen = ggamma; static int *ggBlue = ggamma; static int *ggRed = ggamma; static int gParport = 0; static int gCancel = 0; static int gAutoSettings = 1; /*****************************************************************************/ /* output one byte on given port */ /*****************************************************************************/ static void Outb (int port, int value); /*****************************************************************************/ /* ouput 'size' bytes stored in 'source' on given port */ /*****************************************************************************/ static void Outsb (int port, unsigned char *source, int size); /*****************************************************************************/ /* ouput 'size' 32 bits words stored in 'source' on given port */ /*****************************************************************************/ static void Outsw (int port, unsigned char *source, int size); /*****************************************************************************/ /* input one byte from given port */ /*****************************************************************************/ static int Inb (int port); /*****************************************************************************/ /* input 'size' bytes from given port ans store them in 'dest' */ /*****************************************************************************/ static void Insb (int port, unsigned char *dest, int size); /*****************************************************************************/ /* input 'size' 32 bits word from given port ans store them in 'dest' */ /*****************************************************************************/ static void Insw (int port, unsigned char *dest, int size); char ** sanei_parport_find_port (void) { char **ports = NULL; #ifdef ENABLE_PARPORT_DIRECTIO int i, addr, ecpaddr; int found = 0; char name[80], buffer[80]; FILE *fic = NULL; /* direct I/O detection */ /* linux 2.4 + 2.6 with proc support */ for (i = 0; i < 4; i++) { /* try to ensure loading of lp module */ sprintf (name, "/dev/lp%d", i); fic = fopen (name, "wb"); if (fic != NULL) fclose (fic); sprintf (name, "/proc/sys/dev/parport/parport%d/base-addr", i); fic = fopen (name, "rb"); if (fic != NULL) { fread (buffer, 64, 1, fic); fclose (fic); if (sscanf (buffer, "%d %d", &addr, &ecpaddr) > 0) { DBG (16, "parport at 0x%X\n", addr); ports = (char **) realloc (ports, (found + 2) * sizeof (char *)); ports[found] = (char *) malloc (19); sprintf (ports[found], "0x%X", addr); found++; ports[found] = NULL; } } } #endif return ports; } char ** sanei_parport_find_device (void) { char *devices[] = { /* FreeBSD */ "/dev/ppi0", "/dev/ppi1", "/dev/ppi2", "/dev/ppi3", /* linux ppdev with devfs */ "/dev/parports/0", "/dev/parports/1", "/dev/parports/2", "/dev/parports/3", /* linux ppdev */ "/dev/parport0", "/dev/parport1", "/dev/parport2", "/dev/parport3", NULL }; int i, file; int rc = 0; int found = 0; char **ports = NULL; /* device finding */ i = 0; while (devices[i] != NULL) { DBG (16, "Controlling %s: ", devices[i]); file = open (devices[i], O_RDWR); if (file < 0) { switch (errno) { case ENOENT: #ifdef ENIO case ENXIO: #endif #ifdef ENODEV case ENODEV: #endif DBG (16, "no %s device ...\n", devices[i]); break; case EACCES: DBG (16, "current user cannot use existing %s device ...\n", devices[i]); break; default: perror (devices[i]); } } else { #ifdef HAVE_LINUX_PPDEV_H /* on kernel < 2.4.23, you have to CLAIM the device * to check it really exists * we may hang if another program already claimed it */ rc = ioctl (file, PPCLAIM); if (rc) { switch (errno) { case ENOENT: #ifdef ENXIO case ENXIO: #endif #ifdef ENODEV case ENODEV: #endif DBG (16, "no %s device ...\n", devices[i]); break; case EACCES: DBG (16, "current user cannot use existing %s device ...\n", devices[i]); break; default: DBG (16, "errno=%d\n", errno); perror (devices[i]); } } else { rc = ioctl (file, PPRELEASE); } #endif /* HAVE_LINUX_PPDEV_H */ close (file); if (!rc) { DBG (16, "adding %s to valid devices ...\n", devices[i]); ports = (char **) realloc (ports, (found + 2) * sizeof (char *)); ports[found] = strdup (devices[i]); found++; ports[found] = NULL; } } /* suite */ i++; } return ports; } /* * gain direct acces to IO port, and set parport to the 'right' mode * returns 1 on success, 0 an failure */ int sanei_umax_pp_initPort (int port, char *name) { int fd, ectr; int found = 0; #if ((defined HAVE_IOPERM)||(defined HAVE_MACHINE_CPUFUNC_H)||(defined HAVE_LINUX_PPDEV_H)) int mode, modes, rc; #endif #ifdef HAVE_LINUX_PPDEV_H char strmodes[160]; #endif /* since this function must be called before */ /* any other, we put debug init here */ DBG_INIT (); DBG (1, "SANE_INB level %d\n", SANE_INB); /* sets global vars */ ggGreen = ggamma; ggBlue = ggamma; ggRed = ggamma; gParport = 0; gCancel = 0; gAutoSettings = 1; gControl = 0; gData = 0; g674 = 0; g67D = 0; g67E = 0; gEPAT = 0; g6FE = 0; sanei_umax_pp_setparport (0); DBG (1, "sanei_umax_pp_InitPort(0x%X,%s)\n", port, name); #ifndef ENABLE_PARPORT_DIRECTIO if ((name == NULL) || ((name != NULL) && (strlen (name) < 4))) { DBG (0, "sanei_umax_pp_InitPort cannot use direct hardware access\n"); DBG (0, "if not compiled with --enable-parport-directio\n"); return 0; } #endif /* init global var holding port value */ gPort = port; #ifdef IO_SUPPORT_MISSING DBG (1, "*** Direct I/O or ppdev unavailable, giving up ***\n"); return 0; #else #ifdef HAVE_LINUX_PPDEV_H if (name != NULL) { if (strlen (name) > 3) { /* ppdev opening and configuration */ found = 0; fd = open (name, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) { switch (errno) { case ENOENT: DBG (1, "umax_pp: '%s' does not exist \n", name); break; case EACCES: DBG (1, "umax_pp: current user has not R/W permissions on '%s' \n", name); break; } return 0; } /* claim port */ if (ioctl (fd, PPCLAIM)) { DBG (1, "umax_pp: cannot claim port '%s'\n", name); } else { /* we check if parport does EPP or ECP */ #ifdef PPGETMODES if (ioctl (fd, PPGETMODES, &modes)) { DBG (16, "umax_pp: ppdev couldn't gave modes for port '%s'\n", name); } else { sprintf (strmodes, "\n"); if (modes & PARPORT_MODE_PCSPP) sprintf (strmodes, "%s\t\tPARPORT_MODE_PCSPP\n", strmodes); if (modes & PARPORT_MODE_TRISTATE) sprintf (strmodes, "%s\t\tPARPORT_MODE_TRISTATE\n", strmodes); if (modes & PARPORT_MODE_EPP) sprintf (strmodes, "%s\t\tPARPORT_MODE_EPP\n", strmodes); if (modes & PARPORT_MODE_ECP) { sprintf (strmodes, "%s\t\tPARPORT_MODE_ECP\n", strmodes); gECP = 1; } if (modes & PARPORT_MODE_COMPAT) sprintf (strmodes, "%s\t\tPARPORT_MODE_COMPAT\n", strmodes); if (modes & PARPORT_MODE_DMA) sprintf (strmodes, "%s\t\tPARPORT_MODE_DMA\n", strmodes); DBG (32, "parport modes: %X\n", modes); DBG (32, "parport modes: %s\n", strmodes); if (!(modes & PARPORT_MODE_EPP) && !(modes & PARPORT_MODE_ECP)) { DBG (1, "port 0x%X does not have EPP or ECP, giving up ...\n", port); mode = IEEE1284_MODE_COMPAT; ioctl (fd, PPSETMODE, &mode); ioctl (fd, PPRELEASE); close (fd); return 0; } } #else DBG (16, "umax_pp: ppdev used to build SANE doesn't have PPGETMODES.\n"); /* faking result */ modes = 0xFFFFFFFF; #endif mode = 0; /* prefered mode is EPP */ if (modes & PARPORT_MODE_EPP) { mode = IEEE1284_MODE_EPP; /* negot allways fail here ... */ rc = ioctl (fd, PPNEGOT, &mode); if (rc) { DBG (16, "umax_pp: ppdev couldn't negotiate mode IEEE1284_MODE_EPP for '%s' (ignored)\n", name); } if (ioctl (fd, PPSETMODE, &mode)) { DBG (16, "umax_pp: ppdev couldn't set mode to IEEE1284_MODE_EPP for '%s'\n", name); /* signal failure for ECP test */ mode = 0; } else { DBG (16, "umax_pp: mode set to PARPORT_MODE_EPP for '%s'\n", name); } } if ((modes & PARPORT_MODE_ECP) && (mode == 0)) { mode = IEEE1284_MODE_ECP; rc = ioctl (fd, PPNEGOT, &mode); if (rc) { DBG (16, "umax_pp: ppdev couldn't negotiate mode IEEE1284_MODE_ECP for '%s' (ignored)\n", name); } if (ioctl (fd, PPSETMODE, &mode)) { DBG (16, "umax_pp: ppdev couldn't set mode to IEEE1284_MODE_ECP for '%s'\n", name); DBG (1, "port 0x%X can't be set to EPP or ECP, giving up ...\n", port); mode = IEEE1284_MODE_COMPAT; ioctl (fd, PPSETMODE, &mode); ioctl (fd, PPRELEASE); close (fd); return 0; } else { gECP = 1; DBG (16, "umax_pp: mode set to PARPORT_MODE_ECP for '%s'\n", name); } } /* allways start in compat mode (for probe) */ mode = IEEE1284_MODE_COMPAT; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = 0; /* data forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = 1; /* FW IDLE */ rc = ioctl (fd, PPSETPHASE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); found = 1; } if (!found) { DBG (1, "device %s does not fit ...\n", name); } else { DBG (1, "Using %s ...\n", name); sanei_umax_pp_setparport (fd); return 1; } } } #endif /* HAVE_LINUX_PPDEV_H */ #ifdef HAVE_DEV_PPBUS_PPI_H /* the ppi device let user access to parallel port on freebsd */ if (name != NULL) { if (strlen (name) > 3) { /* ppi opening and configuration */ found = 0; fd = open (name, O_RDONLY); if (fd < 0) { switch (errno) { case ENOENT: DBG (1, "umax_pp: '%s' does not exist \n", name); break; case EACCES: DBG (1, "umax_pp: current user has not read permissions on '%s' \n", name); break; } return 0; } else { DBG (1, "Using %s ...\n", name); sanei_umax_pp_setparport (fd); return 1; } } } #endif /* HAVE_DEV_PPBUS_PPI_H */ if (port < 0x400) { if (sanei_ioperm (port, 8, 1) != 0) { DBG (1, "sanei_ioperm() could not gain access to 0x%X\n", port); return 0; } DBG (1, "sanei_ioperm(0x%X, 8, 1) OK ...\n", port); } #ifdef HAVE_IOPERM /* ECP i/o range */ if (iopl (3) != 0) { DBG (1, "iopl could not raise IO permission to level 3\n"); DBG (1, "*NO* ECP support\n"); } else { /* any ECP out there ? */ ectr = Inb (ECR); if (ectr != 0xFF) { gECP = 1; } } #endif #endif /* IO_SUPPORT_MISSING */ return 1; } static void Outb (int port, int value) { #ifndef IO_SUPPORT_MISSING #ifdef HAVE_LINUX_PPDEV_H int fd, rc, mode, exmode; unsigned char val; fd = sanei_umax_pp_getparport (); val = (unsigned char) value; if (fd > 0) { /* there should be ECR that doesn't go through ppdev */ /* it will leave when all the I/O will be done with ppdev */ switch (port - gPort) { case 0: rc = ioctl (fd, PPWDATA, &val); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #ifdef IOLOG DBG (0, "outb DATA,%02X\n", value); #endif return; case 2: mode = val & 0x20; rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); val = val & 0xDF; rc = ioctl (fd, PPWCONTROL, &val); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #ifdef IOLOG DBG (0, "outb CONTROL,%02X\n", value); #endif return; case 4: rc = ioctl (fd, PPGETMODE, &exmode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = 0; /* data forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &val, 1); if (rc != 1) DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__); rc = ioctl (fd, PPSETMODE, &exmode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #ifdef IOLOG DBG (0, "outb EPPDATA,%02X\n", value); #endif return; case 3: rc = ioctl (fd, PPGETMODE, &exmode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = 0; /* data forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &val, 1); if (rc != 1) DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__); rc = ioctl (fd, PPSETMODE, &exmode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; case 0x400: case 0x402: break; default: DBG (16, "Outb(0x%03X,0x%02X) escaped ppdev\n", port, value); return; } } #endif /* HAVE_LINUX_PPDEV_H */ #ifdef HAVE_DEV_PPBUS_PPI_H int fd, rc; unsigned char val; fd = sanei_umax_pp_getparport (); val = (unsigned char) value; if (fd > 0) { switch (port - gPort) { case 0: rc = ioctl (fd, PPISDATA, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; case 1: rc = ioctl (fd, PPISSTATUS, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; case 2: rc = ioctl (fd, PPISCTRL, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; case 3: rc = ioctl (fd, PPISEPPA, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; case 4: rc = ioctl (fd, PPISEPPD, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; case 0x402: rc = ioctl (fd, PPISECR, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; default: DBG (16, "Outb(0x%03X,0x%02X) escaped ppi\n", port, value); return; } } #endif /* HAVE_DEV_PPBUS_PPI_H */ sanei_outb (port, value); #endif /* IO_SUPPORT_MISSING */ } static int Inb (int port) { int res = 0xFF; #ifndef IO_SUPPORT_MISSING #ifdef HAVE_LINUX_PPDEV_H int fd, rc, mode; unsigned char val; fd = sanei_umax_pp_getparport (); if (fd > 0) { /* there should be ECR that doesn't go through ppdev */ /* it will leave when all the I/O will be done with ppdev */ switch (port - gPort) { case 0: rc = ioctl (fd, PPRDATA, &val); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; #ifdef IOLOG DBG (0, "inb DATA,%02X\n", res); #endif return res; case 1: rc = ioctl (fd, PPRSTATUS, &val); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; #ifdef IOLOG DBG (0, "inb STATUS,%02X\n", res); #endif return res; case 2: rc = ioctl (fd, PPRCONTROL, &val); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; #ifdef IOLOG DBG (0, "inb CONTROL,%02X\n", res); #endif return res; case 4: mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = read (fd, &val, 1); if (rc != 1) DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__); mode = 0; /* data_forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; #ifdef IOLOG DBG (0, "inb EPPDATA,%02X\n", res); #endif return res; case 0x400: case 0x402: default: DBG (16, "Inb(0x%03X) escaped ppdev\n", port); return 0xFF; } } #endif /* HAVE_LINUX_PPDEV_H */ #ifdef HAVE_DEV_PPBUS_PPI_H int fd, rc; unsigned char val; fd = sanei_umax_pp_getparport (); if (fd > 0) { switch (port - gPort) { case 0: rc = ioctl (fd, PPIGDATA, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; return res; case 1: rc = ioctl (fd, PPIGSTATUS, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; return res; case 2: rc = ioctl (fd, PPIGCTRL, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; return res; case 3: rc = ioctl (fd, PPIGEPPA, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; return res; case 4: rc = ioctl (fd, PPIGEPPD, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; return res; case 0x402: rc = ioctl (fd, PPIGECR, &val); if (rc) DBG (0, "ppi ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); res = val; return res; default: DBG (16, "Inb(0x%03X) escaped ppi\n", port); return 0xFF; } } #endif /* HAVE_DEV_PPBUS_PPI_H */ res = sanei_inb (port); #endif /* IO_SUPPORT_MISSING */ return res; } static void Insb (int port, unsigned char *dest, int size) { #ifndef IO_SUPPORT_MISSING #ifdef HAVE_DEV_PPBUS_PPI_H int i; if (sanei_umax_pp_getparport () > 0) { for (i = 0; i < size; i++) dest[i] = Inb (port); return; } #endif /* HAVE_DEV_PPBUS_PPI_H */ sanei_insb (port, dest, size); #endif } static void Outsb (int port, unsigned char *source, int size) { #ifndef IO_SUPPORT_MISSING #ifdef HAVE_DEV_PPBUS_PPI_H int i; if (sanei_umax_pp_getparport () > 0) { for (i = 0; i < size; i++) Outb (port, source[i]); return; } #endif /* HAVE_DEV_PPBUS_PPI_H */ sanei_outsb (port, source, size); #endif } /* size = nb words */ static void Insw (int port, unsigned char *dest, int size) { #ifndef IO_SUPPORT_MISSING #ifdef HAVE_DEV_PPBUS_PPI_H int i; if (sanei_umax_pp_getparport () > 0) { for (i = 0; i < size * 4; i++) dest[i] = Inb (port); return; } #endif /* HAVE_DEV_PPBUS_PPI_H */ sanei_insl (port, dest, size); #endif } static void Outsw (int port, unsigned char *source, int size) { #ifndef IO_SUPPORT_MISSING #ifdef HAVE_DEV_PPBUS_PPI_H int i; if (sanei_umax_pp_getparport () > 0) { for (i = 0; i < size * 4; i++) Outb (port, source[i]); return; } #endif /* HAVE_DEV_PPBUS_PPI_H */ sanei_outsl (port, source, size); #endif } /* we're trying to gather information on the scanner here, */ /* and published it through an easy interface */ /* will turn it into a struct when 610P code will be done */ static int scannerStatus = 0; static time_t gTime = 0; static time_t gDelay = 0; static int epp32 = 1; static int gMode = 0; static int gprobed = 0; static int model = 0x15; static int astra = 0; static int hasUTA = 0; /* signals that scan width matches full ccd width */ static int fullCCDWidth = 0; int sanei_umax_pp_getfull (void) { return fullCCDWidth; } void sanei_umax_pp_setfull (int mod) { fullCCDWidth = mod; } int sanei_umax_pp_UTA (void) { return hasUTA; } int sanei_umax_pp_scannerStatus (void) { struct timeval tv; /* the 610P ASIC needs some time to settle down after probe */ if ((gTime > 0) && (gDelay > 0)) { gettimeofday (&tv, NULL); /* delay elapsed ? */ if (tv.tv_sec - gTime < gDelay) /* still waiting */ return ASIC_BIT; /* wait finished */ gDelay = 0; gTime = 0; } /* 0x07 variant returns status with bit 0 or 1 allways set to 1 */ /* so we mask it out */ return scannerStatus & 0xFC; } static int getEPPMode (void) { if (epp32) return 32; return 8; } static void setEPPMode (int mode) { if (mode == 8) epp32 = 0; else epp32 = 1; } static int getModel (void) { return model; } static void setModel (int mod) { model = mod; } int sanei_umax_pp_getparport (void) { return gParport; } void sanei_umax_pp_setparport (int fd) { gParport = fd; } int sanei_umax_pp_getport (void) { return gPort; } void sanei_umax_pp_setport (int port) { gPort = port; } int sanei_umax_pp_getastra (void) { return astra; } void sanei_umax_pp_setastra (int mod) { astra = mod; } int sanei_umax_pp_getLeft (void) { switch (sanei_umax_pp_getastra ()) { case 610: return 92; default: return 144; } } void sanei_umax_pp_setLeft (int mod) { gLeft = mod; } int sanei_umax_pp_getauto (void) { return gAutoSettings; } void sanei_umax_pp_setauto (int autoset) { gAutoSettings = autoset; } #ifdef HAVE_LINUX_PPDEV_H /* set to the parallel port needed using ppdev * returns 1 if ok, 0 else */ static int ppdev_set_mode (int mode) { int fd, rc; /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { rc = ioctl (fd, PPSETMODE, &mode); if (rc) { DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return 0; } return 1; } return 0; } #endif /* set parallel port mode to 'compatible'*/ static void compatMode (void) { #ifdef HAVE_LINUX_PPDEV_H if (ppdev_set_mode (IEEE1284_MODE_COMPAT)) return; #endif if (!gECP) return; Outb (ECR, 0x15); } /* set parallel port mode to 'bidirectionel'*/ static void byteMode (void) { #ifdef HAVE_LINUX_PPDEV_H if (ppdev_set_mode (IEEE1284_MODE_BYTE)) return; #endif if (!gECP) return; Outb (ECR, 0x35); /* or 0x34 */ } /* set parallel port mode to 'fifo'*/ static void ECPFifoMode (void) { /* bits 7:5 : 000 Standard Mode 001 Byte Mode 010 Parallel Port FIFO Mode 011 ECP FIFO Mode 100 EPP Mode 101 Reserved 110 FIFO Test Mode 111 Configuration Mode */ /* logged as 74/75 */ #ifdef HAVE_LINUX_PPDEV_H if (ppdev_set_mode (IEEE1284_MODE_ECP)) return; #endif if (!gECP) return; Outb (ECR, 0x75); } /* wait for ack bit */ /* return 1 on success, 0 on error */ static int waitAck () { unsigned char breg = 0; int i = 0; Outb (CONTROL, 0x0C); /* select printer + initialize printer */ Outb (CONTROL, 0x0C); Outb (CONTROL, 0x0C); breg = Inb (STATUS) & 0xF8; while ((i < 1024) && ((breg & 0x04) == 0)) { Outb (CONTROL, 0x0E); /* autolinefeed ?.. */ Outb (CONTROL, 0x0E); Outb (CONTROL, 0x0E); breg = Inb (STATUS) & 0xF8; i++; usleep (1000); } if (i == 1024) { DBG (1, "waitAck failed, time-out waiting for Ack (%s:%d)\n", __FILE__, __LINE__); /* return 0; seems to be non-blocking ... */ } Outb (CONTROL, 0x04); /* printer reset */ Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); return 1; } static int waitFifoEmpty (void) { int i; unsigned char breg; breg = Inb (ECR); i = 0; while ((i < FIFO_WAIT) && ((breg & 0x01) == 0)) { breg = Inb (ECR); i++; } if (i == FIFO_WAIT) { DBG (0, "waitFifoEmpty failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return 0; } return 1; } static int waitFifoNotEmpty (void) { int i; unsigned char breg; breg = Inb (ECR); i = 0; while ((i < FIFO_WAIT) && ((breg & 0x01) != 0)) { breg = Inb (ECR); i++; /* usleep (2000); */ } if (i == FIFO_WAIT) { DBG (0, "waitFifoNotEmpty failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return 0; } return 1; } static int waitFifoFull (void) { int i; unsigned char breg; breg = Inb (ECR); /* two wait loop */ /* the first apply to fast data transfer (ie when no scaaning is undergoing) */ /* and we fallback to the second in case the scanner is answering slowly */ i = 0; while ((i < FIFO_WAIT) && ((breg & 0x02) == 0)) { breg = Inb (ECR); i++; } /* don't need to wait any longer */ if (i < FIFO_WAIT) return 1; i = 0; while ((i < FIFO_WAIT) && ((breg & 0x02) == 0)) { breg = Inb (ECR); i++; usleep (500); } if (i == FIFO_WAIT) { DBG (0, "waitFifoFull failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return 0; } return 1; } /* * surely some register reading in PS2 mode * only one nibble is accessed, may be * PS2RegisterLowNibbleRead(reg) */ static int PS2Something (int reg) { unsigned char breg, low, high = 0; Outb (CONTROL, 0x04); Outb (DATA, reg); /* register number ? */ Outb (CONTROL, 0x06); Outb (CONTROL, 0x06); Outb (CONTROL, 0x06); breg = Inb (STATUS) & 0xF8; low = breg; breg = breg & 0x08; /* surely means register(0x10)=0x0B */ /* since reg & 0x08 != 0, high and low nibble * differ, but we don't care, since we surely expect it * to be 0 */ if (breg != 0x08) { DBG (0, "PS2Something failed, expecting 0x08, got 0x%02X (%s:%d)\n", breg, __FILE__, __LINE__); } Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); if (breg != 0x08) high = Inb (STATUS) & 0xF0; return high + ((low & 0xF0) >> 4); } static int PS2Read (void) { int res; int tmp; res = Inb (STATUS); res = Inb (STATUS); res = res & 0xF0; Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); tmp = Inb (STATUS); tmp = Inb (STATUS); tmp = (tmp & 0xF0) >> 4; res = res | tmp; Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 5); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); return res; } /******************************************************************************/ /* PS2registerWrite: write value in register, slow method */ /******************************************************************************/ static void PS2registerWrite (int reg, int value) { /* select register */ Outb (DATA, reg | 0x60); Outb (DATA, reg | 0x60); Outb (CONTROL, 0x01); Outb (CONTROL, 0x01); Outb (CONTROL, 0x01); /* send value */ Outb (DATA, value); Outb (DATA, value); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); } /*****************************************************************************/ /* Send command returns 0 on failure, 1 on success */ /*****************************************************************************/ static int sendCommand (int cmd) { int control; int tmp; int val; int i; if (g674 != 0) { DBG (0, "No scanner attached, sendCommand(0x%X) failed\n", cmd); return 0; } control = Inb (CONTROL) & 0x3F; tmp = cmd & 0xF8; if ((g67D != 1) && (tmp != 0xE0) && (tmp != 0x20) && (tmp != 0x40) && (tmp != 0xD0) && (tmp != 0x08) && (tmp != 0x48)) { Outb (CONTROL, 4); /* reset printer */ } else { val = control & 0x1F; if (g67D != 1) val = val & 0xF; /* no IRQ */ val = val | 0x4; Outb (CONTROL, val); Outb (CONTROL, val); } /* send sequence */ Outb (DATA, 0x22); Outb (DATA, 0x22); Outb (DATA, 0xAA); Outb (DATA, 0xAA); Outb (DATA, 0x55); Outb (DATA, 0x55); Outb (DATA, 0x00); Outb (DATA, 0x00); Outb (DATA, 0xFF); Outb (DATA, 0xFF); Outb (DATA, 0x87); Outb (DATA, 0x87); Outb (DATA, 0x78); Outb (DATA, 0x78); Outb (DATA, cmd); Outb (DATA, cmd); cmd = cmd & 0xF8; if ((g67D == 1) && (cmd == 0xE0)) { val = Inb (CONTROL); val = (val & 0xC) | 0x01; Outb (CONTROL, val); Outb (CONTROL, val); val = val & 0xC; Outb (CONTROL, val); Outb (CONTROL, val); goto sendCommandEnd; } if ((cmd != 8) && (cmd != 0x48)) { tmp = Inb (CONTROL); tmp = Inb (CONTROL); tmp = tmp & 0x1E; if (g67D != 1) tmp = tmp & 0xE; Outb (CONTROL, tmp); Outb (CONTROL, tmp); } if (cmd == 0x10) { tmp = PS2Read (); tmp = tmp * 256 + PS2Read (); goto sendCommandEnd; } if (cmd == 8) { if (g67D == 1) { i = 0; while (i < g67E) { tmp = Inb (CONTROL); tmp = Inb (CONTROL); tmp = (tmp & 0x1E) | 0x1; Outb (CONTROL, tmp); Outb (CONTROL, tmp); Inb (STATUS); tmp = tmp & 0x1E; Outb (CONTROL, tmp); Outb (CONTROL, tmp); /* next read */ i++; if (i < g67E) { Outb (DATA, i | 8); Outb (DATA, i | 8); } } goto sendCommandEnd; } else { DBG (0, "UNEXPLORED BRANCH %s:%d\n", __FILE__, __LINE__); return 0; } } /* */ if (cmd == 0) { i = 0; do { tmp = Inb (CONTROL); tmp = (tmp & 0xE) | 0x1; Outb (CONTROL, tmp); Outb (CONTROL, tmp); tmp = tmp & 0xE; Outb (CONTROL, tmp); Outb (CONTROL, tmp); i++; if (i < g67E) { Outb (DATA, i); Outb (DATA, i); } } while (i < g67E); goto sendCommandEnd; } if (cmd == 0x48) { /* this case is unneeded, should fit with the rest */ tmp = Inb (CONTROL) & 0x1E; if (g67D != 1) tmp = tmp & 0xE; Outb (CONTROL, tmp | 0x1); Outb (CONTROL, tmp | 0x1); Outb (CONTROL, tmp); Outb (CONTROL, tmp); goto sendCommandEnd; } /* */ tmp = Inb (CONTROL) & 0x1E; if (g67D != 1) tmp = tmp & 0xE; Outb (CONTROL, tmp | 0x1); Outb (CONTROL, tmp | 0x1); Outb (CONTROL, tmp); Outb (CONTROL, tmp); /* success */ sendCommandEnd: if (cmd == 0x48) Outb (CONTROL, (control & 0xF) | 0x4); if (cmd == 0x30) Outb (CONTROL, (gControl & 0xF) | 0x4); /* end signature */ Outb (DATA, 0xFF); Outb (DATA, 0xFF); if (cmd == 8) { Outb (CONTROL, control); return 1; } if (cmd == 0x30) { Outb (CONTROL, gControl); return 1; } if (cmd != 0xE0) Outb (CONTROL, control); return 1; } static void ClearRegister (int reg) { /* choose register */ Outb (DATA, reg); Outb (DATA, reg); Outb (CONTROL, 1); Outb (CONTROL, 1); if ((g6FE == 0) || (g674 != 0)) { Outb (CONTROL, 1); Outb (CONTROL, 1); Outb (CONTROL, 1); Outb (CONTROL, 1); } /* clears it by not sending new value */ Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); } static void SPPResetLPT (void) { Outb (CONTROL, 0x04); } static int PS2registerRead (int reg) { int low, high; /* send register number */ Outb (DATA, reg); Outb (DATA, reg); /* get low nibble */ Outb (CONTROL, 1); Outb (CONTROL, 3); Outb (CONTROL, 3); Outb (CONTROL, 3); Outb (CONTROL, 3); low = Inb (STATUS); low = Inb (STATUS); /* get high nibble */ Outb (CONTROL, 4); Outb (CONTROL, 4); Outb (CONTROL, 4); high = Inb (STATUS); high = Inb (STATUS); /* merge nibbles and return */ high = (high & 0xF0) | ((low & 0xF0) >> 4); return high; } static void PS2bufferRead (int size, unsigned char *dest) { int high; int low; int i; int count; int bytel, byteh; /* init transfer */ Outb (DATA, 7); Outb (DATA, 7); Outb (CONTROL, 1); Outb (CONTROL, 1); Outb (CONTROL, 3); Outb (CONTROL, 3); Outb (CONTROL, 3); Outb (DATA, 0xFF); Outb (DATA, 0xFF); count = (size - 2) / 2; i = 0; bytel = 0x06; /* signals low byte of word */ byteh = 0x07; /* signals high byte of word */ /* read loop */ while (count > 0) { /* low nibble byte 0 */ Outb (CONTROL, bytel); Outb (CONTROL, bytel); Outb (CONTROL, bytel); low = Inb (STATUS); if ((low & 0x08) == 0) { /* high nibble <> low nibble */ Outb (CONTROL, bytel & 0x05); Outb (CONTROL, bytel & 0x05); Outb (CONTROL, bytel & 0x05); high = Inb (STATUS); } else { high = low; } low = low & 0xF0; high = high & 0xF0; dest[i] = (unsigned char) (high | (low >> 4)); i++; /* low nibble byte 1 */ Outb (CONTROL, byteh); Outb (CONTROL, byteh); Outb (CONTROL, byteh); low = Inb (STATUS); if ((low & 0x08) == 0) { /* high nibble <> low nibble */ Outb (CONTROL, byteh & 0x05); Outb (CONTROL, byteh & 0x05); Outb (CONTROL, byteh & 0x05); high = Inb (STATUS); } else { high = low; } low = low & 0xF0; high = high & 0xF0; dest[i] = (unsigned char) (high | (low >> 4)); i++; /* next read */ count--; } /* final read */ /* low nibble byte 0 */ Outb (CONTROL, bytel); Outb (CONTROL, bytel); Outb (CONTROL, bytel); low = Inb (STATUS); if ((low & 0x08) == 0) { /* high nibble <> low nibble */ Outb (CONTROL, bytel & 0x05); Outb (CONTROL, bytel & 0x05); Outb (CONTROL, bytel & 0x05); high = Inb (STATUS); } else { high = low; } low = low & 0xF0; high = high & 0xF0; dest[i] = (unsigned char) (high | (low >> 4)); i++; /* uneven size need an extra read */ if ((size & 0x01) == 1) { /* low nibble byte 1 */ Outb (CONTROL, byteh); Outb (CONTROL, byteh); Outb (CONTROL, byteh); low = Inb (STATUS); if ((low & 0x08) == 0) { /* high nibble <> low nibble */ Outb (CONTROL, byteh & 0x05); Outb (CONTROL, byteh & 0x05); Outb (CONTROL, byteh & 0x05); high = Inb (STATUS); } else { high = low; } low = low & 0xF0; high = high & 0xF0; dest[i] = (unsigned char) (high | (low >> 4)); i++; /* swap high/low word */ count = bytel; bytel = byteh; byteh = count; } /* final byte ... */ Outb (DATA, 0xFD); Outb (DATA, 0xFD); Outb (DATA, 0xFD); /* low nibble */ Outb (CONTROL, byteh); Outb (CONTROL, byteh); Outb (CONTROL, byteh); low = Inb (STATUS); if ((low & 0x08) == 0) { /* high nibble <> low nibble */ Outb (CONTROL, byteh & 0x05); Outb (CONTROL, byteh & 0x05); Outb (CONTROL, byteh & 0x05); high = Inb (STATUS); } else { high = low; } low = low & 0xF0; high = high & 0xF0; dest[i] = (unsigned char) (high | (low >> 4)); i++; /* reset port */ Outb (DATA, 0x00); Outb (DATA, 0x00); Outb (CONTROL, 0x04); } static void PS2bufferWrite (int size, unsigned char *source) { int i; int count; int val; /* init buffer write */ i = 0; count = size / 2; Outb (DATA, 0x67); Outb (CONTROL, 0x01); Outb (CONTROL, 0x01); Outb (CONTROL, 0x05); /* write loop */ while (count > 0) { /* low byte of word */ val = source[i]; i++; Outb (DATA, val); Outb (DATA, val); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); /* high byte of word */ val = source[i]; i++; Outb (DATA, val); Outb (DATA, val); Outb (CONTROL, 0x05); Outb (CONTROL, 0x05); Outb (CONTROL, 0x05); Outb (CONTROL, 0x05); /* next write */ count--; } /* termination sequence */ Outb (CONTROL, 0x05); Outb (CONTROL, 0x05); Outb (CONTROL, 0x05); Outb (CONTROL, 0x05); Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); } static void init001 (void) { int i; int val; int status; ClearRegister (0); Outb (CONTROL, 0x0C); if (g674 != 0) { Outb (CONTROL, 0x0C); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x0C); } Outb (DATA, 0x40); if (g674 != 0) { Outb (DATA, 0x40); Outb (DATA, 0x40); Outb (DATA, 0x40); } Outb (CONTROL, 0x06); Outb (CONTROL, 0x06); Outb (CONTROL, 0x06); if (g674 != 0) { Outb (CONTROL, 0x06); Outb (CONTROL, 0x06); Outb (CONTROL, 0x06); } /* sync loop */ i = 256; do { status = Inb (STATUS); i--; } while ((i > 0) && ((status & 0x40))); val = 0x0C; if (i > 0) { Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); if (g674 != 0) { Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); Outb (CONTROL, 0x07); } val = 0x04; Outb (CONTROL, val); Outb (CONTROL, val); Outb (CONTROL, val); if (g674 != 0) { Outb (CONTROL, val); Outb (CONTROL, val); Outb (CONTROL, val); } } val = val | 0x0C; Outb (CONTROL, val); Outb (CONTROL, val); Outb (CONTROL, val); if (g674 != 0) { Outb (CONTROL, val); Outb (CONTROL, val); Outb (CONTROL, val); } val = val & 0xF7; Outb (CONTROL, val); Outb (CONTROL, val); Outb (CONTROL, val); if (g674 != 0) { Outb (CONTROL, val); Outb (CONTROL, val); Outb (CONTROL, val); } } /* SPP register reading */ static int init002 (int arg) { int data; if (arg == 1) return 0; Outb (DATA, 0x0B); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x04); Outb (CONTROL, 0x24); Outb (CONTROL, 0x24); Outb (CONTROL, 0x26); Outb (CONTROL, 0x26); data = Inb (DATA); Outb (CONTROL, 0x04); if (data == gEPAT) { return 1; } return 0; } /* * connecct to the EPAT chip, and * prepare command sending */ static int ECPconnect (void) { int ret, control; /* these 3 lines set to 'inital mode' */ byteMode (); /*Outb (ECR, 0x20); */ Outb (DATA, 0x04); /* gData */ Outb (CONTROL, 0x0C); /* gControl */ Inb (ECR); /* 0x35 */ byteMode (); /*Outb (ECR, 0x20); */ byteMode (); /*Outb (ECR, 0x20); */ gData = Inb (DATA); gControl = Inb (CONTROL); Inb (DATA); control = Inb (CONTROL); Outb (CONTROL, control & 0x1F); control = Inb (CONTROL); Outb (CONTROL, control & 0x1F); sendCommand (0xE0); Outb (DATA, 0xFF); Outb (DATA, 0xFF); ClearRegister (0); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x04); ClearRegister (0); ret = PS2Something (0x10); if (ret != 0x0B) { DBG (16, "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", ret, __FILE__, __LINE__); } return 1; } static void EPPdisconnect (void) { if (getModel () != 0x07) sendCommand (40); sendCommand (30); Outb (DATA, gData); Outb (CONTROL, gControl); } static void ECPdisconnect (void) { int control; if (getModel () != 0x07) /* guessed */ sendCommand (40); /* guessed */ sendCommand (0x30); control = Inb (CONTROL) | 0x01; Outb (CONTROL, control); Outb (CONTROL, control); control = control & 0x04; Outb (CONTROL, control); Outb (CONTROL, control); control = control | 0x08; Outb (CONTROL, control); Outb (DATA, 0xFF); Outb (DATA, 0xFF); Outb (CONTROL, control); } static int ECPregisterRead (int reg) { unsigned char breg, value; #ifdef HAVE_LINUX_PPDEV_H int rc, mode, fd; unsigned char bval; fd = sanei_umax_pp_getparport (); if (fd > 0) { Outb (CONTROL, 0x04); ECPFifoMode (); Outb (DATA, reg); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = read (fd, &bval, 1); if (rc != 1) DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__); value = bval; breg = (Inb (CONTROL) & 0x3F); if (breg != 0x20) { DBG (0, "ECPregisterRead failed, expecting 0x20, got 0x%02X (%s:%d)\n", breg, __FILE__, __LINE__); } /* restore port state */ mode = 0; /* data_forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); Outb (CONTROL, 0x04); byteMode (); return value; } #endif Outb (CONTROL, 0x4); /* ECP FIFO mode, interrupt bit, dma disabled, service bit, fifo full=0, fifo empty=0 */ ECPFifoMode (); /*Outb (ECR, 0x60); */ if (waitFifoEmpty () == 0) { DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n", __FILE__, __LINE__); } breg = Inb (ECR); Outb (DATA, reg); if (waitFifoEmpty () == 0) { DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n", __FILE__, __LINE__); } breg = Inb (ECR); /* byte mode, interrupt bit, dma disabled, service bit, fifo full=0, fifo empty=0 */ byteMode (); /*Outb (ECR, 0x20); */ Outb (CONTROL, 0x20); /* data reverse */ /* ECP FIFO mode, interrupt bit, dma disabled, service bit, fifo full=0, fifo empty=0 */ ECPFifoMode (); /*Outb (ECR, 0x60); */ if (waitFifoNotEmpty () == 0) { DBG (0, "ECPregisterRead failed, FIFO time-out (%s:%d)\n", __FILE__, __LINE__); } breg = Inb (ECR); value = Inb (ECPDATA); /* according to the spec bit 7 and 6 are unused */ breg = (Inb (CONTROL) & 0x3F); if (breg != 0x20) { DBG (0, "ECPregisterRead failed, expecting 0x20, got 0x%02X (%s:%d)\n", breg, __FILE__, __LINE__); } Outb (CONTROL, 0x04); byteMode (); return value; } static int EPPregisterRead (int reg) { #ifdef HAVE_LINUX_PPDEV_H int fd, mode, rc; unsigned char breg, bval; #endif int control; int value; #ifdef HAVE_LINUX_PPDEV_H /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { breg = (unsigned char) (reg); mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &breg, 1); if (rc != 1) DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = read (fd, &bval, 1); if (rc != 1) DBG (0, "ppdev short read (%s:%d)\n", __FILE__, __LINE__); value = bval; mode = 0; /* forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return value; } /* if not, direct hardware access */ #endif Outb (EPPADDR, reg); control = Inb (CONTROL); control = (control & 0x1F) | 0x20; Outb (CONTROL, control); value = Inb (EPPDATA); control = Inb (CONTROL); control = control & 0x1F; Outb (CONTROL, control); return 0xFF; /* return value; */ } static int registerRead (int reg) { switch (gMode) { case UMAX_PP_PARPORT_ECP: return ECPregisterRead (reg); case UMAX_PP_PARPORT_BYTE: DBG (0, "STEF: gMode BYTE in registerRead !!\n"); return 0xFF; case UMAX_PP_PARPORT_EPP: return EPPregisterRead (reg); case UMAX_PP_PARPORT_PS2: DBG (0, "STEF: gMode PS2 in registerRead !!\n"); return PS2registerRead (reg); default: DBG (0, "STEF: gMode unset in registerRead !!\n"); return 0xFF; } } static void ECPregisterWrite (int reg, int value) { unsigned char breg; #ifdef HAVE_LINUX_PPDEV_H int rc, fd; fd = sanei_umax_pp_getparport (); if (fd > 0) { ECPFifoMode (); Outb (DATA, reg); breg = value; rc = write (fd, &breg, 1); if (rc != 1) DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__); Outb (CONTROL, 0x04); byteMode (); return; } #endif /* standard mode, interrupt bit, dma disabled, service bit, fifo full=0, fifo empty=0 */ compatMode (); Outb (CONTROL, 0x04); /* reset ? */ /* ECP FIFO mode, interrupt bit, dma disabled, service bit, fifo full=0, fifo empty=0 */ ECPFifoMode (); /*Outb (ECR, 0x60); */ if (waitFifoEmpty () == 0) { DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } breg = Inb (ECR); Outb (DATA, reg); if (waitFifoEmpty () == 0) { DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } breg = Inb (ECR); Outb (ECPDATA, value); if (waitFifoEmpty () == 0) { DBG (0, "ECPregisterWrite failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } breg = Inb (ECR); Outb (CONTROL, 0x04); byteMode (); return; } static void EPPregisterWrite (int reg, int value) { #ifdef HAVE_LINUX_PPDEV_H int fd, mode, rc; unsigned char breg, bval; #endif reg = reg | 0x40; #ifdef HAVE_LINUX_PPDEV_H /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { breg = (unsigned char) (reg); mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &breg, 1); if (rc != 1) DBG (0, "ppdev short write (%s:%d)\n", __FILE__, __LINE__); bval = (unsigned char) (value); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); return; } /* if not, direct hardware access */ #endif Outb (EPPADDR, reg); Outb (EPPDATA, value); } static void registerWrite (int reg, int value) { switch (gMode) { case UMAX_PP_PARPORT_PS2: PS2registerWrite (reg, value); DBG (0, "STEF: gMode PS2 in registerWrite !!\n"); break; case UMAX_PP_PARPORT_ECP: ECPregisterWrite (reg, value); break; case UMAX_PP_PARPORT_EPP: EPPregisterWrite (reg, value); break; case UMAX_PP_PARPORT_BYTE: DBG (0, "STEF: gMode BYTE in registerWrite !!\n"); break; default: DBG (0, "STEF: gMode unset in registerWrite !!\n"); break; } } static void EPPBlockMode (int flag) { #ifdef HAVE_LINUX_PPDEV_H int fd, mode, rc; unsigned char bval; /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { bval = (unsigned char) (flag); mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); return; } #endif Outb (EPPADDR, flag); } static void EPPbufferRead (int size, unsigned char *dest) { #ifdef HAVE_LINUX_PPDEV_H int fd, mode, rc, nb; unsigned char bval; #endif int control; #ifdef HAVE_LINUX_PPDEV_H /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { bval = 0x80; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #ifdef PPSETFLAGS mode = PP_FASTREAD; rc = ioctl (fd, PPSETFLAGS, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #endif mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); nb = 0; while (nb < size - 1) { rc = read (fd, dest + nb, size - 1 - nb); nb += rc; } mode = 0; /* forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); bval = 0xA0; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = read (fd, dest + size - 1, 1); mode = 0; /* forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; } /* if not, direct hardware access */ #endif EPPBlockMode (0x80); control = Inb (CONTROL); Outb (CONTROL, (control & 0x1F) | 0x20); /* reverse */ Insb (EPPDATA, dest, size - 1); control = Inb (CONTROL); Outb (CONTROL, (control & 0x1F)); /* forward */ EPPBlockMode (0xA0); control = Inb (CONTROL); Outb (CONTROL, (control & 0x1F) | 0x20); /* reverse */ Insb (EPPDATA, (unsigned char *) (dest + size - 1), 1); control = Inb (CONTROL); Outb (CONTROL, (control & 0x1F)); /* forward */ } /* block transfer init */ static void ECPSetBuffer (int size) { static int last = 0; /* routine XX */ compatMode (); Outb (CONTROL, 0x04); /* reset ? */ /* we set size only if it has changed */ /* from last time */ if (size == last) return; last = size; /* mode and size setting */ ECPFifoMode (); /*Outb (ECR, 0x60); */ if (waitFifoEmpty () == 0) { DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } Inb (ECR); Outb (DATA, 0x0E); if (waitFifoEmpty () == 0) { DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } Inb (ECR); Outb (ECPDATA, 0x0B); /* R0E=0x0B */ if (waitFifoEmpty () == 0) { DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } Inb (ECR); Outb (DATA, 0x0F); /* R0F=size MSB */ if (waitFifoEmpty () == 0) { DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } Inb (ECR); Outb (ECPDATA, size / 256); if (waitFifoEmpty () == 0) { DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } Inb (ECR); Outb (DATA, 0x0B); /* R0B=size LSB */ if (waitFifoEmpty () == 0) { DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } Inb (ECR); Outb (ECPDATA, size % 256); if (waitFifoEmpty () == 0) { DBG (0, "ECPSetBuffer failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } Inb (ECR); DBG (16, "ECPSetBuffer(%d) passed ...\n", size); } static int ECPbufferRead (int size, unsigned char *dest) { int n, idx, remain; idx = 0; n = size / 16; remain = size - 16 * n; /* block transfer */ Inb (ECR); /* 0x15,0x75 expected: fifo empty */ byteMode (); /*Outb (ECR, 0x20); byte mode */ Outb (CONTROL, 0x04); ECPFifoMode (); /*Outb (ECR, 0x60); */ if (waitFifoEmpty () == 0) { DBG (0, "ECPbufferRead failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return idx; } Inb (ECR); Outb (DATA, 0x80); if (waitFifoEmpty () == 0) { DBG (0, "ECPbufferRead failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return idx; } Inb (ECR); /* 0x75 expected */ byteMode (); /*Outb (ECR, 0x20); byte mode */ Outb (CONTROL, 0x20); /* data reverse */ ECPFifoMode (); /*Outb (ECR, 0x60); */ while (n > 0) { if (waitFifoFull () == 0) { DBG (0, "ECPbufferRead failed, time-out waiting for FIFO idx=%d (%s:%d)\n", idx, __FILE__, __LINE__); return idx; } Insb (ECPDATA, dest + idx, 16); idx += 16; n--; } /* reading trailing bytes */ while (remain > 0) { if (waitFifoNotEmpty () == 0) { DBG (0, "ECPbufferRead failed, FIFO time-out (%s:%d)\n", __FILE__, __LINE__); } dest[idx] = Inb (ECPDATA); idx++; remain--; } return idx; } static void EPPbufferWrite (int size, unsigned char *source) { #ifdef HAVE_LINUX_PPDEV_H int fd, mode, rc; unsigned char bval; #endif #ifdef HAVE_LINUX_PPDEV_H /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { bval = 0xC0; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, source, size); return; } /* if not, direct hardware access */ #endif EPPBlockMode (0xC0); Outsb (EPPDATA, source, size); } static void ECPbufferWrite (int size, unsigned char *source) { unsigned char breg; int n, idx; /* until we know to handle that case, fail */ if (size % 16 != 0) { DBG (0, "ECPbufferWrite failed, size %%16 !=0 (%s:%d)\n", __FILE__, __LINE__); return; } /* prepare actual transfer */ compatMode (); Outb (CONTROL, 0x04); /* reset ? */ breg = Inb (CONTROL); Outb (CONTROL, 0x04); /* data forward */ ECPFifoMode (); /*Outb (ECR, 0x60); */ if (waitFifoEmpty () == 0) { DBG (0, "ECPWriteBuffer failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } breg = Inb (ECR); breg = (Inb (STATUS)) & 0xF8; n = 0; while ((n < 1024) && (breg != 0xF8)) { breg = (Inb (STATUS)) & 0xF8; n++; } if (breg != 0xF8) { DBG (0, "ECPbufferWrite failed, expected status=0xF8, got 0x%02X (%s:%d)\n", breg, __FILE__, __LINE__); return; } /* wait for FIFO empty (bit 0) */ if (waitFifoEmpty () == 0) { DBG (0, "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } breg = Inb (ECR); /* block transfer direction * 0x80 means from scanner to PC, 0xC0 means PC to scanner */ Outb (DATA, 0xC0); n = size / 16; idx = 0; while (n > 0) { /* wait for FIFO empty */ if (waitFifoEmpty () == 0) { DBG (0, "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } breg = Inb (ECR); Outsb (ECPDATA, source + idx * 16, 16); idx++; n--; } /* final FIFO check and go to Byte mode */ if (waitFifoEmpty () == 0) { DBG (0, "ECPbufferWrite failed, time-out waiting for FIFO (%s:%d)\n", __FILE__, __LINE__); return; } breg = Inb (ECR); Outb (CONTROL, 0x04); byteMode (); } static void bufferWrite (int size, unsigned char *source) { switch (gMode) { case UMAX_PP_PARPORT_PS2: PS2bufferWrite (size, source); DBG (0, "STEF: gMode PS2 in bufferWrite !!\n"); break; case UMAX_PP_PARPORT_ECP: ECPbufferWrite (size, source); break; case UMAX_PP_PARPORT_EPP: switch (getEPPMode ()) { case 32: EPPWrite32Buffer (size, source); break; default: EPPbufferWrite (size, source); break; } break; default: DBG (0, "STEF: gMode PS2 in bufferWrite !!\n"); break; } return; } static void bufferRead (int size, unsigned char *dest) { switch (gMode) { case UMAX_PP_PARPORT_PS2: PS2bufferRead (size, dest); DBG (0, "STEF: gMode PS2 in bufferRead !!\n"); break; case UMAX_PP_PARPORT_ECP: ECPbufferRead (size, dest); break; case UMAX_PP_PARPORT_EPP: switch (getEPPMode ()) { case 32: EPPRead32Buffer (size, dest); break; default: EPPbufferRead (size, dest); break; } break; default: DBG (0, "STEF: gMode unset in bufferRead !!\n"); break; } return; } static int connect (void) { if (sanei_umax_pp_getastra () == 610) return connect610p (); switch (gMode) { case UMAX_PP_PARPORT_PS2: DBG (0, "STEF: unimplemented gMode PS2 in connect() !!\n"); return 0; break; case UMAX_PP_PARPORT_ECP: return ECPconnect (); break; case UMAX_PP_PARPORT_BYTE: DBG (0, "STEF: unimplemented gMode BYTE in connect() !!\n"); return 0; break; case UMAX_PP_PARPORT_EPP: return EPPconnect (); default: DBG (0, "STEF: gMode unset in connect() !!\n"); break; } return 0; } static void disconnect (void) { if (sanei_umax_pp_getastra () == 610) disconnect610p (); switch (gMode) { case UMAX_PP_PARPORT_PS2: DBG (0, "STEF: unimplemented gMode PS2 in disconnect() !!\n"); break; case UMAX_PP_PARPORT_ECP: ECPdisconnect (); break; case UMAX_PP_PARPORT_BYTE: DBG (0, "STEF: unimplemented gMode BYTE in disconnect() !!\n"); break; case UMAX_PP_PARPORT_EPP: EPPdisconnect (); break; default: DBG (0, "STEF: gMode unset in disconnect() !!\n"); break; } } /* returns 0 if mode OK, else -1 */ static int checkEPAT (void) { int version; version = registerRead (0x0B); if (version == 0xC7) return 0; DBG (0, "checkEPAT: expected EPAT version 0xC7, got 0x%X! (%s:%d)\n", version, __FILE__, __LINE__); return -1; } static int init005 (int arg) { int count = 5; int res; while (count > 0) { registerWrite (0x0A, arg); Outb (DATA, 0xFF); res = registerRead (0x0A); /* failed ? */ if (res != arg) return 1; /* ror arg */ res = arg & 0x01; arg = arg / 2; if (res == 1) arg = arg | 0x80; /* next loop */ count--; } return 0; } /* write 1 byte in EPP mode, returning scnner's status */ static int EPPputByte610p (int data) { int status, control; status = Inb (STATUS) & 0xF8; if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0)) { DBG (0, "EPPputByte610p failed, expected 0xC8, 0xD0 or 0xC0 got 0x%02X ! (%s:%d)\n", status, __FILE__, __LINE__); return 0; } control = (Inb (CONTROL) & 0x44) | 0x44; /* data forward, bit 5 cleared (!!) */ Outb (CONTROL, control); Outb (EPPDATA, data); return status; } static int putByte610p (int data) { int status, control, j; if (gMode == UMAX_PP_PARPORT_EPP) return EPPputByte610p (data); j = 0; do { status = Inb (STATUS) & 0xF8; j++; } while ((j < 20) && (status & 0x08)); if ((status != 0xC8) && (status != 0xC0)) { DBG (0, "putByte610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n", status, __FILE__, __LINE__); return 0; } control = Inb (CONTROL) & 0x1F; /* data forward */ Outb (CONTROL, control); Outb (DATA, data); Outb (CONTROL, 0x07); status = Inb (STATUS) & 0xF8; if ((status != 0x48) && (status != 0x40)) { DBG (0, "putByte610p failed, expected 0x48 or 0x40 got 0x%02X ! (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (CONTROL, 0x05); status = Inb (STATUS) & 0xF8; Outb (CONTROL, control); return status; } /* 1 OK, 0 failure */ static int sync610p (void) { int status; Outb (DATA, 0x40); Outb (CONTROL, 0x06); status = Inb (STATUS) & 0xF8; if (status != 0x38) { DBG (0, "sync610p failed (got 0x%02X expected 0x38)! (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (CONTROL, 0x07); status = Inb (STATUS) & 0xF8; if (status != 0x38) { DBG (0, "sync610p failed (got 0x%02X expected 0x38)! (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (CONTROL, 0x04); status = Inb (STATUS) & 0xF8; if (status != 0xF8) { DBG (0, "sync610p failed (got 0x%02X expected 0xF8)! (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (CONTROL, 0x05); Inb (CONTROL); /* 0x05 expected */ Outb (CONTROL, 0x04); return 1; } static int EPPcmdSync610p (int cmd) { int word[5]; int status; int i; word[0] = 0; word[1] = 0; word[2] = 0; word[3] = cmd; connect610p (); sync610p (); /* sends magic seal 55 AA */ status = EPPputByte610p (0x55); if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0)) { DBG (1, "EPPcmdSync610p: Found 0x%X expected 0xC8, 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } status = EPPputByte610p (0xAA); if ((status != 0xC8) && (status != 0xC0) && (status != 0xD0)) { DBG (1, "EPPcmdSync610p: Found 0x%X expected 0xC8, 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } status = EPPgetStatus610p (); if (status == 0xC0) for (i = 0; i < 10; i++) status = Inb (STATUS) & 0xF8; if (status != 0xC8) { DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC8 (%s:%d)\n", status, __FILE__, __LINE__); /*return 0; */ } /* sends 4 bytes of data */ for (i = 0; i < 4; i++) { status = EPPputByte610p (word[i]); } if (status != 0xC8) { DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC8 (%s:%d)\n", status, __FILE__, __LINE__); /*return 0; */ } /* tests status */ Outb (DATA, 0xFF); if (cmd == 0xC2) { status = EPPgetStatus610p (); if (status != 0xC0) { DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); /*return 0; */ } } status = EPPgetStatus610p (); if (status != 0xC0) { DBG (0, "EPPcmdSync610p: Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); /*return 0; */ } disconnect610p (); return 1; } static int cmdSync610p (int cmd) { int word[5]; int status; if (gMode == UMAX_PP_PARPORT_EPP) return EPPcmdSync610p (cmd); word[0] = 0; word[1] = 0; word[2] = 0; word[3] = cmd; connect610p (); sync610p (); if (sendLength610p (word) == 0) { DBG (0, "sendLength610p() failed... (%s:%d)\n", __FILE__, __LINE__); return 0; } if (cmd == 0xC2) { status = getStatus610p (); if (status != 0xC0) { DBG (1, "Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } } status = getStatus610p (); if (status != 0xC0) { DBG (1, "Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } disconnect610p (); return 1; } static int EPPgetStatus610p (void) { int data, status, control, i; control = Inb (CONTROL) & 0xA4; control = control | 0xE0; Outb (CONTROL, control); status = Inb (STATUS) & 0xF8; if (status & 0x08) { for (i = 1; i < 10; i++) status = Inb (STATUS) & 0xF8; } else { data = Inb (EPPDATA); scannerStatus = data; } return status; } static int getStatus610p (void) { int data, status; byteMode (); status = Inb (STATUS) & 0xF8; Outb (CONTROL, 0x26); /* data reverse */ data = Inb (DATA); scannerStatus = data; Outb (CONTROL, 0x24); return status; } int sendLength610p (int *cmd) { int ret, i, wait; /* 55,AA,x,y,z,t */ byteMode (); wait = putByte610p (0x55); if ((wait != 0xC8) && (wait != 0xC0)) { DBG (0, "sendLength610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n", wait, __FILE__, __LINE__); return 0; } wait = putByte610p (0xAA); if ((wait != 0xC8) && (wait != 0xC0)) { DBG (0, "sendLength610p failed, expected 0xC8 or 0xC0 got 0x%02X ! (%s:%d)\n", wait, __FILE__, __LINE__); return 0; } /* if wait=C0, we have to ... wait */ if (wait == 0xC0) { byteMode (); wait = Inb (STATUS); /* C0 expected */ Outb (CONTROL, 0x26); ret = Inb (DATA); /* 88 expected */ Outb (CONTROL, 0x24); for (i = 0; i < 10; i++) wait = Inb (STATUS); /* C8 expected */ byteMode (); } for (i = 0; i < 3; i++) { ret = putByte610p (cmd[i]); if (ret != 0xC8) { DBG (0, "sendLength610p failed, expected 0xC8 got 0x%02X ! (%s:%d)\n", ret, __FILE__, __LINE__); return 0; } } ret = putByte610p (cmd[3]); if ((ret != 0xC0) && (ret != 0xD0)) { DBG (0, "sendLength610p failed, expected 0xC0 or 0xD0 got 0x%02X ! (%s:%d)\n", ret, __FILE__, __LINE__); return 0; } return 1; } /* 1 OK, 0 failure */ static int disconnect610p (void) { int control, i; Outb (CONTROL, 0x04); for (i = 0; i < 41; i++) { control = Inb (CONTROL) & 0x3F; if (control != 0x04) { DBG (0, "disconnect610p failed (idx %d=%02X)! (%s:%d)\n", i, control, __FILE__, __LINE__); return 0; } } Outb (CONTROL, 0x0C); control = Inb (CONTROL) & 0x3F; if (control != 0x0C) { DBG (0, "disconnect610p failed expected 0x0C got %02X (%s:%d)\n", control, __FILE__, __LINE__); return 0; } /* XXX STEF XXX Outb (DATA, gData); */ Outb (DATA, 0xFF); return 1; } /* 1 OK, 0 failure */ /* 0: short connect, 1 long connect */ static int connect610p (void) { int control; gData = Inb (DATA); /* to gDATA ? */ Outb (DATA, 0xAA); Outb (CONTROL, 0x0E); control = Inb (CONTROL); /* 0x0E expected */ control = Inb (CONTROL) & 0x3F; if (control != 0x0E) { DBG (0, "connect610p control=%02X, expected 0x0E (%s:%d)\n", control, __FILE__, __LINE__); } Outb (DATA, 0x00); Outb (CONTROL, 0x0C); control = Inb (CONTROL); /* 0x0C expected */ control = Inb (CONTROL) & 0x3F; if (control != 0x0C) { DBG (0, "connect610p control=%02X, expected 0x0C (%s:%d)\n", control, __FILE__, __LINE__); } Outb (DATA, 0x55); Outb (CONTROL, 0x0E); control = Inb (CONTROL); /* 0x0E expected */ control = Inb (CONTROL) & 0x3F; if (control != 0x0E) { DBG (0, "connect610p control=%02X, expected 0x0E (%s:%d)\n", control, __FILE__, __LINE__); } Outb (DATA, 0xFF); Outb (CONTROL, 0x0C); control = Inb (CONTROL); /* 0x0C expected */ control = Inb (CONTROL) & 0x3F; if (control != 0x0C) { DBG (0, "connect610p control=%02X, expected 0x0C (%s:%d)\n", control, __FILE__, __LINE__); } Outb (CONTROL, 0x04); control = Inb (CONTROL); /* 0x04 expected */ control = Inb (CONTROL) & 0x3F; if (control != 0x04) { DBG (0, "connect610p control=%02X, expected 0x04 (%s:%d)\n", control, __FILE__, __LINE__); } return 1; } /* 1 OK, 0 failure */ static int EPPconnect (void) { int control; /* initial values, don't hardcode */ Outb (DATA, 0x04); Outb (CONTROL, 0x0C); Inb (DATA); control = Inb (CONTROL); Outb (CONTROL, control & 0x1F); control = Inb (CONTROL); Outb (CONTROL, control & 0x1F); if (sendCommand (0xE0) != 1) { DBG (0, "EPPconnect: sendCommand(0xE0) failed! (%s:%d)\n", __FILE__, __LINE__); return 0; } ClearRegister (0); init001 (); return 1; } static void EPPRead32Buffer (int size, unsigned char *dest) { #ifdef HAVE_LINUX_PPDEV_H int fd, mode, rc, nb; unsigned char bval; #endif int control; #ifdef HAVE_LINUX_PPDEV_H /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { bval = 0x80; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #ifdef PPSETFLAGS mode = PP_FASTREAD; rc = ioctl (fd, PPSETFLAGS, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #endif mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); nb = 0; while (nb < size - 4) { rc = read (fd, dest + nb, size - 4 - nb); nb += rc; } rc = read (fd, dest + size - 4, 3); mode = 0; /* forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); bval = 0xA0; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = read (fd, dest + size - 1, 1); mode = 0; /* forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return; } /* if not, direct hardware access */ #endif EPPBlockMode (0x80); control = Inb (CONTROL); Outb (CONTROL, (control & 0x1F) | 0x20); Insw (EPPDATA, dest, size / 4 - 1); Insb (EPPDATA, (unsigned char *) (dest + size - 4), 3); control = Inb (CONTROL); Outb (CONTROL, (control & 0x1F)); EPPBlockMode (0xA0); control = Inb (CONTROL); Outb (CONTROL, (control & 0x1F) | 0x20); Insb (EPPDATA, (unsigned char *) (dest + size - 1), 1); control = Inb (CONTROL); Outb (CONTROL, (control & 0x1F)); } static void EPPWrite32Buffer (int size, unsigned char *source) { #ifdef HAVE_LINUX_PPDEV_H int fd, mode, rc; unsigned char bval; #endif if ((size % 4) != 0) { DBG (0, "EPPWrite32Buffer: size %% 4 != 0!! (%s:%d)\n", __FILE__, __LINE__); } #ifdef HAVE_LINUX_PPDEV_H /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { bval = 0xC0; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); #ifdef PPSETFLAGS mode = PP_FASTWRITE; rc = ioctl (fd, PPSETFLAGS, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #endif mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, source, size); return; } /* if not, direct hardware access */ #endif EPPBlockMode (0xC0); Outsw (EPPDATA, source, size / 4); } /* returns 0 if ERROR cleared in STATUS within 1024 inb, else 1 */ static int WaitOnError (void) { int c = 0; int count = 1024; int status; do { do { status = Inb (STATUS) & 0x08; if (status != 0) { count--; if (count == 0) c = 1; } } while ((count > 0) && (status != 0)); if (status == 0) { status = Inb (STATUS) & 0x08; if (status == 0) c = 0; } } while ((status != 0) && (c == 0)); return c; } #ifdef HAVE_LINUX_PPDEV_H /* read up to size bytes, returns bytes read */ static int ParportpausedBufferRead (int size, unsigned char *dest) { unsigned char status, bval; int error; int word; int bread; int c; int fd, rc, mode; /* WIP check */ if (gMode == UMAX_PP_PARPORT_ECP) { DBG (0, "ECP access not implemented yet (WIP) ! (%s:%d)\n", __FILE__, __LINE__); } /* init */ bread = 0; error = 0; fd = sanei_umax_pp_getparport (); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #ifdef PPSETFLAGS mode = PP_FASTREAD; rc = ioctl (fd, PPSETFLAGS, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #endif mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); if ((size & 0x03) != 0) { while ((!error) && ((size & 0x03) != 0)) { rc = read (fd, dest, 1); size--; dest++; bread++; rc = ioctl (fd, PPRSTATUS, &status); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); error = status & 0x08; } if (error) { DBG (0, "Read error (%s:%d)\n", __FILE__, __LINE__); return 0; } } /* from here, we read 1 byte, then size/4-1 32 bits words, and then 3 bytes, pausing on ERROR bit of STATUS */ size -= 4; /* sanity test, seems to be wrongly handled ... */ if (size == 0) { DBG (0, "case not handled! (%s:%d)\n", __FILE__, __LINE__); return 0; } word = 0; error = 0; bread += size; do { do { rc = read (fd, dest, 1); size--; dest++; readstatus: if (size > 0) { rc = ioctl (fd, PPRSTATUS, &status); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); word = status & 0x10; error = status & 0x08; } } while ((size > 0) && (!error) && (!word)); } while ((size < 4) && (!error) && (size > 0)); /* here size=0 or error=8 or word=0x10 */ if ((word) && (!error) && (size)) { rc = read (fd, dest, 4); dest += 4; size -= 4; if (size != 0) error = 0x08; } if (!error) { c = 0; rc = ioctl (fd, PPRSTATUS, &status); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); error = status & 0x08; if (error) c = WaitOnError (); } else { /* 8282 */ c = WaitOnError (); if (c == 0) goto readstatus; } if (c == 1) { bread -= size; } else { bread += 3; size = 3; do { do { rc = read (fd, dest, 1); dest++; size--; if (size) { rc = ioctl (fd, PPRSTATUS, &status); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); error = status & 0x08; if (!error) { rc = ioctl (fd, PPRSTATUS, &status); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); error = status & 0x08; } } } while ((size > 0) && (!error)); c = 0; if (error) c = WaitOnError (); } while ((size > 0) && (c == 0)); } /* end reading */ mode = 0; /* forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); bval = 0xA0; mode = IEEE1284_MODE_EPP | IEEE1284_ADDR; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = write (fd, &bval, 1); mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); rc = read (fd, dest, 1); bread++; mode = 0; /* forward */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return bread; } #endif /* read up to size bytes, returns bytes read */ static int DirectpausedBufferRead (int size, unsigned char *dest) { int control; int status; int error; int word; int read; int c; /* init */ read = 0; error = 0; control = Inb (CONTROL) & 0x1F; Outb (CONTROL, control | 0x20); if ((size & 0x03) != 0) { /* 8174 */ while ((!error) && ((size & 0x03) != 0)) { Insb (EPPDATA, dest, 1); size--; dest++; read++; status = Inb (STATUS) & 0x1F; error = status & 0x08; } if (error) { DBG (0, "Read error (%s:%d)\n", __FILE__, __LINE__); return 0; } } /* from here, we read 1 byte, then size/4-1 32 bits words, and then 3 bytes, pausing on ERROR bit of STATUS */ size -= 4; /* sanity test, seems to be wrongly handled ... */ if (size == 0) { DBG (0, "case not handled! (%s:%d)\n", __FILE__, __LINE__); return 0; } word = 0; error = 0; read += size; do { do { Insb (EPPDATA, dest, 1); size--; dest++; readstatus: if (size > 0) { status = Inb (STATUS) & 0x1F; word = status & 0x10; error = status & 0x08; } } while ((size > 0) && (!error) && (!word)); } while ((size < 4) && (!error) && (size > 0)); /* here size=0 or error=8 or word=0x10 */ if ((word) && (!error) && (size)) { if (epp32) Insw (EPPDATA, dest, 1); else Insb (EPPDATA, dest, 4); dest += 4; size -= 4; if (size != 0) error = 0x08; } if (!error) { c = 0; error = Inb (STATUS) & 0x08; if (error) c = WaitOnError (); } else { /* 8282 */ c = WaitOnError (); if (c == 0) goto readstatus; } if (c == 1) { read -= size; } else { read += 3; size = 3; do { do { Insb (EPPDATA, dest, 1); dest++; size--; if (size) { error = Inb (STATUS) & 0x08; if (!error) error = Inb (STATUS) & 0x08; } } while ((size > 0) && (!error)); c = 0; if (error) c = WaitOnError (); } while ((size > 0) && (c == 0)); } /* end reading */ control = Inb (CONTROL) & 0x1F; Outb (CONTROL, control); EPPBlockMode (0xA0); control = Inb (CONTROL) & 0x1F; Outb (CONTROL, control | 0x20); Insb (EPPDATA, dest, 1); read++; control = Inb (CONTROL) & 0x1F; Outb (CONTROL, control); return read; } int pausedBufferRead (int size, unsigned char *dest) { EPPBlockMode (0x80); #ifdef HAVE_LINUX_PPDEV_H if (sanei_umax_pp_getparport () > 0) return ParportpausedBufferRead (size, dest); #endif /* only EPP hardware access for now */ if (gMode == UMAX_PP_PARPORT_EPP) return DirectpausedBufferRead (size, dest); return 0; } /* returns 1 on success, 0 otherwise */ static int sendWord1220P (int *cmd) { int i; int reg; int try = 0; /* send header */ reg = registerRead (0x19) & 0xF8; retry: registerWrite (0x1C, 0x55); reg = registerRead (0x19) & 0xF8; registerWrite (0x1C, 0xAA); reg = registerRead (0x19) & 0xF8; /* sync when needed */ if ((reg & 0x08) == 0x00) { reg = registerRead (0x1C); DBG (16, "UTA: reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); if (((reg & 0x10) != 0x10) && (reg != 0x6B) && (reg != 0xAB) && (reg != 0x23)) { DBG (0, "sendWord failed (reg1C=0x%02X) (%s:%d)\n", reg, __FILE__, __LINE__); return 0; } for (i = 0; i < 10; i++) { usleep (1000); reg = registerRead (0x19) & 0xF8; if (reg != 0xC8) { DBG (0, "Unexpected reg19=0x%2X (%s:%d)\n", reg, __FILE__, __LINE__); } } do { if ((reg != 0xC0) && (reg != 0xC8)) { DBG (0, "Unexpected reg19=0x%2X (%s:%d)\n", reg, __FILE__, __LINE__); } /* 0xF0 certainly means error */ if ((reg == 0xC0) || (reg == 0xD0)) { try++; goto retry; } reg = registerRead (0x19) & 0xF8; } while (reg != 0xC8); } /* send word */ i = 0; while ((reg == 0xC8) && (cmd[i] != -1)) { registerWrite (0x1C, cmd[i]); i++; reg = registerRead (0x19) & 0xF8; } TRACE (16, "sendWord() passed "); if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "sendWord failed got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n", reg, __FILE__, __LINE__); DBG (0, "Blindly going on .....\n"); } if (((reg == 0xC0) || (reg == 0xD0)) && (cmd[i] != -1)) { DBG (0, "sendWord failed: short send (%s:%d)\n", __FILE__, __LINE__); return 0; } reg = registerRead (0x1C); DBG (16, "sendWord, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); /* model 0x07 has always the last bit set to 1, and even bit 1 */ /* when UTA is present, we get 0x6B there */ scannerStatus = reg & 0xFC; if (scannerStatus == 0x68) hasUTA = 1; reg = reg & 0x10; if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8)) { DBG (0, "sendWord failed: acknowledge not received (%s:%d)\n", __FILE__, __LINE__); return 0; } if (try) { DBG (0, "sendWord retry success (retry %d time%s) ... (%s:%d)\n", try, (try > 1) ? "s" : "", __FILE__, __LINE__); } return 1; } /* returns 1 on success, 0 otherwise */ static int SPPsendWord610p (int *cmd) { int i, j; int tmp, status; #ifdef HAVE_LINUX_PPDEV_H int exmode, mode, rc, fd; #endif connect610p (); #ifdef HAVE_LINUX_PPDEV_H fd = sanei_umax_pp_getparport (); if (fd > 0) { rc = ioctl (fd, PPGETMODE, &exmode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); mode = IEEE1284_MODE_COMPAT; rc = ioctl (fd, PPSETMODE, &mode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); } #endif Outb (DATA, 0x55); Outb (CONTROL, 0x05); status = Inb (STATUS) & 0xF8; if (status != 0x88) { DBG (0, "SPPsendWord610p found 0x%02X expected 0x88 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (CONTROL, 0x04); Outb (DATA, 0xAA); Outb (CONTROL, 0x05); status = Inb (STATUS) & 0xF8; if (status != 0x88) { DBG (0, "SPPsendWord610p found 0x%02X expected 0x88 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (CONTROL, 0x04); for (i = 0; i < 4; i++) { Outb (DATA, cmd[i]); Outb (CONTROL, 0x05); status = Inb (STATUS) & 0xF8; if (status != 0x88) { DBG (0, "SPPsendWord610p found 0x%02X expected 0x88 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (CONTROL, 0x04); } Outb (CONTROL, 0x07); Outb (DATA, 0xFF); tmp = Inb (DATA); if (tmp != 0xFF) { DBG (0, "SPPsendWord610p found 0x%X expected 0xFF (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } status = Inb (STATUS) & 0xF8; j = 0; while ((j < 256) && (status & 0x08)) { j++; status = Inb (STATUS) & 0xF8; } if ((status != 0x80) && (status != 0xA0)) { DBG (0, "SPPsendWord610p found 0x%X expected 0x80 or 0xA0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (DATA, 0x7F); status = Inb (STATUS) & 0xF8; if (status != 0xC0) { DBG (0, "SPPsendWord610p found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (DATA, 0xFF); if (cmd[3] == 0xC2) { Outb (CONTROL, 0x07); Outb (DATA, 0xFF); tmp = Inb (DATA); if (tmp != 0xFF) { DBG (0, "SPPsendWord610p found 0x%X expected 0xFF (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } status = Inb (STATUS) & 0xF8; if ((status != 0x80) && (status != 0xA0)) { DBG (0, "SPPsendWord610p found 0x%X expected 0x80 or 0xA0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (DATA, 0x7F); status = Inb (STATUS) & 0xF8; if (status != 0xC0) { DBG (0, "SPPsendWord610p found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } Outb (DATA, 0xFF); } #ifdef HAVE_LINUX_PPDEV_H fd = sanei_umax_pp_getparport (); if (fd > 0) { rc = ioctl (fd, PPSETMODE, &exmode); if (rc) DBG (0, "ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); } #endif disconnect610p (); return 1; } /* returns 1 on success, 0 otherwise */ static int EPPsendWord610p (int *cmd) { int i; int tmp, control; /* send magic tag */ tmp = Inb (STATUS) & 0xF8; if (tmp != 0xC8) { DBG (0, "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } /* sets to EPP, and get sure that data direction is forward */ tmp = (Inb (CONTROL) & 0x44) | 0x44; /* !! */ Outb (CONTROL, tmp); Outb (EPPDATA, 0x55); /* bit0 is timeout bit in EPP mode, should we take care of it ? */ tmp = Inb (STATUS) & 0xF8; if (tmp != 0xC8) { DBG (0, "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } tmp = (Inb (CONTROL) & 0x44) | 0x44; Outb (CONTROL, tmp); Outb (EPPDATA, 0xAA); control = (Inb (CONTROL) & 0xE0) | 0xE4; Outb (CONTROL, control); /* bit 7 + data reverse + reset */ for (i = 0; i < 10; i++) { tmp = Inb (STATUS) & 0xF8; if (tmp != 0xC8) { DBG (0, "EPPsendWord610p failed, expected tmp=0xC8 , found 0x%02X (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } } i = 0; while ((tmp == 0xC8) && (cmd[i] != -1)) { tmp = Inb (STATUS) & 0xF8; control = (Inb (CONTROL) & 0x44) | 0x44; /* !! */ Outb (CONTROL, control); Outb (EPPDATA, cmd[i]); i++; } /* end */ Outb (DATA, 0xFF); control = (Inb (CONTROL) & 0x44) | 0xE4; Outb (CONTROL, control); /* data reverse + ????? */ tmp = Inb (STATUS) & 0xF8; if (tmp == 0xC8) { for (i = 0; i < 9; i++) tmp = Inb (STATUS) & 0xF8; scannerStatus = tmp; } else { scannerStatus = Inb (EPPDATA); } if ((tmp != 0xC0) && (tmp != 0xD0)) { DBG (0, "EPPsendWord610p failed got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } return 1; } /* * 0: failure * 1: success */ static int sendWord (int *cmd) { switch (sanei_umax_pp_getastra ()) { case 610: return sendLength610p (cmd); case 1220: case 1600: case 2000: default: return sendWord1220P (cmd); } } /******************************************************************************/ /* ringScanner: returns 1 if scanner present, else 0 */ /******************************************************************************/ /* * in fact this function is really close to CPP macro in * /usr/src/linux/drivers/block/paride/epat.c ..... * we have almost CPP(8) */ static int ringScanner (int count, unsigned long delay) { int status; int data; int control; int ret = 1; /* save state */ data = Inb (DATA); control = Inb (CONTROL) & 0x1F; /* send -irq,+reset */ Outb (CONTROL, (control & 0xF) | 0x4); /* unhandled case */ if (g674 == 1) { DBG (1, "OUCH! %s:%d\n", __FILE__, __LINE__); return 0; } /* send ring string */ Outb (DATA, 0x22); usleep (delay); Outb (DATA, 0x22); usleep (delay); if (count == 5) { Outb (DATA, 0x22); usleep (delay); Outb (DATA, 0x22); usleep (delay); Outb (DATA, 0x22); usleep (delay); } Outb (DATA, 0xAA); usleep (delay); Outb (DATA, 0xAA); usleep (delay); if (count == 5) { Outb (DATA, 0xAA); usleep (delay); Outb (DATA, 0xAA); usleep (delay); Outb (DATA, 0xAA); usleep (delay); } Outb (DATA, 0x55); usleep (delay); Outb (DATA, 0x55); usleep (delay); if (count == 5) { Outb (DATA, 0x55); usleep (delay); Outb (DATA, 0x55); usleep (delay); Outb (DATA, 0x55); usleep (delay); } Outb (DATA, 0x00); usleep (delay); Outb (DATA, 0x00); usleep (delay); if (count == 5) { Outb (DATA, 0x00); usleep (delay); Outb (DATA, 0x00); usleep (delay); Outb (DATA, 0x00); usleep (delay); } Outb (DATA, 0xFF); usleep (delay); Outb (DATA, 0xFF); usleep (delay); if (count == 5) { Outb (DATA, 0xFF); usleep (delay); Outb (DATA, 0xFF); usleep (delay); Outb (DATA, 0xFF); usleep (delay); } /* OK ? */ status = Inb (STATUS) & 0xF8; usleep (delay); if ((status & 0xB8) != 0xB8) { DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__, __LINE__); ret = 0; } /* if OK send 0x87 */ if (ret) { Outb (DATA, 0x87); usleep (delay); Outb (DATA, 0x87); usleep (delay); if (count == 5) { Outb (DATA, 0x87); usleep (delay); Outb (DATA, 0x87); usleep (delay); Outb (DATA, 0x87); usleep (delay); } status = Inb (STATUS); /* status = 126 when scanner not connected .... */ if ((status & 0xB8) != 0x18) { DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__, __LINE__); ret = 0; } } /* if OK send 0x78 */ if (ret) { Outb (DATA, 0x78); usleep (delay); Outb (DATA, 0x78); usleep (delay); if (count == 5) { Outb (DATA, 0x78); usleep (delay); Outb (DATA, 0x78); usleep (delay); Outb (DATA, 0x78); usleep (delay); } status = Inb (STATUS); if ((status & 0x30) != 0x30) { DBG (1, "status %d doesn't match! %s:%d\n", status, __FILE__, __LINE__); ret = 0; } } /* ring OK, send termination */ if (ret) { Outb (DATA, 0x08); usleep (delay); Outb (DATA, 0x08); usleep (delay); if (count == 5) { Outb (DATA, 0x08); usleep (delay); Outb (DATA, 0x08); usleep (delay); Outb (DATA, 0x08); usleep (delay); } Outb (DATA, 0xFF); usleep (delay); Outb (DATA, 0xFF); usleep (delay); if (count == 5) { Outb (DATA, 0xFF); usleep (delay); Outb (DATA, 0xFF); usleep (delay); Outb (DATA, 0xFF); usleep (delay); } } /* restore state */ Outb (CONTROL, control); Outb (DATA, data); return ret; } /*****************************************************************************/ /* test some version : returns 1 on success, 0 otherwise */ /*****************************************************************************/ static int testVersion (int no) { int data; int status; int control; int count; int tmp; data = Inb (DATA); control = Inb (CONTROL) & 0x3F; Outb (CONTROL, (control & 0x1F) | 0x04); /* send magic sequence */ Outb (DATA, 0x22); Outb (DATA, 0x22); Outb (DATA, 0x22); Outb (DATA, 0x22); Outb (DATA, 0xAA); Outb (DATA, 0xAA); Outb (DATA, 0xAA); Outb (DATA, 0xAA); Outb (DATA, 0xAA); Outb (DATA, 0xAA); Outb (DATA, 0x55); Outb (DATA, 0x55); Outb (DATA, 0x55); Outb (DATA, 0x55); Outb (DATA, 0x55); Outb (DATA, 0x55); Outb (DATA, 0x00); Outb (DATA, 0x00); Outb (DATA, 0x00); Outb (DATA, 0x00); Outb (DATA, 0x00); Outb (DATA, 0x00); Outb (DATA, 0xFF); Outb (DATA, 0xFF); Outb (DATA, 0xFF); Outb (DATA, 0xFF); Outb (DATA, 0xFF); Outb (DATA, 0xFF); Outb (DATA, 0x87); Outb (DATA, 0x87); Outb (DATA, 0x87); Outb (DATA, 0x87); Outb (DATA, 0x87); Outb (DATA, 0x87); Outb (DATA, 0x78); Outb (DATA, 0x78); Outb (DATA, 0x78); Outb (DATA, 0x78); Outb (DATA, 0x78); Outb (DATA, 0x78); tmp = no | 0x88; Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); /* test status */ status = Inb (STATUS); status = Inb (STATUS); if ((status & 0xB8) != 0) { /* 1600P fails here */ DBG (64, "status %d doesn't match! %s:%d\n", status, __FILE__, __LINE__); Outb (CONTROL, control); Outb (DATA, data); return 0; } count = 0xF0; do { tmp = no | 0x80; Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); tmp = no | 0x88; Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); Outb (DATA, tmp); /* command received ? */ status = Inb (STATUS); status = ((status << 1) & 0x70) | (status & 0x80); if (status != count) { /* since failure is expected, we dont't alaways print */ /* this message ... */ DBG (2, "status %d doesn't match count 0x%X! %s:%d\n", status, count, __FILE__, __LINE__); Outb (CONTROL, control); Outb (DATA, data); return 0; } /* next */ count -= 0x10; } while (count > 0); /* restore port , successful exit */ Outb (CONTROL, control); Outb (DATA, data); return 1; } /* sends len bytes to scanner */ /* needs data channel to be set up */ /* returns 1 on success, 0 otherwise */ static int sendLength (int *cmd, int len) { int i; int reg, wait; int try = 0; /* send header */ retry: wait = registerRead (0x19) & 0xF8; registerWrite (0x1C, 0x55); reg = registerRead (0x19) & 0xF8; registerWrite (0x1C, 0xAA); reg = registerRead (0x19) & 0xF8; /* sync when needed */ if ((wait & 0x08) == 0x00) { reg = registerRead (0x1C); while (((reg & 0x10) != 0x10) && (reg != 0x6B) && (reg != 0xAB) && (reg != 0x23)) { DBG (0, "sendLength failed, expected reg & 0x10=0x10 , found 0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); if (try > 10) { DBG (0, "Aborting...\n"); return 0; } else { DBG (0, "Retrying ...\n"); } /* resend */ epilogue (); prologue (0x10); try++; goto retry; } for (i = 0; i < 10; i++) { reg = registerRead (0x19) & 0xF8; if (reg != 0xC8) { DBG (0, "Unexpected reg19=0x%2X (%s:%d)\n", reg, __FILE__, __LINE__); /* 0xF0 certainly means error */ if ((reg == 0xC0) || (reg == 0xD0) || (reg == 0x80)) { /* resend */ try++; if (try > 20) { DBG (0, "sendLength retry failed (%s:%d)\n", __FILE__, __LINE__); return 0; } epilogue (); sendCommand (0x00); sendCommand (0xE0); Outb (DATA, 0x00); Outb (CONTROL, 0x01); Outb (CONTROL, 0x04); sendCommand (0x30); prologue (0x10); goto retry; } } } do { if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0xC8)) { /* status has changed while waiting */ /* but it's too early */ DBG (0, "Unexpected reg19=0x%2X (%s:%d)\n", reg, __FILE__, __LINE__); } /* 0xF0 certainly means error */ if ((reg == 0xC0) || (reg == 0xD0) || (reg == 0x80)) { /* resend */ try++; epilogue (); sendCommand (0x00); sendCommand (0xE0); Outb (DATA, 0x00); Outb (CONTROL, 0x01); Outb (CONTROL, 0x04); sendCommand (0x30); prologue (0x10); goto retry; } reg = registerRead (0x19) & 0xF8; } while (reg != 0xC8); } /* send bytes */ i = 0; while ((reg == 0xC8) && (i < len)) { /* write byte */ registerWrite (0x1C, cmd[i]); reg = registerRead (0x19) & 0xF8; /* 1B handling: escape it to confirm value */ if (cmd[i] == 0x1B) { registerWrite (0x1C, cmd[i]); reg = registerRead (0x19) & 0xF8; } i++; } DBG (16, "sendLength, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "sendLength failed got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n", reg, __FILE__, __LINE__); DBG (0, "Blindly going on .....\n"); } /* check if 'finished status' received too early */ if (((reg == 0xC0) || (reg == 0xD0)) && (i != len)) { DBG (0, "sendLength failed: sent only %d bytes out of %d (%s:%d)\n", i, len, __FILE__, __LINE__); return 0; } reg = registerRead (0x1C); DBG (16, "sendLength, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); /* model 0x07 has always the last bit set to 1 */ scannerStatus = reg & 0xFC; reg = reg & 0x10; if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8)) { DBG (0, "sendLength failed: acknowledge not received (%s:%d)\n", __FILE__, __LINE__); return 0; } if (try) { DBG (0, "sendLength retry success (retry %d time%s) ... (%s:%d)\n", try, (try > 1) ? "s" : "", __FILE__, __LINE__); } return 1; } /* sends data bytes to scanner */ /* needs data channel to be set up */ /* returns 1 on success, 0 otherwise */ static int sendData610p (int *cmd, int len) { int i, status, j; i = 0; status = 0xC8; /* while ((i < len) && ((status & 0x08) == 0x08)) XXX STEF XXX */ while (i < len) { /* escape special values */ if (cmd[i] == 0x1B) status = putByte610p (0x1B); if (i > 0) { if ((cmd[i] == 0xAA) && (cmd[i - 1] == 0x55)) status = putByte610p (0x1B); } /* regular values */ status = putByte610p (cmd[i]); i++; } j = 0; while ((status & 0x08) && (j < 256)) { status = getStatus610p (); j++; } if ((status != 0xC0) && (status != 0xD0)) { DBG (0, "sendData610p() failed, status=0x%02X, expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } /* check if 'finished status' received too early */ if (i < len) { DBG (0, "sendData610p failed: sent only %d bytes out of %d (%s:%d)\n", i, len, __FILE__, __LINE__); return 0; } return 1; } /* sends data bytes to scanner */ /* needs data channel to be set up */ /* returns 1 on success, 0 otherwise */ static int sendData (int *cmd, int len) { int i; int reg; if (sanei_umax_pp_getastra () == 610) return sendData610p (cmd, len); /* send header */ reg = registerRead (0x19) & 0xF8; /* send bytes */ i = 0; while ((reg == 0xC8) && (i < len)) { /* write byte */ registerWrite (0x1C, cmd[i]); reg = registerRead (0x19) & 0xF8; /* 1B handling: escape it to confirm value */ if (cmd[i] == 0x1B) { registerWrite (0x1C, 0x1B); reg = registerRead (0x19) & 0xF8; } /* escape 55 AA pattern by adding 1B */ if ((i < len - 1) && (cmd[i] == 0x55) && (cmd[i + 1] == 0xAA)) { registerWrite (0x1C, 0x1B); reg = registerRead (0x19) & 0xF8; } /* next value */ i++; } DBG (16, "sendData, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "sendData failed got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n", reg, __FILE__, __LINE__); DBG (0, "Blindly going on .....\n"); } /* check if 'finished status' received too early */ if (((reg == 0xC0) || (reg == 0xD0)) && (i < len)) { DBG (0, "sendData failed: sent only %d bytes out of %d (%s:%d)\n", i, len, __FILE__, __LINE__); return 0; } reg = registerRead (0x1C); DBG (16, "sendData, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); /* model 0x07 has always the last bit set to 1 */ scannerStatus = reg & 0xFC; reg = reg & 0x10; if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8) && (scannerStatus != 0x20)) { DBG (0, "sendData failed: acknowledge not received (%s:%d)\n", __FILE__, __LINE__); return 0; } return 1; } /* receive data bytes from scanner */ /* needs data channel to be set up */ /* returns 1 on success, 0 otherwise */ /* uses pausedBufferRead */ static int pausedReadData (int size, unsigned char *dest) { int reg; int tmp; int read; REGISTERWRITE (0x0E, 0x0D); REGISTERWRITE (0x0F, 0x00); reg = registerRead (0x19) & 0xF8; if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "Unexpected reg19: 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n", reg, __FILE__, __LINE__); return 0; } if (gMode == UMAX_PP_PARPORT_ECP) { REGISTERWRITE (0x1A, 0x44); } REGISTERREAD (0x0C, 0x04); REGISTERWRITE (0x0C, 0x44); /* sets data direction ? */ if (gMode == UMAX_PP_PARPORT_ECP) { compatMode (); Outb (CONTROL, 0x04); /* reset ? */ ECPSetBuffer (size); read = ECPbufferRead (size, dest); DBG (16, "ECPbufferRead(%d,dest) passed (%s:%d)\n", size, __FILE__, __LINE__); REGISTERWRITE (0x1A, 0x84); } else { read = pausedBufferRead (size, dest); } if (read < size) { DBG (16, "pausedBufferRead(%d,dest) failed, only got %d bytes (%s:%d)\n", size, read, __FILE__, __LINE__); return 0; } DBG (16, "pausedBufferRead(%d,dest) passed (%s:%d)\n", size, __FILE__, __LINE__); REGISTERWRITE (0x0E, 0x0D); REGISTERWRITE (0x0F, 0x00); return 1; } /* receive data bytes from scanner */ /* needs data channel to be set up */ /* returns 1 on success, 0 otherwise */ static int receiveData610p (int *cmd, int len) { int i; int status; i = 0; status = 0xD0; byteMode (); while (i < len) { status = Inb (STATUS) & 0xF8; Outb (CONTROL, 0x26); /* data reverse+ 'reg' */ cmd[i] = Inb (DATA); Outb (CONTROL, 0x24); /* data reverse+ 'reg' */ i++; } if (status != 0xC0) { DBG (0, "receiveData610p failed got 0x%02X instead of 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); DBG (0, "Blindly going on .....\n"); } /* check if 'finished status' received to early */ if ((status == 0xC0) && (i != len)) { DBG (0, "receiveData610p failed: received only %d bytes out of %d (%s:%d)\n", i, len, __FILE__, __LINE__); return 0; } return 1; } /* receive data bytes from scanner */ /* needs data channel to be set up */ /* returns 1 on success, 0 otherwise */ static int receiveData (int *cmd, int len) { int i; int reg; /* send header */ reg = registerRead (0x19) & 0xF8; /* send bytes */ i = 0; while (((reg == 0xD0) || (reg == 0xC0)) && (i < len)) { /* write byte */ cmd[i] = registerRead (0x1C); reg = registerRead (0x19) & 0xF8; i++; } DBG (16, "receiveData, reg19=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "sendData failed got 0x%02X instead of 0xC0 or 0xD0 (%s:%d)\n", reg, __FILE__, __LINE__); DBG (0, "Blindly going on .....\n"); } /* check if 'finished status' received to early */ if (((reg == 0xC0) || (reg == 0xD0)) && (i != len)) { DBG (0, "receiveData failed: received only %d bytes out of %d (%s:%d)\n", i, len, __FILE__, __LINE__); return 0; } reg = registerRead (0x1C); DBG (16, "receiveData, reg1C=0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); /* model 0x07 has always the last bit set to 1 */ scannerStatus = reg & 0xF8; reg = reg & 0x10; if ((reg != 0x10) && (scannerStatus != 0x68) && (scannerStatus != 0xA8)) { DBG (0, "receiveData failed: acknowledge not received (%s:%d)\n", __FILE__, __LINE__); return 0; } return 1; } /* 1=success, 0 failed */ static int fonc001 (void) { int i; int res; int reg; res = 1; while (res == 1) { registerWrite (0x1A, 0x0C); registerWrite (0x18, 0x40); /* send 0x06 */ registerWrite (0x1A, 0x06); for (i = 0; i < 10; i++) { reg = registerRead (0x19) & 0xF8; if ((reg & 0x78) == 0x38) { res = 0; break; } } if (res == 1) { registerWrite (0x1A, 0x00); registerWrite (0x1A, 0x0C); } } /* send 0x07 */ registerWrite (0x1A, 0x07); res = 1; for (i = 0; i < 10; i++) { reg = registerRead (0x19) & 0xF8; if ((reg & 0x78) == 0x38) { res = 0; break; } } if (res != 0) return 0; /* send 0x04 */ registerWrite (0x1A, 0x04); res = 1; for (i = 0; i < 10; i++) { reg = registerRead (0x19) & 0xF8; if ((reg & 0xF8) == 0xF8) { res = 0; break; } } if (res != 0) return 0; /* send 0x05 */ registerWrite (0x1A, 0x05); res = 1; for (i = 0; i < 10; i++) { reg = registerRead (0x1A); if (reg == 0x05) { res = 0; break; } } if (res != 0) return 0; /* end */ registerWrite (0x1A, 0x84); return 1; } /* 1 OK, 0 failed */ static int foncSendWord (int *cmd) { prologue (0x10); if (sendWord (cmd) == 0) { DBG (0, "sendWord(cmd) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } epilogue (); return 1; } static int cmdSetDataBuffer (int *data) { int cmd1[] = { 0x00, 0x00, 0x22, 0x88, -1 }; /* 34 bytes write on channel 8 */ int cmd2[] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -1 }; int cmd3[] = { 0x00, 0x08, 0x00, 0x84, -1 }; /* 2048 bytes size write on channel 4 (data) */ int cmd4[] = { 0x00, 0x08, 0x00, 0xC4, -1 }; /* 2048 bytes size read on channel 4 (data) */ int i; unsigned char dest[2048]; /* cmdSet(8,34,cmd2), but without prologue/epilogue */ /* set block length to 34 bytes on 'channel 8' */ sendWord (cmd1); DBG (16, "sendWord(cmd1) passed (%s:%d) \n", __FILE__, __LINE__); /* sendData */ sendData (cmd2, 0x22); DBG (16, "sendData(cmd2) passed (%s:%d) \n", __FILE__, __LINE__); if (DBG_LEVEL >= 128) { bloc8Decode (cmd2); } /* set block length to 2048, write on 'channel 4' */ sendWord (cmd3); DBG (16, "sendWord(cmd3) passed (%s:%d) \n", __FILE__, __LINE__); if (sendData (data, 2048) == 0) { DBG (0, "sendData(data,%d) failed (%s:%d)\n", 2048, __FILE__, __LINE__); return 0; } TRACE (16, "sendData(data,2048) passed ..."); /* read back all data sent to 'channel 4' */ sendWord (cmd4); DBG (16, "sendWord(cmd4) passed (%s:%d) \n", __FILE__, __LINE__); if (pausedReadData (2048, dest) == 0) { DBG (16, "pausedReadData(2048,dest) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "pausedReadData(2048,dest) passed (%s:%d)\n", __FILE__, __LINE__); /* dest should hold the same data than donnees */ for (i = 0; i < 2047; i++) { if (data[i] != (int) (dest[i])) { DBG (0, "Warning data read back differs: expected %02X found dest[%d]=%02X ! (%s:%d)\n", data[i], i, dest[i], __FILE__, __LINE__); } } return 1; } /* 1: OK 0: end session failed */ int sanei_umax_pp_endSession (void) { int zero[5] = { 0, 0, 0, 0, -1 }; if (sanei_umax_pp_getastra () != 610) { prologue (0x00); sendWord (zero); epilogue (); sanei_umax_pp_cmdSync (0xC2); sanei_umax_pp_cmdSync (0x00); /* cancels any pending operation */ sanei_umax_pp_cmdSync (0x00); /* cancels any pending operation */ } else { CMDSYNC (0x00); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSYNC (0x00); } compatMode (); /* restore port state */ Outb (DATA, gData); Outb (CONTROL, gControl); /* OUF */ DBG (1, "End session done ...\n"); return 1; } /* initialize scanner with default values * and do head re-homing if needed */ int initScanner610p (int recover) { int first, rc, x; int cmd55AA[9] = { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, -1 }; int cmd02[17] = { 0x02, 0x80, 0x00, 0x40, 0x30, 0x00, 0xC0, 0x2F, 0x2F, 0x07, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x00, -1 }; int op01[17] = { 0x01, 0x00, 0x32, 0x70, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x00, -1 }; int op11[17] = { 0x01, 0x80, 0x0C, 0x70, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x01, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x00, -1 }; int op21[17] = { 0x01, 0x00, 0x01, 0x40, 0x30, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00, 0x00, 0x80, 0xF4, 0x00, -1 }; int op31[17] = { 0x01, 0x00, 0x39, 0x73, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00, 0x00, 0x80, 0xB4, 0x00, -1 }; int op02[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00, 0x76, 0x00, 0x75, 0xEF, 0x06, 0x00, 0x00, 0xF6, 0x4D, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x1B, -1 }; int op22[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x1B, -1 }; int op03[9] = { 0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0xFF, 0xFF, -1 }; struct timeval tv; byteMode (); /* just to get sure */ first = 0; rc = inquire (); /* get time to handle settle time delay */ gettimeofday (&tv, NULL); gTime = tv.tv_sec; /* default delay */ gDelay = 5; if (rc == 0) { DBG (0, "inquire() failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } if (rc == 2) { /* same value used by windows driver */ gDelay = 45; DBG (1, "inquire() signals re-homing needed ... (%s:%d) \n", __FILE__, __LINE__); first = 1; } DBG (1, "inquire() passed ... (%s:%d) \n", __FILE__, __LINE__); rc = loadDefaultTables (); if (rc == 0) { DBG (0, "loadDefaultTables() failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (1, "loadDefaultTables() passed ... (%s:%d) \n", __FILE__, __LINE__); if (recover) first = 1; CMDSETGET (2, 0x10, cmd02); CMDSETGET (1, 0x08, cmd55AA); if (!first) { CMDSYNC (0x00); CMDSYNC (0xC2); CMDSYNC (0x00); DBG (1, "initScanner610p done ...\n"); return 1; } /* here we do re-homing * since it is first probe or recover */ /* move forward */ CMDSYNC (0xC2); if (!recover) { CMDSETGET (2, 0x10, op01); CMDSETGET (8, 0x22, op02); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, op03); CMDSYNC (0x40); CMDSYNC (0xC2); sleep (2); } /* move backward */ CMDSETGET (2, 0x10, op11); CMDSETGET (8, 0x22, op02); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSYNC (0x00); CMDSETGET (4, 0x08, op03); CMDSYNC (0x40); CMDSYNC (0xC2); sleep (2); /* means 'CONTINUE MOVE' */ CMDSYNC (0x00); while ((scannerStatus & MOTOR_BIT) == 0) { CMDSYNC (0xC2); CMDSETGET (2, 0x10, op21); CMDSETGET (8, 0x22, op22); CMDSYNC (0x40); usleep (20000); } CMDSYNC (0xC2); CMDSYNC (0x00); /* send head away */ if (!recover) { CMDSETGET (2, 0x10, op31); CMDSETGET (8, 0x22, op02); if (DBG_LEVEL > 8) { bloc2Decode (op31); bloc8Decode (op02); } CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, op03); CMDSYNC (0x40); CMDSYNC (0xC2); sleep (9); } CMDSYNC (0x00); /* this code has been added, without corresponding logs/ * it seem I just can't found 'real' parking command ... */ /* send park command */ if (sanei_umax_pp_park () == 0) { TRACE (0, "sanei_umax_pp_park failed! "); return 0; } /* and wait it to succeed */ if (sanei_umax_pp_parkWait () == 0) { TRACE (0, "sanei_umax_pp_parkWait failed! "); return 0; } /* override gamma table with 610P defaults */ for (x = 0; x < 256; x++) { ggRed[x] = x; ggGreen[x] = x; ggBlue[x] = x; } DBG (1, "initScanner610p done ...\n"); return 1; } /* 1: OK 2: homing happened 3: scanner busy 0: init failed init transport layer init scanner */ int sanei_umax_pp_initScanner (int recover) { int i; int status; int readcmd[64]; /* in umax1220u, this buffer is opc[16] */ int sentcmd[17] = { 0x02, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00, 0x2F, 0x2F, 0x07, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x00, -1 }; int cmdA7[9] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, -1 }; if (sanei_umax_pp_getastra () == 610) return initScanner610p (recover); if (getModel () == 0x07) sentcmd[15] = 0x00; else sentcmd[15] = 0x18; /* fails here if there is an unfinished previous scan */ CMDSETGET (0x02, 16, sentcmd); /* needs some init */ if (sentcmd[15] == 0x18) { sentcmd[15] = 0x00; /* was 0x18 */ CMDSETGET (0x02, 16, sentcmd); /* in umax1220u, this buffer does not exist */ CMDSETGET (0x01, 8, cmdA7); } /* ~ opb3: inquire status */ CMDGET (0x08, 36, readcmd); if (DBG_LEVEL >= 32) { bloc8Decode (readcmd); } DBG (16, "cmdGet(0x08,36,readcmd) passed (%s:%d)\n", __FILE__, __LINE__); /* is the scanner busy parking ? */ status = sanei_umax_pp_scannerStatus (); DBG (8, "INQUIRE SCANNER STATUS IS 0x%02X (%s:%d)\n", status, __FILE__, __LINE__); if ((!recover) && (status & MOTOR_BIT) == 0x00) { DBG (1, "Warning: scanner motor on, giving up ... (%s:%d)\n", __FILE__, __LINE__); return 3; } /* head homing needed ? */ if ((readcmd[34] != 0x1A) || (recover == 1)) { /* homing needed, readcmd[34] should be 0x48 */ int op01[17] = { 0x01, 0x00, 0x32, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x17, 0x05, 0x00, 0x00, 0x00, 0x80, 0xE4, 0x00, -1 }; int op05[17] = { 0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x13, 0x05, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x00, -1 }; int op02[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00, 0x16, 0x00, 0x70, 0x9F, 0x06, 0x00, 0x00, 0xF6, 0x4D, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x0B, 0x1A, 0x00, -1 }; int op04[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x0B, 0x1A, 0x00, -1 }; int op03[9] = { 0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0xFF, 0xFF, -1 }; CMDSYNC (0xC2); CMDSETGET (0x02, 16, op01); CMDSETGET (0x08, 36, op02); if (!recover) { CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (0x04, 8, op03); CMDSYNC (0x40); do { sleep (1); CMDSYNC (0xC2); } while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90); op01[2] = 0x1E; op01[9] = 0x01; CMDSETGET (0x02, 16, op01); CMDSETGET (0x08, 36, op02); CMDSYNC (0x00); CMDSYNC (0x00); CMDSETGET (0x04, 8, op03); CMDSYNC (0x40); do { sleep (1); CMDSYNC (0xC2); } while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90); CMDSYNC (0x00); } for (i = 0; i < 4; i++) { do { usleep (500000); CMDSYNC (0xC2); status = sanei_umax_pp_scannerStatus (); status = status & 0x10; } while (status != 0x10); /* was 0x90 */ CMDSETGET (0x02, 16, op05); CMDSETGET (0x08, 36, op04); CMDSYNC (0x40); status = sanei_umax_pp_scannerStatus (); DBG (16, "loop %d passed, status=0x%02X (%s:%d)\n", i, status, __FILE__, __LINE__); } /* get head back home ... */ do { i++; do { usleep (500000); CMDSYNC (0xC2); status = sanei_umax_pp_scannerStatus (); status = status & 0x10; } while (status != 0x10); /* was 0x90 */ CMDSETGET (0x02, 16, op05); CMDSETGET (0x08, 36, op04); CMDSYNC (0x40); status = sanei_umax_pp_scannerStatus (); DBG (16, "loop %d passed, status=0x%02X (%s:%d)\n", i, status, __FILE__, __LINE__); } while ((status & MOTOR_BIT) == 0x00); /* 0xD0 when head is back home */ do { usleep (500000); CMDSYNC (0xC2); } while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90); /* don't do automatic home sequence on recovery */ if (!recover) { CMDSYNC (0x00); op01[2] = 0x1A; op01[3] = 0x74; /* was 0x70 */ op01[9] = 0x05; /* initial value */ op01[14] = 0xF4; /* was 0xE4 */ CMDSETGET (0x02, 16, op01); CMDSETGET (0x08, 36, op02); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (0x04, 8, op03); CMDSYNC (0x40); /* wait for automatic homing sequence */ /* to complete, thus avoiding */ /* scanning too early */ do { /* the sleep is here to prevent */ /* excessive CPU usage, can be */ /* removed, if we don't care */ sleep (3); CMDSYNC (0xC2); DBG (16, "PARKING polling status is 0x%02X (%s:%d)\n", sanei_umax_pp_scannerStatus (), __FILE__, __LINE__); } while (sanei_umax_pp_scannerStatus () == 0x90); } /* signal homing */ return 2; } /* end ... */ DBG (1, "Scanner init done ...\n"); return 1; } /* 1: OK 2: failed, try again 0: init failed initialize the transport layer */ static int initTransport610p (void) { int tmp, i; int zero[5] = { 0, 0, 0, 0, -1 }; /* test EPP availability */ connect610p (); if (sync610p () == 0) { DBG (0, "sync610p failed! Scanner not present or powered off ... (%s:%d)\n", __FILE__, __LINE__); return 0; } if (EPPsendWord610p (zero) == 0) { DBG (1, "No EPP mode detected\n"); gMode = UMAX_PP_PARPORT_BYTE; } else { DBG (1, "EPP mode detected\n"); gMode = UMAX_PP_PARPORT_EPP; } disconnect610p (); /* set up to bidirectionnal */ /* in fact we could add support for EPP */ /* but let's make 610 work first */ if (gMode == UMAX_PP_PARPORT_BYTE) { byteMode (); /* reset after failure */ /* set to data reverse */ Outb (CONTROL, 0x2C); Inb (CONTROL); for (i = 0; i < 10; i++) Outb (DATA, 0xAA); tmp = Inb (DATA); tmp = Inb (DATA); if (tmp != 0xFF) { DBG (1, "Found 0x%X expected 0xFF (%s:%d)\n", tmp, __FILE__, __LINE__); } for (i = 0; i < 4; i++) { Outb (DATA, 0x00); tmp = Inb (DATA); if (tmp != 0xFF) { DBG (1, "Found 0x%X expected 0xFF (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } Outb (DATA, 0xFF); tmp = Inb (DATA); if (tmp != 0xFF) { DBG (1, "Found 0x%X expected 0xFF (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } } TRACE (16, "RESET done... "); byteMode (); if (SPPsendWord610p (zero) == 0) { DBG (0, "SPPsendWord610p(zero) failed! (%s:%d)\n", __FILE__, __LINE__); return 0; } TRACE (16, "SPPsendWord610p(zero) passed... "); } /* OK ! */ TRACE (1, "initTransport610p done... "); return 1; } /* 1: OK 2: failed, try again 0: init failed initialize the transport layer */ static int initTransport1220P (int recover) /* ECP OK !! */ { int i, j; int reg, tmp; unsigned char *dest = NULL; int zero[5] = { 0, 0, 0, 0, -1 }; int model, nb; connect (); DBG (16, "connect() passed... (%s:%d)\n", __FILE__, __LINE__); gEPAT = 0xC7; reg = registerRead (0x0B); if (reg != gEPAT) { DBG (16, "Error! expected reg0B=0x%02X, found 0x%02X! (%s:%d) \n", gEPAT, reg, __FILE__, __LINE__); DBG (16, "Scanner needs probing ... \n"); if (sanei_umax_pp_probeScanner (recover) != 1) { return 0; } else { return 2; /* signals retry initTransport() */ } } reg = registerRead (0x0D); reg = (reg & 0xE8) | 0x43; registerWrite (0x0D, reg); REGISTERWRITE (0x0C, 0x04); reg = registerRead (0x0A); if (reg != 0x00) { if (reg != 0x1C) { DBG (0, "Warning! expected reg0A=0x00, found 0x%02X! (%s:%d) \n", reg, __FILE__, __LINE__); } else { DBG (16, "Scanner in idle state .... (%s:%d)\n", __FILE__, __LINE__); } } /* model detection: redone since we might not be probing each time ... */ /* write addr in 0x0E, read value at 0x0F */ REGISTERWRITE (0x0E, 0x01); model = registerRead (0x0F); setModel (model); REGISTERWRITE (0x0A, 0x1C); if (gMode == UMAX_PP_PARPORT_ECP) { REGISTERWRITE (0x08, 0x10); } else { REGISTERWRITE (0x08, 0x21); } REGISTERWRITE (0x0E, 0x0F); REGISTERWRITE (0x0F, 0x0C); REGISTERWRITE (0x0A, 0x1C); REGISTERWRITE (0x0E, 0x10); REGISTERWRITE (0x0F, 0x1C); if (gMode == UMAX_PP_PARPORT_ECP) { REGISTERWRITE (0x0F, 0x00); } REGISTERWRITE (0x0A, 0x11); dest = (unsigned char *) (malloc (65536)); if (dest == NULL) { DBG (0, "Failed to allocate 64 Ko !\n"); return 0; } for (i = 0; i < 256; i++) { dest[i * 2] = i; dest[i * 2 + 1] = 0xFF - i; dest[512 + i * 2] = i; dest[512 + i * 2 + 1] = 0xFF - i; } nb = 150; for (i = 0; i < nb; i++) { bufferWrite (0x400, dest); DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i, __FILE__, __LINE__); } REGISTERWRITE (0x0A, 0x18); REGISTERWRITE (0x0A, 0x11); if (gMode == UMAX_PP_PARPORT_ECP) { ECPSetBuffer (0x400); } for (i = 0; i < nb; i++) { /* XXX Compat/Byte ??? XXX */ bufferRead (0x400, dest); for (j = 0; j < 256; j++) { if (dest[j * 2] != j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", j * 2, j, dest[j * 2]); return 0; } if (dest[j * 2 + 1] != 0xFF - j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", j * 2 + 1, 0xFF - j, dest[j * 2 + 1]); return 0; } if (dest[512 + j * 2] != j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", 512 + j * 2, j, dest[512 + j * 2]); return 0; } if (dest[512 + j * 2 + 1] != 0xFF - j) { DBG (0, "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n", 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]); return 0; } } DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n", i, __FILE__, __LINE__); } REGISTERWRITE (0x0A, 0x18); /* ECP: "HEAVY" reconnect here */ if (gMode == UMAX_PP_PARPORT_ECP) { epilogue (); /* 3 line: set to initial parport state ? */ byteMode (); /*Outb (ECR, 0x20); */ Outb (DATA, 0x04); Outb (CONTROL, 0x0C); /* the following is a variant of connect(); */ Inb (ECR); Inb (ECR); byteMode (); /*Outb (ECR, 0x20); */ byteMode (); /*Outb (ECR, 0x20); */ Inb (CONTROL); Outb (CONTROL, 0x0C); Inb (DATA); sendCommand (0xE0); Outb (DATA, 0XFF); Outb (DATA, 0XFF); ClearRegister (0); WRITESLOW (0x0E, 0x0A); SLOWNIBBLEREGISTERREAD (0x0F, 0x08); /* resend value OR'ed 0x08 ? */ WRITESLOW (0x0F, 0x08); WRITESLOW (0x08, 0x10); disconnect (); prologue (0x10); } if (fonc001 () != 1) { DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (16, "fonc001() passed ... (%s:%d) \n", __FILE__, __LINE__); /* sync */ if (sendWord (zero) == 0) { DBG (0, "sendWord(zero) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "sendWord(zero) passed (%s:%d)\n", __FILE__, __LINE__); epilogue (); /* OK ! */ free (dest); DBG (1, "initTransport1220P done ...\n"); return 1; } /* 1: OK 2: failed, try again 0: init failed initialize the transport layer */ int sanei_umax_pp_initTransport (int recover) { TRACE (16, "sanei_umax_pp_initTransport"); switch (sanei_umax_pp_getastra ()) { case 610: return initTransport610p (); case 1220: case 1600: case 2000: default: return initTransport1220P (recover); } } /* 1: OK 0: probe failed */ static int probe610p (int recover) { if (initTransport610p () == 0) { DBG (0, "initTransport610p() failed (%s:%d)\n", __FILE__, __LINE__); return 0; } /* make sure we won't try 1220/200P later * since we got here, we have a 610, and in any case * NOT a 1220P/2000P, since no EPAT present */ sanei_umax_pp_setastra (610); if (initScanner610p (recover) == 0) { DBG (0, "initScanner610p() failed (%s:%d)\n", __FILE__, __LINE__); return 0; } /* successfull end ... */ DBG (1, "UMAX Astra 610p detected\n"); DBG (1, "probe610p done ...\n"); return 1; } /* * try PS2 mode * returns 1 on success, 0 on failure */ int probePS2 (unsigned char *dest) { int i, tmp; /* write/read full buffer */ for (i = 0; i < 256; i++) { WRITESLOW (0x0A, i); SLOWNIBBLEREGISTERREAD (0x0A, i); WRITESLOW (0x0A, 0xFF - i); SLOWNIBBLEREGISTERREAD (0x0A, 0xFF - i); } /* end test for nibble byte/byte mode */ /* now we try nibble buffered mode */ WRITESLOW (0x13, 0x01); WRITESLOW (0x13, 0x00); /*reset something */ WRITESLOW (0x0A, 0x11); for (i = 0; i < 10; i++) /* 10 ~ 11 ? */ { PS2bufferRead (0x400, dest); DBG (16, "Loop %d: PS2bufferRead passed ... (%s:%d)\n", i, __FILE__, __LINE__); } /* write buffer */ for (i = 0; i < 10; i++) { PS2bufferWrite (0x400, dest); DBG (16, "Loop %d: PS2bufferWrite passed ... (%s:%d)\n", i, __FILE__, __LINE__); } SLOWNIBBLEREGISTERREAD (0x0C, 0x04); WRITESLOW (0x13, 0x01); WRITESLOW (0x13, 0x00); WRITESLOW (0x0A, 0x18); return 1; } /* * try EPP 8 then 32 bits * returns 1 on success, 0 on failure */ int probeEPP (unsigned char *dest) { int tmp, i, j; int reg; /* test EPP MODE */ setEPPMode (8); gMode = UMAX_PP_PARPORT_EPP; ClearRegister (0); DBG (16, "ClearRegister(0) passed... (%s:%d)\n", __FILE__, __LINE__); WRITESLOW (0x08, 0x22); init001 (); DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__); gEPAT = 0xC7; init002 (0); DBG (16, "init002(0) passed... (%s:%d)\n", __FILE__, __LINE__); REGISTERWRITE (0x0A, 0); /* catch any failure to read back data in EPP mode */ reg = registerRead (0x0A); if (reg != 0) { DBG (0, "registerRead, found 0x%X expected 0x00 (%s:%d)\n", reg, __FILE__, __LINE__); if (reg == 0xFF) { DBG (0, "*** It appears that EPP data transfer doesn't work ***\n"); DBG (0, "*** Please read SETTING EPP section in sane-umax_pp.5 ***\n"); } return 0; } else { DBG (16, "registerRead(0x0A)=0x00 passed... (%s:%d)\n", __FILE__, __LINE__); } registerWrite (0x0A, 0xFF); DBG (16, "registerWrite(0x%X,0x%X) passed... (%s:%d)\n", 0x0A, 0xFF, __FILE__, __LINE__); REGISTERREAD (0x0A, 0xFF); for (i = 1; i < 256; i++) { REGISTERWRITE (0x0A, i); REGISTERREAD (0x0A, i); REGISTERWRITE (0x0A, 0xFF - i); REGISTERREAD (0x0A, 0xFF - i); } REGISTERWRITE (0x13, 0x01); REGISTERWRITE (0x13, 0x00); REGISTERWRITE (0x0A, 0x11); for (i = 0; i < 10; i++) { bufferRead (0x400, dest); for (j = 0; j < 512; j++) { if (dest[2 * j] != (j % 256)) { DBG (0, "Loop %d, char %d bufferRead failed! (%s:%d)\n", i, j * 2, __FILE__, __LINE__); return 0; } if (dest[2 * j + 1] != (0xFF - (j % 256))) { DBG (0, "Loop %d, char %d bufferRead failed! (%s:%d)\n", i, j * 2 + 1, __FILE__, __LINE__); return 0; } } DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n", i, __FILE__, __LINE__); } for (i = 0; i < 10; i++) { bufferWrite (0x400, dest); DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i, __FILE__, __LINE__); } REGISTERREAD (0x0C, 4); REGISTERWRITE (0x13, 0x01); REGISTERWRITE (0x13, 0x00); REGISTERWRITE (0x0A, 0x18); Outb (DATA, 0x0); ClearRegister (0); init001 (); if (checkEPAT () != 0) return 0; DBG (16, "checkEPAT() passed... (%s:%d)\n", __FILE__, __LINE__); tmp = Inb (CONTROL) & 0x1F; Outb (CONTROL, tmp); Outb (CONTROL, tmp); WRITESLOW (0x08, 0x21); init001 (); DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__); WRITESLOW (0x08, 0x21); init001 (); DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__); SPPResetLPT (); if (init005 (0x80)) { DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__); } DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__); if (init005 (0xEC)) { DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__); } DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__); /* write/read buffer loop */ for (i = 0; i < 256; i++) { REGISTERWRITE (0x0A, i); REGISTERREAD (0x0A, i); REGISTERWRITE (0x0A, 0xFF - i); REGISTERREAD (0x0A, 0xFF - i); } DBG (16, "EPP write/read buffer loop passed... (%s:%d)\n", __FILE__, __LINE__); REGISTERWRITE (0x13, 0x01); REGISTERWRITE (0x13, 0x00); REGISTERWRITE (0x0A, 0x11); /* test EPP32 mode */ /* we set 32 bits I/O mode first, then step back to */ /* 8bits if tests fail */ setEPPMode (32); for (i = 0; (i < 10) && (getEPPMode () == 32); i++) { bufferRead (0x400, dest); /* if 32 bit I/O work, we should have a buffer */ /* filled by 00 FF 01 FE 02 FD 03 FC ..... */ for (j = 0; j < 0x200; j++) { if ((dest[j * 2] != j % 256) || (dest[j * 2 + 1] != 0xFF - (j % 256))) { DBG (1, "Setting EPP I/O to 8 bits ... (%s:%d)\n", __FILE__, __LINE__); setEPPMode (8); /* leave out current loop since an error was detected */ break; } } DBG (16, "Loop %d: bufferRead(0x400) passed... (%s:%d)\n", i, __FILE__, __LINE__); } DBG (1, "%d bits EPP data transfer\n", getEPPMode ()); for (i = 0; i < 10; i++) { bufferWrite (0x400, dest); DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i, __FILE__, __LINE__); } REGISTERREAD (0x0C, 0x04); REGISTERWRITE (0x13, 0x01); REGISTERWRITE (0x13, 0x00); REGISTERWRITE (0x0A, 0x18); WRITESLOW (0x08, 0x21); init001 (); DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__); SPPResetLPT (); if (init005 (0x80)) { DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__); } DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__); if (init005 (0xEC)) { DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__); } DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__); /* write/read buffer loop */ for (i = 0; i < 256; i++) { REGISTERWRITE (0x0A, i); REGISTERREAD (0x0A, i); REGISTERWRITE (0x0A, 0xFF - i); REGISTERREAD (0x0A, 0xFF - i); } DBG (16, "EPP write/read buffer loop passed... (%s:%d)\n", __FILE__, __LINE__); REGISTERWRITE (0x13, 0x01); REGISTERWRITE (0x13, 0x00); REGISTERWRITE (0x0A, 0x11); for (i = 0; i < 10; i++) { bufferRead (0x400, dest); DBG (16, "Loop %d: bufferRead(0x400) passed... (%s:%d)\n", i, __FILE__, __LINE__); } for (i = 0; i < 10; i++) { bufferWrite (0x400, dest); DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i, __FILE__, __LINE__); } REGISTERREAD (0x0C, 0x04); REGISTERWRITE (0x13, 0x01); REGISTERWRITE (0x13, 0x00); REGISTERWRITE (0x0A, 0x18); gMode = UMAX_PP_PARPORT_EPP; return 1; } /* * try ECP mode * returns 1 on success, 0 on failure */ int probeECP (unsigned char *dest) { int i, j, tmp; unsigned char breg; /* if ECP not available, fail */ if (gECP != 1) { DBG (1, "Hardware can't do ECP, giving up (%s:%d) ...\n", __FILE__, __LINE__); return 0; } gMode = UMAX_PP_PARPORT_ECP; /* clean from EPP failure */ breg = Inb (CONTROL); Outb (CONTROL, breg & 0x04); /* reset sequence */ byteMode (); /*Outb (ECR, 0x20); byte mode */ Outb (CONTROL, 0x04); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x0C); for (i = 0; i < 256; i++) { breg = (Inb (STATUS)) & 0xF8; if (breg != 0x48) { DBG (0, "probeECP() failed at sync step %d, status=0x%02X, expected 0x48 (%s:%d)\n", i, breg, __FILE__, __LINE__); return 0; } } Outb (CONTROL, 0x0E); Outb (CONTROL, 0x0E); Outb (CONTROL, 0x0E); breg = (Inb (STATUS)) & 0xF8; if (breg != 0x48) { DBG (0, "probeECP() failed, status=0x%02X, expected 0x48 (%s:%d)\n", breg, __FILE__, __LINE__); return 0; } Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); breg = Inb (STATUS) & 0xF8; breg = (Inb (STATUS)) & 0xF8; if (breg != 0xC8) { DBG (0, "probeECP() failed, status=0x%02X, expected 0xC8 (%s:%d)\n", breg, __FILE__, __LINE__); return 0; } /* end of reset sequence */ Outb (DATA, 0x00); ClearRegister (0); /* utile ? semble tester le registre de configuration * inb ECR,35 * inb 77B,FF * inb ECR,35 */ /* routine A */ breg = Inb (CONTROL); /* 0x04 évidemment! */ breg = Inb (ECR); breg = Inb (ECR); breg = Inb (ECR); breg = Inb (ECR); breg = Inb (CONTROL); byteMode (); /*Outb (ECR, 0x20); byte mode */ /*byteMode (); Outb (ECR, 0x20); */ breg = Inb (CONTROL); Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); breg = Inb (ECR); /* 35 expected */ breg = Inb (ECR); /* 35 expected */ breg = Inb (ECR); /* 35 expected */ breg = Inb (ECR); /* 35 expected */ Outb (CONTROL, 0x04); Outb (CONTROL, 0x04); byteMode (); byteMode (); ClearRegister (0); /* routine C */ PS2registerWrite (0x08, 0x01); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x04); ClearRegister (0); breg = PS2Something (0x10); if (breg != 0x0B) { DBG (0, "probeECP() failed, reg10=0x%02X, expected 0x0B (%s:%d)\n", breg, __FILE__, __LINE__); /* return 0; */ } for (i = 0; i < 256; i++) { ECPregisterWrite (0x0A, i); breg = ECPregisterRead (0x0A); if (breg != i) { DBG (0, "probeECP(), loop %d failed (%s:%d)\n", i, __FILE__, __LINE__); return 0; } ECPregisterWrite (0x0A, 0xFF - i); breg = ECPregisterRead (0x0A); if (breg != 0xFF - i) { DBG (0, "probeECP(), loop %d failed (%s:%d)\n", i, __FILE__, __LINE__); return 0; } } DBG (16, "probeECP(), loop passed (%s:%d)\n", __FILE__, __LINE__); ECPregisterWrite (0x13, 0x01); ECPregisterWrite (0x13, 0x00); ECPregisterWrite (0x0A, 0x11); /* there is one buffer transfer size set up */ /* subsequent reads are done in a row */ ECPSetBuffer (0x400); for (i = 0; i < 10; i++) { /* if (i > 0) */ compatMode (); Outb (CONTROL, 0x04); /* reset ? */ ECPbufferRead (1024, dest); /* check content of the returned buffer */ for (j = 0; j < 256; j++) { if (dest[j * 2] != j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", j * 2, j, dest[j * 2]); return 0; } if (dest[j * 2 + 1] != 0xFF - j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", j * 2 + 1, 0xFF - j, dest[j * 2 + 1]); return 0; } if (dest[512 + j * 2] != j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", 512 + j * 2, j, dest[512 + j * 2]); return 0; } if (dest[512 + j * 2 + 1] != 0xFF - j) { DBG (0, "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n", 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]); return 0; } } Outb (CONTROL, 0x04); byteMode (); } for (i = 0; i < 10; i++) ECPbufferWrite (1024, dest); breg = ECPregisterRead (0x0C); if (breg != 0x04) { DBG (0, "Warning! expected reg0C=0x04, found 0x%02X! (%s:%d) \n", breg, __FILE__, __LINE__); } ECPregisterWrite (0x13, 0x01); ECPregisterWrite (0x13, 0x00); ECPregisterWrite (0x0A, 0x18); /* reset printer ? */ Outb (DATA, 0x00); Outb (CONTROL, 0x00); Outb (CONTROL, 0x04); for (i = 0; i < 3; i++) { /* will go in a function */ ClearRegister (0); if (waitAck () != 1) { DBG (0, "probeECP failed because of waitAck() (%s:%d) \n", __FILE__, __LINE__); /* return 0; may fail without harm ... ??? */ } /* are these 2 out really needed ? */ PS2registerWrite (0x08, 0x01); Outb (CONTROL, 0x0C); /* select + reset */ Outb (CONTROL, 0x04); /* reset */ } /* prologue of the 'rotate test' */ ClearRegister (0); breg = PS2Something (0x10); if (breg != 0x0B) { DBG (0, "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", breg, __FILE__, __LINE__); } Outb (CONTROL, 0x04); /* reset */ if (init005 (0x80)) { DBG (0, "init005(0x80) failed... (%s:%d)\n", __FILE__, __LINE__); } DBG (16, "init005(0x80) passed... (%s:%d)\n", __FILE__, __LINE__); if (init005 (0xEC)) { DBG (0, "init005(0xEC) failed... (%s:%d)\n", __FILE__, __LINE__); } DBG (16, "init005(0xEC) passed... (%s:%d)\n", __FILE__, __LINE__); for (i = 0; i < 256; i++) { REGISTERWRITE (0x0A, i); REGISTERREAD (0x0A, i); REGISTERWRITE (0x0A, 0xFF - i); REGISTERREAD (0x0A, 0xFF - i); } DBG (16, "ECPprobe(), write/read buffer loop passed (%s:%d)\n", __FILE__, __LINE__); REGISTERWRITE (0x13, 0x01); REGISTERWRITE (0x13, 0x00); REGISTERWRITE (0x0A, 0x11); /* should be a function */ /* in probeEPP(), we begin 32 bit mode test here */ for (i = 0; i < 10; i++) { compatMode (); Outb (CONTROL, 0x04); /* reset ? */ ECPbufferRead (0x400, dest); /* check content of the returned buffer */ for (j = 0; j < 256; j++) { if (dest[j * 2] != j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", j * 2, j, dest[j * 2]); return 0; } if (dest[j * 2 + 1] != 0xFF - j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", j * 2 + 1, 0xFF - j, dest[j * 2 + 1]); return 0; } if (dest[512 + j * 2] != j) { DBG (0, "Altered buffer value at %03X, expected %02X, found %02X\n", 512 + j * 2, j, dest[512 + j * 2]); return 0; } if (dest[512 + j * 2 + 1] != 0xFF - j) { DBG (0, "Altered buffer value at %03X, expected 0x%02X, found 0x%02X\n", 512 + j * 2 + 1, 0xFF - j, dest[512 + j * 2 + 1]); return 0; } } Outb (CONTROL, 0x04); byteMode (); } for (i = 0; i < 10; i++) ECPbufferWrite (1024, dest); REGISTERREAD (0x0C, 0x04); REGISTERWRITE (0x13, 0x01); REGISTERWRITE (0x13, 0x00); REGISTERWRITE (0x0A, 0x18); waitAck (); return 1; } /* 1: OK 0: probe failed */ int sanei_umax_pp_probeScanner (int recover) { int tmp, i, j; int reg, nb; unsigned char *dest = NULL; int initbuf[2049]; int voidbuf[2049]; int val; int zero[5] = { 0, 0, 0, 0, -1 }; int model; /* saves port state */ gData = Inb (DATA); gControl = Inb (CONTROL); if (sanei_umax_pp_getastra () == 610) return probe610p (recover); /* save and set CONTROL */ tmp = (Inb (CONTROL)) & 0x1F; tmp = (Inb (CONTROL)) & 0x1F; Outb (CONTROL, tmp); Outb (CONTROL, tmp); tmp = Inb (DATA); tmp = Inb (CONTROL) & 0x3F; Outb (CONTROL, tmp); tmp = Inb (CONTROL) & 0x3F; tmp = Inb (DATA); tmp = Inb (CONTROL) & 0x3F; tmp = Inb (DATA); /* any scanner ? */ /* fast detect */ tmp = ringScanner (2, 0); if (!tmp) { DBG (1, "No scanner detected by 'ringScanner(2,0)'...\n"); tmp = ringScanner (5, 0); if (!tmp) { DBG (1, "No scanner detected by 'ringScanner(5,0)'...\n"); tmp = ringScanner (5, 10000); if (!tmp) { DBG (1, "No scanner detected by 'ringScanner(5,10000)'...\n"); tmp = ringScanner (5, 10000); if (!tmp) { DBG (1, "No scanner detected by 'ringScanner(5,10000)'...\n"); } } } } if (!tmp) { DBG (1, "No 1220P/2000P scanner detected by 'ringScanner()'...\n"); } DBG (16, "ringScanner passed...\n"); gControl = Inb (CONTROL) & 0x3F; g67D = 1; if (sendCommand (0x30) == 0) { DBG (0, "sendCommand(0x30) (%s:%d) failed ...\n", __FILE__, __LINE__); return 0; } DBG (16, "sendCommand(0x30) passed ... (%s:%d)\n", __FILE__, __LINE__); g67E = 4; /* bytes to read */ if (sendCommand (0x00) == 0) { DBG (0, "sendCommand(0x00) (%s:%d) failed ...\n", __FILE__, __LINE__); return 0; } DBG (16, "sendCommand(0x00) passed... (%s:%d)\n", __FILE__, __LINE__); g67E = 0; /* bytes to read */ if (testVersion (0) == 0) { DBG (16, "testVersion(0) (%s:%d) failed ...\n", __FILE__, __LINE__); } DBG (16, "testVersion(0) passed...\n"); /* must fail for 1220P and 2000P */ if (testVersion (1) == 0) /* software doesn't do it for model 0x07 */ { /* but it works .. */ DBG (16, "testVersion(1) failed (expected) ... (%s:%d)\n", __FILE__, __LINE__); } else { DBG (16, "Unexpected success on testVersion(1) ... (%s:%d)\n", __FILE__, __LINE__); } if (testVersion (0) == 0) { DBG (16, "testVersion(0) (%s:%d) failed ...\n", __FILE__, __LINE__); } DBG (16, "testVersion(0) passed...\n"); /* must fail */ if (testVersion (1) == 0) { DBG (16, "testVersion(1) failed (expected) ... (%s:%d)\n", __FILE__, __LINE__); } else { DBG (16, "Unexpected success on testVersion(1) ... (%s:%d)\n", __FILE__, __LINE__); } Outb (DATA, 0x04); Outb (CONTROL, 0x0C); Outb (DATA, 0x04); Outb (CONTROL, 0x0C); gControl = Inb (CONTROL) & 0x3F; Outb (CONTROL, gControl & 0xEF); if (sendCommand (0x40) == 0) { DBG (0, "sendCommand(0x40) (%s:%d) failed ...\n", __FILE__, __LINE__); return 0; } DBG (16, "sendCommand(0x40) passed...\n"); if (sendCommand (0xE0) == 0) { DBG (0, "sendCommand(0xE0) (%s:%d) failed ...\n", __FILE__, __LINE__); return 0; } DBG (16, "sendCommand(0xE0) passed...\n"); ClearRegister (0); DBG (16, "ClearRegister(0) passed...\n"); SPPResetLPT (); DBG (16, "SPPResetLPT() passed...\n"); Outb (CONTROL, 4); Outb (CONTROL, 4); /* test PS2 mode */ tmp = PS2registerRead (0x0B); if (tmp == 0xC7) { /* epat C7 detected */ DBG (16, "PS2registerRead(0x0B)=0x%X passed...\n", tmp); PS2registerWrite (8, 0); DBG (16, "PS2registerWrite(8,0) passed... (%s:%d)\n", __FILE__, __LINE__); tmp = PS2registerRead (0x0A); if (tmp != 0x00) { if (tmp == 0x1C) { DBG (16, "Previous probe detected ... (%s:%d)\n", __FILE__, __LINE__); } else { DBG (0, "Found 0x%X expected 0x00 (%s:%d)\n", tmp, __FILE__, __LINE__); } } DBG (16, "PS2registerRead(0x0A)=0x%X passed ...(%s:%d)\n", tmp, __FILE__, __LINE__); } else { DBG (4, "Found 0x%X expected 0xC7 (%s:%d)\n", tmp, __FILE__, __LINE__); if ((tmp == 0xFF) && (sanei_umax_pp_getparport () < 1)) { DBG (0, "It is likely that the hardware address (0x%X) you specified is wrong\n", gPort); return 0; } /* probe for a 610p, since we can't detect an EPAT */ DBG (1, "Trying 610p (%s:%d)\n", __FILE__, __LINE__); return probe610p (recover); } /* clear register 3 */ ClearRegister (3); DBG (16, "ClearRegister(3) passed...\n"); /* wait ? */ i = 65535; while (i > 0) { tmp = Inb (DATA); tmp = Inb (DATA); i--; } DBG (16, "FFFF in loop passed...\n"); ClearRegister (0); DBG (16, "ClearRegister(0) passed... (%s:%d)\n", __FILE__, __LINE__); fflush (stdout); /* 1220/2000P branch */ WRITESLOW (0x0E, 1); /* register 0x0F used only once: model number ? Or ASIC revision ? */ /* comm mode ? */ model = PS2registerRead (0x0F); DBG (1, "UMAX Astra 1220/1600/2000 P ASIC detected (mode=%d)\n", model); setModel (model); DBG (16, "PS2registerRead(0x0F) passed... (%s:%d)\n", __FILE__, __LINE__); /* scanner powered off */ if (model == 0x1B) { DBG (0, "Register 0x0F=0x1B, scanner powered off ! (%s:%d)\n", __FILE__, __LINE__); return 0; } if ((model != 0x1F) && (model != 0x07)) { DBG (0, "Unexpected value for for register 0x0F, expected 0x07 or 0x1F, got 0x%02X ! (%s:%d)\n", model, __FILE__, __LINE__); DBG (0, "There is a new scanner revision in town, or a bug ....\n"); } WRITESLOW (0x08, 0x02); WRITESLOW (0x0E, 0x0F); WRITESLOW (0x0F, 0x0C); WRITESLOW (0x0C, 0x04); tmp = PS2registerRead (0x0D); if ((tmp != 0x00) && (tmp != 0x40)) { DBG (0, "Unexpected value for for register 0x0D, expected 0x00 or 0x40, got 0x%02X ! (%s:%d)\n", tmp, __FILE__, __LINE__); } WRITESLOW (0x0D, 0x1B); switch (model) { case 0x1F: WRITESLOW (0x12, 0x14); SLOWNIBBLEREGISTERREAD (0x12, 0x10); break; case 0x07: WRITESLOW (0x12, 0x00); SLOWNIBBLEREGISTERREAD (0x12, 0x00); /* we may get 0x20, in this case some color aberration may occur */ /* must depend on the parport */ /* model 0x07 + 0x00=>0x20=2000P */ break; default: WRITESLOW (0x12, 0x00); SLOWNIBBLEREGISTERREAD (0x12, 0x20); break; } SLOWNIBBLEREGISTERREAD (0x0D, 0x18); SLOWNIBBLEREGISTERREAD (0x0C, 0x04); SLOWNIBBLEREGISTERREAD (0x0A, 0x00); WRITESLOW (0x0E, 0x0A); WRITESLOW (0x0F, 0x00); WRITESLOW (0x0E, 0x0D); WRITESLOW (0x0F, 0x00); dest = (unsigned char *) malloc (65536); if (dest == NULL) { DBG (0, "Failed to allocate 64K (%s:%d)\n", __FILE__, __LINE__); return 0; } gMode = UMAX_PP_PARPORT_PS2; if (probePS2 (dest)) { /* PS2 mode works */ DBG (16, "probePS2 passed ... (%s:%d)\n", __FILE__, __LINE__); gprobed = UMAX_PP_PARPORT_PS2; } Outb (CONTROL, 4); SLOWNIBBLEREGISTERREAD (0x0A, 0x18); WRITESLOW (0x08, 0x40); WRITESLOW (0x08, 0x60); WRITESLOW (0x08, 0x22); gMode = UMAX_PP_PARPORT_EPP; if (probeEPP (dest)) { /* EPP mode works */ gprobed = UMAX_PP_PARPORT_EPP; gMode = UMAX_PP_PARPORT_EPP; DBG (16, "probeEPP passed ... (%s:%d)\n", __FILE__, __LINE__); } else { /* EPP fails, try ECP */ DBG (16, "probeEPP failed ... (%s:%d)\n", __FILE__, __LINE__); gMode = UMAX_PP_PARPORT_ECP; if (probeECP (dest)) { /* ECP mode works */ DBG (16, "probeECP passed ... (%s:%d)\n", __FILE__, __LINE__); gprobed = UMAX_PP_PARPORT_ECP; } else { /* ECP and EPP fail, give up */ /* PS2 could be used */ DBG (16, "probeECP failed ... (%s:%d)\n", __FILE__, __LINE__); DBG (1, "No EPP or ECP mode working, giving up ... (%s:%d)\n", __FILE__, __LINE__); free (dest); return 0; } } /* some operations here may have to go into probeEPP/probeECP */ g6FE = 1; if (gMode == UMAX_PP_PARPORT_ECP) { WRITESLOW (0x08, 0x01); Outb (CONTROL, 0x0C); Outb (CONTROL, 0x04); ClearRegister (0); tmp = PS2Something (0x10); if (tmp != 0x0B) { DBG (0, "PS2Something returned 0x%02X, 0x0B expected (%s:%d)\n", tmp, __FILE__, __LINE__); } } else { WRITESLOW (0x08, 0x21); init001 (); DBG (16, "init001() passed... (%s:%d)\n", __FILE__, __LINE__); } reg = registerRead (0x0D); reg = (reg & 0xE8) | 0x43; registerWrite (0x0D, reg); REGISTERWRITE (0x0A, 0x18); REGISTERWRITE (0x0E, 0x0F); REGISTERWRITE (0x0F, 0x0C); REGISTERWRITE (0x0A, 0x1C); REGISTERWRITE (0x0E, 0x10); REGISTERWRITE (0x0F, 0x1C); reg = registerRead (0x0D); /* 0x48 expected */ reg = registerRead (0x0D); reg = registerRead (0x0D); reg = (reg & 0xB7) | 0x03; registerWrite (0x0D, reg); DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__); reg = registerRead (0x12); /* 0x10 for model 0x0F, 0x20 for model 0x07 */ /* 0x00 when in ECP mode ... */ reg = reg & 0xEF; registerWrite (0x12, reg); DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__); reg = registerRead (0x0A); if (reg != 0x1C) { DBG (0, "Warning! expected reg0A=0x1C, found 0x%02X! (%s:%d) \n", reg, __FILE__, __LINE__); } DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__); /*Inb(CONTROL); ECP 0x04 expected */ disconnect (); DBG (16, "disconnect() passed... (%s:%d)\n", __FILE__, __LINE__); connect (); DBG (16, "connect() passed... (%s:%d)\n", __FILE__, __LINE__); /* some sort of countdown, some warming-up ? */ /* maybe some data sent to the stepper motor */ /* if (model == 0x07) */ { /* REGISTERWRITE (0x0A, 0x00); reg = registerRead (0x0D); reg = (reg & 0xE8); registerWrite (0x0D, reg); DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__); */ epilogue (); prologue (0x10); reg = registerRead (0x13); if (reg != 0x00) { DBG (0, "Warning! expected reg13=0x00, found 0x%02X! (%s:%d) \n", reg, __FILE__, __LINE__); } REGISTERWRITE (0x13, 0x81); usleep (10000); REGISTERWRITE (0x13, 0x80); /* could it be step-motor values ? */ REGISTERWRITE (0x0E, 0x04); /* FF->R04 */ REGISTERWRITE (0x0F, 0xFF); REGISTERWRITE (0x0E, 0x05); /* 03->R05 */ REGISTERWRITE (0x0F, 0x03); REGISTERWRITE (0x10, 0x66); usleep (10000); REGISTERWRITE (0x0E, 0x04); /* FF->R04 */ REGISTERWRITE (0x0F, 0xFF); REGISTERWRITE (0x0E, 0x05); /* 01 ->R05 */ REGISTERWRITE (0x0F, 0x01); REGISTERWRITE (0x10, 0x55); usleep (10000); REGISTERWRITE (0x0E, 0x04); /* FF -> R04 */ REGISTERWRITE (0x0F, 0xFF); REGISTERWRITE (0x0E, 0x05); /* 00 -> R05 */ REGISTERWRITE (0x0F, 0x00); REGISTERWRITE (0x10, 0x44); usleep (10000); REGISTERWRITE (0x0E, 0x04); /* 7F -> R04 */ REGISTERWRITE (0x0F, 0x7F); REGISTERWRITE (0x0E, 0x05); /* 00 -> R05 */ REGISTERWRITE (0x0F, 0x00); REGISTERWRITE (0x10, 0x33); usleep (10000); REGISTERWRITE (0x0E, 0x04); /* 3F -> R04 */ REGISTERWRITE (0x0F, 0x3F); REGISTERWRITE (0x0E, 0x05); REGISTERWRITE (0x0F, 0x00); /* 00 -> R05 */ REGISTERWRITE (0x10, 0x22); usleep (10000); REGISTERWRITE (0x0E, 0x04); REGISTERWRITE (0x0F, 0x00); REGISTERWRITE (0x0E, 0x05); REGISTERWRITE (0x0F, 0x00); REGISTERWRITE (0x10, 0x11); usleep (10000); REGISTERWRITE (0x13, 0x81); usleep (10000); REGISTERWRITE (0x13, 0x80); REGISTERWRITE (0x0E, 0x04); REGISTERWRITE (0x0F, 0x00); REGISTERWRITE (0x0E, 0x05); REGISTERWRITE (0x0F, 0x00); usleep (10000); reg = registerRead (0x10); DBG (1, "Count-down value is 0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); /* 2 reports of CF, was FF first (typo ?) */ /* CF seems a valid value */ /* in case of CF, we may have timeout ... */ /*if (reg != 0x00) { DBG (0, "Warning! expected reg10=0x00, found 0x%02X! (%s:%d) \n", reg, __FILE__, __LINE__); } */ REGISTERWRITE (0x13, 0x00); } /* end of countdown */ DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__); /* *NOT* epilogue(); (when EPP) */ /*REGISTERWRITE (0x0A, 0x00); REGISTERREAD (0x0D, 0x40); REGISTERWRITE (0x0D, 0x00); */ epilogue (); prologue (0x10); REGISTERWRITE (0x0E, 0x0D); REGISTERWRITE (0x0F, 0x00); REGISTERWRITE (0x0A, 0x1C); /* real start of high level protocol ? */ if (fonc001 () != 1) { DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (16, "fonc001() passed (%s:%d) \n", __FILE__, __LINE__); reg = registerRead (0x19) & 0xC8; /* if reg=E8 or D8 , we have a 'messed' scanner */ /* 4 tranform buffers + 'void' are sent: 1 B&W, and 3 RGB ? */ memset (initbuf, 0x00, 2048 * sizeof (int)); memset (voidbuf, 0x00, 2048 * sizeof (int)); initbuf[512] = 0xFF; initbuf[513] = 0xAA; initbuf[514] = 0x55; for (j = 0; j < 4; j++) { for (i = 0; i < 256; i++) { voidbuf[512 * j + 2 * i] = i; voidbuf[512 * j + 2 * i] = 0xFF - i; } } /* one pass (B&W ?) */ if (cmdSetDataBuffer (initbuf) != 1) { DBG (0, "cmdSetDataBuffer(initbuf) failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (16, "cmdSetDataBuffer(initbuf) passed... (%s:%d)\n", __FILE__, __LINE__); if (cmdSetDataBuffer (voidbuf) != 1) { DBG (0, "cmdSetDataBuffer(voidbuf) failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (16, "cmdSetDataBuffer(voidbuf) passed... (%s:%d)\n", __FILE__, __LINE__); /* everything above the FF 55 AA tag is 'void' */ /* it seems that the buffer is reused and only the beginning is initalized */ for (i = 515; i < 2048; i++) initbuf[i] = voidbuf[i]; /* three pass (RGB ?) */ for (i = 0; i < 3; i++) { if (cmdSetDataBuffer (initbuf) != 1) { DBG (0, "cmdSetDataBuffer(initbuf) failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (16, "Loop %d: cmdSetDataBuffer(initbuf) passed... (%s:%d)\n", i, __FILE__, __LINE__); if (cmdSetDataBuffer (voidbuf) != 1) { DBG (0, "Loop %d: cmdSetDataBuffer(voidbuf) failed ! (%s:%d) \n", i, __FILE__, __LINE__); return 0; } } /* memory size testing ? */ /* load 150 Ko in scanner */ REGISTERWRITE (0x1A, 0x00); REGISTERWRITE (0x1A, 0x0C); REGISTERWRITE (0x1A, 0x00); REGISTERWRITE (0x1A, 0x0C); REGISTERWRITE (0x0A, 0x11); /* start */ nb = 150; for (i = 0; i < nb; i++) /* 300 for ECP ??? */ { bufferWrite (0x400, dest); DBG (16, "Loop %d: bufferWrite(0x400,dest) passed... (%s:%d)\n", i, __FILE__, __LINE__); } REGISTERWRITE (0x0A, 0x18); /* end */ /* read them back */ REGISTERWRITE (0x0A, 0x11); /*start transfert */ if (gMode == UMAX_PP_PARPORT_ECP) { ECPSetBuffer (0x400); } for (i = 0; i < nb; i++) /* 300 for ECP ??? */ { bufferRead (0x400, dest); DBG (16, "Loop %d: bufferRead(0x400,dest) passed... (%s:%d)\n", i, __FILE__, __LINE__); } REGISTERWRITE (0x0A, 0x18); /*end transfer */ /* fully disconnect, then reconnect */ if (gMode == UMAX_PP_PARPORT_ECP) { epilogue (); sendCommand (0xE0); Outb (DATA, 0xFF); Outb (DATA, 0xFF); ClearRegister (0); WRITESLOW (0x0E, 0x0A); SLOWNIBBLEREGISTERREAD (0x0F, 0x00); WRITESLOW (0x0F, 0x08); WRITESLOW (0x08, 0x10); /* 0x10 ?? */ prologue (0x10); } /* almost cmdSync(0x00) which halts any pending operation */ if (fonc001 () != 1) { DBG (0, "fonc001() failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (16, "Fct001() passed (%s:%d) \n", __FILE__, __LINE__); if (sendWord (zero) == 0) { DBG (0, "sendWord(zero) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } epilogue (); DBG (16, "sendWord(zero) passed (%s:%d)\n", __FILE__, __LINE__); /* end transport init */ /* now high level (connected) protocol begins */ val = sanei_umax_pp_initScanner (recover); if (val == 0) { DBG (0, "initScanner() failed (%s:%d)\n", __FILE__, __LINE__); return 0; } /* if no homing .... */ if (val == 1) { CMDSYNC (0); CMDSYNC (0xC2); CMDSYNC (0); } /* set port to its initial state */ Outb (DATA, gData); Outb (CONTROL, gControl); free (dest); DBG (1, "probe done ...\n"); return 1; } static int disconnect_epat (void) { REGISTERWRITE (0x0A, 0x00); registerRead (0x0D); REGISTERWRITE (0x0D, 0x00); disconnect (); return 1; } static int connect_epat (int r08) { int reg; if (connect () != 1) { DBG (0, "connect_epat: connect() failed! (%s:%d)\n", __FILE__, __LINE__); return 0; } reg = registerRead (0x0B); if (reg != gEPAT) { /* ASIC version is not */ /* the one expected (epat c7) */ DBG (0, "Error! expected reg0B=0x%02X, found 0x%02X! (%s:%d) \n", gEPAT, reg, __FILE__, __LINE__); /* we try to clean all */ disconnect (); return 0; } reg = registerRead (0x0D); reg = (reg | 0x43) & 0xEB; REGISTERWRITE (0x0D, reg); REGISTERWRITE (0x0C, 0x04); reg = registerRead (0x0A); if (reg != 0x00) { /* a previous unfinished command */ /* has left an uncleared value */ DBG (0, "Warning! expected reg0A=0x00, found 0x%02X! (%s:%d) \n", reg, __FILE__, __LINE__); } REGISTERWRITE (0x0A, 0x1C); if (r08 != 0) { if (gMode == UMAX_PP_PARPORT_ECP) { REGISTERWRITE (0x08, r08); /* 0x01 or 0x10 ??? */ } else { REGISTERWRITE (0x08, 0x21); } } REGISTERWRITE (0x0E, 0x0F); REGISTERWRITE (0x0F, 0x0C); REGISTERWRITE (0x0A, 0x1C); REGISTERWRITE (0x0E, 0x10); REGISTERWRITE (0x0F, 0x1C); if (gMode == UMAX_PP_PARPORT_ECP) { REGISTERWRITE (0x0F, 0x00); } return 1; } static int prologue (int r08) { switch (sanei_umax_pp_getastra ()) { case 610: connect610p (); return sync610p (); case 1220: case 1600: case 2000: default: return connect_epat (r08); } } static int epilogue (void) { switch (sanei_umax_pp_getastra ()) { case 610: return disconnect610p (); case 1220: case 1600: case 2000: default: return disconnect_epat (); } } static int EPPcmdGet610p (int cmd, int len, int *val) { int word[4]; int i, status, control; word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x3F) | 0x80 | 0x40; /* 0x40 means 'read' */ connect610p (); sync610p (); /* sends magic seal 55 AA */ status = EPPputByte610p (0x55); if (status != 0xC8) { DBG (1, "EPPcmdGet610p: Found 0x%X expected 0xC8 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } status = EPPputByte610p (0xAA); if (status != 0xC8) { DBG (1, "EPPcmdGet610p: Found 0x%02X expected 0xC8 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } /* tests status */ /* scannerStatus=0x58 */ status = EPPgetStatus610p (); if (status != 0xC8) { DBG (1, "EPPcmdGet610p: Found 0x%X expected 0xC8, status=0x%02X (%s:%d)\n", status, scannerStatus, __FILE__, __LINE__); return 0; } /* sends length of data */ for (i = 0; (i < 4) && (status == 0xC8); i++) { status = EPPputByte610p (word[i]); } if (status != 0xC8) { DBG (1, "EPPcmdGet610p: loop %d, found 0x%02X expected 0xC8 (%s:%d)\n", i, status, __FILE__, __LINE__); return 0; } Outb (DATA, 0xFF); /* tests status */ /* scannerStatus=0x58 */ status = EPPgetStatus610p (); if (status != 0xD0) { DBG (1, "EPPcmdGet610p: Found 0x%X expected 0xD0, status=0x%02X (%s:%d)\n", status, scannerStatus, __FILE__, __LINE__); return 0; } /* data reverse */ control = Inb (CONTROL) & 0xF4; control = control | 0xA0; /* receive data */ i = 0; while (i < len) { status = Inb (STATUS) & 0xF8; if (status & 0x08) { DBG (1, "EPPcmdGet610p: loop %d, found 0x%X expected 0xD0 or 0xC0 (%s:%d)\n", i, status, __FILE__, __LINE__); return 0; } val[i] = Inb (EPPDATA); i++; } if (DBG_LEVEL >= 8) { char *str = NULL; str = malloc (3 * len + 1); if (str != NULL) { for (i = 0; i < len; i++) { sprintf (str + 3 * i, "%02X ", val[i]); } str[3 * i] = 0x00; DBG (8, "String received for %02X: %s\n", cmd, str); free (str); } else { TRACE (8, "not enough memory for debugging ..."); } } /* scannerStatus=0x58 */ status = EPPgetStatus610p (); scannerStatus = status; if (status != 0xC0) { DBG (0, "EPPcmdGet610p: Found 0x%02X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } disconnect610p (); return 1; } static int cmdGet610p (int cmd, int len, int *val) { int word[5]; int i, j, status; if ((cmd == 8) && (len > 0x23)) len = 0x23; if (gMode == UMAX_PP_PARPORT_EPP) return EPPcmdGet610p (cmd, len, val); /* compute word */ word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x3F) | 0x80 | 0x40; /* 0x40 means 'read' */ word[4] = -1; connect610p (); sync610p (); if (sendLength610p (word) == 0) { DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__); return 0; } status = getStatus610p (); scannerStatus = status; if ((status != 0xC0) && (status != 0xD0)) { DBG (0, "Found 0x%02X expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } if (receiveData610p (val, len) == 0) { DBG (0, "sendData610p(val,%d) failed (%s:%d)\n", len, __FILE__, __LINE__); return 0; } status = getStatus610p (); scannerStatus = status; j = 0; while ((j < 256) && (status & 0x08)) { status = getStatus610p (); j++; } if (status != 0xC0) { DBG (0, "Found 0x%02X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } disconnect610p (); if (DBG_LEVEL >= 8) { char *str = NULL; str = malloc (3 * len + 1); if (str != NULL) { for (i = 0; i < len; i++) { sprintf (str + 3 * i, "%02X ", val[i]); } str[3 * i] = 0x00; DBG (8, "String received for %02X: %s\n", cmd, str); free (str); } else { TRACE (8, "not enough memory for debugging ..."); } } return 1; } static int EPPcmdSet610p (int cmd, int len, int *val) { int word[5]; int i, status; if ((cmd == 8) && (len > 0x23)) { /* blank useless extra bytes */ for (i = 0x22; i < len; i++) val[i] = 0x00; } word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x3F) | 0x80; connect610p (); sync610p (); /* sends magic seal 55 AA */ status = EPPputByte610p (0x55); if ((status != 0xC8) && (status!=0xC0)) { DBG (0, "EPPcmdSet610p: Found 0x%X expected 0xC0 or 0xC8 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } status = EPPputByte610p (0xAA); if ((status != 0xC8) && (status!=0xC0)) { DBG (0, "EPPcmdSet610p: Found 0x%X expected 0xC0 or 0xC8 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } /* tests status */ status = EPPgetStatus610p (); if ((status != 0xC8) && (status!=0xC0)) { DBG (0, "EPPcmdSet610p: Found 0x%02X expected 0xC0 or 0xC8 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } /* sends length of data */ for (i = 0; i < 4; i++) { status = EPPputByte610p (word[i]); } if ((status != 0xC8) && (status!=0xC0)) { DBG (0, "EPPcmdSet610p: loop %d, found 0x%02X expected 0xC0 or 0xC8 (%s:%d)\n", i, status, __FILE__, __LINE__); return 0; } Outb (DATA, 0xFF); /* tests status */ status = EPPgetStatus610p (); if (status != 0xC0) { DBG (0, "Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } /* sends data */ status = 0xC8; for (i = 0; (i < len) && (status == 0xC8); i++) { /* escape special values with ESC (0x1B) */ if (val[i] == 0x1B) status = EPPputByte610p (0x1B); if (i > 0) { if ((val[i] == 0xAA) && (val[i - 1] == 0x55)) status = EPPputByte610p (0x1B); } /* now send data */ status = EPPputByte610p (val[i]); } if (status != 0xC8) { DBG (0, "EPPcmdSet610p: loop %d, found 0x%02X expected 0xC8 (%s:%d)\n", i, status, __FILE__, __LINE__); return 0; } Outb (DATA, 0xFF); status = EPPgetStatus610p (); if (status != 0xC0) { DBG (0, "Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } disconnect610p (); return 1; } static int cmdSet610p (int cmd, int len, int *val) { int word[5]; int i, j, status; if (gMode == UMAX_PP_PARPORT_EPP) return EPPcmdSet610p (cmd, len, val); if ((cmd == 8) && (len > 0x23)) { /* blank useless extra bytes */ for (i = 0x22; i < len; i++) val[i] = 0x00; } /* compute word */ word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x3F) | 0x80; word[4] = -1; connect610p (); sync610p (); if (sendLength610p (word) == 0) { DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__); return 0; } status = getStatus610p (); scannerStatus = status; if ((status != 0xC0) && (status != 0xD0)) { DBG (1, "Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } if (sendData610p (val, len) == 0) { DBG (1, "sendData610p(val,%d) failed (%s:%d)\n", len, __FILE__, __LINE__); return 0; } status = getStatus610p (); scannerStatus = status; j = 0; while ((j < 256) && (status & 0x08)) { status = getStatus610p (); j++; } if (status != 0xC0) { DBG (1, "Found 0x%X expected 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); /* return 0; */ } disconnect610p (); return 1; } static int cmdSet (int cmd, int len, int *val) { int word[5]; int i; if (DBG_LEVEL >= 8) { char *str = NULL; str = malloc (3 * len + 1); if (str != NULL) { for (i = 0; i < len; i++) { sprintf (str + 3 * i, "%02X ", val[i]); } str[3 * i] = 0x00; DBG (8, "String sent for %02X: %s\n", cmd, str); free (str); } else { TRACE (8, "not enough memory for debugging ..."); } } if (sanei_umax_pp_getastra () == 610) return cmdSet610p (cmd, len, val); /* cmd 08 as 2 length depending upon model */ if ((cmd == 8) && (getModel () == 0x07)) { len = 35; } /* compute word */ word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x3F) | 0x80; if (!prologue (0x10)) { DBG (0, "cmdSet: prologue failed ! (%s:%d)\n", __FILE__, __LINE__); return 0; } /* send data */ if (sendLength (word, 4) == 0) { DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } TRACE (16, "sendLength(word,4) passed ..."); /* head end */ epilogue (); if (len > 0) { /* send body */ if (!prologue (0x10)) { DBG (0, "cmdSet: prologue failed ! (%s:%d)\n", __FILE__, __LINE__); } /* send data */ if (sendData (val, len) == 0) { DBG (0, "sendData(word,%d) failed (%s:%d)\n", len, __FILE__, __LINE__); epilogue (); return 0; } TRACE (16, "sendData(val,len) passed ..."); /* body end */ epilogue (); } return 1; } static int cmdGet (int cmd, int len, int *val) { int word[5]; int i; if (sanei_umax_pp_getastra () == 610) return cmdGet610p (cmd, len, val); /* cmd 08 as 2 length depending upon model */ if ((cmd == 8) && (getModel () == 0x07)) { len = 35; } /* compute word */ word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x3F) | 0x80 | 0x40; /* 0x40 means 'read' */ word[4] = -1; /* send header */ if (!prologue (0x10)) { DBG (0, "cmdGet: prologue failed ! (%s:%d)\n", __FILE__, __LINE__); return 0; } /* send data */ if (sendLength (word, 4) == 0) { DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } TRACE (16, "sendLength(word,4) passed ..."); /* head end */ epilogue (); /* send header */ if (!prologue (0x10)) { DBG (0, "cmdGet: prologue failed ! (%s:%d)\n", __FILE__, __LINE__); return 0; } /* get actual data */ if (receiveData (val, len) == 0) { DBG (0, "receiveData(val,len) failed (%s:%d)\n", __FILE__, __LINE__); epilogue (); return 0; } if (DBG_LEVEL >= 8) { char *str = NULL; str = malloc (3 * len + 1); if (str != NULL) { for (i = 0; i < len; i++) { sprintf (str + 3 * i, "%02X ", val[i]); } str[3 * i] = 0x00; DBG (8, "String received for %02X: %s\n", cmd, str); free (str); } else { TRACE (8, "not enough memory for debugging ..."); } } epilogue (); return 1; } static int cmdSetGet (int cmd, int len, int *val) { int *tampon; int i; /* model revision 0x07 uses 35 bytes buffers */ /* cmd 08 as 2 length depending upon model */ if ((cmd == 8) && (getModel () == 0x07)) { len = 0x23; } /* first we send */ if (cmdSet (cmd, len, val) == 0) { DBG (0, "cmdSetGet failed ! (%s:%d)\n", __FILE__, __LINE__); return 0; } tampon = (int *) malloc (len * sizeof (int)); memset (tampon, 0x00, len * sizeof (int)); if (tampon == NULL) { DBG (0, "Failed to allocate room for %d int ! (%s:%d)\n", len, __FILE__, __LINE__); epilogue (); return 0; } /* then we receive */ if (cmdGet (cmd, len, tampon) == 0) { DBG (0, "cmdSetGet failed ! (%s:%d)\n", __FILE__, __LINE__); free (tampon); epilogue (); return 0; } /* check and copy */ for (i = 0; (i < len) && (val[i] >= 0); i++) { if (tampon[i] != val[i]) { DBG (0, "Warning data read back differs: expected %02X found tampon[%d]=%02X ! (%s:%d)\n", val[i], i, tampon[i], __FILE__, __LINE__); } val[i] = tampon[i]; } /* OK */ free (tampon); return 1; } /* 1 OK, 0 failed */ static int EPPcmdGetBuffer610p (int cmd, int len, unsigned char *buffer) { int status, i, tmp, control; int word[5]; int count, needed, max; #ifdef HAVE_LINUX_PPDEV_H int fd, mode, rc; #endif int loop, wait, remain; /* first we set length and channel */ /* compute word */ word[0] = len / 65536; word[1] = (len / 256) % 256; word[2] = len % 256; word[3] = (cmd & 0x0F) | 0xC0; word[4] = -1; connect610p (); /* start of EPPsendLength610p */ sync610p (); /* sends magic seal 55 AA */ status = EPPputByte610p (0x55); if ((status != 0xD0) && (status != 0xC8)) { DBG (0, "EPPcmdGetBuffer610p: Found 0x%X expected 0xC8 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } status = EPPputByte610p (0xAA); if ((status != 0xD0) && (status != 0xC8)) { DBG (0, "EPPcmdGetBuffer610p: Found 0x%02X expected 0xC8 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } /* tests status */ status = EPPgetStatus610p (); if ((status != 0xD0) && (status != 0xC8)) { DBG (0, "EPPcmdGetBuffer610p: Found 0x%X expected 0xC8 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } /* sends length of data */ for (i = 0; i < 4; i++) { status = EPPputByte610p (word[i]); } if ((status != 0xC0) && (status != 0xC8)) { DBG (0, "EPPcmdGetBuffer610p: loop %d, found 0x%02X expected 0xC0 or 0xC8 (%s:%d)\n", i, status, __FILE__, __LINE__); return 0; } Outb (DATA, 0xFF); /* test status */ status = EPPgetStatus610p (); if ((status != 0xC0) && (status != 0xD0)) { DBG (0, "EPPcmdGetBuffer610p: Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); /*return 0; */ } disconnect610p (); /* end of EPPsendLength610p */ /* max data read in one go */ if (sanei_umax_pp_getfull () == 1) max = 2550 / 3; else max = 32768; /* loop until enough data is read */ count = 0; while (count < len) { if (len - count > max) needed = max; else needed = len - count; if (needed % 4) remain = needed % 4; else remain = 4; loop = (needed - remain) / 2; wait = 0; DBG (32, "EPPcmdGetBuffer610p: %d loops to do \n", loop); status = 0x20; /* wait for data ready */ while ((status & 0x80) != 0x80) { /* this is SPPgetStatus */ connect610p (); Outb (CONTROL, 0x07); Outb (DATA, 0xFF); tmp = Inb (DATA); if (tmp != 0xFF) { DBG (0, "EPPcmdGetBuffer610p found 0x%02X expected 0xFF (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } status = Inb (STATUS) & 0xF8; if ((status & 0x80) != 0x80) { disconnect610p (); usleep(1000); } else { Outb (CONTROL, 0x04); sync610p (); Outb (DATA, 0xFF); control = (Inb (CONTROL) & 0x44) | 0xE4; Outb (CONTROL, control); } } /* EPP block read */ /* there is one form for full CCD width reads, and another for other reads */ #ifdef HAVE_LINUX_PPDEV_H /* check we have ppdev working */ fd = sanei_umax_pp_getparport (); if (fd > 0) { mode = 1; /* data_reverse */ rc = ioctl (fd, PPDATADIR, &mode); if (rc) DBG (0, "EPPcmdGetBuffer610p: ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #ifdef PPSETFLAGS mode = PP_FASTREAD; rc = ioctl (fd, PPSETFLAGS, &mode); if (rc) DBG (0, "EPPcmdGetBuffer610p: ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); #endif mode = IEEE1284_MODE_EPP | IEEE1284_DATA; rc = ioctl (fd, PPSETMODE, &mode); if (rc) { DBG (0, "EPPcmdGetBuffer610p: ppdev ioctl returned <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return 0; } if (sanei_umax_pp_getfull () == 1) { do { rc = read (fd, buffer + count, needed); } while (rc == EAGAIN); if (rc < 0) { DBG (0, "EPPcmdGetBuffer610p: ppdev read failed <%s> (%s:%d)\n", strerror (errno), __FILE__, __LINE__); return 0; } #ifdef IOLOG DBG (0, "insb *%d\n", rc); #endif needed = rc; } else { for (loop = 0; (loop < needed) && (wait==0); loop++) { status = Inb (STATUS) & 0xF8; if ((status != 0xD0) && (status != 0xC0) && (status != 0xC8)) { DBG (0, "EPPcmdGetBuffer610p found 0x%02X expected 0xD0 or 0xC0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } if (status == 0xC8) { wait = 1; needed=loop; } else { tmp = Inb (EPPDATA); buffer[count + loop] = tmp; } } } } else #endif /* HAVE_LINUX_PPDEV_H */ { Insb (EPPDATA, buffer + count, needed); } count += needed; disconnect610p (); } usleep (10000); /* ??? CMDSYNC (0x00); */ /* everything went fine */ return 1; } /* 1 OK, 0 failed */ static int cmdGetBuffer610p (int cmd, int len, unsigned char *buffer) { int status, i, tmp; int word[5]; int read, needed, max; if (gMode == UMAX_PP_PARPORT_EPP) return EPPcmdGetBuffer610p (cmd, len, buffer); /* first we set length and channel */ /* compute word */ word[0] = len / 65536; word[1] = (len / 256) % 256; word[2] = len % 256; word[3] = (cmd & 0x0F) | 0xC0; word[4] = -1; connect610p (); sync610p (); if (sendLength610p (word) == 0) { DBG (0, "sendLength610p(word) failed... (%s:%d)\n", __FILE__, __LINE__); return 0; } status = getStatus610p (); scannerStatus = status; if ((status != 0xC0) && (status != 0xD0)) { DBG (1, "Found 0x%X expected 0xC0 or 0xD0 (%s:%d)\n", status, __FILE__, __LINE__); return 0; } disconnect610p (); if (sanei_umax_pp_getfull () == 1) max = 2550 / 3; else max = 32768; read = 0; while (read < len) { if (len - read > max) needed = max; else needed = len - read; if (sanei_umax_pp_getfull () == 0) status = getStatus610p (); else status = 0x20; /* wait for data ready */ while ((status & 0x80) == 0x00) { connect610p (); Outb (CONTROL, 0x07); Outb (DATA, 0xFF); tmp = Inb (DATA); if (tmp != 0xFF) { DBG (0, "cmdGetBuffer610p found 0x%02X expected 0xFF (%s:%d)\n", tmp, __FILE__, __LINE__); return 0; } status = Inb (STATUS) & 0xF8; if ((status & 0x80) == 0x00) disconnect610p (); else { Outb (CONTROL, 0x04); sync610p (); byteMode (); } } i = 0; while (i < needed) { if (sanei_umax_pp_getfull () == 0) { status = Inb (STATUS) & 0xF8; if (status == 0xC8) { for (tmp = 0; tmp < 18; tmp++) status = Inb (STATUS) & 0xF8; break; } } Outb (CONTROL, 0x26); /* data reverse+ 'reg' */ buffer[read + i] = Inb (DATA); Outb (CONTROL, 0x24); /* data reverse+ 'reg' */ i++; } byteMode (); disconnect610p (); read += i; } return 1; } /* 1 OK, 0 failed */ static int cmdGetBuffer (int cmd, int len, unsigned char *buffer) { int reg, tmp; int word[5], read; int needed; if (sanei_umax_pp_getastra () == 610) return cmdGetBuffer610p (cmd, len, buffer); /* compute word */ word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x0F) | 0xC0; word[4] = -1; /* send word: len+addr(?) */ if (foncSendWord (word) == 0) { DBG (0, "foncSendWord(word) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "(%s:%d) passed \n", __FILE__, __LINE__); prologue (0x10); REGISTERWRITE (0x0E, 0x0D); REGISTERWRITE (0x0F, 0x00); reg = registerRead (0x19) & 0xF8; /* wait if busy */ while ((reg & 0x08) == 0x08) reg = registerRead (0x19) & 0xF8; if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "cmdGetBuffer failed (%s:%d)\n", __FILE__, __LINE__); return 0; } if (gMode == UMAX_PP_PARPORT_ECP) { REGISTERWRITE (0x1A, 0x44); } read = 0; reg = registerRead (0x0C); if (reg != 0x04) { DBG (0, "cmdGetBuffer failed: unexpected status 0x%02X ...(%s:%d)\n", reg, __FILE__, __LINE__); return 0; } REGISTERWRITE (0x0C, reg | 0x40); /* actual data */ read = 0; while (read < len) { needed = len - read; if (needed > 32768) needed = 32768; if (gMode == UMAX_PP_PARPORT_ECP) { compatMode (); Outb (CONTROL, 0x04); /* reset ? */ ECPSetBuffer (needed); tmp = ECPbufferRead (needed, buffer + read); DBG (16, "ECPbufferRead(%d,buffer+read) passed (%s:%d)\n", needed, __FILE__, __LINE__); REGISTERWRITE (0x1A, 0x84); } else { tmp = pausedBufferRead (needed, buffer + read); } if (tmp < needed) { DBG (64, "cmdGetBuffer only got %d bytes out of %d ...(%s:%d)\n", tmp, needed, __FILE__, __LINE__); } else { DBG (64, "cmdGetBuffer got all %d bytes out of %d , read=%d...(%s:%d)\n", tmp, 32768, read, __FILE__, __LINE__); } read += tmp; DBG (16, "Read %d bytes out of %d (last block is %d bytes) (%s:%d)\n", read, len, tmp, __FILE__, __LINE__); if (read < len) { /* wait for scanner to be ready */ reg = registerRead (0x19) & 0xF8; DBG (64, "Status after block read is 0x%02X (%s:%d)\n", reg, __FILE__, __LINE__); if ((reg & 0x08) == 0x08) { int pass = 0; do { reg = registerRead (0x19) & 0xF8; usleep (100); pass++; } while ((pass < 32768) && ((reg & 0x08) == 0x08)); DBG (64, "Status after waiting is 0x%02X (pass=%d) (%s:%d)\n", reg, pass, __FILE__, __LINE__); if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n", reg, __FILE__, __LINE__); DBG (0, "Going on...\n"); } } /* signal we want next data chunk */ if (gMode == UMAX_PP_PARPORT_ECP) { REGISTERWRITE (0x1A, 0x44); } reg = registerRead (0x0C); registerWrite (0x0C, reg | 0x40); } } /* OK ! */ REGISTERWRITE (0x0E, 0x0D); REGISTERWRITE (0x0F, 0x00); /* epilogue */ epilogue (); return 1; } /* 1 OK, 0 failed */ static int cmdGetBuffer32 (int cmd, int len, unsigned char *buffer) { int reg, tmp; int word[5], read; /* compute word */ word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x3F) | 0x80 | 0x40; if (!prologue (0x10)) { DBG (0, "cmdSet: prologue failed ! (%s:%d)\n", __FILE__, __LINE__); return 0; } /* send data */ if (sendLength (word, 4) == 0) { DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } TRACE (16, "sendLength(word,4) passed ..."); /* head end */ epilogue (); prologue (0x10); REGISTERWRITE (0x0E, 0x0D); REGISTERWRITE (0x0F, 0x00); reg = registerRead (0x19) & 0xF8; /* wait if busy */ while ((reg & 0x08) == 0x08) reg = registerRead (0x19) & 0xF8; if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "cmdGetBuffer32 failed: unexpected status 0x%02X ...(%s:%d)\n", reg, __FILE__, __LINE__); return 0; } reg = registerRead (0x0C); if (reg != 0x04) { DBG (0, "cmdGetBuffer32 failed: unexpected status 0x%02X ...(%s:%d)\n", reg, __FILE__, __LINE__); return 0; } REGISTERWRITE (0x0C, reg | 0x40); read = 0; while (read < len) { if (read + 1700 < len) { tmp = 1700; bufferRead (tmp, buffer + read); reg = registerRead (0x19) & 0xF8; if ((read + tmp < len) && (reg & 0x08) == 0x08) { do { reg = registerRead (0x19) & 0xF8; } while ((reg & 0x08) == 0x08); if ((reg != 0xC0) && (reg != 0xD0)) { DBG (0, "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n", reg, __FILE__, __LINE__); DBG (0, "Going on...\n"); } } reg = registerRead (0x0C); registerWrite (0x0C, reg | 0x40); read += tmp; } else { tmp = len - read; bufferRead (tmp, buffer + read); read += tmp; if ((read < len)) { reg = registerRead (0x19) & 0xF8; while ((reg & 0x08) == 0x08) { reg = registerRead (0x19) & 0xF8; } } } } /* OK ! */ epilogue (); return 1; } int sanei_umax_pp_cmdSync (int cmd) { int word[5]; if (sanei_umax_pp_getastra () == 610) return cmdSync610p (cmd); /* compute word */ word[0] = 0x00; word[1] = 0x00; word[2] = 0x00; word[3] = cmd; if (!prologue (0x10)) { DBG (0, "cmdSync: prologue failed ! (%s:%d)\n", __FILE__, __LINE__); } /* send data */ if (sendLength (word, 4) == 0) { DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } TRACE (16, "sendLength(word,4) passed ..."); /* end OK */ epilogue (); return 1; } /* numbers of bytes read, else 0 (failed) */ /* read data by chunk EXACTLY the width of the scan area in the given */ /* resolution . If a valid file descriptor is given, we write data */ /* in it according to the color mode, before polling the scanner */ /* len should not be bigger than 2 Megs */ int cmdGetBlockBuffer (int cmd, int len, int window, unsigned char *buffer) { #ifdef HAVE_SYS_TIME_H struct timeval td, tf; float elapsed; #endif int reg; int word[5], read; /* compute word */ word[0] = len / 65536; word[1] = len / 256 % 256; word[2] = len % 256; word[3] = (cmd & 0x3F) | 0x80 | 0x40; if (!prologue (0x10)) { DBG (0, "cmdGetBlockBuffer: prologue failed ! (%s:%d)\n", __FILE__, __LINE__); } /* send data */ if (sendLength (word, 4) == 0) { DBG (0, "sendLength(word,4) failed (%s:%d)\n", __FILE__, __LINE__); return 0; } TRACE (16, "sendLength(word,4) passed ..."); /* head end */ epilogue (); if (!prologue (0x10)) { DBG (0, "cmdGetBlockBuffer: prologue failed ! (%s:%d)\n", __FILE__, __LINE__); } REGISTERWRITE (0x0E, 0x0D); REGISTERWRITE (0x0F, 0x00); /* init counter */ read = 0; /* read scanner state */ reg = registerRead (0x19) & 0xF8; /* read loop */ while (read < len) { /* wait for the data to be ready */ #ifdef HAVE_SYS_TIME_H gettimeofday (&td, NULL); #endif while ((reg & 0x08) == 0x08) { reg = registerRead (0x19) & 0xF8; #ifdef HAVE_SYS_TIME_H gettimeofday (&tf, NULL); elapsed = ((tf.tv_sec * 1000000 + tf.tv_usec) - (td.tv_sec * 1000000 + td.tv_usec)) / 1000000; if (elapsed > 3) { DBG (0, "Time-out (%.2f s) waiting for scanner ... giving up on status 0x%02X ! (%s:%d)\n", elapsed, reg, __FILE__, __LINE__); epilogue (); return read; } #endif } if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0x00)) { DBG (0, "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n", reg, __FILE__, __LINE__); DBG (0, "Going on...\n"); } /* signals next chunk */ reg = registerRead (0x0C); if (reg != 0x04) { DBG (0, "cmdGetBlockBuffer failed: unexpected value reg0C=0x%02X ...(%s:%d)\n", reg, __FILE__, __LINE__); return 0; } REGISTERWRITE (0x0C, reg | 0x40); /* there is always a full block ready when scanner is ready */ /* 32 bits I/O read , window must match the width of scan */ bufferRead (window, buffer + read); /* add bytes read */ read += window; DBG (16, "Read %d bytes out of %d (last block is %d bytes) (%s:%d)\n", read, len, window, __FILE__, __LINE__); /* test status after read */ reg = registerRead (0x19) & 0xF8; } /* wait for the data to be ready */ #ifdef HAVE_SYS_TIME_H gettimeofday (&td, NULL); #endif while ((reg & 0x08) == 0x08) { reg = registerRead (0x19) & 0xF8; #ifdef HAVE_SYS_TIME_H gettimeofday (&tf, NULL); elapsed = ((tf.tv_sec * 1000000 + tf.tv_usec) - (td.tv_sec * 1000000 + td.tv_usec)) / 1000000; if (elapsed > 3) { DBG (0, "Time-out (%.2f s) waiting for scanner ... giving up on status 0x%02X ! (%s:%d)\n", elapsed, reg, __FILE__, __LINE__); epilogue (); return read; } #endif } if ((reg != 0xC0) && (reg != 0xD0) && (reg != 0x00)) { DBG (0, "Unexpected status 0x%02X, expected 0xC0 or 0xD0 ! (%s:%d)\n", reg, __FILE__, __LINE__); DBG (0, "Going on...\n"); } REGISTERWRITE (0x0E, 0x0D); REGISTERWRITE (0x0F, 0x00); /* OK ! */ epilogue (); return read; } /* * encodes DC offsets: must be in [0..0x0F] range */ static void encodeDC (int dcRed, int dcGreen, int dcBlue, int *motor) { motor[11] = (motor[11] & 0x0F) | dcRed << 4; motor[12] = (motor[12] & 0xC3) | dcGreen << 2; motor[13] = (motor[13] & 0xF0) | dcBlue; } static void decodeDC (int *motor) { DBG (0, "DC (R,G,B)=(%d,%d,%d)\n", (motor[11] & 0xF0) >> 4, (motor[12] & 0x3C) >> 2, motor[13] & 0x0F); } /* * encodes VGA : must be in [0..0x0F] range */ static void encodeVGA (int vgaRed, int vgaGreen, int vgaBlue, int *motor) { if (sanei_umax_pp_getastra () > 610) { motor[10] = (vgaRed << 4) | vgaGreen; motor[11] = (motor[11] & 0xF0) | vgaBlue; } else { motor[10] = (vgaGreen << 4) | vgaBlue; motor[11] = (motor[11] & 0xF0) | vgaRed; /* ancien F00: vert 0F0: bleu 00F: rouge motor[10] = (vgaRed << 4) | vgaGreen; motor[11] = (motor[11] & 0xF0) | vgaBlue; */ } } static void decodeVGA (int *motor) { if (sanei_umax_pp_getastra () > 610) { DBG (0, "VGA (R,G,B)=(%d,%d,%d)\n", (motor[10] & 0xF0) >> 4, (motor[10] & 0x0F), (motor[11] & 0x0F)); } else { DBG (0, "VGA (R,G,B)=(%d,%d,%d)\n", (motor[11] & 0x0F), (motor[10] & 0xF0) >> 4, (motor[10] & 0x0F)); } } /* * this function encodes total head movement which includes * y movement and scan area height * height is scan area height * ypos is head movement before scan * total move will be ypos+height */ static void encodeHY (int height, int ypos, int *motor) { motor[0] = height % 256; motor[1] = (height / 256) & 0x3F; motor[1] = motor[1] | (ypos & 0x03) << 6; motor[2] = (ypos >> 2) % 256; motor[3] = (motor[3] & 0xF0) | ((ypos >> 10) & 0x0F); } /* * this function encodes x start and x end on the CCD * w is width of scanning area * x is start of scanning area * dpi is x resolution * color is non zero if scanning in color * bytes is on aoverride for bpl, since it sin't clear today when * the formula has to be applied */ static void encodeWX (int width, int xstart, int dpi, int color, int *ccd, int bytes) { int xend; int bpl; int x; xend = xstart + width; x = xstart - 1; /* x start encoding */ ccd[17] = x % 256; ccd[18] = (ccd[18] & 0xF0) | ((x / 256) & 0x0F); /* models >=1220P have a 600 dpi CCD: x is bigger */ if (sanei_umax_pp_getastra () > 610) { if (x > 0x1000) ccd[33] |= 0x40; else ccd[33] &= 0xBF; } /* x end encoding */ ccd[18] = (ccd[18] & 0x0F) | ((xend % 16) << 4); ccd[19] = (xend / 16) % 256; /* models >=1220P have a 600 dpi CCD: x is bigger */ if (sanei_umax_pp_getastra () > 610) { if (xend > 0x1000) ccd[33] |= 0x80; else ccd[33] &= 0x7F; } /* now bytes per line */ /* bpl = (op[24] - 0x41) * 256 + 8192 * (op[34] & 0x01) + op[23]; */ bpl = (color == 0 ? 1 : 3) * width * dpi; if (sanei_umax_pp_getastra () > 610) { bpl /= 600; if (bpl >= 8192) ccd[34] |= 0x01; else ccd[34] &= 0xFE; } else { bpl /= 300; } if (bytes > 0) bpl = bytes; ccd[23] = bpl % 256; ccd[24] = 0x41 + ((bpl / 256) & 0x1F); } /* cropping coefficient: last 2 bytes gives the coefficient applied */ /* to data scanned to get the actual image resolution */ static void encodeCoefficient (int color, int dpi, int *calibration) { int w, idx = 0; int *coeff; /* 75, 150, 300, 600 and 1200 dpi */ int color610p[4][2] = { {0x88, 0x88}, {0xAA, 0xAA}, {0xFF, 0xFF}, {0xFF, 0xFF} }; int gray610p[4][2] = { {0x88, 0x01}, {0xAA, 0x11}, {0xFF, 0xAA}, {0xFF, 0xFF} }; /* FF means coeff=1 * AA coeff=1/2 * 88 coeff=1/4 * 80 coeff=1/8 * first coeff for CCD (x) * second coeff for motor steps (y) */ int color1220p[5][2] = { {0x80, 0xAA}, {0x88, 0xFF}, {0xAA, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} }; int gray1220p[5][2] = { {0x80, 0x88}, {0x88, 0xAA}, {0xAA, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF} }; switch (dpi) { case 1200: idx = 4; break; case 600: idx = 3; break; case 300: idx = 2; break; case 150: idx = 1; break; case 75: idx = 0; break; } if (sanei_umax_pp_getastra () < 1210) { w = 2550; if (color >= RGB_MODE) coeff = color610p[idx]; else coeff = gray610p[idx]; } else { w = 5100; if (color >= RGB_MODE) coeff = color1220p[idx]; else coeff = gray1220p[idx]; } /* x coefficient */ calibration[3 * w + 768] = coeff[0]; /* y coefficient */ calibration[3 * w + 769] = coeff[1]; } static void bloc2Decode (int *op) { int i; int scanh; int skiph; int dpi = 0; int dir = 0; int color = 0; char str[64]; for (i = 0; i < 16; i++) sprintf (str + 3 * i, "%02X ", (unsigned char) op[i]); str[48] = 0x00; DBG (0, "Command bloc 2: %s\n", str); scanh = op[0] + (op[1] & 0x3F) * 256; skiph = ((op[1] & 0xC0) >> 6) + (op[2] << 2) + ((op[3] & 0x0F) << 10); if (op[3] & 0x10) dir = 1; else dir = 0; /* XXX STEF XXX seems to conflict with DC definitions */ if (op[13] & 0x40) color = 1; else color = 0; /* op[6]=0x60 at 600 and 1200 dpi */ if ((op[8] == 0x17) && (op[9] != 0x05)) dpi = 150; if ((op[8] == 0x17) && (op[9] == 0x05)) dpi = 300; if ((op[9] == 0x05) && (op[14] & 0x08)) dpi = 1200; if ((dpi == 0) && ((op[14] & 0x08) == 0)) dpi = 600; DBG (0, "\t->scan height =0x%04X (%d)\n", scanh, scanh); DBG (0, "\t->skip height =0x%04X (%d)\n", skiph, skiph); DBG (0, "\t->y dpi =0x%04X (%d)\n", dpi, dpi); decodeVGA (op); decodeDC (op); if (dir) DBG (0, "\t->forward direction\n"); else DBG (0, "\t->reverse direction\n"); if (color) DBG (0, "\t->color scan \n"); else DBG (0, "\t->no color scan \n"); /* byte 14 */ if (op[14] & 0x20) { DBG (0, "\t->lamp on \n"); } else { DBG (0, "\t->lamp off \n"); } if (op[14] & 0x04) { DBG (0, "\t->normal scan (head stops at each row) \n"); } else { DBG (0, "\t->move and scan (head doesn't stop at each row) \n"); } DBG (0, "\n"); } static void bloc8Decode (int *op) { int i, bpl; int xskip; int xend, len; char str[128]; if (sanei_umax_pp_getastra () < 1220) len = 34; else len = 36; for (i = 0; i < len; i++) sprintf (str + 3 * i, "%02X ", (unsigned char) op[i]); str[3 * i] = 0x00; DBG (0, "Command bloc 8: %s\n", str); xskip = op[17] + 256 * (op[18] & 0x0F); if (op[33] & 0x40) xskip += 0x1000; xend = (op[18] & 0xF0) / 16 + 16 * op[19]; if (op[33] & 0x80) xend += 0x1000; if (len > 34) bpl = (op[24] - 0x41) * 256 + 8192 * (op[34] & 0x01) + op[23]; else bpl = (op[24] - 0x41) * 256 + op[23]; DBG (0, "\t->xskip =0x%X (%d)\n", xskip, xskip); DBG (0, "\t->xend =0x%X (%d)\n", xend, xend); DBG (0, "\t->scan width=0x%X (%d)\n", xend - xskip - 1, xend - xskip - 1); DBG (0, "\t->bytes/line=0x%X (%d)\n", bpl, bpl); DBG (0, "\t->raw =0x%X (%d)\n", op[24] * 256 + op[23], op[24] * 256 + op[23]); DBG (0, "\n"); } static int completionWait (void) { /* for 610P, wait and sync is done while * reading data from the scanner */ CMDSYNC (0x40); usleep (100000); CMDSYNC (0xC2); if ((sanei_umax_pp_getastra () == 610) || ((sanei_umax_pp_scannerStatus () & 0x90) == 0x90)) return 1; do { usleep (100000); CMDSYNC (0xC2); } while ((sanei_umax_pp_scannerStatus () & 0x90) != 0x90); CMDSYNC (0xC2); return 1; } int sanei_umax_pp_setLamp (int on) { int buffer[17]; int state; /* reset? */ sanei_umax_pp_cmdSync (0x00); sanei_umax_pp_cmdSync (0xC2); sanei_umax_pp_cmdSync (0x00); /* get status */ cmdGet (0x02, 16, buffer); state = buffer[14] & LAMP_STATE; buffer[16] = -1; if ((state == 0) && (on == 0)) { DBG (0, "Lamp already off ... (%s:%d)\n", __FILE__, __LINE__); return 1; } if ((state) && (on)) { DBG (2, "Lamp already on ... (%s:%d)\n", __FILE__, __LINE__); return 1; } /* set lamp state */ if (on) buffer[14] = buffer[14] | LAMP_STATE; else buffer[14] = buffer[14] & ~LAMP_STATE; CMDSETGET (0x02, 16, buffer); TRACE (16, "setLamp passed ..."); return 1; } static int num = 0; static void Dump (int len, unsigned char *data, char *name) { FILE *fic; char titre[80]; if (name == NULL) { sprintf (titre, "dump%04d.bin", num); num++; } else { sprintf (titre, "%s", name); } fic = fopen (titre, "wb"); if (fic == NULL) { DBG (0, "could not open %s for writing\n", titre); return; } fwrite (data, 1, len, fic); fclose (fic); } static void DumpNB (int width, int height, unsigned char *data, char *name) { FILE *fic; char titre[80]; if (name == NULL) { sprintf (titre, "dump%04d.pnm", num); num++; } else { sprintf (titre, "%s", name); } fic = fopen (titre, "wb"); if (fic == NULL) { DBG (0, "could not open %s for writing\n", titre); return; } fprintf (fic, "P5\n%d %d\n255\n", width, height); fwrite (data, width, height, fic); fclose (fic); } /* dump data has received from scanner (red line/green line/blue line) to a color pnm file */ static void DumpRVB (int width, int height, unsigned char *data, char *name) { FILE *fic; char titre[80]; int y, x; if (name == NULL) { sprintf (titre, "dump%04d.pnm", num); num++; } else { sprintf (titre, "%s", name); } fic = fopen (titre, "wb"); if (fic == NULL) { DBG (0, "could not open %s for writing\n", titre); return; } fprintf (fic, "P6\n%d %d\n255\n", width, height); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { fputc (data[3 * y * width + 2 * width + x], fic); fputc (data[3 * y * width + width + x], fic); fputc (data[3 * y * width + x], fic); } } fclose (fic); } /* dump a color buffer in a color PNM */ static void DumpRGB (int width, int height, unsigned char *data, char *name) { FILE *fic; char titre[80]; int y, x; if (name == NULL) { sprintf (titre, "dump%04d.pnm", num); num++; } else { sprintf (titre, "%s", name); } fic = fopen (titre, "wb"); fprintf (fic, "P6\n%d %d\n255\n", width, height); if (fic == NULL) { DBG (0, "could not open %s for writing\n", titre); return; } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { fputc (data[3 * y * width + x * 3], fic); fputc (data[3 * y * width + x * 3 + 1], fic); fputc (data[3 * y * width + x * 3 + 2], fic); } } fclose (fic); } static int evalGain (int sum, int count) { int gn; float pct; float avg; float area=50; float coeff=2.5; float cnst=0.9; /* after ~ 60 * 10 scans , it looks like 1 step is a 0.57% increase */ /* so we take the value and compute the percent increase to reach 250 */ /* (target code) not 255, because we want some room for inaccuracy */ /* pct=100-(value*100)/250 */ /* then correction is pct/0.57 */ avg = (float) (sum) / (float) (count); pct = 100.0 - (avg * 100.0) / targetCode; gn = (int) (pct / 0.57); /* give gain for dark areas a boost */ #ifdef UMAX_PP_DANGEROUS_EXPERIMENT if(getenv("AREA")!=NULL) cnst=atol(getenv("AREA")); if(getenv("COEFF")!=NULL) cnst=atol(getenv("COEFF")); if(getenv("CNST")!=NULL) cnst=atol(getenv("CNST")); #endif pct = gn; avg = exp((-pct)/area)*coeff+cnst; gn = gn * avg; /* bound checking : there are sightings of >127 values being negative */ if (gn < 0) gn = 0; else if (gn > 127) gn = 127; return gn; } static void computeCalibrationData (int color, int width, unsigned char *source, int *data) { int p, i, l; int sum; memset (data, 0, (3 * 5100 + 768 + 3) * sizeof (int)); /* 0 -> 5099 */ for (i = 0; i < width; i++) { /* red calibration data */ if (color >= RGB_MODE) { /* compute average */ sum = 0; for (l = 0; l < 66; l++) sum += source[i + l * 5100 * 3]; data[i] = evalGain (sum, l); } else data[i] = 0x00; } /* 5100 -> 10199: green data */ p = 5100; for (i = 0; i < width; i++) { /* compute average */ sum = 0; for (l = 0; l < 66; l++) sum += source[i + l * 5100 * 3 + 5100]; data[p + i] = evalGain (sum, l); } /* 10200 -> 15299: blue */ p = 10200; for (i = 0; i < width; i++) { if (color >= RGB_MODE) { /* compute average */ sum = 0; for (l = 0; l < 66; l++) sum += source[i + l * 5100 * 3 + 5100 * 2]; data[p + i] = evalGain (sum, l); } else data[p + i] = 0x00; } /* gamma tables */ for (i = 0; i < 256; i++) data[15300 + i] = ggRed[i]; for (i = 0; i < 256; i++) data[15300 + 256 + i] = ggGreen[i]; for (i = 0; i < 256; i++) data[15300 + 512 + i] = ggBlue[i]; data[16070] = -1; } /* move head by the distance given using precision or not */ /* 0: failed 1: success */ static int move (int distance, int precision, unsigned char *buffer) { int header[17] = { 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x01, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x00, -1 }; int body[37] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x6E, 0xF6, 0x79, 0xBF, 0x01, 0x00, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; int end[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 }; int steps, len, cmdlen; unsigned char tmp[0x200]; unsigned char *ptr; if (distance == 0) return 0; if (buffer == NULL) ptr = tmp; else ptr = buffer; /* build commands */ if (distance < 0) { /* header */ steps = -distance - 1; header[3] = 0x20; header[9] = 0x01; /* reverse direction body by default */ /* end */ end[1] = 0xFF; end[2] = 0xFF; end[3] = -1; len = 3; } else { /* header */ steps = distance - 1; header[3] = 0x70; header[9] = 0x05; /* body */ body[2] = 0x04; body[4] = 0x02; body[7] = 0x0C; body[9] = 0x04; body[10] = 0x40; body[11] = 0x01; /* end */ len = 8; } if (steps > 0) { encodeHY (1, steps, header); } if (sanei_umax_pp_getastra () < 1220) { header[6] = 0xC0; body[16] = 0x76; /* encodeWX */ body[17] = 0x00; body[18] = 0x15; body[19] = 0x70; body[20] = 0x01; body[21] = 0x00; body[28] = 0x4D; body[29] = 0x4B; body[30] = 0xD0; cmdlen = 0x22; } else cmdlen = 0x24; /* precision: default header set to precision on */ if (precision == PRECISION_OFF) { if (sanei_umax_pp_getastra () == 1600) header[8] = 0x15; else header[8] = 0x17; if (sanei_umax_pp_getastra () > 610) header[14] = 0xAC; body[20] = 0x06; } CMDSETGET (0x02, 16, header); CMDSETGET (0x08, cmdlen, body); if (DBG_LEVEL >= 128) { bloc2Decode (header); bloc8Decode (body); } CMDSYNC (0xC2); if ((sanei_umax_pp_scannerStatus () & 0x80) || (sanei_umax_pp_getastra () < 1220)) { CMDSYNC (0x00); } CMDSETGET (4, len, end); COMPLETIONWAIT; CMDGETBUF (4, 0x200, ptr); if (DBG_LEVEL >= 128) { Dump (0x200, ptr, NULL); } DBG (16, "MOVE STATUS IS 0x%02X (%s:%d)\n", sanei_umax_pp_scannerStatus (), __FILE__, __LINE__); CMDSYNC (0x00); return 1; } /* for each column, finds the row where white/black transition occurs then returns the average */ static float edgePosition (int width, int height, unsigned char *data) { int ecnt, x, y; float epos; int d, dmax, dpos, i; unsigned char *dbuffer = NULL; if (DBG_LEVEL > 128) { dbuffer = (unsigned char *) malloc (3 * width * height); memset (dbuffer, 0x00, 3 * width * height); } epos = 0; ecnt = 0; for (x = 0; x < width; x++) { /* edge: white->black drop */ /* loop stops on black area */ dmax = 0; dpos = 0; d = 0; i = 0; for (y = 10; (y < height) && (data[i] > 10); y++) { i = x + y * width; d = data[i - width] - data[i]; if (d > dmax) { dmax = d; dpos = y; } if ((DBG_LEVEL > 128) && (dbuffer != NULL)) { dbuffer[i * 3] = data[i]; dbuffer[i * 3 + 1] = data[i]; dbuffer[i * 3 + 2] = data[i]; } } epos += dpos; ecnt++; if ((DBG_LEVEL > 128) && (dbuffer != NULL)) { dbuffer[(x + dpos * width) * 3] = 0xFF; dbuffer[(x + dpos * width) * 3 + 1] = 0x00; dbuffer[(x + dpos * width) * 3 + 2] = 0x00; } } if (ecnt == 0) epos = 70; else epos = epos / ecnt; if ((DBG_LEVEL > 128) && (dbuffer != NULL)) { i = ((int) epos) * width; for (x = 0; x < width; x++) { dbuffer[(x + i) * 3] = 0x00; dbuffer[(x + i) * 3 + 1] = 0xFF; dbuffer[(x + i) * 3 + 2] = 0xFF; } for (y = 0; y < height; y++) { dbuffer[(width / 2 + y * width) * 3] = 0x00; dbuffer[(width / 2 + y * width) * 3 + 1] = 0xFF; dbuffer[(width / 2 + y * width) * 3 + 2] = 0x00; } DumpRGB (width, height, dbuffer, NULL); free (dbuffer); } return epos; } static int moveToOrigin (void) { unsigned char buffer[54000]; float edge; int val, delta = 188; int header[17] = { 0xB4, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x05, 0x00, 0x00, 0x00, 0x80, 0xA4, 0x00, -1 }; int body[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6E, 0xFB, 0xC4, 0xE5, 0x06, 0x00, 0x00, 0x60, 0x4D, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; int end[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x08, 0x00, -1 }; int opsc03[9] = { 0x00, 0x00, 0x00, 0xAA, 0xCC, 0xEE, 0x80, 0xFF, -1 }; int w = 300, h = 180, len = 36; switch (sanei_umax_pp_getastra ()) { case 1600: header[8] = 0x2B; body[29] = 0x1A; body[30] = 0xEE; end[0] = 0x19; end[1] = 0xD5; end[4] = 0x1B; case 1220: case 2000: w = 300; h = 180; len = 36; delta = -188; CMDSYNC (0x00); CMDSYNC (0xC2); CMDSYNC (0x00); MOVE (196, PRECISION_OFF, NULL); break; case 610: w = 512; h = 90; len = 34; delta = -81; opsc03[6] = 0xFF; /* instead of 0x80 */ encodeHY (h, 60, header); /* will add encodeDpi(dpi,cmd) */ header[6] = 0xC0; header[8] = 0x17; body[13] = 0x20; body[14] = 0x02; body[16] = 0x76; encodeWX (0x200, 0x501, 300, 0, body, 0x500); /* fixed values for all 610p commands */ body[28] = 0x4D; body[29] = 0x4B; body[30] = 0xD0; /* LM9811 command block ? */ end[0] = 0x88; end[1] = 0xE6; end[2] = 0xFD; end[3] = 0x8E; end[4] = 0x30; break; } /* scan an area where is a white and a black regions, which */ /* can be detected and gives this offset to the origin of the */ /* scanning windows */ CMDSETGET (2, 0x10, header); CMDSETGET (8, len, body); CMDSETGET (1, 0x08, end); CMDSYNC (0xC2); CMDSYNC (0x00); /* signals black & white ? */ CMDSETGET (4, 8, opsc03); COMPLETIONWAIT; CMDGETBUF (4, w * h, buffer); /* get find position data */ if (DBG_LEVEL > 128) { DumpNB (w, h, buffer, NULL); } /* detection of 1600P is a by product of origin finding */ edge = 0.0; for (val = 0; val < w * h; val++) if (buffer[val] > edge) edge = buffer[val]; DBG (32, "MAX VALUE=%f (%s:%d)\n", edge, __FILE__, __LINE__); if ((edge <= 30) && (sanei_umax_pp_getastra () != 1600)) { DBG (2, "moveToOrigin() detected a 1600P"); sanei_umax_pp_setastra (1600); } edge = edgePosition (w, h, buffer); /* rounded to lowest integer, since upping origin might lead */ /* to bump in the other side if doing a full size preview */ val = (int) (edge); delta += val; DBG (64, "Edge=%f, val=%d, delta=%d\n", edge, val, delta); /* move back to y-coordinate origin */ if (sanei_umax_pp_getastra () < 1220) { MOVE (delta, PRECISION_OFF, NULL); } else { MOVE (delta, PRECISION_ON, NULL); } /* head successfully set to the origin */ return 1; } /* park head: returns 1 on success, 0 otherwise */ int sanei_umax_pp_park (void) { int header610[17] = { 0x01, 0x00, 0x01, 0x40, 0x30, 0x00, 0xC0, 0x2F, 0x17, 0x05, 0x00, 0x00, 0x00, 0x80, 0xF4, 0x00, -1 }; int body610[35] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x00, 0x20, 0x02, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x1B, -1 }; int header[17] = { 0x01, 0x00, 0x01, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x13, 0x05, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x00, -1 }; int body[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x80, 0x15, 0x78, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x1B, 0x1A, 0x00, -1 }; int status = 0x90; CMDSYNC (0x00); if (sanei_umax_pp_getastra () > 610) { CMDSETGET (0x02, 0x10, header); CMDSETGET (0x08, 0x24, body); } else { CMDSETGET (0x02, 0x10, header610); CMDSETGET (0x08, 0x22, body610); } CMDSYNC (0x40); status = sanei_umax_pp_scannerStatus (); DBG (16, "PARKING STATUS is 0x%02X (%s:%d)\n", status, __FILE__, __LINE__); DBG (1, "Park command issued ...\n"); return 1; } /* calibrates CCD: returns 1 on success, 0 on failure */ static int shadingCalibration1220p (int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration) { int opsc32[17] = { 0x4A, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x17, 0x05, 0xA5, 0x08, 0x00, 0x00, 0xAC, 0x00, -1 }; int opsc41[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6E, 0x90, 0xD0, 0x47, 0x06, 0x00, 0x00, 0xC4, 0x5C, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1B, 0x00, -1 }; int opscnb[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6E, 0x90, 0xD0, 0x47, 0x06, 0x00, 0x00, 0xEC, 0x54, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1A, 0x00, -1 }; int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 }; int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 }; int size; int width = 5100; /* full usable CCD width */ unsigned char buffer[0x105798]; /* 1600P have a different CCD command block */ if (sanei_umax_pp_getastra () == 1600) { opsc04[0] = 0x19; opsc04[1] = 0xD5; opsc04[4] = 0x1B; opsc41[29] = 0x1A; opsc41[30] = 0xEE; } /* step back by 67 ticks: */ /* since we're going to scan 66 lines of data */ /* which are going to be used as calibration */ /* data */ /* we are on the white area just before */ /* the user scan area */ MOVE (-67, PRECISION_ON, NULL); CMDSYNC (0x00); /* get calibration data */ /* if (sanei_umax_pp_getauto ()) { auto settings doesn't use offset offset = 0x000; } else { manual settings gain = 0x777; offset = 0x000; } */ encodeDC (dcRed, dcGreen, dcBlue, opsc32); encodeVGA (vgaRed, vgaGreen, vgaBlue, opsc32); if (sanei_umax_pp_getastra () == 1600) { opsc32[13] = 0x03; } /* 1220P/2000P shading calibration */ if (color < RGB_MODE) { opsc32[0] -= 4; opsc32[13] = 0xC0; } CMDSETGET (2, 0x10, opsc32); if (DBG_LEVEL >= 64) { bloc2Decode (opsc32); } if (color < RGB_MODE) { CMDSETGET (8, 0x24, opscnb); if (DBG_LEVEL >= 64) { bloc8Decode (opscnb); } opsc04[6] = 0x85; } else { CMDSETGET (8, 0x24, opsc41); if (DBG_LEVEL >= 64) { bloc8Decode (opsc41); } opsc04[6] = 0x0F; if (sanei_umax_pp_getastra () == 1600) opsc04[7] = 0xC0; else opsc04[7] = 0x70; } /* BUG BW noisy here */ CMDSETGET (1, 0x08, opsc04); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); /* opsc03 hangs it */ COMPLETIONWAIT; opsc04[0] = 0x06; if (color >= RGB_MODE) size = 3 * width * 70; else size = width * 66; if (getEPPMode () == 32) { cmdGetBuffer32 (4, size, buffer); } else { CMDGETBUF (4, size, buffer); } if (DBG_LEVEL >= 128) { Dump (size, buffer, NULL); if (color >= RGB_MODE) { DumpRVB (width, 66, buffer, NULL); } else { DumpNB (width, 66, buffer, NULL); } } computeCalibrationData (color, width, buffer, calibration); DBG (1, "shadingCalibration1220p() done ...\n"); return 1; } /* returns number of bytes read or 0 on failure */ int sanei_umax_pp_readBlock (long len, int window, int dpi, int last, unsigned char *buffer) { DBG (8, "readBlock(%ld,%d,%d,%d)\n", len, window, dpi, last); /* EPP block reading is available only when dpi >=600 */ if ((dpi >= 600) && (gMode != UMAX_PP_PARPORT_ECP) && (sanei_umax_pp_getastra () > 610)) { DBG (8, "cmdGetBlockBuffer(4,%ld,%d);\n", len, window); len = cmdGetBlockBuffer (4, len, window, buffer); if (len == 0) { DBG (0, "cmdGetBlockBuffer(4,%ld,%d) failed (%s:%d)\n", len, window, __FILE__, __LINE__); gCancel = 1; } } else { if ((sanei_umax_pp_getastra () < 1210) && (len > 0xFDCE)) { len = 0xFDCE; last = 0; } DBG (8, "cmdGetBuffer(4,%ld);\n", len); if (cmdGetBuffer (4, len, buffer) != 1) { DBG (0, "cmdGetBuffer(4,%ld) failed (%s:%d)\n", len, __FILE__, __LINE__); gCancel = 1; } } if (!last) { /* sync with scanner */ if (sanei_umax_pp_cmdSync (0xC2) == 0) { DBG (0, "Warning cmdSync(0xC2) failed! (%s:%d)\n", __FILE__, __LINE__); DBG (0, "Trying again ...\n"); if (sanei_umax_pp_cmdSync (0xC2) == 0) { DBG (0, " failed again! (%s:%d)\n", __FILE__, __LINE__); DBG (0, "Aborting ...\n"); gCancel = 1; } else DBG (0, " success ...\n"); } } return len; } int sanei_umax_pp_scan (int x, int y, int width, int height, int dpi, int color, int gain, int offset) { #ifdef HAVE_SYS_TIME_H struct timeval td, tf; float elapsed; #endif unsigned char *buffer; long int somme, len, read, blocksize; FILE *fout = NULL; int *dest = NULL; int bpl, hp; int th, tw, bpp; int nb; int bx, by, delta; int reserve, rc, remain, dataoffset; if (gain != 0 || offset != 0) sanei_umax_pp_setauto (0); /* colors don't come in sync, so we must increase y */ /* to have extra lines to reorder datas */ if (sanei_umax_pp_getastra () > 610) { switch (dpi) { case 1200: delta = 8; break; case 600: delta = 4; break; case 300: delta = 2; break; case 150: delta = 1; break; default: delta = 0; break; } } else { if (color >= RGB_MODE) { switch (dpi) { case 600: delta = 16; break; case 300: delta = 8; break; case 150: delta = 4; break; default: delta = 2; break; } } else delta = 0; } /* in color mode, we need extra lines to reorder data */ if (color >= RGB_MODE) { if (sanei_umax_pp_getastra () <= 610) dataoffset = 4 * delta; else dataoffset = 2 * delta; } else dataoffset = 0; rc = sanei_umax_pp_startScan (x, y - dataoffset, width, height + dataoffset, dpi, color, gain, offset, &bpp, &tw, &th); if (rc == 1) { /* blocksize must be multiple of the number of bytes per line */ /* max is 2096100 */ /* so blocksize will hold a round number of lines, easing the */ /* write data to file operation */ bpl = bpp * tw; hp = 2096100 / bpl; blocksize = hp * bpl; nb = 0; somme = bpl * th; DBG (8, "Getting buffer %d*%d*%d=%ld=0x%lX (%s:%d) \n", bpp, tw, th, somme, somme, __FILE__, __LINE__); /* correct th to be usable scan height */ th -= dataoffset; /* we need a 2 * delta lines reserve to reorder data */ if (color >= RGB_MODE) { reserve = 2 * delta * bpl; if (sanei_umax_pp_getastra () < 1210) dataoffset = reserve; else dataoffset = 0; } else { reserve = 0; dataoffset = 0; } /* get scanned data */ /* allocate memory */ buffer = (unsigned char *) malloc (blocksize + reserve); if (buffer == NULL) { DBG (0, "Failed to allocate %ld bytes, giving up....\n", blocksize + reserve); DBG (0, "Try to scan at lower resolution, or a smaller area.\n"); gCancel = 1; } /* open output file */ fout = fopen ("out.pnm", "wb"); if (fout == NULL) { DBG (0, "Failed to open 'out.pnm', giving up....\n"); gCancel = 1; } else { /* write pnm header */ if (color >= RGB_MODE) fprintf (fout, "P6\n%d %d\n255\n", tw, th - 2 * delta); else fprintf (fout, "P5\n%d %d\n255\n", tw, th); } /* read some line first until we got clean data */ read = 0; remain = 0; while (read < dataoffset) { if (read == 0) len = dataoffset; else len = dataoffset - read; len = sanei_umax_pp_readBlock (len, tw, dpi, 0, buffer + read); if (len == 0) { DBG (0, "sanei_umax_pp_readBlock failed, cancelling scan ...\n"); gCancel = 1; } read += len; } /* in color mode we have to fill the 'reserve' area * so that we can reorder data lines */ while ((read - dataoffset < reserve) && (!gCancel)) { len = reserve - read + dataoffset; len = sanei_umax_pp_readBlock (len, tw, dpi, 0, buffer + read - dataoffset); if (len == 0) { DBG (0, "sanei_umax_pp_readBlock failed, cancelling scan ...\n"); gCancel = 1; } read += len; } /* data reading loop */ #ifdef HAVE_SYS_TIME_H gettimeofday (&td, NULL); #endif while ((read < somme) && (!gCancel)) { /* 2096100 max */ if (somme - read > blocksize - remain) len = blocksize - remain; else len = somme - read; len = sanei_umax_pp_readBlock (len, tw, dpi, (len < blocksize), buffer + reserve + remain); if (len == 0) { DBG (0, "sanei_umax_pp_readBlock failed, cancelling scan ...\n"); gCancel = 1; } read += len; nb++; DBG (8, "Read %ld bytes out of %ld ...\n", read, somme); DBG (8, "Read %d blocks ... \n", nb); /* write partial buffer to file */ if (len) { if (color >= RGB_MODE) { /* using an image format that doesn't need */ /* reordering would speed up write operation */ /* don't forget remaining bytes from previous block */ hp = (len + remain) / bpl; remain = (len + remain) - hp * bpl; switch (sanei_umax_pp_getastra ()) { case 610: /* first comes RED * then BLUE * and finally GREEN */ for (by = 0; by < hp; by++) { for (bx = 0; bx < tw; bx++) { /* scanner data: red line, blue line then green line */ /* red */ fputc (buffer [3 * (by - 2 * delta) * tw + bx + reserve], fout); /* green */ fputc (buffer [3 * by * tw + 2 * tw + bx + reserve], fout); /* blue */ fputc (buffer [3 * (by - delta) * tw + tw + bx + reserve], fout); } } /* copy tail lines for next block */ /* memcpy (buffer, * (buffer + reserve) + (hp * bpl - reserve), * reserve + remain); */ memcpy (buffer, buffer + hp * bpl, reserve + remain); break; case 1600: for (by = 0; by < hp; by++) { for (bx = 0; bx < tw; bx++) { fputc (buffer[3 * by * tw + 2 * tw + bx], fout); fputc (buffer[3 * by * tw + bx], fout); fputc (buffer[3 * by * tw + tw + bx], fout); } } break; default: for (by = 0; by < hp; by++) { for (bx = 0; bx < tw; bx++) { fputc (buffer[3 * by * tw + 2 * tw + bx], fout); fputc (buffer[3 * by * tw + tw + bx], fout); fputc (buffer[3 * by * tw + bx], fout); } } /* put remaining partial lines at start of buffer */ memcpy (buffer, buffer + hp * bpl, remain); break; } } else fwrite (buffer, len, 1, fout); } } #ifdef HAVE_SYS_TIME_H gettimeofday (&tf, NULL); /* scan time are high enough to forget about usec */ elapsed = tf.tv_sec - td.tv_sec; DBG (8, "%ld bytes transferred in %f seconds ( %.2f Kb/s)\n", somme, elapsed, (somme / elapsed) / 1024.0); #endif /* release ressources */ if (fout != NULL) fclose (fout); free (dest); free (buffer); } /* if start scan OK */ else { DBG (0, "startScan failed..... \n"); } /* terminate any pending command */ if (sanei_umax_pp_cmdSync (0x00) == 0) { DBG (0, "Warning cmdSync(0x00) failed! (%s:%d)\n", __FILE__, __LINE__); DBG (0, "Trying again ... "); if (sanei_umax_pp_cmdSync (0x00) == 0) { DBG (0, " failed again! (%s:%d)\n", __FILE__, __LINE__); DBG (0, "Blindly going on ...\n"); } else DBG (0, " success ...\n"); } /* parking */ if (sanei_umax_pp_park () == 0) DBG (0, "Park failed !!! (%s:%d)\n", __FILE__, __LINE__); /* end ... */ DBG (16, "Scan done ...\n"); return 1; } /* * returns 0 on error, 1 on success: ie head parked */ int sanei_umax_pp_parkWait (void) { int status; /* check if head is at home */ DBG (16, "entering parkWait ...\n"); do { usleep (1000); CMDSYNC (0x40); status = sanei_umax_pp_scannerStatus (); } while ((status & MOTOR_BIT) == 0x00); DBG (16, "parkWait done ...\n"); return 1; } /* starts scan: return 1 on success */ int sanei_umax_pp_startScan (int x, int y, int width, int height, int dpi, int color, int gain, int offset, int *rbpp, int *rtw, int *rth) { unsigned char *buffer; int rc = 0; int calibration[3 * 5100 + 768 + 2 + 1]; int xdpi, ydpi, h; int th, tw, bpp; int hwdpi = 600; /* CCD hardware dpi */ /* DC offsets */ int dcRed, dcGreen, dcBlue; int vgaRed, vgaGreen, vgaBlue; int len, delta; int lm9811[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 }; int motor[17] = { 0xA4, 0x80, 0x07, 0x50, 0xEC, 0x03, 0x00, 0x2F, 0x17, 0x07, 0x84, 0x08, 0x90, 0x00, 0xAC, 0x00, -1 }; int ccd[37] = { 0x00, 0x00, 0xB0, 0x4F, 0xD8, 0xE7, 0xFA, 0x10, 0xEF, 0xC4, 0x3C, 0x71, 0x0F, 0x00, 0x04, 0x00, 0x6E, 0x61, 0xA1, 0x24, 0xC4, 0x7E, 0x00, 0xAE, 0x41, 0xA0, 0x0A, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x33, 0x1A, 0x00, -1 }; #ifdef UMAX_PP_DANGEROUS_EXPERIMENT FILE *f = NULL; char line[1024], *ptr; int *base = NULL; int channel; int max = 0; #endif if (sanei_umax_pp_getastra () == 610) { hwdpi = 300; len = 0x22; lm9811[0] = 0x88; lm9811[1] = 0xE6; lm9811[2] = 0xFD; lm9811[3] = 0x8E; lm9811[4] = 0x30; lm9811[5] = 0x00; lm9811[6] = 0x8F; lm9811[7] = 0x80; motor[3] = 0x30; motor[4] = 0x0E; motor[5] = 0x02; motor[12] = 0xAA; ccd[0] = 0x00; ccd[1] = 0x00; ccd[2] = 0xD8; ccd[3] = 0x27; ccd[4] = 0xEC; ccd[5] = 0x53; ccd[6] = 0x7D; ccd[7] = 0x8A; ccd[8] = 0x77; ccd[9] = 0xE2; ccd[10] = 0x9E; ccd[11] = 0xF8; ccd[12] = 0x07; ccd[13] = 0x20; ccd[14] = 0x02; ccd[15] = 0x00; ccd[16] = 0x76; ccd[17] = 0x5D; ccd[18] = 0xE0; ccd[19] = 0x13; ccd[20] = 0xE2; ccd[21] = 0x20; ccd[22] = 0x00; ccd[23] = 0xA8; ccd[24] = 0x41; ccd[25] = 0xA0; ccd[26] = 0x0A; ccd[27] = 0x8B; ccd[28] = 0x4D; ccd[29] = 0x4B; ccd[30] = 0xD0; ccd[31] = 0x68; ccd[32] = 0xDF; ccd[33] = 0x13; } else { len = 0x24; hwdpi = 600; } DBG (8, "startScan(%d,%d,%d,%d,%d,%d,%X);\n", x, y, width, height, dpi, color, gain); buffer = (unsigned char *) malloc (2096100); if (buffer == NULL) { DBG (0, "Failed to allocate 2096100 bytes... (%s:%d)\n", __FILE__, __LINE__); return 0; } /* 1600P have a different CCD command block */ if (sanei_umax_pp_getastra () == 1600) { lm9811[0] = 0x19; lm9811[1] = 0xD5; lm9811[4] = 0x1B; lm9811[7] = 0x70; ccd[29] = 0x1A; ccd[30] = 0xEE; motor[13] = 0x03; /* may be blur filter */ } /* matches intTransport610P */ /* get scanner status */ rc = inquire (); if (rc == 0) { DBG (0, "inquire() failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (16, "inquire() passed ... (%s:%d)\n", __FILE__, __LINE__); rc = loadDefaultTables (); if (rc == 0) { DBG (0, "loadDefaultTables() failed ! (%s:%d) \n", __FILE__, __LINE__); return 0; } DBG (16, "loadDefaultTables() passed ... (%s:%d)\n", __FILE__, __LINE__); /* find and move to zero */ if (moveToOrigin () == 0) { DBG (0, "moveToOrigin() failed ... (%s:%d)\n", __FILE__, __LINE__); } else { DBG (16, "moveToOrigin() passed ... (%s:%d)\n", __FILE__, __LINE__); } /* 1600P have a different CCD command block */ if (sanei_umax_pp_getastra () == 1600) { lm9811[0] = 0x19; lm9811[1] = 0xD5; lm9811[4] = 0x1B; lm9811[7] = 0x70; ccd[29] = 0x1A; ccd[30] = 0xEE; motor[13] = 0x03; /* may be blur filter */ } /* XXX STEF XXX : done even is manual settings, some day skip it * and move head the right amount */ if (offsetCalibration (color, &dcRed, &dcGreen, &dcBlue) == 0) { DBG (0, "offsetCalibration failed !!! (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "offsetCalibration(%d=>%d,%d,%d) passed ... (%s:%d)\n", color, dcRed, dcGreen, dcBlue, __FILE__, __LINE__); if (coarseGainCalibration (color, dcRed, dcGreen, dcBlue, &vgaRed, &vgaGreen, &vgaBlue) == 0) { DBG (0, "coarseGainCalibration failed !!! (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "coarseGainCalibration(%d,%d,%d,%d=>%d,%d,%d) passed ... (%s:%d)\n", color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, __FILE__, __LINE__); /* manual setting overrides evaluated values */ if (!sanei_umax_pp_getauto ()) { dcRed = (offset & 0xF00) >> 8; dcGreen = (offset & 0x0F0) >> 4; dcBlue = offset & 0x00F; vgaRed = (gain & 0xF00) >> 8; vgaGreen = (gain & 0x0F0) >> 4; vgaBlue = gain & 0x00F; } /* ccd calibration is allways done */ /* with final dc and vga */ if (shadingCalibration (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, calibration) == 0) { DBG (0, "shadingCalibration failed !!! (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "shadingCalibration(%d,%d,%d,%d,%d,%d,%d) passed ... (%s:%d)\n", color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, __FILE__, __LINE__); /* gamma or left shading calibration ? */ if (sanei_umax_pp_getastra () <= 610) { if (leftShadingCalibration610p (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, calibration) == 0) { DBG (0, "leftShadingCalibration610p failed !!! (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "leftShadingCalibration610p(%d,%d,%d,%d,%d,%d,%d) passed ... (%s:%d)\n", color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, __FILE__, __LINE__); } /* 1220P: x dpi is from 75 to 600 max, any modes */ /* 610P: x dpi is from 75 to 300 max, any modes */ if (dpi > hwdpi) xdpi = hwdpi; else xdpi = dpi; /* EPPRead32Buffer does not work */ /* with length not multiple of four bytes, so we enlarge */ /* width to meet this criteria ... */ if ((getEPPMode () == 32) && (xdpi >= 600) && (width & 0x03) && (sanei_umax_pp_getastra () > 610)) { width += (4 - (width & 0x03)); /* in case we go too far on the right */ if (x + width > 5100) { x = 5100 - width; } } /* compute target size */ th = (height * dpi) / hwdpi; tw = (width * xdpi) / hwdpi; /* corrects y to match exact scan area start * and lets room for a leading zone so that * we can reorder data */ switch (sanei_umax_pp_getastra ()) { case 610: if (color >= RGB_MODE) switch (dpi) { case 600: y += 64; break; case 300: y += 32; break; case 150: y += 16; break; case 75: y += 8; break; } else y += 80; default: y += 8; break; } /* for 1220P/2000P move fast to scan target if possible */ /* it is faster to move at low resolution, then scan */ /* than scan & move at high resolution */ if ((sanei_umax_pp_getastra () > 610 && (dpi > 300)) && (y > 100)) { /* move at 150 dpi resolution */ move (y / 2, PRECISION_OFF, NULL); /* keep the remainder for scan */ y = y % 4; } /* build final scan command */ /* round width and height */ width = (tw * hwdpi) / xdpi; height = (th * hwdpi) / dpi; ydpi = dpi; if (ydpi < 300) { if ((color >= RGB_MODE) && (sanei_umax_pp_getastra () > 610)) { if (dpi < 150) ydpi = 150; } else ydpi = 300; } if ((color < RGB_MODE) && (sanei_umax_pp_getastra () <= 610)) ydpi = 600; /* at maximum resolution */ if (color >= RGB_MODE) { h = ((height * ydpi) / hwdpi) + 8; bpp = 3; } else { h = ((height * ydpi) / hwdpi) + 4; if (sanei_umax_pp_getastra () <= 610) h += 16; bpp = 1; } /* sets y resolution */ switch (ydpi) { case 1200: motor[6] = 0x60; motor[8] = 0x5E; /* *WORKING* value */ motor[8] = 0x5F; /* 5F gives wrong colors ? */ motor[8] = 0x58; motor[9] = 0x05; /* XXX test value XXX motor[14] = motor[14] & 0xF0; ~ 0x08 -> scan AND move */ /* XXX test value XXX motor[14] = (motor[14] & 0xF0) | 0x04; -> 600 dpi ? */ /* XXX test value XXX motor[14] = (motor[14] & 0xF0) | 0x0C; */ motor[14] = motor[14] & 0xF0; /* *WORKING* 1200 dpi */ break; case 600: if (sanei_umax_pp_getastra () <= 610) { motor[6] = 0xC0; motor[7] = 0x2F; motor[14] = motor[14] & 0xF0; /* if (color >= RGB_MODE) motor[14] |= 0x04; XXX STEF XXX */ } else { motor[6] = 0x60; motor[14] = (motor[14] & 0xF0) | 0x04; } motor[8] = 0x2F; motor[9] = 0x05; break; case 300: if (sanei_umax_pp_getastra () <= 610) { motor[6] = 0xC0; motor[14] = motor[14] & 0xF0; if (color >= RGB_MODE) motor[14] |= 0x04; } else { motor[6] = 0x00; motor[14] = (motor[14] & 0xF0) | 0x0C; } motor[8] = 0x17; motor[9] = 0x05; /* si | 0C h=2*w, si | 04 h=w ? */ break; case 150: if (sanei_umax_pp_getastra () <= 610) { motor[6] = 0xC0; motor[9] = 0x05; motor[14] = motor[14] & 0xF0; if (color >= RGB_MODE) motor[14] |= 0x04; } else { motor[6] = 0x00; motor[9] = 0x07; motor[14] = (motor[14] & 0xF0) | 0x0C; } motor[8] = 0x17; break; } /* different values for 610P in B&W */ if ((sanei_umax_pp_getastra () <= 610) && (color < RGB_MODE)) { motor[7] = 0xC8; motor[8] = 0x2F; motor[9] = 0x05; } /* y start -1 */ y = (y * ydpi) / hwdpi; if (color >= RGB_MODE) { /* 00 seems to give better results ? */ /* 80 some more gain, lamp power level ? */ /* 8x does not make much difference */ lm9811[6] = 0x8F; switch (sanei_umax_pp_getastra ()) { case 610: lm9811[7] = 0x80; motor[13] = 0x20; break; case 1600: lm9811[7] = 0x70; motor[13] = 0x03; break; default: lm9811[7] = 0xF0; motor[13] = 0x09; } } else { motor[13] = 0xC0; lm9811[6] = 0x80 | vgaGreen; switch (sanei_umax_pp_getastra ()) { case 610: lm9811[7] = 0xA0; lm9811[6] = lm9811[6] | 0x40; motor[13] = 0x6F; break; case 1600: lm9811[7] = 0x20; motor[13] = 0xC3; break; default: lm9811[7] = 0xA0; motor[13] = 0xC9; } } encodeCoefficient (color, dpi, calibration); encodeWX (width, x, dpi, color, ccd, 0); encodeHY (h, y, motor); encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (vgaRed, vgaGreen, vgaBlue, motor); #ifdef UMAX_PP_DANGEROUS_EXPERIMENT /*motor[13] = 0x80; B&W bit */ /*motor[13] = 0x40; green bit */ /*motor[13] = 0x20; red bit */ /*motor[13] = 0x10; blue bit */ /* with cmd 01, may be use to do 3 pass scanning ? */ /* bits 0 to 3 seem related to sharpness */ f = fopen ("/tmp/dangerous.params", "rb"); if (f != NULL) { fgets (line, 1024, f); while (!feof (f)) { channel = 0; if (sscanf (line, "CMD%1d", &channel) != 1) channel = 0; switch (channel) { case 0: break; case 1: base = lm9811; max = 8; break; case 2: base = motor; max = 16; break; case 8: base = ccd; max = 36; break; default: channel = 0; } printf ("CMD%d BEFORE: ", channel); for (i = 0; i < max; i++) printf ("%02X ", base[i]); printf ("\n"); if (channel > 0) { ptr = line + 6; for (i = 0; (i < max) && ((ptr - line) < strlen (line)); i++) { if (ptr[0] != '-') { sscanf (ptr, "%X", base + i); } ptr += 3; } } printf ("CMD%d AFTER : ", channel); for (i = 0; i < max; i++) printf ("%02X ", base[i]); printf ("\n"); fgets (line, 1024, f); } fclose (f); } #endif if (DBG_LEVEL >= 64) { bloc2Decode (motor); bloc8Decode (ccd); } CMDSYNC (0x00); CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); /* 3 ccd lines + 3 gamma tables + end tag */ if (sanei_umax_pp_getastra () <= 610) { /* XXX STEF XXX : there is a 4 pixels shift to the right * the first shading correction value applies to the forth * pixel of scan (at 300 dpi), we allready shift to the left * when doing shadingCalibration, but now we have to move coeffs * to match x coordinate */ delta = x - sanei_umax_pp_getLeft (); if (delta) { memcpy (calibration, calibration + delta, (7650 - delta) * sizeof (int)); } CMDSET (4, 0x20E4, calibration); } else { CMDSET (4, 0x3EC6, calibration); } COMPLETIONWAIT; *rbpp = bpp; *rtw = tw; *rth = th; free (buffer); return 1; } /* * check the scanner model. Return 1220 for * a 1220P, or 2000 for a 2000P. * and 610 for a 610p * values less than 610 are errors */ int sanei_umax_pp_checkModel (void) { int *dest = NULL; int state[16]; int err = 0; int i; int opsc35[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; /* if we have already detected a scanner different from */ /* default type, no need to check again */ if (sanei_umax_pp_getastra ()) return sanei_umax_pp_getastra (); /* get scanner status */ CMDGET (0x02, 16, state); CMDSETGET (0x08, 36, opsc35); CMDSYNC (0xC2); dest = (int *) malloc (65536 * sizeof (int)); if (dest == NULL) { DBG (0, "%s:%d failed to allocate 256 Ko !\n", __FILE__, __LINE__); return 0; } /* init some buffer : default calibration data ? */ dest[0] = 0x00; dest[1] = 0x00; dest[2] = 0x00; for (i = 0; i < 768; i++) dest[i + 3] = i % 256; dest[768 + 3] = 0xAA; dest[768 + 4] = 0xAA; dest[768 + 5] = -1; CMDSETGET (0x04, 768 + 5, dest); /* check buffer returned */ for (i = 0; i < 768; i++) { if (dest[i + 3] != (i % 256)) { DBG (0, "Error data altered: byte %d=0x%02X, should be 0x%02X ! (%s:%d)\n", i, dest[i + 3], i % 256, __FILE__, __LINE__); err = 1; } } if (err) return 0; /* new part of buffer ... */ for (i = 0; i < 256; i++) { dest[i * 2] = i; dest[i * 2 + 1] = 0x00; } CMDSETGET (0x08, 36, opsc35); CMDSYNC (0xC2); CMDSET (0x04, 512, dest); /* another new part ... */ for (i = 0; i < 256; i++) { dest[i * 2] = i; dest[i * 2 + 1] = 0x04; /* instead of 0x00 */ } opsc35[2] = 0x06; /* instead of 0x04, write flag ? */ CMDSETGET (0x08, 36, opsc35); CMDSYNC (0xC2); CMDSET (0x04, 512, dest); opsc35[2] = 0x04; /* return to initial value, read flag? */ CMDSETGET (0x08, 36, opsc35); CMDGET (0x04, 512, dest); /* check buffer returned */ /* if 0x4 are still 0x04, we got a 1220P, else it is a 2000P */ for (i = 0; i < 256; i++) { if ((dest[2 * i] != i) || ((dest[2 * i + 1] != 0x04) && (dest[2 * i + 1] != 0x00))) { DBG (0, "Error data altered: expected %d=(0x%02X,0x04), found (0x%02X,0x%02X) ! (%s:%d)\n", i, i, dest[i * 2], dest[i * 2 + 1], __FILE__, __LINE__); err = 0; } } /* if buffer unchanged, we have a 1600P, or a 1220P */ /* if data has turned into 0, we have a 2000P */ if (dest[1] == 0x00) { sanei_umax_pp_setastra (2000); err = 2000; } else { /* detects 1600 by finding black scans */ /* we defaults to 1220 */ sanei_umax_pp_setastra (1220); moveToOrigin (); err = sanei_umax_pp_getastra (); /* parking */ CMDSYNC (0xC2); CMDSYNC (0x00); if (sanei_umax_pp_park () == 0) DBG (0, "Park failed !!! (%s:%d)\n", __FILE__, __LINE__); /* poll parking */ do { sleep (1); CMDSYNC (0x40); } while ((sanei_umax_pp_scannerStatus () & MOTOR_BIT) == 0x00); } /* return guessed model number */ CMDSYNC (0x00); return err; } /* sets, resets gamma tables */ void sanei_umax_pp_gamma (int *red, int *green, int *blue) { if (red != NULL) { ggRed = red; } else { ggRed = ggamma; } if (green != NULL) { ggGreen = green; } else { ggGreen = ggamma; } if (blue != NULL) { ggBlue = blue; } else { ggBlue = ggamma; } } /* initialize scanner by loading default transformation table */ /* O: failure * 1: OK */ int loadDefaultTables (void) { int cmd01[36] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x60, 0x20, 0x00, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x13, -1 }; int opsc35[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x00, 0x00, 0x04, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; int i, len, *cmd, err; int buffer[774]; int rc = 1; /* 1600P have a different CCD command block */ if (sanei_umax_pp_getastra () == 1600) { opsc35[29] = 0x1A; opsc35[30] = 0xEE; } if (sanei_umax_pp_getastra () <= 610) { len = 0x22; cmd = cmd01; /* XXX STEF XXX if we send F0, we get 0x10 back */ cmd[0x21] = 0x10; } else { len = 0x24; cmd = opsc35; } /* set and reread first table */ /* since 1660P seems to have another type of CCD * this table is not sent/needed */ err = 0; if (sanei_umax_pp_getastra () != 1600) { CMDSETGET (8, len, cmd); CMDSYNC (0xC2); buffer[0] = 0x00; buffer[1] = 0x00; buffer[2] = 0x00; for (i = 0; i < 768; i++) buffer[i + 3] = i % 256; if (sanei_umax_pp_getastra () <= 610) { buffer[768 + 3] = 0xFF; buffer[768 + 4] = 0xFF; } else { buffer[768 + 3] = 0xAA; buffer[768 + 4] = 0xAA; } buffer[768 + 5] = -1; CMDSETGET (4, 0x305, buffer); /* check buffer returned */ for (i = 0; i < 768; i++) { if (buffer[i + 3] != (i % 256)) { DBG (0, "Error data altered: byte %d=0x%02X, should be 0x%02X ! (%s:%d)\n", i, buffer[i + 3], i % 256, __FILE__, __LINE__); err = 1; } } if (err) return 0; } /* second table ... */ for (i = 0; i < 256; i++) { buffer[i * 2] = i; buffer[i * 2 + 1] = 0; } CMDSETGET (8, len, cmd); CMDSYNC (0xC2); CMDSET (4, 0x200, buffer); /* third table ... */ if (sanei_umax_pp_getastra () <= 610) { for (i = 0; i < 256; i++) { buffer[i * 2] = i; buffer[i * 2 + 1] = 0x01; /* instead of 0x00 */ } } else { for (i = 0; i < 256; i++) { buffer[i * 2] = i; buffer[i * 2 + 1] = 0x04; /* instead of 0x00 */ } } opsc35[2] = 0x06; cmd01[1] = 0x80; CMDSETGET (8, len, cmd); CMDSYNC (0xC2); CMDSET (4, 0x200, buffer); opsc35[2] = 0x04; cmd01[1] = 0x00; CMDSETGET (8, len, cmd); CMDGET (4, 0x200, buffer); /* check buffer returned */ /* if 0x4 are still 0x0 (hum..), we got a 1220P, else it is a 2000P */ for (i = 0; i < 256; i++) { if ((buffer[2 * i] != i) || ((buffer[2 * i + 1] != 0x04) && (buffer[2 * i + 1] != 0x01) && (buffer[2 * i + 1] != 0x00))) { DBG (0, "Error data altered: expected %d=(0x%02X,0x04), found (0x%02X,0x%02X) ! (%s:%d)\n", i, i, buffer[i * 2], buffer[i * 2 + 1], __FILE__, __LINE__); err = 1; } } if (err) return 0; return rc; } /* inquire scanner status * O: failure * 1: OK * 2: first scanner init, needs re-homing */ int inquire (void) { int cmd01[36] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x03, 0xC1, 0x80, 0x60, 0x20, 0x00, 0x00, 0x16, 0x41, 0xE0, 0xAC, 0x03, 0x03, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1B, -1 }; int buffer[37]; int rc = 1, first, i; char str[106]; /* inquiry: ask for RAM, CCD, ... */ CMDSET (8, 0x23, cmd01); CMDGET (8, 0x23, buffer); if (DBG_LEVEL > 8) { for (i = 0; i < 35; i++) sprintf (str + 3 * i, "%02X ", buffer[i]); str[105] = 0x00; DBG (8, "SCANNER INFORMATION=%s\n", str); } /* get state */ CMDGET (2, 0x10, buffer); first = 1; for (i = 0; i < 14; i++) { if (buffer[i] != 0) first = 0; } if (buffer[15] != 0) first = 0; if (first) rc = 2; if (DBG_LEVEL > 8) { for (i = 0; i < 16; i++) sprintf (str + 3 * i, "%02X ", buffer[i]); str[48] = 0x00; DBG (8, "SCANNER STATE=%s\n", str); } return rc; } /* * computes DC offset to have black pixel really black out of * CCD ie black gives 0 * 1220P implements the method described in LM9811 datasheet * returns 1 and DC offsets in the corresponding vars on success . * On failure, returns 0. */ static int offsetCalibration1220p (int color, int *offRed, int *offGreen, int *offBlue) { unsigned char buffer[5300]; int i, val; int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 }; int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 }; int opsc38[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6E, 0x18, 0x10, 0x03, 0x06, 0x00, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; int opsc48[17] = { 0x09, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x40, 0xA4, 0x00, -1 }; float low, high; DBG (16, "entering offsetCalibration1220p() ... (%s:%d)\n", __FILE__, __LINE__); /* really dirty hack: somethig is buggy in BW mode */ /* we override mode with color until the bug is found */ /* color = RGB_MODE; */ /* 1600P have a different CCD command block */ if (sanei_umax_pp_getastra () == 1600) { opsc04[0] = 0x19; opsc04[1] = 0xD5; opsc04[4] = 0x1B; opsc04[7] = 0x20; opsc48[8] = 0x2B; opsc48[11] = 0x20; opsc48[12] = 0x08; opsc48[13] = 0x42; } /* offset calibration, scan 24 bytes of black in each color */ /* component see section 5.1 of LM9811 datasheet */ if (color >= RGB_MODE) { CMDSETGET (2, 0x10, opsc48); CMDSETGET (8, 0x24, opsc38); CMDSETGET (1, 0x08, opsc04); /* scan std, no 'enhancing' */ CMDSYNC (0xC2); if (sanei_umax_pp_scannerStatus () & 0x80) { CMDSYNC (0x00); } CMDSETGET (4, 0x08, commit); /* commit ? */ COMPLETIONWAIT; CMDGETBUF (4, 0x18, buffer); if (DBG_LEVEL >= 128) Dump (0x18, buffer, NULL); val = 0; for (i = 0; i < 24; i++) val += buffer[i]; low = (float) val / i; /* Vadc1 */ CMDSYNC (0x00); opsc04[7] = opsc04[7] | 0x10; /* enhanced ? */ CMDSETGET (1, 0x08, opsc04); COMPLETIONWAIT; CMDGETBUF (4, 0x18, buffer); val = 0; for (i = 0; i < 24; i++) val += buffer[i]; high = (float) val / i; /* Vadc2 */ if (DBG_LEVEL >= 128) Dump (0x18, buffer, NULL); *offRed = 15.0 - ((high - low) * 2); /* block that repeats */ /* must be monochrome since hscan=1 */ opsc48[0] = 0x01; if (sanei_umax_pp_getastra () == 1600) { opsc48[12] = 0x0C; opsc48[13] = 0x82; } else { opsc48[12] = 0x04; opsc48[13] = 0x80; } CMDSETGET (2, 0x10, opsc48); CMDSETGET (8, 0x24, opsc38); opsc04[7] = opsc04[7] & 0x20; CMDSETGET (1, 0x08, opsc04); CMDSYNC (0xC2); if (sanei_umax_pp_scannerStatus () & 0x80) { CMDSYNC (0x00); } CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, 0x18, buffer); if (DBG_LEVEL >= 128) Dump (0x18, buffer, NULL); val = 0; for (i = 0; i < 24; i++) val += buffer[i]; low = (float) val / i; CMDSYNC (0x00); opsc04[7] = opsc04[7] | 0x10; /* gain ? */ CMDSETGET (1, 0x08, opsc04); COMPLETIONWAIT; CMDGETBUF (4, 0x18, buffer); if (DBG_LEVEL >= 128) Dump (0x18, buffer, NULL); val = 0; for (i = 0; i < 24; i++) val += buffer[i]; high = (float) val / i; *offBlue = 15.0 - ((high - low) * 2); } /* block that repeats */ if (color < RGB_MODE) { opsc48[0] = 0x05; /* B&H height is 5 */ opsc48[13] = 0xC0; /* B&W mode */ } else { opsc48[0] = 0x05; /* color height is 5 (+4 ?) */ opsc48[13] = 0xC1; /* some strange mode ? */ } if (sanei_umax_pp_getastra () == 1600) opsc48[13] = opsc48[13] | 0x02; CMDSETGET (2, 0x10, opsc48); CMDSETGET (8, 0x24, opsc38); opsc04[7] = opsc04[7] & 0x20; CMDSETGET (1, 0x08, opsc04); CMDSYNC (0xC2); if (sanei_umax_pp_scannerStatus () & 0x80) { CMDSYNC (0x00); } CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, 0x18, buffer); if (DBG_LEVEL >= 128) Dump (0x18, buffer, NULL); val = 0; for (i = 0; i < 24; i++) val += buffer[i]; low = (float) val / i; CMDSYNC (0x00); opsc04[7] = opsc04[7] | 0x10; CMDSETGET (1, 0x08, opsc04); COMPLETIONWAIT; CMDGETBUF (4, 0x18, buffer); if (DBG_LEVEL >= 128) Dump (0x18, buffer, NULL); val = 0; for (i = 0; i < 24; i++) val += buffer[i]; high = (float) val / i; *offGreen = 15.0 - ((high - low) * 2); /*DBG (1, "STEF: offsets(RED,GREEN,BLUE=(%d,%d,%d)\n", *offRed, *offGreen, *offBlue);*/ DBG (16, "offsetCalibration1220p() done ...\n"); return 1; } /* * computes DC offset to have black pixel really black out of * CCD ie black gives 0 * 610P doesn't implement method described in LM9811 datasheet * but scan a black line with decreasing offsets until the * scanned data reach a 'good black level'. * returns 1 and DC offsets in the corresponding vars on success . * On failure, returns 0. */ static int offsetCalibration610p (int color, int *offRed, int *offGreen, int *offBlue) { int motor[17] = { 0x11, 0x00, 0x00, 0x70, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x00, 0x00, 0xF0, 0x7D, 0x5F, 0xA4, 0x00, -1 }; int ccd[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00, 0x76, 0x12, 0xB0, 0x03, 0x06, 0x00, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; int lm9811[9] = { 0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x40, 0xF0, -1 }; int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 }; int offset; int level; unsigned char data[40]; int i; int len; int w; DBG (16, "entering offsetCalibration610P() ... (%s:%d)\n", __FILE__, __LINE__); if (sanei_umax_pp_getastra () < 1220) { len = 0x22; w = 40; } else { len = 0x24; w = 40; } *offRed = 0; *offGreen = 0; *offBlue = 0; /* first color channel: used both in color and b&w modes */ /* offset to the max */ /* supposed to be green componant */ offset = 0x10; do { offset--; /* 7D: 0111 1101 */ /* sets for the current offset */ motor[12] = (offset << 2) | 0x40 | 0x01; lm9811[7] = offset << 4; /* sends commands */ CMDSYNC (0x00); CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, w, data); if (DBG_LEVEL > 128) { DumpNB (w, 1, data, NULL); } level = 0; for (i = 0; i < w; i++) level += data[i]; } /* loop while average >0.5 */ while ((offset > 0) && ((level * 2) / w > 1)); *offGreen = offset; /* offset calibration for the two other channels when in color */ if (color >= RGB_MODE) { motor[0] = 0x01; offset = 0x10; do { offset--; /* sets for the current offset */ motor[13] = 0x90 | offset; lm9811[7] = offset << 4; /* sends commands */ CMDSYNC (0x00); CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, w, data); if (DBG_LEVEL > 128) { DumpNB (w, 1, data, NULL); } level = 0; for (i = 0; i < w; i++) level += data[i]; } /* loop while average >0.5 */ while ((offset > 0) && ((level * 2) / w > 1)); *offBlue = offset; /* last color component */ motor[0] = 0x09; ccd[13] = 0xD0 | (ccd[13] & 0x0F); offset = 0x10; do { offset--; /* sets for the current offset */ motor[11] = offset << 4; lm9811[7] = offset << 4; /* sends commands */ CMDSYNC (0x00); CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, w, data); if (gMode == UMAX_PP_PARPORT_EPP) { CMDSYNC (0x00); } if (DBG_LEVEL > 128) { DumpNB (w, 1, data, NULL); } level = 0; for (i = 0; i < w; i++) level += data[i]; } /* loop while average >0.5 */ while ((offset > 0) && ((level * 2) / w > 1)); *offRed = offset; } else { *offRed = 0x0F; *offBlue = 0x0F; } return 1; } /* * generic offset calibration function */ static int offsetCalibration (int color, int *dcRed, int *dcGreen, int *dcBlue) { if (sanei_umax_pp_getastra () <= 610) { if (offsetCalibration610p (color, dcRed, dcGreen, dcBlue) == 0) { DBG (0, "offsetCalibration610p failed !!! (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "offsetCalibration610p(%d=>%d,%d,%d) passed ... (%s:%d)\n", color, *dcRed, *dcGreen, *dcBlue, __FILE__, __LINE__); } else { if (offsetCalibration1220p (color, dcRed, dcGreen, dcBlue) == 0) { DBG (0, "offsetCalibration1220p failed !!! (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "offsetCalibration1220p(%d=>%d,%d,%d) passed ... (%s:%d)\n", color, *dcRed, *dcGreen, *dcBlue, __FILE__, __LINE__); } return 1; } /* * computes Video Gain Amplifier : LM9811 can corrects up to 3dB of * light variation. So we must adjust VGA so that dynamic range is * within 3db. It is achieved when min white pixel >= max white pixel / 2.8 * So we scan a white area and decrease gain until this condition is met. * returns 1 and VGA values in the corresponding vars on success . * On failure, returns 0. */ static int coarseGainCalibration610p (int color, int dcRed, int dcGreen, int dcBlue, int *vgaRed, int *vgaGreen, int *vgaBlue) { int motor[17] = { 0x11, 0x00, 0x00, 0x70, 0x00, 0x00, 0xC0, 0x2F, 0x17, 0x00, 0xFF, 0xAF, 0xAA, 0x6A, 0xA4, 0x00, -1 }; int ccd[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00, 0x76, 0x41, 0xE0, 0xAC, 0x06, 0x00, 0x00, 0x9C, 0x4A, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; /* * lm9811[7]= VGA << 4 * lm9811[6]= 0x40 | DC offset */ int lm9811[9] = { 0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x40, 0xF0, -1 }; int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 }; unsigned char data[5400]; int i, len; int w, xstart, xend; int min, max; TRACE (16, "entering coarseGainCalibration610p ...\n"); if (sanei_umax_pp_getastra () < 1220) { w = 2700; len = 0x22; } else { w = 5400; len = 0x24; } /* move back to desired area */ MOVE (-69, PRECISION_OFF, NULL); /* first scan : taking a reference full width scan to * find usable full width of the CCD */ *vgaRed = 0x08; *vgaGreen = 0x00; *vgaBlue = 0x00; /* scanning red component -> h=1 */ motor[0] = 0x01; motor[13] = 0xAA; /* will be 6A below */ encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor); lm9811[7] = dcRed << 4; lm9811[6] = 0x40 | *vgaRed; CMDSYNC (0x00); CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, w, data); if (gMode == UMAX_PP_PARPORT_EPP) { CMDSYNC (0x00); } if (DBG_LEVEL > 128) { DumpNB (w, 1, data, NULL); } /* find usable CCD area */ i = 0; while ((i < w) && (data[i] <= (targetCode * 2) / 5)) i++; xstart = i; i = w - 1; while ((i > 0) && (data[i] <= (targetCode * 2) / 5)) i--; xend = i; DBG (32, "coarseGainCalibration610p: xstart=%d, xend=%d ->left=%d\n", xstart, xend, ((xend + xstart - w) / 2)); /* choose best 'left' position */ sanei_umax_pp_setLeft ((xend + xstart - w) / 2); /* now do VGA calibration for green (=B&W channel) */ motor[0] = 0x11; motor[13] = 0x60 | (motor[13] & 0x0F); *vgaRed = 0x0F; *vgaGreen = 0x0F; *vgaBlue = 0x0F; for (*vgaGreen = 0x0F; *vgaGreen > 0; (*vgaGreen)--) { encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor); lm9811[7] = dcGreen << 4; lm9811[6] = 0x40 | *vgaGreen; CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, w, data); if (gMode == UMAX_PP_PARPORT_EPP) { CMDSYNC (0x00); } if (DBG_LEVEL > 128) { DumpNB (w, 1, data, NULL); } min = 0xFF; max = 0x00; for (i = xstart; i <= xend; i++) { if (data[i] < min) min = data[i]; if (data[i] > max) max = data[i]; } if ((max <= targetCode) && (min > (((float) targetCode) / 2.8))) break; DBG (32, "coarseGainCalibration610p, target/2.8=%f\n", (((float) targetCode) / 2.8)); DBG (32, "coarseGainCalibration610p, green: min=%d, max=%d\n", min, max); } if (color >= RGB_MODE) { motor[0] = 0x01; motor[13] = 0xA0 | (motor[13] & 0x0F); for (*vgaBlue = 0x0F; *vgaBlue > 0; (*vgaBlue)--) { encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor); lm9811[7] = dcBlue << 4; lm9811[6] = 0x40 | *vgaBlue; CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, w, data); if (gMode == UMAX_PP_PARPORT_EPP) { CMDSYNC (0x00); } if (DBG_LEVEL > 128) { DumpNB (w, 1, data, NULL); } min = 0xFF; max = 0x00; for (i = xstart; i <= xend; i++) { if (data[i] < min) min = data[i]; if (data[i] > max) max = data[i]; } if ((max <= targetCode) && (min > (((float) targetCode) / 2.8))) break; DBG (32, "coarseGainCalibration610p, blue: min=%d, max=%d\n", min, max); } motor[0] = 0x09; motor[13] = 0xE0 | (motor[13] & 0x0F); for (*vgaRed = 0x0F; *vgaRed > 0; (*vgaRed)--) { encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (*vgaRed, *vgaGreen, *vgaBlue, motor); lm9811[7] = dcRed << 4; lm9811[6] = 0x40 | *vgaRed; CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, w, data); if (gMode == UMAX_PP_PARPORT_EPP) { CMDSYNC (0x00); } if (DBG_LEVEL > 128) { DumpNB (w, 1, data, NULL); } min = 0xFF; max = 0x00; for (i = xstart; i <= xend; i++) { if (data[i] < min) min = data[i]; if (data[i] > max) max = data[i]; } if ((max <= targetCode) && (min > (((float) targetCode) / 2.8))) break; DBG (32, "coarseGainCalibration610p, red: min=%d, max=%d\n", min, max); } } else { *vgaRed = 0x0F; *vgaBlue = 0x0F; } TRACE (16, "coarseGainCalibration610p end ...\n"); return 1; } /* same as above, but for 1220P/1600P/200P */ static int coarseGainCalibration1220p (int color, int dcRed, int dcGreen, int dcBlue, int *vgaRed, int *vgaGreen, int *vgaBlue) { unsigned char buffer[5300]; int i; double sum; int xstart = 540; int xend = 5100; int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 }; int opsc04[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x00, 0x00, -1 }; int opsc10[9] = { 0x06, 0xF4, 0xFF, 0x81, 0x1B, 0x00, 0x08, 0x00, -1 }; int opsc18[17] = { 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0x88, 0x08, 0x00, 0x80, 0xA4, 0x00, -1 }; int opsc39[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6E, 0x41, 0x20, 0x24, 0x06, 0x00, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; int opsc40[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x6E, 0x41, 0x60, 0x4F, 0x06, 0x00, 0x00, 0x00, 0x46, 0xA0, 0x00, 0x8B, 0x49, 0x2A, 0xE9, 0x68, 0xDF, 0x93, 0x1A, 0x00, -1 }; int motor[17] = { 0x09, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x2F, 0x2F, 0x00, 0xA5, 0x09, 0x00, 0x40, 0xA4, 0x00, -1 }; DBG (16, "entering coarseGainCalibration1220p() ... (%s:%d) \n", __FILE__, __LINE__); /* temporay workaround */ color = RGB_MODE; /* initialize VGA components */ *vgaGreen = 0; *vgaRed = 2; *vgaBlue = 2; CMDSETGET (2, 0x10, opsc18); CMDSETGET (8, 0x24, opsc39); opsc04[7] = opsc04[7] & 0x20; opsc04[6] = 0x06; /* one channel gain value */ CMDSETGET (1, 0x08, opsc10); /* was opsc04, extraneaous string */ /* that prevents using move .... */ CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, 0x200, buffer); if (DBG_LEVEL >= 128) Dump (0x200, buffer, NULL); /* auto correction of gain levels */ /* first color component X */ if (color >= RGB_MODE) { if (sanei_umax_pp_getastra () == 1600) { motor[11] |= 0x20; motor[12] = 0x08; motor[13] |= 0x02; opsc04[7] |= 0x20; } encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (*vgaRed, 0, 0, motor); CMDSETGET (2, 0x10, motor); CMDSETGET (8, 0x24, opsc40); if (DBG_LEVEL >= 128) { bloc2Decode (motor); bloc8Decode (opsc40); } opsc04[6] = *vgaRed; CMDSETGET (1, 0x08, opsc04); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, 0x14B4, buffer); if (DBG_LEVEL >= 128) Dump (0x14B4, buffer, NULL); sum = 0; for (i = xstart; i < xend; i++) sum += buffer[i]; sum = sum / (xend - xstart); while ((opsc04[6] < 0x0F) && (sum < 140)) { CMDSYNC (0x00); opsc04[6]++; CMDSETGET (1, 0x000008, opsc04); COMPLETIONWAIT; CMDGETBUF (4, 0x0014B4, buffer); if (DBG_LEVEL >= 128) Dump (0x14B4, buffer, NULL); sum = 0; for (i = xstart; i < xend; i++) sum += buffer[i]; sum = sum / (xend - xstart); } *vgaRed = opsc04[6]; /* blue */ encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (0, 0, *vgaBlue, motor); if (sanei_umax_pp_getastra () == 1600) { motor[11] |= 0x20; motor[12] = 0x08; motor[13] |= 0x02; opsc04[7] |= 0x20; } CMDSETGET (2, 0x10, motor); CMDSETGET (8, 0x24, opsc40); opsc04[6] = *vgaBlue; CMDSETGET (1, 0x08, opsc04); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; CMDGETBUF (4, 0x14B4, buffer); if (DBG_LEVEL >= 128) Dump (0x14B4, buffer, NULL); sum = 0; for (i = xstart; i < xend; i++) sum += buffer[i]; sum = sum / (xend - xstart); while ((opsc04[6] < 0x0F) && (sum < 140)) { CMDSYNC (0x00); opsc04[6]++; CMDSETGET (1, 0x08, opsc04); COMPLETIONWAIT; CMDGETBUF (4, 0x14B4, buffer); if (DBG_LEVEL >= 128) Dump (0x14B4, buffer, NULL); sum = 0; for (i = xstart; i < xend; i++) sum += buffer[i]; sum = sum / (xend - xstart); } *vgaBlue = opsc04[6]; } /* component Z: B&W component (green ...) */ encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (0, *vgaGreen, 0, motor); if (color < RGB_MODE) motor[0] = 0x01; /* in BW, scan zone doesn't have an extra 4 points */ else motor[0] = 0x05; /* extra 4 points */ motor[13] = 0xC0; /* B&W */ if (sanei_umax_pp_getastra () == 1600) { motor[11] |= 0x20; motor[12] = 0x08; motor[13] |= 0x02; opsc04[7] |= 0x20; } CMDSETGET (2, 0x10, motor); if (DBG_LEVEL >= 128) { bloc2Decode (motor); } CMDSETGET (8, 0x24, opsc40); opsc04[6] = *vgaGreen; CMDSETGET (1, 0x08, opsc04); CMDSYNC (0xC2); CMDSYNC (0x00); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; /* B&W hangs here XXX STEF XXX */ CMDGETBUF (4, 0x14B4, buffer); if (DBG_LEVEL >= 128) Dump (0x14B4, buffer, NULL); sum = 0; for (i = xstart; i < xend; i++) sum += buffer[i]; sum = sum / (xend - xstart); while ((opsc04[6] < 0x07) && (sum < 110)) { CMDSYNC (0x00); opsc04[6]++; CMDSETGET (1, 0x08, opsc04); COMPLETIONWAIT; CMDGETBUF (4, 0x0014B4, buffer); if (DBG_LEVEL >= 128) Dump (0x14B4, buffer, NULL); sum = 0; for (i = xstart; i < xend; i++) sum += buffer[i]; sum = sum / (xend - xstart); } *vgaGreen = opsc04[6]; DBG (1, "coarseGainCalibration1220p()=%d,%d,%d done ...\n", *vgaRed, *vgaGreen, *vgaBlue); return 1; } /* * generic function */ static int coarseGainCalibration (int color, int dcRed, int dcGreen, int dcBlue, int *vgaRed, int *vgaGreen, int *vgaBlue) { if (sanei_umax_pp_getastra () <= 610) { if (coarseGainCalibration610p (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue) == 0) { DBG (0, "coarseGainCalibration610p failed !!! (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "coarseGainCalibration610p passed ... (%s:%d)\n", __FILE__, __LINE__); } else { if (coarseGainCalibration1220p (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue) == 0) { DBG (0, "coarseGainCalibration1220p failed !!! (%s:%d)\n", __FILE__, __LINE__); return 0; } DBG (16, "coarseGainCalibration1220p passed ... (%s:%d)\n", __FILE__, __LINE__); } return 1; } /* * computes PGA offset for each pixel of the ccd. * We scan a white area with PGA=0 and computes the * offset to push the result in the correctable range * returns 1 and PGA values in 'calibration' var on success . * On failure, returns 0. */ static int shadingCalibration610p (int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration) { int motor[17] = { 0x5A, 0x80, 0x02, 0x70, 0x00, 0x00, 0xC0, 0x00, 0x17, 0x05, 0x6C, 0xAB, 0xAA, 0x2A, 0xA4, 0x00, -1 }; int ccd[37] = { 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x40, 0x01, 0x00, 0x20, 0x02, 0x00, 0x76, 0x5D, 0x40, 0xA5, 0x06, 0x00, 0x00, 0xE2, 0x5E, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; /* * lm9811[7]= VGA << 4 * lm9811[6]= 0x40 | DC offset */ int lm9811[9] = { 0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x0F, 0x80, -1 }; int commit[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, -1 }; int len, dpi, size; int bpp = 3; /* defaults to color scan value */ int w, h, x, y; int sum, i; float avg, pct, coeff = 0; unsigned char *data = NULL; int top, bottom; TRACE (16, "entering shadingCalibration610p ...\n"); len = 0x22; w = 2550; y = 10; dpi = 300; h = 90; top = 8; bottom = 8; /* move back first */ MOVE (-31, PRECISION_OFF, NULL); /* gray scanning handling */ if (color < RGB_MODE) { lm9811[7] = dcGreen << 4; lm9811[6] = 0x40 | vgaGreen; bpp = 1; motor[13] = 0x6F; } data = (unsigned char *) malloc (w * h * bpp); if (data == NULL) { DBG (0, "shadingCalibration610p: failed to allocate memory (%s:%d)\n", __FILE__, __LINE__); return 0; } memset (data, 0x00, w * h * bpp); /* prepare scan command */ x = sanei_umax_pp_getLeft (); encodeWX (w, x, dpi, color, ccd, bpp * w); encodeHY (h, y, motor); encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (vgaRed, vgaGreen, vgaBlue, motor); if (DBG_LEVEL > 128) { bloc2Decode (motor); bloc8Decode (ccd); } CMDSYNC (0x00); CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSETGET (4, 0x08, commit); COMPLETIONWAIT; /* picture height is scan area height minus y */ /* then we substract 14 or 6 lines that aren't scanned */ if (color < RGB_MODE) h = h - y - 14; else h = h - y - 6; size = w * bpp * h; DBG (128, "shadingCalibration610p: trying to read 0x%06X bytes ... (%s:%d)\n", size, __FILE__, __LINE__); /* since we know that each scan line matches CCD width, we signals * that data reading doens't need to sync on each byte, but at each * row end */ sanei_umax_pp_setfull (1); CMDGETBUF (4, size, data); sanei_umax_pp_setfull (0); /* computes correction here ... */ /* debug image files */ /* data is in R B G order */ if (DBG_LEVEL > 128) DumpNB (w * bpp, h, data, NULL); /* zeroes all shading coefficients first */ memset (calibration, 0x00, 3 * w * sizeof (int)); /* in gray scans, we have only green component (i=3) */ if (color < RGB_MODE) { /* build green only coefficients */ for (x = 4; x < w; x++) { sum = 0; for (y = top; y < h - bottom; y++) sum += data[(y * bpp) * w + x]; avg = ((float) (sum)) / ((float) (h - (top + bottom))); /* XXX ICI XXX avg=128==>2 */ /*coeff = (256.0 * (targetCode / avg - 1.0)) / 2.00;*/ coeff = (256.0 * (targetCode / avg - 1.0)) / ((avg*3.5)/targetCode); if (coeff < 0) coeff = 0; if (coeff > 255) coeff = 255; calibration[x + 2 * w - 4] = (int) (coeff + 0.5); } } else { for (i = 0; i < 3; i++) { for (x = 4; x < w; x++) { sum = 0; for (y = top; y < h - bottom; y++) sum += data[(y * bpp + i) * w + x]; avg = ((float) (sum)) / ((float) (h - (top + bottom))); /* one step increase means a 0.71% increase of the final pixel */ pct = 100.0 - (avg * 100.0) / targetCode; switch (i) { case 0: /* RED 1.80 */ case 1: /* BLUE : 2.10 */ coeff = (int) (pct / 0.57 + 0.5); break; case 2: /* GREEN 1.50 */ coeff = (int) (pct / 0.45 + 0.5); break; } if (coeff < 0) coeff = 0; if (coeff > 255) coeff = 255; calibration[x + i * w - 4] = (int) (coeff + 0.5); } /* 100 in coeffs -> +104 on picture */ } } /* use default color tables */ for (x = 0; x < 256; x++) { calibration[3 * w + x] = ggRed[x]; calibration[3 * w + x + 256] = ggGreen[x]; calibration[3 * w + x + 512] = ggBlue[x]; } if (DBG_LEVEL > 128) { DumpNB (w * bpp, h, data, NULL); DumpNB (w, h * bpp, data, NULL); } free (data); TRACE (16, "shadingCalibration610p end ...\n"); return 1; } /* * build CCD correction: a white area below the top is scanned without * correction, and the data are used to compute the coefficents needed * to correct the light/CCD variations */ static int shadingCalibration (int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration) { if (sanei_umax_pp_getastra () < 1220) return shadingCalibration610p (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, calibration); return shadingCalibration1220p (color, dcRed, dcGreen, dcBlue, vgaRed, vgaGreen, vgaBlue, calibration); } /* * this is certainly gamma calibration * We scan a white area with PGA=0 and computes the * offset to push the result in the correctable range * returns 1 and PGA values in 'calibration' var on success . * On failure, returns 0. */ static int leftShadingCalibration610p (int color, int dcRed, int dcGreen, int dcBlue, int vgaRed, int vgaGreen, int vgaBlue, int *calibration) { int motor[17] = { 0x14, 0x80, 0x02, 0x60, 0xDE, 0x01, 0xC0, 0x2F, 0x17, 0x00, 0x6C, 0xAB, 0xAA, 0x2A, 0xA4, 0x00, -1 }; int ccd[37] = { 0x00, 0x00, 0xD8, 0x27, 0xEC, 0x53, 0x7D, 0x8A, 0x77, 0xE3, 0x1D, 0x79, 0x07, 0x20, 0x02, 0x00, 0x76, 0x41, 0x80, 0xA3, 0xE5, 0x1D, 0x00, 0xF2, 0x5D, 0xA0, 0x00, 0x8B, 0x4D, 0x4B, 0xD0, 0x68, 0xDF, 0x13, 0x1A, 0x00, -1 }; /* * lm9811[7]= VGA << 4 * lm9811[6]= 0x40 | DC offset * lm9811[6].bit7 = use shading data */ int lm9811[9] = { 0x88, 0xE6, 0xFD, 0x8E, 0x30, 0x00, 0x8F, 0x80, -1 }; int *commit = NULL; int len, dpi, size; int w, h, x, y; int ofst; unsigned char *data = NULL; TRACE (16, "entering leftShadingCalibration610p ...\n"); if (sanei_umax_pp_getastra () < 1220) { len = 0x22; ofst = 28; w = 2550; x = 94 - ofst; /* left shift compared to shading calibration */ y = 10; dpi = 75; h = 20; } else { len = 0x24; ofst = 28; w = 5100; x = 180; y = 10; dpi = 600; h = 67; } commit = (int *) malloc ((w * 3 + 5) * sizeof (int)); if (commit == NULL) { DBG (0, "leftShadingCalibration610p: failed to allocate memory (%s:%d)\n", __FILE__, __LINE__); return 0; } data = (unsigned char *) malloc (w * h * 3); if (data == NULL) { DBG (0, "leftShadingCalibration610p: failed to allocate memory (%s:%d)\n", __FILE__, __LINE__); free (commit); return 0; } /* prepare scan command */ encodeWX (w, x, dpi, color, ccd, 7410); encodeHY (h, y, motor); encodeDC (dcRed, dcGreen, dcBlue, motor); encodeVGA (vgaRed, vgaGreen, vgaBlue, motor); if (DBG_LEVEL > 128) { bloc2Decode (motor); bloc8Decode (ccd); } /* build shading calibration data */ memset (commit, 0x00, (3 * w + 5) * sizeof (int)); for (x = ofst; x < w; x++) { commit[x] = calibration[x - ofst]; commit[x + w] = calibration[x - ofst + w]; commit[x + 2 * w] = calibration[x - ofst + 2 * w]; } /* image data cropping coefficient */ commit[3 * w + 3] = 0xFF; commit[3 * w + 4] = 0xFF; CMDSYNC (0x00); CMDSETGET (2, 0x10, motor); CMDSETGET (8, len, ccd); CMDSETGET (1, 0x08, lm9811); CMDSYNC (0xC2); CMDSETGET (4, 3 * w + 5, commit); free (commit); COMPLETIONWAIT; if (color >= RGB_MODE) { /* picture height is scan area height minus y */ h = h - y; size = w * 3 * h; } else { h = h - y - 1; size = w * h; } DBG (128, "leftShadingCalibration610p: trying to read 0x%06X bytes ... (%s:%d)\n", size, __FILE__, __LINE__); CMDGETBUF (4, size, data); if (DBG_LEVEL > 128) DumpNB (3 * w, h, data, NULL); /* XXX STEF XXX */ /* build coefficients for the 25 left pixels */ /* and compute gamma correction ? */ free (data); TRACE (16, "leftShadingCalibration610p end ...\n"); return 1; } sane-backends-1.0.27/backend/rts8891_low.c0000664000175000017500000005577212775312261015026 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007-2013 stef.dev@free.fr This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* this file contains all the low level functions needed for the higher level * functions of the sane standard. They are put there to keep files smaller * and separate functions with different goals. */ #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include #ifdef HAVE_SYS_TIME_H #include #endif #include "rts8891_low.h" #define RTS8891_BUILD 30 #define RTS8891_MAX_REGISTERS 244 /* init rts8891 library */ static void rts8891_low_init (void) { DBG_INIT (); DBG (DBG_info, "RTS8891 low-level functions, version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, RTS8891_BUILD); } /****************************************************************/ /* ASIC specific functions */ /****************************************************************/ /* write all registers, taking care of the special 0xaa value which * must be escaped with a zero */ static SANE_Status rts8891_write_all (SANE_Int devnum, SANE_Byte * regs, SANE_Int count) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte local_regs[RTS8891_MAX_REGISTERS]; size_t size = 0; SANE_Byte buffer[260]; unsigned int i, j; char message[256 * 5]; if (DBG_LEVEL > DBG_io) { for (i = 0; i < (unsigned int) count; i++) { if (i != 0xb3) sprintf (message + 5 * i, "0x%02x ", regs[i]); else sprintf (message + 5 * i, "---- "); } DBG (DBG_io, "rts8891_write_all : write_all(0x00,%d)=%s\n", count, message); } /* copy register set and escaping 0xaa values */ /* b0, b1 abd b3 values may be scribled, but that isn't important */ /* since they are read-only registers */ j = 0; for (i = 0; i < 0xb3; i++) { local_regs[j] = regs[i]; if (local_regs[j] == 0xaa && i < 0xb3) { j++; local_regs[j] = 0x00; } j++; } buffer[0] = 0x88; buffer[1] = 0; buffer[2] = 0x00; buffer[3] = 0xb3; for (i = 0; i < j; i++) buffer[i + 4] = local_regs[i]; /* the USB block is size + 4 bytes of header long */ size = j + 4; if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) { DBG (DBG_error, "rts88xx_write_all : write registers part 1 failed ...\n"); return SANE_STATUS_IO_ERROR; } size = count - 0xb4; /* we need to substract one reg since b3 won't be written */ buffer[0] = 0x88; buffer[1] = 0xb4; buffer[2] = 0x00; buffer[3] = size; for (i = 0; i < size; i++) buffer[i + 4] = regs[0xb4 + i]; /* the USB block is size + 4 bytes of header long */ size += 4; if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) { DBG (DBG_error, "rts88xx_write_all : write registers part 2 failed ...\n"); return SANE_STATUS_IO_ERROR; } return status; } /* this functions "commits" pending scan command */ static SANE_Status rts8891_commit (SANE_Int devnum, SANE_Byte value) { SANE_Status status; SANE_Byte reg; reg = value; sanei_rts88xx_write_reg (devnum, 0xd3, ®); sanei_rts88xx_cancel (devnum); sanei_rts88xx_write_control (devnum, 0x08); status = sanei_rts88xx_write_control (devnum, 0x08); return status; } /* this functions reads button status */ static SANE_Status rts8891_read_buttons (SANE_Int devnum, SANE_Int * mask) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte reg; /* check CONTROL_REG */ sanei_rts88xx_read_reg (devnum, CONTROL_REG, ®); /* read 'base' button status */ sanei_rts88xx_read_reg (devnum, 0x25, ®); DBG (DBG_io, "rts8891_read_buttons: r25=0x%02x\n", reg); *mask |= reg; /* read 'extended' button status */ sanei_rts88xx_read_reg (devnum, 0x1a, ®); DBG (DBG_io, "rts8891_read_buttons: r1a=0x%02x\n", reg); *mask |= reg << 8; /* clear register r25 */ reg = 0x00; sanei_rts88xx_write_reg (devnum, 0x25, ®); /* clear register r1a */ sanei_rts88xx_read_reg (devnum, 0x1a, ®); reg = 0x00; status = sanei_rts88xx_write_reg (devnum, 0x1a, ®); DBG (DBG_info, "rts8891_read_buttons: mask=0x%04x\n", *mask); return status; } /* * Does a simple scan based on the given register set, returning data in a * preallocated buffer of the claimed size. * sanei_rts88xx_data_count cannot be made reliable, when the announced data * amount is read, it may no be ready, leading to errors. To work around * it, we read data count one more time before reading. */ static SANE_Status rts8891_simple_scan (SANE_Int devnum, SANE_Byte * regs, int regcount, SANE_Int format, SANE_Word total, unsigned char *image) { SANE_Word count, read, len, dummy; SANE_Status status = SANE_STATUS_GOOD; SANE_Byte control; rts8891_write_all (devnum, regs, regcount); rts8891_commit (devnum, format); read = 0; count = 0; while (count == 0) { status = sanei_rts88xx_data_count (devnum, &count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "simple_scan: failed to wait for data\n"); return status; } if (count == 0) { status = sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); if (((control & 0x08) == 0) || (status != SANE_STATUS_GOOD)) { DBG (DBG_error, "simple_scan: failed to wait for data\n"); return SANE_STATUS_IO_ERROR; } } } /* data reading */ read = 0; while ((read < total) && (count != 0 || (control & 0x08) == 0x08)) { /* sync ? */ status = sanei_rts88xx_data_count (devnum, &dummy); /* read */ if (count > 0) { len = count; /* read even size unless last chunk */ if ((len & 1) && (read + len < total)) { len++; } if (len > RTS88XX_MAX_XFER_SIZE) { len = RTS88XX_MAX_XFER_SIZE; } if (len > 0) { status = sanei_rts88xx_read_data (devnum, &len, image + read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "simple_scan: failed to read from scanner\n"); return status; } read += len; } } /* don't try to read data count if we have enough data */ if (read < total) { status = sanei_rts88xx_data_count (devnum, &count); } else { count = 0; } if (count == 0) { sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); } } /* sanity check */ if (read < total) { DBG (DBG_io2, "simple_scan: ERROR, %d bytes missing ... \n", total - read); } /* wait for the motor to stop */ do { sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); } while ((control & 0x08) == 0x08); return status; } /** * set the data format. Is part of the commit sequence. Then returned * value is the value used in d3 register for a scan. */ static SANE_Int rts8891_data_format (SANE_Int dpi, int sensor) { SANE_Byte reg = 0x00; /* it seems that lower nibble is a divisor */ if (sensor == SENSOR_TYPE_BARE || sensor == SENSOR_TYPE_XPA) { switch (dpi) { case 75: reg = 0x02; break; case 150: if (sensor == SENSOR_TYPE_BARE) reg = 0x0e; else reg = 0x0b; break; case 300: reg = 0x17; break; case 600: if (sensor == SENSOR_TYPE_BARE) reg = 0x02; else reg = 0x0e; break; case 1200: if (sensor == SENSOR_TYPE_BARE) reg = 0x17; else reg = 0x05; break; } } if (sensor == SENSOR_TYPE_4400 || sensor == SENSOR_TYPE_4400_BARE) { switch (dpi) { case 75: reg = 0x02; break; case 150: if (sensor == SENSOR_TYPE_4400) reg = 0x0b; else reg = 0x17; break; case 300: reg = 0x17; break; case 600: if (sensor == SENSOR_TYPE_4400) reg = 0x0e; else reg = 0x02; break; case 1200: if (sensor == SENSOR_TYPE_4400) reg = 0x05; else reg = 0x17; break; } } return reg; } /** * set up default values for a 75xdpi, 150 ydpi scan */ static void rts8891_set_default_regs (SANE_Byte * scanner_regs) { SANE_Byte default_75[RTS8891_MAX_REGISTERS] = { 0xe5, 0x41, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0a, 0x0a, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x28, 0x3f, 0xff, 0x20, 0xf8, 0x28, 0x07, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x3a, 0xf2, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8c, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x14, 0x18, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x80, 0x68, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x27, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x00, 0xf0, 0xff, 0xf5, 0xf7, 0xea, 0x0b, 0x03, 0x05, 0x86, 0x1b, 0x30, 0xf6, 0xa2, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned int i; for (i = 0; i < RTS8891_MAX_REGISTERS; i++) scanner_regs[i] = default_75[i]; } static SANE_Status rts8891_move (struct Rts8891_Device *device, SANE_Byte * regs, SANE_Int distance, SANE_Bool forward) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte regs10, regs11; DBG (DBG_proc, "rts8891_move: start\n"); DBG (DBG_io, "rts8891_move: %d lines %s, sensor=%d\n", distance, forward == SANE_TRUE ? "forward" : "backward", device->sensor); /* prepare scan */ rts8891_set_default_regs (regs); if (device->sensor != SENSOR_TYPE_4400 && device->sensor != SENSOR_TYPE_4400_BARE) { regs10 = 0x20; regs11 = 0x28; } else { regs10 = 0x10; regs11 = 0x2a; } regs[0x32] = 0x80; regs[0x33] = 0x81; regs[0x35] = 0x10; regs[0x36] = 0x24; regs[0x39] = 0x02; regs[0x3a] = 0x0e; regs[0x64] = 0x01; regs[0x65] = 0x20; regs[0x79] = 0x20; regs[0x7a] = 0x01; regs[0x80] = 0x32; regs[0x82] = 0x33; regs[0x85] = 0x46; regs[0x86] = 0x0b; regs[0x87] = 0x8c; regs[0x88] = 0x10; regs[0x89] = 0xb2; regs[0x8d] = 0x3b; regs[0x8e] = 0x60; regs[0x90] = 0x1c; regs[0xb2] = 0x16; /* 0x10 : stop when at home, 0x04: no data */ regs[0xc0] = 0x00; regs[0xc1] = 0x00; regs[0xc3] = 0x00; regs[0xc4] = 0x00; regs[0xc5] = 0x00; regs[0xc6] = 0x00; regs[0xc7] = 0x00; regs[0xc8] = 0x00; regs[0xca] = 0x00; regs[0xcd] = 0x00; regs[0xce] = 0x00; regs[0xcf] = 0x00; regs[0xd0] = 0x00; regs[0xd1] = 0x00; regs[0xd2] = 0x00; regs[0xd3] = 0x00; regs[0xd4] = 0x00; regs[0xd6] = 0x6b; regs[0xd7] = 0x00; regs[0xd8] = 0x00; regs[0xd9] = 0xad; regs[0xda] = 0xa7; regs[0xe2] = 0x17; regs[0xe3] = 0x0d; regs[0xe4] = 0x06; regs[0xe5] = 0xf9; regs[0xe7] = 0x53; regs[0xe8] = 0x02; regs[0xe9] = 0x02; /* hp4400 sensors */ if (device->sensor == SENSOR_TYPE_4400 || device->sensor == SENSOR_TYPE_4400_BARE) { regs[0x13] = 0x39; /* 0x20 */ regs[0x14] = 0xf0; /* 0xf8 */ regs[0x15] = 0x29; /* 0x28 */ regs[0x16] = 0x0f; /* 0x07 */ regs[0x17] = 0x10; /* 0x00 */ regs[0x23] = 0x00; /* 0xff */ regs[0x35] = 0x29; /* 0x10 */ regs[0x36] = 0x21; /* 0x24 */ regs[0x39] = 0x00; /* 0x02 */ regs[0x80] = 0xb0; /* 0x32 */ regs[0x82] = 0xb1; /* 0x33 */ regs[0xe2] = 0x0b; /* 0x17 */ regs[0xe5] = 0xf3; /* 0xf9 */ regs[0xe6] = 0x01; /* 0x00 */ } /* disable CCD */ regs[0] = 0xf5; sanei_rts88xx_set_status (device->devnum, regs, regs10, regs11); sanei_rts88xx_set_scan_area (regs, distance, distance + 1, 100, 200); sanei_rts88xx_set_gain (regs, 16, 16, 16); sanei_rts88xx_set_offset (regs, 127, 127, 127); /* forward/backward */ /* 0x2c is forward, 0x24 backward */ if (forward == SANE_TRUE) { /* forward */ regs[0x36] = regs[0x36] | 0x08; } else { /* backward */ regs[0x36] = regs[0x36] & 0xf7; } /* write regiters values */ status = rts8891_write_all (device->devnum, regs, RTS8891_MAX_REGISTERS); /* commit it */ rts8891_commit (device->devnum, 0x00); return status; } /** * wait for the scanning head to reach home position */ static SANE_Status rts8891_wait_for_home (struct Rts8891_Device *device, SANE_Byte * regs) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte motor, sensor, reg; DBG (DBG_proc, "rts8891_wait_for_home: start\n"); /* wait for controller home bit to raise, no timeout */ /* at each loop we check that motor is on, then that the sensor bit it cleared */ do { sanei_rts88xx_read_reg (device->devnum, CONTROL_REG, &motor); sanei_rts88xx_read_reg (device->devnum, CONTROLER_REG, &sensor); } while ((motor & 0x08) && ((sensor & 0x02) == 0)); /* flag that device has finished parking */ device->parking=SANE_FALSE; /* check for error */ if (((motor & 0x08) == 0x00) && ((sensor & 0x02) == 0)) { DBG (DBG_error, "rts8891_wait_for_home: error, motor stopped before head parked\n"); status = SANE_STATUS_INVAL; } /* re-enable CCD */ regs[0] = regs[0] & 0xef; sanei_rts88xx_cancel (device->devnum); /* reset ? so we don't need to read data */ reg = 0; /* b7: movement on/off, b3-b0 : movement divisor */ sanei_rts88xx_write_reg (device->devnum, 0x33, ®); sanei_rts88xx_write_reg (device->devnum, 0x33, ®); /* movement direction */ sanei_rts88xx_write_reg (device->devnum, 0x36, ®); sanei_rts88xx_cancel (device->devnum); DBG (DBG_proc, "rts8891_wait_for_home: end\n"); return status; } /** * move the head backward by a huge line number then poll home sensor until * head has get back home. We have our own copy of the registers to avoid * messing scanner status */ static SANE_Status rts8891_park (struct Rts8891_Device *device, SANE_Byte *regs, SANE_Bool wait) { SANE_Status status = SANE_STATUS_GOOD; DBG (DBG_proc, "rts8891_park: start\n"); device->parking=SANE_TRUE; rts8891_move (device, regs, 8000, SANE_FALSE); if(wait==SANE_TRUE) { status = rts8891_wait_for_home (device,regs); } DBG (DBG_proc, "rts8891_park: end\n"); return status; } /* reads data from scanner. * First we wait for some data to be available and then loop reading * from scanner until the required amount is reached. * We handle non blocking I/O by returning immediatly (with SANE_STATUS_BUSY) * if there is no data available from scanner. But once read is started, * all the required amount is read. Once wait for data succeeded, we still poll * for data in order no to read it too fast, but we don' take care of non blocking * mode since we cope with it on first data wait. */ static SANE_Status read_data (struct Rts8891_Session *session, SANE_Byte * dest, SANE_Int length) { SANE_Status status = SANE_STATUS_GOOD; SANE_Int count, read, len, dummy; struct Rts8891_Device *dev = session->dev; static FILE *raw = NULL; /* for debugging purpose we need it static */ SANE_Byte control = 0x08; unsigned char buffer[RTS88XX_MAX_XFER_SIZE]; DBG (DBG_proc, "read_data: start\n"); DBG (DBG_proc, "read_data: requiring %d bytes\n", length); /* wait for data being available and handle non blocking mode */ /* only when data reading hasn't produce any data yet */ if (dev->read == 0) { do { status = sanei_rts88xx_data_count (dev->devnum, &count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to wait for data\n"); return status; } if (count == 0) { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if ((control & 0x08) == 0 && (count == 0)) { DBG (DBG_error, "read_data: scanner stopped being busy before data are available\n"); return SANE_STATUS_IO_ERROR; } } /* in case there is no data, we return BUSY since this mean */ /* that scanning head hasn't reach is position and data hasn't */ /* come yet */ if (session->non_blocking && count == 0) { dev->regs[LAMP_REG] = 0x8d; sanei_rts88xx_write_reg (dev->devnum, LAMP_REG, &(dev->regs[LAMP_REG])); DBG (DBG_io, "read_data: no data vailable\n"); DBG (DBG_proc, "read_data: end\n"); return SANE_STATUS_DEVICE_BUSY; } } while (count == 0); } else { /* start of read for a new block */ status = sanei_rts88xx_data_count (dev->devnum, &count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to wait for data\n"); return status; } if (count == 0) { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if ((control & 0x08) == 0 && (count == 0)) { DBG (DBG_error, "read_data: scanner stopped being busy before data are available\n"); return SANE_STATUS_IO_ERROR; } } } /* fill scanned data buffer */ read = 0; /* now loop reading data until we have the amount requested */ /* we also take care of not reading too much data */ while (read < length && dev->read < dev->to_read && ((control & 0x08) == 0x08)) { /* used to sync */ if (dev->read == 0) { status = sanei_rts88xx_data_count (dev->devnum, &dummy); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to read data count\n"); return status; } } /* if there is data to read, read it */ if (count > 0) { len = count; if (len > RTS88XX_MAX_XFER_SIZE) { len = RTS88XX_MAX_XFER_SIZE; } /* we only read even size blocks of data */ if (len & 1) { DBG (DBG_io, "read_data: round to next even number\n"); len++; } if (len > length - read) { len = length - read; } status = sanei_rts88xx_read_data (dev->devnum, &len, dest + read); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to read from scanner\n"); return status; } /* raw data tracing */ if (DBG_LEVEL >= DBG_io2) { /* open a new file only when no data scanned */ if (dev->read == 0) { raw = fopen ("raw_data.pnm", "wb"); if (raw != NULL) { /* PNM header */ fprintf (raw, "P%c\n%d %d\n255\n", session->params.format == SANE_FRAME_RGB || session->emulated_gray == SANE_TRUE ? '6' : '5', dev->pixels, dev->lines); } } if (raw != NULL) { fwrite (dest + read, 1, len, raw); } } /* move pointer and counter */ read += len; dev->read += len; DBG (DBG_io2, "read_data: %d/%d\n", dev->read, dev->to_read); } /* in fast scan mode, read data count * in slow scan, head moves by the amount of data read */ status = sanei_rts88xx_data_count (dev->devnum, &count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "read_data: failed to read data count\n"); return status; } /* if no data, check if still scanning */ if (count == 0 && dev->read < dev->to_read) { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); if ((control & 0x08) == 0x00) { DBG (DBG_error, "read_data: scanner stopped being busy before data are available\n"); return SANE_STATUS_IO_ERROR; } } } /* end of physical reads */ if (dev->read >= dev->to_read) { /* check there is no more data in case of a bug */ sanei_rts88xx_data_count (dev->devnum, &count); if (count > 0) { DBG (DBG_warn, "read_data: %d bytes are still available from scanner\n", count); /* flush left-over data */ while (count > 0) { len = count; if (len > RTS88XX_MAX_XFER_SIZE) { len = RTS88XX_MAX_XFER_SIZE; } /* we only read even size blocks of data */ if (len & 1) { len++; } sanei_rts88xx_read_data (dev->devnum, &len, buffer); sanei_rts88xx_data_count (dev->devnum, &count); } } /* wait for motor to stop at the end of the scan */ do { sanei_rts88xx_read_reg (dev->devnum, CONTROL_REG, &control); } while ((control & 0x08) != 0); /* close log file if needed */ if (DBG_LEVEL >= DBG_io2) { if (raw != NULL) { fclose (raw); raw = NULL; } } } DBG (DBG_io, "read_data: read %d bytes from scanner\n", length); DBG (DBG_proc, "read_data: end\n"); return status; } /** * set scanner idle before leaving xxx_quiet() write_reg(0x33,1)=0x00 write_reg(0x33,1)=0x00 write_reg(0x36,1)=0x00 prepare(); ------ write_reg(LAMP_REG,1)=0x80 write_reg(LAMP_REG,1)=0xad read_reg(0x14,2)=0xf8 0x28 write_reg(0x14,2)=0x78 0x28 get_status()=0x20 0x3f read_reg(0xb1,1)=0x00 read_control()=0x00 reset_lamp()=(0x20,0x3f) write_reg(LAMP_REG,1)=0x8d write_reg(LAMP_REG,1)=0xad */ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/epson2-commands.c0000664000175000017500000006056312775312260016001 00000000000000/* * ESC/I commands for Epson scanners * * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for original copyrights. * * Copyright (C) 2006 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #include #include #include #include "epson2.h" #include "epson2-io.h" #include "epson2-commands.h" /* ESC H, set zoom */ SANE_Status esci_set_zoom(Epson_Scanner * s, unsigned char x, unsigned char y) { SANE_Status status; unsigned char params[2]; DBG(8, "%s: x = %d, y = %d\n", __func__, x, y); if (!s->hw->cmd->set_zoom) { DBG(1, "%s: not supported\n", __func__); return SANE_STATUS_GOOD; } params[0] = ESC; params[1] = s->hw->cmd->set_zoom; status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; params[0] = x; params[1] = y; return e2_cmd_simple(s, params, 2); } /* ESC R */ SANE_Status esci_set_resolution(Epson_Scanner * s, int x, int y) { SANE_Status status; unsigned char params[4]; DBG(8, "%s: x = %d, y = %d\n", __func__, x, y); if (!s->hw->cmd->set_resolution) { DBG(1, "%s: not supported\n", __func__); return SANE_STATUS_GOOD; } params[0] = ESC; params[1] = s->hw->cmd->set_resolution; status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; params[0] = x; params[1] = x >> 8; params[2] = y; params[3] = y >> 8; return e2_cmd_simple(s, params, 4); } /* * Sends the "set scan area" command to the scanner with the currently selected * scan area. This scan area must be already corrected for "color shuffling" if * necessary. */ SANE_Status esci_set_scan_area(Epson_Scanner * s, int x, int y, int width, int height) { SANE_Status status; unsigned char params[8]; DBG(8, "%s: x = %d, y = %d, w = %d, h = %d\n", __func__, x, y, width, height); if (!s->hw->cmd->set_scan_area) { DBG(1, "%s: not supported\n", __func__); return SANE_STATUS_UNSUPPORTED; } /* verify the scan area */ if (x < 0 || y < 0 || width <= 0 || height <= 0) return SANE_STATUS_INVAL; params[0] = ESC; params[1] = s->hw->cmd->set_scan_area; status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; params[0] = x; params[1] = x >> 8; params[2] = y; params[3] = y >> 8; params[4] = width; params[5] = width >> 8; params[6] = height; params[7] = height >> 8; return e2_cmd_simple(s, params, 8); } static int get_roundup_index(double frac[], int n) { int i, index = -1; double max_val = 0.0; for (i = 0; i < n; i++) { if (frac[i] < 0) continue; if (max_val < frac[i]) { index = i; max_val = frac[i]; } } return index; } static int get_rounddown_index(double frac[], int n) { int i, index = -1; double min_val = 1.0; for (i = 0; i < n; i++) { if (frac[i] > 0) continue; if (min_val > frac[i]) { index = i; min_val = frac[i]; } } return index; } static unsigned char int2cpt(int val) { if (val >= 0) { if (val > 127) val = 127; return (unsigned char) val; } else { val = -val; if (val > 127) val = 127; return (unsigned char) (0x80 | val); } } static void round_cct(double org_cct[], int rnd_cct[]) { int loop = 0; int i, j, sum[3]; double mult_cct[9], frac[9]; for (i = 0; i < 9; i++) { mult_cct[i] = org_cct[i] * 32; rnd_cct[i] = (int) floor(mult_cct[i] + 0.5); } do { for (i = 0; i < 3; i++) { int k = i * 3; if ((rnd_cct[k] == 11) && (rnd_cct[k] == rnd_cct[k + 1]) && (rnd_cct[k] == rnd_cct[k + 2])) { rnd_cct[k + i]--; mult_cct[k + i] = rnd_cct[k + i]; } } for (i = 0; i < 3; i++) { int k = i * 3; for (sum[i] = j = 0; j < 3; j++) sum[i] += rnd_cct[k + j]; } for (i = 0; i < 9; i++) frac[i] = mult_cct[i] - rnd_cct[i]; for (i = 0; i < 3; i++) { int k = i * 3; if (sum[i] < 32) { int index = get_roundup_index(&frac[k], 3); if (index != -1) { rnd_cct[k + index]++; mult_cct[k + index] = rnd_cct[k + index]; sum[i]++; } } else if (sum[i] > 32) { int index = get_rounddown_index(&frac[k], 3); if (index != -1) { rnd_cct[k + index]--; mult_cct[k + index] = rnd_cct[k + index]; sum[i]--; } } } } while ((++loop < 2) && ((sum[0] != 32) || (sum[1] != 32) || (sum[2] != 32))); } static void profile_to_colorcoeff(double *profile, unsigned char *color_coeff) { int cc_idx[] = { 4, 1, 7, 3, 0, 6, 5, 2, 8 }; int i, color_table[9]; round_cct(profile, color_table); for (i = 0; i < 9; i++) color_coeff[i] = int2cpt(color_table[cc_idx[i]]); } /* * Sends the "set color correction coefficients" command with the * currently selected parameters to the scanner. */ SANE_Status esci_set_color_correction_coefficients(Epson_Scanner * s, SANE_Word *table) { SANE_Status status; unsigned char params[2]; unsigned char data[9]; double cct[9]; DBG(8, "%s\n", __func__); if (!s->hw->cmd->set_color_correction_coefficients) { DBG(1, "%s: not supported\n", __func__); return SANE_STATUS_UNSUPPORTED; } params[0] = ESC; params[1] = s->hw->cmd->set_color_correction_coefficients; status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; cct[0] = SANE_UNFIX(table[0]); cct[1] = SANE_UNFIX(table[1]); cct[2] = SANE_UNFIX(table[2]); cct[3] = SANE_UNFIX(table[3]); cct[4] = SANE_UNFIX(table[4]); cct[5] = SANE_UNFIX(table[5]); cct[6] = SANE_UNFIX(table[6]); cct[7] = SANE_UNFIX(table[7]); cct[8] = SANE_UNFIX(table[8]); profile_to_colorcoeff(cct, data); DBG(11, "%s: %d,%d,%d %d,%d,%d %d,%d,%d\n", __func__, data[0] , data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]); return e2_cmd_simple(s, data, 9); } SANE_Status esci_set_gamma_table(Epson_Scanner * s) { SANE_Status status; unsigned char params[2]; unsigned char gamma[257]; int n; int table; /* static const char gamma_cmds[] = { 'M', 'R', 'G', 'B' }; */ static const char gamma_cmds[] = { 'R', 'G', 'B' }; DBG(8, "%s\n", __func__); if (!s->hw->cmd->set_gamma_table) return SANE_STATUS_UNSUPPORTED; params[0] = ESC; params[1] = s->hw->cmd->set_gamma_table; /* Print the gamma tables before sending them to the scanner */ if (DBG_LEVEL >= 16) { int c, i, j; for (c = 0; c < 3; c++) { for (i = 0; i < 256; i += 16) { char gammaValues[16 * 3 + 1], newValue[4]; gammaValues[0] = '\0'; for (j = 0; j < 16; j++) { sprintf(newValue, " %02x", s->gamma_table[c][i + j]); strcat(gammaValues, newValue); } DBG(16, "gamma table[%d][%d] %s\n", c, i, gammaValues); } } } for (table = 0; table < 3; table++) { gamma[0] = gamma_cmds[table]; for (n = 0; n < 256; ++n) gamma[n + 1] = s->gamma_table[table][n]; status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; status = e2_cmd_simple(s, gamma, 257); if (status != SANE_STATUS_GOOD) return status; } return status; } /* ESC F - Request Status * -> ESC f * <- Information block */ SANE_Status esci_request_status(SANE_Handle handle, unsigned char *scanner_status) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; unsigned char params[2]; DBG(8, "%s\n", __func__); if (s->hw->cmd->request_status == 0) return SANE_STATUS_UNSUPPORTED; params[0] = ESC; params[1] = s->hw->cmd->request_status; e2_send(s, params, 2, 4, &status); if (status != SANE_STATUS_GOOD) return status; status = e2_recv_info_block(s, params, 4, NULL); if (status != SANE_STATUS_GOOD) return status; if (scanner_status) *scanner_status = params[0]; DBG(1, "status: %02x\n", params[0]); if (params[0] & STATUS_NOT_READY) DBG(1, " scanner in use on another interface\n"); else DBG(1, " ready\n"); if (params[0] & STATUS_FER) DBG(1, " system error\n"); if (params[0] & STATUS_OPTION) DBG(1, " option equipment is installed\n"); else DBG(1, " no option equipment installed\n"); if (params[0] & STATUS_EXT_COMMANDS) DBG(1, " support extended commands\n"); else DBG(1, " does NOT support extended commands\n"); if (params[0] & STATUS_RESERVED) DBG(0, " a reserved bit is set, please contact the author.\n"); return status; } /* extended commands */ /* FS I, Request Extended Identity * -> FS I * <- Extended identity data (80) * * Request the properties of the scanner. */ SANE_Status esci_request_extended_identity(SANE_Handle handle, unsigned char *buf) { unsigned char model[17]; Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; unsigned char params[2]; DBG(8, "%s\n", __func__); if (buf == NULL) return SANE_STATUS_INVAL; if (s->hw->cmd->request_extended_identity == 0) return SANE_STATUS_UNSUPPORTED; params[0] = FS; params[1] = s->hw->cmd->request_extended_identity; status = e2_txrx(s, params, 2, buf, 80); if (status != SANE_STATUS_GOOD) return status; DBG(1, " command level : %c%c\n", buf[0], buf[1]); DBG(1, " basic resolution: %lu\n", (unsigned long) le32atoh(&buf[4])); DBG(1, " min resolution : %lu\n", (unsigned long) le32atoh(&buf[8])); DBG(1, " max resolution : %lu\n", (unsigned long) le32atoh(&buf[12])); DBG(1, " max pixel num : %lu\n", (unsigned long) le32atoh(&buf[16])); DBG(1, " scan area : %lux%lu\n", (unsigned long) le32atoh(&buf[20]), (unsigned long) le32atoh(&buf[24])); DBG(1, " adf area : %lux%lu\n", (unsigned long) le32atoh(&buf[28]), (unsigned long) le32atoh(&buf[32])); DBG(1, " tpu area : %lux%lu\n", (unsigned long) le32atoh(&buf[36]), (unsigned long) le32atoh(&buf[40])); DBG(1, " capabilities (1): 0x%02x\n", buf[44]); DBG(1, " capabilities (2): 0x%02x\n", buf[45]); DBG(1, " input depth : %d\n", buf[66]); DBG(1, " max output depth: %d\n", buf[67]); DBG(1, " rom version : %c%c%c%c\n", buf[62], buf[63], buf[64], buf[65]); memcpy(model, &buf[46], 16); model[16] = '\0'; DBG(1, " model name : %s\n", model); DBG(1, "options:\n"); if (le32atoh(&buf[28]) > 0) DBG(1, " ADF detected\n"); if (le32atoh(&buf[36]) > 0) DBG(1, " TPU detected\n"); if (buf[44]) DBG(1, "capabilities (1):\n"); if (buf[44] & EXT_IDTY_CAP1_DLF) DBG(1, " main lamp change is supported\n"); if (buf[44] & EXT_IDTY_CAP1_NOTFBF) DBG(1, " the device is NOT flatbed\n"); if (buf[44] & EXT_IDTY_CAP1_ADFT) DBG(1, " page type ADF is installed\n"); if (buf[44] & EXT_IDTY_CAP1_ADFS) DBG(1, " ADF is duplex capable\n"); if (buf[44] & EXT_IDTY_CAP1_ADFO) DBG(1, " page type ADF loads from the first sheet\n"); if (buf[44] & EXT_IDTY_CAP1_LID) DBG(1, " lid type option is installed\n"); if (buf[44] & EXT_IDTY_CAP1_TPIR) DBG(1, " infrared scanning is supported\n"); if (buf[44] & EXT_IDTY_CAP1_PB) DBG(1, " push button is supported\n"); if (buf[45]) DBG(1, "capabilities (2):\n"); if (buf[45] & EXT_IDTY_CAP2_AFF) DBG(1, " ADF has auto form feed\n"); if (buf[45] & EXT_IDTY_CAP2_DFD) DBG(1, " ADF has double feed detection\n"); if (buf[45] & EXT_IDTY_CAP2_ADFAS) DBG(1, " ADF has auto scan\n"); return SANE_STATUS_GOOD; } /* FS F, request scanner status */ SANE_Status esci_request_scanner_status(SANE_Handle handle, unsigned char *buf) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; unsigned char params[2]; DBG(8, "%s\n", __func__); if (!s->hw->extended_commands) return SANE_STATUS_UNSUPPORTED; if (buf == NULL) return SANE_STATUS_INVAL; params[0] = FS; params[1] = 'F'; status = e2_txrx(s, params, 2, buf, 16); if (status != SANE_STATUS_GOOD) return status; DBG(1, "global status : 0x%02x\n", buf[0]); if (buf[0] & FSF_STATUS_MAIN_FER) DBG(1, " system error\n"); if (buf[0] & FSF_STATUS_MAIN_NR) DBG(1, " not ready\n"); if (buf[0] & FSF_STATUS_MAIN_WU) DBG(1, " scanner is warming up\n"); if (buf[0] & FSF_STATUS_MAIN_CWU) DBG(1, " warmup can be cancelled\n"); DBG(1, "adf status : 0x%02x\n", buf[1]); if (buf[1] & FSF_STATUS_ADF_IST) DBG(11, " installed\n"); else DBG(11, " not installed\n"); if (buf[1] & FSF_STATUS_ADF_EN) DBG(11, " enabled\n"); else DBG(11, " not enabled\n"); if (buf[1] & FSF_STATUS_ADF_ERR) DBG(1, " error\n"); if (buf[1] & FSF_STATUS_ADF_PE) DBG(1, " paper empty\n"); if (buf[1] & FSF_STATUS_ADF_PJ) DBG(1, " paper jam\n"); if (buf[1] & FSF_STATUS_ADF_OPN) DBG(1, " cover open\n"); if (buf[1] & FSF_STATUS_ADF_PAG) DBG(1, " duplex capable\n"); DBG(1, "tpu status : 0x%02x\n", buf[2]); if (buf[2] & FSF_STATUS_TPU_IST) DBG(11, " installed\n"); else DBG(11, " not installed\n"); if (buf[2] & FSF_STATUS_TPU_EN) DBG(11, " enabled\n"); else DBG(11, " not enabled\n"); if (buf[2] & FSF_STATUS_TPU_ERR) DBG(1, " error\n"); if (buf[1] & FSF_STATUS_TPU_OPN) DBG(1, " cover open\n"); DBG(1, "device type : 0x%02x\n", buf[3] & 0xC0); DBG(1, "main body status: 0x%02x\n", buf[3] & 0x3F); if (buf[3] & FSF_STATUS_MAIN2_PE) DBG(1, " paper empty\n"); if (buf[3] & FSF_STATUS_MAIN2_PJ) DBG(1, " paper jam\n"); if (buf[3] & FSF_STATUS_MAIN2_OPN) DBG(1, " cover open\n"); return SANE_STATUS_GOOD; } SANE_Status esci_set_scanning_parameter(SANE_Handle handle, unsigned char *buf) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; unsigned char params[2]; DBG(8, "%s\n", __func__); if (buf == NULL) return SANE_STATUS_INVAL; params[0] = FS; params[1] = 'W'; DBG(10, "resolution of main scan : %lu\n", (unsigned long) le32atoh(&buf[0])); DBG(10, "resolution of sub scan : %lu\n", (unsigned long) le32atoh(&buf[4])); DBG(10, "offset length of main scan : %lu\n", (unsigned long) le32atoh(&buf[8])); DBG(10, "offset length of sub scan : %lu\n", (unsigned long) le32atoh(&buf[12])); DBG(10, "scanning length of main scan: %lu\n", (unsigned long) le32atoh(&buf[16])); DBG(10, "scanning length of sub scan : %lu\n", (unsigned long) le32atoh(&buf[20])); DBG(10, "scanning color : %d\n", buf[24]); DBG(10, "data format : %d\n", buf[25]); DBG(10, "option control : %d\n", buf[26]); DBG(10, "scanning mode : %d\n", buf[27]); DBG(10, "block line number : %d\n", buf[28]); DBG(10, "gamma correction : %d\n", buf[29]); DBG(10, "brightness : %d\n", buf[30]); DBG(10, "color correction : %d\n", buf[31]); DBG(10, "halftone processing : %d\n", buf[32]); DBG(10, "threshold : %d\n", buf[33]); DBG(10, "auto area segmentation : %d\n", buf[34]); DBG(10, "sharpness control : %d\n", buf[35]); DBG(10, "mirroring : %d\n", buf[36]); DBG(10, "film type : %d\n", buf[37]); DBG(10, "main lamp lighting mode : %d\n", buf[38]); status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; status = e2_cmd_simple(s, buf, 64); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: invalid scanning parameters\n", __func__); return status; } return SANE_STATUS_GOOD; } /* FS S */ SANE_Status esci_get_scanning_parameter(SANE_Handle handle, unsigned char *buf) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; unsigned char params[2]; DBG(8, "%s\n", __func__); if (buf == NULL) return SANE_STATUS_INVAL; params[0] = FS; params[1] = 'S'; status = e2_txrx(s, params, 2, buf, 64); if (status != SANE_STATUS_GOOD) return status; DBG(10, "resolution of main scan : %lu\n", (u_long) le32atoh(&buf[0])); DBG(10, "resolution of sub scan : %lu\n", (u_long) le32atoh(&buf[4])); DBG(10, "offset length of main scan : %lu\n", (u_long) le32atoh(&buf[8])); DBG(10, "offset length of sub scan : %lu\n", (u_long) le32atoh(&buf[12])); DBG(10, "scanning length of main scan: %lu\n", (u_long) le32atoh(&buf[16])); DBG(10, "scanning length of sub scan : %lu\n", (u_long) le32atoh(&buf[20])); DBG(10, "scanning color : %d\n", buf[24]); DBG(10, "data format : %d\n", buf[25]); DBG(10, "option control : %d\n", buf[26]); DBG(10, "scanning mode : %d\n", buf[27]); DBG(10, "block line number : %d\n", buf[28]); DBG(10, "gamma correction : %d\n", buf[29]); DBG(10, "brightness : %d\n", buf[30]); DBG(10, "color correction : %d\n", buf[31]); DBG(10, "halftone processing : %d\n", buf[32]); DBG(10, "threshold : %d\n", buf[33]); DBG(10, "auto area segmentation : %d\n", buf[34]); DBG(10, "sharpness control : %d\n", buf[35]); DBG(10, "mirroring : %d\n", buf[36]); DBG(10, "film type : %d\n", buf[37]); DBG(10, "main lamp lighting mode : %d\n", buf[38]); return SANE_STATUS_GOOD; } /* ESC # */ SANE_Status esci_enable_infrared(SANE_Handle handle) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; int i; unsigned char params[2]; unsigned char buf[64]; unsigned char seq[32] = { 0xCA, 0xFB, 0x77, 0x71, 0x20, 0x16, 0xDA, 0x09, 0x5F, 0x57, 0x09, 0x12, 0x04, 0x83, 0x76, 0x77, 0x3C, 0x73, 0x9C, 0xBE, 0x7A, 0xE0, 0x52, 0xE2, 0x90, 0x0D, 0xFF, 0x9A, 0xEF, 0x4C, 0x2C, 0x81 }; DBG(8, "%s\n", __func__); status = esci_get_scanning_parameter(handle, buf); if (status != SANE_STATUS_GOOD) return status; for (i = 0; i < 32; i++) { buf[i] = seq[i] ^ buf[i]; } params[0] = ESC; params[1] = '#'; status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; status = e2_cmd_simple(s, buf, 32); if (status != SANE_STATUS_GOOD) return status; return SANE_STATUS_GOOD; } SANE_Status esci_request_command_parameter(SANE_Handle handle, unsigned char *buf) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; unsigned char params[2]; DBG(8, "%s\n", __func__); if (s->hw->cmd->request_condition == 0) return SANE_STATUS_UNSUPPORTED; params[0] = ESC; params[1] = s->hw->cmd->request_condition; status = e2_cmd_info_block(s, params, 2, 45, &buf, NULL); if (status != SANE_STATUS_GOOD) return status; DBG(1, "scanning parameters:\n"); DBG(1, "color : %d\n", buf[1]); DBG(1, "resolution : %dx%d\n", buf[4] << 8 | buf[3], buf[6] << 8 | buf[5]); DBG(1, "halftone : %d\n", buf[19]); DBG(1, "brightness : %d\n", buf[21]); DBG(1, "color correction : %d\n", buf[28]); DBG(1, "gamma : %d\n", buf[23]); DBG(1, "sharpness : %d\n", buf[30]); DBG(1, "threshold : %d\n", buf[38]); DBG(1, "data format : %d\n", buf[17]); DBG(1, "mirroring : %d\n", buf[34]); DBG(1, "option unit control : %d\n", buf[42]); DBG(1, "film type : %d\n", buf[44]); DBG(1, "auto area segmentation : %d\n", buf[36]); DBG(1, "line counter : %d\n", buf[40]); DBG(1, "scanning mode : %d\n", buf[32]); DBG(1, "zoom : %d,%d\n", buf[26], buf[25]); DBG(1, "scan area : %d,%d %d,%d\n", buf[9] << 8 | buf[8], buf[11] << 8 | buf[10], buf[13] << 8 | buf[12], buf[15] << 8 | buf[14]); return status; } /* ESC q - Request Focus Position * -> ESC q * <- Information block * <- Focus position status (2) * 0 - Error status * 1 - Focus position */ SANE_Status esci_request_focus_position(SANE_Handle handle, unsigned char *position) { SANE_Status status; unsigned char *buf; Epson_Scanner *s = (Epson_Scanner *) handle; unsigned char params[2]; DBG(8, "%s\n", __func__); if (s->hw->cmd->request_focus_position == 0) return SANE_STATUS_UNSUPPORTED; params[0] = ESC; params[1] = s->hw->cmd->request_focus_position; status = e2_cmd_info_block(s, params, 2, 2, &buf, NULL); if (status != SANE_STATUS_GOOD) return status; if (buf[0] & 0x01) DBG(1, "autofocus error\n"); *position = buf[1]; DBG(8, " focus position = 0x%x\n", buf[1]); free(buf); return status; } /* ESC ! - Request Push Button Status * -> ESC ! * <- Information block * <- Push button status (1) */ SANE_Status esci_request_push_button_status(SANE_Handle handle, unsigned char *bstatus) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; unsigned char params[2]; unsigned char *buf; DBG(8, "%s\n", __func__); if (s->hw->cmd->request_push_button_status == 0) { DBG(1, "push button status unsupported\n"); return SANE_STATUS_UNSUPPORTED; } params[0] = ESC; params[1] = s->hw->cmd->request_push_button_status; status = e2_cmd_info_block(s, params, 2, 1, &buf, NULL); if (status != SANE_STATUS_GOOD) return status; DBG(1, "push button status = %d\n", buf[0]); *bstatus = buf[0]; free(buf); return status; } /* * Request Identity information from scanner and fill in information * into dev and/or scanner structures. * XXX information should be parsed separately. */ SANE_Status esci_request_identity(SANE_Handle handle, unsigned char **buf, size_t *len) { Epson_Scanner *s = (Epson_Scanner *) handle; unsigned char params[2]; DBG(8, "%s\n", __func__); if (!s->hw->cmd->request_identity) return SANE_STATUS_INVAL; params[0] = ESC; params[1] = s->hw->cmd->request_identity; return e2_cmd_info_block(s, params, 2, 0, buf, len); } /* * Request information from scanner */ SANE_Status esci_request_identity2(SANE_Handle handle, unsigned char **buf) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status; size_t len; unsigned char params[2]; DBG(8, "%s\n", __func__); if (s->hw->cmd->request_identity2 == 0) return SANE_STATUS_UNSUPPORTED; params[0] = ESC; params[1] = s->hw->cmd->request_identity2; status = e2_cmd_info_block(s, params, 2, 0, buf, &len); if (status != SANE_STATUS_GOOD) return status; return status; } /* Send the "initialize scanner" command to the device and reset it */ SANE_Status esci_reset(Epson_Scanner * s) { SANE_Status status; unsigned char params[2]; DBG(8, "%s\n", __func__); if (!s->hw->cmd->initialize_scanner) return SANE_STATUS_GOOD; params[0] = ESC; params[1] = s->hw->cmd->initialize_scanner; if (s->fd == -1) return SANE_STATUS_GOOD; status = e2_cmd_simple(s, params, 2); return status; } SANE_Status esci_feed(Epson_Scanner * s) { unsigned char params[1]; DBG(8, "%s\n", __func__); if (!s->hw->cmd->feed) return SANE_STATUS_UNSUPPORTED; params[0] = s->hw->cmd->feed; return e2_cmd_simple(s, params, 1); } /* * Eject the current page from the ADF. The scanner is opened prior to * sending the command and closed afterwards. */ SANE_Status esci_eject(Epson_Scanner * s) { unsigned char params[1]; DBG(8, "%s\n", __func__); if (!s->hw->cmd->eject) return SANE_STATUS_UNSUPPORTED; if (s->fd == -1) return SANE_STATUS_GOOD; params[0] = s->hw->cmd->eject; return e2_cmd_simple(s, params, 1); } SANE_Status esci_request_extended_status(SANE_Handle handle, unsigned char **data, size_t * data_len) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Status status = SANE_STATUS_GOOD; unsigned char params[2]; unsigned char *buf; size_t buf_len; DBG(8, "%s\n", __func__); if (s->hw->cmd->request_extended_status == 0) return SANE_STATUS_UNSUPPORTED; params[0] = ESC; params[1] = s->hw->cmd->request_extended_status; /* This command returns 33 bytes of data on old scanners * and 42 (CMD_SIZE_EXT_STATUS) on new ones. */ status = e2_cmd_info_block(s, params, 2, CMD_SIZE_EXT_STATUS, &buf, &buf_len); if (status != SANE_STATUS_GOOD) return status; switch (buf_len) { case 33: case 42: break; default: DBG(1, "%s: unknown reply length (%lu)\n", __func__, (unsigned long) buf_len); break; } DBG(4, "main = %02x, ADF = %02x, TPU = %02x, main 2 = %02x\n", buf[0], buf[1], buf[6], buf[11]); if (buf[0] & EXT_STATUS_FER) DBG(1, "system error\n"); if (buf[0] & EXT_STATUS_WU) DBG(1, "scanner is warming up\n"); if (buf[1] & EXT_STATUS_ERR) DBG(1, "ADF: other error\n"); if (buf[1] & EXT_STATUS_PE) DBG(1, "ADF: no paper\n"); if (buf[1] & EXT_STATUS_PJ) DBG(1, "ADF: paper jam\n"); if (buf[1] & EXT_STATUS_OPN) DBG(1, "ADF: cover open\n"); if (buf[6] & EXT_STATUS_ERR) DBG(1, "TPU: other error\n"); /* give back a pointer to the payload * if the user requested it, otherwise * free it. */ if (data) *data = buf; else free(buf); if (data_len) *data_len = buf_len; return status; } sane-backends-1.0.27/backend/gt68xx_gt6801.h0000664000175000017500000000523012112021330015124 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov GT6801 support by Andreas Nowack This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GT68XX_GT6801_H #define GT68XX_GT6801_H static SANE_Status gt6801_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded); static SANE_Status gt6801_check_plustek_firmware (GT68xx_Device * dev, SANE_Bool * loaded); static SANE_Status gt6801_download_firmware (GT68xx_Device * dev, SANE_Byte * data, SANE_Word size); static SANE_Status gt6801_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok); static SANE_Status gt6801_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp, SANE_Bool ta_lamp); static SANE_Status gt6801_is_moving (GT68xx_Device * dev, SANE_Bool * moving); static SANE_Status gt6801_carriage_home (GT68xx_Device * dev); static SANE_Status gt6801_stop_scan (GT68xx_Device * dev); #endif /* not GT68XX_GT6801_H */ sane-backends-1.0.27/backend/matsushita.h0000664000175000017500000002631412112021330015133 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Frank Zago (sane at zago dot net) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ */ /* Commands supported by the KV-SS 25 scanner. */ #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_INQUIRY 0x12 #define SCSI_SET_WINDOW 0x24 #define SCSI_READ_10 0x28 #define SCSI_REQUEST_SENSE 0x03 typedef struct { unsigned char data[16]; int len; } CDB; /* Set a specific bit depending on a boolean. * MKSCSI_BIT(TRUE, 3) will generate 0x08. */ #define MKSCSI_BIT(bit, pos) ((bit)? 1<<(pos): 0) /* Set a value in a range of bits. * MKSCSI_I2B(5, 3, 5) will generate 0x28 */ #define MKSCSI_I2B(bits, pos_b, pos_e) ((bits) << (pos_b) & ((1<<((pos_e)-(pos_b)+1))-1)) /* Store an integer in 2, 3 or 4 byte in an array. */ #define Ito16(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 0) & 0xff; \ } #define Ito24(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 0) & 0xff; \ } #define Ito32(val, buf) { \ ((unsigned char *)buf)[0] = ((val) >> 24) & 0xff; \ ((unsigned char *)buf)[1] = ((val) >> 16) & 0xff; \ ((unsigned char *)buf)[2] = ((val) >> 8) & 0xff; \ ((unsigned char *)buf)[3] = ((val) >> 0) & 0xff; \ } #define MKSCSI_TEST_UNIT_READY(cdb) \ cdb.data[0] = SCSI_TEST_UNIT_READY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_INQUIRY(cdb, buflen) \ cdb.data[0] = SCSI_INQUIRY; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = buflen; \ cdb.data[5] = 0; \ cdb.len = 6; #define MKSCSI_SET_WINDOW(cdb, buflen) \ cdb.data[0] = SCSI_SET_WINDOW; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = 0; \ cdb.data[5] = 0; \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_READ_10(cdb, dtc, dtq, buflen) \ cdb.data[0] = SCSI_READ_10; \ cdb.data[1] = 0; \ cdb.data[2] = (dtc); \ cdb.data[3] = 0; \ cdb.data[4] = (((dtq) >> 8) & 0xff); \ cdb.data[5] = (((dtq) >> 0) & 0xff); \ cdb.data[6] = (((buflen) >> 16) & 0xff); \ cdb.data[7] = (((buflen) >> 8) & 0xff); \ cdb.data[8] = (((buflen) >> 0) & 0xff); \ cdb.data[9] = 0; \ cdb.len = 10; #define MKSCSI_REQUEST_SENSE(cdb, buflen) \ cdb.data[0] = SCSI_REQUEST_SENSE; \ cdb.data[1] = 0; \ cdb.data[2] = 0; \ cdb.data[3] = 0; \ cdb.data[4] = (buflen); \ cdb.data[5] = 0; \ cdb.len = 6; /*--------------------------------------------------------------------------*/ static inline int getbitfield (unsigned char *pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /*--------------------------------------------------------------------------*/ #define mmToIlu(mm) (((mm) * 1200) / MM_PER_INCH) #define iluToMm(ilu) (((ilu) * MM_PER_INCH) / 1200) #define PAGE_FRONT 0x00 #define PAGE_BACK 0x80 /*--------------------------------------------------------------------------*/ enum Matsushita_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_MODE, /* scanner modes */ OPT_RESOLUTION, /* X and Y resolution */ OPT_DUPLEX, /* Duplex mode */ OPT_FEEDER_MODE, /* Feeding mode */ OPT_GEOMETRY_GROUP, OPT_PAPER_SIZE, /* Paper size */ OPT_TL_X, /* upper left X */ OPT_TL_Y, /* upper left Y */ OPT_BR_X, /* bottom right X */ OPT_BR_Y, /* bottom right Y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, /* Brightness */ OPT_CONTRAST, /* Contrast */ OPT_AUTOMATIC_THRESHOLD, /* Automatic threshold */ OPT_HALFTONE_PATTERN, /* Halftone pattern */ OPT_AUTOMATIC_SEPARATION, /* Automatic separation */ OPT_WHITE_LEVEL, /* White level */ OPT_NOISE_REDUCTION, /* Noise reduction */ OPT_IMAGE_EMPHASIS, /* Image emphasis */ OPT_GAMMA, /* Gamma */ /* must come last: */ OPT_NUM_OPTIONS }; /*--------------------------------------------------------------------------*/ #define BLACK_WHITE_STR SANE_VALUE_SCAN_MODE_LINEART #define GRAY4_STR SANE_I18N("Grayscale 4 bits") #define GRAY8_STR SANE_I18N("Grayscale 8 bits") /*--------------------------------------------------------------------------*/ #define SANE_NAME_DUPLEX "duplex" #define SANE_NAME_PAPER_SIZE "paper-size" #define SANE_NAME_AUTOSEP "autoseparation" #define SANE_TITLE_DUPLEX SANE_I18N("Duplex") #define SANE_TITLE_PAPER_SIZE SANE_I18N("Paper size") #define SANE_TITLE_AUTOSEP SANE_I18N("Automatic separation") #define SANE_DESC_DUPLEX \ SANE_I18N("Enable Duplex (Dual-Sided) Scanning") #define SANE_DESC_PAPER_SIZE \ SANE_I18N("Physical size of the paper in the ADF"); #define SANE_DESC_AUTOSEP \ SANE_I18N("Automatic separation") /*--------------------------------------------------------------------------*/ /* Differences between the scanners. * The scsi_* fields are used to lookup the correcte entry. */ struct scanners_supported { int scsi_type; char scsi_vendor[9]; char scsi_product[17]; SANE_Range x_range; SANE_Range y_range; SANE_Range brightness_range; SANE_Range contrast_range; SANE_String_Const *scan_mode_list; /* array of scan modes */ const SANE_Word *resolutions_list; /* array of available resolutions */ const SANE_Word *resolutions_round; /* rounding values for each resolutions */ SANE_String_Const *image_emphasis_list; /* list of image emphasis options */ const int *image_emphasis_val; /* list of image emphasis values */ /* Scanner capabilities. */ int cap; /* bit field */ #define MAT_CAP_DUPLEX 0x00000002 /* can do duplex */ #define MAT_CAP_CONTRAST 0x00000004 /* have contrast */ #define MAT_CAP_AUTOMATIC_THRESHOLD 0x00000008 #define MAT_CAP_WHITE_LEVEL 0x00000010 #define MAT_CAP_GAMMA 0x00000020 #define MAT_CAP_NOISE_REDUCTION 0x00000040 #define MAT_CAP_PAPER_DETECT 0x00000080 #define MAT_CAP_MIRROR_IMAGE 0x00000100 #define MAT_CAP_DETECT_DOUBLE_FEED 0x00000200 #define MAT_CAP_MANUAL_FEED 0x00000400 }; struct paper_sizes { SANE_String_Const name; /* name of the paper */ int width; int length; }; /*--------------------------------------------------------------------------*/ /* Define a scanner occurence. */ typedef struct Matsushita_Scanner { struct Matsushita_Scanner *next; SANE_Device sane; char *devicename; int sfd; /* device handle */ /* Infos from inquiry. */ char scsi_type; char scsi_vendor[9]; char scsi_product[17]; char scsi_version[5]; /* Scanner infos. */ int scnum; /* index of that scanner in * scanners_supported */ SANE_String_Const *paper_sizes_list; /* names of supported papers */ int *paper_sizes_val; /* indirection into paper_sizes[] */ /* SCSI handling */ size_t buffer_size; /* size of the buffer */ SANE_Byte *buffer; /* for SCSI transfer. */ /* Scanning handling. */ int scanning; /* TRUE if a scan is running. */ int resolution; /* resolution in DPI, for both X and Y */ int x_tl; /* X top left */ int y_tl; /* Y top left */ int x_br; /* X bottom right */ int y_br; /* Y bottom right */ int width; /* width of the scan area in mm */ int length; /* length of the scan area in mm */ enum { MATSUSHITA_BW, MATSUSHITA_HALFTONE, MATSUSHITA_GRAYSCALE } scan_mode; int depth; /* depth per color */ int halftone_pattern; /* haltone number, valid for MATSUSHITA_HALFTONE */ size_t bytes_left; /* number of bytes left to give to the backend */ size_t real_bytes_left; /* number of bytes left the scanner will return. */ SANE_Parameters params; int page_side; /* 0=front, 1=back */ int page_num; /* current number of the page */ /* For Grayscale 4 bits only */ SANE_Byte *image; /* keep the current image there */ size_t image_size; /* allocated size of image */ size_t image_begin; /* first significant byte in image */ size_t image_end; /* first free byte in image */ /* Options */ SANE_Option_Descriptor opt[OPT_NUM_OPTIONS]; Option_Value val[OPT_NUM_OPTIONS]; } Matsushita_Scanner; /*--------------------------------------------------------------------------*/ /* Debug levels. * Should be common to all backends. */ #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 /*--------------------------------------------------------------------------*/ /* 32 bits from an array to an integer (eg ntohl). */ #define B32TOI(buf) \ ((((unsigned char *)buf)[0] << 24) | \ (((unsigned char *)buf)[1] << 16) | \ (((unsigned char *)buf)[2] << 8) | \ (((unsigned char *)buf)[3] << 0)) sane-backends-1.0.27/backend/hp-handle.c0000664000175000017500000005330212775312261014626 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ /* #define STUBS extern int sanei_debug_hp; */ #define DEBUG_DECLARE_ONLY #include "../include/sane/config.h" #ifdef HAVE_UNISTD_H # include #endif #include #include #include "../include/lassert.h" #include #include #include #include "hp-handle.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_thread.h" #include "hp-device.h" #include "hp-option.h" #include "hp-accessor.h" #include "hp-scsi.h" #include "hp-scl.h" struct hp_handle_s { HpData data; HpDevice dev; SANE_Parameters scan_params; SANE_Pid reader_pid; int child_forked; /* Flag if we used fork() or not */ size_t bytes_left; int pipe_read_fd; sigset_t sig_set; sig_atomic_t cancelled; /* These data are used by the child */ HpScsi scsi; HpProcessData procdata; int pipe_write_fd; }; static hp_bool_t hp_handle_isScanning (HpHandle this) { return this->reader_pid != 0; } /* * reader thread. Used when threads are used */ static int reader_thread (void *data) { struct hp_handle_s *this = (struct hp_handle_s *) data; struct SIGACTION act; SANE_Status status; DBG (1, "reader_thread: thread started\n" " parameters: scsi = 0x%08lx, pipe_write_fd = %d\n", (long) this->scsi, this->pipe_write_fd); memset(&act, 0, sizeof(act)); sigaction(SIGTERM, &act, 0); DBG (1, "Starting sanei_hp_scsi_pipeout()\n"); status = sanei_hp_scsi_pipeout (this->scsi, this->pipe_write_fd, &(this->procdata)); DBG (1, "sanei_hp_scsi_pipeout finished with %s\n", sane_strstatus (status)); close (this->pipe_write_fd); this->pipe_write_fd = -1; sanei_hp_scsi_destroy (this->scsi, 0); return status; } /* * reader process. Used when forking child. */ static int reader_process (void *data) { struct hp_handle_s *this = (struct hp_handle_s *) data; struct SIGACTION sa; SANE_Status status; /* Here we are in a forked child. The thread will not come up to here. */ /* Forked child must close read end of pipe */ close (this->pipe_read_fd); this->pipe_read_fd = -1; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; sigaction(SIGTERM, &sa, 0); sigdelset(&(this->sig_set), SIGTERM); sigprocmask(SIG_SETMASK, &(this->sig_set), 0); /* not closing writing end of pipe gives an infinite loop on Digital UNIX */ status = sanei_hp_scsi_pipeout (this->scsi, this->pipe_write_fd, &(this->procdata)); close (this->pipe_write_fd); this->pipe_write_fd = -1; DBG(3,"reader_process: Exiting child (%s)\n",sane_strstatus(status)); return (status); } static SANE_Status hp_handle_startReader (HpHandle this, HpScsi scsi) { int fds[2]; sigset_t old_set; assert(this->reader_pid == 0); this->cancelled = 0; this->pipe_write_fd = this->pipe_read_fd = -1; if (pipe(fds)) return SANE_STATUS_IO_ERROR; sigfillset(&(this->sig_set)); sigprocmask(SIG_BLOCK, &(this->sig_set), &old_set); this->scsi = scsi; this->pipe_write_fd = fds[1]; this->pipe_read_fd = fds[0]; /* Will childs be forked ? */ this->child_forked = sanei_thread_is_forked (); /* Start a thread or fork a child. None of them will return here. */ /* Returning means to be in the parent or thread/fork failed */ this->reader_pid = sanei_thread_begin (this->child_forked ? reader_process : reader_thread, (void *) this); if (this->reader_pid != 0) { /* Here we are in the parent */ sigprocmask(SIG_SETMASK, &old_set, 0); if ( this->child_forked ) { /* After fork(), parent must close writing end of pipe */ DBG(3, "hp_handle_startReader: parent closes write end of pipe\n"); close (this->pipe_write_fd); this->pipe_write_fd = -1; } if (!sanei_thread_is_valid (this->reader_pid)) { if ( !this->child_forked ) { close (this->pipe_write_fd); this->pipe_write_fd = -1; } close (this->pipe_read_fd); this->pipe_read_fd = -1; DBG(1, "hp_handle_startReader: fork() failed\n"); return SANE_STATUS_IO_ERROR; } DBG(1, "start_reader: reader process %ld started\n", (long) this->reader_pid); return SANE_STATUS_GOOD; } DBG(3, "Unexpected return from sanei_thread_begin()\n"); return SANE_STATUS_INVAL; } static SANE_Status hp_handle_stopScan (HpHandle this) { HpScsi scsi; this->cancelled = 0; this->bytes_left = 0; if (this->reader_pid) { int info; DBG(3, "hp_handle_stopScan: killing child (%ld)\n", (long) this->reader_pid); if (this->child_forked) { kill(this->reader_pid, SIGTERM); waitpid(this->reader_pid, &info, 0); } else { sanei_thread_kill (this->reader_pid); sanei_thread_waitpid(this->reader_pid, &info); } DBG(1, "hp_handle_stopScan: child %s = %d\n", WIFEXITED(info) ? "exited, status" : "signalled, signal", WIFEXITED(info) ? WEXITSTATUS(info) : WTERMSIG(info)); close(this->pipe_read_fd); this->reader_pid = 0; if ( !FAILED( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name)) ) { if (WIFSIGNALED(info)) { /* sanei_hp_scl_set(scsi, SCL_CLEAR_ERRORS, 0); sanei_hp_scl_errcheck(scsi); */ sanei_hp_scl_reset(scsi); } sanei_hp_scsi_destroy(scsi,0); } } else { DBG(3, "hp_handle_stopScan: no pid for child\n"); } return SANE_STATUS_GOOD; } static SANE_Status hp_handle_uploadParameters (HpHandle this, HpScsi scsi, int *scan_depth, hp_bool_t *soft_invert, hp_bool_t *out8) { SANE_Parameters * p = &this->scan_params; int data_width; enum hp_device_compat_e compat; assert(scsi); *soft_invert = 0; *out8 = 0; p->last_frame = SANE_TRUE; /* inquire resulting size of image after setting it up */ RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_PIXELS_PER_LINE, &p->pixels_per_line,0,0) ); RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_BYTES_PER_LINE, &p->bytes_per_line,0,0) ); RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_NUMBER_OF_LINES, &p->lines,0,0)); RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_DATA_WIDTH, &data_width,0,0)); switch (sanei_hp_optset_scanmode(this->dev->options, this->data)) { case HP_SCANMODE_LINEART: /* Lineart */ case HP_SCANMODE_HALFTONE: /* Halftone */ p->format = SANE_FRAME_GRAY; p->depth = 1; *scan_depth = 1; /* The OfficeJets don't seem to handle SCL_INVERSE_IMAGE, so we'll * have to invert in software. */ if ((sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_OJ_1150C)) { *soft_invert=1; } break; case HP_SCANMODE_GRAYSCALE: /* Grayscale */ p->format = SANE_FRAME_GRAY; p->depth = (data_width > 8) ? 16 : 8; *scan_depth = data_width; /* 8 bit output forced ? */ if ( *scan_depth > 8 ) { *out8 = sanei_hp_optset_output_8bit (this->dev->options, this->data); DBG(1,"hp_handle_uploadParameters: out8=%d\n", (int)*out8); if (*out8) { p->depth = 8; p->bytes_per_line /= 2; } } break; case HP_SCANMODE_COLOR: /* RGB */ p->format = SANE_FRAME_RGB; p->depth = (data_width > 24) ? 16 : 8; *scan_depth = data_width / 3; /* 8 bit output forced ? */ if ( *scan_depth > 8 ) { *out8 = sanei_hp_optset_output_8bit (this->dev->options, this->data); DBG(1,"hp_handle_uploadParameters: out8=%d\n", (int)*out8); if (*out8) { p->depth = 8; p->bytes_per_line /= 2; } } /* HP PhotoSmart does not invert when depth > 8. Lets do it by software */ if ( (*scan_depth > 8) && (sanei_hp_device_probe (&compat, scsi) == SANE_STATUS_GOOD) && (compat & HP_COMPAT_PS) ) *soft_invert = 1; DBG(1, "hp_handle_uploadParameters: data width %d\n", data_width); break; default: assert(!"Aack"); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } HpHandle sanei_hp_handle_new (HpDevice dev) { HpHandle new = sanei_hp_allocz(sizeof(*new)); if (!new) return 0; if (!(new->data = sanei_hp_data_dup(dev->data))) { sanei_hp_free(new); return 0; } new->dev = dev; return new; } void sanei_hp_handle_destroy (HpHandle this) { HpScsi scsi=0; DBG(3,"sanei_hp_handle_destroy: stop scan\n"); hp_handle_stopScan(this); if (sanei_hp_scsi_new(&scsi,this->dev->sanedev.name)==SANE_STATUS_GOOD && scsi) { sanei_hp_scsi_destroy(scsi,1); } sanei_hp_data_destroy(this->data); sanei_hp_free(this); } const SANE_Option_Descriptor * sanei_hp_handle_saneoption (HpHandle this, SANE_Int optnum) { if (this->cancelled) { DBG(1, "sanei_hp_handle_saneoption: cancelled. Stop scan\n"); hp_handle_stopScan(this); } return sanei_hp_optset_saneoption(this->dev->options, this->data, optnum); } SANE_Status sanei_hp_handle_control(HpHandle this, SANE_Int optnum, SANE_Action action, void *valp, SANE_Int *info) { SANE_Status status; HpScsi scsi; hp_bool_t immediate; if (this->cancelled) { DBG(1, "sanei_hp_handle_control: cancelled. Stop scan\n"); RETURN_IF_FAIL( hp_handle_stopScan(this) ); } if (hp_handle_isScanning(this)) return SANE_STATUS_DEVICE_BUSY; RETURN_IF_FAIL( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name) ); immediate = sanei_hp_optset_isImmediate(this->dev->options, optnum); status = sanei_hp_optset_control(this->dev->options, this->data, optnum, action, valp, info, scsi, immediate); sanei_hp_scsi_destroy ( scsi,0 ); return status; } SANE_Status sanei_hp_handle_getParameters (HpHandle this, SANE_Parameters *params) { SANE_Status status; if (!params) return SANE_STATUS_GOOD; if (this->cancelled) { DBG(1, "sanei_hp_handle_getParameters: cancelled. Stop scan\n"); RETURN_IF_FAIL( hp_handle_stopScan(this) ); } if (hp_handle_isScanning(this)) { *params = this->scan_params; return SANE_STATUS_GOOD; } status = sanei_hp_optset_guessParameters(this->dev->options, this->data, params); #ifdef INQUIRE_AFTER_SCAN /* Photosmart: this gives the correct number of lines when doing an update of the SANE parameters right after a preview */ if (!strcmp("C5100A", this->dev->sanedev.model)) { HpScsi scsi; SANE_Parameters * p = &this->scan_params; if (!FAILED( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name) )) { RETURN_IF_FAIL( sanei_hp_scl_inquire(scsi, SCL_NUMBER_OF_LINES, &p->lines,0,0)); sanei_hp_scsi_destroy(scsi,0); *params = this->scan_params; } } #endif return status; } SANE_Status sanei_hp_handle_startScan (HpHandle this) { SANE_Status status; HpScsi scsi; HpScl scl; HpProcessData *procdata = &(this->procdata); int adfscan; /* FIXME: setup preview mode stuff? */ if (hp_handle_isScanning(this)) { DBG(3,"sanei_hp_handle_startScan: Stop current scan\n"); RETURN_IF_FAIL( hp_handle_stopScan(this) ); } RETURN_IF_FAIL( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name) ); status = sanei_hp_optset_download(this->dev->options, this->data, scsi); if (!FAILED(status)) status = hp_handle_uploadParameters(this, scsi, &(procdata->bits_per_channel), &(procdata->invert), &(procdata->out8)); if (FAILED(status)) { sanei_hp_scsi_destroy(scsi,0); return status; } procdata->mirror_vertical = sanei_hp_optset_mirror_vert (this->dev->options, this->data, scsi); DBG(1, "start: %s to mirror image vertically\n", procdata->mirror_vertical ? "Request" : "No request" ); scl = sanei_hp_optset_scan_type (this->dev->options, this->data); adfscan = (scl == SCL_ADF_SCAN); /* For ADF scan we should check if there is paper available */ if ( adfscan ) {int adfstat = 0; int can_check_paper = 0; int is_flatbed = 0; int minval, maxval; /* For ADF-support, we have three different types of scanners: * ScanJet, ScanJet+, IIp, 3p: * scroll feed, no support for inquire paper in ADF, unload document * and preload document * IIc, IIcx, 3c, 4c, 6100C, 4p: * flatbed, no support for preload document * 5100C, 5200C, 6200C, 6300C: * scroll feed. * For all scroll feed types, we use the usual scan window command. * For flatbed types, use a sequence of special commands. */ /* Check the IIp group */ if ( (sanei_hp_device_support_get (this->dev->sanedev.name, SCL_UNLOAD, &minval, &maxval) != SANE_STATUS_GOOD ) && (sanei_hp_device_support_get (this->dev->sanedev.name, SCL_CHANGE_DOC, &minval, &maxval) != SANE_STATUS_GOOD ) ) { DBG(3, "start: Request for ADF scan without support of unload doc\n"); DBG(3, " and change doc. Seems to be something like a IIp.\n"); DBG(3, " Use standard scan window command.\n"); scl = SCL_START_SCAN; can_check_paper = 0; is_flatbed = 0; } /* else if ( sanei_hp_device_support_get (this->dev->sanedev.name, SCL_PRELOAD_ADF, &minval, &maxval) != SANE_STATUS_GOOD ) */ else if ( sanei_hp_is_flatbed_adf (scsi) ) { DBG(3, "start: Request for ADF scan without support of preload doc.\n"); DBG(3, " Seems to be a flatbed ADF.\n"); DBG(3, " Use ADF scan window command.\n"); can_check_paper = 1; is_flatbed = 1; } else { DBG(3, "start: Request for ADF scan with support of preload doc.\n"); DBG(3, " Seems to be a scroll feed ADF.\n"); DBG(3, " Use standard scan window command.\n"); scl = SCL_START_SCAN; can_check_paper = 1; is_flatbed = 0; } /* Check if the ADF is ready */ if ( sanei_hp_scl_inquire(scsi, SCL_ADF_READY, &adfstat, 0, 0) != SANE_STATUS_GOOD ) { DBG(1, "start: Error checking if ADF is ready\n"); sanei_hp_scsi_destroy(scsi,0); return SANE_STATUS_UNSUPPORTED; } if ( adfstat != 1 ) { DBG(1, "start: ADF is not ready. Finished.\n"); sanei_hp_scsi_destroy(scsi,0); return SANE_STATUS_NO_DOCS; } /* Check paper in ADF */ if ( can_check_paper ) { if ( sanei_hp_scl_inquire(scsi, SCL_ADF_BIN, &adfstat, 0, 0) != SANE_STATUS_GOOD ) { DBG(1, "start: Error checking if paper in ADF\n"); sanei_hp_scsi_destroy(scsi,0); return SANE_STATUS_UNSUPPORTED; } if ( adfstat != 1 ) { DBG(1, "start: No paper in ADF bin. Finished.\n"); sanei_hp_scsi_destroy(scsi,0); return SANE_STATUS_NO_DOCS; } if ( is_flatbed ) { if ( sanei_hp_scl_set(scsi, SCL_CHANGE_DOC, 0) != SANE_STATUS_GOOD ) { DBG(1, "start: Error changing document\n"); sanei_hp_scsi_destroy(scsi,0); return SANE_STATUS_UNSUPPORTED; } } } } DBG(1, "start: %s to mirror image vertically\n", procdata->mirror_vertical ? "Request" : "No request" ); this->bytes_left = ( this->scan_params.bytes_per_line * this->scan_params.lines ); DBG(1, "start: %d pixels per line, %d bytes per line, %d lines high\n", this->scan_params.pixels_per_line, this->scan_params.bytes_per_line, this->scan_params.lines); procdata->bytes_per_line = (int)this->scan_params.bytes_per_line; if (procdata->out8) { procdata->bytes_per_line *= 2; DBG(1,"(scanner will send %d bytes per line, 8 bit output forced)\n", procdata->bytes_per_line); } procdata->lines = this->scan_params.lines; /* Wait for front-panel button push ? */ status = sanei_hp_optset_start_wait(this->dev->options, this->data); if (status) /* Wait for front button push ? Start scan in reader process */ { procdata->startscan = scl; status = SANE_STATUS_GOOD; } else { procdata->startscan = 0; status = sanei_hp_scl_startScan(scsi, scl); } if (!FAILED( status )) { status = hp_handle_startReader(this, scsi); } /* Close SCSI-connection in forked environment */ if (this->child_forked) sanei_hp_scsi_destroy(scsi,0); return status; } SANE_Status sanei_hp_handle_read (HpHandle this, void * buf, size_t *lengthp) { ssize_t nread; SANE_Status status; DBG(3, "sanei_hp_handle_read: trying to read %lu bytes\n", (unsigned long) *lengthp); if (!hp_handle_isScanning(this)) { DBG(1, "sanei_hp_handle_read: not scanning\n"); return SANE_STATUS_INVAL; } if (this->cancelled) { DBG(1, "sanei_hp_handle_read: cancelled. Stop scan\n"); RETURN_IF_FAIL( hp_handle_stopScan(this) ); return SANE_STATUS_CANCELLED; } if (*lengthp == 0) return SANE_STATUS_GOOD; if (*lengthp > this->bytes_left) *lengthp = this->bytes_left; if ((nread = read(this->pipe_read_fd, buf, *lengthp)) < 0) { *lengthp = 0; if (errno == EAGAIN) return SANE_STATUS_GOOD; DBG(1, "sanei_hp_handle_read: read from pipe: %s. Stop scan\n", strerror(errno)); hp_handle_stopScan(this); return SANE_STATUS_IO_ERROR; } this->bytes_left -= (*lengthp = nread); if (nread > 0) { DBG(3, "sanei_hp_handle_read: read %lu bytes\n", (unsigned long) nread); return SANE_STATUS_GOOD; } DBG(1, "sanei_hp_handle_read: EOF from pipe. Stop scan\n"); status = this->bytes_left ? SANE_STATUS_IO_ERROR : SANE_STATUS_EOF; RETURN_IF_FAIL( hp_handle_stopScan(this) ); /* Switch off lamp and check unload after scan */ if (status == SANE_STATUS_EOF) { const HpDeviceInfo *hpinfo; HpScsi scsi; if ( sanei_hp_scsi_new(&scsi, this->dev->sanedev.name) == SANE_STATUS_GOOD ) { hpinfo = sanei_hp_device_info_get ( this->dev->sanedev.name ); if ( hpinfo ) { if ( hpinfo->unload_after_scan ) sanei_hp_scl_set(scsi, SCL_UNLOAD, 0); } sanei_hp_scsi_destroy(scsi,0); } } return status; } void sanei_hp_handle_cancel (HpHandle this) { this->cancelled = 1; /* The OfficeJet K series may not deliver enough data. */ /* Therefore the read might not return until it is interrupted. */ DBG(3,"sanei_hp_handle_cancel: compat flags: 0x%04x\n", (int)this->dev->compat); if ( (this->reader_pid) && (this->dev->compat & HP_COMPAT_OJ_1150C) ) { DBG(3,"sanei_hp_handle_cancel: send SIGTERM to child (%ld)\n", (long) this->reader_pid); if (this->child_forked) kill(this->reader_pid, SIGTERM); else sanei_thread_kill(this->reader_pid); } } SANE_Status sanei_hp_handle_setNonblocking (HpHandle this, hp_bool_t non_blocking) { if (!hp_handle_isScanning(this)) return SANE_STATUS_INVAL; if (this->cancelled) { DBG(3,"sanei_hp_handle_setNonblocking: cancelled. Stop scan\n"); RETURN_IF_FAIL( hp_handle_stopScan(this) ); return SANE_STATUS_CANCELLED; } if (fcntl(this->pipe_read_fd, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } SANE_Status sanei_hp_handle_getPipefd (HpHandle this, SANE_Int *fd) { if (! hp_handle_isScanning(this)) return SANE_STATUS_INVAL; if (this->cancelled) { DBG(3,"sanei_hp_handle_getPipefd: cancelled. Stop scan\n"); RETURN_IF_FAIL( hp_handle_stopScan(this) ); return SANE_STATUS_CANCELLED; } *fd = this->pipe_read_fd; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/rts88xx_lib.c0000664000175000017500000005573413106201017015160 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007-2012 stef.dev@free.fr This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* this file contains functions common to rts88xx ASICs */ #undef BACKEND_NAME #define BACKEND_NAME rts88xx_lib #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "rts88xx_lib.h" #include #include #include #include "../include/_stdint.h" #define RTS88XX_LIB_BUILD 30 /* init rts88xx library */ void sanei_rts88xx_lib_init (void) { DBG_INIT (); DBG (DBG_info, "RTS88XX library, version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, RTS88XX_LIB_BUILD); } /* * registers helpers to avoid direct access */ SANE_Bool sanei_rts88xx_is_color (SANE_Byte * regs) { if ((regs[0x2f] & 0x11) == 0x11) return SANE_TRUE; return SANE_FALSE; } void sanei_rts88xx_set_gray_scan (SANE_Byte * regs) { regs[0x2f] = (regs[0x2f] & 0x0f) | 0x20; } void sanei_rts88xx_set_color_scan (SANE_Byte * regs) { regs[0x2f] = (regs[0x2f] & 0x0f) | 0x10; } void sanei_rts88xx_set_offset (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, SANE_Byte blue) { /* offset for odd pixels */ regs[0x02] = red; regs[0x03] = green; regs[0x04] = blue; /* offset for even pixels */ regs[0x05] = red; regs[0x06] = green; regs[0x07] = blue; } void sanei_rts88xx_set_gain (SANE_Byte * regs, SANE_Byte red, SANE_Byte green, SANE_Byte blue) { regs[0x08] = red; regs[0x09] = green; regs[0x0a] = blue; } void sanei_rts88xx_set_scan_frequency (SANE_Byte * regs, int frequency) { regs[0x64] = (regs[0x64] & 0xf0) | (frequency & 0x0f); } /* * read one register at given index */ SANE_Status sanei_rts88xx_read_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg) { SANE_Status status = SANE_STATUS_GOOD; unsigned char cmd[] = { 0x80, 0x00, 0x00, 0x01 }; size_t size; cmd[1] = index; size = 4; status = sanei_usb_write_bulk (devnum, cmd, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_read_reg: bulk write failed\n"); return status; } size = 1; status = sanei_usb_read_bulk (devnum, reg, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_read_reg: bulk read failed\n"); return status; } DBG (DBG_io2, "sanei_rts88xx_read_reg: reg[0x%02x]=0x%02x\n", index, *reg); return status; } /* * write one register at given index */ SANE_Status sanei_rts88xx_write_reg (SANE_Int devnum, SANE_Int index, SANE_Byte * reg) { SANE_Status status = SANE_STATUS_GOOD; unsigned char cmd[] = { 0x88, 0x00, 0x00, 0x01, 0xff }; size_t size; cmd[1] = index; cmd[4] = *reg; size = 5; status = sanei_usb_write_bulk (devnum, cmd, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_write_reg: bulk write failed\n"); return status; } DBG (DBG_io2, "sanei_rts88xx_write_reg: reg[0x%02x]=0x%02x\n", index, *reg); return status; } /* * write length consecutive registers, starting at index * register 0xb3 is never wrote in bulk register write, so we split * write if it belongs to the register set sent */ SANE_Status sanei_rts88xx_write_regs (SANE_Int devnum, SANE_Int start, SANE_Byte * source, SANE_Int length) { size_t size = 0; size_t i; SANE_Byte buffer[260]; char message[256 * 5]; if (DBG_LEVEL > DBG_io) { for (i = 0; i < (size_t) length; i++) { sprintf (message + 5 * i, "0x%02x ", source[i]); } DBG (DBG_io, "sanei_rts88xx_write_regs : write_regs(0x%02x,%d)=%s\n", start, length, message); } /* when writing several registers at a time, we avoid writing the 0xb3 register * which is used to control the status of the scanner */ if ((start + length > 0xb3) && (length > 1)) { size = 0xb3 - start; buffer[0] = 0x88; buffer[1] = start; buffer[2] = 0x00; buffer[3] = size; for (i = 0; i < size; i++) buffer[i + 4] = source[i]; /* the USB block is size + 4 bytes of header long */ size += 4; if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_write_regs : write registers part 1 failed ...\n"); return SANE_STATUS_IO_ERROR; } /* skip 0xb3 register */ size -= 3; start = 0xb4; source = source + size; } size = length - size; buffer[0] = 0x88; buffer[1] = start; buffer[2] = 0x00; buffer[3] = size; for (i = 0; i < size; i++) buffer[i + 4] = source[i]; /* the USB block is size + 4 bytes of header long */ size += 4; if (sanei_usb_write_bulk (devnum, buffer, &size) != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_write_regs : write registers part 2 failed ...\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* read several registers starting at the given index */ SANE_Status sanei_rts88xx_read_regs (SANE_Int devnum, SANE_Int start, SANE_Byte * dest, SANE_Int length) { SANE_Status status; static SANE_Byte command_block[] = { 0x80, 0, 0x00, 0xFF }; size_t size, i; char message[256 * 5]; if (start + length > 255) { DBG (DBG_error, "sanei_rts88xx_read_regs: start and length must be within [0..255]\n"); return SANE_STATUS_INVAL; } /* write header */ size = 4; command_block[1] = start; command_block[3] = length; status = sanei_usb_write_bulk (devnum, command_block, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_read_regs: failed to write header\n"); return status; } /* read data */ size = length; status = sanei_usb_read_bulk (devnum, dest, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_read_regs: failed to read data\n"); return status; } if (size != (size_t) length) { DBG (DBG_warn, "sanei_rts88xx_read_regs: read got only %lu bytes\n", (u_long) size); } if (DBG_LEVEL >= DBG_io) { for (i = 0; i < size; i++) sprintf (message + 5 * i, "0x%02x ", dest[i]); DBG (DBG_io, "sanei_rts88xx_read_regs: read_regs(0x%02x,%d)=%s\n", start, length, message); } return status; } /* * get status by reading registers 0x10 and 0x11 */ SANE_Status sanei_rts88xx_get_status (SANE_Int devnum, SANE_Byte * regs) { SANE_Status status; status = sanei_rts88xx_read_regs (devnum, 0x10, regs + 0x10, 2); DBG (DBG_io, "sanei_rts88xx_get_status: get_status()=0x%02x 0x%02x\n", regs[0x10], regs[0x11]); return status; } /* * set status by writing registers 0x10 and 0x11 */ SANE_Status sanei_rts88xx_set_status (SANE_Int devnum, SANE_Byte * regs, SANE_Byte reg10, SANE_Byte reg11) { SANE_Status status; regs[0x10] = reg10; regs[0x11] = reg11; status = sanei_rts88xx_write_regs (devnum, 0x10, regs + 0x10, 2); DBG (DBG_io, "sanei_rts88xx_set_status: 0x%02x 0x%02x\n", regs[0x10], regs[0x11]); return status; } /* * get lamp status by reading registers 0x84 to 0x8f, only 0x8F is currently usefull * 0x84 and following could "on" timers */ SANE_Status sanei_rts88xx_get_lamp_status (SANE_Int devnum, SANE_Byte * regs) { SANE_Status status; status = sanei_rts88xx_read_regs (devnum, 0x84, regs + 0x84, 11); return status; } /* resets lamp */ SANE_Status sanei_rts88xx_reset_lamp (SANE_Int devnum, SANE_Byte * regs) { SANE_Status status; SANE_Byte reg; /* read the 0xda register, then clear lower nibble and write it back */ status = sanei_rts88xx_read_reg (devnum, 0xda, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to read 0xda register\n"); return status; } reg = 0xa0; status = sanei_rts88xx_write_reg (devnum, 0xda, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to write 0xda register\n"); return status; } /* on cleared, get status */ status = sanei_rts88xx_get_status (devnum, regs); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to get status\n"); return status; } DBG (DBG_io, "sanei_rts88xx_reset_lamp: status=0x%02x 0x%02x\n", regs[0x10], regs[0x11]); /* set low nibble to 7 and write it */ reg = reg | 0x07; status = sanei_rts88xx_write_reg (devnum, 0xda, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to write 0xda register\n"); return status; } status = sanei_rts88xx_read_reg (devnum, 0xda, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_reset_lamp: failed to read 0xda register\n"); return status; } if (reg != 0xa7) { DBG (DBG_warn, "sanei_rts88xx_reset_lamp: expected reg[0xda]=0xa7, got 0x%02x\n", reg); } /* store read value in shadow register */ regs[0xda] = reg; return status; } /* * get lcd status by reading registers 0x20, 0x21 and 0x22 */ SANE_Status sanei_rts88xx_get_lcd (SANE_Int devnum, SANE_Byte * regs) { SANE_Status status; status = sanei_rts88xx_read_regs (devnum, 0x20, regs + 0x20, 3); DBG (DBG_io, "sanei_rts88xx_get_lcd: 0x%02x 0x%02x 0x%02x\n", regs[0x20], regs[0x21], regs[0x22]); return status; } /* * write to special control register CONTROL_REG=0xb3 */ SANE_Status sanei_rts88xx_write_control (SANE_Int devnum, SANE_Byte value) { SANE_Status status; status = sanei_rts88xx_write_reg (devnum, CONTROL_REG, &value); return status; } /* * send the cancel control sequence */ SANE_Status sanei_rts88xx_cancel (SANE_Int devnum) { SANE_Status status; status = sanei_rts88xx_write_control (devnum, 0x02); if (status != SANE_STATUS_GOOD) return status; status = sanei_rts88xx_write_control (devnum, 0x02); if (status != SANE_STATUS_GOOD) return status; status = sanei_rts88xx_write_control (devnum, 0x00); if (status != SANE_STATUS_GOOD) return status; status = sanei_rts88xx_write_control (devnum, 0x00); return status; } /* * write the given number of bytes pointed by value into memory * length is payload length * extra is number of bytes to add to the usb write length */ SANE_Status sanei_rts88xx_write_mem (SANE_Int devnum, SANE_Int length, SANE_Int extra, SANE_Byte * value) { SANE_Status status; SANE_Byte *buffer; size_t i, size; char message[(0xFFC0 + 10) * 3] = ""; buffer = (SANE_Byte *) malloc (length + 10); if (buffer == NULL) return SANE_STATUS_NO_MEM; memset (buffer, 0, length + 10); buffer[0] = 0x89; buffer[1] = 0x00; buffer[2] = HIBYTE (length); buffer[3] = LOBYTE (length); for (i = 0; i < (size_t) length; i++) { buffer[i + 4] = value[i]; if (DBG_LEVEL > DBG_io2) { sprintf (message + 3 * i, "%02x ", buffer[i + 4]); } } DBG (DBG_io, "sanei_rts88xx_write_mem: %02x %02x %02x %02x -> %s\n", buffer[0], buffer[1], buffer[2], buffer[3], message); size = length + 4 + extra; status = sanei_usb_write_bulk (devnum, buffer, &size); free (buffer); if ((status == SANE_STATUS_GOOD) && (size != (size_t) length + 4 + extra)) { DBG (DBG_error, "sanei_rts88xx_write_mem: only wrote %lu bytes out of %d\n", (u_long) size, length + 4); status = SANE_STATUS_IO_ERROR; } return status; } /* * set memory with the given data */ SANE_Status sanei_rts88xx_set_mem (SANE_Int devnum, SANE_Byte ctrl1, SANE_Byte ctrl2, SANE_Int length, SANE_Byte * value) { SANE_Status status; SANE_Byte regs[2]; regs[0] = ctrl1; regs[1] = ctrl2; status = sanei_rts88xx_write_regs (devnum, 0x91, regs, 2); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_set_mem: failed to write 0x91/0x92 registers\n"); return status; } status = sanei_rts88xx_write_mem (devnum, length, 0, value); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_set_mem: failed to write memory\n"); } return status; } /* * read length bytes of memory into area pointed by value */ SANE_Status sanei_rts88xx_read_mem (SANE_Int devnum, SANE_Int length, SANE_Byte * value) { SANE_Status status; size_t size, read, want; SANE_Byte header[4]; /* build and write length header */ header[0] = 0x81; header[1] = 0x00; header[2] = HIBYTE (length); header[3] = LOBYTE (length); size = 4; status = sanei_usb_write_bulk (devnum, header, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_read_mem: failed to write length header\n"); return status; } DBG (DBG_io, "sanei_rts88xx_read_mem: %02x %02x %02x %02x -> ...\n", header[0], header[1], header[2], header[3]); read = 0; while (length > 0) { if (length > 2048) want = 2048; else want = length; size = want; status = sanei_usb_read_bulk (devnum, value + read, &size); if (size != want) { DBG (DBG_error, "sanei_rts88xx_read_mem: only read %lu bytes out of %lu\n", (u_long) size, (u_long) want); status = SANE_STATUS_IO_ERROR; } length -= size; read += size; } return status; } /* * set memory with the given data */ SANE_Status sanei_rts88xx_get_mem (SANE_Int devnum, SANE_Byte ctrl1, SANE_Byte ctrl2, SANE_Int length, SANE_Byte * value) { SANE_Status status; SANE_Byte regs[2]; regs[0] = ctrl1; regs[1] = ctrl2; status = sanei_rts88xx_write_regs (devnum, 0x91, regs, 2); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_get_mem: failed to write 0x91/0x92 registers\n"); return status; } status = sanei_rts88xx_read_mem (devnum, length, value); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_get_mem: failed to read memory\n"); } return status; } /* * write to the nvram controler */ SANE_Status sanei_rts88xx_nvram_ctrl (SANE_Int devnum, SANE_Int length, SANE_Byte * value) { SANE_Status status; SANE_Int i; char message[60 * 5]; #ifdef HAZARDOUS_EXPERIMENT SANE_Int size = 0; SANE_Byte buffer[60]; #endif if (DBG_LEVEL > DBG_io) { for (i = 0; i < length; i++) { sprintf (message + 5 * i, "0x%02x ", value[i]); } DBG (DBG_io, "sanei_rts88xx_nvram_ctrl : devnum=%d, nvram_ctrl(0x00,%d)=%s\n", devnum, length, message); } #ifdef HAZARDOUS_EXPERIMENT buffer[0] = 0x8a; buffer[1] = 0x00; buffer[2] = 0x00; buffer[3] = length; for (i = 0; i < size; i++) buffer[i + 4] = value[i]; /* the USB block is size + 4 bytes of header long */ size = length + 4; status = sanei_usb_write_bulk (devnum, buffer, &size); #else status = SANE_STATUS_GOOD; #endif if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_nvram_ctrl : write failed ...\n"); } return status; } /* * setup nvram */ SANE_Status sanei_rts88xx_setup_nvram (SANE_Int devnum, SANE_Int length, SANE_Byte * value) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte local[2], reg; int i; status = sanei_rts88xx_nvram_ctrl (devnum, length, value); #ifndef HAZARDOUS_EXPERIMENT return SANE_STATUS_GOOD; #endif if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : failed step #1 ...\n"); return status; } local[0] = 0x18; local[1] = 0x08; for (i = 0; i < 8; i++) { status = sanei_rts88xx_nvram_ctrl (devnum, 2, local); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : failed loop #%d ...\n", i); return status; } status = sanei_rts88xx_read_reg (devnum, 0x10, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : register reading failed loop #%d ...\n", i); return status; } DBG (DBG_io, "sanei_rts88xx_setup_nvram: reg[0x10]=0x%02x\n", reg); } reg = 0; status = sanei_rts88xx_write_reg (devnum, CONTROLER_REG, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : controller register write failed\n"); return status; } reg = 1; status = sanei_rts88xx_write_reg (devnum, CONTROLER_REG, ®); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_setup_nvram : controller register write failed\n"); return status; } return status; } /* * Sets scan area, no checks are being done, so watch your steps */ void sanei_rts88xx_set_scan_area (SANE_Byte * regs, SANE_Int ystart, SANE_Int yend, SANE_Int xstart, SANE_Int xend) { /* vertical lines to move before scan */ regs[START_LINE] = LOBYTE (ystart); regs[START_LINE + 1] = HIBYTE (ystart); /* total number of line to move */ regs[END_LINE] = LOBYTE (yend); regs[END_LINE + 1] = HIBYTE (yend); /* set horizontal start position */ regs[START_PIXEL] = LOBYTE (xstart); regs[START_PIXEL + 1] = HIBYTE (xstart); /* set horizontal end position */ regs[END_PIXEL] = LOBYTE (xend); regs[END_PIXEL + 1] = HIBYTE (xend); } /** * read available data count from scanner * from tests it appears that advertised data * may not be really available, and that a pause must be made * before reading data so that it is really there. * Such as reading data twice. */ SANE_Status sanei_rts88xx_data_count (SANE_Int devnum, SANE_Word * count) { SANE_Status status; size_t size; static SANE_Byte header[4] = { 0x90, 0x00, 0x00, 3 }; SANE_Byte result[3]; /* set count in case of failure */ *count = 0; size = 4; status = sanei_usb_write_bulk (devnum, header, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_data_count : failed to write header\n"); return status; } size = 3; status = sanei_usb_read_bulk (devnum, result, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_data_count : failed to read data count\n"); return status; } *count = result[0] + (result[1] << 8) + (result[2] << 16); DBG (DBG_io2, "sanei_rts88xx_data_count: %d bytes available (0x%06x)\n", *count, *count); return status; } /** * Waits for data being available while optionally polling motor. There is a timeout * to prevent scanner waiting forever non coming data. */ SANE_Status sanei_rts88xx_wait_data (SANE_Int devnum, SANE_Bool busy, SANE_Word * count) { SANE_Status status; SANE_Byte control; /* poll the available byte count until not 0 */ while (SANE_TRUE) { status = sanei_rts88xx_data_count (devnum, count); if (*count != 0) { DBG (DBG_io, "sanei_rts88xx_wait_data: %d bytes available\n", *count); return status; } /* check that the scanner is busy scanning */ if (busy) { sanei_rts88xx_read_reg (devnum, CONTROL_REG, &control); if ((control & 0x08) == 0 && (*count == 0)) { DBG (DBG_error, "sanei_rts88xx_wait_data: scanner stopped being busy before data are available\n"); return SANE_STATUS_IO_ERROR; } } } /* we hit timeout */ return SANE_STATUS_IO_ERROR; } /* * read scanned data from scanner up to the size given. The actual length read is returned. */ SANE_Status sanei_rts88xx_read_data (SANE_Int devnum, SANE_Word * length, unsigned char *dest) { SANE_Status status = SANE_STATUS_GOOD; SANE_Byte header[4]; size_t size, len, remain, read; /* do not read too much data */ if (*length > RTS88XX_MAX_XFER_SIZE) len = RTS88XX_MAX_XFER_SIZE; else len = *length; /* write command header first */ header[0] = 0x91; header[1] = 0x00; header[2] = HIBYTE (len); header[3] = LOBYTE (len); size = 4; status = sanei_usb_write_bulk (devnum, header, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_read_data: failed to write header\n"); } read = 0; /* first read blocks aligned on 64 bytes boundary */ while (len - read > 64) { size = (len - read) & 0xFFC0; status = sanei_usb_read_bulk (devnum, dest + read, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_read_data: failed to read data\n"); return status; } DBG (DBG_io2, "sanei_rts88xx_read_data: read %lu bytes\n", (u_long) size); read += size; } /* then read remainder */ remain = len - read; if (remain > 0) { status = sanei_usb_read_bulk (devnum, dest + read, &remain); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sanei_rts88xx_read_data: failed to read data\n"); return status; } DBG (DBG_io2, "sanei_rts88xx_read_data: read %lu bytes\n", (u_long) remain); read += remain; } /* update actual read length */ DBG (DBG_io, "sanei_rts88xx_read_data: read %lu bytes, %d required\n", (u_long) read, *length); *length = read; return status; } sane-backends-1.0.27/backend/plustek-pp_p12.c0000664000175000017500000006162312775277260015572 00000000000000/* @file plustek-pp_p12.c * @brief p12 and pt12 specific stuff * * based on sources acquired from Plustek Inc. * Copyright (C) 2000 Plustek Inc. * Copyright (C) 2001-2013 Gerhard Jaeger * * History: * - 0.38 - initial version * - 0.39 - added Genius Colorpage Vivid III V2 stuff * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - removed setting of ps->sCaps.dwFlag in p12InitiateComponentModel() * - 0.43 - no changes * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** some local vars *********************************/ static RegDef p12CcdStop[] = { {0x41, 0xff}, {0x42, 0xff}, {0x60, 0xff}, {0x61, 0xff}, {0x4b, 0xff}, {0x4c, 0xff}, {0x4d, 0xff}, {0x4e, 0xff}, {0x2a, 0x01}, {0x2b, 0x00}, {0x2d, 0x00}, {0x1b, 0x19}, {0x15, 0x00} }; /*************************** local functions *********************************/ /** init the stuff according to the buttons */ static void p12ButtonSetup( pScanData ps, Byte nrOfButtons ) { ps->Device.buttons = nrOfButtons; ps->Device.Model1Mono &= ~_BUTTON_MODE; ps->Device.Model1Color &= ~_BUTTON_MODE; ps->AsicReg.RD_MotorDriverType |= _BUTTON_DISABLE; ps->Scan.motorPower |= _BUTTON_DISABLE; } /** According to what we have detected, set the other stuff */ static void p12InitiateComponentModel( pScanData ps ) { /* preset some stuff and do the differences later */ ps->Device.buttons = 0; ps->Device.Model1Mono = _BUTTON_MODE + _CCD_SHIFT_GATE + _SCAN_GRAYTYPE; ps->Device.Model1Color = _BUTTON_MODE + _CCD_SHIFT_GATE; ps->Device.dwModelOriginY = 64; ps->Device.fTpa = _FALSE; ps->Device.ModelCtrl = (_LED_ACTIVITY | _LED_CONTROL); /* ps->sCaps.dwFlag should have been set correctly in models.c */ switch( ps->Device.bPCBID ) { case _PLUSTEK_SCANNER: DBG( DBG_LOW, "We have a Plustek Scanner\n" ); ps->sCaps.Model = MODEL_OP_P12; break; case _SCANNER_WITH_TPA: DBG( DBG_LOW, "Scanner has TPA\n" ); ps->Device.fTpa = _TRUE; ps->sCaps.dwFlag |= SFLAG_TPA; break; case _SCANNER4Button: DBG( DBG_LOW, "Scanner has 4 Buttons\n" ); p12ButtonSetup( ps, 4 ); break; case _SCANNER4ButtonTPA: DBG( DBG_LOW, "Scanner has 4 Buttons & TPA\n" ); ps->Device.fTpa = _TRUE; ps->sCaps.dwFlag |= SFLAG_TPA; p12ButtonSetup( ps, 4 ); break; case _SCANNER5Button: DBG( DBG_LOW, "Scanner has 5 Buttons\n" ); ps->Device.dwModelOriginY = 64 + 20; p12ButtonSetup( ps, 5 ); break; case _SCANNER5ButtonTPA: DBG( DBG_LOW, "Scanner has 5 Buttons & TPA\n" ); ps->Device.dwModelOriginY = 64 + 20; ps->Device.fTpa = _TRUE; ps->sCaps.dwFlag |= SFLAG_TPA; p12ButtonSetup( ps, 5 ); break; case _SCANNER1Button: DBG( DBG_LOW, "Scanner has 1 Button\n" ); p12ButtonSetup( ps, 1 ); break; case _SCANNER1ButtonTPA: DBG( DBG_LOW, "Scanner has 1 Button & TPA\n" ); ps-> Device.fTpa = _TRUE; ps->sCaps.dwFlag |= SFLAG_TPA; p12ButtonSetup( ps, 1 ); break; case _AGFA_SCANNER: DBG( DBG_LOW, "Agfa Scanner\n" ); ps->Device.dwModelOriginY = 24; /* 1200 dpi */ break; case _SCANNER2Button: DBG( DBG_LOW, "Scanner has 2 Buttons\n" ); DBG( DBG_LOW, "Seems we have a Genius Colorpage Vivid III V2\n" ); ps->Device.dwModelOriginY = 64 - 33; p12ButtonSetup( ps, 2 ); ps->sCaps.Model = MODEL_GEN_CPV2; break; default: DBG( DBG_LOW, "Default Model: P12\n" ); ps->sCaps.Model = MODEL_OP_P12; break; } if( _MOTOR0_2003 == ps->Device.bMotorID ) { ps->Device.f2003 = _TRUE; ps->Device.XStepMono = 10; ps->Device.XStepColor = 6; ps->Device.XStepBack = 5; ps->AsicReg.RD_MotorDriverType |= _MOTORR_STRONG; } else { ps->Device.f2003 = _FALSE; ps->Device.XStepMono = 8; ps->Device.XStepColor = 4; ps->Device.XStepBack = 5; ps->AsicReg.RD_MotorDriverType |= _MOTORR_WEAK; } } /*............................................................................. * prepare all the necessary variables - */ static void p12SetupScannerVariables( pScanData ps ) { DBG( DBG_LOW, "p12SetupScannerVariables()\n" ); /* * these values were originally altered by registry entries (NT-driver) * and used to adjust the picture position... */ ps->Device.lUpNormal = 0; ps->Device.lUpNegative = 20; ps->Device.lUpPositive = -30; ps->Device.lLeftNormal = 51; ps->OpenScanPath( ps ); ps->ReInitAsic( ps, _FALSE ); ps->CloseScanPath( ps ); } /*............................................................................. * */ static void p12SetupScanningCondition( pScanData ps ) { TimerDef timer; ULong channel; Byte bState; pUChar pState = ps->Bufs.b1.pReadBuf; DBG( DBG_LOW, "p12SetupScanningCondition()\n" ); P12SetGeneralRegister( ps ); IORegisterToScanner( ps, ps->RegResetMTSC ); /* ------- Setup MinRead/MaxRead Fifo size ------- */ if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 ) { ps->Scan.dwMaxReadFifo = ps->Scan.dwMinReadFifo = ps->DataInf.dwAsicBytesPerPlane * 2; } else { ps->Scan.dwMaxReadFifo = ps->Scan.dwMinReadFifo = ps->DataInf.dwAppPixelsPerLine << 1; } if( ps->Scan.dwMinReadFifo < 1024) ps->Scan.dwMinReadFifo = ps->Scan.dwMaxReadFifo = 1024; ps->Scan.dwMaxReadFifo += (ps->DataInf.dwAsicBytesPerPlane / 2); DBG( DBG_LOW, "MinReadFifo=%u, MaxReadFifo=%u\n", ps->Scan.dwMinReadFifo, ps->Scan.dwMaxReadFifo ); /* ------- Set the max. read fifo to asic ------- */ if( ps->DataInf.wPhyDataType > COLOR_256GRAY ) { ps->Scan.bFifoSelect = ps->RegBFifoOffset; if( !ps->Scan.p48BitBuf.pb ) { Long lRed, lGreen; lRed = (_SIZE_REDFIFO - _SIZE_BLUEFIFO) / ps->DataInf.dwAsicBytesPerPlane - ps->Scan.bd_rk.wRedKeep; lGreen = (_SIZE_GREENFIFO - _SIZE_BLUEFIFO) / ps->DataInf.dwAsicBytesPerPlane - ps->Scan.gd_gk.wGreenKeep; if((lRed < 0) || (lGreen < 0)) { if( lRed < lGreen ) { channel = _RED_FULLSIZE << 16; ps->AsicReg.RD_BufFullSize = _SIZE_REDFIFO; lGreen = lRed; } else { channel = _GREEN_FULLSIZE << 16; ps->AsicReg.RD_BufFullSize = _SIZE_GREENFIFO; } lGreen = (ULong)(-lGreen * ps->DataInf.dwAsicBytesPerPlane); if( ps->DataInf.wPhyDataType > COLOR_TRUE24 ) lGreen >>= 1; ps->Scan.dwMinReadFifo += (ULong)lGreen; ps->Scan.dwMaxReadFifo += (ULong)lGreen; } else { channel = _BLUE_FULLSIZE << 16; ps->AsicReg.RD_BufFullSize = _SIZE_BLUEFIFO; } } else { channel = _BLUE_FULLSIZE << 16; ps->AsicReg.RD_BufFullSize = _SIZE_BLUEFIFO; } } else { ps->Scan.bFifoSelect = ps->RegGFifoOffset; channel = _GREEN_FULLSIZE << 16; ps->AsicReg.RD_BufFullSize = _SIZE_GRAYFIFO; } ps->AsicReg.RD_BufFullSize -= (ps->DataInf.dwAsicBytesPerPlane << 1); if( ps->DataInf.wPhyDataType > COLOR_TRUE24 ) ps->AsicReg.RD_BufFullSize >>= 1; ps->AsicReg.RD_BufFullSize |= channel; ps->Scan.bRefresh = (Byte)(ps->Scan.dwInterval << 1); ps->AsicReg.RD_LineControl = (_LOBYTE (ps->Shade.wExposure)); ps->AsicReg.RD_ExtLineControl = (_HIBYTE (ps->Shade.wExposure)); ps->AsicReg.RD_XStepTime = (_LOBYTE (ps->Shade.wXStep)); ps->AsicReg.RD_ExtXStepTime = (_HIBYTE (ps->Shade.wXStep)); ps->AsicReg.RD_Motor0Control = _FORWARD_MOTOR; ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; ps->AsicReg.RD_ModeControl = (_ModeScan | _ModeFifoGSel); DBG( DBG_LOW, "bRefresh = %i\n", ps->Scan.bRefresh ); if( ps->DataInf.wPhyDataType == COLOR_BW ) { ps->AsicReg.RD_ScanControl = _SCAN_BITMODE; if( !(ps->DataInf.dwScanFlag & SCANDEF_Inverse)) ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT; } else if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 ) ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; else { ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE; if(!(ps->DataInf.dwScanFlag & SCANDEF_RightAlign)) ps->AsicReg.RD_ScanControl |= _BITALIGN_LEFT; if( ps->DataInf.dwScanFlag & SCANDEF_Inverse) ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT; } ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE; IOSelectLampSource( ps ); DBG( DBG_LOW, "RD_ScanControl = 0x%02x\n", ps->AsicReg.RD_ScanControl ); ps->AsicReg.RD_MotorTotalSteps = (ULong)ps->DataInf.crImage.cy * 4 + ((ps->Device.f0_8_16) ? 32 : 16) + ((ps->Scan.bDiscardAll) ? 32 : 0); ps->AsicReg.RD_ScanControl1 = (_MTSC_ENABLE | _SCANSTOPONBUFFULL | _MFRC_RUNSCANSTATE | _MFRC_BY_XSTEP); ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x; if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA )) { ps->AsicReg.RD_Origin = (UShort)(ps->Device.lLeftNormal * 2 + ps->Device.DataOriginX + ps->DataInf.crImage.x ); } else if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) { ps->AsicReg.RD_Origin = (UShort)(ps->Scan.posBegin + ps->DataInf.crImage.x); } else { ps->AsicReg.RD_Origin = (UShort)(ps->Scan.negBegin + ps->DataInf.crImage.x); } if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) ps->AsicReg.RD_Origin >>= 1; if( ps->DataInf.wPhyDataType == COLOR_BW ) ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicBytesPerPlane; else ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAppPixelsPerLine; DBG( DBG_LOW, "RD_Origin = %u, RD_Pixels = %u\n", ps->AsicReg.RD_Origin, ps->AsicReg.RD_Pixels ); /* ------- Prepare scan states ------- */ memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); memset( ps->Bufs.b1.pReadBuf, 0, _NUMBER_OF_SCANSTEPS ); if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) bState = (_SS_MONO | _SS_STEP); else bState = (_SS_COLOR | _SS_STEP); for( channel = _NUMBER_OF_SCANSTEPS; channel; channel -= ps->Scan.dwInterval ) { *pState = bState; if( ps->Scan.dwInterlace ) pState[ ps->Scan.dwInterlace] = _SS_STEP; pState += ps->Scan.dwInterval; } for( channel = 0, pState = ps->Bufs.b1.pReadBuf; channel < _SCANSTATE_BYTES; channel++) { ps->a_nbNewAdrPointer[channel] = pState [0] | (pState [1] << 4); pState += 2; } /* ------- Wait for scan state stop ------- */ MiscStartTimer( &timer, _SECOND * 2 ); while(!(IOGetScanState( ps, _FALSE ) & _SCANSTATE_STOP) && !MiscCheckTimer(&timer)); /* CHECK: Replace by IOPutAll.... */ IODownloadScanStates( ps ); IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl); IODataToRegister( ps, ps->RegExtendedLineControl, ps->AsicReg.RD_ExtLineControl); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime); IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime); IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType); IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl); IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control); IODataToRegister( ps, ps->RegModelControl,ps->AsicReg.RD_ModelControl); IODataToRegister( ps, ps->RegDpiLow, (_LOBYTE(ps->AsicReg.RD_Dpi))); IODataToRegister( ps, ps->RegDpiHigh, (_HIBYTE(ps->AsicReg.RD_Dpi))); IODataToRegister( ps, ps->RegScanPosLow, (_LOBYTE(ps->AsicReg.RD_Origin))); IODataToRegister( ps, ps->RegScanPosHigh,(_HIBYTE(ps->AsicReg.RD_Origin))); IODataToRegister( ps, ps->RegWidthPixelsLow, (_LOBYTE(ps->AsicReg.RD_Pixels))); IODataToRegister( ps, ps->RegWidthPixelsHigh, (_HIBYTE(ps->AsicReg.RD_Pixels))); IODataToRegister( ps, ps->RegThresholdLow, (_LOBYTE(ps->AsicReg.RD_ThresholdControl))); IODataToRegister( ps, ps->RegThresholdHigh, (_HIBYTE(ps->AsicReg.RD_ThresholdControl))); IODataToRegister( ps, ps->RegMotorTotalStep0, (_LOBYTE(ps->AsicReg.RD_MotorTotalSteps))); IODataToRegister( ps, ps->RegMotorTotalStep1, (_HIBYTE(ps->AsicReg.RD_MotorTotalSteps))); IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); IORegisterToScanner( ps, ps->RegInitDataFifo); } /*............................................................................. * program the CCD relevant stuff */ static void p12ProgramCCD( pScanData ps) { UShort w; pRegDef rp; DBG( DBG_IO, "p12ProgramCCD: 0x%08lx[%lu]\n", (unsigned long)ps->Device.pCCDRegisters, ((unsigned long)ps->Device.wNumCCDRegs * ps->Shade.bIntermediate)); DBG( DBG_IO, " %u regs * %u (intermediate)\n", ps->Device.wNumCCDRegs, ps->Shade.bIntermediate ); rp = ps->Device.pCCDRegisters + (ULong)ps->Device.wNumCCDRegs * ps->Shade.bIntermediate; for( w = ps->Device.wNumCCDRegs; w--; rp++ ) { DBG( DBG_IO, "[0x%02x] = 0x%02x\n", rp->bReg, rp->bParam ); IODataToRegister( ps, rp->bReg, rp->bParam ); } } /*............................................................................. * this initializes the ASIC and prepares the different functions for shading * and scanning */ static void p12Init98003( pScanData ps, Bool shading ) { DBG( DBG_LOW, "p12InitP98003(%d)\n", shading ); /* get DAC and motor stuff */ ps->Device.bDACType = IODataFromRegister( ps, ps->RegResetConfig ); ps->Device.bMotorID = (Byte)(ps->Device.bDACType & _MOTOR0_MASK); ps->AsicReg.RD_MotorDriverType = (Byte)((ps->Device.bDACType & _MOTOR0_MASK) >> 3); ps->AsicReg.RD_MotorDriverType |= (Byte)((ps->Device.bDACType & _MOTOR1_MASK) >> 1); ps->Scan.motorPower = ps->AsicReg.RD_MotorDriverType | _MOTORR_STRONG; ps->Device.bDACType &= _ADC_MASK; /*get CCD and PCB ID */ ps->Device.bPCBID = IODataFromRegister( ps, ps->RegConfiguration ); ps->Device.bCCDID = ps->Device.bPCBID & 0x07; ps->Device.bPCBID &= 0xf0; if( _AGFA_SCANNER == ps->Device.bPCBID ) ps->Device.bDACType = _DA_WOLFSON8141; DBG( DBG_LOW, "PCB-ID=0x%02x, CCD-ID=0x%02x, DAC-TYPE=0x%02x\n", ps->Device.bPCBID, ps->Device.bCCDID, ps->Device.bDACType ); p12InitiateComponentModel( ps ); /* encode the CCD-id into the flag parameter */ ps->sCaps.dwFlag |= ((ULong)(ps->Device.bCCDID | ps->Device.bPCBID) << 16); P12InitCCDandDAC( ps, shading ); if( ps->Shade.bIntermediate & _ScanMode_Mono ) ps->AsicReg.RD_Model1Control = ps->Device.Model1Mono; else ps->AsicReg.RD_Model1Control = ps->Device.Model1Color; IODataToRegister( ps, ps->RegPllPredivider, 1 ); IODataToRegister( ps, ps->RegPllMaindivider, 0x20 ); IODataToRegister( ps, ps->RegPllPostdivider, 2 ); IODataToRegister( ps, ps->RegClockSelector, 3 ); /* 2 */ IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType ); /* this might be changed, def value is 11 */ IODataToRegister( ps, ps->RegWaitStateInsert, 11 ); IODataToRegister( ps, ps->RegModel1Control, ps->AsicReg.RD_Model1Control ); p12ProgramCCD( ps ); } /*............................................................................. * initialize the register values for the 98003 asic and preset other stuff */ static void p12InitializeAsicRegister( pScanData ps ) { memset( &ps->AsicReg, 0, sizeof(RegData)); } /*............................................................................. * as the function name says */ static void p12PutToIdleMode( pScanData ps ) { ULong i; ps->OpenScanPath( ps ); DBG( DBG_IO, "CCD-Stop\n" ); for( i = 0; i < 13; i++ ) { DBG( DBG_IO, "[0x%02x] = 0x%02x\n", p12CcdStop[i].bReg, p12CcdStop[i].bParam ); IODataToRegister( ps, p12CcdStop[i].bReg, p12CcdStop[i].bParam ); } ps->CloseScanPath( ps ); } /*............................................................................. * here we simply call the WaitForShading function which performs this topic */ static int p12Calibration( pScanData ps ) { Bool result; DBG( DBG_LOW, "p12Calibration()\n" ); /* * wait for shading to be done */ ps->OpenScanPath( ps ); _ASSERT(ps->WaitForShading); result = ps->WaitForShading( ps ); ps->CloseScanPath( ps ); if( !result ) return _E_TIMEOUT; return _OK; } /************************ exported functions *********************************/ /*............................................................................. * initialize the register values and function calls for the 98003 asic */ _LOC int P12InitAsic( pScanData ps ) { int result; DBG( DBG_LOW, "P12InitAsic()\n" ); /* * preset the asic shadow registers */ p12InitializeAsicRegister( ps ); ps->IO.bOpenCount = 0; /* * setup the register values */ ps->RegSwitchBus = 0; ps->RegEPPEnable = 1; ps->RegECPEnable = 2; ps->RegReadDataMode = 3; ps->RegWriteDataMode = 4; ps->RegInitDataFifo = 5; ps->RegForceStep = 6; ps->RegInitScanState = 7; ps->RegRefreshScanState = 8; ps->RegWaitStateInsert = 0x0a; ps->RegRFifoOffset = 0x0a; ps->RegGFifoOffset = 0x0b; ps->RegBFifoOffset = 0x0c; ps->RegBitDepth = 0x13; ps->RegStepControl = 0x14; ps->RegMotor0Control = 0x15; ps->RegXStepTime = 0x16; ps->RegGetScanState = 0x17; ps->RegAsicID = 0x18; ps->RegMemoryLow = 0x19; ps->RegMemoryHigh = 0x1a; ps->RegModeControl = 0x1b; ps->RegLineControl = 0x1c; ps->RegScanControl = 0x1d; ps->RegConfiguration = 0x1e; ps->RegModelControl = 0x1f; ps->RegModel1Control = 0x20; ps->RegDpiLow = 0x21; ps->RegDpiHigh = 0x22; ps->RegScanPosLow = 0x23; ps->RegScanPosHigh = 0x24; ps->RegWidthPixelsLow = 0x25; ps->RegWidthPixelsHigh = 0x26; ps->RegThresholdLow = 0x27; ps->RegThresholdHigh = 0x28; ps->RegThresholdGapControl = 0x29; ps->RegADCAddress = 0x2a; ps->RegADCData = 0x2b; ps->RegADCPixelOffset = 0x2c; ps->RegADCSerialOutStr = 0x2d; ps->RegResetConfig = 0x2e; ps->RegLensPosition = 0x2f; ps->RegStatus = 0x30; ps->RegScanStateControl = 0x31; ps->RegRedChDarkOffsetLow = 0x33; ps->RegRedChDarkOffsetHigh = 0x34; ps->RegGreenChDarkOffsetLow = 0x35; ps->RegGreenChDarkOffsetHigh= 0x36; ps->RegBlueChDarkOffsetLow = 0x37; ps->RegBlueChDarkOffsetHigh = 0x38; ps->RegResetPulse0 = 0x39; ps->RegResetPulse1 = 0x3a; ps->RegCCDClampTiming0 = 0x3b; ps->RegCCDClampTiming1 = 0x3c; ps->RegVSMPTiming0 = 0x41; ps->RegVSMPTiming1 = 0x42; ps->RegCCDQ1Timing0 = 0x43; ps->RegCCDQ1Timing1 = 0x44; ps->RegCCDQ1Timing2 = 0x45; ps->RegCCDQ1Timing3 = 0x46; ps->RegCCDQ2Timing0 = 0x47; ps->RegCCDQ2Timing1 = 0x48; ps->RegCCDQ2Timing2 = 0x49; ps->RegCCDQ2Timing3 = 0x4a; ps->RegADCclockTiming0 = 0x4b; ps->RegADCclockTiming1 = 0x4c; ps->RegADCclockTiming2 = 0x4d; ps->RegADCclockTiming3 = 0x4e; ps->RegADCDVTiming0 = 0x50; ps->RegADCDVTiming1 = 0x51; ps->RegADCDVTiming2 = 0x52; ps->RegADCDVTiming3 = 0x53; ps->RegFifoFullLength0 = 0x54; ps->RegFifoFullLength1 = 0x55; ps->RegFifoFullLength2 = 0x56; ps->RegMotorTotalStep0 = 0x57; ps->RegMotorTotalStep1 = 0x58; ps->RegMotorFreeRunCount0 = 0x59; ps->RegMotorFreeRunCount1 = 0x5a; ps->RegScanControl1 = 0x5b; ps->RegMotorFreeRunTrigger = 0x5c; ps->RegResetMTSC = 0x5d; ps->RegMotor1Control = 0x62; ps->RegMotor2Control = 0x63; ps->RegMotorDriverType = 0x64; ps->RegStatus2 = 0x66; ps->RegExtendedLineControl = 0x6d; ps->RegExtendedXStep = 0x6e; ps->RegPllPredivider = 0x71; ps->RegPllMaindivider = 0x72; ps->RegPllPostdivider = 0x73; ps->RegClockSelector = 0x74; ps->RegTestMode = 0xf0; /* * setup function calls */ ps->SetupScannerVariables = p12SetupScannerVariables; ps->SetupScanningCondition = p12SetupScanningCondition; ps->Calibration = p12Calibration; ps->PutToIdleMode = p12PutToIdleMode; ps->ReInitAsic = p12Init98003; ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE; ps->CtrlReadLowNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF; ps->IO.useEPPCmdMode = _FALSE; /* * initialize the other modules and set some * function pointer */ result = DacInitialize( ps ); if( _OK != result ) return result; result = ImageInitialize( ps ); if( _OK != result ) return result; result = IOFuncInitialize( ps ); if( _OK != result ) return result; result = IOInitialize( ps ); if( _OK != result ) return result; result = MotorInitialize( ps ); if( _OK != result ) return result; if( _FALSE == ps->OpenScanPath( ps )) { DBG( DBG_LOW, "P12InitAsic() failed.\n" ); return _E_NO_DEV; } /*get CCD and PCB ID */ ps->Device.bPCBID = IODataFromRegister( ps, ps->RegConfiguration ); ps->Device.bCCDID = ps->Device.bPCBID & 0x07; ps->Device.bPCBID &= 0xf0; DBG( DBG_LOW, "PCB-ID=0x%02x, CCD-ID=0x%02x\n", ps->Device.bPCBID, ps->Device.bCCDID ); /* get a more closer model description...*/ p12InitiateComponentModel( ps ); ps->CloseScanPath( ps ); /* here we check for the OpticWorks 2000, which is not supported */ if( _OPTICWORKS2000 == ps->Device.bPCBID ) { DBG( DBG_LOW, "OpticWorks 2000 not supported!\n" ); return _E_NOSUPP; } DBG( DBG_LOW, "P12InitAsic() done.\n" ); return _OK; } /*............................................................................. * set all necessary register contents */ _LOC void P12SetGeneralRegister( pScanData ps ) { DBG( DBG_LOW, "P12SetGeneralRegister()\n" ); ps->Scan.fMotorBackward = _FALSE; ps->Scan.fRefreshState = _FALSE; if( COLOR_BW == ps->DataInf.wPhyDataType ) ps->AsicReg.RD_ScanControl = _SCAN_BITMODE; else { if( ps->DataInf.wPhyDataType <= COLOR_TRUE24 ) ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; else ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE; } IOSelectLampSource( ps ); if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelDpi300; else ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelDpi600; ps->AsicReg.RD_Motor0Control = _MotorOn | _MotorHQuarterStep | _MotorPowerEnable; ps->AsicReg.RD_ScanControl1 = _SCANSTOPONBUFFULL | _MFRC_BY_XSTEP; ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; } /* END PLUSTEK-PP_P12.C .....................................................*/ sane-backends-1.0.27/backend/as6e.c0000664000175000017500000007136713106201017013620 00000000000000/* sane - Scanner Access Now Easy. Artec AS6E backend. Copyright (C) 2000 Eugene S. Weiss This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a backend for the Artec AS6E by making a bridge to the as6edriver program. The as6edriver program can be found at http://as6edriver.sourceforge.net . */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #define BACKENDNAME as6e #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "as6e.h" static int num_devices; static AS6E_Device *first_dev; static AS6E_Scan *first_handle; static const SANE_Device **devlist = 0; static SANE_Status attach (const char *devname, AS6E_Device ** devp); /* static SANE_Status attach_one (const char *dev); */ static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static const SANE_Word resolution_list[] = { 4, 300, 200, 100, 50 }; static const SANE_Range x_range = { SANE_FIX (0), SANE_FIX (215.91), SANE_FIX (0) }; static const SANE_Range y_range = { SANE_FIX (0), SANE_FIX (297.19), SANE_FIX (0) }; static const SANE_Range brightness_range = { -100, 100, 1 }; static const SANE_Range contrast_range = { -100, 100, 1 }; /*--------------------------------------------------------------------------*/ static SANE_Int as6e_unit_convert (SANE_Fixed value) { double precise; SANE_Int return_value; precise = SANE_UNFIX (value); precise = (precise * 300) / MM_PER_INCH; return_value = precise; return return_value; } /*--------------------------------------------------------------------------*/ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { AS6E_Scan *s = handle; SANE_Word buffer_offset = 0; int written = 0, bytes_read = 0, maxbytes; SANE_Word bytecounter, linebufcounter, ctlbytes; SANE_Byte *linebuffer; DBG (3, "reading %d bytes, %d bytes in carryover buffer\n", max_len, s->scan_buffer_count); if ((unsigned int) s->image_counter >= s->bytes_to_read) { *len = 0; if (s->scanning) { read (s->as6e_params.ctlinpipe, &written, sizeof (written)); if (written != -1) DBG (3, "pipe error\n"); DBG (3, "trying to read -1 ...written = %d\n", written); } s->scanning = SANE_FALSE; DBG (1, "image data complete, sending EOF...\n"); return SANE_STATUS_EOF; } /*image complete */ linebuffer = s->line_buffer; if (s->scan_buffer_count > 0) { /*there are leftover bytes from the last call */ if (s->scan_buffer_count <= max_len) { for (*len = 0; *len < s->scan_buffer_count; (*len)++) { buf[*len] = s->scan_buffer[*len]; buffer_offset++; } s->scan_buffer_count = 0; if (s->scan_buffer_count == max_len) { s->scan_buffer_count = 0; s->image_counter += max_len; DBG (3, "returning %d bytes from the carryover buffer\n", *len); return SANE_STATUS_GOOD; } } else { for (*len = 0; *len < max_len; (*len)++) buf[*len] = s->scan_buffer[*len]; for (bytecounter = max_len; bytecounter < s->scan_buffer_count; bytecounter++) s->scan_buffer[bytecounter - max_len] = s->scan_buffer[bytecounter]; s->scan_buffer_count -= max_len; s->image_counter += max_len; DBG (3, "returning %d bytes from the carryover buffer\n", *len); return SANE_STATUS_GOOD; } } else { *len = 0; /*no bytes in the buffer */ if (!s->scanning) { DBG (1, "scan over returning %d\n", *len); if (s->scan_buffer_count) return SANE_STATUS_GOOD; else return SANE_STATUS_EOF; } } while (*len < max_len) { DBG (3, "trying to read number of bytes...\n"); ctlbytes = read (s->as6e_params.ctlinpipe, &written, sizeof (written)); DBG (3, "bytes written = %d, ctlbytes =%d\n", written, ctlbytes); fflush (stdout); if ((s->cancelled) && (written == 0)) { /*first clear -1 from pipe */ DBG (1, "sending SANE_STATUS_CANCELLED\n"); read (s->as6e_params.ctlinpipe, &written, sizeof (written)); s->scanning = SANE_FALSE; return SANE_STATUS_CANCELLED; } if (written == -1) { DBG (1, "-1READ Scanner through. returning %d bytes\n", *len); s->image_counter += *len; s->scanning = SANE_FALSE; return SANE_STATUS_GOOD; } linebufcounter = 0; DBG (3, "linebufctr reset, len =%d written =%d bytes_read =%d, max = %d\n", *len, written, bytes_read, max_len); maxbytes = written; while (linebufcounter < written) { DBG (4, "trying to read data pipe\n"); bytes_read = read (s->as6e_params.datapipe, linebuffer + linebufcounter, maxbytes); linebufcounter += bytes_read; maxbytes -= bytes_read; DBG (3, "bytes_read = %d linebufcounter = %d\n", bytes_read, linebufcounter); } DBG (3, "written =%d max_len =%d len =%d\n", written, max_len, *len); if (written <= (max_len - *len)) { for (bytecounter = 0; bytecounter < written; bytecounter++) { buf[bytecounter + buffer_offset] = linebuffer[bytecounter]; (*len)++; } buffer_offset += written; DBG (3, "buffer offset = %d\n", buffer_offset); } else if (max_len > *len) { /*there's still room to send data */ for (bytecounter = 0; bytecounter < (max_len - *len); bytecounter++) buf[bytecounter + buffer_offset] = linebuffer[bytecounter]; DBG (3, "topping off buffer\n"); for (bytecounter = (max_len - *len); bytecounter < written; bytecounter++) { s->scan_buffer[s->scan_buffer_count + bytecounter - (max_len - *len)] = linebuffer[bytecounter]; } s->scan_buffer_count += (written - (max_len - *len)); *len = max_len; } else { /*everything goes into the carryover buffer */ for (bytecounter = 0; bytecounter < written; bytecounter++) s->scan_buffer[s->scan_buffer_count + bytecounter] = linebuffer[bytecounter]; s->scan_buffer_count += written; } } /*while there's space in the buffer */ s->image_counter += *len; DBG (3, "image ctr = %d bytes_to_read = %lu returning %d\n", s->image_counter, (u_long) s->bytes_to_read, *len); return SANE_STATUS_GOOD; } /*--------------------------------------------------------------------------*/ void sane_cancel (SANE_Handle h) { AS6E_Scan *s = h; SANE_Word test; DBG (2, "trying to cancel...\n"); if (s->scanning) { test = kill (s->child_pid, SIGUSR1); if (test == 0) s->cancelled = SANE_TRUE; } } /*--------------------------------------------------------------------------*/ SANE_Status sane_start (SANE_Handle handle) { AS6E_Scan *s = handle; SANE_Status status; int repeat = 1; SANE_Word numbytes; int scan_params[8]; /* First make sure we have a current parameter set. Some of the * parameters will be overwritten below, but that's OK. */ DBG (2, "sane_start\n"); status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; DBG (1, "Got params again...\n"); numbytes = write (s->as6e_params.ctloutpipe, &repeat, sizeof (repeat)); if (numbytes != sizeof (repeat)) return (SANE_STATUS_IO_ERROR); DBG (1, "sending start_scan signal\n"); scan_params[0] = s->as6e_params.resolution; if (strcmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) scan_params[1] = 0; else if (strcmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) scan_params[1] = 1; else if (strcmp (s->value[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) scan_params[1] = 2; else return (SANE_STATUS_JAMMED); /*this should never happen */ scan_params[2] = s->as6e_params.startpos; scan_params[3] = s->as6e_params.stoppos; scan_params[4] = s->as6e_params.startline; scan_params[5] = s->as6e_params.stopline; scan_params[6] = s->value[OPT_BRIGHTNESS].w; scan_params[7] = s->value[OPT_CONTRAST].w; DBG (1, "scan params = %d %d %d %d %d %d %d %d\n", scan_params[0], scan_params[1], scan_params[2], scan_params[3], scan_params[4], scan_params[5], scan_params[6], scan_params[7]); numbytes = write (s->as6e_params.ctloutpipe, scan_params, sizeof (scan_params)); if (numbytes != sizeof (scan_params)) return (SANE_STATUS_IO_ERROR); s->scanning = SANE_TRUE; s->scan_buffer_count = 0; s->image_counter = 0; s->cancelled = 0; return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { AS6E_Scan *s = handle; SANE_String mode; SANE_Word divisor = 1; DBG (2, "sane_get_parameters\n"); if (!s->scanning) { memset (&s->sane_params, 0, sizeof (s->sane_params)); s->as6e_params.resolution = s->value[OPT_RESOLUTION].w; s->as6e_params.startpos = as6e_unit_convert (s->value[OPT_TL_X].w); s->as6e_params.stoppos = as6e_unit_convert (s->value[OPT_BR_X].w); s->as6e_params.startline = as6e_unit_convert (s->value[OPT_TL_Y].w); s->as6e_params.stopline = as6e_unit_convert (s->value[OPT_BR_Y].w); if ((s->as6e_params.resolution == 200) || (s->as6e_params.resolution == 100)) divisor = 3; else if (s->as6e_params.resolution == 50) divisor = 6; /*get legal values for 200 dpi */ s->as6e_params.startpos = (s->as6e_params.startpos / divisor) * divisor; s->as6e_params.stoppos = (s->as6e_params.stoppos / divisor) * divisor; s->as6e_params.startline = (s->as6e_params.startline / divisor) * divisor; s->as6e_params.stopline = (s->as6e_params.stopline / divisor) * divisor; s->sane_params.pixels_per_line = (s->as6e_params.stoppos - s->as6e_params.startpos) * s->as6e_params.resolution / 300; s->sane_params.lines = (s->as6e_params.stopline - s->as6e_params.startline) * s->as6e_params.resolution / 300; mode = s->value[OPT_MODE].s; /* if ((strcmp (s->mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) || (strcmp (s->mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0)) { s->sane_params.format = SANE_FRAME_GRAY; s->sane_params.bytes_per_line = (s->sane_params.pixels_per_line + 7) / 8; s->sane_params.depth = 1; } */ /*else*/ if ((strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) || (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)) { s->sane_params.format = SANE_FRAME_GRAY; s->sane_params.bytes_per_line = s->sane_params.pixels_per_line; s->sane_params.depth = 8; } /*grey frame */ else { s->sane_params.format = SANE_FRAME_RGB; s->sane_params.bytes_per_line = 3 * s->sane_params.pixels_per_line; s->sane_params.depth = 8; } /*color frame */ s->bytes_to_read = s->sane_params.lines * s->sane_params.bytes_per_line; s->sane_params.last_frame = SANE_TRUE; } /*!scanning */ if (params) *params = s->sane_params; return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { AS6E_Scan *s = handle; SANE_Status status = 0; SANE_Word cap; DBG (2, "sane_control_option\n"); if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->options_list[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { DBG (1, "sane_control_option %d, get value\n", option); switch (option) { /* word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_CONTRAST: case OPT_BRIGHTNESS: *(SANE_Word *) val = s->value[option].w; return (SANE_STATUS_GOOD); /* string options: */ case OPT_MODE: strcpy (val, s->value[option].s); return (SANE_STATUS_GOOD); } } else if (action == SANE_ACTION_SET_VALUE) { DBG (1, "sane_control_option %d, set value\n", option); if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); /* status = sanei_constrain_value (s->options_list[option], val, info);*/ if (status != SANE_STATUS_GOOD) return (status); switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_BR_X: case OPT_BR_Y: case OPT_TL_X: case OPT_TL_Y: if (info && s->value[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_NUM_OPTS: case OPT_CONTRAST: case OPT_BRIGHTNESS: s->value[option].w = *(SANE_Word *) val; DBG (1, "set brightness to\n"); return (SANE_STATUS_GOOD); case OPT_MODE: if (s->value[option].s) free (s->value[option].s); s->value[option].s = strdup (val); return (SANE_STATUS_GOOD); } } return (SANE_STATUS_INVAL); } /*--------------------------------------------------------------------------*/ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { AS6E_Scan *s = handle; DBG (2, "sane_get_option_descriptor\n"); if ((unsigned) option >= NUM_OPTIONS) return (0); return (&s->options_list[option]); } /*--------------------------------------------------------------------------*/ void sane_close (SANE_Handle handle) { AS6E_Scan *prev, *s; SANE_Word repeat = 0; DBG (2, "sane_close\n"); /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (1, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (s->scanning) sane_cancel (handle); write (s->as6e_params.ctloutpipe, &repeat, sizeof (repeat)); close (s->as6e_params.ctloutpipe); free (s->scan_buffer); free (s->line_buffer); if (prev) prev->next = s->next; else first_handle = s; free (handle); } /*--------------------------------------------------------------------------*/ void sane_exit (void) { AS6E_Device *next; DBG (2, "sane_exit\n"); while (first_dev != NULL) { next = first_dev->next; free (first_dev); first_dev = next; } if (devlist) free (devlist); } /*--------------------------------------------------------------------------*/ static SANE_Status as6e_open (AS6E_Scan * s) { int data_processed, exec_result, as6e_status; int ctloutpipe[2], ctlinpipe[2], datapipe[2]; char inpipe_desc[32], outpipe_desc[32], datapipe_desc[32]; pid_t fork_result; DBG (1, "as6e_open\n"); memset (inpipe_desc, '\0', sizeof (inpipe_desc)); memset (outpipe_desc, '\0', sizeof (outpipe_desc)); memset (datapipe_desc, '\0', sizeof (datapipe_desc)); if ((pipe (ctloutpipe) == 0) && (pipe (ctlinpipe) == 0) && (pipe (datapipe) == 0)) { fork_result = fork (); if (fork_result == (pid_t) - 1) { DBG (1, "Fork failure"); return (SANE_STATUS_IO_ERROR); } if (fork_result == 0) { /*in child */ sprintf (inpipe_desc, "%d", ctlinpipe[WRITEPIPE]); sprintf (outpipe_desc, "%d", ctloutpipe[READPIPE]); sprintf (datapipe_desc, "%d", datapipe[WRITEPIPE]); exec_result = execlp ("as6edriver", "as6edriver", "-s", inpipe_desc, outpipe_desc, datapipe_desc, (char *) 0); DBG (1, "The SANE backend was unable to start \"as6edriver\".\n"); DBG (1, "This must be installed in a directory in your PATH.\n"); DBG (1, "To acquire the as6edriver program,\n"); DBG (1, "go to http://as6edriver.sourceforge.net.\n"); write (ctlinpipe[WRITEPIPE], &exec_result, sizeof (exec_result)); exit (-1); } else { /*parent process */ data_processed = read (ctlinpipe[READPIPE], &as6e_status, sizeof (as6e_status)); DBG (1, "%d - read %d status = %d\n", getpid (), data_processed, as6e_status); if (as6e_status == -2) { DBG (1, "Port access denied.\n"); return (SANE_STATUS_IO_ERROR); } if (as6e_status == -1) { DBG (1, "Could not contact scanner.\n"); return (SANE_STATUS_IO_ERROR); } if (as6e_status == 1) DBG (1, "Using nibble mode.\n"); if (as6e_status == 2) DBG (1, "Using byte mode.\n"); if (as6e_status == 3) DBG (1, "Using EPP mode.\n"); s->as6e_params.ctlinpipe = ctlinpipe[READPIPE]; s->as6e_params.ctloutpipe = ctloutpipe[WRITEPIPE]; s->as6e_params.datapipe = datapipe[READPIPE]; s->child_pid = fork_result; return (SANE_STATUS_GOOD); } /*else */ } else return (SANE_STATUS_IO_ERROR); } /*--------------------------------------------------------------------------*/ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp = NULL; DBG_INIT (); DBG (2, "sane_init (authorize %s null)\n", (authorize) ? "!=" : "=="); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); /* fp = sanei_config_open (AS6E_CONFIG_FILE);*/ if (!fp) { return (attach ("as6edriver", 0)); } while (fgets (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (dev_name[len - 1] == '\n') dev_name[--len] = '\0'; if (!len) continue; /* ignore empty lines */ /* sanei_config_attach_matching_devices (dev_name, attach_one);*/ } fclose (fp); return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ /* static SANE_Status attach_one (const char *dev) { DBG (2, "attach_one\n"); attach (dev, 0); return (SANE_STATUS_GOOD); } */ /*--------------------------------------------------------------------------*/ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { static const SANE_Device **devlist = 0; AS6E_Device *dev; int i; DBG (3, "sane_get_devices (local_only = %d)\n", local_only); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return (max_size); } /*--------------------------------------------------------------------------*/ static void initialize_options_list (AS6E_Scan * s) { SANE_Int option; DBG (2, "initialize_options_list\n"); for (option = 0; option < NUM_OPTIONS; ++option) { s->options_list[option].size = sizeof (SANE_Word); s->options_list[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->options_list[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->options_list[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->options_list[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->options_list[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->options_list[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; s->options_list[OPT_NUM_OPTS].size = sizeof (SANE_Word); s->options_list[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->options_list[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; s->value[OPT_NUM_OPTS].w = NUM_OPTIONS; s->options_list[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->options_list[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->options_list[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->options_list[OPT_MODE].type = SANE_TYPE_STRING; s->options_list[OPT_MODE].size = max_string_size (mode_list); s->options_list[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->options_list[OPT_MODE].constraint.string_list = mode_list; s->value[OPT_MODE].s = strdup (mode_list[2]); s->options_list[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->options_list[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->options_list[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->options_list[OPT_RESOLUTION].type = SANE_TYPE_INT; s->options_list[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->options_list[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->options_list[OPT_RESOLUTION].constraint.word_list = resolution_list; s->value[OPT_RESOLUTION].w = 200; s->options_list[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->options_list[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->options_list[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->options_list[OPT_TL_X].type = SANE_TYPE_FIXED; s->options_list[OPT_TL_X].unit = SANE_UNIT_MM; s->options_list[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_TL_X].constraint.range = &x_range; s->value[OPT_TL_X].w = s->options_list[OPT_TL_X].constraint.range->min; s->options_list[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->options_list[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->options_list[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->options_list[OPT_TL_Y].type = SANE_TYPE_FIXED; s->options_list[OPT_TL_Y].unit = SANE_UNIT_MM; s->options_list[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_TL_Y].constraint.range = &y_range; s->value[OPT_TL_Y].w = s->options_list[OPT_TL_Y].constraint.range->min; s->options_list[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->options_list[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->options_list[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->options_list[OPT_BR_X].type = SANE_TYPE_FIXED; s->options_list[OPT_BR_X].unit = SANE_UNIT_MM; s->options_list[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_BR_X].constraint.range = &x_range; s->value[OPT_BR_X].w = s->options_list[OPT_BR_X].constraint.range->max; s->options_list[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->options_list[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->options_list[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->options_list[OPT_BR_Y].type = SANE_TYPE_FIXED; s->options_list[OPT_BR_Y].unit = SANE_UNIT_MM; s->options_list[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_BR_Y].constraint.range = &y_range; s->value[OPT_BR_Y].w = s->options_list[OPT_BR_Y].constraint.range->max; s->options_list[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->options_list[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->options_list[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->options_list[OPT_CONTRAST].type = SANE_TYPE_INT; s->options_list[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->options_list[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_CONTRAST].constraint.range = &brightness_range; s->value[OPT_BRIGHTNESS].w = 10; s->options_list[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->options_list[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->options_list[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->options_list[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->options_list[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->options_list[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->options_list[OPT_BRIGHTNESS].constraint.range = &contrast_range; s->value[OPT_CONTRAST].w = -32; } /*--------------------------------------------------------------------------*/ static int check_for_driver (const char *devname) { #define NAMESIZE 128 struct stat statbuf; mode_t modes; char *path; char fullname[NAMESIZE]; char dir[NAMESIZE]; int count = 0, offset = 0; path = getenv ("PATH"); if (!path) return 0; while (path[count] != '\0') { memset (fullname, '\0', sizeof (fullname)); memset (dir, '\0', sizeof (dir)); while ((path[count] != ':') && (path[count] != '\0')) { dir[count - offset] = path[count]; count++; } /* use sizeof(fullname)-1 to make sure there is at least one padded null byte */ strncpy (fullname, dir, sizeof(fullname)-1); /* take into account that fullname already contains non-null bytes */ strncat (fullname, "/", sizeof(fullname)-strlen(fullname)-1); strncat (fullname, devname, sizeof(fullname)-strlen(fullname)-1); if (!stat (fullname, &statbuf)) { modes = statbuf.st_mode; if (S_ISREG (modes)) return (1); /* found as6edriver */ } if (path[count] == '\0') return (0); /* end of path --no driver found */ count++; offset = count; } return (0); } /*--------------------------------------------------------------------------*/ static SANE_Status attach (const char *devname, AS6E_Device ** devp) { AS6E_Device *dev; /* SANE_Status status; */ DBG (2, "attach\n"); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } dev = malloc (sizeof (*dev)); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devname); if (!check_for_driver (devname)) { free (dev); return (SANE_STATUS_INVAL); } dev->sane.model = "AS6E"; dev->sane.vendor = "Artec"; dev->sane.type = "flatbed scanner"; ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return (SANE_STATUS_GOOD); } /*--------------------------------------------------------------------------*/ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { SANE_Status status; AS6E_Device *dev; AS6E_Scan *s; DBG (2, "sane_open\n"); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) return (status); } } else { /* empty devicname -> use first device */ dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->scan_buffer = malloc (SCAN_BUF_SIZE); if (!s->scan_buffer) return SANE_STATUS_NO_MEM; memset (s->scan_buffer, 0, SCAN_BUF_SIZE); s->line_buffer = malloc (SCAN_BUF_SIZE); if (!s->line_buffer) return SANE_STATUS_NO_MEM; memset (s->line_buffer, 0, SCAN_BUF_SIZE); status = as6e_open (s); if (status != SANE_STATUS_GOOD) return status; initialize_options_list (s); s->scanning = 0; /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return (status); } /*--------------------------------------------------------------------------*/ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (2, "sane_set_io_mode( %p, %d )\n", handle, non_blocking); return (SANE_STATUS_UNSUPPORTED); } /*---------------------------------------------------------------------------*/ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (2, "sane_get_select_fd( %p, %p )\n",(void *) handle, (void *) fd); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/apple.c0000664000175000017500000022371213106201017014054 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998 Milon Firikis based on David Mosberger-Tang previous Work on mustek.c file from the SANE package. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Apple flatbed scanners. */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" /* SCSI commands that the Apple scanners understand: */ #define APPLE_SCSI_TEST_UNIT_READY 0x00 #define APPLE_SCSI_REQUEST_SENSE 0x03 #define APPLE_SCSI_INQUIRY 0x12 #define APPLE_SCSI_MODE_SELECT 0x15 #define APPLE_SCSI_RESERVE 0x16 #define APPLE_SCSI_RELEASE 0x17 #define APPLE_SCSI_START 0x1b #define APPLE_SCSI_AREA_AND_WINDOWS 0x24 #define APPLE_SCSI_READ_SCANNED_DATA 0x28 #define APPLE_SCSI_GET_DATA_STATUS 0x34 #define INQ_LEN 0x60 #define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE #define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE #define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) #define XQSTEP(XRES,BPP) (SANE_Int) (((double) (8*1200)) / ((double) (XRES*BPP))) #define YQSTEP(YRES) (SANE_Int) (((double) (1200)) / ((double) (YRES))) /* Very low info, Apple Scanners only */ /* TODO: Ok I admit it. I am not so clever to do this operations with bitwised operators. Sorry. */ #define STORE8(p,v) \ { \ *(p)=(v); \ } #define STORE16(p,v) \ { \ *(p)=(v)/256; \ *(p+1)=(v-*(p)*256); \ } #define STORE24(p,v) \ { \ *(p)=(v)/65536; \ *(p+1)=(v-*(p)*65536)/256; \ *(p+2)=(v-*(p)*65536-*(p+1)*256); \ } #define STORE32(p,v) \ { \ *(p)=(v)/16777216; \ *(p+1)=(v-*(p)*16777216)/65536; \ *(p+2)=(v-*(p)*16777216-*(p+1)*65536)/256; \ *(p+3)=(v-*(p)*16777216-*(p+1)*65536-*(p+2)*256);\ } #define READ24(p) *(p)*65536 + *(p+1)*256 + *(p+2) #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define APPLE_CONFIG_FILE "apple.conf" #include "apple.h" static const SANE_Device **devlist = 0; static int num_devices; static Apple_Device *first_dev; static Apple_Scanner *first_handle; static SANE_String_Const mode_list[6]; static SANE_String_Const SupportedModel[] = { "3", "AppleScanner 4bit, 16 Shades of Gray", "OneScanner 8bit, 256 Shades of Gray", "ColorOneScanner, RGB color 8bit per band", NULL }; static const SANE_String_Const graymap_list[] = { "dark", "normal", "light", 0 }; #if 0 static const SANE_Int resbit4_list[] = { 5, 75, 100, 150, 200, 300 }; static const SANE_Int resbit1_list[] = { 17, 75, 90, 100, 120, 135, 150, 165, 180, 195, 200, 210, 225, 240, 255, 270, 285, 300 }; #endif static const SANE_Int resbit_list[] = { 5, 75, 100, 150, 200, 300 }; static const SANE_String_Const speed_list[] = { "normal", "high", "high wo H/S", 0 }; static SANE_String_Const halftone_pattern_list[6]; static const SANE_String_Const color_sensor_list[] = { "All", "Red", "Green", "Blue", 0 }; /* NOTE: This is used for Brightness, Contrast, Threshold, AutoBackAdj and 0 is the default value */ static const SANE_Range byte_range = { 1, 255, 1 }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /* NOTE: However I can select from different lists during the hardware probing time. */ static const uint8_t inquiry[] = { APPLE_SCSI_INQUIRY, 0x00, 0x00, 0x00, INQ_LEN, 0x00 }; static const uint8_t test_unit_ready[] = { APPLE_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 }; #if 0 SANE_Int xqstep (unsigned int Xres, unsigned int bpp) { return (SANE_Int) ((double) (8 * 1200)) / ((double) (Xres * bpp)); } SANE_Int yqstep (unsigned int Yres, unsigned int bpp) { return (SANE_Int) ((double) (1200)) / ((double) (Yres)); } #endif /* The functions below return the quantized value of x,y in scanners dots aka 1/1200 of an inch */ static SANE_Int xquant (double x, unsigned int Xres, unsigned int bpp, int dir) { double tmp; unsigned int t; tmp = (double) x *Xres * bpp / (double) 8; t = (unsigned int) tmp; if (tmp - ((double) t) >= 0.1) if (dir) t++;; return t * 8 * 1200 / (Xres * bpp); } static SANE_Int yquant (double y, unsigned int Yres, int dir) { double tmp; unsigned int t; tmp = (double) y *Yres; t = (unsigned int) tmp; if (tmp - ((double) t) >= 0.1) if (dir) t++;; return t * 1200 / Yres; } static SANE_Status wait_ready (int fd) { #define MAX_WAITING_TIME 60 /* one minute, at most */ struct timeval now, start; SANE_Status status; #ifdef NEUTRALIZE_BACKEND return SANE_STATUS_GOOD; #else gettimeofday (&start, 0); while (1) { DBG (USER_MESSAGE, "wait_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG (ERROR_MESSAGE, "wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG (ERROR_MESSAGE, "wait_ready: timed out after %lu seconds\n", (u_long) now.tv_sec - start.tv_sec); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; } } return SANE_STATUS_INVAL; #endif /* NEUTRALIZE_BACKEND */ } static SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg) { scsi_fd = scsi_fd; /* silence gcc */ arg = arg; /* silence gcc */ switch (result[2] & 0x0F) { case 0: DBG (USER_MESSAGE, "Sense: No sense Error\n"); return SANE_STATUS_GOOD; case 2: DBG (ERROR_MESSAGE, "Sense: Scanner not ready\n"); return SANE_STATUS_DEVICE_BUSY; case 4: DBG (ERROR_MESSAGE, "Sense: Hardware Error. Read more...\n"); return SANE_STATUS_IO_ERROR; case 5: DBG (ERROR_MESSAGE, "Sense: Illegall request\n"); return SANE_STATUS_UNSUPPORTED; case 6: DBG (ERROR_MESSAGE, "Sense: Unit Attention (Wait until scanner " "boots)\n"); return SANE_STATUS_DEVICE_BUSY; case 9: DBG (ERROR_MESSAGE, "Sense: Vendor Unique. Read more...\n"); return SANE_STATUS_IO_ERROR; default: DBG (ERROR_MESSAGE, "Sense: Unknown Sense Key. Read more...\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } static SANE_Status request_sense (Apple_Scanner * s) { uint8_t cmd[6]; uint8_t result[22]; size_t size = sizeof (result); SANE_Status status; memset (cmd, 0, sizeof (cmd)); memset (result, 0, sizeof (result)); #ifdef NEUTRALIZE_BACKEND return SANE_STATUS_GOOD; #else cmd[0] = APPLE_SCSI_REQUEST_SENSE; STORE8 (cmd + 4, sizeof (result)); sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), result, &size); if (result[7] != 14) { DBG (ERROR_MESSAGE, "Additional Length %u\n", (unsigned int) result[7]); status = SANE_STATUS_IO_ERROR; } status = sense_handler (s->fd, result, NULL); if (status == SANE_STATUS_IO_ERROR) { /* Now we are checking for Harware and Vendor Unique Errors for all models */ /* First check the common Error conditions */ if (result[18] & 0x80) DBG (ERROR_MESSAGE, "Sense: Dim Light (output of lamp below 70%%).\n"); if (result[18] & 0x40) DBG (ERROR_MESSAGE, "Sense: No Light at all.\n"); if (result[18] & 0x20) DBG (ERROR_MESSAGE, "Sense: No Home.\n"); if (result[18] & 0x10) DBG (ERROR_MESSAGE, "Sense: No Limit. Tried to scan out of range.\n"); switch (s->hw->ScannerModel) { case APPLESCANNER: if (result[18] & 0x08) DBG (ERROR_MESSAGE, "Sense: Shade Error. Failed Calibration.\n"); if (result[18] & 0x04) DBG (ERROR_MESSAGE, "Sense: ROM Error.\n"); if (result[18] & 0x02) DBG (ERROR_MESSAGE, "Sense: RAM Error.\n"); if (result[18] & 0x01) DBG (ERROR_MESSAGE, "Sense: CPU Error.\n"); if (result[19] & 0x80) DBG (ERROR_MESSAGE, "Sense: DIPP Error.\n"); if (result[19] & 0x40) DBG (ERROR_MESSAGE, "Sense: DMA Error.\n"); if (result[19] & 0x20) DBG (ERROR_MESSAGE, "Sense: GA1 Error.\n"); break; case ONESCANNER: if (result[18] & 0x08) DBG (ERROR_MESSAGE, "Sense: CCD clock generator failed.\n"); if (result[18] & 0x04) DBG (ERROR_MESSAGE, "Sense: LRAM (Line RAM) Error.\n"); if (result[18] & 0x02) DBG (ERROR_MESSAGE, "Sense: CRAM (Correction RAM) Error.\n"); if (result[18] & 0x01) DBG (ERROR_MESSAGE, "Sense: ROM Error.\n"); if (result[19] & 0x08) DBG (ERROR_MESSAGE, "Sense: SRAM Error.\n"); if (result[19] & 0x04) DBG (ERROR_MESSAGE, "Sense: CPU Error.\n"); break; case COLORONESCANNER: if (result[18] & 0x08) DBG (ERROR_MESSAGE, "Sense: Calibration cirquit cannot " "support normal shading.\n"); if (result[18] & 0x04) DBG (ERROR_MESSAGE, "Sense: PSRAM (Correction RAM) Error.\n"); if (result[18] & 0x02) DBG (ERROR_MESSAGE, "Sense: SRAM Error.\n"); if (result[18] & 0x01) DBG (ERROR_MESSAGE, "Sense: ROM Error.\n"); if (result[19] & 0x10) DBG (ERROR_MESSAGE, "Sense: ICP (CPU) Error.\n"); if (result[19] & 0x02) DBG (ERROR_MESSAGE, "Sense: Over light. (Too bright lamp ?).\n"); break; default: DBG (ERROR_MESSAGE, "Sense: Unselected Scanner model. Please report this.\n"); break; } } DBG (USER_MESSAGE, "Sense: Optical gain %u.\n", (unsigned int) result[20]); return status; #endif /* NEUTRALIZE_BACKEND */ } static SANE_Status attach (const char *devname, Apple_Device ** devp, int may_wait) { char result[INQ_LEN]; const char *model_name = result + 44; int fd, apple_scanner, fw_revision; Apple_Device *dev; SANE_Status status; size_t size; for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } DBG (USER_MESSAGE, "attach: opening %s\n", devname); #ifdef NEUTRALIZE_BACKEND result[0]=0x06; strcpy(result + 8, "APPLE "); if (APPLE_MODEL_SELECT==APPLESCANNER) strcpy(result + 16, "SCANNER A9M0337 "); if (APPLE_MODEL_SELECT==ONESCANNER) strcpy(result + 16, "SCANNER II "); if (APPLE_MODEL_SELECT==COLORONESCANNER) strcpy(result + 16, "SCANNER III "); #else status = sanei_scsi_open (devname, &fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG (ERROR_MESSAGE, "attach: open failed (%s)\n", sane_strstatus (status)); return SANE_STATUS_INVAL; } if (may_wait) wait_ready (fd); DBG (USER_MESSAGE, "attach: sending INQUIRY\n"); size = sizeof (result); status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size); if (status != SANE_STATUS_GOOD) { DBG (ERROR_MESSAGE, "attach: inquiry failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } status = wait_ready (fd); sanei_scsi_close (fd); if (status != SANE_STATUS_GOOD) return status; #endif /* NEUTRALIZE_BACKEND */ /* check for old format: */ apple_scanner = (strncmp (result + 8, "APPLE ", 8) == 0); model_name = result + 16; apple_scanner = apple_scanner && (result[0] == 0x06); if (!apple_scanner) { DBG (ERROR_MESSAGE, "attach: device doesn't look like an Apple scanner" "(result[0]=%#02x)\n", result[0]); return SANE_STATUS_INVAL; } /* get firmware revision as BCD number: */ fw_revision = (result[32] - '0') << 8 | (result[34] - '0') << 4 | (result[35] - '0'); DBG (USER_MESSAGE, "attach: firmware revision %d.%02x\n", fw_revision >> 8, fw_revision & 0xff); dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devname); dev->sane.vendor = "Apple"; dev->sane.model = strndup (model_name, 16); dev->sane.type = "flatbed scanner"; dev->x_range.min = 0; dev->x_range.max = SANE_FIX (8.51 * MM_PER_INCH); dev->x_range.quant = 0; dev->y_range.min = 0; dev->y_range.max = SANE_FIX (14.0 * MM_PER_INCH); dev->y_range.quant = 0; dev->MaxHeight = 16800; if (strncmp (model_name, "SCANNER A9M0337 ", 16) == 0) { dev->ScannerModel = APPLESCANNER; dev->dpi_range.min = SANE_FIX (75); dev->dpi_range.max = SANE_FIX (300); dev->dpi_range.quant = SANE_FIX (1); dev->MaxWidth = 10208; } else if (strncmp (model_name, "SCANNER II ", 16) == 0) { dev->ScannerModel = ONESCANNER; dev->dpi_range.min = SANE_FIX (72); dev->dpi_range.max = SANE_FIX (300); dev->dpi_range.quant = SANE_FIX (1); dev->MaxWidth = 10200; } else if (strncmp (model_name, "SCANNER III ", 16) == 0) { dev->ScannerModel = COLORONESCANNER; dev->dpi_range.min = SANE_FIX (72); dev->dpi_range.max = SANE_FIX (300); dev->dpi_range.quant = SANE_FIX (1); dev->MaxWidth = 10200; } else { DBG (ERROR_MESSAGE, "attach: Cannot found Apple scanner in the neighborhood\n"); free (dev); return SANE_STATUS_INVAL; } DBG (USER_MESSAGE, "attach: found Apple scanner model %s (%s)\n", dev->sane.model, dev->sane.type); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status scan_area_and_windows (Apple_Scanner * s) { uint8_t cmd[10 + 8 + 42]; #define CMD cmd + 0 #define WH cmd + 10 #define WP WH + 8 #ifdef NEUTRALIZE_BACKEND return SANE_STATUS_GOOD; #else /* setup SCSI command (except length): */ memset (cmd, 0, sizeof (cmd)); cmd[0] = APPLE_SCSI_AREA_AND_WINDOWS; if (s->hw->ScannerModel == COLORONESCANNER) { STORE24 (CMD + 6, 50); STORE16 (WH + 6, 42); } else { STORE24 (CMD + 6, 48); STORE16 (WH + 6, 40); } /* Store resolution. First X, the Y */ STORE16 (WP + 2, s->val[OPT_RESOLUTION].w); STORE16 (WP + 4, s->val[OPT_RESOLUTION].w); /* Now the Scanner Window in Scanner Parameters */ STORE32 (WP + 6, s->ULx); STORE32 (WP + 10, s->ULy); STORE32 (WP + 14, s->Width); STORE32 (WP + 18, s->Height); /* Now The Enhansment Group */ STORE8 (WP + 22, s->val[OPT_BRIGHTNESS].w); STORE8 (WP + 23, s->val[OPT_THRESHOLD].w); STORE8 (WP + 24, s->val[OPT_CONTRAST].w); /* The Mode */ if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) STORE8 (WP + 25, 0) else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_HALFTONE)) STORE8 (WP + 25, 1) else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) || !strcmp (s->val[OPT_MODE].s, "Gray16")) STORE8 (WP + 25, 2) else if (!strcmp (s->val[OPT_MODE].s, "BiColor")) STORE8 (WP + 25, 3) else if (!strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR)) STORE8 (WP + 25, 5) else { DBG (ERROR_MESSAGE, "Cannot much mode %s\n", s->val[OPT_MODE].s); return SANE_STATUS_INVAL; } STORE8 (WP + 26, s->bpp) /* HalfTone */ if (s->hw->ScannerModel != COLORONESCANNER) { if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "spiral4x4")) STORE16 (WP + 27, 0) else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "bayer4x4")) STORE16 (WP + 27, 1) else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "download")) STORE16 (WP + 27, 1) else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "spiral8x8")) STORE16 (WP + 27, 3) else if (!strcmp (s->val[OPT_HALFTONE_PATTERN].s, "bayer8x8")) STORE16 (WP + 27, 4) else { DBG (ERROR_MESSAGE, "Cannot much haftone pattern %s\n", s->val[OPT_HALFTONE_PATTERN].s); return SANE_STATUS_INVAL; } } /* Padding Type */ STORE8 (WP + 29, 3); if (s->hw->ScannerModel == COLORONESCANNER) { if (s->val[OPT_VOLT_REF].w) { STORE8(WP+40,s->val[OPT_VOLT_REF_TOP].w); STORE8(WP+41,s->val[OPT_VOLT_REF_BOTTOM].w); } else { STORE8(WP+40,0); STORE8(WP+41,0); } return sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0); } else return sanei_scsi_cmd (s->fd, cmd, sizeof (cmd) - 2, 0, 0); #endif /* NEUTRALIZE_BACKEND */ } static SANE_Status mode_select (Apple_Scanner * s) { uint8_t cmd[6 + 12]; #define CMD cmd + 0 #define PP cmd + 6 /* setup SCSI command (except length): */ memset (cmd, 0, sizeof (cmd)); cmd[0] = APPLE_SCSI_MODE_SELECT; /* Apple Hardware Magic */ STORE8 (CMD + 1, 0x10); /* Parameter list length */ STORE8 (CMD + 4, 12); STORE8 (PP + 5, 6); if (s->val[OPT_LAMP].w) *(PP+8) |= 1; switch (s->hw->ScannerModel) { case APPLESCANNER: if (!strcmp (s->val[OPT_GRAYMAP].s, "dark")) STORE8 (PP + 6, 0) else if (!strcmp (s->val[OPT_GRAYMAP].s, "normal")) STORE8 (PP + 6, 1) else if (!strcmp (s->val[OPT_GRAYMAP].s, "light")) STORE8 (PP + 6, 2) else { DBG (ERROR_MESSAGE, "Cannot mach GrayMap Function %s\n", s->val[OPT_GRAYMAP].s); return SANE_STATUS_INVAL; } /* And the auto background threshold */ STORE8 (PP + 7, s->val[OPT_AUTOBACKGROUND_THRESHOLD].w) break; case ONESCANNER: if (s->val[OPT_LED].w) *(PP+7) |= 4; if (s->val[OPT_CCD].w) *(PP+8) |= 2; if (!strcmp (s->val[OPT_SPEED].s, "high")) *(PP+8) |= 4; else if (!strcmp (s->val[OPT_SPEED].s, "high wo H/S")) *(PP+8) |= 8; else if (!strcmp (s->val[OPT_SPEED].s, "normal")) { /* Do nothing. Zeros are great */} else { DBG (ERROR_MESSAGE, "Cannot mach speed selection %s\n", s->val[OPT_SPEED].s); return SANE_STATUS_INVAL; } break; case COLORONESCANNER: if (s->val[OPT_LED].w) *(PP+7) |= 4; if (!s->val[OPT_CUSTOM_GAMMA].w) *(PP+7) |= 2; if (!s->val[OPT_CUSTOM_CCT].w) *(PP+7) |= 1; if (s->val[OPT_MTF_CIRCUIT].w) *(PP+8) |= 16; if (s->val[OPT_ICP].w) *(PP+8) |= 8; if (s->val[OPT_POLARITY].w) *(PP+8) |= 4; if (s->val[OPT_CCD].w) *(PP+8) |= 2; if (!strcmp (s->val[OPT_COLOR_SENSOR].s, "All")) STORE8 (PP + 9, 0) else if (!strcmp (s->val[OPT_COLOR_SENSOR].s, "Red")) STORE8 (PP + 9, 1) else if (!strcmp (s->val[OPT_COLOR_SENSOR].s, "Green")) STORE8 (PP + 9, 2) else if (!strcmp (s->val[OPT_COLOR_SENSOR].s, "Blue")) STORE8 (PP + 9, 3) else { DBG (ERROR_MESSAGE, "Cannot mach Color Sensor for gray scans %s\n", s->val[OPT_COLOR_SENSOR].s); return SANE_STATUS_INVAL; } break; default: DBG(ERROR_MESSAGE,"Bad Scanner.\n"); break; } #ifdef NEUTRALIZE_BACKEND return SANE_STATUS_GOOD; #else return sanei_scsi_cmd (s->fd, cmd, sizeof (cmd), 0, 0); #endif /* NEUTRALIZE_BACKEND */ } static SANE_Status start_scan (Apple_Scanner * s) { SANE_Status status; uint8_t start[7]; memset (start, 0, sizeof (start)); start[0] = APPLE_SCSI_START; start[4] = 1; switch (s->hw->ScannerModel) { case APPLESCANNER: if (s->val[OPT_WAIT].w) start[5]=0x80; /* NOT TODO NoHome */ break; case ONESCANNER: if (!s->val[OPT_CALIBRATE].w) start[5]=0x20; break; case COLORONESCANNER: break; default: DBG(ERROR_MESSAGE,"Bad Scanner.\n"); break; } #ifdef NEUTRALIZE_BACKEND return SANE_STATUS_GOOD; #else status = sanei_scsi_cmd (s->fd, start, sizeof (start), 0, 0); return status; #endif /* NEUTRALIZE_BACKEND */ } static SANE_Status calc_parameters (Apple_Scanner * s) { SANE_String val = s->val[OPT_MODE].s; SANE_Status status = SANE_STATUS_GOOD; SANE_Bool OutOfRangeX, OutOfRangeY, Protect = SANE_TRUE; SANE_Int xqstep, yqstep; DBG (FLOW_CONTROL, "Entering calc_parameters\n"); if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) { s->params.last_frame = SANE_TRUE; s->params.format = SANE_FRAME_GRAY; s->params.depth = 1; s->bpp = 1; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE)) { s->params.last_frame = SANE_TRUE; s->params.format = SANE_FRAME_GRAY; s->params.depth = 1; s->bpp = 1; } else if (!strcmp (val, "Gray16")) { s->params.last_frame = SANE_TRUE; s->params.format = SANE_FRAME_GRAY; s->params.depth = 8; s->bpp = 4; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) { s->params.last_frame = SANE_TRUE; s->params.format = SANE_FRAME_GRAY; s->params.depth = 8; s->bpp = 8; } else if (!strcmp (val, "BiColor")) { s->params.last_frame = SANE_TRUE; s->params.format = SANE_FRAME_RGB; s->params.depth = 24; s->bpp = 3; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR)) { s->params.last_frame = SANE_FALSE; s->params.format = SANE_FRAME_RED; s->params.depth = 24; s->bpp = 24; } else { DBG (ERROR_MESSAGE, "calc_parameters: Invalid mode %s\n", (char *) val); status = SANE_STATUS_INVAL; } s->ulx = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH; s->uly = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH; s->wx = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH - s->ulx; s->wy = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH - s->uly; DBG (VARIABLE_CONTROL, "Desired [%g,%g] to +[%g,%g]\n", s->ulx, s->uly, s->wx, s->wy); xqstep = XQSTEP (s->val[OPT_RESOLUTION].w, s->bpp); yqstep = YQSTEP (s->val[OPT_RESOLUTION].w); DBG (VARIABLE_CONTROL, "Quantization steps of [%u,%u].\n", xqstep, yqstep); s->ULx = xquant (s->ulx, s->val[OPT_RESOLUTION].w, s->bpp, 0); s->Width = xquant (s->wx, s->val[OPT_RESOLUTION].w, s->bpp, 1); s->ULy = yquant (s->uly, s->val[OPT_RESOLUTION].w, 0); s->Height = yquant (s->wy, s->val[OPT_RESOLUTION].w, 1); DBG (VARIABLE_CONTROL, "Scanner [%u,%u] to +[%u,%u]\n", s->ULx, s->ULy, s->Width, s->Height); do { OutOfRangeX = SANE_FALSE; OutOfRangeY = SANE_FALSE; if (s->ULx + s->Width > s->hw->MaxWidth) { OutOfRangeX = SANE_TRUE; Protect = SANE_FALSE; s->Width -= xqstep; } if (s->ULy + s->Height > s->hw->MaxHeight) { OutOfRangeY = SANE_TRUE; Protect = SANE_FALSE; s->Height -= yqstep; } DBG (VARIABLE_CONTROL, "Adapting to [%u,%u] to +[%u,%u]\n", s->ULx, s->ULy, s->Width, s->Height); } while (OutOfRangeX || OutOfRangeY); s->ulx = (double) s->ULx / 1200; s->uly = (double) s->ULy / 1200; s->wx = (double) s->Width / 1200; s->wy = (double) s->Height / 1200; DBG (VARIABLE_CONTROL, "Real [%g,%g] to +[%g,%g]\n", s->ulx, s->uly, s->wx, s->wy); /* TODO: Remove this ugly hack (Protect). Read to learn why! NOTE: I hate the Fixed Sane type. This type gave me a terrible headache and a difficult bug to find out. The xscanimage frontend was looping and segfaulting all the time with random order. The problem was the following: * You select new let's say BR_X * sane_control_option returns info inexact (always for BR_X) but does not modify val because it fits under the constrained quantization. Hm... Well sane_control doesn't change the (double) value of val but the Fixed interpatation may have been change (by 1 or something small). So now we should protect the val if the change is smaller than the quantization step or better under the SANE_[UN]FIX accuracy. Looks like for two distinct val (Fixed) values we get the same double. How come ? This hack fixed the looping situtation. Unfortunately SIGSEGV remains when you touch the slice bars (thouhg not all the time). But it's OK if you select scan_area from the preview window (cool). */ if (!Protect) { s->val[OPT_TL_X].w = SANE_FIX (s->ulx * MM_PER_INCH); s->val[OPT_TL_Y].w = SANE_FIX (s->uly * MM_PER_INCH); s->val[OPT_BR_X].w = SANE_FIX ((s->ulx + s->wx) * MM_PER_INCH); s->val[OPT_BR_Y].w = SANE_FIX ((s->uly + s->wy) * MM_PER_INCH); } else DBG (VARIABLE_CONTROL, "Not adapted. Protecting\n"); DBG (VARIABLE_CONTROL, "GUI [%g,%g] to [%g,%g]\n", SANE_UNFIX (s->val[OPT_TL_X].w), SANE_UNFIX (s->val[OPT_TL_Y].w), SANE_UNFIX (s->val[OPT_BR_X].w), SANE_UNFIX (s->val[OPT_BR_Y].w)); /* NOTE: remember that AppleScanners quantize the scan area to be a byte multiple */ s->params.pixels_per_line = s->Width * s->val[OPT_RESOLUTION].w / 1200; s->params.lines = s->Height * s->val[OPT_RESOLUTION].w / 1200; s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8; DBG (VARIABLE_CONTROL, "format=%d\n", s->params.format); DBG (VARIABLE_CONTROL, "last_frame=%d\n", s->params.last_frame); DBG (VARIABLE_CONTROL, "lines=%d\n", s->params.lines); DBG (VARIABLE_CONTROL, "depth=%d (%d)\n", s->params.depth, s->bpp); DBG (VARIABLE_CONTROL, "pixels_per_line=%d\n", s->params.pixels_per_line); DBG (VARIABLE_CONTROL, "bytes_per_line=%d\n", s->params.bytes_per_line); DBG (VARIABLE_CONTROL, "Pixels %dx%dx%d\n", s->params.pixels_per_line, s->params.lines, 1 << s->params.depth); DBG (FLOW_CONTROL, "Leaving calc_parameters\n"); return status; } static SANE_Status gamma_update(SANE_Handle handle) { Apple_Scanner *s = handle; if (s->hw->ScannerModel == COLORONESCANNER) { if ( !strcmp(s->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_GRAY) || !strcmp(s->val[OPT_MODE].s,"Gray16") ) { ENABLE (OPT_CUSTOM_GAMMA); if (s->val[OPT_CUSTOM_GAMMA].w) { ENABLE (OPT_DOWNLOAD_GAMMA); if (! strcmp(s->val[OPT_COLOR_SENSOR].s,"All")) { ENABLE (OPT_GAMMA_VECTOR_R); ENABLE (OPT_GAMMA_VECTOR_G); ENABLE (OPT_GAMMA_VECTOR_B); } if (! strcmp(s->val[OPT_COLOR_SENSOR].s,"Red")) { ENABLE (OPT_GAMMA_VECTOR_R); DISABLE(OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); } if (! strcmp(s->val[OPT_COLOR_SENSOR].s,"Green")) { DISABLE (OPT_GAMMA_VECTOR_R); ENABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); } if (! strcmp(s->val[OPT_COLOR_SENSOR].s,"Blue")) { DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); ENABLE (OPT_GAMMA_VECTOR_B); } } else /* Not custom gamma */ { goto discustom; } } else if (!strcmp(s->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_COLOR)) { ENABLE (OPT_CUSTOM_GAMMA); if (s->val[OPT_CUSTOM_GAMMA].w) { ENABLE (OPT_DOWNLOAD_GAMMA); ENABLE (OPT_GAMMA_VECTOR_R); ENABLE (OPT_GAMMA_VECTOR_G); ENABLE (OPT_GAMMA_VECTOR_B); } else /* Not custom gamma */ { goto discustom; } } else /* Not Gamma capable mode */ { goto disall; } } /* Not Gamma capable Scanner */ else { disall: DISABLE (OPT_CUSTOM_GAMMA); discustom: DISABLE (OPT_GAMMA_VECTOR_R); DISABLE (OPT_GAMMA_VECTOR_G); DISABLE (OPT_GAMMA_VECTOR_B); DISABLE (OPT_DOWNLOAD_GAMMA); } return SANE_STATUS_GOOD; } static SANE_Status mode_update (SANE_Handle handle, char *val) { Apple_Scanner *s = handle; SANE_Bool cct=SANE_FALSE; SANE_Bool UseThreshold=SANE_FALSE; DISABLE(OPT_COLOR_SENSOR); if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) { if (s->hw->ScannerModel == APPLESCANNER) ENABLE (OPT_AUTOBACKGROUND); else DISABLE (OPT_AUTOBACKGROUND); DISABLE (OPT_HALFTONE_PATTERN); UseThreshold=SANE_TRUE; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE)) { DISABLE (OPT_AUTOBACKGROUND); ENABLE (OPT_HALFTONE_PATTERN); } else if (!strcmp (val, "Gray16") || !strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) { DISABLE (OPT_AUTOBACKGROUND); DISABLE (OPT_HALFTONE_PATTERN); if (s->hw->ScannerModel == COLORONESCANNER) ENABLE(OPT_COLOR_SENSOR); } /* End of Gray */ else if (!strcmp (val, "BiColor")) { DISABLE (OPT_AUTOBACKGROUND); DISABLE (OPT_HALFTONE_PATTERN); UseThreshold=SANE_TRUE; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR)) { DISABLE (OPT_AUTOBACKGROUND); DISABLE (OPT_HALFTONE_PATTERN); cct=SANE_TRUE; } else { DBG (ERROR_MESSAGE, "Invalid mode %s\n", (char *) val); return SANE_STATUS_INVAL; } /* Second hand dependancies of mode option */ /* Looks like code doubling */ if (UseThreshold) { DISABLE (OPT_BRIGHTNESS); DISABLE (OPT_CONTRAST); DISABLE (OPT_VOLT_REF); DISABLE (OPT_VOLT_REF_TOP); DISABLE (OPT_VOLT_REF_BOTTOM); if (IS_ACTIVE (OPT_AUTOBACKGROUND) && s->val[OPT_AUTOBACKGROUND].w) { DISABLE (OPT_THRESHOLD); ENABLE (OPT_AUTOBACKGROUND_THRESHOLD); } else { ENABLE (OPT_THRESHOLD); DISABLE (OPT_AUTOBACKGROUND_THRESHOLD); } } else { DISABLE (OPT_THRESHOLD); DISABLE (OPT_AUTOBACKGROUND_THRESHOLD); if (s->hw->ScannerModel == COLORONESCANNER) { ENABLE (OPT_VOLT_REF); if (s->val[OPT_VOLT_REF].w) { ENABLE (OPT_VOLT_REF_TOP); ENABLE (OPT_VOLT_REF_BOTTOM); DISABLE (OPT_BRIGHTNESS); DISABLE (OPT_CONTRAST); } else { DISABLE (OPT_VOLT_REF_TOP); DISABLE (OPT_VOLT_REF_BOTTOM); ENABLE (OPT_BRIGHTNESS); ENABLE (OPT_CONTRAST); } } else { ENABLE (OPT_BRIGHTNESS); ENABLE (OPT_CONTRAST); } } if (IS_ACTIVE (OPT_HALFTONE_PATTERN) && !strcmp (s->val[OPT_HALFTONE_PATTERN].s, "download")) ENABLE (OPT_HALFTONE_FILE); else DISABLE (OPT_HALFTONE_FILE); if (cct) ENABLE (OPT_CUSTOM_CCT); else DISABLE (OPT_CUSTOM_CCT); if (cct && s->val[OPT_CUSTOM_CCT].w) { ENABLE(OPT_CCT); ENABLE(OPT_DOWNLOAD_CCT); } else { DISABLE(OPT_CCT); DISABLE(OPT_DOWNLOAD_CCT); } gamma_update (s); calc_parameters (s); return SANE_STATUS_GOOD; } static SANE_Status init_options (Apple_Scanner * s) { int i; memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* Hardware detect Information group: */ s->opt[OPT_HWDETECT_GROUP].title = "Hardware"; s->opt[OPT_HWDETECT_GROUP].desc = "Detected during hardware probing"; s->opt[OPT_HWDETECT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_HWDETECT_GROUP].cap = 0; s->opt[OPT_HWDETECT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_MODEL].name = "model"; s->opt[OPT_MODEL].title = "Model"; s->opt[OPT_MODEL].desc = "Model and capabilities"; s->opt[OPT_MODEL].type = SANE_TYPE_STRING; s->opt[OPT_MODEL].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_MODEL].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_MODEL].size = max_string_size (SupportedModel); s->val[OPT_MODEL].s = strdup (SupportedModel[s->hw->ScannerModel]); /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; halftone_pattern_list[0]="spiral4x4"; halftone_pattern_list[1]="bayer4x4"; halftone_pattern_list[2]="download"; halftone_pattern_list[3]=NULL; switch (s->hw->ScannerModel) { case APPLESCANNER: mode_list[0]=SANE_VALUE_SCAN_MODE_LINEART; mode_list[1]=SANE_VALUE_SCAN_MODE_HALFTONE; mode_list[2]="Gray16"; mode_list[3]=NULL; break; case ONESCANNER: mode_list[0]=SANE_VALUE_SCAN_MODE_LINEART; mode_list[1]=SANE_VALUE_SCAN_MODE_HALFTONE; mode_list[2]="Gray16"; mode_list[3]=SANE_VALUE_SCAN_MODE_GRAY; mode_list[4]=NULL; halftone_pattern_list[3]="spiral8x8"; halftone_pattern_list[4]="bayer8x8"; halftone_pattern_list[5]=NULL; break; case COLORONESCANNER: mode_list[0]=SANE_VALUE_SCAN_MODE_LINEART; mode_list[1]="Gray16"; mode_list[2]=SANE_VALUE_SCAN_MODE_GRAY; mode_list[3]="BiColor"; mode_list[4]=SANE_VALUE_SCAN_MODE_COLOR; mode_list[5]=NULL; break; default: break; } /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[0]); /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; /* TODO: Build the constraints on resolution in a smart way */ s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = resbit_list; s->val[OPT_RESOLUTION].w = resbit_list[1]; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_PREVIEW].w = SANE_FALSE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &byte_range; s->val[OPT_BRIGHTNESS].w = 128; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST " This option is active for halftone/Grayscale modes only."; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &byte_range; s->val[OPT_CONTRAST].w = 1; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &byte_range; s->val[OPT_THRESHOLD].w = 128; /* AppleScanner Only options */ /* GrayMap Enhance */ s->opt[OPT_GRAYMAP].name = "graymap"; s->opt[OPT_GRAYMAP].title = "GrayMap"; s->opt[OPT_GRAYMAP].desc = "Fixed Gamma Enhancing"; s->opt[OPT_GRAYMAP].type = SANE_TYPE_STRING; s->opt[OPT_GRAYMAP].constraint_type = SANE_CONSTRAINT_STRING_LIST; if (s->hw->ScannerModel != APPLESCANNER) s->opt[OPT_GRAYMAP].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GRAYMAP].constraint.string_list = graymap_list; s->opt[OPT_GRAYMAP].size = max_string_size (graymap_list); s->val[OPT_GRAYMAP].s = strdup (graymap_list[1]); /* Enable auto background adjustment */ s->opt[OPT_AUTOBACKGROUND].name = "abj"; s->opt[OPT_AUTOBACKGROUND].title = "Use Auto Background Adjustment"; s->opt[OPT_AUTOBACKGROUND].desc = "Enables/Disables the Auto Background Adjustment feature"; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) || (s->hw->ScannerModel != APPLESCANNER)) DISABLE (OPT_AUTOBACKGROUND); s->opt[OPT_AUTOBACKGROUND].type = SANE_TYPE_BOOL; s->val[OPT_AUTOBACKGROUND].w = SANE_FALSE; /* auto background adjustment threshold */ s->opt[OPT_AUTOBACKGROUND_THRESHOLD].name = "abjthreshold"; s->opt[OPT_AUTOBACKGROUND_THRESHOLD].title = "Auto Background Adjustment Threshold"; s->opt[OPT_AUTOBACKGROUND_THRESHOLD].desc = "Selects the automatically adjustable threshold"; s->opt[OPT_AUTOBACKGROUND_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_AUTOBACKGROUND_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_AUTOBACKGROUND_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; if (!IS_ACTIVE (OPT_AUTOBACKGROUND) || s->val[OPT_AUTOBACKGROUND].w == SANE_FALSE) s->opt[OPT_AUTOBACKGROUND_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_AUTOBACKGROUND_THRESHOLD].constraint.range = &byte_range; s->val[OPT_AUTOBACKGROUND_THRESHOLD].w = 64; /* AppleScanner & OneScanner options */ /* Select HalfTone Pattern */ s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].size = max_string_size (halftone_pattern_list); s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_AUTOMATIC; s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_pattern_list; s->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[0]); if (s->hw->ScannerModel!=APPLESCANNER && s->hw->ScannerModel!=ONESCANNER) s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; /* halftone pattern file */ s->opt[OPT_HALFTONE_FILE].name = "halftone-pattern-file"; s->opt[OPT_HALFTONE_FILE].title = "Halftone Pattern File"; s->opt[OPT_HALFTONE_FILE].desc = "Download and use the specified file as halftone pattern"; s->opt[OPT_HALFTONE_FILE].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE_FILE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_FILE].size = 256; s->val[OPT_HALFTONE_FILE].s = "halftone.pgm"; /* Use volt_ref */ s->opt[OPT_VOLT_REF].name = "volt-ref"; s->opt[OPT_VOLT_REF].title = "Volt Reference"; s->opt[OPT_VOLT_REF].desc ="It's brightness equivalant."; s->opt[OPT_VOLT_REF].type = SANE_TYPE_BOOL; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_VOLT_REF].cap |= SANE_CAP_INACTIVE; s->val[OPT_VOLT_REF].w = SANE_FALSE; s->opt[OPT_VOLT_REF_TOP].name = "volt-ref-top"; s->opt[OPT_VOLT_REF_TOP].title = "Top Voltage Reference"; s->opt[OPT_VOLT_REF_TOP].desc = "I really do not know."; s->opt[OPT_VOLT_REF_TOP].type = SANE_TYPE_INT; s->opt[OPT_VOLT_REF_TOP].unit = SANE_UNIT_NONE; if (s->hw->ScannerModel!=COLORONESCANNER || s->val[OPT_VOLT_REF].w==SANE_FALSE) s->opt[OPT_VOLT_REF_TOP].cap |= SANE_CAP_INACTIVE; s->opt[OPT_VOLT_REF_TOP].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_VOLT_REF_TOP].constraint.range = &byte_range; s->val[OPT_VOLT_REF_TOP].w = 255; s->opt[OPT_VOLT_REF_BOTTOM].name = "volt-ref-bottom"; s->opt[OPT_VOLT_REF_BOTTOM].title = "Bottom Voltage Reference"; s->opt[OPT_VOLT_REF_BOTTOM].desc = "I really do not know."; s->opt[OPT_VOLT_REF_BOTTOM].type = SANE_TYPE_INT; s->opt[OPT_VOLT_REF_BOTTOM].unit = SANE_UNIT_NONE; if (s->hw->ScannerModel!=COLORONESCANNER || s->val[OPT_VOLT_REF].w==SANE_FALSE) s->opt[OPT_VOLT_REF_BOTTOM].cap |= SANE_CAP_INACTIVE; s->opt[OPT_VOLT_REF_BOTTOM].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_VOLT_REF_BOTTOM].constraint.range = &byte_range; s->val[OPT_VOLT_REF_BOTTOM].w = 1; /* Misc Functions: Advanced */ s->opt[OPT_MISC_GROUP].title = "Miscallaneous"; s->opt[OPT_MISC_GROUP].desc = ""; s->opt[OPT_MISC_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MISC_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_MISC_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Turn On lamp during scan: All scanners */ s->opt[OPT_LAMP].name = "lamp"; s->opt[OPT_LAMP].title = "Lamp"; s->opt[OPT_LAMP].desc = "Hold the lamp on during scans."; s->opt[OPT_LAMP].type = SANE_TYPE_BOOL; s->val[OPT_LAMP].w = SANE_FALSE; /* AppleScanner Only options */ /* Wait for button to be pressed before scanning */ s->opt[OPT_WAIT].name = "wait"; s->opt[OPT_WAIT].title = "Wait"; s->opt[OPT_WAIT].desc = "You may issue the scan command but the actual " "scan will not start unless you press the button in the front of the " "scanner. It is a useful feature when you want to make a network scan (?) " "In the mean time you may halt your computer waiting for the SCSI bus " "to be free. If this happens just press the scanner button."; s->opt[OPT_WAIT].type = SANE_TYPE_BOOL; if (s->hw->ScannerModel != APPLESCANNER) s->opt[OPT_WAIT].cap |= SANE_CAP_INACTIVE; s->val[OPT_WAIT].w = SANE_FALSE; /* OneScanner Only options */ /* Calibrate before scanning ? */ s->opt[OPT_CALIBRATE].name = "calibrate"; s->opt[OPT_CALIBRATE].title = "Calibrate"; s->opt[OPT_CALIBRATE].desc = "You may avoid the calibration before " "scanning but this will lead you to lower image quality."; s->opt[OPT_CALIBRATE].type = SANE_TYPE_BOOL; if (s->hw->ScannerModel != ONESCANNER) s->opt[OPT_CALIBRATE].cap |= SANE_CAP_INACTIVE; s->val[OPT_CALIBRATE].w = SANE_TRUE; /* speed */ s->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; s->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; s->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; s->opt[OPT_SPEED].type = SANE_TYPE_STRING; if (s->hw->ScannerModel != ONESCANNER) s->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE; s->opt[OPT_SPEED].size = max_string_size (speed_list); s->opt[OPT_SPEED].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SPEED].constraint.string_list = speed_list; s->val[OPT_SPEED].s = strdup (speed_list[0]); /* OneScanner & ColorOneScanner (LED && CCD) */ /* LED ? */ s->opt[OPT_LED].name = "led"; s->opt[OPT_LED].title = "LED"; s->opt[OPT_LED].desc ="This option controls the setting of the ambler LED."; s->opt[OPT_LED].type = SANE_TYPE_BOOL; if (s->hw->ScannerModel!=ONESCANNER && s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_LED].cap |= SANE_CAP_INACTIVE; s->val[OPT_LED].w = SANE_TRUE; /* CCD Power ? */ s->opt[OPT_CCD].name = "ccd"; s->opt[OPT_CCD].title = "CCD Power"; s->opt[OPT_CCD].desc ="This option controls the power to the CCD array."; s->opt[OPT_CCD].type = SANE_TYPE_BOOL; if (s->hw->ScannerModel!=ONESCANNER && s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_CCD].cap |= SANE_CAP_INACTIVE; s->val[OPT_CCD].w = SANE_TRUE; /* Use MTF Circuit */ s->opt[OPT_MTF_CIRCUIT].name = "mtf"; s->opt[OPT_MTF_CIRCUIT].title = "MTF Circuit"; s->opt[OPT_MTF_CIRCUIT].desc ="Turns the MTF (Modulation Transfer Function) " "peaking circuit on or off."; s->opt[OPT_MTF_CIRCUIT].type = SANE_TYPE_BOOL; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_MTF_CIRCUIT].cap |= SANE_CAP_INACTIVE; s->val[OPT_MTF_CIRCUIT].w = SANE_TRUE; /* Use ICP */ s->opt[OPT_ICP].name = "icp"; s->opt[OPT_ICP].title = "ICP"; s->opt[OPT_ICP].desc ="What is an ICP anyway?"; s->opt[OPT_ICP].type = SANE_TYPE_BOOL; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_ICP].cap |= SANE_CAP_INACTIVE; s->val[OPT_ICP].w = SANE_TRUE; /* Data Polarity */ s->opt[OPT_POLARITY].name = "polarity"; s->opt[OPT_POLARITY].title = "Data Polarity"; s->opt[OPT_POLARITY].desc = "Reverse black and white."; s->opt[OPT_POLARITY].type = SANE_TYPE_BOOL; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_POLARITY].cap |= SANE_CAP_INACTIVE; s->val[OPT_POLARITY].w = SANE_FALSE; /* Color Functions: Advanced */ s->opt[OPT_COLOR_GROUP].title = SANE_VALUE_SCAN_MODE_COLOR; s->opt[OPT_COLOR_GROUP].desc = ""; s->opt[OPT_COLOR_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_COLOR_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_COLOR_GROUP].constraint_type = SANE_CONSTRAINT_NONE; #ifdef CALIBRATION_FUNCTIONALITY /* OneScanner calibration vector */ s->opt[OPT_CALIBRATION_VECTOR].name = "calibration-vector"; s->opt[OPT_CALIBRATION_VECTOR].title = "Calibration Vector"; s->opt[OPT_CALIBRATION_VECTOR].desc = "Calibration vector for the CCD array."; s->opt[OPT_CALIBRATION_VECTOR].type = SANE_TYPE_INT; if (s->hw->ScannerModel!=ONESCANNER) s->opt[OPT_CALIBRATION_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CALIBRATION_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_CALIBRATION_VECTOR].size = 2550 * sizeof (SANE_Word); s->opt[OPT_CALIBRATION_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CALIBRATION_VECTOR].constraint.range = &u8_range; s->val[OPT_CALIBRATION_VECTOR].wa = s->calibration_vector; /* ColorOneScanner calibration vector per band */ s->opt[OPT_CALIBRATION_VECTOR_RED].name = "calibration-vector-red"; s->opt[OPT_CALIBRATION_VECTOR_RED].title = "Calibration Vector for Red"; s->opt[OPT_CALIBRATION_VECTOR_RED].desc = "Calibration vector for the CCD array."; s->opt[OPT_CALIBRATION_VECTOR_RED].type = SANE_TYPE_INT; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_CALIBRATION_VECTOR_RED].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CALIBRATION_VECTOR_RED].unit = SANE_UNIT_NONE; s->opt[OPT_CALIBRATION_VECTOR_RED].size = 2700 * sizeof (SANE_Word); s->opt[OPT_CALIBRATION_VECTOR_RED].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CALIBRATION_VECTOR_RED].constraint.range = &u8_range; s->val[OPT_CALIBRATION_VECTOR_RED].wa = s->calibration_vector_red; /* ColorOneScanner calibration vector per band */ s->opt[OPT_CALIBRATION_VECTOR_GREEN].name = "calibration-vector-green"; s->opt[OPT_CALIBRATION_VECTOR_GREEN].title = "Calibration Vector for Green"; s->opt[OPT_CALIBRATION_VECTOR_GREEN].desc = "Calibration vector for the CCD array."; s->opt[OPT_CALIBRATION_VECTOR_GREEN].type = SANE_TYPE_INT; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_CALIBRATION_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CALIBRATION_VECTOR_GREEN].unit = SANE_UNIT_NONE; s->opt[OPT_CALIBRATION_VECTOR_GREEN].size = 2700 * sizeof (SANE_Word); s->opt[OPT_CALIBRATION_VECTOR_GREEN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CALIBRATION_VECTOR_GREEN].constraint.range = &u8_range; s->val[OPT_CALIBRATION_VECTOR_GREEN].wa = s->calibration_vector_green; /* ColorOneScanner calibration vector per band */ s->opt[OPT_CALIBRATION_VECTOR_BLUE].name = "calibration-vector-blue"; s->opt[OPT_CALIBRATION_VECTOR_BLUE].title = "Calibration Vector for Blue"; s->opt[OPT_CALIBRATION_VECTOR_BLUE].desc = "Calibration vector for the CCD array."; s->opt[OPT_CALIBRATION_VECTOR_BLUE].type = SANE_TYPE_INT; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_CALIBRATION_VECTOR_BLUE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CALIBRATION_VECTOR_BLUE].unit = SANE_UNIT_NONE; s->opt[OPT_CALIBRATION_VECTOR_BLUE].size = 2700 * sizeof (SANE_Word); s->opt[OPT_CALIBRATION_VECTOR_BLUE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CALIBRATION_VECTOR_BLUE].constraint.range = &u8_range; s->val[OPT_CALIBRATION_VECTOR_BLUE].wa = s->calibration_vector_blue; #endif /* CALIBRATION_FUNCTIONALITY */ /* Action: Download calibration vector */ s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].name = "download-calibration"; s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].title = "Download Calibration Vector"; s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].desc = "Download calibration vector to scanner"; s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].type = SANE_TYPE_BUTTON; if (s->hw->ScannerModel!=ONESCANNER && s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_DOWNLOAD_CALIBRATION_VECTOR].cap |= SANE_CAP_INACTIVE; /* custom-cct table */ s->opt[OPT_CUSTOM_CCT].name = "custom-cct"; s->opt[OPT_CUSTOM_CCT].title = "Use Custom CCT"; s->opt[OPT_CUSTOM_CCT].desc ="Determines whether a builtin " "or a custom 3x3 Color Correction Table (CCT) should be used."; s->opt[OPT_CUSTOM_CCT].type = SANE_TYPE_BOOL; s->opt[OPT_CUSTOM_CCT].cap |= SANE_CAP_INACTIVE; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_CUSTOM_CCT].cap |= SANE_CAP_INACTIVE; s->val[OPT_CUSTOM_CCT].w = SANE_FALSE; /* CCT */ s->opt[OPT_CCT].name = "cct"; s->opt[OPT_CCT].title = "3x3 Color Correction Table"; s->opt[OPT_CCT].desc = "TODO: Color Correction is currently unsupported"; s->opt[OPT_CCT].type = SANE_TYPE_FIXED; s->opt[OPT_CCT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CCT].unit = SANE_UNIT_NONE; s->opt[OPT_CCT].size = 9 * sizeof (SANE_Word); s->opt[OPT_CCT].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CCT].constraint.range = &u8_range; s->val[OPT_CCT].wa = s->cct3x3; /* Action: custom 3x3 color correction table */ s->opt[OPT_DOWNLOAD_CCT].name = "download-3x3"; s->opt[OPT_DOWNLOAD_CCT].title = "Download 3x3 CCT"; s->opt[OPT_DOWNLOAD_CCT].desc = "Download 3x3 color correction table"; s->opt[OPT_DOWNLOAD_CCT].type = SANE_TYPE_BUTTON; if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_DOWNLOAD_CCT].cap |= SANE_CAP_INACTIVE; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[0][0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[1][0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[2][0]; /* Action: download gamma vectors table */ s->opt[OPT_DOWNLOAD_GAMMA].name = "download-gamma"; s->opt[OPT_DOWNLOAD_GAMMA].title = "Download Gamma Vector(s)"; s->opt[OPT_DOWNLOAD_GAMMA].desc = "Download Gamma Vector(s)."; s->opt[OPT_DOWNLOAD_GAMMA].type = SANE_TYPE_BUTTON; s->opt[OPT_DOWNLOAD_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_COLOR_SENSOR].name = "color-sensor"; s->opt[OPT_COLOR_SENSOR].title = "Gray scan with"; s->opt[OPT_COLOR_SENSOR].desc = "Select the color sensor to scan in gray mode."; s->opt[OPT_COLOR_SENSOR].type = SANE_TYPE_STRING; s->opt[OPT_COLOR_SENSOR].unit = SANE_UNIT_NONE; s->opt[OPT_COLOR_SENSOR].size = max_string_size (color_sensor_list); if (s->hw->ScannerModel!=COLORONESCANNER) s->opt[OPT_COLOR_SENSOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_COLOR_SENSOR].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_COLOR_SENSOR].constraint.string_list = color_sensor_list; s->val[OPT_COLOR_SENSOR].s = strdup(color_sensor_list[2]); mode_update (s, s->val[OPT_MODE].s); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach (dev, 0, SANE_FALSE); return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; authorize = authorize; /* silence gcc */ DBG_INIT (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (APPLE_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach ("/dev/scanner", 0, SANE_FALSE); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ if (strncmp (dev_name, "option", 6) == 0 && isspace (dev_name[6])) { const char *str = dev_name + 7; while (isspace (*str)) ++str; continue; } sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { Apple_Device *dev, *next; for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free (dev); } if (devlist) free (devlist); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Apple_Device *dev; int i; local_only = local_only; /* silence gcc */ if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Apple_Device *dev; SANE_Status status; Apple_Scanner *s; int i, j; if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach (devicename, &dev, SANE_TRUE); if (status != SANE_STATUS_GOOD) return status; } } else /* empty devicname -> use first device */ dev = first_dev; if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->hw = dev; for (i = 0; i < 3; ++i) for (j = 0; j < 256; ++j) s->gamma_table[i][j] = j; init_options (s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Apple_Scanner *prev, *s; /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (ERROR_MESSAGE, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (prev) prev->next = s->next; else first_handle = s->next; free (handle); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Apple_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Apple_Scanner *s = handle; SANE_Status status; SANE_Word cap; DBG (FLOW_CONTROL, "(%s): Entering on control_option for option %s (%d).\n", (action == SANE_ACTION_GET_VALUE) ? "get" : "set", s->opt[option].name, option); if (val || action == SANE_ACTION_GET_VALUE) switch (s->opt[option].type) { case SANE_TYPE_STRING: DBG (FLOW_CONTROL, "Value %s\n", (action == SANE_ACTION_GET_VALUE) ? s->val[option].s : (char *) val); break; case SANE_TYPE_FIXED: { double v1, v2; SANE_Fixed f; v1 = SANE_UNFIX (s->val[option].w); f = *(SANE_Fixed *) val; v2 = SANE_UNFIX (f); DBG (FLOW_CONTROL, "Value %g (Fixed)\n", (action == SANE_ACTION_GET_VALUE) ? v1 : v2); } default: DBG (FLOW_CONTROL, "Value %u (Int).\n", (action == SANE_ACTION_GET_VALUE) ? s->val[option].w : *(SANE_Int *) val); break; } if (info) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_AUTOBACKGROUND: case OPT_AUTOBACKGROUND_THRESHOLD: case OPT_VOLT_REF: case OPT_VOLT_REF_TOP: case OPT_VOLT_REF_BOTTOM: case OPT_LAMP: case OPT_WAIT: case OPT_CALIBRATE: case OPT_LED: case OPT_CCD: case OPT_MTF_CIRCUIT: case OPT_ICP: case OPT_POLARITY: case OPT_CUSTOM_CCT: case OPT_CUSTOM_GAMMA: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; /* word-array options: */ case OPT_CCT: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); return SANE_STATUS_GOOD; /* string options: */ case OPT_MODE: /* TODO: This is to protect the mode string to be ruined from the dll? backend. I do not know why. It's definitely an overkill and should be eliminated. status = sanei_constrain_value (s->opt + option, s->val[option].s, info); */ case OPT_MODEL: case OPT_GRAYMAP: case OPT_HALFTONE_PATTERN: case OPT_HALFTONE_FILE: case OPT_SPEED: case OPT_COLOR_SENSOR: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; /* Some Buttons */ case OPT_DOWNLOAD_CALIBRATION_VECTOR: case OPT_DOWNLOAD_CCT: case OPT_DOWNLOAD_GAMMA: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; calc_parameters (s); if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; return SANE_STATUS_GOOD; /* fall through */ case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_AUTOBACKGROUND_THRESHOLD: case OPT_VOLT_REF_TOP: case OPT_VOLT_REF_BOTTOM: case OPT_LAMP: case OPT_WAIT: case OPT_CALIBRATE: case OPT_LED: case OPT_CCD: case OPT_MTF_CIRCUIT: case OPT_ICP: case OPT_POLARITY: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* Simple Strings */ case OPT_GRAYMAP: case OPT_HALFTONE_FILE: case OPT_SPEED: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return SANE_STATUS_GOOD; /* Boolean */ case OPT_PREVIEW: s->val[option].w = *(SANE_Bool *) val; return SANE_STATUS_GOOD; /* side-effect-free word-array options: */ case OPT_CCT: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); return SANE_STATUS_GOOD; /* options with light side-effects: */ case OPT_HALFTONE_PATTERN: if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (!strcmp (val, "download")) { return SANE_STATUS_UNSUPPORTED; /* TODO: ENABLE(OPT_HALFTONE_FILE); */ } else DISABLE (OPT_HALFTONE_FILE); return SANE_STATUS_GOOD; case OPT_AUTOBACKGROUND: if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[option].w = *(SANE_Bool *) val; if (*(SANE_Bool *) val) { DISABLE (OPT_THRESHOLD); ENABLE (OPT_AUTOBACKGROUND_THRESHOLD); } else { ENABLE (OPT_THRESHOLD); DISABLE (OPT_AUTOBACKGROUND_THRESHOLD); } return SANE_STATUS_GOOD; case OPT_VOLT_REF: if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[option].w = *(SANE_Bool *) val; if (*(SANE_Bool *) val) { DISABLE(OPT_BRIGHTNESS); DISABLE(OPT_CONTRAST); ENABLE(OPT_VOLT_REF_TOP); ENABLE(OPT_VOLT_REF_BOTTOM); } else { ENABLE(OPT_BRIGHTNESS); ENABLE(OPT_CONTRAST); DISABLE(OPT_VOLT_REF_TOP); DISABLE(OPT_VOLT_REF_BOTTOM); } return SANE_STATUS_GOOD; /* Actions: Buttons */ case OPT_DOWNLOAD_CALIBRATION_VECTOR: case OPT_DOWNLOAD_CCT: case OPT_DOWNLOAD_GAMMA: /* TODO: fix {down/up}loads */ return SANE_STATUS_UNSUPPORTED; case OPT_CUSTOM_CCT: s->val[OPT_CUSTOM_CCT].w=*(SANE_Word *) val; if (s->val[OPT_CUSTOM_CCT].w) { ENABLE(OPT_CCT); ENABLE(OPT_DOWNLOAD_CCT); } else { DISABLE(OPT_CCT); DISABLE(OPT_DOWNLOAD_CCT); } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: s->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; gamma_update(s); if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_COLOR_SENSOR: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); gamma_update(s); if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; /* HEAVY (RADIOACTIVE) SIDE EFFECTS: CHECKME */ case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); status = mode_update (s, val); if (status != SANE_STATUS_GOOD) return status; if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; } /* End of switch */ } /* End of SET_VALUE */ return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Apple_Scanner *s = handle; DBG (FLOW_CONTROL, "Entering sane_get_parameters\n"); calc_parameters (s); if (params) *params = s->params; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Apple_Scanner *s = handle; SANE_Status status; /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ calc_parameters (s); if (s->fd < 0) { /* this is the first (and maybe only) pass... */ status = sanei_scsi_open (s->hw->sane.name, &s->fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG (ERROR_MESSAGE, "open: open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return status; } } status = wait_ready (s->fd); if (status != SANE_STATUS_GOOD) { DBG (ERROR_MESSAGE, "open: wait_ready() failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = mode_select (s); if (status != SANE_STATUS_GOOD) { DBG (ERROR_MESSAGE, "sane_start: mode_select command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = scan_area_and_windows (s); if (status != SANE_STATUS_GOOD) { DBG (ERROR_MESSAGE, "open: set scan area command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = request_sense (s); if (status != SANE_STATUS_GOOD) { DBG (ERROR_MESSAGE, "sane_start: request_sense revealed error: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } s->scanning = SANE_TRUE; s->AbortedByUser = SANE_FALSE; status = start_scan (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; return SANE_STATUS_GOOD; stop_scanner_and_return: s->scanning = SANE_FALSE; s->AbortedByUser = SANE_FALSE; return status; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Apple_Scanner *s = handle; SANE_Status status; uint8_t get_data_status[10]; uint8_t read[10]; #ifdef RESERVE_RELEASE_HACK uint8_t reserve[6]; uint8_t release[6]; #endif uint8_t result[12]; size_t size; SANE_Int data_length = 0; SANE_Int data_av = 0; SANE_Int offset = 0; SANE_Int rread = 0; SANE_Bool Pseudo8bit = SANE_FALSE; #ifdef NEUTRALIZE_BACKEND *len=max_len; return SANE_STATUS_GOOD; #else *len = 0; if (!s->scanning) return SANE_STATUS_EOF; if (!strcmp (s->val[OPT_MODE].s, "Gray16")) Pseudo8bit = SANE_TRUE; /* TODO: The current function only implements for APPLESCANNER In order to use the COLORONESCANNER you have to study the docs to see how it the parameters get modified before scan. From this starting point it should be trivial to use a ONESCANNER int the gray256 mode but I don't have one from these pets in home. MF */ memset (get_data_status, 0, sizeof (get_data_status)); get_data_status[0] = APPLE_SCSI_GET_DATA_STATUS; get_data_status[1] = 1; /* Wait */ STORE24 (get_data_status + 6, sizeof (result)); memset (read, 0, sizeof (read)); read[0] = APPLE_SCSI_READ_SCANNED_DATA; #ifdef RESERVE_RELEASE_HACK memset (reserve, 0, sizeof (reserve)); reserve[0] = APPLE_SCSI_RESERVE; reserve[1]=CONTROLLER_SCSI_ID; reserve[1]=reserve[1] << 1; reserve[1]|=SETTHIRDPARTY; memset (release, 0, sizeof (release)); release[0] = APPLE_SCSI_RELEASE; release[1]=CONTROLLER_SCSI_ID; release[1]=reserve[1] << 1; release[1]|=SETTHIRDPARTY; #endif do { size = sizeof (result); status = sanei_scsi_cmd (s->fd, get_data_status, sizeof (get_data_status), result, &size); if (status != SANE_STATUS_GOOD) return status; if (!size) { DBG (ERROR_MESSAGE, "sane_read: cannot get_data_status.\n"); return SANE_STATUS_IO_ERROR; } data_length = READ24 (result); data_av = READ24 (result + 9); if (data_length) { /* if (result[3] & 1) Scanner Blocked: Retrieve data */ if ((result[3] & 1) || data_av) { DBG (IO_MESSAGE, "sane_read: (status) Available in scanner buffer %u.\n", data_av); if (Pseudo8bit) if ((data_av << 1) + offset > max_len) rread = (max_len - offset) >> 1; else rread = data_av; else if (data_av + offset > max_len) rread = max_len - offset; else rread = data_av; DBG (IO_MESSAGE, "sane_read: (action) Actual read request for %u bytes.\n", rread); size = rread; STORE24 (read + 6, rread); #ifdef RESERVE_RELEASE_HACK { SANE_Status status; DBG(IO_MESSAGE,"Reserving the SCSI bus.\n"); status=sanei_scsi_cmd (s->fd,reserve,sizeof(reserve),0,0); DBG(IO_MESSAGE,"Reserving... status:= %d\n",status); } #endif /* RESERVE_RELEASE_HACK */ status = sanei_scsi_cmd (s->fd, read, sizeof (read), buf + offset, &size); #ifdef RESERVE_RELEASE_HACK { SANE_Status status; DBG(IO_MESSAGE,"Releasing the SCSI bus.\n"); status=sanei_scsi_cmd (s->fd,release,sizeof(release),0,0); DBG(IO_MESSAGE,"Releasing... status:= %d\n",status); } #endif /* RESERVE_RELEASE_HACK */ if (Pseudo8bit) { SANE_Int byte; SANE_Int pos = offset + (rread << 1) - 1; SANE_Byte B; for (byte = offset + rread - 1; byte >= offset; byte--) { B = buf[byte]; buf[pos--] = 255 - (B << 4); /* low (right) nibble */ buf[pos--] = 255 - (B & 0xF0); /* high (left) nibble */ } offset += size << 1; } else offset += size; DBG (IO_MESSAGE, "sane_read: Buffer %u of %u full %g%%\n", offset, max_len, (double) (offset * 100. / max_len)); } } } while (offset < max_len && data_length != 0 && !s->AbortedByUser); if (s->AbortedByUser) { s->scanning = SANE_FALSE; status = sanei_scsi_cmd (s->fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); if (status != SANE_STATUS_GOOD) return status; return SANE_STATUS_CANCELLED; } if (!data_length) /* If not blocked */ { s->scanning = SANE_FALSE; DBG (IO_MESSAGE, "sane_read: (status) Oups! No more data..."); if (!offset) { *len = 0; DBG (IO_MESSAGE, "EOF\n"); return SANE_STATUS_EOF; } else { *len = offset; DBG (IO_MESSAGE, "GOOD\n"); return SANE_STATUS_GOOD; } } DBG (FLOW_CONTROL, "sane_read: Normal Exiting (?), Aborted=%u, data_length=%u\n", s->AbortedByUser, data_length); *len = offset; return SANE_STATUS_GOOD; #endif /* NEUTRALIZE_BACKEND */ } void sane_cancel (SANE_Handle handle) { Apple_Scanner *s = handle; if (s->scanning) { if (s->AbortedByUser) { DBG (FLOW_CONTROL, "sane_cancel: Already Aborted. Please Wait...\n"); } else { s->scanning=SANE_FALSE; s->AbortedByUser = SANE_TRUE; DBG (FLOW_CONTROL, "sane_cancel: Signal Caught! Aborting...\n"); } } else { if (s->AbortedByUser) { DBG (FLOW_CONTROL, "sane_cancel: Scan has not been Initiated yet, " "or it is already aborted.\n"); s->AbortedByUser = SANE_FALSE; sanei_scsi_cmd (s->fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); } else { DBG (FLOW_CONTROL, "sane_cancel: Scan has not been Initiated " "yet (or it's over).\n"); } } return; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (FLOW_CONTROL,"sane_set_io_mode: Entering.\n"); handle = handle; /* silence gcc */ if (non_blocking) { DBG (FLOW_CONTROL, "sane_set_io_mode: Don't call me please. " "Unimplemented function\n"); return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { handle = handle; /* silence gcc */ fd = fd; /* silence gcc */ DBG (FLOW_CONTROL, "sane_get_select_fd: Don't call me please. " "Unimplemented function\n"); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/pixma.c0000664000175000017500000014101013072310420014060 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2007-2008 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "../include/sane/config.h" #include #include #include #ifdef USE_PTHREAD # include #endif #include /* sigaction(POSIX) */ #include /* POSIX: write read close pipe */ #ifdef HAVE_FCNTL_H # include #endif #include "pixma_rename.h" #include "pixma.h" # define DEBUG_NOT_STATIC # include "../include/sane/sane.h" # include "../include/sane/sanei.h" # include "../include/sane/saneopts.h" # include "../include/sane/sanei_thread.h" # include "../include/sane/sanei_backend.h" # include "../include/sane/sanei_config.h" #ifdef NDEBUG # define PDBG(x) #else # define PDBG(x) IF_DBG(x) #endif /* NDEBUG */ #ifdef __GNUC__ # define UNUSED(v) (void) v #else # define UNUSED(v) #endif #define DECL_CTX pixma_sane_t *ss = check_handle(h) #define OPT_IN_CTX ss->opt #define SOD(opt) OPT_IN_CTX[opt].sod #define OVAL(opt) OPT_IN_CTX[opt].val #define AUTO_GAMMA 2.2 /* pixma_sane_options.h generated by * scripts/pixma_gen_options.py h < pixma.c > pixma_sane_options.h */ #include "pixma_sane_options.h" #define BUTTON_GROUP_SIZE ( opt_scan_resolution - opt_button_1 + 1 ) #define BUTTON_GROUP_INDEX(x) ( x - opt_button_1 ) typedef struct pixma_sane_t { struct pixma_sane_t *next; pixma_t *s; pixma_scan_param_t sp; SANE_Bool cancel; /* valid states: idle, !idle && scanning, !idle && !scanning */ SANE_Bool idle; SANE_Bool scanning; SANE_Status last_read_status; /* valid if !idle && !scanning */ option_descriptor_t opt[opt_last]; char button_option_is_cached[BUTTON_GROUP_SIZE]; SANE_Range xrange, yrange; SANE_Word dpi_list[9]; /* up to 9600 dpi */ SANE_String_Const mode_list[6]; pixma_scan_mode_t mode_map[6]; uint8_t gamma_table[4096]; SANE_String_Const source_list[4]; pixma_paper_source_t source_map[4]; unsigned byte_pos_in_line, output_line_size; uint64_t image_bytes_read; unsigned page_count; /* valid for ADF */ SANE_Pid reader_taskid; int wpipe, rpipe; SANE_Bool reader_stop; } pixma_sane_t; static const char vendor_str[] = "CANON"; static const char type_str[] = "multi-function peripheral"; static pixma_sane_t *first_scanner = NULL; static const SANE_Device **dev_list = NULL; static const char* conf_devices[MAX_CONF_DEVICES]; static void mark_all_button_options_cached ( struct pixma_sane_t * ss ) { int i; for (i = 0; i < (opt__group_5 - opt_button_1); i++ ) ss -> button_option_is_cached[i] = 1; } static SANE_Status config_attach_pixma(SANEI_Config * config, const char *devname) { int i; UNUSED(config); for (i=0; i < (MAX_CONF_DEVICES -1); i++) { if(conf_devices[i] == NULL) { conf_devices[i] = strdup(devname); return SANE_STATUS_GOOD; } } return SANE_STATUS_INVAL; } static SANE_Status map_error (int error) { if (error >= 0) return SANE_STATUS_GOOD; switch (error) { case PIXMA_ENOMEM: return SANE_STATUS_NO_MEM; case PIXMA_ECANCELED: return SANE_STATUS_CANCELLED; case PIXMA_EBUSY: return SANE_STATUS_DEVICE_BUSY; case PIXMA_EINVAL: return SANE_STATUS_INVAL; case PIXMA_EACCES: return SANE_STATUS_ACCESS_DENIED; case PIXMA_EPAPER_JAMMED: return SANE_STATUS_JAMMED; case PIXMA_ENO_PAPER: return SANE_STATUS_NO_DOCS; case PIXMA_ECOVER_OPEN: return SANE_STATUS_COVER_OPEN; case PIXMA_ENOTSUP: return SANE_STATUS_UNSUPPORTED; case PIXMA_EPROTO: case PIXMA_ENODEV: case PIXMA_EIO: case PIXMA_ETIMEDOUT: return SANE_STATUS_IO_ERROR; } PDBG (pixma_dbg (1, "BUG: unmapped error %d\n", error)); return SANE_STATUS_IO_ERROR; } static int getenv_atoi (const char *name, int def) { const char *str = getenv (name); return (str) ? atoi (str) : def; } #define CONST_CAST(t,x) (t)(x) static void free_block (const void * ptr) { free (CONST_CAST (void *, ptr)); } static void cleanup_device_list (void) { if (dev_list) { int i; for (i = 0; dev_list[i]; i++) { free_block ((const void *) dev_list[i]->name); free_block ((const void *) dev_list[i]->model); free_block ((const void *) dev_list[i]); } } free (dev_list); dev_list = NULL; } static void find_scanners (void) { unsigned i, nscanners; cleanup_device_list (); nscanners = pixma_find_scanners (conf_devices); PDBG (pixma_dbg (3, "pixma_find_scanners() found %u devices\n", nscanners)); dev_list = (const SANE_Device **) calloc (nscanners + 1, sizeof (*dev_list)); if (!dev_list) return; for (i = 0; i != nscanners; i++) { SANE_Device *sdev = (SANE_Device *) calloc (1, sizeof (*sdev)); char *name, *model; if (!sdev) goto nomem; name = strdup (pixma_get_device_id (i)); model = strdup (pixma_get_device_model (i)); if (!name || !model) { free (name); free (model); free (sdev); goto nomem; } sdev->name = name; sdev->model = model; sdev->vendor = vendor_str; sdev->type = type_str; dev_list[i] = sdev; } /* dev_list is already NULL terminated by calloc(). */ return; nomem: PDBG (pixma_dbg (1, "WARNING:not enough memory for device list\n")); return; } static pixma_sane_t * check_handle (SANE_Handle h) { pixma_sane_t *p; for (p = first_scanner; p && (SANE_Handle) p != h; p = p->next) { } return p; } static void update_button_state (pixma_sane_t * ss, SANE_Int * info) { SANE_Int b1 = OVAL (opt_button_1).w; SANE_Int b2 = OVAL (opt_button_2).w; uint32_t ev = pixma_wait_event (ss->s, 300); switch (ev & ~PIXMA_EV_ACTION_MASK) { case PIXMA_EV_BUTTON1: b1 = 1; break; case PIXMA_EV_BUTTON2: b2 = 1; break; } if (b1 != OVAL (opt_button_1).w || b2 != OVAL (opt_button_2).w) { *info |= SANE_INFO_RELOAD_OPTIONS; OVAL (opt_button_1).w = b1; OVAL (opt_button_2).w = b2; OVAL (opt_original).w = GET_EV_ORIGINAL(ev); OVAL (opt_target).w = GET_EV_TARGET(ev); OVAL (opt_scan_resolution).w = GET_EV_DPI(ev); } mark_all_button_options_cached(ss); } static SANE_Bool enable_option (pixma_sane_t * ss, SANE_Int o, SANE_Bool enable) { SANE_Word save = SOD (o).cap; if (enable) SOD (o).cap &= ~SANE_CAP_INACTIVE; else SOD (o).cap |= SANE_CAP_INACTIVE; return (save != SOD (o).cap); } static void clamp_value (pixma_sane_t * ss, SANE_Int n, void *v, SANE_Int * info) { SANE_Option_Descriptor *sod = &SOD (n); SANE_Word *va = (SANE_Word *) v; const SANE_Range *range = sod->constraint.range; int i, nmemb; nmemb = sod->size / sizeof (SANE_Word); for (i = 0; i < nmemb; i++) { SANE_Word value = va[i]; if (value < range->min) { value = range->min; } else if (value > range->max) { value = range->max; } if (range->quant != 0) { value = (value - range->min + range->quant / 2) / range->quant * range->quant; } if (value != va[i]) { va[i] = value; *info |= SANE_INFO_INEXACT; } } } /* create dynamic mode_list * ss: scanner device * tpu = 0: flatbed or ADF mode * 1 bit lineart, 8 bit grayscale and 24 bit color scans * tpu = 1: TPU mode * 16 bit grayscale and 48 bit color scans */ static void create_mode_list (pixma_sane_t * ss) { SANE_Bool tpu; const pixma_config_t *cfg; int i; cfg = pixma_get_config (ss->s); tpu = (ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_TPU); /* setup available mode */ i = 0; ss->mode_list[i] = SANE_VALUE_SCAN_MODE_COLOR; ss->mode_map[i] = PIXMA_SCAN_MODE_COLOR; i++; if (cfg->cap & PIXMA_CAP_GRAY) { ss->mode_list[i] = SANE_VALUE_SCAN_MODE_GRAY; ss->mode_map[i] = PIXMA_SCAN_MODE_GRAY; i++; } if (tpu && (cfg->cap & PIXMA_CAP_NEGATIVE)) { ss->mode_list[i] = SANE_I18N ("Negative color"); ss->mode_map[i] = PIXMA_SCAN_MODE_NEGATIVE_COLOR; i++; if (cfg->cap & PIXMA_CAP_GRAY) { ss->mode_list[i] = SANE_I18N ("Negative gray"); ss->mode_map[i] = PIXMA_SCAN_MODE_NEGATIVE_GRAY; i++; } } if (tpu && (cfg->cap & PIXMA_CAP_TPUIR) == PIXMA_CAP_TPUIR) { ss->mode_list[i] = SANE_I18N ("Infrared"); ss->mode_map[i] = PIXMA_SCAN_MODE_TPUIR; i++; } if (!tpu && (cfg->cap & PIXMA_CAP_48BIT)) { ss->mode_list[i] = SANE_I18N ("48 bits color"); ss->mode_map[i] = PIXMA_SCAN_MODE_COLOR_48; i++; if (cfg->cap & PIXMA_CAP_GRAY) { ss->mode_list[i] = SANE_I18N ("16 bits gray"); ss->mode_map[i] = PIXMA_SCAN_MODE_GRAY_16; i++; } } if (!tpu && (cfg->cap & PIXMA_CAP_LINEART)) { ss->mode_list[i] = SANE_VALUE_SCAN_MODE_LINEART; ss->mode_map[i] = PIXMA_SCAN_MODE_LINEART; i++; } /* terminate mode_list and mode_map */ ss->mode_list[i] = 0; ss->mode_map[i] = 0; } /* create dynamic dpi_list * ss: scanner device */ static void create_dpi_list (pixma_sane_t * ss) { const pixma_config_t *cfg; int i, j; int min; unsigned min_dpi; unsigned max_dpi; cfg = pixma_get_config (ss->s); /* get min/max dpi */ max_dpi = cfg->xdpi; min_dpi = 75; if (ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_TPU && ss->mode_map[OVAL (opt_mode).w] == PIXMA_SCAN_MODE_TPUIR) { /* IR mode */ /*PDBG (pixma_dbg (4, "*create_dpi_list***** TPUIR mode\n"));*/ min_dpi = (cfg->tpuir_min_dpi) ? cfg->tpuir_min_dpi : 75; max_dpi = (cfg->tpuir_max_dpi) ? cfg->tpuir_max_dpi : cfg->xdpi; } else if (ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_TPU || ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_ADF || ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_ADFDUP) { /* ADF / TPU mode */ /*PDBG (pixma_dbg (4, "*create_dpi_list***** ADF/TPU mode\n"));*/ min_dpi = (cfg->adftpu_min_dpi) ? cfg->adftpu_min_dpi : 75; max_dpi = (cfg->adftpu_max_dpi) ? cfg->adftpu_max_dpi : cfg->xdpi; } else if (ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_FLATBED && (ss->mode_map[OVAL (opt_mode).w] == PIXMA_SCAN_MODE_COLOR_48 || ss->mode_map[OVAL (opt_mode).w] == PIXMA_SCAN_MODE_GRAY_16)) { /* 48 bits flatbed */ /*PDBG (pixma_dbg (4, "*create_dpi_list***** 48 bits flatbed mode\n"));*/ min_dpi = 150; } /* set j for min. dpi * 75 dpi: j = 0 * 150 dpi: j = 1 \ * 300 dpi: j = 2 |--> from cfg->adftpu_min_dpi or cfg->tpuir_min_dpi * 600 dpi: j = 3 / * */ j = -1; min = min_dpi / 75; do { j++; min >>= 1; } while (min > 0); /* create dpi_list * use j for min. dpi */ i = 0; do { i++; j++; ss->dpi_list[i] = 75 * (1 << (j - 1)); /* 75 x 2^(j-1) */ } while ((unsigned) ss->dpi_list[i] < max_dpi); ss->dpi_list[0] = i; /*PDBG (pixma_dbg (4, "*create_dpi_list***** min_dpi = %d, max_dpi = %d\n", min_dpi, max_dpi));*/ } static void select_value_from_list (pixma_sane_t * ss, SANE_Int n, void *v, SANE_Int * info) { SANE_Option_Descriptor *sod = &SOD (n); SANE_Word *va = (SANE_Word *) v; const SANE_Word *list = sod->constraint.word_list; int i, j, nmemb; nmemb = sod->size / sizeof (SANE_Word); for (i = 0; i < nmemb; i++) { SANE_Word value = va[i]; SANE_Word mindelta = abs (value - list[1]); SANE_Word nearest = list[1]; for (j = 2; j <= list[0]; j++) { SANE_Word delta = abs (value - list[j]); if (delta < mindelta) { mindelta = delta; nearest = list[j]; } if (mindelta == 0) break; } if (va[i] != nearest) { va[i] = nearest; *info |= SANE_INFO_INEXACT; } } } static SANE_Status control_scalar_option (pixma_sane_t * ss, SANE_Int n, SANE_Action a, void *v, SANE_Int * info) { option_descriptor_t *opt = &(OPT_IN_CTX[n]); SANE_Word val; switch (a) { case SANE_ACTION_GET_VALUE: switch (opt->sod.type) { case SANE_TYPE_BOOL: case SANE_TYPE_INT: case SANE_TYPE_FIXED: *(SANE_Word *) v = opt->val.w; break; default: return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; case SANE_ACTION_SET_VALUE: switch (opt->sod.type) { case SANE_TYPE_BOOL: val = *(SANE_Word *) v; if (val != SANE_TRUE && val != SANE_FALSE) return SANE_STATUS_INVAL; opt->val.w = val; break; case SANE_TYPE_INT: case SANE_TYPE_FIXED: if (opt->sod.constraint_type == SANE_CONSTRAINT_RANGE) clamp_value (ss, n, v, info); else if (opt->sod.constraint_type == SANE_CONSTRAINT_WORD_LIST) select_value_from_list (ss, n, v, info); opt->val.w = *(SANE_Word *) v; break; default: return SANE_STATUS_UNSUPPORTED; } *info |= opt->info; return SANE_STATUS_GOOD; case SANE_ACTION_SET_AUTO: switch (opt->sod.type) { case SANE_TYPE_BOOL: case SANE_TYPE_INT: case SANE_TYPE_FIXED: opt->val.w = opt->def.w; break; default: return SANE_STATUS_UNSUPPORTED; } *info |= opt->info; return SANE_STATUS_GOOD; } return SANE_STATUS_UNSUPPORTED; } static SANE_Status control_string_option (pixma_sane_t * ss, SANE_Int n, SANE_Action a, void *v, SANE_Int * info) { option_descriptor_t *opt = &(OPT_IN_CTX[n]); const SANE_String_Const *slist = opt->sod.constraint.string_list; SANE_String str = (SANE_String) v; if (opt->sod.constraint_type == SANE_CONSTRAINT_NONE) { switch (a) { case SANE_ACTION_GET_VALUE: strcpy (str, opt->val.s); break; case SANE_ACTION_SET_AUTO: str = opt->def.s; /* fall through */ case SANE_ACTION_SET_VALUE: strncpy (opt->val.s, str, opt->sod.size - 1); *info |= opt->info; break; } return SANE_STATUS_GOOD; } else { int i; switch (a) { case SANE_ACTION_GET_VALUE: strcpy (str, slist[opt->val.w]); break; case SANE_ACTION_SET_AUTO: str = opt->def.ptr; /* fall through */ case SANE_ACTION_SET_VALUE: i = 0; while (slist[i] && strcasecmp (str, slist[i]) != 0) i++; if (!slist[i]) return SANE_STATUS_INVAL; if (strcmp (slist[i], str) != 0) { strcpy (str, slist[i]); *info |= SANE_INFO_INEXACT; } opt->val.w = i; *info |= opt->info; break; } return SANE_STATUS_GOOD; } } static SANE_Status control_option (pixma_sane_t * ss, SANE_Int n, SANE_Action a, void *v, SANE_Int * info) { int result, i; const pixma_config_t *cfg; SANE_Int dummy; /* info may be null, better to set a dummy here then test everywhere */ if (info == NULL) info = &dummy; cfg = pixma_get_config (ss->s); /* PDBG (pixma_dbg (4, "*control_option***** n = %u, a = %u\n", n, a)); */ /* first deal with options that require special treatment */ result = SANE_STATUS_UNSUPPORTED; switch (n) { case opt_gamma_table: switch (a) { case SANE_ACTION_SET_VALUE: clamp_value (ss, n, v, info); for (i = 0; i != 4096; i++) ss->gamma_table[i] = *((SANE_Int *) v + i); break; case SANE_ACTION_GET_VALUE: for (i = 0; i != 4096; i++) *((SANE_Int *) v + i) = ss->gamma_table[i]; break; case SANE_ACTION_SET_AUTO: pixma_fill_gamma_table (AUTO_GAMMA, ss->gamma_table, sizeof (ss->gamma_table)); break; default: return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; case opt_button_update: if (a == SANE_ACTION_SET_VALUE) { update_button_state (ss, info); return SANE_STATUS_GOOD; } else { return SANE_STATUS_INVAL; } break; case opt_button_1: case opt_button_2: case opt_original: case opt_target: case opt_scan_resolution: /* poll scanner if option is not cached */ if (! ss->button_option_is_cached[ BUTTON_GROUP_INDEX(n) ] ) update_button_state (ss, info); /* mark this option as read */ ss->button_option_is_cached[ BUTTON_GROUP_INDEX(n) ] = 0; } /* now deal with getting and setting of options */ switch (SOD (n).type) { case SANE_TYPE_BOOL: case SANE_TYPE_INT: case SANE_TYPE_FIXED: result = control_scalar_option (ss, n, a, v, info); break; case SANE_TYPE_STRING: result = control_string_option (ss, n, a, v, info); break; case SANE_TYPE_BUTTON: case SANE_TYPE_GROUP: PDBG (pixma_dbg (1, "BUG:control_option():Unhandled option\n")); result = SANE_STATUS_INVAL; break; } if (result != SANE_STATUS_GOOD) return result; /* deal with dependencies between options */ switch (n) { case opt_custom_gamma: if (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO) { if (enable_option (ss, opt_gamma_table, OVAL (opt_custom_gamma).b)) *info |= SANE_INFO_RELOAD_OPTIONS; } break; case opt_gamma: if (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO) { /* PDBG (pixma_dbg (4, "*control_option***** gamma = %f *\n", SANE_UNFIX (OVAL (opt_gamma).w))); */ pixma_fill_gamma_table (SANE_UNFIX (OVAL (opt_gamma).w), ss->gamma_table, sizeof (ss->gamma_table)); } break; case opt_mode: if (cfg->cap & (PIXMA_CAP_48BIT|PIXMA_CAP_LINEART|PIXMA_CAP_TPUIR) && (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO)) { /* new mode selected: Color, Gray, ... */ /* PDBG (pixma_dbg (4, "*control_option***** mode = %u *\n", ss->mode_map[OVAL (opt_mode).w])); */ /* recreate dynamic lists */ create_dpi_list (ss); if (ss->mode_map[OVAL (opt_mode).w] == PIXMA_SCAN_MODE_LINEART) { /* lineart */ enable_option (ss, opt_threshold, SANE_TRUE); enable_option (ss, opt_threshold_curve, SANE_TRUE); } else { /* all other modes */ enable_option (ss, opt_threshold, SANE_FALSE); enable_option (ss, opt_threshold_curve, SANE_FALSE); } *info |= SANE_INFO_RELOAD_OPTIONS; } break; case opt_source: if ((cfg->cap & (PIXMA_CAP_ADF|PIXMA_CAP_ADFDUP|PIXMA_CAP_TPU)) && (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO)) { /* new source selected: flatbed, ADF, TPU, ... */ /* to avoid fatal errors, * select first entry of dynamic mode_list * identifiers are unknown here */ OVAL (opt_mode).w = ss->mode_map[0]; /* recreate dynamic lists */ create_mode_list (ss); create_dpi_list (ss); /* to avoid fatal errors, * select first entry of dynamic dpi_list * identifiers are unknown here */ OVAL (opt_resolution).w = ss->dpi_list[1]; if (ss->mode_map[OVAL (opt_mode).w] == PIXMA_SCAN_MODE_LINEART) { /* lineart */ enable_option (ss, opt_threshold, SANE_TRUE); enable_option (ss, opt_threshold_curve, SANE_TRUE); } else { /* all other modes */ enable_option (ss, opt_threshold, SANE_FALSE); enable_option (ss, opt_threshold_curve, SANE_FALSE); } if (cfg->cap & (PIXMA_CAP_ADF_WAIT)) { /* adf-wait */ enable_option (ss, opt_adf_wait, SANE_TRUE); } else { /* disable adf-wait */ enable_option (ss, opt_adf_wait, SANE_FALSE); } *info |= SANE_INFO_RELOAD_OPTIONS; } break; } return result; } #ifndef NDEBUG static void print_scan_param (int level, const pixma_scan_param_t * sp) { pixma_dbg (level, "Scan parameters\n"); pixma_dbg (level, " line_size=%"PRIu64" image_size=%"PRIu64" channels=%u depth=%u\n", sp->line_size, sp->image_size, sp->channels, sp->depth); pixma_dbg (level, " dpi=%ux%u offset=(%u,%u) dimension=%ux%u\n", sp->xdpi, sp->ydpi, sp->x, sp->y, sp->w, sp->h); pixma_dbg (level, " gamma_table=%p source=%d\n", sp->gamma_table, sp->source); pixma_dbg (level, " adf-wait=%d\n", sp->adf_wait); } #endif static int calc_scan_param (pixma_sane_t * ss, pixma_scan_param_t * sp) { int x1, y1, x2, y2; int error; memset (sp, 0, sizeof (*sp)); sp->channels = (OVAL (opt_mode).w == 0) ? 3 : 1; sp->depth = (OVAL (opt_mode).w == 2) ? 1 : 8; sp->xdpi = sp->ydpi = OVAL (opt_resolution).w; #define PIXEL(x,dpi) (int)((SANE_UNFIX(x) / 25.4 * (dpi)) + 0.5) x1 = PIXEL (OVAL (opt_tl_x).w, sp->xdpi); x2 = PIXEL (OVAL (opt_br_x).w, sp->xdpi); if (x2 < x1) { int temp = x1; x1 = x2; x2 = temp; } y1 = PIXEL (OVAL (opt_tl_y).w, sp->ydpi); y2 = PIXEL (OVAL (opt_br_y).w, sp->ydpi); if (y2 < y1) { int temp = y1; y1 = y2; y2 = temp; } #undef PIXEL sp->x = x1; sp->y = y1; sp->w = x2 - x1; sp->h = y2 - y1; if (sp->w == 0) sp->w = 1; if (sp->h == 0) sp->h = 1; sp->tpu_offset_added = 0; sp->gamma_table = (OVAL (opt_custom_gamma).b) ? ss->gamma_table : NULL; sp->source = ss->source_map[OVAL (opt_source).w]; sp->mode = ss->mode_map[OVAL (opt_mode).w]; sp->adf_pageid = ss->page_count; sp->threshold = 2.55 * OVAL (opt_threshold).w; sp->threshold_curve = OVAL (opt_threshold_curve).w; sp->adf_wait = OVAL (opt_adf_wait).w; error = pixma_check_scan_param (ss->s, sp); if (error < 0) { PDBG (pixma_dbg (1, "BUG:calc_scan_param() failed %d\n", error)); PDBG (print_scan_param (1, sp)); } return error; } static void init_option_descriptors (pixma_sane_t * ss) { const pixma_config_t *cfg; int i; cfg = pixma_get_config (ss->s); /* setup range for the scan area. */ ss->xrange.min = SANE_FIX (0); ss->xrange.max = SANE_FIX (cfg->width / 75.0 * 25.4); ss->xrange.quant = SANE_FIX (0); ss->yrange.min = SANE_FIX (0); ss->yrange.max = SANE_FIX (cfg->height / 75.0 * 25.4); ss->yrange.quant = SANE_FIX (0); /* mode_list and source_list were already NULL-terminated, * because the whole pixma_sane_t was cleared during allocation. */ /* setup available mode. */ create_mode_list (ss); /* setup dpi up to the value supported by the scanner. */ create_dpi_list (ss); /* setup paper source */ i = 0; ss->source_list[i] = SANE_I18N ("Flatbed"); ss->source_map[i] = PIXMA_SOURCE_FLATBED; i++; if (cfg->cap & PIXMA_CAP_ADF) { ss->source_list[i] = SANE_I18N ("Automatic Document Feeder"); ss->source_map[i] = PIXMA_SOURCE_ADF; i++; } if ((cfg->cap & PIXMA_CAP_ADFDUP) == PIXMA_CAP_ADFDUP) { ss->source_list[i] = SANE_I18N ("ADF Duplex"); ss->source_map[i] = PIXMA_SOURCE_ADFDUP; i++; } if (cfg->cap & PIXMA_CAP_TPU) { ss->source_list[i] = SANE_I18N ("Transparency Unit"); ss->source_map[i] = PIXMA_SOURCE_TPU; i++; } build_option_descriptors (ss); /* Enable options that are available only in some scanners. */ if (cfg->cap & PIXMA_CAP_GAMMA_TABLE) { enable_option (ss, opt_gamma, SANE_TRUE); enable_option (ss, opt_custom_gamma, SANE_TRUE); sane_control_option (ss, opt_custom_gamma, SANE_ACTION_SET_AUTO, NULL, NULL); pixma_fill_gamma_table (AUTO_GAMMA, ss->gamma_table, 4096); } enable_option (ss, opt_button_controlled, ((cfg->cap & PIXMA_CAP_EVENTS) != 0)); } /* Writing to reader_ss outside reader_process() is a BUG! */ static pixma_sane_t *reader_ss = NULL; static void reader_signal_handler (int sig) { if (reader_ss) { reader_ss->reader_stop = SANE_TRUE; /* reader process is ended by SIGTERM, so no cancel in this case */ if (sig != SIGTERM) pixma_cancel (reader_ss->s); } } static int write_all (pixma_sane_t * ss, void *buf_, size_t size) { uint8_t *buf = (uint8_t *) buf_; int count; while (size != 0 && !ss->reader_stop) { count = write (ss->wpipe, buf, size); if (count == -1 && errno != EINTR) break; if (count == -1 && errno == EINTR) continue; buf += count; size -= count; } return buf - (uint8_t *) buf_; } /* NOTE: reader_loop() runs either in a separate thread or process. */ static SANE_Status reader_loop (pixma_sane_t * ss) { void *buf; unsigned bufsize; int count = 0; PDBG (pixma_dbg (3, "Reader task started\n")); /*bufsize = ss->sp.line_size + 1;*/ /* XXX: "odd" bufsize for testing pixma_read_image() */ bufsize = ss->sp.line_size; /* bufsize EVEN needed by Xsane for 48 bits depth */ buf = malloc (bufsize); if (!buf) { count = PIXMA_ENOMEM; goto done; } count = pixma_activate_connection (ss->s); if (count < 0) goto done; pixma_enable_background (ss->s, 1); if (OVAL (opt_button_controlled).b && ss->page_count == 0) { int start = 0; #ifndef NDEBUG pixma_dbg (1, "==== Button-controlled scan mode is enabled.\n"); pixma_dbg (1, "==== To proceed, press 'SCAN' or 'COLOR' button. " "To cancel, press 'GRAY' or 'END' button.\n"); #endif while (pixma_wait_event (ss->s, 10) != 0) { } while (!start) { uint32_t events; if (ss->reader_stop) { count = PIXMA_ECANCELED; goto done; } events = pixma_wait_event (ss->s, 1000); switch (events & ~PIXMA_EV_ACTION_MASK) { case PIXMA_EV_BUTTON1: start = 1; break; case PIXMA_EV_BUTTON2: count = PIXMA_ECANCELED; goto done; } } } count = pixma_scan (ss->s, &ss->sp); if (count >= 0) { while ((count = pixma_read_image (ss->s, buf, bufsize)) > 0) { if (write_all (ss, buf, count) != count) pixma_cancel (ss->s); } } done: pixma_enable_background (ss->s, 0); pixma_deactivate_connection (ss->s); free (buf); close (ss->wpipe); ss->wpipe = -1; if (count >= 0) { PDBG (pixma_dbg (3, "Reader task terminated\n")); } else { PDBG (pixma_dbg (2, "Reader task terminated: %s\n", pixma_strerror (count))); } return map_error (count); } static int reader_process (void *arg) { pixma_sane_t *ss = (pixma_sane_t *) arg; struct SIGACTION sa; reader_ss = ss; memset (&sa, 0, sizeof (sa)); sigemptyset (&sa.sa_mask); sa.sa_handler = reader_signal_handler; /* FIXME: which signal else? */ sigaction (SIGHUP, &sa, NULL); sigaction (SIGINT, &sa, NULL); sigaction (SIGPIPE, &sa, NULL); sigaction (SIGTERM, &sa, NULL); close (ss->rpipe); ss->rpipe = -1; return reader_loop (ss); } static int reader_thread (void *arg) { pixma_sane_t *ss = (pixma_sane_t *) arg; #ifdef USE_PTHREAD /* Block SIGPIPE. We will handle this in reader_loop() by checking ss->reader_stop and the return value from write(). */ sigset_t sigs; sigemptyset (&sigs); sigaddset (&sigs, SIGPIPE); pthread_sigmask (SIG_BLOCK, &sigs, NULL); #endif /* USE_PTHREAD */ return reader_loop (ss); } static SANE_Pid terminate_reader_task (pixma_sane_t * ss, int *exit_code) { SANE_Pid result, pid; int status = 0; pid = ss->reader_taskid; if (!sanei_thread_is_valid (pid)) return -1; if (sanei_thread_is_forked ()) { sanei_thread_kill (pid); } else { ss->reader_stop = SANE_TRUE; /* pixma_cancel (ss->s); What is this for ? Makes end-of-scan buggy => removing */ } result = sanei_thread_waitpid (pid, &status); ss->reader_taskid = -1; if (ss->sp.source != PIXMA_SOURCE_ADF && ss->sp.source != PIXMA_SOURCE_ADFDUP) ss->idle = SANE_TRUE; if (result == pid) { if (exit_code) *exit_code = status; return pid; } else { PDBG (pixma_dbg (1, "WARNING:waitpid() failed %s\n", strerror (errno))); return -1; } } static int start_reader_task (pixma_sane_t * ss) { int fds[2]; SANE_Pid pid; int is_forked; if (ss->rpipe != -1 || ss->wpipe != -1) { PDBG (pixma_dbg (1, "BUG:rpipe = %d, wpipe = %d\n", ss->rpipe, ss->wpipe)); close (ss->rpipe); close (ss->wpipe); ss->rpipe = -1; ss->wpipe = -1; } if (sanei_thread_is_valid (ss->reader_taskid)) { PDBG (pixma_dbg (1, "BUG:reader_taskid(%ld) != -1\n", (long) ss->reader_taskid)); terminate_reader_task (ss, NULL); } if (pipe (fds) == -1) { PDBG (pixma_dbg (1, "ERROR:start_reader_task():pipe() failed %s\n", strerror (errno))); return PIXMA_ENOMEM; } ss->rpipe = fds[0]; ss->wpipe = fds[1]; ss->reader_stop = SANE_FALSE; is_forked = sanei_thread_is_forked (); if (is_forked) { pid = sanei_thread_begin (reader_process, ss); if (pid > 0) { close (ss->wpipe); ss->wpipe = -1; } } else { pid = sanei_thread_begin (reader_thread, ss); } if (!sanei_thread_is_valid (pid)) { close (ss->wpipe); close (ss->rpipe); ss->wpipe = -1; ss->rpipe = -1; PDBG (pixma_dbg (1, "ERROR:unable to start reader task\n")); return PIXMA_ENOMEM; } PDBG (pixma_dbg (3, "Reader task id=%ld (%s)\n", (long) pid, (is_forked) ? "forked" : "threaded")); ss->reader_taskid = pid; return 0; } static SANE_Status read_image (pixma_sane_t * ss, void *buf, unsigned size, int *readlen) { int count, status; if (readlen) *readlen = 0; if (ss->image_bytes_read >= ss->sp.image_size) return SANE_STATUS_EOF; do { if (ss->cancel) /* ss->rpipe has already been closed by sane_cancel(). */ return SANE_STATUS_CANCELLED; count = read (ss->rpipe, buf, size); } while (count == -1 && errno == EINTR); if (count == -1) { if (errno == EAGAIN) return SANE_STATUS_GOOD; if (!ss->cancel) { PDBG (pixma_dbg (1, "WARNING:read_image():read() failed %s\n", strerror (errno))); } close (ss->rpipe); ss->rpipe = -1; terminate_reader_task (ss, NULL); return SANE_STATUS_IO_ERROR; } /* here count >= 0 */ ss->image_bytes_read += count; if (ss->image_bytes_read > ss->sp.image_size) { PDBG (pixma_dbg (1, "BUG:ss->image_bytes_read > ss->sp.image_size\n")); } if (ss->image_bytes_read >= ss->sp.image_size) { close (ss->rpipe); ss->rpipe = -1; terminate_reader_task (ss, NULL); } else if (count == 0) { PDBG (pixma_dbg (3, "read_image():reader task closed the pipe:%" PRIu64" bytes received, %"PRIu64" bytes expected\n", ss->image_bytes_read, ss->sp.image_size)); close (ss->rpipe); ss->rpipe = -1; if (sanei_thread_is_valid (terminate_reader_task (ss, &status)) && status != SANE_STATUS_GOOD) { return status; } else { /* either terminate_reader_task failed or rpipe was closed but we expect more data */ return SANE_STATUS_IO_ERROR; } } if (readlen) *readlen = count; return SANE_STATUS_GOOD; } /******************************************************************* ** SANE API *******************************************************************/ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { int status, myversion, i; SANEI_Config config; UNUSED (authorize); if (!version_code) return SANE_STATUS_INVAL; myversion = 100 * PIXMA_VERSION_MAJOR + PIXMA_VERSION_MINOR; *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, myversion); DBG_INIT (); sanei_thread_init (); pixma_set_debug_level (DBG_LEVEL); PDBG(pixma_dbg(2, "pixma is compiled %s pthread support.\n", (sanei_thread_is_forked () ? "without" : "with"))); for (i = 0; i < MAX_CONF_DEVICES; i++) conf_devices[i] = NULL; config.count = 0; config.descriptors = NULL; config.values = NULL; if (sanei_configure_attach(PIXMA_CONFIG_FILE, &config, config_attach_pixma) != SANE_STATUS_GOOD) PDBG(pixma_dbg(2, "Could not read pixma configuration file: %s\n", PIXMA_CONFIG_FILE)); status = pixma_init (); if (status < 0) { PDBG (pixma_dbg (2, "pixma_init() failed %s\n", pixma_strerror (status))); } return map_error (status); } void sane_exit (void) { while (first_scanner) sane_close (first_scanner); cleanup_device_list (); pixma_cleanup (); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { UNUSED (local_only); if (!device_list) return SANE_STATUS_INVAL; find_scanners (); *device_list = dev_list; return (dev_list) ? SANE_STATUS_GOOD : SANE_STATUS_NO_MEM; } SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h) { unsigned i, j, nscanners; int error = 0; pixma_sane_t *ss = NULL; const pixma_config_t *cfg; if (!name || !h) return SANE_STATUS_INVAL; *h = NULL; nscanners = pixma_find_scanners (conf_devices); if (nscanners == 0) return SANE_STATUS_INVAL; if (name[0] == '\0') name = pixma_get_device_id (0); /* Have we already opened the scanner? */ for (ss = first_scanner; ss; ss = ss->next) { if (strcmp (pixma_get_string (ss->s, PIXMA_STRING_ID), name) == 0) { /* We have already opened it! */ return SANE_STATUS_DEVICE_BUSY; } } i = 0; while (strcmp (pixma_get_device_id (i), name) != 0) { if (++i >= nscanners) return SANE_STATUS_INVAL; } cfg = pixma_get_device_config (i); if ((cfg->cap & PIXMA_CAP_EXPERIMENT) != 0) { #ifndef NDEBUG pixma_dbg (1, "WARNING:" "Experimental backend CAN DAMAGE your hardware!\n"); if (getenv_atoi ("PIXMA_EXPERIMENT", 0) == 0) { pixma_dbg (1, "Experimental SANE backend for %s is disabled " "by default.\n", pixma_get_device_model (i)); pixma_dbg (1, "To enable it, set the environment variable " "PIXMA_EXPERIMENT to non-zero.\n"); return SANE_STATUS_UNSUPPORTED; } #else return SANE_STATUS_UNSUPPORTED; #endif } ss = (pixma_sane_t *) calloc (1, sizeof (*ss)); if (!ss) return SANE_STATUS_NO_MEM; ss->next = first_scanner; first_scanner = ss; ss->reader_taskid = -1; ss->wpipe = -1; ss->rpipe = -1; ss->idle = SANE_TRUE; ss->scanning = SANE_FALSE; ss->sp.frontend_cancel = SANE_FALSE; for (j=0; j < BUTTON_GROUP_SIZE; j++) ss->button_option_is_cached[j] = 0; error = pixma_open (i, &ss->s); if (error < 0) { sane_close (ss); return map_error (error); } pixma_enable_background (ss->s, 0); init_option_descriptors (ss); *h = ss; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle h) { pixma_sane_t **p, *ss; for (p = &first_scanner; *p && *p != (pixma_sane_t *) h; p = &((*p)->next)) { } if (!(*p)) return; ss = *p; sane_cancel (ss); pixma_close (ss->s); *p = ss->next; free (ss); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int n) { DECL_CTX; if (ss && 0 <= n && n < opt_last) return &SOD (n); return NULL; } SANE_Status sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int * i) { DECL_CTX; SANE_Int info = 0; int error; option_descriptor_t *opt; if (i) *i = 0; if (!ss) return SANE_STATUS_INVAL; if (n < 0 || n >= opt_last) return SANE_STATUS_UNSUPPORTED; if (!ss->idle && a != SANE_ACTION_GET_VALUE) { PDBG (pixma_dbg (3, "Warning: !idle && !SANE_ACTION_GET_VALUE\n")); if (ss->sp.source != PIXMA_SOURCE_ADF && ss->sp.source != PIXMA_SOURCE_ADFDUP) return SANE_STATUS_INVAL; } opt = &(OPT_IN_CTX[n]); if (!SANE_OPTION_IS_ACTIVE (opt->sod.cap)) return SANE_STATUS_INVAL; switch (a) { case SANE_ACTION_SET_VALUE: if ((opt->sod.type != SANE_TYPE_BUTTON && !v) || !SANE_OPTION_IS_SETTABLE (opt->sod.cap)) return SANE_STATUS_INVAL; /* or _UNSUPPORTED? */ break; case SANE_ACTION_SET_AUTO: if (!(opt->sod.cap & SANE_CAP_AUTOMATIC) || !SANE_OPTION_IS_SETTABLE (opt->sod.cap)) return SANE_STATUS_INVAL; /* or _UNSUPPORTED? */ break; case SANE_ACTION_GET_VALUE: if (!v || !(opt->sod.cap & SANE_CAP_SOFT_DETECT)) return SANE_STATUS_INVAL; /* or _UNSUPPORTED? */ break; default: return SANE_STATUS_UNSUPPORTED; } error = control_option (ss, n, a, v, &info); if (error == SANE_STATUS_GOOD && i) *i = info; return error; } SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p) { DECL_CTX; pixma_scan_param_t temp, *sp; if (!ss || !p) return SANE_STATUS_INVAL; if (!ss->idle) { sp = &ss->sp; /* sp is calculated in sane_start() */ } else { calc_scan_param (ss, &temp); sp = &temp; } p->format = (sp->channels == 3) ? SANE_FRAME_RGB : SANE_FRAME_GRAY; p->last_frame = SANE_TRUE; p->lines = sp->h; p->depth = sp->depth; p->pixels_per_line = sp->w; /* p->bytes_per_line = sp->line_size; NOTE: It should work this way, but it doesn't. No SANE frontend can cope with this. */ p->bytes_per_line = (sp->w * sp->channels * sp->depth) / 8; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle h) { DECL_CTX; int error = 0; if (!ss) return SANE_STATUS_INVAL; if (!ss->idle && ss->scanning) { PDBG (pixma_dbg (3, "Warning in Sane_start: !idle && scanning. idle=%d, ss->scanning=%d\n", ss->idle, ss->scanning)); if (ss->sp.source != PIXMA_SOURCE_ADF && ss->sp.source != PIXMA_SOURCE_ADFDUP) return SANE_STATUS_INVAL; } ss->cancel = SANE_FALSE; if (ss->idle || ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_FLATBED || ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_TPU) ss->page_count = 0; /* start from idle state or scan from flatbed or TPU */ else ss->page_count++; if (calc_scan_param (ss, &ss->sp) < 0) return SANE_STATUS_INVAL; ss->image_bytes_read = 0; /* TODO: Check paper here in sane_start(). A function like pixma_get_status() is needed. */ error = start_reader_task (ss); if (error >= 0) { ss->output_line_size = (ss->sp.w * ss->sp.channels * ss->sp.depth) / 8; ss->byte_pos_in_line = 0; ss->last_read_status = SANE_STATUS_GOOD; ss->scanning = SANE_TRUE; ss->idle = SANE_FALSE; } return map_error (error); } SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) { DECL_CTX; int sum, n; /* Due to 32 pixels alignment, sizeof(temp) is to be greater than: * max(nchannels) * max (sp.line_size - output_line_size) * so currently: 3 * 32 = 96 for better end line cropping efficiency */ SANE_Byte temp[100]; SANE_Status status; if (len) *len = 0; if (!ss || !buf || !len) return SANE_STATUS_INVAL; if (ss->cancel) return SANE_STATUS_CANCELLED; if ((ss->idle) && (ss->sp.source == PIXMA_SOURCE_ADF || ss->sp.source == PIXMA_SOURCE_ADFDUP)) return SANE_STATUS_INVAL; if (!ss->scanning) return ss->last_read_status; status = SANE_STATUS_GOOD; /* CCD scanners use software lineart * the scanner must scan 24 bit color or 8 bit grayscale for one bit lineart */ if ((ss->sp.line_size - ((ss->sp.software_lineart == 1) ? (ss->output_line_size * 8) : ss->output_line_size)) == 0) { status = read_image (ss, buf, maxlen, &sum); } else { /* FIXME: Because there is no frontend that can cope with padding at the end of line, we've to remove it here in the backend! */ PDBG (pixma_dbg (1, "*sane_read***** Warning: padding may cause incomplete scan results\n")); sum = 0; while (sum < maxlen) { if (ss->byte_pos_in_line < ss->output_line_size) { n = ss->output_line_size - ss->byte_pos_in_line; if ((maxlen - sum) < n) n = maxlen - sum; status = read_image (ss, buf, n, &n); if (n == 0) break; sum += n; buf += n; ss->byte_pos_in_line += n; } else { /* skip padding */ n = ss->sp.line_size - ss->byte_pos_in_line; if (n > (int) sizeof (temp)) { PDBG (pixma_dbg (3, "Inefficient skip buffer. Should be %d\n", n)); n = sizeof (temp); } status = read_image (ss, temp, n, &n); if (n == 0) break; ss->byte_pos_in_line += n; if (ss->byte_pos_in_line == ss->sp.line_size) ss->byte_pos_in_line = 0; } } } if (ss->cancel) status = SANE_STATUS_CANCELLED; else if ((status == SANE_STATUS_GOOD || status == SANE_STATUS_EOF) && sum > 0) { *len = sum; status = SANE_STATUS_GOOD; } ss->scanning = (status == SANE_STATUS_GOOD); ss->last_read_status = status; return status; } void sane_cancel (SANE_Handle h) { DECL_CTX; if (!ss) return; ss->cancel = SANE_TRUE; ss->sp.frontend_cancel = SANE_TRUE; if (ss->idle) return; close (ss->rpipe); ss->rpipe = -1; terminate_reader_task (ss, NULL); ss->idle = SANE_TRUE; } SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool m) { DECL_CTX; if (!ss || ss->idle || ss->rpipe == -1) return SANE_STATUS_INVAL; #ifdef HAVE_FCNTL_H PDBG (pixma_dbg (2, "Setting %sblocking mode\n", (m) ? "non-" : "")); if (fcntl (ss->rpipe, F_SETFL, (m) ? O_NONBLOCK : 0) == -1) { PDBG (pixma_dbg (1, "WARNING:fcntl(F_SETFL) failed %s\n", strerror (errno))); return SANE_STATUS_UNSUPPORTED; } return SANE_STATUS_GOOD; #else return (m) ? SANE_STATUS_UNSUPPORTED : SANE_STATUS_GOOD; #endif } SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fd) { DECL_CTX; *fd = -1; if (!ss || !fd || ss->idle || ss->rpipe == -1) return SANE_STATUS_INVAL; *fd = ss->rpipe; return SANE_STATUS_GOOD; } /* BEGIN SANE_Option_Descriptor rem ------------------------------------------- type group title Scan mode type int resolution unit dpi constraint @word_list = ss->dpi_list default 75 title @SANE_TITLE_SCAN_RESOLUTION desc @SANE_DESC_SCAN_RESOLUTION cap soft_select soft_detect automatic info reload_params type string mode[30] constraint @string_list = ss->mode_list default @s = SANE_VALUE_SCAN_MODE_COLOR title @SANE_TITLE_SCAN_MODE desc @SANE_DESC_SCAN_MODE cap soft_select soft_detect automatic info reload_params type string source[30] constraint @string_list = ss->source_list title @SANE_TITLE_SCAN_SOURCE desc Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values. default Flatbed cap soft_select soft_detect type bool button-controlled title Button-controlled scan desc When enabled, scan process will not start immediately. To proceed, press \"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To cancel, press \"GRAY\" button. default SANE_FALSE cap soft_select soft_detect inactive rem ------------------------------------------- type group title Gamma type bool custom-gamma default SANE_TRUE title @SANE_TITLE_CUSTOM_GAMMA desc @SANE_DESC_CUSTOM_GAMMA cap soft_select soft_detect automatic inactive type int gamma-table[4096] constraint (0,255,0) title @SANE_TITLE_GAMMA_VECTOR desc @SANE_DESC_GAMMA_VECTOR cap soft_select soft_detect automatic inactive type fixed gamma default AUTO_GAMMA constraint (0.3,5,0) title Gamma function exponent desc Changes intensity of midtones cap soft_select soft_detect automatic inactive rem ------------------------------------------- type group title Geometry type fixed tl-x unit mm default 0 constraint @range = &ss->xrange title @SANE_TITLE_SCAN_TL_X desc @SANE_DESC_SCAN_TL_X cap soft_select soft_detect automatic info reload_params type fixed tl-y unit mm default 0 constraint @range = &ss->yrange title @SANE_TITLE_SCAN_TL_Y desc @SANE_DESC_SCAN_TL_Y cap soft_select soft_detect automatic info reload_params type fixed br-x unit mm default _MAX constraint @range = &ss->xrange title @SANE_TITLE_SCAN_BR_X desc @SANE_DESC_SCAN_BR_X cap soft_select soft_detect automatic info reload_params type fixed br-y unit mm default _MAX constraint @range = &ss->yrange title @SANE_TITLE_SCAN_BR_Y desc @SANE_DESC_SCAN_BR_Y cap soft_select soft_detect automatic info reload_params rem ------------------------------------------- type group title Buttons type button button-update title Update button state cap soft_select soft_detect advanced type int button-1 default 0 title Button 1 cap soft_detect advanced type int button-2 default 0 title Button 2 cap soft_detect advanced type int original default 0 title Type of original to scan cap soft_detect advanced type int target default 0 title Target operation type cap soft_detect advanced type int scan-resolution default 0 title Scan resolution cap soft_detect advanced rem ------------------------------------------- type group title Extras type int threshold unit PERCENT default 50 constraint (0,100,1) title @SANE_TITLE_THRESHOLD desc @SANE_DESC_THRESHOLD cap soft_select soft_detect automatic inactive type int threshold-curve constraint (0,127,1) title Threshold curve desc Dynamic threshold curve, from light to dark, normally 50-65 cap soft_select soft_detect automatic inactive type int adf-wait default 0 constraint (0,3600,1) title ADF Waiting Time desc When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder. cap soft_select soft_detect automatic inactive rem ------------------------------------------- END SANE_Option_Descriptor */ /* pixma_sane_options.c generated by * scripts/pixma_gen_options.py < pixma.c > pixma_sane_options.c * * pixma_sane_options.h generated by * scripts/pixma_gen_options.py h < pixma.c > pixma_sane_options.h */ #include "pixma_sane_options.c" sane-backends-1.0.27/backend/ma1509.c0000664000175000017500000015200512775312261013702 00000000000000/* sane - Scanner Access Now Easy. (C) 2003 Henning Meier-Geinitz . Based on the mustek (SCSI) backend. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for scanners based on the Mustek MA-1509 chipset. Currently the Mustek BearPaw 1200F is known to work. */ /**************************************************************************/ /* ma1509 backend version */ #define BUILD 3 /**************************************************************************/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" #define BACKEND_NAME ma1509 #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "ma1509.h" #ifndef SANE_I18N #define SANE_I18N(text) text #endif /* Debug level from sanei_init_debug */ static SANE_Int debug_level; static SANE_Int num_devices; static Ma1509_Device *first_dev; static Ma1509_Scanner *first_handle; static const SANE_Device **devlist = 0; static int warmup_time = MA1509_WARMUP_TIME; /* Array of newly attached devices */ static Ma1509_Device **new_dev; /* Length of new_dev array */ static SANE_Int new_dev_len; /* Number of entries alloced for new_dev */ static SANE_Int new_dev_alloced; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static SANE_String_Const ta_source_list[] = { SANE_I18N ("Flatbed"), SANE_I18N ("Transparency Adapter"), 0 }; static SANE_Word resolution_list[] = { 9, 50, 100, 150, 200, 300, 400, 450, 500, 600 }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /* "SCSI" command buffers used by the backend */ static const SANE_Byte scsi_inquiry[] = { 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, INQ_LEN, 0x00 }; static const SANE_Byte scsi_test_unit_ready[] = { 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00 }; static const SANE_Byte scsi_set_window[] = { 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00 }; static void print_data_buffer (const SANE_Byte * buffer, size_t len) { SANE_Byte buffer_byte_list[50]; SANE_Byte buffer_byte[5]; const SANE_Byte *pp; buffer_byte_list[0] = '\0'; for (pp = buffer; pp < (buffer + len); pp++) { sprintf ((SANE_String) buffer_byte, " %02x", *pp); strcat ((SANE_String) buffer_byte_list, (SANE_String) buffer_byte); if (((pp - buffer) % 0x10 == 0x0f) || (pp >= (buffer + len - 1))) { DBG (5, "buffer: %s\n", buffer_byte_list); buffer_byte_list[0] = '\0'; } } } static SANE_Status ma1509_cmd (Ma1509_Scanner * s, const SANE_Byte * cmd, SANE_Byte * data, size_t * data_size) { SANE_Status status; size_t size; #define MA1509_WRITE_LIMIT (1024 * 64) #define MA1509_READ_LIMIT (1024 * 256) DBG (5, "ma1509_cmd: fd=%d, cmd=%p, data=%p, data_size=%ld\n", s->fd, cmd, data, (long int) (data_size ? *data_size : 0)); DBG (5, "ma1509_cmd: cmd = %02x %02x %02x %02x %02x %02x %02x %02x \n", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]); size = MA1509_COMMAND_LENGTH; status = sanei_usb_write_bulk (s->fd, cmd, &size); if (status != SANE_STATUS_GOOD || size != MA1509_COMMAND_LENGTH) { DBG (5, "ma1509_cmd: sanei_usb_write_bulk returned %s (size = %ld, expected %d)\n", sane_strstatus (status), (long int) size, MA1509_COMMAND_LENGTH); return status; } if (cmd[1] == 1) { /* receive data */ if (data && data_size && *data_size) { size_t bytes_left = *data_size; DBG (5, "ma1509_cmd: trying to receive %ld bytes of data\n", (long int) *data_size); while (status == SANE_STATUS_GOOD && bytes_left > 0) { size = bytes_left; if (size > MA1509_READ_LIMIT) size = MA1509_READ_LIMIT; status = sanei_usb_read_bulk (s->fd, data + *data_size - bytes_left, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "ma1509_cmd: sanei_usb_read_bulk returned %s\n", sane_strstatus (status)); return status; } bytes_left -= size; DBG (5, "ma1509_cmd: read %ld bytes, %ld bytes to go\n", (long int) size, (long int) bytes_left); } if (debug_level >= 5) print_data_buffer (data, *data_size); } } else { /* send data */ if (data && data_size && *data_size) { size_t bytes_left = *data_size; DBG (5, "ma1509_cmd: sending %ld bytes of data\n", (long int) *data_size); if (debug_level >= 5) print_data_buffer (data, *data_size); while (status == SANE_STATUS_GOOD && bytes_left > 0) { size = bytes_left; if (size > MA1509_WRITE_LIMIT) size = MA1509_WRITE_LIMIT; status = sanei_usb_write_bulk (s->fd, data + *data_size - bytes_left, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "ma1509_cmd: sanei_usb_write_bulk returned %s\n", sane_strstatus (status)); return status; } bytes_left -= size; DBG (5, "ma1509_cmd: wrote %ld bytes, %ld bytes to go\n", (long int) size, (long int) bytes_left); } } } DBG (5, "ma1509_cmd: finished: data_size=%ld, status=%s\n", (long int) (data_size ? *data_size : 0), sane_strstatus (status)); return status; } static SANE_Status test_unit_ready (Ma1509_Scanner * s) { SANE_Status status; SANE_Byte buffer[0x04]; size_t size = sizeof (buffer); status = ma1509_cmd (s, scsi_test_unit_ready, buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "test_unit_ready: ma1509_cmd failed: %s\n", sane_strstatus (status)); return status; } if (buffer[1] == 0x14) s->hw->has_adf = SANE_TRUE; else s->hw->has_adf = SANE_FALSE; return status; } static SANE_Status attach (SANE_String_Const devname, Ma1509_Device ** devp) { SANE_Int fw_revision; SANE_Byte result[INQ_LEN]; SANE_Byte inquiry_byte_list[50], inquiry_text_list[17]; SANE_Byte inquiry_byte[5], inquiry_text[5]; SANE_Byte *model_name = result + 44; Ma1509_Scanner s; Ma1509_Device *dev, new_dev; SANE_Status status; size_t size; SANE_Byte *pp; SANE_Word vendor, product; if (devp) *devp = 0; for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } memset (&new_dev, 0, sizeof (new_dev)); memset (&s, 0, sizeof (s)); s.hw = &new_dev; DBG (3, "attach: trying device %s\n", devname); status = sanei_usb_open (devname, &s.fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: sanei_usb_open failed: %s\n", sane_strstatus (status)); return status; } status = sanei_usb_get_vendor_product (s.fd, &vendor, &product); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_UNSUPPORTED) { DBG (1, "attach: sanei_usb_get_vendor_product failed: %s\n", sane_strstatus (status)); sanei_usb_close (s.fd); return status; } if (status == SANE_STATUS_UNSUPPORTED) { DBG (3, "attach: can't detect vendor/product, trying anyway\n"); } else if (vendor != 0x055f || product != 0x0010) { DBG (1, "attach: unknown vendor/product (0x%x/0x%x)\n", vendor, product); sanei_usb_close (s.fd); return SANE_STATUS_UNSUPPORTED; } DBG (4, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (&s); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test_unit_ready device %s failed (%s)\n", devname, sane_strstatus (status)); sanei_usb_close (s.fd); return status; } DBG (4, "attach: sending INQUIRY\n"); size = sizeof (result); memset (result, 0, sizeof (result)); status = ma1509_cmd (&s, scsi_inquiry, result, &size); if (status != SANE_STATUS_GOOD || size != INQ_LEN) { DBG (1, "attach: inquiry for device %s failed (%s)\n", devname, sane_strstatus (status)); sanei_usb_close (s.fd); return status; } sanei_usb_close (s.fd); if ((result[0] & 0x1f) != 0x06) { DBG (1, "attach: device %s doesn't look like a scanner at all (%d)\n", devname, result[0] & 0x1f); return SANE_STATUS_INVAL; } if (debug_level >= 5) { /* print out inquiry */ DBG (5, "attach: inquiry output:\n"); inquiry_byte_list[0] = '\0'; inquiry_text_list[0] = '\0'; for (pp = result; pp < (result + INQ_LEN); pp++) { sprintf ((SANE_String) inquiry_text, "%c", (*pp < 127) && (*pp > 31) ? *pp : '.'); strcat ((SANE_String) inquiry_text_list, (SANE_String) inquiry_text); sprintf ((SANE_String) inquiry_byte, " %02x", *pp); strcat ((SANE_String) inquiry_byte_list, (SANE_String) inquiry_byte); if ((pp - result) % 0x10 == 0x0f) { DBG (5, "%s %s\n", inquiry_byte_list, inquiry_text_list); inquiry_byte_list[0] = '\0'; inquiry_text_list[0] = '\0'; } } } /* get firmware revision as BCD number: */ fw_revision = (result[32] - '0') << 8 | (result[34] - '0') << 4 | (result[35] - '0'); DBG (4, "attach: firmware revision %d.%02x\n", fw_revision >> 8, fw_revision & 0xff); dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memcpy (dev, &new_dev, sizeof (*dev)); dev->name = strdup (devname); if (!dev->name) return SANE_STATUS_NO_MEM; dev->sane.name = (SANE_String_Const) dev->name; dev->sane.vendor = "Mustek"; dev->sane.type = "flatbed scanner"; dev->x_range.min = 0; dev->y_range.min = 0; dev->x_range.quant = SANE_FIX (0.1); dev->y_range.quant = SANE_FIX (0.1); dev->x_trans_range.min = 0; dev->y_trans_range.min = 0; /* default to something really small to be on the safe side: */ dev->x_trans_range.max = SANE_FIX (8.0 * MM_PER_INCH); dev->y_trans_range.max = SANE_FIX (5.0 * MM_PER_INCH); dev->x_trans_range.quant = SANE_FIX (0.1); dev->y_trans_range.quant = SANE_FIX (0.1); DBG (3, "attach: scanner id: %.11s\n", model_name); /* BearPaw 1200F (SCSI-over-USB) */ if (strncmp ((SANE_String) model_name, " B06", 4) == 0) { dev->x_range.max = SANE_FIX (211.3); dev->y_range.min = SANE_FIX (0); dev->y_range.max = SANE_FIX (296.7); dev->x_trans_range.min = SANE_FIX (0); dev->y_trans_range.min = SANE_FIX (0); dev->x_trans_range.max = SANE_FIX (150.0); dev->y_trans_range.max = SANE_FIX (175.0); dev->sane.model = "BearPaw 1200F"; } else { DBG (0, "attach: this scanner (ID: %s) is not supported yet\n", model_name); DBG (0, "attach: please set the debug level to 5 and send a debug " "report\n"); DBG (0, "attach: to henning@meier-geinitz.de (export " "SANE_DEBUG_MA1509=5\n"); DBG (0, "attach: scanimage -L 2>debug.txt). Thank you.\n"); free (dev); return SANE_STATUS_INVAL; } DBG (2, "attach: found Mustek %s %s %s%s\n", dev->sane.model, dev->sane.type, dev->has_ta ? "(TA)" : "", dev->has_adf ? "(ADF)" : ""); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status init_options (Ma1509_Scanner * s) { SANE_Int i; memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = ""; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[1]); if (!s->val[OPT_MODE].s) return SANE_STATUS_NO_MEM; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = resolution_list; s->val[OPT_RESOLUTION].w = 50; /* source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].size = max_string_size (ta_source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = ta_source_list; s->val[OPT_SOURCE].s = strdup (ta_source_list[0]); if (!s->val[OPT_SOURCE].s) return SANE_STATUS_NO_MEM; s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = 0; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = s->hw->x_range.min; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = s->hw->y_range.min; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &u8_range; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->val[OPT_THRESHOLD].w = 128; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = MA1509_GAMMA_SIZE * sizeof (SANE_Word); s->val[OPT_GAMMA_VECTOR_R].wa = &s->red_gamma_table[0]; s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; for (i = 0; i < MA1509_GAMMA_SIZE; i++) s->red_gamma_table[i] = i * MA1509_GAMMA_SIZE / 256; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = MA1509_GAMMA_SIZE * sizeof (SANE_Word); s->val[OPT_GAMMA_VECTOR_G].wa = &s->green_gamma_table[0]; s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; for (i = 0; i < MA1509_GAMMA_SIZE; i++) s->green_gamma_table[i] = i * MA1509_GAMMA_SIZE / 256; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = MA1509_GAMMA_SIZE * sizeof (SANE_Word); s->val[OPT_GAMMA_VECTOR_B].wa = &s->blue_gamma_table[0]; s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; for (i = 0; i < MA1509_GAMMA_SIZE; i++) s->blue_gamma_table[i] = i * MA1509_GAMMA_SIZE / 256; return SANE_STATUS_GOOD; } static SANE_Status attach_one_device (SANE_String_Const devname) { Ma1509_Device *dev; attach (devname, &dev); if (dev) { /* Keep track of newly attached devices so we can set options as necessary. */ if (new_dev_len >= new_dev_alloced) { new_dev_alloced += 4; if (new_dev) new_dev = realloc (new_dev, new_dev_alloced * sizeof (new_dev[0])); else new_dev = malloc (new_dev_alloced * sizeof (new_dev[0])); if (!new_dev) { DBG (1, "attach_one_device: out of memory\n"); return SANE_STATUS_NO_MEM; } } new_dev[new_dev_len++] = dev; } return SANE_STATUS_GOOD; } static SANE_Status set_window (Ma1509_Scanner * s) { SANE_Byte buffer[0x30], *cp; double pixels_per_mm; size_t size = sizeof (buffer); SANE_Status status; SANE_Int tlx, tly, width, height; SANE_Int offset = 0; struct timeval now; long remaining_time; /* check if lamp is warmed up */ gettimeofday (&now, 0); remaining_time = warmup_time - (now.tv_sec - s->lamp_time); if (remaining_time > 0) { DBG (0, "Warm-up in progress: please wait %2ld seconds\n", remaining_time); sleep (remaining_time); } memset (buffer, 0, size); cp = buffer; STORE16B (cp, 0); /* window identifier */ STORE16B (cp, s->val[OPT_RESOLUTION].w); STORE16B (cp, 0); /* not used acc. to specs */ pixels_per_mm = s->val[OPT_RESOLUTION].w / MM_PER_INCH; tlx = SANE_UNFIX (s->val[OPT_TL_X].w) * pixels_per_mm + 0.5; tly = SANE_UNFIX (s->val[OPT_TL_Y].w) * pixels_per_mm + 0.5; width = (SANE_UNFIX (s->val[OPT_BR_X].w) - SANE_UNFIX (s->val[OPT_TL_X].w)) * pixels_per_mm + 0.5; height = (SANE_UNFIX (s->val[OPT_BR_Y].w) - SANE_UNFIX (s->val[OPT_TL_Y].w)) * pixels_per_mm + 0.5 + offset; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { width /= 64; width *= 64; if (!width) width = 64; } else { width /= 8; width *= 8; if (!width) width = 8; } DBG (4, "set_window: tlx=%d (%d mm); tly=%d (%d mm); width=%d (%d mm); " "height=%d (%d mm)\n", tlx, (int) (tlx / pixels_per_mm), tly, (int) (tly / pixels_per_mm), width, (int) (width / pixels_per_mm), height, (int) (height / pixels_per_mm)); STORE16B (cp, 0); STORE16B (cp, tlx); STORE16B (cp, 0); STORE16B (cp, tly); *cp++ = 0x14; *cp++ = 0xc0; STORE16B (cp, width); *cp++ = 0x28; *cp++ = 0x20; STORE16B (cp, height); s->hw->ppl = width; s->hw->bpl = s->hw->ppl; s->hw->lines = height; *cp++ = 0x00; /* brightness, not impl. */ /* threshold */ if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) *cp++ = (SANE_Byte) s->val[OPT_THRESHOLD].w; else *cp++ = 0x80; *cp++ = 0x00; /* contrast, not impl. */ *cp++ = 0x00; /* ??? . */ /* Note that 'image composition' has no meaning for the SE series */ /* Mode selection is accomplished solely by bits/pixel (1, 8, 24) */ if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { *cp++ = 24; /* 24 bits/pixel in color mode */ s->hw->bpl *= 3; } else if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) *cp++ = 8; /* 8 bits/pixel in gray mode */ else { *cp++ = 1; /* 1 bit/pixel in lineart mode */ s->hw->bpl /= 8; } cp += 13; /* skip reserved bytes */ *cp++ = 0x00; /* lamp mode */ if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) != 0) *cp++ = 0x02; /* ??? */ status = ma1509_cmd (s, scsi_set_window, buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "set_window: ma1509_cmd failed: %s\n", sane_strstatus (status)); return status; } return status; } static SANE_Status calibration (Ma1509_Scanner * s) { SANE_Byte cmd[0x08], *buffer, *calibration_buffer; SANE_Status status; SANE_Int ppl = 5312; SANE_Int lines = 40; size_t total_size = lines * ppl; SANE_Int color, column, line; buffer = malloc (total_size * 3); if (!buffer) { DBG (1, "calibration: couldn't malloc %lu bytes for calibration buffer\n", (u_long) (total_size * 3)); return SANE_STATUS_NO_MEM; } memset (buffer, 0x00, total_size); memset (cmd, 0, 8); cmd[0] = 0x28; /* read data */ cmd[1] = 0x01; /* read */ cmd[2] = 0x01; /* calibration */ cmd[4] = (total_size >> 16) & 0xff; cmd[5] = (total_size >> 8) & 0xff; cmd[6] = total_size & 0xff; total_size *= 3; status = ma1509_cmd (s, cmd, buffer, &total_size); if (status != SANE_STATUS_GOOD) { DBG (1, "calibration: ma1509_cmd read data failed: %s\n", sane_strstatus (status)); free (buffer); return status; } calibration_buffer = malloc (ppl); if (!calibration_buffer) { DBG (1, "calibration: couldn't malloc %d bytes for calibration buffer\n", ppl); return SANE_STATUS_NO_MEM; } memset (calibration_buffer, 0x00, ppl); memset (cmd, 0, 8); cmd[0] = 0x2a; /* send data */ cmd[1] = 0x00; /* write */ cmd[2] = 0x01; /* calibration */ cmd[5] = (ppl >> 8) & 0xff; cmd[6] = ppl & 0xff; for (color = 1; color < 4; color++) { cmd[4] = color; for (column = 0; column < ppl; column++) { SANE_Int average = 0; for (line = 0; line < lines; line++) average += buffer[line * ppl * 3 + column * 3 + (color - 1)]; average /= lines; if (average < 1) average = 1; if (average > 255) average = 255; average = (256 * 256) / average - 256; if (average < 0) average = 0; if (average > 255) average = 255; calibration_buffer[column] = average; } total_size = ppl; status = ma1509_cmd (s, cmd, calibration_buffer, &total_size); if (status != SANE_STATUS_GOOD) { DBG (1, "calibration: ma1509_cmd send data failed: %s\n", sane_strstatus (status)); free (buffer); free (calibration_buffer); return status; } } free (buffer); free (calibration_buffer); DBG (4, "calibration: done\n"); return status; } static SANE_Status send_gamma (Ma1509_Scanner * s) { SANE_Byte cmd[0x08], *buffer; SANE_Status status; size_t total_size = MA1509_GAMMA_SIZE; SANE_Int color; buffer = malloc (total_size); if (!buffer) { DBG (1, "send_gamma: couldn't malloc %lu bytes for gamma buffer\n", (u_long) total_size); return SANE_STATUS_NO_MEM; } memset (cmd, 0, 8); cmd[0] = 0x2a; /* send data */ cmd[1] = 0x00; /* write */ cmd[2] = 0x03; /* gamma */ cmd[5] = (total_size >> 8) & 0xff; cmd[6] = total_size & 0xff; for (color = 1; color < 4; color++) { unsigned int i; if (s->val[OPT_CUSTOM_GAMMA].w) { SANE_Int *int_buffer; if (color == 1) int_buffer = s->red_gamma_table; else if (color == 2) int_buffer = s->green_gamma_table; else int_buffer = s->blue_gamma_table; for (i = 0; i < total_size; i++) buffer[i] = int_buffer[i]; } else { /* linear tables */ for (i = 0; i < total_size; i++) buffer[i] = i * 256 / total_size; } cmd[4] = color; status = ma1509_cmd (s, cmd, buffer, &total_size); if (status != SANE_STATUS_GOOD) { DBG (1, "send_gamma: ma1509_cmd send data failed: %s\n", sane_strstatus (status)); free (buffer); return status; } } if (!s->val[OPT_CUSTOM_GAMMA].w) free (buffer); DBG (4, "send_gamma: done\n"); return status; } static SANE_Status start_scan (Ma1509_Scanner * s) { SANE_Byte cmd[8]; SANE_Status status; DBG (4, "start_scan\n"); memset (cmd, 0, 8); cmd[0] = 0x1b; cmd[1] = 0x01; cmd[2] = 0x01; status = ma1509_cmd (s, cmd, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "start_scan: ma1509_cmd failed: %s\n", sane_strstatus (status)); return status; } return status; } static SANE_Status turn_lamp (Ma1509_Scanner * s, SANE_Bool is_on) { SANE_Status status; SANE_Byte buffer[0x30]; size_t size = sizeof (buffer); struct timeval lamp_time; DBG (4, "turn_lamp %s\n", is_on ? "on" : "off"); memset (buffer, 0, size); if (is_on) buffer[0x28] = 0x01; else buffer[0x28] = 0x02; status = ma1509_cmd (s, scsi_set_window, buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "turn_lamp: ma1509_cmd set_window failed: %s\n", sane_strstatus (status)); return status; } gettimeofday (&lamp_time, 0); s->lamp_time = lamp_time.tv_sec; return status; } static SANE_Status stop_scan (Ma1509_Scanner * s) { SANE_Byte cmd[8]; SANE_Status status; DBG (4, "stop_scan\n"); memset (cmd, 0, 8); cmd[0] = 0x1b; cmd[1] = 0x01; cmd[2] = 0x00; status = ma1509_cmd (s, cmd, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "stop_scan: ma1509_cmd failed: %s\n", sane_strstatus (status)); return status; } DBG (4, "stop_scan: scan stopped\n"); return status; } static SANE_Status start_read_data (Ma1509_Scanner * s) { SANE_Byte cmd[8]; SANE_Status status; SANE_Int total_size = s->hw->ppl * s->hw->lines; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) total_size /= 8; memset (cmd, 0, 8); cmd[0] = 0x28; /* read data */ cmd[1] = 0x01; /* read */ cmd[2] = 0x00; /* scan data */ cmd[3] = (total_size >> 24) & 0xff; cmd[4] = (total_size >> 16) & 0xff; cmd[5] = (total_size >> 8) & 0xff; cmd[6] = total_size & 0xff; status = ma1509_cmd (s, cmd, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "stop_scan: ma1509_cmd failed: %s\n", sane_strstatus (status)); return status; } return status; } static SANE_Status read_data (Ma1509_Scanner * s, SANE_Byte * buffer, SANE_Int * size) { size_t local_size = *size; SANE_Status status; status = sanei_usb_read_bulk (s->fd, buffer, &local_size); if (status != SANE_STATUS_GOOD) { DBG (1, "read_data: sanei_usb_read_bulk failed: %s\n", sane_strstatus (status)); return status; } *size = local_size; return status; } /**************************************************************************/ /* SANE API calls */ /**************************************************************************/ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { SANE_Char line[PATH_MAX], *word, *end; SANE_String_Const cp; SANE_Int linenumber; FILE *fp; DBG_INIT (); #ifdef DBG_LEVEL debug_level = DBG_LEVEL; #else debug_level = 0; #endif DBG (2, "SANE ma1509 backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (4, "sane_init: authorize %s null\n", authorize ? "!=" : "=="); sanei_usb_init (); num_devices = 0; first_dev = 0; first_handle = 0; devlist = 0; new_dev = 0; new_dev_len = 0; new_dev_alloced = 0; fp = sanei_config_open (MA1509_CONFIG_FILE); if (!fp) { /* default to /dev/usb/scanner0 instead of insisting on config file */ DBG (3, "sane_init: couldn't find config file (%s), trying " "/dev/usb/scanner0 directly\n", MA1509_CONFIG_FILE); attach ("/dev/usb/scanner0", 0); return SANE_STATUS_GOOD; } linenumber = 0; DBG (4, "sane_init: reading config file `%s'\n", MA1509_CONFIG_FILE); while (sanei_config_read (line, sizeof (line), fp)) { word = 0; linenumber++; cp = sanei_config_get_string (line, &word); if (!word || cp == line) { DBG (5, "sane_init: config file line %d: ignoring empty line\n", linenumber); if (word) free (word); continue; } if (word[0] == '#') { DBG (5, "sane_init: config file line %d: ignoring comment line\n", linenumber); free (word); continue; } if (strcmp (word, "option") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (!word) { DBG (1, "sane_init: config file line %d: missing quotation mark?\n", linenumber); continue; } if (strcmp (word, "warmup-time") == 0) { long local_warmup_time; free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (!word) { DBG (1, "sane_init: config file line %d: missing quotation mark?\n", linenumber); continue; } errno = 0; local_warmup_time = strtol (word, &end, 0); if (end == word) { DBG (3, "sane-init: config file line %d: warmup-time must " "have a parameter; using default (%d)\n", linenumber, warmup_time); } else if (errno) { DBG (3, "sane-init: config file line %d: warmup-time `%s' " "is invalid (%s); using default (%d)\n", linenumber, word, strerror (errno), warmup_time); } else { warmup_time = local_warmup_time; DBG (4, "sane_init: config file line %d: warmup-time set " "to %d seconds\n", linenumber, warmup_time); } if (word) free (word); word = 0; } else { DBG (3, "sane_init: config file line %d: ignoring unknown " "option `%s'\n", linenumber, word); if (word) free (word); word = 0; } } else { new_dev_len = 0; DBG (4, "sane_init: config file line %d: trying to attach `%s'\n", linenumber, line); sanei_usb_attach_matching_devices (line, attach_one_device); if (word) free (word); word = 0; } } if (new_dev_alloced > 0) { new_dev_len = new_dev_alloced = 0; free (new_dev); } fclose (fp); return SANE_STATUS_GOOD; } void sane_exit (void) { Ma1509_Device *dev, *next; DBG (4, "sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free (dev->name); free (dev); } if (devlist) free (devlist); devlist = 0; first_dev = 0; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Ma1509_Device *dev; SANE_Int i; DBG (4, "sane_get_devices: %d devices %s\n", num_devices, local_only ? "(local only)" : ""); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (5, "sane_get_devices: end\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Ma1509_Device *dev; SANE_Status status; Ma1509_Scanner *s; if (!devicename) { DBG (1, "sane_open: devicename is null!\n"); return SANE_STATUS_INVAL; } if (!handle) { DBG (1, "sane_open: handle is null!\n"); return SANE_STATUS_INVAL; } DBG (4, "sane_open: devicename=%s\n", devicename); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach (devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } } else /* empty devicname -> use first device */ dev = first_dev; if (!dev) { DBG (1, "sane_open: %s doesn't seem to exist\n", devicename); return SANE_STATUS_INVAL; } s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->hw = dev; init_options (s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; status = sanei_usb_open (s->hw->sane.name, &s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: couldn't open %s: %s\n", s->hw->sane.name, sane_strstatus (status)); return status; } status = turn_lamp (s, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: couldn't turn on lamp: %s\n", sane_strstatus (status)); return status; } status = turn_lamp (s, SANE_TRUE); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_open: couldn't turn on lamp: %s\n", sane_strstatus (status)); return status; } *handle = s; DBG (5, "sane_open: finished (handle=%p)\n", (void *) s); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Ma1509_Scanner *prev, *s; SANE_Status status; DBG (4, "sane_close: handle=%p\n", handle); /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (1, "sane_close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (s->val[OPT_MODE].s) free (s->val[OPT_MODE].s); if (s->val[OPT_SOURCE].s) free (s->val[OPT_SOURCE].s); status = turn_lamp (s, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_close: couldn't turn off lamp: %s\n", sane_strstatus (status)); return; } sanei_usb_close (s->fd); if (prev) prev->next = s->next; else first_handle = s->next; free (handle); handle = 0; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Ma1509_Scanner *s = handle; if (((unsigned) option >= NUM_OPTIONS) || (option < 0)) { DBG (3, "sane_get_option_descriptor: option %d >= NUM_OPTIONS or < 0\n", option); return 0; } if (!s) { DBG (1, "sane_get_option_descriptor: handle is null!\n"); return 0; } if (s->opt[option].name && s->opt[option].name[0] != 0) DBG (4, "sane_get_option_descriptor for option %s (%sactive%s)\n", s->opt[option].name, s->opt[option].cap & SANE_CAP_INACTIVE ? "in" : "", s->opt[option].cap & SANE_CAP_ADVANCED ? ", advanced" : ""); else DBG (4, "sane_get_option_descriptor for option \"%s\" (%sactive%s)\n", s->opt[option].title, s->opt[option].cap & SANE_CAP_INACTIVE ? "in" : "", s->opt[option].cap & SANE_CAP_ADVANCED ? ", advanced" : ""); return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Ma1509_Scanner *s = handle; SANE_Status status; SANE_Word cap; SANE_Word w; if (((unsigned) option >= NUM_OPTIONS) || (option < 0)) { DBG (3, "sane_control_option: option %d < 0 or >= NUM_OPTIONS\n", option); return SANE_STATUS_INVAL; } if (!s) { DBG (1, "sane_control_option: handle is null!\n"); return SANE_STATUS_INVAL; } if (!val && s->opt[option].type != SANE_TYPE_BUTTON) { DBG (1, "sane_control_option: val is null!\n"); return SANE_STATUS_INVAL; } if (s->opt[option].name && s->opt[option].name[0] != 0) DBG (4, "sane_control_option (%s option %s)\n", action == SANE_ACTION_GET_VALUE ? "get" : (action == SANE_ACTION_SET_VALUE ? "set" : "unknown action with"), s->opt[option].name); else DBG (4, "sane_control_option (%s option \"%s\")\n", action == SANE_ACTION_GET_VALUE ? "get" : (action == SANE_ACTION_SET_VALUE ? "set" : "unknown action with"), s->opt[option].title); if (info) *info = 0; if (s->scanning) { DBG (3, "sane_control_option: don't use while scanning (option %s)\n", s->opt[option].name); return SANE_STATUS_DEVICE_BUSY; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (3, "sane_control_option: option %s is inactive\n", s->opt[option].name); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_PREVIEW: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_THRESHOLD: case OPT_CUSTOM_GAMMA: case OPT_NUM_OPTS: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; /* word-array options: */ case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); return SANE_STATUS_GOOD; /* string options: */ case OPT_SOURCE: case OPT_MODE: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (3, "sane_control_option: option %s is not setable\n", s->opt[option].name); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (4, "sane_control_option: constrain_value error (option %s)\n", s->opt[option].name); return status; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_BR_X: case OPT_TL_Y: case OPT_BR_Y: if (info) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_THRESHOLD: case OPT_PREVIEW: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); return SANE_STATUS_GOOD; case OPT_MODE: { SANE_Char *old_val = s->val[option].s; if (old_val) { if (strcmp (old_val, val) == 0) return SANE_STATUS_GOOD; /* no change */ free (old_val); } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w) { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } return SANE_STATUS_GOOD; } case OPT_SOURCE: if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; if (strcmp (val, "Transparency Adapter") == 0) { s->opt[OPT_TL_X].constraint.range = &s->hw->x_trans_range; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_trans_range; s->opt[OPT_BR_X].constraint.range = &s->hw->x_trans_range; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_trans_range; } else { s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; } return SANE_STATUS_GOOD; /* options with side-effects: */ case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == s->val[OPT_CUSTOM_GAMMA].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[OPT_CUSTOM_GAMMA].w = w; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; if (w && strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) != 0) { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; } } DBG (4, "sane_control_option: unknown action for option %s\n", s->opt[option].name); return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Ma1509_Scanner *s = handle; SANE_String_Const mode; if (!s) { DBG (1, "sane_get_parameters: handle is null!\n"); return SANE_STATUS_INVAL; } if (!s->scanning) { double width, height, dpi; memset (&s->params, 0, sizeof (s->params)); width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); dpi = s->val[OPT_RESOLUTION].w; /* make best-effort guess at what parameters will look like once scanning starts. */ if (dpi > 0.0 && width > 0.0 && height > 0.0) { double dots_per_mm = dpi / MM_PER_INCH; s->params.pixels_per_line = width * dots_per_mm; s->params.lines = height * dots_per_mm; } mode = s->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; s->params.depth = 1; } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } else { /* it's one of the color modes... */ s->params.bytes_per_line = 3 * s->params.pixels_per_line; s->params.depth = 8; s->params.format = SANE_FRAME_RGB; } } s->params.last_frame = SANE_TRUE; if (params) *params = s->params; DBG (4, "sane_get_parameters: frame = %d; last_frame = %s; depth = %d\n", s->params.format, s->params.last_frame ? "true" : "false", s->params.depth); DBG (4, "sane_get_parameters: lines = %d; ppl = %d; bpl = %d\n", s->params.lines, s->params.pixels_per_line, s->params.bytes_per_line); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Ma1509_Scanner *s = handle; SANE_Status status; struct timeval start; if (!s) { DBG (1, "sane_start: handle is null!\n"); return SANE_STATUS_INVAL; } DBG (4, "sane_start\n"); status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; /* Check for inconsistencies */ if (s->val[OPT_TL_X].w > s->val[OPT_BR_X].w) { DBG (0, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) " "-- aborting\n", s->opt[OPT_TL_X].title, SANE_UNFIX (s->val[OPT_TL_X].w), s->opt[OPT_BR_X].title, SANE_UNFIX (s->val[OPT_BR_X].w)); return SANE_STATUS_INVAL; } if (s->val[OPT_TL_Y].w > s->val[OPT_BR_Y].w) { DBG (0, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) " "-- aborting\n", s->opt[OPT_TL_Y].title, SANE_UNFIX (s->val[OPT_TL_Y].w), s->opt[OPT_BR_Y].title, SANE_UNFIX (s->val[OPT_BR_Y].w)); return SANE_STATUS_INVAL; } s->total_bytes = 0; s->read_bytes = 0; /* save start time */ gettimeofday (&start, 0); s->start_time = start.tv_sec; status = set_window (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: set window command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = test_unit_ready (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: test_unit_ready failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) != 0) { status = calibration (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: calibration failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = send_gamma (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: send_gamma failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } } s->scanning = SANE_TRUE; s->cancelled = SANE_FALSE; status = start_scan (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: start_scan command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = start_read_data (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: start_read_data command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } s->params.bytes_per_line = s->hw->bpl; s->params.pixels_per_line = s->params.bytes_per_line; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) s->params.pixels_per_line /= 3; else if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) s->params.pixels_per_line *= 8; s->params.lines = s->hw->lines; s->buffer = (SANE_Byte *) malloc (MA1509_BUFFER_SIZE); if (!s->buffer) return SANE_STATUS_NO_MEM; s->buffer_bytes = 0; DBG (5, "sane_start: finished\n"); return SANE_STATUS_GOOD; stop_scanner_and_return: sanei_usb_close (s->fd); s->scanning = SANE_FALSE; return status; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Ma1509_Scanner *s = handle; SANE_Status status; SANE_Int total_size = s->hw->lines * s->hw->bpl; SANE_Int i; if (!s) { DBG (1, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } if (!buf) { DBG (1, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (!len) { DBG (1, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } DBG (5, "sane_read\n"); *len = 0; if (s->cancelled) { DBG (4, "sane_read: scan was cancelled\n"); return SANE_STATUS_CANCELLED; } if (!s->scanning) { DBG (1, "sane_read: must call sane_start before sane_read\n"); return SANE_STATUS_INVAL; } if (total_size - s->read_bytes <= 0) { DBG (4, "sane_read: EOF\n"); stop_scan (s); s->scanning = SANE_FALSE; return SANE_STATUS_EOF; } if (s->buffer_bytes == 0) { SANE_Int size = MA1509_BUFFER_SIZE; if (size > (total_size - s->total_bytes)) size = total_size - s->total_bytes; DBG (4, "sane_read: trying to read %d bytes\n", size); status = read_data (s, s->buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_read: read_data failed: %s\n", sane_strstatus (status)); *len = 0; return status; } s->total_bytes += size; s->buffer_start = s->buffer; s->buffer_bytes = size; } *len = max_len; if (*len > s->buffer_bytes) *len = s->buffer_bytes; memcpy (buf, s->buffer_start, *len); s->buffer_start += (*len); s->buffer_bytes -= (*len); s->read_bytes += (*len); /* invert for lineart mode */ if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { for (i = 0; i < *len; i++) buf[i] = ~buf[i]; } DBG (4, "sane_read: read %d/%d bytes (%d bytes to go, %d total)\n", *len, max_len, total_size - s->read_bytes, total_size); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Ma1509_Scanner *s = handle; if (!s) { DBG (1, "sane_cancel: handle is null!\n"); return; } DBG (4, "sane_cancel\n"); if (s->scanning) { s->cancelled = SANE_TRUE; stop_scan (s); free (s->buffer); } s->scanning = SANE_FALSE; DBG (4, "sane_cancel finished\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Ma1509_Scanner *s = handle; if (!s) { DBG (1, "sane_set_io_mode: handle is null!\n"); return SANE_STATUS_INVAL; } DBG (4, "sane_set_io_mode: %s\n", non_blocking ? "non-blocking" : "blocking"); if (!s->scanning) { DBG (1, "sane_set_io_mode: call sane_start before sane_set_io_mode"); return SANE_STATUS_INVAL; } if (non_blocking) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Ma1509_Scanner *s = handle; if (!s) { DBG (1, "sane_get_select_fd: handle is null!\n"); return SANE_STATUS_INVAL; } if (!fd) { DBG (1, "sane_get_select_fd: fd is null!\n"); return SANE_STATUS_INVAL; } DBG (4, "sane_get_select_fd\n"); if (!s->scanning) return SANE_STATUS_INVAL; return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/hp3900.c0000664000175000017500000000463112112021330013665 00000000000000/* HP Scanjet 3900 series - Stand-alone/SANE Backend controller Copyright (C) 2005-2008 Jonathan Bravo Lopez This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* Backend info */ #define BACKEND_NAME hp3900 #define BACKEND_VRSN "0.12" #define BACKEND_AUTHOR "Jonathan Bravo Lopez (JKD)" #define BACKEND_EMAIL "jkdsoft@gmail.com" #define BACKEND_URL "http://jkdsoftware.dyndns.org" #define BACKEND_LICENSE "General Public License (GPL)" /* if you want to compile this one as a sane backend then comment next line */ /* Caution: Sources included in SANE project don't provide hp3900_stdalone.c */ /*#define STANDALONE*/ #ifdef STANDALONE #include "hp3900_stdalone.c" #else #include "hp3900_sane.c" #endif sane-backends-1.0.27/backend/dc240.c0000664000175000017500000014045612775312260013610 00000000000000/*************************************************************************** * _S_A_N_E - Scanner Access Now Easy. dc240.c 03/12/01 - Peter Fales Based on the dc210 driver, (C) 1998 Brian J. Murrell (which is based on dc25 driver (C) 1998 by Peter Fales) This file (C) 2001 by Peter Fales This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for the Kodak DC-240 digital camera. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! (feedback to: dc240-devel@fales-lorenz.net) This backend is based somewhat on the dc25 backend included in this package by Peter Fales, and the dc210 backend by Brian J. Murrell ***************************************************************************/ #include "../include/sane/config.h" #include #include #include #include #include #include #include "../include/sane/sanei_jpeg.h" #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME dc240 #include "../include/sane/sanei_backend.h" #include "dc240.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define MAGIC (void *)0xab730324 #define DC240_CONFIG_FILE "dc240.conf" #define THUMBSIZE 20736 #ifdef B115200 # define DEFAULT_BAUD_RATE B115200 #else # define DEFAULT_BAUD_RATE B38400 #endif #if defined (__sgi) # define DEFAULT_TTY "/dev/ttyd1" /* Irix */ #elif defined (__sun) # define DEFAULT_TTY "/dev/term/a" /* Solaris */ #elif defined (hpux) # define DEFAULT_TTY "/dev/tty1d0" /* HP-UX */ #elif defined (__osf__) # define DEFAULT_TTY "/dev/tty00" /* Digital UNIX */ #else # define DEFAULT_TTY "/dev/ttyS0" /* Linux */ #endif static SANE_Bool is_open = 0; static SANE_Bool dc240_opt_thumbnails; static SANE_Bool dc240_opt_snap; static SANE_Bool dc240_opt_lowres; static SANE_Bool dc240_opt_erase; static SANE_Bool dc240_opt_autoinc; static SANE_Bool dumpinquiry; static struct jpeg_decompress_struct cinfo; static djpeg_dest_ptr dest_mgr = NULL; static unsigned long cmdrespause = 250000UL; /* pause after sending cmd */ static unsigned long breakpause = 1000000UL; /* pause after sending break */ static DC240 Camera; static SANE_Range image_range = { 0, 0, 0 }; static SANE_String **folder_list; static SANE_Int current_folder = 0; static SANE_Option_Descriptor sod[] = { { SANE_NAME_NUM_OPTIONS, SANE_TITLE_NUM_OPTIONS, SANE_DESC_NUM_OPTIONS, SANE_TYPE_INT, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC240_OPT_IMAGE_SELECTION 1 { "", "Image Selection", "Selection of the image to load.", SANE_TYPE_GROUP, SANE_UNIT_NONE, 0, 0, SANE_CONSTRAINT_NONE, {NULL} } , #define DC240_OPT_FOLDER 2 { "folder", "Folder", "Select folder within camera", SANE_TYPE_STRING, SANE_UNIT_NONE, 256, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_STRING_LIST, {NULL} } , #define DC240_OPT_IMAGE_NUMBER 3 { "image", "Image Number", "Select Image Number to load from camera", SANE_TYPE_INT, SANE_UNIT_NONE, 4, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_RANGE, {(SANE_String_Const *) & image_range} /* this is ANSI conformant! */ } , #define DC240_OPT_THUMBS 4 { "thumbs", "Load Thumbnail", "Load the image as thumbnail.", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC240_OPT_SNAP 5 { "snap", "Snap new picture", "Take new picture and download it", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT /* | SANE_CAP_ADVANCED */ , SANE_CONSTRAINT_NONE, {NULL} } , #define DC240_OPT_LOWRES 6 { "lowres", "Low Resolution", "Resolution of new pictures", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE /* | SANE_CAP_ADVANCED */ , SANE_CONSTRAINT_NONE, {NULL} } , #define DC240_OPT_ERASE 7 { "erase", "Erase", "Erase the picture after downloading", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC240_OPT_DEFAULT 8 { "default-enhancements", "Defaults", "Set default values for enhancement controls.", SANE_TYPE_BUTTON, SANE_UNIT_NONE, 0, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC240_OPT_INIT_DC240 9 { "camera-init", "Re-establish Communications", "Re-establish communications with camera (in case of timeout, etc.)", SANE_TYPE_BUTTON, SANE_UNIT_NONE, 0, SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT, SANE_CONSTRAINT_NONE, {NULL} } , #define DC240_OPT_AUTOINC 10 { "autoinc", "Auto Increment", "Increment image number after each scan", SANE_TYPE_BOOL, SANE_UNIT_NONE, sizeof (SANE_Word), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED, SANE_CONSTRAINT_NONE, {NULL} } , }; static SANE_Parameters parms = { SANE_FRAME_RGB, 0, 0, /* Number of bytes returned per scan line: */ 0, /* Number of pixels per scan line. */ 0, /* Number of lines for the current scan. */ 8, /* Number of bits per sample. */ }; static SANE_Byte shoot_pck[] = SHOOT_PCK; static SANE_Byte init_pck[] = INIT_PCK; static SANE_Byte thumb_pck[] = THUMBS_PCK; static SANE_Byte pic_pck[] = PICS_PCK; static SANE_Byte pic_info_pck[] = PICS_INFO_PCK; static SANE_Byte info_pck[] = INFO_PCK; static SANE_Byte erase_pck[] = ERASE_PCK; static SANE_Byte res_pck[] = RES_PCK; static SANE_Byte open_card_pck[] = OPEN_CARD_PCK; static SANE_Byte read_dir_pck[] = READ_DIR_PCK; static struct pkt_speed speeds[] = SPEEDS; static struct termios tty_orig; SANE_Byte dir_buf2[2 + CAMDIRENTRYSIZE * DIRENTRIES]; static struct cam_dirlist *dir_head = NULL; static SANE_Byte info_buf[256]; static SANE_Byte name_buf[60]; #include #include static SANE_Int send_pck (SANE_Int fd, SANE_Byte * pck) { SANE_Int n; SANE_Byte r = 0xf0; /* prime the loop with a "camera busy" */ DBG (127, "send_pck<%x %x %x %x %x %x %x %x>\n", pck[0], pck[1], pck[2], pck[3], pck[4], pck[5], pck[6], pck[7]); /* keep trying if camera says it's busy */ while (r == 0xf0) { if (write (fd, (char *) pck, 8) != 8) { DBG (1, "send_pck: error: write returned -1\n"); return -1; } /* need to wait before we read command result */ usleep (cmdrespause); if ((n = read (fd, (char *) &r, 1)) != 1) { DBG (1, "send_pck: error: read returned -1\n"); return -1; } } DBG (127, "send_pck: read one byte result from camera = %x\n", r); return (r == 0xd1) ? 0 : -1; } static SANE_Int init_dc240 (DC240 * camera) { struct termios tty_new; SANE_Int speed_index; SANE_Char buf[5], n; DBG (1, "DC-240 Backend 05/16/01\n"); for (speed_index = 0; speed_index < NELEMS (speeds); speed_index++) { if (speeds[speed_index].baud == camera->baud) { init_pck[2] = speeds[speed_index].pkt_code[0]; init_pck[3] = speeds[speed_index].pkt_code[1]; break; } } if (init_pck[2] == 0) { DBG (1, "unsupported baud rate.\n"); return -1; } /* Open device file. */ if ((camera->fd = open (camera->tty_name, O_RDWR)) == -1) { DBG (1, "init_dc240: error: could not open %s for read/write\n", camera->tty_name); return -1; } /* Save old device information to restore when we are done. */ if (tcgetattr (camera->fd, &tty_orig) == -1) { DBG (1, "init_dc240: error: could not get attributes\n"); return -1; } memcpy ((char *) &tty_new, (char *) &tty_orig, sizeof (struct termios)); /* We need the device to be raw. 8 bits even parity on 9600 baud to start. */ #ifdef HAVE_CFMAKERAW cfmakeraw (&tty_new); #else /* Modified to set the port REALLY as required (9600, 8b, 1sb, NO parity). Code inspired by the gPhoto2 serial port setup */ /* input control settings */ tty_new.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC | IXANY | IXON | IXOFF | INPCK | ISTRIP); tty_new.c_iflag |= (BRKINT | IGNPAR); /* output control settings */ tty_new.c_oflag &= ~OPOST; /* hardware control settings */ tty_new.c_cflag = (tty_new.c_cflag & ~CSIZE) | CS8; tty_new.c_cflag &= ~(PARENB | PARODD | CSTOPB); # if defined(__sgi) tty_new.c_cflag &= ~CNEW_RTSCTS; # else /* OS/2 doesn't have CRTSCTS - will this work for them? */ # ifdef CRTSCTS tty_new.c_cflag &= ~CRTSCTS; # endif # endif tty_new.c_cflag |= CLOCAL | CREAD; #endif /* line discipline settings */ tty_new.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE | ECHOK | IEXTEN); tty_new.c_cc[VMIN] = 0; tty_new.c_cc[VTIME] = 5; cfsetospeed (&tty_new, B9600); cfsetispeed (&tty_new, B9600); if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) { DBG (1, "init_dc240: error: could not set attributes\n"); return -1; } /* send a break to get it back to a known state */ /* Used to supply a non-zero argument to tcsendbreak(), TCSBRK, * and TCSBRKP, but that is system dependent. e.g. on irix a non-zero * value does a drain instead of a break. A zero value is universally * used to send a break. */ #ifdef HAVE_TCSENDBREAK tcsendbreak (camera->fd, 0); # if defined(__sgi) tcdrain (camera->fd); # endif # elif defined(TCSBRKP) ioctl (camera->fd, TCSBRKP, 0); # elif defined(TCSBRK) ioctl (camera->fd, TCSBRK, 0); #endif /* and wait for it to recover from the break */ #ifdef HAVE_USLEEP usleep (breakpause); #else sleep (1); #endif /* We seem to get some garbage following the break, so * read anything pending */ n = read (camera->fd, buf, 5); DBG (127, "init_dc240 flushed %d bytes: %x %x %x %x %x\n", n, buf[0], buf[1], buf[2], buf[3], buf[4]); if (send_pck (camera->fd, init_pck) == -1) { /* * The camera always powers up at 9600, so we try * that first. However, it may be already set to * a different speed. Try the entries in the table: */ tcsetattr (camera->fd, TCSANOW, &tty_orig); DBG (1, "init_dc240: error: no response from camera\n"); return -1; } n = read (camera->fd, buf, 5); DBG (127, "init_dc240 flushed %d bytes: %x %x %x %x %x\n", n, buf[0], buf[1], buf[2], buf[3], buf[4]); /* Set speed to requested speed. */ cfsetospeed (&tty_new, Camera.baud); cfsetispeed (&tty_new, Camera.baud); if (tcsetattr (camera->fd, TCSANOW, &tty_new) == -1) { DBG (1, "init_dc240: error: could not set attributes\n"); return -1; } if (send_pck (camera->fd, open_card_pck) == -1) { DBG (1, "init_dc240: error: send_pck returned -1\n"); return -1; } if (end_of_data (camera->fd) == -1) { DBG (1, "init_dc240: error: end_of_data returned -1\n"); return -1; } return camera->fd; } static void close_dc240 (SANE_Int fd) { /* * Put the camera back to 9600 baud */ if (close (fd) == -1) { DBG (1, "close_dc240: error: could not close device\n"); } } int get_info (DC240 * camera) { SANE_Char f[] = "get_info"; SANE_Byte buf[256]; SANE_Int n; struct cam_dirlist *e; if (send_pck (camera->fd, info_pck) == -1) { DBG (1, "%s: error: send_pck returned -1\n", f); return -1; } DBG (9, "%s: read info packet\n", f); if (read_data (camera->fd, buf, 256) == -1) { DBG (1, "%s: error: read_data returned -1\n", f); return -1; } if (end_of_data (camera->fd) == -1) { DBG (1, "%s: error: end_of_data returned -1\n", f); return -1; } camera->model = buf[1]; if (camera->model != 0x5) { DBG (0, "Camera model (%d) is not DC-240 (5). " "Only the DC-240 is supported by this driver.\n", camera->model); } camera->ver_major = buf[2]; camera->ver_minor = buf[3]; camera->pic_taken = buf[14] << 8 | buf[15]; DBG (4, "pic_taken=%d\n", camera->pic_taken); camera->pic_left = buf[64] << 8 | buf[65]; DBG (4, "pictures left (at current res)=%d\n", camera->pic_left); camera->flags.low_batt = buf[8]; DBG (4, "battery=%d (0=OK, 1=weak, 2=empty)\n", camera->flags.low_batt); DBG (4, "AC adapter status=%d\n", buf[9]); dc240_opt_lowres = !buf[79]; if (Camera.pic_taken == 0) { sod[DC240_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; image_range.min = 0; image_range.max = 0; } else { sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; image_range.min = 1; image_range.max = Camera.pic_taken; } n = read_dir ("\\PCCARD\\DCIM\\*.*"); /* If we've already got a folder_list, free it up before starting * the new one */ if (folder_list != NULL) { int tmp; for (tmp = 0; folder_list[tmp]; tmp++) { free (folder_list[tmp]); } free (folder_list); } folder_list = (SANE_String * *)malloc ((n + 1) * sizeof (SANE_String *)); for (e = dir_head, n = 0; e; e = e->next, n++) { folder_list[n] = (SANE_String *) strdup (e->name); if (strchr ((char *) folder_list[n], ' ')) { *strchr ((char *) folder_list[n], ' ') = '\0'; } } folder_list[n] = NULL; sod[DC240_OPT_FOLDER].constraint.string_list = (SANE_String_Const *) folder_list; return 0; } /* NEW */ static SANE_Int read_data (SANE_Int fd, SANE_Byte * buf, SANE_Int sz) { SANE_Byte ccsum; SANE_Byte rcsum; SANE_Byte c; SANE_Int retries = 0; SANE_Int n; SANE_Int r = 0; SANE_Int i; while (retries++ < 5) { /* * If this is not the first time through, then it must be * a retry - signal the camera that we didn't like what * we got. In either case, start filling the packet */ if (retries != 1) { DBG (2, "Attempt retry %d\n", retries); c = 0xe3; if (write (fd, (char *) &c, 1) != 1) { DBG (1, "read_data: error: write ack\n"); return -1; } } /* read the control byte */ if (read (fd, &c, 1) != 1) { DBG (3, "read_data: error: " "read for packet control byte returned bad stat!us\n"); return -1; } if (c != 1 && c != 0) { DBG (1, "read_data: error: incorrect packet control byte: %02x\n", c); return -1; } for (n = 0; n < sz && (r = read (fd, (char *) &buf[n], sz - n)) > 0; n += r); if (r <= 0) { DBG (2, "read_data: warning: read returned -1\n"); continue; } if (n < sz || read (fd, &rcsum, 1) != 1) { DBG (2, "read_data: warning: buffer underrun or no checksum\n"); continue; } for (i = 0, ccsum = 0; i < n; i++) ccsum ^= buf[i]; if (ccsum != rcsum) { DBG (2, "read_data: warning: " "bad checksum (got %02x != expected %02x)\n", rcsum, ccsum); continue; } /* If we got this far, then the packet is OK */ break; } c = 0xd2; if (write (fd, (char *) &c, 1) != 1) { DBG (1, "read_data: error: write ack\n"); return -1; } return 0; } static SANE_Int end_of_data (SANE_Int fd) { SANE_Int n; SANE_Byte c; do { /* loop until the camera isn't busy */ if ((n = read (fd, &c, 1)) == -1) { DBG (1, "end_of_data: error: read returned -1\n"); return -1; } if (n == 1 && c == 0) /* got successful end of data */ return 0; /* return success */ if (n == 1) { DBG (127, "end_of_data: got %x while waiting\n", c); } else { DBG (127, "end_of_data: waiting...\n"); } sleep (1); /* not too fast */ } /* It's not documented, but we see a d1 after snapping a picture */ while (c == 0xf0 || c == 0xd1); /* Accck! Not busy, but not a good end of data either */ if (c != 0) { DBG (1, "end_of_data: error: bad EOD from camera (%02x)\n", (unsigned) c); return -1; } return 0; /* should never get here but shut gcc -Wall up */ } static SANE_Int erase (SANE_Int fd) { if (send_pck (fd, erase_pck) == -1) { DBG (1, "erase: error: send_pck returned -1\n"); return -1; } if (send_data (name_buf) == -1) { DBG (1, "erase: error: send_data returned -1\n"); return SANE_STATUS_INVAL; } if (end_of_data (fd) == -1) { DBG (1, "erase: error: end_of_data returned -1\n"); return -1; } return 0; } static SANE_Int change_res (SANE_Int fd, SANE_Byte res) { SANE_Char f[] = "change_res"; DBG (127, "%s called, low_res=%d\n", f, res); if (res != 0 && res != 1) { DBG (1, "%s: error: unsupported resolution\n", f); return -1; } /* cameras resolution semantics are opposite of ours */ res = !res; DBG (127, "%s: setting res to %d\n", f, res); res_pck[2] = res; if (send_pck (fd, res_pck) == -1) { DBG (1, "%s: error: send_pck returned -1\n", f); } if (end_of_data (fd) == -1) { DBG (1, "%s: error: end_of_data returned -1\n", f); } return 0; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { SANE_Char f[] = "sane_init"; SANE_Char dev_name[PATH_MAX], *p; size_t len; FILE *fp; SANE_Int baud; DBG_INIT (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (DC240_CONFIG_FILE); /* defaults */ Camera.baud = DEFAULT_BAUD_RATE; Camera.tty_name = DEFAULT_TTY; if (!fp) { /* default to /dev/whatever instead of insisting on config file */ DBG (1, "%s: missing config file '%s'\n", f, DC240_CONFIG_FILE); } else { while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { dev_name[sizeof (dev_name) - 1] = '\0'; DBG (20, "%s: config- %s\n", f, dev_name); if (dev_name[0] == '#') continue; /* ignore line comments */ len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ if (strncmp (dev_name, "port=", 5) == 0) { p = strchr (dev_name, '/'); if (p) Camera.tty_name = strdup (p); DBG (20, "Config file port=%s\n", Camera.tty_name); } else if (strncmp (dev_name, "baud=", 5) == 0) { baud = atoi (&dev_name[5]); switch (baud) { case 9600: Camera.baud = B9600; break; case 19200: Camera.baud = B19200; break; case 38400: Camera.baud = B38400; break; #ifdef B57600 case 57600: Camera.baud = B57600; break; #endif #ifdef B115200 case 115200: Camera.baud = B115200; break; #endif } DBG (20, "Config file baud=%d\n", Camera.baud); } else if (strcmp (dev_name, "dumpinquiry") == 0) { dumpinquiry = SANE_TRUE; } else if (strncmp (dev_name, "cmdrespause=", 12) == 0) { cmdrespause = atoi (&dev_name[12]); DBG (20, "Config file cmdrespause=%lu\n", cmdrespause); } else if (strncmp (dev_name, "breakpause=", 11) == 0) { breakpause = atoi (&dev_name[11]); DBG (20, "Config file breakpause=%lu\n", breakpause); } } fclose (fp); } if (init_dc240 (&Camera) == -1) return SANE_STATUS_INVAL; if (get_info (&Camera) == -1) { DBG (1, "error: could not get info\n"); close_dc240 (Camera.fd); return SANE_STATUS_INVAL; } /* load the current images array */ get_pictures_info (); if (Camera.pic_taken == 0) { Camera.current_picture_number = 0; parms.bytes_per_line = 0; parms.pixels_per_line = 0; parms.lines = 0; } else { Camera.current_picture_number = 1; set_res (Camera.Pictures[Camera.current_picture_number - 1].low_res); } if (dumpinquiry) { DBG (0, "\nCamera information:\n~~~~~~~~~~~~~~~~~\n\n"); DBG (0, "Model...........: DC%s\n", "240"); DBG (0, "Firmware version: %d.%d\n", Camera.ver_major, Camera.ver_minor); DBG (0, "Pictures........: %d/%d\n", Camera.pic_taken, Camera.pic_taken + Camera.pic_left); DBG (0, "Battery state...: %s\n", Camera.flags.low_batt == 0 ? "good" : (Camera.flags.low_batt == 1 ? "weak" : "empty")); } return SANE_STATUS_GOOD; } void sane_exit (void) { } /* Device select/open/close */ static const SANE_Device dev[] = { { "0", "Kodak", "DC-240", "still camera"}, }; static const SANE_Device *devlist[] = { dev + 0, 0 }; SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { DBG (127, "sane_get_devices called\n"); *device_list = devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { SANE_Int i; DBG (127, "sane_open for device %s\n", devicename); if (!devicename[0]) { i = 0; } else { for (i = 0; i < NELEMS (dev); ++i) { if (strcmp (devicename, dev[i].name) == 0) { break; } } } if (i >= NELEMS (dev)) { return SANE_STATUS_INVAL; } if (is_open) { return SANE_STATUS_DEVICE_BUSY; } is_open = 1; *handle = MAGIC; DBG (4, "sane_open: pictures taken=%d\n", Camera.pic_taken); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { DBG (127, "sane_close called\n"); if (handle == MAGIC) is_open = 0; DBG (127, "sane_close returning\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { if (handle != MAGIC || !is_open) return NULL; /* wrong device */ if (option < 0 || option >= NELEMS (sod)) return NULL; return &sod[option]; } static SANE_Int myinfo = 0; SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { SANE_Status status; if (option < 0 || option >= NELEMS (sod)) return SANE_STATUS_INVAL; /* Unknown option ... */ /* Need to put this DBG line after the range check on option */ DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n", handle, sod[option].title, (action == SANE_ACTION_SET_VALUE ? "SET" : (action == SANE_ACTION_GET_VALUE ? "GET" : "SETAUTO")), value, (void *) info); if (handle != MAGIC || !is_open) return SANE_STATUS_INVAL; /* Unknown handle ... */ switch (action) { case SANE_ACTION_SET_VALUE: /* Can't set disabled options */ if (!SANE_OPTION_IS_ACTIVE (sod[option].cap)) { return (SANE_STATUS_INVAL); } /* initialize info to zero - we'll OR in various values later */ if (info) *info = 0; status = sanei_constrain_value (sod + option, value, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (2, "Constraint error in control_option\n"); return status; } switch (option) { case DC240_OPT_IMAGE_NUMBER: if (*(SANE_Word *) value <= Camera.pic_taken) Camera.current_picture_number = *(SANE_Word *) value; else Camera.current_picture_number = Camera.pic_taken; myinfo |= SANE_INFO_RELOAD_PARAMS; /* get the image's resolution, unless the camera has no * pictures yet */ if (Camera.pic_taken != 0) { set_res (Camera. Pictures[Camera.current_picture_number - 1].low_res); } break; case DC240_OPT_THUMBS: dc240_opt_thumbnails = !!*(SANE_Word *) value; /* Thumbnail forces an image size change: */ myinfo |= SANE_INFO_RELOAD_PARAMS; if (Camera.pic_taken != 0) { set_res (Camera. Pictures[Camera.current_picture_number - 1].low_res); } break; case DC240_OPT_SNAP: switch (*(SANE_Bool *) value) { case SANE_TRUE: dc240_opt_snap = SANE_TRUE; break; case SANE_FALSE: dc240_opt_snap = SANE_FALSE; break; default: return SANE_STATUS_INVAL; } /* Snap forces new image size and changes image range */ myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; /* if we are snapping a new one */ if (dc240_opt_snap) { /* activate the resolution setting */ sod[DC240_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE; /* and de-activate the image number selector */ sod[DC240_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; } else { /* deactivate the resolution setting */ sod[DC240_OPT_LOWRES].cap |= SANE_CAP_INACTIVE; /* and activate the image number selector */ sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; } /* set params according to resolution settings */ set_res (dc240_opt_lowres); break; case DC240_OPT_LOWRES: dc240_opt_lowres = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; /* XXX - change the number of pictures left depending on resolution perhaps just call get_info again? */ set_res (dc240_opt_lowres); break; case DC240_OPT_ERASE: dc240_opt_erase = !!*(SANE_Word *) value; break; case DC240_OPT_AUTOINC: dc240_opt_autoinc = !!*(SANE_Word *) value; break; case DC240_OPT_FOLDER: DBG (1, "FIXME set folder not implemented yet\n"); break; case DC240_OPT_DEFAULT: dc240_opt_thumbnails = 0; dc240_opt_snap = 0; /* deactivate the resolution setting */ sod[DC240_OPT_LOWRES].cap |= SANE_CAP_INACTIVE; /* and activate the image number selector */ sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; DBG (1, "Fixme: Set all defaults here!\n"); break; case DC240_OPT_INIT_DC240: if ((Camera.fd = init_dc240 (&Camera)) == -1) { return SANE_STATUS_INVAL; } if (get_info (&Camera) == -1) { DBG (1, "error: could not get info\n"); close_dc240 (Camera.fd); return SANE_STATUS_INVAL; } /* load the current images array */ get_pictures_info (); myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_GET_VALUE: /* Can't return status for disabled options */ if (!SANE_OPTION_IS_ACTIVE (sod[option].cap)) { return (SANE_STATUS_INVAL); } switch (option) { case 0: *(SANE_Word *) value = NELEMS (sod); break; case DC240_OPT_IMAGE_NUMBER: *(SANE_Word *) value = Camera.current_picture_number; break; case DC240_OPT_THUMBS: *(SANE_Word *) value = dc240_opt_thumbnails; break; case DC240_OPT_SNAP: *(SANE_Word *) value = dc240_opt_snap; break; case DC240_OPT_LOWRES: *(SANE_Word *) value = dc240_opt_lowres; break; case DC240_OPT_ERASE: *(SANE_Word *) value = dc240_opt_erase; break; case DC240_OPT_AUTOINC: *(SANE_Word *) value = dc240_opt_autoinc; break; case DC240_OPT_FOLDER: strcpy ((char *) value, (char *) folder_list[current_folder]); break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_AUTO: switch (option) { default: return SANE_STATUS_UNSUPPORTED; /* We are DUMB */ } } if (info && action == SANE_ACTION_SET_VALUE) { *info = myinfo; myinfo = 0; } return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { SANE_Int rc = SANE_STATUS_GOOD; DBG (127, "sane_get_params called, wid=%d,height=%d\n", parms.pixels_per_line, parms.lines); if (handle != MAGIC || !is_open) rc = SANE_STATUS_INVAL; /* Unknown handle ... */ parms.last_frame = SANE_TRUE; /* Have no idea what this does */ *params = parms; DBG (127, "sane_get_params return %d\n", rc); return rc; } typedef struct { struct jpeg_source_mgr pub; JOCTET *buffer; } my_source_mgr; typedef my_source_mgr *my_src_ptr; METHODDEF (void) jpeg_init_source (j_decompress_ptr __sane_unused__ cinfo) { /* nothing to do */ } METHODDEF (boolean) jpeg_fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; if (read_data (Camera.fd, src->buffer, 512) == -1) { DBG (5, "sane_start: read_data failed\n"); src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; return FALSE; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = 512; return TRUE; } METHODDEF (void) jpeg_skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr) cinfo->src; if (num_bytes > 0) { while (num_bytes > (long) src->pub.bytes_in_buffer) { num_bytes -= (long) src->pub.bytes_in_buffer; (void) jpeg_fill_input_buffer (cinfo); } } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; } static SANE_Byte linebuffer[HIGHRES_WIDTH * 3]; static SANE_Int linebuffer_size = 0; static SANE_Int linebuffer_index = 0; METHODDEF (void) jpeg_term_source (j_decompress_ptr __sane_unused__ cinfo) { /* no work necessary here */ } SANE_Status sane_start (SANE_Handle handle) { SANE_Int i; DBG (127, "sane_start called\n"); if (handle != MAGIC || !is_open || (Camera.current_picture_number == 0 && dc240_opt_snap == SANE_FALSE)) return SANE_STATUS_INVAL; /* Unknown handle ... */ if (Camera.scanning) return SANE_STATUS_EOF; /* * This shouldn't normally happen, but we allow it as a special case * when batch/autoinc are in effect. The first illegal picture number * terminates the scan */ if (Camera.current_picture_number > Camera.pic_taken) { return SANE_STATUS_INVAL; } if (dc240_opt_snap) { /* * Don't allow picture unless there is room in the * camera. */ if (Camera.pic_left == 0) { DBG (3, "No room to store new picture\n"); return SANE_STATUS_INVAL; } if (snap_pic (Camera.fd) == SANE_STATUS_INVAL) { DBG (1, "Failed to snap new picture\n"); return SANE_STATUS_INVAL; } } if (dc240_opt_thumbnails) { if (send_pck (Camera.fd, thumb_pck) == -1) { DBG (1, "sane_start: error: send_pck returned -1\n"); return SANE_STATUS_INVAL; } /* Picture size should have been set when thumbnails were * selected. But, check just in case */ if (parms.pixels_per_line != 160 || parms.bytes_per_line != 160 * 3 || parms.lines != 120) { DBG (1, "sane_start: fixme! thumbnail image size is wrong\n"); return SANE_STATUS_INVAL; } } else { if (send_pck (Camera.fd, pic_pck) == -1) { DBG (1, "sane_start: error: send_pck returned -1\n"); return SANE_STATUS_INVAL; } } { my_src_ptr src; struct jpeg_error_mgr jerr; SANE_Int n; SANE_Char f[] = "sane_start"; SANE_Char path[256]; struct cam_dirlist *e; name_buf[0] = 0x80; for (n = 1, e = dir_head; e; n++, e = e->next) { if (n == Camera.current_picture_number) break; } strcpy (path, "\\PCCARD\\DCIM\\"); strcat (path, (char *) folder_list[current_folder]); strcat (path, "\\"); strcat (path, e->name); path[strlen (path) - 3] = '\0'; strcat (path, ".JPG"); DBG (9, "%s: pic to read is %d name is %s\n", f, n, path); strcpy ((char *) &name_buf[1], path); for (i = 49; i <= 56; i++) { name_buf[i] = 0xff; } if (send_data (name_buf) == -1) { DBG (1, "%s: error: send_data returned -1\n", f); return SANE_STATUS_INVAL; } cinfo.err = jpeg_std_error (&jerr); jpeg_create_decompress (&cinfo); cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem-> alloc_small) ((j_common_ptr) & cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr)); src = (my_src_ptr) cinfo.src; src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) & cinfo, JPOOL_PERMANENT, 1024 * sizeof (JOCTET)); src->pub.init_source = jpeg_init_source; src->pub.fill_input_buffer = jpeg_fill_input_buffer; src->pub.skip_input_data = jpeg_skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* default */ src->pub.term_source = jpeg_term_source; src->pub.bytes_in_buffer = 0; src->pub.next_input_byte = NULL; (void) jpeg_read_header (&cinfo, TRUE); dest_mgr = sanei_jpeg_jinit_write_ppm (&cinfo); (void) jpeg_start_decompress (&cinfo); linebuffer_size = 0; linebuffer_index = 0; } Camera.scanning = SANE_TRUE; /* don't overlap scan requests */ return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle __sane_unused__ handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { SANE_Int lines = 0; SANE_Char filename_buf[256]; if (Camera.scanning == SANE_FALSE) { return SANE_STATUS_INVAL; } /* If there is anything in the buffer, satisfy the read from there */ if (linebuffer_size && linebuffer_index < linebuffer_size) { *length = linebuffer_size - linebuffer_index; if (*length > max_length) { *length = max_length; } memcpy (data, linebuffer + linebuffer_index, *length); linebuffer_index += *length; return SANE_STATUS_GOOD; } if (cinfo.output_scanline >= cinfo.output_height) { *length = 0; /* clean up comms with the camera */ if (end_of_data (Camera.fd) == -1) { DBG (1, "sane_read: error: end_of_data returned -1\n"); return SANE_STATUS_INVAL; } if (dc240_opt_erase) { DBG (127, "sane_read bp%d, erase image\n", __LINE__); if (erase (Camera.fd) == -1) { DBG (1, "Failed to erase memory\n"); return SANE_STATUS_INVAL; } Camera.pic_taken--; Camera.pic_left++; Camera.current_picture_number = Camera.pic_taken; image_range.max--; myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; strcpy ((char *) filename_buf, strrchr ((char *) name_buf + 1, '\\') + 1); strcpy (strrchr ((char *) filename_buf, '.'), "JPG"); dir_delete ((SANE_String) filename_buf); } if (dc240_opt_autoinc) { if (Camera.current_picture_number <= Camera.pic_taken) { Camera.current_picture_number++; myinfo |= SANE_INFO_RELOAD_PARAMS; /* get the image's resolution */ set_res (Camera.Pictures[Camera.current_picture_number - 1]. low_res); } DBG (4, "Increment count to %d (total %d)\n", Camera.current_picture_number, Camera.pic_taken); } return SANE_STATUS_EOF; } /* XXX - we should read more than 1 line at a time here */ lines = 1; (void) jpeg_read_scanlines (&cinfo, dest_mgr->buffer, lines); (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, lines, (char *) linebuffer); *length = cinfo.output_width * cinfo.output_components * lines; linebuffer_size = *length; linebuffer_index = 0; if (*length > max_length) { *length = max_length; } memcpy (data, linebuffer + linebuffer_index, *length); linebuffer_index += *length; return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle __sane_unused__ handle) { unsigned char cancel_byte[] = { 0xe4 }; if (Camera.scanning) { /* Flush any pending data from the camera before continuing */ { SANE_Int n; SANE_Char flush[1024]; do { sleep (1); n = read (Camera.fd, flush, 1024); if (n > 0) { DBG (127, "%s: flushed %d bytes\n", "sane_cancel", n); } else { DBG (127, "%s: nothing to flush\n", "sane_cancel"); } } while (n > 0); } if (cinfo.output_scanline < cinfo.output_height) { write (Camera.fd, cancel_byte, 1); } Camera.scanning = SANE_FALSE; /* done with scan */ } else DBG (4, "sane_cancel: not scanning - nothing to do\n"); } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { /* sane_set_io_mode() is only valid during a scan */ if (Camera.scanning) { if (non_blocking == SANE_FALSE) { return SANE_STATUS_GOOD; } else { return SANE_STATUS_UNSUPPORTED; } } else { /* We aren't currently scanning */ return SANE_STATUS_INVAL; } } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { return SANE_STATUS_UNSUPPORTED; } /* * get_pictures_info - load information about all pictures currently in * camera: Mainly the mapping of picture number * to picture name, and the resolution of each picture. */ static PictureInfo * get_pictures_info (void) { SANE_Char f[] = "get_pictures_info"; SANE_Char path[256]; SANE_Int num_pictures; SANE_Int p; PictureInfo *pics; if (Camera.Pictures) { free (Camera.Pictures); Camera.Pictures = NULL; } strcpy (path, "\\PCCARD\\DCIM\\"); strcat (path, (char *) folder_list[current_folder]); strcat (path, "\\*.*"); num_pictures = read_dir (path); if (num_pictures != Camera.pic_taken) { DBG (2, "%s: warning: Number of pictures in directory (%d) doesn't match camera status table (%d). Using directory count\n", f, num_pictures, Camera.pic_taken); Camera.pic_taken = num_pictures; image_range.max = num_pictures; } if ((pics = (PictureInfo *) malloc (Camera.pic_taken * sizeof (PictureInfo))) == NULL) { DBG (1, "%s: error: allocate memory for pictures array\n", f); return NULL; } for (p = 0; p < Camera.pic_taken; p++) { if (get_picture_info (pics + p, p) == -1) { free (pics); return NULL; } } Camera.Pictures = pics; return pics; } static SANE_Int get_picture_info (PictureInfo * pic, SANE_Int p) { SANE_Char f[] = "get_picture_info"; SANE_Int n; struct cam_dirlist *e; DBG (4, "%s: info for pic #%d\n", f, p); for (n = 0, e = dir_head; e && n < p; n++, e = e->next) ; DBG (4, "Name is %s\n", e->name); read_info (e->name); /* Validate picture info * byte 0 - 1 == picture info * byte 1 - 5 == DC240 Camera * byte 2 - 3 == JFIF file * byte 6 - 0 == Image is complete */ if (info_buf[0] != 1 || info_buf[1] != 5 || info_buf[2] != 3 || info_buf[6] != 0) { DBG (1, "%s: error: Image %s does not come from a DC-240.\n", f, e->name); return -1; } pic->low_res = info_buf[3] == 0 ? SANE_TRUE : SANE_FALSE; /* * byte 12 - Year MSB * byte 13 - Year LSB * byte 14 - Month * byte 15 - Day * byte 16 - Hour * byte 17 - Minute * byte 18 - Second */ DBG (1, "Picture %d taken %02d/%02d/%02d %02d:%02d:%02d\n", p, info_buf[14], info_buf[15], (info_buf[12] << 8) + info_buf[13], info_buf[16], info_buf[17], info_buf[18]); return 0; } /* * snap_pic - take a picture (and call get_pictures_info to re-create * the directory related data structures) */ static SANE_Status snap_pic (SANE_Int fd) { SANE_Char f[] = "snap_pic"; #if 0 /* Just checking... It looks like after snapping the picture, we * get two "d1" ACK responses back, even though the documentation seems * to say that there should only be one. I thought the first one could * have been an unread response from an earlier command, so I * I tried flushing any data here. Still seeing the multiple * d1 bytes, however... */ { SANE_Int n; SANE_Char flush[10]; n = read (Camera.fd, flush, 10); if (n > 0) { DBG (127, "%s: flushed %d bytes\n", f, n); } else { DBG (127, "%s: nothing to flush\n", f); } } #endif /* make sure camera is set to our settings state */ if (change_res (Camera.fd, dc240_opt_lowres) == -1) { DBG (1, "%s: Failed to set resolution\n", f); return SANE_STATUS_INVAL; } /* take the picture */ if (send_pck (fd, shoot_pck) == -1) { DBG (1, "%s: error: send_pck returned -1\n", f); return SANE_STATUS_INVAL; } else { if (end_of_data (Camera.fd) == -1) { DBG (1, "%s: error: end_of_data returned -1\n", f); return SANE_STATUS_INVAL; } } Camera.pic_taken++; Camera.pic_left--; Camera.current_picture_number = Camera.pic_taken; image_range.max++; sod[DC240_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; /* add this one to the Pictures array */ if (get_pictures_info () == NULL) { DBG (1, "%s: Failed to get new picture info\n", f); /* XXX - I guess we should try to erase the image here */ return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /* * read_dir - read a list of file names from the specified directory * and create a linked list of file name entries in * alphabetical order. The first entry in the list will * be "picture #1", etc. */ static SANE_Int read_dir (SANE_String dir) { SANE_Int retval = 0; SANE_Byte buf[256]; SANE_Byte *next_buf; SANE_Int i, entries; SANE_Byte r = 0xf0; /* prime the loop with a "camera busy" */ SANE_Char f[] = "read_dir"; struct cam_dirlist *e, *next; /* Free up current list */ for (e = dir_head; e; e = next) { DBG (127, "%s: free entry %s\n", f, e->name); next = e->next; free (e); } dir_head = NULL; if (send_pck (Camera.fd, read_dir_pck) == -1) { DBG (1, "%s: error: send_pck returned -1\n", f); return -1; } buf[0] = 0x80; strcpy ((char *) &buf[1], dir); for (i = 49; i <= 56; i++) { buf[i] = 0xff; } if (send_data (buf) == -1) { DBG (1, "%s: error: send_data returned -1\n", f); return -1; } if (read_data (Camera.fd, (SANE_Byte *) & dir_buf2, 256) == -1) { DBG (1, "%s: error: read_data returned -1\n", f); return -1; } entries = (dir_buf2[0] << 8) + dir_buf2[1]; DBG (127, "%s: result of dir read is %x, number of entries=%d\n", f, r, entries); if (entries > 1001) { DBG (1, "%s: error: more than 999 pictures not supported yet\n", f); return -1; } /* Determine if it's time to read another 256 byte buffer from the camera */ next_buf = ((SANE_Byte *) & dir_buf2) + 256; while (dir_buf2 + 2 + CAMDIRENTRYSIZE * entries >= (SANE_Byte *) next_buf) { DBG (127, "%s: reading additional directory buffer\n", f); if (read_data (Camera.fd, next_buf, 256) == -1) { DBG (1, "%s: error: read_data returned -1\n", f); return -1; } next_buf += 256; } for (i = 0; i < entries; i++) { /* Hack: I don't know what attr is used for, so setting it * to zero is a convenient way to put in the null terminator */ get_attr (i) = 0; DBG (127, "%s: entry=%s\n", f, get_name (i)); if ((get_name (i))[0] == '.') { continue; } if (dir_insert ((struct cam_dirent *) &dir_buf2[2 + CAMDIRENTRYSIZE * i]) != 0) { DBG (1, "%s: error: failed to insert dir entry\n", f); return -1; } retval++; } if (end_of_data (Camera.fd) == -1) { DBG (1, "%s: error: end_of_data returned -1\n", f); return -1; } return retval; } /* * read_info - read the info block from camera for the specified file */ static SANE_Int read_info (SANE_String fname) { SANE_Byte buf[256]; SANE_Int i; SANE_Char f[] = "read_info"; SANE_Char path[256]; strcpy (path, "\\PCCARD\\DCIM\\"); strcat (path, (char *) folder_list[current_folder]); strcat (path, "\\"); strcat (path, fname); path[strlen (path) - 3] = '\0'; strcat (path, ".JPG"); if (send_pck (Camera.fd, pic_info_pck) == -1) { DBG (1, "%s: error: send_pck returned -1\n", f); return SANE_STATUS_INVAL; } buf[0] = 0x80; strcpy ((char *) &buf[1], path); for (i = 49; i <= 56; i++) { buf[i] = 0xff; } if (send_data (buf) == -1) { DBG (1, "%s: error: send_data returned -1\n", f); return SANE_STATUS_INVAL; } if (read_data (Camera.fd, info_buf, 256) != 0) { DBG (1, "%s: error: Failed in read_data\n", f); return -1; } DBG (9, "%s: data type=%d, cam type=%d, file type=%d\n", f, info_buf[0], info_buf[1], info_buf[2]); if (end_of_data (Camera.fd) == -1) { DBG (1, "%s: error: end_of_data returned -1\n", f); return -1; } return 0; } /* * send_data - Send a data block - assumes all data blocks to camera * are 60 bytes long */ static SANE_Int send_data (SANE_Byte * buf) { SANE_Byte r = 0xf0; /* prime the loop with a "camera busy" */ SANE_Int i, n; SANE_Byte csum; SANE_Char f[] = "send_data"; for (i = 1, csum = 0; i < 59; i++) { csum ^= buf[i]; } buf[59] = csum; DBG (127, "%s: about to send data block\n", f); /* keep trying if camera says it's busy */ while (r == 0xf0) { if (write (Camera.fd, (char *) buf, 60) != 60) { DBG (1, "%s: error: write returned -1\n", f); return -1; } /* need to wait before we read command result */ #ifdef HAVE_USLEEP usleep (cmdrespause); #else sleep (1); #endif if ((n = read (Camera.fd, (char *) &r, 1)) != 1) { DBG (1, "%s: error: read returned -1\n", f); return -1; } } if (r != 0xd2) { DBG (1, "%s: error: bad response to send_data (%d)\n", f, r); return -1; } return 0; } /* * dir_insert - Add (in alphabetical order) a directory entry to the * current list of entries. */ static SANE_Int dir_insert (struct cam_dirent *entry) { struct cam_dirlist *cur, *e; cur = (struct cam_dirlist *) malloc (sizeof (struct cam_dirlist)); if (cur == NULL) { DBG (1, "dir_insert: error: could not malloc entry\n"); return -1; } strcpy (cur->name, entry->name); DBG (127, "dir_insert: name is %s\n", cur->name); cur->next = NULL; if (dir_head == NULL) { dir_head = cur; } else if (strcmp (cur->name, dir_head->name) < 0) { cur->next = dir_head; dir_head = cur; return 0; } else { for (e = dir_head; e->next; e = e->next) { if (strcmp (e->next->name, cur->name) > 0) { cur->next = e->next; e->next = cur; return 0; } } e->next = cur; } return 0; } /* * dir_delete - Delete a directory entry from the linked list of file * names */ static SANE_Int dir_delete (SANE_String fname) { struct cam_dirlist *cur, *e; DBG (127, "dir_delete: %s\n", fname); if (strcmp (fname, dir_head->name) == 0) { cur = dir_head; dir_head = dir_head->next; free (cur); return 0; } for (e = dir_head; e->next; e = e->next) { if (strcmp (fname, e->next->name) == 0) { cur = e->next; e->next = e->next->next; free (cur); return (0); } } DBG (1, "dir_delete: Couldn't find entry %s in dir list\n", fname); return -1; } /* * set_res - set picture size depending on resolution settings */ static void set_res (SANE_Int lowres) { if (dc240_opt_thumbnails) { parms.bytes_per_line = 160 * 3; parms.pixels_per_line = 160; parms.lines = 120; } else if (lowres) { parms.bytes_per_line = LOWRES_WIDTH * 3; parms.pixels_per_line = LOWRES_WIDTH; parms.lines = LOWRES_HEIGHT; } else { parms.bytes_per_line = HIGHRES_WIDTH * 3; parms.pixels_per_line = HIGHRES_WIDTH; parms.lines = HIGHRES_HEIGHT; } } sane-backends-1.0.27/backend/pixma_mp810.c0000664000175000017500000022723312775312261015037 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2007-2009 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* test cases 1. short USB packet (must be no -ETIMEDOUT) 2. cancel using button on the printer (look for abort command) 3. start scan while busy (status 0x1414) 4. cancel using ctrl-c (must send abort command) */ #define TPU_48 /* uncomment to activate TPU scan at 48 bits */ /*#define DEBUG_TPU_48*//* uncomment to debug 48 bits TPU on a non TPU device */ /*#define DEBUG_TPU_24*//* uncomment to debug 24 bits TPU on a non TPU device */ /*#define TPUIR_USE_RGB*/ /* uncomment to use RGB channels and convert them to gray; otherwise use R channel only */ #include "../include/sane/config.h" #include #include #include #include /* localtime(C90) */ #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" /* Some macro code to enhance readability */ #define RET_IF_ERR(x) do { \ if ((error = (x)) < 0) \ return error; \ } while(0) #define WAIT_INTERRUPT(x) do { \ error = handle_interrupt (s, x); \ if (s->cancel) \ return PIXMA_ECANCELED; \ if (error != PIXMA_ECANCELED && error < 0) \ return error; \ } while(0) #ifdef __GNUC__ # define UNUSED(v) (void) v #else # define UNUSED(v) #endif /* Size of the command buffer should be multiple of wMaxPacketLength and greater than 4096+24. 4096 = size of gamma table. 24 = header + checksum */ #define IMAGE_BLOCK_SIZE (512*1024) #define CMDBUF_SIZE (4096 + 24) #define DEFAULT_GAMMA 2.0 /***** Gamma different from 1.0 is potentially impacting color profile generation *****/ #define UNKNOWN_PID 0xffff #define CANON_VID 0x04a9 /* Generation 2 */ #define MP810_PID 0x171a #define MP960_PID 0x171b /* Generation 3 */ /* PIXMA 2007 vintage */ #define MP970_PID 0x1726 /* Flatbed scanner CCD (2007) */ #define CS8800F_PID 0x1901 /* PIXMA 2008 vintage */ #define MP980_PID 0x172d /* Generation 4 */ #define MP990_PID 0x1740 /* Flatbed scanner CCD (2010) */ #define CS9000F_PID 0x1908 /* 2010 new device (untested) */ #define MG8100_PID 0x174b /* CCD */ /* 2011 new device (untested) */ #define MG8200_PID 0x1756 /* CCD */ /* 2013 new device */ #define CS9000F_MII_PID 0x190d /* Generation 4 XML messages that encapsulates the Pixma protocol messages */ #define XML_START_1 \ "\ \ StartJob\ 00000001\ 1" #define XML_START_2 \ "\ \ VendorCmd\ 00000001\ ModeShift1\ " #define XML_END \ "\ \ EndJob\ 00000001\ " #define XML_OK "OK" enum mp810_state_t { state_idle, state_warmup, state_scanning, state_transfering, state_finished }; enum mp810_cmd_t { cmd_start_session = 0xdb20, cmd_select_source = 0xdd20, cmd_gamma = 0xee20, cmd_scan_param = 0xde20, cmd_status = 0xf320, cmd_abort_session = 0xef20, cmd_time = 0xeb80, cmd_read_image = 0xd420, cmd_error_info = 0xff20, cmd_start_calibrate_ccd_3 = 0xd520, cmd_end_calibrate_ccd_3 = 0xd720, cmd_scan_param_3 = 0xd820, cmd_scan_start_3 = 0xd920, cmd_status_3 = 0xda20, cmd_get_tpu_info_3 = 0xf520, cmd_set_tpu_info_3 = 0xea20, cmd_e920 = 0xe920 /* seen in MP800 */ }; typedef struct mp810_t { enum mp810_state_t state; pixma_cmdbuf_t cb; uint8_t *imgbuf; uint8_t current_status[16]; unsigned last_block; uint8_t generation; /* for Generation 3 and CCD shift */ uint8_t *linebuf; uint8_t *data_left_ofs; unsigned data_left_len; int shift[3]; unsigned color_shift; unsigned stripe_shift; unsigned stripe_shift2; /* added for MP810, MP960 at 4800dpi & 9000F at 9600dpi */ unsigned jumplines; /* added for MP810, MP960 at 4800dpi & 9000F at 9600dpi */ uint8_t tpu_datalen; uint8_t tpu_data[0x40]; } mp810_t; /* STAT: 0x0606 = ok, 0x1515 = failed (PIXMA_ECANCELED), 0x1414 = busy (PIXMA_EBUSY) Transaction scheme 1. command_header/data | result_header 2. command_header | result_header/data 3. command_header | result_header/image_data - data has checksum in the last byte. - image_data has no checksum. - data and image_data begins in the same USB packet as command_header or result_header. command format #1: u16be cmd u8[6] 0 u8[4] 0 u32be PLEN parameter length u8[PLEN-1] parameter u8 parameter check sum result: u16be STAT u8 0 u8 0 or 0x21 if STAT == 0x1414 u8[4] 0 command format #2: u16be cmd u8[6] 0 u8[4] 0 u32be RLEN result length result: u16be STAT u8[6] 0 u8[RLEN-1] result u8 result check sum command format #3: (only used by read_image_block) u16be 0xd420 u8[6] 0 u8[4] 0 u32be max. block size + 8 result: u16be STAT u8[6] 0 u8 block info bitfield: 0x8 = end of scan, 0x10 = no more paper, 0x20 = no more data u8[3] 0 u32be ILEN image data size u8[ILEN] image data */ static void mp810_finish_scan (pixma_t * s); static int is_scanning_from_adf (pixma_t * s) { return (s->param->source == PIXMA_SOURCE_ADF || s->param->source == PIXMA_SOURCE_ADFDUP); } static int is_scanning_from_adfdup (pixma_t * s) { return (s->param->source == PIXMA_SOURCE_ADFDUP); } static int is_scanning_from_tpu (pixma_t * s) { return (s->param->source == PIXMA_SOURCE_TPU); } static int send_xml_dialog (pixma_t * s, const char * xml_message) { mp810_t *mp = (mp810_t *) s->subdriver; int datalen; datalen = pixma_cmd_transaction (s, xml_message, strlen (xml_message), mp->cb.buf, 1024); if (datalen < 0) return datalen; mp->cb.buf[datalen] = 0; PDBG(pixma_dbg (10, "XML message sent to scanner:\n%s\n", xml_message)); PDBG(pixma_dbg (10, "XML response back from scanner:\n%s\n", mp->cb.buf)); return (strcasestr ((const char *) mp->cb.buf, XML_OK) != NULL); } static void new_cmd_tpu_msg (pixma_t *s, pixma_cmdbuf_t * cb, uint16_t cmd) { pixma_newcmd (cb, cmd, 0, 0); cb->buf[3] = (is_scanning_from_tpu (s)) ? 0x01 : 0x00; } static int start_session (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; new_cmd_tpu_msg (s, &mp->cb, cmd_start_session); return pixma_exec (s, &mp->cb); } static int start_scan_3 (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; new_cmd_tpu_msg (s, &mp->cb, cmd_scan_start_3); return pixma_exec (s, &mp->cb); } static int send_cmd_start_calibrate_ccd_3 (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; pixma_newcmd (&mp->cb, cmd_start_calibrate_ccd_3, 0, 0); mp->cb.buf[3] = 0x01; return pixma_exec (s, &mp->cb); } static int is_calibrated (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; if (mp->generation >= 3) { return ((mp->current_status[0] & 0x01) == 1); } if (mp->generation == 1) { return (mp->current_status[8] == 1); } else { return (mp->current_status[9] == 1); } } static int has_paper (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; if (is_scanning_from_adfdup (s)) return (mp->current_status[1] == 0 || mp->current_status[2] == 0); else return (mp->current_status[1] == 0); } static void drain_bulk_in (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; while (pixma_read (s->io, mp->imgbuf, IMAGE_BLOCK_SIZE) >= 0) ; } static int abort_session (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_abort_session); } static int send_cmd_e920 (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; return pixma_exec_short_cmd (s, &mp->cb, cmd_e920); } static int select_source (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; uint8_t *data; data = pixma_newcmd (&mp->cb, cmd_select_source, 12, 0); data[5] = ((mp->generation == 2) ? 1 : 0); switch (s->param->source) { case PIXMA_SOURCE_FLATBED: data[0] = 1; data[1] = 1; break; case PIXMA_SOURCE_ADF: data[0] = 2; data[5] = 1; data[6] = 1; break; case PIXMA_SOURCE_ADFDUP: data[0] = 2; data[5] = 3; data[6] = 3; break; case PIXMA_SOURCE_TPU: data[0] = 4; data[1] = 2; break; } return pixma_exec (s, &mp->cb); } static int send_get_tpu_info_3 (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_get_tpu_info_3, 0, 0x34); RET_IF_ERR(pixma_exec (s, &mp->cb)); memcpy (mp->tpu_data, data, 0x34); return error; } static int send_set_tpu_info (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; uint8_t *data; if (mp->tpu_datalen == 0) return 0; data = pixma_newcmd (&mp->cb, cmd_set_tpu_info_3, 0x34, 0); memcpy (data, mp->tpu_data, 0x34); return pixma_exec (s, &mp->cb); } static int send_gamma_table (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; const uint8_t *lut = s->param->gamma_table; uint8_t *data; if (mp->generation == 1) { data = pixma_newcmd (&mp->cb, cmd_gamma, 4096 + 8, 0); data[0] = (s->param->channels == 3) ? 0x10 : 0x01; pixma_set_be16 (0x1004, data + 2); if (lut) memcpy (data + 4, lut, 4096); else pixma_fill_gamma_table (DEFAULT_GAMMA, data + 4, 4096); } else { /* FIXME: Gamma table for 2nd generation: 1024 * uint16_le */ data = pixma_newcmd (&mp->cb, cmd_gamma, 2048 + 8, 0); data[0] = 0x10; pixma_set_be16 (0x0804, data + 2); if (lut) { int i; for (i = 0; i < 1024; i++) { int j = (i << 2) + (i >> 8); data[4 + 2 * i + 0] = lut[j]; data[4 + 2 * i + 1] = lut[j]; } } else { int i; pixma_fill_gamma_table (DEFAULT_GAMMA, data + 4, 2048); for (i = 0; i < 1024; i++) { int j = (i << 1) + (i >> 9); data[4 + 2 * i + 0] = data[4 + j]; data[4 + 2 * i + 1] = data[4 + j]; } } } return pixma_exec (s, &mp->cb); } static unsigned calc_raw_width (const mp810_t * mp, const pixma_scan_param_t * param) { unsigned raw_width; /* NOTE: Actually, we can send arbitary width to MP810. Lines returned are always padded to multiple of 4 or 12 pixels. Is this valid for other models, too? */ if (mp->generation >= 2) { raw_width = ALIGN_SUP (param->w + param->xs, 32); /* PDBG (pixma_dbg (4, "*calc_raw_width***** width %u extended by %u and rounded to %u *****\n", param->w, param->xs, raw_width)); */ } else if (param->channels == 1) { raw_width = ALIGN_SUP (param->w + param->xs, 12); } else { raw_width = ALIGN_SUP (param->w + param->xs, 4); } return raw_width; } static int has_ccd_sensor (pixma_t * s) { return ((s->cfg->cap & PIXMA_CAP_CCD) != 0); } #if 0 static int is_color (pixma_t * s) { return (s->param->mode == PIXMA_SCAN_MODE_COLOR); } static int is_color_48 (pixma_t * s) { return (s->param->mode == PIXMA_SCAN_MODE_COLOR_48); } static int is_color_negative (pixma_t * s) { return (s->param->mode == PIXMA_SCAN_MODE_NEGATIVE_COLOR); } static int is_color_all (pixma_t * s) { return (is_color (s) || is_color_48 (s) || is_color_negative (s)); } #endif static int is_gray (pixma_t * s) { return (s->param->mode == PIXMA_SCAN_MODE_GRAY); } static int is_gray_16 (pixma_t * s) { return (s->param->mode == PIXMA_SCAN_MODE_GRAY_16); } static int is_gray_negative (pixma_t * s) { return (s->param->mode == PIXMA_SCAN_MODE_NEGATIVE_GRAY); } static int is_gray_all (pixma_t * s) { return (is_gray (s) || is_gray_16 (s) || is_gray_negative (s)); } static int is_lineart (pixma_t * s) { return (s->param->mode == PIXMA_SCAN_MODE_LINEART); } static int is_tpuir (pixma_t * s) { return (s->param->mode == PIXMA_SCAN_MODE_TPUIR); } /* CCD sensors don't have neither a Grayscale mode nor a Lineart mode, * but use color mode instead */ static unsigned get_cis_ccd_line_size (pixma_t * s) { return (( s->param->wx ? s->param->line_size / s->param->w * s->param->wx : s->param->line_size) * ((is_tpuir (s) || is_gray_all (s) || is_lineart (s)) ? 3 : 1)); } static unsigned calc_shifting (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; /* If stripes shift needed (CCD devices), how many pixels shift */ mp->stripe_shift = 0; mp->stripe_shift2 = 0; mp->jumplines = 0; switch (s->cfg->pid) { case MP970_PID: /* MP970 at 4800 dpi */ case CS8800F_PID: /* CanoScan 8800F at 4800 dpi */ if (s->param->xdpi == 4800) { if (is_scanning_from_tpu (s)) mp->stripe_shift = 6; else mp->stripe_shift = 3; } break; case CS9000F_PID: /* CanoScan 9000F at 4800 dpi */ case CS9000F_MII_PID: if (s->param->xdpi == 4800) { if (is_scanning_from_tpu (s)) mp->stripe_shift = 6; /* should work for CS9000F same as manual */ else mp->stripe_shift = 3; } if (s->param->xdpi == 9600) { if (is_scanning_from_tpu (s)) { /* need to double up for TPU */ mp->stripe_shift = 6; /* for 1st set of 4 images */ /* unfortunately there are 2 stripe shifts */ mp->stripe_shift2 = 6; /* for 2nd set of 4 images */ mp->jumplines = 32; /* try 33 or 34 */ } /* there is no 9600dpi support in flatbed mode */ } break; case MP960_PID: if (s->param->xdpi == 2400) { if (is_scanning_from_tpu (s)) mp->stripe_shift = 6; else mp->stripe_shift = 3; } if (s->param->xdpi == 4800) { if (is_scanning_from_tpu (s)) { mp->stripe_shift = 6; mp->stripe_shift2 = 6; } else { mp->stripe_shift = 3; mp->stripe_shift2 = 3; } mp->jumplines = 33; /* better than 32 or 34 : applies to flatbed & TPU */ } break; case MP810_PID: if (s->param->xdpi == 2400) { if (is_scanning_from_tpu (s)) mp->stripe_shift = 6; else mp->stripe_shift = 3; } if (s->param->xdpi == 4800) { if (is_scanning_from_tpu (s)) { mp->stripe_shift = 6; mp->stripe_shift2 = 6; } else { mp->stripe_shift = 3; mp->stripe_shift2 = 3; } mp->jumplines = 33; /* better than 32 or 34 : applies to flatbed & TPU */ } break; case MP990_PID: if (s->param->xdpi == 4800) { if (is_scanning_from_tpu (s)) { mp->stripe_shift = 6; mp->stripe_shift2 = 6; } else { mp->stripe_shift = 3; mp->stripe_shift2 = 3; } mp->jumplines = 34; /* better than 32 or 34 : applies to flatbed & TPU */ } break; default: /* Default, and all CIS devices */ break; } /* If color plane shift (CCD devices), how many pixels shift */ mp->color_shift = mp->shift[0] = mp->shift[1] = mp->shift[2] = 0; if (s->param->ydpi > 75) { switch (s->cfg->pid) { case MP970_PID: case CS8800F_PID: /* CanoScan 8800F */ mp->color_shift = s->param->ydpi / 50; mp->shift[1] = mp->color_shift * get_cis_ccd_line_size (s); mp->shift[0] = 0; mp->shift[2] = 2 * mp->shift[1]; break; case CS9000F_PID: /* CanoScan 9000F */ case CS9000F_MII_PID: mp->color_shift = s->param->ydpi / 30; mp->shift[1] = mp->color_shift * get_cis_ccd_line_size (s); mp->shift[0] = 0; mp->shift[2] = 2 * mp->shift[1]; break; case MP980_PID: case MP990_PID: case MG8200_PID: if (s->param->ydpi > 150) { mp->color_shift = s->param->ydpi / 75; mp->shift[1] = mp->color_shift * get_cis_ccd_line_size (s); mp->shift[0] = 0; mp->shift[2] = 2 * mp->shift[1]; } break; case MP810_PID: case MP960_PID: mp->color_shift = s->param->ydpi / 50; if (is_scanning_from_tpu (s)) mp->color_shift = s->param->ydpi / 50; mp->shift[1] = mp->color_shift * get_cis_ccd_line_size (s); mp->shift[0] = 2 * mp->shift[1]; mp->shift[2] = 0; break; default: break; } } /* special settings for 16 bit flatbed mode @ 75 dpi * minimum of 150 dpi is used yet */ /* else if (!is_scanning_from_tpu (s)) { switch (s->cfg->pid) { case CS9000F_PID: case CS9000F_MII_PID: if (is_color_48 (s) || is_gray_16 (s)) { mp->color_shift = 5; mp->shift[1] = 0; mp->shift[0] = 0; mp->shift[2] = 0; } break; } } */ /* PDBG (pixma_dbg (4, "*calc_shifing***** color_shift = %u, stripe_shift = %u, jumplines = %u *****\n", mp->color_shift, mp->stripe_shift, mp->jumplines)); */ return (2 * mp->color_shift + mp->stripe_shift + mp->jumplines); /* note impact of stripe shift2 later if needed! */ } static int send_scan_param (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; uint8_t *data; unsigned raw_width = calc_raw_width (mp, s->param); unsigned h, h1, h2, shifting; /* TPU scan does not support lineart */ if (is_scanning_from_tpu (s) && is_lineart (s)) { return PIXMA_ENOTSUP; } shifting = calc_shifting (s); h1 = s->param->h + shifting; /* add lines for color shifting */ /* PDBG (pixma_dbg (4, "* send_scan_param: height calc (choose lesser) 1 %u \n", h1 )); */ if (mp->generation >= 4) /* use most global condition */ { /* tested for MP960, 9000F */ /* add lines for color shifting */ /* otherwise you cannot scan all lines defined for flatbed mode */ /* this shouldn't affect TPU mode */ h2 = s->cfg->height * s->param->ydpi / 75 + shifting; /* PDBG (pixma_dbg (4, "* send_scan_param: height calc (choose lesser) 2 %u = %u max. lines for scanner + %u lines for color shifting \n", h2, s->cfg->height * s->param->ydpi / 75, shifting )); */ } else { /* TODO: Check for other scanners. */ h2 = s->cfg->height * s->param->ydpi / 75; /* this might be causing problems for generation 1 devices */ /* PDBG (pixma_dbg (4, "* send_scan_param: height calc (choose lesser) 2 %u \n", h2 )); */ } h = MIN (h1, h2); if (mp->generation <= 2) { data = pixma_newcmd (&mp->cb, cmd_scan_param, 0x30, 0); pixma_set_be16 (s->param->xdpi | 0x8000, data + 0x04); pixma_set_be16 (s->param->ydpi | 0x8000, data + 0x06); pixma_set_be32 (s->param->x, data + 0x08); if (mp->generation == 2) pixma_set_be32 (s->param->x - s->param->xs, data + 0x08); pixma_set_be32 (s->param->y, data + 0x0c); pixma_set_be32 (raw_width, data + 0x10); pixma_set_be32 (h, data + 0x14); data[0x18] = ((s->param->channels != 1) || is_gray_all (s) || is_lineart (s)) ? 0x08 : 0x04; data[0x19] = ((s->param->software_lineart) ? 8 : s->param->depth) * ((is_gray_all (s) || is_lineart (s)) ? 3 : s->param->channels); /* bits per pixel */ data[0x1a] = (is_scanning_from_tpu (s) ? 1 : 0); data[0x20] = 0xff; data[0x23] = 0x81; data[0x26] = 0x02; data[0x27] = 0x01; } else { /* scan parameters: * ================ * * byte | # of | mode | value / description * | bytes | | * -----+-------+---------+--------------------------- * 0x00 | 1 | default | 0x01 * | | adf | 0x02 * | | tpu | 0x04 * | | tpuir | cs9000f: 0x03 * -----+-------+---------+--------------------------- * 0x01 | 1 | default | 0x00 * | | tpu | 0x02 * -----+-------+---------+--------------------------- * 0x02 | 1 | default | 0x01 * | | adfdup | 0x03 * -----+-------+---------+--------------------------- * 0x03 | 1 | default | 0x00 * | | adfdup | 0x03 * -----+-------+---------+--------------------------- * 0x04 | 1 | all | 0x00 * -----+-------+---------+--------------------------- * 0x05 | 1 | all | 0x01: This one also seen at 0. Don't know yet what's used for. * -----+-------+---------+--------------------------- * ... | 1 | all | 0x00 * -----+-------+---------+--------------------------- * 0x08 | 2 | all | xdpi | 0x8000 * -----+-------+---------+--------------------------- * 0x0a | 2 | all | ydpi | 0x8000: Must be the same as xdpi. * -----+-------+---------+--------------------------- * 0x0c | 4 | all | x position of start pixel * -----+-------+---------+--------------------------- * 0x10 | 4 | all | y position of start pixel * -----+-------+---------+--------------------------- * 0x14 | 4 | all | # of pixels in 1 line * -----+-------+---------+--------------------------- * 0x18 | 4 | all | # of scan lines * -----+-------+---------+--------------------------- * 0x1c | 1 | all | 0x08 * | | | 0x04 = relict from cis scanners? * -----+-------+---------+--------------------------- * 0x1d | 1 | all | # of bits per pixel * -----+-------+---------+--------------------------- * 0x1e | 1 | default | 0x00: paper * | | tpu | 0x01: positives * | | tpu | 0x02: negatives * | | tpuir | 0x01: positives * -----+-------+---------+--------------------------- * 0x1f | 1 | all | 0x01 * | | | cs9000f: 0x00: Not sure if that is because of positives. * -----+-------+---------+--------------------------- * 0x20 | 1 | all | 0xff * -----+-------+---------+--------------------------- * 0x21 | 1 | all | 0x81 * -----+-------+---------+--------------------------- * 0x22 | 1 | all | 0x00 * -----+-------+---------+--------------------------- * 0x23 | 1 | all | 0x02 * -----+-------+---------+--------------------------- * 0x24 | 1 | all | 0x01 * -----+-------+---------+--------------------------- * 0x25 | 1 | default | 0x00; cs8800f: 0x01 * | | tpu | 0x00; cs9000f, mg8200, mp990: 0x01 * | | tpuir | cs9000f: 0x00 * -----+-------+---------+--------------------------- * ... | 1 | all | 0x00 * -----+-------+---------+--------------------------- * 0x30 | 1 | all | 0x01 * */ data = pixma_newcmd (&mp->cb, cmd_scan_param_3, 0x38, 0); data[0x00] = is_scanning_from_adf (s) ? 0x02 : 0x01; data[0x01] = 0x01; if (is_scanning_from_tpu (s)) { data[0x00] = is_tpuir (s) ? 0x03 : 0x04; data[0x01] = 0x02; data[0x1e] = 0x02; /* NB: CanoScan 8800F: 0x02->negatives, 0x01->positives, paper->0x00 */ } data[0x02] = 0x01; if (is_scanning_from_adfdup (s)) { data[0x02] = 0x03; data[0x03] = 0x03; } if (s->cfg->pid != MG8200_PID) data[0x05] = 0x01; /* This one also seen at 0. Don't know yet what's used for */ /* the scanner controls the scan */ /* no software control needed */ pixma_set_be16 (s->param->xdpi | 0x8000, data + 0x08); pixma_set_be16 (s->param->ydpi | 0x8000, data + 0x0a); /*PDBG (pixma_dbg (4, "*send_scan_param***** Setting: xdpi=%hi ydpi=%hi x=%u y=%u w=%u h=%u ***** \n", s->param->xdpi,s->param->ydpi,(s->param->x)-(s->param->xs),s->param->y,raw_width,h));*/ pixma_set_be32 (s->param->x - s->param->xs, data + 0x0c); pixma_set_be32 (s->param->y, data + 0x10); pixma_set_be32 (raw_width, data + 0x14); pixma_set_be32 (h, data + 0x18); data[0x1c] = ((s->param->channels != 1) || is_tpuir (s) || is_gray_all (s) || is_lineart (s)) ? 0x08 : 0x04; #ifdef DEBUG_TPU_48 data[0x1d] = 24; #else data[0x1d] = (is_scanning_from_tpu (s)) ? 48 : (((s->param->software_lineart) ? 8 : s->param->depth) * ((is_tpuir (s) || is_gray_all (s) || is_lineart (s)) ? 3 : s->param->channels)); /* bits per pixel */ #endif data[0x1f] = 0x01; /* for 9000F this appears to be 0x00, not sure if that is because of positives */ if (s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID || s->cfg->pid == MG8200_PID) { data[0x1f] = 0x00; } data[0x20] = 0xff; data[0x21] = 0x81; data[0x23] = 0x02; data[0x24] = 0x01; /* MG8200 & MP990 addition */ if (s->cfg->pid == MG8200_PID || s->cfg->pid == MP990_PID) { if (is_scanning_from_tpu (s)) { data[0x25] = 0x01; } } /* CS8800F & CS9000F addition */ if (s->cfg->pid == CS8800F_PID || s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) { if (is_scanning_from_tpu (s)) { /* TPU */ /* 0x02->negatives, 0x01->positives, paper->0x00 * no paper in TPU mode */ if (s->param->mode == PIXMA_SCAN_MODE_NEGATIVE_COLOR || s->param->mode == PIXMA_SCAN_MODE_NEGATIVE_GRAY) { PDBG( pixma_dbg (4, "*send_scan_param***** TPU scan negatives *****\n")); data[0x1e] = 0x02; } else { PDBG( pixma_dbg (4, "*send_scan_param***** TPU scan positives *****\n")); data[0x1e] = 0x01; } /* CS8800F: 0x00 for TPU color management */ if (s->cfg->pid == CS8800F_PID) data[0x25] = 0x00; /* CS9000F: 0x01 for TPU */ if (s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) data[0x25] = 0x01; if (s->param->mode == PIXMA_SCAN_MODE_TPUIR) data[0x25] = 0x00; } else { /* flatbed and ADF */ /* paper->0x00 */ data[0x1e] = 0x00; /* CS8800F: 0x01 normally */ if (s->cfg->pid == CS8800F_PID) data[0x25] = 0x01; /* CS9000F: 0x00 normally */ if (s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) data[0x25] = 0x00; } } data[0x30] = 0x01; } return pixma_exec (s, &mp->cb); } static int query_status_3 (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; uint8_t *data; int error, status_len; status_len = 8; data = pixma_newcmd (&mp->cb, cmd_status_3, 0, status_len); RET_IF_ERR(pixma_exec (s, &mp->cb)); memcpy (mp->current_status, data, status_len); return error; } static int query_status (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; uint8_t *data; int error, status_len; status_len = (mp->generation == 1) ? 12 : 16; data = pixma_newcmd (&mp->cb, cmd_status, 0, status_len); RET_IF_ERR(pixma_exec (s, &mp->cb)); memcpy (mp->current_status, data, status_len); PDBG( pixma_dbg (3, "Current status: paper=%u cal=%u lamp=%u busy=%u\n", data[1], data[8], data[7], data[9])); return error; } #if 0 static int send_time (pixma_t * s) { /* Why does a scanner need a time? */ time_t now; struct tm *t; uint8_t *data; mp810_t *mp = (mp810_t *) s->subdriver; data = pixma_newcmd (&mp->cb, cmd_time, 20, 0); pixma_get_time (&now, NULL); t = localtime (&now); snprintf ((char *) data, 16, "%02d/%02d/%02d %02d:%02d", t->tm_year % 100, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min); PDBG(pixma_dbg (3, "Sending time: '%s'\n", (char *) data)); return pixma_exec (s, &mp->cb); } #endif /* TODO: Simplify this function. Read the whole data packet in one shot. */ static int read_image_block (pixma_t * s, uint8_t * header, uint8_t * data) { uint8_t cmd[16]; mp810_t *mp = (mp810_t *) s->subdriver; const int hlen = 8 + 8; int error, datalen; memset (cmd, 0, sizeof(cmd)); /* PDBG (pixma_dbg (4, "* read_image_block: last_block\n", mp->last_block)); */ pixma_set_be16 (cmd_read_image, cmd); if ((mp->last_block & 0x20) == 0) pixma_set_be32 ((IMAGE_BLOCK_SIZE / 65536) * 65536 + 8, cmd + 0xc); else pixma_set_be32 (32 + 8, cmd + 0xc); mp->state = state_transfering; mp->cb.reslen = pixma_cmd_transaction (s, cmd, sizeof(cmd), mp->cb.buf, 512); /* read 1st 512 bytes of image block */ datalen = mp->cb.reslen; if (datalen < 0) return datalen; memcpy (header, mp->cb.buf, hlen); /* PDBG (pixma_dbg (4, "* read_image_block: datalen %i\n", datalen)); */ /* PDBG (pixma_dbg (4, "* read_image_block: hlen %i\n", hlen)); */ if (datalen >= hlen) { datalen -= hlen; memcpy (data, mp->cb.buf + hlen, datalen); data += datalen; if (mp->cb.reslen == 512) { /* read the rest of the image block */ error = pixma_read (s->io, data, IMAGE_BLOCK_SIZE - 512 + hlen); RET_IF_ERR(error); datalen += error; } } mp->state = state_scanning; mp->cb.expected_reslen = 0; RET_IF_ERR(pixma_check_result (&mp->cb)); if (mp->cb.reslen < hlen) return PIXMA_EPROTO; return datalen; } static int read_error_info (pixma_t * s, void *buf, unsigned size) { unsigned len = 16; mp810_t *mp = (mp810_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mp->cb, cmd_error_info, 0, len); RET_IF_ERR(pixma_exec (s, &mp->cb)); if (buf && len < size) { size = len; /* NOTE: I've absolutely no idea what the returned data mean. */ memcpy (buf, data, size); error = len; } return error; } /* handle_interrupt() waits until it receives an interrupt packet or times out. It calls send_time() and query_status() if necessary. Therefore, make sure that handle_interrupt() is only called from a safe context for send_time() and query_status(). Returns: 0 timed out 1 an interrupt packet received PIXMA_ECANCELED interrupted by signal <0 error */ static int handle_interrupt (pixma_t * s, int timeout) { uint8_t buf[64]; /* check max. packet size with 'lsusb -v' for "EP 9 IN" */ int len; len = pixma_wait_interrupt (s->io, buf, sizeof(buf), timeout); if (len == PIXMA_ETIMEDOUT) return 0; if (len < 0) return len; if (len%16) /* len must be a multiple of 16 bytes */ { PDBG(pixma_dbg (1, "WARNING:unexpected interrupt packet length %d\n", len)); return PIXMA_EPROTO; } /* s->event = 0x0brroott * b: button * oo: original * tt: target * rr: scan resolution * poll event with 'scanimage -A' */ if (s->cfg->pid == MG8200_PID) /* button no. in buf[7] * size in buf[10] 01=A4; 02=Letter; 08=10x15; 09=13x18; 0b=auto * format in buf[11] 01=JPEG; 02=TIFF; 03=PDF; 04=Kompakt-PDF * dpi in buf[12] 01=75; 02=150; 03=300; 04=600 * target = format; original = size; scan-resolution = dpi */ { if (buf[7] & 1) s->events = PIXMA_EV_BUTTON1 | buf[11] | buf[10]<<8 | buf[12]<<16; /* color scan */ if (buf[7] & 2) s->events = PIXMA_EV_BUTTON2 | buf[11] | buf[10]<<8 | buf[12]<<16; /* b/w scan */ } else if (s->cfg->pid == CS8800F_PID || s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) /* button no. in buf[1] * target = button no. * "Finish PDF" is Button-2, all others are Button-1 */ { if ((s->cfg->pid == CS8800F_PID && buf[1] == 0x70) || (s->cfg->pid != CS8800F_PID && buf[1] == 0x50)) s->events = PIXMA_EV_BUTTON2 | buf[1] >> 4; /* button 2 = cancel / end scan */ else s->events = PIXMA_EV_BUTTON1 | buf[1] >> 4; /* button 1 = start scan */ } else /* button no. in buf[0] * original in buf[0] * target in buf[1] */ { /* More than one event can be reported at the same time. */ if (buf[3] & 1) /* FIXME: This function makes trouble with a lot of scanners send_time (s); */ PDBG (pixma_dbg (1, "WARNING:send_time() disabled!\n")); if (buf[9] & 2) query_status (s); if (buf[0] & 2) s->events = PIXMA_EV_BUTTON2 | buf[1] | ((buf[0] & 0xf0) << 4); /* b/w scan */ if (buf[0] & 1) s->events = PIXMA_EV_BUTTON1 | buf[1] | ((buf[0] & 0xf0) << 4); /* color scan */ } return 1; } static int init_ccd_lamp_3 (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; uint8_t *data; int error, status_len, tmo; status_len = 8; RET_IF_ERR(query_status (s)); RET_IF_ERR(query_status (s)); RET_IF_ERR(send_cmd_start_calibrate_ccd_3 (s)); RET_IF_ERR(query_status (s)); tmo = 20; /* like Windows driver, CCD lamp adjustment */ while (--tmo >= 0) { data = pixma_newcmd (&mp->cb, cmd_end_calibrate_ccd_3, 0, status_len); RET_IF_ERR(pixma_exec (s, &mp->cb)); memcpy (mp->current_status, data, status_len); PDBG(pixma_dbg (3, "Lamp status: %u , timeout in: %u\n", data[0], tmo)); if (mp->current_status[0] == 3 || !is_scanning_from_tpu (s)) break; WAIT_INTERRUPT(1000); } return error; } static int wait_until_ready (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; int error, tmo = 60; RET_IF_ERR((mp->generation >= 3) ? query_status_3 (s) : query_status (s)); while (!is_calibrated (s)) { WAIT_INTERRUPT(1000); if (mp->generation >= 3) RET_IF_ERR(query_status_3 (s)); if (--tmo == 0) { PDBG(pixma_dbg (1, "WARNING: Timed out in wait_until_ready()\n")); PDBG(query_status (s)); return PIXMA_ETIMEDOUT; } } return 0; } /* the RGB images are shifted by # of lines */ /* the R image is shifted by colshift[0] */ /* the G image is shifted by colshift[1] */ /* the B image is shifted by colshift[2] */ /* usually one of the RGB images must not be shifted */ /* which one depends on the scanner */ /* some scanners have an additional stripe shift */ /* e.g. colshift[0]=0, colshift[1]=1, colshift[2]=2 */ /* R image is OK: RGBRGBRGB... */ /* ^^ ^^ ^^ */ /* || || || */ /* shift G image: RG|RG|RG|... */ /* | | | */ /* shift B image: RGBRGBRGB... */ /* this doesn't affect the G and B images */ /* G image will become the R image in the next run */ /* B image will become the G image in the next run */ /* the next line will become the B image in the next run */ static uint8_t * shift_colors (uint8_t * dptr, uint8_t * sptr, unsigned w, unsigned dpi, unsigned pid, unsigned c, int * colshft, unsigned strshft) { unsigned i, sr, sg, sb, st; UNUSED(dpi); UNUSED(pid); sr = colshft[0]; sg = colshft[1]; sb = colshft[2]; /* PDBG (pixma_dbg (4, "*shift_colors***** c=%u, w=%i, sr=%u, sg=%u, sb=%u, strshft=%u ***** \n", c, w, sr, sg, sb, strshft)); */ for (i = 0; i < w; i++) { /* stripes shift for MP970 at 4800 dpi, MP810 at 2400 dpi */ st = (i % 2 == 0) ? strshft : 0; *sptr++ = *(dptr++ + sr + st); if (c == 6) *sptr++ = *(dptr++ + sr + st); *sptr++ = *(dptr++ + sg + st); if (c == 6) *sptr++ = *(dptr++ + sg + st); *sptr++ = *(dptr++ + sb + st); if (c == 6) *sptr++ = *(dptr++ + sb + st); } return dptr; } static uint8_t * shift_colorsCS9000 (uint8_t * dptr, uint8_t * sptr, unsigned w, unsigned dpi, unsigned pid, unsigned c, int * colshft, unsigned strshft, unsigned strshft2, unsigned jump) { unsigned i, sr, sg, sb, st, st2; UNUSED(dpi); UNUSED(pid); sr = colshft[0]; sg = colshft[1]; sb = colshft[2]; for (i = 0; i < w; i++) { if (i < (w / 2)) { /* stripes shift for 1st 4 images for Canoscan 9000F at 9600dpi */ st = (i % 2 == 0) ? strshft : 0; *sptr++ = *(dptr++ + sr + st); if (c == 6) *sptr++ = *(dptr++ + sr + st); *sptr++ = *(dptr++ + sg + st); if (c == 6) *sptr++ = *(dptr++ + sg + st); *sptr++ = *(dptr++ + sb + st); if (c == 6) *sptr++ = *(dptr++ + sb + st); } if (i >= (w / 2)) { /* stripes shift for 2nd 4 images for Canoscan 9000F at 9600dpi */ st2 = (i % 2 == 0) ? strshft2 : 0; *sptr++ = *(dptr++ + sr + jump + st2); if (c == 6) *sptr++ = *(dptr++ + sr + jump + st2); *sptr++ = *(dptr++ + sg + jump + st2); if (c == 6) *sptr++ = *(dptr++ + sg + jump + st2); *sptr++ = *(dptr++ + sb + jump + st2); if (c == 6) *sptr++ = *(dptr++ + sb + jump + st2); } } return dptr; } static uint8_t * shift_colorsCS9000_4800 (uint8_t * dptr, uint8_t * sptr, unsigned w, unsigned dpi, unsigned pid, unsigned c, int * colshft, unsigned strshft, unsigned strshft2, unsigned jump) { unsigned i, sr, sg, sb, st2; UNUSED(dpi); UNUSED(pid); UNUSED(strshft); sr = colshft[0]; sg = colshft[1]; sb = colshft[2]; for (i = 0; i < w; i++) { /* stripes shift for 2nd 4 images * for Canoscan 9000F with 16 bit flatbed scans at 4800dpi */ st2 = (i % 2 == 0) ? strshft2 : 0; *sptr++ = *(dptr++ + sr + jump + st2); if (c == 6) *sptr++ = *(dptr++ + sr + jump + st2); *sptr++ = *(dptr++ + sg + jump + st2); if (c == 6) *sptr++ = *(dptr++ + sg + jump + st2); *sptr++ = *(dptr++ + sb + jump + st2); if (c == 6) *sptr++ = *(dptr++ + sb + jump + st2); } return dptr; } /* under some conditions some scanners have sub images in one line */ /* e.g. doubled image, line size = 8 */ /* line before reordering: px1 px3 px5 px7 px2 px4 px6 px8 */ /* line after reordering: px1 px2 px3 px4 px5 px6 px7 px8 */ static void reorder_pixels (uint8_t * linebuf, uint8_t * sptr, unsigned c, unsigned n, unsigned m, unsigned w, unsigned line_size) { unsigned i; for (i = 0; i < w; i++) { /* process complete line */ memcpy (linebuf + c * (n * (i % m) + i / m), sptr + c * i, c); } memcpy (sptr, linebuf, line_size); } /* special reorder matrix for mp960 */ static void mp960_reorder_pixels (uint8_t * linebuf, uint8_t * sptr, unsigned c, unsigned n, unsigned m, unsigned w, unsigned line_size) { unsigned i, i2; /* try and copy 2 px at once */ for (i = 0; i < w; i++) { /* process complete line */ i2 = i % 2; if (i < w / 2) { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m)), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m)), sptr + c * i, c); } else { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m) + 1), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m) + 1), sptr + c * i, c); } } memcpy (sptr, linebuf, line_size); } /* special reorder matrix for mp970 */ static void mp970_reorder_pixels (uint8_t * linebuf, uint8_t * sptr, unsigned c, unsigned w, unsigned line_size) { unsigned i, i8; for (i = 0; i < w; i++) { /* process complete line */ i8 = i % 8; memcpy (linebuf + c * (i + i8 - ((i8 > 3) ? 7 : 0)), sptr + c * i, c); } memcpy (sptr, linebuf, line_size); } /* special reorder matrix for CS9000F */ static void cs9000f_initial_reorder_pixels (uint8_t * linebuf, uint8_t * sptr, unsigned c, unsigned n, unsigned m, unsigned w, unsigned line_size) { unsigned i, i2; /* try and copy 2 px at once */ for (i = 0; i < w; i++) { /* process complete line */ i2 = i % 2; if (i < w / 8) { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m)), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m)), sptr + c * i, c); } else if (i >= w / 8 && i < w / 4) { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m) + 1), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m) + 1), sptr + c * i, c); } else if (i >= w / 4 && i < 3 * w / 8) { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m) + 2), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m) + 2), sptr + c * i, c); } else if (i >= 3 * w / 8 && i < w / 2) { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m) + 3), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m) + 3), sptr + c * i, c); } else if (i >= w / 2 && i < 5 * w / 8) { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m) + 4), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m) + 4), sptr + c * i, c); } else if (i >= 5 * w / 8 && i < 3 * w / 4) { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m) + 5), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m) + 5), sptr + c * i, c); } else if (i >= 3 * w / 4 && i < 7 * w / 8) { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m) + 6), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m) + 6), sptr + c * i, c); } else { if (i2 == 0) memcpy (linebuf + c * (n * ((i) % m) + ((i) / m) + 7), sptr + c * i, c); else memcpy (linebuf + c * (n * ((i - 1) % m) + 1 + ((i) / m) + 7), sptr + c * i, c); } } memcpy (sptr, linebuf, line_size); } /* CS9000F 9600dpi reorder: actually 4800dpi since each pixel is doubled */ /* need to rearrange each sequence of 16 pairs of pixels as follows: */ /* start px : 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 */ /* before : p1a p1b p1c p1d p2a p2b p2c p2d p3a p3b p3c p3d p4a p4b p4c p4d */ /* after : p1a p3a p1b p3b p1c p3c p1d p3d p2a p4a p2b p4b p2c p4c p2d p4d */ /* start px : 0 16 2 18 4 20 6 22 8 24 10 26 12 28 14 30 */ /* change : * * * * * * * * * * * * * * */ /* no change: * * */ /* so the 1st and the 3rd set are interleaved, followed by the 2nd and 4th sets interleaved */ static void cs9000f_second_reorder_pixels (uint8_t * linebuf, uint8_t * sptr, unsigned c, unsigned w, unsigned line_size) { unsigned i, i8; static const int shifts[8] = { 2, 4, 6, 8, -8, -6, -4, -2 }; for (i = 0; i < w; i += 2) { /* process complete line */ i8 = (i >> 1) & 0x7; /* Copy 2 pixels at once */ memcpy (linebuf + c * (i + shifts[i8]), sptr + c * i, c * 2); } memcpy (sptr, linebuf, line_size); } #ifndef TPU_48 static unsigned pack_48_24_bpc (uint8_t * sptr, unsigned n) { unsigned i; uint8_t *cptr, lsb; static uint8_t offset = 0; cptr = sptr; if (n % 2 != 0) PDBG (pixma_dbg (3, "WARNING: misaligned image.\n")); for (i = 0; i < n; i += 2) { /* offset = 1 + (offset % 3); */ lsb = *sptr++; *cptr++ = ((*sptr++) << offset) | lsb >> (8 - offset); } return (n / 2); } #endif /* This function deals both with PIXMA CCD sensors producing shifted color * planes images, Grayscale CCD scan and Generation >= 3 high dpi images. * Each complete line in mp->imgbuf is processed for shifting CCD sensor * color planes, reordering pixels above 600 dpi for Generation >= 3, and * converting to Grayscale for CCD sensors. */ static unsigned post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib) { mp810_t *mp = (mp810_t *) s->subdriver; unsigned c, lines, line_size, n, m, cw, cx, reducelines; uint8_t *sptr, *dptr, *gptr, *cptr; unsigned /*color_shift, stripe_shift, stripe_shift2,*/ jumplines /*, height*/; int test; /* For testers: */ /* set this to 1 in order to get unprocessed images next to one another at 9600dpi */ /* other resolutions should not be affected */ /* set this to 2 if you want to see the same with jumplines=0 */ test = 0; jumplines = 0; c = ((is_tpuir (s) || is_gray_all (s) || is_lineart (s)) ? 3 : s->param->channels) * ((s->param->software_lineart) ? 8 : s->param->depth) / 8; cw = c * s->param->w; cx = c * s->param->xs; /* PDBG (pixma_dbg (4, "*post_process_image_data***** c = %u, cw = %u, cx = %u *****\n", c, cw, cx)); */ if (mp->generation >= 3) n = s->param->xdpi / 600; else /* FIXME: maybe need different values for CIS and CCD sensors */ n = s->param->xdpi / 2400; /* Some exceptions to global rules here */ if (s->cfg->pid == MP970_PID || s->cfg->pid == MP990_PID || s->cfg->pid == MG8200_PID || s->cfg->pid == CS8800F_PID || s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) n = MIN (n, 4); /* exception for 9600dpi on Canoscan 9000F */ if ((s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) && (s->param->xdpi == 9600)) { n = 8; if (test > 0) n = 1; /* test if 8 images are next to one another */ } /* test if 2 images are next to one another */ if ((s->cfg->pid == MP960_PID) && (s->param->xdpi == 4800) && (test > 0)) { n = 1; } m = (n > 0) ? s->param->wx / n : 1; sptr = dptr = gptr = cptr = mp->imgbuf; line_size = get_cis_ccd_line_size (s); /* PDBG (pixma_dbg (4, "*post_process_image_data***** ----- Set n=%u, m=%u, line_size=%u ----- ***** \n", n, m, line_size)); */ /* PDBG (pixma_dbg (4, "*post_process_image_data***** ----- spr=dpr=%u, linebuf=%u ----- ***** \n", sptr, mp->linebuf)); */ lines = (mp->data_left_ofs - mp->imgbuf) / line_size; /* PDBG (pixma_dbg (4, "*post_process_image_data***** lines = %i > 2 * mp->color_shift + mp->stripe_shift = %i ***** \n", lines, 2 * mp->color_shift + mp->stripe_shift)); */ /* PDBG (pixma_dbg (4, "*post_process_image_data***** mp->color_shift = %u, mp->stripe_shift = %u, , mp->stripe_shift2 = %u ***** \n", mp->color_shift, mp->stripe_shift, mp->stripe_shift2)); */ /*color_shift = mp->color_shift;*/ /*stripe_shift = mp->stripe_shift;*/ /*stripe_shift2 = mp->stripe_shift2;*/ jumplines = mp->jumplines; /* height not needed here! */ /* removed to avoid confusion */ /* height = MIN (s->param->h + calc_shifting (s), s->cfg->height * s->param->ydpi / 75); */ /* have to test if rounding down is OK or not -- currently 0.5 lines is rounded down */ /* note stripe shifts doubled already in definitions */ if ((s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) && (s->param->xdpi == 9600) && (test > 0)) { /* using test==2 you can check in GIMP the required offset, and use the below line (uncommented) and replace XXX with that number, and then compile again with test set to 1. */ jumplines = 32; if (test == 2) jumplines = 0; } /* mp960 test */ if ((s->cfg->pid == MP960_PID) && (s->param->xdpi == 4800) && (test > 0)) { jumplines = 32; if (test == 2) jumplines = 0; } reducelines = ((2 * mp->color_shift + mp->stripe_shift) + jumplines); /* PDBG (pixma_dbg (4, "*post_process_image_data: lines %u, reducelines %u \n", lines, reducelines)); */ if (lines > reducelines) { /* (line - reducelines) of image lines can be converted */ unsigned i; lines -= reducelines; for (i = 0; i < lines; i++, sptr += line_size) { /* convert only full image lines */ /* Color plane and stripes shift needed by e.g. CCD */ /* PDBG (pixma_dbg (4, "*post_process_image_data***** Processing with c=%u, n=%u, m=%u, w=%i, line_size=%u ***** \n", c, n, m, s->param->wx, line_size)); */ if (c >= 3) { if (((s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) && (s->param->xdpi == 9600)) || ((s->cfg->pid == MP960_PID) && (s->param->xdpi == 4800)) || ((s->cfg->pid == MP810_PID) && (s->param->xdpi == 4800))) { dptr = shift_colorsCS9000 (dptr, sptr, s->param->wx, s->param->xdpi, s->cfg->pid, c, mp->shift, mp->stripe_shift, mp->stripe_shift2, jumplines * line_size); } else if ((s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) /* 9000F: 16 bit flatbed scan at 4800dpi */ && ((s->param->mode == PIXMA_SCAN_MODE_COLOR_48) || (s->param->mode == PIXMA_SCAN_MODE_GRAY_16)) && (s->param->xdpi == 4800) && (s->param->source == PIXMA_SOURCE_FLATBED)) dptr = shift_colorsCS9000_4800 (dptr, sptr, s->param->wx, s->param->xdpi, s->cfg->pid, c, mp->shift, mp->stripe_shift, mp->stripe_shift2, jumplines * line_size); else /* all except 9000F at 9600dpi */ dptr = shift_colors (dptr, sptr, s->param->wx, s->param->xdpi, s->cfg->pid, c, mp->shift, mp->stripe_shift); } /*PDBG (pixma_dbg (4, "*post_process_image_data***** test = %i *****\n", test)); */ /*--comment out all between this line and the one below for 9000F tests at 9600dpi or MP960 at 4800dpi ------*/ /* if ( 0 ) */ if ((((s->cfg->pid != CS9000F_PID && s->cfg->pid != CS9000F_MII_PID) || (s->param->xdpi < 9600)) && ((s->cfg->pid != MP960_PID) || (s->param->xdpi < 4800)) && ((s->cfg->pid != MP810_PID) || (s->param->xdpi < 4800))) || (test == 0)) { /* PDBG (pixma_dbg (4, "*post_process_image_data***** MUST GET HERE WHEN TEST == 0 *****\n")); */ if (!((s->cfg->pid == MP810_PID) && (s->param->xdpi == 4800)) && !((s->cfg->pid == MP960_PID) && (s->param->xdpi == 4800)) && !((s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) && (s->param->xdpi == 9600))) { /* for both flatbed & TPU */ /* PDBG (pixma_dbg (4, "*post_process_image_data***** reordering pixels normal n = %i *****\n", n)); */ reorder_pixels (mp->linebuf, sptr, c, n, m, s->param->wx, line_size); } if ((s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) && (s->param->xdpi == 9600)) { /* PDBG (pixma_dbg (4, "*post_process_image_data***** cs900f_initial_reorder_pixels n = %i *****\n", n)); */ /* this combines pixels from 8 images 2px at a time from left to right: 1122334455667788... */ cs9000f_initial_reorder_pixels (mp->linebuf, sptr, c, n, m, s->param->wx, line_size); /* final interleaving */ cs9000f_second_reorder_pixels (mp->linebuf, sptr, c, s->param->wx, line_size); } /* comment: special image format for MP960 in flatbed mode at 4800dpi. It is actually 2400dpi, with each pixel doubled. The TPU mode has proper pixel ordering */ if ((((s->cfg->pid == MP960_PID) || (s->cfg->pid == MP810_PID)) && (s->param->xdpi == 4800)) && (n > 0)) { /* for both flatbed & TPU */ /* PDBG (pixma_dbg (4, "*post_process_image_data***** flatbed mp960_reordering pixels n = %i *****\n", n)); */ mp960_reorder_pixels (mp->linebuf, sptr, c, n, m, s->param->wx, line_size); } /* comment: MP970, CS8800F, CS9000F specific reordering for 4800 dpi */ if ((s->cfg->pid == MP970_PID || s->cfg->pid == CS8800F_PID || s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID || s->cfg->pid == MP990_PID) && (s->param->xdpi == 4800)) { /*PDBG (pixma_dbg (4, "*post_process_image_data***** mp970_reordering pixels n = %i *****\n", n)); */ mp970_reorder_pixels (mp->linebuf, sptr, c, s->param->wx, line_size); } } /*-------------------------------------------------------*/ /* PDBG (pixma_dbg (4, "*post_process_image_data: sptr=%u, dptr=%u \n", sptr, dptr)); */ /* Crop line to selected borders */ memmove (cptr, sptr + cx, cw); /* PDBG (pixma_dbg (4, "*post_process_image_data***** crop line: cx=%u, cw=%u ***** \n", cx, cw)); */ /* Color to Lineart convert for CCD sensor */ if (is_lineart (s)) cptr = gptr = pixma_binarize_line (s->param, gptr, cptr, s->param->w, c); #ifndef TPUIR_USE_RGB /* save IR only for CCD sensor */ else if (is_tpuir (s)) cptr = gptr = pixma_r_to_ir (gptr, cptr, s->param->w, c); /* Color to Grayscale convert for CCD sensor */ else if (is_gray_all (s)) #else /* IR *and* Color to Grayscale convert for CCD sensor */ else if (is_tpuir (s) || is_gray_all (s)) #endif cptr = gptr = pixma_rgb_to_gray (gptr, cptr, s->param->w, c); else cptr += cw; } /* PDBG (pixma_dbg (4, "*post_process_image_data: sptr=%u, dptr=%u \n", sptr, dptr)); */ } ib->rptr = mp->imgbuf; ib->rend = cptr; return mp->data_left_ofs - sptr; /* # of non processed bytes */ /* contains shift color data for new lines */ /* and already received data for the next line */ } static int mp810_open (pixma_t * s) { mp810_t *mp; uint8_t *buf; mp = (mp810_t *) calloc (1, sizeof(*mp)); if (!mp) return PIXMA_ENOMEM; buf = (uint8_t *) malloc (CMDBUF_SIZE + IMAGE_BLOCK_SIZE); if (!buf) { free (mp); return PIXMA_ENOMEM; } s->subdriver = mp; mp->state = state_idle; mp->cb.buf = buf; mp->cb.size = CMDBUF_SIZE; mp->cb.res_header_len = 8; mp->cb.cmd_header_len = 16; mp->cb.cmd_len_field_ofs = 14; mp->imgbuf = buf + CMDBUF_SIZE; /* General rules for setting Pixma protocol generation # */ mp->generation = (s->cfg->pid >= MP810_PID) ? 2 : 1; /* no generation 1 devices anyway, but keep similar to pixma_mp150.c file */ if (s->cfg->pid >= MP970_PID) mp->generation = 3; if (s->cfg->pid >= MP990_PID) mp->generation = 4; /* And exceptions to be added here */ if (s->cfg->pid == CS8800F_PID) mp->generation = 3; if (s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID) mp->generation = 4; /* TPU info data setup */ mp->tpu_datalen = 0; if (mp->generation < 4) { /* Canoscan 8800F ignores commands if not initialized */ if (s->cfg->pid == CS8800F_PID) abort_session (s); else { query_status (s); handle_interrupt (s, 200); if (mp->generation == 3 && has_ccd_sensor (s)) send_cmd_start_calibrate_ccd_3 (s); } } return 0; } static void mp810_close (pixma_t * s) { mp810_t *mp = (mp810_t *) s->subdriver; mp810_finish_scan (s); free (mp->cb.buf); free (mp); s->subdriver = NULL; } static int mp810_check_param (pixma_t * s, pixma_scan_param_t * sp) { mp810_t *mp = (mp810_t *) s->subdriver; unsigned w_max; /* PDBG (pixma_dbg (4, "*mp810_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u *****\n", sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx)); */ sp->channels = 3; sp->software_lineart = 0; switch (sp->mode) { /* standard scan modes * 8 bit per channel in color and grayscale mode * 16 bit per channel with TPU */ case PIXMA_SCAN_MODE_GRAY: case PIXMA_SCAN_MODE_NEGATIVE_GRAY: case PIXMA_SCAN_MODE_TPUIR: sp->channels = 1; /* fall through */ case PIXMA_SCAN_MODE_COLOR: case PIXMA_SCAN_MODE_NEGATIVE_COLOR: sp->depth = 8; #ifdef TPU_48 #ifndef DEBUG_TPU_48 if (sp->source == PIXMA_SOURCE_TPU) #endif sp->depth = 16; /* TPU in 16 bits mode */ #endif break; /* extended scan modes for 48 bit flatbed scanners * 16 bit per channel in color and grayscale mode */ case PIXMA_SCAN_MODE_GRAY_16: sp->channels = 1; sp->depth = 16; break; case PIXMA_SCAN_MODE_COLOR_48: sp->channels = 3; sp->depth = 16; break; /* software lineart * 1 bit per channel */ case PIXMA_SCAN_MODE_LINEART: sp->software_lineart = 1; sp->channels = 1; sp->depth = 1; break; } /* for software lineart w must be a multiple of 8 * I don't know why is_lineart(s) doesn't work here */ if (sp->software_lineart == 1 && sp->w % 8) { sp->w += 8 - (sp->w % 8); /* do not exceed the scanner capability */ w_max = s->cfg->width * s->cfg->xdpi / 75; w_max -= w_max % 8; if (sp->w > w_max) sp->w = w_max; } if (sp->source == PIXMA_SOURCE_TPU && !sp->tpu_offset_added) { unsigned fixed_offset_y; /* TPU offsets for CanoScan 8800F, or other CCD at 300dpi. */ unsigned max_y; /* max TPU height for CS9000F at 75 dpi */ /* CanoScan 8800F and others adding an offset depending on resolution */ /* CS9000F and others maximum TPU height */ switch (s->cfg->pid) { case CS8800F_PID: fixed_offset_y = 140; max_y = MIN (740, s->cfg->height); break; case CS9000F_PID: case CS9000F_MII_PID: fixed_offset_y = 146; max_y = MIN (740, s->cfg->height); break; default: fixed_offset_y = 0; max_y = s->cfg->height; break; } /* cropping y and h to scanable area */ max_y *= (sp->ydpi) / 75; sp->y = MIN(sp->y, max_y); sp->h = MIN(sp->h, max_y - sp->y); /* PDBG (pixma_dbg (4, "*mp810_check_param***** Cropping: y=%u, h=%u *****\n", sp->y, sp->h)); */ if (!sp->h) return SANE_STATUS_INVAL; /* no lines */ /* Convert the offsets from 300dpi to actual resolution */ fixed_offset_y = fixed_offset_y * (sp->xdpi) / 300; /* In TPU mode, the CS9000F appears to always subtract 146 from the vertical starting position, but clamps its at 0. Therefore vertical offsets 0 through 146 (@300 dpi) get all mapped onto the same physical starting position: line 0. Then, starting from 147, the offsets get mapped onto successive physical lines: y line 0 -> 0 1 -> 0 2 -> 0 ... 146 -> 0 147 -> 1 148 -> 2 ... Since a preview scan is typically made starting from y = 0, but partial image scans usually start at y >> 147, this results in a discontinuity in the y to line mapping, resulting in wrong offsets. To prevent this, we must always add (at least) 146 to the y offset before it is sent to the scanner. The scanner will then map y = 0 (146) to the first line, y = 1 (147) to the second line, and so on. Any distance that is then measured on the preview scan, can be translated without any discontinuity. However, there is one complication: during a preview scan, which normally covers the whole scan area of the scanner, we should _not_ add the offset because it will result in a reduced number of lines being returned (the scan height is clamped in pixma_check_scan_param()). Since the frontend has no way of telling that the scan area has been reduced, it would derive an incorrect effective scan resolution, and any position calculations based on this would therefore be inaccurate. To prevent this, we don't add the offset in case y = 0, which is typically the case during a preview scan (the scanner effectively adds the offset for us, see above). In that way we keep the linearity and we don't affect the scan area during previews. */ if (sp->y > 0) sp->y += fixed_offset_y; /* Prevent repeated corrections as check_param may be called multiple times */ sp->tpu_offset_added = 1; } if (mp->generation >= 2) { /* mod 32 and expansion of the X scan limits */ /* PDBG (pixma_dbg (4, "*mp810_check_param***** (gen>=2) xs=mod32 ----- Initially: x=%u, y=%u, w=%u, h=%u *****\n", sp->x, sp->y, sp->w, sp->h)); */ sp->xs = (sp->x) % 32; } else { sp->xs = 0; /* PDBG (pixma_dbg (4, "*mp810_check_param***** (else) xs=0 Selected origin, origin shift: %u, %u *****\n", sp->x, sp->xs)); */ } sp->wx = calc_raw_width (mp, sp); sp->line_size = sp->w * sp->channels * (((sp->software_lineart) ? 8 : sp->depth) / 8); /* bytes per line per color after cropping */ /* PDBG (pixma_dbg (4, "*mp810_check_param***** (else) Final scan width and line-size: %u, %"PRIu64" *****\n", sp->wx, sp->line_size)); */ /* highest res is 600, 2400, 4800 or 9600 dpi */ { uint8_t k; if ((sp->source == PIXMA_SOURCE_ADF || sp->source == PIXMA_SOURCE_ADFDUP) && mp->generation >= 4) /* ADF/ADF duplex mode: max scan res is 600 dpi, at least for generation 4 */ k = sp->xdpi / MIN (sp->xdpi, 600); else if (sp->source == PIXMA_SOURCE_TPU && sp->mode == PIXMA_SCAN_MODE_TPUIR) /* TPUIR mode: max scan res is 2400 dpi */ k = sp->xdpi / MIN (sp->xdpi, 2400); else if (sp->source == PIXMA_SOURCE_TPU && (s->cfg->pid == CS9000F_PID || s->cfg->pid == CS9000F_MII_PID)) /* CS9000F in TPU mode */ k = sp->xdpi / MIN (sp->xdpi, 9600); else /* default */ k = sp->xdpi / MIN (sp->xdpi, 4800); sp->x /= k; sp->xs /= k; sp->y /= k; sp->w /= k; sp->wx /= k; sp->h /= k; sp->xdpi /= k; sp->ydpi = sp->xdpi; } /* lowest res is 75, 150, 300 or 600 dpi */ { uint8_t k; if (sp->source == PIXMA_SOURCE_TPU && sp->mode == PIXMA_SCAN_MODE_TPUIR) /* TPUIR mode */ k = MAX (sp->xdpi, 600) / sp->xdpi; else if (sp->source == PIXMA_SOURCE_TPU && ((mp->generation >= 3) || (s->cfg->pid == MP810_PID) || (s->cfg->pid == MP960_PID))) /* TPU mode for generation 3+ scanners * MP810, MP960 appear to have a 200dpi mode for low-res scans, not 150 dpi */ k = MAX (sp->xdpi, 300) / sp->xdpi; else if (sp->source == PIXMA_SOURCE_TPU || sp->mode == PIXMA_SCAN_MODE_COLOR_48 || sp->mode == PIXMA_SCAN_MODE_GRAY_16) /* TPU mode and 16 bit flatbed scans * TODO: either the frontend (xsane) cannot handle 48 bit flatbed scans @ 75 dpi (prescan) * or there is a bug in this subdriver */ k = MAX (sp->xdpi, 150) / sp->xdpi; else /* default */ k = MAX (sp->xdpi, 75) / sp->xdpi; sp->x *= k; sp->xs *= k; sp->y *= k; sp->w *= k; sp->wx *= k; sp->h *= k; sp->xdpi *= k; sp->ydpi = sp->xdpi; } /* PDBG (pixma_dbg (4, "*mp810_check_param***** Finally: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u *****\n", sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx)); */ return 0; } static int mp810_scan (pixma_t * s) { int error = 0, tmo; mp810_t *mp = (mp810_t *) s->subdriver; if (mp->state != state_idle) return PIXMA_EBUSY; /* Generation 4: send XML dialog */ if (mp->generation == 4 && s->param->adf_pageid == 0) { if (!send_xml_dialog (s, XML_START_1)) return PIXMA_EPROTO; if (!send_xml_dialog (s, XML_START_2)) return PIXMA_EPROTO; } /* clear interrupt packets buffer */ while (handle_interrupt (s, 0) > 0) { } /* FIXME: Duplex ADF: check paper status only before odd pages (1,3,5,...). */ if (is_scanning_from_adf (s)) { if ((error = query_status (s)) < 0) return error; tmo = 10; while (!has_paper (s) && --tmo >= 0) { WAIT_INTERRUPT(1000); PDBG(pixma_dbg (2, "No paper in ADF. Timed out in %d sec.\n", tmo)); } if (!has_paper (s)) return PIXMA_ENO_PAPER; } if (has_ccd_sensor (s) && (mp->generation <= 2)) { error = send_cmd_e920 (s); switch (error) { case PIXMA_ECANCELED: case PIXMA_EBUSY: PDBG(pixma_dbg (2, "cmd e920 or d520 returned %s\n", pixma_strerror (error))); /* fall through */ case 0: query_status (s); break; default: PDBG(pixma_dbg (1, "WARNING: cmd e920 or d520 failed %s\n", pixma_strerror (error))); return error; } tmo = 3; /* like Windows driver, CCD calibration ? */ while (--tmo >= 0) { WAIT_INTERRUPT(1000); PDBG(pixma_dbg (2, "CCD Calibration ends in %d sec.\n", tmo)); } /* pixma_sleep(2000000); */ } tmo = 10; if (s->param->adf_pageid == 0 || mp->generation <= 2) { error = start_session (s); while (error == PIXMA_EBUSY && --tmo >= 0) { if (s->cancel) { error = PIXMA_ECANCELED; break; } PDBG(pixma_dbg (2, "Scanner is busy. Timed out in %d sec.\n", tmo + 1)); pixma_sleep (1000000); error = start_session (s); } if (error == PIXMA_EBUSY || error == PIXMA_ETIMEDOUT) { /* The scanner maybe hangs. We try to empty output buffer of the * scanner and issue the cancel command. */ PDBG(pixma_dbg (2, "Scanner hangs? Sending abort_session command.\n")); drain_bulk_in (s); abort_session (s); pixma_sleep (500000); error = start_session (s); } if ((error >= 0) || (mp->generation >= 3)) mp->state = state_warmup; if ((error >= 0) && (mp->generation <= 2)) error = select_source (s); if ((error >= 0) && (mp->generation >= 3) && has_ccd_sensor (s)) error = init_ccd_lamp_3 (s); if ((error >= 0) && !is_scanning_from_tpu (s)) { int i; /* FIXME: 48 bit flatbed scans don't need gamma tables * the code below doesn't run */ /*if (is_color_48 (s) || is_gray_16 (s)) error = 0; else*/ for (i = (mp->generation >= 3) ? 3 : 1; i > 0 && error >= 0; i--) error = send_gamma_table (s); } else if (error >= 0) /* in TPU mode, for gen 1, 2, and 3 */ error = send_set_tpu_info (s); } else /* ADF pageid != 0 and gen3 or above */ pixma_sleep (1000000); if ((error >= 0) || (mp->generation >= 3)) mp->state = state_warmup; if (error >= 0) error = send_scan_param (s); if ((error >= 0) && (mp->generation >= 3)) error = start_scan_3 (s); if (error < 0) { mp->last_block = 0x38; /* Force abort session if ADF scan */ mp810_finish_scan (s); return error; } return 0; } static int mp810_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { int error; mp810_t *mp = (mp810_t *) s->subdriver; unsigned block_size, bytes_received, proc_buf_size, line_size; uint8_t header[16]; if (mp->state == state_warmup) { /* prepare read image data */ /* PDBG (pixma_dbg (4, "**mp810_fill_buffer***** warmup *****\n")); */ RET_IF_ERR(wait_until_ready (s)); pixma_sleep (1000000); /* No need to sleep, actually, but Window's driver * sleep 1.5 sec. */ mp->state = state_scanning; mp->last_block = 0; line_size = get_cis_ccd_line_size (s); proc_buf_size = (2 * calc_shifting (s) + 2) * line_size; mp->cb.buf = realloc (mp->cb.buf, CMDBUF_SIZE + IMAGE_BLOCK_SIZE + proc_buf_size); if (!mp->cb.buf) return PIXMA_ENOMEM; mp->linebuf = mp->cb.buf + CMDBUF_SIZE; mp->imgbuf = mp->data_left_ofs = mp->linebuf + line_size; mp->data_left_len = 0; } do { /* read complete image data from the scanner */ if (s->cancel) return PIXMA_ECANCELED; if ((mp->last_block & 0x28) == 0x28) { /* end of image */ mp->state = state_finished; /* PDBG (pixma_dbg (4, "**mp810_fill_buffer***** end of image *****\n")); */ return 0; } /* PDBG (pixma_dbg (4, "*mp810_fill_buffer***** moving %u bytes into buffer *****\n", mp->data_left_len)); */ memmove (mp->imgbuf, mp->data_left_ofs, mp->data_left_len); error = read_image_block (s, header, mp->imgbuf + mp->data_left_len); if (error < 0) { if (error == PIXMA_ECANCELED) { /* NOTE: I see this in traffic logs but I don't know its meaning. */ read_error_info (s, NULL, 0); } return error; } bytes_received = error; /*PDBG (pixma_dbg (4, "*mp810_fill_buffer***** %u bytes received by read_image_block *****\n", bytes_received));*/ block_size = pixma_get_be32 (header + 12); mp->last_block = header[8] & 0x38; if ((header[8] & ~0x38) != 0) { PDBG(pixma_dbg (1, "WARNING: Unexpected result header\n")); PDBG(pixma_hexdump (1, header, 16)); } PASSERT(bytes_received == block_size); if (block_size == 0) { /* no image data at this moment. */ pixma_sleep (10000); } /* For TPU at 48 bits/pixel to output at 24 bits/pixel */ #ifndef DEBUG_TPU_48 #ifndef TPU_48 PDBG (pixma_dbg (1, "WARNING: 9000F using 24 instead of 48 bit processing \n")); #ifndef DEBUG_TPU_24 if (is_scanning_from_tpu (s)) #endif bytes_received = pack_48_24_bpc (mp->imgbuf + mp->data_left_len, bytes_received); #endif #endif /* Post-process the image data */ mp->data_left_ofs = mp->imgbuf + mp->data_left_len + bytes_received; mp->data_left_len = post_process_image_data (s, ib); mp->data_left_ofs -= mp->data_left_len; /* PDBG (pixma_dbg (4, "* mp810_fill_buffer: data_left_len %u \n", mp->data_left_len)); */ /* PDBG (pixma_dbg (4, "* mp810_fill_buffer: data_left_ofs %u \n", mp->data_left_ofs)); */ } while (ib->rend == ib->rptr); return ib->rend - ib->rptr; } static void mp810_finish_scan (pixma_t * s) { int error; mp810_t *mp = (mp810_t *) s->subdriver; switch (mp->state) { case state_transfering: drain_bulk_in (s); /* fall through */ case state_scanning: case state_warmup: case state_finished: /* Send the get TPU info message */ if (is_scanning_from_tpu (s) && mp->tpu_datalen == 0) send_get_tpu_info_3 (s); /* FIXME: to process several pages ADF scan, must not send * abort_session and start_session between pages (last_block=0x28) */ if (mp->generation <= 2 || !is_scanning_from_adf (s) || mp->last_block == 0x38) { error = abort_session (s); /* FIXME: it probably doesn't work in duplex mode! */ if (error < 0) PDBG(pixma_dbg (1, "WARNING:abort_session() failed %d\n", error)); /* Generation 4: send XML end of scan dialog */ if (mp->generation == 4) { if (!send_xml_dialog (s, XML_END)) PDBG(pixma_dbg (1, "WARNING:XML_END dialog failed \n")); } } mp->state = state_idle; /* fall through */ case state_idle: break; } } static void mp810_wait_event (pixma_t * s, int timeout) { /* FIXME: timeout is not correct. See usbGetCompleteUrbNoIntr() for * instance. */ while (s->events == 0 && handle_interrupt (s, timeout) > 0) { } } static int mp810_get_status (pixma_t * s, pixma_device_status_t * status) { int error; RET_IF_ERR(query_status (s)); status->hardware = PIXMA_HARDWARE_OK; status->adf = (has_paper (s)) ? PIXMA_ADF_OK : PIXMA_ADF_NO_PAPER; status->cal = (is_calibrated (s)) ? PIXMA_CALIBRATION_OK : PIXMA_CALIBRATION_OFF; return 0; } static const pixma_scan_ops_t pixma_mp810_ops = { mp810_open, mp810_close, mp810_scan, mp810_fill_buffer, mp810_finish_scan, mp810_wait_event, mp810_check_param, mp810_get_status }; #define DEVICE(name, model, pid, dpi, adftpu_min_dpi, adftpu_max_dpi, tpuir_min_dpi, tpuir_max_dpi, w, h, cap) { \ name, /* name */ \ model, /* model */ \ CANON_VID, pid, /* vid pid */ \ 0, /* iface */ \ &pixma_mp810_ops, /* ops */ \ dpi, 2*(dpi), /* xdpi, ydpi */ \ adftpu_min_dpi, adftpu_max_dpi, /* adftpu_min_dpi, adftpu_max_dpi */ \ tpuir_min_dpi, tpuir_max_dpi, /* tpuir_min_dpi, tpuir_max_dpi */ \ w, h, /* width, height */ \ PIXMA_CAP_EASY_RGB| \ PIXMA_CAP_GRAY| /* all scanners with software grayscale */ \ PIXMA_CAP_LINEART| /* all scanners with software lineart */ \ PIXMA_CAP_GAMMA_TABLE|PIXMA_CAP_EVENTS|cap \ } #define END_OF_DEVICE_LIST DEVICE(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0) const pixma_config_t pixma_mp810_devices[] = { /* Generation 2: CCD */ DEVICE ("Canon PIXMA MP810", "MP810", MP810_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), DEVICE ("Canon PIXMA MP960", "MP960", MP960_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), /* Generation 3 CCD not managed as Generation 2 */ DEVICE ("Canon Pixma MP970", "MP970", MP970_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), /* Flatbed scanner CCD (2007) */ DEVICE ("Canoscan 8800F", "8800F", CS8800F_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU /*| PIXMA_CAP_NEGATIVE*/ | PIXMA_CAP_48BIT), /* PIXMA 2008 vintage CCD */ DEVICE ("Canon MP980 series", "MP980", MP980_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), /* Generation 4 CCD */ DEVICE ("Canon MP990 series", "MP990", MP990_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), /* Flatbed scanner (2010) */ DEVICE ("Canoscan 9000F", "9000F", CS9000F_PID, 4800, 300, 9600, 600, 2400, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPUIR /*| PIXMA_CAP_NEGATIVE*/ | PIXMA_CAP_48BIT), /* Latest devices (2010) Generation 4 CCD untested */ DEVICE ("Canon PIXMA MG8100", "MG8100", MG8100_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), /* Latest devices (2011) Generation 4 CCD untested */ DEVICE ("Canon PIXMA MG8200", "MG8200", MG8200_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPU), /* Flatbed scanner (2013) */ DEVICE ("Canoscan 9000F Mark II", "9000FMarkII", CS9000F_MII_PID, 4800, 300, 9600, 600, 2400, 638, 877, PIXMA_CAP_CCD | PIXMA_CAP_TPUIR | PIXMA_CAP_48BIT), END_OF_DEVICE_LIST }; sane-backends-1.0.27/backend/epson2-io.c0000664000175000017500000002241313106201017014561 00000000000000/* * I/O routines for Epson scanners * * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for original copyrights. * * Copyright (C) 2006 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #include #include "epson2.h" #include "epson2-io.h" #include "sane/sanei_scsi.h" #include "sane/sanei_usb.h" #include "sane/sanei_pio.h" #include "sane/sanei_tcp.h" #include "epson2_scsi.h" #include "epson_usb.h" #include "epson2_net.h" #include "byteorder.h" /* flaming hack to get USB scanners * working without timeouts under linux * (cribbed from fujitsu.c) */ unsigned int r_cmd_count = 0; unsigned int w_cmd_count = 0; int e2_send(Epson_Scanner * s, void *buf, size_t buf_size, size_t reply_len, SANE_Status * status) { DBG(15, "%s: size = %lu, reply = %lu\n", __func__, (u_long) buf_size, (u_long) reply_len); if (buf_size == 2) { char *cmd = buf; switch (cmd[0]) { case ESC: DBG(9, "%s: ESC %c\n", __func__, cmd[1]); break; case FS: DBG(9, "%s: FS %c\n", __func__, cmd[1]); break; } } if (DBG_LEVEL >= 125) { unsigned int k; const unsigned char *s = buf; for (k = 0; k < buf_size; k++) { DBG(125, "buf[%d] %02x %c\n", k, s[k], isprint(s[k]) ? s[k] : '.'); } } if (s->hw->connection == SANE_EPSON_NET) { if (reply_len == 0) { DBG(0, "Cannot send this command to a networked scanner\n"); return SANE_STATUS_INVAL; } return sanei_epson_net_write(s, 0x2000, buf, buf_size, reply_len, status); } else if (s->hw->connection == SANE_EPSON_SCSI) { return sanei_epson2_scsi_write(s->fd, buf, buf_size, status); } else if (s->hw->connection == SANE_EPSON_PIO) { size_t n; if (buf_size == (n = sanei_pio_write(s->fd, buf, buf_size))) *status = SANE_STATUS_GOOD; else *status = SANE_STATUS_INVAL; return n; } else if (s->hw->connection == SANE_EPSON_USB) { size_t n; n = buf_size; *status = sanei_usb_write_bulk(s->fd, buf, &n); w_cmd_count++; DBG(20, "%s: cmd count, r = %d, w = %d\n", __func__, r_cmd_count, w_cmd_count); return n; } *status = SANE_STATUS_INVAL; return 0; /* never reached */ } ssize_t e2_recv(Epson_Scanner *s, void *buf, ssize_t buf_size, SANE_Status *status) { ssize_t n = buf_size; /* network interface needs to read header back even data is 0.*/ DBG(15, "%s: size = %ld, buf = %p\n", __func__, (long) buf_size, buf); *status = SANE_STATUS_GOOD; if (s->hw->connection == SANE_EPSON_NET) { n = sanei_epson_net_read(s, buf, buf_size, status); } else if (s->hw->connection == SANE_EPSON_SCSI) { if (buf_size) n = sanei_epson2_scsi_read(s->fd, buf, buf_size, status); } else if (s->hw->connection == SANE_EPSON_PIO) { if (buf_size) { if (buf_size == (n = sanei_pio_read(s->fd, buf, (size_t) buf_size))) *status = SANE_STATUS_GOOD; else *status = SANE_STATUS_INVAL; } } else if (s->hw->connection == SANE_EPSON_USB) { /* !!! only report an error if we don't read anything */ if (n) { *status = sanei_usb_read_bulk(s->fd, (SANE_Byte *) buf, (size_t *) & n); r_cmd_count += (n + 63) / 64; /* add # of packets, rounding up */ DBG(20, "%s: cmd count, r = %d, w = %d\n", __func__, r_cmd_count, w_cmd_count); if (n > 0) *status = SANE_STATUS_GOOD; } } if (n < buf_size) { DBG(1, "%s: expected = %lu, got = %ld, canceling: %d\n", __func__, (u_long) buf_size, (long) n, s->canceling); *status = SANE_STATUS_IO_ERROR; } /* dump buffer if appropriate */ if (DBG_LEVEL >= 127 && n > 0) { int k; const unsigned char *s = buf; for (k = 0; k < n; k++) DBG(127, "buf[%d] %02x %c\n", k, s[k], isprint(s[k]) ? s[k] : '.'); } return n; } /* Simple function to exchange a fixed amount of * data with the scanner */ SANE_Status e2_txrx(Epson_Scanner * s, unsigned char *txbuf, size_t txlen, unsigned char *rxbuf, size_t rxlen) { SANE_Status status; size_t done; done = e2_send(s, txbuf, txlen, rxlen, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status)); return status; } if (done != txlen) { DBG(1, "%s: tx err, short write\n", __func__); return SANE_STATUS_IO_ERROR; } e2_recv(s, rxbuf, rxlen, &status); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: rx err, %s\n", __func__, sane_strstatus(status)); } DBG(1, "%s: eds_recv status, %s\n", __func__, sane_strstatus(status)); return status; } /* This function should be used to send codes that only requires the scanner * to give back an ACK or a NAK. */ SANE_Status e2_cmd_simple(Epson_Scanner * s, void *buf, size_t buf_size) { unsigned char result; SANE_Status status; DBG(12, "%s: size = %lu\n", __func__, (u_long) buf_size); status = e2_txrx(s, buf, buf_size, &result, 1); if (status != SANE_STATUS_GOOD) { DBG(1, "%s: failed, %s\n", __func__, sane_strstatus(status)); return status; } if (result == ACK) return SANE_STATUS_GOOD; if (result == NAK) { DBG(3, "%s: NAK\n", __func__); return SANE_STATUS_INVAL; } DBG(1, "%s: result is neither ACK nor NAK but 0x%02x\n", __func__, result); return SANE_STATUS_GOOD; } /* receives a 4 or 6 bytes information block from the scanner*/ SANE_Status e2_recv_info_block(Epson_Scanner * s, unsigned char *scanner_status, size_t info_size, size_t * payload_size) { SANE_Status status; unsigned char info[6]; if (s->hw->connection == SANE_EPSON_PIO) e2_recv(s, info, 1, &status); else e2_recv(s, info, info_size, &status); if (status != SANE_STATUS_GOOD) return status; /* check for explicit NAK */ if (info[0] == NAK) { DBG(1, "%s: command not supported\n", __func__); return SANE_STATUS_UNSUPPORTED; } /* check the first byte: if it's not STX, bail out */ if (info[0] != STX) { DBG(1, "%s: expecting STX, got %02X\n", __func__, info[0]); return SANE_STATUS_INVAL; } /* if connection is PIO read the remaining bytes. */ if (s->hw->connection == SANE_EPSON_PIO) { e2_recv(s, &info[1], info_size - 1, &status); if (status != SANE_STATUS_GOOD) return status; } if (scanner_status) *scanner_status = info[1]; if (payload_size) { *payload_size = le16atoh(&info[2]); if (info_size == 6) *payload_size *= le16atoh(&info[4]); DBG(14, "%s: payload length: %lu\n", __func__, (u_long) *payload_size); } return SANE_STATUS_GOOD; } /* This function can be called for commands that * will be answered by the scanner with an info block of 4 bytes * and a variable payload. The payload is passed back to the caller * in **buf. The caller must free it if != NULL, * even if the status != SANE_STATUS_GOOD. */ SANE_Status e2_cmd_info_block(SANE_Handle handle, unsigned char *params, unsigned char params_len, size_t reply_len, unsigned char **buf, size_t * buf_len) { SANE_Status status; Epson_Scanner *s = (Epson_Scanner *) handle; size_t len; DBG(13, "%s, params len = %d, reply len = %lu, buf = %p\n", __func__, params_len, (u_long) reply_len, (void *) buf); if (buf == NULL) return SANE_STATUS_INVAL; /* initialize */ *buf = NULL; /* send command, we expect the info block + reply_len back */ e2_send(s, params, params_len, reply_len ? reply_len + 4 : 0, &status); if (status != SANE_STATUS_GOOD) goto end; status = e2_recv_info_block(s, NULL, 4, &len); if (status != SANE_STATUS_GOOD) goto end; /* do we need to provide the length of the payload? */ if (buf_len) *buf_len = len; /* no payload, stop here */ if (len == 0) goto end; /* if a reply_len has been specified and the actual * length differs, throw a warning */ if (reply_len && (len != reply_len)) { DBG(1, "%s: mismatched len - expected %lu, got %lu\n", __func__, (u_long) reply_len, (u_long) len); } /* allocate and receive the payload */ *buf = malloc(len); if (*buf) { memset(*buf, 0x00, len); e2_recv(s, *buf, len, &status); /* receive actual data */ } else status = SANE_STATUS_NO_MEM; end: if (status != SANE_STATUS_GOOD) { DBG(1, "%s: failed, %s\n", __func__, sane_strstatus(status)); if (*buf) { free(*buf); *buf = NULL; } } return status; } /* This is used for ESC commands with a single byte parameter. Scanner * will answer with ACK/NAK. */ SANE_Status e2_esc_cmd(Epson_Scanner * s, unsigned char cmd, unsigned char val) { SANE_Status status; unsigned char params[2]; DBG(8, "%s: cmd = 0x%02x, val = %d\n", __func__, cmd, val); if (!cmd) return SANE_STATUS_UNSUPPORTED; params[0] = ESC; params[1] = cmd; status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; params[0] = val; return e2_cmd_simple(s, params, 1); } /* Send an ACK to the scanner */ SANE_Status e2_ack(Epson_Scanner * s) { SANE_Status status; e2_send(s, S_ACK, 1, 0, &status); return status; } SANE_Status e2_ack_next(Epson_Scanner * s, size_t reply_len) { SANE_Status status; e2_send(s, S_ACK, 1, reply_len, &status); return status; } SANE_Status e2_cancel(Epson_Scanner * s) { DBG(1, "%s\n", __func__); return e2_cmd_simple(s, S_CAN, 1); } sane-backends-1.0.27/backend/epsonds-ops.c0000664000175000017500000002556612775312261015253 00000000000000/* * epsonds-ops.c - Epson ESC/I-2 driver, support routines. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #include /* sleep */ #ifdef HAVE_SYS_SELECT_H #include #endif #include "epsonds.h" #include "epsonds-io.h" #include "epsonds-ops.h" #include "epsonds-cmd.h" extern struct mode_param mode_params[]; /* Define the different scan sources */ #define FBF_STR SANE_I18N("Flatbed") #define TPU_STR SANE_I18N("Transparency Unit") #define ADF_STR SANE_I18N("Automatic Document Feeder") extern SANE_String_Const source_list[]; void eds_dev_init(epsonds_device *dev) { dev->res_list = malloc(sizeof(SANE_Word)); dev->res_list[0] = 0; dev->depth_list = malloc(sizeof(SANE_Word)); dev->depth_list[0] = 0; } SANE_Status eds_dev_post_init(struct epsonds_device *dev) { SANE_String_Const *source_list_add = source_list; DBG(10, "%s\n", __func__); if (dev->has_fb) *source_list_add++ = FBF_STR; if (dev->has_adf) *source_list_add++ = ADF_STR; if (source_list[0] == 0 || (dev->res_list[0] == 0 && dev->dpi_range.min == 0) || dev->depth_list[0] == 0) { DBG(1, "something is wrong in the discovery process, aborting.\n"); DBG(1, "sources: %ld, res: %d, depths: %d.\n", source_list_add - source_list, dev->res_list[0], dev->depth_list[0]); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } SANE_Bool eds_is_model(epsonds_device *dev, const char *model) { if (dev->model == NULL) return SANE_FALSE; if (strncmp(dev->model, model, strlen(model)) == 0) return SANE_TRUE; return SANE_FALSE; } SANE_Status eds_add_resolution(epsonds_device *dev, int r) { DBG(10, "%s: add (dpi): %d\n", __func__, r); /* first element is the list size */ dev->res_list[0]++; dev->res_list = realloc(dev->res_list, (dev->res_list[0] + 1) * sizeof(SANE_Word)); if (dev->res_list == NULL) return SANE_STATUS_NO_MEM; dev->res_list[dev->res_list[0]] = r; return SANE_STATUS_GOOD; } SANE_Status eds_set_resolution_range(epsonds_device *dev, int min, int max) { DBG(10, "%s: set min/max (dpi): %d/%d\n", __func__, min, max); dev->dpi_range.min = min; dev->dpi_range.max = max; dev->dpi_range.quant = 1; return SANE_STATUS_GOOD; } void eds_set_fbf_area(epsonds_device *dev, int x, int y, int unit) { if (x == 0 || y == 0) return; dev->fbf_x_range.min = 0; dev->fbf_x_range.max = SANE_FIX(x * MM_PER_INCH / unit); dev->fbf_x_range.quant = 0; dev->fbf_y_range.min = 0; dev->fbf_y_range.max = SANE_FIX(y * MM_PER_INCH / unit); dev->fbf_y_range.quant = 0; DBG(5, "%s: %f,%f %f,%f %d [mm]\n", __func__, SANE_UNFIX(dev->fbf_x_range.min), SANE_UNFIX(dev->fbf_y_range.min), SANE_UNFIX(dev->fbf_x_range.max), SANE_UNFIX(dev->fbf_y_range.max), unit); } void eds_set_adf_area(struct epsonds_device *dev, int x, int y, int unit) { dev->adf_x_range.min = 0; dev->adf_x_range.max = SANE_FIX(x * MM_PER_INCH / unit); dev->adf_x_range.quant = 0; dev->adf_y_range.min = 0; dev->adf_y_range.max = SANE_FIX(y * MM_PER_INCH / unit); dev->adf_y_range.quant = 0; DBG(5, "%s: %f,%f %f,%f %d [mm]\n", __func__, SANE_UNFIX(dev->adf_x_range.min), SANE_UNFIX(dev->adf_y_range.min), SANE_UNFIX(dev->adf_x_range.max), SANE_UNFIX(dev->adf_y_range.max), unit); } void eds_set_tpu_area(struct epsonds_device *dev, int x, int y, int unit) { dev->tpu_x_range.min = 0; dev->tpu_x_range.max = SANE_FIX(x * MM_PER_INCH / unit); dev->tpu_x_range.quant = 0; dev->tpu_y_range.min = 0; dev->tpu_y_range.max = SANE_FIX(y * MM_PER_INCH / unit); dev->tpu_y_range.quant = 0; DBG(5, "%s: %f,%f %f,%f %d [mm]\n", __func__, SANE_UNFIX(dev->tpu_x_range.min), SANE_UNFIX(dev->tpu_y_range.min), SANE_UNFIX(dev->tpu_x_range.max), SANE_UNFIX(dev->tpu_y_range.max), unit); } SANE_Status eds_add_depth(epsonds_device *dev, SANE_Word depth) { DBG(5, "%s: add (bpp): %d\n", __func__, depth); /* > 8bpp not implemented yet */ if (depth > 8) { DBG(1, " not supported"); return SANE_STATUS_GOOD; } if (depth > dev->max_depth) dev->max_depth = depth; /* first element is the list size */ dev->depth_list[0]++; dev->depth_list = realloc(dev->depth_list, (dev->depth_list[0] + 1) * sizeof(SANE_Word)); if (dev->depth_list == NULL) return SANE_STATUS_NO_MEM; dev->depth_list[dev->depth_list[0]] = depth; return SANE_STATUS_GOOD; } SANE_Status eds_init_parameters(epsonds_scanner *s) { int dpi, bytes_per_pixel; memset(&s->params, 0, sizeof(SANE_Parameters)); s->dummy = 0; /* setup depth according to our mode table */ if (mode_params[s->val[OPT_MODE].w].depth == 1) s->params.depth = 1; else s->params.depth = s->val[OPT_DEPTH].w; dpi = s->val[OPT_RESOLUTION].w; if (SANE_UNFIX(s->val[OPT_BR_Y].w) == 0 || SANE_UNFIX(s->val[OPT_BR_X].w) == 0) return SANE_STATUS_INVAL; s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) * s->val[OPT_RESOLUTION].w) + 0.5; s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) * s->val[OPT_RESOLUTION].w) + 0.5; s->params.pixels_per_line = ((SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) / MM_PER_INCH) * dpi) + 0.5; s->params.lines = ((SANE_UNFIX(s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) / MM_PER_INCH) * dpi) + 0.5; DBG(5, "%s: tlx %f tly %f brx %f bry %f [mm]\n", __func__, SANE_UNFIX(s->val[OPT_TL_X].w), SANE_UNFIX(s->val[OPT_TL_Y].w), SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w)); DBG(5, "%s: tlx %d tly %d brx %d bry %d [dots @ %d dpi]\n", __func__, s->left, s->top, s->params.pixels_per_line, s->params.lines, dpi); /* center aligned? */ if (s->hw->alignment == 1) { SANE_Int offset = ((SANE_UNFIX(s->hw->x_range->max) / MM_PER_INCH) * dpi) + 0.5; s->left += ((offset - s->params.pixels_per_line) / 2); DBG(5, "%s: centered to tlx %d tly %d brx %d bry %d [dots @ %d dpi]\n", __func__, s->left, s->top, s->params.pixels_per_line, s->params.lines, dpi); } /* * Calculate bytes_per_pixel and bytes_per_line for * any color depths. * * The default color depth is stored in mode_params.depth: */ /* this works because it can only be set to 1, 8 or 16 */ bytes_per_pixel = s->params.depth / 8; if (s->params.depth % 8) { /* just in case ... */ bytes_per_pixel++; } /* pixels_per_line is rounded to the next 8bit boundary */ s->params.pixels_per_line = s->params.pixels_per_line & ~7; s->params.last_frame = SANE_TRUE; switch (s->val[OPT_MODE].w) { case MODE_BINARY: case MODE_GRAY: s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8; break; case MODE_COLOR: s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line * bytes_per_pixel; break; } if (s->params.bytes_per_line == 0) { DBG(1, "bytes_per_line is ZERO\n"); return SANE_STATUS_INVAL; } /* * If (s->top + s->params.lines) is larger than the max scan area, reset * the number of scan lines: * XXX: precalculate the maximum scanning area elsewhere (use dev max_y) */ if (SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH * dpi < (s->params.lines + s->top)) { s->params.lines = ((int) SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH * dpi + 0.5) - s->top; } if (s->params.lines <= 0) { DBG(1, "wrong number of lines: %d\n", s->params.lines); return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } void eds_copy_image_from_ring(epsonds_scanner *s, SANE_Byte *data, SANE_Int max_length, SANE_Int *length) { int lines, available; int hw_line_size = (s->params.bytes_per_line + s->dummy); /* trim max_length to a multiple of hw_line_size */ max_length -= (max_length % hw_line_size); /* check available data */ available = eds_ring_avail(s->current); if (max_length > available) max_length = available; lines = max_length / hw_line_size; DBG(18, "copying %d lines (%d, %d)\n", lines, s->params.bytes_per_line, s->dummy); /* need more data? */ if (lines == 0) { *length = 0; return; } *length = (lines * s->params.bytes_per_line); /* we need to copy one line at time, skipping * dummy bytes at the end of each line */ /* lineart */ if (s->params.depth == 1) { while (lines--) { int i; SANE_Byte *p; eds_ring_read(s->current, s->line_buffer, s->params.bytes_per_line); eds_ring_skip(s->current, s->dummy); p = s->line_buffer; for (i = 0; i < s->params.bytes_per_line; i++) { *data++ = ~*p++; } } } else { /* gray and color */ while (lines--) { eds_ring_read(s->current, data, s->params.bytes_per_line); eds_ring_skip(s->current, s->dummy); data += s->params.bytes_per_line; } } } SANE_Status eds_ring_init(ring_buffer *ring, SANE_Int size) { ring->ring = realloc(ring->ring, size); if (!ring->ring) { return SANE_STATUS_NO_MEM; } ring->size = size; ring->fill = 0; ring->end = ring->ring + size; ring->wp = ring->rp = ring->ring; return SANE_STATUS_GOOD; } SANE_Status eds_ring_write(ring_buffer *ring, SANE_Byte *buf, SANE_Int size) { SANE_Int tail; if (size > (ring->size - ring->fill)) { DBG(1, "ring buffer full, requested: %d, available: %d\n", size, ring->size - ring->fill); return SANE_STATUS_NO_MEM; } tail = ring->end - ring->wp; if (size < tail) { memcpy(ring->wp, buf, size); ring->wp += size; ring->fill += size; } else { memcpy(ring->wp, buf, tail); size -= tail; ring->wp = ring->ring; memcpy(ring->wp, buf + tail, size); ring->wp += size; ring->fill += (tail + size); } return SANE_STATUS_GOOD; } SANE_Int eds_ring_read(ring_buffer *ring, SANE_Byte *buf, SANE_Int size) { SANE_Int tail; DBG(18, "reading from ring, %d bytes available\n", (int)ring->fill); /* limit read to available */ if (size > ring->fill) { DBG(1, "not enough data in the ring, shouldn't happen\n"); size = ring->fill; } tail = ring->end - ring->rp; if (size < tail) { memcpy(buf, ring->rp, size); ring->rp += size; ring->fill -= size; return size; } else { memcpy(buf, ring->rp, tail); size -= tail; ring->rp = ring->ring; memcpy(buf + tail, ring->rp, size); ring->rp += size; ring->fill -= (size + tail); return size + tail; } } SANE_Int eds_ring_skip(ring_buffer *ring, SANE_Int size) { SANE_Int tail; /* limit skip to available */ if (size > ring->fill) size = ring->fill; tail = ring->end - ring->rp; if (size < tail) { ring->rp += size; } else { ring->rp = ring->ring + (size - tail); } ring->fill -= size; return size; } SANE_Int eds_ring_avail(ring_buffer *ring) { return ring->fill; } void eds_ring_flush(ring_buffer *ring) { eds_ring_skip(ring, ring->fill); } sane-backends-1.0.27/backend/ricoh-scsi.c0000664000175000017500000002634412112021330015012 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998 F.W. Dillema (dillema@acm.org) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ This file implements the low-level scsi-commands. */ /* SCSI commands that the Ricoh scanners understand: */ #define RICOH_SCSI_TEST_UNIT_READY 0x00 #define RICOH_SCSI_SET_WINDOW 0x24 #define RICOH_SCSI_GET_WINDOW 0x25 #define RICOH_SCSI_READ_SCANNED_DATA 0x28 #define RICOH_SCSI_INQUIRY 0x12 #define RICOH_SCSI_MODE_SELECT 0x15 #define RICOH_SCSI_START_SCAN 0x1b #define RICOH_SCSI_MODE_SENSE 0x1a #define RICOH_SCSI_GET_BUFFER_STATUS 0x34 #define RICOH_SCSI_OBJECT_POSITION 0x31 /* How long do we wait for scanner to have data for us */ #define MAX_WAITING_TIME 15 struct scsi_window_cmd { SANE_Byte opcode; SANE_Byte byte2; SANE_Byte reserved[4]; SANE_Byte len[3]; SANE_Byte control; }; struct scsi_mode_select_cmd { SANE_Byte opcode; SANE_Byte byte2; #define SMS_SP 0x01 #define SMS_PF 0x10 SANE_Byte page_code; /* for mode_sense, reserved for mode_select */ SANE_Byte unused[1]; SANE_Byte len; SANE_Byte control; }; struct scsi_mode_header { SANE_Byte data_length; /* Sense data length */ SANE_Byte medium_type; SANE_Byte dev_spec; SANE_Byte blk_desc_len; }; struct scsi_get_buffer_status_cmd { SANE_Byte opcode; SANE_Byte byte2; SANE_Byte res[5]; SANE_Byte len[2]; SANE_Byte control; }; struct scsi_status_desc { SANE_Byte window_id; SANE_Byte byte2; SANE_Byte available[3]; SANE_Byte filled[3]; }; struct scsi_status_data { SANE_Byte len[3]; SANE_Byte byte4; struct scsi_status_desc desc; }; struct scsi_start_scan_cmd { SANE_Byte opcode; SANE_Byte byte2; SANE_Byte unused[2]; SANE_Byte len; SANE_Byte control; }; struct scsi_read_scanner_cmd { SANE_Byte opcode; SANE_Byte byte2; SANE_Byte data_type; SANE_Byte byte3; SANE_Byte data_type_qualifier[2]; SANE_Byte len[3]; SANE_Byte control; }; static SANE_Status test_unit_ready (int fd) { static SANE_Byte cmd[6]; SANE_Status status; DBG (11, ">> test_unit_ready\n"); cmd[0] = RICOH_SCSI_TEST_UNIT_READY; memset (cmd, 0, sizeof (cmd)); status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, "<< test_unit_ready\n"); return (status); } static SANE_Status inquiry (int fd, void *buf, size_t * buf_size) { static SANE_Byte cmd[6]; SANE_Status status; DBG (11, ">> inquiry\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = RICOH_SCSI_INQUIRY; cmd[4] = *buf_size; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); DBG (11, "<< inquiry\n"); return (status); } static SANE_Status mode_select (int fd, struct mode_pages *mp) { static struct { struct scsi_mode_select_cmd cmd; struct scsi_mode_header smh; struct mode_pages mp; } select_cmd; SANE_Status status; DBG (11, ">> mode_select\n"); memset (&select_cmd, 0, sizeof (select_cmd)); select_cmd.cmd.opcode = RICOH_SCSI_MODE_SELECT; select_cmd.cmd.byte2 |= SMS_PF; select_cmd.cmd.len = sizeof(select_cmd.smh) + sizeof(select_cmd.mp); memcpy (&select_cmd.mp, mp, sizeof(*mp)); status = sanei_scsi_cmd (fd, &select_cmd, sizeof (select_cmd), 0, 0); DBG (11, "<< mode_select\n"); return (status); } #if 0 static SANE_Status mode_sense (int fd, struct mode_pages *mp, SANE_Byte page_code) { static struct scsi_mode_select_cmd cmd; /* no type, we can reuse it for sensing */ static struct { struct scsi_mode_header smh; struct mode_pages mp; } select_data; static size_t select_size = sizeof(select_data); SANE_Status status; DBG (11, ">> mode_sense\n"); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = RICOH_SCSI_MODE_SENSE; cmd.page_code = page_code; cmd.len = sizeof(select_data); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &select_data, &select_size); memcpy (mp, &select_data.mp, sizeof(*mp)); DBG (11, "<< mode_sense\n"); return (status); } #endif static SANE_Status trigger_scan (int fd) { static struct scsi_start_scan_cmd cmd; static char window_id_list[1] = { '\0' }; /* scan start data out */ static size_t wl_size = 1; SANE_Status status; DBG (11, ">> trigger scan\n"); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = RICOH_SCSI_START_SCAN; cmd.len = wl_size; if (wl_size) status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &window_id_list, &wl_size); else status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), 0, 0); DBG (11, "<< trigger scan\n"); return (status); } static SANE_Status set_window (int fd, struct ricoh_window_data *rwd) { static struct { struct scsi_window_cmd cmd; struct ricoh_window_data rwd; } win; SANE_Status status; DBG (11, ">> set_window\n"); memset (&win, 0, sizeof (win)); win.cmd.opcode = RICOH_SCSI_SET_WINDOW; _lto3b(sizeof(*rwd), win.cmd.len); memcpy (&win.rwd, rwd, sizeof(*rwd)); status = sanei_scsi_cmd (fd, &win, sizeof (win), 0, 0); DBG (11, "<< set_window\n"); return (status); } static SANE_Status get_window (int fd, struct ricoh_window_data *rwd) { static struct scsi_window_cmd cmd; static size_t rwd_size; SANE_Status status; rwd_size = sizeof(*rwd); DBG (11, ">> get_window datalen = %lu\n", (unsigned long) rwd_size); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = RICOH_SCSI_GET_WINDOW; #if 0 cmd.byte2 |= (SANE_Byte)0x01; /* set Single bit to get one window desc. */ #endif _lto3b(rwd_size, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), rwd, &rwd_size); DBG (11, "<< get_window, datalen = %lu\n", (unsigned long) rwd_size); return (status); } static SANE_Status read_data (int fd, void *buf, size_t * buf_size) { static struct scsi_read_scanner_cmd cmd; SANE_Status status; DBG (11, ">> read_data %lu\n", (unsigned long) *buf_size); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = RICOH_SCSI_READ_SCANNED_DATA; _lto3b(*buf_size, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), buf, buf_size); DBG (11, "<< read_data %lu\n", (unsigned long) *buf_size); return (status); } static SANE_Status object_position (int fd) { static SANE_Byte cmd[10]; SANE_Status status; DBG (11, ">> object_position\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = RICOH_SCSI_OBJECT_POSITION; status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), 0, 0); DBG (11, "<< object_position\n"); return (status); } static SANE_Status get_data_status (int fd, struct scsi_status_desc *dbs) { static struct scsi_get_buffer_status_cmd cmd; static struct scsi_status_data ssd; size_t ssd_size = sizeof(ssd); SANE_Status status; DBG (11, ">> get_data_status %lu\n", (unsigned long) ssd_size); memset (&cmd, 0, sizeof (cmd)); cmd.opcode = RICOH_SCSI_GET_BUFFER_STATUS; _lto2b(ssd_size, cmd.len); status = sanei_scsi_cmd (fd, &cmd, sizeof (cmd), &ssd, &ssd_size); memcpy (dbs, &ssd.desc, sizeof(*dbs)); if (status == SANE_STATUS_GOOD && (((unsigned int) _3btol(ssd.len)) <= sizeof(*dbs) || _3btol(ssd.desc.filled) == 0)) { DBG (11, "get_data_status: busy\n"); status = SANE_STATUS_DEVICE_BUSY; } DBG (11, "<< get_data_status %lu\n", (unsigned long) ssd_size); return (status); } #if 0 static SANE_Status ricoh_wait_ready_tur (int fd) { struct timeval now, start; SANE_Status status; gettimeofday (&start, 0); while (1) { DBG(3, "scsi_wait_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (fd, test_unit_ready, sizeof (test_unit_ready), 0, 0); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG(1, "scsi_wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG(1, "ricoh_wait_ready: timed out after %lu seconds\n", (u_long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; } } return SANE_STATUS_INVAL; } #endif static SANE_Status ricoh_wait_ready (Ricoh_Scanner * s) { struct scsi_status_desc dbs; time_t now, start; SANE_Status status; start = time(NULL); while (1) { status = get_data_status (s->fd, &dbs); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG(1, "scsi_wait_ready: get datat status failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: now = time(NULL); if (now - start >= MAX_WAITING_TIME) { DBG(1, "ricoh_wait_ready: timed out after %lu seconds\n", (u_long) (now - start)); return SANE_STATUS_INVAL; } break; case SANE_STATUS_GOOD: DBG(11, "ricoh_wait_ready: %d bytes ready\n", _3btol(dbs.filled)); return status; break; } usleep (1000000); /* retry after 100ms */ } return SANE_STATUS_INVAL; } sane-backends-1.0.27/backend/umax_pp.conf.in0000664000175000017500000000322412112021330015520 00000000000000# For documentation see sane-umax_pp(5) # GLOBAL # # size (in bytes) of scan buffer (default: 2 megabyte) option buffer 2097152 # the following options are local to this scanner # gain for red channel, if not given, will be automatically computed # must be between 0 and 15 #option red-gain 8 # gain for green channel, if not given, will be automatically computed # must be between 0 and 15 #option green-gain 4 # gain for blue channel, if not given, will be automatically computed # must be between 0 and 15 #option blue-gain 8 # offset for red channel, if not given, will default to 0 # must be between 0 and 15 #option red-offset 2 # offset for green channel, if not given, will default to 0 # must be between 0 and 15 #option green-offset 1 # offset for blue channel, if not given, will default to 0 # must be between 0 and 15 #option blue-offset 1 # # # model number # # valid values are 610, 1220, 1600 and 2000 # # by default, no model, we rely on autodetection # in case you have black or 'inverted' scans, # you may override detection by providing the # model number #option astra 1220 # DEVICES # # specify the port your scanner is connected to. # # the value 'auto' will make the backend find the correct value # by itself, it will scan ppdev, ppi device, then hardware address # 'safe-auto' will do the same but won't do direct hardware access # on linux systems, you may provide the device name of the ppdev character # device : /dev/parport0, /dev/parport1, ...... # # on *BSD, you may provide the device name of the ppi device: /dev/ppi0, # /dev/ppi1, ... # # Possible hardware addresses are 0x378 (lp0) # 0x278 (lp2) and 0x3c8 (lp1) # port safe-auto sane-backends-1.0.27/backend/genesys_gl843.c0000664000175000017500000035373212775312261015376 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2010-2013 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #undef BACKEND_NAME #define BACKEND_NAME genesys_gl843 #include "genesys_gl843.h" /**************************************************************************** Low level function ****************************************************************************/ /* ------------------------------------------------------------------------ */ /* Read and write RAM, registers and AFE */ /* ------------------------------------------------------------------------ */ /** * Write bulk data (e.g. gamma or shading data) */ static SANE_Status gl843_bulk_write_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size; uint8_t outdata[8]; DBGSTART; DBG (DBG_io, "gl843_bulk_write_data writing %lu bytes\n", (u_long) len); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX, 1, &addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_bulk_write_data failed while setting register: %s\n", sane_strstatus (status)); return status; } while (len) { if(len>65472) size=65472; else size = len; outdata[0] = BULK_OUT; outdata[1] = BULK_RAM; outdata[2] = 0x00; outdata[3] = 0x00; outdata[4] = (size & 0xff); outdata[5] = ((size >> 8) & 0xff); outdata[6] = ((size >> 16) & 0xff); outdata[7] = ((size >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_bulk_write_data failed while writing command: %s\n", sane_strstatus (status)); return status; } status = sanei_usb_write_bulk (dev->dn, data, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_bulk_write_data failed while writing bulk data: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io2, "gl843_bulk_write_data: wrote %lu bytes, %lu remaining\n", (u_long) size, (u_long) (len - size)); len -= size; data += size; } DBGCOMPLETED; return status; } /* Set address for writing data */ static SANE_Status gl843_set_buffer_address (Genesys_Device * dev, uint32_t addr) { SANE_Status status; DBG (DBG_io, "gl843_set_buffer_address: setting address to 0x%05x\n", addr & 0xffff); status = sanei_genesys_write_register (dev, 0x5b, ((addr >> 8) & 0xff)); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_set_buffer_address: failed while writing high byte: %s\n", sane_strstatus (status)); return status; } status = sanei_genesys_write_register (dev, 0x5c, (addr & 0xff)); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_set_buffer_address: failed while writing low byte: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io, "gl843_set_buffer_address: completed\n"); return status; } /** * writes a block of data to RAM * @param dev USB device * @param addr RAM address to write to * @param size size of the chunk of data * @param data pointer to the data to write */ static SANE_Status write_data (Genesys_Device * dev, uint32_t addr, uint32_t size, uint8_t * data) { SANE_Status status = SANE_STATUS_GOOD; DBGSTART; status = gl843_set_buffer_address (dev, addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "write_data: failed while setting address for bulk write data: %s\n", sane_strstatus (status)); return status; } /* write actual data */ status = gl843_bulk_write_data (dev, 0x28, data, size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "write_data: failed while writing bulk write data: %s\n", sane_strstatus (status)); return status; } /* set back address to 0 */ status = gl843_set_buffer_address (dev, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "write_data: failed setting to default RAM address: %s\n", sane_strstatus (status)); return status; } DBGCOMPLETED; return status; } static SANE_Status gl843_bulk_read_data (Genesys_Device * dev, uint8_t addr, uint8_t * data, size_t len) { SANE_Status status; size_t size; uint8_t outdata[8]; DBGSTART; DBG (DBG_io, "gl843_bulk_read_data: requesting %lu bytes from 0x%02x addr\n", (u_long) len, addr); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, 0, 1, &addr); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "write_data: failed to set register address %s\n", sane_strstatus (status)); return status; } if (len == 0) return SANE_STATUS_GOOD; outdata[0] = BULK_IN; outdata[1] = BULK_RAM; outdata[2] = VALUE_BUFFER; outdata[3] = 0; outdata[4] = (len & 0xff); outdata[5] = ((len >> 8) & 0xff); outdata[6] = ((len >> 16) & 0xff); outdata[7] = ((len >> 24) & 0xff); status = sanei_usb_control_msg (dev->dn, REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX, sizeof (outdata), outdata); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_bulk_read_data failed while writing command: %s\n", sane_strstatus (status)); return status; } while (len) { if (len > 0xF000) size = 0xF000; else size = len; if (size >= 512) { size /= 512; size *= 512; } DBG (DBG_io2, "gl843_bulk_read_data: trying to read %lu bytes of data\n", (u_long) size); status = sanei_usb_read_bulk (dev->dn, data, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_bulk_read_data failed while reading bulk data: %s\n", sane_strstatus (status)); return status; } DBG (DBG_io2, "gl843_bulk_read_data read %lu bytes, %lu remaining\n", (u_long) size, (u_long) (len - size)); len -= size; data += size; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /**************************************************************************** Mid level functions ****************************************************************************/ static SANE_Bool gl843_get_fast_feed_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG02); if (r && (r->value & REG02_FASTFED)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl843_get_filter_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_FILTER)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl843_get_lineart_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_LINEART)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl843_get_bitset_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG04); if (r && (r->value & REG04_BITSET)) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl843_get_gain4_bit (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; r = sanei_genesys_get_address (regs, REG06); if (r && (r->value & REG06_GAIN4)) return SANE_TRUE; return SANE_FALSE; } /** * compute the step multiplier used */ static int gl843_get_step_multiplier (Genesys_Register_Set * regs) { Genesys_Register_Set *r = NULL; int value = 1; r = sanei_genesys_get_address (regs, REG9D); if (r != NULL) { switch (r->value & 0x0c) { case 0x04: value = 2; break; case 0x08: value = 4; break; default: value = 1; } } DBG (DBG_io, "%s: step multiplier is %d\n", __func__, value); return value; } static SANE_Bool gl843_test_buffer_empty_bit (SANE_Byte val) { if (val & REG41_BUFEMPTY) return SANE_TRUE; return SANE_FALSE; } static SANE_Bool gl843_test_motor_flag_bit (SANE_Byte val) { if (val & REG41_MOTORENB) return SANE_TRUE; return SANE_FALSE; } /** @brief sensor profile * search for the database of motor profiles and get the best one. Each * profile is at a specific dpihw. Use first entry of table by default. * @param sensor_type sensor id * @param dpi hardware dpi for the scan * @param flags to select between XPA, XPA+IR or regular scan from OPTICAL_FLAGS_* * @return a pointer to a Sensor_Profile struct */ static Sensor_Profile *get_sensor_profile(int sensor_type, int dpi, int flags) { unsigned int i, count; int idx; Sensor_Profile *sp; if(flags & OPTICAL_FLAG_USE_XPA) { sp=xpa_sensors; count=sizeof(xpa_sensors)/sizeof(Sensor_Profile); } else { sp=sensors; count=sizeof(sensors)/sizeof(Sensor_Profile); } i=0; idx=-1; while(i=dpi && sp[i].dpimodel->ccd_type, dpihw, flags); for (i = 0x06; i < 0x0e; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); if (r) r->value = sensor->regs_0x10_0x1d[i]; } for (i = 0; i < 9; i++) { r = sanei_genesys_get_address (regs, 0x52 + i); if (r) r->value = sensor->regs_0x52_0x5e[i]; } /* specific registers */ r = sanei_genesys_get_address (regs, 0x0c); if (r) { r->value = sensor->reg0c; } r = sanei_genesys_get_address (regs, 0x70); if (r) { r->value = sensor->reg70; } r = sanei_genesys_get_address (regs, 0x71); if (r) { r->value = sensor->reg71; } r = sanei_genesys_get_address (regs, 0x7d); if (r) { if (!(dev->model->flags & GENESYS_FLAG_FULL_HWDPI_MODE)) { r->value = 0x90; } } r = sanei_genesys_get_address (regs, 0x9e); if (r) { r->value = sensor->reg9e; } /* undocumented register */ r = sanei_genesys_get_address (regs, 0xaa); if (r) { r->value = sensor->regaa; } /* CKxMAP */ sanei_genesys_set_triple(regs,REG_CK1MAP,sensor->ck1map); sanei_genesys_set_triple(regs,REG_CK3MAP,sensor->ck3map); sanei_genesys_set_triple(regs,REG_CK4MAP,sensor->ck4map); DBGCOMPLETED; } /* returns the max register bulk size */ static int gl843_bulk_full_size (void) { return GENESYS_GL843_MAX_REGS; } /** @brief set all registers to default values . * This function is called only once at the beginning and * fills register startup values for registers reused across scans. * Those that are rarely modified or not modified are written * individually. * @param dev device structure holding register set to initialize */ static void gl843_init_registers (Genesys_Device * dev) { DBGSTART; memset (dev->reg, 0, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); /* default to KV-SS080 */ SETREG (0xa2, 0x0f); SETREG (0x01, 0x00); SETREG (0x02, 0x78); SETREG (0x03, 0x1f); SETREG (0x04, 0x10); SETREG (0x05, 0x80); SETREG (0x06, 0xd8); /* SCANMOD=110, PWRBIT and GAIN4 */ SETREG (0x08, 0x00); SETREG (0x09, 0x00); SETREG (0x0a, 0x00); SETREG (0x0b, 0x6a); SETREG (0x10, 0x00); SETREG (0x11, 0x00); SETREG (0x12, 0x00); SETREG (0x13, 0x00); SETREG (0x14, 0x00); SETREG (0x15, 0x00); SETREG (0x16, 0x33); SETREG (0x17, 0x1c); SETREG (0x18, 0x10); SETREG (0x19, 0x2a); SETREG (0x1a, 0x04); SETREG (0x1b, 0x00); SETREG (0x1c, 0x20); SETREG (0x1d, 0x04); SETREG (0x1e, 0x10); SETREG (0x1f, 0x01); SETREG (0x20, 0x10); SETREG (0x21, 0x04); SETREG (0x22, 0x01); SETREG (0x23, 0x01); SETREG (0x24, 0x04); SETREG (0x25, 0x00); SETREG (0x26, 0x00); SETREG (0x27, 0x00); SETREG (0x2c, 0x02); SETREG (0x2d, 0x58); SETREG (0x2e, 0x80); SETREG (0x2f, 0x80); SETREG (0x30, 0x00); SETREG (0x31, 0x14); SETREG (0x32, 0x27); SETREG (0x33, 0xec); SETREG (0x34, 0x24); SETREG (0x35, 0x00); SETREG (0x36, 0xff); SETREG (0x37, 0xff); SETREG (0x38, 0x55); SETREG (0x39, 0xf0); SETREG (0x3d, 0x00); SETREG (0x3e, 0x00); SETREG (0x3f, 0x01); SETREG (0x52, 0x01); SETREG (0x53, 0x04); SETREG (0x54, 0x07); SETREG (0x55, 0x0a); SETREG (0x56, 0x0d); SETREG (0x57, 0x10); SETREG (0x58, 0x1b); SETREG (0x59, 0x00); SETREG (0x5a, 0x40); SETREG (0x5e, 0x23); SETREG (0x5f, 0x01); SETREG (0x60, 0x00); SETREG (0x61, 0x00); SETREG (0x62, 0x00); SETREG (0x63, 0x00); SETREG (0x64, 0x00); SETREG (0x65, 0x00); SETREG (0x67, 0x7f); SETREG (0x68, 0x7f); SETREG (0x69, 0x01); SETREG (0x6a, 0x04); SETREG (0x6b, 0x30); SETREG (0x70, 0x01); SETREG (0x71, 0x03); SETREG (0x72, 0x04); SETREG (0x73, 0x05); /* CKxMAP */ SETREG (0x74, 0x00); SETREG (0x75, 0x00); SETREG (0x76, 0x3c); SETREG (0x77, 0x00); SETREG (0x78, 0x00); SETREG (0x79, 0x9f); SETREG (0x7a, 0x00); SETREG (0x7b, 0x00); SETREG (0x7c, 0x55); SETREG (0x7d, 0x00); SETREG (0x7f, 0x00); SETREG (0x80, 0x00); if (strcmp (dev->model->name, "canon-canoscan-4400f") != 0) { SETREG (0x81, 0x00); SETREG (0x82, 0x00); SETREG (0x83, 0x00); SETREG (0x84, 0x00); SETREG (0x85, 0x00); SETREG (0x86, 0x00); } SETREG (0x87, 0x00); SETREG (0x9d, 0x04); SETREG (0x9e, 0x00); if (strcmp (dev->model->name, "canon-canoscan-8400f") != 0) { SETREG (0x0c, 0x00); SETREG (0x94, 0xff); SETREG (0xab, 0x50); } /* so many time burnt for this register ....*/ if (strcmp (dev->model->name, "canon-canoscan-4400f") != 0 &&strcmp (dev->model->name, "canon-canoscan-8400f") != 0) { SETREG (0xaa, 0x00); } /* G4050 values */ if ((strcmp (dev->model->name, "hewlett-packard-scanjet-g4050") == 0) || (strcmp (dev->model->name, "hewlett-packard-scanjet-4850c") == 0) || (strcmp (dev->model->name, "hewlett-packard-scanjet-g4010") == 0)) { SETREG (0x03, 0x1d); SETREG (0x05, 0x08); SETREG (0x06, 0xd0); /* SCANMOD=110, PWRBIT and no GAIN4 */ SETREG (0x06, 0xd8); /* SCANMOD=110, PWRBIT and GAIN4 */ SETREG (0x0a, 0x18); SETREG (0x0b, 0x69); /* CIS exposure is used for XPA lamp movement */ SETREG (0x10, 0x2c); SETREG (0x11, 0x09); SETREG (0x12, 0x22); SETREG (0x13, 0xb8); SETREG (0x14, 0x10); SETREG (0x15, 0xf0); SETREG (0x6b, 0xf4); SETREG (0x70, 0x00); SETREG (0x71, 0x02); SETREG (0x72, 0x00); SETREG (0x73, 0x00); SETREG (0x80, 0x50); SETREG (0x9d, 0x08); SETREG (0xab, 0x40); /* XXX STEF XXX TODO move to set for scan */ SETREG (0x98, 0x03); SETREG (0x99, 0x30); SETREG (0x9a, 0x01); SETREG (0x9b, 0x80); SETREG (0xac, 0x00); } if (strcmp (dev->model->name, "canon-canoscan-4400f") == 0) { SETREG (0x06, 0xf0); /* SCANMOD=111, PWRBIT and no GAIN4 */ SETREG (0x0b, 0x69); /* 16M only */ SETREG (0x1e, 0x20); SETREG (0x22, 0xc8); SETREG (0x23, 0xc8); SETREG (0x5e, 0x3f); SETREG (0x5f, 0xf0); SETREG (0x6b, 0x72); SETREG (0x72, 0x01); SETREG (0x73, 0x03); SETREG (0x80, 0x0c); SETREG (0x87, 0x02); /* MCLOCK -> CK4MAP */ SETREG (0x9d, 0x08); /* STEPTIM=2 */ SETREG (0xa2, 0x1f); SETREG (0xab, 0x00); sanei_genesys_set_double(dev->reg,REG_EXPR,0x9c40); sanei_genesys_set_double(dev->reg,REG_EXPG,0x9c40); sanei_genesys_set_double(dev->reg,REG_EXPB,0x9c40); } if (strcmp (dev->model->name, "canon-canoscan-8400f") == 0) { SETREG (0x03, 0x1c); SETREG (0x06, 0xd0); /* SCANMOD=110, PWRBIT and no GAIN4 */ SETREG (0x0a, 0x10); SETREG (0x22, 0x50); SETREG (0x23, 0x50); SETREG (0x5e, 0x85); SETREG (0x6b, 0xb1); SETREG (0x1e, 0xa0); SETREG (0x72, 0x03); SETREG (0x73, 0x04); SETREG (0x7d, 0x20); SETREG (0x80, 0x28); SETREG (0x87, 0x02); /* MCLOCK -> CK4MAP */ SETREG (0x9d, 0x08); /* STEPTIM=2 */ } /* fine tune upon device description */ dev->reg[reg_0x05].value &= ~REG05_DPIHW; switch (dev->sensor.optical_res) { case 600: dev->reg[reg_0x05].value |= REG05_DPIHW_600; break; case 1200: dev->reg[reg_0x05].value |= REG05_DPIHW_1200; break; case 2400: dev->reg[reg_0x05].value |= REG05_DPIHW_2400; break; case 4800: dev->reg[reg_0x05].value |= REG05_DPIHW_4800; break; } /* initalize calibration reg */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); DBGCOMPLETED; } /* Send slope table for motor movement slope_table in machine byte order */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_send_slope_table (Genesys_Device * dev, int table_nr, uint16_t * slope_table, int steps) { SANE_Status status; uint8_t *table; int i; char msg[10000]; DBG (DBG_proc, "%s (table_nr = %d, steps = %d)\n", __func__, table_nr, steps); table = (uint8_t *) malloc (steps * 2); for (i = 0; i < steps; i++) { table[i * 2] = slope_table[i] & 0xff; table[i * 2 + 1] = slope_table[i] >> 8; } if (DBG_LEVEL >= DBG_io) { sprintf (msg, "write slope %d (%d)=", table_nr, steps); for (i = 0; i < steps; i++) { sprintf (msg+strlen(msg), "%d", slope_table[i]); } DBG (DBG_io, "%s: %s\n", __func__, msg); } /* slope table addresses are fixed : 0x4000, 0x4800, 0x5000, 0x5800, 0x6000 */ /* XXX STEF XXX USB 1.1 ? sanei_genesys_write_0x8c (dev, 0x0f, 0x14); */ status = write_data (dev, 0x4000 + 0x800 * table_nr, steps * 2, table); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: write data failed writing slope table %d (%s)\n", __func__, table_nr, sane_strstatus (status)); } free (table); DBGCOMPLETED; return status; } /* Set values of analog frontend */ static SANE_Status gl843_set_fe (Genesys_Device * dev, uint8_t set) { SANE_Status status; uint8_t val; int i; DBG (DBG_proc, "gl843_set_fe (%s)\n", set == AFE_INIT ? "init" : set == AFE_SET ? "set" : set == AFE_POWER_SAVE ? "powersave" : "huh?"); if (set == AFE_INIT) { DBG (DBG_proc, "gl843_set_fe(): setting DAC %u\n", dev->model->dac_type); sanei_genesys_init_fe (dev); } /* check analog frontend type */ RIE (sanei_genesys_read_register (dev, REG04, &val)); if ((val & REG04_FESET) != 0x00) { /* for now there is no support for AD fe */ DBG (DBG_proc, "gl843_set_fe(): unsupported frontend type %d\n", dev->reg[reg_0x04].value & REG04_FESET); return SANE_STATUS_UNSUPPORTED; } DBG (DBG_proc, "gl843_set_fe(): frontend reset complete\n"); for (i = 1; i <= 3; i++) { status = sanei_genesys_fe_write_data (dev, i, dev->frontend.reg[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_set_fe: writing reg[%d] failed: %s\n", i, sane_strstatus (status)); return status; } } for (i = 0; i < 3; i++) { status = sanei_genesys_fe_write_data (dev, 0x20 + i, dev->frontend.offset[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_set_fe: writing offset[%d] failed: %s\n", i, sane_strstatus (status)); return status; } } if (dev->model->ccd_type == CCD_KVSS080) { for (i = 0; i < 3; i++) { status = sanei_genesys_fe_write_data (dev, 0x24 + i, dev->frontend.sign[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_set_fe: writing sign[%d] failed: %s\n", i, sane_strstatus (status)); return status; } } } for (i = 0; i < 3; i++) { status = sanei_genesys_fe_write_data (dev, 0x28 + i, dev->frontend.gain[i]); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_set_fe: writing gain[%d] failed: %s\n", i, sane_strstatus (status)); return status; } } DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl843_init_motor_regs_scan (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int exposure, float scan_yres, int scan_step_type, unsigned int scan_lines, unsigned int scan_dummy, unsigned int feed_steps, int scan_power_mode, unsigned int flags) { SANE_Status status; int use_fast_fed, coeff; unsigned int lincnt; uint16_t scan_table[1024]; uint16_t fast_table[1024]; int scan_steps,fast_steps, fast_step_type; unsigned int feedl,factor,dist; Genesys_Register_Set *r; uint32_t z1, z2; DBGSTART; DBG (DBG_info, "gl843_init_motor_regs_scan : exposure=%d, " "scan_yres=%g, scan_step_type=%d, scan_lines=%d, scan_dummy=%d, " "feed_steps=%d, scan_power_mode=%d, flags=%x\n", exposure, scan_yres, scan_step_type, scan_lines, scan_dummy, feed_steps, scan_power_mode, flags); /* get step multiplier */ factor = gl843_get_step_multiplier (reg); use_fast_fed = 0; if((scan_yres>=300 && feed_steps>900) || (flags & MOTOR_FLAG_FEED)) use_fast_fed=1; lincnt=scan_lines; sanei_genesys_set_triple(reg,REG_LINCNT,lincnt); DBG (DBG_io, "%s: lincnt=%d\n", __func__, lincnt); /* compute register 02 value */ r = sanei_genesys_get_address (reg, REG02); r->value = 0x00; r->value |= REG02_MTRPWR; if (use_fast_fed) r->value |= REG02_FASTFED; else r->value &= ~REG02_FASTFED; /* in case of automatic go home, move until home sensor */ if (flags & MOTOR_FLAG_AUTO_GO_HOME) r->value |= REG02_AGOHOME | REG02_NOTHOME; /* disable backtracking */ if ((flags & MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE) ||(scan_yres>=2400) ||(scan_yres>=dev->sensor.optical_res)) r->value |= REG02_ACDCDIS; /* scan and backtracking slope table */ sanei_genesys_slope_table(scan_table, &scan_steps, scan_yres, exposure, dev->motor.base_ydpi, scan_step_type, factor, dev->model->motor_type, gl843_motors); RIE(gl843_send_slope_table (dev, SCAN_TABLE, scan_table, scan_steps*factor)); RIE(gl843_send_slope_table (dev, BACKTRACK_TABLE, scan_table, scan_steps*factor)); /* STEPNO */ r = sanei_genesys_get_address (reg, REG_STEPNO); r->value = scan_steps; /* FSHDEC */ r = sanei_genesys_get_address (reg, REG_FSHDEC); r->value = scan_steps; /* fast table */ fast_step_type=0; if(scan_step_type<=fast_step_type) { fast_step_type=scan_step_type; } sanei_genesys_slope_table(fast_table, &fast_steps, sanei_genesys_get_lowest_ydpi(dev), exposure, dev->motor.base_ydpi, fast_step_type, factor, dev->model->motor_type, gl843_motors); RIE(gl843_send_slope_table (dev, STOP_TABLE, fast_table, fast_steps*factor)); RIE(gl843_send_slope_table (dev, FAST_TABLE, fast_table, fast_steps*factor)); RIE(gl843_send_slope_table (dev, HOME_TABLE, fast_table, fast_steps*factor)); /* FASTNO */ r = sanei_genesys_get_address (reg, REG_FASTNO); r->value = fast_steps; /* FMOVNO */ r = sanei_genesys_get_address (reg, REG_FMOVNO); r->value = fast_steps; /* substract acceleration distance from feedl */ feedl=feed_steps; feedl<<=scan_step_type; dist = scan_steps; if (use_fast_fed) { dist += fast_steps*2; } DBG (DBG_io2, "%s: acceleration distance=%d\n", __func__, dist); /* get sure when don't insane value : XXX STEF XXX in this case we should * fall back to single table move */ if(dist600) { z1=0; z2=0; } sanei_genesys_set_triple(reg,REG_Z1MOD,z1); DBG (DBG_info, "gl843_init_motor_regs_scan: z1 = %d\n", z1); sanei_genesys_set_triple(reg,REG_Z2MOD,z2); DBG (DBG_info, "gl843_init_motor_regs_scan: z2 = %d\n", z2); r = sanei_genesys_get_address (reg, REG1E); r->value &= 0xf0; /* 0 dummy lines */ r->value |= scan_dummy; /* dummy lines */ r = sanei_genesys_get_address (reg, REG67); r->value = 0x3f | (scan_step_type << REG67S_STEPSEL); r = sanei_genesys_get_address (reg, REG68); r->value = 0x3f | (scan_step_type << REG68S_FSTPSEL); /* steps for STOP table */ r = sanei_genesys_get_address (reg, REG_FMOVDEC); r->value = fast_steps; /* Vref XXX STEF XXX : optical divider or step type ? */ r = sanei_genesys_get_address (reg, 0x80); if (!(dev->model->flags & GENESYS_FLAG_FULL_HWDPI_MODE)) { r->value = 0x50; coeff=dev->sensor.optical_res/sanei_genesys_compute_dpihw(dev, scan_yres); if (dev->model->motor_type == MOTOR_KVSS080) { if(coeff>=1) { r->value |= 0x05; } } else { switch(coeff) { case 4: r->value |= 0x0a; break; case 2: r->value |= 0x0f; break; case 1: r->value |= 0x0f; break; } } } DBGCOMPLETED; return SANE_STATUS_GOOD; } /**@brief compute exposure to use * compute the sensor exposure based on target resolution */ static int gl843_compute_exposure(Genesys_Device *dev, int xres, int flags) { Sensor_Profile *sensor; sensor=get_sensor_profile(dev->model->ccd_type, xres, flags); return sensor->exposure; } /** @brief setup optical related registers * start and pixels are expressed in optical sensor resolution coordinate * space. * @param dev device to use * @param reg registers to set up * @param exposure exposure time to use * @param used_res scanning resolution used, may differ from * scan's one * @param start logical start pixel coordinate * @param pixels logical number of pixels to use * @param channels number of color channles used (1 or 3) * @param depth bit depth of the scan (1, 8 or 16 bits) * @param half_ccd SANE_TRUE if timings are such that x coordiantes must be halved * @param color_filter to choose the color channel used in gray scans * @param flags to drive specific settings such no calibration, XPA use ... * @return SANE_STATUS_GOOD if OK */ static SANE_Status gl843_init_optical_regs_scan (Genesys_Device * dev, Genesys_Register_Set * reg, unsigned int exposure, int used_res, unsigned int start, unsigned int pixels, int channels, int depth, SANE_Bool half_ccd, int color_filter, int flags) { unsigned int words_per_line; unsigned int startx, endx, used_pixels; unsigned int dpiset, dpihw, factor; unsigned int bytes; unsigned int tgtime; /**> exposure time multiplier */ unsigned int cksel; /**> clock per system pixel time in capturing image */ Genesys_Register_Set *r; SANE_Status status; DBG (DBG_proc, "gl843_init_optical_regs_scan : exposure=%d, " "used_res=%d, start=%d, pixels=%d, channels=%d, depth=%d, " "half_ccd=%d, flags=%x\n", exposure, used_res, start, pixels, channels, depth, half_ccd, flags); /* tgtime */ tgtime=1; if (dev->model->ccd_type == CCD_G4050 && used_res>2400) { tgtime=2; } DBG (DBG_io2, "%s: tgtime=%d\n", __func__, tgtime); /* to manage high resolution device while keeping good * low resolution scanning speed, we make hardware dpi vary */ dpihw=sanei_genesys_compute_dpihw(dev, used_res); factor=dev->sensor.optical_res/dpihw; DBG (DBG_io2, "%s: dpihw=%d (factor=%d)\n", __func__, dpihw, factor); /* sensor parameters */ gl843_setup_sensor (dev, reg, dpihw, flags); /* resolution is divided according to CKSEL which is known once sensor is set up */ r = sanei_genesys_get_address (reg, REG18); cksel= (r->value & REG18_CKSEL)+1; DBG (DBG_io2, "%s: cksel=%d\n", __func__, cksel); dpiset = used_res * cksel; /* start and end coordinate in optical dpi coordinates */ startx = (start + dev->sensor.dummy_pixel * tgtime)/cksel; used_pixels=pixels/cksel; endx = startx + used_pixels; /* pixel coordinate factor correction when used dpihw is not maximal one */ startx/=factor; endx/=factor; used_pixels=endx-startx; /* in case of stagger we have to start at an odd coordinate */ if ((flags & OPTICAL_FLAG_STAGGER) &&((startx & 1)==0)) { startx++; endx++; } status = gl843_set_fe (dev, AFE_SET); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to set frontend: %s\n", __func__, sane_strstatus (status)); return status; } /* enable shading */ r = sanei_genesys_get_address (reg, REG01); r->value &= ~REG01_SCAN; if ((flags & OPTICAL_FLAG_DISABLE_SHADING) || (dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) { r->value &= ~REG01_DVDSET; } else { r->value |= REG01_DVDSET; } if(dpihw>600) { r->value |= REG01_SHDAREA; } else { r->value &= ~REG01_SHDAREA; } r = sanei_genesys_get_address (reg, REG03); r->value &= ~REG03_AVEENB; if (flags & OPTICAL_FLAG_DISABLE_LAMP) r->value &= ~REG03_LAMPPWR; else r->value |= REG03_LAMPPWR; /* select XPA */ r->value &= ~REG03_XPASEL; if (flags & OPTICAL_FLAG_USE_XPA) { r->value |= REG03_XPASEL; } /* BW threshold */ r = sanei_genesys_get_address (reg, REG2E); r->value = dev->settings.threshold; r = sanei_genesys_get_address (reg, REG2F); r->value = dev->settings.threshold; /* monochrome / color scan */ r = sanei_genesys_get_address (reg, REG04); switch (depth) { case 1: r->value &= ~REG04_BITSET; r->value |= REG04_LINEART; break; case 8: r->value &= ~(REG04_LINEART | REG04_BITSET); break; case 16: r->value &= ~REG04_LINEART; r->value |= REG04_BITSET; break; } r->value &= ~(REG04_FILTER | REG04_AFEMOD); if (channels == 1) { switch (color_filter) { case 0: r->value |= 0x14; /* red filter */ break; case 2: r->value |= 0x1c; /* blue filter */ break; default: r->value |= 0x18; /* green filter */ break; } } else r->value |= 0x10; /* mono */ /* register 05 */ r = sanei_genesys_get_address (reg, REG05); /* set up dpihw */ r->value &= ~REG05_DPIHW; switch(dpihw) { case 600: r->value |= REG05_DPIHW_600; break; case 1200: r->value |= REG05_DPIHW_1200; break; case 2400: r->value |= REG05_DPIHW_2400; break; case 4800: r->value |= REG05_DPIHW_4800; break; } /* enable gamma tables */ if (flags & OPTICAL_FLAG_DISABLE_GAMMA) r->value &= ~REG05_GMMENB; else r->value |= REG05_GMMENB; if(half_ccd) { sanei_genesys_set_double(reg,REG_DPISET,dpiset*4); DBG (DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset*4); } else { sanei_genesys_set_double(reg,REG_DPISET,dpiset); DBG (DBG_io2, "%s: dpiset used=%d\n", __func__, dpiset); } sanei_genesys_set_double(reg,REG_STRPIXEL,startx/tgtime); sanei_genesys_set_double(reg,REG_ENDPIXEL,endx/tgtime); /* words(16bit) before gamma, conversion to 8 bit or lineart */ words_per_line = (used_pixels * dpiset) / dpihw; bytes = depth / 8; if (depth == 1) { words_per_line = (words_per_line >> 3) + ((words_per_line & 7) ? 1 : 0); } else { words_per_line *= bytes; } dev->wpl = words_per_line; dev->bpl = words_per_line; DBG (DBG_io2, "%s: used_pixels=%d\n", __func__, used_pixels); DBG (DBG_io2, "%s: pixels =%d\n", __func__, pixels); DBG (DBG_io2, "%s: depth =%d\n", __func__, depth); DBG (DBG_io2, "%s: dev->bpl =%lu\n", __func__, (unsigned long) dev->bpl); DBG (DBG_io2, "%s: dev->len =%lu\n", __func__, (unsigned long)dev->len); DBG (DBG_io2, "%s: dev->dist =%lu\n", __func__, (unsigned long)dev->dist); words_per_line *= channels; /* MAXWD is expressed in 2 words unit */ /* nousedspace = (mem_bank_range * 1024 / 256 -1 ) * 4; */ sanei_genesys_set_triple(reg,REG_MAXWD,(words_per_line)>>1); DBG (DBG_io2, "%s: words_per_line used=%d\n", __func__, words_per_line); sanei_genesys_set_double(reg,REG_LPERIOD,exposure/tgtime); DBG (DBG_io2, "%s: exposure used=%d\n", __func__, exposure/tgtime); r = sanei_genesys_get_address (reg, REG_DUMMY); r->value = dev->sensor.dummy_pixel * tgtime; DBGCOMPLETED; return SANE_STATUS_GOOD; } /* set up registers for an actual scan * * this function sets up the scanner to scan in normal or single line mode */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_init_scan_regs (Genesys_Device * dev, Genesys_Register_Set * reg, float xres, /*dpi */ float yres, /*dpi */ float startx, /*optical_res, from dummy_pixel+1 */ float starty, /*base_ydpi, from home! */ float pixels, float lines, unsigned int depth, unsigned int channels, int scan_mode, int color_filter, unsigned int flags) { int used_res; int start, used_pixels; int bytes_per_line; int move; unsigned int lincnt; /**> line count to scan */ unsigned int oflags, mflags; /**> optical and motor flags */ int exposure; int stagger; int slope_dpi = 0; int dummy = 0; int scan_step_type = 1; int scan_power_mode = 0; int max_shift; size_t requested_buffer_size, read_buffer_size; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; SANE_Status status; DBG (DBG_info, "gl843_init_scan_regs settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g/%g\n" "Depth/Channels: %u/%u\n" "Flags : %x\n\n", xres, yres, lines, pixels, startx, starty, depth, channels, flags); /* we have 2 domains for ccd: xres below or above half ccd max dpi */ if (dev->sensor.optical_res < 4 * xres || !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)) { half_ccd = SANE_FALSE; } else { half_ccd = SANE_TRUE; } /* optical_res */ optical_res = dev->sensor.optical_res; if (half_ccd) optical_res /= 4; /* stagger starting at 2400, and not applied for calibration */ stagger = 0; if ( (yres>1200) && ((flags & SCAN_FLAG_IGNORE_LINE_DISTANCE)==0) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) { stagger = (4 * yres) / dev->motor.base_ydpi; } DBG (DBG_info, "%s : stagger=%d lines\n", __func__, stagger); /* we enable true gray for cis scanners only, and just when doing * scan since color calibration is OK for this mode */ oflags = 0; if (flags & SCAN_FLAG_DISABLE_SHADING) oflags |= OPTICAL_FLAG_DISABLE_SHADING; if (flags & SCAN_FLAG_DISABLE_GAMMA) oflags |= OPTICAL_FLAG_DISABLE_GAMMA; if (flags & SCAN_FLAG_DISABLE_LAMP) oflags |= OPTICAL_FLAG_DISABLE_LAMP; if (flags & SCAN_FLAG_CALIBRATION) oflags |= OPTICAL_FLAG_DISABLE_DOUBLE; if(stagger) oflags |= OPTICAL_FLAG_STAGGER; if (flags & SCAN_FLAG_USE_XPA) oflags |= OPTICAL_FLAG_USE_XPA; /** @brief compute used resolution */ if (flags & SCAN_FLAG_USE_OPTICAL_RES) { used_res = optical_res; } else { /* resolution is choosen from a fixed list and can be used directly * unless we have ydpi higher than sensor's maximum one */ if(xres>optical_res) used_res=optical_res; else used_res = xres; } /* compute scan parameters values */ /* pixels are allways given at full optical resolution */ /* use detected left margin and fixed value */ /* start */ start = startx; /* compute correct pixels number */ used_pixels = (pixels * optical_res) / xres; DBG (DBG_info, "%s: used_pixels=%d\n", __func__, used_pixels); /* round up pixels number if needed */ if (used_pixels * xres < pixels * optical_res) used_pixels++; /* we want even number of pixels here */ if(used_pixels & 1) used_pixels++; dummy = 0; /* dummy = 1; XXX STEF XXX */ /* slope_dpi */ /* cis color scan is effectively a gray scan with 3 gray lines per color line and a FILTER of 0 */ if (dev->model->is_cis) slope_dpi = yres * channels; else slope_dpi = yres; slope_dpi = slope_dpi * (1 + dummy); /* scan_step_type */ if(flags & SCAN_FLAG_FEEDING) { exposure=gl843_compute_exposure (dev, sanei_genesys_get_lowest_ydpi(dev), oflags); scan_step_type=sanei_genesys_compute_step_type (gl843_motors, dev->model->motor_type, exposure); } else { exposure = gl843_compute_exposure (dev, used_res, oflags); scan_step_type = sanei_genesys_compute_step_type(gl843_motors, dev->model->motor_type, exposure); } DBG (DBG_info, "%s : exposure=%d pixels\n", __func__, exposure); DBG (DBG_info, "%s : scan_step_type=%d\n", __func__, scan_step_type); /*** optical parameters ***/ /* in case of dynamic lineart, we use an internal 8 bit gray scan * to generate 1 lineart data */ if ((flags & SCAN_FLAG_DYNAMIC_LINEART) && (scan_mode == SCAN_MODE_LINEART)) { depth = 8; } /* no 16 bit gamma for this ASIC */ if (depth == 16) { flags |= SCAN_FLAG_DISABLE_GAMMA; oflags |= OPTICAL_FLAG_DISABLE_GAMMA; } /* now _LOGICAL_ optical values used are known, setup registers */ status = gl843_init_optical_regs_scan (dev, reg, exposure, used_res, start, used_pixels, channels, depth, half_ccd, color_filter, oflags); if (status != SANE_STATUS_GOOD) return status; /*** motor parameters ***/ /* it seems base_dpi of the G4050 motor is changed above 600 dpi*/ if (dev->model->motor_type == MOTOR_G4050 && yres>600) { dev->ld_shift_r = (dev->model->ld_shift_r*3800)/dev->motor.base_ydpi; dev->ld_shift_g = (dev->model->ld_shift_g*3800)/dev->motor.base_ydpi; dev->ld_shift_b = (dev->model->ld_shift_b*3800)/dev->motor.base_ydpi; } else { dev->ld_shift_r = dev->model->ld_shift_r; dev->ld_shift_g = dev->model->ld_shift_g; dev->ld_shift_b = dev->model->ld_shift_b; } /* max_shift */ /* scanned area must be enlarged by max color shift needed */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,flags); /* lines to scan */ lincnt = lines + max_shift + stagger; /* add tl_y to base movement */ move = starty; DBG (DBG_info, "gl843_init_scan_regs: move=%d steps\n", move); mflags=0; if(flags & SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE) mflags|=MOTOR_FLAG_DISABLE_BUFFER_FULL_MOVE; if(flags & SCAN_FLAG_FEEDING) mflags|=MOTOR_FLAG_FEED; if (flags & SCAN_FLAG_USE_XPA) mflags |= MOTOR_FLAG_USE_XPA; status = gl843_init_motor_regs_scan (dev, reg, exposure, slope_dpi, scan_step_type, dev->model->is_cis ? lincnt * channels : lincnt, dummy, move, scan_power_mode, mflags); if (status != SANE_STATUS_GOOD) return status; /*** prepares data reordering ***/ /* words_per_line */ bytes_per_line = (used_pixels * used_res) / optical_res; bytes_per_line = (bytes_per_line * channels * depth) / 8; /* since we don't have sheetfed scanners to handle, * use huge read buffer */ /* TODO find the best size according to settings */ requested_buffer_size = 16 * bytes_per_line; read_buffer_size = 2 * requested_buffer_size + ((max_shift + stagger) * used_pixels * channels * depth) / 8; RIE (sanei_genesys_buffer_free (&(dev->read_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->read_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->lines_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->lines_buffer), read_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->shrink_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->shrink_buffer), requested_buffer_size)); RIE (sanei_genesys_buffer_free (&(dev->out_buffer))); RIE (sanei_genesys_buffer_alloc (&(dev->out_buffer), (8 * dev->settings.pixels * channels * depth) / 8)); dev->read_bytes_left = bytes_per_line * lincnt; DBG (DBG_info, "gl843_init_scan_regs: physical bytes to read = %lu\n", (u_long) dev->read_bytes_left); dev->read_active = SANE_TRUE; dev->current_setup.pixels = (used_pixels * used_res) / optical_res; DBG (DBG_info, "%s: current_setup.pixels=%d\n", __func__, dev->current_setup.pixels); dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; dev->total_bytes_read = 0; if (depth == 1) dev->total_bytes_to_read = ((dev->settings.pixels * dev->settings.lines) / 8 + (((dev->settings.pixels * dev->settings.lines) % 8) ? 1 : 0)) * channels; else dev->total_bytes_to_read = dev->settings.pixels * dev->settings.lines * channels * (depth / 8); DBG (DBG_info, "gl843_init_scan_regs: total bytes to send = %lu\n", (u_long) dev->total_bytes_to_read); DBG (DBG_proc, "gl843_init_scan_regs: completed\n"); return SANE_STATUS_GOOD; } static SANE_Status gl843_calculate_current_setup (Genesys_Device * dev) { int channels; int depth; int start; float xres; /*dpi */ float yres; /*dpi */ float startx; /*optical_res, from dummy_pixel+1 */ float pixels; float lines; int used_res; int used_pixels; unsigned int lincnt; int exposure; int stagger; int max_shift; SANE_Bool half_ccd; /* false: full CCD res is used, true, half max CCD res is used */ int optical_res; int oflags; DBG (DBG_info, "gl843_calculate_current_setup settings:\n" "Resolution: %ux%uDPI\n" "Lines : %u\n" "PPL : %u\n" "Startpos : %.3f/%.3f\n" "Scan mode : %d\n\n", dev->settings.xres, dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* channels */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == SCAN_MODE_LINEART) depth = 1; /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; /* optical flags */ oflags=0; if(dev->settings.scan_method==SCAN_METHOD_TRANSPARENCY) { oflags=OPTICAL_FLAG_USE_XPA; } xres = dev->settings.xres; yres = dev->settings.yres; startx = start; pixels = dev->settings.pixels; lines = dev->settings.lines; DBG (DBG_info, "gl843_calculate_current_setup settings:\n" "Resolution : %gDPI/%gDPI\n" "Lines : %g\n" "PPL : %g\n" "Startpos : %g\n" "Depth/Channels: %u/%u\n\n", xres, yres, lines, pixels, startx, depth, channels); /* half_ccd */ /* we have 2 domains for ccd: xres below or above half ccd max dpi */ if ((dev->sensor.optical_res < 4 * xres) || !(dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)) { half_ccd = SANE_FALSE; } else { half_ccd = SANE_TRUE; } /* optical_res */ optical_res = dev->sensor.optical_res; if (half_ccd) optical_res /= 4; /* stagger */ if ((!half_ccd) && (dev->model->flags & GENESYS_FLAG_STAGGERED_LINE)) stagger = (4 * yres) / dev->motor.base_ydpi; else stagger = 0; DBG (DBG_info, "%s: stagger=%d lines\n", __func__, stagger); if(xres<=optical_res) used_res = xres; else used_res=optical_res; /* compute scan parameters values */ /* pixels are allways given at half or full CCD optical resolution */ /* use detected left margin and fixed value */ /* compute correct pixels number */ used_pixels = (pixels * optical_res) / xres; DBG (DBG_info, "%s: used_pixels=%d\n", __func__, used_pixels); /* exposure */ exposure = gl843_compute_exposure (dev, used_res, oflags); DBG (DBG_info, "%s : exposure=%d pixels\n", __func__, exposure); /* it seems base_dpi of the G4050 motor is changed above 600 dpi*/ if (dev->model->motor_type == MOTOR_G4050 && yres>600) { dev->ld_shift_r = (dev->model->ld_shift_r*3800)/dev->motor.base_ydpi; dev->ld_shift_g = (dev->model->ld_shift_g*3800)/dev->motor.base_ydpi; dev->ld_shift_b = (dev->model->ld_shift_b*3800)/dev->motor.base_ydpi; } else { dev->ld_shift_r = dev->model->ld_shift_r; dev->ld_shift_g = dev->model->ld_shift_g; dev->ld_shift_b = dev->model->ld_shift_b; } /* scanned area must be enlarged by max color shift needed */ max_shift=sanei_genesys_compute_max_shift(dev,channels,yres,0); /* lincnt */ lincnt = lines + max_shift + stagger; dev->current_setup.pixels = (used_pixels * used_res) / optical_res; DBG (DBG_info, "%s: current_setup.pixels=%d\n", __func__, dev->current_setup.pixels); dev->current_setup.lines = lincnt; dev->current_setup.depth = depth; dev->current_setup.channels = channels; dev->current_setup.exposure_time = exposure; dev->current_setup.xres = used_res; dev->current_setup.yres = yres; dev->current_setup.half_ccd = half_ccd; dev->current_setup.stagger = stagger; dev->current_setup.max_shift = max_shift + stagger; DBG (DBG_proc, "gl843_calculate_current_setup: completed\n"); return SANE_STATUS_GOOD; } static void gl843_set_motor_power (Genesys_Register_Set * regs, SANE_Bool set) { DBG (DBG_proc, "gl843_set_motor_power\n"); if (set) { sanei_genesys_set_reg_from_set (regs, REG02, sanei_genesys_read_reg_from_set (regs, REG02) | REG02_MTRPWR); } else { sanei_genesys_set_reg_from_set (regs, REG02, sanei_genesys_read_reg_from_set (regs, REG02) & ~REG02_MTRPWR); } } static void gl843_set_lamp_power (Genesys_Device * dev, Genesys_Register_Set * regs, SANE_Bool set) { Genesys_Register_Set *r; int i; uint8_t val; val = sanei_genesys_read_reg_from_set (regs, REG03); if (set) { val |= REG03_LAMPPWR; sanei_genesys_set_reg_from_set (regs, REG03, val); for (i = 0; i < 6; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); r->value = dev->sensor.regs_0x10_0x1d[i]; } } else { val &= ~REG03_LAMPPWR; sanei_genesys_set_reg_from_set (regs, REG03, val); for (i = 0; i < 6; i++) { r = sanei_genesys_get_address (regs, 0x10 + i); r->value = 0x00; } } } /** * for fast power saving methods only, like disabling certain amplifiers * @param dev device to use * @param enable true to set inot powersaving * */ static SANE_Status gl843_save_power (Genesys_Device * dev, SANE_Bool enable) { uint8_t val; SANE_Status status; DBG (DBG_proc, "gl843_save_power: enable = %d\n", enable); if (dev == NULL) return SANE_STATUS_INVAL; /* switch KV-SS080 lamp off */ if (dev->model->gpo_type == GPO_KVSS080) { RIE(sanei_genesys_read_register (dev, REG6C, &val)); if(enable) val &= 0xef; else val |= 0x10; RIE(sanei_genesys_write_register(dev,REG6C,val)); } DBGCOMPLETED; return SANE_STATUS_GOOD; } static SANE_Status gl843_set_powersaving (Genesys_Device * dev, int delay /* in minutes */ ) { SANE_Status status = SANE_STATUS_GOOD; DBG (DBG_proc, "gl843_set_powersaving (delay = %d)\n", delay); if (dev == NULL) return SANE_STATUS_INVAL; DBGCOMPLETED; return status; } #ifndef UNIT_TESTING static #endif SANE_Status gl843_start_action (Genesys_Device * dev) { return sanei_genesys_write_register (dev, 0x0f, 0x01); } static SANE_Status gl843_stop_action (Genesys_Device * dev) { SANE_Status status; uint8_t val40, val; unsigned int loop; DBG (DBG_proc, "%s\n", __func__); status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } val40 = 0; status = sanei_genesys_read_register (dev, REG40, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n", __func__, sane_strstatus (status)); DBG (DBG_proc, "%s: completed\n", __func__); return status; } /* only stop action if needed */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG)) { DBG (DBG_info, "%s: already stopped\n", __func__); DBG (DBG_proc, "%s: completed\n", __func__); return SANE_STATUS_GOOD; } /* ends scan 646 */ val = sanei_genesys_read_reg_from_set (dev->reg, REG01); val &= ~REG01_SCAN; sanei_genesys_set_reg_from_set (dev->reg, REG01, val); status = sanei_genesys_write_register (dev, REG01, val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to write register 01: %s\n", __func__, sane_strstatus (status)); return status; } usleep (100 * 1000); loop = 10; while (loop > 0) { status = sanei_genesys_get_status (dev, &val); if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } val40 = 0; status = sanei_genesys_read_register (dev, 0x40, &val40); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n", __func__, sane_strstatus (status)); DBGCOMPLETED; return status; } /* if scanner is in command mode, we are done */ if (!(val40 & REG40_DATAENB) && !(val40 & REG40_MOTMFLG) && !(val & REG41_MOTORENB)) { DBGCOMPLETED; return SANE_STATUS_GOOD; } usleep (100 * 1000); loop--; } DBGCOMPLETED; return SANE_STATUS_IO_ERROR; } static SANE_Status gl843_get_paper_sensor (Genesys_Device * dev, SANE_Bool * paper_loaded) { SANE_Status status; uint8_t val; status = sanei_genesys_read_register (dev, REG6D, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_get_paper_sensor: failed to read gpio: %s\n", sane_strstatus (status)); return status; } *paper_loaded = (val & 0x1) == 0; return SANE_STATUS_GOOD; return SANE_STATUS_INVAL; } static SANE_Status gl843_eject_document (Genesys_Device * dev) { DBG (DBG_proc, "%s: not implemented \n", __func__); if (dev == NULL) return SANE_STATUS_INVAL; return SANE_STATUS_GOOD; } static SANE_Status gl843_load_document (Genesys_Device * dev) { DBG (DBG_proc, "%s: not implemented \n", __func__); if (dev == NULL) return SANE_STATUS_INVAL; return SANE_STATUS_GOOD; } /** * detects end of document and adjust current scan * to take it into account * used by sheetfed scanners */ static SANE_Status gl843_detect_document_end (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; SANE_Bool paper_loaded; unsigned int scancnt = 0; int flines, channels, depth, bytes_remain, sublines, bytes_to_flush, lines, sub_bytes, tmp, read_bytes_left; DBG (DBG_proc, "%s: begin\n", __func__); RIE (gl843_get_paper_sensor (dev, &paper_loaded)); /* sheetfed scanner uses home sensor as paper present */ if ((dev->document == SANE_TRUE) && !paper_loaded) { DBG (DBG_info, "%s: no more document\n", __func__); dev->document = SANE_FALSE; channels = dev->current_setup.channels; depth = dev->current_setup.depth; read_bytes_left = (int) dev->read_bytes_left; DBG (DBG_io, "gl843_detect_document_end: read_bytes_left=%d\n", read_bytes_left); /* get lines read */ status = sanei_genesys_read_scancnt (dev, &scancnt); if (status != SANE_STATUS_GOOD) { flines = 0; } else { /* compute number of line read */ tmp = (int) dev->total_bytes_read; if (depth == 1 || dev->settings.scan_mode == SCAN_MODE_LINEART) flines = tmp * 8 / dev->settings.pixels / channels; else flines = tmp / (depth / 8) / dev->settings.pixels / channels; /* number of scanned lines, but no read yet */ flines = scancnt - flines; DBG (DBG_io, "gl843_detect_document_end: %d scanned but not read lines\n", flines); } /* adjust number of bytes to read * we need to read the final bytes which are word per line * number of last lines * to have doc leaving feeder */ lines = (SANE_UNFIX (dev->model->post_scan) * dev->current_setup.yres) / MM_PER_INCH + flines; DBG (DBG_io, "gl843_detect_document_end: adding %d line to flush\n", lines); /* number of bytes to read from scanner to get document out of it after * end of document dectected by hardware sensor */ bytes_to_flush = lines * dev->wpl; /* if we are already close to end of scan, flushing isn't needed */ if (bytes_to_flush < read_bytes_left) { /* we take all these step to work around an overflow on some plateforms */ tmp = (int) dev->total_bytes_read; DBG (DBG_io, "gl843_detect_document_end: tmp=%d\n", tmp); bytes_remain = (int) dev->total_bytes_to_read; DBG (DBG_io, "gl843_detect_document_end: bytes_remain=%d\n", bytes_remain); bytes_remain = bytes_remain - tmp; DBG (DBG_io, "gl843_detect_document_end: bytes_remain=%d\n", bytes_remain); /* remaining lines to read by frontend for the current scan */ if (depth == 1 || dev->settings.scan_mode == SCAN_MODE_LINEART) { flines = bytes_remain * 8 / dev->settings.pixels / channels; } else flines = bytes_remain / (depth / 8) / dev->settings.pixels / channels; DBG (DBG_io, "gl843_detect_document_end: flines=%d\n", flines); if (flines > lines) { /* change the value controlling communication with the frontend : * total bytes to read is current value plus the number of remaining lines * multiplied by bytes per line */ sublines = flines - lines; if (depth == 1 || dev->settings.scan_mode == SCAN_MODE_LINEART) sub_bytes = ((dev->settings.pixels * sublines) / 8 + (((dev->settings.pixels * sublines) % 8) ? 1 : 0)) * channels; else sub_bytes = dev->settings.pixels * sublines * channels * (depth / 8); dev->total_bytes_to_read -= sub_bytes; /* then adjust the physical bytes to read */ if (read_bytes_left > sub_bytes) { dev->read_bytes_left -= sub_bytes; } else { dev->total_bytes_to_read = dev->total_bytes_read; dev->read_bytes_left = 0; } DBG (DBG_io, "gl843_detect_document_end: sublines=%d\n", sublines); DBG (DBG_io, "gl843_detect_document_end: subbytes=%d\n", sub_bytes); DBG (DBG_io, "gl843_detect_document_end: total_bytes_to_read=%lu\n", (unsigned long) dev->total_bytes_to_read); DBG (DBG_io, "gl843_detect_document_end: read_bytes_left=%d\n", read_bytes_left); } } else { DBG (DBG_io, "gl843_detect_document_end: no flushing needed\n"); } } DBG (DBG_proc, "%s: finished\n", __func__); return SANE_STATUS_GOOD; } /** @brief disable XPA slider motor * toggle gpios to switch disble XPA slider motor * @param dev device to set up */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_xpa_motor_off(Genesys_Device *dev) { uint8_t val; SANE_Status status=SANE_STATUS_GOOD; DBGSTART; /* unset GPOADF */ RIE (sanei_genesys_read_register (dev, REG6B, &val)); val &= ~REG6B_GPOADF; RIE (sanei_genesys_write_register (dev, REG6B, val)); RIE (sanei_genesys_read_register (dev, REGA8, &val)); val |= REGA8_GPO27; RIE (sanei_genesys_write_register (dev, REGA8, val)); RIE (sanei_genesys_read_register (dev, REGA9, &val)); val &= ~REGA9_GPO31; RIE (sanei_genesys_write_register (dev, REGA9, val)); DBGCOMPLETED; return status; } /** @brief enable XPA slider motor * toggle gpios to switch enable XPA slider motor * @param dev device to set up */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_xpa_motor_on(Genesys_Device *dev) { uint8_t val; SANE_Status status=SANE_STATUS_GOOD; DBGSTART; /* set MULTFILM et GPOADF */ RIE (sanei_genesys_read_register (dev, REG6B, &val)); val |=REG6B_MULTFILM|REG6B_GPOADF; RIE (sanei_genesys_write_register (dev, REG6B, val)); RIE (sanei_genesys_read_register (dev, REG6C, &val)); val &= ~REG6C_GPIO15; RIE (sanei_genesys_write_register (dev, REG6C, val)); /* Motor power ? No move at all without this one */ RIE (sanei_genesys_read_register (dev, REGA6, &val)); val |= REGA6_GPIO20; RIE (sanei_genesys_write_register(dev,REGA6,val)); RIE (sanei_genesys_read_register (dev, REGA8, &val)); val &= ~REGA8_GPO27; RIE (sanei_genesys_write_register (dev, REGA8, val)); RIE (sanei_genesys_read_register (dev, REGA9, &val)); val |= REGA9_GPO32|REGA9_GPO31; RIE (sanei_genesys_write_register (dev, REGA9, val)); DBGCOMPLETED; return status; } /** @brief light XPA lamp * toggle gpios to switch off regular lamp and light on the * XPA light * @param dev device to set up */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_xpa_lamp_on(Genesys_Device *dev) { uint8_t val; SANE_Status status=SANE_STATUS_GOOD; DBGSTART; /* REGA6 */ RIE(sanei_genesys_read_register(dev, REGA6, &val)); /* cut regular lamp power */ val &= ~(REGA6_GPIO24|REGA6_GPIO23); /* set XPA lamp power */ val |= REGA6_GPIO22 | REGA6_GPIO21 | REGA6_GPIO19; RIE(sanei_genesys_write_register(dev, REGA6, val)); RIE(sanei_genesys_read_register(dev, REGA7, &val)); val|=REGA7_GPOE24; /* lamp 1 off GPOE 24 */ val|=REGA7_GPOE23; /* lamp 2 off GPOE 23 */ val|=REGA7_GPOE22; /* full XPA lamp power */ RIE(sanei_genesys_write_register(dev, REGA7, val)); DBGCOMPLETED; return status; } /* Send the low-level scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_begin_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool start_motor) { SANE_Status status; uint8_t val,r03; uint16_t dpiset, dpihw; DBGSTART; /* get back the target dpihw */ sanei_genesys_get_double (reg, REG_DPISET, &dpiset); dpihw = sanei_genesys_compute_dpihw (dev, dpiset); /* set up GPIO for scan */ switch(dev->model->gpo_type) { /* KV case */ case GPO_KVSS080: RIE (sanei_genesys_write_register (dev, REGA9, 0x00)); RIE (sanei_genesys_write_register (dev, REGA6, 0xf6)); /* blinking led */ RIE (sanei_genesys_write_register (dev, 0x7e, 0x04)); break; case GPO_G4050: RIE (sanei_genesys_write_register (dev, REGA7, 0xfe)); RIE (sanei_genesys_write_register (dev, REGA8, 0x3e)); RIE (sanei_genesys_write_register (dev, REGA9, 0x06)); switch (dpihw) { case 1200: case 2400: case 4800: RIE (sanei_genesys_write_register (dev, REG6C, 0x60)); RIE (sanei_genesys_write_register (dev, REGA6, 0x46)); break; default: /* 600 dpi case */ RIE (sanei_genesys_write_register (dev, REG6C, 0x20)); RIE (sanei_genesys_write_register (dev, REGA6, 0x44)); } /* turn on XPA lamp if XPA is selected and lamp power on*/ r03 = sanei_genesys_read_reg_from_set (reg, REG03); if ((r03 & REG03_XPASEL) && (r03 & REG03_LAMPPWR)) { RIE(gl843_xpa_lamp_on(dev)); } /* enable XPA lamp motor */ if (r03 & REG03_XPASEL) { RIE(gl843_xpa_motor_on(dev)); } /* blinking led */ RIE (sanei_genesys_write_register (dev, REG7E, 0x01)); break; case GPO_CS4400F: case GPO_CS8400F: default: break; } /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); /* enable scan and motor */ RIE (sanei_genesys_read_register (dev, REG01, &val)); val |= REG01_SCAN; RIE (sanei_genesys_write_register (dev, REG01, val)); if (start_motor) { RIE (sanei_genesys_write_register (dev, REG0F, 1)); } else { RIE (sanei_genesys_write_register (dev, REG0F, 0)); } DBGCOMPLETED; return status; } /* Send the stop scan command */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_end_scan (Genesys_Device * dev, Genesys_Register_Set * reg, SANE_Bool check_stop) { SANE_Status status; uint8_t val; DBG (DBG_proc, "gl843_end_scan (check_stop = %d)\n", check_stop); if (reg == NULL) return SANE_STATUS_INVAL; /* post scan gpio */ RIE(sanei_genesys_write_register(dev,0x7e,0x00)); /* turn off XPA lamp if XPA is selected and lamp power on*/ val = sanei_genesys_read_reg_from_set (reg, REG03); if (val & (REG03_XPASEL|REG03_LAMPPWR)) { sanei_genesys_read_register (dev, REGA6, &val); /* switch on regular lamp */ val |= 0x40; /* no XPA lamp power (2 bits for level: __11 ____) */ val &= ~0x30; RIE (sanei_genesys_write_register (dev, REGA6, val)); } if (dev->model->is_sheetfed == SANE_TRUE) { status = SANE_STATUS_GOOD; } else /* flat bed scanners */ { status = gl843_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_end_scan: failed to stop: %s\n", sane_strstatus (status)); return status; } } DBGCOMPLETED; return status; } /** @brief park XPA lamp * park the XPA lamp if needed */ static SANE_Status gl843_park_xpa_lamp (Genesys_Device * dev) { Genesys_Register_Set local_reg[GENESYS_GL843_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; uint8_t val; int loop = 0; DBGSTART; /* copy scan settings */ memcpy (local_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); /* set a huge feedl and reverse direction */ sanei_genesys_set_triple(local_reg,REG_FEEDL,0xbdcd); /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); /* set up for reverse and no scan */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; /* write to scanner and start action */ RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL843_MAX_REGS)); RIE (gl843_xpa_motor_on(dev)); status = gl843_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to start motor: %s\n",__func__, sane_strstatus (status)); gl843_stop_action (dev); /* restore original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL843_MAX_REGS); return status; } while (loop < 600) /* do not wait longer then 60 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n",__func__, sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io2) { sanei_genesys_print_status (val); } if (val & REG41_HOMESNR) /* home sensor */ { DBG (DBG_info, "%s: reached home position\n",__func__); DBG (DBG_proc, "%s: finished\n",__func__); /* clear GPOADF to avoid reparking again */ sanei_genesys_read_register (dev, REG6B, &val); val &= ~REG6B_GPOADF; sanei_genesys_write_register (dev, REG6B, val); /* disable XPA slider motor */ gl843_xpa_motor_off(dev); return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ ++loop; } /* we are not parked here.... should we fail ? */ DBG (DBG_info, "%s: XPA lamp is not parked\n", __func__); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief Moves the slider to the home (top) position slowly * */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_slow_back_home (Genesys_Device * dev, SANE_Bool wait_until_home) { Genesys_Register_Set local_reg[GENESYS_GL843_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; uint8_t val; float resolution; int loop = 0; DBG (DBG_proc, "gl843_slow_back_home (wait_until_home = %d)\n", wait_until_home); if (dev->model->gpo_type == GPO_G4050) { /* test if we need to park XPA lamp, we check GPOADF */ RIE (sanei_genesys_read_register (dev, REG6B, &val)); if(val & REG6B_GPOADF) { RIE(gl843_park_xpa_lamp(dev)); } } /* regular slow back home */ dev->scanhead_position_in_steps = 0; /* first read gives HOME_SENSOR true */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to read home sensor: %s\n", __func__, sane_strstatus (status)); return status; } usleep (100000); /* sleep 100 ms */ /* second is reliable */ status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io) { sanei_genesys_print_status (val); } if (val & HOMESNR) /* is sensor at home? */ { DBGCOMPLETED; return SANE_STATUS_GOOD; } memcpy (local_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); status = gl843_init_scan_regs (dev, local_reg, resolution, resolution, 100, 40000, 100, 100, 8, 1, SCAN_MODE_LINEART, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_slow_back_home: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT | REG0D_CLRMCNT)); /* set up for reverse and no scan */ r = sanei_genesys_get_address (local_reg, REG02); r->value |= REG02_MTRREV; r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL843_MAX_REGS)); status = gl843_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_slow_back_home: failed to start motor: %s\n", sane_strstatus (status)); gl843_stop_action (dev); /* restore original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL843_MAX_REGS); return status; } if (wait_until_home) { while (loop < 300) /* do not wait longer then 30 seconds */ { status = sanei_genesys_get_status (dev, &val); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_slow_back_home: failed to read home sensor: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_io2) { sanei_genesys_print_status (val); } if (val & REG41_HOMESNR) /* home sensor */ { DBG (DBG_info, "gl843_slow_back_home: reached home position\n"); DBG (DBG_proc, "gl843_slow_back_home: finished\n"); return SANE_STATUS_GOOD; } usleep (100000); /* sleep 100 ms */ ++loop; } /* when we come here then the scanner needed too much time for this, so we better stop the motor */ gl843_stop_action (dev); DBG (DBG_error, "gl843_slow_back_home: timeout while waiting for scanhead to go home\n"); return SANE_STATUS_IO_ERROR; } DBG (DBG_info, "%s: scanhead is still moving\n", __func__); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* Automatically set top-left edge of the scan area by scanning a 200x200 pixels area at 600 dpi from very top of scanner */ static SANE_Status gl843_search_start_position (Genesys_Device * dev) { int size; SANE_Status status; uint8_t *data; Genesys_Register_Set local_reg[GENESYS_GL843_MAX_REGS]; int steps; int pixels = 600; int dpi = 300; DBG (DBG_proc, "gl843_search_start_position\n"); memcpy (local_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); /* sets for a 200 lines * 600 pixels */ /* normal scan with no shading */ status = gl843_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, /*we should give a small offset here~60 steps */ 600, dev->model->search_lines, 8, 1, SCAN_MODE_GRAY, 1, /*green */ SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_IGNORE_LINE_DISTANCE | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_search_start_position: failed to bulk setup registers: %s\n", sane_strstatus (status)); return status; } /* send to scanner */ status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL843_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_search_start_position: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } size = pixels * dev->model->search_lines; data = malloc (size); if (!data) { DBG (DBG_error, "gl843_search_start_position: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } status = gl843_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_start_position: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("search_position.pnm", data, 8, 1, pixels, dev->model->search_lines); status = gl843_end_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_start_position: failed to end scan: %s\n", sane_strstatus (status)); return status; } /* update regs to copy ASIC internal state */ memcpy (dev->reg, local_reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); status = sanei_genesys_search_reference_point (dev, data, 0, dpi, pixels, dev->model->search_lines); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_start_position: failed to set search reference point: %s\n", sane_strstatus (status)); return status; } free (data); return SANE_STATUS_GOOD; } /* * sets up register for coarse gain calibration * todo: check it for scanners using it */ static SANE_Status gl843_init_regs_for_coarse_calibration (Genesys_Device * dev) { SANE_Status status; uint8_t channels; uint8_t cksel; DBGSTART; cksel = (dev->calib_reg[reg_0x18].value & REG18_CKSEL) + 1; /* clock speed = 1..4 clocks */ /* set line size */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */ channels = 3; else channels = 1; status = gl843_init_scan_regs (dev, dev->calib_reg, dev->settings.xres, dev->settings.yres, 0, 0, /* XXX STEF XXX dpi instead of pixels !*/ dev->sensor.optical_res / cksel, 20, 16, channels, dev->settings.scan_mode, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_init_register_for_coarse_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } gl843_set_motor_power (dev->calib_reg, SANE_FALSE); DBG (DBG_info, "gl843_init_register_for_coarse_calibration: optical sensor res: %d dpi, actual res: %d\n", dev->sensor.optical_res / cksel, dev->settings.xres); status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_init_register_for_coarse_calibration: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief moves the slider to steps at motor base dpi * @param dev device to work on * @param steps number of steps to move * */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_feed (Genesys_Device * dev, unsigned int steps) { Genesys_Register_Set local_reg[GENESYS_GL843_MAX_REGS]; SANE_Status status; Genesys_Register_Set *r; float resolution; uint8_t val; DBGSTART; /* prepare local registers */ memcpy (local_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); resolution=sanei_genesys_get_lowest_ydpi(dev); status = gl843_init_scan_regs (dev, local_reg, resolution, resolution, 0, steps, 100, 3, 8, 3, SCAN_MODE_COLOR, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_FEEDING | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_feed: failed to set up registers: %s\n", sane_strstatus (status)); DBGCOMPLETED; return status; } /* clear scan and feed count */ RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRLNCNT)); RIE (sanei_genesys_write_register (dev, REG0D, REG0D_CLRMCNT)); /* set up for no scan */ r = sanei_genesys_get_address (local_reg, REG01); r->value &= ~REG01_SCAN; /* send registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL843_MAX_REGS)); status = gl843_start_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to start motor: %s\n", __func__, sane_strstatus (status)); gl843_stop_action (dev); /* restore original registers */ dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL843_MAX_REGS); return status; } /* wait until feed count reaches the required value, but do not * exceed 30s */ do { status = sanei_genesys_get_status (dev, &val); } while (status == SANE_STATUS_GOOD && !(val & FEEDFSH)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* init registers for shading calibration */ /* shading calibration is done at dpihw */ static SANE_Status gl843_init_regs_for_shading (Genesys_Device * dev) { SANE_Status status; int move, resolution, dpihw, factor; uint16_t strpixel; DBGSTART; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); dev->calib_channels = 3; dev->calib_lines = dev->model->shading_lines; dpihw=sanei_genesys_compute_dpihw(dev,dev->settings.xres); factor=dev->sensor.optical_res/dpihw; resolution=dpihw; dev->calib_resolution = resolution; dev->calib_pixels = dev->sensor.sensor_pixels/factor; /* distance to move to reach white target */ move = SANE_UNFIX (dev->model->y_offset_calib); move = (move * resolution) / MM_PER_INCH; status = gl843_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, move, dev->calib_pixels, dev->calib_lines, 16, dev->calib_channels, dev->settings.scan_mode, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_DISABLE_BUFFER_FULL_MOVE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_init_registers_for_shading: failed to setup scan: %s\n", sane_strstatus (status)); return status; } dev->scanhead_position_in_steps += dev->calib_lines + move; sanei_genesys_get_double(dev->calib_reg,REG_STRPIXEL,&strpixel); DBG (DBG_info, "%s: STRPIXEL=%d\n", __func__, strpixel); status = dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_init_registers_for_shading: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } DBGCOMPLETED; return SANE_STATUS_GOOD; } /** @brief set up registers for the actual scan */ static SANE_Status gl843_init_regs_for_scan (Genesys_Device * dev) { int channels; int flags; int depth; float move; int move_dpi; float start; SANE_Status status; DBG (DBG_info, "gl843_init_regs_for_scan settings:\nResolution: %ux%uDPI\n" "Lines : %u\npixels : %u\nStartpos : %.3f/%.3f\nScan mode : %d\n\n", dev->settings.xres, dev->settings.yres, dev->settings.lines, dev->settings.pixels, dev->settings.tl_x, dev->settings.tl_y, dev->settings.scan_mode); /* ensure head is parked in case of calibration */ gl843_slow_back_home (dev, SANE_TRUE); /* channels */ if (dev->settings.scan_mode == SCAN_MODE_COLOR) channels = 3; else channels = 1; /* depth */ depth = dev->settings.depth; if (dev->settings.scan_mode == SCAN_MODE_LINEART) depth = 1; move_dpi = dev->motor.base_ydpi; move = SANE_UNFIX (dev->model->y_offset); move += dev->settings.tl_y; move = (move * move_dpi) / MM_PER_INCH; DBG (DBG_info, "gl843_init_regs_for_scan: move=%f steps\n", move); /* start */ start = SANE_UNFIX (dev->model->x_offset); start += dev->settings.tl_x; start = (start * dev->sensor.optical_res) / MM_PER_INCH; flags = 0; /* enable emulated lineart from gray data */ if(dev->settings.scan_mode == SCAN_MODE_LINEART && dev->settings.dynamic_lineart) { flags |= SCAN_FLAG_DYNAMIC_LINEART; } status = gl843_init_scan_regs (dev, dev->reg, dev->settings.xres, dev->settings.yres, start, move, dev->settings.pixels, dev->settings.lines, depth, channels, dev->settings.scan_mode, dev->settings.color_filter, flags); if (status != SANE_STATUS_GOOD) return status; DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * This function sends gamma tables to ASIC */ static SANE_Status gl843_send_gamma_table (Genesys_Device * dev) { int size; int status; uint8_t *gamma; int i; DBGSTART; size = 256; /* allocate temporary gamma tables: 16 bits words, 3 channels */ gamma = (uint8_t *) malloc (size * 2 * 3); if (!gamma) return SANE_STATUS_NO_MEM; /* copy sensor specific's gamma tables */ for (i = 0; i < size; i++) { gamma[i * 2 + size * 0 + 0] = dev->sensor.gamma_table[GENESYS_RED][i] & 0xff; gamma[i * 2 + size * 0 + 1] = (dev->sensor.gamma_table[GENESYS_RED][i] >> 8) & 0xff; gamma[i * 2 + size * 2 + 0] = dev->sensor.gamma_table[GENESYS_GREEN][i] & 0xff; gamma[i * 2 + size * 2 + 1] = (dev->sensor.gamma_table[GENESYS_GREEN][i] >> 8) & 0xff; gamma[i * 2 + size * 4 + 0] = dev->sensor.gamma_table[GENESYS_BLUE][i] & 0xff; gamma[i * 2 + size * 4 + 1] = (dev->sensor.gamma_table[GENESYS_BLUE][i] >> 8) & 0xff; } /* send address */ status = gl843_set_buffer_address (dev, 0x0000); if (status != SANE_STATUS_GOOD) { free (gamma); DBG (DBG_error, "gl843_send_gamma_table: failed to set buffer address: %s\n", sane_strstatus (status)); return status; } /* send data */ status = gl843_bulk_write_data (dev, 0x28, (uint8_t *) gamma, size * 2 * 3); if (status != SANE_STATUS_GOOD) { free (gamma); DBG (DBG_error, "gl843_send_gamma_table: failed to send gamma table: %s\n", sane_strstatus (status)); return status; } DBG (DBG_proc, "gl843_send_gamma_table: completed\n"); free (gamma); return SANE_STATUS_GOOD; } /* this function does the led calibration by scanning one line of the calibration area below scanner's top on white strip. -needs working coarse/gain */ static SANE_Status gl843_led_calibration (Genesys_Device * dev) { int num_pixels; int total_size; int used_res; uint8_t *line; int i, j; SANE_Status status = SANE_STATUS_GOOD; int val; int channels, depth; int avg[3], avga, avge; int turn; char fn[20]; uint16_t expr, expg, expb; Genesys_Register_Set *r; SANE_Bool acceptable = SANE_FALSE; DBG (DBG_proc, "gl843_led_calibration\n"); /* offset calibration is always done in color mode */ channels = 3; depth = 16; used_res = dev->sensor.optical_res; num_pixels = (dev->sensor.sensor_pixels * used_res) / dev->sensor.optical_res; /* initial calibration reg values */ memcpy (dev->calib_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); status = gl843_init_scan_regs (dev, dev->calib_reg, used_res, dev->motor.base_ydpi, 0, 0, num_pixels, 1, depth, channels, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_led_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } RIE (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS)); total_size = num_pixels * channels * (depth / 8) * 1; /* colors * bytes_per_color * scan lines */ line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; /* we try to get equal bright leds here: loop: average per color adjust exposure times */ expr = (dev->sensor.regs_0x10_0x1d[0] << 8) | dev->sensor.regs_0x10_0x1d[1]; expg = (dev->sensor.regs_0x10_0x1d[2] << 8) | dev->sensor.regs_0x10_0x1d[3]; expb = (dev->sensor.regs_0x10_0x1d[4] << 8) | dev->sensor.regs_0x10_0x1d[5]; turn = 0; do { dev->sensor.regs_0x10_0x1d[0] = (expr >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[1] = expr & 0xff; dev->sensor.regs_0x10_0x1d[2] = (expg >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[3] = expg & 0xff; dev->sensor.regs_0x10_0x1d[4] = (expb >> 8) & 0xff; dev->sensor.regs_0x10_0x1d[5] = expb & 0xff; for (i = 0; i < 6; i++) { r = sanei_genesys_get_address (dev->calib_reg, 0x10 + i); r->value = dev->sensor.regs_0x10_0x1d[i]; } RIE (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS)); DBG (DBG_info, "gl843_led_calibration: starting first line reading\n"); RIE (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE)); RIE (sanei_genesys_read_data_from_scanner (dev, line, total_size)); if (DBG_LEVEL >= DBG_data) { snprintf (fn, 20, "led_%02d.pnm", turn); sanei_genesys_write_pnm_file (fn, line, depth, channels, num_pixels, 1); } acceptable = SANE_TRUE; for (j = 0; j < channels; j++) { avg[j] = 0; for (i = 0; i < num_pixels; i++) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * num_pixels + 1] * 256 + line[i * 2 + j * 2 * num_pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; avg[j] += val; } avg[j] /= num_pixels; } DBG (DBG_info, "gl843_led_calibration: average: " "%d,%d,%d\n", avg[0], avg[1], avg[2]); acceptable = SANE_TRUE; if (avg[0] < avg[1] * 0.95 || avg[1] < avg[0] * 0.95 || avg[0] < avg[2] * 0.95 || avg[2] < avg[0] * 0.95 || avg[1] < avg[2] * 0.95 || avg[2] < avg[1] * 0.95) acceptable = SANE_FALSE; if (!acceptable) { avga = (avg[0] + avg[1] + avg[2]) / 3; expr = (expr * avga) / avg[0]; expg = (expg * avga) / avg[1]; expb = (expb * avga) / avg[2]; /* keep the resulting exposures below this value. too long exposure drives the ccd into saturation. we may fix this by relying on the fact that we get a striped scan without shading, by means of statistical calculation */ avge = (expr + expg + expb) / 3; /* don't overflow max exposure */ if (avge > 3000) { expr = (expr * 2000) / avge; expg = (expg * 2000) / avge; expb = (expb * 2000) / avge; } if (avge < 50) { expr = (expr * 50) / avge; expg = (expg * 50) / avge; expb = (expb * 50) / avge; } } RIE (gl843_stop_action (dev)); turn++; } while (!acceptable && turn < 100); DBG (DBG_info, "gl843_led_calibration: acceptable exposure: %d,%d,%d\n", expr, expg, expb); /* cleanup before return */ free (line); gl843_slow_back_home (dev, SANE_TRUE); DBG (DBG_proc, "gl843_led_calibration: completed\n"); return status; } /** * average dark pixels of a 8 bits scan of a given channel */ static int dark_average_channel (uint8_t * data, unsigned int pixels, unsigned int lines, unsigned int channels, unsigned int black, int channel) { unsigned int i, j, k, count; unsigned int avg[3]; uint8_t val; /* computes average values on black margin */ for (k = 0; k < channels; k++) { avg[k] = 0; count = 0; for (i = 0; i < lines; i++) { for (j = 0; j < black; j++) { val = data[i * channels * pixels + j*channels + k]; avg[k] += val; count++; } } if (count) avg[k] /= count; DBG (DBG_info, "%s: avg[%d] = %d\n", __func__, k, avg[k]); } DBG (DBG_info, "%s: average = %d\n", __func__, avg[channel]); return avg[channel]; } /** @brief calibrate AFE offset * Iterate doing scans at target dpi until AFE offset if correct. One * color line is scanned at a time. Scanning head doesn't move. * @param dev device to calibrate */ static SANE_Status gl843_offset_calibration (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; uint8_t *first_line, *second_line; unsigned int channels, bpp; char title[32]; int pass, total_size, i, resolution, lines; int topavg[3], bottomavg[3], avg[3]; int top[3], bottom[3], black_pixels, pixels, factor, dpihw; DBGSTART; /* offset calibration is always done in color mode */ channels = 3; lines = 8; bpp = 8; /* compute divider factor to compute final pixels number */ dpihw = sanei_genesys_compute_dpihw (dev, dev->settings.xres); factor = dev->sensor.optical_res / dpihw; resolution = dpihw; pixels = dev->sensor.sensor_pixels / factor; black_pixels = dev->sensor.black_pixels / factor; DBG (DBG_io, "gl843_offset_calibration: dpihw =%d\n", dpihw); DBG (DBG_io, "gl843_offset_calibration: factor =%d\n", factor); DBG (DBG_io, "gl843_offset_calibration: resolution =%d\n", resolution); DBG (DBG_io, "gl843_offset_calibration: pixels =%d\n", pixels); DBG (DBG_io, "gl843_offset_calibration: black_pixels=%d\n", black_pixels); status = gl843_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, pixels, lines, bpp, channels, SCAN_MODE_COLOR, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_offset_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } gl843_set_motor_power (dev->calib_reg, SANE_FALSE); /* allocate memory for scans */ total_size = pixels * channels * lines * (bpp / 8); /* colors * bytes_per_color * scan lines */ first_line = malloc (total_size); if (!first_line) return SANE_STATUS_NO_MEM; second_line = malloc (total_size); if (!second_line) { free (first_line); return SANE_STATUS_NO_MEM; } /* init gain and offset */ for (i = 0; i < 3; i++) { bottom[i] = 10; dev->frontend.offset[i] = bottom[i]; dev->frontend.gain[i] = 0; } RIEF2 (gl843_set_fe (dev, AFE_SET), first_line, second_line); /* scan with obttom AFE settings */ RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl843_offset_calibration: starting first line reading\n"); RIEF2 (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, first_line, total_size), first_line, second_line); if (DBG_LEVEL >= DBG_data) { for (i = 0; i < 3; i++) { snprintf (title, 20, "offset_%d_%03d.pnm", i, bottom[i]); sanei_genesys_write_pnm_file (title, first_line, bpp, channels, pixels, lines); } } for (i = 0; i < 3; i++) { bottomavg[i] = dark_average_channel (first_line, pixels, lines, channels, black_pixels, i); DBG (DBG_io2, "gl843_offset_calibration: bottom avg %d=%d\n", i, bottomavg[i]); } /* now top value */ for (i = 0; i < 3; i++) { top[i] = 255; dev->frontend.offset[i] = top[i]; } RIEF2 (gl843_set_fe (dev, AFE_SET), first_line, second_line); /* scan with top AFE values */ RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl843_offset_calibration: starting second line reading\n"); RIEF2 (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); for (i = 0; i < 3; i++) { topavg[i] = dark_average_channel (second_line, pixels, lines, channels, black_pixels, i); DBG (DBG_io2, "gl843_offset_calibration: top avg %d=%d\n", i, topavg[i]); } pass = 0; /* loop until acceptable level */ while ((pass < 32) && ((top[0] - bottom[0] > 1) || (top[1] - bottom[1] > 1) || (top[2] - bottom[2] > 1))) { pass++; /* settings for new scan */ for (i = 0; i < 3; i++) { if (top[i] - bottom[i] > 1) { dev->frontend.offset[i] = (top[i] + bottom[i]) / 2; } } RIEF2 (gl843_set_fe (dev, AFE_SET), first_line, second_line); /* scan with no move */ RIEF2 (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS), first_line, second_line); DBG (DBG_info, "gl843_offset_calibration: starting second line reading\n"); RIEF2 (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE), first_line, second_line); RIEF2 (sanei_genesys_read_data_from_scanner (dev, second_line, total_size), first_line, second_line); if (DBG_LEVEL >= DBG_data) { for (i = 0; i < 3; i++) { sprintf (title, "offset_%d_%03d.pnm", i, dev->frontend.offset[i]); sanei_genesys_write_pnm_file (title, second_line, bpp, channels, pixels, lines); } } for (i = 0; i < 3; i++) { avg[i] = dark_average_channel (second_line, pixels, lines, channels, black_pixels, i); DBG (DBG_info, "gl843_offset_calibration: avg[%d]=%d offset=%d\n", i, avg[i], dev->frontend.offset[i]); } /* compute new boundaries */ for (i = 0; i < 3; i++) { if (topavg[i] >= avg[i]) { topavg[i] = avg[i]; top[i] = dev->frontend.offset[i]; } else { bottomavg[i] = avg[i]; bottom[i] = dev->frontend.offset[i]; } } } DBG (DBG_info, "gl843_offset_calibration: offset=(%d,%d,%d)\n", dev->frontend.offset[0], dev->frontend.offset[1], dev->frontend.offset[2]); /* cleanup before return */ free (first_line); free (second_line); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* alternative coarse gain calibration this on uses the settings from offset_calibration and uses only one scanline */ /* with offset and coarse calibration we only want to get our input range into a reasonable shape. the fine calibration of the upper and lower bounds will be done with shading. */ static SANE_Status gl843_coarse_gain_calibration (Genesys_Device * dev, int dpi) { int pixels, factor, dpihw; int total_size; uint8_t *line; int i, j, channels; SANE_Status status = SANE_STATUS_GOOD; int max[3]; float gain[3],coeff; int val, code, lines; int resolution; int bpp; DBG (DBG_proc, "gl843_coarse_gain_calibration: dpi = %d\n", dpi); dpihw=sanei_genesys_compute_dpihw(dev, dpi); factor=dev->sensor.optical_res/dpihw; /* coarse gain calibration is always done in color mode */ channels = 3; /* follow CKSEL */ if (dev->model->ccd_type == CCD_KVSS080) { if(dev->settings.xressensor.optical_res) { coeff=0.9; } else { coeff=1.0; } } else { coeff=1.0; } resolution=dpihw; lines=10; bpp=8; pixels = dev->sensor.sensor_pixels / factor; status = gl843_init_scan_regs (dev, dev->calib_reg, resolution, resolution, 0, 0, pixels, lines, bpp, channels, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); gl843_set_motor_power (dev->calib_reg, SANE_FALSE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_coarse_calibration: failed to setup scan: %s\n", sane_strstatus (status)); return status; } RIE (dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg, GENESYS_GL843_MAX_REGS)); total_size = pixels * channels * (16/bpp) * lines; line = malloc (total_size); if (!line) return SANE_STATUS_NO_MEM; RIEF (gl843_set_fe(dev, AFE_SET), line); RIEF (gl843_begin_scan (dev, dev->calib_reg, SANE_TRUE), line); RIEF (sanei_genesys_read_data_from_scanner (dev, line, total_size), line); if (DBG_LEVEL >= DBG_data) sanei_genesys_write_pnm_file ("coarse.pnm", line, bpp, channels, pixels, lines); /* average value on each channel */ for (j = 0; j < channels; j++) { max[j] = 0; for (i = pixels/4; i < (pixels*3/4); i++) { if(bpp==16) { if (dev->model->is_cis) val = line[i * 2 + j * 2 * pixels + 1] * 256 + line[i * 2 + j * 2 * pixels]; else val = line[i * 2 * channels + 2 * j + 1] * 256 + line[i * 2 * channels + 2 * j]; } else { if (dev->model->is_cis) val = line[i + j * pixels]; else val = line[i * channels + j]; } max[j] += val; } max[j] = max[j] / (pixels/2); gain[j] = ((float) dev->sensor.gain_white_ref*coeff) / max[j]; /* turn logical gain value into gain code, checking for overflow */ code = 283 - 208 / gain[j]; if (code > 255) code = 255; else if (code < 0) code = 0; dev->frontend.gain[j] = code; DBG (DBG_proc, "gl843_coarse_gain_calibration: channel %d, max=%d, gain = %f, setting:%d\n", j, max[j], gain[j], dev->frontend.gain[j]); } if (dev->model->is_cis) { if (dev->frontend.gain[0] > dev->frontend.gain[1]) dev->frontend.gain[0] = dev->frontend.gain[1]; if (dev->frontend.gain[0] > dev->frontend.gain[2]) dev->frontend.gain[0] = dev->frontend.gain[2]; dev->frontend.gain[2] = dev->frontend.gain[1] = dev->frontend.gain[0]; } if (channels == 1) { dev->frontend.gain[0] = dev->frontend.gain[1]; dev->frontend.gain[2] = dev->frontend.gain[1]; } free (line); RIE (gl843_stop_action (dev)); status=gl843_slow_back_home (dev, SANE_TRUE); DBGCOMPLETED; return status; } /* * wait for lamp warmup by scanning the same line until difference * between 2 scans is below a threshold */ static SANE_Status gl843_init_regs_for_warmup (Genesys_Device * dev, Genesys_Register_Set * reg, int *channels, int *total_size) { int num_pixels; SANE_Status status = SANE_STATUS_GOOD; int dpihw; int resolution; int factor; DBGSTART; if (dev == NULL || reg == NULL || channels == NULL || total_size == NULL) return SANE_STATUS_INVAL; /* setup scan */ *channels=3; resolution=600; dpihw=sanei_genesys_compute_dpihw(dev, resolution); factor=dev->sensor.optical_res/dpihw; num_pixels=dev->sensor.sensor_pixels/(factor*2); *total_size = num_pixels * 3 * 1; memcpy (reg, dev->reg, (GENESYS_GL843_MAX_REGS + 1) * sizeof (Genesys_Register_Set)); status = gl843_init_scan_regs (dev, reg, resolution, resolution, num_pixels/2, 0, num_pixels, 1, 8, *channels, SCAN_MODE_COLOR, dev->settings.color_filter, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA | SCAN_FLAG_SINGLE_LINE | SCAN_FLAG_IGNORE_LINE_DISTANCE); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to setup scan: %s\n", __func__, sane_strstatus (status)); return status; } gl843_set_motor_power (reg, SANE_FALSE); RIE (dev->model->cmd_set->bulk_write_register (dev, reg, GENESYS_GL843_MAX_REGS)); DBGCOMPLETED; return SANE_STATUS_GOOD; } /** * set up GPIO/GPOE for idle state WRITE GPIO[17-21]= GPIO19 WRITE GPOE[17-21]= GPOE21 GPOE20 GPOE19 GPOE18 genesys_write_register(0xa8,0x3e) GPIO(0xa8)=0x3e */ static SANE_Status gl843_init_gpio (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; int idx; DBGSTART; RIE (sanei_genesys_write_register (dev, REG6E, dev->gpo.enable[0])); RIE (sanei_genesys_write_register (dev, REG6F, dev->gpo.enable[1])); RIE (sanei_genesys_write_register (dev, REG6C, dev->gpo.value[0])); RIE (sanei_genesys_write_register (dev, REG6D, dev->gpo.value[1])); idx=0; while(dev->model->gpo_type != gpios[idx].gpo_type && gpios[idx].gpo_type!=0) { idx++; } if (gpios[idx].gpo_type!=0) { RIE (sanei_genesys_write_register (dev, REGA6, gpios[idx].ra6)); RIE (sanei_genesys_write_register (dev, REGA7, gpios[idx].ra7)); RIE (sanei_genesys_write_register (dev, REGA8, gpios[idx].ra8)); RIE (sanei_genesys_write_register (dev, REGA9, gpios[idx].ra9)); } else { status=SANE_STATUS_INVAL; } DBGCOMPLETED; return status; } /* * * initialize ASIC from power on condition */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_boot (Genesys_Device * dev, SANE_Bool cold) { SANE_Status status; uint8_t val; DBGSTART; if(cold) { RIE (sanei_genesys_write_register (dev, 0x0e, 0x01)); RIE (sanei_genesys_write_register (dev, 0x0e, 0x00)); } if(dev->usb_mode == 1) { val = 0x14; } else { val = 0x11; } RIE (sanei_genesys_write_0x8c (dev, 0x0f, val)); /* test CHKVER */ RIE (sanei_genesys_read_register (dev, REG40, &val)); if (val & REG40_CHKVER) { RIE (sanei_genesys_read_register (dev, 0x00, &val)); DBG (DBG_info, "%s: reported version for genesys chip is 0x%02x\n", __func__, val); } /* Set default values for registers */ gl843_init_registers (dev); RIE (sanei_genesys_write_register (dev, REG6B, 0x02)); /* Write initial registers */ RIE (dev->model->cmd_set->bulk_write_register (dev, dev->reg, GENESYS_GL843_MAX_REGS)); /* Enable DRAM by setting a rising edge on bit 3 of reg 0x0b */ val = dev->reg[reg_0x0b].value & REG0B_DRAMSEL; val = (val | REG0B_ENBDRAM); RIE (sanei_genesys_write_register (dev, REG0B, val)); dev->reg[reg_0x0b].value = val; /* URB 14 control 0x40 0x0c 0x8c 0x10 len 1 wrote 0xb4 */ RIE (sanei_genesys_write_0x8c (dev, 0x10, 0xb4)); /* CLKSET */ val = (dev->reg[reg_0x0b].value & ~REG0B_CLKSET) | REG0B_48MHZ; RIE (sanei_genesys_write_register (dev, REG0B, val)); dev->reg[reg_0x0b].value = val; /* prevent further writings by bulk write register */ dev->reg[reg_0x0b].address = 0x00; /* set up end access */ sanei_genesys_write_register (dev, REGA7, 0x04); sanei_genesys_write_register (dev, REGA9, 0x00); /* set RAM read address */ RIE (sanei_genesys_write_register (dev, REG29, 0x00)); RIE (sanei_genesys_write_register (dev, REG2A, 0x00)); RIE (sanei_genesys_write_register (dev, REG2B, 0x00)); /* setup gpio */ RIE (gl843_init_gpio (dev)); gl843_feed (dev, 300); usleep (100000); DBGCOMPLETED; return SANE_STATUS_GOOD; } /* * * initialize backend and ASIC : registers, motor tables, and gamma tables * then ensure scanner's head is at home */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_init (Genesys_Device * dev) { SANE_Status status; DBG_INIT (); DBGSTART; status=sanei_genesys_asic_init(dev, GENESYS_GL843_MAX_REGS); DBGCOMPLETED; return status; } static SANE_Status gl843_update_hardware_sensors (Genesys_Scanner * s) { /* do what is needed to get a new set of events, but try to not lose any of them. */ SANE_Status status = SANE_STATUS_GOOD; uint8_t val; RIE (sanei_genesys_read_register (s->dev, REG6D, &val)); switch (s->dev->model->gpo_type) { case GPO_KVSS080: if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b) s->val[OPT_SCAN_SW].b = (val & 0x04) == 0; break; case GPO_G4050: if (s->val[OPT_SCAN_SW].b == s->last_val[OPT_SCAN_SW].b) s->val[OPT_SCAN_SW].b = (val & 0x01) == 0; if (s->val[OPT_FILE_SW].b == s->last_val[OPT_FILE_SW].b) s->val[OPT_FILE_SW].b = (val & 0x02) == 0; if (s->val[OPT_EMAIL_SW].b == s->last_val[OPT_EMAIL_SW].b) s->val[OPT_EMAIL_SW].b = (val & 0x04) == 0; if (s->val[OPT_COPY_SW].b == s->last_val[OPT_COPY_SW].b) s->val[OPT_COPY_SW].b = (val & 0x08) == 0; break; case GPO_CS4400F: case GPO_CS8400F: default: break; } return status; } #ifndef UNIT_TESTING static #endif /** @brief move sensor to transparency adaptor * Move sensor to the calibration of the transparency adapator (XPA). * @param dev device to use */ SANE_Status gl843_move_to_ta (Genesys_Device * dev) { SANE_Status status = SANE_STATUS_GOOD; float resolution; unsigned int feed; DBGSTART; resolution=sanei_genesys_get_lowest_ydpi(dev); feed = 16*(SANE_UNFIX (dev->model->y_offset_calib_ta) * resolution) / MM_PER_INCH; status = gl843_feed (dev, feed); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to move to XPA calibration area\n", __func__); return status; } DBGCOMPLETED; return status; } /** @brief search for a full width black or white strip. * This function searches for a black or white stripe across the scanning area. * When searching backward, the searched area must completely be of the desired * color since this area will be used for calibration which scans forward. * @param dev scanner device * @param forward SANE_TRUE if searching forward, SANE_FALSE if searching backward * @param black SANE_TRUE if searching for a black strip, SANE_FALSE for a white strip * @return SANE_STATUS_GOOD if a matching strip is found, SANE_STATUS_UNSUPPORTED if not */ static SANE_Status gl843_search_strip (Genesys_Device * dev, SANE_Bool forward, SANE_Bool black) { unsigned int pixels, lines, channels; SANE_Status status; Genesys_Register_Set local_reg[GENESYS_GL843_MAX_REGS]; size_t size; uint8_t *data; int steps, depth, dpi; unsigned int pass, count, found, x, y; char title[80]; Genesys_Register_Set *r; DBG (DBG_proc, "gl843_search_strip %s %s\n", black ? "black" : "white", forward ? "forward" : "reverse"); gl843_set_fe (dev, AFE_SET); status = gl843_stop_action (dev); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_search_strip: failed to stop: %s\n", sane_strstatus (status)); return status; } /* set up for a gray scan at lowest dpi */ dpi = sanei_genesys_get_lowest_dpi(dev); channels = 1; /* 10 MM */ /* lines = (10 * dpi) / MM_PER_INCH; */ /* shading calibation is done with dev->motor.base_ydpi */ lines = (dev->model->shading_lines * dpi) / dev->motor.base_ydpi; depth = 8; pixels = (dev->sensor.sensor_pixels * dpi) / dev->sensor.optical_res; size = pixels * channels * lines * (depth / 8); data = malloc (size); if (!data) { DBG (DBG_error, "gl843_search_strip: failed to allocate memory\n"); return SANE_STATUS_NO_MEM; } dev->scanhead_position_in_steps = 0; memcpy (local_reg, dev->reg, GENESYS_GL843_MAX_REGS * sizeof (Genesys_Register_Set)); status = gl843_init_scan_regs (dev, local_reg, dpi, dpi, 0, 0, pixels, lines, depth, channels, SCAN_MODE_GRAY, 0, SCAN_FLAG_DISABLE_SHADING | SCAN_FLAG_DISABLE_GAMMA); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "gl843_search_strip: failed to setup for scan: %s\n", sane_strstatus (status)); return status; } /* set up for reverse or forward */ r = sanei_genesys_get_address (local_reg, REG02); if (forward) r->value &= ~REG02_MTRREV; else r->value |= REG02_MTRREV; status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL843_MAX_REGS); if (status != SANE_STATUS_GOOD) { free(data); DBG (DBG_error, "gl843_search_strip: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } status = gl843_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_strip: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } status = gl843_stop_action (dev); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_strip: gl843_stop_action failed\n"); return status; } pass = 0; if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s_%s%02d.pnm", black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass); sanei_genesys_write_pnm_file (title, data, depth, channels, pixels, lines); } /* loop until strip is found or maximum pass number done */ found = 0; while (pass < 20 && !found) { status = dev->model->cmd_set->bulk_write_register (dev, local_reg, GENESYS_GL843_MAX_REGS); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "gl843_search_strip: failed to bulk write registers: %s\n", sane_strstatus (status)); return status; } /* now start scan */ status = gl843_begin_scan (dev, local_reg, SANE_TRUE); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_strip: failed to begin scan: %s\n", sane_strstatus (status)); return status; } /* waits for valid data */ do sanei_genesys_test_buffer_empty (dev, &steps); while (steps); /* now we're on target, we can read data */ status = sanei_genesys_read_data_from_scanner (dev, data, size); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_start_position: failed to read data: %s\n", sane_strstatus (status)); return status; } status = gl843_stop_action (dev); if (status != SANE_STATUS_GOOD) { free (data); DBG (DBG_error, "gl843_search_strip: gl843_stop_action failed\n"); return status; } if (DBG_LEVEL >= DBG_data) { sprintf (title, "search_strip_%s_%s%02d.pnm", black ? "black" : "white", forward ? "fwd" : "bwd", (int)pass); sanei_genesys_write_pnm_file (title, data, depth, channels, pixels, lines); } /* search data to find black strip */ /* when searching forward, we only need one line of the searched color since we * will scan forward. But when doing backward search, we need all the area of the * same color */ if (forward) { for (y = 0; y < lines && !found; y++) { count = 0; /* count of white/black pixels depending on the color searched */ for (x = 0; x < pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * pixels + x] > 90) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * pixels + x] < 60) { count++; } } /* at end of line, if count >= 3%, line is not fully of the desired color * so we must go to next line of the buffer */ /* count*100/pixels < 3 */ if ((count * 100) / pixels < 3) { found = 1; DBG (DBG_data, "gl843_search_strip: strip found forward during pass %d at line %d\n", pass, y); } else { DBG (DBG_data, "gl843_search_strip: pixels=%d, count=%d (%d%%)\n", pixels, count, (100 * count) / pixels); } } } else /* since calibration scans are done forward, we need the whole area to be of the required color when searching backward */ { count = 0; for (y = 0; y < lines; y++) { /* count of white/black pixels depending on the color searched */ for (x = 0; x < pixels; x++) { /* when searching for black, detect white pixels */ if (black && data[y * pixels + x] > 90) { count++; } /* when searching for white, detect black pixels */ if (!black && data[y * pixels + x] < 60) { count++; } } } /* at end of area, if count >= 3%, area is not fully of the desired color * so we must go to next buffer */ if ((count * 100) / (pixels * lines) < 3) { found = 1; DBG (DBG_data, "gl843_search_strip: strip found backward during pass %d \n", pass); } else { DBG (DBG_data, "gl843_search_strip: pixels=%d, count=%d (%d%%)\n", pixels, count, (100 * count) / pixels); } } pass++; } free (data); if (found) { status = SANE_STATUS_GOOD; DBG (DBG_info, "gl843_search_strip: %s strip found\n", black ? "black" : "white"); } else { status = SANE_STATUS_UNSUPPORTED; DBG (DBG_info, "gl843_search_strip: %s strip not found\n", black ? "black" : "white"); } DBG (DBG_proc, "gl843_search_strip: completed\n"); return status; } /** * Send shading calibration data. The buffer is considered to always hold values * for all the channels. */ #ifndef UNIT_TESTING static #endif SANE_Status gl843_send_shading_data (Genesys_Device * dev, uint8_t * data, int size) { SANE_Status status; uint32_t final_size, length, i; uint8_t *final_data; uint8_t *buffer; int count,offset; unsigned int tgtime; unsigned int cksel; Genesys_Register_Set *r; uint16_t dpiset, strpixel, endpixel, startx, factor; DBGSTART; offset=0; length=size; r = sanei_genesys_get_address (dev->reg, REG01); if(r->value & REG01_SHDAREA) { /* recompute STRPIXEL used shading calibration so we can * compute offset within data for SHDAREA case */ r = sanei_genesys_get_address (dev->reg, REG18); cksel= (r->value & REG18_CKSEL)+1; sanei_genesys_get_double(dev->reg,REG_DPISET,&strpixel); tgtime=1; sanei_genesys_get_double(dev->reg,REG_DPISET,&dpiset); factor=dev->sensor.optical_res/sanei_genesys_compute_dpihw(dev,dpiset); if (dev->model->ccd_type == CCD_G4050 && dpiset>2400) { tgtime=2; } /* start coordinate in optical dpi coordinates */ startx = ((dev->sensor.dummy_pixel * tgtime)/cksel)/factor; /* current scan coordinates */ sanei_genesys_get_double(dev->reg,REG_STRPIXEL,&strpixel); sanei_genesys_get_double(dev->reg,REG_ENDPIXEL,&endpixel); strpixel*=tgtime; endpixel*=tgtime; /* 16 bit words, 2 words per color, 3 color channels */ offset=(strpixel-startx)*2*2*3; length=(endpixel-strpixel)*2*2*3; DBG (DBG_info, "%s: STRPIXEL=%d, ENDPIXEL=%d, startx=%d\n", __func__, strpixel, endpixel, startx); } /* compute and allocate size for final data */ final_size = ((length+251) / 252) * 256; DBG (DBG_io, "%s: final shading size=%04x (length=%d)\n", __func__, final_size, length); final_data = (uint8_t *) malloc (final_size); if(final_data==NULL) { DBG (DBG_error, "%s: failed to allocate memory for shading data\n", __func__); return SANE_STATUS_NO_MEM; } memset(final_data,0x00,final_size); /* copy regular shading data to the expected layout */ buffer = final_data; count = 0; /* loop over calibration data */ for (i = 0; i < length; i++) { buffer[count] = data[offset+i]; count++; if ((count % (256*2)) == (252*2)) { count += 4*2; } } /* send data */ status = sanei_genesys_set_buffer_address (dev, 0); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to set buffer address: %s\n", __func__, sane_strstatus (status)); free(final_data); return status; } status = dev->model->cmd_set->bulk_write_data (dev, 0x3c, final_data, count); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "%s: failed to send shading table: %s\n", __func__, sane_strstatus (status)); } free(final_data); DBGCOMPLETED; return status; } /** the gl843 command set */ static Genesys_Command_Set gl843_cmd_set = { "gl843-generic", /* the name of this set */ gl843_init, gl843_init_regs_for_warmup, gl843_init_regs_for_coarse_calibration, gl843_init_regs_for_shading, gl843_init_regs_for_scan, gl843_get_filter_bit, gl843_get_lineart_bit, gl843_get_bitset_bit, gl843_get_gain4_bit, gl843_get_fast_feed_bit, gl843_test_buffer_empty_bit, gl843_test_motor_flag_bit, gl843_bulk_full_size, gl843_set_fe, gl843_set_powersaving, gl843_save_power, gl843_set_motor_power, gl843_set_lamp_power, gl843_begin_scan, gl843_end_scan, gl843_send_gamma_table, gl843_search_start_position, gl843_offset_calibration, gl843_coarse_gain_calibration, gl843_led_calibration, gl843_slow_back_home, NULL, sanei_genesys_bulk_write_register, gl843_bulk_write_data, gl843_bulk_read_data, gl843_update_hardware_sensors, gl843_load_document, gl843_detect_document_end, gl843_eject_document, gl843_search_strip, sanei_genesys_is_compatible_calibration, gl843_move_to_ta, gl843_send_shading_data, gl843_calculate_current_setup, gl843_boot, NULL }; SANE_Status sanei_gl843_init_cmd_set (Genesys_Device * dev) { dev->model->cmd_set = &gl843_cmd_set; return SANE_STATUS_GOOD; } /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/hp5400_xfer.h0000664000175000017500000000637212112021330014717 00000000000000#ifndef _HP5400_XFER_H_ #define _HP5400_XFER_H_ /* sane - Scanner Access Now Easy. Copyright (C) 2003 Martijn van Oosterhout Copyright (C) 2003 Thomas Soumarmon Originally copied from HP3300 testtools. Original notice follows: Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Transport layer for communication with HP5400/5470 scanner. Add support for bulk transport of data - 19/02/2003 Martijn */ #include HP5400_SANE_STATIC int hp5400_open (const char *filename); HP5400_SANE_STATIC void hp5400_close (int iHandle); HP5400_SANE_STATIC int hp5400_command_verify (int iHandle, int iCmd); HP5400_SANE_STATIC int hp5400_command_read (int iHandle, int iCmd, int iLen, void *pbData); HP5400_SANE_STATIC int hp5400_command_read_noverify (int iHandle, int iCmd, int iLen, void *pbData); HP5400_SANE_STATIC int hp5400_command_write (int iHandle, int iCmd, int iLen, void *pbData); HP5400_SANE_STATIC void hp5400_command_write_noverify (int fd, int iValue, void *pabData, int iSize); #ifdef STANDALONE HP5400_SANE_STATIC int hp5400_bulk_read (int iHandle, size_t size, int block, FILE * file); #endif HP5400_SANE_STATIC int hp5400_bulk_read_block (int iHandle, int iCmd, void *cmd, int cmdlen, void *buffer, int len); HP5400_SANE_STATIC int hp5400_bulk_command_write (int iHandle, int iCmd, void *cmd, int cmdlen, int len, int block, char *data); #ifdef STANDALONE HP5400_SANE_STATIC int hp5400_isOn (int iHandle); #endif #endif sane-backends-1.0.27/backend/pie-scsidef.h0000664000175000017500000003641212112021330015144 00000000000000/* ----------------------------------------------------------------------------- */ /* sane - Scanner Access Now Easy. pie-scsidef.h: scsi-definiton header file for PIE scanner driver. Copyright (C) 2000 Simon Munton, based on the umax-scsidef.h by Oliver Rauch & Michael Johnson This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* --------------------------------------------------------------------------------------------------------- */ #ifndef PIE_SCSIDEF_H #define PIE_SCSIDEF_H /* --------------------------------------------------------------------------------------------------------- */ /* I'm using functions derived from Eric Youngdale's scsiinfo * program here for dealing with parts of SCSI commands. */ static inline void setbitfield(unsigned char * pageaddr, int mask, int shift, int val) { *pageaddr = (*pageaddr & ~(mask << shift)) | ((val & mask) << shift); } static inline void resetbitfield(unsigned char * pageaddr, int mask, int shift, int val) { *pageaddr = (*pageaddr & ~(mask << shift)) | (((!val) & mask) << shift); } static inline int getbitfield(unsigned char * pageaddr, int mask, int shift) { return ((*pageaddr >> shift) & mask); } /* ------------------------------------------------------------------------- */ static inline int getnbyte(unsigned char * pnt, int nbytes) { unsigned int result = 0; int i; for(i=0; i= 0; i--) result = (result << 8) | (pnt[i] & 0xff); return result; } /* ------------------------------------------------------------------------- */ static inline void putnbyte(unsigned char * pnt, unsigned int value, unsigned int nbytes) { int i; for(i=nbytes-1; i>= 0; i--) { pnt[i] = value & 0xff; value = value >> 8; } } /* ------------------------------------------------------------------------- */ static inline void putnbyte1(unsigned char * pnt, unsigned int value, unsigned int nbytes) { unsigned int i; for(i=0; i< nbytes; i++) { pnt[i] = value & 0xff; value = value >> 8; } } /* --------------------------------------------------------------------------------------------------------- */ /* Not all of these are defined in scsi.h, so we'll make sure * we agree about them here... */ #define TEST_UNIT_READY 0x00 #define REQUEST_SENSE 0x03 #define INQUIRY 0x12 #define RESERVE_UNIT 0x16 #define RELEASE_UNIT 0x17 #define SCAN 0x1B #define READ 0x08 #define WRITE 0x0A #define PARAM 0x0F #define MODE 0x15 /* --------------------------------------------------------------------------------------------------------- */ #define STD_WDB_LEN 0x28 /* wdb_len if nothing is set by inquiry */ /* --------------------------------------------------------------------------------------------------------- */ /* SCSI commands */ typedef struct { unsigned char *cmd; size_t size; } scsiblk; /* --------------------------------------------------------------------------------------------------------- */ #define set_inquiry_return_size(icb,val) icb[0x04]=val static unsigned char inquiryC[] = { INQUIRY, 0x00, 0x00, 0x00, 0x7c, 0x00 }; static scsiblk inquiry = { inquiryC, sizeof(inquiryC) }; /* --------------------------------------------------------------------------------------------------------- */ #define get_inquiry_periph_qual(in) getbitfield(in, 0x07, 5) # define IN_periph_qual_lun 0x00 # define IN_periph_qual_nolun 0x03 #define get_inquiry_periph_devtype(in) getbitfield(in, 0x1f, 0) # define IN_periph_devtype_scanner 0x06 # define IN_periph_devtype_unknown 0x1f #define get_inquiry_rmb(in) getbitfield(in + 0x01, 0x01, 7) #define get_inquiry_0x01_bit6(in) getbitfield(in + 0x01, 0x01, 6) #define get_inquiry_0x01_bit5(in) getbitfield(in + 0x01, 0x01, 5) #define get_inquiry_iso_version(in) getbitfield(in + 0x02, 0x03, 6) #define get_inquiry_ecma_version(in) getbitfield(in + 0x02, 0x07, 3) #define get_inquiry_ansi_version(in) getbitfield(in + 0x02, 0x07, 0) #define get_inquiry_aenc(in) getbitfield(in + 0x03, 0x01, 7) #define get_inquiry_tmiop(in) getbitfield(in + 0x03, 0x01, 6) #define get_inquiry_0x03_bit5(in) getbitfield(in + 0x03, 0x01, 5) #define get_inquiry_0x03_bit4(in) getbitfield(in + 0x03, 0x01, 4) #define get_inquiry_response_format(in) getbitfield(in + 0x03, 0x0f, 0) # define IN_recognized 0x02 #define get_inquiry_additional_length(in) in[0x04] #define set_inquiry_length(out,n) out[0x04]=n-5 #define get_inquiry_vendor(in, buf) strncpy(buf, in + 0x08, 0x08) #define get_inquiry_product(in, buf) strncpy(buf, in + 0x10, 0x010) #define get_inquiry_version(in, buf) strncpy(buf, in + 0x20, 0x04) #define get_inquiry_max_x_res(in) getnbyte1(in + 0x24, 2) #define get_inquiry_max_y_res(in) getnbyte1(in + 0x26, 2) #define get_inquiry_fb_max_scan_width(in) getnbyte1(in + 0x28, 2) #define get_inquiry_fb_max_scan_length(in) getnbyte1(in + 0x2a, 2) #define get_inquiry_filters(in) in[0x2c] #define get_inquiry_color_depths(in) in[0x2d] #define get_inquiry_color_format(in) in[0x2e] #define get_inquiry_image_format(in) in[0x30] #define get_inquiry_scan_capability(in) in[0x31] #define get_inquiry_optional_devices(in) in[0x32] #define get_inquiry_enhancements(in) in[0x33] #define get_inquiry_gamma_bits(in) in[0x34] #define get_inquiry_last_filter(in) in[0x35] #define get_inquiry_fast_preview_res(in) getnbyte1(in + 0x36, 2) #define get_inquiry_halftones(in) in[0x60] #define get_inquiry_halftone_max_width(in) in[0x61] #define get_inquiry_halftone_max_heighgt(in) in[0x62] #define get_inquiry_max_windows(in) in[0x63] #define get_inquiry_min_highlight(in) in[0x65] #define get_inquiry_max_shadow(in) in[0x66] #define get_inquiry_cal_eqn(in) in[0x67] #define get_inquiry_max_exp(in) getnbyte1(in + 0x68, 2) #define get_inquiry_min_exp(in) getnbyte1(in + 0x6a, 2) #define get_inquiry_trans_x1(in) getnbyte1(in + 0x6c, 2) #define get_inquiry_trans_y1(in) getnbyte1(in + 0x6e, 2) #define get_inquiry_trans_x2(in) getnbyte1(in + 0x70, 2) #define get_inquiry_trans_y2(in) getnbyte1(in + 0x72, 2) #define INQ_ONE_PASS_COLOR 0x80 #define INQ_FILTER_BLUE 0x08 #define INQ_FILTER_GREEN 0x04 #define INQ_FILTER_RED 0x02 #define INQ_FILTER_NEUTRAL 0x01 #define INQ_COLOR_DEPTH_16 0x20 #define INQ_COLOR_DEPTH_12 0x10 #define INQ_COLOR_DEPTH_10 0x08 #define INQ_COLOR_DEPTH_8 0x04 #define INQ_COLOR_DEPTH_4 0x02 #define INQ_COLOR_DEPTH_1 0x01 #define INQ_COLOR_FORMAT_INDEX 0x04 #define INQ_COLOR_FORMAT_LINE 0x02 #define INQ_COLOR_FORMAT_PIXEL 0x01 #define INQ_IMG_FMT_OKLINE 0x08 #define INQ_IMG_FMT_BLK_ONE 0x04 #define INQ_IMG_FMT_MOTOROLA 0x02 #define INQ_IMG_FMT_INTEL 0x01 #define INQ_CAP_PWRSAV 0x80 #define INQ_CAP_EXT_CAL 0x40 #define INQ_CAP_FAST_PREVIEW 0x10 #define INQ_CAP_DISABLE_CAL 0x08 #define INQ_CAP_SPEEDS 0x07 #define INQ_OPT_DEV_MPCL 0x80 #define INQ_OPT_DEV_TP1 0x04 #define INQ_OPT_DEV_TP 0x02 #define INQ_OPT_DEV_ADF 0x01 #define INQ_ENHANCE_EDGE 0x02 #define INQ_LAST_FILTER_BLUE 0x08 #define INQ_LAST_FILTER_GREEN 0x04 #define INQ_LAST_FILTER_RED 0x02 #define INQ_LAST_FILTER_NEUTRAL 0x01 #define INQ_DWNLD_HALFTONE 0x80 #define INQ_NUM_HALFTONES 0x7f /* --------------------------------------------------------------------------------------------------------- */ static unsigned char test_unit_readyC[] = { TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk test_unit_ready = { test_unit_readyC,sizeof(test_unit_readyC) }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char reserve_unitC[] = { RESERVE_UNIT, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk reserve_unit = { reserve_unitC, sizeof(reserve_unitC) }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char release_unitC[] = { RELEASE_UNIT, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk release_unit = { release_unitC, sizeof(release_unitC) }; /* --------------------------------------------------------------------------------------------------------- */ static unsigned char paramC[] = { PARAM, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk param = { paramC, sizeof(paramC) }; #define set_param_length(in, l) putnbyte(in + 3, (l), 2) #define get_param_scan_width(b) getnbyte1(b, 2) #define get_param_scan_lines(b) getnbyte1(b + 2, 2) #define get_param_scan_bytes(b) getnbyte1(b + 4, 2) #define get_param_scan_filter_offset1(b) b[6] #define get_param_scan_filter_offset2(b) b[7] #define get_param_scan_period(b) getnbyte1(b + 8, 4) #define get_param_scsi_xfer_rate(b) getnbyte1(b + 12, 2) #define get_param_scan_available_lines(b) getnbyte1(b + 14, 2) /* --------------------------------------------------------------------------------------------------------- */ static unsigned char writeC[] = { WRITE, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk swrite = { writeC, sizeof(writeC) }; #define set_write_length(in, l) putnbyte(in + 2, (l), 3) /* --------------------------------------------------------------------------------------------------------- */ static unsigned char modeC[] = { MODE, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk smode = { modeC, sizeof(modeC) }; #define set_mode_length(in, l) putnbyte(in + 3, (l), 2) /* --------------------------------------------------------------------------------------------------------- */ static unsigned char scanC[] = { SCAN, 0x00, 0x00, 0x00, 0x01, 0x00 }; static scsiblk scan = { scanC, sizeof(scanC) }; #define set_scan_cmd(in, l) in[4] = l /* --------------------------------------------------------------------------------------------------------- */ /* sread instead of read because read is a libc primitive */ static unsigned char sreadC[] = { READ, 0x00, 0x00, 0x00, 0x00, 0x00 }; static scsiblk sread = { sreadC, sizeof(sreadC) }; #define set_read_length(in, l) putnbyte(in + 2, (l), 3) /* --------------------------------------------------------------------------------------------------------- */ #if 0 static unsigned char request_senseC[] = { REQUEST_SENSE, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define set_RS_allocation_length(sb,val) sb[0x04]=val #define set_RS_LUN(sb,val) setbitfield(sb + 0x01, 7, 5) /* ??? */ static scsiblk request_sense = { request_senseC, sizeof(request_senseC) }; #endif /* defines for request sense return block */ #define get_RS_information_valid(b) getbitfield(b + 0x00, 1, 7) #define get_RS_error_code(b) getbitfield(b + 0x00, 0x7f, 0) #define get_RS_filemark(b) getbitfield(b + 0x02, 1, 7) #define get_RS_EOM(b) getbitfield(b + 0x02, 1, 6) #define get_RS_ILI(b) getbitfield(b + 0x02, 1, 5) #define get_RS_sense_key(b) getbitfield(b + 0x02, 0x0f, 0) #define get_RS_information(b) getnbyte(b+0x03, 4) #define get_RS_additional_length(b) b[0x07] #define get_RS_ASC(b) b[0x0c] #define get_RS_ASCQ(b) b[0x0d] #define get_RS_SKSV(b) getbitfield(b+0x0f,1,7) /* valid */ #define get_RS_CD(b) getbitfield(b+0x0f,1,6) /* 1=CDB */ #define get_RS_field_pointer(b) getnbyte(b+0x10, 2) #define get_RS_additional_sense(b) getnbyte(b+0x12, 2) #define rs_return_block_size 0x1f /* --------------------------------------------------------------------------------------------------------- */ static char *sense_str[] = {"NO SENSE", "RECOVERED ERROR", "NOT READY", "MEDIUM ERROR", "HARDWARE ERROR", "ILLEGAL REQUEST", "UNIT ATTENTION", "DATA PROTECT", "BLANK CHECK", "VENDOR SPECIFIC", "COPY ABORTED", "ABORTED COMMAND", "EQUAL", "VOLUME OVERFLOW", "MISCOMPARE", "??? - SENSE 0FH" }; /* --------------------------------------------------------------------------------------------------------- */ /* command codes used in the data part of a SCSI write command */ #define SET_POWER_SAVE_CONTROL 0x01 #define DWNLD_GAMMA_TABLE 0x10 #define DWNLD_HALFTONE 0x11 #define SET_SCAN_FRAME 0x12 #define SET_EXP_TIME 0x13 #define SET_HIGHLIGHT_SHADOW 0x14 #define SEND_CAL_DATA 0x16 #define READ_POWER_SAVE_CONTROL 0x81 #define READ_GAMMA_TABLE 0x90 #define READ_HALFTONE 0x91 #define READ_SCAN_FRAME 0x92 #define READ_EXP_TIME 0x93 #define READ_HIGHLIGHT_SHADOW 0x94 #define READ_CAL_INFO 0x95 #define set_command(in, cmd) putnbyte1(in, cmd, 2) #define set_data_length(in, len) putnbyte1(in + 2, len, 2) #define set_data(in, ofs, val, num) putnbyte1(in + ofs, val, num) #define FILTER_BLUE 0x08 #define FILTER_GREEN 0x04 #define FILTER_RED 0x02 #define FILTER_NEUTRAL 0x01 #endif sane-backends-1.0.27/backend/pixma_imageclass.c0000664000175000017500000007162413106201017016264 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2007-2009 Nicolas Martin, Copyright (C) 2008 Dennis Lou, dlou 99 at yahoo dot com This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* * imageCLASS backend based on pixma_mp730.c */ #include "../include/sane/config.h" #include #include #include #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" #ifdef __GNUC__ # define UNUSED(v) (void) v #else # define UNUSED(v) #endif #define IMAGE_BLOCK_SIZE (0x80000) #define MAX_CHUNK_SIZE (0x1000) #define MIN_CHUNK_SIZE (0x0200) #define CMDBUF_SIZE 512 #define MF4100_PID 0x26a3 #define MF4600_PID 0x26b0 #define MF4010_PID 0x26b4 #define MF4200_PID 0x26b5 #define MF4360_PID 0x26ec #define D480_PID 0x26ed #define MF4320_PID 0x26ee #define D420_PID 0x26ef #define MF3200_PID 0x2684 #define MF6500_PID 0x2686 /* generation 2 scanners (>=0x2707) */ #define MF8300_PID 0x2708 #define MF4500_PID 0x2736 #define MF4410_PID 0x2737 #define MF3010_PID 0x2759 #define MF4570_PID 0x275a #define MF4800_PID 0x2773 #define MF4700_PID 0x2774 #define MF8200_PID 0x2779 /* the following are all untested */ #define MF5630_PID 0x264e #define MF5650_PID 0x264f #define MF8100_PID 0x2659 #define MF5880_PID 0x26f9 #define MF6680_PID 0x26fa #define MF8030_PID 0x2707 #define IR1133_PID 0x2742 #define MF5900_PID 0x2743 #define D530_PID 0x2775 #define MF8500_PID 0x277a #define MF6100_PID 0x278e #define MF820_PID 0x27a6 #define MF220_PID 0x27a8 #define MF210_PID 0x27a9 #define MF230_PID 0x27d1 #define MF240_PID 0x27d2 enum iclass_state_t { state_idle, state_warmup, /* MF4200 always warm/calibrated; others? */ state_scanning, state_finished }; enum iclass_cmd_t { cmd_start_session = 0xdb20, cmd_select_source = 0xdd20, cmd_scan_param = 0xde20, cmd_status = 0xf320, cmd_abort_session = 0xef20, cmd_read_image = 0xd420, cmd_read_image2 = 0xd460, /* New multifunctionals, such as MF4410 */ cmd_error_info = 0xff20, cmd_activate = 0xcf60 }; typedef struct iclass_t { enum iclass_state_t state; pixma_cmdbuf_t cb; unsigned raw_width; uint8_t current_status[12]; uint8_t *buf, *blkptr, *lineptr; unsigned buf_len, blk_len; unsigned last_block; uint8_t generation; /* New multifunctionals are (generation == 2) */ uint8_t adf_state; /* handle adf scanning */ } iclass_t; static int is_scanning_from_adf (pixma_t * s) { return (s->param->source == PIXMA_SOURCE_ADF || s->param->source == PIXMA_SOURCE_ADFDUP); } static int is_scanning_from_adfdup (pixma_t * s) { return (s->param->source == PIXMA_SOURCE_ADFDUP); } static void iclass_finish_scan (pixma_t * s); /* checksumming is sometimes different than pixmas */ static int iclass_exec (pixma_t * s, pixma_cmdbuf_t * cb, char invcksum) { if (cb->cmdlen > cb->cmd_header_len) pixma_fill_checksum (cb->buf + cb->cmd_header_len, cb->buf + cb->cmdlen - 2); cb->buf[cb->cmdlen - 1] = invcksum ? -cb->buf[cb->cmdlen - 2] : 0; cb->reslen = pixma_cmd_transaction (s, cb->buf, cb->cmdlen, cb->buf, cb->expected_reslen); return pixma_check_result (cb); } static int has_paper (pixma_t * s) { iclass_t *mf = (iclass_t *) s->subdriver; return ((mf->current_status[1] & 0x0f) == 0 /* allow 0x10 as ADF paper OK */ || mf->current_status[1] == 81); /* allow 0x51 as ADF paper OK */ } static int abort_session (pixma_t * s) { iclass_t *mf = (iclass_t *) s->subdriver; return pixma_exec_short_cmd (s, &mf->cb, cmd_abort_session); } static int query_status (pixma_t * s) { iclass_t *mf = (iclass_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mf->cb, cmd_status, 0, 12); error = pixma_exec (s, &mf->cb); if (error >= 0) { memcpy (mf->current_status, data, 12); /*DBG (3, "Current status: paper=0x%02x cal=%u lamp=%u\n", data[1], data[8], data[7]);*/ PDBG (pixma_dbg (3, "Current status: paper=0x%02x cal=%u lamp=%u\n", data[1], data[8], data[7])); } return error; } static int activate (pixma_t * s, uint8_t x) { iclass_t *mf = (iclass_t *) s->subdriver; uint8_t *data = pixma_newcmd (&mf->cb, cmd_activate, 10, 0); data[0] = 1; data[3] = x; switch (s->cfg->pid) { case MF4200_PID: case MF4600_PID: case MF6500_PID: case D480_PID: case D420_PID: case MF4360_PID: case MF4100_PID: case MF8300_PID: return iclass_exec (s, &mf->cb, 1); break; default: return pixma_exec (s, &mf->cb); } } static int start_session (pixma_t * s) { iclass_t *mf = (iclass_t *) s->subdriver; return pixma_exec_short_cmd (s, &mf->cb, cmd_start_session); } static int select_source (pixma_t * s) { iclass_t *mf = (iclass_t *) s->subdriver; uint8_t *data = pixma_newcmd (&mf->cb, cmd_select_source, 10, 0); data[0] = (is_scanning_from_adf(s)) ? 2 : 1; /* special settings for MF6100 */ data[5] = is_scanning_from_adfdup(s) ? 3 : ((s->cfg->pid == MF6100_PID && s->param->source == PIXMA_SOURCE_ADF) ? 1 : 0); switch (s->cfg->pid) { case MF4200_PID: case MF4600_PID: case MF6500_PID: case D480_PID: case D420_PID: case MF4360_PID: case MF4100_PID: case MF8300_PID: return iclass_exec (s, &mf->cb, 0); break; default: return pixma_exec (s, &mf->cb); } } static int send_scan_param (pixma_t * s) { iclass_t *mf = (iclass_t *) s->subdriver; uint8_t *data; data = pixma_newcmd (&mf->cb, cmd_scan_param, 0x2e, 0); pixma_set_be16 (s->param->xdpi | 0x1000, data + 0x04); pixma_set_be16 (s->param->ydpi | 0x1000, data + 0x06); pixma_set_be32 (s->param->x, data + 0x08); pixma_set_be32 (s->param->y, data + 0x0c); pixma_set_be32 (mf->raw_width, data + 0x10); pixma_set_be32 (s->param->h, data + 0x14); data[0x18] = (s->param->channels == 1) ? 0x04 : 0x08; data[0x19] = s->param->channels * ((s->param->depth == 1) ? 8 : s->param->depth); /* bits per pixel */ data[0x1f] = 0x7f; data[0x20] = 0xff; data[0x23] = 0x81; switch (s->cfg->pid) { case MF4200_PID: case MF4600_PID: case MF6500_PID: case D480_PID: case D420_PID: case MF4360_PID: case MF4100_PID: case MF8300_PID: return iclass_exec (s, &mf->cb, 0); break; default: return pixma_exec (s, &mf->cb); } } static int request_image_block (pixma_t * s, unsigned flag, uint8_t * info, unsigned * size, uint8_t * data, unsigned * datalen) { iclass_t *mf = (iclass_t *) s->subdriver; int error; unsigned expected_len; const int hlen = 2 + 6; memset (mf->cb.buf, 0, 11); /* generation 2 scanners use cmd_read_image2. * MF6100, ... are exceptions */ pixma_set_be16 (((mf->generation >= 2 && s->cfg->pid != MF6100_PID) ? cmd_read_image2 : cmd_read_image), mf->cb.buf); mf->cb.buf[8] = flag; mf->cb.buf[10] = 0x06; expected_len = (mf->generation >= 2 || s->cfg->pid == MF4600_PID || s->cfg->pid == MF6500_PID || s->cfg->pid == MF8030_PID) ? 512 : hlen; mf->cb.reslen = pixma_cmd_transaction (s, mf->cb.buf, 11, mf->cb.buf, expected_len); if (mf->cb.reslen >= hlen) { *info = mf->cb.buf[2]; *size = pixma_get_be16 (mf->cb.buf + 6); /* 16bit size */ error = 0; if (mf->generation >= 2 || s->cfg->pid == MF4600_PID || s->cfg->pid == MF6500_PID || s->cfg->pid == MF8030_PID) { /* 32bit size */ *datalen = mf->cb.reslen - hlen; *size = (*datalen + hlen == 512) ? pixma_get_be32 (mf->cb.buf + 4) - *datalen : 0; memcpy (data, mf->cb.buf + hlen, *datalen); } PDBG (pixma_dbg (11, "*request_image_block***** size = %u *****\n", *size)); } else { error = PIXMA_EPROTO; } return error; } static int read_image_block (pixma_t * s, uint8_t * data, unsigned size) { iclass_t *mf = (iclass_t *) s->subdriver; int error; unsigned maxchunksize, chunksize, count = 0; maxchunksize = MAX_CHUNK_SIZE * ((mf->generation >= 2 || s->cfg->pid == MF4600_PID || s->cfg->pid == MF6500_PID || s->cfg->pid == MF8030_PID) ? 4 : 1); while (size) { if (size >= maxchunksize) chunksize = maxchunksize; else if (size < MIN_CHUNK_SIZE) chunksize = size; else chunksize = size - (size % MIN_CHUNK_SIZE); error = pixma_read (s->io, data, chunksize); if (error < 0) return count; count += error; data += error; size -= error; } return count; } static int read_error_info (pixma_t * s, void *buf, unsigned size) { unsigned len = 16; iclass_t *mf = (iclass_t *) s->subdriver; uint8_t *data; int error; data = pixma_newcmd (&mf->cb, cmd_error_info, 0, len); switch (s->cfg->pid) { case MF4200_PID: case MF4600_PID: case MF6500_PID: case D480_PID: case D420_PID: case MF4360_PID: case MF4100_PID: case MF8300_PID: error = iclass_exec (s, &mf->cb, 0); break; default: error = pixma_exec (s, &mf->cb); } if (error < 0) return error; if (buf && len < size) { size = len; /* NOTE: I've absolutely no idea what the returned data mean. */ memcpy (buf, data, size); error = len; } return error; } static int handle_interrupt (pixma_t * s, int timeout) { uint8_t buf[16]; int len; len = pixma_wait_interrupt (s->io, buf, sizeof (buf), timeout); if (len == PIXMA_ETIMEDOUT) return 0; if (len < 0) return len; if (len != 16) { PDBG (pixma_dbg (1, "WARNING:unexpected interrupt packet length %d\n", len)); return PIXMA_EPROTO; } if (buf[12] & 0x40) query_status (s); if (buf[15] & 1) s->events = PIXMA_EV_BUTTON1; return 1; } static int step1 (pixma_t * s) { int error; int rec_tmo; iclass_t *mf = (iclass_t *) s->subdriver; /* don't wait full timeout for 1st command */ rec_tmo = s->rec_tmo; /* save globel timeout */ s->rec_tmo = 2; /* set timeout to 2 seconds */ error = query_status (s); s->rec_tmo = rec_tmo; /* restore global timeout */ if (error < 0) { PDBG (pixma_dbg (1, "WARNING: Resend first USB command after timeout!\n")); error = query_status (s); } if (error < 0) return error; /* wait for inserted paper */ if (s->param->adf_wait != 0 && is_scanning_from_adf(s)) { int tmo = s->param->adf_wait; while (!has_paper (s) && --tmo >= 0 && !s->param->frontend_cancel) { if ((error = query_status (s)) < 0) return error; pixma_sleep (1000000); PDBG (pixma_dbg(2, "No paper in ADF. Timed out in %d sec.\n", tmo)); } /* canceled from frontend */ if (s->param->frontend_cancel) { return PIXMA_ECANCELED; } } /* no paper inserted * => abort session */ if (is_scanning_from_adf(s) && !has_paper (s)) { return PIXMA_ENO_PAPER; } /* activate only seen for generation 1 scanners */ if (mf->generation == 1) { if (error >= 0) error = activate (s, 0); if (error >= 0) error = activate (s, 4); } return error; } /* line in=rrr... ggg... bbb... line out=rgbrgbrgb... */ static void pack_rgb (const uint8_t * src, unsigned nlines, unsigned w, uint8_t * dst) { unsigned w2, stride; w2 = 2 * w; stride = 3 * w; for (; nlines != 0; nlines--) { unsigned x; for (x = 0; x != w; x++) { *dst++ = src[x + 0]; *dst++ = src[x + w]; *dst++ = src[x + w2]; } src += stride; } } static int iclass_open (pixma_t * s) { iclass_t *mf; uint8_t *buf; mf = (iclass_t *) calloc (1, sizeof (*mf)); if (!mf) return PIXMA_ENOMEM; buf = (uint8_t *) malloc (CMDBUF_SIZE); if (!buf) { free (mf); return PIXMA_ENOMEM; } s->subdriver = mf; mf->state = state_idle; mf->cb.buf = buf; mf->cb.size = CMDBUF_SIZE; mf->cb.res_header_len = 2; mf->cb.cmd_header_len = 10; mf->cb.cmd_len_field_ofs = 7; /* adf scanning */ mf->adf_state = state_idle; /* set generation = 2 for new multifunctionals */ mf->generation = (s->cfg->pid >= MF8030_PID) ? 2 : 1; PDBG (pixma_dbg (3, "*iclass_open***** This is a generation %d scanner. *****\n", mf->generation)); PDBG (pixma_dbg (3, "Trying to clear the interrupt buffer...\n")); if (handle_interrupt (s, 200) == 0) { PDBG (pixma_dbg (3, " no packets in buffer\n")); } return 0; } static void iclass_close (pixma_t * s) { iclass_t *mf = (iclass_t *) s->subdriver; iclass_finish_scan (s); free (mf->cb.buf); free (mf->buf); free (mf); s->subdriver = NULL; } static int iclass_check_param (pixma_t * s, pixma_scan_param_t * sp) { UNUSED (s); /* PDBG (pixma_dbg (4, "*iclass_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, line_size=%" PRIu64 " , h=%u*****\n", sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->line_size, sp->h)); */ sp->depth = 8; sp->software_lineart = 0; if (sp->mode == PIXMA_SCAN_MODE_LINEART) { sp->software_lineart = 1; sp->channels = 1; sp->depth = 1; } if (sp->software_lineart == 1) { unsigned w_max; /* for software lineart line_size and w must be a multiple of 8 */ sp->line_size = ALIGN_SUP (sp->w, 8) * sp->channels; sp->w = ALIGN_SUP (sp->w, 8); /* do not exceed the scanner capability */ w_max = s->cfg->width * s->cfg->xdpi / 75; w_max -= w_max % 32; if (sp->w > w_max) sp->w = w_max; } else sp->line_size = ALIGN_SUP (sp->w, 32) * sp->channels; /* Some exceptions here for particular devices */ /* Those devices can scan up to Legal 14" with ADF, but A4 11.7" in flatbed */ /* PIXMA_CAP_ADF also works for PIXMA_CAP_ADFDUP */ if ((s->cfg->cap & PIXMA_CAP_ADF) && sp->source == PIXMA_SOURCE_FLATBED) sp->h = MIN (sp->h, 877 * sp->xdpi / 75); /* PDBG (pixma_dbg (4, "*iclass_check_param***** Finally: channels=%u, depth=%u, x=%u, y=%u, w=%u, line_size=%" PRIu64 " , h=%u*****\n", sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->line_size, sp->h)); */ return 0; } static int iclass_scan (pixma_t * s) { int error, n; iclass_t *mf = (iclass_t *) s->subdriver; uint8_t *buf, ignore; unsigned buf_len, ignore2; if (mf->state != state_idle) return PIXMA_EBUSY; /* clear interrupt packets buffer */ while (handle_interrupt (s, 0) > 0) { } mf->raw_width = ALIGN_SUP (s->param->w, 32); PDBG (pixma_dbg (3, "raw_width = %u\n", mf->raw_width)); n = IMAGE_BLOCK_SIZE / s->param->line_size + 1; buf_len = (n + 1) * s->param->line_size + IMAGE_BLOCK_SIZE; if (buf_len > mf->buf_len) { buf = (uint8_t *) realloc (mf->buf, buf_len); if (!buf) return PIXMA_ENOMEM; mf->buf = buf; mf->buf_len = buf_len; } mf->lineptr = mf->buf; mf->blkptr = mf->buf + n * s->param->line_size; mf->blk_len = 0; error = step1 (s); if (error >= 0 && (s->param->adf_pageid == 0 || mf->generation == 1 || mf->adf_state == state_idle)) { /* single sheet or first sheet from ADF */ PDBG (pixma_dbg (3, "*iclass_scan***** start scanning *****\n")); error = start_session (s); if (error >= 0) mf->state = state_scanning; if (error >= 0) error = select_source (s); } else if (error >= 0) { /* next sheet from ADF */ PDBG (pixma_dbg (3, "*iclass_scan***** scan next sheet from ADF *****\n")); mf->state = state_scanning; } if (error >= 0) error = send_scan_param (s); if (error >= 0) error = request_image_block (s, 0, &ignore, &ignore2, &ignore, &ignore2); if (error < 0) { iclass_finish_scan (s); return error; } mf->last_block = 0; /* ADF scanning active */ if (is_scanning_from_adf (s)) mf->adf_state = state_scanning; return 0; } static int iclass_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib) { int error, n; iclass_t *mf = (iclass_t *) s->subdriver; unsigned block_size, lines_size, lineart_lines_size, first_block_size; uint8_t info; /* * 1. send a block request cmd (d4 20 00... 04 00 06) * 2. examine the response for block size and/or end-of-scan flag * 3. read the block one chunk at a time * 4. repeat until have enough to process >=1 lines */ do { do { if (s->cancel) return PIXMA_ECANCELED; if (mf->last_block) { /* end of image */ mf->state = state_finished; return 0; } first_block_size = 0; error = request_image_block (s, 4, &info, &block_size, mf->blkptr + mf->blk_len, &first_block_size); /* add current block to remainder of previous */ mf->blk_len += first_block_size; if (error < 0) { /* NOTE: seen in traffic logs but don't know the meaning. */ read_error_info (s, NULL, 0); if (error == PIXMA_ECANCELED) return error; } /* info: 0x28 = end; 0x38 = end + ADF empty */ mf->last_block = info & 0x38; if ((info & ~0x38) != 0) { PDBG (pixma_dbg (1, "WARNING: Unexpected result header\n")); PDBG (pixma_hexdump (1, &info, 1)); } if (block_size == 0) { /* no image data at this moment. */ /*pixma_sleep(100000); *//* FIXME: too short, too long? */ handle_interrupt (s, 100); } } while (block_size == 0 && first_block_size == 0); error = read_image_block (s, mf->blkptr + mf->blk_len, block_size); block_size = error; if (error < 0) return error; /* add current block to remainder of previous */ mf->blk_len += block_size; /* n = number of full lines (rows) we have in the buffer. */ n = mf->blk_len / ((s->param->mode == PIXMA_SCAN_MODE_LINEART) ? mf->raw_width : s->param->line_size); if (n != 0) { /* PDBG (pixma_dbg (4, "*iclass_fill_buffer***** Processing with n=%d, w=%i, line_size=%" PRIu64 ", raw_width=%u ***** \n", n, s->param->w, s->param->line_size, mf->raw_width)); */ /* PDBG (pixma_dbg (4, "*iclass_fill_buffer***** scan_mode=%d, lineptr=%" PRIu64 ", blkptr=%" PRIu64 " \n", s->param->mode, (uint64_t)mf->lineptr, (uint64_t)mf->blkptr)); */ /* gray to lineart convert * mf->lineptr : image line * mf->blkptr : scanned image block as grayscale * s->param->w : image width * s->param->line_size : scanned image width */ if (s->param->mode == PIXMA_SCAN_MODE_LINEART) { int i; uint8_t *sptr, *dptr; /* PDBG (pixma_dbg (4, "*iclass_fill_buffer***** Processing lineart *****\n")); */ /* process ALL lines */ sptr = mf->blkptr; dptr = mf->lineptr; for (i = 0; i < n; i++, sptr += mf->raw_width) dptr = pixma_binarize_line (s->param, dptr, sptr, s->param->line_size, 1); } else if (s->param->channels != 1 && mf->generation == 1 && s->cfg->pid != MF4600_PID && s->cfg->pid != MF6500_PID && s->cfg->pid != MF8030_PID) { /* color and not MF46xx or MF65xx */ pack_rgb (mf->blkptr, n, mf->raw_width, mf->lineptr); } else { /* grayscale */ memcpy (mf->lineptr, mf->blkptr, n * s->param->line_size); } /* cull remainder and shift left */ lineart_lines_size = n * s->param->line_size / 8; lines_size = n * ((s->param->mode == PIXMA_SCAN_MODE_LINEART) ? mf->raw_width : s->param->line_size); mf->blk_len -= lines_size; memcpy (mf->blkptr, mf->blkptr + lines_size, mf->blk_len); } } while (n == 0); /* output full lines, keep partial lines for next block * ib->rptr : start of image buffer * ib->rend : end of image buffer */ ib->rptr = mf->lineptr; ib->rend = mf->lineptr + (s->param->mode == PIXMA_SCAN_MODE_LINEART ? lineart_lines_size : lines_size); /* PDBG (pixma_dbg (4, "*iclass_fill_buffer***** rptr=%" PRIu64 ", rend=%" PRIu64 ", diff=%ld \n", (uint64_t)ib->rptr, (uint64_t)ib->rend, ib->rend - ib->rptr)); */ return ib->rend - ib->rptr; } static void iclass_finish_scan (pixma_t * s) { int error; iclass_t *mf = (iclass_t *) s->subdriver; switch (mf->state) { /* fall through */ case state_warmup: case state_scanning: error = abort_session (s); if (error < 0) PDBG (pixma_dbg (1, "WARNING:abort_session() failed %s\n", pixma_strerror (error))); /* fall through */ case state_finished: query_status (s); query_status (s); if (mf->generation == 1) { /* activate only seen for generation 1 scanners */ activate (s, 0); query_status (s); } /* generation = 1: * 0x28 = last block (no multi page scan) * generation >= 2: * 0x38 = last block and ADF empty (generation >= 2) * 0x28 = last block and Paper in ADF (multi page scan) * some generation 2 scanners don't use 0x38 for ADF empty => check status */ if (mf->last_block==0x38 /* generation 2 scanner ADF empty */ || (mf->generation == 1 && mf->last_block == 0x28) /* generation 1 scanner last block */ || (mf->generation >= 2 && !has_paper(s))) /* check status: no paper in ADF */ { /* ADFDUP scan: wait for 8sec to throw last page out of ADF feeder */ if (is_scanning_from_adfdup(s)) { PDBG (pixma_dbg (4, "*iclass_finish_scan***** sleep for 8s *****\n")); pixma_sleep(8000000); /* sleep for 8s */ query_status (s); } PDBG (pixma_dbg (3, "*iclass_finish_scan***** abort session *****\n")); abort_session (s); mf->adf_state = state_idle; mf->last_block = 0; } else PDBG (pixma_dbg (3, "*iclass_finish_scan***** wait for next page from ADF *****\n")); mf->state = state_idle; /* fall through */ case state_idle: break; } } static void iclass_wait_event (pixma_t * s, int timeout) { /* FIXME: timeout is not correct. See usbGetCompleteUrbNoIntr() for * instance. */ while (s->events == 0 && handle_interrupt (s, timeout) > 0) { } } static int iclass_get_status (pixma_t * s, pixma_device_status_t * status) { int error; error = query_status (s); if (error < 0) return error; status->hardware = PIXMA_HARDWARE_OK; status->adf = (has_paper (s)) ? PIXMA_ADF_OK : PIXMA_ADF_NO_PAPER; return 0; } static const pixma_scan_ops_t pixma_iclass_ops = { iclass_open, iclass_close, iclass_scan, iclass_fill_buffer, iclass_finish_scan, iclass_wait_event, iclass_check_param, iclass_get_status }; #define DEV(name, model, pid, dpi, adftpu_max_dpi, w, h, cap) { \ name, /* name */ \ model, /* model */ \ 0x04a9, pid, /* vid pid */ \ 1, /* iface */ \ &pixma_iclass_ops, /* ops */ \ dpi, dpi, /* xdpi, ydpi */ \ 0, /* adftpu_min_dpi not used in this subdriver */ \ adftpu_max_dpi, /* adftpu_max_dpi */ \ 0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \ w, h, /* width, height */ \ PIXMA_CAP_LINEART| /* all scanners have software lineart */ \ PIXMA_CAP_ADF_WAIT| /* adf wait for all ADF and ADFDUP scanners */ \ PIXMA_CAP_GRAY|PIXMA_CAP_EVENTS|cap \ } const pixma_config_t pixma_iclass_devices[] = { DEV ("Canon imageCLASS MF4270", "MF4270", MF4200_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon imageCLASS MF4150", "MF4100", MF4100_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon imageCLASS MF4690", "MF4690", MF4600_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon imageCLASS D420", "D420", D420_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), DEV ("Canon imageCLASS D480", "D480", D480_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), DEV ("Canon imageCLASS MF4360", "MF4360", MF4360_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), DEV ("Canon imageCLASS MF4320", "MF4320", MF4320_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon imageCLASS MF4010", "MF4010", MF4010_PID, 600, 0, 640, 877, 0), DEV ("Canon imageCLASS MF3240", "MF3240", MF3200_PID, 600, 0, 640, 877, 0), DEV ("Canon imageClass MF6500", "MF6500", MF6500_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon imageCLASS MF4410", "MF4410", MF4410_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF4500 Series", "MF4500", MF4500_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF3010", "MF3010", MF3010_PID, 600, 0, 640, 877, 0), DEV ("Canon i-SENSYS MF4700 Series", "MF4700", MF4700_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF4800 Series", "MF4800", MF4800_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon imageCLASS MF4570dw", "MF4570dw", MF4570_PID, 600, 0, 640, 877, 0), DEV ("Canon i-SENSYS MF8200C Series", "MF8200C", MF8200_PID, 600, 300, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF8300 Series", "MF8300", MF8300_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon imageCLASS D530", "D530", D530_PID, 600, 0, 640, 877, 0), /* FIXME: the following capabilities all need updating/verifying */ DEV ("Canon imageCLASS MF5630", "MF5630", MF5630_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon laserBase MF5650", "MF5650", MF5650_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon imageCLASS MF8170c", "MF8170c", MF8100_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon imageClass MF8030", "MF8030", MF8030_PID, 600, 0, 640, 877, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF5880dn", "MF5880", MF5880_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), DEV ("Canon i-SENSYS MF6680dn", "MF6680", MF6680_PID, 600, 0, 640, 877, PIXMA_CAP_ADFDUP), DEV ("Canon imageRUNNER 1133", "iR1133", IR1133_PID, 600, 0, 637, 877, PIXMA_CAP_ADFDUP), DEV ("Canon i-SENSYS MF5900 Series", "MF5900", MF5900_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP), DEV ("Canon i-SENSYS MF8500C Series", "MF8500C", MF8500_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP), DEV ("Canon i-SENSYS MF6100 Series", "MF6100", MF6100_PID, 600, 300, 640, 1050, PIXMA_CAP_ADFDUP), DEV ("Canon imageClass MF810/820", "MF810/820", MF820_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP), DEV ("Canon i-SENSYS MF220 Series", "MF220", MF220_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP), DEV ("Canon i-SENSYS MF210 Series", "MF210", MF210_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF230 Series", "MF230", MF230_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV ("Canon i-SENSYS MF240 Series", "MF240", MF240_PID, 600, 0, 640, 1050, PIXMA_CAP_ADF), DEV (NULL, NULL, 0, 0, 0, 0, 0, 0) }; sane-backends-1.0.27/backend/microtek.conf.in0000664000175000017500000000041412112021330015662 00000000000000# Uncomment following line to disable "real calibration" routines... #norealcal # Uncomment following line to disable "clever precalibration" routines... #noprecal # Using "norealcal" will revert backend to pre-0.11.0 calibration code. scsi * * Scanner /dev/scanner sane-backends-1.0.27/backend/epsonds-jpeg.h0000664000175000017500000000116612775312261015372 00000000000000/* * epsonds.c - Epson ESC/I-2 driver, JPEG support. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ SANE_Status eds_jpeg_start(epsonds_scanner *s); void eds_jpeg_finish(epsonds_scanner *s); SANE_Status eds_jpeg_read_header(epsonds_scanner *s); void eds_jpeg_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length); sane-backends-1.0.27/backend/hp.conf.in0000664000175000017500000000076112112021330014461 00000000000000scsi HP # Uncomment the following if you have "Error during device I/O" on SCSI # option dumb-read # # The usual place for a SCSI-scanner on Linux /dev/scanner # # USB-scanners supported by the hp-backend # HP ScanJet 4100C usb 0x03f0 0x0101 # HP ScanJet 5200C usb 0x03f0 0x0401 # HP ScanJet 62X0C usb 0x03f0 0x0201 # HP ScanJet 63X0C usb 0x03f0 0x0601 # # Uncomment the following if your scanner is connected by USB, # but you are not using libusb # /dev/usb/scanner0 # option connect-device sane-backends-1.0.27/backend/kvs1025_usb.h0000664000175000017500000000121712112021330014730 00000000000000/* Copyright (C) 2008, Panasonic Russia Ltd. */ /* sane - Scanner Access Now Easy. Panasonic KV-S1020C / KV-S1025C USB scanners. */ #ifndef __KVS1025_USB_H #define __KVS1025_USB_H #include "kvs1025_cmds.h" SANE_Status kv_usb_enum_devices (void); SANE_Status kv_usb_open (PKV_DEV dev); SANE_Bool kv_usb_already_open (PKV_DEV dev); void kv_usb_close (PKV_DEV dev); void kv_usb_cleanup (void); SANE_Status kv_usb_escape (PKV_DEV dev, PKV_CMD_HEADER header, unsigned char *status_byte); SANE_Status kv_usb_send_command (PKV_DEV dev, PKV_CMD_HEADER header, PKV_CMD_RESPONSE response); #endif /* #ifndef __KVS1025_USB_H */ sane-backends-1.0.27/backend/gt68xx_low.h0000664000175000017500000010775212775312261015035 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov Copyright (C) 2002 - 2007 Henning Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GT68XX_LOW_H #define GT68XX_LOW_H /** @file * @brief Low-level scanner interface functions. */ #include "../include/sane/sane.h" #include #ifdef USE_FORK #include #include "gt68xx_shm_channel.h" #endif #ifdef NDEBUG #undef MAX_DEBUG #endif /* calculate the minimum/maximum values */ #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) /* return the lower/upper 8 bits of a 16 bit word */ #define HIBYTE(w) ((SANE_Byte)(((SANE_Word)(w) >> 8) & 0xFF)) #define LOBYTE(w) ((SANE_Byte)(w)) /* return if an error occured while the function was called */ #ifdef MAX_DEBUG # define RIE(function) \ do \ { \ status = function; \ if (status != SANE_STATUS_GOOD) \ { \ DBG (7, "%s: %s: %s\n", __func__, STRINGIFY(function), \ sane_strstatus (status)); \ return status; \ } \ } \ while (SANE_FALSE) #else # define RIE(function) \ do { status = function; \ if (status != SANE_STATUS_GOOD) return status; \ } while (SANE_FALSE) #endif /* Flags */ #define GT68XX_FLAG_MIRROR_X (1 << 0) /* CIS unit mounted the other way round? */ #define GT68XX_FLAG_MOTOR_HOME (1 << 1) /* Use motor_home command (0x34) */ #define GT68XX_FLAG_OFFSET_INV (1 << 2) /* Offset control is inverted */ #define GT68XX_FLAG_UNTESTED (1 << 3) /* Print a warning for these scanners */ #define GT68XX_FLAG_SE_2400 (1 << 4) /* Special quirks for SE 2400USB */ #define GT68XX_FLAG_NO_STOP (1 << 5) /* Don't call stop_scan before the scan */ #define GT68XX_FLAG_CIS_LAMP (1 << 6) /* CIS sensor with lamp */ #define GT68XX_FLAG_NO_POWER_STATUS (1 << 7) /* get_power_status_doesn't work */ #define GT68XX_FLAG_NO_LINEMODE (1 << 8) /* Linemode does not work with this scanner */ #define GT68XX_FLAG_SCAN_FROM_HOME (1 << 9) /* Move home after calibration */ #define GT68XX_FLAG_USE_OPTICAL_X (1 << 10) /* Use optical xdpi for 50 dpi and below */ #define GT68XX_FLAG_ALWAYS_LINEMODE (1 << 11) /* Linemode must be used for any resolution */ #define GT68XX_FLAG_SHEET_FED (1 << 12) /* we have a sheet fed scanner */ #define GT68XX_FLAG_HAS_CALIBRATE (1 << 13) /* for sheet fed scanners that be calibrated with an calibration sheet */ /* Forward typedefs */ typedef struct GT68xx_USB_Device_Entry GT68xx_USB_Device_Entry; typedef struct GT68xx_Command_Set GT68xx_Command_Set; typedef struct GT68xx_Model GT68xx_Model; typedef struct GT68xx_Device GT68xx_Device; typedef struct GT68xx_Scan_Request GT68xx_Scan_Request; typedef struct GT68xx_Scan_Parameters GT68xx_Scan_Parameters; typedef struct GT68xx_AFE_Parameters GT68xx_AFE_Parameters; typedef struct GT68xx_Exposure_Parameters GT68xx_Exposure_Parameters; typedef enum GT68xx_Color_Order { COLOR_ORDER_RGB, COLOR_ORDER_BGR } GT68xx_Color_Order; #define GT68XX_COLOR_RED SANE_I18N ("Red") #define GT68XX_COLOR_GREEN SANE_I18N ("Green") #define GT68XX_COLOR_BLUE SANE_I18N ("Blue") /** Scan action code (purpose of the scan). * * The scan action code affects various scanning mode fields in the setup * command. */ typedef enum GT68xx_Scan_Action { SA_CALIBRATE, /**< Calibration scan, no offsets, no LD correction */ SA_CALIBRATE_ONE_LINE, /**< Same, but only one line for auto AFE */ SA_SCAN /**< Normal scan */ } GT68xx_Scan_Action; /** USB device list entry. */ struct GT68xx_USB_Device_Entry { SANE_Word vendor; /**< USB vendor identifier */ SANE_Word product; /**< USB product identifier */ GT68xx_Model *model; /**< Scanner model information */ }; #define MAX_SCANNERS 50 /* Looks like gcc doesn't like declarations without specificating the number of array elements at least when --enable-warnings is active */ /** List of all supported devices. * * This is an array of GT68xx_USB_Device_Entry structures which describe * USB devices supported by this backend. The array is terminated by an * entry with model = NULL. * */ static GT68xx_USB_Device_Entry gt68xx_usb_device_list[MAX_SCANNERS]; /** GT68xx analog front-end (AFE) parameters. */ struct GT68xx_AFE_Parameters { SANE_Byte r_offset; /**< Red channel offset */ SANE_Byte r_pga; /**< Red channel PGA gain */ SANE_Byte g_offset; /**< Green channel offset (also used for mono) */ SANE_Byte g_pga; /**< Green channel PGA gain (also used for mono) */ SANE_Byte b_offset; /**< Blue channel offset */ SANE_Byte b_pga; /**< Blue channel PGA gain */ }; /** GT68xx exposure time parameters. */ struct GT68xx_Exposure_Parameters { SANE_Int r_time; /**< Red exposure time */ SANE_Int g_time; /**< Red exposure time */ SANE_Int b_time; /**< Red exposure time */ }; /** * Scanner command set description. * * This description contains parts which are common to all scanners with the * same command set, but may have different optical resolution and other * parameters. */ struct GT68xx_Command_Set { /** @name Identification */ /*@{ */ /** Name of this command set */ SANE_String_Const name; /*@} */ /** @name USB request parameters * * These values are used in the USB control transfer parameters (wValue and * wIndex fields, as in the USB specification). */ /*@{ */ SANE_Byte request_type; /**< Request type (should be 0x40, vendor spec) */ SANE_Byte request; /**< Vendor spec resquest (0x01 or 0x04) */ SANE_Word memory_read_value; /**< Memory read - wValue */ SANE_Word memory_write_value; /**< Memory write - wValue */ SANE_Word send_cmd_value; /**< Send normal command - wValue */ SANE_Word send_cmd_index; /**< Send normal command - wIndex */ SANE_Word recv_res_value; /**< Receive normal result - wValue */ SANE_Word recv_res_index; /**< Receive normal result - wIndex */ SANE_Word send_small_cmd_value; /**< Send small command - wValue */ SANE_Word send_small_cmd_index; /**< Send small command - wIndex */ SANE_Word recv_small_res_value; /**< Receive small result - wValue */ SANE_Word recv_small_res_index; /**< Receive small result - wIndex */ /*@} */ /** @name Activation/deactivation hooks * * These hooks can be used to perform additional actions when the device is * activated and deactivated. */ /*@{ */ /** Activate the device. * * This function may allocate a command-set-specific data structure and place * the pointer to it into the GT68xx_Device::command_set_private field. */ SANE_Status (*activate) (GT68xx_Device * dev); /** Deactivate the device. * * If the activate function has allocated a command-set-specific data * structure, this function must free all corresponding resources and set the * GT68xx_Device::command_set_private pointer to #NULL. */ SANE_Status (*deactivate) (GT68xx_Device * dev); /*@} */ /** @name Low-level command implementation functions * * These functions should implement the corresponding commands for the * particular command set. If a function cannot be implemented because there * is no corresponding command in the command set, the function pointer * should be set to #NULL; the wrapper will return #SANE_STATUS_UNSUPPORTED * in this case. */ /*@{ */ /** Check whether the firmware is already downloaded. * * @param dev Device object. * @param loaded Returned firmware status: * - #SANE_TRUE - the firmware is already loaded. * - #SANE_FALSE - the firmware is not loaded. */ SANE_Status (*check_firmware) (GT68xx_Device * dev, SANE_Bool * loaded); /** Download the firmware */ SANE_Status (*download_firmware) (GT68xx_Device * dev, SANE_Byte * data, SANE_Word size); /** Check whether the external power supply is connected. * * @param dev Device object. * @param power_ok Returned power status: * - #SANE_TRUE - the external power supply is connected, or the scanner does * not need external power. * - #SANE_FALSE - the external power supply is not connected, so the scanner * will not work. */ SANE_Status (*get_power_status) (GT68xx_Device * dev, SANE_Bool * power_ok); /** Check whether a transparency adapter is attached to the scanner. * * @param dev Device object. * @param ta_attached Returned transparency adapter status: * - #SANE_TRUE - the transparency adapter is connected. * - #SANE_FALSE - the transparency adapter is not connected. * * @return * - #SANE_STATUS_GOOD - transparency adapter status was checked * successfully; check @a *ta_attached for the result. * - #SANE_STATUS_UNSUPPORTED - this scanner model does not support the * transparency adapter. * */ SANE_Status (*get_ta_status) (GT68xx_Device * dev, SANE_Bool * ta_attached); /** Turn the lamps in the scanner and/or the transparency adapter on or off. * * @param dev Device object. * @param fb_lamp #SANE_TRUE turns on the flatbed lamp. * @param ta_lamp #SANE_TRUE turns on the transparency adapter lamp. * * @return * - #SANE_STATUS_GOOD - the command completed successfully. * - #SANE_STATUS_UNSUPPORTED - unsupported request was made (like attempt to * turn on the TA lamp on a scanner which does not support TA). */ SANE_Status (*lamp_control) (GT68xx_Device * dev, SANE_Bool fb_lamp, SANE_Bool ta_lamp); /** Check whether the scanner carriage is still moving. * * @param dev Device object. * @param moving Returned state of the scanner: * - #SANE_TRUE - the scanner carriage is still moving. * - #SANE_FALSE - the scanner carriage has stopped. * * @return * - #SANE_STATUS_GOOD - the command completed successfully, the status in @a * *moving is valid. */ SANE_Status (*is_moving) (GT68xx_Device * dev, SANE_Bool * moving); /** Move the scanner carriage by the specified number of steps. * * @param dev Device object. * @param distance Number of steps to move (positive to move forward, * negative to move backward). The measurement unit is model-dependent; * number of steps per inch is found in the GT68xx_Model::base_ydpi field. * * @return * - #SANE_STATUS_GOOD - the command completed successfully; the movement is * started. Call gt68xx_device_is_moving() periodically to determine when * the movement is complete. */ SANE_Status (*move_relative) (GT68xx_Device * dev, SANE_Int distance); /** Move the scanner carriage to the home position. * * @param dev Device object. */ SANE_Status (*carriage_home) (GT68xx_Device * dev); /** Eject the paper at the end of the scan. * * @param dev Device object. */ SANE_Status (*paperfeed) (GT68xx_Device * dev); /** Start scanning the image. * * @param dev Device object. */ SANE_Status (*start_scan) (GT68xx_Device * dev); /** Start reading the scanned image data from the scanner. * * @param dev Device object. * */ SANE_Status (*read_scanned_data) (GT68xx_Device * dev, SANE_Bool * ready); /** Stop scanning the image and reading the data. */ SANE_Status (*stop_scan) (GT68xx_Device * dev); /** Set parameters for the next scan. */ SANE_Status (*setup_scan) (GT68xx_Device * dev, GT68xx_Scan_Request * request, GT68xx_Scan_Action action, GT68xx_Scan_Parameters * params); SANE_Status (*set_afe) (GT68xx_Device * dev, GT68xx_AFE_Parameters * params); SANE_Status (*set_exposure_time) (GT68xx_Device * dev, GT68xx_Exposure_Parameters * params); /** Get the vendor, product and some more ids from the scanner */ SANE_Status (*get_id) (GT68xx_Device * dev); /** Move the paper by the amount of y offset needed to reach scan area * * @param dev Device object. * @param request scan request used to compute move to reach scan area */ SANE_Status (*move_paper) (GT68xx_Device * dev, GT68xx_Scan_Request * request); /** Detect if a document is inserted in the feeder * * @param dev Device object. * @param present */ SANE_Status (*document_present) (GT68xx_Device * dev, SANE_Bool *present); /*@} */ }; #define MAX_RESOLUTIONS 12 #define MAX_DPI 4 /** Model-specific scanner data. */ struct GT68xx_Model { /** @name Identification */ /*@{ */ /** A single lowercase word to be used in the configuration file. */ SANE_String_Const name; /** Device vendor string. */ SANE_String_Const vendor; /** Device model name. */ SANE_String_Const model; /** Name of the firmware file. */ SANE_String_Const firmware_name; /** Dynamic allocation flag. * * This flag must be set to SANE_TRUE if the structure is dynamically * allocated; in this case the structure will be freed when the GT68xx_Device * is freed. */ SANE_Bool allocated; /*@} */ /** @name Scanner model parameters */ /*@{ */ GT68xx_Command_Set *command_set; SANE_Int optical_xdpi; /* maximum resolution in x-direction */ SANE_Int optical_ydpi; /* maximum resolution in y-direction */ SANE_Int base_xdpi; /* x-resolution used to calculate geometry */ SANE_Int base_ydpi; /* y-resolution used to calculate geometry */ SANE_Int ydpi_no_backtrack; /* if ydpi is equal or higher, disable backtracking */ SANE_Bool constant_ydpi; /* Use base_ydpi for all resolutions */ SANE_Int xdpi_values[MAX_RESOLUTIONS]; /* possible x resolutions */ SANE_Int ydpi_values[MAX_RESOLUTIONS]; /* possible y resolutions */ SANE_Int bpp_gray_values[MAX_DPI]; /* possible depths in gray mode */ SANE_Int bpp_color_values[MAX_DPI]; /* possible depths in color mode */ SANE_Fixed x_offset; /* Start of scan area in mm */ SANE_Fixed y_offset; /* Start of scan area in mm */ SANE_Fixed x_size; /* Size of scan area in mm */ SANE_Fixed y_size; /* Size of scan area in mm */ SANE_Fixed y_offset_calib; /* Start of white strip in mm */ SANE_Fixed x_offset_mark; /* Start of black mark in mm */ SANE_Fixed x_offset_ta; /* Start of scan area in TA mode in mm */ SANE_Fixed y_offset_ta; /* Start of scan area in TA mode in mm */ SANE_Fixed x_size_ta; /* Size of scan area in TA mode in mm */ SANE_Fixed y_size_ta; /* Size of scan area in TA mode in mm */ SANE_Fixed y_offset_calib_ta; /* Start of white strip in TA mode in mm */ /* Line-distance correction (in pixel at optical_ydpi) for CCD scanners */ SANE_Int ld_shift_r; /* red */ SANE_Int ld_shift_g; /* green */ SANE_Int ld_shift_b; /* blue */ SANE_Int ld_shift_double; /* distance between two CCD lines of one color (only applicable for CCD with 6 lines) */ GT68xx_Color_Order line_mode_color_order; /* Order of the CCD/CIS colors */ GT68xx_AFE_Parameters afe_params; /* Default offset/gain */ GT68xx_Exposure_Parameters exposure; /* Default exposure parameters */ SANE_Fixed default_gamma_value; /* Default gamma value */ SANE_Bool is_cis; /* Is this a CIS or CCD scanner? */ SANE_Word flags; /* Which hacks are needed for this scanner? */ /*@} */ }; /** GT68xx device instance. * */ struct GT68xx_Device { /** Device file descriptor. */ int fd; /** Device activation flag. */ SANE_Bool active; /** Device missing to flag devices that are unplugged * after sane_init and befor sane_exit */ SANE_Bool missing; /** Scanner model data. */ GT68xx_Model *model; /** Pointer to command-set-specific data. */ void *command_set_private; GT68xx_AFE_Parameters *afe; GT68xx_Exposure_Parameters *exposure; SANE_Fixed gamma_value; SANE_Bool read_active; SANE_Bool final_scan; SANE_Byte *read_buffer; size_t requested_buffer_size; size_t read_buffer_size; size_t read_pos; size_t read_bytes_in_buffer; size_t read_bytes_left; SANE_Byte gray_mode_color; SANE_Bool manual_selection; #ifdef USE_FORK Shm_Channel *shm_channel; pid_t reader_pid; #endif /* USE_FORK */ /** Pointer to next device */ struct GT68xx_Device *next; /** Device file name */ SANE_String file_name; }; /** Parameters for the high-level scan request. * * These parameters describe the scan request sent by the SANE frontend. */ struct GT68xx_Scan_Request { SANE_Fixed x0; /**< Left boundary */ SANE_Fixed y0; /**< Top boundary */ SANE_Fixed xs; /**< Width */ SANE_Fixed ys; /**< Height */ SANE_Int xdpi; /**< Horizontal resolution */ SANE_Int ydpi; /**< Vertical resolution */ SANE_Int depth; /**< Number of bits per channel */ SANE_Bool color; /**< Color mode flag */ SANE_Bool mbs; /**< Move before scan */ SANE_Bool mds; /**< Move during scan */ SANE_Bool mas; /**< Move after scan */ SANE_Bool lamp; /**< Lamp on/off */ SANE_Bool calculate; /**< Don't scan, only calculate parameters */ SANE_Bool use_ta; /**< Use the tansparency adapter */ SANE_Bool backtrack; /**< Enable backtracking */ SANE_Bool backtrack_lines; /**< How many lines to backtrack */ }; /** Scan parameters for gt68xx_device_setup_scan(). * * These parameters describe a low-level scan request; many such requests are * executed during calibration, and they need to have parameters separate from * the main request (GT68xx_Scan_Request). */ struct GT68xx_Scan_Parameters { SANE_Int xdpi; /**< Horizontal resolution */ SANE_Int ydpi; /**< Vertical resolution */ SANE_Int depth; /**< Number of bits per channel */ SANE_Bool color; /**< Color mode flag */ SANE_Int pixel_xs; /**< Logical width in pixels */ SANE_Int pixel_ys; /**< Logical height in pixels */ SANE_Int scan_xs; /**< Physical width in pixels */ SANE_Int scan_ys; /**< Physical height in pixels */ SANE_Int scan_bpl; /**< Number of bytes per scan line */ SANE_Bool line_mode; /**< Use line mode instead of pixel mode */ SANE_Int overscan_lines; /**< Number of extra scan lines */ SANE_Int ld_shift_r; SANE_Int ld_shift_g; SANE_Int ld_shift_b; SANE_Int ld_shift_double; SANE_Int double_column; SANE_Int pixel_x0; /**< x start postion */ }; #define GT68XX_PACKET_SIZE 64 typedef SANE_Byte GT68xx_Packet[GT68XX_PACKET_SIZE]; /** Create a new GT68xx_Device object. * * The newly created device object is in the closed state. * * @param dev_return Returned pointer to the created device object. * * @return * - #SANE_STATUS_GOOD - the device object was created. * - #SANE_STATUS_NO_MEM - not enough system resources to create the object. */ static SANE_Status gt68xx_device_new (GT68xx_Device ** dev_return); /** Destroy the device object and release all associated resources. * * If the device was active, it will be deactivated; if the device was open, it * will be closed. * * @param dev Device object. * * @return * - #SANE_STATUS_GOOD - success. */ static SANE_Status gt68xx_device_free (GT68xx_Device * dev); /** Open the scanner device. * * This function opens the device special file @a dev_name and tries to detect * the device model by its USB ID. * * If the device is detected successfully (its USB ID is found in the supported * device list), this function sets the appropriate model parameters. * * If the USB ID is not recognized, the device remains unconfigured; an attempt * to activate it will fail unless gt68xx_device_set_model() is used to force * the parameter set. Note that the open is considered to be successful in * this case. * * @param dev Device object. * @param dev_name Scanner device name. * * @return * - #SANE_STATUS_GOOD - the device was opened successfully (it still may be * unconfigured). */ static SANE_Status gt68xx_device_open (GT68xx_Device * dev, const char *dev_name); /** Close the scanner device. * * @param dev Device object. */ static SANE_Status gt68xx_device_close (GT68xx_Device * dev); /** Check if the device is configured. * * A device is considered configured when it has a model parameters structure * (GT68xx_Model) and a command set (GT68xx_Command_Set). Normally these * parameters are assigned automatically by gt68xx_device_open(), if the device * is known. If the USB ID of the device is not found in the list, or the OS * does not support identification of USB devices, the device will be * unconfigured after opening. * * @param dev Device object. * * @return * - #SANE_TRUE - device is configured and can be activated. * - #SANE_FALSE - device is not configured; attempt to activate it will fail. */ static SANE_Bool gt68xx_device_is_configured (GT68xx_Device * dev); /** Change the device model structure. * * This function can be used to change all model-dependent parameters at once * by supplying a whole model data structure. The model may be changed only * when the device is not active. * * If the device already had a model structure which was dynamically allocated, * the old structure is freed. * * If the new model structure @a model is dynamically allocated, the device @a * dev takes ownership of it: @a model will be freed when @a dev is destroyed * or gt68xx_device_set_model() is called again. * * @param dev Device object. * @param model Device model data. * * @return * - #SANE_STATUS_GOOD - model successfully changed. * - #SANE_STATUS_INVAL - invalid request (attempt to change model when the * device is already active, or not yet opened). */ static SANE_Status gt68xx_device_set_model (GT68xx_Device * dev, GT68xx_Model * model); /** Get model by name. * * This function can be used to find a model by its name. * * @param name Device model name. * @param model Device model data. * * @return * - #SANE_TRUE - model successfully found. * - #SANE_FALSE - model not found. */ static SANE_Bool gt68xx_device_get_model (SANE_String name, GT68xx_Model ** model); #if 0 /** Create a new private copy of the model data for this device. * * Normally the model data structures can be shared between several devices. * If the program needs to modify some model parameters for a device, it must * call this function to make a private copy of parameters. This private copy * will be automatically freed when the device is destroyed. * * @param dev Device object. * * @return * - #SANE_STATUS_GOOD - a private copy was made successfully. * - #SANE_STATUS_INVAL - invalid request (the device was already active, or * not yet opened). * - #SANE_STATUS_NO_MEM - not enough memory for copy of the model parameters. */ static SANE_Status gt68xx_device_unshare_model (GT68xx_Device * dev); #endif /** Activate the device. * * The device must be activated before performing any I/O operations with it. * All device model parameters must be configured before activation; it is * impossible to change them after the device is active. * * This function might need to acquire resources (it calls * GT68xx_Command_Set::activate). These resources will be released when * gt68xx_device_deactivate() is called. * * @param dev Device object. * * @return * - #SANE_STATUS_GOOD - device activated successfully. * - #SANE_STATUS_INVAL - invalid request (attempt to activate a closed or * unconfigured device). */ static SANE_Status gt68xx_device_activate (GT68xx_Device * dev); /** Deactivate the device. * * This function reverses the action of gt68xx_device_activate(). * * @param dev Device object. * * @return * - #SANE_STATUS_GOOD - device deactivated successfully. * - #SANE_STATUS_INVAL - invalid request (the device was not activated). */ static SANE_Status gt68xx_device_deactivate (GT68xx_Device * dev); /** Write a data block to the GT68xx memory. * * @param dev Device object. * @param addr Start address in the GT68xx memory. * @param size Size of the data block in bytes. * @param data Data block to write. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. * * @warning * @a size must be a multiple of 64 (at least with GT6816), otherwise the * scanner (and possibly the entire USB bus) will lock up. */ static SANE_Status gt68xx_device_memory_write (GT68xx_Device * dev, SANE_Word addr, SANE_Word size, SANE_Byte * data); /** Read a data block from the GT68xx memory. * * @param dev Device object. * @param addr Start address in the GT68xx memory. * @param size Size of the data block in bytes. * @param data Buffer for the read data. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. * * @warning * @a size must be a multiple of 64 (at least with GT6816), otherwise the * scanner (and possibly the entire USB bus) will lock up. */ static SANE_Status gt68xx_device_memory_read (GT68xx_Device * dev, SANE_Word addr, SANE_Word size, SANE_Byte * data); /** Execute a control command. * * @param dev Device object. * @param cmd Command packet. * @param res Result packet (may point to the same buffer as @a cmd). * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_req (GT68xx_Device * dev, GT68xx_Packet cmd, GT68xx_Packet res); /** Execute a "small" control command. * * @param dev Device object. * @param cmd Command packet; only first 8 bytes are used. * @param res Result packet (may point to the same buffer as @a cmd). * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_small_req (GT68xx_Device * dev, GT68xx_Packet cmd, GT68xx_Packet res); #if 0 /** Check whether the firmware is downloaded into the scanner. * * @param dev Device object. * @param loaded Returned firmware status: * - #SANE_TRUE - the firmware is already loaded. * - #SANE_FALSE - the firmware is not loaded. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded); #endif static SANE_Status gt68xx_device_download_firmware (GT68xx_Device * dev, SANE_Byte * data, SANE_Word size); /** Check whether the external power supply is connected. * * @param dev Device object. * @param power_ok Returned power status: * - #SANE_TRUE - the external power supply is connected, or the scanner does * not need external power. * - #SANE_FALSE - the external power supply is not connected, so the scanner * will not work. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok); /** Check whether the transparency adapter is connected. * * @param dev Device object. * @param ta_attached Returned TA status: * - #SANE_TRUE - the TA is connected. * - #SANE_FALSE - the TA is not connected. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_UNSUPPORTED - the scanner does not support TA connection. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_get_ta_status (GT68xx_Device * dev, SANE_Bool * ta_attached); /** Turn the lamps in the scanner and/or the transparency adapter on or off. * * @param dev Device object. * @param fb_lamp #SANE_TRUE turns on the flatbed lamp. * @param ta_lamp #SANE_TRUE turns on the transparency adapter lamp. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. * - #SANE_STATUS_UNSUPPORTED - unsupported request was made (like attempt to * turn on the TA lamp on a scanner which does not support TA). */ static SANE_Status gt68xx_device_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp, SANE_Bool ta_lamp); /** Check whether the scanner carriage is still moving. * * @param dev Device object. * @param moving Returned state of the scanner: * - #SANE_TRUE - the scanner carriage is still moving. * - #SANE_FALSE - the scanner carriage has stopped. * * @return * - #SANE_STATUS_GOOD - success; the status in @a *moving is valid. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_is_moving (GT68xx_Device * dev, SANE_Bool * moving); #if 0 /** Move the scanner carriage by the specified number of steps. * * @param dev Device object. * @param distance Number of steps to move (positive to move forward, negative * to move backward). The measurement unit is model-dependent; number of steps * per inch is found in the GT68xx_Model::base_ydpi field. * * @return * - #SANE_STATUS_GOOD - success; the movement is started. Call * gt68xx_device_is_moving() periodically to determine when the movement is * complete. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_move_relative (GT68xx_Device * dev, SANE_Int distance); #endif /** Move the scanner carriage to the home position. * * This function starts moving the scanner carriage to the home position, but * deos not wait for finishing the movement. To determine when the carriage * returned to the home position, the program should periodically call * gt68xx_device_is_moving(). * * @param dev Device object. * * @return * - #SANE_STATUS_GOOD - success; the movement is started. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_carriage_home (GT68xx_Device * dev); /** Eject the paper after the end of scanning. * * * @param dev Device object. * * @return * - #SANE_STATUS_GOOD - success; the movement is started. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_paperfeed (GT68xx_Device * dev); /** Start scanning the image. * * This function initiates scanning with parameters set by * gt68xx_device_setup_scan() (which should be called before). In particular, * it starts the carriage movement to the start of the scanning window. * * After calling this function, gt68xx_device_read_scanned_data() should be * called repeatedly until the scanner signals that it is ready to deliver the * data. * * @param dev Device object. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_start_scan (GT68xx_Device * dev); /** Start reading the scanned image data. * * This function should be used only after gt68xx_device_start_scan(). It * should be called repeatedly until @a *ready flag becomes true, at which * point reading the image data should be started using * gt68xx_device_read_prepare(). * * @param dev Device object. * @param ready Returned status of the scanner: * - #SANE_TRUE - the scanner is ready to send data. * - #SANE_FALSE - the scanner is not ready (e.g., the carriage has not reached * the start of the scanning window). * * @return * - #SANE_STATUS_GOOD - success; the value in @a *ready is valid. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_read_scanned_data (GT68xx_Device * dev, SANE_Bool * ready); /** Stop scanning the image. * * This function should be used after reading all image data from the scanner, * or in the middle of scan to abort the scanning process. * * @param dev Device object. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_stop_scan (GT68xx_Device * dev); /** Set parameters for the next scan. * * This function calculates the hardware-dependent scanning parameters and, * unless @a calculate_only is set, sends the command to prepare for scanning * with the specified window and parameters. * * @param dev Device object. * @param request High-level scanning request. * @param action Action code describing the phase of calibration or scanning * process. * @param params Returned structure with hardware-dependent scanning * parameters. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_UNSUPPORTED - the requested scanning parameters in @a request * are not supported by hardware. * - #SANE_STATUS_INVAL - some of the parameters in @a request, or the @a * action code, are completely invalid. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_setup_scan (GT68xx_Device * dev, GT68xx_Scan_Request * request, GT68xx_Scan_Action action, GT68xx_Scan_Parameters * params); /** Configure the analog front-end (AFE) of the GT68xx. * * @param dev Device object. * @param params AFE parameters. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_set_afe (GT68xx_Device * dev, GT68xx_AFE_Parameters * params); static SANE_Status gt68xx_device_set_exposure_time (GT68xx_Device * dev, GT68xx_Exposure_Parameters * params); /** Read raw data from the bulk-in scanner pipe. * * @param dev Device object. * @param buffer Buffer for the read data. * @param size Pointer to the variable which must be set to the requested data * size before call. After completion this variable will hold the number of * bytes actually read. * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - a communication error occured. */ static SANE_Status gt68xx_device_read_raw (GT68xx_Device * dev, SANE_Byte * buffer, size_t * size); static SANE_Status gt68xx_device_set_read_buffer_size (GT68xx_Device * dev, size_t buffer_size); static SANE_Status gt68xx_device_read_prepare (GT68xx_Device * dev, size_t expected_count, SANE_Bool final_scan); static SANE_Status gt68xx_device_read (GT68xx_Device * dev, SANE_Byte * buffer, size_t * size); static SANE_Status gt68xx_device_read_finish (GT68xx_Device * dev); /** Make sure that the result of a command is ok. * * @param res Result packet from the last command * @param command Command * * @return * - #SANE_STATUS_GOOD - success. * - #SANE_STATUS_IO_ERROR - the command wasn't successful */ static SANE_Status gt68xx_device_check_result (GT68xx_Packet res, SANE_Byte command); static SANE_Status gt68xx_device_get_id (GT68xx_Device * dev); /** Read the device descriptor of the scanner. * * This function should be called before closing the device to make sure * that the device descriptor is propperly stored in the scanner's memory. * If that's not done, the next try to get the config descriptor will * result in a corrupted descriptor. * * @param dev device */ static void gt68xx_device_fix_descriptor (GT68xx_Device * dev); #endif /* not GT68XX_LOW_H */ /* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */ sane-backends-1.0.27/backend/canon_dr.conf.in0000664000175000017500000000757112775312260015667 00000000000000####################################################################### # NOTE: 'option' lines only apply to the devices found by # the NEXT 'usb' or 'scsi' line. You may repeat the option line if # required for multiple scanners of different models/connections. ####################################################################### # Some machines are incapable of providing basic inquiry info, and will # lock up if asked for it. The driver will not ask for this info if all # three of these options are provided. They should NOT be used unless # you know for sure that your machine requires it. # NOTE: the vendor and model must be correct. The version need not. #option vendor-name CANON #option model-name DR-2050C #option version-name XXXX ####################################################################### # Set data buffer size, in bytes. The value ranges from 4096 - infinity # Large values may cause timeouts, or long pauses at the end of each # page. Small values may cause slow scans. 2MB is the default. #option buffer-size 2097152 ####################################################################### # Most scanners dont pad their reads #option padded-read 0 ####################################################################### # SCSI scanners: # To search for any CANON scsi device, if name starts with 'CR' or 'DR' scsi CANON CR scsi CANON DR # To use a specific scsi device #scsi /dev/sg1 ####################################################################### # USB scanners: # For Canon scanners connected via USB on a known device (kernel driver): #usb /dev/usb/scanner0 # For Canon scanners connected via USB using vendor and device ids (libusb): #usb VENDORID PRODUCTID # NOTE: if you have to add your device here- please send the id and model # to the author via email, so it can be included in next version. kitno455 at # gmail dot com - with canon_dr in the subject line # DR-2080C (uses weird protocol) option duplex-offset 840 option vendor-name CANON option model-name DR-2080C option version-name XXXX option padded-read 1 usb 0x04a9 0x1601 # CR-180 usb 0x04a9 0x1602 # DR-9080C usb 0x04a9 0x1603 # DR-7080C usb 0x04a9 0x1604 # DR-5010C usb 0x04a9 0x1606 # DR-6080C usb 0x04a9 0x1607 # DR-2580C option duplex-offset 432 usb 0x04a9 0x1608 # DR-3080CII option padded-read 1 usb 0x04a9 0x1609 # DR-2050C/SP (uses weird protocol) option duplex-offset 840 option vendor-name CANON option model-name DR-2050C option version-name XXXX option padded-read 1 usb 0x04a9 0x160a # DR-7580 usb 0x04a9 0x160b # CR-55 usb 0x1083 0x160c # DR-1210C (two versions?) usb 0x1083 0x160f usb 0x04a9 0x2222 # DR-4010C usb 0x1083 0x1614 # DR-2510C option duplex-offset 400 usb 0x1083 0x1617 # DR-X10C usb 0x1083 0x1618 # CR-25 usb 0x1083 0x161a # DR-2010C option duplex-offset 400 usb 0x1083 0x161b # DR-3010C option duplex-offset 400 usb 0x1083 0x161d # DR-7090C usb 0x1083 0x1620 # DR-9050C usb 0x1083 0x1622 # DR-7550C usb 0x1083 0x1623 # DR-6050C usb 0x1083 0x1624 # DR-6010C usb 0x1083 0x1626 # CR-190i usb 0x1083 0x162b # P-150M usb 0x1083 0x162c # DR-6030C usb 0x1083 0x1638 # CR-135i usb 0x1083 0x1639 # DR-M160 option extra-status 1 option duplex-offset 400 usb 0x1083 0x163e # DR-M140 option extra-status 1 option duplex-offset 400 usb 0x1083 0x163f # DR-C125 option duplex-offset 400 usb 0x1083 0x1640 # DR-P215 usb 0x1083 0x1641 # P-215 usb 0x1083 0x1646 # FSU-201 usb 0x1083 0x1648 # DR-C130 usb 0x1083 0x164a # DR-P208 usb 0x1083 0x164b # P-208 usb 0x1083 0x164c # DR-G1130 option buffer-size 8000000 usb 0x1083 0x164f # DR-G1100 option buffer-size 8000000 usb 0x1083 0x1650 # DR-C120 usb 0x1083 0x1651 # P-201 usb 0x1083 0x1652 # DR-F120 option duplex-offset 1640 usb 0x1083 0x1654 # DR-M1060 usb 0x1083 0x1657 # DR-C225 usb 0x1083 0x1658 # DR-P215II usb 0x1083 0x1659 # P-215II usb 0x1083 0x165b # DR-P208II usb 0x1083 0x165d # P-208II usb 0x1083 0x165f sane-backends-1.0.27/backend/tamarack.conf.in0000664000175000017500000000003412112021330015626 00000000000000scsi TAMARACK /dev/scanner sane-backends-1.0.27/backend/umax.h0000664000175000017500000005460712112021330013731 00000000000000/* --------------------------------------------------------------------------------------------------------- */ /* umax.h - headerfile for SANE-backend for umax scanners (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* --------------------------------------------------------------------------------------------------------- */ #ifndef umax_h #define umax_h #include "sys/types.h" /* --------------------------------------------------------------------------------------------------------- */ /* COMPILER OPTIONS: */ #define UMAX_ENABLE_USB #define UMAX_HIDE_UNUSED /* #define SANE_UMAX_DEBUG_S12 */ /* #define UMAX_CALIBRATION_MODE_SELECTABLE */ /* --------------------------------------------------------------------------------------------------------- */ #define SANE_UMAX_SCSI_MAXQUEUE 8 /* --------------------------------------------------------------------------------------------------------- */ #define SANE_UMAX_FIX_ROUND(val) ((SANE_Word) ((val) * (1 << SANE_FIXED_SCALE_SHIFT) + 1.0 / (1 << (SANE_FIXED_SCALE_SHIFT+1)))) /* --------------------------------------------------------------------------------------------------------- */ enum Umax_Option { OPT_NUM_OPTS = 0, /* ------------------------------------------- */ OPT_MODE_GROUP, OPT_MODE, OPT_SOURCE, OPT_X_RESOLUTION, OPT_Y_RESOLUTION, OPT_RESOLUTION_BIND, /* bind x and y resolution */ OPT_NEGATIVE, /* ------------------------------------------- */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ /* ------------------------------------------- */ OPT_ENHANCEMENT_GROUP, OPT_BIT_DEPTH, /* output bit depth */ OPT_QUALITY, /* quality calibration */ OPT_DOR, /* double optical resolution */ OPT_WARMUP, OPT_RGB_BIND, /* use same rgb-values for each color in color-mode */ OPT_BRIGHTNESS, OPT_CONTRAST, OPT_THRESHOLD, OPT_HIGHLIGHT, /* highlight */ OPT_HIGHLIGHT_R, OPT_HIGHLIGHT_G, OPT_HIGHLIGHT_B, OPT_SHADOW, /* shadow */ OPT_SHADOW_R, OPT_SHADOW_G, OPT_SHADOW_B, OPT_ANALOG_GAMMA, /* analog gamma */ OPT_ANALOG_GAMMA_R, OPT_ANALOG_GAMMA_G, OPT_ANALOG_GAMMA_B, OPT_CUSTOM_GAMMA, /* use custom gamma tables */ /* The gamma vectors MUST appear in the order gray, red, green, blue. */ OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, OPT_HALFTONE_DIMENSION, OPT_HALFTONE_PATTERN, /* ------------------------------------------- */ OPT_ADVANCED_GROUP, OPT_CAL_EXPOS_TIME, /* exposure time for calibration */ OPT_CAL_EXPOS_TIME_R, OPT_CAL_EXPOS_TIME_G, OPT_CAL_EXPOS_TIME_B, OPT_SCAN_EXPOS_TIME, /* exposure time for scan */ OPT_SCAN_EXPOS_TIME_R, OPT_SCAN_EXPOS_TIME_G, OPT_SCAN_EXPOS_TIME_B, OPT_DISABLE_PRE_FOCUS, OPT_MANUAL_PRE_FOCUS, OPT_FIX_FOCUS_POSITION, OPT_LENS_CALIBRATION_DOC_POS, OPT_HOLDER_FOCUS_POS_0MM, OPT_CAL_LAMP_DEN, OPT_SCAN_LAMP_DEN, OPT_SELECT_EXPOSURE_TIME, OPT_SELECT_CAL_EXPOSURE_TIME, OPT_SELECT_LAMP_DENSITY, OPT_LAMP_ON, OPT_LAMP_OFF, OPT_LAMP_OFF_AT_EXIT, OPT_BATCH_SCAN_START, /* start batch scan function */ OPT_BATCH_SCAN_LOOP, /* loop batch scan function */ OPT_BATCH_SCAN_END, /* end batch scan function */ OPT_BATCH_NEXT_TL_Y, /* batch scan function next y position */ #ifdef UMAX_CALIBRATION_MODE_SELECTABLE OPT_CALIB_MODE, #endif OPT_PREVIEW, /* preview, sets preview-bit and bind x/y-resolution */ /* must come last: */ NUM_OPTIONS }; /* -------------------------------------------------------------------------------------------------------- */ /* LIST OF AVAILABLE SCANNERS, THE VALUES LISTED HERE ARE THE SAME FOR DIFFERENT APPLICATIONS THAT USE THE SAME DEVICE */ /* Umax_Device contains values relevant for the device that are not intersting for the sane interface */ typedef struct Umax_Device { struct Umax_Device *next; SANE_Device sane; int connection_type; #define SANE_UMAX_UNKNOWN 0 #define SANE_UMAX_SCSI 1 #define SANE_UMAX_USB 2 SANE_Range x_dpi_range; SANE_Range y_dpi_range; SANE_Range x_range; SANE_Range y_range; SANE_Range analog_gamma_range; unsigned flags; unsigned char *buffer[SANE_UMAX_SCSI_MAXQUEUE]; /* buffer used for scsi-transfer */ void *queue_id[SANE_UMAX_SCSI_MAXQUEUE]; /* scsi queue id */ size_t length_queued[SANE_UMAX_SCSI_MAXQUEUE]; /* length of queued data */ size_t length_read[SANE_UMAX_SCSI_MAXQUEUE]; /* length of returned data */ unsigned int bufsize; unsigned int row_bufsize; unsigned int request_scsi_maxqueue; unsigned int request_preview_lines; unsigned int request_scan_lines; unsigned int handle_bad_sense_error; unsigned int execute_request_sense; unsigned int force_preview_bit_rgb; unsigned int scsi_buffer_size_min; unsigned int scsi_buffer_size_max; unsigned int scsi_maxqueue; unsigned char *pixelbuffer; /* buffer used for pixel ordering */ unsigned int pixelline_max; /* number of lines that fit into pixelbuffer */ unsigned int pixelline_ready[3]; /* finished absolute line for each color */ unsigned int pixelline_next[3]; /* next line to write for each color */ unsigned int pixelline_del[3]; /* next line to delete in opt_res for col */ unsigned int pixelline_optic[3]; /* scanned line in opt_res for each color */ unsigned int pixelline_opt_res; /* number of scanned line in optical res */ unsigned int pixelline_read; /* number of read pixel-lines */ unsigned int pixelline_written; /* number of written pixel-lines */ unsigned int CCD_distance; /* color line distance in optical resolution */ unsigned int CCD_color[9]; /* color order */ /* 0 / 1 2 / 3 4 5 / 6 7 / 8 */ # define CCD_color_red 0 # define CCD_color_green 1 # define CCD_color_blue 2 char *devicename; /* name of the scanner device */ int sfd; /* output file descriptor, scanner device */ char vendor[9]; /* will be UMAX */ char product[17]; /* e.g. "SuperVista_S12" or so */ char version[5]; /* e.g. V1.3 */ int three_pass; /* used in RGB-mode if 3-pass => 1 */ int three_pass_color; /* select color for scanning in 3pass mode */ unsigned int row_len; /* len of one scan-line in bytes */ unsigned int lines_max; /* maximum number of lines to scan */ unsigned int max_value; /* used for pnm-file */ /* data defined by inquiry */ int inquiry_len; /* length of inquiry return block */ int inquiry_wdb_len; /* length of window descriptor block */ int inquiry_vidmem; /* size of video memory */ int inquiry_optical_res; /* optical resolution */ int inquiry_x_res; /* maximum x-resolution */ int inquiry_y_res; /* maximum y-resolution */ int inquiry_dor_optical_res; /* optical resolution for dor mode */ int inquiry_dor_x_res; /* maximum x-resolution for dor mode */ int inquiry_dor_y_res; /* maximum y-resolution for dor mode */ double inquiry_fb_width; /* flatbed width in inches */ double inquiry_fb_length; /* flatbed length in inches */ double inquiry_uta_width; /* transparency width in inches */ double inquiry_uta_length; /* transparency length in inches */ double inquiry_uta_x_off; /* transparency x offset in inches */ double inquiry_uta_y_off; /* transparency y offset in inches */ double inquiry_dor_width; /* double resolution width in inches */ double inquiry_dor_length; /* double resolution length in inches */ double inquiry_dor_x_off; /* double resolution x offset in inches */ double inquiry_dor_y_off; /* double resolution y offset in inches */ int inquiry_exposure_adj; /* 1 if exposure adjust is supported */ int inquiry_exposure_time_step_unit; /* exposure time unit in micro sec */ int inquiry_exposure_time_max; /* exposure time maximum */ int inquiry_exposure_time_l_min; /* exposure tine minimum for lineart */ int inquiry_exposure_time_l_fb_def; /* exposure time default for lineart/flatbed */ int inquiry_exposure_time_l_uta_def; /* exposure time default for lineart/uta */ int inquiry_exposure_time_h_min; /* exposure tine minimum for halftone */ int inquiry_exposure_time_h_fb_def; /* exposure time default for halftone/flatbed */ int inquiry_exposure_time_h_uta_def; /* exposure time default for halftone/uta */ int inquiry_exposure_time_g_min; /* exposure tine minimum for grayscale */ int inquiry_exposure_time_g_fb_def; /* exposure time default for grayscale/flatbed */ int inquiry_exposure_time_g_uta_def; /* exposure time default for grayscale/uta */ int inquiry_exposure_time_c_min; /* exposure tine minimum for color */ int inquiry_exposure_time_c_fb_def_r; /* exposure time default for color red/flatbed */ int inquiry_exposure_time_c_fb_def_g; /* exposure time default for color green/flatbed */ int inquiry_exposure_time_c_fb_def_b; /* exposure time default for color blue/flatbed */ int inquiry_exposure_time_c_uta_def_r; /* exposure time default for color red/uta */ int inquiry_exposure_time_c_uta_def_g; /* exposure time default for color green/uta */ int inquiry_exposure_time_c_uta_def_b; /* exposure time default for color blue/uta */ int inquiry_max_warmup_time; /* maximum lamp warmup time in sec */ int inquiry_cbhs; /* 50, 255, 255+autoexp. */ int inquiry_cbhs_min; /* minimum value for cbhs */ int inquiry_cbhs_max; /* maximum value for cbhs */ int inquiry_contrast_min; /* minimum value for c */ int inquiry_contrast_max; /* maximum value for c */ int inquiry_brightness_min; /* minimum value for b */ int inquiry_brightness_max; /* maximum value for b */ int inquiry_threshold_min; /* minimum value for t */ int inquiry_threshold_max; /* maximum value for t */ int inquiry_highlight_min; /* minimum value for h */ int inquiry_highlight_max; /* maximum value for h */ int inquiry_shadow_min; /* minimum value for s */ int inquiry_shadow_max; /* maximum value for s */ int inquiry_quality_ctrl; /* 1 = supported */ int inquiry_batch_scan; /* 1 = supported */ int inquiry_preview; /* 1 = supported */ int inquiry_lamp_ctrl; /* 1 = supported */ int inquiry_transavail; /* 1 = uta available */ int inquiry_adfmode; /* 1 = adf available */ int inquiry_uta; /* 1 = uta supported */ int inquiry_adf; /* 1 = adf supported */ int inquiry_dor; /* 1 = dor supported */ int inquiry_reverse; /* 1 = 1 bit reverse supported */ int inquiry_reverse_multi; /* 1 = multi bit reverse supported */ int inquiry_analog_gamma; /* 1 = analog gamma supported */ int inquiry_lineart_order; /* 1 = LSB first, 0 = MSB first */ int inquiry_lens_cal_in_doc_pos; /* 1 = lens calibration in doc pos supported */ int inquiry_manual_focus; /* 1 = manual focus supported */ int inquiry_sel_uta_lens_cal_pos; /* 1 = selection of lens calib pos for uta supported */ int inquiry_gamma_dwload; /* 1 = gamma download supported */ int inquiry_gamma_DCF; /* gamma download curve format */ int inquiry_one_pass_color; /* 1 = 1 pass supported */ int inquiry_three_pass_color; /* 1 = 3 pass supported */ int inquiry_color; /* 1 = color mode supported */ int inquiry_gray; /* 1 = grayscale mode supported */ int inquiry_halftone; /* 1 = halftone mode supported */ int inquiry_lineart; /* 1 = lineart mode supported */ int inquiry_calibration; /* 1 = calibration mode control supported */ int inquiry_highlight; /* 1 = highlight supported */ int inquiry_shadow; /* 1 = shadow supported */ int inquiry_GIB; /* gamma input bits */ int inquiry_GOB; /* gamma output bits */ int inquiry_max_calib_lines; /* maximum calibration lines */ int inquiry_color_order; /* color ordering support */ int inquiry_CCD_line_distance; /* color line distance */ int inquiry_fb_uta_color_arrangement; /* line arrangement for fb & uta */ int inquiry_adf_color_arrangement; /* line arrangement for adf */ unsigned int relevant_optical_res; /* optical resolution */ unsigned int relevant_max_x_res; /* maximum x-resolution */ unsigned int relevant_max_y_res; /* maximum y-resolution */ /* selected data */ int use_exposure_time_min; /* exposure tine minimum */ int use_exposure_time_def_r; /* exposure time default */ int use_exposure_time_def_g; /* exposure time default */ int use_exposure_time_def_b; /* exposure time default */ int wdb_len; /* use this length of WDB */ unsigned int width_in_pixels; /* thats the wanted width in pixels */ unsigned int length_in_pixels; /* thats the wanted length in pixels */ unsigned int scanwidth; /* thats the width in pixels at x_coordinate_base dpi */ unsigned int scanlength; /* thats the length in pixels at y_coordinate_base dpi */ unsigned int bytes_per_color; /* bytes per each color */ unsigned int x_resolution; /* scan-resolution for x in dpi */ unsigned int y_resolution; /* scan-resolution for y in dpi */ double scale_x; /* x-scaling of optical resolution */ double scale_y; /* y-scaling of optical resolution */ int upper_left_x; /* thats the left edge in points at 1200pt/inch */ int upper_left_y; /* thats the top edge in points at 1200pt/inch */ unsigned int x_coordinate_base; /* x base in pixels/inch, normaly 1200 */ unsigned int y_coordinate_base; /* y base in pixels/inch, normaly 1200 */ unsigned int bits_per_pixel; /* number of bits per pixel */ int bits_per_pixel_code; /* 1 = 24bpp, 4 = 30 bpp, 8 = 36 bpp */ int gamma_input_bits_code; /* 1 = 24bpp, 4 = 30 bpp, 8 = 36 bpp */ int set_auto; /* 0 or 1, don't know what it is */ int preview; /* 1 if preview */ int batch_scan; /* 1 = batch scan, 0 = normal scan */ int batch_end; /* 1 = reposition scanhead */ int batch_next_tl_y; /* top left y position for next batch scan */ int quality; /* 1 = quality_calibration, 0 = fast */ int reverse; /* 1: exchange black and white */ int reverse_multi; /* 1: invert color values */ int WD_speed; /* is a combination of slow and smear */ int slow; /* 1: slow scan speed */ int smear; /* 1: don't care about image smearing problem */ int dor; /* double resolution */ int cbhs_range; /* 50,255 or 255+autoexposure */ int fix_focus_position; /* fix focus position */ int lens_cal_in_doc_pos; /* lens calibration in document position */ int disable_pre_focus; /* disable pre focus */ int holder_focus_pos_0mm; /* 0.6mm <-> 0.0mm holder focus position */ int manual_focus; /* automatic <-> manual focus */ int warmup; /* 1=set warmup-bit */ int module; /* flatbed or transparency */ int adf; /* 1 if ADF turned on */ int uta; /* 1 if UTA turned on */ int calibration; /* calibration :0=ignore, 1=driver, 2=by image */ int low_byte_first; /* 10 bit mode: 0=high byte frist, 1=low byte frist */ int colormode; /* LINEART, HALFTONE, GRAYSCALE or RGB */ # define LINEART 1 # define HALFTONE 2 # define GRAYSCALE 3 # define RGB_LINEART 4 # define RGB_HALFTONE 5 # define RGB 6 int exposure_time_calibration_r; /* red exposure time for calibration */ int exposure_time_calibration_g; /* green exposure time for calibration */ int exposure_time_calibration_b; /* blue exposure time for calibration */ int exposure_time_scan_r; /* red exposure time for scan */ int exposure_time_scan_g; /* green exposure time for scan */ int exposure_time_scan_b; /* bue exposure time for scan */ int c_density; /* next calibration lamp density */ int s_density; /* next scan lamp density */ int threshold; /* (128) 0-255, lineart mode */ int brightness; /* (128) cbhs_range 0-255, halftone mode */ int contrast; /* (128) cbhs_range 0-255, halftone-mode */ int highlight_r; /* (255) cbhs_range 1-255, each mode */ int highlight_g; /* (255) cbhs_range 1-255, each mode */ int highlight_b; /* (255) cbhs_range 1-255, each mode */ int shadow_r; /* (0) cbhs_range 0-254, each mode */ int shadow_g; /* (0) cbhs_range 0-254, each mode */ int shadow_b; /* (0) cbhs_range 0-254, each mode */ int halftone; /* halftone pattern select */ int digital_gamma_r; /* gamma-select for red and gray */ int digital_gamma_g; /* gamma-select value for green */ int digital_gamma_b; /* gamma-select value for blue */ int analog_gamma_r; /* analog gamma red and gray */ int analog_gamma_g; /* analog gamma green */ int analog_gamma_b; /* analog gamma blue */ int calib_lines; /* request calibration lines */ int do_calibration; /* 1: do calibration by driver */ int do_color_ordering; /* 1: order line-mode to pixel-mode */ int button0_pressed; /* scan-button 0 on scanner is pressed => 1 */ int button1_pressed; /* scan-button 1 on scanner is pressed => 1 */ int button2_pressed; /* scan-button 2 on scanner is pressed => 1 */ int calibration_area; /* define calibration area if no area is given */ int calibration_width_offset; /* some scanners do calibrate with some additional pixels */ int calibration_width_offset_batch; /* the same for batch scanning */ int calibration_bytespp; /* correction of bytespp if driver knows about it */ int exposure_time_rgb_bind; /* exposure time can not be defined for each color */ int invert_shading_data; /* invert shading data before sending it to the scanner */ int common_xy_resolutions; /* do not allow different x and y resolution */ int pause_for_color_calibration; /* pause between start_scan and do_calibration in ms */ int pause_for_gray_calibration; /* pause between start_scan and do_calibration in ms */ int pause_after_calibration; /* pause between do_calibration and read data in ms */ int pause_after_reposition; /* pause for repositioning in ms */ int pause_for_moving; /* pause for moving scanhead over full scanarea in ms */ int lamp_control_available; /* is set when scanner supportes lamp control */ int gamma_lsb_padded; /* 16 bit gamma data is padded to lsb */ int force_quality_calibration; /* always set quality calibration */ } Umax_Device; /* --------------------------------------------------------------------------------------------------------- */ /* LIST OF OPEND DEVICES, A DEVICE MAY BE OPEND TWICE, ALL VALUES LISTED HERE MAY BE DIFFERENT FOR DIFFERENT APPLICATIONS */ /* Umax_Scanner contains values relevant for the sane interface */ typedef struct Umax_Scanner { struct Umax_Scanner *next; Umax_Device *device; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Int *gamma_table[4]; SANE_Int halftone_pattern[64]; SANE_Range gamma_range; unsigned int gamma_length; SANE_Range output_range; unsigned int output_bytes; SANE_Range exposure_time_range; int scanning; SANE_Parameters params; SANE_Pid reader_pid; int pipe_read_fd; int pipe_write_fd; } Umax_Scanner; /* --------------------------------------------------------------------------------------------------------- */ #endif /* umax-sane_h */ sane-backends-1.0.27/backend/mustek_usb2_high.h0000664000175000017500000001575612621242546016246 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2005 Mustek. Originally maintained by Mustek Author:Jack Roy 2005.5.24 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro and similar USB2 scanners. */ #ifndef MUSTEK_USB2_HIGH_H #define MUSTEK_USB2_HIGH_H /* const use in structures*/ /*scan mode*/ typedef unsigned short SCANMODE, *LPSCANMODE; #define SM_TEXT 0x00 #define SM_GRAY 0x01 #define SM_RGB24 0x02 #define SM_GRAY10 0x03 #define SM_RGB30 0x04 #define SM_GRAY12 0x05 #define SM_RGB36 0x06 #define SM_GRAY14 0x07 #define SM_RGB42 0x08 #define SM_GRAY16 0x09 #define SM_RGB48 0x0a /*pixel flavor*/ typedef SANE_Byte PIXELFLAVOR, *LPPIXELFLAVOR; #define PF_BlackIs0 0x00 #define PF_WhiteIs0 0x01 /*scan source*/ typedef SANE_Byte SCANSOURCE, *LPSCANSOURCE; #define SS_Reflective 0x00 #define SS_Positive 0x01 #define SS_Negative 0x02 #define SS_ADF 0x03 /*RGB order*/ typedef unsigned short RGBORDER, *LPRGBORDER; #define RO_RGB 0x00 #define RO_BGR 0x01 /* structures use in parameters of export function*/ typedef struct tagGAMMAINFO { SCANMODE smScanMode; unsigned short wInputGammaBits; unsigned short wOutputGammaBits; } GAMMAINFO, *LPGAMMAINFO; typedef struct tagGETPARAMETERS { unsigned short wSourceXDPI; unsigned short wSourceYDPI; unsigned int dwLineByteWidth; unsigned int dwLength; } GETPARAMETERS, *LPGETPARAMETERS; typedef struct tagFRAME { unsigned short x1; unsigned short y1; unsigned short x2; unsigned short y2; } FRAME, *LPFRAME; typedef struct tagSETPARAMETERS { FRAME fmArea; unsigned short wTargetDPI; SCANMODE smScanMode; unsigned short wLinearThreshold; /*threshold for Line art mode */ PIXELFLAVOR pfPixelFlavor; SCANSOURCE ssScanSource; unsigned short * pGammaTable; } SETPARAMETERS, *LPSETPARAMETERS; typedef struct tagIMAGEROWS { RGBORDER roRgbOrder; unsigned short wWantedLineNum; unsigned short wXferedLineNum; SANE_Byte * pBuffer; } IMAGEROWS, *LPIMAGEROWS; /*Macro define*/ #define R_GAIN 0 #define G_GAIN 0 #define B_GAIN 0 #define R_OFFSET 0 #define G_OFFSET 0 #define B_OFFSET 0 #define R_DIRECTION 0 #define G_DIRECTION 0 #define B_DIRECTION 0 /* use for adjust AD's offset*/ /* for Reflective*/ #define REFL_DARK_MAX_LEVEL 20 #define REFL_DARK_MIN_LEVEL 10 #define REFL_WHITE_MAX_LEVEL 220 #define REFL_WHITE_MIN_LEVEL 210 #define REFL_MAX_LEVEL_RANGE 210 #define REFL_MIN_LEVEL_RANGE 190 /*for Transparent*/ #define TRAN_DARK_MAX_LEVEL 20 #define TRAN_DARK_MIN_LEVEL 10 #define TRAN_WHITE_MAX_LEVEL 220 #define TRAN_WHITE_MIN_LEVEL 210 #define TRAN_MAX_LEVEL_RANGE 210 #define TRAN_MIN_LEVEL_RANGE 190 /* in 600 dpi*/ #define FIND_LEFT_TOP_WIDTH_IN_DIP 512 #define FIND_LEFT_TOP_HEIGHT_IN_DIP 180 #define FIND_LEFT_TOP_CALIBRATE_RESOLUTION 600 #define TA_FIND_LEFT_TOP_WIDTH_IN_DIP 2668 #define TA_FIND_LEFT_TOP_HEIGHT_IN_DIP 300 #define TA_MOTOR_BACK_STEP_AFTER_FIND_BOUNDARY 150 #define TA_MOTOR_FORWARD_STEP_AFTER_READ_WHITE_DATA 1100 /*must be 8x*/ #define LINE_CALIBRATION__16BITS_HEIGHT 40 /* the length from block bar to start Calibration position*/ #define BEFORE_SCANNING_MOTOR_FORWARD_PIXEL 40 #define PRE_MOVE_MOTOR_LENGTH_IN_DPI 1450 /* if the motor is 1/8 step, setup MOTOR_STEP_MULTI as 8 if the motor is 1/4 step, setup MOTOR_STEP_MULTI as 4 if the motor is full step, setup MOTOR_STEP_MULTI as 1 #define MOTOR_EIGHTH_STEP*/ #ifdef MOTOR_EIGHTH_STEP #define MOTOR_STEP_MULTI 8 #define GPIO_95_Config 0x68 #else #define MOTOR_STEP_MULTI 4 #define GPIO_95_Config 0x60 #endif #define TRAN_START_POS 4550 /* in 300dpi*/ #define MAX_SCANNING_WIDTH 2550 /*just for A4 */ #define MAX_SCANNING_HEIGHT 3540 /*just for A4 */ #define INIFILENAME "./msam.ini" /*enable gamma*/ #define ENABLE_GAMMA /*save debug image*/ /*#define DEBUG_SAVE_IMAGE*/ /*type define*/ typedef unsigned char SCANTYPE; #define ST_Reflective 0x00 #define ST_Transparent 0x01 typedef enum tagCOLORMODE { CM_RGB48 = 0, CM_RGB42 = 1, CM_RGB36 = 2, CM_RGB30 = 3, CM_RGB24 = 4, CM_GRAY16 = 5, CM_GRAY14 = 6, CM_GRAY12 = 7, CM_GRAY10 = 8, CM_GRAY8 = 9, CM_TEXT = 10, CM_RGB48ext = 11, CM_RGB42ext = 12, CM_RGB36ext = 13, CM_RGB30ext = 14, CM_RGB24ext = 15, CM_GRAY16ext = 16, CM_GRAY14ext = 17, CM_GRAY12ext = 18, CM_GRAY10ext = 19, CM_GRAY8ext = 20, CM_TEXText = 21 } COLORMODE, *PCOLORMODE; typedef struct tagTARGETIMAGE { SANE_Bool isOptimalSpeed; COLORMODE cmColorMode; unsigned short wDpi; unsigned short wX; unsigned short wY; unsigned short wWidth; unsigned short wHeight; SANE_Byte bScanSource; } TARGETIMAGE, *PTARGETIMAGE; typedef struct tagSUGGESTSETTING { COLORMODE cmScanMode; unsigned short wXDpi; unsigned short wYDpi; unsigned short wX; unsigned short wY; unsigned short wWidth; unsigned short wHeight; unsigned int dwBytesPerRow; } SUGGESTSETTING, *PSUGGESTSETTING; #endif sane-backends-1.0.27/backend/snapscan-sources.h0000664000175000017500000000752012775312261016263 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997, 1998 Franck Schnefra, Michel Roelofs, Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller, Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Oliver Schwartz and Kevin Charter This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is a component of the implementation of a backend for many of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */ /* $Id$ SnapScan backend scan data sources */ #ifndef SNAPSCAN_SOURCES_H #define SNAPSCAN_SOURCES_H typedef struct source Source; typedef SANE_Int (*SourceRemaining) (Source *ps); typedef SANE_Int (*SourceBytesPerLine) (Source *ps); typedef SANE_Int (*SourcePixelsPerLine) (Source *ps); typedef SANE_Status (*SourceGet) (Source *ps, SANE_Byte *pbuf, SANE_Int *plen); typedef SANE_Status (*SourceDone) (Source *ps); #define SOURCE_GUTS \ SnapScan_Scanner *pss;\ SourceRemaining remaining;\ SourceBytesPerLine bytesPerLine;\ SourcePixelsPerLine pixelsPerLine;\ SourceGet get;\ SourceDone done struct source { SOURCE_GUTS; }; static SANE_Status Source_init (Source *pself, SnapScan_Scanner *pss, SourceRemaining remaining, SourceBytesPerLine bytesPerLine, SourcePixelsPerLine pixelsPerLine, SourceGet get, SourceDone done); /* base sources */ #endif /* * $Log$ * Revision 1.5 2001/12/17 22:51:50 oliverschwartz * Update to snapscan-20011212 (snapscan 1.4.3) * * Revision 1.5 2001/12/12 19:44:59 oliverschwartz * Clean up CVS log * * Revision 1.4 2001/09/18 15:01:07 oliverschwartz * - Read scanner id string again after firmware upload * to indentify correct model * - Make firmware upload work for AGFA scanners * - Change copyright notice * * Revision 1.3 2001/03/17 22:53:21 sable * Applying Mikael Magnusson patch concerning Gamma correction * Support for 1212U_2 * * Revision 1.2 2000/10/13 03:50:27 cbagwell * Updating to source from SANE 1.0.3. Calling this versin 1.1 * */ sane-backends-1.0.27/backend/plustek-pp_p12ccd.c0000664000175000017500000013406212112021330016204 00000000000000/* @file plustek-pp_p12ccd.c * @brief here we have the whole code to intialize the CCD and DAC stuff * * based on sources acquired from Plustek Inc. * Copyright (C) 2000 Plustek Inc. * Copyright (C) 2001-2004 Gerhard Jaeger * * History: * - 0.38 - initial version * - 0.39 - using now fnDarkOffsetWolfson3797 instead of fnDarkOffsetWolfson3799 * This should provide a better picture quality on the GENIUS Colorpage * Vivid V2 * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** some definitions ********************************/ #define _REFLECTION 0 #define _TRANSPARENCY 1 #define _NEGATIVE 2 #define _NUM_OF_CCDREGS_W8143 25 #define _NUM_OF_DACREGS_W8143 10 #define _NUM_OF_CCDREGS_S1224 29 #define _NUM_OF_DACREGS_S1224 7 #define _NUM_OF_CCDREGS_S8531 29 #define _NUM_OF_DACREGS_S8531 9 #define _NUM_OF_CCDREGS_Max _NUM_OF_CCDREGS_S1224 #define _NUM_OF_DACREGS_Max _NUM_OF_DACREGS_W8143 /*************************** some local vars *********************************/ static pFnVoid p12ccdInitFunc = NULL; static RegDef W3797CCDParams[4][_NUM_OF_CCDREGS_W8143] = { { {0x2c, 0x02}, {0x39, 0x2a}, {0x3a, 0x0a}, {0x3b, 0x37}, {0x3c, 0x16}, {0x41, 0x0e}, {0x42, 0x90}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x03}, {0x48, 0x27}, {0x49, 0x2f}, {0x4a, 0x09}, {0x4b, 0x03}, {0x4c, 0x07}, {0x4d, 0x06}, {0x4e, 0x06}, {0x67, 0x00}, {0x50, 0x08}, {0x51, 0x0e}, {0x52, 0x0c}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x3d}, {0x3a, 0x04}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x1f}, {0x42, 0x8c}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x00}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x01}, {0x51, 0x06}, {0x52, 0x09}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x00}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x04}, {0x42, 0x1e}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xf9}, {0x4b, 0x04}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x03}, {0x67, 0x00}, {0x50, 0x06}, {0x51, 0x03}, {0x52, 0x09}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x18}, {0x3a, 0x04}, {0x3b, 0x1d}, {0x3c, 0x03}, {0x41, 0x0c}, {0x42, 0x84}, {0x43, 0x03}, {0x44, 0x0a}, {0x45, 0x08}, {0x46, 0xfa}, {0x47, 0x04}, {0x48, 0x0a}, {0x49, 0x08}, {0x4a, 0xf2}, {0x4b, 0x02}, {0x4c, 0x03}, {0x4d, 0x02}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x00}, {0x51, 0x09}, {0x52, 0x03}, {0x53, 0x03}, {0xf0, 0x00} } }; static RegDef W3799CCDParams[4][_NUM_OF_CCDREGS_W8143] = { { {0x2c, 0x02}, {0x39, 0x2c}, {0x3a, 0x05}, {0x3b, 0x3c}, {0x3c, 0x0e}, {0x41, 0x0e}, {0x42, 0x90}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x02}, {0x48, 0x27}, {0x49, 0x2f}, {0x4a, 0x09}, {0x4b, 0x05}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x06}, {0x67, 0x00}, {0x50, 0x08}, {0x51, 0x0d}, {0x52, 0x0c}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x3d}, {0x3a, 0x04}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x1f}, {0x42, 0x8c}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x00}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x01}, {0x51, 0x06}, {0x52, 0x12}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x00}, {0x39, 0x16}, {0x3a, 0x02}, {0x3b, 0x1a}, {0x3c, 0x05}, {0x41, 0x04}, {0x42, 0x1e}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xf9}, {0x4b, 0x04}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x03}, {0x67, 0x00}, {0x50, 0x06}, {0x51, 0x03}, {0x52, 0x09}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x18}, {0x3a, 0x04}, {0x3b, 0x1d}, {0x3c, 0x03}, {0x41, 0x0c}, {0x42, 0x84}, {0x43, 0x03}, {0x44, 0x0a}, {0x45, 0x08}, {0x46, 0xfa}, {0x47, 0x03}, {0x48, 0x0a}, {0x49, 0x08}, {0x4a, 0xf2}, {0x4b, 0x02}, {0x4c, 0x03}, {0x4d, 0x02}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x00}, {0x51, 0x09}, {0x52, 0x03}, {0x53, 0x03}, {0xf0, 0x00} } }; /* Genius ColorPage Vivid III */ static RegDef W548CCDParams[4][_NUM_OF_CCDREGS_W8143] = { { {0x2c, 0x02}, {0x39, 0x2c}, {0x3a, 0x05}, {0x3b, 0x3c}, {0x3c, 0x0e}, {0x41, 0x0e}, {0x42, 0x90}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x02}, {0x48, 0x27}, {0x49, 0x2f}, {0x4a, 0x09}, {0x4b, 0x05}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x06}, {0x67, 0x00}, {0x50, 0x08}, {0x51, 0x0d}, {0x52, 0x0c}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x3d}, {0x3a, 0x04}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x1f}, {0x42, 0x8c}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x00}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x01}, {0x51, 0x06}, {0x52, 0x12}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x00}, {0x39, 0x16}, {0x3a, 0x02}, {0x3b, 0x1a}, {0x3c, 0x05}, {0x41, 0x04}, {0x42, 0x1e}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xf9}, {0x4b, 0x04}, {0x4c, 0x07}, {0x4d, 0x05}, {0x4e, 0x03}, {0x67, 0x00}, {0x50, 0x06}, {0x51, 0x03}, {0x52, 0x09}, {0x53, 0x0b}, {0xf0, 0x00} }, { {0x2c, 0x02}, {0x39, 0x18}, {0x3a, 0x04}, {0x3b, 0x1d}, {0x3c, 0x03}, {0x41, 0x0c}, {0x42, 0x84}, {0x43, 0x03}, {0x44, 0x0a}, {0x45, 0x08}, {0x46, 0xfa}, {0x47, 0x03}, {0x48, 0x0a}, {0x49, 0x08}, {0x4a, 0xf2}, {0x4b, 0x02}, {0x4c, 0x03}, {0x4d, 0x02}, {0x4e, 0x0e}, {0x67, 0x00}, {0x50, 0x00}, {0x51, 0x09}, {0x52, 0x03}, {0x53, 0x03}, {0xf0, 0x00} } }; static RegDef S3797CCDParams[4][_NUM_OF_CCDREGS_S1224] = { { {0x2c, 0x00}, {0x39, 0x2a}, {0x3a, 0x0a}, {0x3b, 0x37}, {0x3c, 0x16}, {0x41, 0x2c}, {0x42, 0x9f}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x03}, {0x48, 0x27}, {0x49, 0x27}, {0x4a, 0x09}, {0x4b, 0x0b}, {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x0b}, {0x50, 0x13}, {0x51, 0x06}, {0x52, 0x06}, {0x53, 0x0b}, {0x67, 0x00}, {0x6f, 0x20}, {0x70, 0x06}, {0x60, 0x07}, {0x61, 0x9f}, {0x65, 0x01} }, { {0x2c, 0x00}, {0x39, 0x3d}, {0x3a, 0x06}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x3d}, {0x42, 0x92}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x1b}, {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x0b}, {0x50, 0x23}, {0x51, 0x06}, {0x52, 0x06}, {0x53, 0x0b}, {0x67, 0x00}, {0x6f, 0x30}, {0x70, 0x06}, {0x60, 0x17}, {0x61, 0x9f}, {0x65, 0x01} }, { {0x2c, 0x02}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x1c}, {0x42, 0x99}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x09}, {0x4c, 0x13}, {0x4d, 0x14}, {0x4e, 0x09}, {0x50, 0x09}, {0x51, 0x14}, {0x52, 0x13}, {0x53, 0x01}, {0x67, 0x00}, {0x6f, 0xff}, {0x70, 0x7f}, {0x60, 0x04}, {0x61, 0x8f}, {0x65, 0x01} }, { {0x2c, 0x02}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x1c}, {0x42, 0x99}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x02}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x09}, {0x4c, 0x13}, {0x4d, 0x14}, {0x4e, 0x09}, {0x50, 0x09}, {0x51, 0x14}, {0x52, 0x13}, {0x53, 0x01}, {0x67, 0x00}, {0x6f, 0xff}, {0x70, 0x7f}, {0x60, 0x04}, {0x61, 0x8f}, {0x65, 0x01} } }; static RegDef S3799CCDParams[4][_NUM_OF_CCDREGS_S1224] = { { {0x2c, 0x00}, {0x39, 0x2a}, {0x3a, 0x0a}, {0x3b, 0x37}, {0x3c, 0x16}, {0x41, 0x2c}, {0x42, 0x8f}, {0x43, 0x01}, {0x44, 0x27}, {0x45, 0x27}, {0x46, 0x01}, {0x47, 0x01}, {0x48, 0x27}, {0x49, 0x27}, {0x4a, 0x09}, {0x4b, 0x0b}, {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x0b}, {0x50, 0x13}, {0x51, 0x06}, {0x52, 0x06}, {0x53, 0x0b}, {0x67, 0x00}, {0x6f, 0x20}, {0x70, 0x06}, {0x60, 0x07}, {0x61, 0x9f}, {0x65, 0x01} }, { {0x2c, 0x00}, {0x39, 0x3d}, {0x3a, 0x06}, {0x3b, 0x46}, {0x3c, 0x06}, {0x41, 0x3d}, {0x42, 0x92}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf2}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x1b}, {0x4c, 0x06}, {0x4d, 0x06}, {0x4e, 0x0b}, {0x50, 0x23}, {0x51, 0x06}, {0x52, 0x06}, {0x53, 0x0b}, {0x67, 0x00}, {0x6f, 0x30}, {0x70, 0x06}, {0x60, 0x17}, {0x61, 0x9f}, {0x65, 0x01} }, { {0x2c, 0x02}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x1c}, {0x42, 0x99}, {0x43, 0x01}, {0x44, 0x13}, {0x45, 0x13}, {0x46, 0xf1}, {0x47, 0x01}, {0x48, 0x13}, {0x49, 0x13}, {0x4a, 0xfa}, {0x4b, 0x09}, {0x4c, 0x13}, {0x4d, 0x14}, {0x4e, 0x09}, {0x50, 0x09}, {0x51, 0x14}, {0x52, 0x13}, {0x53, 0x01}, {0x67, 0x00}, {0x6f, 0xff}, {0x70, 0x7f}, {0x60, 0x04}, {0x61, 0x8f}, {0x65, 0x01} }, { {0x2c, 0x00}, {0x39, 0x16}, {0x3a, 0x03}, {0x3b, 0x1f}, {0x3c, 0x07}, {0x41, 0x1c}, {0x42, 0x99}, {0x43, 0x03}, {0x44, 0x0a}, {0x45, 0x08}, {0x46, 0xfa}, {0x47, 0x03}, {0x48, 0x0a}, {0x49, 0x08}, {0x4a, 0xf2}, {0x4b, 0x02}, {0x4c, 0x03}, {0x4d, 0x02}, {0x4e, 0x0e}, {0x50, 0x00}, {0x51, 0x09}, {0x52, 0x03}, {0x53, 0x03}, {0x67, 0x00}, {0x6f, 0xff}, {0x70, 0x7f}, {0x60, 0x04}, {0x61, 0x8f}, {0x65, 0x01} } }; static RegDef WolfsonDAC8143[_NUM_OF_DACREGS_W8143] = { {0x01, 0x01}, {0x02, 0x04}, {0x03, 0x42}, {0x05, 0x10}, {0x20, 0xd0}, {0x21, 0xd0}, {0x22, 0xd0}, {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00} }; static RegDef SamsungDAC8531[_NUM_OF_DACREGS_S8531] = { {0x00, 0x51}, {0x02, 0x01}, {0x01, 0x80}, {0x00, 0x55}, {0x02, 0x01}, {0x01, 0x80}, {0x00, 0x59}, {0x02, 0x01}, {0x01, 0x80} }; static RegDef SamsungDAC1224[_NUM_OF_DACREGS_S1224] ={ {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x03, 0x80}, {0x04, 0x06}, {0x05, 0x06}, {0x06, 0x06} }; static DACTblDef ShadingVar3797[3] = { { {{99, 100, 94}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x04, 0x00, 0x00}}, {{0xcc, 0xcc, 0xcc}}, 0 }, { {{100, 90, 100}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0xcc, 0xcc, 0xcc}}, 0 }, { {{90, 90, 90}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x80, 0x80, 0x80}}, 0 } }; static DACTblDef ShadingVar3799[3] = { { {{100, 97, 92}}, {{0x90, 0xe0, 0x80}}, {{0x70, 0xc0, 0x60}}, {{0x90, 0x34, 0x3c}}, {{0x80, 0x80, 0x80}}, 0 }, { {{75, 75, 75}}, {{0x30, 0x30, 0x30}}, {{0x10, 0x10, 0x10}}, {{0x20, 0x20, 0x20}}, {{0x80, 0x80, 0x80}}, 0 }, { {{80, 75, 64}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x80, 0x80, 0x80}}, 0 } }; /* Genius ColorPage Vivid III */ static DACTblDef ShadingVar548[3] = { { {{100, 97, 92}}, {{0x90, 0xe0, 0x80}}, {{0x70, 0xc0, 0x60}}, {{0x90, 0x34, 0x3c}}, {{0x80, 0x80, 0x80}}, 0 }, { {{75, 75, 75}}, {{0x30, 0x30, 0x30}}, {{0x10, 0x10, 0x10}}, {{0x20, 0x20, 0x20}}, {{0x80, 0x80, 0x80}}, 0 }, { {{80, 75, 64}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x80, 0x80, 0x80}}, 0 } }; static DACTblDef ShadingVar3777[3] = { { {{100, 100, 100}}, {{0x90, 0xe0, 0x80}}, {{0x70, 0xc0, 0x60}}, {{0x90, 0x34, 0x3c}}, {{0x80, 0x80, 0x80}}, 0 }, { {{75, 75, 75}}, {{0x30, 0x30, 0x30}}, {{0x10, 0x10, 0x10}}, {{0x20, 0x20, 0x20}}, {{0x80, 0x80, 0x80}}, 0 }, { {{80, 75, 64}}, {{0x30, 0x30, 0x30}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x80, 0x80, 0x80}}, 0 } }; /*************************** local functions *********************************/ /*............................................................................. * */ static void fnCCDInitWolfson3797( pScanData ps ) { if( ps->Shade.bIntermediate & _ScanMode_Mono ) ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xcc; else if (ps->Shade.bIntermediate & _ScanMode_AverageOut) ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x68; else ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xa0; if((ps->Shade.bIntermediate & _ScanMode_AverageOut) || (ps->DataInf.dwScanFlag & SCANDEF_Negative)) WolfsonDAC8143[3].bParam = 0x12; else WolfsonDAC8143[3].bParam = 0x10; } /*............................................................................. * */ static void fnCCDInitSamsung3797( pScanData ps ) { if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) { if (!(ps->Shade.bIntermediate & _ScanMode_AverageOut)) { if( ps->Device.bPCBID == _OPTICWORKS2000 ) { ps->Shade.pCcdDac->GainResize.Colors.Red = 102; ps->Shade.pCcdDac->GainResize.Colors.Green = 102; ps->Shade.pCcdDac->GainResize.Colors.Blue = 97; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x40; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x40; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x40; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x40; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x40; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x38; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x38; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x40; } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 99; ps->Shade.pCcdDac->GainResize.Colors.Green = 101; ps->Shade.pCcdDac->GainResize.Colors.Blue = 94; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x40; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x40; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x40; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x04; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x00; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x00; } } else { if( ps->Device.bPCBID == _OPTICWORKS2000 ) { ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 100; ps->Shade.pCcdDac->GainResize.Colors.Blue = 96; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x48; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x48; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x38; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x38; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x38; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x48; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x48; } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 100; /* 98 */ ps->Shade.pCcdDac->GainResize.Colors.Green = 103; /* 106 */ ps->Shade.pCcdDac->GainResize.Colors.Blue = 96; /* 96 */ ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x10; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x10; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x110; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x1f0; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x190; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x100; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x1e0; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x180; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x10; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x20; } } } } /*............................................................................. * */ static void fnCCDInitWolfson3799( pScanData ps ) { if(!(ps->DataInf.dwScanFlag & SCANDEF_Negative)) { if (!(ps->Shade.bIntermediate & _ScanMode_AverageOut)) { ps->Shade.pCcdDac->GainResize.Colors.Red = 103; ps->Shade.pCcdDac->GainResize.Colors.Green = 102; ps->Shade.pCcdDac->GainResize.Colors.Blue = 99; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xc8; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xc8; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xc8; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x40; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x18; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x2c; } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 98; ps->Shade.pCcdDac->GainResize.Colors.Blue = 95; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xd0; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xd0; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xd0; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x0; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x0; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x0; } } else { ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x80; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = -0x38; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = -0x108; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = -0x1c8; } } /*............................................................................. * Genius ColorPage VIVID III */ static void fnCCDInitWolfson548( pScanData ps ) { if (!(ps->Shade.bIntermediate & _ScanMode_AverageOut)) { ps->Shade.pCcdDac->GainResize.Colors.Red = 103; ps->Shade.pCcdDac->GainResize.Colors.Green = 102; ps->Shade.pCcdDac->GainResize.Colors.Blue = 99; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xc8; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xc8; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xc8; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x40; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x18; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x2c; } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 98; ps->Shade.pCcdDac->GainResize.Colors.Blue = 95; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xd0; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xd0; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xd0; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x0; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x0; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x0; } } /*............................................................................. * */ static void fnCCDInitSamsung3777( pScanData ps ) { if(!(ps->DataInf.dwScanFlag & SCANDEF_Negative)) { if (!(ps->Shade.bIntermediate & _ScanMode_AverageOut)) { ps->Shade.pCcdDac->GainResize.Colors.Red = 109; ps->Shade.pCcdDac->GainResize.Colors.Green = 108; ps->Shade.pCcdDac->GainResize.Colors.Blue = 105; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x4a; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x4a; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x4a; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x3c; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x38; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x38; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x2c; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x3C; } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 108; ps->Shade.pCcdDac->GainResize.Colors.Green = 107; ps->Shade.pCcdDac->GainResize.Colors.Blue = 104; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x50; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x50; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x50; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x40; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x40; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x40; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x20; } } else { ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x80; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = -0x38; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = -0x108; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = -0x1c8; } } /*............................................................................. * */ static void fnCCDInitSamsung3799( pScanData ps ) { if(!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) { if (!(ps->Shade.bIntermediate & _ScanMode_AverageOut)) { if( ps->Device.bPCBID == _SCANNER2Button ) { ps->Shade.pCcdDac->GainResize.Colors.Red = 109; ps->Shade.pCcdDac->GainResize.Colors.Green = 109; ps->Shade.pCcdDac->GainResize.Colors.Blue = 105; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x68; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x68; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x68; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x24; /* 0 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x20; /* 0 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x1c; /* 0 */ } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 98; ps->Shade.pCcdDac->GainResize.Colors.Green = 97; ps->Shade.pCcdDac->GainResize.Colors.Blue = 92; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x90; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x90; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x90; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0xc0; /* 0x90 */ ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0xc0; /* 0xe0 */ ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0xc0; /* 0x80 */ ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0xb0; /* 0x70 */ ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0xb0; /* 0xc0 */ ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0xb0; /* 0x60 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x24; /* 0x90 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x00; /* 0x34 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x0c; /* 0x3c */ } } else { if( ps->Device.bPCBID == _SCANNER2Button ) { ps->Shade.pCcdDac->GainResize.Colors.Red = 107; ps->Shade.pCcdDac->GainResize.Colors.Green = 106; ps->Shade.pCcdDac->GainResize.Colors.Blue = 103; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x48; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x48; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x28; /* 0 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x18; /* 0 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x20; /* 0 */ } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 104; ps->Shade.pCcdDac->GainResize.Colors.Green = 107; ps->Shade.pCcdDac->GainResize.Colors.Blue = 99; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x30; /* 0x80 */ ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x30; /* 0x0a0 */ ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x150; /* 0x170 */ ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x130; /* 0x90 */ ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x110; /* 0x130 */ ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x140; /* 0x150 */ ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x120; /* 0x70 */ ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x100; /* 0x120 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0xF0; /* 0x90 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0xD4; /* 0x50 */ ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0xCC; /* 0x60 */ } } } } /*............................................................................. * */ static void fnCCDInitESIC3799( pScanData ps ) { if(!(ps->DataInf.dwScanFlag & SCANDEF_Negative)) { if (!(ps->Shade.bIntermediate & _ScanMode_AverageOut)) { ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 99; ps->Shade.pCcdDac->GainResize.Colors.Blue = 94; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xc8; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xc8; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xc8; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x58; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x38; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x48; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x48; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x38; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x58; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x38; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x48; } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 98; ps->Shade.pCcdDac->GainResize.Colors.Blue = 93; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xd0; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xd0; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xd0; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x108; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0xf8; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0xc8; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x100; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0xf0; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0xc0; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x108; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0xf8; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0xc8; } } else { ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x80; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = -0x38; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = -0x38; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = -0x38; } } /*............................................................................. * */ static void fnDarkOffsetWolfson3797( pScanData ps, pDACTblDef pDacTbl, ULong dwCh ) { if(( ps->Shade.DarkOffset.wColors[dwCh] -= pDacTbl->DarkOffSub.wColors[dwCh]) > 0xfff ) { ps->Shade.DarkOffset.wColors[dwCh] = 0; } } /*............................................................................. * this function was defined in the original sources, but never used... */ #if 0 static void fnDarkOffsetWolfson3799( pScanData ps, pDACTblDef pDacTbl, ULong dwCh ) { if( ps->Shade.DarkOffset.wColors[dwCh] > pDacTbl->DarkOffSub.wColors[dwCh]) ps->Shade.DarkOffset.wColors[dwCh] -= pDacTbl->DarkOffSub.wColors[dwCh]; else ps->Shade.DarkOffset.wColors[dwCh] = 0; } #endif /*............................................................................. * */ static void fnDarkOffsetSamsung3777( pScanData ps, pDACTblDef pDacTbl, ULong dwCh ) { ps->Shade.DarkOffset.wColors[dwCh] += pDacTbl->DarkOffSub.wColors [dwCh]; } /*............................................................................. * */ static void fnDarkOffsetSamsung3797( pScanData ps, pDACTblDef pDacTbl, ULong dwCh ) { if( ps->Shade.DarkOffset.wColors[dwCh] > pDacTbl->DarkOffSub.wColors[dwCh] ) ps->Shade.DarkOffset.wColors[dwCh] -= pDacTbl->DarkOffSub.wColors[dwCh]; else ps->Shade.DarkOffset.wColors[dwCh] = 0; } /*............................................................................. * */ static void fnDarkOffsetSamsung3799( pScanData ps, pDACTblDef pDacTbl, ULong dwCh ) { if( ps->Shade.DarkOffset.wColors[dwCh] > pDacTbl->DarkOffSub.wColors[dwCh]) ps->Shade.DarkOffset.wColors[dwCh] -= pDacTbl->DarkOffSub.wColors[dwCh]; else ps->Shade.DarkOffset.wColors[dwCh] = 0; } /*............................................................................. * */ static void fnDACDarkWolfson( pScanData ps, pDACTblDef pDacTbl, ULong dwCh, UShort wDarkest ) { UShort w; w = ps->Shade.DarkDAC.bColors[dwCh]; if (wDarkest > pDacTbl->DarkCmpHi.wColors[dwCh] ) { wDarkest -= pDacTbl->DarkCmpHi.wColors[dwCh]; if (wDarkest > ps->Shade.wDarkLevels) w += (UShort)wDarkest / ps->Shade.wDarkLevels; else w++; if (w > 0xff) w = 0xff; if(w != (UShort)ps->Shade.DarkDAC.bColors[dwCh] ) { ps->Shade.DarkDAC.bColors[dwCh] = (Byte)w; ps->Shade.fStop = _FALSE; } } else if((wDarkest < pDacTbl->DarkCmpLo.wColors[dwCh]) && ps->Shade.DarkDAC.bColors[dwCh]) { if (wDarkest) w = (UShort)ps->Shade.DarkDAC.bColors[dwCh] - 2U; else w = (UShort)ps->Shade.DarkDAC.bColors[dwCh] - ps->Shade.wDarkLevels; if ((short) w < 0) w = 0; if (w != (UShort)ps->Shade.DarkDAC.bColors[dwCh] ) { ps->Shade.DarkDAC.bColors [dwCh] = (Byte)w; ps->Shade.fStop = _FALSE; } } } /*............................................................................. * */ static void fnDACDarkSamsung( pScanData ps, pDACTblDef pDacTbl, ULong dwCh, UShort wDarkest ) { UShort w; if( wDarkest > pDacTbl->DarkCmpHi.wColors[dwCh] ) { wDarkest -= pDacTbl->DarkCmpHi.wColors [dwCh]; if (wDarkest > ps->Shade.wDarkLevels) w = (UShort)ps->Shade.DarkDAC.bColors[dwCh] - wDarkest / ps->Shade.wDarkLevels; else w = (UShort)ps->Shade.DarkDAC.bColors[dwCh] - 1U; if((short) w < 0) w = 0; if(w != (UShort)ps->Shade.DarkDAC.bColors[dwCh]) { ps->Shade.DarkDAC.bColors [dwCh] = (Byte)w; ps->Shade.fStop = _FALSE; } } else if((wDarkest < pDacTbl->DarkCmpLo.wColors[dwCh]) && ps->Shade.DarkDAC.bColors[dwCh]) { if (wDarkest) w = (UShort)ps->Shade.DarkDAC.bColors[dwCh] + 2U; else w = ps->Shade.wDarkLevels + (UShort)ps->Shade.DarkDAC.bColors [dwCh]; if (w > 0xff) w = 0xff; if(w != (UShort)ps->Shade.DarkDAC.bColors[dwCh]) { ps->Shade.DarkDAC.bColors[dwCh] = (Byte)w; ps->Shade.fStop = _FALSE; } } } /************************ exported functions *********************************/ /*............................................................................. * according to detected CCD and DAC, we set their correct init values * and functions */ _LOC void P12InitCCDandDAC( pScanData ps, Bool shading ) { UShort w; pDACTblDef pDAC_CCD; /* some presets */ ps->Device.f0_8_16 = _FALSE; switch( ps->Device.bDACType ) { case _DA_WOLFSON8143: DBG( DBG_LOW, "WOLFSON 8143\n" ); switch( ps->Device.bCCDID ) { case _CCD_3797: DBG( DBG_LOW, "CCD-3797\n" ); pDAC_CCD = ShadingVar3797; p12ccdInitFunc = fnCCDInitWolfson3797; ps->Device.fnDarkOffset = fnDarkOffsetWolfson3797; ps->Device.fnDACDark = fnDACDarkWolfson; ps->Device.pCCDRegisters = (pRegDef)W3797CCDParams; break; case _CCD_548: DBG( DBG_LOW, "CCD-548\n" ); pDAC_CCD = ShadingVar548; p12ccdInitFunc = fnCCDInitWolfson548; ps->Device.fnDarkOffset = fnDarkOffsetWolfson3797; ps->Device.fnDACDark = fnDACDarkWolfson; ps->Device.pCCDRegisters = (pRegDef)W548CCDParams; break; default: DBG( DBG_LOW, "CCD-3799\n" ); pDAC_CCD = ShadingVar3799; p12ccdInitFunc = fnCCDInitWolfson3799; /* CHECK: org was to fnDarkOffsetWolfson3797 */ ps->Device.fnDarkOffset = fnDarkOffsetWolfson3797; ps->Device.fnDACDark = fnDACDarkWolfson; ps->Device.pCCDRegisters = (pRegDef)W3799CCDParams; } ps->Device.wNumCCDRegs = _NUM_OF_CCDREGS_W8143; ps->Device.wNumDACRegs = _NUM_OF_DACREGS_W8143; ps->Device.pDACRegisters = WolfsonDAC8143; ps->Device.RegDACOffset.Red = 0x20; ps->Device.RegDACOffset.Green = 0x21; ps->Device.RegDACOffset.Blue = 0x22; ps->Device.RegDACGain.Red = 0x28; ps->Device.RegDACGain.Green = 0x29; ps->Device.RegDACGain.Blue = 0x2a; if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) { ps->Shade.bUniGain = 1; ps->Shade.bGainDouble = 1; } else { ps->Shade.bUniGain = 2; ps->Shade.bGainDouble = 4; } ps->Shade.bMinGain = 1; ps->Shade.bMaxGain = 0x1f; ps->Shade.wDarkLevels = 10; if( ps->Shade.bIntermediate == _ScanMode_Color ) WolfsonDAC8143[2].bParam = 0x52; else WolfsonDAC8143[2].bParam = 0x42; if (ps->Shade.bIntermediate == _ScanMode_Mono ) WolfsonDAC8143 [0].bParam = 7; else WolfsonDAC8143 [0].bParam = 3; break; case _DA_SAMSUNG1224: DBG( DBG_LOW, "Samsung 1224\n" ); switch(ps->Device.bCCDID ) { case _CCD_3797: DBG( DBG_LOW, "CCD-3797\n" ); pDAC_CCD = ShadingVar3797; p12ccdInitFunc = fnCCDInitSamsung3797; ps->Device.fnDarkOffset = fnDarkOffsetSamsung3797; ps->Device.fnDACDark = fnDACDarkSamsung; ps->Device.pCCDRegisters = (pRegDef)S3797CCDParams; break; default: DBG( DBG_LOW, "CCD-3799\n" ); pDAC_CCD = ShadingVar3799; p12ccdInitFunc = fnCCDInitSamsung3799; ps->Device.fnDarkOffset = fnDarkOffsetSamsung3799; ps->Device.fnDACDark = fnDACDarkSamsung; ps->Device.pCCDRegisters = (pRegDef)S3799CCDParams; } ps->Device.wNumCCDRegs = _NUM_OF_CCDREGS_S1224; ps->Device.wNumDACRegs = _NUM_OF_DACREGS_S1224; ps->Device.pDACRegisters = SamsungDAC1224; ps->Device.RegDACOffset.Red = 1; ps->Device.RegDACOffset.Green = 2; ps->Device.RegDACOffset.Blue = 3; ps->Device.RegDACGain.Red = 4; ps->Device.RegDACGain.Green = 5; ps->Device.RegDACGain.Blue = 6; ps->Shade.bGainDouble = 6; ps->Shade.bUniGain = 7; ps->Shade.bMinGain = 0; ps->Shade.bMaxGain = 0x1f; ps->Shade.wDarkLevels = 10; if( ps->Shade.bIntermediate & _ScanMode_Mono ) SamsungDAC1224[0].bParam = 0x57; else SamsungDAC1224[0].bParam = 0x51; break; case _DA_ESIC: DBG( DBG_LOW, "ESIC\n" ); switch( ps->Device.bCCDID ) { case _CCD_3797: DBG( DBG_LOW, "CCD-3797\n" ); pDAC_CCD = ShadingVar3797; p12ccdInitFunc = fnCCDInitWolfson3797; ps->Device.fnDarkOffset = fnDarkOffsetWolfson3797; ps->Device.fnDACDark = fnDACDarkWolfson; ps->Device.pCCDRegisters = (pRegDef)W3797CCDParams; break; default: DBG( DBG_LOW, "CCD-3799\n" ); pDAC_CCD = ShadingVar3799; p12ccdInitFunc = fnCCDInitESIC3799; ps->Device.fnDarkOffset = fnDarkOffsetWolfson3797; ps->Device.fnDACDark = fnDACDarkWolfson; ps->Device.pCCDRegisters = (pRegDef)W3799CCDParams; } ps->Device.wNumCCDRegs = _NUM_OF_CCDREGS_W8143; ps->Device.wNumDACRegs = _NUM_OF_DACREGS_W8143; ps->Device.pDACRegisters = WolfsonDAC8143; ps->Device.RegDACOffset.Red = 0x20; ps->Device.RegDACOffset.Green = 0x21; ps->Device.RegDACOffset.Blue = 0x22; ps->Device.RegDACGain.Red = 0x28; ps->Device.RegDACGain.Green = 0x29; ps->Device.RegDACGain.Blue = 0x2a; if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) { ps->Shade.bUniGain = 1; ps->Shade.bGainDouble = 1; } else { ps->Shade.bUniGain = 2; ps->Shade.bGainDouble = 4; } ps->Shade.bMinGain = 1; ps->Shade.bMaxGain = 0x1f; ps->Shade.wDarkLevels = 10; if( ps->Shade.bIntermediate == _ScanMode_Color ) WolfsonDAC8143 [2].bParam = 0x52; else WolfsonDAC8143 [2].bParam = 0x42; if(ps->Shade.bIntermediate == _ScanMode_Mono ) WolfsonDAC8143[0].bParam = 7; else WolfsonDAC8143[0].bParam = 3; break; /* _DA_SAMSUNG8531 */ default: DBG( DBG_LOW, "SAMSUNG 8531\n" ); switch( ps->Device.bCCDID ) { case _CCD_3797: DBG( DBG_LOW, "CCD-3797\n" ); pDAC_CCD = ShadingVar3797; p12ccdInitFunc = fnCCDInitSamsung3797; ps->Device.fnDarkOffset = fnDarkOffsetSamsung3797; ps->Device.fnDACDark = fnDACDarkSamsung; ps->Device.pCCDRegisters = (pRegDef)S3797CCDParams; break; case _CCD_3777: DBG( DBG_LOW, "CCD-3777\n" ); pDAC_CCD = ShadingVar3777; p12ccdInitFunc = fnCCDInitSamsung3777; ps->Device.fnDarkOffset = fnDarkOffsetSamsung3777; ps->Device.fnDACDark = fnDACDarkSamsung; ps->Device.pCCDRegisters = (pRegDef)S3797CCDParams; ps->Device.f0_8_16 = _TRUE; break; default: DBG( DBG_LOW, "CCD-3799\n" ); pDAC_CCD = ShadingVar3799; p12ccdInitFunc = fnCCDInitSamsung3799; ps->Device.fnDarkOffset = fnDarkOffsetSamsung3799; ps->Device.fnDACDark = fnDACDarkSamsung; ps->Device.pCCDRegisters = (pRegDef)S3799CCDParams; } ps->Device.wNumCCDRegs = _NUM_OF_CCDREGS_S8531; ps->Device.wNumDACRegs = _NUM_OF_DACREGS_S8531; ps->Device.pDACRegisters = SamsungDAC8531; ps->Device.RegDACOffset.Red = ps->Device.RegDACOffset.Green = ps->Device.RegDACOffset.Blue = 1; ps->Device.RegDACGain.Red = ps->Device.RegDACGain.Green = ps->Device.RegDACGain.Blue = 2; ps->Shade.bGainDouble = 6; ps->Shade.bMinGain = 1; ps->Shade.bMaxGain = 0x1f; if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) ps->Shade.bUniGain = 2; else ps->Shade.bUniGain = 7; ps->Shade.wDarkLevels = 10; if( ps->Shade.bIntermediate & _ScanMode_Mono ) { SamsungDAC8531[0].bParam = 0x57; SamsungDAC8531[3].bParam = 0x57; SamsungDAC8531[6].bParam = 0x57; } else { SamsungDAC8531[0].bParam = 0x51; SamsungDAC8531[3].bParam = 0x55; SamsungDAC8531[6].bParam = 0x59; } } if( shading ) { if( !(ps->DataInf.dwScanFlag & SCANDEF_TPA)) ps->Shade.pCcdDac = &pDAC_CCD[_REFLECTION]; else { if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) ps->Shade.pCcdDac = &pDAC_CCD[_TRANSPARENCY]; else ps->Shade.pCcdDac = &pDAC_CCD[_NEGATIVE]; } } else ps->Shade.pCcdDac = &pDAC_CCD[_REFLECTION]; /* as we now have the correct init function, call it */ p12ccdInitFunc( ps ); DBG( DBG_IO, "Programming DAC (%u regs)\n", ps->Device.wNumDACRegs ); for(w = 0; w < ps->Device.wNumDACRegs; w++ ) { DBG( DBG_IO, "[0x%02x] = 0x%02x\n", ps->Device.pDACRegisters[w].bReg, ps->Device.pDACRegisters[w].bParam ); IODataRegisterToDAC( ps, ps->Device.pDACRegisters[w].bReg, ps->Device.pDACRegisters[w].bParam ); } } /* END PLUSTEK-PP_P12CCD.C ..................................................*/ sane-backends-1.0.27/backend/coolscan2.conf.in0000664000175000017500000000136212112021330015733 00000000000000# coolscan2.conf: sample configuration file for coolscan2 backend # # The following entrie checks for your scanner by manufacturer (SCSI) # and by vendor and product ID (USB). This is what the backend does when # no configuration file can be found. # auto # You can also configure the backend for specific device files, but this # should not normally be necessary (under Linux at least). # Syntax for specific devices: : # # For a SCSI scanner, uncomment and edit the following line: #scsi:/dev/scanner # # For a USB scanner, uncomment and edit the following line: #usb:/dev/usbscanner # # For an IEEE 1394 scanner, use the SBP2 protocol (under Linux, use the # sbp2 kernel module), and your scanner will be handled as a SCSI device. sane-backends-1.0.27/backend/qcam.h0000664000175000017500000001264312112021330013672 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 David Mosberger-Tang This file is part of the SANE package. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. Portions of this code are derived from Scott Laird's qcam driver. It's copyright notice is reproduced here: Copyright (C) 1996 by Scott Laird Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef qcam_h #define qcam_h #include "../include/sane/sane.h" typedef enum { QC_MONO = 0x01, QC_COLOR = 0x10 } QC_Model; typedef enum { QC_RES_LOW = 0, QC_RES_HIGH } QC_Resolution; /* commands common to all quick-cameras: */ typedef enum { QC_SEND_VIDEO_FRAME = 7, QC_SET_BRIGHTNESS = 11, QC_SET_TOP = 13, QC_SET_LEFT = 15, QC_SET_NUM_V = 17, QC_SET_NUM_H = 19, QC_SEND_VERSION = 23, QC_SET_BLACK = 29, QC_SET_WHITE = 31, QC_SET_SATURATION = 35, QC_SEND_STATUS = 41, QC_SET_SPEED = 45 } QC_Command; /* commands for grayscale camera: */ typedef enum { QC_MONO_SET_CONTRAST = 25, QC_MONO_AUTO_ADJUST_OFFSET = 27, QC_MONO_GET_OFFSET = 33 } QC_Mono_Command; /* commands for color camera: */ typedef enum { QC_COL_LOAD_RAM = 27, QC_COL_SET_HUE = 33, QC_COL_SET_CONTRAST = 37 } QC_Col_Command; typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_DEPTH, /* 4 or 6 (b&w) or 24 (color) */ OPT_RESOLUTION, /* resolution in pixels */ OPT_XFER_SCALE, /* transfer-scale */ OPT_DESPECKLE, /* turn on despeckling? */ OPT_TEST, /* test image */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_BLACK_LEVEL, OPT_WHITE_LEVEL, OPT_HUE, OPT_SATURATION, /* must come last: */ NUM_OPTIONS } QC_Option; typedef enum { QC_UNIDIR, QC_BIDIR } QC_Port_Mode; typedef struct { size_t num_bytes; /* # of bytes to read */ QC_Resolution resolution; /* high-resolution? */ SANE_Parameters params; /* other parameters */ u_int mode; /* qcam scan code (get video data command) */ int despeckle; /* apply despeckling filter? */ } QC_Scan_Request; typedef struct QC_Device { struct QC_Device * next; SANE_Device sane; QC_Port_Mode port_mode; int port; /* i/o port address */ int version; /* camera version */ int lock_fd; /* used for locking protocol */ } QC_Device; typedef struct QC_Scanner { struct QC_Scanner *next; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; QC_Resolution resolution; SANE_Parameters params; QC_Device *hw; SANE_Int user_corner; /* bitmask of user-selected coordinates */ SANE_Int value_changed; /* bitmask of options that were set */ SANE_Bool scanning; SANE_Bool deliver_eof; SANE_Bool holding_lock; /* are we holding the lock? */ /* state for reading a frame: */ size_t num_bytes; /* # of bytes read so far */ size_t bytes_per_frame; /* total number of bytes in frame */ /* state relating to the reader-process */ int reader_pid; /* -1 if there is no reader process (yet) */ int from_child; /* fd to read from child process*/ int to_child; /* fd to write to child */ int read_fd; /* used to read data */ /* internal state for qc_readbytes(): */ int readbytes_state; unsigned int saved_bits; } QC_Scanner; #endif /* qcam_h */ sane-backends-1.0.27/backend/hp4200.conf.in0000664000175000017500000000011412112021330014757 00000000000000# # Configuration file for the hp4200 backend # # HP4200 usb 0x03f0 0x0105 sane-backends-1.0.27/backend/hpljm1005.c0000664000175000017500000007217012112021330014365 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2007-2008 Philippe Rétornaz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This backend is for HP LaserJet M1005 MFP Highly inspired from the epson backend */ #define BUILD 1 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #define BACKEND_NAME hpljm1005 #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/saneopts.h" #define MAGIC_NUMBER 0x41535001 #define PKT_READ_STATUS 0x0 #define PKT_UNKNOW_1 0x1 #define PKT_START_SCAN 0x2 #define PKT_GO_IDLE 0x3 #define PKT_DATA 0x5 #define PKT_READCONF 0x6 #define PKT_SETCONF 0x7 #define PKT_END_DATA 0xe #define PKT_RESET 0x15 #define RED_LAYER 0x3 #define GREEN_LAYER 0x4 #define BLUE_LAYER 0x5 #define GRAY_LAYER 0x6 #define MIN_SCAN_ZONE 101 struct usbdev_s { SANE_Int vendor_id; SANE_Int product_id; SANE_String_Const vendor_s; SANE_String_Const model_s; SANE_String_Const type_s; }; /* Zero-terminated USB VID/PID array */ static struct usbdev_s usbid[] = { {0x03f0, 0x3b17, "Hewlett-Packard", "LaserJet M1005", "multi-function peripheral"}, {0x03f0, 0x5617, "Hewlett-Packard", "LaserJet M1120", "multi-function peripheral"}, {0x03f0, 0x5717, "Hewlett-Packard", "LaserJet M1120n", "multi-function peripheral"}, {0, 0, NULL, NULL, NULL}, {0, 0, NULL, NULL, NULL} }; static int cur_idx; #define BR_CONT_MIN 0x1 #define BR_CONT_MAX 0xb #define RGB 1 #define GRAY 0 #define MAX_X_H 0x350 #define MAX_Y_H 0x490 #define MAX_X_S 220 #define MAX_Y_S 330 #define OPTION_MAX 9 static SANE_Word resolution_list[] = { 7, 75, 100, 150, 200, 300, 600, 1200 }; static SANE_Range range_x = { 0, MAX_X_S, 0 }; static SANE_Range range_y = { 0, MAX_Y_S, 0 }; static SANE_Range range_br_cont = { BR_CONT_MIN, BR_CONT_MAX, 0 }; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; #define X1_OFFSET 2 #define X2_OFFSET 4 #define Y1_OFFSET 3 #define Y2_OFFSET 5 #define RES_OFFSET 1 #define COLOR_OFFSET 8 #define BRIGH_OFFSET 6 #define CONTR_OFFSET 7 #define STATUS_IDLE 0 #define STATUS_SCANNING 1 #define STATUS_CANCELING 2 struct device_s { struct device_s *next; SANE_String_Const devname; int idx; /* Index in the usbid array */ int dn; /* Usb "Handle" */ SANE_Option_Descriptor optiond[OPTION_MAX]; char *buffer; int bufs; int read_offset; int write_offset_r; int write_offset_g; int write_offset_b; int status; int width; int height; SANE_Word optionw[OPTION_MAX]; uint32_t conf_data[512]; uint32_t packet_data[512]; }; static void do_cancel(struct device_s *dev); static struct device_s *devlist_head; static int devlist_count; /* Number of element in the list */ /* * List of pointers to devices - will be dynamically allocated depending * on the number of devices found. */ static SANE_Device **devlist = NULL; /* round() is c99, so we provide our own, though this version wont return -0 */ static double round2(double x) { return (double)(x >= 0.0) ? (int)(x+0.5) : (int)(x-0.5); } static void update_img_size (struct device_s *dev) { int dx, dy; /* Only update the width when not scanning, * otherwise the scanner give us the correct width */ if (dev->status == STATUS_SCANNING) { dev->height = -1; return; } dx = dev->optionw[X2_OFFSET] - dev->optionw[X1_OFFSET]; dy = dev->optionw[Y2_OFFSET] - dev->optionw[Y1_OFFSET]; switch (dev->optionw[RES_OFFSET]) { case 75: dev->width = round2 ((dx / ((double) MAX_X_S)) * 640); dev->height = round2 ((dy / ((double) MAX_Y_S)) * 880); break; case 100: dev->width = round2 ((dx / ((double) MAX_X_S)) * 848); dev->height = round2 ((dy / ((double) MAX_Y_S)) * 1180); break; case 150: dev->width = round2 ((dx / ((double) MAX_X_S)) * 1264); dev->height = round2 ((dy / ((double) MAX_Y_S)) * 1775); break; case 200: dev->width = round2 ((dx / ((double) MAX_X_S)) * 1696); dev->height = round2 ((dy / ((double) MAX_Y_S)) * 2351); break; case 300: dev->width = round2 ((dx / ((double) MAX_X_S)) * 2528); dev->height = round2 ((dy / ((double) MAX_Y_S)) * 3510); break; case 600: dev->width = round2 ((dx / ((double) MAX_X_S)) * 5088); dev->height = round2 ((dy / ((double) MAX_Y_S)) * 7020); break; case 1200: dev->width = round2 ((dx / ((double) MAX_X_S)) * 10208); dev->height = round2 ((dy / ((double) MAX_Y_S)) * 14025); break; } DBG(2,"New image size: %dx%d\n",dev->width, dev->height); } /* This function is copy/pasted from the Epson backend */ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; i++) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status attach (SANE_String_Const devname) { struct device_s *dev; dev = malloc (sizeof (struct device_s)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (struct device_s)); dev->devname = devname; DBG(1,"New device found: %s\n",dev->devname); /* Init the whole structure with default values */ /* Number of options */ dev->optiond[0].name = ""; dev->optiond[0].title = NULL; dev->optiond[0].desc = NULL; dev->optiond[0].type = SANE_TYPE_INT; dev->optiond[0].unit = SANE_UNIT_NONE; dev->optiond[0].size = sizeof (SANE_Word); dev->optionw[0] = OPTION_MAX; /* resolution */ dev->optiond[RES_OFFSET].name = "resolution"; dev->optiond[RES_OFFSET].title = "resolution"; dev->optiond[RES_OFFSET].desc = "resolution"; dev->optiond[RES_OFFSET].type = SANE_TYPE_INT; dev->optiond[RES_OFFSET].unit = SANE_UNIT_DPI; dev->optiond[RES_OFFSET].type = SANE_TYPE_INT; dev->optiond[RES_OFFSET].size = sizeof (SANE_Word); dev->optiond[RES_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->optiond[RES_OFFSET].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->optiond[RES_OFFSET].constraint.word_list = resolution_list; dev->optionw[RES_OFFSET] = 75; /* scan area */ dev->optiond[X1_OFFSET].name = "tl-x"; dev->optiond[X1_OFFSET].title = "tl-x"; dev->optiond[X1_OFFSET].desc = "tl-x"; dev->optiond[X1_OFFSET].type = SANE_TYPE_INT; dev->optiond[X1_OFFSET].unit = SANE_UNIT_MM; dev->optiond[X1_OFFSET].size = sizeof (SANE_Word); dev->optiond[X1_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->optiond[X1_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->optiond[X1_OFFSET].constraint.range = &range_x; dev->optionw[X1_OFFSET] = 0; dev->optiond[Y1_OFFSET].name = "tl-y"; dev->optiond[Y1_OFFSET].title = "tl-y"; dev->optiond[Y1_OFFSET].desc = "tl-y"; dev->optiond[Y1_OFFSET].type = SANE_TYPE_INT; dev->optiond[Y1_OFFSET].unit = SANE_UNIT_MM; dev->optiond[Y1_OFFSET].size = sizeof (SANE_Word); dev->optiond[Y1_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->optiond[Y1_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->optiond[Y1_OFFSET].constraint.range = &range_y; dev->optionw[Y1_OFFSET] = 0; dev->optiond[X2_OFFSET].name = "br-x"; dev->optiond[X2_OFFSET].title = "br-x"; dev->optiond[X2_OFFSET].desc = "br-x"; dev->optiond[X2_OFFSET].type = SANE_TYPE_INT; dev->optiond[X2_OFFSET].unit = SANE_UNIT_MM; dev->optiond[X2_OFFSET].size = sizeof (SANE_Word); dev->optiond[X2_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->optiond[X2_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->optiond[X2_OFFSET].constraint.range = &range_x; dev->optionw[X2_OFFSET] = MAX_X_S; dev->optiond[Y2_OFFSET].name = "br-y"; dev->optiond[Y2_OFFSET].title = "br-y"; dev->optiond[Y2_OFFSET].desc = "br-y"; dev->optiond[Y2_OFFSET].type = SANE_TYPE_INT; dev->optiond[Y2_OFFSET].unit = SANE_UNIT_MM; dev->optiond[Y2_OFFSET].size = sizeof (SANE_Word); dev->optiond[Y2_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->optiond[Y2_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->optiond[Y2_OFFSET].constraint.range = &range_y; dev->optionw[Y2_OFFSET] = MAX_Y_S; /* brightness */ dev->optiond[BRIGH_OFFSET].name = "brightness"; dev->optiond[BRIGH_OFFSET].title = "Brightness"; dev->optiond[BRIGH_OFFSET].desc = "Set the brightness"; dev->optiond[BRIGH_OFFSET].type = SANE_TYPE_INT; dev->optiond[BRIGH_OFFSET].unit = SANE_UNIT_NONE; dev->optiond[BRIGH_OFFSET].size = sizeof (SANE_Word); dev->optiond[BRIGH_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->optiond[BRIGH_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->optiond[BRIGH_OFFSET].constraint.range = &range_br_cont; dev->optionw[BRIGH_OFFSET] = 0x6; /* contrast */ dev->optiond[CONTR_OFFSET].name = "contrast"; dev->optiond[CONTR_OFFSET].title = "Contrast"; dev->optiond[CONTR_OFFSET].desc = "Set the contrast"; dev->optiond[CONTR_OFFSET].type = SANE_TYPE_INT; dev->optiond[CONTR_OFFSET].unit = SANE_UNIT_NONE; dev->optiond[CONTR_OFFSET].size = sizeof (SANE_Word); dev->optiond[CONTR_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->optiond[CONTR_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->optiond[CONTR_OFFSET].constraint.range = &range_br_cont; dev->optionw[CONTR_OFFSET] = 0x6; /* Color */ dev->optiond[COLOR_OFFSET].name = SANE_NAME_SCAN_MODE; dev->optiond[COLOR_OFFSET].title = SANE_TITLE_SCAN_MODE; dev->optiond[COLOR_OFFSET].desc = SANE_DESC_SCAN_MODE; dev->optiond[COLOR_OFFSET].type = SANE_TYPE_STRING; dev->optiond[COLOR_OFFSET].size = max_string_size (mode_list); dev->optiond[COLOR_OFFSET].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; dev->optiond[COLOR_OFFSET].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->optiond[COLOR_OFFSET].constraint.string_list = mode_list; dev->optionw[COLOR_OFFSET] = RGB; dev->dn = 0; dev->idx = cur_idx; dev->status = STATUS_IDLE; dev->next = devlist_head; devlist_head = dev; devlist_count++; return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { if (version_code != NULL) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG_INIT(); sanei_usb_init (); return SANE_STATUS_GOOD; } void sane_exit (void) { /* free everything */ struct device_s *iter; if (devlist) { int i; for (i = 0; devlist[i]; i++) free (devlist[i]); free (devlist); devlist = NULL; } if (devlist_head) { iter = devlist_head->next; free (devlist_head); devlist_head = NULL; while (iter) { struct device_s *tmp = iter; iter = iter->next; free (tmp); } } devlist_count = 0; } SANE_Status sane_get_devices (const SANE_Device * **device_list, SANE_Bool __sane_unused__ local_only) { struct device_s *iter; int i; devlist_count = 0; if (devlist_head) { iter = devlist_head->next; free (devlist_head); devlist_head = NULL; while (iter) { struct device_s *tmp = iter; iter = iter->next; free (tmp); } } /* Rebuild our internal scanner list */ for (cur_idx = 0; usbid[cur_idx].vendor_id; cur_idx++) sanei_usb_find_devices (usbid[cur_idx].vendor_id, usbid[cur_idx].product_id, attach); if (devlist) { for (i = 0; devlist[i]; i++) free (devlist[i]); free (devlist); } /* rebuild the sane-API scanner list array */ devlist = malloc (sizeof (devlist[0]) * (devlist_count + 1)); if (!devlist) return SANE_STATUS_NO_MEM; memset (devlist, 0, sizeof (devlist[0]) * (devlist_count + 1)); for (i = 0, iter = devlist_head; i < devlist_count; i++, iter = iter->next) { devlist[i] = malloc (sizeof (SANE_Device)); if (!devlist[i]) { int j; for (j = 0; j < i; j++) free (devlist[j]); free (devlist); devlist = NULL; return SANE_STATUS_NO_MEM; } devlist[i]->name = iter->devname; devlist[i]->vendor = usbid[iter->idx].vendor_s; devlist[i]->model = usbid[iter->idx].model_s; devlist[i]->type = usbid[iter->idx].type_s; } if (device_list) *device_list = (const SANE_Device **) devlist; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h) { struct device_s *dev; int ret; if(!devlist_head) sane_get_devices(NULL,(SANE_Bool)0); dev = devlist_head; if (strlen (name)) for (; dev; dev = dev->next) if (!strcmp (name, dev->devname)) break; if (!dev) { DBG(1,"Unable to find device %s\n",name); return SANE_STATUS_INVAL; } DBG(1,"Found device %s\n",name); /* Now open the usb device */ ret = sanei_usb_open (name, &(dev->dn)); if (ret != SANE_STATUS_GOOD) { DBG(1,"Unable to open device %s\n",name); return ret; } /* Claim the first interface */ ret = sanei_usb_claim_interface (dev->dn, 0); if (ret != SANE_STATUS_GOOD) { sanei_usb_close (dev->dn); /* if we cannot claim the interface, this is because someone else is using it */ DBG(1,"Unable to claim scanner interface on device %s\n",name); return SANE_STATUS_DEVICE_BUSY; } #ifdef HAVE_SANEI_USB_SET_TIMEOUT sanei_usb_set_timeout (30000); /* 30s timeout */ #endif *h = dev; return SANE_STATUS_GOOD; } void sane_close (SANE_Handle h) { struct device_s *dev = (struct device_s *) h; /* Just in case if sane_cancel() is called * after starting a scan but not while a sane_read */ if (dev->status == STATUS_CANCELING) { do_cancel(dev); } sanei_usb_release_interface (dev->dn, 0); sanei_usb_close (dev->dn); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int option) { struct device_s *dev = (struct device_s *) h; if (option >= OPTION_MAX || option < 0) return NULL; return &(dev->optiond[option]); } static SANE_Status getvalue (SANE_Handle h, SANE_Int option, void *v) { struct device_s *dev = (struct device_s *) h; if (option != COLOR_OFFSET) *((SANE_Word *) v) = dev->optionw[option]; else { strcpy ((char *) v, dev->optiond[option].constraint.string_list[dev-> optionw[option]]); } return SANE_STATUS_GOOD; } static SANE_Status setvalue (SANE_Handle h, SANE_Int option, void *value, SANE_Int * info) { struct device_s *dev = (struct device_s *) h; SANE_Status status = SANE_STATUS_GOOD; int s_unit; int s_unit_2; if (option == 0) return SANE_STATUS_UNSUPPORTED; status = sanei_constrain_value (&(dev->optiond[option]), value, info); if (status != SANE_STATUS_GOOD) return status; if (info) *info |= SANE_INFO_RELOAD_PARAMS; switch (option) { case X1_OFFSET: dev->optionw[option] = *((SANE_Word *) value); s_unit = (int) round2 ((dev->optionw[option] / ((double) MAX_X_S)) * MAX_X_H); s_unit_2 = (int) round2 ((dev->optionw[X2_OFFSET] / ((double) MAX_X_S)) * MAX_X_H); if (abs (s_unit_2 - s_unit) < MIN_SCAN_ZONE) s_unit = s_unit_2 - MIN_SCAN_ZONE; dev->optionw[option] = round2 ((s_unit / ((double) MAX_X_H)) * MAX_X_S); if (info) *info |= SANE_INFO_INEXACT; break; case X2_OFFSET: /* X units */ /* convert into "scanner" unit, then back into mm */ dev->optionw[option] = *((SANE_Word *) value); s_unit = (int) round2 ((dev->optionw[option] / ((double) MAX_X_S)) * MAX_X_H); s_unit_2 = (int) round2 ((dev->optionw[X1_OFFSET] / ((double) MAX_X_S)) * MAX_X_H); if (abs (s_unit_2 - s_unit) < MIN_SCAN_ZONE) s_unit = s_unit_2 + MIN_SCAN_ZONE; dev->optionw[option] = round2 ((s_unit / ((double) MAX_X_H)) * MAX_X_S); if (info) *info |= SANE_INFO_INEXACT; break; case Y1_OFFSET: /* Y units */ dev->optionw[option] = *((SANE_Word *) value); s_unit = (int) round2 ((dev->optionw[option] / ((double) MAX_Y_S)) * MAX_Y_H); s_unit_2 = (int) round2 ((dev->optionw[Y2_OFFSET] / ((double) MAX_Y_S)) * MAX_Y_H); if (abs (s_unit_2 - s_unit) < MIN_SCAN_ZONE) s_unit = s_unit_2 - MIN_SCAN_ZONE; dev->optionw[option] = round2 ((s_unit / ((double) MAX_Y_H)) * MAX_Y_S); if (info) *info |= SANE_INFO_INEXACT; break; case Y2_OFFSET: /* Y units */ dev->optionw[option] = *((SANE_Word *) value); s_unit = (int) round2 ((dev->optionw[option] / ((double) MAX_Y_S)) * MAX_Y_H); s_unit_2 = (int) round2 ((dev->optionw[Y1_OFFSET] / ((double) MAX_Y_S)) * MAX_Y_H); if (abs (s_unit_2 - s_unit) < MIN_SCAN_ZONE) s_unit = s_unit_2 + MIN_SCAN_ZONE; dev->optionw[option] = round2 ((s_unit / ((double) MAX_Y_H)) * MAX_Y_S); if (info) *info |= SANE_INFO_INEXACT; break; case COLOR_OFFSET: if (!strcmp ((char *) value, mode_list[0])) dev->optionw[option] = GRAY; /* Gray */ else if (!strcmp ((char *) value, mode_list[1])) dev->optionw[option] = RGB; /* RGB */ else return SANE_STATUS_INVAL; break; default: dev->optionw[option] = *((SANE_Word *) value); } return SANE_STATUS_GOOD; } SANE_Status sane_control_option (SANE_Handle h, SANE_Int option, SANE_Action a, void *v, SANE_Int * i) { if (option < 0 || option >= OPTION_MAX) return SANE_STATUS_INVAL; if (i) *i = 0; switch (a) { case SANE_ACTION_GET_VALUE: return getvalue (h, option, v); case SANE_ACTION_SET_VALUE: return setvalue (h, option, v, i); default: return SANE_STATUS_INVAL; } } SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p) { struct device_s *dev = (struct device_s *) h; if (!p) return SANE_STATUS_INVAL; p->format = dev->optionw[COLOR_OFFSET] == RGB ? SANE_FRAME_RGB : SANE_FRAME_GRAY; p->last_frame = SANE_TRUE; p->depth = 8; update_img_size (dev); p->pixels_per_line = dev->width; p->lines = dev->height; p->bytes_per_line = p->pixels_per_line; if (p->format == SANE_FRAME_RGB) p->bytes_per_line *= 3; return SANE_STATUS_GOOD; } static void send_pkt (int command, int data_size, struct device_s *dev) { size_t size = 32; DBG(100,"Sending packet %d, next data size %d, device %s\n", command, data_size, dev->devname); memset (dev->packet_data, 0, size); dev->packet_data[0] = htonl (MAGIC_NUMBER); dev->packet_data[1] = htonl (command); dev->packet_data[5] = htonl (data_size); sanei_usb_write_bulk (dev->dn, (unsigned char *) dev->packet_data, &size); } /* s: printer status */ /* Return the next packet size */ static int wait_ack (struct device_s *dev, int *s) { SANE_Status ret; size_t size; DBG(100, "Waiting scanner answer on device %s\n",dev->devname); do { size = 32; ret = sanei_usb_read_bulk (dev->dn, (unsigned char *) dev->packet_data, &size); } while (SANE_STATUS_EOF == ret || size == 0); if (s) *s = ntohl (dev->packet_data[4]); return ntohl (dev->packet_data[5]); } static void send_conf (struct device_s *dev) { int y1, y2, x1, x2; size_t size = 100; DBG(100,"Sending configuration packet on device %s\n",dev->devname); y1 = (int) round2 ((dev->optionw[Y1_OFFSET] / ((double) MAX_Y_S)) * MAX_Y_H); y2 = (int) round2 ((dev->optionw[Y2_OFFSET] / ((double) MAX_Y_S)) * MAX_Y_H); x1 = (int) round2 ((dev->optionw[X1_OFFSET] / ((double) MAX_X_S)) * MAX_X_H); x2 = (int) round2 ((dev->optionw[X2_OFFSET] / ((double) MAX_X_S)) * MAX_X_H); DBG(100,"\t x1: %d, x2: %d, y1: %d, y2: %d\n",x1, x2, y1, y2); DBG(100,"\t brightness: %d, contrast: %d\n", dev->optionw[BRIGH_OFFSET], dev->optionw[CONTR_OFFSET]); DBG(100,"\t resolution: %d\n",dev->optionw[RES_OFFSET]); dev->conf_data[0] = htonl (0x15); dev->conf_data[1] = htonl (dev->optionw[BRIGH_OFFSET]); dev->conf_data[2] = htonl (dev->optionw[CONTR_OFFSET]); dev->conf_data[3] = htonl (dev->optionw[RES_OFFSET]); dev->conf_data[4] = htonl (0x1); dev->conf_data[5] = htonl (0x1); dev->conf_data[6] = htonl (0x1); dev->conf_data[7] = htonl (0x1); dev->conf_data[8] = 0; dev->conf_data[9] = 0; dev->conf_data[10] = htonl (0x8); dev->conf_data[11] = 0; dev->conf_data[12] = 0; dev->conf_data[13] = 0; dev->conf_data[14] = 0; dev->conf_data[16] = htonl (y1); dev->conf_data[17] = htonl (x1); dev->conf_data[18] = htonl (y2); dev->conf_data[19] = htonl (x2); dev->conf_data[20] = 0; dev->conf_data[21] = 0; dev->conf_data[22] = htonl (0x491); dev->conf_data[23] = htonl (0x352); if (dev->optionw[COLOR_OFFSET] == RGB) { dev->conf_data[15] = htonl (0x2); dev->conf_data[24] = htonl (0x1); DBG(100,"\t Scanning in RGB format\n"); } else { dev->conf_data[15] = htonl (0x6); dev->conf_data[24] = htonl (0x0); DBG(100,"\t Scanning in Grayscale format\n"); } sanei_usb_write_bulk (dev->dn, (unsigned char *) dev->conf_data, &size); } static SANE_Status get_data (struct device_s *dev) { int color; size_t size; int packet_size; unsigned char *buffer = (unsigned char *) dev->packet_data; if (dev->status == STATUS_IDLE) return SANE_STATUS_IO_ERROR; /* first wait a standard data pkt */ do { size = 32; sanei_usb_read_bulk (dev->dn, buffer, &size); if (size) { if (ntohl (dev->packet_data[0]) == MAGIC_NUMBER) { if (ntohl (dev->packet_data[1]) == PKT_DATA) break; if (ntohl (dev->packet_data[1]) == PKT_END_DATA) { dev->status = STATUS_IDLE; DBG(100,"End of scan encountered on device %s\n",dev->devname); send_pkt (PKT_GO_IDLE, 0, dev); wait_ack (dev, NULL); wait_ack (dev, NULL); send_pkt (PKT_UNKNOW_1, 0, dev); wait_ack (dev, NULL); send_pkt (PKT_RESET, 0, dev); sleep (2); /* Time for the scanning head to go back home */ return SANE_STATUS_EOF; } } } } while (1); packet_size = ntohl (dev->packet_data[5]); if (!dev->buffer) { dev->bufs = packet_size - 24 /* size of header */ ; if (dev->optionw[COLOR_OFFSET] == RGB) dev->bufs *= 3; dev->buffer = malloc (dev->bufs); if (!dev->buffer) return SANE_STATUS_NO_MEM; dev->write_offset_r = 0; dev->write_offset_g = 1; dev->write_offset_b = 2; } /* Get the "data header" */ do { size = 24; sanei_usb_read_bulk (dev->dn, buffer, &size); } while (!size); color = ntohl (dev->packet_data[0]); packet_size -= size; dev->width = ntohl (dev->packet_data[5]); DBG(100,"Got data size %d on device %s. Scan width: %d\n",packet_size, dev->devname, dev->width); /* Now, read the data */ do { int j; int i; int ret; do { size = packet_size > 512 ? 512 : packet_size; ret = sanei_usb_read_bulk (dev->dn, buffer, &size); } while (!size || ret != SANE_STATUS_GOOD); packet_size -= size; switch (color) { case RED_LAYER: DBG(101,"Got red layer data on device %s\n",dev->devname); i = dev->write_offset_r + 3 * size; if (i > dev->bufs) i = dev->bufs; for (j = 0; dev->write_offset_r < i; dev->write_offset_r += 3) dev->buffer[dev->write_offset_r] = buffer[j++]; break; case GREEN_LAYER: DBG(101,"Got green layer data on device %s\n",dev->devname); i = dev->write_offset_g + 3 * size; if (i > dev->bufs) i = dev->bufs; for (j = 0; dev->write_offset_g < i; dev->write_offset_g += 3) dev->buffer[dev->write_offset_g] = buffer[j++]; break; case BLUE_LAYER: DBG(101,"Got blue layer data on device %s\n",dev->devname); i = dev->write_offset_b + 3 * size; if (i > dev->bufs) i = dev->bufs; for (j = 0; dev->write_offset_b < i; dev->write_offset_b += 3) dev->buffer[dev->write_offset_b] = buffer[j++]; break; case GRAY_LAYER: DBG(101,"Got gray layer data on device %s\n",dev->devname); if (dev->write_offset_r + (int)size >= dev->bufs) size = dev->bufs - dev->write_offset_r; memcpy (dev->buffer + dev->write_offset_r, buffer, size); dev->write_offset_r += size; break; } } while (packet_size > 0); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle h) { struct device_s *dev = (struct device_s *) h; int status; size_t size; dev->read_offset = 0; dev->write_offset_r = 0; dev->write_offset_g = 1; dev->write_offset_b = 2; free (dev->buffer); dev->buffer = NULL; send_pkt (PKT_RESET, 0, dev); send_pkt (PKT_READ_STATUS, 0, dev); wait_ack (dev, &status); if (status) return SANE_STATUS_IO_ERROR; send_pkt (PKT_READCONF, 0, dev); if ((size = wait_ack (dev, NULL))) { sanei_usb_read_bulk (dev->dn, (unsigned char *) dev->conf_data, &size); } send_pkt (PKT_SETCONF, 100, dev); send_conf (dev); wait_ack (dev, NULL); send_pkt (PKT_START_SCAN, 0, dev); wait_ack (dev, NULL); if ((size = wait_ack (dev, NULL))) { sanei_usb_read_bulk (dev->dn, (unsigned char *) dev->conf_data, &size); } if ((size = wait_ack (dev, NULL))) { sanei_usb_read_bulk (dev->dn, (unsigned char *) dev->conf_data, &size); } if ((size = wait_ack (dev, NULL))) { sanei_usb_read_bulk (dev->dn, (unsigned char *) dev->conf_data, &size); } dev->status = STATUS_SCANNING; /* Get the first data */ return get_data (dev); } static void do_cancel(struct device_s *dev) { while (get_data (dev) == SANE_STATUS_GOOD); free (dev->buffer); dev->buffer = NULL; } static int min3 (int r, int g, int b) { /* Optimize me ! */ g--; b -= 2; if (r < g && r < b) return r; if (b < r && b < g) return b; return g; } SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) { struct device_s *dev = (struct device_s *) h; int available; int ret; *len = 0; if (dev->status == STATUS_IDLE) return SANE_STATUS_IO_ERROR; if (dev->optionw[COLOR_OFFSET] == RGB) { while (min3 (dev->write_offset_r, dev->write_offset_g, dev->write_offset_b) <= dev->read_offset) { ret = get_data (dev); if (ret != SANE_STATUS_GOOD) { if (min3 (dev->write_offset_r, dev->write_offset_g, dev->write_offset_b) <= dev->read_offset) return ret; } } available = min3 (dev->write_offset_r, dev->write_offset_g, dev->write_offset_b); } else { while (dev->write_offset_r <= dev->read_offset) { ret = get_data (dev); if (ret != SANE_STATUS_GOOD) if (dev->write_offset_r <= dev->read_offset) return ret; } available = dev->write_offset_r; } *len = available - dev->read_offset; if (*len > maxlen) *len = maxlen; memcpy (buf, dev->buffer + dev->read_offset, *len); dev->read_offset += *len; if (dev->read_offset == dev->bufs) { free (dev->buffer); dev->buffer = NULL; dev->read_offset = 0; dev->write_offset_r = 0; dev->write_offset_g = 1; dev->write_offset_b = 2; } /* Special case where sane_cancel is called while scanning */ if (dev->status == STATUS_CANCELING) { do_cancel(dev); return SANE_STATUS_CANCELLED; } return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle h) { struct device_s *dev = (struct device_s *) h; if (dev->status == STATUS_SCANNING) { dev->status = STATUS_CANCELING; return; } free (dev->buffer); dev->buffer = NULL; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/umax_pp.c0000664000175000017500000022425713106201017014431 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2001-2012 Stéphane Voltz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Umax PP flatbed scanners. */ /* CREDITS: Started by being a mere copy of mustek_pp by Jochen Eisinger then evolved in its own thing support for the 610P has been made possible thank to an hardware donation from William Stuart */ #include "../include/sane/config.h" #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #define DEBUG_NOT_STATIC #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #define BACKEND_NAME umax_pp #include "../include/sane/sanei_backend.h" #include "umax_pp_mid.h" #include "umax_pp.h" #ifdef DMALLOC #include "dmalloc.h" #endif #define UMAX_PP_CONFIG_FILE "umax_pp.conf" #define MIN(a,b) ((a) < (b) ? (a) : (b)) /* DEBUG * for debug output, set SANE_DEBUG_UMAX_PP to * 0 for nothing * 1 for errors * 2 for warnings * 3 for additional information * 4 for debug information * 5 for code flow protocol (there isn't any) * 129 if you want to know which parameters are unused */ /* history: * see Changelog */ #define UMAX_PP_BUILD 2301 #define UMAX_PP_STATE "release" static int num_devices = 0; static Umax_PP_Descriptor *devlist = NULL; static const SANE_Device **devarray = NULL; static Umax_PP_Device *first_dev = NULL; /* 2 Meg scan buffer */ static SANE_Word buf_size = 2048 * 1024; static SANE_Word red_gain = 0; static SANE_Word green_gain = 0; static SANE_Word blue_gain = 0; static SANE_Word red_offset = 0; static SANE_Word green_offset = 0; static SANE_Word blue_offset = 0; static SANE_Char scanner_vendor[128]=""; static SANE_Char scanner_name[128]=""; static SANE_Char scanner_model[128]=""; static SANE_Char astra[128]; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static const SANE_Range u4_range = { 0, /* minimum */ 15, /* maximum */ 0 /* quantization */ }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /* range for int value in [0-15] */ static const SANE_Range value16_range = { 0, /* minimum */ 15, /* maximum */ 1 /* quantization */ }; /* range for buffer size */ static const SANE_Range buffer_range = { 2048, /* minimum */ 4096 * 4096, /* maximum */ 1 /* quantization */ }; /* list of astra models */ static const SANE_String_Const astra_models[] = { "610", "1220", "1600", "2000", NULL }; #define UMAX_PP_CHANNEL_RED 0 #define UMAX_PP_CHANNEL_GREEN 1 #define UMAX_PP_CHANNEL_BLUE 2 #define UMAX_PP_CHANNEL_GRAY 1 #define UMAX_PP_STATE_SCANNING 2 #define UMAX_PP_STATE_CANCELLED 1 #define UMAX_PP_STATE_IDLE 0 #define UMAX_PP_MODE_LINEART 0 #define UMAX_PP_MODE_GRAYSCALE 1 #define UMAX_PP_MODE_COLOR 2 #define MM_TO_PIXEL(mm, res) (SANE_UNFIX(mm) * (float )res / MM_PER_INCH) #define PIXEL_TO_MM(px, res) (SANE_FIX((float )(px * MM_PER_INCH / (res / 10)) / 10.0)) #define UMAX_PP_DEFAULT_PORT "/dev/parport0" #define UMAX_PP_RESERVE 259200 /* * devname may be either an hardware address for direct I/O (0x378 for instance) * or the device name used by ppdev on linux systems (/dev/parport0 ) */ static SANE_Status umax_pp_attach (SANEI_Config * config, const char *devname) { Umax_PP_Descriptor *dev; int i; SANE_Status status = SANE_STATUS_GOOD; int ret, prt = 0, mdl; char model[32]; char name[64]; char *val; memset (name, 0, 64); if ((strlen (devname) < 3)) return SANE_STATUS_INVAL; sanei_umax_pp_setastra (atoi((SANE_Char *) config->values[CFG_ASTRA])); /* if the name begins with a slash, it's a device, else it's an addr */ if (devname != NULL) { if ((devname[0] == '/')) { strncpy (name, devname, 64); } else { if ((devname[0] == '0') && ((devname[1] == 'x') || (devname[1] == 'X'))) prt = strtol (devname + 2, NULL, 16); else prt = atoi (devname); } } for (i = 0; i < num_devices; i++) { if (devname[0] == '/') { if (strcmp (devlist[i].ppdevice, devname) == 0) return SANE_STATUS_GOOD; } else { if (strcmp (devlist[i].port, devname) == 0) return SANE_STATUS_GOOD; } } ret = sanei_umax_pp_attach (prt, name); switch (ret) { case UMAX1220P_OK: status = SANE_STATUS_GOOD; break; case UMAX1220P_BUSY: status = SANE_STATUS_DEVICE_BUSY; break; case UMAX1220P_TRANSPORT_FAILED: DBG (1, "umax_pp_attach: failed to init transport layer on %s\n", devname); status = SANE_STATUS_IO_ERROR; break; case UMAX1220P_PROBE_FAILED: DBG (1, "umax_pp_attach: failed to probe scanner on %s\n", devname); status = SANE_STATUS_IO_ERROR; break; } if (status != SANE_STATUS_GOOD) { DBG (2, "umax_pp_attach: couldn't attach to `%s' (%s)\n", devname, sane_strstatus (status)); DEBUG (); return status; } /* now look for the model */ do { ret = sanei_umax_pp_model (prt, &mdl); if (ret != UMAX1220P_OK) { DBG (1, "umax_pp_attach: waiting for busy scanner on %s\n", devname); } } while (ret == UMAX1220P_BUSY); if (ret != UMAX1220P_OK) { DBG (1, "umax_pp_attach: failed to recognize scanner model on %s\n", devname); return SANE_STATUS_IO_ERROR; } sprintf (model, "Astra %dP", mdl); dev = malloc (sizeof (Umax_PP_Descriptor) * (num_devices + 1)); if (dev == NULL) { DBG (2, "umax_pp_attach: not enough memory for device descriptor\n"); DEBUG (); return SANE_STATUS_NO_MEM; } memset (dev, 0, sizeof (Umax_PP_Descriptor) * (num_devices + 1)); if (num_devices > 0) { memcpy (dev + 1, devlist, sizeof (Umax_PP_Descriptor) * (num_devices)); free (devlist); } devlist = dev; num_devices++; /* if there are user provided values, use them */ val=(SANE_Char *) config->values[CFG_NAME]; if(strlen(val)==0) dev->sane.name = strdup (devname); else dev->sane.name = strdup (val); val=(SANE_Char *) config->values[CFG_VENDOR]; if(strlen(val)==0) dev->sane.vendor = strdup ("UMAX"); else dev->sane.vendor = strdup (val); dev->sane.type = "flatbed scanner"; if (devname[0] == '/') dev->ppdevice = strdup (devname); else dev->port = strdup (devname); dev->buf_size = buf_size; if (mdl > 610) { /* Astra 1220, 1600 and 2000 */ dev->max_res = 1200; dev->ccd_res = 600; dev->max_h_size = 5100; dev->max_v_size = 7000 - 8; /* -8: workaround 'y overflow bug at 600 dpi' */ } else { /* Astra 610 */ dev->max_res = 600; dev->ccd_res = 300; dev->max_h_size = 2550; dev->max_v_size = 3500; } val=(SANE_Char *) config->values[CFG_MODEL]; if(strlen(val)==0) dev->sane.model = strdup (model); else dev->sane.model = strdup (val); DBG (3, "umax_pp_attach: device %s attached\n", devname); return SANE_STATUS_GOOD; } /* * walk a port list and try to attach to them * */ static SANE_Int umax_pp_try_ports (SANEI_Config * config, char **ports) { int i; int rc = SANE_STATUS_INVAL; if (ports != NULL) { i = 0; rc = SANE_STATUS_INVAL; while (ports[i] != NULL) { if (rc != SANE_STATUS_GOOD) { DBG (3, "umax_pp_try_ports: trying port `%s'\n", ports[i]); rc = umax_pp_attach (config, ports[i]); if (rc != SANE_STATUS_GOOD) DBG (3, "umax_pp_try_ports: couldn't attach to port `%s'\n", ports[i]); else DBG (3, "umax_pp_try_ports: attach to port `%s' successful\n", ports[i]); } free (ports[i]); i++; } free (ports); } return rc; } /* * attempt to auto detect right parallel port * if safe set to SANE_TRUE, no direct hardware access * is tried */ static SANE_Int umax_pp_auto_attach (SANEI_Config * config, SANE_Int safe) { char **ports; int rc = SANE_STATUS_INVAL; /* safe tests: user parallel port devices */ ports = sanei_parport_find_device (); if (ports != NULL) rc = umax_pp_try_ports (config, ports); /* try for direct hardware access */ if ((safe != SANE_TRUE) && (rc != SANE_STATUS_GOOD)) { ports = sanei_parport_find_port (); if (ports != NULL) rc = umax_pp_try_ports (config, ports); } return rc; } /** callback use by sanei_configure_attach, it is called with the * device name to use for attach try. */ static SANE_Status umax_pp_configure_attach (SANEI_Config * config, const char *devname) { const char *lp; SANE_Char *token; SANE_Status status = SANE_STATUS_INVAL; /* check for mandatory 'port' token */ lp = sanei_config_get_string (devname, &token); if (strncmp (token, "port", 4) != 0) { DBG (3, "umax_pp_configure_attach: invalid port line `%s'\n", devname); free (token); return SANE_STATUS_INVAL; } free (token); /* get argument */ lp = sanei_config_get_string (lp, &token); /* if "safe-auto" or "auto" devname, use umax_pp_attach_auto */ if (strncmp (token, "safe-auto", 9) == 0) { status = umax_pp_auto_attach (config, SANE_TRUE); } else if (strncmp (token, "auto", 4) == 0) { status = umax_pp_auto_attach (config, SANE_FALSE); } else { status = umax_pp_attach (config, token); } free (token); return status; } static SANE_Int umax_pp_get_sync (SANE_Int dpi) { /* delta between color frames */ if (sanei_umax_pp_getastra () > 610) { switch (dpi) { case 1200: return 8; case 600: return 4; case 300: return 2; case 150: return 1; default: return 0; } } else { switch (dpi) { case 600: return 16; case 300: return 8; /* 8 double-checked */ case 150: /* wrong: 2, 3, 5 * double-checked : 4 */ return 4; default: return 2; /* 2 double-checked */ } } } static SANE_Status init_options (Umax_PP_Device * dev) { int i; /* sets initial option value to zero */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } dev->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ dev->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE_GROUP].name = ""; dev->opt[OPT_MODE_GROUP].desc = ""; dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].size = 10; dev->opt[OPT_MODE].constraint.string_list = mode_list; dev->val[OPT_MODE].s = strdup (mode_list[1]); /* resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RESOLUTION].constraint.range = &dev->dpi_range; dev->val[OPT_RESOLUTION].w = dev->dpi_range.min; /* preview */ dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; dev->opt[OPT_PREVIEW].size = sizeof (SANE_Word); dev->opt[OPT_PREVIEW].unit = SANE_UNIT_NONE; dev->val[OPT_PREVIEW].w = SANE_FALSE; /* gray preview */ dev->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW; dev->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW; dev->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW; dev->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL; dev->opt[OPT_GRAY_PREVIEW].size = sizeof (SANE_Word); dev->opt[OPT_GRAY_PREVIEW].unit = SANE_UNIT_NONE; dev->val[OPT_GRAY_PREVIEW].w = SANE_FALSE; /* "Geometry" group: */ dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); dev->opt[OPT_GEOMETRY_GROUP].desc = ""; dev->opt[OPT_GEOMETRY_GROUP].name = ""; dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_GEOMETRY_GROUP].size = 0; dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_INT; dev->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &dev->x_range; dev->val[OPT_TL_X].w = 0; /* top-left y */ dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_INT; dev->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &dev->y_range; dev->val[OPT_TL_Y].w = 0; /* bottom-right x */ dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_INT; dev->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &dev->x_range; dev->val[OPT_BR_X].w = dev->x_range.max; /* bottom-right y */ dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_INT; dev->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &dev->y_range; dev->val[OPT_BR_Y].w = dev->y_range.max; /* "Enhancement" group: */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; dev->opt[OPT_ENHANCEMENT_GROUP].name = ""; dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].cap |= SANE_CAP_ADVANCED; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* lamp control */ dev->opt[OPT_LAMP_CONTROL].name = "lamp-control"; dev->opt[OPT_LAMP_CONTROL].title = SANE_I18N ("Lamp on"); dev->opt[OPT_LAMP_CONTROL].desc = SANE_I18N ("Sets lamp on/off"); dev->opt[OPT_LAMP_CONTROL].type = SANE_TYPE_BOOL; dev->opt[OPT_LAMP_CONTROL].size = sizeof (SANE_Word); dev->opt[OPT_LAMP_CONTROL].unit = SANE_UNIT_NONE; dev->val[OPT_LAMP_CONTROL].w = SANE_TRUE; dev->opt[OPT_LAMP_CONTROL].cap |= SANE_CAP_ADVANCED; /* UTA control */ dev->opt[OPT_UTA_CONTROL].name = "UTA-control"; dev->opt[OPT_UTA_CONTROL].title = SANE_I18N ("UTA on"); dev->opt[OPT_UTA_CONTROL].desc = SANE_I18N ("Sets UTA on/off"); dev->opt[OPT_UTA_CONTROL].type = SANE_TYPE_BOOL; dev->opt[OPT_UTA_CONTROL].size = sizeof (SANE_Word); dev->opt[OPT_UTA_CONTROL].unit = SANE_UNIT_NONE; dev->val[OPT_UTA_CONTROL].w = SANE_TRUE; dev->opt[OPT_UTA_CONTROL].cap |= SANE_CAP_ADVANCED | SANE_CAP_INACTIVE; /* custom-gamma table */ dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_ADVANCED; dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* grayscale gamma vector */ dev->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; dev->val[OPT_GAMMA_VECTOR].wa = &dev->gamma_table[0][0]; /* red gamma vector */ dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; dev->val[OPT_GAMMA_VECTOR_R].wa = &dev->gamma_table[1][0]; /* green gamma vector */ dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; dev->val[OPT_GAMMA_VECTOR_G].wa = &dev->gamma_table[2][0]; /* blue gamma vector */ dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; dev->val[OPT_GAMMA_VECTOR_B].wa = &dev->gamma_table[3][0]; /* gain group */ dev->opt[OPT_MANUAL_GAIN].name = "manual-channel-gain"; dev->opt[OPT_MANUAL_GAIN].title = SANE_I18N ("Gain"); dev->opt[OPT_MANUAL_GAIN].desc = SANE_I18N ("Color channels gain settings"); dev->opt[OPT_MANUAL_GAIN].type = SANE_TYPE_BOOL; dev->opt[OPT_MANUAL_GAIN].cap |= SANE_CAP_ADVANCED; dev->val[OPT_MANUAL_GAIN].w = SANE_FALSE; /* gray gain */ dev->opt[OPT_GRAY_GAIN].name = "gray-gain"; dev->opt[OPT_GRAY_GAIN].title = SANE_I18N ("Gray gain"); dev->opt[OPT_GRAY_GAIN].desc = SANE_I18N ("Sets gray channel gain"); dev->opt[OPT_GRAY_GAIN].type = SANE_TYPE_INT; dev->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_GRAY_GAIN].unit = SANE_UNIT_NONE; dev->opt[OPT_GRAY_GAIN].size = sizeof (SANE_Int); dev->opt[OPT_GRAY_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GRAY_GAIN].constraint.range = &u4_range; dev->val[OPT_GRAY_GAIN].w = dev->gray_gain; /* red gain */ dev->opt[OPT_RED_GAIN].name = "red-gain"; dev->opt[OPT_RED_GAIN].title = SANE_I18N ("Red gain"); dev->opt[OPT_RED_GAIN].desc = SANE_I18N ("Sets red channel gain"); dev->opt[OPT_RED_GAIN].type = SANE_TYPE_INT; dev->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_RED_GAIN].unit = SANE_UNIT_NONE; dev->opt[OPT_RED_GAIN].size = sizeof (SANE_Int); dev->opt[OPT_RED_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RED_GAIN].constraint.range = &u4_range; dev->val[OPT_RED_GAIN].w = dev->red_gain; /* green gain */ dev->opt[OPT_GREEN_GAIN].name = "green-gain"; dev->opt[OPT_GREEN_GAIN].title = SANE_I18N ("Green gain"); dev->opt[OPT_GREEN_GAIN].desc = SANE_I18N ("Sets green channel gain"); dev->opt[OPT_GREEN_GAIN].type = SANE_TYPE_INT; dev->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_GREEN_GAIN].unit = SANE_UNIT_NONE; dev->opt[OPT_GREEN_GAIN].size = sizeof (SANE_Int); dev->opt[OPT_GREEN_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GREEN_GAIN].constraint.range = &u4_range; dev->val[OPT_GREEN_GAIN].w = dev->green_gain; /* blue gain */ dev->opt[OPT_BLUE_GAIN].name = "blue-gain"; dev->opt[OPT_BLUE_GAIN].title = SANE_I18N ("Blue gain"); dev->opt[OPT_BLUE_GAIN].desc = SANE_I18N ("Sets blue channel gain"); dev->opt[OPT_BLUE_GAIN].type = SANE_TYPE_INT; dev->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_BLUE_GAIN].unit = SANE_UNIT_NONE; dev->opt[OPT_BLUE_GAIN].size = sizeof (SANE_Int); dev->opt[OPT_BLUE_GAIN].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BLUE_GAIN].constraint.range = &u4_range; dev->val[OPT_BLUE_GAIN].w = dev->blue_gain; /* offset group */ dev->opt[OPT_MANUAL_OFFSET].name = "manual-offset"; dev->opt[OPT_MANUAL_OFFSET].title = SANE_I18N ("Offset"); dev->opt[OPT_MANUAL_OFFSET].desc = SANE_I18N ("Color channels offset settings"); dev->opt[OPT_MANUAL_OFFSET].type = SANE_TYPE_BOOL; dev->opt[OPT_MANUAL_OFFSET].cap |= SANE_CAP_ADVANCED; dev->val[OPT_MANUAL_OFFSET].w = SANE_FALSE; /* gray offset */ dev->opt[OPT_GRAY_OFFSET].name = "gray-offset"; dev->opt[OPT_GRAY_OFFSET].title = SANE_I18N ("Gray offset"); dev->opt[OPT_GRAY_OFFSET].desc = SANE_I18N ("Sets gray channel offset"); dev->opt[OPT_GRAY_OFFSET].type = SANE_TYPE_INT; dev->opt[OPT_GRAY_OFFSET].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_GRAY_OFFSET].unit = SANE_UNIT_NONE; dev->opt[OPT_GRAY_OFFSET].size = sizeof (SANE_Int); dev->opt[OPT_GRAY_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GRAY_OFFSET].constraint.range = &u4_range; dev->val[OPT_GRAY_OFFSET].w = dev->gray_offset; /* red offset */ dev->opt[OPT_RED_OFFSET].name = "red-offset"; dev->opt[OPT_RED_OFFSET].title = SANE_I18N ("Red offset"); dev->opt[OPT_RED_OFFSET].desc = SANE_I18N ("Sets red channel offset"); dev->opt[OPT_RED_OFFSET].type = SANE_TYPE_INT; dev->opt[OPT_RED_OFFSET].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_RED_OFFSET].unit = SANE_UNIT_NONE; dev->opt[OPT_RED_OFFSET].size = sizeof (SANE_Int); dev->opt[OPT_RED_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RED_OFFSET].constraint.range = &u4_range; dev->val[OPT_RED_OFFSET].w = dev->red_offset; /* green offset */ dev->opt[OPT_GREEN_OFFSET].name = "green-offset"; dev->opt[OPT_GREEN_OFFSET].title = SANE_I18N ("Green offset"); dev->opt[OPT_GREEN_OFFSET].desc = SANE_I18N ("Sets green channel offset"); dev->opt[OPT_GREEN_OFFSET].type = SANE_TYPE_INT; dev->opt[OPT_GREEN_OFFSET].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_GREEN_OFFSET].unit = SANE_UNIT_NONE; dev->opt[OPT_GREEN_OFFSET].size = sizeof (SANE_Int); dev->opt[OPT_GREEN_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GREEN_OFFSET].constraint.range = &u4_range; dev->val[OPT_GREEN_OFFSET].w = dev->green_offset; /* blue offset */ dev->opt[OPT_BLUE_OFFSET].name = "blue-offset"; dev->opt[OPT_BLUE_OFFSET].title = SANE_I18N ("Blue offset"); dev->opt[OPT_BLUE_OFFSET].desc = SANE_I18N ("Sets blue channel offset"); dev->opt[OPT_BLUE_OFFSET].type = SANE_TYPE_INT; dev->opt[OPT_BLUE_OFFSET].cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; dev->opt[OPT_BLUE_OFFSET].unit = SANE_UNIT_NONE; dev->opt[OPT_BLUE_OFFSET].size = sizeof (SANE_Int); dev->opt[OPT_BLUE_OFFSET].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BLUE_OFFSET].constraint.range = &u4_range; dev->val[OPT_BLUE_OFFSET].w = dev->blue_offset; return SANE_STATUS_GOOD; } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { SANE_Status status; SANEI_Config config; SANE_Option_Descriptor *options[NUM_CFG_OPTIONS]; void *values[NUM_CFG_OPTIONS]; int i = 0; DBG_INIT (); if (authorize != NULL) { DBG (2, "init: SANE_Auth_Callback not supported ...\n"); } if (version_code != NULL) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, UMAX_PP_BUILD); DBG (3, "init: SANE v%s, backend v%d.%d.%d-%s\n", VERSION, SANE_CURRENT_MAJOR, V_MINOR, UMAX_PP_BUILD, UMAX_PP_STATE); /* set up configuration options to parse */ options[CFG_BUFFER] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_BUFFER]->name = "buffer"; options[CFG_BUFFER]->type = SANE_TYPE_INT; options[CFG_BUFFER]->unit = SANE_UNIT_NONE; options[CFG_BUFFER]->size = sizeof (SANE_Word); options[CFG_BUFFER]->cap = SANE_CAP_SOFT_SELECT; options[CFG_BUFFER]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_BUFFER]->constraint.range = &buffer_range; values[CFG_BUFFER] = &buf_size; options[CFG_RED_GAIN] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_RED_GAIN]->name = "red-gain"; options[CFG_RED_GAIN]->type = SANE_TYPE_INT; options[CFG_RED_GAIN]->unit = SANE_UNIT_NONE; options[CFG_RED_GAIN]->size = sizeof (SANE_Word); options[CFG_RED_GAIN]->cap = SANE_CAP_SOFT_SELECT; options[CFG_RED_GAIN]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_RED_GAIN]->constraint.range = &value16_range; values[CFG_RED_GAIN] = &red_gain; options[CFG_GREEN_GAIN] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_GREEN_GAIN]->name = "green-gain"; options[CFG_GREEN_GAIN]->type = SANE_TYPE_INT; options[CFG_GREEN_GAIN]->unit = SANE_UNIT_NONE; options[CFG_GREEN_GAIN]->size = sizeof (SANE_Word); options[CFG_GREEN_GAIN]->cap = SANE_CAP_SOFT_SELECT; options[CFG_GREEN_GAIN]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_GREEN_GAIN]->constraint.range = &value16_range; values[CFG_GREEN_GAIN] = &green_gain; options[CFG_BLUE_GAIN] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_BLUE_GAIN]->name = "blue-gain"; options[CFG_BLUE_GAIN]->type = SANE_TYPE_INT; options[CFG_BLUE_GAIN]->unit = SANE_UNIT_NONE; options[CFG_BLUE_GAIN]->size = sizeof (SANE_Word); options[CFG_BLUE_GAIN]->cap = SANE_CAP_SOFT_SELECT; options[CFG_BLUE_GAIN]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_BLUE_GAIN]->constraint.range = &value16_range; values[CFG_BLUE_GAIN] = &blue_gain; options[CFG_RED_OFFSET] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_RED_OFFSET]->name = "red-offset"; options[CFG_RED_OFFSET]->type = SANE_TYPE_INT; options[CFG_RED_OFFSET]->unit = SANE_UNIT_NONE; options[CFG_RED_OFFSET]->size = sizeof (SANE_Word); options[CFG_RED_OFFSET]->cap = SANE_CAP_SOFT_SELECT; options[CFG_RED_OFFSET]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_RED_OFFSET]->constraint.range = &value16_range; values[CFG_RED_OFFSET] = &red_offset; options[CFG_GREEN_OFFSET] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_GREEN_OFFSET]->name = "green-offset"; options[CFG_GREEN_OFFSET]->type = SANE_TYPE_INT; options[CFG_GREEN_OFFSET]->unit = SANE_UNIT_NONE; options[CFG_GREEN_OFFSET]->size = sizeof (SANE_Word); options[CFG_GREEN_OFFSET]->cap = SANE_CAP_SOFT_SELECT; options[CFG_GREEN_OFFSET]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_GREEN_OFFSET]->constraint.range = &value16_range; values[CFG_GREEN_OFFSET] = &green_offset; options[CFG_BLUE_OFFSET] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_BLUE_OFFSET]->name = "blue-offset"; options[CFG_BLUE_OFFSET]->type = SANE_TYPE_INT; options[CFG_BLUE_OFFSET]->unit = SANE_UNIT_NONE; options[CFG_BLUE_OFFSET]->size = sizeof (SANE_Word); options[CFG_BLUE_OFFSET]->cap = SANE_CAP_SOFT_SELECT; options[CFG_BLUE_OFFSET]->constraint_type = SANE_CONSTRAINT_RANGE; options[CFG_BLUE_OFFSET]->constraint.range = &value16_range; values[CFG_BLUE_OFFSET] = &blue_offset; options[CFG_VENDOR] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_VENDOR]->name = "vendor"; options[CFG_VENDOR]->type = SANE_TYPE_STRING; options[CFG_VENDOR]->unit = SANE_UNIT_NONE; options[CFG_VENDOR]->size = 128; options[CFG_VENDOR]->cap = SANE_CAP_SOFT_SELECT; values[CFG_VENDOR] = scanner_vendor; options[CFG_NAME] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_NAME]->name = "name"; options[CFG_NAME]->type = SANE_TYPE_STRING; options[CFG_NAME]->unit = SANE_UNIT_NONE; options[CFG_NAME]->size = 128; options[CFG_NAME]->cap = SANE_CAP_SOFT_SELECT; values[CFG_NAME] = scanner_name; options[CFG_MODEL] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_MODEL]->name = "model"; options[CFG_MODEL]->type = SANE_TYPE_STRING; options[CFG_MODEL]->unit = SANE_UNIT_NONE; options[CFG_MODEL]->size = 128; options[CFG_MODEL]->cap = SANE_CAP_SOFT_SELECT; values[CFG_MODEL] = scanner_model; options[CFG_ASTRA] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[CFG_ASTRA]->name = "astra"; options[CFG_ASTRA]->type = SANE_TYPE_STRING; options[CFG_ASTRA]->unit = SANE_UNIT_NONE; options[CFG_ASTRA]->size = 128; options[CFG_ASTRA]->cap = SANE_CAP_SOFT_SELECT; options[CFG_ASTRA]->constraint_type = SANE_CONSTRAINT_STRING_LIST; options[CFG_ASTRA]->constraint.string_list = astra_models; values[CFG_ASTRA] = astra; config.descriptors = options; config.values = values; config.count = NUM_CFG_OPTIONS; /* generic configure and attach function */ status = sanei_configure_attach (UMAX_PP_CONFIG_FILE, &config, umax_pp_configure_attach); /* free option descriptors */ for (i = 0; i < NUM_CFG_OPTIONS; i++) { free (options[i]); } return status; } void sane_exit (void) { int i; Umax_PP_Device *dev; DBG (3, "sane_exit: (...)\n"); if (first_dev) DBG (3, "exit: closing open devices\n"); while (first_dev) { dev = first_dev; sane_close (dev); } for (i = 0; i < num_devices; i++) { free (devlist[i].port); free ((void *) devlist[i].sane.name); free ((void *) devlist[i].sane.model); free ((void *) devlist[i].sane.vendor); } if (devlist != NULL) { free (devlist); devlist = NULL; } if (devarray != NULL) { free (devarray); devarray = NULL; } /* reset values */ num_devices = 0; first_dev = NULL; red_gain = 0; green_gain = 0; blue_gain = 0; red_offset = 0; green_offset = 0; blue_offset = 0; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { int i; DBG (3, "get_devices\n"); DBG (129, "unused arg: local_only = %d\n", (int) local_only); if (devarray != NULL) { free (devarray); devarray = NULL; } devarray = malloc ((num_devices + 1) * sizeof (devarray[0])); if (devarray == NULL) { DBG (2, "get_devices: not enough memory for device list\n"); DEBUG (); return SANE_STATUS_NO_MEM; } for (i = 0; i < num_devices; i++) devarray[i] = &devlist[i].sane; devarray[num_devices] = NULL; *device_list = devarray; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Umax_PP_Device *dev; Umax_PP_Descriptor *desc; int i, j; int rc, prt = 0; char *name = NULL; DBG (3, "open: device `%s'\n", devicename); /* if no device given or 'umax_pp' default value given */ if (devicename == NULL || devicename[0] == 0 || strncmp (devicename, "umax_pp", 7) == 0) { if (num_devices == 0) { DBG (1, "open: no devices present\n"); return SANE_STATUS_INVAL; } DBG (3, "open: trying default device %s, port=%s,ppdev=%s\n", devlist[0].sane.name, devlist[0].port, devlist[0].ppdevice); if (devlist[0].port != NULL) { if ((devlist[0].port[0] == '0') && ((devlist[0].port[1] == 'x') || (devlist[0].port[1] == 'X'))) prt = strtol (devlist[0].port + 2, NULL, 16); else prt = atoi (devlist[0].port); rc = sanei_umax_pp_open (prt, NULL); } else { rc = sanei_umax_pp_open (0, devlist[0].ppdevice); } desc = &devlist[0]; } else /* specific value */ { for (i = 0; i < num_devices; i++) if (strcmp (devlist[i].sane.name, devicename) == 0) break; if (i >= num_devices) for (i = 0; i < num_devices; i++) if (strcmp (devlist[i].port, devicename) == 0) break; if (i >= num_devices) { DBG (2, "open: device doesn't exist\n"); DEBUG (); return SANE_STATUS_INVAL; } desc = &devlist[i]; if (devlist[i].ppdevice != NULL) { if (devlist[i].ppdevice[0] == '/') { name = devlist[i].ppdevice; } } else { if ((devlist[i].port[0] == '0') && ((devlist[i].port[1] == 'x') || (devlist[i].port[1] == 'X'))) prt = strtol (devlist[i].port + 2, NULL, 16); else prt = atoi (devlist[i].port); DBG (64, "open: devlist[i].port='%s' -> port=0x%X\n", devlist[i].port, prt); } rc = sanei_umax_pp_open (prt, name); } /* treat return code from open */ switch (rc) { case UMAX1220P_TRANSPORT_FAILED: if (name == NULL) { DBG (1, "failed to init transport layer on port 0x%03X\n", prt); } else { DBG (1, "failed to init transport layer on device %s\n", name); } return SANE_STATUS_IO_ERROR; case UMAX1220P_SCANNER_FAILED: if (name == NULL) { DBG (1, "failed to initialize scanner on port 0x%03X\n", prt); } else { DBG (1, "failed to initialize scanner on device %s\n", name); } return SANE_STATUS_IO_ERROR; case UMAX1220P_BUSY: if (name == NULL) { DBG (1, "busy scanner on port 0x%03X\n", prt); } else { DBG (1, "busy scanner on device %s\n", name); } return SANE_STATUS_DEVICE_BUSY; } dev = (Umax_PP_Device *) malloc (sizeof (*dev)); if (dev == NULL) { DBG (2, "open: not enough memory for device descriptor\n"); DEBUG (); return SANE_STATUS_NO_MEM; } memset (dev, 0, sizeof (*dev)); dev->desc = desc; for (i = 0; i < 4; ++i) for (j = 0; j < 256; ++j) dev->gamma_table[i][j] = j; /* the extra amount of UMAX_PP_RESERVE bytes is to handle */ /* the data needed to resync the color frames */ dev->buf = malloc (dev->desc->buf_size + UMAX_PP_RESERVE); dev->bufsize = dev->desc->buf_size; dev->dpi_range.min = SANE_FIX (75); dev->dpi_range.max = SANE_FIX (dev->desc->max_res); dev->dpi_range.quant = 0; dev->x_range.min = 0; dev->x_range.max = dev->desc->max_h_size; dev->x_range.quant = 0; dev->y_range.min = 0; dev->y_range.max = dev->desc->max_v_size; dev->y_range.quant = 0; dev->gray_gain = 0; /* use pre defined settings read from umax_pp.conf */ dev->red_gain = red_gain; dev->green_gain = green_gain; dev->blue_gain = blue_gain; dev->red_offset = red_offset; dev->green_offset = green_offset; dev->blue_offset = blue_offset; if (dev->buf == NULL) { DBG (2, "open: not enough memory for scan buffer (%lu bytes)\n", (long int) dev->desc->buf_size); DEBUG (); free (dev); return SANE_STATUS_NO_MEM; } init_options (dev); dev->next = first_dev; first_dev = dev; if (sanei_umax_pp_UTA () == 1) dev->opt[OPT_UTA_CONTROL].cap &= ~SANE_CAP_INACTIVE; *handle = dev; DBG (3, "open: success\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Umax_PP_Device *prev, *dev; int rc; DBG (3, "sane_close: ...\n"); /* remove handle from list of open handles: */ prev = NULL; for (dev = first_dev; dev; dev = dev->next) { if (dev == handle) break; prev = dev; } if (dev == NULL) { DBG (2, "close: unknown device\n"); DEBUG (); return; /* oops, not a handle we know about */ } if (dev->state == UMAX_PP_STATE_SCANNING) sane_cancel (handle); /* remember: sane_cancel is a macro and expands to sane_umax_pp_cancel ()... */ /* if the scanner is parking head, we wait it to finish */ while (dev->state == UMAX_PP_STATE_CANCELLED) { DBG (2, "close: waiting scanner to park head\n"); rc = sanei_umax_pp_status (); /* check if scanner busy parking */ if (rc != UMAX1220P_BUSY) { DBG (2, "close: scanner head parked\n"); dev->state = UMAX_PP_STATE_IDLE; } } /* then we switch off gain if needed */ if (dev->val[OPT_LAMP_CONTROL].w == SANE_TRUE) { rc = sanei_umax_pp_lamp (0); if (rc == UMAX1220P_TRANSPORT_FAILED) { DBG (1, "close: switch off gain failed (ignored....)\n"); } } sanei_umax_pp_close (); if (prev != NULL) prev->next = dev->next; else first_dev = dev->next; free (dev->buf); DBG (3, "close: device closed\n"); free (handle); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Umax_PP_Device *dev = handle; if ((unsigned) option >= NUM_OPTIONS) { DBG (2, "get_option_descriptor: option %d doesn't exist\n", option); DEBUG (); return NULL; } DBG (6, "get_option_descriptor: requested option %d (%s)\n", option, dev->opt[option].name); return dev->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Umax_PP_Device *dev = handle; SANE_Status status; SANE_Word w, cap, tmpw; int dpi, rc; DBG (6, "control_option: option %d, action %d\n", option, action); if (info) *info = 0; if (dev->state == UMAX_PP_STATE_SCANNING) { DBG (2, "control_option: device is scanning\n"); return SANE_STATUS_DEVICE_BUSY; } if ((unsigned int) option >= NUM_OPTIONS) { DBG (2, "control_option: option doesn't exist\n"); return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (2, "control_option: option isn't active\n"); return SANE_STATUS_INVAL; } DBG (6, "control_option: option <%s>, action ... %d\n", dev->opt[option].name, action); if (action == SANE_ACTION_GET_VALUE) { DBG (6, " get value\n"); switch (option) { /* word options: */ case OPT_PREVIEW: case OPT_GRAY_PREVIEW: case OPT_LAMP_CONTROL: case OPT_UTA_CONTROL: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_CUSTOM_GAMMA: case OPT_MANUAL_GAIN: case OPT_GRAY_GAIN: case OPT_GREEN_GAIN: case OPT_RED_GAIN: case OPT_BLUE_GAIN: case OPT_MANUAL_OFFSET: case OPT_GRAY_OFFSET: case OPT_GREEN_OFFSET: case OPT_RED_OFFSET: case OPT_BLUE_OFFSET: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, dev->val[option].wa, dev->opt[option].size); return SANE_STATUS_GOOD; /* string options: */ case OPT_MODE: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { DBG (6, " set value\n"); if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (2, "control_option: option can't be set\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (2, "control_option: constrain_value failed (%s)\n", sane_strstatus (status)); return status; } if (option == OPT_RESOLUTION) { DBG (16, "control_option: setting resolution to %d\n", *(SANE_Int *) val); } if (option == OPT_PREVIEW) { DBG (16, "control_option: setting preview to %d\n", *(SANE_Word *) val); } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_PREVIEW: case OPT_GRAY_PREVIEW: case OPT_TL_Y: case OPT_BR_Y: if (info) *info |= SANE_INFO_RELOAD_PARAMS; case OPT_GRAY_GAIN: case OPT_GREEN_GAIN: case OPT_RED_GAIN: case OPT_BLUE_GAIN: case OPT_GRAY_OFFSET: case OPT_GREEN_OFFSET: case OPT_RED_OFFSET: case OPT_BLUE_OFFSET: dev->val[option].w = *(SANE_Word *) val; /* sanity check */ if (dev->val[OPT_BR_Y].w < dev->val[OPT_TL_Y].w) { tmpw = dev->val[OPT_BR_Y].w; dev->val[OPT_BR_Y].w = dev->val[OPT_TL_Y].w; dev->val[OPT_TL_Y].w = tmpw; if (info) *info |= SANE_INFO_INEXACT; DBG (16, "control_option: swapping Y coordinates\n"); } if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dpi = (int) (SANE_UNFIX (dev->val[OPT_RESOLUTION].w)); if (dev->val[OPT_TL_Y].w < 2 * umax_pp_get_sync (dpi)) { DBG (16, "control_option: correcting TL_Y coordinates\n"); dev->val[OPT_TL_Y].w = 2 * umax_pp_get_sync (dpi); if (info) *info |= SANE_INFO_INEXACT; } } return SANE_STATUS_GOOD; /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (dev->val[option].wa, val, dev->opt[option].size); return SANE_STATUS_GOOD; /* options with side-effects: */ case OPT_UTA_CONTROL: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_LAMP_CONTROL: if (dev->state != UMAX_PP_STATE_IDLE) { rc = sanei_umax_pp_status (); /* check if scanner busy parking */ if (rc == UMAX1220P_BUSY) { DBG (2, "control_option: scanner busy\n"); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_DEVICE_BUSY; } dev->state = UMAX_PP_STATE_IDLE; } dev->val[option].w = *(SANE_Word *) val; if (dev->val[option].w == SANE_TRUE) rc = sanei_umax_pp_lamp (1); else rc = sanei_umax_pp_lamp (0); if (rc == UMAX1220P_TRANSPORT_FAILED) return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; case OPT_TL_X: case OPT_BR_X: if (info) *info |= SANE_INFO_RELOAD_PARAMS; dpi = (int) (SANE_UNFIX (dev->val[OPT_RESOLUTION].w)); dev->val[option].w = *(SANE_Word *) val; /* coords rounded to allow 32 bit IO/transfer */ /* at high resolution */ if (dpi >= 600) { if (dev->val[option].w & 0x03) { if (info) *info |= SANE_INFO_INEXACT; dev->val[option].w = dev->val[option].w & 0xFFFC; *(SANE_Word *) val = dev->val[option].w; DBG (16, "control_option: rounding X to %d\n", *(SANE_Word *) val); } } /* sanity check */ if (dev->val[OPT_BR_X].w < dev->val[OPT_TL_X].w) { tmpw = dev->val[OPT_BR_X].w; dev->val[OPT_BR_X].w = dev->val[OPT_TL_X].w; dev->val[OPT_TL_X].w = tmpw; if (info) *info |= SANE_INFO_INEXACT; DBG (16, "control_option: swapping X coordinates\n"); } return SANE_STATUS_GOOD; case OPT_RESOLUTION: if (info) *info |= SANE_INFO_RELOAD_PARAMS; /* resolution : only have 75, 150, 300, 600 and 1200 */ dpi = (int) (SANE_UNFIX (*(SANE_Word *) val)); if ((dpi != 75) && (dpi != 150) && (dpi != 300) && (dpi != 600) && (dpi != 1200)) { if (dpi <= 75) dpi = 75; else if (dpi <= 150) dpi = 150; else if (dpi <= 300) dpi = 300; else if (dpi <= 600) dpi = 600; else dpi = 1200; if (info) *info |= SANE_INFO_INEXACT; *(SANE_Word *) val = SANE_FIX ((SANE_Word) dpi); } dev->val[option].w = *(SANE_Word *) val; /* correct top x and bottom x if needed */ if (dpi >= 600) { dev->val[OPT_TL_X].w = dev->val[OPT_TL_X].w & 0xFFFC; dev->val[OPT_BR_X].w = dev->val[OPT_BR_X].w & 0xFFFC; } /* corrects top y for offset */ if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { if (dev->val[OPT_TL_Y].w < 2 * umax_pp_get_sync (dpi)) { DBG (16, "control_option: correcting TL_Y coordinates\n"); dev->val[OPT_TL_Y].w = 2 * umax_pp_get_sync (dpi); if (info) *info |= SANE_INFO_INEXACT; } } return SANE_STATUS_GOOD; case OPT_MANUAL_OFFSET: w = *(SANE_Word *) val; if (w == dev->val[OPT_MANUAL_OFFSET].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; dev->val[OPT_MANUAL_OFFSET].w = w; if (w == SANE_TRUE) { const char *mode = dev->val[OPT_MODE].s; if ((strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) || (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)) dev->opt[OPT_GRAY_OFFSET].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dev->opt[OPT_GRAY_OFFSET].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_RED_OFFSET].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GREEN_OFFSET].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_BLUE_OFFSET].cap &= ~SANE_CAP_INACTIVE; } } else { dev->opt[OPT_GRAY_OFFSET].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_RED_OFFSET].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GREEN_OFFSET].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_BLUE_OFFSET].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; case OPT_MANUAL_GAIN: w = *(SANE_Word *) val; if (w == dev->val[OPT_MANUAL_GAIN].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; dev->val[OPT_MANUAL_GAIN].w = w; if (w == SANE_TRUE) { const char *mode = dev->val[OPT_MODE].s; if ((strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) || (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)) dev->opt[OPT_GRAY_GAIN].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dev->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_RED_GAIN].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GREEN_GAIN].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_BLUE_GAIN].cap &= ~SANE_CAP_INACTIVE; } } else { dev->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == dev->val[OPT_CUSTOM_GAMMA].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; dev->val[OPT_CUSTOM_GAMMA].w = w; if (w == SANE_TRUE) { const char *mode = dev->val[OPT_MODE].s; if ((strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) || (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0)) { dev->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; sanei_umax_pp_gamma (NULL, dev->val[OPT_GAMMA_VECTOR].wa, NULL); } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dev->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; sanei_umax_pp_gamma (dev->val[OPT_GAMMA_VECTOR_R].wa, dev->val[OPT_GAMMA_VECTOR_G].wa, dev->val[OPT_GAMMA_VECTOR_B].wa); } } else { dev->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; sanei_umax_pp_gamma (NULL, NULL, NULL); } return SANE_STATUS_GOOD; case OPT_MODE: { char *old_val = dev->val[option].s; if (old_val) { if (strcmp (old_val, val) == 0) return SANE_STATUS_GOOD; /* no change */ free (old_val); } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; dev->val[option].s = strdup (val); /* corrects top y for offset */ if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dpi = (int) (SANE_UNFIX (dev->val[OPT_RESOLUTION].w)); if (dev->val[OPT_TL_Y].w < 2 * umax_pp_get_sync (dpi)) { dev->val[OPT_TL_Y].w = 2 * umax_pp_get_sync (dpi); DBG (16, "control_option: correcting TL_Y coordinates\n"); if (info) *info |= SANE_INFO_INEXACT; } } dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; sanei_umax_pp_gamma (NULL, NULL, NULL); if (dev->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { if ((strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) || (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)) { dev->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; sanei_umax_pp_gamma (NULL, dev->val[OPT_GAMMA_VECTOR].wa, NULL); } else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dev->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; sanei_umax_pp_gamma (dev->val[OPT_GAMMA_VECTOR_R].wa, dev->val[OPT_GAMMA_VECTOR_G].wa, dev->val[OPT_GAMMA_VECTOR_B].wa); } } /* rebuild OPT OFFSET */ dev->opt[OPT_GRAY_OFFSET].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_RED_OFFSET].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GREEN_OFFSET].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_BLUE_OFFSET].cap |= SANE_CAP_INACTIVE; if (dev->val[OPT_MANUAL_OFFSET].w == SANE_TRUE) { if ((strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) || (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)) dev->opt[OPT_GRAY_OFFSET].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dev->opt[OPT_RED_OFFSET].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GREEN_OFFSET].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_BLUE_OFFSET].cap &= ~SANE_CAP_INACTIVE; } } /* rebuild OPT GAIN */ dev->opt[OPT_GRAY_GAIN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_RED_GAIN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GREEN_GAIN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_BLUE_GAIN].cap |= SANE_CAP_INACTIVE; if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE) { if ((strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) || (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0)) dev->opt[OPT_GRAY_GAIN].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dev->opt[OPT_RED_GAIN].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GREEN_GAIN].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_BLUE_GAIN].cap &= ~SANE_CAP_INACTIVE; } } return SANE_STATUS_GOOD; } } } DBG (2, "control_option: unknown action %d \n", action); return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Umax_PP_Device *dev = handle; int dpi, remain; memset (&(dev->params), 0, sizeof (dev->params)); DBG (64, "sane_get_parameters\n"); /* color/gray */ if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) != 0) { if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) != 0) dev->color = UMAX_PP_MODE_LINEART; else dev->color = UMAX_PP_MODE_GRAYSCALE; } else dev->color = UMAX_PP_MODE_COLOR; /* offset control */ if (dev->val[OPT_MANUAL_OFFSET].w == SANE_TRUE) { if (dev->color != UMAX_PP_MODE_COLOR) { dev->red_offset = 0; dev->green_offset = (int) (dev->val[OPT_GRAY_OFFSET].w); dev->blue_offset = 0; } else { dev->red_offset = (int) (dev->val[OPT_RED_OFFSET].w); dev->green_offset = (int) (dev->val[OPT_GREEN_OFFSET].w); dev->blue_offset = (int) (dev->val[OPT_BLUE_OFFSET].w); } } else { dev->red_offset = 6; dev->green_offset = 6; dev->blue_offset = 6; } /* gain control */ if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE) { if (dev->color != UMAX_PP_MODE_COLOR) { dev->red_gain = 0; dev->green_gain = (int) (dev->val[OPT_GRAY_GAIN].w); dev->blue_gain = 0; } else { dev->red_gain = (int) (dev->val[OPT_RED_GAIN].w); dev->green_gain = (int) (dev->val[OPT_GREEN_GAIN].w); dev->blue_gain = (int) (dev->val[OPT_BLUE_GAIN].w); } } else { dev->red_gain = red_gain; dev->green_gain = green_gain; dev->blue_gain = blue_gain; } /* geometry */ dev->TopX = dev->val[OPT_TL_X].w; dev->TopY = dev->val[OPT_TL_Y].w; dev->BottomX = dev->val[OPT_BR_X].w; dev->BottomY = dev->val[OPT_BR_Y].w; /* resolution : only have 75, 150, 300, 600 and 1200 */ dpi = (int) (SANE_UNFIX (dev->val[OPT_RESOLUTION].w)); if (dpi <= 75) dpi = 75; else if (dpi <= 150) dpi = 150; else if (dpi <= 300) dpi = 300; else if (dpi <= 600) dpi = 600; else dpi = 1200; dev->dpi = dpi; DBG (16, "sane_get_parameters: dpi set to %d\n", dpi); /* for highest resolutions , width must be aligned on 32 bit word */ if (dpi >= 600) { remain = (dev->BottomX - dev->TopX) & 0x03; if (remain) { DBG (64, "sane_get_parameters: %d-%d -> remain is %d\n", dev->BottomX, dev->TopX, remain); if (dev->BottomX + remain < dev->desc->max_h_size) dev->BottomX += remain; else { remain -= (dev->desc->max_h_size - dev->BottomX); dev->BottomX = dev->desc->max_h_size; dev->TopX -= remain; } } } if (dev->val[OPT_PREVIEW].w == SANE_TRUE) { if (dev->val[OPT_GRAY_PREVIEW].w == SANE_TRUE) { DBG (16, "sane_get_parameters: gray preview\n"); dev->color = UMAX_PP_MODE_GRAYSCALE; dev->params.format = SANE_FRAME_GRAY; } else { DBG (16, "sane_get_parameters: color preview\n"); dev->color = UMAX_PP_MODE_COLOR; dev->params.format = SANE_FRAME_RGB; } dev->dpi = 75; dev->TopX = 0; dev->TopY = 0; dev->BottomX = dev->desc->max_h_size; dev->BottomY = dev->desc->max_v_size; } /* fill params */ dev->params.last_frame = SANE_TRUE; dev->params.lines = ((dev->BottomY - dev->TopY) * dev->dpi) / dev->desc->ccd_res; if (dev->dpi >= dev->desc->ccd_res) dpi = dev->desc->ccd_res; else dpi = dev->dpi; dev->params.pixels_per_line = ((dev->BottomX - dev->TopX) * dpi) / dev->desc->ccd_res; if (dev->color == UMAX_PP_MODE_COLOR) { dev->params.bytes_per_line = dev->params.pixels_per_line * 3; dev->params.format = SANE_FRAME_RGB; } else { dev->params.bytes_per_line = dev->params.pixels_per_line; dev->params.format = SANE_FRAME_GRAY; } dev->params.depth = 8; /* success */ if (params != NULL) memcpy (params, &(dev->params), sizeof (dev->params)); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Umax_PP_Device *dev = handle; int rc, autoset; int delta = 0, points; /* sanity check */ if (dev->state == UMAX_PP_STATE_SCANNING) { DBG (2, "sane_start: device is already scanning\n"); DEBUG (); return SANE_STATUS_DEVICE_BUSY; } /* if cancelled, check if head is back home */ if (dev->state == UMAX_PP_STATE_CANCELLED) { DBG (2, "sane_start: checking if scanner is parking head .... \n"); rc = sanei_umax_pp_status (); points = 0; /* check if scanner busy parking */ /* if so, wait parking completion */ DBG (2, "sane_start: scanner busy\n"); while ((rc == UMAX1220P_BUSY) && (points < 30)) { sleep (1); rc = sanei_umax_pp_status (); points++; } /* timeout waiting for scanner */ if (rc == UMAX1220P_BUSY) { DBG (2, "sane_start: scanner still busy\n"); return SANE_STATUS_DEVICE_BUSY; } dev->state = UMAX_PP_STATE_IDLE; } /* get values from options */ sane_get_parameters (handle, NULL); /* sets lamp flag to TRUE */ dev->val[OPT_LAMP_CONTROL].w = SANE_TRUE; /* tests if we do auto setting */ if (dev->val[OPT_MANUAL_GAIN].w == SANE_TRUE) autoset = 0; else autoset = 1; /* call start scan */ if (dev->color == UMAX_PP_MODE_COLOR) { delta = umax_pp_get_sync (dev->dpi); points = 2 * delta; /* first lines are 'garbage' for 610P */ if (sanei_umax_pp_getastra () < 1210) points *= 2; DBG (64, "sane_start:umax_pp_start(%d,%d,%d,%d,%d,1,%X,%X)\n", dev->TopX, dev->TopY - points, dev->BottomX - dev->TopX, dev->BottomY - dev->TopY + points, dev->dpi, (dev->red_gain << 8) + (dev->green_gain << 4) + dev->blue_gain, (dev->red_offset << 8) + (dev->green_offset << 4) + dev->blue_offset); rc = sanei_umax_pp_start (dev->TopX, dev->TopY - points, dev->BottomX - dev->TopX, dev->BottomY - dev->TopY + points, dev->dpi, 2, autoset, (dev->red_gain << 8) | (dev->green_gain << 4) | dev->blue_gain, (dev->red_offset << 8) | (dev->green_offset << 4) | dev->blue_offset, &(dev->bpp), &(dev->tw), &(dev->th)); /* we enlarged the scanning zone */ /* to allow reordering, we must */ /* substract it from real scanning */ /* zone */ dev->th -= points; DBG (64, "sane_start: bpp=%d,tw=%d,th=%d\n", dev->bpp, dev->tw, dev->th); } else { DBG (64, "sane_start:umax_pp_start(%d,%d,%d,%d,%d,0,%X,%X)\n", dev->TopX, dev->TopY, dev->BottomX - dev->TopX, dev->BottomY - dev->TopY, dev->dpi, dev->gray_gain << 4, dev->gray_offset << 4); rc = sanei_umax_pp_start (dev->TopX, dev->TopY, dev->BottomX - dev->TopX, dev->BottomY - dev->TopY, dev->dpi, 1, autoset, dev->gray_gain << 4, dev->gray_offset << 4, &(dev->bpp), &(dev->tw), &(dev->th)); DBG (64, "sane_start: bpp=%d,tw=%d,th=%d\n", dev->bpp, dev->tw, dev->th); } if (rc != UMAX1220P_OK) { DBG (2, "sane_start: failure\n"); return SANE_STATUS_IO_ERROR; } /* scan started, no bytes read */ dev->state = UMAX_PP_STATE_SCANNING; dev->buflen = 0; dev->bufread = 0; dev->read = 0; /* leading lines for 610P aren't complete in color mode */ /* and should be discarded */ if ((sanei_umax_pp_getastra () < 1210) && (dev->color == UMAX_PP_MODE_COLOR)) { rc = sanei_umax_pp_read (2 * delta * dev->tw * dev->bpp, dev->tw, dev->dpi, 0, dev->buf + UMAX_PP_RESERVE - 2 * delta * dev->tw * dev->bpp); if (rc != UMAX1220P_OK) { DBG (2, "sane_start: first lines discarding failed\n"); return SANE_STATUS_IO_ERROR; } } /* in case of color, we have to preload blue and green */ /* data to allow reordering while later read */ if ((dev->color == UMAX_PP_MODE_COLOR) && (delta > 0)) { rc = sanei_umax_pp_read (2 * delta * dev->tw * dev->bpp, dev->tw, dev->dpi, 0, dev->buf + UMAX_PP_RESERVE - 2 * delta * dev->tw * dev->bpp); if (rc != UMAX1220P_OK) { DBG (2, "sane_start: preload buffer failed\n"); return SANE_STATUS_IO_ERROR; } } /* OK .... */ return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Umax_PP_Device *dev = handle; long int length; int last, rc; int x, y, nl, ll; SANE_Byte *lbuf; int max = 0; int min = 255; int delta = 0; /* no data until further notice */ *len = 0; DBG (64, "sane_read(max_len=%d)\n", max_len); ll = dev->tw * dev->bpp; /* sanity check */ if (dev->state == UMAX_PP_STATE_CANCELLED) { DBG (2, "sane_read: scan cancelled\n"); DEBUG (); return SANE_STATUS_CANCELLED; } /* eof test */ if (dev->read >= dev->th * ll) { DBG (2, "sane_read: end of scan reached\n"); return SANE_STATUS_EOF; } /* read data from scanner if needed */ if ((dev->buflen == 0) || (dev->bufread >= dev->buflen)) { DBG (64, "sane_read: reading data from scanner\n"); /* absolute number of bytes needed */ length = ll * dev->th - dev->read; /* does all fit in a single last read ? */ if (length <= dev->bufsize) { last = 1; } else { last = 0; /* round number of scan lines */ length = (dev->bufsize / ll) * ll; } if (dev->color == UMAX_PP_MODE_COLOR) { delta = umax_pp_get_sync (dev->dpi); rc = sanei_umax_pp_read (length, dev->tw, dev->dpi, last, dev->buf + UMAX_PP_RESERVE); } else rc = sanei_umax_pp_read (length, dev->tw, dev->dpi, last, dev->buf); if (rc != UMAX1220P_OK) return SANE_STATUS_IO_ERROR; dev->buflen = length; DBG (64, "sane_read: got %ld bytes of data from scanner\n", length); /* we transform data for software lineart */ if (dev->color == UMAX_PP_MODE_LINEART) { DBG (64, "sane_read: software lineart\n"); for (y = 0; y < length; y++) { if (dev->buf[y] > max) max = dev->buf[y]; if (dev->buf[y] < min) min = dev->buf[y]; } max = (min + max) / 2; for (y = 0; y < length; y++) { if (dev->buf[y] > max) dev->buf[y] = 255; else dev->buf[y] = 0; } } else if (dev->color == UMAX_PP_MODE_COLOR) { /* number of lines */ nl = dev->buflen / ll; DBG (64, "sane_read: reordering %ld bytes of data (lines=%d)\n", length, nl); lbuf = (SANE_Byte *) malloc (dev->bufsize + UMAX_PP_RESERVE); if (lbuf == NULL) { DBG (1, "sane_read: couldn't allocate %ld bytes\n", dev->bufsize + UMAX_PP_RESERVE); return SANE_STATUS_NO_MEM; } /* reorder data in R,G,B values */ for (y = 0; y < nl; y++) { for (x = 0; x < dev->tw; x++) { switch (sanei_umax_pp_getastra ()) { case 610: /* green value: sync'ed */ lbuf[x * dev->bpp + y * ll + 1 + UMAX_PP_RESERVE] = dev->buf[x + y * ll + 2 * dev->tw + UMAX_PP_RESERVE]; /* blue value, +delta line ahead of sync */ lbuf[x * dev->bpp + y * ll + 2 + UMAX_PP_RESERVE] = dev->buf[x + (y - delta) * ll + dev->tw + UMAX_PP_RESERVE]; /* red value, +2*delta line ahead of sync */ lbuf[x * dev->bpp + y * ll + UMAX_PP_RESERVE] = dev->buf[x + (y - 2 * delta) * ll + UMAX_PP_RESERVE]; break; default: /* red value: sync'ed */ lbuf[x * dev->bpp + y * ll + UMAX_PP_RESERVE] = dev->buf[x + y * ll + 2 * dev->tw + UMAX_PP_RESERVE]; /* green value, +delta line ahead of sync */ lbuf[x * dev->bpp + y * ll + 1 + UMAX_PP_RESERVE] = dev->buf[x + (y - delta) * ll + dev->tw + UMAX_PP_RESERVE]; /* blue value, +2*delta line ahead of sync */ lbuf[x * dev->bpp + y * ll + 2 + UMAX_PP_RESERVE] = dev->buf[x + (y - 2 * delta) * ll + UMAX_PP_RESERVE]; } } } /* store last data lines for next reordering */ if (!last) memcpy (lbuf + UMAX_PP_RESERVE - 2 * delta * ll, dev->buf + UMAX_PP_RESERVE + dev->buflen - 2 * delta * ll, 2 * delta * ll); free (dev->buf); dev->buf = lbuf; } dev->bufread = 0; } /* how much get data we can get from memory buffer */ length = dev->buflen - dev->bufread; DBG (64, "sane_read: %ld bytes of data available\n", length); if (length > max_len) length = max_len; if (dev->color == UMAX_PP_MODE_COLOR) memcpy (buf, dev->buf + dev->bufread + UMAX_PP_RESERVE, length); else memcpy (buf, dev->buf + dev->bufread, length); *len = length; dev->bufread += length; dev->read += length; DBG (64, "sane_read: %ld bytes read\n", length); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Umax_PP_Device *dev = handle; int rc; DBG (64, "sane_cancel\n"); if (dev->state == UMAX_PP_STATE_IDLE) { DBG (3, "cancel: cancelling idle \n"); return; } if (dev->state == UMAX_PP_STATE_SCANNING) { DBG (3, "cancel: stopping current scan\n"); dev->buflen = 0; dev->state = UMAX_PP_STATE_CANCELLED; sanei_umax_pp_cancel (); } else { /* STATE_CANCELLED */ DBG (2, "cancel: checking if scanner is still parking head .... \n"); rc = sanei_umax_pp_status (); /* check if scanner busy parking */ if (rc == UMAX1220P_BUSY) { DBG (2, "cancel: scanner busy\n"); return; } dev->state = UMAX_PP_STATE_IDLE; } } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (129, "unused arg: handle = %p, non_blocking = %d\n", handle, (int) non_blocking); DBG (2, "set_io_mode: not supported\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (129, "unused arg: handle = %p, fd = %p\n", handle, (void *) fd); DBG (2, "get_select_fd: not supported\n"); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/mustek.c0000664000175000017500000061235313106201017014266 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1996, 1997 David Mosberger-Tang and Andreas Czechanowski, 1998 Andreas Bolsch for extension to ScanExpress models version 0.6, 2000-2005 Henning Meier-Geinitz, 2003 James Perry (600 EP). This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek and some Trust flatbed scanners with SCSI, parallel port (600 EP) or proprietary interface. */ /**************************************************************************/ /* Mustek backend version */ #define BUILD 138 /**************************************************************************/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_ab306.h" #include "../include/sane/sanei_thread.h" #define BACKEND_NAME mustek #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "mustek.h" #include "mustek_scsi_pp.h" #ifndef SANE_I18N #define SANE_I18N(text) text #endif /* Debug level from sanei_init_debug */ static SANE_Int debug_level; /* Maximum # of inches to scan in one swoop. 0 means "unlimited." This is here to be nice on the SCSI bus---Mustek scanners don't disconnect while scanning is in progress, which confuses some drivers that expect no reasonable SCSI request would take more than 10 seconds. That's not really true for Mustek scanners operating in certain modes, hence this limit. Usually you don't need to set it. */ static double strip_height; /* Should we wait for the scan slider to return after each scan? */ static SANE_Bool force_wait; /* Should we disable double buffering when reading data from the scanner? */ static SANE_Bool disable_double_buffering; static SANE_Int num_devices; static Mustek_Device *first_dev; static Mustek_Scanner *first_handle; static const SANE_Device **devlist = 0; /* Array of newly attached devices */ static Mustek_Device **new_dev; /* Length of new_dev array */ static SANE_Int new_dev_len; /* Number of entries alloced for new_dev */ static SANE_Int new_dev_alloced; static SANE_Int lamp_off_time = 60; /* Used for line-distance correction: */ static const SANE_Int color_seq[] = { 1, 2, 0 /* green, blue, red */ }; /* Which modes are supported? */ static SANE_String_Const mode_list_paragon[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static SANE_String_Const mode_list_se[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, 0 }; static SANE_String_Const bit_depth_list_pro[] = { "8", "12", 0 }; /* Some scanners support setting speed manually */ static SANE_String_Const speed_list[] = { SANE_I18N ("Slowest"), SANE_I18N ("Slower"), SANE_I18N ("Normal"), SANE_I18N ("Faster"), SANE_I18N ("Fastest"), 0 }; /* Which scan-sources are supported? */ static const SANE_String_Const source_list[] = { SANE_I18N ("Flatbed"), 0 }; static SANE_String_Const adf_source_list[] = { SANE_I18N ("Flatbed"), SANE_I18N ("Automatic Document Feeder"), 0 }; static SANE_String_Const ta_source_list[] = { SANE_I18N ("Flatbed"), SANE_I18N ("Transparency Adapter"), 0 }; /* Range used for gamma and halftone pattern */ static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /* Which kind of halftone patterns are available? */ static SANE_String_Const halftone_list[] = { SANE_I18N ("8x8 coarse"), SANE_I18N ("8x8 normal"), SANE_I18N ("8x8 fine"), SANE_I18N ("8x8 very fine"), SANE_I18N ("6x6 normal"), SANE_I18N ("5x5 coarse"), SANE_I18N ("5x5 fine"), SANE_I18N ("4x4 coarse"), SANE_I18N ("4x4 normal"), SANE_I18N ("4x4 fine"), SANE_I18N ("3x3 normal"), SANE_I18N ("2x2 normal"), SANE_I18N ("8x8 custom"), SANE_I18N ("6x6 custom"), SANE_I18N ("5x5 custom"), SANE_I18N ("4x4 custom"), SANE_I18N ("3x3 custom"), SANE_I18N ("2x2 custom"), 0 }; /* Range used for brightness and contrast */ static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 1 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; /* SCSI command buffers used by the backend */ static const SANE_Byte scsi_inquiry[] = { MUSTEK_SCSI_INQUIRY, 0x00, 0x00, 0x00, INQ_LEN, 0x00 }; static const SANE_Byte scsi_test_unit_ready[] = { MUSTEK_SCSI_TEST_UNIT_READY, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const SANE_Byte scsi_area_and_windows[] = { MUSTEK_SCSI_AREA_AND_WINDOWS, 0x00, 0x00, 0x00, 0x09, 0x00 }; static const SANE_Byte scsi_request_sense[] = { MUSTEK_SCSI_REQUEST_SENSE, 0x00, 0x00, 0x00, 0x04, 0x00 }; static const SANE_Byte scsi_start_stop[] = { MUSTEK_SCSI_START_STOP, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const SANE_Byte scsi_ccd_distance[] = { MUSTEK_SCSI_CCD_DISTANCE, 0x00, 0x00, 0x00, 0x05, 0x00 }; static const SANE_Byte scsi_get_image_status[] = { MUSTEK_SCSI_GET_IMAGE_STATUS, 0x00, 0x00, 0x00, 0x06, 0x00 }; static const SANE_Byte scsi_set_window[] = { MUSTEK_SCSI_SET_WINDOW, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00 }; static const SANE_Byte scsi_get_window[] = { MUSTEK_SCSI_GET_WINDOW, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00 }; static const SANE_Byte scsi_read_data[] = { MUSTEK_SCSI_READ_DATA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const SANE_Byte scsi_send_data[] = { MUSTEK_SCSI_SEND_DATA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const SANE_Byte scsi_lookup_table[] = { MUSTEK_SCSI_LOOKUP_TABLE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* prototypes */ static SANE_Status area_and_windows (Mustek_Scanner * s); static SANE_Status inquiry (Mustek_Scanner * s); /* Test if this machine is little endian (from coolscan.c) */ static SANE_Bool little_endian (void) { SANE_Int testvalue = 255; uint8_t *firstbyte = (uint8_t *) & testvalue; if (*firstbyte == 255) return SANE_TRUE; return SANE_FALSE; } /* Used for Pro series. First value seems to be always 85, second one varies. First bit of second value clear == device ready (?) */ static SANE_Status scsi_sense_wait_ready (Mustek_Scanner * s) { struct timeval now, start; SANE_Status status; size_t len; SANE_Byte sense_buffer[4]; SANE_Byte bytetxt[300], dbgtxt[300], *pp; gettimeofday (&start, 0); while (1) { len = sizeof (sense_buffer); DBG (5, "scsi_sense_wait_ready: command size = %ld, sense size = %ld\n", (long int) sizeof (scsi_request_sense), (long int) len); status = sanei_scsi_cmd (s->fd, scsi_request_sense, sizeof (scsi_request_sense), sense_buffer, &len); if (status != SANE_STATUS_GOOD) { DBG (1, "scsi_sense_wait_ready: failed: %s\n", sane_strstatus (status)); return status; } dbgtxt[0] = '\0'; for (pp = sense_buffer; pp < (sense_buffer + 4); pp++) { sprintf ((SANE_String) bytetxt, " %02x", *pp); strcat ((SANE_String) dbgtxt, (SANE_String) bytetxt); } DBG (5, "scsi_sense_wait_ready: sensebuffer: %s\n", dbgtxt); if (!(sense_buffer[1] & 0x01)) { DBG (4, "scsi_sense_wait_ready: ok\n"); return SANE_STATUS_GOOD; } else { gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG (1, "scsi_sense_wait_ready: timed out after %lu seconds\n", (u_long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ } } return SANE_STATUS_INVAL; } /* Used for 3pass series */ static SANE_Status scsi_area_wait_ready (Mustek_Scanner * s) { struct timeval now, start; SANE_Status status; gettimeofday (&start, 0); DBG (5, "scsi_area_wait_ready\n"); while (1) { status = area_and_windows (s); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG (3, "scsi_area_wait_ready: failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG (1, "scsi_area_wait_ready: timed out after %lu seconds\n", (u_long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; } } return SANE_STATUS_INVAL; } static SANE_Status scsi_unit_wait_ready (Mustek_Scanner * s) { struct timeval now, start; SANE_Status status; gettimeofday (&start, 0); while (1) { DBG (5, "scsi_unit_wait_ready: sending TEST_UNIT_READY\n"); status = sanei_scsi_cmd (s->fd, scsi_test_unit_ready, sizeof (scsi_test_unit_ready), 0, 0); DBG (5, "scsi_unit_wait_ready: TEST_UNIT_READY finished\n"); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG (3, "scsi_unit_wait_ready: test unit ready failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG (1, "scsi_unit_wait_ready: timed out after %lu seconds\n", (u_long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ break; case SANE_STATUS_GOOD: return status; } } return SANE_STATUS_INVAL; } static SANE_Status scsi_inquiry_wait_ready (Mustek_Scanner * s) { struct timeval now, start; SANE_Status status; gettimeofday (&start, 0); while (1) { DBG (5, "scsi_inquiry_wait_ready: sending INQUIRY\n"); status = inquiry (s); DBG (5, "scsi_inquiry_wait_ready: INQUIRY finished\n"); switch (status) { default: /* Ignore errors while waiting for scanner to become ready. Some SCSI drivers return EIO while the scanner is returning to the home position. */ DBG (3, "scsi_unit_wait_ready: inquiry failed (%s)\n", sane_strstatus (status)); /* fall through */ case SANE_STATUS_DEVICE_BUSY: gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG (1, "scsi_unit_wait_ready: timed out after %lu seconds\n", (u_long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (500000); /* retry after 500ms */ break; case SANE_STATUS_GOOD: return status; } } return SANE_STATUS_INVAL; } static SANE_Status n_wait_ready (Mustek_Scanner * s) { struct timeval now, start; SANE_Status status; gettimeofday (&start, 0); DBG (5, "n_wait_ready\n"); while (1) { status = sanei_ab306_test_ready (s->fd); if (status == SANE_STATUS_GOOD) return SANE_STATUS_GOOD; gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG (1, "n_wait_ready: timed out after %lu seconds\n", (u_long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ } } static SANE_Status scsi_pp_wait_ready (Mustek_Scanner * s) { struct timeval now, start; SANE_Status status; gettimeofday (&start, 0); DBG (5, "scsi_pp_wait_ready\n"); while (1) { status = mustek_scsi_pp_test_ready (s->fd); if (status == SANE_STATUS_GOOD) return SANE_STATUS_GOOD; gettimeofday (&now, 0); if (now.tv_sec - start.tv_sec >= MAX_WAITING_TIME) { DBG (1, "scsi_pp_wait_ready: timed out after %lu seconds\n", (u_long) (now.tv_sec - start.tv_sec)); return SANE_STATUS_INVAL; } usleep (100000); /* retry after 100ms */ } } static SANE_Status dev_wait_ready (Mustek_Scanner * s) { if (s->hw->flags & MUSTEK_FLAG_N) return n_wait_ready (s); else if (s->hw->flags & MUSTEK_FLAG_SCSI_PP) return scsi_pp_wait_ready (s); else if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { SANE_Status status; /* some 3-pass scanners seem to need the inquiry wait, too */ status = scsi_area_wait_ready (s); if (status != SANE_STATUS_GOOD) return status; return scsi_inquiry_wait_ready (s); } else if ((s->hw->flags & MUSTEK_FLAG_PARAGON_1) || (s->hw->flags & MUSTEK_FLAG_PARAGON_2)) return scsi_inquiry_wait_ready (s); else if (s->hw->flags & MUSTEK_FLAG_PRO) return scsi_sense_wait_ready (s); else return scsi_unit_wait_ready (s); } static SANE_Status dev_open (SANE_String_Const devname, Mustek_Scanner * s, SANEI_SCSI_Sense_Handler handler) { SANE_Status status; DBG (5, "dev_open %s\n", devname); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED s->hw->buffer_size = s->hw->max_buffer_size; status = sanei_scsi_open_extended (devname, &s->fd, handler, 0, &s->hw->buffer_size); #else s->hw->buffer_size = MIN (sanei_scsi_max_request_size, s->hw->max_buffer_size); status = sanei_scsi_open (devname, &s->fd, handler, 0); #endif if (status == SANE_STATUS_GOOD) { DBG (3, "dev_open: %s is a SCSI device\n", devname); DBG (4, "dev_open: wanted %d kbytes, got %d kbytes buffer\n", s->hw->max_buffer_size / 1024, s->hw->buffer_size / 1024); if (s->hw->buffer_size < 4096) { DBG (1, "dev_open: sanei_scsi_open buffer too small\n"); sanei_scsi_close (s->fd); return SANE_STATUS_NO_MEM; } } else { DBG (3, "dev_open: %s: can't open %s as a SCSI device\n", sane_strstatus (status), devname); status = sanei_ab306_open (devname, &s->fd); if (status == SANE_STATUS_GOOD) { s->hw->flags |= MUSTEK_FLAG_N; DBG (3, "dev_open: %s is an AB306N device\n", devname); } else { DBG (3, "dev_open: %s: can't open %s as an AB306N device\n", sane_strstatus (status), devname); status = mustek_scsi_pp_open (devname, &s->fd); if (status == SANE_STATUS_GOOD) { s->hw->flags |= MUSTEK_FLAG_SCSI_PP; DBG (3, "dev_open: %s is a SCSI-over-parallel device\n", devname); } else { DBG (3, "dev_open: %s: can't open %s as a SCSI-over-parallel device\n", sane_strstatus (status), devname); DBG (1, "dev_open: can't open %s\n", devname); return SANE_STATUS_INVAL; } } } return SANE_STATUS_GOOD; } static SANE_Status dev_cmd (Mustek_Scanner * s, const void *src, size_t src_size, void *dst, size_t * dst_size) { SANE_Status status; SANE_Byte cmd_byte_list[50]; SANE_Byte cmd_byte[5]; const SANE_Byte *pp; DBG (5, "dev_cmd: fd=%d, src=%p, src_size=%ld, dst=%p, dst_size=%ld\n", s->fd, src, (long int) src_size, dst, (long int) (dst_size ? *dst_size : 0)); if (src && (debug_level >= 5)) /* output data sent to SCSI device */ { cmd_byte_list[0] = '\0'; for (pp = (const SANE_Byte *) src; pp < (((const SANE_Byte *) src) + src_size); pp++) { sprintf ((SANE_String) cmd_byte, " %02x", *pp); strcat ((SANE_String) cmd_byte_list, (SANE_String) cmd_byte); if (((pp - (const SANE_Byte *) src) % 0x10 == 0x0f) || (pp >= (((const SANE_Byte *) src) + src_size - 1))) { DBG (5, "dev_cmd: sending: %s\n", cmd_byte_list); cmd_byte_list[0] = '\0'; } } } if (s->hw->flags & MUSTEK_FLAG_N) status = sanei_ab306_cmd (s->fd, src, src_size, dst, dst_size); else if (s->hw->flags & MUSTEK_FLAG_SCSI_PP) status = mustek_scsi_pp_cmd (s->fd, src, src_size, dst, dst_size); else status = sanei_scsi_cmd (s->fd, src, src_size, dst, dst_size); if (dst && dst_size && (debug_level >= 5)) /* output data received from SCSI device */ { cmd_byte_list[0] = '\0'; for (pp = (const SANE_Byte *) dst; pp < (((const SANE_Byte *) dst) + *dst_size); pp++) { sprintf ((SANE_String) cmd_byte, " %02x", *pp); strcat ((SANE_String) cmd_byte_list, (SANE_String) cmd_byte); if (((pp - (const SANE_Byte *) dst) % 0x10 == 0x0f) || (pp >= (((const SANE_Byte *) dst) + *dst_size - 1))) { DBG (5, "dev_cmd: receiving: %s\n", cmd_byte_list); cmd_byte_list[0] = '\0'; } } } DBG (5, "dev_cmd: finished: dst_size=%ld, status=%s\n", (long int) (dst_size ? *dst_size : 0), sane_strstatus (status)); return status; } static SANE_Status dev_req_wait (void *id) { if (!id) return SANE_STATUS_GOOD; else return sanei_scsi_req_wait (id); } static SANE_Status dev_block_read_start (Mustek_Scanner * s, SANE_Int lines) { DBG (4, "dev_block_read_start: entering block for %d lines\n", lines); if (s->hw->flags & MUSTEK_FLAG_N) { SANE_Byte readlines[6]; memset (readlines, 0, sizeof (readlines)); readlines[0] = MUSTEK_SCSI_READ_SCANNED_DATA; readlines[2] = (lines >> 16) & 0xff; readlines[3] = (lines >> 8) & 0xff; readlines[4] = (lines >> 0) & 0xff; return sanei_ab306_cmd (s->fd, readlines, sizeof (readlines), 0, 0); } else if (s->hw->flags & MUSTEK_FLAG_SCSI_PP) { SANE_Byte readlines[6]; memset (readlines, 0, sizeof (readlines)); readlines[0] = MUSTEK_SCSI_READ_SCANNED_DATA; readlines[2] = (lines >> 16) & 0xff; readlines[3] = (lines >> 8) & 0xff; readlines[4] = (lines >> 0) & 0xff; return mustek_scsi_pp_cmd (s->fd, readlines, sizeof (readlines), 0, 0); } else if (s->hw->flags & MUSTEK_FLAG_PARAGON_2) { SANE_Byte buffer[6]; size_t len; SANE_Int color; SANE_Status status; /* reset line-distance values */ if (s->mode & MUSTEK_MODE_COLOR) { for (color = 0; color < 3; ++color) { s->ld.index[color] = -s->ld.dist[color]; } s->ld.lmod3 = -1; s->ld.ld_line = 0; } /* Get image status (necessary to start new block) */ len = sizeof (buffer); status = dev_cmd (s, scsi_get_image_status, sizeof (scsi_get_image_status), buffer, &len); if (status != SANE_STATUS_GOOD) return status; /* tell scanner how many lines to scan in one block */ memset (buffer, 0, sizeof (buffer)); buffer[0] = MUSTEK_SCSI_READ_SCANNED_DATA; buffer[2] = (lines >> 16) & 0xff; buffer[3] = (lines >> 8) & 0xff; buffer[4] = (lines >> 0) & 0xff; buffer[5] = 0x04; return sanei_scsi_cmd (s->fd, buffer, sizeof (buffer), 0, 0); } else return SANE_STATUS_GOOD; } static SANE_Status dev_read_req_enter (Mustek_Scanner * s, SANE_Byte * buf, SANE_Int lines, SANE_Int bpl, size_t * lenp, void **idp, SANE_Int bank, SANE_Byte * command) { *lenp = lines * bpl; if (s->hw->flags & MUSTEK_FLAG_N) { SANE_Int planes; *idp = 0; planes = (s->mode & MUSTEK_MODE_COLOR) ? 3 : 1; return sanei_ab306_rdata (s->fd, planes, buf, lines, bpl); } else if (s->hw->flags & MUSTEK_FLAG_SCSI_PP) { SANE_Int planes; *idp = 0; planes = (s->mode & MUSTEK_MODE_COLOR) ? 3 : 1; return mustek_scsi_pp_rdata (s->fd, planes, buf, lines, bpl); } else { if (s->hw->flags & MUSTEK_FLAG_SE) { if (s->mode & MUSTEK_MODE_COLOR) lines *= 3; memset (command, 0, 10); command[0] = MUSTEK_SCSI_READ_DATA; command[6] = bank; /* buffer bank not used ??? */ command[7] = (lines >> 8) & 0xff; command[8] = (lines >> 0) & 0xff; return sanei_scsi_req_enter (s->fd, command, 10, buf, lenp, idp); } else if (s->hw->flags & MUSTEK_FLAG_PRO) { memset (command, 0, 6); command[0] = MUSTEK_SCSI_READ_SCANNED_DATA; command[2] = ((lines * bpl) >> 16) & 0xff; command[3] = ((lines * bpl) >> 8) & 0xff; command[4] = ((lines * bpl) >> 0) & 0xff; return sanei_scsi_req_enter (s->fd, command, 6, buf, lenp, idp); } else /* Paragon series */ { memset (command, 0, 6); command[0] = MUSTEK_SCSI_READ_SCANNED_DATA; command[2] = (lines >> 16) & 0xff; command[3] = (lines >> 8) & 0xff; command[4] = (lines >> 0) & 0xff; return sanei_scsi_req_enter (s->fd, command, 6, buf, lenp, idp); } } } static void dev_close (Mustek_Scanner * s) { if (s->hw->flags & MUSTEK_FLAG_N) sanei_ab306_close (s->fd); else if (s->hw->flags & MUSTEK_FLAG_SCSI_PP) mustek_scsi_pp_close (s->fd); else sanei_scsi_close (s->fd); } static SANE_Status sense_handler (SANE_Int scsi_fd, SANE_Byte * result, void *arg) { if (!result) { DBG (5, "sense_handler: no sense buffer\n"); return SANE_STATUS_IO_ERROR; } if (!arg) DBG (5, "sense_handler: got sense code %02x for fd %d (arg = null)\n", result[0], scsi_fd); else DBG (5, "sense_handler: got sense code %02x for fd %d (arg = %uc)\n", result[0], scsi_fd, *(SANE_Byte *) arg); switch (result[0]) { case 0x00: break; case 0x82: if (result[1] & 0x80) { DBG (3, "sense_handler: ADF is jammed\n"); return SANE_STATUS_JAMMED; /* ADF is jammed */ } break; case 0x83: if (result[2] & 0x02) { DBG (3, "sense_handler: ADF is out of documents\n"); return SANE_STATUS_NO_DOCS; /* ADF out of documents */ } break; case 0x84: if (result[1] & 0x10) { DBG (3, "sense_handler: transparency adapter cover open\n"); return SANE_STATUS_COVER_OPEN; /* open transparency adapter cover */ } break; default: DBG (1, "sense_handler: got unknown sense code %02x for fd %d\n", result[0], scsi_fd); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } static SANE_Status inquiry (Mustek_Scanner * s) { SANE_Byte result[INQ_LEN]; size_t size; SANE_Status status; DBG (5, "inquiry: sending INQUIRY\n"); size = sizeof (result); memset (result, 0, size); status = dev_cmd (s, scsi_inquiry, sizeof (scsi_inquiry), result, &size); if (status != SANE_STATUS_GOOD) return status; /* checking ADF status */ if (s->hw->flags & MUSTEK_FLAG_ADF) { if (result[63] & (1 << 3)) { s->hw->flags |= MUSTEK_FLAG_ADF_READY; DBG (4, "inquiry: ADF ready\n"); } else { s->hw->flags &= ~MUSTEK_FLAG_ADF_READY; DBG (4, "inquiry: ADF not ready (out of paper)\n"); } } if (!result[0]) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_GOOD; } static SANE_Status paragon_2_get_adf_status (Mustek_Scanner * s) { SANE_Status status; size_t len; SANE_Byte sense_buffer[4]; len = sizeof (sense_buffer); status = sanei_scsi_cmd (s->fd, scsi_request_sense, sizeof (scsi_request_sense), sense_buffer, &len); if (status != SANE_STATUS_GOOD) { DBG (1, "paragon_2_get_adf_status: %s\n", sane_strstatus (status)); return status; } DBG (5, "paragon_2_get_adf_status: sense_buffer: %x %x %x %x\n", sense_buffer[0], sense_buffer[1], sense_buffer[3], sense_buffer[3]); if (sense_buffer[0] == 0x00 && sense_buffer[1] == 0x00) return SANE_STATUS_GOOD; return SANE_STATUS_NO_DOCS; } static SANE_Bool ta_available_pro (Mustek_Scanner * s) { SANE_Status status; size_t len; SANE_Byte sense_buffer[4]; len = sizeof (sense_buffer); status = sanei_scsi_cmd (s->fd, scsi_request_sense, sizeof (scsi_request_sense), sense_buffer, &len); if (status != SANE_STATUS_GOOD) { DBG (1, "ta_available_pro: failed: %s\n", sane_strstatus (status)); return status; } DBG (5, "ta_available_pro: sense_buffer[2] = %x\n", sense_buffer[2]); scsi_unit_wait_ready (s); if (sense_buffer[2] == 0x40) return SANE_TRUE; return SANE_FALSE; } static SANE_Status attach (SANE_String_Const devname, Mustek_Device ** devp, SANE_Bool may_wait) { SANE_Int mustek_scanner, fw_revision; SANE_Byte result[INQ_LEN]; SANE_Byte inquiry_byte_list[50], inquiry_text_list[17]; SANE_Byte inquiry_byte[5], inquiry_text[5]; SANE_Byte *model_name = result + 44; Mustek_Scanner s; Mustek_Device *dev, new_dev; SANE_Status status; size_t size; SANE_String scsi_device_type[] = { "Direct-Access", "Sequential-Access", "Printer", "Processor", "Write-Once", "CD-ROM", "Scanner", "Optical Memory", "Medium Changer", "Communications" }; SANE_Byte scsi_vendor[9]; SANE_Byte scsi_product[17]; SANE_Byte scsi_revision[5]; SANE_Byte *pp; SANE_Bool warning = SANE_FALSE; SANE_Int firmware_format = 0; SANE_Int firmware_revision_system = 0; if (devp) *devp = 0; for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } memset (&new_dev, 0, sizeof (new_dev)); memset (&s, 0, sizeof (s)); s.hw = &new_dev; s.hw->max_buffer_size = 8 * 1024; DBG (3, "attach: trying device %s\n", devname); status = dev_open (devname, &s, sense_handler); if (status != SANE_STATUS_GOOD) return status; if (may_wait || force_wait) dev_wait_ready (&s); DBG (5, "attach: sending INQUIRY\n"); size = sizeof (result); memset (result, 0, sizeof (result)); status = dev_cmd (&s, scsi_inquiry, sizeof (scsi_inquiry), result, &size); if (status != SANE_STATUS_GOOD || size != INQ_LEN) { DBG (1, "attach: inquiry for device %s failed (%s)\n", devname, sane_strstatus (status)); dev_close (&s); return status; } status = dev_wait_ready (&s); dev_close (&s); if (status != SANE_STATUS_GOOD) return status; if ((result[0] & 0x1f) != 0x06) { DBG (1, "attach: device %s doesn't look like a scanner at all (%d)\n", devname, result[0] & 0x1f); return SANE_STATUS_INVAL; } if (debug_level >= 3) { /* clear spaces and special chars */ strncpy ((SANE_String) scsi_vendor, (SANE_String) result + 8, 8); scsi_vendor[8] = '\0'; pp = scsi_vendor + 7; while (pp >= scsi_vendor && (*pp == ' ' || *pp >= 127)) *pp-- = '\0'; strncpy ((SANE_String) scsi_product, (SANE_String) result + 16, 16); scsi_product[16] = '\0'; pp = scsi_product + 15; while (pp >= scsi_product && (*pp == ' ' || *pp >= 127)) *pp-- = '\0'; strncpy ((SANE_String) scsi_revision, (SANE_String) result + 32, 4); scsi_revision[4] = '\0'; pp = scsi_revision + 3; while (pp >= scsi_revision && (*pp == ' ' || *pp >= 127)) *pp-- = '\0'; DBG (3, "attach: SCSI Vendor: `%-8s' Model: `%-16s' Rev.: `%-4s'\n", scsi_vendor, scsi_product, scsi_revision); DBG (3, "attach: SCSI Type: %s; ANSI rev.: %d\n", ((result[0] & 0x1f) < 0x10) ? scsi_device_type[result[0] & 0x1f] : "Unknown", result[2] & 0x03); DBG (3, "attach: SCSI flags: %s%s%s%s%s%s%s\n", (result[7] & 0x80) ? "RelAdr " : "", (result[7] & 0x40) ? "WBus32 " : "", (result[7] & 0x20) ? "WBus16 " : "", (result[7] & 0x10) ? "Sync " : "", (result[7] & 0x08) ? "Linked " : "", (result[7] & 0x02) ? "CmdQue " : "", (result[7] & 0x01) ? "SftRe " : ""); } if (debug_level >= 4) { /* print out inquiry */ DBG (4, "attach: inquiry output:\n"); inquiry_byte_list[0] = '\0'; inquiry_text_list[0] = '\0'; for (pp = result; pp < (result + INQ_LEN); pp++) { sprintf ((SANE_String) inquiry_text, "%c", (*pp < 127) && (*pp > 31) ? *pp : '.'); strcat ((SANE_String) inquiry_text_list, (SANE_String) inquiry_text); sprintf ((SANE_String) inquiry_byte, " %02x", *pp); strcat ((SANE_String) inquiry_byte_list, (SANE_String) inquiry_byte); if ((pp - result) % 0x10 == 0x0f) { DBG (4, "%s %s\n", inquiry_byte_list, inquiry_text_list); inquiry_byte_list[0] = '\0'; inquiry_text_list[0] = '\0'; } } } /* first check for new firmware format: */ mustek_scanner = (strncmp ((SANE_String) result + 36, "MUSTEK", 6) == 0); if (mustek_scanner) { if (result[43] == 'M') { DBG (3, "attach: found Mustek scanner (pro series firmware " "format)\n"); firmware_format = 2; model_name = result + 43; } else { DBG (3, "attach: found Mustek scanner (new firmware format)\n"); firmware_format = 1; } } else { /* check for old format: */ mustek_scanner = (strncmp ((SANE_String) result + 8, "MUSTEK", 6) == 0); if (mustek_scanner) { model_name = result + 16; DBG (3, "attach: found Mustek scanner (old firmware format)\n"); firmware_format = 0; } else { /* Check for some non-Mustek scanners an print warning */ if (strncmp ((SANE_String) result + 8, "Trust", 5) == 0) DBG (1, "attach: this is a real Trust scanner. It is not " " supported by this backend.\n"); if (strncmp ((SANE_String) result + 8, "Aashima", 7) == 0) DBG (1, "attach: this is an Aashima/Teco scanner. It is not " " supported by this backend.\n"); if (strncmp ((SANE_String) result + 16, "Flatbed Scanner", 15) == 0 && strncmp ((SANE_String) result + 42, "TECO", 4) == 0) DBG (1, "attach: this is a Relysis/Teco scanner. It is not " " supported by this backend.\n"); DBG (1, "attach: device %s doesn't look like a Mustek scanner\n", devname); return SANE_STATUS_INVAL; } } /* get firmware revision as BCD number: */ /* General format: x.yz */ /* Newer ScanExpress scanners (ID XC06): Vxyz */ if (result[33] == '.') { fw_revision = (result[32] - '0') << 8 | (result[34] - '0') << 4 | (result[35] - '0'); firmware_revision_system = 0; DBG (4, "attach: old firmware revision system\n"); } else { fw_revision = (result[33] - '0') << 8 | (result[34] - '0') << 4 | (result[35] - '0'); firmware_revision_system = 1; DBG (4, "attach: new firmware revision system\n"); } DBG (3, "attach: firmware revision %d.%02x\n", fw_revision >> 8, fw_revision & 0xff); dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memcpy (dev, &new_dev, sizeof (*dev)); dev->name = strdup (devname); if (!dev->name) return SANE_STATUS_NO_MEM; dev->sane.name = (SANE_String_Const) dev->name; dev->sane.vendor = "Mustek"; dev->sane.type = "flatbed scanner"; dev->x_range.min = 0; dev->y_range.min = 0; dev->x_range.quant = 0; dev->y_range.quant = 0; dev->x_trans_range.min = 0; dev->y_trans_range.min = 0; /* default to something really small to be on the safe side: */ dev->x_trans_range.max = SANE_FIX (8.0 * MM_PER_INCH); dev->y_trans_range.max = SANE_FIX (5.0 * MM_PER_INCH); dev->x_trans_range.quant = 0; dev->y_trans_range.quant = 0; dev->dpi_range.min = SANE_FIX (72); /* some scanners don't like low dpi */ dev->dpi_range.quant = SANE_FIX (1); /* default to 128 kB */ dev->max_buffer_size = 128 * 1024; /* SCSI buffer -> use 64 k per buffer */ dev->max_block_buffer_size = 1024 * 1024 * 1024; dev->firmware_format = firmware_format; dev->firmware_revision_system = firmware_revision_system; DBG (3, "attach: scanner id: %.11s\n", model_name); if (strncmp ((SANE_String) model_name + 10, "PRO", 3) == 0) DBG (3, "attach: this is probably a Paragon Pro series scanner\n"); else if (strncmp ((SANE_String) model_name, "MFC", 3) == 0) DBG (3, "attach: this is probably a Paragon series II scanner\n"); else if (strncmp ((SANE_String) model_name, "M", 1) == 0) DBG (3, "attach: this is probably a Paragon series I or 3-pass scanner\n"); else if (strncmp ((SANE_String) model_name, " C", 2) == 0) DBG (3, "attach: this is probably a ScanExpress series A4 scanner\n"); else if (strncmp ((SANE_String) model_name, " L", 2) == 0) DBG (3, "attach: this is probably a ScanExpress series A3 scanner\n"); else if (strncmp ((SANE_String) model_name, "XC", 2) == 0) DBG (3, "attach: this is probably a ScanExpress Plus series A4 scanner\n"); else DBG (3, "attach: I am not sure what type of scanner this is\n"); /* Paragon 3-pass series */ if (strncmp ((SANE_String) model_name, "MFS-12000CX", 11) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a Paragon MFS-12000CX v4.00 */ dev->x_range.min = SANE_FIX (0.0); dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.min = SANE_FIX (0.0); dev->y_range.max = SANE_FIX (14.00 * MM_PER_INCH); dev->x_trans_range.min = SANE_FIX (1.0); dev->y_trans_range.min = SANE_FIX (1.0); dev->x_trans_range.max = SANE_FIX (205.0); dev->y_trans_range.max = SANE_FIX (255.0); dev->dpi_range.max = SANE_FIX (1200); dev->sane.model = "MFS-12000CX"; } /* There are two different versions of the MFS-6000CX, one has the model name "MFS-06000CX", the other one is "MSF-06000CZ" */ else if (strncmp ((SANE_String) model_name, "MFS-06000CX", 11) == 0) { /* These values were measured and tested with a Paragon MFS-6000CX v4.06 */ dev->x_range.min = SANE_FIX (0.0); dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.min = SANE_FIX (0.0); dev->y_range.max = SANE_FIX (13.86 * MM_PER_INCH); dev->x_trans_range.min = SANE_FIX (1.0); dev->y_trans_range.min = SANE_FIX (2.0); dev->x_trans_range.max = SANE_FIX (203.0); dev->y_trans_range.max = SANE_FIX (255.0); dev->dpi_range.max = SANE_FIX (600); dev->sane.model = "MFS-6000CX"; } else if (strncmp ((SANE_String) model_name, "MSF-06000CZ", 11) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a Paragon MFS-6000CX v4.00 */ dev->x_range.min = SANE_FIX (0.0); dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.min = SANE_FIX (0.0); dev->y_range.max = SANE_FIX (13.85 * MM_PER_INCH); dev->x_trans_range.min = SANE_FIX (1.0); dev->y_trans_range.min = SANE_FIX (2.0); dev->x_trans_range.max = SANE_FIX (205.0); dev->y_trans_range.max = SANE_FIX (255.0); dev->dpi_range.max = SANE_FIX (600); dev->sane.model = "MFS-6000CX"; } /* Paragon 1-pass 14" series I */ /* I haven't seen a single report for this, but it is mentioned in the old man page. All reported Paragon 1200SP had a model name "MFS-12000SP" */ else if (strncmp ((SANE_String) model_name, "MSF-12000SP", 11) == 0) { /* These values are not tested and mostly guessed. */ dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.max = SANE_FIX (13.85 * MM_PER_INCH); dev->x_trans_range.min = SANE_FIX (1.0); dev->y_trans_range.min = SANE_FIX (1.0); dev->x_trans_range.max = SANE_FIX (200.0); dev->y_trans_range.max = SANE_FIX (250.0); dev->dpi_range.max = SANE_FIX (1200); dev->flags |= MUSTEK_FLAG_LD_NONE; dev->flags |= MUSTEK_FLAG_PARAGON_1; dev->flags |= MUSTEK_FLAG_USE_BLOCK; dev->sane.model = "MFS-12000SP"; warning = SANE_TRUE; } /* MFS-8000 SP v 1.x */ else if (strncmp ((SANE_String) model_name, "MSF-08000SP", 11) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a Paragon MFS-8000SP v1.20 */ dev->x_range.min = SANE_FIX (0.0); dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.min = SANE_FIX (0); dev->y_range.max = SANE_FIX (355.6); dev->x_trans_range.min = SANE_FIX (1.0); dev->y_trans_range.min = SANE_FIX (1.0); dev->x_trans_range.max = SANE_FIX (205.0); dev->y_trans_range.max = SANE_FIX (255.0); dev->dpi_range.max = SANE_FIX (800); /* At least scanners with firmware 1.20 need a gamma table upload in color mode, otherwise the image is red */ if (fw_revision == 0x120) dev->flags |= MUSTEK_FLAG_FORCE_GAMMA; dev->flags |= MUSTEK_FLAG_PARAGON_1; dev->sane.model = "MFS-8000SP"; } /* This model name exists */ else if (strncmp ((SANE_String) model_name, "MSF-06000SP", 11) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a Paragon MFS-6000SP v3.12 */ dev->x_range.min = SANE_FIX (0.0); dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.min = SANE_FIX (0.0); dev->y_range.max = SANE_FIX (355.6); dev->x_trans_range.min = SANE_FIX (1.0); dev->y_trans_range.min = SANE_FIX (1.0); dev->x_trans_range.max = SANE_FIX (205.0); dev->y_trans_range.max = SANE_FIX (255.0); dev->dpi_range.max = SANE_FIX (600); /* Looks like at least some versions of this scanner produce black images in gray and color mode if MUSTEK_FORCE_GAMMA is not set. At least versions 2.01, 2.02 and 2.10 are reported as having this bug. 3.12 doesn't need this workaround but it doesn't harm either. */ dev->flags |= MUSTEK_FLAG_FORCE_GAMMA; dev->flags |= MUSTEK_FLAG_PARAGON_1; dev->sane.model = "MFS-6000SP"; } /* This one was reported multiple times */ else if (strncmp ((SANE_String) model_name, "MFS-12000SP", 11) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a Paragon MFS-12000SP v1.02 and v1.00 */ dev->x_range.min = SANE_FIX (0.0); dev->x_range.max = SANE_FIX (217.0); dev->y_range.min = SANE_FIX (2.0); dev->y_range.max = SANE_FIX (352.0); dev->x_trans_range.min = SANE_FIX (0.0); dev->y_trans_range.min = SANE_FIX (0.0); dev->x_trans_range.max = SANE_FIX (205.0); dev->y_trans_range.max = SANE_FIX (250.0); dev->dpi_range.max = SANE_FIX (1200); /* Earlier versions of this source code used MUSTEK_FLAG_LD_MFS for firmware versions < 1.02 and LD_NONE for the rest. This didn't work for my scanners. 1.00 doesn't need any LD correction, 1.02, 1.07 and 1.11 do need normal LD corrections. Maybe all != 1.00 need normal LD */ dev->flags |= MUSTEK_FLAG_PARAGON_1; dev->flags |= MUSTEK_FLAG_LD_BLOCK; dev->flags |= MUSTEK_FLAG_USE_BLOCK; dev->sane.model = "MFS-12000SP"; } /* MFS-8000 SP v2.x */ else if (strncmp ((SANE_String) model_name, "MFS-08000SP", 11) == 0) { /* These values are tested with a MFS-08000SP v 2.04 */ dev->x_range.min = SANE_FIX (0.0); dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.min = SANE_FIX (0); dev->y_range.max = SANE_FIX (355.6); dev->x_trans_range.min = SANE_FIX (1.0); dev->y_trans_range.min = SANE_FIX (1.0); dev->x_trans_range.max = SANE_FIX (205.0); dev->y_trans_range.max = SANE_FIX (255.0); dev->dpi_range.max = SANE_FIX (800); /* At least scanners with firmware 1.20 need a gamma table upload in color mode, otherwise the image is red */ if (fw_revision == 0x120) dev->flags |= MUSTEK_FLAG_FORCE_GAMMA; dev->flags |= MUSTEK_FLAG_PARAGON_1; dev->sane.model = "MFS-8000SP"; } /* I have never seen one of those */ else if (strncmp ((SANE_String) model_name, "MFS-06000SP", 11) == 0) { /* These values are not tested. */ dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.max = SANE_FIX (13.84 * MM_PER_INCH); /* copied from MSF-06000SP */ dev->x_trans_range.min = SANE_FIX (1.0); dev->y_trans_range.min = SANE_FIX (1.0); dev->x_trans_range.max = SANE_FIX (205.0); dev->y_trans_range.max = SANE_FIX (255.0); dev->dpi_range.max = SANE_FIX (600); dev->flags |= MUSTEK_FLAG_PARAGON_1; dev->sane.model = "MFS-6000SP"; warning = SANE_TRUE; } /* Paragon 1-pass A4 series II */ else if (strncmp ((SANE_String) model_name, "MFC-08000CZ", 11) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a Paragon 800 II SP v1.06. */ dev->x_range.min = SANE_FIX (1.5); dev->x_range.max = SANE_FIX (218.0); dev->y_range.min = SANE_FIX (0.0); dev->y_range.max = SANE_FIX (293.0); dev->x_trans_range.min = SANE_FIX (0.0); dev->y_trans_range.min = SANE_FIX (0.0); dev->x_trans_range.max = SANE_FIX (205.0); dev->y_trans_range.max = SANE_FIX (254.0); dev->dpi_range.max = SANE_FIX (800); dev->max_block_buffer_size = 2 * 1024 * 1024; dev->flags |= MUSTEK_FLAG_PARAGON_2; dev->flags |= MUSTEK_FLAG_LD_BLOCK; dev->flags |= MUSTEK_FLAG_USE_BLOCK; dev->sane.model = "800S/800 II SP"; } else if (strncmp ((SANE_String) model_name, "MFC-06000CZ", 11) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a Paragon 600 II CD, a Paragon MFC-600S and a Paragon 600 II N. */ dev->x_range.min = SANE_FIX (0.0); dev->x_range.max = SANE_FIX (218.0); dev->y_range.min = SANE_FIX (0.0); dev->y_range.max = SANE_FIX (293.0); dev->x_trans_range.min = SANE_FIX (0.0); dev->y_trans_range.min = SANE_FIX (0.0); dev->x_trans_range.max = SANE_FIX (201.0); dev->y_trans_range.max = SANE_FIX (257.0); dev->dpi_range.max = SANE_FIX (600); /* This model comes in a non-scsi version, too. It is supplied with its own parallel-port like adapter, an AB306N. Two firmware revisions are known: 1.01 and 2.00. Each needs its own line-distance correction code. */ if (dev->flags & MUSTEK_FLAG_N) { if (fw_revision < 0x200) dev->flags |= MUSTEK_FLAG_LD_N1; else dev->flags |= MUSTEK_FLAG_LD_N2; dev->x_trans_range.min = SANE_FIX (33.0); dev->y_trans_range.min = SANE_FIX (62.0); dev->x_trans_range.max = SANE_FIX (183.0); dev->y_trans_range.max = SANE_FIX (238.0); dev->max_block_buffer_size = 1024 * 1024 * 1024; dev->sane.model = "600 II N"; } else if (dev->flags & MUSTEK_FLAG_SCSI_PP) { /* FIXME; experiment with different line distance codes later */ dev->dpi_range.min = SANE_FIX (75.0); dev->flags |= MUSTEK_FLAG_LD_NONE; dev->max_block_buffer_size = 2 * 1024 * 1024; dev->sane.model = "600 II EP"; } else { dev->sane.model = "600S/600 II CD"; dev->flags |= MUSTEK_FLAG_PARAGON_2; dev->flags |= MUSTEK_FLAG_LD_BLOCK; dev->flags |= MUSTEK_FLAG_USE_BLOCK; dev->max_block_buffer_size = 2 * 1024 * 1024; } } /* ScanExpress and ScanMagic series */ else if (strncmp ((SANE_String) model_name, " C03", 4) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a ScannExpress 6000SP 1.00 */ dev->x_range.max = SANE_FIX (215); dev->y_range.min = SANE_FIX (0); dev->y_range.max = SANE_FIX (293); dev->x_trans_range.min = SANE_FIX (0); dev->y_trans_range.min = SANE_FIX (0); dev->x_trans_range.max = SANE_FIX (150.0); dev->y_trans_range.max = SANE_FIX (175.0); dev->dpi_range.max = SANE_FIX (600); dev->dpi_range.min = SANE_FIX (60); dev->flags |= MUSTEK_FLAG_SE; /* At least the SE 6000SP with firmware 1.00 limits its x-resolution to 300 dpi and does *no* interpolation at higher resolutions. So this has to be done in software. */ dev->flags |= MUSTEK_FLAG_ENLARGE_X; dev->sane.model = "ScanExpress 6000SP"; } /* There are two different versions of the ScanExpress 12000SP, one has the model name " C06", the other one is "XC06". The latter seems to be used in the newer "Plus" models. Also there is the Mustek ScanExpress 1200 FS, which looks similar to the ScanExpress 12000 SP but has an "F" instead of the "V" in the firmware version. */ else if (strncmp ((SANE_String) model_name, " C06", 4) == 0) { if (result[32] == 'F') { /* Mustek ScanExpress 1200 FS. Completely untested. */ dev->x_range.min = SANE_FIX (0); dev->y_range.min = SANE_FIX (0); dev->x_range.max = SANE_FIX (215.9); dev->y_range.max = SANE_FIX (291.2); dev->x_trans_range.min = SANE_FIX (0); dev->y_trans_range.min = SANE_FIX (0); dev->x_trans_range.max = SANE_FIX (150.0); dev->y_trans_range.max = SANE_FIX (175.0); dev->dpi_range.max = SANE_FIX (1200); dev->dpi_range.min = SANE_FIX (60); dev->flags |= MUSTEK_FLAG_SE; /* The ScanExpress models limit their x-resolution to 600 dpi and do *no* interpolation at higher resolutions. So this has to be done in software. */ dev->flags |= MUSTEK_FLAG_ENLARGE_X; dev->flags |= MUSTEK_FLAG_COVER_SENSOR; dev->sane.model = "ScanExpress 12000 FS (untested)"; } else { /* These values were measured and compared to those from the Windows driver. Tested with a ScaneExpress 12000SP 2.02 and a ScanMagic 9636S v 1.01 */ dev->x_range.min = SANE_FIX (0); dev->y_range.min = SANE_FIX (0); dev->x_range.max = SANE_FIX (215.9); dev->y_range.max = SANE_FIX (291.2); dev->x_trans_range.min = SANE_FIX (0); dev->y_trans_range.min = SANE_FIX (0); dev->x_trans_range.max = SANE_FIX (150.0); dev->y_trans_range.max = SANE_FIX (175.0); dev->dpi_range.max = SANE_FIX (1200); dev->dpi_range.min = SANE_FIX (60); dev->flags |= MUSTEK_FLAG_SE; /* The ScanExpress models limit their x-resolution to 600 dpi and do *no* interpolation at higher resolutions. So this has to be done in software. */ dev->flags |= MUSTEK_FLAG_ENLARGE_X; dev->flags |= MUSTEK_FLAG_COVER_SENSOR; dev->sane.model = "ScanExpress 12000SP"; } } else if (strncmp ((SANE_String) model_name, "XC06", 4) == 0) { /* These values are tested with a SE 12000 SP Plus v 1.01 */ dev->x_range.max = SANE_FIX (216); dev->y_range.min = SANE_FIX (0); dev->y_range.max = SANE_FIX (294.5); dev->x_trans_range.min = SANE_FIX (0); dev->y_trans_range.min = SANE_FIX (0); dev->x_trans_range.max = SANE_FIX (152.0); dev->y_trans_range.max = SANE_FIX (177.0); dev->dpi_range.max = SANE_FIX (1200); dev->dpi_range.min = SANE_FIX (60); dev->flags |= MUSTEK_FLAG_SE; dev->flags |= MUSTEK_FLAG_SE_PLUS; /* The ScanExpress models limit their x-resolution to 600 dpi and do *no* interpolation at higher resolutions. So this has to be done in software. */ dev->flags |= MUSTEK_FLAG_ENLARGE_X; dev->flags |= MUSTEK_FLAG_COVER_SENSOR; dev->sane.model = "ScanExpress 12000SP Plus"; } /* ScanExpress A3 SP */ else if (strncmp ((SANE_String) model_name, " L03", 4) == 0) { /* These values were measured with a ScannExpress A3 SP 2.00 */ dev->x_range.max = SANE_FIX (297); dev->y_range.min = SANE_FIX (0); dev->y_range.max = SANE_FIX (430); /* TA couldn't be tested due to lack of equipment. So At least the TA IV (A4 size) is supported */ dev->x_trans_range.min = SANE_FIX (0); dev->y_trans_range.min = SANE_FIX (0); dev->x_trans_range.max = SANE_FIX (150.0); dev->y_trans_range.max = SANE_FIX (175.0); dev->dpi_range.max = SANE_FIX (600); dev->dpi_range.min = SANE_FIX (60); dev->flags |= MUSTEK_FLAG_SE; /* The ScanExpress models limit their x-resolution to 300 dpi and do *no* interpolation at higher resolutions. So this has to be done in software. */ dev->flags |= MUSTEK_FLAG_ENLARGE_X; dev->flags |= MUSTEK_FLAG_COVER_SENSOR; dev->sane.model = "ScanExpress A3 SP"; } /* Paragon 1200 SP Pro */ else if (strncmp ((SANE_String) model_name, "MFS-1200SPPRO", 13) == 0) { /* These values were measured with a Paragon 1200 SP Pro v2.01 */ dev->x_range.max = SANE_FIX (8.6 * MM_PER_INCH); dev->y_range.max = SANE_FIX (13.70 * MM_PER_INCH); dev->dpi_range.max = SANE_FIX (1200); dev->sane.model = "1200 SP PRO"; dev->flags |= MUSTEK_FLAG_LD_NONE; dev->flags |= MUSTEK_FLAG_ENLARGE_X; } /* No documentation, but it works: Paragon 1200 A3 PRO */ else if (strncmp ((SANE_String) model_name, "MFS-1200A3PRO", 13) == 0) { /* These values were measured and compared to those from the Windows driver. Tested with a Paragon 1200 A3 Pro v1.10 */ dev->x_range.max = SANE_FIX (11.7 * MM_PER_INCH); dev->y_range.max = SANE_FIX (424); dev->dpi_range.max = SANE_FIX (1200); dev->sane.model = "1200 A3 PRO"; dev->flags |= MUSTEK_FLAG_LD_NONE; dev->flags |= MUSTEK_FLAG_ENLARGE_X; } else { DBG (0, "attach: this Mustek scanner (ID: %s) is not supported yet\n", model_name); DBG (0, "attach: please set the debug level to 5 and send a debug " "report\n"); DBG (0, "attach: to henning@meier-geinitz.de (export " "SANE_DEBUG_MUSTEK=5\n"); DBG (0, "attach: scanimage -L 2>debug.txt). Thank you.\n"); free (dev); return SANE_STATUS_INVAL; } if (dev->flags & MUSTEK_FLAG_SE) { DBG (3, "attach: this is a single-pass scanner\n"); if (result[63] & (1 << 6)) { dev->flags |= MUSTEK_FLAG_TA; DBG (3, "attach: scanner supports transparency adapter (TA)\n"); } } else { if (result[57] & (1 << 6)) { DBG (3, "attach: this is a single-pass scanner\n"); if (dev->flags & MUSTEK_FLAG_LD_NONE) DBG (4, "attach: scanner doesn't need line-distance correction\n"); else if (dev->flags & MUSTEK_FLAG_LD_N1) DBG (4, "attach: scanner has N1 line-distance correction\n"); else if (dev->flags & MUSTEK_FLAG_LD_N2) DBG (4, "attach: scanner has N2 line-distance correction\n"); else if (dev->flags & MUSTEK_FLAG_LD_BLOCK) DBG (4, "attach: scanner has block line-distance correction\n"); else DBG (4, "attach: scanner has normal line-distance correction\n"); } else { dev->flags |= MUSTEK_FLAG_THREE_PASS; /* three-pass scanners quantize to 0.5% of the maximum resolution: */ dev->dpi_range.quant = dev->dpi_range.max / 200; dev->dpi_range.min = dev->dpi_range.quant; DBG (3, "attach: this is a three-pass scanner\n"); } if (result[57] & (1 << 5)) { DBG (3, "attach: this is a professional series scanner\n"); dev->flags |= MUSTEK_FLAG_PRO; status = dev_open (devname, &s, sense_handler); if (status == SANE_STATUS_GOOD) { if (ta_available_pro (&s)) { dev->flags |= MUSTEK_FLAG_TA; DBG (3, "attach: found transparency adapter (TA)\n"); } dev_close (&s); } else { DBG (1, "attach: couldn't open device: %s\n", sane_strstatus (status)); return status; } } if (result[63] & (1 << 2)) { dev->flags |= MUSTEK_FLAG_ADF; DBG (3, "attach: found automatic document feeder (ADF)\n"); if (result[63] & (1 << 3)) { dev->flags |= MUSTEK_FLAG_ADF_READY; DBG (4, "attach: automatic document feeder is ready\n"); } else { DBG (4, "attach: automatic document feeder is out of " "documents\n"); } } if (result[63] & (1 << 6)) { dev->flags |= MUSTEK_FLAG_TA; DBG (3, "attach: found transparency adapter (TA)\n"); } } if (dev->flags & MUSTEK_FLAG_COVER_SENSOR) { if (result[62] & (1 << 0)) DBG (4, "attach: scanner cover is closed\n"); else DBG (4, "attach: scanner cover is open\n"); } if (warning == SANE_TRUE) { DBG (0, "WARNING: Your scanner was detected by the SANE Mustek backend, " "but\n it is not fully tested. It may or may not work. Be " "careful and read\n the PROBLEMS file in the sane directory. " "Please set the debug level of this\n backend to maximum " "(export SANE_DEBUG_MUSTEK=255) and send the output of\n " "scanimage -L to the SANE mailing list sane-devel@lists.alioth.debian.org. " "Please include\n the exact model name of your scanner and to " "which extend it works.\n"); } DBG (2, "attach: found Mustek %s %s, %s%s%s%s\n", dev->sane.model, dev->sane.type, (dev->flags & MUSTEK_FLAG_THREE_PASS) ? "3-pass" : "1-pass", (dev->flags & MUSTEK_FLAG_ADF) ? ", ADF" : "", (dev->flags & MUSTEK_FLAG_TA) ? ", TA" : "", (dev->flags & MUSTEK_FLAG_SE) ? ", SE" : ""); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; } static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status constrain_value (Mustek_Scanner * s, SANE_Int option, void *value, SANE_Int * info) { SANE_Fixed w, dpi; SANE_Status status; if (value) w = *(SANE_Fixed *) value; else w = 0; if (option == OPT_RESOLUTION) { if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { /* The three pass scanners use a 0.5% of the maximum resolution increment for resolutions less than or equal to half of the maximum resolution. The MFS-06000CX uses a 5% of the maximum resolution increment for larger resolutions. The models MFS-12000CX and MSF-06000CZ use 1% of the maximum resolution. We can't represent this easily in SANE, so the constraint is simply for 0.5% and then we round to the 5% or 1% increments if necessary. */ SANE_Fixed max_dpi, quant, half_res; /*w = *(SANE_Word *) value; */ max_dpi = s->hw->dpi_range.max; half_res = max_dpi / 2; if (w > half_res) { /* quantizize to 1% step */ quant = max_dpi / 100; dpi = (w + quant / 2) / quant; dpi *= quant; if (dpi != w) { *(SANE_Word *) value = dpi; if (info) *info |= SANE_INFO_INEXACT; } } } } status = sanei_constrain_value (s->opt + option, value, info); if (s->opt[option].type == SANE_TYPE_FIXED) DBG (5, "constrain_value: %s = %.2f (was %.2f)\n", s->opt[option].name, SANE_UNFIX (*(SANE_Word *) value), SANE_UNFIX (w)); return status; } /* Quantize s->val[OPT_RESOLUTION].w and return the resolution code for the quantized resolution. Quantization depends on scanner type (single pass vs. three-pass) and resolution */ static SANE_Int encode_resolution (Mustek_Scanner * s) { SANE_Fixed max_dpi, dpi; SANE_Int code, mode = 0; dpi = s->val[OPT_RESOLUTION].w; if (!(s->hw->flags & MUSTEK_FLAG_THREE_PASS)) { code = dpi >> SANE_FIXED_SCALE_SHIFT; } else { SANE_Fixed quant, half_res; max_dpi = s->hw->dpi_range.max; half_res = max_dpi / 2; if (dpi <= half_res) { /* quantizize to 0.5% step */ quant = max_dpi / 200; } else { /* quantizize to 1% step */ quant = max_dpi / 100; mode = 0x100; /* indicate 5% or 1% quantization */ } code = (dpi + quant / 2) / quant; if (code < 1) code = 1; } DBG (5, "encode_resolution: code = 0x%x (%d); mode = %x\n", code, code, mode); return code | mode; } static SANE_Int encode_percentage (Mustek_Scanner * s, double value) { SANE_Int max, code, sign = 0; if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { code = (int) ((value / 100.0 * 12) + 12.5); max = 0x18; } else { if (value < 0.0) { value = -value; sign = 0x80; } code = (int) (value / 100.0 * 127 + 0.5); code |= sign; max = 0xff; } if (code > max) code = max; if (code < 0) code = 0x00; return code; } /* encode halftone pattern type and size */ static SANE_Status encode_halftone (Mustek_Scanner * s) { SANE_String selection = s->val[OPT_HALFTONE_DIMENSION].s; SANE_Int i = 0; while ((halftone_list[i] != 0) && (strcmp (selection, halftone_list[i]) != 0)) { i++; } if (halftone_list[i] == 0) return SANE_STATUS_INVAL; if (i < 0x0c) /* standard pattern */ { s->custom_halftone_pattern = SANE_FALSE; s->halftone_pattern_type = i; } else /* custom pattern */ { s->custom_halftone_pattern = SANE_TRUE; i -= 0x0c; i = 8 - i; if (i < 8) i--; i = i + (i << 4); s->halftone_pattern_type = i; } DBG (5, "encode_halftone: %s pattern type %x\n", s->custom_halftone_pattern ? "custom" : "standard", s->halftone_pattern_type); return SANE_STATUS_GOOD; } /* Paragon series */ static SANE_Status area_and_windows (Mustek_Scanner * s) { SANE_Byte cmd[117], *cp; SANE_Int i, offset; /* setup SCSI command (except length): */ memset (cmd, 0, sizeof (cmd)); cmd[0] = MUSTEK_SCSI_AREA_AND_WINDOWS; cp = cmd + 6; /* Some scanners need a larger scanarea for line-distance correction */ offset = 0; if (((s->hw->flags & MUSTEK_FLAG_LD_N1) || ((s->hw->flags & MUSTEK_FLAG_LD_BLOCK) && (s->hw->flags & MUSTEK_FLAG_PARAGON_1))) && (s->mode & MUSTEK_MODE_COLOR)) offset = MAX_LINE_DIST; /* fill in frame header: */ if (s->hw->flags & MUSTEK_FLAG_USE_EIGHTS) { double eights_per_mm = 8 / MM_PER_INCH; SANE_Int tlx, tly, brx, bry; /* * The MSF-06000CZ seems to lock-up if the pixel-unit is used. * Using 1/8" works. * This doesn't seem to be true with the current scheme. * This code isn't used at the moment. */ *cp++ = ((s->mode & MUSTEK_MODE_LINEART) ? 0x00 : 0x01); tlx = SANE_UNFIX (s->val[OPT_TL_X].w) * eights_per_mm + 0.5; tly = SANE_UNFIX (s->val[OPT_TL_Y].w) * eights_per_mm + 0.5; brx = SANE_UNFIX (s->val[OPT_BR_X].w) * eights_per_mm + 0.5; bry = SANE_UNFIX (s->val[OPT_BR_Y].w) * eights_per_mm + 0.5; STORE16L (cp, tlx); STORE16L (cp, tly); STORE16L (cp, brx); STORE16L (cp, bry); DBG (5, "area_and_windows: tlx=%d (%d mm); tly=%d (%d mm); " "brx=%d (%d mm); bry=%d (%d mm)\n", tlx, (int) (tlx / eights_per_mm), tly, (int) (tly / eights_per_mm), brx, (int) (brx / eights_per_mm), bry, (int) (bry / eights_per_mm)); } else { double pixels_per_mm = SANE_UNFIX (s->hw->dpi_range.max) / MM_PER_INCH; SANE_Int tlx, tly, brx, bry; if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) /* 3pass scanners use 1/2 of the max resolution as base */ pixels_per_mm /= 2; /* pixel unit and halftoning: */ *cp++ = 0x8 | ((s->mode & MUSTEK_MODE_LINEART) ? 0x00 : 0x01); /* fill in scanning area: */ if (strcmp (s->val[OPT_SOURCE].s, "Automatic Document Feeder") == 0) { /* must mirror the x coordinates */ brx = SANE_UNFIX (s->hw->x_range.max - s->val[OPT_TL_X].w) * pixels_per_mm + 0.5; tlx = SANE_UNFIX (s->hw->x_range.max - s->val[OPT_BR_X].w) * pixels_per_mm + 0.5; } else { tlx = SANE_UNFIX (s->val[OPT_TL_X].w) * pixels_per_mm + 0.5; brx = SANE_UNFIX (s->val[OPT_BR_X].w) * pixels_per_mm + 0.5; } tly = SANE_UNFIX (s->val[OPT_TL_Y].w) * pixels_per_mm + 0.5; bry = SANE_UNFIX (s->val[OPT_BR_Y].w) * pixels_per_mm + 0.5 + offset; STORE16L (cp, tlx); STORE16L (cp, tly); STORE16L (cp, brx); STORE16L (cp, bry); DBG (5, "area_and_windows: tlx=%d (%d mm); tly=%d (%d mm); " "brx=%d (%d mm); bry=%d (%d mm)\n", tlx, (int) (tlx / pixels_per_mm), tly, (int) (tly / pixels_per_mm), brx, (int) (brx / pixels_per_mm), bry, (int) (bry / pixels_per_mm)); } if (s->custom_halftone_pattern) { *cp++ = 0x40; /* mark presence of user pattern */ *cp++ = s->halftone_pattern_type; /* set pattern length */ for (i = 0; i < (s->halftone_pattern_type & 0x0f) * ((s->halftone_pattern_type >> 4) & 0x0f); ++i) *cp++ = s->val[OPT_HALFTONE_PATTERN].wa[i]; } cmd[4] = (cp - cmd) - 6; return dev_cmd (s, cmd, (cp - cmd), 0, 0); } /* ScanExpress */ static SANE_Status set_window_se (Mustek_Scanner * s, SANE_Int lamp) { SANE_Byte cmd[58], *cp; double pixels_per_mm; SANE_Int offset; SANE_Int tlx, tly, width, height; /* setup SCSI command (except length): */ memset (cmd, 0, sizeof (cmd)); cmd[0] = MUSTEK_SCSI_SET_WINDOW; cp = cmd + sizeof (scsi_set_window); /* skip command block */ if (s->mode & MUSTEK_MODE_COLOR) { /* We have to increase the specified resolution to the next */ /* "standard" resolution due to a firmware bug(?) in color mode */ /* It's possible to scan in 36, 75, 100, 150, 200, 250, 300, */ /* 400, 500, 600, 900, 1200 dpi but the speed is only different */ /* with 36, 150, 300, 600, 1200 dpi. */ /* Additionally we must increase the window length slightly to */ /* compensate for different line counts for r/g/b */ const SANE_Int resolution_list[] = { 36, 150, 300, 600, 1200, 0 }; SANE_Int entry = 0; while (resolution_list[entry] < s->resolution_code) entry++; s->ld.peak_res = resolution_list[entry]; offset = MAX_LINE_DIST; /* distance r/b lines */ } else { /* In gray and lineart modes all resolutions are possible */ s->ld.peak_res = s->resolution_code; offset = 0; } DBG (5, "set_window_se: hardware resolution is %d dpi; offset is %d\n", s->ld.peak_res, offset); STORE16B (cp, 0); /* window identifier */ STORE16B (cp, s->ld.peak_res); /* x and y resolution */ STORE16B (cp, 0); /* not used acc. to specs */ pixels_per_mm = SANE_UNFIX (s->hw->dpi_range.max) / MM_PER_INCH; /* fill in scanning area, begin and length(!) */ if ((strcmp (s->val[OPT_SOURCE].s, "Transparency Adapter") == 0) && !(s->hw->flags & MUSTEK_FLAG_TA)) { /* need to add the start values of the transparency adapter */ tlx = (SANE_UNFIX (s->val[OPT_TL_X].w) + 33.0) * pixels_per_mm + 0.5; tly = (SANE_UNFIX (s->val[OPT_TL_Y].w) + 60.0) * pixels_per_mm + 0.5; DBG (5, "set_window_se: added offset for transparency adapter\n"); } else { /* no transparency adapter selected or calculation done in firmware */ tlx = SANE_UNFIX (s->val[OPT_TL_X].w) * pixels_per_mm + 0.5; tly = SANE_UNFIX (s->val[OPT_TL_Y].w) * pixels_per_mm + 0.5; } width = (SANE_UNFIX (s->val[OPT_BR_X].w) - SANE_UNFIX (s->val[OPT_TL_X].w)) * pixels_per_mm + 0.5; height = (SANE_UNFIX (s->val[OPT_BR_Y].w) - SANE_UNFIX (s->val[OPT_TL_Y].w)) * pixels_per_mm + 0.5 + offset; DBG (5, "set_window_se: tlx=%d (%d mm); tly=%d (%d mm); width=%d (%d mm); " "height=%d (%d mm)\n", tlx, (int) (tlx / pixels_per_mm), tly, (int) (tly / pixels_per_mm), width, (int) (width / pixels_per_mm), height, (int) (height / pixels_per_mm)); STORE32B (cp, tlx); STORE32B (cp, tly); STORE32B (cp, width); STORE32B (cp, height); *cp++ = 0x00; /* brightness, not impl. */ *cp++ = 0x80; /* threshold, not impl. */ *cp++ = 0x00; /* contrast, not impl. */ /* Note that 'image composition' has no meaning for the SE series */ /* Mode selection is accomplished solely by bits/pixel (1, 8, 24) */ if (s->mode & MUSTEK_MODE_COLOR) { *cp++ = 0x05; /* actually not used! */ *cp++ = 24; /* 24 bits/pixel in color mode */ } else if (s->mode & MUSTEK_MODE_GRAY) { *cp++ = 0x02; /* actually not used! */ *cp++ = 8; /* 8 bits/pixel in gray mode */ } else { *cp++ = 0x00; /* actually not used! */ *cp++ = 1; /* 1 bit/pixel in lineart mode */ } cp += 14; /* skip reserved bytes */ *cp++ = lamp; /* 0 = normal, 1 = on, 2 = off */ if ((s->hw->flags & MUSTEK_FLAG_TA) && (strcmp (s->val[OPT_SOURCE].s, "Transparency Adapter") == 0)) *cp++ = 1; else *cp++ = 0; cp += 5; /* skip reserved bytes */ cmd[8] = cp - cmd - sizeof (scsi_set_window); return dev_cmd (s, cmd, (cp - cmd), 0, 0); } /* Pro series */ static SANE_Status set_window_pro (Mustek_Scanner * s) { SANE_Byte cmd[20], *cp; double pixels_per_mm; memset (cmd, 0, sizeof (cmd)); cmd[0] = MUSTEK_SCSI_SET_WINDOW; if (strcmp (s->hw->sane.model, "1200 SP PRO") == 0) cmd[8] = 0x09; else cmd[8] = 0x0a; cp = cmd + sizeof (scsi_set_window); /* skip command block */ *cp++ = 0; /* what's this? */ pixels_per_mm = SANE_UNFIX (s->hw->dpi_range.max) / MM_PER_INCH; /* The next for 16 bit values are x0, y0, x1, y1 in pixels at max res */ STORE16L (cp, SANE_UNFIX (s->val[OPT_TL_X].w) * pixels_per_mm + 0.5); STORE16L (cp, SANE_UNFIX (s->val[OPT_TL_Y].w) * pixels_per_mm + 0.5); STORE16L (cp, SANE_UNFIX (s->val[OPT_BR_X].w) * pixels_per_mm + 0.5); STORE16L (cp, SANE_UNFIX (s->val[OPT_BR_Y].w) * pixels_per_mm + 0.5); if (strcmp (s->hw->sane.model, "1200 SP PRO") != 0) *cp++ = lamp_off_time; /* Only needed for A3 Pro, default: 60 minutes until lamp-off */ DBG (5, "set_window_pro\n"); return dev_cmd (s, cmd, (cp - cmd), 0, 0); } /* Pro series calibration */ static SANE_Status get_calibration_size_pro (Mustek_Scanner * s) { SANE_Status status; SANE_Byte cmd[6]; SANE_Byte result[6]; size_t len; memset (cmd, 0, sizeof (cmd)); memset (result, 0, sizeof (result)); cmd[0] = MUSTEK_SCSI_GET_IMAGE_STATUS; cmd[4] = 0x06; /* size of result */ cmd[5] = 0x80; /* get back buffer size and number of buffers */ len = sizeof (result); status = dev_cmd (s, cmd, sizeof (cmd), result, &len); if (status != SANE_STATUS_GOOD) return status; s->hw->cal.bytes = result[1] | (result[2] << 8); s->hw->cal.lines = result[3] | (result[4] << 8); DBG (4, "get_calibration_size_pro: bytes=%d, lines=%d\n", s->hw->cal.bytes, s->hw->cal.lines); return SANE_STATUS_GOOD; } static SANE_Status get_calibration_lines_pro (Mustek_Scanner * s) { SANE_Status status; SANE_Byte cmd[10]; size_t len; SANE_Int line; DBG (2, "get_calibration_lines_pro: please wait for warmup\n"); memset (cmd, 0, sizeof (cmd)); cmd[0] = MUSTEK_SCSI_READ_DATA; len = s->hw->cal.bytes; cmd[6] = (len >> 16) & 0xff; cmd[7] = (len >> 8) & 0xff; cmd[8] = (len >> 0) & 0xff; for (line = 0; line < s->hw->cal.lines; line++) { status = dev_cmd (s, cmd, sizeof (scsi_read_data), s->hw->cal.buffer + line * len, &len); if ((status != SANE_STATUS_GOOD) || (len != (unsigned int) s->hw->cal.bytes)) { DBG (1, "get_calibration_lines_pro: read failed\n"); return status; } } DBG (5, "get_calibration_lines_pro finished. Assuming 12 bits per color\n"); return SANE_STATUS_GOOD; } static SANE_Status send_calibration_lines_pro (Mustek_Scanner * s) { SANE_Status status; SANE_Byte *cmd1, *cmd2; size_t buf_size; SANE_Word column, line, color; DBG (5, "send_calibration_lines_pro\n"); buf_size = s->hw->cal.bytes / 2; cmd1 = (SANE_Byte *) malloc (buf_size + sizeof (scsi_send_data)); cmd2 = (SANE_Byte *) malloc (buf_size + sizeof (scsi_send_data)); if (!cmd1 || !cmd2) { DBG (1, "send_calibration_lines_pro: failed to malloc %ld bytes for " "sending lines\n", (long int) (buf_size + sizeof (scsi_send_data))); return SANE_STATUS_NO_MEM; } memset (cmd1, 0, sizeof (scsi_send_data)); memset (cmd2, 0, sizeof (scsi_send_data)); cmd1[0] = cmd2[0] = MUSTEK_SCSI_SEND_DATA; cmd1[6] = cmd2[6] = (buf_size >> 16) & 0xff; cmd1[7] = cmd2[7] = (buf_size >> 8) & 0xff; cmd1[8] = cmd2[8] = (buf_size >> 0) & 0xff; cmd1[9] = 0; /* Least significant 8 bits */ cmd2[9] = 0x80; /* Most significant 2 bits */ for (color = 0; color < 3; color++) { for (column = 0; column < s->hw->cal.bytes / 6; column++) { SANE_Word calibration_word = 0; for (line = 0; line < s->hw->cal.lines; line++) { calibration_word += *(s->hw->cal.buffer + column * 6 + color_seq[color] * 2 + 0) + (*(s->hw->cal.buffer + column * 6 + color_seq[color] * 2 + 1) << 8); } if (!calibration_word) calibration_word = 1; calibration_word = (1024 * 65536 / calibration_word) - 1024; if (calibration_word > 1023) calibration_word = 1023; *(cmd1 + sizeof (scsi_send_data) + (buf_size / 3) * color + column) = calibration_word & 0xff; *(cmd2 + sizeof (scsi_send_data) + (buf_size / 3) * color + column) = (calibration_word >> 8) & 0xff; } } status = dev_cmd (s, cmd1, buf_size + sizeof (scsi_send_data), 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "send_calibration_lines_pro: send failed\n"); return status; } status = dev_cmd (s, cmd2, buf_size + sizeof (scsi_send_data), 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "send_calibration_lines_pro: send failed\n"); return status; } free (cmd1); free (cmd2); return SANE_STATUS_GOOD; } static SANE_Status calibration_pro (Mustek_Scanner * s) { SANE_Status status; if (s->val[OPT_QUALITY_CAL].w) DBG (4, "calibration_pro: doing calibration\n"); else { DBG (4, "calibration_pro: calibration not necessary\n"); return SANE_STATUS_GOOD; } status = get_calibration_size_pro (s); if (status != SANE_STATUS_GOOD) return status; s->hw->cal.buffer = (SANE_Byte *) malloc (s->hw->cal.bytes * s->hw->cal.lines); if (!s->hw->cal.buffer) { DBG (1, "calibration_pro: failed to malloc %d bytes for buffer\n", s->hw->cal.bytes * s->hw->cal.lines); return SANE_STATUS_NO_MEM; } status = get_calibration_lines_pro (s); if (status != SANE_STATUS_GOOD) return status; status = send_calibration_lines_pro (s); if (status != SANE_STATUS_GOOD) return status; free (s->hw->cal.buffer); return SANE_STATUS_GOOD; } /* ScanExpress series calibration */ static SANE_Status get_calibration_lines_se (Mustek_Scanner * s) { SANE_Status status; SANE_Byte cmd[10]; size_t len; SANE_Word lines, bytes_per_color; if (s->mode == MUSTEK_MODE_COLOR) { lines = s->hw->cal.lines * 3; bytes_per_color = s->hw->cal.bytes / 3; } else { lines = s->hw->cal.lines; bytes_per_color = s->hw->cal.bytes; } DBG (4, "get_calibration_lines_se: reading %d lines (%d bytes per color)\n", lines, bytes_per_color); memset (cmd, 0, sizeof (cmd)); cmd[0] = MUSTEK_SCSI_READ_DATA; cmd[2] = 1; cmd[7] = (lines >> 8) & 0xff; cmd[8] = (lines >> 0) & 0xff; len = lines * bytes_per_color; status = dev_cmd (s, cmd, sizeof (scsi_read_data), s->hw->cal.buffer, &len); if ((status != SANE_STATUS_GOOD) || (len != (unsigned int) (lines * bytes_per_color))) { DBG (1, "get_calibration_lines_se: read failed\n"); return status; } return SANE_STATUS_GOOD; } static SANE_Status send_calibration_lines_se (Mustek_Scanner * s, SANE_Word color) { SANE_Status status; SANE_Byte *cmd; size_t buf_size; SANE_Word column; SANE_Word bytes_per_color; if (s->mode == MUSTEK_MODE_COLOR) { bytes_per_color = s->hw->cal.bytes / 3; } else { bytes_per_color = s->hw->cal.bytes; } buf_size = bytes_per_color; DBG (5, "send_calibration_lines_se: %d bytes, color: %d\n", bytes_per_color, color + 1); cmd = (SANE_Byte *) malloc (buf_size + sizeof (scsi_send_data)); if (!cmd) { DBG (1, "send_calibration_lines_se: failed to malloc %ld bytes for " "sending lines\n", (long int) (buf_size + sizeof (scsi_send_data))); return SANE_STATUS_NO_MEM; } memset (cmd, 0, sizeof (scsi_send_data)); for (column = 0; column < bytes_per_color; column++) { SANE_Word line; SANE_Word cali_word = 0; SANE_Int color_seq[] = { 2, 0, 1 }; for (line = 0; line < s->hw->cal.lines; line++) cali_word += *(s->hw->cal.buffer + line * bytes_per_color + bytes_per_color * color_seq[color] + column); if (!cali_word) cali_word = 1; cali_word = 256 * s->hw->cal.lines * 255 / cali_word - 256; if (cali_word > 255) cali_word = 255; *(cmd + sizeof (scsi_send_data) + column) = cali_word; } cmd[0] = MUSTEK_SCSI_SEND_DATA; cmd[2] = 1; cmd[6] = color + 1; cmd[7] = (buf_size >> 8) & 0xff; cmd[8] = (buf_size >> 0) & 0xff; status = dev_cmd (s, cmd, buf_size + sizeof (scsi_send_data), 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "send_calibration_lines_se: send failed\n"); return status; } free (cmd); return SANE_STATUS_GOOD; } static SANE_Status calibration_se (Mustek_Scanner * s) { SANE_Status status; if (!s->val[OPT_QUALITY_CAL].w || s->val[OPT_PREVIEW].w || s->mode == MUSTEK_MODE_LINEART) return SANE_STATUS_GOOD; DBG (4, "calibration_se: doing calibration\n"); s->hw->cal.lines = MIN (s->hw->cal.lines, s->hw->buffer_size / s->hw->cal.bytes); s->hw->cal.buffer = (SANE_Byte *) malloc (s->hw->cal.bytes * s->hw->cal.lines); if (!s->hw->cal.buffer) { DBG (1, "calibration_se: failed to malloc %d bytes for buffer\n", s->hw->cal.bytes * s->hw->cal.lines); return SANE_STATUS_NO_MEM; } status = get_calibration_lines_se (s); if (status != SANE_STATUS_GOOD) return status; if (s->mode == MUSTEK_MODE_GRAY) status = send_calibration_lines_se (s, 0); else { status = send_calibration_lines_se (s, 0); status = send_calibration_lines_se (s, 1); status = send_calibration_lines_se (s, 2); } if (status != SANE_STATUS_GOOD) return status; free (s->hw->cal.buffer); return SANE_STATUS_GOOD; } /* ScanExpress series */ static SANE_Status send_gamma_table_se (Mustek_Scanner * s) { SANE_Status status; SANE_Byte gamma[10 + 4096], *cp; SANE_Int color, factor, val_a, val_b; SANE_Int i, j; # define CLIP(x) ((x) < 0 ? 0 : ((x) > 255 ? 255 : (x))) memset (gamma, 0, sizeof (scsi_send_data)); gamma[0] = MUSTEK_SCSI_SEND_DATA; gamma[2] = 0x03; /* indicates gamma table */ if ((s->mode & MUSTEK_MODE_GRAY) || (s->mode & MUSTEK_MODE_COLOR)) { if (s->hw->gamma_length + sizeof (scsi_send_data) > sizeof (gamma)) return SANE_STATUS_NO_MEM; gamma[7] = (s->hw->gamma_length >> 8) & 0xff; gamma[8] = (s->hw->gamma_length >> 0) & 0xff; factor = s->hw->gamma_length / 256; color = (s->mode & MUSTEK_MODE_COLOR) ? 1 : 0; do { gamma[6] = color; if (color == 0) { val_a = s->gamma_table[0][1]; val_b = s->gamma_table[0][0]; } else { /* compose intensity gamma and color channel gamma: */ val_a = s->gamma_table[0][s->gamma_table[color][1]]; val_b = s->gamma_table[0][s->gamma_table[color][0]]; } /* Now val_a is extrapolated from [0] and [1] */ val_a = MAX (2 * val_b - val_a, 0); /* Interpolate first entries from 256 entry table */ cp = gamma + sizeof (scsi_send_data); for (j = 0; j < factor; j++) *cp++ = CLIP (((factor - j) * val_a + j * val_b + factor / 2) / factor); for (i = 1; i < 256; i++) { if (color == 0) { val_a = s->gamma_table[0][i - 1]; val_b = s->gamma_table[0][i]; } else { /* compose intensity gamma and color channel gamma: */ val_a = s->gamma_table[0][s->gamma_table[color][i - 1]]; val_b = s->gamma_table[0][s->gamma_table[color][i]]; } /* Interpolate next entries from the 256 entry table */ for (j = 0; j < factor; j++) *cp++ = CLIP (((factor - j) * val_a + j * val_b + factor / 2) / factor); } DBG (5, "send_gamma_table_se: sending table for color %d\n", gamma[6]); status = dev_cmd (s, gamma, sizeof (scsi_send_data) + s->hw->gamma_length, 0, 0); ++color; } while ((color != 1) & (color < 4) & (status == SANE_STATUS_GOOD)); return status; } else { /* In lineart mode the threshold is encoded in byte 8 as follows */ /* brightest -> 00 01 02 ... 7F 80 81 82 ... FF <- darkest image */ gamma[6] = 0x04; gamma[8] = 128 - 127 * SANE_UNFIX (s->val[OPT_BRIGHTNESS].w) / 100.0; DBG (5, "send_gamma_table_se: sending lineart threshold %2X\n", gamma[8]); return dev_cmd (s, gamma, sizeof (scsi_send_data), 0, 0); } } /* Paragon series */ static SANE_Status mode_select_paragon (Mustek_Scanner * s, SANE_Int color_code) { SANE_Int speed_code; SANE_Byte mode[19], *cp; /* calculate funky speed code: */ for (speed_code = 0; speed_list[speed_code]; ++speed_code) { if (strcmp (speed_list[speed_code], s->val[OPT_SPEED].s) == 0) break; } if (speed_code > 4) speed_code = 4; else if (speed_code < 0) speed_code = 0; if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { speed_code = 5 - speed_code; /* 1 is fast, 5 is slow */ } else { speed_code = 4 - speed_code; /* 0 is fast, 4 is slow */ } memset (mode, 0, sizeof (mode)); mode[0] = MUSTEK_SCSI_MODE_SELECT; /* set command length and resolution code: */ if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { mode[4] = 0x0b; mode[7] = s->resolution_code; } else { mode[4] = 0x0d; cp = mode + 17; STORE16L (cp, s->resolution_code); } /* set mode byte: */ mode[6] = 0x83 | (color_code << 5); if (!(s->hw->flags & MUSTEK_FLAG_USE_EIGHTS)) mode[6] |= 0x08; if (s->custom_halftone_pattern) mode[6] |= 0x10; if (s->hw->flags & MUSTEK_FLAG_PARAGON_1) { if ((s->mode == MUSTEK_MODE_LINEART) || (s->mode == MUSTEK_MODE_HALFTONE)) { mode[8] = encode_percentage (s, SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)); mode[9] = encode_percentage (s, SANE_UNFIX (s->val[OPT_CONTRAST].w)); } else { mode[8] = 0x0c; mode[9] = 0x0c; } mode[10] = 2; /* grain */ if (s->val[OPT_PREVIEW].w && s->val[OPT_FAST_PREVIEW].w) mode[11] = 0x01; else if ((s->mode == MUSTEK_MODE_COLOR) || (s->mode == MUSTEK_MODE_HALFTONE)) mode[11] = 0x00; /* speed */ else mode[11] = 0x02; /* speed */ mode[12] = 0x00; /* shadow param not used by Mustek */ mode[13] = 0xff; /* highlight only used by some scanners */ mode[14] = 0x70; /* paper- */ mode[15] = 0x00; /* length */ mode[16] = 0x53; /* midtone param not used by Mustek */ } else if (s->hw->flags & MUSTEK_FLAG_PARAGON_2) { mode[8] = encode_percentage (s, SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)); mode[9] = encode_percentage (s, SANE_UNFIX (s->val[OPT_CONTRAST].w)); mode[10] = 2; /* grain */ if ((s->mode == MUSTEK_MODE_COLOR) || (s->mode == MUSTEK_MODE_HALFTONE)) mode[11] = 0x00; /* speed */ else mode[11] = 0x02; /* speed */ mode[12] = 0x00; /* shadow param not used by Mustek */ mode[13] = 0x00; /* highlight param not used by Mustek */ mode[14] = 0x5c; /* paper- */ mode[15] = 0x00; /* length */ mode[16] = 0x41; /* midtone param not used by Mustek */ } else if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { if (s->mode & MUSTEK_MODE_COLOR) { mode[8] = encode_percentage (s, SANE_UNFIX (s->val[OPT_BRIGHTNESS + s->pass + 1].w - 1)); mode[9] = encode_percentage (s, SANE_UNFIX (s->val[OPT_CONTRAST + s->pass + 1].w - 1)); } else { mode[8] = encode_percentage (s, SANE_UNFIX (s->val[OPT_BRIGHTNESS].w - 1)); mode[9] = encode_percentage (s, SANE_UNFIX (s->val[OPT_CONTRAST].w - 1)); } mode[10] = s->halftone_pattern_type; mode[11] = speed_code; /* lamp setting not supported yet */ mode[12] = 0; /* shadow param not used by Mustek */ mode[13] = 0; /* highlight param not used by Mustek */ mode[14] = mode[15] = 0; /* paperlength not used by Mustek */ mode[16] = 0; /* midtone param not used by Mustek */ } else { mode[8] = encode_percentage (s, SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)); mode[9] = encode_percentage (s, SANE_UNFIX (s->val[OPT_CONTRAST].w)); mode[10] = s->halftone_pattern_type; mode[11] = speed_code; /* lamp setting not supported yet */ mode[12] = 0; /* shadow param not used by Mustek */ mode[13] = 0; /* highlight param not used by Mustek */ mode[14] = mode[15] = 0; /* paperlength not used by Mustek */ mode[16] = 0; /* midtone param not used by Mustek */ } DBG (5, "mode_select: resolution_code=%d (0x%x)\n", s->resolution_code, s->resolution_code); return dev_cmd (s, mode, 6 + mode[4], 0, 0); } /* Pro series */ static SANE_Status mode_select_pro (Mustek_Scanner * s) { SANE_Byte mode[19], *cp; memset (mode, 0, sizeof (mode)); mode[0] = MUSTEK_SCSI_MODE_SELECT; mode[4] = 0x0d; if (s->mode & MUSTEK_MODE_COLOR) { if (strcmp (s->val[OPT_BIT_DEPTH].s, "12") == 0) mode[6] = 0xE0; else mode[6] = 0x60; } else if (s->mode & MUSTEK_MODE_GRAY) { if (s->val[OPT_FAST_GRAY_MODE].w) mode[6] = 0x20; else mode[6] = 0x40; } else mode[6] = 0x00; /* lineart */ mode[7] = 0; mode[8] = 0; mode[9] = 0; mode[10] = 0; mode[11] = 0x00; mode[12] = 0x27; mode[13] = 0xb0; mode[14] = 0x04; mode[15] = 0x43; mode[16] = 0x41; cp = mode + 17; STORE16L (cp, s->resolution_code); DBG (5, "mode_select_pro: resolution_code=%d (0x%x), mode=0x%x\n", s->resolution_code, s->resolution_code, mode[6]); return dev_cmd (s, mode, 6 + mode[4], 0, 0); } /* Paragon and Pro series. According to Mustek, the only builtin gamma table is a linear table, so all we support here is user-defined gamma tables. */ static SANE_Status gamma_correction (Mustek_Scanner * s, SANE_Int color_code) { SANE_Int i, j, table = 0, len = 0, bytes_per_channel, num_channels = 1; SANE_Byte gamma[4096 + 10], val, *cp; /* for Paragon models 3 x 256 is the maximum. Pro needs 4096 bytes */ if ((s->hw->flags & MUSTEK_FLAG_N) && ((s->mode & MUSTEK_MODE_LINEART) || (s->mode & MUSTEK_MODE_HALFTONE))) { /* sigh! - the 600 II N needs a (dummy) table download even for lineart and halftone mode, else it produces a completely white image. Thank Mustek for their buggy firmware ! */ memset (gamma, 0, sizeof (gamma)); gamma[0] = MUSTEK_SCSI_LOOKUP_TABLE; gamma[2] = 0x0; /* indicate any preloaded gamma table */ DBG (5, "gamma_correction: sending dummy gamma table\n"); return dev_cmd (s, gamma, 6, 0, 0); } if (((s->mode & MUSTEK_MODE_LINEART) || (s->mode & MUSTEK_MODE_HALFTONE)) && !(s->hw->flags & MUSTEK_FLAG_PRO)) { DBG (5, "gamma_correction: nothing to do in lineart mode -- exiting\n"); return SANE_STATUS_GOOD; } if ((!s->val[OPT_CUSTOM_GAMMA].w) && (!(s->hw->flags & MUSTEK_FLAG_PRO))) { /* Do we need to upload a gamma table even if the user didn't select this option? Some scanners need this work around. */ if (!(s->hw->flags & MUSTEK_FLAG_FORCE_GAMMA) || !((s->mode & MUSTEK_MODE_COLOR) || (s->mode & MUSTEK_MODE_GRAY))) { DBG (5, "gamma_correction: no custom table selected -- exititing\n"); return SANE_STATUS_GOOD; } } if (s->mode & MUSTEK_MODE_COLOR) { table = 1; if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) table += s->pass; else { if ((color_code == MUSTEK_CODE_GRAY) && !(s->hw->flags & MUSTEK_FLAG_PRO)) num_channels = 3; else table = color_code; } } else if (s->hw->flags & MUSTEK_FLAG_N) { /* it seems 600 II N (firmware 1.x at least) wants 768 bytes in * gray mode too */ num_channels = 3; } memset (gamma, 0, sizeof (gamma)); gamma[0] = MUSTEK_SCSI_LOOKUP_TABLE; if (s->hw->flags & MUSTEK_FLAG_PRO) { bytes_per_channel = 4096; len = bytes_per_channel; if (s->mode == MUSTEK_MODE_COLOR) { gamma[9] = (color_code << 6); /* color */ if (strcmp (s->val[OPT_BIT_DEPTH].s, "12") == 0) gamma[2] = 0x7f; /* medium brightness */ } else if (s->mode == MUSTEK_MODE_GRAY) { gamma[9] = 0x80; /* grayscale */ if (s->val[OPT_FAST_GRAY_MODE].w) gamma[2] = 0x7f; /* medium brightness */ } else /* lineart */ { gamma[2] = 128 - 127 * SANE_UNFIX (s->val[OPT_BRIGHTNESS].w) / 100.0; gamma[9] = 0x80; /* grayscale/lineart */ DBG (5, "gamma_correction: sending brightness information\n"); } gamma[7] = (len >> 8) & 0xff; /* big endian! */ gamma[8] = (len >> 0) & 0xff; } else { bytes_per_channel = 256; len = num_channels * bytes_per_channel; gamma[2] = 0x27; /* indicate user-selected gamma table */ if (s->hw->flags & MUSTEK_FLAG_N) { /* 600 II N always uses 6-byte cdb */ gamma[3] = (len >> 8) & 0xff; /* big endian! */ gamma[4] = (len >> 0) & 0xff; /* no way to pass color_code (?) */ } else { gamma[7] = (len >> 8) & 0xff; /* big endian! */ gamma[8] = (len >> 0) & 0xff; gamma[9] = (color_code << 6); } } if (len > 0) { cp = gamma + 10; for (j = 0; j < num_channels; ++j) { for (i = 0; i < bytes_per_channel; ++i) { if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) val = s->gamma_table[table][i * 256 / bytes_per_channel]; else val = i * 256 / bytes_per_channel; if ((s->mode & MUSTEK_MODE_COLOR) && (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE)) /* compose intensity gamma and color channel gamma: */ val = s->gamma_table[0][val]; *cp++ = val; } if (!(s->hw->flags & MUSTEK_FLAG_N) || !(s->mode & MUSTEK_MODE_GRAY)) table++; } } DBG (5, "gamma_correction: sending gamma table of %d bytes\n", len); return dev_cmd (s, gamma, 10 + len, 0, 0); } static SANE_Status send_gamma_table (Mustek_Scanner * s) { SANE_Status status; if (s->one_pass_color_scan) { if (s->hw->flags & MUSTEK_FLAG_N) /* This _should_ work for all one-pass scanners (not just AB306N scanners), but it doesn't work for my Paragon 600 II SP with firmware rev 1.01. Too bad, since it would simplify the gamma correction code quite a bit. */ status = gamma_correction (s, MUSTEK_CODE_GRAY); else { status = gamma_correction (s, MUSTEK_CODE_RED); if (status != SANE_STATUS_GOOD) return status; status = gamma_correction (s, MUSTEK_CODE_GREEN); if (status != SANE_STATUS_GOOD) return status; status = gamma_correction (s, MUSTEK_CODE_BLUE); } } else status = gamma_correction (s, MUSTEK_CODE_GRAY); return status; } /* ScanExpress and Paragon series */ static SANE_Status start_scan (Mustek_Scanner * s) { SANE_Byte start[6]; SANE_Status status; memset (start, 0, sizeof (start)); start[0] = MUSTEK_SCSI_START_STOP; start[4] = 0x01; DBG (4, "start_scan\n"); /* ScanExpress and Pro models don't have any variants */ if (!(s->hw->flags & MUSTEK_FLAG_SE) && !(s->hw->flags & MUSTEK_FLAG_PRO)) { if (s->mode & MUSTEK_MODE_COLOR) { if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) start[4] |= ((s->pass + 1) << 3); else start[4] |= 0x20; } /* or in single/multi bit: */ start[4] |= ((s->mode & MUSTEK_MODE_LINEART) || (s->mode & MUSTEK_MODE_HALFTONE)) ? 0 : (1 << 6); /* or in expanded resolution bit: */ if (s->val[OPT_RESOLUTION].w > (s->hw->dpi_range.max / 2) && ((s->hw->flags & MUSTEK_FLAG_THREE_PASS) || (s->hw->flags & MUSTEK_FLAG_PARAGON_1) || (s->hw->flags & MUSTEK_FLAG_PARAGON_2))) start[4] |= 1 << 7; /* block mode (or whatever) */ if (s->hw->flags & MUSTEK_FLAG_USE_BLOCK) { start[5] = 0x08; DBG (4, "start_scan: using block mode\n"); } } status = dev_cmd (s, start, sizeof (start), 0, 0); if (status != SANE_STATUS_GOOD) DBG (1, "start_scan returned status %s\n", sane_strstatus (status)); return status; } static SANE_Status do_eof (Mustek_Scanner * s) { if (s->pipe >= 0) { close (s->pipe); s->pipe = -1; DBG (5, "do_eof: closing pipe\n"); } return SANE_STATUS_EOF; } static SANE_Status do_stop (Mustek_Scanner * s) { SANE_Status status = SANE_STATUS_GOOD; DBG (5, "do_stop\n"); if (s->cancelled) status = SANE_STATUS_CANCELLED; s->scanning = SANE_FALSE; s->pass = 0; if (sanei_thread_is_valid (s->reader_pid)) { SANE_Int exit_status; struct timeval now; long int scan_time; long int scan_size; SANE_Pid pid; /* print scanning time */ gettimeofday (&now, 0); scan_time = now.tv_sec - s->start_time; if (scan_time < 1) scan_time = 1; scan_size = s->hw->bpl * s->hw->lines / 1024; DBG (2, "Scanning time was %ld seconds, %ld kB/s\n", scan_time, scan_size / scan_time); if (s->total_bytes == s->params.lines * s->params.bytes_per_line) DBG (3, "Scanned %d bytes as expected\n", s->total_bytes); else if (s->total_bytes < s->params.lines * s->params.bytes_per_line) DBG (3, "Scanned %d bytes, expected %d bytes\n", s->total_bytes, s->params.lines * s->params.bytes_per_line); else DBG (1, "Warning: Scanned %d bytes, but expected only %d bytes\n", s->total_bytes, s->params.lines * s->params.bytes_per_line); /* ensure child knows it's time to stop: */ DBG (5, "do_stop: terminating reader process\n"); sanei_thread_kill (s->reader_pid); pid = sanei_thread_waitpid (s->reader_pid, &exit_status); if (!sanei_thread_is_valid (pid)) { DBG (1, "do_stop: sanei_thread_waitpid failed, already terminated? (%s)\n", strerror (errno)); } else { DBG (2, "do_stop: reader process terminated with status %s\n", sane_strstatus (exit_status)); if (status != SANE_STATUS_CANCELLED && exit_status != SANE_STATUS_GOOD) status = exit_status; } s->reader_pid = -1; } if (s->fd >= 0) { if (!sanei_thread_is_forked ()) sanei_scsi_req_flush_all (); /* flush SCSI queue */ if (s->hw->flags & MUSTEK_FLAG_PRO) { if (s->total_bytes < s->params.lines * s->params.bytes_per_line) status = dev_cmd (s, scsi_start_stop, sizeof (scsi_start_stop), 0, 0); dev_wait_ready (s); } else if ((s->hw->flags & MUSTEK_FLAG_PARAGON_1) || (s->hw->flags & MUSTEK_FLAG_PARAGON_2) || (s->hw->flags & MUSTEK_FLAG_THREE_PASS)) { if (s->cancelled && (s->total_bytes < s->params.lines * s->params.bytes_per_line)) status = dev_cmd (s, scsi_start_stop, sizeof (scsi_start_stop), 0, 0); } else status = dev_cmd (s, scsi_start_stop, sizeof (scsi_start_stop), 0, 0); if (force_wait) { DBG (5, "do_stop: waiting for scanner to be ready\n"); dev_wait_ready (s); } do_eof (s); DBG (5, "do_stop: closing scanner\n"); dev_close (s); s->fd = -1; } DBG (5, "do_stop: finished\n"); return status; } /* Paragon I + II: Determine the CCD's distance between the primary color lines. */ static SANE_Status line_distance (Mustek_Scanner * s) { SANE_Int factor, color, res, peak_res; SANE_Status status; SANE_Byte result[5]; size_t len; memset (result, 0, 5); res = SANE_UNFIX (s->val[OPT_RESOLUTION].w) + 0.5; peak_res = SANE_UNFIX (s->hw->dpi_range.max) + 0.5; s->ld.buf[0] = NULL; len = sizeof (result); status = dev_cmd (s, scsi_ccd_distance, sizeof (scsi_ccd_distance), result, &len); if (status != SANE_STATUS_GOOD) return status; DBG (3, "line_distance: got factor=%d, (r/g/b)=(%d/%d/%d)\n", result[0] | (result[1] << 8), result[2], result[3], result[4]); if (s->hw->flags & MUSTEK_FLAG_LD_FIX) { result[0] = 0xff; result[1] = 0xff; if (s->mode & MUSTEK_MODE_COLOR) { if (s->hw->flags & MUSTEK_FLAG_N) { /* According to Andreas Czechanowski, the line-distance values returned for the AB306N scanners are garbage, so we have to fix things up manually. Not good. This seems to be true only for firmware 2.00 which is extremely seldom.. AB306N scanners with firmware 1.01 don't need this fix. */ if (peak_res == 600) { if (res < 51) { result[0] = 8; result[1] = 0; result[2] = 0; result[3] = 2; result[4] = 3; } else if (res < 75 || (res > 90 && res < 150)) { /* 51-74 and 91-149 dpi: */ result[0] = 4; result[1] = 0; result[2] = 0; result[3] = 3; result[4] = 5; } else if (res <= 90 || (res >= 150 && res <= 300)) { /* 75-90 and 150-300 dpi: */ result[0] = 2; result[1] = 0; result[2] = 0; result[3] = 5; result[4] = 9; } else { /* 301-600 dpi: */ result[0] = 1; result[1] = 0; result[2] = 0; result[3] = 9; result[4] = 23; } } else DBG (1, "don't know how to fix up line-distance for %d dpi\n", peak_res); } else if (!(s->hw->flags & MUSTEK_FLAG_LD_NONE)) { if (peak_res == 600) { if (res < 51) { /* 1-50 dpi: */ result[0] = 4; result[1] = 0; result[2] = 0; result[3] = 3; result[4] = 5; } else if (res <= 300) { /* 51-300 dpi: */ result[0] = 2; result[1] = 0; result[2] = 0; result[3] = 5; result[4] = 9; } else { /*301-600 dpi: */ result[0] = 1; result[1] = 0; result[2] = 0; result[3] = 9; result[4] = 17; } } else if (peak_res == 800) { if (res < 72) { /* 1-71 dpi: */ result[0] = 4; result[1] = 0; result[2] = 0; result[3] = 3; result[4] = 5; } else if (res <= 400) { /* 72-400 dpi: */ result[0] = 2; result[1] = 0; result[2] = 0; result[3] = 9; result[4] = 17; } else { /*401-800 dpi: */ result[0] = 1; result[1] = 0; result[2] = 0; result[3] = 16; result[4] = 32; } } } } DBG (4, "line_distance: fixed up to factor=%d, (r/g/b)=(%d/%d/%d)\n", result[0] | (result[1] << 8), result[2], result[3], result[4]); } factor = result[0] | (result[1] << 8); if (factor != 0xffff) { /* need to do line-distance adjustment ourselves... */ s->ld.max_value = peak_res; if (factor == 0) { if (res <= peak_res / 2) res *= 2; } else res *= factor; s->ld.peak_res = res; for (color = 0; color < 3; ++color) { s->ld.dist[color] = result[2 + color]; s->ld.quant[color] = s->ld.max_value; s->ld.index[color] = -s->ld.dist[color]; } s->ld.lmod3 = -1; DBG (4, "line_distance: max_value = %d, peak_res = %d, ld.quant = " "(%d, %d, %d)\n", s->ld.max_value, s->ld.peak_res, s->ld.quant[0], s->ld.quant[1], s->ld.quant[2]); } else s->ld.max_value = 0; return SANE_STATUS_GOOD; } /* Paragon + Pro series */ static SANE_Status get_image_status (Mustek_Scanner * s, SANE_Int * bpl, SANE_Int * lines) { SANE_Byte result[6]; SANE_Status status; size_t len; SANE_Int busy, offset; long res, half_res; memset (result, 0, 6); /* The 600 II N v1.01 and Paragon 12000SP need a larger scan-area for line-distance correction in color mode */ offset = 0; if ((s->hw->flags & MUSTEK_FLAG_LD_N1) && (s->mode & MUSTEK_MODE_COLOR)) offset = s->ld.dist[1]; else if ((s->hw->flags & MUSTEK_FLAG_LD_BLOCK) && (s->hw->flags & MUSTEK_FLAG_PARAGON_1) && (s->mode & MUSTEK_MODE_COLOR)) offset = MAX_LINE_DIST * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / SANE_UNFIX (s->hw->dpi_range.max); do { len = sizeof (result); status = dev_cmd (s, scsi_get_image_status, sizeof (scsi_get_image_status), result, &len); if (status != SANE_STATUS_GOOD) return status; busy = result[0]; if (busy) usleep (100000); if (!s->scanning) /* ? */ if (!(s->hw->flags & MUSTEK_FLAG_PRO)) return do_stop (s); } while (busy); s->hw->bpl = result[1] | (result[2] << 8); s->hw->lines = result[3] | (result[4] << 8) | (result[5] << 16); res = SANE_UNFIX (s->val[OPT_RESOLUTION].w); half_res = SANE_UNFIX (s->hw->dpi_range.max) / 2; /* Need to interpolate resolutions > max x-resolution? */ if ((s->hw->flags & MUSTEK_FLAG_ENLARGE_X) && (res > half_res)) { *bpl = (s->hw->bpl * res) / half_res / 3; *bpl *= 3; DBG (4, "get_image_status: resolution > x-max; enlarge %d bpl to " "%d bpl\n", s->hw->bpl, *bpl); } else *bpl = s->hw->bpl; *lines = s->hw->lines - offset; DBG (3, "get_image_status: bytes_per_line=%d, lines=%d (offset = %d)\n", *bpl, *lines, offset); return SANE_STATUS_GOOD; } /* ScanExpress models */ static SANE_Status get_window (Mustek_Scanner * s, SANE_Int * bpl, SANE_Int * lines, SANE_Int * pixels) { SANE_Byte result[48]; SANE_Status status; size_t len; SANE_Int color; long res, half_res; res = s->resolution_code; half_res = SANE_UNFIX (s->hw->dpi_range.max) / 2; DBG (5, "get_window: resolution: %ld dpi (hardware: %d dpi)\n", res, s->ld.peak_res); len = sizeof (result); status = dev_cmd (s, scsi_get_window, sizeof (scsi_get_window), result, &len); if (status != SANE_STATUS_GOOD) return status; if (!s->scanning) return do_stop (s); s->hw->cal.bytes = (result[6] << 24) | (result[7] << 16) | (result[8] << 8) | (result[9] << 0); s->hw->cal.lines = (result[10] << 24) | (result[11] << 16) | (result[12] << 8) | (result[13] << 0); DBG (4, "get_window: calibration bpl=%d, lines=%d\n", s->hw->cal.bytes, s->hw->cal.lines); s->hw->bpl = (result[14] << 24) | (result[15] << 16) | (result[16] << 8) | result[17]; s->hw->lines = (result[18] << 24) | (result[19] << 16) | (result[20] << 8) | result[21]; DBG (4, "get_window: scan bpl=%d, lines=%d\n", s->hw->bpl, s->hw->lines); if ((s->hw->cal.bytes == 0) || (s->hw->cal.lines == 0) || (s->hw->bpl == 0) || (s->hw->lines == 0)) { DBG (1, "get_window: oops, none of these values should be 0 " "-- exiting\n"); return SANE_STATUS_INVAL; } s->hw->gamma_length = 1 << result[26]; DBG (4, "get_window: gamma length=%d\n", s->hw->gamma_length); if (s->mode & MUSTEK_MODE_COLOR) { s->ld.buf[0] = NULL; for (color = 0; color < 3; ++color) { s->ld.dist[color] = result[42 + color]; } DBG (4, "get_window: LD res=%d, (r/g/b)=(%d/%d/%d)\n", (result[40] << 8) | result[41], s->ld.dist[0], s->ld.dist[1], s->ld.dist[2]); s->ld.max_value = (result[40] << 8) | result[41]; if ((s->hw->flags & MUSTEK_FLAG_ENLARGE_X) && (res > half_res)) { /* We must interpolate resolutions > max x-resolution */ *bpl = *pixels = (((s->hw->bpl / 3) * res) / half_res) * 3; } else { /* Scale down the image according to desired resolution */ *bpl = *pixels = (((s->hw->bpl / 3) * res) / s->ld.peak_res) * 3; } *lines = (s->hw->lines - s->ld.dist[2]) * res / s->ld.peak_res; } else { if ((s->hw->flags & MUSTEK_FLAG_ENLARGE_X) && (res > half_res)) { /* We must interpolate resolutions > max x-resolution */ *bpl = s->hw->bpl * res / half_res; } else { *bpl = s->hw->bpl; } *lines = s->hw->lines; } DBG (4, "get_window: bpl = %d (hardware: %d), lines = %d (hardware: %d)\n", *bpl, s->hw->bpl, *lines, s->hw->lines); return SANE_STATUS_GOOD; } static SANE_Status adf_and_backtrack (Mustek_Scanner * s) { SANE_Byte backtrack[6]; SANE_Int code = 0x80; if (!(s->hw->flags & MUSTEK_FLAG_NO_BACKTRACK)) code |= 0x02; /* enable backtracking */ if (strcmp (s->val[OPT_SOURCE].s, "Automatic Document Feeder") == 0) code |= 0x01; else if (strcmp (s->val[OPT_SOURCE].s, "Transparency Adapter") == 0) code |= 0x04; memset (backtrack, 0, sizeof (backtrack)); backtrack[0] = MUSTEK_SCSI_ADF_AND_BACKTRACK; backtrack[4] = code; DBG (4, "adf_and_backtrack: backtrack: %s; ADF: %s; TA: %s\n", code & 0x02 ? "yes" : "no", code & 0x01 ? "yes" : "no", code & 0x04 ? "yes" : "no"); return dev_cmd (s, backtrack, sizeof (backtrack), 0, 0); } /* 600 II N firmware 2.x */ static SANE_Int fix_line_distance_n_2 (Mustek_Scanner * s, SANE_Int num_lines, SANE_Int bpl, SANE_Byte * raw, SANE_Byte * out) { SANE_Byte *out_end, *out_ptr, *raw_end = raw + num_lines * bpl; SANE_Int c, num_saved_lines, line; if (!s->ld.buf[0]) { /* This buffer must be big enough to hold maximum line distance times max_bpl bytes. The maximum line distance for the Paragon 600 II N scanner is 23, so 40 should be safe. */ DBG (5, "fix_line_distance_n_2: allocating temp buffer of %d*%d bytes\n", MAX_LINE_DIST, bpl); s->ld.buf[0] = malloc (MAX_LINE_DIST * (long) bpl); if (!s->ld.buf[0]) { DBG (1, "fix_line_distance_n_2: failed to malloc temporary buffer\n"); return 0; } } num_saved_lines = s->ld.index[0] - s->ld.index[2]; if (num_saved_lines > 0) /* restore the previously saved lines: */ memcpy (out, s->ld.buf[0], num_saved_lines * bpl); while (1) { if (++s->ld.lmod3 >= 3) s->ld.lmod3 = 0; c = color_seq[s->ld.lmod3]; if (s->ld.index[c] < 0) ++s->ld.index[c]; else if (s->ld.index[c] < s->params.lines) { s->ld.quant[c] += s->ld.peak_res; if (s->ld.quant[c] > s->ld.max_value) { s->ld.quant[c] -= s->ld.max_value; line = s->ld.index[c]++ - s->ld.ld_line; out_ptr = out + line * bpl + c; out_end = out_ptr + bpl; while (out_ptr != out_end) { *out_ptr = *raw++; out_ptr += 3; } if (raw >= raw_end) { DBG (3, "fix_line_distance_n_2: lmod3=%d, " "index=(%d,%d,%d)\n", s->ld.lmod3, s->ld.index[0], s->ld.index[1], s->ld.index[2]); num_lines = s->ld.index[2] - s->ld.ld_line; /* copy away the lines with at least one missing color component, so that we can interleave them with new scan data on the next call */ num_saved_lines = s->ld.index[0] - s->ld.index[2]; memcpy (s->ld.buf[0], out + num_lines * bpl, num_saved_lines * bpl); /* notice the number of lines we processed */ s->ld.ld_line = s->ld.index[2]; /* return number of complete (r+g+b) lines */ return num_lines; } } } } } /* 600 II N firmware 1.x */ static SANE_Int fix_line_distance_n_1 (Mustek_Scanner * s, SANE_Int num_lines, SANE_Int bpl, SANE_Byte * raw, SANE_Byte * out) { SANE_Byte *out_end, *out_ptr, *raw_end = raw + num_lines * bpl; SANE_Int c, num_saved_lines, line; /* For firmware 1.x the scanarea must be soemwhat bigger than needed because of the linedistance correction */ if (!s->ld.buf[0]) { /* This buffer must be big enough to hold maximum line distance times max_bpl bytes. The maximum line distance for the 600 II N is 23, so 40 is safe. */ DBG (5, "fix_line_distance_n_1: allocating temp buffer of %d*%d bytes\n", MAX_LINE_DIST, bpl); s->ld.buf[0] = malloc (MAX_LINE_DIST * (long) bpl); if (!s->ld.buf[0]) { DBG (1, "fix_line_distance_n_1: failed to malloc temporary buffer\n"); return 0; } } num_saved_lines = s->ld.index[0] - s->ld.index[1]; DBG (5, "fix_line_distance_n_1: got %d lines, %d bpl\n", num_lines, bpl); DBG (5, "fix_line_distance_n_1: num_saved_lines = %d; peak_res = %d; " "max_value = %d\n", num_saved_lines, s->ld.peak_res, s->ld.max_value); if (num_saved_lines > 0) /* restore the previously saved lines: */ memcpy (out, s->ld.buf[0], num_saved_lines * bpl); while (1) { if (++s->ld.lmod3 >= 3) s->ld.lmod3 = 0; c = s->ld.lmod3; if (s->ld.index[c] < 0) ++s->ld.index[c]; else { s->ld.quant[c] += s->ld.peak_res; if (s->ld.quant[c] > s->ld.max_value) { s->ld.quant[c] -= s->ld.max_value; line = s->ld.index[c]++ - s->ld.ld_line; out_ptr = out + line * bpl + c; out_end = out_ptr + bpl; while (out_ptr != out_end) { *out_ptr = *raw++; out_ptr += 3; } DBG (5, "fix_line_distance_n_1: copied line %d (color %d)\n", line, c); } } if ((raw >= raw_end) || ((s->ld.index[0] >= s->params.lines) && (s->ld.index[1] >= s->params.lines) && (s->ld.index[2] >= s->params.lines))) { DBG (3, "fix_line_distance_n_1: lmod3=%d, index=(%d,%d,%d)%s\n", s->ld.lmod3, s->ld.index[0], s->ld.index[1], s->ld.index[2], raw >= raw_end ? " raw >= raw_end" : ""); num_lines = s->ld.index[1] - s->ld.ld_line; if (num_lines < 0) num_lines = 0; DBG (4, "fix_line_distance_n_1: lines ready: %d\n", num_lines); /* copy away the lines with at least one missing color component, so that we can interleave them with new scan data on the next call */ num_saved_lines = s->ld.index[0] - s->ld.index[1]; DBG (4, "fix_line_distance_n_1: copied %d lines to " "ld.buf\n", num_saved_lines); memcpy (s->ld.buf[0], out + num_lines * bpl, num_saved_lines * bpl); /* notice the number of lines we processed */ s->ld.ld_line = s->ld.index[1]; if (s->ld.ld_line < 0) s->ld.ld_line = 0; /* return number of complete (r+g+b) lines */ return num_lines; } } } /* For ScanExpress models */ static SANE_Int fix_line_distance_se (Mustek_Scanner * s, SANE_Int num_lines, SANE_Int bpl, SANE_Byte * raw, SANE_Byte * out) { SANE_Byte *raw_end = raw + num_lines * bpl; SANE_Byte *out_ptr[3], *ptr; SANE_Int index[3], lines[3], quant[3], dist[3]; SANE_Int max_value; SANE_Int color, pixel, res, half_res, scale; SANE_Int bpc = bpl / 3; /* bytes per color (per line) */ SANE_Bool preview = SANE_FALSE; res = s->resolution_code; half_res = SANE_UNFIX (s->hw->dpi_range.max) / 2; max_value = s->ld.max_value; if ((s->val[OPT_PREVIEW].w == SANE_TRUE) && (s->val[OPT_FAST_PREVIEW].w == SANE_TRUE)) { preview = SANE_TRUE; /*max_value = 75; */ dist[0] = s->ld.dist[0]; dist[1] = s->ld.dist[1]; dist[2] = s->ld.dist[2]; } else { dist[0] = s->ld.dist[0]; dist[1] = s->ld.dist[1]; dist[2] = s->ld.dist[2]; } if (!s->ld.buf[0]) { /* This buffer must be big enough to hold maximum line distance times 3*bpl bytes. The maximum line distance for 1200 dpi is 32 */ DBG (5, "fix_line_distance_se: allocating temp buffer of %d*%d bytes\n", 3 * MAX_LINE_DIST, bpc); s->ld.buf[0] = malloc (3 * MAX_LINE_DIST * (long) bpc); if (!s->ld.buf[0]) { DBG (1, "fix_line_distance_se: failed to malloc temporary buffer\n"); return 0; } /* Note that either s->ld.buf[1] or s->ld.buf[2] is never used. */ s->ld.buf[1] = s->ld.buf[2] = s->ld.buf[0] + 2 * MAX_LINE_DIST * (long) bpc; /* Since the blocks don't start necessarily with red note color. */ s->ld.color = 0; /* The scan area must be longer than desired because of the line distance. So me must count complete (r+g+b) lines already submitted to the fronted. */ s->ld.ld_line = s->params.lines; for (color = 0; color < 3; ++color) { s->ld.index[color] = -dist[color]; s->ld.quant[color] = 0; s->ld.saved[color] = 0; } } num_lines *= 3; DBG (5, "fix_line_distance_se: start color: %d; %d lines \n", s->ld.color, num_lines); /* First scan the lines read and count red, green and blue ones. Since we will step through the lines a second time we must not alter any global variables here! */ for (color = 0; color < 3; ++color) { index[color] = s->ld.index[color]; lines[color] = s->ld.saved[color]; quant[color] = s->ld.quant[color]; } color = s->ld.color; while (num_lines > 0) { if (index[color] < 0) ++index[color]; else { quant[color] += res; if (quant[color] >= max_value) { /* This line must be processed, not dropped. */ quant[color] -= max_value; ++lines[color]; --num_lines; } else if (!preview) --num_lines; } if (++color > 2) color = 0; } /* Calculate how many triples of color lines we can output now. Because the number of available red lines is always greater than for the other colors we may ignore the red ones here. */ num_lines = MIN (lines[1], lines[2]); DBG (5, "fix_line_distance_se: saved lines: %d/%d/%d\n", s->ld.saved[0], s->ld.saved[1], s->ld.saved[2]); DBG (5, "fix_line_distance_se: available: %d/%d/%d --> triples: %d\n", lines[0], lines[1], lines[2], num_lines); lines[0] = lines[1] = lines[2] = num_lines; /* Output the color lines saved in previous call first. Note that data is converted in r/g/b interleave on the fly. */ for (color = 0; color < 3; ++color) { out_ptr[color] = out + color; ptr = s->ld.buf[color]; while ((s->ld.saved[color] > 0) && (lines[color] > 0)) { scale = 0; if ((s->hw->flags & MUSTEK_FLAG_ENLARGE_X) && (res > half_res)) { /* Need to enlarge x-resolution */ SANE_Byte *ptr_start = ptr; for (pixel = 0; pixel < s->params.pixels_per_line; ++pixel) { *out_ptr[color] = *ptr; out_ptr[color] += 3; scale += half_res; if (scale >= half_res) { scale -= res; ++ptr; } } DBG (5, "fix_line_distance_se: got saved line: %d; line: %d; " "color: %d; raw bytes: %lu; out bytes: %d\n", s->ld.saved[color], lines[color], color, (u_long) (ptr - ptr_start), s->params.pixels_per_line); ptr = ptr_start + bpc; } else { if (preview) { for (pixel = 0; pixel < bpc; ++pixel) { *out_ptr[color] = *ptr++; out_ptr[color] += 3; } } else { for (pixel = 0; pixel < bpc; ++pixel) { scale += res; if (scale >= max_value) { scale -= max_value; *out_ptr[color] = *ptr; out_ptr[color] += 3; } ++ptr; } } DBG (5, "fix_line_distance_se: got saved line: %d; line: %d; " "color: %d\n", s->ld.saved[color], lines[color], color); } --(s->ld.saved[color]); --lines[color]; } if (s->ld.saved[color] > 0) memmove (s->ld.buf[color], ptr, s->ld.saved[color] * bpc); } while (1) { if (s->ld.index[s->ld.color] < 0) ++(s->ld.index[s->ld.color]); else { s->ld.quant[s->ld.color] += res; if (s->ld.quant[s->ld.color] >= max_value) { /* This line must be processed, not dropped. */ s->ld.quant[s->ld.color] -= max_value; if (lines[s->ld.color] > 0) { /* There's still a line to be output for current color. Then shuffle current color line to output buffer. */ scale = 0; /* need to enlarge x-resolution? */ if ((s->hw->flags & MUSTEK_FLAG_ENLARGE_X) && (res > half_res)) { SANE_Byte *raw_start = raw; for (pixel = 0; pixel < s->params.pixels_per_line; ++pixel) { *out_ptr[s->ld.color] = *raw; out_ptr[s->ld.color] += 3; scale += half_res; if (scale >= half_res) { scale -= res; ++raw; } } DBG (5, "fix_line_distance_se: got line: %d; color: %d; " "raw bytes: %lu; out bytes: %d\n", lines[s->ld.color], s->ld.color, (u_long) (raw - raw_start), s->params.pixels_per_line); raw = raw_start + bpc; } else { if (preview) { for (pixel = 0; pixel < bpc; ++pixel) { *out_ptr[s->ld.color] = *raw++; out_ptr[s->ld.color] += 3; } } else { for (pixel = 0; pixel < bpc; ++pixel) { scale += res; if (scale >= max_value) { scale -= max_value; *out_ptr[s->ld.color] = *raw; out_ptr[s->ld.color] += 3; } ++raw; } } DBG (5, "fix_line_distance_se: got line: %d; color: " "%d\n", lines[s->ld.color], s->ld.color); } --lines[s->ld.color]; } else { /* At least one component missing, so save this line. */ memcpy (s->ld.buf[s->ld.color] + s->ld.saved[s->ld.color] * bpc, raw, bpc); DBG (5, "fix_line_distance_se: saved line %d; color %d\n", s->ld.saved[s->ld.color], s->ld.color); ++(s->ld.saved[s->ld.color]); raw += bpc; } } else { if (!preview) raw += bpc; DBG (5, "fix_line_distance_se: ignored line; color: %d\n", s->ld.color); } if (raw >= raw_end) { /* Reduce num_lines if we encounter excess lines. */ if (num_lines > s->ld.ld_line) num_lines = s->ld.ld_line; s->ld.ld_line -= num_lines; if (++s->ld.color > 2) s->ld.color = 0; return num_lines; } } if (++s->ld.color > 2) s->ld.color = 0; } } /* For Pro models. Not really a linedistance correction (they don't need one) only enlarging x-res here */ static void fix_line_distance_pro (Mustek_Scanner * s, SANE_Int num_lines, SANE_Int bpl, SANE_Byte * raw, SANE_Byte * out) { SANE_Byte *out_addr, *in_addr; SANE_Int res, half_res, y, x_out, x_in; res = SANE_UNFIX (s->val[OPT_RESOLUTION].w); half_res = SANE_UNFIX (s->hw->dpi_range.max) / 2; DBG (5, "fix_line_distance_pro: res=%d; halfres=%d; num_lines=%d; bpl=%d\n", res, half_res, num_lines, bpl); if (strcmp (s->val[OPT_BIT_DEPTH].s, "12") == 0) { if ((s->hw->flags & MUSTEK_FLAG_ENLARGE_X) && (res > half_res)) { /*12 bit, need to enlarge x-resolution */ DBG (5, "fix_line_distance_pro: res > half_res --> need to " "enlarge x\n"); if (little_endian ()) for (y = 0; y < num_lines; y++) { for (x_out = 0; x_out < s->params.pixels_per_line; x_out++) { x_in = x_out * bpl / s->params.bytes_per_line / 2; x_in *= 2; out_addr = out + y * s->params.bytes_per_line + x_out * 6; in_addr = raw + y * bpl + x_in * 6; *(out_addr) = *(in_addr) << 4; *(out_addr + 1) = (*(in_addr) >> 4) + (*(in_addr + 1) << 4); *(out_addr + 2) = *(in_addr + 2) << 4; *(out_addr + 3) = (*(in_addr + 2) >> 4) + (*(in_addr + 3) << 4); *(out_addr + 4) = *(in_addr + 4) << 4; *(out_addr + 5) = (*(in_addr + 4) >> 4) + (*(in_addr + 5) << 4); } } else /* big endian */ for (y = 0; y < num_lines; y++) { for (x_out = 0; x_out < s->params.pixels_per_line; x_out++) { x_in = x_out * bpl / s->params.bytes_per_line / 2; out_addr = out + y * s->params.bytes_per_line + x_out * 6; in_addr = raw + y * bpl + x_in * 6; *(out_addr) = (*(in_addr) >> 4) + (*(in_addr + 1) << 4); *(out_addr + 1) = *(in_addr) << 4; *(out_addr + 2) = (*(in_addr + 2) >> 4) + (*(in_addr + 3) << 4); *(out_addr + 3) = *(in_addr + 2) << 4; *(out_addr + 4) = (*(in_addr + 4) >> 4) + (*(in_addr + 5) << 4); *(out_addr + 5) = *(in_addr + 4) << 4; } } } else /* 12 bit, no need to enlarge x */ { SANE_Word pixel; if (little_endian ()) for (pixel = 0; pixel < (num_lines * bpl / 2); pixel++) { *(out + pixel * 2) = *(raw + pixel * 2) << 4; *(out + pixel * 2 + 1) = (*(raw + pixel * 2) >> 4) + (*(raw + pixel * 2 + 1) << 4); } else /* big endian */ for (pixel = 0; pixel < (num_lines * bpl / 2); pixel++) { *(out + pixel * 2) = (*(raw + pixel * 2) >> 4) + (*(raw + pixel * 2 + 1) << 4); *(out + pixel * 2 + 1) = *(raw + pixel * 2) << 4; } } } else /* 8 bit */ { /* need to enlarge x-resolution? */ if ((s->hw->flags & MUSTEK_FLAG_ENLARGE_X) && (res > half_res)) { DBG (5, "fix_line_distance_pro: res > half_res --> need to " "enlarge x\n"); for (y = 0; y < num_lines; y++) { for (x_out = 0; x_out < s->params.pixels_per_line; x_out++) { x_in = x_out * bpl / s->params.bytes_per_line; out_addr = out + y * s->params.bytes_per_line + x_out * 3; in_addr = raw + y * bpl + x_in * 3; *(out_addr) = *(in_addr); *(out_addr + 1) = *(in_addr + 1); *(out_addr + 2) = *(in_addr + 2); } } } else memcpy (out, raw, num_lines * bpl); } return; } /* For MFS-08000SP, MFS-06000SP. MFC-08000CZ, MFC-06000CZ */ static void fix_line_distance_normal (Mustek_Scanner * s, SANE_Int num_lines, SANE_Int bpl, SANE_Byte * raw, SANE_Byte * out) { SANE_Byte *out_end, *out_ptr, *raw_end = raw + num_lines * bpl; SANE_Int index[3]; /* index of the next output line for color C */ SANE_Int i, color; /* Initialize the indices with the line distances that were returned by the CCD linedistance command or set manually (option linedistance-fix). We want to skip data for the first OFFSET rounds, so we initialize the indices to the negative of this offset. */ DBG (5, "fix_line_distance_normal: %d lines, %d bpl\n", num_lines, bpl); for (color = 0; color < 3; ++color) index[color] = -s->ld.dist[color]; while (1) { for (i = 0; i < 3; ++i) { color = color_seq[i]; if (index[color] < 0) ++index[color]; else if (index[color] < num_lines) { s->ld.quant[color] += s->ld.peak_res; if (s->ld.quant[color] > s->ld.max_value) { s->ld.quant[color] -= s->ld.max_value; out_ptr = out + index[color] * bpl + color; out_end = out_ptr + bpl; while (out_ptr != out_end) { *out_ptr = *raw++; out_ptr += 3; } ++index[color]; if (raw >= raw_end) return; } } } } } /* Paragon series I + II. */ static SANE_Int fix_line_distance_block (Mustek_Scanner * s, SANE_Int num_lines, SANE_Int bpl, SANE_Byte * raw, SANE_Byte * out, SANE_Int num_lines_total) { SANE_Byte *out_end, *out_ptr, *raw_end = raw + num_lines * bpl; SANE_Int c, num_saved_lines, line, max_index, min_index; if (!s->ld.buf[0]) { DBG (5, "fix_line_distance_block: allocating temp buffer of %d*%d " "bytes\n", MAX_LINE_DIST, bpl); s->ld.buf[0] = malloc (MAX_LINE_DIST * (long) bpl); if (!s->ld.buf[0]) { DBG (1, "fix_line_distance_block: failed to malloc temporary " "buffer\n"); return 0; } } DBG (5, "fix_line_distance_block: s->ld.index = {%d, %d, %d}, " "s->ld.lmod3 = %d\n", s->ld.index[0], s->ld.index[1], s->ld.index[2], s->ld.lmod3); DBG (5, "fix_line_distance_block: s->ld.quant = {%d, %d, %d}, " "s->ld.max_value = %d\n", s->ld.quant[0], s->ld.quant[1], s->ld.quant[2], s->ld.max_value); DBG (5, "fix_line_distance_block: s->ld.peak_res = %d, s->ld.ld_line = %d\n", s->ld.peak_res, s->ld.ld_line); /* search maximum and minimum index */ max_index = MAX (s->ld.index[0], MAX (s->ld.index[1], s->ld.index[2])); min_index = MIN (s->ld.index[0], MIN (s->ld.index[1], s->ld.index[2])); num_saved_lines = max_index - min_index; if (s->ld.index[0] == 0) num_saved_lines = 0; /* restore the previously saved lines: */ memcpy (out, s->ld.buf[0], num_saved_lines * bpl); DBG (5, "fix_line_distance_block: copied %d lines from " "ld.buf to buffer (max=%d, min=%d)\n", num_saved_lines, max_index, min_index); while (1) { if (++s->ld.lmod3 >= 3) s->ld.lmod3 = 0; c = color_seq[s->ld.lmod3]; if (s->ld.index[c] < 0) ++s->ld.index[c]; else if (s->ld.index[c] < num_lines_total) { s->ld.quant[c] += s->ld.peak_res; if (s->ld.quant[c] > s->ld.max_value) { s->ld.quant[c] -= s->ld.max_value; line = s->ld.index[c]++ - s->ld.ld_line; out_ptr = out + line * bpl + c; out_end = out_ptr + bpl; while (out_ptr != out_end) { *out_ptr = *raw++; out_ptr += 3; } DBG (5, "fix_line_distance_block: copied line %d (color %d)\n", line + s->ld.ld_line, c); max_index = MAX (s->ld.index[0], MAX (s->ld.index[1], s->ld.index[2])); min_index = MIN (s->ld.index[0], MIN (s->ld.index[1], s->ld.index[2])); if ((raw >= raw_end) || ((min_index >= num_lines_total))) { DBG (5, "fix_line_distance_block: got num_lines: %d\n", num_lines); num_lines = min_index - s->ld.ld_line; if (num_lines < 0) num_lines = 0; if ((s->total_lines + num_lines) > s->params.lines) num_lines = s->params.lines - s->total_lines; s->total_lines += num_lines; /* copy away the lines with at least one missing color component, so that we can interleave them with new scan data on the next call */ num_saved_lines = max_index - min_index; DBG (5, "fix_line_distance_block: num_saved_lines = %d; " "num_lines = %d; bpl = %d\n", num_saved_lines, num_lines, bpl); memcpy (s->ld.buf[0], out + num_lines * bpl, num_saved_lines * bpl); DBG (5, "fix_line_distance_block: copied %d lines to " "ld.buf\n", num_saved_lines); /* notice the number of lines we processed */ s->ld.ld_line = min_index; if (s->ld.ld_line < 0) s->ld.ld_line = 0; DBG (4, "fix_line_distance_block: lmod3=%d, " "index=(%d,%d,%d), line = %d, lines = %d\n", s->ld.lmod3, s->ld.index[0], s->ld.index[1], s->ld.index[2], s->ld.ld_line, num_lines); /* return number of complete (r+g+b) lines */ return num_lines; } } } } } /* For MFS-1200SP 1.00 and others */ /* No LD correction necessary, just shuffle around data */ static SANE_Int fix_line_distance_none (Mustek_Scanner * s, SANE_Int num_lines, SANE_Int bpl, SANE_Byte * raw, SANE_Byte * out) { SANE_Byte *red_ptr, *grn_ptr, *blu_ptr, *ptr, *ptr_end; SANE_Word y; ptr = out; red_ptr = raw; DBG (5, "fix_line_distance_none: no ld correction necessary (%d lines)\n", num_lines); s->ld.ld_line += num_lines; if (s->ld.ld_line > s->params.lines) num_lines -= (s->ld.ld_line - s->params.lines); if (num_lines < 0) num_lines = 0; DBG (5, "fix_line_distance_none: using %d lines (ld_line = %d, " "s->params.lines = %d)\n", num_lines, s->ld.ld_line, s->params.lines); for (y = 0; y < num_lines; ++y) { grn_ptr = red_ptr + bpl / 3; blu_ptr = grn_ptr + bpl / 3; ptr_end = red_ptr + bpl; while (blu_ptr != ptr_end) { *ptr++ = *red_ptr++; *ptr++ = *grn_ptr++; *ptr++ = *blu_ptr++; } red_ptr = ptr_end; } return num_lines; } static SANE_Status init_options (Mustek_Scanner * s) { SANE_Int i, j, gammasize; memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = ""; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; if (s->hw->flags & MUSTEK_FLAG_SE) { s->opt[OPT_MODE].size = max_string_size (mode_list_se); s->opt[OPT_MODE].constraint.string_list = mode_list_se; s->val[OPT_MODE].s = strdup (mode_list_se[1]); if (!s->val[OPT_MODE].s) return SANE_STATUS_NO_MEM; } else { s->opt[OPT_MODE].size = max_string_size (mode_list_paragon); s->opt[OPT_MODE].constraint.string_list = mode_list_paragon; s->val[OPT_MODE].s = strdup (mode_list_paragon[2]); if (!s->val[OPT_MODE].s) return SANE_STATUS_NO_MEM; } /* fast gray mode (pro models) */ s->opt[OPT_FAST_GRAY_MODE].name = "fast-gray-mode"; s->opt[OPT_FAST_GRAY_MODE].title = SANE_I18N ("Fast gray mode"); s->opt[OPT_FAST_GRAY_MODE].desc = SANE_I18N ("Scan in fast gray mode " "(lower quality)."); s->opt[OPT_FAST_GRAY_MODE].type = SANE_TYPE_BOOL; s->val[OPT_FAST_GRAY_MODE].w = SANE_FALSE; s->opt[OPT_FAST_GRAY_MODE].cap |= SANE_CAP_INACTIVE; if (s->hw->flags & MUSTEK_FLAG_PRO) { /* Only Pro models support fast gray mode */ s->opt[OPT_FAST_GRAY_MODE].cap &= ~SANE_CAP_INACTIVE; } /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = MAX (SANE_FIX (72), s->hw->dpi_range.min); /* bit depth */ s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_BIT_DEPTH].type = SANE_TYPE_STRING; s->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BIT_DEPTH].size = max_string_size (bit_depth_list_pro); s->opt[OPT_BIT_DEPTH].constraint.string_list = bit_depth_list_pro; s->val[OPT_BIT_DEPTH].s = strdup (bit_depth_list_pro[0]); if (!s->val[OPT_BIT_DEPTH].s) return SANE_STATUS_NO_MEM; /* speed */ s->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; s->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; s->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; s->opt[OPT_SPEED].type = SANE_TYPE_STRING; s->opt[OPT_SPEED].size = max_string_size (speed_list); s->opt[OPT_SPEED].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SPEED].constraint.string_list = speed_list; s->val[OPT_SPEED].s = strdup (speed_list[4]); if (!s->val[OPT_SPEED].s) return SANE_STATUS_NO_MEM; if (!(s->hw->flags & MUSTEK_FLAG_THREE_PASS)) { /* Speed only supported by 3-pass scanners */ s->opt[OPT_SPEED].cap |= SANE_CAP_INACTIVE; } /* source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; if ((s->hw->flags & MUSTEK_FLAG_SE) || (s->hw->flags & MUSTEK_FLAG_N) || (s->hw->flags & MUSTEK_FLAG_TA)) { s->opt[OPT_SOURCE].size = max_string_size (ta_source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = ta_source_list; s->val[OPT_SOURCE].s = strdup (ta_source_list[0]); if (!s->val[OPT_SOURCE].s) return SANE_STATUS_NO_MEM; } else if (s->hw->flags & MUSTEK_FLAG_ADF) { s->opt[OPT_SOURCE].size = max_string_size (adf_source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = adf_source_list; s->val[OPT_SOURCE].s = strdup (adf_source_list[0]); if (!s->val[OPT_SOURCE].s) return SANE_STATUS_NO_MEM; } else { s->opt[OPT_SOURCE].size = max_string_size (source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].s = strdup (source_list[0]); s->opt[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; if (!s->val[OPT_SOURCE].s) return SANE_STATUS_NO_MEM; } /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = 0; /* fast preview */ s->opt[OPT_FAST_PREVIEW].name = "fast-preview"; s->opt[OPT_FAST_PREVIEW].title = SANE_I18N ("Fast preview"); s->opt[OPT_FAST_PREVIEW].desc = SANE_I18N ("Request that all previews are " "done in the fastest (low-quality) mode. This may be a non-color " "mode or a low resolution mode."); s->opt[OPT_FAST_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_FAST_PREVIEW].w = SANE_FALSE; /* lamp off time*/ s->opt[OPT_LAMP_OFF_TIME].name = "lamp-off-time"; s->opt[OPT_LAMP_OFF_TIME].title = SANE_I18N ("Lamp off time (minutes)"); s->opt[OPT_LAMP_OFF_TIME].desc = SANE_I18N ("Set the time (in minutes) after " "which the lamp is shut off."); s->opt[OPT_LAMP_OFF_TIME].type = SANE_TYPE_INT; if (strcmp (s->hw->sane.model, "1200 A3 PRO") != 0) s->opt[OPT_LAMP_OFF_TIME].cap |= SANE_CAP_INACTIVE; s->opt[OPT_LAMP_OFF_TIME].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_LAMP_OFF_TIME].constraint.range = &u8_range; s->val[OPT_LAMP_OFF_TIME].w = 60; /* shut lamp off */ s->opt[OPT_LAMP_OFF_BUTTON].name = "lamp-off"; s->opt[OPT_LAMP_OFF_BUTTON].title = SANE_I18N ("Turn lamp off"); s->opt[OPT_LAMP_OFF_BUTTON].desc = SANE_I18N ("Turns the lamp off immediately."); s->opt[OPT_LAMP_OFF_BUTTON].type = SANE_TYPE_BUTTON; s->opt[OPT_LAMP_OFF_BUTTON].cap = SANE_CAP_SOFT_SELECT; if (strcmp (s->hw->sane.model, "1200 A3 PRO") != 0) s->opt[OPT_LAMP_OFF_BUTTON].cap |= SANE_CAP_INACTIVE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = s->hw->x_range.min; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = s->hw->y_range.min; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; if (!s->hw->flags & MUSTEK_FLAG_THREE_PASS) /* 1-pass scanners don't support brightness in multibit mode */ s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->val[OPT_BRIGHTNESS].w = 0; /* brightness red */ s->opt[OPT_BRIGHTNESS_R].name = "brightness-r"; s->opt[OPT_BRIGHTNESS_R].title = SANE_I18N ("Red brightness"); s->opt[OPT_BRIGHTNESS_R].desc = SANE_I18N ("Controls the brightness of " "the red channel of the " "acquired image."); s->opt[OPT_BRIGHTNESS_R].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS_R].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS_R].constraint.range = &percentage_range; s->opt[OPT_BRIGHTNESS_R].cap |= SANE_CAP_INACTIVE; s->val[OPT_BRIGHTNESS_R].w = 0; /* brightness green */ s->opt[OPT_BRIGHTNESS_G].name = "brightness-g"; s->opt[OPT_BRIGHTNESS_G].title = SANE_I18N ("Green brightness"); s->opt[OPT_BRIGHTNESS_G].desc = SANE_I18N ("Controls the brightness of " "the green channel of the " "acquired image."); s->opt[OPT_BRIGHTNESS_G].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS_G].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS_G].constraint.range = &percentage_range; s->opt[OPT_BRIGHTNESS_G].cap |= SANE_CAP_INACTIVE; s->val[OPT_BRIGHTNESS_G].w = 0; /* brightness blue */ s->opt[OPT_BRIGHTNESS_B].name = "brightness-b"; s->opt[OPT_BRIGHTNESS_B].title = SANE_I18N ("Blue brightness"); s->opt[OPT_BRIGHTNESS_B].desc = SANE_I18N ("Controls the brightness of " "the blue channel of the " "acquired image."); s->opt[OPT_BRIGHTNESS_B].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS_B].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS_B].constraint.range = &percentage_range; s->opt[OPT_BRIGHTNESS_B].cap |= SANE_CAP_INACTIVE; s->val[OPT_BRIGHTNESS_B].w = 0; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; if (!(s->hw->flags & MUSTEK_FLAG_THREE_PASS)) /* 1-pass scanners don't support contrast in multibit mode */ s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->val[OPT_CONTRAST].w = 0; /* contrast red */ s->opt[OPT_CONTRAST_R].name = "contrast-r"; s->opt[OPT_CONTRAST_R].title = SANE_I18N ("Contrast red channel"); s->opt[OPT_CONTRAST_R].desc = SANE_I18N ("Controls the contrast of " "the red channel of the " "acquired image."); s->opt[OPT_CONTRAST_R].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST_R].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST_R].constraint.range = &percentage_range; s->opt[OPT_CONTRAST_R].cap |= SANE_CAP_INACTIVE; s->val[OPT_CONTRAST_R].w = 0; /* contrast green */ s->opt[OPT_CONTRAST_G].name = "contrast-g"; s->opt[OPT_CONTRAST_G].title = SANE_I18N ("Contrast green channel"); s->opt[OPT_CONTRAST_G].desc = SANE_I18N ("Controls the contrast of " "the green channel of the " "acquired image."); s->opt[OPT_CONTRAST_G].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST_G].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST_G].constraint.range = &percentage_range; s->opt[OPT_CONTRAST_G].cap |= SANE_CAP_INACTIVE; s->val[OPT_CONTRAST_G].w = 0; /* contrast blue */ s->opt[OPT_CONTRAST_B].name = "contrast-b"; s->opt[OPT_CONTRAST_B].title = SANE_I18N ("Contrast blue channel"); s->opt[OPT_CONTRAST_B].desc = SANE_I18N ("Controls the contrast of " "the blue channel of the " "acquired image."); s->opt[OPT_CONTRAST_B].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST_B].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST_B].constraint.range = &percentage_range; s->opt[OPT_CONTRAST_B].cap |= SANE_CAP_INACTIVE; s->val[OPT_CONTRAST_B].w = 0; /* gamma */ gammasize = 256; for (i = 0; i < 4; ++i) for (j = 0; j < gammasize; ++j) s->gamma_table[i][j] = j; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0]; s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0]; s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0]; s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; /* quality calibration */ s->opt[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL; s->opt[OPT_QUALITY_CAL].title = SANE_TITLE_QUALITY_CAL; s->opt[OPT_QUALITY_CAL].desc = SANE_DESC_QUALITY_CAL; s->opt[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL; if (s->hw->flags & MUSTEK_FLAG_PRO) s->val[OPT_QUALITY_CAL].w = SANE_TRUE; else s->val[OPT_QUALITY_CAL].w = SANE_FALSE; s->opt[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE; if ((s->hw->flags & MUSTEK_FLAG_PRO) || (s->hw->flags & MUSTEK_FLAG_SE_PLUS)) { /* Only Pro and SE Plus models support calibration */ s->opt[OPT_QUALITY_CAL].cap &= ~SANE_CAP_INACTIVE; } /* halftone dimension */ s->opt[OPT_HALFTONE_DIMENSION].name = SANE_NAME_HALFTONE_DIMENSION; s->opt[OPT_HALFTONE_DIMENSION].title = SANE_TITLE_HALFTONE_DIMENSION; s->opt[OPT_HALFTONE_DIMENSION].desc = SANE_DESC_HALFTONE_DIMENSION; s->opt[OPT_HALFTONE_DIMENSION].type = SANE_TYPE_STRING; s->opt[OPT_HALFTONE_DIMENSION].size = max_string_size (halftone_list); s->opt[OPT_HALFTONE_DIMENSION].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_HALFTONE_DIMENSION].constraint.string_list = halftone_list; s->val[OPT_HALFTONE_DIMENSION].s = strdup (halftone_list[0]); if (!s->val[OPT_HALFTONE_DIMENSION].s) return SANE_STATUS_NO_MEM; s->opt[OPT_HALFTONE_DIMENSION].cap |= SANE_CAP_INACTIVE; /* halftone pattern */ s->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; s->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_INT; s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_HALFTONE_PATTERN].constraint.range = &u8_range; s->val[OPT_HALFTONE_PATTERN].wa = s->halftone_pattern; return SANE_STATUS_GOOD; } /* The following three functions execute as a child process. The reason for using a subprocess is that some (most?) generic SCSI interfaces block a SCSI request until it has completed. With a subprocess, we can let it block waiting for the request to finish while the main process can go about to do more important things (such as recognizing when the user presses a cancel button). WARNING: Since this is executed as a subprocess, it's NOT possible to update any of the variables in the main process (in particular the scanner state cannot be updated). NOTE: At least for Linux, it seems that we could get rid of the subprocess. Linux v2.0 does seem to allow select() on SCSI descriptors. */ static void output_data (Mustek_Scanner * s, FILE * fp, SANE_Byte * data, SANE_Int lines_per_buffer, SANE_Int bpl, SANE_Byte * extra) { SANE_Byte *ptr, *ptr_end; SANE_Int y, num_lines; DBG (5, "output_data: data=%p, lpb=%d, bpl=%d, extra=%p\n", data, lines_per_buffer, bpl, extra); /* convert to pixel-interleaved format: */ if ((s->mode & MUSTEK_MODE_COLOR) && !(s->hw->flags & MUSTEK_FLAG_THREE_PASS)) { num_lines = lines_per_buffer; /* need to correct for distance between r/g/b sensors: */ if (s->hw->flags & MUSTEK_FLAG_PRO) fix_line_distance_pro (s, num_lines, bpl, data, extra); else if (s->hw->flags & MUSTEK_FLAG_SE) { num_lines = fix_line_distance_se (s, num_lines, bpl, data, extra); } else if (s->hw->flags & MUSTEK_FLAG_N) { if (s->hw->flags & MUSTEK_FLAG_LD_N2) num_lines = fix_line_distance_n_2 (s, num_lines, bpl, data, extra); else num_lines = fix_line_distance_n_1 (s, num_lines, bpl, data, extra); } else if ((s->hw->flags & MUSTEK_FLAG_LD_BLOCK) && (s->ld.max_value != 0)) { if (s->hw->flags & MUSTEK_FLAG_PARAGON_1) num_lines = fix_line_distance_block (s, num_lines, bpl, data, extra, s->hw->lines); else num_lines = fix_line_distance_block (s, num_lines, bpl, data, extra, s->hw->lines_per_block); } else if (!(s->hw->flags & MUSTEK_FLAG_LD_NONE) && (s->ld.max_value != 0)) fix_line_distance_normal (s, num_lines, bpl, data, extra); else num_lines = fix_line_distance_none (s, num_lines, bpl, data, extra); if (strcmp (s->val[OPT_SOURCE].s, "Automatic Document Feeder") == 0) { /* need to revert line direction */ SANE_Int line_number; SANE_Int byte_number; DBG (5, "output_data: ADF found, mirroring lines\n"); for (line_number = 0; line_number < num_lines; line_number++) { for (byte_number = bpl - 3; byte_number >= 0; byte_number -= 3) { fputc (*(extra + line_number * bpl + byte_number), fp); fputc (*(extra + line_number * bpl + byte_number + 1), fp); fputc (*(extra + line_number * bpl + byte_number + 2), fp); } } } else fwrite (extra, num_lines, s->params.bytes_per_line, fp); } else { DBG (5, "output_data: write %d lpb; %d bpl\n", lines_per_buffer, bpl); /* Scale x-resolution above 1/2 of the maximum resolution for SE and Pro scanners */ if ((s->hw->flags & MUSTEK_FLAG_ENLARGE_X) && (s->val[OPT_RESOLUTION].w > (s->hw->dpi_range.max / 2))) { SANE_Int x; SANE_Int half_res = SANE_UNFIX (s->hw->dpi_range.max) / 2; SANE_Int res = SANE_UNFIX (s->val[OPT_RESOLUTION].w); SANE_Int res_counter; SANE_Int enlarged_x; DBG (5, "output_data: enlarge lines from %d bpl to %d bpl\n", s->hw->bpl, s->params.bytes_per_line); for (y = 0; y < lines_per_buffer; y++) { SANE_Byte byte = 0; x = 0; res_counter = 0; enlarged_x = 0; while (enlarged_x < s->params.pixels_per_line) { if (s->mode & MUSTEK_MODE_GRAY) { fputc (*(data + y * bpl + x), fp); res_counter += half_res; if (res_counter >= half_res) { res_counter -= res; x++; } enlarged_x++; } else /* lineart */ { /* need to invert image because of funny SANE 1-bit image polarity */ if (*(data + x / 8 + y * bpl) & (1 << (7 - (x % 8)))) byte |= 1 << (7 - (enlarged_x % 8)); if ((enlarged_x % 8) == 7) { fputc (~byte, fp); /* invert image */ byte = 0; } res_counter += half_res; if (res_counter >= half_res) { res_counter -= res; x++; } enlarged_x++; } } } } else /* lineart, gray or halftone (nothing to scale) */ { if ((s->mode & MUSTEK_MODE_LINEART) || (s->mode & MUSTEK_MODE_HALFTONE)) { /* need to invert image because of funny SANE 1-bit image polarity */ ptr = data; ptr_end = ptr + lines_per_buffer * bpl; if (strcmp (s->val[OPT_SOURCE].s, "Automatic Document Feeder") == 0) { while (ptr != ptr_end) { (*ptr) = ~(*ptr); ptr++; /* need to revert bit direction */ *ptr = ((*ptr & 0x80) >> 7) + ((*ptr & 0x40) >> 5) + ((*ptr & 0x20) >> 3) + ((*ptr & 0x10) >> 1) + ((*ptr & 0x08) << 1) + ((*ptr & 0x04) << 3) + ((*ptr & 0x02) << 5) + ((*ptr & 0x01) << 7); } } else while (ptr != ptr_end) { (*ptr) = ~(*ptr); ptr++; } } if (strcmp (s->val[OPT_SOURCE].s, "Automatic Document Feeder") == 0) { /* need to revert line direction */ SANE_Int line_number; SANE_Int byte_number; DBG (5, "output_data: ADF found, mirroring lines\n"); for (line_number = 0; line_number < lines_per_buffer; line_number++) { for (byte_number = bpl - 1; byte_number >= 0; byte_number--) { fputc (*(data + line_number * bpl + byte_number), fp); } } } else { fwrite (data, lines_per_buffer, bpl, fp); } } } DBG (5, "output_data: end\n"); } static void sigterm_handler (int signal) { DBG (4, "sigterm_handler: started, signal is %d, starting sanei_scsi_req_flush_all()\n", signal); sanei_scsi_req_flush_all (); /* flush SCSI queue */ DBG (4, "sigterm_handler: sanei_scsi_req_flush_all() finisheshed, _exiting()\n"); _exit (SANE_STATUS_GOOD); } static SANE_Int reader_process (void *data) { Mustek_Scanner *s = (Mustek_Scanner *) data; SANE_Int lines_per_buffer, bpl; SANE_Byte *extra = 0, *ptr; sigset_t sigterm_set; struct SIGACTION act; SANE_Status status; FILE *fp; int fd = s->reader_fds; SANE_Int buffernumber = 0; SANE_Int buffer_count, max_buffers; struct { void *id; /* scsi queue id */ SANE_Byte *data; /* data buffer */ SANE_Byte *command; /* command buffer */ SANE_Int lines; /* # lines in buffer */ size_t num_read; /* # of bytes read (return value) */ SANE_Int bank; /* needed by SE models */ SANE_Bool ready; /* ready to send to application? */ SANE_Bool finished; /* block is finished */ } bstat[2]; DBG (3, "reader_process: started\n"); if (sanei_thread_is_forked ()) { DBG (4, "reader_process: using fork ()\n"); close (s->pipe); s->pipe = -1; } else { DBG (4, "reader_process: using threads\n"); } if (sanei_thread_is_forked ()) { /* ignore SIGTERM while writing SCSI commands */ sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); /* call our sigterm handler to clean up ongoing SCSI requests */ memset (&act, 0, sizeof (act)); act.sa_handler = sigterm_handler; sigaction (SIGTERM, &act, 0); } if (disable_double_buffering) DBG (3, "reader_process: disable_double_buffering is set, this may be " "slow\n"); fp = fdopen (fd, "w"); if (!fp) return SANE_STATUS_IO_ERROR; s->total_lines = 0; bpl = s->hw->bpl; /* buffer size is scanner dependant */ lines_per_buffer = s->hw->buffer_size / bpl / 2; if (strip_height > 0.0) { SANE_Int max_lines; double dpi; dpi = SANE_UNFIX (s->val[OPT_RESOLUTION].w); max_lines = (int) (strip_height * dpi + 0.5); if (lines_per_buffer > max_lines) { DBG (2, "reader_process: limiting strip height to %g inches " "(%d lines)\n", strip_height, max_lines); lines_per_buffer = max_lines; } } if (!lines_per_buffer) { DBG (1, "reader_process: bpl (%d) > SCSI buffer size / 2 (%d)\n", bpl, s->hw->buffer_size / 2); return SANE_STATUS_NO_MEM; /* resolution is too high */ } DBG (4, "reader_process: %d lines per buffer, %d bytes per line, " "%d bytes per buffer\n", lines_per_buffer, bpl, lines_per_buffer * bpl); bstat[0].data = malloc (2 * lines_per_buffer * (long) bpl); if (!bstat[0].data) { DBG (1, "reader_process: failed to malloc %ld bytes for data buffer\n", lines_per_buffer * (long) bpl); return SANE_STATUS_NO_MEM; } bstat[1].data = bstat[0].data + lines_per_buffer * (long) bpl; bstat[0].command = malloc (2 * 10); if (!bstat[0].command) { DBG (1, "reader_process: failed to malloc %d bytes for command buffer\n", 2 * 10); return SANE_STATUS_NO_MEM; } bstat[1].command = bstat[0].command + 10; /* Touch all pages of the buffer to fool the memory management. */ ptr = bstat[0].data + 2 * lines_per_buffer * (long) bpl - 1; while (ptr >= bstat[0].data) { *ptr = 0x00; ptr -= 256; } if (!(s->hw->flags & MUSTEK_FLAG_THREE_PASS)) { /* get temporary buffer for line-distance correction and/or bit expansion. For some scanners more space is needed because the data must be read in as single big block (cut up into pieces of lines_per_buffer). This requires that the line distance correction continues on every call exactly where it stopped if the image shall be reconstructed without any stripes. */ extra = malloc ((lines_per_buffer + MAX_LINE_DIST) * (long) s->params.bytes_per_line); if (!extra) { DBG (1, "reader_process: failed to malloc extra buffer\n"); return SANE_STATUS_NO_MEM; } } if (s->hw->flags & MUSTEK_FLAG_N) { /* reacquire port access rights (lost because of fork()): */ sanei_ab306_get_io_privilege (s->fd); } if ((s->hw->flags & MUSTEK_FLAG_N) || (s->hw->flags & MUSTEK_FLAG_LD_BLOCK)) { /* reset counter of line number for line-dictance correction */ s->ld.ld_line = 0; } max_buffers = s->hw->max_block_buffer_size / (lines_per_buffer * bpl); if (max_buffers < 1) { DBG (1, "reader_process: buffersize > blocksize!\n"); return SANE_STATUS_NO_MEM; } DBG (4, "reader_process: limiting block read to %d buffers (%d lines)\n", max_buffers, MIN (s->hw->lines, (max_buffers * lines_per_buffer))); while (s->line < s->hw->lines) { s->hw->lines_per_block = MIN (s->hw->lines - s->line, (max_buffers * lines_per_buffer)); status = dev_block_read_start (s, s->hw->lines_per_block); if (status != SANE_STATUS_GOOD) return status; for (buffernumber = 0; buffernumber < 2; buffernumber++) { bstat[buffernumber].ready = SANE_FALSE; bstat[buffernumber].finished = SANE_FALSE; } buffer_count = 0; buffernumber = 0; while (1) { /* omit reading first two buffers (not yet ready) */ if (bstat[buffernumber].ready == SANE_TRUE) { DBG (4, "reader_process: buffer %d: waiting for request to be " "ready\n", buffernumber + 1); status = dev_req_wait (bstat[buffernumber].id); if (status == SANE_STATUS_GOOD) { DBG (4, "reader_process: buffer %d is ready, wanted %d, " "got %ld bytes\n", buffernumber + 1, bstat[buffernumber].lines * bpl, (long int) bstat[buffernumber].num_read); } else { DBG (1, "reader_process: failed to read data, status: %s, " "buffer: %d\n", sane_strstatus (status), buffernumber + 1); if (status == SANE_STATUS_NO_MEM) { DBG (1, "Probably the size of the kernel SCSI buffer is " "too small for the\n selected buffersize " "in mustek.conf. Either decrease " "buffersize in\n mustek.conf to e.g. 32, " "increase SG_BIG_BUF in kernel to 130560, " "or\n use SANE_SG_BUFFERSIZE variable. " "See man sane-scsi and README for\n " "details.\n"); } return status; } DBG (4, "reader_process: buffer %d: sending %ld bytes to " "output_data\n", buffernumber + 1, (long int) bstat[buffernumber].num_read); output_data (s, fp, bstat[buffernumber].data, bstat[buffernumber].lines, bpl, extra); if (bstat[buffernumber].finished) break; /* everything written; exit loop */ } if (disable_double_buffering) { /* Enter only one buffer at once */ if (buffernumber == 1) buffernumber = 0; else buffernumber = 1; } /* enter read requests only if data left */ if ((s->line < s->hw->lines) && (buffer_count < max_buffers)) { if (s->line + lines_per_buffer >= s->hw->lines) { /* do the last few lines: */ bstat[buffernumber].lines = s->hw->lines - s->line; bstat[buffernumber].bank = 0x01; bstat[buffernumber].finished = SANE_TRUE; } else { bstat[buffernumber].lines = lines_per_buffer; bstat[buffernumber].bank = 0x00; } if ((buffer_count + 1) >= max_buffers) bstat[buffernumber].finished = SANE_TRUE; s->line += bstat[buffernumber].lines; bstat[buffernumber].ready = SANE_TRUE; buffer_count++; DBG (4, "reader_process: buffer %d: entering read request for %d " "bytes (buffer %d)\n", buffernumber + 1, bstat[buffernumber].lines * bpl, buffer_count); sigprocmask (SIG_BLOCK, &sigterm_set, 0); status = dev_read_req_enter (s, bstat[buffernumber].data, bstat[buffernumber].lines, bpl, &bstat[buffernumber].num_read, &bstat[buffernumber].id, bstat[buffernumber].bank, bstat[buffernumber].command); sigprocmask (SIG_UNBLOCK, &sigterm_set, 0); if (status == SANE_STATUS_GOOD) { DBG (5, "reader_process: buffer %d: entered (line %d of %d," " buffer %d)\n", buffernumber + 1, s->line, s->hw->lines, buffer_count); } else { DBG (1, "reader_process: buffer %d: failed to enter read " "request, status: %s\n", buffernumber + 1, sane_strstatus (status)); return status; } } if (!disable_double_buffering) { if (buffernumber == 1) buffernumber = 0; else buffernumber = 1; } /* This is said to fix the scanner hangs that reportedly show on some MFS-12000SP scanners. */ if (s->mode == 0 && (s->hw->flags & MUSTEK_FLAG_LINEART_FIX)) usleep (200000); } } fclose (fp); free (bstat[0].data); if (s->ld.buf[0]) free (s->ld.buf[0]); s->ld.buf[0] = NULL; if (extra) free (extra); close (fd); return SANE_STATUS_GOOD; } static SANE_Status attach_one_device (SANE_String_Const devname) { Mustek_Device *dev; attach (devname, &dev, SANE_FALSE); if (dev) { /* Keep track of newly attached devices so we can set options as necessary. */ if (new_dev_len >= new_dev_alloced) { new_dev_alloced += 4; if (new_dev) new_dev = realloc (new_dev, new_dev_alloced * sizeof (new_dev[0])); else new_dev = malloc (new_dev_alloced * sizeof (new_dev[0])); if (!new_dev) { DBG (1, "attach_one_device: out of memory\n"); return SANE_STATUS_NO_MEM; } } new_dev[new_dev_len++] = dev; } return SANE_STATUS_GOOD; } /**************************************************************************/ /* SANE API calls */ /**************************************************************************/ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { SANE_Char line[PATH_MAX], *word, *end; SANE_String_Const cp; SANE_Int linenumber; FILE *fp; DBG_INIT (); sanei_thread_init (); #ifdef DBG_LEVEL debug_level = DBG_LEVEL; #else debug_level = 0; #endif DBG (2, "SANE mustek backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (5, "sane_init: authorize %s null\n", authorize ? "!=" : "=="); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED DBG (5, "sane_init: using sanei_scsi_open_extended\n"); #else DBG (5, "sane_init: using sanei_scsi_open with buffer size = %d bytes\n", sanei_scsi_max_request_size); #endif num_devices = 0; force_wait = SANE_FALSE; disable_double_buffering = SANE_FALSE; first_dev = 0; first_handle = 0; devlist = 0; new_dev = 0; new_dev_len = 0; new_dev_alloced = 0; fp = sanei_config_open (MUSTEK_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ DBG (3, "sane_init: couldn't find config file (%s), trying " "/dev/scanner directly\n", MUSTEK_CONFIG_FILE); attach ("/dev/scanner", 0, SANE_FALSE); return SANE_STATUS_GOOD; } linenumber = 0; DBG (4, "sane_init: reading config file `%s'\n", MUSTEK_CONFIG_FILE); while (sanei_config_read (line, sizeof (line), fp)) { word = 0; linenumber++; cp = sanei_config_get_string (line, &word); if (!word || cp == line) { DBG (5, "sane_init: config file line %d: ignoring empty line\n", linenumber); if (word) free (word); continue; } if (word[0] == '#') { DBG (5, "sane_init: config file line %d: ignoring comment line\n", linenumber); free (word); continue; } if (strcmp (word, "option") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (!word) { DBG (1, "sane_init: config file line %d: missing quotation mark?\n", linenumber); continue; } if (strcmp (word, "strip-height") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (!word) { DBG (1, "sane_init: config file line %d: missing quotation mark?\n", linenumber); continue; } errno = 0; strip_height = strtod (word, &end); if (end == word) { DBG (3, "sane-init: config file line %d: strip-height " "must have a parameter; using 1 inch\n", linenumber); strip_height = 1.0; } if (errno) { DBG (3, "sane-init: config file line %d: strip-height `%s' " "is invalid (%s); using 1 inch\n", linenumber, word, strerror (errno)); strip_height = 1.0; } else { if (strip_height < 0.1) strip_height = 0.1; DBG (3, "sane_init: config file line %d: strip-height set " "to %g inches\n", linenumber, strip_height); } if (word) free (word); word = 0; } else if (strcmp (word, "force-wait") == 0) { DBG (3, "sane_init: config file line %d: enabling force-wait\n", linenumber); force_wait = SANE_TRUE; if (word) free (word); word = 0; } else if (strcmp (word, "disable-double-buffering") == 0) { DBG (3, "sane_init: config file line %d: disabling " "double-buffering\n", linenumber); disable_double_buffering = SANE_TRUE; if (word) free (word); word = 0; } else if (strcmp (word, "legal-size") == 0) { if (new_dev_len > 0) { /* Check for 12000 LS, no way to find out automatically */ if (strcmp (new_dev[new_dev_len - 1]->sane.model, "ScanExpress 12000SP") == 0) { new_dev[new_dev_len - 1]->x_range.max = SANE_FIX (220.0); new_dev[new_dev_len - 1]->y_range.max = SANE_FIX (360.0); new_dev[new_dev_len - 1]->sane.model = "Paragon 1200 LS"; DBG (3, "sane_init: config file line %d: enabling " "legal-size for %s\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "legal-size ignored, device %s is not a " "Paragon 1200 LS\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } } else { DBG (3, "sane_init: config file line %d: option " "legal-size ignored, was set before any device " "name\n", linenumber); } if (word) free (word); word = 0; } else if (strcmp (word, "linedistance-fix") == 0) { if (new_dev_len > 0) { new_dev[new_dev_len - 1]->flags |= MUSTEK_FLAG_LD_FIX; DBG (3, "sane_init: config file line %d: enabling " "linedistance-fix for %s\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "linedistance-fix ignored, was set before any device " "name\n", linenumber); } if (word) free (word); word = 0; } else if (strcmp (word, "disable-backtracking") == 0) { if (new_dev_len > 0) { new_dev[new_dev_len - 1]->flags |= MUSTEK_FLAG_NO_BACKTRACK; DBG (3, "sane_init: config file line %d: disabling " "backtracking for %s\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "disable-backtracking ignored, was set before any " "device name\n", linenumber); } if (word) free (word); word = 0; } else if (strcmp (word, "lineart-fix") == 0) { if (new_dev_len > 0) { new_dev[new_dev_len - 1]->flags |= MUSTEK_FLAG_LINEART_FIX; DBG (3, "sane_init: config file line %d: enabling " "lineart-fix for %s\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "lineart-fix ignored, was set before any device name\n", linenumber); } if (word) free (word); word = 0; } else if (strcmp (word, "buffersize") == 0) { long buffer_size; free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (!word) { DBG (1, "sane_init: config file line %d: missing quotation mark?\n", linenumber); continue; } errno = 0; buffer_size = strtol (word, &end, 0); if (end == word) { DBG (3, "sane-init: config file line %d: buffersize must " "have a parameter; using default (%d kb)\n", linenumber, new_dev[new_dev_len - 1]->max_buffer_size); } if (errno) { DBG (3, "sane-init: config file line %d: buffersize `%s' " "is invalid (%s); using default (%d kb)\n", linenumber, word, strerror (errno), new_dev[new_dev_len - 1]->max_buffer_size); } else { if (new_dev_len > 0) { if (buffer_size < 32.0) buffer_size = 32.0; new_dev[new_dev_len - 1]->max_buffer_size = buffer_size * 1024; DBG (3, "sane_init: config file line %d: buffersize set " "to %ld kb for %s\n", linenumber, buffer_size, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "buffersize ignored, was set before any device " "name\n", linenumber); } } if (word) free (word); word = 0; } else if (strcmp (word, "blocksize") == 0) { long block_size; free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (!word) { DBG (1, "sane_init: config file line %d: missing quotation mark?\n", linenumber); continue; } errno = 0; block_size = strtol (word, &end, 0); if (end == word) { DBG (3, "sane-init: config file line %d:: blocksize must " "have a parameter; using default (1 GB)\n", linenumber); } if (errno) { DBG (3, "sane-init: config file line %d: blocksize `%s' " "is invalid (%s); using default (1 GB)\n", linenumber, word, strerror (errno)); } else { if (new_dev_len > 0) { if (block_size < 256.0) block_size = 256.0; new_dev[new_dev_len - 1]->max_block_buffer_size = block_size * 1024; DBG (3, "sane_init: config file line %d: blocksize set " "to %ld kb for %s\n", linenumber, block_size, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "blocksize ignored, was set before any device " "name\n", linenumber); } } if (word) free (word); word = 0; } else { DBG (3, "sane_init: config file line %d: ignoring unknown " "option `%s'\n", linenumber, word); if (word) free (word); word = 0; } } else { new_dev_len = 0; DBG (4, "sane_init: config file line %d: trying to attach `%s'\n", linenumber, line); sanei_config_attach_matching_devices (line, attach_one_device); if (word) free (word); word = 0; } } if (new_dev_alloced > 0) { new_dev_len = new_dev_alloced = 0; free (new_dev); } fclose (fp); DBG (5, "sane_init: end\n"); return SANE_STATUS_GOOD; } void sane_exit (void) { Mustek_Device *dev, *next; DBG (4, "sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free (dev->name); free (dev); } if (devlist) free (devlist); devlist = 0; first_dev = 0; sanei_ab306_exit (); /* may have to do some cleanup */ mustek_scsi_pp_exit (); DBG (5, "sane_exit: finished\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Mustek_Device *dev; SANE_Int i; DBG (4, "sane_get_devices: %d devices %s\n", num_devices, local_only ? "(local only)" : ""); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (5, "sane_get_devices: end\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Mustek_Device *dev; SANE_Status status; Mustek_Scanner *s; if (!devicename) { DBG (1, "sane_open: devicename is null!\n"); return SANE_STATUS_INVAL; } if (!handle) { DBG (1, "sane_open: handle is null!\n"); return SANE_STATUS_INVAL; } DBG (4, "sane_open: devicename=%s\n", devicename); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { status = attach (devicename, &dev, SANE_TRUE); if (status != SANE_STATUS_GOOD) return status; } } else /* empty devicname -> use first device */ dev = first_dev; if (!dev) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->pipe = -1; s->hw = dev; s->ld.ld_line = 0; s->halftone_pattern = malloc (8 * 8 * sizeof (SANE_Int)); if (!s->halftone_pattern) return SANE_STATUS_NO_MEM; init_options (s); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; DBG (4, "sane_open: finished (handle=%p)\n", (void *) s); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Mustek_Scanner *prev, *s; DBG (4, "sane_close: handle=%p\n", handle); /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (1, "sane_close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (s->scanning) do_stop (handle); if (s->ld.buf[0]) free (s->ld.buf[0]); if (s->val[OPT_MODE].s) free (s->val[OPT_MODE].s); if (s->val[OPT_BIT_DEPTH].s) free (s->val[OPT_BIT_DEPTH].s); if (s->val[OPT_SPEED].s) free (s->val[OPT_SPEED].s); if (s->val[OPT_SOURCE].s) free (s->val[OPT_SOURCE].s); if (s->val[OPT_HALFTONE_DIMENSION].s) free (s->val[OPT_HALFTONE_DIMENSION].s); if (s->halftone_pattern) free (s->halftone_pattern); if (prev) prev->next = s->next; else first_handle = s->next; free (handle); handle = 0; DBG (5, "sane_close: finished\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Mustek_Scanner *s = handle; if (((unsigned) option >= NUM_OPTIONS) || (option < 0)) { DBG (4, "sane_get_option_descriptor: option %d >= NUM_OPTIONS or < 0\n", option); return 0; } if (!s) { DBG (1, "sane_get_option_descriptor: handle is null!\n"); return 0; } if (s->opt[option].name && s->opt[option].name[0] != 0) DBG (5, "sane_get_option_descriptor for option %s (%sactive%s)\n", s->opt[option].name, s->opt[option].cap & SANE_CAP_INACTIVE ? "in" : "", s->opt[option].cap & SANE_CAP_ADVANCED ? ", advanced" : ""); else DBG (5, "sane_get_option_descriptor for option \"%s\" (%sactive%s)\n", s->opt[option].title, s->opt[option].cap & SANE_CAP_INACTIVE ? "in" : "", s->opt[option].cap & SANE_CAP_ADVANCED ? ", advanced" : ""); return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Mustek_Scanner *s = handle; SANE_Status status; SANE_Word w, cap; if (((unsigned) option >= NUM_OPTIONS) || (option < 0)) { DBG (4, "sane_control_option: option %d < 0 or >= NUM_OPTIONS\n", option); return SANE_STATUS_INVAL; } if (!s) { DBG (1, "sane_control_option: handle is null!\n"); return SANE_STATUS_INVAL; } if (s->opt[option].type != SANE_TYPE_BUTTON && !val) { DBG (1, "sane_control_option: val is null!\n"); return SANE_STATUS_INVAL; } if (s->opt[option].name && s->opt[option].name[0] != 0) DBG (5, "sane_control_option (%s option %s)\n", action == SANE_ACTION_GET_VALUE ? "get" : (action == SANE_ACTION_SET_VALUE ? "set" : "unknown action with"), s->opt[option].name); else DBG (5, "sane_control_option (%s option \"%s\")\n", action == SANE_ACTION_GET_VALUE ? "get" : (action == SANE_ACTION_SET_VALUE ? "set" : "unknown action with"), s->opt[option].title); if (info) *info = 0; if (s->scanning) { DBG (4, "sane_control_option: don't use while scanning (option %s)\n", s->opt[option].name); return SANE_STATUS_DEVICE_BUSY; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (4, "sane_control_option: option %s is inactive\n", s->opt[option].name); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_PREVIEW: case OPT_FAST_PREVIEW: case OPT_RESOLUTION: case OPT_FAST_GRAY_MODE: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_BRIGHTNESS_R: case OPT_BRIGHTNESS_G: case OPT_BRIGHTNESS_B: case OPT_CONTRAST: case OPT_CONTRAST_R: case OPT_CONTRAST_G: case OPT_CONTRAST_B: case OPT_CUSTOM_GAMMA: case OPT_QUALITY_CAL: case OPT_LAMP_OFF_TIME: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_HALFTONE_PATTERN: memcpy (val, s->val[option].wa, s->opt[option].size); return SANE_STATUS_GOOD; /* string options: */ case OPT_SPEED: case OPT_SOURCE: case OPT_MODE: case OPT_BIT_DEPTH: case OPT_HALFTONE_DIMENSION: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (4, "sane_control_option: option %s is not setable\n", s->opt[option].name); return SANE_STATUS_INVAL; } status = constrain_value (s, option, val, info); if (status != SANE_STATUS_GOOD) { DBG (4, "sane_control_option: constrain_value error (option %s)\n", s->opt[option].name); return status; } switch (option) { case OPT_LAMP_OFF_BUTTON: { SANE_Int old_time = lamp_off_time; SANE_Status status; status = dev_open (s->hw->sane.name, s, sense_handler); if (status != SANE_STATUS_GOOD) return status; lamp_off_time = 0; set_window_pro (s); lamp_off_time = old_time; dev_close (s); return SANE_STATUS_GOOD; } /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_BR_X: case OPT_TL_Y: case OPT_BR_Y: if (info) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_PREVIEW: case OPT_FAST_PREVIEW: case OPT_FAST_GRAY_MODE: case OPT_BRIGHTNESS: case OPT_BRIGHTNESS_R: case OPT_BRIGHTNESS_G: case OPT_BRIGHTNESS_B: case OPT_CONTRAST: case OPT_CONTRAST_R: case OPT_CONTRAST_G: case OPT_CONTRAST_B: case OPT_QUALITY_CAL: case OPT_LAMP_OFF_TIME: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* side-effect-free word-array options: */ case OPT_HALFTONE_PATTERN: case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); return SANE_STATUS_GOOD; /* side-effect-free single-string options: */ case OPT_SPEED: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; return SANE_STATUS_GOOD; /* side-effect-free string list options: */ case OPT_BIT_DEPTH: { SANE_Char *old_val = s->val[option].s; if (old_val) { if (strcmp (old_val, val) == 0) return SANE_STATUS_GOOD; /* no change */ free (old_val); } s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; return SANE_STATUS_GOOD; } /* options with side-effects: */ case OPT_CUSTOM_GAMMA: w = *(SANE_Word *) val; if (w == s->val[OPT_CUSTOM_GAMMA].w) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[OPT_CUSTOM_GAMMA].w = w; if (w) { SANE_String_Const mode = s->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } else if ((strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) && (s->hw->flags & MUSTEK_FLAG_PRO)) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } } else { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; case OPT_MODE: { SANE_Char *old_val = s->val[option].s; SANE_Int halftoning, binary; if (old_val) { if (strcmp (old_val, val) == 0) return SANE_STATUS_GOOD; /* no change */ free (old_val); } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_DIMENSION].cap |= SANE_CAP_INACTIVE; s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; halftoning = strcmp (val, SANE_VALUE_SCAN_MODE_HALFTONE) == 0; binary = (halftoning || strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0); if (binary) { /* enable brightness/contrast for when in a binary mode */ s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; /* The SE and paragon models support only threshold in lineart */ if (!(s->hw->flags & MUSTEK_FLAG_SE) && !(s->hw->flags & MUSTEK_FLAG_PRO)) s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; if (halftoning) { s->opt[OPT_HALFTONE_DIMENSION].cap &= ~SANE_CAP_INACTIVE; encode_halftone (s); if (s->custom_halftone_pattern) { s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; } } } else { s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; } if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { s->opt[OPT_BRIGHTNESS_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_BRIGHTNESS_B].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST_B].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; } } else if (s->hw->flags & MUSTEK_FLAG_PRO) { if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->opt[OPT_FAST_GRAY_MODE].cap &= ~SANE_CAP_INACTIVE; else s->opt[OPT_FAST_GRAY_MODE].cap |= SANE_CAP_INACTIVE; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; else s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; } else if (s->hw->flags & MUSTEK_FLAG_SE_PLUS) { if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE; else s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE; } if (s->val[OPT_CUSTOM_GAMMA].w) { if (strcmp (val, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (val, SANE_VALUE_SCAN_MODE_COLOR) == 0) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } return SANE_STATUS_GOOD; } case OPT_HALFTONE_DIMENSION: /* halftone pattern dimension affects halftone pattern option: */ { if (strcmp (s->val[option].s, (SANE_String) val) == 0) return SANE_STATUS_GOOD; /* no change */ if (info) *info |= SANE_INFO_RELOAD_OPTIONS; s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; encode_halftone (s); s->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (s->custom_halftone_pattern) { s->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; /* BUG: The SANE standard does nor allow to change the option size at run time */ s->opt[OPT_HALFTONE_PATTERN].size = (s->halftone_pattern_type & 0x0f) * sizeof (SANE_Word); } return SANE_STATUS_GOOD; } case OPT_SOURCE: if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; if (strcmp (val, "Transparency Adapter") == 0) { s->opt[OPT_TL_X].constraint.range = &s->hw->x_trans_range; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_trans_range; s->opt[OPT_BR_X].constraint.range = &s->hw->x_trans_range; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_trans_range; } else { s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; } return SANE_STATUS_GOOD; } } DBG (4, "sane_control_option: unknown action for option %s\n", s->opt[option].name); return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Mustek_Scanner *s = handle; SANE_String_Const mode; if (!s) { DBG (1, "sane_get_parameters: handle is null!\n"); return SANE_STATUS_INVAL; } if (!s->scanning) { double width, height, dpi; memset (&s->params, 0, sizeof (s->params)); width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); dpi = SANE_UNFIX (s->val[OPT_RESOLUTION].w); /* make best-effort guess at what parameters will look like once scanning starts. */ if (dpi > 0.0 && width > 0.0 && height > 0.0) { double dots_per_mm = dpi / MM_PER_INCH; s->params.pixels_per_line = width * dots_per_mm; s->params.lines = height * dots_per_mm; } encode_halftone (s); mode = s->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0 || strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; s->params.depth = 1; } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } else { /* it's one of the color modes... */ if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { s->params.format = SANE_FRAME_RED + s->pass; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } else /* 1-pass */ { if (strcmp (s->val[OPT_BIT_DEPTH].s, "12") == 0) { s->params.bytes_per_line = 6 * s->params.pixels_per_line; s->params.depth = 16; } else { s->params.bytes_per_line = 3 * s->params.pixels_per_line; s->params.depth = 8; } s->params.format = SANE_FRAME_RGB; } } } else if ((s->mode & MUSTEK_MODE_COLOR) && (s->hw->flags & MUSTEK_FLAG_THREE_PASS)) s->params.format = SANE_FRAME_RED + s->pass; s->params.last_frame = (s->params.format != SANE_FRAME_RED && s->params.format != SANE_FRAME_GREEN); if (params) *params = s->params; DBG (4, "sane_get_parameters: frame = %d; last_frame = %s; depth = %d\n", s->params.format, s->params.last_frame ? "true" : "false", s->params.depth); DBG (4, "sane_get_parameters: lines = %d; ppl = %d; bpl = %d\n", s->params.lines, s->params.pixels_per_line, s->params.bytes_per_line); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Mustek_Scanner *s = handle; SANE_Status status; int fds[2]; struct SIGACTION act; if (!s) { DBG (1, "sane_start: handle is null!\n"); return SANE_STATUS_INVAL; } DBG (4, "sane_start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; /* Check for inconsistencies */ if (s->val[OPT_TL_X].w > s->val[OPT_BR_X].w) { DBG (0, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) " "-- aborting\n", s->opt[OPT_TL_X].title, SANE_UNFIX (s->val[OPT_TL_X].w), s->opt[OPT_BR_X].title, SANE_UNFIX (s->val[OPT_BR_X].w)); return SANE_STATUS_INVAL; } if (s->val[OPT_TL_Y].w > s->val[OPT_BR_Y].w) { DBG (0, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) " "-- aborting\n", s->opt[OPT_TL_Y].title, SANE_UNFIX (s->val[OPT_TL_Y].w), s->opt[OPT_BR_Y].title, SANE_UNFIX (s->val[OPT_BR_Y].w)); return SANE_STATUS_INVAL; } s->total_bytes = 0; if (s->fd < 0) { /* this is the first (and maybe only) pass... */ SANE_String_Const mode; struct timeval start; /* save start time */ gettimeofday (&start, 0); s->start_time = start.tv_sec; /* translate options into s->mode for convenient access: */ mode = s->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) s->mode = MUSTEK_MODE_LINEART; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) s->mode = MUSTEK_MODE_HALFTONE; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->mode = MUSTEK_MODE_GRAY; else if (strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0) s->mode = MUSTEK_MODE_COLOR; /* scanner dependant specials */ s->one_pass_color_scan = SANE_FALSE; if ((s->mode & MUSTEK_MODE_COLOR) && !(s->hw->flags & MUSTEK_FLAG_THREE_PASS)) { s->one_pass_color_scan = SANE_TRUE; } s->resolution_code = encode_resolution (s); if (s->val[OPT_PREVIEW].w && s->val[OPT_FAST_PREVIEW].w) { if (s->hw->flags & MUSTEK_FLAG_THREE_PASS) { if (s->mode & MUSTEK_MODE_COLOR) { /* Force gray-scale mode when previewing. */ s->mode = MUSTEK_MODE_GRAY; s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.last_frame = SANE_TRUE; } } else if (s->hw->flags & MUSTEK_FLAG_SE) { /* use 36 dpi color in any case */ s->mode = MUSTEK_MODE_COLOR; s->params.format = SANE_FRAME_RGB; s->params.depth = 8; s->one_pass_color_scan = SANE_TRUE; s->resolution_code = 36; } else if (s->hw->flags & MUSTEK_FLAG_PARAGON_1) { /* use 36 dpi */ s->resolution_code = 36; } else if (s->hw->flags & MUSTEK_FLAG_PRO) { /* use 30 dpi color mode */ s->mode = MUSTEK_MODE_COLOR; s->params.format = SANE_FRAME_RGB; s->params.depth = 8; s->one_pass_color_scan = SANE_TRUE; s->resolution_code = 30; } DBG (4, "sane_start: use fast preview (res=%d dpi)\n", s->resolution_code); } status = dev_open (s->hw->sane.name, s, sense_handler); if (status != SANE_STATUS_GOOD) return status; } status = dev_wait_ready (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: wait_ready() failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } if (!(s->hw->flags & MUSTEK_FLAG_SCSI_PP)) { /* SCSI-over-parallel port doesn't seem to like being inquired here */ status = inquiry (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: inquiry command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } } if ((strcmp (s->val[OPT_SOURCE].s, "Automatic Document Feeder") == 0) && !(s->hw->flags & MUSTEK_FLAG_ADF_READY)) { DBG (2, "sane_start: automatic document feeder is out of documents\n"); status = SANE_STATUS_NO_DOCS; goto stop_scanner_and_return; } if (s->hw->flags & MUSTEK_FLAG_SE) { status = set_window_se (s, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: set window command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } s->scanning = SANE_TRUE; s->cancelled = SANE_FALSE; dev_wait_ready (s); status = get_window (s, &s->params.bytes_per_line, &s->params.lines, &s->params.pixels_per_line); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: get window command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = calibration_se (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = start_scan (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = send_gamma_table_se (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; } else if (s->hw->flags & MUSTEK_FLAG_PRO) { status = dev_wait_ready (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = set_window_pro (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; s->scanning = SANE_TRUE; s->cancelled = SANE_FALSE; status = adf_and_backtrack (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = mode_select_pro (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = scsi_sense_wait_ready (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = calibration_pro (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = send_gamma_table (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = start_scan (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = get_image_status (s, &s->params.bytes_per_line, &s->params.lines); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = scsi_sense_wait_ready (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; } else /* Paragon series */ { status = area_and_windows (s); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_start: set scan area command failed: %s\n", sane_strstatus (status)); goto stop_scanner_and_return; } status = adf_and_backtrack (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; if (s->one_pass_color_scan) { status = mode_select_paragon (s, MUSTEK_CODE_RED); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = mode_select_paragon (s, MUSTEK_CODE_GREEN); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = mode_select_paragon (s, MUSTEK_CODE_BLUE); } else status = mode_select_paragon (s, MUSTEK_CODE_GRAY); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; s->scanning = SANE_TRUE; s->cancelled = SANE_FALSE; status = send_gamma_table (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; status = start_scan (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; if (!(s->hw->flags & MUSTEK_FLAG_SCSI_PP)) { /* This second gamma table download upsets the SCSI-over-parallel models */ status = send_gamma_table (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; } s->ld.max_value = 0; if (!(s->hw->flags & MUSTEK_FLAG_THREE_PASS)) { status = line_distance (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; } status = get_image_status (s, &s->params.bytes_per_line, &s->params.lines); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; if ((strcmp (s->val[OPT_SOURCE].s, "Automatic Document Feeder") == 0) && (s->hw->flags & MUSTEK_FLAG_PARAGON_2)) { status = paragon_2_get_adf_status (s); if (status != SANE_STATUS_GOOD) goto stop_scanner_and_return; } } s->params.pixels_per_line = s->params.bytes_per_line; if (s->one_pass_color_scan) { if (strcmp (s->val[OPT_BIT_DEPTH].s, "12") == 0) s->params.pixels_per_line /= 6; else s->params.pixels_per_line /= 3; } else if ((s->mode & MUSTEK_MODE_LINEART) || (s->mode & MUSTEK_MODE_HALFTONE)) s->params.pixels_per_line *= 8; s->line = 0; /* don't call any SIGTERM or SIGCHLD handlers this is to stop xsane and other frontends from calling its quit handlers */ memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); sigaction (SIGCHLD, &act, 0); if (pipe (fds) < 0) return SANE_STATUS_IO_ERROR; s->reader_fds = fds[1]; /* create reader routine as new process or thread */ s->reader_pid = sanei_thread_begin (reader_process, (void *) s); if (!sanei_thread_is_valid (s->reader_pid)) { DBG (1, "sane_start: sanei_thread_begin failed (%s)\n", strerror (errno)); return SANE_STATUS_NO_MEM; } if (sanei_thread_is_forked ()) { close (s->reader_fds); s->reader_fds = -1; } s->pipe = fds[0]; return SANE_STATUS_GOOD; stop_scanner_and_return: do_stop (s); return status; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Mustek_Scanner *s = handle; SANE_Status status; ssize_t nread; if (!s) { DBG (1, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } if (!buf) { DBG (1, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (!len) { DBG (1, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } DBG (5, "sane_read\n"); *len = 0; if (s->cancelled) { DBG (4, "sane_read: scan was cancelled\n"); return SANE_STATUS_CANCELLED; } if (!s->scanning) { DBG (3, "sane_read: must call sane_start before sane_read\n"); return SANE_STATUS_INVAL; } while (*len < max_len) { nread = read (s->pipe, buf + *len, max_len - *len); if (s->cancelled) { DBG (4, "sane_read: scan was cancelled\n"); *len = 0; return SANE_STATUS_CANCELLED; } if (nread < 0) { if (errno == EAGAIN) { if (*len == 0) DBG (5, "sane_read: no more data at the moment--try again\n"); else DBG (5, "sane_read: read buffer of %d bytes " "(%d bytes total)\n", *len, s->total_bytes); return SANE_STATUS_GOOD; } else { DBG (1, "sane_read: IO error\n"); do_stop (s); *len = 0; return SANE_STATUS_IO_ERROR; } } *len += nread; s->total_bytes += nread; if (nread == 0) { if (*len == 0) { if (!(s->hw->flags & MUSTEK_FLAG_THREE_PASS) || !(s->mode & MUSTEK_MODE_COLOR) || ++s->pass >= 3) { DBG (5, "sane_read: pipe was closed ... calling do_stop\n"); status = do_stop (s); if (status != SANE_STATUS_CANCELLED && status != SANE_STATUS_GOOD) return status; /* something went wrong */ } else /* 3pass color first or second pass */ { DBG (5, "sane_read: pipe was closed ... finishing pass %d\n", s->pass); } return do_eof (s); } else { DBG (5, "sane_read: read last buffer of %d bytes " "(%d bytes total)\n", *len, s->total_bytes); return SANE_STATUS_GOOD; } } } DBG (5, "sane_read: read full buffer of %d bytes (%d total bytes)\n", *len, s->total_bytes); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Mustek_Scanner *s = handle; if (!s) { DBG (1, "sane_cancel: handle is null!\n"); return; } DBG (4, "sane_cancel\n"); if (s->scanning) { s->cancelled = SANE_TRUE; do_stop (handle); } DBG (5, "sane_cancel: finished\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Mustek_Scanner *s = handle; if (!s) { DBG (1, "sane_set_io_mode: handle is null!\n"); return SANE_STATUS_INVAL; } DBG (4, "sane_set_io_mode: %s\n", non_blocking ? "non-blocking" : "blocking"); if (!s->scanning) { DBG (1, "sane_set_io_mode: call sane_start before sane_set_io_mode"); return SANE_STATUS_INVAL; } if (fcntl (s->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { DBG (1, "sane_set_io_mode: can't set io mode"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Mustek_Scanner *s = handle; if (!s) { DBG (1, "sane_get_select_fd: handle is null!\n"); return SANE_STATUS_INVAL; } if (!fd) { DBG (1, "sane_get_select_fd: fd is null!\n"); return SANE_STATUS_INVAL; } DBG (4, "sane_get_select_fd\n"); if (!s->scanning) return SANE_STATUS_INVAL; *fd = s->pipe; return SANE_STATUS_GOOD; } #include "mustek_scsi_pp.c" sane-backends-1.0.27/backend/plustek-usbio.c0000664000175000017500000002143412112021330015550 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbio.c * @brief Some I/O stuff. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2007 Gerhard Jaeger * * History: * History: * - 0.40 - starting version of the USB support * - 0.41 - moved some functions to a sane library (sanei_lm983x.c) * - 0.42 - no changes * - 0.43 - no changes * - 0.44 - added dump registers and dumpPic functions * - beautyfied output of ASIC detection * - 0.45 - fixed dumpRegs * - added dimension stuff to dumpPic * - 0.46 - disabled reset prior to the detection of Merlin * - 0.47 - no changes * - 0.48 - cleanup * - 0.49 - no changes * - 0.50 - usbio_DetectLM983x() now returns error if register * could not be red * - usbio_ResetLM983x() checks for reg7 value before writing * - 0.51 - allow dumpRegs to be called without valid fd * - 0.52 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_lm983x.h" #define _UIO(func) \ { \ SANE_Status status; \ status = func; \ if (status != SANE_STATUS_GOOD) { \ DBG( _DBG_ERROR, "UIO error\n" ); \ return SANE_FALSE; \ } \ } #define usbio_ReadReg(fd, reg, value) \ sanei_lm983x_read (fd, reg, value, 1, 0) typedef struct { u_char depth; u_long x; u_long y; } PicDef, *pPicDef; static PicDef dPix; /** */ static void dumpPic( char* name, SANE_Byte *buffer, u_long len, int is_gray ) { u_short type; FILE *fp; if( DBG_LEVEL < _DBG_DPIC ) return; if( NULL == buffer ) { DBG( _DBG_DPIC, "Creating file '%s'\n", name ); fp = fopen( name, "w+b" ); if( NULL != fp ) { if( 0 != dPix.x ) { if (is_gray) type = 5; else type = 6; DBG( _DBG_DPIC, "> X=%lu, Y=%lu, depth=%u\n", dPix.x, dPix.y, dPix.depth ); if( dPix.depth > 8 ) fprintf( fp, "P%u\n%lu %lu\n65535\n", type, dPix.x, dPix.y); else fprintf( fp, "P%u\n%lu %lu\n255\n", type, dPix.x, dPix.y); } } } else { fp = fopen( name, "a+b" ); } if( NULL == fp ) { DBG( _DBG_DPIC, "Can not open file '%s'\n", name ); return; } fwrite( buffer, 1, len, fp ); fclose( fp ); } /** */ static void dumpPicInit( ScanParam *sd, char* name ) { dPix.x = sd->Size.dwPhyBytes; if( sd->bDataType == SCANDATATYPE_Color ) dPix.x /= 3; if( sd->bBitDepth > 8 ) dPix.x /= 2; dPix.y = sd->Size.dwLines; dPix.depth = sd->bBitDepth; if( sd->bDataType == SCANDATATYPE_Color ) dumpPic(name, NULL, 0, 0); else dumpPic(name, NULL, 0, 1); } /** * dump the LM983x registers */ static void dumpregs( int fd, SANE_Byte *cmp ) { char buf[256], b2[10]; SANE_Byte regs[0x80]; int i; if( DBG_LEVEL < _DBG_DREGS ) return; buf[0] = '\0'; if( fd >= 0 ) { usbio_ReadReg(fd, 0x01, ®s[0x01]); usbio_ReadReg(fd, 0x02, ®s[0x02]); usbio_ReadReg(fd, 0x03, ®s[0x03]); usbio_ReadReg(fd, 0x04, ®s[0x04]); usbio_ReadReg(fd, 0x07, ®s[0x07]); sanei_lm983x_read( fd, 0x08, ®s[0x8], 0x80-0x8, SANE_TRUE ); for( i = 0x0; i < 0x80; i++ ) { if((i%16) ==0 ) { if( buf[0] ) DBG( _DBG_DREGS, "%s\n", buf ); sprintf( buf, "0x%02x:", i ); } if((i%8)==0) strcat( buf, " "); /* the dataport read returns with "0 Bytes read", of course. */ if((i == 0) || (i == 5) || (i == 6)) strcat( buf, "XX "); else { sprintf( b2, "%02x ", regs[i]); strcat( buf, b2 ); } } DBG( _DBG_DREGS, "%s\n", buf ); } if( cmp ) { buf[0] = '\0'; DBG( _DBG_DREGS, "Internal setting:\n" ); for( i = 0x0; i < 0x80; i++ ) { if((i%16) ==0 ) { if( buf[0] ) DBG( _DBG_DREGS, "%s\n", buf ); sprintf( buf, "0x%02x:", i ); } if((i%8)==0) strcat( buf, " "); if((i == 0) || (i == 5) || (i == 6)) strcat( buf, "XX "); else { sprintf( b2, "%02x ", cmp[i]); strcat( buf, b2 ); } } DBG( _DBG_DREGS, "%s\n", buf ); } } /** * function to read the contents of a LM983x register and regarding some * extra stuff, like flushing register 2 when writing register 0x58, etc * * @param handle - * @param reg - * @param value - * @return */ static SANE_Bool usbio_WriteReg( SANE_Int handle, SANE_Byte reg, SANE_Byte value ) { int i; SANE_Byte data; /* retry loop... */ for( i = 0; i < 100; i++ ) { sanei_lm983x_write_byte( handle, reg, value ); /* Flush register 0x02 when register 0x58 is written */ if( 0x58 == reg ) { _UIO( usbio_ReadReg( handle, 2, &data )); _UIO( usbio_ReadReg( handle, 2, &data )); } if( reg != 7 ) return SANE_TRUE; /* verify register 7 */ _UIO( usbio_ReadReg( handle, 7, &data )); if( data == value ) { return SANE_TRUE; } } return SANE_FALSE; } /** try and read register 0x69 from a LM983x to find out which version we have. */ static SANE_Status usbio_DetectLM983x( SANE_Int fd, SANE_Byte *version ) { char buf[256]; SANE_Byte value; SANE_Status res; DBG( _DBG_INFO, "usbio_DetectLM983x\n"); res = usbio_ReadReg(fd, 0x69, &value); if( res != SANE_STATUS_GOOD ) { DBG( _DBG_ERROR, " * could not read version register!\n"); return res; } value &= 7; if (version) *version = value; res = SANE_STATUS_GOOD; sprintf( buf, "usbio_DetectLM983x: found " ); switch((SANE_Int)value ) { case 4: strcat( buf, "LM9832/3" ); break; case 3: strcat( buf, "LM9831" ); break; case 2: strcat( buf, "LM9830 --> unsupported!!!" ); res = SANE_STATUS_INVAL; break; default: DBG( _DBG_INFO, "Unknown chip v%d", value ); res = SANE_STATUS_INVAL; break; } DBG( _DBG_INFO, "%s\n", buf ); return res; } /** well, this is more or less a reset function, for LM9831 based devices * we issue a real reset command, while for LM9832/3 based devices, checking * and resetting register 7 will be enough... */ static SANE_Status usbio_ResetLM983x( Plustek_Device *dev ) { SANE_Byte value; HWDef *hw = &dev->usbDev.HwSetting; if( _LM9831 == hw->chip ) { DBG( _DBG_INFO," * resetting LM9831 device!\n"); _UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0)); _UIO( sanei_lm983x_write_byte( dev->fd, 0x07,0x20)); _UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0)); _UIO( usbio_ReadReg( dev->fd, 0x07, &value)); if (value != 0) { DBG( _DBG_ERROR, "usbio_ResetLM983x: reset was not " "successful, status=%d\n", value ); return SANE_STATUS_INVAL; } } else { _UIO( usbio_ReadReg( dev->fd, 0x07, &value)); if (value != 0 ) { DBG( _DBG_INFO," * setting device to idle state!\n"); _UIO( sanei_lm983x_write_byte( dev->fd, 0x07, 0)); } } return SANE_STATUS_GOOD; } /* END PLUSTEK-USBIO.C ......................................................*/ sane-backends-1.0.27/backend/plustek-usbshading.c0000664000175000017500000026747212775277260016632 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbshading.c * @brief Calibration routines. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2013 Gerhard Jaeger * * History: * - 0.40 - starting version of the USB support * - 0.41 - minor fixes * - added workaround stuff for EPSON1250 * - 0.42 - added workaround stuff for UMAX 3400 * - 0.43 - added call to usb_switchLamp before reading dark data * - 0.44 - added more debug output and bypass calibration * - added dump of shading data * - 0.45 - added coarse calibration for CIS devices * - added _WAF_SKIP_FINE to skip the results of fine calibration * - CanoScan fixes and fine-tuning * - 0.46 - CanoScan will now be calibrated by code in plustek-usbcal.c * - added functions to save and restore calibration data from a file * - fixed some TPA issues * - 0.47 - made calibration work on big-endian machines * - 0.48 - added more debug output * - added usb_AutoWarmup() * - 0.49 - a_bRegs is now part of the device structure * - using now PhyDpi.y as selector for the motor MCLK range * - 0.50 - readded kCIS670 to add 5% extra to LiDE20 fine calibration * - fixed line statistics and added data output * - 0.51 - added fine calibration cache * - 0.52 - added get_ptrs to let various sensororders work * correctly * - fixed warning condition * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /************** global stuff - I hate it, but we need it... ******************/ #define _MAX_AUTO_WARMUP 60 /**< number of loops */ #define _AUTO_SLEEP 1 /**< time to sleep, when lamp is not stable */ #define _AUTO_THRESH 60 /**< threshold for stop waiting (normal lamp) */ #define _AUTO_TPA_THRESH 40 /**< threshold for stop waiting (TPA lamp) */ #define _MAX_GAIN_LOOPS 10 /**< max number of loops for coarse calibration */ #define _TLOOPS 3 /**< test loops for transfer rate measurement */ #define SWAP_COARSE #define SWAP_FINE /************************** static variables *********************************/ static RGBUShortDef Gain_Hilight; static RGBUShortDef Gain_NegHilight; static RGBByteDef Gain_Reg; static u_long m_dwPixels; static ScanParam m_ScanParam; static u_long m_dwIdealGain; static double dMCLK, dExpect, dMax; static double dMCLK_ADF; /** do some statistics... */ static void usb_line_statistics( char *cmt, u_short* buf, u_long dim_x, SANE_Bool color ) { char fn[50]; int i, channel; u_long dw, imad, imid, alld, cld, cud; u_short mid, mad, aved, lbd, ubd, tmp; MonoWordDef *pvd, *pvd2; FILE *fp; SANE_Bool swap = usb_HostSwap(); pvd = pvd2 = (MonoWordDef*)buf; if( color ) channel = 3; else channel = 1; for( i = 0; i < channel; i++ ) { mid = 0xFFFF; mad = 0; imid = 0; imad = 0; alld = 0; fp = NULL; if( DBG_LEVEL >= _DBG_DCALDATA ) { sprintf( fn, "%scal%u.dat", cmt, i ); fp = fopen( fn, "w+b" ); if( fp == NULL ) DBG( _DBG_ERROR, "Could not open %s\n", fn ); } /* do the standard min/max stuff */ for( dw = 0; dw < dim_x; pvd++, dw++ ) { if( swap ) tmp = _LOBYTE(pvd->Mono) * 256 + _HIBYTE(pvd->Mono); else tmp = pvd->Mono; if( tmp > mad ) { mad = tmp; imad = dw; } if( tmp < mid ) { mid = tmp; imid = dw; } if( fp ) fprintf(fp, "%u\n", tmp ); alld += tmp; } if( fp ) fclose(fp); /* calculate average and 5% limit */ aved = (u_short)(alld/dim_x); lbd = aved - 0.05*aved; ubd = aved + 0.05*aved; cld = 0; cud = 0; /* find the number of values beyond the 5% limits */ for( dw = 0; dw < dim_x; pvd2++, dw++ ) { if( swap ) tmp = _LOBYTE(pvd2->Mono) * 256 + _HIBYTE(pvd2->Mono); else tmp = pvd2->Mono; if( tmp > ubd ) cud++; if( tmp < lbd ) cld++; } DBG( _DBG_INFO2, "Color[%u] (%s): %lu all " "min=%u(%lu) max=%u(%lu) ave=%u\n", i, cmt, dim_x, mid, imid, mad, imad, aved); DBG( _DBG_INFO2, "5%%: low@%u (count=%lu), upper@%u (count=%lu)\n", lbd, cld, ubd, cud); } } /** */ static void usb_PrepareFineCal( Plustek_Device *dev, ScanParam *tmp_sp, u_short cal_dpi ) { ScanParam *sp = &dev->scanning.sParam; DCapsDef *scaps = &dev->usbDev.Caps; *tmp_sp = *sp; if( dev->adj.cacheCalData ) { DBG( _DBG_INFO2, "* Cal-cache active, tweaking scanparams" " - DPI=%u!\n", cal_dpi ); tmp_sp->UserDpi.x = usb_SetAsicDpiX(dev, sp->UserDpi.x ); if( cal_dpi != 0 ) tmp_sp->UserDpi.x = cal_dpi; tmp_sp->PhyDpi = scaps->OpticDpi; tmp_sp->Origin.x = 0; tmp_sp->Size.dwPixels = scaps->Normal.Size.x * usb_SetAsicDpiX(dev, tmp_sp->UserDpi.x)/ 300UL; } #if 0 if( tmp_sp->PhyDpi.x > 75) tmp_sp->Size.dwLines = 64; else #endif tmp_sp->Size.dwLines = 32; tmp_sp->Origin.y = 0; tmp_sp->bBitDepth = 16; tmp_sp->UserDpi.y = scaps->OpticDpi.y; tmp_sp->Size.dwBytes = tmp_sp->Size.dwPixels * 2 * tmp_sp->bChannels; if( usb_IsCISDevice(dev) && (tmp_sp->bDataType == SCANDATATYPE_Color)) { tmp_sp->Size.dwBytes *= 3; } tmp_sp->dMCLK = dMCLK; } /** */ static double usb_GetMCLK( Plustek_Device *dev, ScanParam *param ) { int idx, i; double mclk; ClkMotorDef *clk; HWDef *hw = &dev->usbDev.HwSetting; clk = usb_GetMotorSet( hw->motorModel ); idx = 0; for( i = 0; i < _MAX_CLK; i++ ) { if( param->PhyDpi.y <= dpi_ranges[i] ) break; idx++; } if( idx >= _MAX_CLK ) idx = _MAX_CLK - 1; if( param->bDataType != SCANDATATYPE_Color ) { if( param->bBitDepth > 8 ) mclk = clk->gray_mclk_16[idx]; else mclk = clk->gray_mclk_8[idx]; } else { if( param->bBitDepth > 8 ) mclk = clk->color_mclk_16[idx]; else mclk = clk->color_mclk_8[idx]; } DBG( _DBG_INFO, "GETMCLK[%u/%u], using entry %u: %.3f, %u\n", hw->motorModel, param->bDataType, idx, mclk, param->PhyDpi.x ); return mclk; } /** usb_SetMCLK * get the MCLK out of our table */ static void usb_SetMCLK( Plustek_Device *dev, ScanParam *param ) { HWDef *hw = &dev->usbDev.HwSetting; dMCLK = usb_GetMCLK( dev, param ); param->dMCLK = dMCLK; DBG( _DBG_INFO, "SETMCLK[%u/%u]: %.3f\n", hw->motorModel, param->bDataType, dMCLK ); } /** usb_SetDarkShading * download the dark shading data to Merlins' DRAM */ static SANE_Bool usb_SetDarkShading( Plustek_Device *dev, u_char channel, void *coeff_buffer, u_short wCount ) { int res; u_char *regs = dev->usbDev.a_bRegs; regs[0x03] = 0; if( channel == CHANNEL_green ) regs[0x03] |= 4; else if( channel == CHANNEL_blue ) regs[0x03] |= 8; if( usbio_WriteReg( dev->fd, 0x03, regs[0x03] )) { /* Dataport address is always 0 for setting offset coefficient */ regs[0x04] = 0; regs[0x05] = 0; res = sanei_lm983x_write( dev->fd, 0x04, ®s[0x04], 2, SANE_TRUE ); /* Download offset coefficients */ if( SANE_STATUS_GOOD == res ) { res = sanei_lm983x_write( dev->fd, 0x06, (u_char*)coeff_buffer, wCount, SANE_FALSE ); if( SANE_STATUS_GOOD == res ) return SANE_TRUE; } } DBG( _DBG_ERROR, "usb_SetDarkShading() failed\n" ); return SANE_FALSE; } /** usb_SetWhiteShading * download the white shading data to Merlins' DRAM */ static SANE_Bool usb_SetWhiteShading( Plustek_Device *dev, u_char channel, void *data_buffer, u_short wCount ) { int res; u_char *regs = dev->usbDev.a_bRegs; regs[0x03] = 1; if (channel == CHANNEL_green) regs [0x03] |= 4; else if (channel == CHANNEL_blue) regs[0x03] |= 8; if( usbio_WriteReg( dev->fd, 0x03, regs[0x03] )) { /* Dataport address is always 0 for setting offset coefficient */ regs[0x04] = 0; regs[0x05] = 0; res = sanei_lm983x_write( dev->fd, 0x04, ®s[0x04], 2, SANE_TRUE ); /* Download offset coefficients */ if( SANE_STATUS_GOOD == res ) { res = sanei_lm983x_write(dev->fd, 0x06, (u_char*)data_buffer, wCount, SANE_FALSE ); if( SANE_STATUS_GOOD == res ) return SANE_TRUE; } } DBG( _DBG_ERROR, "usb_SetWhiteShading() failed\n" ); return SANE_FALSE; } /** usb_GetSWOffsetGain4TPA * preset the offset and gain parameter for fine calibration for * TPA/ADF scanning */ static void usb_GetSWOffsetGain4TPA( Plustek_Device *dev ) { ScanParam *param = &dev->scanning.sParam; DCapsDef *sCaps = &dev->usbDev.Caps; switch( sCaps->bCCD ) { case kEPSON: DBG( _DBG_INFO2, "kEPSON TPA adjustments\n" ); param->swGain[0] = 1000; param->swGain[1] = 1000; param->swGain[2] = 1000; break; } } /** usb_GetSWOffsetGain * preset the offset and gain parameter for fine calibration for normal * scanning */ static void usb_GetSWOffsetGain( Plustek_Device *dev ) { ScanParam *param = &dev->scanning.sParam; DCapsDef *sCaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; param->swOffset[0] = 0; param->swOffset[1] = 0; param->swOffset[2] = 0; param->swGain[0] = 1000; param->swGain[1] = 1000; param->swGain[2] = 1000; if( param->bSource != SOURCE_Reflection ) { usb_GetSWOffsetGain4TPA( dev ); return; } /* only valid for normal scanning... */ switch( sCaps->bCCD ) { case kEPSON: DBG( _DBG_INFO2, "kEPSON adjustments\n" ); #if 0 param->swGain[0] = 800; param->swGain[1] = 800; param->swGain[2] = 800; #endif break; case kNECSLIM: DBG( _DBG_INFO2, "kNECSLIM adjustments\n" ); if( param->PhyDpi.x <= 150 ) { param->swOffset[0] = 600; param->swOffset[1] = 500; param->swOffset[2] = 300; param->swGain[0] = 960; param->swGain[1] = 970; param->swGain[2] = 1000; } else if (param->PhyDpi.x <= 300) { param->swOffset[0] = 700; param->swOffset[1] = 600; param->swOffset[2] = 400; param->swGain[0] = 967; param->swGain[1] = 980; param->swGain[2] = 1000; } else { param->swOffset[0] = 900; param->swOffset[1] = 850; param->swOffset[2] = 620; param->swGain[0] = 965; param->swGain[1] = 980; param->swGain[2] = 1000; } break; case kNEC8861: DBG( _DBG_INFO2, "kNEC8861 adjustments\n" ); break; case kCIS670: DBG( _DBG_INFO2, "kCIS670 adjustments\n" ); if(param->bDataType == SCANDATATYPE_Color) { param->swGain[0] = param->swGain[1] = param->swGain[2] = 952; param->swOffset[0] = param->swOffset[1] = param->swOffset[2] = 1000; } break; #if 0 case kCIS650: case kCIS1220: DBG( _DBG_INFO2, "kCIS adjustments\n" ); if(param->bDataType == SCANDATATYPE_Color) { param->swGain[0] = param->swGain[1] = param->swGain[2] = 952; param->swOffset[0] = param->swOffset[1] = param->swOffset[2] = 1000; } break; case kCIS1240: DBG( _DBG_INFO2, "kCIS1240 adjustments\n" ); if(param->bDataType == SCANDATATYPE_Color) { param->swGain[0] = 950; param->swGain[1] = 950; param->swGain[2] = 900; param->swOffset[0] = param->swOffset[1] = param->swOffset[2] = 0; /*1000;*/ } break; #endif case kNEC3799: DBG( _DBG_INFO2, "kNEC3799 adjustments\n" ); if( sCaps->bPCB == 2 ) { if( param->PhyDpi.x <= 150 ) { param->swOffset[0] = 600; param->swOffset[1] = 500; param->swOffset[2] = 300; param->swGain[0] = 960; param->swGain[1] = 970; param->swGain[2] = 1000; } else if (param->PhyDpi.x <= 300) { param->swOffset[0] = 700; param->swOffset[1] = 600; param->swOffset[2] = 400; param->swGain[0] = 967; param->swGain[1] = 980; param->swGain[2] = 1000; } else { param->swOffset[0] = 900; param->swOffset[1] = 850; param->swOffset[2] = 620; param->swGain[0] = 965; param->swGain[1] = 980; param->swGain[2] = 1000; } } else if( hw->motorModel == MODEL_KaoHsiung ) { param->swOffset[0] = 1950; param->swOffset[1] = 1700; param->swOffset[2] = 1250; param->swGain[0] = 955; param->swGain[1] = 950; param->swGain[2] = 1000; } else { /* MODEL_Hualien */ if( param->PhyDpi.x <= 300 ) { if( param->bBitDepth > 8 ) { param->swOffset[0] = 0; param->swOffset[1] = 0; param->swOffset[2] = -300; param->swGain[0] = 970; param->swGain[1] = 985; param->swGain[2] = 1050; } else { param->swOffset[0] = -485; param->swOffset[1] = -375; param->swOffset[2] = -628; param->swGain[0] = 970; param->swGain[1] = 980; param->swGain[2] = 1050; } } else { if( param->bBitDepth > 8 ) { param->swOffset[0] = 1150; param->swOffset[1] = 1000; param->swOffset[2] = 700; param->swGain[0] = 990; param->swGain[1] = 1000; param->swGain[2] = 1050; } else { param->swOffset[0] = -30; param->swOffset[1] = 0; param->swOffset[2] = -250; param->swGain[0] = 985; param->swGain[1] = 995; param->swGain[2] = 1050; } } } break; case kSONY548: DBG( _DBG_INFO2, "kSONY548 adjustments\n" ); if(param->bDataType == SCANDATATYPE_Color) { if(param->PhyDpi.x <= 75) { param->swOffset[0] = 650; param->swOffset[1] = 850; param->swOffset[2] = 500; param->swGain[0] = 980; param->swGain[1] = 1004; param->swGain[2] = 1036; } else if(param->PhyDpi.x <= 300) { param->swOffset[0] = 700; param->swOffset[1] = 900; param->swOffset[2] = 550; param->swGain[0] = 970; param->swGain[1] = 995; param->swGain[2] = 1020; } else if(param->PhyDpi.x <= 400) { param->swOffset[0] = 770; param->swOffset[1] = 1010; param->swOffset[2] = 600; param->swGain[0] = 970; param->swGain[1] = 993; param->swGain[2] = 1023; } else { param->swOffset[0] = 380; param->swOffset[1] = 920; param->swOffset[2] = 450; param->swGain[0] = 957; param->swGain[1] = 980; param->swGain[2] = 1008; } } else { if(param->PhyDpi.x <= 75) { param->swOffset[1] = 1250; param->swGain[1] = 950; } else if(param->PhyDpi.x <= 300) { param->swOffset[1] = 1250; param->swGain[1] = 950; } else if(param->PhyDpi.x <= 400) { param->swOffset[1] = 1250; param->swGain[1] = 950; } else { param->swOffset[1] = 1250; param->swGain[1] = 950; } } break; case kNEC3778: DBG( _DBG_INFO2, "kNEC3778 adjustments\n" ); if((_LM9831 == hw->chip) && (param->PhyDpi.x <= 300)) { param->swOffset[0] = 0; param->swOffset[1] = 0; param->swOffset[2] = 0; param->swGain[0] = 900; param->swGain[1] = 920; param->swGain[2] = 980; } else if( hw->motorModel == MODEL_HuaLien && param->PhyDpi.x > 800) { param->swOffset[0] = 0; param->swOffset[1] = 0; param->swOffset[2] = -200; param->swGain[0] = 980; param->swGain[1] = 930; param->swGain[2] = 1080; } else { param->swOffset[0] = -304; param->swOffset[1] = -304; param->swOffset[2] = -304; param->swGain[0] = 910; param->swGain[1] = 920; param->swGain[2] = 975; } if(param->bDataType == SCANDATATYPE_BW && param->PhyDpi.x <= 300) { param->swOffset[1] = 1000; param->swGain[1] = 1000; } break; } } /** according to the pixel values, */ static u_char usb_GetNewGain( Plustek_Device *dev, u_short wMax, int channel ) { double dRatio, dAmp; u_long dwInc, dwDec; u_char bGain; if( !wMax ) wMax = 1; dAmp = 0.93 + 0.067 * dev->usbDev.a_bRegs[0x3b+channel]; if((m_dwIdealGain / (wMax / dAmp)) < 3) { dRatio = ((double) m_dwIdealGain * dAmp / wMax - 0.93) / 0.067; if(ceil(dRatio) > 0x3f) return 0x3f; dwInc = (u_long)((0.93 + ceil (dRatio) * 0.067) * wMax / dAmp); dwDec = (u_long)((0.93 + floor (dRatio) * 0.067) * wMax / dAmp); if((dwInc >= 0xff00) || (labs (dwInc - m_dwIdealGain) > labs(dwDec - m_dwIdealGain))) { bGain = (u_char)floor(dRatio); } else { bGain = (u_char)ceil(dRatio); } } else { dRatio = m_dwIdealGain / (wMax / dAmp); dAmp = floor((dRatio / 3 - 0.93)/0.067); if( dAmp > 31 ) dAmp = 31; bGain = (u_char)dAmp + 32; } if( bGain > 0x3f ) { DBG( _DBG_INFO, "* GAIN Overflow!!!\n" ); bGain = 0x3f; } return bGain; } /** limit and set register given by address * @param gain - * @param reg - */ static void setAdjGain( int gain, u_char *reg ) { if( gain >= 0 ) { if( gain > 0x3f ) *reg = 0x3f; else *reg = gain; } } /** * @param channel - 0 = red, 1 = green, 2 = blue * @param max - * @param ideal - * @param l_on - * @param l_off - * @return */ static SANE_Bool adjLampSetting( Plustek_Device *dev, int channel, u_long max, u_long ideal, u_short l_on, u_short *l_off ) { SANE_Bool adj = SANE_FALSE; u_long lamp_on; /* so if the image was too bright, we dim the lamps by 3% */ if( max > ideal ) { lamp_on = (*l_off) - l_on; lamp_on = (lamp_on * 97)/100; *l_off = l_on + lamp_on; DBG( _DBG_INFO2, "lamp(%u) adjust (-3%%): %i %i\n", channel, l_on, *l_off ); adj = SANE_TRUE; } /* if the image was too dull, increase lamp by 1% */ if( dev->usbDev.a_bRegs[0x3b + channel] == 63 ) { lamp_on = (*l_off) - l_on; lamp_on += (lamp_on/100); *l_off = l_on + lamp_on; DBG( _DBG_INFO2, "lamp(%u) adjust (+1%%): %i %i\n", channel, l_on, *l_off ); adj = SANE_TRUE; } return adj; } /** usb_AdjustGain * function to perform the "coarse calibration step" part 1. * We scan reference image pixels to determine the optimum coarse gain settings * for R, G, B. (Analog gain and offset prior to ADC). These coefficients are * applied at the line rate during normal scanning. * The scanned line should contain a white strip with some black at the * beginning. The function searches for the maximum value which corresponds to * the maximum white value. * Affects register 0x3b, 0x3c and 0x3d * */ static SANE_Bool usb_AdjustGain( Plustek_Device *dev, int fNegative ) { char tmp[40]; int i; double min_mclk; ScanDef *scanning = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_long *scanbuf = scanning->pScanBuffer; u_char *regs = dev->usbDev.a_bRegs; u_long dw, start, end, len; SANE_Bool fRepeatITA = SANE_TRUE; if( usb_IsEscPressed()) return SANE_FALSE; bMaxITA = 0xff; DBG( _DBG_INFO, "#########################\n" ); DBG( _DBG_INFO, "usb_AdjustGain()\n" ); if((dev->adj.rgain != -1) && (dev->adj.ggain != -1) && (dev->adj.bgain != -1)) { setAdjGain( dev->adj.rgain, ®s[0x3b] ); setAdjGain( dev->adj.ggain, ®s[0x3c] ); setAdjGain( dev->adj.bgain, ®s[0x3d] ); DBG( _DBG_INFO, "- function skipped, using frontend values!\n" ); return SANE_TRUE; } min_mclk = usb_GetMCLK( dev, &scanning->sParam ); /* define the strip to scan for coarse calibration */ m_ScanParam.Size.dwLines = 1; m_ScanParam.Size.dwPixels = scaps->Normal.Size.x * scaps->OpticDpi.x / 300UL; m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2 * m_ScanParam.bChannels; if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color) m_ScanParam.Size.dwBytes *= 3; m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart * 300UL / scaps->OpticDpi.x); m_ScanParam.bCalibration = PARAM_Gain; start = 0; len = m_ScanParam.Size.dwPixels; if( scanning->sParam.bSource == SOURCE_Transparency ) { start = scaps->Positive.DataOrigin.x * scaps->OpticDpi.x / 300UL; len = scaps->Positive.Size.x * scaps->OpticDpi.x / 300UL; } else if( scanning->sParam.bSource == SOURCE_Negative ) { start = scaps->Negative.DataOrigin.x * scaps->OpticDpi.x / 300UL; len = scaps->Negative.Size.x * scaps->OpticDpi.x / 300UL; } end = start + len; start = ((u_long)dev->usbDev.pSource->DataOrigin.x*scaps->OpticDpi.x/300UL); len = ((u_long)dev->usbDev.pSource->Size.x * scaps->OpticDpi.x / 300UL); DBG( _DBG_INFO2, "Coarse Calibration Strip:\n" ); DBG( _DBG_INFO2, "Lines = %lu\n", m_ScanParam.Size.dwLines ); DBG( _DBG_INFO2, "Pixels = %lu\n", m_ScanParam.Size.dwPixels ); DBG( _DBG_INFO2, "Bytes = %lu\n", m_ScanParam.Size.dwBytes ); DBG( _DBG_INFO2, "Origin.X = %u\n", m_ScanParam.Origin.x ); DBG( _DBG_INFO2, "Start = %lu\n", start ); DBG( _DBG_INFO2, "Len = %lu\n", len ); DBG( _DBG_INFO2, "End = %lu\n", end ); DBG( _DBG_INFO, "MIN MCLK = %.2f\n", min_mclk ); i = 0; TOGAIN: m_ScanParam.dMCLK = dMCLK; if( !usb_SetScanParameters( dev, &m_ScanParam )) return SANE_FALSE; if( !usb_ScanBegin( dev, SANE_FALSE) || !usb_ScanReadImage( dev, scanbuf, m_ScanParam.Size.dwPhyBytes ) || !usb_ScanEnd( dev )) { DBG( _DBG_ERROR, "usb_AdjustGain() failed\n" ); return SANE_FALSE; } DBG( _DBG_INFO2, "PhyBytes = %lu\n", m_ScanParam.Size.dwPhyBytes ); DBG( _DBG_INFO2, "PhyPixels = %lu\n", m_ScanParam.Size.dwPhyPixels ); if( end > m_ScanParam.Size.dwPhyPixels ) end = m_ScanParam.Size.dwPhyPixels; sprintf( tmp, "coarse-gain-%u.raw", i++ ); dumpPicInit(&m_ScanParam, tmp); dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwPhyBytes, 0); #ifdef SWAP_COARSE if(usb_HostSwap()) #endif usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwPhyBytes ); if( fNegative ) { if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { RGBULongDef rgb, rgbSum; u_long dwLoop = len / 20 * 20; u_long dw10, dwGray, dwGrayMax; rgb.Red = rgb.Green = rgb.Blue = dwGrayMax = 0; for( dw = start; dwLoop; dwLoop-- ) { rgbSum.Red = rgbSum.Green = rgbSum.Blue = 0; for( dw10 = 20; dw10--; dw++ ) { rgbSum.Red += (u_long)(((RGBULongDef*)scanbuf)[dw].Red); rgbSum.Green += (u_long)(((RGBULongDef*)scanbuf)[dw].Green); rgbSum.Blue += (u_long)(((RGBULongDef*)scanbuf)[dw].Blue); } /* do some weighting of the color planes for negatives */ dwGray = (rgbSum.Red * 30UL + rgbSum.Green * 59UL + rgbSum.Blue * 11UL) / 100UL; if( fNegative == 1 || rgbSum.Red > rgbSum.Green) { if( dwGray > dwGrayMax ) { dwGrayMax = dwGray; rgb.Red = rgbSum.Red; rgb.Green = rgbSum.Green; rgb.Blue = rgbSum.Blue; } } } Gain_Hilight.Red = (u_short)(rgb.Red / 20UL); Gain_Hilight.Green = (u_short)(rgb.Green / 20UL); Gain_Hilight.Blue = (u_short)(rgb.Blue / 20UL); DBG(_DBG_INFO2, "MAX(R,G,B)= 0x%04x(%u), 0x%04x(%u), 0x%04x(%u)\n", Gain_Hilight.Red, Gain_Hilight.Red, Gain_Hilight.Green, Gain_Hilight.Green, Gain_Hilight.Blue, Gain_Hilight.Blue ); regs[0x3b] = usb_GetNewGain(dev,Gain_Hilight.Red, 0 ); regs[0x3c] = usb_GetNewGain(dev,Gain_Hilight.Green, 1 ); regs[0x3d] = usb_GetNewGain(dev,Gain_Hilight.Blue, 2 ); } else { u_long dwMax = 0, dwSum; u_long dwLoop = len / 20 * 20; u_long dw10; for( dw = start; dwLoop; dwLoop-- ) { dwSum = 0; for( dw10 = 20; dw10--; dw++ ) dwSum += (u_long)((u_short*)scanbuf)[dw]; if((fNegative == 1) || (dwSum < 0x6000 * 20)) { if( dwMax < dwSum ) dwMax = dwSum; } } Gain_Hilight.Red = Gain_Hilight.Green = Gain_Hilight.Blue = (u_short)(dwMax / 20UL); Gain_Reg.Red = Gain_Reg.Green = Gain_Reg.Blue = regs[0x3b] = regs[0x3c] = regs[0x3d] = usb_GetNewGain(dev,Gain_Hilight.Green,1); } } else { if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { RGBUShortDef max_rgb, min_rgb, tmp_rgb; u_long dwR, dwG, dwB; u_long dwDiv = 10; u_long dwLoop1 = len / dwDiv, dwLoop2; max_rgb.Red = max_rgb.Green = max_rgb.Blue = 0; min_rgb.Red = min_rgb.Green = min_rgb.Blue = 0xffff; /* find out the max pixel value for R, G, B */ for( dw = start; dwLoop1; dwLoop1-- ) { /* do some averaging... */ for (dwLoop2 = dwDiv, dwR = dwG = dwB = 0; dwLoop2; dwLoop2--, dw++) { if( usb_IsCISDevice(dev)) { dwR += ((u_short*)scanbuf)[dw]; dwG += ((u_short*)scanbuf)[dw+m_ScanParam.Size.dwPhyPixels+1]; dwB += ((u_short*)scanbuf)[dw+(m_ScanParam.Size.dwPhyPixels+1)*2]; } else { dwR += ((RGBUShortDef*)scanbuf)[dw].Red; dwG += ((RGBUShortDef*)scanbuf)[dw].Green; dwB += ((RGBUShortDef*)scanbuf)[dw].Blue; } } dwR = dwR / dwDiv; dwG = dwG / dwDiv; dwB = dwB / dwDiv; if(max_rgb.Red < dwR) max_rgb.Red = dwR; if(max_rgb.Green < dwG) max_rgb.Green = dwG; if(max_rgb.Blue < dwB) max_rgb.Blue = dwB; if(min_rgb.Red > dwR) min_rgb.Red = dwR; if(min_rgb.Green > dwG) min_rgb.Green = dwG; if(min_rgb.Blue > dwB) min_rgb.Blue = dwB; } DBG(_DBG_INFO2, "MAX(R,G,B)= 0x%04x(%u), 0x%04x(%u), 0x%04x(%u)\n", max_rgb.Red, max_rgb.Red, max_rgb.Green, max_rgb.Green, max_rgb.Blue, max_rgb.Blue ); DBG(_DBG_INFO2, "MIN(R,G,B)= 0x%04x(%u), 0x%04x(%u), 0x%04x(%u)\n", min_rgb.Red, min_rgb.Red, min_rgb.Green, min_rgb.Green, min_rgb.Blue, min_rgb.Blue ); /* on CIS scanner, we use the min value, on CCD the max value * for adjusting the gain */ tmp_rgb = max_rgb; if( usb_IsCISDevice(dev)) tmp_rgb = min_rgb; DBG(_DBG_INFO2, "CUR(R,G,B)= 0x%04x(%u), 0x%04x(%u), 0x%04x(%u)\n", tmp_rgb.Red, tmp_rgb.Red, tmp_rgb.Green, tmp_rgb.Green, tmp_rgb.Blue, tmp_rgb.Blue); /* m_dwIdealGain = IDEAL_GainNormal; */ /* min(min(rgb.wRed, rgb.wGreen), rgb.wBlue) */ regs[0x3b] = usb_GetNewGain( dev, tmp_rgb.Red, 0 ); regs[0x3c] = usb_GetNewGain( dev, tmp_rgb.Green, 1 ); regs[0x3d] = usb_GetNewGain( dev, tmp_rgb.Blue, 2 ); if( !_IS_PLUSTEKMOTOR(hw->motorModel)) { SANE_Bool adj = SANE_FALSE; /* on CIS devices, we can control the lamp off settings */ if( usb_IsCISDevice(dev)) { /* m_dwIdealGain = IDEAL_GainNormal; */ if( adjLampSetting( dev, CHANNEL_red, tmp_rgb.Red, m_dwIdealGain, hw->red_lamp_on, &hw->red_lamp_off )) { adj = SANE_TRUE; } if( adjLampSetting( dev, CHANNEL_green, tmp_rgb.Green, m_dwIdealGain, hw->green_lamp_on, &hw->green_lamp_off )) { adj = SANE_TRUE; } if( adjLampSetting( dev, CHANNEL_blue, tmp_rgb.Blue, m_dwIdealGain, hw->blue_lamp_on, &hw->blue_lamp_off)){ adj = SANE_TRUE; } /* on any adjustment, set the registers... */ if( adj ) { usb_AdjustLamps( dev, SANE_TRUE ); if( i < _MAX_GAIN_LOOPS ) goto TOGAIN; } } else { if((!regs[0x3b] || !regs[0x3c] || !regs[0x3d]) && dMCLK > min_mclk) { scanning->sParam.dMCLK = dMCLK = dMCLK - 0.5; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; adj = SANE_TRUE; } else if(((regs[0x3b] == 63) || (regs[0x3c] == 63) || (regs[0x3d] == 63)) && (dMCLK < 10)) { scanning->sParam.dMCLK = dMCLK = dMCLK + 0.5; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; adj = SANE_TRUE; } if( adj ) { if( i < _MAX_GAIN_LOOPS ) goto TOGAIN; } } } else { /* for MODEL KaoHsiung 1200 scanner multi-straight-line bug at * 1200 dpi color mode */ if( hw->motorModel == MODEL_KaoHsiung && scaps->bCCD == kNEC3778 && dMCLK>= 5.5 && !regs[0x3c]){ regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; scanning->sParam.dMCLK = dMCLK = dMCLK - 1.5; goto TOGAIN; } else if( hw->motorModel == MODEL_HuaLien && scaps->bCCD == kNEC3799 && fRepeatITA ) { if((!regs[0x3b] || !regs[0x3c] || !regs[0x3d]) && dMCLK > 3.0) { scanning->sParam.dMCLK = dMCLK = dMCLK - 0.5; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; goto TOGAIN; } else if(((regs[0x3b] == 63) || (regs[0x3c] == 63) || (regs[0x3d] == 63)) && (dMCLK < 10)) { scanning->sParam.dMCLK = dMCLK = dMCLK + 0.5; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; goto TOGAIN; } bMaxITA = (u_char)floor((dMCLK + 1) / 2); fRepeatITA = SANE_FALSE; } } } else { u_short w_max = 0, w_min = 0xffff, w_tmp; for( dw = start; dw < end; dw++ ) { if( w_max < ((u_short*)scanbuf)[dw]) w_max = ((u_short*)scanbuf)[dw]; if( w_min > ((u_short*)scanbuf)[dw]) w_min = ((u_short*)scanbuf)[dw]; } w_tmp = w_max; if( usb_IsCISDevice(dev)) w_tmp = w_min; regs[0x3b] = regs[0x3c] = regs[0x3d] = usb_GetNewGain(dev, w_tmp, 0); DBG(_DBG_INFO2, "MAX(G)= 0x%04x(%u)\n", w_max, w_max ); DBG(_DBG_INFO2, "MIN(G)= 0x%04x(%u)\n", w_min, w_min ); DBG(_DBG_INFO2, "CUR(G)= 0x%04x(%u)\n", w_tmp, w_tmp ); /* m_dwIdealGain = IDEAL_GainNormal; */ if( !_IS_PLUSTEKMOTOR(hw->motorModel)) { SANE_Bool adj = SANE_FALSE; /* on CIS devices, we can control the lamp off settings */ if( usb_IsCISDevice(dev)) { if( adjLampSetting( dev, CHANNEL_green, w_tmp, m_dwIdealGain, hw->green_lamp_on, &hw->green_lamp_off )) { adj = SANE_TRUE; } /* on any adjustment, set the registers... */ if( adj ) { usb_AdjustLamps( dev, SANE_TRUE ); if( i < _MAX_GAIN_LOOPS ) goto TOGAIN; } } else { if( !regs[0x3b] && (dMCLK > min_mclk)) { scanning->sParam.dMCLK = dMCLK = dMCLK - 0.5; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; adj = SANE_TRUE; } else if((regs[0x3b] == 63) && (dMCLK < 20)) { scanning->sParam.dMCLK = dMCLK = dMCLK + 0.5; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; adj = SANE_TRUE; } if( adj ) { if( i < _MAX_GAIN_LOOPS ) goto TOGAIN; } } } } } DBG( _DBG_INFO2, "REG[0x3b] = %u\n", regs[0x3b] ); DBG( _DBG_INFO2, "REG[0x3c] = %u\n", regs[0x3c] ); DBG( _DBG_INFO2, "REG[0x3d] = %u\n", regs[0x3d] ); DBG( _DBG_INFO2, "red_lamp_on = %u\n", hw->red_lamp_on ); DBG( _DBG_INFO2, "red_lamp_off = %u\n", hw->red_lamp_off ); DBG( _DBG_INFO2, "green_lamp_on = %u\n", hw->green_lamp_on ); DBG( _DBG_INFO2, "green_lamp_off = %u\n", hw->green_lamp_off ); DBG( _DBG_INFO2, "blue_lamp_on = %u\n", hw->blue_lamp_on ); DBG( _DBG_INFO2, "blue_lamp_off = %u\n", hw->blue_lamp_off ); DBG( _DBG_INFO, "usb_AdjustGain() done.\n" ); return SANE_TRUE; } /** usb_GetNewOffset * @param pdwSum - * @param pdwDiff - * @param pcOffset - * @param pIdeal - * @param channel - * @param cAdjust - */ static void usb_GetNewOffset( Plustek_Device *dev, u_long *pdwSum, u_long *pdwDiff, signed char *pcOffset, u_char *pIdeal, u_long channel, signed char cAdjust ) { /* IDEAL_Offset is currently set to 0x1000 = 4096 */ u_long dwIdealOffset = IDEAL_Offset; if( pdwSum[channel] > dwIdealOffset ) { /* Over ideal value */ pdwSum[channel] -= dwIdealOffset; if( pdwSum[channel] < pdwDiff[channel] ) { /* New offset is better than old one */ pdwDiff[channel] = pdwSum[channel]; pIdeal[channel] = dev->usbDev.a_bRegs[0x38 + channel]; } pcOffset[channel] -= cAdjust; } else { /* Below than ideal value */ pdwSum[channel] = dwIdealOffset - pdwSum [channel]; if( pdwSum[channel] < pdwDiff[channel] ) { /* New offset is better than old one */ pdwDiff[channel] = pdwSum[channel]; pIdeal[channel] = dev->usbDev.a_bRegs[0x38 + channel]; } pcOffset[channel] += cAdjust; } if( pcOffset[channel] >= 0 ) dev->usbDev.a_bRegs[0x38 + channel] = pcOffset[channel]; else dev->usbDev.a_bRegs[0x38 + channel] = (u_char)(32 - pcOffset[channel]); } /** usb_AdjustOffset * function to perform the "coarse calibration step" part 2. * We scan reference image pixels to determine the optimum coarse offset settings * for R, G, B. (Analog gain and offset prior to ADC). These coefficients are * applied at the line rate during normal scanning. * On CIS based devices, we switch the light off, on CCD devices, we use the optical * black pixels. * Affects register 0x38, 0x39 and 0x3a */ static SANE_Bool usb_AdjustOffset( Plustek_Device *dev ) { char tmp[40]; signed char cAdjust = 16; signed char cOffset[3]; u_char bExpect[3]; int i; u_long dw, dwPixels; u_long dwDiff[3], dwSum[3]; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; u_long *scanbuf = dev->scanning.pScanBuffer; if( usb_IsEscPressed()) return SANE_FALSE; DBG( _DBG_INFO, "#########################\n" ); DBG( _DBG_INFO, "usb_AdjustOffset()\n" ); if((dev->adj.rofs != -1) && (dev->adj.gofs != -1) && (dev->adj.bofs != -1)) { regs[0x38] = (dev->adj.rofs & 0x3f); regs[0x39] = (dev->adj.gofs & 0x3f); regs[0x3a] = (dev->adj.bofs & 0x3f); DBG( _DBG_INFO, "- function skipped, using frontend values!\n" ); return SANE_TRUE; } m_ScanParam.Size.dwLines = 1; m_ScanParam.Size.dwPixels = 2550; if( usb_IsCISDevice(dev)) dwPixels = m_ScanParam.Size.dwPixels; else dwPixels = (u_long)(hw->bOpticBlackEnd - hw->bOpticBlackStart ); m_ScanParam.Size.dwPixels = 2550; m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2 * m_ScanParam.bChannels; if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color ) m_ScanParam.Size.dwBytes *= 3; m_ScanParam.Origin.x = (u_short)((u_long)hw->bOpticBlackStart * 300UL / dev->usbDev.Caps.OpticDpi.x); m_ScanParam.bCalibration = PARAM_Offset; m_ScanParam.dMCLK = dMCLK; dwDiff[0] = dwDiff[1] = dwDiff[2] = 0xffff; cOffset[0] = cOffset[1] = cOffset[2] = 0; bExpect[0] = bExpect[1] = bExpect[2] = 0; regs[0x38] = regs[0x39] = regs[0x3a] = 0; if( usb_IsCISDevice(dev)) { /* * if we have dark shading strip, there's no need to switch * the lamp off */ if( dev->usbDev.pSource->DarkShadOrgY >= 0 ) { usb_ModuleToHome( dev, SANE_TRUE ); usb_ModuleMove ( dev, MOVE_Forward, (u_long)dev->usbDev.pSource->DarkShadOrgY ); regs[0x45] &= ~0x10; } else { /* switch lamp off to read dark data... */ regs[0x29] = 0; usb_switchLamp( dev, SANE_FALSE ); } } if( 0 == dwPixels ) { DBG( _DBG_ERROR, "OpticBlackEnd = OpticBlackStart!!!\n" ); return SANE_FALSE; } if( !usb_SetScanParameters( dev, &m_ScanParam )) { DBG( _DBG_ERROR, "usb_AdjustOffset() failed\n" ); return SANE_FALSE; } i = 0; DBG( _DBG_INFO2, "S.dwPixels = %lu\n", m_ScanParam.Size.dwPixels ); DBG( _DBG_INFO2, "dwPixels = %lu\n", dwPixels ); DBG( _DBG_INFO2, "dwPhyBytes = %lu\n", m_ScanParam.Size.dwPhyBytes ); DBG( _DBG_INFO2, "dwPhyPixels = %lu\n", m_ScanParam.Size.dwPhyPixels ); while( cAdjust ) { /* * read data (a white calibration strip - hopefully ;-) */ if((!usb_ScanBegin(dev, SANE_FALSE)) || (!usb_ScanReadImage(dev,scanbuf,m_ScanParam.Size.dwPhyBytes)) || !usb_ScanEnd( dev )) { DBG( _DBG_ERROR, "usb_AdjustOffset() failed\n" ); return SANE_FALSE; } sprintf( tmp, "coarse-off-%u.raw", i++ ); #ifdef SWAP_COARSE if(usb_HostSwap()) usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwPhyBytes ); #endif dumpPicInit(&m_ScanParam, tmp); dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwPhyBytes, 0); if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { dwSum[0] = dwSum[1] = dwSum[2] = 0; for (dw = 0; dw < dwPixels; dw++) { #ifndef SWAP_COARSE dwSum[0] += (u_long)_HILO2WORD(((ColorWordDef*)scanbuf)[dw].HiLo[0]); dwSum[1] += (u_long)_HILO2WORD(((ColorWordDef*)scanbuf)[dw].HiLo[1]); dwSum[2] += (u_long)_HILO2WORD(((ColorWordDef*)scanbuf)[dw].HiLo[2]); #else dwSum[0] += ((RGBUShortDef*)scanbuf)[dw].Red; dwSum[1] += ((RGBUShortDef*)scanbuf)[dw].Green; dwSum[2] += ((RGBUShortDef*)scanbuf)[dw].Blue; #endif } DBG( _DBG_INFO2, "RedSum = %lu, ave = %lu\n", dwSum[0], dwSum[0] /dwPixels ); DBG( _DBG_INFO2, "GreenSum = %lu, ave = %lu\n", dwSum[1], dwSum[1] /dwPixels ); DBG( _DBG_INFO2, "BlueSum = %lu, ave = %lu\n", dwSum[2], dwSum[2] /dwPixels ); /* do averaging for each channel */ dwSum[0] /= dwPixels; dwSum[1] /= dwPixels; dwSum[2] /= dwPixels; usb_GetNewOffset( dev, dwSum, dwDiff, cOffset, bExpect, 0, cAdjust ); usb_GetNewOffset( dev, dwSum, dwDiff, cOffset, bExpect, 1, cAdjust ); usb_GetNewOffset( dev, dwSum, dwDiff, cOffset, bExpect, 2, cAdjust ); DBG( _DBG_INFO2, "RedExpect = %u\n", bExpect[0] ); DBG( _DBG_INFO2, "GreenExpect = %u\n", bExpect[1] ); DBG( _DBG_INFO2, "BlueExpect = %u\n", bExpect[2] ); } else { dwSum[0] = 0; for( dw = 0; dw < dwPixels; dw++ ) { #ifndef SWAP_COARSE dwSum[0] += (u_long)_HILO2WORD(((HiLoDef*)scanbuf)[dw]); #else dwSum[0] += ((u_short*)scanbuf)[dw]; #endif } dwSum [0] /= dwPixels; usb_GetNewOffset( dev, dwSum, dwDiff, cOffset, bExpect, 0, cAdjust ); regs[0x3a] = regs[0x39] = regs[0x38]; DBG(_DBG_INFO2,"Sum = %lu, ave = %lu\n",dwSum[0],dwSum[0]/dwPixels); DBG(_DBG_INFO2,"Expect = %u\n", bExpect[0]); } _UIO(sanei_lm983x_write(dev->fd, 0x38, ®s[0x38], 3, SANE_TRUE)); cAdjust >>= 1; } if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { regs[0x38] = bExpect[0]; regs[0x39] = bExpect[1]; regs[0x3a] = bExpect[2]; } else { regs[0x38] = regs[0x39] = regs[0x3a] = bExpect[0]; } DBG( _DBG_INFO2, "REG[0x38] = %u\n", regs[0x38] ); DBG( _DBG_INFO2, "REG[0x39] = %u\n", regs[0x39] ); DBG( _DBG_INFO2, "REG[0x3a] = %u\n", regs[0x3a] ); DBG( _DBG_INFO, "usb_AdjustOffset() done.\n" ); /* switch it on again on CIS based scanners */ if( usb_IsCISDevice(dev)) { if( dev->usbDev.pSource->DarkShadOrgY < 0 ) { regs[0x29] = hw->bReg_0x29; usb_switchLamp( dev, SANE_TRUE ); usbio_WriteReg( dev->fd, 0x29, regs[0x29]); } } return SANE_TRUE; } /** this function tries to find out some suitable values for the dark * fine calibration. If the device owns a black calibration strip * the data is simply copied. If not, then the white strip is read * with the lamp switched off... */ static void usb_GetDarkShading( Plustek_Device *dev, u_short *pwDest, HiLoDef *pSrce, u_long dwPixels, u_long dwAdd, int iOffset ) { u_long dw; u_long dwSum[2]; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; if( dev->usbDev.pSource->DarkShadOrgY >= 0 ) { u_short w; int wtmp; /* here we use the source buffer + a static offset */ for (dw = 0; dw < dwPixels; dw++, pSrce += dwAdd) { #ifndef SWAP_FINE wtmp = ((int)_PHILO2WORD(pSrce) + iOffset); #else wtmp = ((int)_PLOHI2WORD(pSrce) + iOffset); #endif if( wtmp < 0 ) wtmp = 0; if( wtmp > 0xffff ) wtmp = 0xffff; w = (u_short)wtmp; #ifndef SWAP_FINE pwDest[dw] = _LOBYTE(w) * 256 + _HIBYTE(w); #else pwDest[dw] = w; #endif } } else { dwSum[0] = dwSum[1] = 0; if( hw->bSensorConfiguration & 0x04 ) { /* Even/Odd CCD */ for( dw = 0; dw < dwPixels; dw++, pSrce += dwAdd ) { #ifndef SWAP_FINE dwSum[dw & 1] += (u_long)_PHILO2WORD(pSrce); #else dwSum[dw & 1] += (u_long)_PLOHI2WORD(pSrce); #endif } dwSum[0] /= ((dwPixels + 1UL) >> 1); dwSum[1] /= (dwPixels >> 1); if( /*Registry.GetEvenOdd() == 1 ||*/ scaps->bPCB == 2) { dwSum[0] = dwSum[1] = (dwSum[0] + dwSum[1]) / 2; } dwSum[0] = (int)dwSum[0] + iOffset; dwSum[1] = (int)dwSum[1] + iOffset; if((int)dwSum[0] < 0) dwSum[0] = 0; if((int)dwSum[1] < 0) dwSum[1] = 0; #ifndef SWAP_FINE dwSum[0] = (u_long)_LOBYTE(_LOWORD(dwSum[0])) * 256UL + _HIBYTE(_LOWORD(dwSum[0])); dwSum[1] = (u_long)_LOBYTE(_LOWORD(dwSum[1])) * 256UL + _HIBYTE(_LOWORD(dwSum[1])); #else dwSum[0] = (u_long)_LOWORD(dwSum[0]); dwSum[1] = (u_long)_LOWORD(dwSum[1]); #endif for( dw = 0; dw < dwPixels; dw++ ) pwDest[dw] = (u_short)dwSum[dw & 1]; } else { /* Standard CCD */ /* do some averaging on the line */ for( dw = 0; dw < dwPixels; dw++, pSrce += dwAdd ) { #ifndef SWAP_FINE dwSum[0] += (u_long)_PHILO2WORD(pSrce); #else dwSum[0] += (u_long)_PLOHI2WORD(pSrce); #endif } dwSum[0] /= dwPixels; /* add our offset... */ dwSum[0] = (int)dwSum[0] + iOffset; if((int)dwSum[0] < 0) dwSum[0] = 0; #ifndef SWAP_FINE dwSum[0] = (u_long)_LOBYTE(_LOWORD(dwSum[0])) * 256UL + _HIBYTE(_LOWORD(dwSum[0])); #else dwSum[0] = (u_long)_LOWORD(dwSum[0]); #endif /* fill the shading data */ for( dw = 0; dw < dwPixels; dw++ ) pwDest[dw] = (u_short)dwSum[0]; } } #ifdef SWAP_FINE if(usb_HostSwap()) usb_Swap( pwDest, dwPixels *2 ); #endif } /** usb_AdjustDarkShading * fine calibration part 1 - read the black calibration area and write * the black line data to the offset coefficient data in Merlins' DRAM * If there's no black line available, we can use the min pixel value * from coarse calibration... */ static SANE_Bool usb_AdjustDarkShading( Plustek_Device *dev ) { char tmp[40]; ScanDef *scanning = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_long *scanbuf = scanning->pScanBuffer; u_char *regs = dev->usbDev.a_bRegs; if( usb_IsEscPressed()) return SANE_FALSE; if( scaps->workaroundFlag & _WAF_SKIP_FINE ) return SANE_TRUE; DBG( _DBG_INFO, "#########################\n" ); DBG( _DBG_INFO, "usb_AdjustDarkShading()\n" ); DBG( _DBG_INFO2, "* MCLK = %f (scanparam-MCLK=%f)\n", dMCLK, scanning->sParam.dMCLK ); usb_PrepareFineCal( dev, &m_ScanParam, 0 ); m_ScanParam.Size.dwLines = 1; /* for gain */ m_ScanParam.bCalibration = PARAM_DarkShading; if( _LM9831 == hw->chip ) { m_ScanParam.UserDpi.x = usb_SetAsicDpiX( dev, m_ScanParam.UserDpi.x); if( m_ScanParam.UserDpi.x < 100) m_ScanParam.UserDpi.x = 150; /* Now DPI X is physical */ m_ScanParam.Origin.x = m_ScanParam.Origin.x % (u_short)m_dHDPIDivider; m_ScanParam.Size.dwPixels = (u_long)scaps->Normal.Size.x * m_ScanParam.UserDpi.x / 300UL; m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2UL * m_ScanParam.bChannels; m_dwPixels = scanning->sParam.Size.dwPixels * m_ScanParam.UserDpi.x / scanning->sParam.UserDpi.x; if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color ) m_ScanParam.Size.dwBytes *= 3; } /* if we have dark shading strip, there's no need to switch * the lamp off */ if( dev->usbDev.pSource->DarkShadOrgY >= 0 ) { usb_ModuleToHome( dev, SANE_TRUE ); usb_ModuleMove ( dev, MOVE_Forward, (u_long)dev->usbDev.pSource->DarkShadOrgY ); } else { /* switch lamp off to read dark data... */ regs[0x29] = 0; usb_switchLamp( dev, SANE_FALSE ); } usb_SetScanParameters( dev, &m_ScanParam ); if((!usb_ScanBegin(dev, SANE_FALSE)) || (!usb_ScanReadImage(dev,scanbuf, m_ScanParam.Size.dwPhyBytes)) || (!usb_ScanEnd( dev ))) { /* on error, reset the lamp settings*/ regs[0x29] = hw->bReg_0x29; usb_switchLamp( dev, SANE_TRUE ); usbio_WriteReg( dev->fd, 0x29, regs[0x29] ); DBG( _DBG_ERROR, "usb_AdjustDarkShading() failed\n" ); return SANE_FALSE; } /* set illumination mode and switch lamp on again */ regs[0x29] = hw->bReg_0x29; usb_switchLamp( dev, SANE_TRUE ); if( !usbio_WriteReg( dev->fd, 0x29, regs[0x29])) { DBG( _DBG_ERROR, "usb_AdjustDarkShading() failed\n" ); return SANE_FALSE; } #ifdef SWAP_FINE if(usb_HostSwap()) usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwPhyBytes ); #endif sprintf( tmp, "fine-black.raw" ); dumpPicInit(&m_ScanParam, tmp); dumpPic(tmp, (u_char*)scanbuf, m_ScanParam.Size.dwPhyBytes, 0); usleep(500 * 1000); /* Warm up lamp again */ if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { if( usb_IsCISDevice(dev)) { usb_GetDarkShading( dev, a_wDarkShading, (HiLoDef*)scanbuf, m_ScanParam.Size.dwPhyPixels, 1, scanning->sParam.swOffset[0]); usb_GetDarkShading( dev, a_wDarkShading + m_ScanParam.Size.dwPhyPixels, (HiLoDef*)scanbuf + m_ScanParam.Size.dwPhyPixels, m_ScanParam.Size.dwPhyPixels, 1, scanning->sParam.swOffset[1]); usb_GetDarkShading( dev, a_wDarkShading + m_ScanParam.Size.dwPhyPixels * 2, (HiLoDef*)scanbuf + m_ScanParam.Size.dwPhyPixels * 2, m_ScanParam.Size.dwPhyPixels, 1, scanning->sParam.swOffset[2]); } else { usb_GetDarkShading( dev, a_wDarkShading, (HiLoDef*)scanbuf, m_ScanParam.Size.dwPhyPixels, 3, scanning->sParam.swOffset[0]); usb_GetDarkShading( dev, a_wDarkShading + m_ScanParam.Size.dwPhyPixels, (HiLoDef*)scanbuf + 1, m_ScanParam.Size.dwPhyPixels, 3, scanning->sParam.swOffset[1]); usb_GetDarkShading( dev, a_wDarkShading + m_ScanParam.Size.dwPhyPixels * 2, (HiLoDef*)scanbuf + 2, m_ScanParam.Size.dwPhyPixels, 3, scanning->sParam.swOffset[2]); } } else { usb_GetDarkShading( dev, a_wDarkShading, (HiLoDef*)scanbuf, m_ScanParam.Size.dwPhyPixels, 1, scanning->sParam.swOffset[1]); memcpy( a_wDarkShading + m_ScanParam.Size.dwPhyPixels, a_wDarkShading, m_ScanParam.Size.dwPhyPixels * 2 ); memcpy( a_wDarkShading + m_ScanParam.Size.dwPhyPixels * 2, a_wDarkShading, m_ScanParam.Size.dwPhyPixels * 2 ); } regs[0x45] |= 0x10; usb_line_statistics( "Dark", a_wDarkShading, m_ScanParam.Size.dwPhyPixels, scanning->sParam.bDataType == SCANDATATYPE_Color?1:0); return SANE_TRUE; } /** function to remove the brightest values out of each row * @param dev - the almighty device structure. * @param sp - is a pointer to the scanparam structure used for * scanning the shading lines. * @param hilight - defines the number of values to skip. * @param shading_lines - defines the overall number of shading lines. */ static void usb_CalSortHighlight( Plustek_Device *dev, ScanParam *sp, u_long hilight, u_long shading_lines ) { ScanDef *scan = &dev->scanning; u_short r, g, b; u_long lines, w, x; RGBUShortDef *pw, *rgb; if( hilight == 0 ) return; rgb = (RGBUShortDef*)scan->pScanBuffer; /* do it for all relevant lines */ for( lines = hilight, rgb = rgb + sp->Size.dwPhyPixels * lines; lines < shading_lines; lines++, rgb += sp->Size.dwPhyPixels ) { /* scan the complete line */ for( x = 0; x < sp->Size.dwPhyPixels; x++ ) { /* reference is the first scanline */ pw = (RGBUShortDef*)scan->pScanBuffer; r = rgb[x].Red; g = rgb[x].Green; b = rgb[x].Blue; for( w = 0; w < hilight; w++, pw += sp->Size.dwPhyPixels ) { if( r > pw[x].Red ) _SWAP( r, pw[x].Red ); if( g > pw[x].Green ) _SWAP( g, pw[x].Green ); if( b > pw[x].Blue ) _SWAP( b, pw[x].Blue ); } rgb[x].Red = r; rgb[x].Green = g; rgb[x].Blue = b; } } } /** function to remove the brightest values out of each row * @param dev - the almighty device structure. * @param sp - is a pointer to the scanparam structure used for * scanning the shading lines. * @param hilight - defines the number of values to skip. * @param shading_lines - defines the overall number of shading lines. */ static void usb_CalSortShadow( Plustek_Device *dev, ScanParam *sp, u_long hilight, u_long shadow, u_long shading_lines ) { ScanDef *scan = &dev->scanning; u_short r, g, b; u_long lines, w, x; RGBUShortDef *pw, *rgb; if( shadow == 0 ) return; rgb = (RGBUShortDef*)scan->pScanBuffer; for( lines = hilight, rgb = rgb + sp->Size.dwPhyPixels * lines; lines < shading_lines-shadow; lines++, rgb += sp->Size.dwPhyPixels ) { for (x = 0; x < sp->Size.dwPhyPixels; x++) { pw = ((RGBUShortDef*)scan->pScanBuffer) + (shading_lines - shadow) * sp->Size.dwPhyPixels; r = rgb[x].Red; g = rgb[x].Green; b = rgb[x].Blue; for( w = 0; w < shadow; w++, pw += sp->Size.dwPhyPixels ) { if( r < pw[x].Red ) _SWAP( r, pw[x].Red ); if( g < pw[x].Green ) _SWAP( g, pw [x].Green ); if( b > pw[x].Blue ) _SWAP( b, pw[x].Blue ); } rgb[x].Red = r; rgb[x].Green = g; rgb[x].Blue = b; } } } static void usb_procHighlightAndShadow( Plustek_Device *dev, ScanParam *sp, u_long hilight, u_long shadow, u_long shading_lines ) { ScanDef *scan = &dev->scanning; u_long lines, x; u_long *pr, *pg, *pb; RGBUShortDef *rgb; pr = (u_long*)((u_char*)scan->pScanBuffer + sp->Size.dwPhyBytes * shading_lines); pg = pr + sp->Size.dwPhyPixels; pb = pg + sp->Size.dwPhyPixels; memset(pr, 0, sp->Size.dwPhyPixels * 4UL * 3UL); /* Sort hilight */ usb_CalSortHighlight(dev, sp, hilight, shading_lines); /* Sort shadow */ usb_CalSortShadow(dev, sp, hilight, shadow, shading_lines); rgb = (RGBUShortDef*)scan->pScanBuffer; rgb += sp->Size.dwPhyPixels * hilight; /* Sum */ for( lines = hilight; lines < (shading_lines-shadow); lines++ ) { for( x = 0; x < sp->Size.dwPhyPixels; x++ ) { pr[x] += rgb[x].Red; pg[x] += rgb[x].Green; pb[x] += rgb[x].Blue; } rgb += sp->Size.dwPhyPixels; } } /** usb_AdjustWhiteShading * fine calibration part 2 - read the white calibration area and calculate * the gain coefficient for each pixel */ static SANE_Bool usb_AdjustWhiteShading( Plustek_Device *dev ) { char tmp[40]; ScanDef *scan = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_long *pBuf = scan->pScanBuffer; u_long dw, dwLines, dwRead; u_long shading_lines; MonoWordDef *pValue; u_short *m_pAvMono; u_long *pdw, *m_pSum; u_short hilight, shadow; int i; SANE_Bool swap = usb_HostSwap(); if( scaps->workaroundFlag & _WAF_SKIP_FINE ) return SANE_TRUE; DBG( _DBG_INFO, "#########################\n" ); DBG( _DBG_INFO, "usb_AdjustWhiteShading()\n" ); m_pAvMono = (u_short*)scan->pScanBuffer; if( usb_IsEscPressed()) return SANE_FALSE; usb_PrepareFineCal( dev, &m_ScanParam, 0 ); if( m_ScanParam.PhyDpi.x > 75) shading_lines = 64; else shading_lines = 32; /* NOTE: hilight + shadow < shading_lines */ hilight = 4; shadow = 4; m_ScanParam.bCalibration = PARAM_WhiteShading; m_ScanParam.Size.dwLines = shading_lines; if( _LM9831 == hw->chip ) { m_ScanParam.UserDpi.x = usb_SetAsicDpiX( dev, m_ScanParam.UserDpi.x); if( m_ScanParam.UserDpi.x < 100 ) m_ScanParam.UserDpi.x = 150; /* Now DPI X is physical */ m_ScanParam.Origin.x = m_ScanParam.Origin.x % (u_short)m_dHDPIDivider; m_ScanParam.Size.dwPixels = (u_long)scaps->Normal.Size.x * m_ScanParam.UserDpi.x / 300UL; m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2UL * m_ScanParam.bChannels; if( usb_IsCISDevice(dev) && m_ScanParam.bDataType == SCANDATATYPE_Color ) m_ScanParam.Size.dwBytes *= 3; m_dwPixels = scan->sParam.Size.dwPixels * m_ScanParam.UserDpi.x / scan->sParam.UserDpi.x; dw = (u_long)(hw->wDRAMSize - 196 /*192 KiB*/) * 1024UL; for( dwLines = dw / m_ScanParam.Size.dwBytes; dwLines < m_ScanParam.Size.dwLines; m_ScanParam.Size.dwLines>>=1); } /* goto the correct position again... */ if( dev->usbDev.pSource->DarkShadOrgY >= 0 ) { usb_ModuleToHome( dev, SANE_TRUE ); usb_ModuleMove ( dev, MOVE_Forward, (u_long)dev->usbDev.pSource->ShadingOriginY ); } sprintf( tmp, "fine-white.raw" ); DBG( _DBG_INFO2, "FINE WHITE Calibration Strip: %s\n", tmp ); DBG( _DBG_INFO2, "Shad.-Lines = %lu\n", shading_lines ); DBG( _DBG_INFO2, "Lines = %lu\n", m_ScanParam.Size.dwLines ); DBG( _DBG_INFO2, "Pixels = %lu\n", m_ScanParam.Size.dwPixels ); DBG( _DBG_INFO2, "Bytes = %lu\n", m_ScanParam.Size.dwBytes ); DBG( _DBG_INFO2, "Origin.X = %u\n", m_ScanParam.Origin.x ); for( dw = shading_lines, dwRead = 0; dw; dw -= m_ScanParam.Size.dwLines ) { if( usb_SetScanParameters( dev, &m_ScanParam ) && usb_ScanBegin( dev, SANE_FALSE )) { DBG(_DBG_INFO2,"TotalBytes = %lu\n",m_ScanParam.Size.dwTotalBytes); if( _LM9831 == hw->chip ) { /* Delay for white shading hold for 9831-1200 scanner */ usleep(900000); } if( usb_ScanReadImage( dev, (u_char*)pBuf + dwRead, m_ScanParam.Size.dwTotalBytes)) { if( _LM9831 == hw->chip ) { /* Delay for white shading hold for 9831-1200 scanner */ usleep(10000); } if( 0 == dwRead ) { dumpPicInit(&m_ScanParam, tmp); } dumpPic(tmp, (u_char*)pBuf + dwRead, m_ScanParam.Size.dwTotalBytes, 0); if( usb_ScanEnd( dev )) { dwRead += m_ScanParam.Size.dwTotalBytes; continue; } } } DBG( _DBG_ERROR, "usb_AdjustWhiteShading() failed\n" ); return SANE_FALSE; } m_pSum = (u_long*)((u_char*)pBuf + m_ScanParam.Size.dwPhyBytes * shading_lines); /* * do some reordering on CIS based devices: * from RRRRRRR.... GGGGGGGG.... BBBBBBBBB, create RGB RGB RGB ... * to use the following code, originally written for CCD devices... */ if( usb_IsCISDevice(dev)) { u_short *dest, *src; u_long dww; src = (u_short*)pBuf; DBG( _DBG_INFO2, "PhyBytes = %lu\n", m_ScanParam.Size.dwPhyBytes ); DBG( _DBG_INFO2, "PhyPixels = %lu\n", m_ScanParam.Size.dwPhyPixels ); DBG( _DBG_INFO2, "Pixels = %lu\n", m_ScanParam.Size.dwPixels ); DBG( _DBG_INFO2, "Bytes = %lu\n", m_ScanParam.Size.dwBytes ); DBG( _DBG_INFO2, "Channels = %u\n", m_ScanParam.bChannels ); for( dwLines = shading_lines; dwLines; dwLines-- ) { dest = a_wWhiteShading; for( dw=dww=0; dw < m_ScanParam.Size.dwPhyPixels; dw++, dww+=3 ) { dest[dww] = src[dw]; dest[dww + 1] = src[m_ScanParam.Size.dwPhyPixels + dw]; dest[dww + 2] = src[m_ScanParam.Size.dwPhyPixels * 2 + dw]; } /* copy line back ... */ memcpy( src, dest, m_ScanParam.Size.dwPhyPixels * 3 * 2 ); src = &src[m_ScanParam.Size.dwPhyPixels * 3]; } m_ScanParam.bChannels = 3; } if( _LM9831 == hw->chip ) { u_short *pwDest = (u_short*)pBuf; HiLoDef *pwSrce = (HiLoDef*)pBuf; pwSrce += ((u_long)(scan->sParam.Origin.x-m_ScanParam.Origin.x) / (u_short)m_dHDPIDivider) * (scaps->OpticDpi.x / 300UL) * m_ScanParam.bChannels; for( dwLines = shading_lines; dwLines; dwLines--) { #ifdef SWAP_FINE if(usb_HostSwap()) { #endif for( dw = 0; dw < m_dwPixels * m_ScanParam.bChannels; dw++ ) pwDest[dw] = _HILO2WORD(pwSrce[dw]); #ifdef SWAP_FINE } else { for( dw = 0; dw < m_dwPixels * m_ScanParam.bChannels; dw++ ) pwDest[dw] = _LOHI2WORD(pwSrce[dw]); } #endif pwDest += (u_long)m_dwPixels * m_ScanParam.bChannels; pwSrce = (HiLoDef*)((u_char*)pwSrce + m_ScanParam.Size.dwPhyBytes); } _SWAP(m_ScanParam.Size.dwPhyPixels, m_dwPixels); } else { /* Discard the status word and conv. the hi-lo order to intel format */ u_short *pwDest = (u_short*)pBuf; HiLoDef *pwSrce = (HiLoDef*)pBuf; for( dwLines = shading_lines; dwLines; dwLines-- ) { #ifdef SWAP_FINE if(usb_HostSwap()) { #endif for( dw = 0; dw < m_ScanParam.Size.dwPhyPixels * m_ScanParam.bChannels; dw++) { pwDest[dw] = _HILO2WORD(pwSrce[dw]); } #ifdef SWAP_FINE } else { for( dw = 0; dw < m_ScanParam.Size.dwPhyPixels * m_ScanParam.bChannels; dw++) { pwDest[dw] = _LOHI2WORD(pwSrce[dw]); } } #endif pwDest += m_ScanParam.Size.dwPhyPixels * m_ScanParam.bChannels; pwSrce = (HiLoDef*)((u_char*)pwSrce + m_ScanParam.Size.dwPhyBytes); } } if( scan->sParam.bDataType == SCANDATATYPE_Color ) { usb_procHighlightAndShadow(dev, &m_ScanParam, hilight, shadow, shading_lines); pValue = (MonoWordDef*)a_wWhiteShading; pdw = (u_long*)m_pSum; /* Software gain */ if( scan->sParam.bSource != SOURCE_Negative ) { for( i = 0; i < 3; i++ ) { for(dw=m_ScanParam.Size.dwPhyPixels; dw; dw--,pValue++,pdw++) { *pdw = *pdw * 1000 / ((shading_lines - hilight - shadow) * scan->sParam.swGain[i]); if(*pdw > 65535U) pValue->Mono = 65535U; else pValue->Mono = (u_short)*pdw; if (pValue->Mono > 16384U) pValue->Mono = (u_short)(GAIN_Target * 16384U / pValue->Mono); else pValue->Mono = GAIN_Target; #ifdef SWAP_FINE if( swap ) #endif _SWAP(pValue->HiLo.bHi, pValue->HiLo.bLo); } } } else { for( dw = m_ScanParam.Size.dwPhyPixels*3; dw; dw--,pValue++,pdw++) pValue->Mono=(u_short)(*pdw/(shading_lines-hilight-shadow)); /* swapping will be done later in usb_ResizeWhiteShading() */ } } else { /* gray mode */ u_short *pwAv, *pw; u_short w, wV; memset( m_pSum, 0, m_ScanParam.Size.dwPhyPixels << 2 ); if( hilight ) { for( dwLines = hilight, pwAv = m_pAvMono + m_ScanParam.Size.dwPhyPixels * dwLines; dwLines < shading_lines; dwLines++, pwAv += m_ScanParam.Size.dwPhyPixels) { for( dw = 0; dw < m_ScanParam.Size.dwPhyPixels; dw++ ) { pw = m_pAvMono; wV = pwAv [dw]; for( w = 0; w < hilight; w++, pw += m_ScanParam.Size.dwPhyPixels ) { if( wV > pw[dw] ) _SWAP( wV, pw[dw] ); } pwAv[dw] = wV; } } } /* Sort shadow */ if (shadow) { for (dwLines = hilight, pwAv = m_pAvMono + m_ScanParam.Size.dwPhyPixels * dwLines; dwLines < (shading_lines - shadow); dwLines++, pwAv += m_ScanParam.Size.dwPhyPixels) for (dw = 0; dw < m_ScanParam.Size.dwPhyPixels; dw++) { pw = m_pAvMono + (shading_lines - shadow) * m_ScanParam.Size.dwPhyPixels; wV = pwAv [dw]; for (w = 0; w < shadow; w++, pw += m_ScanParam.Size.dwPhyPixels) if (wV < pw [dw]) _SWAP (wV, pw[dw]); pwAv [dw] = wV; } } /* Sum */ pdw = (u_long*)m_pSum; for (dwLines = hilight, pwAv = m_pAvMono + m_ScanParam.Size.dwPhyPixels * dwLines; dwLines < (shading_lines - shadow); dwLines++, pwAv += m_ScanParam.Size.dwPhyPixels) { for (dw = 0; dw < m_ScanParam.Size.dwPhyPixels; dw++) pdw[dw] += pwAv[dw]; } /* Software gain */ pValue = (MonoWordDef*)a_wWhiteShading; if( scan->sParam.bSource != SOURCE_Negative ) { for( dw = 0; dw < m_ScanParam.Size.dwPhyPixels; dw++) { pdw[dw] = pdw[dw] * 1000 /((shading_lines-hilight-shadow) * scan->sParam.swGain[1]); if( pdw[dw] > 65535U ) pValue[dw].Mono = 65535; else pValue[dw].Mono = (u_short)pdw[dw]; if( pValue[dw].Mono > 16384U ) { pValue[dw].Mono = (u_short)(GAIN_Target * 16384U / pValue[dw].Mono); } else { pValue[dw].Mono = GAIN_Target; } #ifdef SWAP_FINE if( swap ) #endif _SWAP(pValue[dw].HiLo.bHi, pValue[dw].HiLo.bLo); } } else{ for( dw = 0; dw < m_ScanParam.Size.dwPhyPixels; dw++ ) { pValue[dw].Mono = (u_short)(pdw[dw] / (shading_lines - hilight - shadow)); /* swapping will be done later in usb_ResizeWhiteShading() */ } } } usb_SaveCalSetShading( dev, &m_ScanParam ); if( scan->sParam.bSource != SOURCE_Negative ) { usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels, scan->sParam.bDataType == SCANDATATYPE_Color?1:0); } return SANE_TRUE; } /** for negative film only * we need to resize the gain to obtain bright white... */ static void usb_ResizeWhiteShading( double dAmp, u_short *pwShading, int iGain ) { u_long dw, dwAmp; u_short w; DBG( _DBG_INFO2, "ResizeWhiteShading: dAmp=%.3f, iGain=%i\n", dAmp, iGain ); for( dw = 0; dw < m_ScanParam.Size.dwPhyPixels; dw++ ) { dwAmp = (u_long)(GAIN_Target * 0x4000 / (pwShading[dw] + 1) * dAmp) * iGain / 1000; if( dwAmp <= GAIN_Target) w = (u_short)dwAmp; else w = GAIN_Target; #ifndef SWAP_FINE pwShading[dw] = (u_short)_LOBYTE(w) * 256 + _HIBYTE(w); #else pwShading[dw] = w; #endif } #ifdef SWAP_FINE if( usb_HostSwap()) usb_Swap( pwShading, m_ScanParam.Size.dwPhyPixels ); #endif } /** do the base settings for calibration scans */ static void usb_PrepareCalibration( Plustek_Device *dev ) { ScanDef *scan = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; u_char *regs = dev->usbDev.a_bRegs; usb_GetSWOffsetGain( dev ); memset( &m_ScanParam, 0, sizeof(ScanParam)); m_ScanParam.UserDpi = scaps->OpticDpi; m_ScanParam.PhyDpi = scaps->OpticDpi; m_ScanParam.bChannels = scan->sParam.bChannels; m_ScanParam.bBitDepth = 16; m_ScanParam.bSource = scan->sParam.bSource; m_ScanParam.Origin.y = 0; if( scan->sParam.bDataType == SCANDATATYPE_Color ) m_ScanParam.bDataType = SCANDATATYPE_Color; else m_ScanParam.bDataType = SCANDATATYPE_Gray; usb_SetMCLK( dev, &m_ScanParam ); /* preset these registers offset/gain */ regs[0x38] = regs[0x39] = regs[0x3a] = 0; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; regs[0x45] &= ~0x10; memset( a_wWhiteShading, 0, _SHADING_BUF ); memset( a_wDarkShading, 0, _SHADING_BUF ); scan->skipCoarseCalib = SANE_FALSE; if( dev->adj.cacheCalData ) if( usb_ReadAndSetCalData( dev )) scan->skipCoarseCalib = SANE_TRUE; /* as sheet-fed device we use the cached values, or * perform the calibration upon request */ if( usb_IsSheetFedDevice(dev)) { if( !scan->skipCoarseCalib && !usb_InCalibrationMode(dev)) { DBG(_DBG_INFO2,"SHEET-FED device, skip coarse calibration!\n"); scan->skipCoarseCalib = SANE_TRUE; regs[0x3b] = 0x0a; regs[0x3c] = 0x0a; regs[0x3d] = 0x0a; /* use frontend values... */ if((dev->adj.rofs != -1) && (dev->adj.gofs != -1) && (dev->adj.bofs != -1)) { regs[0x38] = (dev->adj.rofs & 0x3f); regs[0x39] = (dev->adj.gofs & 0x3f); regs[0x3a] = (dev->adj.bofs & 0x3f); } if((dev->adj.rgain != -1) && (dev->adj.ggain != -1) && (dev->adj.bgain != -1)) { setAdjGain( dev->adj.rgain, ®s[0x3b] ); setAdjGain( dev->adj.ggain, ®s[0x3c] ); setAdjGain( dev->adj.bgain, ®s[0x3d] ); } } } } /** */ static SANE_Bool usb_SpeedTest( Plustek_Device *dev ) { int i; double s, e, r, tr; struct timeval start, end; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; u_long *scanbuf = dev->scanning.pScanBuffer; if( usb_IsEscPressed()) return SANE_FALSE; bMaxITA = 0xff; DBG( 1, "#########################\n" ); DBG( 1, "usb_SpeedTest(%d,%lu)\n", dev->initialized, dev->transferRate ); if( dev->transferRate != DEFAULT_RATE ) { DBG( 1, "* skipped, using already detected speed: %lu Bytes/s\n", dev->transferRate ); return SANE_TRUE; } usb_PrepareCalibration( dev ); regs[0x38] = regs[0x39] = regs[0x3a] = 0; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; /* define the strip to scan for warming up the lamp, in the end * we always scan the full line, even for TPA */ m_ScanParam.bDataType = SCANDATATYPE_Color; m_ScanParam.bCalibration = PARAM_Gain; m_ScanParam.dMCLK = dMCLK; m_ScanParam.bBitDepth = 8; m_ScanParam.Size.dwLines = 1; m_ScanParam.Size.dwPixels = scaps->Normal.Size.x * scaps->OpticDpi.x / 300UL; m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2 * m_ScanParam.bChannels; if( usb_IsCISDevice(dev)) m_ScanParam.Size.dwBytes *= 3; m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart * 300UL / scaps->OpticDpi.x); r = 0.0; dev->transferRate = 2000000; for( i = 0; i < _TLOOPS ; i++ ) { if( !usb_SetScanParameters( dev, &m_ScanParam )) return SANE_FALSE; if( !usb_ScanBegin( dev, SANE_FALSE )) { DBG( _DBG_ERROR, "usb_SpeedTest() failed\n" ); return SANE_FALSE; } if (!usb_IsDataAvailableInDRAM( dev )) return SANE_FALSE; m_fFirst = SANE_FALSE; gettimeofday( &start, NULL ); usb_ScanReadImage( dev, scanbuf, m_ScanParam.Size.dwPhyBytes ); gettimeofday( &end, NULL ); usb_ScanEnd( dev ); s = (double)start.tv_sec * 1000000.0 + (double)start.tv_usec; e = (double)end.tv_sec * 1000000.0 + (double)end.tv_usec; if( e > s ) r += (e - s); else r += (s - e); } tr = ((double)m_ScanParam.Size.dwPhyBytes * _TLOOPS * 1000000.0)/r; dev->transferRate = (u_long)tr; DBG( 1, "usb_SpeedTest() done - %u loops, %.4fus --> %.4f B/s, %lu\n", _TLOOPS, r, tr, dev->transferRate ); return SANE_TRUE; } /** read the white calibration strip until the lamp seems to be stable * the timed warmup will be used, when the warmup time is set to -1 */ static SANE_Bool usb_AutoWarmup( Plustek_Device *dev ) { int i, stable_count; ScanDef *scanning = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_long *scanbuf = scanning->pScanBuffer; u_char *regs = dev->usbDev.a_bRegs; u_long dw, start, end, len; u_long curR, curG, curB; u_long lastR, lastG, lastB; long diffR, diffG, diffB; long thresh = _AUTO_THRESH; if( usb_IsEscPressed()) return SANE_FALSE; bMaxITA = 0xff; DBG( _DBG_INFO, "#########################\n" ); DBG( _DBG_INFO, "usb_AutoWarmup()\n" ); if( usb_IsCISDevice(dev)) { DBG( _DBG_INFO, "- function skipped, CIS device!\n" ); return SANE_TRUE; } if( dev->adj.warmup >= 0 ) { DBG( _DBG_INFO, "- using timed warmup: %ds\n", dev->adj.warmup ); if( !usb_Wait4Warmup( dev )) { DBG( _DBG_ERROR, "- CANCEL detected\n" ); return SANE_FALSE; } return SANE_TRUE; } usb_PrepareCalibration( dev ); regs[0x38] = regs[0x39] = regs[0x3a] = 0; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; /* define the strip to scan for warming up the lamp, in the end * we always scan the full line, even for TPA */ m_ScanParam.bDataType = SCANDATATYPE_Color; m_ScanParam.bCalibration = PARAM_Gain; m_ScanParam.dMCLK = dMCLK; m_ScanParam.Size.dwLines = 1; m_ScanParam.Size.dwPixels = scaps->Normal.Size.x * scaps->OpticDpi.x / 300UL; m_ScanParam.Size.dwBytes = m_ScanParam.Size.dwPixels * 2 * m_ScanParam.bChannels; if( usb_IsCISDevice(dev)) m_ScanParam.Size.dwBytes *= 3; m_ScanParam.Origin.x = (u_short)((u_long) hw->wActivePixelsStart * 300UL / scaps->OpticDpi.x); stable_count = 0; start = 500; len = m_ScanParam.Size.dwPixels; if( scanning->sParam.bSource == SOURCE_Transparency ) { start = scaps->Positive.DataOrigin.x * scaps->OpticDpi.x / 300UL; len = scaps->Positive.Size.x * scaps->OpticDpi.x / 300UL; thresh = _AUTO_TPA_THRESH; } else if( scanning->sParam.bSource == SOURCE_Negative ) { start = scaps->Negative.DataOrigin.x * scaps->OpticDpi.x / 300UL; len = scaps->Negative.Size.x * scaps->OpticDpi.x / 300UL; thresh = _AUTO_TPA_THRESH; } end = start + len; DBG( _DBG_INFO2, "Start=%lu, End=%lu, Len=%lu, Thresh=%li\n", start, end, len, thresh ); lastR = lastG = lastB = 0; for( i = 0; i < _MAX_AUTO_WARMUP + 1 ; i++ ) { if( !usb_SetScanParameters( dev, &m_ScanParam )) return SANE_FALSE; if( !usb_ScanBegin( dev, SANE_FALSE ) || !usb_ScanReadImage( dev, scanbuf, m_ScanParam.Size.dwPhyBytes ) || !usb_ScanEnd( dev )) { DBG( _DBG_ERROR, "usb_AutoWarmup() failed\n" ); return SANE_FALSE; } #ifdef SWAP_COARSE if(usb_HostSwap()) #endif usb_Swap((u_short *)scanbuf, m_ScanParam.Size.dwPhyBytes ); if( end > m_ScanParam.Size.dwPhyPixels ) end = m_ScanParam.Size.dwPhyPixels; curR = curG = curB = 0; for( dw = start; dw < end; dw++ ) { if( usb_IsCISDevice(dev)) { curR += ((u_short*)scanbuf)[dw]; curG += ((u_short*)scanbuf)[dw+m_ScanParam.Size.dwPhyPixels+1]; curB += ((u_short*)scanbuf)[dw+(m_ScanParam.Size.dwPhyPixels+1)*2]; } else { curR += ((RGBUShortDef*)scanbuf)[dw].Red; curG += ((RGBUShortDef*)scanbuf)[dw].Green; curB += ((RGBUShortDef*)scanbuf)[dw].Blue; } } curR /= len; curG /= len; curB /= len; diffR = curR - lastR; lastR = curR; diffG = curG - lastG; lastG = curG; diffB = curB - lastB; lastB = curB; DBG( _DBG_INFO2, "%i/%i-AVE(R,G,B)= %lu(%ld), %lu(%ld), %lu(%ld)\n", i, stable_count, curR, diffR, curG, diffG, curB, diffB ); /* we consider the lamp to be stable, * when the diffs are less than thresh for at least 3 loops */ if((diffR < thresh) && (diffG < thresh) && (diffB < thresh)) { if( stable_count > 3 ) break; stable_count++; } else { stable_count = 0; } /* no need to sleep in the first loop */ if((i != 0) && (stable_count == 0)) sleep( _AUTO_SLEEP ); } DBG( _DBG_INFO, "usb_AutoWarmup() done - %u loops\n", i+1 ); DBG( _DBG_INFO, "* AVE(R,G,B)= %lu(%ld), %lu(%ld), %lu(%ld)\n", curR, diffR, curG, diffG, curB, diffB ); return SANE_TRUE; } /** */ static int usb_DoIt( Plustek_Device *dev ) { SANE_Bool skip_fine; ScanDef *scan = &dev->scanning; DBG( _DBG_INFO, "Settings done, so start...\n" ); if( !scan->skipCoarseCalib ) { DBG( _DBG_INFO2, "###### ADJUST GAIN (COARSE)#######\n" ); if( !usb_AdjustGain(dev, 0)) { DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" ); return _E_INTERNAL; } DBG( _DBG_INFO2, "###### ADJUST OFFSET (COARSE) ####\n" ); if( !usb_AdjustOffset(dev)) { DBG( _DBG_ERROR, "Coarse Calibration failed!!!\n" ); return _E_INTERNAL; } } else { DBG( _DBG_INFO2, "Coarse Calibration skipped, using saved data\n" ); } skip_fine = SANE_FALSE; if( dev->adj.cacheCalData ) { skip_fine = usb_FineShadingFromFile(dev); } if( !skip_fine ) { DBG( _DBG_INFO2, "###### ADJUST DARK (FINE) ########\n" ); if( !usb_AdjustDarkShading(dev)) { DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" ); return _E_INTERNAL; } DBG( _DBG_INFO2, "###### ADJUST WHITE (FINE) #######\n" ); if( !usb_AdjustWhiteShading(dev)) { DBG( _DBG_ERROR, "Fine Calibration failed!!!\n" ); return _E_INTERNAL; } } else { DBG( _DBG_INFO2, "###### FINE calibration skipped #######\n" ); m_ScanParam = scan->sParam; usb_GetPhyPixels( dev, &m_ScanParam ); usb_line_statistics( "Dark", a_wDarkShading, m_ScanParam.Size.dwPhyPixels, m_ScanParam.bDataType == SCANDATATYPE_Color?1:0); usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels, m_ScanParam.bDataType == SCANDATATYPE_Color?1:0); /* dev->usbDev.a_bRegs[0x45] &= ~0x10;*/ } return 0; } /** usb_DoCalibration */ static int usb_DoCalibration( Plustek_Device *dev ) { int result; ScanDef *scanning = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; double dRed, dGreen, dBlue; DBG( _DBG_INFO, "usb_DoCalibration()\n" ); if( SANE_TRUE == scanning->fCalibrated ) return SANE_TRUE; /* Go to shading position */ DBG( _DBG_INFO, "...goto shading position\n" ); /* HEINER: Currently not clear why Plustek didn't use the ShadingOriginY * for all modes * It should be okay to remove this and reference to the ShadingOriginY */ #if 0 if( scanning->sParam.bSource == SOURCE_Negative ) { DBG( _DBG_INFO, "DataOrigin.x=%u, DataOrigin.y=%u\n", dev->usbDev.pSource->DataOrigin.x, dev->usbDev.pSource->DataOrigin.y); if(!usb_ModuleMove( dev, MOVE_Forward, (dev->usbDev.pSource->DataOrigin.y + dev->usbDev.pSource->Size.y / 2))) { return _E_LAMP_NOT_IN_POS; } } else { #endif DBG( _DBG_INFO, "ShadingOriginY=%lu\n", (u_long)dev->usbDev.pSource->ShadingOriginY ); if((hw->motorModel == MODEL_HuaLien) && (scaps->OpticDpi.x==600)) { if (!usb_ModuleMove(dev, MOVE_ToShading, (u_long)dev->usbDev.pSource->ShadingOriginY)) { return _E_LAMP_NOT_IN_POS; } } else { if( !usb_ModuleMove(dev, MOVE_Forward, (u_long)dev->usbDev.pSource->ShadingOriginY)) { return _E_LAMP_NOT_IN_POS; } } /* }*/ DBG( _DBG_INFO, "shading position reached\n" ); usb_SpeedTest( dev ); if( !usb_AutoWarmup( dev )) return SANE_FALSE; usb_PrepareCalibration( dev ); /** this won't work for Plustek devices!!! */ #if 0 if( scaps->workaroundFlag & _WAF_BYPASS_CALIBRATION || !(SCANDEF_QualityScan & dev->scanning.dwFlag)) { #else if( scaps->workaroundFlag & _WAF_BYPASS_CALIBRATION ) { #endif DBG( _DBG_INFO, "--> BYPASS\n" ); regs[0x38] = regs[0x39] = regs[0x3a] = 0; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; setAdjGain( dev->adj.rgain, ®s[0x3b] ); setAdjGain( dev->adj.ggain, ®s[0x3c] ); setAdjGain( dev->adj.bgain, ®s[0x3d] ); regs[0x45] |= 0x10; usb_SetMCLK( dev, &scanning->sParam ); dumpregs( dev->fd, regs ); DBG( _DBG_INFO, "<-- BYPASS\n" ); } else { switch( scanning->sParam.bSource ) { case SOURCE_Negative: DBG( _DBG_INFO, "NEGATIVE Shading\n" ); m_dwIdealGain = IDEAL_GainNormal; if( !_IS_PLUSTEKMOTOR(hw->motorModel)) { DBG( _DBG_INFO, "No Plustek model: %udpi\n", scanning->sParam.PhyDpi.x ); usb_SetMCLK( dev, &scanning->sParam ); } else { if( dev->usbDev.Caps.OpticDpi.x == 600 ) dMCLK = 7; else dMCLK = 8; } for(;;) { if( usb_AdjustGain( dev, 2)) { if( regs[0x3b] && regs[0x3c] && regs[0x3d]) { break; } else { regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; dMCLK--; } } else { return _E_LAMP_NOT_STABLE; } } scanning->sParam.dMCLK = dMCLK; Gain_Reg.Red = regs[0x3b]; Gain_Reg.Green = regs[0x3c]; Gain_Reg.Blue = regs[0x3d]; Gain_NegHilight = Gain_Hilight; DBG( _DBG_INFO, "MCLK = %.3f\n", dMCLK ); DBG( _DBG_INFO, "GainRed = %u\n", regs[0x3b] ); DBG( _DBG_INFO, "GainGreen = %u\n", regs[0x3c] ); DBG( _DBG_INFO, "GainBlue = %u\n", regs[0x3d] ); #if 0 if( !usb_ModuleMove( dev, MOVE_Backward, dev->usbDev.pSource->DataOrigin.y + dev->usbDev.pSource->Size.y / 2 - dev->usbDev.pSource->ShadingOriginY)) { return _E_LAMP_NOT_IN_POS; } #endif regs[0x45] &= ~0x10; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; if(!usb_AdjustGain( dev, 1 )) return _E_INTERNAL; regs[0x3b] = regs[0x3c] = regs[0x3d] = 1; DBG( _DBG_INFO, "Settings done, so start...\n" ); if( !usb_AdjustOffset(dev) || !usb_AdjustDarkShading(dev) || !usb_AdjustWhiteShading(dev)) { return _E_INTERNAL; } dRed = 0.93 + 0.067 * Gain_Reg.Red; dGreen = 0.93 + 0.067 * Gain_Reg.Green; dBlue = 0.93 + 0.067 * Gain_Reg.Blue; dExpect = 2.85; if( dBlue >= dGreen && dBlue >= dRed ) dMax = dBlue; else if( dGreen >= dRed && dGreen >= dBlue ) dMax = dGreen; else dMax = dRed; dMax = dExpect / dMax; dRed *= dMax; dGreen *= dMax; dBlue *= dMax; if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { usb_ResizeWhiteShading( dRed, a_wWhiteShading, scanning->sParam.swGain[0]); usb_ResizeWhiteShading( dGreen, a_wWhiteShading + m_ScanParam.Size.dwPhyPixels, scanning->sParam.swGain[1]); usb_ResizeWhiteShading( dBlue, a_wWhiteShading + m_ScanParam.Size.dwPhyPixels*2, scanning->sParam.swGain[2]); } usb_line_statistics( "White", a_wWhiteShading, m_ScanParam.Size.dwPhyPixels, SANE_TRUE); break; case SOURCE_ADF: DBG( _DBG_INFO, "ADF Shading\n" ); m_dwIdealGain = IDEAL_GainPositive; if( scanning->sParam.bDataType == SCANDATATYPE_BW ) { if( scanning->sParam.PhyDpi.x <= 200 ) { scanning->sParam.dMCLK = 4.5; dMCLK = 4.0; } else if ( scanning->sParam.PhyDpi.x <= 300 ) { scanning->sParam.dMCLK = 4.0; dMCLK = 3.5; } else if( scanning->sParam.PhyDpi.x <= 400 ) { scanning->sParam.dMCLK = 5.0; dMCLK = 4.0; } else { scanning->sParam.dMCLK = 6.0; dMCLK = 4.0; } } else { /* Gray */ if( scanning->sParam.PhyDpi.x <= 400 ) { scanning->sParam.dMCLK = 6.0; dMCLK = 4.5; } else { scanning->sParam.dMCLK = 9.0; dMCLK = 7.0; } } dMCLK_ADF = dMCLK; result = usb_DoIt( dev ); if( result != 0 ) return result; break; case SOURCE_Transparency: DBG( _DBG_INFO, "TRANSPARENCY Shading\n" ); m_dwIdealGain = IDEAL_GainPositive; if( !_IS_PLUSTEKMOTOR(hw->motorModel)) { DBG( _DBG_INFO, "No Plustek model: %udpi\n", scanning->sParam.PhyDpi.x ); usb_SetMCLK( dev, &scanning->sParam ); } else { if( dev->usbDev.Caps.OpticDpi.x == 600 ) { scanning->sParam.dMCLK = 8; dMCLK = 4; } else { scanning->sParam.dMCLK = 8; dMCLK = 6; } } result = usb_DoIt( dev ); if( result != 0 ) return result; break; default: if( !_IS_PLUSTEKMOTOR(hw->motorModel)) { DBG( _DBG_INFO, "No Plustek model: %udpi\n", scanning->sParam.PhyDpi.x ); usb_SetMCLK( dev, &scanning->sParam ); } else if( dev->usbDev.Caps.OpticDpi.x == 600 ) { DBG( _DBG_INFO, "Default Shading (600dpi)\n" ); if( dev->usbDev.Caps.bCCD == kSONY548 ) { DBG( _DBG_INFO, "CCD - SONY548\n" ); if( scanning->sParam.PhyDpi.x <= 75 ) { if( scanning->sParam.bDataType == SCANDATATYPE_Color ) scanning->sParam.dMCLK = dMCLK = 2.5; else if(scanning->sParam.bDataType == SCANDATATYPE_Gray) scanning->sParam.dMCLK = dMCLK = 7.0; else scanning->sParam.dMCLK = dMCLK = 7.0; } else if( scanning->sParam.PhyDpi.x <= 300 ) { if( scanning->sParam.bDataType == SCANDATATYPE_Color ) scanning->sParam.dMCLK = dMCLK = 3.0; else if(scanning->sParam.bDataType == SCANDATATYPE_Gray) scanning->sParam.dMCLK = dMCLK = 6.0; else { if( scanning->sParam.PhyDpi.x <= 100 ) scanning->sParam.dMCLK = dMCLK = 6.0; else if( scanning->sParam.PhyDpi.x <= 200 ) scanning->sParam.dMCLK = dMCLK = 5.0; else scanning->sParam.dMCLK = dMCLK = 4.5; } } else if( scanning->sParam.PhyDpi.x <= 400 ) { if( scanning->sParam.bDataType == SCANDATATYPE_Color ) scanning->sParam.dMCLK = dMCLK = 4.0; else if( scanning->sParam.bDataType == SCANDATATYPE_Gray ) scanning->sParam.dMCLK = dMCLK = 6.0; else scanning->sParam.dMCLK = dMCLK = 4.0; } else { if(scanning->sParam.bDataType == SCANDATATYPE_Color) scanning->sParam.dMCLK = dMCLK = 6.0; else if(scanning->sParam.bDataType == SCANDATATYPE_Gray) scanning->sParam.dMCLK = dMCLK = 7.0; else scanning->sParam.dMCLK = dMCLK = 6.0; } } else if( dev->usbDev.Caps.bPCB == 0x02 ) { DBG( _DBG_INFO, "PCB - 0x02\n" ); if( scanning->sParam.PhyDpi.x > 300 ) scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)? 6: 16); else if( scanning->sParam.PhyDpi.x > 150 ) scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)?4.5: 13.5); else scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)?3: 8); } else if( dev->usbDev.Caps.bButtons ) { /* with lens Shading piece (with gobo) */ DBG( _DBG_INFO, "CAPS - Buttons\n" ); scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)?3: 6); if( dev->usbDev.HwSetting.motorModel == MODEL_KaoHsiung ) { if( dev->usbDev.Caps.bCCD == kNEC3799 ) { if( scanning->sParam.PhyDpi.x > 300 ) scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)? 6: 13); else if(scanning->sParam.PhyDpi.x > 150) scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)?4.5:13.5); else scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)?3: 6); } else { scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)?3: 6); } } else { /* motorModel == MODEL_Hualien */ /* IMPORTANT !!!! * for Hualien 600 dpi scanner big noise */ hw->wLineEnd = 5384; if(scanning->sParam.bDataType == SCANDATATYPE_Color && ((scanning->sParam.bBitDepth == 8 && (scanning->sParam.PhyDpi.x == 200 ||scanning->sParam.PhyDpi.x == 300)))) hw->wLineEnd = 7000; regs[0x20] = _HIBYTE(hw->wLineEnd); regs[0x21] = _LOBYTE(hw->wLineEnd); if( scanning->sParam.PhyDpi.x > 300 ) { if (scanning->sParam.bBitDepth > 8) scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)? 5: 13); else scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)? 6: 13); } else { if( scanning->sParam.bBitDepth > 8 ) scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)? 5: 13); else scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)?3: 6); } } } else { /* without lens Shading piece (without gobo) - Model U12 only */ DBG( _DBG_INFO, "Default trunc (U12)\n" ); if( scanning->sParam.PhyDpi.x > 300 ) scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)? 3: 9); else scanning->sParam.dMCLK = dMCLK = ((scanning->sParam.bDataType == SCANDATATYPE_Color)? 2: 6); } } else { /* Device.Caps.OpticDpi.x == 1200 */ DBG( _DBG_INFO, "Default Shading (1200dpi)\n" ); if( scanning->sParam.bDataType != SCANDATATYPE_Color ) { if( scanning->sParam.PhyDpi.x > 300 ) scanning->sParam.dMCLK = dMCLK = 6.0; else { scanning->sParam.dMCLK = dMCLK = 5.0; regs[0x0a] = 1; } } else { if( scanning->sParam.PhyDpi.x <= 300) scanning->sParam.dMCLK = dMCLK = 2.0; else if( scanning->sParam.PhyDpi.x <= 800 ) scanning->sParam.dMCLK = dMCLK = 4.0; else scanning->sParam.dMCLK = dMCLK = 5.5; } } if (m_ScanParam.bSource == SOURCE_ADF) m_dwIdealGain = IDEAL_GainPositive; else m_dwIdealGain = IDEAL_GainNormal; result = usb_DoIt( dev ); if( result != 0 ) return result; break; } } /* home the sensor after calibration */ if( _IS_PLUSTEKMOTOR(hw->motorModel)) { if( hw->motorModel != MODEL_Tokyo600 ) { usb_ModuleMove ( dev, MOVE_Forward, hw->wMotorDpi / 5 ); usb_ModuleToHome( dev, SANE_TRUE ); } } else { usb_ModuleMove( dev, MOVE_Forward, 10 ); usleep( 1500 ); usb_ModuleToHome( dev, SANE_TRUE ); } if( scanning->sParam.bSource == SOURCE_ADF ) { if( scaps->bCCD == kNEC3778 ) usb_ModuleMove( dev, MOVE_Forward, 1000 ); else /* if( scaps->bCCD == kNEC3799) */ usb_ModuleMove( dev, MOVE_Forward, 3 * 300 + 38 ); usb_MotorOn( dev, SANE_FALSE ); } scanning->fCalibrated = SANE_TRUE; DBG( _DBG_INFO, "Calibration done\n" ); DBG( _DBG_INFO, "-----------------------\n" ); DBG( _DBG_INFO, "Static Gain:\n" ); DBG( _DBG_INFO, "REG[0x3b] = %u\n", regs[0x3b] ); DBG( _DBG_INFO, "REG[0x3c] = %u\n", regs[0x3c] ); DBG( _DBG_INFO, "REG[0x3d] = %u\n", regs[0x3d] ); DBG( _DBG_INFO, "Static Offset:\n" ); DBG( _DBG_INFO, "REG[0x38] = %i\n", regs[0x38] ); DBG( _DBG_INFO, "REG[0x39] = %i\n", regs[0x39] ); DBG( _DBG_INFO, "REG[0x3a] = %i\n", regs[0x3a] ); DBG( _DBG_INFO, "MCLK = %.2f\n", scanning->sParam.dMCLK ); DBG( _DBG_INFO, "-----------------------\n" ); return SANE_TRUE; } /* on different sensor orders, we need to adjust the shading buffer * pointer, otherwise we correct the wrong channels */ static void get_ptrs(Plustek_Device *dev, u_short *buf, u_long offs, u_short **r, u_short **g, u_short **b) { ScanDef *scan = &dev->scanning; DCapsDef *scaps = &dev->usbDev.Caps; u_char so = scaps->bSensorOrder; if (_WAF_RESET_SO_TO_RGB & scaps->workaroundFlag) { if (scaps->bPCB != 0) { if (scan->sParam.PhyDpi.x > scaps->bPCB) so = SENSORORDER_rgb; } } switch( so ) { case SENSORORDER_gbr: *g = buf; *b = buf + offs; *r = buf + offs * 2; break; case SENSORORDER_bgr: *b = buf; *g = buf + offs; *r = buf + offs * 2; break; case SENSORORDER_rgb: default: *r = buf; *g = buf + offs; *b = buf + offs * 2; break; } } /** usb_DownloadShadingData * according to the job id, different registers or DRAM areas are set * in preparation for calibration or scanning */ static SANE_Bool usb_DownloadShadingData( Plustek_Device *dev, u_char what ) { u_char channel; u_short *r, *g, *b; DCapsDef *scaps = &dev->usbDev.Caps; ScanDef *scan = &dev->scanning; HWDef *hw = &dev->usbDev.HwSetting; ScanParam *param = &dev->scanning.sParam; u_char *regs = dev->usbDev.a_bRegs; DBG( _DBG_INFO, "usb_DownloadShadingData(%u)\n", what ); channel = CHANNEL_green; if( usb_IsCISDevice(dev)) channel = CHANNEL_blue; switch( what ) { case PARAM_WhiteShading: if( m_ScanParam.bDataType == SCANDATATYPE_Color ) { usb_SetDarkShading( dev, CHANNEL_red, a_wDarkShading, (u_short)m_ScanParam.Size.dwPhyPixels * 2); usb_SetDarkShading( dev, CHANNEL_green, a_wDarkShading + m_ScanParam.Size.dwPhyPixels, (u_short)m_ScanParam.Size.dwPhyPixels * 2); usb_SetDarkShading( dev, CHANNEL_blue, a_wDarkShading + m_ScanParam.Size.dwPhyPixels * 2, (u_short)m_ScanParam.Size.dwPhyPixels * 2); } else { usb_SetDarkShading( dev, channel, a_wDarkShading + m_ScanParam.Size.dwPhyPixels, (u_short)m_ScanParam.Size.dwPhyPixels * 2); } regs[0x40] = 0x40; regs[0x41] = 0x00; /* set RAM configuration AND * Gain = Multiplier Coefficient/16384 * CFG Register 0x40/0x41 for Multiplier Coefficient Source * External DRAM for Offset Coefficient Source */ regs[0x42] = (u_char)(( hw->wDRAMSize > 512)? 0x64: 0x24); _UIO(sanei_lm983x_write( dev->fd, 0x40, ®s[0x40], 0x42-0x40+1, SANE_TRUE )); break; case PARAM_Scan: { #if 0 if( scaps->workaroundFlag & _WAF_BYPASS_CALIBRATION || !(SCANDEF_QualityScan & dev->scanning.dwFlag)) { #else if( scaps->workaroundFlag & _WAF_BYPASS_CALIBRATION ) { #endif DBG( _DBG_INFO, "--> BYPASS\n" ); /* set RAM configuration AND * Bypass Multiplier * CFG Register 0x40/0x41 for Multiplier Coefficient Source * CFG Register 0x3e/0x3f for Offset Coefficient Source */ regs[0x03] = 0; regs[0x40] = 0x40; regs[0x41] = 0x00; regs[0x42] = (u_char)((hw->wDRAMSize > 512)? 0x61:0x21); if( !usbio_WriteReg( dev->fd, 0x03, regs[0x03])) return SANE_FALSE; _UIO(sanei_lm983x_write( dev->fd, 0x40, ®s[0x40], 3, SANE_TRUE)); break; } if( _LM9831 != hw->chip ) m_dwPixels = m_ScanParam.Size.dwPhyPixels; if( scaps->workaroundFlag & _WAF_SKIP_FINE ) { DBG( _DBG_INFO, "Skipping fine calibration\n" ); regs[0x42] = (u_char)(( hw->wDRAMSize > 512)? 0x60: 0x20); if (scan->skipCoarseCalib) { DBG( _DBG_INFO, "...cleaning shading buffer\n" ); memset( a_wWhiteShading, 0, _SHADING_BUF ); memset( a_wDarkShading, 0, _SHADING_BUF ); regs[0x40] = 0x3f; regs[0x41] = 0xff; _UIO(sanei_lm983x_write( dev->fd, 0x40, ®s[0x40], 3, SANE_TRUE)); } else { if( !usbio_WriteReg( dev->fd, 0x42, regs[0x42])) return SANE_FALSE; } break; } DBG( _DBG_INFO, "Downloading %lu pixels\n", m_dwPixels ); /* Download the dark & white shadings to LM983x */ if( param->bDataType == SCANDATATYPE_Color ) { get_ptrs(dev, a_wDarkShading, m_dwPixels, &r, &g, &b); usb_SetDarkShading( dev, CHANNEL_red, r, (u_short)m_ScanParam.Size.dwPhyPixels * 2); usb_SetDarkShading( dev, CHANNEL_green, g, (u_short)m_ScanParam.Size.dwPhyPixels * 2); usb_SetDarkShading( dev, CHANNEL_blue, b, (u_short)m_ScanParam.Size.dwPhyPixels * 2); } else { usb_SetDarkShading( dev, channel, a_wDarkShading + m_dwPixels, (u_short)m_ScanParam.Size.dwPhyPixels * 2); } if( param->bDataType == SCANDATATYPE_Color ) { get_ptrs(dev, a_wWhiteShading, m_ScanParam.Size.dwPhyPixels, &r, &g, &b); usb_SetWhiteShading( dev, CHANNEL_red, r, (u_short)m_ScanParam.Size.dwPhyPixels * 2); usb_SetWhiteShading( dev, CHANNEL_green, g, (u_short)m_ScanParam.Size.dwPhyPixels * 2); usb_SetWhiteShading( dev, CHANNEL_blue, b, (u_short)m_ScanParam.Size.dwPhyPixels * 2); } else { usb_SetWhiteShading( dev, channel, a_wWhiteShading, (u_short)m_ScanParam.Size.dwPhyPixels * 2); } /* set RAM configuration AND * Gain = Multiplier Coefficient/16384 * External DRAM for Multiplier Coefficient Source * External DRAM for Offset Coefficient Source */ regs[0x42] = (u_char)((hw->wDRAMSize > 512)? 0x66: 0x26); if( scaps->workaroundFlag & _WAF_SKIP_WHITEFINE ) { DBG( _DBG_INFO,"Skipping fine white calibration result\n"); regs[0x42] = (u_char)(( hw->wDRAMSize > 512)? 0x64: 0x24); } if( !usbio_WriteReg( dev->fd, 0x42, regs[0x42])) return SANE_FALSE; } break; default: /* for coarse calibration and "black fine" */ regs[0x3e] = 0; regs[0x3f] = 0; regs[0x40] = 0x40; regs[0x41] = 0x00; /* set RAM configuration AND * GAIN = Multiplier Coefficient/16384 * CFG Register 0x40/0x41 for Multiplier Coefficient Source * CFG Register 0x3e/0x3f for Offset Coefficient Source */ regs[0x42] = (u_char)((hw->wDRAMSize > 512)? 0x60: 0x20); _UIO(sanei_lm983x_write( dev->fd, 0x3e, ®s[0x3e], 0x42 - 0x3e + 1, SANE_TRUE )); break; } return SANE_TRUE; } /* END PLUSTEK-USBSHADING.C .................................................*/ sane-backends-1.0.27/backend/gt68xx.h0000664000175000017500000000430312112021330014113 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef GT68XX_H #define GT68XX_H #include #include "gt68xx_high.h" #define ENABLE(OPTION) s->opt[OPTION].cap &= ~SANE_CAP_INACTIVE #define DISABLE(OPTION) s->opt[OPTION].cap |= SANE_CAP_INACTIVE #define IS_ACTIVE(OPTION) (((s->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0) #define GT68XX_CONFIG_FILE "gt68xx.conf" #endif /* not GT68XX_H */ sane-backends-1.0.27/backend/sm3840_params.h0000664000175000017500000000475012112021330015252 00000000000000/* sane - Scanner Access Now Easy. ScanMaker 3840 Backend Copyright (C) 2005-7 Earle F. Philhower, III earle@ziplabel.com - http://www.ziplabel.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef _SM3840_Params #define _SM3840_Params typedef struct SM3840_Params { int gray; /* 0, 1 */ int halftone; /* 0, 1 (also set gray=1) */ int lineart; /* 0, 1 (also set gray=1) */ int dpi; /* 150, 300, 600, 1200 */ int bpp; /* 8, 16 */ double gain; /* 0.01...9.9 */ int offset; /* 0..4095 */ int lamp; /* 1..15 mins */ int threshold; /* 0...255 luminosity */ /* Input to configure(), in inches */ double top, left; double width, height; /* Output from configure(), in pixels */ int topline; int scanlines; int leftpix; int scanpix; int linelen; /* bytes per line */ } SM3840_Params; #endif sane-backends-1.0.27/backend/plustek-pp_motor.c0000664000175000017500000026463012775277260016333 00000000000000/* @file plustek-pp_motor.c * @brief all functions for motor control * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - slight cosmetic changes * - added function MotorToHomePosition() * - 0.33 - added additional debug-messages * - increased speed for returning to homeposition for Models >= 9630 * (and ASIC 96003) * - 0.34 - added FIFO overflow check in motorP96SetSpeed * - removed WaitBack() function from pScanData structure * - removed wStayMaxStep from pScanData structure * - 0.35 - changed motorP96UpdateDataCurrentReadLine() to handle proper * - work of ASIC96003 based 600dpi models * - 0.36 - merged motorP96WaitBack and motorP98WaitBack to motorWaitBack * - merged motorP96SetSpeed and motorP98SetSpedd to motorSetSpeed * - added Sensor-Check in function MotorToHomePosition * - reduced number of forward steps for MotorToHomePosition * - 0.37 - removed function motorP96GetStartStopGap() - no longer used * - removed a_bStepDown1Table and a_bStepUp1Table * - removed // comments * - added A3I stuff * - 0.38 - cosmetic changes * - added P12 stuff * - 0.39 - Did some finetuning in MotorP98003ModuleForwardBackward() * - Fixed a problem, that could cause the driver to throw a * kernel exception * - 0.40 - changed back to build 0.39-3 (disabled A3I stuff) * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - no changes * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** some definitons *********************************/ /* #define _A3I_EN */ /* * adjustments for scanning in negative and tranparency mode */ #define _NEG_SCANNINGPOS 770 #define _POS_SCANNINGPOS 660 /* original value was 710 */ #define _P98_BACKMOVES 0x3d #define _P98_FORWARDMOVES 0x3b /* Origin = 3c */ #define _P98003_BACKSTEPS 120 #define _P98003_FORWARDSTEPS 120 #define _P96_BACKMOVES 130 #define _P96_FORWARDMOVES 87 /* 95 */ #define _P96_FIFOOVERFLOWTHRESH 180 #define _COLORRUNTABLE_RED 0x11 #define _COLORRUNTABLE_GREEN 0x22 #define _COLORRUNTABLE_BLUE 0x44 #define _BW_ORIGIN 0x0D #define _GRAY_ORIGIN 0x0B #define _COLOR_ORIGIN 0x0B #define _P98003_YOFFSET 300 /**************************** local vars *************************************/ static TimerDef p98003MotorTimer; static UShort a_wMoveStepTable [_NUMBER_OF_SCANSTEPS]; static Byte a_bScanStateTable[_SCANSTATE_TABLE_SIZE]; static Byte a_bHalfStepTable [_NUMBER_OF_SCANSTEPS]; static Byte a_bColorByteTable[_NUMBER_OF_SCANSTEPS]; static Byte a_bColorsSum[8] = {0, 1, 1, 2, 1, 2, 2, 3}; static pUShort pwEndMoveStepTable = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS; static pUChar pbEndColorByteTable = a_bColorByteTable + _NUMBER_OF_SCANSTEPS; static pUChar pbEndHalfStepTable = a_bHalfStepTable + _NUMBER_OF_SCANSTEPS; /* * for the 96001/3 based units */ static UShort wP96BaseDpi = 0; static Byte a_bStepDown1Table[20] = {3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static Byte a_bStepUp1Table[20] = {4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static Byte a_bMotorDown2Table[20] = {0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; #ifndef _A3I_EN static Byte a_bHalfStep2Table[32] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; static Byte a_bHalfStep4Table[16] = {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; static Byte a_bHalfStep6Table[12] = {3,3,3,3,3,3,3,3,3,3,3,3}; static Byte a_bHalfStep8Table[8] = {4,4,4,4,4,4,4,4}; static Byte a_bHalfStep10Table[8] = {5,5,5,5,5,5,5,5}; static Byte a_bHalfStep12Table[6] = {6,6,6,6,6,6}; static Byte a_bHalfStep14Table[6] = {7,7,7,7,7,7}; static Byte a_bHalfStep16Table[4] = {8,8,8,8}; static Byte a_bHalfStep18Table[4] = {9,9,9,9}; static Byte a_bHalfStep20Table[4] = {10,10,10,10}; static Byte a_bHalfStep22Table[4] = {11,11,11,11}; static Byte a_bHalfStep24Table[4] = {12,12,12,12}; static Byte a_bHalfStep26Table[4] = {13,13,13,13}; static Byte a_bHalfStep28Table[4] = {14,14,14,14}; static Byte a_bHalfStep30Table[4] = {15,15,15,15}; static Byte a_bHalfStep32Table[2] = {16,16}; static Byte a_bHalfStep34Table[2] = {17,17}; static Byte a_bHalfStep36Table[2] = {18,18}; static Byte a_bHalfStep38Table[2] = {19,19}; static Byte a_bHalfStep40Table[2] = {20,20}; static pUChar a_pbHalfStepTables[20] = { a_bHalfStep2Table, a_bHalfStep4Table, a_bHalfStep6Table, a_bHalfStep8Table, a_bHalfStep10Table, a_bHalfStep12Table, a_bHalfStep14Table, a_bHalfStep16Table, a_bHalfStep18Table, a_bHalfStep20Table, a_bHalfStep22Table, a_bHalfStep24Table, a_bHalfStep26Table, a_bHalfStep28Table, a_bHalfStep30Table, a_bHalfStep32Table, a_bHalfStep34Table, a_bHalfStep36Table, a_bHalfStep38Table, a_bHalfStep40Table }; #endif /*************************** local functions *********************************/ /*............................................................................. * */ static void motorP96GetStartStopGap( pScanData ps, Bool fCheckState ) { UChar bMotorCountDownIndex; if( fCheckState ) { ps->bMotorStepTableNo = 0xff; if( ps->Scan.bModuleState == _MotorInNormalState ) return; } bMotorCountDownIndex = ps->bMotorSpeedData / 2; if( ps->bCurrentSpeed == 4 && ps->AsicReg.RD_Dpi < 80 ) ps->bMotorStepTableNo = 4; else if( ps->Scan.bModuleState == _MotorGoBackward ) ps->bMotorStepTableNo = a_bStepUp1Table[bMotorCountDownIndex]; else ps->bMotorStepTableNo = a_bStepDown1Table[bMotorCountDownIndex]; } /*............................................................................. * wait for the ScanState stop or ScanState reachs the dwScanStateCount */ static Bool motorCheckMotorPresetLength( pScanData ps ) { Byte bScanState; TimerDef timer; MiscStartTimer( &timer, (_SECOND * 4)); do { bScanState = IOGetScanState( ps, _FALSE ); if (ps->fFullLength) { if (!(bScanState & _SCANSTATE_STOP)) /* still running */ if ((ULong)(bScanState & _SCANSTATE_MASK) != ps->dwScanStateCount ) continue; return ps->fFullLength; } if (bScanState & _SCANSTATE_STOP) break; /* * the code may work for all units */ if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { if (bScanState < ps->bOldStateCount) bScanState += _NUMBER_OF_SCANSTEPS; bScanState -= ps->bOldStateCount; if (bScanState >= 40) return ps->fFullLength; } } while ( !MiscCheckTimer( &timer )); _DODELAY(1); /* delay one ms */ return ps->fFullLength; } /*............................................................................. * 1) Keep the valid content of a_bColorByteTable, and fill others to 0: * BeginFill = ((bCurrentLineCount + DL) < 64) ? bCurrentLineCount + DL : * bCurrentLineCount + DL - 64; * FillLength = 64 - DL * [NOTE] Keep the content of a_bColorByteTable that begin at * bCurrentLineCount and in DL bytes * 2) Keep the valid content of a_bHalfStepTable, and fill the others to 0: * BeginFill = ((bCurrentLineCount + bCurrentSpeed / 2 + 1) < 64) ? * bCurrentLineCount + bCurrentSpeed / 2 + 1 : * bCurrentLineCount + bCurrentSpeed / 2 + 1 - 64; * FillLength = 64 - (bMotorSpeedData / 2 + 1); */ static void motorClearColorByteTableLoop0( pScanData ps, Byte bColors ) { ULong dw; pUChar pb; if ((ps->bCurrentLineCount + bColors) >= _NUMBER_OF_SCANSTEPS) { pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + bColors - _NUMBER_OF_SCANSTEPS); } else { pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + bColors); } for (dw = _NUMBER_OF_SCANSTEPS - bColors; dw; dw--) { *pb++ = 0; if (pb >= pbEndColorByteTable) pb = a_bColorByteTable; } if ((ps->bCurrentLineCount+ps->bCurrentSpeed/2+1) >= _NUMBER_OF_SCANSTEPS) { pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount + ps->bCurrentSpeed / 2 + 1 - _NUMBER_OF_SCANSTEPS); } else { pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount + ps->bCurrentSpeed / 2 + 1); } for (dw = _NUMBER_OF_SCANSTEPS - ps->bMotorSpeedData / 2 - 1; dw; dw--) { *pb++ = 0; if (pb >= pbEndHalfStepTable) pb = a_bHalfStepTable; } } /*............................................................................. * motorClearColorByteTableLoop1 () * 1) Adjust bNewGap: * bNewGap = (bNewGap <= bNewCurrentLineCountGap) ? * 0 : bNewGap - bNewCurrentLineCount - 1; * 2) Fill the 0 to a_bColorByteTable: * FillIndex = ((bCurrentLineCount + bNewGap + 1) < 64) ? * bCurrentLineCount + bNewGap + 1 : * bCurrentLineCount + bNewGap + 1 - 64; * FillCount = 64 - bNewGap - 1; * 3) Adjust bNewGap: * bNewGap = (bCurrentLineCount <= bNewCurrentLineCountGap) ? * 0 : bNewGap - bNewCurrentLineCount - 1; * 4) Fill the a_bHalfStepTable: * FillIndex = ((bCurrentLineCount + bNewGap + 1) < 64) ? * bCurrentLineCount + bNewGap + 1 : * bCurrentLineCount + bNewGap + 1 - 64; * FillCount = 64 - bNewGap - 1; */ static void motorClearColorByteTableLoop1( pScanData ps ) { ULong dw = _NUMBER_OF_SCANSTEPS - 1; pUChar pb; if (ps->bNewGap > ps->bNewCurrentLineCountGap) { ps->bNewGap = ps->bNewGap - ps->bNewCurrentLineCountGap - 1; dw -= (ULong)ps->bNewGap; } else { ps->bNewGap = 0; } if ((ps->bCurrentLineCount + ps->bNewGap + 1) >= _NUMBER_OF_SCANSTEPS) { pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount+ps->bNewGap+1-_NUMBER_OF_SCANSTEPS); } else { pb = a_bColorByteTable + (ULong)(ps->bCurrentLineCount + ps->bNewGap + 1); } for (; dw; dw--) { *pb++ = 0; if (pb >= pbEndColorByteTable) pb = a_bColorByteTable; } if (ps->bCurrentSpeed > ps->bNewCurrentLineCountGap) { ps->bNewGap = ps->bCurrentSpeed - ps->bNewCurrentLineCountGap; dw = _NUMBER_OF_SCANSTEPS - 1 - (ULong)ps->bNewGap; } else { dw = _NUMBER_OF_SCANSTEPS - 1; ps->bNewGap = 0; } if ((ps->bCurrentLineCount + ps->bNewGap + 1) >= _NUMBER_OF_SCANSTEPS) { pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount + ps->bNewGap + 1 - _NUMBER_OF_SCANSTEPS); } else { pb = a_bHalfStepTable + (ULong)(ps->bCurrentLineCount+ps->bNewGap +1); } for (; dw; dw--) { *pb++ = 0; if (pb >= pbEndHalfStepTable) pb = a_bHalfStepTable; } } /*............................................................................. * According the flag to set motor direction */ static void motorSetRunPositionRegister( pScanData ps ) { Byte bData; if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { if( ps->Scan.fMotorBackward ) { bData = ps->AsicReg.RD_Motor0Control & ~_MotorDirForward; } else { bData = ps->AsicReg.RD_Motor0Control | _MotorDirForward; } IOCmdRegisterToScanner( ps, ps->RegMotor0Control, bData ); } else { if( ps->Scan.fMotorBackward ) { bData = ps->Asic96Reg.RD_MotorControl & ~_MotorDirForward; } else { bData = ps->Asic96Reg.RD_MotorControl | _MotorDirForward; } IOCmdRegisterToScanner( ps, ps->RegMotorControl, bData ); } } /*............................................................................. * */ static void motorPauseColorMotorRunStates( pScanData ps ) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES); if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ps->a_nbNewAdrPointer[2] = 0x77; /* Read color at the same time */ } else { ps->a_nbNewAdrPointer[2] = 1; ps->a_nbNewAdrPointer[3] = 3; ps->a_nbNewAdrPointer[4] = 2; } MotorSetConstantMove( ps, 0 ); } /*............................................................................. * Setup the a_nbNewAdrPointer for ASIC stepping register */ static void motorP98FillDataToColorTable( pScanData ps, Byte bIndex, ULong dwSteps) { pUChar pb; pUShort pw; Byte bColor; UShort w; for ( pb = &a_bColorByteTable[bIndex], pw = &a_wMoveStepTable[bIndex]; dwSteps; dwSteps-- ) { if (*pw) { /* valid state */ if( *pw >= ps->BufferForColorRunTable ) { DBG( DBG_LOW, "*pw = %u > %u !!\n", *pw, ps->BufferForColorRunTable ); } else { bColor = ps->pColorRunTable[*pw]; /* get the colors */ if (a_bColorsSum[bColor & 7]) /* need to read data */ *pb = bColor & 7; } } if (++pw >= pwEndMoveStepTable) { pw = a_wMoveStepTable; pb = a_bColorByteTable; } else pb++; } /* ToCondense */ pb = a_bColorByteTable; for (w = 0; w < _SCANSTATE_BYTES; w++, pb += 2) ps->a_nbNewAdrPointer[w] = (Byte)((*pb & 7) + ((*(pb + 1) & 7) << 4)); /* ToCondenseMotor */ for (pb = a_bHalfStepTable, w = 0; w < _SCANSTATE_BYTES; w++) { if (*pb++) ps->a_nbNewAdrPointer [w] |= 8; if (*pb++) ps->a_nbNewAdrPointer [w] |= 0x80; } } /*............................................................................. * */ static void motorP98FillHalfStepTable( pScanData ps ) { pUChar pbHalfStepTbl, pb; pUShort pwMoveStep; DataType Data; ULong dw; if (1 == ps->bMotorSpeedData) { for (dw = 0; dw < _NUMBER_OF_SCANSTEPS; dw++) a_bHalfStepTable [dw] = (a_wMoveStepTable [dw] > ps->wMaxMoveStep) ? 0: 1; } else { pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount]; pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount]; if (ps->DataInf.wAppDataType >= COLOR_TRUE24) Data.dwValue = _NUMBER_OF_SCANSTEPS - 1; else Data.dwValue = _NUMBER_OF_SCANSTEPS; for (; Data.dwValue; Data.dwValue--, pbHalfStepTbl++, pwMoveStep++ ) { if (pwMoveStep >= pwEndMoveStepTable) { pbHalfStepTbl = a_bHalfStepTable; pwMoveStep = a_wMoveStepTable; } if (*pwMoveStep) { /* need to exposure */ dw = (ULong)ps->bMotorSpeedData; if (Data.bValue < ps->bMotorSpeedData) *pwMoveStep = 0; else { *pbHalfStepTbl = 1; if (ps->dwFullStateSpeed) { dw -= ps->dwFullStateSpeed; for (pb = pbHalfStepTbl; dw; dw -= ps->dwFullStateSpeed) { pb += ps->dwFullStateSpeed; if (pb >= pbEndHalfStepTable) pb -= _NUMBER_OF_SCANSTEPS; *pb = 1; } } } } } } } /*............................................................................. * */ static void motorP98FillBackColorDataTable( pScanData ps ) { Byte bIndex; if ((bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1) >= _NUMBER_OF_SCANSTEPS) { bIndex -= _NUMBER_OF_SCANSTEPS; } motorP98FillDataToColorTable( ps, bIndex, (ULong)(_NUMBER_OF_SCANSTEPS - ps->bNewCurrentLineCountGap)); } /*............................................................................. * i/p: * pScanStep = pColorRunTable if forward, a_bScanStateTable if backward * dwState = how many states is requested to process * NOTE: * The content of pScanStep contain: * 0: Idle state * 0xff: End mark * others: The motor speed value */ static void motorP98FillBackLoop( pScanData ps, pUChar pScanStep, ULong dwStates ) { for (ps->fFullLength = _FALSE; dwStates; dwStates--) { if (*pScanStep == 0xff ) { ULong dw = ps->dwScanStateCount; for (; dwStates; dwStates--) { ps->a_nbNewAdrPointer [dw / 2] &= ((dw & 1) ? 0x7f: 0xf7); dw = (dw + 1U) & _SCANSTATE_MASK; } if (!ps->dwScanStateCount) ps->dwScanStateCount = _NUMBER_OF_SCANSTEPS; ps->dwScanStateCount--; ps->fFullLength = _TRUE; break; } else { ps->a_nbNewAdrPointer [ps->dwScanStateCount / 2] |= ((ps->dwScanStateCount & 1) ? 0x80 : 0x08); if (++ps->dwScanStateCount == _NUMBER_OF_SCANSTEPS) ps->dwScanStateCount = 0; /* reset to begin */ pScanStep++; } } IOSetToMotorStepCount( ps ); /* put all scan states to ASIC */ } /*............................................................................. * */ static void motorP98SetRunFullStep( pScanData ps ) { ps->OpenScanPath( ps ); ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE; IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl ); IODataToRegister( ps, ps->RegLineControl, 96 ); if ( ps->bFastMoveFlag == _FastMove_Low_C75_G150_Back ) { IODataToRegister( ps, ps->RegMotor0Control, (_MotorHQuarterStep + _MotorOn + _MotorDirBackward)); } else { IODataToRegister( ps, ps->RegMotor0Control, (_MotorHQuarterStep + _MotorOn + _MotorDirForward)); } if (ps->bFastMoveFlag == _FastMove_Film_150) { ps->AsicReg.RD_XStepTime = 12; } else { if (ps->bFastMoveFlag == _FastMove_Fast_C50_G100) { ps->AsicReg.RD_XStepTime = ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? 4 : 8); } else { ps->AsicReg.RD_XStepTime = ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) ? 6 : 12); } } DBG( DBG_LOW, "XStepTime = %u\n", ps->AsicReg.RD_XStepTime ); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime); ps->CloseScanPath( ps ); } /*............................................................................. * moves the sensor back home... */ static int motorP98BackToHomeSensor( pScanData ps ) { int result = _OK; TimerDef timer; MotorSetConstantMove( ps, 1 ); ps->OpenScanPath( ps ); ps->AsicReg.RD_StepControl = (_MOTOR_FREERUN + _MOTOR0_SCANSTATE+ _MOTOR0_ONESTEP); IODataToRegister( ps, ps->RegStepControl, ps->AsicReg.RD_StepControl); ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); ps->AsicReg.RD_Motor0Control = _MotorHQuarterStep + _MotorOn + _MotorDirBackward; IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control ); if( ps->DataInf.wPhyDataType >= COLOR_TRUE24) { ps->AsicReg.RD_XStepTime = ps->bSpeed24; } else { ps->AsicReg.RD_XStepTime = ps->bSpeed12; } DBG( DBG_HIGH, "XStepTime = %u\n", ps->AsicReg.RD_XStepTime ); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime ); IORegisterToScanner( ps, ps->RegRefreshScanState ); /* CHANGE: We allow up to 25 seconds for returning (org. val was 10) */ MiscStartTimer( &timer, _SECOND * 25 ); do { if (IODataFromRegister( ps, ps->RegStatus) & _FLAG_P98_PAPER ) { IODataToRegister( ps, ps->RegModelControl, (Byte)(ps->AsicReg.RD_ModelControl | _HOME_SENSOR_POLARITY)); if(!(IODataFromRegister(ps, ps->RegStatus) & _FLAG_P98_PAPER)) break; } _DODELAY( 10 ); /* delay 10 ms */ } while ( !(result = MiscCheckTimer( &timer ))); ps->CloseScanPath( ps ); if( _OK != result ) return result; memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); return _OK; } /*............................................................................. * 1) Clear scan states * 2) Adjust the new scan state */ static void motorP98FillRunNewAdrPointer1( pScanData ps ) { ScanState sState; Byte bTemp; IOGetCurrentStateCount( ps, &sState); bTemp = sState.bStep; if (sState.bStep < ps->bOldStateCount) { sState.bStep += _NUMBER_OF_SCANSTEPS;/* over table (table just can */ } /* holds 64 step, then reset to */ /* 0, so if less than means over*/ /* the table) */ sState.bStep -= ps->bOldStateCount; /* how many states passed */ ps->pScanState += sState.bStep; /* * if current state != no stepped or stepped a cycle, fill the table with * 1 in NOT STEPPED length. (1 means to this state has to be processing). */ ps->bOldStateCount = bTemp; ps->dwScanStateCount = (ULong)((bTemp + 1) & _SCANSTATE_MASK); motorP98FillBackLoop( ps, ps->pScanState, _NUMBER_OF_SCANSTEPS ); } /*............................................................................. * */ static void motorP98FillRunNewAdrPointer( pScanData ps ) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); motorP98FillRunNewAdrPointer1( ps ); } /*............................................................................. * move the sensor to a specific Y-position */ static void motorP98PositionYProc( pScanData ps, ULong dwStates ) { ScanState sState; memset( ps->pColorRunTable, 1, dwStates ); memset( ps->pColorRunTable + dwStates, 0xff, (3800UL - dwStates)); IOGetCurrentStateCount( ps, &sState); ps->bOldStateCount = sState.bStep; ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegMotor0Control, (Byte)(_MotorOn + _MotorHEightStep +(ps->Scan.fMotorBackward)? _MotorDirBackward : _MotorDirForward)); DBG( DBG_LOW, "XStepTime = %u\n", ps->bSpeed6 ); IODataToRegister( ps, ps->RegXStepTime, ps->bSpeed6 ); ps->CloseScanPath( ps ); ps->pScanState = ps->pColorRunTable; ps->FillRunNewAdrPointer( ps ); while(!motorCheckMotorPresetLength( ps )) motorP98FillRunNewAdrPointer1( ps ); } /*............................................................................. * checks if the sensor is in it´s home position and moves it back if necessary */ static int motorP98CheckSensorInHome( pScanData ps ) { int result; if (!(IODataRegisterFromScanner(ps,ps->RegStatus) & _FLAG_P98_PAPER)){ MotorSetConstantMove( ps, 1 ); ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = 0; motorP98PositionYProc( ps, 20 ); result = motorP98BackToHomeSensor( ps ); if( _OK != result ) return result; _DODELAY( 250 ); } return _OK; } /*............................................................................. * move the sensor to the scan-start position */ static void motorP98WaitForPositionY( pScanData ps ) { ULong dw; ULong dwBX, dwDX; if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { motorP98BackToHomeSensor( ps ); _DODELAY( 100 ); /* CHECK do we need this block ? was test code in the original source code */ ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl); IODataToRegister( ps, ps->RegStepControl, (Byte)(_MOTOR_FREERUN + _MOTOR0_SCANSTATE + _MOTOR0_ONESTEP)); IODataToRegister( ps, ps->RegMotor0Control, (Byte)(_MotorOn + _MotorHQuarterStep + _MotorDirForward)); ps->CloseScanPath( ps ); for (dw=1000; dw; dw--) { if (IODataRegisterFromScanner( ps, ps->RegStatus) & _FLAG_P98_PAPER) { IORegisterDirectToScanner( ps, ps->RegForceStep ); _DODELAY( 1000 / 400 ); } } /*-*/ ps->AsicReg.RD_ModeControl = _ModeScan; IOCmdRegisterToScanner( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = 0; ps->bFastMoveFlag = _FastMove_Film_150; if (ps->DataInf.dwScanFlag & SCANDEF_Negative) { MotorP98GoFullStep(ps, (ps->DataInf.crImage.y+_NEG_SCANNINGPOS)/2); } else { MotorP98GoFullStep(ps, (ps->DataInf.crImage.y+_POS_SCANNINGPOS)/2); } return; } ps->AsicReg.RD_ModeControl = _ModeScan; IOCmdRegisterToScanner( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = 0; /* SetStartPoint */ dw = ps->wInitialStep + ps->DataInf.crImage.y; /* * CHANGE: when checking out the values from the NT registry * I found that the values are NOT 0 */ switch (ps->DataInf.wPhyDataType) { case COLOR_BW: dw += _BW_ORIGIN; break; case COLOR_256GRAY: dw += _GRAY_ORIGIN; break; default: dw += _COLOR_ORIGIN; break; } if (dw & 0x80000000) dw = 0; /* negative */ if (dw > 180) { if (ps->bSetScanModeFlag & _ScanMode_Mono) { dwBX = 90; /* go via 150 dpi, so 180 / 2 = 90 */ dwDX = (dw -180) % 3; dw = (dw -180) / 3; /* 100 dpi */ } else { dwBX = 45; /* go via 75 dpi, so 180 / 4 = 45 */ dwDX = (dw -180) % 6; dw = (dw -180) / 6; /* 50 dpi */ } dwDX = (dwDX * 3 + 1) / 2 + dwBX; /* * 100/50 dpi lines is 3/2 times of 150/75 * eax = (remainder * 3 + 1) / 2 + 180 / (2 or 4) lines */ ps->bFastMoveFlag = _FastMove_Low_C75_G150; MotorP98GoFullStep( ps, dwDX); if (dw) { DBG( DBG_LOW, "FAST MOVE MODE !!!\n" ); ps->bFastMoveFlag = _FastMove_Fast_C50_G100; MotorP98GoFullStep( ps, dw); } } else { dwBX = ((ps->bSetScanModeFlag & _ScanMode_Mono) ? 2: 4); dw = (dw + dwBX/2) / dwBX; ps->bFastMoveFlag = _FastMove_Low_C75_G150; MotorP98GoFullStep(ps, dw); } } /*............................................................................. * PreMove/EndMove * PreMove is only in ADF and CFB mode * In ADF version, there is a distance gap between Paper flag and Real initial * position and it need premove to real initial position and turn the motor * Inverse and start Fast move to start scan position * In CFB version , PreMove 1 mm to avoid bouncing of PaperFlag sensor then * fast move * In CIS and CSP although there have not PreMove but there have End move * when paper out there still have several mm need to read, * So it need EndMove 2mm and set Inverse Paper */ static Bool motorP98GotoShadingPosition( pScanData ps ) { int result; DBG( DBG_LOW, "motorP98GotoShadingPosition()\n" ); /* Modify Lamp Back to Home step for Scan twice in short time */ result = motorP98CheckSensorInHome( ps ); if( _OK != result ) return _FALSE; MotorSetConstantMove( ps, 0 ); /* clear scan states */ IOCmdRegisterToScanner( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl ); ps->Scan.fMotorBackward = _FALSE; /* forward */ ps->bExtraMotorCtrl = 0; if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { ps->bFastMoveFlag = _FastMove_Low_C75_G150; MotorP98GoFullStep( ps, 0x40 ); ps->bFastMoveFlag = _FastMove_Middle_C75_G150; MotorP98GoFullStep( ps, ps->Device.dwModelOriginY ); } memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); return _TRUE; } /*............................................................................. * round to the next physical available value */ static void motorP98SetMaxDpiAndLength( pScanData ps, pUShort wLengthY, pUShort wBaseDpi ) { if (ps->DataInf.xyAppDpi.y > 600) *wLengthY = ps->LensInf.rExtentY.wMax * 4 + 200; else *wLengthY = ps->LensInf.rExtentY.wMax * 2 + 200; if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) && (ps->DataInf.xyAppDpi.y <= ps->wMinCmpDpi)) { *wBaseDpi = ps->wMinCmpDpi; } else { if ((ps->DataInf.wPhyDataType < COLOR_TRUE24) && (ps->DataInf.xyAppDpi.y <= 75)) { *wBaseDpi = 75; } else { if (ps->DataInf.xyAppDpi.y <= 150) { *wBaseDpi = 150; } else { if (ps->DataInf.xyAppDpi.y <= 300) { *wBaseDpi = 300; } else { if (ps->DataInf.xyAppDpi.y <= 600) *wBaseDpi = 600; else *wBaseDpi = 1200; } } } } DBG( DBG_LOW, "wBaseDPI = %u, %u\n", *wBaseDpi, ps->wMinCmpDpi ); } /*............................................................................. * */ static void motorP98FillGBColorRunTable( pScanData ps, pUChar pTable, Byte bHi, Byte bLo, UShort wBaseDpi ) { if( ps->Device.f0_8_16 ) { if (wBaseDpi == ps->wMinCmpDpi) { *pTable |= bHi; *(pTable + 1) |= bLo; } else { switch (wBaseDpi) { case 150: *(pTable + 2) |= bHi; *(pTable + 4) |= bLo; break; case 300: *(pTable + 4) |= bHi; *(pTable + 8) |= bLo; break; case 600: *(pTable + 8) |= bHi; *(pTable + 16) |= bLo; break; default: *(pTable + 16) |= bHi; *(pTable + 32) |= bLo; break; } } } else { if (wBaseDpi == ps->wMinCmpDpi) { *pTable |= bHi; *(pTable + 1) |= bLo; } else { switch(wBaseDpi) { case 150: *(pTable + 1) |= bHi; *(pTable + 2) |= bLo; break; case 300: *(pTable + 2) |= bHi; *(pTable + 4) |= bLo; break; case 600: *(pTable + 4) |= bHi; *(pTable + 8) |= bLo; break; default: *(pTable + 8) |= bHi; *(pTable + 16) |= bLo; break; } } } } /*............................................................................. * */ static void motorP98SetupRunTable( pScanData ps ) { UShort wDpi, w, wBaseDpi, wLengthY; pUChar pTable; motorP98SetMaxDpiAndLength( ps, &wLengthY, &wBaseDpi ); /*ClearColorRunTable(); */ memset( ps->pColorRunTable, 0, ps->BufferForColorRunTable ); wDpi = wBaseDpi; w = wLengthY + 1000; pTable = ps->pColorRunTable + (_NUMBER_OF_SCANSTEPS / 4); if( ps->DataInf.wPhyDataType >= COLOR_TRUE24) { for(; w; w--, pTable++) { if((short)(wDpi -= ps->DataInf.xyPhyDpi.y) <= 0) { wDpi += wBaseDpi; *pTable |= 0x44; motorP98FillGBColorRunTable( ps, pTable, 0x22, 0x11, wBaseDpi ); } } } else { for(; w; w--, pTable++) { if((short)(wDpi -= ps->DataInf.xyPhyDpi.y) <= 0) { wDpi += wBaseDpi; *pTable = 0x22; } } } ps->dwColorRunIndex = 0; } /*............................................................................. * */ static void motorP98UpdateDataCurrentReadLine( pScanData ps ) { if(!(ps->Scan.bNowScanState & _SCANSTATE_STOP)) { Byte b; if (ps->Scan.bNowScanState >= ps->bCurrentLineCount) b = ps->Scan.bNowScanState - ps->bCurrentLineCount; else b = ps->Scan.bNowScanState + _NUMBER_OF_SCANSTEPS - ps->bCurrentLineCount; if (b < 40) return; } ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE ); IOSetToMotorRegister( ps ); ps->Scan.bModuleState = _MotorAdvancing; } /*............................................................................. * Byte - Scan State Index (0-63) and StopStep bit * pScanState->bStep - Scan State Index (0-63) * pScanState->bStatus - Scanner Status Register value */ static void motorP96GetScanStateAndStatus( pScanData ps, pScanState pScanStep ) { ps->OpenScanPath( ps ); pScanStep->bStep = IOGetScanState(ps, _TRUE); pScanStep->bStep &= _SCANSTATE_MASK; /* org was. ~_ScanStateStop; */ pScanStep->bStatus = IODataFromRegister( ps, ps->RegStatus ); ps->CloseScanPath( ps ); } /*............................................................................. * Capture the image data and average them. */ static Byte motorP96ReadDarkData( pScanData ps ) { Byte bFifoOffset; UShort wSum, w; TimerDef timer; MiscStartTimer( &timer, _SECOND/2); do { bFifoOffset = IODataRegisterFromScanner( ps, ps->RegFifoOffset ); /* stepped 1 block */ if( bFifoOffset ) { /* read data */ IOReadScannerImageData( ps, ps->pScanBuffer1, 512UL); /* 320 = 192 + 128 (128 is size to fetch data) */ for (w = 192, wSum = 0; w < 320; w++) wSum += (UShort)ps->pScanBuffer1[w];/* average data from */ /* offset 192 and size 128*/ return (Byte)(wSum >> 7); /* divided by 128 */ } } while (!MiscCheckTimer(&timer)); return 0xff; /* timed-out */ } /*............................................................................. * move the sensor to a specific Y-position */ static void motorP96PositionYProc( pScanData ps, ULong dwStates ) { ScanState sState; memset( ps->pColorRunTable, 1, dwStates ); #ifdef DEBUG if( dwStates > 800UL ) DBG( DBG_HIGH, "!!!!! RUNTABLE OVERFLOW !!!!!\n" ); #endif memset( ps->pColorRunTable + dwStates, 0xff, 800UL - dwStates ); IOGetCurrentStateCount( ps, &sState ); ps->bOldStateCount = sState.bStep; /* TurnOnMotorAndSetDirection (); */ if( ps->Scan.fMotorBackward ) { IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->IgnorePF | ps->MotorOn)); } else { IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->IgnorePF | ps->MotorOn | _MotorDirForward)); } ps->pScanState = ps->pColorRunTable; do { ps->FillRunNewAdrPointer( ps ); } while (!motorCheckMotorPresetLength( ps )); } /*............................................................................. * move the sensor to the scan-start position */ static void motorP96WaitForPositionY( pScanData ps ) { /* scheint OKAY zu sein fuer OP4830 */ #ifdef _A3I_EN #warning "compiling for A3I" ULong dw; ScanState sState; memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->Asic96Reg.RD_MotorControl = ps->IgnorePF|ps->MotorOn|_MotorDirForward; ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = ps->IgnorePF; if( ps->DataInf.xyAppDpi.y <= ps->PhysicalDpi ) dw = 30UL; else dw = 46UL; dw = (dw + ps->DataInf.crImage.y) * 4 / 3; if( ps->DataInf.wPhyDataType == COLOR_TRUE24 ) dw += 99; /* dwStepsForColor; */ else if( ps->DataInf.wPhyDataType == COLOR_256GRAY ) dw += 99; /* dwStepsForGray; */ else dw += 99; /* dwStepsForBW; */ if( dw >= 130UL ) { dw -= 100UL; dw <<= 1; /* GoFullStep (dw); */ memset( ps->pColorRunTable, 1, dw ); memset( ps->pColorRunTable + dw, 0xff, ps->BufferForColorRunTable - dw ); IOGetCurrentStateCount( ps, &sState ); ps->bOldStateCount = sState.bStep; /* AdjustMotorTime () */ IOCmdRegisterToScanner( ps, ps->RegLineControl, 31 ); /* SetRunHalfStep () */ if( ps->Scan.fMotorBackward ) IOCmdRegisterToScanner( ps, ps->RegMotorControl, _Motor1FullStep | ps->IgnorePF | ps->MotorOn ); else IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->IgnorePF | ps->MotorOn | _MotorDirForward ); ps->pScanState = ps->pColorRunTable; do { ps->FillRunNewAdrPointer( ps ); } while (!motorCheckMotorPresetLength(ps)); /* RestoreMotorTime () */ IOCmdRegisterToScanner( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); dw = 100UL; } if( ps->DataInf.wPhyDataType != COLOR_TRUE24 ) dw += 20; motorP96PositionYProc( ps, dw ); #else ULong dw; ScanState sState; TimerDef timer; MiscStartTimer( &timer, _SECOND / 4); while (!MiscCheckTimer( &timer )); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); ps->Asic96Reg.RD_MotorControl = ps->IgnorePF|ps->MotorOn|_MotorDirForward; ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = ps->IgnorePF; if ((ps->DataInf.wPhyDataType >= COLOR_TRUE24) || (ps->DataInf.xyAppDpi.y <= 300)) { dw = 6UL; } else { if (ps->DataInf.xyAppDpi.y <= 600) { /* 50 is from 6/300 */ dw = (ULong)ps->DataInf.xyAppDpi.y / 50UL + 3UL; } else dw = 15; /* 6UL * 600UL / 300UL + 3; */ } dw += ps->DataInf.crImage.y; if (dw >= 180UL) { dw -= 180UL; /* GoFullStep (ps, dw);----------------------------------------------*/ memset( ps->pColorRunTable, 1, dw ); #ifdef DEBUG if( dw > 8000UL ) DBG( DBG_HIGH, "!!!!! RUNTABLE OVERFLOW !!!!!\n" ); #endif memset( ps->pColorRunTable + dw, 0xff, 8000UL - dw ); IOGetCurrentStateCount( ps, &sState ); ps->bOldStateCount = sState.bStep; /* SetRunFullStep (ps) */ if( ps->Scan.fMotorBackward ) { IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->FullStep | ps->IgnorePF | ps->MotorOn)); } else { IOCmdRegisterToScanner( ps, ps->RegMotorControl, (Byte)(ps->FullStep | ps->IgnorePF | ps->MotorOn | _MotorDirForward)); } ps->pScanState = ps->pColorRunTable; do { ps->FillRunNewAdrPointer (ps); } while (!motorCheckMotorPresetLength(ps)); /*-------------------------------------------------------------------*/ dw = 180UL; } if (ps->DataInf.wPhyDataType != COLOR_TRUE24) dw = dw * 2 + 16; else dw *= 2; motorP96PositionYProc( ps, dw ); #endif } /*............................................................................. * Position Scan Module to specified line number (Forward or Backward & wait * for paper flag ON) */ static void motorP96ConstantMoveProc1( pScanData ps, ULong dwLines ) { Byte bRemainder, bLastState; UShort wQuotient; ULong dwDelayMaxTime; ScanState StateStatus; TimerDef timer; Bool fTimeout = _FALSE; /* state cycles */ wQuotient = (UShort)(dwLines / _NUMBER_OF_SCANSTEPS); bRemainder = (Byte)(dwLines % _NUMBER_OF_SCANSTEPS); /* 3.3 ms per line */ #ifdef _A3I_EN dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 2; #else dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 20; #endif /* step every time */ MotorSetConstantMove( ps, 1 ); ps->OpenScanPath( ps ); ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, _ModeScan ); ps->Asic96Reg.RD_MotorControl = ps->MotorFreeRun | ps->MotorOn | _MotorDirForward; IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); ps->CloseScanPath( ps ); bLastState = 0; MiscStartTimer( &timer, dwDelayMaxTime ); do { /* GetStatusAndScanStateAddr () */ motorP96GetScanStateAndStatus( ps, &StateStatus ); if (StateStatus.bStatus & _FLAG_P96_PAPER ) { if (wQuotient) { if (StateStatus.bStep != bLastState) { bLastState = StateStatus.bStep; if (!bLastState) wQuotient--; } } else if (StateStatus.bStep >= bRemainder) break; } else break; } while (!(fTimeout = MiscCheckTimer( &timer ))); if (!fTimeout) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); } } /*............................................................................. * PreMove/EndMove * PreMove is only in ADF and CFB mode * In ADF version, there is a distance gap between Paper flag and Real initial * position and it need premove to real initial position and turn the motor * Inverse and start Fast move to start scan position * In CFB version , PreMove 1 mm to avoid bouncing of PaperFlag sensor then * fast move * In CIS and CSP although there have not PreMove but there have End move * when paper out there still have several mm need to read, * So it need EndMove 2mm and set Inverse Paper */ static Bool motorP96GotoShadingPosition( pScanData ps ) { DBG( DBG_LOW, "motorP96GotoShadingPosition()\n" ); MotorSetConstantMove( ps, 0 ); /* clear scan states */ ps->Scan.fMotorBackward = _FALSE; /* forward */ ps->bExtraMotorCtrl = ps->IgnorePF; MotorP96ConstantMoveProc( ps, 15 * 12 ); /* forward 180 lines */ if (IODataRegisterFromScanner(ps, ps->RegStatus) & _FLAG_P96_PAPER ) { ps->Asic96Reg.RD_MotorControl = 0; IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); DBG( DBG_LOW, "motorP96GotoShadingPosition() failed\n" ); return _FALSE; } ps->Scan.fMotorBackward = _TRUE; /* backward */ ps->bExtraMotorCtrl = 0; /* no extra action for motor */ /* backward a few thousand lines to touch sensor */ MotorP96ConstantMoveProc( ps, ps->BackwardSteps ); _DODELAY( 250 ); IOCmdRegisterToScanner( ps, ps->RegModelControl, (Byte)(ps->AsicReg.RD_ModelControl | _ModelInvertPF)); ps->Scan.fMotorBackward = _FALSE; /* forward */ motorP96ConstantMoveProc1( ps, 14 * 12 * 2); /* ahead 336 lines */ if( MODEL_OP_A3I == ps->sCaps.Model ) { motorP96PositionYProc( ps, 80 ); } else { /* forward 24 + pScanData->wOverBlue lines */ if (!ps->fColorMoreRedFlag) motorP96PositionYProc( ps, ps->wOverBlue + 12 * 2); } if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { ps->Scan.fMotorBackward = _FALSE; ps->bExtraMotorCtrl = ps->IgnorePF; MotorP96ConstantMoveProc( ps, 1200 ); } IOCmdRegisterToScanner( ps, ps->RegModelControl, ps->AsicReg.RD_ModelControl ); return _TRUE; } /*............................................................................. * */ static void motorP96FillHalfStepTable( pScanData ps ) { #ifdef _A3I_EN if ( ps->Scan.bModuleState == _MotorInStopState ) { /* clear the table and get the step value */ memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS ); ps->bMotorStepTableNo = a_bMotorDown2Table[(ps->bMotorSpeedData-1)/2]; } /* the fastest stepping */ if( ps->bMotorSpeedData & 1 ) { memset( a_bHalfStepTable, ((ps->Scan.bModuleState != _MotorInStopState) ? 1 : 0), _NUMBER_OF_SCANSTEPS ); } else { pUChar pbHalfStepTbl; Byte bHalfSteps; pUShort pwMoveStep; DataType Data; bHalfSteps = ps->bMotorSpeedData / 2; pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount]; pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount]; if( ps->DataInf.wAppDataType == COLOR_TRUE24) Data.dwValue = _NUMBER_OF_SCANSTEPS - 1; else Data.dwValue = _NUMBER_OF_SCANSTEPS; /* FillDataToHalfStepTable */ for(; Data.dwValue; Data.dwValue-- ) { if( *pwMoveStep ) { /* need to exposure */ if( Data.bValue >= bHalfSteps ) { pUChar pb = pbHalfStepTbl + bHalfSteps; /* AdjustHalfStepStart */ if( ps->DataInf.wAppDataType == COLOR_TRUE24 ) { if (bHalfSteps >= 2) pb -= (bHalfSteps - 1); } if( pb >= pbEndHalfStepTable ) pb -= _NUMBER_OF_SCANSTEPS; if( wP96BaseDpi <= ps->PhysicalDpi && *pwMoveStep != 2 ) *pb = 1; pb += bHalfSteps; if( pb >= pbEndHalfStepTable ) pb -= _NUMBER_OF_SCANSTEPS; *pb = 1; } else *pwMoveStep = 0; /* idle state */ } if( ++pwMoveStep >= pwEndMoveStepTable ) { pwMoveStep = a_wMoveStepTable; pbHalfStepTbl = a_bHalfStepTable; } else pbHalfStepTbl++; } } #else #ifdef DEBUG if( 0 == wP96BaseDpi ) DBG( DBG_HIGH, "!!!! WARNING - motorP96FillHalfStepTable(), " "wP96BaseDpi == 0 !!!!\n" ); #endif if ( ps->Scan.bModuleState == _MotorInStopState ) { /* clear the table and get the step value */ memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS ); ps->bMotorStepTableNo = a_bMotorDown2Table[(ps->bMotorSpeedData-1)/2]; } /* the fastest stepping */ if( ps->bMotorSpeedData & 1 ) { memset( a_bHalfStepTable, ((ps->Scan.bModuleState != _MotorInStopState) ? 1 : 0), _NUMBER_OF_SCANSTEPS ); } else { pUChar pbHalfStepTbl, pbHalfStepContent; pUShort pwMoveStep; DataType Data; pbHalfStepContent = a_pbHalfStepTables[ps->bMotorSpeedData / 2 - 1]; pwMoveStep = &a_wMoveStepTable[ps->bCurrentLineCount]; pbHalfStepTbl = &a_bHalfStepTable[ps->bCurrentLineCount]; if (ps->DataInf.wAppDataType == COLOR_TRUE24) Data.dwValue = _NUMBER_OF_SCANSTEPS - 1; else Data.dwValue = _NUMBER_OF_SCANSTEPS; /* FillDataToHalfStepTable */ for (; Data.dwValue; Data.dwValue--) { if (*pwMoveStep) { /* need to exposure */ if (Data.bValue >= *pbHalfStepContent) { pUChar pb = pbHalfStepTbl + *pbHalfStepContent; if (pb >= pbEndHalfStepTable) pb -= _NUMBER_OF_SCANSTEPS; /* JudgeStep1 () */ if ((wP96BaseDpi != 600) && (*pwMoveStep != 2)) { if (ps->Scan.bModuleState != _MotorInStopState) { *pb = 1; } else { if (ps->bMotorStepTableNo) { ps->bMotorStepTableNo--; *pb = 1; } } } pb += *pbHalfStepContent; if (pb >= pbEndHalfStepTable) pb -= _NUMBER_OF_SCANSTEPS; /* JudgeStep2 () */ if (ps->Scan.bModuleState == _MotorInStopState) { if (ps->bMotorStepTableNo) { ps->bMotorStepTableNo--; *pb = 1; } } else { *pb = 1; } pbHalfStepContent++; } else { *pwMoveStep = 0; /* idle state */ } } if (++pwMoveStep >= pwEndMoveStepTable) { pwMoveStep = a_wMoveStepTable; pbHalfStepTbl = a_bHalfStepTable; } else { pbHalfStepTbl++; } } } #endif } /*............................................................................. * */ static void motorP96FillDataToColorTable( pScanData ps, Byte bIndex, ULong dwSteps) { Byte bColor, bColors; pUChar pb, pb1; pUShort pw; DataType Data; for (pb = &a_bColorByteTable[bIndex], pw = &a_wMoveStepTable[bIndex]; dwSteps; dwSteps--) { if (*pw) { /* valid state */ if( *pw >= ps->BufferForColorRunTable ) { DBG( DBG_LOW, "*pw = %u > %u !!\n", *pw, ps->BufferForColorRunTable ); } else { bColor = ps->pColorRunTable [*pw]; /* get the colors */ bColors = a_bColorsSum [bColor & 7];/* number of colors */ if (bColors) { /* need to read data */ if (dwSteps >= bColors) { /* enough room */ /* separate the colors to byte */ pb1 = pb; if (bColor & ps->b1stColor) { *pb1 = ps->b1stColorByte; if (++pb1 >= pbEndColorByteTable) pb1 = a_bColorByteTable; } if (bColor & ps->b2ndColor) { *pb1 = ps->b2ndColorByte; if (++pb1 >= pbEndColorByteTable) pb1 = a_bColorByteTable; } if (bColor & ps->b3rdColor) *pb1 = ps->b3rdColorByte; } else *pw = 0; } } } if (++pw >= pwEndMoveStepTable) { pw = a_wMoveStepTable; pb = a_bColorByteTable; } else pb++; } /* ps->bOldSpeed = ps->bMotorRunStatus; non functional */ /* ToCondense, CondenseColorByteTable */ for (dwSteps = _SCANSTATE_BYTES, pw = (pUShort)a_bColorByteTable, pb = ps->a_nbNewAdrPointer; dwSteps; dwSteps--, pw++, pb++) { Data.wValue = *pw & 0x0303; *pb = Data.wOverlap.b1st | (Data.wOverlap.b2nd << 4); } /* ToCondenseMotor */ for (dwSteps = _SCANSTATE_BYTES, pb1 = a_bHalfStepTable, pb = ps->a_nbNewAdrPointer; dwSteps; dwSteps--, pb1++, pb++) { if (*pb1++) *pb |= 4; if (*pb1) *pb |= 0x40; } } /*............................................................................. * */ static void motorP96FillBackColorDataTable( pScanData ps ) { Byte bIndex; ULong dw; if ((ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1) >= _NUMBER_OF_SCANSTEPS){ bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1 - _NUMBER_OF_SCANSTEPS; } else { bIndex = ps->bCurrentLineCount + ps->bNewCurrentLineCountGap + 1; } dw = _NUMBER_OF_SCANSTEPS - ps->bNewCurrentLineCountGap; motorP96FillDataToColorTable( ps, bIndex, dw ); } /*............................................................................. * i/p: * pScanStep = pScanData->pColorRunTable if forward, a_bScanStateTable if backward * dwState = how many states is requested to process * NOTE: * The content of pScanStep contain: * 0: Idle state * 0xff: End mark * others: The motor speed value */ static void motorP96FillBackLoop( pScanData ps, pUChar pScanStep, ULong dwStates ) { for (; dwStates; dwStates--) { if (*pScanStep == 0xff) break; /* end of states */ if (*pScanStep) { if (*pScanStep == 1) { /* speed == 1, this state has to step */ if (ps->dwScanStateCount & 1) ps->a_nbNewAdrPointer[ps->dwScanStateCount / 2] |= 0x40; else ps->a_nbNewAdrPointer[ps->dwScanStateCount / 2] |= 0x04; } *pScanStep -= 1; /* speed decrease by 1 */ if (!(*pScanStep)) pScanStep++; /* state processed */ } else pScanStep++; /* skip this state */ if (++ps->dwScanStateCount == _NUMBER_OF_SCANSTEPS) ps->dwScanStateCount = 0; /* reset to begin */ } if (*pScanStep != 0xff) ps->fFullLength = _FALSE; else ps->fFullLength = _TRUE; IOSetToMotorStepCount( ps ); /* put all scan states to ASIC */ } /*............................................................................. * 1) Clear scan states * 2) Adjust the new scan state */ static void motorP96FillRunNewAdrPointer( pScanData ps ) { ScanState sState; memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES); IOGetCurrentStateCount( ps, &sState ); if (sState.bStep < ps->bOldStateCount ) sState.bStep += _NUMBER_OF_SCANSTEPS;/* over table (table just can */ /* holds 64 step, then reset to */ /* 0, so if less than means over*/ /* the table) */ sState.bStep -= ps->bOldStateCount; /* how many states passed */ ps->pScanState += sState.bStep; /* * if current state != no stepped or stepped a cycle, fill the table with * 1 in NOT STEPPED length. (1 means to this state has to be processing). */ if (sState.bStep && sState.bStep != (_NUMBER_OF_SCANSTEPS - 1)) memset( ps->pScanState, 1, _NUMBER_OF_SCANSTEPS - sState.bStep - 1 ); IOGetCurrentStateCount( ps, &sState); ps->bOldStateCount = sState.bStep; /* update current state */ ps->dwScanStateCount = (ULong)((sState.bStep + 1) & (_NUMBER_OF_SCANSTEPS - 1)); /* fill begin at next step */ motorP96FillBackLoop( ps, ps->pScanState, (_NUMBER_OF_SCANSTEPS - 1)); } /*............................................................................. * */ static void motorP96SetupRunTable( pScanData ps ) { Short siSum; UShort wLoop; UShort wLengthY; DataPointer p; DBG( DBG_LOW, "motorP96SetupRunTable()\n" ); /* SetMaxDpiAndLength (ps) */ #ifdef _A3I_EN if( ps->DataInf.xyPhyDpi.y > ps->PhysicalDpi ) { wLengthY = 6800 * 2; wP96BaseDpi = ps->PhysicalDpi *2; } else { wLengthY = 6800; wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax >> 1; } #else if( ps->DataInf.xyPhyDpi.y > (ps->LensInf.rDpiY.wPhyMax / 2)) { wLengthY = ps->LensInf.rExtentY.wMax << 1; wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax; } else { wLengthY = ps->LensInf.rExtentY.wMax; wP96BaseDpi = ps->LensInf.rDpiY.wPhyMax >> 1; } #endif DBG( DBG_LOW, "wLengthY = %u, wP96BaseDpi = %u\n", wLengthY, wP96BaseDpi ); /* ClearColorRunTable (ps) */ memset( ps->pColorRunTable, 0, ps->BufferForColorRunTable ); /*wLengthY + 0x60 ); */ p.pb = ps->pColorRunTable + _SCANSTATE_BYTES; #ifdef _A3I_EN wLoop = wLengthY + 200; #else wLoop = wLengthY + 0x20; #endif siSum = (Short)wP96BaseDpi; if (ps->DataInf.wPhyDataType != COLOR_TRUE24) { for (; wLoop; wLoop--, p.pb++) { if ((siSum -= (Short)ps->DataInf.xyPhyDpi.y) <= 0) { siSum += (Short)wP96BaseDpi; *p.pb = _COLORRUNTABLE_GREEN; } } #ifdef _A3I_EN memset( ps->pColorRunTable + _NUMBER_OF_SCANSTEPS / 8 + wLengthY, 0x77, 0x100 ); #endif } else { /* CalColorRunTable */ DataType Data; if (ps->fSonyCCD) { if((ps->sCaps.Model == MODEL_OP_12000P) || (ps->sCaps.Model == MODEL_OP_A3I)) { Data.wValue = (_COLORRUNTABLE_RED << 8) | _COLORRUNTABLE_BLUE; } else { Data.wValue = (_COLORRUNTABLE_GREEN << 8) | _COLORRUNTABLE_BLUE; } } else { Data.wValue = (_COLORRUNTABLE_BLUE << 8) | _COLORRUNTABLE_GREEN; } for (; wLoop; wLoop--, p.pb++) { if ((siSum -= (Short)ps->DataInf.xyPhyDpi.y) <= 0) { siSum += (Short)wP96BaseDpi; if((ps->sCaps.Model == MODEL_OP_12000P)|| (ps->sCaps.Model == MODEL_OP_A3I)) { *p.pb |= _COLORRUNTABLE_GREEN; } else { *p.pb |= _COLORRUNTABLE_RED; } /* Sony:Green,Toshiba:Blue */ *(p.pb + 8) |= Data.wOverlap.b2nd; *(p.pb + 16) |= Data.wOverlap.b1st; } } #ifdef _A3I_EN memset( ps->pColorRunTable + _NUMBER_OF_SCANSTEPS / 8 + wLengthY, 0x77, 0x100 ); #endif if (ps->DataInf.xyPhyDpi.y < 100) { Byte bColor; /* CheckColorTable () */ if (ps->fSonyCCD) Data.wValue = 0xdd22; else Data.wValue = 0xbb44; for (wLoop = wLengthY - _SCANSTATE_BYTES, p.pb = ps->pColorRunTable + _SCANSTATE_BYTES; wLoop; wLoop--, p.pb++) { bColor = 0; switch (a_bColorsSum[*p.pb & 0x0f]) { case 3: if (*(p.pb + 2)) bColor = 1; case 2: if (*(p.pb + 1)) bColor++; if (bColor == 2) { *p.pb &= ~_COLORRUNTABLE_RED; *(p.pb - 2) = _COLORRUNTABLE_RED; } if (bColor) { if (*p.pb & ps->RedDataReady) { *p.pb &= ~_COLORRUNTABLE_RED; *(p.pb - 1) = _COLORRUNTABLE_RED; } else { *p.pb &= Data.wOverlap.b2nd; *(p.pb - 1) = Data.wOverlap.b1st; } } } } } } } /*............................................................................. * */ static void motorP96UpdateDataCurrentReadLine( pScanData ps ) { ScanState State1, State2; TimerDef timer; IOGetCurrentStateCount( ps, &State1 ); IOGetCurrentStateCount( ps, &State2 ); if (State1.bStatus == State2.bStatus) { if (!(State2.bStatus & _SCANSTATE_STOP)) { /* motor still running */ if (State2.bStep < ps->bCurrentLineCount) { State2.bStep = State2.bStep + _NUMBER_OF_SCANSTEPS - ps->bCurrentLineCount; } else State2.bStep -= ps->bCurrentLineCount; if (State2.bStep >= (_NUMBER_OF_SCANSTEPS - 3)) { MiscStartTimer( &timer, _SECOND ); do { State2.bStatus = IOGetScanState( ps, _FALSE ); } while (!(State2.bStatus & _SCANSTATE_STOP) && !MiscCheckTimer( &timer )); } else if (State2.bStep < 40) return; } #ifdef _A3I_EN if( ps->bFifoCount >= 140) { #else if( ps->bFifoCount >= 20) { #endif if( 1 == ps->bCurrentSpeed ) { ps->bCurrentSpeed *= 2; } else { if( COLOR_TRUE24 == ps->DataInf.wPhyDataType ) ps->bCurrentSpeed += 4; else ps->bCurrentSpeed += 2; } MotorP96AdjustCurrentSpeed( ps, ps->bCurrentSpeed ); } /* * when using the full-step speed on 600 dpi models, then set * the motor into half-step mode, to avoid that the scanner hits * the back of its bed */ /* HEINER:A3I */ #if 1 if((600 == ps->PhysicalDpi) && (1 == ps->bCurrentSpeed)) { if( ps->Asic96Reg.RD_MotorControl & ps->FullStep ) { ps->Asic96Reg.RD_MotorControl &= ~ps->FullStep; IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); } } #endif ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _TRUE ); IOSetToMotorRegister( ps); } } /*............................................................................. * 1) Save the current scan state * 2) Set the motor direction */ static void motorGoHalfStep1( pScanData ps ) { ScanState sState; IOGetCurrentStateCount( ps, &sState ); ps->bOldStateCount = sState.bStep; motorSetRunPositionRegister(ps); ps->pScanState = a_bScanStateTable; if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ps->FillRunNewAdrPointer( ps ); while (!motorCheckMotorPresetLength(ps)) motorP98FillRunNewAdrPointer1( ps ); } else { while (!motorCheckMotorPresetLength( ps )) ps->FillRunNewAdrPointer( ps ); } } /*............................................................................. * when loosing data, we use this function to go back some lines and read them * again... */ static void motorP96WaitBack( pScanData ps ) { DataPointer p; DataType Data; ULong dw; UShort w; UShort wStayMaxStep; /* FindMaxMoveStepIndex () */ p.pw = a_wMoveStepTable; for( Data.dwValue = _NUMBER_OF_SCANSTEPS, wStayMaxStep = 1; Data.dwValue; Data.dwValue--, p.pw++ ) if( *p.pw > wStayMaxStep ) wStayMaxStep = *p.pw; /* save the largest step number */ if( ps->DataInf.xyPhyDpi.y > ps->PhysicalDpi ) wStayMaxStep -= 40; else wStayMaxStep -= 20; IORegisterDirectToScanner( ps, ps->RegInitDataFifo ); memset( a_bScanStateTable, 1, _P96_BACKMOVES ); memset(&a_bScanStateTable[_P96_BACKMOVES], 0xff, 250 - _P96_BACKMOVES ); ps->Scan.fMotorBackward = _TRUE; motorGoHalfStep1( ps ); /* backward 130 lines */ _DODELAY(200); /* let the motor stable */ if( ps->DataInf.xyPhyDpi.y <= ps->PhysicalDpi ) { if( ps->DataInf.wPhyDataType == COLOR_TRUE24 ) { dw = _P96_FORWARDMOVES - 1; } else { dw = _P96_FORWARDMOVES - 2; } } else { dw = _P96_FORWARDMOVES; } memset( a_bScanStateTable, 1, dw ); memset(&a_bScanStateTable[dw], 0xff, 250 - dw ); ps->Scan.fMotorBackward = _FALSE; motorGoHalfStep1( ps ); /* move forward */ /* GetNowStepTable () */ ps->bCurrentLineCount = IOGetScanState( ps, _FALSE ) & _SCANSTATE_MASK; ps->bNewCurrentLineCountGap = 0; /* ClearColorByteTable () */ memset( a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS ); /* ClearHalfStepTable () */ memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS ); /* FillWaitMoveStepTable () */ p.pw = &a_wMoveStepTable[((ps->bCurrentLineCount + 1) & 0x3f)]; *p.pw = 1; p.pw++; for(w = wStayMaxStep, Data.bValue = ps->bMotorSpeedData, dw = 60;dw;dw--) { if( p.pw >= pwEndMoveStepTable ) /* make sure pointer in range */ p.pw = a_wMoveStepTable; if (--Data.bValue) *p.pw = 0; /* don't step */ else { Data.bValue = ps->bMotorSpeedData; /* speed value */ *p.pw = w; /* the ptr to pColorRunTable */ w++; /* pointer++ */ } p.pw++; /* to next entry */ } motorP96FillHalfStepTable( ps ); motorP96FillBackColorDataTable( ps ); } /*............................................................................. * when loosing data, we use this function to go back some lines and read them * again... */ static void motorP98WaitBack( pScanData ps ) { DataPointer p; DataType Data; ULong dw; UShort w; UShort wStayMaxStep; UShort back, forward; p.pw = &a_wMoveStepTable[ps->bCurrentLineCount]; if (0 == *p.pw) { for (w = _NUMBER_OF_SCANSTEPS; w && !*p.pw; w--) { p.pw--; if (p.pw < a_wMoveStepTable) p.pw = &a_wMoveStepTable[_NUMBER_OF_SCANSTEPS - 1]; } wStayMaxStep = *p.pw + 1; } else { wStayMaxStep = *p.pw; /* save the largest step number */ } if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { forward = _P98_FORWARDMOVES; back = _P98_BACKMOVES; } else { forward = _P96_FORWARDMOVES; back = _P96_BACKMOVES; } /* * Off to avoid the problem of block data re-read/lost */ memset( a_bScanStateTable, 1, back ); memset( &a_bScanStateTable[back], 0xff, (_SCANSTATE_TABLE_SIZE - back)); ps->Scan.fMotorBackward = _TRUE; motorGoHalfStep1( ps ); _DODELAY(200); /* let the motor stable */ memset(a_bScanStateTable, 1, forward ); memset(&a_bScanStateTable[forward], 0xff, (_SCANSTATE_TABLE_SIZE-forward)); ps->Scan.fMotorBackward = _FALSE; motorGoHalfStep1( ps ); ps->bNewCurrentLineCountGap = 0; memset( a_bColorByteTable, 0, _NUMBER_OF_SCANSTEPS ); memset( a_bHalfStepTable, 0, _NUMBER_OF_SCANSTEPS ); ps->bCurrentLineCount = (ps->bCurrentLineCount + 1) & 0x3f; p.pw = &a_wMoveStepTable[ps->bCurrentLineCount]; for (w = wStayMaxStep, Data.bValue = ps->bMotorSpeedData, dw = _NUMBER_OF_SCANSTEPS; dw; dw--) { if (--Data.bValue) { *p.pw = 0; /* don't step */ } else { /* speed value */ Data.bValue = ps->bMotorSpeedData; *p.pw = w; /* the pointer to pColorRunTable*/ w++; /* pointer++ */ } /* make sure pointer in range */ if (++p.pw >= pwEndMoveStepTable) p.pw = a_wMoveStepTable; } if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { motorP98FillHalfStepTable( ps ); motorP98FillBackColorDataTable( ps ); } else { motorP96FillHalfStepTable( ps ); motorP96FillBackColorDataTable( ps ); } } /*............................................................................. * */ static void motorFillMoveStepTable( pScanData ps, UShort wIndex, Byte bStep, pUShort pw ) { UShort w; Byte b; if (++pw >= pwEndMoveStepTable ) pw = a_wMoveStepTable; wIndex++; b = ps->bMotorSpeedData; for (w = _NUMBER_OF_SCANSTEPS - bStep; w; w--) { if (b == 1) { b = ps->bMotorSpeedData; *pw = wIndex; wIndex++; } else { b--; *pw = 0; } if (++pw >= pwEndMoveStepTable) pw = a_wMoveStepTable; } if( _ASIC_IS_98001 == ps->sCaps.AsicID ) motorP98FillHalfStepTable( ps ); else motorP96FillHalfStepTable( ps ); if ((ps->bCurrentLineCount + 1) >= _NUMBER_OF_SCANSTEPS) { b = ps->bCurrentLineCount + 1 - _NUMBER_OF_SCANSTEPS; } else { b = ps->bCurrentLineCount + 1; } if( _ASIC_IS_98001 == ps->sCaps.AsicID ) motorP98FillDataToColorTable( ps, b, _NUMBER_OF_SCANSTEPS - 1); else motorP96FillDataToColorTable( ps, b, _NUMBER_OF_SCANSTEPS - 1); } /*............................................................................. * */ static void noMotorRunStatusStop( pScanData ps, Byte bScanState ) { Byte b, b1, bCur; pUShort pw; pByte pb; UShort w; ps->bCurrentLineCount = (bScanState & _SCANSTATE_MASK); ps->Scan.fRefreshState = _FALSE; IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); bCur = ps->bCurrentLineCount; pw = &a_wMoveStepTable[bCur]; pb = ps->pColorRunTable; b = 0; b1 = 0; w = _NUMBER_OF_SCANSTEPS; if (*pw) { b = a_bColorsSum[pb [*pw] >> 4]; if (b) { motorClearColorByteTableLoop0( ps, b ); ps->bNewCurrentLineCountGap = b; motorFillMoveStepTable( ps, *pw, 1, pw ); return; } b1++; bCur--; if (--pw < a_wMoveStepTable) { pw = &a_wMoveStepTable [_NUMBER_OF_SCANSTEPS - 1]; bCur = _NUMBER_OF_SCANSTEPS - 1; } } for(; w; w--) { if (*pw) { if (*pw < _SCANSTATE_BYTES) { b = 0; break; } else if ((b = a_bColorsSum [pb [*pw] >> 4])) break; } b1++; bCur--; if (--pw < a_wMoveStepTable) { pw = &a_wMoveStepTable [_NUMBER_OF_SCANSTEPS - 1]; bCur = _NUMBER_OF_SCANSTEPS - 1; } } if (b1 == _NUMBER_OF_SCANSTEPS) { ps->bNewCurrentLineCountGap = 0; ps->bNewGap = 0; } else { ps->bNewCurrentLineCountGap = b1; ps->bNewGap = b; } motorClearColorByteTableLoop1( ps ); motorFillMoveStepTable( ps, *pw, 0, pw); } /*............................................................................. * */ static void motorP96SetSpeed( pScanData ps, Byte bSpeed, Bool fSetRunState ) { #if 0 PUCHAR pb; Byte bScanState; #endif Byte bState, bData; UShort wMoveStep; pUShort pw; ULong dw; TimerDef timer; if( fSetRunState ) ps->Scan.bModuleState = _MotorInNormalState; ps->bMotorSpeedData = bSpeed; if( ps->bMoveDataOutFlag == _DataAfterRefreshState) { ps->bMoveDataOutFlag = _DataInNormalState; MiscStartTimer( &timer, (_SECOND /2)); while (!MiscCheckTimer(&timer)) { if ((bState = IOGetScanState( ps, _FALSE)) & _SCANSTATE_STOP) { ps->bCurrentLineCount = bState & ~_SCANSTATE_STOP; motorP96WaitBack( ps ); return; } } } bState = IOGetScanState( ps, _FALSE ); if((ps->Scan.bModuleState != _MotorInStopState) || !(bState & _SCANSTATE_STOP)) { /* Try to find the available step for all rest steps. * 1) if current step is valid (with data request), fill all steps * after it * 2) if current step is NULL (for delay purpose), backward search the * valid entry, then fill all steps after it * 3) if no step is valid, fill all entries */ Byte bColors = 0; UShort w; /* NoMotorRunStatusStop () */ ps->bCurrentLineCount = (bState &= _SCANSTATE_MASK); ps->Scan.fRefreshState = _TRUE; IORegisterDirectToScanner( ps, ps->RegRefreshScanState ); pw = &a_wMoveStepTable[bState]; bData = 0; bState = ps->bCurrentLineCount; dw = _NUMBER_OF_SCANSTEPS; if( (wMoveStep = *pw) ) { bColors = a_bColorsSum[ ps->pColorRunTable[*pw] / 16]; if( bColors ) { motorClearColorByteTableLoop0( ps, bColors ); ps->bNewCurrentLineCountGap = bColors; bColors = 1; goto FillMoveStepTable; } else { bData++; dw--; if( --pw < a_wMoveStepTable ) { pw = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS - 1; bState = _NUMBER_OF_SCANSTEPS - 1; } else bState--; } } /* FindNextStep */ while( dw-- ) { if( (wMoveStep = *pw) ) { if (wMoveStep < (_NUMBER_OF_SCANSTEPS / 2)) { bColors = 0; break; } if((bColors = a_bColorsSum [ps->pColorRunTable[wMoveStep] / 16])) break; } bData++; if( --pw < a_wMoveStepTable ) { pw = a_wMoveStepTable + _NUMBER_OF_SCANSTEPS - 1; bState = _NUMBER_OF_SCANSTEPS - 1; } else bState--; } if (bData == _NUMBER_OF_SCANSTEPS ) bData = bColors = 0; ps->bNewCurrentLineCountGap = bData; ps->bNewGap = bColors; motorClearColorByteTableLoop1( ps ); bColors = 0; /* use pw (new pointer) and new speed to recreate MoveStepTable * wMoveStep = Index number from a_wMoveStepTable ([esi]) * bColors = number of steps should be reserved * pw = where to fill */ FillMoveStepTable: motorP96GetStartStopGap( ps, _TRUE ); if( !ps->bMotorStepTableNo ) ps->bMotorStepTableNo = 1; if( ps->bMotorStepTableNo != 0xff && ps->IO.portMode == _PORT_SPP && ps->DataInf.xyPhyDpi.y <= 200) { ps->bMotorStepTableNo++; } if (++pw >= pwEndMoveStepTable) pw = a_wMoveStepTable; for( dw = _NUMBER_OF_SCANSTEPS - bColors, wMoveStep++, bData = ps->bMotorSpeedData; dw; dw-- ) { if( bData == 1 ) { bData = ps->bMotorSpeedData; if( ps->bMotorStepTableNo ) { ps->bMotorStepTableNo--; w = wMoveStep; wMoveStep++; } else { bData--; w = 0; } } else { bData--; w = 0; } *pw = w; if (++pw >= pwEndMoveStepTable) pw = a_wMoveStepTable; } motorP96FillHalfStepTable( ps ); /* FillColorBytesTable */ if((ps->bCurrentLineCount + 1) < _NUMBER_OF_SCANSTEPS ) bState = ps->bCurrentLineCount + 1; else bState = ps->bCurrentLineCount + 1 - _NUMBER_OF_SCANSTEPS; motorP96FillDataToColorTable( ps, bState, _NUMBER_OF_SCANSTEPS - 1); } } /*............................................................................. * */ static void motorP98SetSpeed( pScanData ps, Byte bSpeed, Bool fSetRunState ) { static Byte lastFifoState = 0; Bool overflow; Byte bOld1ScanState, bData; if( fSetRunState ) ps->Scan.bModuleState = _MotorInNormalState; ps->bMotorSpeedData = bSpeed; overflow = _FALSE; if( _ASIC_IS_98001 != ps->sCaps.AsicID ) { ps->bMoveDataOutFlag = _DataInNormalState; bData = IODataRegisterFromScanner( ps, ps->RegFifoOffset ); if((lastFifoState > _P96_FIFOOVERFLOWTHRESH) && (bData < lastFifoState)) { DBG( DBG_HIGH, "FIFO OVERFLOW, loosing data !!\n" ); overflow = _TRUE; } lastFifoState = bData; } bOld1ScanState = IOGetScanState( ps, _FALSE ); if(!(bOld1ScanState & _SCANSTATE_STOP) && !overflow) noMotorRunStatusStop( ps, bOld1ScanState ); else { ps->bCurrentLineCount = (bOld1ScanState & 0x3f); ps->Scan.bModuleState = _MotorGoBackward; motorP98WaitBack( ps ); if( overflow ) lastFifoState = 0; if( _ASIC_IS_98001 != ps->sCaps.AsicID ) ps->bMoveDataOutFlag = _DataFromStopState; } } /*............................................................................. * */ static void motorP98003ModuleFreeRun( pScanData ps, ULong steps ) { IODataToRegister( ps, ps->RegMotorFreeRunCount1, (_HIBYTE(steps))); IODataToRegister( ps, ps->RegMotorFreeRunCount0, (_LOBYTE(steps))); IORegisterToScanner( ps, ps->RegMotorFreeRunTrigger ); } /*............................................................................. * */ static void motorP98003ModuleToHome( pScanData ps ) { if(!(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) { IODataToRegister( ps, ps->RegMotor0Control, (Byte)(ps->AsicReg.RD_Motor0Control|_MotorDirForward)); MotorP98003PositionYProc( ps, 40 ); MotorP98003BackToHomeSensor( ps ); _DODELAY( 250 ); } } /*............................................................................. * */ static void motorP98003DownloadNullScanStates( pScanData ps ) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IODownloadScanStates( ps ); } /*............................................................................. * */ static void motorP98003Force16Steps( pScanData ps ) { ULong dw; IODataToRegister( ps, ps->RegStepControl, _MOTOR0_ONESTEP); IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR ); for(dw = 16; dw; dw--) { IORegisterToScanner( ps, ps->RegForceStep ); _DODELAY( 10 ); } IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE ); } /*............................................................................. * */ static void motorP98003WaitForPositionY( pScanData ps ) { Byte bXStep; ULong dwBeginY; dwBeginY = (ULong)ps->DataInf.crImage.y * 4 + ps->Scan.dwScanOrigin; if( ps->DataInf.wPhyDataType <= COLOR_256GRAY ) { if( ps->Device.f0_8_16 ) dwBeginY += 16; else dwBeginY += 8; } bXStep = (Byte)((ps->DataInf.wPhyDataType <= COLOR_256GRAY) ? ps->Device.XStepMono : ps->Device.XStepColor); if( ps->Shade.bIntermediate & _ScanMode_AverageOut ) bXStep = 8; motorP98003Force16Steps( ps); dwBeginY -= 16; if (dwBeginY > (_RFT_SCANNING_ORG + _P98003_YOFFSET) && bXStep < ps->AsicReg.RD_XStepTime) { IODataToRegister( ps, ps->RegMotorDriverType, ps->Scan.motorPower ); _DODELAY( 12 ); IODataToRegister( ps, ps->RegXStepTime, bXStep); IODataToRegister( ps, ps->RegExtendedXStep, 0 ); IODataToRegister( ps, ps->RegScanControl1, (UChar)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); MotorP98003PositionYProc( ps, dwBeginY - 64 ); dwBeginY = 64; } IODataToRegister( ps, ps->RegFifoFullLength0, _LOBYTE(ps->AsicReg.RD_BufFullSize)); IODataToRegister( ps, ps->RegFifoFullLength1, _HIBYTE(ps->AsicReg.RD_BufFullSize)); IODataToRegister( ps, ps->RegFifoFullLength2, _LOBYTE(_HIWORD(ps->AsicReg.RD_BufFullSize))); IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType); _DODELAY( 12 ); if(!ps->Device.f2003 || (ps->Shade.bIntermediate & _ScanMode_AverageOut) || ( ps->DataInf.xyAppDpi.y <= 75 && ps->DataInf.wPhyDataType <= COLOR_256GRAY)) { IODataToRegister( ps, ps->RegMotorDriverType, (Byte)(ps->Scan.motorPower & (_MOTORR_MASK | _MOTORR_STRONG))); } else { IODataToRegister( ps, ps->RegMotorDriverType, ps->AsicReg.RD_MotorDriverType ); } IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime ); IODataToRegister( ps, ps->RegExtendedXStep, ps->AsicReg.RD_ExtXStepTime ); IODataToRegister( ps, ps->RegScanControl1, (Byte)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); if( ps->DataInf.dwVxdFlag & _VF_PREVIEW ) { TimerDef timer; motorP98003ModuleFreeRun( ps, dwBeginY ); _DODELAY( 15 ); MiscStartTimer( &timer, (_SECOND * 20)); while(( IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING) && !MiscCheckTimer(&timer)); IODataToRegister( ps, ps->RegModeControl, _ModeScan ); } else { MotorP98003PositionYProc( ps, dwBeginY ); IORegisterToScanner( ps, ps->RegRefreshScanState ); } } /*............................................................................. * move the sensor to the appropriate shading position */ static Bool motorP98003GotoShadingPosition( pScanData ps ) { motorP98003ModuleToHome( ps ); /* position to somewhere under the transparency adapter */ if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { MotorP98003ForceToLeaveHomePos( ps ); motorP98003DownloadNullScanStates( ps ); IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE ); IODataToRegister( ps, ps->RegModeControl, _ModeScan); IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR ); IODataToRegister( ps, ps->RegXStepTime, 6); IODataToRegister( ps, ps->RegExtendedXStep, 0); IODataToRegister( ps, ps->RegScanControl1, _MFRC_BY_XSTEP); MotorP98003PositionYProc( ps, _TPA_P98003_SHADINGORG ); } return _TRUE; } /*............................................................................. * initialize this module and setup the correct function pointer according * to the ASIC */ static void motorP98003PositionModuleToHome( pScanData ps ) { Byte save, saveModel; saveModel = ps->AsicReg.RD_ModelControl; ps->Scan.fRefreshState = _FALSE; motorP98003DownloadNullScanStates( ps ); _DODELAY( 1000UL / 8UL); save = ps->Shade.bIntermediate; ps->Shade.bIntermediate = _ScanMode_AverageOut; ps->ReInitAsic( ps, _FALSE ); ps->Shade.bIntermediate = save; IODataToRegister( ps, ps->RegModeControl, _ModeScan ); IORegisterToScanner( ps, ps->RegResetMTSC ); IODataToRegister( ps, ps->RegScanControl1, 0 ); IODataToRegister( ps, ps->RegModelControl, ps->Device.ModelCtrl | _ModelDpi300 ); IODataToRegister( ps, ps->RegLineControl, 80); IODataToRegister( ps, ps->RegXStepTime, ps->Device.XStepBack); IODataToRegister( ps, ps->RegMotorDriverType, ps->Scan.motorPower); _DODELAY( 12 ); IODataToRegister( ps, ps->RegMotor0Control, (_MotorHHomeStop | _MotorOn | _MotorHQuarterStep | _MotorPowerEnable)); IODataToRegister( ps, ps->RegStepControl, (_MOTOR0_SCANSTATE | _MOTOR_FREERUN)); memset( ps->a_nbNewAdrPointer, 0x88, _SCANSTATE_BYTES ); IODownloadScanStates( ps ); IORegisterToScanner( ps, ps->RegRefreshScanState ); ps->AsicReg.RD_ModelControl = saveModel; } /************************ exported functions *********************************/ /*............................................................................. * initialize this module and setup the correct function pointer according * to the ASIC */ _LOC int MotorInitialize( pScanData ps ) { DBG( DBG_HIGH, "MotorInitialize()\n" ); if( NULL == ps ) return _E_NULLPTR; ps->a_wMoveStepTable = a_wMoveStepTable; ps->a_bColorByteTable = a_bColorByteTable; wP96BaseDpi = 0; ps->PauseColorMotorRunStates = motorPauseColorMotorRunStates; /* * depending on the asic, we set some functions */ if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ps->WaitForPositionY = motorP98WaitForPositionY; ps->GotoShadingPosition = motorP98GotoShadingPosition; ps->FillRunNewAdrPointer = motorP98FillRunNewAdrPointer; ps->SetupMotorRunTable = motorP98SetupRunTable; ps->UpdateDataCurrentReadLine = motorP98UpdateDataCurrentReadLine; ps->SetMotorSpeed = motorP98SetSpeed; } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->WaitForPositionY = motorP98003WaitForPositionY; ps->GotoShadingPosition = motorP98003GotoShadingPosition; ps->SetMotorSpeed = motorP98SetSpeed; } else if( _IS_ASIC96(ps->sCaps.AsicID)) { ps->WaitForPositionY = motorP96WaitForPositionY; ps->GotoShadingPosition = motorP96GotoShadingPosition; ps->FillRunNewAdrPointer = motorP96FillRunNewAdrPointer; ps->SetupMotorRunTable = motorP96SetupRunTable; ps->UpdateDataCurrentReadLine = motorP96UpdateDataCurrentReadLine; ps->SetMotorSpeed = motorP96SetSpeed; } else { DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); return _E_NOSUPP; } return _OK; } /*............................................................................. * */ _LOC void MotorSetConstantMove( pScanData ps, Byte bMovePerStep ) { DataPointer p; ULong dw; p.pb = ps->a_nbNewAdrPointer; switch( bMovePerStep ) { case 0: /* doesn't move at all */ for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pdw &= 0x77777777; else *p.pdw &= 0xbbbbbbbb; } break; case 1: for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pdw |= 0x88888888; else *p.pdw |= 0x44444444; } break; case 2: for (dw = _NUMBER_OF_SCANSTEPS / 8; dw; dw--, p.pdw++) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pdw |= 0x80808080; else *p.pdw |= 0x40404040; } break; default: { Byte bMoves = bMovePerStep; for (dw = _SCANSTATE_BYTES; dw; dw--, p.pb++) { if (!(--bMoves)) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pb |= 8; else *p.pb |= 4; bMoves = bMovePerStep; } if (!(--bMoves)) { if( _ASIC_IS_98001 == ps->sCaps.AsicID ) *p.pb |= 0x80; else *p.pb |= 0x40; bMoves = bMovePerStep; } } } } IOSetToMotorRegister( ps ); } /*............................................................................. * function to bring the sensor back home */ _LOC void MotorToHomePosition( pScanData ps ) { TimerDef timer; ScanState StateStatus; DBG( DBG_HIGH, "Waiting for Sensor to be back in position\n" ); _DODELAY( 250 ); if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { if (!(IODataRegisterFromScanner(ps,ps->RegStatus) & _FLAG_P98_PAPER)){ ps->GotoShadingPosition( ps ); } } else if( _ASIC_IS_98003 == ps->sCaps.AsicID ) { ps->OpenScanPath( ps ); if( !(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) { motorP98003PositionModuleToHome( ps ); MiscStartTimer( &timer, _SECOND * 20); do { if( IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER) break; } while( !MiscCheckTimer( &timer)); } ps->CloseScanPath( ps ); } else { if( ps->sCaps.Model >= MODEL_OP_9630P ) { if( ps->sCaps.Model == MODEL_OP_A3I ) IOCmdRegisterToScanner( ps, ps->RegLineControl, 0x34 ); else IOCmdRegisterToScanner( ps, ps->RegLineControl, 0x30 ); } ps->bExtraMotorCtrl = 0; ps->Scan.fMotorBackward = _FALSE; MotorP96ConstantMoveProc( ps, 25 ); ps->Scan.fMotorBackward = _TRUE; for(;;) { motorP96GetScanStateAndStatus( ps, &StateStatus ); if ( StateStatus.bStatus & _FLAG_P96_PAPER ) { break; } MotorP96ConstantMoveProc( ps, 50000 ); } ps->Scan.fMotorBackward = _FALSE; ps->Asic96Reg.RD_MotorControl = 0; IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); _DODELAY(250); ps->Asic96Reg.RD_LedControl = 0; IOCmdRegisterToScanner(ps, ps->RegLedControl, ps->Asic96Reg.RD_LedControl); } DBG( DBG_HIGH, "- done !\n" ); } /*............................................................................. * */ _LOC void MotorP98GoFullStep( pScanData ps, ULong dwStep ) { memset( ps->pColorRunTable, 1, dwStep ); memset( ps->pColorRunTable + dwStep, 0xff, 0x40); ps->bOldStateCount = IOGetScanState( ps, _FALSE ) & _SCANSTATE_MASK; motorP98SetRunFullStep( ps ); ps->pScanState = ps->pColorRunTable; ps->FillRunNewAdrPointer( ps ); while(!motorCheckMotorPresetLength( ps )) motorP98FillRunNewAdrPointer1( ps ); } /*............................................................................. * */ _LOC void MotorP96SetSpeedToStopProc( pScanData ps ) { Byte bData; TimerDef timer; MiscStartTimer( &timer, _SECOND); while( !MiscCheckTimer( &timer )) { bData = IODataRegisterFromScanner( ps, ps->RegFifoOffset ); if ((bData > ps->bMinReadFifo) && (bData != ps->bFifoCount)) break; } bData = IOGetScanState( ps, _FALSE ); if (!(bData & _SCANSTATE_STOP)) { MiscStartTimer( &timer, (_SECOND / 2)); while (!MiscCheckTimer( &timer )) { if (IOGetScanState( ps, _FALSE) != bData ) break; } } ps->Scan.bModuleState = _MotorInStopState; ps->SetMotorSpeed( ps, ps->bCurrentSpeed, _FALSE ); IOSetToMotorRegister( ps ); } /*............................................................................. * Position Scan Module to specified line number (Forward or Backward & wait * for paper flag ON) */ _LOC void MotorP96ConstantMoveProc( pScanData ps, ULong dwLines ) { Byte bRemainder, bLastState; UShort wQuotient; ULong dwDelayMaxTime; ScanState StateStatus; TimerDef timer; Bool fTimeout = _FALSE; wQuotient = (UShort)(dwLines / _NUMBER_OF_SCANSTEPS); /* state cycles */ bRemainder = (Byte)(dwLines % _NUMBER_OF_SCANSTEPS); /* 3.3 ms per line */ dwDelayMaxTime = dwLines * _MOTOR_ONE_LINE_TIME + _SECOND * 2; MotorSetConstantMove( ps, 1 ); /* step every time */ ps->OpenScanPath( ps ); ps->AsicReg.RD_ModeControl = _ModeScan; IODataToRegister( ps, ps->RegModeControl, _ModeScan ); if( ps->Scan.fMotorBackward ) { ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->MotorOn | ps->FullStep | ps->bExtraMotorCtrl); } else { ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->MotorOn | _MotorDirForward | ps->bExtraMotorCtrl); } IODataToRegister( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); ps->CloseScanPath( ps ); bLastState = 0; MiscStartTimer( &timer, dwDelayMaxTime ); do { motorP96GetScanStateAndStatus( ps, &StateStatus ); if( ps->Scan.fMotorBackward && (StateStatus.bStatus&_FLAG_P96_PAPER)) { break; } else { /* * 1) Forward will not reach the sensor. * 2) Backwarding, doesn't reach the sensor */ if (wQuotient) { /* stepped */ if (StateStatus.bStep != bLastState) { bLastState = StateStatus.bStep; if (!bLastState) /* done a cycle! */ wQuotient--; } } else { if (StateStatus.bStep >= bRemainder) { break; } } } fTimeout = MiscCheckTimer( &timer ); } while ( _OK == fTimeout ); if ( _OK == fTimeout ) { memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES ); IOSetToMotorRegister( ps ); } } /*............................................................................. * */ _LOC Bool MotorP96AheadToDarkArea( pScanData ps ) { Byte bDark; UShort wTL; UShort wTotalLastLine; TimerDef timer; ps->fColorMoreRedFlag = _FALSE; ps->fColorMoreBlueFlag = _FALSE; ps->wOverBlue = 0; /* FillToDarkCounter () */ memset( ps->a_nbNewAdrPointer, 0x30, _SCANSTATE_BYTES); MotorSetConstantMove( ps, 2 ); /* SetToDarkRegister () */ ps->AsicReg.RD_ModeControl = _ModeScan; ps->AsicReg.RD_ScanControl = ps->bLampOn | _SCAN_BYTEMODE; ps->Asic96Reg.RD_MotorControl = _MotorDirForward | ps->FullStep; ps->AsicReg.RD_ModelControl = ps->Device.ModelCtrl | _ModelWhiteIs0; ps->AsicReg.RD_Dpi = 300; wTL = 296; /* if( MODEL_OP_A3I == ps->sCaps.Model ) { */ if( ps->PhysicalDpi > 300 ) { wTL = 400; ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + 64 + 8 + 2048); } else { ps->AsicReg.RD_Origin = (UShort)(ps->Offset70 + 64 + 8 + 1024); } ps->AsicReg.RD_Pixels = 512; IOPutOnAllRegisters( ps ); ps->Asic96Reg.RD_MotorControl = (ps->MotorFreeRun | ps->IgnorePF | ps->MotorOn | _MotorDirForward ); IOCmdRegisterToScanner( ps, ps->RegMotorControl, ps->Asic96Reg.RD_MotorControl ); MiscStartTimer( &timer, _SECOND * 2 ); wTotalLastLine = 0; #ifdef _A3I_EN while( !MiscCheckTimer( &timer )) { bDark = motorP96ReadDarkData( ps ); wTotalLastLine++; if((bDark < 0x80) || (wTotalLastLine==wTL)) { IOCmdRegisterToScanner( ps, ps->RegMotorControl, 0 ); return _TRUE; } } #else while (!MiscCheckTimer( &timer )) { bDark = motorP96ReadDarkData( ps ); wTotalLastLine++; if (((ps->sCaps.AsicID == _ASIC_IS_96001) && (bDark > 0x80)) || ((ps->sCaps.AsicID != _ASIC_IS_96001) && (bDark < 0x80)) || (wTotalLastLine==wTL)) { IOCmdRegisterToScanner( ps, ps->RegModeControl, _ModeProgram ); if (wTotalLastLine <= 24) ps->fColorMoreRedFlag = _TRUE; else if (wTotalLastLine >= 120) { ps->wOverBlue = wTotalLastLine - 80; ps->fColorMoreBlueFlag = _TRUE; } return _TRUE; } } #endif return _FALSE; /* already timed out */ } /*............................................................................. * limit the speed settings for 96001/3 based models */ _LOC void MotorP96AdjustCurrentSpeed( pScanData ps, Byte bSpeed ) { if (bSpeed != 1) { if (bSpeed > 34) ps->bCurrentSpeed = 34; else ps->bCurrentSpeed = (bSpeed + 1) & 0xfe; } } /*............................................................................. * */ _LOC void MotorP98003ForceToLeaveHomePos( pScanData ps ) { TimerDef timer; IODataToRegister( ps, ps->RegStepControl, _MOTOR0_ONESTEP ); IODataToRegister( ps, ps->RegMotor0Control, _FORWARD_MOTOR ); MiscStartTimer( &timer, _SECOND ); do { if( !(IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER)) break; IORegisterToScanner( ps, ps->RegForceStep ); _DODELAY( 10 ); } while( _OK == MiscCheckTimer( &timer )); IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE ); } /*............................................................................. * */ _LOC void MotorP98003BackToHomeSensor( pScanData ps ) { TimerDef timer; DBG( DBG_HIGH, "MotorP98003BackToHomeSensor()\n" ); IODataToRegister( ps, ps->RegStepControl, _MOTOR0_SCANSTATE ); IODataToRegister( ps, ps->RegModeControl, _ModeScan ); /* stepping every state */ memset( ps->a_nbNewAdrPointer, 0x88, _SCANSTATE_BYTES ); IODownloadScanStates( ps ); MiscStartTimer( &timer, _SECOND * 2 ); while(!(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP) && !MiscCheckTimer( &timer )); _DODELAY( 1000UL ); ps->AsicReg.RD_ModeControl = _ModeScan; if (!(ps->DataInf.dwScanFlag & SCANDEF_TPA)) { IODataToRegister( ps, ps->RegLineControl, _LOBYTE(ps->Shade.wExposure)); IODataToRegister( ps, ps->RegXStepTime, _LOBYTE(ps->Shade.wXStep)); } else { IODataToRegister( ps, ps->RegLineControl, _DEFAULT_LINESCANTIME ); IODataToRegister( ps, ps->RegXStepTime, 6); } IODataToRegister( ps, ps->RegStepControl, (_MOTOR_FREERUN | _MOTOR0_SCANSTATE)); IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); IODataToRegister( ps, ps->RegMotor0Control, (_MotorHQuarterStep | _MotorOn | _MotorDirBackward | _MotorPowerEnable | _MotorHHomeStop)); IORegisterToScanner( ps, ps->RegRefreshScanState ); MiscStartTimer( &timer, _SECOND * 5 ); do { if( IODataFromRegister( ps, ps->RegStatus ) & _FLAG_P98_PAPER ) break; _DODELAY( 55 ); } while( !MiscCheckTimer( &timer )); IODataToRegister( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl); IODataToRegister( ps, ps->RegXStepTime, ps->AsicReg.RD_XStepTime); DBG( DBG_HIGH, "LineCtrl=%u, XStepTime=%u\n", ps->AsicReg.RD_LineControl, ps->AsicReg.RD_XStepTime ); motorP98003DownloadNullScanStates( ps ); } /*............................................................................. * */ _LOC void MotorP98003ModuleForwardBackward( pScanData ps ) { switch( ps->Scan.bModuleState ) { case _MotorInNormalState: ps->Scan.bModuleState = _MotorGoBackward; IODataToRegister( ps, ps->RegScanControl1, (UChar)(ps->AsicReg.RD_ScanControl1 & ~_MFRC_RUNSCANSTATE)); IODataToRegister( ps, ps->RegMotor0Control, (UChar)(ps->AsicReg.RD_Motor0Control & ~_MotorDirForward)); motorP98003ModuleFreeRun( ps, _P98003_BACKSTEPS ); MiscStartTimer( &p98003MotorTimer, (15 * _MSECOND)); break; case _MotorGoBackward: if( MiscCheckTimer(& p98003MotorTimer)) { if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING )) { ps->Scan.bModuleState = _MotorInStopState; MiscStartTimer( &p98003MotorTimer, (50 *_MSECOND)); } } break; case _MotorInStopState: if( MiscCheckTimer(&p98003MotorTimer)) { if( IOReadFifoLength( ps ) < ps->Scan.dwMaxReadFifo ) { ps->Scan.bModuleState = _MotorAdvancing; IODataToRegister( ps, ps->RegScanControl1, ps->AsicReg.RD_ScanControl1); IODataToRegister( ps, ps->RegMotor0Control, ps->AsicReg.RD_Motor0Control); motorP98003ModuleFreeRun( ps, _P98003_FORWARDSTEPS ); MiscStartTimer( &p98003MotorTimer, (15 * _MSECOND)); } } break; case _MotorAdvancing: if( MiscCheckTimer(&p98003MotorTimer)) { if( !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP)) ps->Scan.bModuleState = _MotorInNormalState; else { if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING )) { IORegisterToScanner( ps, ps->RegRefreshScanState ); ps->Scan.bModuleState = _MotorInNormalState; } } } break; } } /*............................................................................. * */ _LOC void MotorP98003PositionYProc( pScanData ps, ULong steps) { TimerDef timer; DBG( DBG_HIGH, "MotorP98003PositionYProc()\n" ); MiscStartTimer( &timer, _SECOND * 5 ); while(!(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP) && (!MiscCheckTimer( &timer ))); _DODELAY( 12 ); motorP98003ModuleFreeRun( ps, steps ); _DODELAY( 15 ); MiscStartTimer( &timer, _SECOND * 30 ); do { if (!(IOGetExtendedStatus( ps ) & _STILL_FREE_RUNNING) || !(IOGetScanState( ps, _TRUE ) & _SCANSTATE_STOP)) break; } while( !MiscCheckTimer( &timer )); DBG( DBG_HIGH, "MotorP98003PositionYProc() - done\n" ); } /* END PLUSTEK-PP_MOTOR.C ...................................................*/ sane-backends-1.0.27/backend/ricoh.c0000664000175000017500000007150212775312261014074 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1998, Feico W. Dillema This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ This file implements a SANE backend for Ricoh flatbed scanners. */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #define BACKEND_NAME ricoh #include "../include/sane/sanei_backend.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #include "../include/sane/sanei_config.h" #define RICOH_CONFIG_FILE "ricoh.conf" #include "ricoh.h" #define MAX(a,b) ((a) > (b) ? (a) : (b)) static const SANE_Device **devlist = NULL; static int num_devices = 0; static Ricoh_Device *first_dev = NULL; static Ricoh_Scanner *first_handle = NULL; static int is50 = 0; #include "ricoh-scsi.c" static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; DBG (11, ">> max_string_size\n"); for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } DBG (11, "<< max_string_size\n"); return max_size; } static SANE_Status attach (const char *devnam, Ricoh_Device ** devp) { SANE_Status status; Ricoh_Device *dev; int fd; struct inquiry_data ibuf; struct measurements_units_page mup; struct ricoh_window_data wbuf; size_t buf_size; char *str; DBG (11, ">> attach\n"); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) { if (devp) *devp = dev; return (SANE_STATUS_GOOD); } } DBG (3, "attach: opening %s\n", devnam); status = sanei_scsi_open (devnam, &fd, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: open failed: %s\n", sane_strstatus (status)); return (status); } DBG (3, "attach: sending INQUIRY\n"); memset (&ibuf, 0, sizeof (ibuf)); buf_size = sizeof(ibuf); status = inquiry (fd, &ibuf, &buf_size); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: inquiry failed: %s\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } if (ibuf.devtype != 6 || strncmp ((char *)ibuf.vendor, "RICOH", 5) != 0 || (strncmp ((char *)ibuf.product, "IS50", 4) != 0 && strncmp ((char *)ibuf.product, "IS60", 4) != 0)) { DBG (1, "attach: device doesn't look like the Ricoh scanner I know\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } is50 = (strncmp ((char *)ibuf.product, "IS50", 4) == 0); DBG (3, "attach: sending TEST_UNIT_READY\n"); status = test_unit_ready (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: test unit ready failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return (status); } DBG (3, "attach: sending OBJECT POSITION\n"); status = object_position (fd); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: OBJECT POSTITION failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } memset (&mup, 0, sizeof (mup)); mup.page_code = MEASUREMENTS_PAGE; mup.parameter_length = 0x06; mup.bmu = INCHES; mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff; mup.mud[1] = (DEFAULT_MUD & 0xff); #if 0 DBG (3, "attach: sending MODE SELECT\n"); status = mode_select (fd, (struct mode_pages *) &mup); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #endif #if 0 DBG (3, "attach: sending MODE SENSE\n"); memset (&mup, 0, sizeof (mup)); status = mode_sense (fd, (struct mode_pages *) &mup, PC_CURRENT | MEASUREMENTS_PAGE); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SENSE failed\n"); sanei_scsi_close (fd); return (SANE_STATUS_INVAL); } #endif DBG (3, "attach: sending GET WINDOW\n"); memset (&wbuf, 0, sizeof (wbuf)); status = get_window (fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: GET_WINDOW failed %d\n", status); sanei_scsi_close (fd); DBG (11, "<< attach\n"); return (SANE_STATUS_INVAL); } sanei_scsi_close (fd); dev = malloc (sizeof (*dev)); if (!dev) return (SANE_STATUS_NO_MEM); memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devnam); dev->sane.vendor = "RICOH"; str = malloc (sizeof(ibuf.product) + sizeof(ibuf.revision) + 1); if (str) { str[0] = '\0'; strncat (str, (char *)ibuf.product, sizeof(ibuf.product)); strncat (str, (char *)ibuf.revision, sizeof(ibuf.revision)); } dev->sane.model = str; dev->sane.type = "flatbed scanner"; DBG (5, "dev->sane.name = %s\n", dev->sane.name); DBG (5, "dev->sane.vendor = %s\n", dev->sane.vendor); DBG (5, "dev->sane.model = %s\n", dev->sane.model); DBG (5, "dev->sane.type = %s\n", dev->sane.type); dev->info.xres_default = _2btol(wbuf.x_res); dev->info.yres_default = _2btol(wbuf.y_res); dev->info.image_mode_default = wbuf.image_comp; /* if you throw the MRIF bit the brighness control reverses too */ /* so I reverse the reversal in software for symmetry's sake */ /* I should make this into an option */ if (wbuf.image_comp == RICOH_GRAYSCALE || wbuf.image_comp == RICOH_DITHERED_MONOCHROME) { dev->info.brightness_default = 256 - wbuf.brightness; if (is50) dev->info.contrast_default = wbuf.contrast; else dev->info.contrast_default = 256 - wbuf.contrast; } else /* wbuf.image_comp == RICOH_BINARY_MONOCHROME */ { dev->info.brightness_default = wbuf.brightness; dev->info.contrast_default = wbuf.contrast; } #if 1 dev->info.bmu = mup.bmu; dev->info.mud = _2btol(mup.mud); if (dev->info.mud == 0) { /* The RICOH says it uses points as default Basic Measurement Unit */ /* but gives a Measurement Unit Divisor of zero */ /* So, we set it to the default (SCSI-standard) of 1200 */ /* with BMU in inches, i.e. 1200 points equal 1 inch */ dev->info.bmu = INCHES; dev->info.mud = DEFAULT_MUD; } #else dev->info.bmu = INCHES; dev->info.mud = DEFAULT_MUD; #endif DBG (5, "xres_default=%d\n", dev->info.xres_default); DBG (5, "xres_range.max=%d\n", dev->info.xres_range.max); DBG (5, "xres_range.min=%d\n", dev->info.xres_range.min); DBG (5, "yres_default=%d\n", dev->info.yres_default); DBG (5, "yres_range.max=%d\n", dev->info.yres_range.max); DBG (5, "yres_range.min=%d\n", dev->info.yres_range.min); DBG (5, "x_range.max=%d\n", dev->info.x_range.max); DBG (5, "y_range.max=%d\n", dev->info.y_range.max); DBG (5, "image_mode=%d\n", dev->info.image_mode_default); DBG (5, "brightness=%d\n", dev->info.brightness_default); DBG (5, "contrast=%d\n", dev->info.contrast_default); DBG (5, "bmu=%d\n", dev->info.bmu); DBG (5, "mud=%d\n", dev->info.mud); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (11, "<< attach\n"); return (SANE_STATUS_GOOD); } static SANE_Status attach_one(const char *devnam) { attach (devnam, NULL); return SANE_STATUS_GOOD; } static SANE_Status init_options (Ricoh_Scanner * s) { int i; DBG (11, ">> init_options\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[s->hw->info.image_mode_default]); /* x resolution */ s->opt[OPT_X_RESOLUTION].name = "X" SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].title = "X " SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_X_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_X_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_X_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_X_RESOLUTION].constraint.range = &is60_res_range; s->val[OPT_X_RESOLUTION].w = s->hw->info.xres_default; if (is50) s->opt[OPT_X_RESOLUTION].constraint.range = &is50_res_range; else s->opt[OPT_X_RESOLUTION].constraint.range = &is60_res_range; /* y resolution */ s->opt[OPT_Y_RESOLUTION].name = "Y" SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].title = "Y " SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_Y_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_Y_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_Y_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_Y_RESOLUTION].w = s->hw->info.yres_default; if (is50) s->opt[OPT_Y_RESOLUTION].constraint.range = &is50_res_range; else s->opt[OPT_Y_RESOLUTION].constraint.range = &is60_res_range; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_INT; s->opt[OPT_TL_X].unit = SANE_UNIT_PIXEL; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &default_x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_INT; s->opt[OPT_TL_Y].unit = SANE_UNIT_PIXEL; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &default_y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_INT; s->opt[OPT_BR_X].unit = SANE_UNIT_PIXEL; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &default_x_range; s->val[OPT_BR_X].w = default_x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_INT; s->opt[OPT_BR_Y].unit = SANE_UNIT_PIXEL; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &default_y_range; s->val[OPT_BR_Y].w = default_y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &u8_range; s->val[OPT_BRIGHTNESS].w = s->hw->info.brightness_default; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &u8_range; s->val[OPT_CONTRAST].w = s->hw->info.contrast_default; DBG (11, "<< init_options\n"); return SANE_STATUS_GOOD; } static SANE_Status do_cancel (Ricoh_Scanner * s) { SANE_Status status; DBG (11, ">> do_cancel\n"); DBG (3, "cancel: sending OBJECT POSITION\n"); status = object_position (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "cancel: OBJECT POSTITION failed\n"); } s->scanning = SANE_FALSE; if (s->fd >= 0) { sanei_scsi_close (s->fd); s->fd = -1; } DBG (11, "<< do_cancel\n"); return (SANE_STATUS_CANCELLED); } SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char devnam[PATH_MAX] = "/dev/scanner"; FILE *fp; authorize = authorize; /* silence gcc */ DBG_INIT (); DBG (11, ">> sane_init\n"); #if defined PACKAGE && defined VERSION DBG (2, "sane_init: " PACKAGE " " VERSION "\n"); #endif if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open(RICOH_CONFIG_FILE); if (fp) { char line[PATH_MAX], *lp; size_t len; /* read config file */ while (sanei_config_read (line, sizeof (line), fp)) { if (line[0] == '#') /* ignore line comments */ continue; len = strlen (line); if (!len) continue; /* ignore empty lines */ /* skip white space: */ for (lp = line; isspace(*lp); ++lp); strcpy (devnam, lp); } fclose (fp); } sanei_config_attach_matching_devices (devnam, attach_one); DBG (11, "<< sane_init\n"); return SANE_STATUS_GOOD; } void sane_exit (void) { Ricoh_Device *dev, *next; DBG (11, ">> sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free ((void *) dev->sane.name); free ((void *) dev->sane.model); free (dev); } if (devlist) free (devlist); DBG (11, "<< sane_exit\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Ricoh_Device *dev; int i; local_only = local_only; /* silence gcc */ DBG (11, ">> sane_get_devices\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return (SANE_STATUS_NO_MEM); i = 0; for (dev = first_dev; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (11, "<< sane_get_devices\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devnam, SANE_Handle * handle) { SANE_Status status; Ricoh_Device *dev; Ricoh_Scanner *s; DBG (11, ">> sane_open\n"); if (devnam[0] == '\0') { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devnam) == 0) break; } if (!dev) { status = attach (devnam, &dev); if (status != SANE_STATUS_GOOD) return (status); } } else { dev = first_dev; } if (!dev) return (SANE_STATUS_INVAL); s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->fd = -1; s->hw = dev; init_options (s); s->next = first_handle; first_handle = s; *handle = s; DBG (11, "<< sane_open\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Ricoh_Scanner *s = (Ricoh_Scanner *) handle; DBG (11, ">> sane_close\n"); if (s->fd != -1) sanei_scsi_close (s->fd); free (s); DBG (11, ">> sane_close\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Ricoh_Scanner *s = handle; DBG (11, ">> sane_get_option_descriptor\n"); if ((unsigned) option >= NUM_OPTIONS) return (0); DBG (11, "<< sane_get_option_descriptor\n"); return (s->opt + option); } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Ricoh_Scanner *s = handle; SANE_Status status; SANE_Word cap; DBG (11, ">> sane_control_option\n"); if (info) *info = 0; if (s->scanning) return (SANE_STATUS_DEVICE_BUSY); if (option >= NUM_OPTIONS) return (SANE_STATUS_INVAL); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return (SANE_STATUS_INVAL); if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: *(SANE_Word *) val = s->val[option].w; return (SANE_STATUS_GOOD); /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); return (SANE_STATUS_GOOD); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_MODE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return (SANE_STATUS_GOOD); } } DBG (11, "<< sane_control_option\n"); return (SANE_STATUS_INVAL); } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Ricoh_Scanner *s = handle; DBG (11, ">> sane_get_parameters\n"); if (!s->scanning) { int width, length, xres, yres; const char *mode; memset (&s->params, 0, sizeof (s->params)); width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w; length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w; xres = s->val[OPT_X_RESOLUTION].w; yres = s->val[OPT_Y_RESOLUTION].w; /* make best-effort guess at what parameters will look like once scanning starts. */ if (xres > 0 && yres > 0 && width > 0 && length > 0) { s->params.pixels_per_line = width * xres / s->hw->info.mud; s->params.lines = length * yres / s->hw->info.mud; } mode = s->val[OPT_MODE].s; if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0 || strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line / 8; /* the Ricoh truncates to the byte boundary, so: chop! */ s->params.pixels_per_line = s->params.bytes_per_line * 8; s->params.depth = 1; } else /* if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) */ { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } s->params.last_frame = SANE_TRUE; } if (params) *params = s->params; DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w); DBG (11, "<< sane_get_parameters\n"); return (SANE_STATUS_GOOD); } SANE_Status sane_start (SANE_Handle handle) { char *mode_str; Ricoh_Scanner *s = handle; SANE_Status status; struct ricoh_window_data wbuf; struct measurements_units_page mup; DBG (11, ">> sane_start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ status = sane_get_parameters (s, 0); if (status != SANE_STATUS_GOOD) return status; status = sanei_scsi_open (s->hw->sane.name, &s->fd, 0, 0); if (status != SANE_STATUS_GOOD) { DBG (1, "open of %s failed: %s\n", s->hw->sane.name, sane_strstatus (status)); return (status); } mode_str = s->val[OPT_MODE].s; s->xres = s->val[OPT_X_RESOLUTION].w; s->yres = s->val[OPT_Y_RESOLUTION].w; s->ulx = s->val[OPT_TL_X].w; s->uly = s->val[OPT_TL_Y].w; s->width = s->val[OPT_BR_X].w - s->val[OPT_TL_X].w; s->length = s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w; s->brightness = s->val[OPT_BRIGHTNESS].w; s->contrast = s->val[OPT_CONTRAST].w; s->bpp = s->params.depth; if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->image_composition = RICOH_BINARY_MONOCHROME; } else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) { s->image_composition = RICOH_DITHERED_MONOCHROME; } else if (strcmp (mode_str, SANE_VALUE_SCAN_MODE_GRAY) == 0) { s->image_composition = RICOH_GRAYSCALE; } memset (&wbuf, 0, sizeof (wbuf)); _lto2b(sizeof(wbuf) - 8, wbuf.len); _lto2b(s->xres, wbuf.x_res); _lto2b(s->yres, wbuf.y_res); _lto4b(s->ulx, wbuf.x_org); _lto4b(s->uly, wbuf.y_org); _lto4b(s->width, wbuf.width); _lto4b(s->length, wbuf.length); wbuf.image_comp = s->image_composition; /* if you throw the MRIF bit the brighness control reverses too */ /* so I reverse the reversal in software for symmetry's sake */ if (wbuf.image_comp == RICOH_GRAYSCALE || wbuf.image_comp == RICOH_DITHERED_MONOCHROME) { if (wbuf.image_comp == RICOH_GRAYSCALE) wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x90; if (wbuf.image_comp == RICOH_DITHERED_MONOCHROME) wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x10; wbuf.brightness = 256 - (SANE_Byte) s->brightness; if (is50) wbuf.contrast = (SANE_Byte) s->contrast; else wbuf.contrast = 256 - (SANE_Byte) s->contrast; } else /* wbuf.image_comp == RICOH_BINARY_MONOCHROME */ { wbuf.mrif_filtering_gamma_id = (SANE_Byte) 0x00; wbuf.brightness = (SANE_Byte) s->brightness; wbuf.contrast = (SANE_Byte) s->contrast; } wbuf.threshold = 0; wbuf.bits_per_pixel = s->bpp; wbuf.halftone_pattern[0] = 2; wbuf.halftone_pattern[1] = 0; wbuf.pad_type = 3; wbuf.bit_ordering[0] = 0; wbuf.bit_ordering[1] = 3; DBG (5, "xres=%d\n", _2btol(wbuf.x_res)); DBG (5, "yres=%d\n", _2btol(wbuf.y_res)); DBG (5, "ulx=%d\n", _4btol(wbuf.x_org)); DBG (5, "uly=%d\n", _4btol(wbuf.y_org)); DBG (5, "width=%d\n", _4btol(wbuf.width)); DBG (5, "length=%d\n", _4btol(wbuf.length)); DBG (5, "image_comp=%d\n", wbuf.image_comp); DBG (11, "sane_start: sending SET WINDOW\n"); status = set_window (s->fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "SET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (11, "sane_start: sending GET WINDOW\n"); memset (&wbuf, 0, sizeof (wbuf)); status = get_window (s->fd, &wbuf); if (status != SANE_STATUS_GOOD) { DBG (1, "GET WINDOW failed: %s\n", sane_strstatus (status)); return (status); } DBG (5, "xres=%d\n", _2btol(wbuf.x_res)); DBG (5, "yres=%d\n", _2btol(wbuf.y_res)); DBG (5, "ulx=%d\n", _4btol(wbuf.x_org)); DBG (5, "uly=%d\n", _4btol(wbuf.y_org)); DBG (5, "width=%d\n", _4btol(wbuf.width)); DBG (5, "length=%d\n", _4btol(wbuf.length)); DBG (5, "image_comp=%d\n", wbuf.image_comp); DBG (11, "sane_start: sending MODE SELECT\n"); memset (&mup, 0, sizeof (mup)); mup.page_code = MEASUREMENTS_PAGE; mup.parameter_length = 0x06; mup.bmu = INCHES; mup.mud[0] = (DEFAULT_MUD >> 8) & 0xff; mup.mud[1] = (DEFAULT_MUD & 0xff); status = mode_select (s->fd, (struct mode_pages *) &mup); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: MODE_SELECT failed\n"); return (SANE_STATUS_INVAL); } status = trigger_scan (s->fd); if (status != SANE_STATUS_GOOD) { DBG (1, "start of scan failed: %s\n", sane_strstatus (status)); return (status); } /* Wait for scanner to become ready to transmit data */ status = ricoh_wait_ready (s); if (status != SANE_STATUS_GOOD) { DBG (1, "GET DATA STATUS failed: %s\n", sane_strstatus (status)); return (status); } s->bytes_to_read = s->params.bytes_per_line * s->params.lines; DBG (1, "%d pixels per line, %d bytes, %d lines high, total %lu bytes, " "dpi=%d\n", s->params.pixels_per_line, s->params.bytes_per_line, s->params.lines, (u_long) s->bytes_to_read, s->val[OPT_Y_RESOLUTION].w); s->scanning = SANE_TRUE; DBG (11, "<< sane_start\n"); return (SANE_STATUS_GOOD); } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Ricoh_Scanner *s = handle; SANE_Status status; size_t nread; DBG (11, ">> sane_read\n"); *len = 0; DBG (11, "sane_read: bytes left to read: %ld\n", (u_long) s->bytes_to_read); if (s->bytes_to_read == 0) { do_cancel (s); return (SANE_STATUS_EOF); } if (!s->scanning) { DBG (11, "sane_read: scanning is false!\n"); return (do_cancel (s)); } nread = max_len; if (nread > s->bytes_to_read) nread = s->bytes_to_read; DBG (11, "sane_read: read %ld bytes\n", (u_long) nread); status = read_data (s->fd, buf, &nread); if (status != SANE_STATUS_GOOD) { DBG (11, "sane_read: read error\n"); do_cancel (s); return (SANE_STATUS_IO_ERROR); } *len = nread; s->bytes_to_read -= nread; DBG (11, "<< sane_read\n"); return (SANE_STATUS_GOOD); } void sane_cancel (SANE_Handle handle) { Ricoh_Scanner *s = handle; DBG (11, ">> sane_cancel\n"); s->scanning = SANE_FALSE; DBG (11, "<< sane_cancel\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { handle = handle; /* silence gcc */ non_blocking = non_blocking; /* silence gcc */ DBG (5, ">> sane_set_io_mode\n"); DBG (5, "<< sane_set_io_mode\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { handle = handle; /* silence gcc */ fd = fd; /* silence gcc */ DBG (5, ">> sane_get_select_fd\n"); DBG (5, "<< sane_get_select_fd\n"); return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/hp.c0000664000175000017500000006612612775312261013405 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki Support for HP PhotoSmart Photoscanner by Peter Kirchgessner This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ static char *hp_backend_version = "1.06"; static char *hp_backend_revision = "$Revision$"; /* Changes: V 1.06: $Log$ Revision 1.22 2008/11/26 21:21:25 kitno-guest * backend/ *.[ch]: nearly every backend used V_MAJOR instead of SANE_CURRENT_MAJOR in sane_init() * backend/snapscan.c: remove EXPECTED_VERSION check since new SANE standard is forward compatible Revision 1.21 2004-10-04 18:09:05 kig-guest Rename global function hp_init_openfd to sanei_hp_init_openfd Revision 1.20 2004/03/27 13:52:39 kig-guest Keep USB-connection open (was problem with Linux 2.6.x) V 1.05: Revision 1.19 2003/10/24 17:26:07 kig-guest Use new sanei-thread-interface Revision 1.18 2003/10/09 19:37:29 kig-guest Redo when TEST UNIT READY failed Redo when read returns with 0 bytes (non-SCSI only) Bug #300241: fix invers image on 3c/4c/6100C at 10 bit depth Revision 1.17 2003/10/06 19:54:07 kig-guest Bug #300248: correct "Negatives" to "Negative" in option description V 1.04, 24-Jul-2003, PK (peter@kirchgessner.net) - Add internationalization V 1.03, 14-Apr-2003, PK (peter@kirchgessner.net) - check valp in call of sane_control_option() V 1.02, 02-Feb-2003, PK (peter@kirchgessner.net) - add OS/2-support by Franz Bakan V 1.01, 06-Dec-2002, PK (peter@kirchgessner.net) - add option dumb-read to work around problems with BusLogic SCSI driver (error during device I/O) V 1.00, 17-Nov-2002, PK (peter@kirchgessner.net) - add libusb support V 0.96, 05-Aug-2002, PK (peter@kirchgessner.net) - check USB device names V 0.95, 07-Jul-2001, PK (peter@kirchgessner.net) - add support for active XPA - check if paper in ADF for ADF scan - add option lamp off - remove some really unused parameters V 0.94, 31-Dec-2000, PK (peter@kirchgessner.net) - always switch off lamp after scan V 0.93, 04-Dec-2000, PK (peter@kirchgessner.net) - fix problem with ADF-support on ScanJet 6350 (and maybe others) V 0.92, 03-Oct-2000, Rupert W. Curwen (rcurwen@uk.research.att.com): - try to not allocate accessors twice (only for accessors that have fixed length) - fix problem with leaving connection open for some error conditions V 0.91, 04-Sep-2000, David Paschal (paschal@rcsis.com): - Added support for flatbed HP OfficeJets - (PK) fix problem with cancel preview V 0.90, 02-Sep-2000, PK: - fix timing problem between killing child and writing to pipe - change fprintf(stderr,...) to DBG - change include to "sane.." in hp.h - change handling of options that have global effects. i.e. if option scanmode is received (has global effect), all options that "may change" are send to the scanner again. This fixes a problem that --resolution specified infront of --mode on command line of scanimage was ignored. NOTE: This change does not allow to specify --depth 12 infront of --mode color, because --depth is only enabled with --mode color. - add depth greater 8 bits for mode grayscale - add option for 8 bit output but 10/12 bit scanning V 0.88, 25-Jul-2000, PK: - remove inlines V 0.88, 20-Jul-2000, PK: - Use sanei_config_read() - dont write chars < 32 to DBG V 0.88, 09-Jul-2000, PK: - Add front button support by Chris S. Cowles, Houston, Texas, c_cowles@ieee.org V 0.87, 28-Jun-2000, PK: - ADF-support for ScanJet IIp - Return error SANE_STATUS_NO_DOCS if no paper in ADF V 0.86, 12-Feb-2000, PK: - fix gcc warnings - fix problems with bitdepths > 8 - allow hp_data_resize to be called with newsize==bufsiz (Jens Heise, ) - add option enable-image-buffering V 0.85, 30-Jan-2000, PK: - correct and enhace data widths > 8 (Ewald de Wit ) - enable data width for all scanners - PhotoSmart: exposure "Off" changed to "Default" - PhotoSmart: even if max. datawidth 24 is reported, allow 30 bits. - change keyword -data-width to -depth and use value for bits per sample - change keyword -halftone-type to -halftone-pattern - change keyword -scantype to -source - fix problem with multiple definition of sanei_debug_hp V 0.83, 04-Jul-99, PK: - reset scanner before downloading parameters (fixes problem with sleep mode of scanners) - fix problem with coredump if non-scanner HP SCSI devices are connected (CDR) - option scan-from-adf replaced by scantype normal/adf/xpa - change value "Film strip" to "Film-strip" for option --media-type - PhotoScanner: allow only scanning at multiple of 300 dpi for scanning slides/film strips. This also fixes a problem with the preview which uses arbitrary resolutions. - Marian Szebenyi: close pipe (endless loop on Digital UNIX) V 0.82, 28-Feb-99, Ewald de Wit : - add options 'exposure time' and 'data width' V 0.81, 11-Jan-99, PK: - occasionally 'scan from ADF' was active for Photoscanner V 0.80, 10-Jan-99, PK: - fix problem with scan size for ADF-scan (thanks to Christop Biardzki for tests) - add option "unload after scan" for HP PhotoScanner - no blanks in command line options - fix problem with segmentation fault for scanimage -d hp:/dev/sga with /dev/sga not included in hp.conf V 0.72, 25-Dec-98, PK: - add patches from mike@easysw.com to fix problems: - core dumps by memory alignment - config file to accept matching devices (scsi HP) - add simulation for brightness/contrast/custom gamma table if not supported by scanner - add configuration options for connect-... V 0.72c, 04-Dec-98, PK: - use sanei_pio - try ADF support V 0.72b, 29-Nov-98 James Carter , PK: - try to add parallel scanner support V 0.71, 14-Nov-98 PK: - add HP 6200 C - cleanup hp_scsi_s structure - show calibrate button on photoscanner only for print media - suppress halftone mode on photoscanner - add media selection for photoscanner V 0.70, 26-Jul-98 PK: - Rename global symbols to sanei_... Change filenames to hp-... Use backend name hp V 0.65, 18-Jul-98 PK: - Dont use pwd.h for VACPP-Compiler to get home-directory, check $SANE_HOME_XHP instead V 0.64, 12-Jul-98 PK: - only download calibration file for media = 1 (prints) - Changes for VACPP-Compiler (check macros __IBMC__, __IBMCPP__) V 0.63, 07-Jun-98 PK: - fix problem with custom gamma table - Add unload button V 0.62, 25-May-98 PK: - make it compilable under sane V 0.73 V 0.61, 28-Mar-98, Peter Kirchgessner : - Add support for HP PhotoSmart Photoscanner - Use more inquiries to see what the scanner supports - Add options: calibrate/Mirror horizontal+vertical - Upload/download calibration data */ #define VERSIO 8 #include "../include/sane/config.h" #include "hp.h" #include /* #include */ /* #include "../include/sane/sane.h" */ #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_thread.h" /* #include "../include/sane/sanei_debug.h" */ #include "hp-device.h" #include "hp-handle.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #ifndef NDEBUG #include void sanei_hp_dbgdump (const void * bufp, size_t len) { const hp_byte_t *buf = bufp; int offset = 0; int i; char line[128], pt[32]; for (offset = 0; offset < (int)len; offset += 16) { sprintf (line," 0x%04X ", offset); for (i = offset; i < offset + 16 && i < (int)len; i++) { sprintf (pt," %02X", buf[i]); strcat (line, pt); } while (i++ < offset + 16) strcat (line, " "); strcat (line, " "); for (i = offset; i < offset + 16 && i < (int)len; i++) { sprintf (pt, "%c", isprint(buf[i]) ? buf[i] : '.'); strcat (line, pt); } DBG(16,"%s\n",line); } } #endif typedef struct info_list_el_s * HpDeviceInfoList; struct info_list_el_s { HpDeviceInfoList next; HpDeviceInfo info; }; typedef struct device_list_el_s * HpDeviceList; struct device_list_el_s { HpDeviceList next; HpDevice dev; }; /* Global state */ static struct hp_global_s { hp_bool_t is_up; hp_bool_t config_read; const SANE_Device ** devlist; HpDeviceList device_list; HpDeviceList handle_list; HpDeviceInfoList infolist; HpDeviceConfig config; } global; /* Get the info structure for a device. If not available in global list */ /* add new entry and return it */ static HpDeviceInfo * hp_device_info_create (const char *devname) { HpDeviceInfoList *infolist = &(global.infolist); HpDeviceInfoList infolistelement; HpDeviceInfo *info; int k, found; if (!global.is_up) return 0; found = 0; infolistelement = 0; info = 0; while (*infolist) { infolistelement = *infolist; info = &(infolistelement->info); if (strcmp (info->devname, devname) == 0) /* Already in list ? */ { found = 1; break; } infolist = &(infolistelement->next); } if (found) /* Clear old entry */ { memset (infolistelement, 0, sizeof (*infolistelement)); } else /* New element */ { infolistelement = (HpDeviceInfoList) sanei_hp_allocz (sizeof (*infolistelement)); if (!infolistelement) return 0; info = &(infolistelement->info); *infolist = infolistelement; } k = sizeof (info->devname); strncpy (info->devname, devname, k); info->devname[k-1] = '\0'; info->max_model = -1; info->active_xpa = -1; return info; } static void hp_init_config (HpDeviceConfig *config) { if (config) { config->connect = HP_CONNECT_SCSI; config->use_scsi_request = 1; config->use_image_buffering = 0; config->got_connect_type = 0; config->dumb_read = 0; } } static HpDeviceConfig * hp_global_config_get (void) { if (!global.is_up) return 0; return &(global.config); } static SANE_Status hp_device_config_add (const char *devname) { HpDeviceInfo *info; HpDeviceConfig *config; info = hp_device_info_create (devname); if (!info) return SANE_STATUS_INVAL; config = hp_global_config_get (); if (config) { memcpy (&(info->config), config, sizeof (info->config)); info->config_is_up = 1; } else /* Initialize with default configuration */ { DBG(3, "hp_device_config_add: No configuration found for device %s.\n\tUseing default\n", devname); hp_init_config (&(info->config)); info->config_is_up = 1; } return SANE_STATUS_GOOD; } HpDeviceInfo * sanei_hp_device_info_get (const char *devname) { HpDeviceInfoList *infolist; HpDeviceInfoList infolistelement; HpDeviceInfo *info; int retries = 1; if (!global.is_up) { DBG(17, "sanei_hp_device_info_get: global.is_up = %d\n", (int)global.is_up); return 0; } DBG(250, "sanei_hp_device_info_get: searching %s\n", devname); do { infolist = &(global.infolist); while (*infolist) { infolistelement = *infolist; info = &(infolistelement->info); DBG(250, "sanei_hp_device_info_get: check %s\n", info->devname); if (strcmp (info->devname, devname) == 0) /* Found ? */ { return info; } infolist = &(infolistelement->next); } /* No configuration found. Assume default */ DBG(1, "hp_device_info_get: device %s not configured. Using default\n", devname); if (hp_device_config_add (devname) != SANE_STATUS_GOOD) return 0; } while (retries-- > 0); return 0; } HpDevice sanei_hp_device_get (const char *devname) { HpDeviceList ptr; for (ptr = global.device_list; ptr; ptr = ptr->next) if (strcmp(sanei_hp_device_sanedevice(ptr->dev)->name, devname) == 0) return ptr->dev; return 0; } static void hp_device_info_remove (void) { HpDeviceInfoList next, infolistelement = global.infolist; if (!global.is_up) return; while (infolistelement) { next = infolistelement->next; sanei_hp_free (infolistelement); infolistelement = next; } } static SANE_Status hp_device_list_add (HpDeviceList * list, HpDevice dev) { HpDeviceList new = sanei_hp_alloc(sizeof(*new)); if (!new) return SANE_STATUS_NO_MEM; while (*list) list = &(*list)->next; *list = new; new->next = 0; new->dev = dev; return SANE_STATUS_GOOD; } static SANE_Status hp_device_list_remove (HpDeviceList * list, HpDevice dev) { HpDeviceList old; while (*list && (*list)->dev != dev) list = &(*list)->next; if (!*list) return SANE_STATUS_INVAL; old = *list; *list = (*list)->next; sanei_hp_free(old); return SANE_STATUS_GOOD; } static SANE_Status hp_handle_list_add (HpDeviceList * list, HpHandle h) { return hp_device_list_add(list, (HpDevice)h); } static SANE_Status hp_handle_list_remove (HpDeviceList * list, HpHandle h) { return hp_device_list_remove(list, (HpDevice)h); } static SANE_Status hp_init (void) { memset(&global, 0, sizeof(global)); global.is_up++; DBG(3, "hp_init: global.is_up = %d\n", (int)global.is_up); return SANE_STATUS_GOOD; } static void hp_destroy (void) { if (global.is_up) { /* Close open handles */ while (global.handle_list) sane_close(global.handle_list->dev); /* Remove device infos */ hp_device_info_remove (); sanei_hp_free_all(); global.is_up = 0; DBG(3, "hp_destroy: global.is_up = %d\n", (int)global.is_up); } } static SANE_Status hp_get_dev (const char *devname, HpDevice* devp) { HpDeviceList ptr; HpDevice new; const HpDeviceInfo *info; char *connect; HpConnect hp_connect; SANE_Status status; for (ptr = global.device_list; ptr; ptr = ptr->next) if (strcmp(sanei_hp_device_sanedevice(ptr->dev)->name, devname) == 0) { if (devp) *devp = ptr->dev; return SANE_STATUS_GOOD; } info = sanei_hp_device_info_get (devname); hp_connect = info->config.connect; if (hp_connect == HP_CONNECT_SCSI) connect = "scsi"; else if (hp_connect == HP_CONNECT_DEVICE) connect = "device"; else if (hp_connect == HP_CONNECT_PIO) connect = "pio"; else if (hp_connect == HP_CONNECT_USB) connect = "usb"; else if (hp_connect == HP_CONNECT_RESERVE) connect = "reserve"; else connect = "unknown"; DBG(3, "hp_get_dev: New device %s, connect-%s, scsi-request=%lu\n", devname, connect, (unsigned long)info->config.use_scsi_request); if (!ptr) { status = sanei_hp_device_new (&new, devname); if ( status != SANE_STATUS_GOOD ) return status; } if (devp) *devp = new; RETURN_IF_FAIL( hp_device_list_add(&global.device_list, new) ); return SANE_STATUS_GOOD; } static SANE_Status hp_attach (const char *devname) { DBG(7,"hp_attach: \"%s\"\n", devname); hp_device_config_add (devname); return hp_get_dev (devname, 0); } static void hp_attach_matching_devices (HpDeviceConfig *config, const char *devname) { static int usb_initialized = 0; if (strncmp (devname, "usb", 3) == 0) { config->connect = HP_CONNECT_USB; config->use_scsi_request = 0; DBG(1,"hp_attach_matching_devices: usb attach matching \"%s\"\n",devname); if (!usb_initialized) { sanei_usb_init (); usb_initialized = 1; } sanei_usb_attach_matching_devices (devname, hp_attach); } else { DBG(1, "hp_attach_matching_devices: attach matching %s\n", devname); sanei_config_attach_matching_devices (devname, hp_attach); } } static SANE_Status hp_read_config (void) { FILE * fp; char buf[PATH_MAX], arg1[PATH_MAX], arg2[PATH_MAX], arg3[PATH_MAX]; int nl, nargs; HpDeviceConfig *config, df_config, dev_config; hp_bool_t is_df_config; char cu_device[PATH_MAX]; if (!global.is_up) return SANE_STATUS_INVAL; if (global.config_read) return SANE_STATUS_GOOD; /* The default config will keep options set up until the first device is specified */ hp_init_config (&df_config); config = &df_config; is_df_config = 1; cu_device[0] = '\0'; DBG(1, "hp_read_config: hp backend v%s/%s starts reading config file\n", hp_backend_version, hp_backend_revision); if ((fp = sanei_config_open(HP_CONFIG_FILE)) != 0) { while (sanei_config_read(buf, sizeof(buf), fp)) { char *dev_name; nl = strlen (buf); while (nl > 0) { nl--; if ( (buf[nl] == ' ') || (buf[nl] == '\t') || (buf[nl] == '\r') || (buf[nl] == '\n')) buf[nl] = '\0'; else break; } DBG(1, "hp_read_config: processing line <%s>\n", buf); nargs = sscanf (buf, "%s%s%s", arg1, arg2, arg3); if ((nargs <= 0) || (arg1[0] == '#')) continue; /* Option to process ? */ if ((strcmp (arg1, "option") == 0) && (nargs >= 2)) { if (strcmp (arg2, "connect-scsi") == 0) { config->connect = HP_CONNECT_SCSI; config->got_connect_type = 1; } else if (strcmp (arg2, "connect-device") == 0) { config->connect = HP_CONNECT_DEVICE; config->got_connect_type = 1; config->use_scsi_request = 0; } else if (strcmp (arg2, "connect-pio") == 0) { config->connect = HP_CONNECT_PIO; config->got_connect_type = 1; config->use_scsi_request = 0; } else if (strcmp (arg2, "connect-usb") == 0) { config->connect = HP_CONNECT_USB; config->got_connect_type = 1; config->use_scsi_request = 0; } else if (strcmp (arg2, "connect-reserve") == 0) { config->connect = HP_CONNECT_RESERVE; config->got_connect_type = 1; config->use_scsi_request = 0; } else if (strcmp (arg2, "disable-scsi-request") == 0) { config->use_scsi_request = 0; } else if (strcmp (arg2, "enable-image-buffering") == 0) { config->use_image_buffering = 1; } else if (strcmp (arg2, "dumb-read") == 0) { config->dumb_read = 1; } else { DBG(1,"hp_read_config: Invalid option %s\n", arg2); } } else /* No option. This is the start of a new device */ { if (is_df_config) /* Did we only read default configurations ? */ { is_df_config = 0; /* Stop reading default config */ /* Initialize device config with default-config */ memcpy (&dev_config, &df_config, sizeof (dev_config)); config = &dev_config; /* Start reading a device config */ } if (cu_device[0] != '\0') /* Did we work on a device ? */ { memcpy (hp_global_config_get(), &dev_config,sizeof (dev_config)); hp_attach_matching_devices (hp_global_config_get(), cu_device); cu_device[0] = '\0'; } /* Initialize new device with default config */ memcpy (&dev_config, &df_config, sizeof (dev_config)); /* Cut off leading blanks of device name */ dev_name = buf+strspn (buf, " \t\n\r"); strcpy (cu_device, dev_name); /* Save the device name */ } } if (cu_device[0] != '\0') /* Did we work on a device ? */ { memcpy (hp_global_config_get (), &dev_config, sizeof (dev_config)); DBG(1, "hp_read_config: attach %s\n", cu_device); hp_attach_matching_devices (hp_global_config_get (), cu_device); cu_device[0] = '\0'; } fclose (fp); DBG(1, "hp_read_config: reset to default config\n"); memcpy (hp_global_config_get (), &df_config, sizeof (df_config)); } else { /* default to /dev/scanner instead of insisting on config file */ char *dev_name = "/dev/scanner"; memcpy (hp_global_config_get (), &df_config, sizeof (df_config)); hp_attach_matching_devices (hp_global_config_get (), dev_name); } global.config_read++; return SANE_STATUS_GOOD; } static SANE_Status hp_update_devlist (void) { HpDeviceList devp; const SANE_Device **devlist; int count = 0; RETURN_IF_FAIL( hp_read_config() ); if (global.devlist) sanei_hp_free(global.devlist); for (devp = global.device_list; devp; devp = devp->next) count++; if (!(devlist = sanei_hp_alloc((count + 1) * sizeof(*devlist)))) return SANE_STATUS_NO_MEM; global.devlist = devlist; for (devp = global.device_list; devp; devp = devp->next) *devlist++ = sanei_hp_device_sanedevice(devp->dev); *devlist = 0; return SANE_STATUS_GOOD; } /* * */ SANE_Status sane_init (SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) {SANE_Status status; DBG_INIT(); DBG(3, "sane_init called\n"); sanei_thread_init (); sanei_hp_init_openfd (); hp_destroy(); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, VERSIO); status = hp_init(); DBG(3, "sane_init will finish with %s\n", sane_strstatus (status)); return status; } void sane_exit (void) { DBG(3, "sane_exit called\n"); hp_destroy(); DBG(3, "sane_exit will finish\n"); } SANE_Status sane_get_devices (const SANE_Device ***device_list, SANE_Bool __sane_unused__ local_only) { DBG(3, "sane_get_devices called\n"); RETURN_IF_FAIL( hp_update_devlist() ); *device_list = global.devlist; DBG(3, "sane_get_devices will finish with %s\n", sane_strstatus (SANE_STATUS_GOOD)); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle *handle) { HpDevice dev = 0; HpHandle h; DBG(3, "sane_open called\n"); RETURN_IF_FAIL( hp_read_config() ); if (devicename[0]) RETURN_IF_FAIL( hp_get_dev(devicename, &dev) ); else { /* empty devicname -> use first device */ if (global.device_list) dev = global.device_list->dev; } if (!dev) return SANE_STATUS_INVAL; if (!(h = sanei_hp_handle_new(dev))) return SANE_STATUS_NO_MEM; RETURN_IF_FAIL( hp_handle_list_add(&global.handle_list, h) ); *handle = h; DBG(3, "sane_open will finish with %s\n", sane_strstatus (SANE_STATUS_GOOD)); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { HpHandle h = handle; DBG(3, "sane_close called\n"); if (!FAILED( hp_handle_list_remove(&global.handle_list, h) )) sanei_hp_handle_destroy(h); DBG(3, "sane_close will finish\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int optnum) { HpHandle h = handle; const SANE_Option_Descriptor *optd; DBG(10, "sane_get_option_descriptor called\n"); optd = sanei_hp_handle_saneoption(h, optnum); DBG(10, "sane_get_option_descriptor will finish\n"); return optd; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int optnum, SANE_Action action, void *valp, SANE_Int *info) { HpHandle h = handle; SANE_Status status; DBG(10, "sane_control_option called\n"); status = sanei_hp_handle_control(h, optnum, action, valp, info); DBG(10, "sane_control_option will finish with %s\n", sane_strstatus (status)); return status; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) { HpHandle h = handle; SANE_Status status; DBG(10, "sane_get_parameters called\n"); status = sanei_hp_handle_getParameters(h, params); DBG(10, "sane_get_parameters will finish with %s\n", sane_strstatus (status)); return status; } SANE_Status sane_start (SANE_Handle handle) { HpHandle h = handle; SANE_Status status; DBG(3, "sane_start called\n"); status = sanei_hp_handle_startScan(h); DBG(3, "sane_start will finish with %s\n", sane_strstatus (status)); return status; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte *buf, SANE_Int max_len, SANE_Int *len) { HpHandle h = handle; size_t length = max_len; SANE_Status status; DBG(16, "sane_read called\n"); status = sanei_hp_handle_read(h, buf, &length); *len = length; DBG(16, "sane_read will finish with %s\n", sane_strstatus (status)); return status; } void sane_cancel (SANE_Handle handle) { HpHandle h = handle; DBG(3, "sane_cancel called\n"); sanei_hp_handle_cancel(h); DBG(3, "sane_cancel will finish\n"); } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { HpHandle h = handle; SANE_Status status; DBG(3, "sane_set_io_mode called\n"); status = sanei_hp_handle_setNonblocking(h, non_blocking); DBG(3, "sane_set_io_mode will finish with %s\n", sane_strstatus (status)); return status; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int *fd) { HpHandle h = handle; SANE_Status status; DBG(10, "sane_get_select_fd called\n"); status = sanei_hp_handle_getPipefd(h, fd); DBG(10, "sane_get_select_fd will finish with %s\n", sane_strstatus (status)); return status; } sane-backends-1.0.27/backend/sp15c.c0000664000175000017500000020155512775312261013726 00000000000000static const char RCSid[] = "$Header$"; /* sane - Scanner Access Now Easy. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Fujitsu ScanParner 15C flatbed/ADF scanners. It was derived from the COOLSCAN driver. Written by Randolph Bentson */ /* * $Log$ * Revision 1.17 2008/11/26 21:21:30 kitno-guest * * backend/ *.[ch]: nearly every backend used V_MAJOR * instead of SANE_CURRENT_MAJOR in sane_init() * * backend/snapscan.c: remove EXPECTED_VERSION check * since new SANE standard is forward compatible * * Revision 1.16 2008-07-26 03:53:44 kitno-guest * separate x-resolution from resolution, and update all backends that use * it, to prevent ui change * * Revision 1.15 2007-11-18 10:59:18 ellert-guest * Fix handling of valid "negative" PIDs * * Revision 1.14 2007-10-26 14:56:38 jblache * OPT_NUM_OPTS must be of type SANE_TYPE_INT. * * Revision 1.13 2006/03/29 20:48:50 hmg-guest * Fixed ADF support. Patch from Andreas Degert . * * Revision 1.12 2005/10/01 17:06:25 hmg-guest * Fixed some warnings (bug #302290). * * Revision 1.11 2005/07/15 18:12:49 hmg-guest * Better 4->8 bit depth expansion algorithm (from Mattias Ellert * ). * * Revision 1.10 2004/10/06 15:59:40 hmg-guest * Don't eject medium twice after each page. * * Revision 1.9 2004/06/20 00:34:10 ellert-guest * Missed one... * * Revision 1.8 2004/05/29 10:27:47 hmg-guest * Fixed the fix of the sanei_thread fix (from Mattias Ellert). * * Revision 1.7 2004/05/28 18:52:53 hmg-guest * Fixed sanei_thread fix (bug #300634, by Mattias Ellert). * * Revision 1.6 2004/05/23 17:28:56 hmg-guest * Use sanei_thread instead of fork() in the unmaintained backends. * Patches from Mattias Ellert (bugs: 300635, 300634, 300633, 300629). * * Revision 1.5 2003/12/27 17:48:38 hmg-guest * Silenced some compilation warnings. * * Revision 1.4 2001/05/31 18:01:39 hmg * Fixed config_line[len-1] bug which could generate an access * violation if len==0. * Henning Meier-Geinitz * * Revision 1.3 2000/08/12 15:09:38 pere * Merge devel (v1.0.3) into head branch. * * Revision 1.1.2.6 2000/07/30 11:16:06 hmg * 2000-07-30 Henning Meier-Geinitz * * * backend/mustek.*: Update to Mustek backend 1.0-95. Changed from * wait() to waitpid() and removed unused code. * * configure configure.in backend/m3096g.c backend/sp15c.c: Reverted * the V_REV patch. V_REV should not be used in backends. * * Revision 1.1.2.5 2000/07/29 21:38:13 hmg * 2000-07-29 Henning Meier-Geinitz * * * backend/sp15.c backend/m3096g.c: Replace fgets with * sanei_config_read, return V_REV as part of version_code string * (patch from Randolph Bentson). * * Revision 1.1.2.4 2000/07/25 21:47:46 hmg * 2000-07-25 Henning Meier-Geinitz * * * backend/snapscan.c: Use DBG(0, ...) instead of fprintf (stderr, ...). * * backend/abaton.c backend/agfafocus.c backend/apple.c backend/dc210.c * backend/dll.c backend/dmc.c backend/microtek2.c backend/pint.c * backend/qcam.c backend/ricoh.c backend/s9036.c backend/snapscan.c * backend/tamarack.c: Use sanei_config_read instead of fgets. * * backend/dc210.c backend/microtek.c backend/pnm.c: Added * #include "../include/sane/config.h". * * backend/dc25.c backend/m3096.c backend/sp15.c * backend/st400.c: Moved #include "../include/sane/config.h" to the beginning. * * AUTHORS: Changed agfa to agfafocus. * * Revision 1.1.2.3 2000/03/14 17:47:12 abel * new version of the Sharp backend added. * * Revision 1.1.2.2 2000/01/26 03:51:48 pere * Updated backends sp15c (v1.12) and m3096g (v1.11). * * Revision 1.12 2000/01/25 16:23:13 bentson * tab expansion; add one debug message * * Revision 1.11 2000/01/05 05:21:37 bentson * indent to barfable GNU style * * Revision 1.10 1999/12/06 17:36:55 bentson * show default value for scan size at the start * * Revision 1.9 1999/12/04 00:30:35 bentson * fold in 1.8.1.x versions * * Revision 1.8.1.2 1999/12/04 00:19:43 bentson * bunch of changes to complete MEDIA CHECK use * * Revision 1.8.1.1 1999/12/03 20:44:56 bentson * trial changes to use MEDIA CHECK command * * Revision 1.8 1999/12/03 18:30:56 bentson * cosmetic changes * * Revision 1.7 1999/11/24 20:09:25 bentson * fold in 1.6.1.x changes * * Revision 1.6.1.3 1999/11/24 15:56:48 bentson * remove some debugging; final :-) fix to option constraint processing * * Revision 1.6.1.2 1999/11/24 15:37:42 bentson * more constraint debugging * * Revision 1.6.1.1 1999/11/24 14:35:24 bentson * fix some of the constraint handling * * Revision 1.6 1999/11/23 18:48:27 bentson * add constraint checking and enforcement * * Revision 1.5 1999/11/23 08:26:03 bentson * basic color seems to work * * Revision 1.4 1999/11/23 06:41:26 bentson * 4-bit Grayscale works; now working on color * * Revision 1.3 1999/11/22 18:15:07 bentson * more work on color support * * Revision 1.2 1999/11/19 17:30:54 bentson * enhance control (works with xscanimage) * * Revision 1.1 1999/11/19 15:09:08 bentson * cribbed from m3096g * */ /* SANE-FLOW-DIAGRAM - sane_init() : initialize backend, attach scanners . - sane_get_devices() : query list of scanner-devices . - sane_open() : open a particular scanner-device . . - sane_set_io_mode : set blocking-mode . . - sane_get_select_fd : get scanner-fd . . - sane_get_option_descriptor() : get option informations . . - sane_control_option() : change option values . . . . - sane_start() : start image aquisition . . - sane_get_parameters() : returns actual scan-parameters . . - sane_read() : read image-data (from pipe) . . . . - sane_cancel() : cancel operation . - sane_close() : close opened scanner-device - sane_exit() : terminate use of backend */ /* ------------------------------------------------------------------------- */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_thread.h" #include "sp15c-scsi.h" #include "sp15c.h" /* ------------------------------------------------------------------------- */ static const char negativeStr[] = "Negative"; static const char positiveStr[] = "Positive"; static SANE_String_Const type_list[] = {positiveStr, negativeStr, 0}; static SANE_String_Const source_list[] = {"ADF", "FB", NULL}; static const SANE_Int resolution_list[] = {11, 0, 60, 75, 80, 100, 120, 150, 200, 240, 300, 600}; static const SANE_Int x_res_list[] = {11, 0, 60, 75, 80, 100, 120, 150, 200, 240, 300, 600}; static const SANE_Int y_res_list[] = {11, 0, 60, 75, 80, 100, 120, 150, 200, 240, 300, 600}; static const char lineStr[] = SANE_VALUE_SCAN_MODE_LINEART; static const char halfStr[] = SANE_VALUE_SCAN_MODE_HALFTONE; static const char gray4Str[] = "4-bit Gray"; static const char gray8Str[] = "8-bit Gray"; static const char colorStr[] = SANE_VALUE_SCAN_MODE_COLOR; static SANE_String_Const scan_mode_list[] = {lineStr, halfStr, gray4Str, gray8Str, colorStr, NULL}; /* how do the following work? */ static const SANE_Range brightness_range = {0, 255, 32}; static const SANE_Range threshold_range = {0, 255, 4}; static const SANE_Range x_range = {0, SANE_FIX (216), 1}; static const SANE_Range y_range_fb = {0, SANE_FIX (295), 1}; static const SANE_Range y_range_adf = {0, SANE_FIX (356), 1}; /* ################# externally visible routines ################{ */ SANE_Status /* looks like frontend ignores results */ sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; authorize = authorize; /* silence compilation warnings */ DBG_INIT (); DBG (10, "sane_init\n"); sanei_thread_init (); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open (SP15C_CONFIG_FILE); if (!fp) { attach_scanner ("/dev/scanner", 0); /* no config-file: /dev/scanner */ return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') continue; len = strlen (dev_name); if (!len) continue; sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); return SANE_STATUS_GOOD; } /* sane_init */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { struct sp15c *dev; int i; local_only = local_only; /* silence compilation warnings */ DBG (10, "sane_get_devices\n"); if (devlist) free (devlist); devlist = calloc (num_devices + 1, sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; for (dev = first_dev, i = 0; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } /* sane_get_devices */ SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle) { struct sp15c *dev = first_dev; name = name; /* silence compilation warnings */ /* Strange, name is not used? */ DBG (10, "sane_open\n"); if (!dev) return SANE_STATUS_INVAL; init_options (dev); *handle = dev; dev->use_adf = SANE_TRUE; dev->x_res = 200; dev->y_res = 200; dev->tl_x = 0; dev->tl_y = 0; dev->br_x = 1200 * 17 / 2; dev->br_y = 1200 * 11; dev->brightness = 128; dev->threshold = 128; dev->contrast = 128; dev->composition = WD_comp_LA; dev->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; dev->bitsperpixel = 1; dev->halftone = 0; dev->rif = 0; dev->bitorder = 0; dev->compress_type = 0; dev->compress_arg = 0; dev->vendor_id_code = 0; dev->outline = 0; dev->emphasis = 0; dev->auto_sep = 0; dev->mirroring = 0; dev->var_rate_dyn_thresh = 0; dev->white_level_follow = 0; dev->paper_size = 0x87; dev->paper_width_X = 1200 * 17 / 2; dev->paper_length_Y = 1200 * 11; dev->opt[OPT_TL_Y].constraint.range = &y_range_adf; dev->opt[OPT_BR_Y].constraint.range = &y_range_adf; adjust_width (dev, 0); return SANE_STATUS_GOOD; } /* sane_open */ SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) { h = h; non_blocking = non_blocking; /* silence compilation warnings */ DBG (10, "sane_set_io_mode\n"); return SANE_STATUS_UNSUPPORTED; } /* sane_set_io_mode */ SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp) { h = h; fdp = fdp; /* silence compilation warnings */ DBG (10, "sane_get_select_fd\n"); return SANE_STATUS_UNSUPPORTED; } /* sane_get_select_fd */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { struct sp15c *scanner = handle; DBG (10, "sane_get_option_descriptor: \"%s\"\n", scanner->opt[option].name); if ((unsigned) option >= NUM_OPTIONS) return 0; return &scanner->opt[option]; } /* sane_get_option_descriptor */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { struct sp15c *scanner = handle; SANE_Status status; SANE_Word cap; if (info) *info = 0; if (scanner->scanning == SANE_TRUE) { DBG (5, "sane_control_option: device busy\n"); return SANE_STATUS_IO_ERROR; } if (option >= NUM_OPTIONS) return SANE_STATUS_INVAL; cap = scanner->opt[option].cap; if (action == SANE_ACTION_GET_VALUE) { DBG (10, "sane_control_option: get value \"%s\"\n", scanner->opt[option].name); DBG (11, "\tcap = %d\n", cap); if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (10, "\tinactive\n"); return SANE_STATUS_INVAL; } switch (option) { case OPT_NUM_OPTS: *(SANE_Word *) val = NUM_OPTIONS; return SANE_STATUS_GOOD; case OPT_SOURCE: if (scanner->use_adf == SANE_TRUE) { strcpy (val, "ADF"); } else { strcpy (val, "FB"); } return SANE_STATUS_GOOD; case OPT_MODE: switch (scanner->composition) { case WD_comp_LA: strcpy (val, lineStr); break; case WD_comp_HT: strcpy (val, halfStr); break; case WD_comp_G4: strcpy (val, gray4Str); break; case WD_comp_G8: strcpy (val, gray8Str); break; case WD_comp_MC: strcpy (val, colorStr); break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; case OPT_TYPE: return SANE_STATUS_INVAL; case OPT_PRESCAN: return SANE_STATUS_INVAL; case OPT_X_RES: *(SANE_Word *) val = scanner->x_res; return SANE_STATUS_GOOD; case OPT_Y_RES: *(SANE_Word *) val = scanner->y_res; return SANE_STATUS_GOOD; case OPT_PREVIEW_RES: return SANE_STATUS_INVAL; case OPT_TL_X: *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tl_x)); return SANE_STATUS_GOOD; case OPT_TL_Y: *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tl_y)); return SANE_STATUS_GOOD; case OPT_BR_X: *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->br_x)); return SANE_STATUS_GOOD; case OPT_BR_Y: *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->br_y)); return SANE_STATUS_GOOD; case OPT_AVERAGING: return SANE_STATUS_INVAL; case OPT_BRIGHTNESS: *(SANE_Word *) val = scanner->brightness; return SANE_STATUS_GOOD; case OPT_THRESHOLD: *(SANE_Word *) val = scanner->threshold; return SANE_STATUS_GOOD; case OPT_PREVIEW: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { DBG (10, "sane_control_option: set value \"%s\"\n", scanner->opt[option].name); if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (10, "\tinactive\n"); return SANE_STATUS_INVAL; } if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (10, "\tnot settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (scanner->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (10, "\tbad value\n"); return status; } switch (option) { case OPT_NUM_OPTS: return SANE_STATUS_GOOD; case OPT_SOURCE: if (strcmp (val, "ADF") == 0) { if (scanner->use_adf == SANE_TRUE) return SANE_STATUS_GOOD; scanner->use_adf = SANE_TRUE; scanner->opt[OPT_TL_Y].constraint.range = &y_range_adf; scanner->opt[OPT_BR_Y].constraint.range = &y_range_adf; apply_constraints (scanner, OPT_TL_Y, &scanner->tl_y, info); apply_constraints (scanner, OPT_BR_Y, &scanner->br_y, info); } else if (strcmp (val, "FB") == 0) { if (scanner->use_adf == SANE_FALSE) return SANE_STATUS_GOOD; scanner->use_adf = SANE_FALSE; scanner->opt[OPT_TL_Y].constraint.range = &y_range_fb; scanner->opt[OPT_BR_Y].constraint.range = &y_range_fb; apply_constraints (scanner, OPT_TL_Y, &scanner->tl_y, info); apply_constraints (scanner, OPT_BR_Y, &scanner->br_y, info); } else { return SANE_STATUS_INVAL; } if (info) { *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_MODE: if (strcmp (val, lineStr) == 0) { if (scanner->composition == WD_comp_LA) return SANE_STATUS_GOOD; scanner->composition = WD_comp_LA; scanner->bitsperpixel = 1; scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; scanner->vendor_id_code = 0; } else if (strcmp (val, halfStr) == 0) { if (scanner->composition == WD_comp_HT) return SANE_STATUS_GOOD; scanner->composition = WD_comp_HT; scanner->bitsperpixel = 1; scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_INACTIVE; scanner->vendor_id_code = 0; } else if (strcmp (val, gray4Str) == 0) { if (scanner->composition == WD_comp_G4) return SANE_STATUS_GOOD; scanner->composition = WD_comp_G4; scanner->bitsperpixel = 4; scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_INACTIVE; scanner->vendor_id_code = 0; } else if (strcmp (val, gray8Str) == 0) { if (scanner->composition == WD_comp_G8) return SANE_STATUS_GOOD; scanner->composition = WD_comp_G8; scanner->bitsperpixel = 8; scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_INACTIVE; scanner->vendor_id_code = 0; } else if (strcmp (val, colorStr) == 0) { if (scanner->composition == WD_comp_MC) return SANE_STATUS_GOOD; scanner->composition = WD_comp_MC; scanner->bitsperpixel = 8; scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_INACTIVE; scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_INACTIVE; scanner->vendor_id_code = 0xff; } else { return SANE_STATUS_INVAL; } if (info) { *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_TYPE: return SANE_STATUS_INVAL; case OPT_PRESCAN: return SANE_STATUS_INVAL; case OPT_X_RES: scanner->x_res = (*(SANE_Word *) val); adjust_width (scanner, info); if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_Y_RES: scanner->y_res = (*(SANE_Word *) val); if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_PREVIEW_RES: return SANE_STATUS_INVAL; case OPT_TL_X: scanner->tl_x = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); adjust_width (scanner, info); *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tl_x)); if (info) { *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; } return SANE_STATUS_GOOD; case OPT_TL_Y: scanner->tl_y = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->tl_y)); if (info) { *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; } return SANE_STATUS_GOOD; case OPT_BR_X: scanner->br_x = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); adjust_width (scanner, info); *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->br_x)); if (info) { *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; } return SANE_STATUS_GOOD; case OPT_BR_Y: scanner->br_y = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); *(SANE_Word *) val = SANE_FIX (iluToMm (scanner->br_y)); if (info) { *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; } return SANE_STATUS_GOOD; case OPT_AVERAGING: return SANE_STATUS_INVAL; case OPT_BRIGHTNESS: scanner->brightness = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_THRESHOLD: scanner->threshold = *(SANE_Word *) val; return SANE_STATUS_GOOD; } /* switch */ } /* else */ return SANE_STATUS_INVAL; } /* sane_control_option */ SANE_Status sane_start (SANE_Handle handle) { struct sp15c *scanner = handle; int fds[2]; int ret; DBG (10, "sane_start\n"); if (scanner->scanning == SANE_TRUE) { DBG (5, "sane_start: device busy\n"); return SANE_STATUS_DEVICE_BUSY; } if (scanner->sfd < 0) { /* first call */ if (sanei_scsi_open (scanner->sane.name, &(scanner->sfd), sense_handler, 0) != SANE_STATUS_GOOD) { DBG (1, "sane_start: open of %s failed:\n", scanner->sane.name); return SANE_STATUS_INVAL; } } scanner->scanning = SANE_TRUE; if ((ret = sp15c_check_values (scanner)) != 0) { /* Verify values */ DBG (1, "sane_start: ERROR: invalid scan-values\n"); sanei_scsi_close (scanner->sfd); scanner->scanning = SANE_FALSE; scanner->sfd = -1; return SANE_STATUS_INVAL; } if ((ret = sp15c_grab_scanner (scanner))) { DBG (5, "sane_start: unable to reserve scanner\n"); sanei_scsi_close (scanner->sfd); scanner->scanning = SANE_FALSE; scanner->sfd = -1; return ret; } if ((ret = sp15c_set_window_param (scanner, 0))) { DBG (5, "sane_start: ERROR: failed to set window\n"); sp15c_free_scanner (scanner); sanei_scsi_close (scanner->sfd); scanner->scanning = SANE_FALSE; scanner->sfd = -1; return ret; } /* Since the SET WINDOW can specify the use of the ADF, and since the ScanPartner 15C automatically pre-loads sheets from the ADF, it is only necessary to see if any paper is available. The OEM Manual offers the OBJECT POSITION command, but it causes the carrier unit into a "homing" cycle. The undocumented MEDIA CHECK command avoids the "homing" cycle. (Note the SET WINDOW command had to use the color scanning vendor unique parameters, regardless of scanning mode, so that it could invoke the ADF.) */ if (scanner->use_adf == SANE_TRUE && (ret = sp15c_media_check (scanner))) { DBG (5, "sane_start: WARNING: ADF empty\n"); sp15c_free_scanner (scanner); sanei_scsi_close (scanner->sfd); scanner->scanning = SANE_FALSE; scanner->sfd = -1; return ret; } swap_res (scanner); DBG (10, "\tbytes per line = %d\n", bytes_per_line (scanner)); DBG (10, "\tpixels_per_line = %d\n", pixels_per_line (scanner)); DBG (10, "\tlines = %d\n", lines_per_scan (scanner)); DBG (10, "\tbrightness (halftone) = %d\n", scanner->brightness); DBG (10, "\tthreshold (line art) = %d\n", scanner->threshold); if (scanner->composition == WD_comp_MC && (ret = sp15c_start_scan (scanner))) { DBG (5, "sane_start: start_scan failed\n"); sp15c_free_scanner (scanner); sanei_scsi_close (scanner->sfd); scanner->scanning = SANE_FALSE; scanner->sfd = -1; return SANE_STATUS_INVAL; } /* create a pipe, fds[0]=read-fd, fds[1]=write-fd */ if (pipe (fds) < 0) { DBG (1, "ERROR: could not create pipe\n"); swap_res (scanner); scanner->scanning = SANE_FALSE; sp15c_free_scanner (scanner); sanei_scsi_close (scanner->sfd); scanner->sfd = -1; return SANE_STATUS_IO_ERROR; } scanner->pipe = fds[0]; scanner->reader_pipe = fds[1]; scanner->reader_pid = sanei_thread_begin (reader_process, (void *) scanner); if (sanei_thread_is_forked ()) close (scanner->reader_pipe); DBG (10, "sane_start: ok\n"); return SANE_STATUS_GOOD; } /* sane_start */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { struct sp15c *scanner = handle; DBG (10, "sane_get_parameters\n"); if (scanner->composition == WD_comp_MC) { params->format = SANE_FRAME_RGB; params->depth = 8; } else if (scanner->composition == WD_comp_LA || scanner->composition == WD_comp_HT) { params->format = SANE_FRAME_GRAY; params->depth = 1; } else { params->format = SANE_FRAME_GRAY; params->depth = 8; } params->pixels_per_line = pixels_per_line (scanner); params->lines = lines_per_scan (scanner); params->bytes_per_line = bytes_per_line (scanner); params->last_frame = 1; DBG (10, "\tdepth %d\n", params->depth); DBG (10, "\tlines %d\n", params->lines); DBG (10, "\tpixels_per_line %d\n", params->pixels_per_line); DBG (10, "\tbytes_per_line %d\n", params->bytes_per_line); /*************************/ DBG (10, "\tlength %d\n", scanner->br_y - scanner->tl_y); DBG (10, "\t(nom.) width %d\n", scanner->br_x - scanner->tl_x); DBG (10, "\tx res %d\n", scanner->x_res); DBG (10, "\ty res %d\n", scanner->y_res); /*************************/ return SANE_STATUS_GOOD; } /* sane_get_parameters */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { struct sp15c *scanner = handle; ssize_t nread; DBG (10, "sane_read\n"); *len = 0; nread = read (scanner->pipe, buf, max_len); DBG (10, "sane_read: read %ld bytes of %ld\n", (long) nread, (long) max_len); if (scanner->scanning == SANE_FALSE) { /* PREDICATE WAS (!(scanner->scanning)) */ return do_cancel (scanner); } if (nread < 0) { if (errno == EAGAIN) { return SANE_STATUS_GOOD; } else { do_cancel (scanner); return SANE_STATUS_IO_ERROR; } } *len = nread; if (nread == 0) return do_eof (scanner); /* close pipe */ return SANE_STATUS_GOOD; } /* sane_read */ void sane_cancel (SANE_Handle h) { DBG (10, "sane_cancel\n"); do_cancel ((struct sp15c *) h); } /* sane_cancel */ void sane_close (SANE_Handle handle) { DBG (10, "sane_close\n"); if (((struct sp15c *) handle)->scanning == SANE_TRUE) do_cancel (handle); } /* sane_close */ void sane_exit (void) { struct sp15c *dev, *next; DBG (10, "sane_exit\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free (dev->devicename); free (dev->buffer); free (dev); } if (devlist) free (devlist); } /* sane_exit */ /* }################ internal (support) routines ################{ */ static SANE_Status attach_scanner (const char *devicename, struct sp15c **devp) { struct sp15c *dev; int sfd; DBG (15, "attach_scanner: %s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (5, "attach_scanner: scanner already attached (is ok)!\n"); return SANE_STATUS_GOOD; } } DBG (15, "attach_scanner: opening %s\n", devicename); if (sanei_scsi_open (devicename, &sfd, sense_handler, 0) != 0) { DBG (5, "attach_scanner: open failed\n"); return SANE_STATUS_INVAL; } if (NULL == (dev = malloc (sizeof (*dev)))) return SANE_STATUS_NO_MEM; dev->row_bufsize = (sanei_scsi_max_request_size < (64 * 1024)) ? sanei_scsi_max_request_size : 64 * 1024; if ((dev->buffer = malloc (dev->row_bufsize)) == NULL) return SANE_STATUS_NO_MEM; dev->devicename = strdup (devicename); dev->sfd = sfd; if (sp15c_identify_scanner (dev) != 0) { DBG (5, "attach_scanner: scanner-identification failed\n"); sanei_scsi_close (dev->sfd); free (dev->buffer); free (dev); return SANE_STATUS_INVAL; } #if 0 /* Get MUD (via mode_sense), internal info (via get_internal_info), and * initialize values */ coolscan_initialize_values (dev); #endif /* Why? */ sanei_scsi_close (dev->sfd); dev->sfd = -1; dev->sane.name = dev->devicename; dev->sane.vendor = dev->vendor; dev->sane.model = dev->product; dev->sane.type = "flatbed/ADF scanner"; ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } DBG (15, "attach_scanner: done\n"); return SANE_STATUS_GOOD; } /* attach_scanner */ static SANE_Status attach_one (const char *name) { return attach_scanner (name, 0); } /* attach_one */ static SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg) { scsi_fd = scsi_fd; arg = arg; /* silence compilation warnings */ return request_sense_parse (result); } /* sense_handler */ static int request_sense_parse (u_char * sensed_data) { unsigned int ret, sense, asc, ascq; sense = get_RS_sense_key (sensed_data); asc = get_RS_ASC (sensed_data); ascq = get_RS_ASCQ (sensed_data); ret = SANE_STATUS_IO_ERROR; switch (sense) { case 0x0: /* No Sense */ DBG (5, "\t%d/%d/%d: Scanner ready\n", sense, asc, ascq); return SANE_STATUS_GOOD; case 0x2: /* Not Ready */ if ((0x00 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: Not Ready \n", sense, asc, ascq); } else { DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); } break; case 0x3: /* Medium Error */ if ((0x80 == asc) && (0x01 == ascq)) { DBG (1, "\t%d/%d/%d: Jam \n", sense, asc, ascq); ret = SANE_STATUS_JAMMED; } else if ((0x80 == asc) && (0x02 == ascq)) { DBG (1, "\t%d/%d/%d: ADF cover open \n", sense, asc, ascq); ret = SANE_STATUS_COVER_OPEN; } else if ((0x80 == asc) && (0x03 == ascq)) { DBG (1, "\t%d/%d/%d: ADF empty \n", sense, asc, ascq); ret = SANE_STATUS_NO_DOCS; } else { DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); } break; case 0x4: /* Hardware Error */ if ((0x80 == asc) && (0x01 == ascq)) { DBG (1, "\t%d/%d/%d: FB motor fuse \n", sense, asc, ascq); } else if ((0x80 == asc) && (0x02 == ascq)) { DBG (1, "\t%d/%d/%d: heater fuse \n", sense, asc, ascq); } else if ((0x80 == asc) && (0x04 == ascq)) { DBG (1, "\t%d/%d/%d: ADF motor fuse \n", sense, asc, ascq); } else if ((0x80 == asc) && (0x05 == ascq)) { DBG (1, "\t%d/%d/%d: mechanical alarm \n", sense, asc, ascq); } else if ((0x80 == asc) && (0x06 == ascq)) { DBG (1, "\t%d/%d/%d: optical alarm \n", sense, asc, ascq); } else if ((0x44 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: abnormal internal target \n", sense, asc, ascq); } else if ((0x47 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: SCSI parity error \n", sense, asc, ascq); } else { DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); } break; case 0x5: /* Illegal Request */ if ((0x20 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: Invalid command \n", sense, asc, ascq); ret = SANE_STATUS_INVAL; } else if ((0x24 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: Invalid field in CDB \n", sense, asc, ascq); ret = SANE_STATUS_INVAL; } else if ((0x25 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: Unsupported logical unit \n", sense, asc, ascq); ret = SANE_STATUS_UNSUPPORTED; } else if ((0x26 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: Invalid field in parm list \n", sense, asc, ascq); ret = SANE_STATUS_INVAL; } else if ((0x2C == asc) && (0x02 == ascq)) { DBG (1, "\t%d/%d/%d: wrong window combination \n", sense, asc, ascq); ret = SANE_STATUS_INVAL; } else { DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); } break; case 0x6: /* Unit Attention */ if ((0x00 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: UNIT ATTENTION \n", sense, asc, ascq); } else { DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); } break; case 0xb: /* Aborted Command */ if ((0x43 == asc) && (0x00 == ascq)) { DBG (1, "\t%d/%d/%d: Message error \n", sense, asc, ascq); } else if ((0x80 == asc) && (0x01 == ascq)) { DBG (1, "\t%d/%d/%d: Image transfer error \n", sense, asc, ascq); } else { DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); } break; default: DBG (1, "\tUnknown - Sense=%d, ASC=%d, ASCQ=%d\n", sense, asc, ascq); } return ret; } /* request_sense_parse */ static SANE_Status sp15c_identify_scanner (struct sp15c *s) { char vendor[9]; char product[0x11]; char version[5]; char *pp; SANE_Status ret; DBG (10, "identify_scanner\n"); vendor[8] = product[0x10] = version[4] = 0; if ((ret = sp15c_do_inquiry (s))) { DBG (5, "identify_scanner: inquiry failed\n"); return ret; } if (get_IN_periph_devtype (s->buffer) != IN_periph_devtype_scanner) { DBG (5, "identify_scanner: not a scanner\n"); return SANE_STATUS_INVAL; } get_IN_vendor ((char *) s->buffer, vendor); get_IN_product ((char *)s->buffer, product); get_IN_version ((char *)s->buffer, version); if (strncmp ("FCPA ", vendor, 8)) { DBG (5, "identify_scanner: \"%s\" isn't a Fujitsu product\n", vendor); return 1; } pp = &vendor[8]; vendor[8] = ' '; while (*pp == ' ') { *pp-- = '\0'; } pp = &product[0x10]; product[0x10] = ' '; while (*(pp - 1) == ' ') { *pp-- = '\0'; } /* leave one blank at the end! */ pp = &version[4]; version[4] = ' '; while (*pp == ' ') { *pp-- = '\0'; } if (get_IN_adf (s->buffer)) { s->autofeeder = 1; } else { s->autofeeder = 0; } DBG (10, "Found %s scanner %s version %s on device %s %x/%x/%x\n", vendor, product, version, s->devicename, s->autofeeder, get_IN_color_mode (s->buffer), get_IN_color_seq (s->buffer)); vendor[8] = '\0'; product[16] = '\0'; version[4] = '\0'; strncpy (s->vendor, vendor, 9); strncpy (s->product, product, 17); strncpy (s->version, version, 5); return SANE_STATUS_GOOD; } /* sp15c_identify_scanner */ static SANE_Status sp15c_do_inquiry (struct sp15c *s) { static SANE_Status ret; DBG (10, "do_inquiry\n"); memset (s->buffer, '\0', 256); /* clear buffer */ set_IN_return_size (inquiryB.cmd, 96); ret = do_scsi_cmd (s->sfd, inquiryB.cmd, inquiryB.size, s->buffer, 96); return ret; } /* sp15c_do_inquiry */ static SANE_Status do_scsi_cmd (int fd, unsigned char *cmd, int cmd_len, unsigned char *out, size_t out_len) { SANE_Status ret; size_t ol = out_len; hexdump (20, "rslt>", out, (out_len > 0x60) ? 0x60 : out_len); return ret; } /* do_scsi_cmd */ static void hexdump (int level, char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; DBG (level, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { *ptr = '\0'; DBG (level, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3d:", i); ptr += 4; } sprintf (ptr, " %2.2x", *p); ptr += 3; } *ptr = '\0'; DBG (level, "%s\n", line); } /* hexdump */ static SANE_Status init_options (struct sp15c *scanner) { int i; DBG (10, "init_options\n"); memset (scanner->opt, 0, sizeof (scanner->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { scanner->opt[i].size = sizeof (SANE_Word); scanner->opt[i].cap = SANE_CAP_INACTIVE; } scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; /************** "Mode" group: **************/ scanner->opt[OPT_MODE_GROUP].title = "Scan Mode"; scanner->opt[OPT_MODE_GROUP].desc = ""; scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* source */ scanner->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; scanner->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; scanner->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; scanner->opt[OPT_SOURCE].type = SANE_TYPE_STRING; scanner->opt[OPT_SOURCE].size = max_string_size (source_list); scanner->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_SOURCE].constraint.string_list = source_list; if (scanner->autofeeder) { scanner->opt[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* scan mode */ scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; scanner->opt[OPT_MODE].type = SANE_TYPE_STRING; scanner->opt[OPT_MODE].size = max_string_size (scan_mode_list); scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_MODE].constraint.string_list = scan_mode_list; scanner->opt[OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* negative */ scanner->opt[OPT_TYPE].name = "type"; scanner->opt[OPT_TYPE].title = "Film type"; scanner->opt[OPT_TYPE].desc = "positive or negative image"; scanner->opt[OPT_TYPE].type = SANE_TYPE_STRING; scanner->opt[OPT_TYPE].size = max_string_size (type_list); scanner->opt[OPT_TYPE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_TYPE].constraint.string_list = type_list; scanner->opt[OPT_PRESCAN].name = "prescan"; scanner->opt[OPT_PRESCAN].title = "Prescan"; scanner->opt[OPT_PRESCAN].desc = "Perform a prescan during preview"; scanner->opt[OPT_PRESCAN].type = SANE_TYPE_BOOL; scanner->opt[OPT_PRESCAN].unit = SANE_UNIT_NONE; /* resolution */ scanner->opt[OPT_X_RES].name = SANE_NAME_SCAN_RESOLUTION; scanner->opt[OPT_X_RES].title = SANE_TITLE_SCAN_X_RESOLUTION; scanner->opt[OPT_X_RES].desc = SANE_DESC_SCAN_X_RESOLUTION; scanner->opt[OPT_X_RES].type = SANE_TYPE_INT; scanner->opt[OPT_X_RES].unit = SANE_UNIT_DPI; scanner->opt[OPT_X_RES].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_X_RES].constraint.word_list = x_res_list; scanner->opt[OPT_X_RES].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; scanner->opt[OPT_Y_RES].name = SANE_NAME_SCAN_Y_RESOLUTION; scanner->opt[OPT_Y_RES].title = SANE_TITLE_SCAN_Y_RESOLUTION; scanner->opt[OPT_Y_RES].desc = SANE_DESC_SCAN_Y_RESOLUTION; scanner->opt[OPT_Y_RES].type = SANE_TYPE_INT; scanner->opt[OPT_Y_RES].unit = SANE_UNIT_DPI; scanner->opt[OPT_Y_RES].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_Y_RES].constraint.word_list = y_res_list; scanner->opt[OPT_Y_RES].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; scanner->opt[OPT_PREVIEW_RES].name = "preview-resolution"; scanner->opt[OPT_PREVIEW_RES].title = "Preview resolution"; scanner->opt[OPT_PREVIEW_RES].desc = SANE_DESC_SCAN_RESOLUTION; scanner->opt[OPT_PREVIEW_RES].type = SANE_TYPE_INT; scanner->opt[OPT_PREVIEW_RES].unit = SANE_UNIT_DPI; scanner->opt[OPT_PREVIEW_RES].constraint_type = SANE_CONSTRAINT_WORD_LIST; scanner->opt[OPT_PREVIEW_RES].constraint.word_list = resolution_list; /************** "Geometry" group: **************/ scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; scanner->opt[OPT_GEOMETRY_GROUP].desc = ""; scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_X].constraint.range = &x_range; scanner->opt[OPT_TL_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* top-left y */ scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_Y].constraint.range = &y_range_fb; scanner->opt[OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* bottom-right x */ scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_X].constraint.range = &x_range; scanner->opt[OPT_BR_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* bottom-right y */ scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_Y].constraint.range = &y_range_fb; scanner->opt[OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; /* ------------------------------ */ /************** "Enhancement" group: **************/ scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; scanner->opt[OPT_ENHANCEMENT_GROUP].desc = ""; scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; scanner->opt[OPT_AVERAGING].name = "averaging"; scanner->opt[OPT_AVERAGING].title = "Averaging"; scanner->opt[OPT_AVERAGING].desc = "Averaging"; scanner->opt[OPT_AVERAGING].type = SANE_TYPE_BOOL; scanner->opt[OPT_AVERAGING].unit = SANE_UNIT_NONE; scanner->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; scanner->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; scanner->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; scanner->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BRIGHTNESS].constraint.range = &brightness_range; scanner->opt[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_DETECT; scanner->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; scanner->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; scanner->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; scanner->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; scanner->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; scanner->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_THRESHOLD].constraint.range = &threshold_range; scanner->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_DETECT; /* ------------------------------ */ /************** "Advanced" group: **************/ scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced"; scanner->opt[OPT_ADVANCED_GROUP].desc = ""; scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* preview */ scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; DBG (10, "init_options:ok\n"); return SANE_STATUS_GOOD; } /* init_options */ static int sp15c_check_values (struct sp15c *s) { if (s->use_adf == SANE_TRUE && s->autofeeder == 0) { DBG (1, "sp15c_check_values: %s\n", "ERROR: ADF-MODE NOT SUPPORTED BY SCANNER, ABORTING"); return (1); } return (0); } /* sp15c_check_values */ /* sp15c_free_scanner should go through the following sequence: * OBJECT POSITION DISCHARGE * GOOD * RELEASE UNIT * GOOD */ static int sp15c_free_scanner (struct sp15c *s) { int ret; DBG (10, "sp15c_free_scanner\n"); #if 0 /* hmg: reports from several people show that this code ejects two pages instead of one. So I've commented it out for now. */ ret = sp15c_object_discharge (s); if (ret) return ret; #endif wait_scanner (s); ret = do_scsi_cmd (s->sfd, release_unitB.cmd, release_unitB.size, NULL, 0); if (ret) return ret; DBG (10, "sp15c_free_scanner: ok\n"); return ret; } /* sp15c_free_scanner */ /* sp15c_grab_scanner should go through the following command sequence: * TEST UNIT READY * CHECK CONDITION \ * REQUEST SENSE > These should be handled automagically by * UNIT ATTENTION / the kernel if they happen (powerup/reset) * TEST UNIT READY * GOOD * RESERVE UNIT * GOOD * * It is then responsible for installing appropriate signal handlers * to call emergency_give_scanner() if user aborts. */ static int sp15c_grab_scanner (struct sp15c *s) { int ret; DBG (10, "sp15c_grab_scanner\n"); wait_scanner (s); ret = do_scsi_cmd (s->sfd, reserve_unitB.cmd, reserve_unitB.size, NULL, 0); if (ret) return ret; DBG (10, "sp15c_grab_scanner: ok\n"); return 0; } /* sp15c_grab_scanner */ /* * wait_scanner spins until TEST_UNIT_READY returns 0 (GOOD) * returns 0 on success, * returns -1 on error or timeout */ static int wait_scanner (struct sp15c *s) { int ret = -1; int cnt = 0; DBG (10, "wait_scanner\n"); while (ret != 0) { ret = do_scsi_cmd (s->sfd, test_unit_readyB.cmd, test_unit_readyB.size, 0, 0); if (ret == SANE_STATUS_DEVICE_BUSY) { usleep (50000); /* wait 0.05 seconds */ /* 20 sec. max (prescan takes up to 15 sec.) */ if (cnt++ > 400) { DBG (1, "wait_scanner: scanner does NOT get ready\n"); return -1; } } else if (ret == SANE_STATUS_GOOD) { DBG (10, "wait_scanner: ok\n"); return ret; } else { DBG (1, "wait_scanner: unit ready failed (%s)\n", sane_strstatus (ret)); } } DBG (10, "wait_scanner: ok\n"); return 0; } /* wait_scanner */ /* As noted above, this command has been supplanted by the MEDIA CHECK command. Nevertheless, it's still available here in case some future need is discovered. */ static int sp15c_object_position (struct sp15c *s) { int ret; DBG (10, "sp15c_object_position\n"); if (s->use_adf != SANE_TRUE) { return SANE_STATUS_GOOD; } if (s->autofeeder == 0) { DBG (10, "sp15c_object_position: Autofeeder not present.\n"); return SANE_STATUS_UNSUPPORTED; } memcpy (s->buffer, object_positionB.cmd, object_positionB.size); set_OP_autofeed (s->buffer, OP_Feed); ret = do_scsi_cmd (s->sfd, s->buffer, object_positionB.size, NULL, 0); if (ret != SANE_STATUS_GOOD) { return ret; } wait_scanner (s); DBG (10, "sp15c_object_position: ok\n"); return ret; } /* sp15c_object_position */ static int sp15c_media_check (struct sp15c *s) { static SANE_Status ret; DBG (10, "sp15c_media_check\n"); if (s->use_adf != SANE_TRUE) { return SANE_STATUS_GOOD; } if (s->autofeeder == 0) { DBG (10, "sp15c_media_check: Autofeeder not present.\n"); return SANE_STATUS_UNSUPPORTED; } memset (s->buffer, '\0', 256); /* clear buffer */ set_MC_return_size (media_checkB.cmd, 1); ret = do_scsi_cmd (s->sfd, media_checkB.cmd, media_checkB.size, s->buffer, 1); if (ret != SANE_STATUS_GOOD) { return ret; } wait_scanner (s); if (get_MC_adf_status (s->buffer) == MC_ADF_OK) { DBG (10, "sp15c_media_check: ok\n"); return SANE_STATUS_GOOD; } return SANE_STATUS_NO_DOCS; } /* sp15c_media_check */ static SANE_Status do_cancel (struct sp15c *scanner) { DBG (10, "do_cancel\n"); swap_res (scanner); do_eof (scanner); /* close pipe and reposition scanner */ if (sanei_thread_is_valid (scanner->reader_pid)) { int exit_status; DBG (10, "do_cancel: kill reader_process\n"); /* ensure child knows it's time to stop: */ sanei_thread_kill (scanner->reader_pid); DBG (50, "wait for scanner to stop\n"); sanei_thread_waitpid (scanner->reader_pid, &exit_status); scanner->reader_pid = -1; } if (scanner->sfd >= 0) { sp15c_free_scanner (scanner); DBG (10, "do_cancel: close filedescriptor\n"); sanei_scsi_close (scanner->sfd); scanner->sfd = -1; } return SANE_STATUS_CANCELLED; } /* do_cancel */ static void swap_res (struct sp15c *s) { s = s; /* silence compilation warnings */ /* for the time being, do nothing */ } /* swap_res */ static int sp15c_object_discharge (struct sp15c *s) { int ret; DBG (10, "sp15c_object_discharge\n"); if (s->use_adf != SANE_TRUE) { return SANE_STATUS_GOOD; } memcpy (s->buffer, object_positionB.cmd, object_positionB.size); set_OP_autofeed (s->buffer, OP_Discharge); ret = do_scsi_cmd (s->sfd, s->buffer, object_positionB.size, NULL, 0); wait_scanner (s); DBG (10, "sp15c_object_discharge: ok\n"); return ret; } /* sp15c_object_discharge */ static int sp15c_set_window_param (struct sp15c *s, int prescan) { unsigned char buffer_r[WDB_size_max]; int ret; int active_buffer_size; prescan = prescan; /* silence compilation warnings */ wait_scanner (s); DBG (10, "set_window_param\n"); memset (buffer_r, '\0', WDB_size_max); /* clear buffer */ memcpy (buffer_r, window_descriptor_blockB.cmd, window_descriptor_blockB.size); /* copy preset data */ set_WD_wid (buffer_r, WD_wid_all); /* window identifier */ set_WD_Xres (buffer_r, s->x_res); /* x resolution in dpi */ set_WD_Yres (buffer_r, s->y_res); /* y resolution in dpi */ set_WD_ULX (buffer_r, s->tl_x); /* top left x */ set_WD_ULY (buffer_r, s->tl_y); /* top left y */ set_WD_width (buffer_r, s->br_x - s->tl_x); set_WD_length (buffer_r, s->br_y - s->tl_y); set_WD_brightness (buffer_r, s->brightness); set_WD_threshold (buffer_r, s->threshold); set_WD_contrast (buffer_r, s->contrast); set_WD_bitsperpixel (buffer_r, s->bitsperpixel); set_WD_rif (buffer_r, s->rif); set_WD_pad (buffer_r, 0x3); set_WD_halftone (buffer_r, s->halftone); set_WD_bitorder (buffer_r, s->bitorder); set_WD_compress_type (buffer_r, s->compress_type); set_WD_compress_arg (buffer_r, s->compress_arg); set_WD_composition (buffer_r, s->composition); /* may be overridden below */ set_WD_vendor_id_code (buffer_r, 0xff); set_WD_adf (buffer_r, s->use_adf == SANE_TRUE ? 1 : 0); set_WD_source (buffer_r, 1); set_WD_highlight_color (buffer_r, 0xff); set_WD_shadow_value (buffer_r, 0x00); switch (s->composition) { case WD_comp_LA: case WD_comp_HT: set_WD_line_width (buffer_r, ((s->br_x - s->tl_x) * s->x_res / 1200) / 8); set_WD_line_count (buffer_r, (s->br_y - s->tl_y) * s->y_res / 1200); goto b_and_w; case WD_comp_G4: set_WD_line_width (buffer_r, ((s->br_x - s->tl_x) * s->x_res / 1200) / 2); set_WD_line_count (buffer_r, (s->br_y - s->tl_y) * s->y_res / 1200); goto grayscale; case WD_comp_G8: set_WD_line_width (buffer_r, (s->br_x - s->tl_x) * s->x_res / 1200); set_WD_line_count (buffer_r, (s->br_y - s->tl_y) * s->y_res / 1200); grayscale: set_WD_composition (buffer_r, WD_comp_GS); b_and_w: set_WD_color (buffer_r, WD_color_greenx); break; case WD_comp_MC: set_WD_color (buffer_r, WD_color_rgb); set_WD_line_width (buffer_r, 3 * (s->br_x - s->tl_x) * s->x_res / 1200); set_WD_line_count (buffer_r, (s->br_y - s->tl_y) * s->y_res / 1200); break; case WD_comp_BC: case WD_comp_DC: default: return SANE_STATUS_INVAL; } /* prepare SCSI-BUFFER */ memcpy (s->buffer, set_windowB.cmd, set_windowB.size); memcpy ((s->buffer + set_windowB.size), window_parameter_data_blockB.cmd, window_parameter_data_blockB.size); memcpy ((s->buffer + set_windowB.size + window_parameter_data_blockB.size), buffer_r, window_descriptor_blockB.size); set_SW_xferlen (s->buffer, (window_parameter_data_blockB.size + WDB_size_Color)); set_WDPB_wdblen ((s->buffer + set_windowB.size), WDB_size_Color); set_WD_parm_length ((s->buffer + set_windowB.size + window_parameter_data_blockB.size), 9); DBG (10, "\tx_res=%d, y_res=%d\n", s->x_res, s->y_res); DBG (10, "\tupper left-x=%d, upper left-y=%d\n", s->tl_x, s->tl_y); DBG (10, "\twindow width=%d, length=%d\n", s->br_x - s->tl_x, s->br_y - s->tl_y); active_buffer_size = set_windowB.size + get_SW_xferlen (s->buffer); hexdump (15, "Window set", s->buffer, active_buffer_size); ret = do_scsi_cmd (s->sfd, s->buffer, active_buffer_size, NULL, 0); if (ret) return ret; DBG (10, "set_window_param: ok\n"); return ret; } /* sp15c_set_window_param */ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /* max_string_size */ static int sp15c_start_scan (struct sp15c *s) { int ret; DBG (10, "sp15c_start_scan\n"); ret = do_scsi_cmd (s->sfd, scanB.cmd, scanB.size, NULL, 0); if (ret) return ret; DBG (10, "sp15c_start_scan:ok\n"); return ret; } /* sp15c_start_scan */ static void sigterm_handler (int signal) { signal = signal; /* silence compilation warnings */ sanei_scsi_req_flush_all (); /* flush SCSI queue */ _exit (SANE_STATUS_GOOD); } /* sigterm_handler */ /* This function is executed as a child process. */ static int reader_process (void *data) { struct sp15c *scanner = (struct sp15c *) data; int pipe_fd = scanner->reader_pipe; int status; unsigned int data_left; unsigned int data_to_read; FILE *fp; sigset_t ignore_set; sigset_t sigterm_set; struct SIGACTION act; unsigned int i; unsigned char *src, *dst; DBG (10, "reader_process started\n"); if (sanei_thread_is_forked ()) close (scanner->pipe); sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); #if defined (__APPLE__) && defined (__MACH__) sigdelset (&ignore_set, SIGUSR2); #endif sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); fp = fdopen (pipe_fd, "w"); if (!fp) { DBG (1, "reader_process: couldn't open pipe!\n"); return 1; } DBG (10, "reader_process: starting to READ data\n"); data_left = bytes_per_line (scanner) * lines_per_scan (scanner); sp15c_trim_rowbufsize (scanner); /* trim bufsize */ DBG (10, "reader_process: reading %u bytes in blocks of %u bytes\n", data_left, scanner->row_bufsize); memset (&act, 0, sizeof (act)); act.sa_handler = sigterm_handler; sigaction (SIGTERM, &act, 0); /* wait_scanner(scanner); */ do { data_to_read = (data_left < scanner->row_bufsize) ? data_left : scanner->row_bufsize; if (scanner->composition == WD_comp_G4) { data_to_read /= 2; /* 'cause each byte holds two pixels */ } status = sp15c_read_data_block (scanner, data_to_read); if (status == 0) { DBG (1, "reader_process: no data yet\n"); fflush (stdout); fflush (stderr); usleep (50000); continue; } if (status == -1) { DBG (1, "reader_process: unable to get image data from scanner!\n"); fflush (stdout); fflush (stderr); fclose (fp); return (-1); } /* expand 4-bit pixels to 8-bit bytes */ if (scanner->composition == WD_comp_G4) { src = &scanner->buffer[data_to_read - 1]; dst = &scanner->buffer[data_to_read * 2 - 1]; for (i = 0; i < data_to_read; i++) { *dst-- = ((*src << 4) & 0xf0) + ((*src) & 0x0f); *dst-- = ((*src) & 0xf0) + ((*src >> 4) & 0x0f); --src; } data_to_read *= 2; } fwrite (scanner->buffer, 1, data_to_read, fp); fflush (fp); data_left -= data_to_read; DBG (10, "reader_process: buffer of %d bytes read; %d bytes to go\n", data_to_read, data_left); fflush (stdout); fflush (stderr); } while (data_left); fclose (fp); DBG (10, "reader_process: finished\n"); return 0; } /* reader_process */ static SANE_Status do_eof (struct sp15c *scanner) { DBG (10, "do_eof\n"); scanner->scanning = SANE_FALSE; if (scanner->pipe >= 0) { close (scanner->pipe); scanner->pipe = -1; } return SANE_STATUS_EOF; } /* do_eof */ static int pixels_per_line (struct sp15c *s) { int pixels; pixels = s->x_res * (s->br_x - s->tl_x) / 1200; return pixels; } /* pixels_per_line */ static int lines_per_scan (struct sp15c *s) { int lines; lines = s->y_res * (s->br_y - s->tl_y) / 1200; return lines; } /* lines_per_scan */ static int bytes_per_line (struct sp15c *s) { int bytes; /* SEE PAGE 29 OF SANE SPEC!!! */ if (s->bitsperpixel == 1) { bytes = (pixels_per_line (s) + 7) / 8; } else { bytes = pixels_per_line (s); } if (s->composition == WD_comp_MC) { bytes *= 3; } return bytes; } /* bytes_per_line */ static void sp15c_trim_rowbufsize (struct sp15c *s) { unsigned int row_len; row_len = bytes_per_line (s); if (s->row_bufsize >= row_len) { s->row_bufsize = s->row_bufsize - (s->row_bufsize % row_len); DBG (10, "trim_rowbufsize to %d (%d lines)\n", s->row_bufsize, s->row_bufsize / row_len); } } /* sp15c_trim_rowbufsize */ static int sp15c_read_data_block (struct sp15c *s, unsigned int length) { int r; DBG (10, "sp15c_read_data_block (length = %d)\n", length); /*wait_scanner(s); */ set_R_datatype_code (readB.cmd, R_datatype_imagedata); set_R_xfer_length (readB.cmd, length); r = do_scsi_cmd (s->sfd, readB.cmd, readB.size, s->buffer, length); #if 0 return ((r != 0) ? -1 : length); #else if (r) { return -1; } else { return length; } #endif } /* sp15c_read_data_block */ /* Increase initial width by increasing bottom right X * until we have a HAPPY number of bytes in line. * Should be called whenever s->composition, s->x_res, * s->br_x, or s->tl_x are changed */ static void adjust_width (struct sp15c *s, SANE_Int * info) { int pixels; int changed = 0; if (s->composition == WD_comp_MC) { while (pixels = s->x_res * (s->br_x - s->tl_x) / 1200, (s->bitsperpixel * pixels) % (8 * 4)) { s->br_x--; changed++; } } else { while (pixels = s->x_res * (s->br_x - s->tl_x) / 1200, (s->bitsperpixel * pixels) % 8) { s->br_x--; changed++; } } if (changed && info) *info |= SANE_INFO_INEXACT; return; } /* adjust_width */ static SANE_Status apply_constraints (struct sp15c *scanner, SANE_Int opt, SANE_Int * target, SANE_Word * info) { SANE_Status status; status = sanei_constrain_value (scanner->opt + opt, target, info); if (status != SANE_STATUS_GOOD) { if (SANE_CONSTRAINT_RANGE == scanner->opt[opt].constraint_type) { if (*target < scanner->opt[opt].constraint.range->min) { *target = scanner->opt[opt].constraint.range->min; return SANE_STATUS_GOOD; } else if (scanner->opt[opt].constraint.range->max < *target) { *target = scanner->opt[opt].constraint.range->max; return SANE_STATUS_GOOD; } } return status; } else { return SANE_STATUS_GOOD; } } /* apply_constraints */ /****************************************************************************** }############################################################################# ******************************************************************************/ sane-backends-1.0.27/backend/kvs1025.conf.in0000664000175000017500000000004712112021330015162 00000000000000usb "Panasonic KV-S1025C" /dev/scanner sane-backends-1.0.27/backend/epson2-commands.h0000664000175000017500000000664112112021330015757 00000000000000/* * Prototypes for Epson ESC/I commands * * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for original copyrights. * * Copyright (C) 2006 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ /* simple scanner commands, ESC */ #define esci_set_focus_position(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_focus_position, v) #define esci_set_color_mode(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_color_mode, v) #define esci_set_data_format(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_data_format, v) #define esci_set_halftoning(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_halftoning, v) #define esci_set_gamma(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_gamma, v) #define esci_set_color_correction(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_color_correction, v) #define esci_set_lcount(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_lcount, v) #define esci_set_bright(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_bright, v) #define esci_mirror_image(s,v) e2_esc_cmd( s,(s)->hw->cmd->mirror_image, v) #define esci_set_speed(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_speed, v) #define esci_set_sharpness(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_outline_emphasis, v) #define esci_set_auto_area_segmentation(s,v) e2_esc_cmd( s,(s)->hw->cmd->control_auto_area_segmentation, v) #define esci_set_film_type(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_film_type, v) #define esci_set_exposure_time(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_exposure_time, v) #define esci_set_bay(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_bay, v) #define esci_set_threshold(s,v) e2_esc_cmd( s,(s)->hw->cmd->set_threshold, v) #define esci_control_extension(s,v) e2_esc_cmd( s,(s)->hw->cmd->control_an_extension, v) SANE_Status esci_set_zoom(Epson_Scanner * s, unsigned char x, unsigned char y); SANE_Status esci_set_resolution(Epson_Scanner * s, int x, int y); SANE_Status esci_set_scan_area(Epson_Scanner * s, int x, int y, int width, int height); SANE_Status esci_set_color_correction_coefficients(Epson_Scanner * s, SANE_Word *table); SANE_Status esci_set_gamma_table(Epson_Scanner * s); SANE_Status esci_request_status(SANE_Handle handle, unsigned char *scanner_status); SANE_Status esci_request_extended_identity(SANE_Handle handle, unsigned char *buf); SANE_Status esci_request_scanner_status(SANE_Handle handle, unsigned char *buf); SANE_Status esci_set_scanning_parameter(SANE_Handle handle, unsigned char *buf); SANE_Status esci_get_scanning_parameter(SANE_Handle handle, unsigned char *buf); SANE_Status esci_request_command_parameter(SANE_Handle handle, unsigned char *buf); SANE_Status esci_request_focus_position(SANE_Handle handle, unsigned char *position); SANE_Status esci_request_push_button_status(SANE_Handle handle, unsigned char *bstatus); SANE_Status esci_request_identity(SANE_Handle handle, unsigned char **buf, size_t *len); SANE_Status esci_request_identity2(SANE_Handle handle, unsigned char **buf); SANE_Status esci_reset(Epson_Scanner * s); SANE_Status esci_feed(Epson_Scanner * s); SANE_Status esci_eject(Epson_Scanner * s); SANE_Status esci_request_extended_status(SANE_Handle handle, unsigned char **data, size_t * data_len); SANE_Status esci_enable_infrared(SANE_Handle handle); sane-backends-1.0.27/backend/kvs20xx_cmd.h0000664000175000017500000000572512775312261015151 00000000000000#ifndef __KVS20XX_CMD_H #define __KVS20XX_CMD_H /* Copyright (C) 2008, Panasonic Russia Ltd. Copyright (C) 2010, m. allan noah */ /* Panasonic KV-S20xx USB-SCSI scanners. */ #ifdef HAVE_SYS_TYPES_H #include #endif #define COMMAND_BLOCK 1 #define DATA_BLOCK 2 #define RESPONSE_BLOCK 3 #define COMMAND_CODE 0x9000 #define DATA_CODE 0xb000 #define RESPONSE_CODE 0xa000 #define STATUS_SIZE 4 struct bulk_header { u32 length; u16 type; u16 code; u32 transaction_id; }; #define TEST_UNIT_READY 0x00 #define INQUIRY 0x12 #define SET_WINDOW 0x24 #define SCAN 0x1B #define SEND_10 0x2A #define READ_10 0x28 #define REQUEST_SENSE 0x03 #define GET_BUFFER_STATUS 0x34 #define SET_TIMEOUT 0xE1 #define GET_ADJUST_DATA 0xE0 #define GOOD 0 #define CHECK_CONDITION 2 typedef enum { CMD_NONE = 0, CMD_IN = 0x81, /* scanner to pc */ CMD_OUT = 0x02 /* pc to scanner */ } CMD_DIRECTION; /* equals to endpoint address */ #define RESPONSE_SIZE 0x12 #define MAX_CMD_SIZE 12 struct cmd { unsigned char cmd[MAX_CMD_SIZE]; int cmd_size; void *data; int data_size; int dir; }; struct response { int status; unsigned char data[RESPONSE_SIZE]; }; #define END_OF_MEDIUM (1<<6) #define INCORRECT_LENGTH_INDICATOR (1<<5) static const struct { unsigned sense, asc, ascq; SANE_Status st; } s_errors[] = { { 0, 0, 0, SANE_STATUS_GOOD}, { 2, 0, 0, SANE_STATUS_DEVICE_BUSY}, { 2, 4, 1, SANE_STATUS_DEVICE_BUSY}, { 2, 4, 0x80, SANE_STATUS_COVER_OPEN}, { 2, 4, 0x81, SANE_STATUS_COVER_OPEN}, { 2, 4, 0x82, SANE_STATUS_COVER_OPEN}, { 2, 4, 0x83, SANE_STATUS_COVER_OPEN}, { 2, 4, 0x84, SANE_STATUS_COVER_OPEN}, { 2, 0x80, 1, SANE_STATUS_CANCELLED}, { 2, 0x80, 2, SANE_STATUS_CANCELLED}, { 3, 0x3a, 0, SANE_STATUS_NO_DOCS}, { 3, 0x80, 1, SANE_STATUS_JAMMED}, { 3, 0x80, 2, SANE_STATUS_JAMMED}, { 3, 0x80, 3, SANE_STATUS_JAMMED}, { 3, 0x80, 4, SANE_STATUS_JAMMED}, { 3, 0x80, 5, SANE_STATUS_JAMMED}, { 3, 0x80, 6, SANE_STATUS_JAMMED}, { 3, 0x80, 7, SANE_STATUS_JAMMED}, { 3, 0x80, 8, SANE_STATUS_JAMMED}, { 3, 0x80, 9, SANE_STATUS_JAMMED},}; SANE_Status kvs20xx_scan (struct scanner *s); SANE_Status kvs20xx_test_unit_ready (struct scanner *s); SANE_Status kvs20xx_set_timeout (struct scanner *s, int timeout); SANE_Status kvs20xx_set_window (struct scanner *s, int wnd_id); SANE_Status kvs20xx_reset_window (struct scanner *s); SANE_Status kvs20xx_read_picture_element (struct scanner *s, unsigned side, SANE_Parameters * p); SANE_Status kvs20xx_read_image_data (struct scanner *s, unsigned page, unsigned side, void *buf, unsigned max_size, unsigned *size); SANE_Status kvs20xx_document_exist (struct scanner *s); SANE_Status get_adjust_data (struct scanner *s, unsigned *dummy_length); SANE_Status kvs20xx_sense_handler (int fd, u_char * sense_buffer, void *arg); #endif /*__KVS20XX_CMD_H*/ sane-backends-1.0.27/backend/st400.c0000664000175000017500000011250112112021330013610 00000000000000/* vim: ts=4 sw=4 noexpandtab */ /* st400.c - SANE module for Siemens ST400 flatbed scanner Copyright (C) 1999-2000 Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. ************************************************************************* This file implements a SANE backend for the Siemens ST400 flatbed scanner. Unfortunately, I have no documentation for this scanner. All I have is an old PC Pascal source and an Amiga C source (derived from the Pascal source). Both are quite primitive, and so is this backend... Version numbers of this backend follow SANE version scheme: The first number is SANE's major version (i.e. the version of the SANE API that this backend conforms to), the second is the version of this backend. Thus, version 1.2 is the second release of this backend for SANE v1. 1.0 (08 Mar 1999): First public release, for SANE v1.0.0 1.1 (12 Mar 1999): Fixed some stupid bugs (caused crash if accessed via net). 1.2 (23 Apr 1999): Oops, got threshold backwards. Tested with SANE 1.0.1. 1.3 (27 Apr 1999): Seems the separate MODE SELECT to switch the light on is not necessary. Removed debugging output via syslog, it was only used to track down a bug in saned. Some minor cleanups. Removed illegal version check (only frontends should do this). Made "maxread" and "delay" config options instead of compile-time #define's. Added model check via INQUIRY, and related changes. 1.4 (29 Jun 1999): New config options to configure scanner models. See st400.conf for details. These options are only for testing, and will be removed someday. 1.5 (26 Mar 2000): Check for optnum >= 0. Fixed some hardcoded paths in manpage. ST400 locks up with reads >64KB - added maxread entry to model struct. Tested with SANE 1.0.2. 1.6 (08 Apr 2000): Minor cleanups. 1.7 (18 Dec 2001): Security fix from Tim Waugh. Dump inquiry data to "$HOME/st400.dump" instead of "/tmp/st400.dump". */ #include "../include/sane/config.h" #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define BACKEND_NAME st400 #include "../include/sane/sanei_backend.h" #include "st400.h" /* supported scanners */ static ST400_Model st400_models[] = { { 8, "SIEMENS", 16, "ST 400", 6, 0x200000UL, 65536UL, NULL, "Siemens", "ST400", "flatbed scanner" }, { 8, "SIEMENS", 16, "ST 800", 6, 0x200000UL, 65536UL, NULL, "Siemens", "ST800", "flatbed scanner" }, /* to be tested */ { 0, "", 0, "", 6, 0x200000UL, 65536UL, NULL, "Unknown", "untested", "flatbed scanner" }, /* matches anything */ /* must be last */ { 0, NULL, 0, NULL, 0, 0, 0, NULL, NULL, NULL, NULL } }; static ST400_Device *st400_devices = NULL; static unsigned int st400_num_devices = 0; static const SANE_Device **st400_device_array = NULL; /* The array pointer must stay valid between calls to sane_get_devices(). * So we cannot modify or deallocate the array when a new device is attached * - until the next call to sane_get_devices(). The array_valid bit indicates * whether the array is still in sync with the device list or not (if new * devices have been attached in the meantime). */ static struct { unsigned array_valid: 1; } st400_status = { 0 }; static size_t st400_maxread = 0; static size_t st400_light_delay = 0; static int st400_dump_data = 0; /* SCSI commands */ #define CMD_TEST_UNIT_READY 0x00 #define CMD_INQUIRY 0x12 #define CMD_MODE_SELECT 0x15 #define CMD_RESERVE 0x16 #define CMD_RELEASE 0x17 #define CMD_START_STOP 0x1b #define CMD_SET_WINDOW 0x24 #define CMD_READ_CAPACITY 0x25 /* get window settings - unused */ #define CMD_READ10 0x28 /* prototypes */ static SANE_Status st400_inquiry( int fd, ST400_Model **modelP ); static SANE_Status st400_sense_handler( int fd, SANE_Byte *result, void *arg ); static SANE_Status st400_attach( const char *devname, ST400_Device **devP ); static SANE_Status st400_attach_one( const char *device ); static void st400_init_options( ST400_Device *dev ); static SANE_Status st400_set_window( ST400_Device *dev ); static SANE_Status st400_wait_ready( int fd ); static SANE_Status st400_cmd6( int fd, SANE_Byte cmd, SANE_Byte ctrl ); static SANE_Status st400_read10( int fd, SANE_Byte *buf, size_t *lenP ); static void st400_reset_options( ST400_Device *dev ); #undef min #define min(a, b) ((a) < (b) ? (a) : (b)) #define maxval(bpp) ((1<<(bpp))-1) /* Debugging levels */ #define DERR 0 /* errors */ #define DINFO 1 /* misc information */ #define DSENSE 2 /* SCSI sense */ #define DSCSI 3 /* SCSI commands */ #define DOPT 4 /* option control */ #define DVAR 5 /* important variables */ #define DCODE 6 /* code flow */ /********************************************************************* * low-level SCSI functions *********************************************************************/ #define set24(m, x) do { \ *((SANE_Byte *)(m)+0) = (SANE_Byte)(((x) >> 16) & 0xff); \ *((SANE_Byte *)(m)+1) = (SANE_Byte)(((x) >> 8) & 0xff); \ *((SANE_Byte *)(m)+2) = (SANE_Byte)(((x) >> 0) & 0xff); \ } while(0) #define set16(m, x) do { \ *((SANE_Byte *)(m)+0) = (SANE_Byte)(((x) >> 8) & 0xff); \ *((SANE_Byte *)(m)+1) = (SANE_Byte)(((x) >> 0) & 0xff); \ } while(0) static int str_at_offset(char *str, size_t offset, unsigned char *data) { size_t len; len = strlen(str); return !strncmp((char *)&data[offset], str, len); } static SANE_Status st400_inquiry( int fd, ST400_Model **modelP ) { struct { SANE_Byte cmd, lun, reserved[2], tr_len, ctrl; } scsi_cmd; /* struct { SANE_Byte devtype, devqual, version; SANE_Byte reserved1, additionallength; SANE_Byte reserved2[2], flags; SANE_Byte vendor[8], product[16], release[4]; SANE_Byte reserved3[60]; } inqdata; */ struct { SANE_Byte bytes[96]; } inqdata; size_t inqlen; SANE_Status status; ST400_Model *model; inqlen = sizeof(inqdata); memset(&scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd.cmd = CMD_INQUIRY; scsi_cmd.tr_len = inqlen; DBG(DSCSI, "SCSI: sending INQUIRY (%lu bytes)\n", (u_long)inqlen); status = sanei_scsi_cmd(fd, &scsi_cmd, sizeof(scsi_cmd), &inqdata, &inqlen); DBG(DSCSI, "SCSI: result=%s (%lu bytes)\n", sane_strstatus(status), (u_long)inqlen); if( status != SANE_STATUS_GOOD ) return status; if( st400_dump_data ) { const char *home = getenv ("HOME"); char basename[] = "st400.dump"; char *name; FILE *fp; if (home) { name = malloc (strlen (home) + sizeof (basename) + 1); sprintf (name, "%s/%s", home, basename); } else name = basename; fp = fopen(name, "ab"); if( fp != NULL ) { fwrite(inqdata.bytes, 1, inqlen, fp); fclose(fp); } if (name != basename) free (name); } if( inqlen != sizeof(inqdata) ) return SANE_STATUS_IO_ERROR; for( model = st400_models; model->inq_vendor; model++ ) { if( str_at_offset(model->inq_vendor, model->inq_voffset, inqdata.bytes) && str_at_offset(model->inq_model, model->inq_moffset, inqdata.bytes) ) { *modelP = model; DBG(DINFO, "found matching scanner model \"%s %s\" in list\n", model->sane_vendor, model->sane_model); return SANE_STATUS_GOOD; } } return SANE_STATUS_UNSUPPORTED; } static SANE_Status st400_cmd6( int fd, SANE_Byte cmd, SANE_Byte ctrl ) { struct { SANE_Byte cmd, lun, reserved[2], tr_len, ctrl; } scsi_cmd; SANE_Status status; memset(&scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd.cmd = cmd; scsi_cmd.ctrl = ctrl; DBG(DSCSI, "SCSI: sending cmd6 0x%02x (ctrl=%d)\n", (int)cmd, (int)ctrl); status = sanei_scsi_cmd(fd, &scsi_cmd, sizeof(scsi_cmd), 0, 0); DBG(DSCSI, "SCSI: result=%s\n", sane_strstatus(status)); return status; } #define st400_test_ready(fd) st400_cmd6(fd, CMD_TEST_UNIT_READY, 0) #define st400_reserve(fd) st400_cmd6(fd, CMD_RESERVE, 0) #define st400_release(fd) st400_cmd6(fd, CMD_RELEASE, 0) #define st400_start_scan(fd) st400_cmd6(fd, CMD_START_STOP, 0) #define st400_light_on(fd) st400_cmd6(fd, CMD_MODE_SELECT, 0x80) #define st400_light_off(fd) st400_cmd6(fd, CMD_MODE_SELECT, 0) static SANE_Status st400_wait_ready( int fd ) { #define SLEEPTIME 100000L /* 100ms */ long max_sleep = 60000000L; /* 60 seconds */ SANE_Status status; DBG(DCODE, "st400_wait_ready(%d)\n", fd); while(1) { status = st400_test_ready(fd); switch( status ) { case SANE_STATUS_DEVICE_BUSY: if( max_sleep > 0 ) { usleep(SLEEPTIME); /* retry after 100ms */ max_sleep -= SLEEPTIME; break; } /* else fall through */ default: DBG(DERR, "st400_wait_ready: failed, error=%s\n", sane_strstatus(status)); /* fall through */ case SANE_STATUS_GOOD: return status; } } /*NOTREACHED*/ } static SANE_Status st400_set_window( ST400_Device *dev ) { unsigned short xoff, yoff; SANE_Byte th; struct { /* 10byte command */ SANE_Byte cmd, lun, reserved1[4], tr_len[3], ctrl; /* 40byte window struct */ SANE_Byte reserved2[6], wd_len[2], winnr, reserved3; SANE_Byte x_res[2], y_res[2]; /* resolution: 200, 300, 400 */ SANE_Byte x_ul[2], y_ul[2]; /* upper left corner */ SANE_Byte width[2], height[2]; SANE_Byte reserved4, threshold; SANE_Byte reserved5, halftone; /* ht: 0 or 2 */ SANE_Byte bitsperpixel, reserved6[13]; /* bpp: 1 or 8 */ } scsi_cmd; /* The PC/Amiga source uses reserved5 to indicate A4/A5 paper size * (values 4 and 5), but a comment implies that this is only for the * scanning program and the value is ignored by the scanner. */ SANE_Status status; memset(&scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd.cmd = CMD_SET_WINDOW; set24(scsi_cmd.tr_len, 40); set16(scsi_cmd.wd_len, 32); /* These offsets seem to be required to avoid damaging the scanner: * If a scan with 0/0 as the top left corner is started, the scanner * seems to try to move the carriage over the bottom end (not a * pretty sound). */ xoff = (11L * dev->val[OPT_RESOLUTION]) / 100; yoff = 6; th = (double)maxval(dev->model->bits) * SANE_UNFIX(dev->val[OPT_THRESHOLD]) / 100.0; scsi_cmd.winnr = 1; set16(scsi_cmd.x_res, (unsigned short)dev->val[OPT_RESOLUTION]); set16(scsi_cmd.y_res, (unsigned short)dev->val[OPT_RESOLUTION]); set16(scsi_cmd.x_ul, dev->x + xoff); set16(scsi_cmd.y_ul, dev->wy + yoff); set16(scsi_cmd.width, dev->w); set16(scsi_cmd.height, dev->wh); scsi_cmd.threshold = th; scsi_cmd.halftone = (dev->val[OPT_DEPTH] == 1) ? 0 : 2; scsi_cmd.bitsperpixel = dev->val[OPT_DEPTH]; DBG(DSCSI, "SCSI: sending SET_WINDOW (x=%hu y=%hu w=%hu h=%hu wy=%hu wh=%hu th=%d\n", dev->x, dev->y, dev->w, dev->h, dev->wy, dev->wh, (int)th); status = sanei_scsi_cmd(dev->fd, &scsi_cmd, sizeof(scsi_cmd), 0, 0); DBG(DSCSI, "SCSI: result=%s\n", sane_strstatus(status)); return status; } static SANE_Status st400_read10( int fd, SANE_Byte *buf, size_t *lenP ) { struct { SANE_Byte cmd, lun, res[4], tr_len[3], ctrl; } scsi_cmd; SANE_Status status; memset(&scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd.cmd = CMD_READ10; set24(scsi_cmd.tr_len, *lenP); DBG(DSCSI, "SCSI: sending READ10 (%lu bytes)\n", (u_long)(*lenP)); status = sanei_scsi_cmd(fd, &scsi_cmd, sizeof(scsi_cmd), buf, lenP); DBG(DSCSI, "SCSI: result=%s (%lu bytes)\n", sane_strstatus(status), (u_long)(*lenP)); return status; } static SANE_Status st400_fill_scanner_buffer( ST400_Device *dev ) { SANE_Status status; DBG(DCODE, "st400_fill_scanner_buffer(%p)\n", (void *) dev); if( dev->lines_to_read == 0 ) dev->status.eof = 1; if( dev->status.eof ) return SANE_STATUS_EOF; dev->wh = dev->model->bufsize / dev->params.bytes_per_line; if( dev->wh > dev->lines_to_read ) dev->wh = dev->lines_to_read; DBG(DVAR, "dev->wh = %hu\n", dev->wh); status = st400_set_window(dev); if( status != SANE_STATUS_GOOD ) return status; status = st400_start_scan(dev->fd); if( status != SANE_STATUS_GOOD ) return status; dev->wy += dev->wh; dev->lines_to_read -= dev->wh; dev->bytes_in_scanner = dev->wh * dev->params.bytes_per_line; return SANE_STATUS_GOOD; } static SANE_Status st400_fill_backend_buffer( ST400_Device *dev ) { size_t r; SANE_Status status; DBG(DCODE, "st400_fill_backend_buffer(%p)\n", (void *) dev); if( dev->bytes_in_scanner == 0 ) { status = st400_fill_scanner_buffer(dev); if( status != SANE_STATUS_GOOD ) return status; } r = min(dev->bufsize, dev->bytes_in_scanner); status = st400_read10(dev->fd, dev->buffer, &r); if( status == SANE_STATUS_GOOD ) { dev->bufp = dev->buffer; dev->bytes_in_buffer = r; dev->bytes_in_scanner -= r; if( r == 0 ) dev->status.eof = 1; } return status; } static SANE_Status st400_sense_handler( int fd, SANE_Byte *result, void *arg ) { /* ST400_Device *dev = arg; */ SANE_Status status; fd = fd; arg = arg; /* silence compilation warnings */ switch( result[0] & 0x0f ) { case 0x0: status = SANE_STATUS_GOOD; break; case 0x1: DBG(DSENSE, "SCSI: sense RECOVERED_ERROR\n"); status = SANE_STATUS_GOOD; /* ?? */ break; case 0x2: DBG(DSENSE, "SCSI: sense NOT_READY\n"); status = SANE_STATUS_DEVICE_BUSY; break; case 0x4: DBG(DSENSE, "SCSI: sense HARDWARE_ERROR\n"); status = SANE_STATUS_IO_ERROR; break; case 0x5: DBG(DSENSE, "SCSI: sense ILLEGAL_REQUEST\n"); status = SANE_STATUS_IO_ERROR; break; case 0x6: DBG(DSENSE, "SCSI: sense UNIT_ATTENTION\n"); status = SANE_STATUS_DEVICE_BUSY; break; case 0xb: DBG(DSENSE, "SCSI: sense ABORTED_COMMAND\n"); status = SANE_STATUS_CANCELLED; /* ?? */ break; default: DBG(DSENSE, "SCSI: sense unknown (%d)\n", result[0] & 0x0f); status = SANE_STATUS_IO_ERROR; break; } return status; } /********************************************************************* * Sane initializing stuff *********************************************************************/ static SANE_Status st400_attach( const char *devname, ST400_Device **devP ) { ST400_Device *dev; ST400_Model *model; SANE_Status status; int fd; DBG(DCODE, "st400_attach(%s, %p)\n", devname, (void *) devP); if( devP ) *devP = NULL; for( dev = st400_devices; dev != NULL; dev = dev->next ) { if( strcmp(dev->sane.name, devname) == 0 ) { if( devP ) *devP = dev; DBG(DCODE, "st400_attach: found device in list\n"); return SANE_STATUS_GOOD; } } dev = calloc(1, sizeof(*dev)); if( !dev ) return SANE_STATUS_NO_MEM; DBG(DCODE, "st400_attach: new device struct at %p\n", (void *) dev); status = sanei_scsi_open(devname, &fd, st400_sense_handler, dev); if( status == SANE_STATUS_GOOD ) { status = st400_inquiry(fd, &model); if( status == SANE_STATUS_GOOD ) status = st400_test_ready(fd); sanei_scsi_close(fd); } if( status != SANE_STATUS_GOOD ) { free(dev); return status; } /* initialize device structure */ dev->sane.name = strdup(devname); if( !dev->sane.name ) { free(dev); return SANE_STATUS_NO_MEM; } dev->sane.vendor = model->sane_vendor; dev->sane.model = model->sane_model; dev->sane.type = model->sane_type; dev->status.open = 0; dev->status.scanning = 0; dev->status.eof = 0; dev->fd = -1; dev->buffer = NULL; dev->model = model; st400_init_options(dev); DBG(DCODE, "st400_attach: everything ok, adding device to list\n"); dev->next = st400_devices; st400_devices = dev; ++st400_num_devices; st400_status.array_valid = 0; if( devP ) *devP = dev; return SANE_STATUS_GOOD; } static SANE_Status st400_attach_one( const char *device ) { DBG(DCODE, "st400_attach_one(%s)\n", device); return st400_attach(device, NULL); } static SANE_Status st400_config_get_arg(char **optP, unsigned long *argP, size_t linenum) { int n; linenum = linenum; /* silence compilation warnings */ if( sscanf(*optP, "%lu%n", argP, &n) == 1 ) { *optP += n; *optP = (char *)sanei_config_skip_whitespace(*optP); return SANE_STATUS_GOOD; } return SANE_STATUS_INVAL; } static SANE_Status st400_config_get_single_arg(char *opt, unsigned long *argP, size_t linenum) { int n; if( sscanf(opt, "%lu%n", argP, &n) == 1 ) { opt += n; opt = (char *)sanei_config_skip_whitespace(opt); if( *opt == '\0' ) return SANE_STATUS_GOOD; else { DBG(DERR, "extraneous arguments at line %lu: %s\n", (u_long)linenum, opt); return SANE_STATUS_INVAL; } } DBG(DERR, "invalid option argument at line %lu: %s\n", (u_long)linenum, opt); return SANE_STATUS_INVAL; } static SANE_Status st400_config_do_option(char *opt, size_t linenum) { unsigned long arg; SANE_Status status; int i; status = SANE_STATUS_GOOD; opt = (char *)sanei_config_skip_whitespace(opt); if( strncmp(opt, "maxread", 7) == 0 && isspace(opt[7]) ) { opt += 8; status = st400_config_get_single_arg(opt, &arg, linenum); if( status == SANE_STATUS_GOOD ) { if( arg == 0 ) st400_maxread = sanei_scsi_max_request_size; else st400_maxread = (size_t)arg; } } else if( strncmp(opt, "delay", 5) == 0 && isspace(opt[5]) ) { opt += 6; status = st400_config_get_single_arg(opt, &arg, linenum); if( status == SANE_STATUS_GOOD ) st400_light_delay = (size_t)arg; } else if( strncmp(opt, "scanner_bufsize", 15) == 0 && isspace(opt[15]) ) { opt += 16; status = st400_config_get_single_arg(opt, &arg, linenum); if( status == SANE_STATUS_GOOD ) if( st400_devices ) st400_devices->model->bufsize = arg; /* FIXME: changes bufsize for all scanners of this model! */ } else if( strncmp(opt, "scanner_bits", 12) == 0 && isspace(opt[12]) ) { opt += 13; status = st400_config_get_single_arg(opt, &arg, linenum); if( status == SANE_STATUS_GOOD ) if( st400_devices ) st400_devices->model->bits = arg; /* FIXME */ } else if( strncmp(opt, "scanner_maxread", 15) == 0 && isspace(opt[15]) ) { opt += 16; status = st400_config_get_single_arg(opt, &arg, linenum); if( status == SANE_STATUS_GOOD ) if( st400_devices ) st400_devices->model->maxread = arg; /* FIXME */ } else if( strncmp(opt, "scanner_resolutions", 19) == 0 && isspace(opt[19]) ) { opt += 20; st400_devices->model->dpi_list = malloc(16 * sizeof(SANE_Int)); i = 0; do { status = st400_config_get_arg(&opt, &arg, linenum); if( status == SANE_STATUS_GOOD ) { ++i; st400_devices->model->dpi_list[i] = (SANE_Int)arg; } } while( status == SANE_STATUS_GOOD && i < 15 ); st400_devices->model->dpi_list[0] = i; DBG(DINFO, "%d entries for resolution\n", i); status = SANE_STATUS_GOOD; } else if( strncmp(opt, "dump_inquiry", 12) == 0 ) { st400_dump_data = 1; } if( st400_devices ) st400_reset_options(st400_devices); return status; } SANE_Status sane_init( SANE_Int *versionP, SANE_Auth_Callback authorize ) { FILE *fp; SANE_Status status; DBG_INIT(); DBG(DCODE, "sane_init: version %s null, authorize %s null\n", (versionP) ? "!=" : "==", (authorize) ? "!=" : "=="); if( versionP != NULL ) *versionP = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, 0); status = SANE_STATUS_GOOD; if( (fp = sanei_config_open(ST400_CONFIG_FILE)) != NULL ) { char line[PATH_MAX], *str; size_t len, linenum; linenum = 0; DBG(DCODE, "sane_init: reading config file\n"); while( sanei_config_read(line, sizeof(line), fp) ) { ++linenum; str = line; if( str[0] == '#' ) continue; /* ignore comments */ str = (char *)sanei_config_skip_whitespace(str); len = strlen(str); if( !len ) continue; /* ignore empty lines */ if( strncmp(str, "option", 6) == 0 && isspace(str[6]) ) { DBG(DCODE, "sane_init: config line <%s>\n", line); status = st400_config_do_option(str+7, linenum); } else { DBG(DCODE, "sane_init: attaching device <%s>\n", line); sanei_config_attach_matching_devices(line, st400_attach_one); } if( status != SANE_STATUS_GOOD ) break; } DBG(DCODE, "sane_init: closing config file\n"); fclose(fp); } if( status == SANE_STATUS_GOOD && st400_devices == NULL ) { DBG(DCODE, "sane_init: attaching default device <%s>\n", ST400_DEFAULT_DEVICE); sanei_config_attach_matching_devices(ST400_DEFAULT_DEVICE, st400_attach_one); } return status; } void sane_exit( void ) { ST400_Device *dev; DBG(DCODE, "sane_exit()\n"); while( (dev = st400_devices) != NULL ) { st400_devices = dev->next; sane_close(dev); free((char *)(dev->sane.name)); free(dev); } st400_num_devices = 0; if( st400_device_array ) { DBG(DCODE, "sane_exit: freeing device array\n"); free(st400_device_array); st400_device_array = NULL; st400_status.array_valid = 0; } } SANE_Status sane_get_devices( const SANE_Device ***devarrayP, SANE_Bool local_only ) { ST400_Device *dev; unsigned int i; DBG(DCODE, "sane_get_devices(%p, %d)\n", (void *) devarrayP, (int)local_only); if( !st400_status.array_valid ) { if( st400_device_array ) { DBG(DCODE, "sane_get_devices: freeing old device array\n"); free(st400_device_array); } st400_device_array = malloc((st400_num_devices + 1) * sizeof(*st400_device_array)); if( !st400_device_array ) return SANE_STATUS_NO_MEM; DBG(DCODE, "sane_get_devices: new device array at %p\n", (void *) st400_device_array); dev = st400_devices; for( i = 0; i < st400_num_devices; i++ ) { st400_device_array[i] = &dev->sane; dev = dev->next; } st400_device_array[st400_num_devices] = NULL; st400_status.array_valid = 1; } DBG(DCODE, "sane_get_devices: %u entries in device array\n", st400_num_devices); if( devarrayP ) *devarrayP = st400_device_array; return SANE_STATUS_GOOD; } SANE_Status sane_open( SANE_String_Const devicename, SANE_Handle *handleP ) { ST400_Device *dev; SANE_Status status; DBG(DCODE, "sane_open(%s, %p)\n", devicename, (void *) handleP); *handleP = NULL; if( devicename && devicename[0] ) { status = st400_attach(devicename, &dev); if( status != SANE_STATUS_GOOD ) return status; } else dev = st400_devices; if( !dev ) return SANE_STATUS_INVAL; if( dev->status.open ) return SANE_STATUS_DEVICE_BUSY; dev->status.open = 1; st400_reset_options(dev); *handleP = (SANE_Handle)dev; return SANE_STATUS_GOOD; } void sane_close( SANE_Handle handle ) { ST400_Device *dev = handle; DBG(DCODE, "sane_close(%p)\n", handle); if( dev->status.open ) { sane_cancel(dev); dev->status.open = 0; } } /* * options */ static void st400_reset_options( ST400_Device *dev ) { DBG(DCODE, "st400_reset_options(%p)\n", (void *) dev); dev->val[OPT_NUM_OPTS] = NUM_OPTIONS; dev->val[OPT_RESOLUTION] = dev->opt[OPT_RESOLUTION].constraint.word_list[1]; dev->val[OPT_DEPTH] = dev->opt[OPT_DEPTH].constraint.word_list[1]; dev->val[OPT_THRESHOLD] = SANE_FIX(50.0); dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; dev->val[OPT_TL_X] = SANE_FIX(0.0); dev->val[OPT_TL_Y] = SANE_FIX(0.0); dev->val[OPT_BR_X] = SANE_FIX(0.0); dev->val[OPT_BR_Y] = SANE_FIX(0.0); if( dev->model->dpi_list ) dev->opt[OPT_RESOLUTION].constraint.word_list = dev->model->dpi_list; } static void st400_init_options( ST400_Device *dev ) { static const SANE_Int depth_list[] = { 2, 1, 8 }; static const SANE_Int dpi_list[] = { 3, 200, 300, 400 }; static const SANE_Range thres_range = { SANE_FIX(0.0), SANE_FIX(100.0), SANE_FIX(0.0) }; static const SANE_Range x_range = { SANE_FIX(0.0), SANE_FIX(ST400_MAX_X * MM_PER_INCH), SANE_FIX(0.0) }; static const SANE_Range y_range = { SANE_FIX(0.0), SANE_FIX(ST400_MAX_Y * MM_PER_INCH), SANE_FIX(0.0) }; DBG(DCODE, "st400_init_options(%p)\n", (void *)dev); dev->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; dev->opt[OPT_NUM_OPTS].size = sizeof(SANE_Word); dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; dev->opt[OPT_MODE_GROUP].title= "Scan Mode"; dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title= SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].size = sizeof(SANE_Word); dev->opt[OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; dev->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH; dev->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH; dev->opt[OPT_DEPTH].desc = SANE_DESC_BIT_DEPTH; dev->opt[OPT_DEPTH].type = SANE_TYPE_INT; dev->opt[OPT_DEPTH].unit = SANE_UNIT_BIT; dev->opt[OPT_DEPTH].size = sizeof(SANE_Word); dev->opt[OPT_DEPTH].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_DEPTH].constraint.word_list = depth_list; dev->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; dev->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; dev->opt[OPT_THRESHOLD].size = sizeof(SANE_Word); dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_THRESHOLD].constraint.range = &thres_range; dev->opt[OPT_GEOMETRY_GROUP].title= "Geometry"; dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].size = sizeof(SANE_Word); dev->opt[OPT_TL_X].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &x_range; dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].size = sizeof(SANE_Word); dev->opt[OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &y_range; dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].size = sizeof(SANE_Word); dev->opt[OPT_BR_X].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &x_range; dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].size = sizeof(SANE_Word); dev->opt[OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &y_range; st400_reset_options(dev); } const SANE_Option_Descriptor * sane_get_option_descriptor( SANE_Handle handle, SANE_Int optnum ) { ST400_Device *dev = handle; DBG(DOPT, "sane_get_option_descriptor(%p, %d)\n", handle, (int)optnum); if( dev->status.open && optnum >= 0 && optnum < NUM_OPTIONS ) return &dev->opt[optnum]; return NULL; } SANE_Status sane_control_option( SANE_Handle handle, SANE_Int optnum, SANE_Action action, void *valP, SANE_Int *infoP) { ST400_Device *dev = handle; SANE_Status status; DBG(DCODE, "sane_control_option(%p, %d, %d, %p, %p)\n", (void *) handle, (int)optnum, (int)action, valP, (void *) infoP); if( infoP ) *infoP = 0; if( !dev->status.open ) return SANE_STATUS_INVAL; if( dev->status.scanning ) return SANE_STATUS_DEVICE_BUSY; if( optnum < 0 || optnum >= NUM_OPTIONS ) return SANE_STATUS_INVAL; switch( action ) { case SANE_ACTION_GET_VALUE: DBG(DOPT, "getting option %d (value=%d)\n", (int)optnum, (int)dev->val[optnum]); switch( optnum ) { case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_DEPTH: case OPT_THRESHOLD: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *)valP = dev->val[optnum]; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: if( !SANE_OPTION_IS_SETTABLE(dev->opt[optnum].cap) ) return SANE_STATUS_INVAL; status = sanei_constrain_value(&dev->opt[optnum], valP, infoP); if( status != SANE_STATUS_GOOD ) return status; DBG(DOPT, "setting option %d to %d\n", (int)optnum, (int)*(SANE_Word *)valP); switch( optnum ) { case OPT_DEPTH: if( *(SANE_Word *)valP != 1 ) dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; else dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; if( infoP ) *infoP |= SANE_INFO_RELOAD_OPTIONS; /* fall through */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if( infoP ) *infoP |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_THRESHOLD: dev->val[optnum] = *(SANE_Word *)valP; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_AUTO: DBG(DOPT, "automatic option setting\n"); return SANE_STATUS_UNSUPPORTED; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters( SANE_Handle handle, SANE_Parameters *paramsP ) { ST400_Device *dev = handle; DBG(DCODE, "sane_get_parameters(%p, %p)\n", handle, (void *) paramsP); if( !dev->status.open ) return SANE_STATUS_INVAL; if( !dev->status.scanning ) { double width, height, dpi; dev->params.format = SANE_FRAME_GRAY; dev->params.last_frame = SANE_TRUE; dev->params.lines = 0; dev->params.depth = dev->val[OPT_DEPTH]; width = SANE_UNFIX(dev->val[OPT_BR_X] - dev->val[OPT_TL_X]); height = SANE_UNFIX(dev->val[OPT_BR_Y] - dev->val[OPT_TL_Y]); dpi = dev->val[OPT_RESOLUTION]; /* make best-effort guess at what parameters will look like once scanning starts. */ if( dpi > 0.0 && width > 0.0 && height > 0.0 ) { double dots_per_mm = dpi / MM_PER_INCH; dev->params.pixels_per_line = width * dots_per_mm + 0.5; dev->params.lines = height * dots_per_mm + 0.5; if( dev->params.depth == 1 ) { /* Pad to an even multiple of 8. This way we can simply * copy the bytes from the scanner to the SANE buffer * (only need to invert them). */ dev->params.pixels_per_line += 7; dev->params.pixels_per_line &= ~7; /*dev->params.bytes_per_line = (dev->params.pixels_per_line + 7)/8;*/ dev->params.bytes_per_line = dev->params.pixels_per_line/8; } else dev->params.bytes_per_line = dev->params.pixels_per_line; dev->x = SANE_UNFIX(dev->val[OPT_TL_X]) * dots_per_mm + 0.5; dev->y = SANE_UNFIX(dev->val[OPT_TL_Y]) * dots_per_mm + 0.5; dev->w = dev->params.pixels_per_line; dev->h = dev->params.lines; DBG(DVAR, "parameters: bpl=%d, x=%hu, y=%hu, w=%hu, h=%hu\n", (int)dev->params.bytes_per_line, dev->x, dev->y, dev->w, dev->h); } } if( paramsP ) *paramsP = dev->params; return SANE_STATUS_GOOD; } SANE_Status sane_start( SANE_Handle handle ) { ST400_Device *dev = handle; SANE_Status status; DBG(DCODE, "sane_start(%p)\n", handle); if( !dev->status.open ) return SANE_STATUS_INVAL; if( dev->status.scanning ) return SANE_STATUS_DEVICE_BUSY; status = sane_get_parameters(dev, NULL); if( status != SANE_STATUS_GOOD ) return status; if( !dev->buffer ) { if( st400_maxread > 0 ) dev->bufsize = min(st400_maxread, (unsigned int) sanei_scsi_max_request_size); else if( dev->model->maxread > 0 ) dev->bufsize = min(dev->model->maxread, (unsigned int) sanei_scsi_max_request_size); else dev->bufsize = sanei_scsi_max_request_size; DBG(DVAR, "allocating %lu bytes buffer\n", (u_long)dev->bufsize); dev->buffer = malloc(dev->bufsize); if( !dev->buffer ) return SANE_STATUS_NO_MEM; } dev->bufp = dev->buffer; dev->bytes_in_buffer = 0; if( dev->fd < 0 ) { status = sanei_scsi_open(dev->sane.name, &dev->fd, st400_sense_handler, dev); if( status != SANE_STATUS_GOOD ) goto return_error; } dev->status.eof = 0; status = st400_wait_ready(dev->fd); if( status != SANE_STATUS_GOOD ) goto close_and_return; status = st400_reserve(dev->fd); if( status != SANE_STATUS_GOOD ) goto close_and_return; if( st400_light_delay > 0 ) { status = st400_light_on(dev->fd); if( status != SANE_STATUS_GOOD ) goto release_and_return; usleep(st400_light_delay * 100000); /* 1/10 seconds */ } dev->wy = dev->y; dev->lines_to_read = dev->h; dev->bytes_in_scanner = 0; status = st400_fill_scanner_buffer(dev); if( status != SANE_STATUS_GOOD ) goto lightoff_and_return; /* everything ok */ dev->status.scanning = 1; return SANE_STATUS_GOOD; lightoff_and_return: if( st400_light_delay ) st400_light_off(dev->fd); release_and_return: st400_release(dev->fd); close_and_return: sanei_scsi_close(dev->fd); return_error: dev->fd = -1; return status; } void sane_cancel( SANE_Handle handle ) { ST400_Device *dev = handle; DBG(DCODE, "sane_cancel(%p)\n", handle); if( dev->status.scanning ) { #if 0 st400_stop_scan(dev->fd); #endif if( st400_light_delay ) st400_light_off(dev->fd); st400_release(dev->fd); sanei_scsi_close(dev->fd); dev->status.scanning = 0; dev->fd = -1; } if( dev->buffer ) { free(dev->buffer); dev->buffer = NULL; } } SANE_Status sane_read( SANE_Handle handle, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenP ) { ST400_Device *dev = handle; SANE_Status status; size_t r, i; SANE_Byte val; DBG(DCODE, "sane_read(%p, %p, %d, %p)\n", handle, buf, (int)maxlen, (void *) lenP); *lenP = 0; if( !dev->status.scanning ) return SANE_STATUS_INVAL; if( dev->status.eof ) return SANE_STATUS_EOF; status = SANE_STATUS_GOOD; while( maxlen > 0 ) { if( dev->bytes_in_buffer == 0 ) { status = st400_fill_backend_buffer(dev); if( status == SANE_STATUS_EOF ) return SANE_STATUS_GOOD; if( status != SANE_STATUS_GOOD ) { *lenP = 0; return status; } } r = min((SANE_Int) dev->bytes_in_buffer, maxlen); if( dev->val[OPT_DEPTH] == 1 || dev->model->bits == 8 ) { /* This is simple. We made sure the scanning are is aligned to * 8 pixels (see sane_get_parameters()), so we can simply copy * the stuff - only need to invert it. */ for( i = 0; i < r; i++ ) *buf++ = ~(*dev->bufp++); } else { SANE_Byte mv; /* The scanner sends bytes with 6bit-values (0..63), where 0 means * white. To convert to 8bit, we invert the values (so 0 means * black) and then shift them two bits to the left and replicate * the most- significant bits in the lowest two bits of the * 8bit-value: * bit-pattern x x 5 4 3 2 1 0 becomes 5 4 3 2 1 0 5 4 * This is more accurate than simply shifting the values two bits * to the left (e.g. 6bit-white 00111111 gets converted to 8bit- * white 11111111 instead of almost-white 11111100) and is still * reasonably fast. */ mv = (SANE_Byte)maxval(dev->model->bits); /* Note: this works with any bit depth <= 8 */ for( i = 0; i < r; i++ ) { val = mv - *dev->bufp++; val <<= (8 - dev->model->bits); val += (val >> dev->model->bits); *buf++ = val; } } maxlen -= r; dev->bytes_in_buffer -= r; *lenP += r; } return status; } /********************************************************************* * Advanced functions (not supported) *********************************************************************/ SANE_Status sane_set_io_mode( SANE_Handle handle, SANE_Bool nonblock ) { DBG(DCODE, "sane_set_io_mode(%p, %d)\n", handle, (int)nonblock); if( nonblock == SANE_TRUE ) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd( SANE_Handle handle, SANE_Int *fdP ) { DBG(DCODE, "sane_get_select_fd(%p, %p)\n", handle, (void *) fdP); return SANE_STATUS_UNSUPPORTED; } /* The End */ sane-backends-1.0.27/backend/hp5400.conf.in0000664000175000017500000000035612112021330014772 00000000000000# hp5400.conf # See man sane-hp5400 for a description. # # HP 5400C usb 0x03F0 0x1005 # # HP 5470C usb 0x03F0 0x1105 # # Device filename to use for scanner access # # Uncomment the following line if autodetection fails # #/dev/usbscanner sane-backends-1.0.27/backend/umax-uc840.c0000664000175000017500000001027512112021330014556 00000000000000/* ------------------------------------------------------------------------- */ /* umax-uc840.c: inquiry for UMAX scanner uc840 (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------- */ #include "umax-scanner.h" /* ------------------------------------------------------------------------- */ static unsigned char UC840_INQUIRY[] = { #define UC840_INQUIRY_LEN 0x94 /* 24 F/W support function */ 0x00, /* ? */ /* 25 -27 exposure-times */ 0x00, 0x00, 0x00, /* 28 - 29 reserved */ 0x00, 0x00, /* 2a - 35 exposure times */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 37 reserved */ 0x00, 0x00, /* 38 - 5f scsi reserved */ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, /* 60 -62 scanner capability*/ 0xfd, 0x8c, /* 0xbc ? */ 0x03, /* 63 reserved */ 0x00, /* 64 gamma */ 0xa1, /* 65 reserved */ 0x00, /* 66 GIB */ 0x01, /* 67 reserved */ 0x00, /* 68 GOB */ 0x01, /* 69 - 6a halftone */ 0x88, 0x2f, /* 6b - 6c reserved */ 0x00, 0x00, /* 6d color sequence */ 0xe5, /* 6e - 71 video memory */ 0x00, 0x20, 0x00, 0x00, /* 72 reserved */ 0x00, /* 73 max optical res in 100 dpi */ 0x04, /* 74 max x_res in 100 dpi */ 0x04, /* 75 max y_res in 100 dpi */ 0x08, /* 76-77 fb max scan width in 0.01 inch */ 0x03, 0x52, /* 78-79 fb max scan length in 0.01 inch */ 0x05, 0x78, /* 7a-7b uta x original point, may be 0x05, 0x89 */ 0x00, 0x76, /* 7c-7d uta y original point, may be 0x06, 0x75 */ 0x00, 0x89, /* 7e-7f uta max scan width in 0.01 inch */ 0x02, 0x4e, /* 80-81 uta max scan length in 0.01 inch */ 0x03, 0x65, /* 82-85 reserved */ 00, 00, 00, 00, /* 86-87 dor x original point */ 0x00, 0x00, /* 88-89 dor x original point */ 0x00, 0x00, /* 8a-8b dor max scan width in 0.01 inch */ 0x00, 0x00, /* 8c-8d dor max scan length in 0.01 inch */ 0x00, 0x00, /* 8e reserved */ 0x00, /* 8f last calibration lamp density */ 0x00, /* 90 reserved */ 0x00, /* 91 lamp warmup max time */ 0x00, /* 92-93 window descriptor block length */ 0x00, 0x30, /* 94 optical resolution residue (1dpi) */ 0x00, /* 95 x_resolution residue (1dpi) */ 0x00, /* 96 y_resolution residue (1dpi) */ 0x00, /* 97 analog gamma table */ 0x00, /* 98-99 reserved */ 0x00, 0x00, /* 9a max calibration data lines */ 0x00 }; static inquiry_blk inquiry_uc840 = { "UC840 ", UC840_INQUIRY, UC840_INQUIRY_LEN }; sane-backends-1.0.27/backend/hp5400_debug.c0000664000175000017500000000457512112021330015037 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Martijn van Oosterhout Copyright (C) 2003 Thomas Soumarmon Originally copied from HP3300 testtools. Original notice follows: Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #include "hp5400_debug.h" #ifdef STANDALONE #include FILE *DBG_ASSERT = NULL; FILE *DBG_ERR = NULL; FILE *DBG_MSG = NULL; void hp5400_dbg_start() { DBG_MSG = stdout; DBG_ERR = stderr; DBG_ASSERT = stderr; } #else /* #define DEBUG_NOT_STATIC */ #undef DEBUG_DECLARE_ONLY #undef _SANEI_DEBUG_H #include "../include/sane/sanei_debug.h" #endif sane-backends-1.0.27/backend/hp4200_lm9830.h0000664000175000017500000001372512112021330014704 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Adrian Perez Jorge This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a backend for the HP4200C flatbed scanner */ #define INPUT_SIGNAL_POLARITY_NEGATIVE 0 #define INPUT_SIGNAL_POLARITY_POSITIVE 1 #define CDS_OFF 0 #define CDS_ON (1 << 1) #define SENSOR_EVENODD (1 << 2) #define SENSOR_STANDARD 0 #define SENSOR_RESOLUTION_300 0 #define SENSOR_RESOLUTION_600 (1 << 3) #define LINE_SKIPPING_COLOR_PHASE_DELAY(n) (((n) & 0x0f) << 4) #define PHI1_POLARITY_POSITIVE 0 #define PHI1_POLARITY_NEGATIVE 1 #define PHI2_POLARITY_POSITIVE 0 #define PHI2_POLARITY_NEGATIVE (1 << 1) #define RS_POLARITY_POSITIVE 0 #define RS_POLARITY_NEGATIVE (1 << 2) #define CP1_POLARITY_POSITIVE 0 #define CP1_POLARITY_NEGATIVE (1 << 3) #define CP2_POLARITY_POSITIVE 0 #define CP2_POLARITY_NEGATIVE (1 << 4) #define TR1_POLARITY_POSITIVE 0 #define TR1_POLARITY_NEGATIVE (1 << 5) #define TR2_POLARITY_POSITIVE 0 #define TR2_POLARITY_NEGATIVE (1 << 6) #define PHI1_OFF 0 #define PHI1_ACTIVE 1 #define PHI2_OFF 0 #define PHI2_ACTIVE (1 << 1) #define RS_OFF 0 #define RS_ACTIVE (1 << 2) #define CP1_OFF 0 #define CP1_ACTIVE (1 << 3) #define CP2_OFF 0 #define CP2_ACTIVE (1 << 4) #define TR1_OFF 0 #define TR1_ACTIVE (1 << 5) #define TR2_OFF 0 #define TR2_ACTIVE (1 << 6) #define NUMBER_OF_TR_PULSES(n) (((n) - 1) << 7) #define TR_PULSE_DURATION(n) ((n) & 0x0f) #define TR_PHI1_GUARDBAND_DURATION(n) (((n) & 0x0f) << 4) #define CIS_TR1_TIMING_OFF 0 #define CIS_TR1_TIMING_MODE1 1 #define CIS_TR1_TIMING_MODE2 2 #define FAKE_OPTICAL_BLACK_PIXELS_OFF 0 #define FAKE_OPTICAL_BLACK_PIXELS_ON (1 << 2) #define PIXEL_RATE_3_CHANNELS 0 #define LINE_RATE_3_CHANNELS 1 #define MODEA_1_CHANNEL 4 #define MODEB_1_CHANNEL 5 #define GRAY_CHANNEL_RED 0 #define GRAY_CHANNEL_GREEN (1 << 3) #define GRAY_CHANNEL_BLU (2 << 3) #define TR_RED(n) ((n) << 5) #define TR_GREEN(n) ((n) << 6) #define TR_BLUE(n) ((n) << 7) #define TR_RED_DROP(n) (n) #define TR_GREEN_DROP(n) ((n) << 2) #define TR_BLUE_DROP(n) ((n) << 4) #define ILLUMINATION_MODE(n) (n) #define HIBYTE(w) ((SANE_Byte)(((w) >> 8) & 0xff)) #define LOBYTE(w) ((SANE_Byte)((w) & 0xff)) #define EPP_MODE 0 #define NIBBLE_MODE 1 #define PPORT_DRIVE_CURRENT(n) ((n) << 1) #define RAM_SIZE_64 0 #define RAM_SIZE_128 1 #define RAM_SIZE_256 2 #define SRAM_DRIVER_CURRENT(n) ((n) << 2) #define SRAM_BANDWIDTH_4 0 #define SRAM_BANDWIDTH_8 (1 << 4) #define SCANNING_FULL_DUPLEX 0 #define SCANNING_HALF_DUPLEX (1 << 5) #define FULL_STEPPING 0 #define MICRO_STEPPING 1 #define CURRENT_SENSING_PHASES(n) (((n) - 1) << 1) #define PHASE_A_POLARITY_POSITIVE 0 #define PHASE_A_POLARITY_NEGATIVE (1 << 2) #define PHASE_B_POLARITY_POSITIVE 0 #define PHASE_B_POLARITY_NEGATIVE (1 << 3) #define STEPPER_MOTOR_TRISTATE 0 #define STEPPER_MOTOR_OUTPUT (1 << 4) #define ACCELERATION_PROFILE_STOPPED(n) (n) #define ACCELERATION_PROFILE_25P(n) ((n) << 2) #define ACCELERATION_PROFILE_50P(n) ((n) << 4) #define NON_REVERSING_EXTRA_LINES(n) (n) #define FIRST_LINE_TO_PROCESS(n) ((n) << 3) #define KICKSTART_STEPS(n) (n) #define HOLD_CURRENT_TIMEOUT(n) ((n) << 3) #define PAPER_SENSOR_1_POLARITY_LOW 0 #define PAPER_SENSOR_1_POLARITY_HIGH 1 #define PAPER_SENSOR_1_TRIGGER_LEVEL 0 #define PAPER_SENSOR_1_TRIGGER_EDGE (1 << 1) #define PAPER_SENSOR_1_NO_STOP_SCAN 0 #define PAPER_SENSOR_1_STOP_SCAN (1 << 2) #define PAPER_SENSOR_2_POLARITY_LOW 0 #define PAPER_SENSOR_2_POLARITY_HIGH (1 << 3) #define PAPER_SENSOR_2_TRIGGER_LEVEL 0 #define PAPER_SENSOR_2_TRIGGER_EDGE (1 << 4) #define PAPER_SENSOR_2_NO_STOP_SCAN 0 #define PAPER_SENSOR_2_STOP_SCAN (1 << 5) #define MISCIO_1_TYPE_INPUT 0 #define MISCIO_1_TYPE_OUTPUT 1 #define MISCIO_1_POLARITY_LOW 0 #define MISCIO_1_POLARITY_HIGH (1 << 1) #define MISCIO_1_TRIGGER_LEVEL 0 #define MISCIO_1_TRIGGER_EDGE (1 << 2) #define MISCIO_1_OUTPUT_STATE_LOW 0 #define MISCIO_1_OUTPUT_STATE_HIGH (1 << 3) #define MISCIO_2_TYPE_INPUT 0 #define MISCIO_2_TYPE_OUTPUT (1 << 4) #define MISCIO_2_POLARITY_LOW 0 #define MISCIO_2_POLARITY_HIGH (1 << 5) #define MISCIO_2_TRIGGER_LEVEL 0 #define MISCIO_2_TRIGGER_EDGE (1 << 6) #define MISCIO_2_OUTPUT_STATE_LOW 0 #define MISCIO_2_OUTPUT_STATE_HIGH (1 << 7) #define PIXEL_PACKING(n) ((n) << 3) #define DATAMODE(n) ((n) << 5) sane-backends-1.0.27/backend/plustek-usbcalfile.c0000664000175000017500000005323512775312261016571 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbcalfile.c * @brief Functions for saving/restoring calibration settings * * Copyright (C) 2001-2007 Gerhard Jaeger * * History: * - 0.46 - first version * - 0.47 - no changes * - 0.48 - no changes * - 0.49 - a_bRegs is now part of the device structure * - 0.50 - cleanup * - 0.51 - added functions for saving, reading and restoring * fine calibration data * - 0.52 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ typedef struct { u_long red_light_on; u_long red_light_off; u_long green_light_on; u_long green_light_off; u_long blue_light_on; u_long blue_light_off; u_long green_pwm_duty; } LightCtrl; typedef struct { u_short version; u_short red_gain; u_short green_gain; u_short blue_gain; u_short red_offs; u_short green_offs; u_short blue_offs; LightCtrl light; } CalData; /* our shading buffers */ static u_short a_wWhiteShading[_SHADING_BUF] = {0}; static u_short a_wDarkShading[_SHADING_BUF] = {0}; /* the version the calibration files */ #define _PT_CF_VERSION 0x0002 /** function to read a text file and returns the string which starts which * 'id' string. * no duplicate entries where detected, always the first occurance will be * red. * @param fp - file pointer of file to read * @param id - what to search for * @param res - where to store the result upon success * @return SANE_TRUE on success, SANE_FALSE on any error */ static SANE_Bool usb_ReadSpecLine( FILE *fp, char *id, char* res ) { char tmp[1024]; char *ptr; /* rewind file pointer */ if( 0 != fseek( fp, 0L, SEEK_SET)) { DBG( _DBG_ERROR, "fseek: %s\n", strerror(errno)); return SANE_FALSE; } /* roam through the file and examine each line... */ while( !feof( fp )) { memset( tmp, 0, sizeof(tmp)); if( NULL != fgets( tmp, 1024, fp )) { if( 0 == strncmp( tmp, id, strlen(id))) { ptr = &tmp[strlen(id)]; if( '\0' == *ptr ) break; strcpy( res, ptr ); res[strlen(res)-1] = '\0'; return SANE_TRUE; } } } return SANE_FALSE; } /** function to read data from a file and excluding certain stuff like * the version lines * @param fp - file pointer of file to read * @param except - what to exclude * @return Pointer to the allocated memory for the data, NULL on any error. */ static char* usb_ReadOtherLines( FILE *fp, char *except ) { char tmp[1024]; char *ptr, *ptr_base; int ignore; int len; if( 0 != fseek( fp, 0L, SEEK_END)) return NULL; len = ftell(fp); /* rewind file pointer */ if( 0 != fseek( fp, 0L, SEEK_SET)) return NULL; if( len == 0 ) return NULL; ptr = (char*)malloc(len); if( NULL == ptr ) return NULL; ptr_base = ptr; *ptr = '\0'; ignore = 0; /* roam through the file and examine each line... */ while( !feof( fp )) { if( NULL != fgets( tmp, 1024, fp )) { /* we ignore the version line... */ if( 0 == strncmp( tmp, "version=", 8 )) continue; if( !ignore ) { if(0 != strncmp(tmp, except, strlen(except))) { if( strlen( tmp ) > 0 ) { strcpy( ptr, tmp ); ptr += strlen(tmp); *ptr = '\0'; } } else { ignore = 1; } } /* newline in tmp string resets ignore flag */ if( strrchr(tmp, '\n')) { ignore = 0; } } } return ptr_base; } /** */ static SANE_Bool usb_ReadSamples( FILE *fp, char *which, u_long *dim, u_short *buffer ) { char *p, *next, *rb; char tmp[1024+30]; int ignore, diml, c; u_long val; /* rewind file pointer */ if( 0 != fseek( fp, 0L, SEEK_SET)) return SANE_FALSE; ignore = 0; diml = 0; c = 0; rb = tmp; *dim = 0; /* roam through the file and examine each line... */ while( !feof( fp )) { if( NULL != fgets( rb, 1024, fp )) { /* we ignore the version line... */ if( 0 == strncmp( tmp, "version=", 8 )) continue; p = tmp; if( !ignore && diml == 0) { if(0 == strncmp(tmp, which, strlen(which))) { /* get dimension */ diml = strtol(&tmp[strlen(which)], NULL, 10); p = strchr( &tmp[strlen(which)], ':' ); p++; } else { ignore = 1; } } /* parse the values... */ if( !ignore ) { rb = tmp; while( *p ) { val = strtoul( p, &next, 10 ); /* check for error condition */ if( val == 0 ) { if( p == next ) { if( c+1 == diml ) { *dim = diml; return SANE_TRUE; } break; } } buffer[c] = (u_short)val; /* more values? */ if( *next == ',') { p = next+1; c++; } else { p = next; } /* reached the end? */ if( *next == '\0' ) { /* we probably have only parsed a part of a value * so we copy that back to the input buffer and * parse it the next time... */ if( c < diml ) { sprintf( tmp, "%u", buffer[c] ); rb = &tmp[strlen(tmp)]; } } } } /* newline in tmp string resets ignore flag */ if( strrchr(tmp, '\n')) { ignore = 0; } } } return SANE_FALSE; } /** */ static void usb_RestoreCalData( Plustek_Device *dev, CalData *cal ) { HWDef *hw = &dev->usbDev.HwSetting; u_char *regs = dev->usbDev.a_bRegs; regs[0x3b] = (u_char)cal->red_gain; regs[0x3c] = (u_char)cal->green_gain; regs[0x3d] = (u_char)cal->blue_gain; regs[0x38] = (u_char)cal->red_offs; regs[0x39] = (u_char)cal->green_offs; regs[0x3a] = (u_char)cal->blue_offs; regs[0x2a] = _HIBYTE((u_short)cal->light.green_pwm_duty); regs[0x2b] = _LOBYTE((u_short)cal->light.green_pwm_duty); regs[0x2c] = _HIBYTE((u_short)cal->light.red_light_on); regs[0x2d] = _LOBYTE((u_short)cal->light.red_light_on); regs[0x2e] = _HIBYTE((u_short)cal->light.red_light_off); regs[0x2f] = _LOBYTE((u_short)cal->light.red_light_off); regs[0x30] = _HIBYTE((u_short)cal->light.green_light_on); regs[0x31] = _LOBYTE((u_short)cal->light.green_light_on); regs[0x32] = _HIBYTE((u_short)cal->light.green_light_off); regs[0x33] = _LOBYTE((u_short)cal->light.green_light_off); regs[0x34] = _HIBYTE((u_short)cal->light.blue_light_on); regs[0x35] = _LOBYTE((u_short)cal->light.blue_light_on); regs[0x36] = _HIBYTE((u_short)cal->light.blue_light_off); regs[0x37] = _LOBYTE((u_short)cal->light.blue_light_off); hw->red_lamp_on = (u_short)cal->light.red_light_on; hw->red_lamp_off = (u_short)cal->light.red_light_off; hw->green_lamp_on = (u_short)cal->light.green_light_on; hw->green_lamp_off = (u_short)cal->light.green_light_off; hw->blue_lamp_on = (u_short)cal->light.blue_light_on; hw->blue_lamp_off = (u_short)cal->light.blue_light_off; } /** */ static void usb_CreatePrefix( Plustek_Device *dev, char *pfx, SANE_Bool add_bitdepth ) { char bd[5]; ScanDef *scanning = &dev->scanning; ScanParam *param = &scanning->sParam; switch( scanning->sParam.bSource ) { case SOURCE_Transparency: strcpy( pfx, "tpa-" ); break; case SOURCE_Negative: strcpy( pfx, "neg-" ); break; case SOURCE_ADF: strcpy( pfx, "adf-" ); break; default: pfx[0] = '\0'; break; } sprintf( bd, "%u=", param->bBitDepth ); if( param->bDataType == SCANDATATYPE_Color ) strcat( pfx, "color" ); else strcat( pfx, "gray" ); if( add_bitdepth ) strcat( pfx, bd ); } /** function to read and set the calibration data from external file */ static SANE_Bool usb_ReadAndSetCalData( Plustek_Device *dev ) { char pfx[20]; char tmp[1024]; u_short version; int res; FILE *fp; CalData cal; SANE_Bool ret; DBG( _DBG_INFO, "usb_ReadAndSetCalData()\n" ); if( usb_InCalibrationMode(dev)) { DBG( _DBG_INFO, "- we are in calibration mode!\n" ); return SANE_FALSE; } if( NULL == dev->calFile ) { DBG( _DBG_ERROR, "- No calibration filename set!\n" ); return SANE_FALSE; } sprintf( tmp, "%s-coarse.cal", dev->calFile ); DBG( _DBG_INFO, "- Reading coarse calibration data from file\n"); DBG( _DBG_INFO, " %s\n", tmp ); fp = fopen( tmp, "r" ); if( NULL == fp ) { DBG( _DBG_ERROR, "File %s not found\n", tmp ); return SANE_FALSE; } /* check version */ if( !usb_ReadSpecLine( fp, "version=", tmp )) { DBG( _DBG_ERROR, "Could not find version info!\n" ); fclose( fp ); return SANE_FALSE; } DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp ); if( 1 != sscanf( tmp, "0x%04hx", &version )) { DBG( _DBG_ERROR, "Could not decode version info!\n" ); fclose( fp ); return SANE_FALSE; } if( version != _PT_CF_VERSION ) { DBG( _DBG_ERROR, "Versions do not match!\n" ); fclose( fp ); return SANE_FALSE; } usb_CreatePrefix( dev, pfx, SANE_TRUE ); ret = SANE_FALSE; if( usb_ReadSpecLine( fp, pfx, tmp )) { DBG( _DBG_INFO, "- Calibration data: %s\n", tmp ); res = sscanf( tmp, "%hu,%hu,%hu,%hu,%hu,%hu," "%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", &cal.red_gain, &cal.red_offs, &cal.green_gain, &cal.green_offs, &cal.blue_gain, &cal.blue_offs, &cal.light.red_light_on, &cal.light.red_light_off, &cal.light.green_light_on, &cal.light.green_light_off, &cal.light.blue_light_on, &cal.light.blue_light_off, &cal.light.green_pwm_duty ); if( 13 == res ) { usb_RestoreCalData( dev, &cal ); ret = SANE_TRUE; } else { DBG( _DBG_ERROR, "Error reading coarse-calibration data, only " "%d elements available!\n", res ); } } else { DBG( _DBG_ERROR, "Error reading coarse-calibration data for " "PFX: >%s %u\n", ret ); return ret; } /** */ static void usb_PrepCalData( Plustek_Device *dev, CalData *cal ) { u_char *regs = dev->usbDev.a_bRegs; memset( cal, 0, sizeof(CalData)); cal->version = _PT_CF_VERSION; cal->red_gain = (u_short)regs[0x3b]; cal->green_gain = (u_short)regs[0x3c]; cal->blue_gain = (u_short)regs[0x3d]; cal->red_offs = (u_short)regs[0x38]; cal->green_offs = (u_short)regs[0x39]; cal->blue_offs = (u_short)regs[0x3a]; cal->light.green_pwm_duty = regs[0x2a] * 256 + regs[0x2b]; cal->light.red_light_on = regs[0x2c] * 256 + regs[0x2d]; cal->light.red_light_off = regs[0x2e] * 256 + regs[0x2f]; cal->light.green_light_on = regs[0x30] * 256 + regs[0x31]; cal->light.green_light_off = regs[0x32] * 256 + regs[0x33]; cal->light.blue_light_on = regs[0x34] * 256 + regs[0x35]; cal->light.blue_light_off = regs[0x36] * 256 + regs[0x37]; } /** function to save/update the calibration data */ static void usb_SaveCalData( Plustek_Device *dev ) { char pfx[20]; char fn[1024]; char tmp[1024]; char set_tmp[1024]; char *other_tmp; u_short version; FILE *fp; CalData cal; ScanDef *scanning = &dev->scanning; DBG( _DBG_INFO, "usb_SaveCalData()\n" ); /* no new data, so skip this step too */ if( SANE_TRUE == scanning->skipCoarseCalib ) { DBG( _DBG_INFO, "- No calibration data to save!\n" ); return; } if( NULL == dev->calFile ) { DBG( _DBG_ERROR, "- No calibration filename set!\n" ); return; } sprintf( fn, "%s-coarse.cal", dev->calFile ); DBG( _DBG_INFO, "- Saving coarse calibration data to file\n" ); DBG( _DBG_INFO, " %s\n", fn ); usb_PrepCalData ( dev, &cal ); usb_CreatePrefix( dev, pfx, SANE_TRUE ); DBG( _DBG_INFO2, "- PFX: >%s<\n", pfx ); sprintf( set_tmp, "%s%u,%u,%u,%u,%u,%u," "%lu,%lu,%lu,%lu,%lu,%lu,%lu\n", pfx, cal.red_gain, cal.red_offs, cal.green_gain, cal.green_offs, cal.blue_gain, cal.blue_offs, cal.light.red_light_on, cal.light.red_light_off, cal.light.green_light_on, cal.light.green_light_off, cal.light.blue_light_on, cal.light.blue_light_off, cal.light.green_pwm_duty ); /* read complete old file if compatible... */ other_tmp = NULL; fp = fopen( fn, "r+" ); if( NULL != fp ) { if( usb_ReadSpecLine( fp, "version=", tmp )) { DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp ); if( 1 == sscanf( tmp, "0x%04hx", &version )) { if( version == cal.version ) { DBG( _DBG_INFO, "- Versions do match\n" ); /* read the rest... */ other_tmp = usb_ReadOtherLines( fp, pfx ); } else { DBG( _DBG_INFO2, "- Versions do not match (0x%04x)\n", version ); } } else { DBG( _DBG_INFO2, "- cannot decode version\n" ); } } else { DBG( _DBG_INFO2, "- Version not found\n" ); } fclose( fp ); } fp = fopen( fn, "w+" ); if( NULL == fp ) { DBG( _DBG_ERROR, "- Cannot create file %s\n", fn ); DBG( _DBG_ERROR, "- -> %s\n", strerror(errno)); if( other_tmp ) free( other_tmp ); return; } /* rewrite the file again... */ fprintf( fp, "version=0x%04X\n", cal.version ); if( strlen( set_tmp )) fprintf( fp, "%s", set_tmp ); if( other_tmp ) { fprintf( fp, "%s", other_tmp ); free( other_tmp ); } fclose( fp ); DBG( _DBG_INFO, "usb_SaveCalData() done.\n" ); } /** */ static void usb_SaveFineCalData( Plustek_Device *dev, int dpi, u_short *dark, u_short *white, u_long vals ) { char pfx[30]; char fn[1024]; char tmp[1024]; char *other_tmp; u_short version; u_long i; FILE *fp; if( NULL == dev->calFile ) { DBG( _DBG_ERROR, "- No calibration filename set!\n" ); return; } sprintf( fn, "%s-fine.cal", dev->calFile ); DBG( _DBG_INFO, "- Saving fine calibration data to file\n" ); DBG( _DBG_INFO, " %s\n", fn ); usb_CreatePrefix( dev, pfx, SANE_FALSE ); sprintf( tmp, "%s:%u", pfx, dpi ); strcpy( pfx, tmp ); DBG( _DBG_INFO2, "- PFX: >%s<\n", pfx ); /* read complete old file if compatible... */ other_tmp = NULL; fp = fopen( fn, "r+" ); if( NULL != fp ) { if( usb_ReadSpecLine( fp, "version=", tmp )) { DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp ); if( 1 == sscanf( tmp, "0x%04hx", &version )) { if( version == _PT_CF_VERSION ) { DBG( _DBG_INFO, "- Versions do match\n" ); /* read the rest... */ other_tmp = usb_ReadOtherLines( fp, pfx ); } else { DBG( _DBG_INFO2, "- Versions do not match (0x%04x)\n", version ); } } else { DBG( _DBG_INFO2, "- cannot decode version\n" ); } } else { DBG( _DBG_INFO2, "- Version not found\n" ); } fclose( fp ); } fp = fopen( fn, "w+" ); if( NULL == fp ) { DBG( _DBG_ERROR, "- Cannot create file %s\n", fn ); return; } /* rewrite the file again... */ fprintf( fp, "version=0x%04X\n", _PT_CF_VERSION ); if( other_tmp ) { fprintf( fp, "%s", other_tmp ); free( other_tmp ); } fprintf( fp, "%s:dark:dim=%lu:", pfx, vals ); for( i=0; icalFile ) { DBG( _DBG_ERROR, "- No calibration filename set!\n" ); return SANE_FALSE; } sprintf( tmp, "%s-fine.cal", dev->calFile ); DBG( _DBG_INFO, "- Reading fine calibration data from file\n"); DBG( _DBG_INFO, " %s\n", tmp ); *dim_d = *dim_w = 0; fp = fopen( tmp, "r" ); if( NULL == fp ) { DBG( _DBG_ERROR, "File %s not found\n", tmp ); return SANE_FALSE; } /* check version */ if( !usb_ReadSpecLine( fp, "version=", tmp )) { DBG( _DBG_ERROR, "Could not find version info!\n" ); fclose( fp ); return SANE_FALSE; } DBG( _DBG_INFO, "- Calibration file version: %s\n", tmp ); if( 1 != sscanf( tmp, "0x%04hx", &version )) { DBG( _DBG_ERROR, "Could not decode version info!\n" ); fclose( fp ); return SANE_FALSE; } if( version != _PT_CF_VERSION ) { DBG( _DBG_ERROR, "Versions do not match!\n" ); fclose( fp ); return SANE_FALSE; } usb_CreatePrefix( dev, pfx, SANE_FALSE ); sprintf( tmp, "%s:%u:%s:dim=", pfx, dpi, "dark" ); if( !usb_ReadSamples( fp, tmp, dim_d, dark )) { DBG( _DBG_ERROR, "Error reading dark-calibration data!\n" ); fclose( fp ); return SANE_FALSE; } sprintf( tmp, "%s:%u:%s:dim=", pfx, dpi, "white" ); if( !usb_ReadSamples( fp, tmp, dim_w, white )) { DBG( _DBG_ERROR, "Error reading white-calibration data!\n" ); fclose( fp ); return SANE_FALSE; } fclose( fp ); return SANE_TRUE; } /** */ static void usb_get_shading_part(u_short *buf, u_long offs, u_long src_len, int dst_len) { u_short *p_src, *p_dst; int i, j; if (src_len == 0 || dst_len == 0) return; p_dst = buf; for (i=0; i<3; i++) { p_src = buf + src_len * i + offs; for (j=0; jscanning; ScanParam *sp = &scan->sParam; u_short xdpi; u_long dim_w, dim_d, offs; xdpi = usb_SetAsicDpiX( dev, sp->UserDpi.x ); if( !usb_ReadFineCalData( dev, xdpi, &dim_d, a_wDarkShading, &dim_w, a_wWhiteShading)) { return SANE_FALSE; } /* now we need to get the correct part of the line... */ dim_d /= 3; dim_w /= 3; offs = ((u_long)sp->Origin.x * xdpi) / 300; usb_GetPhyPixels( dev, sp ); DBG( _DBG_INFO2, "FINE Calibration from file:\n" ); DBG( _DBG_INFO2, "XDPI = %u\n", xdpi ); DBG( _DBG_INFO2, "Dim = %lu\n", dim_d ); DBG( _DBG_INFO2, "Pixels = %lu\n", sp->Size.dwPixels ); DBG( _DBG_INFO2, "PhyPixels = %lu\n", sp->Size.dwPhyPixels ); DBG( _DBG_INFO2, "Origin.X = %u\n", sp->Origin.x ); DBG( _DBG_INFO2, "Offset = %lu\n", offs ); usb_get_shading_part(a_wDarkShading, offs, dim_d, sp->Size.dwPhyPixels); usb_get_shading_part(a_wWhiteShading, offs, dim_w, sp->Size.dwPhyPixels); return SANE_TRUE; } /** function to save the fine calibration results and to set the correct part * of the calibration buffers for storing in the device * @param dev - the almigthy device structure * @param tmp_sp - intermediate scan parameter */ static void usb_SaveCalSetShading( Plustek_Device *dev, ScanParam *tmp_sp ) { ScanParam *sp = &dev->scanning.sParam; u_short xdpi; u_long offs; if( !dev->adj.cacheCalData ) return; /* save the values */ xdpi = usb_SetAsicDpiX( dev, tmp_sp->UserDpi.x ); usb_SaveFineCalData( dev, xdpi, a_wDarkShading, a_wWhiteShading, tmp_sp->Size.dwPixels*3 ); /* now we need to get the correct part of the line... */ xdpi = usb_SetAsicDpiX( dev, sp->UserDpi.x ); offs = ((u_long)sp->Origin.x * xdpi) / 300; usb_GetPhyPixels( dev, sp ); DBG( _DBG_INFO2, "FINE Calibration area after saving:\n" ); DBG( _DBG_INFO2, "XDPI = %u\n", xdpi ); DBG( _DBG_INFO2, "Dim = %lu\n", tmp_sp->Size.dwPixels ); DBG( _DBG_INFO2, "Pixels = %lu\n", sp->Size.dwPixels ); DBG( _DBG_INFO2, "PhyPixels = %lu\n", sp->Size.dwPhyPixels ); DBG( _DBG_INFO2, "Origin.X = %u\n", sp->Origin.x ); DBG( _DBG_INFO2, "Offset = %lu\n", offs ); if (!usb_InCalibrationMode(dev)) { usb_get_shading_part( a_wDarkShading, offs, tmp_sp->Size.dwPixels, sp->Size.dwPhyPixels ); usb_get_shading_part( a_wWhiteShading, offs, tmp_sp->Size.dwPixels, sp->Size.dwPhyPixels ); memcpy( tmp_sp, sp, sizeof(ScanParam)); tmp_sp->bBitDepth = 16; usb_GetPhyPixels( dev, tmp_sp ); } } /* END PLUSTEK-USBCALFILE.C .................................................*/ sane-backends-1.0.27/backend/u12-image.c0000664000175000017500000006421712112021330014437 00000000000000/* @file u12_image.c * @brief functions to convert scanner data into image data * * based on sources acquired from Plustek Inc. * Copyright (c) 2003-2004 Gerhard Jaeger * * History: * - 0.01 - initial version * - 0.02 - fixed fnColor42() to return 16bit values instead of * only 12bit (this is the maximum the scanner can) * - added scaling function u12image_ScaleX() * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /*************************** local vars **************************************/ static u_short wPreviewScanned = 0; static ExpXStepDef negScan[5] = { {128, 8}, {96, 12}, {96, 24}, {96, 48}, {96, 96} }; static ExpXStepDef posScan[5] = { {128, 8}, {96, 12}, {96, 24}, {96, 48}, {96, 96} }; static ExpXStepDef nmlScan[5] = { {160, 10}, {96, 12}, {96, 24}, {96, 48}, {96, 96}, }; /*************************** local functions *********************************/ /** */ static SANE_Bool fnReadToDriver( U12_Device *dev ) { dev->regs.RD_ModeControl = _ModeFifoBSel; u12io_ReadMonoData( dev, dev->scan.BufPut.blue.bp, dev->DataInf.dwAsicBytesPerPlane ); dev->regs.RD_ModeControl = _ModeFifoGSel; u12io_ReadMonoData( dev, dev->scan.BufPut.green.bp, dev->DataInf.dwAsicBytesPerPlane ); if( dev->scan.gd_gk.wGreenKeep ) dev->scan.gd_gk.wGreenKeep--; else { dev->scan.BufPut.green.bp += dev->DataInf.dwAsicBytesPerPlane; if( dev->scan.BufPut.green.bp >= dev->scan.BufEnd.green.bp ) dev->scan.BufPut.green.bp = dev->scan.BufBegin.green.bp; } dev->regs.RD_ModeControl = _ModeFifoRSel; u12io_ReadMonoData( dev, dev->scan.BufPut.red.bp, dev->DataInf.dwAsicBytesPerPlane ); dev->scan.BufPut.red.bp += dev->DataInf.dwAsicBytesPerPlane; if( dev->scan.BufPut.red.bp >= dev->scan.BufEnd.red.bp ) dev->scan.BufPut.red.bp = dev->scan.BufBegin.red.bp; if( dev->scan.bd_rk.wRedKeep ) { dev->scan.bd_rk.wRedKeep--; return SANE_FALSE; } else { dev->scan.BufData.green.bp = dev->scan.BufGet.green.bp; dev->scan.BufData.red.bp = dev->scan.BufGet.red.bp; dev->scan.BufData.blue.bp = dev->scan.BufGet.blue.bp; dev->scan.BufGet.red.bp += dev->DataInf.dwAsicBytesPerPlane; dev->scan.BufGet.green.bp += dev->DataInf.dwAsicBytesPerPlane; if( dev->scan.BufGet.red.bp >= dev->scan.BufEnd.red.bp ) dev->scan.BufGet.red.bp = dev->scan.BufBegin.red.bp; if( dev->scan.BufGet.green.bp >= dev->scan.BufEnd.green.bp ) dev->scan.BufGet.green.bp = dev->scan.BufBegin.green.bp; return SANE_TRUE; } } /** */ static SANE_Bool fnReadOutScanner( U12_Device *dev ) { if( dev->scan.bd_rk.wBlueDiscard ) { dev->scan.bd_rk.wBlueDiscard--; dev->regs.RD_ModeControl = _ModeFifoBSel; u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf, dev->DataInf.dwAsicBytesPerPlane ); if( dev->scan.gd_gk.wGreenDiscard ) { dev->scan.gd_gk.wGreenDiscard--; dev->regs.RD_ModeControl = _ModeFifoGSel; u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf, dev->DataInf.dwAsicBytesPerPlane ); } return SANE_FALSE; } else { u12io_ReadColorData( dev, dev->bufs.b1.pReadBuf, dev->DataInf.dwAsicBytesPerPlane ); return SANE_TRUE; } } /** some sampling functions */ static SANE_Bool fnEveryLine( U12_Device *dev ) { _VAR_NOT_USED( dev ); return SANE_TRUE; } static SANE_Bool fnSampleLines( U12_Device *dev ) { dev->DataInf.wYSum += dev->DataInf.xyAppDpi.y; if( dev->DataInf.wYSum >= dev->DataInf.xyPhyDpi.y ) { dev->DataInf.wYSum -= dev->DataInf.xyPhyDpi.y; return SANE_TRUE; } return SANE_FALSE; } static SANE_Bool fnSamplePreview( U12_Device *dev ) { dev->DataInf.wYSum += wPreviewScanned; if( dev->DataInf.wYSum >= 150 ) { dev->DataInf.wYSum -= 150; return SANE_TRUE; } return SANE_FALSE; } /** this function is used when * - the data type is B/W or GrayScale. * - the required horizontal resolution doesn't exceed the optic spec. * - the required vertical resolution exceeds the optic spec. */ static void fnDataDirect( U12_Device *dev, void *src, void *dest, u_long len ) { _VAR_NOT_USED( dev ); memcpy( dest, src, len ); } /** merges the color planes to pixels style without enlarge operation. */ static void fnColorDirect( U12_Device *dev, void *pb, void *img, u_long len ) { SANE_Byte *src; RGBByteDef *dest; src = (SANE_Byte*)img; dest = (RGBByteDef*)pb; for ( len = dev->DataInf.dwAsicPixelsPerPlane; len; len--, src++, dest++) { dest->Red = *src; dest->Green = src[dev->DataInf.dwAsicPixelsPerPlane]; dest->Blue = src[dev->DataInf.dwAsicPixelsPerPlane*2]; } } /** merges the color planes to pixels style without enlarge operation. * The scanner returns the pixel data in Motorola-Format, so we have to swap * (at least on x86) */ static void fnColor42( U12_Device *dev, void *pb, void *img, u_long len ) { u_short *src; RGBUShortDef *dest; register u_long i; _VAR_NOT_USED( len ); src = (u_short*)img; dest = (RGBUShortDef*)pb; for ( i = dev->DataInf.dwAsicPixelsPerPlane; i; i--, src++, dest++) { dest->Red = (*src) << 4; dest->Green = (src[dev->DataInf.dwAsicPixelsPerPlane]) << 4; dest->Blue = (src[dev->DataInf.dwAsicPixelsPerPlane * 2]) << 4; } } /** */ static void u12image_SetupScanStateVariables( U12_Device *dev, u_long index ) { DataType var; DBG( _DBG_INFO, "u12image_SetupScanStateVariables(%lu)\n", index ); dev->scan.dpiIdx = index; if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA)) { dev->shade.wExposure = nmlScan[index].exposureTime; dev->shade.wXStep = nmlScan[index].xStepTime; if( dev->shade.intermediate & _ScanMode_AverageOut ) { dev->shade.wExposure >>= 1; dev->shade.wXStep >>= 1; } } else { if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency ) { dev->shade.wExposure = posScan[index].exposureTime; dev->shade.wXStep = posScan[index].xStepTime; } else { dev->shade.wExposure = dev->scan.negScan[index].exposureTime; dev->shade.wXStep = dev->scan.negScan[index].xStepTime; } } dev->scan.dwInterval = 1; if( dev->DataInf.wPhyDataType == COLOR_BW ) var.dwValue = 0; else { if( dev->DataInf.wPhyDataType == COLOR_256GRAY ) var.dwValue = 2500; else var.dwValue = 3200; } /* for small size/descreen */ if((dev->DataInf.xyAppDpi.y >= 300) && var.dwValue && (dev->DataInf.dwAsicBytesPerPlane <= var.dwValue)) { dev->scan.dwInterval <<= 1; } if( var.dwValue && dev->DataInf.dwAsicBytesPerPlane > var.dwValue ) { if((var.dwValue << 1) > dev->DataInf.dwAsicBytesPerPlane) dev->scan.dwInterval <<= 1; else if((var.dwValue << 2) > dev->DataInf.dwAsicBytesPerPlane) dev->scan.dwInterval <<= 2; else dev->scan.dwInterval <<= 3; } if( dev->DataInf.wPhyDataType >= COLOR_TRUE24 ) { if( dev->DataInf.xyPhyDpi.y > 75U ) { if( dev->f0_8_16 ) { dev->scan.gd_gk.wGreenDiscard = dev->DataInf.xyPhyDpi.y / 75U; } else { dev->scan.gd_gk.wGreenDiscard = dev->DataInf.xyPhyDpi.y / 150U; } } else { dev->scan.gd_gk.wGreenDiscard = 1; } dev->scan.bd_rk.wBlueDiscard = dev->scan.gd_gk.wGreenDiscard << 1; } else { dev->scan.bd_rk.wBlueDiscard = dev->scan.gd_gk.wGreenDiscard = 0; } } /** limit the resolution */ static u_short u12image_GetPhysDPI( U12_Device *dev, ImgDef *img, SANE_Bool fDpiX ) { if( fDpiX ) { if( img->xyDpi.x > dev->dpi_max_x ) return dev->dpi_max_x; else return img->xyDpi.x; } else { if( img->xyDpi.y > dev->dpi_max_y ) return dev->dpi_max_y; else return img->xyDpi.y; } } /** calculate the image properties according to the scanmode * set all internally needed information */ static void u12image_GetImageInfo( U12_Device *dev, ImgDef *image ) { DBG( _DBG_INFO, "u12image_GetImageInfo()\n" ); dev->DataInf.xyPhyDpi.x = u12image_GetPhysDPI(dev, image, SANE_TRUE ); dev->DataInf.xyPhyDpi.y = u12image_GetPhysDPI(dev, image, SANE_FALSE); DBG( _DBG_INFO, "* xyPhyDpi.x = %u, xyPhyDpi.y = %u\n", dev->DataInf.xyPhyDpi.x, dev->DataInf.xyPhyDpi.y ); DBG( _DBG_INFO, "* crArea.x = %u, crArea.y = %u\n", image->crArea.x, image->crArea.y ); DBG( _DBG_INFO, "* crArea.cx = %u, crArea.cy = %u\n", image->crArea.cx, image->crArea.cy ); dev->DataInf.xyRatio = (double)dev->DataInf.xyPhyDpi.y/ (double)dev->DataInf.xyPhyDpi.x; dev->DataInf.dwAppLinesPerArea = (u_long)image->crArea.cy * image->xyDpi.y / _MEASURE_BASE; dev->DataInf.dwAppPixelsPerLine = (u_long)image->crArea.cx * image->xyDpi.x / _MEASURE_BASE; dev->DataInf.dwPhysBytesPerLine = (u_long)image->crArea.cx * dev->DataInf.xyPhyDpi.x / _MEASURE_BASE; if( image->wDataType <= COLOR_BW ) { dev->DataInf.dwAsicPixelsPerPlane = (dev->DataInf.dwAppPixelsPerLine+7UL) & 0xfffffff8UL; dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppBytesPerLine = dev->DataInf.dwAsicBytesPerLine = dev->DataInf.dwAsicBytesPerPlane = dev->DataInf.dwAsicPixelsPerPlane>>3; } else { dev->DataInf.dwAsicBytesPerPlane = dev->DataInf.dwAsicPixelsPerPlane = dev->DataInf.dwAppPixelsPerLine; } if( COLOR_TRUE42 == image->wDataType ) { dev->DataInf.dwAsicBytesPerPlane *= 2; } switch( image->wDataType ) { case COLOR_BW: dev->scan.DataProcess = fnDataDirect; dev->DataInf.wPhyDataType = COLOR_BW; dev->shade.intermediate = _ScanMode_Mono; break; case COLOR_256GRAY: dev->scan.DataProcess = fnDataDirect; dev->DataInf.dwAsicBytesPerLine = dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine; dev->DataInf.wPhyDataType = COLOR_256GRAY; dev->shade.intermediate = _ScanMode_Mono; break; case COLOR_TRUE24: dev->scan.DataProcess = fnColorDirect; dev->DataInf.dwAsicBytesPerLine = dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine * 3; dev->DataInf.wPhyDataType = COLOR_TRUE24; dev->shade.intermediate = _ScanMode_Color; break; case COLOR_TRUE42: dev->scan.DataProcess = fnColor42; dev->DataInf.dwAsicBytesPerLine = dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine * 6; dev->DataInf.wPhyDataType = COLOR_TRUE42; dev->shade.intermediate = _ScanMode_Color; break; } /* raus mit einem von beiden!!!!*/ dev->DataInf.dwAppBytesPerLine = dev->DataInf.dwAppPhyBytesPerLine; DBG( _DBG_INFO, "AppLinesPerArea = %lu\n", dev->DataInf.dwAppLinesPerArea ); DBG( _DBG_INFO, "AppPixelsPerLine = %lu\n", dev->DataInf.dwAppPixelsPerLine ); DBG( _DBG_INFO, "AppPhyBytesPerLine = %lu\n", dev->DataInf.dwAppPhyBytesPerLine ); DBG( _DBG_INFO, "AppBytesPerLine = %lu\n", dev->DataInf.dwAppBytesPerLine ); DBG( _DBG_INFO, "AsicPixelsPerPlane = %lu\n", dev->DataInf.dwAsicPixelsPerPlane ); DBG( _DBG_INFO, "AsicBytesPerPlane = %lu\n", dev->DataInf.dwAsicBytesPerPlane ); DBG( _DBG_INFO, "AsicBytesPerLine = %lu\n", dev->DataInf.dwAsicBytesPerLine ); DBG( _DBG_INFO, "Physical Bytes = %lu\n", dev->DataInf.dwPhysBytesPerLine ); } /** */ static int imageSetupScanSettings( U12_Device *dev, ImgDef *img ) { u_short brightness; DBG( _DBG_INFO, "imageSetupScanSettings()\n" ); dev->DataInf.dwScanFlag = img->dwFlag; dev->DataInf.crImage = img->crArea; DBG( _DBG_INFO,"* DataInf.dwScanFlag = 0x%08lx\n",dev->DataInf.dwScanFlag); dev->DataInf.crImage.x <<= 1; dev->DataInf.xyAppDpi = img->xyDpi; dev->DataInf.wAppDataType = img->wDataType; u12image_GetImageInfo( dev, img ); dev->scan.lBufferAdjust = (long)dev->DataInf.dwAppBytesPerLine; DBG( _DBG_INFO, "* Scan settings:\n" ); DBG( _DBG_INFO, "* ImageInfo: (x=%u,y=%u,dx=%u,dy=%u)\n", dev->DataInf.crImage.x, dev->DataInf.crImage.y, dev->DataInf.crImage.cx, dev->DataInf.crImage.cy ); /* * 0 _DEF_BW_THRESHOLD 255 * +-------------------------+--------------------------------+ * |<------- Black --------->|<----------- White ------------>| * So, if user wish to make image darker, the threshold value should be * higher than _defBwThreshold, otherwise it should lower than the * _DefBwThreshold. * Darker = _DEF_BW_THRESHOLD + White * Input / 127; * Input < 0, and White = 255 - _DEF_BW_THRESHOLD, so * = _DEF_BW_THRESHOLD - (255 - _DEF_BW_THRESHOLD) * Input / 127; * The brighter is the same idea. */ /* CHECK: We have now two methods for setting the brightness... */ DBG( _DBG_INFO, "* brightness = %i\n", dev->DataInf.siBrightness ); if ( dev->DataInf.siBrightness < 0) { brightness = (u_short)(_DEF_BW_THRESHOLD - (255 - _DEF_BW_THRESHOLD) * dev->DataInf.siBrightness /127); } else { brightness = (u_short)(_DEF_BW_THRESHOLD - _DEF_BW_THRESHOLD * dev->DataInf.siBrightness /127); } dev->regs.RD_ThresholdControl = brightness; DBG( _DBG_INFO, "* RD_ThresholdControl = %i\n", brightness ); return 0; } /** PrepareScanningVariables() !!! */ static SANE_Status u12image_SetupScanSettings( U12_Device *dev, ImgDef *img ) { DBG( _DBG_INFO, "u12image_SetupScanSettings()\n" ); wPreviewScanned = 0; dev->scan.dpiIdx = 0; dev->scan.negScan = negScan; imageSetupScanSettings( dev, img ); if( !(dev->DataInf.dwScanFlag & _SCANDEF_TPA )) { dev->scan.dwScanOrigin = dev->adj.upNormal * 4 + _RFT_SCANNING_ORG; } else if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency) { dev->scan.dwScanOrigin = dev->adj.upPositive * 4 + _POS_SCANNING_ORG; } else { dev->scan.dwScanOrigin = dev->adj.upNegative * 4 + _NEG_SCANNING_ORG; } dev->scan.dwScanOrigin += 64 /*dev->dwModelOriginY*/; if( dev->DataInf.xyAppDpi.y <= 75 ) { if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) { dev->scan.bDiscardAll = 0; dev->DataInf.xyPhyDpi.y = 150; dev->shade.intermediate |= _ScanMode_AverageOut; u12image_SetupScanStateVariables( dev, 1 ); dev->scan.gd_gk.wGreenDiscard = 0; if( dev->DataInf.xyAppDpi.y >= 38 ) dev->scan.bd_rk.wBlueDiscard = 1; else dev->scan.bd_rk.wBlueDiscard = 0; if( dev->DataInf.wPhyDataType >= COLOR_256GRAY ) { dev->shade.wXStep = 6; dev->shade.wExposure = 8 * dev->shade.wXStep; } } else { if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA) && (dev->DataInf.xyAppDpi.y <= 50) && (dev->DataInf.wPhyDataType >= COLOR_TRUE24)) { dev->shade.intermediate |= _ScanMode_AverageOut; } if((dev->DataInf.wPhyDataTypef0_8_16 || (dev->shade.intermediate & _ScanMode_AverageOut)) { dev->scan.bDiscardAll = 1; dev->DataInf.xyPhyDpi.y = 75; u12image_SetupScanStateVariables( dev, 0 ); } else { dev->scan.bDiscardAll = 2; dev->DataInf.xyPhyDpi.y = 150; u12image_SetupScanStateVariables( dev, 1 ); } } } else { if( dev->DataInf.xyAppDpi.y <= 150 ) { dev->scan.bDiscardAll = 2; dev->DataInf.xyPhyDpi.y = 150; u12image_SetupScanStateVariables( dev, 1 ); } else if( dev->DataInf.xyAppDpi.y <= 300 ) { dev->scan.bDiscardAll = 4; dev->DataInf.xyPhyDpi.y = 300; u12image_SetupScanStateVariables( dev, 2 ); } else if( dev->DataInf.xyAppDpi.y <= 600 ) { dev->scan.bDiscardAll = 8; dev->DataInf.xyPhyDpi.y = 600; u12image_SetupScanStateVariables( dev, 3 ); } else { dev->scan.bDiscardAll = 16; dev->DataInf.xyPhyDpi.y = 1200; u12image_SetupScanStateVariables( dev, 4 ); } } /* ------- lines to sample or not? ------- */ if( dev->DataInf.xyAppDpi.y == dev->DataInf.xyPhyDpi.y ) { DBG( _DBG_INFO, "* Sample every line\n" ); dev->scan.DoSample = fnEveryLine; } else { if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) { DBG( _DBG_INFO, "* Sample preview\n" ); dev->scan.DoSample = fnSamplePreview; dev->DataInf.wYSum = 150; if( dev->DataInf.xyAppDpi.y >= 38 ) wPreviewScanned = dev->DataInf.xyAppDpi.y * 2; else if( dev->DataInf.xyAppDpi.y >= 19 ) wPreviewScanned = dev->DataInf.xyAppDpi.y * 4; else wPreviewScanned = dev->DataInf.xyAppDpi.y * 8; } else { DBG( _DBG_INFO, "* Sample lines (%u - %u)...\n", dev->DataInf.xyPhyDpi.y, dev->DataInf.xyAppDpi.y ); dev->scan.DoSample = fnSampleLines; dev->DataInf.wYSum = dev->DataInf.xyPhyDpi.y - dev->DataInf.xyAppDpi.y; } } /* now assign the buffer pointers for image aquisition */ dev->scan.p48BitBuf.pb = NULL; if( dev->DataInf.wPhyDataType >= COLOR_TRUE24 ) { u_long r, g, b; r = (u_long)_SIZE_REDFIFO / dev->DataInf.dwAsicBytesPerPlane - dev->scan.bd_rk.wRedKeep; g = (u_long)_SIZE_GREENFIFO / dev->DataInf.dwAsicBytesPerPlane - dev->scan.gd_gk.wGreenKeep; if((int)r < 16 || (int)g < 16) { b = (u_long)(dev->scan.bd_rk.wRedKeep + dev->scan.gd_gk.wGreenKeep + 2U) * dev->DataInf.dwAsicBytesPerPlane; DBG( _DBG_INFO, "48Bit buffer request: " "len=%lu bytes, available=%lu\n", b, _SIZE_TOTAL_BUF_TPA ); if( b > _SIZE_TOTAL_BUF_TPA ) { DBG( _DBG_ERROR, "Not that much FIFO memory available!\n" ); return SANE_STATUS_NO_MEM; } dev->scan.p48BitBuf.pb = dev->bufs.b1.pReadBuf; } } if( dev->scan.p48BitBuf.pb ){ dev->scan.DataRead = fnReadToDriver; dev->scan.BufGet.red.bp = dev->scan.BufPut.red.bp = dev->scan.BufBegin.red.bp = dev->scan.p48BitBuf.pb; dev->scan.BufEnd.red.bp = dev->scan.BufBegin.green.bp = dev->scan.BufGet.green.bp = dev->scan.BufPut.green.bp = dev->scan.p48BitBuf.pb + dev->DataInf.dwAsicBytesPerLine * (dev->scan.bd_rk.wRedKeep + 1U); dev->scan.BufEnd.green.bp = dev->scan.BufBegin.green.bp + dev->DataInf.dwAsicBytesPerLine * (dev->scan.gd_gk.wGreenKeep + 1U); dev->scan.BufPut.blue.bp = dev->scan.BufGet.blue.bp = dev->bufs.b1.pReadBuf + dev->DataInf.dwAsicBytesPerLine * 2; } else { dev->scan.DataRead = fnReadOutScanner; dev->scan.BufPut.red.bp = dev->bufs.b1.pReadBuf; dev->scan.BufData.green.bp = dev->scan.BufPut.green.bp = dev->scan.BufPut.red.bp + dev->DataInf.dwAsicBytesPerLine; dev->scan.BufPut.blue.bp = dev->scan.BufPut.green.bp + dev->DataInf.dwAsicBytesPerLine; dev->scan.BufData.red.bp = dev->scan.BufPut.red.bp; dev->scan.BufData.blue.bp = dev->scan.BufPut.blue.bp; } /* CHECK: maybe remove this stuff */ #if 0 if( ps->DataInf.dwScanFlag & _SCANDEF_Transparency) { posScan[1].exposureTime = 96; posScan[1].xStepTime = 12; posScan[2].exposureTime = 96; posScan[2].xStepTime = 24; posScan[3].exposureTime = 96; posScan[3].xStepTime = 48; posScan[4].exposureTime = 96; posScan[4].xStepTime = 96; /* Reset shading Exposure Time & xStep Time */ ps->Shade.wExposure = posScan[ps->Scan.dpiIdx].exposureTime; ps->Shade.wXStep = posScan[ps->Scan.dpiIdx].xStepTime; } else if( ps->DataInf.dwScanFlag & _SCANDEF_Negative) { ps->Scan.negScan[1].exposureTime = 96; ps->Scan.negScan[1].xStepTime = 12; ps->Scan.negScan[2].exposureTime = 96; ps->Scan.negScan[2].xStepTime = 24; ps->Scan.negScan[3].exposureTime = 96; ps->Scan.negScan[3].xStepTime = 48; ps->Scan.negScan[4].exposureTime = 96; ps->Scan.negScan[4].xStepTime = 96; /* Reset shading Exposure Time & xStep Time */ ps->Shade.wExposure = ps->Scan.negScan[ps->Scan.dpiIdx].exposureTime; ps->Shade.wXStep = ps->Scan.negScan[ps->Scan.dpiIdx].xStepTime; } #endif return SANE_STATUS_GOOD; } /** */ static SANE_Bool u12image_DataIsReady( U12_Device *dev, void* buf ) { DBG( _DBG_READ, "* DataIsReady()\n" ); if( dev->scan.bDiscardAll ) { dev->scan.bDiscardAll--; if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { dev->regs.RD_ModeControl = _ModeFifoGSel; u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf, dev->DataInf.dwAsicBytesPerPlane ); } else { u12io_ReadColorData( dev, dev->bufs.b1.pReadBuf, dev->DataInf.dwAsicBytesPerPlane ); } return SANE_FALSE; } if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) { dev->regs.RD_ModeControl = _ModeFifoGSel; u12io_ReadMonoData( dev, buf, dev->DataInf.dwAsicBytesPerPlane ); } else { if( !dev->scan.DataRead( dev )) { return SANE_FALSE; } } if( dev->scan.DoSample( dev )) { /* direct is done here without copying...*/ if( fnDataDirect != dev->scan.DataProcess ) { (*dev->scan.DataProcess)(dev, buf, (void*)(dev->scan.BufPut.red.bp), dev->DataInf.dwAppPhyBytesPerLine); } return SANE_TRUE; } return SANE_FALSE; } /** */ static SANE_Status u12image_ReadOneImageLine( U12_Device *dev, void* buf ) { SANE_Byte b, state; TimerDef timer, t2; DBG( _DBG_READ, "u12image_ReadOneImageLine()\n" ); u12io_StartTimer( &timer, _LINE_TIMEOUT ); u12io_StartTimer( &t2, _SECOND*2 ); do { state = u12io_GetScanState( dev ); dev->scan.bNowScanState = (state & _SCANSTATE_MASK); if( state & _SCANSTATE_STOP ) { DBG( _DBG_READ, "* SCANSTATE_STOP\n" ); u12motor_ModuleForwardBackward( dev ); if( u12io_GetFifoLength( dev ) >= dev->scan.dwMinReadFifo ) if( u12image_DataIsReady( dev, buf )) return SANE_STATUS_GOOD; } else { dev->scan.bModuleState = _MotorInNormalState; b = dev->scan.bNowScanState - dev->scan.oldScanState; if((char) b < 0) b += _NUMBER_OF_SCANSTEPS; if( b >= dev->scan.bRefresh ) { u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); dev->scan.oldScanState = u12io_GetScanState( dev ); dev->scan.oldScanState &= _SCANSTATE_MASK; } if( u12io_GetFifoLength( dev ) >= dev->scan.dwMaxReadFifo ) { if( u12image_DataIsReady( dev, buf )) return SANE_STATUS_GOOD; } else { b = dev->scan.bNowScanState - dev->scan.oldScanState; if((char) b < 0) b += _NUMBER_OF_SCANSTEPS; if( b >= dev->scan.bRefresh ) { u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE ); dev->scan.oldScanState = u12io_GetScanState( dev ); dev->scan.oldScanState &= _SCANSTATE_MASK; } if( u12io_GetFifoLength( dev ) >= dev->scan.dwMinReadFifo ) { if( u12image_DataIsReady( dev, buf )) return SANE_STATUS_GOOD; } } } } while( !u12io_CheckTimer( &timer )); DBG( _DBG_ERROR, "Timeout - Scanner malfunction !!\n" ); u12motor_ToHomePosition( dev, SANE_TRUE ); /* timed out, scanner malfunction */ return SANE_STATUS_IO_ERROR; } /** */ static void u12image_PrepareScaling( U12_Device *dev ) { int step; double ratio; dev->scaleBuf = NULL; DBG( _DBG_INFO, "APP-DPIX=%u, MAX-DPIX=%u\n", dev->DataInf.xyAppDpi.x, dev->dpi_max_x ); if( dev->DataInf.xyAppDpi.x > dev->dpi_max_x ) { dev->scaleBuf = malloc( dev->DataInf.dwAppBytesPerLine ); ratio = (double)dev->DataInf.xyAppDpi.x/(double)dev->dpi_max_x; dev->scaleIzoom = (int)(1.0/ratio * 1000); switch( dev->DataInf.wAppDataType ) { case COLOR_BW : step = 0; break; case COLOR_256GRAY : step = 1; break; case COLOR_TRUE24 : step = 3; break; case COLOR_TRUE42 : step = 6; break; default : step = 99; break; } dev->scaleStep = step; DBG( _DBG_INFO, "u12image_PrepareScaling: izoom=%i, step=%u\n", dev->scaleIzoom, step ); } else { DBG( _DBG_INFO, "u12image_PrepareScaling: DISABLED\n" ); } } /** scaling picture data in x-direction, using a DDA algorithm * (digital differential analyzer). */ static void u12image_ScaleX( U12_Device *dev, SANE_Byte *ib, SANE_Byte *ob ) { SANE_Byte tmp; int ddax; u_long i, j, x; /* when not supported, only copy the data */ if( 99 == dev->scaleStep ) { memcpy( ob, ib, dev->DataInf.dwAppBytesPerLine ); return; } /* now scale... */ if( 0 == dev->scaleStep ) { /* binary scaling */ ddax = 0; x = 0; memset( ob, 0, dev->DataInf.dwAppBytesPerLine ); for( i = 0; i < dev->DataInf.dwPhysBytesPerLine*8; i++ ) { ddax -= 1000; while( ddax < 0 ) { tmp = ib[(i>>3)]; if((x>>3) < dev->DataInf.dwAppBytesPerLine ) { if( 0 != (tmp &= (1 << ((~(i & 0x7))&0x7)))) ob[x>>3] |= (1 << ((~(x & 0x7))&0x7)); } x++; ddax += dev->scaleIzoom; } } } else { /* color and gray scaling */ ddax = 0; x = 0; for( i = 0; i < dev->DataInf.dwPhysBytesPerLine*dev->scaleStep; i+=dev->scaleStep ) { ddax -= 1000; while( ddax < 0 ) { for( j = 0; j < (u_long)dev->scaleStep; j++ ) { if((x+j) < dev->DataInf.dwAppBytesPerLine ) { ob[x+j] = ib[i+j]; } } x += dev->scaleStep; ddax += dev->scaleIzoom; } } } } /* END U12_IMAGE.C ..........................................................*/ sane-backends-1.0.27/backend/dc25.h0000664000175000017500000001734712775312260013540 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. dc25.h 6/1/98 This file (C) 1998 Peter Fales This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for the Kodak DC-25 (and probably the DC-20) digital cameras. THIS IS EXTREMELY ALPHA CODE! USE AT YOUR OWN RISK!! (feedback to: dc25-devel@fales-lorenz.net) This backend is based heavily on the dc20ctrl package by Ugo Paternostro . I've attached his header below: *************************************************************************** * Copyright (C) 1998 Ugo Paternostro * * This file is part of the dc20ctrl package. The complete package can be * downloaded from: * http://aguirre.dsi.unifi.it/~paterno/binaries/dc20ctrl.tar.gz * * This package is derived from the dc20 package, built by Karl Hakimian * that you can find it at ftp.eecs.wsu.edu in the * /pub/hakimian directory. The complete URL is: * ftp://ftp.eecs.wsu.edu/pub/hakimian/dc20.tar.gz * * This package also includes a sligthly modified version of the Comet to ppm * conversion routine written by YOSHIDA Hideki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ***************************************************************************/ #include #include #include #include #include #include #ifndef TRUE #define TRUE (1==1) #endif #ifndef FALSE #define FALSE (!TRUE) #endif #ifndef NULL #define NULL 0L #endif typedef struct dc20_info_s { unsigned char model; unsigned char ver_major; unsigned char ver_minor; int pic_taken; int pic_left; struct { unsigned int low_res:1; unsigned int low_batt:1; } flags; } Dc20Info, *Dc20InfoPtr; static Dc20Info *get_info (int); #define INIT_PCK {0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^^^^^^^ * Baud rate: (see pkt_speed structure) * 0x96 0x00 -> 9600 baud * 0x19 0x20 -> 19200 baud * 0x38 0x40 -> 38400 baud * 0x57 0x60 -> 57600 baud * 0x11 0x52 -> 115200 baud */ #define INFO_PCK {0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define SHOOT_PCK {0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define ERASE_PCK {0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} #define RES_PCK {0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * Resolution: 0x00 = high, 0x01 = low */ #define THUMBS_PCK {0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * Thumbnail number */ #define PICS_PCK {0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A} /* ^^^^ * Picture number */ struct pkt_speed { speed_t baud; unsigned char pkt_code[2]; }; #define DEFAULT_TTY_BAUD B38400 #define HIGH_RES 0 #define LOW_RES 1 /* * Image parameters */ #define LOW_CAMERA_HEADER 256 #define HIGH_CAMERA_HEADER 512 #define CAMERA_HEADER(r) ( (r) ? LOW_CAMERA_HEADER : HIGH_CAMERA_HEADER ) #define LOW_WIDTH 256 #define HIGH_WIDTH 512 #define WIDTH(r) ( (r) ? LOW_WIDTH : HIGH_WIDTH ) #define HEIGHT 243 #define LEFT_MARGIN 1 #define LOW_RIGHT_MARGIN 5 #define HIGH_RIGHT_MARGIN 10 #define RIGHT_MARGIN(r) ( (r) ? LOW_RIGHT_MARGIN : HIGH_RIGHT_MARGIN ) #define TOP_MARGIN 1 #define BOTTOM_MARGIN 1 #define BLOCK_SIZE 1024 #define LOW_BLOCKS 61 #define HIGH_BLOCKS 122 #define BLOCKS(r) ( (r) ? LOW_BLOCKS : HIGH_BLOCKS ) #define LOW_IMAGE_SIZE ( LOW_BLOCKS * BLOCK_SIZE ) #define HIGH_IMAGE_SIZE ( HIGH_BLOCKS * BLOCK_SIZE ) #define IMAGE_SIZE(r) ( (r) ? LOW_IMAGE_SIZE : HIGH_IMAGE_SIZE ) #define MAX_IMAGE_SIZE ( HIGH_IMAGE_SIZE ) /* * Comet file */ #define COMET_MAGIC "COMET" #define COMET_HEADER_SIZE 128 #define COMET_EXT "cmt" /* * Pixmap structure */ struct pixmap { int width; int height; int components; unsigned char *planes; }; /* * Rotations */ #define ROT_STRAIGHT 0x00 #define ROT_LEFT 0x01 #define ROT_RIGHT 0x02 #define ROT_HEADDOWN 0x03 #define ROT_MASK 0x03 /* * File formats */ #define SAVE_RAW 0x01 #define SAVE_GREYSCALE 0x02 #define SAVE_24BITS 0x04 #define SAVE_FILES 0x07 #define SAVE_FORMATS 0x38 #define SAVE_ADJASPECT 0x80 /* * External definitions */ extern char *__progname; /* Defined in /usr/lib/crt0.o */ #include FILE * sanei_config_open (const char *filename); char *sanei_config_read (char *str, int n, FILE * stream); static int init_dc20 (char *, speed_t); static void close_dc20 (int); static int read_data (int fd, unsigned char *buf, int sz); static int end_of_data (int fd); static int set_pixel_rgb (struct pixmap *, int, int, unsigned char, unsigned char, unsigned char); static struct pixmap *alloc_pixmap (int x, int y, int d); static void free_pixmap (struct pixmap *p); static int zoom_x (struct pixmap *source, struct pixmap *dest); static int zoom_y (struct pixmap *source, struct pixmap *dest); static int comet_to_pixmap (unsigned char *, struct pixmap *); sane-backends-1.0.27/backend/lexmark_models.c0000664000175000017500000001001612617742237015774 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2006-2010 Stéphane Voltz Copyright (C) 2010 "Torsten Houwaart" X74 support This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ static Lexmark_Model model_list[] = { { 0x043d, /* vendor id */ 0x007c, /* product id */ 0xb2, /* submodel id */ "Lexmark X1100", /* name */ "Lexmark", /* vendor */ "X1100/rev. B2", /* model */ X1100_MOTOR, /* X1100 series has 2 sensors */ X1100_B2_SENSOR, 1235, /* first x-coordinate of Home Point */ 1258}, /* second x-coordinate of Home Point */ { 0x043d, /* vendor id */ 0x007c, /* product id */ 0x2c, /* submodel id */ "Lexmark X1100", /* name */ "Lexmark", /* vendor */ "X1100/rev. 2C", /* model */ A920_MOTOR, /* X1100 series has 2 sensors, 2C or B2. It is detected at sane_open() */ X1100_2C_SENSOR, 1235, /* first x-coordinate of Home Point */ 1258}, /* second x-coordinate of Home Point */ { 0x413c, /* vendor id */ 0x5105, /* product id */ 0x2c, /* submodel id */ "Dell A920", /* name */ "Dell", /* vendor */ "A920", /* model */ A920_MOTOR, A920_SENSOR, 1235, /* first x-coordinate of Home Point */ 1258}, /* second x-coordinate of Home Point */ { 0x043d, /* vendor id */ 0x007d, /* product id */ 0x87, /* submodel id */ "Lexmark X1200", /* name */ "Lexmark", /* vendor */ "X1200/USB1.1", /* model */ A920_MOTOR, X1200_SENSOR, 1235, /* first x-coordinate of Home Point */ 1258}, /* second x-coordinate of Home Point */ { 0x043d, /* vendor id */ 0x007d, /* product id */ 0x97, /* submodel id */ "Lexmark X1200", /* name */ "Lexmark", /* vendor */ "X1200/USB2.0", /* model */ A920_MOTOR, X1200_USB2_SENSOR, 1235, /* first x-coordinate of Home Point */ 1258}, /* second x-coordinate of Home Point */ { 0x043d, /* vendor id */ 0x0060, /* product id */ 0x00, /* submodel id */ "Lexmark X74", /* name */ "Lexmark", /* vendor */ "X74", /* model */ X74_MOTOR, X74_SENSOR, 1222, /* first x-coordinate of Home Point */ 1322}, /* second x-coordinate of Home Point */ { /* termination model, must be last */ 0, 0, 0, NULL, NULL, NULL, 0, 0, 0, 0} }; /* end models description */ sane-backends-1.0.27/backend/s9036.h0000664000175000017500000000422712112021330013534 00000000000000/* sane - Scanner Access Now Easy. This file (C) 1997 Ingo Schneider This file is part of the SANE package. SANE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SANE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with sane; see the file COPYING. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef s9036_h #define s9036_h enum S9036_Option { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, OPT_DEPTH, OPT_RESOLUTION, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_BRIGHT_ADJUST, OPT_CONTR_ADJUST, /* must come last: */ NUM_OPTIONS }; typedef struct S9036_Device { struct S9036_Device *next; SANE_Device sane; SANE_Handle handle; } S9036_Device; typedef struct S9036_Scanner { /* all the state needed to define a scan request: */ SANE_Option_Descriptor opt[NUM_OPTIONS]; SANE_Word val[NUM_OPTIONS]; /* Parsed option values and variables that are valid only during actual scanning: */ SANE_Bool scanning; SANE_Parameters params; size_t bufsize; /* about SCSI_MAX_REQUEST_SIZE */ SANE_Byte *buffer; /* buffer of size 'bufsize' */ SANE_Byte *bufstart; /* Start of data for next read */ size_t in_buffer; /* bytes already in buffer */ int lines_in_scanner; /* Lines in scanner memory */ int lines_read; /* Total lines read for now */ int fd; /* SCSI filedescriptor */ /* scanner dependent/low-level state: */ S9036_Device *hw; } S9036_Scanner; #endif /* s9036_h */ sane-backends-1.0.27/backend/dmc.conf.in0000664000175000017500000000001412112021330014604 00000000000000/dev/camera sane-backends-1.0.27/backend/pieusb_scancmd.h0000664000175000017500000004475413106201017015746 00000000000000/* sane - Scanner Access Now Easy. pieusb_scancmd.h Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIEUSB_SCANCMD_H #define PIEUSB_SCANCMD_H #include "../include/sane/sane.h" /* ========================================================================= * * Data-structures used by scanner commands * * For SENSE descriptions, see SCSI-2 p158, table 67 (p469 ASC/Q alphabetically) * For the INQUIRY command, see SCSI-2 p141 table 45, 46, 47 * * 2-byte short ints are represented by 4-byte SANE_Int types * * ========================================================================= */ struct Pieusb_Scanner_Properties { SANE_Byte deviceType; /* 0x06 = scanner */ SANE_Byte additionalLength; /* including this byte: 0xb4 = 180, so total structure 184 bytes */ SANE_Char vendor[9]; /* actually 8 bytes, not null-terminated ...PIE ... */ SANE_Char product[17]; /* actually 16 bytes, null-terminated ...SF Scanner... */ SANE_Char productRevision[5]; /* actually 4 bytes, not null-terminated ...1.70... */ /* 1st Vendor-specific block, 20 bytes, see pie_get_inquiry_values(), partially: */ SANE_Int maxResolutionX; /* 7200 maximum scan resolution in x direction */ SANE_Int maxResolutionY; /* 7200 maximum scan resolution in y direction */ SANE_Int maxScanWidth; /* 10680 flatbed_max_scan_width (& calibration block size) */ SANE_Int maxScanHeight; /* 6888 flatbed_max_scan_height */ SANE_Byte filters; /* 0x9e = 10011110 ?-0-0-OnePassColor-B-G-R-N => additional infrared? */ SANE_Byte colorDepths; /* 0x35 = 00110101 0-0-16-12-10-8-4-1 */ SANE_Byte colorFormat; /* 0x07 = 00000111 0-0-0-0-0-Index-Line-Pixel */ SANE_Byte imageFormat; /* 0x09 = 00001001 0-0-0-0-OKLine-BlkOne-Motorola-Intel */ SANE_Byte scanCapability; /* 0x4b = 01001011 PowerSave-ExtCal-0-FastPreview-DisableCal-[CalSpeeds=3] * PowerSave: no * ExtCal: yes => * FastPreview: no * DisableCal: yes => can calibration be disabled? * CalSpeeds: 3 => 1 line, 13 lines, 31 lines */ SANE_Byte optionalDevices; /* 0x61 = 01100001 MultiPageLoad-?-?-0-0-TransModule1-TransModule-AutoDocFeeder => additional? * MultiPageLoad: no * ?: yes * ?: yes * TransModule1: no * TransModule: no * AutoDocFeeder: yes */ SANE_Byte enhancements; /* 0x02 = no info in pie.c */ SANE_Byte gammaBits; /* 0x0c = 00001100 = 12 ? used when downloading gamma table ... does not happen */ SANE_Byte lastFilter; /* 0x00 = ? no info in pie.c, not used */ SANE_Int previewScanResolution; /* 0x2c01 = 300 fast preview scan resolution */ /* Reserved (56-95) */ /* SANE_Byte div_56[40]; */ /* 2nd vendor specific block (36 bytes at offset 96) */ SANE_Char firmwareVersion[5]; /* actually 4 bytes, not null terminated "1.05" */ SANE_Byte halftones; /* 0x08 = halftones (4 LSbits) = 00001000 ? */ SANE_Byte minumumHighlight; /* 0x64 = 100 */ SANE_Byte maximumShadow; /* 0x64 = 100 */ SANE_Byte calibrationEquation; /* 0x01 ? see pie_perform_cal() */ SANE_Int maximumExposure; /* 0xc409 = 2500 (units?) */ SANE_Int minimumExposure; /* 0x6400 = 100 (units?) */ SANE_Int x0; /* 0xd002 = 720 transparency top left x */ SANE_Int y0; /* 0x8604 = 1158 transparency top left y */ SANE_Int x1; /* 0xbc10 = 4284 transparency bottom right x */ SANE_Int y1; /* 0xc015 = 5568 transparency bottom right y */ SANE_Int model; /* 0x3000 => model number */ /* SANE_Int div_118; 0x0000 meaning? */ SANE_Char production[4]; /* null terminated */ SANE_Char timestamp[20]; /* null terminated */ SANE_Byte signature[40]; /* null terminated */ }; struct Pieusb_Sense { /* 14 bytes according to SCSI-2 p158, table 67 (p469 ASC/Q alphabetically) */ SANE_Byte errorCode; /* 0x70 or 0x71 */ SANE_Byte segment; SANE_Byte senseKey; /* sense key is actually this value & 0x0F - table 69 */ SANE_Byte info[4]; SANE_Byte addLength; /* should be 0x07 (remaining struct length including this byte) */ SANE_Byte cmdInfo[4]; /* command specific information */ SANE_Byte senseCode; /* abbreviated ASC - table 71 */ SANE_Byte senseQualifier; /* abbreviated ASCQ - table 71 */ }; struct Pieusb_Scanner_State { SANE_Byte buttonPushed; /* 0x01 if pushed */ SANE_Byte warmingUp; /* 0x01 if warming up, 0x00 if not */ SANE_Byte scanning; /* bit 6 set if SCAN active, bit 7 motor direction inverted (not analysed in detail) */ }; struct Pieusb_Scan_Parameters { SANE_Int width; /* Number of pixels on a scan line */ SANE_Int lines; /* Number of lines in the scan. Value depends on color format, see Pieusb_Mode. */ SANE_Int bytes; /* Number of bytes on a scan line. Value depends on color format. */ SANE_Byte filterOffset1; /* 0x08 in the logs, but may also be set to 0x16, they seem to be used in “lineâ€-format only. */ SANE_Byte filterOffset2; /* 0x08 in the logs, but may also be set to 0x16, they seem to be used in “lineâ€-format only. */ SANE_Int period; /* Seems to be unused */ SANE_Int scsiTransferRate; /* Don't use, values cannot be trusted */ SANE_Int availableLines; /* The number of currently available scanned lines. Value depends on color format. Returns a value >0 if PARAM is called while scanning is in progress */ SANE_Byte motor; /* Motor direction in bit 0 */ }; struct Pieusb_Mode { /* SANE_Byte size; of remaining data, not useful */ SANE_Int resolution; /* in dpi */ SANE_Byte passes; /* 0x80 = One pass color; 0x90 = One pass RGBI; * bit 7 : one-pass-color bit (equivalent to RGB all set?) * bit 6 & 5: unused * bit 4 : Infrared * bit 3 : Blue * bit 2 : Green * bit 1 : Red * bit 0: Neutral (not supported, ignored) */ SANE_Byte colorDepth; /* 0x04 = 8, 0x20 = 16 bit * bit 7 & 6 : 0 (unused) * bit 5 : 16 bit * bit 4 : 12 bit * bit 3 : 10 bit * bit 2 : 8 bit * bit 1 : 4 bit * bit 0 : 1 bit */ SANE_Byte colorFormat; /* 0x04 = index, cf. INQUIRY * bit 7-3 : 0 (unused) * bit 2 : Index = scanned data are lines preceeded by a two-byte index, 'RR', 'GG', 'BB', or 'II' * bit 1 : Line = scanned data are (probably) lines in RGBI order (needs testing) * bit 0 : Pixel = scanned data are always RGB-pixels, i.e. 3x2 bytes at depth = 16 bits, 3 bytes * at depth = 8 bits, and 3 packed bytes at depth = 1. This is also the case in * a single color or gray scale scan; in these cases only the first pixel contains * valid data. */ SANE_Byte byteOrder; /* 0x01 = Intel; only bit 0 used */ SANE_Bool sharpen; /* byte 9 bit 1 */ SANE_Bool skipShadingAnalysis; /* byte 9 bit 3 */ SANE_Bool fastInfrared; /* byte 9 bit 7 */ /* bit 7 : “fast infrared†flag * bit 6,5,4 : 0 (unused) * bit 3 : “skip calibration†flag (skip collecting shading information) * bit 2 : 0 (unused) * bit 1 : “sharpen†flag (only effective with fastInfrared off, one-pass-color and no extra BADF-entries) * bit 0 : 0 (unused) */ SANE_Byte halftonePattern; /* 0x00 = no halftone pattern */ SANE_Byte lineThreshold; /* 0xFF = 100% */ }; struct Pieusb_Settings { SANE_Int saturationLevel[3]; /* The average pixel values for the three colors Red, Green and Blue, * which are the result of optimizing the Timer 1 counts so that Red and * Blue values are least 90% of full scale (58981) and the Green value is * at least 80% (52428). These levels are only determined during warming up. */ SANE_Int exposureTime[4]; /* Optimized exposure times for Red, Green and Blue. The exposure times are * Timer 1 counts which define when Timer 1 interrupts. These values are * only determined at startup. * Exposure time for Infrared. The value is optimized and set at startup * with the other exposure times. Quite often, it is subsequently reset to * a default value (0x0B79). */ SANE_Word offset[4]; /* Optimized offsets for Red, Green and Blue. See above. These values are * also updated before outputting the CCD-mask. * Element 4 is offset for Infrared. */ SANE_Word gain[4]; /* Optimized gains for Red, Green and Blue. See the remark for * exposureTime above. Element 4 is gain for Infrared. */ SANE_Byte light; /* Current light level. The stability of the light source is tested during * warming up. The check starts with a light value 7 or 6, and decrements * it when the light warms up. At a light value of 4, the scanner produces * stable scans (i.e. successive “white†scan values don't differ more * than 0x200). */ SANE_Int minimumExposureTime; /* Fixed value: 0x0b79 (2937) */ SANE_Byte extraEntries; SANE_Byte doubleTimes; /* Originally 20 unused bytes (uninitialized memory) * To complete the mapping to the Pieusb_Settings_Condensed struct, * the last two bytes are given an explicit meaning. */ /* SANE_Int exposureTimeIR; */ /* SANE_Byte offsetIR; */ /* SANE_Byte gainIR; */ }; /* Not used, Pieusb_Settings contains the same fields (after a bit of juggling) */ struct Pieusb_Settings_Condensed { SANE_Int exposureTime[4]; /* => Pieusb_Settings.exposureTime */ SANE_Byte offset[4]; /* => Pieusb_Settings.offset */ SANE_Byte gain[4]; /* => Pieusb_Settings.gain */ SANE_Byte light; /* => Pieusb_Settings.light */ SANE_Byte extraEntries; /* => Pieusb_Settings.extraEntries */ SANE_Byte doubleTimes; /* => Pieusb_Settings.doubleTimes */ }; struct Pieusb_Halftone_Pattern { SANE_Int code; /* 0x91 */ /*TODO */ }; struct Pieusb_Scan_Frame { SANE_Int index; /* scan frame index (0-7) */ SANE_Int x0; /* top left, is origin */ SANE_Int y0; SANE_Int x1; /* bottom right */ SANE_Int y1; }; struct Pieusb_Exposure_Time_Color { SANE_Int filter; /* color mask 0x02, 0x04 or 0x08 for R, G, B */ SANE_Int value; /* relative exposure time 0 - 100 */ }; struct Pieusb_Exposure_Time { SANE_Int code; /* 0x93 */ SANE_Int size; /* number of bytes in rest of structure */ struct Pieusb_Exposure_Time_Color color[3]; /* not all elements may actually be used */ }; struct Pieusb_Highlight_Shadow_Color { SANE_Int filter; /* color mask 0x02, 0x04 or 0x08 for R, G, B */ SANE_Int value; /* 0-100 */ }; struct Pieusb_Highlight_Shadow { SANE_Int code; /* 0x94 */ SANE_Int size; /* number of bytes in rest of structure */ struct Pieusb_Highlight_Shadow_Color color[3]; }; struct Pieusb_Shading_Parameters_Info { SANE_Byte type; /* 0x00, 0x08, 0x10, 0x20; RGBI(?) */ SANE_Byte sendBits; /* 0x10 = 16 */ SANE_Byte recieveBits; /* 0x10 = 16 */ SANE_Byte nLines; /* 0x2D = 45 */ SANE_Int pixelsPerLine; /* 0x14dc = 5340 */ }; #define SHADING_PARAMETERS_INFO_COUNT 4 struct Pieusb_Shading_Parameters { SANE_Byte code; /* 0x95 */ SANE_Int size; /* number of bytes in rest of structure (0x1c=28) */ SANE_Byte calInfoCount; /* number of individual info structures (=0x04) */ SANE_Byte calInfoSize; /* size of individual info structure (=0x06) */ SANE_Int div_6; /* 0x0004, meaning not clear */ struct Pieusb_Shading_Parameters_Info cal[SHADING_PARAMETERS_INFO_COUNT]; }; typedef enum { PIEUSB_STATUS_GOOD = 0, /* 0 everything A-OK */ PIEUSB_STATUS_UNSUPPORTED, /* 1 operation is not supported */ PIEUSB_STATUS_CANCELLED, /* 2 operation was cancelled */ PIEUSB_STATUS_DEVICE_BUSY, /* 3 device is busy; try again later */ PIEUSB_STATUS_INVAL, /* 4 data is invalid (includes no dev at open) */ PIEUSB_STATUS_EOF, /* 5 no more data available (end-of-file) */ PIEUSB_STATUS_JAMMED, /* 6 document feeder jammed */ PIEUSB_STATUS_NO_DOCS, /* 7 document feeder out of documents */ PIEUSB_STATUS_COVER_OPEN, /* 8 scanner cover is open */ PIEUSB_STATUS_IO_ERROR, /* 9 error during device I/O */ PIEUSB_STATUS_NO_MEM, /* 10 out of memory */ PIEUSB_STATUS_ACCESS_DENIED, /* 11 access to resource has been denied */ PIEUSB_STATUS_WARMING_UP, /* 12 lamp not ready, please retry */ PIEUSB_STATUS_HW_LOCKED, /* 13 scanner mechanism locked for transport */ PIEUSB_STATUS_MUST_CALIBRATE /* 14 */ } PIEUSB_Status; /* Structures used by the USB functions */ struct Pieusb_Command_Status { PIEUSB_Status pieusb_status; SANE_Byte senseKey; /* sense key: see Pieusb_Sense */ SANE_Byte senseCode; /* sense code */ SANE_Byte senseQualifier; /* sense code qualifier */ }; typedef struct Pieusb_Scanner_Properties Pieusb_Scanner_Properties; typedef enum { SLIDE_NEXT = 0x04, SLIDE_PREV = 0x05, SLIDE_INIT = 0x10, SLIDE_RELOAD = 0x40 } slide_action; void sanei_pieusb_cmd_slide(SANE_Int device_number, slide_action action, struct Pieusb_Command_Status *status); /* Scanner commands */ void sanei_pieusb_cmd_test_unit_ready(SANE_Int device_number, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_sense(SANE_Int device_number, struct Pieusb_Sense* sense, struct Pieusb_Command_Status *status, PIEUSB_Status *ret); void sanei_pieusb_cmd_get_halftone_pattern(SANE_Int device_number, SANE_Int index, struct Pieusb_Halftone_Pattern* pattern, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_set_halftone_pattern(SANE_Int device_number, SANE_Int index, struct Pieusb_Halftone_Pattern* pattern, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_scan_frame(SANE_Int device_number, SANE_Int index, struct Pieusb_Scan_Frame* frame, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_set_scan_frame(SANE_Int device_number, SANE_Int index, struct Pieusb_Scan_Frame* frame, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_17(SANE_Int device_number, SANE_Int value, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_exposure_time(SANE_Int device_number, SANE_Int colorbits, struct Pieusb_Exposure_Time* time, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_set_exposure_time(SANE_Int device_number, struct Pieusb_Exposure_Time* time, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_highlight_shadow(SANE_Int device_number, SANE_Int colorbits, struct Pieusb_Highlight_Shadow* hgltshdw, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_set_highlight_shadow(SANE_Int device_number, struct Pieusb_Highlight_Shadow* hgltshdw, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_shading_parms(SANE_Int device_number, struct Pieusb_Shading_Parameters_Info* shading, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_scanned_lines(SANE_Int device_number, SANE_Byte* data, SANE_Int lines, SANE_Int size, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_ccd_mask(SANE_Int device_number, SANE_Byte* mask, SANE_Int mask_size, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_set_ccd_mask(SANE_Int device_number, SANE_Byte colorbits, SANE_Byte* mask, SANE_Int mask_size, struct Pieusb_Command_Status *status); /* void cmdPrepareHalftonePattern(SANE_Int device_number, SANE_Int index, struct Pieusb_Command_Status *status); void cmdPrepareScanFrame(SANE_Int device_number, SANE_Int index, struct Pieusb_Command_Status *status); void cmdPrepareRelativeExposureTime(SANE_Int device_number, SANE_Int colorbits, struct Pieusb_Command_Status *status); void cmdPrepareHighlightShadow(SANE_Int device_number, SANE_Int colorbits, struct Pieusb_Command_Status *status); void cmdPrepareShadingParameters(SANE_Int device_number, struct Pieusb_Command_Status *status); */ void sanei_pieusb_cmd_get_parameters(SANE_Int device_number, struct Pieusb_Scan_Parameters* parameters, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_inquiry(SANE_Int device_number, struct Pieusb_Scanner_Properties* inq, SANE_Byte size, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_mode(SANE_Int device_number, struct Pieusb_Mode* mode, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_set_mode(SANE_Int device_number, struct Pieusb_Mode* mode, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_start_scan(SANE_Int device_number, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_stop_scan(SANE_Int device_number, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_set_scan_head(SANE_Int device_number, SANE_Int mode, SANE_Int steps, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_get_gain_offset(SANE_Int device_number, struct Pieusb_Settings* settings, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_set_gain_offset(SANE_Int device_number, struct Pieusb_Settings* settings, struct Pieusb_Command_Status *status); void sanei_pieusb_cmd_read_state(SANE_Int device_number, struct Pieusb_Scanner_State* state, struct Pieusb_Command_Status *status); #endif /* PIEUSB_SCANCMD_H */ sane-backends-1.0.27/backend/teco2.c0000664000175000017500000026640112112021330013763 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002-2003 Frank Zago (sane at zago dot net) Copyright (C) 2003-2008 Gerard Klaver (gerard at gkall dot hobby dot nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ TECO scanner VM3575, VM656A, VM6575, VM6586, VM356A, VM3564 update 2003/02/14, Patch for VM356A Gerard Klaver update 2003/03/19, traces, tests VM356A Gerard Klaver, Michael Hoeller update 2003/07/19, white level calibration, color modes VM3564, VM356A, VM3575 Gerard Klaver, Michael Hoeller update 2004/01/15, white level , red, green, and blue calibration and leave out highest and lowest value and then divide VM3564, VM356A and VM3575: Gerard Klaver update 2004/08/04, white level, red, green and blue calibration for the VM6575 changed default SANE_TECO_CAL_ALGO to 1 for VM3564 and VM6575 preview value changed to 75 dpi for VM6575 leave out highest and lowest value and then divide VM656A, VM6586 update 2004/08/05, use of SANE_VALUE_SCAN_MODE_LINEART, _GRAY, and _COLOR, changed use of %d to %ld (when bytes values are displayed) update 2005/03/04, use of __sane_unused__ update 2005/07/29. Removed using teco_request_sense (dev) routine for VM3564 update 2008/01/12, Update teco_request_sense routine due to no init value for size. */ /*--------------------------------------------------------------------------*/ #define BUILD 10 /* 2008/01/12 */ #define BACKEND_NAME teco2 #define TECO2_CONFIG_FILE "teco2.conf" /*--------------------------------------------------------------------------*/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "teco2.h" /* This is used to debug the backend without having the real hardware. */ #undef sim #ifdef sim #define sanei_scsi_cmd2(a, b, c, d, e, f, g) SANE_STATUS_GOOD #define sanei_scsi_open(a, b, c, d) 0 #define sanei_scsi_cmd(a, b, c, d, e) SANE_STATUS_GOOD #define sanei_scsi_close(a) SANE_STATUS_GOOD #endif /* For debugging purposes: output a stream straight out from the * scanner without reordering the colors, 0=normal, 1 = raw. */ static int raw_output = 0; /*--------------------------------------------------------------------------*/ /* Lists of possible scan modes. */ static SANE_String_Const scan_mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; /*--------------------------------------------------------------------------*/ /* List of color dropout. */ static SANE_String_Const filter_color_list[] = { "Red", "Green", "Blue", NULL }; static const int filter_color_val[] = { 0, 1, 2 }; /*--------------------------------------------------------------------------*/ /* List of dithering options. */ static SANE_String_Const dither_list[] = { "Line art", "2x2", "3x3", "4x4 bayer", "4x4 smooth", "8x8 bayer", "8x8 smooth", "8x8 horizontal", "8x8 vertical", NULL }; static const int dither_val[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; /*--------------------------------------------------------------------------*/ static const SANE_Range threshold_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ static const SANE_Range red_level_range = { 0, /* minimum */ 64, /* maximum */ 1 /* quantization */ }; /*--------------------------------------------------------------------------*/ static const SANE_Range green_level_range = { 0, /* minimum */ 64, /* maximum */ 1 /* quantization */ }; /*--------------------------------------------------------------------------*/ static const SANE_Range blue_level_range = { 0, /* minimum */ 64, /* maximum */ 1 /* quantization */ }; /*--------------------------------------------------------------------------*/ /* Gamma range */ static const SANE_Range gamma_range = { 0, /* minimum */ 255, /* 255 maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ static const struct dpi_color_adjust vm3564_dpi_color_adjust[] = { /*dpi, color sequence R G or B, 0 (-) or 1 (+) color skewing, lines skewing */ {25, 1, 0, 2, 0, 0}, {50, 1, 2, 0, 0, 1}, {75, 1, 0, 2, 1, 1}, {150, 1, 0, 2, 1, 2}, {225, 1, 0, 2, 1, 3}, {300, 1, 0, 2, 1, 4}, {375, 1, 0, 2, 1, 5}, {450, 1, 0, 2, 1, 6}, {525, 1, 0, 2, 1, 7}, {600, 1, 0, 2, 1, 8}, /* must be the last entry */ {0, 0, 0, 0, 0, 0} }; /* Used for VM356A only */ static const struct dpi_color_adjust vm356a_dpi_color_adjust[] = { /* All values with ydpi > 300 result in a wrong proportion for */ /* the scan. The proportion can be adjusted with the following */ /* command: convert -geometry (dpi/max_xdpi * 100%)x100% */ /* max_xdpi is for the vm356a constant with 300 dpi */ /* e.g. 600dpi adjust with: convert -geometry 200%x100% */ /* All resolutions in increments of 25 are testede, only the shown */ /* bring back good results */ /*dpi, color sequence R G or B, 0 (-) or 1 (+) color skewing, lines skewing */ {25, 1, 0, 2, 0, 0}, {50, 1, 2, 0, 0, 1}, {75, 1, 0, 2, 1, 1}, {150, 1, 0, 2, 1, 2}, {225, 1, 0, 2, 1, 3}, {300, 1, 0, 2, 1, 4}, {375, 1, 0, 2, 1, 5}, {450, 1, 0, 2, 1, 6}, {525, 1, 0, 2, 1, 7}, {600, 1, 0, 2, 1, 8}, /* must be the last entry */ {0, 0, 0, 0, 0, 0} }; /* Used for the VM3575 only */ static const struct dpi_color_adjust vm3575_dpi_color_adjust[] = { /* All values with ydpi > 300 result in a wrong proportion for */ /* the scan. The proportion can be adjusted with the following */ /* command: convert -geometry (dpi/max_xdpi * 100%)x100% */ /* max_xdpi is for the vm3575 constant with 300 dpi */ /* e.g. 600dpi adjust with: convert -geometry 200%x100% */ {50, 2, 0, 1, 1, 1}, {60, 2, 1, 0, 0, 2}, /* {75, 2, 0, 1, 1, 2}, NOK, effects in scan, also with twain driver*/ {100, 2, 1, 0, 0, 3}, {120, 2, 0, 1, 1, 3}, {150, 2, 0, 1, 1, 4}, /* {180, 2, 1, 0, 0, 4}, NOK, skewing problem*/ {225, 2, 0, 1, 1, 6}, {300, 2, 0, 1, 1, 8}, {375, 2, 0, 1, 1, 10}, {450, 2, 0, 1, 1, 12}, {525, 2, 0, 1, 1, 14}, {600, 2, 0, 1, 1, 16}, /* must be the last entry */ {0, 0, 0, 0, 0, 0} }; static const struct dpi_color_adjust vm656a_dpi_color_adjust[1] = { {0, 0, 1, 2, 0, 0} }; static const struct dpi_color_adjust vm6575_dpi_color_adjust[] = { {75, 1, 0, 2, 1, 1}, {150, 1, 0, 2, 1, 2}, {300, 1, 0, 2, 1, 4}, {600, 1, 0, 2, 1, 8}, }; static const struct dpi_color_adjust vm6586_dpi_color_adjust[] = { {25, 1, 0, 2, 1, 0}, {40, 1, 0, 2, 1, 0}, {50, 1, 0, 2, 1, 0}, {75, 1, 2, 0, 0, 1}, {150, 1, 0, 2, 1, 1}, {160, 1, 0, 2, 1, 1}, {175, 1, 0, 2, 1, 1}, {180, 1, 0, 2, 1, 1}, {300, 1, 0, 2, 1, 2}, {320, 1, 0, 2, 1, 2}, {325, 1, 0, 2, 1, 2}, {450, 1, 0, 2, 1, 3}, {460, 1, 0, 2, 1, 3}, {600, 1, 0, 2, 1, 4}, {620, 1, 0, 2, 1, 6}, {625, 1, 0, 2, 1, 6}, {750, 1, 0, 2, 1, 12}, {760, 1, 0, 2, 1, 12}, {900, 1, 0, 2, 1, 12}, {1050, 1, 0, 2, 1, 15}, {1200, 1, 0, 2, 1, 15}, /* must be the last entry */ {0, 0, 0, 0, 0, 0} }; static const struct dpi_color_adjust default_dpi_color_adjust[1] = { {0, 0, 1, 2, 0, 0} }; /* For all scanners. Must be reasonable (eg. between 50 and 300) and * appear in the ...._dpi_color_adjust list of all supported scanners. */ #define DEF_RESOLUTION 150 /*--------------------------------------------------------------------------*/ /* Define the supported scanners and their characteristics. */ static const struct scanners_supported scanners[] = { {6, "TECO VM3564", TECO_VM3564, "Relisys", "AVEC II S3", {1, 600, 1}, /* resolution */ 300, 600, /* max x and Y resolution */ 2550, 12, 3, 1, /* calibration */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm3564_dpi_color_adjust}, {6, "TECO VM356A", TECO_VM356A, "Relisys", "APOLLO Express 3", {1, 600, 1}, /* resolution */ 300, 600, /* max x and Y resolution */ 2550, 12, 3, 1, /* calibration */ /* dots/inch * x-length, calibration samples, tot.bytes for 3 colors, default SANE_TECO2_CAL_ALGO value */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm356a_dpi_color_adjust}, {6, "TECO VM356A", TECO_VM356A, "Primax", "Jewel 4800", {1, 600, 1}, /* resolution */ 300, 600, /* max x and Y resolution */ 2550, 12, 3, 1, /* calibration */ /* dots/inch * x-length, calibration samples, tot.bytes for 3 colors, default SANE_TECO2_CAL_ALGO value */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm356a_dpi_color_adjust}, {6, "TECO VM3575", TECO_VM3575, "Relisys", "SCORPIO Super 3", {1, 600, 1}, /* resolution */ 300, 600, /* max x and Y resolution */ 2550, 12, 6, 1, /* calibration */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm3575_dpi_color_adjust}, {6, "TECO VM3575", TECO_VM3575, "Relisys", "AVEC Super 3", {1, 600, 1}, /* resolution */ 300, 600, /* max x and Y resolution */ 2550, 12, 6, 1, /* calibration */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm3575_dpi_color_adjust}, {6, "TECO VM656A", TECO_VM656A, "Relisys", "APOLLO Express 6", {1, 600, 1}, /* resolution */ 600, 1200, /* max x and Y resolution */ 5100, 8, 6, 0, /* calibration */ {SANE_FIX (0), SANE_FIX (210), 0}, {SANE_FIX (0), SANE_FIX (297), 0}, vm656a_dpi_color_adjust}, {6, "TECO VM6575", TECO_VM6575, "Relisys", "SCORPIO Pro", {1, 600, 1}, /* resolution */ 600, 1200, /* max x and Y resolution */ 5100, 8, 6, 1, /* calibration */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm6575_dpi_color_adjust}, {6, "TECO VM6575", TECO_VM6575, "Primax", "Profi 9600", {1, 600, 1}, /* resolution */ 600, 1200, /* max x and Y resolution */ 5100, 8, 6, 1, /* calibration */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm6575_dpi_color_adjust}, {6, "TECO VM6586", TECO_VM6586, "Relisys", "SCORPIO Pro-S", {1, 600, 1}, /* resolution */ 600, 1200, /* max x and Y resolution */ 5100, 8, 6, 0, /* calibration */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm6586_dpi_color_adjust}, {6, "TECO VM6586", TECO_VM6586, "Primax", "Profi 19200", {1, 600, 1}, /* resolution */ 600, 1200, /* max x and Y resolution */ 5100, 8, 6, 0, /* calibration */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, {SANE_FIX (0), SANE_FIX (11.7 * MM_PER_INCH), 0}, vm6586_dpi_color_adjust} }; /*--------------------------------------------------------------------------*/ /* List of scanner attached. */ static Teco_Scanner *first_dev = NULL; static int num_devices = 0; static const SANE_Device **devlist = NULL; /* Local functions. */ /* Display a buffer in the log. Display by lines of 16 bytes. */ static void hexdump (int level, const char *comment, unsigned char *buf, const int length) { int i; char line[128]; char *ptr; char asc_buf[17]; char *asc_ptr; DBG (level, " %s\n", comment); i = 0; goto start; do { if (i < length) { ptr += sprintf (ptr, " %2.2x", *buf); if (*buf >= 32 && *buf <= 127) { asc_ptr += sprintf (asc_ptr, "%c", *buf); } else { asc_ptr += sprintf (asc_ptr, "."); } } else { /* After the length; do nothing. */ ptr += sprintf (ptr, " "); } i++; buf++; if ((i % 16) == 0) { /* It's a new line */ DBG (level, " %s %s\n", line, asc_buf); start: ptr = line; *ptr = '\0'; asc_ptr = asc_buf; *asc_ptr = '\0'; ptr += sprintf (ptr, " %3.3d:", i); } } while (i < ((length + 15) & ~15)); } /* Returns the length of the longest string, including the terminating * character. */ static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* Lookup a string list from one array and return its index. */ static int get_string_list_index (SANE_String_Const list[], SANE_String_Const name) { int index; index = 0; while (list[index] != NULL) { if (strcmp (list[index], name) == 0) { return (index); } index++; } DBG (DBG_error, "name %s not found in list\n", name); assert (0); /* bug in backend, core dump */ return (-1); } /* Initialize a scanner entry. Return an allocated scanner with some * preset values. */ static Teco_Scanner * teco_init (void) { Teco_Scanner *dev; DBG (DBG_proc, "teco_init: enter\n"); /* Allocate a new scanner entry. */ dev = malloc (sizeof (Teco_Scanner)); if (dev == NULL) { return NULL; } memset (dev, 0, sizeof (Teco_Scanner)); /* Allocate the buffer used to transfer the SCSI data. */ dev->buffer_size = 64 * 1024; dev->buffer = malloc (dev->buffer_size); if (dev->buffer == NULL) { free (dev); return NULL; } dev->sfd = -1; DBG (DBG_proc, "teco_init: exit\n"); return (dev); } /* Closes an open scanner. */ static void teco_close (Teco_Scanner * dev) { DBG (DBG_proc, "teco_close: enter\n"); if (dev->sfd != -1) { sanei_scsi_close (dev->sfd); dev->sfd = -1; } DBG (DBG_proc, "teco_close: exit\n"); } /* Frees the memory used by a scanner. */ static void teco_free (Teco_Scanner * dev) { int i; DBG (DBG_proc, "teco_free: enter\n"); if (dev == NULL) return; teco_close (dev); if (dev->devicename) { free (dev->devicename); } if (dev->buffer) { free (dev->buffer); } for (i = 1; i < OPT_NUM_OPTIONS; i++) { if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) { free (dev->val[i].s); } } if (dev->resolutions_list) free (dev->resolutions_list); free (dev); DBG (DBG_proc, "teco_free: exit\n"); } /* Inquiry a device and returns TRUE if is supported. */ static int teco_identify_scanner (Teco_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; int i; DBG (DBG_proc, "teco_identify_scanner: enter\n"); size = 5; MKSCSI_INQUIRY (cdb, size); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "teco_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } size = dev->buffer[4] + 5; /* total length of the inquiry data */ #ifndef sim if (size < 53) { DBG (DBG_error, "teco_identify_scanner: not enough data to identify device\n"); return (SANE_FALSE); } #endif #ifdef sim { #if 0 /* vm3564 */ unsigned char table[] = { 0x06, 0x00, 0x02, 0x02, 0x43, 0x00, 0x00, 0x10, 0x52, 0x45, 0x4c, 0x49, 0x53, 0x59, 0x53, 0x20, 0x41, 0x56, 0x45, 0x43, 0x20, 0x49, 0x49, 0x20, 0x53, 0x33, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x2e, 0x30, 0x37, 0x31, 0x2e, 0x30, 0x37, 0x00, 0x01, 0x54, 0x45, 0x43, 0x4f, 0x20, 0x56, 0x4d, 0x33, 0x35, 0x36, 0x34, 0x20, 0x00, 0x01, 0x01, 0x2c, 0x00, 0x01, 0x02, 0x58, 0x09, 0xf6, 0x0d, 0xaf, 0x01, 0x2c, 0x00, 0x08, 0x01, 0x00 }; #endif #if 0 /* vm356A */ unsigned char table[] = { 0x06, 0x00, 0x02, 0x02, 0x43, 0x00, 0x00, 0x10, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x78, 0x20, 0x20, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x2e, 0x30, 0x30, 0x31, 0x2e, 0x30, 0x30, 0x00, 0x01, 0x54, 0x45, 0x43, 0x4f, 0x20, 0x56, 0x4d, 0x33, 0x35, 0x36, 0x41, 0x20, 0x00, 0x01, 0x01, 0x2c, 0x00, 0x01, 0x02, 0x58, 0x09, 0xf6, 0x0d, 0xaf, 0x01, 0x2c, 0x00, 0x08, 0x10, 0x00 }; #endif #if 1 /* vm3575 */ unsigned char table[] = { 0x06, 0x00, 0x02, 0x02, 0x43, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x6c, 0x61, 0x74, 0x62, 0x65, 0x64, 0x20, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x31, 0x2e, 0x30, 0x33, 0x31, 0x2e, 0x30, 0x33, 0x00, 0x01, 0x54, 0x45, 0x43, 0x4f, 0x20, 0x56, 0x4d, 0x33, 0x35, 0x37, 0x35, 0x20, 0x00, 0x01, 0x01, 0x2c, 0x00, 0x01, 0x02, 0x58, 0x09, 0xf6, 0x0d, 0xaf, 0x01, 0x2c, 0x00, 0x08, 0x01, 0x00 }; #endif #if 0 /* vm6586 */ unsigned char table[] = { 0x06, 0x00, 0x02, 0x02, 0x43, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x6c, 0x61, 0x74, 0x62, 0x65, 0x64, 0x20, 0x53, 0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x33, 0x2e, 0x30, 0x31, 0x33, 0x2e, 0x30, 0x31, 0x00, 0x01, 0x54, 0x45, 0x43, 0x4f, 0x20, 0x56, 0x4d, 0x36, 0x35, 0x38, 0x36, 0x20, 0x00, 0x01, 0x01, 0x2c, 0x00, 0x01, 0x02, 0x58, 0x09, 0xf6, 0x0d, 0xaf, 0x01, 0x2c, 0x00, 0x08, 0x01, 0x00 }; #endif #if 0 /* vm656A */ unsigned char table[] = { 0x06, 0x00, 0x02, 0x02, 0x43, 0x00, 0x00, 0x00, 0x52, 0x45, 0x4c, 0x49, 0x53, 0x59, 0x53, 0x20, 0x41, 0x50, 0x4f, 0x4c, 0x4c, 0x4f, 0x20, 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x36, 0x31, 0x2e, 0x30, 0x33, 0x31, 0x2e, 0x30, 0x33, 0x00, 0x01, 0x54, 0x45, 0x43, 0x4f, 0x20, 0x56, 0x4d, 0x36, 0x35, 0x36, 0x41, 0x00, 0x01, 0x01, 0x2c, 0x00, 0x01, 0x02, 0x58, 0x09, 0xf6, 0x0d, 0xaf, 0x01, 0x2c, 0x00, 0x08, 0x01, 0x00, 0x00 }; #endif size = sizeof (table); memcpy (dev->buffer, table, sizeof (table)); } #endif MKSCSI_INQUIRY (cdb, size); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "teco_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } hexdump (DBG_info2, "inquiry", dev->buffer, size); dev->scsi_type = dev->buffer[0] & 0x1f; memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); dev->scsi_vendor[0x08] = 0; memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); dev->scsi_product[0x10] = 0; memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); dev->scsi_version[0x04] = 0; memcpy (dev->scsi_teco_name, dev->buffer + 0x2A, 0x0B); dev->scsi_teco_name[0x0B] = 0; DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\" \"%s\"\n", dev->scsi_vendor, dev->scsi_product, dev->scsi_version, dev->scsi_teco_name); /* Lookup through the supported scanners table to find if this * backend supports that one. */ for (i = 0; i < NELEMS (scanners); i++) { if (dev->scsi_type == scanners[i].scsi_type && strcmp (dev->scsi_teco_name, scanners[i].scsi_teco_name) == 0) { DBG (DBG_error, "teco_identify_scanner: scanner supported\n"); /*patch for VM356A Jewel or Apollo text in frontend-+ others-------------- */ if (strncmp (dev->scsi_vendor, "RELISYS", 1) == 0 || strncmp (dev->scsi_vendor, " ", 1) == 0) { DBG (DBG_error, "teco_identify_scanner: scanner detected with this teco_name and first brand/name entry in table\n"); dev->def = &(scanners[i]); return (SANE_TRUE); } else { i++; DBG (DBG_error, "teco_identify_scanner: scanner detected with this teco_name and second brand/name entry in table\n"); dev->def = &(scanners[i]); return (SANE_TRUE); } } } DBG (DBG_proc, "teco_identify_scanner: exit, device not supported\n"); return (SANE_FALSE); } /* Set a window. */ static SANE_Status teco_set_window (Teco_Scanner * dev) { size_t size; /* significant size of window */ CDB cdb; unsigned char window[56]; SANE_Status status; int i; DBG (DBG_proc, "teco_set_window: enter\n"); /* size of the whole windows block */ size = 0; /* keep gcc quiet */ switch (dev->def->tecoref) { case TECO_VM3575: size = 53; break; case TECO_VM3564: case TECO_VM356A: case TECO_VM656A: case TECO_VM6575: case TECO_VM6586: size = 56; break; default: assert (0); } /* Check that window is big enough */ assert (size <= sizeof (window)); MKSCSI_SET_WINDOW (cdb, size); memset (window, 0, size); /* size of the windows descriptor block */ window[7] = size - 8; /* X and Y resolution */ Ito16 (dev->x_resolution, &window[10]); Ito16 (dev->y_resolution, &window[12]); /* Upper Left (X,Y) */ Ito32 (dev->x_tl, &window[14]); Ito32 (dev->y_tl, &window[18]); /* Width and length */ Ito32 (dev->width, &window[22]); Ito32 (dev->length, &window[26]); /* Image Composition */ switch (dev->scan_mode) { case TECO_BW: window[31] = dev->val[OPT_THRESHOLD].w; window[33] = 0x00; i = get_string_list_index (dither_list, dev->val[OPT_DITHER].s); window[36] = dither_val[i]; break; case TECO_GRAYSCALE: window[33] = 0x02; break; case TECO_COLOR: window[33] = 0x05; break; } /* Depth */ window[34] = dev->depth; /* Lamp to use */ i = get_string_list_index (filter_color_list, dev->val[OPT_FILTER_COLOR].s); window[48] = filter_color_val[i]; /* Unknown - invariants */ window[31] = 0x80; window[37] = 0x80; /* Set the expected size line and number of lines. */ if (dev->def->tecoref == TECO_VM656A || dev->def->tecoref == TECO_VM6575 || dev->def->tecoref == TECO_VM6586) { switch (dev->scan_mode) { case TECO_BW: case TECO_GRAYSCALE: Ito16 (dev->params.bytes_per_line, &window[52]); break; case TECO_COLOR: Ito16 (dev->params.bytes_per_line / 3, &window[52]); break; } Ito16 (dev->params.lines, &window[54]); } hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); hexdump (DBG_info2, "windows", window, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, window, size, NULL, NULL); DBG (DBG_proc, "teco_set_window: exit, status=%d\n", status); return status; } /* Park the CCD */ static SANE_Status teco_reset_window (Teco_Scanner * dev) { SANE_Status status; CDB cdb; DBG (DBG_proc, "teco_reset_window: enter\n"); MKSCSI_OBJECT_POSITION (cdb, 0); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "teco_reset_window: leave, status=%d\n", status); return status; } #ifdef sim unsigned char *image_buf; int image_buf_begin; #endif /* Read the size of the scan. */ static SANE_Status teco_get_scan_size (Teco_Scanner * dev) { size_t size; CDB cdb; SANE_Status status; DBG (DBG_proc, "teco_get_scan_size: enter\n"); size = 0x12; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); assert (size == 0x12); hexdump (DBG_info2, "teco_get_scan_size return", dev->buffer, size); #ifndef sim dev->params.lines = B16TOI (&dev->buffer[12]); dev->bytes_per_raster = B16TOI (&dev->buffer[14]); switch (dev->scan_mode) { case TECO_BW: dev->params.bytes_per_line = B16TOI (&dev->buffer[14]); dev->params.pixels_per_line = dev->params.bytes_per_line * 8; break; case TECO_GRAYSCALE: dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); dev->params.bytes_per_line = dev->params.pixels_per_line; break; case TECO_COLOR: dev->params.pixels_per_line = B16TOI (&dev->buffer[14]); dev->params.bytes_per_line = dev->params.pixels_per_line * 3; break; } #else { size_t s1, s2; int fd; char *name; switch (dev->def->tecoref) { case TECO_VM3575: if (dev->scan_mode == TECO_GRAYSCALE) { dev->params.pixels_per_line = 850; dev->params.bytes_per_line = 850; dev->params.lines = 1170; dev->bytes_per_raster = 850; name = "/home/fzago/sane/teco2/vm3575/gr100d-2.raw"; } else { switch (dev->val[OPT_RESOLUTION].w) { case 50: dev->params.pixels_per_line = 425; dev->params.lines = 585; name = "/home/fzago/sane/teco2/vm3575/out12-co50.raw"; break; case 60: dev->params.pixels_per_line = 510; dev->params.lines = 702; name = "/home/fzago/sane/teco2/vm3575/out12-co60.raw"; break; case 75: dev->params.pixels_per_line = 638; dev->params.lines = 431; name = "/home/fzago/sane/teco2/vm3575/out12-co75.raw"; break; case 100: dev->params.pixels_per_line = 402; dev->params.lines = 575; name = "/home/fzago/sane/teco2/vm3575/out12-co100.raw"; break; } dev->params.bytes_per_line = dev->params.pixels_per_line * 3; dev->bytes_per_raster = dev->params.pixels_per_line; } break; case TECO_VM6586: switch (dev->val[OPT_RESOLUTION].w) { case 150: dev->params.pixels_per_line = 297; dev->params.lines = 296; name = "/home/fzago/sane/teco2/vm6586/150dpi.raw"; break; case 600: dev->params.pixels_per_line = 1186; dev->params.lines = 1186; name = "/home/fzago/sane/teco2/vm6586/600dpi.raw"; break; } dev->params.bytes_per_line = dev->params.pixels_per_line * 3; dev->bytes_per_raster = dev->params.pixels_per_line; } s1 = dev->params.bytes_per_line * dev->params.lines; image_buf = malloc (s1); assert (image_buf); image_buf_begin = 0; fd = open (name, O_RDONLY); assert (fd >= 0); s2 = read (fd, image_buf, s1); assert (s1 == s2); close (fd); } #endif DBG (DBG_proc, "teco_get_scan_size: exit, status=%d\n", status); return (status); } /* Wait until the scanner is ready to send the data. This is the almost the same code as teco_get_scan_size(). This function has to be called once after the scan has started. */ static SANE_Status teco_wait_for_data (Teco_Scanner * dev) { size_t size; CDB cdb; SANE_Status status; int i; #ifdef sim return SANE_STATUS_GOOD; #endif DBG (DBG_proc, "teco_wait_for_data: enter\n"); for (i = 0; i < 60; i++) { size = 0x12; MKSCSI_GET_DATA_BUFFER_STATUS (cdb, 1, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); assert (size == 0x12); hexdump (DBG_info2, "teco_wait_for_data return", dev->buffer, size); switch (dev->def->tecoref) { case TECO_VM3564: case TECO_VM356A: if (dev->buffer[11] > 0x01) { return SANE_STATUS_GOOD; } sleep (1); break; /* For VM3575, VM6575, VM656A, VM6586 until otherwise default value is used */ default: if (dev->buffer[11] == 0x80) { return SANE_STATUS_GOOD; } sleep (1); break; } } DBG (DBG_proc, "teco_wait_for_data: scanner not ready to send data (%d)\n", status); return SANE_STATUS_DEVICE_BUSY; } /* Do the calibration stuff. Get 12 or 8 lines of data. Each pixel is coded * in 6 bytes (2 per color) or 3 bytes (3564 and 356A). To do the calibration, * allocates an array big enough for one line, read the 12 or 8 lines of calibration, * subtract the highest and lowest value and do a average. * The input line is 1 raster for each color. However * the output line is interlaced (ie RBG for the first pixel, then RGB * for the second, and so on...). The output line are the value to use * to compensate for the white point. * There is two algorithms: * * The range goes from 0 to 0xfff, and the average is 0x800. So if * the average input is 0x700, the output value for that dot must be * 0x1000-0x700=0x900. * * and * * the calibration needs to be a multiplication factor, to * compensate for the too strong or too weak pixel in the sensor. * * See more info in doc/teco/teco2.txt * **/ static SANE_Status teco_do_calibration (Teco_Scanner * dev) { SANE_Status status; CDB cdb; size_t size; int i; int j; int colsub0_0, colsub0_1, colsub0_2; int colsub1_0, colsub1_1, colsub1_2; int *tmp_buf, *tmp_min_buf, *tmp_max_buf; /* hold the temporary calibration */ size_t tmp_buf_size, tmp_min_buf_size, tmp_max_buf_size; const char *calibration_algo; int cal_algo; colsub0_0 = 0; colsub0_1 = 0; colsub0_2 = 0; colsub1_0 = 0; colsub1_1 = 0; colsub1_2 = 0; DBG (DBG_proc, "teco_do_calibration: enter\n"); /* Get default calibration algorithm. */ cal_algo = dev->def->cal_algo; if ((calibration_algo = getenv ("SANE_TECO2_CAL_ALGO")) != NULL) { cal_algo = atoi (calibration_algo); } if (cal_algo != 0 && cal_algo != 1) { DBG (DBG_error, "Invalid calibration algorithm (%d)\n", cal_algo); cal_algo = 0; } switch (dev->def->tecoref) { case TECO_VM3564: case TECO_VM356A: /* white level red, green and blue calibration correction */ /* 0x110 or 272 is middle value */ colsub0_1 = 240 + (dev->val[OPT_WHITE_LEVEL_R].w); colsub0_2 = 240 + (dev->val[OPT_WHITE_LEVEL_G].w); colsub0_0 = 240 + (dev->val[OPT_WHITE_LEVEL_B].w); /* 14000 is middle value */ colsub1_1 = 12720 + (40 * dev->val[OPT_WHITE_LEVEL_R].w); colsub1_2 = 12720 + (40 * dev->val[OPT_WHITE_LEVEL_G].w); colsub1_0 = 12720 + (40 * dev->val[OPT_WHITE_LEVEL_B].w); break; case TECO_VM3575: case TECO_VM6575: /* 0x1100 or 4352 is middle value */ colsub0_1 = 4096 + (8 * dev->val[OPT_WHITE_LEVEL_R].w); colsub0_2 = 4096 + (8 * dev->val[OPT_WHITE_LEVEL_G].w); colsub0_0 = 4096 + (8 * dev->val[OPT_WHITE_LEVEL_B].w); /* 4206639 is middle value */ colsub1_1 = 4078639 + (4000 * dev->val[OPT_WHITE_LEVEL_R].w); colsub1_2 = 4078639 + (4000 * dev->val[OPT_WHITE_LEVEL_G].w); colsub1_0 = 4078639 + (4000 * dev->val[OPT_WHITE_LEVEL_B].w); break; /* old default value */ case TECO_VM656A: case TECO_VM6586: colsub0_1 = 0x1000; colsub0_2 = 0x1000; colsub0_0 = 0x1000; colsub1_1 = 4206639; colsub1_2 = 4206639; colsub1_0 = 4206639; break; default: colsub0_1 = 0x1000; colsub0_2 = 0x1000; colsub0_0 = 0x1000; colsub1_1 = 4206639; colsub1_2 = 4206639; colsub1_0 = 4206639; break; } tmp_buf_size = dev->def->cal_length * 3 * sizeof (int); tmp_min_buf_size = dev->def->cal_length * 3 * sizeof (int); tmp_max_buf_size = dev->def->cal_length * 3 * sizeof (int); tmp_buf = malloc (tmp_buf_size); tmp_min_buf = malloc (tmp_min_buf_size); tmp_max_buf = malloc (tmp_max_buf_size); memset (tmp_buf, 0, tmp_buf_size); switch (dev->def->tecoref) { case TECO_VM3564: case TECO_VM356A: memset (tmp_min_buf, 0xff, tmp_min_buf_size); memset (tmp_max_buf, 0x00, tmp_max_buf_size); break; case TECO_VM3575: case TECO_VM656A: case TECO_VM6575: case TECO_VM6586: memset (tmp_min_buf, 0xffff, tmp_min_buf_size); memset (tmp_max_buf, 0x0000, tmp_max_buf_size); break; } if ((tmp_buf == NULL) || (tmp_min_buf == NULL) || (tmp_max_buf == NULL)) { DBG (DBG_proc, "teco_do_calibration: not enough memory (%ld bytes)\n", (long) tmp_buf_size); return (SANE_STATUS_NO_MEM); } for (i = 0; i < dev->def->cal_lines; i++) { MKSCSI_VENDOR_SPEC (cdb, SCSI_VENDOR_09, 6); /* No idea what that is. */ switch (dev->scan_mode) { case TECO_BW: cdb.data[2] = 0x02; break; case TECO_GRAYSCALE: cdb.data[2] = 0x01; break; case TECO_COLOR: cdb.data[2] = 0x00; break; } /* Length of the scanner * number of bytes per color */ size = dev->def->cal_length * dev->def->cal_col_len; cdb.data[3] = (size >> 8) & 0xff; cdb.data[4] = (size >> 0) & 0xff; hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "teco_do_calibration: cannot read from the scanner\n"); free (tmp_buf); return status; } #ifdef sim for (j = 0; j < dev->def->cal_length; j++) { dev->buffer[6 * j + 0] = 0x10; dev->buffer[6 * j + 1] = 0x12; dev->buffer[6 * j + 2] = 0x14; dev->buffer[6 * j + 3] = 0x16; dev->buffer[6 * j + 4] = 0x20; dev->buffer[6 * j + 5] = 0x25; } #endif /*hexdump (DBG_info2, "got calibration line:", dev->buffer, size); */ for (j = 0; j < dev->def->cal_length; j++) { switch (dev->def->tecoref) { case TECO_VM3575: case TECO_VM6575: case TECO_VM656A: case TECO_VM6586: tmp_buf[3 * j + 0] += (dev->buffer[6 * j + 1] << 8) + dev->buffer[6 * j + 0]; /* get lowest value */ if (tmp_min_buf[3 * j + 0] >> ((dev->buffer[6 * j + 1] << 8) + dev->buffer[6 * j + 0])) { tmp_min_buf[3 * j + 0] = (dev->buffer[6 * j + 1] << 8) + dev->buffer[6 * j + 0]; } /* get highest value */ if (tmp_max_buf[3 * j + 0] < ((dev->buffer[6 * j + 1] << 8) + dev->buffer[6 * j + 0])) { tmp_max_buf[3 * j + 0] = (dev->buffer[6 * j + 1] << 8) + dev->buffer[6 * j + 0]; } tmp_buf[3 * j + 1] += (dev->buffer[6 * j + 3] << 8) + dev->buffer[6 * j + 2]; /* get lowest value */ if (tmp_min_buf[3 * j + 1] >> ((dev->buffer[6 * j + 3] << 8) + dev->buffer[6 * j + 2])) { tmp_min_buf[3 * j + 1] = (dev->buffer[6 * j + 3] << 8) + dev->buffer[6 * j + 2]; } /* get highest value */ if (tmp_max_buf[3 * j + 1] < ((dev->buffer[6 * j + 3] << 8) + dev->buffer[6 * j + 2])) { tmp_max_buf[3 * j + 1] = (dev->buffer[6 * j + 3] << 8) + dev->buffer[6 * j + 2]; } tmp_buf[3 * j + 2] += (dev->buffer[6 * j + 5] << 8) + dev->buffer[6 * j + 4]; /* get lowest value */ if (tmp_min_buf[3 * j + 2] >> ((dev->buffer[6 * j + 5] << 8) + dev->buffer[6 * j + 4])) { tmp_min_buf[3 * j + 2] = (dev->buffer[6 * j + 5] << 8) + dev->buffer[6 * j + 4]; } /* get highest value */ if (tmp_max_buf[3 * j + 2] < ((dev->buffer[6 * j + 5] << 8) + dev->buffer[6 * j + 4])) { tmp_max_buf[3 * j + 2] = (dev->buffer[6 * j + 5] << 8) + dev->buffer[6 * j + 4]; } break; case TECO_VM3564: case TECO_VM356A: tmp_buf[3 * j + 0] += dev->buffer[3 * j + 0]; /* get lowest value */ if (tmp_min_buf[3 * j + 0] >> dev->buffer[3 * j + 0]) { tmp_min_buf[3 * j + 0] = dev->buffer[3 * j + 0]; } /* get highest value */ if (tmp_max_buf[3 * j + 0] < dev->buffer[3 * j + 0]) { tmp_max_buf[3 * j + 0] = dev->buffer[3 * j + 0]; } tmp_buf[3 * j + 1] += dev->buffer[3 * j + 1]; /* get lowest value */ if (tmp_min_buf[3 * j + 1] >> dev->buffer[3 * j + 1]) { tmp_min_buf[3 * j + 1] = dev->buffer[3 * j + 1]; } /* get hightest value */ if (tmp_max_buf[3 * j + 1] < dev->buffer[3 * j + 1]) { tmp_max_buf[3 * j + 1] = dev->buffer[3 * j + 1]; } tmp_buf[3 * j + 2] += dev->buffer[3 * j + 2]; /* get lowest value */ if (tmp_min_buf[3 * j + 2] >> dev->buffer[3 * j + 2]) { tmp_min_buf[3 * j + 2] = dev->buffer[3 * j + 2]; } /* get highest value */ if (tmp_max_buf[3 * j + 2] < dev->buffer[3 * j + 2]) { tmp_max_buf[3 * j + 2] = dev->buffer[3 * j + 2]; } break; /* default: tmp_buf[3 * j + 0] += (dev->buffer[6 * j + 1] << 8) + dev->buffer[6 * j + 0]; tmp_buf[3 * j + 1] += (dev->buffer[6 * j + 3] << 8) + dev->buffer[6 * j + 2]; tmp_buf[3 * j + 2] += (dev->buffer[6 * j + 5] << 8) + dev->buffer[6 * j + 4]; break; */ } } } /* hexdump (DBG_info2, "calibration before average:", tmp_buf, tmp_buf_size); */ /* hexdump (DBG_info2, "calibration before average min value:", tmp_min_buf, tmp_min_buf_size); */ /* hexdump (DBG_info2, "calibration before average max value:", tmp_max_buf, tmp_max_buf_size); */ /* Do the average. Since we got 12 or 8 lines, divide all values by 10 or 6 * and create the final calibration value that compensates for the * white values read. */ switch (dev->def->tecoref) { case TECO_VM356A: case TECO_VM3564: case TECO_VM3575: case TECO_VM6575: case TECO_VM656A: case TECO_VM6586: for (j = 0; j < dev->def->cal_length; j++) { /* subtract lowest and highest value */ tmp_buf[j] = tmp_buf[j] - (tmp_min_buf[j] + tmp_max_buf[j]); tmp_buf[j + dev->def->cal_length] = tmp_buf[j + dev->def->cal_length] - (tmp_min_buf[j + dev->def->cal_length] + tmp_max_buf[j + dev->def->cal_length]); tmp_buf[j + 2 * dev->def->cal_length] = tmp_buf[j + 2 * dev->def->cal_length] - (tmp_min_buf[j + 2 * dev->def->cal_length] + tmp_max_buf[j + 2 *dev->def->cal_length]); /* sequence colors first color row one then two and last three */ if (cal_algo == 1) { tmp_buf[j] = (colsub1_0 * (dev->def->cal_lines - 2)) / tmp_buf[j]; tmp_buf[j + dev->def->cal_length] = (colsub1_1 * (dev->def->cal_lines - 2)) / tmp_buf[j + dev->def->cal_length]; tmp_buf[j + 2 * dev->def->cal_length] = (colsub1_2 * (dev->def->cal_lines - 2)) / tmp_buf[j + 2 * dev->def->cal_length]; } else { tmp_buf[j] = colsub0_0 - (tmp_buf[j] / (dev->def->cal_lines - 2)); tmp_buf[j + dev->def->cal_length] = colsub0_1 - (tmp_buf[j + dev->def->cal_length] / (dev->def->cal_lines - 2)); tmp_buf[j + 2 * dev->def->cal_length] = colsub0_2 - (tmp_buf[j + 2 * dev->def->cal_length] / (dev->def->cal_lines - 2)); } } break; /* default: for (j = 0; j < (3 * dev->def->cal_length); j++) { if (cal_algo == 1) tmp_buf[j] = (colsub1_1 * dev->def->cal_lines) / tmp_buf[j]; else tmp_buf[j] = colsub0_1 - (tmp_buf[j] / dev->def->cal_lines); } break; */ } /*hexdump (DBG_info2, "calibration after average:", tmp_buf, tmp_buf_size); */ /* Build the calibration line to send. */ for (j = 0; j < dev->def->cal_length; j++) { switch (dev->def->tecoref) { case TECO_VM3575: case TECO_VM6575: case TECO_VM656A: case TECO_VM6586: dev->buffer[6 * j + 0] = (tmp_buf[0 * dev->def->cal_length + j] >> 0) & 0xff; dev->buffer[6 * j + 1] = (tmp_buf[0 * dev->def->cal_length + j] >> 8) & 0xff; dev->buffer[6 * j + 2] = (tmp_buf[1 * dev->def->cal_length + j] >> 0) & 0xff; dev->buffer[6 * j + 3] = (tmp_buf[1 * dev->def->cal_length + j] >> 8) & 0xff; dev->buffer[6 * j + 4] = (tmp_buf[2 * dev->def->cal_length + j] >> 0) & 0xff; dev->buffer[6 * j + 5] = (tmp_buf[2 * dev->def->cal_length + j] >> 8) & 0xff; break; case TECO_VM3564: case TECO_VM356A: dev->buffer[3 * j + 0] = (tmp_buf[3 * j + 0] >> 0) & 0xff; dev->buffer[3 * j + 1] = (tmp_buf[3 * j + 1] >> 0) & 0xff; dev->buffer[3 * j + 2] = (tmp_buf[3 * j + 2] >> 0) & 0xff; break; } } free (tmp_buf); tmp_buf = NULL; /* Send the calibration line. The CDB is the same as the previous * one, except for the command. */ cdb.data[0] = 0x0E; size = dev->def->cal_length * dev->def->cal_col_len; hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); /*hexdump (DBG_info2, "calibration line sent:", dev->buffer, size); */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, dev->buffer, size, NULL, NULL); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "teco_do_calibration: calibration line was not sent correctly\n"); return status; } DBG (DBG_proc, "teco_do_calibration: leave\n"); return SANE_STATUS_GOOD; } /*------------request sense command 03----------------*/ static SANE_Status teco_request_sense (Teco_Scanner * dev) { SANE_Status status; unsigned char buf[255]; CDB cdb; size_t size; /* size = 0; */ DBG (DBG_proc, "teco_request_sense: enter\n"); size = sizeof (buf); MKSCSI_REQUEST_SENSE (cdb, size); /*size = cdb.data[5]; hexdump (DBG_info2, "teco_request_sense", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, buf, &size); hexdump (DBG_info2, "teco_request_sense:", buf, size); DBG (DBG_proc, "teco_request_sense: exit, status=%d\n", status); return (status); } /*----------------------------------------------------*/ /* Send the gamma */ static SANE_Status teco_send_gamma (Teco_Scanner * dev) { CDB cdb; SANE_Status status; struct { unsigned char gamma_R[GAMMA_LENGTH]; unsigned char gamma_G[GAMMA_LENGTH]; /* also gray */ unsigned char gamma_B[GAMMA_LENGTH]; } param; size_t i; size_t size; DBG (DBG_proc, "teco_send_gamma: enter\n"); size = sizeof (param); assert (size == 3 * GAMMA_LENGTH); MKSCSI_SEND_10 (cdb, 0x03, 0x04, size); if (dev->val[OPT_CUSTOM_GAMMA].w) { /* Use the custom gamma. */ if (dev->scan_mode == TECO_GRAYSCALE) { /* Gray */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = dev->gamma_GRAY[i]; param.gamma_G[i] = dev->gamma_GRAY[i]; param.gamma_B[i] = dev->gamma_GRAY[i]; } } else { /* Color */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = dev->gamma_R[i]; param.gamma_G[i] = dev->gamma_G[i]; param.gamma_B[i] = dev->gamma_B[i]; } } } else { /* Defaults to a linear gamma for now. */ for (i = 0; i < GAMMA_LENGTH; i++) { param.gamma_R[i] = i / 4; param.gamma_G[i] = i / 4; param.gamma_B[i] = i / 4; } } hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); switch (dev->def->tecoref) { case TECO_VM3564: case TECO_VM356A: status = 0; break; default: status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, ¶m, size, NULL, NULL); } DBG (DBG_proc, "teco_send_gamma: exit, status=%d\n", status); return (status); } /* Send a vendor specific command. */ static SANE_Status teco_send_vendor_06 (Teco_Scanner * dev) { SANE_Status status; CDB cdb; size_t size; DBG (DBG_proc, "teco_send_vendor_06: enter\n"); MKSCSI_VENDOR_SPEC (cdb, SCSI_VENDOR_06, 6); size = 4; hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); MKSCSI_VENDOR_SPEC (cdb, SCSI_VENDOR_1C, 6); size = 4; memset (dev->buffer, 0, size); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, dev->buffer, size, NULL, NULL); DBG (DBG_proc, "teco_send_vendor_06: exit, status=%d\n", status); return (status); } /* Start a scan. */ static SANE_Status teco_scan (Teco_Scanner * dev) { CDB cdb; SANE_Status status; DBG (DBG_proc, "teco_scan: enter\n"); MKSCSI_SCAN (cdb); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "teco_scan: exit, status=%d\n", status); return status; } /* SCSI sense handler. Callback for SANE. */ static SANE_Status teco_sense_handler (int scsi_fd, unsigned char *result, void __sane_unused__ *arg) { int asc, ascq, sensekey; int len; DBG (DBG_proc, "teco_sense_handler (scsi_fd = %d)\n", scsi_fd); sensekey = get_RS_sense_key (result); len = 7 + get_RS_additional_length (result); hexdump (DBG_info2, "sense", result, len); if (get_RS_error_code (result) != 0x70) { DBG (DBG_error, "teco_sense_handler: invalid sense key error code (%d)\n", get_RS_error_code (result)); return SANE_STATUS_IO_ERROR; } if (get_RS_ILI (result) != 0) { DBG (DBG_sense, "teco_sense_handler: short read\n"); } if (len < 14) { DBG (DBG_error, "teco_sense_handler: sense too short, no ASC/ASCQ\n"); return SANE_STATUS_IO_ERROR; } asc = get_RS_ASC (result); ascq = get_RS_ASCQ (result); DBG (DBG_sense, "teco_sense_handler: sense=%d, ASC/ASCQ=%02x%02x\n", sensekey, asc, ascq); switch (sensekey) { case 0x00: /* no sense */ case 0x02: /* not ready */ case 0x03: /* medium error */ case 0x05: case 0x06: break; } DBG (DBG_sense, "teco_sense_handler: unknown error condition. Please report it to the backend maintainer\n"); return SANE_STATUS_IO_ERROR; } /* Attach a scanner to this backend. */ static SANE_Status attach_scanner (const char *devicename, Teco_Scanner ** devp) { Teco_Scanner *dev; int sfd; DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); if (devp) *devp = NULL; /* Check if we know this device name. */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (DBG_info, "device is already known\n"); return SANE_STATUS_GOOD; } } /* Allocate a new scanner entry. */ dev = teco_init (); if (dev == NULL) { DBG (DBG_error, "ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_scanner: opening %s\n", devicename); if (sanei_scsi_open (devicename, &sfd, teco_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: attach_scanner: open failed\n"); teco_free (dev); return SANE_STATUS_INVAL; } #ifdef sim sfd = -1; #endif /* Fill some scanner specific values. */ dev->devicename = strdup (devicename); dev->sfd = sfd; /* Now, check that it is a scanner we support. */ if (teco_identify_scanner (dev) == SANE_FALSE) { DBG (DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); teco_free (dev); return SANE_STATUS_INVAL; } teco_close (dev); /* If this scanner only supports a given number of resolutions, * build that list now. */ if (dev->def->color_adjust[0].resolution != 0) { int num_entries; int i; num_entries = 0; while (dev->def->color_adjust[num_entries].resolution != 0) num_entries++; dev->resolutions_list = malloc (sizeof (SANE_Word) * (num_entries + 1)); if (dev->resolutions_list == NULL) { DBG (DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); teco_free (dev); return SANE_STATUS_NO_MEM; } dev->resolutions_list[0] = num_entries; for (i = 0; i < num_entries; i++) { dev->resolutions_list[i + 1] = dev->def->color_adjust[i].resolution; } } else { dev->resolutions_list = NULL; } /* Set the default options for that scanner. */ dev->sane.name = dev->devicename; dev->sane.vendor = dev->def->real_vendor; dev->sane.model = dev->def->real_product; dev->sane.type = SANE_I18N ("flatbed scanner"); /* Link the scanner with the others. */ dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } num_devices++; DBG (DBG_proc, "attach_scanner: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach_scanner (dev, NULL); return SANE_STATUS_GOOD; } /* Reset the options for that scanner. */ static void teco_init_options (Teco_Scanner * dev) { int i; /* Pre-initialize the options. */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < OPT_NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options. */ dev->opt[OPT_NUM_OPTS].name = ""; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; /* Mode group */ dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].cap = 0; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scanner supported modes */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = max_string_size (scan_mode_list); dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = scan_mode_list; dev->val[OPT_MODE].s = (SANE_Char *) strdup (""); /* will be set later */ /* X and Y resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RESOLUTION].constraint.range = &dev->def->res_range; dev->val[OPT_RESOLUTION].w = DEF_RESOLUTION; /* Geometry group */ dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_GEOMETRY_GROUP].cap = 0; dev->opt[OPT_GEOMETRY_GROUP].size = 0; dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Upper left X */ dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &dev->def->x_range; dev->val[OPT_TL_X].w = dev->def->x_range.min; /* Upper left Y */ dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &dev->def->y_range; dev->val[OPT_TL_Y].w = dev->def->y_range.min; /* Bottom-right x */ dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &dev->def->x_range; dev->val[OPT_BR_X].w = dev->def->x_range.max; /* Bottom-right y */ dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &dev->def->y_range; dev->val[OPT_BR_Y].w = dev->def->y_range.max; /* Enhancement group */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Halftone pattern */ dev->opt[OPT_DITHER].name = "dither"; dev->opt[OPT_DITHER].title = SANE_I18N ("Dither"); dev->opt[OPT_DITHER].desc = SANE_I18N ("Dither"); dev->opt[OPT_DITHER].type = SANE_TYPE_STRING; dev->opt[OPT_DITHER].size = max_string_size (dither_list); dev->opt[OPT_DITHER].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_DITHER].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_DITHER].constraint.string_list = dither_list; dev->val[OPT_DITHER].s = strdup (dither_list[0]); /* custom-gamma table */ dev->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; dev->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* red gamma vector */ dev->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; dev->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_R].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_R].wa = dev->gamma_R; /* green and gamma vector */ dev->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; dev->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_G].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_G].wa = dev->gamma_G; /* blue gamma vector */ dev->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; dev->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_B].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_B].wa = dev->gamma_B; /* grayscale gamma vector */ dev->opt[OPT_GAMMA_VECTOR_GRAY].name = SANE_NAME_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].title = SANE_TITLE_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].desc = SANE_DESC_GAMMA_VECTOR; dev->opt[OPT_GAMMA_VECTOR_GRAY].type = SANE_TYPE_INT; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].unit = SANE_UNIT_NONE; dev->opt[OPT_GAMMA_VECTOR_GRAY].size = GAMMA_LENGTH * sizeof (SANE_Word); dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_GAMMA_VECTOR_GRAY].constraint.range = &gamma_range; dev->val[OPT_GAMMA_VECTOR_GRAY].wa = dev->gamma_GRAY; /* Color filter */ dev->opt[OPT_FILTER_COLOR].name = "color-filter"; dev->opt[OPT_FILTER_COLOR].title = "Color dropout"; dev->opt[OPT_FILTER_COLOR].desc = "Color dropout"; dev->opt[OPT_FILTER_COLOR].type = SANE_TYPE_STRING; dev->opt[OPT_FILTER_COLOR].size = max_string_size (filter_color_list); dev->opt[OPT_FILTER_COLOR].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_FILTER_COLOR].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_FILTER_COLOR].constraint.string_list = filter_color_list; dev->val[OPT_FILTER_COLOR].s = (SANE_Char *) strdup (filter_color_list[0]); /* Threshold */ dev->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; dev->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; dev->opt[OPT_THRESHOLD].size = sizeof (SANE_Int); dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_THRESHOLD].constraint.range = &threshold_range; dev->val[OPT_THRESHOLD].w = 128; /* preview */ dev->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; dev->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; dev->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; dev->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; dev->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; dev->val[OPT_PREVIEW].w = SANE_FALSE; /* red level calibration manual correction */ dev->opt[OPT_WHITE_LEVEL_R].name = SANE_NAME_WHITE_LEVEL_R; dev->opt[OPT_WHITE_LEVEL_R].title = SANE_TITLE_WHITE_LEVEL_R; dev->opt[OPT_WHITE_LEVEL_R].desc = SANE_DESC_WHITE_LEVEL_R; dev->opt[OPT_WHITE_LEVEL_R].type = SANE_TYPE_INT; dev->opt[OPT_WHITE_LEVEL_R].unit = SANE_UNIT_NONE; dev->opt[OPT_WHITE_LEVEL_R].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_WHITE_LEVEL_R].constraint.range = &red_level_range; dev->val[OPT_WHITE_LEVEL_R].w = 32; /* to get middle value */ /* green level calibration manual correction */ dev->opt[OPT_WHITE_LEVEL_G].name = SANE_NAME_WHITE_LEVEL_G; dev->opt[OPT_WHITE_LEVEL_G].title = SANE_TITLE_WHITE_LEVEL_G; dev->opt[OPT_WHITE_LEVEL_G].desc = SANE_DESC_WHITE_LEVEL_G; dev->opt[OPT_WHITE_LEVEL_G].type = SANE_TYPE_INT; dev->opt[OPT_WHITE_LEVEL_G].unit = SANE_UNIT_NONE; dev->opt[OPT_WHITE_LEVEL_G].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_WHITE_LEVEL_G].constraint.range = &green_level_range; dev->val[OPT_WHITE_LEVEL_G].w = 32; /* to get middle value */ /* blue level calibration manual correction */ dev->opt[OPT_WHITE_LEVEL_B].name = SANE_NAME_WHITE_LEVEL_B; dev->opt[OPT_WHITE_LEVEL_B].title = SANE_TITLE_WHITE_LEVEL_B; dev->opt[OPT_WHITE_LEVEL_B].desc = SANE_DESC_WHITE_LEVEL_B; dev->opt[OPT_WHITE_LEVEL_B].type = SANE_TYPE_INT; dev->opt[OPT_WHITE_LEVEL_B].unit = SANE_UNIT_NONE; dev->opt[OPT_WHITE_LEVEL_B].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_WHITE_LEVEL_B].constraint.range = &blue_level_range; dev->val[OPT_WHITE_LEVEL_B].w = 32; /* to get middle value */ /* Lastly, set the default scan mode. This might change some * values previously set here. */ sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, (SANE_String_Const *) scan_mode_list[0], NULL); } /* * Wait until the scanner is ready. */ static SANE_Status teco_wait_scanner (Teco_Scanner * dev) { SANE_Status status; int timeout; CDB cdb; DBG (DBG_proc, "teco_wait_scanner: enter\n"); MKSCSI_TEST_UNIT_READY (cdb); /* Set the timeout to 60 seconds. */ timeout = 60; while (timeout > 0) { /* test unit ready */ hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd (dev->sfd, cdb.data, cdb.len, NULL, NULL); if (status == SANE_STATUS_GOOD) { return SANE_STATUS_GOOD; } sleep (1); }; DBG (DBG_proc, "teco_wait_scanner: scanner not ready\n"); return (SANE_STATUS_IO_ERROR); } /* * Adjust the rasters. This function is used during a color scan, * because the scanner does not present a format sane can interpret * directly. * * The scanner sends the colors by rasters (B then G then R), whereas * sane is waiting for a group of 3 bytes per color. To make things * funnier, the rasters are shifted. As a result, color planes appear to be shifted be a few pixels. * * The order of the color is dependant on each scanners. Also the same * scanner can change the order depending on the resolution. * * For instance, the VM6586 at 300dpi has a color shift of 2 lines. The rasters sent are: * starts with two blue rasters - BB, * then red in added - BRBR * then green - BRG ... (most of the picture) * then blue is removed - RGRG * and finaly only green stays - GG * * Overall there is the same number of RGB rasters. * The VM3575 is a variant (when factor_x is 0). It does not keep the same order, * but reverses it, eg: * BB RBRB GRB... GRGR GG * (ie it adds the new color in front of the previous one, instead of after). * * So this function reorders all that mess. It gets the input from * dev->buffer and write the output in dev->image. size_in the the * length of the valid data in dev->buffer. */ #define COLOR_0 (color_adjust->z3_color_0) #define COLOR_1 (color_adjust->z3_color_1) #define COLOR_2 (color_adjust->z3_color_2) static void teco_adjust_raster (Teco_Scanner * dev, size_t size_in) { int nb_rasters; /* number of rasters in dev->buffer */ int raster; /* current raster number in buffer */ int line; /* line number for that raster */ int color; /* color for that raster */ size_t offset; const struct dpi_color_adjust *color_adjust = dev->color_adjust; DBG (DBG_proc, "teco_adjust_raster: enter\n"); color = 0; /* keep gcc quiet */ assert (dev->scan_mode == TECO_COLOR); assert ((size_in % dev->params.bytes_per_line) == 0); if (size_in == 0) { return; } /* * The color coding is one line for each color (in the RGB order). * Recombine that stuff to create a RGB value for each pixel. */ nb_rasters = size_in / dev->raster_size; for (raster = 0; raster < nb_rasters; raster++) { /* * Find the color and the line which this raster belongs to. */ line = 0; if (dev->raster_num < color_adjust->color_shift) { /* Top of the picture. */ if (color_adjust->factor_x) { color = COLOR_2; } else { color = COLOR_1; } line = dev->raster_num; } else if (dev->raster_num < (3 * color_adjust->color_shift)) { /* Top of the picture. */ if ((dev->raster_num - color_adjust->color_shift) % 2) { color = COLOR_0; line = (dev->raster_num - color_adjust->color_shift) / 2; } else { if (color_adjust->factor_x) { color = COLOR_2; } else { color = COLOR_1; } line = (dev->raster_num + color_adjust->color_shift) / 2; } } else if (dev->raster_num >= dev->raster_real - color_adjust->color_shift) { /* Bottom of the picture. */ if (color_adjust->factor_x) { color = COLOR_1; } else { color = COLOR_2; } line = dev->line; } else if (dev->raster_num >= dev->raster_real - 3 * color_adjust->color_shift) { /* Bottom of the picture. */ if ((dev->raster_real - dev->raster_num - color_adjust->color_shift) % 2) { if (color_adjust->factor_x) { color = COLOR_1; line = dev->line; } else { color = COLOR_0; line = dev->line + color_adjust->color_shift - 1; } } else { if (color_adjust->factor_x) { color = COLOR_0; line = dev->line + color_adjust->color_shift; } else { color = COLOR_2; line = dev->line; } } } else { /* Middle of the picture. */ switch ((dev->raster_num) % 3) { case 0: color = COLOR_2; if (color_adjust->factor_x) line = dev->raster_num / 3 + color_adjust->color_shift; else line = dev->raster_num / 3 - color_adjust->color_shift; break; case 1: color = COLOR_0; line = dev->raster_num / 3; break; case 2: color = COLOR_1; if (color_adjust->factor_x) line = dev->raster_num / 3 - color_adjust->color_shift; else line = dev->raster_num / 3 + color_adjust->color_shift; break; } } /* Adjust the line number relative to the image. */ line -= dev->line; offset = dev->image_end + line * dev->params.bytes_per_line; assert (offset <= (dev->image_size - dev->params.bytes_per_line)); /* Copy the raster to the temporary image. */ { int i; unsigned char *src = dev->buffer + raster * dev->raster_size; unsigned char *dest = dev->image + offset + color; for (i = 0; i < dev->raster_size; i++) { *dest = *src; src++; dest += 3; } } DBG (DBG_info, "raster=%d, line=%d, color=%d\n", dev->raster_num, dev->line + line, color); if ((color_adjust->factor_x == 0 && color == COLOR_2) || (color_adjust->factor_x == 1 && color == COLOR_1)) { /* This blue raster completes a new line */ dev->line++; dev->image_end += dev->params.bytes_per_line; } dev->raster_num++; } DBG (DBG_proc, "teco_adjust_raster: exit\n"); } /* Read the image from the scanner and fill the temporary buffer with it. */ static SANE_Status teco_fill_image (Teco_Scanner * dev) { SANE_Status status; size_t size; CDB cdb; DBG (DBG_proc, "teco_fill_image: enter\n"); assert (dev->image_begin == dev->image_end); assert (dev->real_bytes_left > 0); /* Copy the complete lines, plus the incompletes * ones. We don't keep the real end of data used * in image, so we copy the biggest possible. * * This is a no-op for non color images. */ memmove (dev->image, dev->image + dev->image_begin, dev->raster_ahead); dev->image_begin = 0; dev->image_end = 0; while (dev->real_bytes_left) { /* * Try to read the maximum number of bytes. */ size = dev->real_bytes_left; if (size > dev->image_size - dev->raster_ahead - dev->image_end) { size = dev->image_size - dev->raster_ahead - dev->image_end; } if (size > dev->buffer_size) { size = dev->buffer_size; } /* Limit to 0x2000 bytes as does the TWAIN driver. */ if (size > 0x2000) size = 0x2000; /* Round down to a multiple of line size. */ size = size - (size % dev->params.bytes_per_line); if (size == 0) { /* Probably reached the end of the buffer. * Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } DBG (DBG_info, "teco_fill_image: to read = %ld bytes (bpl=%d)\n", (long) size, dev->params.bytes_per_line); MKSCSI_READ_10 (cdb, 0, 0, size); cdb.data[5] = size / dev->params.bytes_per_line; hexdump (DBG_info2, "teco_fill_image: READ_10 CDB", cdb.data, cdb.len); hexdump (DBG_info2, "CDB:", cdb.data, cdb.len); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); #ifdef sim memcpy (dev->buffer, image_buf + image_buf_begin, size); image_buf_begin += size; #endif if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "teco_fill_image: cannot read from the scanner\n"); return status; } DBG (DBG_info, "teco_fill_image: real bytes left = %ld\n", (long) dev->real_bytes_left); if (dev->scan_mode == TECO_COLOR && dev->def->tecoref != TECO_VM656A && raw_output == 0) { teco_adjust_raster (dev, size); } else { memcpy (dev->image + dev->image_end, dev->buffer, size); dev->image_end += size; } dev->real_bytes_left -= size; } return (SANE_STATUS_GOOD); /* unreachable */ } /* Copy from the raw buffer to the buffer given by the backend. * * len in input is the maximum length available in buf, and, in * output, is the length written into buf. */ static void teco_copy_raw_to_frontend (Teco_Scanner * dev, SANE_Byte * buf, size_t * len) { size_t size; size = dev->image_end - dev->image_begin; if (size > *len) { size = *len; } *len = size; switch (dev->scan_mode) { case TECO_BW: { /* Invert black and white. */ unsigned char *src = dev->image + dev->image_begin; size_t i; for (i = 0; i < size; i++) { *buf = *src ^ 0xff; src++; buf++; } } break; case TECO_GRAYSCALE: case TECO_COLOR: memcpy (buf, dev->image + dev->image_begin, size); break; } dev->image_begin += size; } /* Stop a scan. */ static SANE_Status do_cancel (Teco_Scanner * dev) { DBG (DBG_sane_proc, "do_cancel enter\n"); if (dev->scanning == SANE_TRUE) { /* Reset the scanner */ teco_reset_window (dev); teco_close (dev); } dev->scanning = SANE_FALSE; DBG (DBG_sane_proc, "do_cancel exit\n"); return SANE_STATUS_CANCELLED; } /*--------------------------------------------------------------------------*/ /* Sane entry points */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; char dev_name[PATH_MAX]; size_t len; DBG_INIT (); DBG (DBG_sane_init, "sane_init\n"); DBG (DBG_error, "This is sane-teco2 version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_error, "(C) 2002 - 2003 by Frank Zago, update 2003 - 2008 by Gerard Klaver\n"); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); } fp = sanei_config_open (TECO2_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach_scanner ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); DBG (DBG_proc, "sane_init: leave\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { Teco_Scanner *dev; int i; DBG (DBG_proc, "sane_get_devices: enter\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Teco_Scanner *dev; SANE_Status status; int i; DBG (DBG_proc, "sane_open: enter\n"); /* search for devicename */ if (devicename[0]) { DBG (DBG_info, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); dev = first_dev; /* empty devicename -> use first device */ } if (!dev) { DBG (DBG_error, "No scanner found\n"); return SANE_STATUS_INVAL; } teco_init_options (dev); /* Initialize the gamma table. */ for (i = 0; i < GAMMA_LENGTH; i++) { dev->gamma_R[i] = i / 4; dev->gamma_G[i] = i / 4; dev->gamma_B[i] = i / 4; dev->gamma_GRAY[i] = i / 4; } *handle = dev; DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); if ((unsigned) option >= OPT_NUM_OPTIONS) { return NULL; } DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return dev->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Teco_Scanner *dev = handle; SANE_Status status; SANE_Word cap; DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", option, action); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_CUSTOM_GAMMA: case OPT_PREVIEW: case OPT_THRESHOLD: case OPT_WHITE_LEVEL_R: case OPT_WHITE_LEVEL_G: case OPT_WHITE_LEVEL_B: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_DITHER: case OPT_FILTER_COLOR: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; /* Gamma */ case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (val, dev->val[option].wa, dev->opt[option].size); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Numeric side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_THRESHOLD: case OPT_RESOLUTION: case OPT_WHITE_LEVEL_R: case OPT_WHITE_LEVEL_G: case OPT_WHITE_LEVEL_B: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* Numeric side-effect free options */ case OPT_PREVIEW: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* String side-effect free options */ case OPT_DITHER: free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); return SANE_STATUS_GOOD; case OPT_FILTER_COLOR: free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); return SANE_STATUS_GOOD; /* String side-effect options */ case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_DITHER].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_FILTER_COLOR].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_B].cap |= SANE_CAP_INACTIVE; /* This the default resolution range, except for the * VM3575, VM3564, VM356A and VM6586 in color mode. */ dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_RESOLUTION].constraint.range = &dev->def->res_range; if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) == 0) { dev->scan_mode = TECO_BW; dev->depth = 8; dev->opt[OPT_DITHER].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_FILTER_COLOR].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) { dev->scan_mode = TECO_GRAYSCALE; dev->depth = 8; switch (dev->def->tecoref) { case TECO_VM3564: case TECO_VM356A: dev->opt[OPT_WHITE_LEVEL_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_B].cap &= ~SANE_CAP_INACTIVE; break; case TECO_VM3575: case TECO_VM6575: dev->opt[OPT_WHITE_LEVEL_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_B].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } break; case TECO_VM656A: case TECO_VM6586: dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } break; } dev->opt[OPT_FILTER_COLOR].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { dev->scan_mode = TECO_COLOR; dev->depth = 8; switch (dev->def->tecoref) { case TECO_VM3564: case TECO_VM356A: dev->opt[OPT_WHITE_LEVEL_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_B].cap &= ~SANE_CAP_INACTIVE; break; case TECO_VM3575: case TECO_VM6575: dev->opt[OPT_WHITE_LEVEL_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_WHITE_LEVEL_B].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } break; case TECO_VM656A: case TECO_VM6586: dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } break; } /* The VM3575, VM3564, VM356A and VM6586 supports only a handful of resolution. Do that here. * Ugly! */ if (dev->resolutions_list != NULL) { int i; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_RESOLUTION].constraint.word_list = dev->resolutions_list; /* If the resolution isn't in the list, set a default. */ for (i = 1; i <= dev->resolutions_list[0]; i++) { if (dev->resolutions_list[i] >= dev->val[OPT_RESOLUTION].w) break; } if (i > dev->resolutions_list[0]) { /* Too big. Take default. */ dev->val[OPT_RESOLUTION].w = DEF_RESOLUTION; } else { /* Take immediate superioir value. */ dev->val[OPT_RESOLUTION].w = dev->resolutions_list[i]; } } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (dev->val[option].wa, val, dev->opt[option].size); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: dev->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; if (dev->val[OPT_CUSTOM_GAMMA].w) { /* use custom_gamma_table */ if (dev->scan_mode == TECO_GRAYSCALE) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } else { /* color mode */ dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { /* Setup the parameters for the scan. These values will be re-used * in the SET WINDOWS command. */ if (dev->val[OPT_PREVIEW].w == SANE_TRUE) { /* for VM356A, no good 50 dpi scan possible, now leave as */ switch (dev->def->tecoref) { case TECO_VM356A: case TECO_VM6575: dev->x_resolution = 75; dev->y_resolution = 75; break; /* For VM3575, VM656A, VM6586 etc until otherwise default value is used */ default: dev->x_resolution = 50; dev->y_resolution = 50; break; } dev->x_tl = 0; dev->y_tl = 0; dev->x_br = mmToIlu (SANE_UNFIX (dev->def->x_range.max)); dev->y_br = mmToIlu (SANE_UNFIX (dev->def->y_range.max)); } else { dev->x_resolution = dev->val[OPT_RESOLUTION].w; dev->y_resolution = dev->val[OPT_RESOLUTION].w; dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); } if (dev->x_resolution > dev->def->x_resolution_max) { dev->x_resolution = dev->def->x_resolution_max; } /* Check the corners are OK. */ if (dev->x_tl > dev->x_br) { int s; s = dev->x_tl; dev->x_tl = dev->x_br; dev->x_br = s; } if (dev->y_tl > dev->y_br) { int s; s = dev->y_tl; dev->y_tl = dev->y_br; dev->y_br = s; } dev->width = dev->x_br - dev->x_tl; dev->length = dev->y_br - dev->y_tl; /* Prepare the parameters for the caller. */ memset (&dev->params, 0, sizeof (SANE_Parameters)); dev->params.last_frame = SANE_TRUE; switch (dev->scan_mode) { case TECO_BW: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / dev->def->x_resolution_max) & ~0x7; dev->params.bytes_per_line = dev->params.pixels_per_line / 8; dev->params.depth = 1; dev->color_adjust = NULL; break; case TECO_GRAYSCALE: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / dev->def->x_resolution_max); if ((dev->def->tecoref == TECO_VM656A || dev->def->tecoref == TECO_VM6586) && ((dev->width * dev->x_resolution) % dev->def->x_resolution_max != 0)) { /* Round up */ dev->params.pixels_per_line += 1; } dev->params.bytes_per_line = dev->params.pixels_per_line; dev->params.depth = 8; dev->color_adjust = NULL; break; case TECO_COLOR: dev->params.format = SANE_FRAME_RGB; dev->params.pixels_per_line = ((dev->width * dev->x_resolution) / dev->def->x_resolution_max); if ((dev->def->tecoref == TECO_VM656A || dev->def->tecoref == TECO_VM6586) && ((dev->width * dev->x_resolution) % dev->def->x_resolution_max != 0)) { /* Round up */ dev->params.pixels_per_line += 1; } dev->params.bytes_per_line = dev->params.pixels_per_line * 3; dev->params.depth = 8; if (dev->resolutions_list != NULL) { /* This scanner has a fixed number of supported * resolutions. Find the color shift for that * resolution. */ int i; for (i = 0; dev->def->color_adjust[i].resolution != dev->y_resolution; i++); dev->color_adjust = &dev->def->color_adjust[i]; } else { dev->color_adjust = &dev->def->color_adjust[0]; } break; } dev->params.lines = (dev->length * dev->y_resolution) / dev->def->x_resolution_max; } /* Return the current values. */ if (params) { *params = (dev->params); } DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Teco_Scanner *dev = handle; SANE_Status status; DBG (DBG_proc, "sane_start: enter\n"); if (!(dev->scanning)) { sane_get_parameters (dev, NULL); /* Open again the scanner. */ if (sanei_scsi_open (dev->devicename, &(dev->sfd), teco_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: sane_start: open failed\n"); return SANE_STATUS_INVAL; } /* The scanner must be ready. */ status = teco_wait_scanner (dev); if (status) { teco_close (dev); return status; } status = teco_set_window (dev); if (status) { teco_close (dev); return status; } status = teco_get_scan_size (dev); if (status) { teco_close (dev); return status; } /* Compute the length necessary in image. The first part will store * the complete lines, and the rest is used to stored ahead * rasters. */ if (dev->color_adjust) { dev->raster_ahead = (2 * dev->color_adjust->color_shift) * dev->params.bytes_per_line; } else { dev->raster_ahead = 0; } dev->image_size = dev->buffer_size + dev->raster_ahead; dev->image = malloc (dev->image_size); if (dev->image == NULL) { return SANE_STATUS_NO_MEM; } /* Rasters are meaningfull only in color mode. */ dev->raster_size = dev->params.pixels_per_line; dev->raster_real = dev->params.lines * 3; dev->raster_num = 0; dev->line = 0; #if 1 status = teco_do_calibration (dev); if (status) { teco_close (dev); return status; } #endif switch (dev->def->tecoref) { /* case TECO_VM3564: not for VM3564 */ case TECO_VM356A: /*--------------request sense for first time loop---*/ status = teco_request_sense (dev); if (status) { teco_close (dev); return status; } break; default: break; } status = teco_send_gamma (dev); if (status) { teco_close (dev); return status; } status = teco_set_window (dev); if (status) { teco_close (dev); return status; } switch (dev->def->tecoref) { case TECO_VM3564: case TECO_VM356A: break; default: status = teco_send_vendor_06 (dev); if (status) { teco_close (dev); return status; } } status = teco_scan (dev); if (status) { teco_close (dev); return status; } status = teco_wait_for_data (dev); if (status) { teco_close (dev); return status; } } dev->image_end = 0; dev->image_begin = 0; dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->real_bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->scanning = SANE_TRUE; DBG (DBG_proc, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status status; Teco_Scanner *dev = handle; size_t size; int buf_offset; /* offset into buf */ DBG (DBG_proc, "sane_read: enter\n"); *len = 0; if (!(dev->scanning)) { /* OOPS, not scanning */ return do_cancel (dev); } if (dev->bytes_left <= 0) { return (SANE_STATUS_EOF); } buf_offset = 0; do { if (dev->image_begin == dev->image_end) { /* Fill image */ status = teco_fill_image (dev); if (status != SANE_STATUS_GOOD) { return (status); } } /* Something must have been read */ #if 1 assert (dev->image_begin != dev->image_end); #else if (dev->image_begin == dev->image_end) { DBG (DBG_info, "sane_read: nothing read\n"); return SANE_STATUS_IO_ERROR; } #endif /* Copy the data to the frontend buffer. */ size = max_len - buf_offset; if (size > dev->bytes_left) { size = dev->bytes_left; } teco_copy_raw_to_frontend (dev, buf + buf_offset, &size); buf_offset += size; dev->bytes_left -= size; *len += size; } while ((buf_offset != max_len) && dev->bytes_left); DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", (long) dev->bytes_left); return SANE_STATUS_GOOD; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { SANE_Status status; Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_set_io_mode: enter\n"); if (dev->scanning == SANE_FALSE) { return SANE_STATUS_INVAL; } if (non_blocking == SANE_FALSE) { status = SANE_STATUS_GOOD; } else { status = SANE_STATUS_UNSUPPORTED; } DBG (DBG_proc, "sane_set_io_mode: exit\n"); return status; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { DBG (DBG_proc, "sane_get_select_fd: enter\n"); DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } void sane_cancel (SANE_Handle handle) { Teco_Scanner *dev = handle; DBG (DBG_proc, "sane_cancel: enter\n"); do_cancel (dev); DBG (DBG_proc, "sane_cancel: exit\n"); } void sane_close (SANE_Handle handle) { Teco_Scanner *dev = handle; Teco_Scanner *dev_tmp; DBG (DBG_proc, "sane_close: enter\n"); do_cancel (dev); teco_close (dev); /* Unlink dev. */ if (first_dev == dev) { first_dev = dev->next; } else { dev_tmp = first_dev; while (dev_tmp->next && dev_tmp->next != dev) { dev_tmp = dev_tmp->next; } if (dev_tmp->next != NULL) { dev_tmp->next = dev_tmp->next->next; } } teco_free (dev); num_devices--; DBG (DBG_proc, "sane_close: exit\n"); } void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); while (first_dev) { sane_close (first_dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); } sane-backends-1.0.27/backend/u12.c0000664000175000017500000014501012775312261013373 00000000000000/** @file u12.c * @brief SANE backend for USB scanner, based on Plusteks' ASIC P98003 and * the GeneSys Logic GL640 parallel-port to USB bridge. * * Based on source aquired from Plustek
* Copyright (c) 2003-2004 Gerhard Jaeger
* * History: * - 0.01 - initial version * - 0.02 - enabled other scan-modes * - increased default gamma to 1.5 *. *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_VERSION "0.02-11" #define BACKEND_NAME u12 #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_thread.h" #include "../include/sane/sanei_usb.h" #define ALL_MODES #include "u12-scanner.h" #include "u12-hwdef.h" #include "u12.h" /*********************** the debug levels ************************************/ #define _DBG_FATAL 0 #define _DBG_ERROR 1 #define _DBG_WARNING 3 #define _DBG_INFO 5 #define _DBG_PROC 7 #define _DBG_SANE_INIT 10 #define _DBG_IO 128 #define _DBG_READ 255 /* uncomment this for testing... */ /*#define _FAKE_DEVICE */ /*****************************************************************************/ #define _SECTION "[usb]" #define _DEFAULT_DEVICE "auto" /* including the "worker" code... */ #include "u12-io.c" #include "u12-ccd.c" #include "u12-hw.c" #include "u12-motor.c" #include "u12-image.c" #include "u12-map.c" #include "u12-shading.c" #include "u12-tpa.c" #include "u12-if.c" /************************** global vars **************************************/ static int num_devices; static U12_Device *first_dev; static U12_Scanner *first_handle; static const SANE_Device **devlist = 0; static unsigned long tsecs = 0; static SANE_Bool cancelRead; #ifdef ALL_MODES static ModeParam mode_params[] = { {0, 1, COLOR_BW}, {0, 8, COLOR_256GRAY}, {1, 8, COLOR_TRUE24}, {1, 16, COLOR_TRUE42} }; static const SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, SANE_I18N("Color 36"), NULL }; static const SANE_String_Const src_list[] = { SANE_I18N("Normal"), SANE_I18N("Transparency"), SANE_I18N("Negative"), NULL }; #endif static const SANE_Range percentage_range = { -100 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 1 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; /* authorization stuff */ static SANE_Auth_Callback auth = NULL; /****************************** the backend... *******************************/ #define _YN(x) (x?"yes":"no") /** * function to display the configuration options for the current device * @param cnf - pointer to the configuration structure whose content should be * displayed */ static void show_cnf( pCnfDef cnf ) { DBG( _DBG_SANE_INIT,"Device configuration:\n" ); DBG( _DBG_SANE_INIT,"device name : >%s<\n",cnf->devName ); DBG( _DBG_SANE_INIT,"USB-ID : >%s<\n",cnf->usbId ); DBG( _DBG_SANE_INIT,"warmup : %ds\n", cnf->adj.warmup ); DBG( _DBG_SANE_INIT,"lampOff : %d\n", cnf->adj.lampOff ); DBG( _DBG_SANE_INIT,"lampOffOnEnd : %s\n", _YN(cnf->adj.lampOffOnEnd )); DBG( _DBG_SANE_INIT,"red Gamma : %.2f\n",cnf->adj.rgamma ); DBG( _DBG_SANE_INIT,"green Gamma : %.2f\n",cnf->adj.ggamma ); DBG( _DBG_SANE_INIT,"blue Gamma : %.2f\n",cnf->adj.bgamma ); DBG( _DBG_SANE_INIT,"gray Gamma : %.2f\n",cnf->adj.graygamma ); DBG( _DBG_SANE_INIT,"---------------------\n" ); } /** Calls the device specific stop and close functions. * @param dev - pointer to the device specific structure * @return The function always returns SANE_STATUS_GOOD */ static SANE_Status drvClose( U12_Device *dev ) { if( dev->fd >= 0 ) { DBG( _DBG_INFO, "drvClose()\n" ); if( 0 != tsecs ) { DBG( _DBG_INFO, "TIME END 1: %lus\n", time(NULL)-tsecs); } /* don't check the return values, simply do it */ u12if_stopScan( dev ); u12if_close ( dev ); } dev->fd = -1; return SANE_STATUS_GOOD; } /** as the name says, close our pipes * @param scanner - * @return */ static SANE_Status drvClosePipes( U12_Scanner *scanner ) { if( scanner->r_pipe >= 0 ) { DBG( _DBG_PROC, "drvClosePipes(r_pipe)\n" ); close( scanner->r_pipe ); scanner->r_pipe = -1; } if( scanner->w_pipe >= 0 ) { DBG( _DBG_PROC, "drvClosePipes(w_pipe)\n" ); close( scanner->w_pipe ); scanner->w_pipe = -1; } return SANE_STATUS_EOF; } #ifdef ALL_MODES /** according to the mode and source we return the corresponding mode list */ static pModeParam getModeList( U12_Scanner *scanner ) { pModeParam mp = mode_params; /* the transparency/negative mode supports only gray and color */ if( 0 != scanner->val[OPT_EXT_MODE].w ) { mp = &mp[_TPAModeSupportMin]; } return mp; } #endif /** goes through a string list and returns the start-address of the string * that has been found, or NULL on error */ static const SANE_String_Const *search_string_list( const SANE_String_Const *list, SANE_String value ) { while( *list != NULL && strcmp(value, *list) != 0 ) ++list; if( *list == NULL ) return NULL; return list; } /** */ static void sig_chldhandler( int signo ) { DBG( _DBG_PROC, "(SIG) Child is down (signal=%d)\n", signo ); } /** signal handler to kill the child process */ static void reader_process_sigterm_handler( int signo ) { DBG( _DBG_PROC, "(SIG) reader_process: terminated by signal %d\n", signo ); _exit( SANE_STATUS_GOOD ); } static void usb_reader_process_sigterm_handler( int signo ) { DBG( _DBG_PROC, "(SIG) reader_process: terminated by signal %d\n", signo ); cancelRead = SANE_TRUE; } static void sigalarm_handler( int signo ) { _VAR_NOT_USED( signo ); DBG( _DBG_PROC, "ALARM!!!\n" ); } /** executed as a child process * read the data from the driver and send them to the parent process */ static int reader_process( void *args ) { int line; unsigned char *buf; unsigned long data_length; struct SIGACTION act; sigset_t ignore_set; SANE_Status status; U12_Scanner *scanner = (U12_Scanner *)args; if( sanei_thread_is_forked()) { DBG( _DBG_PROC, "reader_process started (forked)\n" ); close( scanner->r_pipe ); scanner->r_pipe = -1; } else { DBG( _DBG_PROC, "reader_process started (as thread)\n" ); } sigfillset ( &ignore_set ); sigdelset ( &ignore_set, SIGTERM ); #if defined (__APPLE__) && defined (__MACH__) sigdelset ( &ignore_set, SIGUSR2 ); #endif sigprocmask( SIG_SETMASK, &ignore_set, 0 ); cancelRead = SANE_FALSE; /* install the signal handler */ memset( &act, 0, sizeof (act)); sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = reader_process_sigterm_handler; sigaction( SIGTERM, &act, 0 ); act.sa_handler = usb_reader_process_sigterm_handler; sigaction( SIGUSR1, &act, 0 ); data_length = scanner->params.lines * scanner->params.bytes_per_line; DBG( _DBG_PROC, "reader_process:" "starting to READ data (%lu bytes)\n", data_length ); DBG( _DBG_PROC, "buf = 0x%08lx\n", (unsigned long)scanner->buf ); if( NULL == scanner->buf ) { DBG( _DBG_FATAL, "NULL Pointer !!!!\n" ); return SANE_STATUS_IO_ERROR; } /* here we read all data from the scanner... */ buf = scanner->buf; status = u12if_prepare( scanner->hw ); if( SANE_STATUS_GOOD == status ) { for( line = 0; line < scanner->params.lines; line++ ) { status = u12if_readLine( scanner->hw, buf ); if( SANE_STATUS_GOOD != status ) { break; } write( scanner->w_pipe, buf, scanner->params.bytes_per_line ); buf += scanner->params.bytes_per_line; } } close( scanner->w_pipe ); scanner->w_pipe = -1; /* on error, there's no need to clean up, as this is done by the parent */ if( SANE_STATUS_GOOD != status ) { DBG( _DBG_ERROR, "read failed, status = %i\n", (int)status ); return status; } DBG( _DBG_PROC, "reader_process: finished reading data\n" ); return SANE_STATUS_GOOD; } /** stop the current scan process */ static SANE_Status do_cancel( U12_Scanner *scanner, SANE_Bool closepipe ) { struct SIGACTION act; SANE_Pid res; DBG( _DBG_PROC,"do_cancel\n" ); scanner->scanning = SANE_FALSE; if( sanei_thread_is_valid (scanner->reader_pid) ) { DBG( _DBG_PROC, ">>>>>>>> killing reader_process <<<<<<<<\n" ); cancelRead = SANE_TRUE; sigemptyset(&(act.sa_mask)); act.sa_flags = 0; act.sa_handler = sigalarm_handler; sigaction( SIGALRM, &act, 0 ); /* kill our child process and wait until done */ sanei_thread_sendsig( scanner->reader_pid, SIGUSR1 ); /* give'em 10 seconds 'til done...*/ alarm(10); res = sanei_thread_waitpid( scanner->reader_pid, 0 ); alarm(0); if( res != scanner->reader_pid ) { DBG( _DBG_PROC,"sanei_thread_waitpid() failed !\n"); /* do it the hard way...*/ #ifdef USE_PTHREAD sanei_thread_kill( scanner->reader_pid ); #else sanei_thread_sendsig( scanner->reader_pid, SIGKILL ); #endif } scanner->reader_pid = -1; DBG( _DBG_PROC, "reader_process killed\n"); if( scanner->hw->fd >= 0 ) { u12hw_CancelSequence( scanner->hw ); } #ifndef HAVE_SETITIMER u12hw_StartLampTimer( scanner->hw ); #endif } if( SANE_TRUE == closepipe ) { drvClosePipes( scanner ); } drvClose( scanner->hw ); if( tsecs != 0 ) { DBG( _DBG_INFO, "TIME END 2: %lus\n", time(NULL)-tsecs); tsecs = 0; } return SANE_STATUS_CANCELLED; } /** initialize the options for the backend according to the device we have */ static SANE_Status init_options( U12_Scanner *s ) { int i; memset( s->opt, 0, sizeof(s->opt)); for( i = 0; i < NUM_OPTIONS; ++i ) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_MODE_GROUP].name = "scanmode-group"; s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; #ifdef ALL_MODES /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = 32; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = COLOR_TRUE24; /* scan source */ s->opt[OPT_EXT_MODE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_EXT_MODE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_EXT_MODE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_EXT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_EXT_MODE].size = 32; s->opt[OPT_EXT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_EXT_MODE].constraint.string_list = src_list; s->val[OPT_EXT_MODE].w = 0; /* Normal */ #endif /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; s->val[OPT_BRIGHTNESS].w = 0; /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; s->val[OPT_CONTRAST].w = 0; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = 0; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].name = "geometry-group"; s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TLX); /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TLY); /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_BRX); /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY); /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; u12map_InitGammaSettings( s->hw ); /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR].wa = &(s->hw->gamma_table[0][0]); s->opt[OPT_GAMMA_VECTOR].constraint.range = &(s->hw->gamma_range); s->opt[OPT_GAMMA_VECTOR].size = s->hw->gamma_length * sizeof(SANE_Word); /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_R].wa = &(s->hw->gamma_table[1][0]); s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(s->hw->gamma_range); s->opt[OPT_GAMMA_VECTOR_R].size = s->hw->gamma_length * sizeof(SANE_Word); /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_G].wa = &(s->hw->gamma_table[2][0]); s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(s->hw->gamma_range); s->opt[OPT_GAMMA_VECTOR_G].size = s->hw->gamma_length * sizeof(SANE_Word); /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->val[OPT_GAMMA_VECTOR_B].wa = &(s->hw->gamma_table[3][0]); s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(s->hw->gamma_range); s->opt[OPT_GAMMA_VECTOR_B].size = s->hw->gamma_length * sizeof(SANE_Word); /* GAMMA stuff is disabled per default */ s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; #ifdef ALL_MODES /* disable extended mode list for devices without TPA */ if( SANE_FALSE == s->hw->Tpa ) { s->opt[OPT_EXT_MODE].cap |= SANE_CAP_INACTIVE; } #endif return SANE_STATUS_GOOD; } /** Function to retrieve the vendor and product id from a given string * @param src - string, that should be investigated * @param dest - pointer to a string to receive the USB ID */ static void decodeUsbIDs( char *src, char **dest ) { const char *name; char *tmp = *dest; int len = strlen(_SECTION); if( isspace(src[len])) { strncpy( tmp, &src[len+1], (strlen(src)-(len+1))); tmp[(strlen(src)-(len+1))] = '\0'; } name = tmp; name = sanei_config_skip_whitespace( name ); if( '\0' == name[0] ) { DBG( _DBG_SANE_INIT, "next device uses autodetection\n" ); } else { u_short pi = 0, vi = 0; if( *name ) { name = sanei_config_get_string( name, &tmp ); if( tmp ) { vi = strtol( tmp, 0, 0 ); free( tmp ); } } name = sanei_config_skip_whitespace( name ); if( *name ) { name = sanei_config_get_string( name, &tmp ); if( tmp ) { pi = strtol( tmp, 0, 0 ); free( tmp ); } } /* create what we need to go through our device list...*/ sprintf( *dest, "0x%04X-0x%04X", vi, pi ); DBG( _DBG_SANE_INIT, "next device is a USB device (%s)\n", *dest ); } } #define _INT 0 #define _FLOAT 1 /** function to decode an value and give it back to the caller. * @param src - pointer to the source string to check * @param opt - string that keeps the option name to check src for * @param what - _FLOAT or _INT * @param result - pointer to the var that should receive our result * @param def - default value that result should be in case of any error * @return The function returns SANE_TRUE if the option has been found, * if not, it returns SANE_FALSE */ static SANE_Bool decodeVal( char *src, char *opt, int what, void *result, void *def ) { char *tmp, *tmp2; const char *name; /* skip the option string */ name = (const char*)&src[strlen("option")]; /* get the name of the option */ name = sanei_config_get_string( name, &tmp ); if( tmp ) { /* on success, compare wiht the given one */ if( 0 == strcmp( tmp, opt )) { DBG( _DBG_SANE_INIT, "Decoding option >%s<\n", opt ); if( _INT == what ) { /* assign the default value for this option... */ *((int*)result) = *((int*)def); if( *name ) { /* get the configuration value and decode it */ name = sanei_config_get_string( name, &tmp2 ); if( tmp2 ) { *((int*)result) = strtol( tmp2, 0, 0 ); free( tmp2 ); } } free( tmp ); return SANE_TRUE; } else if( _FLOAT == what ) { /* assign the default value for this option... */ *((double*)result) = *((double*)def); if( *name ) { /* get the configuration value and decode it */ name = sanei_config_get_string( name, &tmp2 ); if( tmp2 ) { *((double*)result) = strtod( tmp2, 0 ); free( tmp2 ); } } free( tmp ); return SANE_TRUE; } } free( tmp ); } return SANE_FALSE; } /** function to retrive the device name of a given string * @param src - string that keeps the option name to check src for * @param dest - pointer to the string, that should receive the detected * devicename * @return The function returns SANE_TRUE if the devicename has been found, * if not, it returns SANE_FALSE */ static SANE_Bool decodeDevName( char *src, char *dest ) { char *tmp; const char *name; if( 0 == strncmp( "device", src, 6 )) { name = (const char*)&src[strlen("device")]; name = sanei_config_skip_whitespace( name ); DBG( _DBG_SANE_INIT, "Decoding device name >%s<\n", name ); if( *name ) { name = sanei_config_get_string( name, &tmp ); if( tmp ) { strcpy( dest, tmp ); free( tmp ); return SANE_TRUE; } } } return SANE_FALSE; } /** attach a device to the backend */ static SANE_Status attach( const char *dev_name, pCnfDef cnf, U12_Device **devp ) { int result; int handle; U12_Device *dev; DBG( _DBG_SANE_INIT, "attach (%s, %p, %p)\n", dev_name, (void *)cnf, (void *)devp); /* already attached ?*/ for( dev = first_dev; dev; dev = dev->next ) { if( 0 == strcmp( dev->sane.name, dev_name )) { if( devp ) *devp = dev; return SANE_STATUS_GOOD; } } /* allocate some memory for the device */ dev = malloc( sizeof (*dev)); if( NULL == dev ) return SANE_STATUS_NO_MEM; /* assign all the stuff we need fo this device... */ memset(dev, 0, sizeof (*dev)); dev->fd = -1; dev->name = strdup(dev_name); /* hold it double to avoid */ dev->sane.name = dev->name; /* compiler warnings */ dev->sane.vendor = "Plustek"; dev->sane.model = "U12/1212U"; dev->sane.type = SANE_I18N ("flatbed scanner"); dev->initialized = SANE_FALSE; memcpy( &dev->adj, &cnf->adj, sizeof(AdjDef)); show_cnf( cnf ); strncpy( dev->usbId, cnf->usbId, _MAX_ID_LEN ); /* go ahead and open the scanner device */ handle = u12if_open( dev ); if( handle < 0 ) { DBG( _DBG_ERROR,"open failed: %d\n", handle ); return SANE_STATUS_IO_ERROR; } /* okay, so assign the handle... */ dev->fd = handle; /* now check what we have */ result = u12if_getCaps( dev ); if( result < 0 ) { DBG( _DBG_ERROR, "u12if_getCaps() failed(%d)\n", result); u12if_close( dev ); return SANE_STATUS_IO_ERROR; } /* save the info we got from the driver */ DBG( _DBG_INFO, "Scanner information:\n" ); DBG( _DBG_INFO, "Vendor : %s\n", dev->sane.vendor ); DBG( _DBG_INFO, "Model : %s\n", dev->sane.model ); DBG( _DBG_INFO, "Flags : 0x%08lx\n", dev->caps.flag ); if( SANE_STATUS_GOOD != u12if_SetupBuffer( dev )) { DBG( _DBG_ERROR, "u12if_SetupBuffer() failed\n" ); u12if_close( dev ); return SANE_STATUS_NO_MEM; } drvClose( dev ); DBG( _DBG_SANE_INIT, "attach: model = >%s<\n", dev->sane.model ); ++num_devices; dev->next = first_dev; first_dev = dev; if( devp ) *devp = dev; return SANE_STATUS_GOOD; } /** function to preset a configuration structure * @param cnf - pointer to the structure that should be initialized */ static void init_config_struct( pCnfDef cnf ) { memset( cnf, 0, sizeof(CnfDef)); cnf->adj.warmup = -1; cnf->adj.lampOff = -1; cnf->adj.lampOffOnEnd = -1; cnf->adj.graygamma = 1.0; cnf->adj.rgamma = 1.0; cnf->adj.ggamma = 1.0; cnf->adj.bgamma = 1.0; } /** intialize the backend */ SANE_Status sane_init( SANE_Int *version_code, SANE_Auth_Callback authorize ) { char str[PATH_MAX] = _DEFAULT_DEVICE; CnfDef config; size_t len; FILE *fp; DBG_INIT(); sanei_usb_init(); sanei_thread_init(); DBG( _DBG_INFO, "U12 backend V" BACKEND_VERSION", part of "PACKAGE " " VERSION "\n"); /* do some presettings... */ auth = authorize; first_dev = NULL; first_handle = NULL; num_devices = 0; /* initialize the configuration structure */ init_config_struct( &config ); if( version_code != NULL ) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, 0); fp = sanei_config_open( U12_CONFIG_FILE ); /* default to _DEFAULT_DEVICE instead of insisting on config file */ if( NULL == fp ) { return attach( _DEFAULT_DEVICE, &config, 0 ); } while( sanei_config_read( str, sizeof(str), fp)) { DBG( _DBG_SANE_INIT, ">%s<\n", str ); if( str[0] == '#') /* ignore line comments */ continue; len = strlen(str); if( 0 == len ) continue; /* ignore empty lines */ /* check for options */ if( 0 == strncmp(str, "option", 6)) { int ival; double dval; ival = -1; decodeVal( str, "warmup", _INT, &config.adj.warmup, &ival); decodeVal( str, "lampOff", _INT, &config.adj.lampOff, &ival); decodeVal( str, "lOffOnEnd", _INT, &config.adj.lampOffOnEnd,&ival); ival = 0; dval = 1.5; decodeVal( str, "grayGamma", _FLOAT, &config.adj.graygamma,&dval); decodeVal( str, "redGamma", _FLOAT, &config.adj.rgamma, &dval ); decodeVal( str, "greenGamma", _FLOAT, &config.adj.ggamma, &dval ); decodeVal( str, "blueGamma", _FLOAT, &config.adj.bgamma, &dval ); continue; /* check for sections: */ } else if( 0 == strncmp( str, _SECTION, strlen(_SECTION))) { char *tmp; /* new section, try and attach previous device */ if( config.devName[0] != '\0' ) { attach( config.devName, &config, 0 ); } else { if( first_dev != NULL ) { DBG( _DBG_WARNING, "section contains no device name," " ignored!\n" ); } } /* re-initialize the configuration structure */ init_config_struct( &config ); tmp = config.usbId; decodeUsbIDs( str, &tmp ); DBG( _DBG_SANE_INIT, "... next device\n" ); continue; } else if( SANE_TRUE == decodeDevName( str, config.devName )) { continue; } /* ignore other stuff... */ DBG( _DBG_SANE_INIT, "ignoring >%s<\n", str ); } fclose( fp ); /* try to attach the last device in the config file... */ if( config.devName[0] != '\0' ) attach( config.devName, &config, 0 ); return SANE_STATUS_GOOD; } /** cleanup the backend... */ void sane_exit( void ) { U12_Device *dev, *next; DBG( _DBG_SANE_INIT, "sane_exit\n" ); for( dev = first_dev; dev; ) { next = dev->next; u12if_shutdown( dev ); /* * we're doin' this to avoid compiler warnings as dev->sane.name * is defined as const char* */ if( dev->sane.name ) free( dev->name ); if( dev->res_list ) free( dev->res_list ); free( dev ); dev = next; } if( devlist ) free( devlist ); devlist = NULL; auth = NULL; first_dev = NULL; first_handle = NULL; } /** return a list of all devices */ SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only ) { int i; U12_Device *dev; DBG(_DBG_SANE_INIT, "sane_get_devices (%p, %ld)\n", (void *)device_list, (long) local_only); /* already called, so cleanup */ if( devlist ) free( devlist ); devlist = malloc((num_devices + 1) * sizeof (devlist[0])); if ( NULL == devlist ) return SANE_STATUS_NO_MEM; i = 0; for( dev = first_dev; i < num_devices; dev = dev->next ) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } /** open the sane device */ SANE_Status sane_open( SANE_String_Const devicename, SANE_Handle* handle ) { SANE_Status status; U12_Device *dev; U12_Scanner *s; CnfDef config; DBG( _DBG_SANE_INIT, "sane_open - %s\n", devicename ); if( devicename[0] ) { for( dev = first_dev; dev; dev = dev->next ) { if( strcmp( dev->sane.name, devicename ) == 0 ) break; } if( !dev ) { memset( &config, 0, sizeof(CnfDef)); status = attach( devicename, &config, &dev ); if( SANE_STATUS_GOOD != status ) return status; } } else { /* empty devicename -> use first device */ dev = first_dev; } if( !dev ) return SANE_STATUS_INVAL; s = malloc (sizeof (*s)); if( NULL == s ) return SANE_STATUS_NO_MEM; memset(s, 0, sizeof (*s)); s->r_pipe = -1; s->w_pipe = -1; s->hw = dev; s->scanning = SANE_FALSE; init_options( s ); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; return SANE_STATUS_GOOD; } /** */ void sane_close( SANE_Handle handle ) { U12_Scanner *prev, *s; DBG( _DBG_SANE_INIT, "sane_close\n" ); /* remove handle from list of open handles: */ prev = 0; for( s = first_handle; s; s = s->next ) { if( s == handle ) break; prev = s; } if( !s ) { DBG( _DBG_ERROR, "close: invalid handle %p\n", handle); return; } drvClosePipes( s ); if( NULL != s->buf ) free(s->buf); if( NULL != s->hw->bufs.b1.pReadBuf ) free( s->hw->bufs.b1.pReadBuf ); if( NULL != s->hw->shade.pHilight ) free( s->hw->shade.pHilight ); if( NULL != s->hw->scaleBuf ) free( s->hw->scaleBuf ); drvClose( s->hw ); if (prev) prev->next = s->next; else first_handle = s->next; free(s); } /** return or set the parameter values, also do some checks */ SANE_Status sane_control_option( SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { U12_Scanner *s = (U12_Scanner *)handle; SANE_Status status; const SANE_String_Const *optval; #ifdef ALL_MODES pModeParam mp; int idx; #endif int scanmode; if ( s->scanning ) return SANE_STATUS_DEVICE_BUSY; if((option < 0) || (option >= NUM_OPTIONS)) return SANE_STATUS_INVAL; if( NULL != info ) *info = 0; switch( action ) { case SANE_ACTION_GET_VALUE: switch (option) { case OPT_PREVIEW: case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_CUSTOM_GAMMA: *(SANE_Word *)value = s->val[option].w; break; case OPT_CONTRAST: case OPT_BRIGHTNESS: *(SANE_Word *)value = (s->val[option].w << SANE_FIXED_SCALE_SHIFT); break; #ifdef ALL_MODES case OPT_MODE: case OPT_EXT_MODE: strcpy ((char *) value, s->opt[option].constraint.string_list[s->val[option].w]); break; #endif /* word array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy( value, s->val[option].wa, s->opt[option].size ); break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: status = sanei_constrain_value( s->opt + option, value, info ); if( SANE_STATUS_GOOD != status ) return status; optval = NULL; if( SANE_CONSTRAINT_STRING_LIST == s->opt[option].constraint_type ) { optval = search_string_list( s->opt[option].constraint.string_list, (char *) value); if( NULL == optval ) return SANE_STATUS_INVAL; } switch (option) { case OPT_RESOLUTION: { int n; int min_d = s->hw->res_list[s->hw->res_list_size - 1]; int v = *(SANE_Word *)value; int best = v; for( n = 0; n < s->hw->res_list_size; n++ ) { int d = abs(v - s->hw->res_list[n]); if( d < min_d ) { min_d = d; best = s->hw->res_list[n]; } } s->val[option].w = (SANE_Word)best; if( v != best ) *(SANE_Word *)value = best; if( NULL != info ) { if( v != best ) *info |= SANE_INFO_INEXACT; *info |= SANE_INFO_RELOAD_PARAMS; } break; } case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *)value; if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_CUSTOM_GAMMA: s->val[option].w = *(SANE_Word *)value; if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; #ifdef ALL_MODES mp = getModeList( s ); scanmode = mp[s->val[OPT_MODE].w].scanmode; #else scanmode = COLOR_TRUE24; #endif s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; if( SANE_TRUE == s->val[option].w ) { if( scanmode == COLOR_256GRAY ) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { u12map_InitGammaSettings( s->hw ); if( scanmode == COLOR_256GRAY ) { s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } } break; case OPT_CONTRAST: case OPT_BRIGHTNESS: s->val[option].w = ((*(SANE_Word *)value) >> SANE_FIXED_SCALE_SHIFT); break; #ifdef ALL_MODES case OPT_MODE: idx = (optval - mode_list); mp = getModeList( s ); s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if( mp[idx].scanmode == COLOR_BW ) { s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; } s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; if( s->val[OPT_CUSTOM_GAMMA].w && !(s->opt[OPT_CUSTOM_GAMMA].cap & SANE_CAP_INACTIVE)) { if( mp[idx].scanmode == COLOR_256GRAY ) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } if( NULL != info ) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; s->val[option].w = optval - s->opt[option].constraint.string_list; break; case OPT_EXT_MODE: { s->val[option].w = optval - s->opt[option].constraint.string_list; /* * change the area and mode_list when changing the source */ if( s->val[option].w == 0 ) { s->hw->dpi_range.min = _DEF_DPI; s->hw->x_range.max = SANE_FIX(s->hw->max_x); s->hw->y_range.max = SANE_FIX(s->hw->max_y); s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_BRY); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = COLOR_TRUE24; } else { s->hw->dpi_range.min = _TPAMinDpi; if( s->val[option].w == 1 ) { s->hw->x_range.max = SANE_FIX(_TP_X); s->hw->y_range.max = SANE_FIX(_TP_Y); s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_TP_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_TP_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_TP_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_TP_BRY); } else { s->hw->x_range.max = SANE_FIX(_NEG_X); s->hw->y_range.max = SANE_FIX(_NEG_Y); s->val[OPT_TL_X].w = SANE_FIX(_DEFAULT_NEG_TLX); s->val[OPT_TL_Y].w = SANE_FIX(_DEFAULT_NEG_TLY); s->val[OPT_BR_X].w = SANE_FIX(_DEFAULT_NEG_BRX); s->val[OPT_BR_Y].w = SANE_FIX(_DEFAULT_NEG_BRY); } s->opt[OPT_MODE].constraint.string_list = &mode_list[_TPAModeSupportMin]; s->val[OPT_MODE].w = 0; /* COLOR_24 is the default */ } s->opt[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE; if( NULL != info ) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; } #endif case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy( s->val[option].wa, value, s->opt[option].size ); u12map_CheckGammaSettings(s->hw); if( NULL != info ) *info |= SANE_INFO_RELOAD_PARAMS; break; default: return SANE_STATUS_INVAL; } break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } /** according to the option number, return a pointer to a descriptor */ const SANE_Option_Descriptor * sane_get_option_descriptor( SANE_Handle handle, SANE_Int option ) { U12_Scanner *s = (U12_Scanner *)handle; if((option < 0) || (option >= NUM_OPTIONS)) return NULL; return &(s->opt[option]); } /** return the current parameter settings */ SANE_Status sane_get_parameters( SANE_Handle handle, SANE_Parameters *params ) { int ndpi; #ifdef ALL_MODES pModeParam mp; #endif U12_Scanner *s = (U12_Scanner *)handle; /* if we're called from within, calc best guess * do the same, if sane_get_parameters() is called * by a frontend before sane_start() is called */ if((NULL == params) || (s->scanning != SANE_TRUE)) { #ifdef ALL_MODES mp = getModeList( s ); #endif memset( &s->params, 0, sizeof (SANE_Parameters)); ndpi = s->val[OPT_RESOLUTION].w; s->params.pixels_per_line = SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) / _MM_PER_INCH * ndpi; s->params.lines = SANE_UNFIX( s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) / _MM_PER_INCH * ndpi; /* pixels_per_line seems to be 8 * n. */ /* s->params.pixels_per_line = s->params.pixels_per_line & ~7; debug only */ s->params.last_frame = SANE_TRUE; #ifdef ALL_MODES s->params.depth = mp[s->val[OPT_MODE].w].depth; #else s->params.depth = 8; s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line; #endif #ifdef ALL_MODES if( mp[s->val[OPT_MODE].w].color ) { s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line; } else { s->params.format = SANE_FRAME_GRAY; if (s->params.depth == 1) s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; else s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8; } #endif /* if sane_get_parameters() was called before sane_start() */ /* pass new values to the caller */ if ((NULL != params) && (s->scanning != SANE_TRUE)) *params = s->params; } else *params = s->params; return SANE_STATUS_GOOD; } /** initiate the scan process */ SANE_Status sane_start( SANE_Handle handle ) { U12_Scanner *s = (U12_Scanner *)handle; U12_Device *dev; #ifdef ALL_MODES ModeParam *mp; #endif int result; int ndpi; int left, top; int width, height; int scanmode; int fds[2]; double dpi_x, dpi_y; ImgDef image; SANE_Status status; SANE_Word tmp; DBG( _DBG_SANE_INIT, "sane_start\n" ); if( s->scanning ) { return SANE_STATUS_DEVICE_BUSY; } status = sane_get_parameters (handle, NULL); if (status != SANE_STATUS_GOOD) { DBG( _DBG_ERROR, "sane_get_parameters failed\n" ); return status; } dev = s->hw; /* open the driver and get some information about the scanner */ dev->fd = u12if_open( dev ); if( dev->fd < 0 ) { DBG( _DBG_ERROR,"sane_start: open failed: %d\n", errno ); if( errno == EBUSY ) return SANE_STATUS_DEVICE_BUSY; return SANE_STATUS_IO_ERROR; } tsecs = 0; result = u12if_getCaps( dev ); if( result < 0 ) { DBG( _DBG_ERROR, "u12if_getCaps() failed(%d)\n", result); u12if_close( dev ); return SANE_STATUS_IO_ERROR; } /* All ready to go. Set image def and see what the scanner * says for crop info. */ ndpi = s->val[OPT_RESOLUTION].w; /* exchange the values as we can't deal with negative heights and so on...*/ tmp = s->val[OPT_TL_X].w; if( tmp > s->val[OPT_BR_X].w ) { DBG( _DBG_INFO, "exchanging BR-X - TL-X\n" ); s->val[OPT_TL_X].w = s->val[OPT_BR_X].w; s->val[OPT_BR_X].w = tmp; } tmp = s->val[OPT_TL_Y].w; if( tmp > s->val[OPT_BR_Y].w ) { DBG( _DBG_INFO, "exchanging BR-Y - TL-Y\n" ); s->val[OPT_TL_Y].w = s->val[OPT_BR_Y].w; s->val[OPT_BR_Y].w = tmp; } /* position and extent are always relative to 300 dpi */ dpi_x = (double)dev->dpi_max_x; dpi_y = (double)dev->dpi_max_y; left = (int)(SANE_UNFIX(s->val[OPT_TL_X].w)* dpi_x/ (_MM_PER_INCH*(dpi_x/_MEASURE_BASE))); top = (int)(SANE_UNFIX(s->val[OPT_TL_Y].w)*dpi_y/ (_MM_PER_INCH*(dpi_y/_MEASURE_BASE))); width = (int)(SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) * dpi_x / (_MM_PER_INCH *(dpi_x/_MEASURE_BASE))); height = (int)(SANE_UNFIX(s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) * dpi_y / (_MM_PER_INCH *(dpi_y/_MEASURE_BASE))); if((width == 0) || (height == 0)) { DBG( _DBG_ERROR, "invalid width or height!\n" ); return SANE_STATUS_INVAL; } /* adjust mode list according to the model we use and the source we have */ #ifdef ALL_MODES mp = getModeList( s ); scanmode = mp[s->val[OPT_MODE].w].scanmode; #else scanmode = COLOR_TRUE24; #endif DBG( _DBG_INFO, "scanmode = %u\n", scanmode ); /* clear it out just in case */ memset (&image, 0, sizeof(ImgDef)); /* this is what we want */ image.xyDpi.x = ndpi; image.xyDpi.y = ndpi; image.crArea.x = left; /* offset from left edge to area you want to scan */ image.crArea.y = top; /* offset from top edge to area you want to scan */ image.crArea.cx = width; /* always relative to 300 dpi */ image.crArea.cy = height; image.wDataType = scanmode; #ifdef ALL_MODES switch( s->val[OPT_EXT_MODE].w ) { case 1: image.dwFlag |= _SCANDEF_Transparency; break; case 2: image.dwFlag |= _SCANDEF_Negative; break; default: break; } #endif #if 0 if( s->val[OPT_PREVIEW].w ) image.dwFlag |= _SCANDEF_PREVIEW; #endif /* set adjustments for brightness and contrast */ dev->DataInf.siBrightness = s->val[OPT_BRIGHTNESS].w; dev->DataInf.siContrast = s->val[OPT_CONTRAST].w; DBG( _DBG_SANE_INIT, "brightness %i, contrast %i\n", dev->DataInf.siBrightness, dev->DataInf.siContrast ); result = u12image_SetupScanSettings( dev, &image ); if( SANE_STATUS_GOOD != result ) { DBG( _DBG_ERROR, "u12image_SetupScanSettings() failed(%d)\n", result ); u12if_close( dev ); return SANE_STATUS_IO_ERROR; } s->params.pixels_per_line = dev->DataInf.dwAppPixelsPerLine; s->params.bytes_per_line = dev->DataInf.dwAppBytesPerLine; s->params.lines = dev->DataInf.dwAppLinesPerArea; DBG( _DBG_INFO, "* PixelPerLine = %u\n", s->params.pixels_per_line ); DBG( _DBG_INFO, "* BytesPerLine = %u\n", s->params.bytes_per_line ); DBG( _DBG_INFO, "* Lines = %u\n", s->params.lines ); /* reset our timer...*/ tsecs = 0; s->buf = realloc( s->buf, (s->params.lines) * s->params.bytes_per_line ); if( NULL == s->buf ) { DBG( _DBG_ERROR, "realloc failed\n" ); u12if_close( dev ); return SANE_STATUS_NO_MEM; } result = u12if_startScan( dev ); if( SANE_STATUS_GOOD != result ) { DBG( _DBG_ERROR, "u12if_startScan() failed(%d)\n", result ); u12if_close( dev ); return SANE_STATUS_IO_ERROR; } s->scanning = SANE_TRUE; tsecs = (unsigned long)time(NULL); DBG( _DBG_INFO, "TIME START\n" ); /* * everything prepared, so start the child process and a pipe to communicate * pipe --> fds[0]=read-fd, fds[1]=write-fd */ if( pipe(fds) < 0 ) { DBG( _DBG_ERROR, "ERROR: could not create pipe\n" ); s->scanning = SANE_FALSE; u12if_close( dev ); return SANE_STATUS_IO_ERROR; } /* create reader routine as new process */ s->bytes_read = 0; s->r_pipe = fds[0]; s->w_pipe = fds[1]; s->reader_pid = sanei_thread_begin( reader_process, s ); cancelRead = SANE_FALSE; if( !sanei_thread_is_valid (s->reader_pid) ) { DBG( _DBG_ERROR, "ERROR: could not start reader task\n" ); s->scanning = SANE_FALSE; u12if_close( dev ); return SANE_STATUS_IO_ERROR; } signal( SIGCHLD, sig_chldhandler ); if( sanei_thread_is_forked()) { close( s->w_pipe ); s->w_pipe = -1; } DBG( _DBG_SANE_INIT, "sane_start done\n" ); return SANE_STATUS_GOOD; } /** function to read the data from our child process */ SANE_Status sane_read( SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length ) { U12_Scanner *s = (U12_Scanner*)handle; ssize_t nread; *length = 0; /* here we read all data from the driver... */ nread = read( s->r_pipe, data, max_length ); DBG( _DBG_READ, "sane_read - read %ld bytes\n", (long)nread ); if (!(s->scanning)) { return do_cancel( s, SANE_TRUE ); } if( nread < 0 ) { if( EAGAIN == errno ) { /* if we already had red the picture, so it's okay and stop */ if( s->bytes_read == (unsigned long)(s->params.lines * s->params.bytes_per_line)) { sanei_thread_waitpid( s->reader_pid, 0 ); s->reader_pid = -1; drvClose( s->hw ); return drvClosePipes(s); } /* else force the frontend to try again*/ return SANE_STATUS_GOOD; } else { DBG( _DBG_ERROR, "ERROR: errno=%d\n", errno ); do_cancel( s, SANE_TRUE ); return SANE_STATUS_IO_ERROR; } } *length = nread; s->bytes_read += nread; /* nothing red means that we're finished OR we had a problem...*/ if( 0 == nread ) { drvClose( s->hw ); s->exit_code = sanei_thread_get_status( s->reader_pid ); if( SANE_STATUS_GOOD != s->exit_code ) { drvClosePipes(s); return s->exit_code; } s->reader_pid = -1; return drvClosePipes(s); } return SANE_STATUS_GOOD; } /** cancel the scanning process */ void sane_cancel( SANE_Handle handle ) { U12_Scanner *s = (U12_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_cancel\n" ); if( s->scanning ) do_cancel( s, SANE_FALSE ); } /** set the pipe to blocking/non blocking mode */ SANE_Status sane_set_io_mode( SANE_Handle handle, SANE_Bool non_blocking ) { U12_Scanner *s = (U12_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_set_io_mode: non_blocking=%d\n", non_blocking ); if ( !s->scanning ) { DBG( _DBG_ERROR, "ERROR: not scanning !\n" ); return SANE_STATUS_INVAL; } if( -1 == s->r_pipe ) { DBG( _DBG_ERROR, "ERROR: not supported !\n" ); return SANE_STATUS_UNSUPPORTED; } if( fcntl (s->r_pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { DBG( _DBG_ERROR, "ERROR: can´t set to non-blocking mode !\n" ); return SANE_STATUS_IO_ERROR; } DBG( _DBG_SANE_INIT, "sane_set_io_mode done\n" ); return SANE_STATUS_GOOD; } /** return the descriptor if available */ SANE_Status sane_get_select_fd( SANE_Handle handle, SANE_Int * fd ) { U12_Scanner *s = (U12_Scanner *)handle; DBG( _DBG_SANE_INIT, "sane_get_select_fd\n" ); if( !s->scanning ) { DBG( _DBG_ERROR, "ERROR: not scanning !\n" ); return SANE_STATUS_INVAL; } *fd = s->r_pipe; DBG( _DBG_SANE_INIT, "sane_get_select_fd done\n" ); return SANE_STATUS_GOOD; } /* END U12.C ................................................................*/ sane-backends-1.0.27/backend/mustek_usb.c0000664000175000017500000013115213106201017015130 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2000 Mustek. Originally maintained by Tom Wang Copyright (C) 2001 - 2004 by Henning Meier-Geinitz. This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Mustek 1200UB and similar USB flatbed scanners. */ #define BUILD 18 #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME mustek_usb #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_usb.h" #include "mustek_usb.h" #include "mustek_usb_high.c" #ifndef SANE_I18N #define SANE_I18N(text) text #endif static SANE_Int num_devices; static Mustek_Usb_Device *first_dev; static Mustek_Usb_Scanner *first_handle; static const SANE_Device **devlist = 0; /* Maximum amount of data read in one turn from USB. */ static SANE_Word max_block_size = (8 * 1024); /* Array of newly attached devices */ static Mustek_Usb_Device **new_dev; /* Length of new_dev array */ static SANE_Int new_dev_len; /* Number of entries alloced for new_dev */ static SANE_Int new_dev_alloced; static SANE_String_Const mode_list[6]; static const SANE_Range char_range = { -127, 127, 1 }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; SANE_Int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status calc_parameters (Mustek_Usb_Scanner * s) { SANE_String val; SANE_Status status = SANE_STATUS_GOOD; SANE_Int max_x, max_y; DBG (5, "calc_parameters: start\n"); val = s->val[OPT_MODE].s; s->params.last_frame = SANE_TRUE; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 1; s->bpp = 1; s->channels = 1; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 8; s->bpp = 8; s->channels = 1; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR)) { s->params.format = SANE_FRAME_RGB; s->params.depth = 8; s->bpp = 24; s->channels = 3; } else { DBG (1, "calc_parameters: invalid mode %s\n", (SANE_Char *) val); status = SANE_STATUS_INVAL; } s->tl_x = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH; s->tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH; s->width = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH - s->tl_x; s->height = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH - s->tl_y; if (s->width < 0) { DBG (1, "calc_parameters: warning: tl_x > br_x\n"); } if (s->height < 0) { DBG (1, "calc_parameters: warning: tl_y > br_y\n"); } max_x = s->hw->max_width * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / 300; max_y = s->hw->max_height * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / 300; s->tl_x_dots = s->tl_x * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->width_dots = s->width * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->tl_y_dots = s->tl_y * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->height_dots = s->height * SANE_UNFIX (s->val[OPT_RESOLUTION].w); if (s->width_dots > max_x) s->width_dots = max_x; if (s->height_dots > max_y) s->height_dots = max_y; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) { s->width_dots = (s->width_dots / 8) * 8; if (s->width_dots == 0) s->width_dots = 8; } if (s->tl_x_dots < 0) s->tl_x_dots = 0; if (s->tl_y_dots < 0) s->tl_y_dots = 0; if (s->tl_x_dots + s->width_dots > max_x) s->tl_x_dots = max_x - s->width_dots; if (s->tl_y_dots + s->height_dots > max_y) s->tl_y_dots = max_y - s->height_dots; s->val[OPT_TL_X].w = SANE_FIX (s->tl_x * MM_PER_INCH); s->val[OPT_TL_Y].w = SANE_FIX (s->tl_y * MM_PER_INCH); s->val[OPT_BR_X].w = SANE_FIX ((s->tl_x + s->width) * MM_PER_INCH); s->val[OPT_BR_Y].w = SANE_FIX ((s->tl_y + s->height) * MM_PER_INCH); s->params.pixels_per_line = s->width_dots; if (s->params.pixels_per_line < 0) s->params.pixels_per_line = 0; s->params.lines = s->height_dots; if (s->params.lines < 0) s->params.lines = 0; s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8 * s->channels; DBG (4, "calc_parameters: format=%d\n", s->params.format); DBG (4, "calc_parameters: last frame=%d\n", s->params.last_frame); DBG (4, "calc_parameters: lines=%d\n", s->params.lines); DBG (4, "calc_parameters: pixels per line=%d\n", s->params.pixels_per_line); DBG (4, "calc_parameters: bytes per line=%d\n", s->params.bytes_per_line); DBG (4, "calc_parameters: Pixels %dx%dx%d\n", s->params.pixels_per_line, s->params.lines, 1 << s->params.depth); DBG (5, "calc_parameters: exit\n"); return status; } static SANE_Status init_options (Mustek_Usb_Scanner * s) { SANE_Int option; SANE_Status status; DBG (5, "init_options: start\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (option = 0; option < NUM_OPTIONS; ++option) { s->opt[option].size = sizeof (SANE_Word); s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ mode_list[0] = SANE_VALUE_SCAN_MODE_COLOR; mode_list[1] = SANE_VALUE_SCAN_MODE_GRAY; mode_list[2] = SANE_VALUE_SCAN_MODE_LINEART; mode_list[3] = NULL; s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[1]); /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; if (s->hw->chip->scanner_type == MT_600CU) s->hw->dpi_range.max = SANE_FIX (600); else s->hw->dpi_range.max = SANE_FIX (1200); /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_PREVIEW].w = SANE_FALSE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &u8_range; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->val[OPT_THRESHOLD].w = 128; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* gray gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gray_gamma_table[0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->red_gamma_table[0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->green_gamma_table[0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->blue_gamma_table[0]; RIE (calc_parameters (s)); DBG (5, "init_options: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach (SANE_String_Const devname, Mustek_Usb_Device ** devp, SANE_Bool may_wait) { Mustek_Usb_Device *dev; SANE_Status status; Mustek_Type scanner_type; SANE_Int fd; DBG (5, "attach: start: devp %s NULL, may_wait = %d\n", devp ? "!=" : "==", may_wait); if (!devname) { DBG (1, "attach: devname == NULL\n"); return SANE_STATUS_INVAL; } for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; DBG (4, "attach: device `%s' was already in device list\n", devname); return SANE_STATUS_GOOD; } DBG (4, "attach: trying to open device `%s'\n", devname); status = sanei_usb_open (devname, &fd); if (status != SANE_STATUS_GOOD) { DBG (3, "attach: couldn't open device `%s': %s\n", devname, sane_strstatus (status)); return status; } DBG (4, "attach: device `%s' successfully opened\n", devname); /* try to identify model */ DBG (4, "attach: trying to identify device `%s'\n", devname); status = usb_low_identify_scanner (fd, &scanner_type); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: device `%s' doesn't look like a supported scanner\n", devname); sanei_usb_close (fd); return status; } sanei_usb_close (fd); if (scanner_type == MT_UNKNOWN) { DBG (3, "attach: warning: couldn't identify device `%s', must set " "type manually\n", devname); } dev = malloc (sizeof (Mustek_Usb_Device)); if (!dev) { DBG (1, "attach: couldn't malloc Mustek_Usb_Device\n"); return SANE_STATUS_NO_MEM; } memset (dev, 0, sizeof (*dev)); dev->name = strdup (devname); dev->sane.name = (SANE_String_Const) dev->name; dev->sane.vendor = "Mustek"; switch (scanner_type) { case MT_1200CU: dev->sane.model = "1200 CU"; break; case MT_1200CU_PLUS: dev->sane.model = "1200 CU Plus"; break; case MT_1200USB: dev->sane.model = "1200 USB (unsupported)"; break; case MT_1200UB: dev->sane.model = "1200 UB"; break; case MT_600CU: dev->sane.model = "600 CU"; break; case MT_600USB: dev->sane.model = "600 USB (unsupported)"; break; default: dev->sane.model = "(unidentified)"; break; } dev->sane.type = "flatbed scanner"; dev->x_range.min = 0; dev->x_range.max = SANE_FIX (8.4 * MM_PER_INCH); dev->x_range.quant = 0; dev->y_range.min = 0; dev->y_range.max = SANE_FIX (11.7 * MM_PER_INCH); dev->y_range.quant = 0; dev->max_height = 11.7 * 300; dev->max_width = 8.4 * 300; dev->dpi_range.min = SANE_FIX (50); dev->dpi_range.max = SANE_FIX (600); dev->dpi_range.quant = SANE_FIX (1); status = usb_high_scan_init (dev); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: usb_high_scan_init returned status: %s\n", sane_strstatus (status)); free (dev); return status; } dev->chip->scanner_type = scanner_type; dev->chip->max_block_size = max_block_size; DBG (2, "attach: found %s %s %s at %s\n", dev->sane.vendor, dev->sane.type, dev->sane.model, dev->sane.name); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (5, "attach: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one_device (SANE_String_Const devname) { Mustek_Usb_Device *dev; SANE_Status status; RIE (attach (devname, &dev, SANE_FALSE)); if (dev) { /* Keep track of newly attached devices so we can set options as necessary. */ if (new_dev_len >= new_dev_alloced) { new_dev_alloced += 4; if (new_dev) new_dev = realloc (new_dev, new_dev_alloced * sizeof (new_dev[0])); else new_dev = malloc (new_dev_alloced * sizeof (new_dev[0])); if (!new_dev) { DBG (1, "attach_one_device: out of memory\n"); return SANE_STATUS_NO_MEM; } } new_dev[new_dev_len++] = dev; } return SANE_STATUS_GOOD; } static SANE_Status fit_lines (Mustek_Usb_Scanner * s, SANE_Byte * src, SANE_Byte * dst, SANE_Word src_lines, SANE_Word * dst_lines) { SANE_Int threshold; SANE_Word src_width, dst_width; SANE_Word dst_pixel, src_pixel; SANE_Word dst_line, src_line; SANE_Word pixel_switch; SANE_Word src_address, dst_address; src_width = s->hw->width; dst_width = s->width_dots; threshold = s->val[OPT_THRESHOLD].w; DBG (5, "fit_lines: dst_width=%d, src_width=%d, src_lines=%d, " "offset=%d\n", dst_width, src_width, src_lines, s->hw->line_offset); dst_line = 0; src_line = s->hw->line_offset; while (src_line < src_lines) { DBG (5, "fit_lines: getting line: dst_line=%d, src_line=%d, " "line_switch=%d\n", dst_line, src_line, s->hw->line_switch); src_pixel = 0; pixel_switch = src_width; for (dst_pixel = 0; dst_pixel < dst_width; dst_pixel++) { while (pixel_switch > dst_width) { src_pixel++; pixel_switch -= dst_width; } pixel_switch += src_width; src_address = src_pixel * s->hw->bpp / 8 + src_width * src_line * s->hw->bpp / 8; dst_address = dst_pixel * s->bpp / 8 + dst_width * dst_line * s->bpp / 8; if (s->bpp == 8) { dst[dst_address] = s->gray_table[src[src_address]]; } else if (s->bpp == 24) { dst[dst_address] = s->red_table[s->gray_table[src[src_address]]]; dst[dst_address + 1] = s->green_table[s->gray_table[src[src_address + 1]]]; dst[dst_address + 2] = s->blue_table[s->gray_table[src[src_address + 2]]]; } else /* lineart */ { if ((dst_pixel % 8) == 0) dst[dst_address] = 0; dst[dst_address] |= (((src[src_address] > threshold) ? 0 : 1) << (7 - (dst_pixel % 8))); } } dst_line++; while (s->hw->line_switch >= s->height_dots) { src_line++; s->hw->line_switch -= s->height_dots; } s->hw->line_switch += s->hw->height; } *dst_lines = dst_line; s->hw->line_offset = (src_line - src_lines); DBG (4, "fit_lines: exit, src_line=%d, *dst_lines=%d, offset=%d\n", src_line, *dst_lines, s->hw->line_offset); return SANE_STATUS_GOOD; } static SANE_Status check_gamma_table (SANE_Word * table) { SANE_Word entry, value; SANE_Status status = SANE_STATUS_GOOD; for (entry = 0; entry < 256; entry++) { value = table[entry]; if (value > 255) { DBG (1, "check_gamma_table: warning: entry %d > 255 (%d) - fixed\n", entry, value); table[entry] = 255; status = SANE_STATUS_INVAL; } } return status; } /* -------------------------- SANE API functions ------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { SANE_Char line[PATH_MAX]; SANE_Char *word, *end; SANE_String_Const cp; SANE_Int linenumber; FILE *fp; DBG_INIT (); DBG (2, "SANE Mustek USB backend version %d.%d build %d from %s\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD, PACKAGE_STRING); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (5, "sane_init: authorize %s null\n", authorize ? "!=" : "=="); num_devices = 0; first_dev = 0; first_handle = 0; devlist = 0; new_dev = 0; new_dev_len = 0; new_dev_alloced = 0; sanei_usb_init (); fp = sanei_config_open (MUSTEK_USB_CONFIG_FILE); if (!fp) { /* default to /dev/usb/scanner instead of insisting on config file */ DBG (3, "sane_init: couldn't open config file `%s': %s. Using " "/dev/usb/scanner directly\n", MUSTEK_USB_CONFIG_FILE, strerror (errno)); attach ("/dev/usb/scanner", 0, SANE_FALSE); return SANE_STATUS_GOOD; } linenumber = 0; DBG (4, "sane_init: reading config file `%s'\n", MUSTEK_USB_CONFIG_FILE); while (sanei_config_read (line, sizeof (line), fp)) { word = 0; linenumber++; cp = sanei_config_get_string (line, &word); if (!word || cp == line) { DBG (5, "sane_init: config file line %d: ignoring empty line\n", linenumber); if (word) free (word); continue; } if (word[0] == '#') { DBG (5, "sane_init: config file line %d: ignoring comment line\n", linenumber); free (word); continue; } if (strcmp (word, "option") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (!word) { DBG (1, "sane_init: config file line %d: missing quotation mark?\n", linenumber); continue; } if (strcmp (word, "max_block_size") == 0) { free (word); word = 0; cp = sanei_config_get_string (cp, &word); if (!word) { DBG (1, "sane_init: config file line %d: missing quotation mark?\n", linenumber); continue; } errno = 0; max_block_size = strtol (word, &end, 0); if (end == word) { DBG (3, "sane-init: config file line %d: max_block_size " "must have a parameter; using 8192 bytes\n", linenumber); max_block_size = 8192; } if (errno) { DBG (3, "sane-init: config file line %d: max_block_size `%s' " "is invalid (%s); using 8192 bytes\n", linenumber, word, strerror (errno)); max_block_size = 8192; } else { DBG (3, "sane_init: config file line %d: max_block_size set " "to %d bytes\n", linenumber, max_block_size); } if (word) free (word); word = 0; } else if (strcmp (word, "1200ub") == 0) { if (new_dev_len > 0) { /* this is a 1200 UB */ new_dev[new_dev_len - 1]->chip->scanner_type = MT_1200UB; new_dev[new_dev_len - 1]->sane.model = "1200 UB"; DBG (3, "sane_init: config file line %d: `%s' is a Mustek " "1200 UB\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "1200ub ignored, was set before any device " "name\n", linenumber); } if (word) free (word); word = 0; } else if (strcmp (word, "1200cu") == 0) { if (new_dev_len > 0) { /* this is a 1200 CU */ new_dev[new_dev_len - 1]->chip->scanner_type = MT_1200CU; new_dev[new_dev_len - 1]->sane.model = "1200 CU"; DBG (3, "sane_init: config file line %d: `%s' is a Mustek " "1200 CU\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "1200cu ignored, was set before any device " "name\n", linenumber); } if (word) free (word); word = 0; } else if (strcmp (word, "1200cu_plus") == 0) { if (new_dev_len > 0) { /* this is a 1200 CU Plus */ new_dev[new_dev_len - 1]->chip->scanner_type = MT_1200CU_PLUS; new_dev[new_dev_len - 1]->sane.model = "1200 CU Plus"; DBG (3, "sane_init: config file line %d: `%s' is a Mustek " "1200 CU Plus\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "1200cu_plus ignored, was set before any device " "name\n", linenumber); } if (word) free (word); word = 0; } else if (strcmp (word, "600cu") == 0) { if (new_dev_len > 0) { /* this is a 600 CU */ new_dev[new_dev_len - 1]->chip->scanner_type = MT_600CU; new_dev[new_dev_len - 1]->sane.model = "600 CU"; DBG (3, "sane_init: config file line %d: `%s' is a Mustek " "600 CU\n", linenumber, new_dev[new_dev_len - 1]->sane.name); } else { DBG (3, "sane_init: config file line %d: option " "600cu ignored, was set before any device " "name\n", linenumber); } if (word) free (word); word = 0; } else { DBG (3, "sane_init: config file line %d: option " "%s is unknown\n", linenumber, word); if (word) free (word); word = 0; } } else { new_dev_len = 0; DBG (4, "sane_init: config file line %d: trying to attach `%s'\n", linenumber, line); sanei_usb_attach_matching_devices (line, attach_one_device); if (word) free (word); word = 0; } } if (new_dev_alloced > 0) { new_dev_len = new_dev_alloced = 0; free (new_dev); } fclose (fp); DBG (5, "sane_init: exit\n"); return SANE_STATUS_GOOD; } void sane_exit (void) { Mustek_Usb_Device *dev, *next; SANE_Status status; DBG (5, "sane_exit: start\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; if (dev->is_prepared) { status = usb_high_scan_clearup (dev); if (status != SANE_STATUS_GOOD) DBG (3, "sane_close: usb_high_scan_clearup returned %s\n", sane_strstatus (status)); } status = usb_high_scan_exit (dev); if (status != SANE_STATUS_GOOD) DBG (3, "sane_close: usb_high_scan_exit returned %s\n", sane_strstatus (status)); if (dev->chip) { status = usb_high_scan_exit (dev); if (status != SANE_STATUS_GOOD) DBG (3, "sane_exit: while closing %s, usb_high_scan_exit returned: " "%s\n", dev->name, sane_strstatus (status)); } free ((void *) dev->name); free (dev); } first_dev = 0; if (devlist) free (devlist); devlist = 0; DBG (5, "sane_exit: exit\n"); } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only) { Mustek_Usb_Device *dev; SANE_Int dev_num; DBG (5, "sane_get_devices: start: local_only = %s\n", local_only == SANE_TRUE ? "true" : "false"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; dev_num = 0; for (dev = first_dev; dev_num < num_devices; dev = dev->next) devlist[dev_num++] = &dev->sane; devlist[dev_num++] = 0; *device_list = devlist; DBG (5, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Mustek_Usb_Device *dev; SANE_Status status; Mustek_Usb_Scanner *s; SANE_Int value; DBG (5, "sane_open: start (devicename = `%s')\n", devicename); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devicename) == 0) break; if (!dev) { DBG (5, "sane_open: couldn't find `%s' in devlist, trying attach)\n", devicename); RIE (attach (devicename, &dev, SANE_TRUE)); } else DBG (5, "sane_open: found `%s' in devlist\n", dev->name); } else { /* empty devicname -> use first device */ dev = first_dev; if (dev) DBG (5, "sane_open: empty devicename, trying `%s'\n", dev->name); } if (!dev) return SANE_STATUS_INVAL; if (dev->chip->scanner_type == MT_UNKNOWN) { DBG (0, "sane_open: the type of your scanner is unknown, edit " "mustek_usb.conf before using the scanner\n"); return SANE_STATUS_INVAL; } s = malloc (sizeof (*s)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (*s)); s->hw = dev; RIE (init_options (s)); /* insert newly opened handle into list of open handles: */ s->next = first_handle; first_handle = s; *handle = s; strcpy (s->hw->device_name, dev->name); RIE (usb_high_scan_turn_power (s->hw, SANE_TRUE)); RIE (usb_high_scan_back_home (s->hw)); s->hw->scan_buffer = (SANE_Byte *) malloc (SCAN_BUFFER_SIZE * 2); if (!s->hw->scan_buffer) { DBG (5, "sane_open: couldn't malloc s->hw->scan_buffer (%d bytes)\n", SCAN_BUFFER_SIZE * 2); return SANE_STATUS_NO_MEM; } s->hw->scan_buffer_len = 0; s->hw->scan_buffer_start = s->hw->scan_buffer; s->hw->temp_buffer = (SANE_Byte *) malloc (SCAN_BUFFER_SIZE); if (!s->hw->temp_buffer) { DBG (5, "sane_open: couldn't malloc s->hw->temp_buffer (%d bytes)\n", SCAN_BUFFER_SIZE); return SANE_STATUS_NO_MEM; } s->hw->temp_buffer_len = 0; s->hw->temp_buffer_start = s->hw->temp_buffer; for (value = 0; value < 256; value++) { s->linear_gamma_table[value] = value; s->red_gamma_table[value] = value; s->green_gamma_table[value] = value; s->blue_gamma_table[value] = value; s->gray_gamma_table[value] = value; } s->red_table = s->linear_gamma_table; s->green_table = s->linear_gamma_table; s->blue_table = s->linear_gamma_table; s->gray_table = s->linear_gamma_table; DBG (5, "sane_open: exit\n"); return SANE_STATUS_GOOD; } void sane_close (SANE_Handle handle) { Mustek_Usb_Scanner *prev, *s; SANE_Status status; DBG (5, "sane_close: start\n"); /* remove handle from list of open handles: */ prev = 0; for (s = first_handle; s; s = s->next) { if (s == handle) break; prev = s; } if (!s) { DBG (5, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (prev) prev->next = s->next; else first_handle = s->next; if (s->hw->is_open) { status = usb_high_scan_turn_power (s->hw, SANE_FALSE); if (status != SANE_STATUS_GOOD) DBG (3, "sane_close: usb_high_scan_turn_power returned %s\n", sane_strstatus (status)); } #if 0 if (s->hw->is_prepared) { status = usb_high_scan_clearup (s->hw); if (status != SANE_STATUS_GOOD) DBG (3, "sane_close: usb_high_scan_clearup returned %s\n", sane_strstatus (status)); } status = usb_high_scan_exit (s->hw); if (status != SANE_STATUS_GOOD) DBG (3, "sane_close: usb_high_scan_exit returned %s\n", sane_strstatus (status)); #endif if (s->hw->scan_buffer) { free (s->hw->scan_buffer); s->hw->scan_buffer = 0; } if (s->hw->temp_buffer) { free (s->hw->temp_buffer); s->hw->temp_buffer = 0; } free (handle); DBG (5, "sane_close: exit\n"); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Mustek_Usb_Scanner *s = handle; if ((unsigned) option >= NUM_OPTIONS) return 0; DBG (5, "sane_get_option_descriptor: option = %s (%d)\n", s->opt[option].name, option); return s->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Mustek_Usb_Scanner *s = handle; SANE_Status status; SANE_Word cap; SANE_Int myinfo = 0; DBG (5, "sane_control_option: start: action = %s, option = %s (%d)\n", (action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_SET_VALUE) ? "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->opt[option].name, option); if (info) *info = 0; if (s->scanning) { DBG (1, "sane_control_option: don't call this function while " "scanning\n"); return SANE_STATUS_DEVICE_BUSY; } if (option >= NUM_OPTIONS || option < 0) { DBG (1, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", option); return SANE_STATUS_INVAL; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (2, "sane_control_option: option %d is inactive\n", option); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_THRESHOLD: case OPT_CUSTOM_GAMMA: *(SANE_Word *) val = s->val[option].w; break; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); break; /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); break; default: DBG (2, "sane_control_option: can't get unknown option %d\n", option); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (2, "sane_control_option: option %d is not settable\n", option); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (2, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; RIE (calc_parameters (s)); myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_THRESHOLD: s->val[option].w = *(SANE_Word *) val; break; /* Boolean */ case OPT_PREVIEW: s->val[option].w = *(SANE_Bool *) val; break; /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); check_gamma_table (s->val[option].wa); break; case OPT_CUSTOM_GAMMA: s->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; myinfo |= SANE_INFO_RELOAD_OPTIONS; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { s->red_table = s->red_gamma_table; s->green_table = s->green_gamma_table; s->blue_table = s->blue_gamma_table; s->gray_table = s->gray_gamma_table; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { s->red_table = s->linear_gamma_table; s->green_table = s->linear_gamma_table; s->blue_table = s->linear_gamma_table; s->gray_table = s->linear_gamma_table; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } break; case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); RIE (calc_parameters (s)); s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; default: DBG (2, "sane_control_option: can't set unknown option %d\n", option); } } else { DBG (2, "sane_control_option: unknown action %d for option %d\n", action, option); return SANE_STATUS_INVAL; } if (info) *info = myinfo; DBG (5, "sane_control_option: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Mustek_Usb_Scanner *s = handle; SANE_Status status; DBG (5, "sane_get_parameters: start\n"); RIE (calc_parameters (s)); if (params) *params = s->params; DBG (5, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Mustek_Usb_Scanner *s = handle; SANE_Status status; SANE_String val; Colormode color_mode; SANE_Word dpi, x, y, width, height; DBG (5, "sane_start: start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ s->total_bytes = 0; s->total_lines = 0; RIE (calc_parameters (s)); if (s->width_dots <= 0) { DBG (0, "sane_start: top left x > bottom right x --- exiting\n"); return SANE_STATUS_INVAL; } if (s->height_dots <= 0) { DBG (0, "sane_start: top left y > bottom right y --- exiting\n"); return SANE_STATUS_INVAL; } val = s->val[OPT_MODE].s; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) color_mode = GRAY8; else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) color_mode = GRAY8; else /* Color */ color_mode = RGB24; dpi = SANE_UNFIX (s->val[OPT_RESOLUTION].w); x = s->tl_x_dots; y = s->tl_y_dots; width = s->width_dots; height = s->height_dots; if (!s->hw->is_prepared) { RIE (usb_high_scan_prepare (s->hw)); RIE (usb_high_scan_reset (s->hw)); } RIE (usb_high_scan_set_threshold (s->hw, 128)); RIE (usb_high_scan_embed_gamma (s->hw, NULL)); RIE (usb_high_scan_suggest_parameters (s->hw, dpi, x, y, width, height, color_mode)); RIE (usb_high_scan_setup_scan (s->hw, s->hw->scan_mode, s->hw->x_dpi, s->hw->y_dpi, 0, s->hw->x, s->hw->y, s->hw->width)); DBG (3, "sane_start: wanted: dpi=%d, x=%d, y=%d, width=%d, height=%d, " "scan_mode=%d\n", dpi, x, y, width, height, color_mode); DBG (3, "sane_start: got: x_dpi=%d, y_dpi=%d, x=%d, y=%d, width=%d, " "height=%d, scan_mode=%d\n", s->hw->x_dpi, s->hw->y_dpi, s->hw->x, s->hw->y, s->hw->width, s->hw->height, s->hw->scan_mode); s->scanning = SANE_TRUE; s->read_rows = s->hw->height; s->hw->line_switch = s->hw->height; s->hw->line_offset = 0; s->hw->scan_buffer_len = 0; DBG (5, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Mustek_Usb_Scanner *s = handle; SANE_Word lines_to_read, lines_read; SANE_Status status; DBG (5, "sane_read: start\n"); if (!s) { DBG (1, "sane_read: handle is null!\n"); return SANE_STATUS_INVAL; } if (!buf) { DBG (1, "sane_read: buf is null!\n"); return SANE_STATUS_INVAL; } if (!len) { DBG (1, "sane_read: len is null!\n"); return SANE_STATUS_INVAL; } *len = 0; if (!s->scanning) { DBG (3, "sane_read: scan was cancelled, is over or has not been " "initiated yet\n"); return SANE_STATUS_CANCELLED; } if (s->hw->scan_buffer_len == 0) { if (s->read_rows > 0) { lines_to_read = SCAN_BUFFER_SIZE / (s->hw->width * s->hw->bpp / 8); if (lines_to_read > s->read_rows) lines_to_read = s->read_rows; s->hw->temp_buffer_start = s->hw->temp_buffer; s->hw->temp_buffer_len = (s->hw->width * s->hw->bpp / 8) * lines_to_read; DBG (4, "sane_read: reading %d source lines\n", lines_to_read); RIE (usb_high_scan_get_rows (s->hw, s->hw->temp_buffer, lines_to_read, SANE_FALSE)); RIE (fit_lines (s, s->hw->temp_buffer, s->hw->scan_buffer, lines_to_read, &lines_read)); s->read_rows -= lines_to_read; if ((s->total_lines + lines_read) > s->height_dots) lines_read = s->height_dots - s->total_lines; s->total_lines += lines_read; DBG (4, "sane_read: %d destination lines, %d total\n", lines_read, s->total_lines); s->hw->scan_buffer_start = s->hw->scan_buffer; s->hw->scan_buffer_len = (s->width_dots * s->bpp / 8) * lines_read; } else { DBG (4, "sane_read: scan finished -- exit\n"); return SANE_STATUS_EOF; } } if (s->hw->scan_buffer_len == 0) { DBG (4, "sane_read: scan finished -- exit\n"); return SANE_STATUS_EOF; } *len = MIN (max_len, (SANE_Int) s->hw->scan_buffer_len); memcpy (buf, s->hw->scan_buffer_start, *len); DBG (4, "sane_read: exit, read %d bytes from scan_buffer; " "%ld bytes remaining\n", *len, (long int) (s->hw->scan_buffer_len - *len)); s->hw->scan_buffer_len -= (*len); s->hw->scan_buffer_start += (*len); s->total_bytes += (*len); return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle handle) { Mustek_Usb_Scanner *s = handle; SANE_Status status; DBG (5, "sane_cancel: start\n"); status = usb_high_scan_stop_scan (s->hw); if (status != SANE_STATUS_GOOD) DBG (3, "sane_cancel: usb_high_scan_stop_scan returned `%s' for `%s'\n", sane_strstatus (status), s->hw->name); usb_high_scan_back_home (s->hw); if (status != SANE_STATUS_GOOD) DBG (3, "sane_cancel: usb_high_scan_back_home returned `%s' for `%s'\n", sane_strstatus (status), s->hw->name); if (s->scanning) { s->scanning = SANE_FALSE; if (s->total_bytes != (s->params.bytes_per_line * s->params.lines)) DBG (1, "sane_cancel: warning: scanned %d bytes, expected %d " "bytes\n", s->total_bytes, s->params.bytes_per_line * s->params.lines); else DBG (3, "sane_cancel: scan finished, scanned %d bytes\n", s->total_bytes); } else { DBG (4, "sane_cancel: scan has not been initiated yet, " "or it is already aborted\n"); } DBG (5, "sane_cancel: exit\n"); return; } SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Mustek_Usb_Scanner *s = handle; DBG (5, "sane_set_io_mode: handle = %p, non_blocking = %s\n", handle, non_blocking == SANE_TRUE ? "true" : "false"); if (!s->scanning) { DBG (1, "sane_set_io_mode: not scanning\n"); return SANE_STATUS_INVAL; } if (non_blocking) return SANE_STATUS_UNSUPPORTED; return SANE_STATUS_GOOD; } SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Mustek_Usb_Scanner *s = handle; DBG (5, "sane_get_select_fd: handle = %p, fd = %p\n", handle, (void *) fd); if (!s->scanning) { DBG (1, "sane_get_select_fd: not scanning\n"); return SANE_STATUS_INVAL; } return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/matsushita.c0000664000175000017500000020236012112021330015123 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002, 2004 Frank Zago (sane at zago dot net) Copyright (C) 2002 Other SANE contributors This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* $Id$ Matsushita/Panasonic KV-SS25, KV-SS50, KV-SS55, KV-SS50EX, KV-SS55EX, KV-SS850, KV-SS855 SCSI scanners. This backend may support more Panasonic scanners. */ /*--------------------------------------------------------------------------*/ #define BUILD 7 /* 2004-02-11 */ #define BACKEND_NAME matsushita #define MATSUSHITA_CONFIG_FILE "matsushita.conf" /*--------------------------------------------------------------------------*/ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/lassert.h" #include "matsushita.h" /*--------------------------------------------------------------------------*/ /* Lists of possible scan modes. */ static SANE_String_Const scan_mode_list_1[] = { BLACK_WHITE_STR, NULL }; static SANE_String_Const scan_mode_list_3[] = { BLACK_WHITE_STR, GRAY4_STR, GRAY8_STR, NULL }; /*--------------------------------------------------------------------------*/ /* Lists of supported resolutions (in DPI). * 200 DPI scanners are using resolutions_list_200 * 300 DPI scanners are using resolutions_list_300 * 400 DPI scanners are using resolutions_list_400 * * The resolutions_rounds_* lists provide the value with which round * up the X value given by the interface. */ #ifdef unused_yet static const SANE_Word resolutions_list_200[4] = { 3, 100, 150, 200 }; static const SANE_Word resolutions_rounds_200[4] = { 3, 0x100, 0x40, 0x20 }; #endif static const SANE_Word resolutions_list_300[5] = { 4, 150, 200, 240, 300 }; static const SANE_Word resolutions_rounds_300[5] = { 4, 0x100, 0x40, 0x20, 0x80 }; static const SANE_Word resolutions_list_400[8] = { 7, 100, 150, 200, 240, 300, 360, 400 }; static const SANE_Word resolutions_rounds_400[8] = { 7, 0x100, 0x100, 0x40, 0x20, 0x80, 0x100, 0x100 /* TO FIX */ }; /*--------------------------------------------------------------------------*/ /* Lists of supported halftone. They are only valid with * for the Black&White mode. */ static SANE_String_Const halftone_pattern_list[] = { SANE_I18N ("None"), SANE_I18N ("Bayer Dither 16"), SANE_I18N ("Bayer Dither 64"), SANE_I18N ("Halftone Dot 32"), SANE_I18N ("Halftone Dot 64"), SANE_I18N ("Error Diffusion"), NULL }; static const int halftone_pattern_val[] = { -1, 0x01, 0x00, 0x02, 0x03, 0x04 }; /*--------------------------------------------------------------------------*/ /* List of automatic threshold options */ static SANE_String_Const automatic_threshold_list[] = { SANE_I18N ("None"), SANE_I18N ("Mode 1"), SANE_I18N ("Mode 2"), SANE_I18N ("Mode 3"), NULL }; static const int automatic_threshold_val[] = { 0, 0x80, 0x81, 0x82 }; /*--------------------------------------------------------------------------*/ /* List of white level base. */ static SANE_String_Const white_level_list[] = { SANE_I18N ("From white stick"), SANE_I18N ("From paper"), SANE_I18N ("Automatic"), NULL }; static const int white_level_val[] = { 0x00, 0x80, 0x81 }; /*--------------------------------------------------------------------------*/ /* List of noise reduction options. */ static SANE_String_Const noise_reduction_list[] = { SANE_I18N ("None"), "1x1", "2x2", "3x3", "4x4", "5x5", NULL }; static const int noise_reduction_val[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; /*--------------------------------------------------------------------------*/ /* List of image emphasis options, 5 steps */ static SANE_String_Const image_emphasis_list_5[] = { SANE_I18N ("Smooth"), SANE_I18N ("None"), SANE_I18N ("Low"), SANE_I18N ("Medium"), /* default */ SANE_I18N ("High"), NULL }; static const int image_emphasis_val_5[] = { 0x80, 0x00, 0x01, 0x30, 0x50 }; /* List of image emphasis options, 3 steps */ static SANE_String_Const image_emphasis_list_3[] = { SANE_I18N ("Low"), SANE_I18N ("Medium"), /* default ? */ SANE_I18N ("High"), NULL }; static const int image_emphasis_val_3[] = { 0x01, 0x30, 0x50 }; /*--------------------------------------------------------------------------*/ /* List of gamma */ static SANE_String_Const gamma_list[] = { SANE_I18N ("Normal"), SANE_I18N ("CRT"), NULL }; static const int gamma_val[] = { 0x00, 0x01 }; /*--------------------------------------------------------------------------*/ /* Page feeder options */ static SANE_String_Const feeder_mode_list[] = { SANE_I18N ("One page"), SANE_I18N ("All pages"), NULL }; static const int feeder_mode_val[] = { 0x00, 0xff }; /*--------------------------------------------------------------------------*/ /* Paper size in millimeters. * Values from http://www.twics.com/~eds/paper/. */ static const struct paper_sizes paper_sizes[] = { {"2A0", 1189, 1682}, {"4A0", 1682, 2378}, {"A0", 841, 1189}, {"A1", 594, 841}, {"A2", 420, 594}, {"A3", 297, 420}, {"A4", 210, 297}, {"A5", 148, 210}, {"A6", 105, 148}, {"A7", 74, 105}, {"A8", 52, 74}, {"A9", 37, 52}, {"A10", 26, 37}, {"B0", 1000, 1414}, {"B1", 707, 1000}, {"B2", 500, 707}, {"B3", 353, 500}, {"B4", 250, 353}, {"B5", 176, 250}, {"B6", 125, 176}, {"B7", 88, 125}, {"B8", 62, 88}, {"B9", 44, 62}, {"B10", 31, 44}, {"C0", 917, 1297}, {"C1", 648, 917}, {"C2", 458, 648}, {"C3", 324, 458}, {"C4", 229, 324}, {"C5", 162, 229}, {"C6", 114, 162}, {"C7", 81, 114}, {"C8", 57, 81}, {"C9", 40, 57}, {"C10", 28, 40}, {"Legal", 8.5 * MM_PER_INCH, 14 * MM_PER_INCH}, {"Letter", 8.5 * MM_PER_INCH, 11 * MM_PER_INCH} }; /*--------------------------------------------------------------------------*/ /* Define the supported scanners and their characteristics. */ static const struct scanners_supported scanners[] = { /* Panasonic KV-SS25 */ { 0x06, "K.M.E. ", "KV-SS25A ", {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ {1, 255, 1}, /* brightness range */ {1, 255, 1}, /* contrast range */ scan_mode_list_3, resolutions_list_300, resolutions_rounds_300, image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION}, /* Panasonic KV-SS25D */ { 0x06, "K.M.E. ", "KV-SS25D ", /* TO FIX */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ {1, 255, 1}, /* brightness range */ {1, 255, 1}, /* contrast range */ scan_mode_list_3, resolutions_list_300, resolutions_rounds_300, image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION}, /* Panasonic KV-SS50 */ { 0x06, "K.M.E. ", "KV-SS50 ", /* TO FIX */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (14 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ {1, 5, 1}, /* brightness range, TO FIX */ {0, 0, 0}, /* contrast range */ scan_mode_list_1, resolutions_list_300, resolutions_rounds_300, /* TO FIX */ image_emphasis_list_3, image_emphasis_val_3, MAT_CAP_PAPER_DETECT | MAT_CAP_MIRROR_IMAGE}, /* Panasonic KV-SS55 */ { 0x06, "K.M.E. ", "KV-SS55 ", /* TO FIX */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (14 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ {1, 5, 1}, /* brightness range, TO FIX */ {1, 255, 1}, /* contrast range, TO FIX */ scan_mode_list_1, resolutions_list_300, resolutions_rounds_300, /* TO FIX */ image_emphasis_list_3, image_emphasis_val_3, MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_PAPER_DETECT | MAT_CAP_MIRROR_IMAGE}, /* Panasonic KV-SS50EX */ { 0x06, "K.M.E. ", "KV-SS50EX ", /* TO FIX */ {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ {1, 255, 1}, /* brightness range */ {0, 0, 0}, /* contrast range */ scan_mode_list_3, resolutions_list_300, resolutions_rounds_300, /* TO FIX */ image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION | MAT_CAP_PAPER_DETECT | MAT_CAP_MIRROR_IMAGE}, /* Panasonic KV-SS55EX */ { 0x06, "K.M.E. ", "KV-SS55EX ", {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ {1, 255, 1}, /* brightness range */ {1, 255, 1}, /* contrast range */ scan_mode_list_3, resolutions_list_300, resolutions_rounds_300, image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION}, /* Panasonic KV-SS850 */ { 0x06, "K.M.E. ", "KV-SS850 ", /* TO FIX */ {SANE_FIX (0), SANE_FIX (11.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ {1, 255, 1}, /* brightness range */ {0, 0, 0}, /* contrast range */ scan_mode_list_3, resolutions_list_300, resolutions_rounds_300, /* TO FIX */ image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION | MAT_CAP_PAPER_DETECT | MAT_CAP_DETECT_DOUBLE_FEED | MAT_CAP_MANUAL_FEED}, /* Panasonic KV-SS855 */ { 0x06, "K.M.E. ", "KV-SS855 ", /* TO FIX */ {SANE_FIX (0), SANE_FIX (11.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 355.6 mm */ {1, 255, 1}, /* brightness range */ {1, 255, 1}, /* contrast range, TO FIX */ scan_mode_list_3, resolutions_list_400, resolutions_rounds_400, /* TO FIX */ image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION | MAT_CAP_PAPER_DETECT | MAT_CAP_DETECT_DOUBLE_FEED | MAT_CAP_MANUAL_FEED}, /* Panasonic KV-S2065L */ { 0x06, "K.M.E. ", "KV-S2065L ", {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ {1, 255, 1}, /* brightness range */ {1, 255, 1}, /* contrast range */ scan_mode_list_3, resolutions_list_300, resolutions_rounds_300, image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION}, /* Panasonic KV-S2025C */ { 0x06, "K.M.E. ", "KV-S2025C ", {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ {1, 255, 1}, /* brightness range */ {1, 255, 1}, /* contrast range */ scan_mode_list_3, resolutions_list_300, resolutions_rounds_300, image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION}, /* Panasonic KV-S2045C */ { 0x06, "K.M.E. ", "KV-S2045C ", {SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0}, /* x range 0 to 215.9 mm */ {SANE_FIX (0), SANE_FIX (17 * MM_PER_INCH), 0}, /* y range 0 to 431.8 mm */ {1, 255, 1}, /* brightness range */ {1, 255, 1}, /* contrast range */ scan_mode_list_3, resolutions_list_300, resolutions_rounds_300, image_emphasis_list_5, image_emphasis_val_5, MAT_CAP_DUPLEX | MAT_CAP_CONTRAST | MAT_CAP_AUTOMATIC_THRESHOLD | MAT_CAP_WHITE_LEVEL | MAT_CAP_GAMMA | MAT_CAP_NOISE_REDUCTION} }; /*--------------------------------------------------------------------------*/ /* List of scanner attached. */ static Matsushita_Scanner *first_dev = NULL; static int num_devices = 0; static const SANE_Device **devlist = NULL; /* Local functions. */ /* Display a buffer in the log. */ static void hexdump (int level, const char *comment, unsigned char *p, int l) { int i; char line[128]; char *ptr; DBG (level, "%s\n", comment); ptr = line; for (i = 0; i < l; i++, p++) { if ((i % 16) == 0) { if (ptr != line) { *ptr = '\0'; DBG (level, "%s\n", line); ptr = line; } sprintf (ptr, "%3.3d:", i); ptr += 4; } sprintf (ptr, " %2.2x", *p); ptr += 3; } *ptr = '\0'; DBG (level, "%s\n", line); } /* Returns the length of the longest string, including the terminating * character. */ static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* After the windows has been set, issue that command to get the * document size. */ static SANE_Status matsushita_read_document_size (Matsushita_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; DBG (DBG_proc, "matsushita_read_document_size: enter\n"); size = 0x10; MKSCSI_READ_10 (cdb, 0x80, 0, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status != SANE_STATUS_GOOD || size != 0x10) { DBG (DBG_error, "matsushita_read_document_size: cannot read document size\n"); return (SANE_STATUS_IO_ERROR); } hexdump (DBG_info2, "document size", dev->buffer, 16); /* Check that X and Y are the same values the backend computed. */ assert (dev->params.lines == B32TOI (&dev->buffer[4])); assert (dev->params.pixels_per_line == B32TOI (&dev->buffer[0])); DBG (DBG_proc, "matsushita_read_document_size: exit, %ld bytes read\n", (long)size); return (SANE_STATUS_GOOD); } /* Initialize a scanner entry. Return an allocated scanner with some * preset values. */ static Matsushita_Scanner * matsushita_init (void) { Matsushita_Scanner *dev; DBG (DBG_proc, "matsushita_init: enter\n"); /* Allocate a new scanner entry. */ dev = malloc (sizeof (Matsushita_Scanner)); if (dev == NULL) { return NULL; } memset (dev, 0, sizeof (Matsushita_Scanner)); /* Allocate the buffer used to transfer the SCSI data. */ dev->buffer_size = 64 * 1024; dev->buffer = malloc (dev->buffer_size); if (dev->buffer == NULL) { free (dev); return NULL; } /* Allocate a buffer to store the temporary image. */ dev->image_size = 64 * 1024; /* enough for 1 line at max res */ dev->image = malloc (dev->image_size); if (dev->image == NULL) { free (dev->buffer); free (dev); return NULL; } dev->sfd = -1; DBG (DBG_proc, "matsushita_init: exit\n"); return (dev); } /* Closes an open scanner. */ static void matsushita_close (Matsushita_Scanner * dev) { DBG (DBG_proc, "matsushita_close: enter\n"); if (dev->sfd != -1) { sanei_scsi_close (dev->sfd); dev->sfd = -1; } DBG (DBG_proc, "matsushita_close: exit\n"); } /* Frees the memory used by a scanner. */ static void matsushita_free (Matsushita_Scanner * dev) { int i; DBG (DBG_proc, "matsushita_free: enter\n"); if (dev == NULL) return; matsushita_close (dev); if (dev->devicename) { free (dev->devicename); } if (dev->buffer) { free (dev->buffer); } if (dev->image) { free (dev->image); } for (i = 1; i < OPT_NUM_OPTIONS; i++) { if (dev->opt[i].type == SANE_TYPE_STRING && dev->val[i].s) { free (dev->val[i].s); } } free (dev->paper_sizes_list); free (dev->paper_sizes_val); free (dev); DBG (DBG_proc, "matsushita_free: exit\n"); } /* Inquiry a device and returns TRUE if is supported. */ static int matsushita_identify_scanner (Matsushita_Scanner * dev) { CDB cdb; SANE_Status status; size_t size; int i; DBG (DBG_proc, "matsushita_identify_scanner: enter\n"); size = 5; MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "matsushita_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } size = dev->buffer[4] + 5; /* total length of the inquiry data */ if (size < 36) { DBG (DBG_error, "matsushita_identify_scanner: not enough data to identify device\n"); return (SANE_FALSE); } MKSCSI_INQUIRY (cdb, size); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status) { DBG (DBG_error, "matsushita_identify_scanner: inquiry failed with status %s\n", sane_strstatus (status)); return (SANE_FALSE); } hexdump (DBG_info2, "inquiry", dev->buffer, size); dev->scsi_type = dev->buffer[0] & 0x1f; memcpy (dev->scsi_vendor, dev->buffer + 0x08, 0x08); dev->scsi_vendor[0x08] = 0; memcpy (dev->scsi_product, dev->buffer + 0x10, 0x010); dev->scsi_product[0x10] = 0; memcpy (dev->scsi_version, dev->buffer + 0x20, 0x04); dev->scsi_version[0x04] = 0; DBG (DBG_info, "device is \"%s\" \"%s\" \"%s\"\n", dev->scsi_vendor, dev->scsi_product, dev->scsi_version); /* Lookup through the supported scanners table to find if this * backend supports that one. */ for (i = 0; i < NELEMS (scanners); i++) { if (dev->scsi_type == scanners[i].scsi_type && strcmp (dev->scsi_vendor, scanners[i].scsi_vendor) == 0 && strcmp (dev->scsi_product, scanners[i].scsi_product) == 0) { DBG (DBG_error, "matsushita_identify_scanner: scanner supported\n"); dev->scnum = i; return (SANE_TRUE); } } DBG (DBG_proc, "matsushita_identify_scanner: exit, device not supported\n"); return (SANE_FALSE); } /* The interface can show different paper sizes. Show only the sizes * available for that scanner. */ static int matsushita_build_paper_sizes (Matsushita_Scanner * dev) { SANE_String_Const *psl; /* string list */ int *psv; /* value list */ int num; int i; DBG (DBG_proc, "matsushita_build_paper_sizes: enter\n"); psl = malloc ((sizeof (SANE_String_Const) + 1) * NELEMS (paper_sizes)); if (psl == NULL) { DBG (DBG_error, "ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } psv = malloc ((sizeof (int) + 1) * NELEMS (paper_sizes)); if (psv == NULL) { DBG (DBG_error, "ERROR: not enough memory\n"); free (psl); return SANE_STATUS_NO_MEM; } for (i = 0, num = 0; i < NELEMS (paper_sizes); i++) { if (SANE_UNFIX (scanners[dev->scnum].x_range.max) >= paper_sizes[i].width && SANE_UNFIX (scanners[dev->scnum].y_range.max) >= paper_sizes[i].length) { /* This paper size fits into the scanner. */ psl[num] = paper_sizes[i].name; psv[num] = i; num++; } } psl[num] = NULL; /* terminate the list */ dev->paper_sizes_list = psl; dev->paper_sizes_val = psv; DBG (DBG_proc, "matsushita_build_paper_sizes: exit (%d)\n", num); return SANE_STATUS_GOOD; } /* Lookup a string list from one array and return its index. */ static int get_string_list_index (SANE_String_Const list[], SANE_String_Const name) { int index; index = 0; while (list[index] != NULL) { if (strcmp (list[index], name) == 0) { return (index); } index++; } DBG (DBG_error, "name %s not found in list\n", name); assert (0 == 1); /* bug in backend, core dump */ return (-1); } /* Lookup an int list from one array and return its index. */ static int get_int_list_index (const SANE_Word list[], const SANE_Word value) { int index; int size; /* number of elements */ index = 1; size = list[0]; while (index <= size) { if (list[index] == value) { return (index); } index++; } DBG (DBG_error, "word %d not found in list\n", value); assert (0 == 1); /* bug in backend, core dump */ return (-1); } /* SCSI sense handler. Callback for SANE. */ static SANE_Status matsushita_sense_handler (int scsi_fd, unsigned char *result, void __sane_unused__ *arg) { int asc, ascq, sensekey; int len; DBG (DBG_proc, "matsushita_sense_handler (scsi_fd = %d)\n", scsi_fd); sensekey = get_RS_sense_key (result); len = 7 + get_RS_additional_length (result); hexdump (DBG_info2, "sense", result, len); if (get_RS_error_code (result) != 0x70) { DBG (DBG_error, "matsushita_sense_handler: invalid sense key error code (%d)\n", get_RS_error_code (result)); return SANE_STATUS_IO_ERROR; } if (get_RS_ILI (result) != 0) { DBG (DBG_sense, "matsushita_sense_handler: short read\n"); } if (len < 14) { DBG (DBG_error, "matsushita_sense_handler: sense too short, no ASC/ASCQ\n"); return SANE_STATUS_IO_ERROR; } asc = get_RS_ASC (result); ascq = get_RS_ASCQ (result); DBG (DBG_sense, "matsushita_sense_handler: sense=%d, ASC/ASCQ=%02x%02x\n", sensekey, asc, ascq); switch (sensekey) { case 0x00: /* no sense */ if (get_RS_EOM (result) && asc == 0x00 && ascq == 0x00) { DBG (DBG_sense, "matsushita_sense_handler: EOF\n"); return SANE_STATUS_EOF; } return SANE_STATUS_GOOD; break; case 0x02: /* not ready */ if (asc == 0x04 && ascq == 0x81) { /* Jam door open. */ return SANE_STATUS_COVER_OPEN; } break; case 0x03: /* medium error */ if (asc == 0x3a) { /* No paper in the feeder. */ return SANE_STATUS_NO_DOCS; } if (asc == 0x80) { /* Probably a paper jam. ascq might give more info. */ return SANE_STATUS_JAMMED; } break; case 0x05: if (asc == 0x20 || asc == 0x24 || asc == 0x26) { /* Invalid command, invalid field in CDB or invalid field in data. * The backend has prepared some wrong combination of options. * Shot the backend maintainer. */ return SANE_STATUS_IO_ERROR; } else if (asc == 0x2c && ascq == 0x80) { /* The scanner does have enough memory to scan the whole * area. For instance the KV-SS25 has only 4MB of memory, * which is not enough to scan a A4 page at 300dpi in gray * 8 bits. */ return SANE_STATUS_NO_MEM; } break; case 0x06: if (asc == 0x29) { /* Reset occured. May be the backend should retry the * command. */ return SANE_STATUS_GOOD; } break; } DBG (DBG_sense, "matsushita_sense_handler: unknown error condition. Please report it to the backend maintainer\n"); return SANE_STATUS_IO_ERROR; } /* Check that a new page is available by issuing an empty read. The * sense handler might return SANE_STATUS_NO_DOCS which indicates that * the feeder is now empty. */ static SANE_Status matsushita_check_next_page (Matsushita_Scanner * dev) { CDB cdb; SANE_Status status; DBG (DBG_proc, "matsushita_check_next_page: enter\n"); MKSCSI_READ_10 (cdb, 0, 0, 0); cdb.data[4] = dev->page_num; /* May be cdb.data[3] too? */ cdb.data[5] = dev->page_side; status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "matsushita_check_next_page: exit with status %d\n", status); return (status); } /* Attach a scanner to this backend. */ static SANE_Status attach_scanner (const char *devicename, Matsushita_Scanner ** devp) { Matsushita_Scanner *dev; int sfd; DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); if (devp) *devp = NULL; /* Check if we know this device name. */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } DBG (DBG_info, "device is already known\n"); return SANE_STATUS_GOOD; } } /* Allocate a new scanner entry. */ dev = matsushita_init (); if (dev == NULL) { DBG (DBG_error, "ERROR: not enough memory\n"); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_scanner: opening %s\n", devicename); if (sanei_scsi_open (devicename, &sfd, matsushita_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: attach_scanner: open failed\n"); matsushita_free (dev); return SANE_STATUS_INVAL; } /* Fill some scanner specific values. */ dev->devicename = strdup (devicename); dev->sfd = sfd; /* Now, check that it is a scanner we support. */ if (matsushita_identify_scanner (dev) == SANE_FALSE) { DBG (DBG_error, "ERROR: attach_scanner: scanner-identification failed\n"); matsushita_free (dev); return SANE_STATUS_INVAL; } matsushita_close (dev); /* Set the default options for that scanner. */ dev->sane.name = dev->devicename; dev->sane.vendor = "Panasonic"; dev->sane.model = dev->scsi_product; dev->sane.type = SANE_I18N ("sheetfed scanner"); /* Link the scanner with the others. */ dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } num_devices++; DBG (DBG_proc, "attach_scanner: exit\n"); return SANE_STATUS_GOOD; } static SANE_Status attach_one (const char *dev) { attach_scanner (dev, NULL); return SANE_STATUS_GOOD; } /* Reset the options for that scanner. */ static void matsushita_init_options (Matsushita_Scanner * dev) { int i; /* Pre-initialize the options. */ memset (dev->opt, 0, sizeof (dev->opt)); memset (dev->val, 0, sizeof (dev->val)); for (i = 0; i < OPT_NUM_OPTIONS; ++i) { dev->opt[i].size = sizeof (SANE_Word); dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } /* Number of options. */ dev->opt[OPT_NUM_OPTS].name = ""; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->val[OPT_NUM_OPTS].w = OPT_NUM_OPTIONS; /* Mode group */ dev->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); dev->opt[OPT_MODE_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_MODE_GROUP].cap = 0; dev->opt[OPT_MODE_GROUP].size = 0; dev->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Scanner supported modes */ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; dev->opt[OPT_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_MODE].size = max_string_size (scanners[dev->scnum].scan_mode_list); dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_MODE].constraint.string_list = scanners[dev->scnum].scan_mode_list; dev->val[OPT_MODE].s = (SANE_Char *) strdup (""); /* will be set later */ /* X and Y resolution */ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_RESOLUTION].constraint.word_list = scanners[dev->scnum].resolutions_list; dev->val[OPT_RESOLUTION].w = resolutions_list_300[1]; /* Duplex */ dev->opt[OPT_DUPLEX].name = SANE_NAME_DUPLEX; dev->opt[OPT_DUPLEX].title = SANE_TITLE_DUPLEX; dev->opt[OPT_DUPLEX].desc = SANE_DESC_DUPLEX; dev->opt[OPT_DUPLEX].type = SANE_TYPE_BOOL; dev->opt[OPT_DUPLEX].unit = SANE_UNIT_NONE; dev->val[OPT_DUPLEX].w = SANE_FALSE; if ((scanners[dev->scnum].cap & MAT_CAP_DUPLEX) == 0) dev->opt[OPT_DUPLEX].cap |= SANE_CAP_INACTIVE; /* Feeder mode */ dev->opt[OPT_FEEDER_MODE].name = "feeder-mode"; dev->opt[OPT_FEEDER_MODE].title = SANE_I18N ("Feeder mode"); dev->opt[OPT_FEEDER_MODE].desc = SANE_I18N ("Sets the feeding mode"); dev->opt[OPT_FEEDER_MODE].type = SANE_TYPE_STRING; dev->opt[OPT_FEEDER_MODE].size = max_string_size (feeder_mode_list); dev->opt[OPT_FEEDER_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_FEEDER_MODE].constraint.string_list = feeder_mode_list; dev->val[OPT_FEEDER_MODE].s = strdup (feeder_mode_list[0]); /* Geometry group */ dev->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); dev->opt[OPT_GEOMETRY_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_GEOMETRY_GROUP].cap = 0; dev->opt[OPT_GEOMETRY_GROUP].size = 0; dev->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Paper sizes list. */ dev->opt[OPT_PAPER_SIZE].name = SANE_NAME_PAPER_SIZE; dev->opt[OPT_PAPER_SIZE].title = SANE_TITLE_PAPER_SIZE; dev->opt[OPT_PAPER_SIZE].desc = SANE_DESC_PAPER_SIZE; dev->opt[OPT_PAPER_SIZE].type = SANE_TYPE_STRING; dev->opt[OPT_PAPER_SIZE].size = max_string_size (dev->paper_sizes_list); dev->opt[OPT_PAPER_SIZE].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_PAPER_SIZE].constraint.string_list = dev->paper_sizes_list; dev->val[OPT_PAPER_SIZE].s = strdup (""); /* will do it later */ /* Upper left X */ dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &(scanners[dev->scnum].x_range); /* Upper left Y */ dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &(scanners[dev->scnum].y_range); /* Bottom-right x */ dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &(scanners[dev->scnum].x_range); /* Bottom-right y */ dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &(scanners[dev->scnum].y_range); /* Enhancement group */ dev->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); dev->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* not valid for a group */ dev->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; dev->opt[OPT_ENHANCEMENT_GROUP].size = 0; dev->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* Brightness */ dev->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; dev->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; dev->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; dev->opt[OPT_BRIGHTNESS].size = sizeof (SANE_Int); dev->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BRIGHTNESS].constraint.range = &(scanners[dev->scnum].brightness_range); dev->val[OPT_BRIGHTNESS].w = 128; /* Contrast */ dev->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; dev->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; dev->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; dev->opt[OPT_CONTRAST].type = SANE_TYPE_INT; dev->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; dev->opt[OPT_CONTRAST].size = sizeof (SANE_Int); dev->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_CONTRAST].constraint.range = &(scanners[dev->scnum].contrast_range); dev->val[OPT_CONTRAST].w = 128; if ((scanners[dev->scnum].cap & MAT_CAP_CONTRAST) == 0) dev->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; /* Automatic threshold */ dev->opt[OPT_AUTOMATIC_THRESHOLD].name = "automatic-threshold"; dev->opt[OPT_AUTOMATIC_THRESHOLD].title = SANE_I18N ("Automatic threshold"); dev->opt[OPT_AUTOMATIC_THRESHOLD].desc = SANE_I18N ("Automatically sets brightness, contrast, white level, gamma, noise reduction and image emphasis"); dev->opt[OPT_AUTOMATIC_THRESHOLD].type = SANE_TYPE_STRING; dev->opt[OPT_AUTOMATIC_THRESHOLD].size = max_string_size (automatic_threshold_list); dev->opt[OPT_AUTOMATIC_THRESHOLD].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_AUTOMATIC_THRESHOLD].constraint.string_list = automatic_threshold_list; dev->val[OPT_AUTOMATIC_THRESHOLD].s = strdup (automatic_threshold_list[0]); if ((scanners[dev->scnum].cap & MAT_CAP_AUTOMATIC_THRESHOLD) == 0) dev->opt[OPT_AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* Halftone pattern */ dev->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; dev->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; dev->opt[OPT_HALFTONE_PATTERN].size = max_string_size (halftone_pattern_list); dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_pattern_list; dev->val[OPT_HALFTONE_PATTERN].s = strdup (halftone_pattern_list[0]); /* Automatic separation */ dev->opt[OPT_AUTOMATIC_SEPARATION].name = SANE_NAME_AUTOSEP; dev->opt[OPT_AUTOMATIC_SEPARATION].title = SANE_TITLE_AUTOSEP; dev->opt[OPT_AUTOMATIC_SEPARATION].desc = SANE_DESC_AUTOSEP; dev->opt[OPT_AUTOMATIC_SEPARATION].type = SANE_TYPE_BOOL; dev->opt[OPT_AUTOMATIC_SEPARATION].unit = SANE_UNIT_NONE; dev->val[OPT_AUTOMATIC_SEPARATION].w = SANE_FALSE; /* White level base */ dev->opt[OPT_WHITE_LEVEL].name = SANE_NAME_WHITE_LEVEL; dev->opt[OPT_WHITE_LEVEL].title = SANE_TITLE_WHITE_LEVEL; dev->opt[OPT_WHITE_LEVEL].desc = SANE_DESC_WHITE_LEVEL; dev->opt[OPT_WHITE_LEVEL].type = SANE_TYPE_STRING; dev->opt[OPT_WHITE_LEVEL].size = max_string_size (white_level_list); dev->opt[OPT_WHITE_LEVEL].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_WHITE_LEVEL].constraint.string_list = white_level_list; dev->val[OPT_WHITE_LEVEL].s = strdup (white_level_list[0]); if ((scanners[dev->scnum].cap & MAT_CAP_WHITE_LEVEL) == 0) dev->opt[OPT_WHITE_LEVEL].cap |= SANE_CAP_INACTIVE; /* Noise reduction */ dev->opt[OPT_NOISE_REDUCTION].name = "noise-reduction"; dev->opt[OPT_NOISE_REDUCTION].title = SANE_I18N ("Noise reduction"); dev->opt[OPT_NOISE_REDUCTION].desc = SANE_I18N ("Reduce the isolated dot noise"); dev->opt[OPT_NOISE_REDUCTION].type = SANE_TYPE_STRING; dev->opt[OPT_NOISE_REDUCTION].size = max_string_size (noise_reduction_list); dev->opt[OPT_NOISE_REDUCTION].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_NOISE_REDUCTION].constraint.string_list = noise_reduction_list; dev->val[OPT_NOISE_REDUCTION].s = strdup (noise_reduction_list[0]); if ((scanners[dev->scnum].cap & MAT_CAP_NOISE_REDUCTION) == 0) dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; /* Image emphasis */ dev->opt[OPT_IMAGE_EMPHASIS].name = "image-emphasis"; dev->opt[OPT_IMAGE_EMPHASIS].title = SANE_I18N ("Image emphasis"); dev->opt[OPT_IMAGE_EMPHASIS].desc = SANE_I18N ("Sets the image emphasis"); dev->opt[OPT_IMAGE_EMPHASIS].type = SANE_TYPE_STRING; dev->opt[OPT_IMAGE_EMPHASIS].size = max_string_size (scanners[dev->scnum].image_emphasis_list); dev->opt[OPT_IMAGE_EMPHASIS].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_IMAGE_EMPHASIS].constraint.string_list = scanners[dev->scnum].image_emphasis_list; dev->val[OPT_IMAGE_EMPHASIS].s = strdup (SANE_I18N ("Medium")); /* Gamma */ dev->opt[OPT_GAMMA].name = "gamma"; dev->opt[OPT_GAMMA].title = SANE_I18N ("Gamma"); dev->opt[OPT_GAMMA].desc = SANE_I18N ("Gamma"); dev->opt[OPT_GAMMA].type = SANE_TYPE_STRING; dev->opt[OPT_GAMMA].size = max_string_size (gamma_list); dev->opt[OPT_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST; dev->opt[OPT_GAMMA].constraint.string_list = gamma_list; dev->val[OPT_GAMMA].s = strdup (gamma_list[0]); /* Lastly, set the default scan mode. This might change some * values previously set here. */ sane_control_option (dev, OPT_PAPER_SIZE, SANE_ACTION_SET_VALUE, (SANE_String_Const *) dev->paper_sizes_list[0], NULL); sane_control_option (dev, OPT_MODE, SANE_ACTION_SET_VALUE, (SANE_String_Const *) scanners[dev->scnum]. scan_mode_list[0], NULL); } /* Wait until the scanner is ready. * * The only reason I know the scanner is not ready is because it is * moving the CCD. */ static SANE_Status matsushita_wait_scanner (Matsushita_Scanner * dev) { SANE_Status status; int timeout; CDB cdb; DBG (DBG_proc, "matsushita_wait_scanner: enter\n"); MKSCSI_TEST_UNIT_READY (cdb); /* Set the timeout to 60 seconds. */ timeout = 60; while (timeout > 0) { /* test unit ready */ status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); if (status == SANE_STATUS_GOOD) { return SANE_STATUS_GOOD; } sleep (1); }; DBG (DBG_proc, "matsushita_wait_scanner: scanner not ready\n"); return (SANE_STATUS_IO_ERROR); } /* Reset a window. This is used to re-initialize the scanner. */ static SANE_Status matsushita_reset_window (Matsushita_Scanner * dev) { CDB cdb; SANE_Status status; DBG (DBG_proc, "matsushita_reset_window: enter\n"); MKSCSI_SET_WINDOW (cdb, 0); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, NULL, NULL); DBG (DBG_proc, "matsushita_reset_window: exit, status=%d\n", status); return status; } /* Set a window. */ static SANE_Status matsushita_set_window (Matsushita_Scanner * dev, int side) { size_t size; CDB cdb; unsigned char window[72]; SANE_Status status; int i; DBG (DBG_proc, "matsushita_set_window: enter\n"); size = sizeof (window); MKSCSI_SET_WINDOW (cdb, size); memset (window, 0, size); /* size of the windows descriptor block */ window[7] = sizeof (window) - 8; /* Page side */ window[8] = side; /* X and Y resolution */ Ito16 (dev->resolution, &window[10]); Ito16 (dev->resolution, &window[12]); /* Upper Left (X,Y) */ Ito32 (dev->x_tl, &window[14]); Ito32 (dev->y_tl, &window[18]); /* Width and length */ Ito32 (dev->width, &window[22]); Ito32 (dev->length, &window[26]); Ito32 (dev->width, &window[56]); /* again, verso? */ Ito32 (dev->length, &window[60]); /* again, verso? */ /* Brightness */ window[30] = 255 - dev->val[OPT_BRIGHTNESS].w; window[31] = window[30]; /* same as brightness. */ /* Contrast */ window[32] = dev->val[OPT_CONTRAST].w; /* Image Composition */ switch (dev->scan_mode) { case MATSUSHITA_BW: window[33] = 0x00; break; case MATSUSHITA_HALFTONE: window[33] = 0x01; break; case MATSUSHITA_GRAYSCALE: window[33] = 0x02; break; } /* Depth */ window[34] = dev->depth; /* Halftone pattern. */ if (dev->scan_mode == MATSUSHITA_HALFTONE) { i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); window[36] = halftone_pattern_val[i]; } /* Gamma */ if (dev->scan_mode == MATSUSHITA_GRAYSCALE) { i = get_string_list_index (gamma_list, dev->val[OPT_GAMMA].s); window[52] = gamma_val[i]; } /* Feeder mode */ i = get_string_list_index (feeder_mode_list, dev->val[OPT_FEEDER_MODE].s); window[65] = feeder_mode_val[i]; /* Image emphasis */ i = get_string_list_index (scanners[dev->scnum].image_emphasis_list, dev->val[OPT_IMAGE_EMPHASIS].s); window[51] = scanners[dev->scnum].image_emphasis_val[i]; /* White level */ i = get_string_list_index (white_level_list, dev->val[OPT_WHITE_LEVEL].s); window[68] = white_level_val[i]; if (dev->scan_mode == MATSUSHITA_BW || dev->scan_mode == MATSUSHITA_HALFTONE) { /* Noise reduction */ i = get_string_list_index (noise_reduction_list, dev->val[OPT_NOISE_REDUCTION].s); window[69] = noise_reduction_val[i]; /* Automatic separation */ if (dev->val[OPT_AUTOMATIC_SEPARATION].w) { window[67] = 0x80; } /* Automatic threshold. Must be last because it may override * some previous options. */ i = get_string_list_index (automatic_threshold_list, dev->val[OPT_AUTOMATIC_THRESHOLD].s); window[66] = automatic_threshold_val[i]; if (automatic_threshold_val[i] != 0) { /* Automatic threshold is enabled. */ window[30] = 0; /* brightness. */ window[31] = 0; /* same as brightness. */ window[32] = 0; /* contrast */ window[33] = 0; /* B&W mode */ window[36] = 0; /* Halftone pattern. */ window[51] = 0; /* Image emphasis */ window[67] = 0; /* Automatic separation */ window[68] = 0; /* White level */ window[69] = 0; /* Noise reduction */ } } hexdump (DBG_info2, "windows", window, 72); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, window, sizeof (window), NULL, NULL); DBG (DBG_proc, "matsushita_set_window: exit, status=%d\n", status); return status; } /* Read the image from the scanner and fill the temporary buffer with it. */ static SANE_Status matsushita_fill_image (Matsushita_Scanner * dev) { SANE_Status status; size_t size; CDB cdb; DBG (DBG_proc, "matsushita_fill_image: enter\n"); assert (dev->image_begin == dev->image_end); assert (dev->real_bytes_left > 0); dev->image_begin = 0; dev->image_end = 0; while (dev->real_bytes_left) { /* * Try to read the maximum number of bytes. * * The windows driver reads no more than 0x8000 byte. * * This backend operates differently than the windows * driver. The windows TWAIN driver always read 2 more bytes * at the end, so it gets a CHECK CONDITION with a short read * sense. Since the linux scsi layer seem to be buggy * regarding the resid, always read exactly the number of * remaining bytes. */ size = dev->real_bytes_left; if (size > dev->image_size - dev->image_end) size = dev->image_size - dev->image_end; if (size > 0x8000) size = 0x8000; if (size == 0) { /* Probably reached the end of the buffer. * Check, just in case. */ assert (dev->image_end != 0); return (SANE_STATUS_GOOD); } DBG (DBG_info, "sane_read: to read = %ld bytes (bpl=%d)\n", (long) size, dev->params.bytes_per_line); MKSCSI_READ_10 (cdb, 0, 0, size); cdb.data[4] = dev->page_num; /* May be cdb.data[3] too? */ cdb.data[5] = dev->page_side; hexdump (DBG_info2, "sane_read: READ_10 CDB", cdb.data, 10); status = sanei_scsi_cmd2 (dev->sfd, cdb.data, cdb.len, NULL, 0, dev->buffer, &size); if (status == SANE_STATUS_EOF) { DBG (DBG_proc, "sane_read: exit, end of page scan\n"); return (SANE_STATUS_EOF); } if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_read: cannot read from the scanner\n"); return status; } dev->real_bytes_left -= size; switch (dev->depth) { case 1: { /* For Black & White, the bits in every bytes are mirrored. * for instance 11010001 is coded as 10001011 */ unsigned char *src = dev->buffer; unsigned char *dest = dev->image + dev->image_end; unsigned char s; unsigned char d; size_t i; for (i = 0; i < size; i++) { s = *src; d = 0; if (s & 0x01) d |= 0x80; if (s & 0x02) d |= 0x40; if (s & 0x04) d |= 0x20; if (s & 0x08) d |= 0x10; if (s & 0x10) d |= 0x08; if (s & 0x20) d |= 0x04; if (s & 0x40) d |= 0x02; if (s & 0x80) d |= 0x01; *dest = d; src++; dest++; } } break; case 4: { /* Adjust from a depth of 4 bits ([0..15]) to * a depth of 8 bits ([0..255]) */ unsigned char *src = dev->buffer; unsigned char *dest = dev->image + dev->image_end; size_t i; /* n bytes from image --> 2*n bytes in buf. */ for (i = 0; i < size; i++) { *dest = ((*src & 0x0f) >> 0) * 17; dest++; *dest = ((*src & 0xf0) >> 4) * 17; dest++; src++; } size *= 2; } break; default: memcpy (dev->image + dev->image_end, dev->buffer, size); break; } dev->image_end += size; } return (SANE_STATUS_GOOD); /* unreachable */ } /* Copy from the raw buffer to the buffer given by the backend. * * len in input is the maximum length available in buf, and, in * output, is the length written into buf. */ static void matsushita_copy_raw_to_frontend (Matsushita_Scanner * dev, SANE_Byte * buf, size_t * len) { size_t size; size = dev->image_end - dev->image_begin; if (size > *len) { size = *len; } *len = size; memcpy (buf, dev->image + dev->image_begin, size); dev->image_begin += size; } /* Stop a scan. */ static SANE_Status do_cancel (Matsushita_Scanner * dev) { DBG (DBG_sane_proc, "do_cancel enter\n"); if (dev->scanning == SANE_TRUE) { /* Reset the scanner */ matsushita_reset_window (dev); matsushita_close (dev); } dev->scanning = SANE_FALSE; DBG (DBG_sane_proc, "do_cancel exit\n"); return SANE_STATUS_CANCELLED; } /*--------------------------------------------------------------------------*/ /* Entry points */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { FILE *fp; char dev_name[PATH_MAX]; size_t len; DBG_INIT (); DBG (DBG_sane_init, "sane_init\n"); DBG (DBG_error, "This is sane-matsushita version %d.%d-%d\n", SANE_CURRENT_MAJOR, V_MINOR, BUILD); DBG (DBG_error, "(C) 2002 by Frank Zago\n"); if (version_code) { *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); } fp = sanei_config_open (MATSUSHITA_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ attach_scanner ("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') /* ignore line comments */ continue; len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); DBG (DBG_proc, "sane_init: leave\n"); return SANE_STATUS_GOOD; } SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { Matsushita_Scanner *dev; int i; DBG (DBG_proc, "sane_get_devices: enter\n"); if (devlist) free (devlist); devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; i = 0; for (dev = first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; DBG (DBG_proc, "sane_get_devices: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Matsushita_Scanner *dev; SANE_Status status; DBG (DBG_proc, "sane_open: enter\n"); /* search for devicename */ if (devicename[0]) { DBG (DBG_info, "sane_open: devicename=%s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { DBG (DBG_sane_info, "sane_open: no devicename, opening first device\n"); dev = first_dev; /* empty devicename -> use first device */ } if (!dev) { DBG (DBG_error, "No scanner found\n"); return SANE_STATUS_INVAL; } /* Build a list a paper size that fit into this scanner. */ matsushita_build_paper_sizes (dev); matsushita_init_options (dev); *handle = dev; DBG (DBG_proc, "sane_open: exit\n"); return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Matsushita_Scanner *dev = handle; DBG (DBG_proc, "sane_get_option_descriptor: enter, option %d\n", option); if ((unsigned) option >= OPT_NUM_OPTIONS) { return NULL; } DBG (DBG_proc, "sane_get_option_descriptor: exit\n"); return dev->opt + option; } SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Matsushita_Scanner *dev = handle; SANE_Status status; SANE_Word cap; SANE_String_Const name; int i; SANE_Word value; int rc; DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", option, action); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } name = dev->opt[option].name; if (!name) { name = "(no name)"; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_DUPLEX: case OPT_AUTOMATIC_SEPARATION: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_FEEDER_MODE: case OPT_HALFTONE_PATTERN: case OPT_PAPER_SIZE: case OPT_AUTOMATIC_THRESHOLD: case OPT_WHITE_LEVEL: case OPT_NOISE_REDUCTION: case OPT_IMAGE_EMPHASIS: case OPT_GAMMA: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* The length of X must be rounded (up). */ case OPT_TL_X: case OPT_BR_X: value = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)); i = get_int_list_index (scanners[dev->scnum].resolutions_list, dev->val[OPT_RESOLUTION].w); if (value & (scanners[dev->scnum].resolutions_round[i] - 1)) { value = (value | (scanners[dev->scnum].resolutions_round[i] - 1)) + 1; if (info) { *info |= SANE_INFO_INEXACT; } } *(SANE_Word *) val = SANE_FIX (iluToMm (value)); dev->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; /* Side-effect free options */ case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_DUPLEX: case OPT_AUTOMATIC_SEPARATION: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* String mode */ case OPT_WHITE_LEVEL: case OPT_NOISE_REDUCTION: case OPT_IMAGE_EMPHASIS: case OPT_GAMMA: case OPT_FEEDER_MODE: free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); return SANE_STATUS_GOOD; case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_Char *) strdup (val); /* Set default options for the scan modes. */ dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, BLACK_WHITE_STR) == 0) { dev->depth = 1; dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE; i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); if (halftone_pattern_val[i] == -1) { dev->scan_mode = MATSUSHITA_BW; } else { dev->scan_mode = MATSUSHITA_HALFTONE; } } else if (strcmp (dev->val[OPT_MODE].s, GRAY4_STR) == 0) { dev->scan_mode = MATSUSHITA_GRAYSCALE; dev->depth = 4; dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, GRAY8_STR) == 0) { dev->scan_mode = MATSUSHITA_GRAYSCALE; dev->depth = 8; dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; } else { assert (0 == 1); } /* Some options might not be supported by the scanner. */ if ((scanners[dev->scnum].cap & MAT_CAP_GAMMA) == 0) dev->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_HALFTONE_PATTERN: free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); if (halftone_pattern_val[i] == -1) { dev->scan_mode = MATSUSHITA_BW; } else { dev->scan_mode = MATSUSHITA_HALFTONE; } return SANE_STATUS_GOOD; case OPT_PAPER_SIZE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_PAPER_SIZE].s); dev->val[OPT_PAPER_SIZE].s = (SANE_Char *) strdup (val); i = get_string_list_index (dev->paper_sizes_list, dev->val[OPT_PAPER_SIZE].s); i = dev->paper_sizes_val[i]; /* Set the 4 corners values. */ value = 0; rc = sane_control_option (handle, OPT_TL_X, SANE_ACTION_SET_VALUE, &value, info); assert (rc == SANE_STATUS_GOOD); value = 0; rc = sane_control_option (handle, OPT_TL_Y, SANE_ACTION_SET_VALUE, &value, info); assert (rc == SANE_STATUS_GOOD); value = SANE_FIX (paper_sizes[i].width); rc = sane_control_option (handle, OPT_BR_X, SANE_ACTION_SET_VALUE, &value, info); assert (rc == SANE_STATUS_GOOD); value = SANE_FIX (paper_sizes[i].length); rc = sane_control_option (handle, OPT_BR_Y, SANE_ACTION_SET_VALUE, &value, info); assert (rc == SANE_STATUS_GOOD); if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_AUTOMATIC_THRESHOLD: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_Char *) strdup (val); /* If the threshold is not set to none, some option must * disappear. */ dev->opt[OPT_WHITE_LEVEL].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_IMAGE_EMPHASIS].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (strcmp (dev->val[option].s, automatic_threshold_list[0]) == 0) { dev->opt[OPT_WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_IMAGE_EMPHASIS].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; if (dev->scan_mode == MATSUSHITA_BW || dev->scan_mode == MATSUSHITA_HALFTONE) { dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Matsushita_Scanner *dev = handle; DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { /* Setup the parameters for the scan. These values will be re-used * in the SET WINDOWS command. */ dev->resolution = dev->val[OPT_RESOLUTION].w; dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); /* Check the corners are OK. */ if (dev->x_tl > dev->x_br) { int s; s = dev->x_tl; dev->x_tl = dev->x_br; dev->x_br = s; } if (dev->y_tl > dev->y_br) { int s; s = dev->y_tl; dev->y_tl = dev->y_br; dev->y_br = s; } dev->width = dev->x_br - dev->x_tl; dev->length = dev->y_br - dev->y_tl; /* Prepare the parameters for the caller. */ memset (&dev->params, 0, sizeof (SANE_Parameters)); dev->params.format = SANE_FRAME_GRAY; dev->params.last_frame = SANE_TRUE; dev->params.pixels_per_line = (((dev->width * dev->resolution) / 1200) + 7) & ~0x7; if (dev->depth == 4) { dev->params.depth = 8; } else { dev->params.depth = dev->depth; } dev->params.bytes_per_line = (dev->params.pixels_per_line / 8) * dev->params.depth; dev->params.lines = (dev->length * dev->resolution) / 1200; } /* Return the current values. */ if (params) { *params = (dev->params); } DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Matsushita_Scanner *dev = handle; SANE_Status status; DBG (DBG_proc, "sane_start: enter\n"); if (!(dev->scanning)) { sane_get_parameters (dev, NULL); if (dev->image == NULL) { dev->image_size = 3 * dev->buffer_size; dev->image = malloc (dev->image_size); if (dev->image == NULL) { return SANE_STATUS_NO_MEM; } } /* Open again the scanner. */ if (sanei_scsi_open (dev->devicename, &(dev->sfd), matsushita_sense_handler, dev) != 0) { DBG (DBG_error, "ERROR: sane_start: open failed\n"); return SANE_STATUS_INVAL; } dev->page_side = 0; /* page front */ dev->page_num = 0; /* first page */ /* The scanner must be ready. */ status = matsushita_wait_scanner (dev); if (status) { matsushita_close (dev); return status; } status = matsushita_reset_window (dev); if (status) { matsushita_close (dev); return status; } status = matsushita_set_window (dev, PAGE_FRONT); if (status) { matsushita_close (dev); return status; } if (dev->val[OPT_DUPLEX].w == SANE_TRUE) { status = matsushita_set_window (dev, PAGE_BACK); if (status) { matsushita_close (dev); return status; } } status = matsushita_read_document_size (dev); if (status) { matsushita_close (dev); return status; } } else { if (dev->val[OPT_DUPLEX].w == SANE_TRUE && dev->page_side == PAGE_FRONT) { dev->page_side = PAGE_BACK; } else { /* new sheet. */ dev->page_side = PAGE_FRONT; dev->page_num++; } status = matsushita_check_next_page (dev); if (status) { return status; } } dev->bytes_left = dev->params.bytes_per_line * dev->params.lines; dev->real_bytes_left = dev->params.bytes_per_line * dev->params.lines; if (dev->depth == 4) { /* Every byte read will be expanded into 2 bytes. */ dev->real_bytes_left /= 2; } dev->image_end = 0; dev->image_begin = 0; dev->scanning = SANE_TRUE; DBG (DBG_proc, "sane_start: exit\n"); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { SANE_Status status; Matsushita_Scanner *dev = handle; size_t size; int buf_offset; /* offset into buf */ DBG (DBG_proc, "sane_read: enter\n"); *len = 0; if (!(dev->scanning)) { /* OOPS, not scanning */ return do_cancel (dev); } if (dev->bytes_left <= 0) { return (SANE_STATUS_EOF); } buf_offset = 0; do { if (dev->image_begin == dev->image_end) { /* Fill image */ status = matsushita_fill_image (dev); if (status != SANE_STATUS_GOOD) { return (status); } } /* Something must have been read */ if (dev->image_begin == dev->image_end) { DBG (DBG_info, "sane_read: nothing read\n"); return SANE_STATUS_IO_ERROR; } /* Copy the data to the frontend buffer. */ size = max_len - buf_offset; if (size > dev->bytes_left) { size = dev->bytes_left; } matsushita_copy_raw_to_frontend (dev, buf + buf_offset, &size); buf_offset += size; dev->bytes_left -= size; *len += size; } while ((buf_offset != max_len) && dev->bytes_left); DBG (DBG_info, "sane_read: leave, bytes_left=%ld\n", (long)dev->bytes_left); return SANE_STATUS_GOOD; } SANE_Status sane_set_io_mode (SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { SANE_Status status; Matsushita_Scanner *dev = handle; DBG (DBG_proc, "sane_set_io_mode: enter\n"); if (dev->scanning == SANE_FALSE) { return (SANE_STATUS_INVAL); } if (non_blocking == SANE_FALSE) { status = SANE_STATUS_GOOD; } else { status = SANE_STATUS_UNSUPPORTED; } DBG (DBG_proc, "sane_set_io_mode: exit\n"); return status; } SANE_Status sane_get_select_fd (SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ * fd) { DBG (DBG_proc, "sane_get_select_fd: enter\n"); DBG (DBG_proc, "sane_get_select_fd: exit\n"); return SANE_STATUS_UNSUPPORTED; } void sane_cancel (SANE_Handle handle) { Matsushita_Scanner *dev = handle; DBG (DBG_proc, "sane_cancel: enter\n"); do_cancel (dev); DBG (DBG_proc, "sane_cancel: exit\n"); } void sane_close (SANE_Handle handle) { Matsushita_Scanner *dev = handle; Matsushita_Scanner *dev_tmp; DBG (DBG_proc, "sane_close: enter\n"); do_cancel (dev); matsushita_close (dev); /* Unlink dev. */ if (first_dev == dev) { first_dev = dev->next; } else { dev_tmp = first_dev; while (dev_tmp->next && dev_tmp->next != dev) { dev_tmp = dev_tmp->next; } if (dev_tmp->next != NULL) { dev_tmp->next = dev_tmp->next->next; } } matsushita_free (dev); num_devices--; DBG (DBG_proc, "sane_close: exit\n"); } void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); while (first_dev) { sane_close (first_dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); } sane-backends-1.0.27/backend/hp.TODO0000664000175000017500000000265412112021330013677 00000000000000These are Geoffreys TODOs: Fix ifdef ENABLE_'s Add emulation for color separation matrixes? Gamma plot initialization? Dither pattern option not working right. More use of FAILED macro , maybe SUCCESS macro ? Convert to single .h file? /** FIXME: ToDo * * Split up hp_scsi_open -- don't need full probe every time? * or if probing at least make sure answer is constant. * * Stale flage so don't download unchanged parameters? * * Fix or disable dither stuff. * * Add controls * * Preview mode: fast, grayscale instead of halftone. * Separate X and Y resolutions + bind button. * 10x8 tone maps? * Sharpening? * Matrixes - fix color separtion? * Dither pattern? COlor dither pattern? * * check return values (of maybe others)? * get rid of overly verbose DBG's * add som DBG's */ New TODOs: Find a way to set matrices in the frontend (gtk-table with sliders ?) Find a way to set dither matrices in the frontend (See the ENABLE_...-macros in hp.h to enable these features) Fix problem with performance of reader-process. Communication through the pipe might be too slow and make the scanner repeating several strips. Fix various problems with PhotoScanner: - rubbish on bottom of scanned image - too few data that is received on bottom of scanned image for PhotoScanner - scan time for slides at 2400 dpi is twice as long as under M$-Windows Support 10/12-bits for greyscale sane-backends-1.0.27/backend/canon630u.conf.in0000664000175000017500000000030112112021330015554 00000000000000# Options for the canonusb backend # Autodetect the Canon CanoScan FB630u usb 0x04a9 0x2204 # device list for non-linux-systems (enable if autodetect fails): #/dev/scanner #/dev/usb/scanner0 sane-backends-1.0.27/backend/plustek-pp_io.c0000664000175000017500000005537112775277260015602 00000000000000/* @file plustekpp-io.c * @brief as the name says, here we have all the I/O * functions according to the parallel port hardware * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2013 Gerhard Jaeger * * History: * - 0.37 - initial version * - added Kevins' suggestions * - 0.38 - added Asic 98003 stuff and ioP98ReadWriteTest() * - added IODataRegisterToDAC() * - replaced function IOSPPWrite by IOMoveDataToScanner * - modified ioP98OpenScanPath again and reuse V0.36 stuff again * - added IO functions * - 0.39 - added IO functions * - added f97003 stuff from A3I code * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - no changes * - 0.44 - fix format string issues, as Long types default to int32_t * now * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** some prototypes *********************************/ static Bool fnEPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize ); static Bool fnSPPRead ( pScanData ps, pUChar pBuffer, ULong ulSize ); static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize ); typedef struct { pFnReadData func; char *name; } ioReadFuncDef; static ioReadFuncDef ioReadFunc[3] = { { fnEPPRead, "fnEPPRead" }, { fnSPPRead, "fnSPPRead" }, { fnBiDirRead, "fnBiDirRead" } }; /*************************** some definitions ********************************/ #define _MEMTEST_SIZE 1280 /*************************** local functions *********************************/ /** we provide some functions to read data from SPP port according to * the speed we have detected (ReadWriteTest!!) */ static Byte ioDataFromSPPFast( pScanData ps ) { Byte bData, tmp; /* notify asic we will read the high nibble data from status port */ if( _FALSE == ps->f97003 ) { _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); _DO_UDELAY( 1 ); } /* read high nibble */ bData = _INB_STATUS( ps ); bData &= 0xf0; _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); _DO_UDELAY( 1 ); /* read low nibble */ tmp = _INB_STATUS( ps ); /* combine with low nibble */ bData |= (tmp >> 4); _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); _DO_UDELAY( 1 ); return bData; } static Byte ioDataFromSPPMiddle( pScanData ps ) { Byte bData, tmp; /* notify asic we will read the high nibble data from status port */ if( _FALSE == ps->f97003 ) { _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); _DO_UDELAY( 1 ); } /* read high nibble */ _INB_STATUS( ps ); bData = _INB_STATUS( ps ); bData &= 0xf0; _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); _DO_UDELAY( 1 ); /* read low nibble */ _INB_STATUS( ps ); tmp = _INB_STATUS( ps ); /* combine with low nibble */ bData |= (tmp >> 4); _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); _DO_UDELAY( 1 ); return bData; } static UChar ioDataFromSPPSlow( pScanData ps ) { Byte bData, tmp; /* notify asic we will read the high nibble data from status port */ if( _FALSE == ps->f97003 ) { _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); _DO_UDELAY( 2 ); } /* read high nibble */ _INB_STATUS( ps ); _INB_STATUS( ps ); bData = _INB_STATUS( ps ); bData &= 0xf0; _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); _DO_UDELAY( 2 ); /* read low nibble */ _INB_STATUS( ps ); _INB_STATUS( ps ); tmp = _INB_STATUS( ps ); /* combine with low nibble */ bData |= (tmp >> 4); _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); _DO_UDELAY( 2 ); return bData; } static UChar ioDataFromSPPSlowest( pScanData ps ) { Byte bData, tmp; /* notify asic we will read the high nibble data from status port */ if( _FALSE == ps->f97003 ) { _OUTB_CTRL( ps, ps->CtrlReadHighNibble ); _DO_UDELAY( 3 ); } /* read high nibble */ _INB_STATUS( ps ); _INB_STATUS( ps ); _INB_STATUS( ps ); bData = _INB_STATUS( ps ); bData &= 0xf0; _OUTB_CTRL( ps, ps->CtrlReadLowNibble ); _DO_UDELAY( 3 ); /* read low nibble */ _INB_STATUS( ps ); _INB_STATUS( ps ); _INB_STATUS( ps ); tmp = _INB_STATUS( ps ); /* combine with low nibble */ bData |= (tmp >> 4); _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); _DO_UDELAY( 3 ); return bData; } /** Read data from STATUS port. We have to read twice and combine two nibble * data to one byte. */ static Bool fnSPPRead( pScanData ps, pUChar pBuffer, ULong ulSize ) { switch( ps->IO.delay ) { case 0: for (; ulSize; ulSize--, pBuffer++) *pBuffer = ioDataFromSPPFast( ps ); break; case 1: for (; ulSize; ulSize--, pBuffer++) *pBuffer = ioDataFromSPPMiddle( ps ); break; case 2: for (; ulSize; ulSize--, pBuffer++) *pBuffer = ioDataFromSPPSlow( ps ); break; default: for (; ulSize; ulSize--, pBuffer++) *pBuffer = ioDataFromSPPSlowest( ps ); break; } return _TRUE; } /** Using buffered I/O to read data from EPP Data Port */ static Bool fnEPPRead( pScanData ps, pUChar pBuffer, ULong ulSize ) { register ULong i; if( _IS_ASIC98(ps->sCaps.AsicID)) { #ifndef __KERNEL__ sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN ); #else _OUTB_CTRL( ps, (_CTRL_GENSIGNAL + _CTRL_DIRECTION)); _DO_UDELAY( 1 ); #endif for( i = 0; i < ulSize; i++ ) pBuffer[i] = _INB_EPPDATA( ps ); #ifndef __KERNEL__ sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT ); #else _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); _DO_UDELAY( 1 ); #endif } else { for( i = 0; i < ulSize; i++ ) pBuffer[i] = _INB_EPPDATA( ps ); } return _TRUE; } /** */ static Bool fnBiDirRead( pScanData ps, pUChar pBuffer, ULong ulSize ) { UChar start, end; start = _CTRL_START_BIDIREAD; end = _CTRL_END_BIDIREAD; #ifndef __KERNEL__ sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAIN ); if( !sanei_pp_uses_directio()) { start &= ~_CTRL_DIRECTION; end &= ~_CTRL_DIRECTION; } #else if( _IS_ASIC98(ps->sCaps.AsicID)) { _OUTB_CTRL( ps, (_CTRL_GENSIGNAL + _CTRL_DIRECTION)); } #endif switch( ps->IO.delay ) { case 0: for( ; ulSize; ulSize--, pBuffer++ ) { _OUTB_CTRL( ps, start ); *pBuffer = _INB_DATA( ps ); _OUTB_CTRL( ps, end ); } break; case 1: _DO_UDELAY( 1 ); for(; ulSize; ulSize--, pBuffer++ ) { _OUTB_CTRL( ps, start ); _DO_UDELAY( 1 ); *pBuffer = _INB_DATA( ps ); _OUTB_CTRL( ps, end ); _DO_UDELAY( 1 ); } break; default: _DO_UDELAY( 2 ); for(; ulSize; ulSize--, pBuffer++ ) { _OUTB_CTRL( ps, start ); _DO_UDELAY( 2 ); *pBuffer = _INB_DATA( ps ); _OUTB_CTRL( ps, end ); _DO_UDELAY( 2 ); } break; } #ifndef __KERNEL__ sanei_pp_set_datadir( ps->pardev, SANEI_PP_DATAOUT ); #else if( _IS_ASIC98(ps->sCaps.AsicID)) { _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); } #endif return _TRUE; } /** as the name says, we switch to SPP mode */ static void ioSwitchToSPPMode( pScanData ps ) { /* save the control and data port value */ ps->IO.bOldControlValue = _INB_CTRL( ps ); ps->IO.bOldDataValue = _INB_DATA( ps ); _OUTB_CTRL( ps, _CTRL_GENSIGNAL ); /* 0xc4 */ _DO_UDELAY( 2 ); } /** restore the port settings */ static void ioRestoreParallelMode( pScanData ps ) { _OUTB_CTRL( ps, ps->IO.bOldControlValue & 0x3f ); _DO_UDELAY( 1 ); _OUTB_DATA( ps, ps->IO.bOldDataValue ); _DO_UDELAY( 1 ); } /** try to connect to scanner (ASIC 9600x and 98001) */ _LOC void ioP98001EstablishScannerConnection( pScanData ps, ULong delTime ) { _OUTB_DATA( ps, _ID_TO_PRINTER ); _DO_UDELAY( delTime ); _OUTB_DATA( ps, _ID1ST ); _DO_UDELAY( delTime ); _OUTB_DATA( ps, _ID2ND ); _DO_UDELAY( delTime ); _OUTB_DATA( ps, _ID3RD ); _DO_UDELAY( delTime ); _OUTB_DATA( ps, _ID4TH ); _DO_UDELAY( delTime ); } /** try to connect to scanner (ASIC 98003) */ static void ioP98003EstablishScannerConnection( pScanData ps, ULong delTime ) { _OUTB_DATA( ps, _ID1ST ); _DO_UDELAY( delTime ); _OUTB_DATA( ps, _ID2ND ); _DO_UDELAY( delTime ); _OUTB_DATA( ps, _ID3RD ); _DO_UDELAY( delTime ); _OUTB_DATA( ps, _ID4TH ); _DO_UDELAY( delTime ); } /** switch the printer interface to scanner */ static Bool ioP96OpenScanPath( pScanData ps ) { if( 0 == ps->IO.bOpenCount ) { /* not established */ ioSwitchToSPPMode( ps ); /* Scanner command sequence to open scanner path */ ioP98001EstablishScannerConnection( ps, 5 ); } #ifdef DEBUG else DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount ); #endif ps->IO.bOpenCount++; /* increment the opened count */ /* * CHECK to we really need that !! */ ps->IO.useEPPCmdMode = _FALSE; return _TRUE; } /** try to connect to scanner */ static Bool ioP98OpenScanPath( pScanData ps ) { Byte tmp; ULong dw; ULong dwTime = 1; if( 0 == ps->IO.bOpenCount ) { /* not established */ ioSwitchToSPPMode( ps ); for( dw = 10; dw; dw-- ) { /* * this seems to be necessary... */ if( _ASIC_IS_98001 == ps->sCaps.AsicID ) { ioP98001EstablishScannerConnection( ps, dw ); #if 0 ioP98001EstablishScannerConnection( ps, dw ); ioP98001EstablishScannerConnection( ps, dw ); #endif } else { ioP98003EstablishScannerConnection( ps, dw ); } _INB_STATUS( ps ); tmp = _INB_STATUS( ps ); if( 0x50 == ( tmp & 0xf0 )) { ps->IO.bOpenCount = 1; if( ps->sCaps.AsicID == IODataFromRegister(ps, ps->RegAsicID)) { return _TRUE; } ps->IO.bOpenCount = 0; } dwTime++; } DBG( DBG_IO, "ioP98OpenScanPath() failed!\n" ); return _FALSE; } #ifdef DEBUG else DBG( DBG_IO, "!!!! Path already open (%u)!!!!\n", ps->IO.bOpenCount ); #endif ps->IO.bOpenCount++; /* increment the opened count */ return _TRUE; } /** Switch back to printer mode. * Restore the printer control/data port value. */ static void ioCloseScanPath( pScanData ps ) { if( ps->IO.bOpenCount && !(--ps->IO.bOpenCount)) { #ifdef DEBUG ps->IO.bOpenCount = 1; #endif IORegisterToScanner( ps, 0xff ); /* * back to pass-through printer mode */ IORegisterToScanner( ps, ps->RegSwitchBus ); #ifdef DEBUG ps->IO.bOpenCount = 0; #endif ps->IO.useEPPCmdMode = _FALSE; ioRestoreParallelMode( ps ); } } /** check the memory to see that the data-transfers will work. * (ASIC 9800x only) */ static int ioP98ReadWriteTest( pScanData ps ) { UChar tmp; ULong ul; pUChar buffer; int retval; DBG( DBG_LOW, "ioP98ReadWriteTest()\n" ); /* _MEMTEST_SIZE: Read, _MEMTEST_SIZE:Write */ buffer = _KALLOC( sizeof(UChar) * _MEMTEST_SIZE*2, GFP_KERNEL ); if( NULL == buffer ) return _E_ALLOC; /* prepare content */ for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) buffer[ul] = (UChar)ul; ps->OpenScanPath(ps); /* avoid switching to Lamp0, when previously scanned in transp./neg mode */ tmp = ps->bLastLampStatus + _SCAN_BYTEMODE; IODataToRegister( ps, ps->RegScanControl, tmp ); IODataToRegister( ps, ps->RegModelControl, (_LED_ACTIVITY | _LED_CONTROL)); IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem ); IODataToRegister( ps, ps->RegMemoryLow, 0 ); IODataToRegister( ps, ps->RegMemoryHigh, 0 ); /* fill to buffer */ IOMoveDataToScanner( ps, buffer, _MEMTEST_SIZE ); IODataToRegister( ps, ps->RegModeControl, _ModeMappingMem ); IODataToRegister( ps, ps->RegMemoryLow, 0 ); IODataToRegister( ps, ps->RegMemoryHigh, 0 ); IODataToRegister( ps, ps->RegWidthPixelsLow, 0 ); IODataToRegister( ps, ps->RegWidthPixelsHigh, 5 ); ps->AsicReg.RD_ModeControl = _ModeReadMappingMem; if( _ASIC_IS_98001 == ps->sCaps.AsicID ) ps->CloseScanPath( ps ); IOReadScannerImageData( ps, buffer + _MEMTEST_SIZE, _MEMTEST_SIZE ); if( _ASIC_IS_98003 == ps->sCaps.AsicID ) ps->CloseScanPath( ps ); /* check the result ! */ retval = _OK; for( ul = 0; ul < _MEMTEST_SIZE; ul++ ) { if( buffer[ul] != buffer[ul+_MEMTEST_SIZE] ) { DBG( DBG_HIGH, "Error in memory test at pos %u (%u != %u)\n", ul, buffer[ul], buffer[ul+_MEMTEST_SIZE] ); retval = _E_NO_DEV; break; } } _KFREE(buffer); return retval; } /** Put data to DATA port and trigger hardware through CONTROL port to read it. */ static void ioSPPWrite( pScanData ps, pUChar pBuffer, ULong size ) { DBG( DBG_IO , "Moving %u bytes to scanner, IODELAY = %u...\n", size, ps->IO.delay ); switch( ps->IO.delay ) { case 0: for (; size; size--, pBuffer++) { _OUTB_DATA( ps, *pBuffer ); _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); } break; case 1: case 2: for (; size; size--, pBuffer++) { _OUTB_DATA( ps, *pBuffer ); _DO_UDELAY( 1 ); _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); _DO_UDELAY( 1 ); _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); _DO_UDELAY( 2 ); } break; default: for (; size; size--, pBuffer++) { _OUTB_DATA( ps, *pBuffer ); _DO_UDELAY( 1 ); _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); _DO_UDELAY( 2 ); _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); _DO_UDELAY( 3 ); } break; } DBG( DBG_IO , "... done.\n" ); } /** set the scanner to "read" data mode */ static void ioEnterReadMode( pScanData ps ) { if( ps->IO.portMode != _PORT_SPP ) { _DO_UDELAY( 1 ); IORegisterToScanner( ps, ps->RegEPPEnable ); if( _IS_ASIC98( ps->sCaps.AsicID )) ps->IO.useEPPCmdMode = _TRUE; } if( _ASIC_IS_98003 == ps->sCaps.AsicID ) ps->IO.bOldControlValue = _INB_CTRL( ps ); /* ask ASIC to enter read mode */ IORegisterToScanner( ps, ps->RegReadDataMode ); } /************************ exported functions *********************************/ /** here we do some init work */ _LOC int IOInitialize( pScanData ps ) { DBG( DBG_HIGH, "IOInitialize()\n" ); if( NULL == ps ) return _E_NULLPTR; if( _IS_ASIC98(ps->sCaps.AsicID)) { ps->OpenScanPath = ioP98OpenScanPath; ps->ReadWriteTest = ioP98ReadWriteTest; } else if( _IS_ASIC96(ps->sCaps.AsicID)) { ps->OpenScanPath = ioP96OpenScanPath; } else { DBG( DBG_HIGH , "NOT SUPPORTED ASIC !!!\n" ); return _E_NOSUPP; } ps->CloseScanPath = ioCloseScanPath; ps->Device.ReadData = ioReadFunc[ps->IO.portMode].func; DBG( DBG_HIGH, "* using readfunction >%s<\n", ioReadFunc[ps->IO.portMode].name ); return _OK; } /** Write specific length buffer to scanner * The scan path is already established */ _LOC void IOMoveDataToScanner( pScanData ps, pUChar pBuffer, ULong size ) { #ifdef DEBUG if( 0 == ps->IO.bOpenCount ) DBG( DBG_IO, "IOMoveDataToScanner - no connection!\n" ); #endif IORegisterToScanner( ps, ps->RegInitDataFifo ); IORegisterToScanner( ps, ps->RegWriteDataMode ); ioSPPWrite( ps, pBuffer, size ); } /** Calling SITUATION: Scanner path is established. * download a scanstate-table */ _LOC void IODownloadScanStates( pScanData ps ) { TimerDef timer; #ifdef DEBUG if( 0 == ps->IO.bOpenCount ) DBG( DBG_IO, "IODownloadScanStates - no connection!\n" ); #endif IORegisterToScanner( ps, ps->RegScanStateControl ); ioSPPWrite( ps, ps->a_nbNewAdrPointer, _SCANSTATE_BYTES ); if( ps->Scan.fRefreshState ) { IORegisterToScanner( ps, ps->RegRefreshScanState ); MiscStartTimer( &timer, (_SECOND/2)); do { if (!( IOGetScanState( ps, _TRUE) & _SCANSTATE_STOP)) break; } while( !MiscCheckTimer(&timer)); } } /** Calling SITUATION: Scanner path is established. * Write a data to asic */ _LOC void IODataToScanner( pScanData ps, Byte bValue ) { ULong deltime = 4; #ifdef DEBUG if( 0 == ps->IO.bOpenCount ) DBG( DBG_IO, "IODataToScanner - no connection!\n" ); #endif if( ps->IO.delay < 2 ) deltime = 2; /* output data */ _OUTB_DATA( ps, bValue ); _DO_UDELAY( deltime ); /* notify asic there is data */ _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); _DO_UDELAY( deltime ); /* end write cycle */ _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); _DO_UDELAY( deltime-1 ); } /** Calling SITUATION: Scanner path is established. * Write a data to specific asic's register */ _LOC void IODataToRegister( pScanData ps, Byte bReg, Byte bData ) { #ifdef DEBUG if( 0 == ps->IO.bOpenCount ) DBG( DBG_IO, "IODataToRegister - no connection!\n" ); #endif /* specify register */ IORegisterToScanner( ps, bReg ); /* then write the content */ IODataToScanner( ps, bData ); } /** Calling SITUATION: Scanner path is established. * Read the content of specific asic's register */ _LOC Byte IODataFromRegister( pScanData ps, Byte bReg ) { IORegisterToScanner( ps, bReg ); if( 0 == ps->IO.delay ) return ioDataFromSPPFast( ps ); else if( 1 == ps->IO.delay ) return ioDataFromSPPMiddle( ps ); else if( 2 == ps->IO.delay ) return ioDataFromSPPSlow( ps ); else return ioDataFromSPPSlowest( ps ); } /** Calling SITUATION: Scanner path is established. * Write a register to asic (used for a command without parameter) */ _LOC void IORegisterToScanner( pScanData ps, Byte bReg ) { #ifdef DEBUG if( 0 == ps->IO.bOpenCount ) DBG( DBG_IO, "IORegisterToScanner - no connection!\n" ); #endif /* * write data to port */ _OUTB_DATA( ps, bReg ); /* * depending on the mode, generate the trigger signals */ if( ps->IO.useEPPCmdMode ) { _DO_UDELAY( 5 ); _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */ _DO_UDELAY( 5 ); _OUTB_CTRL( ps, _CTRL_EPPTRIG_REGWRITE);/* 0xcd */ _DO_UDELAY( 5 ); _OUTB_CTRL( ps, _CTRL_EPPSIGNAL_WRITE); /* 0xc5 */ _DO_UDELAY( 5 ); _OUTB_CTRL( ps, _CTRL_END_REGWRITE); /* 0xc4 */ } else { if( ps->IO.delay < 2 ) { _DO_UDELAY( 1 ); _OUTB_CTRL( ps, _CTRL_START_REGWRITE); _DO_UDELAY( 1 ); _OUTB_CTRL( ps, _CTRL_END_REGWRITE); } else { _DO_UDELAY( 2 ); _OUTB_CTRL( ps, _CTRL_START_REGWRITE); _DO_UDELAY( 2 ); _OUTB_CTRL( ps, _CTRL_END_REGWRITE); _DO_UDELAY( 2 ); } } } /** write data to the DAC - ASIC 98001/3 only */ _LOC void IODataRegisterToDAC( pScanData ps, Byte bReg, Byte bData ) { ULong i; IODataToRegister( ps, ps->RegADCAddress, bReg ); IODataToRegister( ps, ps->RegADCData, bData ); IODataToRegister( ps, ps->RegADCSerialOutStr, bData ); /* TEST: ORG was 1 ms for ASIC 98001 */ _DO_UDELAY( 12 ); for( i = 4; i; i-- ) { _OUTB_CTRL( ps, _CTRL_START_DATAWRITE ); _DO_UDELAY( 5 ); _OUTB_CTRL( ps, _CTRL_END_DATAWRITE ); _DO_UDELAY( 12 ); } } /** Calling SITUATION: Scanner path was not established. * Read the content of specific asics' register */ _LOC Byte IODataRegisterFromScanner( pScanData ps, Byte bReg ) { Byte bData; ps->OpenScanPath( ps ); bData = IODataFromRegister( ps, bReg ); ps->CloseScanPath( ps ); return bData; } /** Calling SITUATION: Scanner path not established. * Write a value of register to asic */ _LOC void IOCmdRegisterToScanner( pScanData ps, Byte bReg, Byte bData ) { ps->OpenScanPath( ps ); IODataToRegister( ps, bReg, bData ); ps->CloseScanPath( ps ); } /** Calling SITUATION: Scanner path not established. * Write a register to asic (used for a command without parameter) */ _LOC void IORegisterDirectToScanner( pScanData ps, Byte bReg ) { ps->OpenScanPath( ps ); /* establish the connection */ IORegisterToScanner( ps, bReg ); /* write register to asic */ ps->CloseScanPath( ps ); /* disconnect */ } /** perform a SW reset of ASIC 98003 models */ _LOC void IOSoftwareReset( pScanData ps ) { if( _ASIC_IS_98003 != ps->sCaps.AsicID ) return; ps->OpenScanPath( ps ); IODataToRegister( ps, ps->RegTestMode, _SW_TESTMODE ); ioSwitchToSPPMode( ps ); _OUTB_DATA( ps, _RESET1ST ); _DODELAY( 5 ); _OUTB_DATA( ps, _RESET2ND ); _DODELAY( 5 ); _OUTB_DATA( ps, _RESET3RD ); _DODELAY( 5 ); _OUTB_DATA( ps, _RESET4TH ); _DODELAY( 5 ); ioRestoreParallelMode( ps ); /* reset test mode register */ IODataToRegister( ps, ps->RegTestMode, 0 ); IODataToRegister( ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl ); ps->CloseScanPath( ps ); } /** Read specific length data from scanner and the method depends on the * mode defined in registry. */ _LOC void IOReadScannerImageData( pScanData ps, pUChar pBuf, ULong size ) { if( _ASIC_IS_98003 != ps->sCaps.AsicID ) ps->OpenScanPath( ps); if( _IS_ASIC98( ps->sCaps.AsicID)) IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl ); /* enter read mode */ ioEnterReadMode( ps ); /* call corresponding read proc */ ps->Device.ReadData( ps, pBuf, size ); /* Clear EPP/ECP read mode by simply close scanner path and re-open it */ ps->CloseScanPath( ps ); if( _ASIC_IS_98003 == ps->sCaps.AsicID ) ps->OpenScanPath( ps ); } #ifdef __KERNEL__ /** the wrapper functions to support delayed and non-delayed I/O */ _LOC void IOOut( Byte data, UShort port ) { DBG( DBG_IOF, "outb(0x%04x, 0x%02x)\n", port, data ); outb( data, port ); } _LOC void IOOutDelayed( Byte data, UShort port ) { DBG( DBG_IOF, "outb_p(0x%04x, 0x%02x)\n", port, data ); outb_p( data, port ); } _LOC Byte IOIn( UShort port ) { #ifdef DEBUG Byte data = inb( port ); DBG( DBG_IOF, "inb(0x%04x) = 0x%02x\n", port, data ); return data; #else return inb( port ); #endif } _LOC Byte IOInDelayed( UShort port ) { #ifdef DEBUG Byte data = inb_p( port ); DBG( DBG_IOF, "inb_p(0x%04x) = 0x%02x\n", port, data ); return data; #else return inb_p( port ); #endif } #endif /* guard __KERNEL__ */ /* END PLUSTEK-PP_IO.C ......................................................*/ sane-backends-1.0.27/backend/pixma_sane_options.c0000664000175000017500000003012413072310420016644 00000000000000/* Automatically generated from pixma_sane.c */ static const SANE_Range constraint_gamma_table = { 0,255,0 }; static const SANE_Range constraint_gamma = { SANE_FIX(0.3),SANE_FIX(5),SANE_FIX(0) }; static const SANE_Range constraint_threshold = { 0,100,1 }; static const SANE_Range constraint_threshold_curve = { 0,127,1 }; static const SANE_Range constraint_adf_wait = { 0,3600,1 }; static int find_string_in_list(SANE_String_Const str, const SANE_String_Const *list) { int i; for (i = 0; list[i] && strcmp(str, list[i]) != 0; i++) {} return i; } static int build_option_descriptors(struct pixma_sane_t *ss) { SANE_Option_Descriptor *sod; option_descriptor_t *opt; memset(OPT_IN_CTX, 0, sizeof(OPT_IN_CTX)); opt = &(OPT_IN_CTX[opt_opt_num_opts]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_TITLE_NUM_OPTIONS; sod->desc = SANE_DESC_NUM_OPTIONS; sod->name = ""; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_DETECT; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_opt_num_opts].info = 0; opt->def.w = opt_last; opt->val.w = opt_last; opt = &(OPT_IN_CTX[opt__group_1]); sod = &opt->sod; sod->type = SANE_TYPE_GROUP; sod->title = SANE_I18N("Scan mode"); sod->desc = sod->title; opt = &(OPT_IN_CTX[opt_resolution]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_TITLE_SCAN_RESOLUTION; sod->desc = SANE_DESC_SCAN_RESOLUTION; sod->name = "resolution"; sod->unit = SANE_UNIT_DPI; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC; sod->constraint_type = SANE_CONSTRAINT_WORD_LIST; sod->constraint.word_list = ss->dpi_list; OPT_IN_CTX[opt_resolution].info = SANE_INFO_RELOAD_PARAMS; opt->def.w = 75; opt->val.w = 75; opt = &(OPT_IN_CTX[opt_mode]); sod = &opt->sod; sod->type = SANE_TYPE_STRING; sod->title = SANE_TITLE_SCAN_MODE; sod->desc = SANE_DESC_SCAN_MODE; sod->name = "mode"; sod->unit = SANE_UNIT_NONE; sod->size = 31; sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC; sod->constraint_type = SANE_CONSTRAINT_STRING_LIST; sod->constraint.string_list = ss->mode_list; OPT_IN_CTX[opt_mode].info = SANE_INFO_RELOAD_PARAMS; opt->def.s = SANE_VALUE_SCAN_MODE_COLOR; opt->val.w = find_string_in_list(opt->def.s, sod->constraint.string_list); opt = &(OPT_IN_CTX[opt_source]); sod = &opt->sod; sod->type = SANE_TYPE_STRING; sod->title = SANE_TITLE_SCAN_SOURCE; sod->desc = SANE_I18N("Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values."); sod->name = "source"; sod->unit = SANE_UNIT_NONE; sod->size = 31; sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; sod->constraint_type = SANE_CONSTRAINT_STRING_LIST; sod->constraint.string_list = ss->source_list; OPT_IN_CTX[opt_source].info = 0; opt->def.s = SANE_I18N("Flatbed"); opt->val.w = find_string_in_list(opt->def.s, sod->constraint.string_list); opt = &(OPT_IN_CTX[opt_button_controlled]); sod = &opt->sod; sod->type = SANE_TYPE_BOOL; sod->title = SANE_I18N("Button-controlled scan"); sod->desc = SANE_I18N("When enabled, scan process will not start immediately. To proceed, press \"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To cancel, press \"GRAY\" button."); sod->name = "button-controlled"; sod->unit = SANE_UNIT_NONE; sod->size = sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_INACTIVE; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_button_controlled].info = 0; opt->def.w = SANE_FALSE; opt->val.w = SANE_FALSE; opt = &(OPT_IN_CTX[opt__group_2]); sod = &opt->sod; sod->type = SANE_TYPE_GROUP; sod->title = SANE_I18N("Gamma"); sod->desc = sod->title; opt = &(OPT_IN_CTX[opt_custom_gamma]); sod = &opt->sod; sod->type = SANE_TYPE_BOOL; sod->title = SANE_TITLE_CUSTOM_GAMMA; sod->desc = SANE_DESC_CUSTOM_GAMMA; sod->name = "custom-gamma"; sod->unit = SANE_UNIT_NONE; sod->size = sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_custom_gamma].info = 0; opt->def.w = SANE_TRUE; opt->val.w = SANE_TRUE; opt = &(OPT_IN_CTX[opt_gamma_table]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_TITLE_GAMMA_VECTOR; sod->desc = SANE_DESC_GAMMA_VECTOR; sod->name = "gamma-table"; sod->unit = SANE_UNIT_NONE; sod->size = 4096 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &constraint_gamma_table; OPT_IN_CTX[opt_gamma_table].info = 0; opt = &(OPT_IN_CTX[opt_gamma]); sod = &opt->sod; sod->type = SANE_TYPE_FIXED; sod->title = SANE_I18N("Gamma function exponent"); sod->desc = SANE_I18N("Changes intensity of midtones"); sod->name = "gamma"; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &constraint_gamma; OPT_IN_CTX[opt_gamma].info = 0; opt->def.w = SANE_FIX(AUTO_GAMMA); opt->val.w = SANE_FIX(AUTO_GAMMA); opt = &(OPT_IN_CTX[opt__group_3]); sod = &opt->sod; sod->type = SANE_TYPE_GROUP; sod->title = SANE_I18N("Geometry"); sod->desc = sod->title; opt = &(OPT_IN_CTX[opt_tl_x]); sod = &opt->sod; sod->type = SANE_TYPE_FIXED; sod->title = SANE_TITLE_SCAN_TL_X; sod->desc = SANE_DESC_SCAN_TL_X; sod->name = "tl-x"; sod->unit = SANE_UNIT_MM; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &ss->xrange; OPT_IN_CTX[opt_tl_x].info = SANE_INFO_RELOAD_PARAMS; opt->def.w = SANE_FIX(0); opt->val.w = SANE_FIX(0); opt = &(OPT_IN_CTX[opt_tl_y]); sod = &opt->sod; sod->type = SANE_TYPE_FIXED; sod->title = SANE_TITLE_SCAN_TL_Y; sod->desc = SANE_DESC_SCAN_TL_Y; sod->name = "tl-y"; sod->unit = SANE_UNIT_MM; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &ss->yrange; OPT_IN_CTX[opt_tl_y].info = SANE_INFO_RELOAD_PARAMS; opt->def.w = SANE_FIX(0); opt->val.w = SANE_FIX(0); opt = &(OPT_IN_CTX[opt_br_x]); sod = &opt->sod; sod->type = SANE_TYPE_FIXED; sod->title = SANE_TITLE_SCAN_BR_X; sod->desc = SANE_DESC_SCAN_BR_X; sod->name = "br-x"; sod->unit = SANE_UNIT_MM; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &ss->xrange; OPT_IN_CTX[opt_br_x].info = SANE_INFO_RELOAD_PARAMS; opt->def.w = sod->constraint.range->max; opt->val.w = sod->constraint.range->max; opt = &(OPT_IN_CTX[opt_br_y]); sod = &opt->sod; sod->type = SANE_TYPE_FIXED; sod->title = SANE_TITLE_SCAN_BR_Y; sod->desc = SANE_DESC_SCAN_BR_Y; sod->name = "br-y"; sod->unit = SANE_UNIT_MM; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &ss->yrange; OPT_IN_CTX[opt_br_y].info = SANE_INFO_RELOAD_PARAMS; opt->def.w = sod->constraint.range->max; opt->val.w = sod->constraint.range->max; opt = &(OPT_IN_CTX[opt__group_4]); sod = &opt->sod; sod->type = SANE_TYPE_GROUP; sod->title = SANE_I18N("Buttons"); sod->desc = sod->title; opt = &(OPT_IN_CTX[opt_button_update]); sod = &opt->sod; sod->type = SANE_TYPE_BUTTON; sod->title = SANE_I18N("Update button state"); sod->desc = sod->title; sod->name = "button-update"; sod->unit = SANE_UNIT_NONE; sod->size = 0; sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_button_update].info = 0; opt = &(OPT_IN_CTX[opt_button_1]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_I18N("Button 1"); sod->desc = sod->title; sod->name = "button-1"; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_button_1].info = 0; opt->def.w = 0; opt->val.w = 0; opt = &(OPT_IN_CTX[opt_button_2]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_I18N("Button 2"); sod->desc = sod->title; sod->name = "button-2"; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_button_2].info = 0; opt->def.w = 0; opt->val.w = 0; opt = &(OPT_IN_CTX[opt_original]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_I18N("Type of original to scan"); sod->desc = sod->title; sod->name = "original"; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_original].info = 0; opt->def.w = 0; opt->val.w = 0; opt = &(OPT_IN_CTX[opt_target]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_I18N("Target operation type"); sod->desc = sod->title; sod->name = "target"; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_target].info = 0; opt->def.w = 0; opt->val.w = 0; opt = &(OPT_IN_CTX[opt_scan_resolution]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_I18N("Scan resolution"); sod->desc = sod->title; sod->name = "scan-resolution"; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED; sod->constraint_type = SANE_CONSTRAINT_NONE; OPT_IN_CTX[opt_scan_resolution].info = 0; opt->def.w = 0; opt->val.w = 0; opt = &(OPT_IN_CTX[opt__group_5]); sod = &opt->sod; sod->type = SANE_TYPE_GROUP; sod->title = SANE_I18N("Extras"); sod->desc = sod->title; opt = &(OPT_IN_CTX[opt_threshold]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_TITLE_THRESHOLD; sod->desc = SANE_DESC_THRESHOLD; sod->name = "threshold"; sod->unit = SANE_UNIT_PERCENT; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &constraint_threshold; OPT_IN_CTX[opt_threshold].info = 0; opt->def.w = 50; opt->val.w = 50; opt = &(OPT_IN_CTX[opt_threshold_curve]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_I18N("Threshold curve"); sod->desc = SANE_I18N("Dynamic threshold curve, from light to dark, normally 50-65"); sod->name = "threshold-curve"; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &constraint_threshold_curve; OPT_IN_CTX[opt_threshold_curve].info = 0; opt = &(OPT_IN_CTX[opt_adf_wait]); sod = &opt->sod; sod->type = SANE_TYPE_INT; sod->title = SANE_I18N("ADF Waiting Time"); sod->desc = SANE_I18N("When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder."); sod->name = "adf-wait"; sod->unit = SANE_UNIT_NONE; sod->size = 1 * sizeof(SANE_Word); sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE; sod->constraint_type = SANE_CONSTRAINT_RANGE; sod->constraint.range = &constraint_adf_wait; OPT_IN_CTX[opt_adf_wait].info = 0; opt->def.w = 0; opt->val.w = 0; return 0; } sane-backends-1.0.27/backend/epsonds.c0000664000175000017500000010434113106201017014422 00000000000000/* * epsonds.c - Epson ESC/I-2 driver. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define EPSONDS_VERSION 1 #define EPSONDS_REVISION 1 #define EPSONDS_BUILD 0 /* debugging levels: * * 32 eds_send * 30 eds_recv * 20 sane_read and related * 18 sane_read and related * 17 setvalue, getvalue, control_option * 16 * 15 esci2_img * 13 image_cb * 12 eds_control * 11 all received params * 10 some received params * 9 * 8 esci2_xxx * 7 open/close/attach * 6 print_params * 5 basic functions * 3 JPEG decompressor * 1 scanner info and capabilities * 0 errors */ #include "sane/config.h" #include #include #include "sane/saneopts.h" #include "sane/sanei_config.h" #include "sane/sanei_tcp.h" #include "sane/sanei_udp.h" #include "epsonds.h" #include "epsonds-usb.h" #include "epsonds-io.h" #include "epsonds-cmd.h" #include "epsonds-ops.h" #include "epsonds-jpeg.h" #include "epsonds-net.h" /* * Definition of the mode_param struct, that is used to * specify the valid parameters for the different scan modes. * * The depth variable gets updated when the bit depth is modified. */ struct mode_param mode_params[] = { {0, 0x00, 0x30, 1}, {0, 0x00, 0x30, 8}, {1, 0x02, 0x00, 8}, {0, 0x00, 0x30, 1} }; static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; static const SANE_String_Const adf_mode_list[] = { SANE_I18N("Simplex"), SANE_I18N("Duplex"), NULL }; /* Define the different scan sources */ #define FBF_STR SANE_I18N("Flatbed") #define ADF_STR SANE_I18N("Automatic Document Feeder") /* order will be fixed: fb, adf, tpu */ SANE_String_Const source_list[] = { NULL, NULL, NULL, NULL }; /* * List of pointers to devices - will be dynamically allocated depending * on the number of devices found. */ static const SANE_Device **devlist; /* Some utility functions */ static size_t max_string_size(const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; i++) { size = strlen(strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } static SANE_Status attach_one_usb(SANE_String_Const devname); static SANE_Status attach_one_net(SANE_String_Const devname); static void print_params(const SANE_Parameters params) { DBG(6, "params.format = %d\n", params.format); DBG(6, "params.last_frame = %d\n", params.last_frame); DBG(6, "params.bytes_per_line = %d\n", params.bytes_per_line); DBG(6, "params.pixels_per_line = %d\n", params.pixels_per_line); DBG(6, "params.lines = %d\n", params.lines); DBG(6, "params.depth = %d\n", params.depth); } static void close_scanner(epsonds_scanner *s) { DBG(7, "%s: fd = %d\n", __func__, s->fd); if (s->fd == -1) goto free; if (s->locked) { DBG(7, " unlocking scanner\n"); esci2_fin(s); } if (s->hw->connection == SANE_EPSONDS_NET) { epsonds_net_unlock(s); sanei_tcp_close(s->fd); } else if (s->hw->connection == SANE_EPSONDS_USB) { sanei_usb_close(s->fd); } free: free(s->front.ring); free(s->back.ring); free(s->line_buffer); free(s); DBG(7, "%s: ZZZ\n", __func__); } static void e2_network_discovery(void) { fd_set rfds; int fd, len; SANE_Status status; char *ip, *query = "EPSONP\x00\xff\x00\x00\x00\x00\x00\x00\x00"; unsigned char buf[76]; struct timeval to; status = sanei_udp_open_broadcast(&fd); if (status != SANE_STATUS_GOOD) return; sanei_udp_write_broadcast(fd, 3289, (unsigned char *) query, 15); DBG(5, "%s, sent discovery packet\n", __func__); to.tv_sec = 1; to.tv_usec = 0; FD_ZERO(&rfds); FD_SET(fd, &rfds); sanei_udp_set_nonblock(fd, SANE_TRUE); while (select(fd + 1, &rfds, NULL, NULL, &to) > 0) { if ((len = sanei_udp_recvfrom(fd, buf, 76, &ip)) == 76) { DBG(5, " response from %s\n", ip); /* minimal check, protocol unknown */ if (strncmp((char *) buf, "EPSON", 5) == 0) attach_one_net(ip); } } DBG(5, "%s, end\n", __func__); sanei_udp_close(fd); } static SANE_Status open_scanner(epsonds_scanner *s) { SANE_Status status = SANE_STATUS_INVAL; DBG(7, "%s: %s\n", __func__, s->hw->sane.name); if (s->fd != -1) { DBG(5, "scanner is already open: fd = %d\n", s->fd); return SANE_STATUS_GOOD; /* no need to open the scanner */ } if (s->hw->connection == SANE_EPSONDS_NET) { unsigned char buf[5]; /* device name has the form net:ipaddr */ status = sanei_tcp_open(&s->hw->sane.name[4], 1865, &s->fd); if (status == SANE_STATUS_GOOD) { ssize_t read; struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); s->netlen = 0; DBG(32, "awaiting welcome message\n"); /* the scanner sends a kind of welcome msg */ // XXX check command type, answer to connect is 0x80 read = eds_recv(s, buf, 3, &status); if (read != 3) { sanei_tcp_close(s->fd); s->fd = -1; return SANE_STATUS_IO_ERROR; } DBG(32, "welcome message received, locking the scanner...\n"); /* lock the scanner for use by sane */ status = epsonds_net_lock(s); if (status != SANE_STATUS_GOOD) { DBG(1, "%s cannot lock scanner: %s\n", s->hw->sane.name, sane_strstatus(status)); sanei_tcp_close(s->fd); s->fd = -1; return status; } DBG(32, "scanner locked\n"); } } else if (s->hw->connection == SANE_EPSONDS_USB) { status = sanei_usb_open(s->hw->sane.name, &s->fd); if (status == SANE_STATUS_GOOD) { sanei_usb_set_timeout(USB_TIMEOUT); sanei_usb_clear_halt(s->fd); } } else { DBG(1, "unknown connection type: %d\n", s->hw->connection); } if (status == SANE_STATUS_ACCESS_DENIED) { DBG(1, "please check that you have permissions on the device.\n"); DBG(1, "if this is a multi-function device with a printer,\n"); DBG(1, "disable any conflicting driver (like usblp).\n"); } if (status != SANE_STATUS_GOOD) DBG(1, "%s open failed: %s\n", s->hw->sane.name, sane_strstatus(status)); else DBG(5, " opened correctly\n"); return status; } static int num_devices; /* number of scanners attached to backend */ static epsonds_device *first_dev; /* first EPSON scanner in list */ static struct epsonds_scanner * scanner_create(struct epsonds_device *dev, SANE_Status *status) { struct epsonds_scanner *s; s = malloc(sizeof(struct epsonds_scanner)); if (s == NULL) { *status = SANE_STATUS_NO_MEM; return NULL; } /* clear verything */ memset(s, 0x00, sizeof(struct epsonds_scanner)); s->fd = -1; s->hw = dev; return s; } static struct epsonds_scanner * device_detect(const char *name, int type, SANE_Status *status) { struct epsonds_scanner *s; struct epsonds_device *dev; DBG(1, "%s, %s, type: %d\n", __func__, name, type); /* try to find the device in our list */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, name) == 0) { DBG(1, " found cached device\n"); // the device might have been just probed, sleep a bit. if (dev->connection == SANE_EPSONDS_NET) { sleep(1); } return scanner_create(dev, status); } } /* not found, create new if valid */ if (type == SANE_EPSONDS_NODEV) { *status = SANE_STATUS_INVAL; return NULL; } /* alloc and clear our device structure */ dev = malloc(sizeof(*dev)); if (!dev) { *status = SANE_STATUS_NO_MEM; return NULL; } memset(dev, 0x00, sizeof(struct epsonds_device)); s = scanner_create(dev, status); if (s == NULL) return NULL; dev->connection = type; dev->model = strdup("(undetermined)"); dev->name = strdup(name); dev->sane.name = dev->name; dev->sane.vendor = "Epson"; dev->sane.model = dev->model; dev->sane.type = "ESC/I-2"; *status = open_scanner(s); if (*status != SANE_STATUS_GOOD) { free(s); return NULL; } eds_dev_init(dev); /* lock scanner */ *status = eds_lock(s); if (*status != SANE_STATUS_GOOD) { goto close; } /* discover capabilities */ *status = esci2_info(s); if (*status != SANE_STATUS_GOOD) goto close; *status = esci2_capa(s); if (*status != SANE_STATUS_GOOD) goto close; *status = esci2_resa(s); if (*status != SANE_STATUS_GOOD) goto close; // assume 1 and 8 bit are always supported eds_add_depth(s->hw, 1); eds_add_depth(s->hw, 8); // setup area according to available options if (s->hw->has_fb) { dev->x_range = &dev->fbf_x_range; dev->y_range = &dev->fbf_y_range; dev->alignment = dev->fbf_alignment; } else if (s->hw->has_adf) { dev->x_range = &dev->adf_x_range; dev->y_range = &dev->adf_y_range; dev->alignment = dev->adf_alignment; } else { DBG(0, "unable to lay on the flatbed or feed the feeder. is that a scanner??\n"); } *status = eds_dev_post_init(dev); if (*status != SANE_STATUS_GOOD) goto close; DBG(1, "scanner model: %s\n", dev->model); /* add this scanner to the device list */ num_devices++; dev->next = first_dev; first_dev = dev; return s; close: DBG(1, " failed\n"); close_scanner(s); return NULL; } static SANE_Status attach(const char *name, int type) { SANE_Status status; epsonds_scanner * s; DBG(7, "%s: devname = %s, type = %d\n", __func__, name, type); s = device_detect(name, type, &status); if (s == NULL) return status; close_scanner(s); return status; } SANE_Status attach_one_usb(const char *dev) { DBG(7, "%s: dev = %s\n", __func__, dev); return attach(dev, SANE_EPSONDS_USB); } static SANE_Status attach_one_net(const char *dev) { char name[39 + 4]; DBG(7, "%s: dev = %s\n", __func__, dev); strcpy(name, "net:"); strcat(name, dev); return attach(name, SANE_EPSONDS_NET); } static SANE_Status attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) { int vendor, product; int len = strlen(line); DBG(7, "%s: len = %d, line = %s\n", __func__, len, line); if (sscanf(line, "usb %i %i", &vendor, &product) == 2) { DBG(7, " user configured device\n"); if (vendor != SANE_EPSONDS_VENDOR_ID) return SANE_STATUS_INVAL; /* this is not an Epson device */ sanei_usb_attach_matching_devices(line, attach_one_usb); } else if (strncmp(line, "usb", 3) == 0 && len == 3) { int i, numIds; DBG(7, " probing usb devices\n"); numIds = epsonds_get_number_of_ids(); for (i = 0; i < numIds; i++) { sanei_usb_find_devices(SANE_EPSONDS_VENDOR_ID, epsonds_usb_product_ids[i], attach_one_usb); } } else if (strncmp(line, "net", 3) == 0) { /* remove the "net" sub string */ const char *name = sanei_config_skip_whitespace(line + 3); if (strncmp(name, "autodiscovery", 13) == 0) e2_network_discovery(); else attach_one_net(name); } else { DBG(0, "unable to parse config line: %s\n", line); } return SANE_STATUS_GOOD; } static void free_devices(void) { epsonds_device *dev, *next; for (dev = first_dev; dev; dev = next) { next = dev->next; free(dev->name); free(dev->model); free(dev); } free(devlist); first_dev = NULL; } static void probe_devices(void) { DBG(5, "%s\n", __func__); free_devices(); sanei_configure_attach(EPSONDS_CONFIG_FILE, NULL, attach_one_config); } /**** SANE API ****/ SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) { DBG_INIT(); DBG(2, "%s: " PACKAGE " " VERSION "\n", __func__); DBG(1, "epsonds backend, version %i.%i.%i\n", EPSONDS_VERSION, EPSONDS_REVISION, EPSONDS_BUILD); if (version_code != NULL) *version_code = SANE_VERSION_CODE(SANE_CURRENT_MAJOR, V_MINOR, EPSONDS_BUILD); sanei_usb_init(); return SANE_STATUS_GOOD; } void sane_exit(void) { DBG(5, "** %s\n", __func__); free_devices(); } SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool __sane_unused__ local_only) { int i; epsonds_device *dev; DBG(5, "** %s\n", __func__); probe_devices(); devlist = malloc((num_devices + 1) * sizeof(devlist[0])); if (!devlist) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } DBG(5, "%s - results:\n", __func__); for (i = 0, dev = first_dev; i < num_devices && dev; dev = dev->next, i++) { DBG(1, " %d (%d): %s\n", i, dev->connection, dev->model); devlist[i] = &dev->sane; } devlist[i] = NULL; *device_list = devlist; return SANE_STATUS_GOOD; } static SANE_Status init_options(epsonds_scanner *s) { int i; for (i = 0; i < NUM_OPTIONS; i++) { s->opt[i].size = sizeof(SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Scan Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size(mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].w = 0; /* Lineart */ /* bit depth */ s->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH; s->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH; s->opt[OPT_DEPTH].desc = SANE_DESC_BIT_DEPTH; s->opt[OPT_DEPTH].type = SANE_TYPE_INT; s->opt[OPT_DEPTH].unit = SANE_UNIT_BIT; s->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_DEPTH].constraint.word_list = s->hw->depth_list; s->val[OPT_DEPTH].w = s->hw->depth_list[1]; /* the first "real" element is the default */ /* default is Lineart, disable depth selection */ s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; /* range */ if (s->hw->dpi_range.quant) { s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; } else { /* list */ s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; s->opt[OPT_RESOLUTION].constraint.word_list = s->hw->res_list; s->val[OPT_RESOLUTION].w = s->hw->res_list[1]; } /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range->max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range->max; /* "Optional equipment" group: */ s->opt[OPT_EQU_GROUP].title = SANE_I18N("Optional equipment"); s->opt[OPT_EQU_GROUP].desc = ""; s->opt[OPT_EQU_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_EQU_GROUP].cap = SANE_CAP_ADVANCED; /* source */ s->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; s->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; s->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; s->opt[OPT_SOURCE].type = SANE_TYPE_STRING; s->opt[OPT_SOURCE].size = max_string_size(source_list); s->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_SOURCE].constraint.string_list = source_list; s->val[OPT_SOURCE].w = 0; s->opt[OPT_EJECT].name = "eject"; s->opt[OPT_EJECT].title = SANE_I18N("Eject"); s->opt[OPT_EJECT].desc = SANE_I18N("Eject the sheet in the ADF"); s->opt[OPT_EJECT].type = SANE_TYPE_BUTTON; if (!s->hw->adf_has_eject) s->opt[OPT_EJECT].cap |= SANE_CAP_INACTIVE; s->opt[OPT_LOAD].name = "load"; s->opt[OPT_LOAD].title = SANE_I18N("Load"); s->opt[OPT_LOAD].desc = SANE_I18N("Load a sheet in the ADF"); s->opt[OPT_LOAD].type = SANE_TYPE_BUTTON; if (!s->hw->adf_has_load) s->opt[OPT_LOAD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ADF_MODE].name = "adf-mode"; s->opt[OPT_ADF_MODE].title = SANE_I18N("ADF Mode"); s->opt[OPT_ADF_MODE].desc = SANE_I18N("Selects the ADF mode (simplex/duplex)"); s->opt[OPT_ADF_MODE].type = SANE_TYPE_STRING; s->opt[OPT_ADF_MODE].size = max_string_size(adf_mode_list); s->opt[OPT_ADF_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_ADF_MODE].constraint.string_list = adf_mode_list; s->val[OPT_ADF_MODE].w = 0; /* simplex */ if (!s->hw->adf_is_duplex) s->opt[OPT_ADF_MODE].cap |= SANE_CAP_INACTIVE; s->opt[OPT_ADF_SKEW].name = "adf-skew"; s->opt[OPT_ADF_SKEW].title = SANE_I18N("ADF Skew Correction"); s->opt[OPT_ADF_SKEW].desc = SANE_I18N("Enables ADF skew correction"); s->opt[OPT_ADF_SKEW].type = SANE_TYPE_BOOL; s->val[OPT_ADF_SKEW].w = 0; if (!s->hw->adf_has_skew) s->opt[OPT_ADF_SKEW].cap |= SANE_CAP_INACTIVE; return SANE_STATUS_GOOD; } SANE_Status sane_open(SANE_String_Const name, SANE_Handle *handle) { SANE_Status status; epsonds_scanner *s = NULL; DBG(7, "** %s: name = '%s'\n", __func__, name); /* probe if empty device name provided */ if (name[0] == '\0') { probe_devices(); if (first_dev == NULL) { DBG(1, "no devices detected\n"); return SANE_STATUS_INVAL; } s = device_detect(first_dev->sane.name, first_dev->connection, &status); if (s == NULL) { DBG(1, "cannot open a perfectly valid device (%s)," " please report to the authors\n", name); return SANE_STATUS_INVAL; } } else { if (strncmp(name, "net:", 4) == 0) { s = device_detect(name, SANE_EPSONDS_NET, &status); if (s == NULL) return status; } else if (strncmp(name, "libusb:", 7) == 0) { s = device_detect(name, SANE_EPSONDS_USB, &status); if (s == NULL) return status; } else { DBG(1, "invalid device name: %s\n", name); return SANE_STATUS_INVAL; } } /* s is always valid here */ DBG(5, "%s: handle obtained\n", __func__); init_options(s); *handle = (SANE_Handle)s; status = open_scanner(s); if (status != SANE_STATUS_GOOD) { free(s); return status; } /* lock scanner if required */ if (!s->locked) { status = eds_lock(s); } return status; } void sane_close(SANE_Handle handle) { epsonds_scanner *s = (epsonds_scanner *)handle; DBG(1, "** %s\n", __func__); close_scanner(s); } const SANE_Option_Descriptor * sane_get_option_descriptor(SANE_Handle handle, SANE_Int option) { epsonds_scanner *s = (epsonds_scanner *) handle; if (option < 0 || option >= NUM_OPTIONS) return NULL; return s->opt + option; } static const SANE_String_Const * search_string_list(const SANE_String_Const *list, SANE_String value) { while (*list != NULL && strcmp(value, *list) != 0) list++; return ((*list == NULL) ? NULL : list); } static void activateOption(epsonds_scanner *s, SANE_Int option, SANE_Bool *change) { if (!SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { s->opt[option].cap &= ~SANE_CAP_INACTIVE; *change = SANE_TRUE; } } static void deactivateOption(epsonds_scanner *s, SANE_Int option, SANE_Bool *change) { if (SANE_OPTION_IS_ACTIVE(s->opt[option].cap)) { s->opt[option].cap |= SANE_CAP_INACTIVE; *change = SANE_TRUE; } } /* * Handles setting the source (flatbed, transparency adapter (TPU), * or auto document feeder (ADF)). * * For newer scanners it also sets the focus according to the * glass / TPU settings. */ static void change_source(epsonds_scanner *s, SANE_Int optindex, char *value) { int force_max = SANE_FALSE; SANE_Bool dummy; DBG(1, "%s: optindex = %d, source = '%s'\n", __func__, optindex, value); s->val[OPT_SOURCE].w = optindex; /* if current selected area is the maximum available, * keep this setting on the new source. */ if (s->val[OPT_TL_X].w == s->hw->x_range->min && s->val[OPT_TL_Y].w == s->hw->y_range->min && s->val[OPT_BR_X].w == s->hw->x_range->max && s->val[OPT_BR_Y].w == s->hw->y_range->max) { force_max = SANE_TRUE; } if (strcmp(ADF_STR, value) == 0) { s->hw->x_range = &s->hw->adf_x_range; s->hw->y_range = &s->hw->adf_y_range; s->hw->alignment = s->hw->adf_alignment; if (s->hw->adf_is_duplex) { activateOption(s, OPT_ADF_MODE, &dummy); } else { deactivateOption(s, OPT_ADF_MODE, &dummy); s->val[OPT_ADF_MODE].w = 0; } } else if (strcmp(TPU_STR, value) == 0) { s->hw->x_range = &s->hw->tpu_x_range; s->hw->y_range = &s->hw->tpu_y_range; deactivateOption(s, OPT_ADF_MODE, &dummy); } else { /* neither ADF nor TPU active, assume FB */ s->hw->x_range = &s->hw->fbf_x_range; s->hw->y_range = &s->hw->fbf_y_range; s->hw->alignment = s->hw->fbf_alignment; } s->opt[OPT_BR_X].constraint.range = s->hw->x_range; s->opt[OPT_BR_Y].constraint.range = s->hw->y_range; if (s->val[OPT_TL_X].w < s->hw->x_range->min || force_max) s->val[OPT_TL_X].w = s->hw->x_range->min; if (s->val[OPT_TL_Y].w < s->hw->y_range->min || force_max) s->val[OPT_TL_Y].w = s->hw->y_range->min; if (s->val[OPT_BR_X].w > s->hw->x_range->max || force_max) s->val[OPT_BR_X].w = s->hw->x_range->max; if (s->val[OPT_BR_Y].w > s->hw->y_range->max || force_max) s->val[OPT_BR_Y].w = s->hw->y_range->max; } static SANE_Status getvalue(SANE_Handle handle, SANE_Int option, void *value) { epsonds_scanner *s = (epsonds_scanner *)handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); DBG(17, "%s: option = %d\n", __func__, option); switch (option) { case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_DEPTH: case OPT_ADF_SKEW: *((SANE_Word *) value) = sval->w; break; case OPT_MODE: case OPT_ADF_MODE: case OPT_SOURCE: strcpy((char *) value, sopt->constraint.string_list[sval->w]); break; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; } static SANE_Status setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info) { epsonds_scanner *s = (epsonds_scanner *) handle; SANE_Option_Descriptor *sopt = &(s->opt[option]); Option_Value *sval = &(s->val[option]); SANE_Status status; const SANE_String_Const *optval = NULL; int optindex = 0; SANE_Bool reload = SANE_FALSE; DBG(17, "** %s: option = %d, value = %p\n", __func__, option, value); status = sanei_constrain_value(sopt, value, info); if (status != SANE_STATUS_GOOD) return status; if (info && value && (*info & SANE_INFO_INEXACT) && sopt->type == SANE_TYPE_INT) DBG(17, " constrained val = %d\n", *(SANE_Word *) value); if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST) { optval = search_string_list(sopt->constraint.string_list, (char *) value); if (optval == NULL) return SANE_STATUS_INVAL; optindex = optval - sopt->constraint.string_list; } /* block faulty frontends */ if (sopt->cap & SANE_CAP_INACTIVE) { DBG(1, " tried to modify a disabled parameter"); return SANE_STATUS_INVAL; } switch (option) { case OPT_ADF_MODE: /* simple lists */ sval->w = optindex; break; case OPT_ADF_SKEW: case OPT_RESOLUTION: sval->w = *((SANE_Word *) value); reload = SANE_TRUE; break; case OPT_BR_X: case OPT_BR_Y: sval->w = *((SANE_Word *) value); if (SANE_UNFIX(sval->w) == 0) { DBG(17, " invalid br-x or br-y\n"); return SANE_STATUS_INVAL; } /* passthru */ case OPT_TL_X: case OPT_TL_Y: sval->w = *((SANE_Word *) value); if (NULL != info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_SOURCE: change_source(s, optindex, (char *) value); reload = SANE_TRUE; break; case OPT_MODE: { /* use JPEG mode if RAW is not available when bpp > 1 */ if (optindex > 0 && !s->hw->has_raw) { s->mode_jpeg = 1; } else { s->mode_jpeg = 0; } sval->w = optindex; /* if binary, then disable the bit depth selection */ if (optindex == 0) { s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; } else { if (s->hw->depth_list[0] == 1) s->opt[OPT_DEPTH].cap |= SANE_CAP_INACTIVE; else { s->opt[OPT_DEPTH].cap &= ~SANE_CAP_INACTIVE; s->val[OPT_DEPTH].w = mode_params[optindex].depth; } } reload = SANE_TRUE; break; } case OPT_DEPTH: sval->w = *((SANE_Word *) value); mode_params[s->val[OPT_MODE].w].depth = sval->w; reload = SANE_TRUE; break; case OPT_LOAD: esci2_mech(s, "#ADFLOAD"); break; case OPT_EJECT: esci2_mech(s, "#ADFEJCT"); break; default: return SANE_STATUS_INVAL; } if (reload && info != NULL) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; } SANE_Status sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info) { DBG(17, "** %s: action = %x, option = %d\n", __func__, action, option); if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_INVAL; if (info != NULL) *info = 0; switch (action) { case SANE_ACTION_GET_VALUE: return getvalue(handle, option, value); case SANE_ACTION_SET_VALUE: return setvalue(handle, option, value, info); default: return SANE_STATUS_INVAL; } return SANE_STATUS_INVAL; } SANE_Status sane_get_parameters(SANE_Handle handle, SANE_Parameters *params) { epsonds_scanner *s = (epsonds_scanner *)handle; DBG(5, "** %s\n", __func__); if (params == NULL) DBG(1, "%s: params is NULL\n", __func__); /* * If sane_start was already called, then just retrieve the parameters * from the scanner data structure */ if (s->scanning) { DBG(5, "scan in progress, returning saved params structure\n"); } else { /* otherwise initialize the params structure */ eds_init_parameters(s); } if (params != NULL) *params = s->params; print_params(s->params); return SANE_STATUS_GOOD; } /* * This function is part of the SANE API and gets called from the front end to * start the scan process. */ SANE_Status sane_start(SANE_Handle handle) { epsonds_scanner *s = (epsonds_scanner *)handle; char buf[65]; /* add one more byte to correct buffer overflow issue */ char cmd[100]; /* take care not to overflow */ SANE_Status status = 0; s->pages++; DBG(5, "** %s, pages = %d, scanning = %d, backside = %d, front fill: %d, back fill: %d\n", __func__, s->pages, s->scanning, s->backside, eds_ring_avail(&s->front), eds_ring_avail(&s->back)); s->eof = 0; s->canceling = 0; if ((s->pages % 2) == 1) { s->current = &s->front; eds_ring_flush(s->current); } else if (eds_ring_avail(&s->back)) { DBG(5, "back side\n"); s->current = &s->back; } /* prepare the JPEG decompressor */ if (s->mode_jpeg) { status = eds_jpeg_start(s); if (status != SANE_STATUS_GOOD) { goto end; } } /* scan already in progress? (one pass adf) */ if (s->scanning) { DBG(5, " scan in progress, returning early\n"); return SANE_STATUS_GOOD; } /* calc scanning parameters */ status = eds_init_parameters(s); if (status != SANE_STATUS_GOOD) { DBG(1, " parameters initialization failed\n"); return status; } /* allocate line buffer */ s->line_buffer = realloc(s->line_buffer, s->params.bytes_per_line); if (s->line_buffer == NULL) return SANE_STATUS_NO_MEM; /* ring buffer for front page, twice bsz */ /* XXX read value from scanner */ status = eds_ring_init(&s->front, (65536 * 4) * 2); if (status != SANE_STATUS_GOOD) { return status; } /* transfer buffer, bsz */ /* XXX read value from scanner */ s->buf = realloc(s->buf, 65536 * 4); if (s->buf == NULL) return SANE_STATUS_NO_MEM; print_params(s->params); /* set scanning parameters */ /* document source */ if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { sprintf(buf, "#ADF%s%s", s->val[OPT_ADF_MODE].w ? "DPLX" : "", s->val[OPT_ADF_SKEW].w ? "SKEW" : ""); /* it seems that DFL only works in duplex mode, but it's * also required to be enabled or duplex will be rejected. */ if (s->val[OPT_ADF_MODE].w) { if (s->hw->adf_has_dfd == 2) { strcat(buf, "DFL2"); } else if (s->hw->adf_has_dfd == 1) { strcat(buf, "DFL1"); } } } else if (strcmp(source_list[s->val[OPT_SOURCE].w], FBF_STR) == 0) { strcpy(buf, "#FB "); } else { /* XXX */ } strcpy(cmd, buf); if (s->params.format == SANE_FRAME_GRAY) { sprintf(buf, "#COLM%03d", s->params.depth); } else if (s->params.format == SANE_FRAME_RGB) { sprintf(buf, "#COLC%03d", s->params.depth * 3); } strcat(cmd, buf); /* image transfer format */ if (!s->mode_jpeg) { if (s->params.depth > 1 || s->hw->has_raw) { strcat(cmd, "#FMTRAW "); } } else { strcat(cmd, "#FMTJPG #JPGd090"); } /* resolution (RSMi not always supported) */ if (s->val[OPT_RESOLUTION].w > 999) { sprintf(buf, "#RSMi%07d#RSSi%07d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w); } else { sprintf(buf, "#RSMd%03d#RSSd%03d", s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w); } strcat(cmd, buf); /* scanning area */ sprintf(buf, "#ACQi%07di%07di%07di%07d", s->left, s->top, s->params.pixels_per_line, s->params.lines); strcat(cmd, buf); status = esci2_para(s, cmd); if (status != SANE_STATUS_GOOD) { goto end; } /* start scanning */ DBG(1, "%s: scanning...\n", __func__); /* switch to data state */ status = esci2_trdt(s); if (status != SANE_STATUS_GOOD) { goto end; } /* first page is page 1 */ s->pages = 1; s->scanning = 1; end: if (status != SANE_STATUS_GOOD) { DBG(1, "%s: start failed: %s\n", __func__, sane_strstatus(status)); } return status; } /* this moves data from our buffers to SANE */ SANE_Status sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length, SANE_Int *length) { SANE_Int read = 0, tries = 3; SANE_Int available; SANE_Status status = 0; epsonds_scanner *s = (epsonds_scanner *)handle; *length = read = 0; DBG(20, "** %s: backside = %d\n", __func__, s->backside); /* sane_read called before sane_start? */ if (s->current == NULL) { DBG(0, "%s: buffer is NULL", __func__); return SANE_STATUS_INVAL; } /* anything in the buffer? pass it to the frontend */ available = eds_ring_avail(s->current); if (available) { DBG(18, "reading from ring buffer, %d left\n", available); if (s->mode_jpeg && !s->jpeg_header_seen) { status = eds_jpeg_read_header(s); if (status != SANE_STATUS_GOOD && --tries) { goto read_again; } } if (s->mode_jpeg) { eds_jpeg_read(handle, data, max_length, &read); } else { eds_copy_image_from_ring(s, data, max_length, &read); } if (read == 0) { goto read_again; } *length = read; return SANE_STATUS_GOOD; } else if (s->current == &s->back) { /* finished reading the back page, next * command should give us the EOF */ DBG(18, "back side ring buffer empty\n"); } /* read until data or error */ read_again: status = esci2_img(s, &read); if (status != SANE_STATUS_GOOD) { DBG(20, "read: %d, eof: %d, backside: %d, status: %d\n", read, s->eof, s->backside, status); } /* just got a back side page, alloc ring buffer if necessary * we didn't before because dummy was not known */ if (s->backside) { int required = s->params.lines * (s->params.bytes_per_line + s->dummy); if (s->back.size < required) { DBG(20, "allocating buffer for the back side\n"); status = eds_ring_init(&s->back, required); if (status != SANE_STATUS_GOOD) { return status; } } } /* abort scanning when appropriate */ if (status == SANE_STATUS_CANCELLED) { esci2_can(s); return status; } if (s->eof && s->backside) { DBG(18, "back side scan finished\n"); } /* read again if no error and no data */ if (read == 0 && status == SANE_STATUS_GOOD) { goto read_again; } /* got something, write to ring */ if (read) { DBG(20, " %d bytes read, %d lines, eof: %d, canceling: %d, status: %d, backside: %d\n", read, read / (s->params.bytes_per_line + s->dummy), s->canceling, s->eof, status, s->backside); /* move data to the appropriate ring */ status = eds_ring_write(s->backside ? &s->back : &s->front, s->buf, read); if (0 && s->mode_jpeg && !s->jpeg_header_seen && status == SANE_STATUS_GOOD) { status = eds_jpeg_read_header(s); if (status != SANE_STATUS_GOOD && --tries) { goto read_again; } } } /* continue reading if appropriate */ if (status == SANE_STATUS_GOOD) return status; /* cleanup */ DBG(5, "** %s: cleaning up\n", __func__); if (s->mode_jpeg) { eds_jpeg_finish(s); } eds_ring_flush(s->current); return status; } /* * void sane_cancel(SANE_Handle handle) * * Set the cancel flag to true. The next time the backend requests data * from the scanner the CAN message will be sent. */ void sane_cancel(SANE_Handle handle) { DBG(1, "** %s\n", __func__); ((epsonds_scanner *)handle)->canceling = SANE_TRUE; } /* * SANE_Status sane_set_io_mode() * * not supported - for asynchronous I/O */ SANE_Status sane_set_io_mode(SANE_Handle __sane_unused__ handle, SANE_Bool __sane_unused__ non_blocking) { return SANE_STATUS_UNSUPPORTED; } /* * SANE_Status sane_get_select_fd() * * not supported - for asynchronous I/O */ SANE_Status sane_get_select_fd(SANE_Handle __sane_unused__ handle, SANE_Int __sane_unused__ *fd) { return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/hp5400.c0000664000175000017500000000555312775312261013713 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Martijn van Oosterhout Copyright (C) 2003 Thomas Soumarmon This file was initially copied from the hp3300 testools and adjusted to suit. Original copyright notice follows: Copyright (C) 2001 Bertrik Sikken (bertrik@zonnet.nl) This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* SANE interface for hp54xx scanners. Prototype. Parts of this source were inspired by other backends. */ #include "../include/sane/config.h" #include "hp5400_debug.h" #include "hp5400.h" #include "../include/sane/config.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" #include "../include/sane/saneopts.h" #include /* malloc, free */ #include /* memcpy */ #include #ifdef HAVE_SYS_TYPES_H #include #endif #define HP5400_CONFIG_FILE "hp5400.conf" #define BUILD 3 /* (source) includes for data transfer methods */ #include "hp5400_debug.c" #include "hp5400_internal.c" #include "hp5400_sane.c" #include "hp5400_sanei.c" sane-backends-1.0.27/backend/microtek.c0000664000175000017500000042367612775312261014622 00000000000000/*************************************************************************** * SANE - Scanner Access Now Easy. microtek.c This file Copyright 2002 Matthew Marjanovic This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. *************************************************************************** This file implements a SANE backend for Microtek scanners. (feedback to: mtek-bugs@mir.com) (for latest info: http://www.mir.com/mtek/) ***************************************************************************/ #define MICROTEK_MAJOR 0 #define MICROTEK_MINOR 13 #define MICROTEK_PATCH 1 #include "../include/sane/config.h" #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/saneopts.h" #define BACKEND_NAME microtek #include "../include/sane/sanei_backend.h" #include "microtek.h" #define MICROTEK_CONFIG_FILE "microtek.conf" #ifndef PATH_MAX # define PATH_MAX 1024 #endif #define SCSI_BUFF_SIZE sanei_scsi_max_request_size #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) static int num_devices = 0; static Microtek_Device *first_dev = NULL; /* list of known devices */ static Microtek_Scanner *first_handle = NULL; /* list of open scanners */ static const SANE_Device **devlist = NULL; /* sane_get_devices() */ static SANE_Bool inhibit_clever_precal = SANE_FALSE; static SANE_Bool inhibit_real_calib = SANE_FALSE; #define M_GSS_WAIT 5 /* seconds */ #define M_LINEART SANE_VALUE_SCAN_MODE_LINEART #define M_HALFTONE SANE_VALUE_SCAN_MODE_HALFTONE #define M_GRAY SANE_VALUE_SCAN_MODE_GRAY #define M_COLOR SANE_VALUE_SCAN_MODE_COLOR #define M_OPAQUE "Opaque/Normal" #define M_TRANS "Transparency" #define M_AUTOFEED "AutoFeeder" #define M_NONE "None" #define M_SCALAR "Scalar" #define M_TABLE "Table" static SANE_String_Const gamma_mode_list[4] = { M_NONE, M_SCALAR, M_TABLE, NULL }; /* These are for the E6. Does this hold for other models? */ static SANE_String_Const halftone_mode_list[13] = { " 1 53-dot screen (53 gray levels)", " 2 Horiz. screen (65 gray levels)", " 3 Vert. screen (65 gray levels)", " 4 Mixed page (33 gray levels)", " 5 71-dot screen (29 gray levels)", " 6 60-dot #1 (26 gray levels)", " 7 60-dot #2 (26 gray levels)", " 8 Fine detail #1 (17 gray levels)", " 9 Fine detail #2 (17 gray levels)", "10 Slant line (17 gray levels)", "11 Posterizing (10 gray levels)", "12 High Contrast (5 gray levels)", NULL }; static SANE_Range speed_range = {1, 7, 1}; static SANE_Range brightness_range = {-100, 100, 1}; /*static SANE_Range brightness_range = {0, 255, 1};*/ /*static SANE_Range exposure_range = {-18, 21, 3};*/ /*static SANE_Range contrast_range = {-42, 49, 7};*/ static SANE_Range u8_range = {0, 255, 1}; static SANE_Range analog_gamma_range = { SANE_FIX(0.1), SANE_FIX(4.0), SANE_FIX(0) }; #define MAX_MDBG_LENGTH 1024 static char _mdebug_string[MAX_MDBG_LENGTH]; static void MDBG_INIT(const char *format, ...) { va_list ap; va_start(ap, format); vsnprintf(_mdebug_string, MAX_MDBG_LENGTH, format, ap); va_end(ap); } static void MDBG_ADD(const char *format, ...) { int len = strlen(_mdebug_string); va_list ap; va_start(ap, format); vsnprintf(_mdebug_string+len, MAX_MDBG_LENGTH-len, format, ap); va_end(ap); } static void MDBG_FINISH(int dbglvl) { DBG(dbglvl, "%s\n", _mdebug_string); } /********************************************************************/ /********************************************************************/ /*** Utility Functions **********************************************/ /********************************************************************/ /********************************************************************/ static size_t max_string_size (const SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen(strings[i]) + 1; if (size > max_size) max_size = size; } return max_size; } /********************************************************************/ /* Allocate/create a new ring buffer */ /********************************************************************/ static ring_buffer * ring_alloc (size_t initial_size, size_t bpl, size_t ppl) { ring_buffer *rb; uint8_t *buff; if ((rb = (ring_buffer *)malloc(sizeof(*rb))) == NULL) return NULL; if ((buff = (uint8_t *)malloc(initial_size * sizeof(*buff))) == NULL) { free(rb); return NULL; } rb->base = buff; rb->size = initial_size; rb->initial_size = initial_size; rb->bpl = bpl; rb->ppl = ppl; rb->tail_red = 0; rb->tail_green = 1; rb->tail_blue = 2; rb->head_complete = 0; rb->red_extra = 0; rb->green_extra = 0; rb->blue_extra = 0; rb->complete_count = 0; return rb; } /********************************************************************/ /* Enlarge an existing ring buffer */ /********************************************************************/ static SANE_Status ring_expand (ring_buffer *rb, size_t amount) { uint8_t *buff; size_t oldsize; if (rb == NULL) return SANE_STATUS_INVAL; buff = (uint8_t *)realloc(rb->base, (rb->size + amount) * sizeof(*buff)); if (buff == NULL) return SANE_STATUS_NO_MEM; rb->base = buff; oldsize = rb->size; rb->size += amount; DBG(23, "ring_expand: old, new, inc size: %lu, %lu, %lu\n", (u_long)oldsize, (u_long)rb->size, (u_long)amount); DBG(23, "ring_expand: old tr: %lu tg: %lu tb: %lu hc: %lu\n", (u_long)rb->tail_red, (u_long)rb->tail_green, (u_long)rb->tail_blue, (u_long)rb->head_complete); /* if necessary, move data and fix up them pointers */ /* (will break subtly if ring is filled with G or B bytes, and tail_g or tail_b have rolled over...) */ if (((rb->complete_count) || (rb->red_extra) || (rb->green_extra) || (rb->blue_extra)) && ((rb->tail_red <= rb->head_complete) || (rb->tail_green <= rb->head_complete) || (rb->tail_blue <= rb->head_complete))) { memmove(rb->base + rb->head_complete + amount, rb->base + rb->head_complete, oldsize - rb->head_complete); if ((rb->tail_red > rb->head_complete) || ((rb->tail_red == rb->head_complete) && !(rb->complete_count) && !(rb->red_extra))) rb->tail_red += amount; if ((rb->tail_green > rb->head_complete) || ((rb->tail_green == rb->head_complete) && !(rb->complete_count) && !(rb->green_extra))) rb->tail_green += amount; if ((rb->tail_blue > rb->head_complete) || ((rb->tail_blue == rb->head_complete) && !(rb->complete_count) && !(rb->blue_extra))) rb->tail_blue += amount; rb->head_complete += amount; } DBG(23, "ring_expand: new tr: %lu tg: %lu tb: %lu hc: %lu\n", (u_long)rb->tail_red, (u_long)rb->tail_green, (u_long)rb->tail_blue, (u_long)rb->head_complete); return SANE_STATUS_GOOD; } /********************************************************************/ /* Deallocate a ring buffer */ /********************************************************************/ static void ring_free (ring_buffer *rb) { free(rb->base); free(rb); } /********************************************************************/ /********************************************************************/ /*** Basic SCSI Commands ********************************************/ /********************************************************************/ /********************************************************************/ /********************************************************************/ /* parse sense from scsi error */ /* (even though microtek sense codes are non-standard and */ /* typically misinterpreted/munged by the low-level scsi driver) */ /********************************************************************/ static SANE_Status sense_handler (int scsi_fd, u_char *sense, void *arg) { int *sense_flags = (int *)arg; SANE_Status stat; DBG(10, "SENSE! fd = %d\n", scsi_fd); DBG(10, "sense = %02x %02x %02x %02x.\n", sense[0], sense[1], sense[2], sense[3]); switch(sense[0]) { case 0x00: return SANE_STATUS_GOOD; case 0x81: /* COMMAND/DATA ERROR */ stat = SANE_STATUS_GOOD; if (sense[1] & 0x01) { if ((sense_flags != NULL) && (*sense_flags & MS_SENSE_IGNORE)) DBG(10, "sense: ERR_SCSICMD -- ignored\n"); else { DBG(10, "sense: ERR_SCSICMD\n"); stat = SANE_STATUS_IO_ERROR; } } if (sense[1] & 0x02) { DBG(10, "sense: ERR_TOOMANY\n"); stat = SANE_STATUS_IO_ERROR; } return stat; case 0x82 : /* SCANNER HARDWARE ERROR */ if (sense[1] & 0x01) DBG(10, "sense: ERR_CPURAMFAIL\n"); if (sense[1] & 0x02) DBG(10, "sense: ERR_SYSRAMFAIL\n"); if (sense[1] & 0x04) DBG(10, "sense: ERR_IMGRAMFAIL\n"); if (sense[1] & 0x10) DBG(10, "sense: ERR_CALIBRATE\n"); if (sense[1] & 0x20) DBG(10, "sense: ERR_LAMPFAIL\n"); if (sense[1] & 0x40) DBG(10, "sense: ERR_MOTORFAIL\n"); if (sense[1] & 0x80) DBG(10, "sense: ERR_FEEDERFAIL\n"); if (sense[2] & 0x01) DBG(10, "sense: ERR_POWERFAIL\n"); if (sense[2] & 0x02) DBG(10, "sense: ERR_ILAMPFAIL\n"); if (sense[2] & 0x04) DBG(10, "sense: ERR_IMOTORFAIL\n"); if (sense[2] & 0x08) DBG(10, "sense: ERR_PAPERFAIL\n"); if (sense[2] & 0x10) DBG(10, "sense: ERR_FILTERFAIL\n"); return SANE_STATUS_IO_ERROR; case 0x83 : /* OPERATION ERROR */ if (sense[1] & 0x01) DBG(10, "sense: ERR_ILLGRAIN\n"); if (sense[1] & 0x02) DBG(10, "sense: ERR_ILLRES\n"); if (sense[1] & 0x04) DBG(10, "sense: ERR_ILLCOORD\n"); if (sense[1] & 0x10) DBG(10, "sense: ERR_ILLCNTR\n"); if (sense[1] & 0x20) DBG(10, "sense: ERR_ILLLENGTH\n"); if (sense[1] & 0x40) DBG(10, "sense: ERR_ILLADJUST\n"); if (sense[1] & 0x80) DBG(10, "sense: ERR_ILLEXPOSE\n"); if (sense[2] & 0x01) DBG(10, "sense: ERR_ILLFILTER\n"); if (sense[2] & 0x02) DBG(10, "sense: ERR_NOPAPER\n"); if (sense[2] & 0x04) DBG(10, "sense: ERR_ILLTABLE\n"); if (sense[2] & 0x08) DBG(10, "sense: ERR_ILLOFFSET\n"); if (sense[2] & 0x10) DBG(10, "sense: ERR_ILLBPP\n"); return SANE_STATUS_IO_ERROR; default : DBG(10, "sense: unknown error\n"); return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /********************************************************************/ /* wait (via polling) until scanner seems "ready" */ /********************************************************************/ static SANE_Status wait_ready(Microtek_Scanner *ms) { uint8_t comm[6] = { 0, 0, 0, 0, 0, 0 }; SANE_Status status; int retry = 0; DBG(23, ".wait_ready %d...\n", ms->sfd); while ((status = sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0)) != SANE_STATUS_GOOD) { DBG(23, "wait_ready failed (%d)\n", retry); if (retry > 5) return SANE_STATUS_IO_ERROR; /* XXXXXXXX */ retry++; sleep(3); } return SANE_STATUS_GOOD; } /********************************************************************/ /* send scan region coordinates */ /********************************************************************/ static SANE_Status scanning_frame(Microtek_Scanner *ms) { uint8_t *data, comm[15] = { 0x04, 0, 0, 0, 0x09, 0 }; int x1, y1, x2, y2; DBG(23, ".scanning_frame...\n"); x1 = ms->x1; x2 = ms->x2; y1 = ms->y1; y2 = ms->y2; /* E6 weirdness (other models too?) */ if (ms->unit_type == MS_UNIT_18INCH) { x1 /= 2; x2 /= 2; y1 /= 2; y2 /= 2; } DBG(23, ".scanning_frame: in- %d,%d %d,%d\n", ms->x1, ms->y1, ms->x2, ms->y2); DBG(23, ".scanning_frame: out- %d,%d %d,%d\n", x1, y1, x2, y2); data = comm + 6; data[0] = ((ms->unit_type == MS_UNIT_PIXELS) ? 0x08 : 0 ) | ((ms->mode == MS_MODE_HALFTONE) ? 0x01 : 0 ); data[1] = x1 & 0xFF; data[2] = (x1 >> 8) & 0xFF; data[3] = y1 & 0xFF; data[4] = (y1 >> 8) & 0xFF; data[5] = x2 & 0xFF; data[6] = (x2 >> 8) & 0xFF; data[7] = y2 & 0xFF; data[8] = (y2 >> 8) & 0xFF; if (DBG_LEVEL >= 192) { int i; #if 0 fprintf(stderr, "SF: "); for (i=0;i<6+0x09;i++) fprintf(stderr, "%2x ", comm[i]); fprintf(stderr, "\n"); #endif MDBG_INIT("SF: "); for (i=0;i<6+0x09;i++) MDBG_ADD("%2x ", comm[i]); MDBG_FINISH(192); } return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x09, 0, 0); } /********************************************************************/ /* send "mode_select" */ /********************************************************************/ static SANE_Status mode_select(Microtek_Scanner *ms) { uint8_t *data, comm[19] = { 0x15, 0, 0, 0, 0, 0 }; DBG(23, ".mode_select %d...\n", ms->sfd); data = comm + 6; data[0] = 0x81 | ((ms->unit_type == MS_UNIT_18INCH) ? 0 : 0x08) | ((ms->res_type == MS_RES_5PER) ? 0 : 0x02); data[1] = ms->resolution_code; data[2] = ms->exposure; data[3] = ms->contrast; data[4] = ms->pattern; data[5] = ms->velocity; data[6] = ms->shadow; data[7] = ms->highlight; DBG(23, ".mode_select: pap_len: %d\n", ms->paper_length); data[8] = ms->paper_length & 0xFF; data[9] = (ms->paper_length >> 8) & 0xFF; data[10] = ms->midtone; /* set command/data length */ comm[4] = (ms->midtone_support) ? 0x0B : 0x0A; if (DBG_LEVEL >= 192) { int i; #if 0 fprintf(stderr, "MSL: "); for (i=0;i<6+comm[4];i++) fprintf(stderr, "%2x ", comm[i]); fprintf(stderr, "\n"); #endif MDBG_INIT("MSL: "); for (i=0;i<6+comm[4];i++) MDBG_ADD("%2x ", comm[i]); MDBG_FINISH(192); } return sanei_scsi_cmd(ms->sfd, comm, 6 + comm[4], 0, 0); } /********************************************************************/ /* send "mode_select_1" */ /********************************************************************/ static SANE_Status mode_select_1(Microtek_Scanner *ms) { uint8_t *data, comm[16] = { 0x16, 0, 0, 0, 0x0A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; DBG(23, ".mode_select_1 %d...\n", ms->sfd); data = comm + 6; data[1] = ms->bright_r; data[3] = ((ms->allow_calibrate) ? 0 : 0x02); /* | 0x01; */ if (DBG_LEVEL >= 192) { int i; #if 0 fprintf(stderr, "MSL1: "); for (i=0;i<6+0x0A;i++) fprintf(stderr, "%2x ", comm[i]); fprintf(stderr, "\n"); #endif MDBG_INIT("MSL1: "); for (i=0;i<6+0x0A;i++) MDBG_ADD("%2x ", comm[i]); MDBG_FINISH(192); } return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x0A, 0, 0); } /********************************************************************/ /* record mode_sense results in the mode_sense buffer */ /* (this is to tell if something catastrophic has happened */ /* to the scanner in-between scans) */ /********************************************************************/ static SANE_Status save_mode_sense(Microtek_Scanner *ms) { uint8_t data[20], comm[6] = { 0x1A, 0, 0, 0, 0, 0}; size_t lenp; SANE_Status status; int i; DBG(23, ".save_mode_sense %d...\n", ms->sfd); if (ms->onepass) comm[4] = 0x13; else if (ms->midtone_support) comm[4] = 0x0B; else comm[4] = 0x0A; lenp = comm[4]; status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp); for (i=0; i<10; i++) ms->mode_sense_cache[i] = data[i]; if (DBG_LEVEL >= 192) { unsigned int i; #if 0 fprintf(stderr, "SMS: "); for (i=0;isfd); if (ms->onepass) comm[4] = 0x13; else if (ms->midtone_support) comm[4] = 0x0B; else comm[4] = 0x0A; lenp = comm[4]; status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp); *match = 1; for (i=0; i<10; i++) *match = *match && (ms->mode_sense_cache[i] == data[i]); if (DBG_LEVEL >= 192) { unsigned int i; #if 0 fprintf(stderr, "CMS: "); for (i=0;imode_sense_cache[i]); fprintf(stderr, "\n"); #endif MDBG_INIT("CMS: "); for (i=0;imode_sense_cache[i]); MDBG_FINISH(192); } return status; } /********************************************************************/ /* send mode_sense_1, and upset every scsi driver known to mankind */ /********************************************************************/ #if 0 static SANE_Status mode_sense_1(Microtek_Scanner *ms) { uint8_t *data, comm[36] = { 0x19, 0, 0, 0, 0x1E, 0 }; DBG(23, ".mode_sense_1...\n"); data = comm + 6; memset(data, 0, 30); data[1] = ms->bright_r; data[2] = ms->bright_g; data[3] = ms->bright_b; if (DBG_LEVEL >= 192) { int i; fprintf(stderr, "MS1: "); for (i=0;i<6+0x1E;i++) fprintf(stderr, "%2x ", comm[i]); fprintf(stderr, "\n"); } return sanei_scsi_cmd(ms->sfd, comm, 6 + 0x1E, 0, 0); } #endif /********************************************************************/ /* send "accessory" command */ /********************************************************************/ static SANE_Status accessory(Microtek_Scanner *ms) { uint8_t comm[6] = { 0x10, 0, 0, 0, 0, 0 }; DBG(23, ".accessory...\n"); comm[4] = ((ms->useADF) ? 0x41 : 0x40) | ((ms->prescan) ? 0x18 : 0x10) | ((ms->transparency) ? 0x24 : 0x20) | ((ms->allowbacktrack) ? 0x82 : 0x80); if (DBG_LEVEL >= 192) { int i; #if 0 fprintf(stderr, "AC: "); for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]); fprintf(stderr, "\n"); #endif MDBG_INIT("AC: "); for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]); MDBG_FINISH(192); } return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0); } /********************************************************************/ /* start the scanner a-scannin' */ /********************************************************************/ static SANE_Status start_scan(Microtek_Scanner *ms) { uint8_t comm[6] = { 0x1B, 0, 0, 0, 0, 0 }; DBG(23, ".start_scan...\n"); comm[4] = 0x01 | /* "start" */ ((ms->expandedresolution) ? 0x80 : 0) | ((ms->multibit) ? 0x40 : 0) | ((ms->onepasscolor) ? 0x20 : 0) | ((ms->reversecolors) ? 0x04 : 0) | ((ms->fastprescan) ? 0x02 : 0) | ((ms->filter == MS_FILT_RED) ? 0x08 : 0) | ((ms->filter == MS_FILT_GREEN) ? 0x10 : 0) | ((ms->filter == MS_FILT_BLUE) ? 0x18 : 0) ; if (DBG_LEVEL >= 192) { int i; #if 0 fprintf(stderr, "SS: "); for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]); fprintf(stderr, "\n"); #endif MDBG_INIT("SS: "); for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]); MDBG_FINISH(192); } return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0); } /********************************************************************/ /* stop the scanner a-scannin' */ /********************************************************************/ static SANE_Status stop_scan(Microtek_Scanner *ms) { uint8_t comm[6] = { 0x1B, 0, 0, 0, 0, 0 }; DBG(23, ".stop_scan...\n"); if (DBG_LEVEL >= 192) { int i; #if 0 fprintf(stderr, "SPS:"); for (i=0;i<6;i++) fprintf(stderr, "%2x ", comm[i]); fprintf(stderr, "\n"); #endif MDBG_INIT("SPS:"); for (i=0;i<6;i++) MDBG_ADD("%2x ", comm[i]); MDBG_FINISH(192); } return sanei_scsi_cmd(ms->sfd, comm, 6, 0, 0); } /********************************************************************/ /* get scan status */ /********************************************************************/ static SANE_Status get_scan_status(Microtek_Scanner *ms, SANE_Int *busy, SANE_Int *bytes_per_line, SANE_Int *lines) { uint8_t data[6], comm[6] = { 0x0F, 0, 0, 0, 0x06, 0 }; SANE_Status status; size_t lenp; int retry = 0; DBG(23, ".get_scan_status %d...\n", ms->sfd); do { lenp = 6; /* do some retry stuff in here, too */ status = sanei_scsi_cmd(ms->sfd, comm, 6, data, &lenp); if (status != SANE_STATUS_GOOD) { DBG(20, "get_scan_status: scsi error\n"); return status; } *busy = data[0]; *bytes_per_line = (data[1]) + (data[2] << 8); *lines = (data[3]) + (data[4] << 8) + (data[5] << 16); DBG(20, "get_scan_status(%lu): %d, %d, %d -> #%d\n", (u_long) lenp, *busy, *bytes_per_line, *lines, retry); DBG(20, "> %2x %2x %2x %2x %2x %2x\n", data[0], data[1], data[2], data[3], data[4], data[5]); if (*busy != 0) { retry++; DBG(23, "get_scan_status: busy, retry in %d...\n", M_GSS_WAIT * retry); sleep(M_GSS_WAIT * retry); } } while ((*busy != 0) && (retry < 4)); if (*busy == 0) return status; else return SANE_STATUS_IO_ERROR; } /********************************************************************/ /* get scanlines from scanner */ /********************************************************************/ static SANE_Status read_scan_data(Microtek_Scanner *ms, int lines, uint8_t *buffer, size_t *bufsize) { uint8_t comm[6] = { 0x08, 0, 0, 0, 0, 0 }; DBG(23, ".read_scan_data...\n"); comm[2] = (lines >> 16) & 0xFF; comm[3] = (lines >> 8) & 0xFF; comm[4] = (lines) & 0xFF; return sanei_scsi_cmd(ms->sfd, comm, 6, buffer, bufsize); } /********************************************************************/ /* download color LUT to scanner (if it takes one) */ /********************************************************************/ static SANE_Status download_gamma(Microtek_Scanner *ms) { uint8_t *data, *comm; /* commbytes[10] = { 0x55, 0, 0x27, 0, 0, 0, 0, 0, 0, 0 };*/ int i, pl; int commsize; int bit_depth = 8; /* hard-code for now, should match bpp XXXXXXX */ int max_entry; SANE_Status status; DBG(23, ".download_gamma...\n"); /* skip if scanner doesn't take 'em */ if (!(ms->gamma_entries)) { DBG(23, ".download_gamma: no entries; skipping\n"); return SANE_STATUS_GOOD; } if ((ms->gamma_entry_size != 1) && (ms->gamma_entry_size != 2)) { DBG(23, ".download_gamma: entry size %d?!?!?\n", ms->gamma_entry_size); return SANE_STATUS_INVAL; /* XXXXXXXxx */ } max_entry = (1 << bit_depth) - 1; DBG(23, ".download_gamma: %d entries of %d bytes, max %d\n", ms->gamma_entries, ms->gamma_entry_size, max_entry); commsize = 10 + (ms->gamma_entries * ms->gamma_entry_size); comm = calloc(commsize, sizeof(uint8_t)); if (comm == NULL) { DBG(23, ".download_gamma: couldn't allocate %d bytes for comm buffer!\n", commsize); return SANE_STATUS_NO_MEM; } data = comm + 10; comm[0] = 0x55; comm[1] = 0; comm[2] = 0x27; comm[3] = 0; comm[4] = 0; comm[5] = 0; comm[6] = 0; comm[7] = ((ms->gamma_entries * ms->gamma_entry_size) >> 8) & 0xFF; comm[8] = (ms->gamma_entries * ms->gamma_entry_size) & 0xFF; comm[9] = (ms->gamma_entry_size == 2) ? 1 : 0; if (!(strcmp(ms->val[OPT_CUSTOM_GAMMA].s, M_TABLE))) { /***** Gamma by TABLE *****/ int table_shift = (ms->gamma_bit_depth - bit_depth); DBG(23, ".download_gamma: by table (%d bpe, %d shift)\n", ms->gamma_bit_depth, table_shift); if (ms->val[OPT_GAMMA_BIND].w == SANE_TRUE) { for (i=0; igamma_entries; i++) { int val = ms->gray_lut[i] >> table_shift; switch (ms->gamma_entry_size) { case 1: data[i] = (uint8_t) val; break; case 2: data[i*2] = val & 0xFF; data[(i*2)+1] = (val>>8) & 0xFF; break; } } status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); } else { pl = 1; do { SANE_Int *pl_lut; switch (pl) { case 1: pl_lut = ms->red_lut; break; case 2: pl_lut = ms->green_lut; break; case 3: pl_lut = ms->blue_lut; break; default: DBG(23, ".download_gamma: uh, exceeded pl bound!\n"); free(comm); return SANE_STATUS_INVAL; /* XXXXXXXxx */ break; } for (i=0; igamma_entries; i++) { int val = pl_lut[i] >> table_shift; switch (ms->gamma_entry_size) { case 1: data[i] = (uint8_t) val; break; case 2: data[i*2] = val & 0xFF; data[(i*2)+1] = (val>>8) & 0xFF; break; } } /* XXXXXXX */ comm[9] = (comm[9] & 0x3F) | (pl << 6); status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); pl++; } while ((pl < 4) && (status == SANE_STATUS_GOOD)); } } else if (!(strcmp(ms->val[OPT_CUSTOM_GAMMA].s, M_SCALAR))) { /***** Gamma by SCALAR *****/ DBG(23, ".download_gamma: by scalar\n"); if (ms->val[OPT_GAMMA_BIND].w == SANE_TRUE) { double gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA].w); for (i=0; igamma_entries; i++) { int val = (max_entry * pow((double) i / ((double) ms->gamma_entries - 1.0), 1.0 / gamma)); switch (ms->gamma_entry_size) { case 1: data[i] = (uint8_t) val; break; case 2: data[i*2] = val & 0xFF; data[(i*2)+1] = (val>>8) & 0xFF; break; } } status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); } else { double gamma; pl = 1; do { switch (pl) { case 1: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_R].w); break; case 2: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_G].w); break; case 3: gamma = SANE_UNFIX(ms->val[OPT_ANALOG_GAMMA_B].w); break; default: gamma = 1.0; break; /* should never happen */ } for (i=0; igamma_entries; i++) { int val = (max_entry * pow((double) i / ((double) ms->gamma_entries - 1.0), 1.0 / gamma)); switch (ms->gamma_entry_size) { case 1: data[i] = (uint8_t) val; break; case 2: data[i*2] = val & 0xFF; data[(i*2)+1] = (val>>8) & 0xFF; break; } } comm[9] = (comm[9] & 0x3F) | (pl << 6); status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); pl++; } while ((pl < 4) && (status == SANE_STATUS_GOOD)); } } else { /***** No custom Gamma *****/ DBG(23, ".download_gamma: by default\n"); for (i=0; igamma_entries; i++) { /* int val = (((double) max_entry * (double) i / ((double) ms->gamma_entries - 1.0)) + 0.5); ROUNDING????*/ int val = (double) max_entry * (double) i / ((double) ms->gamma_entries - 1.0); switch (ms->gamma_entry_size) { case 1: data[i] = (uint8_t) val; break; case 2: data[i*2] = val & 0xFF; data[(i*2)+1] = (val >> 8) & 0xFF; break; } } status = sanei_scsi_cmd(ms->sfd, comm, commsize, 0, 0); } free(comm); return status; } /********************************************************************/ /* magic command to start calibration */ /********************************************************************/ static SANE_Status start_calibration(Microtek_Scanner *ms) { uint8_t comm[8] = { 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x0a }; DBG(23, ".start_calibrate...\n"); if (DBG_LEVEL >= 192) { int i; #if 0 fprintf(stderr, "STCal:"); for (i=0;i<8;i++) fprintf(stderr, "%2x ", comm[i]); fprintf(stderr, "\n"); #endif MDBG_INIT("STCal:"); for (i=0;i<8;i++) MDBG_ADD("%2x ", comm[i]); MDBG_FINISH(192); } return sanei_scsi_cmd(ms->sfd, comm, 8, 0, 0); } /********************************************************************/ /* magic command to download calibration values */ /********************************************************************/ static SANE_Status download_calibration(Microtek_Scanner *ms, uint8_t *comm, uint8_t letter, int linewidth) { DBG(23, ".download_calibration... %c %d\n", letter, linewidth); comm[0] = 0x0c; comm[1] = 0x00; comm[2] = 0x00; comm[3] = (linewidth >> 8) & 0xFF; comm[4] = linewidth & 0xFF; comm[5] = 0x00; comm[6] = 0x00; switch (letter) { case 'R': comm[7] = 0x40; break; case 'G': comm[7] = 0x80; break; case 'B': comm[7] = 0xc0; break; default: /* XXXXXXX */ break; } return sanei_scsi_cmd(ms->sfd, comm, 6 + linewidth, 0, 0); } /********************************************************************/ /********************************************************************/ /* */ /* Myriad of internal functions */ /* */ /********************************************************************/ /********************************************************************/ /********************************************************************/ /* Initialize the options registry */ /********************************************************************/ static SANE_Status init_options(Microtek_Scanner *ms) { int i; SANE_Option_Descriptor *sod = ms->sod; Option_Value *val = ms->val; DBG(15, "init_options...\n"); memset(ms->sod, 0, sizeof(ms->sod)); memset(ms->val, 0, sizeof(ms->val)); /* default: software selectable word options... */ for (i=0; idev->info.modes & MI_MODES_COLOR) mode_list[i++] = M_COLOR; if (ms->dev->info.modes & MI_MODES_GRAY) mode_list[i++] = M_GRAY; if (ms->dev->info.modes & MI_MODES_HALFTONE) mode_list[i++] = M_HALFTONE; if (ms->dev->info.modes & MI_MODES_LINEART) mode_list[i++] = M_LINEART; mode_list[i] = NULL; sod[OPT_MODE].constraint.string_list = mode_list; sod[OPT_MODE].size = max_string_size(mode_list); val[OPT_MODE].s = strdup(mode_list[0]); } sod[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; sod[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; sod[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; sod[OPT_RESOLUTION].type = SANE_TYPE_FIXED; sod[OPT_RESOLUTION].unit = SANE_UNIT_DPI; sod[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; { SANE_Int maxres = ms->dev->info.base_resolution; ms->res_range.max = SANE_FIX(maxres); ms->exp_res_range.max = SANE_FIX(2 * maxres); if (ms->dev->info.res_step & MI_RESSTEP_1PER) { DBG(23, "init_options: quant yes\n"); ms->res_range.min = SANE_FIX( maxres / 100 ); ms->res_range.quant = ms->res_range.min; ms->exp_res_range.min = SANE_FIX(2 * maxres / 100); ms->exp_res_range.quant = ms->exp_res_range.min; } else { /* XXXXXXXXXXX */ DBG(23, "init_options: quant no\n"); ms->res_range.quant = SANE_FIX( 0 ); } sod[OPT_RESOLUTION].constraint.range = &(ms->res_range); } val[OPT_RESOLUTION].w = SANE_FIX(100); sod[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; sod[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; sod[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; sod[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; sod[OPT_HALFTONE_PATTERN].size = max_string_size(halftone_mode_list); sod[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; sod[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; sod[OPT_HALFTONE_PATTERN].constraint.string_list = halftone_mode_list; val[OPT_HALFTONE_PATTERN].s = strdup(halftone_mode_list[0]); sod[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE; sod[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE; sod[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE; sod[OPT_NEGATIVE].type = SANE_TYPE_BOOL; sod[OPT_NEGATIVE].cap |= (ms->dev->info.modes & MI_MODES_NEGATIVE) ? 0 : SANE_CAP_INACTIVE; val[OPT_NEGATIVE].w = SANE_FALSE; sod[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; sod[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; /* sod[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED;*/ sod[OPT_SPEED].desc = "Scan speed throttle -- higher values are *slower*."; sod[OPT_SPEED].type = SANE_TYPE_INT; sod[OPT_SPEED].cap |= SANE_CAP_ADVANCED; sod[OPT_SPEED].unit = SANE_UNIT_NONE; sod[OPT_SPEED].size = sizeof(SANE_Word); sod[OPT_SPEED].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_SPEED].constraint.range = &speed_range; val[OPT_SPEED].w = 1; sod[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; sod[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; sod[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; sod[OPT_SOURCE].type = SANE_TYPE_STRING; sod[OPT_SOURCE].unit = SANE_UNIT_NONE; sod[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; { SANE_String_Const *source_list; source_list = (SANE_String_Const *) malloc(4 * sizeof(SANE_String_Const)); if (source_list == NULL) return SANE_STATUS_NO_MEM; i = 0; source_list[i++] = M_OPAQUE; if (ms->dev->info.source_options & MI_SRC_HAS_TRANS) source_list[i++] = M_TRANS; if (ms->dev->info.source_options & MI_SRC_HAS_FEED) source_list[i++] = M_AUTOFEED; source_list[i] = NULL; sod[OPT_SOURCE].constraint.string_list = source_list; sod[OPT_SOURCE].size = max_string_size(source_list); if (i < 2) sod[OPT_SOURCE].cap |= SANE_CAP_INACTIVE; val[OPT_SOURCE].s = strdup(source_list[0]); } sod[OPT_PREVIEW].name = SANE_NAME_PREVIEW; sod[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; sod[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; sod[OPT_PREVIEW].type = SANE_TYPE_BOOL; sod[OPT_PREVIEW].unit = SANE_UNIT_NONE; sod[OPT_PREVIEW].size = sizeof(SANE_Word); val[OPT_PREVIEW].w = SANE_FALSE; sod[OPT_GEOMETRY_GROUP].name = ""; sod[OPT_GEOMETRY_GROUP].title = "Geometry"; sod[OPT_GEOMETRY_GROUP].desc = ""; sod[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; sod[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; sod[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; sod[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; sod[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; sod[OPT_TL_X].type = SANE_TYPE_FIXED; sod[OPT_TL_X].unit = SANE_UNIT_MM; sod[OPT_TL_X].size = sizeof(SANE_Word); sod[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; sod[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; sod[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; sod[OPT_TL_Y].type = SANE_TYPE_FIXED; sod[OPT_TL_Y].unit = SANE_UNIT_MM; sod[OPT_TL_Y].size = sizeof(SANE_Word); sod[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; sod[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; sod[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; sod[OPT_BR_X].type = SANE_TYPE_FIXED; sod[OPT_BR_X].unit = SANE_UNIT_MM; sod[OPT_BR_X].size = sizeof(SANE_Word); sod[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; sod[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; sod[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; sod[OPT_BR_Y].type = SANE_TYPE_FIXED; sod[OPT_BR_Y].unit = SANE_UNIT_MM; sod[OPT_BR_Y].size = sizeof(SANE_Word); sod[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_TL_X].constraint.range = sod[OPT_BR_X].constraint.range = &(ms->dev->info.doc_x_range); sod[OPT_TL_Y].constraint.range = sod[OPT_BR_Y].constraint.range = &(ms->dev->info.doc_y_range); /* set default scan region to be maximum size */ val[OPT_TL_X].w = sod[OPT_TL_X].constraint.range->min; val[OPT_TL_Y].w = sod[OPT_TL_Y].constraint.range->min; val[OPT_BR_X].w = sod[OPT_BR_X].constraint.range->max; val[OPT_BR_Y].w = sod[OPT_BR_Y].constraint.range->max; sod[OPT_ENHANCEMENT_GROUP].name = ""; sod[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; sod[OPT_ENHANCEMENT_GROUP].desc = ""; sod[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; sod[OPT_ENHANCEMENT_GROUP].cap = 0; sod[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_EXPOSURE].name = "exposure"; sod[OPT_EXPOSURE].title = "Exposure"; sod[OPT_EXPOSURE].desc = "Analog exposure control"; sod[OPT_EXPOSURE].type = SANE_TYPE_INT; sod[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; sod[OPT_EXPOSURE].size = sizeof(SANE_Word); sod[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; ms->exposure_range.min = ms->dev->info.min_exposure; ms->exposure_range.max = ms->dev->info.max_exposure; ms->exposure_range.quant = 3; sod[OPT_EXPOSURE].constraint.range = &(ms->exposure_range); val[OPT_EXPOSURE].w = 0; sod[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; sod[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; sod[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; sod[OPT_BRIGHTNESS].type = SANE_TYPE_INT; sod[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; sod[OPT_BRIGHTNESS].size = sizeof(SANE_Word); sod[OPT_BRIGHTNESS].cap |= ((ms->dev->info.extra_cap & MI_EXCAP_OFF_CTL) ? 0: SANE_CAP_INACTIVE); sod[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_BRIGHTNESS].constraint.range = &brightness_range; val[OPT_BRIGHTNESS].w = 0; sod[OPT_CONTRAST].name = SANE_NAME_CONTRAST; sod[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; sod[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; sod[OPT_CONTRAST].type = SANE_TYPE_INT; sod[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; sod[OPT_CONTRAST].size = sizeof(SANE_Word); sod[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; ms->contrast_range.min = ms->dev->info.min_contrast; ms->contrast_range.max = ms->dev->info.max_contrast; ms->contrast_range.quant = 7; sod[OPT_CONTRAST].constraint.range = &(ms->contrast_range); val[OPT_CONTRAST].w = 0; sod[OPT_HIGHLIGHT].name = SANE_NAME_WHITE_LEVEL; sod[OPT_HIGHLIGHT].title = SANE_TITLE_WHITE_LEVEL; sod[OPT_HIGHLIGHT].desc = SANE_DESC_WHITE_LEVEL; sod[OPT_HIGHLIGHT].type = SANE_TYPE_INT; sod[OPT_HIGHLIGHT].unit = SANE_UNIT_NONE; sod[OPT_HIGHLIGHT].size = sizeof(SANE_Word); sod[OPT_HIGHLIGHT].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_HIGHLIGHT].constraint.range = &u8_range; val[OPT_HIGHLIGHT].w = 255; sod[OPT_SHADOW].name = SANE_NAME_BLACK_LEVEL; sod[OPT_SHADOW].title = SANE_TITLE_BLACK_LEVEL; sod[OPT_SHADOW].desc = SANE_DESC_BLACK_LEVEL; sod[OPT_SHADOW].type = SANE_TYPE_INT; sod[OPT_SHADOW].unit = SANE_UNIT_NONE; sod[OPT_SHADOW].size = sizeof(SANE_Word); sod[OPT_SHADOW].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_SHADOW].constraint.range = &u8_range; val[OPT_SHADOW].w = 0; if (ms->dev->info.enhance_cap & MI_ENH_CAP_SHADOW) { sod[OPT_HIGHLIGHT].cap |= SANE_CAP_ADVANCED; sod[OPT_SHADOW].cap |= SANE_CAP_ADVANCED; } else { sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; } sod[OPT_MIDTONE].name = "midtone"; sod[OPT_MIDTONE].title = "Midtone Level"; sod[OPT_MIDTONE].desc = "Midtone Level"; sod[OPT_MIDTONE].type = SANE_TYPE_INT; sod[OPT_MIDTONE].unit = SANE_UNIT_NONE; sod[OPT_MIDTONE].size = sizeof(SANE_Word); sod[OPT_MIDTONE].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_MIDTONE].constraint.range = &u8_range; val[OPT_MIDTONE].w = 128; if (ms->midtone_support) { sod[OPT_MIDTONE].cap |= SANE_CAP_ADVANCED; } else { sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; } /* XXXXXXXX is this supported by all scanners?? if ((strcmp(M_COLOR, val[OPT_MODE].s)) && (strcmp(M_GRAY, val[OPT_MODE].s))) { sod[OPT_HIGHLIGHT].cap |= SANE_CAP_INACTIVE; sod[OPT_SHADOW].cap |= SANE_CAP_INACTIVE; sod[OPT_MIDTONE].cap |= SANE_CAP_INACTIVE; } */ sod[OPT_GAMMA_GROUP].name = ""; sod[OPT_GAMMA_GROUP].title = "Gamma Control"; sod[OPT_GAMMA_GROUP].desc = ""; sod[OPT_GAMMA_GROUP].type = SANE_TYPE_GROUP; if (!(ms->gamma_entries)) sod[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_GROUP].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_CUSTOM_GAMMA].name = "gamma-mode"; sod[OPT_CUSTOM_GAMMA].title = "Gamma Control Mode"; sod[OPT_CUSTOM_GAMMA].desc = "How to specify gamma correction, if at all"; sod[OPT_CUSTOM_GAMMA].type = SANE_TYPE_STRING; sod[OPT_CUSTOM_GAMMA].size = max_string_size(gamma_mode_list); sod[OPT_CUSTOM_GAMMA].constraint_type = SANE_CONSTRAINT_STRING_LIST; sod[OPT_CUSTOM_GAMMA].constraint.string_list = gamma_mode_list; if (!(ms->gamma_entries)) sod[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; val[OPT_CUSTOM_GAMMA].s = strdup(gamma_mode_list[0]); sod[OPT_GAMMA_BIND].name = SANE_NAME_ANALOG_GAMMA_BIND; sod[OPT_GAMMA_BIND].title = SANE_TITLE_ANALOG_GAMMA_BIND; sod[OPT_GAMMA_BIND].desc = SANE_DESC_ANALOG_GAMMA_BIND; sod[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL; sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; val[OPT_GAMMA_BIND].w = SANE_TRUE; sod[OPT_ANALOG_GAMMA].name = SANE_NAME_ANALOG_GAMMA; sod[OPT_ANALOG_GAMMA].title = SANE_TITLE_ANALOG_GAMMA; sod[OPT_ANALOG_GAMMA].desc = SANE_DESC_ANALOG_GAMMA; sod[OPT_ANALOG_GAMMA].type = SANE_TYPE_FIXED; sod[OPT_ANALOG_GAMMA].unit = SANE_UNIT_NONE; sod[OPT_ANALOG_GAMMA].size = sizeof(SANE_Word); sod[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_ANALOG_GAMMA].constraint.range = &analog_gamma_range; val[OPT_ANALOG_GAMMA].w = SANE_FIX(1.0); sod[OPT_ANALOG_GAMMA_R].name = SANE_NAME_ANALOG_GAMMA_R; sod[OPT_ANALOG_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R; sod[OPT_ANALOG_GAMMA_R].desc = SANE_DESC_ANALOG_GAMMA_R; sod[OPT_ANALOG_GAMMA_R].type = SANE_TYPE_FIXED; sod[OPT_ANALOG_GAMMA_R].unit = SANE_UNIT_NONE; sod[OPT_ANALOG_GAMMA_R].size = sizeof(SANE_Word); sod[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_ANALOG_GAMMA_R].constraint.range = &analog_gamma_range; val[OPT_ANALOG_GAMMA_R].w = SANE_FIX(1.0); sod[OPT_ANALOG_GAMMA_G].name = SANE_NAME_ANALOG_GAMMA_G; sod[OPT_ANALOG_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G; sod[OPT_ANALOG_GAMMA_G].desc = SANE_DESC_ANALOG_GAMMA_G; sod[OPT_ANALOG_GAMMA_G].type = SANE_TYPE_FIXED; sod[OPT_ANALOG_GAMMA_G].unit = SANE_UNIT_NONE; sod[OPT_ANALOG_GAMMA_G].size = sizeof(SANE_Word); sod[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_ANALOG_GAMMA_G].constraint.range = &analog_gamma_range; val[OPT_ANALOG_GAMMA_G].w = SANE_FIX(1.0); sod[OPT_ANALOG_GAMMA_B].name = SANE_NAME_ANALOG_GAMMA_B; sod[OPT_ANALOG_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B; sod[OPT_ANALOG_GAMMA_B].desc = SANE_DESC_ANALOG_GAMMA_B; sod[OPT_ANALOG_GAMMA_B].type = SANE_TYPE_FIXED; sod[OPT_ANALOG_GAMMA_B].unit = SANE_UNIT_NONE; sod[OPT_ANALOG_GAMMA_B].size = sizeof(SANE_Word); sod[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_ANALOG_GAMMA_B].constraint.range = &analog_gamma_range; val[OPT_ANALOG_GAMMA_B].w = SANE_FIX(1.0); sod[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; sod[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; sod[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; sod[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; sod[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; sod[OPT_GAMMA_VECTOR].size = ms->gamma_entries * sizeof(SANE_Word); sod[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_GAMMA_VECTOR].constraint.range = &(ms->gamma_entry_range); val[OPT_GAMMA_VECTOR].wa = ms->gray_lut; sod[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; sod[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; sod[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; sod[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; sod[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; sod[OPT_GAMMA_VECTOR_R].size = ms->gamma_entries * sizeof(SANE_Word); sod[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_GAMMA_VECTOR_R].constraint.range = &(ms->gamma_entry_range); val[OPT_GAMMA_VECTOR_R].wa = ms->red_lut; sod[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; sod[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; sod[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; sod[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; sod[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; sod[OPT_GAMMA_VECTOR_G].size = ms->gamma_entries * sizeof(SANE_Word); sod[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_GAMMA_VECTOR_G].constraint.range = &(ms->gamma_entry_range); val[OPT_GAMMA_VECTOR_G].wa = ms->green_lut; sod[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; sod[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; sod[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; sod[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; sod[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; sod[OPT_GAMMA_VECTOR_B].size = ms->gamma_entries * sizeof(SANE_Word); sod[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; sod[OPT_GAMMA_VECTOR_B].constraint.range = &(ms->gamma_entry_range); val[OPT_GAMMA_VECTOR_B].wa = ms->blue_lut; sod[OPT_EXP_RES].name = "exp_res"; sod[OPT_EXP_RES].title = "Expanded Resolution"; sod[OPT_EXP_RES].desc = "Enable double-resolution scans"; sod[OPT_EXP_RES].type = SANE_TYPE_BOOL; sod[OPT_EXP_RES].cap |= SANE_CAP_ADVANCED; if (!(ms->dev->info.expanded_resolution)) sod[OPT_EXP_RES].cap |= SANE_CAP_INACTIVE; val[OPT_EXP_RES].w = SANE_FALSE; sod[OPT_CALIB_ONCE].name = "calib_once"; sod[OPT_CALIB_ONCE].title = "Calibrate Only Once"; sod[OPT_CALIB_ONCE].desc = "Avoid CCD calibration on every scan" \ "(toggle off/on to cause calibration on next scan)"; sod[OPT_CALIB_ONCE].type = SANE_TYPE_BOOL; sod[OPT_CALIB_ONCE].cap |= SANE_CAP_ADVANCED; if (!(ms->do_real_calib)) { sod[OPT_CALIB_ONCE].cap |= SANE_CAP_INACTIVE; val[OPT_CALIB_ONCE].w = SANE_FALSE; } else val[OPT_CALIB_ONCE].w = SANE_TRUE; /* sod[OPT_].name = SANE_NAME_; sod[OPT_].title = SANE_TITLE_; sod[OPT_].desc = SANE_DESC_; sod[OPT_].type = SANE_TYPE_; sod[OPT_].unit = SANE_UNIT_NONE; sod[OPT_].size = sizeof(SANE_Word); sod[OPT_].cap = 0; sod[OPT_].constraint_type = SANE_CONSTRAINT_NONE; sod[OPT_].constraint = ; val[OPT_].w = ; */ DBG(15, "init_options: done.\n"); return SANE_STATUS_GOOD; } /********************************************************************/ /* Parse an INQUIRY information block, as returned by scanner */ /********************************************************************/ static SANE_Status parse_inquiry(Microtek_Info *mi, unsigned char *result) { #if 0 unsigned char result[0x60] = { 0x06,0x31,0x23,0x01,0x5b,0x00,0x00,0x00,0x41,0x47,0x46,0x41,0x20,0x20,0x20,0x20, 0x53,0x74,0x75,0x64,0x69,0x6f,0x53,0x63,0x61,0x6e,0x20,0x49,0x49,0x20,0x20,0x20, 0x32,0x2e,0x33,0x30,0x53,0x43,0x53,0x49,0x20,0x46,0x2f,0x57,0x56,0x33,0x2e,0x31, 0x20,0x43,0x54,0x4c,0x35,0x33,0x38,0x30,0x03,0x4f,0x8c,0xc5,0x00,0xee,0x5b,0x43, 0x01,0x01,0x02,0x00,0x00,0x03,0x00,0x01,0x00,0x4a,0x01,0x04,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff }; #endif DBG(15, "parse_inquiry...\n"); strncpy(mi->vendor_id, (char *)&result[8], 8); strncpy(mi->model_name, (char *)&result[16], 16); strncpy(mi->revision_num, (char *)&result[32], 4); strncpy(mi->vendor_string, (char *)&result[36], 20); mi->vendor_id[8] = 0; mi->model_name[16] = 0; mi->revision_num[4] = 0; mi->vendor_string[20] = 0; mi->device_type = (SANE_Byte)(result[0] & 0x1f); mi->SCSI_firmware_ver_major = (SANE_Byte)((result[1] & 0xf0) >> 4); mi->SCSI_firmware_ver_minor = (SANE_Byte)(result[1] & 0x0f); mi->scanner_firmware_ver_major = (SANE_Byte)((result[2] & 0xf0) >> 4); mi->scanner_firmware_ver_minor = (SANE_Byte)(result[2] & 0x0f); mi->response_data_format = (SANE_Byte)(result[3]); mi->res_step = (SANE_Byte)(result[56] & 0x03); mi->modes = (SANE_Byte)(result[57]); mi->pattern_count = (SANE_Int)(result[58] & 0x7f); mi->pattern_dwnld = (SANE_Byte)(result[58] & 0x80) > 0; mi->feed_type = (SANE_Byte)(result[59] & 0x0F); mi->compress_type = (SANE_Byte)(result[59] & 0x30); mi->unit_type = (SANE_Byte)(result[59] & 0xC0); mi->doc_size_code = (SANE_Byte)result[60]; /* we'll compute the max sizes after we know base resolution... */ /* why are these things set in two places (and probably wrong anyway)? */ mi->cont_settings = (SANE_Int)((result[61] & 0xf0) >> 4); if ((SANE_Int)(result[72])) mi->cont_settings = (SANE_Int)(result[72]); mi->min_contrast = -42; mi->max_contrast = (mi->cont_settings * 7) - 49; mi->exp_settings = (SANE_Int)(result[61] & 0x0f); if ((SANE_Int)(result[73])) mi->exp_settings = (SANE_Int)(result[73]); mi->min_exposure = -18; mi->max_exposure = (mi->exp_settings * 3) - 21; #if 0 mi->contrast_vals = (SANE_Int)(result[72]); mi->min_contrast = -42; mi->max_contrast = 49; if (mi->contrast_vals) mi->max_contrast = (mi->contrast_vals * 7) - 49; mi->exposure_vals = (SANE_Int)(result[73]); mi->min_exposure = -18; mi->max_exposure = 21; if (mi->exposure_vals) mi->max_exposure = (mi->exposure_vals * 3) - 21; #endif mi->model_code = (SANE_Byte)(result[62]); switch (mi->model_code) { case 0x16: /* the other ScanMaker 600ZS */ case 0x50: /* ScanMaker II/IIXE */ case 0x54: /* ScanMaker IISP */ case 0x55: /* ScanMaker IIER */ case 0x58: /* ScanMaker IIG */ case 0x5a: /* Agfa StudioScan (untested!) */ case 0x5f: /* ScanMaker E3 */ case 0x56: /* ScanMaker A3t */ case 0x64: /* ScanMaker E2 (,Vobis RealScan) */ case 0x65: /* Color PageWiz */ case 0xC8: /* ScanMaker 600ZS */ mi->base_resolution = 300; break; case 0x5b: /* Agfa StudioScan II/IIsi (untested!) */ mi->base_resolution = 400; break; case 0x57: /* ScanMaker IIHR */ case 0x59: /* ScanMaker III */ case 0x5c: /* Agfa Arcus II */ case 0x5e: /* Agfa StudioStar */ case 0x63: /* ScanMaker E6 */ case 0x66: /* ScanMaker E6 (new)*/ mi->base_resolution = 600; break; case 0x51: /* ScanMaker 45t */ case 0x5d: /* Agfa DuoScan */ mi->base_resolution = 1000; break; case 0x52: /* ScanMaker 35t */ mi->base_resolution = 1828; break; case 0x62: /* ScanMaker 35t+, Polaroid 35/LE */ mi->base_resolution = 1950; break; default: mi->base_resolution = 300; DBG(15, "parse_inquiry: Unknown base resolution for 0x%x!\n", mi->model_code); break; } /* Our max_x,y is in pixels. `Some scanners think in 1/8", though.' */ /* max pixel is, of course, total - 1 */ switch (mi->doc_size_code) { case 0x00: mi->max_x = 8.5 * mi->base_resolution - 1; mi->max_y = 14.0 * mi->base_resolution - 1; break; case 0x01: mi->max_x = 8.5 * mi->base_resolution - 1; mi->max_y = 11.0 * mi->base_resolution - 1; break; case 0x02: mi->max_x = 8.5 * mi->base_resolution - 1; mi->max_y = 11.69 * mi->base_resolution - 1; break; case 0x03: mi->max_x = 8.5 * mi->base_resolution - 1; mi->max_y = 13.0 * mi->base_resolution - 1; break; case 0x04: mi->max_x = 8.0 * mi->base_resolution - 1; mi->max_y = 10.0 * mi->base_resolution - 1; break; case 0x05: mi->max_x = 8.3 * mi->base_resolution - 1; mi->max_y = 14.0 * mi->base_resolution - 1; break; case 0x06: mi->max_x = 8.3 * mi->base_resolution - 1; mi->max_y = 13.5 * mi->base_resolution - 1; break; case 0x07: mi->max_x = 8.0 * mi->base_resolution - 1; mi->max_y = 14.0 * mi->base_resolution - 1; break; case 0x80: /* Slide format, size is mm */ mi->max_x = (35.0 / MM_PER_INCH) * mi->base_resolution - 1; mi->max_y = (35.0 / MM_PER_INCH) * mi->base_resolution - 1; break; case 0x81: mi->max_x = 5.0 * mi->base_resolution - 1; mi->max_y = 5.0 * mi->base_resolution - 1; break; case 0x82: /* Slide format, size is mm */ mi->max_x = (36.0 / MM_PER_INCH) * mi->base_resolution - 1; mi->max_y = (36.0 / MM_PER_INCH) * mi->base_resolution - 1; break; default: /* Undefined document format code */ mi->max_x = mi->max_y = 0; DBG(15, "parse_inquiry: Unknown doc_size_code! 0x%x\n", mi->doc_size_code); } /* create the proper range constraints, given the doc size */ { /* we need base resolution in dots-per-millimeter... */ float base_res_dpmm = (float) mi->base_resolution / MM_PER_INCH; mi->doc_x_range.min = SANE_FIX(0); mi->doc_x_range.max = SANE_FIX((float)mi->max_x / base_res_dpmm); mi->doc_x_range.quant = SANE_FIX(0); mi->doc_y_range.min = SANE_FIX(0); mi->doc_y_range.max = SANE_FIX((float)mi->max_y / base_res_dpmm); mi->doc_y_range.quant = SANE_FIX(0); } mi->source_options = (SANE_Byte)(result[63]); mi->expanded_resolution = (result[64] & 0x01); /* my E6 reports exp-res capability incorrectly */ if ((mi->model_code == 0x66) || (mi->model_code == 0x63)) { mi->expanded_resolution = 0xFF; DBG(4, "parse_inquiry: E6 falsely denies expanded resolution.\n"); } /* the StudioScan II(si) does the expanded-mode aspect correction within the scanner... (do others too?) */ if (mi->model_code == 0x5b) { DBG(4, "parse_inquiry: does expanded-mode expansion internally.\n"); mi->does_expansion = 1; } else mi->does_expansion = 0; mi->enhance_cap = (result[65] & 0x03); /* switch (result[66] & 0x0F) { case 0x00: mi->max_lookup_size = 0; break; case 0x01: mi->max_lookup_size = 256; break; case 0x03: mi->max_lookup_size = 1024; break; case 0x05: mi->max_lookup_size = 4096; break; case 0x09: mi->max_lookup_size = 65536; break; default: mi->max_lookup_size = 0; DBG(15, "parse_inquiry: Unknown gamma LUT size! 0x%x\n", result[66]); } */ /* This is not how the vague documentation specifies this register. We're going to take it literally here -- i.e. if the bit is set, the scanner supports the value, otherwise it doesn't. (The docs say all lower values are always supported. This is not the case for the StudioScan IIsi, at least, which only specifies 0x02==1024-byte table, and only supports that, too.) All-in-all, it doesn't matter, since we take the largest allowed LUT size anyway. */ if (result[66] & 0x08) mi->max_lookup_size = 65536; else if (result[66] & 0x04) mi->max_lookup_size = 4096; else if (result[66] & 0x02) mi->max_lookup_size = 1024; else if (result[66] & 0x01) mi->max_lookup_size = 256; else mi->max_lookup_size = 0; /* my E6 reports incorrectly */ if ((mi->model_code == 0x66) || (mi->model_code == 0x63)) { mi->max_lookup_size = 1024; DBG(4, "parse_inquiry: E6 falsely denies 1024-byte LUT.\n"); } /* switch (result[66] >> 5) { case 0x00: mi->max_gamma_val = 255; mi->gamma_size = 1; break; case 0x01: mi->max_gamma_val = 1023; mi->gamma_size = 2; break; case 0x02: mi->max_gamma_val = 4095; mi->gamma_size = 2; break; case 0x03: mi->max_gamma_val = 65535; mi->gamma_size = 2; break; default: mi->max_gamma_val = 0; mi->gamma_size = 0; DBG(15, "parse_inquiry: Unknown gamma max val! 0x%x\n", result[66]); } */ switch (result[66] >> 5) { case 0x00: mi->max_gamma_bit_depth = 8; mi->gamma_size = 1; break; case 0x01: mi->max_gamma_bit_depth = 10; mi->gamma_size = 2; break; case 0x02: mi->max_gamma_bit_depth = 12; mi->gamma_size = 2; break; case 0x03: mi->max_gamma_bit_depth = 16; mi->gamma_size = 2; break; default: mi->max_gamma_bit_depth = 0; mi->gamma_size = 0; DBG(15, "parse_inquiry: Unknown gamma max val! 0x%x\n", result[66]); } mi->fast_color_preview = (SANE_Byte)(result[67] & 0x01); mi->xfer_format_select = (SANE_Byte)(result[68] & 0x01); mi->color_sequence = (SANE_Byte)(result[69] & 0x7f); mi->does_3pass = (SANE_Byte)(!(result[69] & 0x80)); mi->does_mode1 = (SANE_Byte)(result[71] & 0x01); mi->bit_formats = (SANE_Byte)(result[74] & 0x0F); mi->extra_cap = (SANE_Byte)(result[75] & 0x07); /* XXXXXX a quick hack to disable any [pre/real]cal stuff for anything but an E6... */ if (!((mi->model_code == 0x66) || (mi->model_code == 0x63))) { mi->extra_cap &= ~MI_EXCAP_DIS_RECAL; DBG(4, "parse_inquiry: Not an E6 -- pretend recal cannot be disabled.\n"); } /* The E2 lies... */ if (mi->model_code == 0x64) { DBG(4, "parse_inquiry: The E2 lies about it's 3-pass heritage.\n"); mi->does_3pass = 1; mi->modes &= ~MI_MODES_ONEPASS; } return SANE_STATUS_GOOD; } /********************************************************************/ /* Dump all we know about scanner to stderr */ /********************************************************************/ static SANE_Status dump_inquiry(Microtek_Info *mi, unsigned char *result) { int i; DBG(15, "dump_inquiry...\n"); DBG(1, " === SANE/Microtek backend v%d.%d.%d ===\n", MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH); DBG(1, "========== Scanner Inquiry Block ========mm\n"); for (i=0; i<96; ) { if (!(i % 16)) MDBG_INIT(""); MDBG_ADD("%02x ", (int)result[i++]); if (!(i % 16)) MDBG_FINISH(1); } DBG(1, "========== Scanner Inquiry Report ==========\n"); DBG(1, "===== Scanner ID...\n"); DBG(1, "Device Type Code: 0x%02x\n", mi->device_type); DBG(1, "Model Code: 0x%02x\n", mi->model_code); DBG(1, "Vendor Name: '%s' Model Name: '%s'\n", mi->vendor_id, mi->model_name); DBG(1, "Vendor Specific String: '%s'\n", mi->vendor_string); DBG(1, "Firmware Rev: '%s'\n", mi->revision_num); DBG(1, "SCSI F/W version: %1d.%1d Scanner F/W version: %1d.%1d\n", mi->SCSI_firmware_ver_major, mi->SCSI_firmware_ver_minor, mi->scanner_firmware_ver_major, mi->scanner_firmware_ver_minor); DBG(1, "Response data format: 0x%02x\n", mi->response_data_format); DBG(1, "===== Imaging Capabilities...\n"); DBG(1, "Modes: %s%s%s%s%s%s%s\n", (mi->modes & MI_MODES_LINEART) ? "Lineart " : "", (mi->modes & MI_MODES_HALFTONE) ? "Halftone " : "", (mi->modes & MI_MODES_GRAY) ? "Gray " : "", (mi->modes & MI_MODES_COLOR) ? "Color " : "", (mi->modes & MI_MODES_TRANSMSV) ? "(X-msv) " : "", (mi->modes & MI_MODES_ONEPASS) ? "(OnePass) " : "", (mi->modes & MI_MODES_NEGATIVE) ? "(Negative) " : ""); DBG(1, "Resolution Step Sizes: %s%s Expanded Resolution Support? %s%s\n", (mi->res_step & MI_RESSTEP_1PER) ? "1% " : "", (mi->res_step & MI_RESSTEP_5PER) ? "5%" : "", (mi->expanded_resolution) ? "yes" : "no", (mi->expanded_resolution == 0xFF) ? "(but says no)" : ""); DBG(1, "Supported Bits Per Sample: %s8 %s%s%s\n", (mi->bit_formats & MI_FMT_CAP_4BPP) ? "4 " : "", (mi->bit_formats & MI_FMT_CAP_10BPP) ? "10 " : "", (mi->bit_formats & MI_FMT_CAP_12BPP) ? "12 " : "", (mi->bit_formats & MI_FMT_CAP_16BPP) ? "16 " : ""); DBG(1, "Max. document size code: 0x%02x\n", mi->doc_size_code); DBG(1, "Max. document size: %d x %d pixels\n", mi->max_x, mi->max_y); DBG(1, "Frame units: %s%s\n", (mi->unit_type & MI_UNIT_PIXELS) ? "pixels " : "", (mi->unit_type & MI_UNIT_8TH_INCH) ? "1/8\"'s " : ""); DBG(1, "# of built-in halftones: %d Downloadable patterns? %s\n", mi->pattern_count, (mi->pattern_dwnld) ? "Yes" : "No"); DBG(1, "Data Compression: %s%s\n", (mi->compress_type & MI_COMPRSS_HUFF) ? "huffman " : "", (mi->compress_type & MI_COMPRSS_RD) ? "read-data " : ""); DBG(1, "Contrast Settings: %d Exposure Settings: %d\n", mi->cont_settings, mi->exp_settings); DBG(1, "Adjustable Shadow/Highlight? %s Adjustable Midtone? %s\n", (mi->enhance_cap & MI_ENH_CAP_SHADOW) ? "yes" : "no ", (mi->enhance_cap & MI_ENH_CAP_MIDTONE) ? "yes" : "no "); DBG(1, "Digital brightness/offset? %s\n", (mi->extra_cap & MI_EXCAP_OFF_CTL) ? "yes" : "no"); /* fprintf(stderr, "Gamma Table Size: %d entries of %d bytes (max. value: %d)\n", mi->max_lookup_size, mi->gamma_size, mi->max_gamma_val); */ DBG(1, "Gamma Table Size: %d entries of %d bytes (max. depth: %d)\n", mi->max_lookup_size, mi->gamma_size, mi->max_gamma_bit_depth); DBG(1, "===== Source Options...\n"); DBG(1, "Feed type: %s%s ADF support? %s\n", (mi->feed_type & MI_FEED_FLATBED) ? "flatbed " : "", (mi->feed_type & MI_FEED_EDGEFEED) ? "edge-feed " : "", (mi->feed_type & MI_FEED_AUTOSUPP) ? "yes" : "no"); DBG(1, "Document Feeder Support? %s Feeder Backtracking? %s\n", (mi->source_options & MI_SRC_FEED_SUPP) ? "yes" : "no ", (mi->source_options & MI_SRC_FEED_BT) ? "yes" : "no "); DBG(1, "Feeder Installed? %s Feeder Ready? %s\n", (mi->source_options & MI_SRC_HAS_FEED) ? "yes" : "no ", (mi->source_options & MI_SRC_FEED_RDY) ? "yes" : "no "); DBG(1, "Transparency Adapter Installed? %s\n", (mi->source_options & MI_SRC_HAS_TRANS) ? "yes" : "no "); /* GET_TRANS GET_FEED XXXXXXXXX */ /* mt_SWslct ???? XXXXXXXXXXX */ /*#define DOC_ON_FLATBED 0x00 #define DOC_IN_FEEDER 0x01 #define TRANSPARENCY 0x10 */ DBG(1, "Fast Color Prescan? %s\n", (mi->fast_color_preview) ? "yes" : "no"); DBG(1, "Selectable Transfer Format? %s\n", (mi->xfer_format_select) ? "yes" : "no"); MDBG_INIT("Color Transfer Sequence: "); switch (mi->color_sequence) { case MI_COLSEQ_PLANE: MDBG_ADD("plane-by-plane (3-pass)"); break; case MI_COLSEQ_PIXEL: MDBG_ADD("pixel-by-pixel RGB"); break; case MI_COLSEQ_RGB: MDBG_ADD("line-by-line, R-G-B sequence"); break; case MI_COLSEQ_NONRGB: MDBG_ADD("line-by-line, non-sequential with headers"); break; case MI_COLSEQ_2PIXEL: MDBG_ADD("2pixel-by-2pixel RRGGBB"); break; default: MDBG_ADD("UNKNOWN CODE (0x%02x)", mi->color_sequence); } MDBG_FINISH(1); /* if (mi->modes & MI_MODES_ONEPASS) XXXXXXXXXXX */ DBG(1, "Three pass scan support? %s\n", (mi->does_3pass ? "yes" : "no")); DBG(1, "ModeSelect-1 and ModeSense-1 Support? %s\n", (mi->does_mode1) ? "yes" : "no"); DBG(1, "Can Disable Linearization Table? %s\n", (mi->extra_cap & MI_EXCAP_DIS_LNTBL) ? "yes" : "no"); DBG(1, "Can Disable Start-of-Scan Recalibration? %s\n", (mi->extra_cap & MI_EXCAP_DIS_RECAL) ? "yes" : "no"); DBG(1, "Internal expanded expansion? %s\n", mi->does_expansion ? "yes" : "no"); /* fprintf(stderr, "cntr_vals = %d, min_cntr = %d, max_cntr = %d\n", cntr_vals, min_cntr, max_cntr); fprintf(stderr, "exp_vals = %d, min_exp = %d, max_exp = %d\n", exp_vals, min_exp, max_exp); */ DBG(1, "====== End of Scanner Inquiry Report =======\n"); return SANE_STATUS_GOOD; } /********************************************************************/ /* Dump all we know about some unknown scanner to stderr */ /********************************************************************/ static SANE_Status dump_suspect_inquiry(unsigned char *result) { int i; char vendor_id[64], model_name[64], revision_num[16]; SANE_Byte device_type, model_code; SANE_Byte SCSI_firmware_ver_major, SCSI_firmware_ver_minor; SANE_Byte scanner_firmware_ver_major, scanner_firmware_ver_minor; SANE_Byte response_data_format; DBG(15, "dump_suspect_inquiry...\n"); DBG(1, " === SANE/Microtek backend v%d.%d.%d ===\n", MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH); DBG(1, "========== Scanner Inquiry Block ========mm\n"); for (i=0; i<96; ) { if (!(i % 16)) MDBG_INIT(""); MDBG_ADD("%02x ", (int)result[i++]); if (!(i % 16)) MDBG_FINISH(1); } #if 0 for (i=0; i<96; i++) { if (!(i % 16) && (i)) fprintf(stderr, "\n"); fprintf(stderr, "%02x ", (int)result[i]); } fprintf(stderr, "\n\n"); #endif strncpy(vendor_id, (char *)&result[8], 8); strncpy(model_name, (char *)&result[16], 16); strncpy(revision_num, (char *)&result[32], 4); vendor_id[8] = 0; model_name[16] = 0; revision_num[5] = 0; device_type = (SANE_Byte)(result[0] & 0x1f); SCSI_firmware_ver_major = (SANE_Byte)((result[1] & 0xf0) >> 4); SCSI_firmware_ver_minor = (SANE_Byte)(result[1] & 0x0f); scanner_firmware_ver_major = (SANE_Byte)((result[2] & 0xf0) >> 4); scanner_firmware_ver_minor = (SANE_Byte)(result[2] & 0x0f); response_data_format = (SANE_Byte)(result[3]); model_code = (SANE_Byte)(result[62]); DBG(1, "========== Scanner Inquiry Report ==========\n"); DBG(1, "===== Scanner ID...\n"); DBG(1, "Device Type Code: 0x%02x\n", device_type); DBG(1, "Model Code: 0x%02x\n", model_code); DBG(1, "Vendor Name: '%s' Model Name: '%s'\n", vendor_id, model_name); DBG(1, "Firmware Rev: '%s'\n", revision_num); DBG(1, "SCSI F/W version: %1d.%1d Scanner F/W version: %1d.%1d\n", SCSI_firmware_ver_major, SCSI_firmware_ver_minor, scanner_firmware_ver_major, scanner_firmware_ver_minor); DBG(1, "Response data format: 0x%02x\n", response_data_format); DBG(1, "====== End of Scanner Inquiry Report =======\n"); return SANE_STATUS_GOOD; } /********************************************************************/ /* Determine if device is a Microtek Scanner (from INQUIRY info) */ /********************************************************************/ static SANE_Status id_microtek(uint8_t *result, char **model_string) { SANE_Byte device_type, response_data_format; int forcewarn = 0; DBG(15, "id_microtek...\n"); /* check device type first... */ device_type = (SANE_Byte)(result[0] & 0x1f); if (device_type != 0x06) { DBG(15, "id_microtek: not even a scanner: dev_type = %d\n", device_type); return SANE_STATUS_INVAL; } if (!(strncmp("MICROTEK", (char *)&(result[8]), 8)) || !(strncmp("MII SC31", (char *)&(result[8]), 8)) || /* the IISP */ !(strncmp("MII SC21", (char *)&(result[8]), 8)) || /* the 600ZS */ !(strncmp("MII SC23", (char *)&(result[8]), 8)) || /* the other 600ZS */ !(strncmp("MII SC25", (char *)&(result[8]), 8)) || /* some other 600GS */ !(strncmp("AGFA ", (char *)&(result[8]), 8)) || /* Arcus II */ !(strncmp("Microtek", (char *)&(result[8]), 8)) || /* some 35t+'s */ !(strncmp("Polaroid", (char *)&(result[8]), 8)) || /* SprintScan 35LE */ !(strncmp(" ", (char *)&(result[8]), 8)) ) { switch (result[62]) { case 0x16 : *model_string = "ScanMaker 600ZS"; break; case 0x50 : *model_string = "ScanMaker II/IIXE"; break; case 0x51 : *model_string = "ScanMaker 45t"; break; case 0x52 : *model_string = "ScanMaker 35t"; break; case 0x54 : *model_string = "ScanMaker IISP"; break; case 0x55 : *model_string = "ScanMaker IIER"; break; case 0x56 : *model_string = "ScanMaker A3t"; break; case 0x57 : *model_string = "ScanMaker IIHR"; break; case 0x58 : *model_string = "ScanMaker IIG"; break; case 0x59 : *model_string = "ScanMaker III"; break; case 0x5A : *model_string = "Agfa StudioScan"; break; case 0x5B : *model_string = "Agfa StudioScan II"; break; case 0x5C : *model_string = "Agfa Arcus II"; break; case 0x5f : *model_string = "ScanMaker E3"; break; case 0x62 : if (!(strncmp("Polaroid", (char *)&(result[8]), 8))) *model_string = "Polaroid SprintScan 35/LE"; else *model_string = "ScanMaker 35t+"; break; case 0x63 : case 0x66 : *model_string = "ScanMaker E6"; break; case 0x64 : /* and "Vobis RealScan" */ *model_string = "ScanMaker E2"; break; case 0x65: *model_string = "Color PageWiz"; break; case 0xC8: *model_string = "ScanMaker 600ZS"; break; /* the follow are listed in the docs, but are otherwise a mystery... */ case 0x5D: *model_string = "Agfa DuoScan"; forcewarn = 1; break; case 0x5E: *model_string = "SS3"; forcewarn = 1; break; case 0x60: *model_string = "HR1"; forcewarn = 1; break; case 0x61: *model_string = "45T+"; forcewarn = 1; break; case 0x67: *model_string = "TR3"; forcewarn = 1; break; default : /* this might be a newer scanner, which uses the SCSI II command set. */ /* that's unfortunate, but we'll warn the user anyway.... */ response_data_format = (SANE_Byte)(result[3]); if (response_data_format == 0x02) { DBG(15, "id_microtek: (uses new SCSI II command set)\n"); if (DBG_LEVEL >= 15) { DBG(1, "\n"); DBG(1, "\n"); DBG(1, "\n"); DBG(1, "========== Congratulations! ==========\n"); DBG(1, "You appear to be the proud owner of a \n"); DBG(1, "brand-new Microtek scanner, which uses\n"); DBG(1, "a new SCSI II command set. \n"); DBG(1, "\n"); DBG(1, "Try the `microtek2' backend instead. \n"); DBG(1, "\n"); DBG(1, "\n"); DBG(1, "\n"); } } return SANE_STATUS_INVAL; } if (forcewarn) { /* force debugging on, to encourage user to send in a report */ #ifndef NDEBUG DBG_LEVEL = 1; #endif DBG(1, "\n"); DBG(1, "\n"); DBG(1, "\n"); DBG(1, "========== Congratulations! ==========\n"); DBG(1, "Your scanner appears to be supported \n"); DBG(1, "by the microtek backend. However, it \n"); DBG(1, "has never been tried before, and some \n"); DBG(1, "parameters are bound to be wrong. \n"); DBG(1, "\n"); DBG(1, "Please send the scanner inquiry log in\n"); DBG(1, "its entirety to mtek-bugs@mir.com and \n"); DBG(1, "include a description of the scanner, \n"); DBG(1, "including the base optical resolution.\n"); DBG(1, "\n"); DBG(1, "You'll find complete instructions for \n"); DBG(1, "submitting an error/debug log in the \n"); DBG(1, "'sane-microtek' man-page. \n"); DBG(1, "\n"); DBG(1, "\n"); DBG(1, "\n"); } return SANE_STATUS_GOOD; } DBG(15, "id_microtek: not microtek: %d, %d, %d\n", strncmp("MICROTEK", (char *)&(result[8]), 8), strncmp(" ", (char *)&(result[8]), 8), result[62]); return SANE_STATUS_INVAL; } /********************************************************************/ /* Try to attach a device as a Microtek scanner */ /********************************************************************/ static SANE_Status attach_scanner(const char *devicename, Microtek_Device **devp) { Microtek_Device *dev; int sfd; size_t size; unsigned char result[0x60]; SANE_Status status; char *model_string; uint8_t inquiry[] = { 0x12, 0, 0, 0, 0x60, 0 }; DBG(15,"attach_scanner: %s\n", devicename); /* check if device is already known... */ for (dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, devicename) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } } /* open scsi device... */ DBG(20, "attach_scanner: opening %s\n", devicename); if (sanei_scsi_open(devicename, &sfd, sense_handler, NULL) != 0) { DBG(20, "attach_scanner: open failed\n"); return SANE_STATUS_INVAL; } /* say hello... */ DBG(20, "attach_scanner: sending INQUIRY\n"); size = sizeof(result); status = sanei_scsi_cmd(sfd, inquiry, sizeof(inquiry), result, &size); sanei_scsi_close (sfd); if (status != SANE_STATUS_GOOD || size != 0x60) { DBG(20, "attach_scanner: inquiry failed (%s)\n", sane_strstatus (status)); return status; } if (id_microtek(result, &model_string) != SANE_STATUS_GOOD) { DBG(15, "attach_scanner: device doesn't look like a Microtek scanner."); if (DBG_LEVEL >= 5) dump_suspect_inquiry(result); return SANE_STATUS_INVAL; } dev=malloc(sizeof(*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset(dev, 0, sizeof(*dev)); parse_inquiry(&(dev->info), result); if (DBG_LEVEL > 0) dump_inquiry(&(dev->info), result); /* initialize dev structure */ dev->sane.name = strdup(devicename); dev->sane.vendor = "Microtek"; dev->sane.model = strdup(model_string); dev->sane.type = "flatbed scanner"; /* link into device list... */ ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG(15, "attach_scanner: happy.\n"); return SANE_STATUS_GOOD; } /********************************************************************/ /* Attach a scanner (convenience wrapper for find_scanners...) */ /********************************************************************/ static SANE_Status attach_one (const char *dev) { attach_scanner (dev, 0); return SANE_STATUS_GOOD; } /********************************************************************/ /* End a scan, and clean up afterwards */ /********************************************************************/ static SANE_Status end_scan(Microtek_Scanner *s, SANE_Status ostat) { SANE_Status status; DBG(15, "end_scan...\n"); if (s->scanning) { s->scanning = SANE_FALSE; /* stop the scanner */ if (s->scan_started) { status = stop_scan(s); if (status != SANE_STATUS_GOOD) DBG(23, "end_scan: OY! on stop_scan\n"); s->scan_started = SANE_FALSE; } /* close the SCSI device */ if (s->sfd != -1) { sanei_scsi_close(s->sfd); s->sfd = -1; } /* free the buffers we malloc'ed */ if (s->scsi_buffer != NULL) { free(s->scsi_buffer); s->scsi_buffer = NULL; } if (s->rb != NULL) { ring_free(s->rb); s->rb = NULL; } } /* if this -was- pass 3, or cancel, then we must be done */ if ((s->this_pass == 3) || (s->cancel)) s->this_pass = 0; return ostat; } /********************************************************************/ /********************************************************************/ /***** Scan-time operations *****/ /********************************************************************/ /********************************************************************/ /* number of lines of calibration data returned by scanner */ #define STRIPS 12 /* well, that's what it seems to be for the E6 */ /* simple comparison for the qsort below */ static int comparo(const void *a, const void *b) { return (*(const int *)a - *(const int *)b); } /* extract values from scanlines and sort */ static void sort_values(int *result, uint8_t *scanline[], int pix) { int i; for (i=0; i= bot) && (sorted[j] <= top)) { sum += sorted[j]; count++; } } if (count) caldata[i] = (sum + (count / 2)) / count; else { DBG(23, "zero: i=%d b/t=%d/%d ", i, bot, top); if (DBG_LEVEL >= 23) { MDBG_INIT(""); for (j=0; j 0; nleft -= ntoget, spot += buffsize) { ntoget = (nleft > nmax) ? nmax : nleft; buffsize = ntoget * 3 * linewidth; DBG(23, "...nleft %d toget %d size %lu spot %d input+spot %p\n", nleft, ntoget, (u_long) buffsize, spot, input+spot); if ((statusA = read_scan_data(s, ntoget, input+spot, &buffsize)) != SANE_STATUS_GOOD) { DBG(23, "...read scan failed\n"); break; } } status = stop_scan(s); if ((statusA != SANE_STATUS_GOOD) || (status != SANE_STATUS_GOOD)) { free(input); free(combuff); return ((statusA != SANE_STATUS_GOOD) ? statusA : status); } /* calculate calibration data for each element and download */ for (letter = 'R'; letter != 'X'; ) { DBG(23, "do_real_calibrate: working on %c\n", letter); for (spot=0, i=0; spot < linewidth * STRIPS * 3; spot += linewidth) { if (input[spot+1] == letter) { DBG(23, " found %d (at %d)\n", i, spot); if (i >= STRIPS) { DBG(23, "WHOA!!! %i have already been found!\n", i); break; } scanline[i] = &(input[spot+2]); i++; } } calc_calibration(combuff + 8, scanline, linewidth - 2); if ((status = download_calibration(s, combuff, letter, linewidth)) != SANE_STATUS_GOOD) { DBG(23, "...download_calibration failed\n"); free(input); free(combuff); return status; } switch (letter) { case 'R': letter = 'G'; break; case 'G': letter = 'B'; break; case 'B': default: letter = 'X'; break; } } /* clean up */ free(input); free(combuff); return SANE_STATUS_GOOD; } /********************************************************************/ /* Cause scanner to calibrate, but don't really scan anything */ /* (i.e. do everything but read data) */ /********************************************************************/ static SANE_Status do_precalibrate(SANE_Handle handle) { Microtek_Scanner *s = handle; SANE_Status status, statusA; SANE_Int busy, linewidth, lines; DBG(10, "do_precalibrate...\n"); if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status; { SANE_Int y1 = s->y1; SANE_Int y2 = s->y2; /* some small range, but large enough to cause the scanner to think it'll scan *something*... */ s->y1 = 0; s->y2 = (s->resolution > s->dev->info.base_resolution) ? 4 : 4 * s->dev->info.base_resolution / s->resolution; status = scanning_frame(s); s->y1 = y1; s->y2 = y2; if (status != SANE_STATUS_GOOD) return status; } if (s->dev->info.source_options & (MI_SRC_FEED_BT | MI_SRC_HAS_TRANS | MI_SRC_FEED_SUPP | MI_SRC_HAS_FEED)) { /* ZZZZZZZZZZZ */ if ((status = accessory(s)) != SANE_STATUS_GOOD) return status; } if ((status = mode_select(s)) != SANE_STATUS_GOOD) return status; /* why would we even try if this were not true?... */ /*if (s->dev->info.extra_cap & MI_EXCAP_DIS_RECAL) */ { SANE_Bool allow_calibrate = s->allow_calibrate; s->allow_calibrate = SANE_TRUE; status = mode_select_1(s); s->allow_calibrate = allow_calibrate; if (status != SANE_STATUS_GOOD) return status; } if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status; if ((status = start_scan(s)) != SANE_STATUS_GOOD) return status; if ((statusA = get_scan_status(s, &busy, &linewidth, &lines)) != SANE_STATUS_GOOD) { DBG(10, "do_precalibrate: get_scan_status fails\n"); } if ((status = stop_scan(s)) != SANE_STATUS_GOOD) return status; if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return status; DBG(10, "do_precalibrate done.\n"); if (statusA != SANE_STATUS_GOOD) return statusA; else return SANE_STATUS_GOOD; } /********************************************************************/ /* Calibrate scanner, if necessary; record results */ /********************************************************************/ static SANE_Status finagle_precal(SANE_Handle handle) { Microtek_Scanner *s = handle; SANE_Status status; int match; /* try to check if scanner has been reset */ /* if so, calibrate it (either for real, or via a fake scan, with calibration */ /* (but only bother if you *could* disable calibration) */ DBG(23, "finagle_precal...\n"); if ((s->do_clever_precal) || (s->do_real_calib)) { if ((status = compare_mode_sense(s, &match)) != SANE_STATUS_GOOD) return status; if (((s->do_real_calib) && (!s->calib_once)) || /* user want recal */ (!match) || /* or, possible reset */ ((s->mode == MS_MODE_COLOR) && /* or, other weirdness */ (s->precal_record < MS_PRECAL_COLOR)) || ((s->mode == MS_MODE_COLOR) && (s->expandedresolution) && (s->precal_record < MS_PRECAL_EXP_COLOR))) { DBG(23, "finagle_precal: must precalibrate!\n"); s->precal_record = MS_PRECAL_NONE; if (s->do_real_calib) { /* do a real calibration if allowed */ if ((status = do_real_calibrate(s)) != SANE_STATUS_GOOD) return status; } else if (s->do_clever_precal) {/* otherwise do the fake-scan version */ if ((status = do_precalibrate(s)) != SANE_STATUS_GOOD) return status; } if (s->mode == MS_MODE_COLOR) { if (s->expandedresolution) s->precal_record = MS_PRECAL_EXP_COLOR; else s->precal_record = MS_PRECAL_COLOR; } else s->precal_record = MS_PRECAL_GRAY; } else DBG(23, "finagle_precal: no precalibrate necessary.\n"); } return SANE_STATUS_GOOD; } /********************************************************************/ /* Set pass-dependent parameters (for 3-pass color scans) */ /********************************************************************/ static void set_pass_parameters (SANE_Handle handle) { Microtek_Scanner *s = handle; if (s->threepasscolor) { s->this_pass += 1; DBG(23, "set_pass_parameters: three-pass, on %d\n", s->this_pass); switch (s->this_pass) { case 1: s->filter = MS_FILT_RED; s->params.format = SANE_FRAME_RED; s->params.last_frame = SANE_FALSE; break; case 2: s->filter = MS_FILT_GREEN; s->params.format = SANE_FRAME_GREEN; s->params.last_frame = SANE_FALSE; break; case 3: s->filter = MS_FILT_BLUE; s->params.format = SANE_FRAME_BLUE; s->params.last_frame = SANE_TRUE; break; default: s->filter = MS_FILT_CLEAR; DBG(23, "set_pass_parameters: What?!? pass %d = filter?\n", s->this_pass); break; } } else s->this_pass = 0; } /********************************************************************/ /********************************************************************/ /***** Packing functions *****/ /***** ...process raw scanner bytes, and shove into *****/ /***** the ring buffer *****/ /********************************************************************/ /********************************************************************/ /********************************************************************/ /* Process flat (byte-by-byte) data */ /********************************************************************/ static SANE_Status pack_flat_data(Microtek_Scanner *s, size_t nlines) { SANE_Status status; ring_buffer *rb = s->rb; size_t nbytes = nlines * rb->bpl; size_t start = (rb->head_complete + rb->complete_count) % rb->size; size_t max_xfer = (start < rb->head_complete) ? (rb->head_complete - start) : (rb->size - start + rb->head_complete); size_t length = MIN(nbytes, max_xfer); if (nbytes > max_xfer) { DBG(23, "pack_flat: must expand ring, %lu + %lu\n", (u_long)rb->size, (u_long)(nbytes - max_xfer)); status = ring_expand(rb, (nbytes - max_xfer)); if (status != SANE_STATUS_GOOD) return status; } if (s->doexpansion) { unsigned int line, bit; SANE_Byte *sb, *db, byte; size_t pos; sb = s->scsi_buffer; db = rb->base; pos = start; if (!(s->multibit)) { for (line=0; lineexp_aspect, n1 = 0.0, n2 = floor(x2); i < rb->bpl; i++) { byte = 0; for (bit=0; bit < 8; bit++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) { /* #define getbit(byte, index) (((byte)>>(index))&1) */ byte |= (( (x2 == n2) ? (((sb[(int)n1 / 8])>>(7 - ((int)n1) % 8))&1) : (((double)(((sb[(int)n1/8])>>(7-(int)n1%8))&1) * (n2 - x1) + (double)(((sb[(int)n2/8])>>(7-(int)n2%8))&1) * (x2 - n2) ) / s->exp_aspect) ) > 0.5) << (7 - bit); } db[pos] = byte; if (++pos >= rb->size) pos = 0; } sb += s->pixel_bpl; } } else { /* multibit scan (8 is assumed!) */ for (line=0; lineexp_aspect, n1 = 0.0, n2 = floor(x2); i < s->dest_ppl; i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) { db[pos] = (x2 == n2) ? sb[(int)n1] : (int)(((double)sb[(int)n1] * (n2 - x1) + (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect); if (++pos >= rb->size) pos = 0; } sb += s->pixel_bpl; } } } else { /* adjust for rollover!!! */ if ((start + length) < rb->size) { memcpy(rb->base + start, s->scsi_buffer, length); } else { size_t chunk1 = rb->size - start; size_t chunk2 = length - chunk1; memcpy(rb->base + start, s->scsi_buffer, chunk1); memcpy(rb->base, s->scsi_buffer + chunk1, chunk2); } } rb->complete_count += length; return SANE_STATUS_GOOD; } /********************************************************************/ /* Process sequential R-G-B scan lines (who uses this??? ) */ /********************************************************************/ static SANE_Status pack_seqrgb_data (Microtek_Scanner *s, size_t nlines) { ring_buffer *rb = s->rb; unsigned int seg; SANE_Byte *db = rb->base; SANE_Byte *sb = s->scsi_buffer; size_t completed; size_t spot; SANE_Byte id; { size_t ar, ag, ab; /* allowed additions */ size_t dr, dg, db; /* additions which will occur */ SANE_Status status; dr = dg = db = nlines * rb->bpl; ar = rb->size - (rb->complete_count + rb->red_extra * 3); ag = rb->size - (rb->complete_count + rb->green_extra * 3); ab = rb->size - (rb->complete_count + rb->blue_extra * 3); DBG(23, "pack_seq: dr/ar: %lu/%lu dg/ag: %lu/%lu db/ab: %lu/%lu\n", (u_long)dr, (u_long)ar, (u_long)dg, (u_long)ag, (u_long)db, (u_long)ab); if ((dr > ar) || (dg > ag) || (db > ab)) { size_t increase = 0; if (dr > ar) increase = (dr - ar); if (dg > ag) increase = MAX(increase, (dg - ag)); if (db > ab) increase = MAX(increase, (db - ab)); DBG(23, "pack_seq: must expand ring, %lu + %lu\n", (u_long)rb->size, (u_long)increase); status = ring_expand(rb, increase); if (status != SANE_STATUS_GOOD) return status; } } for (seg = 0, id = 0; seg < nlines * 3; seg++, id = (id+1)%3) { switch (id) { case 0: spot = rb->tail_red; break; case 1: spot = rb->tail_green; break; case 2: spot = rb->tail_blue; break; default: DBG(18, "pack_seq: missing scanline RGB header!\n"); return SANE_STATUS_IO_ERROR; } if (s->doexpansion) { int i; double x1, x2, n1, n2; for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2); i < s->dest_ppl; i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) { db[spot] = (x2 == n2) ? sb[(int)n1] : (int)(((double)sb[(int)n1] * (n2 - x1) + (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect); if ((spot += 3) >= rb->size) spot -= rb->size; } sb += s->ppl; } else { size_t i; for (i=0; i < rb->ppl; i++) { db[spot] = *sb; sb++; if ((spot += 3) >= rb->size) spot -= rb->size; } } switch (id) { case 0: rb->tail_red = spot; rb->red_extra += rb->ppl; break; case 1: rb->tail_green = spot; rb->green_extra += rb->ppl; break; case 2: rb->tail_blue = spot; rb->blue_extra += rb->ppl; break; } } completed = MIN(rb->red_extra, MIN(rb->green_extra, rb->blue_extra)); rb->complete_count += completed * 3; /* 3 complete bytes per pixel! */ rb->red_extra -= completed; rb->green_extra -= completed; rb->blue_extra -= completed; DBG(18, "pack_seq: extra r: %lu g: %lu b: %lu\n", (u_long)rb->red_extra, (u_long)rb->green_extra, (u_long)rb->blue_extra); DBG(18, "pack_seq: completed: %lu complete: %lu\n", (u_long)completed, (u_long)rb->complete_count); return SANE_STATUS_GOOD; } /********************************************************************/ /* Process non-sequential R,G, and B scan-lines */ /********************************************************************/ static SANE_Status pack_goofyrgb_data(Microtek_Scanner *s, size_t nlines) { ring_buffer *rb = s->rb; unsigned int seg; /* , i;*/ SANE_Byte *db; SANE_Byte *sb = s->scsi_buffer; size_t completed; size_t spot; SANE_Byte id; /* prescan to decide if ring should be expanded */ { size_t ar, ag, ab; /* allowed additions */ size_t dr, dg, db; /* additions which will occur */ SANE_Status status; SANE_Byte *pt; for (dr = dg = db = 0, seg = 0, pt = s->scsi_buffer + 1; seg < nlines * 3; seg++, pt += s->ppl + 2) { switch (*pt) { case 'R': dr += rb->bpl; break; case 'G': dg += rb->bpl; break; case 'B': db += rb->bpl; break; } } ar = rb->size - (rb->complete_count + rb->red_extra * 3); ag = rb->size - (rb->complete_count + rb->green_extra * 3); ab = rb->size - (rb->complete_count + rb->blue_extra * 3); DBG(23, "pack_goofy: dr/ar: %lu/%lu dg/ag: %lu/%lu db/ab: %lu/%lu\n", (u_long)dr, (u_long)ar, (u_long)dg, (u_long)ag, (u_long)db, (u_long)ab); /* >, or >= ???????? */ if ((dr > ar) || (dg > ag) || (db > ab)) { size_t increase = 0; if (dr > ar) increase = (dr - ar); if (dg > ag) increase = MAX(increase, (dg - ag)); if (db > ab) increase = MAX(increase, (db - ab)); DBG(23, "pack_goofy: must expand ring, %lu + %lu\n", (u_long)rb->size, (u_long)increase); status = ring_expand(rb, increase); if (status != SANE_STATUS_GOOD) return status; } } db = rb->base; for (seg = 0; seg < nlines * 3; seg++) { sb++; /* skip first byte in line (two byte header) */ id = *sb; switch (id) { case 'R': spot = rb->tail_red; break; case 'G': spot = rb->tail_green; break; case 'B': spot = rb->tail_blue; break; default: DBG(18, "pack_goofy: missing scanline RGB header!\n"); return SANE_STATUS_IO_ERROR; } sb++; /* skip the other header byte */ if (s->doexpansion) { int i; double x1, x2, n1, n2; for (i = 0, x1 = 0.0, x2 = s->exp_aspect, n1 = 0.0, n2 = floor(x2); i < s->dest_ppl; i++, x1 = x2, n1 = n2, x2 += s->exp_aspect, n2 = floor(x2)) { db[spot] = (x2 == n2) ? sb[(int)n1] : (int)(((double)sb[(int)n1] * (n2 - x1) + (double)sb[(int)n2] * (x2 - n2)) / s->exp_aspect); if ((spot += 3) >= rb->size) spot -= rb->size; } sb += s->ppl; } else { unsigned int i; for (i=0; i < rb->ppl; i++) { db[spot] = *sb; sb++; if ((spot += 3) >= rb->size) spot -= rb->size; } } switch (id) { case 'R': rb->tail_red = spot; rb->red_extra += rb->ppl; break; case 'G': rb->tail_green = spot; rb->green_extra += rb->ppl; break; case 'B': rb->tail_blue = spot; rb->blue_extra += rb->ppl; break; } } completed = MIN(rb->red_extra, MIN(rb->green_extra, rb->blue_extra)); rb->complete_count += completed * 3; /* 3 complete bytes per pixel! */ rb->red_extra -= completed; rb->green_extra -= completed; rb->blue_extra -= completed; DBG(18, "pack_goofy: extra r: %lu g: %lu b: %lu\n", (u_long)rb->red_extra, (u_long)rb->green_extra, (u_long)rb->blue_extra); DBG(18, "pack_goofy: completed: %lu complete: %lu\n", (u_long)completed, (u_long)rb->complete_count); return SANE_STATUS_GOOD; } /********************************************************************/ /* Process R1R2-G1G2-B1B2 double pixels (AGFA StudioStar) */ /********************************************************************/ static SANE_Status pack_seq2r2g2b_data(Microtek_Scanner *s, size_t nlines) { SANE_Status status; ring_buffer *rb = s->rb; size_t nbytes = nlines * rb->bpl; size_t start = (rb->head_complete + rb->complete_count) % rb->size; size_t max_xfer = (start < rb->head_complete) ? (rb->head_complete - start) : (rb->size - start + rb->head_complete); size_t length = MIN(nbytes, max_xfer); if (nbytes > max_xfer) { DBG(23, "pack_2r2g2b: must expand ring, %lu + %lu\n", (u_long)rb->size, (u_long)(nbytes - max_xfer)); status = ring_expand(rb, (nbytes - max_xfer)); if (status != SANE_STATUS_GOOD) return status; } { unsigned int line; int p; size_t pos = start; SANE_Byte *sb = s->scsi_buffer; SANE_Byte *db = rb->base; for (line = 0; line < nlines; line++) { for (p = 0; p < s->dest_ppl; p += 2){ /* first pixel */ db[pos] = sb[0]; if (++pos >= rb->size) pos = 0; /* watch out for ringbuff end? */ db[pos] = sb[2]; if (++pos >= rb->size) pos = 0; db[pos] = sb[4]; if (++pos >= rb->size) pos = 0; /* second pixel */ db[pos] = sb[1]; if (++pos >= rb->size) pos = 0; db[pos] = sb[3]; if (++pos >= rb->size) pos = 0; db[pos] = sb[5]; if (++pos >= rb->size) pos = 0; sb += 6; } } } rb->complete_count += length; return SANE_STATUS_GOOD; } /********************************************************************/ /********************************************************************/ /***** the basic scanning chunks for sane_read() *****/ /********************************************************************/ /********************************************************************/ /********************************************************************/ /* Request bytes from scanner (and put in scsi_buffer) */ /********************************************************************/ static SANE_Status read_from_scanner (Microtek_Scanner *s, int *nlines) { SANE_Status status; SANE_Int busy, linewidth, remaining; size_t buffsize; DBG(23, "read_from_scanner...\n"); if (s->unscanned_lines > 0) { status = get_scan_status(s, &busy, &linewidth, &remaining); if (status != SANE_STATUS_GOOD) { DBG(18, "read_from_scanner: bad get_scan_status!\n"); return status; } DBG(18, "read_from_scanner: gss busy, linewidth, remaining: %d, %d, %d\n", busy, linewidth, remaining); } else { DBG(18, "read_from_scanner: no gss/no unscanned\n"); remaining = 0; } *nlines = MIN(remaining, s->max_scsi_lines); DBG(18, "sane_read: max_scsi: %d, rem: %d, nlines: %d\n", s->max_scsi_lines, remaining, *nlines); /* grab them bytes! (only if the scanner still has bytes to give...) */ if (*nlines > 0) { buffsize = *nlines * (s->pixel_bpl + s->header_bpl);/* == "* linewidth" */ status = read_scan_data(s, *nlines, s->scsi_buffer, &buffsize); if (status != SANE_STATUS_GOOD) { DBG(18, "sane_read: bad read_scan_data!\n"); return status; } s->unscanned_lines -= *nlines; DBG(18, "sane_read: buffsize: %lu, unscanned: %d\n", (u_long) buffsize, s->unscanned_lines); } return SANE_STATUS_GOOD; } /********************************************************************/ /* Process scanner bytes, and shove in ring_buffer */ /********************************************************************/ static SANE_Status pack_into_ring(Microtek_Scanner *s, int nlines) { SANE_Status status; DBG(23, "pack_into_ring...\n"); switch (s->line_format) { case MS_LNFMT_FLAT: status = pack_flat_data(s, nlines); break; case MS_LNFMT_SEQ_RGB: status = pack_seqrgb_data(s, nlines); break; case MS_LNFMT_GOOFY_RGB: status = pack_goofyrgb_data(s, nlines); break; case MS_LNFMT_SEQ_2R2G2B: status = pack_seq2r2g2b_data(s, nlines); break; default: status = SANE_STATUS_JAMMED; } return status; } /********************************************************************/ /* Pack processed image bytes into frontend destination buffer */ /********************************************************************/ static SANE_Int pack_into_dest(SANE_Byte *dest_buffer, size_t dest_length, ring_buffer *rb) { size_t ret_length = MIN(rb->complete_count, dest_length); DBG(23, "pack_into_dest...\n"); DBG(23, "pack_into_dest: rl: %lu sz: %lu hc: %lu\n", (u_long)ret_length, (u_long)rb->size, (u_long)rb->head_complete); /* adjust for rollover!!! */ if ((rb->head_complete + ret_length) < rb->size) { memcpy(dest_buffer, rb->base + rb->head_complete, ret_length); rb->head_complete += ret_length; } else { size_t chunk1 = rb->size - rb->head_complete; size_t chunk2 = ret_length - chunk1; memcpy(dest_buffer, rb->base + rb->head_complete, chunk1); memcpy(dest_buffer + chunk1, rb->base, chunk2); rb->head_complete = chunk2; } rb->complete_count -= ret_length; return ret_length; } /********************************************************************/ /********************************************************************/ /****** "Registered" SANE API Functions *****************************/ /********************************************************************/ /********************************************************************/ /********************************************************************/ /* sane_init() */ /********************************************************************/ SANE_Status sane_init(SANE_Int *version_code, SANE_Auth_Callback authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; authorize = authorize; DBG_INIT(); DBG(1, "sane_init: MICROTEK says hello! (v%d.%d.%d)\n", MICROTEK_MAJOR, MICROTEK_MINOR, MICROTEK_PATCH); /* return the SANE version we got compiled under */ if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); /* parse config file */ fp = sanei_config_open (MICROTEK_CONFIG_FILE); if (!fp) { /* default to /dev/scanner instead of insisting on config file */ DBG(1, "sane_init: missing config file '%s'\n", MICROTEK_CONFIG_FILE); attach_scanner("/dev/scanner", 0); return SANE_STATUS_GOOD; } while (sanei_config_read(dev_name, sizeof (dev_name), fp)) { DBG(23, "sane_init: config-> %s\n", dev_name); if (dev_name[0] == '#') continue; /* ignore comments */ if (!(strncmp("noprecal", dev_name, 8))) { DBG(23, "sane_init: Clever Precalibration will be forcibly disabled...\n"); inhibit_clever_precal = SANE_TRUE; continue; } if (!(strncmp("norealcal", dev_name, 9))) { DBG(23, "sane_init: Real calibration will be forcibly disabled...\n"); inhibit_real_calib = SANE_TRUE; continue; } len = strlen (dev_name); if (!len) continue; /* ignore empty lines */ sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); return SANE_STATUS_GOOD; } /********************************************************************/ /* sane_get_devices */ /********************************************************************/ SANE_Status sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only) { Microtek_Device *dev; int i; local_only = local_only; DBG(10, "sane_get_devices\n"); /* we keep an internal copy */ if (devlist) free(devlist); /* hmm, free it if we want a new one, I guess. YYYYY*/ devlist = malloc((num_devices + 1) * sizeof(devlist[0])); if (!devlist) return SANE_STATUS_NO_MEM; for (i=0, dev=first_dev; i < num_devices; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = 0; *device_list = devlist; return SANE_STATUS_GOOD; } /********************************************************************/ /* sane_open */ /********************************************************************/ SANE_Status sane_open(SANE_String_Const devicename, SANE_Handle *handle) { Microtek_Scanner *scanner; Microtek_Device *dev; SANE_Status status; DBG(10, "sane_open\n"); /* find device... */ DBG(23, "sane_open: find device...\n"); if (devicename[0]) { for (dev = first_dev; dev; dev = dev->next) { if (strcmp(dev->sane.name, devicename) == 0) break; } if (!dev) { /* not in list, try manually... */ status = attach_scanner(devicename, &dev); if (status != SANE_STATUS_GOOD) return status; } } else { /* no device specified, so use first */ dev = first_dev; } if (!dev) return SANE_STATUS_INVAL; /* create a scanner... */ DBG(23, "sane_open: create scanner...\n"); scanner = malloc(sizeof(*scanner)); if (!scanner) return SANE_STATUS_NO_MEM; memset(scanner, 0, sizeof(*scanner)); /* initialize scanner dependent stuff */ DBG(23, "sane_open: initialize scanner dependent stuff...\n"); /* ZZZZZZZZZZZZZZ */ scanner->unit_type = (dev->info.unit_type & MI_UNIT_PIXELS) ? MS_UNIT_PIXELS : MS_UNIT_18INCH; scanner->res_type = (dev->info.res_step & MI_RESSTEP_1PER) ? MS_RES_1PER : MS_RES_5PER; scanner->midtone_support = (dev->info.enhance_cap & MI_ENH_CAP_MIDTONE) ? SANE_TRUE : SANE_FALSE; scanner->paper_length = (scanner->unit_type == MS_UNIT_PIXELS) ? dev->info.max_y : (SANE_Int)((double)dev->info.max_y * 8.0 / (double)dev->info.base_resolution); /* (SANE_Int)(SANE_UNFIX(dev->info.max_y) * dev->info.base_resolution) : (SANE_Int)(SANE_UNFIX(dev->info.max_y) * 8); ZZZZZZZ */ scanner->bright_r = 0; scanner->bright_g = 0; scanner->bright_b = 0; /* calibration shenanigans */ if ((dev->info.extra_cap & MI_EXCAP_DIS_RECAL) && (!(inhibit_real_calib))) { DBG(23, "sane_open: Real calibration enabled.\n"); scanner->allow_calibrate = SANE_FALSE; scanner->do_real_calib = SANE_TRUE; scanner->do_clever_precal = SANE_FALSE; } else if ((dev->info.extra_cap & MI_EXCAP_DIS_RECAL) && (!(inhibit_clever_precal))) { DBG(23, "sane_open: Clever precalibration enabled.\n"); scanner->allow_calibrate = SANE_FALSE; scanner->do_real_calib = SANE_FALSE; scanner->do_clever_precal = SANE_TRUE; } else { DBG(23, "sane_open: All calibration routines disabled.\n"); scanner->allow_calibrate = SANE_TRUE; scanner->do_real_calib = SANE_FALSE; scanner->do_clever_precal = SANE_FALSE; } scanner->onepass = (dev->info.modes & MI_MODES_ONEPASS); scanner->allowbacktrack = SANE_TRUE; /* ??? XXXXXXX */ scanner->reversecolors = SANE_FALSE; scanner->fastprescan = SANE_FALSE; scanner->bits_per_color = 8; /* init gamma tables */ if (dev->info.max_lookup_size) { int j, v, max_entry; DBG(23, "sane_open: init gamma tables...\n"); scanner->gamma_entries = dev->info.max_lookup_size; scanner->gamma_entry_size = dev->info.gamma_size; scanner->gamma_bit_depth = dev->info.max_gamma_bit_depth; max_entry = (1 << scanner->gamma_bit_depth) - 1; scanner->gamma_entry_range.min = 0; scanner->gamma_entry_range.max = max_entry; scanner->gamma_entry_range.quant = 1; scanner->gray_lut = calloc(scanner->gamma_entries, sizeof(scanner->gray_lut[0])); scanner->red_lut = calloc(scanner->gamma_entries, sizeof(scanner->red_lut[0])); scanner->green_lut = calloc(scanner->gamma_entries, sizeof(scanner->green_lut[0])); scanner->blue_lut = calloc(scanner->gamma_entries, sizeof(scanner->blue_lut[0])); if ((scanner->gray_lut == NULL) || (scanner->red_lut == NULL) || (scanner->green_lut == NULL) || (scanner->blue_lut == NULL)) { DBG(23, "sane_open: unable to allocate space for %d-entry LUT's;\n", scanner->gamma_entries); DBG(23, " so, gamma tables now DISABLED.\n"); free(scanner->gray_lut); free(scanner->red_lut); free(scanner->green_lut); free(scanner->blue_lut); } for (j=0; jgamma_entries; j += scanner->gamma_entry_size) { v = (SANE_Int) ((double) j * (double) max_entry / ((double) scanner->gamma_entries - 1.0) + 0.5); scanner->gray_lut[j] = v; scanner->red_lut[j] = v; scanner->green_lut[j] = v; scanner->blue_lut[j] = v; } } else { DBG(23, "sane_open: NO gamma tables. (max size = %lu)\n", (u_long)dev->info.max_lookup_size); scanner->gamma_entries = 0; scanner->gray_lut = NULL; scanner->red_lut = NULL; scanner->green_lut = NULL; scanner->blue_lut = NULL; } DBG(23, "sane_open: init pass-time variables...\n"); scanner->scanning = SANE_FALSE; scanner->this_pass = 0; scanner->sfd = -1; scanner->dev = dev; scanner->sense_flags = 0; scanner->scan_started = SANE_FALSE; scanner->woe = SANE_FALSE; scanner->cancel = SANE_FALSE; DBG(23, "sane_open: init clever cache...\n"); /* clear out that clever cache, so it doesn't match anything */ { int j; for (j=0; j<10; j++) scanner->mode_sense_cache[j] = 0; scanner->precal_record = MS_PRECAL_NONE; } DBG(23, "sane_open: initialize options: \n"); if ((status = init_options(scanner)) != SANE_STATUS_GOOD) return status; scanner->next = first_handle; first_handle = scanner; *handle = scanner; return SANE_STATUS_GOOD; } /********************************************************************/ /* sane_close */ /********************************************************************/ void sane_close (SANE_Handle handle) { Microtek_Scanner *ms = handle; DBG(10, "sane_close...\n"); /* free malloc'ed stuff (strdup counts too!) */ free((void *) ms->sod[OPT_MODE].constraint.string_list); free((void *) ms->sod[OPT_SOURCE].constraint.string_list); free(ms->val[OPT_MODE].s); free(ms->val[OPT_HALFTONE_PATTERN].s); free(ms->val[OPT_SOURCE].s); free(ms->val[OPT_CUSTOM_GAMMA].s); free(ms->gray_lut); free(ms->red_lut); free(ms->green_lut); free(ms->blue_lut); /* remove Scanner from linked list */ if (first_handle == ms) first_handle = ms->next; else { Microtek_Scanner *ts = first_handle; while ((ts != NULL) && (ts->next != ms)) ts = ts->next; ts->next = ts->next->next; /* == ms->next */ } /* finally, say goodbye to the Scanner */ free(ms); } /********************************************************************/ /* sane_get_option_descriptor */ /********************************************************************/ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Microtek_Scanner *scanner = handle; DBG(96, "sane_get_option_descriptor (%d)...\n", option); if ((unsigned)option >= NUM_OPTIONS) return NULL; return &(scanner->sod[option]); } /********************************************************************/ /* sane_control_option */ /********************************************************************/ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int *info) { Microtek_Scanner *scanner = handle; SANE_Option_Descriptor *sod; Option_Value *val; SANE_Status status; DBG(96, "sane_control_option (opt=%d,act=%d,val=%p,info=%p)\n", option, action, value, (void*) info); sod = scanner->sod; val = scanner->val; /* no changes while in mid-pass! */ if (scanner->scanning) return SANE_STATUS_DEVICE_BUSY; /* and... no changes while in middle of three-pass series! */ if (scanner->this_pass != 0) return SANE_STATUS_DEVICE_BUSY; if ( ((option >= NUM_OPTIONS) || (option < 0)) || (!SANE_OPTION_IS_ACTIVE(scanner->sod[option].cap)) ) return SANE_STATUS_INVAL; if (info) *info = 0; /* choose by action */ switch (action) { case SANE_ACTION_GET_VALUE: switch (option) { /* word options... */ case OPT_RESOLUTION: case OPT_SPEED: case OPT_BACKTRACK: case OPT_NEGATIVE: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_EXPOSURE: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_HIGHLIGHT: case OPT_SHADOW: case OPT_MIDTONE: case OPT_GAMMA_BIND: case OPT_ANALOG_GAMMA: case OPT_ANALOG_GAMMA_R: case OPT_ANALOG_GAMMA_G: case OPT_ANALOG_GAMMA_B: case OPT_EXP_RES: case OPT_CALIB_ONCE: *(SANE_Word *)value = val[option].w; return SANE_STATUS_GOOD; /* word-array options... */ /* case OPT_HALFTONE_PATTERN:*/ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy(value, val[option].wa, sod[option].size); return SANE_STATUS_GOOD; /* string options... */ case OPT_MODE: case OPT_HALFTONE_PATTERN: case OPT_CUSTOM_GAMMA: case OPT_SOURCE: strcpy(value, val[option].s); return SANE_STATUS_GOOD; /* others.... */ case OPT_NUM_OPTS: *(SANE_Word *) value = NUM_OPTIONS; return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: { status = sanei_constrain_value(sod + option, value, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* set word options... */ case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_RESOLUTION: if (info) *info |= SANE_INFO_RELOAD_PARAMS; case OPT_SPEED: case OPT_PREVIEW: case OPT_BACKTRACK: case OPT_NEGATIVE: case OPT_EXPOSURE: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_ANALOG_GAMMA: case OPT_ANALOG_GAMMA_R: case OPT_ANALOG_GAMMA_G: case OPT_ANALOG_GAMMA_B: val[option].w = *(SANE_Word *)value; return SANE_STATUS_GOOD; case OPT_HIGHLIGHT: case OPT_SHADOW: case OPT_MIDTONE: val[option].w = *(SANE_Word *)value; /* we need to (silently) make sure shadow <= midtone <= highlight */ if (scanner->midtone_support) { if (val[OPT_SHADOW].w > val[OPT_MIDTONE].w) { if (option == OPT_SHADOW) val[OPT_SHADOW].w = val[OPT_MIDTONE].w; else val[OPT_MIDTONE].w = val[OPT_SHADOW].w; } if (val[OPT_HIGHLIGHT].w < val[OPT_MIDTONE].w) { if (option == OPT_HIGHLIGHT) val[OPT_HIGHLIGHT].w = val[OPT_MIDTONE].w; else val[OPT_MIDTONE].w = val[OPT_HIGHLIGHT].w; } } else { if (val[OPT_SHADOW].w > val[OPT_HIGHLIGHT].w) { if (option == OPT_SHADOW) val[OPT_SHADOW].w = val[OPT_HIGHLIGHT].w; else val[OPT_HIGHLIGHT].w = val[OPT_SHADOW].w; } } return SANE_STATUS_GOOD; case OPT_EXP_RES: if (val[option].w != *(SANE_Word *) value) { val[option].w = *(SANE_Word *)value; if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (val[OPT_EXP_RES].w) { sod[OPT_RESOLUTION].constraint.range = &(scanner->exp_res_range); val[OPT_RESOLUTION].w *= 2; } else { sod[OPT_RESOLUTION].constraint.range = &(scanner->res_range); val[OPT_RESOLUTION].w /= 2; } } return SANE_STATUS_GOOD; case OPT_CALIB_ONCE: val[option].w = *(SANE_Word *)value; /* toggling off and on should force a recalibration... */ if (!(val[option].w)) scanner->precal_record = MS_PRECAL_NONE; return SANE_STATUS_GOOD; case OPT_GAMMA_BIND: case OPT_CUSTOM_GAMMA: if (option == OPT_GAMMA_BIND) { if (val[option].w != *(SANE_Word *) value) if (info) *info |= SANE_INFO_RELOAD_OPTIONS; val[option].w = *(SANE_Word *) value; } else if (option == OPT_CUSTOM_GAMMA) { if (val[option].s) { if (strcmp(value, val[option].s)) if (info) *info |= SANE_INFO_RELOAD_OPTIONS; free(val[option].s); } val[option].s = strdup(value); } if ( !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE)) || !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_SCALAR)) ) { sod[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } if ( !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE)) || !(strcmp(val[OPT_CUSTOM_GAMMA].s, M_TABLE)) ) { sod[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE; } if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_SCALAR))) { if (val[OPT_GAMMA_BIND].w == SANE_TRUE) { sod[OPT_ANALOG_GAMMA].cap &= ~SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_R].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_G].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_B].cap |= SANE_CAP_INACTIVE; } else { sod[OPT_ANALOG_GAMMA].cap |= SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_ANALOG_GAMMA_B].cap &= ~SANE_CAP_INACTIVE; } } if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_TABLE))) { if (val[OPT_GAMMA_BIND].w == SANE_TRUE) { sod[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } else { sod[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; sod[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } if (!(strcmp(val[OPT_CUSTOM_GAMMA].s, M_NONE))) sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; else if (!(strcmp(val[OPT_MODE].s, M_COLOR))) sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; return SANE_STATUS_GOOD; case OPT_MODE: if (val[option].s) { if (strcmp(val[option].s, value)) if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; free(val[option].s); } val[option].s = strdup(value); if (strcmp(val[option].s, M_HALFTONE)) { sod[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; } else { sod[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } if (strcmp(val[option].s, M_COLOR)) { /* not color */ /*val[OPT_GAMMA_BIND].w = SANE_TRUE;*/ DBG(23, "FLIP ma LID! bind is %d\n", val[OPT_GAMMA_BIND].w); { SANE_Bool Trueness = SANE_TRUE; SANE_Status status; status = sane_control_option(handle, OPT_GAMMA_BIND, SANE_ACTION_SET_VALUE, &Trueness, NULL); DBG(23, "stat is: %d\n", status); } DBG(23, "LID be FLIPPED! bind is %d\n", val[OPT_GAMMA_BIND].w); sod[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE; /* sod[OPT_FORCE_3PASS].cap |= SANE_CAP_INACTIVE;*/ } else { sod[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE; /* if (scanner->dev->info.modes & MI_MODES_ONEPASS) sod[OPT_FORCE_3PASS].cap &= ~SANE_CAP_INACTIVE;*/ } return SANE_STATUS_GOOD; case OPT_HALFTONE_PATTERN: case OPT_SOURCE: if (val[option].s) free(val[option].s); val[option].s = strdup(value); return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy(val[option].wa, value, sod[option].size); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } break; case SANE_ACTION_SET_AUTO: return SANE_STATUS_UNSUPPORTED; /* We are DUMB. */ } return SANE_STATUS_GOOD; } /********************************************************************/ /* sane_get_parameters */ /********************************************************************/ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) { Microtek_Scanner *s = handle; DBG(23, "sane_get_parameters...\n"); if (!s->scanning) { /* decipher scan mode */ if (!(strcmp(s->val[OPT_MODE].s, M_LINEART))) s->mode = MS_MODE_LINEART; else if (!(strcmp(s->val[OPT_MODE].s, M_HALFTONE))) s->mode = MS_MODE_HALFTONE; else if (!(strcmp(s->val[OPT_MODE].s, M_GRAY))) s->mode = MS_MODE_GRAY; else if (!(strcmp(s->val[OPT_MODE].s, M_COLOR))) s->mode = MS_MODE_COLOR; if (s->mode == MS_MODE_COLOR) { if (s->onepass) { /* regular one-pass */ DBG(23, "sane_get_parameters: regular 1-pass color\n"); s->threepasscolor = SANE_FALSE; s->onepasscolor = SANE_TRUE; s->color_seq = s->dev->info.color_sequence; } else { /* 3-pass scanner */ DBG(23, "sane_get_parameters: regular 3-pass color\n"); s->threepasscolor = SANE_TRUE; s->onepasscolor = SANE_FALSE; s->color_seq = s->dev->info.color_sequence; } } else { /* not color! */ DBG(23, "sane_get_parameters: non-color\n"); s->threepasscolor = SANE_FALSE; s->onepasscolor = SANE_FALSE; s->color_seq = s->dev->info.color_sequence; } s->transparency = !(strcmp(s->val[OPT_SOURCE].s, M_TRANS)); s->useADF = !(strcmp(s->val[OPT_SOURCE].s, M_AUTOFEED)); /* disallow exp. res. during preview scan XXXXXXXXXXX */ /*s->expandedresolution = (s->val[OPT_EXP_RES].w) && !(s->val[OPT_PREVIEW].w);*/ s->expandedresolution = (s->val[OPT_EXP_RES].w); s->doexpansion = (s->expandedresolution && !(s->dev->info.does_expansion)); if (s->res_type == MS_RES_1PER) { s->resolution = (SANE_Int)(SANE_UNFIX(s->val[OPT_RESOLUTION].w)); s->resolution_code = 0xFF & ((s->resolution * 100) / s->dev->info.base_resolution / (s->expandedresolution ? 2 : 1)); DBG(23, "sane_get_parameters: res_code = %d (%2x)\n", s->resolution_code, s->resolution_code); } else { DBG(23, "sane_get_parameters: 5 percent!!!\n"); /* XXXXXXXXXXXXX */ } s->calib_once = s->val[OPT_CALIB_ONCE].w; s->reversecolors = s->val[OPT_NEGATIVE].w; s->prescan = s->val[OPT_PREVIEW].w; s->exposure = (s->val[OPT_EXPOSURE].w / 3) + 7; s->contrast = (s->val[OPT_CONTRAST].w / 7) + 7; s->velocity = s->val[OPT_SPEED].w; s->shadow = s->val[OPT_SHADOW].w; s->highlight = s->val[OPT_HIGHLIGHT].w; s->midtone = s->val[OPT_MIDTONE].w; if (SANE_OPTION_IS_ACTIVE(s->sod[OPT_BRIGHTNESS].cap)) { #if 1 /* this is _not_ what the docs specify! */ if (s->val[OPT_BRIGHTNESS].w >= 0) s->bright_r = (SANE_Byte) (s->val[OPT_BRIGHTNESS].w); else s->bright_r = (SANE_Byte) (0x80 | (- s->val[OPT_BRIGHTNESS].w)); #else s->bright_r = (SANE_Byte) (s->val[OPT_BRIGHTNESS].w); #endif s->bright_g = s->bright_b = s->bright_r; DBG(23, "bright_r of %d set to 0x%0x\n", s->val[OPT_BRIGHTNESS].w, s->bright_r); } else { s->bright_r = s->bright_g = s->bright_b = 0; } /* figure out halftone pattern selection... */ if (s->mode == MS_MODE_HALFTONE) { int i = 0; while ((halftone_mode_list[i] != NULL) && (strcmp(halftone_mode_list[i], s->val[OPT_HALFTONE_PATTERN].s))) i++; s->pattern = ((i < s->dev->info.pattern_count) ? i : 0); } else s->pattern = 0; { /* need to 'round' things properly! XXXXXXXX */ SANE_Int widthpix; double dots_per_mm = s->resolution / MM_PER_INCH; double units_per_mm = (s->unit_type == MS_UNIT_18INCH) ? (8.0 / MM_PER_INCH) : /* 1/8 inches */ (s->dev->info.base_resolution / MM_PER_INCH); /* pixels */ DBG(23, "sane_get_parameters: dots_per_mm: %f\n", dots_per_mm); DBG(23, "sane_get_parameters: units_per_mm: %f\n", units_per_mm); /* calculate frame coordinates... * scanner coords are in 'units' -- pixels or 1/8" * option coords are MM */ s->x1 = (SANE_Int)(SANE_UNFIX(s->val[OPT_TL_X].w) * units_per_mm + 0.5); s->y1 = (SANE_Int)(SANE_UNFIX(s->val[OPT_TL_Y].w) * units_per_mm + 0.5); s->x2 = (SANE_Int)(SANE_UNFIX(s->val[OPT_BR_X].w) * units_per_mm + 0.5); s->y2 = (SANE_Int)(SANE_UNFIX(s->val[OPT_BR_Y].w) * units_per_mm + 0.5); /* bug out if length or width is <= zero... */ if ((s->x1 >= s->x2) || (s->y1 >= s->y2)) return SANE_STATUS_INVAL; /* these are just an estimate... (but *should* be completely accurate) * real values come from scanner after sane_start. */ if (s->unit_type == MS_UNIT_18INCH) { /* who *knows* what happens */ widthpix = (SANE_Int)((double)(s->x2 - s->x1 + 1) / 8.0 * (double)s->resolution); s->params.lines = (SANE_Int)((double)(s->y2 - s->y1 + 1) / 8.0 * (double)s->resolution); } else { /* calculate pixels per scanline returned by scanner... */ /* scanner (E6 at least) always seems to return an -even- number of -bytes- */ if (s->resolution <= s->dev->info.base_resolution) widthpix = (SANE_Int)((double)(s->x2 - s->x1 + 1) * (double)(s->resolution) / (double)(s->dev->info.base_resolution)); else widthpix = (s->x2 - s->x1 + 1); if ((s->mode == MS_MODE_LINEART) || (s->mode == MS_MODE_HALFTONE)) { DBG(23, "WIDTHPIX: before: %d", widthpix); widthpix = ((widthpix / 8) & ~0x1) * 8; DBG(23, "after: %d", widthpix); } else { widthpix = widthpix & ~0x1; } DBG(23, "WIDTHPIX: before exp: %d\n", widthpix); /* ok, now fix up expanded-mode conversions */ if (s->resolution > s->dev->info.base_resolution) widthpix = (SANE_Int) ((double)widthpix * (double)s->resolution / (double)s->dev->info.base_resolution); s->params.pixels_per_line = widthpix; s->params.lines = (SANE_Int)((double)(s->y2 - s->y1 + 1) * (double)(s->resolution) / (double)(s->dev->info.base_resolution)); } } switch (s->mode) { case MS_MODE_LINEART: case MS_MODE_HALFTONE: s->multibit = SANE_FALSE; s->params.format = SANE_FRAME_GRAY; s->params.depth = 1; s->filter = MS_FILT_CLEAR; s->params.bytes_per_line = s->params.pixels_per_line / 8; break; case MS_MODE_GRAY: s->multibit = SANE_TRUE; s->params.format = SANE_FRAME_GRAY; s->params.depth = s->bits_per_color; s->filter = MS_FILT_CLEAR; s->params.bytes_per_line = s->params.pixels_per_line; break; case MS_MODE_COLOR: s->multibit = SANE_TRUE; if (s->onepasscolor) { /* a single-pass color scan */ s->params.format = SANE_FRAME_RGB; s->params.depth = s->bits_per_color; s->filter = MS_FILT_CLEAR; s->params.bytes_per_line = s->params.pixels_per_line * 3; } else { /* a three-pass color scan */ s->params.depth = s->bits_per_color; /* this will be correctly set in sane_start */ s->params.format = SANE_FRAME_RED; s->params.bytes_per_line = s->params.pixels_per_line; } break; } DBG(23, "sane_get_parameters: lines: %d ppl: %d bpl: %d\n", s->params.lines, s->params.pixels_per_line, s->params.bytes_per_line); /* also fixed in sane_start for multi-pass scans */ s->params.last_frame = SANE_TRUE; /* ?? XXXXXXXX */ } if (params) *params = s->params; return SANE_STATUS_GOOD; } /********************************************************************/ /* sane_start */ /********************************************************************/ static SANE_Status sane_start_guts (SANE_Handle handle) { Microtek_Scanner *s = handle; SANE_Status status; SANE_Int busy, linewidth; DBG(10, "sane_start...\n"); if (s->sfd != -1) { DBG(23, "sane_start: sfd already set!\n"); return SANE_STATUS_DEVICE_BUSY; } if ((status = sane_get_parameters(s, 0)) != SANE_STATUS_GOOD) return end_scan(s, status); set_pass_parameters(s); s->scanning = SANE_TRUE; s->cancel = SANE_FALSE; status = sanei_scsi_open(s->dev->sane.name, &(s->sfd), sense_handler, &(s->sense_flags)); if (status != SANE_STATUS_GOOD) { DBG(10, "sane_start: open of %s failed: %s\n", s->dev->sane.name, sane_strstatus (status)); s->sfd = -1; return end_scan(s, status); } if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return end_scan(s, status); if ((status = finagle_precal(s)) != SANE_STATUS_GOOD) return end_scan(s, status); if ((status = scanning_frame(s)) != SANE_STATUS_GOOD) return end_scan(s, status); if (s->dev->info.source_options & (MI_SRC_FEED_BT | MI_SRC_HAS_TRANS | MI_SRC_FEED_SUPP | MI_SRC_HAS_FEED)) { /* ZZZZZZZZZZZ */ if ((status = accessory(s)) != SANE_STATUS_GOOD) return end_scan(s, status); /* if SWslct ???? XXXXXXXXXXXXXXX */ } if ((status = download_gamma(s)) != SANE_STATUS_GOOD) return end_scan(s, status); if ((status = mode_select(s)) != SANE_STATUS_GOOD) return end_scan(s, status); if (s->dev->info.does_mode1) { if ((status = mode_select_1(s)) != SANE_STATUS_GOOD) return end_scan(s, status); } if ((s->do_clever_precal) || (s->do_real_calib)) { if ((status = save_mode_sense(s)) != SANE_STATUS_GOOD) return end_scan(s, status); } if ((status = wait_ready(s)) != SANE_STATUS_GOOD) return end_scan(s, status); s->scan_started = SANE_TRUE; if ((status = start_scan(s)) != SANE_STATUS_GOOD) return end_scan(s, status); if ((status = get_scan_status(s, &busy, &linewidth, &(s->unscanned_lines))) != SANE_STATUS_GOOD) { DBG(10, "sane_start: get_scan_status fails\n"); return end_scan(s, status); } /* check for a bizarre linecount */ if ((s->unscanned_lines < 0) || (s->unscanned_lines > (s->params.lines * 2 * (s->expandedresolution ? 2 : 1)))) { DBG(10, "sane_start: get_scan_status returns weird line count %d\n", s->unscanned_lines); return end_scan(s, SANE_STATUS_DEVICE_BUSY); } /* figure out image format parameters */ switch (s->mode) { case MS_MODE_LINEART: case MS_MODE_HALFTONE: s->pixel_bpl = linewidth; s->header_bpl = 0; s->ppl = linewidth * 8; s->planes = 1; s->line_format = MS_LNFMT_FLAT; break; case MS_MODE_GRAY: if (s->bits_per_color < 8) { s->pixel_bpl = linewidth; s->ppl = linewidth * (8 / s->bits_per_color); } else { s->pixel_bpl = linewidth * ((s->bits_per_color + 7) / 8); s->ppl = linewidth; } s->header_bpl = 0; s->planes = 1; s->line_format = MS_LNFMT_FLAT; break; case MS_MODE_COLOR: switch (s->color_seq) { case MI_COLSEQ_PLANE: s->pixel_bpl = linewidth * ((s->bits_per_color + 7) / 8); s->ppl = linewidth; s->header_bpl = 0; s->planes = 1; s->line_format = MS_LNFMT_FLAT; break; case MI_COLSEQ_NONRGB: s->pixel_bpl = (linewidth - 2) * 3 * ((s->bits_per_color + 7) / 8); s->ppl = linewidth - 2; s->header_bpl = 2 * 3; s->planes = 3; s->line_format = MS_LNFMT_GOOFY_RGB; break; case MI_COLSEQ_PIXEL: s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8); s->ppl = linewidth; s->header_bpl = 0; s->planes = 3; s->line_format = MS_LNFMT_FLAT; break; case MI_COLSEQ_2PIXEL: s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8); s->ppl = linewidth; s->header_bpl = 0; s->planes = 3; s->line_format = MS_LNFMT_SEQ_2R2G2B; break; case MI_COLSEQ_RGB: s->pixel_bpl = linewidth * 3 * ((s->bits_per_color + 7) / 8); s->ppl = linewidth; s->header_bpl = 0; s->planes = 3; s->line_format = MS_LNFMT_SEQ_RGB; break; default: DBG(10, "sane_start: Unknown color_sequence: %d\n", s->dev->info.color_sequence); return end_scan(s, SANE_STATUS_INVAL); } break; default: DBG(10, "sane_start: Unknown scan mode: %d\n", s->mode); return end_scan(s, SANE_STATUS_INVAL); } if ((s->doexpansion) && (s->resolution > s->dev->info.base_resolution)) { s->dest_ppl = (int) ((double)s->ppl * (double)s->resolution / (double)s->dev->info.base_resolution); /*+ 0.5 XXXXXX */ s->exp_aspect = (double)s->ppl / (double)s->dest_ppl; s->dest_pixel_bpl = (int) ceil((double)s->pixel_bpl / s->exp_aspect); /*s->exp_aspect = (double) s->dev->info.base_resolution / (double) s->resolution;*/ /* s->dest_pixel_bpl = s->pixel_bpl / s->exp_aspect; s->dest_ppl = s->ppl / s->exp_aspect;*/ /*s->dest_ppl = s->ppl / s->exp_aspect; s->dest_pixel_bpl = (int) ceil((double)s->dest_ppl * (double)s->pixel_bpl / (double)s->ppl);*/ } else { s->exp_aspect = 1.0; s->dest_pixel_bpl = s->pixel_bpl; s->dest_ppl = s->ppl; } s->params.lines = s->unscanned_lines; s->params.pixels_per_line = s->dest_ppl; s->params.bytes_per_line = s->dest_pixel_bpl; /* calculate maximum line capacity of SCSI buffer */ s->max_scsi_lines = SCSI_BUFF_SIZE / (s->pixel_bpl + s->header_bpl); if (s->max_scsi_lines < 1) { DBG(10, "sane_start: SCSI buffer smaller that one scan line!\n"); return end_scan(s, SANE_STATUS_NO_MEM); } s->scsi_buffer = (uint8_t *) malloc(SCSI_BUFF_SIZE * sizeof(uint8_t)); if (s->scsi_buffer == NULL) return SANE_STATUS_NO_MEM; /* what's a good initial size for this? */ s->rb = ring_alloc(s->max_scsi_lines * s->dest_pixel_bpl, s->dest_pixel_bpl, s->dest_ppl); s->undelivered_bytes = s->unscanned_lines * s->dest_pixel_bpl; DBG(23, "Scan Param:\n"); DBG(23, "pix bpl: %d hdr bpl: %d ppl: %d\n", s->pixel_bpl, s->header_bpl, s->ppl); DBG(23, "undel bytes: %d unscan lines: %d planes: %d\n", s->undelivered_bytes, s->unscanned_lines, s->planes); DBG(23, "dest bpl: %d dest ppl: %d aspect: %f\n", s->dest_pixel_bpl, s->dest_ppl, s->exp_aspect); return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { Microtek_Scanner *s = handle; SANE_Status status; s->woe = SANE_TRUE; status = sane_start_guts(handle); s->woe = SANE_FALSE; return status; } /********************************************************************/ /* sane_read */ /********************************************************************/ static SANE_Status sane_read_guts (SANE_Handle handle, SANE_Byte *dest_buffer, SANE_Int dest_length, SANE_Int *ret_length) { Microtek_Scanner *s = handle; SANE_Status status; int nlines; ring_buffer *rb = s->rb; DBG(10, "sane_read...\n"); *ret_length = 0; /* default: no data */ /* we have been cancelled... */ if (s->cancel) return end_scan(s, SANE_STATUS_CANCELLED); /* we're not really scanning!... */ if (!(s->scanning)) return SANE_STATUS_INVAL; /* we are done scanning... */ if (s->undelivered_bytes <= 0) return end_scan(s, SANE_STATUS_EOF); /* get more bytes if our ring is empty... */ while (rb->complete_count == 0) { if ((status = read_from_scanner(s, &nlines)) != SANE_STATUS_GOOD) { DBG(18, "sane_read: read_from_scanner failed.\n"); return end_scan(s, status); } if ((status = pack_into_ring(s, nlines)) != SANE_STATUS_GOOD) { DBG(18, "sane_read: pack_into_ring failed.\n"); return end_scan(s, status); } } /* return some data to caller */ *ret_length = pack_into_dest(dest_buffer, dest_length, rb); s->undelivered_bytes -= *ret_length; if (s->cancel) return end_scan(s, SANE_STATUS_CANCELLED); return SANE_STATUS_GOOD; } SANE_Status sane_read (SANE_Handle handle, SANE_Byte *dest_buffer, SANE_Int dest_length, SANE_Int *ret_length) { Microtek_Scanner *s = handle; SANE_Status status; s->woe = SANE_TRUE; status = sane_read_guts(handle, dest_buffer, dest_length, ret_length); s->woe = SANE_FALSE; return status; } /********************************************************************/ /* sane_exit */ /********************************************************************/ void sane_exit (void) { Microtek_Device *next; DBG(10, "sane_exit...\n"); /* close all leftover Scanners */ /*(beware of how sane_close interacts with linked list) */ while (first_handle != NULL) sane_close(first_handle); /* free up device list */ while (first_dev != NULL) { next = first_dev->next; free((void *) first_dev->sane.name); free((void *) first_dev->sane.model); free(first_dev); first_dev = next; } /* the devlist allocated by sane_get_devices */ free(devlist); DBG(10, "sane_exit: MICROTEK says goodbye.\n"); } /********************************************************************/ /* sane_cancel */ /********************************************************************/ void sane_cancel (SANE_Handle handle) { Microtek_Scanner *ms = handle; DBG(10, "sane_cancel...\n"); ms->cancel = SANE_TRUE; if (!(ms->woe)) end_scan(ms, SANE_STATUS_CANCELLED); } /********************************************************************/ /* sane_set_io_mode */ /********************************************************************/ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG(10, "sane_set_io_mode...\n"); handle = handle; if (non_blocking) return SANE_STATUS_UNSUPPORTED; else return SANE_STATUS_GOOD; } /********************************************************************/ /* sane_get_select_fd */ /********************************************************************/ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG(10, "sane_get_select_fd...\n"); handle = handle, fd = fd; return SANE_STATUS_UNSUPPORTED; } sane-backends-1.0.27/backend/fujitsu.h0000664000175000017500000005562012776312542014474 00000000000000#ifndef FUJITSU_H #define FUJITSU_H /* * Part of SANE - Scanner Access Now Easy. * Please see opening comment in fujitsu.c */ /* ------------------------------------------------------------------------- * This option list has to contain all options for all scanners supported by * this driver. If a certain scanner cannot handle a certain option, there's * still the possibility to say so, later. */ enum fujitsu_Option { OPT_NUM_OPTS = 0, OPT_STANDARD_GROUP, OPT_SOURCE, /*fb/adf/front/back/duplex*/ OPT_MODE, /*mono/gray/color*/ OPT_RES, /*a range or a list*/ OPT_GEOMETRY_GROUP, OPT_PAGE_WIDTH, OPT_PAGE_HEIGHT, OPT_TL_X, OPT_TL_Y, OPT_BR_X, OPT_BR_Y, OPT_ENHANCEMENT_GROUP, OPT_BRIGHTNESS, OPT_CONTRAST, OPT_GAMMA, OPT_THRESHOLD, /*IPC*/ OPT_RIF, OPT_HT_TYPE, OPT_HT_PATTERN, OPT_OUTLINE, OPT_EMPHASIS, OPT_SEPARATION, OPT_MIRRORING, OPT_WL_FOLLOW, /*IPC/DTC*/ OPT_BP_FILTER, OPT_SMOOTHING, OPT_GAMMA_CURVE, OPT_THRESHOLD_CURVE, OPT_THRESHOLD_WHITE, OPT_NOISE_REMOVAL, OPT_MATRIX_5, OPT_MATRIX_4, OPT_MATRIX_3, OPT_MATRIX_2, /*IPC/SDTC*/ OPT_VARIANCE, OPT_ADVANCED_GROUP, OPT_AWD, OPT_ALD, OPT_COMPRESS, OPT_COMPRESS_ARG, OPT_DF_ACTION, OPT_DF_SKEW, OPT_DF_THICKNESS, OPT_DF_LENGTH, OPT_DF_DIFF, OPT_DF_RECOVERY, OPT_PAPER_PROTECT, OPT_ADV_PAPER_PROT, OPT_STAPLE_DETECT, OPT_BG_COLOR, OPT_DROPOUT_COLOR, OPT_BUFF_MODE, OPT_PREPICK, OPT_OVERSCAN, OPT_SLEEP_TIME, OPT_OFF_TIME, OPT_DUPLEX_OFFSET, OPT_GREEN_OFFSET, OPT_BLUE_OFFSET, OPT_LOW_MEM, OPT_SIDE, OPT_HWDESKEWCROP, OPT_SWDESKEW, OPT_SWDESPECK, OPT_SWCROP, OPT_SWSKIP, OPT_HALT_ON_CANCEL, OPT_ENDORSER_GROUP, OPT_ENDORSER, OPT_ENDORSER_BITS, OPT_ENDORSER_VAL, OPT_ENDORSER_STEP, OPT_ENDORSER_Y, OPT_ENDORSER_FONT, OPT_ENDORSER_DIR, OPT_ENDORSER_SIDE, OPT_ENDORSER_STRING, OPT_SENSOR_GROUP, OPT_TOP, OPT_A3, OPT_B4, OPT_A4, OPT_B5, OPT_HOPPER, OPT_OMR, OPT_ADF_OPEN, OPT_SLEEP, OPT_SEND_SW, OPT_MANUAL_FEED, OPT_SCAN_SW, OPT_FUNCTION, OPT_INK_EMPTY, OPT_DOUBLE_FEED, OPT_ERROR_CODE, OPT_SKEW_ANGLE, OPT_INK_REMAIN, OPT_DUPLEX_SW, OPT_DENSITY_SW, /* must come last: */ NUM_OPTIONS }; /* used to control the max page-height, which varies by resolution */ struct y_size { int res; int len; }; struct fujitsu { /* --------------------------------------------------------------------- */ /* immutable values which are set during init of scanner. */ struct fujitsu *next; char device_name[1024]; /* The name of the device from sanei */ int missing; /* used to mark unplugged scanners */ /* --------------------------------------------------------------------- */ /* immutable values which are set during reading of config file. */ int buffer_size; int connection; /* hardware interface type */ /* --------------------------------------------------------------------- */ /* immutable values which are set during inquiry probing of the scanner. */ /* members in order found in scsi data... */ char vendor_name[9]; /* raw data as returned by SCSI inquiry. */ char model_name[17]; /* raw data as returned by SCSI inquiry. */ char version_name[5]; /* raw data as returned by SCSI inquiry. */ int color_raster_offset; /* offset between r and b scan line and */ /* between b and g scan line (0 or 4) */ int duplex_raster_offset; /* offset between front and rear page when */ /* when scanning 3091 style duplex */ /* --------------------------------------------------------------------- */ /* immutable values which are set during std VPD probing of the scanner. */ /* members in order found in scsi data... */ int basic_x_res; int basic_y_res; int step_x_res[6]; /*one for each mode*/ int step_y_res[6]; /*one for each mode*/ int max_x_res; int max_y_res; int min_x_res; int min_y_res; int std_res[16]; /*some scanners only support a few resolutions*/ /* max scan size in pixels comes from scanner in basic res units */ int max_x_basic; int max_y_basic; int can_overflow; int can_mode[6]; /* mode specific */ /* --------------------------------------------------------------------- */ /* immutable values which are set during vndr VPD probing of the scanner */ /* members in order found in scsi data... */ int has_adf; int has_flatbed; int has_transparency; int has_duplex; int has_endorser_b; int has_barcode; int has_operator_panel; int has_endorser_f; int adbits; int buffer_bytes; /*supported scsi commands*/ int has_cmd_msen10; int has_cmd_msel10; int has_cmd_lsen; int has_cmd_lsel; int has_cmd_change; int has_cmd_rbuff; int has_cmd_wbuff; int has_cmd_cav; int has_cmd_comp; int has_cmd_gdbs; int has_cmd_op; int has_cmd_send; int has_cmd_read; int has_cmd_gwin; int has_cmd_swin; int has_cmd_sdiag; int has_cmd_rdiag; int has_cmd_scan; int has_cmd_msen6; int has_cmd_copy; int has_cmd_rel; int has_cmd_runit; int has_cmd_msel6; int has_cmd_inq; int has_cmd_rs; int has_cmd_tur; /*FIXME: there are more vendor cmds? */ int has_cmd_subwindow; int has_cmd_endorser; int has_cmd_hw_status; int has_cmd_hw_status_2; int has_cmd_hw_status_3; int has_cmd_scanner_ctl; int has_cmd_device_restart; /*FIXME: do we need the vendor window param list? */ int brightness_steps; int threshold_steps; int contrast_steps; int num_internal_gamma; int num_download_gamma; int num_internal_dither; int num_download_dither; int has_df_recovery; int has_paper_protect; int has_adv_paper_prot; int has_staple_detect; int has_rif; int has_dtc; int has_sdtc; int has_outline; int has_emphasis; int has_autosep; int has_mirroring; int has_wl_follow; int has_subwindow; int has_diffusion; int has_ipc3; int has_rotation; int has_hybrid_crop_deskew; int has_off_mode; int has_comp_MH; int has_comp_MR; int has_comp_MMR; int has_comp_JBIG; int has_comp_JPG1; int has_comp_JPG2; int has_comp_JPG3; int has_op_halt; /*FIXME: more endorser data? */ int endorser_type_f; int endorser_type_b; /*FIXME: barcode data? */ /* overscan size in pixels comes from scanner in basic res units */ int os_x_basic; int os_y_basic; /* --------------------------------------------------------------------- */ /* immutable values which are gathered by mode_sense command */ int has_MS_autocolor; int has_MS_prepick; int has_MS_sleep; int has_MS_duplex; int has_MS_rand; int has_MS_bg; int has_MS_df; int has_MS_dropout; /* dropout color specified in mode select data */ int has_MS_buff; int has_MS_auto; int has_MS_lamp; int has_MS_jobsep; /* --------------------------------------------------------------------- */ /* immutable values which are hard coded because they are not in vpd */ /* this section replaces all the old 'switch (s->model)' code */ /* the scan size in 1/1200th inches, NOT basic_units or sane units */ int max_x; int max_y; struct y_size max_y_by_res[4]; int min_x; int min_y; int max_x_fb; int max_y_fb; int has_back; /* not all duplex scanners can do adf back side only */ int color_interlace; /* different models interlace colors differently */ int duplex_interlace; /* different models interlace sides differently */ int jpeg_interlace; /* different models interlace jpeg sides differently */ int cropping_mode; /* lower-end scanners dont crop from paper size */ int ghs_in_rs; int window_gamma; int endorser_string_len; int has_pixelsize; int has_short_pixelsize; /* m3091/2 put weird stuff at end, ignore it */ int broken_diag_serial; /* some scanners are just plain borked */ int need_q_table; /* some scanners wont work without these */ int need_diag_preread; int late_lut; int hopper_before_op; /* some scanners dont like OP when hopper empty */ int no_wait_after_op; /* some scanners dont like TUR after OP */ int has_vuid_mono; /* mono set window data */ int has_vuid_3091; /* 3091/2 set window data */ int has_vuid_color; /* color set window data */ int reverse_by_mode[6]; /* mode specific */ int ppl_mod_by_mode[6]; /* mode specific scanline length limitation */ /* --------------------------------------------------------------------- */ /* immutable values which are set during serial number probing scanner */ char serial_name[28]; /* 16 char model, ':', 10 byte serial, null */ /* --------------------------------------------------------------------- */ /* struct with pointers to device/vendor/model names, and a type value */ /* used to inform sane frontend about the device */ SANE_Device sane; /* --------------------------------------------------------------------- */ /* changeable SANE_Option structs provide our interface to frontend. */ /* some options require lists of strings or numbers, we keep them here */ /* instead of in global vars so that they can differ for each scanner */ /* long array of option structs */ SANE_Option_Descriptor opt[NUM_OPTIONS]; /*mode group*/ SANE_String_Const mode_list[7]; SANE_String_Const source_list[5]; SANE_Int res_list[17]; SANE_Range res_range; /*geometry group*/ SANE_Range tl_x_range; SANE_Range tl_y_range; SANE_Range br_x_range; SANE_Range br_y_range; SANE_Range paper_x_range; SANE_Range paper_y_range; /*enhancement group*/ SANE_Range brightness_range; SANE_Range contrast_range; SANE_Range gamma_range; SANE_Range threshold_range; /*ipc group*/ SANE_String_Const ht_type_list[4]; SANE_Range ht_pattern_range; SANE_Range emphasis_range; SANE_String_Const wl_follow_list[4]; SANE_Range gamma_curve_range; SANE_Range threshold_curve_range; SANE_Range variance_range; /*advanced group*/ SANE_String_Const compress_list[3]; SANE_Range compress_arg_range; SANE_String_Const df_action_list[4]; SANE_String_Const df_diff_list[5]; SANE_String_Const df_recovery_list[4]; SANE_String_Const paper_protect_list[4]; SANE_String_Const adv_paper_prot_list[4]; SANE_String_Const staple_detect_list[4]; SANE_String_Const bg_color_list[4]; SANE_String_Const do_color_list[5]; SANE_String_Const lamp_color_list[5]; SANE_String_Const buff_mode_list[4]; SANE_String_Const prepick_list[4]; SANE_String_Const overscan_list[4]; SANE_Range sleep_time_range; SANE_Range off_time_range; SANE_Range duplex_offset_range; SANE_Range green_offset_range; SANE_Range blue_offset_range; SANE_Range swdespeck_range; SANE_Range swskip_range; /*endorser group*/ SANE_Range endorser_bits_range; SANE_Range endorser_val_range; SANE_Range endorser_step_range; SANE_Range endorser_y_range; SANE_String_Const endorser_font_list[6]; SANE_String_Const endorser_dir_list[3]; SANE_String_Const endorser_side_list[3]; /* --------------------------------------------------------------------- */ /* changeable vars to hold user input. modified by SANE_Options above */ /*mode group*/ int u_mode; /*color,lineart,etc*/ int source; /*fb,adf front,adf duplex,etc*/ int resolution_x; /* X resolution in dpi */ int resolution_y; /* Y resolution in dpi */ /*geometry group*/ /* The desired size of the scan, all in 1/1200 inch */ int tl_x; int tl_y; int br_x; int br_y; int page_width; int page_height; /*enhancement group*/ int brightness; int contrast; double gamma; int threshold; /* ipc */ int rif; int ht_type; int ht_pattern; int outline; int emphasis; int separation; int mirroring; int wl_follow; /* ipc_mode=DTC */ int bp_filter; int smoothing; int gamma_curve; int threshold_curve; int threshold_white; int noise_removal; int matrix_5; int matrix_4; int matrix_3; int matrix_2; /* ipc_mode = SDTC */ int variance; /*advanced group*/ int awd; int ald; int compress; int compress_arg; int df_action; int df_skew; int df_thickness; int df_length; int df_diff; int df_recovery; int paper_protect; int adv_paper_prot; int staple_detect; int bg_color; int dropout_color; int buff_mode; int prepick; int overscan; int lamp_color; int sleep_time; int off_time; int duplex_offset; int green_offset; int blue_offset; int low_mem; int hwdeskewcrop; int swdeskew; int swdespeck; int swcrop; double swskip; int halt_on_cancel; /*endorser group*/ int u_endorser; int u_endorser_bits; int u_endorser_val; int u_endorser_step; int u_endorser_y; int u_endorser_font; int u_endorser_dir; int u_endorser_side; char u_endorser_string[81]; /*max length, plus null byte*/ /* --------------------------------------------------------------------- */ /* values which are derived from setting the options above */ /* the user never directly modifies these */ int s_mode; /*color,lineart,etc: sent to scanner*/ /* this is defined in sane spec as a struct containing: SANE_Frame format; SANE_Bool last_frame; SANE_Int lines; SANE_Int depth; ( binary=1, gray=8, color=8 (!24) ) SANE_Int pixels_per_line; SANE_Int bytes_per_line; */ SANE_Parameters u_params; SANE_Parameters s_params; /* --------------------------------------------------------------------- */ /* values which are set by scanning functions to keep track of pages, etc */ int started; int reading; int cancelled; int side; /* total to read/write */ int bytes_tot[2]; /* how far we have read */ int bytes_rx[2]; int lines_rx[2]; /*only used by 3091*/ int eof_rx[2]; int ili_rx[2]; int eom_rx; /* how far we have written */ int bytes_tx[2]; int eof_tx[2]; /*size of buffers (can be smaller than above*/ int buff_tot[2]; int buff_rx[2]; int buff_tx[2]; unsigned char * buffers[2]; /* --------------------------------------------------------------------- */ /*hardware feature bookkeeping*/ int req_driv_crop; int req_driv_lut; /* --------------------------------------------------------------------- */ /* values used by the software enhancment code (deskew, crop, etc) */ SANE_Status deskew_stat; int deskew_vals[2]; double deskew_slope; int crop_vals[4]; /* --------------------------------------------------------------------- */ /* values used by the compression functions, esp. jpeg with duplex */ int jpeg_stage; int jpeg_ff_offset; int jpeg_front_rst; int jpeg_back_rst; int jpeg_x_byte; /* --------------------------------------------------------------------- */ /* values which used by the command and data sending functions (scsi/usb)*/ int fd; /* The scanner device file descriptor. */ size_t rs_info; int rs_eom; int rs_ili; /* --------------------------------------------------------------------- */ /* values which are used by the get hardware status command */ int hw_top; int hw_A3; int hw_B4; int hw_A4; int hw_B5; int hw_hopper; int hw_omr; int hw_adf_open; int hw_sleep; int hw_send_sw; int hw_manual_feed; int hw_scan_sw; int hw_function; int hw_ink_empty; int hw_double_feed; int hw_error_code; int hw_skew_angle; int hw_ink_remain; int hw_duplex_sw; int hw_density_sw; /* values which are used to track the frontend's access to sensors */ char hw_read[NUM_OPTIONS-OPT_TOP]; }; #define CONNECTION_SCSI 0 /* SCSI interface */ #define CONNECTION_USB 1 /* USB interface */ #define SIDE_FRONT 0 #define SIDE_BACK 1 #define SOURCE_FLATBED 0 #define SOURCE_ADF_FRONT 1 #define SOURCE_ADF_BACK 2 #define SOURCE_ADF_DUPLEX 3 #define COMP_NONE WD_cmp_NONE #define COMP_JPEG WD_cmp_JPG1 #define JPEG_STAGE_NONE 0 #define JPEG_STAGE_SOI 1 #define JPEG_STAGE_HEAD 2 #define JPEG_STAGE_SOF 3 #define JPEG_STAGE_SOS 4 #define JPEG_STAGE_FRONT 5 #define JPEG_STAGE_BACK 6 #define JPEG_STAGE_EOI 7 #define JFIF_APP0_LENGTH 18 /* these are same as scsi data to make code easier */ #define MODE_LINEART WD_comp_LA #define MODE_HALFTONE WD_comp_HT #define MODE_GRAYSCALE WD_comp_GS #define MODE_COLOR_LINEART WD_comp_CL #define MODE_COLOR_HALFTONE WD_comp_CH #define MODE_COLOR WD_comp_CG /* these are same as dropout scsi data to make code easier */ #define COLOR_DEFAULT 0 #define COLOR_GREEN 8 #define COLOR_RED 9 #define COLOR_BLUE 11 #define COLOR_WHITE 1 #define COLOR_BLACK 2 #define COLOR_INTERLACE_UNK 0 #define COLOR_INTERLACE_RGB 1 #define COLOR_INTERLACE_BGR 2 #define COLOR_INTERLACE_RRGGBB 3 #define COLOR_INTERLACE_3091 4 #define DUPLEX_INTERLACE_ALT 0 #define DUPLEX_INTERLACE_NONE 1 #define DUPLEX_INTERLACE_3091 2 #define JPEG_INTERLACE_ALT 0 #define JPEG_INTERLACE_NONE 1 #define CROP_RELATIVE 0 #define CROP_ABSOLUTE 1 #define DF_DEFAULT 0 #define DF_CONTINUE 1 #define DF_STOP 2 #define FONT_H 0 #define FONT_HB 1 #define FONT_HN 2 #define FONT_V 3 #define FONT_VB 4 #define DIR_TTB 0 #define DIR_BTT 1 /* endorser type, same as scsi inquiry data */ #define ET_OLD 0 #define ET_30 1 #define ET_40 2 /* ------------------------------------------------------------------------- */ #define MM_PER_UNIT_UNFIX SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0)) #define MM_PER_UNIT_FIX SANE_FIX(SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0))) #define SCANNER_UNIT_TO_FIXED_MM(number) SANE_FIX((number) * MM_PER_UNIT_UNFIX) #define FIXED_MM_TO_SCANNER_UNIT(number) SANE_UNFIX(number) / MM_PER_UNIT_UNFIX #define FUJITSU_CONFIG_FILE "fujitsu.conf" #ifndef PATH_MAX # define PATH_MAX 1024 #endif /* ------------------------------------------------------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize); SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only); SANE_Status sane_open (SANE_String_Const name, SANE_Handle * handle); SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking); SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp); const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option); SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info); SANE_Status sane_start (SANE_Handle handle); SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params); SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len); void sane_cancel (SANE_Handle h); void sane_close (SANE_Handle h); void sane_exit (void); /* ------------------------------------------------------------------------- */ static SANE_Status attach_one_scsi (const char *name); static SANE_Status attach_one_usb (const char *name); static SANE_Status attach_one (const char *devicename, int connType); static SANE_Status connect_fd (struct fujitsu *s); static SANE_Status disconnect_fd (struct fujitsu *s); static SANE_Status sense_handler (int scsi_fd, u_char * result, void *arg); static SANE_Status init_inquire (struct fujitsu *s); static SANE_Status init_vpd (struct fujitsu *s); static SANE_Status init_ms (struct fujitsu *s); static SANE_Status init_model (struct fujitsu *s); static SANE_Status init_user (struct fujitsu *s); static SANE_Status init_options (struct fujitsu *scanner); static SANE_Status init_interlace (struct fujitsu *scanner); static SANE_Status init_serial (struct fujitsu *scanner); static SANE_Status do_cmd(struct fujitsu *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ); static SANE_Status do_scsi_cmd(struct fujitsu *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ); static SANE_Status do_usb_cmd(struct fujitsu *s, int runRS, int shortTime, unsigned char * cmdBuff, size_t cmdLen, unsigned char * outBuff, size_t outLen, unsigned char * inBuff, size_t * inLen ); static SANE_Status wait_scanner (struct fujitsu *s); static SANE_Status object_position (struct fujitsu *s, int action); static SANE_Status scanner_control (struct fujitsu *s, int function); static SANE_Status scanner_control_ric (struct fujitsu *s, int bytes, int side); static SANE_Status mode_select_df(struct fujitsu *s); static SANE_Status mode_select_dropout(struct fujitsu *s); static SANE_Status mode_select_bg(struct fujitsu *s); static SANE_Status mode_select_buff (struct fujitsu *s); static SANE_Status mode_select_prepick (struct fujitsu *s); static SANE_Status mode_select_auto (struct fujitsu *s); static SANE_Status set_sleep_mode(struct fujitsu *s); static SANE_Status set_off_mode(struct fujitsu *s); static int must_downsample (struct fujitsu *s); static int must_fully_buffer (struct fujitsu *s); static int get_page_width (struct fujitsu *s); static int get_page_height (struct fujitsu *s); static int get_ipc_mode (struct fujitsu *s); static int set_max_y (struct fujitsu *s); static SANE_Status send_lut (struct fujitsu *s); static SANE_Status send_endorser (struct fujitsu *s); static SANE_Status endorser (struct fujitsu *s); static SANE_Status set_window (struct fujitsu *s); static SANE_Status get_pixelsize(struct fujitsu *s, int actual); static SANE_Status update_params (struct fujitsu *s); static SANE_Status update_u_params (struct fujitsu *s); static SANE_Status start_scan (struct fujitsu *s); static SANE_Status check_for_cancel(struct fujitsu *s); static SANE_Status read_from_JPEGduplex(struct fujitsu *s); static SANE_Status read_from_3091duplex(struct fujitsu *s); static SANE_Status read_from_scanner(struct fujitsu *s, int side); static SANE_Status copy_3091(struct fujitsu *s, unsigned char * buf, int len, int side); static SANE_Status copy_JPEG(struct fujitsu *s, unsigned char * buf, int len, int side); static SANE_Status copy_buffer(struct fujitsu *s, unsigned char * buf, int len, int side); static SANE_Status read_from_buffer(struct fujitsu *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side); static SANE_Status downsample_from_buffer(struct fujitsu *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side); static SANE_Status setup_buffers (struct fujitsu *s); static SANE_Status get_hardware_status (struct fujitsu *s, SANE_Int option); static SANE_Status buffer_deskew(struct fujitsu *s, int side); static SANE_Status buffer_crop(struct fujitsu *s, int side); static SANE_Status buffer_despeck(struct fujitsu *s, int side); static int buffer_isblank(struct fujitsu *s, int side); static void hexdump (int level, char *comment, unsigned char *p, int l); static size_t maxStringSize (const SANE_String_Const strings[]); #endif /* FUJITSU_H */ sane-backends-1.0.27/backend/plustek-usbdevs.c0000664000175000017500000033153412775312261016134 00000000000000/*............................................................................. * Project : SANE library for Plustek flatbed scanners. *............................................................................. */ /** @file plustek-usbdevs.c * @brief Here we have our USB device definitions. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2013 Gerhard Jaeger * * History: * - 0.40 - starting version of the USB support * - 0.41 - added EPSON1250 entries * - changed reg 0x58 of EPSON Hw0x04B8_0x010F to 0x0d * - reduced memory size of EPSON to 512 * - adjusted tpa origin of UT24 * - 0.42 - added register 0x27, 0x2c-0x37 * - tweaked EPSON1250 settings according to Gene and Reinhard * - tweaked HP2200 settings according to Stefan * - added UMAX 3400 entries * - added HP2100 settings according to Craig Smoothey * - added LM9832 based U24 * - added Canon N650U entry * - 0.43 - tweaked HP 2200C entries * - added _WAF_MISC_IO5 for HP lamp switching * - added motor profiles * - cleanup * - 0.44 - added EPSON 1260 and 660 * - added Genius Model strings * - added Canon N670U entry * - added bStepsToReverse to the HwDesc structure * - tweaked EPSON1250 settings for TPA (thanks to Till Kamppeter) * - 0.45 - added UMAX motor settings * - added UMAX 5400 settings * - added CanoScan1240 settings (thanks to Johann Philipp) * - tweaked EPSON 1260 settings * - removed EPSON 660 stuff * - added Canon 1220U entry * - added entry for Compaq S4-100 * - 0.46 - fine-tuning for the CanoScan devices * - fixed HP2200 shading position * - renamed to plustek-usbdevs.c * - 0.47 - added BearPaw 1200 settings for PID 0x4001 (LM9832) * - tweaked the LiDE20 MCLK setting for 75DPI grayscale * - enlarged the scan-area of the UMAX3400 to 11.7" * - added CanoScan D660U * - 0.48 - added another incarnation of the UMAX 3400 * - added parameters for UMAX 3450 TPA * - parameter tuning for CanoScan D660U * - cleanup * - 0.49 - tweaked motor settings for EPSON and CANON1200 * - added support for CanoScan LiDE25 * - 0.50 - cleanup * - removed obsolete _WAF_BLACKFINE * - LiDE20 does not seem to have a reliable black calibration area * so the devices now will switch off the lamp for dark calibration * - added Stephan Februarys' LiDE25 changes * - fixed high-speed feature of CanoScan D660U * - tweaked LiDE25, LiDE30 and N1220U settings * - changed high-speed setting for UMAX 3400, due to bugreport #302317 * - fixed CanoScan N650U settings * - fixed CanoScan N670U settings, see (bugreport #302738) * - added high-speed setting for HP2200 * - 0.51 - tweaked CanoScan N1220U settings again * - added settings for Syscan TravelScan 662 * - tweaked settings for Bearpaw 1200 * - fixed CanoScan LiDE20 settings, cause of various reports, seems * Canon has built-in different motortypes * - also fixed Motorsettings for LiDE30 * - 0.52 - added Q-Scan USB001 settings * - added Q-Scan USB201 settings (thanks to Hiroshi Miura) * - tweaked motor settings for Bearpaw 1200 * - added TravelScan 464 settings * - tweaked highspeed motor settings for Epson 1260 * - tweaked CanoScan N650U motor settings * *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /* the other stuff is included by plustek.c ...*/ #include "plustek-usb.h" /** for Register 0x26 */ #define _ONE_CH_COLOR 0x04 #define _RED_CH 0x00 #define _GREEN_CH 0x08 #define _BLUE_CH 0x10 /* Plustek Model: UT12/UT16 * KH: NS9831 + TPA + Button + NEC3799 */ static DCapsDef Cap0x07B3_0x0017_0 = { { /* Normal */ {0, 93}, /* DataOrigin (X: 0, Y: 8mm from home) */ 0, -1, /* ShadingOriginY, DarkShadOrgY */ {2550, 3508}, /* Size */ {50, 50} /* MinDpi */ }, { /* Positive */ {1040 + 15, 744 - 32},/* DataOrigin (X: 7cm + 1.8cm, Y: 8mm + 5.5cm)*/ 543, -1, /* ShadingOriginY (Y: 8mm + 3.8cm) */ {473, 414}, /* Size (X: 4cm, Y: 3.5cm) */ {150, 150} /* MinDpi */ }, { /* Negative */ {1004 + 55, 744 + 12}, /* DataOrigin (X: 7cm + 1.5cm, Y: 8mm + 5.5cm)*/ /* 533 blaustichig */ 537 /* hell */ /* 543 gruenstichig */ /*543*/, -1, /* ShadingOriginY (Y: 8mm + 3.8cm) */ {567, 414}, /* Size (X: 4.8cm, Y: 3.5cm) */ {150, 150} /* MinDpi */ }, { /* Adf */ {0, 95}, /* DataOrigin (X: 0, Y: 8mm from home) */ 0, -1, /* ShadingOriginY, DarkShadOrgY */ {2550, 3508}, /* Size */ {50, 50} /* MinDpi */ }, {600, 600}, /* OpticDpi */ DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, /* wFlags */ SENSORORDER_rgb, /* bSensorOrder */ 4, /* bSensorDistance */ 4, /* bButtons */ kNEC3799, /* bCCD */ 0x07, /* bPCB */ _WAF_NONE, /* no workarounds or other special stuff needed */ _NO_MIO /* does not use misc I/O for lamp */ }; /* Plustek Model: U24 * Description of the entries, see above... */ static DCapsDef Cap0x07B3_0x0015_0 = { {{0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, {473, 414}, {150, 150}}, {{1004 + 20, 744 + 32}, 543, -1, {567, 414}, {150, 150}}, {{0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {600, 600}, 0, SENSORORDER_rgb, 4, 4, kNEC3799, 0x05, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? * KH: NS9831 + TPA + Button + NEC3799 */ static DCapsDef Cap0x07B3_0x0014_0 = { {{0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, {473, 414}, {150, 150}}, {{1004 + 20, 744 + 32}, 543, -1, {567, 414}, {150, 150}}, {{0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {600, 600}, 0, SENSORORDER_rgb, 4, 0, kNEC3799, 0x04, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? and Genius ColorPage-HR6 V2 * KH: NS9831 + TPA + Button + NEC3799 */ static DCapsDef Cap0x07B3_0x0007_0 = { {{0, 124}, 36, -1, {2550, 3508}, { 50, 50 }}, {{1040, 744}, 543, -1, { 473, 414 }, {150, 150}}, {{1004, 744}, 543, -1, { 567, 414 }, {150, 150}}, {{0, 95}, 0, -1, {2550, 3508}, { 50, 50 }}, {600, 600}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_rgb, 4, 5, kNEC3799, 0x07, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? * Tokyo: NS9832 + Button + SONY548 */ static DCapsDef Cap0x07B3_0x0005_2 = { {{ 0, 64}, 0, -1, {2550, 3508}, { 50, 50 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {600, 600}, 0, SENSORORDER_rgb, 8, 2, kSONY548, 0x05, _WAF_NONE, _NO_MIO }; /* Genius ColorPage-HR7 * Hualien: NS9832 + TPA + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0007_4 = { {{ 0, 111 - 4 }, 0, -1, {2550, 3508}, { 50, 50 }}, {{1040 + 5, 744 - 32}, 543, -1, { 473, 414 }, {150, 150}}, {{1040 - 20, 768 }, 543, -1, { 567, 414 }, {150, 150}}, {{ 0, 95 }, 0, -1, {2550, 3508}, { 50, 50 }}, {1200, 1200}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_rgb, 12, 5, kNEC3778, 0x07, _WAF_NONE, _NO_MIO }; /* Genius ColorPage-HR7LE and ColorPage-HR6X * Hualien: NS9832 + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0005_4 = { {{ 0, 111 - 4 }, 0, -1, {2550, 3508}, {50, 50}}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {1200, 1200}, 0, SENSORORDER_rgb, 12, 5, kNEC3778, 0x05, _WAF_NONE, _NO_MIO }; /* Plustek Model: ???, Genius ColorPage HR6A * KH: NS9831 + TPA + Button + NEC3799 */ static DCapsDef Cap0x07B3_0x000F_0 = { {{ 0, 130}, 12, -1, {2550, 3508}, { 50, 50 }}, {{1040, 744}, 543, -1, { 473, 414 }, {150, 150}}, {{1004, 744}, 543, -1, { 567, 414 }, {150, 150}}, {{ 0, 244}, 12, -1, {2550, 4200}, { 50, 50 }}, {600, 600}, DEVCAPSFLAG_Normal + DEVCAPSFLAG_Adf, SENSORORDER_rgb, 4, 5, kNEC3799, 0x0F, _WAF_NONE, _NO_MIO }; /* Plustek Model: UT12 * KH: NS9831 + TPA + Button + NEC3799 */ static DCapsDef Cap0x07B3_0x0013_0 = { {{ 0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 30, 744 + 32}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {600, 600}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_rgb, 4, 4, kNEC3799, 0x03, _WAF_NONE, _NO_MIO }; /* Plustek Model: U24 * KH: NS9831 + Button + NEC3799 // */ static DCapsDef Cap0x07B3_0x0011_0 = { {{ 0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 + 32}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {600, 600}, 0, SENSORORDER_rgb, 4, 4, kNEC3799, 0x01, _WAF_NONE, _NO_MIO }; /* Plustek Model: U12 * KH: NS9831 + TPA + Button + NEC3799 */ static DCapsDef Cap0x07B3_0x0010_0 = { {{ 0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 + 32}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {600, 600}, 0, SENSORORDER_rgb, 4, 0, kNEC3799, 0x00, _WAF_BSHIFT7_BUG, _NO_MIO }; /* Plustek Model: ??? * KH: NS9831 + TPA + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0013_4 = { {{ 0, 99 /*114*/}, 0, -1, {2550, 3508}, { 50, 50}}, {{ 1055, 744 - 84}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 - 20}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {1200, 1200}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_rgb, 12, 4, kNEC3778, 0x03, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? * KH: NS9831 + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0011_4 = { {{ 0, 99 /*114*/}, 0, -1, {2550, 3508}, { 50, 50}}, {{ 1055, 744 - 84}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 - 20}, 543, -1 ,{ 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {1200, 1200}, 0, SENSORORDER_rgb, 12, 4, kNEC3778, 0x01, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? * KH: NS9831 + TPA + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0010_4 = { {{ 0, 99 /*114*/}, 0, -1, {2550, 3508}, { 50, 50}}, {{ 1055, 744 - 84}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 - 20}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {1200, 1200}, 0, SENSORORDER_rgb, 12, 0, kNEC3778, 0x00, _WAF_NONE, _NO_MIO }; /* Plustek Model: UA18? * KH: NS9831 + TPA + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x000F_4 = { {{ 0, 107}, 0, -1, {2550, 3508}, { 50, 50}}, {{ 1040 + 5, 744 - 32}, 543, -1, { 473, 414}, {150, 150}}, {{1040 - 20, 768}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 244}, 0, -1, {2550, 4200}, { 50, 50}}, {1200, 1200}, DEVCAPSFLAG_Normal + DEVCAPSFLAG_Adf, SENSORORDER_rgb, 12, 5, kNEC3778, 0x0F, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? * KH: NS9831 + TPA + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0016_4 = { {{ 0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{ 954, 422}, 272, -1, { 624, 1940}, {150, 150}}, {{1120, 438}, 275, -1, { 304, 1940}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {1200, 1200}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_rgb, 12, 4, kNEC3778, 0x06, _WAF_NONE, _NO_MIO }; /* Plustek Model: UT24 * KH: NS9832 + TPA + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0017_4 = { {{ 0, 99 - 6}, 0, -1, {2550, 3508}, { 50, 50}}, {{1025 /*1055*/, 744 - 84}, 543, -1, { 473, 414}, {150, 150}}, {{1048 /*1024*/, 754/*724*/}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {1200, 1200}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_rgb, 12, 4, kNEC3778, 0x07, _WAF_NONE, _NO_MIO }; /* Plustek Model: U24 * KH: NS9832 + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0015_4 = { {{ 0, 99 - 6}, 0, -1, {2550, 3508}, { 50, 50}}, {{ 1055, 744 - 84}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 - 20}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {1200, 1200}, 0, SENSORORDER_rgb, 12, 4, kNEC3778, 0x05, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? * KH: NS9832 + TPA + Button + NEC3778 */ static DCapsDef Cap0x07B3_0x0014_4 = { {{ 0, 99 - 6}, 0, -1, {2550, 3508}, { 50, 50}}, {{ 1055, 744 - 84}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 - 20}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {1200, 1200}, 0, SENSORORDER_rgb, 12, 0, kNEC3778, 0x04, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? A3 model * KH: NS9831 + TPA + Button + SONY518 */ static DCapsDef Cap0x07B3_0x0014_1 = { {{ 0, 93}, 0, -1, {3600, 5100}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 + 32}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {400, 400}, 0, SENSORORDER_rgb, 8, 0, kSONY518, 0x04, _WAF_NONE, _NO_MIO }; /* Model: ??? * KH: NS9832 + NEC3799 + 600 DPI Motor (for Brother demo only) */ static DCapsDef Cap0x07B3_0x0012_0 = { {{ 0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 20, 744 + 32}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {600, 600}, 0, SENSORORDER_rgb, 4, 0, kNEC3799, 0x02, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? * KH: NS9831 + TPA + Button + SONY548 */ static DCapsDef Cap0x07B3_0x0017_2 = { {{ 0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, { 473, 414}, {150, 150}}, {{ 1004, 744}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {600, 600}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_bgr, 8, 4, kSONY548, 0x07, _WAF_NONE, _NO_MIO }; /* Plustek Model: ??? * KH: NS9831 + TPA + Button + NEC3799 */ static DCapsDef Cap0x07B3_0x0017_3 = { {{ 0, 93}, 0, -1, {2550, 3508}, { 50, 50}}, {{1040 + 15, 744 - 32}, 543, -1, { 473, 414}, {150, 150}}, {{1004 + 30, 744 + 32}, 543, -1, { 567, 414}, {150, 150}}, {{ 0, 95}, 0, -1, {2550, 3508}, { 50, 50}}, {600, 600}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_rgb, 8, 4, kNEC8861, 0x07, _WAF_NONE, _NO_MIO }; /* Model: HP Scanjet 2100c */ static DCapsDef Cap0x03F0_0x0505 = { {{ 0, 65}, 10, -1, {2550, 3508}, { 50, 50}}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {600, 600}, 0, SENSORORDER_rgb, 4, 0, kNECSLIM, 0x00, _WAF_NONE, _NO_MIO }; /* Model: HP Scanjet 2200c (thanks to Stefan Nilsen) * NS9832 + 2 Buttons + NEC3799 + 600 DPI Motor */ static DCapsDef Cap0x03F0_0x0605 = { /* DataOrigin (x, y), ShadingOriginY */ {{ 0, 209}, 40, -1, {2550, 3508}, { 50, 50}}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {600, 600}, 0, SENSORORDER_rgb, 4, 2, kNECSLIM, 0x00, _WAF_NONE, _NO_MIO }; /* Mustek BearPaw 1200 (thanks to Henning Meier-Geinitz) * NS9831 + 5 Buttons + NEC3798 */ static DCapsDef Cap0x0400_0x1000_0 = { {{ 0, 130}, 20, -1, {2550, 3508}, { 50, 50 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {600, 600}, 0, SENSORORDER_rgb, 8, 5, kNEC8861, 0x00, _WAF_MISC_IO_LAMPS | _WAF_LOFF_ON_START | _WAF_USE_ALT_DESC, _NO_MIO }; /* Mustek BearPaw 2400 * NS9832 + 5 Buttons + SONY548 */ static DCapsDef Cap0x0400_0x1001_0 = { {{ 0, 130/*209*/}, 35/*20*/, -1, {2550, 3508}, { 50, 50 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, { 600, 600 }, /*{ 1200, 1200 }, */ 0, SENSORORDER_rgb, 4,/*16*/ /* sensor distance */ 5, /* number of buttons */ kSONY548, /* CCD type */ 0, _WAF_USE_ALT_DESC, _NO_MIO }; /* Epson Perfection/Photo1250 (thanks to Gene Heskett and Reinhard Max) * Epson Perfection/Photo1260 (thanks to Till Kamppeter) * NS9832 + 4 Buttons + CCD???? */ static DCapsDef Cap0x04B8_0x010F = { /* Normal */ {{ 25, 85}, 10, -1, {2550, 3508}, { 100, 100 }}, /* Positive */ {{ 1100, 972}, 720, -1, { 473, 414}, { 150, 150 }}, /* Negative */ {{ 1116, 1049}, 720, -1, { 567, 414}, { 150, 150 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {1200, 1200}, 0, SENSORORDER_rgb, 8, /* sensor distance */ 4, /* number of buttons */ kEPSON, /* use default settings during calibration */ 0, /* not used here... */ _WAF_MISC_IO_LAMPS, /* use miscio 6 for lamp switching */ _MIO6 + _TPA(_MIO1) /* and miscio 1 for optional TPA */ }; /* Umax 3400/3450 */ static DCapsDef Cap0x1606_0x0060 = { /* Normal */ {{ 30, 105 }, 15, -1, {2550, 3508}, { 100, 100 }}, /* Positive */ {{ 700, 760 }, 650, -1, {1200, 1500}, { 150, 150 }}, /* Negative */ {{ 700, 760 }, 650, -1, {1200, 1500}, { 150, 150 }}, {{ 0, 0 }, 0, -1, {0, 0}, { 0, 0 }}, {600, 600}, DEVCAPSFLAG_LargeTPA, SENSORORDER_bgr, 8, /* sensor distance */ 4, /* number of buttons */ kNEC8861, /* use default settings during calibration */ 0, /* not used here... */ _WAF_MISC_IO_LAMPS, /* use miscio 3 for lamp switching */ _MIO3 + _TPA(_MIO6) /* and miscio 6 for optional TPA */ }; /* Umax 5400 */ static DCapsDef Cap0x1606_0x0160 = { {{ 30, 165}, 0, -1, {2550, 3508}, {100, 100}}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, -1, {0, 0}, { 0, 0 }}, {1200, 1200}, 0, SENSORORDER_bgr, 12, /* sensor distance */ 4, /* number of buttons */ kNEC3778, /* use default settings during calibration */ 0, /* not used here... */ _WAF_MISC_IO_LAMPS, /* use miscio 3 for lamp switching */ _MIO3 }; /* Canon N650U/N656U */ static DCapsDef Cap0x04A9_0x2206 = { {{ 0, 90}, 45, 10, {2550, 3508}, {75, 75}}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {600, 600}, 0, SENSORORDER_rgb, 8, /* sensor distance */ 1, /* number of buttons */ kCIS650, /* use default settings during calibration */ 0, /* not used here... */ _WAF_MISC_IO_LAMPS, _NO_MIO }; /* Canon N1220U */ static DCapsDef Cap0x04A9_0x2207 = { {{ 0, 85}, 45, 10, {2550, 3508}, {75, 75}}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {1200, 1200}, 0, SENSORORDER_rgb, 16, /* sensor distance */ 1, /* number of buttons */ kCIS1220, /* use default settings during calibration */ 0, /* not used here... */ _WAF_MISC_IO_LAMPS, _NO_MIO }; /* Canon D660U */ static DCapsDef Cap0x04A9_0x2208 = { {{ 45, 125}, 15, -1, {2550, 3508}, { 50, 50}}, {{1060, 744}, 510, -1, { 473, 414}, {150, 150}}, {{1082, 842}, 610, -1, { 567, 414}, {150, 150}}, {{ 0, 0}, 0, 0, { 0, 0}, { 0, 0}}, {600, 600}, DEVCAPSFLAG_Positive + DEVCAPSFLAG_Negative, SENSORORDER_rgb, 4, 1, kNEC8861, /* use default settings during calibration */ 0, (_WAF_MISC_IO_LAMPS | _WAF_BIN_FROM_COLOR | _WAF_GRAY_FROM_COLOR), _MIO5 + _TPA(_MIO6) }; /* Canon N670U/N676U/LiDE20 */ static DCapsDef Cap0x04A9_0x220D = { {{ 0, 110}, 45, -1, {2550, 3508}, {75, 75}}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {600, 600}, 0, SENSORORDER_rgb, 8, /* sensor distance */ 3, /* number of buttons */ kCIS670, 0, /* not used here... */ _WAF_MISC_IO_LAMPS, _NO_MIO }; /* Canon N1240U/LiDE30 */ static DCapsDef Cap0x04A9_0x220E = { {{ 0, 100}, 50, 10, {2550, 3508}, {75, 75}}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {1200, 1200}, 0, SENSORORDER_rgb, 16, /* sensor distance */ 3, /* number of buttons */ kCIS1240, 0, /* not used here... */ _WAF_MISC_IO_LAMPS, _NO_MIO }; /* Canon LiDE25 */ static DCapsDef Cap0x04A9_0x2220 = { {{ 0, 100}, 50, 10, {2550, 3508}, {75, 75}}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {1200, 1200}, 0, SENSORORDER_rgb, 16, /* sensor distance */ 3, /* number of buttons */ kCIS1240, 0, /* not used here... */ _WAF_MISC_IO_LAMPS, _NO_MIO }; /* Syscan TravelScan 662 A6 sheet-fed scanner */ static DCapsDef Cap0x0A82_0x6620 = { {{ 0, 0}, 100, -1, {1226, 3508}, {75, 75}}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {600, 600}, DEVCAPSFLAG_SheetFed, SENSORORDER_rgb, 8, 1, kNEC8861, /* use default settings during calibration */ 0, /* not used here... */ (_WAF_MISC_IO_LAMPS | _WAF_MISC_IO_BUTTONS | _WAF_BIN_FROM_COLOR | _WAF_GRAY_FROM_COLOR), _MIO5 + _PORT1 + _PS_INP_MIO2 }; /* Syscan TravelScan 464 A4 sheet-fed scanner */ static DCapsDef Cap0x0A82_0x4600 = { {{ 0, 0}, 150, -1, {2550, 3508}, {75, 75}}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {600, 600}, DEVCAPSFLAG_SheetFed, SENSORORDER_rgb, 8, 1, kNEC8861, /* use default settings during calibration */ 0, /* not used here... */ (_WAF_MISC_IO_LAMPS | _WAF_MISC_IO_BUTTONS | _WAF_BIN_FROM_COLOR | _WAF_GRAY_FROM_COLOR), _MIO5 + _PORT1 + _PS_INP_MIO2 }; /* IRIScan/Q-Scan USB001 A4 sheet-fed scanner */ static DCapsDef Cap0x0A53_0x1000 = { {{ 0, 0}, 150, -1, {2550, 3508}, {150, 150}}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {300, 300}, DEVCAPSFLAG_SheetFed, SENSORORDER_gbr, 2, /* sensor distance */ 0, /* number of buttons */ kNEC8861, /* use default settings during calibration */ 200, /* threshold for resetting sensor-order */ (_WAF_MISC_IO_LAMPS | _WAF_RESET_SO_TO_RGB | _WAF_ONLY_8BIT), _PS_INP1 }; /* PandP USB201 Q-Scan A6 Scanner */ static DCapsDef Cap0x0A53_0x2000 = { {{ 0, 0}, 0, -1, {1226, 3508}, { 50, 50 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {{ 0, 0}, 0, 0, {0, 0}, { 0, 0 }}, {600, 600}, DEVCAPSFLAG_SheetFed, SENSORORDER_rgb, 4, 0, kNEC8861, 0, _WAF_NONE, _PS_INP1 }; /******************* additional Hardware descriptions ************************/ /** U24, UT12 and UT16 */ static HWDef Hw0x07B3_0x0017_0 = { 1.5, /* dMaxMotorSpeed */ 1.2, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 9, /* dIntegrationTimeLowLamp */ 9, /* dIntegrationTimeHighLamp */ 300, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 4, /* dMinIntegrationTimeLowres (ms) */ 5, /* dMinIntegrationTimeHighres (ms) */ 3000, /* wGreenPWMDutyCycleLow */ 4095, /* wGreenPWMDutyCycleHigh */ 0x02, /* bSensorConfiguration (0x0b) */ 0x04, /* bReg_0x0c */ 0x37, /* bReg_0x0d */ 0x13, /* bReg_0x0e */ /* bReg_0x0f_Mono [10] (0x0f to 0x18) */ {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, /* bReg_0x0f_Color [10] (0x0f to 0x18) */ {5, 23, 1, 3, 0, 0, 0, 12, 10, 22}, _GREEN_CH, /* bReg_0x26 color mode - bits 4 and 5 */ 0, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, /* StepperPhaseCorrection (0x1a & 0x1b) */ 14, /* 15, bOpticBlackStart (0x1c) */ 62, /* 60, bOpticBlackEnd (0x1d) */ 110, /* 65, wActivePixelsStart (0x1e & 0x1f) */ 5400, /* 5384 ,wLineEnd (0x20 & 0x21) */ 0, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 0, /* green lamp on (reg 0x30 + 0x31) */ 0, /* green lamp off (reg 0x32 + 0x33) */ 0, /* blue lamp on (reg 0x34 + 0x35) */ 16383, /* blue lamp off (reg 0x36 + 0x37) */ /* Misc */ 3, /* bReg_0x45 */ 0, /* wStepsAfterPaperSensor2 (0x4c & 0x4d) */ 0x1e, /* bstepsToReverse reg 0x50) */ 0xa8, /* 0xfc -bReg_0x51 */ 0, /* bReg_0x54 */ 0xff, /* 0xa3 - bReg_0x55 */ 64, /* bReg_0x56 */ 20, /* bReg_0x57 */ 0x0d, /* bReg_0x58 */ 0x22, /* bReg_0x59 */ 0x82, /* bReg_0x5a */ 0x88, /* bReg_0x5b */ 0, /* bReg_0x5c */ 0, /* bReg_0x5d */ 0, /* bReg_0x5e */ _LM9832, /* chip type */ MODEL_KaoHsiung,/* motorModel */ 1.0 }; /** Genius ColorPage-HR6 V2 and ColorPage-HR6X */ static HWDef Hw0x07B3_0x0007_0 = { 1.5, 1.2, 0.0, 9, 9, 300, 512, 4, 5, 3000, 4095, 0x02, 0x14, 0x27, 0x13, {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, {5, 23, 1, 3, 0, 0, 0, 6, 10, 22}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 14, 62, 110, 5384, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 64, 20, 0x0d, 0x88, 0x28, 0x3b, 0, 0, 0, _LM9832, MODEL_HuaLien, 1.0 }; /** unknown */ static HWDef Hw0x07B3_0x0007_2 = { 1.4, 1.2, 0.0, 9, 9, 600, 512, 4, 5, 3000, 4095, 0x02, 0x3f, 0x2f, 0x36, {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, {7, 20, 1, 4, 7, 10, 0, 6, 12, 0}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 16, 64, 152, 5416, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xfc, 0, 0xff, 64, 20, 0x0d, 0x88, 0x28, 0x3b, 0, 0, 0, _LM9832, MODEL_Tokyo600, 1.0 }; /** Genius ColorPage-HR7 and ColorPage-HR7LE */ static HWDef Hw0x07B3_0x0007_4 = { 1.1, 0.9, 0.0, 12, 12, 600, 2048, 8, 8, 4095, 4095, 0x06, 0x30, 0x2f, 0x2a, {2, 7, 5, 6, 6, 7, 0, 0, 0, 5}, {20, 4, 13, 16, 19, 22, 0, 6, 23, 11}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 13, 62, 304, 10684, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 24, 40, 0x0d, 0x88, 0x28, 0x3b, 0, 0, 0, _LM9832, MODEL_HuaLien, 1.0 }; /** Genius ColorPage-HR6A */ static HWDef Hw0x07B3_0x000F_0 = { 1.5, 1.0, 0.0, 9, 9, 300, 512, 4, 5, 3000, 4095, 0x02, 0x14, 0x27, 0x13, {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, {5, 23, 1, 3, 0, 0, 0, 6, 10, 22}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 14, 62, 110, 5384, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 64, 20, 0x05, 0x88, 0x08, 0x3b, 0, 0, 0, _LM9832, MODEL_HuaLien, 1.0 }; /** U12/UT12 and U24 */ static HWDef Hw0x07B3_0x0013_0 = { 1.5, 1.2, 0.0, 9, 9, 300, 512, 4, 5, 3000, 4095, 0x02, 0x04, 0x37, 0x13, {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, {5, 23, 1, 3, 0, 0, 0, 12, 10, 22}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 14, 62, 110, 5400, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 64, 20, 0x0d, 0x22, 0x82, 0x88, 0, 0, 0, _LM9831, MODEL_KaoHsiung, 1.0 }; /** unknown */ static HWDef Hw0x07B3_0x0013_4 = { 1.0, 0.9, 0.0, 12, 12, 600, 2048, 8, 8, 4095, 4095, 0x06, 0x20, 0x2f, 0x2a, {2, 7, 5, 6, 6, 7, 0, 0, 0, 5}, {20, 4, 13, 16, 19, 22, 0, 0, 23, 11}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 13, 62, 320, 10684, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 10, 48, 0x0d, 0x22, 0x82, 0x88, 0, 0, 0, _LM9831, MODEL_KaoHsiung, 1.0 }; /** unknown */ static HWDef Hw0x07B3_0x000F_4 = { 1.1, 0.9, 0.0, 12, 12, 600, 2048, 8, 8, 4095, 4095, 0x06, 0x30, 0x2f, 0x2a, {2, 7, 5, 6, 6, 7, 0, 0, 0, 5}, {20, 4, 13, 16, 19, 22, 0, 6, 23, 11}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 13, 62, 304, 10684, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 24, 40, 0x05, 0x88, 0x08, 0x3b, 0, 0, 0, _LM9832, MODEL_HuaLien, 1.0 }; /** unknown */ static HWDef Hw0x07B3_0x0016_4 = { 1.0, 0.9, 0.0, 12, 12, 600, 2048, 8, 8, 4095, 4095, 0x06, 0x20, 0x2f, 0x2a, {2, 7, 5, 6, 6, 7, 0, 0, 0, 5}, {20, 4, 13, 16, 19, 22, 0, 0, 23, 11}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 13, 62, 320, 10684, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 10, 48, 0x0d, 0x22, 0x82, 0x88, 0, 0, 0, _LM9832, MODEL_KaoHsiung, 1.0 }; /** Plustek OpticPro UT24 and others... */ static HWDef Hw0x07B3_0x0017_4 = { 1.0, 0.9, 0.0, 12, 12, 600, 2048, 8, 8, 4095, 4095, 0x06, 0x20, 0x2f, 0x2a, {2, 7, 5, 6, 6, 7, 0, 0, 0, 5}, {20, 4, 13, 16, 19, 22, 0, 0, 23, 11}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 13, 62, 320, 10684, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 10, 48, 0x0d, 0x22, 0x82, 0x88, 0, 0, 0, _LM9832, MODEL_KaoHsiung, 1.0 }; /** unknown */ static HWDef Hw0x07B3_0x0017_1 = { 1.5, 1.5, 0.0, 9, 9, 200, 2048, 4, 5, 3000, 4095, 0x02, 0x08, 0x2f, 0x36, {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, {5, 23, 1, 4, 7, 10, 0, 0, 10, 12}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 15, 60, 110, 5415, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 64, 20, 0x0d, 0x22, 0x82, 0x88, 0, 0, 0, _LM9832, MODEL_KaoHsiung, 1.0 }; /** unknown */ static HWDef Hw0x07B3_0x0012_0 = { 1.5, 1.4, 0.0, 9, 9, 600, 2048, 4, 5, 3000, 4095, 0x02, 0x04, 0x37, 0x13, {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, {5, 23, 1, 3, 0, 0, 0, 12, 10, 22}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 14, 62, 110, 5400, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 64, 20, 0x0d, 0x22, 0x82, 0x88, 0, 0, 0, _LM9832, MODEL_KaoHsiung, 1.0 }; /** unknown */ static HWDef Hw0x07B3_0x0017_2 = { 1.5, 1.2, 0.0, 9, 9, 300, 512, 4, 5, 3000, 4095, 0x02, 0, 0x2f, 0x36, {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, {5, 0, 1, 4, 7, 10, 0, 0, 12, 0}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 16, 64, 110, 5416, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 64, 20, 0x0d, 0x22, 0x82, 0x88, 0, 0, 0, _LM9832, MODEL_KaoHsiung, 1.0 }; /** unknown */ static HWDef Hw0x07B3_0x0017_3 = { 1.5, 1.2, 0.0, 9, 9, 300, 512, 4, 5, 3000, 4095, 0x02, 0x04, 0x37, 0x13, {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, {5, 23, 1, 4, 7, 10, 0, 0, 11, 23}, _GREEN_CH, 0, 1, /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, 14, 62, 110, 5400, 0, 16383, 0, 0, 0, 16383, 3, 0, 0x1e, 0xa8, 0, 0xff, 64, 20, 0x0d, 0x22, 0x82, 0x88, 0, 0, 0, _LM9832, MODEL_KaoHsiung, 1.0 }; /** HP Scanjet 2100C */ static HWDef Hw0x03F0_0x0505 = { 1.05, /* dMaxMotorSpeed */ 1.05, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 6, /* dIntegrationTimeLowLamp */ 8, /* dIntegrationTimeHighLamp */ 600, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 6, /* dMinIntegrationTimeLowres (ms) */ 6, /* dMinIntegrationTimeHighres (ms) */ 0, /* wGreenPWMDutyCycleLow */ 0, /* wGreenPWMDutyCycleHigh */ 0x02, /* bSensorConfiguration (0x0b) */ 0x00, /* bReg_0x0c */ 0x2F, /* bReg_0x0d */ 0x13, /* bReg_0x0e */ /* bReg_0x0f_Mono[10] (0x0f to 0x18) */ { 0x02, 0x07, 0x01, 0x02, 0x02, 0x03, 0x00, 0x00, 0x04, 0x07 }, /* bReg_0x0f_Color[10] (0x0f to 0x18) */ { 0x08, 0x17, 0x00, 0x03, 0x08, 0x0b, 0x00, 0x00, 0x0a, 0x14 }, _GREEN_CH, /* bReg_0x26 color mode - bits 4 and 5 */ 0, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, /* StepperPhaseCorrection (0x1a & 0x1b) */ 15, /* bOpticBlackStart (0x1c) */ 50, /* bOpticBlackEnd (0x1d) */ 140, /* wActivePixelsStart (0x1e & 0x1f) */ 5414, /* wLineEnd=(0x20 & 0x21) */ 1, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 16383, /* green lamp on (reg 0x30 + 0x31) */ 1, /* green lamp off (reg 0x32 + 0x33) */ 16383, /* blue lamp on (reg 0x34 + 0x35) */ 1, /* blue lamp off (reg 0x36 + 0x37) */ /* Misc */ 0x13, /* bReg_0x45 */ 0, /* wStepsAfterPaperSensor2 (0x4c & 0x4d) */ 0x1e, /* steps to reverse on buffer full reg 0x50 */ 0xfc, /* 0xa8 -bReg_0x51 */ 0, /* bReg_0x54 */ 0x18, /* bReg_0x55 */ 8, /* bReg_0x56 */ 60, /* bReg_0x57 */ 0x0d, /* bReg_0x58 */ 0xaa, /* bReg_0x59 */ 0xba, /* bReg_0x5a */ 0xbb, /* bReg_0x5b */ 0, /* bReg_0x5c */ 0, /* bReg_0x5d */ 0, /* bReg_0x5e */ _LM9831, MODEL_HP, 1.0 }; /** HP Scanjet 2200C */ static HWDef Hw0x03F0_0x0605 = { 1.05, /* dMaxMotorSpeed */ 1.05, /* dMaxMoveSpeed */ 2.2, /* dHighSpeed */ 6, /* dIntegrationTimeLowLamp */ 8, /* dIntegrationTimeHighLamp */ 600, /* ok wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 6, /* dMinIntegrationTimeLowres (ms) */ 6, /* dMinIntegrationTimeHighres (ms) */ 0, /* wGreenPWMDutyCycleLow */ 0, /* wGreenPWMDutyCycleHigh */ 0x02, /* bSensorConfiguration (0x0b) */ 0x04, /* bReg_0x0c */ 0x2F, /* bReg_0x0d */ 0x1F, /* bReg_0x0e */ /* bReg_0x0f_Mono[10] (0x0f to 0x18) */ { 0x02, 0x07, 0x01, 0x02, 0x02, 0x03, 0x00, 0x00, 0x04, 0x07 }, /* bReg_0x0f_Color[10] (0x0f to 0x18) */ { 0x08, 0x17, 0x00, 0x03, 0x08, 0x0b, 0x00, 0x00, 0x0a, 0x14 }, _GREEN_CH, /* bReg_0x26 color mode - bits 4 and 5 */ 0, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices)*/ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, /* StepperPhaseCorrection (0x1a & 0x1b) */ 14, /* bOpticBlackStart (0x1c) */ 63, /* bOpticBlackEnd (0x1d) */ 140, /* wActivePixelsStart (0x1e & 0x1f) */ 5367, /* wLineEnd=(0x20 & 0x21) */ 1, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 16383, /* green lamp on (reg 0x30 + 0x31) */ 1, /* green lamp off (reg 0x32 + 0x33) */ 16383, /* blue lamp on (reg 0x34 + 0x35) */ 1, /* blue lamp off (reg 0x36 + 0x37) */ /* Misc */ 0x13, /* bReg_0x45 */ 0, /* wStepsAfterPaperSensor2 (0x4c & 0x4d) */ 0x1e, /* steps to reverse on buffer full (0x50) */ 0xfc, /* 0xa8 -bReg_0x51 */ 0, /* bReg_0x54 */ 0x18, /* bReg_0x55 */ 8, /* bReg_0x56 */ 60, /* bReg_0x57 */ 0x0d, /* bReg_0x58 */ 0xcc, /* bReg_0x59 */ 0xbc, /* bReg_0x5a */ 0xbb, /* bReg_0x5b */ 0, /* bReg_0x5c */ 0, /* bReg_0x5d */ 0, /* bReg_0x5e */ _LM9832, MODEL_HP, 1.0 }; /** Mustek BearPaw 1200 */ static HWDef Hw0x0400_0x1000_0 = { 1.75, /* ok dMaxMotorSpeed */ 1.25, /* ok dMaxMoveSpeed */ 0.0, /* ok dHighSpeed */ 12, /* ok dIntegrationTimeLowLamp */ 12, /* ok dIntegrationTimeHighLamp */ 600, /* ok wMotorDpi (Full step DPI) */ 512, /* ok wRAMSize (KB) */ 9, /* ok dMinIntegrationTimeLowres (ms) */ 9, /* ok dMinIntegrationTimeHighres (ms) */ 1169, /* ok wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 1169, /* ok wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x02, /* ok bSensorConfiguration (0x0b) */ 0x7c, /* ok sensor control settings (reg 0x0c) */ 0x3f, /* ok sensor control settings (reg 0x0d) */ 0x15, /* ok sensor control settings (reg 0x0e) */ /* ok mono (reg 0x0f to 0x18) */ { 0x04, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x03, 0x06}, /* ok color (reg 0x0f to 0x18) */ { 0x04, 0x16, 0x01, 0x02, 0x05, 0x06, 0x00, 0x00, 0x0a, 0x16}, _GREEN_CH, /* bReg_0x26 color mode - bits 4 and 5 */ 0, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices)*/ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 257, /* ok StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0x0e, /* ok bOpticBlackStart (reg 0x1c) */ 0x1d, /* ok bOpticBlackEnd (reg 0x1d) */ 140, /* ok wActivePixelsStart (reg 0x1e + 0x1f) */ 5369, /* ok wLineEnd (reg 0x20 + 0x21) */ 0, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 0, /* green lamp on (reg 0x30 + 0x31) */ 0, /* green lamp off (reg 0x32 + 0x33) */ 0, /* blue lamp on (reg 0x34 + 0x35) */ 16383, /* blue lamp off (reg 0x36 + 0x37) */ 0x13, /* ok stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x1e, /* steps to reverse on buffer full (reg 0x50) */ 0xfc, /* ok acceleration profile (reg 0x51) */ 0, /* ok lines to process (reg 0x54) */ 0x13, /* ok kickstart (reg 0x55) */ 0x03, /* ok pwm freq (reg 0x56) */ 0x20, /* ok pwm duty cycle (reg 0x57) */ 0x0d, /* ok Paper sense (reg 0x58) */ 0x44, /* ok misc io12 (reg 0x59) */ 0x44, /* ok misc io34 (reg 0x5a) */ 0x16, /* ok misc io56 (reg 0x5b) */ 0, /* ok test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* ok test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* ok test mode (reg 0x5e) */ _LM9831, MODEL_MUSTEK600, 1.5 }; /** Mustek BearPaw 1200 (LM9832) */ static HWDef Hw0x0400_0x1001_1 = { 1.25, /* ok dMaxMotorSpeed */ 1.25, /* ok dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 12, /* ok dIntegrationTimeLowLamp */ 12, /* ok dIntegrationTimeHighLamp */ 600, /* ok wMotorDpi (Full step DPI) */ 512, /* ok wRAMSize (KB) */ 9, /* ok dMinIntegrationTimeLowres (ms) */ 9, /* ok dMinIntegrationTimeHighres (ms) */ 1169, /* ok wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 1169, /* ok wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x02, /* ok bSensorConfiguration (0x0b) */ 0x7c, /* ok sensor control settings (reg 0x0c) */ 0x3f, /* ok sensor control settings (reg 0x0d) */ 0x15, /* ok sensor control settings (reg 0x0e) */ /* ok mono (reg 0x0f to 0x18) */ { 0x04, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x03, 0x06}, /* ok color (reg 0x0f to 0x18) */ { 0x04, 0x16, 0x01, 0x02, 0x05, 0x06, 0x00, 0x00, 0x0a, 0x16}, _GREEN_CH, /* bReg_0x26 color mode - bits 4 and 5 */ 0, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices)*/ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 257, /* ok StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0x0e, /* ok bOpticBlackStart (reg 0x1c) */ 0x1d, /* ok bOpticBlackEnd (reg 0x1d) */ 140, /* ok wActivePixelsStart (reg 0x1e + 0x1f) */ 5369, /* ok wLineEnd (reg 0x20 + 0x21) */ 0, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 0, /* green lamp on (reg 0x30 + 0x31) */ 0, /* green lamp off (reg 0x32 + 0x33) */ 0, /* blue lamp on (reg 0x34 + 0x35) */ 16383, /* blue lamp off (reg 0x36 + 0x37) */ 0x13, /* ok stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x1e, /* steps to reverse on buffer full (reg 0x50) */ 0xfc, /* ok acceleration profile (reg 0x51) */ 0, /* ok lines to process (reg 0x54) */ 0x13, /* ok kickstart (reg 0x55) */ 0x03, /* ok pwm freq (reg 0x56) */ 0x20, /* ok pwm duty cycle (reg 0x57) */ 0x0d, /* ok Paper sense (reg 0x58) */ 0x44, /* ok misc io12 (reg 0x59) */ 0x44, /* ok misc io34 (reg 0x5a) */ 0x16, /* ok misc io56 (reg 0x5b) */ 0, /* ok test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* ok test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* ok test mode (reg 0x5e) */ _LM9832, MODEL_MUSTEK600, 1.5 }; /** BearPaw 2400 */ static HWDef Hw0x0400_0x1001_0 = { 1.0/*1.8*/, /* ok dMaxMotorSpeed */ 0.9/*1.8*/, /* ok dMaxMoveSpeed */ 0.0, /* ok dHighSpeed */ 12, /* ok dIntegrationTimeLowLamp */ 12, /* ok dIntegrationTimeHighLamp */ 1200 /* 600*/ , /* ok wMotorDpi (Full step DPI) */ 2048, /* ok wRAMSize (KB) */ 9, /* ok dMinIntegrationTimeLowres (ms) */ 9, /* ok dMinIntegrationTimeHighres (ms) */ 1169, /* ok wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 1169, /* ok wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x02 /*0x06*/, /* ok bSensorConfiguration (0x0b) */ 0x3c, /* ok sensor control settings (reg 0x0c) */ 0x3f, /* ok sensor control settings (reg 0x0d) */ 0x11, /* ok sensor control settings (reg 0x0e) */ /* ok mono (reg 0x0f to 0x18) */ {2, 7, 0, 1, 0, 0, 0, 0, 4, 0}, /* {5, 14, 12, 15, 18, 21, 0, 0, 0, 9 },*/ {1, 4, 4, 5, 6, 7, 0, 0, 0, 3 }, _GREEN_CH, /* bReg_0x26 color mode - bits 4 and 5 */ 0, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices)*/ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 257, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 13, /* bOpticBlackStart (reg 0x1c) */ 60, /* bOpticBlackEnd (reg 0x1d) */ 10, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 5416 /* 11000*/, /* wLineEnd (reg 0x20 + 0x21) */ 1, /* ok red lamp on (reg 0x2c + 0x2d) */ 16383, /* ok red lamp off (reg 0x2e + 0x2f) */ 1, /* ok green lamp on (reg 0x30 + 0x31) */ 16383, /* ok green lamp off (reg 0x32 + 0x33) */ 1, /* ok blue lamp on (reg 0x34 + 0x35) */ 16383, /* ok blue lamp off (reg 0x36 + 0x37) */ 0x03, /* ok stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x1e, /* steps to reverse on buffer full (reg 0x50) */ 0xfc, /* ok acceleration profile (reg 0x51) */ 0x03, /* ok lines to process (reg 0x54) */ 0x13, /* Kickstart 0x55 */ 2, /* PWM frequency 0x56 */ 32, /* PWM duty cycle 0x57 */ 0x15, /* paper sense 0x58 */ 0x44, /* misc I/O 0x59 */ 0x44, /* misc I/O 0x5a, */ 0x46, /* misc I/O 0x5b */ 0, 0, 0,/* test registers, set to 0 (0x5c, 0x5d, 0x5e) */ _LM9832, MODEL_MUSTEK1200, 1.0 }; /** EPSON Perfection/Photo 1250 */ static HWDef Hw0x04B8_0x010F = { 0.8, /* dMaxMotorSpeed */ 0.8, /* dMaxMoveSpeed */ 4.1, /* dHighSpeed */ 12, /* dIntegrationTimeLowLamp */ 12, /* dIntegrationTimeHighLamp */ 600, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 4, /* dMinIntegrationTimeLowres (ms) */ 5, /* dMinIntegrationTimeHighres (ms) */ 1, /* ok wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 1, /* ok wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x02, /* ok bSensorConfiguration (0x0b) */ 0x04, /* ok sensor control settings (reg 0x0c) */ 0x7d, /* ok sensor control settings (reg 0x0d) */ 0x37, /* ok sensor control settings (reg 0x0e) */ {0x02, 0x07, 0x00, 0x01, 0x04, 0x07, 0x00, 0x00, 0x03, 0x07}, /* ok mono (reg 0x0f to 0x18) */ {0x06, 0x16, 0x00, 0x05, 0x0c, 0x17, 0x00, 0x00, 0x0a, 0x17}, /* ok color (reg 0x0f to 0x18) */ _GREEN_CH, /* ok bReg_0x26 color mode - bits 4 and 5 */ 0x40, /* ok bReg 0x27 color mode */ 3, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices)*/ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, /* ok StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0x00, /* ok bOpticBlackStart (reg 0x1c) */ 0x42, /* ok bOpticBlackEnd (reg 0x1d) */ 69, /* ok wActivePixelsStart (reg 0x1e + 0x1f) */ 10758, /* ok wLineEnd (reg 0x20 + 0x21) */ 16383, /* ok red lamp on (reg 0x2c + 0x2d) */ 0, /* ok red lamp off (reg 0x2e + 0x2f) */ 16383, /* ok green lamp on (reg 0x30 + 0x31) */ 0, /* ok green lamp off (reg 0x32 + 0x33) */ 16383, /* ok blue lamp on (reg 0x34 + 0x35) */ 0, /* ok blue lamp off (reg 0x36 + 0x37) */ 3, /* ok stepper motor control (reg 0x45) */ 0, /* ok wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x1e, /* steps to reverse on buffer full (reg 0x50) */ 0x0c, /* ok acceleration profile (reg 0x51) */ 0, /* ok lines to process (reg 0x54) */ 0x0f, /* ok kickstart (reg 0x55) */ 0x02, /* ok pwm freq (reg 0x56) */ 1, /* ok pwm duty cycle (reg 0x57) */ 0x0d, /* ok Paper sense (reg 0x58) */ 0x41, /* ok misc io12 (reg 0x59) */ 0x44, /* ok misc io34 (reg 0x5a) */ 0x14, /* ok misc io56 (reg 0x5b) */ 0, /* ok test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* ok test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* ok test mode (reg 0x5e) */ _LM9832, MODEL_EPSON, 1.0 }; /** EPSON Perfection/Photo 1260 */ static HWDef Hw0x04B8_0x011D = { 0.9, /* dMaxMotorSpeed */ 0.8, /* dMaxMoveSpeed */ 3.0, /* dHighSpeed */ 12, /* dIntegrationTimeLowLamp */ 12, /* dIntegrationTimeHighLamp */ 600, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 4, /* dMinIntegrationTimeLowres (ms) */ 5, /* dMinIntegrationTimeHighres (ms) */ 1, /* ok wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 1, /* ok wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x02, /* ok bSensorConfiguration (0x0b) */ 0x04, /* ok sensor control settings (reg 0x0c) */ 0x7d, /* ok sensor control settings (reg 0x0d) */ 0x37, /* ok sensor control settings (reg 0x0e) */ {0x02, 0x07, 0x00, 0x01, 0x04, 0x07, 0x00, 0x00, 0x03, 0x07}, /* ok mono (reg 0x0f to 0x18) */ {0x06, 0x0b, 0x00, 0x05, 0x0c, 0x17, 0x00, 0x00, 0x0a, 0x17}, /* ok color (reg 0x0f to 0x18) */ _GREEN_CH, /* ok bReg_0x26 color mode - bits 4 and 5 */ 0x42, /* ok bReg 0x27 color mode */ 3, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices)*/ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, /* ok StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0x00, /* ok bOpticBlackStart (reg 0x1c) */ 0x42, /* ok bOpticBlackEnd (reg 0x1d) */ 69, /* ok wActivePixelsStart (reg 0x1e + 0x1f) */ 10766, /* ok wLineEnd (reg 0x20 + 0x21) */ 16383, /* ok red lamp on (reg 0x2c + 0x2d) */ 0, /* ok red lamp off (reg 0x2e + 0x2f) */ 16383, /* ok green lamp on (reg 0x30 + 0x31) */ 0, /* ok green lamp off (reg 0x32 + 0x33) */ 16383, /* ok blue lamp on (reg 0x34 + 0x35) */ 0, /* ok blue lamp off (reg 0x36 + 0x37) */ 3, /* ok stepper motor control (reg 0x45) */ 0, /* ok wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x1e, /* steps to reverse on buffer full (reg 0x50) */ 0x0c, /* ok acceleration profile (reg 0x51) */ 0, /* ok lines to process (reg 0x54) */ 0x0f, /* ok kickstart (reg 0x55) */ 0x02, /* ok pwm freq (reg 0x56) */ 1, /* ok pwm duty cycle (reg 0x57) */ 0x0d, /* ok Paper sense (reg 0x58) */ 0x41, /* ok misc io12 (reg 0x59) */ 0x44, /* ok misc io34 (reg 0x5a) */ 0x14, /* ok misc io56 (reg 0x5b) */ 0, /* ok test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* ok test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* ok test mode (reg 0x5e) */ _LM9832, MODEL_EPSON, 1.5 }; /** Umax 3400/3450 */ static HWDef Hw0x1606_0x0060 = { 1.5, /* dMaxMotorSpeed */ 0.8, /* dMaxMoveSpeed */ 2.75, /* dHighSpeed */ 9, /* dIntegrationTimeLowLamp */ 9, /* dIntegrationTimeHighLamp */ 600, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 8, /* dMinIntegrationTimeLowres (ms) */ 8, /* dMinIntegrationTimeHighres (ms) */ 4095, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 4095, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x06, /* bSensorConfiguration (0x0b) */ 0x73, /* sensor control settings (reg 0x0c) */ 0x77, /* sensor control settings (reg 0x0d) */ 0x15, /* sensor control settings (reg 0x0e) */ {0x00, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03}, /* mono (reg 0x0f to 0x18) */ {0x01, 0x0c, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0c}, /* color (reg 0x0f to 0x18) */ _GREEN_CH, /* bReg_0x26 color mode - bits 4 and 5 */ 0x40, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0x2f, /* bOpticBlackStart (reg 0x1c) */ 0x3e, /* bOpticBlackEnd (reg 0x1d) */ 110, /* ? wActivePixelsStart (reg 0x1e + 0x1f) */ 5469, /* wLineEnd (reg 0x20 + 0x21) */ 1, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 0, /* green lamp on (reg 0x30 + 0x31) */ 0, /* green lamp off (reg 0x32 + 0x33) */ 32, /* blue lamp on (reg 0x34 + 0x35) */ 48, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 11, /* steps to reverse on buffer full (reg 0x50)*/ 0xfc, /* acceleration profile (reg 0x51) */ 3, /* lines to process (reg 0x54) */ 0xcb, /* kickstart (reg 0x55) */ 0x05, /* pwm freq (reg 0x56) */ 5, /* pwm duty cycle (reg 0x57) */ 0x0d, /* Paper sense (reg 0x58) */ 0x44, /* misc io12 (reg 0x59) */ 0x45, /* misc io34 (reg 0x5a) */ 0x74, /* misc io56 (reg 0x5b) */ 0, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9832, MODEL_UMAX, 1.0 }; /** Umax 5400 */ static HWDef Hw0x1606_0x0160 = { 1.1, /* dMaxMotorSpeed */ 0.9, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 9, /* dIntegrationTimeLowLamp */ 9, /* dIntegrationTimeHighLamp */ 600, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 8, /* dMinIntegrationTimeLowres (ms) */ 8, /* dMinIntegrationTimeHighres (ms) */ 4095, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 4095, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x06, /* bSensorConfiguration (0x0b) */ 0x73, /* sensor control settings (reg 0x0c) */ 0x77, /* sensor control settings (reg 0x0d) */ 0x25, /* sensor control settings (reg 0x0e) */ /* mono (reg 0x0f to 0x18) */ {0x00, 0x03, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03}, /* color (reg 0x0f to 0x18) */ {0x01, 0x0c, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0c}, _GREEN_CH, /* bReg_0x26 color mode - bits 4 and 5 */ 0x40, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 20, /* bOpticBlackStart (reg 0x1c) */ 45, /* bOpticBlackEnd (reg 0x1d) */ 110, /* ? wActivePixelsStart (reg 0x1e + 0x1f) */ 10669, /* wLineEnd (reg 0x20 + 0x21) */ 1, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 0, /* green lamp on (reg 0x30 + 0x31) */ 0, /* green lamp off (reg 0x32 + 0x33) */ 32, /* blue lamp on (reg 0x34 + 0x35) */ 48, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 11, /* steps to reverse on buffer full (reg 0x50)*/ 0xfc, /* acceleration profile (reg 0x51) */ 3, /* lines to process (reg 0x54) */ 0xcb, /* kickstart (reg 0x55) */ 0x05, /* pwm freq (reg 0x56) */ 5, /* pwm duty cycle (reg 0x57) */ 0x0d, /* Paper sense (reg 0x58) */ 0x44, /* misc io12 (reg 0x59) */ 0x45, /* misc io34 (reg 0x5a) */ 0x7c, /* misc io56 (reg 0x5b) */ 0, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9832, MODEL_UMAX1200, 1.0 }; /** Canon N650U/N656U */ static HWDef Hw0x04A9_0x2206 = { 0.76, /* dMaxMotorSpeed */ 0.243, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* dIntegrationTimeLowLamp */ 100, /* dIntegrationTimeHighLamp */ 1200, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 0, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 0, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x15, /* bSensorConfiguration (0x0b) */ 0x4c, /* sensor control settings (reg 0x0c) */ 0x2f, /* sensor control settings (reg 0x0d) */ 0x00, /* sensor control settings (reg 0x0e) */ /* mono & color (reg 0x0f to 0x18) the same for CIS devices */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05}, {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05}, (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode (runtime) */ /* illumination mode settings */ { 3, 0, 0, 23, 850, 0, 0 }, { 2, 23, 2500, 23, 1800, 23, 950 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0, /* bOpticBlackStart (reg 0x1c) */ 0, /* bOpticBlackEnd (reg 0x1d) */ 89, /* ? wActivePixelsStart (reg 0x1e + 0x1f) */ 6074, /* wLineEnd (reg 0x20 + 0x21) */ 23, /* red lamp on (reg 0x2c + 0x2d) */ 2500, /* red lamp off (reg 0x2e + 0x2f) */ 23, /* green lamp on (reg 0x30 + 0x31) */ 1800, /* green lamp off (reg 0x32 + 0x33) */ 23, /* blue lamp on (reg 0x34 + 0x35) */ 950, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x3f, /* steps to reverse when buffer is full reg 0x50) */ 0xfc, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x0f, /* kickstart (reg 0x55) */ 0x08, /* pwm freq (reg 0x56) */ 0x1f, /* pwm duty cycle (reg 0x57) */ 0x05, /* Paper sense (reg 0x58) */ 0x66, /* misc io12 (reg 0x59) */ 0x16, /* misc io34 (reg 0x5a) */ 0x91, /* misc io56 (reg 0x5b) */ 0x01, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9832, MODEL_CANON600, 2.0 }; /** Canon N1220U */ static HWDef Hw0x04A9_0x2207 = { 0.72, /* dMaxMotorSpeed */ 0.36, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* wIntegrationTimeLowLamp */ 100, /* wIntegrationTimeHighLamp */ 1200, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 0, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 0, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x15, /* bSensorConfiguration (0x0b) */ 0x4c, /* sensor control settings (reg 0x0c) */ 0x2f, /* sensor control settings (reg 0x0d) */ 0x00, /* sensor control settings (reg 0x0e) */ /* mono (reg 0x0f to 0x18) */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05}, /* color (reg 0x0f to 0x18) */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05}, (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode */ { 3, 0, 0, 23, 2200, 0, 0 }, { 2, 23, 16383, 23, 15000, 23, 6600 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0, /* bOpticBlackStart (reg 0x1c) */ 0, /* bOpticBlackEnd (reg 0x1d) */ 124, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 10586, /* wLineEnd (reg 0x20 + 0x21) */ 23, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 23, /* green lamp on (reg 0x30 + 0x31) */ 15000, /* green lamp off (reg 0x32 + 0x33) */ 23, /* blue lamp on (reg 0x34 + 0x35) */ 6600, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0, /* steps to reverse when buffer is full reg 0x50) */ 0xfc, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x0f, /* kickstart (reg 0x55) */ 0x08, /* pwm freq (reg 0x56) */ 0x1f, /* pwm duty cycle (reg 0x57) */ 0x05, /* Paper sense (reg 0x58) */ 0x66, /* misc io12 (reg 0x59) */ 0x16, /* misc io34 (reg 0x5a) */ 0x91, /* misc io56 (reg 0x5b) */ 0x01, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9832, MODEL_CANON1200, 2.0 }; /** Canon D660U */ static HWDef Hw0x04A9_0x2208 = { 1.2, /* dMaxMotorSpeed */ 1.1, /* dMaxMoveSpeed */ 2.75, /* dHighSpeed */ 9, /* dIntegrationTimeLowLamp */ 9, /* dIntegrationTimeHighLamp */ 300, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 8, /* dMinIntegrationTimeLowres (ms) */ 8, /* dMinIntegrationTimeHighres (ms) */ 4095, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 4095, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x02, /* bSensorConfiguration (0x0b) */ 0x60, /* sensor control settings (reg 0x0c) */ 0x2f, /* sensor control settings (reg 0x0d) */ 0x13, /* sensor control settings (reg 0x0e) */ {0x06, 0x17, 0x01, 0x03, 0x05, 0x07, 0x00, 0x00, 0x0b }, {0x06, 0x17, 0x01, 0x03, 0x05, 0x07, 0x00, 0x00, 0x0b }, _GREEN_CH, 0, /* bReg 0x27 color mode */ 1, /* bReg 0x29 illumination mode */ /* illumination mode settings (not used for CCD devices) */ { 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, 0, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 13, /* bOpticBlackStart (reg 0x1c) */ 33, /* bOpticBlackEnd (reg 0x1d) */ 64, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 5440, /* wLineEnd (reg 0x20 + 0x21) */ 16383, /* red lamp on (reg 0x2c + 0x2d) */ 1, /* red lamp off (reg 0x2e + 0x2f) */ 0, /* green lamp on (reg 0x30 + 0x31) */ 0, /* green lamp off (reg 0x32 + 0x33) */ 0, /* blue lamp on (reg 0x34 + 0x35) */ 0, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x20, /* steps to reverse when buffer is full reg 0x50) */ 0xfc, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0, /* kickstart (reg 0x55) */ 0x02, /* pwm freq (reg 0x56) */ 0x1f, /* pwm duty cycle (reg 0x57) */ 0x05, /* Paper sense (reg 0x58) */ 0x44, /* misc io12 (reg 0x59) */ 0x14, /* misc io34 (reg 0x5a) */ 0x11, /* misc io56 (reg 0x5b) */ 0, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9832, MODEL_CANONCCD1200, 1.5 }; /** Canon 670/676/LiDE20 */ static HWDef Hw0x04A9_0x220D = { 0.72, /* dMaxMotorSpeed */ 0.23, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* dIntegrationTimeLowLamp */ 100, /* dIntegrationTimeHighLamp */ 1200, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 0, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 0, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x15, /* bSensorConfiguration (0x0b) */ 0x4c, /* sensor control settings (reg 0x0c) */ 0x2f, /* sensor control settings (reg 0x0d) */ 0x00, /* sensor control settings (reg 0x0e) */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05}, /* mono (reg 0x0f to 0x18) */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05}, /* color (reg 0x0f to 0x18) */ (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode (runtime) */ { 3, 0, 0, 23, 1800, 0, 0 }, { 2, 23, 3800, 23, 3300, 23, 2700 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0, /* bOpticBlackStart (reg 0x1c) */ 0, /* bOpticBlackEnd (reg 0x1d) */ 75, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 6074, /* wLineEnd (reg 0x20 + 0x21) */ 23, /* red lamp on (reg 0x2c + 0x2d) */ 3800, /* red lamp off (reg 0x2e + 0x2f) */ 23, /* green lamp on (reg 0x30 + 0x31) */ 3300, /* green lamp off (reg 0x32 + 0x33) */ 23, /* blue lamp on (reg 0x34 + 0x35) */ 2700, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x3f, /* steps to reverse when buffer is full reg 0x50) */ 0xfc, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x0f, /* kickstart (reg 0x55) */ 0x08, /* pwm freq (reg 0x56) */ 0x1f, /* pwm duty cycle (reg 0x57) */ 0x04, /* Paper sense (reg 0x58) */ 0x66, /* misc io12 (reg 0x59) */ 0x16, /* misc io34 (reg 0x5a) */ 0x91, /* misc io56 (reg 0x5b) */ 0x01, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9833, MODEL_CANON600, 2.0 }; /** Canon N1240U/LiDE30 */ static HWDef Hw0x04A9_0x220E = { 0.72, /* dMaxMotorSpeed */ 0.30, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* wIntegrationTimeLowLamp */ 100, /* wIntegrationTimeHighLamp */ 1200, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 0, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 0, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x15, /* bSensorConfiguration (0x0b) */ 0x4c, /* sensor control settings (reg 0x0c) */ 0x2f, /* sensor control settings (reg 0x0d) */ 0x00, /* sensor control settings (reg 0x0e) */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05}, /* mono (reg 0x0f to 0x18) */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05}, /* color (reg 0x0f to 0x18) */ (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode */ { 3, 0, 0, 23, 3000, 0, 0 }, { 2, 23, 16383, 23, 6500, 23, 4900 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0, /* bOpticBlackStart (reg 0x1c) */ 0, /* bOpticBlackEnd (reg 0x1d) */ 52, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 10586, /* wLineEnd (reg 0x20 + 0x21) */ 23, /* red lamp on (reg 0x2c + 0x2d) */ 16383, /* red lamp off (reg 0x2e + 0x2f) */ 23, /* green lamp on (reg 0x30 + 0x31) */ 6500, /* green lamp off (reg 0x32 + 0x33) */ 23, /* blue lamp on (reg 0x34 + 0x35) */ 4900, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x20, /* steps to reverse when buffer is full reg 0x50) */ 0xfc, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x0f, /* kickstart (reg 0x55) */ 0x08, /* pwm freq (reg 0x56) */ 0x1f, /* pwm duty cycle (reg 0x57) */ 0x04, /* Paper sense (reg 0x58) */ 0x66, /* misc io12 (reg 0x59) */ 0x16, /* misc io34 (reg 0x5a) */ 0x91, /* misc io56 (reg 0x5b) */ 0x01, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9833, MODEL_CANON1200, 2.0 }; /** Canon LiDE25 */ static HWDef Hw0x04A9_0x2220 = { 0.70, /* dMaxMotorSpeed */ 0.25, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* wIntegrationTimeLowLamp */ 100, /* wIntegrationTimeHighLamp */ 1200, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 0, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 0, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x11, /* bSensorConfiguration (0x0b) */ 0x4d, /* sensor control settings (reg 0x0c) */ 0x2f, /* sensor control settings (reg 0x0d) */ 0x00, /* sensor control settings (reg 0x0e) */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x07}, /* mono (reg 0x0f to 0x18) */ {0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x07}, /* color (reg 0x0f to 0x18) */ (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode */ { 3, 0, 0, 50, 3700, 0, 0 }, { 2, 50, 5600, 50, 7100, 50, 4600 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0, /* bOpticBlackStart (reg 0x1c) */ 0, /* bOpticBlackEnd (reg 0x1d) */ 0x7f, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 10559, /* wLineEnd (reg 0x20 + 0x21) */ 50, /* red lamp on (reg 0x2c + 0x2d) */ 5600, /* red lamp off (reg 0x2e + 0x2f) */ 50, /* green lamp on (reg 0x30 + 0x31) */ 7100, /* green lamp off (reg 0x32 + 0x33) */ 50, /* blue lamp on (reg 0x34 + 0x35) */ 4600, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0x20, /* steps to reverse when buffer is full reg 0x50) */ 0xfc, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x0f, /* kickstart (reg 0x55) */ 0x08, /* pwm freq (reg 0x56) */ 0x1f, /* pwm duty cycle (reg 0x57) */ 0x04, /* Paper sense (reg 0x58) */ 0x66, /* misc io12 (reg 0x59) */ 0x16, /* misc io34 (reg 0x5a) */ 0x91, /* misc io56 (reg 0x5b) */ 0x01, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9833, MODEL_CANON_LIDE25, 2.0 }; /** TravelScan 662 */ static HWDef Hw0x0A82_0x6620 = { 0.72, /* dMaxMotorSpeed */ 0.188, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* wIntegrationTimeLowLamp */ 100, /* wIntegrationTimeHighLamp */ 740, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 3000, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 3000, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x0d, /* bSensorConfiguration (0x0b) */ 0x00, /* sensor control settings (reg 0x0c) */ 0x25, /* sensor control settings (reg 0x0d) */ 0x00, /* sensor control settings (reg 0x0e) */ {0x18, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07}, /* mono (reg 0x0f to 0x18) */ {0x18, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07}, /* color (reg 0x0f to 0x18) */ (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode */ { 3, 0, 0, 10, 450, 0, 0 }, { 2, 10, 1000, 10, 880, 10, 630 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 1, /* bOpticBlackStart (reg 0x1c) */ 2, /* bOpticBlackEnd (reg 0x1d) */ 0x17, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 2600, /* wLineEnd (reg 0x20 + 0x21) */ 10, /* red lamp on (reg 0x2c + 0x2d) */ 1000, /* red lamp off (reg 0x2e + 0x2f) */ 10, /* green lamp on (reg 0x30 + 0x31) */ 880, /* green lamp off (reg 0x32 + 0x33) */ 10, /* blue lamp on (reg 0x34 + 0x35) */ 630, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0, /* steps to reverse when buffer is full reg 0x50) */ 0, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x09, /* kickstart (reg 0x55) */ 0x02, /* pwm freq (reg 0x56) */ 0x16, /* pwm duty cycle (reg 0x57) */ 0x01, /* Paper sense (reg 0x58) */ 0x0e, /* misc io12 (reg 0x59) */ 0x96, /* misc io34 (reg 0x5a) */ 0x01, /* misc io56 (reg 0x5b) */ 0, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9833, MODEL_TSCAN, 1.8 }; /** TravelScan 464 */ static HWDef Hw0x0A82_0x4600 = { 0.72, /* dMaxMotorSpeed */ 0.26, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* wIntegrationTimeLowLamp */ 100, /* wIntegrationTimeHighLamp */ 740, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 3000, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 3000, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x0d, /* bSensorConfiguration (0x0b) */ 0x00, /* sensor control settings (reg 0x0c) */ 0x25, /* sensor control settings (reg 0x0d) */ 0x00, /* sensor control settings (reg 0x0e) */ {0x18, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07}, /* mono (reg 0x0f to 0x18) */ {0x18, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07}, /* color (reg 0x0f to 0x18) */ (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode */ { 3, 500, 1045, 500, 990, 500, 990 }, { 2, 500, 1045, 500, 990, 500, 990 }, 1, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 1, /* bOpticBlackStart (reg 0x1c) */ 2, /* bOpticBlackEnd (reg 0x1d) */ 0x17, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 5300, /* wLineEnd (reg 0x20 + 0x21) */ 500, /* red lamp on (reg 0x2c + 0x2d) */ 1045, /* red lamp off (reg 0x2e + 0x2f) */ 500, /* green lamp on (reg 0x30 + 0x31) */ 990, /* green lamp off (reg 0x32 + 0x33) */ 500, /* blue lamp on (reg 0x34 + 0x35) */ 990, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0, /* steps to reverse when buffer is full reg 0x50) */ 0, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x09, /* kickstart (reg 0x55) */ 0x02, /* pwm freq (reg 0x56) */ 0x16, /* pwm duty cycle (reg 0x57) */ 0x01, /* Paper sense (reg 0x58) */ 0x0e, /* misc io12 (reg 0x59) */ 0x96, /* misc io34 (reg 0x5a) */ 0x01, /* misc io56 (reg 0x5b) */ 0, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9833, MODEL_TSCAN_A4, 1.8 }; /** IRIScan/Q-Scan USB001 - Portable Peripheral Co., Ltd. */ static HWDef Hw0x0A53_0x1000 = { 0.50, /* dMaxMotorSpeed */ 0.40, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* wIntegrationTimeLowLamp */ 100, /* wIntegrationTimeHighLamp */ 300, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 4095, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 4095, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x09, /* bSensorConfiguration (0x0b) */ 0x00, /* sensor control settings (reg 0x0c) */ 0x65, /* sensor control settings (reg 0x0d) */ 0x13, /* sensor control settings (reg 0x0e) */ {0x02, 0x07, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02}, /* mono (reg 0x0f to 0x18) */ {0x02, 0x07, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02}, /* color (reg 0x0f to 0x18) */ (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode */ { 3, 0, 0, 2593, 4600, 0, 0 }, { 2, 2593, 7100, 2593, 4600, 2593, 4480 }, 256, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0, /* bOpticBlackStart (reg 0x1c) */ 0x15, /* bOpticBlackEnd (reg 0x1d) */ 0x15, /* wActivePixelsStart (reg 0x1e + 0x1f) */ 5500, /* wLineEnd (reg 0x20 + 0x21) */ 2593, /* red lamp on (reg 0x2c + 0x2d) */ 7100, /* red lamp off (reg 0x2e + 0x2f) */ 2593, /* green lamp on (reg 0x30 + 0x31) */ 4600, /* green lamp off (reg 0x32 + 0x33) */ 2593, /* blue lamp on (reg 0x34 + 0x35) */ 4480, /* blue lamp off (reg 0x36 + 0x37) */ 3, /* stepper motor control (reg 0x45) */ 0, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0, /* steps to reverse when buffer is full reg 0x50) */ 0, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x1b, /* kickstart (reg 0x55) */ 0x08, /* pwm freq (reg 0x56) */ 0x15, /* pwm duty cycle (reg 0x57) */ 0x00, /* Paper sense (reg 0x58) */ 0x00, /* misc io12 (reg 0x59) */ 0x00, /* misc io34 (reg 0x5a) */ 0x00, /* misc io56 (reg 0x5b) */ 0, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9832, MODEL_QSCAN, 1.1 }; /** PandP USB201 Q-Scan A6 Scanner */ static HWDef Hw0x0A53_0x2000 = { 0.5, /* dMaxMotorSpeed */ 0.2, /* dMaxMoveSpeed */ 0.0, /* dHighSpeed */ 100, /* wIntegrationTimeLowLamp */ 100, /* wIntegrationTimeHighLamp */ 570, /* wMotorDpi (Full step DPI) */ 512, /* wRAMSize (KB) */ 3.75, /* dMinIntegrationTimeLowres (ms) */ 5.75, /* dMinIntegrationTimeHighres (ms) */ 0x0fff, /* wGreenPWMDutyCycleLow (reg 0x2a + 0x2b) */ 0x0fff, /* wGreenPWMDutyCycleHigh (reg 0x2a + 0x2b) */ 0x02, /* bSensorConfiguration (0x0b) */ 0x00, /* sensor control settings (reg 0x0c) */ 0x25, /* sensor control settings (reg 0x0d) */ 0x06, /* sensor control settings (reg 0x0e) */ {0x05, 0x0a, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0x04, 0x07}, /* mono (reg 0x0f to 0x18) */ {0x05, 0x0a, 0x01, 0x02, 0x00, 0x01, 0x00, 0x00, 0x04, 0x07}, /* color (reg 0x0f to 0x18) */ (_BLUE_CH | _ONE_CH_COLOR), /* bReg_0x26 color mode */ 0x00, /* bReg 0x27 color mode */ 2, /* bReg 0x29 illumination mode */ { 3, 0, 0, 10, 450, 0, 0 }, /* initial illumination settings - mono */ { 2, 10, 1000, 10, 880, 10, 630 }, /* initial illumination settings - color */ 0x0101, /* StepperPhaseCorrection (reg 0x1a + 0x1b) */ 0x004d, /* bOpticBlackStart (reg 0x22 + 0x23) */ 0x11, /* bOpticBlackEnd */ 0x0011, /* wActivePixelsStart */ 0x0bb8, /* wLineEnd (reg 0x20 + 0x21) */ 10, /* red lamp on (reg 0x2c + 0x2d) */ 1000, /* red lamp off (reg 0x2e + 0x2f) */ 10, /* green lamp on (reg 0x30 + 0x31) */ 880, /* green lamp off (reg 0x32 + 0x33) */ 10, /* blue lamp on (reg 0x34 + 0x35) */ 630, /* blue lamp off (reg 0x36 + 0x37) */ 0x13, /* stepper motor control (reg 0x45) */ 0x0000, /* wStepsAfterPaperSensor2 (reg 0x4c + 0x4d) */ 0, /* steps to reverse when buffer is full reg 0x50) */ 0, /* acceleration profile (reg 0x51) */ 0, /* lines to process (reg 0x54) */ 0x1b, /* kickstart (reg 0x55) */ 0x08, /* pwm freq (reg 0x56) */ 0x15, /* pwm duty cycle (reg 0x57) */ 0x00, /* Paper sense (reg 0x58) */ 0x20, /* misc io12 (reg 0x59) */ 0x02, /* misc io34 (reg 0x5a) */ 0x90, /* misc io56 (reg 0x5b) */ 0, /* test mode ADC Output CODE MSB (reg 0x5c) */ 0, /* test mode ADC Output CODE LSB (reg 0x5d) */ 0, /* test mode (reg 0x5e) */ _LM9832, MODEL_QSCAN_A6, 1.8 }; /******************** all available combinations *****************************/ /** here we have all supported devices and their settings... */ static SetDef Settings[] = { /* Plustek devices... */ /* LM9831 based */ {"0x07B3-0x0010-0", &Cap0x07B3_0x0010_0, &Hw0x07B3_0x0013_0, "OpticPro U12" }, {"0x07B3-0x0011-0", &Cap0x07B3_0x0011_0, &Hw0x07B3_0x0013_0, "OpticPro U24" }, {"0x07B3-0x0013-0", &Cap0x07B3_0x0013_0, &Hw0x07B3_0x0013_0, "OpticPro UT12" }, /* LM9832 based */ {"0x07B3-0x0017-0", &Cap0x07B3_0x0017_0, &Hw0x07B3_0x0017_0, "OpticPro UT12/UT16" }, {"0x07B3-0x0015-0", &Cap0x07B3_0x0015_0, &Hw0x07B3_0x0017_0, "OpticPro U24" }, {"0x07B3-0x0015-4", &Cap0x07B3_0x0015_4, &Hw0x07B3_0x0017_4, "OpticPro U24" }, {"0x07B3-0x0017-4", &Cap0x07B3_0x0017_4, &Hw0x07B3_0x0017_4, "OpticPro UT24" }, /* never seen yet */ {"0x07B3-0x0013-4", &Cap0x07B3_0x0013_4, &Hw0x07B3_0x0013_4, "Unknown device" }, {"0x07B3-0x0011-4", &Cap0x07B3_0x0011_4, &Hw0x07B3_0x0013_4, "Unknown device" }, {"0x07B3-0x0010-4", &Cap0x07B3_0x0010_4, &Hw0x07B3_0x0013_4, "Unknown device" }, {"0x07B3-0x0014-0", &Cap0x07B3_0x0014_0, &Hw0x07B3_0x0017_0, "Unknown device" }, {"0x07B3-0x0014-4", &Cap0x07B3_0x0014_4, &Hw0x07B3_0x0017_4, "Unknown device" }, {"0x07B3-0x0016-4", &Cap0x07B3_0x0016_4, &Hw0x07B3_0x0016_4, "Unknown device" }, {"0x07B3-0x0017-2", &Cap0x07B3_0x0017_2, &Hw0x07B3_0x0017_2, "Unknown device" }, {"0x07B3-0x0017-3", &Cap0x07B3_0x0017_3, &Hw0x07B3_0x0017_3, "Unknown device" }, {"0x07B3-0x0007", &Cap0x07B3_0x0007_0, &Hw0x07B3_0x0007_0, "Unknown device" }, {"0x07B3-0x000F", &Cap0x07B3_0x000F_0, &Hw0x07B3_0x000F_0, "Unknown device" }, {"0x07B3-0x000F-4", &Cap0x07B3_0x000F_4, &Hw0x07B3_0x000F_4, "Unknown device" }, {"0x07B3-0x0005-2", &Cap0x07B3_0x0005_2, &Hw0x07B3_0x0007_2, "Unknown device" }, /* TOKYO 600 */ {"0x07B3-0x0014-1", &Cap0x07B3_0x0014_1, &Hw0x07B3_0x0017_1, "Unknown device" }, /* A3 */ {"0x07B3-0x0012-0", &Cap0x07B3_0x0012_0, &Hw0x07B3_0x0012_0, "Unknown device" }, /* Brother Demo */ /* Mustek BearPaw...*/ {"0x0400-0x1000-0", &Cap0x0400_0x1000_0, &Hw0x0400_0x1000_0, "BearPaw 1200" }, {"0x0400-0x1001-1", &Cap0x0400_0x1000_0, &Hw0x0400_0x1001_1, "BearPaw 1200" }, {"0x0400-0x1001-0", &Cap0x0400_0x1001_0, &Hw0x0400_0x1001_0, "BearPaw 2400" }, /* Genius devices... */ {"0x0458-0x2007", &Cap0x07B3_0x0007_0, &Hw0x07B3_0x0007_0, "ColorPage-HR6 V2" }, {"0x0458-0x2008", &Cap0x07B3_0x0007_0, &Hw0x07B3_0x0007_0, "ColorPage-HR6 V2" }, {"0x0458-0x2009", &Cap0x07B3_0x000F_0, &Hw0x07B3_0x000F_0, "ColorPage-HR6A" }, {"0x0458-0x2013", &Cap0x07B3_0x0007_4, &Hw0x07B3_0x0007_4, "ColorPage-HR7" }, {"0x0458-0x2015", &Cap0x07B3_0x0005_4, &Hw0x07B3_0x0007_4, "ColorPage-HR7LE" }, {"0x0458-0x2016", &Cap0x07B3_0x0005_4, &Hw0x07B3_0x0007_0, "ColorPage-HR6X" }, /* Hewlett Packard... */ {"0x03F0-0x0505", &Cap0x03F0_0x0505, &Hw0x03F0_0x0505, "Scanjet 2100c" }, {"0x03F0-0x0605", &Cap0x03F0_0x0605, &Hw0x03F0_0x0605, "Scanjet 2200c" }, /* EPSON... */ {"0x04B8-0x010F", &Cap0x04B8_0x010F, &Hw0x04B8_0x010F, "Perfection 1250/Photo" }, {"0x04B8-0x011D", &Cap0x04B8_0x010F, &Hw0x04B8_0x011D, "Perfection 1260/Photo" }, /* UMAX... */ {"0x1606-0x0050", &Cap0x1606_0x0060, &Hw0x1606_0x0060, "3400" }, {"0x1606-0x0060", &Cap0x1606_0x0060, &Hw0x1606_0x0060, "3400" }, {"0x1606-0x0160", &Cap0x1606_0x0160, &Hw0x1606_0x0160, "5400" }, /* COMPAQ... */ {"0x049F-0x001A", &Cap0x1606_0x0060, &Hw0x1606_0x0060, "S4-100" }, /* CANON... */ {"0x04A9-0x2206", &Cap0x04A9_0x2206, &Hw0x04A9_0x2206, "CanoScan N650U/N656U" }, {"0x04A9-0x2207", &Cap0x04A9_0x2207, &Hw0x04A9_0x2207, "CanoScan N1220U" }, {"0x04A9-0x2208", &Cap0x04A9_0x2208, &Hw0x04A9_0x2208, "CanoScan D660U" }, {"0x04A9-0x220D", &Cap0x04A9_0x220D, &Hw0x04A9_0x220D, "CanoScan N670U/N676U/LiDE20" }, {"0x04A9-0x220E", &Cap0x04A9_0x220E, &Hw0x04A9_0x220E, "CanoScan N1240U/LiDE30" }, {"0x04A9-0x2220", &Cap0x04A9_0x2220, &Hw0x04A9_0x2220, "CanoScan LiDE25" }, /* SYSCAN... */ {"0x0A82-0x4600", &Cap0x0A82_0x4600, &Hw0x0A82_0x4600, "TravelScan 460/464" }, {"0x0A82-0x6620", &Cap0x0A82_0x6620, &Hw0x0A82_0x6620, "TravelScan 662" }, /* Visioneer... */ {"0x04A7-0x0427", &Cap0x0A82_0x4600, &Hw0x0A82_0x4600, "Strobe XP100" }, /* Portable Peripheral Co., Ltd. */ {"0x0A53-0x1000", &Cap0x0A53_0x1000, &Hw0x0A53_0x1000, "Q-Scan USB001" }, {"0x0A53-0x2000", &Cap0x0A53_0x2000, &Hw0x0A53_0x2000, "Q-Scan USB201" }, /* Please add other devices here... * The first entry is a string, composed out of the vendor and product id, * it's used by the driver to select the device settings. For other devices * than those of Plustek, you'll not need to add the second '-' part * * The second entry decribes the capabilities of the device, you may find * one suitable for your scanner, for a better description of the entries * have a look at the beginning of this file at Cap0x07B3_0x0017_0 for * the UT12 * * The third entry is for the default setting of the LM983x register * settings, you can often find these in your Windoze driver ini * Have a look at the Hw0x0400_0x1000_0 or Hw0x07B3_0x0017_0 for further * description * * The fourth entry is simply the name of the device, which will be * displayed by the frontend */ { NULL, NULL, NULL, NULL } /* last entry, never remove... */ }; /** * tables for the motor settings * The models KaoHsiung, HuaLien and Tokyo600 are currently set * within the code in conjunction with some CCD combinations. * NOTE: the touples PWM and PWM_Duty are used to set the registers * 0x56 and 0x57, the recommended setting is 8,10 * if you notice a whining noise and the motor does not move, * you might increase the MCLK variable. */ static ClkMotorDef Motors[] = { { MODEL_KaoHsiung, 64, 20, 6, /* PWM, PWM_Duty, MCLK for fast move */ 0, 0, /* for lineend adjustment, here disabled */ /* Motor settings (PWM and PWM_Duty) */ {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }}, /* Color mode MCLK settings */ { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, /* Gray mode MCLK settings */ { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 } }, { MODEL_HuaLien, 64, 20, 6, 0, 0, /* Motor settings (PWM and PWM_Duty) */ {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }}, /* Color mode MCLK settings */ { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, /* Gray mode MCLK settings */ { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 } }, { MODEL_Tokyo600, 4, 4, 6, 0, 0, /* Motor settings (PWM and PWM_Duty) */ {{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }}, /* Color mode MCLK settings */ { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, /* Gray mode MCLK settings */ { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }, { 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 } }, { MODEL_MUSTEK600, 4, 4, 6, 0, 0, /* Motor settings (PWM and PWM_Duty) */ {{ 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }}, /* Color mode MCLK settings */ { 4.0, 3.5, 3.5, 4.0, 4.0, 5.0, 5.0, 7.5, 7.5, 7.5 }, { 4.0, 3.5, 3.5, 4.0, 4.0, 5.0, 5.0, 7.5, 7.5, 7.5 }, /* Gray mode MCLK settings */ { 7.5, 7.0, 6.5, 5.5, 5.5, 5.5, 7.0, 7.0, 7.0, 7.0 }, { 7.5, 7.0, 6.5, 5.5, 5.5, 5.5, 7.0, 7.0, 7.0, 7.0 } }, { MODEL_MUSTEK1200, 2, 32, 3, 0, 0, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 2, 32, 1 }, { 2, 32, 1 }, { 2, 32, 1 }, { 2, 32, 1 }, { 2, 32, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 2, 32, 1 }, { 2, 32, 1 }, { 2, 32, 1 }, { 2, 32, 1 }, { 2, 32, 1 }}, /* Color mode MCLK settings */ { 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5 }, { 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5 }, /* Gray mode MCLK settings */ { 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0 }, { 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0 } }, /* settings good for the HP models (tested with 2200)*/ { MODEL_HP, 8, 60, 6, 0, 0, /* Motor settings (PWM and PWM_Duty) */ {{ 8, 60, 1 }, { 8, 60, 1 }, { 8, 60, 1 }, { 8, 60, 1 }, { 8, 60, 1 }, { 8, 60, 1 }, { 8, 60, 1 }, { 8, 60, 1 }, { 8, 60, 1 }, { 8, 60, 1 }}, /* Color mode MCLK settings */ { 4.0, 4.0, 4.0, 4.0, 3.0, 4.0, 6.0, 6.0, 6.0, 6.0 }, { 4.0, 4.0, 4.0, 4.0, 3.0, 4.0, 6.0, 6.0, 6.0, 6.0 }, /* Gray mode MCLK settings */ { 8.0, 8.0, 8.0, 8.0, 8.0, 13.0, 13.0, 13.0, 13.0, 13.0 }, { 8.0, 8.0, 8.0, 8.0, 8.0, 13.0, 13.0, 13.0, 13.0, 13.0 } }, { MODEL_CANON600, 8, 31, 12, 0, 0, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }}, /* Color mode MCLK settings */ { 7.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, { 7.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, /* Gray mode MCLK settings */ { 15.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0 }, { 15.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0 } }, { MODEL_CANON1200, 8, 31, 8, 0, 0, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }}, /* Color mode MCLK settings */ { 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0 }, { 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 5.0, 6.0, 6.0, 6.0 }, /* Gray mode MCLK settings */ { 8.5, 7.0, 5.0, 4.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 }, { 8.5, 6.5, 6.0, 6.0, 6.0, 6.0, 8.0, 12.0, 12.0, 12.0 } }, /* settings good for the UMAX models (tested with 3400) */ { MODEL_UMAX, 16, 4, 6, 0, 0, /* Motor settings (PWM and PWM_Duty) */ {{ 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }}, /* Color mode MCLK settings */ { 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5 }, { 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5 }, /* Gray mode MCLK settings */ { 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5 }, { 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5, 10.5 } }, { MODEL_UMAX1200, 16, 4, 6, 0, 0, /* Motor settings (PWM and PWM_Duty) */ {{ 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }, { 16, 4, 1 }}, /* Color mode MCLK settings */ { 3.0, 3.0, 3.0, 3.0, 3.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, { 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0 }, /* Gray mode MCLK settings */ { 6.0, 6.0, 6.0, 6.0, 6.0, 13.0, 13.0, 13.0, 13.0, 13.0 }, { 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0 } }, /* settings good for the EPSON models */ { MODEL_EPSON, 2, 1, 6, 0, 0, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 2, 1, 1 }, { 2, 1, 1 }, { 2, 1, 1 }, { 2, 1, 1 }, { 2, 1, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 2, 1, 1 }, { 2, 1, 1 }, { 2, 1, 1 }, { 2, 1, 1 }, { 2, 1, 1 }}, /* Color mode MCLK settings */ { 2.0, 2.0, 2.5, 2.5, 2.5, 2.5, 4.0, 4.0, 6.0, 6.0 }, { 2.0, 2.0, 2.5, 2.5, 3.0, 3.0, 3.0, 4.0, 6.0, 6.0 }, /* Gray mode MCLK settings */ { 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 9.0, 9.0, 18.0, 18.0 }, { 6.0, 6.0, 6.0, 6.0, 6.0, 8.0, 9.0, 9.0, 18.0, 18.0 } }, { MODEL_CANONCCD1200, 2, 31, 3, 0, 0, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 2, 31, 1 }, { 2, 31, 1 }, { 2, 31, 1 }, { 2, 31, 1 }, { 2, 31, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 2, 31, 1 }, { 2, 31, 1 }, { 2, 31, 1 }, { 2, 31, 1 }, { 2, 31, 1 }}, /* Color mode MCLK settings */ { 2.0, 2.0, 2.0, 2.5, 2.5, 2.5, 3.0, 3.5, 5.0, 5.0 }, { 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 5.0, 5.0 }, /* Gray mode MCLK settings */ { 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, { 6.5, 6.5, 6.5, 7.0, 8.0, 8.0, 8.0, 10.0, 10.0, 10.0 } }, { MODEL_CANON_LIDE25, 8, 31, 3, 0, 0, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }, { 8, 31, 1 }}, /* Color mode MCLK settings */ { 3.0, 3.0, 3.0, 3.0, 3.5, 3.0, 3.0, 3.0, 3.0, 3.0 }, { 3.0, 3.0, 3.0, 3.0, 3.5, 3.5, 5.0, 6.0, 6.0, 6.0 }, /* Gray mode MCLK settings */ { 8.5, 7.0, 5.0, 4.0, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5 }, { 7.5, 6.5, 6.0, 6.0, 6.0, 6.0, 8.0, 12.0, 12.0, 12.0 } }, { MODEL_TSCAN, 2, 22, 6, 75, 4000, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }}, /* Color mode MCLK settings */ { 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, { 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, /* Gray mode MCLK settings */ { 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0 }, { 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0 }, }, { MODEL_TSCAN_A4, 2, 22, 6, 75, 8400, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }, { 2, 22, 1 }}, /* Color mode MCLK settings */ { 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, { 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, /* Gray mode MCLK settings */ { 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0 }, { 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0 }, }, { MODEL_QSCAN, 8, 21, 6, 300, 4600, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 8, 21, 1 }, { 8, 21, 1 }, { 8, 21, 1 }, { 8, 21, 1 }, { 8, 21, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 8, 21, 1 }, { 8, 21, 1 }, { 8, 21, 1 }, { 8, 21, 1 }, { 8, 21, 1 }}, /* Color mode MCLK settings */ { 6.5, 6.5, 6.5, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, { 6.5, 6.5, 6.5, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, /* Gray mode MCLK settings */ { 6.5, 6.5, 6.5, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, { 6.5, 6.5, 6.5, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 }, }, { MODEL_QSCAN_A6, 8, 15, 6, 0, 0, /* Motor settings (PWM and PWM_Duty) */ /* <=75dpi <=100dpi <=150dpi <=200dpi <=300dpi */ {{ 8, 15, 1}, { 8, 15, 1 }, { 8, 15, 1 }, { 8, 15, 1 }, { 8, 15, 1 }, /* <=400dpi <=600dpi <=800dpi <=1200dpi <=2400dpi */ { 8, 15, 1 }, { 8, 15, 1 }, { 8, 15, 1 }, { 8, 15, 1 }, { 8, 15, 1 }}, /* Color mode MCLK settings */ { 7.5, 7.5, 7.5, 7.5, 7.5, 7.5, 7.5, 7.5, 7.5, 7.5 }, { 7.5, 7.5, 7.5, 7.5, 7.5, 7.5, 7.5, 7.5, 7.5, 7.5 }, /* Gray mode MCLK settings */ { 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0 }, { 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0 }, } }; /* END PLUSTEK-USBDEVS.C ....................................................*/ sane-backends-1.0.27/backend/epson2_usb.c0000664000175000017500000002314012775312261015042 00000000000000#include #include "../include/sane/sanei_usb.h" #include "epson_usb.h" /* generated with epson2usb.pl doc/descriptions/epson2.desc */ SANE_Word sanei_epson_usb_product_ids[] = { 0x101, /* GT-7000U, Perfection 636U */ 0x103, /* GT-6600U, Perfection 610 */ 0x104, /* GT-7600U, GT-7600UF, Perfection 1200U, Perfection 1200U PHOTO */ 0x105, /* Stylus Scan 2000 */ 0x106, /* Stylus Scan 2500 */ 0x107, /* ES-2000, Expression 1600 */ 0x109, /* ES-8500, Expression 1640XL */ 0x10a, /* GT-8700, GT-8700F, Perfection 1640SU, Perfection 1640SU PHOTO */ 0x10b, /* GT-7700U, Perfection 1240U */ 0x10c, /* GT-6700U, Perfection 640U */ 0x10e, /* ES-2200, Expression 1680 */ 0x110, /* GT-8200U, GT-8200UF, Perfection 1650, Perfection 1650 PHOTO */ 0x112, /* GT-9700F, Perfection 2450 PHOTO */ 0x11b, /* GT-9300UF, Perfection 2400 PHOTO */ 0x11c, /* GT-9800F, Perfection 3200 PHOTO */ 0x11e, /* GT-8300UF, Perfection 1660 PHOTO */ 0x126, /* ES-7000H, GT-15000 */ 0x128, /* GT-X700, Perfection 4870 PHOTO */ 0x129, /* ES-10000G, Expression 10000XL */ 0x12a, /* GT-X800, Perfection 4990 PHOTO */ 0x12b, /* ES-H300, GT-2500 */ 0x12c, /* GT-X900, Perfection V700 Photo, Perfection V750 Photo */ 0x135, /* GT-X970 */ 0x138, /* ES-H7200, GT-20000 */ 0x14b, /* ES-G11000, Expression 11000XL */ 0x151, /* GT-X980, Perfection V800 Photo, Perfection V850 Pro */ 0x801, /* CC-600PX, Stylus CX5100, Stylus CX5200 */ 0x802, /* CC-570L, Stylus CX3100, Stylus CX3200 */ 0x805, /* Stylus CX6300, Stylus CX6400 */ 0x806, /* PM-A850, Stylus Photo RX600 */ 0x807, /* Stylus Photo RX500, Stylus Photo RX510 */ 0x808, /* Stylus CX5300, Stylus CX5400 */ 0x80d, /* Stylus CX4500, Stylus CX4600 */ 0x80e, /* PX-A550, Stylus CX3500, Stylus CX3600, Stylus CX3650 */ 0x80f, /* Stylus Photo RX420, Stylus Photo RX425, Stylus Photo RX430 */ 0x810, /* PM-A900, Stylus Photo RX700 */ 0x811, /* PM-A870, Stylus Photo RX620, Stylus Photo RX630 */ 0x813, /* Stylus CX6500, Stylus CX6600 */ 0x814, /* PM-A700 */ 0x815, /* AcuLaser CX11, AcuLaser CX11NF, LP-A500 */ 0x817, /* LP-M5500, LP-M5500F */ 0x818, /* Stylus CX3700, Stylus CX3800, Stylus CX3810, Stylus DX3800 */ 0x819, /* PX-A650, Stylus CX4700, Stylus CX4800, Stylus DX4800, Stylus DX4850 */ 0x81a, /* PM-A750, Stylus Photo RX520, Stylus Photo RX530 */ 0x81c, /* PM-A890, Stylus Photo RX640, Stylus Photo RX650 */ 0x81d, /* PM-A950 */ 0x81f, /* Stylus CX7700, Stylus CX7800 */ 0x820, /* Stylus CX4100, Stylus CX4200, Stylus DX4200 */ 0x827, /* PM-A820, Stylus Photo RX560, Stylus Photo RX580, Stylus Photo RX590 */ 0x828, /* PM-A970 */ 0x829, /* PM-T990 */ 0x82a, /* PM-A920 */ 0x82b, /* Stylus CX4900, Stylus CX5000, Stylus DX5000 */ 0x82e, /* PX-A720, Stylus CX5900, Stylus CX6000, Stylus DX6000 */ 0x82f, /* PX-A620, Stylus CX3900, Stylus DX4000 */ 0x830, /* ME 200, Stylus CX2800, Stylus CX2900 */ 0x833, /* LP-M5600 */ 0x834, /* LP-M6000 */ 0x835, /* AcuLaser CX21 */ 0x836, /* PM-T960 */ 0x837, /* PM-A940, Stylus Photo RX680, Stylus Photo RX685, Stylus Photo RX690 */ 0x838, /* PX-A640, Stylus CX7300, Stylus CX7400, Stylus DX7400 */ 0x839, /* PX-A740, Stylus CX8300, Stylus CX8400, Stylus DX8400 */ 0x83a, /* PX-FA700, Stylus CX9300F, Stylus CX9400Fax, Stylus DX9400F */ 0x83c, /* PM-A840, PM-A840S, Stylus Photo RX585, Stylus Photo RX595, Stylus Photo RX610 */ 0x841, /* ME 300, PX-401A, Stylus NX100, Stylus SX100, Stylus TX100 */ 0x843, /* LP-M5000 */ 0x844, /* Artisan 800, EP-901A, EP-901F, Stylus Photo PX800FW, Stylus Photo TX800FW */ 0x846, /* Artisan 700, EP-801A, Stylus Photo PX700W, Stylus Photo TX700W */ 0x847, /* ME Office 700FW, PX-601F, Stylus Office BX600FW, Stylus Office TX600FW, Stylus SX600FW, WorkForce 600 */ 0x848, /* ME Office 600F, Stylus Office BX300F, Stylus Office TX300F, Stylus NX300 Series */ 0x849, /* Stylus NX200, Stylus SX200, Stylus SX205, Stylus TX200, Stylus TX203, Stylus TX209 */ 0x84a, /* PX-501A, Stylus NX400, Stylus SX400, Stylus SX405, Stylus TX400 */ 0x84c, /* WorkForce 500 */ 0x84d, /* PX-402A, Stylus NX110 Series, Stylus SX110 Series, Stylus TX110 Series */ 0x84f, /* ME OFFICE 510, Stylus NX210 Series, Stylus SX210 Series, Stylus TX210 Series */ 0x850, /* EP-702A, Stylus Photo PX650 Series, Stylus Photo TX650 Series */ 0x851, /* Stylus NX410 Series, Stylus SX410 Series, Stylus TX410 Series */ 0x852, /* Artisan 710 Series, EP-802A, Stylus Photo PX710W Series, Stylus Photo TX710W Series */ 0x853, /* Artisan 810 Series, EP-902A, Stylus Photo PX810FW Series */ 0x854, /* ME OFFICE 650FN Series, Stylus Office BX310FN Series, Stylus Office TX510FN Series, WorkForce 310 Series */ 0x855, /* PX-602F, Stylus Office BX610FW Series, Stylus Office TX610FW Series, Stylus SX610FW Series, WorkForce 610 Series */ 0x856, /* PX-502A, Stylus NX510 Series, Stylus SX510W Series, Stylus TX550W Series */ 0x85c, /* ME 320 Series, ME 330 Series, Stylus NX125, Stylus NX127, Stylus SX125, Stylus TX120 Series */ 0x85d, /* ME OFFICE 960FWD Series, PX-603F, Stylus Office BX625FWD, Stylus Office TX620FWD Series, Stylus SX620FW Series, WorkForce 630 Series */ 0x85e, /* ME OFFICE 900WD Series, PX-503A, Stylus Office BX525WD, Stylus NX625, Stylus SX525WD, Stylus TX560WD Series, WorkForce 625 */ 0x85f, /* Stylus Office BX320FW Series, Stylus Office TX525FW, WorkForce 520 Series */ 0x860, /* Artisan 835, EP-903A, EP-903F, Stylus Photo PX820FWD Series, Stylus Photo TX820FWD Series */ 0x861, /* Artisan 725, EP-803A, EP-803AW, Stylus Photo PX720WD Series, Stylus Photo TX720WD Series */ 0x862, /* EP-703A, Stylus Photo PX660 Series */ 0x863, /* ME OFFICE 620F Series, Stylus Office BX305F, Stylus Office BX305FW, Stylus Office TX320F Series, WorkForce 320 Series */ 0x864, /* ME OFFICE 560W Series, Stylus NX420 Series, Stylus SX420W Series, Stylus TX420W Series */ 0x865, /* ME OFFICE 520 Series, Stylus NX220 Series, Stylus SX218, Stylus TX220 Series */ 0x866, /* AcuLaser MX20DN, AcuLaser MX20DNF, AcuLaser MX21DNF */ 0x869, /* PX-1600F, WF-7510 Series */ 0x86a, /* PX-673F, Stylus Office BX925FWD, WorkForce 840 Series */ 0x870, /* Stylus Office BX305FW Plus, WorkForce 435 */ 0x871, /* K200 Series */ 0x872, /* K300 Series, WorkForce K301 */ 0x873, /* L200 Series */ 0x878, /* Artisan 635, EP-704A */ 0x879, /* Artisan 837, EP-904A, EP-904F, Stylus Photo PX830FWD Series */ 0x87b, /* Artisan 730 Series, EP-804A, EP-804AR, EP-804AW, Stylus Photo PX730WD Series, Stylus Photo TX730WD Series */ 0x87c, /* PX-1700F, WF-7520 Series */ 0x87d, /* PX-B750F, WP-4511, WP-4515, WP-4521, WP-4525, WP-4530 Series, WP-4540 Series */ 0x87e, /* WP-4590 Series */ 0x87f, /* PX-403A */ 0x880, /* ME OFFICE 570W Series, PX-434A, Stylus NX330 Series, Stylus SX430W Series, Stylus TX430W Series */ 0x881, /* ME OFFICE 535, PX-404A, Stylus SX230 Series, Stylus TX235 */ 0x883, /* ME 340 Series, Stylus NX130 Series, Stylus SX130 Series, Stylus TX130 Series */ 0x884, /* Stylus NX430W Series, Stylus SX440W Series, Stylus TX435W */ 0x885, /* Stylus NX230 Series, Stylus SX235W, Stylus TX230W Series */ 0x88d, /* Epson ME 350 */ 0x88f, /* Stylus Office BX635FWD, WorkForce 645 */ 0x890, /* ME OFFICE 940FW Series, Stylus Office BX630FW Series, WorkForce 545 */ 0x891, /* PX-504A, Stylus Office BX535WD, Stylus NX530 Series, Stylus NX635, Stylus SX535WD */ 0x892, /* Stylus Office BX935FWD, WorkForce 845 */ 0x893, /* EP-774A */ 0x894, /* LP-M5300 Series */ 0x895, /* PX-045A, XP-100 Series */ 0x896, /* ME-301, XP-200 Series */ 0x897, /* ME-303, PX-405A */ 0x898, /* ME-401, PX-435A, XP-300 Series, XP-400 Series */ 0x899, /* PX-605F, PX-675F, WF-3520 Series, WF-3530 Series, WF-3540 Series */ 0x89a, /* EP-905F, XP-850 Series */ 0x89b, /* EP-905A, XP-800 Series */ 0x89c, /* EP-805A, EP-805AR, EP-805AW, XP-750 Series */ 0x89d, /* XP-700 Series */ 0x89e, /* EP-775A, EP-775AW, XP-600 Series */ 0x89f, /* EP-705A */ 0x8a0, /* ME-101 */ 0x8a1, /* L210 Series, L350, L351 */ 0x8a5, /* PX-505F, WF-2510 Series */ 0x8a6, /* PX-535F, WF-2520 Series, WF-2530 Series, WF-2540 Series */ 0x8a7, /* WP-M4525, WP-M4521, PX-K751F, WP-M4595 */ 0x8a8, /* L355, L358 */ 0x8a9, /* L550 Series */ 0x8aa, /* M200 Series */ 0x8ab, /* WF-M1560 Series */ 0x8ac, /* AL-MX300DN Series, AL-MX300DNF Series */ 0x8ad, /* LP-M8040, LP-M8040A, LP-M8040F */ 0x8ae, /* PX-046A, XP-211, XP-212, XP-215 */ 0x8af, /* PX-436A, XP-310 Series */ 0x8b0, /* XP-410 Series */ 0x8b3, /* EP-976A3, XP-950 Series */ 0x8b4, /* EP-906F, XP-810 Series */ 0x8b5, /* EP-806AB, EP-806AR, EP-806AW, XP-710 Series */ 0x8b6, /* EP-776AB, EP-776AW, XP-610 Series */ 0x8b7, /* EP-706A, XP-510 Series */ 0x8b8, /* PX-M740F, PX-M741F, WF-3620 Series, WF-3640 Series */ 0x8b9, /* PX-M5040F, PX-M5041F, WF-7610 Series, WF-7620 Series */ 0x8bd, /* PX-M840F, WF-5620 Series, WF-5690 Series */ 0x8be, /* WF-4630 Series, WF-4640 Series */ 0x8bf, /* PX-437A, XP-320 Series */ 0x8c0, /* PX-047A, XP-225 */ 0x8c1, /* XP-420 Series */ 0x8c3, /* PX-M650A, PX-M650F, WF-2650 Series, WF-2660 Series */ 0x8c4, /* WF-2630 Series */ 0x8c5, /* EP-977A3 */ 0x8c6, /* EP-907F, XP-820 Series, XP-860 Series */ 0x8c7, /* EP-807AB, EP-807AR, EP-807AW, XP-720 Series, XP-760 Series */ 0x8c8, /* EP-777A, XP-520 Series, XP-620 Series */ 0x8c9, /* EP-707A */ 0x8ca, /* L850 Series */ 0x8cd, /* WF-R4640 Series, WF-R5690 Series */ 0x8d0, /* PX-M350F, WF-M5690 Series */ 0 /* last entry - this is used for devices that are specified in the config file as "usb " */ }; int sanei_epson_getNumberOfUSBProductIds (void) { return sizeof (sanei_epson_usb_product_ids) / sizeof (SANE_Word); } sane-backends-1.0.27/backend/epsonds-ops.h0000664000175000017500000000352512775312261015247 00000000000000/* * epsonds-ops.h - Epson ESC/I-2 driver. * * Copyright (C) 2015 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ extern void eds_dev_init(epsonds_device *dev); extern SANE_Status eds_dev_post_init(struct epsonds_device *dev); extern SANE_Bool eds_is_model(epsonds_device *dev, const char *model); extern SANE_Status eds_add_resolution(epsonds_device *dev, int r); extern SANE_Status eds_set_resolution_range(epsonds_device *dev, int min, int max); extern void eds_set_fbf_area(epsonds_device *dev, int x, int y, int unit); extern void eds_set_adf_area(epsonds_device *dev, int x, int y, int unit); extern void eds_set_tpu_area(epsonds_device *dev, int x, int y, int unit); extern SANE_Status eds_add_depth(epsonds_device *dev, SANE_Word depth); extern SANE_Status eds_discover_capabilities(epsonds_scanner *s); extern SANE_Status eds_set_extended_scanning_parameters(epsonds_scanner *s); extern SANE_Status eds_set_scanning_parameters(epsonds_scanner *s); extern void eds_setup_block_mode(epsonds_scanner *s); extern SANE_Status eds_init_parameters(epsonds_scanner *s); extern void eds_copy_image_from_ring(epsonds_scanner *s, SANE_Byte *data, SANE_Int max_length, SANE_Int *length); extern SANE_Status eds_ring_init(ring_buffer *ring, SANE_Int size); extern SANE_Status eds_ring_write(ring_buffer *ring, SANE_Byte *buf, SANE_Int size); extern SANE_Int eds_ring_read(ring_buffer *ring, SANE_Byte *buf, SANE_Int size); extern SANE_Int eds_ring_skip(ring_buffer *ring, SANE_Int size); extern SANE_Int eds_ring_avail(ring_buffer *ring); extern void eds_ring_flush(ring_buffer *ring) ; sane-backends-1.0.27/backend/epson2-ops.c0000664000175000017500000016224112775312261014776 00000000000000/* * epson2.c - SANE library for Epson scanners. * * Based on Kazuhiro Sasayama previous * Work on epson.[ch] file from the SANE package. * Please see those files for additional copyrights. * * Copyright (C) 2006-09 Tower Technologies * Author: Alessandro Zummo * * This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. */ #define DEBUG_DECLARE_ONLY #include "sane/config.h" #include /* sleep */ #ifdef HAVE_SYS_SELECT_H #include #endif #include "byteorder.h" #include "epson2.h" #include "epson2-ops.h" #include "epson2-io.h" #include "epson2-commands.h" /* * request identity * | request identity2 * | | request status * | | | request condition * | | | | set color mode * | | | | | start scanning * | | | | | | set data format * | | | | | | | set resolution * | | | | | | | | set zoom * | | | | | | | | | set scan area * | | | | | | | | | | set brightness * | | | | | | | | | | | set gamma * | | | | | | | | | | | | set halftoning * | | | | | | | | | | | | | set color correction * | | | | | | | | | | | | | | initialize scanner * | | | | | | | | | | | | | | | set speed * | | | | | | | | | | | | | | | | set lcount * | | | | | | | | | | | | | | | | | mirror image * | | | | | | | | | | | | | | | | | | set gamma table * | | | | | | | | | | | | | | | | | | | set outline emphasis * | | | | | | | | | | | | | | | | | | | | set dither * | | | | | | | | | | | | | | | | | | | | | set color correction coefficients * | | | | | | | | | | | | | | | | | | | | | | request extension status * | | | | | | | | | | | | | | | | | | | | | | | control an extension * | | | | | | | | | | | | | | | | | | | | | | | | forward feed / eject * | | | | | | | | | | | | | | | | | | | | | | | | | feed * | | | | | | | | | | | | | | | | | | | | | | | | | | request push button status * | | | | | | | | | | | | | | | | | | | | | | | | | | | control auto area segmentation * | | | | | | | | | | | | | | | | | | | | | | | | | | | | set film type * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | set exposure time * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | set bay * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | set threshold * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | set focus position * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | request focus position * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | request extended identity * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | request scanner status * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | */ static struct EpsonCmd epson_cmd[] = { {"A1",'I', 0 ,'F','S', 0 ,'G', 0 ,'R', 0 ,'A', 0 ,{ 0, 0, 0}, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, {"A2",'I', 0 ,'F','S', 0 ,'G','D','R','H','A','L',{-3, 3, 0},'Z','B', 0 ,'@', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, {"B1",'I', 0 ,'F','S','C','G','D','R', 0 ,'A', 0 ,{ 0, 0, 0}, 0 ,'B', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, {"B2",'I', 0 ,'F','S','C','G','D','R','H','A','L',{-3, 3, 0},'Z','B', 0 ,'@', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, {"B3",'I', 0 ,'F','S','C','G','D','R','H','A','L',{-3, 3, 0},'Z','B','M','@', 0 , 0 , 0 , 0 , 0 , 0 ,'m','f','e', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, {"B4",'I', 0 ,'F','S','C','G','D','R','H','A','L',{-3, 3, 0},'Z','B','M','@','g','d', 0 ,'z','Q','b','m','f','e', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, {"B5",'I', 0 ,'F','S','C','G','D','R','H','A','L',{-3, 3, 0},'Z','B','M','@','g','d','K','z','Q','b','m','f','e', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, {"B6",'I', 0 ,'F','S','C','G','D','R','H','A','L',{-3, 3, 0},'Z','B','M','@','g','d','K','z','Q','b','m','f','e', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }, {"B7",'I', 0 ,'F','S','C','G','D','R','H','A','L',{-4, 3, 0},'Z','B','M','@','g','d','K','z','Q','b','m','f','e','\f', 0 ,'!','s','N', 0 , 0 ,'t', 0 , 0 ,'I','F'}, {"B8",'I', 0 ,'F','S','C','G','D','R','H','A','L',{-4, 3, 0},'Z','B','M','@','g','d','K','z','Q','b','m','f','e','\f', 0x19,'!','s','N', 0 , 0 ,'t','p','q','I','F'}, /* XXX 'f' probably not supported on F5 */ {"F5",'I', 0 ,'F','S','C','G','D','R','H','A','L',{-3, 3, 0},'Z', 0 ,'M','@','g','d','K','z','Q', 0 ,'m','f','e','\f', 0 , 0 , 0 ,'N','T','P', 0 , 0 , 0 , 0 , 0 }, {"D1",'I','i','F', 0 ,'C','G','D','R', 0 ,'A', 0 ,{ 0, 0, 0},'Z', 0 , 0 ,'@','g','d', 0 ,'z', 0 , 0 , 0 ,'f', 0 , 0 , 0 ,'!', 0 , 0 , 0 , 0 ,'t', 0 , 0 , 0 , 0 }, {"D2",'I','i','F', 0 ,'C','G','D','R', 0 ,'A', 0 ,{ 0, 0, 0},'Z', 0 , 0 ,'@','g','d', 0 ,'z', 0 , 0 , 0 ,'f','e', 0 , 0 ,'!', 0 ,'N', 0 , 0 ,'t', 0 , 0 , 0 , 0 }, {"D7",'I','i','F', 0 ,'C','G','D','R', 0 ,'A', 0 ,{ 0, 0, 0},'Z', 0 , 0 ,'@','g','d', 0 ,'z', 0 , 0 , 0 ,'f','e','\f', 0 ,'!', 0 ,'N', 0 , 0 ,'t', 0 , 0 , 0 , 0 }, {"D8",'I','i','F', 0 ,'C','G','D','R', 0 ,'A', 0 ,{ 0, 0, 0},'Z', 0 , 0 ,'@','g','d', 0 ,'z', 0 , 0 , 0 ,'f','e','\f', 0 ,'!', 0 ,'N', 0 , 0 ,'t', 0 , 0 , 0 , 0 }, }; extern struct mode_param mode_params[]; /* Define the different scan sources */ #define FBF_STR SANE_I18N("Flatbed") #define TPU_STR SANE_I18N("Transparency Unit") #define TP2_STR SANE_I18N("TPU8x10") #define ADF_STR SANE_I18N("Automatic Document Feeder") /* * source list need one dummy entry (save device settings is crashing). * NOTE: no const - this list gets created while exploring the capabilities * of the scanner. */ extern SANE_String_Const source_list[]; static int film_params[] = { 0, 1, 2, 3 }; extern const int halftone_params[]; static const int dropout_params[] = { 0x00, /* none */ 0x10, /* red */ 0x20, /* green */ 0x30 /* blue */ }; /* * Color correction: * One array for the actual parameters that get sent to the scanner (color_params[]), * one array for the strings that get displayed in the user interface (correction_list[]) * and one array to mark the user defined color correction (correction_userdefined[]). */ static const int correction_params[] = { 0x00, /* None */ 0x01, /* Auto */ 0x01, /* User defined */ }; void e2_dev_init(Epson_Device *dev, const char *devname, int conntype) { DBG(5, "%s\n", __func__); dev->name = NULL; dev->model = NULL; dev->connection = conntype; dev->model_id = 0; dev->sane.name = devname; dev->sane.model = NULL; dev->sane.type = "flatbed scanner"; dev->sane.vendor = "Epson"; dev->optical_res = 0; /* just to have it initialized */ dev->color_shuffle = SANE_FALSE; dev->extension = SANE_FALSE; dev->use_extension = SANE_FALSE; dev->need_color_reorder = SANE_FALSE; dev->need_double_vertical = SANE_FALSE; dev->cct_profile = &epson_cct_profiles[0]; /* default profile */ dev->cmd = &epson_cmd[EPSON_LEVEL_DEFAULT]; /* Change default level when using a network connection */ if (dev->connection == SANE_EPSON_NET) dev->cmd = &epson_cmd[EPSON_LEVEL_B7]; dev->last_res = 0; dev->last_res_preview = 0; /* set resolution to safe values */ dev->res_list_size = 0; dev->res_list = NULL; } SANE_Status e2_dev_post_init(struct Epson_Device *dev) { int i, last; DBG(5, "%s\n", __func__); /* find cct model id */ for (i = 0; epson_cct_models[i].name != NULL; i++) { if (strcmp(epson_cct_models[i].name, dev->model) == 0) { dev->model_id = epson_cct_models[i].id; break; } } /* find cct profile */ for (i = 0; epson_cct_profiles[i].model != 0xFF; i++) { if (epson_cct_profiles[i].model == dev->model_id) { dev->cct_profile = &epson_cct_profiles[i]; break; } } DBG(1, "CCT model id is 0x%02x, profile offset %d\n", dev->model_id, i); /* If we have been unable to obtain supported resolutions * due to the fact we are on the network transport, * add some convenient ones */ if (dev->res_list_size == 0) { int val = (dev->dpi_range.min < 150) ? 150 : dev->dpi_range.min; DBG(1, "cannot obtain resolution list, faking (%d-%d)\n", dev->dpi_range.min, dev->dpi_range.max); if (dev->dpi_range.min <= 25) e2_add_resolution(dev, 25); if (dev->dpi_range.min <= 50) e2_add_resolution(dev, 50); if (dev->dpi_range.min <= 75) e2_add_resolution(dev, 75); if (dev->dpi_range.min <= 100) e2_add_resolution(dev, 100); while (val <= dev->dpi_range.max) { e2_add_resolution(dev, val); val *= 2; } } /* try to expand the resolution list where appropriate */ last = dev->res_list[dev->res_list_size - 1]; DBG(1, "highest available resolution: %d\n", last); if (dev->optical_res > last) { DBG(1, "adding optical resolution (%d)\n", dev->optical_res); e2_add_resolution(dev, dev->optical_res); } /* add missing resolutions for known scanners */ if (e2_dev_model(dev, "GT-X800") || e2_dev_model(dev, "GT-X700")) { DBG(1, "known scanner, integrating resolution list\n"); e2_add_resolution(dev, 4800); e2_add_resolution(dev, 6400); e2_add_resolution(dev, 9600); e2_add_resolution(dev, 12800); last = dev->res_list[dev->res_list_size - 1]; } /* guess for the others */ if (dev->dpi_range.max > last && dev->dpi_range.max != dev->optical_res) { int val = last + last; DBG(1, "integrating resolution list (%d-%d)\n", val, dev->dpi_range.max); while (val <= dev->dpi_range.max) { e2_add_resolution(dev, val); val += last; } } /* * Copy the resolution list to the resolution_list array so that the frontend can * display the correct values */ dev->resolution_list = malloc((dev->res_list_size + 1) * sizeof(SANE_Word)); if (dev->resolution_list == NULL) return SANE_STATUS_NO_MEM; *(dev->resolution_list) = dev->res_list_size; memcpy(&(dev->resolution_list[1]), dev->res_list, dev->res_list_size * sizeof(SANE_Word)); /* establish defaults */ dev->need_reset_on_source_change = SANE_FALSE; if (e2_dev_model(dev, "ES-9000H") || e2_dev_model(dev, "GT-30000")) { dev->cmd->set_focus_position = 0; dev->cmd->feed = 0x19; } if (e2_dev_model(dev, "GT-8200") || e2_dev_model(dev, "Perfection1650") || e2_dev_model(dev, "Perfection1640") || e2_dev_model(dev, "GT-8700")) { dev->cmd->feed = 0; dev->cmd->set_focus_position = 0; dev->need_reset_on_source_change = SANE_TRUE; } return SANE_STATUS_GOOD; } SANE_Bool e2_dev_model(Epson_Device *dev, const char *model) { if (dev->model == NULL) return SANE_FALSE; if (strncmp(dev->model, model, strlen(model)) == 0) return SANE_TRUE; return SANE_FALSE; } void e2_set_cmd_level(SANE_Handle handle, unsigned char *level) { Epson_Scanner *s = (Epson_Scanner *) handle; Epson_Device *dev = s->hw; int n; DBG(1, "%s: %c%c\n", __func__, level[0], level[1]); /* set command type and level */ for (n = 0; n < NELEMS(epson_cmd); n++) { char type_level[3]; sprintf(type_level, "%c%c", level[0], level[1]); if (!strncmp(type_level, epson_cmd[n].level, 2)) break; } if (n < NELEMS(epson_cmd)) { dev->cmd = &epson_cmd[n]; } else { dev->cmd = &epson_cmd[EPSON_LEVEL_DEFAULT]; DBG(1, " unknown type %c or level %c, using %s\n", level[0], level[1], dev->cmd->level); } s->hw->level = dev->cmd->level[1] - '0'; } SANE_Status e2_set_model(Epson_Scanner * s, unsigned char *model, size_t len) { unsigned char *buf; unsigned char *p; struct Epson_Device *dev = s->hw; buf = malloc(len + 1); if (buf == NULL) return SANE_STATUS_NO_MEM; memcpy(buf, model, len); buf[len] = '\0'; p = &buf[len - 1]; while (*p == ' ') { *p = '\0'; p--; } if (dev->model) free(dev->model); dev->model = strndup((const char *) buf, len); dev->sane.model = dev->model; DBG(10, "%s: model is '%s'\n", __func__, dev->model); free(buf); return SANE_STATUS_GOOD; } SANE_Status e2_add_resolution(Epson_Device *dev, int r) { dev->res_list_size++; dev->res_list = (SANE_Int *) realloc(dev->res_list, dev->res_list_size * sizeof(SANE_Word)); DBG(10, "%s: add (dpi): %d\n", __func__, r); if (dev->res_list == NULL) return SANE_STATUS_NO_MEM; dev->res_list[dev->res_list_size - 1] = (SANE_Int) r; return SANE_STATUS_GOOD; } void e2_set_fbf_area(Epson_Scanner * s, int x, int y, int unit) { struct Epson_Device *dev = s->hw; if (x == 0 || y == 0) return; dev->fbf_x_range.min = 0; dev->fbf_x_range.max = SANE_FIX(x * MM_PER_INCH / unit); dev->fbf_x_range.quant = 0; dev->fbf_y_range.min = 0; dev->fbf_y_range.max = SANE_FIX(y * MM_PER_INCH / unit); dev->fbf_y_range.quant = 0; DBG(5, "%s: %f,%f %f,%f %d [mm]\n", __func__, SANE_UNFIX(dev->fbf_x_range.min), SANE_UNFIX(dev->fbf_y_range.min), SANE_UNFIX(dev->fbf_x_range.max), SANE_UNFIX(dev->fbf_y_range.max), unit); } void e2_set_adf_area(struct Epson_Scanner *s, int x, int y, int unit) { struct Epson_Device *dev = s->hw; dev->adf_x_range.min = 0; dev->adf_x_range.max = SANE_FIX(x * MM_PER_INCH / unit); dev->adf_x_range.quant = 0; dev->adf_y_range.min = 0; dev->adf_y_range.max = SANE_FIX(y * MM_PER_INCH / unit); dev->adf_y_range.quant = 0; DBG(5, "%s: %f,%f %f,%f %d [mm]\n", __func__, SANE_UNFIX(dev->adf_x_range.min), SANE_UNFIX(dev->adf_y_range.min), SANE_UNFIX(dev->adf_x_range.max), SANE_UNFIX(dev->adf_y_range.max), unit); } void e2_set_tpu_area(struct Epson_Scanner *s, int x, int y, int unit) { struct Epson_Device *dev = s->hw; dev->tpu_x_range.min = 0; dev->tpu_x_range.max = SANE_FIX(x * MM_PER_INCH / unit); dev->tpu_x_range.quant = 0; dev->tpu_y_range.min = 0; dev->tpu_y_range.max = SANE_FIX(y * MM_PER_INCH / unit); dev->tpu_y_range.quant = 0; DBG(5, "%s: %f,%f %f,%f %d [mm]\n", __func__, SANE_UNFIX(dev->tpu_x_range.min), SANE_UNFIX(dev->tpu_y_range.min), SANE_UNFIX(dev->tpu_x_range.max), SANE_UNFIX(dev->tpu_y_range.max), unit); } void e2_set_tpu2_area(struct Epson_Scanner *s, int x, int y, int unit) { struct Epson_Device *dev = s->hw; dev->tpu2_x_range.min = 0; dev->tpu2_x_range.max = SANE_FIX(x * MM_PER_INCH / unit); dev->tpu2_x_range.quant = 0; dev->tpu2_y_range.min = 0; dev->tpu2_y_range.max = SANE_FIX(y * MM_PER_INCH / unit); dev->tpu2_y_range.quant = 0; DBG(5, "%s: %f,%f %f,%f %d [mm]\n", __func__, SANE_UNFIX(dev->tpu2_x_range.min), SANE_UNFIX(dev->tpu2_y_range.min), SANE_UNFIX(dev->tpu2_x_range.max), SANE_UNFIX(dev->tpu2_y_range.max), unit); } void e2_add_depth(Epson_Device *dev, SANE_Int depth) { DBG(10, "%s: add (bpp): %d\n", __func__, depth); if (depth > dev->maxDepth) dev->maxDepth = depth; dev->depth_list[0]++; dev->depth_list[dev->depth_list[0]] = depth; } /* A little helper function to correct the extended status reply * gotten from scanners with known buggy firmware. */ static void fix_up_extended_status_reply(Epson_Scanner * s, unsigned char *buf) { if (e2_model(s, "ES-9000H") || e2_model(s, "GT-30000")) { DBG(1, "fixing up buggy ADF max scan dimensions.\n"); buf[2] = 0xB0; buf[3] = 0x6D; buf[4] = 0x60; buf[5] = 0x9F; } } SANE_Status e2_discover_capabilities(Epson_Scanner *s) { SANE_Status status; unsigned char scanner_status; Epson_Device *dev = s->hw; SANE_String_Const *source_list_add = source_list; DBG(5, "%s\n", __func__); /* always add flatbed */ *source_list_add++ = FBF_STR; /* ESC I, request identity * this must be the first command on the FilmScan 200 */ if (dev->connection != SANE_EPSON_NET) { unsigned int n, k, x = 0, y = 0; unsigned char *buf, *area; size_t len; status = esci_request_identity(s, &buf, &len); if (status != SANE_STATUS_GOOD) return status; e2_set_cmd_level(s, &buf[0]); /* Setting available resolutions and xy ranges for sane frontend. */ /* cycle thru the resolutions, saving them in a list */ for (n = 2, k = 0; n < len; n += k) { area = buf + n; switch (*area) { case 'R': { int val = area[2] << 8 | area[1]; status = e2_add_resolution(s->hw, val); k = 3; continue; } case 'A': { x = area[2] << 8 | area[1]; y = area[4] << 8 | area[3]; DBG(1, "maximum scan area: %dx%d\n", x, y); k = 5; continue; } default: break; } } /* min and max dpi */ dev->dpi_range.min = dev->res_list[0]; dev->dpi_range.max = dev->res_list[dev->res_list_size - 1]; dev->dpi_range.quant = 0; e2_set_fbf_area(s, x, y, dev->dpi_range.max); free(buf); } /* ESC F, request status */ status = esci_request_status(s, &scanner_status); if (status != SANE_STATUS_GOOD) return status;; /* set capabilities */ if (scanner_status & STATUS_OPTION) dev->extension = SANE_TRUE; if (scanner_status & STATUS_EXT_COMMANDS) dev->extended_commands = 1; /* * Extended status flag request (ESC f). * this also requests the scanner device name from the scanner. * It seems unsupported on the network transport (CX11NF/LP-A500). */ if (dev->cmd->request_extended_status && dev->connection != SANE_EPSON_NET) { unsigned char *es; size_t es_len; DBG(1, "detection with request_extended_status\n"); status = esci_request_extended_status(s, &es, &es_len); if (status != SANE_STATUS_GOOD) return status; /* * Get the device name and copy it to dev->sane.model. * The device name starts at es[0x1A] and is up to 16 bytes long * We are overwriting whatever was set previously! */ if (es_len == CMD_SIZE_EXT_STATUS) /* 42 */ e2_set_model(s, es + 0x1A, 16); if (es[0] & EXT_STATUS_LID) DBG(1, "LID detected\n"); if (es[0] & EXT_STATUS_PB) DBG(1, "push button detected\n"); else dev->cmd->request_push_button_status = 0; /* Flatbed */ e2_set_fbf_area(s, es[13] << 8 | es[12], es[15] << 8 | es[14], dev->dpi_range.max); /* ADF */ if (dev->extension && (es[1] & EXT_STATUS_IST)) { DBG(1, "ADF detected\n"); fix_up_extended_status_reply(s, es); dev->duplex = (es[0] & EXT_STATUS_ADFS) != 0; if (dev->duplex) DBG(1, "ADF supports duplex\n"); if (es[1] & EXT_STATUS_EN) { DBG(1, "ADF is enabled\n"); dev->x_range = &dev->adf_x_range; dev->y_range = &dev->adf_y_range; } e2_set_adf_area(s, es[3] << 8 | es[2], es[5] << 8 | es[4], dev->dpi_range.max); *source_list_add++ = ADF_STR; dev->ADF = SANE_TRUE; } /* TPU */ if (dev->extension && (es[6] & EXT_STATUS_IST)) { DBG(1, "TPU detected\n"); if (es[6] & EXT_STATUS_EN) { DBG(1, "TPU is enabled\n"); dev->x_range = &dev->tpu_x_range; dev->y_range = &dev->tpu_y_range; } e2_set_tpu_area(s, (es[8] << 8 | es[7]), (es[10] << 8 | es[9]), dev->dpi_range.max); *source_list_add++ = TPU_STR; dev->TPU = SANE_TRUE; } free(es); *source_list_add = NULL; /* add end marker to source list */ } /* FS I, request extended identity (B7/B8) */ if (dev->extended_commands && dev->cmd->request_extended_identity) { unsigned char buf[80]; DBG(1, "detection with request_extended_identity\n"); status = esci_request_extended_identity(s, buf); if (status != SANE_STATUS_GOOD) return status; e2_set_cmd_level(s, &buf[0]); dev->maxDepth = buf[67]; /* set model name. it will probably be * different than the one reported by request_identity * for the same unit (i.e. LP-A500 vs CX11) . */ e2_set_model(s, &buf[46], 16); dev->optical_res = le32atoh(&buf[4]); dev->dpi_range.min = le32atoh(&buf[8]); dev->dpi_range.max = le32atoh(&buf[12]); /* Flatbed */ e2_set_fbf_area(s, le32atoh(&buf[20]), le32atoh(&buf[24]), dev->optical_res); /* ADF */ if (le32atoh(&buf[28]) > 0) { e2_set_adf_area(s, le32atoh(&buf[28]), le32atoh(&buf[32]), dev->optical_res); if (!dev->ADF) { *source_list_add++ = ADF_STR; dev->ADF = SANE_TRUE; } if (buf[44] & EXT_IDTY_CAP1_ADFS) { dev->duplex = SANE_TRUE; } } /* TPU */ if (le32atoh(&buf[36]) > 0 && !dev->TPU) { e2_set_tpu_area(s, le32atoh(&buf[36]), le32atoh(&buf[40]), dev->optical_res); *source_list_add++ = TPU_STR; dev->TPU = SANE_TRUE; } /* TPU2 */ if (e2_model(s, "GT-X800") || e2_model(s, "GT-X900") || e2_model(s, "GT-X980")) { if (le32atoh(&buf[68]) > 0 ) { e2_set_tpu2_area(s, le32atoh(&buf[68]), le32atoh(&buf[72]), dev->optical_res); *source_list_add++ = TP2_STR; } } *source_list_add = NULL; /* add end marker to source list */ } else { DBG(1, "no command available to detect capabilities\n"); } /* * request identity 2 (ESC i), if available will * get the information from the scanner and store it in dev */ if (dev->cmd->request_identity2 && dev->connection != SANE_EPSON_NET) { unsigned char *buf; status = esci_request_identity2(s, &buf); if (status != SANE_STATUS_GOOD) return status; /* the first two bytes of the buffer contain the optical resolution */ dev->optical_res = buf[1] << 8 | buf[0]; /* * the 4th and 5th byte contain the line distance. Both values have to * be identical, otherwise this software can not handle this scanner. */ if (buf[4] != buf[5]) { status = SANE_STATUS_INVAL; return status; } dev->max_line_distance = buf[4]; } /* * Check for the max. supported color depth and assign * the values to the bitDepthList. */ dev->depth_list = malloc(sizeof(SANE_Int) * (4 + 1)); if (dev->depth_list == NULL) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } dev->depth_list[0] = 0; /* maximum depth discovery */ DBG(3, "discovering max depth, NAKs are expected\n"); /* add default depth */ e2_add_depth(dev, 8); if (dev->maxDepth >= 12 || dev->maxDepth == 0) { if (esci_set_data_format(s, 12) == SANE_STATUS_GOOD) e2_add_depth(dev, 12); } if (dev->maxDepth >= 14 || dev->maxDepth == 0) { if (esci_set_data_format(s, 14) == SANE_STATUS_GOOD) e2_add_depth(dev, 14); } if (dev->maxDepth >= 16 || dev->maxDepth == 0) { if (esci_set_data_format(s, 16) == SANE_STATUS_GOOD) e2_add_depth(dev, 16); } DBG(1, "maximum supported color depth: %d\n", dev->maxDepth); /* * Check for "request focus position" command. If this command is * supported, then the scanner does also support the "set focus * position" command. * XXX ??? */ if (esci_request_focus_position(s, &s->currentFocusPosition) == SANE_STATUS_GOOD) { DBG(1, "setting focus is supported\n"); dev->focusSupport = SANE_TRUE; s->opt[OPT_FOCUS].cap &= ~SANE_CAP_INACTIVE; /* reflect the current focus position in the GUI */ if (s->currentFocusPosition < 0x4C) { /* focus on glass */ s->val[OPT_FOCUS].w = 0; } else { /* focus 2.5mm above glass */ s->val[OPT_FOCUS].w = 1; } } else { DBG(1, "setting focus is not supported\n"); dev->focusSupport = SANE_FALSE; s->opt[OPT_FOCUS].cap |= SANE_CAP_INACTIVE; s->val[OPT_FOCUS].w = 0; /* on glass - just in case */ } /* Set defaults for no extension. */ dev->x_range = &dev->fbf_x_range; dev->y_range = &dev->fbf_y_range; /* * Correct for a firmware bug in some Perfection 1650 scanners: * Firmware version 1.08 reports only half the vertical scan area, we have * to double the number. To find out if we have to do this, we just compare * is the vertical range is smaller than the horizontal range. */ if ((dev->x_range->max - dev->x_range->min) > (dev->y_range->max - dev->y_range->min)) { DBG(1, "found buggy scan area, doubling it.\n"); dev->y_range->max += (dev->y_range->max - dev->y_range->min); dev->need_double_vertical = SANE_TRUE; dev->need_color_reorder = SANE_TRUE; } /* FS F, request scanner status */ if (dev->extended_commands) { unsigned char buf[16]; status = esci_request_scanner_status(s, buf); if (status != SANE_STATUS_GOOD) return status; } return status; } SANE_Status e2_set_extended_scanning_parameters(Epson_Scanner * s) { unsigned char buf[64]; const struct mode_param *mparam; DBG(1, "%s\n", __func__); mparam = &mode_params[s->val[OPT_MODE].w]; memset(buf, 0x00, sizeof(buf)); /* ESC R, resolution */ htole32a(&buf[0], s->val[OPT_RESOLUTION].w); htole32a(&buf[4], s->val[OPT_RESOLUTION].w); /* ESC A, scanning area */ htole32a(&buf[8], s->left); htole32a(&buf[12], s->top); htole32a(&buf[16], s->params.pixels_per_line); htole32a(&buf[20], s->params.lines); /* * The byte sequence mode was introduced in B5, *for B[34] we need line sequence mode */ /* ESC C, set color */ if ((s->hw->cmd->level[0] == 'D' || (s->hw->cmd->level[0] == 'B' && s->hw->level >= 5)) && mparam->flags == 0x02) { buf[24] = 0x13; } else { buf[24] = mparam->flags | (mparam->dropout_mask & dropout_params[s-> val[OPT_DROPOUT]. w]); } /* ESC D, set data format */ mparam = &mode_params[s->val[OPT_MODE].w]; buf[25] = mparam->depth; /* ESC e, control option */ if (s->hw->extension) { char extensionCtrl; extensionCtrl = (s->hw->use_extension ? 1 : 0); if (s->hw->use_extension && (s->val[OPT_ADF_MODE].w == 1)) { extensionCtrl = 2; } /* Test for TPU2 * Epson Perfection 4990 Command Specifications * JZIS-0075 Rev. A, page 31 */ if (s->hw->use_extension && s->hw->TPU2) { extensionCtrl = 5; } if (s->val[OPT_MODE].w == MODE_INFRARED) { /* only infrared in TPU mode (NOT in TPU2 or flatbeth) * XXX investigate this ... only tested on GT-X800 */ if (extensionCtrl == 1) /* test for TPU */ extensionCtrl = 3; else return SANE_STATUS_UNSUPPORTED; } /* ESC e */ buf[26] = extensionCtrl; /* XXX focus */ } /* ESC g, scanning mode (normal or high speed) */ if (s->val[OPT_PREVIEW].w) buf[27] = 1; /* High speed */ else buf[27] = 0; /* ESC d, block line number */ buf[28] = s->lcount; /* ESC Z, set gamma correction */ buf[29] = 0x01; /* default */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_GAMMA_CORRECTION].cap)) { char val; if (s->hw->cmd->level[0] == 'D') { /* The D1 level has only the two user defined gamma * settings. */ val = gamma_params[s->val[OPT_GAMMA_CORRECTION].w]; } else { val = gamma_params[s->val[OPT_GAMMA_CORRECTION].w]; /* * If "Default" is selected then determine the actual value * to send to the scanner: If bilevel mode, just send the * value from the table (0x01), for grayscale or color mode * add one and send 0x02. */ if (s->val[OPT_GAMMA_CORRECTION].w == 0) { val += mparam->depth == 1 ? 0 : 1; } } buf[29] = val; } /* ESC L, set brightness */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_BRIGHTNESS].cap)) buf[30] = s->val[OPT_BRIGHTNESS].w; /* ESC B, set halftoning mode / halftone processing */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_HALFTONE].cap)) buf[32] = halftone_params[s->val[OPT_HALFTONE].w]; /* ESC s, auto area segmentation */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_AAS].cap)) buf[34] = s->val[OPT_AAS].w; /* ESC Q, set sharpness / sharpness control */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_SHARPNESS].cap)) buf[35] = s->val[OPT_SHARPNESS].w; /* ESC K, set data order / mirroring */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_MIRROR].cap)) buf[36] = s->val[OPT_MIRROR].w; /* ESC N, film type */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_FILM_TYPE].cap)) buf[37] = film_params[s->val[OPT_FILM_TYPE].w]; /* ESC M, color correction */ buf[31] = correction_params[s->val[OPT_COLOR_CORRECTION].w]; /* ESC t, threshold */ buf[33] = s->val[OPT_THRESHOLD].w; return esci_set_scanning_parameter(s, buf); } SANE_Status e2_set_scanning_parameters(Epson_Scanner * s) { SANE_Status status; struct mode_param *mparam = &mode_params[s->val[OPT_MODE].w]; unsigned char color_mode; DBG(1, "%s\n", __func__); /* * There is some undocumented special behavior with the TPU enable/disable. * TPU power ESC e status * on 0 NAK * on 1 ACK * off 0 ACK * off 1 NAK * * It makes no sense to scan with TPU powered on and source flatbed, because * light will come from both sides. */ if (s->hw->extension) { int extensionCtrl; extensionCtrl = (s->hw->use_extension ? 1 : 0); if (s->hw->use_extension && (s->val[OPT_ADF_MODE].w == 1)) extensionCtrl = 2; status = esci_control_extension(s, extensionCtrl); if (status != SANE_STATUS_GOOD) { DBG(1, "you may have to power %s your TPU\n", s->hw->use_extension ? "on" : "off"); DBG(1, "and you may also have to restart the SANE frontend.\n"); return status; } /* XXX use request_extended_status and analyze * buffer to set the scan area for * ES-9000H and GT-30000 */ /* * set the focus position according to the extension used: * if the TPU is selected, then focus 2.5mm above the glass, * otherwise focus on the glass. Scanners that don't support * this feature, will just ignore these calls. */ if (s->hw->focusSupport == SANE_TRUE) { if (s->val[OPT_FOCUS].w == 0) { DBG(1, "setting focus to glass surface\n"); esci_set_focus_position(s, 0x40); } else { DBG(1, "setting focus to 2.5mm above glass\n"); esci_set_focus_position(s, 0x59); } } } /* ESC C, Set color */ color_mode = mparam->flags | (mparam->dropout_mask & dropout_params[s->val[OPT_DROPOUT]. w]); /* * The byte sequence mode was introduced in B5, for B[34] we need line sequence mode * XXX Check what to do for the FilmScan 200 */ if ((s->hw->cmd->level[0] == 'D' || (s->hw->cmd->level[0] == 'B' && s->hw->level >= 5)) && mparam->flags == 0x02) color_mode = 0x13; status = esci_set_color_mode(s, color_mode); if (status != SANE_STATUS_GOOD) return status; /* ESC D, set data format */ DBG(1, "%s: setting data format to %d bits\n", __func__, mparam->depth); status = esci_set_data_format(s, mparam->depth); if (status != SANE_STATUS_GOOD) return status; /* ESC B, set halftoning mode */ if (s->hw->cmd->set_halftoning && SANE_OPTION_IS_ACTIVE(s->opt[OPT_HALFTONE].cap)) { status = esci_set_halftoning(s, halftone_params[s-> val [OPT_HALFTONE]. w]); if (status != SANE_STATUS_GOOD) return status; } /* ESC L, set brightness */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_BRIGHTNESS].cap)) { status = esci_set_bright(s, s->val[OPT_BRIGHTNESS].w); if (status != SANE_STATUS_GOOD) return status; } if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_AAS].cap)) { status = esci_set_auto_area_segmentation(s, s->val[OPT_AAS].w); if (status != SANE_STATUS_GOOD) return status; } if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_FILM_TYPE].cap)) { status = esci_set_film_type(s, film_params[s->val[OPT_FILM_TYPE].w]); if (status != SANE_STATUS_GOOD) return status; } if (s->hw->cmd->set_gamma && SANE_OPTION_IS_ACTIVE(s->opt[OPT_GAMMA_CORRECTION].cap)) { int val; if (s->hw->cmd->level[0] == 'D') { /* * The D1 level has only the two user defined gamma * settings. */ val = gamma_params[s->val[OPT_GAMMA_CORRECTION].w]; } else { val = gamma_params[s->val[OPT_GAMMA_CORRECTION].w]; /* * If "Default" is selected then determine the actual value * to send to the scanner: If bilevel mode, just send the * value from the table (0x01), for grayscale or color mode * add one and send 0x02. */ /* if( s->val[ OPT_GAMMA_CORRECTION].w <= 1) { */ if (s->val[OPT_GAMMA_CORRECTION].w == 0) { val += mparam->depth == 1 ? 0 : 1; } } status = esci_set_gamma(s, val); if (status != SANE_STATUS_GOOD) return status; } if (s->hw->cmd->set_threshold != 0 && SANE_OPTION_IS_ACTIVE(s->opt[OPT_THRESHOLD].cap)) { status = esci_set_threshold(s, s->val[OPT_THRESHOLD].w); if (status != SANE_STATUS_GOOD) return status; } /* XXX ESC Z here */ /* ESC M, set color correction */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_COLOR_CORRECTION].cap)) { status = esci_set_color_correction(s, correction_params[s->val[OPT_COLOR_CORRECTION].w]); if (status != SANE_STATUS_GOOD) return status; } /* ESC Q, set sharpness */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_SHARPNESS].cap)) { status = esci_set_sharpness(s, s->val[OPT_SHARPNESS].w); if (status != SANE_STATUS_GOOD) return status; } /* ESC g, set scanning mode */ if (s->val[OPT_PREVIEW].w) status = esci_set_speed(s, 1); else status = esci_set_speed(s, 0); if (status != SANE_STATUS_GOOD) return status; /* ESC K, set data order */ if (SANE_OPTION_IS_ACTIVE(s->opt[OPT_MIRROR].cap)) { status = esci_mirror_image(s, s->val[OPT_MIRROR].w); if (status != SANE_STATUS_GOOD) return status; } /* ESC R */ status = esci_set_resolution(s, s->val[OPT_RESOLUTION].w, s->val[OPT_RESOLUTION].w); if (status != SANE_STATUS_GOOD) return status; /* ESC H, set zoom */ /* not implemented */ /* ESC A, set scanning area */ /* * Modify the scan area: If the scanner requires color shuffling, then we try to * scan more lines to compensate for the lines that will be removed from the scan * due to the color shuffling algorithm. */ if (s->hw->color_shuffle == SANE_TRUE) { unsigned int lines = s->params.lines + (2 * s->line_distance); int top = s->top - (1 * s->line_distance); if (top < 0) top = 0; status = esci_set_scan_area(s, s->left, top, s->params.pixels_per_line, lines); } else { status = esci_set_scan_area(s, s->left, s->top, s->params.pixels_per_line, s->params.lines); } if (status != SANE_STATUS_GOOD) return status; /* ESC d, set block line number / set line counter */ status = esci_set_lcount(s, s->lcount); if (status != SANE_STATUS_GOOD) return status; return SANE_STATUS_GOOD; } void e2_setup_block_mode(Epson_Scanner * s) { int maxreq; DBG(5, "%s\n", __func__); s->block = SANE_TRUE; if (s->hw->connection == SANE_EPSON_SCSI) maxreq = sanei_scsi_max_request_size; else if (s->hw->connection == SANE_EPSON_USB) maxreq = 128 * 1024; else maxreq = 32 * 1024; /* XXX verify if this can b extended to other models */ if (s->hw->connection == SANE_EPSON_NET && e2_model(s, "LP-A500")) maxreq = 64 * 1024; s->lcount = maxreq / s->params.bytes_per_line; DBG(1, "max req size: %d, line count: %d\n", maxreq, s->lcount); /* XXX investigate this */ if (s->lcount < 3 && (e2_model(s, "GT-X800") || e2_model(s, "GT-X900") || e2_model(s, "GT-X980"))) { s->lcount = 21; DBG(17, "%s: set lcount = %i bigger than sanei_scsi_max_request_size\n", __func__, s->lcount); } if (s->lcount >= 255) s->lcount = 255; /* XXX why this? */ if (s->hw->TPU && s->hw->use_extension && s->lcount > 32) s->lcount = 32; /* * The D1 series of scanners only allow an even line number * for bi-level scanning. If a bit depth of 1 is selected, then * make sure the next lower even number is selected. */ /* XXX check bith depth? */ if (s->hw->cmd->level[0] == 'D' && s->lcount > 3 && s->lcount % 2) s->lcount -= 1; DBG(1, "final line count is %d\n", s->lcount); } SANE_Status e2_init_parameters(Epson_Scanner * s) { int dpi, bytes_per_pixel; struct mode_param *mparam; DBG(5, "%s\n", __func__); memset(&s->params, 0, sizeof(SANE_Parameters)); dpi = s->val[OPT_RESOLUTION].w; mparam = &mode_params[s->val[OPT_MODE].w]; if (SANE_UNFIX(s->val[OPT_BR_Y].w) == 0 || SANE_UNFIX(s->val[OPT_BR_X].w) == 0) return SANE_STATUS_INVAL; s->left = ((SANE_UNFIX(s->val[OPT_TL_X].w) / MM_PER_INCH) * s->val[OPT_RESOLUTION].w) + 0.5; s->top = ((SANE_UNFIX(s->val[OPT_TL_Y].w) / MM_PER_INCH) * s->val[OPT_RESOLUTION].w) + 0.5; s->params.pixels_per_line = ((SANE_UNFIX(s->val[OPT_BR_X].w - s->val[OPT_TL_X].w) / MM_PER_INCH) * dpi) + 0.5; s->params.lines = ((SANE_UNFIX(s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w) / MM_PER_INCH) * dpi) + 0.5; DBG(1, "%s: resolution = %d, preview = %d\n", __func__, s->val[OPT_RESOLUTION].w, s->val[OPT_PREVIEW].w); DBG(1, "%s: %p %p tlx %f tly %f brx %f bry %f [mm]\n", __func__, (void *) s, (void *) s->val, SANE_UNFIX(s->val[OPT_TL_X].w), SANE_UNFIX(s->val[OPT_TL_Y].w), SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w)); /* * Calculate bytes_per_pixel and bytes_per_line for * any color depths. * * The default color depth is stored in mode_params.depth: */ if (mode_params[s->val[OPT_MODE].w].depth == 1) s->params.depth = 1; else s->params.depth = s->val[OPT_BIT_DEPTH].w; if (s->params.depth > 8) { s->params.depth = 16; /* * The frontends can only handle 8 or 16 bits * for gray or color - so if it's more than 8, * it gets automatically set to 16. This works * as long as EPSON does not come out with a * scanner that can handle more than 16 bits * per color channel. */ } /* this works because it can only be set to 1, 8 or 16 */ bytes_per_pixel = s->params.depth / 8; if (s->params.depth % 8) { /* just in case ... */ bytes_per_pixel++; } /* pixels_per_line is rounded to the next 8bit boundary */ s->params.pixels_per_line = s->params.pixels_per_line & ~7; s->params.last_frame = SANE_TRUE; switch (s->val[OPT_MODE].w) { case MODE_BINARY: case MODE_GRAY: s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8; break; case MODE_COLOR: s->params.format = SANE_FRAME_RGB; s->params.bytes_per_line = 3 * s->params.pixels_per_line * bytes_per_pixel; break; #ifdef SANE_FRAME_IR case MODE_INFRARED: s->params.format = SANE_FRAME_IR; s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8; break; #endif } if (s->params.bytes_per_line == 0) return SANE_STATUS_INVAL; /* * Calculate correction for line_distance in D1 scanner: * Start line_distance lines earlier and add line_distance lines at the end * * Because the actual line_distance is not yet calculated we have to do this * first. */ s->hw->color_shuffle = SANE_FALSE; s->lines_written = 0; s->color_shuffle_line = 0; s->current_output_line = 0; if ((s->hw->optical_res != 0) && (mparam->depth == 8) && (mparam->flags != 0)) { s->line_distance = s->hw->max_line_distance * dpi / s->hw->optical_res; if (s->line_distance != 0) { s->hw->color_shuffle = SANE_TRUE; DBG(1, "%s: color shuffling required\n", __func__); } } /* * If (s->top + s->params.lines) is larger than the max scan area, reset * the number of scan lines: * XXX: precalculate the maximum scanning area elsewhere (use dev max_y) */ if (SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH * dpi < (s->params.lines + s->top)) { s->params.lines = ((int) SANE_UNFIX(s->val[OPT_BR_Y].w) / MM_PER_INCH * dpi + 0.5) - s->top; } s->block = SANE_FALSE; s->lcount = 1; /* * The set line count commands needs to be sent for certain scanners in * color mode. The D1 level requires it, we are however only testing for * 'D' and not for the actual numeric level. */ if ((s->hw->cmd->level[0] == 'B') && (s->hw->level >= 5)) /* >= B5 */ e2_setup_block_mode(s); else if ((s->hw->cmd->level[0] == 'B') && (s->hw->level == 4) /* B4 !color */ && (!mode_params[s->val[OPT_MODE].w].color)) e2_setup_block_mode(s); else if (s->hw->cmd->level[0] == 'D') /* Dx */ e2_setup_block_mode(s); return (s->params.lines > 0) ? SANE_STATUS_GOOD : SANE_STATUS_INVAL; } void e2_wait_button(Epson_Scanner * s) { DBG(5, "%s\n", __func__); s->hw->wait_for_button = SANE_TRUE; while (s->hw->wait_for_button == SANE_TRUE) { unsigned char button_status = 0; if (s->canceling == SANE_TRUE) s->hw->wait_for_button = SANE_FALSE; /* get the button status from the scanner */ else if (esci_request_push_button_status(s, &button_status) == SANE_STATUS_GOOD) { if (button_status) s->hw->wait_for_button = SANE_FALSE; else sleep(1); } else { /* we run into an error condition, just continue */ s->hw->wait_for_button = SANE_FALSE; } } } /* SANE_Status e2_check_extended_status(Epson_Scanner *s) { SANE_Status status = esci_request_scanner_status(s, buf); if (status != SANE_STATUS_GOOD) return status; if (buf[0] & FSF_STATUS_MAIN_WU) main -> 0 fbf -> 3 adf -> 1, 10 tpu -> 2 } */ SANE_Status e2_check_warm_up(Epson_Scanner * s, SANE_Bool * wup) { SANE_Status status; DBG(5, "%s\n", __func__); *wup = SANE_FALSE; if (s->hw->extended_commands) { unsigned char buf[16]; status = esci_request_scanner_status(s, buf); if (status != SANE_STATUS_GOOD) return status; if (buf[0] & FSF_STATUS_MAIN_WU) *wup = SANE_TRUE; } else { unsigned char *es; /* this command is not available on some scanners */ if (!s->hw->cmd->request_extended_status) return SANE_STATUS_GOOD; status = esci_request_extended_status(s, &es, NULL); if (status != SANE_STATUS_GOOD) return status; if (es[0] & EXT_STATUS_WU) *wup = SANE_TRUE; free(es); } return status; } SANE_Status e2_wait_warm_up(Epson_Scanner * s) { SANE_Status status; SANE_Bool wup; DBG(5, "%s\n", __func__); s->retry_count = 0; while (1) { if (s->canceling) return SANE_STATUS_CANCELLED; status = e2_check_warm_up(s, &wup); if (status != SANE_STATUS_GOOD) return status; if (wup == SANE_FALSE) break; s->retry_count++; if (s->retry_count > SANE_EPSON_MAX_RETRIES) { DBG(1, "max retry count exceeded (%d)\n", s->retry_count); return SANE_STATUS_DEVICE_BUSY; } sleep(5); } return SANE_STATUS_GOOD; } SANE_Status e2_check_adf(Epson_Scanner * s) { SANE_Status status; DBG(5, "%s\n", __func__); if (s->hw->use_extension == SANE_FALSE) return SANE_STATUS_GOOD; if (s->hw->extended_commands) { unsigned char buf[16]; status = esci_request_scanner_status(s, buf); if (status != SANE_STATUS_GOOD) return status; if (buf[1] & FSF_STATUS_ADF_PE) return SANE_STATUS_NO_DOCS; if (buf[1] & FSF_STATUS_ADF_PJ) return SANE_STATUS_JAMMED; } else { unsigned char *buf, t; status = esci_request_extended_status(s, &buf, NULL); if (status != SANE_STATUS_GOOD) return status;; t = buf[1]; free(buf); if (t & EXT_STATUS_PE) return SANE_STATUS_NO_DOCS; if (t & EXT_STATUS_PJ) return SANE_STATUS_JAMMED; } return SANE_STATUS_GOOD; } SANE_Status e2_start_std_scan(Epson_Scanner * s) { SANE_Status status; unsigned char params[2]; DBG(5, "%s\n", __func__); /* ESC g */ params[0] = ESC; params[1] = s->hw->cmd->start_scanning; e2_send(s, params, 2, 6 + (s->lcount * s->params.bytes_per_line), &status); return status; } SANE_Status e2_start_ext_scan(Epson_Scanner * s) { SANE_Status status; unsigned char params[2]; unsigned char buf[14]; DBG(5, "%s\n", __func__); params[0] = FS; params[1] = 'G'; status = e2_txrx(s, params, 2, buf, 14); if (status != SANE_STATUS_GOOD) return status; if (buf[0] != STX) return SANE_STATUS_INVAL; if (buf[1] & 0x80) { DBG(1, "%s: fatal error\n", __func__); return SANE_STATUS_IO_ERROR; } s->ext_block_len = le32atoh(&buf[2]); s->ext_blocks = le32atoh(&buf[6]); s->ext_last_len = le32atoh(&buf[10]); s->ext_counter = 0; DBG(5, " status : 0x%02x\n", buf[1]); DBG(5, " block size : %u\n", (unsigned int) le32atoh(&buf[2])); DBG(5, " block count : %u\n", (unsigned int) le32atoh(&buf[6])); DBG(5, " last block size: %u\n", (unsigned int) le32atoh(&buf[10])); if (s->ext_last_len) { s->ext_blocks++; DBG(1, "adjusted block count: %d\n", s->ext_blocks); } /* adjust block len if we have only one block to read */ if (s->ext_block_len == 0 && s->ext_last_len) s->ext_block_len = s->ext_last_len; return status; } void e2_scan_finish(Epson_Scanner * s) { DBG(5, "%s\n", __func__); free(s->buf); s->buf = NULL; if (s->hw->ADF && s->hw->use_extension && s->val[OPT_AUTO_EJECT].w) if (e2_check_adf(s) == SANE_STATUS_NO_DOCS) esci_eject(s); } void e2_copy_image_data(Epson_Scanner * s, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { if (!s->block && s->params.format == SANE_FRAME_RGB) { max_length /= 3; if (max_length > s->end - s->ptr) max_length = s->end - s->ptr; *length = 3 * max_length; while (max_length-- != 0) { *data++ = s->ptr[0]; *data++ = s->ptr[s->params.pixels_per_line]; *data++ = s->ptr[2 * s->params.pixels_per_line]; ++s->ptr; } } else { if (max_length > s->end - s->ptr) max_length = s->end - s->ptr; *length = max_length; if (s->params.depth == 1) { while (max_length-- != 0) *data++ = ~*s->ptr++; } else { memcpy(data, s->ptr, max_length); s->ptr += max_length; } } } SANE_Status e2_ext_read(struct Epson_Scanner *s) { struct Epson_Device *dev = s->hw; SANE_Status status = SANE_STATUS_GOOD; ssize_t buf_len = 0, read; DBG(18, "%s: begin\n", __func__); /* did we passed everything we read to sane? */ if (s->ptr == s->end) { if (s->eof) return SANE_STATUS_EOF; s->ext_counter++; /* sane has already got the data, read some more, the final * error byte must not be included in buf_len */ buf_len = s->ext_block_len; if (s->ext_counter == s->ext_blocks && s->ext_last_len) buf_len = s->ext_last_len; DBG(18, "%s: block %d/%d, size %lu\n", __func__, s->ext_counter, s->ext_blocks, (unsigned long) buf_len); /* receive image data + error code */ read = e2_recv(s, s->buf, buf_len + 1, &status); DBG(18, "%s: read %lu bytes, status: %d\n", __func__, (unsigned long) read, status); if (status != SANE_STATUS_GOOD) { e2_cancel(s); return status; } if (e2_dev_model(dev, "GT-8200") || e2_dev_model(dev, "Perfection1650")) { /* See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=597922#127 */ s->buf[buf_len] &= 0xc0; } if (s->buf[buf_len] & FSG_STATUS_CANCEL_REQ) { DBG(0, "%s: cancel request received\n", __func__); e2_cancel(s); return SANE_STATUS_CANCELLED; } if (s->buf[buf_len] & (FSG_STATUS_FER | FSG_STATUS_NOT_READY)) return SANE_STATUS_IO_ERROR; /* ack every block except the last one */ if (s->ext_counter < s->ext_blocks) { size_t next_len = s->ext_block_len; if (s->ext_counter == (s->ext_blocks - 1)) next_len = s->ext_last_len; if (s->canceling) { e2_cancel(s); return SANE_STATUS_CANCELLED; } status = e2_ack_next(s, next_len + 1); } else s->eof = SANE_TRUE; s->end = s->buf + buf_len; s->ptr = s->buf; } return status; } /* XXXX use routine from sane-evolution */ typedef struct { unsigned char code; unsigned char status; unsigned char buf[4]; } EpsonDataRec; /* XXX this routine is ugly and should be avoided */ static SANE_Status read_info_block(Epson_Scanner * s, EpsonDataRec * result) { SANE_Status status; unsigned char params[2]; retry: e2_recv(s, result, s->block ? 6 : 4, &status); if (status != SANE_STATUS_GOOD) return status; if (result->code != STX) { DBG(1, "error: got %02x, expected STX\n", result->code); return SANE_STATUS_INVAL; } /* XXX */ if (result->status & STATUS_FER) { unsigned char *ext_status; DBG(1, "fatal error, status = %02x\n", result->status); if (s->retry_count > SANE_EPSON_MAX_RETRIES) { DBG(1, "max retry count exceeded (%d)\n", s->retry_count); return SANE_STATUS_INVAL; } /* if the scanner is warming up, retry after a few secs */ status = esci_request_extended_status(s, &ext_status, NULL); if (status != SANE_STATUS_GOOD) return status; if (ext_status[0] & EXT_STATUS_WU) { free(ext_status); sleep(5); /* for the next attempt */ DBG(1, "retrying ESC G - %d\n", ++(s->retry_count)); params[0] = ESC; params[1] = s->hw->cmd->start_scanning; e2_send(s, params, 2, 0, &status); if (status != SANE_STATUS_GOOD) return status; goto retry; } else free(ext_status); } return status; } static SANE_Status color_shuffle(SANE_Handle handle, int *new_length) { Epson_Scanner *s = (Epson_Scanner *) handle; SANE_Byte *buf = s->buf; int length = s->end - s->buf; SANE_Byte *data_ptr; /* ptr to data to process */ SANE_Byte *data_end; /* ptr to end of processed data */ SANE_Byte *out_data_ptr; /* ptr to memory when writing data */ int i; /* loop counter */ /* * It looks like we are dealing with a scanner that has an odd way * of dealing with colors... The red and blue scan lines are shifted * up or down by a certain number of lines relative to the green line. */ DBG(5, "%s\n", __func__); /* * Initialize the variables we are going to use for the * copying of the data. data_ptr is the pointer to * the currently worked on scan line. data_end is the * end of the data area as calculated from adding *length * to the start of data. * out_data_ptr is used when writing out the processed data * and always points to the beginning of the next line to * write. */ data_ptr = out_data_ptr = buf; data_end = data_ptr + length; /* * The image data is in *buf, we know that the buffer contains s->end - s->buf ( = length) * bytes of data. The width of one line is in s->params.bytes_per_line * * The buffer area is supposed to have a number of full scan * lines, let's test if this is the case. */ if (length % s->params.bytes_per_line != 0) { DBG(1, "error in buffer size: %d / %d\n", length, s->params.bytes_per_line); return SANE_STATUS_INVAL; } while (data_ptr < data_end) { SANE_Byte *source_ptr, *dest_ptr; int loop; /* copy the green information into the current line */ source_ptr = data_ptr + 1; dest_ptr = s->line_buffer[s->color_shuffle_line] + 1; for (i = 0; i < s->params.bytes_per_line / 3; i++) { *dest_ptr = *source_ptr; dest_ptr += 3; source_ptr += 3; } /* copy the red information n lines back */ if (s->color_shuffle_line >= s->line_distance) { source_ptr = data_ptr + 2; dest_ptr = s->line_buffer[s->color_shuffle_line - s->line_distance] + 2; /* while (source_ptr < s->line_buffer[s->color_shuffle_line] + s->params.bytes_per_line) */ for (loop = 0; loop < s->params.bytes_per_line / 3; loop++) { *dest_ptr = *source_ptr; dest_ptr += 3; source_ptr += 3; } } /* copy the blue information n lines forward */ source_ptr = data_ptr; dest_ptr = s->line_buffer[s->color_shuffle_line + s->line_distance]; /* while (source_ptr < s->line_buffer[s->color_shuffle_line] + s->params.bytes_per_line) */ for (loop = 0; loop < s->params.bytes_per_line / 3; loop++) { *dest_ptr = *source_ptr; dest_ptr += 3; source_ptr += 3; } data_ptr += s->params.bytes_per_line; if (s->color_shuffle_line == s->line_distance) { /* * We just finished the line in line_buffer[0] - write it to the * output buffer and continue. * * The ouput buffer ist still "buf", but because we are * only overwriting from the beginning of the memory area * we are not interfering with the "still to shuffle" data * in the same area. */ /* * Strip the first and last n lines and limit to */ if ((s->current_output_line >= s->line_distance) && (s->current_output_line < s->params.lines + s->line_distance)) { memcpy(out_data_ptr, s->line_buffer[0], s->params.bytes_per_line); out_data_ptr += s->params.bytes_per_line; s->lines_written++; } s->current_output_line++; /* * Now remove the 0-entry and move all other * lines up by one. There are 2*line_distance + 1 * buffers, * therefore the loop has to run from 0 * to * 2*line_distance, and because we want to * copy every n+1st entry to n the loop runs * from - to 2*line_distance-1! */ free(s->line_buffer[0]); for (i = 0; i < s->line_distance * 2; i++) { s->line_buffer[i] = s->line_buffer[i + 1]; } /* * and create one new buffer at the end */ s->line_buffer[s->line_distance * 2] = malloc(s->params.bytes_per_line); if (s->line_buffer[s->line_distance * 2] == NULL) { DBG(1, "out of memory (line %d)\n", __LINE__); return SANE_STATUS_NO_MEM; } } else { s->color_shuffle_line++; /* increase the buffer number */ } } /* * At this time we've used up all the new data from the scanner, some of * it is still in the line_buffers, but we are ready to return some of it * to the front end software. To do so we have to adjust the size of the * data area and the *new_length variable. */ *new_length = out_data_ptr - buf; return SANE_STATUS_GOOD; } static inline int get_color(int status) { switch ((status >> 2) & 0x03) { case 1: return 1; case 2: return 0; case 3: return 2; default: return 0; /* required to make the compiler happy */ } } SANE_Status e2_block_read(struct Epson_Scanner *s) { SANE_Status status; SANE_Bool reorder = SANE_FALSE; START_READ: DBG(18, "%s: begin\n", __func__); if (s->ptr == s->end) { EpsonDataRec result; unsigned int buf_len; if (s->eof) { if (s->hw->color_shuffle) { DBG(1, "written %d lines after color shuffle\n", s->lines_written); DBG(1, "lines requested: %d\n", s->params.lines); } return SANE_STATUS_EOF; } status = read_info_block(s, &result); if (status != SANE_STATUS_GOOD) { return status; } buf_len = result.buf[1] << 8 | result.buf[0]; buf_len *= (result.buf[3] << 8 | result.buf[2]); DBG(18, "%s: buf len = %u\n", __func__, buf_len); { /* do we have to reorder the data ? */ if (get_color(result.status) == 0x01) reorder = SANE_TRUE; e2_recv(s, s->buf, buf_len, &status); if (status != SANE_STATUS_GOOD) { return status; } } if (result.status & STATUS_AREA_END) { DBG(1, "%s: EOF\n", __func__); s->eof = SANE_TRUE; } else { if (s->canceling) { e2_cancel(s); return SANE_STATUS_CANCELLED; } else { status = e2_ack(s); } } s->end = s->buf + buf_len; s->ptr = s->buf; /* * if we have to re-order the color components (GRB->RGB) we * are doing this here: */ /* * Certain Perfection 1650 also need this re-ordering of the two * color channels. These scanners are identified by the problem * with the half vertical scanning area. When we corrected this, * we also set the variable s->hw->need_color_reorder */ if (s->hw->need_color_reorder) reorder = SANE_FALSE; /* reordering once is enough */ if (reorder && s->params.format == SANE_FRAME_RGB) { SANE_Byte *ptr; ptr = s->buf; while (ptr < s->end) { if (s->params.depth > 8) { SANE_Byte tmp; /* R->G G->R */ tmp = ptr[0]; ptr[0] = ptr[2]; /* first Byte G */ ptr[2] = tmp; /* first Byte R */ tmp = ptr[1]; ptr[1] = ptr[3]; /* second Byte G */ ptr[3] = tmp; /* second Byte R */ ptr += 6; /* go to next pixel */ } else { /* R->G G->R */ SANE_Byte tmp; tmp = ptr[0]; ptr[0] = ptr[1]; /* G */ ptr[1] = tmp; /* R */ /* B stays the same */ ptr += 3; /* go to next pixel */ } } } /* * Do the color_shuffle if everything else is correct - at this time * most of the stuff is hardcoded for the Perfection 610 */ if (s->hw->color_shuffle) { int new_length = 0; status = color_shuffle(s, &new_length); /* XXX check status here */ /* * If no bytes are returned, check if the scanner is already done, if so, * we'll probably just return, but if there is more data to process get * the next batch. */ if (new_length == 0 && s->end != s->ptr) goto START_READ; s->end = s->buf + new_length; s->ptr = s->buf; } DBG(18, "%s: begin scan2\n", __func__); } DBG(18, "%s: end\n", __func__); return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/plustek-pp_wrapper.c0000664000175000017500000002161612112021330016610 00000000000000/** @file plustek-pp_wrapper.c * @brief The interface to the parport driver-code and the kernel module. * * Based on sources acquired from Plustek Inc.
* Copyright (C) 2001-2004 Gerhard Jaeger * * History: * - 0.40 - initial version * - 0.41 - added _PTDRV_ADJUST call * - 0.42 - added setmap function * - fixed the stopscan problem, that causes a crash in the kernel module * - 0.43 - added initialized setting * - cleanup * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ /******************* wrapper functions for parport device ********************/ #ifndef _BACKEND_ENABLED static int PtDrvInit( char *dev_name, unsigned short model_override ) { _VAR_NOT_USED( dev_name ); _VAR_NOT_USED( model_override ); DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" ); return -1; } static int PtDrvShutdown( void ) { return 0; } static int PtDrvOpen( void ) { DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" ); return -1; } static int PtDrvClose( void ) { DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" ); return 0; } static int PtDrvIoctl( unsigned int cmd, void *arg ) { DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" ); _VAR_NOT_USED( cmd ); if( arg == NULL ) return -2; return -1; } static int PtDrvRead( unsigned char *buffer, int count ) { DBG( _DBG_ERROR, "Backend does not support direct I/O!\n" ); _VAR_NOT_USED( count ); if( buffer == NULL ) return -2; return -1; } #endif /* _BACKEND_ENABLED */ /** */ static int ppDev_open( const char *dev_name, void *misc ) { int result; int handle; CompatAdjDef compatAdj; PPAdjDef adj; unsigned short version = _PTDRV_IOCTL_VERSION; Plustek_Device *dev = (Plustek_Device *)misc; if( dev->adj.direct_io ) { result = PtDrvInit( dev_name, dev->adj.mov ); if( 0 != result ) { DBG( _DBG_ERROR, "open: PtDrvInit failed: %d\n", result ); return -1; } } if( dev->adj.direct_io ) handle = PtDrvOpen(); else handle = open( dev_name, O_RDONLY ); if ( handle < 0 ) { DBG( _DBG_ERROR, "open: can't open %s as a device\n", dev_name ); return handle; } if( dev->adj.direct_io ) result = PtDrvIoctl( _PTDRV_OPEN_DEVICE, &version ); else result = ioctl( handle, _PTDRV_OPEN_DEVICE, &version ); if( result < 0 ) { if( -9019 == result ) { DBG( _DBG_INFO, "Version 0x%04x not supported, trying " "compatibility version 0x%04x\n", _PTDRV_IOCTL_VERSION, _PTDRV_COMPAT_IOCTL_VERSION); version = _PTDRV_COMPAT_IOCTL_VERSION; if( dev->adj.direct_io ) result = PtDrvIoctl( _PTDRV_OPEN_DEVICE, &version ); else result = ioctl( handle, _PTDRV_OPEN_DEVICE, &version ); if( result < 0 ) { if( dev->adj.direct_io ) PtDrvClose(); else close( dev->fd ); DBG( _DBG_ERROR, "ioctl PT_DRV_OPEN_DEVICE failed(%d)\n", result ); if( -9019 == result ) { DBG( _DBG_ERROR, "Version problem, please recompile driver!\n" ); } } else { DBG( _DBG_INFO, "Using compatibility version\n" ); compatAdj.lampOff = dev->adj.lampOff; compatAdj.lampOffOnEnd = dev->adj.lampOffOnEnd; compatAdj.warmup = dev->adj.warmup; memcpy( &compatAdj.pos, &dev->adj.pos, sizeof(OffsDef)); memcpy( &compatAdj.neg, &dev->adj.neg, sizeof(OffsDef)); memcpy( &compatAdj.tpa, &dev->adj.tpa, sizeof(OffsDef)); if( dev->adj.direct_io ) PtDrvIoctl( _PTDRV_ADJUST, &compatAdj ); else ioctl( handle, _PTDRV_ADJUST, &compatAdj ); return handle; } } return result; } memset( &adj, 0, sizeof(PPAdjDef)); adj.lampOff = dev->adj.lampOff; adj.lampOffOnEnd = dev->adj.lampOffOnEnd; adj.warmup = dev->adj.warmup; memcpy( &adj.pos, &dev->adj.pos, sizeof(OffsDef)); memcpy( &adj.neg, &dev->adj.neg, sizeof(OffsDef)); memcpy( &adj.tpa, &dev->adj.tpa, sizeof(OffsDef)); adj.rgamma = dev->adj.rgamma; adj.ggamma = dev->adj.ggamma; adj.bgamma = dev->adj.bgamma; adj.graygamma = dev->adj.graygamma; if( dev->adj.direct_io ) PtDrvIoctl( _PTDRV_ADJUST, &adj ); else ioctl( handle, _PTDRV_ADJUST, &adj ); dev->initialized = SANE_TRUE; return handle; } /** */ static int ppDev_close( Plustek_Device *dev ) { if( dev->adj.direct_io ) return PtDrvClose(); else return close( dev->fd ); } /** */ static int ppDev_getCaps( Plustek_Device *dev ) { if( dev->adj.direct_io ) return PtDrvIoctl( _PTDRV_GET_CAPABILITIES, &dev->caps ); else return ioctl( dev->fd, _PTDRV_GET_CAPABILITIES, &dev->caps ); } /** */ static int ppDev_getLensInfo( Plustek_Device *dev, pLensInfo lens ) { if( dev->adj.direct_io ) return PtDrvIoctl( _PTDRV_GET_LENSINFO, lens ); else return ioctl( dev->fd, _PTDRV_GET_LENSINFO, lens ); } /** */ static int ppDev_getCropInfo( Plustek_Device *dev, pCropInfo crop ) { if( dev->adj.direct_io ) return PtDrvIoctl( _PTDRV_GET_CROPINFO, crop ); else return ioctl( dev->fd, _PTDRV_GET_CROPINFO, crop ); } /** */ static int ppDev_putImgInfo( Plustek_Device *dev, pImgDef img ) { if( dev->adj.direct_io ) return PtDrvIoctl( _PTDRV_PUT_IMAGEINFO, img ); else return ioctl( dev->fd, _PTDRV_PUT_IMAGEINFO, img ); } /** */ static int ppDev_setScanEnv( Plustek_Device *dev, pScanInfo sinfo ) { if( dev->adj.direct_io ) return PtDrvIoctl( _PTDRV_SET_ENV, sinfo ); else return ioctl( dev->fd, _PTDRV_SET_ENV, sinfo ); } /** */ static int ppDev_startScan( Plustek_Device *dev, pStartScan start ) { if( dev->adj.direct_io ) return PtDrvIoctl( _PTDRV_START_SCAN, start ); else return ioctl( dev->fd, _PTDRV_START_SCAN, start ); } /** function to send a gamma table to the kernel module. As the default table * entry is 16-bit, but the maps are 8-bit, we have to copy the values... */ static int ppDev_setMap( Plustek_Device *dev, SANE_Word *map, SANE_Word length, SANE_Word channel ) { SANE_Byte *buf; SANE_Word i; MapDef m; m.len = length; m.map_id = channel; m.map = (void *)map; DBG(_DBG_INFO,"Setting map[%u] at 0x%08lx\n", channel, (unsigned long)map); buf = (SANE_Byte*)malloc( m.len ); if( !buf ) return _E_ALLOC; for( i = 0; i < m.len; i++ ) { buf[i] = (SANE_Byte)map[i]; if( map[i] > 0xFF ) buf[i] = 0xFF; } m.map = buf; if( dev->adj.direct_io ) PtDrvIoctl( _PTDRV_SETMAP, &m ); else ioctl( dev->fd, _PTDRV_SETMAP, &m ); /* we ignore the return values */ free( buf ); return 0; } /** */ static int ppDev_stopScan( Plustek_Device *dev, short *mode ) { int retval, tmp; /* save this one... */ tmp = *mode; if( dev->adj.direct_io ) retval = PtDrvIoctl( _PTDRV_STOP_SCAN, mode ); else retval = ioctl( dev->fd, _PTDRV_STOP_SCAN, mode ); /* ... and use it here */ if( 0 == tmp ) { if( dev->adj.direct_io ) PtDrvIoctl( _PTDRV_CLOSE_DEVICE, 0 ); else ioctl( dev->fd, _PTDRV_CLOSE_DEVICE, 0); }else sleep( 1 ); return retval; } /** */ static int ppDev_readImage( Plustek_Device *dev, SANE_Byte *buf, unsigned long data_length ) { if( dev->adj.direct_io ) return PtDrvRead( buf, data_length ); else return read( dev->fd, buf, data_length ); } /* END PLUSTEK-PP_WRAPPER.C .................................................*/ sane-backends-1.0.27/backend/pixma.h0000664000175000017500000004013413106201017014071 00000000000000/* SANE - Scanner Access Now Easy. Copyright (C) 2011-2016 Rolf Bensch Copyright (C) 2007-2008 Nicolas Martin, Copyright (C) 2006-2007 Wittawat Yamwong This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef PIXMA_H #define PIXMA_H /*! * \mainpage Scanner driver for Canon PIXMA MP series * \section example Sample code for application * \code * pixma_set_debug_level(level); * pixma_init(); * nscanners = pixma_find_scanners(); * devnr = choose_scanner(nscanners); * scanner = pixma_open(devnr); * setup_param(param); * pixma_check_scan_param(scanner, param); * do { * if (I_need_events && * (ev = pixma_wait_event(scanner, timeout)) > 0) { * handle_event(ev); * } * pixma_scan(scanner, param); * while ((count = pixma_read_image(scanner, buf, len)) > 0) { * write(buf, count); * if (error_occured_in_write) { * pixma_cancel(scanner); * } * } * } while (!enough); * pixma_close(scanner); * pixma_cleanup(); * \endcode * * Note: pixma_cancel() can be called asynchronously to * interrupt pixma_read_image(). It does not cancel the operation * immediately. pixma_read_image() must be called until it * returns zero or an error (probably \c PIXMA_ECANCELED). * * \section reference Reference * - \subpage API * - \subpage IO * - \subpage subdriver * - \subpage debug */ /*! * \defgroup API The driver API * \brief The driver API. * * The return value of functions that returns \c int has the following * meaning if not otherwise specified: * - >= 0 if succeeded * - < 0 if failed */ #ifdef HAVE_STDINT_H # include /* available in ISO C99 */ #else # include typedef uint8_t uint8_t; typedef uint16_t uint16_t; typedef uint32_t uint32_t; #endif /* HAVE_STDINT_H */ #ifdef HAVE_INTTYPES_H # include /* available in ISO C99 */ #endif /* HAVE_INTTYPES_H */ /** \addtogroup API * @{ */ /** Don't forget to update the backend version in the SANE Backend specification * file: doc/descriptions/pixma.desc !!! */ /** \name Version of the driver */ /**@{*/ #define PIXMA_VERSION_MAJOR 0 #define PIXMA_VERSION_MINOR 17 #define PIXMA_VERSION_BUILD 37 /**@}*/ /** \name Error codes */ /**@{*/ #define PIXMA_EIO -1 #define PIXMA_ENODEV -2 #define PIXMA_EACCES -3 #define PIXMA_ENOMEM -4 #define PIXMA_EINVAL -5 #define PIXMA_EBUSY -6 #define PIXMA_ECANCELED -7 #define PIXMA_ENOTSUP -8 #define PIXMA_ETIMEDOUT -9 #define PIXMA_EPROTO -10 #define PIXMA_EPAPER_JAMMED -11 #define PIXMA_ECOVER_OPEN -12 #define PIXMA_ENO_PAPER -13 #define PIXMA_EOF -14 /**@}*/ /** \name Capabilities for using with pixma_config_t::cap */ /**@{*/ #define PIXMA_CAP_EASY_RGB (1 << 0) #define PIXMA_CAP_GRAY (1 << 1) #define PIXMA_CAP_ADF (1 << 2) #define PIXMA_CAP_48BIT (1 << 3) #define PIXMA_CAP_GAMMA_TABLE (1 << 4) #define PIXMA_CAP_EVENTS (1 << 5) #define PIXMA_CAP_TPU (1 << 6) #define PIXMA_CAP_ADFDUP ((1 << 7) | PIXMA_CAP_ADF) #define PIXMA_CAP_CIS (0) #define PIXMA_CAP_CCD (1 << 8) #define PIXMA_CAP_LINEART (1 << 9) #define PIXMA_CAP_NEGATIVE (1 << 10) #define PIXMA_CAP_TPUIR ((1 << 11) | PIXMA_CAP_TPU) #define PIXMA_CAP_ADF_WAIT (1 << 12) #define PIXMA_CAP_EXPERIMENT (1 << 31) /**@}*/ /** \name Button events and related information returned by pixma_wait_event() */ /**@{*/ #define PIXMA_EV_NONE 0 #define PIXMA_EV_ACTION_MASK (0xffffff) #define PIXMA_EV_BUTTON1 (1 << 24) #define PIXMA_EV_BUTTON2 (2 << 24) #define PIXMA_EV_TARGET_MASK (0xff) #define PIXMA_EV_ORIGINAL_MASK (0xff00) #define PIXMA_EV_DPI_MASK (0xff0000) #define GET_EV_TARGET(x) (x & PIXMA_EV_TARGET_MASK) #define GET_EV_ORIGINAL(x) ( (x & PIXMA_EV_ORIGINAL_MASK) >> 8 ) #define GET_EV_DPI(x) ( (x & PIXMA_EV_DPI_MASK) >> 16 ) /**@}*/ /** @} end of API group */ #define PIXMA_CONFIG_FILE "pixma.conf" #define MAX_CONF_DEVICES 15 struct pixma_t; struct pixma_scan_ops_t; struct pixma_scan_param_t; struct pixma_config_t; struct pixma_cmdbuf_t; struct pixma_imagebuf_t; struct pixma_device_status_t; typedef struct pixma_t pixma_t; typedef struct pixma_scan_ops_t pixma_scan_ops_t; typedef struct pixma_scan_param_t pixma_scan_param_t; typedef struct pixma_config_t pixma_config_t; typedef struct pixma_cmdbuf_t pixma_cmdbuf_t; typedef struct pixma_imagebuf_t pixma_imagebuf_t; typedef struct pixma_device_status_t pixma_device_status_t; /** \addtogroup API * @{ */ /** String index constants */ typedef enum pixma_string_index_t { PIXMA_STRING_MODEL, PIXMA_STRING_ID, PIXMA_STRING_LAST } pixma_string_index_t; /** Paper sources */ typedef enum pixma_paper_source_t { PIXMA_SOURCE_FLATBED, PIXMA_SOURCE_ADF, PIXMA_SOURCE_TPU, PIXMA_SOURCE_ADFDUP /* duplex */ } pixma_paper_source_t; /** Scan modes */ typedef enum pixma_scan_mode_t { /* standard scan modes */ PIXMA_SCAN_MODE_COLOR, PIXMA_SCAN_MODE_GRAY, /* TPU scan modes for negatives */ PIXMA_SCAN_MODE_NEGATIVE_COLOR, PIXMA_SCAN_MODE_NEGATIVE_GRAY, /* extended scan modes for 48 bit flatbed scanners */ PIXMA_SCAN_MODE_COLOR_48, PIXMA_SCAN_MODE_GRAY_16, /* 1 bit lineart scan mode */ PIXMA_SCAN_MODE_LINEART, /* TPUIR scan mode */ PIXMA_SCAN_MODE_TPUIR } pixma_scan_mode_t; typedef enum pixma_hardware_status_t { PIXMA_HARDWARE_OK, PIXMA_HARDWARE_ERROR } pixma_hardware_status_t; typedef enum pixma_lamp_status_t { PIXMA_LAMP_OK, PIXMA_LAMP_WARMING_UP, PIXMA_LAMP_OFF, PIXMA_LAMP_ERROR } pixma_lamp_status_t; typedef enum pixma_adf_status_t { PIXMA_ADF_OK, PIXMA_ADF_NO_PAPER, PIXMA_ADF_JAMMED, PIXMA_ADF_COVER_OPEN, PIXMA_ADF_ERROR } pixma_adf_status_t; typedef enum pixma_calibration_status_t { PIXMA_CALIBRATION_OK, PIXMA_CALIBRATION_IN_PROGRESS, PIXMA_CALIBRATION_OFF, PIXMA_CALIBRATION_ERROR } pixma_calibration_status_t; /** Device status. */ struct pixma_device_status_t { pixma_hardware_status_t hardware; pixma_lamp_status_t lamp; pixma_adf_status_t adf; pixma_calibration_status_t cal; }; /** Scan parameters. */ struct pixma_scan_param_t { /** Size in bytes of one image line (row). * line_size >= depth / 8 * channels * w
* This field will be set by pixma_check_scan_param(). */ uint64_t line_size; /** Size in bytes of the whole image. * image_size = line_size * h
* This field will be set by pixma_check_scan_param(). */ uint64_t image_size; /** Channels per pixel. 1 = grayscale and lineart, 3 = color */ unsigned channels; /** Bits per channels. * 1 = 1 bit B/W lineart (flatbed) * 8 = 8 bit grayscale, * 24 bit color (both flatbed) * 16 = 16 bit grayscale (TPU, flatbed not implemeted), * 48 bit color (TPU, flatbed not implemented) */ unsigned depth; /*@{ */ /** Resolution. Valid values are 75,150,300,600,1200... */ unsigned xdpi, ydpi; /*@} */ /*! \name Scan area in pixels * (0,0) = top left; positive x extends to the right; positive y to the * bottom; in pixels. * xs is the offset in x direction of the selected scan range relative * to the range read from the scanner and wx the width in x direction * of the scan line read from scanner. */ /*@{ */ unsigned x, y, w, h, xs, wx; /*@} */ /** Flag indicating whether the offset correction for TPU scans * was already performed (to avoid repeated corrections). * Currently only used in pixma_mp810.c sub-driver */ unsigned tpu_offset_added; /** Flag indicating whether a software-lineart scan is in progress * 0 = other scan * 1 = software-lineart scan */ unsigned software_lineart; /** Threshold for software-lineart scans */ unsigned threshold; /** lineart threshold curve for dynamic rasterization */ unsigned threshold_curve; /* look up table used in dynamic rasterization */ unsigned char lineart_lut[256]; /** Gamma table. 4096 entries, 12 bit => 8 bit. If \c NULL, default gamma * specified by subdriver will be used. */ const uint8_t *gamma_table; /** \see #pixma_paper_source_t */ pixma_paper_source_t source; /** \see #pixma_scan_mode_t */ pixma_scan_mode_t mode; /** The current page # in the same ADF scan session, 0 in non ADF */ unsigned adf_pageid; /** adf-wait */ unsigned adf_wait; unsigned frontend_cancel; }; /** PIXMA model information */ struct pixma_config_t { /* If you change this structure, don't forget to update the device list in * subdrivers. */ const char *name; /**< Model name. */ const char *model; /**< Short model */ uint16_t vid; /**< USB Vendor ID */ uint16_t pid; /**< USB Product ID */ unsigned iface; /**< USB Interface number */ const pixma_scan_ops_t *ops; /**< Subdriver ops */ unsigned xdpi; /**< Maximum horizontal resolution[DPI] */ unsigned ydpi; /**< Maximum vertical resolution[DPI] */ unsigned adftpu_min_dpi; /**< Maximum horizontal resolution[DPI] for adf/tpu * only needed if ADF/TPU has another min. dpi value than 75 dpi */ unsigned adftpu_max_dpi; /**< Maximum vertical resolution[DPI] for adf/tpu * only needed if ADF/TPU has another max. dpi value than xdpi */ unsigned tpuir_min_dpi; /**< Minimum resolution[DPI] for tpu-ir * only needed if TPU-IR has another min. dpi value than 75 dpi */ unsigned tpuir_max_dpi; /**< Maximum resolution[DPI] for tpu-ir * only needed if TPU-IR has another max. dpi value than xdpi */ unsigned width; /**< Maximum width of scannable area in pixels at 75DPI */ unsigned height; /**< Maximum height of scannable area in pixels at 75DPI */ unsigned cap; /**< Capability bitfield \see PIXMA_CAP_* */ }; /* Defined in pixma_common.c */ /** Initialize the driver. It must be called before any other functions * except pixma_set_debug_level(). */ int pixma_init (void); /** Free resources allocated by the driver. */ void pixma_cleanup (void); /** Set the debug level. * \param[in] level the debug level * - 0 No debug output at all * - 1 Only errors and warning * - 2 General information * - 3 Debugging messages * - 10 USB traffic dump */ void pixma_set_debug_level (int level); /** Find scanners. The device number used in pixma_open(), * pixma_get_device_model(), pixma_get_device_id() and * pixma_get_device_config() must be less than the value returned by the last * call of this function. * * \return The number of scanners found currently. The return value is * guaranteed to be valid until the next call to pixma_find_scanners(). */ int pixma_find_scanners (const char **conf_devices); /** Return the model name of the device \a devnr. */ const char *pixma_get_device_model (unsigned devnr); /** Return the unique ID of the device \a devnr. */ const char *pixma_get_device_id (unsigned devnr); /** Return the device configuration of the device \a devnr. */ const struct pixma_config_t *pixma_get_device_config (unsigned devnr); /** Open a connection to the scanner \a devnr. * \param[in] devnr The scanner number * \param[out] handle The device handle * \see pixma_find_scanners() */ int pixma_open (unsigned devnr, pixma_t ** handle); /** Close the connection to the scanner. The scanning process is aborted * if necessary before the function returns. */ void pixma_close (pixma_t * s); /** Initiate an image acquisition process. You must keep \a sp valid until the * image acquisition process has finished. */ int pixma_scan (pixma_t *, pixma_scan_param_t * sp); /** Read a block of image data. It blocks until there is at least one byte * available or an error occurs. * * \param[out] buf Pointer to the buffer * \param[in] len Size of the buffer * * \retval count Number of bytes written to the buffer or error. Possible * return value: * - count = 0 for end of image * - count = \a len * - 0 < count < \a len if and only if it is the last block. * - count < 0 for error */ int pixma_read_image (pixma_t *, void *buf, unsigned len); #if 0 /** Read a block of image data and write to \a fd. * \param[in] fd output file descriptor * \see pixma_read_image() */ int pixma_read_image_write (pixma_t *, int fd); #endif /** Cancel the scanning process. No effect if no scanning process is in * progress. It can be called asynchronously e.g. within a signal * handle. pixma_cancel() doesn't abort the operation immediately. It * guarantees that the current call or, at the latest, the next call to * pixma_read_image() will return zero or an error (probably PIXMA_ECANCELED). */ void pixma_cancel (pixma_t *); /** Check the scan parameters. This function can change your parameters to * match the device capability, e.g. adjust width and height to the available * area. * \return PIXMA_EINVAL for invalid parameters. */ int pixma_check_scan_param (pixma_t *, pixma_scan_param_t *); /** Wait until a scanner button is pressed or it times out. It should not be * called during image acquisition is in progress. * \param[in] timeout in milliseconds, less than 0 means forever * \return * - \c PIXMA_EV_NONE if it timed out. * - non-zero value indicates which button was pressed. * \see PIXMA_EV_* */ uint32_t pixma_wait_event (pixma_t *, int timeout); /** Activate connection to scanner */ int pixma_activate_connection (pixma_t *); /** De-activate connection to scanner */ int pixma_deactivate_connection (pixma_t *); /** Enable or disable background tasks. Currently, the only one task * is submitting interrupt URB in background. * \param[in] enabled if not zero, enable background task. * \see pixma_set_interrupt_mode() */ int pixma_enable_background (pixma_t *, int enabled); /** Read the current device status. * \param[out] status the current device status * \return 0 if succeeded. Otherwise, failed. */ int pixma_get_device_status (pixma_t *, pixma_device_status_t * status); const char *pixma_get_string (pixma_t *, pixma_string_index_t); const pixma_config_t *pixma_get_config (pixma_t *); void pixma_fill_gamma_table (double gamma, uint8_t * table, unsigned n); const char *pixma_strerror (int error); /** @} end of API group */ #endif sane-backends-1.0.27/backend/plustek-pp_models.c0000664000175000017500000004442412112021330016415 00000000000000/* @file plustek-pp_models.c * @brief model specific stuff * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2004 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - no changes * - 0.32 - no changes * - 0.33 - no changes * - 0.34 - no changes * - 0.35 - added some comments * - did some fine tuning on the 9630P and 12000P/9600P models * - moved function initPageSettings() to this module * - 0.36 - as the ps->MaxWideLineBlks and ps->MaxWideLineLen are only used * for the OP 4800, it has been removed from pScanData * - changed settings of OP600 according to the Primax Direct 4800 tests * - removed dwPreferSize from struct ScannerCaps * - fixed the 5seconds bed-hit problem for ASIC 96001/3 based models * - changes, due to define renaming * - 0.37 - added ButtonCount init * - added A3I model * - added functions modelInitCaps(), modelInitMotor() and * modelSetBufferSizes() * - 0.38 - added P12 stuff * - code cleanup * - 0.39 - no changes * - 0.40 - changed back to build 0.39-3 (disabled A3I stuff) * - 0.41 - added _OVR_PLUSTEK_4800P switch * - 0.42 - added SFLAG_CUSTOM_GAMMA to capabilities * - added _OVR_PRIMAX_4800D30 switch * - changed include names * - 0.43 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** local functions *********************************/ /*............................................................................. * initialize the extension according to the page size... */ static void modelInitPageSettings( pScanData ps ) { DBG(DBG_LOW, "modelInitPageSettings()\n" ); if( MODEL_OP_9630PL == ps->sCaps.Model ) ps->dwScannerSize = _SCANSIZE_LEGAL; else if( MODEL_OP_A3I == ps->sCaps.Model ) ps->dwScannerSize = _SCANSIZE_A3; else ps->dwScannerSize = _SCANSIZE_A4; /* default width for all but A3 - 8.5"* 300dpi (_MEASURE_BASE) */ ps->sCaps.wMaxExtentX = 2550; /* this applies to all scanners but the A3 model */ ps->LensInf.rExtentX.wMin = 150; ps->LensInf.rExtentX.wDef = 2550; ps->LensInf.rExtentX.wMax = 2550; ps->LensInf.rExtentX.wPhyMax = 2500; ps->LensInf.rExtentY.wMin = 150; ps->LensInf.wBeginX = 0; ps->LensInf.wBeginY = 0; switch( ps->dwScannerSize ) { case _SCANSIZE_A4: /* 11.69 inches */ DBG( DBG_LOW, "A4 set\n" ); ps->sCaps.wMaxExtentY = ps->LensInf.rExtentY.wDef = ps->LensInf.rExtentY.wMax = ps->LensInf.rExtentY.wPhyMax = _MEASURE_BASE * 11.6934; break; case _SCANSIZE_A3: /* 17 inches */ DBG( DBG_LOW, "A3 set\n" ); ps->sCaps.wMaxExtentY = ps->LensInf.rExtentY.wMax = ps->LensInf.rExtentY.wDef = ps->LensInf.rExtentY.wPhyMax = _MEASURE_BASE * 17; /* _MEASURE_BASE * 11.69 */ ps->sCaps.wMaxExtentX = ps->LensInf.rExtentX.wDef = ps->LensInf.rExtentX.wMax = 3507; ps->LensInf.rExtentX.wPhyMax = 3500; break; case _SCANSIZE_LETTER: /* 11 inches */ DBG( DBG_LOW, "Letter set\n" ); ps->sCaps.wMaxExtentY = ps->LensInf.rExtentY.wDef = ps->LensInf.rExtentY.wMax = ps->LensInf.rExtentY.wPhyMax = _MEASURE_BASE * 11; break; case _SCANSIZE_LEGAL: /* 14 inches */ DBG( DBG_LOW, "Legal set\n" ); ps->sCaps.wMaxExtentY = ps->LensInf.rExtentY.wDef = ps->LensInf.rExtentY.wMax = ps->LensInf.rExtentY.wPhyMax = _MEASURE_BASE * 14; } /* * add this value to avoid the problems in binary mode */ ps->LensInf.rExtentY.wMax += 64; /* set the DPI stuff */ ps->LensInf.rDpiX.wMin = 16; ps->LensInf.rDpiX.wDef = 50; ps->LensInf.rDpiX.wMax = (ps->PhysicalDpi * 16); ps->LensInf.rDpiX.wPhyMax = ps->PhysicalDpi; ps->LensInf.rDpiY.wMin = 16; ps->LensInf.rDpiY.wDef = 50; ps->LensInf.rDpiY.wMax = (ps->PhysicalDpi * 16); ps->LensInf.rDpiY.wPhyMax = (ps->PhysicalDpi * 2); } /*............................................................................. * set the scanner capabilities */ static void modelInitCaps( pScanData ps ) { ps->sCaps.wIOBase = _NO_BASE; ps->sCaps.dwFlag = SFLAG_CUSTOM_GAMMA; } /*............................................................................. * set the motor stuff */ static void modelInitMotor( pScanData ps ) { if( _ASIC_IS_96001 == ps->sCaps.AsicID ) { ps->FullStep = _MotorFullStep96001; ps->MotorOn = _MotorOn96001; ps->IgnorePF = _MotorIgnorePF96001; ps->StepMask = ~ps->FullStep; } else { ps->FullStep = _Motor1FullStep; ps->MotorOn = _MotorOn; ps->IgnorePF = _MotorIgnorePF; ps->StepMask = _MotorStepMask; } ps->BackwardSteps = 4000; } /*............................................................................. * according to the models' capabilities, set the buffer stuff */ static void modelSetBufferSizes( pScanData ps ) { /* should depend on the scan-area !!!! */ if( 400 == ps->PhysicalDpi ) { /* assuming a A3I */ ps->BufferSizeBase = 3517; ps->BufferForColorRunTable = (5500 * 4); /* might be 17" * 800dpi !!! */ } else if( 600 == ps->PhysicalDpi ) { ps->BufferSizeBase = 2560; ps->BufferForColorRunTable = (5500 * 4); } else { ps->BufferSizeBase = 1280; ps->BufferForColorRunTable = 9000; } ps->BufferSizePerModel = ps->BufferSizeBase * 2; ps->BufferForDataRead1 = ps->BufferSizePerModel * 3; /* patch that for the 600 DPI models OP9630 etc.*/ if(( 300 != ps->PhysicalDpi) && (_ASIC_IS_96003 == ps->sCaps.AsicID)) ps->BufferForDataRead1 += 300; ps->BufferFor1stColor = (ps->BufferSizePerModel * 17); ps->BufferFor2ndColor = (ps->BufferSizePerModel * 9); ps->TotalBufferRequire = (ps->BufferFor1stColor + ps->BufferFor2ndColor + ps->BufferForDataRead1 + ps->BufferForColorRunTable ); } /************************ exported functions *********************************/ /*............................................................................. * set the model to 4800 */ _LOC void ModelSet4800( pScanData ps ) { DBG( DBG_LOW, "ModelSet4800()\n" ); /* has 96001 ASIC */ ps->sCaps.AsicID = _ASIC_IS_96001; ps->sCaps.Model = MODEL_OP_4800P; ps->Device.buttons = 0; ps->Device.ModelCtrl = (_ModelDpi300 | _ModelMemSize32k96001 | _ModelWhiteIs0); ps->Device.DataOriginX = 72; ps->PhysicalDpi = 300; ps->TimePerLine = 0x30; ps->Offset70 = 70; modelSetBufferSizes( ps ); ps->a_wGrayInitTime[0] = 220; /* _EppTimeForOthers */ ps->a_wGrayInitTime[1] = 720; /* _SppTimeForOthers */ ps->a_wGrayInitTime[2] = 360; /* _BidirTimeForOthers */ ps->a_wColorInitTime[0] = 500; /* _EppTimeForColor */ ps->a_wColorInitTime[1] = 1680; /* _SppTimeForColor */ ps->a_wColorInitTime[2] = 1100; /* _BidirTimeForColor */ ps->AsicRedColor = _ASIC_REDCOLOR; ps->AsicGreenColor = _ASIC_GREENCOLOR; ps->RedDataReady = _RED_DATA_READY; ps->GreenDataReady = _GREEN_DATA_READY; /* * used for shading stuff (see dac.c) */ ps->FBKScanLineBlks = 5; ps->FBKScanLineLenBase = 1024; ps->FBKScanLineLen = (ps->FBKScanLineLenBase * 3); ps->ShadingBufferSize = ps->FBKScanLineLen; ps->ShadingBankSize = (ps->FBKScanLineLenBase * 4); ps->ShadingBankRed = (_MemBankSize4k96001 | 0x3a); ps->ShadingBankGreen = (_MemBankSize4k96001 | 0x3e); ps->ShadingBankBlue = (_MemBankSize4k96001 | 0x3c); ps->ShadingScanLineBlks = 6; ps->ShadingScanLineLen = (ps->BufferSizeBase * 3); ps->OneScanLineLen = (ps->BufferSizePerModel * 3); modelInitMotor( ps ); modelInitCaps ( ps ); modelInitPageSettings( ps ); DBG( DBG_LOW, "ModelSet4800() done.\n" ); } /*............................................................................. * set the model to 4830 */ _LOC void ModelSet4830( pScanData ps ) { DBG( DBG_LOW, "ModelSet4830()\n" ); /* has 96003 ASIC */ ps->sCaps.Model = MODEL_OP_4830P; if( _OVR_PRIMAX_4800D30 == ps->ModelOverride ) { DBG( DBG_LOW, "Model Override --> Primax 4800D 30\n" ); ps->sCaps.Model = MODEL_PMX_4800D3; } ps->sCaps.AsicID = _ASIC_IS_96003; ps->Device.buttons = 1; ps->Device.ModelCtrl = (_ModelDpi300 | _ModelMemSize32k3 | _ModelWhiteIs0); ps->Device.DataOriginX = 72; ps->PhysicalDpi = 300; ps->TimePerLine = 0x30; ps->Offset70 = 70; modelSetBufferSizes( ps ); ps->a_wGrayInitTime[0] = 220; /* _EppTimeForOthers */ ps->a_wGrayInitTime[1] = 720; /* _SppTimeForOthers */ ps->a_wGrayInitTime[2] = 360; /* _BidirTimeForOthers */ ps->a_wColorInitTime[0] = 500; /* _EppTimeForColor */ ps->a_wColorInitTime[1] = 1680; /* _SppTimeForColor */ ps->a_wColorInitTime[2] = 1100; /* _BidirTimeForColor */ ps->AsicRedColor = _ASIC_REDCOLOR; ps->AsicGreenColor = _ASIC_GREENCOLOR; ps->RedDataReady = _RED_DATA_READY; ps->GreenDataReady = _GREEN_DATA_READY; /* * used for shading stuff (see dac.c) */ ps->FBKScanLineBlks = 5; ps->FBKScanLineLenBase = 1024; ps->FBKScanLineLen = (ps->FBKScanLineLenBase * 3); ps->ShadingBufferSize = ps->FBKScanLineLen; ps->ShadingBankSize = (ps->FBKScanLineLenBase * 4); ps->ShadingBankRed = (_MemBankSize4k | 0x3a); ps->ShadingBankGreen = (_MemBankSize4k | 0x3e); ps->ShadingBankBlue = (_MemBankSize4k | 0x3c); ps->ShadingScanLineBlks = 6; ps->ShadingScanLineLen = (ps->BufferSizeBase * 3); ps->OneScanLineLen = (ps->BufferSizePerModel * 3); modelInitMotor( ps ); modelInitCaps ( ps ); modelInitPageSettings( ps ); DBG( DBG_LOW, "ModelSet4830() done.\n" ); } /*............................................................................. * set the model to 600, tested on a Primax Direct 4800 and OP600 */ _LOC void ModelSet600( pScanData ps ) { DBG( DBG_LOW, "ModelSet600()\n" ); /* * set to 4830 first, then do the differences */ ModelSet4830( ps ); ps->Device.buttons = 0; if( _OVR_PLUSTEK_4800P == ps->ModelOverride ) { DBG( DBG_LOW, "Model Override --> OpticPro4800\n" ); ps->sCaps.Model = MODEL_OP_4800P; } else if( _OVR_PRIMAX_4800D == ps->ModelOverride ) { DBG( DBG_LOW, "Model Override --> Primax 4800D\n" ); ps->sCaps.Model = MODEL_PMX_4800D; } else { ps->sCaps.Model = MODEL_OP_600P; /* for Plustek OpticPro 600P it's necessary to swap Red and Green * changed by mh moloch@nikocity.de */ ps->AsicRedColor = _ASIC_GREENCOLOR; ps->AsicGreenColor = _ASIC_REDCOLOR; } DBG( DBG_LOW, "ModelSet600() done.\n" ); } /*............................................................................. * set the model to 12000P, 96000P (tested on a OP96000P) */ _LOC void ModelSet12000( pScanData ps ) { DBG( DBG_LOW, "ModelSet12000()\n" ); /* * set to 9630 first, then do the differences */ ModelSet9630( ps ); ps->Device.buttons = 0; ps->sCaps.Model = MODEL_OP_12000P; /* * swapped Red and Green for 12000P/96000P */ ps->AsicRedColor = _ASIC_GREENCOLOR; ps->AsicGreenColor = _ASIC_REDCOLOR; ps->RedDataReady = _GREEN_DATA_READY; ps->GreenDataReady = _RED_DATA_READY; DBG( DBG_LOW, "ModelSet12000() done.\n" ); } /*............................................................................. * set the model to A3I */ _LOC void ModelSetA3I( pScanData ps ) { DBG( DBG_LOW, "ModelSetA3I()\n" ); /* * has 96003 ASIC */ ps->Device.buttons = 1; ps->sCaps.Model = MODEL_OP_A3I; ps->sCaps.AsicID = _ASIC_IS_96003; ps->Device.ModelCtrl = (_ModelDpi400 | _ModelMemSize128k4 | _ModelWhiteIs0); ps->Device.DataOriginX = 164; ps->PhysicalDpi = 400; ps->TimePerLine = 0x50; ps->Offset70 = 145; modelSetBufferSizes( ps ); ps->a_wGrayInitTime[0] = 133; /* _EppTimeForOthers */ ps->a_wGrayInitTime[1] = 720; /* _SppTimeForOthers */ ps->a_wGrayInitTime[2] = 300; /* _BidirTimeForOthers */ ps->a_wColorInitTime[0] = 400; /* _EppTimeForColor */ ps->a_wColorInitTime[1] = 1800; /* _SppTimeForColor */ ps->a_wColorInitTime[2] = 800; /* _BidirTimeForColor */ ps->AsicRedColor = _ASIC_GREENCOLOR; ps->AsicGreenColor = _ASIC_REDCOLOR; ps->RedDataReady = _GREEN_DATA_READY; ps->GreenDataReady = _RED_DATA_READY; ps->FBKScanLineBlks = 10; ps->FBKScanLineLenBase = 2048; ps->FBKScanLineLen = (ps->FBKScanLineLenBase * 3); ps->ShadingBufferSize = (1024 * 7); ps->ShadingBankSize = 8192; ps->ShadingBankRed = (_MemBankSize8k | 0x34); ps->ShadingBankGreen = (_MemBankSize8k | 0x3c); ps->ShadingBankBlue = (_MemBankSize8k | 0x38); ps->ShadingScanLineBlks = 10; ps->ShadingScanLineLen = (ps->BufferSizeBase * 3); ps->OneScanLineLen = (ps->ShadingScanLineLen * 2); modelInitMotor( ps ); ps->BackwardSteps = 9000; modelInitCaps( ps ); modelInitPageSettings( ps ); /* * need to double the vals */ ps->LensInf.rExtentX.wMax *= 2; ps->LensInf.rExtentX.wPhyMax *= 2; ps->LensInf.rExtentY.wMax *= 2; ps->LensInf.rExtentY.wPhyMax *= 2; DBG( DBG_LOW, "ModelSetA3I() done.\n" ); } /*............................................................................. * set the model to 9630 */ _LOC void ModelSet9630( pScanData ps ) { DBG( DBG_LOW, "ModelSet9360()\n" ); /* * has 96003 ASIC */ if( _OVR_PLUSTEK_9630PL == ps->ModelOverride ) { DBG( DBG_LOW, "Model Override --> 9630PL\n" ); ps->sCaps.Model = MODEL_OP_9630PL; } else { ps->sCaps.Model = MODEL_OP_9630P; } ps->Device.buttons = 1; ps->sCaps.AsicID = _ASIC_IS_96003; ps->Device.ModelCtrl = (_ModelDpi600 | _ModelMemSize128k4 | _ModelWhiteIs0); ps->Device.DataOriginX = 64; ps->PhysicalDpi = 600; ps->TimePerLine = 0x5a; ps->Offset70 = 95; modelSetBufferSizes( ps ); ps->a_wGrayInitTime[0] = 133; /* _EppTimeForOthers */ ps->a_wGrayInitTime[1] = 720; /* _SppTimeForOthers */ ps->a_wGrayInitTime[2] = 300; /* _BidirTimeForOthers */ ps->a_wColorInitTime[0] = 400; /* _EppTimeForColor */ ps->a_wColorInitTime[1] = 1800; /* _SppTimeForColor */ ps->a_wColorInitTime[2] = 800; /* _BidirTimeForColor */ ps->AsicRedColor = _ASIC_REDCOLOR; ps->AsicGreenColor = _ASIC_GREENCOLOR; ps->RedDataReady = _RED_DATA_READY; ps->GreenDataReady = _GREEN_DATA_READY; ps->ShadingBufferSize = (1024 * 7); ps->ShadingBankSize = 8192; ps->ShadingBankRed = (_MemBankSize8k | 0x34); ps->ShadingBankGreen = (_MemBankSize8k | 0x3c); ps->ShadingBankBlue = (_MemBankSize8k | 0x38); ps->ShadingScanLineBlks = 10; ps->ShadingScanLineLen = (2560 * 3); ps->FBKScanLineBlks = 10; ps->FBKScanLineLenBase = 2048; ps->FBKScanLineLen = (ps->FBKScanLineLenBase * 6); ps->OneScanLineLen = (5120 * 3); modelInitMotor( ps ); ps->BackwardSteps = 9000; modelInitCaps( ps ); modelInitPageSettings( ps ); /* * need to double the vals */ ps->LensInf.rExtentX.wMax *= 2; ps->LensInf.rExtentX.wPhyMax *= 2; ps->LensInf.rExtentY.wMax *= 2; ps->LensInf.rExtentY.wPhyMax *= 2; DBG( DBG_LOW, "ModelSet9630() done.\n" ); } /*............................................................................. * set the model to 9636 (ASIC 98001 models) * works for 9636P Turbo and 9636T /12000T */ _LOC void ModelSet9636( pScanData ps ) { DBG( DBG_LOW, "ModelSet9636()\n" ); /* *set to 9630 first, then do the differences */ ModelSet9630( ps ); ps->Device.buttons = 0; /* * has 98001 ASIC */ if( _OVR_PLUSTEK_9636 == ps->ModelOverride ) { DBG( DBG_LOW, "Model Override --> 9636P+/Turbo\n" ); ps->sCaps.Model = MODEL_OP_9636PP; } else if( _OVR_PLUSTEK_9636P == ps->ModelOverride ) { DBG( DBG_LOW, "Model Override --> 9636P\n" ); ps->sCaps.Model = MODEL_OP_9636P; } else { ps->sCaps.Model = MODEL_OP_9636T; ps->sCaps.dwFlag |= SFLAG_TPA; } ps->Device.DataOriginX = 72; ps->sCaps.AsicID = _ASIC_IS_98001; ps->TotalBufferRequire = _LINE_BUFSIZE * 2 + _LINE_BUFSIZE1 + ps->BufferForColorRunTable + _PROCESS_BUFSIZE; /* do it again, as ModelSet9630() changes the result of this function !*/ modelInitPageSettings( ps ); DBG( DBG_LOW, "ModelSet9636() done.\n" ); } /*............................................................................. * set the model to P12 (ASIC 98003 models) */ _LOC void ModelSetP12( pScanData ps ) { DBG( DBG_LOW, "ModelSetP12()\n" ); /* * set to 9630 first, then do the differences */ ModelSet9630( ps ); ps->Device.DataOriginX = 72; ps->sCaps.Model = MODEL_OP_PT12; ps->sCaps.AsicID = _ASIC_IS_98003; ps->TotalBufferRequire = _SizeTotalBufTpa; /* do it again, as ModelSet9630() changes the result of this function !*/ modelInitPageSettings( ps ); DBG( DBG_LOW, "ModelSetP12() done.\n" ); } /* END PLUSTEK-PP_MODEL.C ...................................................*/ sane-backends-1.0.27/backend/ibm.conf.in0000664000175000017500000000004612112021330014615 00000000000000scsi IBM 2456 scsi RICOH /dev/scanner sane-backends-1.0.27/backend/bh.h0000664000175000017500000006750513106201017013357 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1999,2000 Tom Martone This file is part of a SANE backend for Bell and Howell Copiscan II Scanners using the Remote SCSI Controller(RSC). This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef BH_H #define BH_H 1 #ifndef PATH_MAX #define PATH_MAX (1024) #endif #define BH_CONFIG_FILE "bh.conf" /* number of barcode types that can be searched at one time */ #define NUM_SEARCH_BARS 6 /* number of additional scanning/decoding sections supported */ #define NUM_SECTIONS 8 /* number of possible reads per scan plus the extra one for * the barcode file */ #define NUM_READS 56 + 1 /* specify sanity limits for autoborder detection and barcode decoding */ #define BH_AUTOBORDER_TRIES 100 #define BH_DECODE_TRIES 100 /* specify a fudge factor in mm for border around decoded barcodes */ #define BH_DECODE_FUDGE 1.0 /* section flags - what operation(s) to perform on section */ #define BH_SECTION_FRONT_IMAGE (1 << 0) #define BH_SECTION_BACK_IMAGE (1 << 1) #define BH_SECTION_FRONT_BAR (1 << 2) #define BH_SECTION_BACK_BAR (1 << 3) #define BH_SECTION_FRONT_PATCH (1 << 4) #define BH_SECTION_BACK_PATCH (1 << 5) typedef enum { BH_UNIT_INCH, BH_UNIT_MM, BH_UNIT_POINT } bh_measureUnit; typedef enum { BH_COMP_NONE, BH_COMP_G31D, BH_COMP_G32D, BH_COMP_G42D } bh_compress; typedef enum { BH_ROTATION_0, BH_ROTATION_90, BH_ROTATION_180, BH_ROTATION_270 } bh_rotation; typedef enum { OPT_NUM_OPTS = 0, OPT_MODE_GROUP, /* inquiry string */ OPT_INQUIRY, /* preview mode */ OPT_PREVIEW, /* scan mode */ OPT_SCAN_MODE, /* resolution */ OPT_RESOLUTION, /* hardware compression */ OPT_COMPRESSION, OPT_GEOMETRY_GROUP, /* automatic border detection */ OPT_AUTOBORDER, /* hardware rotation */ OPT_ROTATION, /* hardware deskew */ OPT_DESKEW, /* paper size */ OPT_PAPER_SIZE, /* top-left x */ OPT_TL_X, /* top-left y */ OPT_TL_Y, /* bottom-right x */ OPT_BR_X, /* bottom-right y */ OPT_BR_Y, OPT_FEEDER_GROUP, /* scan source (eg. ADF) */ OPT_SCAN_SOURCE, /* scan in batch mode */ OPT_BATCH, /* scan both sides of the page */ OPT_DUPLEX, /* timeout in seconds with manual feed */ OPT_TIMEOUT_MANUAL, /* timeout in seconds with ADF */ OPT_TIMEOUT_ADF, /* check for page in ADF before scanning */ OPT_CHECK_ADF, OPT_ENHANCEMENT_GROUP, /* Enables the scanner's control panel */ OPT_CONTROL_PANEL, /* ACE Function */ OPT_ACE_FUNCTION, /* ACE Sensitivity */ OPT_ACE_SENSITIVITY, /* Brightness */ OPT_BRIGHTNESS, /* Threshold */ OPT_THRESHOLD, /* Contrast */ OPT_CONTRAST, /* Negative (reverse image) */ OPT_NEGATIVE, OPT_ICON_GROUP, /* Width of icon (thumbnail) image in pixels */ OPT_ICON_WIDTH, /* Length of icon (thumbnail) image in pixels */ OPT_ICON_LENGTH, OPT_BARCODE_GROUP, /* Add to barcode search priority. */ OPT_BARCODE_SEARCH_BAR, /* Barcode search count (1-7, default 3). */ OPT_BARCODE_SEARCH_COUNT, /* Barcode search mode. * (1 = horizontal,2 = vertical, 6 = v then h, 9 = h then v). */ OPT_BARCODE_SEARCH_MODE, /* Patch code min height (def=127 (5mm)) */ OPT_BARCODE_HMIN, /* Barcode search timeout in ms * (20-65535,default is disabled). */ OPT_BARCODE_SEARCH_TIMEOUT, /* Specify image sections and functions */ OPT_SECTION, /* Specifies the maximum relation from the widest to * the smallest bar */ OPT_BARCODE_RELMAX, /* Specifies the minimum number of bars in Bar/Patch code */ OPT_BARCODE_BARMIN, /* Specifies the maximum number of bars in a Bar/Patch code */ OPT_BARCODE_BARMAX, /* Specifies the image contrast used in decoding. * Use higher values when there are more white pixels * in the code */ OPT_BARCODE_CONTRAST, /* Controls Patch Code detection. */ OPT_BARCODE_PATCHMODE, /* must come last: */ NUM_OPTIONS } BH_Option; /* macros for accessing the value for an option within a scanning context */ #define _OPT_VAL_WORD(s, o) ((s)->val[(o)].w) #define _OPT_VAL_WORD_THOUSANDTHS(s, o) \ (SANE_UNFIX(_OPT_VAL_WORD((s), (o))) * 1000.0 / MM_PER_INCH) #define _OPT_VAL_STRING(s, o) ((s)->val[(o)].s) #define _OPT_VAL_WORD_ARRAY(s, o) ((s)->val[(o)].wa) typedef struct _BH_Paper { SANE_String name; /* paper dimensions in mm */ double width, length; } BH_Paper; typedef struct _BH_Section { /* section dimensions - in millimeters */ u_long top, left, width, length; /* compression type/arg/frameformat */ SANE_Byte compressiontype; SANE_Byte compressionarg; SANE_Frame format; /* Flags (see BH_SECTION_...) indicating operation(s) to perform * on the section. If zero, the section is completely disabled * and will not even be defined in set_window. */ SANE_Word flags; } BH_Section; typedef struct _BH_Info { SANE_Range x_range; SANE_Range y_range; SANE_Int res_default; SANE_Bool autoborder_default; SANE_Bool batch_default; SANE_Bool deskew_default; SANE_Bool check_adf_default; SANE_Bool duplex_default; SANE_Int timeout_adf_default; SANE_Int timeout_manual_default; SANE_Bool control_panel_default; /* additional discovered/guessed capabilities */ SANE_Bool canACE; SANE_Bool canDuplex; SANE_Bool canCheckADF; /* standard information */ SANE_Byte devtype; SANE_Char vendor[9]; /* model name */ SANE_Char product[17]; /* product name */ SANE_Char revision[5]; /* revision */ /* VPD information */ SANE_Bool canADF; /* is there an ADF available */ SANE_Bool colorBandW; /* can scanner do black and white */ SANE_Bool colorHalftone; /* can scanner do Halftone */ SANE_Bool canWhiteFrame; /* data processing: White Framing */ SANE_Bool canBlackFrame; /* data processing: Black Framing */ SANE_Bool canEdgeExtract; /* data processing: ACE: Edge Extraction */ SANE_Bool canNoiseFilter; /* data processing: ACE: Noise Filtering */ SANE_Bool canSmooth; /* data processing: ACE: Smoothing */ SANE_Bool canLineBold; /* data processing: ACE: LineBolding */ SANE_Bool comprG3_1D; /* compression: Group 3, 1 dimensional */ SANE_Bool comprG3_2D; /* compression: Group 3, 2 dimensional */ SANE_Bool comprG4; /* compression: Group 4 */ SANE_Bool canBorderRecog; /* can do border recognition */ SANE_Bool canBarCode; /* bar code support available */ SANE_Bool canIcon; /* icon support available */ SANE_Bool canSection; /* section support available */ SANE_Int lineMaxBytes; /* maximum bytes per scan-line */ /* jis information */ SANE_Int resBasicX; /* basic X resolution */ SANE_Int resBasicY; /* basic Y resolution */ SANE_Int resMaxX; /* maximum X resolution */ SANE_Int resMaxY; /* maximum Y resolution */ SANE_Int resMinX; /* minimum X resolution */ SANE_Int resMinY; /* minimum Y resolution */ SANE_Int resStdList[16+1]; /* list of available standard resolutions * (first slot is the length) */ SANE_Int winWidth; /* length of window (in BasicX res DPI) */ SANE_Int winHeight; /* height of window (in BasicY res DPI) */ } BH_Info; typedef struct _BH_Device BH_Device; struct _BH_Device { BH_Device *next; SANE_Device sane; BH_Info info; }; typedef struct _BH_Scanner BH_Scanner; struct _BH_Scanner { /* all the state needed to define a scan request: */ /* linked list for housekeeping */ BH_Scanner *next; /* scanner dependent/low-level state: */ BH_Device *hw; /* SCSI filedescriptor */ int fd; /* tempfile which is used to send decoded barcode data */ FILE *barf; char barfname[PATH_MAX+1]; /* SANE option descriptors and values */ SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; /* additional values that don't fit into Option_Value representation */ SANE_Byte search_bars[NUM_SEARCH_BARS]; BH_Section sections[NUM_SECTIONS]; SANE_Int num_sections; /* SANE image parameters */ SANE_Parameters params; /* state information - not options */ /* Basic Measurement Unit */ SANE_Int bmu; /* Measurement Unit Divisor */ SANE_Int mud; /* track data to be read. ReadList contains the codes of the read types * (see BH_READ_TYPE...) to perform, readcnt is the total number of reads * for this scan and readptr points to the current read operation. */ SANE_Byte readlist[NUM_READS]; SANE_Int readcnt, readptr; u_long InvalidBytes; SANE_Bool scanning; SANE_Bool cancelled; SANE_Bool backpage; SANE_Bool barcodes; SANE_Bool patchcodes; SANE_Bool icons; u_long iconwidth, iconlength; SANE_Bool barcode_not_found; }; static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; static const SANE_Range u16_range = { 0, /* minimum */ 65535, /* maximum */ 0 /* quantization */ }; static const SANE_Range icon_range = { 0, /* minimum */ 3600, /* maximum */ 8 /* quantization */ }; static const SANE_Range barcode_search_timeout_range = { 20, /* minimum */ 65535, /* maximum */ 0 /* quantization */ }; static const SANE_Range barcode_hmin_range = { 1, /* minimum */ 1660, /* maximum (when converted from mm * to thousandths will still be less * than 65536) */ 0 /* quantization */ }; static const SANE_Range barcode_search_count_range = { 1, /* minimum */ 7, /* maximum */ 0 /* quantization */ }; static const SANE_Range barcode_relmax_range = { 0, /* minimum */ 6, /* maximum */ 0 /* quantization */ }; static const SANE_Range barcode_contrast_range = { 0, /* minimum */ 6, /* maximum */ 0 /* quantization */ }; static const SANE_Range barcode_patchmode_range = { 0, /* minimum */ 1, /* maximum */ 0 /* quantization */ }; static const SANE_Range ace_function_range = { -4, /* minimum */ 4, /* maximum */ 0 /* quantization */ }; static const SANE_Range ace_sensitivity_range = { 0, /* minimum */ 9, /* maximum */ 0 /* quantization */ }; static SANE_String_Const scan_mode_list[] = { "lineart", "halftone", 0 }; static SANE_String_Const scan_mode_min_list[] = { "lineart", 0 }; static SANE_String_Const barcode_search_mode_list[] = { "horiz-vert", /* 9 */ "horizontal", /* 1 */ "vertical", /* 2 */ "vert-horiz", /* 6 */ 0 }; static SANE_String_Const scan_source_list[] = { "Automatic Document Feeder", "Manual Feed Tray", 0 }; static SANE_String_Const compression_list[] = { "none", "g31d", "g32d", "g42d", 0 }; /* list of supported bar/patch codes */ static SANE_String_Const barcode_search_bar_list[] = { "none", "ean-8", "ean-13", "reserved-ean-add", "code39", "code2-5-interleaved", "code2-5-3lines-matrix", "code2-5-3lines-datalogic", "code2-5-5lines-industrial", "patchcode", "codabar", "codabar-with-start-stop", "code39ascii", "code128", "code2-5-5lines-iata", 0 }; /* list of supported rotation angles */ static SANE_String_Const rotation_list[] = { "0", "90", "180", "270", 0 }; /* list of support paper sizes */ /* 'custom' MUST be item 0; otherwise a width or length of 0 indicates * the maximum value supported by the scanner */ static const BH_Paper paper_sizes[] = { {"Custom", 0.0, 0.0}, {"Letter", 215.9, 279.4}, {"Legal", 215.9, 355.6}, {"A3", 297, 420}, {"A4", 210, 297}, {"A5", 148.5, 210}, {"A6", 105, 148.5}, {"B4", 250, 353}, {"B5", 182, 257}, {"Full", 0.0, 0.0}, }; /* MUST be kept in sync with paper_sizes */ static SANE_String_Const paper_list[] = { "Custom", "Letter", "Legal", "A3", "A4", "A5", "A6", "B4", "B5", "Full", 0 }; static /* inline */ int _is_host_little_endian(void); static /* inline */ int _is_host_little_endian() { SANE_Int val = 255; unsigned char *firstbyte = (unsigned char *) &val; return (*firstbyte == 255) ? SANE_TRUE : SANE_FALSE; } static /* inline */ void _lto2b(u_long val, SANE_Byte *bytes) { bytes[0] = (val >> 8) & 0xff; bytes[1] = val & 0xff; } static /* inline */ void _lto3b(u_long val, SANE_Byte *bytes) { bytes[0] = (val >> 16) & 0xff; bytes[1] = (val >> 8) & 0xff; bytes[2] = val & 0xff; } static /* inline */ void _lto4b(u_long val, SANE_Byte *bytes) { bytes[0] = (val >> 24) & 0xff; bytes[1] = (val >> 16) & 0xff; bytes[2] = (val >> 8) & 0xff; bytes[3] = val & 0xff; } static /* inline */ u_long _2btol(SANE_Byte *bytes) { u_long rv; rv = (bytes[0] << 8) | bytes[1]; return rv; } static /* inline */ u_long _4btol(SANE_Byte *bytes) { u_long rv; rv = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; return rv; } #define SANE_TITLE_SCAN_MODE_GROUP "Scan Mode" #define SANE_TITLE_GEOMETRY_GROUP "Geometry" #define SANE_TITLE_FEEDER_GROUP "Feeder" #define SANE_TITLE_ENHANCEMENT_GROUP "Enhancement" #define SANE_TITLE_ICON_GROUP "Icon" #define SANE_TITLE_BARCODE_GROUP "Barcode" #define SANE_NAME_AUTOBORDER "autoborder" #define SANE_TITLE_AUTOBORDER "Autoborder" #define SANE_DESC_AUTOBORDER "Enable Automatic Border Detection" #define SANE_NAME_COMPRESSION "compression" #define SANE_TITLE_COMPRESSION "Data Compression" #define SANE_DESC_COMPRESSION "Sets the compression mode of the scanner" #define SANE_NAME_ROTATION "rotation" #define SANE_TITLE_ROTATION "Page Rotation" #define SANE_DESC_ROTATION "Sets the page rotation mode of the scanner" #define SANE_NAME_DESKEW "deskew" #define SANE_TITLE_DESKEW "Page Deskew" #define SANE_DESC_DESKEW "Enable Deskew Mode" #define SANE_NAME_TIMEOUT_ADF "timeout-adf" #define SANE_TITLE_TIMEOUT_ADF "ADF Timeout" #define SANE_DESC_TIMEOUT_ADF "Sets the timeout in seconds for the ADF" #define SANE_NAME_TIMEOUT_MANUAL "timeout-manual" #define SANE_TITLE_TIMEOUT_MANUAL "Manual Timeout" #define SANE_DESC_TIMEOUT_MANUAL "Sets the timeout in seconds for manual feeder" #define SANE_NAME_BATCH "batch" #define SANE_TITLE_BATCH "Batch" #define SANE_DESC_BATCH "Enable Batch Mode" #define SANE_NAME_CHECK_ADF "check-adf" #define SANE_TITLE_CHECK_ADF "Check ADF" #define SANE_DESC_CHECK_ADF "Check ADF Status prior to starting scan" #define SANE_NAME_DUPLEX "duplex" #define SANE_TITLE_DUPLEX "Duplex" #define SANE_DESC_DUPLEX "Enable Duplex (Dual-Sided) Scanning" #define SANE_NAME_BARCODE_SEARCH_COUNT "barcode-search-count" #define SANE_TITLE_BARCODE_SEARCH_COUNT "Barcode Search Count" #define SANE_DESC_BARCODE_SEARCH_COUNT "Number of barcodes to search for in the scanned image" #define SANE_NAME_BARCODE_HMIN "barcode-hmin" #define SANE_TITLE_BARCODE_HMIN "Barcode Minimum Height" #define SANE_DESC_BARCODE_HMIN "Sets the Barcode Minimum Height (larger values increase recognition speed)" #define SANE_NAME_BARCODE_SEARCH_MODE "barcode-search-mode" #define SANE_TITLE_BARCODE_SEARCH_MODE "Barcode Search Mode" #define SANE_DESC_BARCODE_SEARCH_MODE "Chooses the orientation of barcodes to be searched" #define SANE_NAME_BARCODE_SEARCH_TIMEOUT "barcode-search-timeout" #define SANE_TITLE_BARCODE_SEARCH_TIMEOUT "Barcode Search Timeout" #define SANE_DESC_BARCODE_SEARCH_TIMEOUT "Sets the timeout for barcode searching" #define SANE_NAME_BARCODE_SEARCH_BAR "barcode-search-bar" #define SANE_TITLE_BARCODE_SEARCH_BAR "Barcode Search Bar" #define SANE_DESC_BARCODE_SEARCH_BAR "Specifies the barcode type to search for" #define SANE_NAME_SECTION "section" #define SANE_TITLE_SECTION "Image/Barcode Search Sections" #define SANE_DESC_SECTION "Specifies an image section and/or a barcode search region" #define SANE_NAME_BARCODE_RELMAX "barcode-relmax" #define SANE_TITLE_BARCODE_RELMAX "Barcode RelMax" #define SANE_DESC_BARCODE_RELMAX "Specifies the maximum relation from the widest to the smallest bar" #define SANE_NAME_BARCODE_BARMIN "barcode-barmin" #define SANE_TITLE_BARCODE_BARMIN "Barcode Bar Minimum" #define SANE_DESC_BARCODE_BARMIN "Specifies the minimum number of bars in Bar/Patch code" #define SANE_NAME_BARCODE_BARMAX "barcode-barmax" #define SANE_TITLE_BARCODE_BARMAX "Barcode Bar Maximum" #define SANE_DESC_BARCODE_BARMAX "Specifies the maximum number of bars in a Bar/Patch code" #define SANE_NAME_BARCODE_CONTRAST "barcode-contrast" #define SANE_TITLE_BARCODE_CONTRAST "Barcode Contrast" #define SANE_DESC_BARCODE_CONTRAST "Specifies the image contrast used in decoding. Use higher values when " \ "there are more white pixels in the code" #define SANE_NAME_BARCODE_PATCHMODE "barcode-patchmode" #define SANE_TITLE_BARCODE_PATCHMODE "Barcode Patch Mode" #define SANE_DESC_BARCODE_PATCHMODE "Controls Patch Code detection." #define SANE_NAME_CONTROL_PANEL "control-panel" #define SANE_TITLE_CONTROL_PANEL "Control Panel " #define SANE_DESC_CONTROL_PANEL "Enables the scanner's control panel" #define SANE_NAME_ACE_FUNCTION "ace-function" #define SANE_TITLE_ACE_FUNCTION "ACE Function" #define SANE_DESC_ACE_FUNCTION "ACE Function" #define SANE_NAME_ACE_SENSITIVITY "ace-sensitivity" #define SANE_TITLE_ACE_SENSITIVITY "ACE Sensitivity" #define SANE_DESC_ACE_SENSITIVITY "ACE Sensitivity" #define SANE_NAME_ICON_WIDTH "icon-width" #define SANE_TITLE_ICON_WIDTH "Icon Width" #define SANE_DESC_ICON_WIDTH "Width of icon (thumbnail) image in pixels" #define SANE_NAME_ICON_LENGTH "icon-length" #define SANE_TITLE_ICON_LENGTH "Icon Length" #define SANE_DESC_ICON_LENGTH "Length of icon (thumbnail) image in pixels" #define SANE_NAME_PAPER_SIZE "paper-size" #define SANE_TITLE_PAPER_SIZE "Paper Size" #define SANE_DESC_PAPER_SIZE "Specify the scan window geometry by specifying the paper size " \ "of the documents to be scanned" #define SANE_NAME_INQUIRY "inquiry" #define SANE_TITLE_INQUIRY "Inquiry Data" #define SANE_DESC_INQUIRY "Displays scanner inquiry data" /* low level SCSI commands and buffers */ /* SCSI commands */ #define BH_SCSI_TEST_UNIT_READY 0x00 #define BH_SCSI_SET_WINDOW 0x24 #define BH_SCSI_GET_WINDOW 0x25 #define BH_SCSI_READ_SCANNED_DATA 0x28 #define BH_SCSI_INQUIRY 0x12 #define BH_SCSI_MODE_SELECT 0x15 #define BH_SCSI_START_SCAN 0x1b #define BH_SCSI_MODE_SENSE 0x1a #define BH_SCSI_GET_BUFFER_STATUS 0x34 #define BH_SCSI_OBJECT_POSITION 0x31 /* page codes used with BH_SCSI_INQUIRY */ #define BH_INQUIRY_STANDARD_PAGE_CODE 0x00 #define BH_INQUIRY_VPD_PAGE_CODE 0xC0 #define BH_INQUIRY_JIS_PAGE_CODE 0xF0 /* page codes used with BH_SCSI_MODE_SELECT and BH_SCSI_MODE_SENSE */ #define BH_MODE_MEASUREMENT_PAGE_CODE 0x03 #define BH_MODE_TIMEOUT_PAGE_CODE 0x20 #define BH_MODE_ICON_PAGE_CODE 0x21 #define BH_MODE_BARCODE_PRIORITY_PAGE_CODE 0x30 #define BH_MODE_BARCODE_PARAM1_PAGE_CODE 0x31 #define BH_MODE_BARCODE_PARAM2_PAGE_CODE 0x32 #define BH_MODE_BARCODE_PARAM3_PAGE_CODE 0x32 /* data type codes used with BH_SCSI_READ_SCANNED_DATA */ #define BH_SCSI_READ_TYPE_FRONT 0x80 /* 0x81 thru 0x88 read front page sections 1 thru 8 respectively */ #define BH_SCSI_READ_TYPE_BACK 0x90 /* 0x91 thru 0x98 read back page sections 1 thru 8 respectively */ #define BH_SCSI_READ_TYPE_FRONT_BARCODE 0xA0 /* 0xA1 thru 0xA8 read front page barcodes in sections 1 thru 8 respectively */ #define BH_SCSI_READ_TYPE_BACK_BARCODE 0xB0 /* 0xB1 thru 0xB8 read back page barcodes in sections 1 thru 8 respectively */ #define BH_SCSI_READ_TYPE_FRONT_PATCHCODE 0xC0 /* 0xC1 thru 0xC8 read front page patchcodes in sections 1 thru 8 respectively */ #define BH_SCSI_READ_TYPE_BACK_PATCHCODE 0xD0 /* 0xD1 thru 0xD8 read back page patchcodes in sections 1 thru 8 respectively */ #define BH_SCSI_READ_TYPE_FRONT_ICON 0x89 #define BH_SCSI_READ_TYPE_BACK_ICON 0x99 /* this one is not a real readtype; it's used to help transfer the barcode file */ #define BH_SCSI_READ_TYPE_SENDBARFILE 0xBB #define BH_HAS_IMAGE_DATA(i) ((i) >= BH_SCSI_READ_TYPE_FRONT && \ (i) <= BH_SCSI_READ_TYPE_BACK_ICON) /* batchmode codes used with BH_SCSI_SET_WINDOW */ #define BH_BATCH_DISABLE 0x00 #define BH_BATCH_ENABLE 0x01 #define BH_BATCH_TERMINATE 0x02 #define BH_BATCH_ABORT 0x03 /* deskew mode codes used with BH_SCSI_SET_WINDOW */ #define BH_DESKEW_DISABLE 0x00 /* border detection is assumed, see page 3-37 of 8000 manual */ #define BH_DESKEW_ENABLE 0x04 /* deskew and border detection */ /* used with BH_SCSI_SET_WINDOW, BH_SCSI_GET_WINDOW */ typedef struct _BH_SectionBlock { SANE_Byte ul_x[4]; SANE_Byte ul_y[4]; SANE_Byte width[4]; SANE_Byte length[4]; SANE_Byte compressiontype; SANE_Byte compressionarg; SANE_Byte reserved[6]; } BH_SectionBlock; /* used with BH_SCSI_SET_WINDOW, BH_SCSI_GET_WINDOW */ struct window_data { /* window descriptor block byte layout */ SANE_Byte windowid; /* 0 */ SANE_Byte autoborder; /* 1 */ SANE_Byte xres[2]; /* 2,3 */ SANE_Byte yres[2]; /* 4,5 */ SANE_Byte ulx[4]; /* 6-9 */ SANE_Byte uly[4]; /* 10-13 */ SANE_Byte windowwidth[4]; /* 14-17 */ SANE_Byte windowlength[4]; /* 18-21 */ SANE_Byte brightness; /* 22 */ SANE_Byte threshold; /* 23 */ SANE_Byte contrast; /* 24 */ SANE_Byte imagecomposition; /* 25 */ SANE_Byte bitsperpixel; /* 26 */ SANE_Byte halftonecode; /* 27 */ SANE_Byte halftoneid; /* 28 */ SANE_Byte paddingtype; /* 29 */ SANE_Byte bitordering[2]; /* 30,31 */ SANE_Byte compressiontype; /* 32 */ SANE_Byte compressionarg; /* 33 */ SANE_Byte reserved2[6]; /* 34-39 */ SANE_Byte remote; /* 40 */ SANE_Byte acefunction; /* 41 */ SANE_Byte acesensitivity; /* 42 */ SANE_Byte batchmode; /* 43 */ SANE_Byte reserved3[2]; /* 44,45 */ SANE_Byte border_rotation; /* 46 added this for copiscan 8080 */ SANE_Byte reserved4[17]; /* 47-63 added this for copiscan 8080 */ BH_SectionBlock sectionblock[NUM_SECTIONS]; }; /* used with BH_SCSI_READ_SCANNED_DATA */ /* structure for returned decoded barcode data */ struct barcode_data { SANE_Byte reserved1[2]; SANE_Byte barcodetype[2]; SANE_Byte statusflag[2]; SANE_Byte barcodeorientation[2]; SANE_Byte posxa[2]; SANE_Byte posya[2]; SANE_Byte posxb[2]; SANE_Byte posyb[2]; SANE_Byte posxc[2]; SANE_Byte posyc[2]; SANE_Byte posxd[2]; SANE_Byte posyd[2]; SANE_Byte barcodesearchtime[2]; SANE_Byte reserved2[13]; SANE_Byte barcodelen; SANE_Byte barcodedata[160]; }; /* structure for returned icon data block */ struct icon_data { SANE_Byte windowwidth[4]; SANE_Byte windowlength[4]; SANE_Byte iconwidth[4]; SANE_Byte iconwidthbytes[4]; SANE_Byte iconlength[4]; SANE_Byte bitordering; SANE_Byte reserved[7]; SANE_Byte icondatalen[4]; }; /* used with BH_SCSI_INQUIRY */ /* Standard Data [EVPD=0] */ struct inquiry_standard_data { SANE_Byte devtype; SANE_Byte reserved[7]; SANE_Byte vendor[8]; SANE_Byte product[16]; SANE_Byte revision[4]; }; /* VPD Information [EVPD=1, PageCode=C0H] */ struct inquiry_vpd_data { SANE_Byte devtype; SANE_Byte pagecode; SANE_Byte reserved1; SANE_Byte alloclen; SANE_Byte adf; SANE_Byte reserved2[2]; SANE_Byte imagecomposition; SANE_Byte imagedataprocessing[2]; SANE_Byte compression; SANE_Byte reserved3; SANE_Byte sizerecognition; SANE_Byte optionalfeatures; SANE_Byte xmaxoutputbytes[2]; }; /* JIS Information [EVPD=1, PageCode=F0H] */ struct inquiry_jis_data { SANE_Byte devtype; SANE_Byte pagecode; SANE_Byte jisversion; SANE_Byte reserved1; SANE_Byte alloclen; SANE_Byte basicxres[2]; SANE_Byte basicyres[2]; SANE_Byte resolutionstep; SANE_Byte maxxres[2]; SANE_Byte maxyres[2]; SANE_Byte minxres[2]; SANE_Byte minyres[2]; SANE_Byte standardres[2]; SANE_Byte windowwidth[4]; SANE_Byte windowlength[4]; SANE_Byte functions; SANE_Byte reserved2; }; /* used with BH_SCSI_MODE_SELECT and BH_SCSI_MODE_SENSE */ /* Scanning Measurement Parameters PageCode=03H */ struct mode_page_03 { SANE_Byte modedatalen; SANE_Byte mediumtype; SANE_Byte devicespecificparam; SANE_Byte blockdescriptorlen; SANE_Byte pagecode; SANE_Byte paramlen; SANE_Byte bmu; SANE_Byte reserved1; SANE_Byte mud[2]; SANE_Byte reserved2[2]; }; /* Scan Command Timeout PageCode=20H */ struct mode_page_20 { SANE_Byte modedatalen; SANE_Byte mediumtype; SANE_Byte devicespecificparam; SANE_Byte blockdescriptorlen; SANE_Byte pagecode; SANE_Byte paramlen; SANE_Byte timeoutmanual; SANE_Byte timeoutadf; SANE_Byte reserved[4]; }; /* Icon Definition PageCode=21H */ struct mode_page_21 { SANE_Byte modedatalen; SANE_Byte mediumtype; SANE_Byte devicespecificparam; SANE_Byte blockdescriptorlen; SANE_Byte pagecode; SANE_Byte paramlen; SANE_Byte iconwidth[2]; SANE_Byte iconlength[2]; SANE_Byte reserved[2]; }; /* Bar/Patch Code search priority order PageCode=30H */ struct mode_page_30 { SANE_Byte modedatalen; SANE_Byte mediumtype; SANE_Byte devicespecificparam; SANE_Byte blockdescriptorlen; SANE_Byte pagecode; SANE_Byte paramlen; SANE_Byte priority[6]; }; /* Bar/Patch Code search parameters 1 of 3 PageCode=31H */ struct mode_page_31 { SANE_Byte modedatalen; SANE_Byte mediumtype; SANE_Byte devicespecificparam; SANE_Byte blockdescriptorlen; SANE_Byte pagecode; SANE_Byte paramlen; SANE_Byte minbarheight[2]; SANE_Byte searchcount; SANE_Byte searchmode; SANE_Byte searchtimeout[2]; }; /* Bar/Patch Code search parameters 2 of 3 PageCode=32H */ struct mode_page_32 { SANE_Byte modedatalen; SANE_Byte mediumtype; SANE_Byte devicespecificparam; SANE_Byte blockdescriptorlen; SANE_Byte pagecode; SANE_Byte paramlen; SANE_Byte relmax[2]; SANE_Byte barmin[2]; SANE_Byte barmax[2]; }; /* Bar/Patch Code search parameters 3 of 3 PageCode=33H */ struct mode_page_33 { SANE_Byte modedatalen; SANE_Byte mediumtype; SANE_Byte devicespecificparam; SANE_Byte blockdescriptorlen; SANE_Byte pagecode; SANE_Byte paramlen; SANE_Byte barcodecontrast[2]; SANE_Byte patchmode[2]; SANE_Byte reserved[2]; }; #ifndef sane_isbasicframe #define SANE_FRAME_TEXT 10 #define SANE_FRAME_JPEG 11 #define SANE_FRAME_G31D 12 #define SANE_FRAME_G32D 13 #define SANE_FRAME_G42D 14 #define sane_strframe(f) ( (f) == SANE_FRAME_GRAY ? "gray" : \ (f) == SANE_FRAME_RGB ? "RGB" : \ (f) == SANE_FRAME_RED ? "red" : \ (f) == SANE_FRAME_GREEN ? "green" : \ (f) == SANE_FRAME_BLUE ? "blue" : \ (f) == SANE_FRAME_TEXT ? "text" : \ (f) == SANE_FRAME_JPEG ? "jpeg" : \ (f) == SANE_FRAME_G31D ? "g31d" : \ (f) == SANE_FRAME_G32D ? "g32d" : \ (f) == SANE_FRAME_G42D ? "g42d" : \ "unknown" ) #define sane_isbasicframe(f) ( (f) == SANE_FRAME_GRAY || \ (f) == SANE_FRAME_RGB || \ (f) == SANE_FRAME_RED || \ (f) == SANE_FRAME_GREEN || \ (f) == SANE_FRAME_BLUE ) #endif #endif /* BH_H */ sane-backends-1.0.27/backend/gt68xx.conf.in0000664000175000017500000001717112112021330015225 00000000000000 # gt68xx.conf: Configuration file for GT68XX based scanners (@PACKAGEVERSION@) # Read man sane-gt68xx for documentation # Put the firmware file into "@DATADIR@/sane/gt68xx/". # Manual configuration is necessary for some scanners. Please uncomment the # override line and optinally the vendor and product lines that apply to your # scanner. For some scanners it's also necessary to change the name of the # firmware file. ############################################################################# # For testing scanners that are not yet supported by this backend add the # vendor and product ids in the usb line below. Also fill in the override # and firmware lines. For more details, see: # http://www.meier-geinitz.de/sane/gt68xx-backend/adding.html # usb vendor product # override "something" # firmware "path" ############################################################################## # Autodetect Mustek BearPaw 1200 CU, 2400 CU, Mustek ScanExpress 1200 UB Plus, # Artec Ultima 2000 (e+), and several other GT-6801-based scanners usb 0x05d8 0x4002 # Mustek BearPaw 1200 CU doesn't need any manual override # Mustek ScanExpress 1200 UB Plus: #override "mustek-scanexpress-1200-ub-plus" # Medion/Lifetec/Tevion LT 9452: #override "mustek-scanexpress-1200-ub-plus" #vendor "Lifetec" #model "LT 9452" # Trust Compact Scan USB 19200: #override "mustek-scanexpress-1200-ub-plus" #vendor "Trust" #model "Compact Scan USB 19200" # Mustek ScanExpress 2400 USB #override "mustek-scanexpress-2400-usb" # Artec Ultima 2000: #override "artec-ultima-2000" #firmware "ePlus2k.usb" # Artec Ultima 2000e+: #override "artec-ultima-2000" #firmware "ePlus2k.usb" #vendor "Artec" #model "Ultima 2000e+" # Boeder SmartScan Slim Edition: #override "artec-ultima-2000" #vendor "Boeder" #model "SmartScan Slim Edition" # Medion/Lifetec/Tevion/Cytron MD/LT 9385: #override "artec-ultima-2000" #vendor "Medion" #model "MD/LT 9385" # Medion/Lifetec/Tevion/Cytron MD 9458: #override "artec-ultima-2000" #vendor "Medion" #model "MD 9458" # Trust Flat Scan USB 19200: #override "artec-ultima-2000" #vendor "Trust" #model "Flat Scan USB 19200" # Mustek BearPaw 2400 CU: #override "mustek-bearpaw-2400-cu" # Fujitsu 1200CUS: #override "mustek-bearpaw-2400-cu" #vendor "Fujitsu" #model "1200CUS" ############################################################################## # Autodetect Mustek BearPaw 1200 TA and Mustek BearPaw 1200 CS usb 0x055f 0x021e # Mustek BearPaw 1200 TA doesn't need any manual settings # Mustek BearPaw 1200 CS: #model "Bearpaw 1200 CS" ############################################################################## # Autodetect Mustek BearPaw 2400 TA and Mustek BearPaw 2400 CS usb 0x055f 0x0218 # Mustek BearPaw 2400 TA doesn't need any manual settings # Mustek BearPaw 2400 CS: #model "Bearpaw 2400 CS" ############################################################################## # Autodetect Mustek BearPaw 2400 TA Plus, Packard Bell Diamond 2450, and # Trust 240TH Easy Webscan Gold usb 0x055f 0x0219 # Mustek BearPaw 2400 TA doesn't need any manual settings # Trust 240TH Easy Webscan Gold: #vendor "Trust" #model "240TH Easy Webscan Gold" # Packard Bell Diamond 2450: #vendor "Packard Bell" #model "Diamond 2450" ############################################################################## # Autodetect Mustek BearPaw 2448 TA Plus and Mustek BearPaw 2448 CS Plus usb 0x055f 0x021a # Mustek BearPaw 2448 CS Plus: #model "Bearpaw 2448 CS Plus" ############################################################################## # Autodetect Mustek BearPaw 2400 CU Plus usb 0x055f 0x021d ############################################################################## # Autodetect Mustek ScanExpress 1248 UB usb 0x055f 0x021f ############################################################################## # Autodetect Mustek Bearpaw 1200 CU Plus and Packard Bell Diamond 1200 usb 0x055f 0x021c # Mustek BearPaw 1200 CU Plus doesn't need any manual settings # Packard Bell Diamond 1200: #vendor "Packard Bell" #model "Diamond 1200" # Another Mustek BearPaw 1200 CU Plus version? usb 0x055f 0x021b ############################################################################## # Autodetect Mustek ScanExpress A3 USB usb 0x055f 0x0210 # Mustek ScanExpress A3 USB doesn't need any manual settings ############################################################################## # Autodetect Lexmark X70/X73 usb 0x043d 0x002d ############################################################################## # Autodetect Plustek OpticPro 1248U and Revscan 19200i usb 0x07b3 0x0401 usb 0x07b3 0x0400 # Plustek OpticPro 1248U doesn't need any manual settings # RevScan 19200i #vendor "RevScan" #model "19200i" ############################################################################## # Autodetect Plustek OpticPro U16B and UT16B usb 0x07b3 0x0402 usb 0x07b3 0x0403 # Plustek OpticPro U16B doesn't need any manual settings # Plustek OpticPro UT16B #model "UT16B" ############################################################################## # Autodetect Plustek OpticPro S12 and Nortek MyScan1200 usb 0x07b3 0x040b #vendor "Nortek" #model "MyScan 1200" ############################################################################## # Autodetect Plustek OpticPro S24 usb 0x07b3 0x040e ############################################################################## # Autodetect Plustek OpticSlim M12 and NeatReceipts Scanalizer Professional 2.5 usb 0x07b3 0x0412 #vendor "NeatReceipts" #model "Scanalizer Professional 2.5" ############################################################################## # Iriscan Express 2 usb 0x07b3 0x045f ############################################################################## # Autodetect NeatReceipts Mobile Scanner usb 0x07b3 0x0462 ############################################################################## # Autodetect Plustek OpticSlim 1200 usb 0x07b3 0x0413 ############################################################################## # Autodetect Plustek OpticSlim 2400 usb 0x07b3 0x0422 ############################################################################## # Autodetect Plustek OpticSlim 2400 plus usb 0x07b3 0x0454 model "OpticSlim 2400 Plus" override "plustek-opticslim-2400" ############################################################################## # Autodetect Genius Colorpage SF600 usb 0x0458 0x2021 ############################################################################## # Autodetect Genius Colorpage Vivid3x usb 0x0458 0x2011 # Genius Colorpage Vivid3x doesn't need any manual settings ############################################################################## # Autodetect Genius Colorpage Vivid4x usb 0x0458 0x201b ############################################################################## # Autodetect Genius Colorpage Vivid3xe usb 0x0458 0x2017 ############################################################################## # Autodetect Genius Colorpage Vivid4xe usb 0x0458 0x201a ############################################################################## # Autodetect Genius Colorpage 1200 X usb 0x0458 0x201d ############################################################################## # Autodetect Genius Colorpage 1200 XE usb 0x0458 0x201f ############################################################################## # Autodetect Genius Colorpage Vivid 4 usb 0x0458 0x2014 ############################################################################## # Autodetect Genius Color Slim 1200 usb 0x0458 0x201E ############################################################################## # Autodetect Visioneer OneTouch 7300 usb 0x04a7 0x0444 ############################################################################## sane-backends-1.0.27/backend/pie.c0000664000175000017500000031676012775312261013555 00000000000000/* sane - Scanner Access Now Easy. pie.c Copyright (C) 2000 Simon Munton, based on the umax backend by Oliver Rauch This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* * 22-2-2003 set devlist to NULL in sane_exit() * set first_dev to NULL in sane_exit() * eliminated num_devices * * 23-7-2002 added TL_X > BR_X, TL_Y > BR_Y check in sane_start * * 17-9-2001 changed ADLIB to AdLib as the comparison is case sensitive and * the scanner returns AdLib * * 7-5-2001 removed removal of '\n' after sanei_config_read() * free devlist allocated in sane_get_devices() on sane_exit() * * 2-3-2001 improved the reordering of RGB data in pie_reader_process() * * 11-11-2000 eliminated some warnings about signed/unsigned comparisons * removed #undef NDEBUG and C++ style comments * * 1-10-2000 force gamma table to one to one mappping if lineart or halftone selected * * 30-9-2000 added ADLIB devices to scanner_str[] * * 29-9-2000 wasn't setting 'background is halftone bit' (BGHT) in halftone mode * * 27-9-2000 went public with build 4 */ #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_debug.h" #define BACKEND_NAME pie #include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_config.h" # include "../include/sane/sanei_thread.h" #include "pie-scsidef.h" #define DBG_error0 0 #define DBG_error 1 #define DBG_sense 2 #define DBG_warning 3 #define DBG_inquiry 4 #define DBG_info 5 #define DBG_info2 6 #define DBG_proc 7 #define DBG_read 8 #define DBG_sane_init 10 #define DBG_sane_proc 11 #define DBG_sane_info 12 #define DBG_sane_option 13 #define DBG_dump 14 #define BUILD 9 #define PIE_CONFIG_FILE "pie.conf" #define LINEART_STR SANE_VALUE_SCAN_MODE_LINEART #define HALFTONE_STR SANE_VALUE_SCAN_MODE_HALFTONE #define GRAY_STR SANE_VALUE_SCAN_MODE_GRAY #define COLOR_STR SANE_VALUE_SCAN_MODE_COLOR #define LINEART 1 #define HALFTONE 2 #define GRAYSCALE 3 #define RGB 4 #define CAL_MODE_PREVIEW (INQ_CAP_FAST_PREVIEW) #define CAL_MODE_FLATBED 0x00 #define CAL_MODE_ADF (INQ_OPT_DEV_ADF) #define CAL_MODE_TRANPSARENCY (INQ_OPT_DEV_TP) #define CAL_MODE_TRANPSARENCY1 (INQ_OPT_DEV_TP1) #define min(a,b) (((a)<(b))?(a):(b)) #define max(a,b) (((a)>(b))?(a):(b)) /* names of scanners that are supported because */ /* the inquiry_return_block is ok and driver is tested */ static char *scanner_str[] = { "DEVCOM", "9636PRO", "DEVCOM", "9636S", "DEVCOM", "9630S", "PIE", "ScanAce 1236S", "PIE", "ScanAce 1230S", "PIE", "ScanAce II", "PIE", "ScanAce III", "PIE", "ScanAce Plus", "PIE", "ScanAce II Plus", "PIE", "ScanAce III Plus", "PIE", "ScanAce V", "PIE", "ScanMedia", "PIE", "ScanMedia II", "PIE", "ScanAce 630S", "PIE", "ScanAce 636S", "AdLib", "JetScan 630", "AdLib", "JetScan 636PRO", "END_OF_LIST" }; /* times (in us) to delay after certain commands. Scanner seems to lock up if it returns busy * status and commands are repeatedly reissued (by kernel error handler) */ #define DOWNLOAD_GAMMA_WAIT_TIME (1000000) #define SCAN_WAIT_TIME (1000000) #define SCAN_WARMUP_WAIT_TIME (500000) #define TUR_WAIT_TIME (500000) /* options supported by the scanner */ enum Pie_Option { OPT_NUM_OPTS = 0, /* ------------------------------------------- */ OPT_MODE_GROUP, OPT_MODE, OPT_RESOLUTION, /* ------------------------------------------- */ OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ /* ------------------------------------------- */ OPT_ENHANCEMENT_GROUP, OPT_HALFTONE_PATTERN, OPT_SPEED, OPT_THRESHOLD, OPT_GAMMA_VECTOR, OPT_GAMMA_VECTOR_R, OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, /* ------------------------------------------- */ OPT_ADVANCED_GROUP, OPT_PREVIEW, /* must come last: */ NUM_OPTIONS }; /* This defines the information needed during calibration */ struct Pie_cal_info { int cal_type; int receive_bits; int send_bits; int num_lines; int pixels_per_line; }; /* This structure holds the information about a physical scanner */ typedef struct Pie_Device { struct Pie_Device *next; char *devicename; /* name of the scanner device */ char vendor[9]; /* will be xxxxx */ char product[17]; /* e.g. "SuperVista_S12" or so */ char version[5]; /* e.g. V1.3 */ SANE_Device sane; SANE_Range dpi_range; SANE_Range x_range; SANE_Range y_range; SANE_Range exposure_range; SANE_Range shadow_range; SANE_Range highlight_range; int inquiry_len; /* length of inquiry return block */ int inquiry_x_res; /* maximum x-resolution */ int inquiry_y_res; /* maximum y-resolution */ int inquiry_pixel_resolution; double inquiry_fb_width; /* flatbed width in inches */ double inquiry_fb_length; /* flatbed length in inches */ int inquiry_trans_top_left_x; int inquiry_trans_top_left_y; double inquiry_trans_width; /* transparency width in inches */ double inquiry_trans_length; /* transparency length in inches */ int inquiry_halftones; /* number of halftones supported */ int inquiry_filters; /* available colour filters */ int inquiry_color_depths; /* available colour depths */ int inquiry_color_format; /* colour format from scanner */ int inquiry_image_format; /* image data format */ int inquiry_scan_capability; /* additional scanner features, number of speeds */ int inquiry_optional_devices; /* optional devices */ int inquiry_enhancements; /* enhancements */ int inquiry_gamma_bits; /* no of bits used for gamma table */ int inquiry_fast_preview_res; /* fast preview resolution */ int inquiry_min_highlight; /* min highlight % that can be used */ int inquiry_max_shadow; /* max shadow % that can be used */ int inquiry_cal_eqn; /* which calibration equation to use */ int inquiry_min_exp; /* min exposure % */ int inquiry_max_exp; /* max exposure % */ SANE_String scan_mode_list[7]; /* holds names of types of scan (color, ...) */ SANE_String halftone_list[17]; /* holds the names of the halftone patterns from the scanner */ SANE_String speed_list[9]; /* holds the names of available speeds */ int cal_info_count; /* number of calibration info sets */ struct Pie_cal_info *cal_info; /* points to the actual calibration information */ } Pie_Device; /* This structure holds information about an instance of an 'opened' scanner */ typedef struct Pie_Scanner { struct Pie_Scanner *next; Pie_Device *device; /* pointer to physical scanner */ int sfd; /* scanner file desc. */ int bufsize; /* max scsi buffer size */ SANE_Option_Descriptor opt[NUM_OPTIONS]; /* option descriptions for this instance */ Option_Value val[NUM_OPTIONS]; /* option settings for this instance */ SANE_Int *gamma_table[4]; /* gamma tables for this instance */ SANE_Range gamma_range; int gamma_length; /* size of gamma table */ int scanning; /* true if actually doing a scan */ SANE_Parameters params; SANE_Pid reader_pid; int pipe; int reader_fds; int colormode; /* whether RGB, GRAY, LINEART, HALFTONE */ int resolution; int cal_mode; /* set to value to compare cal_info mode to */ int cal_filter; /* set to indicate which filters will provide data for cal */ int filter_offset1; /* offsets between colors in indexed scan mode */ int filter_offset2; int bytes_per_line; /* number of bytes per line */ } Pie_Scanner; static const SANE_Range percentage_range_100 = { 0 << SANE_FIXED_SCALE_SHIFT, /* minimum */ 100 << SANE_FIXED_SCALE_SHIFT, /* maximum */ 0 << SANE_FIXED_SCALE_SHIFT /* quantization */ }; static Pie_Device *first_dev = NULL; static Pie_Scanner *first_handle = NULL; static const SANE_Device **devlist = NULL; static SANE_Status pie_wait_scanner (Pie_Scanner * scanner); /* ---------------------------------- PIE DUMP_BUFFER ---------------------------------- */ #define DBG_DUMP(level, buf, n) { if (DBG_LEVEL >= (level)) pie_dump_buffer(level,buf,n); } static void pie_dump_buffer (int level, unsigned char *buf, int n) { char s[80], *p = s; int a = 0; while (n--) { if ((a % 16) == 0) p += sprintf (p, " %04X ", a); p += sprintf (p, "%02X ", *buf++); if ((n == 0) || (a % 16) == 15) { DBG (level, "%s\n", s); p = s; } a++; } } /* ---------------------------------- PIE INIT ---------------------------------- */ static void pie_init (Pie_Device * dev) /* pie_init is called once while driver-initialization */ { DBG (DBG_proc, "init\n"); dev->cal_info_count = 0; dev->cal_info = NULL; dev->devicename = NULL; dev->inquiry_len = 0; #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED DBG (DBG_info, "variable scsi buffer size (usage of sanei_scsi_open_extended)\n"); #else DBG (DBG_info, "fixed scsi buffer size = %d bytes\n", sanei_scsi_max_request_size); #endif } /* ---------------------------- SENSE_HANDLER ------------------------------ */ static SANE_Status sense_handler (__sane_unused__ int scsi_fd, unsigned char *result, __sane_unused__ void *arg) /* is called by sanei_scsi */ { unsigned char asc, ascq, sensekey; int asc_ascq, len; /* Pie_Device *dev = arg; */ DBG (DBG_proc, "check condition sense handler\n"); sensekey = get_RS_sense_key (result); asc = get_RS_ASC (result); ascq = get_RS_ASCQ (result); asc_ascq = (int) (256 * asc + ascq); len = 7 + get_RS_additional_length (result); if (get_RS_error_code (result) != 0x70) { DBG (DBG_proc, "invalid sense key => handled as DEVICE BUSY!\n"); return SANE_STATUS_DEVICE_BUSY; /* sense key invalid */ } DBG (DBG_sense, "check condition sense: %s\n", sense_str[sensekey]); if (get_RS_ILI (result) != 0) { DBG (DBG_sense, "-> ILI-ERROR: requested data length is larger than actual length\n"); } switch (sensekey) { case 0x00: /* no sense, could have been busy */ return SANE_STATUS_IO_ERROR; break; case 0x02: if (asc_ascq == 0x0401) DBG (DBG_sense, "-> Not Ready - Warming Up\n"); else if (asc_ascq == 0x0483) DBG (DBG_sense, "-> Not Ready - Need manual service\n"); else if (asc_ascq == 0x0881) DBG (DBG_sense, "-> Not Ready - Communication time out\n"); else DBG (DBG_sense, "-> unknown medium error: asc=%d, ascq=%d\n", asc, ascq); break; case 0x03: /* medium error */ if (asc_ascq == 0x5300) DBG (DBG_sense, "-> Media load or eject failure\n"); else if (asc_ascq == 0x3a00) DBG (DBG_sense, "-> Media not present\n"); else if (asc_ascq == 0x3b05) DBG (DBG_sense, "-> Paper jam\n"); else if (asc_ascq == 0x3a80) DBG (DBG_sense, "-> ADF paper out\n"); else DBG (DBG_sense, "-> unknown medium error: asc=%d, ascq=%d\n", asc, ascq); break; case 0x04: /* hardware error */ if (asc_ascq == 0x4081) DBG (DBG_sense, "-> CPU RAM failure\n"); else if (asc_ascq == 0x4082) DBG (DBG_sense, "-> Scanning system RAM failure\n"); else if (asc_ascq == 0x4083) DBG (DBG_sense, "-> Image buffer failure\n"); else if (asc_ascq == 0x0403) DBG (DBG_sense, "-> Manual intervention required\n"); else if (asc_ascq == 0x6200) DBG (DBG_sense, "-> Scan head position error\n"); else if (asc_ascq == 0x6000) DBG (DBG_sense, "-> Lamp or CCD failure\n"); else if (asc_ascq == 0x6081) DBG (DBG_sense, "-> Transparency lamp failure\n"); else if (asc_ascq == 0x8180) DBG (DBG_sense, "-> DC offset or black level calibration failure\n"); else if (asc_ascq == 0x8181) DBG (DBG_sense, "-> Integration time adjustment failure (too light)\n"); else if (asc_ascq == 0x8182) DBG (DBG_sense, "-> Integration time adjustment failure (too dark)\n"); else if (asc_ascq == 0x8183) DBG (DBG_sense, "-> Shading curve adjustment failure\n"); else if (asc_ascq == 0x8184) DBG (DBG_sense, "-> Gain adjustment failure\n"); else if (asc_ascq == 0x8185) DBG (DBG_sense, "-> Optical alignment failure\n"); else if (asc_ascq == 0x8186) DBG (DBG_sense, "-> Optical locating failure\n"); else if (asc_ascq == 0x8187) DBG (DBG_sense, "-> Scan pixel map less than 5100 pixels!\n"); else if (asc_ascq == 0x4700) DBG (DBG_sense, "-> Parity error on SCSI bus\n"); else if (asc_ascq == 0x4b00) DBG (DBG_sense, "-> Data phase error\n"); else DBG (DBG_sense, "-> unknown hardware error: asc=%d, ascq=%d\n", asc, ascq); return SANE_STATUS_IO_ERROR; break; case 0x05: /* illegal request */ if (asc_ascq == 0x1a00) DBG (DBG_sense, "-> Parameter list length error\n"); else if (asc_ascq == 0x2c01) DBG (DBG_sense, "-> Too many windows specified\n"); else if (asc_ascq == 0x2c02) DBG (DBG_sense, "-> Invalid combination of windows\n"); else if (asc_ascq == 0x2c81) DBG (DBG_sense, "-> Illegal scanning frame\n"); else if (asc_ascq == 0x2400) DBG (DBG_sense, "-> Invalid field in CDB\n"); else if (asc_ascq == 0x2481) DBG (DBG_sense, "-> Request too many lines of data\n"); else if (asc_ascq == 0x2000) DBG (DBG_sense, "-> Invalid command OP code\n"); else if (asc_ascq == 0x2501) DBG (DBG_sense, "-> LUN not supported\n"); else if (asc_ascq == 0x2601) DBG (DBG_sense, "-> Parameter not supported\n"); else if (asc_ascq == 0x2602) DBG (DBG_sense, "-> Parameter value invalid - Parameter not specified\n"); else if (asc_ascq == 0x2603) DBG (DBG_sense, "-> Parameter value invalid - Invalid threshold\n"); else if (asc_ascq == 0x2680) DBG (DBG_sense, "-> Parameter value invalid - Control command sequence error\n"); else if (asc_ascq == 0x2681) DBG (DBG_sense, "-> Parameter value invalid - Grain setting (halftone pattern\n"); else if (asc_ascq == 0x2682) DBG (DBG_sense, "-> Parameter value invalid - Illegal resolution setting\n"); else if (asc_ascq == 0x2683) DBG (DBG_sense, "-> Parameter value invalid - Invalid filter assignment\n"); else if (asc_ascq == 0x2684) DBG (DBG_sense, "-> Parameter value invalid - Illegal gamma adjustment setting (look-up table)\n"); else if (asc_ascq == 0x2685) DBG (DBG_sense, "-> Parameter value invalid - Illegal offset setting (digital brightness)\n"); else if (asc_ascq == 0x2686) DBG (DBG_sense, "-> Parameter value invalid - Illegal bits per pixel setting\n"); else if (asc_ascq == 0x2687) DBG (DBG_sense, "-> Parameter value invalid - Illegal contrast setting\n"); else if (asc_ascq == 0x2688) DBG (DBG_sense, "-> Parameter value invalid - Illegal paper length setting\n"); else if (asc_ascq == 0x2689) DBG (DBG_sense, "-> Parameter value invalid - Illegal highlight/shadow setting\n"); else if (asc_ascq == 0x268a) DBG (DBG_sense, "-> Parameter value invalid - Illegal exposure time setting (analog brightness)\n"); else if (asc_ascq == 0x268b) DBG (DBG_sense, "-> Parameter value invalid - Invalid device select or device not exist\n"); else if (asc_ascq == 0x268c) DBG (DBG_sense, "-> Parameter value invalid - Illegal color packing\n"); else if (asc_ascq == 0x3d00) DBG (DBG_sense, "-> Invalid bits in identify field\n"); else if (asc_ascq == 0x4900) DBG (DBG_sense, "-> Invalid message\n"); else if (asc_ascq == 0x8101) DBG (DBG_sense, "-> Not enough memory for color packing\n"); if (len >= 0x11) { if (get_RS_SKSV (result) != 0) { if (get_RS_CD (result) == 0) { DBG (DBG_sense, "-> illegal parameter in CDB\n"); } else { DBG (DBG_sense, "-> illegal parameter is in the data parameters sent during data out phase\n"); } DBG (DBG_sense, "-> error detected in byte %d\n", get_RS_field_pointer (result)); } } return SANE_STATUS_IO_ERROR; break; case 0x06: /* unit attention */ if (asc_ascq == 0x2900) DBG (DBG_sense, "-> power on, reset or bus device reset\n"); if (asc_ascq == 0x8200) DBG (DBG_sense, "-> unit attention - calibration disable not granted\n"); if (asc_ascq == 0x8300) DBG (DBG_sense, "-> unit attention - calibration will be ignored\n"); else DBG (DBG_sense, "-> unit attention: asc=%d, ascq=%d\n", asc, ascq); break; case 0x09: /* vendor specific */ DBG (DBG_sense, "-> vendor specific sense-code: asc=%d, ascq=%d\n", asc, ascq); break; case 0x0b: if (asc_ascq == 0x0006) DBG (DBG_sense, "-> Received ABORT message from initiator\n"); if (asc_ascq == 0x4800) DBG (DBG_sense, "-> Initiator detected error message received\n"); if (asc_ascq == 0x4300) DBG (DBG_sense, "-> Message error\n"); if (asc_ascq == 0x4500) DBG (DBG_sense, "-> Select or re-select error\n"); else DBG (DBG_sense, "-> aborted command: asc=%d, ascq=%d\n", asc, ascq); break; } return SANE_STATUS_IO_ERROR; } /* -------------------------------- PIE PRINT INQUIRY ------------------------- */ static void pie_print_inquiry (Pie_Device * dev) { DBG (DBG_inquiry, "INQUIRY:\n"); DBG (DBG_inquiry, "========\n"); DBG (DBG_inquiry, "\n"); DBG (DBG_inquiry, "vendor........................: '%s'\n", dev->vendor); DBG (DBG_inquiry, "product.......................: '%s'\n", dev->product); DBG (DBG_inquiry, "version.......................: '%s'\n", dev->version); DBG (DBG_inquiry, "X resolution..................: %d dpi\n", dev->inquiry_x_res); DBG (DBG_inquiry, "Y resolution..................: %d dpi\n", dev->inquiry_y_res); DBG (DBG_inquiry, "pixel resolution..............: %d dpi\n", dev->inquiry_pixel_resolution); DBG (DBG_inquiry, "fb width......................: %f in\n", dev->inquiry_fb_width); DBG (DBG_inquiry, "fb length.....................: %f in\n", dev->inquiry_fb_length); DBG (DBG_inquiry, "transparency width............: %f in\n", dev->inquiry_trans_width); DBG (DBG_inquiry, "transparency length...........: %f in\n", dev->inquiry_trans_length); DBG (DBG_inquiry, "transparency offset...........: %d,%d\n", dev->inquiry_trans_top_left_x, dev->inquiry_trans_top_left_y); DBG (DBG_inquiry, "# of halftones................: %d\n", dev->inquiry_halftones); DBG (DBG_inquiry, "One pass color................: %s\n", dev->inquiry_filters & INQ_ONE_PASS_COLOR ? "yes" : "no"); DBG (DBG_inquiry, "Filters.......................: %s%s%s%s (%02x)\n", dev->inquiry_filters & INQ_FILTER_RED ? "Red " : "", dev->inquiry_filters & INQ_FILTER_GREEN ? "Green " : "", dev->inquiry_filters & INQ_FILTER_BLUE ? "Blue " : "", dev->inquiry_filters & INQ_FILTER_NEUTRAL ? "Neutral " : "", dev->inquiry_filters); DBG (DBG_inquiry, "Color depths..................: %s%s%s%s%s%s (%02x)\n", dev->inquiry_color_depths & INQ_COLOR_DEPTH_16 ? "16 bit " : "", dev->inquiry_color_depths & INQ_COLOR_DEPTH_12 ? "12 bit " : "", dev->inquiry_color_depths & INQ_COLOR_DEPTH_10 ? "10 bit " : "", dev->inquiry_color_depths & INQ_COLOR_DEPTH_8 ? "8 bit " : "", dev->inquiry_color_depths & INQ_COLOR_DEPTH_4 ? "4 bit " : "", dev->inquiry_color_depths & INQ_COLOR_DEPTH_1 ? "1 bit " : "", dev->inquiry_color_depths); DBG (DBG_inquiry, "Color Format..................: %s%s%s (%02x)\n", dev->inquiry_color_format & INQ_COLOR_FORMAT_INDEX ? "Indexed " : "", dev->inquiry_color_format & INQ_COLOR_FORMAT_LINE ? "Line " : "", dev->inquiry_color_format & INQ_COLOR_FORMAT_PIXEL ? "Pixel " : "", dev->inquiry_color_format); DBG (DBG_inquiry, "Image Format..................: %s%s%s%s (%02x)\n", dev->inquiry_image_format & INQ_IMG_FMT_OKLINE ? "OKLine " : "", dev->inquiry_image_format & INQ_IMG_FMT_BLK_ONE ? "BlackOne " : "", dev->inquiry_image_format & INQ_IMG_FMT_MOTOROLA ? "Motorola " : "", dev->inquiry_image_format & INQ_IMG_FMT_INTEL ? "Intel" : "", dev->inquiry_image_format); DBG (DBG_inquiry, "Scan Capability...............: %s%s%s%s%d speeds (%02x)\n", dev->inquiry_scan_capability & INQ_CAP_PWRSAV ? "PowerSave " : "", dev->inquiry_scan_capability & INQ_CAP_EXT_CAL ? "ExtCal " : "", dev->inquiry_scan_capability & INQ_CAP_FAST_PREVIEW ? "FastPreview" : "", dev->inquiry_scan_capability & INQ_CAP_DISABLE_CAL ? "DisCal " : "", dev->inquiry_scan_capability & INQ_CAP_SPEEDS, dev->inquiry_scan_capability); DBG (DBG_inquiry, "Optional Devices..............: %s%s%s%s (%02x)\n", dev->inquiry_optional_devices & INQ_OPT_DEV_MPCL ? "MultiPageLoad " : "", dev->inquiry_optional_devices & INQ_OPT_DEV_TP1 ? "TransModule1 " : "", dev->inquiry_optional_devices & INQ_OPT_DEV_TP ? "TransModule " : "", dev->inquiry_optional_devices & INQ_OPT_DEV_ADF ? "ADF " : "", dev->inquiry_optional_devices); DBG (DBG_inquiry, "Enhancement...................: %02x\n", dev->inquiry_enhancements); DBG (DBG_inquiry, "Gamma bits....................: %d\n", dev->inquiry_gamma_bits); DBG (DBG_inquiry, "Fast Preview Resolution.......: %d\n", dev->inquiry_fast_preview_res); DBG (DBG_inquiry, "Min Highlight.................: %d\n", dev->inquiry_min_highlight); DBG (DBG_inquiry, "Max Shadow....................: %d\n", dev->inquiry_max_shadow); DBG (DBG_inquiry, "Cal Eqn.......................: %d\n", dev->inquiry_cal_eqn); DBG (DBG_inquiry, "Min Exposure..................: %d\n", dev->inquiry_min_exp); DBG (DBG_inquiry, "Max Exposure..................: %d\n", dev->inquiry_max_exp); } /* ------------------------------ PIE GET INQUIRY VALUES -------------------- */ static void pie_get_inquiry_values (Pie_Device * dev, unsigned char *buffer) { DBG (DBG_proc, "get_inquiry_values\n"); dev->inquiry_len = get_inquiry_additional_length (buffer) + 5; get_inquiry_vendor ((char *) buffer, dev->vendor); dev->vendor[8] = '\0'; get_inquiry_product ((char *) buffer, dev->product); dev->product[16] = '\0'; get_inquiry_version ((char *) buffer, dev->version); dev->version[4] = '\0'; dev->inquiry_x_res = get_inquiry_max_x_res (buffer); dev->inquiry_y_res = get_inquiry_max_y_res (buffer); if (dev->inquiry_y_res < 256) { /* y res is a multiplier */ dev->inquiry_pixel_resolution = dev->inquiry_x_res; dev->inquiry_x_res *= dev->inquiry_y_res; dev->inquiry_y_res = dev->inquiry_x_res; } else { /* y res really is resolution */ dev->inquiry_pixel_resolution = min (dev->inquiry_x_res, dev->inquiry_y_res); } dev->inquiry_fb_width = (double) get_inquiry_fb_max_scan_width (buffer) / dev->inquiry_pixel_resolution; dev->inquiry_fb_length = (double) get_inquiry_fb_max_scan_length (buffer) / dev->inquiry_pixel_resolution; dev->inquiry_trans_top_left_x = get_inquiry_trans_x1 (buffer); dev->inquiry_trans_top_left_y = get_inquiry_trans_y1 (buffer); dev->inquiry_trans_width = (double) (get_inquiry_trans_x2 (buffer) - get_inquiry_trans_x1 (buffer)) / dev->inquiry_pixel_resolution; dev->inquiry_trans_length = (double) (get_inquiry_trans_y2 (buffer) - get_inquiry_trans_y1 (buffer)) / dev->inquiry_pixel_resolution; dev->inquiry_halftones = get_inquiry_halftones (buffer) & 0x0f; dev->inquiry_filters = get_inquiry_filters (buffer); dev->inquiry_color_depths = get_inquiry_color_depths (buffer); dev->inquiry_color_format = get_inquiry_color_format (buffer); dev->inquiry_image_format = get_inquiry_image_format (buffer); dev->inquiry_scan_capability = get_inquiry_scan_capability (buffer); dev->inquiry_optional_devices = get_inquiry_optional_devices (buffer); dev->inquiry_enhancements = get_inquiry_enhancements (buffer); dev->inquiry_gamma_bits = get_inquiry_gamma_bits (buffer); dev->inquiry_fast_preview_res = get_inquiry_fast_preview_res (buffer); dev->inquiry_min_highlight = get_inquiry_min_highlight (buffer); dev->inquiry_max_shadow = get_inquiry_max_shadow (buffer); dev->inquiry_cal_eqn = get_inquiry_cal_eqn (buffer); dev->inquiry_min_exp = get_inquiry_min_exp (buffer); dev->inquiry_max_exp = get_inquiry_max_exp (buffer); pie_print_inquiry (dev); return; } /* ----------------------------- PIE DO INQUIRY ---------------------------- */ static void pie_do_inquiry (int sfd, unsigned char *buffer) { size_t size; SANE_Status status; DBG (DBG_proc, "do_inquiry\n"); memset (buffer, '\0', 256); /* clear buffer */ size = 5; set_inquiry_return_size (inquiry.cmd, size); /* first get only 5 bytes to get size of inquiry_return_block */ status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size); if (status) { DBG (DBG_error, "pie_do_inquiry: command returned status %s\n", sane_strstatus (status)); } size = get_inquiry_additional_length (buffer) + 5; set_inquiry_return_size (inquiry.cmd, size); /* then get inquiry with actual size */ status = sanei_scsi_cmd (sfd, inquiry.cmd, inquiry.size, buffer, &size); if (status) { DBG (DBG_error, "pie_do_inquiry: command returned status %s\n", sane_strstatus (status)); } } /* ---------------------- PIE IDENTIFY SCANNER ---------------------- */ static int pie_identify_scanner (Pie_Device * dev, int sfd) { char vendor[9]; char product[0x11]; char version[5]; char *pp; int i = 0; unsigned char inquiry_block[256]; DBG (DBG_proc, "identify_scanner\n"); pie_do_inquiry (sfd, inquiry_block); /* get inquiry */ if (get_inquiry_periph_devtype (inquiry_block) != IN_periph_devtype_scanner) { return 1; } /* no scanner */ get_inquiry_vendor ((char *) inquiry_block, vendor); get_inquiry_product ((char *) inquiry_block, product); get_inquiry_version ((char *) inquiry_block, version); pp = &vendor[8]; vendor[8] = ' '; while (*pp == ' ') { *pp-- = '\0'; } pp = &product[0x10]; product[0x10] = ' '; while (*pp == ' ') { *pp-- = '\0'; } pp = &version[4]; version[4] = ' '; while (*pp == ' ') { *pp-- = '\0'; } DBG (DBG_info, "Found %s scanner %s version %s on device %s\n", vendor, product, version, dev->devicename); while (strncmp ("END_OF_LIST", scanner_str[2 * i], 11) != 0) /* Now identify full supported scanners */ { if (!strncmp (vendor, scanner_str[2 * i], strlen (scanner_str[2 * i]))) { if (!strncmp (product, scanner_str[2 * i + 1], strlen (scanner_str[2 * i + 1]))) { DBG (DBG_info, "found supported scanner\n"); pie_get_inquiry_values (dev, inquiry_block); return 0; } } i++; } return 1; /* NO SUPPORTED SCANNER: short inquiry-block and unknown scanner */ } /* ------------------------------- GET SPEEDS ----------------------------- */ static void pie_get_speeds (Pie_Device * dev) { int speeds = dev->inquiry_scan_capability & INQ_CAP_SPEEDS; DBG (DBG_proc, "get_speeds\n"); if (speeds == 3) { dev->speed_list[0] = strdup ("Normal"); dev->speed_list[1] = strdup ("Fine"); dev->speed_list[2] = strdup ("Pro"); dev->speed_list[3] = NULL; } else { int i; char buf[2]; buf[1] = '\0'; for (i = 0; i < speeds; i++) { buf[0] = '1' + i; dev->speed_list[i] = strdup (buf); } dev->speed_list[i] = NULL; } } /* ------------------------------- GET HALFTONES ----------------------------- */ static void pie_get_halftones (Pie_Device * dev, int sfd) { int i; size_t size; SANE_Status status; unsigned char *data; unsigned char buffer[128]; DBG (DBG_proc, "get_halftones\n"); for (i = 0; i < dev->inquiry_halftones; i++) { size = 6; set_write_length (swrite.cmd, size); memcpy (buffer, swrite.cmd, swrite.size); data = buffer + swrite.size; memset (data, 0, size); set_command (data, READ_HALFTONE); set_data_length (data, 2); data[4] = i; status = sanei_scsi_cmd (sfd, buffer, swrite.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_get_halftones: write command returned status %s\n", sane_strstatus (status)); } else { /* now read the halftone data */ memset (buffer, '\0', sizeof buffer); /* clear buffer */ size = 128; set_read_length (sread.cmd, size); DBG (DBG_info, "doing read\n"); status = sanei_scsi_cmd (sfd, sread.cmd, sread.size, buffer, &size); if (status) { DBG (DBG_error, "pie_get_halftones: read command returned status %s\n", sane_strstatus (status)); } else { unsigned char *s; s = buffer + 8 + buffer[6] * buffer[7]; DBG (DBG_info, "halftone %d: %s\n", i, s); dev->halftone_list[i] = strdup ((char *)s); } } } dev->halftone_list[i] = NULL; } /* ------------------------------- GET CAL DATA ----------------------------- */ static void pie_get_cal_info (Pie_Device * dev, int sfd) { size_t size; SANE_Status status; unsigned char *data; unsigned char buffer[280]; DBG (DBG_proc, "get_cal_info\n"); if (!(dev->inquiry_scan_capability & INQ_CAP_EXT_CAL)) return; size = 6; set_write_length (swrite.cmd, size); memcpy (buffer, swrite.cmd, swrite.size); data = buffer + swrite.size; memset (data, 0, size); set_command (data, READ_CAL_INFO); status = sanei_scsi_cmd (sfd, buffer, swrite.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_get_cal_info: write command returned status %s\n", sane_strstatus (status)); } else { /* now read the cal data */ memset (buffer, '\0', sizeof buffer); /* clear buffer */ size = 128; set_read_length (sread.cmd, size); DBG (DBG_info, "doing read\n"); status = sanei_scsi_cmd (sfd, sread.cmd, sread.size, buffer, &size); if (status) { DBG (DBG_error, "pie_get_cal_info: read command returned status %s\n", sane_strstatus (status)); } else { int i; dev->cal_info_count = buffer[4]; dev->cal_info = malloc (sizeof (struct Pie_cal_info) * dev->cal_info_count); for (i = 0; i < dev->cal_info_count; i++) { dev->cal_info[i].cal_type = buffer[8 + i * buffer[5]]; dev->cal_info[i].send_bits = buffer[9 + i * buffer[5]]; dev->cal_info[i].receive_bits = buffer[10 + i * buffer[5]]; dev->cal_info[i].num_lines = buffer[11 + i * buffer[5]]; dev->cal_info[i].pixels_per_line = (buffer[13 + i * buffer[5]] << 8) + buffer[12 + i * buffer[5]]; DBG (DBG_info2, "%02x %2d %2d %2d %d\n", dev->cal_info[i].cal_type, dev->cal_info[i].send_bits, dev->cal_info[i].receive_bits, dev->cal_info[i].num_lines, dev->cal_info[i].pixels_per_line); } } } } /* ------------------------------- ATTACH SCANNER ----------------------------- */ static SANE_Status attach_scanner (const char *devicename, Pie_Device ** devp) { Pie_Device *dev; int sfd; int bufsize; DBG (DBG_sane_proc, "attach_scanner: %s\n", devicename); for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { if (devp) { *devp = dev; } return SANE_STATUS_GOOD; } } dev = malloc (sizeof (*dev)); if (!dev) { return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_scanner: opening %s\n", devicename); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED bufsize = 16384; /* 16KB */ if (sanei_scsi_open_extended (devicename, &sfd, sense_handler, dev, &bufsize) != 0) { DBG (DBG_error, "attach_scanner: open failed\n"); free (dev); return SANE_STATUS_INVAL; } if (bufsize < 4096) /* < 4KB */ { DBG (DBG_error, "attach_scanner: sanei_scsi_open_extended returned too small scsi buffer (%d)\n", bufsize); sanei_scsi_close (sfd); free (dev); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "attach_scanner: sanei_scsi_open_extended returned scsi buffer size = %d\n", bufsize); #else bufsize = sanei_scsi_max_request_size; if (sanei_scsi_open (devicename, &sfd, sense_handler, dev) != 0) { DBG (DBG_error, "attach_scanner: open failed\n"); free (dev); return SANE_STATUS_INVAL; } #endif pie_init (dev); /* preset values in structure dev */ dev->devicename = strdup (devicename); if (pie_identify_scanner (dev, sfd) != 0) { DBG (DBG_error, "attach_scanner: scanner-identification failed\n"); sanei_scsi_close (sfd); free (dev); return SANE_STATUS_INVAL; } pie_get_halftones (dev, sfd); pie_get_cal_info (dev, sfd); pie_get_speeds (dev); dev->scan_mode_list[0] = COLOR_STR; dev->scan_mode_list[1] = GRAY_STR; dev->scan_mode_list[2] = LINEART_STR; dev->scan_mode_list[3] = HALFTONE_STR; dev->scan_mode_list[4] = 0; sanei_scsi_close (sfd); dev->sane.name = dev->devicename; dev->sane.vendor = dev->vendor; dev->sane.model = dev->product; dev->sane.type = "flatbed scanner"; dev->x_range.min = SANE_FIX (0); dev->x_range.quant = SANE_FIX (0); dev->x_range.max = SANE_FIX (dev->inquiry_fb_width * MM_PER_INCH); dev->y_range.min = SANE_FIX (0); dev->y_range.quant = SANE_FIX (0); dev->y_range.max = SANE_FIX (dev->inquiry_fb_length * MM_PER_INCH); dev->dpi_range.min = SANE_FIX (25); dev->dpi_range.quant = SANE_FIX (1); dev->dpi_range.max = SANE_FIX (max (dev->inquiry_x_res, dev->inquiry_y_res)); dev->shadow_range.min = SANE_FIX (0); dev->shadow_range.quant = SANE_FIX (1); dev->shadow_range.max = SANE_FIX (dev->inquiry_max_shadow); dev->highlight_range.min = SANE_FIX (dev->inquiry_min_highlight); dev->highlight_range.quant = SANE_FIX (1); dev->highlight_range.max = SANE_FIX (100); dev->exposure_range.min = SANE_FIX (dev->inquiry_min_exp); dev->exposure_range.quant = SANE_FIX (1); dev->exposure_range.max = SANE_FIX (dev->inquiry_max_exp); #if 0 dev->analog_gamma_range.min = SANE_FIX (1.0); dev->analog_gamma_range.quant = SANE_FIX (0.01); dev->analog_gamma_range.max = SANE_FIX (2.0); #endif dev->next = first_dev; first_dev = dev; if (devp) { *devp = dev; } return SANE_STATUS_GOOD; } /* --------------------------- MAX STRING SIZE ---------------------------- */ static size_t max_string_size (SANE_String_Const strings[]) { size_t size, max_size = 0; int i; for (i = 0; strings[i]; ++i) { size = strlen (strings[i]) + 1; if (size > max_size) { max_size = size; } } return max_size; } /* --------------------------- INIT OPTIONS ------------------------------- */ static SANE_Status init_options (Pie_Scanner * scanner) { int i; DBG (DBG_sane_proc, "init_options\n"); memset (scanner->opt, 0, sizeof (scanner->opt)); memset (scanner->val, 0, sizeof (scanner->val)); for (i = 0; i < NUM_OPTIONS; ++i) { scanner->opt[i].size = sizeof (SANE_Word); scanner->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; scanner->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ scanner->opt[OPT_MODE_GROUP].title = "Scan Mode"; scanner->opt[OPT_MODE_GROUP].desc = ""; scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_MODE_GROUP].cap = 0; scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; scanner->opt[OPT_MODE].type = SANE_TYPE_STRING; scanner->opt[OPT_MODE].size = max_string_size ((SANE_String_Const *) scanner->device->scan_mode_list); scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_MODE].constraint.string_list = (SANE_String_Const *) scanner->device->scan_mode_list; scanner->val[OPT_MODE].s = (SANE_Char *) strdup (scanner->device->scan_mode_list[0]); /* x-resolution */ scanner->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; scanner->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; scanner->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; scanner->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_RESOLUTION].constraint.range = &scanner->device->dpi_range; scanner->val[OPT_RESOLUTION].w = 100 << SANE_FIXED_SCALE_SHIFT; /* "Geometry" group: */ scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; scanner->opt[OPT_GEOMETRY_GROUP].desc = ""; scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_X].constraint.range = &(scanner->device->x_range); scanner->val[OPT_TL_X].w = 0; /* top-left y */ scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_TL_Y].constraint.range = &(scanner->device->y_range); scanner->val[OPT_TL_Y].w = 0; /* bottom-right x */ scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_X].constraint.range = &(scanner->device->x_range); scanner->val[OPT_BR_X].w = scanner->device->x_range.max; /* bottom-right y */ scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM; scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_BR_Y].constraint.range = &(scanner->device->y_range); scanner->val[OPT_BR_Y].w = scanner->device->y_range.max; /* "enhancement" group: */ scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; scanner->opt[OPT_ENHANCEMENT_GROUP].desc = ""; scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ENHANCEMENT_GROUP].cap = 0; scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* grayscale gamma vector */ scanner->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; scanner->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; scanner->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; scanner->val[OPT_GAMMA_VECTOR].wa = scanner->gamma_table[0]; scanner->opt[OPT_GAMMA_VECTOR].constraint.range = &scanner->gamma_range; scanner->opt[OPT_GAMMA_VECTOR].size = scanner->gamma_length * sizeof (SANE_Word); scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; /* red gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; scanner->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; scanner->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; scanner->val[OPT_GAMMA_VECTOR_R].wa = scanner->gamma_table[1]; scanner->opt[OPT_GAMMA_VECTOR_R].constraint.range = &(scanner->gamma_range); scanner->opt[OPT_GAMMA_VECTOR_R].size = scanner->gamma_length * sizeof (SANE_Word); /* green gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; scanner->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; scanner->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; scanner->val[OPT_GAMMA_VECTOR_G].wa = scanner->gamma_table[2]; scanner->opt[OPT_GAMMA_VECTOR_G].constraint.range = &(scanner->gamma_range); scanner->opt[OPT_GAMMA_VECTOR_G].size = scanner->gamma_length * sizeof (SANE_Word); /* blue gamma vector */ scanner->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; scanner->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; scanner->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; scanner->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; scanner->val[OPT_GAMMA_VECTOR_B].wa = scanner->gamma_table[3]; scanner->opt[OPT_GAMMA_VECTOR_B].constraint.range = &(scanner->gamma_range); scanner->opt[OPT_GAMMA_VECTOR_B].size = scanner->gamma_length * sizeof (SANE_Word); /* halftone pattern */ scanner->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN; scanner->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING; scanner->opt[OPT_HALFTONE_PATTERN].size = max_string_size ((SANE_String_Const *) scanner->device->halftone_list); scanner->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_HALFTONE_PATTERN].constraint.string_list = (SANE_String_Const *) scanner->device->halftone_list; scanner->val[OPT_HALFTONE_PATTERN].s = (SANE_Char *) strdup (scanner->device->halftone_list[0]); scanner->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; /* speed */ scanner->opt[OPT_SPEED].name = SANE_NAME_SCAN_SPEED; scanner->opt[OPT_SPEED].title = SANE_TITLE_SCAN_SPEED; scanner->opt[OPT_SPEED].desc = SANE_DESC_SCAN_SPEED; scanner->opt[OPT_SPEED].type = SANE_TYPE_STRING; scanner->opt[OPT_SPEED].size = max_string_size ((SANE_String_Const *) scanner->device->speed_list); scanner->opt[OPT_SPEED].constraint_type = SANE_CONSTRAINT_STRING_LIST; scanner->opt[OPT_SPEED].constraint.string_list = (SANE_String_Const *) scanner->device->speed_list; scanner->val[OPT_SPEED].s = (SANE_Char *) strdup (scanner->device->speed_list[0]); /* lineart threshold */ scanner->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; scanner->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; scanner->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; scanner->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; scanner->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; scanner->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; scanner->opt[OPT_THRESHOLD].constraint.range = &percentage_range_100; scanner->val[OPT_THRESHOLD].w = SANE_FIX (50); scanner->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* "advanced" group: */ scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced"; scanner->opt[OPT_ADVANCED_GROUP].desc = ""; scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP; scanner->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED; scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* preview */ scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; scanner->val[OPT_PREVIEW].w = SANE_FALSE; return SANE_STATUS_GOOD; } /*------------------------- PIE POWER SAVE -----------------------------*/ static SANE_Status pie_power_save (Pie_Scanner * scanner, int time) { unsigned char buffer[128]; size_t size; SANE_Status status; unsigned char *data; DBG (DBG_proc, "pie_power_save: %d min\n", time); size = 6; set_write_length (swrite.cmd, size); memcpy (buffer, swrite.cmd, swrite.size); data = buffer + swrite.size; memset (data, 0, size); set_command (data, SET_POWER_SAVE_CONTROL); set_data_length (data, size - 4); data[4] = time & 0x7f; status = sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_power_save: write command returned status %s\n", sane_strstatus (status)); } return status; } /*------------------------- PIE SEND EXPOSURE ONE -----------------------------*/ static SANE_Status pie_send_exposure_one (Pie_Scanner * scanner, int filter, int value) { unsigned char buffer[128]; size_t size; SANE_Status status; unsigned char *data; DBG (DBG_proc, "pie_send_exposure_one\n"); size = 8; set_write_length (swrite.cmd, size); memcpy (buffer, swrite.cmd, swrite.size); data = buffer + swrite.size; memset (data, 0, size); set_command (data, SET_EXP_TIME); set_data_length (data, size - 4); data[4] = filter; set_data (data, 6, (int) value, 2); status = sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_send_exposure_one: write command returned status %s\n", sane_strstatus (status)); } return status; } /*------------------------- PIE SEND EXPOSURE -----------------------------*/ static SANE_Status pie_send_exposure (Pie_Scanner * scanner) { SANE_Status status; DBG (DBG_proc, "pie_send_exposure\n"); status = pie_send_exposure_one (scanner, FILTER_RED, 100); if (status) return status; status = pie_send_exposure_one (scanner, FILTER_GREEN, 100); if (status) return status; status = pie_send_exposure_one (scanner, FILTER_BLUE, 100); if (status) return status; return SANE_STATUS_GOOD; } /*------------------------- PIE SEND HIGHLIGHT/SHADOW ONE -----------------------------*/ static SANE_Status pie_send_highlight_shadow_one (Pie_Scanner * scanner, int filter, int highlight, int shadow) { unsigned char buffer[128]; size_t size; SANE_Status status; unsigned char *data; DBG (DBG_proc, "pie_send_highlight_shadow_one\n"); size = 8; set_write_length (swrite.cmd, size); memcpy (buffer, swrite.cmd, swrite.size); data = buffer + swrite.size; memset (data, 0, size); set_command (data, SET_EXP_TIME); set_data_length (data, size - 4); data[4] = filter; data[6] = highlight; data[7] = shadow; status = sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_send_highlight_shadow_one: write command returned status %s\n", sane_strstatus (status)); } return status; } /*------------------------- PIE SEND HIGHLIGHT/SHADOW -----------------------------*/ static SANE_Status pie_send_highlight_shadow (Pie_Scanner * scanner) { SANE_Status status; DBG (DBG_proc, "pie_send_highlight_shadow\n"); status = pie_send_highlight_shadow_one (scanner, FILTER_RED, 100, 0); if (status) return status; status = pie_send_highlight_shadow_one (scanner, FILTER_GREEN, 100, 0); if (status) return status; status = pie_send_highlight_shadow_one (scanner, FILTER_BLUE, 100, 0); if (status) return status; return SANE_STATUS_GOOD; } /*------------------------- PIE PERFORM CAL ----------------------------*/ static SANE_Status pie_perform_cal (Pie_Scanner * scanner, int cal_index) { long *red_result; long *green_result; long *blue_result; long *neutral_result; long *result = NULL; int rcv_length, send_length; int rcv_lines, rcv_bits, send_bits; int pixels_per_line; int i; unsigned char *rcv_buffer, *rcv_ptr; unsigned char *send_buffer, *send_ptr; size_t size; int fullscale; int cal_limit; int k; int filter; SANE_Status status; DBG (DBG_proc, "pie_perform_cal\n"); pixels_per_line = scanner->device->cal_info[cal_index].pixels_per_line; rcv_length = pixels_per_line; send_length = pixels_per_line; rcv_bits = scanner->device->cal_info[cal_index].receive_bits; if (rcv_bits > 8) rcv_length *= 2; /* 2 bytes / sample */ send_bits = scanner->device->cal_info[cal_index].send_bits; if (send_bits > 8) send_length *= 2; /* 2 bytes / sample */ rcv_lines = scanner->device->cal_info[cal_index].num_lines; send_length += 2; /* space for filter at start */ if (scanner->colormode == RGB) { rcv_lines *= 3; send_length *= 3; rcv_length += 2; /* 2 bytes for index at front of data (only in RGB??) */ } send_length += 4; /* space for header at start of data */ /* alllocate buffers for the receive data, the result buffers, and for the send data */ rcv_buffer = (unsigned char *) malloc (rcv_length); red_result = (long *) calloc (pixels_per_line, sizeof (long)); green_result = (long *) calloc (pixels_per_line, sizeof (long)); blue_result = (long *) calloc (pixels_per_line, sizeof (long)); neutral_result = (long *) calloc (pixels_per_line, sizeof (long)); if (!rcv_buffer || !red_result || !green_result || !blue_result || !neutral_result) { /* at least one malloc failed, so free all buffers (free accepts NULL) */ free (rcv_buffer); free (red_result); free (green_result); free (blue_result); free (neutral_result); return SANE_STATUS_NO_MEM; } /* read the cal data a line at a time, and accumulate into the result arrays */ while (rcv_lines--) { /* TUR */ status = pie_wait_scanner (scanner); if (status) { free (rcv_buffer); free (red_result); free (green_result); free (blue_result); free (neutral_result); return status; } set_read_length (sread.cmd, 1); size = rcv_length; DBG (DBG_info, "pie_perform_cal: reading 1 line (%lu bytes)\n", (u_long) size); status = sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, rcv_buffer, &size); if (status) { DBG (DBG_error, "pie_perform_cal: read command returned status %s\n", sane_strstatus (status)); free (rcv_buffer); free (red_result); free (green_result); free (blue_result); free (neutral_result); return status; } DBG_DUMP (DBG_dump, rcv_buffer, 32); /* which result buffer does this line belong to? */ if (scanner->colormode == RGB) { if (*rcv_buffer == 'R') result = red_result; else if (*rcv_buffer == 'G') result = green_result; else if (*rcv_buffer == 'B') result = blue_result; else if (*rcv_buffer == 'N') result = neutral_result; else { DBG (DBG_error, "pie_perform_cal: invalid index byte (%02x)\n", *rcv_buffer); DBG_DUMP (DBG_error, rcv_buffer, 32); free (rcv_buffer); free (red_result); free (green_result); free (blue_result); free (neutral_result); return SANE_STATUS_INVAL; } rcv_ptr = rcv_buffer + 2; } else { /* monochrome - no bytes indicating filter here */ result = neutral_result; rcv_ptr = rcv_buffer; } /* now add the values in this line to the result array */ for (i = 0; i < pixels_per_line; i++) { result[i] += *rcv_ptr++; if (rcv_bits > 8) { result[i] += (*rcv_ptr++) << 8; } } } /* got all the cal data, now process it ready to send back */ free (rcv_buffer); send_buffer = (unsigned char *) malloc (send_length + swrite.size); if (!send_buffer) { free (red_result); free (green_result); free (blue_result); free (neutral_result); return SANE_STATUS_NO_MEM; } rcv_lines = scanner->device->cal_info[cal_index].num_lines; fullscale = (1 << rcv_bits) - 1; cal_limit = fullscale / (1 << scanner->device->inquiry_cal_eqn); k = (1 << scanner->device->inquiry_cal_eqn) - 1; /* set up scsi command and data */ size = send_length; memcpy (send_buffer, swrite.cmd, swrite.size); set_write_length (send_buffer, size); set_command (send_buffer + swrite.size, SEND_CAL_DATA); set_data_length (send_buffer + swrite.size, size - 4); send_ptr = send_buffer + swrite.size + 4; for (filter = FILTER_NEUTRAL; filter <= FILTER_BLUE; filter <<= 1) { /* only send data for filter we expect to send */ if (!(filter & scanner->cal_filter)) continue; set_data (send_ptr, 0, filter, 2); send_ptr += 2; if (scanner->colormode == RGB) { switch (filter) { case FILTER_RED: result = red_result; break; case FILTER_GREEN: result = green_result; break; case FILTER_BLUE: result = blue_result; break; case FILTER_NEUTRAL: result = neutral_result; break; } } else result = neutral_result; /* for each pixel */ for (i = 0; i < pixels_per_line; i++) { long x; /* make average */ x = result[i] / rcv_lines; /* ensure not overflowed */ if (x > fullscale) x = fullscale; /* process according to required calibration equation */ if (scanner->device->inquiry_cal_eqn) { if (x <= cal_limit) x = fullscale; else x = ((fullscale - x) * fullscale) / (x * k); } if (rcv_bits > send_bits) x >>= (rcv_bits - send_bits); else if (send_bits > rcv_bits) x <<= (send_bits - rcv_bits); /* put result into send buffer */ *send_ptr++ = x; if (send_bits > 8) *send_ptr++ = x >> 8; } } /* now send the data back to scanner */ /* TUR */ status = pie_wait_scanner (scanner); if (status) { free (red_result); free (green_result); free (blue_result); free (neutral_result); free (send_buffer); return status; } DBG (DBG_info, "pie_perform_cal: sending cal data (%lu bytes)\n", (u_long) size); DBG_DUMP (DBG_dump, send_buffer, 64); status = sanei_scsi_cmd (scanner->sfd, send_buffer, swrite.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_perform_cal: write command returned status %s\n", sane_strstatus (status)); free (red_result); free (green_result); free (blue_result); free (neutral_result); free (send_buffer); return status; } free (red_result); free (green_result); free (blue_result); free (neutral_result); free (send_buffer); return SANE_STATUS_GOOD; } /*------------------------- PIE DO CAL -----------------------------*/ static SANE_Status pie_do_cal (Pie_Scanner * scanner) { SANE_Status status; int cal_index; DBG (DBG_proc, "pie_do_cal\n"); if (scanner->device->inquiry_scan_capability & INQ_CAP_EXT_CAL) { for (cal_index = 0; cal_index < scanner->device->cal_info_count; cal_index++) if (scanner->device->cal_info[cal_index].cal_type == scanner->cal_mode) { status = pie_perform_cal (scanner, cal_index); if (status != SANE_STATUS_GOOD) return status; } } return SANE_STATUS_GOOD; } /*------------------------- PIE DWNLD GAMMA ONE -----------------------------*/ static SANE_Status pie_dwnld_gamma_one (Pie_Scanner * scanner, int filter, SANE_Int * table) { unsigned char *buffer; size_t size; SANE_Status status; unsigned char *data; int i; DBG (DBG_proc, "pie_dwnld_gamma_one\n"); /* TUR */ status = pie_wait_scanner (scanner); if (status) { return status; } if (scanner->device->inquiry_gamma_bits > 8) size = scanner->gamma_length * 2 + 6; else size = scanner->gamma_length + 6; buffer = malloc (size + swrite.size); if (!buffer) return SANE_STATUS_NO_MEM; set_write_length (swrite.cmd, size); memcpy (buffer, swrite.cmd, swrite.size); data = buffer + swrite.size; memset (data, 0, size); set_command (data, DWNLD_GAMMA_TABLE); set_data_length (data, size - 4); data[4] = filter; for (i = 0; i < scanner->gamma_length; i++) { if (scanner->device->inquiry_gamma_bits > 8) { set_data (data, 6 + 2 * i, table ? table[i] : i, 2); } else { set_data (data, 6 + i, table ? table[i] : i, 1); } } DBG_DUMP (DBG_dump, data, 128); status = sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_dwnld_gamma_one: write command returned status %s\n", sane_strstatus (status)); } free (buffer); return status; } /*------------------------- PIE DWNLD GAMMA -----------------------------*/ static SANE_Status pie_dwnld_gamma (Pie_Scanner * scanner) { SANE_Status status; DBG (DBG_proc, "pie_dwnld_gamma\n"); if (scanner->colormode == RGB) { status = pie_dwnld_gamma_one (scanner, FILTER_RED, scanner->gamma_table[1]); if (status) return status; status = pie_dwnld_gamma_one (scanner, FILTER_GREEN, scanner->gamma_table[2]); if (status) return status; status = pie_dwnld_gamma_one (scanner, FILTER_BLUE, scanner->gamma_table[3]); if (status) return status; } else { SANE_Int *table; /* if lineart or half tone, force gamma to be one to one by passing NULL */ if (scanner->colormode == GRAYSCALE) table = scanner->gamma_table[0]; else table = NULL; status = pie_dwnld_gamma_one (scanner, FILTER_GREEN, table); if (status) return status; } usleep (DOWNLOAD_GAMMA_WAIT_TIME); return SANE_STATUS_GOOD; } /*------------------------- PIE SET WINDOW -----------------------------*/ static SANE_Status pie_set_window (Pie_Scanner * scanner) { unsigned char buffer[128]; size_t size; SANE_Status status; unsigned char *data; double x, dpmm; DBG (DBG_proc, "pie_set_window\n"); size = 14; set_write_length (swrite.cmd, size); memcpy (buffer, swrite.cmd, swrite.size); data = buffer + swrite.size; memset (data, 0, size); set_command (data, SET_SCAN_FRAME); set_data_length (data, size - 4); data[4] = 0x80; if (scanner->colormode == HALFTONE) data[4] |= 0x40; dpmm = (double) scanner->device->inquiry_pixel_resolution / MM_PER_INCH; x = SANE_UNFIX (scanner->val[OPT_TL_X].w) * dpmm; set_data (data, 6, (int) x, 2); DBG (DBG_info, "TL_X: %d\n", (int) x); x = SANE_UNFIX (scanner->val[OPT_TL_Y].w) * dpmm; set_data (data, 8, (int) x, 2); DBG (DBG_info, "TL_Y: %d\n", (int) x); x = SANE_UNFIX (scanner->val[OPT_BR_X].w) * dpmm; set_data (data, 10, (int) x, 2); DBG (DBG_info, "BR_X: %d\n", (int) x); x = SANE_UNFIX (scanner->val[OPT_BR_Y].w) * dpmm; set_data (data, 12, (int) x, 2); DBG (DBG_info, "BR_Y: %d\n", (int) x); status = sanei_scsi_cmd (scanner->sfd, buffer, swrite.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_set_window: write command returned status %s\n", sane_strstatus (status)); } return status; } /*------------------------- PIE MODE SELECT -----------------------------*/ static SANE_Status pie_mode_select (Pie_Scanner * scanner) { SANE_Status status; unsigned char buffer[128]; size_t size; unsigned char *data; int i; DBG (DBG_proc, "pie_mode_select\n"); size = 14; set_mode_length (smode.cmd, size); memcpy (buffer, smode.cmd, smode.size); data = buffer + smode.size; memset (data, 0, size); /* size of data */ data[1] = size - 2; /* set resolution required */ set_data (data, 2, scanner->resolution, 2); /* set color filter and color depth */ switch (scanner->colormode) { case RGB: if (scanner->device->inquiry_filters & INQ_ONE_PASS_COLOR) { data[4] = INQ_ONE_PASS_COLOR; scanner->cal_filter = FILTER_RED | FILTER_GREEN | FILTER_BLUE; } else { DBG (DBG_error, "pie_mode_select: support for multipass color not yet implemented\n"); return SANE_STATUS_UNSUPPORTED; } data[5] = INQ_COLOR_DEPTH_8; break; case GRAYSCALE: case LINEART: case HALFTONE: /* choose which filter to use for monochrome mode */ if (scanner->device->inquiry_filters & INQ_FILTER_NEUTRAL) { data[4] = FILTER_NEUTRAL; scanner->cal_filter = FILTER_NEUTRAL; } else if (scanner->device->inquiry_filters & INQ_FILTER_GREEN) { data[4] = FILTER_GREEN; scanner->cal_filter = FILTER_GREEN; } else if (scanner->device->inquiry_filters & INQ_FILTER_RED) { data[4] = FILTER_RED; scanner->cal_filter = FILTER_RED; } else if (scanner->device->inquiry_filters & INQ_FILTER_BLUE) { data[4] = FILTER_BLUE; scanner->cal_filter = FILTER_BLUE; } else { DBG (DBG_error, "pie_mode_select: scanner doesn't appear to support monochrome\n"); return SANE_STATUS_UNSUPPORTED; } if (scanner->colormode == GRAYSCALE) data[5] = INQ_COLOR_DEPTH_8; else data[5] = INQ_COLOR_DEPTH_1; break; } /* choose color packing method */ if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_LINE) data[6] = INQ_COLOR_FORMAT_LINE; else if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_INDEX) data[6] = INQ_COLOR_FORMAT_INDEX; else { DBG (DBG_error, "pie_mode_select: support for pixel packing not yet implemented\n"); return SANE_STATUS_UNSUPPORTED; } /* choose data format */ if (scanner->device->inquiry_image_format & INQ_IMG_FMT_INTEL) data[8] = INQ_IMG_FMT_INTEL; else { DBG (DBG_error, "pie_mode_select: support for Motorola format not yet implemented\n"); return SANE_STATUS_UNSUPPORTED; } /* set required speed */ i = 0; while (scanner->device->speed_list[i] != NULL) { if (strcmp (scanner->device->speed_list[i], scanner->val[OPT_SPEED].s) == 0) break; i++; } if (scanner->device->speed_list[i] == NULL) data[9] = 0; else data[9] = i; scanner->cal_mode = CAL_MODE_FLATBED; /* if preview supported, ask for preview, limit resolution to max for fast preview */ if (scanner->val[OPT_PREVIEW].w && (scanner->device->inquiry_scan_capability & INQ_CAP_FAST_PREVIEW)) { DBG (DBG_info, "pie_mode_select: setting preview\n"); scanner->cal_mode |= CAL_MODE_PREVIEW; data[9] |= INQ_CAP_FAST_PREVIEW; data[9] &= ~INQ_CAP_SPEEDS; if (scanner->resolution > scanner->device->inquiry_fast_preview_res) set_data (data, 2, scanner->device->inquiry_fast_preview_res, 2); } /* set required halftone pattern */ i = 0; while (scanner->device->halftone_list[i] != NULL) { if (strcmp (scanner->device->halftone_list[i], scanner->val[OPT_HALFTONE_PATTERN].s) == 0) break; i++; } if (scanner->device->halftone_list[i] == NULL) data[12] = 0; /* halftone pattern */ else data[12] = i; data[13] = SANE_UNFIX (scanner->val[OPT_THRESHOLD].w) * 255 / 100; /* lineart threshold */ DBG (DBG_info, "pie_mode_select: speed %02x\n", data[9]); DBG (DBG_info, "pie_mode_select: halftone %d\n", data[12]); DBG (DBG_info, "pie_mode_select: threshold %02x\n", data[13]); status = sanei_scsi_cmd (scanner->sfd, buffer, smode.size + size, NULL, NULL); if (status) { DBG (DBG_error, "pie_mode_select: write command returned status %s\n", sane_strstatus (status)); } return status; } /*------------------------- PIE SCAN -----------------------------*/ static SANE_Status pie_scan (Pie_Scanner * scanner, int start) { SANE_Status status; DBG (DBG_proc, "pie_scan\n"); /* TUR */ status = pie_wait_scanner (scanner); if (status) { return status; } set_scan_cmd (scan.cmd, start); do { status = sanei_scsi_cmd (scanner->sfd, scan.cmd, scan.size, NULL, NULL); if (status) { DBG (DBG_error, "pie_scan: write command returned status %s\n", sane_strstatus (status)); usleep (SCAN_WARMUP_WAIT_TIME); } } while (start && status); usleep (SCAN_WAIT_TIME); return status; } /* --------------------------------------- PIE WAIT SCANNER -------------------------- */ static SANE_Status pie_wait_scanner (Pie_Scanner * scanner) { SANE_Status status; int cnt = 0; DBG (DBG_proc, "wait_scanner\n"); do { if (cnt > 100) /* maximal 100 * 0.5 sec = 50 sec */ { DBG (DBG_warning, "scanner does not get ready\n"); return -1; } /* test unit ready */ status = sanei_scsi_cmd (scanner->sfd, test_unit_ready.cmd, test_unit_ready.size, NULL, NULL); cnt++; if (status) { if (cnt == 1) { DBG (DBG_info2, "scanner reports %s, waiting ...\n", sane_strstatus (status)); } usleep (TUR_WAIT_TIME); } } while (status != SANE_STATUS_GOOD); DBG (DBG_info, "scanner ready\n"); return status; } /* -------------------------------------- PIE GET PARAMS -------------------------- */ static SANE_Status pie_get_params (Pie_Scanner * scanner) { SANE_Status status; size_t size; unsigned char buffer[128]; DBG (DBG_proc, "pie_get_params\n"); status = pie_wait_scanner (scanner); if (status) return status; if (scanner->device->inquiry_image_format & INQ_IMG_FMT_OKLINE) size = 16; else size = 14; set_param_length (param.cmd, size); status = sanei_scsi_cmd (scanner->sfd, param.cmd, param.size, buffer, &size); if (status) { DBG (DBG_error, "pie_get_params: command returned status %s\n", sane_strstatus (status)); } else { DBG (DBG_info, "Scan Width: %d\n", get_param_scan_width (buffer)); DBG (DBG_info, "Scan Lines: %d\n", get_param_scan_lines (buffer)); DBG (DBG_info, "Scan bytes: %d\n", get_param_scan_bytes (buffer)); DBG (DBG_info, "Offset 1: %d\n", get_param_scan_filter_offset1 (buffer)); DBG (DBG_info, "Offset 2: %d\n", get_param_scan_filter_offset2 (buffer)); DBG (DBG_info, "Scan period: %d\n", get_param_scan_period (buffer)); DBG (DBG_info, "Xfer rate: %d\n", get_param_scsi_xfer_rate (buffer)); if (scanner->device->inquiry_image_format & INQ_IMG_FMT_OKLINE) DBG (DBG_info, "Avail lines: %d\n", get_param_scan_available_lines (buffer)); scanner->filter_offset1 = get_param_scan_filter_offset1 (buffer); scanner->filter_offset2 = get_param_scan_filter_offset2 (buffer); scanner->bytes_per_line = get_param_scan_bytes (buffer); scanner->params.pixels_per_line = get_param_scan_width (buffer); scanner->params.lines = get_param_scan_lines (buffer); switch (scanner->colormode) { case RGB: scanner->params.format = SANE_FRAME_RGB; scanner->params.depth = 8; scanner->params.bytes_per_line = 3 * get_param_scan_bytes (buffer); break; case GRAYSCALE: scanner->params.format = SANE_FRAME_GRAY; scanner->params.depth = 8; scanner->params.bytes_per_line = get_param_scan_bytes (buffer); break; case HALFTONE: case LINEART: scanner->params.format = SANE_FRAME_GRAY; scanner->params.depth = 1; scanner->params.bytes_per_line = get_param_scan_bytes (buffer); break; } scanner->params.last_frame = 0; } return status; } /* -------------------------------------- PIE GRAB SCANNER -------------------------- */ static SANE_Status pie_grab_scanner (Pie_Scanner * scanner) { SANE_Status status; DBG (DBG_proc, "grab_scanner\n"); status = pie_wait_scanner (scanner); if (status) return status; status = sanei_scsi_cmd (scanner->sfd, reserve_unit.cmd, reserve_unit.size, NULL, NULL); if (status) { DBG (DBG_error, "pie_grab_scanner: command returned status %s\n", sane_strstatus (status)); } else { DBG (DBG_info, "scanner reserved\n"); } return status; } /* ------------------------------------ PIE GIVE SCANNER -------------------------- */ static SANE_Status pie_give_scanner (Pie_Scanner * scanner) { SANE_Status status; DBG (DBG_info2, "trying to release scanner ...\n"); status = sanei_scsi_cmd (scanner->sfd, release_unit.cmd, release_unit.size, NULL, NULL); if (status) { DBG (DBG_error, "pie_give_scanner: command returned status %s\n", sane_strstatus (status)); } else { DBG (DBG_info, "scanner released\n"); } return status; } /* ------------------- PIE READER PROCESS INDEXED ------------------- */ static int pie_reader_process_indexed (Pie_Scanner * scanner, FILE * fp) { int status; int lines; unsigned char *buffer, *reorder = NULL; unsigned char *red_buffer = NULL, *green_buffer = NULL; unsigned char *red_in = NULL, *red_out = NULL; unsigned char *green_in = NULL, *green_out = NULL; int red_size = 0, green_size = 0; int bytes_per_line; int red_count = 0, green_count = 0; size_t size; DBG (DBG_read, "reading %d lines of %d bytes/line (indexed)\n", scanner->params.lines, scanner->params.bytes_per_line); lines = scanner->params.lines; bytes_per_line = scanner->bytes_per_line; /* allocate receive buffer */ buffer = malloc (bytes_per_line + 2); if (!buffer) { return SANE_STATUS_NO_MEM; } /* allocate deskew buffers for RGB mode */ if (scanner->colormode == RGB) { lines *= 3; red_size = bytes_per_line * (scanner->filter_offset1 + scanner->filter_offset2 + 2); green_size = bytes_per_line * (scanner->filter_offset2 + 2); DBG (DBG_info2, "pie_reader_process_indexed: alloc %d lines (%d bytes) for red buffer\n", red_size / bytes_per_line, red_size); DBG (DBG_info2, "pie_reader_process_indexed: alloc %d lines (%d bytes) for green buffer\n", green_size / bytes_per_line, green_size); reorder = malloc (scanner->params.bytes_per_line); red_buffer = malloc (red_size); green_buffer = malloc (green_size); if (!reorder || !red_buffer || !green_buffer) { free (buffer); free (reorder); free (red_buffer); free (green_buffer); return SANE_STATUS_NO_MEM; } red_in = red_out = red_buffer; green_in = green_out = green_buffer; } while (lines--) { set_read_length (sread.cmd, 1); size = bytes_per_line + 2; do { status = sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, buffer, &size); } while (status); DBG_DUMP (DBG_dump, buffer, 64); if (scanner->colormode == RGB) { /* we're assuming that we get red before green before blue here */ switch (*buffer) { case 'R': /* copy to red buffer */ memcpy (red_in, buffer + 2, bytes_per_line); /* advance in pointer, and check for wrap */ red_in += bytes_per_line; if (red_in >= (red_buffer + red_size)) red_in = red_buffer; /* increment red line count */ red_count++; DBG (DBG_info2, "pie_reader_process_indexed: got a red line (%d)\n", red_count); break; case 'G': /* copy to green buffer */ memcpy (green_in, buffer + 2, bytes_per_line); /* advance in pointer, and check for wrap */ green_in += bytes_per_line; if (green_in >= (green_buffer + green_size)) green_in = green_buffer; /* increment green line count */ green_count++; DBG (DBG_info2, "pie_reader_process_indexed: got a green line (%d)\n", green_count); break; case 'B': /* check we actually have red and green data available */ if (!red_count || !green_count) { DBG (DBG_error, "pie_reader_process_indexed: deskew buffer empty (%d %d)\n", red_count, green_count); return SANE_STATUS_INVAL; } red_count--; green_count--; DBG (DBG_info2, "pie_reader_process_indexed: got a blue line\n"); { int i; unsigned char *red, *green, *blue, *dest; /* now pack the pixels lines into RGB format */ dest = reorder; red = red_out; green = green_out; blue = buffer + 2; for (i = bytes_per_line; i > 0; i--) { *dest++ = *red++; *dest++ = *green++; *dest++ = *blue++; } fwrite (reorder, 1, scanner->params.bytes_per_line, fp); /* advance out pointers, and check for wrap */ red_out += bytes_per_line; if (red_out >= (red_buffer + red_size)) red_out = red_buffer; green_out += bytes_per_line; if (green_out >= (green_buffer + green_size)) green_out = green_buffer; } break; default: DBG (DBG_error, "pie_reader_process_indexed: bad filter index\n"); } } else { DBG (DBG_info2, "pie_reader_process_indexed: got a line (%lu bytes)\n", (u_long) size); /* just send the data on, assume filter bytes not present as per calibration case */ fwrite (buffer, 1, scanner->params.bytes_per_line, fp); } } free (buffer); free (reorder); free (red_buffer); free (green_buffer); return 0; } /* --------------------------------- PIE READER PROCESS ------------------------ */ static int pie_reader_process (Pie_Scanner * scanner, FILE * fp) { int status; int lines; unsigned char *buffer, *reorder; size_t size; DBG (DBG_read, "reading %d lines of %d bytes/line\n", scanner->params.lines, scanner->params.bytes_per_line); buffer = malloc (scanner->params.bytes_per_line); reorder = malloc (scanner->params.bytes_per_line); if (!buffer || !reorder) { free (buffer); free (reorder); return SANE_STATUS_NO_MEM; } lines = scanner->params.lines; while (lines--) { set_read_length (sread.cmd, 1); size = scanner->params.bytes_per_line; do { status = sanei_scsi_cmd (scanner->sfd, sread.cmd, sread.size, buffer, &size); } while (status); DBG_DUMP (DBG_dump, buffer, 64); if (scanner->colormode == RGB) { int i; unsigned char *src, *dest; int offset; dest = reorder; src = buffer; offset = scanner->params.pixels_per_line; for (i = scanner->params.pixels_per_line; i > 0; i--) { *dest++ = *src; *dest++ = *(src + offset); *dest++ = *(src + 2 * offset); src++; } fwrite (reorder, 1, scanner->params.bytes_per_line, fp); } else { fwrite (buffer, 1, scanner->params.bytes_per_line, fp); } fflush (fp); } free (buffer); free (reorder); return 0; } /* --------------------------------- READER PROCESS SIGTERM HANDLER ------------ */ static void reader_process_sigterm_handler (int signal) { DBG (DBG_sane_info, "reader_process: terminated by signal %d\n", signal); #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED sanei_scsi_req_flush_all (); /* flush SCSI queue */ #else sanei_scsi_req_flush_all (); /* flush SCSI queue */ #endif _exit (SANE_STATUS_GOOD); } /* ------------------------------ READER PROCESS ----------------------------- */ static int reader_process ( void *data ) /* executed as a child process */ { int status; FILE *fp; Pie_Scanner * scanner; sigset_t ignore_set; struct SIGACTION act; scanner = (Pie_Scanner *)data; if (sanei_thread_is_forked ()) { close ( scanner->pipe ); sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); #if defined (__APPLE__) && defined (__MACH__) sigdelset (&ignore_set, SIGUSR2); #endif sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); } DBG (DBG_sane_proc, "reader_process started\n"); memset (&act, 0, sizeof (act)); /* define SIGTERM-handler */ act.sa_handler = reader_process_sigterm_handler; sigaction (SIGTERM, &act, 0); fp = fdopen (scanner->reader_fds, "w"); if (!fp) { return SANE_STATUS_IO_ERROR; } DBG (DBG_sane_info, "reader_process: starting to READ data\n"); if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_LINE) status = pie_reader_process (scanner, fp); else if (scanner->device->inquiry_color_format & INQ_COLOR_FORMAT_INDEX) status = pie_reader_process_indexed (scanner, fp); else status = SANE_STATUS_UNSUPPORTED; fclose (fp); DBG (DBG_sane_info, "reader_process: finished reading data\n"); return status; } /* -------------------------------- ATTACH_ONE ---------------------------------- */ /* callback function for sanei_config_attach_matching_devices(dev_name, attach_one) */ static SANE_Status attach_one (const char *name) { attach_scanner (name, 0); return SANE_STATUS_GOOD; } /* ----------------------------- CLOSE PIPE ---------------------------------- */ static SANE_Status close_pipe (Pie_Scanner * scanner) { DBG (DBG_sane_proc, "close_pipe\n"); if (scanner->pipe >= 0) { close (scanner->pipe); scanner->pipe = -1; } return SANE_STATUS_EOF; } /* ---------------------------- DO CANCEL ---------------------------------- */ static SANE_Status do_cancel (Pie_Scanner * scanner) { DBG (DBG_sane_proc, "do_cancel\n"); scanner->scanning = SANE_FALSE; if (sanei_thread_is_valid (scanner->reader_pid)) { DBG (DBG_sane_info, "killing reader_process\n"); sanei_thread_kill (scanner->reader_pid); sanei_thread_waitpid (scanner->reader_pid, 0); scanner->reader_pid = -1; DBG (DBG_sane_info, "reader_process killed\n"); } if (scanner->sfd >= 0) { pie_scan (scanner, 0); pie_power_save (scanner, 15); pie_give_scanner (scanner); /* reposition and release scanner */ DBG (DBG_sane_info, "closing scannerdevice filedescriptor\n"); sanei_scsi_close (scanner->sfd); scanner->sfd = -1; } return SANE_STATUS_CANCELLED; } /* --------------------------------------- SANE INIT ---------------------------------- */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback __sane_unused__ authorize) { char dev_name[PATH_MAX]; size_t len; FILE *fp; DBG_INIT (); DBG (DBG_sane_init, "sane_init() build %d\n", BUILD); if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, BUILD); fp = sanei_config_open (PIE_CONFIG_FILE); if (!fp) { attach_scanner ("/dev/scanner", 0); /* no config-file: /dev/scanner */ return SANE_STATUS_GOOD; } while (sanei_config_read (dev_name, sizeof (dev_name), fp)) { if (dev_name[0] == '#') { continue; } /* ignore line comments */ len = strlen (dev_name); if (!len) /* ignore empty lines */ { continue; } sanei_config_attach_matching_devices (dev_name, attach_one); } fclose (fp); return SANE_STATUS_GOOD; } /* ----------------------------------------- SANE EXIT ---------------------------------- */ void sane_exit (void) { Pie_Device *dev, *next; int i; DBG (DBG_sane_init, "sane_exit()\n"); for (dev = first_dev; dev; dev = next) { next = dev->next; free (dev->devicename); free (dev->cal_info); i = 0; while (dev->halftone_list[i] != NULL) free (dev->halftone_list[i++]); i = 0; while (dev->speed_list[i] != NULL) free (dev->speed_list[i++]); free (dev); } first_dev = NULL; if (devlist) { free (devlist); devlist = NULL; } } /* ------------------------------------------ SANE GET DEVICES --------------------------- */ SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool __sane_unused__ local_only) { Pie_Device *dev; int i; DBG (DBG_sane_init, "sane_get_devices\n"); i = 0; for (dev = first_dev; dev; dev = dev->next) i++; if (devlist) { free (devlist); } devlist = malloc ((i + 1) * sizeof (devlist[0])); if (!devlist) { return SANE_STATUS_NO_MEM; } i = 0; for (dev = first_dev; dev; dev = dev->next) { devlist[i++] = &dev->sane; } devlist[i] = NULL; *device_list = devlist; return SANE_STATUS_GOOD; } /* --------------------------------------- SANE OPEN ---------------------------------- */ SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { Pie_Device *dev; SANE_Status status; Pie_Scanner *scanner; int i, j; DBG (DBG_sane_init, "sane_open(%s)\n", devicename); if (devicename[0]) /* search for devicename */ { for (dev = first_dev; dev; dev = dev->next) { if (strcmp (dev->sane.name, devicename) == 0) { break; } } if (!dev) { status = attach_scanner (devicename, &dev); if (status != SANE_STATUS_GOOD) { return status; } } } else { dev = first_dev; /* empty devicename -> use first device */ } if (!dev) { return SANE_STATUS_INVAL; } scanner = malloc (sizeof (*scanner)); if (!scanner) { return SANE_STATUS_NO_MEM; } memset (scanner, 0, sizeof (*scanner)); scanner->device = dev; scanner->sfd = -1; scanner->pipe = -1; scanner->gamma_length = 1 << (scanner->device->inquiry_gamma_bits); DBG (DBG_sane_info, "Using %d bits for gamma input\n", scanner->device->inquiry_gamma_bits); scanner->gamma_range.min = 0; scanner->gamma_range.max = scanner->gamma_length - 1; scanner->gamma_range.quant = 0; scanner->gamma_table[0] = (SANE_Int *) malloc (scanner->gamma_length * sizeof (SANE_Int)); scanner->gamma_table[1] = (SANE_Int *) malloc (scanner->gamma_length * sizeof (SANE_Int)); scanner->gamma_table[2] = (SANE_Int *) malloc (scanner->gamma_length * sizeof (SANE_Int)); scanner->gamma_table[3] = (SANE_Int *) malloc (scanner->gamma_length * sizeof (SANE_Int)); for (i = 0; i < 4; ++i) /* gamma_table[0,1,2,3] */ { for (j = 0; j < scanner->gamma_length; ++j) { scanner->gamma_table[i][j] = j; } } init_options (scanner); scanner->next = first_handle; /* insert newly opened handle into list of open handles: */ first_handle = scanner; *handle = scanner; return SANE_STATUS_GOOD; } /* ------------------------------------ SANE CLOSE --------------------------------- */ void sane_close (SANE_Handle handle) { Pie_Scanner *prev, *scanner; DBG (DBG_sane_init, "sane_close\n"); /* remove handle from list of open handles: */ prev = 0; for (scanner = first_handle; scanner; scanner = scanner->next) { if (scanner == handle) { break; } prev = scanner; } if (!scanner) { DBG (DBG_error, "close: invalid handle %p\n", handle); return; /* oops, not a handle we know about */ } if (scanner->scanning) /* stop scan if still scanning */ { do_cancel (handle); } if (prev) { prev->next = scanner->next; } else { first_handle = scanner->next; } free (scanner->gamma_table[0]); /* free custom gamma tables */ free (scanner->gamma_table[1]); free (scanner->gamma_table[2]); free (scanner->gamma_table[3]); free (scanner->val[OPT_MODE].s); free (scanner->val[OPT_SPEED].s); free (scanner->val[OPT_HALFTONE_PATTERN].s); scanner->bufsize = 0; free (scanner); /* free scanner */ } /* ---------------------------------- SANE GET OPTION DESCRIPTOR ----------------- */ const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Pie_Scanner *scanner = handle; DBG (DBG_sane_option, "sane_get_option_descriptor %d\n", option); if ((unsigned) option >= NUM_OPTIONS) { return 0; } return scanner->opt + option; } /* ---------------------------------- SANE CONTROL OPTION ------------------------ */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Pie_Scanner *scanner = handle; SANE_Status status; SANE_Word cap; SANE_String_Const name; if (info) { *info = 0; } if (scanner->scanning) { return SANE_STATUS_DEVICE_BUSY; } if ((unsigned) option >= NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = scanner->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } name = scanner->opt[option].name; if (!name) { name = "(no name)"; } if (action == SANE_ACTION_GET_VALUE) { DBG (DBG_sane_option, "get %s [#%d]\n", name, option); switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_PREVIEW: case OPT_THRESHOLD: *(SANE_Word *) val = scanner->val[option].w; return SANE_STATUS_GOOD; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, scanner->val[option].wa, scanner->opt[option].size); return SANE_STATUS_GOOD; #if 0 /* string options: */ case OPT_SOURCE: #endif case OPT_MODE: case OPT_HALFTONE_PATTERN: case OPT_SPEED: strcpy (val, scanner->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { switch (scanner->opt[option].type) { case SANE_TYPE_INT: DBG (DBG_sane_option, "set %s [#%d] to %d\n", name, option, *(SANE_Word *) val); break; case SANE_TYPE_FIXED: DBG (DBG_sane_option, "set %s [#%d] to %f\n", name, option, SANE_UNFIX (*(SANE_Word *) val)); break; case SANE_TYPE_STRING: DBG (DBG_sane_option, "set %s [#%d] to %s\n", name, option, (char *) val); break; case SANE_TYPE_BOOL: DBG (DBG_sane_option, "set %s [#%d] to %d\n", name, option, *(SANE_Word *) val); break; default: DBG (DBG_sane_option, "set %s [#%d]\n", name, option); } if (!SANE_OPTION_IS_SETTABLE (cap)) { return SANE_STATUS_INVAL; } status = sanei_constrain_value (scanner->opt + option, val, info); if (status != SANE_STATUS_GOOD) { return status; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } /* fall through */ case OPT_NUM_OPTS: case OPT_PREVIEW: case OPT_THRESHOLD: scanner->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (scanner->val[option].wa, val, scanner->opt[option].size); return SANE_STATUS_GOOD; /* options with side-effects: */ case OPT_MODE: { int halftoning; if (scanner->val[option].s) { free (scanner->val[option].s); } scanner->val[option].s = (SANE_Char *) strdup (val); if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } scanner->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; scanner->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; halftoning = (strcmp (val, HALFTONE_STR) == 0); if (halftoning || strcmp (val, LINEART_STR) == 0) { /* one bit modes */ if (halftoning) { /* halftoning modes */ scanner->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } else { /* lineart modes */ } scanner->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { /* multi-bit modes(gray or color) */ } if ((strcmp (val, LINEART_STR) == 0) || (strcmp (val, HALFTONE_STR) == 0) || (strcmp (val, GRAY_STR) == 0)) { scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (val, COLOR_STR) == 0) { /* scanner->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; */ scanner->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; scanner->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } return SANE_STATUS_GOOD; } case OPT_SPEED: case OPT_HALFTONE_PATTERN: { if (scanner->val[option].s) { free (scanner->val[option].s); } scanner->val[option].s = (SANE_Char *) strdup (val); return SANE_STATUS_GOOD; } } } /* else */ return SANE_STATUS_INVAL; } /* ------------------------------------ SANE GET PARAMETERS ------------------------ */ SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Pie_Scanner *scanner = handle; const char *mode; DBG (DBG_sane_info, "sane_get_parameters\n"); if (!scanner->scanning) { /* not scanning, so lets use recent values */ double width, length, x_dpi, y_dpi; memset (&scanner->params, 0, sizeof (scanner->params)); width = SANE_UNFIX (scanner->val[OPT_BR_X].w - scanner->val[OPT_TL_X].w); length = SANE_UNFIX (scanner->val[OPT_BR_Y].w - scanner->val[OPT_TL_Y].w); x_dpi = SANE_UNFIX (scanner->val[OPT_RESOLUTION].w); y_dpi = x_dpi; #if 0 if ((scanner->val[OPT_RESOLUTION_BIND].w == SANE_TRUE) || (scanner->val[OPT_PREVIEW].w == SANE_TRUE)) { y_dpi = x_dpi; } #endif if (x_dpi > 0.0 && y_dpi > 0.0 && width > 0.0 && length > 0.0) { double x_dots_per_mm = x_dpi / MM_PER_INCH; double y_dots_per_mm = y_dpi / MM_PER_INCH; scanner->params.pixels_per_line = width * x_dots_per_mm; scanner->params.lines = length * y_dots_per_mm; } } mode = scanner->val[OPT_MODE].s; if (strcmp (mode, LINEART_STR) == 0 || strcmp (mode, HALFTONE_STR) == 0) { scanner->params.format = SANE_FRAME_GRAY; scanner->params.bytes_per_line = (scanner->params.pixels_per_line + 7) / 8; scanner->params.depth = 1; } else if (strcmp (mode, GRAY_STR) == 0) { scanner->params.format = SANE_FRAME_GRAY; scanner->params.bytes_per_line = scanner->params.pixels_per_line; scanner->params.depth = 8; } else /* RGB */ { scanner->params.format = SANE_FRAME_RGB; scanner->params.bytes_per_line = 3 * scanner->params.pixels_per_line; scanner->params.depth = 8; } scanner->params.last_frame = (scanner->params.format != SANE_FRAME_RED && scanner->params.format != SANE_FRAME_GREEN); if (params) { *params = scanner->params; } return SANE_STATUS_GOOD; } /* ----------------------------------------- SANE START --------------------------------- */ SANE_Status sane_start (SANE_Handle handle) { Pie_Scanner *scanner = handle; int fds[2]; const char *mode; int status; DBG (DBG_sane_init, "sane_start\n"); /* Check for inconsistencies */ if (scanner->val[OPT_TL_X].w > scanner->val[OPT_BR_X].w) { DBG (0, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) " "-- aborting\n", scanner->opt[OPT_TL_X].title, SANE_UNFIX (scanner->val[OPT_TL_X].w), scanner->opt[OPT_BR_X].title, SANE_UNFIX (scanner->val[OPT_BR_X].w)); return SANE_STATUS_INVAL; } if (scanner->val[OPT_TL_Y].w > scanner->val[OPT_BR_Y].w) { DBG (0, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) " "-- aborting\n", scanner->opt[OPT_TL_Y].title, SANE_UNFIX (scanner->val[OPT_TL_Y].w), scanner->opt[OPT_BR_Y].title, SANE_UNFIX (scanner->val[OPT_BR_Y].w)); return SANE_STATUS_INVAL; } mode = scanner->val[OPT_MODE].s; if (scanner->sfd < 0) /* first call, don`t run this routine again on multi frame or multi image scan */ { #ifdef HAVE_SANEI_SCSI_OPEN_EXTENDED int scsi_bufsize = 131072; /* 128KB */ if (sanei_scsi_open_extended (scanner->device->sane.name, &(scanner->sfd), sense_handler, scanner->device, &scsi_bufsize) != 0) { DBG (DBG_error, "sane_start: open failed\n"); return SANE_STATUS_INVAL; } if (scsi_bufsize < 32768) /* < 32KB */ { DBG (DBG_error, "sane_start: sanei_scsi_open_extended returned too small scsi buffer (%d)\n", scsi_bufsize); sanei_scsi_close ((scanner->sfd)); return SANE_STATUS_NO_MEM; } DBG (DBG_info, "sane_start: sanei_scsi_open_extended returned scsi buffer size = %d\n", scsi_bufsize); scanner->bufsize = scsi_bufsize; #else if (sanei_scsi_open (scanner->device->sane.name, &(scanner->sfd), sense_handler, scanner->device) != SANE_STATUS_GOOD) { DBG (DBG_error, "sane_start: open of %s failed:\n", scanner->device->sane.name); return SANE_STATUS_INVAL; } /* there is no need to reallocate the buffer because the size is fixed */ #endif #if 0 if (pie_check_values (scanner->device) != 0) { DBG (DBG_error, "ERROR: invalid scan-values\n"); scanner->scanning = SANE_FALSE; pie_give_scanner (scanner); /* reposition and release scanner */ sanei_scsi_close (scanner->sfd); scanner->sfd = -1; return SANE_STATUS_INVAL; } #endif #if 0 scanner->params.bytes_per_line = scanner->device->row_len; scanner->params.pixels_per_line = scanner->device->width_in_pixels; scanner->params.lines = scanner->device->length_in_pixels; sane_get_parameters (scanner, 0); DBG (DBG_sane_info, "x_resolution (dpi) = %u\n", scanner->device->x_resolution); DBG (DBG_sane_info, "y_resolution (dpi) = %u\n", scanner->device->y_resolution); DBG (DBG_sane_info, "x_coordinate_base (dpi) = %u\n", scanner->device->x_coordinate_base); DBG (DBG_sane_info, "y_coordinate_base (dpi) = %u\n", scanner->device->y_coordinate_base); DBG (DBG_sane_info, "upper_left_x (xbase) = %d\n", scanner->device->upper_left_x); DBG (DBG_sane_info, "upper_left_y (ybase) = %d\n", scanner->device->upper_left_y); DBG (DBG_sane_info, "scanwidth (xbase) = %u\n", scanner->device->scanwidth); DBG (DBG_sane_info, "scanlength (ybase) = %u\n", scanner->device->scanlength); DBG (DBG_sane_info, "width in pixels = %u\n", scanner->device->width_in_pixels); DBG (DBG_sane_info, "length in pixels = %u\n", scanner->device->length_in_pixels); DBG (DBG_sane_info, "bits per pixel/color = %u\n", scanner->device->bits_per_pixel); DBG (DBG_sane_info, "bytes per line = %d\n", scanner->params.bytes_per_line); DBG (DBG_sane_info, "pixels_per_line = %d\n", scanner->params.pixels_per_line); DBG (DBG_sane_info, "lines = %d\n", scanner->params.lines); #endif /* grab scanner */ if (pie_grab_scanner (scanner)) { sanei_scsi_close (scanner->sfd); scanner->sfd = -1; DBG (DBG_warning, "WARNING: unable to reserve scanner: device busy\n"); return SANE_STATUS_DEVICE_BUSY; } scanner->scanning = SANE_TRUE; pie_power_save (scanner, 0); } /* ------------ end of first call -------------- */ if (strcmp (mode, LINEART_STR) == 0) { scanner->colormode = LINEART; } else if (strcmp (mode, HALFTONE_STR) == 0) { scanner->colormode = HALFTONE; } else if (strcmp (mode, GRAY_STR) == 0) { scanner->colormode = GRAYSCALE; } else if (strcmp (mode, COLOR_STR) == 0) { scanner->colormode = RGB; } /* get and set geometric values for scanning */ scanner->resolution = SANE_UNFIX (scanner->val[OPT_RESOLUTION].w); pie_set_window (scanner); pie_send_exposure (scanner); pie_mode_select (scanner); pie_send_highlight_shadow (scanner); pie_scan (scanner, 1); status = pie_do_cal (scanner); if (status) return status; /* send gammacurves */ pie_dwnld_gamma (scanner); pie_get_params (scanner); if (pipe (fds) < 0) /* create a pipe, fds[0]=read-fd, fds[1]=write-fd */ { DBG (DBG_error, "ERROR: could not create pipe\n"); scanner->scanning = SANE_FALSE; pie_scan (scanner, 0); pie_give_scanner (scanner); /* reposition and release scanner */ sanei_scsi_close (scanner->sfd); scanner->sfd = -1; return SANE_STATUS_IO_ERROR; } scanner->pipe = fds[0]; scanner->reader_fds = fds[1]; scanner->reader_pid = sanei_thread_begin( reader_process, (void*)scanner ); if (!sanei_thread_is_valid (scanner->reader_pid)) { DBG (1, "sane_start: sanei_thread_begin failed (%s)\n", strerror (errno)); return SANE_STATUS_NO_MEM; } if (sanei_thread_is_forked ()) { close (scanner->reader_fds); scanner->reader_fds = -1; } return SANE_STATUS_GOOD; } /* -------------------------------------- SANE READ ---------------------------------- */ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len) { Pie_Scanner *scanner = handle; ssize_t nread; *len = 0; nread = read (scanner->pipe, buf, max_len); DBG (DBG_sane_info, "sane_read: read %ld bytes\n", (long) nread); if (!(scanner->scanning)) /* OOPS, not scanning */ { return do_cancel (scanner); } if (nread < 0) { if (errno == EAGAIN) { DBG (DBG_sane_info, "sane_read: EAGAIN\n"); return SANE_STATUS_GOOD; } else { do_cancel (scanner); /* we had an error, stop scanner */ return SANE_STATUS_IO_ERROR; } } *len = nread; if (nread == 0) /* EOF */ { do_cancel (scanner); return close_pipe (scanner); /* close pipe */ } return SANE_STATUS_GOOD; } /* ------------------------------------- SANE CANCEL -------------------------------- */ void sane_cancel (SANE_Handle handle) { Pie_Scanner *scanner = handle; DBG (DBG_sane_init, "sane_cancel\n"); if (scanner->scanning) { do_cancel (scanner); } } /* -------------------------------------- SANE SET IO MODE --------------------------- */ SANE_Status sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { Pie_Scanner *scanner = handle; DBG (DBG_sane_init, "sane_set_io_mode: non_blocking=%d\n", non_blocking); if (!scanner->scanning) { return SANE_STATUS_INVAL; } if (fcntl (scanner->pipe, F_SETFL, non_blocking ? O_NONBLOCK : 0) < 0) { return SANE_STATUS_IO_ERROR; } return SANE_STATUS_GOOD; } /* --------------------------------------- SANE GET SELECT FD ------------------------- */ SANE_Status sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { Pie_Scanner *scanner = handle; DBG (DBG_sane_init, "sane_get_select_fd\n"); if (!scanner->scanning) { return SANE_STATUS_INVAL; } *fd = scanner->pipe; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/gt68xx_gt6816.c0000664000175000017500000001447512112021330015140 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2002 Sergey Vlasov Copyright (C) 2002-2007 Henning Geinitz This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /** @file * @brief Implementation of the gt6816 specific functions. */ #include "gt68xx_gt6816.h" SANE_Status gt6816_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x70; req[1] = 0x01; status = gt68xx_device_small_req (dev, req, req); if (status != SANE_STATUS_GOOD) { /* Assume that firmware is not loaded because without firmware, we need 64 bytes for the result, not 8 */ *loaded = SANE_FALSE; return SANE_STATUS_GOOD; } /* check anyway */ if (req[0] == 0x00 && req[1] == 0x70 && req[2] == 0xff) *loaded = SANE_TRUE; else *loaded = SANE_FALSE; return SANE_STATUS_GOOD; } #define MAX_DOWNLOAD_BLOCK_SIZE 64 SANE_Status gt6816_download_firmware (GT68xx_Device * dev, SANE_Byte * data, SANE_Word size) { SANE_Status status; SANE_Byte download_buf[MAX_DOWNLOAD_BLOCK_SIZE]; SANE_Byte check_buf[MAX_DOWNLOAD_BLOCK_SIZE]; SANE_Byte *block; SANE_Word addr, bytes_left; GT68xx_Packet boot_req; SANE_Word block_size = MAX_DOWNLOAD_BLOCK_SIZE; CHECK_DEV_ACTIVE (dev, "gt6816_download_firmware"); for (addr = 0; addr < size; addr += block_size) { bytes_left = size - addr; if (bytes_left > block_size) block = data + addr; else { memset (download_buf, 0, block_size); memcpy (download_buf, data + addr, bytes_left); block = download_buf; } RIE (gt68xx_device_memory_write (dev, addr, block_size, block)); RIE (gt68xx_device_memory_read (dev, addr, block_size, check_buf)); if (memcmp (block, check_buf, block_size) != 0) { DBG (3, "gt6816_download_firmware: mismatch at block 0x%0x\n", addr); return SANE_STATUS_IO_ERROR; } } memset (boot_req, 0, sizeof (boot_req)); boot_req[0] = 0x69; boot_req[1] = 0x01; boot_req[2] = LOBYTE (addr); boot_req[3] = HIBYTE (addr); RIE (gt68xx_device_req (dev, boot_req, boot_req)); return SANE_STATUS_GOOD; } SANE_Status gt6816_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x3f; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); if ((req[0] == 0x00 && req[1] == 0x3f && req[2] == 0x01) || (dev->model->flags & GT68XX_FLAG_NO_POWER_STATUS)) *power_ok = SANE_TRUE; else *power_ok = SANE_FALSE; return SANE_STATUS_GOOD; } SANE_Status gt6816_get_ta_status (GT68xx_Device * dev, SANE_Bool * ta_attached) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x28; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); if (req[0] == 0x00 && req[1] == 0x28 && (req[8] & 0x01) != 0 && !dev->model->is_cis) *ta_attached = SANE_TRUE; else *ta_attached = SANE_FALSE; return SANE_STATUS_GOOD; } SANE_Status gt6816_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp, SANE_Bool ta_lamp) { GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x25; req[1] = 0x01; req[2] = 0; if (fb_lamp) req[2] |= 0x01; if (ta_lamp) req[2] |= 0x02; return gt68xx_device_req (dev, req, req); } SANE_Status gt6816_is_moving (GT68xx_Device * dev, SANE_Bool * moving) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x17; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); if (req[0] == 0x00 && req[1] == 0x17) { if (req[2] == 0 && (req[3] == 0 || req[3] == 2)) *moving = SANE_FALSE; else *moving = SANE_TRUE; } else return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } SANE_Status gt6816_carriage_home (GT68xx_Device * dev) { GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x24; req[1] = 0x01; return gt68xx_device_req (dev, req, req); } SANE_Status gt6816_stop_scan (GT68xx_Device * dev) { GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x41; req[1] = 0x01; return gt68xx_device_small_req (dev, req, req); } SANE_Status gt6816_document_present (GT68xx_Device * dev, SANE_Bool * present) { SANE_Status status; GT68xx_Packet req; memset (req, 0, sizeof (req)); req[0] = 0x59; req[1] = 0x01; RIE (gt68xx_device_req (dev, req, req)); if (req[0] == 0x00 && req[1] == 0x59) { if (req[2] == 0) *present = SANE_FALSE; else *present = SANE_TRUE; } else return SANE_STATUS_IO_ERROR; return SANE_STATUS_GOOD; } sane-backends-1.0.27/backend/sm3600-scantool.h0000664000175000017500000000745712112021330015530 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) Marian Eichholz 2001 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ #ifndef SCANTOOL_H #define SCANTOOL_H /* ====================================================================== common declarations and definitions. (C) Marian Eichholz 2001 ====================================================================== */ #include #include #include #include #include #include #include #include #include #include #ifdef INSANE_VERSION /* make real exports */ #define __SM3600EXPORT__ typedef enum { SANE_STATUS_GOOD, SANE_STATUS_CANCELLED, SANE_STATUS_UNSUPPORTED, SANE_STATUS_EOF, SANE_STATUS_NO_MEM, SANE_STATUS_IO_ERROR, SANE_STATUS_ACCESS_DENIED, SANE_STATUS_INVAL, SANE_STATUS_DEVICE_BUSY, } SANE_Status; typedef int SANE_Int; #endif #include "sm3600.h" extern char *achErrorMessages[]; #ifdef INSANE_VERSION void DBG(int nLevel, const char *szFormat, ...); /* ====================================================================== */ #ifdef INSTANTIATE_VARIABLES #define GLOBAL char *achErrorMessages[]={ "everything fine", "operation canceled", "unsupported function", "end of scan or file", "memory overflow", "input/output error", "permission problem", "invalid parameter", "device busy", }; #else #define GLOBAL extern #endif #define PFMT_DEFAULT 0 #define PFMT_PBM 1 #define PFMT_PCL 2 #define PFMT_TIFFG4 3 /* ====================================================================== */ GLOBAL unsigned long ulDebugMask; GLOBAL TBool bVerbose; GLOBAL TBool bInteractive; GLOBAL char *szLogFile; GLOBAL char *szScanFile; GLOBAL int idOutputFormat; GLOBAL TInstance devInstance; /* ====================================================================== */ #endif /* INSANE_VERSION */ /* ====================================================================== */ #endif sane-backends-1.0.27/backend/plustek-pp_p9636.c0000664000175000017500000011235412112021330015717 00000000000000/* @file plustek-pp_p9636.c * @brief here we have all functionality according to the p9636t * * based on sources acquired from Plustek Inc. * Copyright (C) 1998 Plustek Inc. * Copyright (C) 2000-2004 Gerhard Jaeger * also based on the work done by Rick Bronson * * History: * - 0.30 - initial version * - 0.31 - Added some comments * - 0.32 - minor bug-fixes * - change p9636ReconnectScannerPath * - moved function IOSetStartStopRegister into this file * - 0.33 - went back to original three calls to p9636ReconnectScannerPath * to make sure that HP-printers will not start to print during * scan-process * - removed function p9636PositionLamp() * - 0.34 - no changes * - 0.35 - no changes * - 0.36 - changes, due to define renaming * - 0.37 - move p9636OpenScanPath, p9636CloseScanPath * and p9636RegisterToScanner to io.c * - removed skipping of the memory test for OP9636P * - removed // comments * - 0.38 - added function p9636PutToIdleMode() * - moved p9636ReadWriteTest to io.c * - added function p9636Calibration * - renamed function p9636SetP98001Init() to p9636InitP98001() * - 0.39 - no changes * - 0.40 - no changes * - 0.41 - no changes * - 0.42 - changed include names * - 0.43 - no changes * . *
* This file is part of the SANE package. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * As a special exception, the authors of SANE give permission for * additional uses of the libraries contained in this release of SANE. * * The exception is that, if you link a SANE library with other files * to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public * License. Your use of that executable is in no way restricted on * account of linking the SANE library code into it. * * This exception does not, however, invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * If you submit changes to SANE to the maintainers to be included in * a subsequent release, you agree by submitting the changes that * those changes may be distributed with this exception intact. * * If you write modifications of your own for SANE, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. *
*/ #include "plustek-pp_scan.h" /*************************** some definitions ********************************/ #define _NUM_OF_DACREGS_W8144 11 /*************************** some local vars *********************************/ static UShort P97ColorModeRegister[] = { 0x022C, 0x2A39, 0x0A3A, 0x373B, 0x163C, 0x0E41, 0x9042, 0x0143, 0x2744, 0x2745, 0x0146, 0x0347, 0x2748, 0x2F49, 0x094A, 0x034B, 0x074C, 0x054D, 0x064E, 0x0850, 0x0D51, 0x0C52, 0x0B53, 0x00F0, 0x022C, 0x3D39, 0x043A, 0x463B, 0x063C, 0x1F41, 0x8C42, 0x0143, 0x1344, 0x1345, 0xF246, 0x0247, 0x1348, 0x1349, 0xFA4A, 0x004B, 0x074C, 0x054D, 0x0E4E, 0x0150, 0x0651, 0x1252, 0x0B53, 0x00F0, 0x002C, 0x1639, 0x033A, 0x1F3B, 0x073C, 0x0441, 0x1E42, 0x0143, 0x1344, 0x1345, 0xF146, 0x0247, 0x1348, 0x1349, 0xF94A, 0x044B, 0x074C, 0x054D, 0x034E, 0x0650, 0x0351, 0x0952, 0x0B53, 0x00F0, 0x022C, 0x1839, 0x043A, 0x1D3B, 0x033C, 0x0C41, 0x8442, 0x0343, 0x0A44, 0x0845, 0xFA46, 0x0447, 0x0A48, 0x0849, 0xF24A, 0x024B, 0x034C, 0x024D, 0x0E4E, 0x0050, 0x0951, 0x0352, 0x0353, 0x00F0 }; static UShort P17ColorModeRegister[] = { 0x022C, 0x2C39, 0x053A, 0x3c3B, 0x0e3C, 0x0E41, 0x9042, 0x0143, 0x2744, 0x2745, 0x0146, 0x0247, 0x2748, 0x2F49, 0x094A, 0x054B, 0x074C, 0x054D, 0x064E, 0x0850, 0x0D51, 0x0C52, 0x0B53, 0x00F0, 0x022C, 0x3D39, 0x043A, 0x463B, 0x063C, 0x1F41, 0x8C42, 0x0143, 0x1344, 0x1345, 0xF246, 0x0147, 0x1348, 0x1349, 0xFA4A, 0x004B, 0x074C, 0x054D, 0x0E4E, 0x0150, 0x0651, 0x1252, 0x0B53, 0x00F0, 0x002C, 0x1639, 0x023A, 0x1a3B, 0x053C, 0x0441, 0x1E42, 0x0143, 0x1344, 0x1345, 0xF146, 0x0147, 0x1348, 0x1349, 0xF94A, 0x044B, 0x074C, 0x054D, 0x034E, 0x0650, 0x0351, 0x0952, 0x0B53, 0x00F0, 0x022C, 0x1839, 0x043A, 0x1D3B, 0x033C, 0x0C41, 0x8442, 0x0343, 0x0A44, 0x0845, 0xFA46, 0x0347, 0x0A48, 0x0849, 0xF24A, 0x024B, 0x034C, 0x024D, 0x0E4E, 0x0050, 0x0951, 0x0352, 0x0353, 0x00F0 }; static UShort P535ColorModeRegister[] = { 0x022C, 0x2F39, 0x883A, 0x403B, 0x0F3C, 0x0E41, 0x9042, 0x0143, 0x2744, 0x2745, 0x0146, 0x0147, 0x2748, 0x2F49, 0x094A, 0x034B, 0x074C, 0x054D, 0x064E, 0x0850, 0x0D51, 0x0C52, 0x0B53, 0x00F0, 0x022C, 0x3D39, 0x843A, 0x463B, 0x063C, 0x1F41, 0x8C42, 0x0143, 0x1344, 0x1345, 0xF246, 0x0147, 0x1348, 0x1349, 0xFA4A, 0x014B, 0x074C, 0x054D, 0x0E4E, 0x0150, 0x0651, 0x1252, 0x0B53, 0x00F0, 0x002C, 0x1639, 0x833A, 0x1F3B, 0x073C, 0x0441, 0x1E42, 0x0143, 0x1344, 0x1345, 0xF146, 0x0147, 0x1348, 0x1349, 0xF94A, 0x044B, 0x074C, 0x054D, 0x034E, 0x0650, 0x0351, 0x0952, 0x0B53, 0x00F0, 0x022C, 0x1639, 0x833A, 0x1D3B, 0x033C, 0x0C41, 0x8442, 0x0343, 0x0A44, 0x0845, 0xFA46, 0x0347, 0x0A48, 0x0849, 0xF24A, 0x024B, 0x034C, 0x024D, 0x0E4E, 0x0050, 0x0951, 0x0352, 0x0353, 0x00F0 }; static UShort P518ColorModeRegister[] = { 0x022C, 0x2F39, 0x883A, 0x403B, 0x0F3C, 0x0E41, 0x9042, 0x0143, 0x2744, 0x2745, 0x0146, 0x0147, 0x2748, 0x2F49, 0x094A, 0x034B, 0x074C, 0x054D, 0x064E, 0x0850, 0x0D51, 0x0C52, 0x0B53, 0x00F0, 0x022C, 0x3D39, 0x843A, 0x463B, 0x063C, 0x1F41, 0x8C42, 0x0143, 0x1344, 0x1345, 0xF246, 0x0147, 0x1348, 0x1349, 0xFA4A, 0x014B, 0x074C, 0x054D, 0x0E4E, 0x0150, 0x0651, 0x1252, 0x0B53, 0x00F0, 0x002C, 0x1639, 0x853A, 0x1F3B, 0x073C, 0x0441, 0x1E42, 0x0143, 0x1344, 0x1345, 0xF146, 0x0147, 0x1348, 0x1349, 0xF94A, 0x044B, 0x074C, 0x054D, 0x034E, 0x0650, 0x0351, 0x0952, 0x0B53, 0x00F0, 0x022C, 0x1639, 0x833A, 0x1D3B, 0x033C, 0x0C41, 0x8442, 0x0343, 0x0A44, 0x0845, 0xFA46, 0x0347, 0x0A48, 0x0849, 0xF24A, 0x024B, 0x034C, 0x024D, 0x0E4E, 0x0050, 0x0951, 0x0352, 0x0353, 0x00F0 }; static UShort P56ColorModeRegister[] = { 0x022C, 0x2F39, 0x043A, 0x363B, 0x033C, 0x0E41, 0x9042, 0x0143, 0x2744, 0x2745, 0x0146, 0x0247, 0x2748, 0x2F49, 0x094A, 0x034B, 0x074C, 0x054D, 0x064E, 0x0850, 0x0D51, 0x0C52, 0x0B53, 0x00F0, 0x022C, 0x3D39, 0x033A, 0x443B, 0x033C, 0x1F41, 0x8C42, 0x0143, 0x1344, 0x1345, 0xF246, 0x0247, 0x1348, 0x1349, 0xFA4A, 0x004B, 0x074C, 0x054D, 0x0E4E, 0x0150, 0x0651, 0x1252, 0x0B53, 0x00F0, 0x002C, 0x1439, 0x033A, 0x1D3B, 0x033C, 0x0441, 0x1E42, 0x0143, 0x1344, 0x1345, 0xF146, 0x0247, 0x1348, 0x1349, 0xF94A, 0x044B, 0x074C, 0x054D, 0x034E, 0x0650, 0x0351, 0x0952, 0x0B53, 0x00F0, 0x022C, 0x1639, 0x033A, 0x1B3B, 0x023C, 0x0C41, 0x8442, 0x0343, 0x0A44, 0x0845, 0xFA46, 0x0447, 0x0A48, 0x0849, 0xF24A, 0x024B, 0x034C, 0x024D, 0x0E4E, 0x0050, 0x0951, 0x0352, 0x0353, 0x00F0 }; static UShort P539ColorModeRegister[] = { 0x022C, 0x2F39, 0x883A, 0x403B, 0x0F3C, 0x0E41, 0x9042, 0x0143, 0x2744, 0x2745, 0x0146, 0x0147, 0x2748, 0x2F49, 0x094A, 0x034B, 0x074C, 0x054D, 0x064E, 0x0850, 0x0D51, 0x0C52, 0x0B53, 0x00F0, 0x022C, 0x3D39, 0x843A, 0x463B, 0x063C, 0x1F41, 0x8C42, 0x0143, 0x1344, 0x1345, 0xF246, 0x0147, 0x1348, 0x1349, 0xFA4A, 0x014B, 0x074C, 0x054D, 0x0E4E, 0x0150, 0x0651, 0x1252, 0x0B53, 0x00F0, 0x002C, 0x1639, 0x833A, 0x1F3B, 0x073C, 0x0441, 0x1E42, 0x0143, 0x1344, 0x1345, 0xF146, 0x0147, 0x1348, 0x1349, 0xF94A, 0x044B, 0x074C, 0x054D, 0x034E, 0x0650, 0x0351, 0x0952, 0x0B53, 0x00F0, 0x022C, 0x1639, 0x833A, 0x1D3B, 0x033C, 0x0C41, 0x8442, 0x0343, 0x0A44, 0x0845, 0xFA46, 0x0347, 0x0A48, 0x0849, 0xF24A, 0x024B, 0x034C, 0x024D, 0x0E4E, 0x0050, 0x0951, 0x0352, 0x0353, 0x00F0 }; static RegDef WolfsonDAC8144[_NUM_OF_DACREGS_W8144] = { {0x01, 0x01}, {0x02, 0x04}, {0x03, 0x42}, {0x05, 0x10}, {0x20, 0xd0}, {0x21, 0xd0}, {0x22, 0xd0}, {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x02, 0x04} }; static RegDef ccdStop[] = { {0x41, 0xff}, {0x42, 0xff}, {0x4b, 0xff}, {0x4c, 0xff}, {0x4d, 0xff}, {0x4e, 0xff}, {0x2a, 0x01}, {0x2b, 0x00}, {0x2d, 0x00}, {0x1b, 0x19}, {0x14, 0xff}, {0x15, 0x00} }; static DACTblDef shadingVar = { {{100, 100, 94}}, {{0x20, 0x20, 0x20}}, {{0x10, 0x10, 0x10}}, {{0x00, 0x00, 0x00}}, {{0xd0, 0xd0, 0xd0}}, 0 }; /*************************** local functions *********************************/ /*............................................................................. * initialize the register values for the 98001 asic */ static void p9636InitializeAsicRegister( pScanData ps ) { memset( &ps->AsicReg, 0, sizeof(RegData)); ps->AsicReg.RD_ScanControl = _SCAN_1ST_AVERAGE + _SCAN_BYTEMODE; ps->Scan.bFifoSelect = ps->RegGFifoOffset; } /*............................................................................. * 1) Setup the registers of asic. * 2) Determine which type of CCD we are using * 3) According to the CCD, prepare the CCD dependent veriables * SONY CCD: * The color exposure sequence: Red, Green (after 11 red lines), * Blue (after 8 green lines) * TOSHIBA CCD: * The color exposure sequence: Red, Blue (after 11 red lines), * Green (after 8 blue lines) */ static void p9636Init98001( pScanData ps, Bool shading ) { Byte bData; UShort w; ULong dwID; DataType Data; pUShort pw; DBG( DBG_LOW, "p9636InitP98001(%d)\n", shading ); bData = IODataRegisterFromScanner( ps, ps->RegConfiguration ); ps->Device.bCCDID = bData; ps->Device.bCCDID &= _P98_CCD_TYPE_ID; DBG( DBG_HIGH, "bData = 0x%04X, PCB-ID = 0x%02X\n", bData, (bData >> 4)); /* encode the CCD-id into the flag parameter */ dwID = (ULong)ps->Device.bCCDID; dwID = dwID << 16; ps->sCaps.dwFlag |= dwID; /* do the defaults here and the differences below */ ps->Device.f0_8_16 = _FALSE; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x10; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x10; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x10; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xd0; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xd0; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xd0; /* * yes, I know this function is rather ugly to read, but depending * on the scan-settings and the detected CCD-chip it prepares the * settings for the DAC */ ps->Device.dwModelOriginY = 0x50; ps->Device.wNumDACRegs = _NUM_OF_DACREGS_W8144; switch( ps->Device.bCCDID ) { case _CCD_3797: DBG( DBG_HIGH, "CCD-ID = 0x%02X = _CCD_3797\n", ps->Device.bCCDID ); ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 100; ps->Shade.pCcdDac->GainResize.Colors.Blue = 96; if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { if (ps->DataInf.dwScanFlag & SCANDEF_Transparency) { ps->Shade.pCcdDac->GainResize.Colors.Red = 130; ps->Shade.pCcdDac->GainResize.Colors.Green = 110; ps->Shade.pCcdDac->GainResize.Colors.Blue = 112; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xcc; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xcc; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xcc; ps->bsPreRedDAC = ps->bsPreGreenDAC = ps->bsPreBlueDAC = 0xcc; ps->wsDACCompareHighRed = 0x0B0; ps->wsDACCompareLowRed = 0x0A0; ps->wsDACCompareHighGreen = 0x90; ps->wsDACCompareLowGreen = 0x80; ps->wsDACCompareHighBlue = 0x90; ps->wsDACCompareLowBlue = 0x80; ps->wsDACOffsetRed = ps->wsDACOffsetGreen = ps->wsDACOffsetBlue = 0x30; } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 97; ps->Shade.pCcdDac->GainResize.Colors.Green = 82; ps->Shade.pCcdDac->GainResize.Colors.Blue = 100; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x80; ps->bsPreRedDAC = ps->bsPreGreenDAC = ps->bsPreBlueDAC = 0x80; ps->wsDACCompareHighRed = 0x90; ps->wsDACCompareLowRed = 0x80; ps->wsDACCompareHighGreen = 0x1a0; ps->wsDACCompareLowGreen = 0x190; ps->wsDACCompareHighBlue = 0x260; ps->wsDACCompareLowBlue = 0x250; ps->wsDACOffsetRed = ps->wsDACOffsetGreen = ps->wsDACOffsetBlue = 0x20; } } else { ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x50; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x40; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x38; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x28; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x28; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x18; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x30; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x18; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x08; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xf0; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xcc; if (ps->bSetScanModeFlag & _ScanMode_Mono) { ps->Shade.pCcdDac->DarkDAC.Colors.Green = ((ps->bSetScanModeFlag & _ScanMode_AverageOut)? 0xa0:0x68); } else { ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xcc; } } if ((ps->bSetScanModeFlag & _ScanMode_Mono) || (ps->DataInf.dwScanFlag & SCANDEF_Negative)) { WolfsonDAC8144[3].bParam = 0x12; } else { WolfsonDAC8144[3].bParam = 0x10; } pw = P97ColorModeRegister; break; case _CCD_3717: DBG( DBG_HIGH, "CCD-ID = 0x%02X = _CCD_3717\n", ps->Device.bCCDID ); ps->Shade.pCcdDac->GainResize.Colors.Red = 96; ps->Shade.pCcdDac->GainResize.Colors.Green = 97; ps->Shade.pCcdDac->GainResize.Colors.Blue = 100; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x15; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x05; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x10; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x01; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x10; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x01; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x28; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x14; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x10; ps->Shade.pCcdDac->DarkDAC.Colors.Green = ((ps->bSetScanModeFlag&_ScanMode_Mono)?0xd0:0xd6); ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xdd; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xd9; ps->Device.f0_8_16 = _TRUE; pw = P17ColorModeRegister; break; case _CCD_535: DBG( DBG_HIGH, "CCD-ID = 0x%02X = _CCD_535\n", ps->Device.bCCDID ); ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 100; ps->Shade.pCcdDac->GainResize.Colors.Blue = 95; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x2e; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0x28; ps->wMinCmpDpi = 75; ps->lpEppColorHomePos->wMaxSteps = 890; ps->lpBppColorHomePos->wMaxSteps = 890; ps->lpSppColorHomePos->wMaxSteps = 890; /* * for less 75 Dpi Motor can't moveable in Some machine * ps->lpEppColorHomePos->bExposureTime = 48; */ ps->lpEppColorHomePos->bExposureTime = 64; ps->a_tabDiffParam[_ColorEpp60].bStepSpeed = 8; ps->a_ColorSettings [1].bExposureTime = 64; ps->a_tabDiffParam[_ColorEpp100_1400].bStepSpeed = 16; ps->lpBppColorHomePos->bExposureTime = 96; ps->lpSppColorHomePos->bExposureTime = 96; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xf0; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xdf; if (ps->bSetScanModeFlag & _ScanMode_Mono) { ps->Shade.pCcdDac->GainResize.Colors.Green = 110; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xf0; } else { if (ps->bSetScanModeFlag & _ScanMode_AverageOut) { ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xf6; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xe5; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xe4; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0x18; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0; } else { ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xf0; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xe1; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xdf; } } pw = P535ColorModeRegister; break; case _CCD_2556: DBG( DBG_HIGH, "CCD-ID = 0x%02X = _CCD_2556\n", ps->Device.bCCDID ); ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 100; ps->Shade.pCcdDac->GainResize.Colors.Blue = 100; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x10; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x10; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x10; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0; pw = P56ColorModeRegister; break; case _CCD_518: DBG( DBG_HIGH, "CCD-ID = 0x%02X = _CCD_518\n", ps->Device.bCCDID ); ps->Device.dwModelOriginY = 0x50-3; /* 0x50-13 */ ps->Shade.pCcdDac->GainResize.Colors.Red = 98; ps->Shade.pCcdDac->GainResize.Colors.Green = 98; ps->Shade.pCcdDac->GainResize.Colors.Blue = 98; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xcc; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xcc; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xcc; if (ps->bSetScanModeFlag & _ScanMode_Mono) { ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x30; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x20; } if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) { ps->Shade.pCcdDac->GainResize.Colors.Red = 104; ps->Shade.pCcdDac->GainResize.Colors.Green = 92; ps->Shade.pCcdDac->GainResize.Colors.Blue = 96; ps->bsPreRedDAC = ps->bsPreGreenDAC = ps->bsPreBlueDAC = 0xcc; ps->Shade.pCcdDac->DarkCmpHi.Colors.Red = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Red = 0x10; ps->Shade.pCcdDac->DarkCmpHi.Colors.Green = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Green = 0x10; ps->Shade.pCcdDac->DarkCmpHi.Colors.Blue = 0x20; ps->Shade.pCcdDac->DarkCmpLo.Colors.Blue = 0x10; ps->Shade.pCcdDac->DarkOffSub.Colors.Red = 0; ps->Shade.pCcdDac->DarkOffSub.Colors.Green = 0; ps->Shade.pCcdDac->DarkOffSub.Colors.Blue = 0; ps->wsDACCompareHighRed = 0x80; /* 0x35 */ ps->wsDACCompareLowRed = 0x70; /* 0x25 */ ps->wsDACCompareHighGreen = 0x80; /* 0x46 */ ps->wsDACCompareLowGreen = 0x70; /* 0x36 */ ps->wsDACCompareHighBlue = 0x80; /* 0x54 */ ps->wsDACCompareLowBlue = 0x70; /* 0x44 */ ps->wsDACOffsetRed = ps->wsDACOffsetGreen = ps->wsDACOffsetBlue = 0; /* 0x70 */ } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 94; ps->Shade.pCcdDac->GainResize.Colors.Green = 80; ps->Shade.pCcdDac->GainResize.Colors.Blue = 78; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x80; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x80; ps->bsPreRedDAC = ps->bsPreGreenDAC = ps->bsPreBlueDAC = 0x80; ps->wsDACCompareHighRed = 0x90; ps->wsDACCompareLowRed = 0x80; ps->wsDACCompareHighGreen = 0x1a0; ps->wsDACCompareLowGreen = 0x190; ps->wsDACCompareHighBlue = 0x160; ps->wsDACCompareLowBlue = 0x150; ps->wsDACOffsetRed = 0xb0; /* 0x180 */ ps->wsDACOffsetGreen = 0xcc; /* 0x180 */ ps->wsDACOffsetBlue = 0xe2; /* 0x240 */ } } if ((ps->bSetScanModeFlag & _ScanMode_Mono) || (ps->DataInf.dwScanFlag & SCANDEF_Negative)) { WolfsonDAC8144[3].bParam = 0x12; } else { WolfsonDAC8144[3].bParam = 0x10; } ps->Device.f0_8_16 = _TRUE; pw = P518ColorModeRegister; break; /* * CCD_539 */ default: DBG( DBG_HIGH, "CCD-ID = 0x%02X = _CCD_539\n", ps->Device.bCCDID ); ps->Shade.pCcdDac->GainResize.Colors.Red = 100; ps->Shade.pCcdDac->GainResize.Colors.Green = 100; ps->Shade.pCcdDac->GainResize.Colors.Blue = 98; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0xcc; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0xcc; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0xcc; if( ps->DataInf.dwScanFlag & SCANDEF_TPA ) { if( ps->DataInf.dwScanFlag & SCANDEF_Transparency ) { ps->Shade.pCcdDac->GainResize.Colors.Red = 80; ps->Shade.pCcdDac->GainResize.Colors.Green = 80; ps->Shade.pCcdDac->GainResize.Colors.Blue = 80; ps->bsPreRedDAC = 0xcc; ps->bsPreGreenDAC = 0xcc; ps->bsPreBlueDAC = 0xcc; ps->wsDACCompareHighRed = 0x90; ps->wsDACCompareLowRed = 0x80; ps->wsDACCompareHighGreen = 0x90; ps->wsDACCompareLowGreen = 0x80; ps->wsDACCompareHighBlue = 0x90; ps->wsDACCompareLowBlue = 0x80; ps->wsDACOffsetRed = ps->wsDACOffsetGreen = ps->wsDACOffsetBlue = 0x70; } else { ps->Shade.pCcdDac->GainResize.Colors.Red = 80; ps->Shade.pCcdDac->GainResize.Colors.Green = 96; ps->Shade.pCcdDac->GainResize.Colors.Blue = 95; ps->Shade.pCcdDac->DarkDAC.Colors.Red = 0x90; ps->Shade.pCcdDac->DarkDAC.Colors.Green = 0x90; ps->Shade.pCcdDac->DarkDAC.Colors.Blue = 0x90; ps->bsPreRedDAC = ps->bsPreGreenDAC = ps->bsPreBlueDAC = 0x90; ps->wsDACCompareHighRed = 0xd0; /* 0x90 */ ps->wsDACCompareLowRed = 0xc0; /* 0x80 */ ps->wsDACCompareHighGreen = 0x110; /* 0x1a0 */ ps->wsDACCompareLowGreen = 0x100; /* 0x190 */ ps->wsDACCompareHighBlue = 0x130; /* 0x260 */ ps->wsDACCompareLowBlue = 0x120; /* 0x250 */ ps->wsDACOffsetRed = 0x70; /* 0x70 */ ps->wsDACOffsetGreen = 0x70; /* 0x180 */ ps->wsDACOffsetBlue = 0x70; /* 0x240 */ } } if (ps->bSetScanModeFlag & _ScanMode_Mono || (ps->DataInf.dwScanFlag & SCANDEF_Negative)) { WolfsonDAC8144[3].bParam = 0x12; } else { WolfsonDAC8144[3].bParam = 0x10; } ps->Device.f0_8_16 = _TRUE; pw = P539ColorModeRegister; break; } if( ps->bSetScanModeFlag == _ScanMode_Color ) WolfsonDAC8144[2].bParam = 0x52; else WolfsonDAC8144[2].bParam = 0x42; if( ps->bSetScanModeFlag == _ScanMode_Mono ) WolfsonDAC8144[0].bParam = 7; else WolfsonDAC8144[0].bParam = 3; ps->OpenScanPath( ps ); /* * base init of the DAC */ DBG( DBG_IO, "Programming DAC (%u regs)\n", ps->Device.wNumDACRegs ); for( w = 0; w < ps->Device.wNumDACRegs; w++) { DBG( DBG_IO, "*[0x%02x] = 0x%02x\n", WolfsonDAC8144[w].bReg, WolfsonDAC8144[w].bParam ); IODataRegisterToDAC( ps, WolfsonDAC8144[w].bReg, WolfsonDAC8144[w].bParam ); } if( ps->bSetScanModeFlag & _ScanMode_Mono ) { ps->AsicReg.RD_Model1Control = _MOTOR_2916 + _BUTTON_MODE + _CCD_SHIFT_GATE + _SCAN_GRAYTYPE; } else { ps->AsicReg.RD_Model1Control = _MOTOR_2916 + _BUTTON_MODE + _CCD_SHIFT_GATE; } IODataToRegister( ps, ps->RegModel1Control, ps->AsicReg.RD_Model1Control ); /* Check: THIS IS 11 on the 98003 */ IODataToRegister( ps, ps->RegWaitStateInsert, 6 ); /* * according to the scan mode, program the CCD */ pw = pw + (ULong)ps->bSetScanModeFlag * 24; DBG( DBG_LOW, "bSetScanModeFlag = %u\n", ps->bSetScanModeFlag ); for( w = 24; w--; pw++) { Data.wValue = *pw; IODataToRegister( ps, Data.wOverlap.b1st, Data.wOverlap.b2nd ); } ps->CloseScanPath( ps ); } /*............................................................................. * call the InitAsic function * set LineControl and stop motor */ static void p9636SetupScannerVariables( pScanData ps ) { ps->ReInitAsic( ps, _FALSE ); IOCmdRegisterToScanner(ps, ps->RegLineControl, ps-> AsicReg.RD_LineControl); memset( ps->a_nbNewAdrPointer, 0, _SCANSTATE_BYTES); IOSetToMotorRegister( ps ); } /*............................................................................. * set all necessary register contents */ static void p9636SetGeneralRegister( pScanData ps ) { DBG( DBG_LOW, "p9636SetGeneralRegister()\n" ); ps->AsicReg.RD_StepControl = _MOTOR0_SCANSTATE + _MOTOR0_ONESTEP; ps->AsicReg.RD_ModeControl = _ModeScan + _ModeFifoRSel; ps->AsicReg.RD_Motor1Control = _MotorOn + _MotorDirForward; ps->AsicReg.RD_Motor0Control = ps->bHpMotor | (_MotorOn+_MotorDirForward); ps->AsicReg.RD_XStepTime = ps->bStepSpeed; if( COLOR_BW == ps->DataInf.wPhyDataType ) { ps->AsicReg.RD_ScanControl = _SCAN_BITMODE; if( !(ps->DataInf.dwScanFlag & SCANDEF_Inverse)) ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT; } else { if (COLOR_TRUE48 == ps->DataInf.wPhyDataType) { ps->AsicReg.RD_ScanControl = _SCAN_12BITMODE; if (!(ps->DataInf.dwScanFlag & SCANDEF_RightAlign)) ps->AsicReg.RD_ScanControl |= _BITALIGN_LEFT; } else ps->AsicReg.RD_ScanControl = _SCAN_BYTEMODE; if( ps->DataInf.dwScanFlag & SCANDEF_Inverse ) ps->AsicReg.RD_ScanControl |= _P98_SCANDATA_INVERT; } ps->AsicReg.RD_ScanControl |= _SCAN_1ST_AVERAGE; IOSelectLampSource( ps ); } /*............................................................................. * tell the scanner/ASIC where to start scanning and how many pixels */ static void p9636SetStartStopRegister( pScanData ps ) { ps->AsicReg.RD_Origin = (UShort)(ps->dwOffset70 + ps->Device.DataOriginX + ps->DataInf.crImage.x); DBG( DBG_LOW, "p9636SetStartStopRegister()\n" ); if (ps->bSetScanModeFlag & _ScanMode_AverageOut ) ps->AsicReg.RD_Origin = ps->AsicReg.RD_Origin >> 1; if (ps->DataInf.wPhyDataType < COLOR_256GRAY) { ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicBytesPerLine; } else { ps->AsicReg.RD_Pixels = (UShort)ps->DataInf.dwAsicPixelsPerPlane; } DBG( DBG_LOW, "RD_Origin = %u, RD_Pixels = %u\n", ps->AsicReg.RD_Origin, ps->AsicReg.RD_Pixels ); } /*............................................................................. * */ static void p9636SetupScanningCondition( pScanData ps ) { ULong dw; IORegisterDirectToScanner( ps, ps->RegInitDataFifo ); ps->InitialSetCurrentSpeed( ps ); if (ps->DataInf.wPhyDataType > COLOR_TRUE24) { if (ps->DataInf.dwAsicBytesPerPlane < 1024) ps->Scan.dwMinReadFifo = 1024; else ps->Scan.dwMinReadFifo = ps->DataInf.dwAsicBytesPerPlane; } else { if (ps->DataInf.dwAsicBytesPerPlane * 2 < 1024) ps->Scan.dwMinReadFifo = 1024; else ps->Scan.dwMinReadFifo = ps->DataInf.dwAsicBytesPerPlane * 2; } p9636SetGeneralRegister( ps ); IORegisterDirectToScanner( ps, ps->RegInitDataFifo ); ps->SetupMotorRunTable( ps ); ps->AsicReg.RD_Dpi = ps->DataInf.xyPhyDpi.x; p9636SetStartStopRegister( ps ); IOSetToMotorRegister ( ps ); ps->bCurrentLineCount = 0; IOCmdRegisterToScanner(ps, ps->RegScanControl, ps->AsicReg.RD_ScanControl); IOPutOnAllRegisters( ps ); ps->OpenScanPath( ps ); ps->AsicReg.RD_ModeControl &= ~_ModeIdle; IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl); ps->AsicReg.RD_ModeControl = _ModeScan + _ModeFifoRSel; IODataToRegister( ps, ps->RegModeControl, ps->AsicReg.RD_ModeControl); IORegisterToScanner( ps, ps->RegInitDataFifo ); ps->CloseScanPath( ps ); if (ps->DataInf.wPhyDataType >= COLOR_TRUE24) { dw = ps->DataInf.dwAsicPixelsPerPlane; ps->dwMaxReadFifoData = _SIZE_COLORFIFO - ps->DataInf.dwAsicBytesPerPlane * 64UL / (ULong)ps->bCurrentSpeed - dw; } else { dw = ps->DataInf.dwAsicBytesPerPlane; ps->dwMaxReadFifoData = _SIZE_GRAYFIFO - ps->DataInf.dwAsicBytesPerPlane * 64UL / (ULong)ps->bCurrentSpeed - dw; } if ((dw = dw * 4UL) > ps->dwMaxReadFifoData) { ps->dwSizeMustProcess = ps->dwMaxReadFifoData; } else { ps->dwSizeMustProcess = dw; } if (ps->DataInf.wPhyDataType >= COLOR_TRUE24) { if (ps->DataInf.xyPhyDpi.y <= 150) { dw = ps->DataInf.dwAsicPixelsPerPlane; } else { if (ps->DataInf.xyPhyDpi.y <= 300) { dw = ps->DataInf.dwAsicPixelsPerPlane * 2; } else { if (ps->DataInf.xyPhyDpi.y <= 600) { dw = ps->DataInf.dwAsicPixelsPerPlane * 4; } else { dw = ps->DataInf.dwAsicPixelsPerPlane * 8; } } } if (ps->Device.f0_8_16 && (ps->DataInf.xyPhyDpi.y >= 150)) dw <<= 1; ps->dwSizeMustProcess += dw; ps->Scan.dwMinReadFifo += dw; ps->dwMaxReadFifoData += dw; } } /*............................................................................. * switch the scanner into idle mode */ static void p9636PutToIdleMode( pScanData ps ) { int i; DBG( DBG_LOW, "Putting Scanner (ASIC 98001) into Idle-Mode\n" ); /* * turn off motor */ IOCmdRegisterToScanner( ps, ps->RegMotor0Control, 0x00 ); IOCmdRegisterToScanner( ps, ps->RegLineControl,ps->AsicReg.RD_LineControl); IOCmdRegisterToScanner( ps, ps->RegModeControl, (_ModeIdle + _ModeFifoClose)); ps->OpenScanPath(ps); DBG( DBG_IO, "CCD-Stop\n" ); for( i = 0; i < 12; i++ ) { DBG(DBG_IO, "*[0x%02x] = 0x%02x\n",ccdStop[i].bReg, ccdStop[i].bParam); IODataToRegister( ps, ccdStop[i].bReg, ccdStop[i].bParam ); } IODataRegisterToDAC( ps, 0x01, 0x00 ); /* Close ADC */ ps->CloseScanPath(ps); } /*............................................................................. * do all the preliminary stuff here (calibrate the scanner and move the * sensor to it´s start position, also setup the driver for the * current run) */ static int p9636Calibration( pScanData ps ) { DBG( DBG_LOW, "p9636Calibration()\n" ); ps->Scan.bFifoSelect = ps->RegGFifoOffset; /* * wait for shading to be done */ _ASSERT(ps->WaitForShading); if( !ps->WaitForShading( ps )) return _E_TIMEOUT; IOCmdRegisterToScanner( ps, ps->RegLineControl, _DEFAULT_LINESCANTIME ); /* * move sensor and setup scanner for grabbing the picture */ _ASSERT(ps->WaitForPositionY); ps->WaitForPositionY( ps ); IOCmdRegisterToScanner( ps, ps->RegLineControl, ps->AsicReg.RD_LineControl ); ps->fDoFilter = ps->fFilterFirstLine = _FALSE; ps->dwDivFilter = ps->dwMul = 53; ps->bOffsetFilter = 12; if (COLOR_256GRAY == ps->DataInf.wPhyDataType) { ps->fDoFilter = _TRUE; ps->pFilterBuf = ps->pGet1 = ps->pProcessingBuf; ps->pGet2 = ps->pGet1 + 5120; ps->pGet3 = ps->pGet2 + 5120; ps->pEndBuf = ps->pGet3 + 5120; ps->fFilterFirstLine = _TRUE; ps->dwLinesFilter = ps->DataInf.dwAppLinesPerArea; } ps->bCurrentLineCount = 0x3f; _DODELAY(1); return _OK; } /************************ exported functions *********************************/ /*............................................................................. * initialize the register values and function calls for the 98001 asic */ _LOC int P9636InitAsic( pScanData ps ) { int result; DBG( DBG_LOW, "P9636InitAsic()\n" ); /* * preset the asic shadow registers */ p9636InitializeAsicRegister( ps ); ps->IO.bOpenCount = 0; /* * setup the register values */ ps->RegSwitchBus = 0; ps->RegEPPEnable = 1; ps->RegECPEnable = 2; ps->RegReadDataMode = 3; ps->RegWriteDataMode = 4; ps->RegInitDataFifo = 5; ps->RegForceStep = 6; ps->RegInitScanState = 7; ps->RegRefreshScanState = 8; ps->RegWaitStateInsert = 0x0a; ps->RegRFifoOffset = 0x0a; ps->RegGFifoOffset = 0x0b; ps->RegBFifoOffset = 0x0c; ps->RegBitDepth = 0x13; ps->RegStepControl = 0x14; ps->RegMotor0Control = 0x15; ps->RegXStepTime = 0x16; ps->RegGetScanState = 0x17; ps->RegAsicID = 0x18; ps->RegMemoryLow = 0x19; ps->RegMemoryHigh = 0x1a; ps->RegModeControl = 0x1b; ps->RegLineControl = 0x1c; ps->RegScanControl = 0x1d; ps->RegConfiguration = 0x1e; ps->RegModelControl = 0x1f; ps->RegModel1Control = 0x20; ps->RegDpiLow = 0x21; ps->RegDpiHigh = 0x22; ps->RegScanPosLow = 0x23; ps->RegScanPosHigh = 0x24; ps->RegWidthPixelsLow = 0x25; ps->RegWidthPixelsHigh = 0x26; ps->RegThresholdLow = 0x27; ps->RegThresholdHigh = 0x28; ps->RegThresholdGapControl = 0x29; ps->RegADCAddress = 0x2a; ps->RegADCData = 0x2b; ps->RegADCPixelOffset = 0x2c; ps->RegADCSerialOutStr = 0x2d; ps->RegResetConfig = 0x2e; ps->RegLensPosition = 0x2f; ps->RegStatus = 0x30; ps->RegScanStateControl = 0x31; ps->RegRedChDarkOffsetLow = 0x33; ps->RegRedChDarkOffsetHigh = 0x34; ps->RegGreenChDarkOffsetLow = 0x35; ps->RegGreenChDarkOffsetHigh= 0x36; ps->RegBlueChDarkOffsetLow = 0x37; ps->RegBlueChDarkOffsetHigh = 0x38; ps->RegResetPulse0 = 0x39; ps->RegResetPulse1 = 0x3a; ps->RegCCDClampTiming0 = 0x3b; ps->RegCCDClampTiming1 = 0x3c; ps->RegVSMPTiming0 = 0x41; ps->RegVSMPTiming1 = 0x42; ps->RegCCDQ1Timing0 = 0x43; ps->RegCCDQ1Timing1 = 0x44; ps->RegCCDQ1Timing2 = 0x45; ps->RegCCDQ1Timing3 = 0x46; ps->RegCCDQ2Timing0 = 0x47; ps->RegCCDQ2Timing1 = 0x48; ps->RegCCDQ2Timing2 = 0x49; ps->RegCCDQ2Timing3 = 0x4a; ps->RegADCclockTiming0 = 0x4b; ps->RegADCclockTiming1 = 0x4c; ps->RegADCclockTiming2 = 0x4d; ps->RegADCclockTiming3 = 0x4e; ps->RegADCDVTiming0 = 0x50; ps->RegADCDVTiming1 = 0x51; ps->RegADCDVTiming2 = 0x52; ps->RegADCDVTiming3 = 0x53; /* * setup function calls */ ps->SetupScannerVariables = p9636SetupScannerVariables; ps->SetupScanningCondition = p9636SetupScanningCondition; ps->ReInitAsic = p9636Init98001; ps->PutToIdleMode = p9636PutToIdleMode; ps->Calibration = p9636Calibration; /* * setup misc */ ps->CtrlReadHighNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF + _CTRL_STROBE; ps->CtrlReadLowNibble = _CTRL_GENSIGNAL + _CTRL_AUTOLF; ps->f97003 = _FALSE; ps->IO.useEPPCmdMode = _FALSE; ps->Scan.fRefreshState = _TRUE; ps->wMinCmpDpi = 60; ps->Scan.fMotorBackward = _FALSE; IOSetXStepLineScanTime( ps, _DEFAULT_LINESCANTIME ); ps->Shade.pCcdDac = &shadingVar; ps->bFastMoveFlag = _FastMove_Low_C75_G150; ps->dwOffset70 = _P98_OFFSET70; /* * initialize the other modules and set some * function pointer */ result = DacInitialize( ps ); if( _OK != result ) return result; result = ImageInitialize( ps ); if( _OK != result ) return result; result = IOFuncInitialize( ps ); if( _OK != result ) return result; result = IOInitialize( ps ); if( _OK != result ) return result; result = MotorInitialize( ps ); if( _OK != result ) return result; /* * in debug version, check all function pointers */ #ifdef DEBUG if( _FALSE == MiscAllPointersSet( ps )) return _E_INTERNAL; #endif DBG( DBG_LOW, "0x%02x\n", ps->sCaps.AsicID ); if( _FALSE == ps->OpenScanPath( ps )) { DBG( DBG_LOW, "P9636InitAsic() failed.\n" ); return _E_NO_DEV; } /*get CCD ID */ ps->Device.bCCDID = IODataFromRegister( ps, ps->RegConfiguration ); ps->Device.bCCDID &= _P98_CCD_TYPE_ID; DBG( DBG_HIGH, "CCID = 0x%02X\n", ps->Device.bCCDID); ps->CloseScanPath( ps ); /* as the program parts concerning some CCDs don't handle TPA stuff, * I assume that these devices won't have TPA functionality */ switch( ps->Device.bCCDID ) { case _CCD_3717: case _CCD_535: case _CCD_2556: DBG( DBG_HIGH, "Seems we have a 9636P\n" ); ps->sCaps.Model = MODEL_OP_9636PP; ps->sCaps.dwFlag &= ~SFLAG_TPA; break; } DBG( DBG_LOW, "P9636InitAsic() done.\n" ); return _OK; } /* END PLUSTEK-PP_P9636.C ...................................................*/ sane-backends-1.0.27/backend/nec.conf.in0000664000175000017500000000001512112021330014607 00000000000000/dev/scanner sane-backends-1.0.27/backend/genesys_devices.c0000664000175000017500000040334212775312261016150 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2003 Oliver Rauch Copyright (C) 2003-2005 Henning Meier-Geinitz Copyright (C) 2004, 2005 Gerhard Jaeger Copyright (C) 2004-2013 Stéphane Voltz Copyright (C) 2005-2009 Pierre Willenbrock Copyright (C) 2007 Luke Copyright (C) 2010 Jack McGill Copyright (C) 2010 Andrey Loginov , xerox travelscan device entry Copyright (C) 2010 Chris Berry and Michael Rickmann for Plustek Opticbook 3600 support This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* ------------------------------------------------------------------------ */ /* Some setup DAC and CCD tables */ /* ------------------------------------------------------------------------ */ /** Setup table for various scanners using a Wolfson DAC */ static Genesys_Frontend Wolfson[] = { { DAC_WOLFSON_UMAX, {0x00, 0x03, 0x05, 0x11} , {0x00, 0x00, 0x00} , {0x80, 0x80, 0x80} , {0x02, 0x02, 0x02} , {0x00, 0x00, 0x00} } , /* 0: UMAX */ {DAC_WOLFSON_ST12, {0x00, 0x03, 0x05, 0x03} , {0x00, 0x00, 0x00} , {0xc8, 0xc8, 0xc8} , {0x04, 0x04, 0x04} , {0x00, 0x00, 0x00} } , /* 1: ST12 */ {DAC_WOLFSON_ST24,{0x00, 0x03, 0x05, 0x21} , {0x00, 0x00, 0x00} , {0xc8, 0xc8, 0xc8} , {0x06, 0x06, 0x06} , {0x00, 0x00, 0x00} } , /* 2: ST24 */ {DAC_WOLFSON_5345,{0x00, 0x03, 0x05, 0x12} , {0x00, 0x00, 0x00} , {0xb8, 0xb8, 0xb8} , {0x04, 0x04, 0x04} , {0x00, 0x00, 0x00} } , /* 3: MD6228/MD6471 */ {DAC_WOLFSON_HP2400, /* reg0 reg1 reg2 reg3 */ {0x00, 0x03, 0x05, 0x02} /* reg3=0x02 for 50-600 dpi, 0x32 (0x12 also works well) at 1200 */ , {0x00, 0x00, 0x00} , {0xb4, 0xb6, 0xbc} , {0x06, 0x09, 0x08} , {0x00, 0x00, 0x00} } , /* 4: HP2400c */ {DAC_WOLFSON_HP2300, {0x00, 0x03, 0x04, 0x02} , {0x00, 0x00, 0x00} , {0xbe, 0xbe, 0xbe} , {0x04, 0x04, 0x04} , {0x00, 0x00, 0x00} } , /* 5: HP2300c */ {DAC_CANONLIDE35,{0x00, 0x3d, 0x08, 0x00} , {0x00, 0x00, 0x00} , {0xe1, 0xe1, 0xe1} , {0x93, 0x93, 0x93} , {0x00, 0x19, 0x06} } , /* 6: CANONLIDE35 */ {DAC_AD_XP200, {0x58, 0x80, 0x00, 0x00} /* reg1=0x80 ? */ , {0x00, 0x00, 0x00} , {0x09, 0x09, 0x09} , {0x09, 0x09, 0x09} , {0x00, 0x00, 0x00} } , {DAC_WOLFSON_XP300,{0x00, 0x35, 0x20, 0x14} /* 7: XP300 */ , {0x00, 0x00, 0x00} , {0xe1, 0xe1, 0xe1} , {0x93, 0x93, 0x93} , {0x07, 0x00, 0x00} } , /* 8: HP3670 */ {DAC_WOLFSON_HP3670, /* reg0 reg1 reg2 reg3 */ {0x00, 0x03, 0x05, 0x32} /* reg3=0x32 for 100-300 dpi, 0x12 at 1200 */ , {0x00, 0x00, 0x00} /* sign */ , {0xba, 0xb8, 0xb8} /* offset */ , {0x06, 0x05, 0x04} /* gain 4,3,2 at 1200 ?*/ , {0x00, 0x00, 0x00} } , {DAC_WOLFSON_DSM600,{0x00, 0x35, 0x20, 0x14} /* 9: DSMOBILE600 */ , {0x00, 0x00, 0x00} , {0x85, 0x85, 0x85} , {0xa0, 0xa0, 0xa0} , {0x07, 0x00, 0x00} } , {DAC_CANONLIDE200, {0x9d, 0x91, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x3f, 0x00} /* 0x00 0x3f 0x00 : offset/brigthness ? */ , {0x32, 0x04, 0x00} , {0x00, 0x00, 0x00} } , {DAC_CANONLIDE700, {0x9d, 0x9e, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x3f, 0x00} /* 0x00 0x3f 0x00 : offset/brigthness ? */ , {0x2f, 0x04, 0x00} , {0x00, 0x00, 0x00} } , /* KV-SS080 */ {DAC_KVSS080, {0x00, 0x23, 0x24, 0x0f} , {0x00, 0x00, 0x00} , {0x80, 0x80, 0x80} , {0x4b, 0x4b, 0x4b} , {0x00,0x00,0x00} } , {DAC_G4050, {0x00, 0x23, 0x24, 0x1f} , {0x00, 0x00, 0x00} , {0x45, 0x45, 0x45} /* 0x20, 0x21, 0x22 */ , {0x4b, 0x4b, 0x4b} /* 0x28, 0x29, 0x2a */ , {0x00,0x00,0x00} } , {DAC_CANONLIDE110, {0x80, 0x8a, 0x23, 0x4c} , {0x00, 0xca, 0x94} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} } , /** @brief GL124 special case * for GL124 based scanners, this struct is "abused" * in fact the fields are map like below to AFE registers * (from Texas Instrument or alike ?) */ {DAC_CANONLIDE120, {0x80, /* 0001 0002 0003 */ 0xa3, 0x2b, 0x4c} /* 0005 0006 0007 */ , {0x00, 0xca, 0x95} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} } , {DAC_PLUSTEK_3600, {0x70, 0x80, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x3f, 0x3d, 0x3d} , {0x00, 0x00, 0x00} } , {DAC_CS8400F, {0x00, 0x23, 0x24, 0x0f} , {0x00, 0x00, 0x00} , {0x60, 0x5c, 0x6c} /* 0x20, 0x21, 0x22 */ , {0x8a, 0x9f, 0xc2} /* 0x28, 0x29, 0x2a */ , {0x00, 0x00, 0x00} } , {DAC_IMG101, {0x78, 0xf0, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} /* 0x20, 0x21, 0x22 */ , {0x00, 0x00, 0x00} /* 0x28, 0x29, 0x2a */ , {0x00, 0x00, 0x00} } , {DAC_PLUSTEK3800, {0x78, 0xf0, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} /* 0x20, 0x21, 0x22 */ , {0x00, 0x00, 0x00} /* 0x28, 0x29, 0x2a */ , {0x00, 0x00, 0x00} }, {DAC_CANONLIDE80, /* reg0: control 74 data, 70 no data * reg3: offset * reg6: gain * reg0 , reg3, reg6 */ {0x70, 0x16, 0x60, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} , {0x00, 0x00, 0x00} } }; /** for setting up the sensor-specific settings: * Optical Resolution, number of black pixels, number of dummy pixels, * CCD_start_xoffset, and overall number of sensor pixels * registers 0x08-0x0b, 0x10-0x1d and 0x52-0x5e */ static Genesys_Sensor Sensor[] = { /* 0: UMAX */ {CCD_UMAX, 1200, 48, 64, 0, 10800, 210, 230, {0x01, 0x03, 0x05, 0x07} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x05, 0x31, 0x2a, 0x00, 0x00, 0x00, 0x02} , {0x13, 0x17, 0x03, 0x07, 0x0b, 0x0f, 0x23, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00} , {1.0, 1.0, 1.0}, {NULL, NULL, NULL}} , /* 1: Plustek OpticPro S12/ST12 */ {CCD_ST12, 600, 48, 85, 152, 5416, 210, 230, {0x02, 0x00, 0x06, 0x04} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x08, 0x20, 0x2a, 0x00, 0x00, 0x0c, 0x03} , {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00} , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* 2: Plustek OpticPro S24/ST24 */ {CCD_ST24, 1200, 48, 64, 0, 10800, 210, 230, {0x0e, 0x0c, 0x00, 0x0c} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x08, 0x31, 0x2a, 0x00, 0x00, 0x00, 0x02} , {0x17, 0x03, 0x07, 0x0b, 0x0f, 0x13, 0x03, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00} , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* 3: MD6471 */ {CCD_5345, 1200, 48, 16, 0, 10872, 190, 190, {0x0d, 0x0f, 0x11, 0x13} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x30, 0x2a, 0x00, 0x00, 0x00, 0x03} , {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x23, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00} , {2.38, 2.35, 2.34}, {NULL, NULL, NULL} } , /* 4: HP2400c */ {CCD_HP2400, 1200, 48, 15, 0, 10872, 210, 200, {0x14, 0x15, 0x00, 0x00} /* registers 0x08-0x0b */ , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x08, 0x3f, 0x2a, 0x00, 0x00, 0x00, 0x02} , {0x0b, 0x0f, 0x13, 0x17, 0x03, 0x07, 0x63, 0x00, 0xc1, 0x00, 0x0e, 0x00, 0x00} , {2.1, 2.1, 2.1}, {NULL, NULL, NULL} } , /* 5: HP2300c */ {CCD_HP2300, 600, 48, 20, 0, 5368, 180, 180, /* 5376 */ {0x16, 0x00, 0x01, 0x03} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a, 0x00, 0x05} , {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x00, 0xc1, 0x06, 0x0b, 0x10, 0x16} , {2.1, 2.1, 2.1}, {NULL, NULL, NULL} } , /* CANOLIDE35 */ {CCD_CANONLIDE35, 1200, 87, /* (black) */ 87, /* (dummy) */ 0, /* (startxoffset) */ 10400, /* sensor_pixels */ 0, 0, {0x00, 0x00, 0x00, 0x00}, {0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x02 /* TODO(these do no harm, but may be neccessery for CCD) */ }, {0x05, 0x07, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ 0x3a, 0x03, 0x40, /*TODO: bit7 */ 0x00, 0x00, 0x00, 0x00 /*TODO (these do no harm, but may be neccessery for CCD) */ } , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* 7: Strobe XP200 */ {CIS_XP200, 600, 5, 38, 0, 5200, 200, 200, /* 5125 */ {0x16, 0x00, 0x01, 0x03} , {0x14, 0x50, 0x0c, 0x80, 0x0a, 0x28, 0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a, 0x00, 0x05} , {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x00, 0xc1, 0x06, 0x0b, 0x10, 0x16} , {2.1, 2.1, 2.1}, {NULL, NULL, NULL} } , /* HP3670 */ {CCD_HP3670,1200, 48, 16, 0, 10872, 210, 200, {0x00, 0x0a, 0x0b, 0x0d} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x07, 0x20, 0x2a, 0x00, 0x00, 0xc0, 0x43} , {0x0f, 0x13, 0x17, 0x03, 0x07, 0x0b, 0x83, 0x00, 0x15, 0x05, 0x0a, 0x0f, 0x00}, {1.00, 1.00, 1.00}, {NULL, NULL, NULL} } , /* Syscan DP 665 */ {CCD_DP665, 600, 27, /*(black) */ 27, /* (dummy) */ 0, /* (startxoffset) */ 2496, /*sensor_pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x02, 0x04, 0x50, 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ 0x54, 0x03, 0x00, /*TODO: bit7 */ 0x00, 0x00, 0x00, 0x01 /*TODO (these do no harm, but may be neccessery for CCD) */ } , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* Visioneer Roadwarrior */ {CCD_ROADWARRIOR, 600, 27, /*(black) */ 27, /* (dummy) */ 0, /* (startxoffset) */ 5200, /*sensor_pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x02, 0x04, 0x50, 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ 0x54, 0x03, 0x00, /*TODO: bit7 */ 0x00, 0x00, 0x00, 0x01 /*TODO (these do no harm, but may be neccessery for CCD) */ } , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* Pentax DS Mobile 600 */ {CCD_DSMOBILE600, 600, 28, /*(black) */ 28, /* (dummy) */ 0, /* (startxoffset) */ 5200, /*sensor_pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, {0x15, 0x44, 0x15, 0x44, 0x15, 0x44, 0x00, 0x02, 0x04, 0x50, 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ 0x54, 0x03, 0x00, /*TODO: bit7 */ 0x00, 0x00, 0x00, 0x01 /*TODO (these do no harm, but may be neccessery for CCD) */ } , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* 13: Strobe XP300 */ {CCD_XP300, 600, 27, /*(black) */ 27, /* (dummy) */ 0, /* (startxoffset) */ 10240, /*sensor_pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x02, 0x04, 0x50, 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ 0x54, 0x03, 0x00, /*TODO: bit7 */ 0x00, 0x00, 0x00, 0x01 /*TODO (these do no harm, but may be neccessery for CCD) */ } , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* 13: Strobe XP300 */ {CCD_DP685, 600, 27, /*(black) */ 27, /* (dummy) */ 0, /* (startxoffset) */ 5020, /*sensor_pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, {0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x00, 0x02, 0x04, 0x50, 0x10, 0x00, 0x20, 0x02 }, {0x04, 0x05, 0x00, 0x00, 0x00, 0x00, /*[GB](HI|LOW) not needed for cis */ 0x54, 0x03, 0x00, /*TODO: bit7 */ 0x00, 0x00, 0x00, 0x01 /*TODO (these do no harm, but may be neccessery for CCD) */ } , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* CANONLIDE200 */ {CIS_CANONLIDE200, 4800, /* optical resolution */ 87*4, /* black pixels */ 16*4, /* dummy pixels */ 320*8, /* CCD_startx_offset 323 */ 5136*8, 210, 200, {0x00, 0x00, 0x00, 0x00}, /* reg 0x10 - 0x1d */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* EXPR/EXPG/EXPB */ 0x10, 0x08, 0x00, 0xff, 0x34, 0x00, 0x02, 0x04 }, /* reg 0x52 - 0x5e */ {0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xe1, 0x55, 0x00, 0x00, 0x00, 0x41 } , {1.7, 1.7, 1.7}, {NULL, NULL, NULL} } , /* CANONLIDE700 */ {CIS_CANONLIDE700, 4800, /* optical resolution */ 73*8, /* black pixels 73 at 600 dpi */ 16*8, /* dummy pixels */ 384*8, /* CCD_startx_offset 384 at 600 dpi */ 5188*8, /* 8x5570 segments , 5187+1 for rounding */ 210, 200, {0x00, 0x00, 0x00, 0x00}, /* reg 0x10 - 0x1d */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* EXPR/EXPG/EXPB */ 0x10, 0x08, 0x00, 0xff, 0x34, 0x00, 0x02, 0x04 }, /* reg 0x52 - 0x5e */ {0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xe1, 0x55, 0x00, 0x00, 0x00, 0x41 } , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* CANONLIDE100 */ {CIS_CANONLIDE100, 2400, /* optical resolution */ 87*4, /* black pixels */ 16*4, /* dummy pixels 16 */ 320*4, /* 323 */ 5136*4, /* 10272 */ 210, 200, {0x00, 0x00, 0x00, 0x00}, /* reg 0x10 - 0x15 */ {0x01, 0xc1, 0x01, 0x26, 0x00, 0xe5, /* EXPR/EXPG/EXPB */ /* reg 0x16 - 0x1d 0x19=0x50*/ 0x10, 0x08, 0x00, 0x50, 0x34, 0x00, 0x02, 0x04 }, /* reg 0x52 - 0x5e */ {0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xe1, 0x55, 0x00, 0x00, 0x00, 0x41 } , {1.7, 1.7, 1.7}, {NULL, NULL, NULL} } , {CCD_KVSS080, 600, 38, /* black pixels on left */ 38, /* 36 dummy pixels */ 152, 5376, /* 5100-> 5200 */ 160, /* TAU white ref */ 160, /* gain white ref */ /* 08 09 0a 0b */ {0x00, 0x00, 0x00, 0x6a} , /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x1c, 0x00, 0x2a, 0x2c, 0x00, 0x20, 0x04} , /* 18=00 at 600 dpi */ /* 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e */ {0x0c, 0x0f, 0x00, 0x03, 0x06, 0x09, 0x6b, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x23} , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , {CCD_G4050, 4800, 50*8, /* black_pixels */ 58, /* 31 at 600 dpi dummy_pixels 58 at 1200 */ 152, 5360*8, /* 5360 max at 600 dpi */ 160, 160, /* 08 09 0a 0b */ {0x00, 0x00, 0x18, 0x69} , /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d */ {0x2c, 0x09, 0x22, 0xb8, 0x10, 0xf0, 0x33, 0x0c, 0x00, 0x2a, 0x30, 0x00, 0x00, 0x08} , /* 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e */ {0x0b, 0x0e, 0x11, 0x02, 0x05, 0x08, 0x63, 0x00, 0x40, 0x00, 0x00, 0x00, 0x6f} , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , {CCD_CS4400F, 4800, 50*8, /* black_pixels */ 20, /* 31 at 600 dpi dummy_pixels 58 at 1200 */ 152, 5360*8, /* 5360 max at 600 dpi */ 160, 160, /* 08 09 0a 0b */ {0x00, 0x00, 0x18, 0x69} , /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d */ {0x9c, 0x40, 0x9c, 0x40, 0x9c, 0x40, 0x13, 0x0a, 0x10, 0x2a, 0x30, 0x00, 0x00, 0x6b}, /* 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e */ {0x0a, 0x0d, 0x00, 0x03, 0x06, 0x08, 0x5b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f}, {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , {CCD_CS8400F, 4800, 50*8, /* black_pixels */ 20, /* 31 at 600 dpi dummy_pixels 58 at 1200 */ 152, 5360*8, /* 5360 max at 600 dpi */ 160, 160, /* 08 09 0a 0b */ {0x00, 0x00, 0x18, 0x69} , /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d */ {0x9c, 0x40, 0x9c, 0x40, 0x9c, 0x40, 0x13, 0x0a, 0x10, 0x2a, 0x30, 0x00, 0x00, 0x6b}, /* 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e */ {0x0a, 0x0d, 0x00, 0x03, 0x06, 0x08, 0x5b, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f}, {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* HP N6310 */ {CCD_HP_N6310, 2400, 96, 26, 128, 42720, 210, 230, /* 08 09 0a 0b */ {0x00, 0x10, 0x10, 0x0c} , /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x0c, 0x02, 0x2a, 0x30, 0x00, 0x00, 0x08} , /* 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e */ {0x0b, 0x0e, 0x11, 0x02, 0x05, 0x08, 0x63, 0x00, 0x40, 0x00, 0x00, 0x06, 0x6f} , {1.0, 1.0, 1.0}, {NULL, NULL, NULL} } , /* CANONLIDE110 */ {CIS_CANONLIDE110, 2400, /* optical resolution */ 87, /* black pixels */ 16, /* dummy pixels 16 */ 303, /* 303 */ 5168*4, /* total pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, /* reg 0x10 - 0x15 : EXPR, EXPG and EXPB */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg 0x16 - 0x1d */ 0x10, 0x04, 0x00, 0x01, 0x30, 0x00, 0x02, 0x01 }, /* reg 0x52 - 0x5e */ { 0x00, 0x02, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x1a, 0x00, 0xc0, 0x00, 0x00 } , {2.1, 2.1, 2.1}, {NULL, NULL, NULL}} , /* CANONLIDE120 */ {CIS_CANONLIDE120, 2400, /* optical resolution */ 87, /* black pixels */ 16, /* dummy pixels 16 */ 303, /* SEGCNT at 600 DPI by number of segments */ 5104*4, /* total pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, /* reg 0x10 - 0x15 : EXPR, EXPG and EXPB */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg 0x16 - 0x1d */ 0x15, 0x04, 0x00, 0x01, 0x30, 0x00, 0x02, 0x01 }, /* reg 0x52 - 0x5e */ { /* 52 53 54 55 56 57 58 59 */ 0x04, 0x06, 0x00, 0x02, 0x04, 0x04, 0x04, 0x04, /* 5a 5b 5c 5d 5e */ 0x3a, 0x00, 0x00, 0x00, 0x1f } , {2.1, 2.1, 2.1}, {NULL, NULL, NULL}} , /* CANON LIDE 210 sensor */ {CIS_CANONLIDE210, 2400, /* optical resolution */ 87, /* black pixels */ 16, /* dummy pixels 16 */ 303, /* 303 */ 5168*4, /* total pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, /* reg 0x10 - 0x15 : EXPR, EXPG and EXPB */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg 0x16 - 0x1d */ 0x10, 0x04, 0x00, 0x01, 0x30, 0x00, 0x02, 0x01 }, /* reg 0x52 - 0x5e */ { 0x00, 0x02, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x1a, 0x00, 0xc0, 0x00, 0x00 } , {2.1, 2.1, 2.1}, {NULL, NULL, NULL}} , /* CANON LIDE 220 sensor */ {CIS_CANONLIDE220, 2400, /* optical resolution */ 87, /* black pixels */ 16, /* dummy pixels 16 */ 303, /* 303 */ 5168*4, /* total pixels */ 210, 200, {0x00, 0x00, 0x00, 0x00}, /* reg 0x10 - 0x15 : EXPR, EXPG and EXPB */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg 0x16 - 0x1d */ 0x10, 0x04, 0x00, 0x01, 0x30, 0x00, 0x02, 0x01 }, /* reg 0x52 - 0x5e */ { 0x00, 0x02, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x1a, 0x00, 0xc0, 0x00, 0x00 } , {2.1, 2.1, 2.1}, {NULL, NULL, NULL}} , {CCD_PLUSTEK_3600, 1200, 87, /*(black) */ 87, /* (dummy) */ 0, /* (startxoffset) */ 10100, /*sensor_pixels */ 210, 230, {0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x0b, 0x11, 0x2a, 0x00, 0x00, 0x00, 0xc4 /* TODO(these do no harm, but may be neccessery for CCD) */ }, {0x07, 0x0a, 0x0c, 0x00, 0x02, 0x06, /*[GB](HI|LOW) not needed for cis */ 0x22, 0x69, 0x40, /*TODO: bit7 */ 0x00, 0x00, 0x00, 0x02 /*TODO (these do no harm, but may be neccessery for CCD) */ } , {1.0, 1.0, 1.0}, {NULL, NULL, NULL}} , /* Canon Image formula 101 */ {CCD_IMG101, 1200, /* optical resolution */ 31, 31, 0, 10800, 210, 200, {0x60, 0x00, 0x00, 0x8b}, /* reg 0x10 - 0x15 */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* EXPR/EXPG/EXPB */ /* reg 0x16 - 0x1d 0x19=0x50*/ 0xbb, 0x13, 0x10, 0x2a, 0x34, 0x00, 0x20, 0x06 }, /* reg 0x52 - 0x5e */ {0x02, 0x04, 0x06, 0x08, 0x0a, 0x00, 0x59, 0x31, 0x40, 0x00, 0x00, 0x00, 0x1f } , {1.7, 1.7, 1.7}, {NULL, NULL, NULL} } , /* Plustek OpticBook 3800 */ {CCD_PLUSTEK3800, 1200, /* optical resolution */ 31, 31, 0, 10200, 210, 200, {0x60, 0x00, 0x00, 0x8b}, /* reg 0x10 - 0x15 */ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* EXPR/EXPG/EXPB */ /* reg 0x16 - 0x1d 0x19=0x50*/ 0xbb, 0x13, 0x10, 0x2a, 0x34, 0x00, 0x20, 0x06 }, /* reg 0x52 - 0x5e */ {0x02, 0x04, 0x06, 0x08, 0x0a, 0x00, 0x59, 0x31, 0x40, 0x00, 0x00, 0x00, 0x1f } , {1.7, 1.7, 1.7}, {NULL, NULL, NULL} }, /* CANOLIDE80 */ {CIS_CANONLIDE80, 1200, /* real hardware limit is 2400 */ 20, /* black pixels */ 6, /* expdummy 6 */ /* tuned to give 3*8 multiple startx coordinate during shading calibration */ 34, /* CCD_start_xoffset 14=>3, 20=>2 */ 10240, /* 10400, too wide=>10288 in shading data 10240~, 10208 too short for shading, max shading data = 10240 pixels, endpix-startpix=10208 */ 150, 150, {0x00, 0x05, 0x07, 0x09}, /* in fact ,maps to 0x70-0x73 for GL841 */ /* [0x10-0x15] values are initial led exposure values */ /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d*/ {0x10, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04}, {0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x29, 0x69, 0x55, 0x00, 0x00, 0x20, 0x41} , {1.0, 1.0, 1.0}, {NULL, NULL, NULL}} }; /** for General Purpose Output specific settings: * initial GPO value (registers 0x66-0x67/0x6c-0x6d) * GPO enable mask (registers 0x68-0x69/0x6e-0x6f) * The first register is for GPIO9-GPIO16, the second for GPIO1-GPIO8 */ static Genesys_Gpo Gpo[] = { /* UMAX */ {GPO_UMAX, {0x11, 0x00} , {0x51, 0x20} , } , /* Plustek OpticPro S12/ST12 */ {GPO_ST12, {0x11, 0x00} , {0x51, 0x20} , } , /* Plustek OpticPro S24/ST24 */ {GPO_ST24, {0x00, 0x00} , {0x51, 0x20} , } , /* MD5345/MD6471 */ {GPO_5345, {0x30, 0x18} , /* bits 11-12 are for bipolar V-ref input voltage */ {0xa0, 0x18} , } , /* HP2400C */ {GPO_HP2400, {0x30, 0x00} , {0x31, 0x00} , } , /* HP2300C */ {GPO_HP2300, {0x00, 0x00} , {0x00, 0x00} , } , /* CANONLIDE35 */ {GPO_CANONLIDE35, {0x02, 0x80} , {0xef, 0x80} , } , /* 7: XP200 */ {GPO_XP200, {0x30, 0x00} , {0xb0, 0x00} , }, /* HP3670 */ {GPO_HP3670, {0x00, 0x00} , {0x00, 0x00} } , /* 8: XP300 */ {GPO_XP300, {0x09, 0xc6}, {0xbb, 0x00}, } , /* Syscan DP 665 */ { GPO_DP665, {0x18, 0x00},/*0x19,0x00*/ {0xbb, 0x00}, } , /* Syscan DP 685 */ { GPO_DP685, {0x3f, 0x46}, /* 6c, 6d */ {0xfb, 0x00}, /* 6e, 6f */ }, /* CANONLIDE200 */ {GPO_CANONLIDE200, {0xfb, 0x20}, /* 0xfb when idle , 0xf9/0xe9 (1200) when scanning */ {0xff, 0x00}, }, /* CANONLIDE700 */ {GPO_CANONLIDE700, {0xdb, 0xff}, {0xff, 0x80}, }, {GPO_KVSS080, {0xf5, 0x20}, {0x7e, 0xa1}, } , {GPO_G4050, {0x20, 0x00}, {0xfc, 0x00}, } , /* HP N6310 */ {GPO_HP_N6310, {0xa3, 0x00}, {0x7f, 0x00}, } , /* CANONLIDE110 */ {GPO_CANONLIDE110, {0xfb, 0x20}, {0xff, 0x00}, } , /* CANONLIDE120 */ {GPO_CANONLIDE120, {0xfb, 0x20}, {0xff, 0x00}, } , /* CANONLIDE210 */ {GPO_CANONLIDE210, {0xfb, 0x20}, {0xff, 0x00}, } , /* Plustek 3600 */ {GPO_PLUSTEK_3600, {0x02, 0x00}, {0x1e, 0x80}, } /* CanoScan 4400f */ , {GPO_CS4400F, {0x01, 0x7f}, {0xff, 0x00}, } /* CanoScan 8400f */ , {GPO_CS8400F, {0x9a, 0xdf}, {0xfe, 0x60}, } /* Canon Image formula 101 */ , {GPO_IMG101, {0x41, 0xa4}, {0x13, 0xa7} } /* Plustek OpticBook 3800 */ , {GPO_PLUSTEK3800, {0x41, 0xa4}, {0x13, 0xa7} }, /* Canon LiDE 80 */ { GPO_CANONLIDE80, {0x28, 0x90}, /* 6c, 6d */ {0x75, 0x80}, /* 6e, 6f */ } }; static Genesys_Motor Motor[] = { /* UMAX */ {MOTOR_UMAX, 1200, /* motor base steps */ 2400, /* maximum motor resolution */ 1, /* maximum step mode */ 1, /* number of power modes*/ {{{ 11000, /* maximum start speed */ 3000, /* maximum end speed */ 128, /* step count */ 1.0, /* nonlinearity */ }, { 11000, 3000, 128, 1.0, },},}, }, {MOTOR_5345, /* MD5345/6228/6471 */ 1200, 2400, 1, 1, {{{ 2000, 1375, 128, 0.5, }, { 2000, 1375, 128, 0.5, },},}, }, {MOTOR_ST24, /* ST24 */ 2400, 2400, 1, 1, {{{ 2289, 2100, 128, 0.3, }, { 2289, 2100, 128, 0.3, },},}, }, {MOTOR_HP3670, /* HP 3670 */ 1200, 2400, 1, 1, {{{ 11000, /* start speed */ 3000, /* max speed */ 128, /* min steps */ 0.25, }, { 11000, 3000, 128, 0.5, },},}, }, {MOTOR_HP2400, /* HP 2400c */ 1200, 1200, 1, 1, {{{ 11000, /* start speed */ 3000, /* max speed */ 128, /* min steps */ 0.25, }, { 11000, 3000, 128, 0.5, },},}, }, {MOTOR_HP2300, /* HP 2300c */ 600, /* 600/1200 */ 1200, 1, 1, {{{ 3200, 1200, 128, 0.5, }, { 3200, 1200, 128, 0.5, },},}, }, {MOTOR_CANONLIDE35, /* Canon LiDE 35 */ 1200, 2400, 1, 1, {{{ 3500, 1300, 60, 0.8, }, { 3500, 1400, 60, 0.8, },},}, }, {MOTOR_XP200, /* Strobe XP200 */ 600, 600, 1, 1, {{{ 3500, 1300, 60, 0.25, }, { 3500, 1400, 60, 0.5, },},}, }, {MOTOR_XP300, /* 7: Visioneer Strobe XP300 */ 300, 600, 1, 1, {{{ /* works best with GPIO10, GPIO14 off */ 3700, 3700, 2, 0.8, }, { 11000, 11000, 2, 0.8, },},}, }, {MOTOR_DP665, /* Syscan DP 665 */ 750, 1500, 1, 1, {{{ 3000, 2500, 10, 0.8, }, { 11000, 11000, 2, 0.8, },},}, }, {MOTOR_ROADWARRIOR, /* Visioneer Roadwarrior */ 750, 1500, 1, 1, {{{ 3000, 2600, 10, 0.8, }, { 11000, 11000, 2, 0.8, },},}, }, {MOTOR_DSMOBILE_600, /* Pentax DSmobile 600 */ 750, 1500, 2, 1, {{{ 6666, 3700, 8, 0.8, }, { 6666, 3700, 8, 0.8, },},}, }, {MOTOR_CANONLIDE100, /* Canon LiDE 100 */ 1200, 6400, 2, /* maximum step type count */ 1, /* maximum power modes count */ { /* motor slopes */ { /* power mode 0 */ { 3000, 1000, 127, 0.50}, /* full step */ { 3000, 1500, 127, 0.50}, /* half step */ { 3*2712, 3*2712, 16, 0.80}, /* quarter step 0.75*2712 */ }, }, }, {MOTOR_CANONLIDE200, /* Canon LiDE 200 */ 1200, 6400, 2, 1, { /* motor slopes */ { /* power mode 0 */ { 3000, 1000, 127, 0.50}, /* full step */ { 3000, 1500, 127, 0.50}, /* half step */ { 3*2712, 3*2712, 16, 0.80}, /* quarter step 0.75*2712 */ }, }, }, {MOTOR_CANONLIDE700, /* Canon LiDE 700 */ 1200, 6400, 2, 1, { /* motor slopes */ { /* power mode 0 */ { 3000, 1000, 127, 0.50}, /* full step */ { 3000, 1500, 127, 0.50}, /* half step */ { 3*2712, 3*2712, 16, 0.80}, /* quarter step 0.75*2712 */ }, }, }, {MOTOR_KVSS080, 1200, 1200, 2, 1, { /* motor slopes */ { /* power mode 0 */ { 22222, 500, 246, 0.5 }, /* max speed / dpi * base dpi => exposure */ { 22222, 500, 246, 0.5 }, { 22222, 500, 246, 0.5 }, }, }, }, {MOTOR_G4050, 2400, 9600, 2, 1, { /* motor slopes */ { /* power mode 0 */ { 3961, 240, 246, 0.8 }, /* full step */ { 3961, 240, 246, 0.8 }, /* half step */ { 3961, 240, 246, 0.8 }, /* quarter step */ }, }, }, {MOTOR_CS8400F, 2400, 9600, 2, 1, { /* motor slopes */ { /* power mode 0 */ { 3961, 240, 246, 0.8 }, /* full step */ { 3961, 240, 246, 0.8 }, /* half step */ { 3961, 240, 246, 0.8 }, /* quarter step */ }, }, }, {MOTOR_CANONLIDE110, /* Canon LiDE 110 */ 4800, 9600, 1, /* maximum step type count */ 1, /* maximum power modes count */ { /* motor slopes */ { /* power mode 0 */ { 3000, 1000, 256, 0.50}, /* full step */ }, }, }, {MOTOR_CANONLIDE120, /* Canon LiDE 120 */ 4800, 9600, 1, /* maximum step type count */ 1, /* maximum power modes count */ { /* motor slopes */ { /* power mode 0 */ { 3000, 1000, 256, 0.50}, /* full step */ }, }, }, {MOTOR_CANONLIDE210, /* Canon LiDE 210 */ 4800, 9600, 1, /* maximum step type count */ 1, /* maximum power modes count */ { /* motor slopes */ { /* power mode 0 */ { 3000, 1000, 256, 0.50}, /* full step */ }, }, }, {MOTOR_PLUSTEK_3600, /* PLUSTEK 3600 */ 1200, 2400, 1, 1, { { { 3500, 1300, 60, 0.8 }, { 3500, 3250, 60, 0.8 }, }, },}, {MOTOR_IMG101, /* Canon Image Formula 101 */ 600, 1200, 1, 1, { { { 3500, 1300, 60, 0.8 }, { 3500, 3250, 60, 0.8 }, }, },}, {MOTOR_PLUSTEK3800, /* Plustek OpticBook 3800 */ 600, 1200, 1, 1, { { { 3500, 1300, 60, 0.8 }, { 3500, 3250, 60, 0.8 }, }, },}, {MOTOR_CANONLIDE80, 2400, /* 2400 ???? */ 4800, /* 9600 ???? */ 1, /* max step type */ 1, /* power mode count */ { { /* start speed, max end speed, step number */ /* maximum speed (second field) is used to compute exposure as seen by motor */ /* exposure=max speed/ slope dpi * base dpi */ /* 5144 = max pixels at 600 dpi */ /* 1288=(5144+8)*ydpi(=300)/base_dpi(=1200) , where 5152 is exposure */ /* 6440=9660/(1932/1288) */ { 9560, 1912, 31, 0.8 }, }, },}, }; /* here we have the various device settings... */ static Genesys_Model umax_astra_4500_model = { "umax-astra-4500", /* Name */ "UMAX", /* Device vendor string */ "Astra 4500", /* Device model name */ GENESYS_GL646, NULL, {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ {2400, 1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_UMAX, DAC_WOLFSON_UMAX, GPO_UMAX, MOTOR_UMAX, GENESYS_FLAG_UNTESTED, /* Which flags are needed for this scanner? */ /* untested, values set by hmg */ GENESYS_HAS_NO_BUTTONS, /* no buttons supported */ 20, 200 }; static Genesys_Model canon_lide_50_model = { "canon-lide-50", /* Name */ "Canon", /* Device vendor string */ "LiDE 35/40/50", /* Device model name */ GENESYS_GL841, NULL, { 1200, 600, 400, 300, 240, 200, 150, 75, 0}, /* possible x-resolutions */ {2400, 1200, 600, 400, 300, 240, 200, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.42), /* Start of scan area in mm (x) */ SANE_FIX (7.9), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (6.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_CANONLIDE35, DAC_CANONLIDE35, GPO_CANONLIDE35, MOTOR_CANONLIDE35, GENESYS_FLAG_LAZY_INIT | /* Which flags are needed for this scanner? */ GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_WHITE_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_HALF_CCD_MODE, GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_COPY_SW, 280, 400 }; static Genesys_Model panasonic_kvss080_model = { "panasonic-kv-ss080", /* Name */ "Panasonic", /* Device vendor string */ "KV-SS080", /* Device model name */ GENESYS_GL843, NULL, { 600, /* 500, 400,*/ 300, 200, 150, 100, 75, 0}, /* possible x-resolutions */ { 1200, 600, /* 500, 400, */ 300, 200, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (7.2), /* Start of scan area in mm (x) */ SANE_FIX (14.7), /* Start of scan area in mm (y) */ SANE_FIX (217.7), /* Size of scan area in mm (x) */ SANE_FIX (300.0), /* Size of scan area in mm (y) */ SANE_FIX (9.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_KVSS080, DAC_KVSS080, GPO_KVSS080, MOTOR_KVSS080, GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW , 100, 100 }; static Genesys_Model hp4850c_model = { "hewlett-packard-scanjet-4850c", /* Name */ "Hewlett Packard", /* Device vendor string */ "ScanJet 4850C", /* Device model name */ GENESYS_GL843, NULL, {2400, 1200, 600, 400, 300, 200, 150, 100, 0}, {2400, 1200, 600, 400, 300, 200, 150, 100, 0}, {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (7.9), /* Start of scan area in mm (x) */ SANE_FIX (5.9), /* Start of scan area in mm (y) */ SANE_FIX (219.6), /* Size of scan area in mm (x) */ SANE_FIX (314.5), /* Size of scan area in mm (y) */ SANE_FIX (3.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ /* 0 38 76 OK 1200/2400 */ /* 0 24 48 OK [100,600] dpi */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_G4050, DAC_G4050, GPO_G4050, MOTOR_G4050, GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW, 100, 100 }; static Genesys_Model hpg4010_model = { "hewlett-packard-scanjet-g4010", /* Name */ "Hewlett Packard", /* Device vendor string */ "ScanJet G4010", /* Device model name */ GENESYS_GL843, NULL, { 2400, 1200, 600, 400, 300, 200, 150, 100, 0}, { 2400, 1200, 600, 400, 300, 200, 150, 100, 0}, {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (8.0), /* Start of scan area in mm (x) */ SANE_FIX (13.00), /* Start of scan area in mm (y) */ SANE_FIX (217.9), /* Size of scan area in mm (x) 5148 pixels at 600 dpi*/ SANE_FIX (315.0), /* Size of scan area in mm (y) */ SANE_FIX (3.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ /* 0 38 76 OK 1200/2400 */ /* 0 24 48 OK [100,600] dpi */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_G4050, DAC_G4050, GPO_G4050, MOTOR_G4050, GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW, 100, 100 }; static Genesys_Model hpg4050_model = { "hewlett-packard-scanjet-g4050", /* Name */ "Hewlett Packard", /* Device vendor string */ "ScanJet G4050", /* Device model name */ GENESYS_GL843, NULL, { 2400, 1200, 600, 400, 300, 200, 150, 100, 0}, { 2400, 1200, 600, 400, 300, 200, 150, 100, 0}, {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (8.0), /* Start of scan area in mm (x) */ SANE_FIX (13.00), /* Start of scan area in mm (y) */ SANE_FIX (217.9), /* Size of scan area in mm (x) 5148 pixels at 600 dpi*/ SANE_FIX (315.0), /* Size of scan area in mm (y) */ SANE_FIX (3.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (8.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (13.00), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (217.9), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (250.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (40.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ /* 0 38 76 OK 1200/2400 */ /* 0 24 48 OK [100,600] dpi */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_G4050, DAC_G4050, GPO_G4050, MOTOR_G4050, GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW, 100, 100 }; static Genesys_Model canon_4400f_model = { "canon-canoscan-4400f", /* Name */ "Canon", /* Device vendor string */ "Canoscan 4400f", /* Device model name */ GENESYS_GL843, NULL, { 4800, 2400, 1200, 600, 400, 300, 200, 150, 100, 0}, { 4800, 2400, 1200, 600, 400, 300, 200, 150, 100, 0}, {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (6.0), /* Start of scan area in mm (x) */ SANE_FIX (13.00), /* Start of scan area in mm (y) */ SANE_FIX (217.9), /* Size of scan area in mm (x) 5148 pixels at 600 dpi*/ SANE_FIX (315.0), /* Size of scan area in mm (y) */ SANE_FIX (3.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (8.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (13.00), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (217.9), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (250.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (40.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ /* 0 38 76 OK 1200/2400 */ /* 0 24 48 OK [100,600] dpi */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_CS4400F, DAC_G4050, GPO_CS4400F, MOTOR_G4050, GENESYS_FLAG_NO_CALIBRATION | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_FULL_HWDPI_MODE | GENESYS_FLAG_HALF_CCD_MODE | /* actually quarter CCD mode ... */ GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW, 100, 100 }; static Genesys_Model canon_8400f_model = { "canon-canoscan-8400f", /* Name */ "Canon", /* Device vendor string */ "Canoscan 8400f", /* Device model name */ GENESYS_GL843, NULL, { 4800, 2400, 1200, 600, 400, 300, 200, 150, 100, 0}, { 4800, 2400, 1200, 600, 400, 300, 200, 150, 100, 0}, {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (4.0), /* Start of scan area in mm (x) */ SANE_FIX (13.00), /* Start of scan area in mm (y) */ SANE_FIX (217.9), /* Size of scan area in mm (x) 5148 pixels at 600 dpi*/ SANE_FIX (315.0), /* Size of scan area in mm (y) */ SANE_FIX (3.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (8.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (13.00), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (217.9), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (250.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (40.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in line number */ /* 0 38 76 OK 1200/2400 */ /* 0 24 48 OK [100,600] dpi */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_CS8400F, DAC_CS8400F, GPO_CS8400F, MOTOR_CS8400F, GENESYS_FLAG_NO_CALIBRATION | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_FULL_HWDPI_MODE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_COPY_SW, 100, 100 }; static Genesys_Model canon_lide_100_model = { "canon-lide-100", /* Name */ "Canon", /* Device vendor string */ "LiDE 100", /* Device model name */ GENESYS_GL847, NULL, {4800, 2400, 1200, 600, 300, 200, 150, 100, 75, 0}, /* possible x-resolutions */ {4800, 2400, 1200, 600, 300, 200, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (1.1), /* Start of scan area in mm (x) */ SANE_FIX (8.3), /* Start of scan area in mm (y) */ SANE_FIX (216.07), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (1.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE100, DAC_CANONLIDE200, GPO_CANONLIDE200, MOTOR_CANONLIDE100, /* Which flags are needed for this scanner? */ GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_SIS_SENSOR | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_SHADING_REPARK | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW, 50, 400 }; static Genesys_Model canon_lide_110_model = { "canon-lide-110", /* Name */ "Canon", /* Device vendor string */ "LiDE 110", /* Device model name */ GENESYS_GL124, NULL, {4800, 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75, 0}, /* possible x-resolutions */ {4800, 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (2.2), /* Start of scan area in mm (x) */ SANE_FIX (9.0), /* Start of scan area in mm (y) */ SANE_FIX (216.70), /* Size of scan area in mm (x) */ SANE_FIX (300.0), /* Size of scan area in mm (y) */ SANE_FIX (1.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE110, DAC_CANONLIDE110, GPO_CANONLIDE110, MOTOR_CANONLIDE110, GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_SHADING_REPARK | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW, 50, 400 }; static Genesys_Model canon_lide_120_model = { "canon-lide-120", /* Name */ "Canon", /* Device vendor string */ "LiDE 120", /* Device model name */ GENESYS_GL124, NULL, {4800, 2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */ {4800, 2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (8.0), /* Start of scan area in mm (y) */ SANE_FIX (216.0), /* Size of scan area in mm (x) */ SANE_FIX (300.0), /* Size of scan area in mm (y) */ SANE_FIX (1.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE120, DAC_CANONLIDE120, GPO_CANONLIDE120, MOTOR_CANONLIDE120, GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_SHADING_REPARK | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW, 50, 400 }; static Genesys_Model canon_lide_210_model = { "canon-lide-210", /* Name */ "Canon", /* Device vendor string */ "LiDE 210", /* Device model name */ GENESYS_GL124, NULL, {4800, 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75, 0}, /* possible x-resolutions */ {4800, 2400, 1200, 600, /* 400,*/ 300, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (2.2), /* Start of scan area in mm (x) */ SANE_FIX (8.7), /* Start of scan area in mm (y) */ SANE_FIX (216.70), /* Size of scan area in mm (x) */ SANE_FIX (297.5), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE210, DAC_CANONLIDE110, GPO_CANONLIDE210, MOTOR_CANONLIDE210, GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_SHADING_REPARK | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_EXTRA_SW, 60, 400 }; static Genesys_Model canon_lide_220_model = { "canon-lide-220", /* Name */ "Canon", /* Device vendor string */ "LiDE 220", /* Device model name */ GENESYS_GL124, /* or a compatible one */ NULL, {4800, 2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */ {4800, 2400, 1200, 600, 300, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (2.2), /* Start of scan area in mm (x) */ SANE_FIX (8.7), /* Start of scan area in mm (y) */ SANE_FIX (216.70), /* Size of scan area in mm (x) */ SANE_FIX (297.5), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE220, DAC_CANONLIDE110, GPO_CANONLIDE210, MOTOR_CANONLIDE210, GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_SHADING_REPARK | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_EXTRA_SW, 60, 400 }; static Genesys_Model canon_5600f_model = { "canon-5600f", /* Name */ "Canon", /* Device vendor string */ "5600F", /* Device model name */ GENESYS_GL847, NULL, {1200, 600, 400, 300, 200, 150, 100, 75, 0}, /* possible x-resolutions */ {1200, 600, 400, 300, 200, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (1.1), /* Start of scan area in mm (x) */ SANE_FIX (8.3), /* Start of scan area in mm (y) */ SANE_FIX (216.07), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (3.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE200, DAC_CANONLIDE200, GPO_CANONLIDE200, MOTOR_CANONLIDE200, GENESYS_FLAG_UNTESTED /* not working yet */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_SIS_SENSOR | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW, 50, 400 }; static Genesys_Model canon_lide_700f_model = { "canon-lide-700f", /* Name */ "Canon", /* Device vendor string */ "LiDE 700F", /* Device model name */ GENESYS_GL847, NULL, {4800, 2400, 1200, 600, 300, 200, 150, 100, 75, 0}, /* possible x-resolutions */ {4800, 2400, 1200, 600, 300, 200, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.1), /* Start of scan area in mm (x) */ SANE_FIX (8.1), /* Start of scan area in mm (y) */ SANE_FIX (216.07), /* Size of scan area in mm (x) */ SANE_FIX (297.0), /* Size of scan area in mm (y) */ SANE_FIX (1.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE700, DAC_CANONLIDE700, GPO_CANONLIDE700, MOTOR_CANONLIDE700, GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_SIS_SENSOR | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_SHADING_REPARK | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW, 70, 400 }; static Genesys_Model canon_lide_200_model = { "canon-lide-200", /* Name */ "Canon", /* Device vendor string */ "LiDE 200", /* Device model name */ GENESYS_GL847, NULL, {4800, 2400, 1200, 600, 300, 200, 150, 100, 75, 0}, /* possible x-resolutions */ {4800, 2400, 1200, 600, 300, 200, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (1.1), /* Start of scan area in mm (x) */ SANE_FIX (8.3), /* Start of scan area in mm (y) */ SANE_FIX (216.07), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE200, DAC_CANONLIDE200, GPO_CANONLIDE200, MOTOR_CANONLIDE200, GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_SIS_SENSOR | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_SHADING_REPARK | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_FILE_SW, 50, 400 }; static Genesys_Model canon_lide_60_model = { "canon-lide-60", /* Name */ "Canon", /* Device vendor string */ "LiDE 60", /* Device model name */ GENESYS_GL841, NULL, {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ {2400, 1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.42), /* Start of scan area in mm (x) */ SANE_FIX (7.9), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (6.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_CANONLIDE35, DAC_CANONLIDE35, GPO_CANONLIDE35, MOTOR_CANONLIDE35, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_WHITE_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_HALF_CCD_MODE, GENESYS_HAS_NO_BUTTONS, /* no buttons supported */ 300, 400 }; /* this is completely untested -- hmg */ static Genesys_Model canon_lide_80_model = { "canon-lide-80", /* Name */ "Canon", /* Device vendor string */ "LiDE 80", /* Device model name */ GENESYS_GL841, NULL, { 1200, 600, 400, 300, 240, 150, 100, 75, 0}, /* possible x-resolutions */ {2400, 1200, 600, 400, 300, 240, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.42), /* Start of scan area in mm (x) 0.42 */ SANE_FIX (7.90), /* Start of scan area in mm (y) 7.90 */ SANE_FIX (216.07), /* Size of scan area in mm (x) 218.00 */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (4.5), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CIS_CANONLIDE80, DAC_CANONLIDE80, GPO_CANONLIDE80, MOTOR_CANONLIDE80, GENESYS_FLAG_LAZY_INIT | /* Which flags are needed for this scanner? */ GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_WHITE_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_HALF_CCD_MODE, GENESYS_HAS_SCAN_SW | GENESYS_HAS_FILE_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_COPY_SW, 160, /* 280 @2400 */ 400 }; static Genesys_Model hp2300c_model = { "hewlett-packard-scanjet-2300c", /* Name */ "Hewlett Packard", /* Device vendor string */ "ScanJet 2300c", /* Device model name */ GENESYS_GL646, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions, motor can go up to 1200 dpi */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (2.0), /* Start of scan area in mm (x_offset) */ SANE_FIX (7.5), /* Start of scan area in mm (y_offset) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (295.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 16, 8, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_HP2300, DAC_WOLFSON_HP2300, GPO_HP2300, MOTOR_HP2300, GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_SEARCH_START | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW, 40, 132 }; static Genesys_Model hp2400c_model = { "hewlett-packard-scanjet-2400c", /* Name */ "Hewlett Packard", /* Device vendor string */ "ScanJet 2400c", /* Device model name */ GENESYS_GL646, NULL, {1200, 600, 300, 150, 100, 50, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 100, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (6.5), /* Start of scan area in mm (x) */ SANE_FIX (2.5), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (297.2), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_HP2400, DAC_WOLFSON_HP2400, GPO_HP2400, MOTOR_HP2400, GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_SCAN_SW, 20, 132 }; static Genesys_Model visioneer_xp200_model = { "visioneer-strobe-xp200", /* Name */ "Visioneer", /* Device vendor string */ "Strobe XP200", /* Device model name */ GENESYS_GL646, NULL, {600, 300, 200, 100, 75, 0}, /* possible x-resolutions */ {600, 300, 200, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.5), /* Start of scan area in mm (x) */ SANE_FIX (16.0), /* Start of scan area in mm (y) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (297.2), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CIS_XP200, DAC_AD_XP200, /* Analog Device frontend */ GPO_XP200, MOTOR_XP200, GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 120, 132 }; static Genesys_Model hp3670c_model = { "hewlett-packard-scanjet-3670c", /* Name */ "Hewlett Packard", /* Device vendor string */ "ScanJet 3670c", /* Device model name */ GENESYS_GL646, NULL, {1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (8.5), /* Start of scan area in mm (x) */ SANE_FIX (11.0), /* Start of scan area in mm (y) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (300.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (104.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (55.6), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (25.6), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (78.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (76.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_HP3670, DAC_WOLFSON_HP3670, GPO_HP3670, MOTOR_HP3670, GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_XPA | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_SCAN_SW, 20, 200 }; static Genesys_Model plustek_st12_model = { "plustek-opticpro-st12", /* Name */ "Plustek", /* Device vendor string */ "OpticPro ST12", /* Device model name */ GENESYS_GL646, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_ST12, DAC_WOLFSON_ST12, GPO_ST12, MOTOR_UMAX, GENESYS_FLAG_UNTESTED | GENESYS_FLAG_14BIT_GAMMA, /* Which flags are needed for this scanner? */ GENESYS_HAS_NO_BUTTONS, /* no buttons supported */ 20, 200 }; static Genesys_Model plustek_st24_model = { "plustek-opticpro-st24", /* Name */ "Plustek", /* Device vendor string */ "OpticPro ST24", /* Device model name */ GENESYS_GL646, NULL, {1200, 600, 300, 150, 75, 0}, /* possible x-resolutions */ {2400, 1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (3.5), /* Start of scan area in mm (x) */ SANE_FIX (7.5), /* Start of scan area in mm (y) */ SANE_FIX (218.0), /* Size of scan area in mm (x) */ SANE_FIX (299.0), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (1.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 8, 16, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_BGR, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_ST24, DAC_WOLFSON_ST24, GPO_ST24, MOTOR_ST24, GENESYS_FLAG_UNTESTED | GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_SEARCH_START | GENESYS_FLAG_OFFSET_CALIBRATION, GENESYS_HAS_NO_BUTTONS, /* no buttons supported */ 20, 200 }; static Genesys_Model medion_md5345_model = { "medion-md5345-model", /* Name */ "Medion", /* Device vendor string */ "MD5345/MD6228/MD6471", /* Device model name */ GENESYS_GL646, NULL, {1200, 600, 400, 300, 200, 150, 100, 75, 50, 0}, /* possible x-resolutions */ {2400, 1200, 600, 400, 300, 200, 150, 100, 75, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX ( 0.30), /* Start of scan area in mm (x) */ SANE_FIX ( 0.80), /* 2.79 < Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (296.4), /* Size of scan area in mm (y) */ SANE_FIX (0.00), /* Start of white strip in mm (y) */ SANE_FIX (0.00), /* Start of black mark in mm (x) */ SANE_FIX (0.00), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.00), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (0.00), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (0.00), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.00), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_5345, DAC_WOLFSON_5345, GPO_5345, MOTOR_5345, GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_SEARCH_START | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_SHADING_NO_MOVE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_POWER_SW | GENESYS_HAS_OCR_SW | GENESYS_HAS_SCAN_SW, 40, 200 }; static Genesys_Model visioneer_xp300_model = { "visioneer-strobe-xp300", /* Name */ "Visioneer", /* Device vendor string */ "Strobe XP300", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (1.0), /* Start of scan area in mm (y) */ SANE_FIX (435.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (26.5), /* Size of scan area after paper sensor stops sensing document in mm */ /* this is larger than needed -- accounts for second sensor head, which is a calibration item */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_XP300, DAC_WOLFSON_XP300, GPO_XP300, MOTOR_XP300, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model syscan_docketport_665_model = { "syscan-docketport-665", /* Name */ "Syscan/Ambir", /* Device vendor string */ "DocketPORT 665", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (0.0), /* Start of scan area in mm (y) */ SANE_FIX (108.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (17.5), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_DP665, DAC_WOLFSON_XP300, GPO_DP665, MOTOR_DP665, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model visioneer_roadwarrior_model = { "visioneer-roadwarrior", /* Name */ "Visioneer", /* Device vendor string */ "Readwarrior", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (0.0), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_ROADWARRIOR, DAC_WOLFSON_XP300, GPO_DP665, MOTOR_ROADWARRIOR, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model syscan_docketport_465_model = { "syscan-docketport-465", /* Name */ "Syscan", /* Device vendor string */ "DocketPORT 465", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (0.0), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_ROADWARRIOR, DAC_WOLFSON_XP300, GPO_DP665, MOTOR_ROADWARRIOR, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_NO_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_UNTESTED, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW, 300, 400 }; static Genesys_Model visioneer_xp100_r3_model = { "visioneer-xp100-revision3", /* Name */ "Visioneer", /* Device vendor string */ "XP100 Revision 3", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (0.0), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_ROADWARRIOR, DAC_WOLFSON_XP300, GPO_DP665, MOTOR_ROADWARRIOR, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model pentax_dsmobile_600_model = { "pentax-dsmobile-600", /* Name */ "Pentax", /* Device vendor string */ "DSmobile 600", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (0.0), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_DSMOBILE600, DAC_WOLFSON_DSM600, GPO_DP665, MOTOR_DSMOBILE_600, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model syscan_docketport_467_model = { "syscan-docketport-467", /* Name */ "Syscan", /* Device vendor string */ "DocketPORT 467", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (0.0), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_DSMOBILE600, DAC_WOLFSON_DSM600, GPO_DP665, MOTOR_DSMOBILE_600, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model syscan_docketport_685_model = { "syscan-docketport-685", /* Name */ "Syscan/Ambir", /* Device vendor string */ "DocketPORT 685", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (1.0), /* Start of scan area in mm (y) */ SANE_FIX (212.0), /* Size of scan area in mm (x) */ SANE_FIX (500), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (26.5), /* Size of scan area after paper sensor stops sensing document in mm */ /* this is larger than needed -- accounts for second sensor head, which is a calibration item */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_DP685, DAC_WOLFSON_DSM600, GPO_DP685, MOTOR_XP300, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model syscan_docketport_485_model = { "syscan-docketport-485", /* Name */ "Syscan/Ambir", /* Device vendor string */ "DocketPORT 485", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (1.0), /* Start of scan area in mm (y) */ SANE_FIX (435.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (26.5), /* Size of scan area after paper sensor stops sensing document in mm */ /* this is larger than needed -- accounts for second sensor head, which is a calibration item */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_XP300, DAC_WOLFSON_XP300, GPO_XP300, MOTOR_XP300, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model dct_docketport_487_model = { "dct-docketport-487", /* Name */ "DCT", /* Device vendor string */ "DocketPORT 487", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.0), /* Start of scan area in mm (x) */ SANE_FIX (1.0), /* Start of scan area in mm (y) */ SANE_FIX (435.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (26.5), /* Size of scan area after paper sensor stops sensing document in mm */ /* this is larger than needed -- accounts for second sensor head, which is a calibration item */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_XP300, DAC_WOLFSON_XP300, GPO_XP300, MOTOR_XP300, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_UNTESTED, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model visioneer_7100_model = { "visioneer-7100-model", /* Name */ "Visioneer", /* Device vendor string */ "OneTouch 7100", /* Device model name */ GENESYS_GL646, NULL, {1200, 600, 400, 300, 200, 150, 100, 75, 50, 0}, /* possible x-resolutions */ {2400, 1200, 600, 400, 300, 200, 150, 100, 75, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX ( 4.00), /* Start of scan area in mm (x) */ SANE_FIX ( 0.80), /* 2.79 < Start of scan area in mm (y) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (296.4), /* Size of scan area in mm (y) */ SANE_FIX (0.00), /* Start of white strip in mm (y) */ SANE_FIX (0.00), /* Start of black mark in mm (x) */ SANE_FIX (0.00), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.00), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (0.00), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (0.00), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.00), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ /* 48, 24, 0, */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_5345, DAC_WOLFSON_5345, GPO_5345, MOTOR_5345, GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_SEARCH_START | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_POWER_SW | GENESYS_HAS_OCR_SW | GENESYS_HAS_SCAN_SW, 40, 200 }; static Genesys_Model xerox_2400_model = { "xerox-2400-model", /* Name */ "Xerox", /* Device vendor string */ "OneTouch 2400", /* Device model name */ GENESYS_GL646, NULL, {1200, 600, 400, 300, 200, 150, 100, 75, 50, 0}, /* possible x-resolutions */ {2400, 1200, 600, 400, 300, 200, 150, 100, 75, 50, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX ( 4.00), /* Start of scan area in mm (x) */ SANE_FIX ( 0.80), /* 2.79 < Start of scan area in mm (y) */ SANE_FIX (215.9), /* Size of scan area in mm (x) */ SANE_FIX (296.4), /* Size of scan area in mm (y) */ SANE_FIX (0.00), /* Start of white strip in mm (y) */ SANE_FIX (0.00), /* Start of black mark in mm (x) */ SANE_FIX (0.00), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.00), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (0.00), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (0.00), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.00), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 48, 24, 0, /* RGB CCD Line-distance correction in pixel */ /* 48, 24, 0, */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_5345, DAC_WOLFSON_5345, GPO_5345, MOTOR_5345, GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_SEARCH_START | GENESYS_FLAG_STAGGERED_LINE | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_COPY_SW | GENESYS_HAS_EMAIL_SW | GENESYS_HAS_POWER_SW | GENESYS_HAS_OCR_SW | GENESYS_HAS_SCAN_SW, 40, 200 }; static Genesys_Model xerox_travelscanner_model = { "xerox-travelscanner", /* Name */ "Xerox", /* Device vendor string */ "Travelscanner 100", /* Device model name */ GENESYS_GL841, NULL, {600, 300, 150, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (4.0), /* Start of scan area in mm (x) */ SANE_FIX (0.0), /* Start of scan area in mm (y) */ SANE_FIX (220.0), /* Size of scan area in mm (x) */ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (16.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_TRUE, /* Is this a CIS scanner? */ SANE_TRUE, /* Is this a sheetfed scanner? */ CCD_ROADWARRIOR, DAC_WOLFSON_XP300, GPO_DP665, MOTOR_ROADWARRIOR, GENESYS_FLAG_LAZY_INIT /* Which flags are needed for this scanner? */ | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_DARK_CALIBRATION, GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE, 100, 400 }; static Genesys_Model plustek_3600_model = { "plustek-opticbook-3600", /* Name */ "PLUSTEK", /* Device vendor string */ "OpticBook 3600", /* Device model name */ GENESYS_GL841, NULL, {/*1200,*/ 600, 400, 300, 200, 150, 100, 75, 0}, /* possible x-resolutions */ {/*2400,*/ 1200, 600, 400, 300, 200, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (0.42),/*SANE_FIX (0.42), Start of scan area in mm (x) */ SANE_FIX (6.75),/*SANE_FIX (7.9), Start of scan area in mm (y) */ SANE_FIX (216.0),/*SANE_FIX (216.0), Size of scan area in mm (x) */ SANE_FIX (297.0),/*SANE_FIX (297.0), Size of scan area in mm (y) */ SANE_FIX (0.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_PLUSTEK_3600, DAC_PLUSTEK_3600, GPO_PLUSTEK_3600, MOTOR_PLUSTEK_3600, GENESYS_FLAG_UNTESTED /* not fully working yet */ | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_HALF_CCD_MODE,/* | GENESYS_FLAG_NO_CALIBRATION,*/ GENESYS_HAS_NO_BUTTONS, 7, 200 }; static Genesys_Model hpn6310_model = { "hewlett-packard-scanjet-N6310", /* Name */ "Hewlett Packard", /* Device vendor string */ "ScanJet N6310", /* Device model name */ GENESYS_GL847, NULL, { 2400, 1200, 600, 400, 300, 200, 150, 100, 75, 0}, { 2400, 1200, 600, 400, 300, 200, 150, 100, 75, 0}, {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (6), /* Start of scan area in mm (x) */ SANE_FIX (2), /* Start of scan area in mm (y) */ SANE_FIX (216), /* Size of scan area in mm (x) 5148 pixels at 600 dpi*/ SANE_FIX (511), /* Size of scan area in mm (y) */ SANE_FIX (3.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (100.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 0, 0, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_HP_N6310, DAC_CANONLIDE200, /*Not defined yet for N6310 */ GPO_HP_N6310, MOTOR_CANONLIDE200, /*Not defined yet for N6310 */ GENESYS_FLAG_UNTESTED /* not fully working yet */ | GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_14BIT_GAMMA | GENESYS_FLAG_DARK_CALIBRATION | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_NO_CALIBRATION, /* | GENESYS_FLAG_HALF_CCD_MODE,*/ GENESYS_HAS_NO_BUTTONS, 100, 100 }; static Genesys_Model plustek_3800_model = { "plustek-opticbook-3800", /* Name */ "PLUSTEK", /* Device vendor string */ "OpticBook 3800", /* Device model name */ GENESYS_GL845, NULL, {1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (7.2), /* Start of scan area in mm (x) */ SANE_FIX (14.7), /* Start of scan area in mm (y) */ SANE_FIX (217.7), /* Size of scan area in mm (x) */ SANE_FIX (300.0), /* Size of scan area in mm (y) */ SANE_FIX (9.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_PLUSTEK3800, DAC_PLUSTEK3800, GPO_PLUSTEK3800, MOTOR_PLUSTEK3800, GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_NO_BUTTONS, /* TODO there are 4 buttons to support */ 100, 100 }; static Genesys_Model canon_formula101_model = { "canon-image-formula-101", /* Name */ "Canon", /* Device vendor string */ "Image Formula 101", /* Device model name */ GENESYS_GL846, NULL, {1200, 600, 300, 150, 100, 75, 0}, /* possible x-resolutions */ {1200, 600, 300, 150, 100, 75, 0}, /* possible y-resolutions */ {16, 8, 0}, /* possible depths in gray mode */ {16, 8, 0}, /* possible depths in color mode */ SANE_FIX (7.2), /* Start of scan area in mm (x) */ SANE_FIX (14.7), /* Start of scan area in mm (y) */ SANE_FIX (217.7), /* Size of scan area in mm (x) */ SANE_FIX (300.0), /* Size of scan area in mm (y) */ SANE_FIX (9.0), /* Start of white strip in mm (y) */ SANE_FIX (0.0), /* Start of black mark in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Start of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (x) */ SANE_FIX (0.0), /* Size of scan area in TA mode in mm (y) */ SANE_FIX (0.0), /* Start of white strip in TA mode in mm (y) */ SANE_FIX (0.0), /* Size of scan area after paper sensor stops sensing document in mm */ SANE_FIX (0.0), /* Amount of feeding needed to eject document after finishing scanning in mm */ 0, 24, 48, /* RGB CCD Line-distance correction in pixel */ COLOR_ORDER_RGB, /* Order of the CCD/CIS colors */ SANE_FALSE, /* Is this a CIS scanner? */ SANE_FALSE, /* Is this a sheetfed scanner? */ CCD_IMG101, DAC_IMG101, GPO_IMG101, MOTOR_IMG101, GENESYS_FLAG_LAZY_INIT | GENESYS_FLAG_SKIP_WARMUP | GENESYS_FLAG_OFFSET_CALIBRATION | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_NO_BUTTONS , 100, 100 }; static Genesys_USB_Device_Entry genesys_usb_device_list[] = { /* GL646 devices */ {0x03f0, 0x0901, &hp2300c_model}, {0x03f0, 0x0a01, &hp2400c_model}, {0x03f0, 0x1405, &hp3670c_model}, {0x0461, 0x0377, &medion_md5345_model}, {0x04a7, 0x0229, &visioneer_7100_model}, {0x0461, 0x038b, &xerox_2400_model}, {0x04a7, 0x0426, &visioneer_xp200_model}, {0x0638, 0x0a10, &umax_astra_4500_model}, {0x07b3, 0x0600, &plustek_st12_model}, {0x07b3, 0x0601, &plustek_st24_model}, /* GL841 devices */ {0x04a7, 0x0474, &visioneer_xp300_model}, {0x04a7, 0x0494, &visioneer_roadwarrior_model}, {0x04a7, 0x049b, &visioneer_xp100_r3_model}, {0x04a7, 0x04ac, &xerox_travelscanner_model}, {0x04a9, 0x2213, &canon_lide_50_model}, {0x04a9, 0x221c, &canon_lide_60_model}, {0x04a9, 0x2214, &canon_lide_80_model}, {0x07b3, 0x0900, &plustek_3600_model}, {0x0a17, 0x3210, &pentax_dsmobile_600_model}, {0x04f9, 0x2038, &pentax_dsmobile_600_model}, /* clone, only usb id is different */ {0x0a82, 0x4800, &syscan_docketport_485_model}, {0x0a82, 0x4802, &syscan_docketport_465_model}, {0x0a82, 0x4803, &syscan_docketport_665_model}, {0x0a82, 0x480c, &syscan_docketport_685_model}, {0x1dcc, 0x4810, &dct_docketport_487_model}, {0x1dcc, 0x4812, &syscan_docketport_467_model}, /* GL843 devices */ {0x04da, 0x100f, &panasonic_kvss080_model}, {0x03f0, 0x1b05, &hp4850c_model}, {0x03f0, 0x4505, &hpg4010_model}, {0x03f0, 0x4605, &hpg4050_model}, {0x04a9, 0x2228, &canon_4400f_model}, {0x04a9, 0x221e, &canon_8400f_model}, /* GL845 devices */ {0x07b3, 0x1300, &plustek_3800_model}, /* GL846 devices */ {0x1083, 0x162e, &canon_formula101_model}, /* GL847 devices */ {0x04a9, 0x1904, &canon_lide_100_model}, {0x04a9, 0x1905, &canon_lide_200_model}, {0x04a9, 0x1906, &canon_5600f_model}, {0x04a9, 0x1907, &canon_lide_700f_model}, {0x03f0, 0x4705, &hpn6310_model}, /* GL124 devices */ {0x04a9, 0x1909, &canon_lide_110_model}, {0x04a9, 0x190e, &canon_lide_120_model}, {0x04a9, 0x190a, &canon_lide_210_model}, {0x04a9, 0x190f, &canon_lide_220_model}, {0, 0, NULL} }; #define MAX_SCANNERS (sizeof(genesys_usb_device_list) / \ sizeof(genesys_usb_device_list[0])) sane-backends-1.0.27/backend/coolscan2.c0000664000175000017500000023626412775312260014662 00000000000000/* ========================================================================= */ /* SANE - Scanner Access Now Easy. coolscan2.c , version 0.1.8 This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file implements a SANE backend for Nikon Coolscan film scanners. Written by András Major (andras@users.sourceforge.net), 2001-2002. The developers wish to express their thanks to Nikon Corporation for providing technical information and thus making this backend possible. */ /* ========================================================================= */ /* ========================================================================= */ /* Revision log: 0.1.9, 20/10/2005, ariel: added support for the LS-50/5000 0.1.8, 27/09/2002, andras: added subframe and load options 0.1.7, 22/08/2002, andras: added exposure correction option and hack for LS-40 IR readout 0.1.6, 14/06/2002, andras: types etc. fixed, fixes for LS-8000 0.1.5, 26/04/2002, andras: lots of minor fixes related to saned 0.1.4, 22/04/2002, andras: first version to be included in SANE CVS */ /* ========================================================================= */ #ifdef _AIX # include "../include/lalloca.h" /* MUST come first for AIX! */ #endif #include "../include/sane/config.h" #include "../include/lalloca.h" #include #include #include #include #include #include #include /* #include #include */ #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_scsi.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_debug.h" #include "../include/sane/sanei_config.h" #define BACKEND_NAME coolscan2 #include "../include/sane/sanei_backend.h" /* must be last */ #define CS2_VERSION_MAJOR 0 #define CS2_VERSION_MINOR 1 #define CS2_REVISION 8 #define CS2_CONFIG_FILE "coolscan2.conf" #define WSIZE (sizeof (SANE_Word)) /* #define CS2_BLEEDING_EDGE */ /* ========================================================================= */ /* typedefs */ typedef enum { CS2_TYPE_UNKOWN, CS2_TYPE_LS30, CS2_TYPE_LS40, CS2_TYPE_LS50, CS2_TYPE_LS2000, CS2_TYPE_LS4000, CS2_TYPE_LS5000, CS2_TYPE_LS8000 } cs2_type_t; typedef enum { CS2_INTERFACE_UNKNOWN, CS2_INTERFACE_SCSI, /* includes IEEE1394 via SBP2 */ CS2_INTERFACE_USB } cs2_interface_t; typedef enum { CS2_PHASE_NONE = 0x00, CS2_PHASE_STATUS = 0x01, CS2_PHASE_OUT = 0x02, CS2_PHASE_IN = 0x03, CS2_PHASE_BUSY = 0x04 } cs2_phase_t; typedef enum { CS2_SCAN_NORMAL, CS2_SCAN_AE, CS2_SCAN_AE_WB } cs2_scan_t; typedef enum { CS2_INFRARED_OFF, CS2_INFRARED_IN, CS2_INFRARED_OUT } cs2_infrared_t; typedef enum { CS2_STATUS_READY = 0, CS2_STATUS_BUSY = 1, CS2_STATUS_NO_DOCS = 2, CS2_STATUS_PROCESSING = 4, CS2_STATUS_ERROR = 8, CS2_STATUS_REISSUE = 16, CS2_STATUS_ALL = 31 /* sum of all others */ } cs2_status_t; typedef enum { CS2_OPTION_NUM = 0, CS2_OPTION_PREVIEW, CS2_OPTION_NEGATIVE, CS2_OPTION_INFRARED, CS2_OPTION_SAMPLES_PER_SCAN, CS2_OPTION_DEPTH, CS2_OPTION_EXPOSURE, CS2_OPTION_EXPOSURE_R, CS2_OPTION_EXPOSURE_G, CS2_OPTION_EXPOSURE_B, CS2_OPTION_SCAN_AE, CS2_OPTION_SCAN_AE_WB, CS2_OPTION_LUT_R, CS2_OPTION_LUT_G, CS2_OPTION_LUT_B, CS2_OPTION_RES, CS2_OPTION_RESX, CS2_OPTION_RESY, CS2_OPTION_RES_INDEPENDENT, CS2_OPTION_PREVIEW_RESOLUTION, CS2_OPTION_FRAME, CS2_OPTION_SUBFRAME, CS2_OPTION_XMIN, CS2_OPTION_XMAX, CS2_OPTION_YMIN, CS2_OPTION_YMAX, CS2_OPTION_LOAD, CS2_OPTION_EJECT, CS2_OPTION_RESET, CS2_OPTION_FOCUS_ON_CENTRE, CS2_OPTION_FOCUS, CS2_OPTION_AUTOFOCUS, CS2_OPTION_FOCUSX, CS2_OPTION_FOCUSY, CS2_N_OPTIONS /* must be last -- counts number of enum items */ } cs2_option_t; typedef unsigned int cs2_pixel_t; typedef struct { /* interface */ cs2_interface_t interface; int fd; SANE_Byte *send_buf, *recv_buf; size_t send_buf_size, recv_buf_size; size_t n_cmd, n_send, n_recv; /* device characteristics */ char vendor_string[9], product_string[17], revision_string[5]; cs2_type_t type; int maxbits; unsigned int resx_optical, resx_min, resx_max, *resx_list, resx_n_list; unsigned int resy_optical, resy_min, resy_max, *resy_list, resy_n_list; unsigned long boundaryx, boundaryy; unsigned long frame_offset; unsigned int unit_dpi; double unit_mm; int n_frames; int focus_min, focus_max; /* settings */ SANE_Bool preview, negative, infrared; int samples_per_scan, depth, real_depth, bytes_per_pixel, shift_bits, n_colour_in, n_colour_out; cs2_pixel_t n_lut; cs2_pixel_t *lut_r, *lut_g, *lut_b, *lut_neutral; unsigned long resx, resy, res, res_independent, res_preview; unsigned long xmin, xmax, ymin, ymax; int i_frame; double subframe; unsigned int real_resx, real_resy, real_pitchx, real_pitchy; unsigned long real_xoffset, real_yoffset, real_width, real_height, logical_width, logical_height; int odd_padding; int block_padding; double exposure, exposure_r, exposure_g, exposure_b; unsigned long real_exposure[10]; SANE_Bool focus_on_centre; unsigned long focusx, focusy, real_focusx, real_focusy; int focus; /* status */ SANE_Bool scanning; cs2_infrared_t infrared_stage, infrared_next; SANE_Byte *infrared_buf; size_t n_infrared_buf, infrared_index; SANE_Byte *line_buf; ssize_t n_line_buf, i_line_buf; unsigned long sense_key, sense_asc, sense_ascq, sense_info; unsigned long sense_code; cs2_status_t status; size_t xfer_position, xfer_bytes_total; /* SANE stuff */ SANE_Option_Descriptor option_list[CS2_N_OPTIONS]; } cs2_t; /* ========================================================================= */ /* prototypes */ static SANE_Status cs2_open (const char *device, cs2_interface_t interface, cs2_t ** sp); static void cs2_close (cs2_t * s); static SANE_Status cs2_attach (const char *dev); static SANE_Status cs2_scsi_sense_handler (int fd, u_char * sense_buffer, void *arg); static SANE_Status cs2_parse_sense_data (cs2_t * s); static void cs2_init_buffer (cs2_t * s); static SANE_Status cs2_pack_byte (cs2_t * s, SANE_Byte byte); static SANE_Status cs2_parse_cmd (cs2_t * s, char *text); static SANE_Status cs2_grow_send_buffer (cs2_t * s); static SANE_Status cs2_issue_cmd (cs2_t * s); static cs2_phase_t cs2_phase_check (cs2_t * s); static SANE_Status cs2_set_boundary (cs2_t *s); static SANE_Status cs2_scanner_ready (cs2_t * s, int flags); static SANE_Status cs2_page_inquiry (cs2_t * s, int page); static SANE_Status cs2_full_inquiry (cs2_t * s); static SANE_Status cs2_execute (cs2_t * s); static SANE_Status cs2_load (cs2_t * s); static SANE_Status cs2_eject (cs2_t * s); static SANE_Status cs2_reset (cs2_t * s); static SANE_Status cs2_focus (cs2_t * s); static SANE_Status cs2_autofocus (cs2_t * s); static SANE_Status cs2_get_exposure (cs2_t * s); static SANE_Status cs2_convert_options (cs2_t * s); static SANE_Status cs2_scan (cs2_t * s, cs2_scan_t type); static void *cs2_xmalloc (size_t size); static void *cs2_xrealloc (void *p, size_t size); static void cs2_xfree (const void *p); /* ========================================================================= */ /* global variables */ static int cs2_colour_list[] = { 1, 2, 3, 9 }; static SANE_Device **device_list = NULL; static int n_device_list = 0; static cs2_interface_t try_interface = CS2_INTERFACE_UNKNOWN; static int open_devices = 0; /* ========================================================================= */ /* SANE entry points */ SANE_Status sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize) { DBG_INIT (); DBG (10, "sane_init() called.\n"); DBG (1, "coolscan2 backend, version %i.%i.%i initializing.\n", CS2_VERSION_MAJOR, CS2_VERSION_MINOR, CS2_REVISION); authorize = authorize; /* to shut up compiler */ if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, V_MINOR, 0); sanei_usb_init (); return SANE_STATUS_GOOD; } void sane_exit (void) { int i; DBG (10, "sane_exit() called.\n"); for (i = 0; i < n_device_list; i++) { cs2_xfree (device_list[i]->name); cs2_xfree (device_list[i]->vendor); cs2_xfree (device_list[i]->model); cs2_xfree (device_list[i]); } cs2_xfree (device_list); } SANE_Status sane_get_devices (const SANE_Device *** list, SANE_Bool local_only) { char line[PATH_MAX], *p; FILE *config; local_only = local_only; /* to shut up compiler */ DBG (10, "sane_get_devices() called.\n"); if (device_list) DBG (6, "sane_get_devices(): Device list already populated, not probing again.\n"); else { if (open_devices) { DBG (4, "sane_get_devices(): Devices open, not scanning for scanners.\n"); return SANE_STATUS_IO_ERROR; } config = sanei_config_open (CS2_CONFIG_FILE); if (config) { DBG (4, "sane_get_devices(): Reading config file.\n"); while (sanei_config_read (line, sizeof (line), config)) { p = line; p += strspn (line, " \t"); if (strlen (p) && (p[0] != '\n') && (p[0] != '#')) cs2_open (line, CS2_INTERFACE_UNKNOWN, NULL); } fclose (config); } else { DBG (4, "sane_get_devices(): No config file found.\n"); cs2_open ("auto", CS2_INTERFACE_UNKNOWN, NULL); } switch (n_device_list) { case 0: DBG (6, "sane_get_devices(): No devices detected.\n"); break; case 1: DBG (6, "sane_get_devices(): 1 device detected.\n"); break; default: DBG (6, "sane_get_devices(): %i devices detected.\n", n_device_list); break; } } *list = (const SANE_Device **) device_list; return SANE_STATUS_GOOD; } SANE_Status sane_open (SANE_String_Const name, SANE_Handle * h) { SANE_Status status; cs2_t *s; int i_option; unsigned int i_list; SANE_Option_Descriptor o; SANE_Word *word_list; SANE_Range *range = NULL; int alloc_failed = 0; DBG (10, "sane_open() called.\n"); status = cs2_open (name, CS2_INTERFACE_UNKNOWN, &s); if (status) return status; *h = (SANE_Handle) s; /* get device properties */ s->lut_r = s->lut_g = s->lut_b = s->lut_neutral = NULL; s->resx_list = s->resy_list = NULL; s->resx_n_list = s->resy_n_list = 0; status = cs2_full_inquiry (s); if (status) return status; /* option descriptors */ for (i_option = 0; i_option < CS2_N_OPTIONS; i_option++) { o.name = o.title = o.desc = NULL; o.type = o.unit = o.cap = o.constraint_type = o.size = 0; o.constraint.range = NULL; /* only one union member needs to be NULLed */ switch (i_option) { case CS2_OPTION_NUM: o.name = ""; o.title = SANE_TITLE_NUM_OPTIONS; o.desc = SANE_DESC_NUM_OPTIONS; o.type = SANE_TYPE_INT; o.size = WSIZE; o.cap = SANE_CAP_SOFT_DETECT; break; case CS2_OPTION_PREVIEW: o.name = "preview"; o.title = "Preview mode"; o.desc = "Preview mode"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; break; case CS2_OPTION_NEGATIVE: o.name = "negative"; o.title = "Negative"; o.desc = "Negative film: make scanner invert colours"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; #ifndef CS2_BLEEDING_EDGE o.cap |= SANE_CAP_INACTIVE; #endif break; case CS2_OPTION_INFRARED: o.name = "infrared"; o.title = "Read infrared channel"; o.desc = "Read infrared channel in addition to scan colours"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS2_OPTION_SAMPLES_PER_SCAN: o.name = "samples-per-scan"; o.title = "Samples per Scan"; o.desc = "Number of samples per scan"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (s->type != CS2_TYPE_LS2000 && s->type != CS2_TYPE_LS4000 && s->type != CS2_TYPE_LS5000 && s->type != CS2_TYPE_LS8000) o.cap |= SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (! range) alloc_failed = 1; else { range->min = 1; range->max = 16; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_DEPTH: o.name = "depth"; o.title = "Bit depth per channel"; o.desc = "Number of bits output by scanner for each channel"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_WORD_LIST; word_list = (SANE_Word *) cs2_xmalloc (2 * sizeof (SANE_Word)); if (!word_list) alloc_failed = 1; else { word_list[1] = 8; word_list[2] = s->maxbits; word_list[0] = 2; o.constraint.word_list = word_list; } break; case CS2_OPTION_EXPOSURE: o.name = "exposure"; o.title = "Exposure multiplier"; o.desc = "Exposure multiplier for all channels"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX (0.); range->max = SANE_FIX (10.); range->quant = SANE_FIX (0.1); o.constraint.range = range; } break; case CS2_OPTION_EXPOSURE_R: o.name = "red-exposure"; o.title = "Red exposure time"; o.desc = "Exposure time for red channel"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_MICROSECOND; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX (50.); range->max = SANE_FIX (20000.); range->quant = SANE_FIX (10.); o.constraint.range = range; } break; case CS2_OPTION_EXPOSURE_G: o.name = "green-exposure"; o.title = "Green exposure time"; o.desc = "Exposure time for green channel"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_MICROSECOND; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX (50.); range->max = SANE_FIX (20000.); range->quant = SANE_FIX (10.); o.constraint.range = range; } break; case CS2_OPTION_EXPOSURE_B: o.name = "blue-exposure"; o.title = "Blue exposure time"; o.desc = "Exposure time for blue channel"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_MICROSECOND; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX (50.); range->max = SANE_FIX (20000.); range->quant = SANE_FIX (10.); o.constraint.range = range; } break; case CS2_OPTION_LUT_R: o.name = "red-gamma-table"; o.title = "LUT for red channel"; o.desc = "LUT for red channel"; o.type = SANE_TYPE_INT; o.size = s->n_lut * WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->n_lut - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_LUT_G: o.name = "green-gamma-table"; o.title = "LUT for green channel"; o.desc = "LUT for green channel"; o.type = SANE_TYPE_INT; o.size = s->n_lut * WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->n_lut - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_LUT_B: o.name = "blue-gamma-table"; o.title = "LUT for blue channel"; o.desc = "LUT for blue channel"; o.type = SANE_TYPE_INT; o.size = s->n_lut * WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->n_lut - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_LOAD: o.name = "load"; o.title = "Load"; o.desc = "Load next slide"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS2_OPTION_EJECT: o.name = "eject"; o.title = "Eject"; o.desc = "Eject loaded medium"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS2_OPTION_RESET: o.name = "reset"; o.title = "Reset scanner"; o.desc = "Initialize scanner"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS2_OPTION_RESX: case CS2_OPTION_RES: case CS2_OPTION_PREVIEW_RESOLUTION: if (i_option == CS2_OPTION_PREVIEW_RESOLUTION) { o.name = "preview-resolution"; o.title = "Preview resolution"; o.desc = "Scanning resolution for preview mode in dpi, affecting both x and y directions"; } else if (i_option == CS2_OPTION_RES) { o.name = "resolution"; o.title = "Resolution"; o.desc = "Scanning resolution in dpi, affecting both x and y directions"; } else { o.name = "x-resolution"; o.title = "X resolution"; o.desc = "Scanning resolution in dpi, affecting x direction only"; } o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_DPI; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (i_option == CS2_OPTION_RESX) o.cap |= SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; if (i_option == CS2_OPTION_PREVIEW_RESOLUTION) o.cap |= SANE_CAP_ADVANCED; o.constraint_type = SANE_CONSTRAINT_WORD_LIST; word_list = (SANE_Word *) cs2_xmalloc ((s->resx_n_list + 1) * sizeof (SANE_Word)); if (!word_list) alloc_failed = 1; else { for (i_list = 0; i_list < s->resx_n_list; i_list++) word_list[i_list + 1] = s->resx_list[i_list]; word_list[0] = s->resx_n_list; o.constraint.word_list = word_list; } break; case CS2_OPTION_RESY: o.name = "y-resolution"; o.title = "Y resolution"; o.desc = "Scanning resolution in dpi, affecting y direction only"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_DPI; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; o.constraint_type = SANE_CONSTRAINT_WORD_LIST; word_list = (SANE_Word *) cs2_xmalloc ((s->resy_n_list + 1) * sizeof (SANE_Word)); if (!word_list) alloc_failed = 1; else { for (i_list = 0; i_list < s->resy_n_list; i_list++) word_list[i_list + 1] = s->resy_list[i_list]; word_list[0] = s->resy_n_list; o.constraint.word_list = word_list; } break; case CS2_OPTION_RES_INDEPENDENT: o.name = "independent-res"; o.title = "Independent x/y resolutions"; o.desc = "Enable independent controls for scanning resolution in x and y direction"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_ADVANCED; break; case CS2_OPTION_FRAME: o.name = "frame"; o.title = "Frame number"; o.desc = "Number of frame to be scanned, starting with 1"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; if (s->n_frames <= 1) o.cap |= SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 1; range->max = s->n_frames; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_SUBFRAME: o.name = "subframe"; o.title = "Frame shift"; o.desc = "Fine position within the selected frame"; o.type = SANE_TYPE_FIXED; o.unit = SANE_UNIT_MM; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = SANE_FIX (0.); range->max = SANE_FIX ((s->boundaryy - 1) * s->unit_mm); range->quant = SANE_FIX (0.); o.constraint.range = range; } break; case CS2_OPTION_XMIN: o.name = "tl-x"; o.title = "Left x value of scan area"; o.desc = "Left x value of scan area"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; if (!range) alloc_failed = 1; else { range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); range->min = 0; range->max = s->boundaryx - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_XMAX: o.name = "br-x"; o.title = "Right x value of scan area"; o.desc = "Right x value of scan area"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryx - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_YMIN: o.name = "tl-y"; o.title = "Top y value of scan area"; o.desc = "Top y value of scan area"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryy - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_YMAX: o.name = "br-y"; o.title = "Bottom y value of scan area"; o.desc = "Bottom y value of scan area"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryy - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_FOCUS_ON_CENTRE: o.name = "focus-on-centre"; o.title = "Use centre of scan area as AF point"; o.desc = "Use centre of scan area as AF point instead of manual AF point selection"; o.type = SANE_TYPE_BOOL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS2_OPTION_FOCUS: o.name = "focus"; o.title = "Focus position"; o.desc = "Focus position for manual focus"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_NONE; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = s->focus_min; range->max = s->focus_max; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_AUTOFOCUS: o.name = "autofocus"; o.title = "Autofocus now"; o.desc = "Autofocus now"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS2_OPTION_FOCUSX: o.name = "focusx"; o.title = "X coordinate of AF point"; o.desc = "X coordinate of AF point"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryx - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_FOCUSY: o.name = "focusy"; o.title = "Y coordinate of AF point"; o.desc = "Y coordinate of AF point"; o.type = SANE_TYPE_INT; o.unit = SANE_UNIT_PIXEL; o.size = WSIZE; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; o.constraint_type = SANE_CONSTRAINT_RANGE; range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range)); if (!range) alloc_failed = 1; else { range->min = 0; range->max = s->boundaryy - 1; range->quant = 1; o.constraint.range = range; } break; case CS2_OPTION_SCAN_AE: o.name = "ae"; o.title = "Auto-exposure scan now"; o.desc = "Perform auto-exposure scan"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; case CS2_OPTION_SCAN_AE_WB: o.name = "ae-wb"; o.title = "Auto-exposure scan with white balance now"; o.desc = "Perform auto-exposure scan with white balance"; o.type = SANE_TYPE_BUTTON; o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; break; default: DBG (1, "BUG: sane_open(): Unknown option number.\n"); return SANE_STATUS_INVAL; break; } s->option_list[i_option] = o; } s->scanning = SANE_FALSE; s->preview = SANE_FALSE; s->negative = SANE_FALSE; s->depth = 8; s->infrared = 0; s->samples_per_scan = 1; s->i_frame = 1; s->subframe = 0.; s->res = s->resx = s->resx_max; s->resy = s->resy_max; s->res_independent = SANE_FALSE; s->res_preview = s->resx_max / 10; if (s->res_preview < s->resx_min) s->res_preview = s->resx_min; s->xmin = 0; s->xmax = s->boundaryx - 1; s->ymin = 0; s->ymax = s->boundaryy - 1; s->focus_on_centre = SANE_TRUE; s->focus = 0; s->focusx = 0; s->focusy = 0; s->exposure = 1.; s->exposure_r = 1200.; s->exposure_g = 1200.; s->exposure_b = 1000.; s->infrared_stage = CS2_INFRARED_OFF; s->infrared_next = CS2_INFRARED_OFF; s->infrared_buf = NULL; s->n_infrared_buf = 0; s->line_buf = NULL; s->n_line_buf = 0; if (alloc_failed) { cs2_close (s); return SANE_STATUS_NO_MEM; } return SANE_STATUS_GOOD; } void sane_close (SANE_Handle h) { cs2_t *s = (cs2_t *) h; DBG (10, "sane_close() called.\n"); cs2_close (s); } const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle h, SANE_Int n) { cs2_t *s = (cs2_t *) h; DBG (10, "sane_get_option_descriptor() called, option #%i.\n", n); if ((n >= 0) && (n < CS2_N_OPTIONS)) return &s->option_list[n]; else return NULL; } SANE_Status sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int * i) { cs2_t *s = (cs2_t *) h; SANE_Int flags = 0; cs2_pixel_t pixel; SANE_Status status; SANE_Option_Descriptor o = s->option_list[n]; DBG (10, "sane_control_option() called, option #%i, action #%i.\n", n, a); switch (a) { case SANE_ACTION_GET_VALUE: switch (n) { case CS2_OPTION_NUM: *(SANE_Word *) v = CS2_N_OPTIONS; break; case CS2_OPTION_NEGATIVE: *(SANE_Word *) v = s->negative; break; case CS2_OPTION_INFRARED: *(SANE_Word *) v = s->infrared; break; case CS2_OPTION_SAMPLES_PER_SCAN: *(SANE_Word *) v = s->samples_per_scan; break; case CS2_OPTION_DEPTH: *(SANE_Word *) v = s->depth; break; case CS2_OPTION_PREVIEW: *(SANE_Word *) v = s->preview; break; case CS2_OPTION_EXPOSURE: *(SANE_Word *) v = SANE_FIX (s->exposure); break; case CS2_OPTION_EXPOSURE_R: *(SANE_Word *) v = SANE_FIX (s->exposure_r); break; case CS2_OPTION_EXPOSURE_G: *(SANE_Word *) v = SANE_FIX (s->exposure_g); break; case CS2_OPTION_EXPOSURE_B: *(SANE_Word *) v = SANE_FIX (s->exposure_b); break; case CS2_OPTION_LUT_R: if (!(s->lut_r)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) ((SANE_Word *) v)[pixel] = s->lut_r[pixel]; break; case CS2_OPTION_LUT_G: if (!(s->lut_g)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) ((SANE_Word *) v)[pixel] = s->lut_g[pixel]; break; case CS2_OPTION_LUT_B: if (!(s->lut_b)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) ((SANE_Word *) v)[pixel] = s->lut_b[pixel]; break; case CS2_OPTION_EJECT: break; case CS2_OPTION_LOAD: break; case CS2_OPTION_RESET: break; case CS2_OPTION_FRAME: *(SANE_Word *) v = s->i_frame; break; case CS2_OPTION_SUBFRAME: *(SANE_Word *) v = SANE_FIX (s->subframe); break; case CS2_OPTION_RES: *(SANE_Word *) v = s->res; break; case CS2_OPTION_RESX: *(SANE_Word *) v = s->resx; break; case CS2_OPTION_RESY: *(SANE_Word *) v = s->resy; break; case CS2_OPTION_RES_INDEPENDENT: *(SANE_Word *) v = s->res_independent; break; case CS2_OPTION_PREVIEW_RESOLUTION: *(SANE_Word *) v = s->res_preview; break; case CS2_OPTION_XMIN: *(SANE_Word *) v = s->xmin; break; case CS2_OPTION_XMAX: *(SANE_Word *) v = s->xmax; break; case CS2_OPTION_YMIN: *(SANE_Word *) v = s->ymin; break; case CS2_OPTION_YMAX: *(SANE_Word *) v = s->ymax; break; case CS2_OPTION_FOCUS_ON_CENTRE: *(SANE_Word *) v = s->focus_on_centre; break; case CS2_OPTION_FOCUS: *(SANE_Word *) v = s->focus; break; case CS2_OPTION_AUTOFOCUS: break; case CS2_OPTION_FOCUSX: *(SANE_Word *) v = s->focusx; break; case CS2_OPTION_FOCUSY: *(SANE_Word *) v = s->focusy; break; case CS2_OPTION_SCAN_AE: break; case CS2_OPTION_SCAN_AE_WB: break; default: DBG (4, "Error: sane_control_option(): Unknown option (bug?).\n"); return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: if (s->scanning) return SANE_STATUS_INVAL; /* XXXXXXXXXXXXXXXXX do this for all elements of arrays */ switch (o.type) { case SANE_TYPE_BOOL: if ((*(SANE_Word *) v != SANE_TRUE) && (*(SANE_Word *) v != SANE_FALSE)) return SANE_STATUS_INVAL; break; case SANE_TYPE_INT: case SANE_TYPE_FIXED: switch (o.constraint_type) { case SANE_CONSTRAINT_RANGE: if (*(SANE_Word *) v < o.constraint.range->min) { *(SANE_Word *) v = o.constraint.range->min; flags |= SANE_INFO_INEXACT; } else if (*(SANE_Word *) v > o.constraint.range->max) { *(SANE_Word *) v = o.constraint.range->max; flags |= SANE_INFO_INEXACT; } break; case SANE_CONSTRAINT_WORD_LIST: break; default: break; } break; case SANE_TYPE_STRING: break; case SANE_TYPE_BUTTON: break; case SANE_TYPE_GROUP: break; } switch (n) { case CS2_OPTION_NUM: return SANE_STATUS_INVAL; break; case CS2_OPTION_NEGATIVE: s->negative = *(SANE_Word *) v; break; case CS2_OPTION_INFRARED: s->infrared = *(SANE_Word *) v; /* flags |= SANE_INFO_RELOAD_PARAMS; XXXXXXXXXXXXXXXXX */ break; case CS2_OPTION_SAMPLES_PER_SCAN: s->samples_per_scan = *(SANE_Word *) v; break; case CS2_OPTION_DEPTH: s->depth = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_PREVIEW: s->preview = *(SANE_Word *) v; break; case CS2_OPTION_EXPOSURE: s->exposure = SANE_UNFIX (*(SANE_Word *) v); break; case CS2_OPTION_EXPOSURE_R: s->exposure_r = SANE_UNFIX (*(SANE_Word *) v); break; case CS2_OPTION_EXPOSURE_G: s->exposure_g = SANE_UNFIX (*(SANE_Word *) v); break; case CS2_OPTION_EXPOSURE_B: s->exposure_b = SANE_UNFIX (*(SANE_Word *) v); break; case CS2_OPTION_LUT_R: if (!(s->lut_r)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) s->lut_r[pixel] = ((SANE_Word *) v)[pixel]; break; case CS2_OPTION_LUT_G: if (!(s->lut_g)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) s->lut_g[pixel] = ((SANE_Word *) v)[pixel]; break; case CS2_OPTION_LUT_B: if (!(s->lut_b)) return SANE_STATUS_INVAL; for (pixel = 0; pixel < s->n_lut; pixel++) s->lut_b[pixel] = ((SANE_Word *) v)[pixel]; break; case CS2_OPTION_LOAD: cs2_load (s); break; case CS2_OPTION_EJECT: cs2_eject (s); break; case CS2_OPTION_RESET: cs2_reset (s); break; case CS2_OPTION_FRAME: s->i_frame = *(SANE_Word *) v; break; case CS2_OPTION_SUBFRAME: s->subframe = SANE_UNFIX (*(SANE_Word *) v); break; case CS2_OPTION_RES: s->res = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_RESX: s->resx = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_RESY: s->resy = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_RES_INDEPENDENT: s->res_independent = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_PREVIEW_RESOLUTION: s->res_preview = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_XMIN: s->xmin = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_XMAX: s->xmax = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_YMIN: s->ymin = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_YMAX: s->ymax = *(SANE_Word *) v; flags |= SANE_INFO_RELOAD_PARAMS; break; case CS2_OPTION_FOCUS_ON_CENTRE: s->focus_on_centre = *(SANE_Word *) v; if (s->focus_on_centre) { s->option_list[CS2_OPTION_FOCUSX].cap |= SANE_CAP_INACTIVE; s->option_list[CS2_OPTION_FOCUSY].cap |= SANE_CAP_INACTIVE; } else { s->option_list[CS2_OPTION_FOCUSX].cap &= ~SANE_CAP_INACTIVE; s->option_list[CS2_OPTION_FOCUSY].cap &= ~SANE_CAP_INACTIVE; } flags |= SANE_INFO_RELOAD_OPTIONS; break; case CS2_OPTION_FOCUS: s->focus = *(SANE_Word *) v; break; case CS2_OPTION_AUTOFOCUS: cs2_autofocus (s); flags |= SANE_INFO_RELOAD_OPTIONS; break; case CS2_OPTION_FOCUSX: s->focusx = *(SANE_Word *) v; break; case CS2_OPTION_FOCUSY: s->focusy = *(SANE_Word *) v; break; case CS2_OPTION_SCAN_AE: cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); status = cs2_scan (s, CS2_SCAN_AE); if (status) return status; status = cs2_get_exposure (s); if (status) return status; s->exposure = 1.; s->exposure_r = s->real_exposure[1] / 100.; s->exposure_g = s->real_exposure[2] / 100.; s->exposure_b = s->real_exposure[3] / 100.; flags |= SANE_INFO_RELOAD_OPTIONS; break; case CS2_OPTION_SCAN_AE_WB: cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); status = cs2_scan (s, CS2_SCAN_AE_WB); if (status) return status; status = cs2_get_exposure (s); if (status) return status; s->exposure = 1.; s->exposure_r = s->real_exposure[1] / 100.; s->exposure_g = s->real_exposure[2] / 100.; s->exposure_b = s->real_exposure[3] / 100.; flags |= SANE_INFO_RELOAD_OPTIONS; break; default: DBG (4, "Error: sane_control_option(): Unknown option number (bug?).\n"); return SANE_STATUS_INVAL; break; } break; default: DBG (1, "BUG: sane_control_option(): Unknown action number.\n"); return SANE_STATUS_INVAL; break; } if (i) *i = flags; return SANE_STATUS_GOOD; } SANE_Status sane_get_parameters (SANE_Handle h, SANE_Parameters * p) { cs2_t *s = (cs2_t *) h; SANE_Status status; DBG (10, "sane_get_parameters() called.\n"); if (!s->scanning) /* only recalculate when not scanning */ { status = cs2_convert_options (s); if (status) return status; } if (s->infrared_stage == CS2_INFRARED_OUT) { p->format = SANE_FRAME_GRAY; p->bytes_per_line = s->logical_width * s->bytes_per_pixel; } else { p->format = SANE_FRAME_RGB; /* XXXXXXXX CCCCCCCCCC */ p->bytes_per_line = s->n_colour_out * s->logical_width * s->bytes_per_pixel; } p->last_frame = SANE_TRUE; p->lines = s->logical_height; p->depth = 8 * s->bytes_per_pixel; p->pixels_per_line = s->logical_width; return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle h) { cs2_t *s = (cs2_t *) h; SANE_Status status; DBG (10, "sane_start() called.\n"); if (s->scanning) return SANE_STATUS_INVAL; status = cs2_convert_options (s); if (status) return status; s->infrared_index = 0; s->i_line_buf = 0; s->xfer_position = 0; s->scanning = SANE_TRUE; if (s->infrared_stage == CS2_INFRARED_OUT) return SANE_STATUS_GOOD; else return cs2_scan (s, CS2_SCAN_NORMAL); } SANE_Status sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len) { cs2_t *s = (cs2_t *) h; SANE_Status status; ssize_t xfer_len_in, xfer_len_line, xfer_len_out; unsigned long index; int colour, n_colours, sample_pass; uint8_t *s8 = NULL; uint16_t *s16 = NULL; double m_avg_sum; SANE_Byte *line_buf_new; DBG (10, "sane_read() called, maxlen = %i.\n", maxlen); if (!s->scanning) { *len = 0; return SANE_STATUS_CANCELLED; } if (s->infrared_stage == CS2_INFRARED_OUT) { xfer_len_out = maxlen; if (s->xfer_position + xfer_len_out > s->n_infrared_buf) xfer_len_out = s->n_infrared_buf - s->xfer_position; if (xfer_len_out == 0) /* no more data */ { *len = 0; s->scanning = SANE_FALSE; return SANE_STATUS_EOF; } memcpy (buf, &(s->infrared_buf[s->xfer_position]), xfer_len_out); s->xfer_position += xfer_len_out; if (s->xfer_position >= s->n_infrared_buf) s->infrared_next = CS2_INFRARED_OFF; *len = xfer_len_out; return SANE_STATUS_GOOD; } if (s->i_line_buf > 0) { xfer_len_out = s->n_line_buf - s->i_line_buf; if (xfer_len_out > maxlen) xfer_len_out = maxlen; memcpy (buf, &(s->line_buf[s->i_line_buf]), xfer_len_out); s->i_line_buf += xfer_len_out; if (s->i_line_buf >= s->n_line_buf) s->i_line_buf = 0; *len = xfer_len_out; return SANE_STATUS_GOOD; } xfer_len_line = s->n_colour_out * s->logical_width * s->bytes_per_pixel; xfer_len_in = s->n_colour_in * s->logical_width * s->bytes_per_pixel + s->n_colour_in * s->odd_padding; /* Do not change the behaviour of older models */ if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000)) { /* Ariel - Check, win driver uses multiple of 64, docu seems to say 512? */ ssize_t i; xfer_len_in += s->block_padding; i = (xfer_len_in & 0x3f); if (i != 0) DBG (1, "BUG: sane_read(): Read size is not a multiple of 64. (0x%06lx)\n", (long) i); } if (s->xfer_position + xfer_len_line > s->xfer_bytes_total) xfer_len_line = s->xfer_bytes_total - s->xfer_position; /* just in case */ if (xfer_len_line == 0) /* no more data */ { *len = 0; s->scanning = SANE_FALSE; return SANE_STATUS_EOF; } if (xfer_len_line != s->n_line_buf) { line_buf_new = (SANE_Byte *) cs2_xrealloc (s->line_buf, xfer_len_line * sizeof (SANE_Byte)); if (!line_buf_new) { *len = 0; return SANE_STATUS_NO_MEM; } s->line_buf = line_buf_new; s->n_line_buf = xfer_len_line; } /* adapt for multi-sampling */ xfer_len_in *= s->samples_per_scan; cs2_scanner_ready (s, CS2_STATUS_READY); cs2_init_buffer (s); cs2_parse_cmd (s, "28 00 00 00 00 00"); cs2_pack_byte (s, (xfer_len_in >> 16) & 0xff); cs2_pack_byte (s, (xfer_len_in >> 8) & 0xff); cs2_pack_byte (s, xfer_len_in & 0xff); cs2_parse_cmd (s, "00"); s->n_recv = xfer_len_in; status = cs2_issue_cmd (s); if (status) { *len = 0; return status; } n_colours = s->n_colour_out + (s->infrared_stage == CS2_INFRARED_IN ? 1 : 0); for (index = 0; index < s->logical_width; index++) for (colour = 0; colour < n_colours; colour++) { m_avg_sum = 0.0; switch (s->bytes_per_pixel) { case 1: /* calculate target address */ if ((s->infrared_stage == CS2_INFRARED_IN) && (colour == s->n_colour_out)) s8 = (uint8_t *) & (s->infrared_buf[s->infrared_index++]); else s8 = (uint8_t *) & (s->line_buf[s->n_colour_out * index + colour]); if (s->samples_per_scan > 1) { /* calculate average of multi samples */ for (sample_pass = 0; sample_pass < s->samples_per_scan; sample_pass++) m_avg_sum += (double) s->recv_buf[s->logical_width * (sample_pass * n_colours + colour) + (colour + 1) * s->odd_padding + index]; *s8 = (uint8_t) (m_avg_sum / s->samples_per_scan + 0.5); } else /* shortcut for single sample */ *s8 = s->recv_buf[colour * s->logical_width + (colour + 1) * s->odd_padding + index]; break; case 2: /* calculate target address */ if ((s->infrared_stage == CS2_INFRARED_IN) && (colour == s->n_colour_out)) s16 = (uint16_t *) & (s->infrared_buf[2 * (s->infrared_index++)]); else s16 = (uint16_t *) & (s-> line_buf[2 * (s->n_colour_out * index + colour)]); if (s->samples_per_scan > 1) { /* calculate average of multi samples */ for (sample_pass = 0; s->samples_per_scan > 1 && sample_pass < s->samples_per_scan; sample_pass++) m_avg_sum += (double) (s->recv_buf[2 * (s->logical_width * (sample_pass * n_colours + colour) + index)] * 256 + s->recv_buf[2 * (s->logical_width * (sample_pass * n_colours + colour) + index) + 1]); *s16 = (uint16_t) (m_avg_sum / s->samples_per_scan + 0.5); } else /* shortcut for single sample */ *s16 = s->recv_buf[2 * (colour * s->logical_width + index)] * 256 + s->recv_buf[2 * (colour * s->logical_width + index) + 1]; *s16 <<= s->shift_bits; break; default: DBG (1, "BUG: sane_read(): Unknown number of bytes per pixel.\n"); *len = 0; return SANE_STATUS_INVAL; break; } } s->xfer_position += xfer_len_line; xfer_len_out = xfer_len_line; if (xfer_len_out > maxlen) xfer_len_out = maxlen; memcpy (buf, s->line_buf, xfer_len_out); if (xfer_len_out < xfer_len_line) s->i_line_buf = xfer_len_out; /* data left in the line buffer, read out next time */ if ((s->infrared_stage == CS2_INFRARED_IN) && (s->xfer_position >= s->n_infrared_buf)) s->infrared_next = CS2_INFRARED_OUT; *len = xfer_len_out; return SANE_STATUS_GOOD; } void sane_cancel (SANE_Handle h) { cs2_t *s = (cs2_t *) h; if (s->scanning) DBG (10, "sane_cancel() called while scanning.\n"); else DBG (10, "sane_cancel() called while not scanning.\n"); if (s->scanning && (s->infrared_stage != CS2_INFRARED_OUT)) { cs2_init_buffer (s); cs2_parse_cmd (s, "c0 00 00 00 00 00"); cs2_issue_cmd (s); } s->scanning = SANE_FALSE; } SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool m) { cs2_t *s = (cs2_t *) h; DBG (10, "sane_set_io_mode() called.\n"); if (!s->scanning) return SANE_STATUS_INVAL; if (m == SANE_FALSE) return SANE_STATUS_GOOD; else return SANE_STATUS_UNSUPPORTED; } SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fd) { cs2_t *s = (cs2_t *) h; DBG (10, "sane_get_select_fd() called.\n"); fd = fd; /* to shut up compiler */ s = s; /* to shut up compiler */ return SANE_STATUS_UNSUPPORTED; } /* ========================================================================= */ /* private functions */ static SANE_Status cs2_open (const char *device, cs2_interface_t interface, cs2_t ** sp) { SANE_Status status; cs2_t *s; char *prefix = NULL, *line; const char *device2; int i; int alloc_failed = 0; SANE_Device **device_list_new; DBG (6, "cs2_open() called, with device = %s and interface = %i\n", device, interface); if (!strncmp (device, "auto", 5)) { try_interface = CS2_INTERFACE_SCSI; sanei_config_attach_matching_devices ("scsi Nikon *", cs2_attach); try_interface = CS2_INTERFACE_USB; sanei_usb_attach_matching_devices ("usb 0x04b0 0x4000", cs2_attach); sanei_usb_attach_matching_devices ("usb 0x04b0 0x4001", cs2_attach); sanei_usb_attach_matching_devices ("usb 0x04b0 0x4002", cs2_attach); return SANE_STATUS_GOOD; } if ((s = (cs2_t *) cs2_xmalloc (sizeof (cs2_t))) == NULL) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (cs2_t)); s->send_buf = s->recv_buf = NULL; s->send_buf_size = s->recv_buf_size = 0; switch (interface) { case CS2_INTERFACE_UNKNOWN: for (i = 0; i < 2; i++) { switch (i) { case 1: prefix = "usb:"; try_interface = CS2_INTERFACE_USB; break; default: prefix = "scsi:"; try_interface = CS2_INTERFACE_SCSI; break; } if (!strncmp (device, prefix, strlen (prefix))) { device2 = device + strlen (prefix); cs2_xfree (s); return cs2_open (device2, try_interface, sp); } } cs2_xfree (s); return SANE_STATUS_INVAL; break; case CS2_INTERFACE_SCSI: s->interface = CS2_INTERFACE_SCSI; DBG (6, "cs2_open(): Trying to open %s, assuming SCSI or SBP2 interface ...\n", device); status = sanei_scsi_open (device, &s->fd, cs2_scsi_sense_handler, s); if (status) { DBG (6, "cs2_open(): ... failed: %s.\n", sane_strstatus (status)); cs2_xfree (s); return status; } break; case CS2_INTERFACE_USB: s->interface = CS2_INTERFACE_USB; DBG (6, "cs2_open(): Trying to open %s, assuming USB interface ...\n", device); status = sanei_usb_open (device, &s->fd); if (status) { DBG (6, "cs2_open(): ... failed: %s.\n", sane_strstatus (status)); cs2_xfree (s); return status; } break; } open_devices++; DBG (6, "cs2_open(): ... looks OK, trying to identify device.\n"); /* identify scanner */ status = cs2_page_inquiry (s, -1); if (status) { DBG (4, "Error: cs2_open(): failed to get page: %s.\n", sane_strstatus (status)); cs2_close (s); return status; } strncpy (s->vendor_string, (char *)s->recv_buf + 8, 8); s->vendor_string[8] = '\0'; strncpy (s->product_string, (char *)s->recv_buf + 16, 16); s->product_string[16] = '\0'; strncpy (s->revision_string, (char *)s->recv_buf + 32, 4); s->revision_string[4] = '\0'; DBG (10, "cs2_open(): Inquiry reveals: vendor = '%s', product = '%s', revision = '%s'.\n", s->vendor_string, s->product_string, s->revision_string); if (!strncmp (s->product_string, "COOLSCANIII ", 16)) s->type = CS2_TYPE_LS30; else if (!strncmp (s->product_string, "LS-40 ED ", 16)) s->type = CS2_TYPE_LS40; else if (!strncmp (s->product_string, "LS-50 ED ", 16)) s->type = CS2_TYPE_LS50; else if (!strncmp (s->product_string, "LS-2000 ", 16)) s->type = CS2_TYPE_LS2000; else if (!strncmp (s->product_string, "LS-4000 ED ", 16)) s->type = CS2_TYPE_LS4000; else if (!strncmp (s->product_string, "LS-5000 ED ", 16)) s->type = CS2_TYPE_LS5000; else if (!strncmp (s->product_string, "LS-8000 ED ", 16)) s->type = CS2_TYPE_LS8000; if (s->type != CS2_TYPE_UNKOWN) DBG (10, "cs2_open(): Device identified as coolscan2 type #%i.\n", s->type); else { DBG (10, "cs2_open(): Device not identified.\n"); cs2_close (s); return SANE_STATUS_UNSUPPORTED; } if (sp) *sp = s; else { device_list_new = (SANE_Device **) cs2_xrealloc (device_list, (n_device_list + 2) * sizeof (SANE_Device *)); if (!device_list_new) return SANE_STATUS_NO_MEM; device_list = device_list_new; device_list[n_device_list] = (SANE_Device *) cs2_xmalloc (sizeof (SANE_Device)); if (!device_list[n_device_list]) return SANE_STATUS_NO_MEM; switch (interface) { case CS2_INTERFACE_UNKNOWN: DBG (1, "BUG: cs2_open(): unknown interface.\n"); cs2_close (s); return SANE_STATUS_UNSUPPORTED; break; case CS2_INTERFACE_SCSI: prefix = "scsi:"; break; case CS2_INTERFACE_USB: prefix = "usb:"; break; } line = (char *) cs2_xmalloc (strlen (device) + strlen (prefix) + 1); if (!line) alloc_failed = 1; else { strcpy (line, prefix); strcat (line, device); device_list[n_device_list]->name = line; } line = (char *) cs2_xmalloc (strlen (s->vendor_string) + 1); if (!line) alloc_failed = 1; else { strcpy (line, s->vendor_string); device_list[n_device_list]->vendor = line; } line = (char *) cs2_xmalloc (strlen (s->product_string) + 1); if (!line) alloc_failed = 1; else { strcpy (line, s->product_string); device_list[n_device_list]->model = line; } device_list[n_device_list]->type = "film scanner"; if (alloc_failed) { cs2_xfree (device_list[n_device_list]->name); cs2_xfree (device_list[n_device_list]->vendor); cs2_xfree (device_list[n_device_list]->model); cs2_xfree (device_list[n_device_list]); } else n_device_list++; device_list[n_device_list] = NULL; cs2_close (s); } return SANE_STATUS_GOOD; } void cs2_close (cs2_t * s) { cs2_xfree (s->lut_r); cs2_xfree (s->lut_g); cs2_xfree (s->lut_b); cs2_xfree (s->lut_neutral); cs2_xfree (s->infrared_buf); cs2_xfree (s->line_buf); switch (s->interface) { case CS2_INTERFACE_UNKNOWN: DBG (1, "BUG: cs2_close(): Unknown interface number.\n"); break; case CS2_INTERFACE_SCSI: sanei_scsi_close (s->fd); open_devices--; break; case CS2_INTERFACE_USB: sanei_usb_close (s->fd); open_devices--; break; } cs2_xfree (s); } static SANE_Status cs2_attach (const char *dev) { SANE_Status status; if (try_interface == CS2_INTERFACE_UNKNOWN) return SANE_STATUS_UNSUPPORTED; status = cs2_open (dev, try_interface, NULL); return status; } static SANE_Status cs2_scsi_sense_handler (int fd, u_char * sense_buffer, void *arg) { cs2_t *s = (cs2_t *) arg; fd = fd; /* to shut up compiler */ /* sort this out ! XXXXXXXXX */ s->sense_key = sense_buffer[2] & 0x0f; s->sense_asc = sense_buffer[12]; s->sense_ascq = sense_buffer[13]; s->sense_info = sense_buffer[3]; return cs2_parse_sense_data (s); } static SANE_Status cs2_parse_sense_data (cs2_t * s) { SANE_Status status = SANE_STATUS_GOOD; s->sense_code = (s->sense_key << 24) + (s->sense_asc << 16) + (s->sense_ascq << 8) + s->sense_info; if (s->sense_key) DBG (10, "Sense code: %02lx-%02lx-%02lx-%02lx\n", s->sense_key, s->sense_asc, s->sense_ascq, s->sense_info); switch (s->sense_key) { case 0x00: s->status = CS2_STATUS_READY; break; case 0x02: switch (s->sense_asc) { case 0x04: s->status = CS2_STATUS_PROCESSING; break; case 0x3a: s->status = CS2_STATUS_NO_DOCS; break; default: s->status = CS2_STATUS_ERROR; status = SANE_STATUS_IO_ERROR; break; } break; default: s->status = CS2_STATUS_ERROR; status = SANE_STATUS_IO_ERROR; break; } if ((s->sense_code == 0x09800600) || (s->sense_code == 0x09800601)) s->status = CS2_STATUS_REISSUE; return status; } static void cs2_init_buffer (cs2_t * s) { s->n_cmd = 0; s->n_send = 0; s->n_recv = 0; } static SANE_Status cs2_pack_byte (cs2_t * s, SANE_Byte byte) { while (s->send_buf_size <= s->n_send) { s->send_buf_size += 16; s->send_buf = (SANE_Byte *) cs2_xrealloc (s->send_buf, s->send_buf_size); if (!s->send_buf) return SANE_STATUS_NO_MEM; } s->send_buf[s->n_send++] = byte; return SANE_STATUS_GOOD; } static SANE_Status cs2_parse_cmd (cs2_t * s, char *text) { size_t i, j; char c, h; SANE_Status status; for (i = 0; i < strlen (text); i += 2) if (text[i] == ' ') i--; /* a bit dirty... advance by -1+2=1 */ else { if ((!isxdigit (text[i])) || (!isxdigit (text[i + 1]))) DBG (1, "BUG: cs2_parse_cmd(): Parser got invalid character.\n"); c = 0; for (j = 0; j < 2; j++) { h = tolower (text[i + j]); if ((h >= 'a') && (h <= 'f')) c += 10 + h - 'a'; else c += h - '0'; if (j == 0) c <<= 4; } status = cs2_pack_byte (s, c); if (status) return status; } return SANE_STATUS_GOOD; } static SANE_Status cs2_grow_send_buffer (cs2_t * s) { if (s->n_send > s->send_buf_size) { s->send_buf_size = s->n_send; s->send_buf = (SANE_Byte *) cs2_xrealloc (s->send_buf, s->send_buf_size); if (!s->send_buf) return SANE_STATUS_NO_MEM; } return SANE_STATUS_GOOD; } static SANE_Status cs2_issue_cmd (cs2_t * s) { SANE_Status status = SANE_STATUS_INVAL; size_t n_data, n_status; static SANE_Byte status_buf[8]; int status_only = 0; DBG (20, "cs2_issue_cmd(): opcode = 0x%02x, n_send = %lu, n_recv = %lu.\n", s->send_buf[0], (unsigned long) s->n_send, (unsigned long) s->n_recv); s->status = CS2_STATUS_READY; if (!s->n_cmd) switch (s->send_buf[0]) { case 0x00: case 0x12: case 0x15: case 0x16: case 0x17: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0xc0: case 0xc1: s->n_cmd = 6; break; case 0x24: case 0x25: case 0x28: case 0x2a: case 0xe0: case 0xe1: s->n_cmd = 10; break; default: DBG (1, "BUG: cs2_issue_cmd(): Unknown command opcode 0x%02x.\n", s->send_buf[0]); break; } if (s->n_send < s->n_cmd) { DBG (1, "BUG: cs2_issue_cmd(): Negative number of data out bytes requested.\n"); return SANE_STATUS_INVAL; } n_data = s->n_send - s->n_cmd; if (s->n_recv > 0) { if (n_data > 0) { DBG (1, "BUG: cs2_issue_cmd(): Both data in and data out requested.\n"); return SANE_STATUS_INVAL; } else { n_data = s->n_recv; } } s->recv_buf = (SANE_Byte *) cs2_xrealloc (s->recv_buf, s->n_recv); if (!s->recv_buf) return SANE_STATUS_NO_MEM; switch (s->interface) { case CS2_INTERFACE_UNKNOWN: DBG (1, "BUG: cs2_issue_cmd(): Unknown or uninitialized interface number.\n"); break; case CS2_INTERFACE_SCSI: sanei_scsi_cmd2 (s->fd, s->send_buf, s->n_cmd, s->send_buf + s->n_cmd, s->n_send - s->n_cmd, s->recv_buf, &s->n_recv); status = SANE_STATUS_GOOD; break; case CS2_INTERFACE_USB: status = sanei_usb_write_bulk (s->fd, s->send_buf, &s->n_cmd); if (status != SANE_STATUS_GOOD) { DBG (1, "Error: cs2_issue_cmd(): Could not write command.\n"); return SANE_STATUS_IO_ERROR; } switch (cs2_phase_check (s)) { case CS2_PHASE_OUT: if (s->n_send - s->n_cmd < n_data || !n_data) { DBG (4, "Error: cs2_issue_cmd(): Unexpected data out phase.\n"); return SANE_STATUS_IO_ERROR; } status = sanei_usb_write_bulk (s->fd, s->send_buf + s->n_cmd, &n_data); break; case CS2_PHASE_IN: if (s->n_recv < n_data || !n_data) { DBG (4, "Error: cs2_issue_cmd(): Unexpected data in phase.\n"); return SANE_STATUS_IO_ERROR; } status = sanei_usb_read_bulk (s->fd, s->recv_buf, &n_data); s->n_recv = n_data; break; case CS2_PHASE_NONE: DBG (4, "Error: cs2_issue_cmd(): No command received!\n"); return SANE_STATUS_IO_ERROR; default: if (n_data) { DBG (4, "Error: cs2_issue_cmd(): Unexpected non-data phase, but n_data != 0.\n"); status_only = 1; } break; } n_status = 8; status = sanei_usb_read_bulk (s->fd, status_buf, &n_status); if (n_status != 8) { DBG (4, "Error: cs2_issue_cmd(): Failed to read 8 status bytes from USB.\n"); return SANE_STATUS_IO_ERROR; } s->sense_key = status_buf[1] & 0x0f; s->sense_asc = status_buf[2] & 0xff; s->sense_ascq = status_buf[3] & 0xff; s->sense_info = status_buf[4] & 0xff; cs2_parse_sense_data (s); break; } if (status_only) return SANE_STATUS_IO_ERROR; else return status; } static cs2_phase_t cs2_phase_check (cs2_t * s) { static SANE_Byte phase_send_buf[1] = { 0xd0 }, phase_recv_buf[1]; SANE_Status status = 0; size_t n = 1; status = sanei_usb_write_bulk (s->fd, phase_send_buf, &n); status |= sanei_usb_read_bulk (s->fd, phase_recv_buf, &n); DBG (6, "cs2_phase_check(): Phase check returned phase = 0x%02x.\n", phase_recv_buf[0]); if (status) return -1; else return phase_recv_buf[0]; } static SANE_Status cs2_scanner_ready (cs2_t * s, int flags) { SANE_Status status = SANE_STATUS_GOOD; int i = -1; unsigned long count = 0; int retry = 3; do { if (i >= 0) /* dirty !!! */ usleep (500000); cs2_init_buffer (s); for (i = 0; i < 6; i++) cs2_pack_byte (s, 0x00); status = cs2_issue_cmd (s); if (status) if (--retry < 0) return status; if (++count > 240) { /* 120s timeout */ DBG (4, "Error: cs2_scanner_ready(): Timeout expired.\n"); status = SANE_STATUS_IO_ERROR; break; } } while (s->status & ~flags); /* until all relevant bits are 0 */ return status; } static SANE_Status cs2_page_inquiry (cs2_t * s, int page) { SANE_Status status; size_t n; if (page >= 0) { cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); cs2_init_buffer (s); cs2_parse_cmd (s, "12 01"); cs2_pack_byte (s, page); cs2_parse_cmd (s, "00 04 00"); s->n_recv = 4; status = cs2_issue_cmd (s); if (status) { DBG (4, "Error: cs2_page_inquiry(): Inquiry of page size failed: %s.\n", sane_strstatus (status)); return status; } n = s->recv_buf[3] + 4; } else n = 36; cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); cs2_init_buffer (s); if (page >= 0) { cs2_parse_cmd (s, "12 01"); cs2_pack_byte (s, page); cs2_parse_cmd (s, "00"); } else cs2_parse_cmd (s, "12 00 00 00"); cs2_pack_byte (s, n); cs2_parse_cmd (s, "00"); s->n_recv = n; status = cs2_issue_cmd (s); if (status) { DBG (4, "Error: cs2_page_inquiry(): Inquiry of page failed: %s.\n", sane_strstatus (status)); return status; } return SANE_STATUS_GOOD; } static SANE_Status cs2_full_inquiry (cs2_t * s) { SANE_Status status; int pitch, pitch_max; cs2_pixel_t pixel; status = cs2_page_inquiry (s, 0xc1); if (status) { DBG (4, "Error: cs2_full_inquiry(): Failed to get page: %s\n", sane_strstatus (status)); return status; } s->maxbits = s->recv_buf[82]; if (s->type == CS2_TYPE_LS30) /* must be overridden, LS-30 claims to have 12 bits */ s->maxbits = 10; s->n_lut = 1; s->n_lut <<= s->maxbits; s->lut_r = (cs2_pixel_t *) cs2_xrealloc (s->lut_r, s->n_lut * sizeof (cs2_pixel_t)); s->lut_g = (cs2_pixel_t *) cs2_xrealloc (s->lut_g, s->n_lut * sizeof (cs2_pixel_t)); s->lut_b = (cs2_pixel_t *) cs2_xrealloc (s->lut_b, s->n_lut * sizeof (cs2_pixel_t)); s->lut_neutral = (cs2_pixel_t *) cs2_xrealloc (s->lut_neutral, s->n_lut * sizeof (cs2_pixel_t)); if (!s->lut_r || !s->lut_g || !s->lut_b || !s->lut_neutral) { cs2_xfree (s->lut_r); cs2_xfree (s->lut_g); cs2_xfree (s->lut_b); cs2_xfree (s->lut_neutral); return SANE_STATUS_NO_MEM; } for (pixel = 0; pixel < s->n_lut; pixel++) s->lut_r[pixel] = s->lut_g[pixel] = s->lut_b[pixel] = s->lut_neutral[pixel] = pixel; s->resx_optical = 256 * s->recv_buf[18] + s->recv_buf[19]; s->resx_max = 256 * s->recv_buf[20] + s->recv_buf[21]; s->resx_min = 256 * s->recv_buf[22] + s->recv_buf[23]; s->boundaryx = 65536 * (256 * s->recv_buf[36] + s->recv_buf[37]) + 256 * s->recv_buf[38] + s->recv_buf[39]; s->resy_optical = 256 * s->recv_buf[40] + s->recv_buf[41]; s->resy_max = 256 * s->recv_buf[42] + s->recv_buf[43]; s->resy_min = 256 * s->recv_buf[44] + s->recv_buf[45]; s->boundaryy = 65536 * (256 * s->recv_buf[58] + s->recv_buf[59]) + 256 * s->recv_buf[60] + s->recv_buf[61]; s->focus_min = 256 * s->recv_buf[76] + s->recv_buf[77]; s->focus_max = 256 * s->recv_buf[78] + s->recv_buf[79]; s->n_frames = s->recv_buf[75]; s->frame_offset = s->resy_max * 1.5 + 1; /* works for LS-30, maybe not for others */ /* generate resolution list for x */ s->resx_n_list = pitch_max = floor (s->resx_max / (double) s->resx_min); s->resx_list = (unsigned int *) cs2_xrealloc (s->resx_list, pitch_max * sizeof (unsigned int)); for (pitch = 1; pitch <= pitch_max; pitch++) s->resx_list[pitch - 1] = s->resx_max / pitch; /* generate resolution list for y */ s->resy_n_list = pitch_max = floor (s->resy_max / (double) s->resy_min); s->resy_list = (unsigned int *) cs2_xrealloc (s->resy_list, pitch_max * sizeof (unsigned int)); for (pitch = 1; pitch <= pitch_max; pitch++) s->resy_list[pitch - 1] = s->resy_max / pitch; s->unit_dpi = s->resx_max; s->unit_mm = 25.4 / s->unit_dpi; return SANE_STATUS_GOOD; } static SANE_Status cs2_execute (cs2_t * s) { cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); cs2_init_buffer (s); cs2_parse_cmd (s, "c1 00 00 00 00 00"); return cs2_issue_cmd (s); } static SANE_Status cs2_load (cs2_t * s) { SANE_Status status; cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); cs2_init_buffer (s); cs2_parse_cmd (s, "e0 00 d1 00 00 00 00 00 0d 00"); s->n_send += 13; status = cs2_grow_send_buffer (s); if (status) return status; status = cs2_issue_cmd (s); if (status) return status; return cs2_execute (s); } static SANE_Status cs2_eject (cs2_t * s) { SANE_Status status; cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); cs2_init_buffer (s); cs2_parse_cmd (s, "e0 00 d0 00 00 00 00 00 0d 00"); s->n_send += 13; status = cs2_grow_send_buffer (s); if (status) return status; status = cs2_issue_cmd (s); if (status) return status; return cs2_execute (s); } static SANE_Status cs2_reset (cs2_t * s) { SANE_Status status; cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); cs2_init_buffer (s); cs2_parse_cmd (s, "e0 00 80 00 00 00 00 00 0d 00"); s->n_send += 13; status = cs2_grow_send_buffer (s); if (status) return status; status = cs2_issue_cmd (s); if (status) return status; return cs2_execute (s); } static SANE_Status cs2_focus (cs2_t * s) { SANE_Status status; cs2_scanner_ready (s, CS2_STATUS_READY); cs2_init_buffer (s); cs2_parse_cmd (s, "e0 00 c1 00 00 00 00 00 0d 00 00"); cs2_pack_byte (s, (s->focus >> 24) & 0xff); cs2_pack_byte (s, (s->focus >> 16) & 0xff); cs2_pack_byte (s, (s->focus >> 8) & 0xff); cs2_pack_byte (s, s->focus & 0xff); cs2_parse_cmd (s, "00 00 00 00 00 00 00 00"); status = cs2_issue_cmd (s); if (status) return status; return cs2_execute (s); } static SANE_Status cs2_autofocus (cs2_t * s) { SANE_Status status; cs2_convert_options (s); cs2_scanner_ready (s, CS2_STATUS_READY); cs2_init_buffer (s); cs2_parse_cmd (s, "e0 00 a0 00 00 00 00 00 0d 00 00"); cs2_pack_byte (s, (s->real_focusx >> 24) & 0xff); cs2_pack_byte (s, (s->real_focusx >> 16) & 0xff); cs2_pack_byte (s, (s->real_focusx >> 8) & 0xff); cs2_pack_byte (s, s->real_focusx & 0xff); cs2_pack_byte (s, (s->real_focusy >> 24) & 0xff); cs2_pack_byte (s, (s->real_focusy >> 16) & 0xff); cs2_pack_byte (s, (s->real_focusy >> 8) & 0xff); cs2_pack_byte (s, s->real_focusy & 0xff); cs2_parse_cmd (s, "00 00 00 00"); status = cs2_issue_cmd (s); if (status) return status; status = cs2_execute (s); if (status) return status; cs2_scanner_ready (s, CS2_STATUS_READY); cs2_init_buffer (s); cs2_parse_cmd (s, "e1 00 c1 00 00 00 00 00 0d 00"); s->n_recv = 13; status = cs2_issue_cmd (s); if (status) return status; s->focus = 65536 * (256 * s->recv_buf[1] + s->recv_buf[2]) + 256 * s->recv_buf[3] + s->recv_buf[4]; return status; } static SANE_Status cs2_get_exposure (cs2_t * s) { SANE_Status status; int i_colour; for (i_colour = 0; i_colour < 3; i_colour++) { /* XXXXXXXXXXXXX CCCCCCCCCCCCC */ cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); cs2_init_buffer (s); cs2_parse_cmd (s, "25 01 00 00 00"); cs2_pack_byte (s, cs2_colour_list[i_colour]); cs2_parse_cmd (s, "00 00 3a 00"); s->n_recv = 58; status = cs2_issue_cmd (s); if (status) return status; s->real_exposure[cs2_colour_list[i_colour]] = 65536 * (256 * s->recv_buf[54] + s->recv_buf[55]) + 256 * s->recv_buf[56] + s->recv_buf[57]; DBG (6, "cs2_get_exposure(): exposure for colour %i: %li * 10ns\n", cs2_colour_list[i_colour], s->real_exposure[cs2_colour_list[i_colour]]); } return SANE_STATUS_GOOD; } static SANE_Status cs2_convert_options (cs2_t * s) { int i_colour; unsigned long xmin, xmax, ymin, ymax; SANE_Byte *infrared_buf_new; s->real_depth = (s->preview ? 8 : s->depth); s->bytes_per_pixel = (s->real_depth > 8 ? 2 : 1); s->shift_bits = 8 * s->bytes_per_pixel - s->real_depth; if (s->preview) { s->real_resx = s->res_preview; s->real_resy = s->res_preview; } else if (s->res_independent) { s->real_resx = s->resx; s->real_resy = s->resy; } else { s->real_resx = s->res; s->real_resy = s->res; } s->real_pitchx = s->resx_max / s->real_resx; s->real_pitchy = s->resy_max / s->real_resy; s->real_resx = s->resx_max / s->real_pitchx; s->real_resy = s->resy_max / s->real_pitchy; /* The prefix "real_" refers to data in device units (1/maxdpi), "logical_" refers to resolution-dependent data. */ if (s->xmin < s->xmax) { xmin = s->xmin; xmax = s->xmax; } else { xmin = s->xmax; xmax = s->xmin; } if (s->ymin < s->ymax) { ymin = s->ymin; ymax = s->ymax; } else { ymin = s->ymax; ymax = s->ymin; } s->real_xoffset = xmin; s->real_yoffset = ymin + (s->i_frame - 1) * s->frame_offset + s->subframe / s->unit_mm; s->logical_width = (xmax - xmin + 1) / s->real_pitchx; /* XXXXXXXXX use mm units */ s->logical_height = (ymax - ymin + 1) / s->real_pitchy; s->real_width = s->logical_width * s->real_pitchx; s->real_height = s->logical_height * s->real_pitchy; s->odd_padding = 0; if ((s->bytes_per_pixel == 1) && (s->logical_width & 0x01) && (s->type != CS2_TYPE_LS30) && (s->type != CS2_TYPE_LS2000)) s->odd_padding = 1; if (s->focus_on_centre) { s->real_focusx = s->real_xoffset + s->real_width / 2; s->real_focusy = s->real_yoffset + s->real_height / 2; } else { s->real_focusx = s->focusx; s->real_focusy = s->focusy + (s->i_frame - 1) * s->frame_offset + s->subframe / s->unit_mm; } s->real_exposure[1] = s->exposure * s->exposure_r * 100.; s->real_exposure[2] = s->exposure * s->exposure_g * 100.; s->real_exposure[3] = s->exposure * s->exposure_b * 100.; for (i_colour = 0; i_colour < 3; i_colour++) if (s->real_exposure[cs2_colour_list[i_colour]] < 1) s->real_exposure[cs2_colour_list[i_colour]] = 1; s->n_colour_out = s->n_colour_in = 3; /* XXXXXXXXXXXXXX CCCCCCCCCCCCCC */ s->xfer_bytes_total = s->bytes_per_pixel * s->n_colour_out * s->logical_width * s->logical_height; if (s->preview) s->infrared_stage = s->infrared_next = CS2_INFRARED_OFF; else { if ((s->infrared) && (s->infrared_stage == CS2_INFRARED_OFF)) s->infrared_next = CS2_INFRARED_IN; s->infrared_stage = s->infrared_next; if (s->infrared) { s->n_colour_in ++; s->n_infrared_buf = s->bytes_per_pixel * s->logical_width * s->logical_height; infrared_buf_new = (SANE_Byte *) cs2_xrealloc (s->infrared_buf, s->n_infrared_buf); if (infrared_buf_new) s->infrared_buf = infrared_buf_new; else return SANE_STATUS_NO_MEM; } } return SANE_STATUS_GOOD; } static SANE_Status cs2_set_boundary (cs2_t *s) { SANE_Status status; int i_boundary; unsigned long lvalue; /* Ariel - Check this function */ cs2_scanner_ready (s, CS2_STATUS_READY); cs2_init_buffer (s); cs2_parse_cmd (s, "2a 00 88 00 00 03"); cs2_pack_byte (s, ((4 + s->n_frames * 16) >> 16) & 0xff); cs2_pack_byte (s, ((4 + s->n_frames * 16) >> 8) & 0xff); cs2_pack_byte (s, (4 + s->n_frames * 16) & 0xff); cs2_parse_cmd (s, "00"); cs2_pack_byte (s, ((4 + s->n_frames * 16) >> 8) & 0xff); cs2_pack_byte (s, (4 + s->n_frames * 16) & 0xff); cs2_pack_byte (s, s->n_frames); cs2_pack_byte (s, s->n_frames); for (i_boundary = 0; i_boundary < s->n_frames; i_boundary++) { lvalue = s->frame_offset * i_boundary + s->subframe / s->unit_mm; cs2_pack_byte (s, (lvalue >> 24) & 0xff); cs2_pack_byte (s, (lvalue >> 16) & 0xff); cs2_pack_byte (s, (lvalue >> 8) & 0xff); cs2_pack_byte (s, lvalue & 0xff); lvalue = 0; cs2_pack_byte (s, (lvalue >> 24) & 0xff); cs2_pack_byte (s, (lvalue >> 16) & 0xff); cs2_pack_byte (s, (lvalue >> 8) & 0xff); cs2_pack_byte (s, lvalue & 0xff); lvalue = s->frame_offset * i_boundary + s->subframe / s->unit_mm + s->frame_offset - 1; cs2_pack_byte (s, (lvalue >> 24) & 0xff); cs2_pack_byte (s, (lvalue >> 16) & 0xff); cs2_pack_byte (s, (lvalue >> 8) & 0xff); cs2_pack_byte (s, lvalue & 0xff); lvalue = s->boundaryx - 1; cs2_pack_byte (s, (lvalue >> 24) & 0xff); cs2_pack_byte (s, (lvalue >> 16) & 0xff); cs2_pack_byte (s, (lvalue >> 8) & 0xff); cs2_pack_byte (s, lvalue & 0xff); } status = cs2_issue_cmd (s); if (status) return status; return SANE_STATUS_GOOD; } static SANE_Status cs2_scan (cs2_t * s, cs2_scan_t type) { SANE_Status status; int i_colour; cs2_pixel_t pixel; cs2_pixel_t *lut; /* wait for device to be ready with document, and set device unit */ status = cs2_scanner_ready (s, CS2_STATUS_NO_DOCS); if (status) return status; if (s->status & CS2_STATUS_NO_DOCS) return SANE_STATUS_NO_DOCS; cs2_scanner_ready (s, CS2_STATUS_READY); cs2_init_buffer (s); /* Ariel - the '0b' byte in the 'else' part seems to be wrong, should be 0 */ if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000)) cs2_parse_cmd (s, "15 10 00 00 14 00 00 00 00 08 00 00 00 00 00 00 00 01 03 06 00 00"); else cs2_parse_cmd (s, "15 10 00 00 0c 00 0b 00 00 00 03 06 00 00"); cs2_pack_byte (s, (s->unit_dpi >> 8) & 0xff); cs2_pack_byte (s, s->unit_dpi & 0xff); cs2_parse_cmd (s, "00 00"); status = cs2_issue_cmd (s); if (status) return status; status = cs2_convert_options (s); if (status) return status; /* Ariel - Is this the best place to initialize it? */ s->block_padding = 0; status = cs2_set_boundary (s); if (status) return status; switch (type) { case CS2_SCAN_NORMAL: for (i_colour = 0; i_colour < s->n_colour_in; i_colour++) { cs2_scanner_ready (s, CS2_STATUS_READY); switch (i_colour) { case 0: lut = s->lut_r; break; case 1: lut = s->lut_g; break; case 2: lut = s->lut_b; break; case 3: lut = s->lut_neutral; break; default: DBG (1, "BUG: cs2_scan(): Unknown colour number for LUT download.\n"); return SANE_STATUS_INVAL; break; } cs2_init_buffer (s); cs2_parse_cmd (s, "2a 00 03 00"); cs2_pack_byte (s, cs2_colour_list[i_colour]); cs2_pack_byte (s, 2 - 1); /* XXXXXXXXXX number of bytes per data point - 1 */ cs2_pack_byte (s, ((2 * s->n_lut) >> 16) & 0xff); /* XXXXXXXXXX 2 bytes per point */ cs2_pack_byte (s, ((2 * s->n_lut) >> 8) & 0xff); /* XXXXXXXXXX 2 bytes per point */ cs2_pack_byte (s, (2 * s->n_lut) & 0xff); /* XXXXXXXXXX 2 bytes per point */ cs2_pack_byte (s, 0x00); for (pixel = 0; pixel < s->n_lut; pixel++) { /* XXXXXXXXXXXXXXX 2 bytes per point */ cs2_pack_byte (s, (lut[pixel] >> 8) & 0xff); cs2_pack_byte (s, lut[pixel] & 0xff); } status = cs2_issue_cmd (s); if (status) return status; } break; default: break; } for (i_colour = 0; i_colour < s->n_colour_in; i_colour++) { cs2_scanner_ready (s, CS2_STATUS_READY); cs2_init_buffer (s); if ((s->type == CS2_TYPE_LS40) || (s->type == CS2_TYPE_LS4000)) cs2_parse_cmd (s, "24 00 00 00 00 00 00 00 3a 80"); else cs2_parse_cmd (s, "24 00 00 00 00 00 00 00 3a 00"); cs2_parse_cmd (s, "00 00 00 00 00 00 00 32"); cs2_pack_byte (s, cs2_colour_list[i_colour]); cs2_pack_byte (s, 0x00); cs2_pack_byte (s, s->real_resx >> 8); cs2_pack_byte (s, s->real_resx & 0xff); cs2_pack_byte (s, s->real_resy >> 8); cs2_pack_byte (s, s->real_resy & 0xff); cs2_pack_byte (s, (s->real_xoffset >> 24) & 0xff); cs2_pack_byte (s, (s->real_xoffset >> 16) & 0xff); cs2_pack_byte (s, (s->real_xoffset >> 8) & 0xff); cs2_pack_byte (s, s->real_xoffset & 0xff); cs2_pack_byte (s, (s->real_yoffset >> 24) & 0xff); cs2_pack_byte (s, (s->real_yoffset >> 16) & 0xff); cs2_pack_byte (s, (s->real_yoffset >> 8) & 0xff); cs2_pack_byte (s, s->real_yoffset & 0xff); cs2_pack_byte (s, (s->real_width >> 24) & 0xff); cs2_pack_byte (s, (s->real_width >> 16) & 0xff); cs2_pack_byte (s, (s->real_width >> 8) & 0xff); cs2_pack_byte (s, s->real_width & 0xff); cs2_pack_byte (s, (s->real_height >> 24) & 0xff); cs2_pack_byte (s, (s->real_height >> 16) & 0xff); cs2_pack_byte (s, (s->real_height >> 8) & 0xff); cs2_pack_byte (s, s->real_height & 0xff); cs2_pack_byte (s, 0x00); /* brightness, etc. */ cs2_pack_byte (s, 0x00); cs2_pack_byte (s, 0x00); cs2_pack_byte (s, 0x05); /* image composition CCCCCCC */ cs2_pack_byte (s, s->real_depth); /* pixel composition */ cs2_parse_cmd (s, "00 00 00 00 00 00 00 00 00 00 00 00 00"); cs2_pack_byte (s, ((s->samples_per_scan - 1) << 4) + 0x00); /* multiread, ordering */ /* No need to use an undocumented bit in LS50 */ if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000)) cs2_pack_byte (s, 0x00 + (s->negative ? 0 : 1)); /* averaging, pos/neg */ else cs2_pack_byte (s, 0x80 + (s->negative ? 0 : 1)); /* averaging, pos/neg */ switch (type) { /* scanning kind */ case CS2_SCAN_NORMAL: cs2_pack_byte (s, 0x01); break; case CS2_SCAN_AE: cs2_pack_byte (s, 0x20); break; case CS2_SCAN_AE_WB: cs2_pack_byte (s, 0x40); break; default: DBG (1, "BUG: cs2_scan(): Unknown scanning type.\n"); return SANE_STATUS_INVAL; } if (s->samples_per_scan == 1) cs2_pack_byte (s, 0x02); /* scanning mode single */ else cs2_pack_byte (s, 0x10); /* scanning mode multi */ cs2_pack_byte (s, 0x02); /* colour interleaving */ cs2_pack_byte (s, 0xff); /* (ae) */ if (i_colour == 3) /* infrared */ cs2_parse_cmd (s, "00 00 00 00"); /* automatic */ else { cs2_pack_byte (s, (s-> real_exposure[cs2_colour_list[i_colour]] >> 24) & 0xff); cs2_pack_byte (s, (s-> real_exposure[cs2_colour_list[i_colour]] >> 16) & 0xff); cs2_pack_byte (s, (s-> real_exposure[cs2_colour_list[i_colour]] >> 8) & 0xff); cs2_pack_byte (s, s->real_exposure[cs2_colour_list[i_colour]] & 0xff); } status = cs2_issue_cmd (s); if (status) return status; } cs2_scanner_ready (s, CS2_STATUS_READY); cs2_focus (s); cs2_scanner_ready (s, CS2_STATUS_READY); cs2_init_buffer (s); switch (s->n_colour_in) { case 3: cs2_parse_cmd (s, "1b 00 00 00 03 00 01 02 03"); break; case 4: cs2_parse_cmd (s, "1b 00 00 00 04 00 01 02 03 09"); break; default: DBG (1, "BUG: cs2_scan(): Unknown number of input colours.\n"); break; } status = cs2_issue_cmd (s); if (status) return status; if (s->status == CS2_STATUS_REISSUE) { /* Make sure we don't affect the behaviour for other scanners */ if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000)) { cs2_init_buffer (s); cs2_parse_cmd (s, "28 00 87 00 00 00 00 00 06 00"); s->n_recv = 6; status = cs2_issue_cmd (s); if (status) return status; cs2_init_buffer (s); cs2_parse_cmd (s, "28 00 87 00 00 00 00 00"); cs2_pack_byte (s, s->recv_buf[5] + 6); cs2_parse_cmd (s, "00"); s->n_recv = s->recv_buf[5] + 6; status = cs2_issue_cmd (s); if (status) return status; if ((s->recv_buf[11] != 0x08) || (s->recv_buf[12] != 0x00)) DBG (1, "BUG: cs2_scan(): Unexpected block_padding position.\n"); s->block_padding = 256 * s->recv_buf[19] + s->recv_buf[20]; cs2_init_buffer (s); switch (s->n_colour_in) { case 3: cs2_parse_cmd (s, "1b 00 00 00 03 00 01 02 03"); break; case 4: cs2_parse_cmd (s, "1b 00 00 00 04 00 01 02 03 09"); break; } } status = cs2_issue_cmd (s); if (status) return status; } return SANE_STATUS_GOOD; } static void * cs2_xmalloc (size_t size) { register void *value = malloc (size); if (!value) DBG (0, "Error: cs2_xmalloc(): Failed to malloc() %lu bytes.\n", (unsigned long) size); return value; } static void * cs2_xrealloc (void *p, size_t size) { register void *value; if (!size) return p; value = realloc (p, size); if (!value) DBG (0, "Error: cs2_xrealloc(): Failed to realloc() %lu bytes.\n", (unsigned long) size); return value; } static void cs2_xfree (const void *p) { if (p) free ((void *) p); } sane-backends-1.0.27/backend/lexmark.h0000664000175000017500000002013412775312261014433 00000000000000/************************************************************************ lexmark.h - SANE library for Lexmark scanners. Copyright (C) 2003-2004 Lexmark International, Inc. (original source) Copyright (C) 2005 Fred Odendaal Copyright (C) 2006-2010 Stéphane Voltz Copyright (C) 2010 "Torsten Houwaart" X74 support This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. **************************************************************************/ #ifndef LEXMARK_H #define LEXMARK_H #undef DEEP_DEBUG #include "../include/sane/config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" #include "../include/sane/sanei_config.h" #include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_backend.h" typedef enum { OPT_NUM_OPTS = 0, OPT_MODE, OPT_RESOLUTION, OPT_PREVIEW, OPT_THRESHOLD, OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ OPT_BR_X, /* bottom-right x */ OPT_BR_Y, /* bottom-right y */ /* manual gain handling */ OPT_MANUAL_GAIN, /* 6 */ OPT_GRAY_GAIN, OPT_RED_GAIN, OPT_GREEN_GAIN, OPT_BLUE_GAIN, /* must come last: */ NUM_OPTIONS } Lexmark_Options; /* * this struct is used to described the specific parts of each model */ typedef struct Lexmark_Model { SANE_Int vendor_id; SANE_Int product_id; SANE_Byte mainboard_id; /* matched against the content of reg B0 */ SANE_String_Const name; SANE_String_Const vendor; SANE_String_Const model; SANE_Int motor_type; SANE_Int sensor_type; SANE_Int HomeEdgePoint1; SANE_Int HomeEdgePoint2; } Lexmark_Model; /* * this struct is used to store per sensor model constants */ typedef struct Lexmark_Sensor { SANE_Int id; SANE_Int offset_startx; /* starting x for offset calibration */ SANE_Int offset_endx; /* end x for offset calibration */ SANE_Int offset_threshold; /* target threshold for offset calibration */ SANE_Int xoffset; /* number of unusable pixels on the start of the sensor */ SANE_Int default_gain; /* value of the default gain for a scan */ SANE_Int red_gain_target; SANE_Int green_gain_target; SANE_Int blue_gain_target; SANE_Int gray_gain_target; SANE_Int red_shading_target; SANE_Int green_shading_target; SANE_Int blue_shading_target; SANE_Int gray_shading_target; SANE_Int offset_fallback; /* offset to use in case offset calibration fails */ SANE_Int gain_fallback; /* gain to use in case offset calibration fails */ } Lexmark_Sensor; typedef enum { RED = 0, GREEN, BLUE } Scan_Regions; /* struct to hold pre channel settings */ typedef struct Channels { SANE_Word red; SANE_Word green; SANE_Word blue; SANE_Word gray; } Channels; /** @name Option_Value union * convenience union to access option values given to the backend * @{ */ #ifndef SANE_OPTION #define SANE_OPTION 1 typedef union { SANE_Bool b; SANE_Word w; SANE_Word *wa; /* word array */ SANE_String s; } Option_Value; #endif /* @} */ typedef struct Read_Buffer { SANE_Int gray_offset; SANE_Int max_gray_offset; SANE_Int region; SANE_Int red_offset; SANE_Int green_offset; SANE_Int blue_offset; SANE_Int max_red_offset; SANE_Int max_green_offset; SANE_Int max_blue_offset; SANE_Byte *data; SANE_Byte *readptr; SANE_Byte *writeptr; SANE_Byte *max_writeptr; size_t size; size_t linesize; SANE_Bool empty; SANE_Int image_line_no; SANE_Int bit_counter; SANE_Int max_lineart_offset; } Read_Buffer; typedef struct Lexmark_Device { struct Lexmark_Device *next; SANE_Bool missing; /**< devices has been unplugged or swtiched off */ SANE_Device sane; SANE_Option_Descriptor opt[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS]; SANE_Parameters params; SANE_Int devnum; long data_size; SANE_Bool initialized; SANE_Bool eof; SANE_Int x_dpi; SANE_Int y_dpi; long data_ctr; SANE_Bool device_cancelled; SANE_Int cancel_ctr; SANE_Byte *transfer_buffer; size_t bytes_read; size_t bytes_remaining; size_t bytes_in_buffer; SANE_Byte *read_pointer; Read_Buffer *read_buffer; SANE_Byte threshold; Lexmark_Model model; /* per model data */ Lexmark_Sensor *sensor; SANE_Byte shadow_regs[255]; /* shadow registers */ struct Channels offset; struct Channels gain; float *shading_coeff; } Lexmark_Device; /* Maximum transfer size */ #define MAX_XFER_SIZE 0xFFC0 /* motors and sensors type defines */ #define X1100_MOTOR 1 #define A920_MOTOR 2 #define X74_MOTOR 3 #define X1100_B2_SENSOR 4 #define A920_SENSOR 5 #define X1100_2C_SENSOR 6 #define X1200_SENSOR 7 /* X1200 on USB 1.0 */ #define X1200_USB2_SENSOR 8 /* X1200 on USB 2.0 */ #define X74_SENSOR 9 /* Non-static Function Proto-types (called by lexmark.c) */ SANE_Status sanei_lexmark_low_init (Lexmark_Device * dev); void sanei_lexmark_low_destroy (Lexmark_Device * dev); SANE_Status sanei_lexmark_low_open_device (Lexmark_Device * dev); void sanei_lexmark_low_close_device (Lexmark_Device * dev); SANE_Bool sanei_lexmark_low_search_home_fwd (Lexmark_Device * dev); void sanei_lexmark_low_move_fwd (SANE_Int distance, Lexmark_Device * dev, SANE_Byte * regs); SANE_Bool sanei_lexmark_low_X74_search_home (Lexmark_Device * dev, SANE_Byte * regs); SANE_Bool sanei_lexmark_low_search_home_bwd (Lexmark_Device * dev); SANE_Int sanei_lexmark_low_find_start_line (Lexmark_Device * dev); SANE_Status sanei_lexmark_low_set_scan_regs (Lexmark_Device * dev, SANE_Int resolution, SANE_Int offset, SANE_Bool calibrated); SANE_Status sanei_lexmark_low_start_scan (Lexmark_Device * dev); long sanei_lexmark_low_read_scan_data (SANE_Byte * data, SANE_Int size, Lexmark_Device * dev); SANE_Status sanei_lexmark_low_assign_model (Lexmark_Device * dev, SANE_String_Const devname, SANE_Int vendor, SANE_Int product, SANE_Byte mainboard); /* * scanner calibration functions */ SANE_Status sanei_lexmark_low_offset_calibration (Lexmark_Device * dev); SANE_Status sanei_lexmark_low_gain_calibration (Lexmark_Device * dev); SANE_Status sanei_lexmark_low_shading_calibration (Lexmark_Device * dev); SANE_Status sanei_lexmark_low_calibration (Lexmark_Device * dev); #endif /* LEXMARK_H */ sane-backends-1.0.27/backend/hp-hpmem.c0000664000175000017500000000745612112021330014465 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 1997 Geoffrey T. Dairiki This file is part of the SANE package. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. This file is part of a SANE backend for HP Scanners supporting HP Scanner Control Language (SCL). */ /* #define STUBS extern int sanei_debug_hp;*/ #define DEBUG_DECLARE_ONLY #include "../include/sane/config.h" #include #include #include "../include/lassert.h" #include "hp.h" typedef struct hp_alloc_s Alloc; struct hp_alloc_s { Alloc * prev; Alloc * next; hp_byte_t buf[1]; }; static Alloc head[] = {{ head, head, {0} }}; #define DATA_OFFSET (head->buf - (hp_byte_t *)head) #define VOID_TO_ALLOCP(p) ((Alloc *)((hp_byte_t *)(p) - DATA_OFFSET)) #define ALLOCSIZE(sz) (sz + DATA_OFFSET) void * sanei_hp_alloc (size_t sz) { Alloc * new = malloc(ALLOCSIZE(sz)); if (!new) return 0; (new->next = head->next)->prev = new; (new->prev = head)->next = new; return new->buf; } void * sanei_hp_allocz (size_t sz) { void * new = sanei_hp_alloc(sz); if (!new) return 0; memset(new, 0, sz); return new; } void * sanei_hp_memdup (const void * src, size_t sz) { char * new = sanei_hp_alloc(sz); if (!new) return 0; return memcpy(new, src, sz); } char * sanei_hp_strdup (const char * str) { return sanei_hp_memdup(str, strlen(str) + 1); } void * sanei_hp_realloc (void * ptr, size_t sz) { if (ptr) { Alloc * old = VOID_TO_ALLOCP(ptr); Alloc copy = *old; Alloc * new = realloc(old, ALLOCSIZE(sz)); if (!new) return 0; if (new != old) (new->prev = copy.prev)->next = (new->next = copy.next)->prev = new; return new->buf; } else return sanei_hp_alloc(sz); } void sanei_hp_free (void * ptr) { Alloc * old = VOID_TO_ALLOCP(ptr); assert(old && old != head); (old->next->prev = old->prev)->next = old->next; old->next = old->prev = 0; /* so we can puke on multiple free's */ free(old); } void sanei_hp_free_all (void) { Alloc * ptr; Alloc * next; for (ptr = head->next; ptr != head; ptr = next) { next = ptr->next; free(ptr); } head->next = head->prev = head; } sane-backends-1.0.27/backend/umax-scanner.h0000664000175000017500000000424612112021330015352 00000000000000/* -------------------------------------------------------------------- */ /* umax-scanner.h: scanner-definiton header-file for UMAX scanner driver. (C) 1997-2002 Oliver Rauch This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, the authors of SANE give permission for additional uses of the libraries contained in this release of SANE. The exception is that, if you link a SANE library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the SANE library code into it. This exception does not, however, invalidate any other reasons why the executable file might be covered by the GNU General Public License. If you submit changes to SANE to the maintainers to be included in a subsequent release, you agree by submitting the changes that those changes may be distributed with this exception intact. If you write modifications of your own for SANE, it is your choice whether to permit this exception to apply to your modifications. If you do not wish that, delete this exception notice. */ /* -------------------------------------------------------------------- */ #ifndef UMAX_SCANNER_H #define UMAX_SCANNER_H /* -------------------------------------------------------------------- */ typedef struct { char *scanner; unsigned char *inquiry; int inquiry_len; } inquiry_blk; #endif sane-backends-1.0.27/backend/p5_device.h0000664000175000017500000001764412775277260014660 00000000000000/* sane - Scanner Access Now Easy. Copyright (C) 2009-2012 stef.dev@free.fr This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** @file p5_device.h * @brief Declaration of low level structures used by the p5 backend. * * The structures and function declared here are used to do the low level * communication with the physical device. */ #ifndef P5_DEVICE_H #define P5_DEVICE_H #include #include #include #include "../include/_stdint.h" #ifdef HAVE_LINUX_PPDEV_H #include #include #include #include #include #include #endif /** @name debugging levels */ /* @{ */ #define DBG_error0 0 /* errors/warnings printed even with devuglevel 0 */ #define DBG_error 1 /* fatal errors */ #define DBG_warn 2 /* warnings and non-fatal errors */ #define DBG_info 4 /* informational messages */ #define DBG_proc 8 /* starting/finishing functions */ #define DBG_trace 16 /* tracing messages */ #define DBG_io 32 /* io functions */ #define DBG_io2 64 /* io functions that are called very often */ #define DBG_data 128 /* log image data */ /* @} */ /** * maximal number of resolutions */ #define MAX_RESOLUTIONS 8 /**> sensor's number of pixels 8.5' @ 300 dpi */ #define MAX_SENSOR_PIXELS 2550 /**> number of lines to skip when doing calibration */ #define CALIBRATION_SKIP_LINES 80 /**> last value considered as black for calibration */ #define BLACK_LEVEL 40 /**> white target value for calibration */ #define WHITE_TARGET 220.0 /** per dpi calibration rgb data * Calibration data structure */ typedef struct P5_Calibration_Data { unsigned int dpi; uint8_t black_data[MAX_SENSOR_PIXELS * 3]; uint8_t white_data[MAX_SENSOR_PIXELS * 3]; } P5_Calibration_Data; /** * This structure describes a particular model which is handled by the backend. * Contained data is immutable and is used to initalize the P5_Device * structure. */ typedef struct P5_Model { /** @name device identifier * These values are set up once the physical device has been detected. They * are used to build the return value of sane_get_devices(). */ /* @{ */ SANE_String_Const name; SANE_String_Const vendor; SANE_String_Const product; SANE_String_Const type; /* @} */ /** @name resolution * list of avalailable physical resolution. * The resolutions must sorted from lower to higher value. The list is terminated * by a value of 0. */ /* @{ */ int xdpi_values[MAX_RESOLUTIONS]; /** possible x resolutions */ int ydpi_values[MAX_RESOLUTIONS]; /** possible y resolutions */ /* @} */ /** @name scan area description * Minimal and maximal values. It's easier to have dedicated members instead * of searching these values in the dpi lists. They are initialized from dpi * lists. */ /* @{ */ int max_xdpi; /** physical maximum x dpi */ int max_ydpi; /** physical maximum y dpi */ int min_xdpi; /** physical minimum x dpi */ int min_ydpi; /** physical minimum y dpi */ /* @} */ /** @name line distance shift * Distance between CCD arrays for each color. Expressed in line * number at maximum motor resolution. */ int lds; /** @name scan area description * The geometry values are expressed from the head parking position, * or the start. For a given model, the scan area selected by a frontend * will have to fit within these values. */ /* @{ */ SANE_Fixed x_offset; /** Start of scan area in mm */ SANE_Fixed y_offset; /** Start of scan area in mm */ SANE_Fixed x_size; /** Size of scan area in mm */ SANE_Fixed y_size; /** Size of scan area in mm */ /* @} */ } P5_Model; /** * Enumeration of configuration options for a device. It must starts at 0. */ enum P5_Configure_Option { CFG_MODEL_NAME = 0, /**
&1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sane-backends' PACKAGE_TARNAME='sane-backends' PACKAGE_VERSION='1.0.27' PACKAGE_STRING='sane-backends 1.0.27' PACKAGE_BUGREPORT='sane-devel@lists.alioth.debian.org' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" gt_needs= ac_config_libobj_dir=lib ac_header_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS AM_LDFLAGS AM_CFLAGS AM_CPPFLAGS WITH_API_HTML_FALSE WITH_API_HTML_TRUE WITH_API_PDF_FALSE WITH_API_PDF_TRUE WITH_API_PS_FALSE WITH_API_PS_TRUE PPMTOGIF DLH GS FIG2DEV PDFLATEX LATEX DVIPS MAKEINDEX BACKEND_MANS_ENABLED BACKEND_CONFS_ENABLED PRELOADABLE_BACKENDS_ENABLED PRELOADABLE_BACKENDS INSTALL_UMAX_PP_TOOLS_FALSE INSTALL_UMAX_PP_TOOLS_TRUE BACKEND_LIBS_ENABLED SANEI_SANEI_JPEG_LO HAVE_JPEG_FALSE HAVE_JPEG_TRUE BACKENDS COMPILE_SANED_FALSE COMPILE_SANED_TRUE configdir locksanedir SCSI_LIBS have_usblib_FALSE have_usblib_TRUE USB_LIBS USB_CFLAGS SYSTEMD_LIBS SYSTEMD_CFLAGS SOCKET_LIBS LTALLOCA LIBOBJS ALLOCA RESMGR_LIBS SNMP_CFLAGS SNMP_LIBS SNMP_CONFIG_PATH AVAHI_LIBS AVAHI_CFLAGS LIBV4L_LIBS LIBV4L_CFLAGS GPHOTO2_LDFLAGS GPHOTO2_LIBS GPHOTO2_CPPFLAGS HAVE_GPHOTO2 LOCKPATH_GROUP INSTALL_LOCKPATH PTHREAD_LIBS IEEE1284_LIBS PNG_LIBS TIFF_LIBS JPEG_LIBS SYSLOG_LIBS MATH_LIB DYNAMIC_FLAG DL_LIBS effective_target STRICT_LDFLAGS CROSS_COMPILING_FALSE CROSS_COMPILING_TRUE PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG SANE_CONFIG_PATH POSUB LTLIBINTL LIBINTL INTLLIBS LTLIBICONV LIBICONV INTL_MACOSX_LIBS XGETTEXT_EXTRA_OPTIONS MSGMERGE XGETTEXT_015 XGETTEXT GMSGFMT_015 MSGFMT_015 GMSGFMT MSGFMT GETTEXT_MACRO_VERSION USE_NLS OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL OBJDUMP DLLTOOL AS ac_ct_AR AR EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC V_REV V_MINOR V_MAJOR MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_maintainer_mode enable_dependency_tracking enable_static enable_shared with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_nls enable_rpath with_libiconv_prefix with_libintl_prefix enable_warnings enable_dynamic enable_pthread enable_locking with_group with_gphoto2 with_v4l enable_avahi with_snmp with_systemd with_usb enable_scsibuffersize enable_scsi_directio enable_ipv6 enable_preload with_lockdir enable_local_backends enable_pnm_backend enable_parport_directio with_api_spec ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR LIBV4L_CFLAGS LIBV4L_LIBS AVAHI_CFLAGS AVAHI_LIBS SYSTEMD_CFLAGS SYSTEMD_LIBS USB_CFLAGS USB_LIBS BACKENDS PRELOADABLE_BACKENDS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sane-backends 1.0.27 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/sane-backends] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sane-backends 1.0.27:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-nls do not use Native Language Support --disable-rpath do not hardcode runtime library paths --enable-warnings turn on tons of compiler warnings (GCC only) --disable-dynamic Disable dynamic loading of backends --enable-pthread use pthread instead of fork (default=yes for Linux/MacOS X/MINGW, no for everything else) --enable-locking activate device locking (default=yes, but only used by some backends) --enable-avahi enable Avahi support for saned and the net backend --enable-scsibuffersize=N specify the default size in bytes of the buffer for SCSI commands [default=131072] --enable-scsi-directio enable SCSI direct IO (Linux only, dangerous, see README.linux) --disable-ipv6 disable IPv6 support --disable-preload Disable preloading of backends --disable-local-backends turn off compilation of all backends but net --enable-pnm-backend enable the pnm backend for testing frontends (possible security risk, see PROBLEMS file) --enable-parport-directio enable direct hardware access to the parallel port, so frontends will require special permission level Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib --without-libiconv-prefix don't search for libiconv in includedir and libdir --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib --without-libintl-prefix don't search for libintl in includedir and libdir --with-group use the specified group for lock dir [default=uucp] --with-gphoto2 include the gphoto2 backend [default=yes] --with-v4l include the v4l backend [default=yes] --with-snmp enable SNMP support [default=yes] --with-systemd enable systemd support [default=yes] --with-usb enable USB support [default=check] --with-lockdir=DIR set SANE lockdir [localstatedir/lock/sane] --with-api-spec convert API spec to supported output formats [default=check] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path LIBV4L_CFLAGS C compiler flags for LIBV4L, overriding pkg-config LIBV4L_LIBS linker flags for LIBV4L, overriding pkg-config AVAHI_CFLAGS C compiler flags for AVAHI, overriding pkg-config AVAHI_LIBS linker flags for AVAHI, overriding pkg-config SYSTEMD_CFLAGS C compiler flags for SYSTEMD, overriding pkg-config SYSTEMD_LIBS linker flags for SYSTEMD, overriding pkg-config USB_CFLAGS C compiler flags for USB, overriding pkg-config USB_LIBS linker flags for USB, overriding pkg-config BACKENDS list of backends to compile PRELOADABLE_BACKENDS list of backends to preload into single DLL Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sane-backends configure 1.0.27 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------------------------- ## ## Report this to sane-devel@lists.alioth.debian.org ## ## ------------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sane-backends $as_me 1.0.27, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi gt_needs="$gt_needs " as_fn_append ac_header_list " stdlib.h" as_fn_append ac_header_list " unistd.h" as_fn_append ac_header_list " sys/param.h" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers include/sane/config.h" am__api_version='1.14' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='sane-backends' VERSION='1.0.27' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE if test x = "x$AWK"; then : for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done fi if test x = "x`echo $VERSION | sed 's/[.0-9]//g'`"; then : is_release=yes else is_release=no fi V_MAJOR=`echo $VERSION | $AWK -F. '{print $1}'` V_MINOR=`echo $VERSION | $AWK -F. '{print $2}'` V_REV=`echo $VERSION | $AWK -F. '{print $3}' | sed 's/[^0-9]//g'`; cat >>confdefs.h <<_ACEOF #define SANE_DLL_V_MAJOR $V_MAJOR _ACEOF cat >>confdefs.h <<_ACEOF #define SANE_DLL_V_MINOR $V_MINOR _ACEOF cat >>confdefs.h <<_ACEOF #define SANE_DLL_V_BUILD $V_REV _ACEOF ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi sane_save_CC=$CC { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : fi if test xno != "x$ac_cv_prog_cc_c99"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $sane_save_CC option for ISO C99 w/o extensions" >&5 $as_echo_n "checking for $sane_save_CC option for ISO C99 w/o extensions... " >&6; } case $ac_cv_prog_cc_c99 in #( -std=gnu99) : sane_prog_cc_c99="-std=c99" ;; #( -qlanglvl=extc99) : sane_prog_cc_c99="-qlanglvl=stdc99" ;; #( *) : ;; esac if test "x$ac_cv_prog_cc_c99" = "x$sane_prog_cc_c99"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_99" >&5 $as_echo "$ac_cv_prog_cc_99" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sane_prog_cc_c99" >&5 $as_echo "$sane_prog_cc_c99" >&6; } CC="$sane_save_CC $sane_prog_cc_c99" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" if test $ac_cv_c_compiler_gnu = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 $as_echo_n "checking whether $CC needs -traditional... " >&6; } if ${ac_cv_prog_gcc_traditional+:} false; then : $as_echo_n "(cached) " >&6 else ac_pattern="Autoconf.*'x'" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Autoconf TIOCGETP _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then : ac_cv_prog_gcc_traditional=yes else ac_cv_prog_gcc_traditional=no fi rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Autoconf TCGETA _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then : ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 $as_echo "$ac_cv_prog_gcc_traditional" >&6; } if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" if test "x$ac_cv_header_minix_config_h" = xyes; then : MINIX=yes else MINIX= fi if test "$MINIX" = yes; then $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h $as_echo "#define _MINIX 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 $as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } if ${ac_cv_safe_to_define___extensions__+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define __EXTENSIONS__ 1 $ac_includes_default int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_safe_to_define___extensions__=yes else ac_cv_safe_to_define___extensions__=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } test $ac_cv_safe_to_define___extensions__ = yes && $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h $as_echo "#define _ALL_SOURCE 1" >>confdefs.h $as_echo "#define _GNU_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h if test -n "$ac_tool_prefix"; then for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} { $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 $as_echo_n "checking the archiver ($AR) interface... " >&6; } if ${am_cv_ar_interface+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am_cv_ar_interface=ar cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int some_variable = 0; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 $as_echo "$am_cv_ar_interface" >&6; } case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) as_fn_error $? "could not determine $AR interface" "$LINENO" 5 ;; esac case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1
&5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=no fi enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. set dummy ${ac_tool_prefix}as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AS="${ac_tool_prefix}as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AS=$ac_cv_prog_AS if test -n "$AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 $as_echo "$AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AS"; then ac_ct_AS=$AS # Extract the first word of "as", so it can be a program name with args. set dummy as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AS"; then ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AS="as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AS=$ac_cv_prog_ac_ct_AS if test -n "$ac_ct_AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 $as_echo "$ac_ct_AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AS" = x; then AS="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AS=$ac_ct_AS fi else AS="$ac_cv_prog_AS" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi ;; esac test -z "$AS" && AS=as test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$OBJDUMP" && OBJDUMP=objdump enable_dlopen=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 $as_echo_n "checking whether NLS is requested... " >&6; } # Check whether --enable-nls was given. if test "${enable_nls+set}" = set; then : enableval=$enable_nls; USE_NLS=$enableval else USE_NLS=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 $as_echo "$USE_NLS" >&6; } GETTEXT_MACRO_VERSION=0.18 # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case "$MSGFMT" in [\\/]* | ?:[\\/]*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" ;; esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 $as_echo "$MSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GMSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case $GMSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT if test -n "$GMSGFMT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 $as_echo "$GMSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; *) MSGFMT_015=$MSGFMT ;; esac case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; *) GMSGFMT_015=$GMSGFMT ;; esac # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_XGETTEXT+:} false; then : $as_echo_n "(cached) " >&6 else case "$XGETTEXT" in [\\/]* | ?:[\\/]*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" ;; esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 $as_echo "$XGETTEXT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f messages.po case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; *) XGETTEXT_015=$XGETTEXT ;; esac # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGMERGE+:} false; then : $as_echo_n "(cached) " >&6 else case "$MSGMERGE" in [\\/]* | ?:[\\/]*) ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" ;; esac fi MSGMERGE="$ac_cv_path_MSGMERGE" if test "$MSGMERGE" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 $as_echo "$MSGMERGE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$localedir" || localedir='${datadir}/locale' test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= ac_config_commands="$ac_config_commands po-directories" if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5 $as_echo_n "checking for ld used by GCC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | [A-Za-z]:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${acl_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$acl_cv_path_LD" if test -n "$LD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${acl_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 &5 $as_echo "$acl_cv_prog_gnu_ld" >&6; } with_gnu_ld=$acl_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 $as_echo_n "checking for shared library run path origin... " >&6; } if ${acl_cv_rpath+:} false; then : $as_echo_n "(cached) " >&6 else CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 $as_echo "$acl_cv_rpath" >&6; } wl="$acl_cv_wl" acl_libext="$acl_cv_libext" acl_shlibext="$acl_cv_shlibext" acl_libname_spec="$acl_cv_libname_spec" acl_library_names_spec="$acl_cv_library_names_spec" acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" acl_hardcode_direct="$acl_cv_hardcode_direct" acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" # Check whether --enable-rpath was given. if test "${enable_rpath+set}" = set; then : enableval=$enable_rpath; : else enable_rpath=yes fi acl_libdirstem=lib acl_libdirstem2= case "$host_os" in solaris*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5 $as_echo_n "checking for 64-bit host... " >&6; } if ${gl_cv_solaris_64bit+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef _LP64 sixtyfour bits #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "sixtyfour bits" >/dev/null 2>&1; then : gl_cv_solaris_64bit=yes else gl_cv_solaris_64bit=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_solaris_64bit" >&5 $as_echo "$gl_cv_solaris_64bit" >&6; } if test $gl_cv_solaris_64bit = yes; then acl_libdirstem=lib/64 case "$host_cpu" in sparc*) acl_libdirstem2=lib/sparcv9 ;; i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; esac fi ;; *) searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test -n "$searchpath"; then acl_save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; */../ | */.. ) # Better ignore directories of this form. They are misleading. ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) acl_libdirstem=lib64 ;; esac ;; esac fi done IFS="$acl_save_IFS" fi ;; esac test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libiconv-prefix was given. if test "${with_libiconv_prefix+set}" = set; then : withval=$with_libiconv_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" if test "$acl_libdirstem2" != "$acl_libdirstem" \ && ! test -d "$withval/$acl_libdirstem"; then additional_libdir="$withval/$acl_libdirstem2" fi fi fi fi LIBICONV= LTLIBICONV= INCICONV= LIBICONV_PREFIX= HAVE_LIBICONV= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='iconv ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" else : fi else found_dir= found_la= found_so= found_a= eval libname=\"$acl_libname_spec\" # typically: libname=lib$name if test -n "$acl_shlibext"; then shrext=".$acl_shlibext" # typically: shrext=.so else shrext= fi if test $use_additional = yes; then dir="$additional_libdir" if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no \ || test "X$found_dir" = "X/usr/$acl_libdirstem" \ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$acl_hardcode_direct" = yes; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" fi if test "$acl_hardcode_minus_L" != no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" else LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` if test "$name" = 'iconv'; then LIBICONV_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; */$acl_libdirstem2 | */$acl_libdirstem2/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` if test "$name" = 'iconv'; then LIBICONV_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" ;; esac done fi else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$acl_hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 $as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : $as_echo_n "(cached) " >&6 else gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { CFPreferencesCopyAppValue(NULL, NULL) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : gt_cv_func_CFPreferencesCopyAppValue=yes else gt_cv_func_CFPreferencesCopyAppValue=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$gt_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 $as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then $as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 $as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : $as_echo_n "(cached) " >&6 else gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { CFLocaleCopyCurrent(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : gt_cv_func_CFLocaleCopyCurrent=yes else gt_cv_func_CFLocaleCopyCurrent=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$gt_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 $as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } if test $gt_cv_func_CFLocaleCopyCurrent = yes; then $as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi LIBINTL= LTLIBINTL= POSUB= case " $gt_needs " in *" need-formatstring-macros "*) gt_api_version=3 ;; *" need-ngettext "*) gt_api_version=2 ;; *) gt_api_version=1 ;; esac gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no if test $gt_api_version -ge 3; then gt_revision_test_code=' #ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; ' else gt_revision_test_code= fi if test $gt_api_version -ge 2; then gt_expression_test_code=' + * ngettext ("", "", 0)' else gt_expression_test_code= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 $as_echo_n "checking for GNU gettext in libc... " >&6; } if eval \${$gt_func_gnugettext_libc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings; int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$gt_func_gnugettext_libc=yes" else eval "$gt_func_gnugettext_libc=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$gt_func_gnugettext_libc { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then am_save_CPPFLAGS="$CPPFLAGS" for element in $INCICONV; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 $as_echo_n "checking for iconv... " >&6; } if ${am_cv_func_iconv+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_lib_iconv=yes am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$am_save_LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 $as_echo "$am_cv_func_iconv" >&6; } if test "$am_cv_func_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 $as_echo_n "checking for working iconv... " >&6; } if ${am_cv_func_iconv_works+:} false; then : $as_echo_n "(cached) " >&6 else am_save_LIBS="$LIBS" if test $am_cv_lib_iconv = yes; then LIBS="$LIBS $LIBICONV" fi if test "$cross_compiling" = yes; then : case "$host_os" in aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; *) am_cv_func_iconv_works="guessing yes" ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { /* Test against AIX 5.1 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); if (cd_utf8_to_88591 != (iconv_t)(-1)) { static const char input[] = "\342\202\254"; /* EURO SIGN */ char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_utf8_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } /* Test against Solaris 10 bug: Failures are not distinguishable from successful returns. */ { iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); if (cd_ascii_to_88591 != (iconv_t)(-1)) { static const char input[] = "\263"; char buf[10]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_ascii_to_88591, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if (res == 0) return 1; } } #if 0 /* This bug could be worked around by the caller. */ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ { iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); if (cd_88591_to_utf8 != (iconv_t)(-1)) { static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; char buf[50]; const char *inptr = input; size_t inbytesleft = strlen (input); char *outptr = buf; size_t outbytesleft = sizeof (buf); size_t res = iconv (cd_88591_to_utf8, (char **) &inptr, &inbytesleft, &outptr, &outbytesleft); if ((int)res > 0) return 1; } } #endif /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is provided. */ if (/* Try standardized names. */ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) /* Try IRIX, OSF/1 names. */ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) /* Try AIX names. */ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) /* Try HP-UX names. */ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) return 1; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : am_cv_func_iconv_works=yes else am_cv_func_iconv_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi LIBS="$am_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 $as_echo "$am_cv_func_iconv_works" >&6; } case "$am_cv_func_iconv_works" in *no) am_func_iconv=no am_cv_lib_iconv=no ;; *) am_func_iconv=yes ;; esac else am_func_iconv=no am_cv_lib_iconv=no fi if test "$am_func_iconv" = yes; then $as_echo "#define HAVE_ICONV 1" >>confdefs.h fi if test "$am_cv_lib_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 $as_echo_n "checking how to link with libiconv... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 $as_echo "$LIBICONV" >&6; } else CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libintl-prefix was given. if test "${with_libintl_prefix+set}" = set; then : withval=$with_libintl_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" if test "$acl_libdirstem2" != "$acl_libdirstem" \ && ! test -d "$withval/$acl_libdirstem"; then additional_libdir="$withval/$acl_libdirstem2" fi fi fi fi LIBINTL= LTLIBINTL= INCINTL= LIBINTL_PREFIX= HAVE_LIBINTL= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='intl ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" else : fi else found_dir= found_la= found_so= found_a= eval libname=\"$acl_libname_spec\" # typically: libname=lib$name if test -n "$acl_shlibext"; then shrext=".$acl_shlibext" # typically: shrext=.so else shrext= fi if test $use_additional = yes; then dir="$additional_libdir" if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$acl_shlibext"; then if test -f "$dir/$libname$shrext"; then found_dir="$dir" found_so="$dir/$libname$shrext" else if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then ver=`(cd "$dir" && \ for f in "$libname$shrext".*; do echo "$f"; done \ | sed -e "s,^$libname$shrext\\\\.,," \ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ | sed 1q ) 2>/dev/null` if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then found_dir="$dir" found_so="$dir/$libname$shrext.$ver" fi else eval library_names=\"$acl_library_names_spec\" for f in $library_names; do if test -f "$dir/$f"; then found_dir="$dir" found_so="$dir/$f" break fi done fi fi fi if test "X$found_dir" = "X"; then if test -f "$dir/$libname.$acl_libext"; then found_dir="$dir" found_a="$dir/$libname.$acl_libext" fi fi if test "X$found_dir" != "X"; then if test -f "$dir/$libname.la"; then found_la="$dir/$libname.la" fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no \ || test "X$found_dir" = "X/usr/$acl_libdirstem" \ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$acl_hardcode_direct" = yes; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" fi if test "$acl_hardcode_minus_L" != no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" else LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` if test "$name" = 'intl'; then LIBINTL_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; */$acl_libdirstem2 | */$acl_libdirstem2/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` if test "$name" = 'intl'; then LIBINTL_PREFIX="$basedir" fi additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" ;; esac done fi else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$acl_hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$acl_hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 $as_echo_n "checking for GNU gettext in libintl... " >&6; } if eval \${$gt_func_gnugettext_libintl+:} false; then : $as_echo_n "(cached) " >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$gt_func_gnugettext_libintl=yes" else eval "$gt_func_gnugettext_libintl=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" eval "$gt_func_gnugettext_libintl=yes" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi eval ac_res=\$$gt_func_gnugettext_libintl { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else LIBINTL= LTLIBINTL= INCINTL= fi if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then $as_echo "#define ENABLE_NLS 1" >>confdefs.h else USE_NLS=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 $as_echo_n "checking whether to use NLS... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 $as_echo "$USE_NLS" >&6; } if test "$USE_NLS" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 $as_echo_n "checking where the gettext function comes from... " >&6; } if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 $as_echo "$gt_source" >&6; } fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 $as_echo_n "checking how to link with libintl... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 $as_echo "$LIBINTL" >&6; } for element in $INCINTL; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done fi $as_echo "#define HAVE_GETTEXT 1" >>confdefs.h $as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h fi POSUB=po fi INTLLIBS="$LIBINTL" # Extract the first word of "sane-config", so it can be a program name with args. set dummy sane-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SANE_CONFIG_PATH+:} false; then : $as_echo_n "(cached) " >&6 else case $SANE_CONFIG_PATH in [\\/]* | ?:[\\/]*) ac_cv_path_SANE_CONFIG_PATH="$SANE_CONFIG_PATH" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SANE_CONFIG_PATH="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_SANE_CONFIG_PATH" && ac_cv_path_SANE_CONFIG_PATH="no" ;; esac fi SANE_CONFIG_PATH=$ac_cv_path_SANE_CONFIG_PATH if test -n "$SANE_CONFIG_PATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SANE_CONFIG_PATH" >&5 $as_echo "$SANE_CONFIG_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi if test x$cross_compiling = xyes; then CROSS_COMPILING_TRUE= CROSS_COMPILING_FALSE='#' else CROSS_COMPILING_TRUE='#' CROSS_COMPILING_FALSE= fi if test "${ac_cv_c_compiler_gnu}" = "yes"; then DEFAULT_CFLAGS="\ -Wall" EXTRA_WARNINGS="\ -Wextra \ -pedantic" for flag in $DEFAULT_CFLAGS; do case "$AM_CFLAGS" in "$flag" | "$flag "* | *" $flag" | *" $flag "* ) : ;; *) AM_CFLAGS="$AM_CFLAGS $flag" ;; esac done # Check whether --enable-warnings was given. if test "${enable_warnings+set}" = set; then : enableval=$enable_warnings; if eval "test x$enable_warnings = xyes"; then for flag in $EXTRA_WARNINGS; do case "$AM_CFLAGS" in "$flag" | "$flag "* | *" $flag" | *" $flag "* ) : ;; *) AM_CFLAGS="$AM_CFLAGS $flag" ;; esac done fi else if test x$is_release = xno; then # Warnings enabled by default (development) for flag in $EXTRA_WARNINGS; do case "$AM_CFLAGS" in "$flag" | "$flag "* | *" $flag" | *" $flag "* ) : ;; *) AM_CFLAGS="$AM_CFLAGS $flag" ;; esac done fi fi fi # ac_cv_c_compiler_gnu # Define stricter linking policy on GNU systems. This is not # added to global LDFLAGS because we may want to create convenience # libraries that don't require such strick linking. if test "$GCC" = yes; then case ${host_os} in linux* | solaris*) STRICT_LDFLAGS="-Wl,-z,defs" ;; esac fi case "${host_os}" in aix*) #enable .so libraries, disable archives AM_LDFLAGS="$AM_LDFLAGS -Wl,-brtl" ;; darwin*) #include frameworks LIBS="$LIBS -framework CoreFoundation -framework IOKit" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 $as_echo_n "checking for library containing strerror... " >&6; } if ${ac_cv_search_strerror+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char strerror (); int main () { return strerror (); ; return 0; } _ACEOF for ac_lib in '' cposix; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_strerror=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_strerror+:} false; then : break fi done if ${ac_cv_search_strerror+:} false; then : else ac_cv_search_strerror=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 $as_echo "$ac_cv_search_strerror" >&6; } ac_res=$ac_cv_search_strerror if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi ac_byteorder_h=`echo include/byteorder.h` ac_dir=`echo $ac_byteorder_h|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_byteorder" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" fi # We're only interested in the target CPU, but it's not always set effective_target="$target" if test "x$effective_target" = xNONE -o "x$effective_target" = x ; then effective_target="$host" fi ac_byteorder=_byteorder.tmp cat > "$ac_byteorder" << EOF /* This file is generated automatically by configure */ /* It is valid only for the system type ${effective_target} */ #ifndef __BYTEORDER_H #define __BYTEORDER_H EOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for le32toh in machine/endian.h" >&5 $as_echo_n "checking for le32toh in machine/endian.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef le32toh symbol is present #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "symbol is present|\" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } HAVE_LE32TOH=1 cat >> "$ac_byteorder" << EOF /* extended byte swapping macros are already available */ #include EOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ntohl in arpa/inet.h" >&5 $as_echo_n "checking for ntohl in arpa/inet.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef ntohl symbol is present #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "symbol is present|\" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >> "$ac_byteorder" << EOF /* ntohl and relatives live here */ #include EOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ntohl in netinet/in.h" >&5 $as_echo_n "checking for ntohl in netinet/in.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef ntohl symbol is present #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "symbol is present|\" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >> "$ac_byteorder" << EOF /* ntohl and relatives live here */ #include EOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } true fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: checking for swap32 in machine/endian.h" >&5 $as_echo_n "checking for swap32 in machine/endian.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef swap32 symbol is present #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "symbol is present|\" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >> "$ac_byteorder" << EOF /* swap32 and swap16 are defined in machine/endian.h */ EOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bswap_32 in byteswap.h" >&5 $as_echo_n "checking for bswap_32 in byteswap.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef bswap_32 symbol is present #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "symbol is present|\" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >> "$ac_byteorder" << EOF /* Define generic byte swapping functions */ #include #define swap16(x) bswap_16(x) #define swap32(x) bswap_32(x) #define swap64(x) bswap_64(x) EOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bswap32 in machine/endian.h" >&5 $as_echo_n "checking for bswap32 in machine/endian.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef bswap32 symbol is present #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "symbol is present|\" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >> "$ac_byteorder" << EOF /* Define generic byte swapping functions */ EOF if test "$HAVE_LE32TOH" != "1"; then echo '#include '>> "$ac_byteorder" fi cat >> "$ac_byteorder" << EOF #define swap16(x) bswap16(x) #define swap32(x) bswap32(x) #define swap64(x) bswap64(x) EOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __byte_swap_long in sys/types.h" >&5 $as_echo_n "checking for __byte_swap_long in sys/types.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef __byte_swap_long symbol is present #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "symbol is present|\<__byte_swap_long\>" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >> "$ac_byteorder" << EOF /* Define generic byte swapping functions */ #include #define swap16(x) __byte_swap_word(x) #define swap32(x) __byte_swap_long(x) /* No optimized 64 bit byte swapping macro is available */ #define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ ((x) >> 8) & 0x00000000ff000000ULL | \\ ((x) >> 24) & 0x0000000000ff0000ULL | \\ ((x) >> 40) & 0x000000000000ff00ULL | \\ ((x) >> 56) & 0x00000000000000ffULL)) EOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NXSwapLong in machine/byte_order.h" >&5 $as_echo_n "checking for NXSwapLong in machine/byte_order.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef NXSwapLong symbol is present #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "symbol is present|\" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >> "$ac_byteorder" << EOF /* Define generic byte swapping functions */ #include #define swap16(x) NXSwapShort(x) #define swap32(x) NXSwapLong(x) #define swap64(x) NXSwapLongLong(x) EOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test $ac_cv_c_bigendian = yes; then cat >> "$ac_byteorder" << EOF /* No other byte swapping functions are available on this big-endian system */ #define swap16(x) ((uint16_t)(((x) << 8) | ((uint16_t)(x) >> 8))) #define swap32(x) ((uint32_t)(((uint32_t)(x) << 24) & 0xff000000UL | \\ ((uint32_t)(x) << 8) & 0x00ff0000UL | \\ ((x) >> 8) & 0x0000ff00UL | \\ ((x) >> 24) & 0x000000ffUL)) #define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ ((x) >> 8) & 0x00000000ff000000ULL | \\ ((x) >> 24) & 0x0000000000ff0000ULL | \\ ((x) >> 40) & 0x000000000000ff00ULL | \\ ((x) >> 56) & 0x00000000000000ffULL)) EOF else cat >> "$ac_byteorder" << EOF /* Use these as generic byteswapping macros on this little endian system */ #define swap16(x) ntohs(x) #define swap32(x) ntohl(x) /* No optimized 64 bit byte swapping macro is available */ #define swap64(x) ((uint64_t)(((uint64_t)(x) << 56) & 0xff00000000000000ULL | \\ ((uint64_t)(x) << 40) & 0x00ff000000000000ULL | \\ ((uint64_t)(x) << 24) & 0x0000ff0000000000ULL | \\ ((uint64_t)(x) << 8) & 0x000000ff00000000ULL | \\ ((x) >> 8) & 0x00000000ff000000ULL | \\ ((x) >> 24) & 0x0000000000ff0000ULL | \\ ((x) >> 40) & 0x000000000000ff00ULL | \\ ((x) >> 56) & 0x00000000000000ffULL)) EOF fi fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* if test "$HAVE_LE32TOH" != "1"; then cat >> "$ac_byteorder" << EOF /* The byte swapping macros have the form: */ /* EENN[a]toh or htoEENN[a] where EE is be (big endian) or */ /* le (little-endian), NN is 16 or 32 (number of bits) and a, */ /* if present, indicates that the endian side is a pointer to an */ /* array of uint8_t bytes instead of an integer of the specified length. */ /* h refers to the host's ordering method. */ /* So, to convert a 32-bit integer stored in a buffer in little-endian */ /* format into a uint32_t usable on this machine, you could use: */ /* uint32_t value = le32atoh(&buf[3]); */ /* To put that value back into the buffer, you could use: */ /* htole32a(&buf[3], value); */ /* Define aliases for the standard byte swapping macros */ /* Arguments to these macros must be properly aligned on natural word */ /* boundaries in order to work properly on all architectures */ #ifndef htobe16 #define htobe16(x) htons(x) #endif #ifndef htobe32 #define htobe32(x) htonl(x) #endif #ifndef be16toh #define be16toh(x) ntohs(x) #endif #ifndef be32toh #define be32toh(x) ntohl(x) #endif #define HTOBE16(x) (x) = htobe16(x) #define HTOBE32(x) (x) = htobe32(x) #define BE32TOH(x) (x) = be32toh(x) #define BE16TOH(x) (x) = be16toh(x) EOF if test $ac_cv_c_bigendian = yes; then cat >> "$ac_byteorder" << EOF /* Define our own extended byte swapping macros for big-endian machines */ #ifndef htole16 #define htole16(x) swap16(x) #endif #ifndef htole32 #define htole32(x) swap32(x) #endif #ifndef le16toh #define le16toh(x) swap16(x) #endif #ifndef le32toh #define le32toh(x) swap32(x) #endif #ifndef htobe64 #define htobe64(x) (x) #endif #ifndef be64toh #define be64toh(x) (x) #endif #define HTOLE16(x) (x) = htole16(x) #define HTOLE32(x) (x) = htole32(x) #define LE16TOH(x) (x) = le16toh(x) #define LE32TOH(x) (x) = le32toh(x) #define HTOBE64(x) (void) (x) #define BE64TOH(x) (void) (x) EOF else cat >> "$ac_byteorder" << EOF /* On little endian machines, these macros are null */ #ifndef htole16 #define htole16(x) (x) #endif #ifndef htole32 #define htole32(x) (x) #endif #ifndef htole64 #define htole64(x) (x) #endif #ifndef le16toh #define le16toh(x) (x) #endif #ifndef le32toh #define le32toh(x) (x) #endif #ifndef le64toh #define le64toh(x) (x) #endif #define HTOLE16(x) (void) (x) #define HTOLE32(x) (void) (x) #define HTOLE64(x) (void) (x) #define LE16TOH(x) (void) (x) #define LE32TOH(x) (void) (x) #define LE64TOH(x) (void) (x) /* These don't have standard aliases */ #ifndef htobe64 #define htobe64(x) swap64(x) #endif #ifndef be64toh #define be64toh(x) swap64(x) #endif #define HTOBE64(x) (x) = htobe64(x) #define BE64TOH(x) (x) = be64toh(x) EOF fi fi cat >> "$ac_byteorder" << EOF /* Define the C99 standard length-specific integer types */ #include <_stdint.h> EOF case "${effective_target}" in i[3456]86-*) cat >> "$ac_byteorder" << EOF /* Here are some macros to create integers from a byte array */ /* These are used to get and put integers from/into a uint8_t array */ /* with a specific endianness. This is the most portable way to generate */ /* and read messages to a network or serial device. Each member of a */ /* packet structure must be handled separately. */ /* The i386 and compatibles can handle unaligned memory access, */ /* so use the optimized macros above to do this job */ #define be16atoh(x) be16toh(*(uint16_t*)(x)) #define be32atoh(x) be32toh(*(uint32_t*)(x)) #define be64atoh(x) be64toh(*(uint64_t*)(x)) #define le16atoh(x) le16toh(*(uint16_t*)(x)) #define le32atoh(x) le32toh(*(uint32_t*)(x)) #define le64atoh(x) le64toh(*(uint64_t*)(x)) #define htobe16a(a,x) *(uint16_t*)(a) = htobe16(x) #define htobe32a(a,x) *(uint32_t*)(a) = htobe32(x) #define htobe64a(a,x) *(uint64_t*)(a) = htobe64(x) #define htole16a(a,x) *(uint16_t*)(a) = htole16(x) #define htole32a(a,x) *(uint32_t*)(a) = htole32(x) #define htole64a(a,x) *(uint64_t*)(a) = htole64(x) EOF ;; *) cat >> "$ac_byteorder" << EOF /* Here are some macros to create integers from a byte array */ /* These are used to get and put integers from/into a uint8_t array */ /* with a specific endianness. This is the most portable way to generate */ /* and read messages to a network or serial device. Each member of a */ /* packet structure must be handled separately. */ /* Non-optimized but portable macros */ #define be16atoh(x) ((uint16_t)(((x)[0]<<8)|(x)[1])) #define be32atoh(x) ((uint32_t)(((x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])) #define be64atoh(x) ((uint64_t)(((x)[0]<<56)|((x)[1]<<48)|((x)[2]<<40)| \\ ((x)[3]<<32)|((x)[4]<<24)|((x)[5]<<16)|((x)[6]<<8)|(x)[7])) #define le16atoh(x) ((uint16_t)(((x)[1]<<8)|(x)[0])) #define le32atoh(x) ((uint32_t)(((x)[3]<<24)|((x)[2]<<16)|((x)[1]<<8)|(x)[0])) #define le64atoh(x) ((uint64_t)(((x)[7]<<56)|((x)[6]<<48)|((x)[5]<<40)| \\ ((x)[4]<<32)|((x)[3]<<24)|((x)[2]<<16)|((x)[1]<<8)|(x)[0])) #define htobe16a(a,x) (a)[0]=(uint8_t)((x)>>8), (a)[1]=(uint8_t)(x) #define htobe32a(a,x) (a)[0]=(uint8_t)((x)>>24), (a)[1]=(uint8_t)((x)>>16), \\ (a)[2]=(uint8_t)((x)>>8), (a)[3]=(uint8_t)(x) #define htobe64a(a,x) (a)[0]=(uint8_t)((x)>>56), (a)[1]=(uint8_t)((x)>>48), \\ (a)[2]=(uint8_t)((x)>>40), (a)[3]=(uint8_t)((x)>>32), \\ (a)[4]=(uint8_t)((x)>>24), (a)[5]=(uint8_t)((x)>>16), \\ (a)[6]=(uint8_t)((x)>>8), (a)[7]=(uint8_t)(x) #define htole16a(a,x) (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) #define htole32a(a,x) (a)[3]=(uint8_t)((x)>>24), (a)[2]=(uint8_t)((x)>>16), \\ (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) #define htole64a(a,x) (a)[7]=(uint8_t)((x)>>56), (a)[6]=(uint8_t)((x)>>48), \\ (a)[5]=(uint8_t)((x)>>40), (a)[4]=(uint8_t)((x)>>32), \\ (a)[3]=(uint8_t)((x)>>24), (a)[2]=(uint8_t)((x)>>16), \\ (a)[1]=(uint8_t)((x)>>8), (a)[0]=(uint8_t)(x) EOF ;; esac cat >> "$ac_byteorder" << EOF #endif /*__BYTEORDER_H*/ EOF if cmp -s $ac_byteorder_h $ac_byteorder 2>/dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_byteorder_h is unchanged" >&5 $as_echo "$as_me: $ac_byteorder_h is unchanged" >&6;} rm $ac_byteorder else rm -f $ac_byteorder_h mv $ac_byteorder $ac_byteorder_h fi # ------ AX CREATE STDINT H ------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint types" >&5 $as_echo_n "checking for stdint types... " >&6; } ac_stdint_h=`echo include/_stdint.h` # try to shortcircuit - if the default include path of the compiler # can find a "stdint.h" header then we assume that all compilers can. if ${ac_cv_header_stdint_t+:} false; then : $as_echo_n "(cached) " >&6 else old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" old_CFLAGS="$CFLAGS" ; CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int_least32_t v = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_stdint_result="(assuming C99 compatible system)" ac_cv_header_stdint_t="stdint.h"; else ac_cv_header_stdint_t="" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then CFLAGS="-std=c99" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int_least32_t v = 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: your GCC compiler has a defunct stdint.h for its default-mode" >&5 $as_echo "$as_me: WARNING: your GCC compiler has a defunct stdint.h for its default-mode" >&2;} fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi CXXFLAGS="$old_CXXFLAGS" CPPFLAGS="$old_CPPFLAGS" CFLAGS="$old_CFLAGS" fi v="... $ac_cv_header_stdint_h" if test "$ac_stdint_h" = "stdint.h" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: (are you sure you want them in ./stdint.h?)" >&5 $as_echo "(are you sure you want them in ./stdint.h?)" >&6; } elif test "$ac_stdint_h" = "inttypes.h" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: (are you sure you want them in ./inttypes.h?)" >&5 $as_echo "(are you sure you want them in ./inttypes.h?)" >&6; } elif test "_$ac_cv_header_stdint_t" = "_" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: (putting them into $ac_stdint_h)$v" >&5 $as_echo "(putting them into $ac_stdint_h)$v" >&6; } else ac_cv_header_stdint="$ac_cv_header_stdint_t" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdint (shortcircuit)" >&5 $as_echo "$ac_cv_header_stdint (shortcircuit)" >&6; } fi if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. inttype_headers=`echo | sed -e 's/,/ /g'` ac_cv_stdint_result="(no helpful system typedefs seen)" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint uintptr_t" >&5 $as_echo_n "checking for stdint uintptr_t... " >&6; } if ${ac_cv_header_stdint_x+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) { $as_echo "$as_me:${as_lineno-$LINENO}: result: (..)" >&5 $as_echo "(..)" >&6; } for i in stdint.h inttypes.h sys/inttypes.h $inttype_headers do unset ac_cv_type_uintptr_t unset ac_cv_type_uint64_t ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include <$i> " if test "x$ac_cv_type_uintptr_t" = xyes; then : ac_cv_header_stdint_x=$i else continue fi ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include<$i> " if test "x$ac_cv_type_uint64_t" = xyes; then : and64="/uint64_t" else and64="" fi stdint.h inttypes.h sys/inttypes.h $inttype_headers break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint uintptr_t" >&5 $as_echo_n "checking for stdint uintptr_t... " >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdint_x" >&5 $as_echo "$ac_cv_header_stdint_x" >&6; } if test "_$ac_cv_header_stdint_x" = "_" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint uint32_t" >&5 $as_echo_n "checking for stdint uint32_t... " >&6; } if ${ac_cv_header_stdint_o+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) { $as_echo "$as_me:${as_lineno-$LINENO}: result: (..)" >&5 $as_echo "(..)" >&6; } for i in inttypes.h sys/inttypes.h stdint.h $inttype_headers do unset ac_cv_type_uint32_t unset ac_cv_type_uint64_t ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "#include <$i> " if test "x$ac_cv_type_uint32_t" = xyes; then : ac_cv_header_stdint_o=$i else continue fi ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include<$i> " if test "x$ac_cv_type_uint64_t" = xyes; then : and64="/uint64_t" else and64="" fi inttypes.h sys/inttypes.h stdint.h $inttype_headers break break; done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint uint32_t" >&5 $as_echo_n "checking for stdint uint32_t... " >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdint_o" >&5 $as_echo "$ac_cv_header_stdint_o" >&6; } fi if test "_$ac_cv_header_stdint_x" = "_" ; then if test "_$ac_cv_header_stdint_o" = "_" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint u_int32_t" >&5 $as_echo_n "checking for stdint u_int32_t... " >&6; } if ${ac_cv_header_stdint_u+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) { $as_echo "$as_me:${as_lineno-$LINENO}: result: (..)" >&5 $as_echo "(..)" >&6; } for i in sys/types.h inttypes.h sys/inttypes.h $inttype_headers ; do unset ac_cv_type_u_int32_t unset ac_cv_type_u_int64_t ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "#include <$i> " if test "x$ac_cv_type_u_int32_t" = xyes; then : ac_cv_header_stdint_u=$i else continue fi ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "#include<$i> " if test "x$ac_cv_type_u_int64_t" = xyes; then : and64="/u_int64_t" else and64="" fi sys/types.h inttypes.h sys/inttypes.h $inttype_headers break break; done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint u_int32_t" >&5 $as_echo_n "checking for stdint u_int32_t... " >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdint_u" >&5 $as_echo "$ac_cv_header_stdint_u" >&6; } fi fi if test "_$ac_cv_header_stdint_x" = "_" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint datatype model" >&5 $as_echo_n "checking for stdint datatype model... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: (..)" >&5 $as_echo "(..)" >&6; } # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5 $as_echo_n "checking size of char... " >&6; } if ${ac_cv_sizeof_char+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"; then : else if test "$ac_cv_type_char" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (char) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_char=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5 $as_echo "$ac_cv_sizeof_char" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_CHAR $ac_cv_sizeof_char _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 $as_echo_n "checking size of short... " >&6; } if ${ac_cv_sizeof_short+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : else if test "$ac_cv_type_short" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (short) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_short=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 $as_echo "$ac_cv_sizeof_short" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_SHORT $ac_cv_sizeof_short _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 $as_echo_n "checking size of int... " >&6; } if ${ac_cv_sizeof_int+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : else if test "$ac_cv_type_int" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_int=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 $as_echo "$ac_cv_sizeof_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 $as_echo_n "checking size of long... " >&6; } if ${ac_cv_sizeof_long+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : else if test "$ac_cv_type_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 $as_echo "$ac_cv_sizeof_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void*" >&5 $as_echo_n "checking size of void*... " >&6; } if ${ac_cv_sizeof_voidp+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void*))" "ac_cv_sizeof_voidp" "$ac_includes_default"; then : else if test "$ac_cv_type_voidp" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (void*) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_voidp=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_voidp" >&5 $as_echo "$ac_cv_sizeof_voidp" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_VOIDP $ac_cv_sizeof_voidp _ACEOF ac_cv_char_data_model="" ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char" ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short" ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int" ac_cv_long_data_model="" ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int" ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long" ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp" { $as_echo "$as_me:${as_lineno-$LINENO}: checking data model" >&5 $as_echo_n "checking data model... " >&6; } case "$ac_cv_char_data_model/$ac_cv_long_data_model" in 122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;; 122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;; 122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;; 124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;; 124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;; 124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;; 124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;; 128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;; 128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;; 222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;; 333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;; 444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;; 666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;; 888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;; 222/*|333/*|444/*|666/*|888/*) : ac_cv_data_model="iDSP" ; n="unusual dsptype" ;; *) ac_cv_data_model="none" ; n="very unusual model" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_data_model ($ac_cv_long_data_model, $n)" >&5 $as_echo "$ac_cv_data_model ($ac_cv_long_data_model, $n)" >&6; } fi if test "_$ac_cv_header_stdint_x" != "_" ; then ac_cv_header_stdint="$ac_cv_header_stdint_x" elif test "_$ac_cv_header_stdint_o" != "_" ; then ac_cv_header_stdint="$ac_cv_header_stdint_o" elif test "_$ac_cv_header_stdint_u" != "_" ; then ac_cv_header_stdint="$ac_cv_header_stdint_u" else ac_cv_header_stdint="stddef.h" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extra inttypes in chosen header" >&5 $as_echo_n "checking for extra inttypes in chosen header... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: ($ac_cv_header_stdint)" >&5 $as_echo "($ac_cv_header_stdint)" >&6; } unset ac_cv_type_int_least32_t unset ac_cv_type_int_fast32_t ac_fn_c_check_type "$LINENO" "int_least32_t" "ac_cv_type_int_least32_t" "#include <$ac_cv_header_stdint> " if test "x$ac_cv_type_int_least32_t" = xyes; then : fi ac_fn_c_check_type "$LINENO" "int_fast32_t" "ac_cv_type_int_fast32_t" "#include<$ac_cv_header_stdint> " if test "x$ac_cv_type_int_fast32_t" = xyes; then : fi ac_fn_c_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" "#include <$ac_cv_header_stdint> " if test "x$ac_cv_type_intmax_t" = xyes; then : fi fi # shortcircut to system "stdint.h" # ------------------ PREPARE VARIABLES ------------------------------ if test "$GCC" = "yes" ; then ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1` else ac_cv_stdint_message="using $CC" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: make use of $ac_cv_header_stdint in $ac_stdint_h $ac_cv_stdint_result" >&5 $as_echo "make use of $ac_cv_header_stdint in $ac_stdint_h $ac_cv_stdint_result" >&6; } # ----------------- DONE inttypes.h checks START header ------------- ac_config_commands="$ac_config_commands $ac_stdint_h" # Check whether --enable-dynamic was given. if test "${enable_dynamic+set}" = set; then : enableval=$enable_dynamic; enable_dynamic=$enableval else enable_dynamic=auto fi DL_LIBS="" if test "${enable_dynamic}" = "auto"; then # default to disabled unless library found. enable_dynamic=no # dlopen for ac_header in dlfcn.h do : ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : DL_LIBS=-ldl fi saved_LIBS="${LIBS}" LIBS="${LIBS} ${DL_LIBS}" for ac_func in dlopen do : ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLOPEN 1 _ACEOF enable_dynamic=yes fi done LIBS="${saved_LIBS}" fi done # HP/UX DLL handling for ac_header in dl.h do : ac_fn_c_check_header_mongrel "$LINENO" "dl.h" "ac_cv_header_dl_h" "$ac_includes_default" if test "x$ac_cv_header_dl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DL_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : DL_LIBS=-ldld fi saved_LIBS="${LIBS}" LIBS="${LIBS} ${DL_LIBS}" for ac_func in shl_load do : ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SHL_LOAD 1 _ACEOF enable_dynamic=yes fi done LIBS="${saved_LIBS}" fi done if test -z "$DL_LIBS" ; then # old Mac OS X/Darwin (without dlopen) for ac_header in mach-o/dyld.h do : ac_fn_c_check_header_mongrel "$LINENO" "mach-o/dyld.h" "ac_cv_header_mach_o_dyld_h" "$ac_includes_default" if test "x$ac_cv_header_mach_o_dyld_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MACH_O_DYLD_H 1 _ACEOF for ac_func in NSLinkModule do : ac_fn_c_check_func "$LINENO" "NSLinkModule" "ac_cv_func_NSLinkModule" if test "x$ac_cv_func_NSLinkModule" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NSLINKMODULE 1 _ACEOF enable_dynamic=yes fi done fi done fi fi DYNAMIC_FLAG= if test "${enable_dynamic}" = yes ; then DYNAMIC_FLAG=-module fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqrt in -lm" >&5 $as_echo_n "checking for sqrt in -lm... " >&6; } if ${ac_cv_lib_m_sqrt+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqrt (); int main () { return sqrt (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_sqrt=yes else ac_cv_lib_m_sqrt=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sqrt" >&5 $as_echo "$ac_cv_lib_m_sqrt" >&6; } if test "x$ac_cv_lib_m_sqrt" = xyes; then : MATH_LIB="-lm" fi case ${host_os} in os2*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sylog in -lsyslog" >&5 $as_echo_n "checking for sylog in -lsyslog... " >&6; } if ${ac_cv_lib_syslog_sylog+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsyslog $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sylog (); int main () { return sylog (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_syslog_sylog=yes else ac_cv_lib_syslog_sylog=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_syslog_sylog" >&5 $as_echo "$ac_cv_lib_syslog_sylog" >&6; } if test "x$ac_cv_lib_syslog_sylog" = xyes; then : SYSLOG_LIBS="-lsyslog" fi ;; beos*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for syslog in -lbe" >&5 $as_echo_n "checking for syslog in -lbe... " >&6; } if ${ac_cv_lib_be_syslog+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbe $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char syslog (); int main () { return syslog (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_be_syslog=yes else ac_cv_lib_be_syslog=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_be_syslog" >&5 $as_echo "$ac_cv_lib_be_syslog" >&6; } if test "x$ac_cv_lib_be_syslog" = xyes; then : SYSLOG_LIBS="-lbe" fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeg_start_decompress in -ljpeg" >&5 $as_echo_n "checking for jpeg_start_decompress in -ljpeg... " >&6; } if ${ac_cv_lib_jpeg_jpeg_start_decompress+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljpeg $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char jpeg_start_decompress (); int main () { return jpeg_start_decompress (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_jpeg_jpeg_start_decompress=yes else ac_cv_lib_jpeg_jpeg_start_decompress=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_start_decompress" >&5 $as_echo "$ac_cv_lib_jpeg_jpeg_start_decompress" >&6; } if test "x$ac_cv_lib_jpeg_jpeg_start_decompress" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "jconfig.h" "ac_cv_header_jconfig_h" "$ac_includes_default" if test "x$ac_cv_header_jconfig_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeglib - version >= 61 (6a)" >&5 $as_echo_n "checking for jpeglib - version >= 61 (6a)... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if JPEG_LIB_VERSION >= 61 sane_correct_jpeg_lib_version_found #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "sane_correct_jpeg_lib_version_found" >/dev/null 2>&1; then : sane_cv_use_libjpeg="yes"; JPEG_LIBS="-ljpeg"; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f conftest* fi fi if test "$sane_cv_use_libjpeg" = "yes" ; then $as_echo "#define HAVE_LIBJPEG 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TIFFFdOpen in -ltiff" >&5 $as_echo_n "checking for TIFFFdOpen in -ltiff... " >&6; } if ${ac_cv_lib_tiff_TIFFFdOpen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ltiff $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char TIFFFdOpen (); int main () { return TIFFFdOpen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_tiff_TIFFFdOpen=yes else ac_cv_lib_tiff_TIFFFdOpen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tiff_TIFFFdOpen" >&5 $as_echo "$ac_cv_lib_tiff_TIFFFdOpen" >&6; } if test "x$ac_cv_lib_tiff_TIFFFdOpen" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "tiffio.h" "ac_cv_header_tiffio_h" "$ac_includes_default" if test "x$ac_cv_header_tiffio_h" = xyes; then : sane_cv_use_libtiff="yes"; TIFF_LIBS="-ltiff" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for png_init_io in -lpng" >&5 $as_echo_n "checking for png_init_io in -lpng... " >&6; } if ${ac_cv_lib_png_png_init_io+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpng $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char png_init_io (); int main () { return png_init_io (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_png_png_init_io=yes else ac_cv_lib_png_png_init_io=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_init_io" >&5 $as_echo "$ac_cv_lib_png_png_init_io" >&6; } if test "x$ac_cv_lib_png_png_init_io" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "png.h" "ac_cv_header_png_h" "$ac_includes_default" if test "x$ac_cv_header_png_h" = xyes; then : sane_cv_use_libpng="yes"; PNG_LIBS="-lpng" fi fi if test "$sane_cv_use_libpng" = "yes" ; then $as_echo "#define HAVE_LIBPNG 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "ieee1284.h" "ac_cv_header_ieee1284_h" "$ac_includes_default" if test "x$ac_cv_header_ieee1284_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libieee1284 >= 0.1.5" >&5 $as_echo_n "checking for libieee1284 >= 0.1.5... " >&6; } if ${sane_cv_use_libieee1284+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct parport p; char *buf; ieee1284_nibble_read(&p, 0, buf, 1); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : sane_cv_use_libieee1284="yes"; IEEE1284_LIBS="-lieee1284" else sane_cv_use_libieee1284="no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sane_cv_use_libieee1284" >&5 $as_echo "$sane_cv_use_libieee1284" >&6; } fi if test "$sane_cv_use_libieee1284" = "yes" ; then $as_echo "#define HAVE_LIBIEEE1284 1" >>confdefs.h fi case "${host_os}" in linux* | darwin* | mingw*) # enabled by default on Linux, MacOS X and MINGW use_pthread=yes ;; *) use_pthread=no esac have_pthread=no # # now that we have the systems preferences, we check # the user # Check whether --enable-pthread was given. if test "${enable_pthread+set}" = set; then : enableval=$enable_pthread; if test $enableval = yes ; then use_pthread=yes else use_pthread=no fi fi if test $use_pthread = yes ; then for ac_header in pthread.h do : ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTHREAD_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5 $as_echo_n "checking for pthread_create in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_create=yes else ac_cv_lib_pthread_pthread_create=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5 $as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then : PTHREAD_LIBS="-lpthread" fi have_pthread=yes save_LIBS="$LIBS" LIBS="$LIBS $PTHREAD_LIBS" for ac_func in pthread_create pthread_kill pthread_join pthread_detach pthread_cancel pthread_testcancel do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else have_pthread=no; use_pthread=no fi done LIBS="$save_LIBS" else have_pthread=no; use_pthread=no fi done fi if test $use_pthread = yes ; then cat >>confdefs.h <<_ACEOF #define USE_PTHREAD "$use_pthread" _ACEOF else PTHREAD_LIBS="" fi if test "$have_pthread" = "yes" ; then AM_CPPFLAGS="${AM_CPPFLAGS} -D_REENTRANT" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable pthread support" >&5 $as_echo_n "checking whether to enable pthread support... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_pthread" >&5 $as_echo "$have_pthread" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use pthread instead of fork" >&5 $as_echo_n "checking whether to use pthread instead of fork... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_pthread" >&5 $as_echo "$use_pthread" >&6; } LOCKPATH_GROUP=uucp use_locking=yes case "${host_os}" in os2* ) use_locking=no ;; esac # # we check the user # Check whether --enable-locking was given. if test "${enable_locking+set}" = set; then : enableval=$enable_locking; if test $enableval = yes ; then use_locking=yes else use_locking=no fi fi if test $use_locking = yes ; then # Check whether --with-group was given. if test "${with_group+set}" = set; then : withval=$with_group; LOCKPATH_GROUP="$withval" fi # check if the group does exist lasterror="" touch sanetest.file chgrp $LOCKPATH_GROUP sanetest.file 2>/dev/null || lasterror=$? rm -f sanetest.file if test ! -z "$lasterror"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Group $LOCKPATH_GROUP does not exist on this system." >&5 $as_echo "$as_me: WARNING: Group $LOCKPATH_GROUP does not exist on this system." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Locking feature will be disabled." >&5 $as_echo "$as_me: WARNING: Locking feature will be disabled." >&2;} use_locking=no fi fi if test $use_locking = yes ; then INSTALL_LOCKPATH=install-lockpath $as_echo "#define ENABLE_LOCKING 1" >>confdefs.h else INSTALL_LOCKPATH= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable device locking" >&5 $as_echo_n "checking whether to enable device locking... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_locking" >&5 $as_echo "$use_locking" >&6; } if test $use_locking = yes ; then { $as_echo "$as_me:${as_lineno-$LINENO}: Setting lockdir group to $LOCKPATH_GROUP" >&5 $as_echo "$as_me: Setting lockdir group to $LOCKPATH_GROUP" >&6;} fi # Check whether --with-gphoto2 was given. if test "${with_gphoto2+set}" = set; then : withval=$with_gphoto2; # If --with-gphoto2=no or --without-gphoto2, disable backend # as "$with_gphoto2" will be set to "no" fi # If --with-gphoto2=yes (or not supplied), first check if # pkg-config exists, then use it to check if libgphoto2 is # present. If all that works, then see if we can actually link # a program. And, if that works, then add the -l flags to # GPHOTO2_LIBS and any other flags to GPHOTO2_LDFLAGS to pass to # sane-config. if test "$with_gphoto2" != "no" ; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_HAVE_GPHOTO2+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$HAVE_GPHOTO2"; then ac_cv_prog_HAVE_GPHOTO2="$HAVE_GPHOTO2" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_HAVE_GPHOTO2="${ac_tool_prefix}pkg-config" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi HAVE_GPHOTO2=$ac_cv_prog_HAVE_GPHOTO2 if test -n "$HAVE_GPHOTO2"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_GPHOTO2" >&5 $as_echo "$HAVE_GPHOTO2" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_HAVE_GPHOTO2"; then ac_ct_HAVE_GPHOTO2=$HAVE_GPHOTO2 # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_HAVE_GPHOTO2+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_HAVE_GPHOTO2"; then ac_cv_prog_ac_ct_HAVE_GPHOTO2="$ac_ct_HAVE_GPHOTO2" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_HAVE_GPHOTO2="pkg-config" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_HAVE_GPHOTO2=$ac_cv_prog_ac_ct_HAVE_GPHOTO2 if test -n "$ac_ct_HAVE_GPHOTO2"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_HAVE_GPHOTO2" >&5 $as_echo "$ac_ct_HAVE_GPHOTO2" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_HAVE_GPHOTO2" = x; then HAVE_GPHOTO2="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac HAVE_GPHOTO2=$ac_ct_HAVE_GPHOTO2 fi else HAVE_GPHOTO2="$ac_cv_prog_HAVE_GPHOTO2" fi if test ${HAVE_GPHOTO2} != "false" ; then if pkg-config --exists libgphoto2 ; then with_gphoto2="`pkg-config --modversion libgphoto2`" GPHOTO2_CPPFLAGS="`pkg-config --cflags libgphoto2`" GPHOTO2_LIBS="`pkg-config --libs libgphoto2`" saved_CPPFLAGS="${CPPFLAGS}" CPPFLAGS="${GPHOTO2_CPPFLAGS}" saved_LIBS="${LIBS}" LIBS="${LIBS} ${GPHOTO2_LIBS}" # Make sure we an really use the library for ac_func in gp_camera_init do : ac_fn_c_check_func "$LINENO" "gp_camera_init" "ac_cv_func_gp_camera_init" if test "x$ac_cv_func_gp_camera_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GP_CAMERA_INIT 1 _ACEOF HAVE_GPHOTO2=true else HAVE_GPHOTO2=false fi done if test "${HAVE_GPHOTO2}" = "true"; then for ac_func in gp_port_info_get_path do : ac_fn_c_check_func "$LINENO" "gp_port_info_get_path" "ac_cv_func_gp_port_info_get_path" if test "x$ac_cv_func_gp_port_info_get_path" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GP_PORT_INFO_GET_PATH 1 _ACEOF fi done fi CPPFLAGS="${saved_CPPFLAGS}" LIBS="${saved_LIBS}" else HAVE_GPHOTO2=false fi if test "${HAVE_GPHOTO2}" = "false"; then GPHOTO2_CPPFLAGS="" GPHOTO2_LIBS="" else tmp_LIBS="" for param in ${GPHOTO2_LIBS}; do case "${param}" in -l*) tmp_LIBS="${tmp_LIBS} ${param}" ;; *) GPHOTO2_LDFLAGS="${GPHOTO2_LDFLAGS} ${param}" ;; esac done GPHOTO2_LIBS="${tmp_LIBS}" unset tmp_LIBS unset param if pkg-config --atleast-version=2.5.0 libgphoto2; then $as_echo "#define GPLOGFUNC_NO_VARGS 1" >>confdefs.h fi fi fi fi # Check whether --with-v4l was given. if test "${with_v4l+set}" = set; then : withval=$with_v4l; # If --with-v4l=no or --without-v4l, disable backend # as "$with_v4l" will be set to "no" fi if test "$with_v4l" != "no" ; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBV4L" >&5 $as_echo_n "checking for LIBV4L... " >&6; } if test -n "$LIBV4L_CFLAGS"; then pkg_cv_LIBV4L_CFLAGS="$LIBV4L_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libv4l1\""; } >&5 ($PKG_CONFIG --exists --print-errors "libv4l1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBV4L_CFLAGS=`$PKG_CONFIG --cflags "libv4l1" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBV4L_LIBS"; then pkg_cv_LIBV4L_LIBS="$LIBV4L_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libv4l1\""; } >&5 ($PKG_CONFIG --exists --print-errors "libv4l1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBV4L_LIBS=`$PKG_CONFIG --libs "libv4l1" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBV4L_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libv4l1" 2>&1` else LIBV4L_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libv4l1" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBV4L_PKG_ERRORS" >&5 have_libv4l1=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_libv4l1=no else LIBV4L_CFLAGS=$pkg_cv_LIBV4L_CFLAGS LIBV4L_LIBS=$pkg_cv_LIBV4L_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_libv4l1=yes fi fi # Check whether --enable-avahi was given. if test "${enable_avahi+set}" = set; then : enableval=$enable_avahi; enable_avahi=$enableval else enable_avahi=no fi if test "$enable_avahi" = "yes"; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVAHI" >&5 $as_echo_n "checking for AVAHI... " >&6; } if test -n "$AVAHI_CFLAGS"; then pkg_cv_AVAHI_CFLAGS="$AVAHI_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" avahi-client >= 0.6.24 \""; } >&5 ($PKG_CONFIG --exists --print-errors " avahi-client >= 0.6.24 ") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVAHI_CFLAGS=`$PKG_CONFIG --cflags " avahi-client >= 0.6.24 " 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$AVAHI_LIBS"; then pkg_cv_AVAHI_LIBS="$AVAHI_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \" avahi-client >= 0.6.24 \""; } >&5 ($PKG_CONFIG --exists --print-errors " avahi-client >= 0.6.24 ") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_AVAHI_LIBS=`$PKG_CONFIG --libs " avahi-client >= 0.6.24 " 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then AVAHI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs " avahi-client >= 0.6.24 " 2>&1` else AVAHI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs " avahi-client >= 0.6.24 " 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$AVAHI_PKG_ERRORS" >&5 enable_avahi=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } enable_avahi=no else AVAHI_CFLAGS=$pkg_cv_AVAHI_CFLAGS AVAHI_LIBS=$pkg_cv_AVAHI_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define WITH_AVAHI 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sane_init in -lsane" >&5 $as_echo_n "checking for sane_init in -lsane... " >&6; } if ${ac_cv_lib_sane_sane_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsane $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sane_init (); int main () { return sane_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sane_sane_init=yes else ac_cv_lib_sane_sane_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sane_sane_init" >&5 $as_echo "$ac_cv_lib_sane_sane_init" >&6; } if test "x$ac_cv_lib_sane_sane_init" = xyes; then : LIBSANE_EXISTS="yes" fi # Check whether --with-snmp was given. if test "${with_snmp+set}" = set; then : withval=$with_snmp; fi if test "$with_snmp" = "no"; then echo "Not including SNMP support" else # Extract the first word of "net-snmp-config", so it can be a program name with args. set dummy net-snmp-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SNMP_CONFIG_PATH+:} false; then : $as_echo_n "(cached) " >&6 else case $SNMP_CONFIG_PATH in [\\/]* | ?:[\\/]*) ac_cv_path_SNMP_CONFIG_PATH="$SNMP_CONFIG_PATH" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SNMP_CONFIG_PATH="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_SNMP_CONFIG_PATH" && ac_cv_path_SNMP_CONFIG_PATH=""no"" ;; esac fi SNMP_CONFIG_PATH=$ac_cv_path_SNMP_CONFIG_PATH if test -n "$SNMP_CONFIG_PATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SNMP_CONFIG_PATH" >&5 $as_echo "$SNMP_CONFIG_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for snmp_timeout in -lnetsnmp" >&5 $as_echo_n "checking for snmp_timeout in -lnetsnmp... " >&6; } if ${ac_cv_lib_netsnmp_snmp_timeout+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnetsnmp $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char snmp_timeout (); int main () { return snmp_timeout (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_netsnmp_snmp_timeout=yes else ac_cv_lib_netsnmp_snmp_timeout=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netsnmp_snmp_timeout" >&5 $as_echo "$ac_cv_lib_netsnmp_snmp_timeout" >&6; } if test "x$ac_cv_lib_netsnmp_snmp_timeout" = xyes; then : LIBSNMP_EXISTS="yes" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for proper SNMP version" >&5 $as_echo_n "checking for proper SNMP version... " >&6; } if test "$SNMP_CONFIG_PATH" != "no" ; then snmp_version=`$SNMP_CONFIG_PATH --version 2>/dev/null` vers=`echo $snmp_version | awk 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2);}'` if test -n "$vers" && test "$vers" -ge 5006; then SNMP_LIBS=`$SNMP_CONFIG_PATH --libs` SNMP_CFLAGS=`$SNMP_CONFIG_PATH --cflags` { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } with_snmp="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You need at least net-snmp 5.6, your version is $snmp_version" >&5 $as_echo "$as_me: WARNING: You need at least net-snmp 5.6, your version is $snmp_version" >&2;} with_snmp="no" fi else with_snmp="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test "$with_snmp" = "yes" && test "${LIBSNMP_EXISTS}x" = "yesx"; then $as_echo "#define HAVE_LIBSNMP 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: net-snmp library disabled, autodetecting network scanners will not be supported." >&5 $as_echo "$as_me: WARNING: net-snmp library disabled, autodetecting network scanners will not be supported." >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in fcntl.h unistd.h libc.h sys/dsreq.h sys/select.h \ sys/time.h sys/shm.h sys/ipc.h sys/signal.h sys/scanio.h os2.h \ sys/socket.h sys/io.h sys/hw.h sys/types.h linux/ppdev.h \ dev/ppbus/ppi.h machine/cpufunc.h sys/sem.h sys/poll.h \ windows.h be/kernel/OS.h limits.h sys/ioctl.h asm/types.h\ netinet/in.h tiffio.h ifaddrs.h pwd.h getopt.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in asm/io.h do : ac_fn_c_check_header_compile "$LINENO" "asm/io.h" "ac_cv_header_asm_io_h" "#include " if test "x$ac_cv_header_asm_io_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ASM_IO_H 1 _ACEOF fi done MISSING_HEADERS= if test "${ac_cv_header_fcntl_h}" != "yes" ; then MISSING_HEADERS="${MISSING_HEADERS}\"fcntl.h\" " fi if test "${ac_cv_header_sys_time_h}" != "yes" ; then MISSING_HEADERS="${MISSING_HEADERS}\"sys/time.h\" " fi if test "${ac_cv_header_unistd_h}" != "yes" ; then MISSING_HEADERS="${MISSING_HEADERS}\"unistd.h\" " fi if test "${ac_cv_header_stdc}" != "yes" ; then MISSING_HEADERS="${MISSING_HEADERS}\"ANSI C headers\" " fi if test "${MISSING_HEADERS}" != "" ; then echo "*** The following essential header files couldn't be found:" echo "*** ${MISSING_HEADERS}" echo "*** Maybe the compiler isn't ANSI C compliant or not properly installed?" echo "*** For details on what went wrong see config.log." as_fn_error $? "Exiting now." "$LINENO" 5 fi for ac_header in winsock2.h do : ac_fn_c_check_header_mongrel "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default" if test "x$ac_cv_header_winsock2_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_WINSOCK2_H 1 _ACEOF SOCKET_LIB="-lws2_32" fi done ac_fn_c_check_header_mongrel "$LINENO" "resmgr.h" "ac_cv_header_resmgr_h" "$ac_includes_default" if test "x$ac_cv_header_resmgr_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rsm_open_device in -lresmgr" >&5 $as_echo_n "checking for rsm_open_device in -lresmgr... " >&6; } if ${ac_cv_lib_resmgr_rsm_open_device+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresmgr $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char rsm_open_device (); int main () { return rsm_open_device (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resmgr_rsm_open_device=yes else ac_cv_lib_resmgr_rsm_open_device=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resmgr_rsm_open_device" >&5 $as_echo "$ac_cv_lib_resmgr_rsm_open_device" >&6; } if test "x$ac_cv_lib_resmgr_rsm_open_device" = xyes; then : $as_echo "#define HAVE_RESMGR 1" >>confdefs.h RESMGR_LIBS="-lresmgr" fi fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" if test "x$ac_cv_type_ssize_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define ssize_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "u_char" "ac_cv_type_u_char" "$ac_includes_default" if test "x$ac_cv_type_u_char" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_U_CHAR 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "u_short" "ac_cv_type_u_short" "$ac_includes_default" if test "x$ac_cv_type_u_short" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_U_SHORT 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "u_int" "ac_cv_type_u_int" "$ac_includes_default" if test "x$ac_cv_type_u_int" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_U_INT 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "u_long" "ac_cv_type_u_long" "$ac_includes_default" if test "x$ac_cv_type_u_long" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_U_LONG 1 _ACEOF fi # from Python, check for "long long" type { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long support" >&5 $as_echo_n "checking for long long support... " >&6; } have_long_long=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { long long x; x = (long long)0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAVE_LONG_LONG 1" >>confdefs.h have_long_long=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_long_long" >&5 $as_echo "$have_long_long" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t in " >&5 $as_echo_n "checking for socklen_t in ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { socklen_t len ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; }; $as_echo "#define socklen_t int" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for union semun in " >&5 $as_echo_n "checking for union semun in ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { union semun test_semun ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; $as_echo "#define HAVE_UNION_SEMUN 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct flock in fcntl.h" >&5 $as_echo_n "checking for struct flock in fcntl.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "struct flock" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ; $as_echo "#define HAVE_STRUCT_FLOCK 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux ioctl defines" >&5 $as_echo_n "checking for Linux ioctl defines... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { __u32 houba = _IOR('v',14, unsigned long); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; have_linux_ioctl_defines="yes"; else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 $as_echo_n "checking for working alloca.h... " >&6; } if ${ac_cv_working_alloca_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *p = (char *) alloca (2 * sizeof (int)); if (p) return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_working_alloca_h=yes else ac_cv_working_alloca_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 $as_echo "$ac_cv_working_alloca_h" >&6; } if test $ac_cv_working_alloca_h = yes; then $as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 $as_echo_n "checking for alloca... " >&6; } if ${ac_cv_func_alloca_works+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __GNUC__ # define alloca __builtin_alloca #else # ifdef _MSC_VER # include # define alloca _alloca # else # ifdef HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ void *alloca (size_t); # endif # endif # endif # endif #endif int main () { char *p = (char *) alloca (1); if (p) return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_func_alloca_works=yes else ac_cv_func_alloca_works=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 $as_echo "$ac_cv_func_alloca_works" >&6; } if test $ac_cv_func_alloca_works = yes; then $as_echo "#define HAVE_ALLOCA 1" >>confdefs.h else # The SVR3 libPW and SVR4 libucb both contain incompatible functions # that cause trouble. Some versions do not even contain alloca or # contain a buggy version. If you still want to use their alloca, # use ar to extract alloca.o from them instead of compiling alloca.c. ALLOCA=\${LIBOBJDIR}alloca.$ac_objext $as_echo "#define C_ALLOCA 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 $as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } if ${ac_cv_os_cray+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined CRAY && ! defined CRAY2 webecray #else wenotbecray #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "webecray" >/dev/null 2>&1; then : ac_cv_os_cray=yes else ac_cv_os_cray=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 $as_echo "$ac_cv_os_cray" >&6; } if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define CRAY_STACKSEG_END $ac_func _ACEOF break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 $as_echo_n "checking stack direction for C alloca... " >&6; } if ${ac_cv_c_stack_direction+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_c_stack_direction=0 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int find_stack_direction (int *addr, int depth) { int dir, dummy = 0; if (! addr) addr = &dummy; *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; dir = depth ? find_stack_direction (addr, depth - 1) : 0; return dir + dummy; } int main (int argc, char **argv) { return find_stack_direction (0, argc + !argv + 20) < 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_stack_direction=1 else ac_cv_c_stack_direction=-1 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 $as_echo "$ac_cv_c_stack_direction" >&6; } cat >>confdefs.h <<_ACEOF #define STACK_DIRECTION $ac_cv_c_stack_direction _ACEOF fi ac_fn_c_check_func "$LINENO" "getenv" "ac_cv_func_getenv" if test "x$ac_cv_func_getenv" = xyes; then : $as_echo "#define HAVE_GETENV 1" >>confdefs.h else case " $LIBOBJS " in *" getenv.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getenv.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" if test "x$ac_cv_func_inet_ntop" = xyes; then : $as_echo "#define HAVE_INET_NTOP 1" >>confdefs.h else case " $LIBOBJS " in *" inet_ntop.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS inet_ntop.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" if test "x$ac_cv_func_inet_pton" = xyes; then : $as_echo "#define HAVE_INET_PTON 1" >>confdefs.h else case " $LIBOBJS " in *" inet_pton.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS inet_pton.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "isfdtype" "ac_cv_func_isfdtype" if test "x$ac_cv_func_isfdtype" = xyes; then : $as_echo "#define HAVE_ISFDTYPE 1" >>confdefs.h else case " $LIBOBJS " in *" isfdtype.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS isfdtype.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "sigprocmask" "ac_cv_func_sigprocmask" if test "x$ac_cv_func_sigprocmask" = xyes; then : $as_echo "#define HAVE_SIGPROCMASK 1" >>confdefs.h else case " $LIBOBJS " in *" sigprocmask.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS sigprocmask.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "sleep" "ac_cv_func_sleep" if test "x$ac_cv_func_sleep" = xyes; then : $as_echo "#define HAVE_SLEEP 1" >>confdefs.h else case " $LIBOBJS " in *" sleep.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS sleep.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" if test "x$ac_cv_func_snprintf" = xyes; then : $as_echo "#define HAVE_SNPRINTF 1" >>confdefs.h else case " $LIBOBJS " in *" snprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "strcasestr" "ac_cv_func_strcasestr" if test "x$ac_cv_func_strcasestr" = xyes; then : $as_echo "#define HAVE_STRCASESTR 1" >>confdefs.h else case " $LIBOBJS " in *" strcasestr.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strcasestr.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" if test "x$ac_cv_func_strdup" = xyes; then : $as_echo "#define HAVE_STRDUP 1" >>confdefs.h else case " $LIBOBJS " in *" strdup.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strdup.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup" if test "x$ac_cv_func_strndup" = xyes; then : $as_echo "#define HAVE_STRNDUP 1" >>confdefs.h else case " $LIBOBJS " in *" strndup.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strndup.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep" if test "x$ac_cv_func_strsep" = xyes; then : $as_echo "#define HAVE_STRSEP 1" >>confdefs.h else case " $LIBOBJS " in *" strsep.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strsep.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "syslog" "ac_cv_func_syslog" if test "x$ac_cv_func_syslog" = xyes; then : $as_echo "#define HAVE_SYSLOG 1" >>confdefs.h else case " $LIBOBJS " in *" syslog.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS syslog.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "usleep" "ac_cv_func_usleep" if test "x$ac_cv_func_usleep" = xyes; then : $as_echo "#define HAVE_USLEEP 1" >>confdefs.h else case " $LIBOBJS " in *" usleep.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS usleep.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "vsyslog" "ac_cv_func_vsyslog" if test "x$ac_cv_func_vsyslog" = xyes; then : $as_echo "#define HAVE_VSYSLOG 1" >>confdefs.h else case " $LIBOBJS " in *" vsyslog.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS vsyslog.$ac_objext" ;; esac fi if test x != x$ALLOCA; then : LTALLOCA=`echo "$ALLOCA" | sed 's/\.o$//; s/\.obj$//'`.lo fi ac_fn_c_check_func "$LINENO" "gethostbyaddr" "ac_cv_func_gethostbyaddr" if test "x$ac_cv_func_gethostbyaddr" = xyes; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr in -lbind" >&5 $as_echo_n "checking for gethostbyaddr in -lbind... " >&6; } if ${ac_cv_lib_bind_gethostbyaddr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyaddr (); int main () { return gethostbyaddr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bind_gethostbyaddr=yes else ac_cv_lib_bind_gethostbyaddr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_gethostbyaddr" >&5 $as_echo "$ac_cv_lib_bind_gethostbyaddr" >&6; } if test "x$ac_cv_lib_bind_gethostbyaddr" = xyes; then : BIND_LIB="-lbind" fi fi ac_fn_c_check_func "$LINENO" "gethostbyaddr" "ac_cv_func_gethostbyaddr" if test "x$ac_cv_func_gethostbyaddr" = xyes; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr in -lnsl" >&5 $as_echo_n "checking for gethostbyaddr in -lnsl... " >&6; } if ${ac_cv_lib_nsl_gethostbyaddr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyaddr (); int main () { return gethostbyaddr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_gethostbyaddr=yes else ac_cv_lib_nsl_gethostbyaddr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyaddr" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyaddr" >&6; } if test "x$ac_cv_lib_nsl_gethostbyaddr" = xyes; then : NSL_LIB="-lnsl" fi fi ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" if test "x$ac_cv_func_socket" = xyes; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socket=yes else ac_cv_lib_socket_socket=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 $as_echo "$ac_cv_lib_socket_socket" >&6; } if test "x$ac_cv_lib_socket_socket" = xyes; then : SOCKET_LIB="-lsocket" fi fi ac_fn_c_check_func "$LINENO" "inet_aton" "ac_cv_func_inet_aton" if test "x$ac_cv_func_inet_aton" = xyes; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_aton in -lresolv" >&5 $as_echo_n "checking for inet_aton in -lresolv... " >&6; } if ${ac_cv_lib_resolv_inet_aton+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_aton (); int main () { return inet_aton (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv_inet_aton=yes else ac_cv_lib_resolv_inet_aton=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_inet_aton" >&5 $as_echo "$ac_cv_lib_resolv_inet_aton" >&6; } if test "x$ac_cv_lib_resolv_inet_aton" = xyes; then : RESOLV_LIB="-lresolv" fi fi SOCKET_LIBS="$SOCKET_LIB $NSL_LIB $BIND_LIB $RESOLV_LIB" save_LIBS="$LIBS" LIBS="$LIBS $SOCKET_LIBS" for ac_func in inet_addr inet_aton inet_ntoa do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done LIBS="$save_LIBS" if test "$ac_cv_header_be_kernel_OS_h" = "yes" ; then ac_cv_func_getaddrinfo=no ac_cv_func_getnameinfo=no fi for ac_header in $ac_header_list do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getpagesize do : ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" if test "x$ac_cv_func_getpagesize" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETPAGESIZE 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5 $as_echo_n "checking for working mmap... " >&6; } if ${ac_cv_func_mmap_fixed_mapped+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_mmap_fixed_mapped=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default /* malloc might have been renamed as rpl_malloc. */ #undef malloc /* Thanks to Mike Haertel and Jim Avera for this test. Here is a matrix of mmap possibilities: mmap private not fixed mmap private fixed at somewhere currently unmapped mmap private fixed at somewhere already mapped mmap shared not fixed mmap shared fixed at somewhere currently unmapped mmap shared fixed at somewhere already mapped For private mappings, we should verify that changes cannot be read() back from the file, nor mmap's back from the file at a different address. (There have been systems where private was not correctly implemented like the infamous i386 svr4.0, and systems where the VM page cache was not coherent with the file system buffer cache like early versions of FreeBSD and possibly contemporary NetBSD.) For shared mappings, we should conversely verify that changes get propagated back to all the places they're supposed to be. Grep wants private fixed already mapped. The main things grep needs to know about mmap are: * does it exist and is it safe to write into the mmap'd area * how to use it (BSD variants) */ #include #include #if !defined STDC_HEADERS && !defined HAVE_STDLIB_H char *malloc (); #endif /* This mess was copied from the GNU getpagesize.h. */ #ifndef HAVE_GETPAGESIZE # ifdef _SC_PAGESIZE # define getpagesize() sysconf(_SC_PAGESIZE) # else /* no _SC_PAGESIZE */ # ifdef HAVE_SYS_PARAM_H # include # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else /* no EXEC_PAGESIZE */ # ifdef NBPG # define getpagesize() NBPG * CLSIZE # ifndef CLSIZE # define CLSIZE 1 # endif /* no CLSIZE */ # else /* no NBPG */ # ifdef NBPC # define getpagesize() NBPC # else /* no NBPC */ # ifdef PAGESIZE # define getpagesize() PAGESIZE # endif /* PAGESIZE */ # endif /* no NBPC */ # endif /* no NBPG */ # endif /* no EXEC_PAGESIZE */ # else /* no HAVE_SYS_PARAM_H */ # define getpagesize() 8192 /* punt totally */ # endif /* no HAVE_SYS_PARAM_H */ # endif /* no _SC_PAGESIZE */ #endif /* no HAVE_GETPAGESIZE */ int main () { char *data, *data2, *data3; const char *cdata2; int i, pagesize; int fd, fd2; pagesize = getpagesize (); /* First, make a file with some known garbage in it. */ data = (char *) malloc (pagesize); if (!data) return 1; for (i = 0; i < pagesize; ++i) *(data + i) = rand (); umask (0); fd = creat ("conftest.mmap", 0600); if (fd < 0) return 2; if (write (fd, data, pagesize) != pagesize) return 3; close (fd); /* Next, check that the tail of a page is zero-filled. File must have non-zero length, otherwise we risk SIGBUS for entire page. */ fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600); if (fd2 < 0) return 4; cdata2 = ""; if (write (fd2, cdata2, 1) != 1) return 5; data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L); if (data2 == MAP_FAILED) return 6; for (i = 0; i < pagesize; ++i) if (*(data2 + i)) return 7; close (fd2); if (munmap (data2, pagesize)) return 8; /* Next, try to mmap the file at a fixed address which already has something else allocated at it. If we can, also make sure that we see the same garbage. */ fd = open ("conftest.mmap", O_RDWR); if (fd < 0) return 9; if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)) return 10; for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data2 + i)) return 11; /* Finally, make sure that changes to the mapped area do not percolate back to the file as seen by read(). (This is a bug on some variants of i386 svr4.0.) */ for (i = 0; i < pagesize; ++i) *(data2 + i) = *(data2 + i) + 1; data3 = (char *) malloc (pagesize); if (!data3) return 12; if (read (fd, data3, pagesize) != pagesize) return 13; for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data3 + i)) return 14; close (fd); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_mmap_fixed_mapped=yes else ac_cv_func_mmap_fixed_mapped=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5 $as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; } if test $ac_cv_func_mmap_fixed_mapped = yes; then $as_echo "#define HAVE_MMAP 1" >>confdefs.h fi rm -f conftest.mmap conftest.txt for ac_func in atexit ioperm i386_set_ioperm \ mkdir strftime strstr strtod \ cfmakeraw tcsendbreak strcasecmp strncasecmp _portaccess \ getaddrinfo getnameinfo poll setitimer iopl getuid getpass do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "${ac_cv_header_sys_io_h}" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inb,outb (provided by sys/io.h)" >&5 $as_echo_n "checking for inb,outb (provided by sys/io.h)... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { inb(0);outb(0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } sane_cv_have_sys_io_h_with_inb_outb="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } sane_cv_have_sys_io_h_with_inb_outb="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: sys/io.h does not provide inb,outb (non i386/x32/x86_64 arch?)" >&5 $as_echo "$as_me: WARNING: sys/io.h does not provide inb,outb (non i386/x32/x86_64 arch?)" >&2;} fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$sane_cv_have_sys_io_h_with_inb_outb" = "yes"; then $as_echo "#define SANE_HAVE_SYS_IO_H_WITH_INB_OUTB 1" >>confdefs.h fi else sane_cv_have_sys_io_h_with_inb_outb="no" fi if test "$ac_cv_header_os2_h" = "yes" ; then $as_echo "#define strncasecmp strnicmp" >>confdefs.h $as_echo "#define strcasecmp stricmp" >>confdefs.h fi if test "$ac_cv_header_getopt_h" = "yes" ; then for ac_func in getopt_long do : ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long" if test "x$ac_cv_func_getopt_long" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETOPT_LONG 1 _ACEOF fi done fi # Slightly abuse the AC_LIBOBJ macro to mark files as replacement code if test x$ac_cv_header_getopt_h != xyes \ && test x$ac_cv_func_getopt_long != xyes; then : case " $LIBOBJS " in *" getopt.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getopt.$ac_objext" ;; esac case " $LIBOBJS " in *" getopt1.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getopt1.$ac_objext" ;; esac fi if test -c /dev/urandom ; then $as_echo "#define HAVE_DEV_URANDOM 1" >>confdefs.h fi # Check whether --with-systemd was given. if test "${with_systemd+set}" = set; then : withval=$with_systemd; fi if test "x$with_systemd" != xno ; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD" >&5 $as_echo_n "checking for SYSTEMD... " >&6; } if test -n "$SYSTEMD_CFLAGS"; then pkg_cv_SYSTEMD_CFLAGS="$SYSTEMD_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5 ($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SYSTEMD_CFLAGS=`$PKG_CONFIG --cflags "libsystemd" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SYSTEMD_LIBS"; then pkg_cv_SYSTEMD_LIBS="$SYSTEMD_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5 ($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SYSTEMD_LIBS=`$PKG_CONFIG --libs "libsystemd" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd" 2>&1` else SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SYSTEMD_PKG_ERRORS" >&5 have_systemd=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_systemd=no else SYSTEMD_CFLAGS=$pkg_cv_SYSTEMD_CFLAGS SYSTEMD_LIBS=$pkg_cv_SYSTEMD_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_systemd=yes fi if test "x$have_systemd" = xno; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD" >&5 $as_echo_n "checking for SYSTEMD... " >&6; } if test -n "$SYSTEMD_CFLAGS"; then pkg_cv_SYSTEMD_CFLAGS="$SYSTEMD_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-daemon\""; } >&5 ($PKG_CONFIG --exists --print-errors "libsystemd-daemon") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SYSTEMD_CFLAGS=`$PKG_CONFIG --cflags "libsystemd-daemon" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SYSTEMD_LIBS"; then pkg_cv_SYSTEMD_LIBS="$SYSTEMD_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd-daemon\""; } >&5 ($PKG_CONFIG --exists --print-errors "libsystemd-daemon") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SYSTEMD_LIBS=`$PKG_CONFIG --libs "libsystemd-daemon" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd-daemon" 2>&1` else SYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd-daemon" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SYSTEMD_PKG_ERRORS" >&5 have_systemd=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_systemd=no else SYSTEMD_CFLAGS=$pkg_cv_SYSTEMD_CFLAGS SYSTEMD_LIBS=$pkg_cv_SYSTEMD_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } have_systemd=yes fi fi if test "x$have_systemd" = xyes; then $as_echo "#define HAVE_SYSTEMD 1" >>confdefs.h else if test "x$with_systemd" = xyes; then as_fn_error $? "Systemd support was requested but systemd was not found" "$LINENO" 5 fi fi fi # Check whether --with-usb was given. if test "${with_usb+set}" = set; then : withval=$with_usb; else with_usb=check fi if test xno != "x$with_usb"; then : have_usb=no case x$host_os in #( beos*) : ac_fn_c_check_header_mongrel "$LINENO" "be/drivers/USB_scanner.h" "ac_cv_header_be_drivers_USB_scanner_h" "$ac_includes_default" if test "x$ac_cv_header_be_drivers_USB_scanner_h" = xyes; then : have_usb=yes fi ;; #( os2*) : ac_fn_c_check_header_compile "$LINENO" "usbcalls.h" "ac_cv_header_usbcalls_h" "#include #include " if test "x$ac_cv_header_usbcalls_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for UsbQueryNumberDevices in -lusbcall" >&5 $as_echo_n "checking for UsbQueryNumberDevices in -lusbcall... " >&6; } if ${ac_cv_lib_usbcall_UsbQueryNumberDevices+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusbcall $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char UsbQueryNumberDevices (); int main () { return UsbQueryNumberDevices (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usbcall_UsbQueryNumberDevices=yes else ac_cv_lib_usbcall_UsbQueryNumberDevices=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usbcall_UsbQueryNumberDevices" >&5 $as_echo "$ac_cv_lib_usbcall_UsbQueryNumberDevices" >&6; } if test "x$ac_cv_lib_usbcall_UsbQueryNumberDevices" = xyes; then : USB_LIBS="-lusbcall" have_usb=yes $as_echo "#define HAVE_USBCALLS 1" >>confdefs.h fi fi ;; #( *) : pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB" >&5 $as_echo_n "checking for USB... " >&6; } if test -n "$USB_CFLAGS"; then pkg_cv_USB_CFLAGS="$USB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb-1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_USB_CFLAGS=`$PKG_CONFIG --cflags "libusb-1.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$USB_LIBS"; then pkg_cv_USB_LIBS="$USB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb-1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb-1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_USB_LIBS=`$PKG_CONFIG --libs "libusb-1.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then USB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libusb-1.0" 2>&1` else USB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libusb-1.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$USB_PKG_ERRORS" >&5 pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB" >&5 $as_echo_n "checking for USB... " >&6; } if test -n "$USB_CFLAGS"; then pkg_cv_USB_CFLAGS="$USB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb >= 0.1.8\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb >= 0.1.8") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_USB_CFLAGS=`$PKG_CONFIG --cflags "libusb >= 0.1.8" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$USB_LIBS"; then pkg_cv_USB_LIBS="$USB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb >= 0.1.8\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb >= 0.1.8") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_USB_LIBS=`$PKG_CONFIG --libs "libusb >= 0.1.8" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then USB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libusb >= 0.1.8" 2>&1` else USB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libusb >= 0.1.8" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$USB_PKG_ERRORS" >&5 ac_fn_c_check_header_mongrel "$LINENO" "usb.h" "ac_cv_header_usb_h" "$ac_includes_default" if test "x$ac_cv_header_usb_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_interrupt_read in -lusb" >&5 $as_echo_n "checking for usb_interrupt_read in -lusb... " >&6; } if ${ac_cv_lib_usb_usb_interrupt_read+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char usb_interrupt_read (); int main () { return usb_interrupt_read (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usb_usb_interrupt_read=yes else ac_cv_lib_usb_usb_interrupt_read=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_interrupt_read" >&5 $as_echo "$ac_cv_lib_usb_usb_interrupt_read" >&6; } if test "x$ac_cv_lib_usb_usb_interrupt_read" = xyes; then : USB_LIBS="-lusb" have_usb=yes fi fi for ac_header in lusb0_usb.h do : ac_fn_c_check_header_mongrel "$LINENO" "lusb0_usb.h" "ac_cv_header_lusb0_usb_h" "$ac_includes_default" if test "x$ac_cv_header_lusb0_usb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LUSB0_USB_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_interrupt_read in -lusb" >&5 $as_echo_n "checking for usb_interrupt_read in -lusb... " >&6; } if ${ac_cv_lib_usb_usb_interrupt_read+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char usb_interrupt_read (); int main () { return usb_interrupt_read (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usb_usb_interrupt_read=yes else ac_cv_lib_usb_usb_interrupt_read=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_interrupt_read" >&5 $as_echo "$ac_cv_lib_usb_usb_interrupt_read" >&6; } if test "x$ac_cv_lib_usb_usb_interrupt_read" = xyes; then : USB_LIBS="-lusb" have_usb=yes fi fi done elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ac_fn_c_check_header_mongrel "$LINENO" "usb.h" "ac_cv_header_usb_h" "$ac_includes_default" if test "x$ac_cv_header_usb_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_interrupt_read in -lusb" >&5 $as_echo_n "checking for usb_interrupt_read in -lusb... " >&6; } if ${ac_cv_lib_usb_usb_interrupt_read+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char usb_interrupt_read (); int main () { return usb_interrupt_read (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usb_usb_interrupt_read=yes else ac_cv_lib_usb_usb_interrupt_read=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_interrupt_read" >&5 $as_echo "$ac_cv_lib_usb_usb_interrupt_read" >&6; } if test "x$ac_cv_lib_usb_usb_interrupt_read" = xyes; then : USB_LIBS="-lusb" have_usb=yes fi fi for ac_header in lusb0_usb.h do : ac_fn_c_check_header_mongrel "$LINENO" "lusb0_usb.h" "ac_cv_header_lusb0_usb_h" "$ac_includes_default" if test "x$ac_cv_header_lusb0_usb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LUSB0_USB_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_interrupt_read in -lusb" >&5 $as_echo_n "checking for usb_interrupt_read in -lusb... " >&6; } if ${ac_cv_lib_usb_usb_interrupt_read+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char usb_interrupt_read (); int main () { return usb_interrupt_read (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usb_usb_interrupt_read=yes else ac_cv_lib_usb_usb_interrupt_read=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_interrupt_read" >&5 $as_echo "$ac_cv_lib_usb_usb_interrupt_read" >&6; } if test "x$ac_cv_lib_usb_usb_interrupt_read" = xyes; then : USB_LIBS="-lusb" have_usb=yes fi fi done else USB_CFLAGS=$pkg_cv_USB_CFLAGS USB_LIBS=$pkg_cv_USB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_LIBUSB_LEGACY 1" >>confdefs.h have_usb=yes fi elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB" >&5 $as_echo_n "checking for USB... " >&6; } if test -n "$USB_CFLAGS"; then pkg_cv_USB_CFLAGS="$USB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb >= 0.1.8\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb >= 0.1.8") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_USB_CFLAGS=`$PKG_CONFIG --cflags "libusb >= 0.1.8" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$USB_LIBS"; then pkg_cv_USB_LIBS="$USB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libusb >= 0.1.8\""; } >&5 ($PKG_CONFIG --exists --print-errors "libusb >= 0.1.8") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_USB_LIBS=`$PKG_CONFIG --libs "libusb >= 0.1.8" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then USB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libusb >= 0.1.8" 2>&1` else USB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libusb >= 0.1.8" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$USB_PKG_ERRORS" >&5 ac_fn_c_check_header_mongrel "$LINENO" "usb.h" "ac_cv_header_usb_h" "$ac_includes_default" if test "x$ac_cv_header_usb_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_interrupt_read in -lusb" >&5 $as_echo_n "checking for usb_interrupt_read in -lusb... " >&6; } if ${ac_cv_lib_usb_usb_interrupt_read+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char usb_interrupt_read (); int main () { return usb_interrupt_read (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usb_usb_interrupt_read=yes else ac_cv_lib_usb_usb_interrupt_read=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_interrupt_read" >&5 $as_echo "$ac_cv_lib_usb_usb_interrupt_read" >&6; } if test "x$ac_cv_lib_usb_usb_interrupt_read" = xyes; then : USB_LIBS="-lusb" have_usb=yes fi fi for ac_header in lusb0_usb.h do : ac_fn_c_check_header_mongrel "$LINENO" "lusb0_usb.h" "ac_cv_header_lusb0_usb_h" "$ac_includes_default" if test "x$ac_cv_header_lusb0_usb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LUSB0_USB_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_interrupt_read in -lusb" >&5 $as_echo_n "checking for usb_interrupt_read in -lusb... " >&6; } if ${ac_cv_lib_usb_usb_interrupt_read+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char usb_interrupt_read (); int main () { return usb_interrupt_read (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usb_usb_interrupt_read=yes else ac_cv_lib_usb_usb_interrupt_read=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_interrupt_read" >&5 $as_echo "$ac_cv_lib_usb_usb_interrupt_read" >&6; } if test "x$ac_cv_lib_usb_usb_interrupt_read" = xyes; then : USB_LIBS="-lusb" have_usb=yes fi fi done elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ac_fn_c_check_header_mongrel "$LINENO" "usb.h" "ac_cv_header_usb_h" "$ac_includes_default" if test "x$ac_cv_header_usb_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_interrupt_read in -lusb" >&5 $as_echo_n "checking for usb_interrupt_read in -lusb... " >&6; } if ${ac_cv_lib_usb_usb_interrupt_read+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char usb_interrupt_read (); int main () { return usb_interrupt_read (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usb_usb_interrupt_read=yes else ac_cv_lib_usb_usb_interrupt_read=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_interrupt_read" >&5 $as_echo "$ac_cv_lib_usb_usb_interrupt_read" >&6; } if test "x$ac_cv_lib_usb_usb_interrupt_read" = xyes; then : USB_LIBS="-lusb" have_usb=yes fi fi for ac_header in lusb0_usb.h do : ac_fn_c_check_header_mongrel "$LINENO" "lusb0_usb.h" "ac_cv_header_lusb0_usb_h" "$ac_includes_default" if test "x$ac_cv_header_lusb0_usb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LUSB0_USB_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for usb_interrupt_read in -lusb" >&5 $as_echo_n "checking for usb_interrupt_read in -lusb... " >&6; } if ${ac_cv_lib_usb_usb_interrupt_read+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lusb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char usb_interrupt_read (); int main () { return usb_interrupt_read (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_usb_usb_interrupt_read=yes else ac_cv_lib_usb_usb_interrupt_read=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_usb_usb_interrupt_read" >&5 $as_echo "$ac_cv_lib_usb_usb_interrupt_read" >&6; } if test "x$ac_cv_lib_usb_usb_interrupt_read" = xyes; then : USB_LIBS="-lusb" have_usb=yes fi fi done else USB_CFLAGS=$pkg_cv_USB_CFLAGS USB_LIBS=$pkg_cv_USB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_LIBUSB_LEGACY 1" >>confdefs.h have_usb=yes fi else USB_CFLAGS=$pkg_cv_USB_CFLAGS USB_LIBS=$pkg_cv_USB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_LIBUSB 1" >>confdefs.h have_usb=yes fi ;; esac fi if test xyes = "x$with_usb" && test xyes != "x$have_usb"; then : as_fn_error $? "USB support requested but required libraries not found." "$LINENO" 5 fi if test x != "x$USB_LIBS"; then have_usblib_TRUE= have_usblib_FALSE='#' else have_usblib_TRUE='#' have_usblib_FALSE= fi # Unset VERSION during the SCSI header check sed "s!^#define VERSION .*!/* & */!" confdefs.h > confdefs.h.tmp mv confdefs.h.tmp confdefs.h for ac_header in IOKit/scsi/SCSITaskLib.h IOKit/cdb/IOSCSILib.h \ IOKit/scsi/SCSICommandOperationCodes.h \ IOKit/scsi-commands/SCSICommandOperationCodes.h scsi.h sys/scsi.h \ sys/scsicmd.h sys/scsiio.h bsd/dev/scsireg.h scsi/sg.h \ camlib.h gscdds.h sys/scsi/scsi.h sys/scsi/sgdefs.h \ sys/scsi/targets/scgio.h apollo/scsi.h sys/sdi_comm.h \ sys/passthrudef.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Restore VERSION sed "s!/\* \(#define VERSION .*\) \*/!\1!" confdefs.h > confdefs.h.tmp mv confdefs.h.tmp confdefs.h for ac_header in io/cam/cam.h do : ac_fn_c_check_header_compile "$LINENO" "io/cam/cam.h" "ac_cv_header_io_cam_cam_h" "#include " if test "x$ac_cv_header_io_cam_cam_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_IO_CAM_CAM_H 1 _ACEOF fi done for ac_header in ntddscsi.h ddk/ntddscsi.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_header_sys_scsiio_h" = "yes" \ && test "$ac_cv_header_scsi_h" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 'scsireq_t' needs to be defined as 'struct scsireq'" >&5 $as_echo_n "checking if 'scsireq_t' needs to be defined as 'struct scsireq'... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { scsireq_t req ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; $as_echo "#define scsireq_t struct scsireq_t" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for scsireq_enter in -lscsi" >&5 $as_echo_n "checking for scsireq_enter in -lscsi... " >&6; } if ${ac_cv_lib_scsi_scsireq_enter+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lscsi $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char scsireq_enter (); int main () { return scsireq_enter (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_scsi_scsireq_enter=yes else ac_cv_lib_scsi_scsireq_enter=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_scsi_scsireq_enter" >&5 $as_echo "$ac_cv_lib_scsi_scsireq_enter" >&6; } if test "x$ac_cv_lib_scsi_scsireq_enter" = xyes; then : SCSI_LIBS="-lscsi" fi # FreeBSD needs this { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cam_open_device in -lcam" >&5 $as_echo_n "checking for cam_open_device in -lcam... " >&6; } if ${ac_cv_lib_cam_cam_open_device+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcam $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char cam_open_device (); int main () { return cam_open_device (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_cam_cam_open_device=yes else ac_cv_lib_cam_cam_open_device=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cam_cam_open_device" >&5 $as_echo "$ac_cv_lib_cam_cam_open_device" >&6; } if test "x$ac_cv_lib_cam_cam_open_device" = xyes; then : SCSI_LIBS="-lcam" fi # FreeBSD 3+ needs this for ac_func in scsireq_enter do : ac_fn_c_check_func "$LINENO" "scsireq_enter" "ac_cv_func_scsireq_enter" if test "x$ac_cv_func_scsireq_enter" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SCSIREQ_ENTER 1 _ACEOF fi done if test "$ac_cv_header_scsi_sg_h" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sg_header.target_status in " >&5 $as_echo_n "checking for sg_header.target_status in ... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct sg_header hdr; hdr.target_status = 1; return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; $as_echo "#define HAVE_SG_TARGET_STATUS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "$ac_cv_header_IOKit_scsi_SCSITaskLib_h" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SCSITaskSGElement in IOKit/scsi/SCSITaskLib.h" >&5 $as_echo_n "checking for SCSITaskSGElement in IOKit/scsi/SCSITaskLib.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #undef VERSION #include int main () { SCSITaskSGElement range; return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; $as_echo "#define HAVE_SCSITASKSGELEMENT 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi # Multiple platforms can set SCSI_LIBS so do substitution at end. # Check whether --enable-scsibuffersize was given. if test "${enable_scsibuffersize+set}" = set; then : enableval=$enable_scsibuffersize; set_scsibuffersize="$enableval" else set_scsibuffersize=131072 fi cat >>confdefs.h <<_ACEOF #define SCSIBUFFERSIZE $set_scsibuffersize _ACEOF echo "scsi buffersize: $set_scsibuffersize" # Check whether --enable-scsi-directio was given. if test "${enable_scsi_directio+set}" = set; then : enableval=$enable_scsi_directio; if eval "test x$enable_scsi_directio = xyes"; then AM_CFLAGS="$AM_CFLAGS -DENABLE_SCSI_DIRECTIO" fi fi if test "$ac_cv_func_getnameinfo" = "yes" \ && test "$ac_cv_func_getaddrinfo" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable IPv6" >&5 $as_echo_n "checking whether to enable IPv6... " >&6; } # Check whether --enable-ipv6 was given. if test "${enable_ipv6+set}" = set; then : enableval=$enable_ipv6; if test "$enableval" = "no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, manually disabled" >&5 $as_echo "no, manually disabled" >&6; } ipv6=no fi fi if test "$ipv6" != "no" ; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define INET6 #include #include int main () { /* AF_INET6 available check */ if (socket(AF_INET6, SOCK_STREAM, 0) < 0) exit(1); else exit(0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define ENABLE_IPV6 1" >>confdefs.h ipv6=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (couldn't compile test program)" >&5 $as_echo "no (couldn't compile test program)" >&6; } ipv6=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "$ipv6" != "no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct sockaddr_storage has an ss_family member" >&5 $as_echo_n "checking whether struct sockaddr_storage has an ss_family member... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define INET6 #include #include int main () { /* test if the ss_family member exists in struct sockaddr_storage */ struct sockaddr_storage ss; ss.ss_family = AF_INET; exit (0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAS_SS_FAMILY 1" >>confdefs.h else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define INET6 #include #include int main () { /* test if the __ss_family member exists in struct sockaddr_storage */ struct sockaddr_storage ss; ss.__ss_family = AF_INET; exit (0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, but __ss_family exists" >&5 $as_echo "no, but __ss_family exists" >&6; } $as_echo "#define HAS___SS_FAMILY 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ipv6=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi else ipv6="no" fi # Check whether --enable-preload was given. if test "${enable_preload+set}" = set; then : enableval=$enable_preload; enable_preload=$enableval else enable_preload=auto fi case $host_os in cygwin* | mingw* | beos* | os2*) AM_LDFLAGS="$AM_LDFLAGS -no-undefined" esac # Check whether --with-lockdir was given. if test "${with_lockdir+set}" = set; then : withval=$with_lockdir; locksanedir=$withval else locksanedir=${localstatedir}/lock/sane fi configdir="${sysconfdir}/sane.d" AM_CPPFLAGS="${AM_CPPFLAGS} -DPATH_SANE_CONFIG_DIR=\$(configdir) \ -DPATH_SANE_DATA_DIR=\$(datadir) \ -DPATH_SANE_LOCK_DIR=\$(locksanedir) \ -DV_MAJOR=${V_MAJOR} -DV_MINOR=${V_MINOR}" if test "${ac_cv_header_sys_socket_h}" = "no"; then echo "*** disabling saned (sys/socket.h not found)" SANED= else SANED=saned fi if test x$SANED = xsaned; then COMPILE_SANED_TRUE= COMPILE_SANED_FALSE='#' else COMPILE_SANED_TRUE='#' COMPILE_SANED_FALSE= fi # Check whether --enable-local-backends was given. if test "${enable_local_backends+set}" = set; then : enableval=$enable_local_backends; fi ALL_BACKENDS="abaton agfafocus apple artec artec_eplus48u as6e \ avision bh canon canon630u canon_dr canon_pp cardscan \ coolscan coolscan2 coolscan3 dc25 dc210 dc240 \ dell1600n_net dmc epjitsu epson epson2 epsonds fujitsu genesys \ gphoto2 gt68xx hp hp3500 hp3900 hp4200 hp5400 \ hp5590 hpsj5s hpljm1005 hs2p ibm kodak kodakaio kvs1025 kvs20xx \ kvs40xx leo lexmark ma1509 magicolor \ matsushita microtek microtek2 mustek mustek_pp \ mustek_usb mustek_usb2 nec net niash pie pieusb pint \ pixma plustek plustek_pp qcam ricoh rts8891 s9036 \ sceptre sharp sm3600 sm3840 snapscan sp15c st400 \ stv680 tamarack teco1 teco2 teco3 test u12 umax umax_pp umax1220u v4l xerox_mfp p5" # If user specifies backends manually then cause configure # to fail if its detected it can't be compiled. If we # are in automatic mode then remove backend from list instead. user_selected_backends="yes" if eval "test x$enable_local_backends = xno"; then BACKENDS="net" else if test "${BACKENDS}" != "" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: Manually selected backends: ${BACKENDS}" >&5 $as_echo "$as_me: Manually selected backends: ${BACKENDS}" >&6;} else BACKENDS="$ALL_BACKENDS" user_selected_backends="no" fi fi if test "${user_selected_backends}" = "yes"; then DISABLE_MSG="aborting" else DISABLE_MSG="disabling" fi FILTERED_BACKENDS="" for be in ${BACKENDS}; do backend_supported="yes" case $be in plustek_pp) case "$host_os" in gnu*) echo "*** $be backend not supported on GNU/Hurd - $DISABLE_MSG" backend_supported="no" ;; esac ;; dc210|dc240) if test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires JPEG library - $DISABLE_MSG" backend_supported="no" fi ;; canon_pp|hpsj5s) if test "${sane_cv_use_libieee1284}" != "yes"; then echo "*** $be backend requires libieee1284 library - $DISABLE_MSG" backend_supported="no" fi ;; mustek_pp) if test "${sane_cv_use_libieee1284}" != "yes" && test "${enable_parport_directio}" != "yes"; then echo "*** $be backend requires libieee1284 or parport-directio libraries - $DISABLE_MSG" backend_supported="no" fi ;; dell1600n_net) if test "${sane_cv_use_libjpeg}" != "yes" || test "${sane_cv_use_libtiff}" != "yes"; then echo "*** $be backend requires JPEG and TIFF library - $DISABLE_MSG" backend_supported="no" fi ;; epsonds) if test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires JPEG library - $DISABLE_MSG" backend_supported="no" fi ;; gphoto2) if test "${HAVE_GPHOTO2}" != "true" \ || test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires gphoto2 and JPEG libraries - $DISABLE_MSG" backend_supported="no" fi ;; pint) if test "${ac_cv_header_sys_scanio_h}" = "no"; then echo "*** $be backend requires sys/scanio.h - $DISABLE_MSG" backend_supported="no" fi ;; qcam) if ( test "${ac_cv_func_ioperm}" = "no" || test "${sane_cv_have_sys_io_h_with_inb_outb}" = "no" )\ && test "${ac_cv_func__portaccess}" = "no"; then echo "*** $be backend requires (ioperm, inb and outb) or portaccess functions - $DISABLE_MSG" backend_supported="no" fi ;; v4l) if test "${have_linux_ioctl_defines}" != "yes" \ || test "${have_libv4l1}" != "yes"; then echo "*** $be backend requires v4l libraries - $DISABLE_MSG" backend_supported="no" fi ;; net) if test "${ac_cv_header_sys_socket_h}" = "no"; then echo "*** $be backend requires sys/socket.h - $DISABLE_MSG" backend_supported="no" fi ;; mustek_usb2|kvs40xx) if test "${have_pthread}" != "yes"; then echo "*** $be backend requires pthread library - $DISABLE_MSG" backend_supported="no" fi ;; esac if test "${backend_supported}" = "no"; then if test "${user_selected_backends}" = "yes"; then exit 1 fi else FILTERED_BACKENDS="${FILTERED_BACKENDS} $be" fi done if test "${sane_cv_use_libjpeg}" = "yes"; then SANEI_SANEI_JPEG_LO="../sanei/sanei_jpeg.lo" fi if test x$sane_cv_use_libjpeg = xyes; then HAVE_JPEG_TRUE= HAVE_JPEG_FALSE='#' else HAVE_JPEG_TRUE='#' HAVE_JPEG_FALSE= fi # Check whether --enable-pnm-backend was given. if test "${enable_pnm_backend+set}" = set; then : enableval=$enable_pnm_backend; FILTERED_BACKENDS="${FILTERED_BACKENDS} pnm" else echo "*** pnm backend not manually selected - disabling" fi BACKENDS="$FILTERED_BACKENDS" BACKEND_LIBS_ENABLED="" BACKEND_CONFS_ENABLED="" BACKEND_MANS_ENABLED="" for backend in ${BACKENDS} ; do BACKEND_LIBS_ENABLED="${BACKEND_LIBS_ENABLED} libsane-${backend}.la" BACKEND_CONFS_ENABLED="${BACKEND_CONFS_ENABLED} ${backend}.conf" BACKEND_MANS_ENABLED="${BACKEND_MANS_ENABLED} sane-${backend}.5" if test x$backend = xumax_pp; then install_umax_pp_tools=yes fi done if test xyes = x$install_umax_pp_tools; then INSTALL_UMAX_PP_TOOLS_TRUE= INSTALL_UMAX_PP_TOOLS_FALSE='#' else INSTALL_UMAX_PP_TOOLS_TRUE='#' INSTALL_UMAX_PP_TOOLS_FALSE= fi if test "${enable_preload}" = "auto"; then if test "${enable_shared}" = "no" || test "${enable_dynamic}" != "yes"; then enable_preload=yes fi fi if test "${enable_preload}" = "yes"; then echo "preloading backends into DLL" # If user specifies backends manually then cause configure # to fail if its detected it can't be compiled. If we # are in automatic mode then remove backend from list instead. user_selected_backends="yes" if eval "test x$enable_local_backends = xno"; then PRELOADABLE_BACKENDS="net" else if test "${PRELOADABLE_BACKENDS}" != "" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: Manually selected preloadable backends: ${PRELOADABLE_BACKENDS}" >&5 $as_echo "$as_me: Manually selected preloadable backends: ${PRELOADABLE_BACKENDS}" >&6;} else PRELOADABLE_BACKENDS="$BACKENDS" user_selected_backends="no" fi fi saved_BACKENDS="$BACKENDS" BACKENDS="${PRELOADABLE_BACKENDS}" if test "${user_selected_backends}" = "yes"; then DISABLE_MSG="aborting" else DISABLE_MSG="disabling" fi FILTERED_BACKENDS="" for be in ${BACKENDS}; do backend_supported="yes" case $be in plustek_pp) case "$host_os" in gnu*) echo "*** $be backend not supported on GNU/Hurd - $DISABLE_MSG" backend_supported="no" ;; esac ;; dc210|dc240) if test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires JPEG library - $DISABLE_MSG" backend_supported="no" fi ;; canon_pp|hpsj5s) if test "${sane_cv_use_libieee1284}" != "yes"; then echo "*** $be backend requires libieee1284 library - $DISABLE_MSG" backend_supported="no" fi ;; mustek_pp) if test "${sane_cv_use_libieee1284}" != "yes" && test "${enable_parport_directio}" != "yes"; then echo "*** $be backend requires libieee1284 or parport-directio libraries - $DISABLE_MSG" backend_supported="no" fi ;; dell1600n_net) if test "${sane_cv_use_libjpeg}" != "yes" || test "${sane_cv_use_libtiff}" != "yes"; then echo "*** $be backend requires JPEG and TIFF library - $DISABLE_MSG" backend_supported="no" fi ;; epsonds) if test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires JPEG library - $DISABLE_MSG" backend_supported="no" fi ;; gphoto2) if test "${HAVE_GPHOTO2}" != "true" \ || test "${sane_cv_use_libjpeg}" != "yes"; then echo "*** $be backend requires gphoto2 and JPEG libraries - $DISABLE_MSG" backend_supported="no" fi ;; pint) if test "${ac_cv_header_sys_scanio_h}" = "no"; then echo "*** $be backend requires sys/scanio.h - $DISABLE_MSG" backend_supported="no" fi ;; qcam) if ( test "${ac_cv_func_ioperm}" = "no" || test "${sane_cv_have_sys_io_h_with_inb_outb}" = "no" )\ && test "${ac_cv_func__portaccess}" = "no"; then echo "*** $be backend requires (ioperm, inb and outb) or portaccess functions - $DISABLE_MSG" backend_supported="no" fi ;; v4l) if test "${have_linux_ioctl_defines}" != "yes" \ || test "${have_libv4l1}" != "yes"; then echo "*** $be backend requires v4l libraries - $DISABLE_MSG" backend_supported="no" fi ;; net) if test "${ac_cv_header_sys_socket_h}" = "no"; then echo "*** $be backend requires sys/socket.h - $DISABLE_MSG" backend_supported="no" fi ;; mustek_usb2|kvs40xx) if test "${have_pthread}" != "yes"; then echo "*** $be backend requires pthread library - $DISABLE_MSG" backend_supported="no" fi ;; esac if test "${backend_supported}" = "no"; then if test "${user_selected_backends}" = "yes"; then exit 1 fi else FILTERED_BACKENDS="${FILTERED_BACKENDS} $be" fi done PRELOADABLE_BACKENDS="$FILTERED_BACKENDS" BACKENDS="$saved_BACKENDS" else PRELOADABLE_BACKENDS="" fi PRELOADABLE_BACKENDS_ENABLED="" # Do not initialize BACKEND_CONFS_ENABLED so that its a combination # of all backends. for backend in ${PRELOADABLE_BACKENDS} ; do BACKEND_CONFS_ENABLED="${BACKEND_CONFS_ENABLED} ${backend}.conf" BACKEND_MANS_ENABLED="${BACKEND_MANS_ENABLED} sane-${backend}.5" # Special hacks. Normally, we create a convenience library that # matches the backend's name but in some cases that will conflict # with an external library name that also matches backend name. # Work around that here by renaming internal library. if test "${backend}" = "gphoto2"; then backend=gphoto2_i fi PRELOADABLE_BACKENDS_ENABLED="${PRELOADABLE_BACKENDS_ENABLED} lib${backend}.la" done case $host_os in beos*) libdir='${exec_prefix}/add-ons' ;; esac # Check whether --enable-parport-directio was given. if test "${enable_parport_directio+set}" = set; then : enableval=$enable_parport_directio; if eval "test x$enable_parport_directio = xyes"; then AM_CFLAGS="$AM_CFLAGS -DENABLE_PARPORT_DIRECTIO" fi fi # Check whether --with-api-spec was given. if test "${with_api_spec+set}" = set; then : withval=$with_api_spec; else with_api_spec=check fi # Extract the first word of "makeindex", so it can be a program name with args. set dummy makeindex; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MAKEINDEX+:} false; then : $as_echo_n "(cached) " >&6 else case $MAKEINDEX in [\\/]* | ?:[\\/]*) ac_cv_path_MAKEINDEX="$MAKEINDEX" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MAKEINDEX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_MAKEINDEX" && ac_cv_path_MAKEINDEX="no" ;; esac fi MAKEINDEX=$ac_cv_path_MAKEINDEX if test -n "$MAKEINDEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINDEX" >&5 $as_echo "$MAKEINDEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "dvips", so it can be a program name with args. set dummy dvips; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_DVIPS+:} false; then : $as_echo_n "(cached) " >&6 else case $DVIPS in [\\/]* | ?:[\\/]*) ac_cv_path_DVIPS="$DVIPS" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_DVIPS="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_DVIPS" && ac_cv_path_DVIPS="no" ;; esac fi DVIPS=$ac_cv_path_DVIPS if test -n "$DVIPS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DVIPS" >&5 $as_echo "$DVIPS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "latex", so it can be a program name with args. set dummy latex; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_LATEX+:} false; then : $as_echo_n "(cached) " >&6 else case $LATEX in [\\/]* | ?:[\\/]*) ac_cv_path_LATEX="$LATEX" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_LATEX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_LATEX" && ac_cv_path_LATEX="no" ;; esac fi LATEX=$ac_cv_path_LATEX if test -n "$LATEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LATEX" >&5 $as_echo "$LATEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "pdflatex", so it can be a program name with args. set dummy pdflatex; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PDFLATEX+:} false; then : $as_echo_n "(cached) " >&6 else case $PDFLATEX in [\\/]* | ?:[\\/]*) ac_cv_path_PDFLATEX="$PDFLATEX" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PDFLATEX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_PDFLATEX" && ac_cv_path_PDFLATEX="no" ;; esac fi PDFLATEX=$ac_cv_path_PDFLATEX if test -n "$PDFLATEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PDFLATEX" >&5 $as_echo "$PDFLATEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "fig2dev", so it can be a program name with args. set dummy fig2dev; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_FIG2DEV+:} false; then : $as_echo_n "(cached) " >&6 else case $FIG2DEV in [\\/]* | ?:[\\/]*) ac_cv_path_FIG2DEV="$FIG2DEV" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_FIG2DEV="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_FIG2DEV" && ac_cv_path_FIG2DEV="no" ;; esac fi FIG2DEV=$ac_cv_path_FIG2DEV if test -n "$FIG2DEV"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FIG2DEV" >&5 $as_echo "$FIG2DEV" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "gs", so it can be a program name with args. set dummy gs; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GS+:} false; then : $as_echo_n "(cached) " >&6 else case $GS in [\\/]* | ?:[\\/]*) ac_cv_path_GS="$GS" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GS="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GS" && ac_cv_path_GS="no" ;; esac fi GS=$ac_cv_path_GS if test -n "$GS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GS" >&5 $as_echo "$GS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "dlh", so it can be a program name with args. set dummy dlh; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_DLH+:} false; then : $as_echo_n "(cached) " >&6 else case $DLH in [\\/]* | ?:[\\/]*) ac_cv_path_DLH="$DLH" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_DLH="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_DLH" && ac_cv_path_DLH="no" ;; esac fi DLH=$ac_cv_path_DLH if test -n "$DLH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLH" >&5 $as_echo "$DLH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "ppmtogif", so it can be a program name with args. set dummy ppmtogif; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PPMTOGIF+:} false; then : $as_echo_n "(cached) " >&6 else case $PPMTOGIF in [\\/]* | ?:[\\/]*) ac_cv_path_PPMTOGIF="$PPMTOGIF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PPMTOGIF="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_PPMTOGIF" && ac_cv_path_PPMTOGIF="no" ;; esac fi PPMTOGIF=$ac_cv_path_PPMTOGIF if test -n "$PPMTOGIF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PPMTOGIF" >&5 $as_echo "$PPMTOGIF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test xno != "x$with_api_spec"; then : if test xno != "x$MAKEINDEX" \ && test xno != "x$DVIPS" \ && test xno != "x$FIG2DEV" \ && test xno != "x$LATEX"; then : with_api_ps=yes fi if test xno != "x$MAKEINDEX" \ && test xno != "x$PDFLATEX" \ && test xno != "x$FIG2DEV" \ && test xno != "x$GS"; then : with_api_pdf=yes fi if test xno != "x$MAKEINDEX" \ && test xno != "x$DVIPS" \ && test xno != "x$FIG2DEV" \ && test xno != "x$DLH" \ && test xno != "x$GS" \ && test xno != "x$PPMTOFIG" ; then : with_api_html=yes fi if test xyes = "x$with_api_spec" \ && test xyes != "x$with_api_ps" \ && test xyes != "x$with_api_pdf" \ && test xyes != "x$with_api_html"; then : as_fn_error $? "tools to convert the API spec are missing" "$LINENO" 5 fi fi if test x$with_api_ps = xyes; then WITH_API_PS_TRUE= WITH_API_PS_FALSE='#' else WITH_API_PS_TRUE='#' WITH_API_PS_FALSE= fi if test x$with_api_pdf = xyes; then WITH_API_PDF_TRUE= WITH_API_PDF_FALSE='#' else WITH_API_PDF_TRUE='#' WITH_API_PDF_FALSE= fi if test x$with_api_html = xyes; then WITH_API_HTML_TRUE= WITH_API_HTML_FALSE='#' else WITH_API_HTML_TRUE='#' WITH_API_HTML_FALSE= fi ac_config_files="$ac_config_files Makefile lib/Makefile sanei/Makefile frontend/Makefile japi/Makefile backend/Makefile include/Makefile doc/Makefile po/Makefile.in testsuite/Makefile testsuite/sanei/Makefile testsuite/tools/Makefile tools/Makefile doc/doxygen-sanei.conf doc/doxygen-genesys.conf" ac_config_files="$ac_config_files tools/sane-config" ac_config_files="$ac_config_files tools/sane-backends.pc" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${CROSS_COMPILING_TRUE}" && test -z "${CROSS_COMPILING_FALSE}"; then as_fn_error $? "conditional \"CROSS_COMPILING\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${have_usblib_TRUE}" && test -z "${have_usblib_FALSE}"; then as_fn_error $? "conditional \"have_usblib\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${COMPILE_SANED_TRUE}" && test -z "${COMPILE_SANED_FALSE}"; then as_fn_error $? "conditional \"COMPILE_SANED\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_JPEG_TRUE}" && test -z "${HAVE_JPEG_FALSE}"; then as_fn_error $? "conditional \"HAVE_JPEG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${INSTALL_UMAX_PP_TOOLS_TRUE}" && test -z "${INSTALL_UMAX_PP_TOOLS_FALSE}"; then as_fn_error $? "conditional \"INSTALL_UMAX_PP_TOOLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_API_PS_TRUE}" && test -z "${WITH_API_PS_FALSE}"; then as_fn_error $? "conditional \"WITH_API_PS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_API_PDF_TRUE}" && test -z "${WITH_API_PDF_FALSE}"; then as_fn_error $? "conditional \"WITH_API_PDF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_API_HTML_TRUE}" && test -z "${WITH_API_HTML_FALSE}"; then as_fn_error $? "conditional \"WITH_API_HTML\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by sane-backends $as_me 1.0.27, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ sane-backends config.status 1.0.27 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in AS \ DLLTOOL \ OBJDUMP \ SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' # Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake < 1.5. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" # variables for create stdint.h replacement PACKAGE="$PACKAGE" VERSION="$VERSION" ac_stdint_h="$ac_stdint_h" _ac_stdint_h=`$as_echo "_$PACKAGE-$ac_stdint_h" | $as_tr_cpp` ac_cv_stdint_message="$ac_cv_stdint_message" ac_cv_header_stdint_t="$ac_cv_header_stdint_t" ac_cv_header_stdint_x="$ac_cv_header_stdint_x" ac_cv_header_stdint_o="$ac_cv_header_stdint_o" ac_cv_header_stdint_u="$ac_cv_header_stdint_u" ac_cv_type_uint64_t="$ac_cv_type_uint64_t" ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" ac_cv_char_data_model="$ac_cv_char_data_model" ac_cv_long_data_model="$ac_cv_long_data_model" ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" ac_cv_type_intmax_t="$ac_cv_type_intmax_t" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "include/sane/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/sane/config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; "$ac_stdint_h") CONFIG_COMMANDS="$CONFIG_COMMANDS $ac_stdint_h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; "sanei/Makefile") CONFIG_FILES="$CONFIG_FILES sanei/Makefile" ;; "frontend/Makefile") CONFIG_FILES="$CONFIG_FILES frontend/Makefile" ;; "japi/Makefile") CONFIG_FILES="$CONFIG_FILES japi/Makefile" ;; "backend/Makefile") CONFIG_FILES="$CONFIG_FILES backend/Makefile" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; "testsuite/sanei/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/sanei/Makefile" ;; "testsuite/tools/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/tools/Makefile" ;; "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; "doc/doxygen-sanei.conf") CONFIG_FILES="$CONFIG_FILES doc/doxygen-sanei.conf" ;; "doc/doxygen-genesys.conf") CONFIG_FILES="$CONFIG_FILES doc/doxygen-genesys.conf" ;; "tools/sane-config") CONFIG_FILES="$CONFIG_FILES tools/sane-config" ;; "tools/sane-backends.pc") CONFIG_FILES="$CONFIG_FILES tools/sane-backends.pc" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static # Assembler program. AS=$lt_AS # DLL creation program. DLLTOOL=$lt_DLLTOOL # Object dumper program. OBJDUMP=$lt_OBJDUMP # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; "po-directories":C) for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) # Compute UPDATEPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) # Compute DUMMYPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) # Compute GMOFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= UPDATEPOFILES= DUMMYPOFILES= GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done ;; "$ac_stdint_h":C) { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_stdint_h : $_ac_stdint_h" >&5 $as_echo "$as_me: creating $ac_stdint_h : $_ac_stdint_h" >&6;} ac_stdint=$tmp/_stdint.h echo "#ifndef" $_ac_stdint_h >$ac_stdint echo "#define" $_ac_stdint_h "1" >>$ac_stdint echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint if test "_$ac_cv_header_stdint_t" != "_" ; then echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint echo "#include " >>$ac_stdint echo "#endif" >>$ac_stdint echo "#endif" >>$ac_stdint else cat >>$ac_stdint < #else #include /* .................... configured part ............................ */ STDINT_EOF echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint if test "_$ac_cv_header_stdint_x" != "_" ; then ac_header="$ac_cv_header_stdint_x" echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint else echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint fi echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint if test "_$ac_cv_header_stdint_o" != "_" ; then ac_header="$ac_cv_header_stdint_o" echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint else echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint fi echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint if test "_$ac_cv_header_stdint_u" != "_" ; then ac_header="$ac_cv_header_stdint_u" echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint else echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint fi echo "" >>$ac_stdint if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then echo "#include <$ac_header>" >>$ac_stdint echo "" >>$ac_stdint fi fi echo "/* which 64bit typedef has been found */" >>$ac_stdint if test "$ac_cv_type_uint64_t" = "yes" ; then echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint fi if test "$ac_cv_type_u_int64_t" = "yes" ; then echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint fi echo "" >>$ac_stdint echo "/* which type model has been detected */" >>$ac_stdint if test "_$ac_cv_char_data_model" != "_" ; then echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint else echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint fi echo "" >>$ac_stdint echo "/* whether int_least types were detected */" >>$ac_stdint if test "$ac_cv_type_int_least32_t" = "yes"; then echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint fi echo "/* whether int_fast types were detected */" >>$ac_stdint if test "$ac_cv_type_int_fast32_t" = "yes"; then echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint fi echo "/* whether intmax_t type was detected */" >>$ac_stdint if test "$ac_cv_type_intmax_t" = "yes"; then echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint else echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint fi echo "" >>$ac_stdint cat >>$ac_stdint <= 199901L #define _HAVE_UINT64_T #define _HAVE_LONGLONG_UINT64_T typedef long long int64_t; typedef unsigned long long uint64_t; #elif !defined __STRICT_ANSI__ #if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ #define _HAVE_UINT64_T typedef __int64 int64_t; typedef unsigned __int64 uint64_t; #elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ /* note: all ELF-systems seem to have loff-support which needs 64-bit */ #if !defined _NO_LONGLONG #define _HAVE_UINT64_T #define _HAVE_LONGLONG_UINT64_T typedef long long int64_t; typedef unsigned long long uint64_t; #endif #elif defined __alpha || (defined __mips && defined _ABIN32) #if !defined _NO_LONGLONG typedef long int64_t; typedef unsigned long uint64_t; #endif /* compiler/cpu type to define int64_t */ #endif #endif #endif #if defined _STDINT_HAVE_U_INT_TYPES /* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */ typedef u_int8_t uint8_t; typedef u_int16_t uint16_t; typedef u_int32_t uint32_t; /* glibc compatibility */ #ifndef __int8_t_defined #define __int8_t_defined #endif #endif #ifdef _STDINT_NEED_INT_MODEL_T /* we must guess all the basic types. Apart from byte-adressable system, */ /* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */ /* (btw, those nibble-addressable systems are way off, or so we assume) */ #if defined _STDINT_BYTE_MODEL #if _STDINT_LONG_MODEL+0 == 242 /* 2:4:2 = IP16 = a normal 16-bit system */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; #ifndef __int8_t_defined #define __int8_t_defined typedef char int8_t; typedef short int16_t; typedef long int32_t; #endif #elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444 /* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */ /* 4:4:4 = ILP32 = a normal 32-bit system */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #ifndef __int8_t_defined #define __int8_t_defined typedef char int8_t; typedef short int16_t; typedef int int32_t; #endif #elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488 /* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */ /* 4:8:8 = LP64 = a normal 64-bit system */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #ifndef __int8_t_defined #define __int8_t_defined typedef char int8_t; typedef short int16_t; typedef int int32_t; #endif /* this system has a "long" of 64bit */ #ifndef _HAVE_UINT64_T #define _HAVE_UINT64_T typedef unsigned long uint64_t; typedef long int64_t; #endif #elif _STDINT_LONG_MODEL+0 == 448 /* LLP64 a 64-bit system derived from a 32-bit system */ typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #ifndef __int8_t_defined #define __int8_t_defined typedef char int8_t; typedef short int16_t; typedef int int32_t; #endif /* assuming the system has a "long long" */ #ifndef _HAVE_UINT64_T #define _HAVE_UINT64_T #define _HAVE_LONGLONG_UINT64_T typedef unsigned long long uint64_t; typedef long long int64_t; #endif #else #define _STDINT_NO_INT32_T #endif #else #define _STDINT_NO_INT8_T #define _STDINT_NO_INT32_T #endif #endif /* * quote from SunOS-5.8 sys/inttypes.h: * Use at your own risk. As of February 1996, the committee is squarely * behind the fixed sized types; the "least" and "fast" types are still being * discussed. The probability that the "fast" types may be removed before * the standard is finalized is high enough that they are not currently * implemented. */ #if defined _STDINT_NEED_INT_LEAST_T typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; #ifdef _HAVE_UINT64_T typedef int64_t int_least64_t; #endif typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; #ifdef _HAVE_UINT64_T typedef uint64_t uint_least64_t; #endif /* least types */ #endif #if defined _STDINT_NEED_INT_FAST_T typedef int8_t int_fast8_t; typedef int int_fast16_t; typedef int32_t int_fast32_t; #ifdef _HAVE_UINT64_T typedef int64_t int_fast64_t; #endif typedef uint8_t uint_fast8_t; typedef unsigned uint_fast16_t; typedef uint32_t uint_fast32_t; #ifdef _HAVE_UINT64_T typedef uint64_t uint_fast64_t; #endif /* fast types */ #endif #ifdef _STDINT_NEED_INTMAX_T #ifdef _HAVE_UINT64_T typedef int64_t intmax_t; typedef uint64_t uintmax_t; #else typedef long intmax_t; typedef unsigned long uintmax_t; #endif #endif #ifdef _STDINT_NEED_INTPTR_T #ifndef __intptr_t_defined #define __intptr_t_defined /* we encourage using "long" to store pointer values, never use "int" ! */ #if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484 typedef unsigned int uintptr_t; typedef int intptr_t; #elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444 typedef unsigned long uintptr_t; typedef long intptr_t; #elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T typedef uint64_t uintptr_t; typedef int64_t intptr_t; #else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */ typedef unsigned long uintptr_t; typedef long intptr_t; #endif #endif #endif /* The ISO C99 standard specifies that in C++ implementations these should only be defined if explicitly requested. */ #if !defined __cplusplus || defined __STDC_CONSTANT_MACROS #ifndef UINT32_C /* Signed. */ # define INT8_C(c) c # define INT16_C(c) c # define INT32_C(c) c # ifdef _HAVE_LONGLONG_UINT64_T # define INT64_C(c) c ## L # else # define INT64_C(c) c ## LL # endif /* Unsigned. */ # define UINT8_C(c) c ## U # define UINT16_C(c) c ## U # define UINT32_C(c) c ## U # ifdef _HAVE_LONGLONG_UINT64_T # define UINT64_C(c) c ## UL # else # define UINT64_C(c) c ## ULL # endif /* Maximal type. */ # ifdef _HAVE_LONGLONG_UINT64_T # define INTMAX_C(c) c ## L # define UINTMAX_C(c) c ## UL # else # define INTMAX_C(c) c ## LL # define UINTMAX_C(c) c ## ULL # endif /* literalnumbers */ #endif #endif /* These limits are merily those of a two complement byte-oriented system */ /* Minimum of signed integral types. */ # define INT8_MIN (-128) # define INT16_MIN (-32767-1) # define INT32_MIN (-2147483647-1) # define INT64_MIN (-__INT64_C(9223372036854775807)-1) /* Maximum of signed integral types. */ # define INT8_MAX (127) # define INT16_MAX (32767) # define INT32_MAX (2147483647) # define INT64_MAX (__INT64_C(9223372036854775807)) /* Maximum of unsigned integral types. */ # define UINT8_MAX (255) # define UINT16_MAX (65535) # define UINT32_MAX (4294967295U) # define UINT64_MAX (__UINT64_C(18446744073709551615)) /* Minimum of signed integral types having a minimum size. */ # define INT_LEAST8_MIN INT8_MIN # define INT_LEAST16_MIN INT16_MIN # define INT_LEAST32_MIN INT32_MIN # define INT_LEAST64_MIN INT64_MIN /* Maximum of signed integral types having a minimum size. */ # define INT_LEAST8_MAX INT8_MAX # define INT_LEAST16_MAX INT16_MAX # define INT_LEAST32_MAX INT32_MAX # define INT_LEAST64_MAX INT64_MAX /* Maximum of unsigned integral types having a minimum size. */ # define UINT_LEAST8_MAX UINT8_MAX # define UINT_LEAST16_MAX UINT16_MAX # define UINT_LEAST32_MAX UINT32_MAX # define UINT_LEAST64_MAX UINT64_MAX /* shortcircuit*/ #endif /* once */ #endif #endif STDINT_EOF fi if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_stdint_h is unchanged" >&5 $as_echo "$as_me: $ac_stdint_h is unchanged" >&6;} else ac_dir=`$as_dirname -- "$ac_stdint_h" || $as_expr X"$ac_stdint_h" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_stdint_h" : 'X\(//\)[^/]' \| \ X"$ac_stdint_h" : 'X\(//\)$' \| \ X"$ac_stdint_h" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_stdint_h" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p rm -f $ac_stdint_h mv $ac_stdint $ac_stdint_h fi ;; "tools/sane-config":F) chmod a+x tools/sane-config ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi echo "-> Variables used for compilation/linking:" echo AM_CPPFLAGS=\"${AM_CPPFLAGS}\" echo AM_CFLAGS=\"${AM_CFLAGS}\" echo AM_LDFLAGS=\"${AM_LDFLAGS}\" echo LIBS=\"${LIBS}\" echo "-> Installation directories:" echo "Configuration: `eval eval echo ${sysconfdir}`" echo "Libraries: `eval eval echo ${libdir}`" echo "Binaries: `eval eval echo ${bindir}` and `eval eval echo ${sbindir}`" echo "Manpages: `eval eval echo ${mandir}`" echo "Documentation: `eval eval echo ${docdir}`" if eval "test x$INSTALL_LOCKPATH = xinstall-lockpath" ; then echo "Lockfiles: `eval eval echo ${locksanedir}`" else echo "Lockfiles: Feature is disabled!" fi echo "-> Network parameters:" if test "${SANED}" = "saned" ; then echo "Build saned: yes" else echo "Build saned: no" fi echo "IPv6 support: `eval eval echo ${ipv6}`" echo "Avahi support: `eval eval echo ${enable_avahi}`" echo "SNMP support: `eval eval echo ${with_snmp}`" echo "-> The following backends will be built:" for backend in ${BACKENDS} ; do echo $ECHO_N "${backend} " done echo echo echo "-> The following preload backends will be built:" for backend in ${PRELOADABLE_BACKENDS} ; do echo $ECHO_N "${backend} " done echo if test "$SANE_CONFIG_PATH" != "no" ; then SANE_INSTALLED_VERSION=`$SANE_CONFIG_PATH --version` SANE_INSTALLED_PREFIX=`$SANE_CONFIG_PATH --prefix` if test "$SANE_INSTALLED_PREFIX" != "$prefix" ; then echo "*** WARNING: SANE is already installed (version $SANE_INSTALLED_VERSION). The old" echo "*** installation is at $SANE_INSTALLED_PREFIX while SANE will now be installed" echo "*** at $prefix. It is recommended to uninstall the old SANE version" echo "*** before installing the new one to avoid problems." fi else if test "$LIBSANE_EXISTS" = "yes" ; then echo "*** Warning: An old version of SANE was detected but the sane-config program" echo "*** couldn't be found. If you encounter any problems with SANE remove the old" echo "*** SANE files and reinstall this version." fi fi if eval "test x${sysconfdir} = x/usr/etc" ; then echo "*** WARNING: Configuration files are stored in /usr/etc. If this is not" echo "*** intended, use --sysconfdir to set another path (e.g. "/etc")." fi if test "$SELECTED_BACKENDS" != "" ; then echo "*** Warning: Local backends have been disabled. This means that scanners" echo "*** connected to your local computer won't be supported. Only a network" echo "*** connection to a remote host is possible." fi if test "$with_usb" != "no" && test "$have_usb" != "yes" ; then echo "*** Warning: sane-backends will be built without USB support. There may" echo "*** be valid reasons to do so, e.g. if you don't use USB scanners or on" echo "*** platforms without USB support but generally this means that you" echo "*** can't use USB devices with SANE. The most probable cause is that" if test "${ac_cv_header_usb_h}" != "yes"; then echo "*** the libusb header file usb.h is not installed. If you use Linux" echo "*** you may need a package called 'libusb-dev', 'libusb-devel' or similar." else echo "*** libusb is not installed at all or is too old. See README." fi fi echo "****************************************************************" echo "* Please be sure to read file PROBLEMS in this directory *" echo "* BEFORE running any of the SANE applications. Some devices *" echo "* may be damaged by improper operation, so please do heed this *" echo "* advice. *" echo "****************************************************************" sane-backends-1.0.27/config.rpath0000775000175000017500000004401212775312261013541 00000000000000#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2010 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's _LT_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; darwin*) case $cc_basename in xlc*) wl='-Wl,' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux* | k*bsd*-gnu) case $cc_basename in ecc*) wl='-Wl,' ;; icc* | ifort*) wl='-Wl,' ;; lf95*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; rdos*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3*) wl='-Wl,' ;; sysv4*MP*) ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) wl='-Wl,' ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's _LT_LINKER_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we cannot use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; gnu* | linux* | k*bsd*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if test "$GCC" = yes ; then : else case $cc_basename in xlc*) ;; *) ld_shlibs=no ;; esac fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. # Unlike libtool.m4, here we don't care about _all_ names of the library, but # only about the one the linker finds when passed -lNAME. This is the last # element of library_names_spec in libtool.m4, or possibly two of them if the # linker has special search rules. library_names_spec= # the last element of library_names_spec in libtool.m4 libname_spec='lib$name' case "$host_os" in aix3*) library_names_spec='$libname.a' ;; aix[4-9]*) library_names_spec='$libname$shrext' ;; amigaos*) library_names_spec='$libname.a' ;; beos*) library_names_spec='$libname$shrext' ;; bsdi[45]*) library_names_spec='$libname$shrext' ;; cygwin* | mingw* | pw32* | cegcc*) shrext=.dll library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib library_names_spec='$libname$shrext' ;; dgux*) library_names_spec='$libname$shrext' ;; freebsd1*) ;; freebsd* | dragonfly*) case "$host_os" in freebsd[123]*) library_names_spec='$libname$shrext$versuffix' ;; *) library_names_spec='$libname$shrext' ;; esac ;; gnu*) library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac library_names_spec='$libname$shrext' ;; interix[3-9]*) library_names_spec='$libname$shrext' ;; irix5* | irix6* | nonstopux*) library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux* | k*bsd*-gnu) library_names_spec='$libname$shrext' ;; knetbsd*-gnu) library_names_spec='$libname$shrext' ;; netbsd*) library_names_spec='$libname$shrext' ;; newsos6) library_names_spec='$libname$shrext' ;; nto-qnx*) library_names_spec='$libname$shrext' ;; openbsd*) library_names_spec='$libname$shrext$versuffix' ;; os2*) libname_spec='$name' shrext=.dll library_names_spec='$libname.a' ;; osf3* | osf4* | osf5*) library_names_spec='$libname$shrext' ;; rdos*) ;; solaris*) library_names_spec='$libname$shrext' ;; sunos4*) library_names_spec='$libname$shrext$versuffix' ;; sysv4 | sysv4.3*) library_names_spec='$libname$shrext' ;; sysv4*MP*) library_names_spec='$libname$shrext' ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) library_names_spec='$libname$shrext' ;; uts4*) library_names_spec='$libname$shrext' ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <, 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.2 Debian-2.4.2-1.11" TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi # Local change for sane-backends: internal name for every lib # is "libsane" not "libsane-backendname". So linking to each # backend is possible. Also the following test was moved to this # location. # If -module or -export-dynamic was specified, set the dlname if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi case $host in *mingw*) ;; *aix*) ;; *) soname=`echo $soname | sed -e "s/libsane-[A-Za-z_0-9]*/libsane/g"` esac # End of local change lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # Local change from sane-backends; moved up # If -module or -export-dynamic was specified, set the dlname. #if test "$module" = yes || test "$export_dynamic" = yes; then # # On all known operating systems, these are identical. # dlname="$soname" #fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 sane-backends-1.0.27/README.beos0000664000175000017500000000157312112021330013020 00000000000000SANE and BeOS ------------- The information in this text is from an article of Philippe Houdoin on sane-devel (29 Aug 2002). SANE 1.0.3 was first ported to BeOS, under the name BeSANE, by Massimiliano Origgi: http://www.intuiware.com/Products/BeSANE/index.html SANE 1.0.5 BeOS port and fixes to some issues with original BeSANE port were made by Philippe Houdoin but aren't released until now. BeOS GUI SANE frontend project (by Philippe Houdoin): http://philippe.houdoin.free.fr/phil/beos/sanity/index-en.html Updates of Sanity from Kaya Memisoglu: http://www.bebits.com/app/2847 SANE was reported to work with the following configuration and features: Platform: BeOS R5.0.x ix86 Latest SANE version tested: 1.0.5 Compiler: gcc 2.95.3 User-level SCSI support: yes USB support: yes Shared library support: yes Dynamic loading support: yes X11 clients: no